summaryrefslogtreecommitdiff
path: root/chromium/components
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-09-03 13:32:17 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-01 14:31:55 +0200
commit21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (patch)
tree91be119f694044dfc1ff9fdc054459e925de9df0 /chromium/components
parent03c549e0392f92c02536d3f86d5e1d8dfa3435ac (diff)
downloadqtwebengine-chromium-21ba0c5d4bf8fba15dddd97cd693bad2358b77fd.tar.gz
BASELINE: Update Chromium to 92.0.4515.166
Change-Id: I42a050486714e9e54fc271f2a8939223a02ae364
Diffstat (limited to 'chromium/components')
-rw-r--r--chromium/components/BUILD.gn25
-rw-r--r--chromium/components/OWNERS5
-rw-r--r--chromium/components/about_ui/android/OWNERS0
-rw-r--r--chromium/components/account_id/account_id.cc2
-rw-r--r--chromium/components/account_manager_core/account_addition_result.h6
-rw-r--r--chromium/components/account_manager_core/account_manager_facade.h2
-rw-r--r--chromium/components/account_manager_core/account_manager_facade_impl.cc15
-rw-r--r--chromium/components/account_manager_core/account_manager_facade_impl_unittest.cc2
-rw-r--r--chromium/components/account_manager_core/account_manager_util.cc30
-rw-r--r--chromium/components/account_manager_core/account_manager_util.h20
-rw-r--r--chromium/components/android_autofill/DEPS5
-rw-r--r--chromium/components/android_autofill/OWNERS (renamed from chromium/components/autofill/android/provider/OWNERS)2
-rw-r--r--chromium/components/android_autofill/android/BUILD.gn (renamed from chromium/components/autofill/android/provider/BUILD.gn)4
-rw-r--r--chromium/components/android_autofill/android/DEPS (renamed from chromium/components/autofill/android/provider/DEPS)2
-rw-r--r--chromium/components/android_autofill/android/autofill_provider_android.cc (renamed from chromium/components/autofill/android/provider/autofill_provider_android.cc)173
-rw-r--r--chromium/components/android_autofill/android/autofill_provider_android.h (renamed from chromium/components/autofill/android/provider/autofill_provider_android.h)72
-rw-r--r--chromium/components/android_autofill/android/form_data_android.cc (renamed from chromium/components/autofill/android/provider/form_data_android.cc)17
-rw-r--r--chromium/components/android_autofill/android/form_data_android.h (renamed from chromium/components/autofill/android/provider/form_data_android.h)6
-rw-r--r--chromium/components/android_autofill/android/form_field_data_android.cc (renamed from chromium/components/autofill/android/provider/form_field_data_android.cc)4
-rw-r--r--chromium/components/android_autofill/android/form_field_data_android.h (renamed from chromium/components/autofill/android/provider/form_field_data_android.h)6
-rw-r--r--chromium/components/android_autofill/android/junit/BUILD.gn (renamed from chromium/components/autofill/android/provider/junit/BUILD.gn)2
-rw-r--r--chromium/components/android_autofill/android/junit/src/org/chromium/components/autofill/AutofillProviderTest.java (renamed from chromium/components/autofill/android/provider/junit/src/org/chromium/components/autofill/AutofillProviderTest.java)11
-rw-r--r--chromium/components/android_autofill/android/test_support/BUILD.gn (renamed from chromium/components/autofill/android/provider/test_support/BUILD.gn)6
-rw-r--r--chromium/components/android_autofill/android/test_support/autofill_provider_test_helper.cc (renamed from chromium/components/autofill/android/provider/test_support/autofill_provider_test_helper.cc)36
-rw-r--r--chromium/components/android_autofill/android/test_support/java/src/org/chromium/components/autofill/AutofillHintsServiceTestHelper.java (renamed from chromium/components/autofill/android/provider/test_support/java/src/org/chromium/components/autofill/AutofillHintsServiceTestHelper.java)0
-rw-r--r--chromium/components/android_autofill/android/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java (renamed from chromium/components/autofill/android/provider/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java)0
-rw-r--r--chromium/components/android_autofill/browser/BUILD.gn34
-rw-r--r--chromium/components/android_autofill/browser/android_autofill_manager.cc156
-rw-r--r--chromium/components/android_autofill/browser/android_autofill_manager.h (renamed from chromium/components/autofill/core/browser/autofill_handler_proxy.h)44
-rw-r--r--chromium/components/android_autofill/browser/autofill_provider.cc (renamed from chromium/components/autofill/core/browser/autofill_provider.cc)27
-rw-r--r--chromium/components/android_autofill/browser/autofill_provider.h (renamed from chromium/components/autofill/core/browser/autofill_provider.h)71
-rw-r--r--chromium/components/android_autofill/browser/autofill_provider_unittest.cc (renamed from chromium/components/autofill/core/browser/autofill_provider_unittest.cc)55
-rw-r--r--chromium/components/android_autofill/browser/test_autofill_provider.h (renamed from chromium/components/autofill/core/browser/test_autofill_provider.h)47
-rw-r--r--chromium/components/apdu/apdu_command.cc12
-rw-r--r--chromium/components/apdu/apdu_command.h4
-rw-r--r--chromium/components/apdu/apdu_response.cc4
-rw-r--r--chromium/components/apdu/apdu_response.h4
-rw-r--r--chromium/components/arc/BUILD.gn41
-rw-r--r--chromium/components/arc/DEPS2
-rw-r--r--chromium/components/arc/app_permissions/arc_app_permissions_bridge.cc47
-rw-r--r--chromium/components/arc/app_permissions/arc_app_permissions_bridge.h37
-rw-r--r--chromium/components/arc/appfuse/arc_appfuse_bridge.cc2
-rw-r--r--chromium/components/arc/arc_features.cc14
-rw-r--r--chromium/components/arc/arc_features.h3
-rw-r--r--chromium/components/arc/arc_features_parser.cc46
-rw-r--r--chromium/components/arc/arc_features_parser.h12
-rw-r--r--chromium/components/arc/arc_features_parser_unittest.cc16
-rw-r--r--chromium/components/arc/arc_prefs.cc5
-rw-r--r--chromium/components/arc/arc_prefs.h1
-rw-r--r--chromium/components/arc/arc_util.cc36
-rw-r--r--chromium/components/arc/arc_util.h11
-rw-r--r--chromium/components/arc/arc_util_unittest.cc30
-rw-r--r--chromium/components/arc/audio/arc_audio_bridge.cc10
-rw-r--r--chromium/components/arc/audio/arc_audio_bridge.h4
-rw-r--r--chromium/components/arc/audio/arc_audio_bridge_unittest.cc42
-rw-r--r--chromium/components/arc/bluetooth/bluetooth_type_converters_unittest.cc6
-rw-r--r--chromium/components/arc/camera/arc_camera_bridge.cc6
-rw-r--r--chromium/components/arc/camera/arc_camera_bridge.h2
-rw-r--r--chromium/components/arc/camera/arc_camera_bridge_unittest.cc37
-rw-r--r--chromium/components/arc/clipboard/arc_clipboard_bridge.h2
-rw-r--r--chromium/components/arc/clipboard/arc_clipboard_bridge_unittest.cc7
-rw-r--r--chromium/components/arc/compat_mode/DEPS2
-rw-r--r--chromium/components/arc/compat_mode/arc_resize_lock_manager.cc40
-rw-r--r--chromium/components/arc/compat_mode/arc_resize_lock_manager.h1
-rw-r--r--chromium/components/arc/compat_mode/arc_resize_lock_pref_delegate.h6
-rw-r--r--chromium/components/arc/compat_mode/arc_splash_screen_dialog_view.cc176
-rw-r--r--chromium/components/arc/compat_mode/arc_splash_screen_dialog_view.h50
-rw-r--r--chromium/components/arc/compat_mode/arc_splash_screen_dialog_view_unittest.cc71
-rw-r--r--chromium/components/arc/compat_mode/resize_confirmation_dialog.cc106
-rw-r--r--chromium/components/arc/compat_mode/resize_confirmation_dialog.h34
-rw-r--r--chromium/components/arc/compat_mode/resize_confirmation_dialog_unittest.cc29
-rw-r--r--chromium/components/arc/compat_mode/resize_confirmation_dialog_view.cc166
-rw-r--r--chromium/components/arc/compat_mode/resize_confirmation_dialog_view.h73
-rw-r--r--chromium/components/arc/compat_mode/resize_confirmation_dialog_view_unittest.cc109
-rw-r--r--chromium/components/arc/compat_mode/resize_toggle_menu.cc12
-rw-r--r--chromium/components/arc/compat_mode/resize_toggle_menu_unittest.cc6
-rw-r--r--chromium/components/arc/compat_mode/resize_util.cc2
-rw-r--r--chromium/components/arc/compat_mode/resize_util_unittest.cc85
-rw-r--r--chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc29
-rw-r--r--chromium/components/arc/crash_collector/arc_crash_collector_bridge.h11
-rw-r--r--chromium/components/arc/crash_collector/arc_crash_collector_bridge_unittest.cc78
-rw-r--r--chromium/components/arc/disk_quota/arc_disk_quota_bridge.cc12
-rw-r--r--chromium/components/arc/enterprise/arc_data_snapshotd_manager.cc149
-rw-r--r--chromium/components/arc/enterprise/arc_data_snapshotd_manager.h27
-rw-r--r--chromium/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc42
-rw-r--r--chromium/components/arc/enterprise/snapshot_hours_policy_service.cc30
-rw-r--r--chromium/components/arc/enterprise/snapshot_hours_policy_service.h4
-rw-r--r--chromium/components/arc/enterprise/snapshot_hours_policy_service_unittest.cc12
-rw-r--r--chromium/components/arc/ime/DIR_METADATA3
-rw-r--r--chromium/components/arc/ime/arc_ime_service.cc46
-rw-r--r--chromium/components/arc/ime/arc_ime_service.h10
-rw-r--r--chromium/components/arc/ime/arc_ime_service_unittest.cc23
-rw-r--r--chromium/components/arc/ime/key_event_result_receiver.cc19
-rw-r--r--chromium/components/arc/ime/key_event_result_receiver.h4
-rw-r--r--chromium/components/arc/ime/key_event_result_receiver_unittest.cc40
-rw-r--r--chromium/components/arc/intent_helper/activity_icon_loader_unittest.cc3
-rw-r--r--chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc30
-rw-r--r--chromium/components/arc/intent_helper/arc_intent_helper_bridge.h8
-rw-r--r--chromium/components/arc/intent_helper/arc_intent_helper_bridge_unittest.cc79
-rw-r--r--chromium/components/arc/intent_helper/arc_intent_helper_observer.h18
-rw-r--r--chromium/components/arc/intent_helper/custom_tab_unittest.cc2
-rw-r--r--chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc8
-rw-r--r--chromium/components/arc/intent_helper/link_handler_model.cc6
-rw-r--r--chromium/components/arc/lock_screen/arc_lock_screen_bridge.cc6
-rw-r--r--chromium/components/arc/lock_screen/arc_lock_screen_bridge.h2
-rw-r--r--chromium/components/arc/lock_screen/arc_lock_screen_bridge_unittest.cc80
-rw-r--r--chromium/components/arc/media_session/arc_media_session_bridge.cc6
-rw-r--r--chromium/components/arc/media_session/arc_media_session_bridge.h4
-rw-r--r--chromium/components/arc/media_session/arc_media_session_bridge_unittest.cc39
-rw-r--r--chromium/components/arc/metrics/arc_metrics_service.cc116
-rw-r--r--chromium/components/arc/metrics/arc_metrics_service.h44
-rw-r--r--chromium/components/arc/metrics/arc_metrics_service_unittest.cc126
-rw-r--r--chromium/components/arc/metrics/stability_metrics_manager.cc14
-rw-r--r--chromium/components/arc/metrics/stability_metrics_manager.h6
-rw-r--r--chromium/components/arc/midis/arc_midis_bridge.cc6
-rw-r--r--chromium/components/arc/midis/arc_midis_bridge.h4
-rw-r--r--chromium/components/arc/midis/arc_midis_bridge_unittest.cc37
-rw-r--r--chromium/components/arc/mojom/BUILD.gn3
-rw-r--r--chromium/components/arc/mojom/app.mojom8
-rw-r--r--chromium/components/arc/mojom/arc_bridge.mojom9
-rw-r--r--chromium/components/arc/mojom/auth.mojom22
-rw-r--r--chromium/components/arc/mojom/camera.mojom2
-rw-r--r--chromium/components/arc/mojom/crash_collector.mojom12
-rw-r--r--chromium/components/arc/mojom/intent_helper.mojom23
-rw-r--r--chromium/components/arc/mojom/metrics.mojom51
-rw-r--r--chromium/components/arc/mojom/payment_app.mojom17
-rw-r--r--chromium/components/arc/mojom/video_accelerator_mojom_traits.cc2
-rw-r--r--chromium/components/arc/mojom/video_accelerator_mojom_traits_unittest.cc2
-rw-r--r--chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.cc8
-rw-r--r--chromium/components/arc/mojom/webapk.mojom36
-rw-r--r--chromium/components/arc/net/DIR_METADATA3
-rw-r--r--chromium/components/arc/net/always_on_vpn_manager.h2
-rw-r--r--chromium/components/arc/net/always_on_vpn_manager_unittest.cc17
-rw-r--r--chromium/components/arc/net/arc_net_host_impl.cc94
-rw-r--r--chromium/components/arc/net/arc_net_host_impl.h2
-rw-r--r--chromium/components/arc/pay/arc_payment_app_bridge.cc12
-rw-r--r--chromium/components/arc/pay/arc_payment_app_bridge.h5
-rw-r--r--chromium/components/arc/pay/arc_payment_app_bridge_unittest.cc40
-rw-r--r--chromium/components/arc/power/arc_power_bridge.cc11
-rw-r--r--chromium/components/arc/power/arc_power_bridge.h10
-rw-r--r--chromium/components/arc/power/arc_power_bridge_unittest.cc2
-rw-r--r--chromium/components/arc/property/arc_property_bridge_unittest.cc6
-rw-r--r--chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.cc6
-rw-r--r--chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h2
-rw-r--r--chromium/components/arc/rotation_lock/arc_rotation_lock_bridge_unittest.cc39
-rw-r--r--chromium/components/arc/sensor/arc_iio_sensor_bridge.cc2
-rw-r--r--chromium/components/arc/sensor/arc_iio_sensor_bridge.h6
-rw-r--r--chromium/components/arc/session/OWNERS1
-rw-r--r--chromium/components/arc/session/arc_bridge_host_impl.cc7
-rw-r--r--chromium/components/arc/session/arc_bridge_host_impl.h3
-rw-r--r--chromium/components/arc/session/arc_bridge_service.h3
-rw-r--r--chromium/components/arc/session/arc_bridge_service_unittest.cc45
-rw-r--r--chromium/components/arc/session/arc_client_adapter.h12
-rw-r--r--chromium/components/arc/session/arc_client_adapter_unittest.cc64
-rw-r--r--chromium/components/arc/session/arc_container_client_adapter.cc36
-rw-r--r--chromium/components/arc/session/arc_container_client_adapter_unittest.cc33
-rw-r--r--chromium/components/arc/session/arc_data_remover.cc4
-rw-r--r--chromium/components/arc/session/arc_data_remover.h4
-rw-r--r--chromium/components/arc/session/arc_data_remover_unittest.cc12
-rw-r--r--chromium/components/arc/session/arc_instance_mode.cc2
-rw-r--r--chromium/components/arc/session/arc_instance_mode.h4
-rw-r--r--chromium/components/arc/session/arc_instance_mode_unittest.cc8
-rw-r--r--chromium/components/arc/session/arc_session.h7
-rw-r--r--chromium/components/arc/session/arc_session_impl.cc13
-rw-r--r--chromium/components/arc/session/arc_session_impl.h5
-rw-r--r--chromium/components/arc/session/arc_session_impl_unittest.cc67
-rw-r--r--chromium/components/arc/session/arc_session_runner.cc32
-rw-r--r--chromium/components/arc/session/arc_session_runner.h11
-rw-r--r--chromium/components/arc/session/arc_supervision_transition.cc2
-rw-r--r--chromium/components/arc/session/arc_supervision_transition.h3
-rw-r--r--chromium/components/arc/session/arc_vm_client_adapter.cc92
-rw-r--r--chromium/components/arc/session/arc_vm_client_adapter.h2
-rw-r--r--chromium/components/arc/session/arc_vm_client_adapter_unittest.cc382
-rw-r--r--chromium/components/arc/session/connection_holder.h1
-rw-r--r--chromium/components/arc/storage_manager/arc_storage_manager.cc6
-rw-r--r--chromium/components/arc/storage_manager/arc_storage_manager.h4
-rw-r--r--chromium/components/arc/storage_manager/arc_storage_manager_unittest.cc83
-rw-r--r--chromium/components/arc/timer/arc_timer_bridge.cc8
-rw-r--r--chromium/components/arc/timer/arc_timer_bridge.h8
-rw-r--r--chromium/components/arc/timer/arc_timer_bridge_unittest.cc10
-rw-r--r--chromium/components/arc/usb/usb_host_bridge.cc23
-rw-r--r--chromium/components/arc/usb/usb_host_bridge.h6
-rw-r--r--chromium/components/arc/usb/usb_host_bridge_unittest.cc37
-rw-r--r--chromium/components/arc/vector_icons/BUILD.gn22
-rw-r--r--chromium/components/arc/vector_icons/OWNERS1
-rw-r--r--chromium/components/arc/vector_icons/compat_mode_splashscreen.icon95
-rw-r--r--chromium/components/arc/vector_icons/vector_icons.cc.template20
-rw-r--r--chromium/components/arc/vector_icons/vector_icons.h.template26
-rw-r--r--chromium/components/arc/video_accelerator/arc_video_accelerator_util.cc16
-rw-r--r--chromium/components/arc/video_accelerator/arc_video_accelerator_util.h8
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.cc2
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_decode_accelerator.h4
-rw-r--r--chromium/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc2
-rw-r--r--chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc7
-rw-r--r--chromium/components/arc/volume_mounter/arc_volume_mounter_bridge_unittest.cc46
-rw-r--r--chromium/components/arc_strings.grdp21
-rw-r--r--chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_DESKTOP.png.sha12
-rw-r--r--chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_PHONE.png.sha12
-rw-r--r--chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_RESIZE_SETTINGS.png.sha12
-rw-r--r--chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TABLET.png.sha12
-rw-r--r--chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_BODY.png.sha11
-rw-r--r--chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_LINK.png.sha11
-rw-r--r--chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_TITLE.png.sha11
-rw-r--r--chromium/components/assist_ranker/assist_ranker_service.h3
-rw-r--r--chromium/components/assist_ranker/base_predictor.h1
-rw-r--r--chromium/components/assist_ranker/base_predictor_unittest.cc1
-rw-r--r--chromium/components/assist_ranker/binary_classifier_predictor_unittest.cc1
-rw-r--r--chromium/components/assist_ranker/classifier_predictor_unittest.cc1
-rw-r--r--chromium/components/assist_ranker/predictor_config_definitions.cc2
-rw-r--r--chromium/components/assist_ranker/predictor_config_definitions.h4
-rw-r--r--chromium/components/assist_ranker/ranker_model_loader.h1
-rw-r--r--chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc1
-rw-r--r--chromium/components/autofill/DEPS1
-rw-r--r--chromium/components/autofill/OWNERS1
-rw-r--r--chromium/components/autofill/PRESUBMIT.py8
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillActionModeCallback.java60
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillHintsService.java74
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java230
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProvider.java880
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProviderUMA.java363
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormData.java56
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormFieldData.java206
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/IAutofillHintsService.aidl22
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/IViewTypeCallback.aidl22
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/OWNERS2
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/README.md53
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/ViewType.aidl7
-rw-r--r--chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/ViewType.java88
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.cc288
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver.h60
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.cc45
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_factory.h22
-rw-r--r--chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc136
-rw-r--r--chromium/components/autofill/content/browser/risk/fingerprint.cc2
-rw-r--r--chromium/components/autofill/content/browser/webauthn/internal_authenticator_impl.h1
-rw-r--r--chromium/components/autofill/content/common/mojom/autofill_agent.mojom10
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.cc99
-rw-r--r--chromium/components/autofill/content/renderer/autofill_agent.h22
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.cc479
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util.h7
-rw-r--r--chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc77
-rw-r--r--chromium/components/autofill/content/renderer/form_cache.cc15
-rw-r--r--chromium/components/autofill/content/renderer/form_cache.h14
-rw-r--r--chromium/components/autofill/content/renderer/form_cache_browsertest.cc37
-rw-r--r--chromium/components/autofill/content/renderer/form_tracker.cc2
-rw-r--r--chromium/components/autofill/content/renderer/form_tracker.h2
-rw-r--r--chromium/components/autofill/content/renderer/html_based_username_detector.cc8
-rw-r--r--chromium/components/autofill/content/renderer/password_autofill_agent.cc15
-rw-r--r--chromium/components/autofill/content/renderer/password_form_conversion_utils.cc21
-rw-r--r--chromium/components/autofill/content/renderer/password_generation_agent.cc4
-rw-r--r--chromium/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/BUILD.gn68
-rw-r--r--chromium/components/autofill/core/browser/DEPS6
-rw-r--r--chromium/components/autofill/core/browser/address_profile_save_manager.cc144
-rw-r--r--chromium/components/autofill/core/browser/address_profile_save_manager.h52
-rw-r--r--chromium/components/autofill/core/browser/address_profile_save_manager_unittest.cc935
-rw-r--r--chromium/components/autofill/core/browser/address_rewriter.cc3
-rw-r--r--chromium/components/autofill/core/browser/address_rewriter_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/autocomplete_history_manager.cc3
-rw-r--r--chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc55
-rw-r--r--chromium/components/autofill/core/browser/autofill_ablation_study.cc164
-rw-r--r--chromium/components/autofill/core/browser/autofill_ablation_study.h74
-rw-r--r--chromium/components/autofill/core/browser/autofill_ablation_study_unittest.cc242
-rw-r--r--chromium/components/autofill/core/browser/autofill_address_util.cc305
-rw-r--r--chromium/components/autofill/core/browser/autofill_address_util.h120
-rw-r--r--chromium/components/autofill/core/browser/autofill_address_util_unittest.cc189
-rw-r--r--chromium/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.css18
-rw-r--r--chromium/components/autofill/core/browser/autofill_client.cc20
-rw-r--r--chromium/components/autofill/core/browser/autofill_client.h68
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager.cc10
-rw-r--r--chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc134
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver.h5
-rw-r--r--chromium/components/autofill/core/browser/autofill_driver_factory.h6
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments.cc75
-rw-r--r--chromium/components/autofill/core/browser/autofill_experiments_unittest.cc8
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.cc7
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate.h11
-rw-r--r--chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc67
-rw-r--r--chromium/components/autofill/core/browser/autofill_field.h12
-rw-r--r--chromium/components/autofill/core/browser/autofill_form_test_utils.cc25
-rw-r--r--chromium/components/autofill/core/browser/autofill_form_test_utils.h41
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler.cc562
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler.h378
-rw-r--r--chromium/components/autofill/core/browser/autofill_handler_proxy.cc115
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.cc2930
-rw-r--r--chromium/components/autofill/core/browser/autofill_manager.h965
-rw-r--r--chromium/components/autofill/core/browser/autofill_merge_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.cc198
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics.h73
-rw-r--r--chromium/components/autofill/core/browser/autofill_metrics_unittest.cc2169
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_import_process.cc380
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_import_process.h215
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_import_process_unittest.cc669
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_save_strike_database.cc100
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_save_strike_database.h42
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_save_strike_database_unittest.cc157
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_sync_util.cc14
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc14
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_update_strike_database.cc59
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_update_strike_database.h36
-rw-r--r--chromium/components/autofill/core/browser/autofill_profile_update_strike_database_unittest.cc71
-rw-r--r--chromium/components/autofill/core/browser/autofill_regex_constants.cc16
-rw-r--r--chromium/components/autofill/core/browser/autofill_regexes.cc7
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios.cc129
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios.h74
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios_unittest.cc29
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios.cc233
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios.h123
-rw-r--r--chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios_unittest.cc118
-rw-r--r--chromium/components/autofill/core/browser/autofill_subject.cc1
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.cc27
-rw-r--r--chromium/components/autofill/core/browser/autofill_test_utils.h7
-rw-r--r--chromium/components/autofill/core/browser/autofill_type.cc4
-rw-r--r--chromium/components/autofill/core/browser/browser_autofill_manager.cc2781
-rw-r--r--chromium/components/autofill/core/browser/browser_autofill_manager.h751
-rw-r--r--chromium/components/autofill/core/browser/browser_autofill_manager_test_delegate.h (renamed from chromium/components/autofill/core/browser/autofill_manager_test_delegate.h)10
-rw-r--r--chromium/components/autofill/core/browser/browser_autofill_manager_unittest.cc (renamed from chromium/components/autofill/core/browser/autofill_manager_unittest.cc)1522
-rw-r--r--chromium/components/autofill/core/browser/data_model/address.cc6
-rw-r--r--chromium/components/autofill/core/browser/data_model/address.h2
-rw-r--r--chromium/components/autofill/core/browser/data_model/address_unittest.cc66
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_offer_data.cc29
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_offer_data.h46
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile.cc22
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile.h30
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.cc105
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.h51
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc311
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_profile_unittest.cc128
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_structured_address.cc26
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_structured_address_component.h7
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_structured_address_name_unittest.cc1
-rw-r--r--chromium/components/autofill/core/browser/data_model/autofill_structured_address_unittest.cc12
-rw-r--r--chromium/components/autofill/core/browser/data_model/borrowed_transliterator.h1
-rw-r--r--chromium/components/autofill/core/browser/data_model/contact_info.cc9
-rw-r--r--chromium/components/autofill/core/browser/data_model/contact_info_unittest.cc1
-rw-r--r--chromium/components/autofill/core/browser/data_model/credit_card.cc21
-rw-r--r--chromium/components/autofill/core/browser/data_model/credit_card.h40
-rw-r--r--chromium/components/autofill/core/browser/data_model/credit_card_art_image.cc21
-rw-r--r--chromium/components/autofill/core/browser/data_model/credit_card_art_image.h36
-rw-r--r--chromium/components/autofill/core/browser/field_filler.cc26
-rw-r--r--chromium/components/autofill/core/browser/field_filler_unittest.cc246
-rw-r--r--chromium/components/autofill/core/browser/field_types.h4
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.cc35
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer.h8
-rw-r--r--chromium/components/autofill/core/browser/form_data_importer_unittest.cc115
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/autofill_parsing_utils.h4
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/autofill_scanner.h1
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/form_field.cc1
-rw-r--r--chromium/components/autofill/core/browser/form_parsing/form_field_unittest.cc47
-rw-r--r--chromium/components/autofill/core/browser/form_processing/label_processing_util.cc6
-rw-r--r--chromium/components/autofill/core/browser/form_processing/label_processing_util.h6
-rw-r--r--chromium/components/autofill/core/browser/form_processing/label_processing_util_unittest.cc16
-rw-r--r--chromium/components/autofill/core/browser/form_processing/name_processing_util.cc30
-rw-r--r--chromium/components/autofill/core/browser/form_processing/name_processing_util.h10
-rw-r--r--chromium/components/autofill/core/browser/form_processing/name_processing_util_unittest.cc37
-rw-r--r--chromium/components/autofill/core/browser/form_structure.cc73
-rw-r--r--chromium/components/autofill/core/browser/form_structure.h20
-rw-r--r--chromium/components/autofill/core/browser/form_structure_unittest.cc313
-rw-r--r--chromium/components/autofill/core/browser/geo/alternative_state_name_map.cc17
-rw-r--r--chromium/components/autofill/core/browser/geo/alternative_state_name_map.h14
-rw-r--r--chromium/components/autofill/core/browser/geo/alternative_state_name_map_test_utils.h2
-rw-r--r--chromium/components/autofill/core/browser/geo/alternative_state_name_map_unittest.cc16
-rw-r--r--chromium/components/autofill/core/browser/geo/alternative_state_name_map_updater.h3
-rw-r--r--chromium/components/autofill/core/browser/geo/alternative_state_name_map_updater_unittest.cc23
-rw-r--r--chromium/components/autofill/core/browser/geo/phone_number_i18n_unittest.cc269
-rw-r--r--chromium/components/autofill/core/browser/geo/state_names.cc125
-rw-r--r--chromium/components/autofill/core/browser/metrics/form_event_logger_base.cc98
-rw-r--r--chromium/components/autofill/core/browser/metrics/form_event_logger_base.h21
-rw-r--r--chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc30
-rw-r--r--chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h6
-rw-r--r--chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser_unittest.cc14
-rw-r--r--chromium/components/autofill/core/browser/pattern_provider/pattern_provider.h7
-rw-r--r--chromium/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json4
-rw-r--r--chromium/components/autofill/core/browser/payments/account_info_getter.h2
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_offer_manager.cc48
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_offer_manager.h23
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_offer_manager_unittest.cc117
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_mobile.h2
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.cc2
-rw-r--r--chromium/components/autofill/core/browser/payments/autofill_wallet_model_type_controller.h1
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_access_manager.cc62
-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.cc168
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator.h10
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_cvc_authenticator_unittest.cc9
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.cc4
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator.h4
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_fido_authenticator_unittest.cc7
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_manager.cc93
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_manager.h13
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc23
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_strike_database.cc13
-rw-r--r--chromium/components/autofill/core/browser/payments/credit_card_save_strike_database.h14
-rw-r--r--chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.cc14
-rw-r--r--chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.h14
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request.cc4
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request.h6
-rw-r--r--chromium/components/autofill/core/browser/payments/full_card_request_unittest.cc42
-rw-r--r--chromium/components/autofill/core/browser/payments/legal_message_line_unittest.cc2
-rw-r--r--chromium/components/autofill/core/browser/payments/local_card_migration_manager.h6
-rw-r--r--chromium/components/autofill/core/browser/payments/local_card_migration_manager_unittest.cc171
-rw-r--r--chromium/components/autofill/core/browser/payments/local_card_migration_strike_database.cc14
-rw-r--r--chromium/components/autofill/core/browser/payments/local_card_migration_strike_database.h14
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.cc2
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client.h19
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_client_unittest.cc15
-rw-r--r--chromium/components/autofill/core/browser/payments/payments_service_url.cc1
-rw-r--r--chromium/components/autofill/core/browser/payments/strike_database_integrator_base.cc109
-rw-r--r--chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database.h44
-rw-r--r--chromium/components/autofill/core/browser/payments/test_authentication_requester.h4
-rw-r--r--chromium/components/autofill/core/browser/payments/test_credit_card_fido_authenticator.h3
-rw-r--r--chromium/components/autofill/core/browser/payments/test_strike_database.h2
-rw-r--r--chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.h2
-rw-r--r--chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout.cc78
-rw-r--r--chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout.h100
-rw-r--r--chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout_unittest.cc188
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.cc115
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager.h71
-rw-r--r--chromium/components/autofill/core/browser/personal_data_manager_unittest.cc503
-rw-r--r--chromium/components/autofill/core/browser/randomized_encoder_unittest.cc3
-rw-r--r--chromium/components/autofill/core/browser/strike_database.cc (renamed from chromium/components/autofill/core/browser/payments/strike_database.cc)79
-rw-r--r--chromium/components/autofill/core/browser/strike_database.h (renamed from chromium/components/autofill/core/browser/payments/strike_database.h)65
-rw-r--r--chromium/components/autofill/core/browser/strike_database_base.cc17
-rw-r--r--chromium/components/autofill/core/browser/strike_database_base.h83
-rw-r--r--chromium/components/autofill/core/browser/strike_database_integrator_base.cc202
-rw-r--r--chromium/components/autofill/core/browser/strike_database_integrator_base.h (renamed from chromium/components/autofill/core/browser/payments/strike_database_integrator_base.h)89
-rw-r--r--chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.cc (renamed from chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database.cc)44
-rw-r--r--chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.h56
-rw-r--r--chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database_unittest.cc (renamed from chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database_unittest.cc)132
-rw-r--r--chromium/components/autofill/core/browser/strike_database_unittest.cc (renamed from chromium/components/autofill/core/browser/payments/strike_database_unittest.cc)83
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.cc2
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_client.h8
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_clock.h2
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_driver.cc3
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_driver.h2
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_external_delegate.cc2
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_external_delegate.h7
-rw-r--r--chromium/components/autofill/core/browser/test_autofill_tick_clock.h2
-rw-r--r--chromium/components/autofill/core/browser/test_browser_autofill_manager.cc (renamed from chromium/components/autofill/core/browser/test_autofill_manager.cc)57
-rw-r--r--chromium/components/autofill/core/browser/test_browser_autofill_manager.h (renamed from chromium/components/autofill/core/browser/test_autofill_manager.h)27
-rw-r--r--chromium/components/autofill/core/browser/test_inmemory_strike_database.cc101
-rw-r--r--chromium/components/autofill/core/browser/test_inmemory_strike_database.h52
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.cc14
-rw-r--r--chromium/components/autofill/core/browser/test_personal_data_manager.h23
-rw-r--r--chromium/components/autofill/core/browser/test_utils/test_profiles.cc123
-rw-r--r--chromium/components/autofill/core/browser/test_utils/test_profiles.h65
-rw-r--r--chromium/components/autofill/core/browser/ui/accessory_sheet_data.cc4
-rw-r--r--chromium/components/autofill/core/browser/ui/accessory_sheet_data.h6
-rw-r--r--chromium/components/autofill/core/browser/ui/accessory_sheet_enums.h2
-rw-r--r--chromium/components/autofill/core/browser/ui/address_form_label_formatter_unittest.cc5
-rw-r--r--chromium/components/autofill/core/browser/ui/mobile_label_formatter_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_controller_impl_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view.h2
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl_unittest.cc4
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h2
-rw-r--r--chromium/components/autofill/core/browser/ui/payments/local_card_migration_bubble_controller.h2
-rw-r--r--chromium/components/autofill/core/browser/ui/region_combobox_model_unittest.cc6
-rw-r--r--chromium/components/autofill/core/browser/validation_unittest.cc318
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc22
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h6
-rw-r--r--chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge_unittest.cc3
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.cc16
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h8
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_bridge_unittest.cc19
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.cc50
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h28
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker_unittest.cc14
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc177
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc89
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.cc360
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table.h49
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc198
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.cc46
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge.h8
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_metadata_sync_bridge_unittest.cc79
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc16
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.h4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge_unittest.cc44
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.cc44
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge.h4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_wallet_sync_bridge_unittest.cc99
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h2
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc4
-rw-r--r--chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h4
-rw-r--r--chromium/components/autofill/core/common/BUILD.gn15
-rw-r--r--chromium/components/autofill/core/common/autofill_features.cc100
-rw-r--r--chromium/components/autofill/core/common/autofill_features.h118
-rw-r--r--chromium/components/autofill/core/common/autofill_internals/log_message.h7
-rw-r--r--chromium/components/autofill/core/common/autofill_internals/logging_scope.h6
-rw-r--r--chromium/components/autofill/core/common/autofill_payments_features.cc36
-rw-r--r--chromium/components/autofill/core/common/autofill_payments_features.h9
-rw-r--r--chromium/components/autofill/core/common/autofill_util.cc14
-rw-r--r--chromium/components/autofill/core/common/autofill_util.h4
-rw-r--r--chromium/components/autofill/core/common/dense_set.h2
-rw-r--r--chromium/components/autofill/core/common/field_data_manager.cc6
-rw-r--r--chromium/components/autofill/core/common/field_data_manager.h4
-rw-r--r--chromium/components/autofill/core/common/logging/log_buffer.cc5
-rw-r--r--chromium/components/autofill/core/common/save_password_progress_logger_unittest.cc1
-rw-r--r--chromium/components/autofill/core/common/signatures.h2
-rw-r--r--chromium/components/autofill/ios/browser/BUILD.gn34
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent.h12
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent.mm177
-rw-r--r--chromium/components/autofill/ios/browser/autofill_agent_unittests.mm12
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.h37
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios.mm19
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h30
-rw-r--r--chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm15
-rw-r--r--chromium/components/autofill/ios/browser/autofill_java_script_feature.mm3
-rw-r--r--chromium/components/autofill/ios/browser/autofill_util.h2
-rw-r--r--chromium/components/autofill/ios/browser/autofill_util.mm14
-rw-r--r--chromium/components/autofill/ios/browser/fake_autofill_agent.mm51
-rw-r--r--chromium/components/autofill/ios/browser/js_suggestion_manager.h94
-rw-r--r--chromium/components/autofill/ios/browser/js_suggestion_manager.mm146
-rw-r--r--chromium/components/autofill/ios/browser/suggestion_controller_java_script_feature.h84
-rw-r--r--chromium/components/autofill/ios/browser/suggestion_controller_java_script_feature.mm141
-rw-r--r--chromium/components/autofill/ios/form_util/BUILD.gn61
-rw-r--r--chromium/components/autofill/ios/form_util/DEPS3
-rw-r--r--chromium/components/autofill/ios/form_util/fill_js_unittest.mm125
-rw-r--r--chromium/components/autofill/ios/form_util/form_activity_tab_helper.h49
-rw-r--r--chromium/components/autofill/ios/form_util/form_activity_tab_helper.mm147
-rw-r--r--chromium/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm141
-rw-r--r--chromium/components/autofill/ios/form_util/form_handlers_java_script_feature.h52
-rw-r--r--chromium/components/autofill/ios/form_util/form_handlers_java_script_feature.mm78
-rw-r--r--chromium/components/autofill/ios/form_util/form_unittest.mm113
-rw-r--r--chromium/components/autofill/ios/form_util/form_util_java_script_feature.h42
-rw-r--r--chromium/components/autofill/ios/form_util/form_util_java_script_feature.mm55
-rw-r--r--chromium/components/autofill/ios/form_util/resources/fill.js2
-rw-r--r--chromium/components/autofill/ios/form_util/resources/form.js3
-rw-r--r--chromium/components/autofill/ios/form_util/resources/form_handlers.js19
-rw-r--r--chromium/components/autofill_assistant/README.md16
-rw-r--r--chromium/components/autofill_assistant/browser/BUILD.gn21
-rw-r--r--chromium/components/autofill_assistant/browser/DEPS1
-rw-r--r--chromium/components/autofill_assistant/browser/action_value.proto66
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action.cc19
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action.h4
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action_delegate.h22
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action_delegate_util.cc77
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action_delegate_util.h13
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action_delegate_util_unittest.cc100
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action_test_utils.cc23
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action_test_utils.h21
-rw-r--r--chromium/components/autofill_assistant/browser/actions/action_unittest.cc3
-rw-r--r--chromium/components/autofill_assistant/browser/actions/check_element_tag_action.cc71
-rw-r--r--chromium/components/autofill_assistant/browser/actions/check_element_tag_action.h43
-rw-r--r--chromium/components/autofill_assistant/browser/actions/check_element_tag_action_unittest.cc98
-rw-r--r--chromium/components/autofill_assistant/browser/actions/check_option_element_action.cc61
-rw-r--r--chromium/components/autofill_assistant/browser/actions/check_option_element_action.h44
-rw-r--r--chromium/components/autofill_assistant/browser/actions/check_option_element_action_unittest.cc153
-rw-r--r--chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action.cc25
-rw-r--r--chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action.h29
-rw-r--r--chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action_unittest.cc45
-rw-r--r--chromium/components/autofill_assistant/browser/actions/click_action.h3
-rw-r--r--chromium/components/autofill_assistant/browser/actions/click_action_unittest.cc21
-rw-r--r--chromium/components/autofill_assistant/browser/actions/collect_user_data_action.cc106
-rw-r--r--chromium/components/autofill_assistant/browser/actions/collect_user_data_action.h15
-rw-r--r--chromium/components/autofill_assistant/browser/actions/collect_user_data_action_unittest.cc390
-rw-r--r--chromium/components/autofill_assistant/browser/actions/configure_bottom_sheet_action_unittest.cc13
-rw-r--r--chromium/components/autofill_assistant/browser/actions/dispatch_js_event_action.h3
-rw-r--r--chromium/components/autofill_assistant/browser/actions/dispatch_js_event_action_unittest.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/actions/expect_navigation_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field.cc23
-rw-r--r--chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field.h54
-rw-r--r--chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field_unittest.cc66
-rw-r--r--chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.cc274
-rw-r--r--chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.h13
-rw-r--r--chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler_unittest.cc299
-rw-r--r--chromium/components/autofill_assistant/browser/actions/generate_password_for_form_field_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/generate_password_for_form_field_action_unittest.cc6
-rw-r--r--chromium/components/autofill_assistant/browser/actions/get_element_status_action.cc72
-rw-r--r--chromium/components/autofill_assistant/browser/actions/get_element_status_action.h12
-rw-r--r--chromium/components/autofill_assistant/browser/actions/get_element_status_action_unittest.cc221
-rw-r--r--chromium/components/autofill_assistant/browser/actions/highlight_element_action.h3
-rw-r--r--chromium/components/autofill_assistant/browser/actions/mock_action_delegate.h189
-rw-r--r--chromium/components/autofill_assistant/browser/actions/navigate_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/presave_generated_password_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/presave_generated_password_action.h4
-rw-r--r--chromium/components/autofill_assistant/browser/actions/presave_generated_password_action_unittest.cc6
-rw-r--r--chromium/components/autofill_assistant/browser/actions/prompt_action.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/actions/prompt_action.h3
-rw-r--r--chromium/components/autofill_assistant/browser/actions/prompt_action_unittest.cc8
-rw-r--r--chromium/components/autofill_assistant/browser/actions/release_elements_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/save_generated_password_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/save_generated_password_action.h4
-rw-r--r--chromium/components/autofill_assistant/browser/actions/select_option_action.cc15
-rw-r--r--chromium/components/autofill_assistant/browser/actions/select_option_action_unittest.cc90
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_attribute_action.h3
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_form_field_value_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc120
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action.cc83
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action.h34
-rw-r--r--chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action_unittest.cc124
-rw-r--r--chromium/components/autofill_assistant/browser/actions/show_details_action.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/show_details_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/show_details_action_unittest.cc10
-rw-r--r--chromium/components/autofill_assistant/browser/actions/show_form_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/show_generic_ui_action.cc6
-rw-r--r--chromium/components/autofill_assistant/browser/actions/show_generic_ui_action.h3
-rw-r--r--chromium/components/autofill_assistant/browser/actions/show_generic_ui_action_unittest.cc121
-rw-r--r--chromium/components/autofill_assistant/browser/actions/stop_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/stopwatch.h3
-rw-r--r--chromium/components/autofill_assistant/browser/actions/tell_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/use_address_action.cc6
-rw-r--r--chromium/components/autofill_assistant/browser/actions/use_address_action.h3
-rw-r--r--chromium/components/autofill_assistant/browser/actions/use_address_action_unittest.cc135
-rw-r--r--chromium/components/autofill_assistant/browser/actions/use_credit_card_action.cc9
-rw-r--r--chromium/components/autofill_assistant/browser/actions/use_credit_card_action.h2
-rw-r--r--chromium/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc175
-rw-r--r--chromium/components/autofill_assistant/browser/actions/wait_for_document_action_unittest.cc12
-rw-r--r--chromium/components/autofill_assistant/browser/actions/wait_for_dom_action_unittest.cc9
-rw-r--r--chromium/components/autofill_assistant/browser/actions/wait_for_navigation_action.h3
-rw-r--r--chromium/components/autofill_assistant/browser/autofill_assistant_onboarding_fetcher.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/basic_interactions.cc59
-rw-r--r--chromium/components/autofill_assistant/browser/basic_interactions.h17
-rw-r--r--chromium/components/autofill_assistant/browser/basic_interactions_unittest.cc38
-rw-r--r--chromium/components/autofill_assistant/browser/client.h2
-rw-r--r--chromium/components/autofill_assistant/browser/client_context.cc3
-rw-r--r--chromium/components/autofill_assistant/browser/client_context_unittest.cc15
-rw-r--r--chromium/components/autofill_assistant/browser/client_settings.h8
-rw-r--r--chromium/components/autofill_assistant/browser/client_status.cc6
-rw-r--r--chromium/components/autofill_assistant/browser/controller.cc83
-rw-r--r--chromium/components/autofill_assistant/browser/controller.h33
-rw-r--r--chromium/components/autofill_assistant/browser/controller_observer.h7
-rw-r--r--chromium/components/autofill_assistant/browser/controller_unittest.cc63
-rw-r--r--chromium/components/autofill_assistant/browser/details.cc28
-rw-r--r--chromium/components/autofill_assistant/browser/details.h2
-rw-r--r--chromium/components/autofill_assistant/browser/details_unittest.cc21
-rw-r--r--chromium/components/autofill_assistant/browser/devtools/BUILD.gn5
-rw-r--r--chromium/components/autofill_assistant/browser/devtools/devtools_api/client_api_generator.py2
-rw-r--r--chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_types_h.template4
-rw-r--r--chromium/components/autofill_assistant/browser/devtools/devtools_client.cc1
-rw-r--r--chromium/components/autofill_assistant/browser/devtools/value_conversions.h3
-rw-r--r--chromium/components/autofill_assistant/browser/dom_action.proto33
-rw-r--r--chromium/components/autofill_assistant/browser/element_area.h1
-rw-r--r--chromium/components/autofill_assistant/browser/element_area_unittest.cc162
-rw-r--r--chromium/components/autofill_assistant/browser/element_precondition.h4
-rw-r--r--chromium/components/autofill_assistant/browser/event_handler.cc28
-rw-r--r--chromium/components/autofill_assistant/browser/event_handler.h4
-rw-r--r--chromium/components/autofill_assistant/browser/fake_script_executor_delegate.cc11
-rw-r--r--chromium/components/autofill_assistant/browser/fake_script_executor_delegate.h10
-rw-r--r--chromium/components/autofill_assistant/browser/fake_starter_platform_delegate.cc49
-rw-r--r--chromium/components/autofill_assistant/browser/fake_starter_platform_delegate.h39
-rw-r--r--chromium/components/autofill_assistant/browser/features.cc23
-rw-r--r--chromium/components/autofill_assistant/browser/features.h4
-rw-r--r--chromium/components/autofill_assistant/browser/field_formatter.cc68
-rw-r--r--chromium/components/autofill_assistant/browser/field_formatter.h26
-rw-r--r--chromium/components/autofill_assistant/browser/field_formatter_unittest.cc95
-rw-r--r--chromium/components/autofill_assistant/browser/full_card_requester.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/generic_ui.proto7
-rw-r--r--chromium/components/autofill_assistant/browser/info_box.h3
-rw-r--r--chromium/components/autofill_assistant/browser/intent_strings.h2
-rw-r--r--chromium/components/autofill_assistant/browser/metrics.cc96
-rw-r--r--chromium/components/autofill_assistant/browser/metrics.h360
-rw-r--r--chromium/components/autofill_assistant/browser/mock_client.h2
-rw-r--r--chromium/components/autofill_assistant/browser/mock_controller_observer.h2
-rw-r--r--chromium/components/autofill_assistant/browser/model.proto29
-rw-r--r--chromium/components/autofill_assistant/browser/onboarding_result.h2
-rw-r--r--chromium/components/autofill_assistant/browser/overlay_state.h2
-rw-r--r--chromium/components/autofill_assistant/browser/protocol_utils.cc54
-rw-r--r--chromium/components/autofill_assistant/browser/protocol_utils.h7
-rw-r--r--chromium/components/autofill_assistant/browser/protocol_utils_unittest.cc59
-rw-r--r--chromium/components/autofill_assistant/browser/public/mock_runtime_manager.h2
-rw-r--r--chromium/components/autofill_assistant/browser/script_executor.cc77
-rw-r--r--chromium/components/autofill_assistant/browser/script_executor.h15
-rw-r--r--chromium/components/autofill_assistant/browser/script_executor_delegate.h9
-rw-r--r--chromium/components/autofill_assistant/browser/script_executor_unittest.cc24
-rw-r--r--chromium/components/autofill_assistant/browser/script_parameters.cc56
-rw-r--r--chromium/components/autofill_assistant/browser/script_parameters.h44
-rw-r--r--chromium/components/autofill_assistant/browser/script_parameters_unittest.cc9
-rw-r--r--chromium/components/autofill_assistant/browser/script_tracker.h1
-rw-r--r--chromium/components/autofill_assistant/browser/selector.cc63
-rw-r--r--chromium/components/autofill_assistant/browser/selector.h15
-rw-r--r--chromium/components/autofill_assistant/browser/service.proto296
-rw-r--r--chromium/components/autofill_assistant/browser/service/mock_url_loader.h2
-rw-r--r--chromium/components/autofill_assistant/browser/service/service_impl.h2
-rw-r--r--chromium/components/autofill_assistant/browser/service/service_request_sender_impl.cc2
-rw-r--r--chromium/components/autofill_assistant/browser/starter.cc587
-rw-r--r--chromium/components/autofill_assistant/browser/starter.h124
-rw-r--r--chromium/components/autofill_assistant/browser/starter_heuristic.cc150
-rw-r--r--chromium/components/autofill_assistant/browser/starter_heuristic.h75
-rw-r--r--chromium/components/autofill_assistant/browser/starter_heuristic_unittest.cc254
-rw-r--r--chromium/components/autofill_assistant/browser/starter_platform_delegate.h22
-rw-r--r--chromium/components/autofill_assistant/browser/starter_unittest.cc1941
-rw-r--r--chromium/components/autofill_assistant/browser/startup_util.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/startup_util.h6
-rw-r--r--chromium/components/autofill_assistant/browser/startup_util_unittest.cc8
-rw-r--r--chromium/components/autofill_assistant/browser/switches.cc29
-rw-r--r--chromium/components/autofill_assistant/browser/switches.h6
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_context.cc38
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_context.h28
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_context_unittest.cc33
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.h4
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions_unittest.cc12
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/mock_dynamic_trigger_conditions.h2
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.cc4
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.h12
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.cc12
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.h27
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.cc33
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.h28
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions_unittest.cc83
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script.h4
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc278
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h107
-rw-r--r--chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc733
-rw-r--r--chromium/components/autofill_assistant/browser/ui_delegate.h22
-rw-r--r--chromium/components/autofill_assistant/browser/url_utils.cc16
-rw-r--r--chromium/components/autofill_assistant/browser/url_utils.h4
-rw-r--r--chromium/components/autofill_assistant/browser/url_utils_unittest.cc12
-rw-r--r--chromium/components/autofill_assistant/browser/user_data.cc10
-rw-r--r--chromium/components/autofill_assistant/browser/user_data.h51
-rw-r--r--chromium/components/autofill_assistant/browser/user_data_util.cc71
-rw-r--r--chromium/components/autofill_assistant/browser/user_data_util.h11
-rw-r--r--chromium/components/autofill_assistant/browser/user_data_util_unittest.cc291
-rw-r--r--chromium/components/autofill_assistant/browser/user_model.cc104
-rw-r--r--chromium/components/autofill_assistant/browser/user_model.h53
-rw-r--r--chromium/components/autofill_assistant/browser/user_model_unittest.cc108
-rw-r--r--chromium/components/autofill_assistant/browser/value_util.cc53
-rw-r--r--chromium/components/autofill_assistant/browser/value_util.h4
-rw-r--r--chromium/components/autofill_assistant/browser/value_util_unittest.cc59
-rw-r--r--chromium/components/autofill_assistant/browser/viewport_mode.h2
-rw-r--r--chromium/components/autofill_assistant/browser/wait_for_document_operation_unittest.cc10
-rw-r--r--chromium/components/autofill_assistant/browser/web/click_or_tap_worker.cc156
-rw-r--r--chromium/components/autofill_assistant/browser/web/click_or_tap_worker.h67
-rw-r--r--chromium/components/autofill_assistant/browser/web/element_finder.h5
-rw-r--r--chromium/components/autofill_assistant/browser/web/element_store_unittest.cc24
-rw-r--r--chromium/components/autofill_assistant/browser/web/mock_web_controller.h89
-rw-r--r--chromium/components/autofill_assistant/browser/web/send_keyboard_input_worker.cc10
-rw-r--r--chromium/components/autofill_assistant/browser/web/send_keyboard_input_worker.h2
-rw-r--r--chromium/components/autofill_assistant/browser/web/web_controller.cc463
-rw-r--r--chromium/components/autofill_assistant/browser/web/web_controller.h94
-rw-r--r--chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc258
-rw-r--r--chromium/components/autofill_assistant/browser/website_login_manager_impl_unittest.cc29
-rw-r--r--chromium/components/autofill_assistant_strings.grdp2
-rw-r--r--chromium/components/autofill_payments_strings.grdp35
-rw-r--r--chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_MOBILE_SAVE_CARD_TO_CLOUD_CONFIRMATION_DIALOG_TITLE.png.sha11
-rw-r--r--chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_CARD_NUMBER_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_CVC_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_EXP_DATE_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_TITLE.png.sha11
-rw-r--r--chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_ICON_TOOLTIP.png.sha11
-rw-r--r--chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_ACTION_TEXT.png.sha11
-rw-r--r--chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_MESSAGE_TEXT.png.sha11
-rw-r--r--chromium/components/autofill_strings.grdp91
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_ANDROID_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_CANCEL_BUTTON_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_SAVE.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_UPDATE.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_TITLE.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_EDIT_BUTTON_TOOLTIP.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_OK_BUTTON_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_NEW_VALUES_SECTION_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_OK_BUTTON_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_OLD_VALUES_SECTION_LABEL.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_PRIMARY_ACTION.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_TITLE.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_PRIMARY_ACTION.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_TITLE.png.sha11
-rw-r--r--chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE.png.sha11
-rw-r--r--chromium/components/back_forward_cache/back_forward_cache_disable.cc6
-rw-r--r--chromium/components/back_forward_cache/back_forward_cache_disable.h7
-rw-r--r--chromium/components/background_fetch/background_fetch_delegate_base.cc52
-rw-r--r--chromium/components/background_fetch/background_fetch_delegate_base.h16
-rw-r--r--chromium/components/background_sync/background_sync_controller_impl.cc5
-rw-r--r--chromium/components/background_sync/background_sync_delegate.h6
-rw-r--r--chromium/components/background_sync/background_sync_metrics.cc2
-rw-r--r--chromium/components/background_sync/background_sync_metrics.h3
-rw-r--r--chromium/components/background_sync/background_sync_permission_context_unittest.cc4
-rw-r--r--chromium/components/background_task_scheduler/task_info.h8
-rw-r--r--chromium/components/blocked_content/BUILD.gn1
-rw-r--r--chromium/components/blocked_content/android/DEPS1
-rw-r--r--chromium/components/blocked_content/android/popup_blocked_infobar_delegate.cc10
-rw-r--r--chromium/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc22
-rw-r--r--chromium/components/blocked_content/android/popup_blocked_message_delegate.cc20
-rw-r--r--chromium/components/blocked_content/android/popup_blocked_message_delegate_unittest.cc40
-rw-r--r--chromium/components/blocked_content/popup_blocker_tab_helper.cc2
-rw-r--r--chromium/components/blocked_content/popup_navigation_delegate.h6
-rw-r--r--chromium/components/blocked_content/popup_opener_tab_helper.h4
-rw-r--r--chromium/components/blocked_content/popup_tracker.h6
-rw-r--r--chromium/components/blocked_content/pref_names.h2
-rw-r--r--chromium/components/blocked_content/safe_browsing_triggered_popup_blocker.cc4
-rw-r--r--chromium/components/blocked_content/safe_browsing_triggered_popup_blocker.h4
-rw-r--r--chromium/components/blocked_content_strings.grdp4
-rw-r--r--chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist.cc3
-rw-r--r--chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist.h2
-rw-r--r--chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_data.cc4
-rw-r--r--chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_data.h2
-rw-r--r--chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_item.h7
-rw-r--r--chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_item_unittest.cc2
-rw-r--r--chromium/components/bookmarks/browser/bookmark_codec_unittest.cc169
-rw-r--r--chromium/components/bookmarks/browser/bookmark_expanded_state_tracker.cc4
-rw-r--r--chromium/components/bookmarks/browser/bookmark_model.cc7
-rw-r--r--chromium/components/bookmarks/browser/bookmark_model.h6
-rw-r--r--chromium/components/bookmarks/browser/bookmark_node_data_unittest.cc10
-rw-r--r--chromium/components/bookmarks/browser/bookmark_storage.h4
-rw-r--r--chromium/components/bookmarks/browser/bookmark_utils_unittest.cc4
-rw-r--r--chromium/components/bookmarks/browser/titled_url_index.cc8
-rw-r--r--chromium/components/bookmarks/browser/titled_url_index.h4
-rw-r--r--chromium/components/bookmarks/browser/titled_url_match.h1
-rw-r--r--chromium/components/bookmarks/managed/managed_bookmarks_policy_handler.cc6
-rw-r--r--chromium/components/bookmarks/managed/managed_bookmarks_policy_handler_unittest.cc6
-rw-r--r--chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc9
-rw-r--r--chromium/components/breadcrumbs/DEPS1
-rw-r--r--chromium/components/breadcrumbs/core/BUILD.gn45
-rw-r--r--chromium/components/breadcrumbs/core/application_breadcrumbs_not_user_action_unittest.cc45
-rw-r--r--chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service.cc73
-rw-r--r--chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service.h79
-rw-r--r--chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service_unittest.cc40
-rw-r--r--chromium/components/breadcrumbs/core/breadcrumb_manager_observer_unittest.cc92
-rw-r--r--chromium/components/breadcrumbs/core/breadcrumb_manager_unittest.cc92
-rw-r--r--chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc346
-rw-r--r--chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.h128
-rw-r--r--chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_util_unittest.cc24
-rw-r--r--chromium/components/breadcrumbs/core/features.cc12
-rw-r--r--chromium/components/breadcrumbs/core/features.h17
-rw-r--r--chromium/components/breadcrumbs/core/generate_not_user_triggered_actions.py72
-rw-r--r--chromium/components/breadcrumbs/ios/BUILD.gn33
-rw-r--r--chromium/components/breadcrumbs/ios/DEPS4
-rw-r--r--chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge.h66
-rw-r--r--chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge.mm61
-rw-r--r--chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge_unittest.mm77
-rw-r--r--chromium/components/browser_sync/active_devices_provider_impl_unittest.cc3
-rw-r--r--chromium/components/browser_sync/browser_sync_switches.h1
-rw-r--r--chromium/components/browser_sync/profile_sync_components_factory_impl.cc5
-rw-r--r--chromium/components/browser_sync/profile_sync_components_factory_impl.h2
-rw-r--r--chromium/components/browser_ui/bottomsheet/android/DIR_METADATA3
-rw-r--r--chromium/components/browser_ui/bottomsheet/android/internal/BUILD.gn1
-rw-r--r--chromium/components/browser_ui/contacts_picker/android/contacts_picker_feature_list.cc10
-rw-r--r--chromium/components/browser_ui/media/OWNERS1
-rw-r--r--chromium/components/browser_ui/notifications/android/DIR_METADATA1
-rw-r--r--chromium/components/browser_ui/photo_picker/android/BUILD.gn7
-rw-r--r--chromium/components/browser_ui/photo_picker/android/features.cc18
-rw-r--r--chromium/components/browser_ui/share/DIR_METADATA1
-rw-r--r--chromium/components/browser_ui/site_settings/android/BUILD.gn1
-rw-r--r--chromium/components/browser_ui/site_settings/android/features.cc5
-rw-r--r--chromium/components/browser_ui/site_settings/android/features.h3
-rw-r--r--chromium/components/browser_ui/site_settings/android/site_settings_feature_list.cc11
-rw-r--r--chromium/components/browser_ui/site_settings/android/storage_info_fetcher.cc3
-rw-r--r--chromium/components/browser_ui/site_settings/android/website_preference_bridge.cc24
-rw-r--r--chromium/components/browser_ui/sms/android/sms_infobar.h2
-rw-r--r--chromium/components/browser_ui/sms/android/sms_infobar_delegate_unittest.cc26
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings.grd149
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_FAST_SITE_MESSAGE.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_FAST_SITE_SUMMARY.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_UPDATE_WEBAPK_CURRENT_ICON.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_UPDATE_WEBAPK_UPDATED_ICON.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_BUTTON_CLOSE.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_BUTTON_UPDATE.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_ICON.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_NAME.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_NAME_AND_ICON.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_ICON.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_NAME.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_NAME_AND_ICON.png.sha11
-rw-r--r--chromium/components/browser_ui/strings/android/site_settings.grdp44
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_af.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ar.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_as.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_az.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_be.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bg.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bn.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bs.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ca.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_cs.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_da.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_de.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_el.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_en-GB.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_es-419.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_es.xtb19
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_et.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_eu.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fa.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fi.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fil.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fr-CA.xtb27
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fr.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_gl.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_gu.xtb21
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hi.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hu.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hy.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_id.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_is.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_it.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ja.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ka.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_kk.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_kn.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ko.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ky.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lo.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lt.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lv.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mk.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ml.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mn.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mr.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ms.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_my.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ne.xtb27
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_nl.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_no.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_or.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pa.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pl.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pt-BR.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pt-PT.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ro.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ru.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_si.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sk.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sq.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sr-Latn.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sr.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sv.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sw.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ta.xtb21
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb29
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_th.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_tr.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_uk.xtb19
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ur.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_vi.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-CN.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-HK.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-TW.xtb17
-rw-r--r--chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb17
-rw-r--r--chromium/components/browser_ui/styles/android/BUILD.gn5
-rw-r--r--chromium/components/browser_ui/webshare/DIR_METADATA1
-rw-r--r--chromium/components/browser_ui/widget/android/BUILD.gn2
-rw-r--r--chromium/components/browser_ui/widget/android/DIR_METADATA7
-rw-r--r--chromium/components/browser_watcher/extended_crash_reporting.cc3
-rw-r--r--chromium/components/browsing_data/content/BUILD.gn2
-rw-r--r--chromium/components/browsing_data/content/appcache_helper_unittest.cc3
-rw-r--r--chromium/components/browsing_data/content/browsing_data_helper.cc13
-rw-r--r--chromium/components/browsing_data/content/cache_storage_helper.h1
-rw-r--r--chromium/components/browsing_data/content/cache_storage_helper_browsertest.cc6
-rw-r--r--chromium/components/browsing_data/content/cache_storage_helper_unittest.cc3
-rw-r--r--chromium/components/browsing_data/content/conditional_cache_counting_helper.h8
-rw-r--r--chromium/components/browsing_data/content/cookie_helper.h1
-rw-r--r--chromium/components/browsing_data/content/cookie_helper_unittest.cc61
-rw-r--r--chromium/components/browsing_data/content/database_helper.cc5
-rw-r--r--chromium/components/browsing_data/content/database_helper.h2
-rw-r--r--chromium/components/browsing_data/content/database_helper_browsertest.cc53
-rw-r--r--chromium/components/browsing_data/content/file_system_helper_unittest.cc112
-rw-r--r--chromium/components/browsing_data/content/indexed_db_helper.h1
-rw-r--r--chromium/components/browsing_data/content/indexed_db_helper_browsertest.cc6
-rw-r--r--chromium/components/browsing_data/content/indexed_db_helper_unittest.cc3
-rw-r--r--chromium/components/browsing_data/content/local_shared_objects_container.cc31
-rw-r--r--chromium/components/browsing_data/content/local_storage_helper.cc4
-rw-r--r--chromium/components/browsing_data/content/local_storage_helper.h8
-rw-r--r--chromium/components/browsing_data/content/local_storage_helper_browsertest.cc151
-rw-r--r--chromium/components/browsing_data/content/mock_appcache_helper.cc4
-rw-r--r--chromium/components/browsing_data/content/mock_cache_storage_helper.cc3
-rw-r--r--chromium/components/browsing_data/content/mock_cookie_helper.cc9
-rw-r--r--chromium/components/browsing_data/content/mock_file_system_helper.cc7
-rw-r--r--chromium/components/browsing_data/content/mock_indexed_db_helper.cc3
-rw-r--r--chromium/components/browsing_data/content/mock_service_worker_helper.cc5
-rw-r--r--chromium/components/browsing_data/content/mock_shared_worker_helper.cc20
-rw-r--r--chromium/components/browsing_data/content/mock_shared_worker_helper.h6
-rw-r--r--chromium/components/browsing_data/content/service_worker_helper_unittest.cc3
-rw-r--r--chromium/components/browsing_data/content/shared_worker_helper.cc25
-rw-r--r--chromium/components/browsing_data/content/shared_worker_helper.h11
-rw-r--r--chromium/components/browsing_data/content/shared_worker_helper_unittest.cc29
-rw-r--r--chromium/components/browsing_data/core/counters/bookmark_counter.h2
-rw-r--r--chromium/components/browsing_data/core/counters/browsing_data_counter.h1
-rw-r--r--chromium/components/browsing_data/core/history_notice_utils.cc5
-rw-r--r--chromium/components/browsing_data/core/history_notice_utils.h2
-rw-r--r--chromium/components/browsing_data/core/history_notice_utils_unittest.cc4
-rw-r--r--chromium/components/captive_portal/content/captive_portal_service.cc5
-rw-r--r--chromium/components/captive_portal/content/captive_portal_tab_reloader.cc8
-rw-r--r--chromium/components/captive_portal/content/captive_portal_tab_reloader.h4
-rw-r--r--chromium/components/captive_portal/core/captive_portal_testing_utils.h2
-rw-r--r--chromium/components/cast/api_bindings/scoped_api_binding.cc3
-rw-r--r--chromium/components/cast/api_bindings/scoped_api_binding.h3
-rw-r--r--chromium/components/cast/common/BUILD.gn10
-rw-r--r--chromium/components/cast/common/constants.cc11
-rw-r--r--chromium/components/cast/common/constants.h15
-rw-r--r--chromium/components/cast/message_port/message_port_fuchsia.cc8
-rw-r--r--chromium/components/cast/message_port/message_port_fuchsia.h4
-rw-r--r--chromium/components/cast/message_port/test_message_port_receiver.cc3
-rw-r--r--chromium/components/cast/named_message_port_connector/named_message_port_connector.cc1
-rw-r--r--chromium/components/cast_certificate/cast_cert_reader.cc10
-rw-r--r--chromium/components/cast_certificate/cast_cert_reader.h4
-rw-r--r--chromium/components/cast_certificate/cast_cert_validator.cc3
-rw-r--r--chromium/components/cast_channel/BUILD.gn13
-rw-r--r--chromium/components/cast_channel/DEPS3
-rw-r--r--chromium/components/cast_channel/cast_auth_util.cc1
-rw-r--r--chromium/components/cast_channel/cast_auth_util_fuzzer.cc7
-rw-r--r--chromium/components/cast_channel/cast_message_handler.cc10
-rw-r--r--chromium/components/cast_channel/cast_message_handler.h10
-rw-r--r--chromium/components/cast_channel/cast_message_handler_unittest.cc54
-rw-r--r--chromium/components/cast_channel/cast_message_util.cc12
-rw-r--r--chromium/components/cast_channel/cast_message_util.h6
-rw-r--r--chromium/components/cast_channel/cast_message_util_fuzzer.cc2
-rw-r--r--chromium/components/cast_channel/cast_socket.cc13
-rw-r--r--chromium/components/cast_channel/cast_socket.h7
-rw-r--r--chromium/components/cast_channel/cast_socket_service.h6
-rw-r--r--chromium/components/cast_channel/cast_socket_service_unittest.cc8
-rw-r--r--chromium/components/cast_channel/cast_socket_unittest.cc12
-rw-r--r--chromium/components/cast_channel/cast_test_util.h33
-rw-r--r--chromium/components/cast_channel/cast_transport.cc1
-rw-r--r--chromium/components/cast_channel/cast_transport_unittest.cc70
-rw-r--r--chromium/components/cast_channel/enum_table.cc4
-rw-r--r--chromium/components/cast_channel/enum_table.h18
-rw-r--r--chromium/components/cast_channel/enum_table_unittest.cc14
-rw-r--r--chromium/components/cast_channel/keep_alive_delegate_unittest.cc8
-rw-r--r--chromium/components/cast_channel/libcast_socket_service.h1
-rw-r--r--chromium/components/cast_channel/logger.h1
-rw-r--r--chromium/components/cast_streaming/BUILD.gn11
-rw-r--r--chromium/components/cast_streaming/DEPS6
-rw-r--r--chromium/components/cast_streaming/DIR_METADATA3
-rw-r--r--chromium/components/cast_streaming/OWNERS3
-rw-r--r--chromium/components/cast_streaming/README.md10
-rw-r--r--chromium/components/cast_streaming/browser/BUILD.gn154
-rw-r--r--chromium/components/cast_streaming/browser/DEPS11
-rw-r--r--chromium/components/cast_streaming/browser/cast_message_port_impl.cc169
-rw-r--r--chromium/components/cast_streaming/browser/cast_message_port_impl.h59
-rw-r--r--chromium/components/cast_streaming/browser/cast_message_port_impl_unittest.cc211
-rw-r--r--chromium/components/cast_streaming/browser/cast_streaming_session.cc313
-rw-r--r--chromium/components/cast_streaming/browser/cast_streaming_session_unittest.cc141
-rw-r--r--chromium/components/cast_streaming/browser/config_conversions.cc112
-rw-r--r--chromium/components/cast_streaming/browser/config_conversions.h30
-rw-r--r--chromium/components/cast_streaming/browser/message_serialization.cc90
-rw-r--r--chromium/components/cast_streaming/browser/message_serialization.h51
-rw-r--r--chromium/components/cast_streaming/browser/network_context_getter.cc15
-rw-r--r--chromium/components/cast_streaming/browser/public/cast_streaming_session.h95
-rw-r--r--chromium/components/cast_streaming/browser/public/network_context_getter.h30
-rw-r--r--chromium/components/cast_streaming/browser/stream_consumer.cc174
-rw-r--r--chromium/components/cast_streaming/browser/stream_consumer.h87
-rw-r--r--chromium/components/cast_streaming/mojo/BUILD.gn13
-rw-r--r--chromium/components/cast_streaming/mojo/OWNERS2
-rw-r--r--chromium/components/cast_streaming/mojo/cast_streaming_session.mojom71
-rw-r--r--chromium/components/cast_streaming/renderer/BUILD.gn33
-rw-r--r--chromium/components/cast_streaming/renderer/DEPS6
-rw-r--r--chromium/components/cast_streaming/renderer/cast_streaming_demuxer.cc420
-rw-r--r--chromium/components/cast_streaming/renderer/cast_streaming_demuxer.h88
-rw-r--r--chromium/components/cast_streaming/renderer/cast_streaming_receiver.cc131
-rw-r--r--chromium/components/cast_streaming/renderer/cast_streaming_receiver.h70
-rw-r--r--chromium/components/cbor/diagnostic_writer_unittest.cc2
-rw-r--r--chromium/components/cbor/reader.cc102
-rw-r--r--chromium/components/cbor/reader.h35
-rw-r--r--chromium/components/cbor/reader_fuzzer.cc4
-rw-r--r--chromium/components/cbor/reader_unittest.cc72
-rw-r--r--chromium/components/cbor/values.cc3
-rw-r--r--chromium/components/cbor/writer.cc6
-rw-r--r--chromium/components/cbor/writer.h6
-rw-r--r--chromium/components/cdm/browser/cdm_message_filter_android.cc1
-rw-r--r--chromium/components/cdm/browser/media_drm_storage_impl.cc10
-rw-r--r--chromium/components/cdm/browser/media_drm_storage_impl.h4
-rw-r--r--chromium/components/cdm/browser/media_drm_storage_impl_unittest.cc6
-rw-r--r--chromium/components/cdm/common/cdm_manifest.cc144
-rw-r--r--chromium/components/cdm/common/cdm_manifest.h8
-rw-r--r--chromium/components/cdm/common/cdm_manifest_unittest.cc22
-rw-r--r--chromium/components/cdm/common/cdm_messages_android.h1
-rw-r--r--chromium/components/cdm/renderer/android_key_systems.cc8
-rw-r--r--chromium/components/cdm/renderer/external_clear_key_key_system_properties.cc3
-rw-r--r--chromium/components/cdm/renderer/external_clear_key_key_system_properties.h3
-rw-r--r--chromium/components/cdm/renderer/widevine_key_system_properties.cc25
-rw-r--r--chromium/components/cdm/renderer/widevine_key_system_properties.h3
-rw-r--r--chromium/components/certificate_transparency/data/log_list.json112
-rw-r--r--chromium/components/chrome_cleaner/DIR_METADATA2
-rw-r--r--chromium/components/chrome_cleaner/public/proto/DIR_METADATA5
-rw-r--r--chromium/components/chromeos_camera/dmabuf_utils.cc2
-rw-r--r--chromium/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc5
-rw-r--r--chromium/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc211
-rw-r--r--chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.h2
-rw-r--r--chromium/components/client_hints/README.md2
-rw-r--r--chromium/components/client_hints/browser/client_hints.h3
-rw-r--r--chromium/components/client_update_protocol/ecdsa_unittest.cc1
-rw-r--r--chromium/components/cloud_devices/common/cloud_device_description.cc2
-rw-r--r--chromium/components/cloud_devices/common/cloud_device_description_consts.h6
-rw-r--r--chromium/components/cloud_devices/common/cloud_devices_urls.cc1
-rw-r--r--chromium/components/cloud_devices/common/description_items.h4
-rw-r--r--chromium/components/cloud_devices/common/description_items_inl.h5
-rw-r--r--chromium/components/cloud_devices/common/printer_description.cc46
-rw-r--r--chromium/components/cloud_devices/common/printer_description.h4
-rw-r--r--chromium/components/cloud_devices/common/printer_description_unittest.cc107
-rw-r--r--chromium/components/component_updater/android/loader_policies/trust_token_key_commitments_component_loader_policy.cc8
-rw-r--r--chromium/components/component_updater/component_installer.cc58
-rw-r--r--chromium/components/component_updater/component_installer.h2
-rw-r--r--chromium/components/component_updater/component_updater_paths.cc1
-rw-r--r--chromium/components/component_updater/component_updater_paths.h2
-rw-r--r--chromium/components/component_updater/component_updater_service.cc4
-rw-r--r--chromium/components/component_updater/component_updater_service_internal.h6
-rw-r--r--chromium/components/component_updater/component_updater_utils.cc10
-rw-r--r--chromium/components/component_updater/component_updater_utils.h6
-rw-r--r--chromium/components/component_updater/installer_policies/on_device_head_suggest_component_installer.h2
-rw-r--r--chromium/components/component_updater/installer_policies/optimization_hints_component_installer.cc1
-rw-r--r--chromium/components/component_updater/installer_policies/optimization_hints_component_installer_unittest.cc2
-rw-r--r--chromium/components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.cc10
-rw-r--r--chromium/components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.h4
-rw-r--r--chromium/components/components_strings.grd10
-rw-r--r--chromium/components/consent_auditor/OWNERS1
-rw-r--r--chromium/components/consent_auditor/consent_auditor_impl_unittest.cc4
-rw-r--r--chromium/components/consent_auditor/consent_sync_bridge_impl.cc16
-rw-r--r--chromium/components/consent_auditor/consent_sync_bridge_impl.h18
-rw-r--r--chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views.cc33
-rw-r--r--chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views.h5
-rw-r--r--chromium/components/content_capture/browser/content_capture_receiver.cc2
-rw-r--r--chromium/components/content_capture/browser/content_capture_receiver_test.cc19
-rw-r--r--chromium/components/content_capture/renderer/content_capture_sender.h2
-rw-r--r--chromium/components/content_creation/DIR_METADATA5
-rw-r--r--chromium/components/content_creation/OWNERS2
-rw-r--r--chromium/components/content_creation/README.md4
-rw-r--r--chromium/components/content_creation/notes/DEPS5
-rw-r--r--chromium/components/content_creation/notes/android/BUILD.gn53
-rw-r--r--chromium/components/content_creation/notes/android/note_service_bridge.cc66
-rw-r--r--chromium/components/content_creation/notes/android/note_service_bridge.h44
-rw-r--r--chromium/components/content_creation/notes/android/note_template_conversion_bridge.cc80
-rw-r--r--chromium/components/content_creation/notes/android/note_template_conversion_bridge.h24
-rw-r--r--chromium/components/content_creation/notes/core/BUILD.gn35
-rw-r--r--chromium/components/content_creation/notes/core/note_service.cc20
-rw-r--r--chromium/components/content_creation/notes/core/note_service.h37
-rw-r--r--chromium/components/content_creation/notes/core/note_service_unittest.cc47
-rw-r--r--chromium/components/content_creation/notes/core/templates/BUILD.gn22
-rw-r--r--chromium/components/content_creation/notes/core/templates/note_template.cc27
-rw-r--r--chromium/components/content_creation/notes/core/templates/note_template.h50
-rw-r--r--chromium/components/content_creation/notes/core/templates/template_constants.cc139
-rw-r--r--chromium/components/content_creation/notes/core/templates/template_constants.h37
-rw-r--r--chromium/components/content_creation/notes/core/templates/template_store.cc43
-rw-r--r--chromium/components/content_creation/notes/core/templates/template_store.h54
-rw-r--r--chromium/components/content_creation/notes/core/templates/template_store_unittest.cc62
-rw-r--r--chromium/components/content_creation/notes/core/templates/template_types.cc54
-rw-r--r--chromium/components/content_creation/notes/core/templates/template_types.h113
-rw-r--r--chromium/components/content_creation/notes/core/test/BUILD.gn17
-rw-r--r--chromium/components/content_creation_strings.grdp38
-rw-r--r--chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_BOLD.png.sha11
-rw-r--r--chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_CLASSIC.png.sha11
-rw-r--r--chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_DREAMY.png.sha11
-rw-r--r--chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRESH.png.sha11
-rw-r--r--chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRIENDLY.png.sha11
-rw-r--r--chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_GROOVY.png.sha11
-rw-r--r--chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_IMPACTFUL.png.sha11
-rw-r--r--chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_LOVELY.png.sha11
-rw-r--r--chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_MONOCHROME.png.sha11
-rw-r--r--chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_POWERFUL.png.sha11
-rw-r--r--chromium/components/content_settings/android/cookie_controls_bridge.h6
-rw-r--r--chromium/components/content_settings/browser/BUILD.gn1
-rw-r--r--chromium/components/content_settings/browser/DEPS1
-rw-r--r--chromium/components/content_settings/browser/page_specific_content_settings.cc116
-rw-r--r--chromium/components/content_settings/browser/page_specific_content_settings.h69
-rw-r--r--chromium/components/content_settings/browser/page_specific_content_settings_unittest.cc30
-rw-r--r--chromium/components/content_settings/common/DIR_METADATA4
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_default_provider.cc38
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_details.h2
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_info.cc8
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_observable_provider.h2
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_observer.h2
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h1
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_policy_provider.cc3
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_pref.cc12
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_provider.h1
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_provider_unittest.cc5
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_registry.cc33
-rw-r--r--chromium/components/content_settings/core/browser/content_settings_registry_unittest.cc13
-rw-r--r--chromium/components/content_settings/core/browser/host_content_settings_map.cc10
-rw-r--r--chromium/components/content_settings/core/browser/host_content_settings_map.h6
-rw-r--r--chromium/components/content_settings/core/browser/insecure_private_network_policy_handler.cc8
-rw-r--r--chromium/components/content_settings/core/browser/website_settings_registry.cc15
-rw-r--r--chromium/components/content_settings/core/browser/website_settings_registry_unittest.cc5
-rw-r--r--chromium/components/content_settings/core/common/content_settings.cc3
-rw-r--r--chromium/components/content_settings/core/common/content_settings_pattern.cc16
-rw-r--r--chromium/components/content_settings/core/common/content_settings_pattern_parser.cc10
-rw-r--r--chromium/components/content_settings/core/common/content_settings_types.h22
-rw-r--r--chromium/components/content_settings/core/common/content_settings_utils.cc5
-rw-r--r--chromium/components/content_settings/core/common/cookie_settings_base.cc2
-rw-r--r--chromium/components/content_settings/core/common/cookie_settings_base.h4
-rw-r--r--chromium/components/content_settings/renderer/content_settings_agent_impl.cc13
-rw-r--r--chromium/components/content_settings/renderer/content_settings_agent_impl.h9
-rw-r--r--chromium/components/contextual_search/core/browser/ctr_aggregator.h2
-rw-r--r--chromium/components/contextual_search/core/browser/weekly_activity_storage.h3
-rw-r--r--chromium/components/continuous_search/OWNERS2
-rw-r--r--chromium/components/continuous_search/browser/search_result_extractor_client_status.h1
-rw-r--r--chromium/components/continuous_search/common/title_validator.cc4
-rw-r--r--chromium/components/continuous_search/renderer/search_result_extractor_impl.cc3
-rw-r--r--chromium/components/crash/android/DIR_METADATA3
-rw-r--r--chromium/components/crash/content/browser/crash_metrics_reporter_android.cc2
-rw-r--r--chromium/components/crash/content/browser/error_reporting/DIR_METADATA3
-rw-r--r--chromium/components/crash/content/browser/error_reporting/javascript_error_report.h14
-rw-r--r--chromium/components/crash/content/browser/error_reporting/mock_crash_endpoint.h6
-rw-r--r--chromium/components/crash/core/DIR_METADATA3
-rw-r--r--chromium/components/crash/core/app/crashpad_mac.mm1
-rw-r--r--chromium/components/crash/core/browser/resources/crashes.js4
-rw-r--r--chromium/components/crash/core/common/crash_key_breakpad.cc2
-rw-r--r--chromium/components/crash/core/common/crash_key_breakpad_ios.mm2
-rw-r--r--chromium/components/cronet/android/BUILD.gn20
-rw-r--r--chromium/components/cronet/ios/test/BUILD.gn2
-rw-r--r--chromium/components/cronet/native/test/BUILD.gn2
-rw-r--r--chromium/components/cronet/test/BUILD.gn55
-rw-r--r--chromium/components/cronet/testing/BUILD.gn55
-rw-r--r--chromium/components/crx_file/crx_verifier.cc2
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc13
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h3
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h6
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.cc29
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h16
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc6
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc6
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h3
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h1
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.cc3
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc5
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h1
-rw-r--r--chromium/components/data_reduction_proxy/core/browser/db_data_owner.h6
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h5
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h3
-rw-r--r--chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc2
-rw-r--r--chromium/components/data_use_measurement/core/data_use.h1
-rw-r--r--chromium/components/data_use_measurement/core/data_use_measurement.h7
-rw-r--r--chromium/components/data_use_measurement/core/data_use_pref_names.h2
-rw-r--r--chromium/components/data_use_measurement/core/data_use_tracker_prefs.cc5
-rw-r--r--chromium/components/data_use_measurement/core/data_use_tracker_prefs_unittest.cc48
-rw-r--r--chromium/components/data_use_measurement/core/data_use_user_data.h3
-rw-r--r--chromium/components/desks_storage/OWNERS5
-rw-r--r--chromium/components/desks_storage/README.md3
-rw-r--r--chromium/components/device_event_log/device_event_log.h2
-rw-r--r--chromium/components/device_event_log/device_event_log_impl.cc54
-rw-r--r--chromium/components/digital_asset_links/digital_asset_links_handler.cc8
-rw-r--r--chromium/components/digital_asset_links/digital_asset_links_handler.h9
-rw-r--r--chromium/components/discardable_memory/client/client_discardable_shared_memory_manager.cc13
-rw-r--r--chromium/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc81
-rw-r--r--chromium/components/discardable_memory/common/discardable_shared_memory_heap.cc102
-rw-r--r--chromium/components/discardable_memory/common/discardable_shared_memory_heap.h38
-rw-r--r--chromium/components/discardable_memory/common/discardable_shared_memory_heap_perftest.cc2
-rw-r--r--chromium/components/discardable_memory/common/discardable_shared_memory_heap_unittest.cc67
-rw-r--r--chromium/components/dom_distiller/content/browser/distillability_driver.cc2
-rw-r--r--chromium/components/dom_distiller/content/browser/distillability_driver.h14
-rw-r--r--chromium/components/dom_distiller/content/browser/distillable_page_utils.cc2
-rw-r--r--chromium/components/dom_distiller/content/browser/distillable_page_utils.h4
-rw-r--r--chromium/components/dom_distiller/content/browser/test_distillability_observer.h2
-rw-r--r--chromium/components/dom_distiller/content/renderer/distillability_agent.cc2
-rw-r--r--chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.cc2
-rw-r--r--chromium/components/dom_distiller/content/renderer/distiller_js_render_frame_observer.h4
-rw-r--r--chromium/components/dom_distiller/core/distilled_content_store.h6
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_service.cc2
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_service.h1
-rw-r--r--chromium/components/dom_distiller/core/dom_distiller_service_android.h2
-rw-r--r--chromium/components/dom_distiller/core/viewer.cc4
-rw-r--r--chromium/components/dom_distiller/core/viewer_unittest.cc4
-rw-r--r--chromium/components/dom_distiller/ios/distiller_page_ios.mm3
-rw-r--r--chromium/components/dom_distiller/standalone/content_extractor_browsertest.cc2
-rw-r--r--chromium/components/domain_reliability/config.cc4
-rw-r--r--chromium/components/domain_reliability/config.h1
-rw-r--r--chromium/components/domain_reliability/dispatcher.h2
-rw-r--r--chromium/components/domain_reliability/google_configs.cc4
-rw-r--r--chromium/components/domain_reliability/monitor.h1
-rw-r--r--chromium/components/download/content/internal/context_menu_download.cc4
-rw-r--r--chromium/components/download/content/internal/download_driver_impl.cc6
-rw-r--r--chromium/components/download/content/internal/download_driver_impl.h2
-rw-r--r--chromium/components/download/content/internal/download_driver_impl_unittest.cc2
-rw-r--r--chromium/components/download/database/download_db.h2
-rw-r--r--chromium/components/download/database/download_db_conversions.cc2
-rw-r--r--chromium/components/download/database/download_db_conversions_unittest.cc8
-rw-r--r--chromium/components/download/database/download_db_entry.h4
-rw-r--r--chromium/components/download/database/download_db_impl.h2
-rw-r--r--chromium/components/download/database/download_info.h6
-rw-r--r--chromium/components/download/database/in_progress/in_progress_info.h4
-rw-r--r--chromium/components/download/internal/background_service/controller.h2
-rw-r--r--chromium/components/download/internal/background_service/controller_impl.cc32
-rw-r--r--chromium/components/download/internal/background_service/controller_impl.h6
-rw-r--r--chromium/components/download/internal/background_service/controller_impl_unittest.cc163
-rw-r--r--chromium/components/download/internal/background_service/download_blockage_status.h2
-rw-r--r--chromium/components/download/internal/background_service/download_driver.h4
-rw-r--r--chromium/components/download/internal/background_service/download_service_impl.cc10
-rw-r--r--chromium/components/download/internal/background_service/download_service_impl.h2
-rw-r--r--chromium/components/download/internal/background_service/download_service_impl_unittest.cc41
-rw-r--r--chromium/components/download/internal/background_service/download_store_unittest.cc4
-rw-r--r--chromium/components/download/internal/background_service/driver_entry.h4
-rw-r--r--chromium/components/download/internal/background_service/entry.h1
-rw-r--r--chromium/components/download/internal/background_service/entry_utils.h1
-rw-r--r--chromium/components/download/internal/background_service/file_monitor.h1
-rw-r--r--chromium/components/download/internal/background_service/file_monitor_impl.h1
-rw-r--r--chromium/components/download/internal/background_service/file_monitor_unittest.cc4
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download.cc5
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver.cc6
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver.h2
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc4
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_unittest.cc2
-rw-r--r--chromium/components/download/internal/background_service/log_source.h6
-rw-r--r--chromium/components/download/internal/background_service/logger_impl.cc12
-rw-r--r--chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc11
-rw-r--r--chromium/components/download/internal/background_service/startup_status.h8
-rw-r--r--chromium/components/download/internal/background_service/stats.h2
-rw-r--r--chromium/components/download/internal/common/download_create_info.cc1
-rw-r--r--chromium/components/download/internal/common/download_db_cache.cc16
-rw-r--r--chromium/components/download/internal/common/download_db_cache.h4
-rw-r--r--chromium/components/download/internal/common/download_file_impl.cc2
-rw-r--r--chromium/components/download/internal/common/download_file_unittest.cc3
-rw-r--r--chromium/components/download/internal/common/download_item_impl.cc45
-rw-r--r--chromium/components/download/internal/common/download_item_impl_delegate.cc2
-rw-r--r--chromium/components/download/internal/common/download_item_impl_unittest.cc56
-rw-r--r--chromium/components/download/internal/common/download_item_rename_handler.cc1
-rw-r--r--chromium/components/download/internal/common/download_ukm_helper.cc2
-rw-r--r--chromium/components/download/internal/common/download_utils.cc6
-rw-r--r--chromium/components/download/internal/common/download_worker.h2
-rw-r--r--chromium/components/download/internal/common/in_progress_download_manager.cc8
-rw-r--r--chromium/components/download/internal/common/resource_downloader.cc2
-rw-r--r--chromium/components/download/internal/common/resource_downloader.h2
-rw-r--r--chromium/components/download/public/background_service/basic_task_scheduler.h2
-rw-r--r--chromium/components/download/public/background_service/client.h1
-rw-r--r--chromium/components/download/public/background_service/download_metadata.h6
-rw-r--r--chromium/components/download/public/background_service/download_params.cc6
-rw-r--r--chromium/components/download/public/background_service/download_params.h6
-rw-r--r--chromium/components/download/public/background_service/download_service.h3
-rw-r--r--chromium/components/download/public/background_service/logger.h2
-rw-r--r--chromium/components/download/public/common/auto_resumption_handler.cc1
-rw-r--r--chromium/components/download/public/common/auto_resumption_handler_unittest.cc10
-rw-r--r--chromium/components/download/public/common/base_file.h2
-rw-r--r--chromium/components/download/public/common/download_content.h6
-rw-r--r--chromium/components/download/public/common/download_create_info.h8
-rw-r--r--chromium/components/download/public/common/download_danger_type.h4
-rw-r--r--chromium/components/download/public/common/download_features.cc2
-rw-r--r--chromium/components/download/public/common/download_item.h9
-rw-r--r--chromium/components/download/public/common/download_item_factory.h4
-rw-r--r--chromium/components/download/public/common/download_item_impl.h24
-rw-r--r--chromium/components/download/public/common/download_item_impl_delegate.h4
-rw-r--r--chromium/components/download/public/common/download_job.h1
-rw-r--r--chromium/components/download/public/common/download_response_handler.h4
-rw-r--r--chromium/components/download/public/common/download_schedule.cc2
-rw-r--r--chromium/components/download/public/common/download_schedule.h8
-rw-r--r--chromium/components/download/public/common/download_schedule_unittest.cc12
-rw-r--r--chromium/components/download/public/common/download_ukm_helper.h2
-rw-r--r--chromium/components/download/public/common/download_url_parameters.h12
-rw-r--r--chromium/components/download/public/common/download_utils.h2
-rw-r--r--chromium/components/download/public/common/in_progress_download_manager.h2
-rw-r--r--chromium/components/download/public/common/mock_download_item.h9
-rw-r--r--chromium/components/download/public/common/mock_download_item_impl.cc2
-rw-r--r--chromium/components/download/public/common/mock_download_item_impl.h6
-rw-r--r--chromium/components/embedder_support/BUILD.gn3
-rw-r--r--chromium/components/embedder_support/DEPS1
-rw-r--r--chromium/components/embedder_support/README5
-rw-r--r--chromium/components/embedder_support/android/contextmenu/context_menu_builder.cc2
-rw-r--r--chromium/components/embedder_support/android/delegate/color_chooser_android.h1
-rw-r--r--chromium/components/embedder_support/android/delegate/web_contents_delegate_android.cc6
-rw-r--r--chromium/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java29
-rw-r--r--chromium/components/embedder_support/android/util/android_stream_reader_url_loader.cc4
-rw-r--r--chromium/components/embedder_support/android/util/android_stream_reader_url_loader.h6
-rw-r--r--chromium/components/embedder_support/android/util/android_stream_reader_url_loader_unittest.cc6
-rw-r--r--chromium/components/embedder_support/android/util/url_utilities.cc69
-rw-r--r--chromium/components/embedder_support/content_settings_utils.cc52
-rw-r--r--chromium/components/embedder_support/content_settings_utils.h32
-rw-r--r--chromium/components/embedder_support/origin_trials/component_updater_utils.cc5
-rw-r--r--chromium/components/embedder_support/origin_trials/component_updater_utils_unittest.cc16
-rw-r--r--chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.cc5
-rw-r--r--chromium/components/embedder_support/user_agent_utils.cc11
-rw-r--r--chromium/components/embedder_support/user_agent_utils.h4
-rw-r--r--chromium/components/embedder_support/user_agent_utils_unittest.cc10
-rw-r--r--chromium/components/encrypted_messages/OWNERS1
-rw-r--r--chromium/components/enterprise/BUILD.gn7
-rw-r--r--chromium/components/enterprise/DEPS1
-rw-r--r--chromium/components/enterprise/browser/controller/browser_dm_token_storage.h2
-rw-r--r--chromium/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc19
-rw-r--r--chromium/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h18
-rw-r--r--chromium/components/enterprise/browser/enterprise_switches.cc2
-rw-r--r--chromium/components/enterprise/browser/enterprise_switches.h2
-rw-r--r--chromium/components/enterprise/browser/reporting/common_pref_names.cc4
-rw-r--r--chromium/components/enterprise/browser/reporting/common_pref_names.h2
-rw-r--r--chromium/components/enterprise/browser/reporting/policy_info.cc2
-rw-r--r--chromium/components/enterprise/browser/reporting/profile_report_generator.h3
-rw-r--r--chromium/components/enterprise/browser/reporting/real_time_report_generator.cc25
-rw-r--r--chromium/components/enterprise/browser/reporting/real_time_report_generator.h54
-rw-r--r--chromium/components/enterprise/browser/reporting/real_time_uploader.cc89
-rw-r--r--chromium/components/enterprise/browser/reporting/real_time_uploader.h39
-rw-r--r--chromium/components/enterprise/browser/reporting/real_time_uploader_unittest.cc123
-rw-r--r--chromium/components/enterprise/browser/reporting/report_request_queue_generator.h1
-rw-r--r--chromium/components/enterprise/browser/reporting/report_scheduler.cc59
-rw-r--r--chromium/components/enterprise/browser/reporting/report_scheduler.h29
-rw-r--r--chromium/components/enterprise/browser/reporting/reporting_delegate_factory.h4
-rw-r--r--chromium/components/enterprise/common/proto/BUILD.gn5
-rw-r--r--chromium/components/enterprise/common/proto/device_trust_report_event.proto39
-rw-r--r--chromium/components/enterprise/common/proto/extensions_workflow_events.proto2
-rw-r--r--chromium/components/error_page/common/alt_game_images.h1
-rw-r--r--chromium/components/error_page/common/localized_error.cc15
-rw-r--r--chromium/components/error_page/content/browser/net_error_auto_reloader.h8
-rw-r--r--chromium/components/error_page/content/browser/net_error_auto_reloader_browsertest.cc56
-rw-r--r--chromium/components/error_page_strings.grdp3
-rw-r--r--chromium/components/error_page_strings_grdp/IDS_ERRORPAGE_DINO_SLOW_SPEED_TOGGLE.png.sha11
-rw-r--r--chromium/components/exo/BUILD.gn8
-rw-r--r--chromium/components/exo/DEPS3
-rw-r--r--chromium/components/exo/OWNERS6
-rw-r--r--chromium/components/exo/buffer.cc1
-rw-r--r--chromium/components/exo/buffer_unittest.cc48
-rw-r--r--chromium/components/exo/client_controlled_shell_surface.cc47
-rw-r--r--chromium/components/exo/client_controlled_shell_surface.h12
-rw-r--r--chromium/components/exo/client_controlled_shell_surface_unittest.cc120
-rw-r--r--chromium/components/exo/data_device.cc8
-rw-r--r--chromium/components/exo/data_device.h2
-rw-r--r--chromium/components/exo/data_device_delegate.h3
-rw-r--r--chromium/components/exo/data_device_unittest.cc2
-rw-r--r--chromium/components/exo/data_exchange_delegate.h12
-rw-r--r--chromium/components/exo/data_offer.cc48
-rw-r--r--chromium/components/exo/data_offer_observer.h2
-rw-r--r--chromium/components/exo/data_source.cc48
-rw-r--r--chromium/components/exo/data_source.h31
-rw-r--r--chromium/components/exo/data_source_delegate.h2
-rw-r--r--chromium/components/exo/data_source_observer.h2
-rw-r--r--chromium/components/exo/data_source_unittest.cc169
-rw-r--r--chromium/components/exo/display.cc35
-rw-r--r--chromium/components/exo/display.h12
-rw-r--r--chromium/components/exo/display_unittest.cc85
-rw-r--r--chromium/components/exo/drag_drop_operation.cc37
-rw-r--r--chromium/components/exo/drag_drop_operation.h3
-rw-r--r--chromium/components/exo/drag_drop_operation_unittest.cc4
-rw-r--r--chromium/components/exo/extended_drag_source.cc16
-rw-r--r--chromium/components/exo/extended_drag_source.h6
-rw-r--r--chromium/components/exo/extended_drag_source_unittest.cc2
-rw-r--r--chromium/components/exo/fullscreen_shell_surface.cc6
-rw-r--r--chromium/components/exo/fullscreen_shell_surface.h6
-rw-r--r--chromium/components/exo/fullscreen_shell_surface_unittest.cc2
-rw-r--r--chromium/components/exo/gaming_seat_unittest.cc3
-rw-r--r--chromium/components/exo/keyboard.cc5
-rw-r--r--chromium/components/exo/keyboard_device_configuration_delegate.h6
-rw-r--r--chromium/components/exo/layer_tree_frame_sink_holder.cc8
-rw-r--r--chromium/components/exo/layer_tree_frame_sink_holder.h5
-rw-r--r--chromium/components/exo/notification.cc10
-rw-r--r--chromium/components/exo/notification.h4
-rw-r--r--chromium/components/exo/notification_surface.cc3
-rw-r--r--chromium/components/exo/notification_unittest.cc8
-rw-r--r--chromium/components/exo/pointer.cc23
-rw-r--r--chromium/components/exo/pointer.h8
-rw-r--r--chromium/components/exo/pointer_unittest.cc2
-rw-r--r--chromium/components/exo/seat.cc62
-rw-r--r--chromium/components/exo/seat.h16
-rw-r--r--chromium/components/exo/seat_unittest.cc13
-rw-r--r--chromium/components/exo/shell_surface.cc6
-rw-r--r--chromium/components/exo/shell_surface.h2
-rw-r--r--chromium/components/exo/shell_surface_base.cc138
-rw-r--r--chromium/components/exo/shell_surface_base.h30
-rw-r--r--chromium/components/exo/shell_surface_unittest.cc74
-rw-r--r--chromium/components/exo/shell_surface_util.cc71
-rw-r--r--chromium/components/exo/shell_surface_util.h35
-rw-r--r--chromium/components/exo/shell_surface_util_unittest.cc107
-rw-r--r--chromium/components/exo/sub_surface.h2
-rw-r--r--chromium/components/exo/surface.cc36
-rw-r--r--chromium/components/exo/surface.h13
-rw-r--r--chromium/components/exo/surface_delegate.h10
-rw-r--r--chromium/components/exo/surface_tree_host.cc7
-rw-r--r--chromium/components/exo/surface_tree_host.h2
-rw-r--r--chromium/components/exo/surface_unittest.cc3
-rw-r--r--chromium/components/exo/text_input.cc32
-rw-r--r--chromium/components/exo/text_input.h15
-rw-r--r--chromium/components/exo/text_input_unittest.cc47
-rw-r--r--chromium/components/exo/touch.cc7
-rw-r--r--chromium/components/exo/touch_unittest.cc2
-rw-r--r--chromium/components/exo/ui_lock_bubble.cc69
-rw-r--r--chromium/components/exo/ui_lock_bubble.h34
-rw-r--r--chromium/components/exo/ui_lock_controller.cc216
-rw-r--r--chromium/components/exo/ui_lock_controller.h5
-rw-r--r--chromium/components/exo/ui_lock_controller_unittest.cc195
-rw-r--r--chromium/components/exo/wayland/clients/client_base.cc8
-rw-r--r--chromium/components/exo/wayland/clients/client_helper.h2
-rw-r--r--chromium/components/exo/wayland/clients/explicit_synchronization.cc6
-rw-r--r--chromium/components/exo/wayland/clients/fullscreen_shell.cc1
-rw-r--r--chromium/components/exo/wayland/clients/rects.cc6
-rw-r--r--chromium/components/exo/wayland/compatibility_test/template_client_event_receiver_version_tests.cc.tmpl8
-rw-r--r--chromium/components/exo/wayland/compatibility_test/wayland_client_event_recorder.h6
-rw-r--r--chromium/components/exo/wayland/compatibility_test/wayland_client_registry.cc2
-rw-r--r--chromium/components/exo/wayland/compatibility_test/wayland_client_registry.h4
-rw-r--r--chromium/components/exo/wayland/fuzzer/wayland_templater.gni6
-rw-r--r--chromium/components/exo/wayland/protocol/aura-shell.xml21
-rw-r--r--chromium/components/exo/wayland/serial_tracker.cc18
-rw-r--r--chromium/components/exo/wayland/serial_tracker.h14
-rw-r--r--chromium/components/exo/wayland/server.cc11
-rw-r--r--chromium/components/exo/wayland/server.h2
-rw-r--r--chromium/components/exo/wayland/wayland_display_observer.cc5
-rw-r--r--chromium/components/exo/wayland/wayland_display_observer.h1
-rw-r--r--chromium/components/exo/wayland/wayland_keyboard_delegate.cc1
-rw-r--r--chromium/components/exo/wayland/wl_data_device_manager.cc10
-rw-r--r--chromium/components/exo/wayland/zaura_shell.cc26
-rw-r--r--chromium/components/exo/wayland/zaura_shell.h4
-rw-r--r--chromium/components/exo/wayland/zaura_shell_unittest.cc7
-rw-r--r--chromium/components/exo/wayland/zcr_notification_shell.cc5
-rw-r--r--chromium/components/exo/wayland/zcr_remote_shell.cc129
-rw-r--r--chromium/components/exo/wayland/zcr_remote_shell.h23
-rw-r--r--chromium/components/exo/wayland/zwp_text_input_manager.cc3
-rw-r--r--chromium/components/exo/wm_helper.h5
-rw-r--r--chromium/components/exo/wm_helper_chromeos.cc11
-rw-r--r--chromium/components/exo/wm_helper_chromeos.h2
-rw-r--r--chromium/components/exo/wm_helper_chromeos_unittest.cc7
-rw-r--r--chromium/components/exo/xdg_shell_surface.h4
-rw-r--r--chromium/components/exo/xkb_tracker.h2
-rw-r--r--chromium/components/external_intents/android/BUILD.gn12
-rw-r--r--chromium/components/external_intents/android/external_intents_features.cc (renamed from chromium/components/external_intents/android/external_intents_feature_list.cc)25
-rw-r--r--chromium/components/external_intents/android/external_intents_features.h (renamed from chromium/components/external_intents/android/external_intents_feature_list.h)6
-rw-r--r--chromium/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java373
-rw-r--r--chromium/components/favicon/android/large_icon_bridge.h2
-rw-r--r--chromium/components/favicon/content/content_favicon_driver.cc90
-rw-r--r--chromium/components/favicon/content/content_favicon_driver.h40
-rw-r--r--chromium/components/favicon/content/content_favicon_driver_unittest.cc67
-rw-r--r--chromium/components/favicon/content/favicon_url_util.cc10
-rw-r--r--chromium/components/favicon/content/favicon_url_util.h6
-rw-r--r--chromium/components/favicon/core/favicon_backend.cc2
-rw-r--r--chromium/components/favicon/core/favicon_database.cc8
-rw-r--r--chromium/components/favicon/core/favicon_database.h4
-rw-r--r--chromium/components/favicon/core/favicon_database_unittest.cc5
-rw-r--r--chromium/components/favicon/core/favicon_driver.h2
-rw-r--r--chromium/components/favicon/core/favicon_handler.cc21
-rw-r--r--chromium/components/favicon/core/favicon_handler.h5
-rw-r--r--chromium/components/favicon/core/favicon_url.h6
-rw-r--r--chromium/components/favicon/core/history_ui_favicon_request_handler_impl.cc24
-rw-r--r--chromium/components/favicon/core/history_ui_favicon_request_handler_impl.h3
-rw-r--r--chromium/components/favicon/core/large_icon_service.h2
-rw-r--r--chromium/components/feature_engagement/README.md19
-rw-r--r--chromium/components/feature_engagement/internal/availability_model.h4
-rw-r--r--chromium/components/feature_engagement/internal/availability_model_impl.cc4
-rw-r--r--chromium/components/feature_engagement/internal/availability_model_impl.h2
-rw-r--r--chromium/components/feature_engagement/internal/availability_model_impl_unittest.cc16
-rw-r--r--chromium/components/feature_engagement/internal/chrome_variations_configuration.cc34
-rw-r--r--chromium/components/feature_engagement/internal/chrome_variations_configuration_unittest.cc87
-rw-r--r--chromium/components/feature_engagement/internal/event_store.h6
-rw-r--r--chromium/components/feature_engagement/internal/feature_config_condition_validator.cc2
-rw-r--r--chromium/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc8
-rw-r--r--chromium/components/feature_engagement/internal/init_aware_event_model_unittest.cc4
-rw-r--r--chromium/components/feature_engagement/internal/never_availability_model.cc6
-rw-r--r--chromium/components/feature_engagement/internal/never_availability_model.h2
-rw-r--r--chromium/components/feature_engagement/internal/never_availability_model_unittest.cc12
-rw-r--r--chromium/components/feature_engagement/internal/persistent_availability_store_unittest.cc4
-rw-r--r--chromium/components/feature_engagement/internal/persistent_event_store_unittest.cc4
-rw-r--r--chromium/components/feature_engagement/internal/tracker_impl_unittest.cc4
-rw-r--r--chromium/components/feature_engagement/public/BUILD.gn1
-rw-r--r--chromium/components/feature_engagement/public/configuration.cc2
-rw-r--r--chromium/components/feature_engagement/public/configuration.h4
-rw-r--r--chromium/components/feature_engagement/public/event_constants.cc4
-rw-r--r--chromium/components/feature_engagement/public/event_constants.h3
-rw-r--r--chromium/components/feature_engagement/public/feature_configurations.cc57
-rw-r--r--chromium/components/feature_engagement/public/feature_configurations.h4
-rw-r--r--chromium/components/feature_engagement/public/feature_constants.cc24
-rw-r--r--chromium/components/feature_engagement/public/feature_constants.h10
-rw-r--r--chromium/components/feature_engagement/public/feature_list.cc7
-rw-r--r--chromium/components/feature_engagement/public/feature_list.h28
-rw-r--r--chromium/components/federated_learning/features/features.cc6
-rw-r--r--chromium/components/federated_learning/features/features.h4
-rw-r--r--chromium/components/federated_learning/floc_id.cc10
-rw-r--r--chromium/components/federated_learning/floc_id.h12
-rw-r--r--chromium/components/federated_learning/floc_id_unittest.cc13
-rw-r--r--chromium/components/federated_learning/floc_sorting_lsh_clusters_service.cc16
-rw-r--r--chromium/components/federated_learning/floc_sorting_lsh_clusters_service.h6
-rw-r--r--chromium/components/federated_learning/floc_sorting_lsh_clusters_service_unittest.cc50
-rw-r--r--chromium/components/feed/DEPS1
-rw-r--r--chromium/components/feed/content/renderer/BUILD.gn11
-rw-r--r--chromium/components/feed/content/renderer/DEPS7
-rw-r--r--chromium/components/feed/content/renderer/rss_link_reader.cc81
-rw-r--r--chromium/components/feed/content/renderer/rss_link_reader.h40
-rw-r--r--chromium/components/feed/core/common/pref_names.cc21
-rw-r--r--chromium/components/feed/core/common/pref_names.h12
-rw-r--r--chromium/components/feed/core/proto/BUILD.gn3
-rw-r--r--chromium/components/feed/core/proto/v2/store.proto16
-rw-r--r--chromium/components/feed/core/proto/v2/ui.proto6
-rw-r--r--chromium/components/feed/core/proto/v2/wire/capability.proto2
-rw-r--r--chromium/components/feed/core/proto/v2/wire/color.proto18
-rw-r--r--chromium/components/feed/core/proto/v2/wire/feed_query.proto7
-rw-r--r--chromium/components/feed/core/proto/v2/wire/token.proto2
-rw-r--r--chromium/components/feed/core/proto/v2/wire/web_feed_token.proto (renamed from chromium/components/feed/core/proto/v2/wire/wrappers.proto)8
-rw-r--r--chromium/components/feed/core/v2/BUILD.gn53
-rw-r--r--chromium/components/feed/core/v2/api_test/feed_api_notice_card_unittest.cc2
-rw-r--r--chromium/components/feed/core/v2/api_test/feed_api_offline_pages_unittest.cc205
-rw-r--r--chromium/components/feed/core/v2/api_test/feed_api_stream_unittest.cc363
-rw-r--r--chromium/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc95
-rw-r--r--chromium/components/feed/core/v2/api_test/feed_api_test.cc225
-rw-r--r--chromium/components/feed/core/v2/api_test/feed_api_test.h113
-rw-r--r--chromium/components/feed/core/v2/common_enums.h4
-rw-r--r--chromium/components/feed/core/v2/config.cc22
-rw-r--r--chromium/components/feed/core/v2/config.h16
-rw-r--r--chromium/components/feed/core/v2/enums.cc2
-rw-r--r--chromium/components/feed/core/v2/enums.h7
-rw-r--r--chromium/components/feed/core/v2/feed_network.h79
-rw-r--r--chromium/components/feed/core/v2/feed_network_impl.cc43
-rw-r--r--chromium/components/feed/core/v2/feed_network_impl.h7
-rw-r--r--chromium/components/feed/core/v2/feed_network_impl_unittest.cc60
-rw-r--r--chromium/components/feed/core/v2/feed_store.cc51
-rw-r--r--chromium/components/feed/core/v2/feed_store.h14
-rw-r--r--chromium/components/feed/core/v2/feed_store_unittest.cc22
-rw-r--r--chromium/components/feed/core/v2/feed_stream.cc223
-rw-r--r--chromium/components/feed/core/v2/feed_stream.h49
-rw-r--r--chromium/components/feed/core/v2/feedstore_util.cc68
-rw-r--r--chromium/components/feed/core/v2/feedstore_util.h28
-rw-r--r--chromium/components/feed/core/v2/feedstore_util_unittest.cc6
-rw-r--r--chromium/components/feed/core/v2/image_fetcher.cc10
-rw-r--r--chromium/components/feed/core/v2/image_fetcher.h4
-rw-r--r--chromium/components/feed/core/v2/metrics_reporter.cc29
-rw-r--r--chromium/components/feed/core/v2/metrics_reporter.h8
-rw-r--r--chromium/components/feed/core/v2/notice_card_tracker.cc44
-rw-r--r--chromium/components/feed/core/v2/notice_card_tracker.h17
-rw-r--r--chromium/components/feed/core/v2/notice_card_tracker_unittest.cc3
-rw-r--r--chromium/components/feed/core/v2/offline_page_spy.cc172
-rw-r--r--chromium/components/feed/core/v2/offline_page_spy.h81
-rw-r--r--chromium/components/feed/core/v2/persistent_key_value_store_impl.h2
-rw-r--r--chromium/components/feed/core/v2/prefs.cc38
-rw-r--r--chromium/components/feed/core/v2/prefs.h18
-rw-r--r--chromium/components/feed/core/v2/proto_util.cc31
-rw-r--r--chromium/components/feed/core/v2/proto_util.h3
-rw-r--r--chromium/components/feed/core/v2/proto_util_unittest.cc33
-rw-r--r--chromium/components/feed/core/v2/protocol_translator.cc47
-rw-r--r--chromium/components/feed/core/v2/protocol_translator.h11
-rw-r--r--chromium/components/feed/core/v2/protocol_translator_unittest.cc14
-rw-r--r--chromium/components/feed/core/v2/public/feed_api.cc48
-rw-r--r--chromium/components/feed/core/v2/public/feed_api.h110
-rw-r--r--chromium/components/feed/core/v2/public/feed_service.cc59
-rw-r--r--chromium/components/feed/core/v2/public/feed_service.h20
-rw-r--r--chromium/components/feed/core/v2/public/feed_stream_surface.cc21
-rw-r--r--chromium/components/feed/core/v2/public/feed_stream_surface.h46
-rw-r--r--chromium/components/feed/core/v2/public/persistent_key_value_store.h4
-rw-r--r--chromium/components/feed/core/v2/public/stream_type.cc42
-rw-r--r--chromium/components/feed/core/v2/public/stream_type.h59
-rw-r--r--chromium/components/feed/core/v2/public/types.cc36
-rw-r--r--chromium/components/feed/core/v2/public/types.h28
-rw-r--r--chromium/components/feed/core/v2/public/types_unittest.cc12
-rw-r--r--chromium/components/feed/core/v2/public/unread_content_observer.cc12
-rw-r--r--chromium/components/feed/core/v2/public/unread_content_observer.h34
-rw-r--r--chromium/components/feed/core/v2/public/web_feed_subscriptions.h15
-rw-r--r--chromium/components/feed/core/v2/request_throttler.cc4
-rw-r--r--chromium/components/feed/core/v2/scheduling.cc18
-rw-r--r--chromium/components/feed/core/v2/scheduling.h9
-rw-r--r--chromium/components/feed/core/v2/stream/unread_content_notifier.h3
-rw-r--r--chromium/components/feed/core/v2/stream/upload_criteria.cc1
-rw-r--r--chromium/components/feed/core/v2/stream_model.cc3
-rw-r--r--chromium/components/feed/core/v2/stream_model.h6
-rw-r--r--chromium/components/feed/core/v2/stream_model_unittest.cc14
-rw-r--r--chromium/components/feed/core/v2/surface_updater.cc8
-rw-r--r--chromium/components/feed/core/v2/surface_updater.h2
-rw-r--r--chromium/components/feed/core/v2/tasks/get_prefetch_suggestions_task.cc111
-rw-r--r--chromium/components/feed/core/v2/tasks/get_prefetch_suggestions_task.h57
-rw-r--r--chromium/components/feed/core/v2/tasks/load_more_task.cc54
-rw-r--r--chromium/components/feed/core/v2/tasks/load_more_task.h7
-rw-r--r--chromium/components/feed/core/v2/tasks/load_stream_from_store_task.cc24
-rw-r--r--chromium/components/feed/core/v2/tasks/load_stream_from_store_task.h21
-rw-r--r--chromium/components/feed/core/v2/tasks/load_stream_task.cc173
-rw-r--r--chromium/components/feed/core/v2/tasks/load_stream_task.h44
-rw-r--r--chromium/components/feed/core/v2/tasks/prefetch_images_task.cc2
-rw-r--r--chromium/components/feed/core/v2/tasks/upload_actions_task.h8
-rw-r--r--chromium/components/feed/core/v2/tasks/wait_for_store_initialize_task.cc44
-rw-r--r--chromium/components/feed/core/v2/tasks/wait_for_store_initialize_task.h7
-rw-r--r--chromium/components/feed/core/v2/types.cc36
-rw-r--r--chromium/components/feed/core/v2/types.h30
-rw-r--r--chromium/components/feed/core/v2/types_unittest.cc10
-rw-r--r--chromium/components/feed/core/v2/web_feed_subscription_coordinator.cc92
-rw-r--r--chromium/components/feed/core/v2/web_feed_subscription_coordinator.h20
-rw-r--r--chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index.cc457
-rw-r--r--chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index.h36
-rw-r--r--chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index_unittest.cc346
-rw-r--r--chromium/components/feed/feed_feature_list.cc2
-rw-r--r--chromium/components/feed/feed_feature_list.h3
-rw-r--r--chromium/components/feed/mojom/BUILD.gn18
-rw-r--r--chromium/components/feed/mojom/rss_link_reader.mojom19
-rw-r--r--chromium/components/feedback/BUILD.gn3
-rw-r--r--chromium/components/feedback/content/content_tracing_manager.cc1
-rw-r--r--chromium/components/feedback/content/content_tracing_manager.h1
-rw-r--r--chromium/components/feedback/content/feedback_uploader_factory.cc2
-rw-r--r--chromium/components/feedback/redaction_tool.cc12
-rw-r--r--chromium/components/feedback/redaction_tool.h9
-rw-r--r--chromium/components/find_in_page/android/DIR_METADATA3
-rw-r--r--chromium/components/flags_ui/flags_state.cc8
-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/flags_ui_metrics.h2
-rw-r--r--chromium/components/flags_ui/pref_service_flags_storage.cc5
-rw-r--r--chromium/components/flags_ui/resources/BUILD.gn7
-rw-r--r--chromium/components/flags_ui/resources/flags.css6
-rw-r--r--chromium/components/flags_ui/resources/flags.html11
-rw-r--r--chromium/components/flags_ui/resources/flags.js23
-rw-r--r--chromium/components/full_restore/app_launch_info.h20
-rw-r--r--chromium/components/full_restore/app_restore_data.cc140
-rw-r--r--chromium/components/full_restore/app_restore_data.h38
-rw-r--r--chromium/components/full_restore/arc_read_handler.cc23
-rw-r--r--chromium/components/full_restore/arc_save_handler.cc13
-rw-r--r--chromium/components/full_restore/arc_save_handler.h5
-rw-r--r--chromium/components/full_restore/full_restore_info.cc27
-rw-r--r--chromium/components/full_restore/full_restore_info.h37
-rw-r--r--chromium/components/full_restore/full_restore_info_unittest.cc78
-rw-r--r--chromium/components/full_restore/full_restore_read_and_save_unittest.cc10
-rw-r--r--chromium/components/full_restore/full_restore_read_handler.cc31
-rw-r--r--chromium/components/full_restore/full_restore_read_handler.h17
-rw-r--r--chromium/components/full_restore/full_restore_save_handler.cc28
-rw-r--r--chromium/components/full_restore/full_restore_save_handler.h13
-rw-r--r--chromium/components/full_restore/full_restore_utils.cc20
-rw-r--r--chromium/components/full_restore/full_restore_utils.h30
-rw-r--r--chromium/components/full_restore/restore_data.cc9
-rw-r--r--chromium/components/full_restore/restore_data.h7
-rw-r--r--chromium/components/full_restore/restore_data_unittest.cc73
-rw-r--r--chromium/components/full_restore/window_info.cc19
-rw-r--r--chromium/components/full_restore/window_info.h30
-rw-r--r--chromium/components/fullscreen_control/BUILD.gn46
-rw-r--r--chromium/components/fullscreen_control/DEPS8
-rw-r--r--chromium/components/fullscreen_control/DIR_METADATA3
-rw-r--r--chromium/components/fullscreen_control/OWNERS2
-rw-r--r--chromium/components/fullscreen_control/README.md7
-rw-r--r--chromium/components/fullscreen_control/fullscreen_control_popup.cc149
-rw-r--r--chromium/components/fullscreen_control/fullscreen_control_popup.h82
-rw-r--r--chromium/components/fullscreen_control/fullscreen_control_popup_unittest.cc122
-rw-r--r--chromium/components/fullscreen_control/fullscreen_control_view.cc82
-rw-r--r--chromium/components/fullscreen_control/fullscreen_control_view.h35
-rw-r--r--chromium/components/fullscreen_control/fullscreen_control_view_unittest.cc16
-rw-r--r--chromium/components/fullscreen_control/subtle_notification_view.cc212
-rw-r--r--chromium/components/fullscreen_control/subtle_notification_view.h51
-rw-r--r--chromium/components/fullscreen_control_strings.grdp9
-rw-r--r--chromium/components/fullscreen_control_strings_grdp/DIR_METADATA3
-rw-r--r--chromium/components/fullscreen_control_strings_grdp/IDS_EXIT_FULLSCREEN_MODE.png.sha11
-rw-r--r--chromium/components/fullscreen_control_strings_grdp/IDS_FULLSCREEN_HOLD_ESC_TO_EXIT_FULLSCREEN.png.sha11
-rw-r--r--chromium/components/fullscreen_control_strings_grdp/OWNERS1
-rw-r--r--chromium/components/fullscreen_control_strings_grdp/README.md5
-rw-r--r--chromium/components/gcm_driver/BUILD.gn4
-rw-r--r--chromium/components/google/core/common/google_util.cc7
-rw-r--r--chromium/components/guest_os/guest_os_engagement_metrics.cc62
-rw-r--r--chromium/components/guest_os/guest_os_engagement_metrics.h18
-rw-r--r--chromium/components/guest_os/guest_os_engagement_metrics_unittest.cc40
-rw-r--r--chromium/components/guest_view/browser/guest_view_base.cc18
-rw-r--r--chromium/components/guest_view/browser/guest_view_base.h4
-rw-r--r--chromium/components/guest_view/browser/guest_view_manager.cc16
-rw-r--r--chromium/components/guest_view/browser/guest_view_manager.h3
-rw-r--r--chromium/components/guest_view/common/DIR_METADATA3
-rw-r--r--chromium/components/guest_view/common/guest_view_messages.h1
-rw-r--r--chromium/components/guest_view/renderer/guest_view_container.h1
-rw-r--r--chromium/components/guest_view/renderer/guest_view_container_dispatcher.cc1
-rw-r--r--chromium/components/guest_view/renderer/guest_view_request.h2
-rw-r--r--chromium/components/guest_view/renderer/iframe_guest_view_request.h1
-rw-r--r--chromium/components/gwp_asan/client/guarded_page_allocator.cc2
-rw-r--r--chromium/components/gwp_asan/client/guarded_page_allocator_unittest.cc2
-rw-r--r--chromium/components/gwp_asan/client/gwp_asan.cc17
-rw-r--r--chromium/components/gwp_asan/client/gwp_asan_unittest.cc4
-rw-r--r--chromium/components/gwp_asan/client/sampling_malloc_shims_unittest.cc2
-rw-r--r--chromium/components/gwp_asan/client/sampling_partitionalloc_shims_unittest.cc2
-rw-r--r--chromium/components/gwp_asan/common/allocator_state.cc2
-rw-r--r--chromium/components/gwp_asan/common/allocator_state_unittest.cc2
-rw-r--r--chromium/components/gwp_asan/crash_handler/crash_handler_unittest.cc2
-rw-r--r--chromium/components/heap_profiling/in_process/heap_profiler_controller.cc41
-rw-r--r--chromium/components/heap_profiling/in_process/heap_profiler_controller.h27
-rw-r--r--chromium/components/heap_profiling/in_process/heap_profiler_controller_unittest.cc24
-rw-r--r--chromium/components/heap_profiling/multi_process/client_connection_manager.cc53
-rw-r--r--chromium/components/heap_profiling/multi_process/supervisor.cc7
-rw-r--r--chromium/components/heavy_ad_intervention/heavy_ad_service.h1
-rw-r--r--chromium/components/history/content/browser/download_conversions.cc5
-rw-r--r--chromium/components/history/content/browser/download_conversions.h2
-rw-r--r--chromium/components/history/content/browser/history_database_helper.h2
-rw-r--r--chromium/components/history/core/browser/BUILD.gn1
-rw-r--r--chromium/components/history/core/browser/android/android_cache_database.h14
-rw-r--r--chromium/components/history/core/browser/android/android_history_types.h4
-rw-r--r--chromium/components/history/core/browser/android/android_urls_database.h12
-rw-r--r--chromium/components/history/core/browser/android/sql_handler.h20
-rw-r--r--chromium/components/history/core/browser/android/visit_sql_handler.cc2
-rw-r--r--chromium/components/history/core/browser/android/visit_sql_handler.h8
-rw-r--r--chromium/components/history/core/browser/browsing_history_driver.h2
-rw-r--r--chromium/components/history/core/browser/browsing_history_service.cc12
-rw-r--r--chromium/components/history/core/browser/browsing_history_service.h12
-rw-r--r--chromium/components/history/core/browser/browsing_history_service_unittest.cc11
-rw-r--r--chromium/components/history/core/browser/download_constants.h3
-rw-r--r--chromium/components/history/core/browser/download_database.cc10
-rw-r--r--chromium/components/history/core/browser/download_database.h12
-rw-r--r--chromium/components/history/core/browser/download_row.h2
-rw-r--r--chromium/components/history/core/browser/download_slice_info.h1
-rw-r--r--chromium/components/history/core/browser/download_types.cc4
-rw-r--r--chromium/components/history/core/browser/expire_history_backend.cc80
-rw-r--r--chromium/components/history/core/browser/expire_history_backend.h24
-rw-r--r--chromium/components/history/core/browser/expire_history_backend_unittest.cc68
-rw-r--r--chromium/components/history/core/browser/history_backend.cc170
-rw-r--r--chromium/components/history/core/browser/history_backend.h189
-rw-r--r--chromium/components/history/core/browser/history_backend_client.h2
-rw-r--r--chromium/components/history/core/browser/history_backend_db_unittest.cc60
-rw-r--r--chromium/components/history/core/browser/history_backend_notifier.h10
-rw-r--r--chromium/components/history/core/browser/history_backend_observer.h22
-rw-r--r--chromium/components/history/core/browser/history_backend_unittest.cc525
-rw-r--r--chromium/components/history/core/browser/history_database.cc22
-rw-r--r--chromium/components/history/core/browser/history_database.h8
-rw-r--r--chromium/components/history/core/browser/history_querying_unittest.cc12
-rw-r--r--chromium/components/history/core/browser/history_service.cc36
-rw-r--r--chromium/components/history/core/browser/history_service.h210
-rw-r--r--chromium/components/history/core/browser/history_service_observer.h22
-rw-r--r--chromium/components/history/core/browser/history_service_unittest.cc74
-rw-r--r--chromium/components/history/core/browser/history_types.cc73
-rw-r--r--chromium/components/history/core/browser/history_types.h166
-rw-r--r--chromium/components/history/core/browser/in_memory_database.cc2
-rw-r--r--chromium/components/history/core/browser/in_memory_history_backend.h4
-rw-r--r--chromium/components/history/core/browser/keyword_search_term.h4
-rw-r--r--chromium/components/history/core/browser/sync/delete_directive_handler.cc21
-rw-r--r--chromium/components/history/core/browser/sync/delete_directive_handler.h16
-rw-r--r--chromium/components/history/core/browser/sync/delete_directive_handler_unittest.cc26
-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/typed_url_sync_bridge.cc27
-rw-r--r--chromium/components/history/core/browser/sync/typed_url_sync_bridge.h50
-rw-r--r--chromium/components/history/core/browser/sync/typed_url_sync_bridge_unittest.cc26
-rw-r--r--chromium/components/history/core/browser/sync/typed_url_sync_metadata_database.cc6
-rw-r--r--chromium/components/history/core/browser/sync/typed_url_sync_metadata_database.h8
-rw-r--r--chromium/components/history/core/browser/top_sites.h2
-rw-r--r--chromium/components/history/core/browser/top_sites_database.cc4
-rw-r--r--chromium/components/history/core/browser/top_sites_database.h7
-rw-r--r--chromium/components/history/core/browser/top_sites_impl.cc11
-rw-r--r--chromium/components/history/core/browser/top_sites_impl.h19
-rw-r--r--chromium/components/history/core/browser/top_sites_impl_unittest.cc8
-rw-r--r--chromium/components/history/core/browser/url_database.cc26
-rw-r--r--chromium/components/history/core/browser/url_database.h50
-rw-r--r--chromium/components/history/core/browser/url_database_unittest.cc10
-rw-r--r--chromium/components/history/core/browser/url_utils.cc12
-rw-r--r--chromium/components/history/core/browser/url_utils.h24
-rw-r--r--chromium/components/history/core/browser/visit_annotations_database.cc223
-rw-r--r--chromium/components/history/core/browser/visit_annotations_database.h63
-rw-r--r--chromium/components/history/core/browser/visit_annotations_database_unittest.cc82
-rw-r--r--chromium/components/history/core/browser/visit_database.cc10
-rw-r--r--chromium/components/history/core/browser/visit_database.h42
-rw-r--r--chromium/components/history/core/browser/visit_database_unittest.cc14
-rw-r--r--chromium/components/history/core/browser/visitsegment_database.cc6
-rw-r--r--chromium/components/history/core/browser/visitsegment_database.h16
-rw-r--r--chromium/components/history/core/browser/web_history_service.cc18
-rw-r--r--chromium/components/history/core/browser/web_history_service.h30
-rw-r--r--chromium/components/history/core/browser/web_history_service_unittest.cc2
-rw-r--r--chromium/components/history/core/common/thumbnail_score.h6
-rw-r--r--chromium/components/history/ios/OWNERS0
-rw-r--r--chromium/components/history/ios/browser/history_database_helper.h2
-rw-r--r--chromium/components/history/metrics/domain_diversity_reporter.cc8
-rw-r--r--chromium/components/history/metrics/domain_diversity_reporter.h6
-rw-r--r--chromium/components/history/metrics/domain_diversity_reporter_unittest.cc6
-rw-r--r--chromium/components/history_clusters/core/BUILD.gn19
-rw-r--r--chromium/components/history_clusters/core/DEPS2
-rw-r--r--chromium/components/history_clusters/core/history_clusters_service.cc233
-rw-r--r--chromium/components/history_clusters/core/history_clusters_service.h132
-rw-r--r--chromium/components/history_clusters/core/history_clusters_service_test_api.h30
-rw-r--r--chromium/components/history_clusters/core/history_clusters_service_unittest.cc754
-rw-r--r--chromium/components/history_clusters/core/memories.mojom51
-rw-r--r--chromium/components/history_clusters/core/memories_features.cc35
-rw-r--r--chromium/components/history_clusters/core/memories_features.h50
-rw-r--r--chromium/components/history_clusters/core/memories_remote_model_helper.cc279
-rw-r--r--chromium/components/history_clusters/core/memories_remote_model_helper.h43
-rw-r--r--chromium/components/history_clusters/core/memories_service.cc61
-rw-r--r--chromium/components/history_clusters/core/memories_service.h72
-rw-r--r--chromium/components/history_clusters/core/memories_service_test_api.h29
-rw-r--r--chromium/components/history_clusters/core/memories_service_unittest.cc474
-rw-r--r--chromium/components/history_clusters/core/proto/BUILD.gn9
-rw-r--r--chromium/components/history_clusters/core/proto/clusters.proto52
-rw-r--r--chromium/components/history_clusters/core/visit_data.h76
-rw-r--r--chromium/components/image_fetcher/core/cache/image_cache.cc2
-rw-r--r--chromium/components/image_fetcher/core/cache/image_cache.h4
-rw-r--r--chromium/components/image_fetcher/core/cache/image_cache_unittest.cc10
-rw-r--r--chromium/components/image_fetcher/core/cache/image_metadata_store_leveldb_unittest.cc22
-rw-r--r--chromium/components/image_fetcher/core/cache/image_store_types.h6
-rw-r--r--chromium/components/image_fetcher/core/cached_image_fetcher_unittest.cc10
-rw-r--r--chromium/components/image_fetcher/core/image_data_fetcher.cc2
-rw-r--r--chromium/components/image_fetcher/core/image_data_fetcher.h6
-rw-r--r--chromium/components/image_fetcher/core/image_fetcher.h12
-rw-r--r--chromium/components/image_fetcher/core/reduced_mode_image_fetcher.h2
-rw-r--r--chromium/components/image_fetcher/core/reduced_mode_image_fetcher_unittest.cc6
-rw-r--r--chromium/components/image_fetcher/ios/ios_image_decoder_impl.h6
-rw-r--r--chromium/components/infobars/android/infobar_android.h2
-rw-r--r--chromium/components/infobars/content/content_infobar_manager.cc22
-rw-r--r--chromium/components/infobars/content/content_infobar_manager.h25
-rw-r--r--chromium/components/infobars/core/BUILD.gn6
-rw-r--r--chromium/components/infobars/core/infobar_container.h1
-rw-r--r--chromium/components/infobars/core/infobar_manager.h5
-rw-r--r--chromium/components/infobars/core/simple_alert_infobar_delegate.cc16
-rw-r--r--chromium/components/infobars/core/simple_alert_infobar_delegate.h17
-rw-r--r--chromium/components/installedapp/android/installed_app_verifier.cc2
-rw-r--r--chromium/components/javascript_dialogs/android/javascript_dialogs_android_strings.grd2
-rw-r--r--chromium/components/javascript_dialogs/tab_modal_dialog_manager.cc3
-rw-r--r--chromium/components/javascript_dialogs/tab_modal_dialog_manager.h2
-rw-r--r--chromium/components/javascript_dialogs/views/OWNERS0
-rw-r--r--chromium/components/javascript_dialogs/views/layer_dimmer_unittest.cc1
-rw-r--r--chromium/components/js_injection/browser/js_communication_host.h6
-rw-r--r--chromium/components/js_injection/browser/js_to_browser_messaging.cc3
-rw-r--r--chromium/components/js_injection/browser/web_message_reply_proxy.h3
-rw-r--r--chromium/components/js_injection/common/origin_matcher_mojom_traits.cc1
-rw-r--r--chromium/components/js_injection/common/origin_matcher_mojom_traits.h1
-rw-r--r--chromium/components/js_injection/renderer/js_binding.cc2
-rw-r--r--chromium/components/keep_alive_registry/keep_alive_types.cc6
-rw-r--r--chromium/components/keep_alive_registry/keep_alive_types.h5
-rw-r--r--chromium/components/keyed_service/content/browser_context_dependency_manager.h2
-rw-r--r--chromium/components/keyed_service/core/BUILD.gn3
-rw-r--r--chromium/components/keyed_service/core/keyed_service.h2
-rw-r--r--chromium/components/keyed_service/core/keyed_service_base_factory.h2
-rw-r--r--chromium/components/keyed_service/core/keyed_service_shutdown_notifier.cc10
-rw-r--r--chromium/components/keyed_service/core/keyed_service_shutdown_notifier.h7
-rw-r--r--chromium/components/keyed_service/ios/BUILD.gn3
-rw-r--r--chromium/components/keyed_service/ios/browser_state_dependency_manager.h1
-rw-r--r--chromium/components/language/android/BUILD.gn23
-rw-r--r--chromium/components/language/android/DEPS7
-rw-r--r--chromium/components/language/android/android_language_metrics_bridge.cc10
-rw-r--r--chromium/components/language/content/browser/geo_language_provider.cc2
-rw-r--r--chromium/components/language/content/browser/geo_language_provider_unittest.cc2
-rw-r--r--chromium/components/language/content/browser/ulp_language_code_locator/BUILD.gn3
-rw-r--r--chromium/components/language/content/browser/ulp_language_code_locator/ulp_serialized_to_static_c.py2
-rw-r--r--chromium/components/language/core/browser/heuristic_language_model.cc5
-rw-r--r--chromium/components/language/core/browser/language_prefs.cc2
-rw-r--r--chromium/components/language/core/browser/url_language_histogram.cc17
-rw-r--r--chromium/components/language/ios/browser/ios_language_detection_tab_helper.h6
-rw-r--r--chromium/components/lens/lens_features.cc2
-rw-r--r--chromium/components/leveldb_proto/internal/leveldb_proto_feature_list.h2
-rw-r--r--chromium/components/leveldb_proto/internal/proto/shared_db_metadata.proto4
-rw-r--r--chromium/components/leveldb_proto/internal/proto_database_selector.h4
-rw-r--r--chromium/components/leveldb_proto/internal/shared_proto_database.cc76
-rw-r--r--chromium/components/leveldb_proto/internal/shared_proto_database.h3
-rw-r--r--chromium/components/leveldb_proto/public/proto_database.h1
-rw-r--r--chromium/components/leveldb_proto/public/proto_database_provider.cc1
-rw-r--r--chromium/components/leveldb_proto/public/shared_proto_database_client_list.cc8
-rw-r--r--chromium/components/leveldb_proto/public/shared_proto_database_client_list.h4
-rw-r--r--chromium/components/link_header_util/link_header_util.cc4
-rw-r--r--chromium/components/link_header_util/link_header_util.h4
-rw-r--r--chromium/components/link_header_util/link_header_util_fuzzer.cc4
-rw-r--r--chromium/components/link_header_util/link_header_util_unittest.cc4
-rw-r--r--chromium/components/live_caption/BUILD.gn49
-rw-r--r--chromium/components/live_caption/DEPS14
-rw-r--r--chromium/components/live_caption/DIR_METADATA3
-rw-r--r--chromium/components/live_caption/OWNERS2
-rw-r--r--chromium/components/live_caption/caption_util.cc117
-rw-r--r--chromium/components/live_caption/caption_util.h21
-rw-r--r--chromium/components/live_caption/pref_names.cc47
-rw-r--r--chromium/components/live_caption/pref_names.h30
-rw-r--r--chromium/components/live_caption/views/caption_bubble.cc905
-rw-r--r--chromium/components/live_caption/views/caption_bubble.h187
-rw-r--r--chromium/components/live_caption/views/caption_bubble_model.cc117
-rw-r--r--chromium/components/live_caption/views/caption_bubble_model.h113
-rw-r--r--chromium/components/live_caption_strings.grdp25
-rw-r--r--chromium/components/live_caption_strings_grdp/DIR_METADATA3
-rw-r--r--chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_APPEAR_SCREENREADER_ANNOUNCEMENT.png.sha11
-rw-r--r--chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_BACK_TO_TAB.png.sha11
-rw-r--r--chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_CLOSE.png.sha11
-rw-r--r--chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_COLLAPSE.png.sha11
-rw-r--r--chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_ERROR.png.sha11
-rw-r--r--chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_EXPAND.png.sha11
-rw-r--r--chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_TITLE.png.sha11
-rw-r--r--chromium/components/live_caption_strings_grdp/OWNERS1
-rw-r--r--chromium/components/live_caption_strings_grdp/README.md5
-rw-r--r--chromium/components/location/android/location_settings_dialog_context.h6
-rw-r--r--chromium/components/location/android/location_settings_dialog_outcome.h6
-rw-r--r--chromium/components/location/android/location_settings_impl.h2
-rw-r--r--chromium/components/login/base_screen_handler_utils.cc6
-rw-r--r--chromium/components/login/base_screen_handler_utils.h1
-rw-r--r--chromium/components/login/secure_module_util_chromeos.h6
-rw-r--r--chromium/components/lookalikes/core/BUILD.gn3
-rw-r--r--chromium/components/lookalikes/core/DEPS2
-rw-r--r--chromium/components/lookalikes/core/features.cc2
-rw-r--r--chromium/components/lookalikes/core/lookalike_url_util.cc91
-rw-r--r--chromium/components/lookalikes/core/lookalike_url_util.h34
-rw-r--r--chromium/components/lookalikes/core/lookalike_url_util_unittest.cc68
-rw-r--r--chromium/components/management_strings.grdp3
-rw-r--r--chromium/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_DLP_EVENTS.png.sha11
-rw-r--r--chromium/components/media_control/browser/media_blocker.h2
-rw-r--r--chromium/components/media_control/renderer/media_playback_options.h1
-rw-r--r--chromium/components/media_message_center/BUILD.gn2
-rw-r--r--chromium/components/media_message_center/media_artwork_view.cc110
-rw-r--r--chromium/components/media_message_center/media_artwork_view.h49
-rw-r--r--chromium/components/media_message_center/media_controls_progress_view.cc2
-rw-r--r--chromium/components/media_message_center/media_controls_progress_view.h7
-rw-r--r--chromium/components/media_message_center/media_notification_background_ash_impl.cc1
-rw-r--r--chromium/components/media_message_center/media_notification_background_impl.cc24
-rw-r--r--chromium/components/media_message_center/media_notification_background_impl.h8
-rw-r--r--chromium/components/media_message_center/media_notification_background_impl_unittest.cc5
-rw-r--r--chromium/components/media_message_center/media_notification_item.h2
-rw-r--r--chromium/components/media_message_center/media_notification_view.h1
-rw-r--r--chromium/components/media_message_center/media_notification_view_impl.cc7
-rw-r--r--chromium/components/media_message_center/media_notification_view_impl.h10
-rw-r--r--chromium/components/media_message_center/media_notification_view_impl_unittest.cc28
-rw-r--r--chromium/components/media_message_center/media_notification_view_modern_impl.cc269
-rw-r--r--chromium/components/media_message_center/media_notification_view_modern_impl.h19
-rw-r--r--chromium/components/media_message_center/media_notification_view_modern_impl_unittest.cc54
-rw-r--r--chromium/components/media_message_center/media_session_notification_item.cc11
-rw-r--r--chromium/components/media_message_center/media_session_notification_item.h18
-rw-r--r--chromium/components/media_router/browser/android/DIR_METADATA4
-rw-r--r--chromium/components/media_router/browser/android/media_router_android.cc2
-rw-r--r--chromium/components/media_router/browser/android/media_router_android.h2
-rw-r--r--chromium/components/media_router/browser/android/media_router_android_bridge.cc4
-rw-r--r--chromium/components/media_router/browser/android/media_router_android_unittest.cc2
-rw-r--r--chromium/components/media_router/browser/android/media_router_dialog_controller_android.h2
-rw-r--r--chromium/components/media_router/browser/logger_impl.cc9
-rw-r--r--chromium/components/media_router/browser/media_router_dialog_controller.h3
-rw-r--r--chromium/components/media_router/browser/media_router_dialog_controller_unittest.cc1
-rw-r--r--chromium/components/media_router/browser/media_router_metrics.h2
-rw-r--r--chromium/components/media_router/browser/media_router_metrics_unittest.cc4
-rw-r--r--chromium/components/media_router/browser/media_sinks_observer.h4
-rw-r--r--chromium/components/media_router/browser/presentation/local_presentation_manager.h4
-rw-r--r--chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.cc2
-rw-r--r--chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.h4
-rw-r--r--chromium/components/media_router/browser/presentation/start_presentation_context.h1
-rw-r--r--chromium/components/media_router/browser/route_message_observer.h1
-rw-r--r--chromium/components/media_router/common/media_route.cc3
-rw-r--r--chromium/components/media_router/common/media_route.h8
-rw-r--r--chromium/components/media_router/common/media_route_provider_helper.h2
-rw-r--r--chromium/components/media_router/common/media_sink.cc11
-rw-r--r--chromium/components/media_router/common/media_sink.h21
-rw-r--r--chromium/components/media_router/common/media_sink_unittest.cc13
-rw-r--r--chromium/components/media_router/common/media_source.cc11
-rw-r--r--chromium/components/media_router/common/media_source.h4
-rw-r--r--chromium/components/media_router/common/mojom/media_router.mojom18
-rw-r--r--chromium/components/media_router/common/mojom/media_router_mojom_traits.cc9
-rw-r--r--chromium/components/media_router/common/mojom/media_router_mojom_traits.h31
-rw-r--r--chromium/components/media_router/common/providers/cast/cast_media_source.cc4
-rw-r--r--chromium/components/media_router/common/providers/cast/cast_media_source.h12
-rw-r--r--chromium/components/media_router/common/providers/cast/cast_media_source_unittest.cc2
-rw-r--r--chromium/components/messages/android/BUILD.gn1
-rw-r--r--chromium/components/messages/android/internal/BUILD.gn1
-rw-r--r--chromium/components/messages/android/internal/java/res/layout/message_banner_view.xml29
-rw-r--r--chromium/components/messages/android/internal/java/res/values/dimens.xml4
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerMediatorUnitTest.java2
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerRenderTest.java32
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerView.java6
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewBinder.java3
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewTest.java4
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageDispatcherImpl.java17
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManager.java59
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java96
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageStateHandler.java4
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessagesFactory.java7
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessagesMetrics.java98
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeController.java19
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeControllerTest.java42
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessage.java35
-rw-r--r--chromium/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessageTest.java45
-rw-r--r--chromium/components/messages/android/message_dispatcher_bridge.cc18
-rw-r--r--chromium/components/messages/android/message_dispatcher_bridge.h7
-rw-r--r--chromium/components/messages/android/message_enums.h41
-rw-r--r--chromium/components/messages/android/message_wrapper.cc40
-rw-r--r--chromium/components/messages/android/message_wrapper.h22
-rw-r--r--chromium/components/messages/android/messages_feature.cc24
-rw-r--r--chromium/components/messages/android/messages_feature.h22
-rw-r--r--chromium/components/messages/android/mock_message_dispatcher_bridge.cc2
-rw-r--r--chromium/components/messages/android/mock_message_dispatcher_bridge.h7
-rw-r--r--chromium/components/metrics/BUILD.gn2
-rw-r--r--chromium/components/metrics/call_stack_profile_builder.h2
-rw-r--r--chromium/components/metrics/call_stack_profile_builder_unittest.cc2
-rw-r--r--chromium/components/metrics/call_stack_profile_metadata.cc30
-rw-r--r--chromium/components/metrics/call_stack_profile_metadata.h6
-rw-r--r--chromium/components/metrics/call_stack_profile_metadata_unittest.cc24
-rw-r--r--chromium/components/metrics/call_stack_profile_params.h1
-rw-r--r--chromium/components/metrics/clean_exit_beacon.cc88
-rw-r--r--chromium/components/metrics/clean_exit_beacon.h20
-rw-r--r--chromium/components/metrics/clean_exit_beacon_unittest.cc90
-rw-r--r--chromium/components/metrics/daily_event_unittest.cc4
-rw-r--r--chromium/components/metrics/data_use_tracker.cc11
-rw-r--r--chromium/components/metrics/data_use_tracker_unittest.cc1
-rw-r--r--chromium/components/metrics/demographics/demographic_metrics_provider.cc14
-rw-r--r--chromium/components/metrics/demographics/demographic_metrics_provider.h5
-rw-r--r--chromium/components/metrics/demographics/user_demographics.cc18
-rw-r--r--chromium/components/metrics/drive_metrics_provider_win.cc1
-rw-r--r--chromium/components/metrics/expired_histogram_util.cc2
-rw-r--r--chromium/components/metrics/expired_histogram_util.h2
-rw-r--r--chromium/components/metrics/expired_histograms_checker.cc6
-rw-r--r--chromium/components/metrics/expired_histograms_checker.h8
-rw-r--r--chromium/components/metrics/expired_histograms_checker_unittest.cc14
-rw-r--r--chromium/components/metrics/file_metrics_provider.cc40
-rw-r--r--chromium/components/metrics/file_metrics_provider.h4
-rw-r--r--chromium/components/metrics/generate_expired_histograms_array.gni7
-rw-r--r--chromium/components/metrics/library_support/histogram_manager.h1
-rw-r--r--chromium/components/metrics/metrics_log.cc11
-rw-r--r--chromium/components/metrics/metrics_log.h4
-rw-r--r--chromium/components/metrics/metrics_log_manager.cc2
-rw-r--r--chromium/components/metrics/metrics_log_manager.h1
-rw-r--r--chromium/components/metrics/metrics_log_store.cc2
-rw-r--r--chromium/components/metrics/metrics_log_store.h4
-rw-r--r--chromium/components/metrics/metrics_log_store_unittest.cc22
-rw-r--r--chromium/components/metrics/metrics_log_unittest.cc12
-rw-r--r--chromium/components/metrics/metrics_service.cc43
-rw-r--r--chromium/components/metrics/metrics_service.h17
-rw-r--r--chromium/components/metrics/metrics_service_accessor.h1
-rw-r--r--chromium/components/metrics/metrics_service_client.cc11
-rw-r--r--chromium/components/metrics/metrics_service_client.h7
-rw-r--r--chromium/components/metrics/metrics_service_unittest.cc4
-rw-r--r--chromium/components/metrics/metrics_state_manager.cc5
-rw-r--r--chromium/components/metrics/metrics_state_manager.h9
-rw-r--r--chromium/components/metrics/metrics_state_manager_unittest.cc17
-rw-r--r--chromium/components/metrics/net/net_metrics_log_uploader.cc43
-rw-r--r--chromium/components/metrics/net/network_metrics_provider.cc7
-rw-r--r--chromium/components/metrics/net/network_metrics_provider_unittest.cc20
-rw-r--r--chromium/components/metrics/persistent_system_profile.h6
-rw-r--r--chromium/components/metrics/public/mojom/call_stack_profile_collector.mojom3
-rw-r--r--chromium/components/metrics/serialization/metric_sample.cc7
-rw-r--r--chromium/components/metrics/serialization/serialization_utils.cc10
-rw-r--r--chromium/components/metrics/single_sample_metrics_factory_impl.h6
-rw-r--r--chromium/components/metrics/structured/DIR_METADATA3
-rw-r--r--chromium/components/metrics/structured/event_base.cc9
-rw-r--r--chromium/components/metrics/structured/event_base.h14
-rw-r--r--chromium/components/metrics/structured/external_metrics.h5
-rw-r--r--chromium/components/metrics/structured/external_metrics_unittest.cc2
-rw-r--r--chromium/components/metrics/structured/histogram_util.h3
-rw-r--r--chromium/components/metrics/structured/key_data.cc10
-rw-r--r--chromium/components/metrics/structured/key_data.h6
-rw-r--r--chromium/components/metrics/structured/persistent_proto.h4
-rw-r--r--chromium/components/metrics/structured/recorder.h2
-rw-r--r--chromium/components/metrics/structured/structured_metrics_features.cc10
-rw-r--r--chromium/components/metrics/structured/structured_metrics_features.h14
-rw-r--r--chromium/components/metrics/structured/structured_metrics_provider.cc76
-rw-r--r--chromium/components/metrics/structured/structured_metrics_provider.h10
-rw-r--r--chromium/components/metrics/structured/structured_metrics_provider_unittest.cc207
-rw-r--r--chromium/components/metrics/system_session_analyzer/DIR_METADATA3
-rw-r--r--chromium/components/metrics/ui/screen_info_metrics_provider.cc8
-rw-r--r--chromium/components/metrics/ui/screen_info_metrics_provider.h4
-rw-r--r--chromium/components/metrics/ui/screen_info_metrics_provider_unittest.cc4
-rw-r--r--chromium/components/metrics/unsent_log_store.cc9
-rw-r--r--chromium/components/metrics/unsent_log_store.h10
-rw-r--r--chromium/components/metrics/unsent_log_store_unittest.cc44
-rw-r--r--chromium/components/metrics_services_manager/metrics_services_manager_client.h1
-rw-r--r--chromium/components/mirroring/browser/single_client_video_capture_host_unittest.cc6
-rw-r--r--chromium/components/mirroring/service/BUILD.gn3
-rw-r--r--chromium/components/mirroring/service/captured_audio_input.cc6
-rw-r--r--chromium/components/mirroring/service/captured_audio_input.h2
-rw-r--r--chromium/components/mirroring/service/captured_audio_input_unittest.cc25
-rw-r--r--chromium/components/mirroring/service/fake_network_service.cc2
-rw-r--r--chromium/components/mirroring/service/fake_video_capture_host.cc10
-rw-r--r--chromium/components/mirroring/service/message_dispatcher.cc10
-rw-r--r--chromium/components/mirroring/service/message_dispatcher_unittest.cc119
-rw-r--r--chromium/components/mirroring/service/mirror_settings.h2
-rw-r--r--chromium/components/mirroring/service/receiver_response.cc51
-rw-r--r--chromium/components/mirroring/service/receiver_response.h25
-rw-r--r--chromium/components/mirroring/service/receiver_response_unittest.cc25
-rw-r--r--chromium/components/mirroring/service/receiver_setup_querier.cc2
-rw-r--r--chromium/components/mirroring/service/receiver_setup_querier.h3
-rw-r--r--chromium/components/mirroring/service/rtp_stream.cc1
-rw-r--r--chromium/components/mirroring/service/rtp_stream.h8
-rw-r--r--chromium/components/mirroring/service/rtp_stream_unittest.cc7
-rw-r--r--chromium/components/mirroring/service/session.cc86
-rw-r--r--chromium/components/mirroring/service/session.h12
-rw-r--r--chromium/components/mirroring/service/session_unittest.cc7
-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/video_capture_client.cc22
-rw-r--r--chromium/components/mirroring/service/video_capture_client.h7
-rw-r--r--chromium/components/mirroring/service/video_capture_client_unittest.cc4
-rw-r--r--chromium/components/mirroring/service/wifi_status_monitor.cc81
-rw-r--r--chromium/components/mirroring/service/wifi_status_monitor.h60
-rw-r--r--chromium/components/mirroring/service/wifi_status_monitor_unittest.cc185
-rw-r--r--chromium/components/navigation_interception/navigation_params.cc2
-rw-r--r--chromium/components/navigation_interception/navigation_params.h6
-rw-r--r--chromium/components/net_log/net_export_file_writer.h2
-rw-r--r--chromium/components/net_log/net_export_file_writer_unittest.cc4
-rw-r--r--chromium/components/net_log/net_export_ui_constants.cc4
-rw-r--r--chromium/components/net_log/net_export_ui_constants.h3
-rw-r--r--chromium/components/net_log/resources/net_export.html11
-rw-r--r--chromium/components/net_log/resources/net_export.js556
-rw-r--r--chromium/components/neterror/resources/neterror.css119
-rw-r--r--chromium/components/neterror/resources/offline.js239
-rw-r--r--chromium/components/network_hints/browser/simple_network_hints_handler_impl.cc6
-rw-r--r--chromium/components/network_session_configurator/OWNERS2
-rw-r--r--chromium/components/network_session_configurator/browser/network_session_configurator.cc2
-rw-r--r--chromium/components/network_session_configurator/common/network_session_configurator_export.h6
-rw-r--r--chromium/components/network_time/network_time_test_utils.cc22
-rw-r--r--chromium/components/network_time/network_time_tracker.cc14
-rw-r--r--chromium/components/network_time/network_time_tracker_unittest.cc1
-rw-r--r--chromium/components/new_or_sad_tab_strings.grdp8
-rw-r--r--chromium/components/no_state_prefetch/browser/BUILD.gn6
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_contents.cc37
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_contents.h10
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_handle.h2
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_link_manager.cc12
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_link_manager.h8
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_manager.cc62
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_manager.h29
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_processor_impl.h2
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_processor_impl_unittest.cc2
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_utils.cc (renamed from chromium/components/no_state_prefetch/browser/prerender_util.cc)8
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_utils.h (renamed from chromium/components/no_state_prefetch/browser/prerender_util.h)8
-rw-r--r--chromium/components/no_state_prefetch/browser/no_state_prefetch_utils_unittest.cc (renamed from chromium/components/no_state_prefetch/browser/prerender_util_unittest.cc)4
-rw-r--r--chromium/components/no_state_prefetch/browser/prerender_config.h2
-rw-r--r--chromium/components/no_state_prefetch/browser/prerender_histograms.cc5
-rw-r--r--chromium/components/no_state_prefetch/browser/prerender_history_unittest.cc75
-rw-r--r--chromium/components/no_state_prefetch/common/BUILD.gn4
-rw-r--r--chromium/components/no_state_prefetch/common/no_state_prefetch_utils.cc (renamed from chromium/components/no_state_prefetch/common/prerender_util.cc)2
-rw-r--r--chromium/components/no_state_prefetch/common/no_state_prefetch_utils.h (renamed from chromium/components/no_state_prefetch/common/prerender_util.h)11
-rw-r--r--chromium/components/no_state_prefetch/common/prerender_origin.cc1
-rw-r--r--chromium/components/no_state_prefetch/common/prerender_origin.h3
-rw-r--r--chromium/components/no_state_prefetch/common/prerender_url_loader_throttle.cc2
-rw-r--r--chromium/components/no_state_prefetch/common/prerender_url_loader_throttle.h4
-rw-r--r--chromium/components/no_state_prefetch/renderer/BUILD.gn4
-rw-r--r--chromium/components/no_state_prefetch/renderer/no_state_prefetch_utils.cc (renamed from chromium/components/no_state_prefetch/renderer/prerender_utils.cc)4
-rw-r--r--chromium/components/no_state_prefetch/renderer/no_state_prefetch_utils.h (renamed from chromium/components/no_state_prefetch/renderer/prerender_utils.h)6
-rw-r--r--chromium/components/ntp_snippets/category_rankers/click_based_category_ranker.cc2
-rw-r--r--chromium/components/ntp_snippets/category_rankers/constant_category_ranker.h7
-rw-r--r--chromium/components/ntp_snippets/content_suggestion.h9
-rw-r--r--chromium/components/ntp_snippets/content_suggestions_metrics.h2
-rw-r--r--chromium/components/ntp_snippets/content_suggestions_service.cc13
-rw-r--r--chromium/components/ntp_snippets/content_suggestions_service.h4
-rw-r--r--chromium/components/ntp_snippets/content_suggestions_service_unittest.cc4
-rw-r--r--chromium/components/ntp_snippets/pref_util.cc2
-rw-r--r--chromium/components/ntp_snippets/remote/json_request.cc2
-rw-r--r--chromium/components/ntp_snippets/remote/json_request.h8
-rw-r--r--chromium/components/ntp_snippets/remote/json_request_unittest.cc2
-rw-r--r--chromium/components/ntp_snippets/remote/json_to_categories.cc8
-rw-r--r--chromium/components/ntp_snippets/remote/json_to_categories.h10
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestion.cc3
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestion.h6
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestion_builder.h48
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestion_unittest.cc1
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_fetcher.h4
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc2
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h2
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc4
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_provider.h2
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc10
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.h4
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl_unittest.cc28
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_scheduler_impl.h1
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.cc14
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.h13
-rw-r--r--chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl_unittest.cc3
-rw-r--r--chromium/components/ntp_snippets/remote/request_params.h4
-rw-r--r--chromium/components/ntp_snippets/remote/request_throttler.h2
-rw-r--r--chromium/components/ntp_snippets/remote/request_throttler_unittest.cc1
-rw-r--r--chromium/components/ntp_tiles/OWNERS1
-rw-r--r--chromium/components/ntp_tiles/constants.h2
-rw-r--r--chromium/components/ntp_tiles/custom_links_manager_impl.cc8
-rw-r--r--chromium/components/ntp_tiles/custom_links_manager_impl.h4
-rw-r--r--chromium/components/ntp_tiles/custom_links_manager_impl_unittest.cc192
-rw-r--r--chromium/components/ntp_tiles/custom_links_store_unittest.cc24
-rw-r--r--chromium/components/ntp_tiles/icon_cacher_impl.cc8
-rw-r--r--chromium/components/ntp_tiles/icon_cacher_impl.h1
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites.cc91
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites.h37
-rw-r--r--chromium/components/ntp_tiles/most_visited_sites_unittest.cc640
-rw-r--r--chromium/components/ntp_tiles/popular_sites_impl.cc2
-rw-r--r--chromium/components/ntp_tiles/popular_sites_impl_unittest.cc56
-rw-r--r--chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc17
-rw-r--r--chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.h2
-rw-r--r--chromium/components/ntp_tiles/webui/resources/ntp_tiles_internals.html11
-rw-r--r--chromium/components/ntp_tiles/webui/resources/ntp_tiles_internals.js90
-rw-r--r--chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc10
-rw-r--r--chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.h2
-rw-r--r--chromium/components/offline_items_collection/core/android/offline_item_bridge.cc6
-rw-r--r--chromium/components/offline_items_collection/core/android/offline_item_bridge.h4
-rw-r--r--chromium/components/offline_items_collection/core/android/offline_item_bridge_unittest.cc6
-rw-r--r--chromium/components/offline_items_collection/core/filtered_offline_item_observer.cc2
-rw-r--r--chromium/components/offline_items_collection/core/filtered_offline_item_observer.h4
-rw-r--r--chromium/components/offline_items_collection/core/filtered_offline_item_observer_unittest.cc10
-rw-r--r--chromium/components/offline_items_collection/core/offline_content_aggregator.cc8
-rw-r--r--chromium/components/offline_items_collection/core/offline_content_aggregator.h12
-rw-r--r--chromium/components/offline_items_collection/core/offline_content_aggregator_unittest.cc26
-rw-r--r--chromium/components/offline_items_collection/core/offline_content_provider.cc2
-rw-r--r--chromium/components/offline_items_collection/core/offline_content_provider.h16
-rw-r--r--chromium/components/offline_items_collection/core/offline_item.cc5
-rw-r--r--chromium/components/offline_items_collection/core/offline_item.h14
-rw-r--r--chromium/components/offline_items_collection/core/offline_item_unittest.cc4
-rw-r--r--chromium/components/offline_items_collection/core/test_support/mock_filtered_offline_item_observer.h2
-rw-r--r--chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.cc4
-rw-r--r--chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.h6
-rw-r--r--chromium/components/offline_items_collection/core/test_support/offline_item_test_support.cc2
-rw-r--r--chromium/components/offline_items_collection/core/throttled_offline_content_provider.cc8
-rw-r--r--chromium/components/offline_items_collection/core/throttled_offline_content_provider.h14
-rw-r--r--chromium/components/offline_items_collection/core/throttled_offline_content_provider_unittest.cc110
-rw-r--r--chromium/components/offline_items_collection/core/update_delta.cc6
-rw-r--r--chromium/components/offline_items_collection/core/update_delta.h8
-rw-r--r--chromium/components/offline_pages/core/BUILD.gn1
-rw-r--r--chromium/components/offline_pages/core/auto_fetch.cc8
-rw-r--r--chromium/components/offline_pages/core/auto_fetch.h4
-rw-r--r--chromium/components/offline_pages/core/auto_fetch_unittest.cc2
-rw-r--r--chromium/components/offline_pages/core/background/change_requests_state_task_unittest.cc18
-rw-r--r--chromium/components/offline_pages/core/background/cleanup_task_unittest.cc44
-rw-r--r--chromium/components/offline_pages/core/background/connection_notifier.h6
-rw-r--r--chromium/components/offline_pages/core/background/get_requests_task.h6
-rw-r--r--chromium/components/offline_pages/core/background/get_requests_task_unittest.cc18
-rw-r--r--chromium/components/offline_pages/core/background/initialize_store_task.h6
-rw-r--r--chromium/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc11
-rw-r--r--chromium/components/offline_pages/core/background/mark_attempt_completed_task.h1
-rw-r--r--chromium/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc11
-rw-r--r--chromium/components/offline_pages/core/background/mark_attempt_deferred_task.h1
-rw-r--r--chromium/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc11
-rw-r--r--chromium/components/offline_pages/core/background/pick_request_task_unittest.cc106
-rw-r--r--chromium/components/offline_pages/core/background/reconcile_task_unittest.cc27
-rw-r--r--chromium/components/offline_pages/core/background/remove_requests_task_unittest.cc17
-rw-r--r--chromium/components/offline_pages/core/background/request_coordinator.cc12
-rw-r--r--chromium/components/offline_pages/core/background/request_coordinator_unittest.cc96
-rw-r--r--chromium/components/offline_pages/core/background/request_queue.h1
-rw-r--r--chromium/components/offline_pages/core/background/request_queue_results.h6
-rw-r--r--chromium/components/offline_pages/core/background/request_queue_store.cc10
-rw-r--r--chromium/components/offline_pages/core/background/request_queue_store_unittest.cc158
-rw-r--r--chromium/components/offline_pages/core/background/request_queue_unittest.cc62
-rw-r--r--chromium/components/offline_pages/core/background/save_page_request_unittest.cc34
-rw-r--r--chromium/components/offline_pages/core/background/update_request_task.h2
-rw-r--r--chromium/components/offline_pages/core/downloads/download_ui_adapter.cc12
-rw-r--r--chromium/components/offline_pages/core/downloads/download_ui_adapter.h2
-rw-r--r--chromium/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc14
-rw-r--r--chromium/components/offline_pages/core/downloads/offline_item_conversions.cc4
-rw-r--r--chromium/components/offline_pages/core/downloads/offline_item_conversions_unittest.cc34
-rw-r--r--chromium/components/offline_pages/core/model/add_page_task_unittest.cc22
-rw-r--r--chromium/components/offline_pages/core/model/cleanup_visuals_task.h2
-rw-r--r--chromium/components/offline_pages/core/model/delete_page_task_unittest.cc55
-rw-r--r--chromium/components/offline_pages/core/model/get_pages_task.cc1
-rw-r--r--chromium/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc17
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc247
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_test_utils.h10
-rw-r--r--chromium/components/offline_pages/core/model/offline_page_upgrade_types.h6
-rw-r--r--chromium/components/offline_pages/core/model/update_publish_id_task.h1
-rw-r--r--chromium/components/offline_pages/core/offline_page_archive_publisher.h1
-rw-r--r--chromium/components/offline_pages/core/offline_page_feature.cc22
-rw-r--r--chromium/components/offline_pages/core/offline_page_feature.h14
-rw-r--r--chromium/components/offline_pages/core/offline_page_feature_unittest.cc88
-rw-r--r--chromium/components/offline_pages/core/offline_page_metadata_store.cc1
-rw-r--r--chromium/components/offline_pages/core/offline_page_metadata_store.h4
-rw-r--r--chromium/components/offline_pages/core/offline_page_metadata_store_test_util.cc1
-rw-r--r--chromium/components/offline_pages/core/offline_page_test_archive_publisher.h2
-rw-r--r--chromium/components/offline_pages/core/page_criteria.h14
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_background_task_handler.h2
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc47
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc7
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl_unittest.cc8
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc37
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_item_unittest.cc1
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_prefs.h1
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc14
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_request_test_base.h6
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_types.cc8
-rw-r--r--chromium/components/offline_pages/core/prefetch/prefetch_types.h6
-rw-r--r--chromium/components/offline_pages/core/prefetch/server_forbidden_check_request.h2
-rw-r--r--chromium/components/offline_pages/core/prefetch/store/prefetch_store.cc1
-rw-r--r--chromium/components/offline_pages/core/prefetch/store/prefetch_store.h3
-rw-r--r--chromium/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc20
-rw-r--r--chromium/components/offline_pages/core/prefetch/store/prefetch_store_test_util.h1
-rw-r--r--chromium/components/offline_pages/core/prefetch/tasks/get_visuals_info_task.h4
-rw-r--r--chromium/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.cc2
-rw-r--r--chromium/components/offline_pages/core/prefetch/tasks/remove_url_task.h1
-rw-r--r--chromium/components/offline_pages/core/prefetch/tasks/sent_get_operation_cleanup_task_unittest.cc2
-rw-r--r--chromium/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.h2
-rw-r--r--chromium/components/offline_pages/core/prefetch/test_download_service.cc6
-rw-r--r--chromium/components/offline_pages/core/prefetch/test_download_service.h4
-rw-r--r--chromium/components/offline_pages/core/prefetch/test_prefetch_network_request_factory.h4
-rw-r--r--chromium/components/offline_pages/core/request_header/offline_page_header.cc7
-rw-r--r--chromium/components/offline_pages/task/sql_store_base.h1
-rw-r--r--chromium/components/omnibox/browser/BUILD.gn27
-rw-r--r--chromium/components/omnibox_strings.grdp11
-rw-r--r--chromium/components/on_load_script_injector/browser/on_load_script_injector_host.h3
-rw-r--r--chromium/components/on_load_script_injector/renderer/on_load_script_injector.h2
-rw-r--r--chromium/components/onc/onc_pref_names.h6
-rw-r--r--chromium/components/open_from_clipboard/clipboard_recent_content.h10
-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.h4
-rw-r--r--chromium/components/open_from_clipboard/clipboard_recent_content_ios.h6
-rw-r--r--chromium/components/open_from_clipboard/clipboard_recent_content_ios.mm18
-rw-r--r--chromium/components/open_from_clipboard/clipboard_recent_content_ios_unittest.mm8
-rw-r--r--chromium/components/open_from_clipboard/fake_clipboard_recent_content.cc28
-rw-r--r--chromium/components/open_from_clipboard/fake_clipboard_recent_content.h10
-rw-r--r--chromium/components/openscreen_platform/BUILD.gn1
-rw-r--r--chromium/components/openscreen_platform/net_udp_socket.h2
-rw-r--r--chromium/components/openscreen_platform/network_util.h2
-rw-r--r--chromium/components/openscreen_platform/tls_connection_factory.cc8
-rw-r--r--chromium/components/openscreen_platform/tls_connection_factory.h8
-rw-r--r--chromium/components/openscreen_platform/tls_connection_factory_unittest.cc4
-rw-r--r--chromium/components/openscreen_platform/udp_socket.cc6
-rw-r--r--chromium/components/openscreen_platform/udp_socket.h8
-rw-r--r--chromium/components/optimization_guide/DEPS1
-rw-r--r--chromium/components/optimization_guide/content/browser/BUILD.gn12
-rw-r--r--chromium/components/optimization_guide/content/browser/DEPS2
-rw-r--r--chromium/components/optimization_guide/content/browser/bert_model_executor.h45
-rw-r--r--chromium/components/optimization_guide/content/browser/optimization_guide_decider.h25
-rw-r--r--chromium/components/optimization_guide/content/browser/optimization_target_model_executor.h324
-rw-r--r--chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager.cc49
-rw-r--r--chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager.h16
-rw-r--r--chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager_unittest.cc21
-rw-r--r--chromium/components/optimization_guide/content/browser/page_content_annotations_service.cc14
-rw-r--r--chromium/components/optimization_guide/content/browser/page_content_annotations_service.h10
-rw-r--r--chromium/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper_unittest.cc23
-rw-r--r--chromium/components/optimization_guide/content/browser/page_text_dump_result.cc21
-rw-r--r--chromium/components/optimization_guide/content/browser/page_text_dump_result.h24
-rw-r--r--chromium/components/optimization_guide/content/browser/page_text_dump_result_unittest.cc7
-rw-r--r--chromium/components/optimization_guide/content/browser/page_text_observer.cc17
-rw-r--r--chromium/components/optimization_guide/content/browser/page_text_observer.h3
-rw-r--r--chromium/components/optimization_guide/content/browser/page_text_observer_unittest.cc44
-rw-r--r--chromium/components/optimization_guide/content/browser/test_optimization_guide_decider.cc9
-rw-r--r--chromium/components/optimization_guide/content/browser/test_optimization_guide_decider.h7
-rw-r--r--chromium/components/optimization_guide/content/mojom/page_text_service.mojom1
-rw-r--r--chromium/components/optimization_guide/content/renderer/page_text_agent.cc8
-rw-r--r--chromium/components/optimization_guide/content/renderer/page_text_agent.h4
-rw-r--r--chromium/components/optimization_guide/content/renderer/page_text_agent_browsertest.cc2
-rw-r--r--chromium/components/optimization_guide/content/renderer/page_text_agent_unittest.cc2
-rw-r--r--chromium/components/optimization_guide/core/BUILD.gn41
-rw-r--r--chromium/components/optimization_guide/core/base_model_executor.h (renamed from chromium/components/optimization_guide/content/browser/base_model_executor.h)38
-rw-r--r--chromium/components/optimization_guide/core/base_model_executor_helpers.h (renamed from chromium/components/optimization_guide/content/browser/base_model_executor_helpers.h)24
-rw-r--r--chromium/components/optimization_guide/core/bert_model_executor.cc (renamed from chromium/components/optimization_guide/content/browser/bert_model_executor.cc)42
-rw-r--r--chromium/components/optimization_guide/core/bert_model_executor.h57
-rw-r--r--chromium/components/optimization_guide/core/bert_model_executor_unittest.cc (renamed from chromium/components/optimization_guide/content/browser/bert_model_executor_unittest.cc)68
-rw-r--r--chromium/components/optimization_guide/core/command_line_top_host_provider.cc4
-rw-r--r--chromium/components/optimization_guide/core/hint_cache.cc27
-rw-r--r--chromium/components/optimization_guide/core/hint_cache.h13
-rw-r--r--chromium/components/optimization_guide/core/hint_cache_unittest.cc72
-rw-r--r--chromium/components/optimization_guide/core/hints_fetcher.cc41
-rw-r--r--chromium/components/optimization_guide/core/hints_fetcher.h14
-rw-r--r--chromium/components/optimization_guide/core/hints_fetcher_unittest.cc43
-rw-r--r--chromium/components/optimization_guide/core/hints_processing_util.cc1
-rw-r--r--chromium/components/optimization_guide/core/insertion_ordered_set.h43
-rw-r--r--chromium/components/optimization_guide/core/insertion_ordered_set_unittest.cc57
-rw-r--r--chromium/components/optimization_guide/core/memory_hint.cc4
-rw-r--r--chromium/components/optimization_guide/core/memory_hint.h8
-rw-r--r--chromium/components/optimization_guide/core/model_executor.h454
-rw-r--r--chromium/components/optimization_guide/core/model_executor_unittest.cc (renamed from chromium/components/optimization_guide/content/browser/optimization_target_model_executor_unittest.cc)282
-rw-r--r--chromium/components/optimization_guide/core/noisy_metrics_recorder.cc54
-rw-r--r--chromium/components/optimization_guide/core/noisy_metrics_recorder.h32
-rw-r--r--chromium/components/optimization_guide/core/noisy_metrics_recorder_unittest.cc128
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_enums.h26
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_features.cc52
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_features.h17
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_model_provider.h47
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_store.cc52
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_store.h21
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_store_unittest.cc125
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_switches.cc30
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_switches.h8
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_switches_unittest.cc40
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_util.cc10
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_util.h14
-rw-r--r--chromium/components/optimization_guide/core/optimization_guide_util_unittest.cc6
-rw-r--r--chromium/components/optimization_guide/core/optimization_hints_component_update_listener.cc2
-rw-r--r--chromium/components/optimization_guide/core/optimization_hints_component_update_listener.h6
-rw-r--r--chromium/components/optimization_guide/core/optimization_metadata.h22
-rw-r--r--chromium/components/optimization_guide/core/optimization_metadata_unittest.cc12
-rw-r--r--chromium/components/optimization_guide/core/optimization_target_model_observer.h4
-rw-r--r--chromium/components/optimization_guide/core/prediction_model_fetcher.cc34
-rw-r--r--chromium/components/optimization_guide/core/prediction_model_fetcher.h5
-rw-r--r--chromium/components/optimization_guide/core/prediction_model_fetcher_unittest.cc119
-rw-r--r--chromium/components/optimization_guide/core/prediction_model_file.cc8
-rw-r--r--chromium/components/optimization_guide/core/prediction_model_file.h8
-rw-r--r--chromium/components/optimization_guide/core/push_notification_manager.h53
-rw-r--r--chromium/components/optimization_guide/core/store_update_data.cc16
-rw-r--r--chromium/components/optimization_guide/core/store_update_data.h20
-rw-r--r--chromium/components/optimization_guide/core/test_optimization_guide_model_provider.cc24
-rw-r--r--chromium/components/optimization_guide/core/test_optimization_guide_model_provider.h37
-rw-r--r--chromium/components/optimization_guide/core/tflite_op_resolver.cc4
-rw-r--r--chromium/components/optimization_guide/features.gni6
-rw-r--r--chromium/components/optimization_guide/proto/BUILD.gn5
-rw-r--r--chromium/components/optimization_guide/proto/delay_async_script_execution_metadata.proto2
-rw-r--r--chromium/components/optimization_guide/proto/delay_competing_low_priority_requests_metadata.proto2
-rw-r--r--chromium/components/optimization_guide/proto/hint_cache.proto4
-rw-r--r--chromium/components/optimization_guide/proto/hints.proto8
-rw-r--r--chromium/components/optimization_guide/proto/lite_video_metadata.proto2
-rw-r--r--chromium/components/optimization_guide/proto/models.proto15
-rw-r--r--chromium/components/optimization_guide/proto/push_notification.proto29
-rw-r--r--chromium/components/os_crypt/BUILD.gn5
-rw-r--r--chromium/components/os_crypt/features.gni6
-rw-r--r--chromium/components/os_crypt/key_storage_config_linux.h6
-rw-r--r--chromium/components/os_crypt/key_storage_keyring.cc25
-rw-r--r--chromium/components/os_crypt/key_storage_keyring.h13
-rw-r--r--chromium/components/os_crypt/key_storage_keyring_unittest.cc10
-rw-r--r--chromium/components/os_crypt/key_storage_kwallet.cc12
-rw-r--r--chromium/components/os_crypt/key_storage_kwallet.h2
-rw-r--r--chromium/components/os_crypt/key_storage_kwallet_unittest.cc6
-rw-r--r--chromium/components/os_crypt/key_storage_libsecret.cc25
-rw-r--r--chromium/components/os_crypt/key_storage_libsecret.h10
-rw-r--r--chromium/components/os_crypt/key_storage_libsecret_unittest.cc12
-rw-r--r--chromium/components/os_crypt/key_storage_linux.cc35
-rw-r--r--chromium/components/os_crypt/key_storage_linux.h8
-rw-r--r--chromium/components/os_crypt/key_storage_linux_unittest.cc2
-rw-r--r--chromium/components/os_crypt/keychain_password_mac.h11
-rw-r--r--chromium/components/os_crypt/keychain_password_mac.mm17
-rw-r--r--chromium/components/os_crypt/kwallet_dbus.cc4
-rw-r--r--chromium/components/os_crypt/kwallet_dbus.h4
-rw-r--r--chromium/components/os_crypt/kwallet_dbus_unittest.cc6
-rw-r--r--chromium/components/os_crypt/os_crypt_linux.cc5
-rw-r--r--chromium/components/os_crypt/os_crypt_mocker_linux.cc2
-rw-r--r--chromium/components/os_crypt/os_crypt_mocker_linux.h4
-rw-r--r--chromium/components/os_crypt/os_crypt_unittest.cc1
-rw-r--r--chromium/components/ownership/mock_owner_key_util.h1
-rw-r--r--chromium/components/page_image_annotation/content/renderer/content_page_annotator_driver.cc8
-rw-r--r--chromium/components/page_info/BUILD.gn2
-rw-r--r--chromium/components/page_info/DEPS54
-rw-r--r--chromium/components/page_info/android/BUILD.gn30
-rw-r--r--chromium/components/page_info/android/DIR_METADATA3
-rw-r--r--chromium/components/page_info/android/connection_info_view_android.cc16
-rw-r--r--chromium/components/page_info/android/connection_info_view_android.h6
-rw-r--r--chromium/components/page_info/android/page_info_controller_android.cc9
-rw-r--r--chromium/components/page_info/android/page_info_controller_android.h4
-rw-r--r--chromium/components/page_info/android/page_info_features.cc28
-rw-r--r--chromium/components/page_info/features.cc1
-rw-r--r--chromium/components/page_info/features.h4
-rw-r--r--chromium/components/page_info/page_info.cc35
-rw-r--r--chromium/components/page_info/page_info.h23
-rw-r--r--chromium/components/page_info/page_info_delegate.h15
-rw-r--r--chromium/components/page_info/page_info_ui.cc270
-rw-r--r--chromium/components/page_info/page_info_ui.h64
-rw-r--r--chromium/components/page_info/page_info_ui_delegate.h3
-rw-r--r--chromium/components/page_info_strings.grdp17
-rw-r--r--chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_CERTIFICATE_IS_NOT_VALID.png.sha11
-rw-r--r--chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_CERTIFICATE_IS_VALID.png.sha11
-rw-r--r--chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_NUM_COOKIES.png.sha11
-rw-r--r--chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SECURITY_SUBPAGE_HEADER.png.sha11
-rw-r--r--chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SERIAL_PORT_ALLOWED_BY_POLICY_LABEL.png.sha11
-rw-r--r--chromium/components/page_load_metrics/browser/BUILD.gn1
-rw-r--r--chromium/components/page_load_metrics/browser/DIR_METADATA3
-rw-r--r--chromium/components/page_load_metrics/browser/layout_shift_normalization.cc8
-rw-r--r--chromium/components/page_load_metrics/browser/layout_shift_normalization.h10
-rw-r--r--chromium/components/page_load_metrics/browser/layout_shift_normalization_unittest.cc2
-rw-r--r--chromium/components/page_load_metrics/browser/metrics_web_contents_observer.cc51
-rw-r--r--chromium/components/page_load_metrics/browser/metrics_web_contents_observer.h16
-rw-r--r--chromium/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc77
-rw-r--r--chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc13
-rw-r--r--chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.h2
-rw-r--r--chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc24
-rw-r--r--chromium/components/page_load_metrics/browser/observers/ad_metrics/frame_tree_data.cc4
-rw-r--r--chromium/components/page_load_metrics/browser/observers/ad_metrics/frame_tree_data.h16
-rw-r--r--chromium/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.cc8
-rw-r--r--chromium/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.h4
-rw-r--r--chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc23
-rw-r--r--chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.h4
-rw-r--r--chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer_unittest.cc101
-rw-r--r--chromium/components/page_load_metrics/browser/observers/core/DIR_METADATA3
-rw-r--r--chromium/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.cc24
-rw-r--r--chromium/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h24
-rw-r--r--chromium/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc3
-rw-r--r--chromium/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer_unittest.cc2
-rw-r--r--chromium/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.cc7
-rw-r--r--chromium/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.cc34
-rw-r--r--chromium/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.h6
-rw-r--r--chromium/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc5
-rw-r--r--chromium/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc11
-rw-r--r--chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc268
-rw-r--r--chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.h27
-rw-r--r--chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer_unittest.cc199
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_embedder_base.cc6
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_embedder_base.h1
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_embedder_interface.h2
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_memory_tracker_unittest.cc3
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_observer.h17
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h10
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_test_waiter.cc39
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_test_waiter.h20
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc45
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.h9
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_util.cc16
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_util.h10
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_metrics_util_unittest.cc2
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_tracker.cc13
-rw-r--r--chromium/components/page_load_metrics/browser/page_load_tracker.h16
-rw-r--r--chromium/components/page_load_metrics/browser/test_metrics_web_contents_observer_embedder.cc15
-rw-r--r--chromium/components/page_load_metrics/browser/test_metrics_web_contents_observer_embedder.h12
-rw-r--r--chromium/components/page_load_metrics/common/BUILD.gn4
-rw-r--r--chromium/components/page_load_metrics/common/page_end_reason.h6
-rw-r--r--chromium/components/page_load_metrics/common/page_load_metrics.mojom31
-rw-r--r--chromium/components/page_load_metrics/common/page_load_metrics_constants.h5
-rw-r--r--chromium/components/page_load_metrics/common/page_load_metrics_util.cc48
-rw-r--r--chromium/components/page_load_metrics/common/page_load_metrics_util.h17
-rw-r--r--chromium/components/page_load_metrics/common/page_load_timing.cc16
-rw-r--r--chromium/components/page_load_metrics/common/page_load_timing.h3
-rw-r--r--chromium/components/page_load_metrics/renderer/fake_page_timing_sender.cc61
-rw-r--r--chromium/components/page_load_metrics/renderer/fake_page_timing_sender.h22
-rw-r--r--chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.cc42
-rw-r--r--chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.h11
-rw-r--r--chromium/components/page_load_metrics/renderer/metrics_render_frame_observer_unittest.cc10
-rw-r--r--chromium/components/page_load_metrics/renderer/page_timing_metadata_recorder.h6
-rw-r--r--chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.cc51
-rw-r--r--chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.h21
-rw-r--r--chromium/components/page_load_metrics/renderer/page_timing_metrics_sender_unittest.cc163
-rw-r--r--chromium/components/page_load_metrics/renderer/page_timing_sender.h2
-rw-r--r--chromium/components/paint_preview/OWNERS3
-rw-r--r--chromium/components/paint_preview/browser/file_manager.cc16
-rw-r--r--chromium/components/paint_preview/browser/file_manager.h5
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_base_service.cc4
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_base_service.h22
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_base_service_unittest.cc25
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_client.cc11
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_client.h11
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_client_unittest.cc6
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_compositor_client_impl.cc2
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_compositor_client_impl.h6
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_file_mixin.cc4
-rw-r--r--chromium/components/paint_preview/browser/paint_preview_file_mixin.h4
-rw-r--r--chromium/components/paint_preview/browser/test_paint_preview_policy.cc2
-rw-r--r--chromium/components/paint_preview/common/capture_result.h14
-rw-r--r--chromium/components/paint_preview/common/mojom/paint_preview_recorder.mojom12
-rw-r--r--chromium/components/paint_preview/common/paint_preview_tracker.cc2
-rw-r--r--chromium/components/paint_preview/common/paint_preview_tracker.h6
-rw-r--r--chromium/components/paint_preview/common/recording_map.h2
-rw-r--r--chromium/components/paint_preview/common/serial_utils.cc50
-rw-r--r--chromium/components/paint_preview/common/serial_utils.h12
-rw-r--r--chromium/components/paint_preview/common/serial_utils_unittest.cc4
-rw-r--r--chromium/components/paint_preview/common/serialized_recording.cc29
-rw-r--r--chromium/components/paint_preview/common/serialized_recording.h25
-rw-r--r--chromium/components/paint_preview/common/serialized_recording_unittest.cc91
-rw-r--r--chromium/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java6
-rw-r--r--chromium/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinatorTest.java4
-rw-r--r--chromium/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java4
-rw-r--r--chromium/components/paint_preview/player/android/player_compositor_delegate_android.cc3
-rw-r--r--chromium/components/paint_preview/player/bitmap_request.cc2
-rw-r--r--chromium/components/paint_preview/player/bitmap_request.h6
-rw-r--r--chromium/components/paint_preview/player/player_compositor_delegate.cc12
-rw-r--r--chromium/components/paint_preview/player/player_compositor_delegate.h4
-rw-r--r--chromium/components/paint_preview/player/player_compositor_delegate_unittest.cc8
-rw-r--r--chromium/components/paint_preview/public/paint_preview_compositor_client.h4
-rw-r--r--chromium/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc78
-rw-r--r--chromium/components/paint_preview/renderer/paint_preview_recorder_impl.cc35
-rw-r--r--chromium/components/paint_preview/renderer/paint_preview_recorder_utils.cc85
-rw-r--r--chromium/components/paint_preview/renderer/paint_preview_recorder_utils.h14
-rw-r--r--chromium/components/paint_preview/renderer/paint_preview_recorder_utils_unittest.cc236
-rw-r--r--chromium/components/password_manager/content/browser/content_password_manager_driver.cc4
-rw-r--r--chromium/components/password_manager/content/browser/password_requirements_service_factory.cc2
-rw-r--r--chromium/components/password_manager/content/common/credential_manager_mojom_traits.h8
-rw-r--r--chromium/components/password_manager/core/browser/BUILD.gn19
-rw-r--r--chromium/components/password_manager/core/browser/DEPS1
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/DIR_METADATA3
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliated_match_helper_unittest.cc8
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_database.h1
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/affiliation_utils.cc4
-rw-r--r--chromium/components/password_manager/core/browser/android_affiliation/android_affiliation_service.h2
-rw-r--r--chromium/components/password_manager/core/browser/biometric_authenticator.h92
-rw-r--r--chromium/components/password_manager/core/browser/browser_save_password_progress_logger.cc2
-rw-r--r--chromium/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc7
-rw-r--r--chromium/components/password_manager/core/browser/change_password_url_service_impl.cc2
-rw-r--r--chromium/components/password_manager/core/browser/credential_cache.h1
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_impl.cc2
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_impl.h2
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_impl_unittest.cc32
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_pending_request_task.cc8
-rw-r--r--chromium/components/password_manager/core/browser/credential_manager_utils.cc2
-rw-r--r--chromium/components/password_manager/core/browser/export/DIR_METADATA4
-rw-r--r--chromium/components/password_manager/core/browser/export/password_manager_exporter.h1
-rw-r--r--chromium/components/password_manager/core/browser/field_info_manager.cc2
-rw-r--r--chromium/components/password_manager/core/browser/form_fetcher_impl.cc6
-rw-r--r--chromium/components/password_manager/core/browser/form_fetcher_impl_unittest.cc20
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/form_parser.cc30
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/form_parser.h8
-rw-r--r--chromium/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc161
-rw-r--r--chromium/components/password_manager/core/browser/form_saver.h2
-rw-r--r--chromium/components/password_manager/core/browser/form_saver_impl_unittest.cc69
-rw-r--r--chromium/components/password_manager/core/browser/hash_password_manager.cc18
-rw-r--r--chromium/components/password_manager/core/browser/hash_password_manager.h4
-rw-r--r--chromium/components/password_manager/core/browser/hash_password_manager_unittest.cc12
-rw-r--r--chromium/components/password_manager/core/browser/http_auth_manager_impl.h1
-rw-r--r--chromium/components/password_manager/core/browser/http_auth_manager_unittest.cc7
-rw-r--r--chromium/components/password_manager/core/browser/import/csv_password_iterator.h4
-rw-r--r--chromium/components/password_manager/core/browser/import/csv_reader.h6
-rw-r--r--chromium/components/password_manager/core/browser/import/password_importer.cc8
-rw-r--r--chromium/components/password_manager/core/browser/import/password_importer.h1
-rw-r--r--chromium/components/password_manager/core/browser/import/password_importer_unittest.cc10
-rw-r--r--chromium/components/password_manager/core/browser/insecure_credentials_table_unittest.cc24
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check.cc4
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check.h4
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/authenticated_leak_check_unittest.cc39
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc4
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h4
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl_unittest.cc41
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/encryption_utils.cc33
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/encryption_utils.h14
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.h2
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request.cc5
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_factory.h4
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_unittest.cc8
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection/leak_detection_request_utils.cc4
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_delegate.cc2
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_delegate_helper_unittest.cc50
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_dialog_utils.cc3
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_dialog_utils.h15
-rw-r--r--chromium/components/password_manager/core/browser/leak_detection_dialog_utils_unittest.cc9
-rw-r--r--chromium/components/password_manager/core/browser/login_database_unittest.cc15
-rw-r--r--chromium/components/password_manager/core/browser/mock_biometric_authenticator.cc12
-rw-r--r--chromium/components/password_manager/core/browser/mock_biometric_authenticator.h32
-rw-r--r--chromium/components/password_manager/core/browser/password_autofill_manager.cc49
-rw-r--r--chromium/components/password_manager/core/browser/password_autofill_manager.h15
-rw-r--r--chromium/components/password_manager/core/browser/password_autofill_manager_unittest.cc315
-rw-r--r--chromium/components/password_manager/core/browser/password_bubble_experiment.cc9
-rw-r--r--chromium/components/password_manager/core/browser/password_bubble_experiment_unittest.cc12
-rw-r--r--chromium/components/password_manager/core/browser/password_form.cc8
-rw-r--r--chromium/components/password_manager/core/browser/password_form.h26
-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.cc77
-rw-r--r--chromium/components/password_manager/core/browser/password_form_manager.cc3
-rw-r--r--chromium/components/password_manager/core/browser/password_form_manager_unittest.cc23
-rw-r--r--chromium/components/password_manager/core/browser/password_form_metrics_recorder.cc2
-rw-r--r--chromium/components/password_manager/core/browser/password_form_metrics_recorder.h16
-rw-r--r--chromium/components/password_manager/core/browser/password_form_metrics_recorder_unittest.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_generation_frame_helper.cc2
-rw-r--r--chromium/components/password_manager/core/browser/password_generation_manager.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_generation_manager.h4
-rw-r--r--chromium/components/password_manager/core/browser/password_manager.cc57
-rw-r--r--chromium/components/password_manager/core/browser/password_manager.h6
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_client.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_client.h2
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_driver.h5
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_features_util.cc17
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_interface.h1
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_metrics_util.cc2
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_metrics_util.h2
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_test_utils.cc14
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_test_utils.h14
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_unittest.cc95
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_util.cc7
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_util.h4
-rw-r--r--chromium/components/password_manager/core/browser/password_manager_util_unittest.cc64
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detection_manager.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detection_manager.h4
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detection_manager_unittest.cc57
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detector.cc53
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detector.h29
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detector_consumer.h5
-rw-r--r--chromium/components/password_manager/core/browser/password_reuse_detector_unittest.cc61
-rw-r--r--chromium/components/password_manager/core/browser/password_save_manager_impl.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_save_manager_impl.h2
-rw-r--r--chromium/components/password_manager/core/browser/password_save_manager_impl_unittest.cc9
-rw-r--r--chromium/components/password_manager/core/browser/password_scripts_fetcher_impl.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_store.cc4
-rw-r--r--chromium/components/password_manager/core/browser/password_store.h4
-rw-r--r--chromium/components/password_manager/core/browser/password_store_factory_util.cc2
-rw-r--r--chromium/components/password_manager/core/browser/password_store_factory_util.h2
-rw-r--r--chromium/components/password_manager/core/browser/password_store_unittest.cc14
-rw-r--r--chromium/components/password_manager/core/browser/password_ui_utils.cc3
-rw-r--r--chromium/components/password_manager/core/browser/possible_username_data.h4
-rw-r--r--chromium/components/password_manager/core/browser/psl_matching_helper_unittest.cc1
-rw-r--r--chromium/components/password_manager/core/browser/site_affiliation/affiliation_fetcher_base.cc4
-rw-r--r--chromium/components/password_manager/core/browser/site_affiliation/affiliation_service_impl_unittest.cc6
-rw-r--r--chromium/components/password_manager/core/browser/sql_table_builder.cc1
-rw-r--r--chromium/components/password_manager/core/browser/statistics_table_unittest.cc14
-rw-r--r--chromium/components/password_manager/core/browser/store_metrics_reporter.cc4
-rw-r--r--chromium/components/password_manager/core/browser/store_metrics_reporter_unittest.cc7
-rw-r--r--chromium/components/password_manager/core/browser/stub_password_manager_client.h4
-rw-r--r--chromium/components/password_manager/core/browser/stub_password_manager_driver.cc2
-rw-r--r--chromium/components/password_manager/core/browser/sync/password_model_type_controller.cc2
-rw-r--r--chromium/components/password_manager/core/browser/sync/password_sync_bridge.cc18
-rw-r--r--chromium/components/password_manager/core/browser/sync/password_sync_bridge.h6
-rw-r--r--chromium/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc58
-rw-r--r--chromium/components/password_manager/core/browser/sync_credentials_filter_unittest.cc3
-rw-r--r--chromium/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter_unittest.cc40
-rw-r--r--chromium/components/password_manager/core/browser/ui/insecure_credentials_manager.cc11
-rw-r--r--chromium/components/password_manager/core/browser/ui/insecure_credentials_manager.h3
-rw-r--r--chromium/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc170
-rw-r--r--chromium/components/password_manager/core/browser/ui/post_save_compromised_helper.cc9
-rw-r--r--chromium/components/password_manager/core/browser/ui/post_save_compromised_helper.h5
-rw-r--r--chromium/components/password_manager/core/browser/ui/post_save_compromised_helper_unittest.cc86
-rw-r--r--chromium/components/password_manager/core/browser/ui/saved_passwords_presenter.cc90
-rw-r--r--chromium/components/password_manager/core/browser/ui/saved_passwords_presenter.h20
-rw-r--r--chromium/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc194
-rw-r--r--chromium/components/password_manager/core/browser/ui/weak_check_utility_unittest.cc34
-rw-r--r--chromium/components/password_manager/core/browser/votes_uploader.cc2
-rw-r--r--chromium/components/password_manager/core/browser/votes_uploader.h6
-rw-r--r--chromium/components/password_manager/core/browser/votes_uploader_unittest.cc25
-rw-r--r--chromium/components/password_manager/core/browser/well_known_change_password_state.cc10
-rw-r--r--chromium/components/password_manager/core/browser/well_known_change_password_state.h8
-rw-r--r--chromium/components/password_manager/core/browser/well_known_change_password_state_unittest.cc2
-rw-r--r--chromium/components/password_manager/core/browser/well_known_change_password_util.h2
-rw-r--r--chromium/components/password_manager/core/common/credential_manager_types.cc6
-rw-r--r--chromium/components/password_manager/core/common/credential_manager_types.h14
-rw-r--r--chromium/components/password_manager/core/common/password_manager_features.cc24
-rw-r--r--chromium/components/password_manager/core/common/password_manager_features.h3
-rw-r--r--chromium/components/password_manager/ios/BUILD.gn63
-rw-r--r--chromium/components/password_manager/ios/js_password_manager.h91
-rw-r--r--chromium/components/password_manager/ios/js_password_manager.mm152
-rw-r--r--chromium/components/password_manager/ios/password_form_helper.h4
-rw-r--r--chromium/components/password_manager/ios/password_form_helper.mm198
-rw-r--r--chromium/components/password_manager/ios/password_form_helper_unittest.mm108
-rw-r--r--chromium/components/password_manager/ios/password_manager_java_script_feature.h110
-rw-r--r--chromium/components/password_manager/ios/password_manager_java_script_feature.mm213
-rw-r--r--chromium/components/password_manager/ios/resources/test_bundle.js11
-rw-r--r--chromium/components/password_manager/ios/shared_password_controller.h1
-rw-r--r--chromium/components/password_manager/ios/shared_password_controller.mm63
-rw-r--r--chromium/components/password_manager/ios/shared_password_controller_unittest.mm16
-rw-r--r--chromium/components/payments/OWNERS4
-rw-r--r--chromium/components/payments/content/android/BUILD.gn10
-rw-r--r--chromium/components/payments/content/android/DEPS1
-rw-r--r--chromium/components/payments/content/android/currency_formatter_android.cc7
-rw-r--r--chromium/components/payments/content/android/payment_feature_list.cc8
-rw-r--r--chromium/components/payments/content/android/payment_manifest_downloader_android.cc4
-rw-r--r--chromium/components/payments/content/android/payment_manifest_web_data_service_android.cc234
-rw-r--r--chromium/components/payments/content/android/payment_manifest_web_data_service_android.h97
-rw-r--r--chromium/components/payments/content/android/url_util.cc12
-rw-r--r--chromium/components/payments/content/android_app_communication.h16
-rw-r--r--chromium/components/payments/content/android_app_communication_chrome_os.cc35
-rw-r--r--chromium/components/payments/content/android_app_communication_stub.cc10
-rw-r--r--chromium/components/payments/content/android_app_communication_test_support.h10
-rw-r--r--chromium/components/payments/content/android_app_communication_test_support_chrome_os.cc29
-rw-r--r--chromium/components/payments/content/android_app_communication_test_support_stub.cc4
-rw-r--r--chromium/components/payments/content/android_app_communication_unittest.cc23
-rw-r--r--chromium/components/payments/content/android_payment_app.cc29
-rw-r--r--chromium/components/payments/content/android_payment_app.h13
-rw-r--r--chromium/components/payments/content/android_payment_app_factory.cc6
-rw-r--r--chromium/components/payments/content/android_payment_app_unittest.cc56
-rw-r--r--chromium/components/payments/content/installable_payment_app_crawler.cc3
-rw-r--r--chromium/components/payments/content/manifest_verifier.cc11
-rw-r--r--chromium/components/payments/content/payment_app.h1
-rw-r--r--chromium/components/payments/content/payment_app_factory.h1
-rw-r--r--chromium/components/payments/content/payment_credential.h4
-rw-r--r--chromium/components/payments/content/payment_credential_enrollment_model_unittest.cc7
-rw-r--r--chromium/components/payments/content/payment_handler_host.cc6
-rw-r--r--chromium/components/payments/content/payment_handler_navigation_throttle.cc5
-rw-r--r--chromium/components/payments/content/payment_request_display_manager.cc2
-rw-r--r--chromium/components/payments/content/payment_request_web_contents_manager.h6
-rw-r--r--chromium/components/payments/content/payment_response_helper_unittest.cc1
-rw-r--r--chromium/components/payments/content/secure_payment_confirmation_app.cc1
-rw-r--r--chromium/components/payments/content/secure_payment_confirmation_app.h2
-rw-r--r--chromium/components/payments/content/service_worker_payment_app_finder.cc4
-rw-r--r--chromium/components/payments/content/service_worker_payment_app_unittest.cc2
-rw-r--r--chromium/components/payments/content/ssl_validity_checker.cc6
-rw-r--r--chromium/components/payments/content/utility/payment_manifest_parser.cc8
-rw-r--r--chromium/components/payments/core/BUILD.gn3
-rw-r--r--chromium/components/payments/core/can_make_payment_query.cc1
-rw-r--r--chromium/components/payments/core/currency_formatter_unittest.cc4
-rw-r--r--chromium/components/payments/core/features.cc2
-rw-r--r--chromium/components/payments/core/journey_logger.cc10
-rw-r--r--chromium/components/payments/core/journey_logger.h1
-rw-r--r--chromium/components/payments/core/method_strings.cc6
-rw-r--r--chromium/components/payments/core/method_strings.h16
-rw-r--r--chromium/components/payments/core/payment_address.h1
-rw-r--r--chromium/components/payments/core/payment_currency_amount.h1
-rw-r--r--chromium/components/payments/core/payment_details_modifier.h1
-rw-r--r--chromium/components/payments/core/payment_manifest_downloader.cc4
-rw-r--r--chromium/components/payments/core/payment_manifest_downloader_unittest.cc6
-rw-r--r--chromium/components/payments/core/web_payment_request.cc97
-rw-r--r--chromium/components/payments/core/web_payment_request.h58
-rw-r--r--chromium/components/payments/core/web_payment_request_unittest.cc182
-rw-r--r--chromium/components/payments_strings.grdp22
-rw-r--r--chromium/components/pdf/browser/pdf_web_contents_helper.cc2
-rw-r--r--chromium/components/pdf/renderer/BUILD.gn3
-rw-r--r--chromium/components/pdf/renderer/DIR_METADATA3
-rw-r--r--chromium/components/pdf/renderer/pdf_accessibility_tree.cc5
-rw-r--r--chromium/components/pdf/renderer/pdf_accessibility_tree.h5
-rw-r--r--chromium/components/pdf/renderer/pdf_ax_action_target.cc2
-rw-r--r--chromium/components/pdf_strings.grdp12
-rw-r--r--chromium/components/performance_manager/BUILD.gn3
-rw-r--r--chromium/components/performance_manager/DEPS2
-rw-r--r--chromium/components/performance_manager/decorators/freezing_vote_decorator.cc4
-rw-r--r--chromium/components/performance_manager/decorators/freezing_vote_decorator.h2
-rw-r--r--chromium/components/performance_manager/decorators/page_live_state_decorator_unittest.cc3
-rw-r--r--chromium/components/performance_manager/decorators/page_load_tracker_decorator.h2
-rw-r--r--chromium/components/performance_manager/decorators/process_metrics_decorator.cc186
-rw-r--r--chromium/components/performance_manager/decorators/site_data_recorder_unittest.cc1
-rw-r--r--chromium/components/performance_manager/embedder/performance_manager_lifetime.h2
-rw-r--r--chromium/components/performance_manager/execution_context/execution_context_registry_impl.h2
-rw-r--r--chromium/components/performance_manager/execution_context_priority/boosting_vote_aggregator.h15
-rw-r--r--chromium/components/performance_manager/execution_context_priority/inherit_client_priority_voter.h2
-rw-r--r--chromium/components/performance_manager/execution_context_priority/max_vote_aggregator.cc2
-rw-r--r--chromium/components/performance_manager/execution_context_priority/max_vote_aggregator.h4
-rw-r--r--chromium/components/performance_manager/execution_context_priority/override_vote_aggregator.cc6
-rw-r--r--chromium/components/performance_manager/execution_context_priority/override_vote_aggregator.h6
-rw-r--r--chromium/components/performance_manager/execution_context_priority/root_vote_observer_unittest.cc6
-rw-r--r--chromium/components/performance_manager/features.cc34
-rw-r--r--chromium/components/performance_manager/freezing/freezing_unittest.cc36
-rw-r--r--chromium/components/performance_manager/freezing/freezing_vote_aggregator.cc2
-rw-r--r--chromium/components/performance_manager/graph/frame_node_impl.cc98
-rw-r--r--chromium/components/performance_manager/graph/frame_node_impl.h35
-rw-r--r--chromium/components/performance_manager/graph/frame_node_impl_describer.cc2
-rw-r--r--chromium/components/performance_manager/graph/frame_node_impl_unittest.cc176
-rw-r--r--chromium/components/performance_manager/graph/graph_impl.cc3
-rw-r--r--chromium/components/performance_manager/graph/graph_impl.h1
-rw-r--r--chromium/components/performance_manager/graph/graph_impl_operations.h1
-rw-r--r--chromium/components/performance_manager/graph/graph_impl_unittest.cc11
-rw-r--r--chromium/components/performance_manager/graph/node_attached_data.h2
-rw-r--r--chromium/components/performance_manager/graph/page_node.cc16
-rw-r--r--chromium/components/performance_manager/graph/page_node_impl.cc93
-rw-r--r--chromium/components/performance_manager/graph/page_node_impl.h38
-rw-r--r--chromium/components/performance_manager/graph/page_node_impl_describer.cc10
-rw-r--r--chromium/components/performance_manager/graph/page_node_impl_unittest.cc20
-rw-r--r--chromium/components/performance_manager/graph/process_node_impl.cc2
-rw-r--r--chromium/components/performance_manager/graph/process_node_impl.h8
-rw-r--r--chromium/components/performance_manager/graph/process_node_impl_unittest.cc2
-rw-r--r--chromium/components/performance_manager/graph/system_node_impl.h1
-rw-r--r--chromium/components/performance_manager/performance_manager_browsertest.cc8
-rw-r--r--chromium/components/performance_manager/performance_manager_lifetime.cc6
-rw-r--r--chromium/components/performance_manager/performance_manager_registry_impl.cc2
-rw-r--r--chromium/components/performance_manager/performance_manager_registry_impl.h1
-rw-r--r--chromium/components/performance_manager/performance_manager_tab_helper.cc39
-rw-r--r--chromium/components/performance_manager/performance_manager_tab_helper.h1
-rw-r--r--chromium/components/performance_manager/persistence/site_data/leveldb_site_data_store.cc15
-rw-r--r--chromium/components/performance_manager/persistence/site_data/leveldb_site_data_store_unittest.cc6
-rw-r--r--chromium/components/performance_manager/persistence/site_data/non_recording_site_data_cache.cc2
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_cache_factory.cc2
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_cache_factory.h4
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc4
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_cache_impl_unittest.cc49
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_cache_inspector.h7
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_impl.cc2
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_impl.h2
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_impl_unittest.cc6
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc2
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_store.h10
-rw-r--r--chromium/components/performance_manager/persistence/site_data/site_data_writer.h2
-rw-r--r--chromium/components/performance_manager/persistence/site_data/unittest_utils.cc4
-rw-r--r--chromium/components/performance_manager/public/decorators/process_metrics_decorator.h111
-rw-r--r--chromium/components/performance_manager/public/features.h52
-rw-r--r--chromium/components/performance_manager/public/graph/frame_node.h16
-rw-r--r--chromium/components/performance_manager/public/graph/node_data_describer_registry.h2
-rw-r--r--chromium/components/performance_manager/public/graph/page_node.h68
-rw-r--r--chromium/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h2
-rw-r--r--chromium/components/performance_manager/public/graph/process_node.h6
-rw-r--r--chromium/components/performance_manager/public/graph/system_node.h4
-rw-r--r--chromium/components/performance_manager/public/mojom/web_memory.mojom5
-rw-r--r--chromium/components/performance_manager/public/performance_manager_main_thread_mechanism.h2
-rw-r--r--chromium/components/performance_manager/public/render_frame_host_proxy.h2
-rw-r--r--chromium/components/performance_manager/public/v8_memory/v8_detailed_memory.h12
-rw-r--r--chromium/components/performance_manager/public/v8_memory/v8_detailed_memory_any_seq.h6
-rw-r--r--chromium/components/performance_manager/test_support/voting.h3
-rw-r--r--chromium/components/performance_manager/v8_memory/v8_context_tracker.cc22
-rw-r--r--chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers.cc4
-rw-r--r--chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers.h6
-rw-r--r--chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers_unittest.cc52
-rw-r--r--chromium/components/performance_manager/v8_memory/v8_context_tracker_unittest.cc34
-rw-r--r--chromium/components/performance_manager/v8_memory/v8_detailed_memory.cc4
-rw-r--r--chromium/components/performance_manager/v8_memory/v8_detailed_memory_any_seq.cc6
-rw-r--r--chromium/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc18
-rw-r--r--chromium/components/performance_manager/v8_memory/v8_memory_test_helpers.cc8
-rw-r--r--chromium/components/performance_manager/v8_memory/v8_memory_test_helpers.h32
-rw-r--r--chromium/components/performance_manager/v8_memory/web_memory_aggregator.cc11
-rw-r--r--chromium/components/performance_manager/v8_memory/web_memory_aggregator.h4
-rw-r--r--chromium/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc106
-rw-r--r--chromium/components/performance_manager/v8_memory/web_memory_impl.cc4
-rw-r--r--chromium/components/performance_manager/v8_memory/web_memory_impl_unittest.cc2
-rw-r--r--chromium/components/performance_manager/worker_watcher_unittest.cc5
-rw-r--r--chromium/components/permissions/BUILD.gn42
-rw-r--r--chromium/components/permissions/android/BUILD.gn19
-rw-r--r--chromium/components/permissions/android/android_permission_util.cc40
-rw-r--r--chromium/components/permissions/android/android_permission_util.h25
-rw-r--r--chromium/components/permissions/android/nfc/nfc_system_level_setting_impl.h2
-rw-r--r--chromium/components/permissions/android/permission_dialog_delegate.cc4
-rw-r--r--chromium/components/permissions/android/permission_dialog_delegate.h2
-rw-r--r--chromium/components/permissions/android/permissions_android_feature_list.cc (renamed from chromium/components/page_info/android/page_info_feature_list.cc)35
-rw-r--r--chromium/components/permissions/android/permissions_android_feature_list.h15
-rw-r--r--chromium/components/permissions/android/translations/permissions_android_strings_fr-CA.xtb2
-rw-r--r--chromium/components/permissions/chooser_controller.cc86
-rw-r--r--chromium/components/permissions/chooser_controller.h183
-rw-r--r--chromium/components/permissions/contexts/DEPS3
-rw-r--r--chromium/components/permissions/contexts/DIR_METADATA5
-rw-r--r--chromium/components/permissions/contexts/OWNERS3
-rw-r--r--chromium/components/permissions/contexts/bluetooth_chooser_context.cc337
-rw-r--r--chromium/components/permissions/contexts/bluetooth_chooser_context.h104
-rw-r--r--chromium/components/permissions/contexts/file_handling_permission_context.cc21
-rw-r--r--chromium/components/permissions/contexts/file_handling_permission_context.h26
-rw-r--r--chromium/components/permissions/contexts/geolocation_permission_context_android.h3
-rw-r--r--chromium/components/permissions/contexts/geolocation_permission_context_unittest.cc6
-rw-r--r--chromium/components/permissions/contexts/midi_permission_context.cc33
-rw-r--r--chromium/components/permissions/contexts/midi_permission_context.h34
-rw-r--r--chromium/components/permissions/contexts/midi_permission_context_unittest.cc50
-rw-r--r--chromium/components/permissions/contexts/midi_sysex_permission_context.cc49
-rw-r--r--chromium/components/permissions/contexts/midi_sysex_permission_context.h34
-rw-r--r--chromium/components/permissions/contexts/midi_sysex_permission_context_unittest.cc138
-rw-r--r--chromium/components/permissions/fake_bluetooth_chooser_controller.cc105
-rw-r--r--chromium/components/permissions/fake_bluetooth_chooser_controller.h92
-rw-r--r--chromium/components/permissions/fake_usb_chooser_controller.cc39
-rw-r--r--chromium/components/permissions/fake_usb_chooser_controller.h42
-rw-r--r--chromium/components/permissions/features.cc7
-rw-r--r--chromium/components/permissions/features.h8
-rw-r--r--chromium/components/permissions/mock_chooser_controller_view.cc13
-rw-r--r--chromium/components/permissions/mock_chooser_controller_view.h32
-rw-r--r--chromium/components/permissions/notification_permission_ui_selector.cc49
-rw-r--r--chromium/components/permissions/object_permission_context_base.cc (renamed from chromium/components/permissions/chooser_context_base.cc)112
-rw-r--r--chromium/components/permissions/object_permission_context_base.h (renamed from chromium/components/permissions/chooser_context_base.h)41
-rw-r--r--chromium/components/permissions/object_permission_context_base_unittest.cc (renamed from chromium/components/permissions/chooser_context_base_unittest.cc)230
-rw-r--r--chromium/components/permissions/permission_auditing_database.cc7
-rw-r--r--chromium/components/permissions/permission_auditing_database.h4
-rw-r--r--chromium/components/permissions/permission_auditing_database_unittest.cc2
-rw-r--r--chromium/components/permissions/permission_auditing_service.h2
-rw-r--r--chromium/components/permissions/permission_auditing_service_unittest.cc3
-rw-r--r--chromium/components/permissions/permission_context_base.cc63
-rw-r--r--chromium/components/permissions/permission_context_base.h39
-rw-r--r--chromium/components/permissions/permission_context_base_unittest.cc6
-rw-r--r--chromium/components/permissions/permission_manager.cc52
-rw-r--r--chromium/components/permissions/permission_manager.h24
-rw-r--r--chromium/components/permissions/permission_manager_unittest.cc81
-rw-r--r--chromium/components/permissions/permission_prompt.h1
-rw-r--r--chromium/components/permissions/permission_request.cc19
-rw-r--r--chromium/components/permissions/permission_request.h20
-rw-r--r--chromium/components/permissions/permission_request_id.cc1
-rw-r--r--chromium/components/permissions/permission_request_impl.cc105
-rw-r--r--chromium/components/permissions/permission_request_impl.h17
-rw-r--r--chromium/components/permissions/permission_request_manager.cc78
-rw-r--r--chromium/components/permissions/permission_request_manager.h55
-rw-r--r--chromium/components/permissions/permission_request_manager_unittest.cc216
-rw-r--r--chromium/components/permissions/permission_ui_selector.cc48
-rw-r--r--chromium/components/permissions/permission_ui_selector.h (renamed from chromium/components/permissions/notification_permission_ui_selector.h)42
-rw-r--r--chromium/components/permissions/permission_uma_util.cc114
-rw-r--r--chromium/components/permissions/permission_uma_util.h56
-rw-r--r--chromium/components/permissions/permission_uma_util_unittest.cc76
-rw-r--r--chromium/components/permissions/permission_util.cc4
-rw-r--r--chromium/components/permissions/permissions_client.cc32
-rw-r--r--chromium/components/permissions/permissions_client.h43
-rw-r--r--chromium/components/permissions/prediction_service/prediction_service.cc3
-rw-r--r--chromium/components/permissions/prediction_service/prediction_service_unittest.cc34
-rw-r--r--chromium/components/permissions/pref_names.h2
-rw-r--r--chromium/components/permissions/quota_permission_context_impl.cc18
-rw-r--r--chromium/components/permissions/request_type.cc6
-rw-r--r--chromium/components/permissions/request_type.h7
-rw-r--r--chromium/components/permissions_strings.grdp37
-rw-r--r--chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT.png.sha11
-rw-r--r--chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_PROMPT_ORIGIN.png.sha11
-rw-r--r--chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL.png.sha11
-rw-r--r--chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL_TOOLTIP.png.sha11
-rw-r--r--chromium/components/permissions_strings_grdp/IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT.png.sha11
-rw-r--r--chromium/components/permissions_strings_grdp/IDS_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT.png.sha11
-rw-r--r--chromium/components/permissions_strings_grdp/IDS_FILE_HANDLING_PERMISSION_FRAGMENT.png.sha11
-rw-r--r--chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_LOADING_LABEL.png.sha11
-rw-r--r--chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_LOADING_LABEL_TOOLTIP.png.sha11
-rw-r--r--chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN.png.sha11
-rw-r--r--chromium/components/plugins/OWNERS1
-rw-r--r--chromium/components/plugins/renderer/loadable_plugin_placeholder.cc1
-rw-r--r--chromium/components/plugins/renderer/webview_plugin.cc33
-rw-r--r--chromium/components/plugins/renderer/webview_plugin.h14
-rw-r--r--chromium/components/policy/BUILD.gn3
-rw-r--r--chromium/components/policy/core/browser/BUILD.gn4
-rw-r--r--chromium/components/policy/core/common/BUILD.gn4
-rw-r--r--chromium/components/policy_strings.grdp12
-rw-r--r--chromium/components/policy_strings_grdp/DIR_METADATA4
-rw-r--r--chromium/components/policy_strings_grdp/IDS_POLICY_DEPENDENCY_ERROR.png.sha11
-rw-r--r--chromium/components/policy_strings_grdp/IDS_POLICY_LABEL_LAST_CLOUD_REPORT_SENT_TIMESTAMP.png.sha11
-rw-r--r--chromium/components/policy_strings_grdp/IDS_POLICY_SOURCE_CLOUD_FROM_ASH.png.sha11
-rw-r--r--chromium/components/policy_strings_grdp/IDS_POLICY_SYNC_DISABLED_PREREQUISITE_MISSING.png.sha11
-rw-r--r--chromium/components/power_scheduler/power_mode.cc8
-rw-r--r--chromium/components/power_scheduler/power_mode.h16
-rw-r--r--chromium/components/power_scheduler/power_mode_arbiter.cc246
-rw-r--r--chromium/components/power_scheduler/power_mode_arbiter.h31
-rw-r--r--chromium/components/power_scheduler/power_mode_arbiter_unittest.cc212
-rw-r--r--chromium/components/power_scheduler/power_mode_voter.cc95
-rw-r--r--chromium/components/power_scheduler/power_mode_voter.h73
-rw-r--r--chromium/components/power_scheduler/power_scheduler.cc169
-rw-r--r--chromium/components/power_scheduler/power_scheduler.h27
-rw-r--r--chromium/components/power_scheduler/traced_power_mode.h1
-rw-r--r--chromium/components/pref_registry/DIR_METADATA2
-rw-r--r--chromium/components/prefs/BUILD.gn3
-rw-r--r--chromium/components/prefs/DIR_METADATA2
-rw-r--r--chromium/components/prefs/android/DIR_METADATA3
-rw-r--r--chromium/components/prefs/command_line_pref_store.cc1
-rw-r--r--chromium/components/prefs/command_line_pref_store.h1
-rw-r--r--chromium/components/prefs/json_pref_store.cc4
-rw-r--r--chromium/components/prefs/json_pref_store_unittest.cc36
-rw-r--r--chromium/components/prefs/mock_pref_change_callback.h2
-rw-r--r--chromium/components/prefs/overlay_user_pref_store.cc2
-rw-r--r--chromium/components/prefs/overlay_user_pref_store_unittest.cc2
-rw-r--r--chromium/components/prefs/persistent_pref_store.h2
-rw-r--r--chromium/components/prefs/pref_member.cc37
-rw-r--r--chromium/components/prefs/pref_service.cc26
-rw-r--r--chromium/components/prefs/pref_service_unittest.cc35
-rw-r--r--chromium/components/prefs/pref_value_map.cc23
-rw-r--r--chromium/components/prefs/prefs_export.h6
-rw-r--r--chromium/components/prefs/scoped_user_pref_update_unittest.cc4
-rw-r--r--chromium/components/prefs/segregated_pref_store.cc224
-rw-r--r--chromium/components/prefs/segregated_pref_store.h118
-rw-r--r--chromium/components/prefs/segregated_pref_store_unittest.cc380
-rw-r--r--chromium/components/prefs/testing_pref_store.cc18
-rw-r--r--chromium/components/printing/browser/BUILD.gn3
-rw-r--r--chromium/components/printing/browser/DEPS1
-rw-r--r--chromium/components/printing/browser/DIR_METADATA3
-rw-r--r--chromium/components/printing/browser/prefs_util.cc44
-rw-r--r--chromium/components/printing/browser/prefs_util.h20
-rw-r--r--chromium/components/printing/browser/print_manager.cc49
-rw-r--r--chromium/components/printing/browser/print_manager.h47
-rw-r--r--chromium/components/printing/common/BUILD.gn1
-rw-r--r--chromium/components/printing/common/DIR_METADATA3
-rw-r--r--chromium/components/printing/common/cloud_print_cdd_conversion.cc12
-rw-r--r--chromium/components/printing/common/cloud_print_cdd_conversion.h3
-rw-r--r--chromium/components/printing/common/print.mojom30
-rw-r--r--chromium/components/printing/renderer/print_render_frame_helper.cc105
-rw-r--r--chromium/components/printing/renderer/print_render_frame_helper.h34
-rw-r--r--chromium/components/printing/resources/DIR_METADATA3
-rw-r--r--chromium/components/printing_component_strings.grdp2
-rw-r--r--chromium/components/privacy_sandbox/privacy_sandbox_prefs.cc5
-rw-r--r--chromium/components/privacy_sandbox/privacy_sandbox_prefs.h11
-rw-r--r--chromium/components/privacy_sandbox_strings.grdp36
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/DIR_METADATA5
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION.png.sha11
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_INVALID.png.sha11
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION.png.sha11
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_ACTIVE.png.sha11
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_ELIGIBLE_NOT_ACTIVE.png.sha11
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_NOT_ACTIVE.png.sha11
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE.png.sha11
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE_INVALID.png.sha11
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/OWNERS1
-rw-r--r--chromium/components/privacy_sandbox_strings_grdp/README.md5
-rw-r--r--chromium/components/profile_metrics/BUILD.gn16
-rw-r--r--chromium/components/profile_metrics/browser_profile_type.cc4
-rw-r--r--chromium/components/profile_metrics/browser_profile_type.h19
-rw-r--r--chromium/components/profile_metrics/browser_profile_type_unittest.cc46
-rw-r--r--chromium/components/qr_code_generator/qr_code_generator.cc14
-rw-r--r--chromium/components/qr_code_generator/qr_code_generator.h8
-rw-r--r--chromium/components/qr_code_generator/qr_code_generator_unittest.cc8
-rw-r--r--chromium/components/qr_code_generator/qr_print.cc6
-rw-r--r--chromium/components/query_parser/query_parser.cc3
-rw-r--r--chromium/components/query_parser/query_parser.h2
-rw-r--r--chromium/components/query_tiles/android/tile_provider_bridge.cc2
-rw-r--r--chromium/components/query_tiles/internal/cached_image_loader.h2
-rw-r--r--chromium/components/query_tiles/internal/image_loader.h3
-rw-r--r--chromium/components/query_tiles/internal/init_aware_tile_service.cc4
-rw-r--r--chromium/components/query_tiles/internal/init_aware_tile_service.h6
-rw-r--r--chromium/components/query_tiles/internal/init_aware_tile_service_unittest.cc14
-rw-r--r--chromium/components/query_tiles/internal/log_source.h2
-rw-r--r--chromium/components/query_tiles/internal/tile_manager.cc4
-rw-r--r--chromium/components/query_tiles/internal/tile_manager.h6
-rw-r--r--chromium/components/query_tiles/internal/tile_manager_unittest.cc14
-rw-r--r--chromium/components/query_tiles/internal/tile_service_impl.cc2
-rw-r--r--chromium/components/query_tiles/internal/tile_service_impl.h2
-rw-r--r--chromium/components/query_tiles/internal/tile_service_impl_unittest.cc4
-rw-r--r--chromium/components/query_tiles/internal/tile_service_scheduler.h3
-rw-r--r--chromium/components/query_tiles/internal/tile_service_scheduler_impl.cc23
-rw-r--r--chromium/components/query_tiles/internal/tile_service_scheduler_impl.h3
-rw-r--r--chromium/components/query_tiles/internal/tile_service_scheduler_unittest.cc35
-rw-r--r--chromium/components/query_tiles/tile_service.h6
-rw-r--r--chromium/components/quirks/pref_names.h6
-rw-r--r--chromium/components/reading_list/core/offline_url_utils.cc1
-rw-r--r--chromium/components/reading_list/core/reading_list_entry.cc4
-rw-r--r--chromium/components/reading_list/core/reading_list_model_impl.cc2
-rw-r--r--chromium/components/reading_list/core/reading_list_model_observer.h3
-rw-r--r--chromium/components/reading_list/core/reading_list_model_unittest.cc8
-rw-r--r--chromium/components/reading_list/core/reading_list_store.cc12
-rw-r--r--chromium/components/reading_list/core/reading_list_store.h12
-rw-r--r--chromium/components/remote_cocoa/app_shim/BUILD.gn2
-rw-r--r--chromium/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm17
-rw-r--r--chromium/components/remote_cocoa/app_shim/color_panel_bridge.mm2
-rw-r--r--chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h5
-rw-r--r--chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm33
-rw-r--r--chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h19
-rw-r--r--chromium/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm80
-rw-r--r--chromium/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm7
-rw-r--r--chromium/components/remote_cocoa/app_shim/views_nswindow_delegate.h6
-rw-r--r--chromium/components/remote_cocoa/app_shim/views_scrollbar_bridge.h2
-rw-r--r--chromium/components/remote_cocoa/app_shim/window_controls_overlay_nsview.h31
-rw-r--r--chromium/components/remote_cocoa/app_shim/window_controls_overlay_nsview.mm36
-rw-r--r--chromium/components/remote_cocoa/app_shim/window_move_loop.h3
-rw-r--r--chromium/components/remote_cocoa/app_shim/window_move_loop.mm12
-rw-r--r--chromium/components/remote_cocoa/common/native_widget_ns_window.mojom15
-rw-r--r--chromium/components/renderer_context_menu/render_view_context_menu_base.cc3
-rw-r--r--chromium/components/renderer_context_menu/render_view_context_menu_base.h4
-rw-r--r--chromium/components/reporting/client/mock_report_queue.h2
-rw-r--r--chromium/components/reporting/client/report_queue_provider.cc30
-rw-r--r--chromium/components/reporting/client/report_queue_provider.h22
-rw-r--r--chromium/components/reporting/client/report_queue_provider_unttest.cc15
-rw-r--r--chromium/components/reporting/encryption/decryption.h2
-rw-r--r--chromium/components/reporting/encryption/encryption.h4
-rw-r--r--chromium/components/reporting/encryption/encryption_module_interface.h3
-rw-r--r--chromium/components/reporting/encryption/encryption_module_unittest.cc2
-rw-r--r--chromium/components/reporting/proto/record.proto8
-rw-r--r--chromium/components/reporting/proto/record_constants.proto3
-rw-r--r--chromium/components/reporting/storage/resources/resource_interface.h4
-rw-r--r--chromium/components/reporting/storage/storage.cc47
-rw-r--r--chromium/components/reporting/storage/storage.h4
-rw-r--r--chromium/components/reporting/storage/storage_module.h2
-rw-r--r--chromium/components/reporting/storage/storage_module_interface.h2
-rw-r--r--chromium/components/reporting/storage/storage_queue.cc114
-rw-r--r--chromium/components/reporting/storage/storage_queue.h12
-rw-r--r--chromium/components/reporting/storage/storage_queue_stress_test.cc11
-rw-r--r--chromium/components/reporting/storage/storage_queue_unittest.cc24
-rw-r--r--chromium/components/reporting/storage/storage_unittest.cc222
-rw-r--r--chromium/components/reporting/storage/test_storage_module.h8
-rw-r--r--chromium/components/reporting/storage_selector/storage_selector.cc18
-rw-r--r--chromium/components/reporting/storage_selector/storage_selector.h4
-rw-r--r--chromium/components/reporting/util/shared_vector_unittest.cc18
-rw-r--r--chromium/components/reporting/util/status.h2
-rw-r--r--chromium/components/reporting/util/statusor.h5
-rw-r--r--chromium/components/reputation/core/safety_tip_test_utils.cc10
-rw-r--r--chromium/components/reputation/core/safety_tip_test_utils.h3
-rw-r--r--chromium/components/reputation/core/safety_tips.proto5
-rw-r--r--chromium/components/reputation/core/safety_tips_config.cc17
-rw-r--r--chromium/components/reputation/core/safety_tips_config.h4
-rw-r--r--chromium/components/reputation/core/safety_tips_config_unittest.cc14
-rw-r--r--chromium/components/resources/android/page_info_resource_id.h18
-rw-r--r--chromium/components/resources/components_scaled_resources.grd1
-rw-r--r--chromium/components/resources/default_100_percent/favicon_info.pngbin0 -> 478 bytes
-rw-r--r--chromium/components/resources/default_200_percent/favicon_info.pngbin0 -> 892 bytes
-rw-r--r--chromium/components/resources/default_300_percent/favicon_info.pngbin0 -> 1161 bytes
-rw-r--r--chromium/components/resources/flags_ui_resources.grdp4
-rw-r--r--chromium/components/resources/gcm_driver_resources.grdp4
-rw-r--r--chromium/components/resources/net_log_resources.grdp5
-rw-r--r--chromium/components/resources/ntp_tiles_dev_ui_resources.grdp3
-rw-r--r--chromium/components/resources/ssl/ssl_error_assistant/BUILD.gn3
-rw-r--r--chromium/components/resources/ssl/ssl_error_assistant/PRESUBMIT.py2
-rwxr-xr-xchromium/components/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py2
-rwxr-xr-xchromium/components/resources/ssl/ssl_error_assistant/push_proto.py22
-rw-r--r--chromium/components/safe_browsing/DEPS2
-rw-r--r--chromium/components/safe_browsing/android/DIR_METADATA5
-rw-r--r--chromium/components/safe_browsing/android/remote_database_manager_unittest.cc1
-rw-r--r--chromium/components/safe_browsing/android/safe_browsing_api_handler.h1
-rw-r--r--chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.h1
-rw-r--r--chromium/components/safe_browsing/content/browser/BUILD.gn19
-rw-r--r--chromium/components/safe_browsing/content/browser/client_side_detection_host.cc26
-rw-r--r--chromium/components/safe_browsing/content/browser/client_side_detection_host.h3
-rw-r--r--chromium/components/safe_browsing/content/browser/client_side_detection_service.cc54
-rw-r--r--chromium/components/safe_browsing/content/browser/client_side_detection_service.h33
-rw-r--r--chromium/components/safe_browsing/content/browser/client_side_model_loader.cc3
-rw-r--r--chromium/components/safe_browsing/content/browser/client_side_model_loader.h5
-rw-r--r--chromium/components/safe_browsing/content/browser/client_side_model_loader_unittest.cc17
-rw-r--r--chromium/components/safe_browsing/content/browser/client_side_phishing_model.cc281
-rw-r--r--chromium/components/safe_browsing/content/browser/client_side_phishing_model.h109
-rw-r--r--chromium/components/safe_browsing/content/browser/client_side_phishing_model_unittest.cc390
-rw-r--r--chromium/components/safe_browsing/content/browser/threat_details.cc1
-rw-r--r--chromium/components/safe_browsing/content/browser/threat_details_history.h1
-rw-r--r--chromium/components/safe_browsing/content/browser/web_api_handshake_checker.cc133
-rw-r--r--chromium/components/safe_browsing/content/browser/web_api_handshake_checker.h64
-rw-r--r--chromium/components/safe_browsing/content/browser/web_api_handshake_checker_unittest.cc129
-rw-r--r--chromium/components/safe_browsing/content/common/safe_browsing.mojom19
-rw-r--r--chromium/components/safe_browsing/content/password_protection/BUILD.gn1
-rw-r--r--chromium/components/safe_browsing/content/password_protection/DIR_METADATA5
-rw-r--r--chromium/components/safe_browsing/content/password_protection/password_protection_request_content.cc43
-rw-r--r--chromium/components/safe_browsing/content/password_protection/password_protection_request_content.h2
-rw-r--r--chromium/components/safe_browsing/content/password_protection/password_protection_service_unittest.cc20
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/BUILD.gn33
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.cc36
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.proto23
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc272
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h96
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc50
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.h5
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.cc33
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.h9
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_dom_feature_extractor.cc4
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.cc26
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.h11
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor_unittest.cc39
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_url_feature_extractor.cc3
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc259
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h100
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc241
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer.h120
-rw-r--r--chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc219
-rw-r--r--chromium/components/safe_browsing/content/renderer/threat_dom_details.cc1
-rw-r--r--chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle.cc4
-rw-r--r--chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle.h1
-rw-r--r--chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle_unittest.cc2
-rw-r--r--chromium/components/safe_browsing/content/web_ui/safe_browsing_ui.cc96
-rw-r--r--chromium/components/safe_browsing/content/web_ui/safe_browsing_ui.h35
-rw-r--r--chromium/components/safe_browsing/core/BUILD.gn24
-rw-r--r--chromium/components/safe_browsing/core/browser/download/BUILD.gn29
-rw-r--r--chromium/components/safe_browsing/core/browser/download/DEPS3
-rw-r--r--chromium/components/safe_browsing/core/browser/download/download_stats.cc121
-rw-r--r--chromium/components/safe_browsing/core/browser/download/download_stats.h42
-rw-r--r--chromium/components/safe_browsing/core/browser/download/download_stats_unittest.cc106
-rw-r--r--chromium/components/safe_browsing/core/browser/safe_browsing_token_fetcher.h5
-rw-r--r--chromium/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.cc8
-rw-r--r--chromium/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h1
-rw-r--r--chromium/components/safe_browsing/core/browser/sync/sync_utils.cc2
-rw-r--r--chromium/components/safe_browsing/core/browser/sync/sync_utils_unittest.cc2
-rw-r--r--chromium/components/safe_browsing/core/common/safe_browsing_policy_handler.cc16
-rw-r--r--chromium/components/safe_browsing/core/common/safebrowsing_constants.cc2
-rw-r--r--chromium/components/safe_browsing/core/common/safebrowsing_constants.h4
-rw-r--r--chromium/components/safe_browsing/core/common/visual_utils.cc171
-rw-r--r--chromium/components/safe_browsing/core/common/visual_utils.h16
-rw-r--r--chromium/components/safe_browsing/core/common/visual_utils_unittest.cc328
-rw-r--r--chromium/components/safe_browsing/core/db/util.h1
-rw-r--r--chromium/components/safe_browsing/core/db/v4_get_hash_protocol_manager_unittest.cc1
-rw-r--r--chromium/components/safe_browsing/core/db/v4_local_database_manager.cc10
-rw-r--r--chromium/components/safe_browsing/core/db/v4_local_database_manager.h2
-rw-r--r--chromium/components/safe_browsing/core/db/v4_protocol_manager_util.cc9
-rw-r--r--chromium/components/safe_browsing/core/db/v4_protocol_manager_util.h2
-rw-r--r--chromium/components/safe_browsing/core/db/v4_store.cc54
-rw-r--r--chromium/components/safe_browsing/core/db/v4_update_protocol_manager.h4
-rw-r--r--chromium/components/safe_browsing/core/db/v4_update_protocol_manager_unittest.cc1
-rw-r--r--chromium/components/safe_browsing/core/fbs/BUILD.gn16
-rw-r--r--chromium/components/safe_browsing/core/fbs/client_model.fbs110
-rw-r--r--chromium/components/safe_browsing/core/fbs/csd.fbs22
-rw-r--r--chromium/components/safe_browsing/core/features.cc75
-rw-r--r--chromium/components/safe_browsing/core/features.h54
-rw-r--r--chromium/components/safe_browsing/core/features_unittest.cc93
-rw-r--r--chromium/components/safe_browsing/core/password_protection/DIR_METADATA4
-rw-r--r--chromium/components/safe_browsing/core/password_protection/password_protection_request.cc9
-rw-r--r--chromium/components/safe_browsing/core/password_protection/password_protection_request.h2
-rw-r--r--chromium/components/safe_browsing/core/password_protection/password_protection_service_base.h1
-rw-r--r--chromium/components/safe_browsing/core/proto/client_model.proto32
-rw-r--r--chromium/components/safe_browsing/core/proto/csd.proto38
-rw-r--r--chromium/components/safe_browsing/core/realtime/DIR_METADATA5
-rw-r--r--chromium/components/safe_browsing/core/realtime/policy_engine.cc4
-rw-r--r--chromium/components/safe_browsing/core/realtime/policy_engine_unittest.cc15
-rw-r--r--chromium/components/safe_browsing/core/realtime/url_lookup_service.cc11
-rw-r--r--chromium/components/safe_browsing/core/realtime/url_lookup_service.h5
-rw-r--r--chromium/components/safe_browsing/core/realtime/url_lookup_service_base.cc25
-rw-r--r--chromium/components/safe_browsing/core/realtime/url_lookup_service_base.h15
-rw-r--r--chromium/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc57
-rw-r--r--chromium/components/safe_browsing/core/resources/BUILD.gn7
-rwxr-xr-xchromium/components/safe_browsing/core/resources/gen_file_type_proto.py10
-rw-r--r--chromium/components/safe_browsing/core/verdict_cache_manager.cc50
-rw-r--r--chromium/components/safe_browsing/core/verdict_cache_manager.h16
-rw-r--r--chromium/components/safe_search_api/safe_search/safe_search_url_checker_client.cc4
-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/stub_url_checker.cc4
-rw-r--r--chromium/components/safe_search_api/url_checker.cc1
-rw-r--r--chromium/components/safety_check/BUILD.gn3
-rw-r--r--chromium/components/safety_check/safety_check.cc35
-rw-r--r--chromium/components/safety_check/safety_check.h132
-rw-r--r--chromium/components/scheduling_metrics/thread_metrics.h3
-rw-r--r--chromium/components/scheduling_metrics/total_duration_metric_reporter.cc2
-rw-r--r--chromium/components/scheduling_metrics/total_duration_metric_reporter.h4
-rw-r--r--chromium/components/schema_org/common/time.cc8
-rw-r--r--chromium/components/schema_org/common/time.h4
-rw-r--r--chromium/components/search/OWNERS3
-rw-r--r--chromium/components/search/ntp_features.cc18
-rw-r--r--chromium/components/search/ntp_features.h9
-rw-r--r--chromium/components/search/repeatable_queries/repeatable_queries_service_unittest.cc2
-rw-r--r--chromium/components/search_engines/android/DIR_METADATA3
-rw-r--r--chromium/components/search_engines/android/template_url_service_android.h2
-rw-r--r--chromium/components/search_engines/default_search_manager.cc2
-rw-r--r--chromium/components/search_engines/keyword_table.cc2
-rw-r--r--chromium/components/search_engines/template_url_data.cc5
-rw-r--r--chromium/components/search_engines/template_url_data_util.cc8
-rw-r--r--chromium/components/search_engines/template_url_fetcher.h1
-rw-r--r--chromium/components/search_engines/template_url_service.cc10
-rw-r--r--chromium/components/search_engines/template_url_service.h10
-rw-r--r--chromium/components/search_engines/template_url_unittest.cc24
-rw-r--r--chromium/components/search_provider_logos/google_logo_api.cc2
-rw-r--r--chromium/components/search_provider_logos/logo_common.h6
-rw-r--r--chromium/components/search_provider_logos/logo_service.h6
-rw-r--r--chromium/components/search_provider_logos/logo_service_impl.cc14
-rw-r--r--chromium/components/search_provider_logos/logo_service_impl.h6
-rw-r--r--chromium/components/search_provider_logos/logo_service_impl_unittest.cc68
-rw-r--r--chromium/components/security_interstitials/content/captive_portal_metrics_recorder.h1
-rw-r--r--chromium/components/security_interstitials/content/cert_report_helper.cc1
-rw-r--r--chromium/components/security_interstitials/content/cert_report_helper.h2
-rw-r--r--chromium/components/security_interstitials/content/common_name_mismatch_handler.h1
-rw-r--r--chromium/components/security_interstitials/content/content_metrics_helper.h2
-rw-r--r--chromium/components/security_interstitials/content/origin_policy_ui.cc4
-rw-r--r--chromium/components/security_interstitials/content/origin_policy_ui.h4
-rw-r--r--chromium/components/security_interstitials/content/renderer/security_interstitial_page_controller.cc3
-rw-r--r--chromium/components/security_interstitials/content/renderer/security_interstitial_page_controller.h1
-rw-r--r--chromium/components/security_interstitials/content/ssl_blocking_page_base.h1
-rw-r--r--chromium/components/security_interstitials/content/ssl_error_assistant.cc4
-rw-r--r--chromium/components/security_interstitials/content/ssl_error_assistant.h4
-rw-r--r--chromium/components/security_interstitials/content/ssl_error_assistant_unittest.cc14
-rw-r--r--chromium/components/security_interstitials/content/ssl_error_handler.cc8
-rw-r--r--chromium/components/security_interstitials/content/stateful_ssl_host_state_delegate.cc29
-rw-r--r--chromium/components/security_interstitials/content/stateful_ssl_host_state_delegate.h2
-rw-r--r--chromium/components/security_interstitials/core/metrics_helper.h1
-rw-r--r--chromium/components/security_interstitials/core/mitm_software_ui.h2
-rw-r--r--chromium/components/security_interstitials/core/pref_names.h2
-rw-r--r--chromium/components/security_interstitials/core/safe_browsing_quiet_error_ui.cc1
-rw-r--r--chromium/components/security_state/OWNERS1
-rw-r--r--chromium/components/security_state/ios/insecure_input_tab_helper.h2
-rw-r--r--chromium/components/segmentation_platform/BUILD.gn22
-rw-r--r--chromium/components/segmentation_platform/DEPS10
-rw-r--r--chromium/components/segmentation_platform/DIR_METADATA5
-rw-r--r--chromium/components/segmentation_platform/OWNERS2
-rw-r--r--chromium/components/segmentation_platform/README.md40
-rw-r--r--chromium/components/segmentation_platform/components_unittests.filter22
-rw-r--r--chromium/components/segmentation_platform/internal/BUILD.gn189
-rw-r--r--chromium/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc92
-rw-r--r--chromium/components/segmentation_platform/internal/android/segmentation_platform_service_android.h45
-rw-r--r--chromium/components/segmentation_platform/internal/constants.cc12
-rw-r--r--chromium/components/segmentation_platform/internal/constants.h15
-rw-r--r--chromium/components/segmentation_platform/internal/database/database_maintenance.h23
-rw-r--r--chromium/components/segmentation_platform/internal/database/database_maintenance_impl.cc227
-rw-r--r--chromium/components/segmentation_platform/internal/database/database_maintenance_impl.h100
-rw-r--r--chromium/components/segmentation_platform/internal/database/database_maintenance_impl_unittest.cc203
-rw-r--r--chromium/components/segmentation_platform/internal/database/metadata_utils.cc196
-rw-r--r--chromium/components/segmentation_platform/internal/database/metadata_utils.h80
-rw-r--r--chromium/components/segmentation_platform/internal/database/metadata_utils_unittest.cc419
-rw-r--r--chromium/components/segmentation_platform/internal/database/mock_signal_database.cc13
-rw-r--r--chromium/components/segmentation_platform/internal/database/mock_signal_database.h57
-rw-r--r--chromium/components/segmentation_platform/internal/database/mock_signal_storage_config.cc16
-rw-r--r--chromium/components/segmentation_platform/internal/database/mock_signal_storage_config.h54
-rw-r--r--chromium/components/segmentation_platform/internal/database/segment_info_database.cc149
-rw-r--r--chromium/components/segmentation_platform/internal/database/segment_info_database.h95
-rw-r--r--chromium/components/segmentation_platform/internal/database/segment_info_database_unittest.cc238
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_database.h70
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_database_impl.cc277
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_database_impl.h113
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_database_impl_unittest.cc258
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_key.cc120
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_key.h97
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_key_internal.cc92
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_key_internal.h128
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_key_internal_unittest.cc330
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_key_unittest.cc195
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_storage_config.cc226
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_storage_config.h105
-rw-r--r--chromium/components/segmentation_platform/internal/database/signal_storage_config_unittest.cc254
-rw-r--r--chromium/components/segmentation_platform/internal/database/test_segment_info_database.cc208
-rw-r--r--chromium/components/segmentation_platform/internal/database/test_segment_info_database.h80
-rw-r--r--chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service.cc28
-rw-r--r--chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service.h35
-rw-r--r--chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service_unittest.cc52
-rw-r--r--chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager.cc44
-rw-r--r--chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager.h36
-rw-r--r--chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager_unittest.cc61
-rw-r--r--chromium/components/segmentation_platform/internal/execution/feature_aggregator.h46
-rw-r--r--chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl.cc286
-rw-r--r--chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl.h46
-rw-r--r--chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl_unittest.cc320
-rw-r--r--chromium/components/segmentation_platform/internal/execution/model_execution_manager.h45
-rw-r--r--chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory.cc74
-rw-r--r--chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory.h45
-rw-r--r--chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory_unittest.cc65
-rw-r--r--chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc458
-rw-r--r--chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl.h163
-rw-r--r--chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc722
-rw-r--r--chromium/components/segmentation_platform/internal/execution/model_execution_status.h22
-rw-r--r--chromium/components/segmentation_platform/internal/execution/segmentation_model_executor.cc51
-rw-r--r--chromium/components/segmentation_platform/internal/execution/segmentation_model_executor.h48
-rw-r--r--chromium/components/segmentation_platform/internal/execution/segmentation_model_executor_unittest.cc183
-rw-r--r--chromium/components/segmentation_platform/internal/execution/segmentation_model_handler.cc65
-rw-r--r--chromium/components/segmentation_platform/internal/execution/segmentation_model_handler.h64
-rw-r--r--chromium/components/segmentation_platform/internal/proto/BUILD.gn20
-rw-r--r--chromium/components/segmentation_platform/internal/proto/aggregation.proto79
-rw-r--r--chromium/components/segmentation_platform/internal/proto/model_metadata.proto101
-rw-r--r--chromium/components/segmentation_platform/internal/proto/model_prediction.proto36
-rw-r--r--chromium/components/segmentation_platform/internal/proto/signal.proto24
-rw-r--r--chromium/components/segmentation_platform/internal/proto/signal_storage_config.proto34
-rw-r--r--chromium/components/segmentation_platform/internal/proto/types.proto16
-rw-r--r--chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler.h63
-rw-r--r--chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc143
-rw-r--r--chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.h82
-rw-r--r--chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_unittest.cc163
-rw-r--r--chromium/components/segmentation_platform/internal/segmentation_platform_service_impl.cc226
-rw-r--r--chromium/components/segmentation_platform/internal/segmentation_platform_service_impl.h151
-rw-r--r--chromium/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc218
-rw-r--r--chromium/components/segmentation_platform/internal/selection/segment_selector.h59
-rw-r--r--chromium/components/segmentation_platform/internal/selection/segment_selector_impl.cc190
-rw-r--r--chromium/components/segmentation_platform/internal/selection/segment_selector_impl.h97
-rw-r--r--chromium/components/segmentation_platform/internal/selection/segment_selector_unittest.cc280
-rw-r--r--chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs.cc70
-rw-r--r--chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs.h65
-rw-r--r--chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs_unittest.cc95
-rw-r--r--chromium/components/segmentation_platform/internal/signals/histogram_signal_handler.cc50
-rw-r--r--chromium/components/segmentation_platform/internal/signals/histogram_signal_handler.h67
-rw-r--r--chromium/components/segmentation_platform/internal/signals/histogram_signal_handler_unittest.cc107
-rw-r--r--chromium/components/segmentation_platform/internal/signals/signal_filter_processor.cc72
-rw-r--r--chromium/components/segmentation_platform/internal/signals/signal_filter_processor.h62
-rw-r--r--chromium/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc125
-rw-r--r--chromium/components/segmentation_platform/internal/signals/user_action_signal_handler.cc57
-rw-r--r--chromium/components/segmentation_platform/internal/signals/user_action_signal_handler.h60
-rw-r--r--chromium/components/segmentation_platform/internal/signals/user_action_signal_handler_unittest.cc110
-rw-r--r--chromium/components/segmentation_platform/internal/stats.cc402
-rw-r--r--chromium/components/segmentation_platform/internal/stats.h139
-rw-r--r--chromium/components/segmentation_platform/internal/stats_unittest.cc131
-rw-r--r--chromium/components/segmentation_platform/public/BUILD.gn56
-rw-r--r--chromium/components/segmentation_platform/public/config.cc17
-rw-r--r--chromium/components/segmentation_platform/public/config.h39
-rw-r--r--chromium/components/segmentation_platform/public/segment_selection_result.cc24
-rw-r--r--chromium/components/segmentation_platform/public/segment_selection_result.h34
-rw-r--r--chromium/components/segmentation_platform/public/segmentation_platform_service.cc15
-rw-r--r--chromium/components/segmentation_platform/public/segmentation_platform_service.h68
-rw-r--r--chromium/components/send_tab_to_self/BUILD.gn2
-rw-r--r--chromium/components/send_tab_to_self/OWNERS1
-rw-r--r--chromium/components/send_tab_to_self/features.cc2
-rw-r--r--chromium/components/send_tab_to_self/features.h4
-rw-r--r--chromium/components/send_tab_to_self/metrics_util.cc54
-rw-r--r--chromium/components/send_tab_to_self/metrics_util.h25
-rw-r--r--chromium/components/send_tab_to_self/send_tab_to_self_bridge.cc20
-rw-r--r--chromium/components/send_tab_to_self/send_tab_to_self_bridge.h12
-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.h2
-rw-r--r--chromium/components/send_tab_to_self/send_tab_to_self_sync_service.h1
-rw-r--r--chromium/components/send_tab_to_self/target_device_info_unittest.cc2
-rw-r--r--chromium/components/services/app_service/README.md4
-rw-r--r--chromium/components/services/app_service/app_service_impl.cc16
-rw-r--r--chromium/components/services/app_service/app_service_impl.h2
-rw-r--r--chromium/components/services/app_service/app_service_impl_unittest.cc40
-rw-r--r--chromium/components/services/app_service/public/cpp/BUILD.gn9
-rw-r--r--chromium/components/services/app_service/public/cpp/app_update_unittest.cc2
-rw-r--r--chromium/components/services/app_service/public/cpp/file_handler.cc12
-rw-r--r--chromium/components/services/app_service/public/cpp/instance.cc33
-rw-r--r--chromium/components/services/app_service/public/cpp/instance.h39
-rw-r--r--chromium/components/services/app_service/public/cpp/instance_registry.cc51
-rw-r--r--chromium/components/services/app_service/public/cpp/instance_registry.h29
-rw-r--r--chromium/components/services/app_service/public/cpp/instance_registry_unittest.cc36
-rw-r--r--chromium/components/services/app_service/public/cpp/instance_update.cc24
-rw-r--r--chromium/components/services/app_service/public/cpp/instance_update.h2
-rw-r--r--chromium/components/services/app_service/public/cpp/instance_update_unittest.cc73
-rw-r--r--chromium/components/services/app_service/public/cpp/intent_filter_util.cc47
-rw-r--r--chromium/components/services/app_service/public/cpp/intent_filter_util.h4
-rw-r--r--chromium/components/services/app_service/public/cpp/intent_util.cc53
-rw-r--r--chromium/components/services/app_service/public/cpp/intent_util.h11
-rw-r--r--chromium/components/services/app_service/public/cpp/intent_util_unittest.cc1
-rw-r--r--chromium/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc24
-rw-r--r--chromium/components/services/app_service/public/cpp/preferred_apps_list.cc116
-rw-r--r--chromium/components/services/app_service/public/cpp/preferred_apps_list.h55
-rw-r--r--chromium/components/services/app_service/public/cpp/preferred_apps_list_unittest.cc66
-rw-r--r--chromium/components/services/app_service/public/cpp/protocol_handler_info.h2
-rw-r--r--chromium/components/services/app_service/public/cpp/publisher_base.cc4
-rw-r--r--chromium/components/services/app_service/public/cpp/publisher_base.h4
-rw-r--r--chromium/components/services/app_service/public/cpp/share_target.cc5
-rw-r--r--chromium/components/services/app_service/public/cpp/types_util.cc25
-rw-r--r--chromium/components/services/app_service/public/cpp/types_util.h18
-rw-r--r--chromium/components/services/app_service/public/cpp/url_handler_info.cc10
-rw-r--r--chromium/components/services/app_service/public/mojom/types.mojom37
-rw-r--r--chromium/components/services/filesystem/OWNERS0
-rw-r--r--chromium/components/services/filesystem/directory_impl.cc4
-rw-r--r--chromium/components/services/filesystem/directory_impl_unittest.cc3
-rw-r--r--chromium/components/services/filesystem/file_impl.cc12
-rw-r--r--chromium/components/services/filesystem/file_impl.h1
-rw-r--r--chromium/components/services/filesystem/file_impl_unittest.cc11
-rw-r--r--chromium/components/services/font/font_service_app.cc2
-rw-r--r--chromium/components/services/font/fontconfig_matching.cc21
-rw-r--r--chromium/components/services/font/fontconfig_matching.h8
-rw-r--r--chromium/components/services/heap_profiling/json_exporter.cc2
-rw-r--r--chromium/components/services/heap_profiling/json_exporter_unittest.cc8
-rw-r--r--chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.cc36
-rw-r--r--chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.h4
-rw-r--r--chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl_unittest.cc34
-rw-r--r--chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl.cc40
-rw-r--r--chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl.h8
-rw-r--r--chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl_unittest.cc8
-rw-r--r--chromium/components/services/patch/file_patcher_impl.h2
-rw-r--r--chromium/components/services/print_compositor/print_compositor_impl.h2
-rw-r--r--chromium/components/services/print_compositor/public/mojom/BUILD.gn1
-rw-r--r--chromium/components/services/quarantine/BUILD.gn8
-rw-r--r--chromium/components/services/quarantine/DEPS1
-rw-r--r--chromium/components/services/quarantine/quarantine.cc15
-rw-r--r--chromium/components/services/quarantine/quarantine.h10
-rw-r--r--chromium/components/services/quarantine/quarantine_chromeos.cc44
-rw-r--r--chromium/components/services/quarantine/quarantine_impl.cc68
-rw-r--r--chromium/components/services/quarantine/quarantine_mac.mm20
-rw-r--r--chromium/components/services/quarantine/quarantine_mac_unittest.mm51
-rw-r--r--chromium/components/services/quarantine/quarantine_unittest.cc24
-rw-r--r--chromium/components/services/quarantine/quarantine_win.cc25
-rw-r--r--chromium/components/services/quarantine/quarantine_win_unittest.cc106
-rw-r--r--chromium/components/services/quarantine/test_support.h2
-rw-r--r--chromium/components/services/storage/BUILD.gn2
-rw-r--r--chromium/components/services/storage/dom_storage/DIR_METADATA1
-rw-r--r--chromium/components/services/storage/dom_storage/async_dom_storage_database.cc7
-rw-r--r--chromium/components/services/storage/dom_storage/async_dom_storage_database.h4
-rw-r--r--chromium/components/services/storage/dom_storage/dom_storage_database.cc10
-rw-r--r--chromium/components/services/storage/dom_storage/dom_storage_database.h14
-rw-r--r--chromium/components/services/storage/dom_storage/dom_storage_database_unittest.cc6
-rw-r--r--chromium/components/services/storage/dom_storage/legacy_dom_storage_database.cc4
-rw-r--r--chromium/components/services/storage/dom_storage/legacy_dom_storage_database.h2
-rw-r--r--chromium/components/services/storage/dom_storage/legacy_dom_storage_database_unittest.cc8
-rw-r--r--chromium/components/services/storage/dom_storage/local_storage_impl.cc12
-rw-r--r--chromium/components/services/storage/dom_storage/local_storage_impl_unittest.cc90
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_area_impl.cc39
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_area_impl.h14
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_area_impl_unittest.cc23
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_data_map.h2
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_data_map_unittest.cc2
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_impl.cc2
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_impl_unittest.cc60
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_metadata.cc6
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_metadata.h4
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_metadata_unittest.cc4
-rw-r--r--chromium/components/services/storage/dom_storage/session_storage_namespace_impl_unittest.cc8
-rw-r--r--chromium/components/services/storage/dom_storage/storage_area_impl.cc12
-rw-r--r--chromium/components/services/storage/dom_storage/storage_area_impl.h10
-rw-r--r--chromium/components/services/storage/dom_storage/storage_area_impl_unittest.cc80
-rw-r--r--chromium/components/services/storage/dom_storage/storage_area_test_util.cc4
-rw-r--r--chromium/components/services/storage/dom_storage/storage_area_test_util.h10
-rw-r--r--chromium/components/services/storage/dom_storage/testing_legacy_session_storage_database.cc4
-rw-r--r--chromium/components/services/storage/indexed_db/DIR_METADATA1
-rw-r--r--chromium/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.cc22
-rw-r--r--chromium/components/services/storage/indexed_db/scopes/disjoint_range_lock_manager.h2
-rw-r--r--chromium/components/services/storage/indexed_db/scopes/leveldb_scope.cc2
-rw-r--r--chromium/components/services/storage/indexed_db/scopes/leveldb_scopes.cc2
-rw-r--r--chromium/components/services/storage/indexed_db/scopes/leveldb_scopes.h1
-rw-r--r--chromium/components/services/storage/indexed_db/scopes/scope_lock.h1
-rw-r--r--chromium/components/services/storage/indexed_db/scopes/scope_lock_range.h2
-rw-r--r--chromium/components/services/storage/indexed_db/scopes/scopes_lock_manager.h1
-rw-r--r--chromium/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h2
-rw-r--r--chromium/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_transaction_unittest.cc4
-rw-r--r--chromium/components/services/storage/partition_impl.cc2
-rw-r--r--chromium/components/services/storage/partition_impl.h8
-rw-r--r--chromium/components/services/storage/partition_impl_unittest.cc2
-rw-r--r--chromium/components/services/storage/public/cpp/BUILD.gn26
-rw-r--r--chromium/components/services/storage/public/cpp/constants.cc5
-rw-r--r--chromium/components/services/storage/public/cpp/constants.h3
-rw-r--r--chromium/components/services/storage/public/cpp/filesystem/file_error_or.h6
-rw-r--r--chromium/components/services/storage/public/cpp/filesystem/filesystem_impl.cc2
-rw-r--r--chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy.cc16
-rw-r--r--chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy.h6
-rw-r--r--chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy_unittest.cc8
-rw-r--r--chromium/components/services/storage/public/cpp/quota_error_or.h54
-rw-r--r--chromium/components/services/storage/public/cpp/storage_key.cc32
-rw-r--r--chromium/components/services/storage/public/cpp/storage_key.h61
-rw-r--r--chromium/components/services/storage/public/cpp/storage_key_unittest.cc115
-rw-r--r--chromium/components/services/storage/public/mojom/BUILD.gn13
-rw-r--r--chromium/components/services/storage/public/mojom/service_worker_storage_control.mojom51
-rw-r--r--chromium/components/services/storage/public/mojom/storage_key/BUILD.gn31
-rw-r--r--chromium/components/services/storage/public/mojom/storage_key/OWNERS4
-rw-r--r--chromium/components/services/storage/public/mojom/storage_key/storage_key.mojom12
-rw-r--r--chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits.cc22
-rw-r--r--chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits.h31
-rw-r--r--chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits_unittest.cc36
-rw-r--r--chromium/components/services/storage/sandboxed_vfs_delegate.cc8
-rw-r--r--chromium/components/services/storage/sandboxed_vfs_delegate.h2
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_database.cc252
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_database.h43
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_database.proto1
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_database_unittest.cc460
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_disk_cache.cc2
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_resource_ops.cc6
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_storage.cc228
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_storage.h95
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_storage_control_impl.cc71
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_storage_control_impl.h37
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_storage_control_impl_unittest.cc194
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_storage_test_utils.h4
-rw-r--r--chromium/components/services/storage/service_worker/service_worker_storage_unittest.cc135
-rw-r--r--chromium/components/services/storage/storage_service_impl.cc2
-rw-r--r--chromium/components/services/storage/storage_service_impl.h2
-rw-r--r--chromium/components/services/storage/storage_service_impl_unittest.cc4
-rw-r--r--chromium/components/services/unzip/public/cpp/unzip.h2
-rw-r--r--chromium/components/services/unzip/unzipper_impl.h2
-rw-r--r--chromium/components/session_manager/README.md2
-rw-r--r--chromium/components/session_manager/core/DIR_METADATA3
-rw-r--r--chromium/components/session_manager/core/OWNERS0
-rw-r--r--chromium/components/sessions/content/OWNERS0
-rw-r--r--chromium/components/sessions/content/content_serialized_navigation_builder.cc8
-rw-r--r--chromium/components/sessions/content/session_tab_helper_delegate.h2
-rw-r--r--chromium/components/sessions/core/base_session_service_commands.cc4
-rw-r--r--chromium/components/sessions/core/base_session_service_commands.h4
-rw-r--r--chromium/components/sessions/core/command_storage_backend.cc6
-rw-r--r--chromium/components/sessions/core/command_storage_backend.h9
-rw-r--r--chromium/components/sessions/core/command_storage_backend_unittest.cc2
-rw-r--r--chromium/components/sessions/core/live_tab_context.h8
-rw-r--r--chromium/components/sessions/core/serialized_navigation_entry.h8
-rw-r--r--chromium/components/sessions/core/serialized_user_agent_override.h4
-rw-r--r--chromium/components/sessions/core/session_service_commands.cc12
-rw-r--r--chromium/components/sessions/core/session_service_commands.h4
-rw-r--r--chromium/components/sessions/core/session_types.h4
-rw-r--r--chromium/components/sessions/core/tab_restore_service.h8
-rw-r--r--chromium/components/sessions/core/tab_restore_service_helper.cc24
-rw-r--r--chromium/components/sessions/core/tab_restore_service_helper.h4
-rw-r--r--chromium/components/sessions/core/tab_restore_service_impl.cc8
-rw-r--r--chromium/components/sessions/core/tab_restore_service_impl.h4
-rw-r--r--chromium/components/sessions/ios/OWNERS0
-rw-r--r--chromium/components/shared_highlighting/core/common/shared_highlighting_features.cc7
-rw-r--r--chromium/components/shared_highlighting/core/common/shared_highlighting_features.h9
-rw-r--r--chromium/components/shared_highlighting/core/common/shared_highlighting_metrics.cc5
-rw-r--r--chromium/components/shared_highlighting/core/common/shared_highlighting_metrics.h13
-rw-r--r--chromium/components/shared_highlighting/core/common/text_fragment.cc12
-rw-r--r--chromium/components/shared_highlighting/core/common/text_fragment.h10
-rw-r--r--chromium/components/shared_highlighting/core/common/text_fragment_unittest.cc4
-rw-r--r--chromium/components/shared_highlighting/core/common/text_fragments_utils.cc26
-rw-r--r--chromium/components/shared_highlighting/core/common/text_fragments_utils.h23
-rw-r--r--chromium/components/shared_highlighting/core/common/text_fragments_utils_unittest.cc25
-rw-r--r--chromium/components/signin/OWNERS1
-rw-r--r--chromium/components/signin/core/browser/BUILD.gn27
-rw-r--r--chromium/components/signin/core/browser/DEPS10
-rw-r--r--chromium/components/signin/core/browser/about_signin_internals.cc24
-rw-r--r--chromium/components/signin/core/browser/account_investigator.cc6
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor.cc337
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor.h110
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_delegate.cc4
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_delegate.h6
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_throttler.cc113
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_throttler.h61
-rw-r--r--chromium/components/signin/core/browser/account_reconcilor_unittest.cc1017
-rw-r--r--chromium/components/signin/core/browser/chrome_connected_header_helper.cc19
-rw-r--r--chromium/components/signin/core/browser/chrome_connected_header_helper.h4
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc7
-rw-r--r--chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h6
-rw-r--r--chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.cc11
-rw-r--r--chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.h1
-rw-r--r--chromium/components/signin/core/browser/signin_error_controller.h2
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper.cc8
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper.h17
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper_unittest.cc109
-rw-r--r--chromium/components/signin/core/browser/signin_internals_util.h1
-rw-r--r--chromium/components/signin/internal/identity_manager/BUILD.gn11
-rw-r--r--chromium/components/signin/internal/identity_manager/account_info_util.cc8
-rw-r--r--chromium/components/signin/internal/identity_manager/account_info_util.h4
-rw-r--r--chromium/components/signin/internal/identity_manager/account_info_util_unittest.cc14
-rw-r--r--chromium/components/signin/internal/identity_manager/account_tracker_service.cc2
-rw-r--r--chromium/components/signin/internal/identity_manager/account_tracker_service_unittest.cc6
-rw-r--r--chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc9
-rw-r--r--chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h2
-rw-r--r--chromium/components/signin/internal/identity_manager/accounts_mutator_impl.cc6
-rw-r--r--chromium/components/signin/internal/identity_manager/accounts_mutator_impl.h4
-rw-r--r--chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.cc5
-rw-r--r--chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.h1
-rw-r--r--chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc2
-rw-r--r--chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h2
-rw-r--r--chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc36
-rw-r--r--chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service.h19
-rw-r--r--chromium/components/signin/internal/identity_manager/gaia_cookie_manager_service_unittest.cc150
-rw-r--r--chromium/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate.cc35
-rw-r--r--chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.h1
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_manager.cc3
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_manager.h3
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.cc49
-rw-r--r--chromium/components/signin/internal/identity_manager/primary_account_mutator_impl.h6
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.cc49
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h8
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h3
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc8
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.h6
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.cc19
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h2
-rw-r--r--chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm2
-rw-r--r--chromium/components/signin/ios/DIR_METADATA3
-rw-r--r--chromium/components/signin/ios/browser/account_consistency_service.h20
-rw-r--r--chromium/components/signin/ios/browser/account_consistency_service.mm139
-rw-r--r--chromium/components/signin/ios/browser/account_consistency_service_unittest.mm229
-rw-r--r--chromium/components/signin/ios/browser/features.cc3
-rw-r--r--chromium/components/signin/ios/browser/features.h3
-rw-r--r--chromium/components/signin/ios/browser/manage_accounts_delegate.h4
-rw-r--r--chromium/components/signin/public/android/BUILD.gn22
-rw-r--r--chromium/components/signin/public/android/DEPS1
-rw-r--r--chromium/components/signin/public/android/DIR_METADATA5
-rw-r--r--chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountManagerFacadeImplTest.java257
-rw-r--r--chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountRenameCheckerTest.java62
-rw-r--r--chromium/components/signin/public/android/junit/src/org/chromium/components/signin/ObservableValueTest.java109
-rw-r--r--chromium/components/signin/public/android/junit/src/org/chromium/components/signin/identitymanager/AccountInfoServiceTest.java5
-rw-r--r--chromium/components/signin/public/android/junit/src/org/chromium/components/signin/identitymanager/AccountTrackerServiceTest.java (renamed from chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountTrackerServiceTest.java)16
-rw-r--r--chromium/components/signin/public/base/account_consistency_method.cc16
-rw-r--r--chromium/components/signin/public/base/account_consistency_method.h14
-rw-r--r--chromium/components/signin/public/base/multilogin_parameters.cc3
-rw-r--r--chromium/components/signin/public/base/multilogin_parameters.h8
-rw-r--r--chromium/components/signin/public/base/signin_client.h5
-rw-r--r--chromium/components/signin/public/base/signin_metrics.cc13
-rw-r--r--chromium/components/signin/public/base/signin_metrics.h45
-rw-r--r--chromium/components/signin/public/base/signin_metrics_unittest.cc4
-rw-r--r--chromium/components/signin/public/base/signin_pref_names.cc4
-rw-r--r--chromium/components/signin/public/base/signin_pref_names.h1
-rw-r--r--chromium/components/signin/public/base/signin_switches.cc10
-rw-r--r--chromium/components/signin/public/base/signin_switches.h7
-rw-r--r--chromium/components/signin/public/base/test_signin_client.cc6
-rw-r--r--chromium/components/signin/public/base/test_signin_client.h6
-rw-r--r--chromium/components/signin/public/identity_manager/access_token_fetcher.cc1
-rw-r--r--chromium/components/signin/public/identity_manager/account_info.h2
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_cookie_mutator.h4
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_cookie_mutator_unittest.cc1
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_mutator.h6
-rw-r--r--chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc14
-rw-r--r--chromium/components/signin/public/identity_manager/device_accounts_synchronizer.h4
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager.cc42
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager.h23
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager_builder.cc8
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager_builder.h28
-rw-r--r--chromium/components/signin/public/identity_manager/identity_manager_unittest.cc51
-rw-r--r--chromium/components/signin/public/identity_manager/identity_mutator.cc20
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_environment.cc26
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_environment.h6
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_utils.cc64
-rw-r--r--chromium/components/signin/public/identity_manager/identity_test_utils.h21
-rw-r--r--chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h1
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_access_token_fetcher.h2
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_mutator.h14
-rw-r--r--chromium/components/signin/public/identity_manager/primary_account_mutator_unittest.cc18
-rw-r--r--chromium/components/signin/public/webdata/token_web_data.cc17
-rw-r--r--chromium/components/signin/public/webdata/token_web_data.h2
-rw-r--r--chromium/components/site_isolation/BUILD.gn1
-rw-r--r--chromium/components/site_isolation/features.cc14
-rw-r--r--chromium/components/site_isolation/features.h1
-rw-r--r--chromium/components/site_isolation/pref_names.cc14
-rw-r--r--chromium/components/site_isolation/pref_names.h3
-rw-r--r--chromium/components/site_isolation/site_isolation_policy.cc226
-rw-r--r--chromium/components/site_isolation/site_isolation_policy.h45
-rw-r--r--chromium/components/site_isolation/site_isolation_policy_unittest.cc204
-rw-r--r--chromium/components/soda/BUILD.gn31
-rw-r--r--chromium/components/soda/DEPS7
-rw-r--r--chromium/components/soda/OWNERS2
-rw-r--r--chromium/components/soda/constants.cc38
-rw-r--r--chromium/components/soda/constants.h10
-rw-r--r--chromium/components/soda/pref_names.cc5
-rw-r--r--chromium/components/soda/pref_names.h1
-rw-r--r--chromium/components/soda/soda_installer.cc156
-rw-r--r--chromium/components/soda/soda_installer.h167
-rw-r--r--chromium/components/soda/soda_installer_impl_chromeos.cc199
-rw-r--r--chromium/components/soda/soda_installer_impl_chromeos.h95
-rw-r--r--chromium/components/speech/chunked_byte_buffer.h1
-rw-r--r--chromium/components/speech/upstream_loader.cc1
-rw-r--r--chromium/components/spellcheck/browser/pref_names.h6
-rw-r--r--chromium/components/spellcheck/browser/spelling_service_client.cc9
-rw-r--r--chromium/components/spellcheck/common/spellcheck_common.cc5
-rw-r--r--chromium/components/spellcheck/renderer/empty_local_interface_provider.h6
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck.cc4
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc4
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_panel.h6
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_provider_unittest.cc60
-rw-r--r--chromium/components/spellcheck/renderer/spellcheck_unittest.cc24
-rw-r--r--chromium/components/sqlite_proto/key_value_data.h10
-rw-r--r--chromium/components/sqlite_proto/key_value_data_unittest.cc7
-rw-r--r--chromium/components/sqlite_proto/proto_table_manager.h1
-rw-r--r--chromium/components/sqlite_proto/proto_table_manager_unittest.cc4
-rw-r--r--chromium/components/ssl_errors/error_info.h6
-rw-r--r--chromium/components/startup_metric_utils/browser/startup_metric_utils.cc33
-rw-r--r--chromium/components/startup_metric_utils/browser/startup_metric_utils.h5
-rw-r--r--chromium/components/storage_monitor/mtp_manager_client_chromeos_unittest.cc10
-rw-r--r--chromium/components/storage_monitor/removable_device_constants.h2
-rw-r--r--chromium/components/storage_monitor/storage_info_utils.cc3
-rw-r--r--chromium/components/storage_monitor/storage_monitor_chromeos_unittest.cc2
-rw-r--r--chromium/components/storage_monitor/storage_monitor_mac.mm7
-rw-r--r--chromium/components/storage_monitor/storage_monitor_win.cc19
-rw-r--r--chromium/components/storage_monitor/storage_monitor_win.h22
-rw-r--r--chromium/components/storage_monitor/storage_monitor_win_unittest.cc17
-rw-r--r--chromium/components/storage_monitor/test_storage_monitor_win.cc11
-rw-r--r--chromium/components/storage_monitor/test_storage_monitor_win.h6
-rw-r--r--chromium/components/storage_monitor/test_volume_mount_watcher_win.cc8
-rw-r--r--chromium/components/strings/components_chromium_strings_gu.xtb2
-rw-r--r--chromium/components/strings/components_chromium_strings_ky.xtb2
-rw-r--r--chromium/components/strings/components_chromium_strings_te.xtb2
-rw-r--r--chromium/components/strings/components_google_chrome_strings_gu.xtb2
-rw-r--r--chromium/components/strings/components_google_chrome_strings_ky.xtb2
-rw-r--r--chromium/components/strings/components_google_chrome_strings_te.xtb2
-rw-r--r--chromium/components/strings/components_strings_af.xtb86
-rw-r--r--chromium/components/strings/components_strings_am.xtb90
-rw-r--r--chromium/components/strings/components_strings_ar.xtb90
-rw-r--r--chromium/components/strings/components_strings_as.xtb86
-rw-r--r--chromium/components/strings/components_strings_az.xtb86
-rw-r--r--chromium/components/strings/components_strings_be.xtb86
-rw-r--r--chromium/components/strings/components_strings_bg.xtb86
-rw-r--r--chromium/components/strings/components_strings_bn.xtb88
-rw-r--r--chromium/components/strings/components_strings_bs.xtb88
-rw-r--r--chromium/components/strings/components_strings_ca.xtb90
-rw-r--r--chromium/components/strings/components_strings_cs.xtb86
-rw-r--r--chromium/components/strings/components_strings_da.xtb86
-rw-r--r--chromium/components/strings/components_strings_de.xtb86
-rw-r--r--chromium/components/strings/components_strings_el.xtb88
-rw-r--r--chromium/components/strings/components_strings_en-GB.xtb86
-rw-r--r--chromium/components/strings/components_strings_es-419.xtb90
-rw-r--r--chromium/components/strings/components_strings_es.xtb88
-rw-r--r--chromium/components/strings/components_strings_et.xtb86
-rw-r--r--chromium/components/strings/components_strings_eu.xtb88
-rw-r--r--chromium/components/strings/components_strings_fa.xtb88
-rw-r--r--chromium/components/strings/components_strings_fi.xtb86
-rw-r--r--chromium/components/strings/components_strings_fil.xtb86
-rw-r--r--chromium/components/strings/components_strings_fr-CA.xtb92
-rw-r--r--chromium/components/strings/components_strings_fr.xtb86
-rw-r--r--chromium/components/strings/components_strings_gl.xtb90
-rw-r--r--chromium/components/strings/components_strings_gu.xtb114
-rw-r--r--chromium/components/strings/components_strings_hi.xtb93
-rw-r--r--chromium/components/strings/components_strings_hr.xtb90
-rw-r--r--chromium/components/strings/components_strings_hu.xtb86
-rw-r--r--chromium/components/strings/components_strings_hy.xtb108
-rw-r--r--chromium/components/strings/components_strings_id.xtb88
-rw-r--r--chromium/components/strings/components_strings_is.xtb86
-rw-r--r--chromium/components/strings/components_strings_it.xtb86
-rw-r--r--chromium/components/strings/components_strings_iw.xtb86
-rw-r--r--chromium/components/strings/components_strings_ja.xtb92
-rw-r--r--chromium/components/strings/components_strings_ka.xtb90
-rw-r--r--chromium/components/strings/components_strings_kk.xtb86
-rw-r--r--chromium/components/strings/components_strings_km.xtb86
-rw-r--r--chromium/components/strings/components_strings_kn.xtb86
-rw-r--r--chromium/components/strings/components_strings_ko.xtb86
-rw-r--r--chromium/components/strings/components_strings_ky.xtb98
-rw-r--r--chromium/components/strings/components_strings_lo.xtb86
-rw-r--r--chromium/components/strings/components_strings_lt.xtb86
-rw-r--r--chromium/components/strings/components_strings_lv.xtb92
-rw-r--r--chromium/components/strings/components_strings_mk.xtb92
-rw-r--r--chromium/components/strings/components_strings_ml.xtb94
-rw-r--r--chromium/components/strings/components_strings_mn.xtb86
-rw-r--r--chromium/components/strings/components_strings_mr.xtb108
-rw-r--r--chromium/components/strings/components_strings_ms.xtb86
-rw-r--r--chromium/components/strings/components_strings_my.xtb86
-rw-r--r--chromium/components/strings/components_strings_ne.xtb94
-rw-r--r--chromium/components/strings/components_strings_nl.xtb86
-rw-r--r--chromium/components/strings/components_strings_no.xtb86
-rw-r--r--chromium/components/strings/components_strings_or.xtb86
-rw-r--r--chromium/components/strings/components_strings_pa.xtb90
-rw-r--r--chromium/components/strings/components_strings_pl.xtb86
-rw-r--r--chromium/components/strings/components_strings_pt-BR.xtb86
-rw-r--r--chromium/components/strings/components_strings_pt-PT.xtb86
-rw-r--r--chromium/components/strings/components_strings_ro.xtb88
-rw-r--r--chromium/components/strings/components_strings_ru.xtb92
-rw-r--r--chromium/components/strings/components_strings_si.xtb86
-rw-r--r--chromium/components/strings/components_strings_sk.xtb86
-rw-r--r--chromium/components/strings/components_strings_sl.xtb86
-rw-r--r--chromium/components/strings/components_strings_sq.xtb88
-rw-r--r--chromium/components/strings/components_strings_sr-Latn.xtb86
-rw-r--r--chromium/components/strings/components_strings_sr.xtb86
-rw-r--r--chromium/components/strings/components_strings_sv.xtb88
-rw-r--r--chromium/components/strings/components_strings_sw.xtb86
-rw-r--r--chromium/components/strings/components_strings_ta.xtb108
-rw-r--r--chromium/components/strings/components_strings_te.xtb152
-rw-r--r--chromium/components/strings/components_strings_th.xtb90
-rw-r--r--chromium/components/strings/components_strings_tr.xtb86
-rw-r--r--chromium/components/strings/components_strings_uk.xtb94
-rw-r--r--chromium/components/strings/components_strings_ur.xtb86
-rw-r--r--chromium/components/strings/components_strings_uz.xtb86
-rw-r--r--chromium/components/strings/components_strings_vi.xtb86
-rw-r--r--chromium/components/strings/components_strings_zh-CN.xtb90
-rw-r--r--chromium/components/strings/components_strings_zh-HK.xtb88
-rw-r--r--chromium/components/strings/components_strings_zh-TW.xtb88
-rw-r--r--chromium/components/strings/components_strings_zu.xtb86
-rw-r--r--chromium/components/subresource_filter/android/BUILD.gn16
-rw-r--r--chromium/components/subresource_filter/android/DEPS9
-rw-r--r--chromium/components/subresource_filter/android/subresource_filter_feature_list.cc10
-rw-r--r--chromium/components/subresource_filter/content/browser/BUILD.gn26
-rw-r--r--chromium/components/subresource_filter/content/browser/DEPS3
-rw-r--r--chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc4
-rw-r--r--chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h12
-rw-r--r--chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc6
-rw-r--r--chromium/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.cc2
-rw-r--r--chromium/components/subresource_filter/content/browser/ads_blocked_infobar.cc (renamed from chromium/components/subresource_filter/android/ads_blocked_infobar.cc)2
-rw-r--r--chromium/components/subresource_filter/content/browser/ads_blocked_infobar.h (renamed from chromium/components/subresource_filter/android/ads_blocked_infobar.h)8
-rw-r--r--chromium/components/subresource_filter/content/browser/ads_blocked_infobar_delegate.cc (renamed from chromium/components/subresource_filter/android/ads_blocked_infobar_delegate.cc)4
-rw-r--r--chromium/components/subresource_filter/content/browser/ads_blocked_infobar_delegate.h (renamed from chromium/components/subresource_filter/android/ads_blocked_infobar_delegate.h)6
-rw-r--r--chromium/components/subresource_filter/content/browser/ads_intervention_manager.cc6
-rw-r--r--chromium/components/subresource_filter/content/browser/ads_intervention_manager.h8
-rw-r--r--chromium/components/subresource_filter/content/browser/ads_intervention_manager_unittest.cc4
-rw-r--r--chromium/components/subresource_filter/content/browser/async_document_subresource_filter.h7
-rw-r--r--chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc102
-rw-r--r--chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h45
-rw-r--r--chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc279
-rw-r--r--chromium/components/subresource_filter/content/browser/profile_interaction_manager.cc20
-rw-r--r--chromium/components/subresource_filter/content/browser/profile_interaction_manager.h9
-rw-r--r--chromium/components/subresource_filter/content/browser/ruleset_publisher.h2
-rw-r--r--chromium/components/subresource_filter/content/browser/ruleset_publisher_impl.h2
-rw-r--r--chromium/components/subresource_filter/content/browser/ruleset_service.h1
-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_unittest.cc4
-rw-r--r--chromium/components/subresource_filter/content/browser/subresource_filter_client.h32
-rw-r--r--chromium/components/subresource_filter/content/browser/subresource_filter_content_settings_manager.cc6
-rw-r--r--chromium/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.cc14
-rw-r--r--chromium/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h12
-rw-r--r--chromium/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc6
-rw-r--r--chromium/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc58
-rw-r--r--chromium/components/subresource_filter/content/browser/subresource_filter_test_harness.cc15
-rw-r--r--chromium/components/subresource_filter/content/browser/subresource_filter_test_harness.h12
-rw-r--r--chromium/components/subresource_filter/content/browser/test_subresource_filter_client.h68
-rw-r--r--chromium/components/subresource_filter/content/browser/throttle_manager_test_support.cc (renamed from chromium/components/subresource_filter/content/browser/test_subresource_filter_client.cc)23
-rw-r--r--chromium/components/subresource_filter/content/browser/throttle_manager_test_support.h50
-rw-r--r--chromium/components/subresource_filter/content/browser/verified_ruleset_dealer_unittest.cc1
-rw-r--r--chromium/components/subresource_filter/content/common/ruleset_dealer.h2
-rw-r--r--chromium/components/subresource_filter/content/common/subresource_filter_utils.cc2
-rw-r--r--chromium/components/subresource_filter/content/common/subresource_filter_utils.h6
-rw-r--r--chromium/components/subresource_filter/content/mojom/subresource_filter_agent.mojom14
-rw-r--r--chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc37
-rw-r--r--chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h17
-rw-r--r--chromium/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc64
-rw-r--r--chromium/components/subresource_filter/content/renderer/unverified_ruleset_dealer.h2
-rw-r--r--chromium/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc1
-rw-r--r--chromium/components/subresource_filter/core/browser/subresource_filter_features.h1
-rw-r--r--chromium/components/subresource_filter/core/common/indexed_ruleset.cc20
-rw-r--r--chromium/components/subresource_filter/core/common/scoped_timers.h6
-rw-r--r--chromium/components/subresource_filter/core/common/test_ruleset_creator.cc3
-rw-r--r--chromium/components/subresource_filter/core/common/test_ruleset_utils.cc10
-rw-r--r--chromium/components/subresource_filter/core/common/time_measurements.h6
-rw-r--r--chromium/components/subresource_filter/tools/filter_tool_main.cc15
-rw-r--r--chromium/components/subresource_filter/tools/ruleset_converter/rule_stream.cc3
-rw-r--r--chromium/components/subresource_filter/tools/ruleset_converter/rule_stream.h1
-rw-r--r--chromium/components/subresource_redirect/common/subresource_redirect_result.h32
-rw-r--r--chromium/components/subresource_redirect/subresource_redirect_browser_test_util.cc2
-rw-r--r--chromium/components/suggestions/suggestions_service.h6
-rw-r--r--chromium/components/suggestions/suggestions_service_impl.cc4
-rw-r--r--chromium/components/suggestions/suggestions_service_impl.h4
-rw-r--r--chromium/components/suggestions/suggestions_store.h2
-rw-r--r--chromium/components/sync/BUILD.gn2
-rw-r--r--chromium/components/sync/base/BUILD.gn1
-rw-r--r--chromium/components/sync/base/ordinal.h1
-rw-r--r--chromium/components/sync/driver/BUILD.gn9
-rw-r--r--chromium/components/sync/engine/BUILD.gn5
-rw-r--r--chromium/components/sync/nigori/BUILD.gn2
-rw-r--r--chromium/components/sync/protocol/protocol_sources.gni2
-rw-r--r--chromium/components/sync/trusted_vault/BUILD.gn2
-rw-r--r--chromium/components/sync_bookmarks/bookmark_local_changes_builder.cc17
-rw-r--r--chromium/components/sync_bookmarks/bookmark_local_changes_builder.h2
-rw-r--r--chromium/components/sync_bookmarks/bookmark_model_merger.cc93
-rw-r--r--chromium/components/sync_bookmarks/bookmark_model_merger.h5
-rw-r--r--chromium/components/sync_bookmarks/bookmark_model_merger_unittest.cc109
-rw-r--r--chromium/components/sync_bookmarks/bookmark_model_observer_impl.cc23
-rw-r--r--chromium/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc24
-rw-r--r--chromium/components/sync_bookmarks/bookmark_model_type_processor.cc4
-rw-r--r--chromium/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc235
-rw-r--r--chromium/components/sync_bookmarks/bookmark_remote_updates_handler.cc85
-rw-r--r--chromium/components/sync_bookmarks/bookmark_remote_updates_handler.h4
-rw-r--r--chromium/components/sync_bookmarks/bookmark_remote_updates_handler_unittest.cc83
-rw-r--r--chromium/components/sync_bookmarks/bookmark_specifics_conversions.cc18
-rw-r--r--chromium/components/sync_bookmarks/bookmark_specifics_conversions_unittest.cc67
-rw-r--r--chromium/components/sync_bookmarks/switches.cc6
-rw-r--r--chromium/components/sync_bookmarks/switches.h4
-rw-r--r--chromium/components/sync_bookmarks/synced_bookmark_tracker.cc12
-rw-r--r--chromium/components/sync_bookmarks/synced_bookmark_tracker.h6
-rw-r--r--chromium/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc40
-rw-r--r--chromium/components/sync_device_info/device_info.cc16
-rw-r--r--chromium/components/sync_device_info/device_info.h32
-rw-r--r--chromium/components/sync_device_info/device_info_prefs.cc2
-rw-r--r--chromium/components/sync_device_info/device_info_sync_bridge.cc70
-rw-r--r--chromium/components/sync_device_info/device_info_sync_bridge.h16
-rw-r--r--chromium/components/sync_device_info/device_info_sync_bridge_unittest.cc53
-rw-r--r--chromium/components/sync_device_info/device_info_sync_client.h14
-rw-r--r--chromium/components/sync_device_info/device_info_sync_service.h3
-rw-r--r--chromium/components/sync_device_info/device_info_sync_service_impl.h1
-rw-r--r--chromium/components/sync_device_info/device_info_tracker.h3
-rw-r--r--chromium/components/sync_device_info/fake_device_info_tracker.h4
-rw-r--r--chromium/components/sync_device_info/fake_local_device_info_provider.cc5
-rw-r--r--chromium/components/sync_device_info/fake_local_device_info_provider.h2
-rw-r--r--chromium/components/sync_device_info/local_device_info_provider_impl.cc10
-rw-r--r--chromium/components/sync_device_info/local_device_info_provider_impl_unittest.cc29
-rw-r--r--chromium/components/sync_device_info/local_device_info_util.cc2
-rw-r--r--chromium/components/sync_preferences/DIR_METADATA2
-rw-r--r--chromium/components/sync_preferences/pref_model_associator.cc20
-rw-r--r--chromium/components/sync_preferences/pref_model_associator.h6
-rw-r--r--chromium/components/sync_preferences/pref_service_syncable_unittest.cc42
-rw-r--r--chromium/components/sync_sessions/local_session_event_handler_impl.cc1
-rw-r--r--chromium/components/sync_sessions/local_session_event_router.h2
-rw-r--r--chromium/components/sync_sessions/proxy_tabs_data_type_controller.h3
-rw-r--r--chromium/components/sync_sessions/session_store.cc15
-rw-r--r--chromium/components/sync_sessions/session_store.h8
-rw-r--r--chromium/components/sync_sessions/session_store_unittest.cc10
-rw-r--r--chromium/components/sync_sessions/session_sync_bridge.cc9
-rw-r--r--chromium/components/sync_sessions/session_sync_bridge.h8
-rw-r--r--chromium/components/sync_sessions/session_sync_bridge_unittest.cc8
-rw-r--r--chromium/components/sync_sessions/session_sync_service.h3
-rw-r--r--chromium/components/sync_sessions/session_sync_service_impl.h1
-rw-r--r--chromium/components/sync_sessions/synced_session.cc4
-rw-r--r--chromium/components/sync_sessions/synced_session.h4
-rw-r--r--chromium/components/sync_sessions/synced_session_tracker.cc8
-rw-r--r--chromium/components/sync_sessions/synced_session_tracker.h4
-rw-r--r--chromium/components/sync_sessions/synced_session_unittest.cc2
-rw-r--r--chromium/components/sync_sessions/synced_window_delegate.h2
-rw-r--r--chromium/components/sync_sessions/tab_node_pool.cc1
-rw-r--r--chromium/components/sync_sessions/tab_node_pool.h1
-rw-r--r--chromium/components/sync_ui_strings.grdp21
-rw-r--r--chromium/components/sync_ui_strings_grdp/IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE_ANDROID.png.sha11
-rw-r--r--chromium/components/sync_user_events/fake_user_event_service.h1
-rw-r--r--chromium/components/sync_user_events/no_op_user_event_service.h1
-rw-r--r--chromium/components/sync_user_events/user_event_model_type_controller.cc2
-rw-r--r--chromium/components/sync_user_events/user_event_service.h1
-rw-r--r--chromium/components/sync_user_events/user_event_service_impl.h1
-rw-r--r--chromium/components/sync_user_events/user_event_sync_bridge.cc14
-rw-r--r--chromium/components/sync_user_events/user_event_sync_bridge.h16
-rw-r--r--chromium/components/system_media_controls/mac/now_playing_info_center_delegate.h5
-rw-r--r--chromium/components/thin_webview/internal/compositor_view_impl.cc2
-rw-r--r--chromium/components/thin_webview/internal/java/src/org/chromium/components/thinwebview/internal/ThinWebViewImpl.java10
-rw-r--r--chromium/components/timers/BUILD.gn25
-rw-r--r--chromium/components/timers/DEPS10
-rw-r--r--chromium/components/timers/DIR_METADATA3
-rw-r--r--chromium/components/timers/OWNERS1
-rw-r--r--chromium/components/timers/README3
-rw-r--r--chromium/components/timers/alarm_timer_chromeos.cc157
-rw-r--r--chromium/components/timers/alarm_timer_chromeos.h89
-rw-r--r--chromium/components/timers/alarm_timer_unittest.cc366
-rw-r--r--chromium/components/translate_strings.grdp16
-rw-r--r--chromium/components/ui_devtools/agent_util.h3
-rw-r--r--chromium/components/ui_devtools/css_agent.cc5
-rw-r--r--chromium/components/ui_devtools/css_agent_unittest.cc1
-rw-r--r--chromium/components/ui_devtools/devtools_export.h6
-rw-r--r--chromium/components/ui_devtools/devtools_server.cc4
-rw-r--r--chromium/components/ui_devtools/devtools_server.h2
-rw-r--r--chromium/components/ui_devtools/dom_agent.cc10
-rw-r--r--chromium/components/ui_devtools/dom_agent.h3
-rw-r--r--chromium/components/ui_devtools/protocol.json59
-rw-r--r--chromium/components/ui_devtools/ui_element.cc5
-rw-r--r--chromium/components/ui_devtools/ui_element.h9
-rw-r--r--chromium/components/ui_devtools/ui_element_delegate.h2
-rw-r--r--chromium/components/ui_devtools/views/BUILD.gn4
-rw-r--r--chromium/components/ui_devtools/views/DEPS3
-rw-r--r--chromium/components/ui_devtools/views/devtools_event_util.cc23
-rw-r--r--chromium/components/ui_devtools/views/devtools_event_util.h17
-rw-r--r--chromium/components/ui_devtools/views/dom_agent_mac.mm2
-rw-r--r--chromium/components/ui_devtools/views/dom_agent_unittest.cc8
-rw-r--r--chromium/components/ui_devtools/views/element_utility.cc1
-rw-r--r--chromium/components/ui_devtools/views/overlay_agent_unittest.cc22
-rw-r--r--chromium/components/ui_devtools/views/ui_element_with_metadata.cc145
-rw-r--r--chromium/components/ui_devtools/views/ui_element_with_metadata.h51
-rw-r--r--chromium/components/ui_devtools/views/view_element.cc158
-rw-r--r--chromium/components/ui_devtools/views/view_element.h21
-rw-r--r--chromium/components/ui_devtools/views/view_element_unittest.cc4
-rw-r--r--chromium/components/ui_devtools/views/widget_element.cc30
-rw-r--r--chromium/components/ui_devtools/views/widget_element.h14
-rw-r--r--chromium/components/ui_devtools/views/widget_element_unittest.cc70
-rw-r--r--chromium/components/ui_devtools/views/window_element.cc81
-rw-r--r--chromium/components/ui_devtools/views/window_element.h17
-rw-r--r--chromium/components/ui_devtools/views/window_element_unittest.cc10
-rw-r--r--chromium/components/ui_devtools/viz/OWNERS2
-rw-r--r--chromium/components/ui_devtools/viz/dom_agent_viz.cc4
-rw-r--r--chromium/components/ui_devtools/viz/surface_element.cc8
-rw-r--r--chromium/components/ui_devtools/viz/viz_devtools_unittest.cc2
-rw-r--r--chromium/components/ui_devtools/viz/viz_element.h2
-rw-r--r--chromium/components/ukm/content/source_url_recorder.cc16
-rw-r--r--chromium/components/ukm/content/source_url_recorder_browsertest.cc7
-rw-r--r--chromium/components/ukm/content/source_url_recorder_test.cc92
-rw-r--r--chromium/components/ukm/debug/ukm_debug_data_extractor.h2
-rw-r--r--chromium/components/ukm/debug/ukm_internals.html1
-rw-r--r--chromium/components/ukm/ios/ukm_url_recorder_unittest.mm10
-rw-r--r--chromium/components/ukm/observers/history_delete_observer.h2
-rw-r--r--chromium/components/ukm/observers/ukm_consent_state_observer_unittest.cc2
-rw-r--r--chromium/components/ukm/ukm_rotation_scheduler.h6
-rw-r--r--chromium/components/ukm/ukm_service.cc4
-rw-r--r--chromium/components/ukm/ukm_service_unittest.cc2
-rw-r--r--chromium/components/unified_consent/unified_consent_service.cc2
-rw-r--r--chromium/components/update_client/background_downloader_win.h1
-rw-r--r--chromium/components/update_client/component.cc4
-rw-r--r--chromium/components/update_client/component.h10
-rw-r--r--chromium/components/update_client/component_patcher.cc4
-rw-r--r--chromium/components/update_client/component_patcher_unittest.h3
-rw-r--r--chromium/components/update_client/component_unpacker.cc1
-rw-r--r--chromium/components/update_client/crx_update_item.h4
-rw-r--r--chromium/components/update_client/patch/patch_impl.h2
-rw-r--r--chromium/components/update_client/protocol_definition.h26
-rw-r--r--chromium/components/update_client/protocol_serializer.cc10
-rw-r--r--chromium/components/update_client/protocol_serializer.h6
-rw-r--r--chromium/components/update_client/protocol_serializer_json_unittest.cc2
-rw-r--r--chromium/components/update_client/request_sender.cc6
-rw-r--r--chromium/components/update_client/test_installer.cc10
-rw-r--r--chromium/components/update_client/update_checker.cc5
-rw-r--r--chromium/components/update_client/update_checker.h4
-rw-r--r--chromium/components/update_client/update_checker_unittest.cc9
-rw-r--r--chromium/components/update_client/update_client.h4
-rw-r--r--chromium/components/update_client/update_client_unittest.cc60
-rw-r--r--chromium/components/update_client/update_engine.cc10
-rw-r--r--chromium/components/update_client/update_engine.h4
-rw-r--r--chromium/components/update_client/utils.cc14
-rw-r--r--chromium/components/update_client/utils.h8
-rw-r--r--chromium/components/upload_list/combining_upload_list.cc6
-rw-r--r--chromium/components/upload_list/combining_upload_list.h1
-rw-r--r--chromium/components/upload_list/combining_upload_list_unittest.cc23
-rw-r--r--chromium/components/upload_list/text_log_upload_list.cc10
-rw-r--r--chromium/components/url_formatter/OWNERS3
-rw-r--r--chromium/components/url_formatter/android/javatests/src/org/chromium/components/url_formatter/UrlFormatterUnitTest.java14
-rw-r--r--chromium/components/url_formatter/elide_url.cc11
-rw-r--r--chromium/components/url_formatter/elide_url.h15
-rw-r--r--chromium/components/url_formatter/elide_url_unittest.cc23
-rw-r--r--chromium/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc1
-rw-r--r--chromium/components/url_formatter/tools/DIR_METADATA3
-rw-r--r--chromium/components/url_formatter/url_formatter.cc25
-rw-r--r--chromium/components/url_formatter/url_formatter_android.cc9
-rw-r--r--chromium/components/url_formatter/url_formatter_unittest.cc1
-rw-r--r--chromium/components/url_matcher/substring_set_matcher.h2
-rw-r--r--chromium/components/url_matcher/url_matcher_factory.cc7
-rw-r--r--chromium/components/url_matcher/url_matcher_factory_unittest.cc3
-rw-r--r--chromium/components/url_pattern_index/flat/url_pattern_index.fbs4
-rw-r--r--chromium/components/url_pattern_index/uint64_hasher.h6
-rw-r--r--chromium/components/url_pattern_index/url_pattern.h4
-rw-r--r--chromium/components/url_pattern_index/url_pattern_index.cc42
-rw-r--r--chromium/components/url_pattern_index/url_pattern_index.h107
-rw-r--r--chromium/components/url_pattern_index/url_pattern_index_unittest.cc92
-rw-r--r--chromium/components/url_pattern_index/url_rule_test_support.cc3
-rw-r--r--chromium/components/url_pattern_index/url_rule_util_unittest.cc3
-rw-r--r--chromium/components/user_manager/BUILD.gn9
-rw-r--r--chromium/components/user_manager/fake_user_manager.cc14
-rw-r--r--chromium/components/user_manager/fake_user_manager.h9
-rw-r--r--chromium/components/user_manager/known_user.cc801
-rw-r--r--chromium/components/user_manager/known_user.h390
-rw-r--r--chromium/components/user_manager/known_user_unittest.cc854
-rw-r--r--chromium/components/user_manager/user.cc5
-rw-r--r--chromium/components/user_manager/user.h6
-rw-r--r--chromium/components/user_manager/user_image/user_image.h1
-rw-r--r--chromium/components/user_manager/user_manager_base.cc64
-rw-r--r--chromium/components/user_manager/user_manager_base.h31
-rw-r--r--chromium/components/user_manager/user_manager_export.h6
-rw-r--r--chromium/components/user_prefs/DIR_METADATA2
-rw-r--r--chromium/components/variations/BUILD.gn13
-rw-r--r--chromium/components/variations/active_field_trials.cc5
-rw-r--r--chromium/components/variations/android/variations_seed_bridge.h2
-rw-r--r--chromium/components/variations/child_process_field_trial_syncer.cc59
-rw-r--r--chromium/components/variations/child_process_field_trial_syncer.h74
-rw-r--r--chromium/components/variations/child_process_field_trial_syncer_unittest.cc63
-rw-r--r--chromium/components/variations/client_filterable_state.cc2
-rw-r--r--chromium/components/variations/client_filterable_state.h4
-rw-r--r--chromium/components/variations/field_trial_config/field_trial_testing_config_schema.json6
-rw-r--r--chromium/components/variations/field_trial_config/field_trial_util.cc2
-rw-r--r--chromium/components/variations/field_trial_config/field_trial_util_unittest.cc44
-rw-r--r--chromium/components/variations/pref_names.cc56
-rw-r--r--chromium/components/variations/pref_names.h6
-rw-r--r--chromium/components/variations/service/generate_ui_string_overrider.gni5
-rwxr-xr-xchromium/components/variations/service/generate_ui_string_overrider.py4
-rw-r--r--chromium/components/variations/service/safe_seed_manager.cc29
-rw-r--r--chromium/components/variations/service/safe_seed_manager.h13
-rw-r--r--chromium/components/variations/service/safe_seed_manager_unittest.cc66
-rw-r--r--chromium/components/variations/service/ui_string_overrider.h2
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator.cc317
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator.h28
-rw-r--r--chromium/components/variations/service/variations_field_trial_creator_unittest.cc40
-rw-r--r--chromium/components/variations/service/variations_service.cc7
-rw-r--r--chromium/components/variations/service/variations_service_unittest.cc4
-rw-r--r--chromium/components/variations/synthetic_trial_registry.h1
-rw-r--r--chromium/components/variations/synthetic_trial_registry_unittest.cc2
-rw-r--r--chromium/components/variations/variations_crash_keys.cc72
-rw-r--r--chromium/components/variations/variations_crash_keys.h24
-rw-r--r--chromium/components/variations/variations_crash_keys_chromeos.cc49
-rw-r--r--chromium/components/variations/variations_crash_keys_chromeos.h21
-rw-r--r--chromium/components/variations/variations_crash_keys_chromeos_unittest.cc87
-rw-r--r--chromium/components/variations/variations_crash_keys_unittest.cc25
-rw-r--r--chromium/components/variations/variations_features.h2
-rw-r--r--chromium/components/variations/variations_ids_provider.cc10
-rw-r--r--chromium/components/variations/variations_ids_provider.h12
-rw-r--r--chromium/components/variations/variations_ids_provider_unittest.cc4
-rw-r--r--chromium/components/variations/variations_layers.cc6
-rw-r--r--chromium/components/variations/variations_layers.h6
-rw-r--r--chromium/components/variations/variations_murmur_hash.h1
-rw-r--r--chromium/components/variations/variations_seed_processor.cc8
-rw-r--r--chromium/components/variations/variations_seed_processor.h1
-rw-r--r--chromium/components/vector_icons/BUILD.gn8
-rw-r--r--chromium/components/vector_icons/add_cellular_network.icon29
-rw-r--r--chromium/components/vector_icons/caret_down.icon20
-rw-r--r--chromium/components/vector_icons/caret_up.icon20
-rw-r--r--chromium/components/vector_icons/email.icon23
-rw-r--r--chromium/components/vector_icons/https_valid.icon49
-rw-r--r--chromium/components/vector_icons/https_valid_arrow.icon20
-rw-r--r--chromium/components/vector_icons/not_secure_warning.icon41
-rw-r--r--chromium/components/vector_icons/submenu_arrow.icon19
-rw-r--r--chromium/components/vector_icons/vector_icons.gni2
-rw-r--r--chromium/components/version_info/version_info.cc2
-rw-r--r--chromium/components/viz/BUILD.gn2
-rw-r--r--chromium/components/viz/DEPS2
-rw-r--r--chromium/components/viz/OWNERS4
-rw-r--r--chromium/components/viz/client/client_resource_provider.cc28
-rw-r--r--chromium/components/viz/client/client_resource_provider.h15
-rw-r--r--chromium/components/viz/client/client_resource_provider_unittest.cc223
-rw-r--r--chromium/components/viz/client/frame_eviction_manager.h4
-rw-r--r--chromium/components/viz/common/BUILD.gn17
-rw-r--r--chromium/components/viz/common/debugger/viz_debugger.gni10
-rw-r--r--chromium/components/viz/common/debugger/viz_debugger.pdl32
-rw-r--r--chromium/components/viz/common/display/renderer_settings.h2
-rw-r--r--chromium/components/viz/common/features.cc56
-rw-r--r--chromium/components/viz/common/features.h8
-rw-r--r--chromium/components/viz/common/frame_sinks/begin_frame_args.h1
-rw-r--r--chromium/components/viz/common/frame_sinks/begin_frame_source.cc1
-rw-r--r--chromium/components/viz/common/frame_sinks/begin_frame_source.h2
-rw-r--r--chromium/components/viz/common/frame_sinks/copy_output_request.h9
-rw-r--r--chromium/components/viz/common/frame_sinks/copy_output_result.cc12
-rw-r--r--chromium/components/viz/common/frame_sinks/copy_output_result.h34
-rw-r--r--chromium/components/viz/common/frame_sinks/delay_based_time_source.cc14
-rw-r--r--chromium/components/viz/common/frame_sinks/delay_based_time_source.h8
-rw-r--r--chromium/components/viz/common/gl_scaler.h4
-rw-r--r--chromium/components/viz/common/gpu/dawn_context_provider.cc2
-rw-r--r--chromium/components/viz/common/gpu/vulkan_context_provider.h3
-rw-r--r--chromium/components/viz/common/gpu/vulkan_in_process_context_provider.cc12
-rw-r--r--chromium/components/viz/common/gpu/vulkan_in_process_context_provider.h2
-rw-r--r--chromium/components/viz/common/quads/aggregated_render_pass.cc2
-rw-r--r--chromium/components/viz/common/quads/aggregated_render_pass.h2
-rw-r--r--chromium/components/viz/common/quads/aggregated_render_pass_draw_quad.h2
-rw-r--r--chromium/components/viz/common/quads/compositor_frame_metadata.h6
-rw-r--r--chromium/components/viz/common/quads/compositor_frame_metadata_unittest.cc2
-rw-r--r--chromium/components/viz/common/quads/compositor_frame_transition_directive.h2
-rw-r--r--chromium/components/viz/common/quads/compositor_render_pass.cc2
-rw-r--r--chromium/components/viz/common/quads/compositor_render_pass.h2
-rw-r--r--chromium/components/viz/common/quads/compositor_render_pass_draw_quad.h2
-rw-r--r--chromium/components/viz/common/quads/compositor_render_pass_unittest.cc28
-rw-r--r--chromium/components/viz/common/quads/content_draw_quad_base.h2
-rw-r--r--chromium/components/viz/common/quads/debug_border_draw_quad.h2
-rw-r--r--chromium/components/viz/common/quads/draw_quad_perftest.cc4
-rw-r--r--chromium/components/viz/common/quads/draw_quad_unittest.cc15
-rw-r--r--chromium/components/viz/common/quads/frame_deadline.cc2
-rw-r--r--chromium/components/viz/common/quads/frame_deadline.h8
-rw-r--r--chromium/components/viz/common/quads/picture_draw_quad.h2
-rw-r--r--chromium/components/viz/common/quads/render_pass_draw_quad_internal.h2
-rw-r--r--chromium/components/viz/common/quads/render_pass_internal.h4
-rw-r--r--chromium/components/viz/common/quads/render_pass_io.cc269
-rw-r--r--chromium/components/viz/common/quads/render_pass_io_unittest.cc37
-rw-r--r--chromium/components/viz/common/quads/shared_quad_state.cc10
-rw-r--r--chromium/components/viz/common/quads/shared_quad_state.h12
-rw-r--r--chromium/components/viz/common/quads/solid_color_draw_quad.h2
-rw-r--r--chromium/components/viz/common/quads/stream_video_draw_quad.h2
-rw-r--r--chromium/components/viz/common/quads/surface_draw_quad.cc2
-rw-r--r--chromium/components/viz/common/quads/surface_draw_quad.h4
-rw-r--r--chromium/components/viz/common/quads/texture_draw_quad.h2
-rw-r--r--chromium/components/viz/common/quads/video_hole_draw_quad.h2
-rw-r--r--chromium/components/viz/common/quads/yuv_video_draw_quad.h2
-rw-r--r--chromium/components/viz/common/resources/bitmap_allocation.h2
-rw-r--r--chromium/components/viz/common/resources/resource_format_utils.cc84
-rw-r--r--chromium/components/viz/common/resources/resource_format_utils.h2
-rw-r--r--chromium/components/viz/common/resources/return_callback.h2
-rw-r--r--chromium/components/viz/common/resources/returned_resource.cc15
-rw-r--r--chromium/components/viz/common/resources/returned_resource.h25
-rw-r--r--chromium/components/viz/common/resources/shared_bitmap.cc1
-rw-r--r--chromium/components/viz/common/resources/single_release_callback.cc27
-rw-r--r--chromium/components/viz/common/resources/single_release_callback.h34
-rw-r--r--chromium/components/viz/common/resources/transferable_resource.h8
-rw-r--r--chromium/components/viz/common/surfaces/frame_sink_id.cc3
-rw-r--r--chromium/components/viz/common/surfaces/surface_range.cc2
-rw-r--r--chromium/components/viz/common/surfaces/surface_range.h8
-rw-r--r--chromium/components/viz/common/surfaces/surface_range_unittest.cc4
-rw-r--r--chromium/components/viz/common/switches.cc13
-rw-r--r--chromium/components/viz/common/switches.h7
-rw-r--r--chromium/components/viz/common/transition_utils.cc99
-rw-r--r--chromium/components/viz/common/transition_utils.h45
-rw-r--r--chromium/components/viz/demo/client/demo_client.cc38
-rw-r--r--chromium/components/viz/demo/client/demo_client.h5
-rw-r--r--chromium/components/viz/host/client_frame_sink_video_capturer.cc2
-rw-r--r--chromium/components/viz/host/client_frame_sink_video_capturer.h14
-rw-r--r--chromium/components/viz/host/gpu_client.cc5
-rw-r--r--chromium/components/viz/host/gpu_client.h6
-rw-r--r--chromium/components/viz/host/gpu_client_delegate.h1
-rw-r--r--chromium/components/viz/host/gpu_host_impl.cc130
-rw-r--r--chromium/components/viz/host/gpu_host_impl.h59
-rw-r--r--chromium/components/viz/host/host_frame_sink_manager.h2
-rw-r--r--chromium/components/viz/host/host_frame_sink_manager_unittest.cc1
-rw-r--r--chromium/components/viz/host/host_gpu_memory_buffer_manager.cc132
-rw-r--r--chromium/components/viz/host/host_gpu_memory_buffer_manager.h16
-rw-r--r--chromium/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc27
-rw-r--r--chromium/components/viz/host/renderer_settings_creation.cc9
-rw-r--r--chromium/components/viz/service/BUILD.gn4
-rw-r--r--chromium/components/viz/service/DEPS1
-rw-r--r--chromium/components/viz/service/compositor_frame_fuzzer/BUILD.gn4
-rw-r--r--chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer.cc4
-rw-r--r--chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc12
-rw-r--r--chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc17
-rw-r--r--chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h3
-rw-r--r--chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_software_output_surface_provider.cc4
-rw-r--r--chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_software_output_surface_provider.h6
-rwxr-xr-xchromium/components/viz/service/compositor_frame_fuzzer/generate_renderpass_binary.py2
-rw-r--r--chromium/components/viz/service/debugger/DEPS9
-rw-r--r--chromium/components/viz/service/debugger/README.md62
-rw-r--r--chromium/components/viz/service/debugger/viz_debugger.cc339
-rw-r--r--chromium/components/viz/service/debugger/viz_debugger.h328
-rw-r--r--chromium/components/viz/service/debugger/viz_debugger_unittest.cc387
-rw-r--r--chromium/components/viz/service/display/DEPS3
-rw-r--r--chromium/components/viz/service/display/aggregated_frame.h4
-rw-r--r--chromium/components/viz/service/display/ca_layer_overlay.cc75
-rw-r--r--chromium/components/viz/service/display/ca_layer_overlay.h7
-rw-r--r--chromium/components/viz/service/display/copy_output_scaling_pixeltest.cc2
-rw-r--r--chromium/components/viz/service/display/damage_frame_annotator.cc2
-rw-r--r--chromium/components/viz/service/display/dc_layer_overlay.cc18
-rw-r--r--chromium/components/viz/service/display/dc_layer_overlay.h5
-rw-r--r--chromium/components/viz/service/display/delegated_ink_point_renderer_base.cc4
-rw-r--r--chromium/components/viz/service/display/delegated_ink_point_renderer_base.h12
-rw-r--r--chromium/components/viz/service/display/delegated_ink_trail_data.cc13
-rw-r--r--chromium/components/viz/service/display/direct_renderer.cc40
-rw-r--r--chromium/components/viz/service/display/direct_renderer.h14
-rw-r--r--chromium/components/viz/service/display/display.cc75
-rw-r--r--chromium/components/viz/service/display/display.h19
-rw-r--r--chromium/components/viz/service/display/display_perftest.cc6
-rw-r--r--chromium/components/viz/service/display/display_resource_provider.cc81
-rw-r--r--chromium/components/viz/service/display/display_resource_provider.h47
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_gl.cc11
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_gl.h7
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_gl_unittest.cc172
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_null.cc1
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_skia.cc48
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_skia.h13
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_skia_unittest.cc171
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_software.cc1
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_software_unittest.cc17
-rw-r--r--chromium/components/viz/service/display/display_scheduler.cc25
-rw-r--r--chromium/components/viz/service/display/display_scheduler.h3
-rw-r--r--chromium/components/viz/service/display/display_scheduler_unittest.cc2
-rw-r--r--chromium/components/viz/service/display/display_unittest.cc578
-rw-r--r--chromium/components/viz/service/display/draw_polygon.h7
-rw-r--r--chromium/components/viz/service/display/draw_polygon_unittest.cc2
-rw-r--r--chromium/components/viz/service/display/external_use_client.cc2
-rw-r--r--chromium/components/viz/service/display/external_use_client.h11
-rw-r--r--chromium/components/viz/service/display/frame_rate_decider.cc2
-rw-r--r--chromium/components/viz/service/display/frame_rate_decider_unittest.cc2
-rw-r--r--chromium/components/viz/service/display/gl_renderer.cc42
-rw-r--r--chromium/components/viz/service/display/gl_renderer.h20
-rw-r--r--chromium/components/viz/service/display/gl_renderer_copier_pixeltest.cc2
-rw-r--r--chromium/components/viz/service/display/gl_renderer_unittest.cc78
-rw-r--r--chromium/components/viz/service/display/output_surface.cc6
-rw-r--r--chromium/components/viz/service/display/output_surface.h11
-rw-r--r--chromium/components/viz/service/display/output_surface_client.h5
-rw-r--r--chromium/components/viz/service/display/output_surface_frame.h4
-rw-r--r--chromium/components/viz/service/display/overlay_ca_unittest.cc100
-rw-r--r--chromium/components/viz/service/display/overlay_candidate.cc11
-rw-r--r--chromium/components/viz/service/display/overlay_candidate.h7
-rw-r--r--chromium/components/viz/service/display/overlay_candidate_temporal_tracker.h3
-rw-r--r--chromium/components/viz/service/display/overlay_dc_unittest.cc12
-rw-r--r--chromium/components/viz/service/display/overlay_processor_android.cc10
-rw-r--r--chromium/components/viz/service/display/overlay_processor_interface.h4
-rw-r--r--chromium/components/viz/service/display/overlay_processor_mac.cc2
-rw-r--r--chromium/components/viz/service/display/overlay_processor_mac.h4
-rw-r--r--chromium/components/viz/service/display/overlay_processor_ozone.cc4
-rw-r--r--chromium/components/viz/service/display/overlay_processor_stub.h2
-rw-r--r--chromium/components/viz/service/display/overlay_processor_surface_control.cc6
-rw-r--r--chromium/components/viz/service/display/overlay_processor_surface_control.h2
-rw-r--r--chromium/components/viz/service/display/overlay_processor_surface_control_unittest.cc8
-rw-r--r--chromium/components/viz/service/display/overlay_processor_using_strategy.cc46
-rw-r--r--chromium/components/viz/service/display/overlay_processor_using_strategy.h4
-rw-r--r--chromium/components/viz/service/display/overlay_processor_win.h2
-rw-r--r--chromium/components/viz/service/display/overlay_unittest.cc140
-rw-r--r--chromium/components/viz/service/display/renderer_perftest.cc46
-rw-r--r--chromium/components/viz/service/display/renderer_pixeltest.cc37
-rw-r--r--chromium/components/viz/service/display/shared_bitmap_manager.h8
-rw-r--r--chromium/components/viz/service/display/skia_readback_pixeltest.cc7
-rw-r--r--chromium/components/viz/service/display/skia_renderer.cc169
-rw-r--r--chromium/components/viz/service/display/skia_renderer.h19
-rw-r--r--chromium/components/viz/service/display/software_renderer.cc13
-rw-r--r--chromium/components/viz/service/display/software_renderer.h4
-rw-r--r--chromium/components/viz/service/display/software_renderer_unittest.cc12
-rw-r--r--chromium/components/viz/service/display/surface_aggregator.cc100
-rw-r--r--chromium/components/viz/service/display/surface_aggregator.h31
-rw-r--r--chromium/components/viz/service/display/surface_aggregator_perftest.cc103
-rw-r--r--chromium/components/viz/service/display/surface_aggregator_pixeltest.cc12
-rw-r--r--chromium/components/viz/service/display/surface_aggregator_unittest.cc2335
-rw-r--r--chromium/components/viz/service/display/texture_deleter.cc37
-rw-r--r--chromium/components/viz/service/display/texture_deleter.h8
-rw-r--r--chromium/components/viz/service/display/texture_deleter_unittest.cc12
-rw-r--r--chromium/components/viz/service/display/viz_perf_test.cc35
-rw-r--r--chromium/components/viz/service/display/viz_perf_test.h12
-rw-r--r--chromium/components/viz/service/display/viz_pixel_test.h2
-rw-r--r--chromium/components/viz/service/display_embedder/buffer_queue.h4
-rw-r--r--chromium/components/viz/service/display_embedder/buffer_queue_unittest.cc5
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface.cc3
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_android.h2
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc3
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue_unittest.cc3
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_offscreen.cc3
-rw-r--r--chromium/components/viz/service/display_embedder/image_context_impl.cc11
-rw-r--r--chromium/components/viz/service/display_embedder/image_context_impl.h4
-rw-r--r--chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.cc3
-rw-r--r--chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h7
-rw-r--r--chromium/components/viz/service/display_embedder/output_presenter.h3
-rw-r--r--chromium/components/viz/service/display_embedder/output_presenter_fuchsia.cc88
-rw-r--r--chromium/components/viz/service/display_embedder/output_presenter_fuchsia.h20
-rw-r--r--chromium/components/viz/service/display_embedder/output_presenter_gl.cc20
-rw-r--r--chromium/components/viz/service/display_embedder/output_presenter_x11.cc10
-rw-r--r--chromium/components/viz/service/display_embedder/output_surface_provider_impl.cc13
-rw-r--r--chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc93
-rw-r--r--chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h2
-rw-r--r--chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc34
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device.cc10
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device.h11
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc27
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue.h7
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc8
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_dawn.cc6
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_gl.cc5
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_vulkan.cc15
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_device_vulkan.h4
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_dependency.h2
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_dependency_impl.cc7
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_dependency_impl.h11
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc122
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl.h39
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc61
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h37
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc3
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_surface.cc3
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc6
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h6
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc86
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h22
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc49
-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.cc54
-rw-r--r--chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h37
-rw-r--r--chromium/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc149
-rw-r--r--chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc36
-rw-r--r--chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h13
-rw-r--r--chromium/components/viz/service/frame_sinks/surface_resource_holder.cc13
-rw-r--r--chromium/components/viz/service/frame_sinks/surface_resource_holder.h2
-rw-r--r--chromium/components/viz/service/frame_sinks/surface_resource_holder_client.h3
-rw-r--r--chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc239
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h6
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc22
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h9
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc31
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/video_capture_overlay_unittest.cc2
-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/gpu_service_impl.cc77
-rw-r--r--chromium/components/viz/service/gl/gpu_service_impl.h36
-rw-r--r--chromium/components/viz/service/gl/gpu_service_impl_unittest.cc2
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator.cc10
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator.h2
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc2
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager.cc2
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager.h8
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc2
-rw-r--r--chromium/components/viz/service/main/viz_compositor_thread_runner.h12
-rw-r--r--chromium/components/viz/service/main/viz_compositor_thread_runner_impl.cc19
-rw-r--r--chromium/components/viz/service/main/viz_compositor_thread_runner_impl.h2
-rw-r--r--chromium/components/viz/service/main/viz_main_impl.cc34
-rw-r--r--chromium/components/viz/service/main/viz_main_impl.h15
-rw-r--r--chromium/components/viz/service/main/viz_main_impl_unittest.cc1
-rw-r--r--chromium/components/viz/service/surfaces/surface.cc39
-rw-r--r--chromium/components/viz/service/surfaces/surface.h13
-rw-r--r--chromium/components/viz/service/surfaces/surface_allocation_group.cc14
-rw-r--r--chromium/components/viz/service/surfaces/surface_allocation_group.h4
-rw-r--r--chromium/components/viz/service/surfaces/surface_client.h7
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_deadline.cc4
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_deadline.h10
-rw-r--r--chromium/components/viz/service/surfaces/surface_manager.cc10
-rw-r--r--chromium/components/viz/service/surfaces/surface_manager.h15
-rw-r--r--chromium/components/viz/service/surfaces/surface_observer.h3
-rw-r--r--chromium/components/viz/service/surfaces/surface_saved_frame.cc310
-rw-r--r--chromium/components/viz/service/surfaces/surface_saved_frame.h87
-rw-r--r--chromium/components/viz/service/surfaces/surface_saved_frame_storage.cc7
-rw-r--r--chromium/components/viz/service/surfaces/surface_saved_frame_unittest.cc387
-rw-r--r--chromium/components/viz/service/transitions/DEPS7
-rw-r--r--chromium/components/viz/service/transitions/surface_animation_manager.cc701
-rw-r--r--chromium/components/viz/service/transitions/surface_animation_manager.h201
-rw-r--r--chromium/components/viz/service/transitions/surface_animation_manager_unittest.cc277
-rw-r--r--chromium/components/viz/service/transitions/transferable_resource_tracker.cc71
-rw-r--r--chromium/components/viz/service/transitions/transferable_resource_tracker.h30
-rw-r--r--chromium/components/viz/service/transitions/transferable_resource_tracker_unittest.cc90
-rw-r--r--chromium/components/web_cache/browser/BUILD.gn1
-rw-r--r--chromium/components/web_cache/browser/web_cache_manager.cc6
-rw-r--r--chromium/components/web_cache/public/BUILD.gn12
-rw-r--r--chromium/components/web_cache/public/features.cc12
-rw-r--r--chromium/components/web_cache/public/features.h19
-rw-r--r--chromium/components/web_cache/renderer/BUILD.gn1
-rw-r--r--chromium/components/web_cache/renderer/web_cache_impl.cc29
-rw-r--r--chromium/components/web_cache/renderer/web_cache_impl.h4
-rw-r--r--chromium/components/web_modal/BUILD.gn1
-rw-r--r--chromium/components/web_modal/DEPS1
-rw-r--r--chromium/components/web_modal/web_contents_modal_dialog_manager.cc17
-rw-r--r--chromium/components/web_package/web_bundle_parser.cc78
-rw-r--r--chromium/components/web_package/web_bundle_parser.h2
-rw-r--r--chromium/components/web_package/web_bundle_parser_factory.cc2
-rw-r--r--chromium/components/web_package/web_bundle_parser_factory_unittest.cc12
-rw-r--r--chromium/components/web_package/web_bundle_parser_fuzzer.cc2
-rw-r--r--chromium/components/web_package/web_bundle_parser_unittest.cc4
-rw-r--r--chromium/components/web_package/web_bundle_utils.h9
-rw-r--r--chromium/components/webapk/BUILD.gn9
-rw-r--r--chromium/components/webapk/webapk.proto185
-rw-r--r--chromium/components/webapps/browser/BUILD.gn1
-rw-r--r--chromium/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc14
-rw-r--r--chromium/components/webapps/browser/android/android_webapps_strings.grd4
-rw-r--r--chromium/components/webapps/browser/android/app_banner_manager_android.cc2
-rw-r--r--chromium/components/webapps/browser/android/shortcut_info.cc2
-rw-r--r--chromium/components/webapps/browser/android/shortcut_info.h8
-rw-r--r--chromium/components/webapps/browser/android/translations/android_webapps_strings_az.xtb2
-rw-r--r--chromium/components/webapps/browser/android/webapps_icon_utils.cc5
-rw-r--r--chromium/components/webapps/browser/banners/app_banner_manager.cc6
-rw-r--r--chromium/components/webapps/browser/banners/app_banner_manager.h2
-rw-r--r--chromium/components/webapps/browser/banners/app_banner_settings_helper.cc38
-rw-r--r--chromium/components/webapps/browser/banners/app_banner_settings_helper.h4
-rw-r--r--chromium/components/webapps/browser/banners/app_banner_settings_helper_unittest.cc4
-rw-r--r--chromium/components/webapps/browser/installable/installable_manager.cc10
-rw-r--r--chromium/components/webapps/browser/installable/installable_manager.h7
-rw-r--r--chromium/components/webapps/browser/installable/installable_manager_unittest.cc8
-rw-r--r--chromium/components/webapps/browser/installable/installable_metrics.cc10
-rw-r--r--chromium/components/webapps/browser/installable/installable_metrics.h60
-rw-r--r--chromium/components/webapps/browser/pwa_install_path_tracker.h4
-rw-r--r--chromium/components/webapps/services/web_app_origin_association/web_app_origin_association_parser.cc28
-rw-r--r--chromium/components/webapps/services/web_app_origin_association/web_app_origin_association_parser.h6
-rw-r--r--chromium/components/webauthn/android/fido2helper_native_android.cc4
-rw-r--r--chromium/components/webcrypto/algorithms/asymmetric_key_util.h6
-rw-r--r--chromium/components/webcrypto/algorithms/secret_key_util.h6
-rw-r--r--chromium/components/webcrypto/algorithms/test_helpers.cc16
-rw-r--r--chromium/components/webcrypto/algorithms/test_helpers.h4
-rw-r--r--chromium/components/webcrypto/jwk.cc5
-rw-r--r--chromium/components/webcrypto/webcrypto_impl.cc2
-rw-r--r--chromium/components/webdata/common/BUILD.gn4
-rw-r--r--chromium/components/webdata/common/web_data_service_base.h1
-rw-r--r--chromium/components/webdata/common/web_database.cc2
-rw-r--r--chromium/components/webdata/common/web_database_migration_unittest.cc133
-rw-r--r--chromium/components/webdata_services/BUILD.gn10
-rw-r--r--chromium/components/webdata_services/DEPS2
-rw-r--r--chromium/components/webdata_services/web_data_service_wrapper_factory.cc68
-rw-r--r--chromium/components/webdata_services/web_data_service_wrapper_factory.h54
-rw-r--r--chromium/components/webrtc/media_stream_devices_controller.cc8
-rw-r--r--chromium/components/webrtc_logging/browser/log_cleanup.cc10
-rw-r--r--chromium/components/webxr/android/BUILD.gn1
-rw-r--r--chromium/components/webxr/android/arcore_install_helper.cc3
-rw-r--r--chromium/components/webxr/mailbox_to_surface_bridge_impl.cc1
-rw-r--r--chromium/components/webxr/mailbox_to_surface_bridge_impl.h2
-rw-r--r--chromium/components/wifi/wifi_test.cc1
-rw-r--r--chromium/components/zoom/zoom_event_manager.h2
-rw-r--r--chromium/components/zucchini/abs32_utils.cc8
-rw-r--r--chromium/components/zucchini/abs32_utils.h8
-rw-r--r--chromium/components/zucchini/abs32_utils_unittest.cc4
-rw-r--r--chromium/components/zucchini/disassembler.cc4
-rw-r--r--chromium/components/zucchini/disassembler.h2
-rw-r--r--chromium/components/zucchini/disassembler_dex.cc18
-rw-r--r--chromium/components/zucchini/disassembler_elf.h4
-rw-r--r--chromium/components/zucchini/disassembler_win32.h4
-rw-r--r--chromium/components/zucchini/disassembler_ztf.cc8
-rw-r--r--chromium/components/zucchini/disassembler_ztf.h6
-rw-r--r--chromium/components/zucchini/element_detection.cc10
-rw-r--r--chromium/components/zucchini/element_detection.h8
-rw-r--r--chromium/components/zucchini/element_detection_unittest.cc10
-rw-r--r--chromium/components/zucchini/ensemble_matcher.cc1
-rw-r--r--chromium/components/zucchini/fuzzers/BUILD.gn7
-rw-r--r--chromium/components/zucchini/heuristic_ensemble_matcher.cc10
-rw-r--r--chromium/components/zucchini/image_utils.h4
-rw-r--r--chromium/components/zucchini/imposed_ensemble_matcher.cc4
-rw-r--r--chromium/components/zucchini/imposed_ensemble_matcher_unittest.cc6
-rw-r--r--chromium/components/zucchini/integration_test.cc4
-rw-r--r--chromium/components/zucchini/main_utils.h1
-rw-r--r--chromium/components/zucchini/patch_reader.cc56
-rw-r--r--chromium/components/zucchini/patch_reader.h20
-rw-r--r--chromium/components/zucchini/patch_writer.h10
-rw-r--r--chromium/components/zucchini/rel32_finder.cc4
-rw-r--r--chromium/components/zucchini/rel32_finder.h8
-rw-r--r--chromium/components/zucchini/rel32_finder_unittest.cc4
-rw-r--r--chromium/components/zucchini/rel32_utils.cc6
-rw-r--r--chromium/components/zucchini/rel32_utils.h24
-rw-r--r--chromium/components/zucchini/rel32_utils_unittest.cc17
-rw-r--r--chromium/components/zucchini/reloc_elf.cc8
-rw-r--r--chromium/components/zucchini/reloc_elf.h4
-rw-r--r--chromium/components/zucchini/reloc_elf_unittest.cc2
-rw-r--r--chromium/components/zucchini/reloc_win32.cc12
-rw-r--r--chromium/components/zucchini/reloc_win32.h8
-rw-r--r--chromium/components/zucchini/reloc_win32_unittest.cc2
-rw-r--r--chromium/components/zucchini/test_reference_reader.cc4
-rw-r--r--chromium/components/zucchini/test_reference_reader.h4
-rw-r--r--chromium/components/zucchini/zucchini_apply.cc4
-rw-r--r--chromium/components/zucchini/zucchini_apply.h2
-rw-r--r--chromium/components/zucchini/zucchini_gen.h2
4543 files changed, 114296 insertions, 49297 deletions
diff --git a/chromium/components/BUILD.gn b/chromium/components/BUILD.gn
index 411a8db298a..5a8cc0300fd 100644
--- a/chromium/components/BUILD.gn
+++ b/chromium/components/BUILD.gn
@@ -11,7 +11,7 @@ import("//components/safe_browsing/buildflags.gni")
import("//components/ui_devtools/devtools.gni")
import("//extensions/buildflags/buildflags.gni")
import("//media/media_options.gni")
-import("//ppapi/buildflags/buildflags.gni")
+import("//pdf/features.gni")
import("//printing/buildflags/buildflags.gni")
import("//rlz/buildflags/buildflags.gni")
import("//testing/test.gni")
@@ -68,6 +68,7 @@ test("components_unittests") {
"//components/blocklist/opt_out_blocklist/sql:unit_tests",
"//components/bookmarks/browser:unit_tests",
"//components/bookmarks/managed:unit_tests",
+ "//components/breadcrumbs/core:unit_tests",
"//components/browser_sync:unit_tests",
"//components/browsing_data/core:unit_tests",
"//components/captive_portal/core:unit_tests",
@@ -127,6 +128,7 @@ test("components_unittests") {
"//components/policy/core/common:unit_tests",
"//components/power_scheduler:unit_tests",
"//components/prefs:unit_tests",
+ "//components/profile_metrics:unit_tests",
"//components/proxy_config:unit_tests",
"//components/qr_code_generator:unit_tests",
"//components/query_parser:unit_tests",
@@ -143,6 +145,7 @@ test("components_unittests") {
"//components/search_provider_logos:unit_tests",
"//components/security_interstitials/core:unit_tests",
"//components/security_state/core:unit_tests",
+ "//components/segmentation_platform:unit_tests",
"//components/services/heap_profiling/public/cpp:unit_tests",
"//components/services/unzip:unit_tests",
"//components/sessions:unit_tests",
@@ -190,6 +193,7 @@ test("components_unittests") {
if (toolkit_views) {
deps += [
+ "//components/fullscreen_control:unit_tests",
"//components/media_message_center:unit_tests",
"//components/ui_devtools:unit_tests",
]
@@ -221,6 +225,7 @@ test("components_unittests") {
deps += [
"//components/autofill/ios/browser:unit_tests",
"//components/autofill/ios/form_util:unit_tests",
+ "//components/breadcrumbs/ios:unit_tests",
"//components/feed/core/v2:feed_core_base_unit_tests",
"//components/image_fetcher/ios:unit_tests",
"//components/language/ios/browser:unit_tests",
@@ -236,6 +241,7 @@ test("components_unittests") {
]
} else { # !is_ios
deps += [
+ "//components/android_autofill/browser:unit_tests",
"//components/autofill/content/browser:unit_tests",
"//components/autofill/content/renderer:unit_tests",
"//components/autofill/core/common/mojom:unit_tests",
@@ -338,7 +344,10 @@ test("components_unittests") {
]
if (!is_win) { # !iOS and !Windows
- deps += [ "//components/cast:unit_tests" ]
+ deps += [
+ "//components/cast:unit_tests",
+ "//components/cast_streaming:unit_tests",
+ ]
}
if (!is_fuchsia) { # !iOS and !Fuchsia
@@ -373,6 +382,7 @@ test("components_unittests") {
"//components/cdm/browser:unit_tests",
"//components/component_updater/android:embedded_component_loader_java",
"//components/component_updater/android:embedded_component_loader_unittests",
+ "//components/content_creation/notes/core:unit_tests",
"//components/crash/android:java",
"//components/crash/android:unit_tests",
"//components/download/internal/common:internal_java",
@@ -452,7 +462,6 @@ test("components_unittests") {
"//components/guest_os:unit_tests",
"//components/metrics/structured:unit_tests",
"//components/ownership:unit_tests",
- "//components/timers:unit_tests",
"//components/user_manager:unit_tests",
]
}
@@ -496,9 +505,11 @@ test("components_unittests") {
if (safe_browsing_mode == 1) {
deps += [
- "//components/safe_browsing/content/browser:client_side_model_loader_unittest",
+ "//components/safe_browsing/content/browser:unit_tests",
"//components/safe_browsing/content/renderer/phishing_classifier:unit_tests",
]
+ } else if (safe_browsing_mode == 2) {
+ deps += [ "//components/safe_browsing/content/browser:unit_tests" ]
}
if (use_dbus) {
@@ -508,7 +519,7 @@ test("components_unittests") {
]
}
- if (enable_plugins) {
+ if (enable_pdf) {
deps += [ "//components/pdf/renderer:unit_tests" ]
}
@@ -703,7 +714,7 @@ if (!is_ios && !is_fuchsia) {
data += [ "$root_out_dir/Content Shell.app/" ]
}
- if (enable_plugins) {
+ if (enable_pdf) {
sources += [
"pdf/browser/pdf_web_contents_helper_browsertest.cc",
"pdf/renderer/pdf_accessibility_tree_browsertest.cc",
@@ -830,7 +841,7 @@ if (!is_ios && !is_fuchsia) {
if (is_android) {
junit_binary("components_junit_tests") {
deps = [
- "//components/autofill/android/provider/junit:components_autofill_junit_tests",
+ "//components/android_autofill/android/junit:components_autofill_junit_tests",
"//components/background_task_scheduler:components_background_task_scheduler_junit_tests",
"//components/browser_ui/bottomsheet/android/internal:junit_tests",
"//components/browser_ui/client_certificate/android:junit",
diff --git a/chromium/components/OWNERS b/chromium/components/OWNERS
index 2f2905362cb..86101e1addb 100644
--- a/chromium/components/OWNERS
+++ b/chromium/components/OWNERS
@@ -17,8 +17,10 @@ per-file browsing_data_strings.grdp=file://components/browsing_data/OWNERS
per-file crash_strings.grdp=file://components/crash/OWNERS
per-file dom_distiller_strings.grdp=file://components/dom_distiller/OWNERS
per-file error_page_strings.grdp=file://components/error_page/OWNERS
+per-file fullscreen_control_strings.grdp=file://components/fullscreen_control/OWNERS
per-file heavy_ad_intervention_strings.grdp=file://components/heavy_ad_intervention/OWNERS
per-file javascript_dialogs_strings.grdp=file://components/javascript_dialogs/OWNERS
+per-file live_caption_strings.grdp=file://components/live_caption/OWNERS
per-file management_mobile_strings.grdp=file://components/management/OWNERS
per-file management_strings.grdp=file://docs/privacy/OWNERS
per-file media_message_center_strings.grdp=file://components/media_message_center/OWNERS
@@ -35,6 +37,7 @@ per-file pdf_strings.grdp=file://pdf/OWNERS
per-file policy_strings.grdp=file://components/policy/OWNERS
per-file print_media_strings.grdp=file://components/printing/OWNERS
per-file printing_component_strings.grdp=file://components/printing/OWNERS
+per-file privacy_sandbox_strings.grdp=file://components/privacy_sandbox/OWNERS
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
@@ -58,7 +61,7 @@ per-file PRESUBMIT.py=file://ui/webui/PLATFORM_OWNERS
per-file *.grd=claudiomagni@chromium.org
# Translation artifacts:
-per-file *.xtb=file://tools/translation/TRANSLATION_OWNERS
+per-file ....xtb=file://tools/translation/TRANSLATION_OWNERS
# This is for the common case of adding or removing tests or files. If you're
# making structural changes, please get a review from one of the overall
diff --git a/chromium/components/about_ui/android/OWNERS b/chromium/components/about_ui/android/OWNERS
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/components/about_ui/android/OWNERS
+++ /dev/null
diff --git a/chromium/components/account_id/account_id.cc b/chromium/components/account_id/account_id.cc
index ddb4c099645..d7af5f7e481 100644
--- a/chromium/components/account_id/account_id.cc
+++ b/chromium/components/account_id/account_id.cc
@@ -244,7 +244,7 @@ std::string AccountId::Serialize() const {
// static
bool AccountId::Deserialize(const std::string& serialized,
AccountId* account_id) {
- base::Optional<base::Value> value(base::JSONReader::Read(serialized));
+ absl::optional<base::Value> value(base::JSONReader::Read(serialized));
if (!value || !value->is_dict())
return false;
diff --git a/chromium/components/account_manager_core/account_addition_result.h b/chromium/components/account_manager_core/account_addition_result.h
index f4fc0080f02..6e3609c650b 100644
--- a/chromium/components/account_manager_core/account_addition_result.h
+++ b/chromium/components/account_manager_core/account_addition_result.h
@@ -5,9 +5,9 @@
#ifndef COMPONENTS_ACCOUNT_MANAGER_CORE_ACCOUNT_ADDITION_RESULT_H_
#define COMPONENTS_ACCOUNT_MANAGER_CORE_ACCOUNT_ADDITION_RESULT_H_
-#include "base/optional.h"
#include "components/account_manager_core/account.h"
#include "google_apis/gaia/google_service_auth_error.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace account_manager {
@@ -31,9 +31,9 @@ struct COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE) AccountAdditionResult {
Status status;
// The account that was added.
- base::Optional<Account> account;
+ absl::optional<Account> account;
// The error is set only if `status` is set to `kNetworkError`.
- base::Optional<GoogleServiceAuthError> error;
+ absl::optional<GoogleServiceAuthError> error;
explicit AccountAdditionResult(Status status);
AccountAdditionResult(Status status, Account account);
diff --git a/chromium/components/account_manager_core/account_manager_facade.h b/chromium/components/account_manager_core/account_manager_facade.h
index a3ae6ee04e5..93e523902ed 100644
--- a/chromium/components/account_manager_core/account_manager_facade.h
+++ b/chromium/components/account_manager_core/account_manager_facade.h
@@ -98,7 +98,7 @@ class COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE) AccountManagerFacade {
// Launches account addition dialog and calls the `callback` with the result.
// If `result` is `kSuccess`, the added account will be passed to the
- // callback. Otherwise `account` will be set to `base::nullopt`.
+ // callback. Otherwise `account` will be set to `absl::nullopt`.
virtual void ShowAddAccountDialog(
const AccountAdditionSource& source,
base::OnceCallback<void(const AccountAdditionResult& result)>
diff --git a/chromium/components/account_manager_core/account_manager_facade_impl.cc b/chromium/components/account_manager_core/account_manager_facade_impl.cc
index 1037921f2e3..61c1471ad2c 100644
--- a/chromium/components/account_manager_core/account_manager_facade_impl.cc
+++ b/chromium/components/account_manager_core/account_manager_facade_impl.cc
@@ -10,12 +10,10 @@
#include <vector>
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_functions.h"
-#include "base/optional.h"
#include "chromeos/crosapi/mojom/account_manager.mojom.h"
#include "components/account_manager_core/account.h"
#include "components/account_manager_core/account_addition_result.h"
@@ -24,6 +22,7 @@
#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_fetcher_immediate_error.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace account_manager {
@@ -40,7 +39,7 @@ void UnmarshalAccounts(
std::vector<crosapi::mojom::AccountPtr> mojo_accounts) {
std::vector<Account> accounts;
for (const auto& mojo_account : mojo_accounts) {
- base::Optional<Account> maybe_account = FromMojoAccount(mojo_account);
+ absl::optional<Account> maybe_account = FromMojoAccount(mojo_account);
if (!maybe_account) {
// Skip accounts we couldn't unmarshal. No logging, as it would produce
// a lot of noise.
@@ -54,7 +53,7 @@ void UnmarshalAccounts(
void UnmarshalPersistentError(
base::OnceCallback<void(const GoogleServiceAuthError&)> callback,
crosapi::mojom::GoogleServiceAuthErrorPtr mojo_error) {
- base::Optional<GoogleServiceAuthError> maybe_error =
+ absl::optional<GoogleServiceAuthError> maybe_error =
FromMojoGoogleServiceAuthError(mojo_error);
if (!maybe_error) {
// Couldn't unmarshal GoogleServiceAuthError, report the account as not
@@ -159,7 +158,7 @@ class AccountManagerFacadeImpl::AccessTokenFetcher
is_request_pending_ = false;
if (result->is_error()) {
- base::Optional<GoogleServiceAuthError> maybe_error =
+ absl::optional<GoogleServiceAuthError> maybe_error =
account_manager::FromMojoGoogleServiceAuthError(result->get_error());
if (!maybe_error.has_value()) {
@@ -369,7 +368,7 @@ void AccountManagerFacadeImpl::OnShowAddAccountDialogFinished(
base::OnceCallback<
void(const account_manager::AccountAdditionResult& result)> callback,
crosapi::mojom::AccountAdditionResultPtr mojo_result) {
- base::Optional<account_manager::AccountAdditionResult> result =
+ absl::optional<account_manager::AccountAdditionResult> result =
account_manager::FromMojoAccountAdditionResult(mojo_result);
if (!result.has_value()) {
FinishAddAccount(std::move(callback),
@@ -391,7 +390,7 @@ void AccountManagerFacadeImpl::FinishAddAccount(
void AccountManagerFacadeImpl::OnTokenUpserted(
crosapi::mojom::AccountPtr account) {
- base::Optional<Account> maybe_account = FromMojoAccount(account);
+ absl::optional<Account> maybe_account = FromMojoAccount(account);
if (!maybe_account) {
LOG(WARNING) << "Can't unmarshal account of type: "
<< account->key->account_type;
@@ -404,7 +403,7 @@ void AccountManagerFacadeImpl::OnTokenUpserted(
void AccountManagerFacadeImpl::OnAccountRemoved(
crosapi::mojom::AccountPtr account) {
- base::Optional<Account> maybe_account = FromMojoAccount(account);
+ absl::optional<Account> maybe_account = FromMojoAccount(account);
if (!maybe_account) {
LOG(WARNING) << "Can't unmarshal account of type: "
<< account->key->account_type;
diff --git a/chromium/components/account_manager_core/account_manager_facade_impl_unittest.cc b/chromium/components/account_manager_core/account_manager_facade_impl_unittest.cc
index 897c93887e9..dac44991d51 100644
--- a/chromium/components/account_manager_core/account_manager_facade_impl_unittest.cc
+++ b/chromium/components/account_manager_core/account_manager_facade_impl_unittest.cc
@@ -140,7 +140,7 @@ class FakeAccountManager : public crosapi::mojom::AccountManager {
void GetPersistentErrorForAccount(
crosapi::mojom::AccountKeyPtr mojo_account_key,
GetPersistentErrorForAccountCallback callback) override {
- base::Optional<AccountKey> account_key =
+ absl::optional<AccountKey> account_key =
FromMojoAccountKey(mojo_account_key);
DCHECK(account_key.has_value());
auto it = persistent_errors_.find(account_key.value());
diff --git a/chromium/components/account_manager_core/account_manager_util.cc b/chromium/components/account_manager_core/account_manager_util.cc
index 4312eead686..3fdf9ecc7e4 100644
--- a/chromium/components/account_manager_core/account_manager_util.cc
+++ b/chromium/components/account_manager_core/account_manager_util.cc
@@ -91,7 +91,7 @@ crosapi::mojom::GoogleServiceAuthError::State ToMojoGoogleServiceAuthErrorState(
}
}
-base::Optional<account_manager::AccountAdditionResult::Status>
+absl::optional<account_manager::AccountAdditionResult::Status>
FromMojoAccountAdditionStatus(
crosapi::mojom::AccountAdditionResult::Status mojo_status) {
switch (mojo_status) {
@@ -109,7 +109,7 @@ FromMojoAccountAdditionStatus(
default:
LOG(WARNING) << "Unknown crosapi::mojom::AccountAdditionResult::Status: "
<< mojo_status;
- return base::nullopt;
+ return absl::nullopt;
}
}
@@ -131,12 +131,12 @@ crosapi::mojom::AccountAdditionResult::Status ToMojoAccountAdditionStatus(
} // namespace
-base::Optional<account_manager::Account> FromMojoAccount(
+absl::optional<account_manager::Account> FromMojoAccount(
const crosapi::mojom::AccountPtr& mojom_account) {
- const base::Optional<account_manager::AccountKey> account_key =
+ const absl::optional<account_manager::AccountKey> account_key =
FromMojoAccountKey(mojom_account->key);
if (!account_key.has_value())
- return base::nullopt;
+ return absl::nullopt;
account_manager::Account account;
account.key = account_key.value();
@@ -152,12 +152,12 @@ crosapi::mojom::AccountPtr ToMojoAccount(
return mojom_account;
}
-base::Optional<account_manager::AccountKey> FromMojoAccountKey(
+absl::optional<account_manager::AccountKey> FromMojoAccountKey(
const crosapi::mojom::AccountKeyPtr& mojom_account_key) {
- const base::Optional<account_manager::AccountType> account_type =
+ const absl::optional<account_manager::AccountType> account_type =
FromMojoAccountType(mojom_account_key->account_type);
if (!account_type.has_value())
- return base::nullopt;
+ return absl::nullopt;
account_manager::AccountKey account_key;
account_key.id = mojom_account_key->id;
@@ -174,7 +174,7 @@ crosapi::mojom::AccountKeyPtr ToMojoAccountKey(
return mojom_account_key;
}
-base::Optional<account_manager::AccountType> FromMojoAccountType(
+absl::optional<account_manager::AccountType> FromMojoAccountType(
const crosapi::mojom::AccountType& account_type) {
switch (account_type) {
case crosapi::mojom::AccountType::kGaia:
@@ -192,7 +192,7 @@ base::Optional<account_manager::AccountType> FromMojoAccountType(
// Don't consider this as as error to preserve forwards compatibility with
// lacros.
LOG(WARNING) << "Unknown account type: " << account_type;
- return base::nullopt;
+ return absl::nullopt;
}
}
@@ -206,7 +206,7 @@ crosapi::mojom::AccountType ToMojoAccountType(
}
}
-base::Optional<GoogleServiceAuthError> FromMojoGoogleServiceAuthError(
+absl::optional<GoogleServiceAuthError> FromMojoGoogleServiceAuthError(
const crosapi::mojom::GoogleServiceAuthErrorPtr& mojo_error) {
switch (mojo_error->state) {
case cm::GoogleServiceAuthError::State::kNone:
@@ -236,7 +236,7 @@ base::Optional<GoogleServiceAuthError> FromMojoGoogleServiceAuthError(
default:
LOG(WARNING) << "Unknown crosapi::mojom::GoogleServiceAuthError::State: "
<< mojo_error->state;
- return base::nullopt;
+ return absl::nullopt;
}
}
@@ -258,13 +258,13 @@ crosapi::mojom::GoogleServiceAuthErrorPtr ToMojoGoogleServiceAuthError(
return mojo_result;
}
-base::Optional<account_manager::AccountAdditionResult>
+absl::optional<account_manager::AccountAdditionResult>
FromMojoAccountAdditionResult(
const crosapi::mojom::AccountAdditionResultPtr& mojo_result) {
- base::Optional<account_manager::AccountAdditionResult::Status> status =
+ absl::optional<account_manager::AccountAdditionResult::Status> status =
FromMojoAccountAdditionStatus(mojo_result->status);
if (!status.has_value()) {
- return base::nullopt;
+ return absl::nullopt;
}
account_manager::AccountAdditionResult result(status.value());
result.status = status.value();
diff --git a/chromium/components/account_manager_core/account_manager_util.h b/chromium/components/account_manager_core/account_manager_util.h
index ce20307382d..690d6969b5a 100644
--- a/chromium/components/account_manager_core/account_manager_util.h
+++ b/chromium/components/account_manager_core/account_manager_util.h
@@ -5,47 +5,47 @@
#ifndef COMPONENTS_ACCOUNT_MANAGER_CORE_ACCOUNT_MANAGER_UTIL_H_
#define COMPONENTS_ACCOUNT_MANAGER_CORE_ACCOUNT_MANAGER_UTIL_H_
-#include "base/optional.h"
#include "chromeos/crosapi/mojom/account_manager.mojom.h"
#include "components/account_manager_core/account.h"
#include "components/account_manager_core/account_addition_result.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GoogleServiceAuthError;
namespace account_manager {
-// Returns `base::nullopt` if `mojom_account` cannot be parsed.
+// Returns `absl::nullopt` if `mojom_account` cannot be parsed.
COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE)
-base::Optional<account_manager::Account> FromMojoAccount(
+absl::optional<account_manager::Account> FromMojoAccount(
const crosapi::mojom::AccountPtr& mojom_account);
COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE)
crosapi::mojom::AccountPtr ToMojoAccount(
const account_manager::Account& account);
-// Returns `base::nullopt` if `mojom_account_key` cannot be parsed.
+// Returns `absl::nullopt` if `mojom_account_key` cannot be parsed.
COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE)
-base::Optional<account_manager::AccountKey> FromMojoAccountKey(
+absl::optional<account_manager::AccountKey> FromMojoAccountKey(
const crosapi::mojom::AccountKeyPtr& mojom_account_key);
COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE)
crosapi::mojom::AccountKeyPtr ToMojoAccountKey(
const account_manager::AccountKey& account_key);
-// Returns `base::nullopt` if `account_type` cannot be parsed.
+// Returns `absl::nullopt` if `account_type` cannot be parsed.
COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE)
-base::Optional<account_manager::AccountType> FromMojoAccountType(
+absl::optional<account_manager::AccountType> FromMojoAccountType(
const crosapi::mojom::AccountType& account_type);
COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE)
crosapi::mojom::AccountType ToMojoAccountType(
const account_manager::AccountType& account_type);
-// Returns `base::nullopt` if `mojo_error` cannot be parsed. This probably means
+// Returns `absl::nullopt` if `mojo_error` cannot be parsed. This probably means
// that a new error type was added, so it should be considered a persistent
// error.
COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE)
-base::Optional<GoogleServiceAuthError> FromMojoGoogleServiceAuthError(
+absl::optional<GoogleServiceAuthError> FromMojoGoogleServiceAuthError(
const crosapi::mojom::GoogleServiceAuthErrorPtr& mojo_error);
COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE)
@@ -53,7 +53,7 @@ crosapi::mojom::GoogleServiceAuthErrorPtr ToMojoGoogleServiceAuthError(
GoogleServiceAuthError error);
COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE)
-base::Optional<account_manager::AccountAdditionResult>
+absl::optional<account_manager::AccountAdditionResult>
FromMojoAccountAdditionResult(
const crosapi::mojom::AccountAdditionResultPtr& mojo_result);
diff --git a/chromium/components/android_autofill/DEPS b/chromium/components/android_autofill/DEPS
new file mode 100644
index 00000000000..6a6f1599851
--- /dev/null
+++ b/chromium/components/android_autofill/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+ "+components/autofill",
+ "+content/public/browser",
+ "+ui",
+]
diff --git a/chromium/components/autofill/android/provider/OWNERS b/chromium/components/android_autofill/OWNERS
index 44a22b15980..c57a48c66de 100644
--- a/chromium/components/autofill/android/provider/OWNERS
+++ b/chromium/components/android_autofill/OWNERS
@@ -1,2 +1,2 @@
michaelbai@chromium.org
-
+battre@chromium.org
diff --git a/chromium/components/autofill/android/provider/BUILD.gn b/chromium/components/android_autofill/android/BUILD.gn
index 80afa602c4d..8c8016c52ab 100644
--- a/chromium/components/autofill/android/provider/BUILD.gn
+++ b/chromium/components/android_autofill/android/BUILD.gn
@@ -46,7 +46,7 @@ generate_jni("jni_headers") {
]
}
-static_library("provider") {
+static_library("android") {
sources = [
"autofill_provider_android.cc",
"autofill_provider_android.h",
@@ -55,9 +55,9 @@ static_library("provider") {
"form_field_data_android.cc",
"form_field_data_android.h",
]
+ public_deps = [ "//components/android_autofill/browser" ]
deps = [
":jni_headers",
- "//components/autofill/core/browser:browser",
"//content/public/browser",
"//ui/android",
]
diff --git a/chromium/components/autofill/android/provider/DEPS b/chromium/components/android_autofill/android/DEPS
index 1bc851ebbbd..fd3f4c796bb 100644
--- a/chromium/components/autofill/android/provider/DEPS
+++ b/chromium/components/android_autofill/android/DEPS
@@ -1,3 +1,5 @@
include_rules = [
+ "+content/public/android",
"+components/autofill/content",
+ "+ui/android",
]
diff --git a/chromium/components/autofill/android/provider/autofill_provider_android.cc b/chromium/components/android_autofill/android/autofill_provider_android.cc
index 433d710b869..f38a27a3558 100644
--- a/chromium/components/autofill/android/provider/autofill_provider_android.cc
+++ b/chromium/components/android_autofill/android/autofill_provider_android.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/android/provider/autofill_provider_android.h"
+#include "components/android_autofill/android/autofill_provider_android.h"
#include <memory>
@@ -10,10 +10,10 @@
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/feature_list.h"
-#include "components/autofill/android/provider/form_data_android.h"
-#include "components/autofill/android/provider/jni_headers/AutofillProvider_jni.h"
+#include "components/android_autofill/android/form_data_android.h"
+#include "components/android_autofill/android/jni_headers/AutofillProvider_jni.h"
+#include "components/android_autofill/browser/android_autofill_manager.h"
#include "components/autofill/core/browser/autofill_driver.h"
-#include "components/autofill/core/browser/autofill_handler_proxy.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "content/public/browser/browser_thread.h"
@@ -25,6 +25,7 @@ using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertUTF16ToJavaString;
using base::android::ConvertUTF8ToJavaString;
+using base::android::JavaParamRef;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
using base::android::ToJavaArrayOfStrings;
@@ -36,39 +37,53 @@ namespace autofill {
using mojom::SubmissionSource;
+static jlong JNI_AutofillProvider_Init(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& jcaller,
+ const JavaParamRef<jobject>& jweb_contents) {
+ auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents);
+ DCHECK(web_contents);
+ auto* provider = AutofillProvider::FromWebContents(web_contents);
+ if (provider) {
+ static_cast<AutofillProviderAndroid*>(provider)
+ ->AttachToJavaAutofillProvider(env, jcaller);
+ return reinterpret_cast<intptr_t>(provider);
+ }
+ return reinterpret_cast<intptr_t>(
+ AutofillProviderAndroid::Create(env, jcaller, web_contents));
+}
+
static jboolean JNI_AutofillProvider_IsQueryServerFieldTypesEnabled(
JNIEnv* env) {
return base::FeatureList::IsEnabled(
features::kAndroidAutofillQueryServerFieldTypes);
}
-AutofillProviderAndroid::AutofillProviderAndroid(
+// Static
+AutofillProviderAndroid* AutofillProviderAndroid::Create(
+ JNIEnv* env,
const JavaRef<jobject>& jcaller,
- content::WebContents* web_contents)
- : id_(kNoQueryId), web_contents_(web_contents), check_submission_(false) {
- OnJavaAutofillProviderChanged(AttachCurrentThread(), jcaller);
+ content::WebContents* web_contents) {
+ DCHECK(!FromWebContents(web_contents));
+ // This object is owned by WebContents.
+ return new AutofillProviderAndroid(env, jcaller, web_contents);
}
-void AutofillProviderAndroid::OnJavaAutofillProviderChanged(
- JNIEnv* env,
- const JavaRef<jobject>& jcaller) {
- // If the current Java object isn't null (e.g., because it hasn't been
- // garbage-collected yet), clear its reference to this object.
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (!obj.is_null()) {
- Java_AutofillProvider_setNativeAutofillProvider(env, obj, 0);
- }
-
- java_ref_ = JavaObjectWeakGlobalRef(env, jcaller);
-
- // If the new Java object isn't null, set its native object to |this|.
- obj = java_ref_.get(env);
- if (!obj.is_null()) {
- Java_AutofillProvider_setNativeAutofillProvider(
- env, obj, reinterpret_cast<jlong>(this));
- }
+AutofillProviderAndroid* AutofillProviderAndroid::FromWebContents(
+ content::WebContents* web_contents) {
+ return static_cast<AutofillProviderAndroid*>(
+ AutofillProvider::FromWebContents(web_contents));
}
+AutofillProviderAndroid::AutofillProviderAndroid(
+ JNIEnv* env,
+ const JavaRef<jobject>& jcaller,
+ content::WebContents* web_contents)
+ : AutofillProvider(web_contents),
+ id_(kNoQueryId),
+ java_ref_(JavaObjectWeakGlobalRef(env, jcaller)),
+ check_submission_(false) {}
+
AutofillProviderAndroid::~AutofillProviderAndroid() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
@@ -79,8 +94,20 @@ AutofillProviderAndroid::~AutofillProviderAndroid() {
Java_AutofillProvider_setNativeAutofillProvider(env, obj, 0);
}
+void AutofillProviderAndroid::AttachToJavaAutofillProvider(
+ JNIEnv* env,
+ const JavaRef<jobject>& jcaller) {
+ DCHECK(java_ref_.get(env).is_null());
+ java_ref_ = JavaObjectWeakGlobalRef(env, jcaller);
+}
+
+void AutofillProviderAndroid::DetachFromJavaAutofillProvider(JNIEnv* env) {
+ // Reset the reference to Java peer.
+ java_ref_.reset();
+}
+
void AutofillProviderAndroid::OnQueryFormFieldAutofill(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
int32_t id,
const FormData& form,
const FormFieldData& field,
@@ -94,7 +121,7 @@ void AutofillProviderAndroid::OnQueryFormFieldAutofill(
// Focus or field value change will also trigger the query, so it should be
// ignored if the form is same.
- MaybeStartNewSession(handler, form, field, bounding_box);
+ MaybeStartNewSession(manager, form, field, bounding_box);
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
@@ -113,18 +140,18 @@ void AutofillProviderAndroid::OnQueryFormFieldAutofill(
}
void AutofillProviderAndroid::MaybeStartNewSession(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) {
// Don't start a new session when the new form is similar to the old form, the
- // new handler is the same as the current handler, and the coordinates of the
+ // new manager is the same as the current manager, and the coordinates of the
// relevant form field haven't changed.
if (form_ && form_->SimilarFormAs(form) &&
- IsCurrentlyLinkedHandler(handler)) {
+ IsCurrentlyLinkedManager(manager)) {
size_t index;
if (form_->GetFieldIndex(field, &index) &&
- handler->driver()->TransformBoundingBoxToViewportCoordinates(
+ manager->driver()->TransformBoundingBoxToViewportCoordinates(
form.fields[index].bounds) == form_->form().fields[index].bounds) {
return;
}
@@ -138,7 +165,7 @@ void AutofillProviderAndroid::MaybeStartNewSession(
form_ = std::make_unique<FormDataAndroid>(
form, base::BindRepeating(
&AutofillDriver::TransformBoundingBoxToViewportCoordinates,
- base::Unretained(handler->driver())));
+ base::Unretained(manager->driver())));
field_id_ = field.global_id();
size_t index;
@@ -149,27 +176,27 @@ void AutofillProviderAndroid::MaybeStartNewSession(
FormStructure* form_structure = nullptr;
AutofillField* autofill_field = nullptr;
- if (!handler->GetCachedFormAndField(form, field, &form_structure,
+ if (!manager->GetCachedFormAndField(form, field, &form_structure,
&autofill_field)) {
form_structure = nullptr;
}
gfx::RectF transformed_bounding = ToClientAreaBound(bounding_box);
ScopedJavaLocalRef<jobject> form_obj = form_->GetJavaPeer(form_structure);
- handler_ = handler->GetWeakPtr();
+ manager_ = manager->GetWeakPtr();
Java_AutofillProvider_startAutofillSession(
env, obj, form_obj, index, transformed_bounding.x(),
transformed_bounding.y(), transformed_bounding.width(),
- transformed_bounding.height(), handler->has_server_prediction());
+ transformed_bounding.height(), manager->has_server_prediction());
}
void AutofillProviderAndroid::OnAutofillAvailable(JNIEnv* env,
jobject jcaller,
jobject formData) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (handler_ && form_) {
+ if (manager_ && form_) {
const FormData& form = form_->GetAutofillValues();
- SendFormDataToRenderer(handler_.get(), id_, form);
+ SendFormDataToRenderer(manager_.get(), id_, form);
}
}
@@ -177,9 +204,9 @@ void AutofillProviderAndroid::OnAcceptDataListSuggestion(JNIEnv* env,
jobject jcaller,
jstring value) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (auto* handler = handler_.get()) {
+ if (auto* manager = manager_.get()) {
RendererShouldAcceptDataListSuggestion(
- handler, field_id_, ConvertJavaStringToUTF16(env, value));
+ manager, field_id_, ConvertJavaStringToUTF16(env, value));
}
}
@@ -190,7 +217,7 @@ void AutofillProviderAndroid::SetAnchorViewRect(JNIEnv* env,
jfloat y,
jfloat width,
jfloat height) {
- ui::ViewAndroid* view_android = web_contents_->GetNativeView();
+ ui::ViewAndroid* view_android = web_contents()->GetNativeView();
if (!view_android)
return;
@@ -199,22 +226,22 @@ void AutofillProviderAndroid::SetAnchorViewRect(JNIEnv* env,
}
void AutofillProviderAndroid::OnTextFieldDidChange(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
const base::TimeTicks timestamp) {
- FireFormFieldDidChanged(handler, form, field, bounding_box);
+ FireFormFieldDidChanged(manager, form, field, bounding_box);
}
void AutofillProviderAndroid::OnTextFieldDidScroll(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
size_t index;
- if (!IsCurrentlyLinkedHandler(handler) || !IsCurrentlyLinkedForm(form) ||
+ if (!IsCurrentlyLinkedManager(manager) || !IsCurrentlyLinkedForm(form) ||
!form_->GetSimilarFieldIndex(field, &index))
return;
@@ -231,12 +258,12 @@ void AutofillProviderAndroid::OnTextFieldDidScroll(
}
void AutofillProviderAndroid::OnSelectControlDidChange(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) {
- MaybeStartNewSession(handler, form, field, bounding_box);
- FireFormFieldDidChanged(handler, form, field, bounding_box);
+ MaybeStartNewSession(manager, form, field, bounding_box);
+ FireFormFieldDidChanged(manager, form, field, bounding_box);
}
void AutofillProviderAndroid::FireSuccessfulSubmission(
@@ -250,12 +277,12 @@ void AutofillProviderAndroid::FireSuccessfulSubmission(
Reset();
}
-void AutofillProviderAndroid::OnFormSubmitted(AutofillHandlerProxy* handler,
+void AutofillProviderAndroid::OnFormSubmitted(AndroidAutofillManager* manager,
const FormData& form,
bool known_success,
SubmissionSource source) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!IsCurrentlyLinkedHandler(handler) || !IsCurrentlyLinkedForm(form))
+ if (!IsCurrentlyLinkedManager(manager) || !IsCurrentlyLinkedForm(form))
return;
if (known_success || source == SubmissionSource::FORM_SUBMISSION) {
@@ -268,24 +295,24 @@ void AutofillProviderAndroid::OnFormSubmitted(AutofillHandlerProxy* handler,
}
void AutofillProviderAndroid::OnFocusNoLongerOnForm(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
bool had_interacted_form) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!IsCurrentlyLinkedHandler(handler))
+ if (!IsCurrentlyLinkedManager(manager))
return;
OnFocusChanged(false, 0, RectF());
}
void AutofillProviderAndroid::OnFocusOnFormField(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
size_t index;
- if (!IsCurrentlyLinkedHandler(handler) || !IsCurrentlyLinkedForm(form) ||
+ if (!IsCurrentlyLinkedManager(manager) || !IsCurrentlyLinkedForm(form) ||
!form_->GetSimilarFieldIndex(field, &index))
return;
@@ -311,13 +338,13 @@ void AutofillProviderAndroid::OnFocusChanged(bool focus_on_form,
}
void AutofillProviderAndroid::FireFormFieldDidChanged(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
size_t index;
- if (!IsCurrentlyLinkedHandler(handler) || !IsCurrentlyLinkedForm(form) ||
+ if (!IsCurrentlyLinkedManager(manager) || !IsCurrentlyLinkedForm(form) ||
!form_->GetSimilarFieldIndex(field, &index))
return;
@@ -334,11 +361,11 @@ void AutofillProviderAndroid::FireFormFieldDidChanged(
}
void AutofillProviderAndroid::OnDidFillAutofillFormData(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
const FormData& form,
base::TimeTicks timestamp) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (handler != handler_.get() || !IsCurrentlyLinkedForm(form))
+ if (manager != manager_.get() || !IsCurrentlyLinkedForm(form))
return;
JNIEnv* env = AttachCurrentThread();
@@ -349,12 +376,12 @@ void AutofillProviderAndroid::OnDidFillAutofillFormData(
Java_AutofillProvider_onDidFillAutofillFormData(env, obj);
}
-void AutofillProviderAndroid::OnFormsSeen(AutofillHandlerProxy* handler,
+void AutofillProviderAndroid::OnFormsSeen(AndroidAutofillManager* manager,
const std::vector<FormData>& forms) {}
-void AutofillProviderAndroid::OnHidePopup(AutofillHandlerProxy* handler) {
+void AutofillProviderAndroid::OnHidePopup(AndroidAutofillManager* manager) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (handler == handler_.get()) {
+ if (manager == manager_.get()) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
@@ -365,13 +392,13 @@ void AutofillProviderAndroid::OnHidePopup(AutofillHandlerProxy* handler) {
}
void AutofillProviderAndroid::OnServerPredictionsAvailable(
- AutofillHandlerProxy* handler) {
+ AndroidAutofillManager* manager) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (handler != handler_.get() || !form_.get())
+ if (manager != manager_.get() || !form_.get())
return;
if (auto* form_structure =
- handler_->FindCachedFormByRendererId(form_->form().global_id())) {
+ manager_->FindCachedFormByRendererId(form_->form().global_id())) {
form_->UpdateFieldTypes(*form_structure);
JNIEnv* env = AttachCurrentThread();
@@ -384,13 +411,13 @@ void AutofillProviderAndroid::OnServerPredictionsAvailable(
}
void AutofillProviderAndroid::OnServerQueryRequestError(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
FormSignature form_signature) {
- if (!IsCurrentlyLinkedHandler(handler) || !form_.get())
+ if (!IsCurrentlyLinkedManager(manager) || !form_.get())
return;
if (auto* form_structure =
- handler_->FindCachedFormByRendererId(form_->form().global_id())) {
+ manager_->FindCachedFormByRendererId(form_->form().global_id())) {
if (form_structure->form_signature() != form_signature)
return;
@@ -403,9 +430,9 @@ void AutofillProviderAndroid::OnServerQueryRequestError(
}
}
-void AutofillProviderAndroid::Reset(AutofillHandlerProxy* handler) {
+void AutofillProviderAndroid::Reset(AndroidAutofillManager* manager) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (handler == handler_.get()) {
+ if (manager == manager_.get()) {
// If we previously received a notification from the renderer that the form
// was likely submitted and no event caused a reset of state in the interim,
// we consider this navigation to be resulting from the submission.
@@ -423,9 +450,9 @@ void AutofillProviderAndroid::Reset(AutofillHandlerProxy* handler) {
}
}
-bool AutofillProviderAndroid::IsCurrentlyLinkedHandler(
- AutofillHandlerProxy* handler) {
- return handler == handler_.get();
+bool AutofillProviderAndroid::IsCurrentlyLinkedManager(
+ AndroidAutofillManager* manager) {
+ return manager == manager_.get();
}
bool AutofillProviderAndroid::IsCurrentlyLinkedForm(const FormData& form) {
@@ -434,7 +461,7 @@ bool AutofillProviderAndroid::IsCurrentlyLinkedForm(const FormData& form) {
gfx::RectF AutofillProviderAndroid::ToClientAreaBound(
const gfx::RectF& bounding_box) {
- gfx::Rect client_area = web_contents_->GetContainerBounds();
+ gfx::Rect client_area = web_contents()->GetContainerBounds();
return bounding_box + client_area.OffsetFromOrigin();
}
diff --git a/chromium/components/autofill/android/provider/autofill_provider_android.h b/chromium/components/android_autofill/android/autofill_provider_android.h
index f2ffedc58b9..64af9790654 100644
--- a/chromium/components/autofill/android/provider/autofill_provider_android.h
+++ b/chromium/components/android_autofill/android/autofill_provider_android.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_AUTOFILL_ANDROID_PROVIDER_AUTOFILL_PROVIDER_ANDROID_H_
-#define COMPONENTS_AUTOFILL_ANDROID_PROVIDER_AUTOFILL_PROVIDER_ANDROID_H_
+#ifndef COMPONENTS_ANDROID_AUTOFILL_ANDROID_AUTOFILL_PROVIDER_ANDROID_H_
+#define COMPONENTS_ANDROID_AUTOFILL_ANDROID_AUTOFILL_PROVIDER_ANDROID_H_
#include "base/android/jni_weak_ref.h"
#include "base/memory/weak_ptr.h"
-#include "components/autofill/core/browser/autofill_provider.h"
+#include "components/android_autofill/browser/autofill_provider.h"
#include "components/autofill/core/common/unique_ids.h"
namespace content {
@@ -20,60 +20,71 @@ class FormDataAndroid;
// Android implementation of AutofillProvider, it has one instance per
// WebContents, this class is native peer of AutofillProvider.java.
+// This class is always instantialized by AutofillProvider Java object.
class AutofillProviderAndroid : public AutofillProvider {
public:
- AutofillProviderAndroid(const base::android::JavaRef<jobject>& jcaller,
- content::WebContents* web_contents);
- // Invoked when the Java-side AutofillProvider counterpart of this object
- // has been changed (either to null or to a new object).
- void OnJavaAutofillProviderChanged(
+ static AutofillProviderAndroid* Create(
JNIEnv* env,
- const base::android::JavaRef<jobject>& jcaller);
+ const base::android::JavaRef<jobject>& jcaller,
+ content::WebContents* web_contents);
+
+ static AutofillProviderAndroid* FromWebContents(
+ content::WebContents* web_contents);
~AutofillProviderAndroid() override;
+ // Attach this detached object to |jcaller|.
+ void AttachToJavaAutofillProvider(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& jcaller);
+
+ // Invoked when the WebContents that associates with Java AutofillProvider
+ // is changed or Java AutofillProvider is destroyed, it indicates this
+ // AutofillProviderAndroid object shall not talk to its Java peer anymore.
+ void DetachFromJavaAutofillProvider(JNIEnv* env);
+
// AutofillProvider:
void OnQueryFormFieldAutofill(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
int32_t id,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
bool /*unused_autoselect_first_suggestion*/) override;
- void OnTextFieldDidChange(AutofillHandlerProxy* handler,
+ void OnTextFieldDidChange(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
const base::TimeTicks timestamp) override;
- void OnTextFieldDidScroll(AutofillHandlerProxy* handler,
+ void OnTextFieldDidScroll(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) override;
- void OnSelectControlDidChange(AutofillHandlerProxy* handler,
+ void OnSelectControlDidChange(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) override;
- void OnFormSubmitted(AutofillHandlerProxy* handler,
+ void OnFormSubmitted(AndroidAutofillManager* manager,
const FormData& form,
bool known_success,
mojom::SubmissionSource source) override;
- void OnFocusNoLongerOnForm(AutofillHandlerProxy* handler,
+ void OnFocusNoLongerOnForm(AndroidAutofillManager* manager,
bool had_interacted_form) override;
- void OnFocusOnFormField(AutofillHandlerProxy* handler,
+ void OnFocusOnFormField(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) override;
- void OnDidFillAutofillFormData(AutofillHandlerProxy* handler,
+ void OnDidFillAutofillFormData(AndroidAutofillManager* manager,
const FormData& form,
base::TimeTicks timestamp) override;
- void OnFormsSeen(AutofillHandlerProxy* handler,
+ void OnFormsSeen(AndroidAutofillManager* manager,
const std::vector<FormData>& forms) override;
- void OnHidePopup(AutofillHandlerProxy* handler) override;
- void OnServerPredictionsAvailable(AutofillHandlerProxy* handler) override;
- void OnServerQueryRequestError(AutofillHandlerProxy* handler,
+ void OnHidePopup(AndroidAutofillManager* manager) override;
+ void OnServerPredictionsAvailable(AndroidAutofillManager* manager) override;
+ void OnServerQueryRequestError(AndroidAutofillManager* manager,
FormSignature form_signature) override;
- void Reset(AutofillHandlerProxy* handler) override;
+ void Reset(AndroidAutofillManager* manager) override;
// Methods called by Java.
void OnAutofillAvailable(JNIEnv* env, jobject jcaller, jobject form_data);
@@ -88,24 +99,28 @@ class AutofillProviderAndroid : public AutofillProvider {
jfloat height);
private:
+ AutofillProviderAndroid(JNIEnv* env,
+ const base::android::JavaRef<jobject>& jcaller,
+ content::WebContents* web_contents);
+
void FireSuccessfulSubmission(mojom::SubmissionSource source);
void OnFocusChanged(bool focus_on_form,
size_t index,
const gfx::RectF& bounding_box);
- void FireFormFieldDidChanged(AutofillHandlerProxy* handler,
+ void FireFormFieldDidChanged(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box);
- bool IsCurrentlyLinkedHandler(AutofillHandlerProxy* handler);
+ bool IsCurrentlyLinkedManager(AndroidAutofillManager* manager);
bool IsCurrentlyLinkedForm(const FormData& form);
gfx::RectF ToClientAreaBound(const gfx::RectF& bounding_box);
- // Starts a new session, but only if |form| or |handler| doesn't match the
+ // Starts a new session, but only if |form| or |manager| doesn't match the
// current session.
- void MaybeStartNewSession(AutofillHandlerProxy* handler,
+ void MaybeStartNewSession(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box);
@@ -115,9 +130,8 @@ class AutofillProviderAndroid : public AutofillProvider {
int32_t id_;
std::unique_ptr<FormDataAndroid> form_;
FieldGlobalId field_id_;
- base::WeakPtr<AutofillHandlerProxy> handler_;
+ base::WeakPtr<AndroidAutofillManager> manager_;
JavaObjectWeakGlobalRef java_ref_;
- content::WebContents* web_contents_;
bool check_submission_;
// Valid only if check_submission_ is true.
mojom::SubmissionSource pending_submission_source_;
@@ -126,4 +140,4 @@ class AutofillProviderAndroid : public AutofillProvider {
};
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_ANDROID_PROVIDER_AUTOFILL_PROVIDER_ANDROID_H_
+#endif // COMPONENTS_ANDROID_AUTOFILL_ANDROID_AUTOFILL_PROVIDER_ANDROID_H_
diff --git a/chromium/components/autofill/android/provider/form_data_android.cc b/chromium/components/android_autofill/android/form_data_android.cc
index 79a43b17789..e848e45f88b 100644
--- a/chromium/components/autofill/android/provider/form_data_android.cc
+++ b/chromium/components/android_autofill/android/form_data_android.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/autofill/android/provider/form_data_android.h"
+#include "components/android_autofill/android/form_data_android.h"
+
+#include <memory>
#include "base/android/jni_string.h"
-#include "components/autofill/android/provider/form_field_data_android.h"
-#include "components/autofill/android/provider/jni_headers/FormData_jni.h"
+#include "components/android_autofill/android/form_field_data_android.h"
+#include "components/android_autofill/android/jni_headers/FormData_jni.h"
#include "components/autofill/core/browser/form_structure.h"
using base::android::AttachCurrentThread;
@@ -36,8 +38,8 @@ ScopedJavaLocalRef<jobject> FormDataAndroid::GetJavaPeer(
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null()) {
for (size_t i = 0; i < form_.fields.size(); ++i) {
- fields_.push_back(std::unique_ptr<FormFieldDataAndroid>(
- new FormFieldDataAndroid(&form_.fields[i])));
+ fields_.push_back(
+ std::make_unique<FormFieldDataAndroid>(&form_.fields[i]));
}
if (form_structure)
UpdateFieldTypes(*form_structure);
@@ -97,7 +99,10 @@ bool FormDataAndroid::SimilarFormAs(const FormData& form) {
}
void FormDataAndroid::UpdateFieldTypes(const FormStructure& form_structure) {
- DCHECK(form_structure.field_count() == fields_.size());
+ // This form has been changed after the query starts, ignore this response,
+ // new one is on the way.
+ if (form_structure.field_count() != fields_.size())
+ return;
auto form_field_data_android = fields_.begin();
for (const auto& autofill_field : form_structure) {
DCHECK(form_field_data_android->get()->SimilarFieldAs(*autofill_field));
diff --git a/chromium/components/autofill/android/provider/form_data_android.h b/chromium/components/android_autofill/android/form_data_android.h
index b6f658554e9..454d7dc8363 100644
--- a/chromium/components/autofill/android/provider/form_data_android.h
+++ b/chromium/components/android_autofill/android/form_data_android.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_ANDROID_PROVIDER_FORM_DATA_ANDROID_H_
-#define COMPONENTS_AUTOFILL_ANDROID_PROVIDER_FORM_DATA_ANDROID_H_
+#ifndef COMPONENTS_ANDROID_AUTOFILL_ANDROID_FORM_DATA_ANDROID_H_
+#define COMPONENTS_ANDROID_AUTOFILL_ANDROID_FORM_DATA_ANDROID_H_
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
@@ -71,4 +71,4 @@ class FormDataAndroid {
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_ANDROID_PROVIDER_FORM_DATA_ANDROID_H_
+#endif // COMPONENTS_ANDROID_AUTOFILL_ANDROID_FORM_DATA_ANDROID_H_
diff --git a/chromium/components/autofill/android/provider/form_field_data_android.cc b/chromium/components/android_autofill/android/form_field_data_android.cc
index 7603d83167b..6ba4a6b4050 100644
--- a/chromium/components/autofill/android/provider/form_field_data_android.cc
+++ b/chromium/components/android_autofill/android/form_field_data_android.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/autofill/android/provider/form_field_data_android.h"
+#include "components/android_autofill/android/form_field_data_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
-#include "components/autofill/android/provider/jni_headers/FormFieldData_jni.h"
+#include "components/android_autofill/android/jni_headers/FormFieldData_jni.h"
#include "components/autofill/core/common/autofill_util.h"
using base::android::AttachCurrentThread;
diff --git a/chromium/components/autofill/android/provider/form_field_data_android.h b/chromium/components/android_autofill/android/form_field_data_android.h
index eaff43fa259..de132fee00e 100644
--- a/chromium/components/autofill/android/provider/form_field_data_android.h
+++ b/chromium/components/android_autofill/android/form_field_data_android.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_ANDROID_PROVIDER_FORM_FIELD_DATA_ANDROID_H_
-#define COMPONENTS_AUTOFILL_ANDROID_PROVIDER_FORM_FIELD_DATA_ANDROID_H_
+#ifndef COMPONENTS_ANDROID_AUTOFILL_ANDROID_FORM_FIELD_DATA_ANDROID_H_
+#define COMPONENTS_ANDROID_AUTOFILL_ANDROID_FORM_FIELD_DATA_ANDROID_H_
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
@@ -43,4 +43,4 @@ class FormFieldDataAndroid {
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_ANDROID_PROVIDER_FORM_FIELD_DATA_ANDROID_H_
+#endif // COMPONENTS_ANDROID_AUTOFILL_ANDROID_FORM_FIELD_DATA_ANDROID_H_
diff --git a/chromium/components/autofill/android/provider/junit/BUILD.gn b/chromium/components/android_autofill/android/junit/BUILD.gn
index 95cea50bf90..f8bdffeecb1 100644
--- a/chromium/components/autofill/android/provider/junit/BUILD.gn
+++ b/chromium/components/android_autofill/android/junit/BUILD.gn
@@ -13,7 +13,7 @@ java_library("components_autofill_junit_tests") {
deps = [
"//base:base_java_test_support",
"//base:base_junit_test_support",
- "//components/autofill/android/provider:java",
+ "//components/android_autofill/android:java",
"//content/public/android:content_java",
"//third_party/android_deps:robolectric_all_java",
"//third_party/junit",
diff --git a/chromium/components/autofill/android/provider/junit/src/org/chromium/components/autofill/AutofillProviderTest.java b/chromium/components/android_autofill/android/junit/src/org/chromium/components/autofill/AutofillProviderTest.java
index 87c73025e49..672961d77d1 100644
--- a/chromium/components/autofill/android/provider/junit/src/org/chromium/components/autofill/AutofillProviderTest.java
+++ b/chromium/components/android_autofill/android/junit/src/org/chromium/components/autofill/AutofillProviderTest.java
@@ -48,6 +48,7 @@ public class AutofillProviderTest {
private ViewGroup mContainerView;
private AutofillProvider mAutofillProvider;
private DisplayAndroid mDisplayAndroid;
+ private long mMockedNativeAutofillProviderAndroid = 1;
@Before
public void setUp() {
@@ -57,8 +58,14 @@ public class AutofillProviderTest {
mDisplayAndroid = Mockito.mock(DisplayAndroid.class);
mWebContents = Mockito.mock(WebContents.class);
mContainerView = Mockito.mock(ViewGroup.class);
- mAutofillProvider = new AutofillProvider(mContext, mContainerView, "AutofillProviderTest");
- mAutofillProvider.setWebContents(mWebContents);
+
+ mAutofillProvider = new AutofillProvider(
+ mContext, mContainerView, mWebContents, "AutofillProviderTest") {
+ @Override
+ protected long initializeNativeAutofillProvider(WebContents webContents) {
+ return mMockedNativeAutofillProviderAndroid;
+ }
+ };
when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindowAndroid);
when(mWindowAndroid.getDisplay()).thenReturn(mDisplayAndroid);
diff --git a/chromium/components/autofill/android/provider/test_support/BUILD.gn b/chromium/components/android_autofill/android/test_support/BUILD.gn
index 6ed8af92b68..ad2c5c2c691 100644
--- a/chromium/components/autofill/android/provider/test_support/BUILD.gn
+++ b/chromium/components/android_autofill/android/test_support/BUILD.gn
@@ -17,8 +17,8 @@ android_library("component_autofill_provider_java_test_support") {
"//base:base_java",
"//base:base_java_test_support",
"//base:jni_java",
- "//components/autofill/android/provider:autofill_aidl",
- "//components/autofill/android/provider:java",
+ "//components/android_autofill/android:autofill_aidl",
+ "//components/android_autofill/android:java",
"//content/public/android:content_java",
"//third_party/androidx:androidx_annotation_annotation_java",
]
@@ -34,7 +34,7 @@ source_set("component_autofill_provider_native_test_support") {
deps = [
":jni_headers",
"//base",
- "//components/autofill/content/browser",
+ "//components/android_autofill/android",
"//components/autofill/core/browser:test_support",
"//content/public/browser",
]
diff --git a/chromium/components/autofill/android/provider/test_support/autofill_provider_test_helper.cc b/chromium/components/android_autofill/android/test_support/autofill_provider_test_helper.cc
index bba53f8489d..34162314920 100644
--- a/chromium/components/autofill/android/provider/test_support/autofill_provider_test_helper.cc
+++ b/chromium/components/android_autofill/android/test_support/autofill_provider_test_helper.cc
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/autofill/android/provider/test_support/jni_headers/AutofillProviderTestHelper_jni.h"
+#include "components/android_autofill/android/test_support/jni_headers/AutofillProviderTestHelper_jni.h"
#include <string>
#include "base/android/jni_array.h"
#include "base/base64.h"
+#include "components/android_autofill/browser/autofill_provider.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/content/browser/content_autofill_driver_factory.h"
-#include "components/autofill/core/browser/autofill_provider.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/field_types.h"
#include "content/public/browser/web_contents.h"
@@ -18,7 +18,7 @@
namespace autofill {
namespace {
-AutofillHandler* GetAutofillHandler(content::WebContents* web_contents,
+AutofillManager* GetAutofillManager(content::WebContents* web_contents,
content::RenderFrameHost* rfh) {
// Avoid using ContentAutofillDriver::GetForRenderFrameHost(), it will create
// a new ContentAutofillDriver.
@@ -26,21 +26,21 @@ AutofillHandler* GetAutofillHandler(content::WebContents* web_contents,
ContentAutofillDriverFactory::FromWebContents(web_contents)) {
if (ContentAutofillDriver* driver =
static_cast<ContentAutofillDriver*>(factory->DriverForKey(rfh))) {
- return driver->autofill_handler();
+ return driver->autofill_manager();
}
}
return nullptr;
}
-AutofillHandler* ToMainFrameAutofillHandler(
+AutofillManager* ToMainFrameAutofillManager(
const base::android::JavaParamRef<jobject>& jweb_contents) {
content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(jweb_contents);
CHECK(web_contents);
- AutofillHandler* autofill_handler =
- GetAutofillHandler(web_contents, web_contents->GetMainFrame());
- CHECK(autofill_handler);
- return autofill_handler;
+ AutofillManager* autofill_manager =
+ GetAutofillManager(web_contents, web_contents->GetMainFrame());
+ CHECK(autofill_manager);
+ return autofill_manager;
}
} // namespace
@@ -62,9 +62,9 @@ JNI_AutofillProviderTestHelper_SimulateMainFrameAutofillServerResponseForTesting
std::vector<int> field_types;
base::android::JavaIntArrayToIntVector(env, jfield_types, &field_types);
- AutofillHandler* autofill_handler = ToMainFrameAutofillHandler(jweb_contents);
+ AutofillManager* autofill_manager = ToMainFrameAutofillManager(jweb_contents);
const std::map<FormGlobalId, std::unique_ptr<FormStructure>>&
- form_structures = autofill_handler->form_structures();
+ form_structures = autofill_manager->form_structures();
CHECK(!form_structures.empty());
// Make API response with suggestions.
@@ -99,7 +99,7 @@ JNI_AutofillProviderTestHelper_SimulateMainFrameAutofillServerResponseForTesting
CHECK(response.SerializeToString(&response_string));
std::string encoded_response_string;
base::Base64Encode(response_string, &encoded_response_string);
- autofill_handler->OnLoadedServerPredictionsForTest(encoded_response_string,
+ autofill_manager->OnLoadedServerPredictionsForTest(encoded_response_string,
signatures);
return true;
}
@@ -117,9 +117,9 @@ JNI_AutofillProviderTestHelper_SimulateMainFramePredictionsAutofillServerRespons
base::android::JavaArrayOfIntArrayToIntVector(env, jfield_types,
&field_types);
- AutofillHandler* autofill_handler = ToMainFrameAutofillHandler(jweb_contents);
+ AutofillManager* autofill_manager = ToMainFrameAutofillManager(jweb_contents);
const std::map<FormGlobalId, std::unique_ptr<FormStructure>>&
- form_structures = autofill_handler->form_structures();
+ form_structures = autofill_manager->form_structures();
CHECK(!form_structures.empty());
// Make API response with suggestions.
@@ -151,7 +151,7 @@ JNI_AutofillProviderTestHelper_SimulateMainFramePredictionsAutofillServerRespons
CHECK(response.SerializeToString(&response_string));
std::string encoded_response_string;
base::Base64Encode(response_string, &encoded_response_string);
- autofill_handler->OnLoadedServerPredictionsForTest(encoded_response_string,
+ autofill_manager->OnLoadedServerPredictionsForTest(encoded_response_string,
signatures);
return true;
}
@@ -160,12 +160,12 @@ static void
JNI_AutofillProviderTestHelper_SimulateMainFrameAutofillQueryFailedForTesting(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jweb_contents) {
- AutofillHandler* autofill_handler = ToMainFrameAutofillHandler(jweb_contents);
+ AutofillManager* autofill_manager = ToMainFrameAutofillManager(jweb_contents);
const std::map<FormGlobalId, std::unique_ptr<FormStructure>>&
- form_structures = autofill_handler->form_structures();
+ form_structures = autofill_manager->form_structures();
// Always use first form.
CHECK(form_structures.size());
- autofill_handler->OnServerRequestErrorForTest(
+ autofill_manager->OnServerRequestErrorForTest(
*(autofill::test::GetEncodedSignatures(*(form_structures.begin()->second))
.begin()),
AutofillDownloadManager::RequestType::REQUEST_QUERY, 400);
diff --git a/chromium/components/autofill/android/provider/test_support/java/src/org/chromium/components/autofill/AutofillHintsServiceTestHelper.java b/chromium/components/android_autofill/android/test_support/java/src/org/chromium/components/autofill/AutofillHintsServiceTestHelper.java
index 742e98d7471..742e98d7471 100644
--- a/chromium/components/autofill/android/provider/test_support/java/src/org/chromium/components/autofill/AutofillHintsServiceTestHelper.java
+++ b/chromium/components/android_autofill/android/test_support/java/src/org/chromium/components/autofill/AutofillHintsServiceTestHelper.java
diff --git a/chromium/components/autofill/android/provider/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java b/chromium/components/android_autofill/android/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java
index 5db6332bce7..5db6332bce7 100644
--- a/chromium/components/autofill/android/provider/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java
+++ b/chromium/components/android_autofill/android/test_support/java/src/org/chromium/components/autofill/AutofillProviderTestHelper.java
diff --git a/chromium/components/android_autofill/browser/BUILD.gn b/chromium/components/android_autofill/browser/BUILD.gn
new file mode 100644
index 00000000000..560d173c637
--- /dev/null
+++ b/chromium/components/android_autofill/browser/BUILD.gn
@@ -0,0 +1,34 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("browser") {
+ sources = [
+ "android_autofill_manager.cc",
+ "android_autofill_manager.h",
+ "autofill_provider.cc",
+ "autofill_provider.h",
+ ]
+ public_deps = [ "//components/autofill/core/browser" ]
+ deps = [
+ "//components/autofill/content/browser",
+ "//content/public/browser",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [ "autofill_provider_unittest.cc" ]
+ deps = [
+ ":test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
+
+source_set("test_support") {
+ testonly = true
+ sources = [ "test_autofill_provider.h" ]
+ public_deps = [ ":browser" ]
+ deps = [ "//content/public/browser" ]
+}
diff --git a/chromium/components/android_autofill/browser/android_autofill_manager.cc b/chromium/components/android_autofill/browser/android_autofill_manager.cc
new file mode 100644
index 00000000000..62a08cf5fcd
--- /dev/null
+++ b/chromium/components/android_autofill/browser/android_autofill_manager.cc
@@ -0,0 +1,156 @@
+// 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/android_autofill/browser/android_autofill_manager.h"
+
+#include "base/memory/ptr_util.h"
+#include "components/android_autofill/browser/autofill_provider.h"
+#include "components/autofill/content/browser/content_autofill_driver.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+namespace autofill {
+
+using base::TimeTicks;
+
+// static
+std::unique_ptr<AutofillManager> AndroidAutofillManager::Create(
+ AutofillDriver* driver,
+ AutofillClient* client,
+ const std::string& /*app_locale*/,
+ AutofillManager::AutofillDownloadManagerState enable_download_manager) {
+ return base::WrapUnique(
+ new AndroidAutofillManager(driver, client, enable_download_manager));
+}
+
+AndroidAutofillManager::AndroidAutofillManager(
+ AutofillDriver* driver,
+ AutofillClient* client,
+ AutofillManager::AutofillDownloadManagerState enable_download_manager)
+ : AutofillManager(driver,
+ client,
+ enable_download_manager,
+ version_info::Channel::UNKNOWN) {}
+
+AndroidAutofillManager::~AndroidAutofillManager() = default;
+
+void AndroidAutofillManager::OnFormSubmittedImpl(
+ const FormData& form,
+ bool known_success,
+ mojom::SubmissionSource source) {
+ if (auto* provider = GetAutofillProvider())
+ provider->OnFormSubmitted(this, form, known_success, source);
+}
+
+void AndroidAutofillManager::OnTextFieldDidChangeImpl(
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box,
+ const TimeTicks timestamp) {
+ if (auto* provider = GetAutofillProvider())
+ provider->OnTextFieldDidChange(this, form, field, bounding_box, timestamp);
+}
+
+void AndroidAutofillManager::OnTextFieldDidScrollImpl(
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) {
+ if (auto* provider = GetAutofillProvider())
+ provider->OnTextFieldDidScroll(this, form, field, bounding_box);
+}
+
+void AndroidAutofillManager::OnQueryFormFieldAutofillImpl(
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box,
+ bool autoselect_first_suggestion) {
+ if (auto* provider = GetAutofillProvider()) {
+ provider->OnQueryFormFieldAutofill(
+ this, query_id, form, field, bounding_box, autoselect_first_suggestion);
+ }
+}
+
+void AndroidAutofillManager::OnFocusOnFormFieldImpl(
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) {
+ if (auto* provider = GetAutofillProvider())
+ provider->OnFocusOnFormField(this, form, field, bounding_box);
+}
+
+void AndroidAutofillManager::OnSelectControlDidChangeImpl(
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) {
+ if (auto* provider = GetAutofillProvider())
+ provider->OnSelectControlDidChange(this, form, field, bounding_box);
+}
+
+bool AndroidAutofillManager::ShouldParseForms(
+ const std::vector<FormData>& forms) {
+ if (auto* provider = GetAutofillProvider())
+ provider->OnFormsSeen(this, forms);
+ // Need to parse the |forms| to FormStructure, so heuristic_type can be
+ // retrieved later.
+ return true;
+}
+
+void AndroidAutofillManager::OnFocusNoLongerOnForm(bool had_interacted_form) {
+ if (auto* provider = GetAutofillProvider())
+ provider->OnFocusNoLongerOnForm(this, had_interacted_form);
+}
+
+void AndroidAutofillManager::OnDidFillAutofillFormData(
+ const FormData& form,
+ const base::TimeTicks timestamp) {
+ if (auto* provider = GetAutofillProvider())
+ provider->OnDidFillAutofillFormData(this, form, timestamp);
+}
+
+void AndroidAutofillManager::OnHidePopup() {
+ if (auto* provider = GetAutofillProvider())
+ provider->OnHidePopup(this);
+}
+
+void AndroidAutofillManager::SelectFieldOptionsDidChange(const FormData& form) {
+}
+
+void AndroidAutofillManager::PropagateAutofillPredictions(
+ content::RenderFrameHost* rfh,
+ const std::vector<FormStructure*>& forms) {
+ has_server_prediction_ = true;
+ if (auto* provider = GetAutofillProvider())
+ provider->OnServerPredictionsAvailable(this);
+}
+
+void AndroidAutofillManager::OnServerRequestError(
+ FormSignature form_signature,
+ AutofillDownloadManager::RequestType request_type,
+ int http_error) {
+ if (auto* provider = GetAutofillProvider())
+ provider->OnServerQueryRequestError(this, form_signature);
+}
+
+void AndroidAutofillManager::Reset() {
+ AutofillManager::Reset();
+ has_server_prediction_ = false;
+ if (auto* provider = GetAutofillProvider())
+ provider->Reset(this);
+}
+
+AutofillProvider* AndroidAutofillManager::GetAutofillProvider() {
+ if (autofill_provider_for_testing_)
+ return autofill_provider_for_testing_;
+ if (auto* rfh =
+ static_cast<ContentAutofillDriver*>(driver())->render_frame_host()) {
+ if (rfh->IsCurrent()) {
+ if (auto* web_contents = content::WebContents::FromRenderFrameHost(rfh)) {
+ return AutofillProvider::FromWebContents(web_contents);
+ }
+ }
+ }
+ return nullptr;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_handler_proxy.h b/chromium/components/android_autofill/browser/android_autofill_manager.h
index 9a41754e3d6..c6f6055f2ee 100644
--- a/chromium/components/autofill/core/browser/autofill_handler_proxy.h
+++ b/chromium/components/android_autofill/browser/android_autofill_manager.h
@@ -2,26 +2,27 @@
// 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_HANDLER_PROXY_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_HANDLER_PROXY_H_
+#ifndef COMPONENTS_ANDROID_AUTOFILL_BROWSER_ANDROID_AUTOFILL_MANAGER_H_
+#define COMPONENTS_ANDROID_AUTOFILL_BROWSER_ANDROID_AUTOFILL_MANAGER_H_
#include "base/memory/weak_ptr.h"
-#include "components/autofill/core/browser/autofill_handler.h"
+#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/common/dense_set.h"
namespace autofill {
class AutofillProvider;
-// This class forwards AutofillHandler calls to AutofillProvider.
-class AutofillHandlerProxy : public AutofillHandler {
+// This class forwards AutofillManager calls to AutofillProvider.
+class AndroidAutofillManager : public AutofillManager {
public:
- AutofillHandlerProxy(
+ static std::unique_ptr<AutofillManager> Create(
AutofillDriver* driver,
AutofillClient* client,
- AutofillProvider* provider,
- AutofillHandler::AutofillDownloadManagerState enable_download_manager);
- ~AutofillHandlerProxy() override;
+ const std::string& app_locale,
+ AutofillManager::AutofillDownloadManagerState enable_download_manager);
+
+ ~AndroidAutofillManager() override;
void OnFocusNoLongerOnForm(bool had_interacted_form) override;
@@ -35,13 +36,18 @@ class AutofillHandlerProxy : public AutofillHandler {
void Reset() override;
- base::WeakPtr<AutofillHandlerProxy> GetWeakPtr() {
+ base::WeakPtr<AndroidAutofillManager> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
bool has_server_prediction() const { return has_server_prediction_; }
protected:
+ AndroidAutofillManager(
+ AutofillDriver* driver,
+ AutofillClient* client,
+ AutofillManager::AutofillDownloadManagerState enable_download_manager);
+
void OnFormSubmittedImpl(const FormData& form,
bool known_success,
mojom::SubmissionSource source) override;
@@ -87,14 +93,24 @@ class AutofillHandlerProxy : public AutofillHandler {
AutofillDownloadManager::RequestType request_type,
int http_error) override;
+ protected:
+#ifdef UNIT_TEST
+ // For the unit tests where WebContents isn't available.
+ void set_autofill_provider_for_testing(AutofillProvider* autofill_provider) {
+ autofill_provider_for_testing_ = autofill_provider;
+ }
+#endif // UNIT_TEST
+
private:
+ AutofillProvider* GetAutofillProvider();
+
bool has_server_prediction_ = false;
- AutofillProvider* provider_;
- base::WeakPtrFactory<AutofillHandlerProxy> weak_ptr_factory_{this};
+ AutofillProvider* autofill_provider_for_testing_ = nullptr;
+ base::WeakPtrFactory<AndroidAutofillManager> weak_ptr_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(AutofillHandlerProxy);
+ DISALLOW_COPY_AND_ASSIGN(AndroidAutofillManager);
};
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_HANDLER_PROXY_H_
+#endif // COMPONENTS_ANDROID_AUTOFILL_BROWSER_ANDROID_AUTOFILL_MANAGER_H_
diff --git a/chromium/components/autofill/core/browser/autofill_provider.cc b/chromium/components/android_autofill/browser/autofill_provider.cc
index 7c87efad75f..0c315391b90 100644
--- a/chromium/components/autofill/core/browser/autofill_provider.cc
+++ b/chromium/components/android_autofill/browser/autofill_provider.cc
@@ -2,16 +2,20 @@
// 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_provider.h"
+#include "components/android_autofill/browser/autofill_provider.h"
-#include "components/autofill/core/browser/autofill_handler_proxy.h"
+#include "base/memory/ptr_util.h"
+#include "components/android_autofill/browser/android_autofill_manager.h"
+#include "content/public/browser/web_contents.h"
namespace autofill {
namespace {
+
bool g_is_download_manager_disabled_for_testing = false;
-}
+} // namespace
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(AutofillProvider)
-// static
bool AutofillProvider::is_download_manager_disabled_for_testing() {
return g_is_download_manager_disabled_for_testing;
}
@@ -20,22 +24,25 @@ void AutofillProvider::set_is_download_manager_disabled_for_testing() {
g_is_download_manager_disabled_for_testing = true;
}
-AutofillProvider::AutofillProvider() {}
+AutofillProvider::AutofillProvider(content::WebContents* web_contents)
+ : web_contents_(web_contents) {
+ web_contents->SetUserData(UserDataKey(), base::WrapUnique(this));
+}
-AutofillProvider::~AutofillProvider() {}
+AutofillProvider::~AutofillProvider() = default;
-void AutofillProvider::SendFormDataToRenderer(AutofillHandlerProxy* handler,
+void AutofillProvider::SendFormDataToRenderer(AndroidAutofillManager* manager,
int requestId,
const FormData& formData) {
- handler->SendFormDataToRenderer(
+ manager->SendFormDataToRenderer(
requestId, AutofillDriver::FORM_DATA_ACTION_FILL, formData);
}
void AutofillProvider::RendererShouldAcceptDataListSuggestion(
- AutofillHandlerProxy* handler,
+ AndroidAutofillManager* manager,
const FieldGlobalId& field_id,
const std::u16string& value) {
- handler->driver()->RendererShouldAcceptDataListSuggestion(field_id, value);
+ manager->driver()->RendererShouldAcceptDataListSuggestion(field_id, value);
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_provider.h b/chromium/components/android_autofill/browser/autofill_provider.h
index 650a93c580d..11a64962769 100644
--- a/chromium/components/autofill/core/browser/autofill_provider.h
+++ b/chromium/components/android_autofill/browser/autofill_provider.h
@@ -2,95 +2,118 @@
// 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_PROVIDER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROVIDER_H_
+#ifndef COMPONENTS_ANDROID_AUTOFILL_BROWSER_AUTOFILL_PROVIDER_H_
+#define COMPONENTS_ANDROID_AUTOFILL_BROWSER_AUTOFILL_PROVIDER_H_
#include "base/time/time.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/signatures.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace content {
+class WebContents;
+} // namespace content
namespace gfx {
class RectF;
-}
+} // namespace gfx
namespace autofill {
-class AutofillHandlerProxy;
+class AndroidAutofillManager;
// This class defines the interface for the autofill implementation other than
-// default AutofillManager.
-class AutofillProvider {
+// default BrowserAutofillManager. Unlike BrowserAutofillManager, this class
+// has one instance per WebContents.
+class AutofillProvider : public content::WebContentsUserData<AutofillProvider> {
public:
- AutofillProvider();
- virtual ~AutofillProvider();
+ ~AutofillProvider() override;
static bool is_download_manager_disabled_for_testing();
static void set_is_download_manager_disabled_for_testing();
- virtual void OnQueryFormFieldAutofill(AutofillHandlerProxy* handler,
+ virtual void OnQueryFormFieldAutofill(AndroidAutofillManager* manager,
int32_t id,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
bool autoselect_first_suggestion) = 0;
- virtual void OnTextFieldDidChange(AutofillHandlerProxy* handler,
+ virtual void OnTextFieldDidChange(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
const base::TimeTicks timestamp) = 0;
- virtual void OnTextFieldDidScroll(AutofillHandlerProxy* handler,
+ virtual void OnTextFieldDidScroll(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) = 0;
- virtual void OnSelectControlDidChange(AutofillHandlerProxy* handler,
+ virtual void OnSelectControlDidChange(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) = 0;
- virtual void OnFormSubmitted(AutofillHandlerProxy* handler,
+ virtual void OnFormSubmitted(AndroidAutofillManager* manager,
const FormData& form,
bool known_success,
mojom::SubmissionSource source) = 0;
- virtual void OnFocusNoLongerOnForm(AutofillHandlerProxy* handler,
+ virtual void OnFocusNoLongerOnForm(AndroidAutofillManager* manager,
bool had_interacted_form) = 0;
- virtual void OnFocusOnFormField(AutofillHandlerProxy* handler,
+ virtual void OnFocusOnFormField(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) = 0;
- virtual void OnDidFillAutofillFormData(AutofillHandlerProxy* handler,
+ virtual void OnDidFillAutofillFormData(AndroidAutofillManager* manager,
const FormData& form,
base::TimeTicks timestamp) = 0;
- virtual void OnFormsSeen(AutofillHandlerProxy* handler,
+ virtual void OnFormsSeen(AndroidAutofillManager* manager,
const std::vector<FormData>& forms) = 0;
- virtual void OnHidePopup(AutofillHandlerProxy* handler) = 0;
+ virtual void OnHidePopup(AndroidAutofillManager* manager) = 0;
- virtual void OnServerPredictionsAvailable(AutofillHandlerProxy* handler) = 0;
+ virtual void OnServerPredictionsAvailable(
+ AndroidAutofillManager* manager) = 0;
- virtual void OnServerQueryRequestError(AutofillHandlerProxy* handler,
+ virtual void OnServerQueryRequestError(AndroidAutofillManager* manager,
FormSignature form_signature) = 0;
- virtual void Reset(AutofillHandlerProxy* handler) = 0;
+ virtual void Reset(AndroidAutofillManager* manager) = 0;
- void SendFormDataToRenderer(AutofillHandlerProxy* handler,
+ void SendFormDataToRenderer(AndroidAutofillManager* manager,
int requestId,
const FormData& formData);
// Notifies the renderer should accept the datalist suggestion given by
// |value| and fill the input field indified by |field_id|.
- void RendererShouldAcceptDataListSuggestion(AutofillHandlerProxy* handler,
+ void RendererShouldAcceptDataListSuggestion(AndroidAutofillManager* manager,
const FieldGlobalId& field_id,
const std::u16string& value);
+
+ protected:
+ // WebContents takes the ownership of AutofillProvider.
+ explicit AutofillProvider(content::WebContents* web_contents);
+ friend class content::WebContentsUserData<AutofillProvider>;
+
+#ifdef UNIT_TEST
+ // For the unit tests where WebContents isn't available.
+ AutofillProvider() = default;
+#endif // UNIT_TEST
+
+ content::WebContents* web_contents() { return web_contents_; }
+
+ private:
+ content::WebContents* web_contents_;
+
+ WEB_CONTENTS_USER_DATA_KEY_DECL();
};
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROVIDER_H_
+#endif // COMPONENTS_ANDROID_AUTOFILL_BROWSER_AUTOFILL_PROVIDER_H_
diff --git a/chromium/components/autofill/core/browser/autofill_provider_unittest.cc b/chromium/components/android_autofill/browser/autofill_provider_unittest.cc
index 567d391e3fb..9859562ec8c 100644
--- a/chromium/components/autofill/core/browser/autofill_provider_unittest.cc
+++ b/chromium/components/android_autofill/browser/autofill_provider_unittest.cc
@@ -2,19 +2,20 @@
// 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_handler_proxy.h"
-#include "components/autofill/core/browser/test_autofill_provider.h"
+#include "components/android_autofill/browser/android_autofill_manager.h"
+#include "components/android_autofill/browser/test_autofill_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace autofill {
-class AutofillHandlerProxyTestHelper : public AutofillHandlerProxy {
+class AndroidAutofillManagerTestHelper : public AndroidAutofillManager {
public:
- explicit AutofillHandlerProxyTestHelper(AutofillProvider* autofill_provider)
- : AutofillHandlerProxy(nullptr,
- nullptr,
- autofill_provider,
- DISABLE_AUTOFILL_DOWNLOAD_MANAGER) {}
+ explicit AndroidAutofillManagerTestHelper(AutofillProvider* autofill_provider)
+ : AndroidAutofillManager(nullptr,
+ nullptr,
+ DISABLE_AUTOFILL_DOWNLOAD_MANAGER) {
+ set_autofill_provider_for_testing(autofill_provider);
+ }
void SimulatePropagateAutofillPredictions() {
PropagateAutofillPredictions(nullptr, std::vector<FormStructure*>());
@@ -28,22 +29,22 @@ class AutofillHandlerProxyTestHelper : public AutofillHandlerProxy {
class AutofillProviderTestHelper : public TestAutofillProvider {
public:
- bool HasServerPrediction() const { return handler_->has_server_prediction(); }
+ bool HasServerPrediction() const { return manager_->has_server_prediction(); }
private:
// AutofillProvider
- void OnQueryFormFieldAutofill(AutofillHandlerProxy* handler,
+ void OnQueryFormFieldAutofill(AndroidAutofillManager* manager,
int32_t id,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
bool autoselect_first_suggestion) override {
- handler_ = handler;
+ manager_ = manager;
}
- void OnServerQueryRequestError(AutofillHandlerProxy* handler,
+ void OnServerQueryRequestError(AndroidAutofillManager* manager,
FormSignature form_signature) override {}
- AutofillHandlerProxy* handler_;
+ AndroidAutofillManager* manager_;
};
class AutofillProviderTest : public testing::Test {
@@ -51,8 +52,8 @@ class AutofillProviderTest : public testing::Test {
void SetUp() override {
autofill_provider_test_helper_ =
std::make_unique<AutofillProviderTestHelper>();
- autofill_handler_proxy_test_helper_ =
- std::make_unique<AutofillHandlerProxyTestHelper>(
+ android_autofill_manager_test_helper_ =
+ std::make_unique<AndroidAutofillManagerTestHelper>(
autofill_provider_test_helper_.get());
}
@@ -60,32 +61,36 @@ class AutofillProviderTest : public testing::Test {
return autofill_provider_test_helper_.get();
}
- AutofillHandlerProxyTestHelper* autofill_handler_proxy_test_helper() {
- return autofill_handler_proxy_test_helper_.get();
+ AndroidAutofillManagerTestHelper* android_autofill_manager_test_helper() {
+ return android_autofill_manager_test_helper_.get();
}
private:
std::unique_ptr<AutofillProviderTestHelper> autofill_provider_test_helper_;
- std::unique_ptr<AutofillHandlerProxyTestHelper>
- autofill_handler_proxy_test_helper_;
+ std::unique_ptr<AndroidAutofillManagerTestHelper>
+ android_autofill_manager_test_helper_;
};
TEST_F(AutofillProviderTest, HasServerPredictionAfterQuery) {
// Simulate the result arrives after starting autofill.
- autofill_handler_proxy_test_helper()->SimulateOnQueryFormFieldAutofillImpl();
+ android_autofill_manager_test_helper()
+ ->SimulateOnQueryFormFieldAutofillImpl();
EXPECT_FALSE(autofill_provider_test_helper()->HasServerPrediction());
- autofill_handler_proxy_test_helper()->SimulatePropagateAutofillPredictions();
+ android_autofill_manager_test_helper()
+ ->SimulatePropagateAutofillPredictions();
EXPECT_TRUE(autofill_provider_test_helper()->HasServerPrediction());
- autofill_handler_proxy_test_helper()->Reset();
+ android_autofill_manager_test_helper()->Reset();
EXPECT_FALSE(autofill_provider_test_helper()->HasServerPrediction());
}
TEST_F(AutofillProviderTest, HasServerPredictionBeforeQuery) {
// Simulate the result arrives before starting autofill.
- autofill_handler_proxy_test_helper()->SimulatePropagateAutofillPredictions();
- autofill_handler_proxy_test_helper()->SimulateOnQueryFormFieldAutofillImpl();
+ android_autofill_manager_test_helper()
+ ->SimulatePropagateAutofillPredictions();
+ android_autofill_manager_test_helper()
+ ->SimulateOnQueryFormFieldAutofillImpl();
EXPECT_TRUE(autofill_provider_test_helper()->HasServerPrediction());
- autofill_handler_proxy_test_helper()->Reset();
+ android_autofill_manager_test_helper()->Reset();
EXPECT_FALSE(autofill_provider_test_helper()->HasServerPrediction());
}
diff --git a/chromium/components/autofill/core/browser/test_autofill_provider.h b/chromium/components/android_autofill/browser/test_autofill_provider.h
index 1c498e1bc5b..4f4c2c2cc03 100644
--- a/chromium/components/autofill/core/browser/test_autofill_provider.h
+++ b/chromium/components/android_autofill/browser/test_autofill_provider.h
@@ -2,59 +2,70 @@
// 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_TEST_AUTOFILL_PROVIDER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_PROVIDER_H_
+#ifndef COMPONENTS_ANDROID_AUTOFILL_BROWSER_TEST_AUTOFILL_PROVIDER_H_
+#define COMPONENTS_ANDROID_AUTOFILL_BROWSER_TEST_AUTOFILL_PROVIDER_H_
-#include "components/autofill/core/browser/autofill_provider.h"
+#include "components/android_autofill/browser/autofill_provider.h"
+
+#include "content/public/browser/web_contents.h"
namespace autofill {
class TestAutofillProvider : public AutofillProvider {
public:
- ~TestAutofillProvider() override {}
+#ifdef UNIT_TEST
+ // For unit testing only.
+ TestAutofillProvider() = default;
+#endif // UNIT_TEST
+
+ // Create a instance owned by |web_contents|.
+ explicit TestAutofillProvider(content::WebContents* web_contents)
+ : AutofillProvider(web_contents) {}
+
+ ~TestAutofillProvider() override = default;
// AutofillProvider:
- void OnQueryFormFieldAutofill(AutofillHandlerProxy* handler,
+ void OnQueryFormFieldAutofill(AndroidAutofillManager* manager,
int32_t id,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
bool autoselect_first_suggestion) override {}
- void OnTextFieldDidChange(AutofillHandlerProxy* handler,
+ void OnTextFieldDidChange(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box,
const base::TimeTicks timestamp) override {}
- void OnTextFieldDidScroll(AutofillHandlerProxy* handler,
+ void OnTextFieldDidScroll(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) override {}
- void OnSelectControlDidChange(AutofillHandlerProxy* handler,
+ void OnSelectControlDidChange(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) override {}
- void OnFormSubmitted(AutofillHandlerProxy* handler,
+ void OnFormSubmitted(AndroidAutofillManager* manager,
const FormData& form,
bool known_success,
mojom::SubmissionSource source) override {}
- void OnFocusNoLongerOnForm(AutofillHandlerProxy* handler,
+ void OnFocusNoLongerOnForm(AndroidAutofillManager* manager,
bool had_interacted_form) override {}
- void OnFocusOnFormField(AutofillHandlerProxy* handler,
+ void OnFocusOnFormField(AndroidAutofillManager* manager,
const FormData& form,
const FormFieldData& field,
const gfx::RectF& bounding_box) override {}
- void OnDidFillAutofillFormData(AutofillHandlerProxy* handler,
+ void OnDidFillAutofillFormData(AndroidAutofillManager* manager,
const FormData& form,
base::TimeTicks timestamp) override {}
- void OnFormsSeen(AutofillHandlerProxy* handler,
+ void OnFormsSeen(AndroidAutofillManager* manager,
const std::vector<FormData>& forms) override {}
- void OnHidePopup(AutofillHandlerProxy* handler) override {}
- void OnServerPredictionsAvailable(AutofillHandlerProxy* handler) override {}
- void OnServerQueryRequestError(AutofillHandlerProxy* handler,
+ void OnHidePopup(AndroidAutofillManager* manager) override {}
+ void OnServerPredictionsAvailable(AndroidAutofillManager* manager) override {}
+ void OnServerQueryRequestError(AndroidAutofillManager* manager,
FormSignature form_signature) override {}
- void Reset(AutofillHandlerProxy* handler) override {}
+ void Reset(AndroidAutofillManager* manager) override {}
};
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_PROVIDER_H_
+#endif // COMPONENTS_ANDROID_AUTOFILL_BROWSER_TEST_AUTOFILL_PROVIDER_H_
diff --git a/chromium/components/apdu/apdu_command.cc b/chromium/components/apdu/apdu_command.cc
index a4d9d8a1ba1..fedbcc7b8fe 100644
--- a/chromium/components/apdu/apdu_command.cc
+++ b/chromium/components/apdu/apdu_command.cc
@@ -16,10 +16,10 @@ uint16_t ParseMessageLength(base::span<const uint8_t> message, size_t offset) {
} // namespace
-base::Optional<ApduCommand> ApduCommand::CreateFromMessage(
+absl::optional<ApduCommand> ApduCommand::CreateFromMessage(
base::span<const uint8_t> message) {
if (message.size() < kApduMinHeader || message.size() > kApduMaxLength)
- return base::nullopt;
+ return absl::nullopt;
uint8_t cla = message[0];
uint8_t ins = message[1];
@@ -36,12 +36,12 @@ base::Optional<ApduCommand> ApduCommand::CreateFromMessage(
// Invalid encoding sizes.
case kApduMinHeader + 1:
case kApduMinHeader + 2:
- return base::nullopt;
+ return absl::nullopt;
// No data present; response expected.
case kApduMinHeader + 3:
// Fifth byte must be 0.
if (message[4] != 0)
- return base::nullopt;
+ return absl::nullopt;
response_length = ParseMessageLength(message, kApduCommandLengthOffset);
// Special case where response length of 0x0000 corresponds to 65536
// as defined in ISO7816-4.
@@ -51,7 +51,7 @@ base::Optional<ApduCommand> ApduCommand::CreateFromMessage(
default:
// Fifth byte must be 0.
if (message[4] != 0)
- return base::nullopt;
+ return absl::nullopt;
auto data_length = ParseMessageLength(message, kApduCommandLengthOffset);
if (message.size() == data_length + kApduCommandDataOffset) {
@@ -69,7 +69,7 @@ base::Optional<ApduCommand> ApduCommand::CreateFromMessage(
if (response_length == 0)
response_length = kApduMaxResponseLength;
} else {
- return base::nullopt;
+ return absl::nullopt;
}
break;
}
diff --git a/chromium/components/apdu/apdu_command.h b/chromium/components/apdu/apdu_command.h
index a43a7c5133e..a5b23e0b6e0 100644
--- a/chromium/components/apdu/apdu_command.h
+++ b/chromium/components/apdu/apdu_command.h
@@ -13,7 +13,7 @@
#include "base/containers/span.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace apdu {
@@ -28,7 +28,7 @@ namespace apdu {
class COMPONENT_EXPORT(APDU) ApduCommand {
public:
// Constructs an APDU command from the serialized message data.
- static base::Optional<ApduCommand> CreateFromMessage(
+ static absl::optional<ApduCommand> CreateFromMessage(
base::span<const uint8_t> message);
ApduCommand();
diff --git a/chromium/components/apdu/apdu_response.cc b/chromium/components/apdu/apdu_response.cc
index ab331d715ac..1d97658f694 100644
--- a/chromium/components/apdu/apdu_response.cc
+++ b/chromium/components/apdu/apdu_response.cc
@@ -11,11 +11,11 @@
namespace apdu {
// static
-base::Optional<ApduResponse> ApduResponse::CreateFromMessage(
+absl::optional<ApduResponse> ApduResponse::CreateFromMessage(
base::span<const uint8_t> data) {
// Invalid message size, data is appended by status byte.
if (data.size() < 2)
- return base::nullopt;
+ return absl::nullopt;
uint16_t status_bytes = data[data.size() - 2] << 8;
status_bytes |= data[data.size() - 1];
diff --git a/chromium/components/apdu/apdu_response.h b/chromium/components/apdu/apdu_response.h
index cadbb17731a..7f4807e71d9 100644
--- a/chromium/components/apdu/apdu_response.h
+++ b/chromium/components/apdu/apdu_response.h
@@ -13,7 +13,7 @@
#include "base/containers/span.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace apdu {
@@ -33,7 +33,7 @@ class COMPONENT_EXPORT(APDU) ApduResponse {
};
// Create a APDU response from the serialized message.
- static base::Optional<ApduResponse> CreateFromMessage(
+ static absl::optional<ApduResponse> CreateFromMessage(
base::span<const uint8_t> data);
ApduResponse(std::vector<uint8_t> data, Status response_status);
diff --git a/chromium/components/arc/BUILD.gn b/chromium/components/arc/BUILD.gn
index 016597e556a..6b88f0f96f1 100644
--- a/chromium/components/arc/BUILD.gn
+++ b/chromium/components/arc/BUILD.gn
@@ -7,8 +7,6 @@ import("//testing/test.gni")
static_library("arc") {
sources = [
- "app_permissions/arc_app_permissions_bridge.cc",
- "app_permissions/arc_app_permissions_bridge.h",
"appfuse/arc_appfuse_bridge.cc",
"appfuse/arc_appfuse_bridge.h",
"audio/arc_audio_bridge.cc",
@@ -22,8 +20,10 @@ static_library("arc") {
"compat_mode/arc_resize_lock_manager.cc",
"compat_mode/arc_resize_lock_manager.h",
"compat_mode/arc_resize_lock_pref_delegate.h",
- "compat_mode/resize_confirmation_dialog.cc",
- "compat_mode/resize_confirmation_dialog.h",
+ "compat_mode/arc_splash_screen_dialog_view.cc",
+ "compat_mode/arc_splash_screen_dialog_view.h",
+ "compat_mode/resize_confirmation_dialog_view.cc",
+ "compat_mode/resize_confirmation_dialog_view.h",
"compat_mode/resize_toggle_menu.cc",
"compat_mode/resize_toggle_menu.h",
"compat_mode/resize_util.cc",
@@ -130,6 +130,7 @@ static_library("arc") {
"//chromeos/network",
"//components/account_id",
"//components/arc/enterprise",
+ "//components/arc/vector_icons",
"//components/exo",
"//components/google/core/common",
"//components/guest_os",
@@ -143,10 +144,10 @@ static_library("arc") {
# in intent_filter and this dependency will be removed.
"//components/services/app_service/public/cpp:intents",
"//components/session_manager/core",
- "//components/timers",
"//components/url_formatter",
"//components/user_manager",
"//components/user_prefs:user_prefs",
+ "//components/vector_icons",
"//content/public/browser:browser",
"//content/public/common",
"//device/bluetooth",
@@ -165,6 +166,7 @@ static_library("arc") {
"//ui/events",
"//ui/events:dom_keycode_converter",
"//ui/events/ozone",
+ "//ui/gfx",
"//ui/wm/public",
"//url:url",
]
@@ -338,6 +340,8 @@ static_library("arc_test_support") {
sources = [
"test/arc_payment_app_bridge_test_support.cc",
"test/arc_payment_app_bridge_test_support.h",
+ "test/arc_util_test_support.cc",
+ "test/arc_util_test_support.h",
"test/fake_accessibility_helper_instance.cc",
"test/fake_accessibility_helper_instance.h",
"test/fake_adbd_monitor_instance.cc",
@@ -354,6 +358,8 @@ static_library("arc_test_support") {
"test/fake_backup_settings_instance.h",
"test/fake_bluetooth_instance.cc",
"test/fake_bluetooth_instance.h",
+ "test/fake_cast_receiver_instance.cc",
+ "test/fake_cast_receiver_instance.h",
"test/fake_clipboard_instance.cc",
"test/fake_clipboard_instance.h",
"test/fake_dark_theme_instance.cc",
@@ -364,20 +370,28 @@ static_library("arc_test_support") {
"test/fake_iio_sensor_instance.h",
"test/fake_intent_helper_instance.cc",
"test/fake_intent_helper_instance.h",
+ "test/fake_lock_screen_instance.cc",
+ "test/fake_lock_screen_instance.h",
"test/fake_pip_instance.cc",
"test/fake_pip_instance.h",
"test/fake_policy_instance.cc",
"test/fake_policy_instance.h",
"test/fake_power_instance.cc",
"test/fake_power_instance.h",
+ "test/fake_sharesheet_instance.cc",
+ "test/fake_sharesheet_instance.h",
"test/fake_snapshot_reboot_notification.cc",
"test/fake_snapshot_reboot_notification.h",
+ "test/fake_storage_manager_instance.cc",
+ "test/fake_storage_manager_instance.h",
"test/fake_timer_instance.cc",
"test/fake_timer_instance.h",
"test/fake_wake_lock_instance.cc",
"test/fake_wake_lock_instance.h",
"test/fake_wallpaper_instance.cc",
"test/fake_wallpaper_instance.h",
+ "test/fake_webapk_instance.cc",
+ "test/fake_webapk_instance.h",
"test/test_browser_context.cc",
"test/test_browser_context.h",
]
@@ -409,13 +423,17 @@ source_set("unit_tests") {
"appfuse/arc_appfuse_bridge_unittest.cc",
"arc_features_parser_unittest.cc",
"arc_util_unittest.cc",
+ "audio/arc_audio_bridge_unittest.cc",
"bluetooth/bluetooth_mojom_traits_unittest.cc",
"bluetooth/bluetooth_type_converters_unittest.cc",
+ "camera/arc_camera_bridge_unittest.cc",
"clipboard/arc_clipboard_bridge_unittest.cc",
"compat_mode/arc_resize_lock_manager_unittest.cc",
- "compat_mode/resize_confirmation_dialog_unittest.cc",
+ "compat_mode/arc_splash_screen_dialog_view_unittest.cc",
+ "compat_mode/resize_confirmation_dialog_view_unittest.cc",
"compat_mode/resize_toggle_menu_unittest.cc",
"compat_mode/resize_util_unittest.cc",
+ "crash_collector/arc_crash_collector_bridge_unittest.cc",
"dark_theme/arc_dark_theme_bridge_unittest.cc",
"disk_quota/arc_disk_quota_bridge_unittest.cc",
"enterprise/arc_data_remove_requested_pref_handler_unittest.cc",
@@ -431,15 +449,21 @@ source_set("unit_tests") {
"intent_helper/custom_tab_unittest.cc",
"intent_helper/intent_filter_unittest.cc",
"intent_helper/link_handler_model_unittest.cc",
+ "lock_screen/arc_lock_screen_bridge_unittest.cc",
+ "media_session/arc_media_session_bridge_unittest.cc",
"metrics/arc_metrics_service_unittest.cc",
"metrics/stability_metrics_manager_unittest.cc",
+ "midis/arc_midis_bridge_unittest.cc",
"net/always_on_vpn_manager_unittest.cc",
"net/arc_net_host_impl_unittest.cc",
"pay/arc_payment_app_bridge_unittest.cc",
"power/arc_power_bridge_unittest.cc",
"property/arc_property_bridge_unittest.cc",
+ "rotation_lock/arc_rotation_lock_bridge_unittest.cc",
"sensor/arc_iio_sensor_bridge_unittest.cc",
"session/arc_bridge_host_impl_unittest.cc",
+ "session/arc_bridge_service_unittest.cc",
+ "session/arc_client_adapter_unittest.cc",
"session/arc_container_client_adapter_unittest.cc",
"session/arc_data_remover_unittest.cc",
"session/arc_instance_mode_unittest.cc",
@@ -447,8 +471,11 @@ source_set("unit_tests") {
"session/arc_session_runner_unittest.cc",
"session/arc_vm_client_adapter_unittest.cc",
"session/file_system_status_unittest.cc",
+ "storage_manager/arc_storage_manager_unittest.cc",
"timer/arc_timer_bridge_unittest.cc",
+ "usb/usb_host_bridge_unittest.cc",
"video_accelerator/arc_video_accelerator_util_unittest.cc",
+ "volume_mounter/arc_volume_mounter_bridge_unittest.cc",
"wake_lock/arc_wake_lock_bridge_unittest.cc",
]
@@ -474,6 +501,7 @@ source_set("unit_tests") {
"//chromeos/system:system",
"//components/account_id",
"//components/arc/enterprise",
+ "//components/arc/media_session",
"//components/arc/video_accelerator:common",
"//components/exo:test_support",
"//components/keyed_service/content",
@@ -497,6 +525,7 @@ source_set("unit_tests") {
"//ui/base/ime",
"//ui/events",
"//ui/events:dom_keycode_converter",
+ "//ui/events:test_support",
"//ui/ozone",
"//ui/views",
"//ui/views:test_support",
diff --git a/chromium/components/arc/DEPS b/chromium/components/arc/DEPS
index b1883adbbb0..b6b8652993d 100644
--- a/chromium/components/arc/DEPS
+++ b/chromium/components/arc/DEPS
@@ -14,9 +14,9 @@ include_rules = [
"+components/pref_registry",
"+components/prefs",
"+components/session_manager/core",
- "+components/timers",
"+components/user_manager",
"+components/user_prefs",
+ "+components/vector_icons",
"+components/version_info",
"+content/public/browser",
"+media/base",
diff --git a/chromium/components/arc/app_permissions/arc_app_permissions_bridge.cc b/chromium/components/arc/app_permissions/arc_app_permissions_bridge.cc
deleted file mode 100644
index c36978c4c8e..00000000000
--- a/chromium/components/arc/app_permissions/arc_app_permissions_bridge.cc
+++ /dev/null
@@ -1,47 +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/app_permissions/arc_app_permissions_bridge.h"
-
-#include "base/memory/singleton.h"
-#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
-#include "components/arc/session/arc_bridge_service.h"
-
-namespace arc {
-
-namespace {
-
-class ArcAppPermissionsBridgeFactory
- : public internal::ArcBrowserContextKeyedServiceFactoryBase<
- ArcAppPermissionsBridge,
- ArcAppPermissionsBridgeFactory> {
- public:
- // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
- static constexpr const char* kName = "ArcAppPermissionsBridgeFactory";
-
- static ArcAppPermissionsBridgeFactory* GetInstance() {
- return base::Singleton<ArcAppPermissionsBridgeFactory>::get();
- }
-
- private:
- friend base::DefaultSingletonTraits<ArcAppPermissionsBridgeFactory>;
- ArcAppPermissionsBridgeFactory() = default;
- ~ArcAppPermissionsBridgeFactory() override = default;
-};
-
-} // namespace
-
-// static
-ArcAppPermissionsBridge* ArcAppPermissionsBridge::GetForBrowserContext(
- content::BrowserContext* context) {
- return ArcAppPermissionsBridgeFactory::GetForBrowserContext(context);
-}
-
-ArcAppPermissionsBridge::ArcAppPermissionsBridge(
- content::BrowserContext* context,
- ArcBridgeService* bridge_service) {}
-
-ArcAppPermissionsBridge::~ArcAppPermissionsBridge() = default;
-
-} // namespace 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
deleted file mode 100644
index 7c3ba6fc33c..00000000000
--- a/chromium/components/arc/app_permissions/arc_app_permissions_bridge.h
+++ /dev/null
@@ -1,37 +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_ARC_APP_PERMISSIONS_ARC_APP_PERMISSIONS_BRIDGE_H_
-#define COMPONENTS_ARC_APP_PERMISSIONS_ARC_APP_PERMISSIONS_BRIDGE_H_
-
-#include "base/macros.h"
-#include "components/arc/mojom/app_permissions.mojom.h"
-#include "components/keyed_service/core/keyed_service.h"
-
-namespace content {
-class BrowserContext;
-} // namespace content
-
-namespace arc {
-
-class ArcBridgeService;
-
-class ArcAppPermissionsBridge : public KeyedService {
- public:
- // Returns singleton instance for the given BrowserContext,
- // or nullptr if the browser |context| is not allowed to use ARC.
- static ArcAppPermissionsBridge* GetForBrowserContext(
- content::BrowserContext* context);
-
- ArcAppPermissionsBridge(content::BrowserContext* context,
- ArcBridgeService* bridge_service);
- ~ArcAppPermissionsBridge() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ArcAppPermissionsBridge);
-};
-
-} // namespace arc
-
-#endif // COMPONENTS_ARC_APP_PERMISSIONS_ARC_APP_PERMISSIONS_BRIDGE_H_
diff --git a/chromium/components/arc/appfuse/arc_appfuse_bridge.cc b/chromium/components/arc/appfuse/arc_appfuse_bridge.cc
index 0b21340655e..83ccc17b4bc 100644
--- a/chromium/components/arc/appfuse/arc_appfuse_bridge.cc
+++ b/chromium/components/arc/appfuse/arc_appfuse_bridge.cc
@@ -40,7 +40,7 @@ class ArcAppfuseBridgeFactory
};
void RunWithScopedHandle(base::OnceCallback<void(mojo::ScopedHandle)> callback,
- base::Optional<base::ScopedFD> fd) {
+ absl::optional<base::ScopedFD> fd) {
if (!fd || !fd.value().is_valid()) {
LOG(ERROR) << "Invalid FD: fd.has_value() = " << fd.has_value();
std::move(callback).Run(mojo::ScopedHandle());
diff --git a/chromium/components/arc/arc_features.cc b/chromium/components/arc/arc_features.cc
index 7d63d1ffe93..46384f8b93c 100644
--- a/chromium/components/arc/arc_features.cc
+++ b/chromium/components/arc/arc_features.cc
@@ -38,6 +38,11 @@ const base::Feature kEnableRegularToChildTransitionFeature{
const base::Feature kEnableUnifiedAudioFocusFeature{
"ArcEnableUnifiedAudioFocus", base::FEATURE_ENABLED_BY_DEFAULT};
+// Controls whether ARC handles unmanaged->managed account transition.
+const base::Feature kEnableUnmanagedToManagedTransitionFeature{
+ "ArcEnableUnmanagedToManagedTransitionFeature",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
// Controls ARC Unspecialized Application Processes.
// When enabled, Android creates a pool of processes
// that will start applications so that zygote doesn't have to wake.
@@ -65,6 +70,10 @@ const base::Feature kNativeBridgeToggleFeature{
const base::Feature kPictureInPictureFeature{"ArcPictureInPicture",
base::FEATURE_ENABLED_BY_DEFAULT};
+// When enabled, tracing raw files are saved in order to help debug failures.
+const base::Feature kSaveRawFilesOnTracing{"ArcSaveRawFilesOnTracing",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls ARCVM real time vcpu feature on a device with 2 logical cores
// online.
const base::Feature kRtVcpuDualCore{"ArcRtVcpuDualCore",
@@ -82,11 +91,6 @@ const base::Feature kRtVcpuQuadCore{"ArcRtVcpuQuadCore",
const base::Feature kUseHighMemoryDalvikProfile{
"ArcUseHighMemoryDalvikProfile", base::FEATURE_DISABLED_BY_DEFAULT};
-// Controls ARC USB host integration.
-// When enabled, Android apps will be able to use usb host features.
-const base::Feature kUsbHostFeature{"ArcUsbHost",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Controls ARC USB Storage UI feature.
// When enabled, chrome://settings and Files.app will ask if the user wants
// to expose USB storage devices to ARC.
diff --git a/chromium/components/arc/arc_features.h b/chromium/components/arc/arc_features.h
index b4ae15d9de9..6b464c27c68 100644
--- a/chromium/components/arc/arc_features.h
+++ b/chromium/components/arc/arc_features.h
@@ -19,6 +19,7 @@ extern const base::Feature kDocumentsProviderUnknownSizeFeature;
extern const base::Feature kEnableChildToRegularTransitionFeature;
extern const base::Feature kEnableRegularToChildTransitionFeature;
extern const base::Feature kEnableUnifiedAudioFocusFeature;
+extern const base::Feature kEnableUnmanagedToManagedTransitionFeature;
extern const base::Feature kEnableUsap;
extern const base::Feature kFilePickerExperimentFeature;
extern const base::Feature kNativeBridge64BitSupportExperimentFeature;
@@ -26,8 +27,8 @@ extern const base::Feature kNativeBridgeToggleFeature;
extern const base::Feature kPictureInPictureFeature;
extern const base::Feature kRtVcpuDualCore;
extern const base::Feature kRtVcpuQuadCore;
+extern const base::Feature kSaveRawFilesOnTracing;
extern const base::Feature kUseHighMemoryDalvikProfile;
-extern const base::Feature kUsbHostFeature;
extern const base::Feature kUsbStorageUIFeature;
extern const base::Feature kVideoDecoder;
diff --git a/chromium/components/arc/arc_features_parser.cc b/chromium/components/arc/arc_features_parser.cc
index 75ec90b1ed7..6ffa6530dfd 100644
--- a/chromium/components/arc/arc_features_parser.cc
+++ b/chromium/components/arc/arc_features_parser.cc
@@ -12,7 +12,6 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
@@ -28,14 +27,17 @@ constexpr const base::FilePath::CharType kArcVmFeaturesJsonFile[] =
constexpr const base::FilePath::CharType kArcFeaturesJsonFile[] =
FILE_PATH_LITERAL("/etc/arc/features.json");
-base::Optional<ArcFeatures> ParseFeaturesJson(base::StringPiece input_json) {
+base::RepeatingCallback<absl::optional<ArcFeatures>()>*
+ g_arc_features_getter_for_testing = nullptr;
+
+absl::optional<ArcFeatures> ParseFeaturesJson(base::StringPiece input_json) {
ArcFeatures arc_features;
base::JSONReader::ValueWithError parsed_json =
base::JSONReader::ReadAndReturnValueWithError(input_json);
if (!parsed_json.value || !parsed_json.value->is_dict()) {
LOG(ERROR) << "Error parsing feature JSON: " << parsed_json.error_message;
- return base::nullopt;
+ return absl::nullopt;
}
// Parse each item under features.
@@ -43,7 +45,7 @@ base::Optional<ArcFeatures> ParseFeaturesJson(base::StringPiece input_json) {
parsed_json.value->FindKeyOfType("features", base::Value::Type::LIST);
if (!feature_list) {
LOG(ERROR) << "No feature list in JSON.";
- return base::nullopt;
+ return absl::nullopt;
}
for (auto& feature_item : feature_list->GetList()) {
const base::Value* feature_name =
@@ -52,11 +54,11 @@ base::Optional<ArcFeatures> ParseFeaturesJson(base::StringPiece input_json) {
feature_item.FindKeyOfType("version", base::Value::Type::INTEGER);
if (!feature_name || feature_name->GetString().empty()) {
LOG(ERROR) << "Missing name in the feature.";
- return base::nullopt;
+ return absl::nullopt;
}
if (!feature_version) {
LOG(ERROR) << "Missing version in the feature.";
- return base::nullopt;
+ return absl::nullopt;
}
arc_features.feature_map.emplace(feature_name->GetString(),
feature_version->GetInt());
@@ -68,17 +70,17 @@ base::Optional<ArcFeatures> ParseFeaturesJson(base::StringPiece input_json) {
base::Value::Type::LIST);
if (!unavailable_feature_list) {
LOG(ERROR) << "No unavailable feature list in JSON.";
- return base::nullopt;
+ return absl::nullopt;
}
for (auto& feature_item : unavailable_feature_list->GetList()) {
if (!feature_item.is_string()) {
LOG(ERROR) << "Item in the unavailable feature list is not a string.";
- return base::nullopt;
+ return absl::nullopt;
}
if (feature_item.GetString().empty()) {
LOG(ERROR) << "Missing name in the feature.";
- return base::nullopt;
+ return absl::nullopt;
}
arc_features.unavailable_features.emplace_back(feature_item.GetString());
}
@@ -88,12 +90,12 @@ base::Optional<ArcFeatures> ParseFeaturesJson(base::StringPiece input_json) {
"properties", base::Value::Type::DICTIONARY);
if (!properties) {
LOG(ERROR) << "No properties in JSON.";
- return base::nullopt;
+ return absl::nullopt;
}
for (const auto& item : properties->DictItems()) {
if (!item.second.is_string()) {
LOG(ERROR) << "Item in the properties mapping is not a string.";
- return base::nullopt;
+ return absl::nullopt;
}
arc_features.build_props.emplace(item.first, item.second.GetString());
@@ -104,14 +106,14 @@ base::Optional<ArcFeatures> ParseFeaturesJson(base::StringPiece input_json) {
"play_store_version", base::Value::Type::STRING);
if (!play_version) {
LOG(ERROR) << "No Play Store version in JSON.";
- return base::nullopt;
+ return absl::nullopt;
}
arc_features.play_store_version = play_version->GetString();
return arc_features;
}
-base::Optional<ArcFeatures> ReadOnFileThread(const base::FilePath& file_path) {
+absl::optional<ArcFeatures> ReadOnFileThread(const base::FilePath& file_path) {
DCHECK(!file_path.empty());
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
@@ -123,13 +125,13 @@ base::Optional<ArcFeatures> ReadOnFileThread(const base::FilePath& file_path) {
if (!base::ReadFileToString(file_path, &input_json)) {
PLOG(ERROR) << "Cannot read file " << file_path.value()
<< " into string.";
- return base::nullopt;
+ return absl::nullopt;
}
}
if (input_json.empty()) {
LOG(ERROR) << "Input JSON is empty in file " << file_path.value();
- return base::nullopt;
+ return absl::nullopt;
}
return ParseFeaturesJson(input_json);
@@ -143,7 +145,12 @@ ArcFeatures::~ArcFeatures() = default;
ArcFeatures& ArcFeatures::operator=(ArcFeatures&& other) = default;
void ArcFeaturesParser::GetArcFeatures(
- base::OnceCallback<void(base::Optional<ArcFeatures>)> callback) {
+ base::OnceCallback<void(absl::optional<ArcFeatures>)> callback) {
+ if (g_arc_features_getter_for_testing) {
+ std::move(callback).Run(g_arc_features_getter_for_testing->Run());
+ return;
+ }
+
const auto* json_file =
arc::IsArcVmEnabled() ? kArcVmFeaturesJsonFile : kArcFeaturesJsonFile;
base::ThreadPool::PostTaskAndReplyWithResult(
@@ -152,9 +159,14 @@ void ArcFeaturesParser::GetArcFeatures(
std::move(callback));
}
-base::Optional<ArcFeatures> ArcFeaturesParser::ParseFeaturesJsonForTesting(
+absl::optional<ArcFeatures> ArcFeaturesParser::ParseFeaturesJsonForTesting(
base::StringPiece input_json) {
return ParseFeaturesJson(input_json);
}
+void ArcFeaturesParser::SetArcFeaturesGetterForTesting(
+ base::RepeatingCallback<absl::optional<ArcFeatures>()>* getter) {
+ g_arc_features_getter_for_testing = getter;
+}
+
} // namespace arc
diff --git a/chromium/components/arc/arc_features_parser.h b/chromium/components/arc/arc_features_parser.h
index 0d4b6fad377..4cfdcbdaba1 100644
--- a/chromium/components/arc/arc_features_parser.h
+++ b/chromium/components/arc/arc_features_parser.h
@@ -11,8 +11,8 @@
#include "base/callback_forward.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
@@ -80,13 +80,19 @@ class ArcFeaturesParser {
public:
// Get ARC system available features.
static void GetArcFeatures(
- base::OnceCallback<void(base::Optional<ArcFeatures>)> callback);
+ base::OnceCallback<void(absl::optional<ArcFeatures>)> callback);
// Given an input feature JSON, return ARC features. This method is for
// testing only.
- static base::Optional<ArcFeatures> ParseFeaturesJsonForTesting(
+ static absl::optional<ArcFeatures> ParseFeaturesJsonForTesting(
base::StringPiece input_json);
+ // Overrides the ArcFeatures returned by GetArcFeatures, for testing only.
+ // Does not take ownership of |getter|, it must be alive when GetArcFeatures
+ // is called.
+ static void SetArcFeaturesGetterForTesting(
+ base::RepeatingCallback<absl::optional<ArcFeatures>()>* getter);
+
private:
DISALLOW_COPY_AND_ASSIGN(ArcFeaturesParser);
};
diff --git a/chromium/components/arc/arc_features_parser_unittest.cc b/chromium/components/arc/arc_features_parser_unittest.cc
index 99f1ba9ef52..9dda377015c 100644
--- a/chromium/components/arc/arc_features_parser_unittest.cc
+++ b/chromium/components/arc/arc_features_parser_unittest.cc
@@ -81,20 +81,20 @@ constexpr const char kInvalidJsonWithMissingFields[] =
"invalid_root_third": {}})json";
TEST_F(ArcFeaturesParserTest, ParseEmptyJson) {
- base::Optional<ArcFeatures> arc_features =
+ absl::optional<ArcFeatures> arc_features =
ArcFeaturesParser::ParseFeaturesJsonForTesting(base::StringPiece());
- EXPECT_EQ(arc_features, base::nullopt);
+ EXPECT_EQ(arc_features, absl::nullopt);
}
TEST_F(ArcFeaturesParserTest, ParseInvalidJson) {
- base::Optional<ArcFeatures> arc_features =
+ absl::optional<ArcFeatures> arc_features =
ArcFeaturesParser::ParseFeaturesJsonForTesting(
kInvalidJsonWithMissingFields);
- EXPECT_EQ(arc_features, base::nullopt);
+ EXPECT_EQ(arc_features, absl::nullopt);
}
TEST_F(ArcFeaturesParserTest, ParseValidJson) {
- base::Optional<ArcFeatures> arc_features =
+ absl::optional<ArcFeatures> arc_features =
ArcFeaturesParser::ParseFeaturesJsonForTesting(kValidJson);
auto feature_map = arc_features->feature_map;
auto unavailable_features = arc_features->unavailable_features;
@@ -107,7 +107,7 @@ TEST_F(ArcFeaturesParserTest, ParseValidJson) {
}
TEST_F(ArcFeaturesParserTest, ParseValidJsonWithUnavailableFeature) {
- base::Optional<ArcFeatures> arc_features =
+ absl::optional<ArcFeatures> arc_features =
ArcFeaturesParser::ParseFeaturesJsonForTesting(
kValidJsonWithUnavailableFeature);
auto feature_map = arc_features->feature_map;
@@ -121,10 +121,10 @@ TEST_F(ArcFeaturesParserTest, ParseValidJsonWithUnavailableFeature) {
}
TEST_F(ArcFeaturesParserTest, ParseValidJsonWithEmptyFeatureName) {
- base::Optional<ArcFeatures> arc_features =
+ absl::optional<ArcFeatures> arc_features =
ArcFeaturesParser::ParseFeaturesJsonForTesting(
kValidJsonFeatureEmptyName);
- EXPECT_EQ(arc_features, base::nullopt);
+ EXPECT_EQ(arc_features, absl::nullopt);
}
} // namespace
diff --git a/chromium/components/arc/arc_prefs.cc b/chromium/components/arc/arc_prefs.cc
index b835ed33fef..afabaf828be 100644
--- a/chromium/components/arc/arc_prefs.cc
+++ b/chromium/components/arc/arc_prefs.cc
@@ -107,6 +107,9 @@ const char kArcCompatibleFilesystemChosen[] =
// GuestOsEngagementMetrics.
const char kEngagementPrefsPrefix[] = "arc.metrics";
+// A boolean preference that indicates ARC management state.
+const char kArcIsManaged[] = "arc.is_managed";
+
// ======== LOCAL STATE PREFS ========
// A boolean preference that indicates whether this device has run with the
@@ -161,6 +164,8 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
kArcSupervisionTransition,
static_cast<int>(ArcSupervisionTransition::NO_TRANSITION));
+ registry->RegisterBooleanPref(kArcIsManaged, false);
+
guest_os::prefs::RegisterEngagementProfilePrefs(registry,
kEngagementPrefsPrefix);
diff --git a/chromium/components/arc/arc_prefs.h b/chromium/components/arc/arc_prefs.h
index 9d496f08756..cd14b7bb85b 100644
--- a/chromium/components/arc/arc_prefs.h
+++ b/chromium/components/arc/arc_prefs.h
@@ -40,6 +40,7 @@ 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 kArcIsManaged[];
ARC_EXPORT extern const char kEcryptfsMigrationStrategy[];
ARC_EXPORT extern const char kEngagementPrefsPrefix[];
diff --git a/chromium/components/arc/arc_util.cc b/chromium/components/arc/arc_util.cc
index 4cdf09309be..200f71bc191 100644
--- a/chromium/components/arc/arc_util.cc
+++ b/chromium/components/arc/arc_util.cc
@@ -13,17 +13,18 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/logging.h"
-#include "base/optional.h"
#include "base/process/launch.h"
+#include "base/process/process_metrics.h"
#include "base/strings/string_number_conversions.h"
-#include "chromeos/dbus/concierge_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
+#include "base/strings/string_util.h"
+#include "chromeos/dbus/concierge/concierge_client.h"
#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
#include "chromeos/dbus/session_manager/session_manager_client.h"
#include "chromeos/dbus/upstart/upstart_client.h"
#include "components/arc/arc_features.h"
#include "components/exo/shell_surface_util.h"
#include "components/user_manager/user_manager.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/display/types/display_constants.h"
@@ -51,6 +52,12 @@ constexpr const char kCrosSystemPath[] = "/usr/bin/crossystem";
constexpr char kGenerate[] = "generate";
constexpr char kDisabled[] = "disabled";
+// Do not run ureadahead in vm for devices with less than 8GB due to memory
+// pressure issues since system will likely drop caches in this case.
+// The value should match platform2/arc/vm/scripts/init/arcvm-ureadahead.conf
+// in Chrome OS.
+constexpr int kReadaheadTotalMinMemoryInKb = 7500000;
+
void SetArcCpuRestrictionCallback(
login_manager::ContainerCpuRestrictionState state,
bool success) {
@@ -64,7 +71,7 @@ void SetArcCpuRestrictionCallback(
}
void OnSetArcVmCpuRestriction(
- base::Optional<vm_tools::concierge::SetVmCpuRestrictionResponse> response) {
+ absl::optional<vm_tools::concierge::SetVmCpuRestrictionResponse> response) {
if (!response) {
LOG(ERROR) << "Failed to call SetVmCpuRestriction";
return;
@@ -74,7 +81,7 @@ void OnSetArcVmCpuRestriction(
}
void SetArcVmCpuRestriction(CpuRestrictionState cpu_restriction_state) {
- auto* client = chromeos::DBusThreadManager::Get()->GetConciergeClient();
+ auto* client = chromeos::ConciergeClient::Get();
if (!client) {
LOG(ERROR) << "ConciergeClient is not available";
return;
@@ -188,13 +195,26 @@ bool IsArcVmRtVcpuEnabled(uint32_t cpus) {
return false;
}
+bool IsArcVmUseHugePages() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ chromeos::switches::kArcVmUseHugePages);
+}
+
bool IsArcVmDevConfIgnored() {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kIgnoreArcVmDevConf);
}
-ArcVmUreadaheadMode GetArcVmUreadaheadMode() {
- ArcVmUreadaheadMode mode = ArcVmUreadaheadMode::READAHEAD;
+ArcVmUreadaheadMode GetArcVmUreadaheadMode(SystemMemoryInfoCallback callback) {
+ base::SystemMemoryInfoKB mem_info;
+ DCHECK(callback);
+ if (!callback.Run(&mem_info)) {
+ LOG(ERROR) << "Failed to get system memory info";
+ return ArcVmUreadaheadMode::DISABLED;
+ }
+ ArcVmUreadaheadMode mode = (mem_info.total > kReadaheadTotalMinMemoryInKb)
+ ? ArcVmUreadaheadMode::READAHEAD
+ : ArcVmUreadaheadMode::DISABLED;
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kArcVmUreadaheadMode)) {
const std::string value =
@@ -376,6 +396,8 @@ int32_t GetLcdDensityForDeviceScaleFactor(float device_scale_factor) {
return 213; // TVDPI
if (std::abs(device_scale_factor - display::kDsf_1_777) < kEpsilon)
return 240; // HDPI
+ if (std::abs(device_scale_factor - display::kDsf_1_8) < kEpsilon)
+ return 240; // HDPI
if (std::abs(device_scale_factor - display::kDsf_2_666) < kEpsilon)
return 320; // XHDPI
diff --git a/chromium/components/arc/arc_util.h b/chromium/components/arc/arc_util.h
index b29cbd14297..18018c8e02a 100644
--- a/chromium/components/arc/arc_util.h
+++ b/chromium/components/arc/arc_util.h
@@ -21,6 +21,7 @@ class Window;
namespace base {
class CommandLine;
+struct SystemMemoryInfoKB;
} // namespace base
namespace user_manager {
@@ -57,6 +58,9 @@ enum class ArcVmUreadaheadMode {
DISABLED,
};
+using SystemMemoryInfoCallback =
+ base::RepeatingCallback<bool(base::SystemMemoryInfoKB*)>;
+
// Upstart Job Description
struct JobDesc {
// Explicit ctor/dtor declaration is necessary for complex struct. See
@@ -94,13 +98,16 @@ bool IsArcVmEnabled();
// device.
bool IsArcVmRtVcpuEnabled(uint32_t cpus);
+// Returns true if ARC VM advised to use Huge Pages for guest memory.
+bool IsArcVmUseHugePages();
+
// Returns true if all development configuration directives in the
// vm_tools/init/arcvm_dev.conf file are ignored during ARCVM start.
bool IsArcVmDevConfIgnored();
// Returns mode of operation for ureadahead during the ARCVM boot flow.
-// Valid modes are readahead (default), generate, or disabled.
-ArcVmUreadaheadMode GetArcVmUreadaheadMode();
+// Valid modes are readahead, generate, or disabled.
+ArcVmUreadaheadMode GetArcVmUreadaheadMode(SystemMemoryInfoCallback callback);
// 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
diff --git a/chromium/components/arc/arc_util_unittest.cc b/chromium/components/arc/arc_util_unittest.cc
index 38cde74c9c1..1c41670ffe9 100644
--- a/chromium/components/arc/arc_util_unittest.cc
+++ b/chromium/components/arc/arc_util_unittest.cc
@@ -23,6 +23,8 @@
#include "chromeos/dbus/upstart/fake_upstart_client.h"
#include "components/account_id/account_id.h"
#include "components/arc/arc_features.h"
+#include "components/arc/test/arc_util_test_support.h"
+#include "components/prefs/testing_pref_service.h"
#include "components/user_manager/fake_user_manager.h"
#include "components/user_manager/scoped_user_manager.h"
#include "components/user_manager/user.h"
@@ -300,6 +302,14 @@ TEST_F(ArcUtilTest, IsArcVmRtVcpuEnabled) {
}
}
+TEST_F(ArcUtilTest, IsArcVmUseHugePages) {
+ EXPECT_FALSE(IsArcVmUseHugePages());
+
+ auto* command_line = base::CommandLine::ForCurrentProcess();
+ command_line->InitFromArgv({"", "--arcvm-use-hugepages"});
+ EXPECT_TRUE(IsArcVmUseHugePages());
+}
+
TEST_F(ArcUtilTest, IsArcVmDevConfIgnored) {
EXPECT_FALSE(IsArcVmDevConfIgnored());
@@ -309,15 +319,26 @@ TEST_F(ArcUtilTest, IsArcVmDevConfIgnored) {
}
TEST_F(ArcUtilTest, GetArcVmUreadaheadMode) {
+ constexpr char kArcMemProfile4GbName[] = "4G";
+ constexpr char kArcMemProfile8GbName[] = "8G";
+ auto callback_disabled = base::BindRepeating(&GetSystemMemoryInfoForTesting,
+ kArcMemProfile4GbName);
+ auto callback_readahead = base::BindRepeating(&GetSystemMemoryInfoForTesting,
+ kArcMemProfile8GbName);
auto* command_line = base::CommandLine::ForCurrentProcess();
command_line->InitFromArgv({""});
- EXPECT_EQ(ArcVmUreadaheadMode::READAHEAD, GetArcVmUreadaheadMode());
+ EXPECT_EQ(ArcVmUreadaheadMode::READAHEAD,
+ GetArcVmUreadaheadMode(callback_readahead));
+ EXPECT_EQ(ArcVmUreadaheadMode::DISABLED,
+ GetArcVmUreadaheadMode(callback_disabled));
command_line->InitFromArgv({"", "--arcvm-ureadahead-mode=generate"});
- EXPECT_EQ(ArcVmUreadaheadMode::GENERATE, GetArcVmUreadaheadMode());
+ EXPECT_EQ(ArcVmUreadaheadMode::GENERATE,
+ GetArcVmUreadaheadMode(callback_readahead));
command_line->InitFromArgv({"", "--arcvm-ureadahead-mode=disabled"});
- EXPECT_EQ(ArcVmUreadaheadMode::DISABLED, GetArcVmUreadaheadMode());
+ EXPECT_EQ(ArcVmUreadaheadMode::DISABLED,
+ GetArcVmUreadaheadMode(callback_readahead));
}
// TODO(hidehiko): Add test for IsArcKioskMode().
@@ -338,6 +359,8 @@ TEST_F(ArcUtilTest, IsArcAllowedForUser) {
new user_manager::FakeUserManager();
user_manager::ScopedUserManager scoped_user_manager(
base::WrapUnique(fake_user_manager));
+ TestingPrefServiceSimple local_state;
+ fake_user_manager->set_local_state(&local_state);
struct {
user_manager::UserType user_type;
@@ -395,6 +418,7 @@ TEST_F(ArcUtilTest, ScaleFactorToDensity) {
EXPECT_EQ(160, GetLcdDensityForDeviceScaleFactor(1.25f));
EXPECT_EQ(213, GetLcdDensityForDeviceScaleFactor(1.6f));
EXPECT_EQ(240, GetLcdDensityForDeviceScaleFactor(display::kDsf_1_777));
+ EXPECT_EQ(240, GetLcdDensityForDeviceScaleFactor(display::kDsf_1_8));
EXPECT_EQ(240, GetLcdDensityForDeviceScaleFactor(2.0f));
EXPECT_EQ(280, GetLcdDensityForDeviceScaleFactor(display::kDsf_2_252));
EXPECT_EQ(280, GetLcdDensityForDeviceScaleFactor(2.4f));
diff --git a/chromium/components/arc/audio/arc_audio_bridge.cc b/chromium/components/arc/audio/arc_audio_bridge.cc
index 7cb0f2b4d94..10844c753aa 100644
--- a/chromium/components/arc/audio/arc_audio_bridge.cc
+++ b/chromium/components/arc/audio/arc_audio_bridge.cc
@@ -46,17 +46,25 @@ ArcAudioBridge* ArcAudioBridge::GetForBrowserContext(
return ArcAudioBridgeFactory::GetForBrowserContext(context);
}
+// static
+ArcAudioBridge* ArcAudioBridge::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcAudioBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
ArcAudioBridge::ArcAudioBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service),
cras_audio_handler_(ash::CrasAudioHandler::Get()) {
arc_bridge_service_->audio()->SetHost(this);
arc_bridge_service_->audio()->AddObserver(this);
+ DCHECK(cras_audio_handler_);
cras_audio_handler_->AddAudioObserver(this);
}
ArcAudioBridge::~ArcAudioBridge() {
- cras_audio_handler_->RemoveAudioObserver(this);
+ if (ash::CrasAudioHandler::Get()) // for unittests
+ cras_audio_handler_->RemoveAudioObserver(this);
arc_bridge_service_->audio()->RemoveObserver(this);
arc_bridge_service_->audio()->SetHost(nullptr);
}
diff --git a/chromium/components/arc/audio/arc_audio_bridge.h b/chromium/components/arc/audio/arc_audio_bridge.h
index 92e5a72700d..01098ef9e05 100644
--- a/chromium/components/arc/audio/arc_audio_bridge.h
+++ b/chromium/components/arc/audio/arc_audio_bridge.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_ARC_AUDIO_ARC_AUDIO_BRIDGE_H_
#define COMPONENTS_ARC_AUDIO_ARC_AUDIO_BRIDGE_H_
-#include <string>
-
#include "ash/components/audio/cras_audio_handler.h"
#include "base/macros.h"
#include "components/arc/mojom/audio.mojom.h"
@@ -29,6 +27,8 @@ class ArcAudioBridge : public KeyedService,
// Returns singleton instance for the given BrowserContext,
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcAudioBridge* GetForBrowserContext(content::BrowserContext* context);
+ static ArcAudioBridge* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
ArcAudioBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service);
diff --git a/chromium/components/arc/audio/arc_audio_bridge_unittest.cc b/chromium/components/arc/audio/arc_audio_bridge_unittest.cc
new file mode 100644
index 00000000000..6a63c5f609d
--- /dev/null
+++ b/chromium/components/arc/audio/arc_audio_bridge_unittest.cc
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/audio/arc_audio_bridge.h"
+
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/test/test_browser_context.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcAudioBridgeTest : public testing::Test {
+ protected:
+ ArcAudioBridgeTest() = default;
+ ArcAudioBridgeTest(const ArcAudioBridgeTest&) = delete;
+ ArcAudioBridgeTest& operator=(const ArcAudioBridgeTest&) = delete;
+ ~ArcAudioBridgeTest() override = default;
+
+ void SetUp() override {
+ ash::CrasAudioHandler::InitializeForTesting();
+ bridge_ = ArcAudioBridge::GetForBrowserContextForTesting(&context_);
+ }
+ void TearDown() override { ash::CrasAudioHandler::Shutdown(); }
+
+ ArcAudioBridge* bridge() { return bridge_; }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ ArcServiceManager arc_service_manager_;
+ TestBrowserContext context_;
+ ArcAudioBridge* bridge_ = nullptr;
+};
+
+TEST_F(ArcAudioBridgeTest, ConstructDestruct) {
+ EXPECT_NE(nullptr, bridge());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/bluetooth/bluetooth_type_converters_unittest.cc b/chromium/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
index c4f9e8be3f9..d30d5c10e60 100644
--- a/chromium/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
+++ b/chromium/components/arc/bluetooth/bluetooth_type_converters_unittest.cc
@@ -230,7 +230,7 @@ TEST(BluetoothTypeConverterTest, ConvertMojoSequenceAttributeToBlueZAttribute) {
sequence_mojo->sequence.push_back(std::move(value_channel));
}
sequence_mojo->type_size = sequence_mojo->sequence.size();
- sequence_mojo->value = base::nullopt;
+ sequence_mojo->value = absl::nullopt;
auto sequence_blue_z =
sequence_mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
@@ -264,7 +264,7 @@ TEST(BluetoothTypeConverterTest,
auto mojo = arc::mojom::BluetoothSdpAttribute::New();
mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::UINT;
mojo->type_size = static_cast<uint32_t>(sizeof(uint32_t));
- mojo->value = base::nullopt;
+ mojo->value = absl::nullopt;
auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
@@ -280,7 +280,7 @@ TEST(BluetoothTypeConverterTest,
auto mojo = arc::mojom::BluetoothSdpAttribute::New();
mojo->type = bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE;
mojo->type_size = 0;
- mojo->value = base::nullopt;
+ mojo->value = absl::nullopt;
auto blue_z = mojo.To<bluez::BluetoothServiceAttributeValueBlueZ>();
diff --git a/chromium/components/arc/camera/arc_camera_bridge.cc b/chromium/components/arc/camera/arc_camera_bridge.cc
index 314ee6e1869..d55a643e7f5 100644
--- a/chromium/components/arc/camera/arc_camera_bridge.cc
+++ b/chromium/components/arc/camera/arc_camera_bridge.cc
@@ -99,6 +99,12 @@ ArcCameraBridge* ArcCameraBridge::GetForBrowserContext(
return ArcCameraBridgeFactory::GetForBrowserContext(context);
}
+// static
+ArcCameraBridge* ArcCameraBridge::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcCameraBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
ArcCameraBridge::ArcCameraBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service) {
diff --git a/chromium/components/arc/camera/arc_camera_bridge.h b/chromium/components/arc/camera/arc_camera_bridge.h
index 90bc4b234b5..c5c44ccc268 100644
--- a/chromium/components/arc/camera/arc_camera_bridge.h
+++ b/chromium/components/arc/camera/arc_camera_bridge.h
@@ -28,6 +28,8 @@ class ArcCameraBridge : public KeyedService, public mojom::CameraHost {
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcCameraBridge* GetForBrowserContext(
content::BrowserContext* context);
+ static ArcCameraBridge* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
ArcCameraBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service);
diff --git a/chromium/components/arc/camera/arc_camera_bridge_unittest.cc b/chromium/components/arc/camera/arc_camera_bridge_unittest.cc
new file mode 100644
index 00000000000..f50a74310e8
--- /dev/null
+++ b/chromium/components/arc/camera/arc_camera_bridge_unittest.cc
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/camera/arc_camera_bridge.h"
+
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/test/test_browser_context.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcCameraBridgeTest : public testing::Test {
+ protected:
+ ArcCameraBridgeTest()
+ : bridge_(ArcCameraBridge::GetForBrowserContextForTesting(&context_)) {}
+ ArcCameraBridgeTest(const ArcCameraBridgeTest&) = delete;
+ ArcCameraBridgeTest& operator=(const ArcCameraBridgeTest&) = delete;
+ ~ArcCameraBridgeTest() override = default;
+
+ ArcCameraBridge* bridge() { return bridge_; }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ ArcServiceManager arc_service_manager_;
+ TestBrowserContext context_;
+ ArcCameraBridge* const bridge_;
+};
+
+TEST_F(ArcCameraBridgeTest, ConstructDestruct) {
+ EXPECT_NE(nullptr, bridge());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/clipboard/arc_clipboard_bridge.h b/chromium/components/arc/clipboard/arc_clipboard_bridge.h
index 1056ad5a080..72591ba5d20 100644
--- a/chromium/components/arc/clipboard/arc_clipboard_bridge.h
+++ b/chromium/components/arc/clipboard/arc_clipboard_bridge.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_ARC_CLIPBOARD_ARC_CLIPBOARD_BRIDGE_H_
#define COMPONENTS_ARC_CLIPBOARD_ARC_CLIPBOARD_BRIDGE_H_
-#include <string>
-
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "components/arc/mojom/clipboard.mojom.h"
diff --git a/chromium/components/arc/clipboard/arc_clipboard_bridge_unittest.cc b/chromium/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
index c115a91b24c..70ed56bb576 100644
--- a/chromium/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
+++ b/chromium/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
@@ -25,7 +25,10 @@ namespace arc {
namespace {
constexpr char kSampleText[] = "Copy&Paste å¤åˆ¶å’Œç²˜è´´ コピペ";
+constexpr char16_t kSampleText16[] = u"Copy&Paste å¤åˆ¶å’Œç²˜è´´ コピペ";
constexpr char kSampleHtml[] = "<span>Copy&amp;Paste</span><span>コピペ</span>";
+constexpr char16_t kSampleHtml16[] =
+ u"<span>Copy&amp;Paste</span><span>コピペ</span>";
MATCHER_P(ClipDataMatcher, expected, "") {
EXPECT_EQ(expected->representations.size(), arg->representations.size());
@@ -85,7 +88,7 @@ class ArcClipboardBridgeTest : public testing::Test {
TEST_F(ArcClipboardBridgeTest, GetClipContent_PlainText) {
{
ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
- writer.WriteText(base::UTF8ToUTF16(kSampleText));
+ writer.WriteText(kSampleText16);
}
mojom::ClipDataPtr expected_clip_data =
@@ -101,7 +104,7 @@ TEST_F(ArcClipboardBridgeTest, GetClipContent_PlainText) {
TEST_F(ArcClipboardBridgeTest, GetClipContent_Html) {
{
ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste);
- writer.WriteHTML(base::UTF8ToUTF16(kSampleHtml), std::string());
+ writer.WriteHTML(kSampleHtml16, std::string());
}
mojom::ClipDataPtr expected_clip_data =
diff --git a/chromium/components/arc/compat_mode/DEPS b/chromium/components/arc/compat_mode/DEPS
index 3079de5a5df..318ac66ab9e 100644
--- a/chromium/components/arc/compat_mode/DEPS
+++ b/chromium/components/arc/compat_mode/DEPS
@@ -3,5 +3,7 @@ include_rules = [
"+ash/resources/vector_icons",
"+components/strings/grit/components_strings.h",
"+ui/aura",
+ "+ui/gfx",
+ "+ui/strings",
"+ui/views",
]
diff --git a/chromium/components/arc/compat_mode/arc_resize_lock_manager.cc b/chromium/components/arc/compat_mode/arc_resize_lock_manager.cc
index c8c7e95b194..a3400c6b5cd 100644
--- a/chromium/components/arc/compat_mode/arc_resize_lock_manager.cc
+++ b/chromium/components/arc/compat_mode/arc_resize_lock_manager.cc
@@ -10,6 +10,9 @@
#include "base/bind.h"
#include "base/memory/singleton.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "components/arc/compat_mode/arc_splash_screen_dialog_view.h"
+#include "components/exo/shell_surface_base.h"
+#include "components/exo/shell_surface_util.h"
namespace arc {
@@ -85,12 +88,45 @@ void ArcResizeLockManager::OnWindowDestroying(aura::Window* window) {
}
void ArcResizeLockManager::EnableResizeLock(aura::Window* window) {
- auto* frame_view = ash::NonClientFrameViewAsh::Get(window);
+ const std::string* app_id = window->GetProperty(ash::kAppIDKey);
+ // The state is |ArcResizeLockState::READY| only when we enable the resize
+ // lock for an app for the first time.
+ if (app_id && pref_delegate_->GetResizeLockState(*app_id) ==
+ mojom::ArcResizeLockState::READY) {
+ pref_delegate_->SetResizeLockState(*app_id, mojom::ArcResizeLockState::ON);
+
+ // Setup splash screen.
+ auto* shell_surface_base = exo::GetShellSurfaceBaseForWindow(window);
+ if (shell_surface_base && !shell_surface_base->HasOverlay()) {
+ // Show the splash screen in current window. The splash screen is an
+ // overlay covering the entire window. User can only remove the overlay
+ // before closing the window.
+ auto splash_screen_dialog = arc::BuildSplashScreenDialogView(
+ views::Button::PressedCallback(base::BindRepeating(
+ [](aura::Window* window, const ui::Event& event) {
+ auto* shell_surface_base =
+ exo::GetShellSurfaceBaseForWindow(window);
+ if (!shell_surface_base)
+ return;
+ if (shell_surface_base->HasOverlay()) {
+ shell_surface_base->RemoveOverlay();
+ }
+ return;
+ },
+ base::Unretained(window))));
+
+ exo::ShellSurfaceBase::OverlayParams params(
+ std::move(splash_screen_dialog));
+ params.translucent = true;
+ shell_surface_base->AddOverlay(std::move(params));
+ }
+ }
+ // Setup size button override.
+ auto* frame_view = ash::NonClientFrameViewAsh::Get(window);
// Resize Lock feature only supports non-client frame view, and doesn't
// browser windows.
DCHECK(frame_view);
-
frame_view->GetHeaderView()
->caption_button_container()
->SetOnSizeButtonPressedCallback(
diff --git a/chromium/components/arc/compat_mode/arc_resize_lock_manager.h b/chromium/components/arc/compat_mode/arc_resize_lock_manager.h
index 92b33c586de..903c0f18c88 100644
--- a/chromium/components/arc/compat_mode/arc_resize_lock_manager.h
+++ b/chromium/components/arc/compat_mode/arc_resize_lock_manager.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_ARC_COMPAT_MODE_ARC_RESIZE_LOCK_MANAGER_H_
#define COMPONENTS_ARC_COMPAT_MODE_ARC_RESIZE_LOCK_MANAGER_H_
-#include "base/callback_forward.h"
#include "base/scoped_multi_source_observation.h"
#include "base/scoped_observation.h"
#include "components/arc/compat_mode/arc_resize_lock_pref_delegate.h"
diff --git a/chromium/components/arc/compat_mode/arc_resize_lock_pref_delegate.h b/chromium/components/arc/compat_mode/arc_resize_lock_pref_delegate.h
index 12c18f638dd..cd1d5036353 100644
--- a/chromium/components/arc/compat_mode/arc_resize_lock_pref_delegate.h
+++ b/chromium/components/arc/compat_mode/arc_resize_lock_pref_delegate.h
@@ -7,12 +7,18 @@
#include <string>
+#include "components/arc/mojom/compatibility_mode.mojom.h"
+
namespace arc {
class ArcResizeLockPrefDelegate {
public:
virtual ~ArcResizeLockPrefDelegate() = default;
+ virtual mojom::ArcResizeLockState GetResizeLockState(
+ const std::string& app_id) const = 0;
+ virtual void SetResizeLockState(const std::string& app_id,
+ mojom::ArcResizeLockState state) = 0;
virtual bool GetResizeLockNeedsConfirmation(const std::string& app_id) = 0;
virtual void SetResizeLockNeedsConfirmation(const std::string& app_id,
bool is_needed) = 0;
diff --git a/chromium/components/arc/compat_mode/arc_splash_screen_dialog_view.cc b/chromium/components/arc/compat_mode/arc_splash_screen_dialog_view.cc
new file mode 100644
index 00000000000..3308b69bb03
--- /dev/null
+++ b/chromium/components/arc/compat_mode/arc_splash_screen_dialog_view.cc
@@ -0,0 +1,176 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/compat_mode/arc_splash_screen_dialog_view.h"
+
+#include "base/bind.h"
+#include "components/arc/vector_icons/vector_icons.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/vector_icons/vector_icons.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/background.h"
+#include "ui/views/border.h"
+#include "ui/views/bubble/bubble_border.h"
+#include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/image_button_factory.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/link.h"
+#include "ui/views/controls/styled_label.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/box_layout_view.h"
+#include "ui/views/layout/fill_layout.h"
+
+namespace arc {
+
+using ClickedCallback = base::RepeatingCallback<void()>;
+
+namespace {
+
+constexpr SkColor kScrimColor = SkColorSetA(gfx::kGoogleGrey900, 0x99);
+
+std::unique_ptr<views::BubbleBorder> CreateBorder(SkColor color) {
+ constexpr int kCornerRadius = 12;
+ auto border = std::make_unique<views::BubbleBorder>(
+ views::BubbleBorder::NONE, views::BubbleBorder::STANDARD_SHADOW, color);
+ border->SetCornerRadius(kCornerRadius);
+ return border;
+}
+
+std::unique_ptr<views::Button> CreateCloseButton(
+ views::Button::PressedCallback close_callback) {
+ constexpr gfx::Size kCloseButtonSize{32, 32};
+ auto close_button = views::CreateVectorImageButtonWithNativeTheme(
+ std::move(close_callback), vector_icons::kCloseRoundedIcon);
+ close_button->SetSize(kCloseButtonSize);
+ close_button->ink_drop()->SetMode(views::InkDropHost::InkDropMode::OFF);
+ return close_button;
+}
+
+std::unique_ptr<views::View> CreateMessageBox(ClickedCallback link_callback) {
+ constexpr int kMessageBoxSpacing = 16;
+ auto message_box_view = std::make_unique<views::BoxLayoutView>();
+ message_box_view->SetOrientation(views::BoxLayout::Orientation::kVertical);
+ message_box_view->SetMainAxisAlignment(
+ views::BoxLayout::MainAxisAlignment::kCenter);
+ message_box_view->SetBetweenChildSpacing(kMessageBoxSpacing);
+
+ // message title
+ const std::u16string heading =
+ l10n_util::GetStringUTF16(IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_TITLE);
+ auto heading_label = std::make_unique<views::Label>(
+ heading, views::style::CONTEXT_DIALOG_TITLE);
+ heading_label->SetMultiLine(true);
+ heading_label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+ heading_label->SetAllowCharacterBreak(true);
+ message_box_view->AddChildView(std::move(heading_label));
+
+ // message body
+ const std::u16string link =
+ l10n_util::GetStringUTF16(IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_LINK);
+ size_t offset;
+ const std::u16string text = l10n_util::GetStringFUTF16(
+ IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_BODY, link, &offset);
+ auto body_label = std::make_unique<views::StyledLabel>();
+ body_label->SetText(text);
+ body_label->SetTextContext(
+ views::style::TextContext::CONTEXT_DIALOG_BODY_TEXT);
+ body_label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+
+ // Create link portion
+ views::StyledLabel::RangeStyleInfo link_style;
+ auto link_view = std::make_unique<views::Link>(link);
+ link_view->SetCallback(std::move(link_callback));
+ link_view->SetEnabledColor(gfx::kGoogleBlue600);
+ link_view->SetTextStyle(views::style::STYLE_SECONDARY);
+ link_view->SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT);
+ link_style.custom_view = link_view.get();
+ body_label->AddCustomView(std::move(link_view));
+ body_label->AddStyleRange(gfx::Range(offset, offset + link.length()),
+ link_style);
+ message_box_view->AddChildView(std::move(body_label));
+ return message_box_view;
+}
+
+} // namespace
+
+ArcSplashScreenDialogView::TestApi::TestApi(ArcSplashScreenDialogView* view)
+ : view_(view) {}
+
+ArcSplashScreenDialogView::TestApi::~TestApi() = default;
+
+views::Button* ArcSplashScreenDialogView::TestApi::close_button() const {
+ return view_->close_button_;
+}
+
+ArcSplashScreenDialogView::ArcSplashScreenDialogView(
+ views::Button::PressedCallback close_callback) {
+ constexpr gfx::Insets kContentHorizontalMargin{0, 32};
+ auto* layout_manager = SetLayoutManager(std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kVertical, kContentHorizontalMargin));
+ layout_manager->set_main_axis_alignment(
+ views::BoxLayout::MainAxisAlignment::kCenter);
+ SetBackground(views::CreateSolidBackground(kScrimColor));
+
+ auto* container = AddChildView(std::make_unique<views::View>());
+ container->SetLayoutManager(std::make_unique<views::FillLayout>());
+ auto border = CreateBorder(kScrimColor);
+ container->SetBackground(
+ std::make_unique<views::BubbleBackground>(border.get()));
+ container->SetBorder(std::move(border));
+
+ auto* contents =
+ container->AddChildView(std::make_unique<views::BoxLayoutView>());
+ contents->SetOrientation(views::BoxLayout::Orientation::kVertical);
+ contents->SetInsideBorderInsets(gfx::Insets(6));
+ contents->SetBackground(views::CreateRoundedRectBackground(
+ GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_DialogBackground),
+ 12));
+
+ // add close button
+ auto* caption =
+ contents->AddChildView(std::make_unique<views::BoxLayoutView>());
+ caption->SetOrientation(views::BoxLayout::Orientation::kHorizontal);
+ caption->SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kEnd);
+ auto close_button = CreateCloseButton(std::move(close_callback));
+ close_button_ = caption->AddChildView(std::move(close_button));
+
+ // add main view
+ constexpr int kImageSpacing = 8;
+ constexpr gfx::Insets kImageMargin{0, 18, 26, 18};
+ auto* main_view =
+ contents->AddChildView(std::make_unique<views::BoxLayoutView>());
+ main_view->SetOrientation(views::BoxLayout::Orientation::kVertical);
+ main_view->SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kCenter);
+ main_view->SetInsideBorderInsets(kImageMargin);
+ main_view->SetBetweenChildSpacing(kImageSpacing);
+
+ auto image_view = std::make_unique<views::ImageView>();
+ constexpr int kLogoImageSize = 122;
+ image_view->SetImage(
+ gfx::CreateVectorIcon(kCompatModeSplashscreenIcon, kLogoImageSize,
+ GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_DefaultIconColor)));
+ main_view->AddChildView(std::move(image_view));
+
+ auto message_box = CreateMessageBox(base::BindRepeating(
+ &ArcSplashScreenDialogView::OnLinkClicked, base::Unretained(this)));
+ main_view->AddChildView(std::move(message_box));
+}
+
+ArcSplashScreenDialogView::~ArcSplashScreenDialogView() = default;
+
+void ArcSplashScreenDialogView::OnLinkClicked() {
+ // TODO(b/180253004): Calling per-app setting
+ NOTIMPLEMENTED();
+}
+
+std::unique_ptr<ArcSplashScreenDialogView> BuildSplashScreenDialogView(
+ views::Button::PressedCallback close_callback) {
+ return std::make_unique<ArcSplashScreenDialogView>(std::move(close_callback));
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/compat_mode/arc_splash_screen_dialog_view.h b/chromium/components/arc/compat_mode/arc_splash_screen_dialog_view.h
new file mode 100644
index 00000000000..0630365b17b
--- /dev/null
+++ b/chromium/components/arc/compat_mode/arc_splash_screen_dialog_view.h
@@ -0,0 +1,50 @@
+// Copyright 2021 The Chromium Authors. 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_ARC_COMPAT_MODE_ARC_SPLASH_SCREEN_DIALOG_VIEW_H_
+#define COMPONENTS_ARC_COMPAT_MODE_ARC_SPLASH_SCREEN_DIALOG_VIEW_H_
+
+#include "ui/views/controls/button/button.h"
+
+namespace arc {
+
+// This class creates a splash screen view looks like a dialog. The view has a
+// transparent background color, with a content box inserted in the middle. It
+// also has a close button on the top right corner. This view is intended to be
+// inserted into a window. The content container contains a logo, a heading
+// text, a message box in vertical alignment.
+class ArcSplashScreenDialogView : public views::View {
+ public:
+ // TestApi is used for tests to get internal implementation details.
+ class TestApi {
+ public:
+ explicit TestApi(ArcSplashScreenDialogView* view);
+ ~TestApi();
+
+ views::Button* close_button() const;
+
+ private:
+ ArcSplashScreenDialogView* const view_;
+ };
+
+ explicit ArcSplashScreenDialogView(
+ views::Button::PressedCallback close_callback);
+ ArcSplashScreenDialogView(const ArcSplashScreenDialogView&) = delete;
+ ArcSplashScreenDialogView& operator=(const ArcSplashScreenDialogView&) =
+ delete;
+ ~ArcSplashScreenDialogView() override;
+
+ private:
+ void OnLinkClicked();
+
+ views::Button* close_button_ = nullptr;
+};
+
+// Build a splash screen dialog view to advertise resize lock feature
+std::unique_ptr<ArcSplashScreenDialogView> BuildSplashScreenDialogView(
+ views::Button::PressedCallback close_callback);
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_COMPAT_MODE_ARC_SPLASH_SCREEN_DIALOG_VIEW_H_
diff --git a/chromium/components/arc/compat_mode/arc_splash_screen_dialog_view_unittest.cc b/chromium/components/arc/compat_mode/arc_splash_screen_dialog_view_unittest.cc
new file mode 100644
index 00000000000..ba29e4f28b2
--- /dev/null
+++ b/chromium/components/arc/compat_mode/arc_splash_screen_dialog_view_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/compat_mode/arc_splash_screen_dialog_view.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace arc {
+namespace {
+
+void ClickOnView(views::View* view) {
+ ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ view->OnMousePressed(click);
+ ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ view->OnMouseReleased(release);
+}
+
+} // namespace
+
+class ArcSplashScreenDialogViewTest : public views::ViewsTestBase {
+ public:
+ ArcSplashScreenDialogViewTest() = default;
+ ArcSplashScreenDialogViewTest(const ArcSplashScreenDialogViewTest& other) =
+ delete;
+ ArcSplashScreenDialogViewTest& operator=(
+ const ArcSplashScreenDialogViewTest& other) = delete;
+ ~ArcSplashScreenDialogViewTest() override = default;
+
+ // views::ViewsTestBase:
+ void SetUp() override {
+ views::ViewsTestBase::SetUp();
+ widget_ = CreateTestWidget();
+ widget_->SetBounds(gfx::Rect(800, 800));
+ auto dialog_view = BuildSplashScreenDialogView(
+ base::BindRepeating(&ArcSplashScreenDialogViewTest::OnCloseCallback,
+ base::Unretained(this)));
+ dialog_view_ = widget_->SetContentsView(std::move(dialog_view));
+ }
+
+ void TearDown() override {
+ widget_.reset();
+ views::ViewsTestBase::TearDown();
+ }
+
+ protected:
+ ArcSplashScreenDialogView* dialog_view() { return dialog_view_; }
+
+ void OnCloseCallback() { on_close_callback_called = true; }
+
+ bool on_close_callback_called = false;
+
+ private:
+ ArcSplashScreenDialogView* dialog_view_;
+ std::unique_ptr<views::Widget> widget_;
+};
+
+TEST_F(ArcSplashScreenDialogViewTest, TestBuildSplashScreenDialogView) {
+ ArcSplashScreenDialogView::TestApi dialog_view_test(dialog_view());
+ EXPECT_TRUE(dialog_view_test.close_button()->GetVisible());
+ ClickOnView(dialog_view_test.close_button());
+ EXPECT_TRUE(on_close_callback_called);
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/compat_mode/resize_confirmation_dialog.cc b/chromium/components/arc/compat_mode/resize_confirmation_dialog.cc
deleted file mode 100644
index 007e7d763f0..00000000000
--- a/chromium/components/arc/compat_mode/resize_confirmation_dialog.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/arc/compat_mode/resize_confirmation_dialog.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/callback_forward.h"
-#include "components/exo/wm_helper.h"
-#include "components/strings/grit/components_strings.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/views/controls/button/checkbox.h"
-#include "ui/views/layout/box_layout_view.h"
-#include "ui/views/layout/layout_provider.h"
-#include "ui/views/window/dialog_delegate.h"
-
-namespace arc {
-
-namespace {
-
-class ResizeConfirmationDialogDelegate : public views::DialogDelegate {
- public:
- ResizeConfirmationDialogDelegate(ResizeConfirmationCallback callback,
- views::Checkbox* do_not_ask_checkbox)
- : callback_(std::move(callback)),
- do_not_ask_checkbox_(do_not_ask_checkbox) {}
- ResizeConfirmationDialogDelegate(const ResizeConfirmationDialogDelegate&) =
- delete;
- ResizeConfirmationDialogDelegate& operator=(
- const ResizeConfirmationDialogDelegate&) = delete;
- ~ResizeConfirmationDialogDelegate() override = default;
-
- void RunCallback(bool accept) {
- DCHECK(callback_);
- std::move(callback_).Run(accept, do_not_ask_checkbox_->GetChecked());
- }
-
- private:
- ResizeConfirmationCallback callback_;
- const views::Checkbox* do_not_ask_checkbox_;
-};
-
-std::unique_ptr<views::DialogDelegate> MakeDialogDelegate(
- ResizeConfirmationCallback callback) {
- // Setup contents.
- views::LayoutProvider* provider = views::LayoutProvider::Get();
- auto contents = std::make_unique<views::BoxLayoutView>();
- contents->SetOrientation(views::BoxLayout::Orientation::kVertical);
- contents->SetInsideBorderInsets(
- provider->GetInsetsMetric(views::InsetsMetric::INSETS_DIALOG));
- contents->SetBetweenChildSpacing(
- provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL));
-
- auto* message_label = contents->AddChildView(std::make_unique<views::Label>(
- l10n_util::GetStringUTF16(IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_BODY),
- views::style::CONTEXT_DIALOG_BODY_TEXT));
- message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- message_label->SetMultiLine(true);
-
- auto* checkbox = contents->AddChildView(
- std::make_unique<views::Checkbox>(l10n_util::GetStringUTF16(
- IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_DONT_ASK_ME)));
-
- // Setup delegate.
- auto delegate = std::make_unique<ResizeConfirmationDialogDelegate>(
- std::move(callback), checkbox);
- delegate->SetContentsView(std::move(contents));
- delegate->SetShowCloseButton(false);
- delegate->SetOwnedByWidget(true);
- delegate->SetTitle(
- l10n_util::GetStringUTF16(IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_TITLE));
- delegate->SetButtonLabel(
- ui::DIALOG_BUTTON_OK,
- l10n_util::GetStringUTF16(IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_ACCEPT));
- delegate->SetModalType(ui::MODAL_TYPE_WINDOW);
- delegate->set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
- views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
-
- // Safe to set "Unretained" as |delegate| is owned by widget, so keeps
- // alive within the life-time of the widget.
- delegate->SetAcceptCallback(
- base::BindOnce(&ResizeConfirmationDialogDelegate::RunCallback,
- base::Unretained(delegate.get()), /*accept=*/true));
- delegate->SetCancelCallback(
- base::BindOnce(&ResizeConfirmationDialogDelegate::RunCallback,
- base::Unretained(delegate.get()), /*accept=*/false));
-
- return delegate;
-}
-
-} // namespace
-
-views::Widget* ShowResizeConfirmationDialog(
- aura::Window* parent,
- ResizeConfirmationCallback callback) {
- // TOOD(b/183664767): Switch dialog to use exo's overlay.
- auto* widget = views::DialogDelegate::CreateDialogWidget(
- MakeDialogDelegate(std::move(callback)),
- exo::WMHelper::GetInstance()->GetRootWindowForNewWindows(), parent);
- widget->Show();
- return widget;
-}
-
-} // namespace arc
diff --git a/chromium/components/arc/compat_mode/resize_confirmation_dialog.h b/chromium/components/arc/compat_mode/resize_confirmation_dialog.h
deleted file mode 100644
index 39e46c160ad..00000000000
--- a/chromium/components/arc/compat_mode/resize_confirmation_dialog.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_H_
-#define COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_H_
-
-#include "base/callback_forward.h"
-
-namespace aura {
-class Window;
-} // namespace aura
-
-namespace views {
-class Widget;
-} // namespace views
-
-namespace arc {
-
-// Callback to notify user's confirmation for allowing to resize the app.
-// If user accept it, the callback is invoked with 1st argument true.
-// Otherwise, with false.
-// If the user marked the "Don't ask me again", 2nd argument will be true.
-using ResizeConfirmationCallback = base::OnceCallback<void(bool, bool)>;
-
-// Shows confirmation dialog for asking user if really want to perform resize
-// operation for the resize-locked ARC app.
-views::Widget* ShowResizeConfirmationDialog(
- aura::Window* parent,
- ResizeConfirmationCallback callback);
-
-} // namespace arc
-
-#endif // COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_H_
diff --git a/chromium/components/arc/compat_mode/resize_confirmation_dialog_unittest.cc b/chromium/components/arc/compat_mode/resize_confirmation_dialog_unittest.cc
deleted file mode 100644
index a259dd224e2..00000000000
--- a/chromium/components/arc/compat_mode/resize_confirmation_dialog_unittest.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/arc/compat_mode/resize_confirmation_dialog.h"
-
-#include "base/callback_helpers.h"
-#include "components/exo/test/exo_test_base_views.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/views/layout/layout_provider.h"
-
-namespace arc {
-namespace {
-
-using ResizeConfirmationDialogTest = exo::test::ExoTestBaseViews;
-
-// Test that ShowResizeConfirmationDialog does not crash
-TEST_F(ResizeConfirmationDialogTest, ShowAndCloseDialog) {
- // A LayoutProvider must exist in scope in order to set up views.
- views::LayoutProvider layout_provider;
-
- auto* widget = ShowResizeConfirmationDialog(nullptr, base::DoNothing());
- RunPendingMessages();
- widget->Close();
- RunPendingMessages();
-}
-
-} // namespace
-} // namespace arc
diff --git a/chromium/components/arc/compat_mode/resize_confirmation_dialog_view.cc b/chromium/components/arc/compat_mode/resize_confirmation_dialog_view.cc
new file mode 100644
index 00000000000..db17fe62e00
--- /dev/null
+++ b/chromium/components/arc/compat_mode/resize_confirmation_dialog_view.cc
@@ -0,0 +1,166 @@
+// Copyright 2021 The Chromium Authors. 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/compat_mode/resize_confirmation_dialog_view.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "components/exo/shell_surface_base.h"
+#include "components/exo/shell_surface_util.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/strings/grit/ui_strings.h"
+#include "ui/views/background.h"
+#include "ui/views/bubble/bubble_border.h"
+#include "ui/views/controls/button/checkbox.h"
+#include "ui/views/controls/button/md_text_button.h"
+#include "ui/views/layout/flex_layout_view.h"
+#include "ui/views/layout/layout_provider.h"
+
+namespace arc {
+
+namespace {
+
+std::unique_ptr<views::View> MakeOverlayDialogContainerView(
+ std::unique_ptr<views::View> dialog_view) {
+ constexpr SkColor kScrimColor = SkColorSetA(gfx::kGoogleGrey900, 0x99);
+
+ auto container = views::Builder<views::FlexLayoutView>()
+ .SetInteriorMargin(gfx::Insets(0, 32))
+ .SetMainAxisAlignment(views::LayoutAlignment::kCenter)
+ .SetCrossAxisAlignment(views::LayoutAlignment::kCenter)
+ .SetBackground(views::CreateSolidBackground(kScrimColor))
+ .Build();
+ dialog_view->SetProperty(
+ views::kFlexBehaviorKey,
+ views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero));
+
+ container->AddChildView(std::move(dialog_view));
+
+ return container;
+}
+
+} // namespace
+
+ResizeConfirmationDialogView::ResizeConfirmationDialogView(
+ ResizeConfirmationCallback callback)
+ : callback_(std::move(callback)) {
+ views::LayoutProvider* provider = views::LayoutProvider::Get();
+ SetOrientation(views::BoxLayout::Orientation::kVertical);
+ SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kStart);
+ SetInsideBorderInsets(gfx::Insets(24, 24, 20, 24));
+ SetBetweenChildSpacing(
+ provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL));
+
+ constexpr int kCornerRadius = 12;
+ auto border = std::make_unique<views::BubbleBorder>(
+ views::BubbleBorder::NONE, views::BubbleBorder::STANDARD_SHADOW,
+ GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_DialogBackground));
+ border->SetCornerRadius(kCornerRadius);
+ SetBackground(std::make_unique<views::BubbleBackground>(border.get()));
+ SetBorder(std::move(border));
+
+ AddChildView(
+ views::Builder<views::Label>()
+ .SetText(l10n_util::GetStringUTF16(
+ IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_TITLE))
+ .SetTextContext(views::style::CONTEXT_DIALOG_TITLE)
+ .SetMultiLine(true)
+ .SetHorizontalAlignment(gfx::ALIGN_LEFT)
+ .SetAllowCharacterBreak(true)
+ .SetFontList(views::style::GetFont(
+ views::style::TextContext::CONTEXT_DIALOG_TITLE,
+ views::style::TextStyle::STYLE_PRIMARY)
+ .DeriveWithWeight(gfx::Font::Weight::MEDIUM))
+ .Build());
+
+ AddChildView(MakeContentsView());
+ AddChildView(MakeButtonsView());
+}
+
+ResizeConfirmationDialogView::~ResizeConfirmationDialogView() = default;
+
+gfx::Size ResizeConfirmationDialogView::CalculatePreferredSize() const {
+ gfx::Size size = views::View::CalculatePreferredSize();
+
+ views::LayoutProvider* provider = views::LayoutProvider::Get();
+ size.set_width(provider->GetDistanceMetric(
+ views::DistanceMetric::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
+ return size;
+}
+
+std::unique_ptr<views::View> ResizeConfirmationDialogView::MakeContentsView() {
+ return views::Builder<views::BoxLayoutView>()
+ .SetOrientation(views::BoxLayout::Orientation::kVertical)
+ .SetBetweenChildSpacing(19)
+ .SetProperty(views::kMarginsKey, gfx::Insets(0, 0, 23, 0))
+ .AddChildren(
+ {views::Builder<views::Label>()
+ .SetText(l10n_util::GetStringUTF16(
+ IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_BODY))
+ .SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT)
+ .SetHorizontalAlignment(gfx::ALIGN_LEFT)
+ .SetMultiLine(true),
+ views::Builder<views::Checkbox>()
+ .CopyAddressTo(&do_not_ask_checkbox_)
+ .SetText(l10n_util::GetStringUTF16(
+ IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_DONT_ASK_ME))})
+ .Build();
+}
+
+std::unique_ptr<views::View> ResizeConfirmationDialogView::MakeButtonsView() {
+ views::LayoutProvider* provider = views::LayoutProvider::Get();
+ return views::Builder<views::BoxLayoutView>()
+ .SetOrientation(views::BoxLayout::Orientation::kHorizontal)
+ .SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kEnd)
+ .SetBetweenChildSpacing(provider->GetDistanceMetric(
+ views::DistanceMetric::DISTANCE_RELATED_BUTTON_HORIZONTAL))
+ .AddChildren({views::Builder<views::MdTextButton>() // Cancel button.
+ .CopyAddressTo(&cancel_button_)
+ .SetCallback(base::BindRepeating(
+ &ResizeConfirmationDialogView::OnButtonClicked,
+ base::Unretained(this), false))
+ .SetText(l10n_util::GetStringUTF16(IDS_APP_CANCEL))
+ .SetProminent(false)
+ .SetIsDefault(false),
+ views::Builder<views::MdTextButton>() // Accept button.
+ .CopyAddressTo(&accept_button_)
+ .SetCallback(base::BindRepeating(
+ &ResizeConfirmationDialogView::OnButtonClicked,
+ base::Unretained(this), true))
+ .SetText(l10n_util::GetStringUTF16(
+ IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_ACCEPT))
+ .SetProminent(true)
+ .SetIsDefault(true)})
+ .Build();
+}
+
+void ResizeConfirmationDialogView::OnButtonClicked(bool accept) {
+ DCHECK(callback_);
+ std::move(callback_).Run(accept, do_not_ask_checkbox_->GetChecked());
+}
+
+void ShowResizeConfirmationDialog(aura::Window* parent,
+ ResizeConfirmationCallback callback) {
+ auto* shell_surface_base = exo::GetShellSurfaceBaseForWindow(parent);
+ if (!shell_surface_base || shell_surface_base->HasOverlay())
+ return;
+
+ auto remove_overlay = base::BindOnce(
+ [](aura::Window* window) {
+ auto* shell_surface_base = exo::GetShellSurfaceBaseForWindow(window);
+ if (shell_surface_base && shell_surface_base->HasOverlay())
+ shell_surface_base->RemoveOverlay();
+ },
+ base::Unretained(parent));
+ exo::ShellSurfaceBase::OverlayParams params(MakeOverlayDialogContainerView(
+ std::make_unique<ResizeConfirmationDialogView>(
+ std::move(callback).Then(std::move(remove_overlay)))));
+ params.translucent = true;
+ shell_surface_base->AddOverlay(std::move(params));
+}
+
+} // namespace arc
diff --git a/chromium/components/arc/compat_mode/resize_confirmation_dialog_view.h b/chromium/components/arc/compat_mode/resize_confirmation_dialog_view.h
new file mode 100644
index 00000000000..d0b36a3968c
--- /dev/null
+++ b/chromium/components/arc/compat_mode/resize_confirmation_dialog_view.h
@@ -0,0 +1,73 @@
+// Copyright 2021 The Chromium Authors. 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_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_VIEW_H_
+#define COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_VIEW_H_
+
+#include "base/callback_forward.h"
+#include "ui/views/layout/box_layout_view.h"
+
+namespace aura {
+class Window;
+} // namespace aura
+
+namespace views {
+class MdTextButton;
+class Checkbox;
+} // namespace views
+
+namespace arc {
+
+// Callback to notify user's confirmation for allowing to resize the app.
+// If user accept it, the callback is invoked with 1st argument true.
+// Otherwise, with false.
+// If the user marked the "Don't ask me again", 2nd argument will be true.
+using ResizeConfirmationCallback = base::OnceCallback<void(bool, bool)>;
+
+class ResizeConfirmationDialogView : public views::BoxLayoutView {
+ public:
+ // TestApi is used only in tests to get internal views.
+ class TestApi {
+ public:
+ explicit TestApi(ResizeConfirmationDialogView* view) : view_(view) {}
+
+ views::MdTextButton* accept_button() const { return view_->accept_button_; }
+ views::MdTextButton* cancel_button() const { return view_->cancel_button_; }
+ views::Checkbox* do_not_ask_checkbox() const {
+ return view_->do_not_ask_checkbox_;
+ }
+
+ private:
+ ResizeConfirmationDialogView* const view_;
+ };
+
+ explicit ResizeConfirmationDialogView(ResizeConfirmationCallback callback);
+ ResizeConfirmationDialogView(const ResizeConfirmationDialogView&) = delete;
+ ResizeConfirmationDialogView& operator=(const ResizeConfirmationDialogView&) =
+ delete;
+ ~ResizeConfirmationDialogView() override;
+
+ gfx::Size CalculatePreferredSize() const override;
+
+ private:
+ std::unique_ptr<views::View> MakeContentsView();
+ std::unique_ptr<views::View> MakeButtonsView();
+
+ void OnButtonClicked(bool accept);
+
+ ResizeConfirmationCallback callback_;
+
+ views::Checkbox* do_not_ask_checkbox_{nullptr};
+ views::MdTextButton* accept_button_{nullptr};
+ views::MdTextButton* cancel_button_{nullptr};
+};
+
+// Shows confirmation dialog for asking user if really want to perform resize
+// operation for the resize-locked ARC app.
+void ShowResizeConfirmationDialog(aura::Window* parent,
+ ResizeConfirmationCallback callback);
+
+} // namespace arc
+
+#endif // COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_VIEW_H_
diff --git a/chromium/components/arc/compat_mode/resize_confirmation_dialog_view_unittest.cc b/chromium/components/arc/compat_mode/resize_confirmation_dialog_view_unittest.cc
new file mode 100644
index 00000000000..75a486c5caf
--- /dev/null
+++ b/chromium/components/arc/compat_mode/resize_confirmation_dialog_view_unittest.cc
@@ -0,0 +1,109 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/compat_mode/resize_confirmation_dialog_view.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/test/event_generator.h"
+#include "ui/views/controls/button/checkbox.h"
+#include "ui/views/controls/button/md_text_button.h"
+#include "ui/views/layout/layout_provider.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/widget_utils.h"
+
+namespace arc {
+namespace {
+
+class ResizeConfirmationDialogViewTest : public views::ViewsTestBase {
+ public:
+ // views::ViewsTestBase:
+ void SetUp() override {
+ views::ViewsTestBase::SetUp();
+ widget_ = CreateTestWidget();
+ widget_->SetBounds(gfx::Rect(800, 800));
+ dialog_view_ =
+ widget_->SetContentsView(std::make_unique<ResizeConfirmationDialogView>(
+ base::BindOnce(&ResizeConfirmationDialogViewTest::OnClicked,
+ base::Unretained(this))));
+ widget_->Show();
+ }
+
+ void TearDown() override {
+ widget_->Close();
+ widget_.reset();
+ views::ViewsTestBase::TearDown();
+ }
+
+ protected:
+ void ClickDialogButton(bool accept, bool with_checkbox) {
+ ResizeConfirmationDialogView::TestApi dialog_view_test(dialog_view_);
+ if (with_checkbox)
+ dialog_view_test.do_not_ask_checkbox()->SetChecked(true);
+
+ auto* target_button = accept ? dialog_view_test.accept_button()
+ : dialog_view_test.cancel_button();
+
+ ui::test::EventGenerator event_generator(GetRootWindow(widget_.get()));
+ event_generator.MoveMouseTo(
+ target_button->GetBoundsInScreen().CenterPoint());
+ event_generator.ClickLeftButton();
+ }
+
+ bool callback_called() { return callback_called_; }
+ bool callback_accepted() { return callback_accepted_; }
+ bool callback_do_not_ask_again() { return callback_do_not_ask_again_; }
+
+ private:
+ void OnClicked(bool accepted, bool do_not_ask_again) {
+ callback_called_ = true;
+ callback_accepted_ = accepted;
+ callback_do_not_ask_again_ = do_not_ask_again;
+ }
+
+ // For callback checks.
+ bool callback_called_{false};
+ bool callback_accepted_{false};
+ bool callback_do_not_ask_again_{false};
+
+ // A LayoutProvider must exist in scope in order to set up views.
+ views::LayoutProvider layout_provider;
+
+ ResizeConfirmationDialogView* dialog_view_;
+ std::unique_ptr<views::Widget> widget_;
+};
+
+TEST_F(ResizeConfirmationDialogViewTest, ClickAcceptWithCheckbox) {
+ ClickDialogButton(/*accept=*/true, /*with_checkbox=*/true);
+ EXPECT_TRUE(callback_called());
+ EXPECT_TRUE(callback_accepted());
+ EXPECT_TRUE(callback_do_not_ask_again());
+}
+
+TEST_F(ResizeConfirmationDialogViewTest, ClickCancelWithCheckbox) {
+ ClickDialogButton(/*accept=*/false, /*with_checkbox=*/true);
+ EXPECT_TRUE(callback_called());
+ EXPECT_FALSE(callback_accepted());
+ EXPECT_TRUE(callback_do_not_ask_again());
+}
+
+TEST_F(ResizeConfirmationDialogViewTest, ClickAcceptWithoutCheckbox) {
+ ClickDialogButton(/*accept=*/true, /*with_checkbox=*/false);
+ EXPECT_TRUE(callback_called());
+ EXPECT_TRUE(callback_accepted());
+ EXPECT_FALSE(callback_do_not_ask_again());
+}
+
+TEST_F(ResizeConfirmationDialogViewTest, ClickCancelWithoutCheckbox) {
+ ClickDialogButton(/*accept=*/false, /*with_checkbox=*/false);
+ EXPECT_TRUE(callback_called());
+ EXPECT_FALSE(callback_accepted());
+ EXPECT_FALSE(callback_do_not_ask_again());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/compat_mode/resize_toggle_menu.cc b/chromium/components/arc/compat_mode/resize_toggle_menu.cc
index 2a5458bbbe9..fa07fed2f99 100644
--- a/chromium/components/arc/compat_mode/resize_toggle_menu.cc
+++ b/chromium/components/arc/compat_mode/resize_toggle_menu.cc
@@ -8,9 +8,9 @@
#include "ash/resources/vector_icons/vector_icons.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "components/arc/compat_mode/resize_util.h"
#include "components/strings/grit/components_strings.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/widget/widget.h"
@@ -19,7 +19,7 @@ namespace arc {
namespace {
-base::Optional<ResizeToggleMenu::CommandId> PredictCurrentMode(
+absl::optional<ResizeToggleMenu::CommandId> PredictCurrentMode(
views::Widget* widget) {
const int width = widget->GetWindowBoundsInScreen().width();
const int height = widget->GetWindowBoundsInScreen().height();
@@ -32,7 +32,7 @@ base::Optional<ResizeToggleMenu::CommandId> PredictCurrentMode(
return ResizeToggleMenu::CommandId::kResizePhone;
else if (width > height)
return ResizeToggleMenu::CommandId::kResizeTablet;
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace
@@ -48,9 +48,9 @@ ResizeToggleMenu::ResizeToggleMenu(views::Widget* widget,
if (currentMode) {
auto* item = root_view_->GetMenuItemByID(*currentMode);
item->SetSelected(true);
- item->SetMinorIcon(
- ui::ThemedVectorIcon(&ash::kHollowCheckCircleIcon,
- ui::NativeTheme::kColorId_ProminentButtonColor));
+ item->SetMinorIcon(ui::ImageModel::FromVectorIcon(
+ ash::kHollowCheckCircleIcon,
+ ui::NativeTheme::kColorId_ProminentButtonColor));
}
menu_runner_ = std::make_unique<views::MenuRunner>(
diff --git a/chromium/components/arc/compat_mode/resize_toggle_menu_unittest.cc b/chromium/components/arc/compat_mode/resize_toggle_menu_unittest.cc
index ada2f34b5b4..cd56699b552 100644
--- a/chromium/components/arc/compat_mode/resize_toggle_menu_unittest.cc
+++ b/chromium/components/arc/compat_mode/resize_toggle_menu_unittest.cc
@@ -23,6 +23,12 @@ class TestArcResizeLockPrefDelegate : public ArcResizeLockPrefDelegate {
~TestArcResizeLockPrefDelegate() override = default;
// ArcResizeLockPrefDelegate:
+ mojom::ArcResizeLockState GetResizeLockState(
+ const std::string& app_id) const override {
+ return mojom::ArcResizeLockState::UNDEFINED;
+ }
+ void SetResizeLockState(const std::string& app_id,
+ mojom::ArcResizeLockState state) override {}
bool GetResizeLockNeedsConfirmation(const std::string& app_id) override {
return false;
}
diff --git a/chromium/components/arc/compat_mode/resize_util.cc b/chromium/components/arc/compat_mode/resize_util.cc
index 37f289a4e83..ddfbf9e07d1 100644
--- a/chromium/components/arc/compat_mode/resize_util.cc
+++ b/chromium/components/arc/compat_mode/resize_util.cc
@@ -9,7 +9,7 @@
#include "ash/public/cpp/window_properties.h"
#include "base/callback_forward.h"
#include "components/arc/compat_mode/arc_resize_lock_pref_delegate.h"
-#include "components/arc/compat_mode/resize_confirmation_dialog.h"
+#include "components/arc/compat_mode/resize_confirmation_dialog_view.h"
#include "ui/aura/window.h"
#include "ui/views/widget/widget.h"
diff --git a/chromium/components/arc/compat_mode/resize_util_unittest.cc b/chromium/components/arc/compat_mode/resize_util_unittest.cc
index 2601ceac789..886d46a1194 100644
--- a/chromium/components/arc/compat_mode/resize_util_unittest.cc
+++ b/chromium/components/arc/compat_mode/resize_util_unittest.cc
@@ -16,7 +16,6 @@
#include "ui/aura/window.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget.h"
-#include "ui/views/window/dialog_delegate.h"
namespace arc {
namespace {
@@ -28,6 +27,12 @@ class TestArcResizeLockPrefDelegate : public ArcResizeLockPrefDelegate {
~TestArcResizeLockPrefDelegate() override = default;
// ArcResizeLockPrefDelegate:
+ mojom::ArcResizeLockState GetResizeLockState(
+ const std::string& app_id) const override {
+ return mojom::ArcResizeLockState::UNDEFINED;
+ }
+ void SetResizeLockState(const std::string& app_id,
+ mojom::ArcResizeLockState state) override {}
bool GetResizeLockNeedsConfirmation(const std::string& app_id) override {
return base::Contains(confirmation_needed_app_ids_, app_id);
}
@@ -50,20 +55,6 @@ class TestArcResizeLockPrefDelegate : public ArcResizeLockPrefDelegate {
class ResizeUtilTest : public exo::test::ExoTestBaseViews {
public:
- void AcceptChildDialog(views::Widget* parent_widget) {
- auto* dialog_widget = GetChildDialogWidget(parent_widget);
- views::test::WidgetDestroyedWaiter waiter(dialog_widget);
- DialogDelegateFor(dialog_widget)->AcceptDialog();
- waiter.Wait();
- }
-
- void CancelChildDialog(views::Widget* parent_widget) {
- auto* dialog_widget = GetChildDialogWidget(parent_widget);
- views::test::WidgetDestroyedWaiter waiter(dialog_widget);
- DialogDelegateFor(dialog_widget)->CancelDialog();
- waiter.Wait();
- }
-
// Overridden from test::Test.
void SetUp() override {
exo::test::ExoTestBaseViews::SetUp();
@@ -76,18 +67,6 @@ class ResizeUtilTest : public exo::test::ExoTestBaseViews {
views::Widget* widget() { return widget_.get(); }
private:
- views::DialogDelegate* DialogDelegateFor(views::Widget* widget) {
- auto* delegate = widget->widget_delegate()->AsDialogDelegate();
- return delegate;
- }
-
- views::Widget* GetChildDialogWidget(views::Widget* widget) {
- std::set<views::Widget*> child_widgets;
- views::Widget::GetAllOwnedWidgets(widget->GetNativeView(), &child_widgets);
- DCHECK_EQ(1u, child_widgets.size());
- return *child_widgets.begin();
- }
-
TestArcResizeLockPrefDelegate pref_delegate_;
std::unique_ptr<views::Widget> widget_;
};
@@ -97,25 +76,11 @@ class ResizeUtilTest : public exo::test::ExoTestBaseViews {
TEST_F(ResizeUtilTest, TestResizeToPhone) {
widget()->Maximize();
- // Test the widget is resized if accepted the confirmation dialog.
- pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true);
- ResizeToPhoneWithConfirmationIfNeeded(widget(), pref_delegate());
- EXPECT_TRUE(widget()->IsMaximized());
- AcceptChildDialog(widget());
- EXPECT_FALSE(widget()->IsMaximized());
- EXPECT_LT(widget()->GetWindowBoundsInScreen().width(),
- widget()->GetWindowBoundsInScreen().height());
-
- widget()->Maximize();
-
- // Test the widget is NOT resized if cancelled the confirmation dialog.
+ // Test the widget is NOT resized immediately if the confirmation dialog is
+ // needed.
pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true);
ResizeToPhoneWithConfirmationIfNeeded(widget(), pref_delegate());
EXPECT_TRUE(widget()->IsMaximized());
- CancelChildDialog(widget());
- EXPECT_TRUE(widget()->IsMaximized());
-
- widget()->Maximize();
// Test the widget is resized without confirmation.
pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, false);
@@ -131,25 +96,11 @@ TEST_F(ResizeUtilTest, TestResizeToPhone) {
TEST_F(ResizeUtilTest, TestResizeToTablet) {
widget()->Maximize();
- // Test the widget is resized if accepted the confirmation dialog.
+ // Test the widget is NOT resized immediately if the confirmation dialog is
+ // needed.
pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true);
ResizeToTabletWithConfirmationIfNeeded(widget(), pref_delegate());
EXPECT_TRUE(widget()->IsMaximized());
- AcceptChildDialog(widget());
- EXPECT_FALSE(widget()->IsMaximized());
- EXPECT_GT(widget()->GetWindowBoundsInScreen().width(),
- widget()->GetWindowBoundsInScreen().height());
-
- widget()->Maximize();
-
- // Test the widget is NOT resized if cancelled the confirmation dialog.
- pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true);
- ResizeToTabletWithConfirmationIfNeeded(widget(), pref_delegate());
- EXPECT_TRUE(widget()->IsMaximized());
- CancelChildDialog(widget());
- EXPECT_TRUE(widget()->IsMaximized());
-
- widget()->Maximize();
// Test the widget is resized without confirmation.
pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, false);
@@ -165,23 +116,11 @@ TEST_F(ResizeUtilTest, TestResizeToTablet) {
TEST_F(ResizeUtilTest, TestResizeToDesktop) {
widget()->Restore();
- // Test the widget is resized if accepted the confirmation dialog.
+ // Test the widget is NOT resized immediately if the confirmation dialog is
+ // needed.
pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true);
ResizeToDesktopWithConfirmationIfNeeded(widget(), pref_delegate());
EXPECT_FALSE(widget()->IsMaximized());
- AcceptChildDialog(widget());
- EXPECT_TRUE(widget()->IsMaximized());
-
- widget()->Restore();
-
- // Test the widget is NOT resized if cancelled the confirmation dialog.
- pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true);
- ResizeToDesktopWithConfirmationIfNeeded(widget(), pref_delegate());
- EXPECT_FALSE(widget()->IsMaximized());
- CancelChildDialog(widget());
- EXPECT_FALSE(widget()->IsMaximized());
-
- widget()->Restore();
// Test the widget is resized without confirmation.
pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, false);
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 f4cb8275a40..8921befdecb 100644
--- a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
+++ b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.cc
@@ -20,7 +20,6 @@
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
-#include "components/arc/arc_util.h"
#include "components/arc/session/arc_bridge_service.h"
#include "mojo/public/cpp/system/platform_handle.h"
@@ -49,8 +48,13 @@ bool RunCrashReporter(const std::vector<std::string>& args, int stdin_fd) {
// Runs crash_reporter to save the java crash info provided via the pipe.
void RunJavaCrashReporter(const std::string& crash_type,
base::ScopedFD pipe,
- std::vector<std::string> args) {
+ std::vector<std::string> args,
+ absl::optional<base::TimeDelta> uptime) {
args.push_back("--arc_java_crash=" + crash_type);
+ if (uptime) {
+ args.push_back(
+ base::StringPrintf("--arc_uptime=%" PRId64, uptime->InMilliseconds()));
+ }
if (!RunCrashReporter(args, pipe.get()))
LOG(ERROR) << "Failed to run crash_reporter";
@@ -112,6 +116,14 @@ ArcCrashCollectorBridge* ArcCrashCollectorBridge::GetForBrowserContext(
return ArcCrashCollectorBridgeFactory::GetForBrowserContext(context);
}
+// static
+ArcCrashCollectorBridge*
+ArcCrashCollectorBridge::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcCrashCollectorBridgeFactory::GetForBrowserContextForTesting(
+ context);
+}
+
ArcCrashCollectorBridge::ArcCrashCollectorBridge(
content::BrowserContext* context,
ArcBridgeService* bridge_service)
@@ -123,13 +135,15 @@ ArcCrashCollectorBridge::~ArcCrashCollectorBridge() {
arc_bridge_service_->crash_collector()->SetHost(nullptr);
}
-void ArcCrashCollectorBridge::DumpCrash(const std::string& type,
- mojo::ScopedHandle pipe) {
+void ArcCrashCollectorBridge::DumpCrash(
+ const std::string& type,
+ mojo::ScopedHandle pipe,
+ absl::optional<base::TimeDelta> uptime) {
base::ThreadPool::PostTask(
FROM_HERE, {base::WithBaseSyncPrimitives()},
base::BindOnce(&RunJavaCrashReporter, type,
mojo::UnwrapPlatformHandle(std::move(pipe)).TakeFD(),
- CreateCrashReporterArgs()));
+ CreateCrashReporterArgs(), uptime));
}
void ArcCrashCollectorBridge::DumpNativeCrash(const std::string& exec_name,
@@ -158,7 +172,7 @@ void ArcCrashCollectorBridge::SetBuildProperties(
const std::string& device,
const std::string& board,
const std::string& cpu_abi,
- const base::Optional<std::string>& fingerprint) {
+ const absl::optional<std::string>& fingerprint) {
device_ = device;
board_ = board;
cpu_abi_ = cpu_abi;
@@ -175,9 +189,6 @@ std::vector<std::string> ArcCrashCollectorBridge::CreateCrashReporterArgs() {
if (fingerprint_)
args.push_back("--arc_fingerprint=" + fingerprint_.value());
- if (arc::IsArcVmEnabled())
- args.emplace_back("--arc_is_arcvm");
-
return args;
}
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 2c13abd6fcd..0d7ee2153b7 100644
--- a/chromium/components/arc/crash_collector/arc_crash_collector_bridge.h
+++ b/chromium/components/arc/crash_collector/arc_crash_collector_bridge.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "components/arc/mojom/crash_collector.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "mojo/public/mojom/base/time.mojom.h"
namespace content {
class BrowserContext;
@@ -28,6 +29,8 @@ class ArcCrashCollectorBridge
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcCrashCollectorBridge* GetForBrowserContext(
content::BrowserContext* context);
+ static ArcCrashCollectorBridge* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
ArcCrashCollectorBridge(content::BrowserContext* context,
ArcBridgeService* bridge);
@@ -38,7 +41,9 @@ class ArcCrashCollectorBridge
~ArcCrashCollectorBridge() override;
// mojom::CrashCollectorHost overrides.
- void DumpCrash(const std::string& type, mojo::ScopedHandle pipe) override;
+ void DumpCrash(const std::string& type,
+ mojo::ScopedHandle pipe,
+ absl::optional<base::TimeDelta> uptime) override;
void DumpNativeCrash(const std::string& exec_name,
int32_t pid,
int64_t timestamp,
@@ -48,7 +53,7 @@ class ArcCrashCollectorBridge
const std::string& device,
const std::string& board,
const std::string& cpu_abi,
- const base::Optional<std::string>& fingerprint) override;
+ const absl::optional<std::string>& fingerprint) override;
private:
std::vector<std::string> CreateCrashReporterArgs();
@@ -58,7 +63,7 @@ class ArcCrashCollectorBridge
std::string device_;
std::string board_;
std::string cpu_abi_;
- base::Optional<std::string> fingerprint_;
+ absl::optional<std::string> fingerprint_;
};
} // namespace arc
diff --git a/chromium/components/arc/crash_collector/arc_crash_collector_bridge_unittest.cc b/chromium/components/arc/crash_collector/arc_crash_collector_bridge_unittest.cc
new file mode 100644
index 00000000000..153b86b123a
--- /dev/null
+++ b/chromium/components/arc/crash_collector/arc_crash_collector_bridge_unittest.cc
@@ -0,0 +1,78 @@
+// Copyright 2021 The Chromium Authors. 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/crash_collector/arc_crash_collector_bridge.h"
+
+#include <unistd.h>
+
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/test/test_browser_context.h"
+#include "content/public/test/browser_task_environment.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcCrashCollectorBridgeTest : public testing::Test {
+ protected:
+ ArcCrashCollectorBridgeTest()
+ : bridge_(ArcCrashCollectorBridge::GetForBrowserContextForTesting(
+ &context_)) {}
+ ArcCrashCollectorBridgeTest(const ArcCrashCollectorBridgeTest&) = delete;
+ ArcCrashCollectorBridgeTest& operator=(const ArcCrashCollectorBridgeTest&) =
+ delete;
+ ~ArcCrashCollectorBridgeTest() override = default;
+
+ ArcCrashCollectorBridge* bridge() { return bridge_; }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ ArcServiceManager arc_service_manager_;
+ TestBrowserContext context_;
+ ArcCrashCollectorBridge* const bridge_;
+};
+
+TEST_F(ArcCrashCollectorBridgeTest, ConstructDestruct) {}
+
+// Tests that SetBuildProperties doesn't crash even if nullopt is passed as a
+// fingerprint.
+TEST_F(ArcCrashCollectorBridgeTest, SetBuildProperties) {
+ ASSERT_NE(nullptr, bridge());
+ bridge()->SetBuildProperties("device", "board", "cpu_abi",
+ absl::optional<std::string>());
+ bridge()->SetBuildProperties("device", "board", "cpu_abi",
+ absl::optional<std::string>("fingerprint"));
+}
+
+// Tests that DumpCrash doesn't crash.
+// TODO(yusukes): Test the behavior beyond just "no crash".
+TEST_F(ArcCrashCollectorBridgeTest, DumpCrash) {
+ ASSERT_NE(nullptr, bridge());
+ bridge()->SetBuildProperties("device", "board", "cpu_abi",
+ absl::optional<std::string>());
+ bridge()->DumpCrash("type", mojo::ScopedHandle(), absl::nullopt);
+}
+
+// Tests that DumpNativeCrash doesn't crash.
+// TODO(yusukes): Test the behavior beyond just "no crash".
+TEST_F(ArcCrashCollectorBridgeTest, DumpNativeCrash) {
+ ASSERT_NE(nullptr, bridge());
+ bridge()->SetBuildProperties("device", "board", "cpu_abi",
+ absl::optional<std::string>());
+ bridge()->DumpNativeCrash("exec_name", getpid(), /*timestamp=*/42,
+ mojo::ScopedHandle());
+}
+
+// Tests that DumpKernelCrash doesn't crash.
+// TODO(yusukes): Test the behavior beyond just "no crash".
+TEST_F(ArcCrashCollectorBridgeTest, DumpKernelCrash) {
+ ASSERT_NE(nullptr, bridge());
+ bridge()->SetBuildProperties("device", "board", "cpu_abi",
+ absl::optional<std::string>());
+ bridge()->DumpKernelCrash(mojo::ScopedHandle());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/disk_quota/arc_disk_quota_bridge.cc b/chromium/components/arc/disk_quota/arc_disk_quota_bridge.cc
index 61752b7ceee..768f1c4fcf8 100644
--- a/chromium/components/arc/disk_quota/arc_disk_quota_bridge.cc
+++ b/chromium/components/arc/disk_quota/arc_disk_quota_bridge.cc
@@ -8,11 +8,11 @@
#include "base/bind.h"
#include "base/memory/singleton.h"
-#include "base/optional.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/userdataauth/arc_quota_client.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
#include "components/arc/session/arc_bridge_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
@@ -111,7 +111,7 @@ void ArcDiskQuotaBridge::IsQuotaSupported(IsQuotaSupportedCallback callback) {
user_data_auth::GetArcDiskFeaturesRequest(),
base::BindOnce(
[](IsQuotaSupportedCallback callback,
- base::Optional<user_data_auth::GetArcDiskFeaturesReply> reply) {
+ absl::optional<user_data_auth::GetArcDiskFeaturesReply> reply) {
LOG_IF(ERROR, !reply.has_value())
<< "Failed to retrieve result from IsQuotaSupported call.";
bool result = false;
@@ -132,7 +132,7 @@ void ArcDiskQuotaBridge::GetCurrentSpaceForUid(
request,
base::BindOnce(
[](GetCurrentSpaceForUidCallback callback, int uid,
- base::Optional<user_data_auth::GetCurrentSpaceForArcUidReply>
+ absl::optional<user_data_auth::GetCurrentSpaceForArcUidReply>
reply) {
LOG_IF(ERROR, !reply.has_value())
<< "Failed to retrieve result from "
@@ -156,7 +156,7 @@ void ArcDiskQuotaBridge::GetCurrentSpaceForGid(
request,
base::BindOnce(
[](GetCurrentSpaceForGidCallback callback, int gid,
- base::Optional<user_data_auth::GetCurrentSpaceForArcGidReply>
+ absl::optional<user_data_auth::GetCurrentSpaceForArcGidReply>
reply) {
LOG_IF(ERROR, !reply.has_value())
<< "Failed to retrieve result from "
@@ -180,7 +180,7 @@ void ArcDiskQuotaBridge::GetCurrentSpaceForProjectId(
request,
base::BindOnce(
[](GetCurrentSpaceForProjectIdCallback callback, int project_id,
- base::Optional<user_data_auth::GetCurrentSpaceForArcProjectIdReply>
+ absl::optional<user_data_auth::GetCurrentSpaceForArcProjectIdReply>
reply) {
LOG_IF(ERROR, !reply.has_value())
<< "Failed to retrieve result from "
@@ -220,7 +220,7 @@ void ArcDiskQuotaBridge::SetProjectId(uint32_t project_id,
[](SetProjectIdCallback callback, const int project_id,
const user_data_auth::SetProjectIdAllowedPathType parent_path,
const std::string& child_path,
- base::Optional<user_data_auth::SetProjectIdReply> reply) {
+ absl::optional<user_data_auth::SetProjectIdReply> reply) {
LOG_IF(ERROR, !reply.has_value())
<< "Failed to set project ID " << project_id
<< " to parent_path=" << parent_path
diff --git a/chromium/components/arc/enterprise/arc_data_snapshotd_manager.cc b/chromium/components/arc/enterprise/arc_data_snapshotd_manager.cc
index 1015aa142aa..d03424211ab 100644
--- a/chromium/components/arc/enterprise/arc_data_snapshotd_manager.cc
+++ b/chromium/components/arc/enterprise/arc_data_snapshotd_manager.cc
@@ -115,15 +115,15 @@ bool ArcDataSnapshotdManager::is_snapshot_enabled_for_testing_ = false;
// This class is owned by ChromeBrowserMainPartsChromeos.
static ArcDataSnapshotdManager* g_arc_data_snapshotd_manager = nullptr;
-ArcDataSnapshotdManager::SnapshotInfo::SnapshotInfo(bool last)
- : is_last_(last) {
+ArcDataSnapshotdManager::SnapshotInfo::SnapshotInfo(bool is_last)
+ : is_last_(is_last) {
os_version_ = base::SysInfo::OperatingSystemVersion();
UpdateCreationDate(base::Time::Now());
}
ArcDataSnapshotdManager::SnapshotInfo::SnapshotInfo(const base::Value* value,
- bool last)
- : is_last_(last) {
+ bool is_last)
+ : is_last_(is_last) {
const base::DictionaryValue* dict;
if (!value || !value->GetAsDictionary(&dict) || !dict)
return;
@@ -161,9 +161,9 @@ ArcDataSnapshotdManager::SnapshotInfo::CreateForTesting(
const base::Time& creation_date,
bool verified,
bool updated,
- bool last) {
+ bool is_last) {
return base::WrapUnique(new ArcDataSnapshotdManager::SnapshotInfo(
- os_version, creation_date, verified, updated, last));
+ os_version, creation_date, verified, updated, is_last));
}
void ArcDataSnapshotdManager::SnapshotInfo::Sync(base::Value* dict) {
@@ -198,8 +198,8 @@ ArcDataSnapshotdManager::SnapshotInfo::SnapshotInfo(
const base::Time& creation_date,
bool verified,
bool updated,
- bool last)
- : is_last_(last),
+ bool is_last)
+ : is_last_(is_last),
os_version_(os_version),
verified_(verified),
updated_(updated) {
@@ -247,11 +247,11 @@ ArcDataSnapshotdManager::Snapshot::CreateForTesting(
PrefService* local_state,
bool blocked_ui_mode,
bool started,
- std::unique_ptr<SnapshotInfo> last,
- std::unique_ptr<SnapshotInfo> previous) {
+ std::unique_ptr<SnapshotInfo> last_snapshot,
+ std::unique_ptr<SnapshotInfo> previous_snapshot) {
return base::WrapUnique(new ArcDataSnapshotdManager::Snapshot(
- local_state, blocked_ui_mode, started, std::move(last),
- std::move(previous)));
+ local_state, blocked_ui_mode, started, std::move(last_snapshot),
+ std::move(previous_snapshot)));
}
void ArcDataSnapshotdManager::Snapshot::Parse() {
@@ -262,12 +262,12 @@ void ArcDataSnapshotdManager::Snapshot::Parse() {
{
const auto* found = dict->FindDictPath(kPrevious);
if (found)
- previous_ = std::make_unique<SnapshotInfo>(found, false);
+ previous_snapshot_ = std::make_unique<SnapshotInfo>(found, false);
}
{
const auto* found = dict->FindDictPath(kLast);
if (found)
- last_ = std::make_unique<SnapshotInfo>(found, true);
+ last_snapshot_ = std::make_unique<SnapshotInfo>(found, true);
}
{
auto found = dict->FindBoolPath(kBlockedUiReboot);
@@ -283,35 +283,41 @@ void ArcDataSnapshotdManager::Snapshot::Parse() {
void ArcDataSnapshotdManager::Snapshot::Sync() {
base::DictionaryValue dict;
- if (previous_)
- previous_->Sync(&dict);
- if (last_)
- last_->Sync(&dict);
+ if (previous_snapshot_)
+ previous_snapshot_->Sync(&dict);
+ if (last_snapshot_)
+ last_snapshot_->Sync(&dict);
dict.SetBoolKey(kBlockedUiReboot, blocked_ui_mode_);
dict.SetBoolKey(kStarted, started_);
local_state_->Set(arc::prefs::kArcSnapshotInfo, std::move(dict));
}
void ArcDataSnapshotdManager::Snapshot::ClearSnapshot(bool last) {
- std::unique_ptr<SnapshotInfo>* snapshot = (last ? &last_ : &previous_);
+ std::unique_ptr<SnapshotInfo>* snapshot =
+ (last ? &last_snapshot_ : &previous_snapshot_);
snapshot->reset();
Sync();
}
void ArcDataSnapshotdManager::Snapshot::StartNewSnapshot() {
- previous_ = std::move(last_);
- last_ = nullptr;
+ // Make the last snapshot a previous one, because the new (last) snapshot is
+ // going to be taken now.
+ if (last_snapshot_) {
+ previous_snapshot_ = std::move(last_snapshot_);
+ previous_snapshot_->set_is_last(false);
+ last_snapshot_ = nullptr;
+ }
started_ = true;
Sync();
}
void ArcDataSnapshotdManager::Snapshot::OnSnapshotTaken() {
- if (last_) {
+ if (last_snapshot_) {
LOG(WARNING) << "Last snapshot exists";
- last_.reset();
+ last_snapshot_.reset();
}
- last_ = std::make_unique<SnapshotInfo>(true /* last */);
+ last_snapshot_ = std::make_unique<SnapshotInfo>(true /* is_last */);
// Clear snapshot started pref to highlight that the snapshot creation process
// is over.
started_ = false;
@@ -319,24 +325,24 @@ void ArcDataSnapshotdManager::Snapshot::OnSnapshotTaken() {
ArcDataSnapshotdManager::SnapshotInfo*
ArcDataSnapshotdManager::Snapshot::GetCurrentSnapshot() {
- if (last_)
- return last_.get();
+ if (last_snapshot_)
+ return last_snapshot_.get();
- DCHECK(previous_);
- return previous_.get();
+ DCHECK(previous_snapshot_);
+ return previous_snapshot_.get();
}
ArcDataSnapshotdManager::Snapshot::Snapshot(
PrefService* local_state,
bool blocked_ui_mode,
bool started,
- std::unique_ptr<SnapshotInfo> last,
- std::unique_ptr<SnapshotInfo> previous)
+ std::unique_ptr<SnapshotInfo> last_snapshot,
+ std::unique_ptr<SnapshotInfo> previous_snapshot)
: local_state_(local_state),
blocked_ui_mode_(blocked_ui_mode),
started_(started),
- last_(std::move(last)),
- previous_(std::move(previous)) {
+ last_snapshot_(std::move(last_snapshot)),
+ previous_snapshot_(std::move(previous_snapshot)) {
DCHECK(local_state_);
}
@@ -382,7 +388,6 @@ ArcDataSnapshotdManager::~ArcDataSnapshotdManager() {
session_controller_->RemoveObserver(this);
policy_service_.RemoveObserver(this);
- snapshot_.Sync();
EnsureDaemonStopped(base::DoNothing());
}
@@ -426,7 +431,7 @@ void ArcDataSnapshotdManager::StartLoadingSnapshot(base::OnceClosure callback) {
}
std::string account_id = GetMgsCryptohomeAccountId();
if (!account_id.empty() && IsSnapshotEnabled() &&
- (snapshot_.last() || snapshot_.previous())) {
+ (snapshot_.last_snapshot() || snapshot_.previous_snapshot())) {
state_ = State::kLoading;
EnsureDaemonStarted(base::BindOnce(
&ArcDataSnapshotdManager::LoadSnapshot, weak_ptr_factory_.GetWeakPtr(),
@@ -480,15 +485,7 @@ void ArcDataSnapshotdManager::OnSnapshotSessionStarted() {
}
void ArcDataSnapshotdManager::OnSnapshotSessionStopped() {
- if (state_ != State::kRunning)
- NOTREACHED();
- state_ = State::kNone;
-
- snapshot_.GetCurrentSnapshot()->set_verified(true);
- snapshot_.Sync();
-
- session_controller_->RemoveObserver(this);
- session_controller_.reset();
+ NOTREACHED();
}
void ArcDataSnapshotdManager::OnSnapshotSessionFailed() {
@@ -503,11 +500,12 @@ void ArcDataSnapshotdManager::OnSnapshotSessionFailed() {
case State::kRunning:
state_ = State::kNone;
- snapshot_.ClearSnapshot(snapshot_.GetCurrentSnapshot()->is_last());
+ if (snapshot_.GetCurrentSnapshot()->is_verified()) {
+ snapshot_.GetCurrentSnapshot()->set_updated(true);
+ } else {
+ snapshot_.ClearSnapshot(snapshot_.GetCurrentSnapshot()->is_last());
+ }
snapshot_.Sync();
-
- DCHECK(!attempt_user_exit_callback_.is_null());
- EnsureDaemonStopped(std::move(attempt_user_exit_callback_));
break;
case State::kBlockedUi:
case State::kLoading:
@@ -526,20 +524,40 @@ void ArcDataSnapshotdManager::OnSnapshotAppInstalled(int percent) {
}
void ArcDataSnapshotdManager::OnSnapshotSessionPolicyCompliant() {
- if (state_ != State::kMgsLaunched)
- return;
- // Stop tracking apps, since ARC is compliant with policy.
- // That means that 100% of required apps got installed and ARC is fully
- // prepared to be snapshotted.
- // If the policy changes or an app gets uninstalled, the compliance with the
- // required apps list will be fixed automatically on the next session
- // startup.
- session_controller_->RemoveObserver(this);
- session_controller_.reset();
+ switch (state_) {
+ case State::kMgsLaunched:
+ // Stop tracking apps, since ARC is compliant with policy.
+ // That means that 100% of required apps got installed and ARC is fully
+ // prepared to be snapshotted.
+ // If the policy changes or an app gets uninstalled, the compliance with
+ // the required apps list will be fixed automatically on the next session
+ // startup.
+ session_controller_->RemoveObserver(this);
+ session_controller_.reset();
- delegate_->RequestStopArcInstance(
- base::BindOnce(&ArcDataSnapshotdManager::OnArcInstanceStopped,
- weak_ptr_factory_.GetWeakPtr()));
+ delegate_->RequestStopArcInstance(
+ base::BindOnce(&ArcDataSnapshotdManager::OnArcInstanceStopped,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ break;
+ case State::kRunning:
+ state_ = State::kNone;
+
+ snapshot_.GetCurrentSnapshot()->set_verified(true);
+ snapshot_.GetCurrentSnapshot()->set_updated(false);
+ snapshot_.Sync();
+
+ session_controller_->RemoveObserver(this);
+ session_controller_.reset();
+ break;
+ case State::kBlockedUi:
+ case State::kLoading:
+ case State::kMgsToLaunch:
+ case State::kNone:
+ case State::kRestored:
+ case State::kStopping:
+ break;
+ }
}
void ArcDataSnapshotdManager::OnSnapshotsDisabled() {
@@ -588,8 +606,9 @@ void ArcDataSnapshotdManager::OnSnapshotUpdateEndTimeChanged() {
return;
// Do not reboot if last and previous snapshots exist and should not be
// updated.
- if (snapshot_.last() && !snapshot_.last()->updated() &&
- snapshot_.previous() && !snapshot_.previous()->updated()) {
+ if (snapshot_.last_snapshot() && !snapshot_.last_snapshot()->updated() &&
+ snapshot_.previous_snapshot() &&
+ !snapshot_.previous_snapshot()->updated()) {
return;
}
@@ -648,10 +667,10 @@ void ArcDataSnapshotdManager::StopDaemon(base::OnceClosure callback) {
void ArcDataSnapshotdManager::DoClearSnapshots() {
DoClearSnapshot(
- snapshot_.previous(),
+ snapshot_.previous_snapshot(),
base::BindOnce(
&ArcDataSnapshotdManager::DoClearSnapshot,
- weak_ptr_factory_.GetWeakPtr(), snapshot_.last(),
+ weak_ptr_factory_.GetWeakPtr(), snapshot_.last_snapshot(),
base::BindOnce(&ArcDataSnapshotdManager::OnSnapshotsCleared,
weak_ptr_factory_.GetWeakPtr())),
true /* success */);
@@ -896,7 +915,7 @@ void ArcDataSnapshotdManager::OnSnapshotLoaded(base::OnceClosure callback,
<< " snapshot";
state_ = State::kRunning;
// Clear last snapshot if the previous one was loaded.
- if (!last && snapshot_.last()) {
+ if (!last && snapshot_.last_snapshot()) {
snapshot_.ClearSnapshot(true /* last */);
snapshot_.Sync();
}
diff --git a/chromium/components/arc/enterprise/arc_data_snapshotd_manager.h b/chromium/components/arc/enterprise/arc_data_snapshotd_manager.h
index 7981964ae5c..94d3c58c708 100644
--- a/chromium/components/arc/enterprise/arc_data_snapshotd_manager.h
+++ b/chromium/components/arc/enterprise/arc_data_snapshotd_manager.h
@@ -102,8 +102,8 @@ class ArcDataSnapshotdManager final
class SnapshotInfo {
public:
// Creates new snapshot with current parameters.
- explicit SnapshotInfo(bool last);
- SnapshotInfo(const base::Value* value, bool last);
+ explicit SnapshotInfo(bool is_last);
+ SnapshotInfo(const base::Value* value, bool is_last);
SnapshotInfo(const SnapshotInfo&) = delete;
SnapshotInfo& operator=(const SnapshotInfo&) = delete;
~SnapshotInfo();
@@ -115,7 +115,7 @@ class ArcDataSnapshotdManager final
const base::Time& creation_date,
bool verified,
bool updated,
- bool last);
+ bool is_last);
// Syncs stored snapshot info to dictionaty |value|.
void Sync(base::Value* value);
@@ -129,8 +129,10 @@ class ArcDataSnapshotdManager final
void set_verified(bool verified) { verified_ = true; }
bool is_verified() const { return verified_; }
+ void set_is_last(bool is_last) { is_last_ = is_last; }
bool is_last() const { return is_last_; }
+ void set_updated(bool updated) { updated_ = updated; }
bool updated() const { return updated_; }
private:
@@ -138,7 +140,7 @@ class ArcDataSnapshotdManager final
const base::Time& creation_date,
bool verified,
bool updated,
- bool last);
+ bool is_last);
// Returns dictionary path in arc.snapshot local state preference.
std::string GetDictPath() const;
@@ -148,6 +150,7 @@ class ArcDataSnapshotdManager final
// Called once this snapshot is expired.
void OnSnapshotExpired();
+ // True if the instance is the last snapshot taken.
bool is_last_;
// Values should be kept in sync with values stored in arc.snapshot.last or
@@ -183,8 +186,8 @@ class ArcDataSnapshotdManager final
PrefService* local_state,
bool blocked_ui_mode,
bool started,
- std::unique_ptr<SnapshotInfo> last,
- std::unique_ptr<SnapshotInfo> previous);
+ std::unique_ptr<SnapshotInfo> last_snapshot,
+ std::unique_ptr<SnapshotInfo> previous_snapshot);
// Parses the snapshot info from arc.snapshot preference.
void Parse();
@@ -209,15 +212,15 @@ class ArcDataSnapshotdManager final
}
bool is_blocked_ui_mode() const { return blocked_ui_mode_; }
bool started() const { return started_; }
- SnapshotInfo* last() { return last_.get(); }
- SnapshotInfo* previous() { return previous_.get(); }
+ SnapshotInfo* last_snapshot() { return last_snapshot_.get(); }
+ SnapshotInfo* previous_snapshot() { return previous_snapshot_.get(); }
private:
Snapshot(PrefService* local_state,
bool blocked_ui_mode,
bool started,
- std::unique_ptr<SnapshotInfo> last,
- std::unique_ptr<SnapshotInfo> previous);
+ std::unique_ptr<SnapshotInfo> last_snapshot,
+ std::unique_ptr<SnapshotInfo> previous_snapshot);
// Unowned pointer - outlives this instance.
PrefService* const local_state_;
@@ -226,8 +229,8 @@ class ArcDataSnapshotdManager final
// preference.
bool blocked_ui_mode_ = false;
bool started_ = false;
- std::unique_ptr<SnapshotInfo> last_;
- std::unique_ptr<SnapshotInfo> previous_;
+ std::unique_ptr<SnapshotInfo> last_snapshot_;
+ std::unique_ptr<SnapshotInfo> previous_snapshot_;
};
ArcDataSnapshotdManager(PrefService* local_state,
diff --git a/chromium/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc b/chromium/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc
index 7ef8f84fc1c..ef8cbcfb59a 100644
--- a/chromium/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc
+++ b/chromium/components/arc/enterprise/arc_data_snapshotd_manager_unittest.cc
@@ -240,10 +240,12 @@ class ArcDataSnapshotdManagerBasicTest : public testing::Test {
ArcDataSnapshotdManager::Snapshot snapshot(local_state());
snapshot.Parse();
int actual_number = 0;
- if (snapshot.previous()) {
+ if (snapshot.previous_snapshot()) {
+ EXPECT_FALSE(snapshot.previous_snapshot()->is_last());
actual_number++;
}
- if (snapshot.last()) {
+ if (snapshot.last_snapshot()) {
+ EXPECT_TRUE(snapshot.last_snapshot()->is_last());
actual_number++;
}
EXPECT_EQ(expected_snapshots_number, actual_number);
@@ -255,8 +257,8 @@ class ArcDataSnapshotdManagerBasicTest : public testing::Test {
ArcDataSnapshotdManager::Snapshot snapshot(local_state());
snapshot.Parse();
- EXPECT_TRUE(snapshot.last());
- EXPECT_TRUE(snapshot.last()->is_verified());
+ EXPECT_TRUE(snapshot.last_snapshot());
+ EXPECT_TRUE(snapshot.last_snapshot()->is_verified());
}
void ExpectStartTrackingApps() {
@@ -279,15 +281,17 @@ class ArcDataSnapshotdManagerBasicTest : public testing::Test {
// Set up local_state with info for previous and last snapshots and blocked ui
// mode.
void SetupLocalState(bool blocked_ui_mode) {
- auto last = ArcDataSnapshotdManager::SnapshotInfo::CreateForTesting(
- base::SysInfo::OperatingSystemVersion(), base::Time::Now(),
- false /* verified */, false /* updated */, true /* last */);
- auto previous = ArcDataSnapshotdManager::SnapshotInfo::CreateForTesting(
- base::SysInfo::OperatingSystemVersion(), base::Time::Now(),
- false /* verified */, false /* updated */, false /* last */);
+ auto last_snapshot =
+ ArcDataSnapshotdManager::SnapshotInfo::CreateForTesting(
+ base::SysInfo::OperatingSystemVersion(), base::Time::Now(),
+ false /* verified */, false /* updated */, true /* is_last */);
+ auto previous_snapshot =
+ ArcDataSnapshotdManager::SnapshotInfo::CreateForTesting(
+ base::SysInfo::OperatingSystemVersion(), base::Time::Now(),
+ false /* verified */, false /* updated */, false /* is_last */);
auto snapshot = ArcDataSnapshotdManager::Snapshot::CreateForTesting(
- local_state(), blocked_ui_mode, false /* started */, std::move(last),
- std::move(previous));
+ local_state(), blocked_ui_mode, false /* started */,
+ std::move(last_snapshot), std::move(previous_snapshot));
snapshot->Sync();
}
@@ -340,7 +344,7 @@ class ArcDataSnapshotdManagerBasicTest : public testing::Test {
void ClearLocalState() {
auto snapshot = ArcDataSnapshotdManager::Snapshot::CreateForTesting(
local_state(), false /* blocked_ui_mode */, false /* started */,
- nullptr /* last */, nullptr /* previous */);
+ nullptr /* last_snapshot */, nullptr /* previous_snapshot */);
snapshot->Sync();
}
@@ -682,9 +686,7 @@ TEST_F(ArcDataSnapshotdManagerBasicTest, OnSnapshotSessionFailedLoad) {
// Stop daemon, nothing to do.
ExpectStopDaemon(true /* success */);
- base::RunLoop attempt_exit_run_loop;
- auto* manager = CreateManager(base::BindLambdaForTesting(
- [&attempt_exit_run_loop]() { attempt_exit_run_loop.Quit(); }));
+ auto* manager = CreateManager(base::DoNothing());
EXPECT_EQ(manager->state(), ArcDataSnapshotdManager::State::kNone);
CheckSnapshots(2 /* expected_snapshots_number */,
@@ -697,7 +699,6 @@ TEST_F(ArcDataSnapshotdManagerBasicTest, OnSnapshotSessionFailedLoad) {
// MGS failure.
session_controller()->StopSession(false /* success */);
- attempt_exit_run_loop.Run();
// Remove failed snapshot.
EXPECT_EQ(manager->state(), ArcDataSnapshotdManager::State::kNone);
@@ -1065,15 +1066,16 @@ TEST_P(ArcDataSnapshotdManagerFlowTest, LoadSnapshotsBasic) {
run_loop.Run();
if (is_dbus_client_available()) {
EXPECT_EQ(manager->state(), ArcDataSnapshotdManager::State::kRunning);
- // Exit MGS successfully.
- LogoutPublicSession();
- manager->OnSnapshotSessionStopped();
+ manager->OnSnapshotSessionPolicyCompliant();
CheckVerifiedLastSnapshot();
}
EXPECT_EQ(manager->state(), ArcDataSnapshotdManager::State::kNone);
CheckSnapshots(2 /* expected_snapshots_number */,
false /* expected_blocked_ui_mode */);
+
+ // Exit MGS successfully.
+ LogoutPublicSession();
}
// Test escape snapshot generating flow.
diff --git a/chromium/components/arc/enterprise/snapshot_hours_policy_service.cc b/chromium/components/arc/enterprise/snapshot_hours_policy_service.cc
index 12def9f3692..a0f69119051 100644
--- a/chromium/components/arc/enterprise/snapshot_hours_policy_service.cc
+++ b/chromium/components/arc/enterprise/snapshot_hours_policy_service.cc
@@ -128,25 +128,21 @@ void SnapshotHoursPolicyService::EnableSnapshots() {
}
void SnapshotHoursPolicyService::UpdateTimer() {
- auto current_time = policy::WeeklyTime::GetCurrentGmtWeeklyTime(
- base::DefaultClock::GetInstance());
- for (const auto& interval : intervals_) {
- if (interval.Contains(current_time)) {
- auto remaining_timer_duration =
- current_time.GetDurationTo(interval.end());
- SetEndTime(base::Time::Now() + remaining_timer_duration);
- StartTimer(remaining_timer_duration);
- return;
- }
- }
- StartTimer(policy::weekly_time_utils::GetDeltaTillNextTimeInterval(
- current_time, intervals_));
- SetEndTime(base::Time());
+ namespace wtu = ::policy::weekly_time_utils;
+ const base::Time now = base::Time::Now();
+ const bool in_interval = wtu::Contains(now, intervals_);
+ const absl::optional<base::Time> update_time =
+ wtu::GetNextEventTime(now, intervals_);
+
+ SetEndTime(in_interval ? update_time.value() : base::Time{});
+ if (update_time)
+ StartTimer(update_time.value());
+ else
+ StopTimer();
}
-void SnapshotHoursPolicyService::StartTimer(base::TimeDelta delay) {
- DCHECK_GT(delay, base::TimeDelta());
- timer_.Start(FROM_HERE, base::DefaultClock::GetInstance()->Now() + delay,
+void SnapshotHoursPolicyService::StartTimer(const base::Time& update_time) {
+ timer_.Start(FROM_HERE, update_time,
base::BindOnce(&SnapshotHoursPolicyService::UpdateTimer,
weak_ptr_factory_.GetWeakPtr()));
}
diff --git a/chromium/components/arc/enterprise/snapshot_hours_policy_service.h b/chromium/components/arc/enterprise/snapshot_hours_policy_service.h
index 3a8618f86d8..32921b3fd86 100644
--- a/chromium/components/arc/enterprise/snapshot_hours_policy_service.h
+++ b/chromium/components/arc/enterprise/snapshot_hours_policy_service.h
@@ -86,8 +86,8 @@ class SnapshotHoursPolicyService {
// Updates ARC data snapshot update timer according to the policy.
void UpdateTimer();
- // Starts timer with |delay|.
- void StartTimer(base::TimeDelta delay);
+ // Starts timer with |update_time|.
+ void StartTimer(const base::Time& update_time);
// Stops timer.
void StopTimer();
// Changes |snapshot_update_end_time_| and notifies observers if necessary.
diff --git a/chromium/components/arc/enterprise/snapshot_hours_policy_service_unittest.cc b/chromium/components/arc/enterprise/snapshot_hours_policy_service_unittest.cc
index 011c787da5a..e92d1659955 100644
--- a/chromium/components/arc/enterprise/snapshot_hours_policy_service_unittest.cc
+++ b/chromium/components/arc/enterprise/snapshot_hours_policy_service_unittest.cc
@@ -9,7 +9,6 @@
#include "base/callback_helpers.h"
#include "base/json/json_reader.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "base/values.h"
@@ -20,6 +19,7 @@
#include "components/user_manager/scoped_user_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
namespace data_snapshotd {
@@ -183,7 +183,7 @@ class SnapshotHoursPolicyServiceTest
// Enable feature and check.
void EnableSnapshot(int enabled_calls_num = 1) {
- base::Optional<base::Value> policy = base::JSONReader::Read(kJsonPolicy);
+ absl::optional<base::Value> policy = base::JSONReader::Read(kJsonPolicy);
EXPECT_TRUE(policy.has_value());
local_state()->Set(arc::prefs::kArcSnapshotHours, policy.value());
EnsureSnapshotEnabled(enabled_calls_num);
@@ -236,7 +236,7 @@ TEST_F(SnapshotHoursPolicyServiceTest, DoubleDisable) {
EnableSnapshot();
{
- base::Optional<base::Value> policy_value =
+ absl::optional<base::Value> policy_value =
base::JSONReader::Read(kJsonPolicyEmptyIntervals);
EXPECT_TRUE(policy_value.has_value());
local_state()->Set(arc::prefs::kArcSnapshotHours, policy_value.value());
@@ -246,7 +246,7 @@ TEST_F(SnapshotHoursPolicyServiceTest, DoubleDisable) {
{
// User a different JSON to ensure the policy value is updated.
- base::Optional<base::Value> policy_value =
+ absl::optional<base::Value> policy_value =
base::JSONReader::Read(kJsonPolicyNoIntervals);
EXPECT_TRUE(policy_value.has_value());
local_state()->Set(arc::prefs::kArcSnapshotHours, policy_value.value());
@@ -285,7 +285,7 @@ TEST_F(SnapshotHoursPolicyServiceTest, InsideInterval) {
// Disable snapshots.
{
- base::Optional<base::Value> policy_value =
+ absl::optional<base::Value> policy_value =
base::JSONReader::Read(kJsonPolicyNoIntervals);
EXPECT_TRUE(policy_value.has_value());
local_state()->Set(arc::prefs::kArcSnapshotHours, policy_value.value());
@@ -330,7 +330,7 @@ TEST_F(SnapshotHoursPolicyServiceTest, DisableByUserPolicyForMGS) {
TEST_P(SnapshotHoursPolicyServiceTest, DisabledByPolicy) {
EnableSnapshot();
- base::Optional<base::Value> policy_value = base::JSONReader::Read(policy());
+ absl::optional<base::Value> policy_value = base::JSONReader::Read(policy());
EXPECT_TRUE(policy_value.has_value());
local_state()->Set(arc::prefs::kArcSnapshotHours, policy_value.value());
diff --git a/chromium/components/arc/ime/DIR_METADATA b/chromium/components/arc/ime/DIR_METADATA
deleted file mode 100644
index e568bf01ba6..00000000000
--- a/chromium/components/arc/ime/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Platform>Apps>ARC"
-}
diff --git a/chromium/components/arc/ime/arc_ime_service.cc b/chromium/components/arc/ime/arc_ime_service.cc
index bdccd1cc33f..7654d2c343c 100644
--- a/chromium/components/arc/ime/arc_ime_service.cc
+++ b/chromium/components/arc/ime/arc_ime_service.cc
@@ -43,7 +43,7 @@ namespace arc {
namespace {
-base::Optional<double> g_override_default_device_scale_factor;
+absl::optional<double> g_override_default_device_scale_factor;
// Return true when a rich text editing is available on a text field with the
// given type.
@@ -393,13 +393,16 @@ void ArcImeService::OnCursorRectChangedWithSurroundingText(
if (!ShouldSendUpdateToInputMethod())
return;
+ if (!UpdateCursorRect(rect, is_screen_coordinates) &&
+ text_range_ == text_range && text_in_range_ == text_in_range &&
+ selection_range_ == selection_range) {
+ return;
+ }
+
text_range_ = text_range;
text_in_range_ = text_in_range;
selection_range_ = selection_range;
- if (!UpdateCursorRect(rect, is_screen_coordinates))
- return;
-
ui::InputMethod* const input_method = GetInputMethod();
if (input_method)
input_method->OnCaretBoundsChanged(this);
@@ -512,6 +515,11 @@ gfx::Rect ArcImeService::GetCaretBounds() const {
return cursor_rect_;
}
+gfx::Rect ArcImeService::GetSelectionBoundingBox() const {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return gfx::Rect();
+}
+
bool ArcImeService::GetTextRange(gfx::Range* range) const {
if (!text_range_.IsValid())
return false;
@@ -544,7 +552,7 @@ void ArcImeService::EnsureCaretNotInRect(const gfx::Rect& rect_in_screen) {
aura::Window* top_level_window = focused_arc_window_->GetToplevelWindow();
// If the window is not a notification, the window move is handled by
// Android.
- if (top_level_window->type() != aura::client::WINDOW_TYPE_POPUP)
+ if (top_level_window->GetType() != aura::client::WINDOW_TYPE_POPUP)
return;
wm::EnsureWindowNotInRect(top_level_window, rect_in_screen);
}
@@ -623,7 +631,7 @@ bool ArcImeService::ShouldDoLearning() {
bool ArcImeService::SetCompositionFromExistingText(
const gfx::Range& range,
const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
- if (!range.IsBoundedBy(text_range_))
+ if (text_range_.IsValid() && !range.IsBoundedBy(text_range_))
return false;
InvalidateSurroundingTextAndSelectionRange();
@@ -637,7 +645,7 @@ bool ArcImeService::SetCompositionFromExistingText(
}
gfx::Range ArcImeService::GetAutocorrectRange() const {
- // TODO(https:://crbug.com/1091088): Implement this method.
+ // TODO(https://crbug.com/1091088): Implement this method.
return gfx::Range();
}
@@ -664,7 +672,27 @@ bool ArcImeService::SetAutocorrectRange(const gfx::Range& range) {
TextInputClient::SubClass::kArcImeService);
}
}
- // TODO(https:://crbug.com/1091088): Implement this method.
+ // TODO(https://crbug.com/1091088): Implement this method.
+ NOTIMPLEMENTED_LOG_ONCE();
+ return false;
+}
+
+absl::optional<ui::GrammarFragment> ArcImeService::GetGrammarFragment(
+ const gfx::Range& range) {
+ // TODO(https://crbug.com/1201454): Implement this method.
+ NOTIMPLEMENTED_LOG_ONCE();
+ return absl::nullopt;
+}
+
+bool ArcImeService::ClearGrammarFragments(const gfx::Range& range) {
+ // TODO(https://crbug.com/1201454): Implement this method.
+ NOTIMPLEMENTED_LOG_ONCE();
+ return false;
+}
+
+bool ArcImeService::AddGrammarFragments(
+ const std::vector<ui::GrammarFragment>& fragments) {
+ // TODO(https://crbug.com/1201454): Implement this method.
NOTIMPLEMENTED_LOG_ONCE();
return false;
}
@@ -701,7 +729,7 @@ void ArcImeService::OnDispatchingKeyEventPostIME(ui::KeyEvent* event) {
// static
void ArcImeService::SetOverrideDefaultDeviceScaleFactorForTesting(
- base::Optional<double> scale_factor) {
+ absl::optional<double> scale_factor) {
g_override_default_device_scale_factor = scale_factor;
}
diff --git a/chromium/components/arc/ime/arc_ime_service.h b/chromium/components/arc/ime/arc_ime_service.h
index d80dc27a847..acaee65d237 100644
--- a/chromium/components/arc/ime/arc_ime_service.h
+++ b/chromium/components/arc/ime/arc_ime_service.h
@@ -9,10 +9,10 @@
#include "ash/public/cpp/keyboard/keyboard_controller_observer.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/arc/ime/arc_ime_bridge.h"
#include "components/arc/ime/key_event_result_receiver.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/client/focus_change_observer.h"
#include "ui/aura/env_observer.h"
#include "ui/aura/window_observer.h"
@@ -119,6 +119,7 @@ class ArcImeService : public KeyedService,
void InsertChar(const ui::KeyEvent& event) override;
ui::TextInputType GetTextInputType() const override;
gfx::Rect GetCaretBounds() const override;
+ gfx::Rect GetSelectionBoundingBox() const override;
bool GetTextRange(gfx::Range* range) const override;
bool GetEditableSelectionRange(gfx::Range* range) const override;
bool GetTextFromRange(const gfx::Range& range,
@@ -154,12 +155,17 @@ class ArcImeService : public KeyedService,
gfx::Range GetAutocorrectRange() const override;
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const gfx::Range& range) override;
+ absl::optional<ui::GrammarFragment> GetGrammarFragment(
+ const gfx::Range& range) override;
+ bool ClearGrammarFragments(const gfx::Range& range) override;
+ bool AddGrammarFragments(
+ const std::vector<ui::GrammarFragment>& fragments) override;
void OnDispatchingKeyEventPostIME(ui::KeyEvent* event) override;
// Normally, the default device scale factor is used to convert from DPI to
// physical pixels. This method provides a way to override it for testing.
static void SetOverrideDefaultDeviceScaleFactorForTesting(
- base::Optional<double> scale_factor);
+ absl::optional<double> scale_factor);
private:
friend class ArcImeServiceTest;
diff --git a/chromium/components/arc/ime/arc_ime_service_unittest.cc b/chromium/components/arc/ime/arc_ime_service_unittest.cc
index 6c0f660e7f8..45fba6bdca7 100644
--- a/chromium/components/arc/ime/arc_ime_service_unittest.cc
+++ b/chromium/components/arc/ime/arc_ime_service_unittest.cc
@@ -166,7 +166,7 @@ class FakeArcWindowDelegate : public ArcImeService::ArcWindowDelegate {
bool IsInArcAppWindow(const aura::Window* window) const override {
if (!window)
return false;
- return arc_window_id_.count(window->id());
+ return arc_window_id_.count(window->GetId());
}
void RegisterFocusObserver() override {}
@@ -240,7 +240,7 @@ class ArcImeServiceTest : public testing::Test {
}
void TearDown() override {
- ArcImeService::SetOverrideDefaultDeviceScaleFactorForTesting(base::nullopt);
+ ArcImeService::SetOverrideDefaultDeviceScaleFactorForTesting(absl::nullopt);
arc_win_.reset();
fake_window_delegate_ = nullptr;
fake_arc_ime_bridge_ = nullptr;
@@ -553,6 +553,19 @@ TEST_F(ArcImeServiceTest, SetComposingRegion) {
EXPECT_EQ(composing_range, fake_arc_ime_bridge_->composing_range());
}
+TEST_F(ArcImeServiceTest, ExtendSelectionAndDeleteThenSetComposingRegion) {
+ instance_->OnWindowFocused(arc_win_.get(), nullptr);
+ instance_->OnCursorRectChangedWithSurroundingText(
+ gfx::Rect(), gfx::Range(0, 100), std::u16string(100, 'a'),
+ gfx::Range(100, 100), false);
+
+ instance_->ExtendSelectionAndDelete(1, 0);
+ const gfx::Range composing_range(0, 99);
+ instance_->SetCompositionFromExistingText(composing_range, {});
+
+ EXPECT_EQ(composing_range, fake_arc_ime_bridge_->composing_range());
+}
+
TEST_F(ArcImeServiceTest, OnDispatchingKeyEventPostIME) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
@@ -625,7 +638,7 @@ TEST_F(ArcImeServiceTest, SendKeyEvent) {
ui::DomKey::FromCharacter('A'),
ui::EventTimeForNow()};
{
- base::Optional<bool> handled;
+ absl::optional<bool> handled;
auto copy = std::make_unique<ui::KeyEvent>(event);
instance_->SendKeyEvent(
std::move(copy),
@@ -645,7 +658,7 @@ TEST_F(ArcImeServiceTest, SendKeyEvent) {
ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::DomCode::ENTER, 0,
ui::DomKey::UNIDENTIFIED, ui::EventTimeForNow()};
{
- base::Optional<bool> handled;
+ absl::optional<bool> handled;
auto copy = std::make_unique<ui::KeyEvent>(non_character_event);
instance_->SendKeyEvent(
std::move(copy),
@@ -668,7 +681,7 @@ TEST_F(ArcImeServiceTest, SendKeyEvent) {
ui::DomKey::FromCharacter('A'),
ui::EventTimeForNow()};
{
- base::Optional<bool> handled;
+ absl::optional<bool> handled;
auto copy = std::make_unique<ui::KeyEvent>(fabricated_event);
instance_->SendKeyEvent(
std::move(copy),
diff --git a/chromium/components/arc/ime/key_event_result_receiver.cc b/chromium/components/arc/ime/key_event_result_receiver.cc
index 74b21f3e895..1a6cd2af900 100644
--- a/chromium/components/arc/ime/key_event_result_receiver.cc
+++ b/chromium/components/arc/ime/key_event_result_receiver.cc
@@ -7,10 +7,11 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
-#include "base/optional.h"
+#include "base/metrics/histogram_functions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/arc/ime/arc_ime_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
#include "ui/events/event_dispatcher.h"
@@ -23,6 +24,12 @@ namespace {
// value after collecting the latency metrics.
constexpr base::TimeDelta kKeyEventDoneCallbackTimeout =
base::TimeDelta::FromMilliseconds(300);
+constexpr base::TimeDelta kKeyEventLatencyMin =
+ base::TimeDelta::FromMilliseconds(1);
+constexpr base::TimeDelta kKeyEventLatencyMax =
+ base::TimeDelta::FromMilliseconds(350);
+
+constexpr char kImeLatencyHistogramName[] = "Arc.ChromeOsImeLatency";
} // namespace
@@ -70,6 +77,7 @@ void KeyEventResultReceiver::SetCallback(KeyEventDoneCallback callback) {
// Cancel the obsolete callback if exist.
RunCallbackIfNeeded(false);
callback_ = std::move(callback);
+ callback_set_time_ = base::TimeTicks::Now();
// Start expiring timer for the callback.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
@@ -90,9 +98,18 @@ void KeyEventResultReceiver::ExpireCallback() {
void KeyEventResultReceiver::RunCallbackIfNeeded(bool result) {
if (callback_) {
weak_ptr_factory_.InvalidateWeakPtrs();
+ RecordImeLatency();
std::move(callback_).Run(result);
callback_.Reset();
}
}
+void KeyEventResultReceiver::RecordImeLatency() {
+ base::UmaHistogramCustomTimes(
+ kImeLatencyHistogramName,
+ base::TimeTicks::Now() - callback_set_time_.value(), kKeyEventLatencyMin,
+ kKeyEventLatencyMax, 50);
+ callback_set_time_ = absl::nullopt;
+}
+
} // namespace arc
diff --git a/chromium/components/arc/ime/key_event_result_receiver.h b/chromium/components/arc/ime/key_event_result_receiver.h
index 926024f270d..f92b5d254f6 100644
--- a/chromium/components/arc/ime/key_event_result_receiver.h
+++ b/chromium/components/arc/ime/key_event_result_receiver.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/ime/input_method_delegate.h"
namespace arc {
@@ -32,7 +33,10 @@ class KeyEventResultReceiver {
void RunCallbackIfNeeded(bool result);
+ void RecordImeLatency();
+
KeyEventDoneCallback callback_{};
+ absl::optional<base::TimeTicks> callback_set_time_{};
base::WeakPtrFactory<KeyEventResultReceiver> weak_ptr_factory_{this};
};
diff --git a/chromium/components/arc/ime/key_event_result_receiver_unittest.cc b/chromium/components/arc/ime/key_event_result_receiver_unittest.cc
index 0329866e697..d51aed2a0c9 100644
--- a/chromium/components/arc/ime/key_event_result_receiver_unittest.cc
+++ b/chromium/components/arc/ime/key_event_result_receiver_unittest.cc
@@ -4,7 +4,9 @@
#include "components/arc/ime/key_event_result_receiver.h"
+#include "base/callback_helpers.h"
#include "base/test/bind.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/base_event_utils.h"
@@ -36,7 +38,7 @@ class KeyEventResultReceiverTest : public testing::Test {
};
TEST_F(KeyEventResultReceiverTest, ExpireCallback) {
- base::Optional<bool> result;
+ absl::optional<bool> result;
auto callback =
base::BindLambdaForTesting([&result](bool res) { result = res; });
@@ -50,7 +52,7 @@ TEST_F(KeyEventResultReceiverTest, ExpireCallback) {
}
TEST_F(KeyEventResultReceiverTest, EventStoppedPropagation) {
- base::Optional<bool> result;
+ absl::optional<bool> result;
auto callback =
base::BindLambdaForTesting([&result](bool res) { result = res; });
@@ -66,7 +68,7 @@ TEST_F(KeyEventResultReceiverTest, EventStoppedPropagation) {
}
TEST_F(KeyEventResultReceiverTest, EventConsumedByIME) {
- base::Optional<bool> result;
+ absl::optional<bool> result;
auto callback =
base::BindLambdaForTesting([&result](bool res) { result = res; });
@@ -83,7 +85,7 @@ TEST_F(KeyEventResultReceiverTest, EventConsumedByIME) {
}
TEST_F(KeyEventResultReceiverTest, EventNotCharacter) {
- base::Optional<bool> result;
+ absl::optional<bool> result;
auto callback =
base::BindLambdaForTesting([&result](bool res) { result = res; });
@@ -101,7 +103,7 @@ TEST_F(KeyEventResultReceiverTest, EventNotCharacter) {
}
TEST_F(KeyEventResultReceiverTest, UnmodifiedEnterAndBackspace) {
- base::Optional<bool> result;
+ absl::optional<bool> result;
auto callback =
base::BindLambdaForTesting([&result](bool res) { result = res; });
@@ -133,7 +135,7 @@ TEST_F(KeyEventResultReceiverTest, UnmodifiedEnterAndBackspace) {
}
TEST_F(KeyEventResultReceiverTest, ControlCharacters) {
- base::Optional<bool> result;
+ absl::optional<bool> result;
auto callback =
base::BindLambdaForTesting([&result](bool res) { result = res; });
@@ -149,7 +151,7 @@ TEST_F(KeyEventResultReceiverTest, ControlCharacters) {
}
TEST_F(KeyEventResultReceiverTest, EventWithSystemModifier) {
- base::Optional<bool> result;
+ absl::optional<bool> result;
auto callback =
base::BindLambdaForTesting([&result](bool res) { result = res; });
@@ -165,7 +167,7 @@ TEST_F(KeyEventResultReceiverTest, EventWithSystemModifier) {
}
TEST_F(KeyEventResultReceiverTest, NormalCharacters) {
- base::Optional<bool> result;
+ absl::optional<bool> result;
auto callback =
base::BindLambdaForTesting([&result](bool res) { result = res; });
@@ -180,4 +182,26 @@ TEST_F(KeyEventResultReceiverTest, NormalCharacters) {
EXPECT_TRUE(result.value());
}
+TEST_F(KeyEventResultReceiverTest, Histrogram) {
+ base::HistogramTester histogram_tester;
+ constexpr char kHistogramName[] = "Arc.ChromeOsImeLatency";
+ auto delay = base::TimeDelta::FromMilliseconds(100);
+
+ receiver()->SetCallback(base::DoNothing());
+
+ ForwardBy(delay);
+
+ ui::KeyEvent event{'a', ui::VKEY_A, ui::DomCode::NONE, ui::EF_NONE};
+ receiver()->DispatchKeyEventPostIME(&event);
+
+ histogram_tester.ExpectTotalCount(kHistogramName, 1);
+ histogram_tester.ExpectUniqueTimeSample(kHistogramName, delay, 1);
+
+ receiver()->SetCallback(base::DoNothing());
+
+ ForwardBy(base::TimeDelta::FromSeconds(1));
+
+ histogram_tester.ExpectTotalCount(kHistogramName, 2);
+}
+
} // namespace arc
diff --git a/chromium/components/arc/intent_helper/activity_icon_loader_unittest.cc b/chromium/components/arc/intent_helper/activity_icon_loader_unittest.cc
index 2fba9214e85..9edb4019630 100644
--- a/chromium/components/arc/intent_helper/activity_icon_loader_unittest.cc
+++ b/chromium/components/arc/intent_helper/activity_icon_loader_unittest.cc
@@ -172,7 +172,8 @@ TEST(ActivityIconLoaderTest, TestOnIconsResized) {
// Call OnIconsResized() again to make sure that the second call does not
// remove the cache the previous call added.
- activity_to_icons.reset(new ActivityIconLoader::ActivityToIconsMap);
+ activity_to_icons =
+ std::make_unique<ActivityIconLoader::ActivityToIconsMap>();
// Duplicated entry.
activity_to_icons->insert(std::make_pair(
ActivityIconLoader::ActivityName("p1", "a1"),
diff --git a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc
index 00521b93d56..579e28a6054 100644
--- a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc
+++ b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -14,7 +14,6 @@
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/values.h"
@@ -25,6 +24,7 @@
#include "components/arc/intent_helper/open_url_delegate.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/url_formatter/url_fixer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/layout.h"
#include "url/url_constants.h"
@@ -91,7 +91,13 @@ ArcIntentHelperBridge* ArcIntentHelperBridge::GetForBrowserContext(
}
// static
-KeyedServiceBaseFactory* ArcIntentHelperBridge::GetFactory() {
+ArcIntentHelperBridge* ArcIntentHelperBridge::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcIntentHelperBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
+// static
+BrowserContextKeyedServiceFactory* ArcIntentHelperBridge::GetFactory() {
return ArcIntentHelperBridgeFactory::GetInstance();
}
@@ -143,7 +149,7 @@ void ArcIntentHelperBridge::OnIntentFiltersUpdated(
intent_filters_[filter.package_name()].push_back(std::move(filter));
for (auto& observer : observer_list_)
- observer.OnIntentFiltersUpdated(base::nullopt);
+ observer.OnIntentFiltersUpdated(absl::nullopt);
}
void ArcIntentHelperBridge::OnOpenDownloads() {
@@ -303,6 +309,24 @@ void ArcIntentHelperBridge::OnPreferredAppsChanged(
observer.OnPreferredAppsChanged();
}
+void ArcIntentHelperBridge::OnDownloadAdded(
+ const std::string& relative_path_as_string,
+ const std::string& owner_package_name) {
+ const base::FilePath download_folder("Download/");
+ const base::FilePath relative_path(relative_path_as_string);
+
+ // Observers should *not* be called when a download is added outside of the
+ // Download/ folder. This would be an unexpected event coming from ARC but
+ // we protect against it because ARC is treated as an untrusted source.
+ if (!download_folder.IsParent(relative_path) ||
+ relative_path.ReferencesParent()) {
+ return;
+ }
+
+ for (auto& observer : observer_list_)
+ observer.OnArcDownloadAdded(relative_path, owner_package_name);
+}
+
ArcIntentHelperBridge::GetResult ArcIntentHelperBridge::GetActivityIcons(
const std::vector<ActivityName>& activities,
OnIconsReadyCallback callback) {
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 c4c865e5996..4f64c34db0a 100644
--- a/chromium/components/arc/intent_helper/arc_intent_helper_bridge.h
+++ b/chromium/components/arc/intent_helper/arc_intent_helper_bridge.h
@@ -21,7 +21,7 @@
#include "components/keyed_service/core/keyed_service.h"
#include "url/gurl.h"
-class KeyedServiceBaseFactory;
+class BrowserContextKeyedServiceFactory;
namespace content {
class BrowserContext;
@@ -51,9 +51,11 @@ class ArcIntentHelperBridge : public KeyedService,
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcIntentHelperBridge* GetForBrowserContext(
content::BrowserContext* context);
+ static ArcIntentHelperBridge* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
// Returns factory for the ArcIntentHelperBridge.
- static KeyedServiceBaseFactory* GetFactory();
+ static BrowserContextKeyedServiceFactory* GetFactory();
// Appends '.' + |to_append| to the intent helper package name.
static std::string AppendStringToIntentHelperPackageName(
@@ -107,6 +109,8 @@ class ArcIntentHelperBridge : public KeyedService,
IsChromeAppEnabledCallback callback) override;
void OnPreferredAppsChanged(std::vector<IntentFilter> added,
std::vector<IntentFilter> deleted) override;
+ void OnDownloadAdded(const std::string& relative_path,
+ const std::string& owner_package_name) override;
// Retrieves icons for the |activities| and calls |callback|.
// See ActivityIconLoader::GetActivityIcons() for more details.
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 4f395318048..2a3f6f57013 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
@@ -5,14 +5,17 @@
#include "components/arc/intent_helper/arc_intent_helper_bridge.h"
#include <memory>
+#include <string>
#include <utility>
+#include <vector>
#include "base/memory/ptr_util.h"
-#include "base/optional.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/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
@@ -177,32 +180,64 @@ TEST_F(ArcIntentHelperTest, TestFilterOutIntentHelper) {
// Tests if observer works as expected.
TEST_F(ArcIntentHelperTest, TestObserver) {
- class FakeObserver : public ArcIntentHelperObserver {
+ class MockObserver : public ArcIntentHelperObserver {
public:
- FakeObserver() = default;
- void OnIntentFiltersUpdated(
- const base::Optional<std::string>& package_name) override {
- updated_ = true;
- }
- bool IsUpdated() { return updated_; }
- void Reset() { updated_ = false; }
-
- private:
- bool updated_ = false;
+ MOCK_METHOD(void,
+ OnArcDownloadAdded,
+ (const base::FilePath& relative_path,
+ const std::string& owner_package_name),
+ (override));
+ MOCK_METHOD(void,
+ OnIntentFiltersUpdated,
+ (const absl::optional<std::string>& package_name),
+ (override));
+ MOCK_METHOD(void, OnPreferredAppsChanged, (), (override));
};
- // Observer should be called when intent filter is updated.
- auto observer = std::make_unique<FakeObserver>();
- instance_->AddObserver(observer.get());
- EXPECT_FALSE(observer->IsUpdated());
- instance_->OnIntentFiltersUpdated(std::vector<IntentFilter>());
- EXPECT_TRUE(observer->IsUpdated());
+ // Create and add observer.
+ testing::StrictMock<MockObserver> observer;
+ instance_->AddObserver(&observer);
+
+ {
+ // Observer should be called when a download is added.
+ std::string relative_path("Download/foo/bar.pdf");
+ std::string owner_package_name("owner_package_name");
+ EXPECT_CALL(observer,
+ OnArcDownloadAdded(testing::Eq(base::FilePath(relative_path)),
+ testing::Ref(owner_package_name)));
+ instance_->OnDownloadAdded(relative_path, owner_package_name);
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ }
+
+ {
+ // Observer should *not* be called when a download is added outside of the
+ // Download/ folder. This would be an unexpected event coming from ARC but
+ // we protect against it because ARC is treated as an untrusted source.
+ instance_->OnDownloadAdded(/*relative_path=*/"Download/../foo/bar.pdf",
+ /*owner_package_name=*/"owner_package_name");
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ }
+
+ {
+ // Observer should be called when an intent filter is updated.
+ EXPECT_CALL(observer, OnIntentFiltersUpdated(testing::Eq(absl::nullopt)));
+ instance_->OnIntentFiltersUpdated(/*filters=*/std::vector<IntentFilter>());
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ }
+
+ {
+ // Observer should be called when preferred apps change.
+ EXPECT_CALL(observer, OnPreferredAppsChanged);
+ instance_->OnPreferredAppsChanged(/*added=*/{}, /*deleted=*/{});
+ testing::Mock::VerifyAndClearExpectations(&observer);
+ }
// Observer should not be called after it's removed.
- observer->Reset();
- instance_->RemoveObserver(observer.get());
- instance_->OnIntentFiltersUpdated(std::vector<IntentFilter>());
- EXPECT_FALSE(observer->IsUpdated());
+ instance_->RemoveObserver(&observer);
+ instance_->OnDownloadAdded(/*relative_path=*/"Download/foo/bar.pdf",
+ /*owner_package_name=*/"owner_package_name");
+ instance_->OnIntentFiltersUpdated(/*filters=*/{});
+ instance_->OnPreferredAppsChanged(/*added=*/{}, /*removed=*/{});
}
// Tests that ShouldChromeHandleUrl returns true by default.
diff --git a/chromium/components/arc/intent_helper/arc_intent_helper_observer.h b/chromium/components/arc/intent_helper/arc_intent_helper_observer.h
index 9f3a71852dd..7847f42e101 100644
--- a/chromium/components/arc/intent_helper/arc_intent_helper_observer.h
+++ b/chromium/components/arc/intent_helper/arc_intent_helper_observer.h
@@ -7,19 +7,31 @@
#include <string>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace base {
+class FilePath;
+} // namespace base
namespace arc {
class ArcIntentHelperObserver {
public:
virtual ~ArcIntentHelperObserver() = default;
+ // Called when a new entry has been added to the MediaStore.Downloads
+ // collection of downloaded items in ARC with the specified metadata.
+ // |relative_path| relative path of the download within the Download/
+ // folder (e.g. "Download/foo/bar.pdf").
+ // |owner_package_name| package name that contributed the download (e.g.
+ // "com.bar.foo").
+ virtual void OnArcDownloadAdded(const base::FilePath& relative_path,
+ const std::string& owner_package_name) {}
// Called when intent filters are added, removed or updated.
- // A base::nullopt |package_name| indicates that intent filters were updated
+ // A absl::nullopt |package_name| indicates that intent filters were updated
// for all packages. Otherwise, |package_name| contains the name of the
// package whose filters were changed.
virtual void OnIntentFiltersUpdated(
- const base::Optional<std::string>& package_name) = 0;
+ const absl::optional<std::string>& package_name) {}
// Called when the preferred apps changed in ARC.
virtual void OnPreferredAppsChanged() {}
};
diff --git a/chromium/components/arc/intent_helper/custom_tab_unittest.cc b/chromium/components/arc/intent_helper/custom_tab_unittest.cc
index f7c0786a869..16f3b15bd29 100644
--- a/chromium/components/arc/intent_helper/custom_tab_unittest.cc
+++ b/chromium/components/arc/intent_helper/custom_tab_unittest.cc
@@ -23,7 +23,7 @@ TEST_F(CustomTabTest, ResizeAfterClose) {
{
views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
+ params.activatable = views::Widget::InitParams::Activatable::kYes;
params.bounds = gfx::Rect(0, 0, 200, 200);
params.parent = root_window();
toplevel_widget.Init(std::move(params));
diff --git a/chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc b/chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc
index 78b82c5d943..69684b64f58 100644
--- a/chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc
+++ b/chromium/components/arc/intent_helper/intent_filter_mojom_traits.cc
@@ -8,8 +8,8 @@
#include <utility>
#include <vector>
-#include "base/optional.h"
#include "base/strings/string_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace mojo {
@@ -24,7 +24,7 @@ bool StructTraits<arc::mojom::IntentFilterDataView, arc::IntentFilter>::Read(
if (!data.ReadDataPaths(&paths))
return false;
- base::Optional<std::string> package_name;
+ absl::optional<std::string> package_name;
if (!data.ReadPackageName(&package_name))
return false;
@@ -40,11 +40,11 @@ bool StructTraits<arc::mojom::IntentFilterDataView, arc::IntentFilter>::Read(
if (!data.ReadMimeTypes(&mime_types))
return false;
- base::Optional<std::string> activity_name;
+ absl::optional<std::string> activity_name;
if (!data.ReadActivityName(&activity_name))
return false;
- base::Optional<std::string> activity_label;
+ absl::optional<std::string> activity_label;
if (!data.ReadActivityLabel(&activity_label))
return false;
diff --git a/chromium/components/arc/intent_helper/link_handler_model.cc b/chromium/components/arc/intent_helper/link_handler_model.cc
index acc0e29222a..ab6a558ca5e 100644
--- a/chromium/components/arc/intent_helper/link_handler_model.cc
+++ b/chromium/components/arc/intent_helper/link_handler_model.cc
@@ -13,6 +13,7 @@
#include "components/arc/arc_service_manager.h"
#include "components/arc/intent_helper/arc_intent_helper_bridge.h"
#include "components/arc/metrics/arc_metrics_constants.h"
+#include "components/arc/metrics/arc_metrics_service.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/google/core/common/google_util.h"
#include "url/url_util.h"
@@ -79,9 +80,8 @@ void LinkHandlerModel::OpenLinkWithHandler(uint32_t handler_id) {
return;
instance->HandleUrl(url_.spec(), handlers_[handler_id]->package_name);
- UMA_HISTOGRAM_ENUMERATION(
- "Arc.UserInteraction",
- arc::UserInteractionType::APP_STARTED_FROM_LINK_CONTEXT_MENU);
+ ArcMetricsService::RecordArcUserInteraction(
+ context_, arc::UserInteractionType::APP_STARTED_FROM_LINK_CONTEXT_MENU);
}
LinkHandlerModel::LinkHandlerModel() = default;
diff --git a/chromium/components/arc/lock_screen/arc_lock_screen_bridge.cc b/chromium/components/arc/lock_screen/arc_lock_screen_bridge.cc
index 41b6db2992d..2bdbe64f712 100644
--- a/chromium/components/arc/lock_screen/arc_lock_screen_bridge.cc
+++ b/chromium/components/arc/lock_screen/arc_lock_screen_bridge.cc
@@ -44,6 +44,12 @@ ArcLockScreenBridge* ArcLockScreenBridge::GetForBrowserContext(
return ArcLockScreenBridgeFactory::GetForBrowserContext(context);
}
+// static
+ArcLockScreenBridge* ArcLockScreenBridge::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcLockScreenBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
ArcLockScreenBridge::ArcLockScreenBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service) {
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 9d1c7757412..b105a2b51f9 100644
--- a/chromium/components/arc/lock_screen/arc_lock_screen_bridge.h
+++ b/chromium/components/arc/lock_screen/arc_lock_screen_bridge.h
@@ -30,6 +30,8 @@ class ArcLockScreenBridge
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcLockScreenBridge* GetForBrowserContext(
content::BrowserContext* context);
+ static ArcLockScreenBridge* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
ArcLockScreenBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service);
diff --git a/chromium/components/arc/lock_screen/arc_lock_screen_bridge_unittest.cc b/chromium/components/arc/lock_screen/arc_lock_screen_bridge_unittest.cc
new file mode 100644
index 00000000000..948f79b150c
--- /dev/null
+++ b/chromium/components/arc/lock_screen/arc_lock_screen_bridge_unittest.cc
@@ -0,0 +1,80 @@
+// Copyright 2021 The Chromium Authors. 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/lock_screen/arc_lock_screen_bridge.h"
+
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/session/arc_bridge_service.h"
+#include "components/arc/test/connection_holder_util.h"
+#include "components/arc/test/fake_lock_screen_instance.h"
+#include "components/arc/test/test_browser_context.h"
+#include "components/session_manager/core/session_manager.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcLockScreenBridgeTest : public testing::Test {
+ protected:
+ ArcLockScreenBridgeTest() = default;
+ ArcLockScreenBridgeTest(const ArcLockScreenBridgeTest&) = delete;
+ ArcLockScreenBridgeTest& operator=(const ArcLockScreenBridgeTest&) = delete;
+ ~ArcLockScreenBridgeTest() override = default;
+
+ void SetUp() override {
+ // Set the state to "logged in" before testing.
+ session_manager_.SetSessionState(session_manager::SessionState::ACTIVE);
+
+ bridge_ = ArcLockScreenBridge::GetForBrowserContextForTesting(&context_);
+ // This results in ArcLockScreenBridge::OnInstanceReady being called.
+ ArcServiceManager::Get()->arc_bridge_service()->lock_screen()->SetInstance(
+ &lock_screen_instance_);
+ WaitForInstanceReady(
+ ArcServiceManager::Get()->arc_bridge_service()->lock_screen());
+ }
+
+ ArcLockScreenBridge* bridge() { return bridge_; }
+ session_manager::SessionManager* session_manager() {
+ return &session_manager_;
+ }
+ FakeLockScreenInstance* lock_screen_instance() {
+ return &lock_screen_instance_;
+ }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ session_manager::SessionManager session_manager_;
+ ArcServiceManager arc_service_manager_;
+ FakeLockScreenInstance lock_screen_instance_;
+ TestBrowserContext context_;
+ ArcLockScreenBridge* bridge_ = nullptr;
+};
+
+TEST_F(ArcLockScreenBridgeTest, ConstructDestruct) {
+ EXPECT_NE(nullptr, bridge());
+}
+
+TEST_F(ArcLockScreenBridgeTest, OnConnectionReady) {
+ const absl::optional<bool>& is_locked = lock_screen_instance()->is_locked();
+ // The state should have been set already. See SetUp().
+ ASSERT_TRUE(is_locked);
+ // And the state should be "not locked";
+ EXPECT_FALSE(*is_locked);
+}
+
+TEST_F(ArcLockScreenBridgeTest, OnSessionStateChanged) {
+ const absl::optional<bool>& is_locked = lock_screen_instance()->is_locked();
+ // The state should have been set already. See SetUp().
+ ASSERT_TRUE(is_locked);
+ // Lock the screen and check the instance state.
+ session_manager()->SetSessionState(session_manager::SessionState::LOCKED);
+ EXPECT_TRUE(*is_locked);
+ // Unlock it and do the same.
+ session_manager()->SetSessionState(session_manager::SessionState::ACTIVE);
+ EXPECT_FALSE(*is_locked);
+}
+
+} // namespace
+} // namespace arc
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 a41fffe9066..6d1d043512f 100644
--- a/chromium/components/arc/media_session/arc_media_session_bridge.cc
+++ b/chromium/components/arc/media_session/arc_media_session_bridge.cc
@@ -54,6 +54,12 @@ ArcMediaSessionBridge* ArcMediaSessionBridge::GetForBrowserContext(
return ArcMediaSessionBridgeFactory::GetForBrowserContext(context);
}
+// static
+ArcMediaSessionBridge* ArcMediaSessionBridge::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcMediaSessionBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
ArcMediaSessionBridge::ArcMediaSessionBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service) {
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 8cb89bed047..b720af58ac3 100644
--- a/chromium/components/arc/media_session/arc_media_session_bridge.h
+++ b/chromium/components/arc/media_session/arc_media_session_bridge.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_ARC_MEDIA_SESSION_ARC_MEDIA_SESSION_BRIDGE_H_
#define COMPONENTS_ARC_MEDIA_SESSION_ARC_MEDIA_SESSION_BRIDGE_H_
-#include <string>
-
#include "base/macros.h"
#include "components/arc/mojom/media_session.mojom.h"
#include "components/arc/session/connection_observer.h"
@@ -32,6 +30,8 @@ class ArcMediaSessionBridge
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcMediaSessionBridge* GetForBrowserContext(
content::BrowserContext* context);
+ static ArcMediaSessionBridge* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
ArcMediaSessionBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service);
diff --git a/chromium/components/arc/media_session/arc_media_session_bridge_unittest.cc b/chromium/components/arc/media_session/arc_media_session_bridge_unittest.cc
new file mode 100644
index 00000000000..49159b5e020
--- /dev/null
+++ b/chromium/components/arc/media_session/arc_media_session_bridge_unittest.cc
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/media_session/arc_media_session_bridge.h"
+
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/test/test_browser_context.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcMediaSessionBridgeTest : public testing::Test {
+ protected:
+ ArcMediaSessionBridgeTest()
+ : bridge_(
+ ArcMediaSessionBridge::GetForBrowserContextForTesting(&context_)) {}
+ ArcMediaSessionBridgeTest(const ArcMediaSessionBridgeTest&) = delete;
+ ArcMediaSessionBridgeTest& operator=(const ArcMediaSessionBridgeTest&) =
+ delete;
+ ~ArcMediaSessionBridgeTest() override = default;
+
+ ArcMediaSessionBridge* bridge() { return bridge_; }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ ArcServiceManager arc_service_manager_;
+ TestBrowserContext context_;
+ ArcMediaSessionBridge* const bridge_;
+};
+
+TEST_F(ArcMediaSessionBridgeTest, ConstructDestruct) {
+ EXPECT_NE(nullptr, bridge());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/metrics/arc_metrics_service.cc b/chromium/components/arc/metrics/arc_metrics_service.cc
index 2d16a431b42..62e9061029f 100644
--- a/chromium/components/arc/metrics/arc_metrics_service.cc
+++ b/chromium/components/arc/metrics/arc_metrics_service.cc
@@ -16,10 +16,8 @@
#include "base/strings/string_util.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"
#include "components/arc/arc_prefs.h"
#include "components/arc/arc_util.h"
-#include "components/arc/metrics/arc_metrics_constants.h"
#include "components/arc/metrics/stability_metrics_manager.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/exo/wm_helper.h"
@@ -46,6 +44,40 @@ constexpr char kGmsProcessNamePrefix[] = "com.google.android.gms";
constexpr char kBootProgressEnableScreen[] = "boot_progress_enable_screen";
constexpr char kBootProgressArcUpgraded[] = "boot_progress_arc_upgraded";
+// App types to report.
+constexpr char kAppTypeArcAppLauncher[] = "ArcAppLauncher";
+constexpr char kAppTypeArcOther[] = "ArcOther";
+constexpr char kAppTypeFirstParty[] = "FirstParty";
+constexpr char kAppTypeGmsCore[] = "GmsCore";
+constexpr char kAppTypePlayStore[] = "PlayStore";
+constexpr char kAppTypeSystemServer[] = "SystemServer";
+constexpr char kAppTypeSystem[] = "SystemApp";
+constexpr char kAppTypeOther[] = "Other";
+
+std::string AnrSourceToTableName(mojom::AnrSource value) {
+ switch (value) {
+ case mojom::AnrSource::OTHER:
+ return kAppTypeOther;
+ case mojom::AnrSource::SYSTEM_SERVER:
+ return kAppTypeSystemServer;
+ case mojom::AnrSource::SYSTEM_APP:
+ return kAppTypeSystem;
+ case mojom::AnrSource::GMS_CORE:
+ return kAppTypeGmsCore;
+ case mojom::AnrSource::PLAY_STORE:
+ return kAppTypePlayStore;
+ case mojom::AnrSource::FIRST_PARTY:
+ return kAppTypeFirstParty;
+ case mojom::AnrSource::ARC_OTHER:
+ return kAppTypeArcOther;
+ case mojom::AnrSource::ARC_APP_LAUNCHER:
+ return kAppTypeArcAppLauncher;
+ default:
+ LOG(ERROR) << "Unrecognized source ANR " << value;
+ return kAppTypeOther;
+ }
+}
+
std::string BootTypeToString(mojom::BootType boot_type) {
switch (boot_type) {
case mojom::BootType::UNKNOWN:
@@ -61,28 +93,14 @@ std::string BootTypeToString(mojom::BootType boot_type) {
return "";
}
-// Singleton factory for ArcMetricsService.
-class ArcMetricsServiceFactory
- : public internal::ArcBrowserContextKeyedServiceFactoryBase<
- ArcMetricsService,
- ArcMetricsServiceFactory> {
- public:
- // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
- static constexpr const char* kName = "ArcMetricsServiceFactory";
-
- static ArcMetricsServiceFactory* GetInstance() {
- return base::Singleton<ArcMetricsServiceFactory>::get();
- }
-
- private:
- friend base::DefaultSingletonTraits<ArcMetricsServiceFactory>;
- ArcMetricsServiceFactory() = default;
- ~ArcMetricsServiceFactory() override = default;
-};
-
} // namespace
// static
+ArcMetricsServiceFactory* ArcMetricsServiceFactory::GetInstance() {
+ return base::Singleton<ArcMetricsServiceFactory>::get();
+}
+
+// static
ArcMetricsService* ArcMetricsService::GetForBrowserContext(
content::BrowserContext* context) {
return ArcMetricsServiceFactory::GetForBrowserContext(context);
@@ -145,6 +163,25 @@ void ArcMetricsService::Shutdown() {
app_kill_observers_.Clear();
}
+// static
+void ArcMetricsService::RecordArcUserInteraction(
+ content::BrowserContext* context,
+ UserInteractionType type) {
+ DCHECK(context);
+ auto* service = GetForBrowserContext(context);
+ if (!service) {
+ LOG(WARNING) << "Cannot get ArcMetricsService for context " << context;
+ return;
+ }
+ service->RecordArcUserInteraction(type);
+}
+
+void ArcMetricsService::RecordArcUserInteraction(UserInteractionType type) {
+ UMA_HISTOGRAM_ENUMERATION("Arc.UserInteraction", type);
+ for (auto& obs : user_interaction_observers_)
+ obs.OnUserInteraction(type);
+}
+
void ArcMetricsService::SetHistogramNamer(HistogramNamer histogram_namer) {
histogram_namer_ = histogram_namer;
}
@@ -199,7 +236,7 @@ void ArcMetricsService::ParseProcessList(
void ArcMetricsService::OnArcStartTimeRetrieved(
std::vector<mojom::BootProgressEventPtr> events,
mojom::BootType boot_type,
- base::Optional<base::TimeTicks> arc_start_time) {
+ absl::optional<base::TimeTicks> arc_start_time) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!arc_start_time.has_value()) {
LOG(ERROR) << "Failed to retrieve ARC start timeticks.";
@@ -240,7 +277,7 @@ void ArcMetricsService::ReportBootProgress(
// For VM builds, do not call into session_manager since we don't use it
// for the builds. The upgrade time is included in the events vector so we
// can extract it here.
- base::Optional<base::TimeTicks> arc_start_time =
+ absl::optional<base::TimeTicks> arc_start_time =
GetArcStartTimeFromEvents(events);
OnArcStartTimeRetrieved(std::move(events), boot_type, arc_start_time);
return;
@@ -325,7 +362,7 @@ void ArcMetricsService::ReportArcCorePriAbiMigDowngradeDelay(
void ArcMetricsService::OnArcStartTimeForPriAbiMigration(
base::TimeTicks durationTicks,
- base::Optional<base::TimeTicks> arc_start_time) {
+ absl::optional<base::TimeTicks> arc_start_time) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!arc_start_time.has_value()) {
LOG(ERROR) << "Failed to retrieve ARC start timeticks.";
@@ -366,6 +403,14 @@ void ArcMetricsService::ReportClipboardDragDropEvent(
base::UmaHistogramEnumeration("Arc.ClipboardDragDrop", event_type);
}
+void ArcMetricsService::ReportAnr(mojom::AnrPtr anr) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ base::UmaHistogramEnumeration("Arc.Anr.Overall", anr->type);
+
+ base::UmaHistogramEnumeration("Arc.Anr." + AnrSourceToTableName(anr->source),
+ anr->type);
+}
+
void ArcMetricsService::OnWindowActivated(
wm::ActivationChangeObserver::ActivationReason reason,
aura::Window* gained_active,
@@ -375,9 +420,7 @@ void ArcMetricsService::OnWindowActivated(
gamepad_interaction_recorded_ = false;
return;
}
- UMA_HISTOGRAM_ENUMERATION(
- "Arc.UserInteraction",
- UserInteractionType::APP_CONTENT_WINDOW_INTERACTION);
+ RecordArcUserInteraction(UserInteractionType::APP_CONTENT_WINDOW_INTERACTION);
}
void ArcMetricsService::OnGamepadEvent(const ui::GamepadEvent& event) {
@@ -386,8 +429,7 @@ void ArcMetricsService::OnGamepadEvent(const ui::GamepadEvent& event) {
if (gamepad_interaction_recorded_)
return;
gamepad_interaction_recorded_ = true;
- UMA_HISTOGRAM_ENUMERATION("Arc.UserInteraction",
- UserInteractionType::GAMEPAD_INTERACTION);
+ RecordArcUserInteraction(UserInteractionType::GAMEPAD_INTERACTION);
}
void ArcMetricsService::OnTaskCreated(int32_t task_id,
@@ -418,7 +460,19 @@ void ArcMetricsService::RemoveAppKillObserver(AppKillObserver* obs) {
app_kill_observers_.RemoveObserver(obs);
}
-base::Optional<base::TimeTicks> ArcMetricsService::GetArcStartTimeFromEvents(
+void ArcMetricsService::AddUserInteractionObserver(
+ UserInteractionObserver* obs) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ user_interaction_observers_.AddObserver(obs);
+}
+
+void ArcMetricsService::RemoveUserInteractionObserver(
+ UserInteractionObserver* obs) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ user_interaction_observers_.RemoveObserver(obs);
+}
+
+absl::optional<base::TimeTicks> ArcMetricsService::GetArcStartTimeFromEvents(
std::vector<mojom::BootProgressEventPtr>& events) {
mojom::BootProgressEventPtr arc_upgraded_event;
for (auto it = events.begin(); it != events.end(); ++it) {
@@ -430,7 +484,7 @@ base::Optional<base::TimeTicks> ArcMetricsService::GetArcStartTimeFromEvents(
base::TimeTicks();
}
}
- return base::nullopt;
+ return absl::nullopt;
}
ArcMetricsService::ProcessObserver::ProcessObserver(
ArcMetricsService* arc_metrics_service)
diff --git a/chromium/components/arc/metrics/arc_metrics_service.h b/chromium/components/arc/metrics/arc_metrics_service.h
index a1c351c865c..f855f58f4e9 100644
--- a/chromium/components/arc/metrics/arc_metrics_service.h
+++ b/chromium/components/arc/metrics/arc_metrics_service.h
@@ -14,16 +14,18 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
+#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "components/arc/metrics/arc_metrics_constants.h"
#include "components/arc/mojom/metrics.mojom.h"
#include "components/arc/mojom/process.mojom.h"
#include "components/arc/session/arc_bridge_service.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 "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/ozone/gamepad/gamepad_observer.h"
#include "ui/wm/public/activation_change_observer.h"
@@ -60,6 +62,11 @@ class ArcMetricsService : public KeyedService,
virtual void OnArcMetricsServiceDestroyed() {}
};
+ class UserInteractionObserver : public base::CheckedObserver {
+ public:
+ virtual void OnUserInteraction(UserInteractionType type) = 0;
+ };
+
// Returns singleton instance for the given BrowserContext,
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcMetricsService* GetForBrowserContext(
@@ -77,6 +84,10 @@ class ArcMetricsService : public KeyedService,
// KeyedService overrides.
void Shutdown() override;
+ // Records one of Arc.UserInteraction UMA stats. |context| cannot be null.
+ static void RecordArcUserInteraction(content::BrowserContext* context,
+ UserInteractionType type);
+
// Sets the histogram namer. Required to not have a dependency on browser
// codebase.
void SetHistogramNamer(HistogramNamer histogram_namer);
@@ -98,6 +109,7 @@ class ArcMetricsService : public KeyedService,
void ReportArcCorePriAbiMigBootTime(base::TimeDelta duration) override;
void ReportClipboardDragDropEvent(
mojom::ArcClipboardDragDropEvent event_type) override;
+ void ReportAnr(mojom::AnrPtr anr) override;
// wm::ActivationChangeObserver overrides.
// Records to UMA when a user has interacted with an ARC app window.
@@ -119,11 +131,14 @@ class ArcMetricsService : public KeyedService,
void AddAppKillObserver(AppKillObserver* obs);
void RemoveAppKillObserver(AppKillObserver* obs);
+ void AddUserInteractionObserver(UserInteractionObserver* obs);
+ void RemoveUserInteractionObserver(UserInteractionObserver* obs);
+
// Finds the boot_progress_arc_upgraded event, removes it from |events|, and
// returns the event time. If the boot_progress_arc_upgraded event is not
- // found, base::nullopt is returned. This function is public for testing
+ // found, absl::nullopt is returned. This function is public for testing
// purposes.
- base::Optional<base::TimeTicks> GetArcStartTimeFromEvents(
+ absl::optional<base::TimeTicks> GetArcStartTimeFromEvents(
std::vector<mojom::BootProgressEventPtr>& events);
private:
@@ -193,16 +208,17 @@ class ArcMetricsService : public KeyedService,
DISALLOW_COPY_AND_ASSIGN(AppLauncherObserver);
};
+ void RecordArcUserInteraction(UserInteractionType type);
void RequestProcessList();
void ParseProcessList(std::vector<mojom::RunningAppProcessInfoPtr> processes);
// DBus callbacks.
void OnArcStartTimeRetrieved(std::vector<mojom::BootProgressEventPtr> events,
mojom::BootType boot_type,
- base::Optional<base::TimeTicks> arc_start_time);
+ absl::optional<base::TimeTicks> arc_start_time);
void OnArcStartTimeForPriAbiMigration(
base::TimeTicks durationTicks,
- base::Optional<base::TimeTicks> arc_start_time);
+ absl::optional<base::TimeTicks> arc_start_time);
// Notify AppKillObservers.
void NotifyLowMemoryKill();
@@ -232,6 +248,7 @@ class ArcMetricsService : public KeyedService,
bool gamepad_interaction_recorded_ = false;
base::ObserverList<AppKillObserver> app_kill_observers_;
+ base::ObserverList<UserInteractionObserver> user_interaction_observers_;
// Always keep this the last member of this class to make sure it's the
// first thing to be destructed.
@@ -240,6 +257,23 @@ class ArcMetricsService : public KeyedService,
DISALLOW_COPY_AND_ASSIGN(ArcMetricsService);
};
+// Singleton factory for ArcMetricsService.
+class ArcMetricsServiceFactory
+ : public internal::ArcBrowserContextKeyedServiceFactoryBase<
+ ArcMetricsService,
+ ArcMetricsServiceFactory> {
+ public:
+ // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
+ static constexpr const char* kName = "ArcMetricsServiceFactory";
+
+ static ArcMetricsServiceFactory* GetInstance();
+
+ private:
+ friend base::DefaultSingletonTraits<ArcMetricsServiceFactory>;
+ ArcMetricsServiceFactory() = default;
+ ~ArcMetricsServiceFactory() override = default;
+};
+
} // namespace arc
#endif // COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H_
diff --git a/chromium/components/arc/metrics/arc_metrics_service_unittest.cc b/chromium/components/arc/metrics/arc_metrics_service_unittest.cc
index e6481624c63..10a7622295b 100644
--- a/chromium/components/arc/metrics/arc_metrics_service_unittest.cc
+++ b/chromium/components/arc/metrics/arc_metrics_service_unittest.cc
@@ -6,11 +6,14 @@
#include <algorithm>
#include <array>
+#include <map>
#include <utility>
+#include <vector>
#include "ash/public/cpp/app_types.h"
#include "base/metrics/histogram_samples.h"
#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
#include "components/arc/arc_prefs.h"
@@ -22,6 +25,7 @@
#include "components/session_manager/core/session_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
@@ -45,6 +49,46 @@ constexpr std::array<const char*, 11> kBootEvents{
constexpr const char kBootProgressArcUpgraded[] = "boot_progress_arc_upgraded";
+constexpr char kAppTypeArcAppLauncher[] = "ArcAppLauncher";
+constexpr char kAppTypeArcOther[] = "ArcOther";
+constexpr char kAppTypeFirstParty[] = "FirstParty";
+constexpr char kAppTypeGmsCore[] = "GmsCore";
+constexpr char kAppTypePlayStore[] = "PlayStore";
+constexpr char kAppTypeSystemServer[] = "SystemServer";
+constexpr char kAppTypeSystem[] = "SystemApp";
+constexpr char kAppTypeOther[] = "Other";
+constexpr char kAppOverall[] = "Overall";
+
+constexpr std::array<const char*, 9> kAppTypes{
+ kAppTypeArcAppLauncher, kAppTypeArcOther, kAppTypeFirstParty,
+ kAppTypeGmsCore, kAppTypePlayStore, kAppTypeSystemServer,
+ kAppTypeSystem, kAppTypeOther, kAppOverall,
+};
+
+std::string CreateAnrKey(const std::string& app_type, mojom::AnrType type) {
+ std::stringstream output;
+ output << app_type << "/" << type;
+ return output.str();
+}
+
+mojom::AnrPtr GetAnr(mojom::AnrSource source, mojom::AnrType type) {
+ return mojom::Anr::New(type, source);
+}
+
+void VerifyAnr(const base::HistogramTester& tester,
+ const std::map<std::string, int>& expectation) {
+ std::map<std::string, int> current;
+ for (const char* app_type : kAppTypes) {
+ const std::vector<base::Bucket> buckets =
+ tester.GetAllSamples("Arc.Anr." + std::string(app_type));
+ for (const auto& bucket : buckets) {
+ current[CreateAnrKey(app_type, static_cast<mojom::AnrType>(bucket.min))] =
+ bucket.count;
+ }
+ }
+ EXPECT_EQ(expectation, current);
+}
+
class ArcMetricsServiceTest : public testing::Test {
protected:
ArcMetricsServiceTest() {
@@ -298,7 +342,7 @@ TEST_F(ArcMetricsServiceTest, GetArcStartTimeFromEvents) {
events.emplace_back(
mojom::BootProgressEvent::New(kBootProgressArcUpgraded, kArcStartTimeMs));
- base::Optional<base::TimeTicks> arc_start_time =
+ absl::optional<base::TimeTicks> arc_start_time =
service()->GetArcStartTimeFromEvents(events);
EXPECT_TRUE(arc_start_time.has_value());
EXPECT_EQ(*arc_start_time,
@@ -316,10 +360,88 @@ TEST_F(ArcMetricsServiceTest, GetArcStartTimeFromEvents_NoArcUpgradedEvent) {
std::vector<mojom::BootProgressEventPtr> events(
GetBootProgressEvents(kArcStartTimeMs, 1 /* step_in_ms */));
- base::Optional<base::TimeTicks> arc_start_time =
+ absl::optional<base::TimeTicks> arc_start_time =
service()->GetArcStartTimeFromEvents(events);
EXPECT_FALSE(arc_start_time.has_value());
}
+TEST_F(ArcMetricsServiceTest, UserInteractionObserver) {
+ class Observer : public ArcMetricsService::UserInteractionObserver {
+ public:
+ void OnUserInteraction(UserInteractionType type) override {
+ this->type = type;
+ }
+ absl::optional<UserInteractionType> type;
+ } observer;
+
+ service()->AddUserInteractionObserver(&observer);
+
+ // This calls RecordArcUserInteraction() with APP_CONTENT_WINDOW_INTERACTION.
+ service()->OnWindowActivated(
+ wm::ActivationChangeObserver::ActivationReason::INPUT_EVENT,
+ fake_arc_window(), nullptr);
+ ASSERT_TRUE(observer.type);
+ EXPECT_EQ(UserInteractionType::APP_CONTENT_WINDOW_INTERACTION,
+ *observer.type);
+
+ service()->RemoveUserInteractionObserver(&observer);
+}
+
+TEST_F(ArcMetricsServiceTest, ArcAnr) {
+ base::HistogramTester tester;
+ std::map<std::string, int> expectation;
+
+ service()->ReportAnr(
+ GetAnr(mojom::AnrSource::OTHER, mojom::AnrType::UNKNOWN));
+ expectation[CreateAnrKey(kAppOverall, mojom::AnrType::UNKNOWN)] = 1;
+ expectation[CreateAnrKey(kAppTypeOther, mojom::AnrType::UNKNOWN)] = 1;
+ VerifyAnr(tester, expectation);
+
+ service()->ReportAnr(
+ GetAnr(mojom::AnrSource::SYSTEM_SERVER, mojom::AnrType::INPUT));
+ expectation[CreateAnrKey(kAppOverall, mojom::AnrType::INPUT)] = 1;
+ expectation[CreateAnrKey(kAppTypeSystemServer, mojom::AnrType::INPUT)] = 1;
+ VerifyAnr(tester, expectation);
+
+ service()->ReportAnr(
+ GetAnr(mojom::AnrSource::SYSTEM_SERVER, mojom::AnrType::SERVICE));
+ expectation[CreateAnrKey(kAppOverall, mojom::AnrType::SERVICE)] = 1;
+ expectation[CreateAnrKey(kAppTypeSystemServer, mojom::AnrType::SERVICE)] = 1;
+ VerifyAnr(tester, expectation);
+
+ service()->ReportAnr(
+ GetAnr(mojom::AnrSource::GMS_CORE, mojom::AnrType::BROADCAST));
+ expectation[CreateAnrKey(kAppOverall, mojom::AnrType::BROADCAST)] = 1;
+ expectation[CreateAnrKey(kAppTypeGmsCore, mojom::AnrType::BROADCAST)] = 1;
+ VerifyAnr(tester, expectation);
+
+ service()->ReportAnr(
+ GetAnr(mojom::AnrSource::PLAY_STORE, mojom::AnrType::CONTENT_PROVIDER));
+ expectation[CreateAnrKey(kAppOverall, mojom::AnrType::CONTENT_PROVIDER)] = 1;
+ expectation[CreateAnrKey(kAppTypePlayStore,
+ mojom::AnrType::CONTENT_PROVIDER)] = 1;
+ VerifyAnr(tester, expectation);
+
+ service()->ReportAnr(
+ GetAnr(mojom::AnrSource::FIRST_PARTY, mojom::AnrType::APP_REQUESTED));
+ expectation[CreateAnrKey(kAppOverall, mojom::AnrType::APP_REQUESTED)] = 1;
+ expectation[CreateAnrKey(kAppTypeFirstParty, mojom::AnrType::APP_REQUESTED)] =
+ 1;
+ VerifyAnr(tester, expectation);
+
+ service()->ReportAnr(
+ GetAnr(mojom::AnrSource::ARC_OTHER, mojom::AnrType::INPUT));
+ expectation[CreateAnrKey(kAppOverall, mojom::AnrType::INPUT)] = 2;
+ expectation[CreateAnrKey(kAppTypeArcOther, mojom::AnrType::INPUT)] = 1;
+ VerifyAnr(tester, expectation);
+
+ service()->ReportAnr(
+ GetAnr(mojom::AnrSource::ARC_APP_LAUNCHER, mojom::AnrType::SERVICE));
+ expectation[CreateAnrKey(kAppOverall, mojom::AnrType::SERVICE)] = 2;
+ expectation[CreateAnrKey(kAppTypeArcAppLauncher, mojom::AnrType::SERVICE)] =
+ 1;
+ VerifyAnr(tester, expectation);
+}
+
} // namespace
} // namespace arc
diff --git a/chromium/components/arc/metrics/stability_metrics_manager.cc b/chromium/components/arc/metrics/stability_metrics_manager.cc
index 8bd1c59c855..6d6e2079b38 100644
--- a/chromium/components/arc/metrics/stability_metrics_manager.cc
+++ b/chromium/components/arc/metrics/stability_metrics_manager.cc
@@ -55,11 +55,11 @@ void StabilityMetricsManager::RecordMetricsToUMA() {
return;
}
- const base::Optional<bool> enabled_state = GetArcEnabledState();
+ const absl::optional<bool> enabled_state = GetArcEnabledState();
if (enabled_state)
UMA_STABILITY_HISTOGRAM_ENUMERATION("Arc.State", *enabled_state ? 1 : 0, 2);
- const base::Optional<NativeBridgeType> native_bridge_type =
+ const absl::optional<NativeBridgeType> native_bridge_type =
GetArcNativeBridgeType();
if (native_bridge_type) {
UMA_STABILITY_HISTOGRAM_ENUMERATION(
@@ -74,7 +74,7 @@ void StabilityMetricsManager::ResetMetrics() {
update->Clear();
}
-base::Optional<bool> StabilityMetricsManager::GetArcEnabledState() {
+absl::optional<bool> StabilityMetricsManager::GetArcEnabledState() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const base::DictionaryValue* dict =
local_state_->GetDictionary(prefs::kStabilityMetrics);
@@ -87,18 +87,18 @@ void StabilityMetricsManager::SetArcEnabledState(bool enabled) {
update->SetKey(kArcEnabledStateKey, base::Value(enabled));
}
-base::Optional<NativeBridgeType>
+absl::optional<NativeBridgeType>
StabilityMetricsManager::GetArcNativeBridgeType() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const base::DictionaryValue* dict =
local_state_->GetDictionary(prefs::kStabilityMetrics);
- base::Optional<int> native_bridge_type =
+ absl::optional<int> native_bridge_type =
dict->FindIntKey(kArcNativeBridgeTypeKey);
if (native_bridge_type) {
- return base::make_optional(
+ return absl::make_optional(
static_cast<NativeBridgeType>(*native_bridge_type));
}
- return base::nullopt;
+ return absl::nullopt;
}
void StabilityMetricsManager::SetArcNativeBridgeType(
diff --git a/chromium/components/arc/metrics/stability_metrics_manager.h b/chromium/components/arc/metrics/stability_metrics_manager.h
index 3e852cc6df6..2ba1cd825f9 100644
--- a/chromium/components/arc/metrics/stability_metrics_manager.h
+++ b/chromium/components/arc/metrics/stability_metrics_manager.h
@@ -5,9 +5,9 @@
#ifndef COMPONENTS_ARC_METRICS_STABILITY_METRICS_MANAGER_H_
#define COMPONENTS_ARC_METRICS_STABILITY_METRICS_MANAGER_H_
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "components/arc/metrics/arc_metrics_constants.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
@@ -37,13 +37,13 @@ class StabilityMetricsManager {
void ResetMetrics();
// Returns current persisted value (if exists) for Arc.State UMA histogram.
- base::Optional<bool> GetArcEnabledState();
+ absl::optional<bool> GetArcEnabledState();
// Sets value for Arc.State UMA histogram.
void SetArcEnabledState(bool enabled);
// Returns current persisted value (if exists) for Arc.State UMA histogram.
- base::Optional<NativeBridgeType> GetArcNativeBridgeType();
+ absl::optional<NativeBridgeType> GetArcNativeBridgeType();
// Sets value for Arc.NativeBridgeType UMA histogram.
void SetArcNativeBridgeType(NativeBridgeType native_bridge_type);
diff --git a/chromium/components/arc/midis/arc_midis_bridge.cc b/chromium/components/arc/midis/arc_midis_bridge.cc
index 478dfbadd21..b3af415d47e 100644
--- a/chromium/components/arc/midis/arc_midis_bridge.cc
+++ b/chromium/components/arc/midis/arc_midis_bridge.cc
@@ -46,6 +46,12 @@ ArcMidisBridge* ArcMidisBridge::GetForBrowserContext(
return ArcMidisBridgeFactory::GetForBrowserContext(context);
}
+// static
+ArcMidisBridge* ArcMidisBridge::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcMidisBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
ArcMidisBridge::ArcMidisBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service) {
diff --git a/chromium/components/arc/midis/arc_midis_bridge.h b/chromium/components/arc/midis/arc_midis_bridge.h
index 3b97a95e022..d5a1a24c266 100644
--- a/chromium/components/arc/midis/arc_midis_bridge.h
+++ b/chromium/components/arc/midis/arc_midis_bridge.h
@@ -7,8 +7,6 @@
#include <stdint.h>
-#include <vector>
-
#include "base/macros.h"
#include "components/arc/mojom/midis.mojom.h"
#include "components/keyed_service/core/keyed_service.h"
@@ -30,6 +28,8 @@ class ArcMidisBridge : public KeyedService,
// Returns singleton instance for the given BrowserContext,
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcMidisBridge* GetForBrowserContext(content::BrowserContext* context);
+ static ArcMidisBridge* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
ArcMidisBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service);
diff --git a/chromium/components/arc/midis/arc_midis_bridge_unittest.cc b/chromium/components/arc/midis/arc_midis_bridge_unittest.cc
new file mode 100644
index 00000000000..00ca51811a9
--- /dev/null
+++ b/chromium/components/arc/midis/arc_midis_bridge_unittest.cc
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/midis/arc_midis_bridge.h"
+
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/test/test_browser_context.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcMidisBridgeTest : public testing::Test {
+ protected:
+ ArcMidisBridgeTest()
+ : bridge_(ArcMidisBridge::GetForBrowserContextForTesting(&context_)) {}
+ ArcMidisBridgeTest(const ArcMidisBridgeTest&) = delete;
+ ArcMidisBridgeTest& operator=(const ArcMidisBridgeTest&) = delete;
+ ~ArcMidisBridgeTest() override = default;
+
+ ArcMidisBridge* bridge() { return bridge_; }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ ArcServiceManager arc_service_manager_;
+ TestBrowserContext context_;
+ ArcMidisBridge* const bridge_;
+};
+
+TEST_F(ArcMidisBridgeTest, ConstructDestruct) {
+ EXPECT_NE(nullptr, bridge());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/mojom/BUILD.gn b/chromium/components/arc/mojom/BUILD.gn
index 825de163af2..76eedfde155 100644
--- a/chromium/components/arc/mojom/BUILD.gn
+++ b/chromium/components/arc/mojom/BUILD.gn
@@ -71,6 +71,7 @@ if (is_chromeos_ash) {
"volume_mounter.mojom",
"wake_lock.mojom",
"wallpaper.mojom",
+ "webapk.mojom",
]
public_deps = [
@@ -87,7 +88,7 @@ if (is_chromeos_ash) {
"//services/media_session/public/mojom",
"//services/resource_coordinator/public/mojom",
"//third_party/blink/public/mojom:android_mojo_bindings",
- "//ui/accessibility/mojom",
+ "//ui/accessibility/mojom:ax_assistant_mojom",
"//ui/gfx/geometry/mojom",
"//url/mojom:url_mojom_gurl",
]
diff --git a/chromium/components/arc/mojom/app.mojom b/chromium/components/arc/mojom/app.mojom
index 68670499b4b..cfe282d26f1 100644
--- a/chromium/components/arc/mojom/app.mojom
+++ b/chromium/components/arc/mojom/app.mojom
@@ -108,7 +108,7 @@ struct RawIconPngData {
// MakeArcWindowInfo in chrome/browser/apps/app_service/launch_utils.cc
struct WindowInfo {
int32 window_id = -1;
- int32 state = -1;
+ int32 state = 0;
int64 display_id = -1;
Rect? bounds;
};
@@ -369,7 +369,11 @@ interface AppHost {
// Sends task label and icon.
[MinVersion=46] OnTaskDescriptionChanged@18(
- int32 task_id, string label, RawIconPngData icon);
+ int32 task_id,
+ string label,
+ RawIconPngData icon,
+ [MinVersion=49] uint32 primary_color,
+ [MinVersion=49] uint32 status_bar_color);
// Notifies that task has been destroyed.
[MinVersion=4] OnTaskDestroyed@5(int32 task_id);
diff --git a/chromium/components/arc/mojom/arc_bridge.mojom b/chromium/components/arc/mojom/arc_bridge.mojom
index 5f61d2acc6e..bddf7d1f734 100644
--- a/chromium/components/arc/mojom/arc_bridge.mojom
+++ b/chromium/components/arc/mojom/arc_bridge.mojom
@@ -61,10 +61,11 @@ 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";
+import "components/arc/mojom/webapk.mojom";
-// Next MinVersion: 57
+// Next MinVersion: 58
// Deprecated method IDs: 101, 105, 121
-// Next method ID: 162
+// Next method ID: 163
interface ArcBridgeHost {
// Keep the entries alphabetical. In order to do so without breaking
// compatibility with the ARC instance, explicitly assign each interface a
@@ -298,4 +299,8 @@ interface ArcBridgeHost {
// Notifies Chrome that the WallpaperInstance interface is ready.
[MinVersion=18] OnWallpaperInstanceReady@124(
pending_remote<WallpaperInstance> instance_remote);
+
+ // Notifies Chrome that the WebApkInstance interface is ready.
+ [MinVersion=57] OnWebApkInstanceReady@162(
+ pending_remote<WebApkInstance> instance_ptr);
};
diff --git a/chromium/components/arc/mojom/auth.mojom b/chromium/components/arc/mojom/auth.mojom
index 9a3af92e304..5ecfc81538a 100644
--- a/chromium/components/arc/mojom/auth.mojom
+++ b/chromium/components/arc/mojom/auth.mojom
@@ -258,24 +258,24 @@ enum MainAccountResolutionStatus {
// tools/metrics/histograms/enums.xml.
};
-// These values describe the result of ARC attempting to change supervision
+// These values describe the result of ARC attempting to change management
// state after an account type change.
[Extensible]
-enum SupervisionChangeStatus {
- // CloudDPC supervision was disabled successfully.
+enum ManagementChangeStatus {
+ // CloudDPC was disabled successfully.
[MinVersion=13] CLOUD_DPC_DISABLED = 0,
- // CloudDPC supervision was already disabled.
+ // CloudDPC was already disabled.
[MinVersion=13] CLOUD_DPC_ALREADY_DISABLED = 1,
- // CloudDPC supervision was enabled successfully.
+ // CloudDPC was enabled successfully.
[MinVersion=13] CLOUD_DPC_ENABLED = 2,
- // CloudDPC supervision was already enabled.
+ // CloudDPC was already enabled.
[MinVersion=13] CLOUD_DPC_ALREADY_ENABLED = 3,
// Invalid state returned from Chrome.
- [MinVersion=13] INVALID_SUPERVISION_STATE = 4,
+ [MinVersion=13] INVALID_MANAGEMENT_STATE = 4,
// Failed to disable CloudDPC due to an unspecified error.
[MinVersion=13] CLOUD_DPC_DISABLING_FAILED = 5,
@@ -384,12 +384,12 @@ interface AuthHost {
// Reports result of account check.
[MinVersion=9] ReportAccountCheckStatus@9(AccountCheckStatus status);
- // Reports to Chrome the result of changing the supervision state.
- // Chrome informs ARC on every boot if a supervision transition is necessary
+ // Reports to Chrome the result of changing the management state.
+ // Chrome informs ARC on every boot if a management transition is necessary
// or not (see https://crrev.com/c/1069031). ARC should report back only if
// a transition was necessary.
- [MinVersion=13] ReportSupervisionChangeStatus@11(
- SupervisionChangeStatus status);
+ [MinVersion=13] ReportManagementChangeStatus@11(
+ ManagementChangeStatus status);
// Returns the primary account from Chrome.
// |account_name| is the email address of the primary account for consumer and
diff --git a/chromium/components/arc/mojom/camera.mojom b/chromium/components/arc/mojom/camera.mojom
index f3313f94513..890a7f4e2af 100644
--- a/chromium/components/arc/mojom/camera.mojom
+++ b/chromium/components/arc/mojom/camera.mojom
@@ -6,7 +6,7 @@
module arc.mojom;
-import "media/capture/video/chromeos/mojom/cros_camera_service.mojom";
+import "media/capture/video/chromeos/mojom/cros_camera_client.mojom";
struct CameraDeviceInfo {
string device_path@0;
diff --git a/chromium/components/arc/mojom/crash_collector.mojom b/chromium/components/arc/mojom/crash_collector.mojom
index 0fffceef939..4faafb051d9 100644
--- a/chromium/components/arc/mojom/crash_collector.mojom
+++ b/chromium/components/arc/mojom/crash_collector.mojom
@@ -2,17 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Next MinVersion: 6
+// Next MinVersion: 7
module arc.mojom;
+import "mojo/public/mojom/base/time.mojom";
+
// Next Method ID: 4
interface CrashCollectorHost {
// Sends a dump for a non-native crash of the given |type|. The host reads
// the dump from |pipe|, or rejects the dump by closing |pipe|. Note that
// |type| is a string instead of an enum, because its value is not relevant
- // to the host: it only serves as a tag in the report.
- DumpCrash@0(string type, handle pipe);
+ // to the host: it only serves as a tag in the report. |uptime| is the value
+ // of CLOCK_BOOTTIME of the guest at the time when crash happened.
+ DumpCrash@0(string type,
+ handle pipe,
+ [MinVersion=6] mojo_base.mojom.TimeDelta? uptime);
// Sets build properties included in every report.
[MinVersion=1] SetBuildProperties@1(string device,
@@ -21,6 +26,7 @@ interface CrashCollectorHost {
[MinVersion=3] string? fingerprint);
// Sends a dump for a native crash.
+ // TODO(kimiyuki): Add |uptime| parameter to DumpNativeCrash.
[MinVersion=4] DumpNativeCrash@2(string exec_name,
int32 pid,
int64 timestamp,
diff --git a/chromium/components/arc/mojom/intent_helper.mojom b/chromium/components/arc/mojom/intent_helper.mojom
index 088ce5fd938..fb5c989cddc 100644
--- a/chromium/components/arc/mojom/intent_helper.mojom
+++ b/chromium/components/arc/mojom/intent_helper.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: 44
+// Next MinVersion: 45
module arc.mojom;
@@ -184,8 +184,8 @@ enum ChromePage {
PLUGINVMSHAREDPATHS,
OSACCESSIBILITY,
OSLANGUAGES,
- OSLANGUAGESDETAILS,
- OSLANGUAGESINPUTMETHODS,
+ DEPRECATED_OSLANGUAGESDETAILS,
+ DEPRECATED_OSLANGUAGESINPUTMETHODS,
OSPRINTING,
PRINTING,
OSPEOPLE,
@@ -199,8 +199,9 @@ enum ChromePage {
OSLANGUAGESEDITDICTIONARY,
KERBEROS,
KERBEROSACCOUNTSV2,
+ SEARCHSUBPAGE,
- LAST = KERBEROSACCOUNTSV2
+ LAST = SEARCHSUBPAGE
};
// Describes an unique chrome app.
@@ -244,7 +245,7 @@ interface CustomTabSession {
// Handles intents from ARC in Chrome.
// Deprecated method ID: 4, 10
-// Next method ID: 18
+// Next method ID: 19
interface IntentHelperHost {
// Called when icons associated with the package are no longer up to date.
[MinVersion=3] OnIconInvalidated@1(string package_name);
@@ -327,6 +328,18 @@ interface IntentHelperHost {
// Send the preferred app changes from ARC to Chrome.
[MinVersion=34] OnPreferredAppsChanged@16(array<IntentFilter> added,
array<IntentFilter> deleted);
+
+ // Called when a new entry has been added to the MediaStore.Downloads
+ // collection of downloaded items with the specified metadata.
+ // |relative_path| relative path of the download within the Download/
+ // folder (e.g. "Download/foo/bar.pdf"). The method
+ // implementation must verify that the `relative_path` is
+ // in fact within the Download/ folder (or subdirectory),
+ // treating ARC as an untrusted source.
+ // |owner_package_name| package name that contributed the download (e.g.
+ // "com.bar.foo").
+ [MinVersion=44] OnDownloadAdded@18(
+ string relative_path, string owner_package_name);
};
// Sends intents to ARC on behalf of Chrome.
diff --git a/chromium/components/arc/mojom/metrics.mojom b/chromium/components/arc/mojom/metrics.mojom
index 0fa106d3112..31f2862c60f 100644
--- a/chromium/components/arc/mojom/metrics.mojom
+++ b/chromium/components/arc/mojom/metrics.mojom
@@ -1,13 +1,57 @@
// 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.
-// Next MinVersion: 9
+// Next MinVersion: 10
module arc.mojom;
import "mojo/public/mojom/base/time.mojom";
[Extensible]
+enum AnrType {
+ // Other types of ANR which are not explicitly defined.
+ UNKNOWN = 0,
+ // ANR while handling input events.
+ INPUT = 1,
+ // ANR in services.
+ SERVICE = 2,
+ // ANR in broadcasts.
+ BROADCAST = 3,
+ // ANR in content provider.
+ CONTENT_PROVIDER = 4,
+ // App custom ANR.
+ APP_REQUESTED = 5,
+};
+
+[Extensible]
+enum AnrSource {
+ // ANR coming from anything else than explicitly defined.
+ OTHER = 0,
+ // ANR coming from system server.
+ SYSTEM_SERVER = 1,
+ // ANR coming from system apps.
+ SYSTEM_APP = 2,
+ // ANR coming from GMS core.
+ GMS_CORE = 3,
+ // ANR coming from Play Store.
+ PLAY_STORE = 4,
+ // ANR coming from first party Google apps
+ FIRST_PARTY = 5,
+ // ANR coming from ARC apps other than explicitly defined.
+ ARC_OTHER = 6,
+ // ANR coming from ARC App launcher.
+ ARC_APP_LAUNCHER = 7,
+};
+
+// Describes an ANR event.
+struct Anr {
+ // Type of ANR event.
+ AnrType type;
+ // ANR source.
+ AnrSource source;
+};
+
+[Extensible]
enum BootType {
// This is used only for backward compatibility reasons and the value has to
// be 0.
@@ -152,7 +196,7 @@ enum ArcClipboardDragDropEvent {
kImageDragDropFromArc = 7,
};
-// Next method ID: 9
+// Next method ID: 10
interface MetricsHost {
// Reports boot progress events from ARC instance.
ReportBootProgress@0(array<BootProgressEvent> events,
@@ -182,6 +226,9 @@ interface MetricsHost {
// Reports a clipboard / drag-and-drop event.
[MinVersion=8] ReportClipboardDragDropEvent@8(
ArcClipboardDragDropEvent event_type);
+
+ // Reports ANR event.
+ [MinVersion=9] ReportAnr@10(Anr anr);
};
// Next method ID: 3
diff --git a/chromium/components/arc/mojom/payment_app.mojom b/chromium/components/arc/mojom/payment_app.mojom
index a52ba82ce66..d206f0d4865 100644
--- a/chromium/components/arc/mojom/payment_app.mojom
+++ b/chromium/components/arc/mojom/payment_app.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: 3
+// Next MinVersion: 4
module arc.mojom;
@@ -85,6 +85,11 @@ struct PaymentParameters {
// not currently need this parameter.
[MinVersion=2]
string? payment_request_id;
+
+ // Opaque, browser-generated identifier for this payment request. Used to
+ // identify a particular request across calls.
+ [MinVersion=3]
+ string? request_token;
};
// After the browser calls IsReadyToPay(), ARC sends back this result.
@@ -165,4 +170,14 @@ interface PaymentAppInstance {
[MinVersion=2]
InvokePaymentApp@2(PaymentParameters parameters)
=> (InvokePaymentAppResult response);
+
+ // Requests to abort a previous payment flow (identified by |request_token|)
+ // which was opened with InvokePaymentApp().
+ //
+ // This may be called by the website if a payment should no longer be made
+ // (e.g., when an item goes out of stock), or by the browser if the payment is
+ // no longer available (e.g., the page was refreshed).
+ [MinVersion=3]
+ AbortPaymentApp@3(string request_token)
+ => (bool aborted);
};
diff --git a/chromium/components/arc/mojom/video_accelerator_mojom_traits.cc b/chromium/components/arc/mojom/video_accelerator_mojom_traits.cc
index 1000ca02f92..d97abca275c 100644
--- a/chromium/components/arc/mojom/video_accelerator_mojom_traits.cc
+++ b/chromium/components/arc/mojom/video_accelerator_mojom_traits.cc
@@ -216,7 +216,7 @@ bool StructTraits<arc::mojom::VideoFrameLayoutDataView,
return false;
}
- base::Optional<media::VideoFrameLayout> layout =
+ absl::optional<media::VideoFrameLayout> layout =
media::VideoFrameLayout::CreateWithPlanes(
format, coded_size, std::move(planes), data.buffer_addr_align(),
data.modifier());
diff --git a/chromium/components/arc/mojom/video_accelerator_mojom_traits_unittest.cc b/chromium/components/arc/mojom/video_accelerator_mojom_traits_unittest.cc
index 1d69b7f2890..95afdd60668 100644
--- a/chromium/components/arc/mojom/video_accelerator_mojom_traits_unittest.cc
+++ b/chromium/components/arc/mojom/video_accelerator_mojom_traits_unittest.cc
@@ -31,7 +31,7 @@ TEST(VideoAcceleratorStructTraitsTest, ConvertVideoFrameLayout) {
constexpr size_t buffer_addr_align = 128;
constexpr uint64_t modifier = 0x1234;
- base::Optional<media::VideoFrameLayout> layout =
+ absl::optional<media::VideoFrameLayout> layout =
media::VideoFrameLayout::CreateWithPlanes(kFormat, kCodedSize, planes,
buffer_addr_align, modifier);
EXPECT_TRUE(layout);
diff --git a/chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.cc b/chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.cc
index 66984100974..7ae1f8bb516 100644
--- a/chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.cc
+++ b/chromium/components/arc/mojom/video_encode_accelerator_mojom_traits.cc
@@ -4,8 +4,8 @@
#include "components/arc/mojom/video_encode_accelerator_mojom_traits.h"
-#include "base/optional.h"
#include "components/arc/mojom/video_accelerator_mojom_traits.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace mojo {
@@ -83,12 +83,12 @@ bool StructTraits<arc::mojom::VideoEncodeAcceleratorConfigDataView,
if (!input.ReadOutputProfile(&output_profile))
return false;
- base::Optional<uint32_t> initial_framerate;
+ absl::optional<uint32_t> initial_framerate;
if (input.has_initial_framerate()) {
initial_framerate = input.initial_framerate();
}
- base::Optional<uint8_t> h264_output_level;
+ absl::optional<uint8_t> h264_output_level;
if (input.has_h264_output_level()) {
h264_output_level = input.h264_output_level();
}
@@ -99,7 +99,7 @@ bool StructTraits<arc::mojom::VideoEncodeAcceleratorConfigDataView,
*output = media::VideoEncodeAccelerator::Config(
input_format, input_visible_size, output_profile, input.initial_bitrate(),
- initial_framerate, base::nullopt, h264_output_level, false, storage_type);
+ initial_framerate, absl::nullopt, h264_output_level, false, storage_type);
return true;
}
diff --git a/chromium/components/arc/mojom/webapk.mojom b/chromium/components/arc/mojom/webapk.mojom
new file mode 100644
index 00000000000..a1fc76bf4e4
--- /dev/null
+++ b/chromium/components/arc/mojom/webapk.mojom
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Next MinVersion: 1
+
+module arc.mojom;
+
+[Extensible]
+enum WebApkInstallResult {
+ kSuccess = 0,
+ kErrorUnknown = 1,
+ // Errors while communicating with PlayInstallService.
+ kErrorServiceCommunication = 2,
+ kErrorServiceTimeout = 3,
+ // Errors returned from PlayInstallService directly.
+ kErrorCallerVerificationFailed = 4,
+ kErrorPolicyViolation = 5,
+ kErrorApiDisabled = 6,
+ kErrorUnknownAccount = 7,
+ kErrorResolveNetworkError = 8,
+ kErrorResolveError = 9,
+ kErrorNotGoogleSigned = 10,
+};
+
+// Allows Chrome to install and manage WebAPKs inside ARC.
+// Next method ID: 1
+interface WebApkInstance {
+
+ // Install or update a WebAPK with the given |package_name|.
+ InstallWebApk@0(string package_name,
+ uint32 version,
+ string app_name,
+ string token) =>
+ (WebApkInstallResult result);
+};
diff --git a/chromium/components/arc/net/DIR_METADATA b/chromium/components/arc/net/DIR_METADATA
deleted file mode 100644
index e568bf01ba6..00000000000
--- a/chromium/components/arc/net/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Platform>Apps>ARC"
-}
diff --git a/chromium/components/arc/net/always_on_vpn_manager.h b/chromium/components/arc/net/always_on_vpn_manager.h
index 528a93cd0b1..40c7a4429b4 100644
--- a/chromium/components/arc/net/always_on_vpn_manager.h
+++ b/chromium/components/arc/net/always_on_vpn_manager.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_ARC_NET_ALWAYS_ON_VPN_MANAGER_H_
#define COMPONENTS_ARC_NET_ALWAYS_ON_VPN_MANAGER_H_
-#include <string>
-
#include "base/macros.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
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 6690263c9a7..59ff37f5f2b 100644
--- a/chromium/components/arc/net/always_on_vpn_manager_unittest.cc
+++ b/chromium/components/arc/net/always_on_vpn_manager_unittest.cc
@@ -7,9 +7,8 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/values.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill/shill_manager_client.h"
-#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_handler_test_helper.h"
#include "components/arc/arc_prefs.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/test/browser_task_environment.h"
@@ -24,7 +23,7 @@ const base::Value kVpnPackageValue(kVpnPackage);
void OnGetProperties(bool* success_out,
std::string* package_name_out,
base::OnceClosure callback,
- base::Optional<base::Value> result) {
+ absl::optional<base::Value> result) {
*success_out = result.has_value();
if (result) {
const base::Value* value = result->FindKeyOfType(
@@ -39,7 +38,7 @@ std::string GetAlwaysOnPackageName() {
bool success = false;
std::string package_name;
chromeos::ShillManagerClient* shill_manager =
- chromeos::DBusThreadManager::Get()->GetShillManagerClient();
+ chromeos::ShillManagerClient::Get();
base::RunLoop run_loop;
shill_manager->GetProperties(
base::BindOnce(&OnGetProperties, base::Unretained(&success),
@@ -59,22 +58,14 @@ class AlwaysOnVpnManagerTest : public testing::Test {
AlwaysOnVpnManagerTest() = default;
void SetUp() override {
- chromeos::DBusThreadManager::Initialize();
- EXPECT_TRUE(chromeos::DBusThreadManager::Get()->IsUsingFakes());
- chromeos::NetworkHandler::Initialize();
- EXPECT_TRUE(chromeos::NetworkHandler::IsInitialized());
arc::prefs::RegisterProfilePrefs(pref_service()->registry());
}
- void TearDown() override {
- chromeos::NetworkHandler::Shutdown();
- chromeos::DBusThreadManager::Shutdown();
- }
-
TestingPrefServiceSimple* pref_service() { return &pref_service_; }
private:
content::BrowserTaskEnvironment task_environment_;
+ chromeos::NetworkHandlerTestHelper network_handler_test_helper_;
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 960609486c2..d91861ba7bf 100644
--- a/chromium/components/arc/net/arc_net_host_impl.cc
+++ b/chromium/components/arc/net/arc_net_host_impl.cc
@@ -18,6 +18,7 @@
#include "chromeos/network/managed_network_configuration_handler.h"
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_connection_handler.h"
+#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
@@ -226,8 +227,8 @@ arc::mojom::NetworkConfigurationPtr TranslateNetworkProperties(
if (const auto* device =
GetStateHandler()->GetDeviceState(network_state->device_path())) {
mojo->network_interface = device->interface();
- for (const auto& kv : device->ip_configs())
- AddIpConfiguration(mojo.get(), kv.second.get());
+ for (const auto& kv : device->ip_configs().DictItems())
+ AddIpConfiguration(mojo.get(), &kv.second);
}
if (shill_dict) {
@@ -524,20 +525,21 @@ void ArcNetHostImpl::CreateNetwork(mojom::WifiConfigurationPtr cfg,
base::Value(details->passphrase.value()));
}
}
- properties->SetWithoutPathExpansion(onc::network_config::kWiFi,
- std::move(wifi_dict));
+ properties->SetKey(onc::network_config::kWiFi,
+ base::Value::FromUniquePtrValue(std::move(wifi_dict)));
std::string user_id_hash = chromeos::LoginState::Get()->primary_user_hash();
- // TODO(crbug.com/730593): Remove AdaptCallbackForRepeating() by updating
+ // TODO(crbug.com/730593): Remove SplitOnceCallback() by updating
// the callee interface.
- auto repeating_callback =
- base::AdaptCallbackForRepeating(std::move(callback));
+ auto split_callback = base::SplitOnceCallback(std::move(callback));
GetManagedConfigurationHandler()->CreateConfiguration(
user_id_hash, *properties,
base::BindOnce(&ArcNetHostImpl::CreateNetworkSuccessCallback,
- weak_factory_.GetWeakPtr(), repeating_callback),
+ weak_factory_.GetWeakPtr(),
+ std::move(split_callback.first)),
base::BindOnce(&ArcNetHostImpl::CreateNetworkFailureCallback,
- weak_factory_.GetWeakPtr(), repeating_callback));
+ weak_factory_.GetWeakPtr(),
+ std::move(split_callback.second)));
}
bool ArcNetHostImpl::GetNetworkPathFromGuid(const std::string& guid,
@@ -573,13 +575,15 @@ void ArcNetHostImpl::ForgetNetwork(const std::string& guid,
}
cached_guid_.clear();
- // TODO(crbug.com/730593): Remove AdaptCallbackForRepeating() by updating
+ // TODO(crbug.com/730593): Remove SplitOnceCallback() by updating
// the callee interface.
- auto repeating_callback =
- base::AdaptCallbackForRepeating(std::move(callback));
+ auto split_callback = base::SplitOnceCallback(std::move(callback));
GetManagedConfigurationHandler()->RemoveConfiguration(
- path, base::BindOnce(&ForgetNetworkSuccessCallback, repeating_callback),
- base::BindOnce(&ForgetNetworkFailureCallback, repeating_callback));
+ path,
+ base::BindOnce(&ForgetNetworkSuccessCallback,
+ std::move(split_callback.first)),
+ base::BindOnce(&ForgetNetworkFailureCallback,
+ std::move(split_callback.second)));
}
void ArcNetHostImpl::StartConnect(const std::string& guid,
@@ -591,13 +595,15 @@ void ArcNetHostImpl::StartConnect(const std::string& guid,
return;
}
- // TODO(crbug.com/730593): Remove AdaptCallbackForRepeating() by updating
+ // TODO(crbug.com/730593): Remove SplitOnceCallback() by updating
// the callee interface.
- auto repeating_callback =
- base::AdaptCallbackForRepeating(std::move(callback));
+ auto split_callback = base::SplitOnceCallback(std::move(callback));
GetNetworkConnectionHandler()->ConnectToNetwork(
- path, base::BindOnce(&StartConnectSuccessCallback, repeating_callback),
- base::BindOnce(&StartConnectFailureCallback, repeating_callback),
+ path,
+ base::BindOnce(&StartConnectSuccessCallback,
+ std::move(split_callback.first)),
+ base::BindOnce(&StartConnectFailureCallback,
+ std::move(split_callback.second)),
false /* check_error_state */, chromeos::ConnectCallbackMode::ON_STARTED);
}
@@ -610,13 +616,15 @@ void ArcNetHostImpl::StartDisconnect(const std::string& guid,
return;
}
- // TODO(crbug.com/730593): Remove AdaptCallbackForRepeating() by updating
+ // TODO(crbug.com/730593): Remove SplitOnceCallback() by updating
// the callee interface.
- auto repeating_callback =
- base::AdaptCallbackForRepeating(std::move(callback));
+ auto split_callback = base::SplitOnceCallback(std::move(callback));
GetNetworkConnectionHandler()->DisconnectNetwork(
- path, base::BindOnce(&StartDisconnectSuccessCallback, repeating_callback),
- base::BindOnce(&StartDisconnectFailureCallback, repeating_callback));
+ path,
+ base::BindOnce(&StartDisconnectSuccessCallback,
+ std::move(split_callback.first)),
+ base::BindOnce(&StartDisconnectFailureCallback,
+ std::move(split_callback.second)));
}
void ArcNetHostImpl::GetWifiEnabledState(GetWifiEnabledStateCallback callback) {
@@ -639,6 +647,7 @@ void ArcNetHostImpl::SetWifiEnabledState(bool is_enabled,
return;
}
+ NET_LOG(USER) << __func__ << ":" << is_enabled;
GetStateHandler()->SetTechnologyEnabled(
chromeos::NetworkTypePattern::WiFi(), is_enabled,
chromeos::network_handler::ErrorCallback());
@@ -730,19 +739,21 @@ ArcNetHostImpl::TranslateVpnConfigurationToOnc(
ip_dict->SetKey(onc::ipconfig::kRoutingPrefix, base::Value(32));
ip_dict->SetKey(onc::ipconfig::kGateway, base::Value(cfg.ipv4_gateway));
- ip_dict->SetWithoutPathExpansion(onc::ipconfig::kNameServers,
- TranslateStringListToValue(cfg.nameservers));
- ip_dict->SetWithoutPathExpansion(onc::ipconfig::kSearchDomains,
- TranslateStringListToValue(cfg.domains));
- ip_dict->SetWithoutPathExpansion(
- onc::ipconfig::kIncludedRoutes,
- TranslateStringListToValue(cfg.split_include));
- ip_dict->SetWithoutPathExpansion(
- onc::ipconfig::kExcludedRoutes,
- TranslateStringListToValue(cfg.split_exclude));
-
- top_dict->SetWithoutPathExpansion(onc::network_config::kStaticIPConfig,
- std::move(ip_dict));
+ ip_dict->SetKey(onc::ipconfig::kNameServers,
+ base::Value::FromUniquePtrValue(
+ TranslateStringListToValue(cfg.nameservers)));
+ ip_dict->SetKey(
+ onc::ipconfig::kSearchDomains,
+ base::Value::FromUniquePtrValue(TranslateStringListToValue(cfg.domains)));
+ ip_dict->SetKey(onc::ipconfig::kIncludedRoutes,
+ base::Value::FromUniquePtrValue(
+ TranslateStringListToValue(cfg.split_include)));
+ ip_dict->SetKey(onc::ipconfig::kExcludedRoutes,
+ base::Value::FromUniquePtrValue(
+ TranslateStringListToValue(cfg.split_exclude)));
+
+ top_dict->SetKey(onc::network_config::kStaticIPConfig,
+ base::Value::FromUniquePtrValue(std::move(ip_dict)));
// VPN dictionary
std::unique_ptr<base::DictionaryValue> vpn_dict =
@@ -756,10 +767,11 @@ ArcNetHostImpl::TranslateVpnConfigurationToOnc(
arcvpn_dict->SetKey(
onc::arc_vpn::kTunnelChrome,
base::Value(cfg.tunnel_chrome_traffic ? "true" : "false"));
- vpn_dict->SetWithoutPathExpansion(onc::vpn::kArcVpn, std::move(arcvpn_dict));
+ vpn_dict->SetKey(onc::vpn::kArcVpn,
+ base::Value::FromUniquePtrValue(std::move(arcvpn_dict)));
- top_dict->SetWithoutPathExpansion(onc::network_config::kVPN,
- std::move(vpn_dict));
+ top_dict->SetKey(onc::network_config::kVPN,
+ base::Value::FromUniquePtrValue(std::move(vpn_dict)));
return top_dict;
}
@@ -865,7 +877,7 @@ void ArcNetHostImpl::NetworkPropertiesUpdated(
void ArcNetHostImpl::ReceiveShillProperties(
const std::string& service_path,
- base::Optional<base::Value> shill_properties) {
+ absl::optional<base::Value> shill_properties) {
if (!shill_properties) {
LOG(ERROR) << "Failed to get shill Service properties for " << service_path;
return;
diff --git a/chromium/components/arc/net/arc_net_host_impl.h b/chromium/components/arc/net/arc_net_host_impl.h
index 9663e7ac770..d590683ad48 100644
--- a/chromium/components/arc/net/arc_net_host_impl.h
+++ b/chromium/components/arc/net/arc_net_host_impl.h
@@ -151,7 +151,7 @@ class ArcNetHostImpl : public KeyedService,
// Callback for chromeos::NetworkHandler::GetShillProperties
void ReceiveShillProperties(const std::string& service_path,
- base::Optional<base::Value> shill_properties);
+ absl::optional<base::Value> shill_properties);
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
diff --git a/chromium/components/arc/pay/arc_payment_app_bridge.cc b/chromium/components/arc/pay/arc_payment_app_bridge.cc
index 33c435d0f2e..c869700d233 100644
--- a/chromium/components/arc/pay/arc_payment_app_bridge.cc
+++ b/chromium/components/arc/pay/arc_payment_app_bridge.cc
@@ -100,4 +100,16 @@ void ArcPaymentAppBridge::InvokePaymentApp(
payment_app->InvokePaymentApp(std::move(parameters), std::move(callback));
}
+void ArcPaymentAppBridge::AbortPaymentApp(const std::string& request_token,
+ AbortPaymentAppCallback callback) {
+ mojom::PaymentAppInstance* payment_app = ARC_GET_INSTANCE_FOR_METHOD(
+ arc_bridge_service_->payment_app(), AbortPaymentApp);
+ if (!payment_app) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ payment_app->AbortPaymentApp(request_token, std::move(callback));
+}
+
} // namespace arc
diff --git a/chromium/components/arc/pay/arc_payment_app_bridge.h b/chromium/components/arc/pay/arc_payment_app_bridge.h
index 2d8583bde78..d0b5c5581f7 100644
--- a/chromium/components/arc/pay/arc_payment_app_bridge.h
+++ b/chromium/components/arc/pay/arc_payment_app_bridge.h
@@ -28,6 +28,7 @@ class ArcPaymentAppBridge : public KeyedService {
base::OnceCallback<void(mojom::IsReadyToPayResultPtr)>;
using InvokePaymentAppCallback =
base::OnceCallback<void(mojom::InvokePaymentAppResultPtr)>;
+ using AbortPaymentAppCallback = base::OnceCallback<void(bool)>;
// Returns the instance owned by the given BrowserContext, or nullptr if the
// browser |context| is not allowed to use ARC.
@@ -60,6 +61,10 @@ class ArcPaymentAppBridge : public KeyedService {
void InvokePaymentApp(mojom::PaymentParametersPtr parameters,
InvokePaymentAppCallback callback);
+ // Aborts an existing TWA payment app flow.
+ void AbortPaymentApp(const std::string& request_token,
+ AbortPaymentAppCallback callback);
+
private:
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
};
diff --git a/chromium/components/arc/pay/arc_payment_app_bridge_unittest.cc b/chromium/components/arc/pay/arc_payment_app_bridge_unittest.cc
index 57876c4ec2b..2017520e03d 100644
--- a/chromium/components/arc/pay/arc_payment_app_bridge_unittest.cc
+++ b/chromium/components/arc/pay/arc_payment_app_bridge_unittest.cc
@@ -13,6 +13,7 @@
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
namespace {
@@ -39,10 +40,13 @@ class ArcPaymentAppBridgeTest : public testing::Test {
invoke_app_ = std::move(response);
}
+ void OnAbortPaymentAppResponse(bool response) { abort_app_ = response; }
+
ArcPaymentAppBridgeTestSupport support_;
mojom::IsPaymentImplementedResultPtr is_implemented_;
mojom::IsReadyToPayResultPtr is_ready_to_pay_;
mojom::InvokePaymentAppResultPtr invoke_app_;
+ absl::optional<bool> abort_app_;
};
TEST_F(ArcPaymentAppBridgeTest, UnableToConnectInIsImplemented) {
@@ -305,5 +309,41 @@ TEST_F(ArcPaymentAppBridgeTest, InvokePaymentAppError) {
EXPECT_EQ("Error message.", invoke_app_->get_error());
}
+TEST_F(ArcPaymentAppBridgeTest, UnableToConnectAbortPaymentApp) {
+ // Intentionally do not set an instance.
+
+ EXPECT_CALL(*support_.instance(), AbortPaymentApp(testing::_, testing::_))
+ .Times(0);
+
+ ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context())
+ ->AbortPaymentApp(
+ "some token",
+ base::BindOnce(&ArcPaymentAppBridgeTest::OnAbortPaymentAppResponse,
+ base::Unretained(this)));
+
+ ASSERT_TRUE(abort_app_.has_value());
+ ASSERT_FALSE(abort_app_.value());
+}
+
+TEST_F(ArcPaymentAppBridgeTest, AbortPaymentAppOK) {
+ auto scoped_set_instance = support_.CreateScopedSetInstance();
+
+ EXPECT_CALL(*support_.instance(), AbortPaymentApp(testing::_, testing::_))
+ .WillOnce(testing::Invoke(
+ [](const std::string& request_token,
+ ArcPaymentAppBridge::AbortPaymentAppCallback callback) {
+ std::move(callback).Run(true);
+ }));
+
+ ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context())
+ ->AbortPaymentApp(
+ "some token",
+ base::BindOnce(&ArcPaymentAppBridgeTest::OnAbortPaymentAppResponse,
+ base::Unretained(this)));
+
+ ASSERT_TRUE(abort_app_.has_value());
+ ASSERT_TRUE(abort_app_.value());
+}
+
} // namespace
} // namespace arc
diff --git a/chromium/components/arc/power/arc_power_bridge.cc b/chromium/components/arc/power/arc_power_bridge.cc
index 143acbdfc17..6f7899c56d1 100644
--- a/chromium/components/arc/power/arc_power_bridge.cc
+++ b/chromium/components/arc/power/arc_power_bridge.cc
@@ -12,7 +12,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power/power_policy_controller.h"
#include "chromeos/dbus/power_manager/backlight.pb.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
@@ -201,7 +200,7 @@ void ArcPowerBridge::OnAndroidSuspendReady(base::UnguessableToken token) {
vm_tools::concierge::SuspendVmRequest request;
request.set_name(kArcVmName);
request.set_owner_id(user_id_hash_);
- chromeos::DBusThreadManager::Get()->GetConciergeClient()->SuspendVm(
+ chromeos::ConciergeClient::Get()->SuspendVm(
request, base::BindOnce(&ArcPowerBridge::OnConciergeSuspendVmResponse,
weak_ptr_factory_.GetWeakPtr(), token));
return;
@@ -212,7 +211,7 @@ void ArcPowerBridge::OnAndroidSuspendReady(base::UnguessableToken token) {
void ArcPowerBridge::OnConciergeSuspendVmResponse(
base::UnguessableToken token,
- base::Optional<vm_tools::concierge::SuspendVmResponse> reply) {
+ absl::optional<vm_tools::concierge::SuspendVmResponse> reply) {
if (!reply.has_value())
LOG(ERROR) << "Failed to suspend arcvm, no reply received.";
else if (!reply.value().success())
@@ -226,7 +225,7 @@ void ArcPowerBridge::SuspendDone(base::TimeDelta sleep_duration) {
vm_tools::concierge::ResumeVmRequest request;
request.set_name(kArcVmName);
request.set_owner_id(user_id_hash_);
- chromeos::DBusThreadManager::Get()->GetConciergeClient()->ResumeVm(
+ chromeos::ConciergeClient::Get()->ResumeVm(
request, base::BindOnce(&ArcPowerBridge::OnConciergeResumeVmResponse,
weak_ptr_factory_.GetWeakPtr()));
return;
@@ -235,7 +234,7 @@ void ArcPowerBridge::SuspendDone(base::TimeDelta sleep_duration) {
}
void ArcPowerBridge::OnConciergeResumeVmResponse(
- base::Optional<vm_tools::concierge::ResumeVmResponse> reply) {
+ absl::optional<vm_tools::concierge::ResumeVmResponse> reply) {
if (!reply.has_value()) {
LOG(ERROR) << "Failed to resume arcvm, no reply received.";
return;
@@ -365,7 +364,7 @@ ArcPowerBridge::WakeLockRequestor* ArcPowerBridge::GetWakeLockRequestor(
}
void ArcPowerBridge::OnGetScreenBrightnessPercent(
- base::Optional<double> percent) {
+ absl::optional<double> percent) {
if (!percent.has_value()) {
LOG(ERROR)
<< "PowerManagerClient::GetScreenBrightnessPercent reports an error";
diff --git a/chromium/components/arc/power/arc_power_bridge.h b/chromium/components/arc/power/arc_power_bridge.h
index a01f714400f..f3ea6dac9ac 100644
--- a/chromium/components/arc/power/arc_power_bridge.h
+++ b/chromium/components/arc/power/arc_power_bridge.h
@@ -11,9 +11,8 @@
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/timer/timer.h"
-#include "chromeos/dbus/concierge_client.h"
+#include "chromeos/dbus/concierge/concierge_client.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "components/arc/mojom/power.mojom.h"
#include "components/arc/session/connection_observer.h"
@@ -21,6 +20,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/wake_lock.mojom.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/display/manager/display_configurator.h"
namespace content {
@@ -99,7 +99,7 @@ class ArcPowerBridge : public KeyedService,
WakeLockRequestor* GetWakeLockRequestor(device::mojom::WakeLockType type);
// Called on PowerManagerClient::GetScreenBrightnessPercent() completion.
- void OnGetScreenBrightnessPercent(base::Optional<double> percent);
+ void OnGetScreenBrightnessPercent(absl::optional<double> percent);
// Called by Android when ready to suspend.
void OnAndroidSuspendReady(base::UnguessableToken token);
@@ -108,12 +108,12 @@ class ArcPowerBridge : public KeyedService,
// SuspendVm D-Bus call.
void OnConciergeSuspendVmResponse(
base::UnguessableToken token,
- base::Optional<vm_tools::concierge::SuspendVmResponse> reply);
+ absl::optional<vm_tools::concierge::SuspendVmResponse> reply);
// Called by ConciergeClient when a response has been receive for the
// ResumeVm D-Bus call.
void OnConciergeResumeVmResponse(
- base::Optional<vm_tools::concierge::ResumeVmResponse> reply);
+ absl::optional<vm_tools::concierge::ResumeVmResponse> reply);
// Sends a PowerInstance::UpdateScreenBrightnessSettings mojo call to Android.
void UpdateAndroidScreenBrightness(double percent);
diff --git a/chromium/components/arc/power/arc_power_bridge_unittest.cc b/chromium/components/arc/power/arc_power_bridge_unittest.cc
index 8aba24cdb65..fdf2249bbba 100644
--- a/chromium/components/arc/power/arc_power_bridge_unittest.cc
+++ b/chromium/components/arc/power/arc_power_bridge_unittest.cc
@@ -225,7 +225,7 @@ TEST_F(ArcPowerBridgeTest, ScreenBrightness) {
}
TEST_F(ArcPowerBridgeTest, PowerSupplyInfoChanged) {
- base::Optional<power_manager::PowerSupplyProperties> prop =
+ absl::optional<power_manager::PowerSupplyProperties> prop =
power_manager_client()->GetLastStatus();
ASSERT_TRUE(prop.has_value());
prop->set_battery_state(power_manager::PowerSupplyProperties::FULL);
diff --git a/chromium/components/arc/property/arc_property_bridge_unittest.cc b/chromium/components/arc/property/arc_property_bridge_unittest.cc
index b9a48e29209..a4c8d9d1833 100644
--- a/chromium/components/arc/property/arc_property_bridge_unittest.cc
+++ b/chromium/components/arc/property/arc_property_bridge_unittest.cc
@@ -31,10 +31,10 @@ class FakePropertyInstance : public mojom::PropertyInstance {
minimize_on_back_ = enable;
}
- base::Optional<bool> minimize_on_back() const { return minimize_on_back_; }
+ absl::optional<bool> minimize_on_back() const { return minimize_on_back_; }
private:
- base::Optional<bool> minimize_on_back_;
+ absl::optional<bool> minimize_on_back_;
};
} // namespace
@@ -76,7 +76,7 @@ class ArcPropertyBridgeTest : public testing::Test {
instance_ = nullptr;
}
- base::Optional<bool> GetMinimizeOnBackState() const {
+ absl::optional<bool> GetMinimizeOnBackState() const {
return instance_->minimize_on_back();
}
diff --git a/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.cc b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.cc
index 1019291a617..bc80a2f7c83 100644
--- a/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.cc
+++ b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.cc
@@ -43,6 +43,12 @@ ArcRotationLockBridge* ArcRotationLockBridge::GetForBrowserContext(
return ArcRotationLockBridgeFactory::GetForBrowserContext(context);
}
+// static
+ArcRotationLockBridge* ArcRotationLockBridge::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcRotationLockBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
ArcRotationLockBridge::ArcRotationLockBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service) {
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 30128e2fa4f..4bb28470df4 100644
--- a/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h
+++ b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge.h
@@ -33,6 +33,8 @@ class ArcRotationLockBridge
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcRotationLockBridge* GetForBrowserContext(
content::BrowserContext* context);
+ static ArcRotationLockBridge* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
ArcRotationLockBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service);
diff --git a/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge_unittest.cc b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge_unittest.cc
new file mode 100644
index 00000000000..6e0c9acae03
--- /dev/null
+++ b/chromium/components/arc/rotation_lock/arc_rotation_lock_bridge_unittest.cc
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/rotation_lock/arc_rotation_lock_bridge.h"
+
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/test/test_browser_context.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcRotationLockBridgeTest : public testing::Test {
+ protected:
+ ArcRotationLockBridgeTest()
+ : bridge_(
+ ArcRotationLockBridge::GetForBrowserContextForTesting(&context_)) {}
+ ArcRotationLockBridgeTest(const ArcRotationLockBridgeTest&) = delete;
+ ArcRotationLockBridgeTest& operator=(const ArcRotationLockBridgeTest&) =
+ delete;
+ ~ArcRotationLockBridgeTest() override = default;
+
+ ArcRotationLockBridge* bridge() { return bridge_; }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ ArcServiceManager arc_service_manager_;
+ TestBrowserContext context_;
+ ArcRotationLockBridge* const bridge_;
+};
+
+TEST_F(ArcRotationLockBridgeTest, ConstructDestruct) {
+ EXPECT_NE(nullptr, bridge());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/sensor/arc_iio_sensor_bridge.cc b/chromium/components/arc/sensor/arc_iio_sensor_bridge.cc
index 7f651f88ebb..57c22f04c6a 100644
--- a/chromium/components/arc/sensor/arc_iio_sensor_bridge.cc
+++ b/chromium/components/arc/sensor/arc_iio_sensor_bridge.cc
@@ -91,7 +91,7 @@ void ArcIioSensorBridge::SetIsTabletModeOn(bool is_tablet_mode_on) {
}
void ArcIioSensorBridge::OnGetSwitchStates(
- base::Optional<chromeos::PowerManagerClient::SwitchStates> states) {
+ absl::optional<chromeos::PowerManagerClient::SwitchStates> states) {
if (states.has_value()) {
SetIsTabletModeOn(states->tablet_mode ==
chromeos::PowerManagerClient::TabletMode::ON);
diff --git a/chromium/components/arc/sensor/arc_iio_sensor_bridge.h b/chromium/components/arc/sensor/arc_iio_sensor_bridge.h
index 9a2d6cde115..2ddca326318 100644
--- a/chromium/components/arc/sensor/arc_iio_sensor_bridge.h
+++ b/chromium/components/arc/sensor/arc_iio_sensor_bridge.h
@@ -6,11 +6,11 @@
#define COMPONENTS_ARC_SENSOR_ARC_IIO_SENSOR_BRIDGE_H_
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "components/arc/mojom/iio_sensor.mojom.h"
#include "components/arc/session/connection_observer.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class BrowserContext;
@@ -58,10 +58,10 @@ class ArcIioSensorBridge : public KeyedService,
// Called with PowerManagerClient::GetSwitchStates() result.
void OnGetSwitchStates(
- base::Optional<chromeos::PowerManagerClient::SwitchStates> states);
+ absl::optional<chromeos::PowerManagerClient::SwitchStates> states);
ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
- base::Optional<bool> is_tablet_mode_on_;
+ absl::optional<bool> is_tablet_mode_on_;
base::WeakPtrFactory<ArcIioSensorBridge> weak_ptr_factory_{this};
};
diff --git a/chromium/components/arc/session/OWNERS b/chromium/components/arc/session/OWNERS
index 868d4207dd8..eb39984483f 100644
--- a/chromium/components/arc/session/OWNERS
+++ b/chromium/components/arc/session/OWNERS
@@ -1,4 +1,3 @@
-ereth@chromium.org
lgcheng@google.com
# backup reviewers
hashimoto@chromium.org
diff --git a/chromium/components/arc/session/arc_bridge_host_impl.cc b/chromium/components/arc/session/arc_bridge_host_impl.cc
index f3b4fb85e5a..9cec61a47f6 100644
--- a/chromium/components/arc/session/arc_bridge_host_impl.cc
+++ b/chromium/components/arc/session/arc_bridge_host_impl.cc
@@ -33,6 +33,7 @@
#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/iio_sensor.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"
@@ -68,6 +69,7 @@
#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/mojom/webapk.mojom.h"
#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/session/mojo_channel.h"
@@ -428,6 +430,11 @@ void ArcBridgeHostImpl::OnWallpaperInstanceReady(
std::move(wallpaper_remote));
}
+void ArcBridgeHostImpl::OnWebApkInstanceReady(
+ mojo::PendingRemote<mojom::WebApkInstance> webapk_remote) {
+ OnInstanceReady(arc_bridge_service_->webapk(), std::move(webapk_remote));
+}
+
size_t ArcBridgeHostImpl::GetNumMojoChannelsForTesting() const {
return mojo_channels_.size();
}
diff --git a/chromium/components/arc/session/arc_bridge_host_impl.h b/chromium/components/arc/session/arc_bridge_host_impl.h
index 02dc6e0f113..ea63b0ef4af 100644
--- a/chromium/components/arc/session/arc_bridge_host_impl.h
+++ b/chromium/components/arc/session/arc_bridge_host_impl.h
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "components/arc/mojom/arc_bridge.mojom.h"
+#include "components/arc/session/arc_bridge_service.h"
#include "components/arc/session/connection_holder.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -176,6 +177,8 @@ class ArcBridgeHostImpl : public mojom::ArcBridgeHost {
mojo::PendingRemote<mojom::WakeLockInstance> wake_lock_remote) override;
void OnWallpaperInstanceReady(
mojo::PendingRemote<mojom::WallpaperInstance> wallpaper_remote) override;
+ void OnWebApkInstanceReady(
+ mojo::PendingRemote<mojom::WebApkInstance> webapk_remote) override;
size_t GetNumMojoChannelsForTesting() const;
diff --git a/chromium/components/arc/session/arc_bridge_service.h b/chromium/components/arc/session/arc_bridge_service.h
index 48525a1b552..5172090ba13 100644
--- a/chromium/components/arc/session/arc_bridge_service.h
+++ b/chromium/components/arc/session/arc_bridge_service.h
@@ -111,6 +111,7 @@ class WakeLockHost;
class WakeLockInstance;
class WallpaperHost;
class WallpaperInstance;
+class WebApkInstance;
} // namespace mojom
// Holds Mojo channels which proxy to ARC side implementation. The actual
@@ -318,6 +319,7 @@ class ArcBridgeService {
wallpaper() {
return &wallpaper_;
}
+ ConnectionHolder<mojom::WebApkInstance>* webapk() { return &webapk_; }
private:
base::ObserverList<Observer> observer_list_;
@@ -394,6 +396,7 @@ class ArcBridgeService {
volume_mounter_;
ConnectionHolder<mojom::WakeLockInstance, mojom::WakeLockHost> wake_lock_;
ConnectionHolder<mojom::WallpaperInstance, mojom::WallpaperHost> wallpaper_;
+ ConnectionHolder<mojom::WebApkInstance> webapk_;
DISALLOW_COPY_AND_ASSIGN(ArcBridgeService);
};
diff --git a/chromium/components/arc/session/arc_bridge_service_unittest.cc b/chromium/components/arc/session/arc_bridge_service_unittest.cc
new file mode 100644
index 00000000000..80c2c1c3534
--- /dev/null
+++ b/chromium/components/arc/session/arc_bridge_service_unittest.cc
@@ -0,0 +1,45 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/session/arc_bridge_service.h"
+
+#include "base/scoped_observation.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcBridgeServiceTest : public testing::Test,
+ public ArcBridgeService::Observer {
+ public:
+ ArcBridgeServiceTest() = default;
+ ArcBridgeServiceTest(const ArcBridgeServiceTest&) = delete;
+ ArcBridgeServiceTest& operator=(const ArcBridgeServiceTest&) = delete;
+ ~ArcBridgeServiceTest() override = default;
+
+ // ArcBridgeService::Observer overrides:
+ void BeforeArcBridgeClosed() override { ++num_before_called_; }
+ void AfterArcBridgeClosed() override { ++num_after_called_; }
+
+ protected:
+ ArcBridgeService bridge_;
+ size_t num_before_called_ = 0;
+ size_t num_after_called_ = 0;
+};
+
+TEST_F(ArcBridgeServiceTest, Observers) {
+ base::ScopedObservation<ArcBridgeService, ArcBridgeService::Observer>
+ bridge_observation(this);
+ bridge_observation.Observe(&bridge_);
+ EXPECT_EQ(0u, num_before_called_);
+ bridge_.ObserveBeforeArcBridgeClosed();
+ EXPECT_EQ(1u, num_before_called_);
+ EXPECT_EQ(0u, num_after_called_);
+ bridge_.ObserveAfterArcBridgeClosed();
+ EXPECT_EQ(1u, num_before_called_); // this should not change
+ EXPECT_EQ(1u, num_after_called_);
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/session/arc_client_adapter.h b/chromium/components/arc/session/arc_client_adapter.h
index 359ac44498c..d8af3b9ce34 100644
--- a/chromium/components/arc/session/arc_client_adapter.h
+++ b/chromium/components/arc/session/arc_client_adapter.h
@@ -28,12 +28,12 @@ class ArcClientAdapter {
class Observer {
public:
virtual ~Observer() = default;
- virtual void ArcInstanceStopped() = 0;
+ virtual void ArcInstanceStopped(bool is_system_shutdown) = 0;
};
// DemoModeDelegate contains functions used to load the demo session apps for
- // ARC. The adapter cannot do this directly because chromeos::DemoSession
- // classes are in //chrome.
+ // ARC. The adapter cannot do this directly because ash::DemoSession classes
+ // are in //chrome.
class DemoModeDelegate {
public:
virtual ~DemoModeDelegate() = default;
@@ -75,6 +75,12 @@ class ArcClientAdapter {
// apps path.
virtual void SetDemoModeDelegate(DemoModeDelegate* delegate) = 0;
+ // Trims VM's memory by moving it to zram. |callback| is called when the
+ // operation is done.
+ using TrimVmMemoryCallback =
+ base::OnceCallback<void(bool success, const std::string& failure_reason)>;
+ virtual void TrimVmMemory(TrimVmMemoryCallback callback) = 0;
+
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
diff --git a/chromium/components/arc/session/arc_client_adapter_unittest.cc b/chromium/components/arc/session/arc_client_adapter_unittest.cc
new file mode 100644
index 00000000000..3fddb4b0d3a
--- /dev/null
+++ b/chromium/components/arc/session/arc_client_adapter_unittest.cc
@@ -0,0 +1,64 @@
+// Copyright 2021 The Chromium Authors. 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_client_adapter.h"
+
+#include <memory>
+
+#include "base/command_line.h"
+#include "base/scoped_observation.h"
+#include "chromeos/dbus/concierge/concierge_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
+#include "chromeos/dbus/upstart/fake_upstart_client.h"
+#include "components/arc/arc_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcClientAdapterTest : public testing::Test,
+ public ArcClientAdapter::Observer {
+ public:
+ ArcClientAdapterTest() = default;
+ ArcClientAdapterTest(const ArcClientAdapterTest&) = delete;
+ ArcClientAdapterTest& operator=(const ArcClientAdapterTest&) = delete;
+ ~ArcClientAdapterTest() override = default;
+
+ // ArcClientAdapter::Observer overrides:
+ void ArcInstanceStopped(bool is_system_shutdown) override {}
+
+ void SetUp() override {
+ chromeos::DBusThreadManager::Initialize();
+ chromeos::DBusThreadManager::GetSetterForTesting()->SetDebugDaemonClient(
+ std::make_unique<chromeos::FakeDebugDaemonClient>());
+ chromeos::ConciergeClient::InitializeFake(/*fake_cicerone_client=*/nullptr);
+ chromeos::UpstartClient::InitializeFake();
+ }
+ void TearDown() override {
+ chromeos::ConciergeClient::Shutdown();
+ chromeos::DBusThreadManager::Shutdown();
+ }
+};
+
+TEST_F(ArcClientAdapterTest, ConstructDestruct) {
+ auto adapter = ArcClientAdapter::Create();
+ base::ScopedObservation<ArcClientAdapter, ArcClientAdapter::Observer>
+ adapter_observation(this);
+ adapter_observation.Observe(adapter.get());
+}
+
+TEST_F(ArcClientAdapterTest, ConstructDestruct_WithARCVM) {
+ auto* command_line = base::CommandLine::ForCurrentProcess();
+ command_line->InitFromArgv({"", "--enable-arcvm"});
+ ASSERT_TRUE(IsArcVmEnabled());
+
+ auto vm_adapter = ArcClientAdapter::Create();
+ base::ScopedObservation<ArcClientAdapter, ArcClientAdapter::Observer>
+ vm_adapter_observation(this);
+ vm_adapter_observation.Observe(vm_adapter.get());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/session/arc_container_client_adapter.cc b/chromium/components/arc/session/arc_container_client_adapter.cc
index 5308084620d..5e677ed0cf9 100644
--- a/chromium/components/arc/session/arc_container_client_adapter.cc
+++ b/chromium/components/arc/session/arc_container_client_adapter.cc
@@ -10,6 +10,8 @@
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/notreached.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/dbus_method_call_status.h"
#include "chromeos/dbus/login_manager/arc.pb.h"
@@ -35,18 +37,21 @@ ToLoginManagerPackageCacheMode(UpgradeParams::PackageCacheMode mode) {
}
// Converts ArcSupervisionTransition into login_manager's.
-login_manager::UpgradeArcContainerRequest_SupervisionTransition
-ToLoginManagerSupervisionTransition(ArcSupervisionTransition transition) {
+login_manager::UpgradeArcContainerRequest_ManagementTransition
+ToLoginManagerManagementTransition(ArcSupervisionTransition transition) {
switch (transition) {
case ArcSupervisionTransition::NO_TRANSITION:
return login_manager::
- UpgradeArcContainerRequest_SupervisionTransition_NONE;
+ UpgradeArcContainerRequest_ManagementTransition_NONE;
case ArcSupervisionTransition::CHILD_TO_REGULAR:
return login_manager::
- UpgradeArcContainerRequest_SupervisionTransition_CHILD_TO_REGULAR;
+ UpgradeArcContainerRequest_ManagementTransition_CHILD_TO_REGULAR;
case ArcSupervisionTransition::REGULAR_TO_CHILD:
return login_manager::
- UpgradeArcContainerRequest_SupervisionTransition_REGULAR_TO_CHILD;
+ UpgradeArcContainerRequest_ManagementTransition_REGULAR_TO_CHILD;
+ case ArcSupervisionTransition::UNMANAGED_TO_MANAGED:
+ return login_manager::
+ UpgradeArcContainerRequest_ManagementTransition_UNMANAGED_TO_MANAGED;
}
}
@@ -152,8 +157,8 @@ class ArcContainerClientAdapter
request.set_locale(params.locale);
for (const auto& language : params.preferred_languages)
request.add_preferred_languages(language);
- request.set_supervision_transition(
- ToLoginManagerSupervisionTransition(params.supervision_transition));
+ request.set_management_transition(
+ ToLoginManagerManagementTransition(params.supervision_transition));
chromeos::SessionManagerClient::Get()->UpgradeArcContainer(
request, std::move(callback));
@@ -179,10 +184,23 @@ class ArcContainerClientAdapter
// UpgradeParams, so it does not use the DemoModeDelegate.
void SetDemoModeDelegate(DemoModeDelegate* delegate) override {}
+ // The interface is only for ARCVM.
+ void TrimVmMemory(TrimVmMemoryCallback callback) override {
+ NOTREACHED();
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback), /*success=*/true,
+ /*failure_reason=*/"ARC container is not supported."));
+ }
+
// chromeos::SessionManagerClient::Observer overrides:
- void ArcInstanceStopped() override {
+ void ArcInstanceStopped(
+ login_manager::ArcContainerStopReason reason) override {
+ const bool is_system_shutdown =
+ reason ==
+ login_manager::ArcContainerStopReason::SESSION_MANAGER_SHUTDOWN;
for (auto& observer : observer_list_)
- observer.ArcInstanceStopped();
+ observer.ArcInstanceStopped(is_system_shutdown);
}
private:
diff --git a/chromium/components/arc/session/arc_container_client_adapter_unittest.cc b/chromium/components/arc/session/arc_container_client_adapter_unittest.cc
index 26c8cd89de1..5195ff1ce2f 100644
--- a/chromium/components/arc/session/arc_container_client_adapter_unittest.cc
+++ b/chromium/components/arc/session/arc_container_client_adapter_unittest.cc
@@ -14,7 +14,8 @@ namespace arc {
namespace {
-class ArcContainerClientAdapterTest : public testing::Test {
+class ArcContainerClientAdapterTest : public testing::Test,
+ public ArcClientAdapter::Observer {
public:
ArcContainerClientAdapterTest() = default;
~ArcContainerClientAdapterTest() override = default;
@@ -25,6 +26,7 @@ class ArcContainerClientAdapterTest : public testing::Test {
void SetUp() override {
chromeos::SessionManagerClient::InitializeFake();
client_adapter_ = CreateArcContainerClientAdapter();
+ client_adapter_->AddObserver(this);
chromeos::FakeSessionManagerClient::Get()->set_arc_available(true);
}
@@ -33,18 +35,42 @@ class ArcContainerClientAdapterTest : public testing::Test {
chromeos::SessionManagerClient::Shutdown();
}
+ // ArcClientAdapter::Observer:
+ void ArcInstanceStopped(bool is_system_shutdown) override {
+ is_system_shutdown_ = is_system_shutdown;
+ }
+
protected:
ArcClientAdapter* client_adapter() { return client_adapter_.get(); }
+ const absl::optional<bool>& is_system_shutdown() const {
+ return is_system_shutdown_;
+ }
+
private:
std::unique_ptr<ArcClientAdapter> client_adapter_;
content::BrowserTaskEnvironment browser_task_environment_;
+ absl::optional<bool> is_system_shutdown_;
};
void OnMiniInstanceStarted(bool result) {
DCHECK(result);
}
+TEST_F(ArcContainerClientAdapterTest, ArcInstanceStopped) {
+ chromeos::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
+ login_manager::ArcContainerStopReason::USER_REQUEST);
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_FALSE(is_system_shutdown().value());
+}
+
+TEST_F(ArcContainerClientAdapterTest, ArcInstanceStoppedSystemShutdown) {
+ chromeos::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
+ login_manager::ArcContainerStopReason::SESSION_MANAGER_SHUTDOWN);
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_TRUE(is_system_shutdown().value());
+}
+
// b/164816080 This test ensures that a new container instance that is
// created while handling the shutting down of the previous instance,
// doesn't incorrectly receive the shutdown event as well.
@@ -65,7 +91,7 @@ TEST_F(ArcContainerClientAdapterTest,
bool stopped_called() const { return stopped_called_; }
// ArcClientAdapter::Observer:
- void ArcInstanceStopped() override {
+ void ArcInstanceStopped(bool is_system_shutdown) override {
stopped_called_ = true;
if (child_observer_) {
@@ -89,7 +115,8 @@ TEST_F(ArcContainerClientAdapterTest,
},
client_adapter(), &parent_observer));
- chromeos::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped();
+ chromeos::FakeSessionManagerClient::Get()->NotifyArcInstanceStopped(
+ login_manager::ArcContainerStopReason::USER_REQUEST);
EXPECT_TRUE(parent_observer.stopped_called());
EXPECT_FALSE(child_observer.stopped_called());
diff --git a/chromium/components/arc/session/arc_data_remover.cc b/chromium/components/arc/session/arc_data_remover.cc
index b1cc83cb809..eb968b1dced 100644
--- a/chromium/components/arc/session/arc_data_remover.cc
+++ b/chromium/components/arc/session/arc_data_remover.cc
@@ -41,7 +41,7 @@ void ArcDataRemover::Run(RunCallback callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!pref_.GetValue()) {
VLOG(1) << "Data removal is not scheduled, skip.";
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
return;
}
@@ -49,7 +49,7 @@ void ArcDataRemover::Run(RunCallback callback) {
auto* upstart_client = chromeos::UpstartClient::Get();
if (!upstart_client) {
// May be null in tests
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
return;
}
const std::string account_id =
diff --git a/chromium/components/arc/session/arc_data_remover.h b/chromium/components/arc/session/arc_data_remover.h
index c18a823eb94..fbc1ca2abdf 100644
--- a/chromium/components/arc/session/arc_data_remover.h
+++ b/chromium/components/arc/session/arc_data_remover.h
@@ -8,10 +8,10 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "components/prefs/pref_member.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
@@ -34,7 +34,7 @@ class ArcDataRemover {
// Executes the removing, if scheduled.
// This must run while ARC instance is stopped.
// If not scheduled, |callback| will be synchronously called with nullopt.
- using RunCallback = base::OnceCallback<void(base::Optional<bool> result)>;
+ using RunCallback = base::OnceCallback<void(absl::optional<bool> result)>;
void Run(RunCallback callback);
private:
diff --git a/chromium/components/arc/session/arc_data_remover_unittest.cc b/chromium/components/arc/session/arc_data_remover_unittest.cc
index 51f8851e409..91ece3500aa 100644
--- a/chromium/components/arc/session/arc_data_remover_unittest.cc
+++ b/chromium/components/arc/session/arc_data_remover_unittest.cc
@@ -83,8 +83,8 @@ TEST_F(ArcDataRemoverTest, NotScheduled) {
base::RunLoop loop;
data_remover.Run(base::BindOnce(
- [](base::RunLoop* loop, base::Optional<bool> result) {
- EXPECT_EQ(result, base::nullopt);
+ [](base::RunLoop* loop, absl::optional<bool> result) {
+ EXPECT_EQ(result, absl::nullopt);
loop->Quit();
},
&loop));
@@ -99,8 +99,8 @@ TEST_F(ArcDataRemoverTest, Success) {
base::RunLoop loop;
data_remover.Run(base::BindOnce(
- [](base::RunLoop* loop, base::Optional<bool> result) {
- EXPECT_EQ(result, base::make_optional(true));
+ [](base::RunLoop* loop, absl::optional<bool> result) {
+ EXPECT_EQ(result, absl::make_optional(true));
loop->Quit();
},
&loop));
@@ -113,8 +113,8 @@ TEST_F(ArcDataRemoverTest, Fail) {
base::RunLoop loop;
data_remover.Run(base::BindOnce(
- [](base::RunLoop* loop, base::Optional<bool> result) {
- EXPECT_EQ(result, base::make_optional(false));
+ [](base::RunLoop* loop, absl::optional<bool> result) {
+ EXPECT_EQ(result, absl::make_optional(false));
loop->Quit();
},
&loop));
diff --git a/chromium/components/arc/session/arc_instance_mode.cc b/chromium/components/arc/session/arc_instance_mode.cc
index f43bbd8bf66..26a4793af5e 100644
--- a/chromium/components/arc/session/arc_instance_mode.cc
+++ b/chromium/components/arc/session/arc_instance_mode.cc
@@ -35,7 +35,7 @@ std::ostream& operator<<(std::ostream& os, ArcInstanceMode mode) {
}
std::ostream& operator<<(std::ostream& os,
- base::Optional<ArcInstanceMode> mode) {
+ absl::optional<ArcInstanceMode> mode) {
return os << (mode.has_value() ? ArcInstanceModeToString(mode.value())
: "(nullopt)");
}
diff --git a/chromium/components/arc/session/arc_instance_mode.h b/chromium/components/arc/session/arc_instance_mode.h
index b8d3bc54fe0..cf04a56dcca 100644
--- a/chromium/components/arc/session/arc_instance_mode.h
+++ b/chromium/components/arc/session/arc_instance_mode.h
@@ -7,7 +7,7 @@
#include <ostream>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
@@ -23,7 +23,7 @@ enum class ArcInstanceMode {
// Stringified output for logging purpose.
std::ostream& operator<<(std::ostream& os, ArcInstanceMode mode);
std::ostream& operator<<(std::ostream& os,
- base::Optional<ArcInstanceMode> mode);
+ absl::optional<ArcInstanceMode> mode);
} // namespace arc
diff --git a/chromium/components/arc/session/arc_instance_mode_unittest.cc b/chromium/components/arc/session/arc_instance_mode_unittest.cc
index 88c3dc0883b..67d5386b7f3 100644
--- a/chromium/components/arc/session/arc_instance_mode_unittest.cc
+++ b/chromium/components/arc/session/arc_instance_mode_unittest.cc
@@ -6,8 +6,8 @@
#include <sstream>
-#include "base/optional.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
namespace {
@@ -28,14 +28,14 @@ TEST(ArcInstanceModeTest, TestLogging) {
EXPECT_TRUE(invalid.str().empty()) << invalid.str();
}
-// Test that base::Optional<ArcInstanceMode> can be logged too.
+// Test that absl::optional<ArcInstanceMode> can be logged too.
TEST(ArcInstanceModeTest, TestLoggingWithOptional) {
std::ostringstream nullopt;
- nullopt << base::Optional<ArcInstanceMode>();
+ nullopt << absl::optional<ArcInstanceMode>();
EXPECT_FALSE(nullopt.str().empty());
std::ostringstream non_nullopt;
- non_nullopt << base::Optional<ArcInstanceMode>(
+ non_nullopt << absl::optional<ArcInstanceMode>(
ArcInstanceMode::MINI_INSTANCE);
EXPECT_FALSE(non_nullopt.str().empty());
EXPECT_NE(nullopt.str(), non_nullopt.str());
diff --git a/chromium/components/arc/session/arc_session.h b/chromium/components/arc/session/arc_session.h
index bf365da2152..5630fa0d160 100644
--- a/chromium/components/arc/session/arc_session.h
+++ b/chromium/components/arc/session/arc_session.h
@@ -8,6 +8,7 @@
#include <memory>
#include <string>
+#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "components/arc/session/adb_sideloading_availability_delegate.h"
@@ -102,6 +103,12 @@ class ArcSession {
virtual void SetDemoModeDelegate(
ArcClientAdapter::DemoModeDelegate* delegate) = 0;
+ // Trims VM's memory by moving it to zram. |callback| is called when the
+ // operation is done.
+ using TrimVmMemoryCallback =
+ base::OnceCallback<void(bool success, const std::string& failure_reason)>;
+ virtual void TrimVmMemory(TrimVmMemoryCallback callback) = 0;
+
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
diff --git a/chromium/components/arc/session/arc_session_impl.cc b/chromium/components/arc/session/arc_session_impl.cc
index 38e54150bbe..6e4754e7b76 100644
--- a/chromium/components/arc/session/arc_session_impl.cc
+++ b/chromium/components/arc/session/arc_session_impl.cc
@@ -805,7 +805,7 @@ void ArcSessionImpl::StopArcInstance(bool on_shutdown, bool should_backup_log) {
client_->StopArcInstance(on_shutdown, should_backup_log);
}
-void ArcSessionImpl::ArcInstanceStopped() {
+void ArcSessionImpl::ArcInstanceStopped(bool is_system_shutdown) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK_NE(state_, State::STARTING_MINI_INSTANCE);
VLOG(1) << "Notified that ARC instance is stopped";
@@ -815,9 +815,9 @@ void ArcSessionImpl::ArcInstanceStopped() {
accept_cancel_pipe_.reset();
ArcStopReason reason;
- if (stop_requested_) {
- // If the ARC instance is stopped after its explicit request,
- // return SHUTDOWN.
+ if (stop_requested_ || is_system_shutdown) {
+ // If the ARC instance is stopped after its explicit request or as part of
+ // system shutdown, return SHUTDOWN.
reason = ArcStopReason::SHUTDOWN;
} else if (insufficient_disk_space_) {
// ARC mini container is stopped because of upgarde failure due to low
@@ -895,6 +895,11 @@ void ArcSessionImpl::SetDemoModeDelegate(
client_->SetDemoModeDelegate(delegate);
}
+void ArcSessionImpl::TrimVmMemory(TrimVmMemoryCallback callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ client_->TrimVmMemory(std::move(callback));
+}
+
void ArcSessionImpl::OnConfigurationSet(bool success,
size_t num_cores_disabled) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/chromium/components/arc/session/arc_session_impl.h b/chromium/components/arc/session/arc_session_impl.h
index 761d105ee7d..c82a2a11fcf 100644
--- a/chromium/components/arc/session/arc_session_impl.h
+++ b/chromium/components/arc/session/arc_session_impl.h
@@ -14,11 +14,11 @@
#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "chromeos/system/scheduler_configuration_manager_base.h"
#include "components/arc/session/arc_client_adapter.h"
#include "components/arc/session/arc_session.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ash {
class DefaultScaleFactorRetriever;
@@ -213,6 +213,7 @@ class ArcSessionImpl
const std::string& serial_number) override;
void SetDemoModeDelegate(
ArcClientAdapter::DemoModeDelegate* delegate) override;
+ void TrimVmMemory(TrimVmMemoryCallback callback) override;
// chromeos::SchedulerConfigurationManagerBase::Observer overrides:
void OnConfigurationSet(bool success, size_t num_cores_disabled) override;
@@ -254,7 +255,7 @@ class ArcSessionImpl
void StopArcInstance(bool on_shutdown, bool should_backup_log);
// ArcClientAdapter::Observer:
- void ArcInstanceStopped() override;
+ void ArcInstanceStopped(bool is_system_shutdown) override;
// Completes the termination procedure. Note that calling this may end up with
// deleting |this| because the function calls observers' OnSessionStopped().
diff --git a/chromium/components/arc/session/arc_session_impl_unittest.cc b/chromium/components/arc/session/arc_session_impl_unittest.cc
index da95b5e42ae..bbcddf6037a 100644
--- a/chromium/components/arc/session/arc_session_impl_unittest.cc
+++ b/chromium/components/arc/session/arc_session_impl_unittest.cc
@@ -13,10 +13,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
-#include "base/files/file_util.h"
#include "base/location.h"
-#include "base/optional.h"
-#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
@@ -27,9 +24,11 @@
#include "components/arc/session/arc_session_impl.h"
#include "components/arc/session/arc_start_params.h"
#include "components/arc/session/arc_upgrade_params.h"
+#include "components/arc/test/arc_util_test_support.h"
#include "components/arc/test/fake_arc_bridge_host.h"
#include "components/version_info/channel.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cryptohome {
class Identification;
@@ -79,7 +78,7 @@ class FakeArcClientAdapter : public ArcClientAdapter {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&FakeArcClientAdapter::NotifyArcInstanceStopped,
- base::Unretained(this)));
+ base::Unretained(this), false /* is_system_shutdown */));
}
void SetUserInfo(const cryptohome::Identification& cryptohome_id,
@@ -87,11 +86,15 @@ class FakeArcClientAdapter : public ArcClientAdapter {
const std::string& serial_number) override {}
void SetDemoModeDelegate(DemoModeDelegate* delegate) override {}
+ void TrimVmMemory(TrimVmMemoryCallback callback) override {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), true, std::string()));
+ }
// Notifies ArcSessionImpl of the ARC instance stop event.
- void NotifyArcInstanceStopped() {
+ void NotifyArcInstanceStopped(bool is_system_shutdown) {
for (auto& observer : observer_list_)
- observer.ArcInstanceStopped();
+ observer.ArcInstanceStopped(is_system_shutdown);
}
void set_arc_available(bool arc_available) { arc_available_ = arc_available; }
@@ -112,7 +115,7 @@ class FakeArcClientAdapter : public ArcClientAdapter {
void OnArcUpgraded(chromeos::VoidDBusMethodCallback callback, bool result) {
std::move(callback).Run(result);
if (!result)
- NotifyArcInstanceStopped();
+ NotifyArcInstanceStopped(false /* is_system_shutdown */);
}
bool arc_available_ = true;
@@ -230,7 +233,7 @@ class TestArcSessionObserver : public ArcSession::Observer {
~TestArcSessionObserver() override { arc_session_->RemoveObserver(this); }
- const base::Optional<OnSessionStoppedArgs>& on_session_stopped_args() const {
+ const absl::optional<OnSessionStoppedArgs>& on_session_stopped_args() const {
return on_session_stopped_args_;
}
@@ -247,7 +250,7 @@ class TestArcSessionObserver : public ArcSession::Observer {
private:
ArcSession* const arc_session_; // Not owned.
base::RunLoop* const run_loop_ = nullptr; // Not owned.
- base::Optional<OnSessionStoppedArgs> on_session_stopped_args_;
+ absl::optional<OnSessionStoppedArgs> on_session_stopped_args_;
DISALLOW_COPY_AND_ASSIGN(TestArcSessionObserver);
};
@@ -274,12 +277,12 @@ class FakeSchedulerConfigurationManager
obs.OnConfigurationSet(reply_->first, reply_->second);
}
- base::Optional<std::pair<bool, size_t>> GetLastReply() const override {
+ absl::optional<std::pair<bool, size_t>> GetLastReply() const override {
return reply_;
}
private:
- base::Optional<std::pair<bool, size_t>> reply_;
+ absl::optional<std::pair<bool, size_t>> reply_;
DISALLOW_COPY_AND_ASSIGN(FakeSchedulerConfigurationManager);
};
@@ -660,7 +663,8 @@ TEST_F(ArcSessionImplTest, ArcStopInstance) {
arc_session->GetStateForTesting());
// Notify ArcClientAdapter's observers of the crash event.
- GetClient(arc_session.get())->NotifyArcInstanceStopped();
+ GetClient(arc_session.get())
+ ->NotifyArcInstanceStopped(false /* is_system_shutdown */);
EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
ASSERT_TRUE(observer.on_session_stopped_args().has_value());
@@ -669,6 +673,28 @@ TEST_F(ArcSessionImplTest, ArcStopInstance) {
EXPECT_TRUE(observer.on_session_stopped_args()->upgrade_requested);
}
+// Emulating system shutdown.
+TEST_F(ArcSessionImplTest, ArcStopInstanceSystemShutdown) {
+ auto arc_session = CreateArcSession();
+ TestArcSessionObserver observer(arc_session.get());
+ arc_session->StartMiniInstance();
+ arc_session->RequestUpgrade(DefaultUpgradeParams());
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(ArcSessionImpl::State::RUNNING_FULL_INSTANCE,
+ arc_session->GetStateForTesting());
+
+ // Notify ArcClientAdapter's observers of the shutdown event.
+ GetClient(arc_session.get())
+ ->NotifyArcInstanceStopped(true /* is_system_shutdown */);
+
+ EXPECT_EQ(ArcSessionImpl::State::STOPPED, arc_session->GetStateForTesting());
+ ASSERT_TRUE(observer.on_session_stopped_args().has_value());
+ EXPECT_EQ(ArcStopReason::SHUTDOWN,
+ observer.on_session_stopped_args()->reason);
+ EXPECT_TRUE(observer.on_session_stopped_args()->was_running);
+ EXPECT_TRUE(observer.on_session_stopped_args()->upgrade_requested);
+}
+
struct PackagesCacheModeState {
// Possible values for chromeos::switches::kArcPackagesCacheMode
const char* chrome_switch;
@@ -949,27 +975,12 @@ class ArcSessionImplDalvikMemoryProfileTest
: public ArcSessionImplTest,
public ::testing::WithParamInterface<DalvikMemoryProfileVariant> {};
-bool GetSystemMemoryInfo(const std::string& file_name,
- base::SystemMemoryInfoKB* mem_info) {
- base::FilePath base_path;
- base::PathService::Get(base::DIR_SOURCE_ROOT, &base_path);
- const base::FilePath test_path = base_path.Append("components")
- .Append("test")
- .Append("data")
- .Append("arc_dalvik_profile")
- .Append(file_name);
- base::ScopedAllowBlockingForTesting allowBlocking;
- std::string mem_info_data;
- return base::ReadFileToString(test_path, &mem_info_data) &&
- base::ParseProcMeminfo(mem_info_data, mem_info);
-}
-
TEST_P(ArcSessionImplDalvikMemoryProfileTest, DalvikMemoryProfiles) {
const DalvikMemoryProfileVariant& variant = GetParam();
auto arc_session = CreateArcSession();
arc_session->SetSystemMemoryInfoCallbackForTesting(
- base::BindRepeating(&GetSystemMemoryInfo, variant.file_name));
+ base::BindRepeating(&GetSystemMemoryInfoForTesting, variant.file_name));
arc_session->StartMiniInstance();
base::RunLoop().RunUntilIdle();
diff --git a/chromium/components/arc/session/arc_session_runner.cc b/chromium/components/arc/session/arc_session_runner.cc
index 7178fa138e5..2179904d169 100644
--- a/chromium/components/arc/session/arc_session_runner.cc
+++ b/chromium/components/arc/session/arc_session_runner.cc
@@ -9,9 +9,9 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/task_runner.h"
#include "components/arc/arc_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
@@ -32,7 +32,7 @@ void RecordInstanceRestartAfterCrashUma(size_t restart_after_crash_count) {
// Gets an ArcContainerLifetimeEvent value to record. Returns nullopt when no
// UMA recording is needed.
-base::Optional<ArcContainerLifetimeEvent> GetArcContainerLifetimeEvent(
+absl::optional<ArcContainerLifetimeEvent> GetArcContainerLifetimeEvent(
size_t restart_after_crash_count,
ArcStopReason stop_reason,
bool was_running) {
@@ -41,13 +41,13 @@ base::Optional<ArcContainerLifetimeEvent> GetArcContainerLifetimeEvent(
// container restart might be recorded. Each CONTAINER_STARTED event can
// be paired up to one non-START event.
if (restart_after_crash_count)
- return base::nullopt;
+ return absl::nullopt;
switch (stop_reason) {
case ArcStopReason::SHUTDOWN:
case ArcStopReason::LOW_DISK_SPACE:
// We don't record these events.
- return base::nullopt;
+ return absl::nullopt;
case ArcStopReason::GENERIC_BOOT_FAILURE:
return ArcContainerLifetimeEvent::CONTAINER_FAILED_TO_START;
case ArcStopReason::CRASH:
@@ -56,11 +56,11 @@ base::Optional<ArcContainerLifetimeEvent> GetArcContainerLifetimeEvent(
}
NOTREACHED();
- return base::nullopt;
+ return absl::nullopt;
}
// Returns true if restart is needed for given conditions.
-bool IsRestartNeeded(base::Optional<ArcInstanceMode> target_mode,
+bool IsRestartNeeded(absl::optional<ArcInstanceMode> target_mode,
ArcStopReason stop_reason,
bool was_running) {
if (!target_mode.has_value()) {
@@ -95,7 +95,7 @@ bool IsRestartNeeded(base::Optional<ArcInstanceMode> target_mode,
// Returns true if the request to start/upgrade ARC instance is allowed
// operation.
-bool IsRequestAllowed(const base::Optional<ArcInstanceMode>& current_mode,
+bool IsRequestAllowed(const absl::optional<ArcInstanceMode>& current_mode,
ArcInstanceMode request_mode) {
if (!current_mode.has_value()) {
// This is a request to start a new ARC instance (either mini instance
@@ -143,7 +143,7 @@ void ArcSessionRunner::ResumeRunner() {
resumed_ = true;
if (target_mode_) {
ArcInstanceMode original_mode = *target_mode_;
- target_mode_ = base::nullopt;
+ target_mode_ = absl::nullopt;
RequestStart(original_mode);
}
}
@@ -205,7 +205,7 @@ void ArcSessionRunner::RequestStop() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
VLOG(1) << "Session stop requested";
- target_mode_ = base::nullopt;
+ target_mode_ = absl::nullopt;
if (arc_session_) {
// If |arc_session_| is running, stop it.
@@ -226,7 +226,7 @@ void ArcSessionRunner::OnShutdown() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
VLOG(1) << "OnShutdown";
- target_mode_ = base::nullopt;
+ target_mode_ = absl::nullopt;
restart_timer_.Stop();
if (arc_session_)
arc_session_->OnShutdown();
@@ -256,6 +256,16 @@ void ArcSessionRunner::SetDemoModeDelegate(
demo_mode_delegate_ = std::move(delegate);
}
+void ArcSessionRunner::TrimVmMemory(TrimVmMemoryCallback callback) {
+ if (arc_session_) {
+ arc_session_->TrimVmMemory(std::move(callback));
+ return;
+ }
+ LOG(WARNING) << "TrimVmMemory is called when no ARC session is running";
+ std::move(callback).Run(/*success=*/false,
+ /*failure_reason=*/"No ARC session is running");
+}
+
void ArcSessionRunner::SetRestartDelayForTesting(
const base::TimeDelta& restart_delay) {
DCHECK(!arc_session_);
@@ -311,7 +321,7 @@ void ArcSessionRunner::OnSessionStopped(ArcStopReason stop_reason,
arc_session_->RemoveObserver(this);
arc_session_.reset();
- const base::Optional<ArcContainerLifetimeEvent> uma_to_record =
+ const absl::optional<ArcContainerLifetimeEvent> uma_to_record =
GetArcContainerLifetimeEvent(restart_after_crash_count_, stop_reason,
was_running);
if (uma_to_record.has_value())
diff --git a/chromium/components/arc/session/arc_session_runner.h b/chromium/components/arc/session/arc_session_runner.h
index 8e7acd77752..9e9eaf8ff6f 100644
--- a/chromium/components/arc/session/arc_session_runner.h
+++ b/chromium/components/arc/session/arc_session_runner.h
@@ -10,10 +10,8 @@
#include <vector>
#include "base/callback.h"
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -23,6 +21,7 @@
#include "components/arc/session/arc_session.h"
#include "components/arc/session/arc_stop_reason.h"
#include "components/arc/session/arc_upgrade_params.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
@@ -111,6 +110,12 @@ class ArcSessionRunner : public ArcSession::Observer {
void SetDemoModeDelegate(
std::unique_ptr<ArcClientAdapter::DemoModeDelegate> delegate);
+ // Trims VM's memory by moving it to zram. |callback| is called when the
+ // operation is done.
+ using TrimVmMemoryCallback =
+ base::OnceCallback<void(bool success, const std::string& failure_reason)>;
+ void TrimVmMemory(TrimVmMemoryCallback callback);
+
// Returns the current ArcSession instance for testing purpose.
ArcSession* GetArcSessionForTesting() { return arc_session_.get(); }
@@ -141,7 +146,7 @@ class ArcSessionRunner : public ArcSession::Observer {
// Target ARC instance running mode. If nullopt, it means the ARC instance
// should stop eventually.
- base::Optional<ArcInstanceMode> target_mode_;
+ absl::optional<ArcInstanceMode> target_mode_;
// Instead of immediately trying to restart the container, give it some time
// to finish tearing down in case it is still in the process of stopping.
diff --git a/chromium/components/arc/session/arc_supervision_transition.cc b/chromium/components/arc/session/arc_supervision_transition.cc
index 359aeb248d4..ac3a52d5688 100644
--- a/chromium/components/arc/session/arc_supervision_transition.cc
+++ b/chromium/components/arc/session/arc_supervision_transition.cc
@@ -16,6 +16,8 @@ std::ostream& operator<<(std::ostream& os,
return os << "CHILD_TO_REGULAR";
case ArcSupervisionTransition::REGULAR_TO_CHILD:
return os << "REGULAR_TO_CHILD";
+ case ArcSupervisionTransition::UNMANAGED_TO_MANAGED:
+ return os << "UNMANAGED_TO_MANAGED";
}
NOTREACHED() << "Unexpected value for ArcSupervisionTransition: "
<< static_cast<int>(supervision_transition);
diff --git a/chromium/components/arc/session/arc_supervision_transition.h b/chromium/components/arc/session/arc_supervision_transition.h
index b28a531e51f..8642ba26749 100644
--- a/chromium/components/arc/session/arc_supervision_transition.h
+++ b/chromium/components/arc/session/arc_supervision_transition.h
@@ -21,6 +21,9 @@ enum class ArcSupervisionTransition : int {
// Regular user is transitioning to a child account, need to enable
// supervision.
REGULAR_TO_CHILD = 2,
+ // Unmanaged user is transitioning to a managed state, need to enable
+ // management.
+ UNMANAGED_TO_MANAGED = 3,
};
std::ostream& operator<<(std::ostream& os,
diff --git a/chromium/components/arc/session/arc_vm_client_adapter.cc b/chromium/components/arc/session/arc_vm_client_adapter.cc
index fea4f3a03b9..b5c9303f44e 100644
--- a/chromium/components/arc/session/arc_vm_client_adapter.cc
+++ b/chromium/components/arc/session/arc_vm_client_adapter.cc
@@ -28,9 +28,9 @@
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
-#include "base/optional.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/launch.h"
+#include "base/process/process_metrics.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -41,11 +41,12 @@
#include "base/task/thread_pool.h"
#include "base/threading/platform_thread.h"
#include "base/threading/scoped_blocking_call.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "chromeos/components/sensors/buildflags.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
-#include "chromeos/dbus/concierge_client.h"
+#include "chromeos/dbus/concierge/concierge_client.h"
#include "chromeos/dbus/dbus_method_call_status.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
@@ -56,6 +57,7 @@
#include "components/arc/session/arc_session.h"
#include "components/arc/session/file_system_status.h"
#include "components/version_info/version_info.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
namespace {
@@ -94,12 +96,12 @@ constexpr base::TimeDelta kConnectTimeoutLimit =
constexpr base::TimeDelta kConnectSleepDurationInitial =
base::TimeDelta::FromMilliseconds(100);
-base::Optional<base::TimeDelta> g_connect_timeout_limit_for_testing;
-base::Optional<base::TimeDelta> g_connect_sleep_duration_initial_for_testing;
-base::Optional<int> g_boot_notification_server_fd;
+absl::optional<base::TimeDelta> g_connect_timeout_limit_for_testing;
+absl::optional<base::TimeDelta> g_connect_sleep_duration_initial_for_testing;
+absl::optional<int> g_boot_notification_server_fd;
chromeos::ConciergeClient* GetConciergeClient() {
- return chromeos::DBusThreadManager::Get()->GetConciergeClient();
+ return chromeos::ConciergeClient::Get();
}
chromeos::DebugDaemonClient* GetDebugDaemonClient() {
@@ -222,7 +224,8 @@ std::vector<std::string> GenerateKernelCmdline(
BUILDFLAG(USE_IIOSERVICE)),
};
- ArcVmUreadaheadMode mode = GetArcVmUreadaheadMode();
+ const ArcVmUreadaheadMode mode =
+ GetArcVmUreadaheadMode(base::BindRepeating(&base::GetSystemMemoryInfo));
switch (mode) {
case ArcVmUreadaheadMode::READAHEAD:
result.push_back("androidboot.arcvm_ureadahead_mode=readahead");
@@ -365,6 +368,9 @@ vm_tools::concierge::StartArcVmRequest CreateStartArcVmRequest(
// Add enable_rt_vcpu.
request.set_enable_rt_vcpu(IsArcVmRtVcpuEnabled(cpus));
+
+ // Add hugepages.
+ request.set_use_hugepages(IsArcVmUseHugePages());
return request;
}
@@ -440,7 +446,7 @@ bool SendUpgradePropsToArcVmBootNotificationServer(
if (!fd.is_valid())
return false;
- if (!base::WriteFileDescriptor(fd.get(), props.c_str(), props.size())) {
+ if (!base::WriteFileDescriptor(fd.get(), props)) {
PLOG(ERROR) << "Unable to write props to "
<< kArcVmBootNotificationServerSocketPath;
return false;
@@ -494,7 +500,9 @@ class ArcVmClientAdapter : public ArcClientAdapter,
}
VLOG(1) << "OnVmStopped: ARCVM cid=" << cid;
current_cid_ = kInvalidCid;
- OnArcInstanceStopped();
+ const bool is_system_shutdown =
+ signal.reason() == vm_tools::concierge::SERVICE_SHUTDOWN;
+ OnArcInstanceStopped(is_system_shutdown);
}
// ArcClientAdapter overrides:
@@ -578,12 +586,32 @@ class ArcVmClientAdapter : public ArcClientAdapter,
demo_mode_delegate_ = delegate;
}
+ void TrimVmMemory(TrimVmMemoryCallback callback) override {
+ VLOG(2) << "Start trimming VM memory";
+ if (user_id_hash_.empty()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback), /*success=*/false,
+ /*failure_reason=*/"user_id_hash_ is not set"));
+ return;
+ }
+ vm_tools::concierge::ReclaimVmMemoryRequest request;
+ request.set_name(kArcVmName);
+ request.set_owner_id(user_id_hash_);
+ GetConciergeClient()->ReclaimVmMemory(
+ request,
+ base::BindOnce(&ArcVmClientAdapter::OnTrimVmMemory,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
+ }
+
// chromeos::ConciergeClient::Observer overrides:
void ConciergeServiceStopped() override {
VLOG(1) << "vm_concierge stopped";
// At this point, all crosvm processes are gone. Notify the observer of the
// event.
- OnArcInstanceStopped();
+ // NOTE: In a normal system shutdown OnVmStopped() is called before this.
+ // When vm_concierge crashes, this is called without OnVmStopped().
+ OnArcInstanceStopped(false /* is_system_shutdown */);
}
void ConciergeServiceStarted() override {}
@@ -621,7 +649,7 @@ class ArcVmClientAdapter : public ArcClientAdapter,
}
void OnGetVmReply(
- base::Optional<vm_tools::concierge::GetVmInfoResponse> reply) {
+ absl::optional<vm_tools::concierge::GetVmInfoResponse> reply) {
vm_tools::concierge::StopVmRequest request;
request.set_name(kArcVmName);
@@ -694,7 +722,7 @@ class ArcVmClientAdapter : public ArcClientAdapter,
void OnExistingMiniVmStopped(
chromeos::VoidDBusMethodCallback callback,
- base::Optional<vm_tools::concierge::StopVmResponse> reply) {
+ absl::optional<vm_tools::concierge::StopVmResponse> reply) {
// reply->success() returns true even when there was no VM running.
if (!reply.has_value() || !reply->success()) {
LOG(ERROR) << "StopVm failed: "
@@ -751,7 +779,6 @@ class ArcVmClientAdapter : public ArcClientAdapter,
base::SysInfo::NumberOfProcessors() - start_params_.num_cores_disabled;
DCHECK_LT(0, cpus);
- DCHECK(is_dev_mode_);
std::vector<std::string> kernel_cmdline = GenerateKernelCmdline(
start_params_, file_system_status, *is_dev_mode_, is_host_on_vm_,
GetChromeOsChannelFromLsbRelease());
@@ -767,7 +794,7 @@ class ArcVmClientAdapter : public ArcClientAdapter,
void OnStartArcVmReply(
chromeos::VoidDBusMethodCallback callback,
- base::Optional<vm_tools::concierge::StartVmResponse> reply) {
+ absl::optional<vm_tools::concierge::StartVmResponse> reply) {
if (!reply.has_value()) {
LOG(ERROR) << "Failed to start arcvm. Empty response.";
std::move(callback).Run(false);
@@ -790,7 +817,7 @@ class ArcVmClientAdapter : public ArcClientAdapter,
void OnExistingFullVmStopped(
UpgradeParams params,
chromeos::VoidDBusMethodCallback callback,
- base::Optional<vm_tools::concierge::StopVmResponse> reply) {
+ absl::optional<vm_tools::concierge::StopVmResponse> reply) {
// reply->success() returns true even when there was no VM running.
if (!reply.has_value() || !reply->success()) {
LOG(ERROR) << "StopVm failed: "
@@ -873,7 +900,7 @@ class ArcVmClientAdapter : public ArcClientAdapter,
void OnSetVmId(UpgradeParams params,
chromeos::VoidDBusMethodCallback callback,
- base::Optional<vm_tools::concierge::SetVmIdResponse> reply) {
+ absl::optional<vm_tools::concierge::SetVmIdResponse> reply) {
if (!reply.has_value()) {
LOG(ERROR) << "Failed to set VM ID. Empty response.";
StopArcInstanceInternal();
@@ -935,7 +962,7 @@ class ArcVmClientAdapter : public ArcClientAdapter,
std::move(callback).Run(true);
}
- void OnArcInstanceStopped() {
+ void OnArcInstanceStopped(bool is_system_shutdown) {
VLOG(1) << "ARCVM stopped.";
// If this method is called before even mini VM is started (e.g. very early
@@ -946,11 +973,11 @@ class ArcVmClientAdapter : public ArcClientAdapter,
should_notify_observers_ = false;
for (auto& observer : observer_list_)
- observer.ArcInstanceStopped();
+ observer.ArcInstanceStopped(is_system_shutdown);
}
void OnStopVmReply(
- base::Optional<vm_tools::concierge::StopVmResponse> reply) {
+ absl::optional<vm_tools::concierge::StopVmResponse> reply) {
// If the reply indicates the D-Bus call is successfully done, do nothing.
// Concierge will call OnVmStopped() eventually.
if (reply.has_value() && reply.value().success())
@@ -960,10 +987,31 @@ class ArcVmClientAdapter : public ArcClientAdapter,
// is if the reply is empty, which means Concierge isn't running and ARCVM
// isn't either.
LOG(ERROR) << "Failed to stop ARCVM: empty reply.";
- OnArcInstanceStopped();
+ OnArcInstanceStopped(false /* is_system_shutdown */);
+ }
+
+ void OnTrimVmMemory(
+ TrimVmMemoryCallback callback,
+ absl::optional<vm_tools::concierge::ReclaimVmMemoryResponse> reply) {
+ bool success = false;
+ std::string failure_reason;
+
+ if (!reply.has_value()) {
+ failure_reason = "Empty response";
+ } else {
+ const vm_tools::concierge::ReclaimVmMemoryResponse& response =
+ reply.value();
+ success = response.success();
+ if (!success)
+ failure_reason = response.failure_reason();
+ }
+
+ VLOG(2) << "Finished trimming memory: success=" << success
+ << (failure_reason.empty() ? "" : " reason=") << failure_reason;
+ std::move(callback).Run(success, failure_reason);
}
- base::Optional<bool> is_dev_mode_;
+ absl::optional<bool> is_dev_mode_;
// True when the *host* is running on a VM.
const bool is_host_on_vm_;
// A cryptohome ID of the primary profile.
@@ -1015,7 +1063,7 @@ void SetArcVmBootNotificationServerAddressForTesting(
g_connect_sleep_duration_initial_for_testing = connect_sleep_duration_initial;
}
-void SetArcVmBootNotificationServerFdForTesting(base::Optional<int> fd) {
+void SetArcVmBootNotificationServerFdForTesting(absl::optional<int> fd) {
g_boot_notification_server_fd = fd;
}
diff --git a/chromium/components/arc/session/arc_vm_client_adapter.h b/chromium/components/arc/session/arc_vm_client_adapter.h
index 6f8e7c337c3..df014446222 100644
--- a/chromium/components/arc/session/arc_vm_client_adapter.h
+++ b/chromium/components/arc/session/arc_vm_client_adapter.h
@@ -39,7 +39,7 @@ void SetArcVmBootNotificationServerAddressForTesting(
base::TimeDelta connect_sleep_duration_initial);
// Sets the an FD ConnectToArcVmBootNotificationServer() returns for testing.
-void SetArcVmBootNotificationServerFdForTesting(base::Optional<int> fd);
+void SetArcVmBootNotificationServerFdForTesting(absl::optional<int> fd);
// Generates a list of props from |upgrade_params|, each of which takes the form
// "prefix.prop_name=value"
diff --git a/chromium/components/arc/session/arc_vm_client_adapter_unittest.cc b/chromium/components/arc/session/arc_vm_client_adapter_unittest.cc
index b8c501fd257..874413ee8b8 100644
--- a/chromium/components/arc/session/arc_vm_client_adapter_unittest.cc
+++ b/chromium/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -34,9 +34,9 @@
#include "base/test/scoped_run_loop_timeout.h"
#include "base/time/time.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/dbus/concierge/fake_concierge_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h"
-#include "chromeos/dbus/fake_concierge_client.h"
#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
#include "chromeos/dbus/upstart/fake_upstart_client.h"
#include "components/arc/arc_features.h"
@@ -130,7 +130,7 @@ class TestDebugDaemonClient : public chromeos::FakeDebugDaemonClient {
// TODO(yusukes): Merge the feature to FakeConciergeClient.
class TestConciergeClient : public chromeos::FakeConciergeClient {
public:
- TestConciergeClient() = default;
+ static void Initialize() { new TestConciergeClient(); }
~TestConciergeClient() override = default;
void StopVm(const vm_tools::concierge::StopVmRequest& request,
@@ -169,6 +169,9 @@ class TestConciergeClient : public chromeos::FakeConciergeClient {
}
private:
+ TestConciergeClient()
+ : chromeos::FakeConciergeClient(/*fake_cicerone_client=*/nullptr) {}
+
int stop_vm_call_count_ = 0;
// When callback_count_ == 0, the on_stop_vm_callback_ is not run.
int callback_count_ = 0;
@@ -213,7 +216,8 @@ class TestArcVmBootNotificationServer
<< "bind failed with " << base::safe_strerror(errno);
ASSERT_EQ(HANDLE_EINTR(listen(fd_.get(), 5)), 0)
<< "listen failed with " << base::safe_strerror(errno);
- controller_.reset(new base::MessagePumpForUI::FdWatchController(FROM_HERE));
+ controller_ =
+ std::make_unique<base::MessagePumpForUI::FdWatchController>(FROM_HERE);
ASSERT_TRUE(base::CurrentUIThread::Get()->WatchFileDescriptor(
fd_.get(), true, base::MessagePumpForUI::WATCH_READ, controller_.get(),
this));
@@ -289,25 +293,22 @@ class ArcVmClientAdapterTest : public testing::Test,
logging::SetMinLogLevel(-1);
// Create and set new fake clients every time to reset clients' status.
+ chromeos::DBusThreadManager::Initialize();
chromeos::DBusThreadManager::GetSetterForTesting()->SetDebugDaemonClient(
std::make_unique<TestDebugDaemonClient>());
- chromeos::DBusThreadManager::GetSetterForTesting()->SetConciergeClient(
- std::make_unique<TestConciergeClient>());
+ TestConciergeClient::Initialize();
chromeos::UpstartClient::InitializeFake();
}
~ArcVmClientAdapterTest() override {
- chromeos::DBusThreadManager::GetSetterForTesting()->SetConciergeClient(
- nullptr);
- chromeos::DBusThreadManager::GetSetterForTesting()->SetDebugDaemonClient(
- nullptr);
+ chromeos::ConciergeClient::Shutdown();
+ chromeos::DBusThreadManager::Shutdown();
}
void SetUp() override {
run_loop_ = std::make_unique<base::RunLoop>();
adapter_ = CreateArcVmClientAdapterForTesting(base::BindRepeating(
&ArcVmClientAdapterTest::RewriteStatus, base::Unretained(this)));
- arc_instance_stopped_called_ = false;
adapter_->AddObserver(this);
ASSERT_TRUE(dir_.CreateUniqueTempDir());
@@ -324,7 +325,7 @@ class ArcVmClientAdapterTest : public testing::Test,
// Reset to the original behavior.
RemoveUpstartStartStopJobFailures();
- SetArcVmBootNotificationServerFdForTesting(base::nullopt);
+ SetArcVmBootNotificationServerFdForTesting(absl::nullopt);
const std::string abstract_addr(GenerateAbstractAddress());
boot_server_ = std::make_unique<TestArcVmBootNotificationServer>();
@@ -349,8 +350,8 @@ class ArcVmClientAdapterTest : public testing::Test,
}
// ArcClientAdapter::Observer:
- void ArcInstanceStopped() override {
- arc_instance_stopped_called_ = true;
+ void ArcInstanceStopped(bool is_system_shutdown) override {
+ is_system_shutdown_ = is_system_shutdown;
run_loop()->Quit();
}
@@ -436,20 +437,26 @@ class ArcVmClientAdapterTest : public testing::Test,
observer.OnVmStarted(signal);
}
- void SendVmStoppedSignalForCid(int64_t cid) {
+ void SendVmStoppedSignalForCid(vm_tools::concierge::VmStopReason reason,
+ int64_t cid) {
vm_tools::concierge::VmStoppedSignal signal;
signal.set_name(kArcVmName);
signal.set_cid(cid);
+ signal.set_reason(reason);
for (auto& observer : GetTestConciergeClient()->vm_observer_list())
observer.OnVmStopped(signal);
}
- void SendVmStoppedSignal() { SendVmStoppedSignalForCid(kCid); }
+ void SendVmStoppedSignal(vm_tools::concierge::VmStopReason reason) {
+ SendVmStoppedSignalForCid(reason, kCid);
+ }
- void SendVmStoppedSignalNotForArcVm() {
+ void SendVmStoppedSignalNotForArcVm(
+ vm_tools::concierge::VmStopReason reason) {
vm_tools::concierge::VmStoppedSignal signal;
signal.set_name("penguin");
signal.set_cid(kCid);
+ signal.set_reason(reason);
for (auto& observer : GetTestConciergeClient()->vm_observer_list())
observer.OnVmStopped(signal);
}
@@ -516,12 +523,13 @@ class ArcVmClientAdapterTest : public testing::Test,
run_loop()->RunUntilIdle();
EXPECT_EQ(arc_upgraded ? 3 : 2,
GetTestConciergeClient()->stop_vm_call_count());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_FALSE(is_system_shutdown().has_value());
RecreateRunLoop();
- SendVmStoppedSignal();
+ SendVmStoppedSignal(vm_tools::concierge::STOP_VM_REQUESTED);
run_loop()->Run();
- EXPECT_TRUE(arc_instance_stopped_called());
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_FALSE(is_system_shutdown().value());
}
// Checks that ArcVmClientAdapter has requested to stop the VM (after an
@@ -535,11 +543,12 @@ class ArcVmClientAdapterTest : public testing::Test,
void ExpectArcStopped(bool stale_full_vm_stopped) {
EXPECT_EQ(stale_full_vm_stopped ? 3 : 2,
GetTestConciergeClient()->stop_vm_call_count());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_FALSE(is_system_shutdown().has_value());
RecreateRunLoop();
- SendVmStoppedSignal();
+ SendVmStoppedSignal(vm_tools::concierge::STOP_VM_REQUESTED);
run_loop()->Run();
- EXPECT_TRUE(arc_instance_stopped_called());
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_FALSE(is_system_shutdown().value());
}
void RecreateRunLoop() { run_loop_ = std::make_unique<base::RunLoop>(); }
@@ -547,18 +556,15 @@ class ArcVmClientAdapterTest : public testing::Test,
base::RunLoop* run_loop() { return run_loop_.get(); }
ArcClientAdapter* adapter() { return adapter_.get(); }
- bool arc_instance_stopped_called() const {
- return arc_instance_stopped_called_;
- }
- void reset_arc_instance_stopped_called() {
- arc_instance_stopped_called_ = false;
+ const absl::optional<bool>& is_system_shutdown() const {
+ return is_system_shutdown_;
}
+ void reset_is_system_shutdown() { is_system_shutdown_ = absl::nullopt; }
const std::vector<std::pair<std::string, bool>>& upstart_operations() const {
return upstart_operations_;
}
TestConciergeClient* GetTestConciergeClient() {
- return static_cast<TestConciergeClient*>(
- chromeos::DBusThreadManager::Get()->GetConciergeClient());
+ return static_cast<TestConciergeClient*>(chromeos::ConciergeClient::Get());
}
TestDebugDaemonClient* GetTestDebugDaemonClient() {
@@ -586,7 +592,7 @@ class ArcVmClientAdapterTest : public testing::Test,
std::unique_ptr<base::RunLoop> run_loop_;
std::unique_ptr<ArcClientAdapter> adapter_;
- bool arc_instance_stopped_called_;
+ absl::optional<bool> is_system_shutdown_;
content::BrowserTaskEnvironment browser_task_environment_;
base::ScopedTempDir dir_;
@@ -623,7 +629,7 @@ TEST_F(ArcVmClientAdapterTest, SetUserInfoEmpty) {
// Tests that StartMiniArc() succeeds by default.
TEST_F(ArcVmClientAdapterTest, StartMiniArc) {
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
StopArcInstance(/*arc_upgraded=*/false);
}
@@ -635,7 +641,7 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StopArcVmPostLoginServicesJobFail) {
InjectUpstartStopJobFailure(kArcVmPostLoginServicesJobName);
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
StopArcInstance(/*arc_upgraded=*/false);
}
@@ -648,7 +654,7 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmPerBoardFeaturesJobFail) {
StartMiniArcWithParams(false, {});
// Confirm that no VM is started.
- EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
+ EXPECT_EQ(GetTestConciergeClient()->start_arc_vm_call_count(), 0);
}
// Tests that StartMiniArc() fails if Upstart fails to start
@@ -658,7 +664,7 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmPreLoginServicesJobFail) {
InjectUpstartStartJobFailure(kArcVmPreLoginServicesJobName);
StartMiniArcWithParams(false, {});
- EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
+ EXPECT_EQ(GetTestConciergeClient()->start_arc_vm_call_count(), 0);
}
// Tests that StartMiniArc() succeeds if Upstart fails to stop
@@ -668,7 +674,7 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StopArcVmPreLoginServicesJobFail) {
InjectUpstartStopJobFailure(kArcVmPreLoginServicesJobName);
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
StopArcInstance(/*arc_upgraded=*/false);
}
@@ -704,14 +710,15 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance) {
EXPECT_EQ(3, GetTestConciergeClient()->stop_vm_call_count());
// The callback for StopVm D-Bus reply does NOT call ArcInstanceStopped when
// the D-Bus call result is successful.
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_FALSE(is_system_shutdown().has_value());
// Instead, vm_concierge explicitly notifies Chrome of the VM termination.
RecreateRunLoop();
- SendVmStoppedSignal();
+ SendVmStoppedSignal(vm_tools::concierge::STOP_VM_REQUESTED);
run_loop()->Run();
// ..and that calls ArcInstanceStopped.
- EXPECT_TRUE(arc_instance_stopped_called());
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_FALSE(is_system_shutdown().value());
}
// b/164816080 This test ensures that a new vm instance that is
@@ -736,7 +743,7 @@ TEST_F(ArcVmClientAdapterTest, DoesNotGetArcInstanceStoppedOnNestedInstance) {
bool stopped_called() const { return stopped_called_; }
// ArcClientAdapter::Observer:
- void ArcInstanceStopped() override {
+ void ArcInstanceStopped(bool is_system_shutdown) override {
stopped_called_ = true;
if (child_observer_) {
@@ -789,7 +796,7 @@ TEST_F(ArcVmClientAdapterTest, DoesNotGetArcInstanceStoppedOnNestedInstance) {
},
adapter(), &parent_observer));
- SendVmStoppedSignal();
+ SendVmStoppedSignal(vm_tools::concierge::STOP_VM_REQUESTED);
EXPECT_TRUE(parent_observer.stopped_called());
EXPECT_FALSE(child_observer.stopped_called());
@@ -806,14 +813,15 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance_WithLogBackup) {
EXPECT_EQ(3, GetTestConciergeClient()->stop_vm_call_count());
// The callback for StopVm D-Bus reply does NOT call ArcInstanceStopped when
// the D-Bus call result is successful.
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_FALSE(is_system_shutdown().has_value());
// Instead, vm_concierge explicitly notifies Chrome of the VM termination.
RecreateRunLoop();
- SendVmStoppedSignal();
+ SendVmStoppedSignal(vm_tools::concierge::STOP_VM_REQUESTED);
run_loop()->Run();
// ..and that calls ArcInstanceStopped.
- EXPECT_TRUE(arc_instance_stopped_called());
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_FALSE(is_system_shutdown().value());
}
TEST_F(ArcVmClientAdapterTest, StopArcInstance_WithLogBackup_BackupFailed) {
@@ -829,16 +837,17 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance_WithLogBackup_BackupFailed) {
EXPECT_EQ(3, GetTestConciergeClient()->stop_vm_call_count());
// The callback for StopVm D-Bus reply does NOT call ArcInstanceStopped when
// the D-Bus call result is successful.
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_FALSE(is_system_shutdown().has_value());
// Instead, vm_concierge explicitly notifies Chrome of the VM termination.
RecreateRunLoop();
- SendVmStoppedSignal();
+ SendVmStoppedSignal(vm_tools::concierge::STOP_VM_REQUESTED);
run_loop()->Run();
EXPECT_TRUE(GetTestDebugDaemonClient()->backup_arc_bug_report_called());
// ..and that calls ArcInstanceStopped.
- EXPECT_TRUE(arc_instance_stopped_called());
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_FALSE(is_system_shutdown().value());
}
// Tests that StopArcInstance() called during shutdown doesn't do anything.
@@ -850,7 +859,7 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance_OnShutdown) {
adapter()->StopArcInstance(/*on_shutdown=*/true, /*should_backup_log=*/false);
run_loop()->RunUntilIdle();
EXPECT_EQ(2, GetTestConciergeClient()->stop_vm_call_count());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
// Tests that StopArcInstance() immediately notifies the observer on failure.
@@ -872,7 +881,8 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance_Fail) {
// The callback for StopVm D-Bus reply does call ArcInstanceStopped when
// the D-Bus call result is NOT successful.
- EXPECT_TRUE(arc_instance_stopped_called());
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_FALSE(is_system_shutdown().value());
}
// Test that StopArcInstance() stops the mini-VM if it cannot find a VM with
@@ -890,7 +900,7 @@ TEST_F(ArcVmClientAdapterTest, StopArcInstance_StopMiniVm) {
/*should_backup_log*/ false);
run_loop()->RunUntilIdle();
- EXPECT_TRUE(GetTestConciergeClient()->get_vm_info_called());
+ EXPECT_GE(GetTestConciergeClient()->get_vm_info_call_count(), 1);
// Expect StopVm() to be called twice; once in StartMiniArc to clear stale
// mini-VM, and again on StopArcInstance().
EXPECT_EQ(2, GetTestConciergeClient()->stop_vm_call_count());
@@ -923,8 +933,8 @@ TEST_F(ArcVmClientAdapterTest,
// StartMiniArc should still succeed.
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
// Make sure StopVm() is called only once, to stop existing VMs on
// StartMiniArc().
@@ -950,7 +960,7 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_NoUserId) {
// Don't set the user id hash.
SetUserInfo(std::string(), kSerialNumber);
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/2);
ExpectArcStopped(/*stale_full_vm_stopped=*/false);
@@ -980,8 +990,8 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_NeedPowerwashAdbResponse) {
chromeos::FakeSessionManagerClient::AdbSideloadResponseCode::
NEED_POWERWASH);
UpgradeArc(true);
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(),
"ro.boot.enable_adb_sideloading=0"));
}
@@ -992,8 +1002,8 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_AdbSideloadingPropertyDefault) {
StartMiniArc();
UpgradeArc(true);
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(),
"ro.boot.enable_adb_sideloading=0"));
}
@@ -1005,8 +1015,8 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_AdbSideloadingPropertyEnabled) {
chromeos::FakeSessionManagerClient::Get()->set_adb_sideload_enabled(true);
UpgradeArc(true);
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(),
"ro.boot.enable_adb_sideloading=1"));
}
@@ -1017,8 +1027,8 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_AdbSideloadingPropertyDisabled) {
chromeos::FakeSessionManagerClient::Get()->set_adb_sideload_enabled(false);
UpgradeArc(true);
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
EXPECT_TRUE(base::Contains(boot_notification_server()->received_data(),
"ro.boot.enable_adb_sideloading=0"));
}
@@ -1028,7 +1038,7 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_NoSerial) {
// Don't set the serial number.
SetUserInfo(kUserIdHash, std::string());
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/2);
ExpectArcStopped(/*stale_full_vm_stopped=*/false);
@@ -1040,7 +1050,7 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_SetVmIdEmptyReply) {
StartMiniArc();
// Inject failure
- GetTestConciergeClient()->set_set_vm_id_response(base::nullopt);
+ GetTestConciergeClient()->set_set_vm_id_response(absl::nullopt);
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
@@ -1068,18 +1078,18 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StopExistingVmFailure) {
StartMiniArcWithParams(false, {});
- EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_EQ(GetTestConciergeClient()->start_arc_vm_call_count(), 0);
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
TEST_F(ArcVmClientAdapterTest, StartMiniArc_StopExistingVmFailureEmptyReply) {
// Inject failure.
- GetTestConciergeClient()->set_stop_vm_response(base::nullopt);
+ GetTestConciergeClient()->set_stop_vm_response(absl::nullopt);
StartMiniArcWithParams(false, {});
- EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_EQ(GetTestConciergeClient()->start_arc_vm_call_count(), 0);
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
TEST_F(ArcVmClientAdapterTest, UpgradeArc_StopExistingVmFailure) {
@@ -1100,7 +1110,7 @@ TEST_F(ArcVmClientAdapterTest, UpgradeArc_StopExistingVmFailureEmptyReply) {
StartMiniArc();
// Inject failure.
- GetTestConciergeClient()->set_stop_vm_response(base::nullopt);
+ GetTestConciergeClient()->set_stop_vm_response(absl::nullopt);
UpgradeArcWithParamsAndStopVmCount(false, {}, /*run_until_stop_vm_count=*/3);
ExpectArcStopped(/*stale_full_vm_stopped=*/true);
@@ -1114,8 +1124,8 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_WaitForConciergeAvailableFailure) {
false);
StartMiniArcWithParams(false, {});
- EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_EQ(GetTestConciergeClient()->start_arc_vm_call_count(), 0);
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
// Tests that StartArcVm() failure is handled properly.
@@ -1128,27 +1138,27 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmFailure) {
StartMiniArcWithParams(false, {});
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmFailureEmptyReply) {
SetValidUserInfo();
// Inject failure to StartArcVm(). This emulates D-Bus timeout situations.
- GetTestConciergeClient()->set_start_vm_response(base::nullopt);
+ GetTestConciergeClient()->set_start_vm_response(absl::nullopt);
StartMiniArcWithParams(false, {});
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
// Tests that successful StartArcVm() call is handled properly.
TEST_F(ArcVmClientAdapterTest, UpgradeArc_Success) {
SetValidUserInfo();
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
UpgradeArc(true);
StopArcInstance(/*arc_upgraded=*/true);
@@ -1160,8 +1170,8 @@ TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_VariousParams) {
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
UpgradeParams params(GetPopulatedUpgradeParams());
UpgradeArcWithParams(true, std::move(params));
@@ -1178,8 +1188,8 @@ TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_VariousParams2) {
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
UpgradeParams params(GetPopulatedUpgradeParams());
// Use slightly different params than StartUpgradeArc_VariousParams.
@@ -1217,8 +1227,8 @@ TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_DemoMode) {
adapter()->SetDemoModeDelegate(&delegate);
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
// Verify the request.
auto request = GetTestConciergeClient()->start_arc_vm_request();
@@ -1246,8 +1256,8 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_DisableSystemDefaultApp) {
start_params.arc_disable_system_default_app = true;
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.disable_system_default_app=1"));
@@ -1260,24 +1270,24 @@ TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_DisableMediaStoreMaintenance) {
StartMiniArcWithParams(true, std::move(start_params));
UpgradeParams params(GetPopulatedUpgradeParams());
UpgradeArcWithParams(true, std::move(params));
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
EXPECT_TRUE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
"androidboot.disable_media_store_maintenance=1"));
}
-TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_ArcVmUreadaheadModeReadahead) {
+TEST_F(ArcVmClientAdapterTest, StartUpgradeArc_ArcVmUreadaheadMode) {
StartParams start_params(GetPopulatedStartParams());
SetValidUserInfo();
StartMiniArcWithParams(true, std::move(start_params));
UpgradeParams params(GetPopulatedUpgradeParams());
UpgradeArcWithParams(true, std::move(params));
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
- EXPECT_TRUE(
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
+ EXPECT_FALSE(
base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
- "androidboot.arcvm_ureadahead_mode=readahead"));
+ "androidboot.arcvm_ureadahead_mode=generate"));
}
TEST_F(ArcVmClientAdapterTest, StartMiniArc_EnablePaiGeneration) {
@@ -1306,7 +1316,7 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_PaiGenerationDefaultDisabled) {
TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmParams) {
SetValidUserInfo();
StartMiniArc();
- ASSERT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+ ASSERT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
// Verify parameters
const auto& params = GetTestConciergeClient()->start_arc_vm_request();
@@ -1324,78 +1334,105 @@ TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmParams) {
TEST_F(ArcVmClientAdapterTest, CrosvmCrash) {
SetValidUserInfo();
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
UpgradeArc(true);
// Kill crosvm and verify StopArcInstance is called.
- SendVmStoppedSignal();
+ SendVmStoppedSignal(vm_tools::concierge::VM_EXITED);
run_loop()->Run();
- EXPECT_TRUE(arc_instance_stopped_called());
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_FALSE(is_system_shutdown().value());
+}
+
+// Tests that vm_concierge shutdown is handled properly.
+TEST_F(ArcVmClientAdapterTest, ConciergeShutdown) {
+ SetValidUserInfo();
+ StartMiniArc();
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
+ UpgradeArc(true);
+
+ // vm_concierge sends a VmStoppedSignal when shutting down.
+ SendVmStoppedSignal(vm_tools::concierge::SERVICE_SHUTDOWN);
+ run_loop()->Run();
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_TRUE(is_system_shutdown().value());
+
+ // Verify StopArcInstance is NOT called when vm_concierge stops since
+ // the observer has already been called.
+ RecreateRunLoop();
+ reset_is_system_shutdown();
+ SendNameOwnerChangedSignal();
+ run_loop()->RunUntilIdle();
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
// Tests that vm_concierge crash is handled properly.
TEST_F(ArcVmClientAdapterTest, ConciergeCrash) {
SetValidUserInfo();
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
UpgradeArc(true);
// Kill vm_concierge and verify StopArcInstance is called.
SendNameOwnerChangedSignal();
run_loop()->Run();
- EXPECT_TRUE(arc_instance_stopped_called());
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_FALSE(is_system_shutdown().value());
}
// Tests the case where crosvm crashes, then vm_concierge crashes too.
TEST_F(ArcVmClientAdapterTest, CrosvmAndConciergeCrashes) {
SetValidUserInfo();
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
UpgradeArc(true);
// Kill crosvm and verify StopArcInstance is called.
- SendVmStoppedSignal();
+ SendVmStoppedSignal(vm_tools::concierge::VM_EXITED);
run_loop()->Run();
- EXPECT_TRUE(arc_instance_stopped_called());
+ ASSERT_TRUE(is_system_shutdown().has_value());
+ EXPECT_FALSE(is_system_shutdown().value());
// Kill vm_concierge and verify StopArcInstance is NOT called since
// the observer has already been called.
RecreateRunLoop();
- reset_arc_instance_stopped_called();
+ reset_is_system_shutdown();
SendNameOwnerChangedSignal();
run_loop()->RunUntilIdle();
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
// Tests the case where a unknown VmStopped signal is sent to Chrome.
TEST_F(ArcVmClientAdapterTest, VmStoppedSignal_UnknownCid) {
SetValidUserInfo();
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
+ EXPECT_FALSE(is_system_shutdown().has_value());
UpgradeArc(true);
- SendVmStoppedSignalForCid(42); // unknown CID
+ SendVmStoppedSignalForCid(vm_tools::concierge::STOP_VM_REQUESTED,
+ 42); // unknown CID
run_loop()->RunUntilIdle();
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
// Tests the case where a stale VmStopped signal is sent to Chrome.
TEST_F(ArcVmClientAdapterTest, VmStoppedSignal_Stale) {
- SendVmStoppedSignalForCid(42);
+ SendVmStoppedSignalForCid(vm_tools::concierge::STOP_VM_REQUESTED, 42);
run_loop()->RunUntilIdle();
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
// Tests the case where a VmStopped signal not for ARCVM (e.g. Termina) is sent
// to Chrome.
TEST_F(ArcVmClientAdapterTest, VmStoppedSignal_Termina) {
- SendVmStoppedSignalNotForArcVm();
+ SendVmStoppedSignalNotForArcVm(vm_tools::concierge::STOP_VM_REQUESTED);
run_loop()->RunUntilIdle();
- EXPECT_FALSE(arc_instance_stopped_called());
+ EXPECT_FALSE(is_system_shutdown().has_value());
}
// Tests that receiving VmStarted signal is no-op.
@@ -1417,7 +1454,7 @@ TEST_F(ArcVmClientAdapterTest, KernelParam_RO) {
set_host_rootfs_writable(false);
set_system_image_ext_format(false);
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
// Check "rw" is not in |params|.
auto request = GetTestConciergeClient()->start_arc_vm_request();
@@ -1430,7 +1467,7 @@ TEST_F(ArcVmClientAdapterTest, KernelParam_RW) {
set_host_rootfs_writable(true);
set_system_image_ext_format(true);
StartMiniArc();
- EXPECT_TRUE(GetTestConciergeClient()->start_arc_vm_called());
+ EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1);
// Check "rw" is in |params|.
auto request = GetTestConciergeClient()->start_arc_vm_request();
@@ -1598,19 +1635,6 @@ TEST_F(ArcVmClientAdapterTest, BintaryTranslationTypeNoNativeBridgeExperiment) {
"androidboot.native_bridge=libhoudini.so"));
}
-// Tests that "readahead" mode is used by default.
-TEST_F(ArcVmClientAdapterTest, TestGetArcVmUreadaheadModeDefault) {
- StartParams start_params(GetPopulatedStartParams());
- SetValidUserInfo();
- StartMiniArcWithParams(true, std::move(start_params));
- EXPECT_TRUE(
- base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
- "androidboot.arcvm_ureadahead_mode=readahead"));
- EXPECT_FALSE(
- base::Contains(GetTestConciergeClient()->start_arc_vm_request().params(),
- "androidboot.arcvm_ureadahead_mode=generate"));
-}
-
// Tests that the "generate" command line switches the mode.
TEST_F(ArcVmClientAdapterTest, TestGetArcVmUreadaheadModeGenerate) {
base::CommandLine::ForCurrentProcess()->InitFromArgv(
@@ -1731,6 +1755,106 @@ TEST_F(ArcVmClientAdapterTest, DisableDownloadProviderEnforced) {
"androidboot.disable_download_provider=1"));
}
+TEST_F(ArcVmClientAdapterTest, TrimVmMemory_Success) {
+ SetValidUserInfo();
+
+ vm_tools::concierge::ReclaimVmMemoryResponse response;
+ response.set_success(true);
+ GetTestConciergeClient()->set_reclaim_vm_memory_response(response);
+
+ bool result = false;
+ std::string reason("non empty");
+ adapter()->TrimVmMemory(base::BindLambdaForTesting(
+ [&result, &reason](bool success, const std::string& failure_reason) {
+ result = success;
+ reason = failure_reason;
+ }));
+ run_loop()->RunUntilIdle();
+ EXPECT_TRUE(result);
+ EXPECT_TRUE(reason.empty());
+}
+
+TEST_F(ArcVmClientAdapterTest, TrimVmMemory_Failure) {
+ SetValidUserInfo();
+
+ constexpr const char kReason[] = "This is the reason";
+ vm_tools::concierge::ReclaimVmMemoryResponse response;
+ response.set_success(false);
+ response.set_failure_reason(kReason);
+ GetTestConciergeClient()->set_reclaim_vm_memory_response(response);
+
+ bool result = true;
+ std::string reason;
+ adapter()->TrimVmMemory(base::BindLambdaForTesting(
+ [&result, &reason](bool success, const std::string& failure_reason) {
+ result = success;
+ reason = failure_reason;
+ }));
+ run_loop()->RunUntilIdle();
+ EXPECT_FALSE(result);
+ EXPECT_EQ(kReason, reason);
+}
+
+TEST_F(ArcVmClientAdapterTest, TrimVmMemory_EmptyResponse) {
+ SetValidUserInfo();
+
+ // By default, the fake concierge client returns an empty response.
+ // This is to make sure TrimMemoty() can handle such a response.
+ bool result = true;
+ std::string reason;
+ adapter()->TrimVmMemory(base::BindLambdaForTesting(
+ [&result, &reason](bool success, const std::string& failure_reason) {
+ result = success;
+ reason = failure_reason;
+ }));
+ run_loop()->RunUntilIdle();
+ EXPECT_FALSE(result);
+ EXPECT_FALSE(reason.empty());
+}
+
+TEST_F(ArcVmClientAdapterTest, TrimVmMemory_EmptyUserIdHash) {
+ adapter()->SetUserInfo(cryptohome::Identification(), std::string(),
+ std::string());
+
+ constexpr const char kReason[] = "This is the reason";
+ vm_tools::concierge::ReclaimVmMemoryResponse response;
+ response.set_success(false);
+ response.set_failure_reason(kReason);
+ GetTestConciergeClient()->set_reclaim_vm_memory_response(response);
+
+ bool result = true;
+ std::string reason;
+ adapter()->TrimVmMemory(base::BindLambdaForTesting(
+ [&result, &reason](bool success, const std::string& failure_reason) {
+ result = success;
+ reason = failure_reason;
+ }));
+ run_loop()->RunUntilIdle();
+ EXPECT_FALSE(result);
+ // When |user_id_hash_| is empty, the call will fail without talking to
+ // Concierge.
+ EXPECT_NE(kReason, reason);
+ EXPECT_FALSE(reason.empty());
+}
+
+TEST_F(ArcVmClientAdapterTest, ArcVmUseHugePagesEnabled) {
+ base::CommandLine::ForCurrentProcess()->InitFromArgv(
+ {"", "--arcvm-use-hugepages"});
+ StartParams start_params(GetPopulatedStartParams());
+ SetValidUserInfo();
+ StartMiniArcWithParams(true, std::move(start_params));
+ auto request = GetTestConciergeClient()->start_arc_vm_request();
+ EXPECT_TRUE(request.use_hugepages());
+}
+
+TEST_F(ArcVmClientAdapterTest, ArcVmUseHugePagesDisabled) {
+ StartParams start_params(GetPopulatedStartParams());
+ SetValidUserInfo();
+ StartMiniArcWithParams(true, std::move(start_params));
+ auto request = GetTestConciergeClient()->start_arc_vm_request();
+ EXPECT_FALSE(request.use_hugepages());
+}
+
struct DalvikMemoryProfileTestParam {
// Requested profile.
StartParams::DalvikMemoryProfile profile;
diff --git a/chromium/components/arc/session/connection_holder.h b/chromium/components/arc/session/connection_holder.h
index 542b19fb47c..19f33fe54fd 100644
--- a/chromium/components/arc/session/connection_holder.h
+++ b/chromium/components/arc/session/connection_holder.h
@@ -6,7 +6,6 @@
#define COMPONENTS_ARC_SESSION_CONNECTION_HOLDER_H_
#include <memory>
-#include <string>
#include <type_traits>
#include <utility>
diff --git a/chromium/components/arc/storage_manager/arc_storage_manager.cc b/chromium/components/arc/storage_manager/arc_storage_manager.cc
index 855bffb0385..16a437117c5 100644
--- a/chromium/components/arc/storage_manager/arc_storage_manager.cc
+++ b/chromium/components/arc/storage_manager/arc_storage_manager.cc
@@ -42,6 +42,12 @@ ArcStorageManager* ArcStorageManager::GetForBrowserContext(
return ArcStorageManagerFactory::GetForBrowserContext(context);
}
+// static
+ArcStorageManager* ArcStorageManager::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcStorageManagerFactory::GetForBrowserContextForTesting(context);
+}
+
ArcStorageManager::ArcStorageManager(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service) {}
diff --git a/chromium/components/arc/storage_manager/arc_storage_manager.h b/chromium/components/arc/storage_manager/arc_storage_manager.h
index 10e7bd4a51e..e56c9b531d2 100644
--- a/chromium/components/arc/storage_manager/arc_storage_manager.h
+++ b/chromium/components/arc/storage_manager/arc_storage_manager.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H_
#define COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H_
-#include <memory>
-
#include "base/callback.h"
#include "base/macros.h"
#include "components/arc/mojom/storage_manager.mojom.h"
@@ -27,6 +25,8 @@ class ArcStorageManager : public KeyedService {
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcStorageManager* GetForBrowserContext(
content::BrowserContext* context);
+ static ArcStorageManager* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
ArcStorageManager(content::BrowserContext* context,
ArcBridgeService* bridge_service);
diff --git a/chromium/components/arc/storage_manager/arc_storage_manager_unittest.cc b/chromium/components/arc/storage_manager/arc_storage_manager_unittest.cc
new file mode 100644
index 00000000000..d2784b0c016
--- /dev/null
+++ b/chromium/components/arc/storage_manager/arc_storage_manager_unittest.cc
@@ -0,0 +1,83 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/storage_manager/arc_storage_manager.h"
+
+#include "base/test/bind.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/session/arc_bridge_service.h"
+#include "components/arc/test/connection_holder_util.h"
+#include "components/arc/test/fake_storage_manager_instance.h"
+#include "components/arc/test/test_browser_context.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcStorageManagerTest : public testing::Test {
+ protected:
+ ArcStorageManagerTest()
+ : bridge_(ArcStorageManager::GetForBrowserContextForTesting(&context_)) {
+ ArcServiceManager::Get()
+ ->arc_bridge_service()
+ ->storage_manager()
+ ->SetInstance(&storage_manager_instance_);
+ WaitForInstanceReady(
+ ArcServiceManager::Get()->arc_bridge_service()->storage_manager());
+ }
+ ArcStorageManagerTest(const ArcStorageManagerTest&) = delete;
+ ArcStorageManagerTest& operator=(const ArcStorageManagerTest&) = delete;
+ ~ArcStorageManagerTest() override = default;
+
+ const FakeStorageManagerInstance* storage_manager_instance() const {
+ return &storage_manager_instance_;
+ }
+ ArcStorageManager* bridge() { return bridge_; }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ ArcServiceManager arc_service_manager_;
+ FakeStorageManagerInstance storage_manager_instance_;
+ TestBrowserContext context_;
+ ArcStorageManager* const bridge_;
+};
+
+TEST_F(ArcStorageManagerTest, ConstructDestruct) {}
+
+// Tests that calling OpenPrivateVolumeSettings() ends up calling the mojo
+// instance.
+TEST_F(ArcStorageManagerTest, OpenPrivateVolumeSettings) {
+ ASSERT_NE(nullptr, bridge());
+ EXPECT_TRUE(bridge()->OpenPrivateVolumeSettings());
+ EXPECT_EQ(
+ 1u,
+ storage_manager_instance()->num_open_private_volume_settings_called());
+}
+
+// Tests that calling GetApplicationsSize() ends up calling the mojo instance.
+// Also verifies that the bridge passes the callback to the instance.
+TEST_F(ArcStorageManagerTest, GetApplicationsSize) {
+ ASSERT_NE(nullptr, bridge());
+ bool called = false;
+ EXPECT_TRUE(bridge()->GetApplicationsSize(base::BindLambdaForTesting(
+ [&called](bool, mojom::ApplicationsSizePtr) { called = true; })));
+ EXPECT_EQ(1u, storage_manager_instance()->num_get_applications_size_called());
+ EXPECT_TRUE(called);
+}
+
+// Tests that calling DeleteApplicationsCache() ends up calling the mojo
+// instance Also verifies that the bridge passes the callback to the instance.
+TEST_F(ArcStorageManagerTest, DeleteApplicationsCache) {
+ ASSERT_NE(nullptr, bridge());
+ bool called = false;
+ EXPECT_TRUE(bridge()->DeleteApplicationsCache(
+ base::BindLambdaForTesting([&called]() { called = true; })));
+ EXPECT_EQ(1u,
+ storage_manager_instance()->num_delete_applications_cache_called());
+ EXPECT_TRUE(called);
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/timer/arc_timer_bridge.cc b/chromium/components/arc/timer/arc_timer_bridge.cc
index eb7542444be..1653a9ee1cb 100644
--- a/chromium/components/arc/timer/arc_timer_bridge.cc
+++ b/chromium/components/arc/timer/arc_timer_bridge.cc
@@ -180,7 +180,7 @@ void ArcTimerBridge::OnDeleteArcTimers(bool result) {
void ArcTimerBridge::OnCreateArcTimers(
std::vector<clockid_t> clock_ids,
CreateTimersCallback callback,
- base::Optional<std::vector<TimerId>> timer_ids) {
+ absl::optional<std::vector<TimerId>> timer_ids) {
// Any old timers associated with the same tag are always cleared by the API
// regardless of the new timers being created successfully or not. Clear the
// cached timer ids in that case.
@@ -217,11 +217,11 @@ void ArcTimerBridge::OnCreateArcTimers(
std::move(callback).Run(mojom::ArcTimerResult::SUCCESS);
}
-base::Optional<ArcTimerBridge::TimerId> ArcTimerBridge::GetTimerId(
+absl::optional<ArcTimerBridge::TimerId> ArcTimerBridge::GetTimerId(
clockid_t clock_id) const {
auto it = timer_ids_.find(clock_id);
- return (it == timer_ids_.end()) ? base::nullopt
- : base::make_optional<TimerId>(it->second);
+ return (it == timer_ids_.end()) ? absl::nullopt
+ : absl::make_optional<TimerId>(it->second);
}
} // namespace arc
diff --git a/chromium/components/arc/timer/arc_timer_bridge.h b/chromium/components/arc/timer/arc_timer_bridge.h
index 5a19f5ce87e..5749a0d5014 100644
--- a/chromium/components/arc/timer/arc_timer_bridge.h
+++ b/chromium/components/arc/timer/arc_timer_bridge.h
@@ -12,13 +12,13 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.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/receiver.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class BrowserContextKeyedServiceFactory;
@@ -72,11 +72,11 @@ class ArcTimerBridge : public KeyedService,
// Callback for powerd's D-Bus API called in |CreateTimers|.
void OnCreateArcTimers(std::vector<clockid_t> clock_ids,
CreateTimersCallback callback,
- base::Optional<std::vector<TimerId>> timer_ids);
+ absl::optional<std::vector<TimerId>> timer_ids);
// Retrieves the timer id corresponding to |clock_id|. If a mapping exists in
- // |timer_ids_| then returns an int32_t >= 0. Else returns base::nullopt.
- base::Optional<TimerId> GetTimerId(clockid_t clock_id) const;
+ // |timer_ids_| then returns an int32_t >= 0. Else returns absl::nullopt.
+ absl::optional<TimerId> GetTimerId(clockid_t clock_id) const;
// Owned by ArcServiceManager.
ArcBridgeService* const arc_bridge_service_;
diff --git a/chromium/components/arc/timer/arc_timer_bridge_unittest.cc b/chromium/components/arc/timer/arc_timer_bridge_unittest.cc
index c421d3baeeb..a122e908977 100644
--- a/chromium/components/arc/timer/arc_timer_bridge_unittest.cc
+++ b/chromium/components/arc/timer/arc_timer_bridge_unittest.cc
@@ -11,7 +11,6 @@
#include "base/callback_helpers.h"
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/files/scoped_file.h"
-#include "base/optional.h"
#include "base/posix/unix_domain_socket.h"
#include "base/run_loop.h"
#include "base/time/time.h"
@@ -30,6 +29,7 @@
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
@@ -67,10 +67,10 @@ class ArcTimerStore {
void ClearTimers() { return arc_timers_.clear(); }
- base::Optional<int> GetTimerReadFd(clockid_t clock_id) {
+ absl::optional<int> GetTimerReadFd(clockid_t clock_id) {
if (!HasTimer(clock_id))
- return base::nullopt;
- return base::Optional<int>(arc_timers_[clock_id].get());
+ return absl::nullopt;
+ return absl::optional<int>(arc_timers_[clock_id].get());
}
bool HasTimer(clockid_t clock_id) const {
@@ -222,7 +222,7 @@ bool ArcTimerTest::WaitForExpiration(clockid_t clock_id) {
// Wait for the host to indicate expiration by watching the read end of the
// socket pair.
- base::Optional<int> timer_read_fd_opt =
+ absl::optional<int> timer_read_fd_opt =
arc_timer_store_.GetTimerReadFd(clock_id);
// This should never happen if the timer was present in the store.
if (!timer_read_fd_opt.has_value()) {
diff --git a/chromium/components/arc/usb/usb_host_bridge.cc b/chromium/components/arc/usb/usb_host_bridge.cc
index ed53d75e7b7..eec3d5f7920 100644
--- a/chromium/components/arc/usb/usb_host_bridge.cc
+++ b/chromium/components/arc/usb/usb_host_bridge.cc
@@ -97,11 +97,18 @@ std::string GetDevicePath(const device::mojom::UsbDeviceInfo& device_info) {
} // namespace
+// static
ArcUsbHostBridge* ArcUsbHostBridge::GetForBrowserContext(
content::BrowserContext* context) {
return ArcUsbHostBridgeFactory::GetForBrowserContext(context);
}
+// static
+ArcUsbHostBridge* ArcUsbHostBridge::GetForBrowserContextForTesting(
+ content::BrowserContext* context) {
+ return ArcUsbHostBridgeFactory::GetForBrowserContextForTesting(context);
+}
+
ArcUsbHostBridge::ArcUsbHostBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service) {
@@ -162,7 +169,7 @@ void ArcUsbHostBridge::RequestPermission(const std::string& guid,
}
void ArcUsbHostBridge::OpenDevice(const std::string& guid,
- const base::Optional<std::string>& package,
+ const absl::optional<std::string>& package,
OpenDeviceCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
@@ -185,17 +192,16 @@ void ArcUsbHostBridge::OpenDevice(const std::string& guid,
return;
}
- auto repeating_callback =
- base::AdaptCallbackForRepeating(std::move(callback));
+ auto split_callback = base::SplitOnceCallback(std::move(callback));
chromeos::PermissionBrokerClient::Get()->OpenPath(
GetDevicePath(*iter->second),
- base::BindOnce(&OnDeviceOpened, repeating_callback),
- base::BindOnce(&OnDeviceOpenError, repeating_callback));
+ base::BindOnce(&OnDeviceOpened, std::move(split_callback.first)),
+ base::BindOnce(&OnDeviceOpenError, std::move(split_callback.second)));
}
void ArcUsbHostBridge::OpenDeviceDeprecated(
const std::string& guid,
- const base::Optional<std::string>& package,
+ const absl::optional<std::string>& package,
OpenDeviceCallback callback) {
LOG(ERROR) << "ArcUsbHostBridge::OpenDeviceDeprecated is deprecated";
OpenDevice(guid, package, std::move(callback));
@@ -300,11 +306,6 @@ std::vector<std::string> ArcUsbHostBridge::GetEventReceiverPackages(
}
void ArcUsbHostBridge::OnDeviceChecked(const std::string& guid, bool allowed) {
- if (!base::FeatureList::IsEnabled(arc::kUsbHostFeature)) {
- VLOG(1) << "AndroidUSBHost: feature is disabled; ignoring";
- return;
- }
-
if (!allowed)
return;
diff --git a/chromium/components/arc/usb/usb_host_bridge.h b/chromium/components/arc/usb/usb_host_bridge.h
index f292a593a8c..b40302e339d 100644
--- a/chromium/components/arc/usb/usb_host_bridge.h
+++ b/chromium/components/arc/usb/usb_host_bridge.h
@@ -53,6 +53,8 @@ class ArcUsbHostBridge : public KeyedService,
// or nullptr if the browser |context| is not allowed to use ARC.
static ArcUsbHostBridge* GetForBrowserContext(
content::BrowserContext* context);
+ static ArcUsbHostBridge* GetForBrowserContextForTesting(
+ content::BrowserContext* context);
// The constructor will register an Observer with ArcBridgeService.
ArcUsbHostBridge(content::BrowserContext* context,
@@ -68,10 +70,10 @@ class ArcUsbHostBridge : public KeyedService,
bool interactive,
RequestPermissionCallback callback) override;
void OpenDeviceDeprecated(const std::string& guid,
- const base::Optional<std::string>& package,
+ const absl::optional<std::string>& package,
OpenDeviceCallback callback) override;
void OpenDevice(const std::string& guid,
- const base::Optional<std::string>& package,
+ const absl::optional<std::string>& package,
OpenDeviceCallback callback) override;
void GetDeviceInfo(const std::string& guid,
GetDeviceInfoCallback callback) override;
diff --git a/chromium/components/arc/usb/usb_host_bridge_unittest.cc b/chromium/components/arc/usb/usb_host_bridge_unittest.cc
new file mode 100644
index 00000000000..9533bcba8c1
--- /dev/null
+++ b/chromium/components/arc/usb/usb_host_bridge_unittest.cc
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/usb/usb_host_bridge.h"
+
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/test/test_browser_context.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcUsbHostBridgeTest : public testing::Test {
+ protected:
+ ArcUsbHostBridgeTest()
+ : bridge_(ArcUsbHostBridge::GetForBrowserContextForTesting(&context_)) {}
+ ArcUsbHostBridgeTest(const ArcUsbHostBridgeTest&) = delete;
+ ArcUsbHostBridgeTest& operator=(const ArcUsbHostBridgeTest&) = delete;
+ ~ArcUsbHostBridgeTest() override = default;
+
+ ArcUsbHostBridge* bridge() { return bridge_; }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ ArcServiceManager arc_service_manager_;
+ TestBrowserContext context_;
+ ArcUsbHostBridge* const bridge_;
+};
+
+TEST_F(ArcUsbHostBridgeTest, ConstructDestruct) {
+ EXPECT_NE(nullptr, bridge());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc/vector_icons/BUILD.gn b/chromium/components/arc/vector_icons/BUILD.gn
new file mode 100644
index 00000000000..6e654ffb35c
--- /dev/null
+++ b/chromium/components/arc/vector_icons/BUILD.gn
@@ -0,0 +1,22 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//components/vector_icons/vector_icons.gni")
+
+aggregate_vector_icons("components_arc_vector_icons") {
+ icon_directory = "."
+
+ sources = [ "compat_mode_splashscreen.icon" ]
+}
+
+source_set("vector_icons") {
+ sources = get_target_outputs(":components_arc_vector_icons")
+
+ deps = [
+ ":components_arc_vector_icons",
+ "//base",
+ "//skia",
+ "//ui/gfx",
+ ]
+}
diff --git a/chromium/components/arc/vector_icons/OWNERS b/chromium/components/arc/vector_icons/OWNERS
new file mode 100644
index 00000000000..d7ec991d34a
--- /dev/null
+++ b/chromium/components/arc/vector_icons/OWNERS
@@ -0,0 +1 @@
+file://components/vector_icons/OWNERS
diff --git a/chromium/components/arc/vector_icons/compat_mode_splashscreen.icon b/chromium/components/arc/vector_icons/compat_mode_splashscreen.icon
new file mode 100644
index 00000000000..9e398e5e5fd
--- /dev/null
+++ b/chromium/components/arc/vector_icons/compat_mode_splashscreen.icon
@@ -0,0 +1,95 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 122,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xAE, 0xCB, 0xFA,
+MOVE_TO, 101, 29.41f,
+H_LINE_TO, 21.51f,
+ARC_TO, 3.53f, 3.53f, 0, 0, 0, 18, 33,
+V_LINE_TO, 90.59f,
+R_H_LINE_TO, 86.57f,
+V_LINE_TO, 33,
+R_ARC_TO, 3.53f, 3.53f, 0, 0, 0, -3.47f, -3.59f,
+CLOSE,
+R_MOVE_TO, -0.2f, 56.32f,
+R_H_LINE_TO, -79,
+V_LINE_TO, 34.5f,
+R_ARC_TO, 1.3f, 1.3f, 0, 0, 1, 1.3f, -1.3f,
+H_LINE_TO, 99.5f,
+R_ARC_TO, 1.3f, 1.3f, 0, 0, 1, 1.3f, 1.3f,
+R_H_LINE_TO, 0,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xF1, 0xF3, 0xF4,
+MOVE_TO, 34.56f, 77,
+R_ARC_TO, 5, 5, 0, 1, 0, -5, -5,
+ARC_TO, 5, 5, 0, 0, 0, 34.56f, 77,
+CLOSE,
+MOVE_TO, 46.61f, 56.59f,
+LINE_TO, 42.12f, 40.38f,
+R_ARC_TO, 1.2f, 1.2f, 0, 0, 0, -1.46f, -0.84f,
+R_ARC_TO, 1.24f, 1.24f, 0, 0, 0, -0.54f, 0.32f,
+R_LINE_TO, -11.79f, 12,
+R_ARC_TO, 1.2f, 1.2f, 0, 0, 0, 0, 1.7f,
+R_ARC_TO, 1.22f, 1.22f, 0, 0, 0, 0.53f, 0.3f,
+R_LINE_TO, 16.28f, 4.21f,
+R_ARC_TO, 1.18f, 1.18f, 0, 0, 0, 1.45f, -1.48f,
+CLOSE,
+MOVE_TO, 54, 63.29f,
+R_LINE_TO, 15.1f, -8.17f,
+R_ARC_TO, 6.58f, 6.58f, 0, 1, 1, 6.58f, 11.4f,
+R_LINE_TO, -0.32f, 0.17f,
+R_LINE_TO, -15.1f, 8.17f,
+R_ARC_TO, 6.58f, 6.58f, 0, 0, 1, -6.58f, -11.4f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x17, 0x4E, 0xA6,
+MOVE_TO, 72.48f, 36.47f,
+H_LINE_TO, 94.63f,
+R_ARC_TO, 1.93f, 1.93f, 0, 0, 1, 1.93f, 1.91f,
+V_LINE_TO, 80.55f,
+R_ARC_TO, 1.94f, 1.94f, 0, 0, 1, -1.93f, 1.92f,
+H_LINE_TO, 72.48f,
+R_ARC_TO, 1.92f, 1.92f, 0, 0, 1, -1.92f, -1.92f,
+V_LINE_TO, 38.38f,
+ARC_TO, 1.92f, 1.92f, 0, 0, 1, 72.48f, 36.47f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xFB, 0xBC, 0x05,
+MOVE_TO, 94, 53.58f,
+R_ARC_TO, 1.31f, 1.31f, 0, 0, 1, -1.83f, -0.27f,
+R_ARC_TO, 1, 1, 0, 0, 1, -0.11f, -0.17f,
+R_ARC_TO, 10.82f, 10.82f, 0, 0, 1, 17.31f, -12.62f,
+R_ARC_TO, 1.32f, 1.32f, 0, 0, 1, 0, 1.87f,
+R_LINE_TO, -0.16f, 0.13f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0x66, 0x9D, 0xF6,
+MOVE_TO, 70.56f, 54.55f,
+V_LINE_TO, 69.29f,
+R_LINE_TO, 4.79f, -2.6f,
+R_ARC_TO, 6.57f, 6.57f, 0, 0, 0, -4.79f, -12.14f,
+CLOSE,
+NEW_PATH,
+PATH_COLOR_ARGB, 0xFF, 0xF8, 0x82, 0xFF,
+MOVE_TO, 109.49f, 65.66f,
+R_ARC_TO, 5.57f, 5.57f, 0, 0, 0, -1.69f, 0.45f,
+R_LINE_TO, -1.88f, 0.36f,
+R_ARC_TO, 5.88f, 5.88f, 0, 0, 1, -4.73f, -0.72f,
+R_ARC_TO, 13.31f, 13.31f, 0, 0, 0, -2.41f, -1.43f,
+R_ARC_TO, 5.27f, 5.27f, 0, 1, 0, -5.25f, 9.14f,
+R_H_LINE_TO, 0,
+R_ARC_TO, 5.35f, 5.35f, 0, 0, 0, 1.59f, 0.59f,
+R_ARC_TO, 31.37f, 31.37f, 0, 0, 0, 4.11f, 0.36f,
+ARC_TO, 6.06f, 6.06f, 0, 0, 1, 103, 76.28f,
+R_LINE_TO, 1.25f, 1.43f,
+LINE_TO, 105.48f, 79,
+R_ARC_TO, 7, 7, 0, 0, 0, 3.39f, 1.61f,
+R_ARC_TO, 7.5f, 7.5f, 0, 0, 0, 8.57f, -4.73f,
+ARC_TO, 7.68f, 7.68f, 0, 0, 0, 112.87f, 66,
+R_LINE_TO, -0.07f, 0,
+R_LINE_TO, -0.27f, -0.09f,
+ARC_TO, 9.15f, 9.15f, 0, 0, 0, 109.49f, 65.66f,
+CLOSE
diff --git a/chromium/components/arc/vector_icons/vector_icons.cc.template b/chromium/components/arc/vector_icons/vector_icons.cc.template
new file mode 100644
index 00000000000..241fa29ec5d
--- /dev/null
+++ b/chromium/components/arc/vector_icons/vector_icons.cc.template
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// vector_icons.cc.template is used to generate vector_icons.cc. Edit the former
+// rather than the latter.
+
+#include "components/arc/vector_icons/vector_icons.h"
+
+#include "components/vector_icons/cc_macros.h"
+#include "ui/gfx/vector_icon_types.h"
+
+#define DECLARE_VECTOR_COMMAND(x) using gfx::x;
+DECLARE_VECTOR_COMMANDS
+
+namespace arc {
+
+TEMPLATE_PLACEHOLDER
+
+}
diff --git a/chromium/components/arc/vector_icons/vector_icons.h.template b/chromium/components/arc/vector_icons/vector_icons.h.template
new file mode 100644
index 00000000000..debe956c3e3
--- /dev/null
+++ b/chromium/components/arc/vector_icons/vector_icons.h.template
@@ -0,0 +1,26 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// vector_icons.h.template is used to generate vector_icons.h. Edit the former
+// rather than the latter.
+
+#ifndef COMPONENTS_ARC_VECTOR_ICONS_VECTOR_ICONS_H_
+#define COMPONENTS_ARC_VECTOR_ICONS_VECTOR_ICONS_H_
+
+namespace gfx {
+struct VectorIcon;
+}
+
+namespace arc {
+
+#define VECTOR_ICON_TEMPLATE_H(icon_name) \
+extern const gfx::VectorIcon icon_name;
+
+TEMPLATE_PLACEHOLDER
+
+#undef VECTOR_ICON_TEMPLATE_H
+
+}
+
+#endif // COMPONENTS_ARC_VECTOR_ICONS_VECTOR_ICONS_H_
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 c34eb3b52c0..bc4557a6c85 100644
--- a/chromium/components/arc/video_accelerator/arc_video_accelerator_util.cc
+++ b/chromium/components/arc/video_accelerator/arc_video_accelerator_util.cc
@@ -49,7 +49,7 @@ std::vector<base::ScopedFD> DuplicateFD(base::ScopedFD fd, size_t num_fds) {
return fds;
}
-base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
+absl::optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
media::VideoPixelFormat pixel_format,
uint64_t modifier,
const gfx::Size& coded_size,
@@ -65,7 +65,7 @@ base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
base::CheckMul(stride, plane_height);
if (!current_size.IsValid()) {
VLOGF(1) << "Invalid stride/height";
- return base::nullopt;
+ return absl::nullopt;
}
color_planes.emplace_back(stride, offset, current_size.ValueOrDie());
@@ -75,7 +75,7 @@ base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
std::move(scoped_fds), color_planes);
}
-base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
+absl::optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
media::VideoPixelFormat pixel_format,
uint64_t modifier,
const gfx::Size& coded_size,
@@ -85,12 +85,12 @@ base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
if (planes.size() != num_planes || planes.size() == 0) {
VLOGF(1) << "Invalid number of dmabuf planes passed: " << planes.size()
<< ", expected: " << num_planes;
- return base::nullopt;
+ return absl::nullopt;
}
if (scoped_fds.size() != num_planes) {
VLOGF(1) << "Invalid number of fds passed: " << scoped_fds.size()
<< ", expected: " << num_planes;
- return base::nullopt;
+ return absl::nullopt;
}
gfx::GpuMemoryBufferHandle gmb_handle;
@@ -101,11 +101,11 @@ base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
// 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;
+ return absl::nullopt;
}
if (!base::IsValueInRangeForNumericType<uint64_t>(planes[i].offset)) {
VLOGF(1) << "Invalid offset";
- return base::nullopt;
+ return absl::nullopt;
}
uint32_t stride = base::checked_cast<uint32_t>(planes[i].stride);
uint64_t offset = base::checked_cast<uint64_t>(planes[i].offset);
@@ -115,7 +115,7 @@ base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
}
if (!media::VerifyGpuMemoryBufferHandle(pixel_format, coded_size, gmb_handle))
- return base::nullopt;
+ return absl::nullopt;
return gmb_handle;
}
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 2da7453333b..276ec5f89d9 100644
--- a/chromium/components/arc/video_accelerator/arc_video_accelerator_util.h
+++ b/chromium/components/arc/video_accelerator/arc_video_accelerator_util.h
@@ -9,11 +9,11 @@
#include <vector>
#include "base/files/scoped_file.h"
-#include "base/optional.h"
#include "components/arc/video_accelerator/video_frame_plane.h"
#include "media/base/color_plane_layout.h"
#include "media/base/video_types.h"
#include "mojo/public/cpp/system/handle.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_memory_buffer.h"
@@ -29,14 +29,14 @@ std::vector<base::ScopedFD> DuplicateFD(base::ScopedFD fd, size_t num_fds);
// Return GpuMemoryBufferHandle iff |planes| are valid for a video frame located
// on |scoped_fds| and of |pixel_format| and |coded_size|. Otherwise
-// returns base::nullopt.
-base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
+// returns absl::nullopt.
+absl::optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
media::VideoPixelFormat pixel_format,
uint64_t modifier,
const gfx::Size& coded_size,
std::vector<base::ScopedFD> scoped_fds,
const std::vector<VideoFramePlane>& planes);
-base::Optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
+absl::optional<gfx::GpuMemoryBufferHandle> CreateGpuMemoryBufferHandle(
media::VideoPixelFormat pixel_format,
uint64_t modifier,
const gfx::Size& coded_size,
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 3c9838d3104..1b44a5908ec 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
@@ -356,7 +356,7 @@ void GpuArcVideoDecodeAccelerator::InitializeTask(
client_count_++;
VLOGF(2) << "Number of concurrent clients: " << client_count_;
- secure_mode_ = base::nullopt;
+ secure_mode_ = absl::nullopt;
error_state_ = false;
pending_requests_ = {};
pending_flush_callbacks_ = {};
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 9f59f1f8cdb..a539ba3f023 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
@@ -12,7 +12,6 @@
#include "base/callback_forward.h"
#include "base/files/scoped_file.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "components/arc/mojom/video_decode_accelerator.mojom.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
@@ -20,6 +19,7 @@
#include "media/video/video_decode_accelerator.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace arc {
@@ -177,7 +177,7 @@ class GpuArcVideoDecodeAccelerator
size_t protected_input_buffer_count_ = 0;
- base::Optional<bool> secure_mode_ = base::nullopt;
+ absl::optional<bool> secure_mode_ = absl::nullopt;
size_t output_buffer_count_ = 0;
DecoderState decoder_state_ = DecoderState::kDecoding;
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 62721ce2c05..ae480b00d5b 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
@@ -191,7 +191,7 @@ void GpuArcVideoEncodeAccelerator::Encode(
return;
}
- base::Optional<gfx::BufferFormat> buffer_format =
+ absl::optional<gfx::BufferFormat> buffer_format =
VideoPixelFormatToGfxBufferFormat(format);
if (!format) {
DLOG(ERROR) << "Unexpected format: " << format;
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 8d4bfd764f7..ea1cd6091ae 100644
--- a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
+++ b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge.cc
@@ -96,7 +96,8 @@ ArcVolumeMounterBridge::ArcVolumeMounterBridge(content::BrowserContext* context,
}
ArcVolumeMounterBridge::~ArcVolumeMounterBridge() {
- DiskMountManager::GetInstance()->RemoveObserver(this);
+ if (DiskMountManager::GetInstance()) // for testing
+ DiskMountManager::GetInstance()->RemoveObserver(this);
arc_bridge_service_->volume_mounter()->SetHost(nullptr);
arc_bridge_service_->volume_mounter()->RemoveObserver(this);
}
@@ -131,8 +132,8 @@ void ArcVolumeMounterBridge::SendMountEventForMyFiles() {
// TODO(niwa): Add a new DeviceType enum value for MyFiles.
chromeos::DeviceType device_type = chromeos::DeviceType::DEVICE_TYPE_SD;
- // Conditionally set MyFiles to be visible for P and invisible for R. In R, we use IsVisibleRead
- // so this is not needed.
+ // Conditionally set MyFiles to be visible for P and invisible for R. In R, we
+ // use IsVisibleRead so this is not needed.
volume_mounter_instance->OnMountEvent(mojom::MountPointInfo::New(
DiskMountManager::MOUNTING, kMyFilesPath, kMyFilesPath, kMyFilesUuid,
device_label, device_type, !IsArcVmEnabled()));
diff --git a/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge_unittest.cc b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge_unittest.cc
new file mode 100644
index 00000000000..c6695c882e9
--- /dev/null
+++ b/chromium/components/arc/volume_mounter/arc_volume_mounter_bridge_unittest.cc
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/volume_mounter/arc_volume_mounter_bridge.h"
+
+#include "chromeos/disks/disk_mount_manager.h"
+#include "chromeos/disks/mock_disk_mount_manager.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/test/test_browser_context.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+namespace {
+
+class ArcVolumeMounterBridgeTest : public testing::Test {
+ protected:
+ ArcVolumeMounterBridgeTest() = default;
+ ArcVolumeMounterBridgeTest(const ArcVolumeMounterBridgeTest&) = delete;
+ ArcVolumeMounterBridgeTest& operator=(const ArcVolumeMounterBridgeTest&) =
+ delete;
+ ~ArcVolumeMounterBridgeTest() override = default;
+
+ void SetUp() override {
+ chromeos::disks::DiskMountManager::InitializeForTesting(
+ new chromeos::disks::MockDiskMountManager);
+ bridge_ = ArcVolumeMounterBridge::GetForBrowserContextForTesting(&context_);
+ }
+ void TearDown() override { chromeos::disks::DiskMountManager::Shutdown(); }
+
+ ArcVolumeMounterBridge* bridge() { return bridge_; }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ ArcServiceManager arc_service_manager_;
+ TestBrowserContext context_;
+ ArcVolumeMounterBridge* bridge_ = nullptr;
+};
+
+TEST_F(ArcVolumeMounterBridgeTest, ConstructDestruct) {
+ EXPECT_NE(nullptr, bridge());
+}
+
+} // namespace
+} // namespace arc
diff --git a/chromium/components/arc_strings.grdp b/chromium/components/arc_strings.grdp
index 217f154adbe..50548d374b9 100644
--- a/chromium/components/arc_strings.grdp
+++ b/chromium/components/arc_strings.grdp
@@ -13,16 +13,25 @@
<message name="IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_DONT_ASK_ME" desc="Label for check box that prevents the dialog from being shown in the future">
Don't ask me again for this app
</message>
- <message name="IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_PHONE" desc="Label for button to resize the window to phone size">
+ <message name="IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_PHONE" desc="Item in a list of possible sizes for the app. Makes the app in a portrait, phone size.">
Phone
</message>
- <message name="IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TABLET" desc="Label for button to resize the window to tablet size">
+ <message name="IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TABLET" desc="Item in a list of possible sizes for the app. Makes the app bigger and wider in a tablet size.">
Tablet
</message>
- <message name="IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_DESKTOP" desc="Label for button to resize the window to desktop size">
- Desktop
+ <message name="IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_DESKTOP" desc="Item in a list of possible sizes for the app. Makes the app expand to the whole screen.">
+ Maximized
</message>
- <message name="IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_RESIZE_SETTINGS" desc="Label for button to open resize settings">
- Resize Settings
+ <message name="IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_RESIZE_SETTINGS" desc="Label for the button to allow the user to go to resize settings.">
+ Settings
+ </message>
+ <message name="IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_TITLE" desc="A Dialog title of splash screen to advertise the app is designed for mobile.">
+ This app is designed for mobile
+ </message>
+ <message name="IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_BODY" desc="A Dialog body of splash screen to advertise resize-lock feature.">
+ It may behave unexpectedly if resized. You can now limit the ability to resize apps in <ph name="SETTINGS">$1<ex>Settings</ex></ph>.
+ </message>
+ <message name="IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_LINK" desc="Text of link to app settings.">
+ Settings
</message>
</grit-part>
diff --git a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_DESKTOP.png.sha1 b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_DESKTOP.png.sha1
index 5303e0529b7..cd3efe488b7 100644
--- a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_DESKTOP.png.sha1
+++ b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_DESKTOP.png.sha1
@@ -1 +1 @@
-67aece4bf2458b01f47e9c175c90cc836ff2f412 \ No newline at end of file
+6e4a6e86d83eab4d63ac64dcbfb0320b060fd659 \ No newline at end of file
diff --git a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_PHONE.png.sha1 b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_PHONE.png.sha1
index 5303e0529b7..cd3efe488b7 100644
--- a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_PHONE.png.sha1
+++ b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_PHONE.png.sha1
@@ -1 +1 @@
-67aece4bf2458b01f47e9c175c90cc836ff2f412 \ No newline at end of file
+6e4a6e86d83eab4d63ac64dcbfb0320b060fd659 \ No newline at end of file
diff --git a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_RESIZE_SETTINGS.png.sha1 b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_RESIZE_SETTINGS.png.sha1
index 5303e0529b7..cd3efe488b7 100644
--- a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_RESIZE_SETTINGS.png.sha1
+++ b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_RESIZE_SETTINGS.png.sha1
@@ -1 +1 @@
-67aece4bf2458b01f47e9c175c90cc836ff2f412 \ No newline at end of file
+6e4a6e86d83eab4d63ac64dcbfb0320b060fd659 \ No newline at end of file
diff --git a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TABLET.png.sha1 b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TABLET.png.sha1
index 5303e0529b7..cd3efe488b7 100644
--- a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TABLET.png.sha1
+++ b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TABLET.png.sha1
@@ -1 +1 @@
-67aece4bf2458b01f47e9c175c90cc836ff2f412 \ No newline at end of file
+6e4a6e86d83eab4d63ac64dcbfb0320b060fd659 \ No newline at end of file
diff --git a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_BODY.png.sha1 b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_BODY.png.sha1
new file mode 100644
index 00000000000..f603b5697ee
--- /dev/null
+++ b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_BODY.png.sha1
@@ -0,0 +1 @@
+e1ffa15d59184a92a203699d0393d5bba43dad67 \ No newline at end of file
diff --git a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_LINK.png.sha1 b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_LINK.png.sha1
new file mode 100644
index 00000000000..f603b5697ee
--- /dev/null
+++ b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_LINK.png.sha1
@@ -0,0 +1 @@
+e1ffa15d59184a92a203699d0393d5bba43dad67 \ No newline at end of file
diff --git a/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_TITLE.png.sha1 b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_TITLE.png.sha1
new file mode 100644
index 00000000000..f603b5697ee
--- /dev/null
+++ b/chromium/components/arc_strings_grdp/IDS_ARC_COMPAT_MODE_SPLASH_SCREEN_TITLE.png.sha1
@@ -0,0 +1 @@
+e1ffa15d59184a92a203699d0393d5bba43dad67 \ No newline at end of file
diff --git a/chromium/components/assist_ranker/assist_ranker_service.h b/chromium/components/assist_ranker/assist_ranker_service.h
index bb11a4789b2..8e37c3599eb 100644
--- a/chromium/components/assist_ranker/assist_ranker_service.h
+++ b/chromium/components/assist_ranker/assist_ranker_service.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_ASSIST_RANKER_ASSIST_RANKER_SERVICE_H_
#define COMPONENTS_ASSIST_RANKER_ASSIST_RANKER_SERVICE_H_
-#include <memory>
-#include <string>
-
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
diff --git a/chromium/components/assist_ranker/base_predictor.h b/chromium/components/assist_ranker/base_predictor.h
index c89a4ae69c7..b4ba028ab46 100644
--- a/chromium/components/assist_ranker/base_predictor.h
+++ b/chromium/components/assist_ranker/base_predictor.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "components/assist_ranker/predictor_config.h"
#include "components/assist_ranker/ranker_model_loader.h"
diff --git a/chromium/components/assist_ranker/base_predictor_unittest.cc b/chromium/components/assist_ranker/base_predictor_unittest.cc
index 5ca2d598eef..75bdb2f7543 100644
--- a/chromium/components/assist_ranker/base_predictor_unittest.cc
+++ b/chromium/components/assist_ranker/base_predictor_unittest.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/metrics/field_trial_params.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "components/assist_ranker/fake_ranker_model_loader.h"
diff --git a/chromium/components/assist_ranker/binary_classifier_predictor_unittest.cc b/chromium/components/assist_ranker/binary_classifier_predictor_unittest.cc
index 9d66221a249..61375ebcc27 100644
--- a/chromium/components/assist_ranker/binary_classifier_predictor_unittest.cc
+++ b/chromium/components/assist_ranker/binary_classifier_predictor_unittest.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
#include "base/test/scoped_feature_list.h"
#include "components/assist_ranker/fake_ranker_model_loader.h"
#include "components/assist_ranker/proto/ranker_model.pb.h"
diff --git a/chromium/components/assist_ranker/classifier_predictor_unittest.cc b/chromium/components/assist_ranker/classifier_predictor_unittest.cc
index 8718e151234..68fb558b297 100644
--- a/chromium/components/assist_ranker/classifier_predictor_unittest.cc
+++ b/chromium/components/assist_ranker/classifier_predictor_unittest.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
#include "base/test/scoped_feature_list.h"
#include "components/assist_ranker/example_preprocessing.h"
#include "components/assist_ranker/fake_ranker_model_loader.h"
diff --git a/chromium/components/assist_ranker/predictor_config_definitions.cc b/chromium/components/assist_ranker/predictor_config_definitions.cc
index 5448f6450eb..3b8890dd843 100644
--- a/chromium/components/assist_ranker/predictor_config_definitions.cc
+++ b/chromium/components/assist_ranker/predictor_config_definitions.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "components/assist_ranker/predictor_config_definitions.h"
+
+#include "base/metrics/field_trial_params.h"
#include "components/assist_ranker/base_predictor.h"
namespace assist_ranker {
diff --git a/chromium/components/assist_ranker/predictor_config_definitions.h b/chromium/components/assist_ranker/predictor_config_definitions.h
index 431e0b4e754..34ae1c414df 100644
--- a/chromium/components/assist_ranker/predictor_config_definitions.h
+++ b/chromium/components/assist_ranker/predictor_config_definitions.h
@@ -5,10 +5,6 @@
#ifndef COMPONENTS_ASSIST_RANKER_PREDICTOR_CONFIG_DEFINITIONS_H_
#define COMPONENTS_ASSIST_RANKER_PREDICTOR_CONFIG_DEFINITIONS_H_
-#include <memory>
-#include <string>
-#include <unordered_map>
-
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "build/build_config.h"
diff --git a/chromium/components/assist_ranker/ranker_model_loader.h b/chromium/components/assist_ranker/ranker_model_loader.h
index 392828fe074..e55fa9d9c5a 100644
--- a/chromium/components/assist_ranker/ranker_model_loader.h
+++ b/chromium/components/assist_ranker/ranker_model_loader.h
@@ -6,7 +6,6 @@
#define COMPONENTS_ASSIST_RANKER_RANKER_MODEL_LOADER_H_
#include <memory>
-#include <string>
#include "base/callback.h"
#include "components/assist_ranker/ranker_model.h"
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 3d643c1f32c..e0a9ef7b6e1 100644
--- a/chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc
+++ b/chromium/components/assist_ranker/ranker_model_loader_impl_unittest.cc
@@ -13,7 +13,6 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
-#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
diff --git a/chromium/components/autofill/DEPS b/chromium/components/autofill/DEPS
index 1e677456fea..d3318af1995 100644
--- a/chromium/components/autofill/DEPS
+++ b/chromium/components/autofill/DEPS
@@ -13,6 +13,7 @@ include_rules = [
# Autofill is a layered component; subdirectories must explicitly introduce
# the ability to use the content layer as appropriate.
"-components/autofill/content",
+ "-components/android_autofill",
# This directory contains build flags and does not pull all of PPAPI in.
"+ppapi/buildflags",
diff --git a/chromium/components/autofill/OWNERS b/chromium/components/autofill/OWNERS
index d2870efd3f4..ad9c7f5168a 100644
--- a/chromium/components/autofill/OWNERS
+++ b/chromium/components/autofill/OWNERS
@@ -10,3 +10,4 @@ mahmadi@chromium.org
rogerm@chromium.org
sebsg@chromium.org
tmartino@chromium.org
+mamir@chromium.org
diff --git a/chromium/components/autofill/PRESUBMIT.py b/chromium/components/autofill/PRESUBMIT.py
index 677910f8ff8..2cb87c0da71 100644
--- a/chromium/components/autofill/PRESUBMIT.py
+++ b/chromium/components/autofill/PRESUBMIT.py
@@ -41,13 +41,19 @@ def _CheckFeatureNames(input_api, output_api):
input_api.re.MULTILINE)
warnings = []
+ def exception(constant, feature):
+ if constant == "AutofillAddressEnhancementVotes" and \
+ feature == "kAutofillAddressEnhancementVotes":
+ return True
+ return False
+
for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
if (f.LocalPath().startswith('components/autofill/') and
f.LocalPath().endswith('features.cc')):
contents = input_api.ReadFile(f)
mismatches = [(constant, feature)
for (constant, feature) in pattern.findall(contents)
- if constant != feature]
+ if constant != feature and not exception(constant, feature)]
if mismatches:
mismatch_strings = ['\t{} -- {}'.format(*m) for m in mismatches]
mismatch_string = format('\n').join(mismatch_strings)
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillActionModeCallback.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillActionModeCallback.java
deleted file mode 100644
index 6921fcab52c..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillActionModeCallback.java
+++ /dev/null
@@ -1,60 +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.autofill;
-
-import android.content.Context;
-import android.view.ActionMode;
-import android.view.Menu;
-import android.view.MenuItem;
-
-/**
- * The class to implement autofill context menu. To match the Android native view behavior, the
- * autofill context menu only appears when there is no text selected.
- */
-public class AutofillActionModeCallback implements ActionMode.Callback {
- private final Context mContext;
- private final AutofillProvider mAutofillProvider;
- private final int mAutofillMenuItemTitle;
- private final int mAutofillMenuItem;
-
- public AutofillActionModeCallback(Context context, AutofillProvider autofillProvider) {
- mContext = context;
- mAutofillProvider = autofillProvider;
- // TODO(michaelbai): Uses the resource directly after sdk roll to Android O MR1.
- // crbug.com/740628
- mAutofillMenuItemTitle =
- mContext.getResources().getIdentifier("autofill", "string", "android");
- mAutofillMenuItem = mContext.getResources().getIdentifier("autofill", "id", "android");
- }
-
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- return mAutofillMenuItemTitle != 0 && mAutofillMenuItem != 0;
- }
-
- @Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- if (mAutofillMenuItemTitle != 0 && mAutofillProvider.shouldQueryAutofillSuggestion()) {
- MenuItem item = menu.add(
- Menu.NONE, mAutofillMenuItem, Menu.CATEGORY_SECONDARY, mAutofillMenuItemTitle);
- item.setShowAsActionFlags(
- MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
- }
- return true;
- }
-
- @Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- if (item.getItemId() == mAutofillMenuItem) {
- mAutofillProvider.queryAutofillSuggestion();
- mode.finish();
- return true;
- }
- return false;
- }
-
- @Override
- public void onDestroyActionMode(ActionMode mode) {}
-}
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillHintsService.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillHintsService.java
deleted file mode 100644
index 14fd7b0e73e..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillHintsService.java
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.autofill;
-
-import android.os.IBinder;
-
-import org.chromium.base.Log;
-import org.chromium.components.autofill_public.IAutofillHintsService;
-import org.chromium.components.autofill_public.IViewTypeCallback;
-import org.chromium.components.autofill_public.ViewType;
-
-import java.util.List;
-
-/**
- * This class is used to talk to autofill service about the view type.
- */
-public class AutofillHintsService {
- private static final String TAG = "AutofillHintsService";
-
- public AutofillHintsService() {
- mBinder = new IAutofillHintsService.Stub() {
- @Override
- public void registerViewTypeCallback(IViewTypeCallback callback) {
- mCallback = callback;
- if (mUnsentViewTypes != null) {
- invokeOnViewTypeAvailable();
- } else if (mQueryFailed != null) {
- invokeOnQueryFailed();
- }
- }
- };
- }
-
- public IBinder getBinder() {
- return mBinder;
- }
-
- public void onViewTypeAvailable(List<ViewType> viewTypes) {
- if (mUnsentViewTypes != null) return;
- mUnsentViewTypes = viewTypes;
- if (mCallback == null) return;
- invokeOnViewTypeAvailable();
- }
-
- public void onQueryFailed() {
- if (mQueryFailed != null) return;
- mQueryFailed = Boolean.TRUE;
- if (mCallback == null) return;
- invokeOnQueryFailed();
- }
-
- private void invokeOnViewTypeAvailable() {
- try {
- mCallback.onViewTypeAvailable(mUnsentViewTypes);
- } catch (Exception e) {
- Log.e(TAG, "onViewTypeAvailable ", e);
- }
- }
-
- private void invokeOnQueryFailed() {
- try {
- mCallback.onQueryFailed();
- } catch (Exception e) {
- Log.e(TAG, "onQueryFailed ", e);
- }
- }
-
- private IAutofillHintsService.Stub mBinder;
- private IViewTypeCallback mCallback;
- private List<ViewType> mUnsentViewTypes;
- private Boolean mQueryFailed;
-}
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java
deleted file mode 100644
index 237cf244e98..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java
+++ /dev/null
@@ -1,230 +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.autofill;
-
-import android.annotation.TargetApi;
-import android.content.ComponentName;
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.Build;
-import android.view.View;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillValue;
-
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.base.CollectionUtil;
-import org.chromium.base.Log;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-
-/**
- * The class to call Android's AutofillManager.
- */
-@TargetApi(Build.VERSION_CODES.O)
-public class AutofillManagerWrapper {
- // Don't change TAG, it is used for runtime log.
- // NOTE: As a result of the above, the tag below still references the name of this class from
- // when it was originally developed specifically for Android WebView.
- public static final String TAG = "AwAutofillManager";
- private static final String AWG_COMPONENT_NAME =
- "com.google.android.gms/com.google.android.gms.autofill.service.AutofillService";
- /**
- * The observer of suggestion window.
- */
- public static interface InputUIObserver { void onInputUIShown(); }
-
- private static class AutofillInputUIMonitor extends AutofillManager.AutofillCallback {
- private WeakReference<AutofillManagerWrapper> mManager;
-
- public AutofillInputUIMonitor(AutofillManagerWrapper manager) {
- mManager = new WeakReference<AutofillManagerWrapper>(manager);
- }
-
- @Override
- public void onAutofillEvent(View view, int virtualId, int event) {
- AutofillManagerWrapper manager = mManager.get();
- if (manager == null) return;
- manager.mIsAutofillInputUIShowing = (event == EVENT_INPUT_SHOWN);
- if (event == EVENT_INPUT_SHOWN) manager.notifyInputUIChange();
- }
- }
-
- private static boolean sIsLoggable;
- private AutofillManager mAutofillManager;
- private boolean mIsAutofillInputUIShowing;
- private AutofillInputUIMonitor mMonitor;
- private boolean mDestroyed;
- private boolean mDisabled;
- private ArrayList<WeakReference<InputUIObserver>> mInputUIObservers;
- // Indicates if AwG is the current Android autofill service.
- private final boolean mIsAwGCurrentAutofillService;
-
- public AutofillManagerWrapper(Context context) {
- updateLogStat();
- if (isLoggable()) log("constructor");
- mAutofillManager = context.getSystemService(AutofillManager.class);
- mDisabled = mAutofillManager == null || !mAutofillManager.isEnabled();
-
- if (mDisabled) {
- mIsAwGCurrentAutofillService = false;
- if (isLoggable()) log("disabled");
- return;
- }
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
- ComponentName componentName = null;
- try {
- componentName = mAutofillManager.getAutofillServiceComponentName();
- } catch (Exception e) {
- // Can't catch com.android.internal.util.SyncResultReceiver.TimeoutException,
- // because
- // - The exception isn't Android API.
- // - Different version of Android handle it differently.
- // Uses Exception to catch various cases. (refer to crbug.com/1186406)
- Log.e(TAG, "getAutofillServiceComponentName", e);
- }
- if (componentName != null) {
- mIsAwGCurrentAutofillService =
- AWG_COMPONENT_NAME.equals(componentName.flattenToString());
- } else {
- mIsAwGCurrentAutofillService = false;
- }
- } else {
- mIsAwGCurrentAutofillService = false;
- }
- mMonitor = new AutofillInputUIMonitor(this);
- mAutofillManager.registerCallback(mMonitor);
- }
-
- public void notifyVirtualValueChanged(View parent, int childId, AutofillValue value) {
- if (mDisabled || checkAndWarnIfDestroyed()) return;
- if (isLoggable()) log("notifyVirtualValueChanged");
- mAutofillManager.notifyValueChanged(parent, childId, value);
- }
-
- public void commit(int submissionSource) {
- if (mDisabled || checkAndWarnIfDestroyed()) return;
- if (isLoggable()) log("commit source:" + submissionSource);
- mAutofillManager.commit();
- }
-
- public void cancel() {
- if (mDisabled || checkAndWarnIfDestroyed()) return;
- if (isLoggable()) log("cancel");
- mAutofillManager.cancel();
- }
-
- public void notifyVirtualViewEntered(View parent, int childId, Rect absBounds) {
- // Log warning only when the autofill is triggered.
- if (mDisabled) {
- Log.w(TAG, "Autofill is disabled: AutofillManager isn't available in given Context.");
- return;
- }
- if (checkAndWarnIfDestroyed()) return;
- if (isLoggable()) log("notifyVirtualViewEntered");
- mAutofillManager.notifyViewEntered(parent, childId, absBounds);
- }
-
- public void notifyVirtualViewExited(View parent, int childId) {
- if (mDisabled || checkAndWarnIfDestroyed()) return;
- if (isLoggable()) log("notifyVirtualViewExited");
- mAutofillManager.notifyViewExited(parent, childId);
- }
-
- public void requestAutofill(View parent, int virtualId, Rect absBounds) {
- if (mDisabled || checkAndWarnIfDestroyed()) return;
- if (isLoggable()) log("requestAutofill");
- mAutofillManager.requestAutofill(parent, virtualId, absBounds);
- }
-
- public boolean isAutofillInputUIShowing() {
- if (mDisabled || checkAndWarnIfDestroyed()) return false;
- if (isLoggable()) log("isAutofillInputUIShowing: " + mIsAutofillInputUIShowing);
- return mIsAutofillInputUIShowing;
- }
-
- public void destroy() {
- if (mDisabled || checkAndWarnIfDestroyed()) return;
- if (isLoggable()) log("destroy");
- try {
- // The binder in the autofill service side might already be dropped,
- // unregisterCallback() will cause various exceptions in this
- // scenario (see crbug.com/1078337), catching RuntimeException here prevents crash.
- mAutofillManager.unregisterCallback(mMonitor);
- } catch (RuntimeException e) {
- // We are not logging anything here since some of the exceptions are raised as 'generic'
- // RuntimeException which makes it difficult to catch and ignore separately; and the
- // RuntimeException seemed only happen in Android O, therefore, isn't actionable.
- } finally {
- mAutofillManager = null;
- mDestroyed = true;
- }
- }
-
- public boolean isDisabled() {
- return mDisabled;
- }
-
- /**
- * Only work for Android P and beyond. Always return false for Android O.
- * @return if the Autofill with Google is the current autofill service.
- */
- public boolean isAwGCurrentAutofillService() {
- return mIsAwGCurrentAutofillService;
- }
-
- private boolean checkAndWarnIfDestroyed() {
- if (mDestroyed) {
- Log.w(TAG, "Application attempted to call on a destroyed AutofillManagerWrapper",
- new Throwable());
- }
- return mDestroyed;
- }
-
- public void addInputUIObserver(InputUIObserver observer) {
- if (observer == null) return;
- if (mInputUIObservers == null) {
- mInputUIObservers = new ArrayList<WeakReference<InputUIObserver>>();
- }
- mInputUIObservers.add(new WeakReference<InputUIObserver>(observer));
- }
-
- @VisibleForTesting
- public void notifyInputUIChange() {
- for (InputUIObserver observer : CollectionUtil.strengthen(mInputUIObservers)) {
- observer.onInputUIShown();
- }
- }
-
- public void notifyNewSessionStarted(boolean hasServerPrediction) {
- updateLogStat();
- if (isLoggable()) log("Session starts, has server prediction = " + hasServerPrediction);
- }
-
- public void onQueryDone(boolean success) {
- if (isLoggable()) log("Query " + (success ? "succeed" : "failed"));
- }
-
- /**
- * Always check isLoggable() before call this method.
- */
- public static void log(String log) {
- // Log.i() instead of Log.d() is used here because log.d() is stripped out in release build.
- Log.i(TAG, log);
- }
-
- public static boolean isLoggable() {
- return sIsLoggable;
- }
-
- private static void updateLogStat() {
- // Use 'setprop log.tag.AwAutofillManager DEBUG' to enable the log at runtime.
- // NOTE: See the comment on TAG above for why this is still AwAutofillManager.
- // Check the system setting directly.
- sIsLoggable = android.util.Log.isLoggable(TAG, Log.DEBUG);
- }
-}
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProvider.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProvider.java
deleted file mode 100644
index 1feb0328e7f..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProvider.java
+++ /dev/null
@@ -1,880 +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.autofill;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.SparseArray;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewStructure;
-import android.view.autofill.AutofillValue;
-
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.StrictModeContext;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.NativeMethods;
-import org.chromium.base.annotations.VerifiesOnO;
-import org.chromium.base.metrics.ScopedSysTraceEvent;
-import org.chromium.components.autofill_public.ViewType;
-import org.chromium.components.version_info.VersionConstants;
-import org.chromium.content_public.browser.RenderCoordinates;
-import org.chromium.content_public.browser.WebContents;
-import org.chromium.content_public.browser.WebContentsAccessibility;
-import org.chromium.ui.DropdownItem;
-import org.chromium.ui.base.ViewAndroidDelegate;
-import org.chromium.ui.base.WindowAndroid;
-import org.chromium.ui.display.DisplayAndroid;
-
-import java.util.ArrayList;
-
-/**
- * This class works with Android autofill service to fill web form, it doesn't use chrome's
- * autofill service or suggestion UI. All methods are supposed to be called in UI thread.
- *
- * AutofillProvider handles one autofill session at time, each call of
- * queryFormFieldAutofill cancels previous session and starts a new one, the
- * calling of other methods shall associate with current session.
- *
- * This class doesn't have 1:1 mapping to native AutofillProviderAndroid; the
- * normal ownership model is that this object is owned by the embedder-specific
- * Java WebContents wrapper (e.g., AwContents.java in //android_webview), and
- * AutofillProviderAndroid is owned by the embedder-specific C++ WebContents
- * wrapper (e.g., native AwContents in //android_webview).
- *
- * VerifiesOnO since it causes class verification errors, see crbug.com/991851.
- */
-@VerifiesOnO
-@TargetApi(Build.VERSION_CODES.O)
-@JNINamespace("autofill")
-public class AutofillProvider {
- private static final String TAG = "AutofillProvider";
-
- // This member is initialize at first use. Not access it directly, always through
- // isQueryServerFieldTypesEnabled().
- private static Boolean sIsQueryServerFieldTypesEnabled;
-
- private static class FocusField {
- public final short fieldIndex;
- public final Rect absBound;
-
- public FocusField(short fieldIndex, Rect absBound) {
- this.fieldIndex = fieldIndex;
- this.absBound = absBound;
- }
- }
- /**
- * The class to wrap the request to framework.
- *
- * Though framework guarantees always giving us the autofill value of current
- * session, we still want to verify this by using unique virtual id which is
- * composed of sessionId and form field index, we don't use the request id
- * which comes from renderer as session id because it is not unique.
- */
- private static class AutofillRequest {
- private static final int INIT_ID = 1; // ID can't be 0 in Android.
- private static int sSessionId = INIT_ID;
- public final int sessionId;
- private FormData mFormData;
- private FocusField mFocusField;
- private AutofillHintsService mAutofillHintsService;
-
- /**
- * @param formData the form of the AutofillRequest.
- * @param focus the current focused field.
- * @param hasServerPrediction whether the server type of formData is valid.
- */
- public AutofillRequest(FormData formData, FocusField focus, boolean hasServerPrediction) {
- sessionId = getNextClientId();
- mFormData = formData;
- mFocusField = focus;
- // Don't need to create binder object if server prediction is already available.
- if (!hasServerPrediction) mAutofillHintsService = new AutofillHintsService();
- }
-
- public void fillViewStructure(ViewStructure structure) {
- structure.setWebDomain(mFormData.mHost);
- structure.setHtmlInfo(structure.newHtmlInfoBuilder("form")
- .addAttribute("name", mFormData.mName)
- .build());
- int index = structure.addChildCount(mFormData.mFields.size());
- short fieldIndex = 0;
- for (FormFieldData field : mFormData.mFields) {
- ViewStructure child = structure.newChild(index++);
- int virtualId = toVirtualId(sessionId, fieldIndex++);
- child.setAutofillId(structure.getAutofillId(), virtualId);
- field.setAutofillId(child.getAutofillId());
- if (field.mAutocompleteAttr != null && !field.mAutocompleteAttr.isEmpty()) {
- child.setAutofillHints(field.mAutocompleteAttr.split(" +"));
- }
- child.setHint(field.mPlaceholder);
-
- RectF bounds = field.getBoundsInContainerViewCoordinates();
- // Field has no scroll.
- child.setDimens((int) bounds.left, (int) bounds.top, 0 /* scrollX*/,
- 0 /* scrollY */, (int) bounds.width(), (int) bounds.height());
- child.setVisibility(field.mVisible ? View.VISIBLE : View.INVISIBLE);
-
- ViewStructure.HtmlInfo.Builder builder =
- child.newHtmlInfoBuilder("input")
- .addAttribute("name", field.mName)
- .addAttribute("type", field.mType)
- .addAttribute("label", field.mLabel)
- .addAttribute("ua-autofill-hints", field.mHeuristicType)
- .addAttribute("id", field.mId);
-
- if (isQueryServerFieldTypesEnabled()) {
- builder.addAttribute("crowdsourcing-autofill-hints", field.getServerType());
- builder.addAttribute("computed-autofill-hints", field.getComputedType());
- // Compose multiple predictions to a string separated by ','.
- String[] predictions = field.getServerPredictions();
- if (predictions != null && predictions.length > 0) {
- builder.addAttribute("crowdsourcing-predictions-autofill-hints",
- String.join(",", predictions));
- }
- }
- switch (field.getControlType()) {
- case FormFieldData.ControlType.LIST:
- child.setAutofillType(View.AUTOFILL_TYPE_LIST);
- child.setAutofillOptions(field.mOptionContents);
- int i = findIndex(field.mOptionValues, field.getValue());
- if (i != -1) {
- child.setAutofillValue(AutofillValue.forList(i));
- }
- break;
- case FormFieldData.ControlType.TOGGLE:
- child.setAutofillType(View.AUTOFILL_TYPE_TOGGLE);
- child.setAutofillValue(AutofillValue.forToggle(field.isChecked()));
- break;
- case FormFieldData.ControlType.TEXT:
- case FormFieldData.ControlType.DATALIST:
- child.setAutofillType(View.AUTOFILL_TYPE_TEXT);
- child.setAutofillValue(AutofillValue.forText(field.getValue()));
- if (field.mMaxLength != 0) {
- builder.addAttribute("maxlength", String.valueOf(field.mMaxLength));
- }
- if (field.getControlType() == FormFieldData.ControlType.DATALIST) {
- child.setAutofillOptions(field.mDatalistValues);
- }
- break;
- default:
- break;
- }
- child.setHtmlInfo(builder.build());
- }
- }
-
- public boolean autofill(final SparseArray<AutofillValue> values) {
- for (int i = 0; i < values.size(); ++i) {
- int id = values.keyAt(i);
- if (toSessionId(id) != sessionId) return false;
- AutofillValue value = values.get(id);
- if (value == null) continue;
- short index = toIndex(id);
- if (index < 0 || index >= mFormData.mFields.size()) return false;
- FormFieldData field = mFormData.mFields.get(index);
- if (field == null) return false;
- try {
- switch (field.getControlType()) {
- case FormFieldData.ControlType.LIST:
- int j = value.getListValue();
- if (j < 0 && j >= field.mOptionValues.length) continue;
- field.setAutofillValue(field.mOptionValues[j]);
- break;
- case FormFieldData.ControlType.TOGGLE:
- field.setChecked(value.getToggleValue());
- break;
- case FormFieldData.ControlType.TEXT:
- case FormFieldData.ControlType.DATALIST:
- field.setAutofillValue((String) value.getTextValue());
- break;
- default:
- break;
- }
- } catch (IllegalStateException e) {
- // Refer to crbug.com/1080580 .
- Log.e(TAG, "The given AutofillValue wasn't expected, abort autofill.", e);
- return false;
- }
- }
- return true;
- }
-
- public void setFocusField(FocusField focusField) {
- mFocusField = focusField;
- }
-
- public FocusField getFocusField() {
- return mFocusField;
- }
-
- public int getFieldCount() {
- return mFormData.mFields.size();
- }
-
- public AutofillValue getFieldNewValue(int index) {
- FormFieldData field = mFormData.mFields.get(index);
- if (field == null) return null;
- switch (field.getControlType()) {
- case FormFieldData.ControlType.LIST:
- int i = findIndex(field.mOptionValues, field.getValue());
- if (i == -1) return null;
- return AutofillValue.forList(i);
- case FormFieldData.ControlType.TOGGLE:
- return AutofillValue.forToggle(field.isChecked());
- case FormFieldData.ControlType.TEXT:
- case FormFieldData.ControlType.DATALIST:
- return AutofillValue.forText(field.getValue());
- default:
- return null;
- }
- }
-
- public int getVirtualId(short index) {
- return toVirtualId(sessionId, index);
- }
-
- public FormFieldData getField(short index) {
- return mFormData.mFields.get(index);
- }
-
- private static int findIndex(String[] values, String value) {
- if (values != null && value != null) {
- for (int i = 0; i < values.length; i++) {
- if (value.equals(values[i])) return i;
- }
- }
- return -1;
- }
-
- private static int getNextClientId() {
- ThreadUtils.assertOnUiThread();
- if (sSessionId == 0xffff) sSessionId = INIT_ID;
- return sSessionId++;
- }
-
- private static int toSessionId(int virtualId) {
- return (virtualId & 0xffff0000) >> 16;
- }
-
- private static short toIndex(int virtualId) {
- return (short) (virtualId & 0xffff);
- }
-
- private static int toVirtualId(int clientId, short index) {
- return (clientId << 16) | index;
- }
-
- public AutofillHintsService getAutofillHintsService() {
- return mAutofillHintsService;
- }
-
- public void onQueryDone(boolean success) {
- if (mAutofillHintsService == null) return;
- if (success) {
- ArrayList<ViewType> viewTypes = new ArrayList<ViewType>();
- for (FormFieldData field : mFormData.mFields) {
- viewTypes.add(new ViewType(field.getAutofillId(), field.getServerType(),
- field.getComputedType(), field.getServerPredictions()));
- }
- mAutofillHintsService.onViewTypeAvailable(viewTypes);
- } else {
- mAutofillHintsService.onQueryFailed();
- }
- }
- }
-
- private final String mProviderName;
- private AutofillManagerWrapper mAutofillManager;
- private ViewGroup mContainerView;
- private WebContents mWebContents;
-
- private AutofillRequest mRequest;
- private long mNativeAutofillProvider;
- private AutofillProviderUMA mAutofillUMA;
- private AutofillManagerWrapper.InputUIObserver mInputUIObserver;
- private long mAutofillTriggeredTimeMillis;
- private Context mContext;
- private AutofillPopup mDatalistPopup;
- private AutofillSuggestion[] mDatalistSuggestions;
- private WebContentsAccessibility mWebContentsAccessibility;
- private View mAnchorView;
-
- public AutofillProvider(Context context, ViewGroup containerView, String providerName) {
- this(containerView, new AutofillManagerWrapper(context), context, providerName);
- }
-
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- public AutofillProvider(ViewGroup containerView, AutofillManagerWrapper manager,
- Context context, String providerName) {
- mProviderName = providerName;
- try (ScopedSysTraceEvent e = ScopedSysTraceEvent.scoped("AutofillProvider.constructor")) {
- assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
- mAutofillManager = manager;
- mContainerView = containerView;
- mAutofillUMA = new AutofillProviderUMA(context, manager.isAwGCurrentAutofillService());
- mInputUIObserver = new AutofillManagerWrapper.InputUIObserver() {
- @Override
- public void onInputUIShown() {
- // Not need to report suggestion window displayed if there is no live autofill
- // session.
- if (mRequest == null) return;
- mAutofillUMA.onSuggestionDisplayed(
- System.currentTimeMillis() - mAutofillTriggeredTimeMillis);
- }
- };
- mAutofillManager.addInputUIObserver(mInputUIObserver);
- mContext = context;
- }
- }
-
- /**
- * Invoked when container view is changed.
- *
- * @param containerView new container view.
- */
- public void onContainerViewChanged(ViewGroup containerView) {
- mContainerView = containerView;
- }
-
- /**
- * Invoked when autofill service needs the form structure.
- *
- * @param structure see View.onProvideAutofillVirtualStructure()
- * @param flags see View.onProvideAutofillVirtualStructure()
- */
- public void onProvideAutoFillVirtualStructure(ViewStructure structure, int flags) {
- // This method could be called for the session started by the native
- // control outside of the scope of autofill, e.g. the URL bar, in this case, we simply
- // return.
- if (mRequest == null) return;
-
- Bundle bundle = structure.getExtras();
- if (bundle != null) {
- bundle.putCharSequence("VIRTUAL_STRUCTURE_PROVIDER_NAME", mProviderName);
- bundle.putCharSequence(
- "VIRTUAL_STRUCTURE_PROVIDER_VERSION", VersionConstants.PRODUCT_VERSION);
-
- if (isQueryServerFieldTypesEnabled()) {
- AutofillHintsService autofillHintsService = mRequest.getAutofillHintsService();
- if (autofillHintsService != null) {
- bundle.putBinder("AUTOFILL_HINTS_SERVICE", autofillHintsService.getBinder());
- }
- }
- }
- mRequest.fillViewStructure(structure);
- if (AutofillManagerWrapper.isLoggable()) {
- AutofillManagerWrapper.log(
- "onProvideAutoFillVirtualStructure fields:" + structure.getChildCount());
- }
- mAutofillUMA.onVirtualStructureProvided();
- }
-
- /**
- * Invoked when autofill value is available, AutofillProvider shall fill the
- * form with the provided values.
- *
- * @param values the array of autofill values, the key is virtual id of form
- * field.
- */
- public void autofill(final SparseArray<AutofillValue> values) {
- if (mNativeAutofillProvider != 0 && mRequest != null && mRequest.autofill((values))) {
- autofill(mNativeAutofillProvider, mRequest.mFormData);
- if (AutofillManagerWrapper.isLoggable()) {
- AutofillManagerWrapper.log("autofill values:" + values.size());
- }
- mAutofillUMA.onAutofill();
- }
- }
-
- /**
- * @return whether query autofill suggestion.
- */
- public boolean shouldQueryAutofillSuggestion() {
- return mRequest != null && mRequest.getFocusField() != null
- && !mAutofillManager.isAutofillInputUIShowing();
- }
-
- public void queryAutofillSuggestion() {
- if (shouldQueryAutofillSuggestion()) {
- FocusField focusField = mRequest.getFocusField();
- mAutofillManager.requestAutofill(mContainerView,
- mRequest.getVirtualId(focusField.fieldIndex), focusField.absBound);
- }
- }
-
- @VisibleForTesting(otherwise = VisibleForTesting.NONE)
- public void setAutofillManagerWrapperForTesting(AutofillManagerWrapper manager) {
- mAutofillManager = manager;
- mAutofillManager.addInputUIObserver(mInputUIObserver);
- }
-
- /**
- * Invoked when filling form is need. AutofillProvider shall ask autofill
- * service for the values with which to fill the form.
- *
- * @param formData the form needs to fill.
- * @param focus the index of focus field in formData
- * @param x the boundary of focus field.
- * @param y the boundary of focus field.
- * @param width the boundary of focus field.
- * @param height the boundary of focus field.
- * @param hasServerPrediction whether the server prediction arrived.
- */
- @CalledByNative
- public void startAutofillSession(FormData formData, int focus, float x, float y, float width,
- float height, boolean hasServerPrediction) {
- // Check focusField inside short value?
- // Autofill Manager might have session that wasn't started by AutofillProvider,
- // we just always cancel existing session here.
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
- mAutofillManager.cancel();
- }
-
- Rect absBound = transformToWindowBounds(new RectF(x, y, x + width, y + height));
- if (mRequest != null) notifyViewExitBeforeDestroyRequest();
- transformFormFieldToContainViewCoordinates(formData);
- mRequest = new AutofillRequest(
- formData, new FocusField((short) focus, absBound), hasServerPrediction);
- int virtualId = mRequest.getVirtualId((short) focus);
- notifyVirtualViewEntered(mContainerView, virtualId, absBound);
- mAutofillUMA.onSessionStarted(mAutofillManager.isDisabled());
- if (hasServerPrediction) {
- mAutofillUMA.onServerTypeAvailable(formData, /*afterSessionStarted=*/false);
- }
- mAutofillTriggeredTimeMillis = System.currentTimeMillis();
-
- mAutofillManager.notifyNewSessionStarted(hasServerPrediction);
- }
-
- /**
- * Invoked when form field's value is changed.
- *
- * @param index index of field in current form.
- * @param x the boundary of focus field.
- * @param y the boundary of focus field.
- * @param width the boundary of focus field.
- * @param height the boundary of focus field.
- *
- */
- @CalledByNative
- public void onFormFieldDidChange(int index, float x, float y, float width, float height) {
- // Check index inside short value?
- if (mRequest == null) return;
-
- short sIndex = (short) index;
- FocusField focusField = mRequest.getFocusField();
- if (focusField == null || sIndex != focusField.fieldIndex) {
- onFocusChangedImpl(true, index, x, y, width, height, true /*causedByValueChange*/);
- } else {
- // Currently there is no api to notify both value and position
- // change, before the API is available, we still need to call
- // notifyVirtualViewEntered() to tell current coordinates because
- // the position could be changed.
- int virtualId = mRequest.getVirtualId(sIndex);
- Rect absBound = transformToWindowBounds(new RectF(x, y, x + width, y + height));
- if (!focusField.absBound.equals(absBound)) {
- notifyVirtualViewExited(mContainerView, virtualId);
- notifyVirtualViewEntered(mContainerView, virtualId, absBound);
- // Update focus field position.
- mRequest.setFocusField(new FocusField(focusField.fieldIndex, absBound));
- }
- }
- notifyVirtualValueChanged(index, /* forceNotify = */ false);
- mAutofillUMA.onUserChangeFieldValue(mRequest.getField(sIndex).hasPreviouslyAutofilled());
- }
-
- /**
- * Invoked when text field is scrolled.
- *
- * @param index index of field in current form.
- * @param x the boundary of focus field.
- * @param y the boundary of focus field.
- * @param width the boundary of focus field.
- * @param height the boundary of focus field.
- *
- */
- @CalledByNative
- public void onTextFieldDidScroll(int index, float x, float y, float width, float height) {
- // crbug.com/730764 - from P and above, Android framework listens to the onScrollChanged()
- // and repositions the autofill UI automatically.
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) return;
- if (mRequest == null) return;
-
- short sIndex = (short) index;
- FocusField focusField = mRequest.getFocusField();
- if (focusField == null || sIndex != focusField.fieldIndex) return;
-
- int virtualId = mRequest.getVirtualId(sIndex);
- Rect absBound = transformToWindowBounds(new RectF(x, y, x + width, y + height));
- // Notify the new position to the Android framework. Note that we do not call
- // notifyVirtualViewExited() here intentionally to avoid flickering.
- notifyVirtualViewEntered(mContainerView, virtualId, absBound);
-
- // Update focus field position.
- mRequest.setFocusField(new FocusField(focusField.fieldIndex, absBound));
- }
-
- private boolean isDatalistField(int childId) {
- FormFieldData field = mRequest.getField((short) childId);
- return field.mControlType == FormFieldData.ControlType.DATALIST;
- }
-
- private void notifyVirtualValueChanged(int index, boolean forceNotify) {
- // The ValueChanged, ViewEntered and ViewExited aren't notified to the autofill service for
- // the focused datalist to avoid the potential UI conflict.
- // The datalist support was added later and the option list is displayed by WebView, the
- // autofill service might also show its suggestions when the datalist (associated the input
- // field) is focused, the two UI overlap, the solution is to completely hide the fact that
- // the datalist is being focused to the autofill service to prevent it from displaying the
- // suggestion.
- // The ValueChange will still be sent to autofill service when the form
- // submitted or autofilled.
- if (!forceNotify && isDatalistField(index)) return;
- AutofillValue autofillValue = mRequest.getFieldNewValue(index);
- if (autofillValue == null) return;
- mAutofillManager.notifyVirtualValueChanged(
- mContainerView, mRequest.getVirtualId((short) index), autofillValue);
- }
-
- private void notifyVirtualViewEntered(View parent, int childId, Rect absBounds) {
- // Refer to notifyVirtualValueChanged() for the reason of the datalist's special handling.
- if (isDatalistField(childId)) return;
- mAutofillManager.notifyVirtualViewEntered(parent, childId, absBounds);
- }
-
- private void notifyVirtualViewExited(View parent, int childId) {
- // Refer to notifyVirtualValueChanged() for the reason of the datalist's special handling.
- if (isDatalistField(childId)) return;
- mAutofillManager.notifyVirtualViewExited(parent, childId);
- }
-
- /**
- * Invoked when current form will be submitted.
- * @param submissionSource the submission source, could be any member defined in
- * SubmissionSource.java
- */
- @CalledByNative
- public void onFormSubmitted(int submissionSource) {
- // The changes could be missing, like those made by Javascript, we'd better to notify
- // AutofillManager current values. also see crbug.com/353001 and crbug.com/732856.
- forceNotifyFormValues();
- mAutofillManager.commit(submissionSource);
- mRequest = null;
- mAutofillUMA.onFormSubmitted(submissionSource);
- }
-
- /**
- * Invoked when focus field changed.
- *
- * @param focusOnForm whether focus is still on form.
- * @param focusItem the index of field has focus
- * @param x the boundary of focus field.
- * @param y the boundary of focus field.
- * @param width the boundary of focus field.
- * @param height the boundary of focus field.
- */
- @CalledByNative
- public void onFocusChanged(
- boolean focusOnForm, int focusField, float x, float y, float width, float height) {
- onFocusChangedImpl(
- focusOnForm, focusField, x, y, width, height, false /*causedByValueChange*/);
- }
-
- @CalledByNative
- public void hidePopup() {
- if (mDatalistPopup != null) {
- mDatalistPopup.dismiss();
- mDatalistPopup = null;
- mDatalistSuggestions = null;
- }
- if (mWebContentsAccessibility != null) {
- mWebContentsAccessibility.onAutofillPopupDismissed();
- }
- }
-
- private void notifyViewExitBeforeDestroyRequest() {
- if (mRequest == null) return;
- FocusField focusField = mRequest.getFocusField();
- if (focusField == null) return;
- notifyVirtualViewExited(mContainerView, mRequest.getVirtualId(focusField.fieldIndex));
- mRequest.setFocusField(null);
- }
-
- private void onFocusChangedImpl(boolean focusOnForm, int focusField, float x, float y,
- float width, float height, boolean causedByValueChange) {
- // Check focusField inside short value?
- // FocusNoLongerOnForm is called after form submitted.
- if (mRequest == null) return;
- FocusField prev = mRequest.getFocusField();
- if (focusOnForm) {
- Rect absBound = transformToWindowBounds(new RectF(x, y, x + width, y + height));
- if (prev != null && prev.fieldIndex == focusField && absBound.equals(prev.absBound)) {
- return;
- }
-
- // Notify focus changed.
- if (prev != null) {
- notifyVirtualViewExited(mContainerView, mRequest.getVirtualId(prev.fieldIndex));
- }
-
- notifyVirtualViewEntered(
- mContainerView, mRequest.getVirtualId((short) focusField), absBound);
-
- if (!causedByValueChange) {
- // The focus field value might not sync with platform's
- // AutofillManager, just notify it value changed.
- notifyVirtualValueChanged(focusField, /* forceNotify = */ false);
- mAutofillTriggeredTimeMillis = System.currentTimeMillis();
- }
- mRequest.setFocusField(new FocusField((short) focusField, absBound));
- } else {
- if (prev == null) return;
- // Notify focus changed.
- notifyVirtualViewExited(mContainerView, mRequest.getVirtualId(prev.fieldIndex));
- mRequest.setFocusField(null);
- }
- }
-
- @CalledByNative
- protected void showDatalistPopup(
- String[] datalistValues, String[] datalistLabels, boolean isRtl) {
- if (mRequest == null) return;
- FocusField focusField = mRequest.getFocusField();
- if (focusField != null) {
- showDatalistPopup(datalistValues, datalistLabels,
- mRequest.getField(focusField.fieldIndex).getBounds(), isRtl);
- }
- }
-
- /**
- * Display the simplest popup for the datalist. This is same as WebView's datalist popup in
- * Android pre-o. No suggestion from the autofill service will be presented, No advance
- * features of AutofillPopup are used.
- */
- private void showDatalistPopup(
- String[] datalistValues, String[] datalistLabels, RectF bounds, boolean isRtl) {
- mDatalistSuggestions = new AutofillSuggestion[datalistValues.length];
- for (int i = 0; i < mDatalistSuggestions.length; i++) {
- mDatalistSuggestions[i] = new AutofillSuggestion(datalistValues[i], datalistLabels[i],
- /* itemTag= */ "", DropdownItem.NO_ICON, false /* isIconAtLeft */, i,
- false /* isDeletable */, false /* isMultilineLabel */, false /* isBoldLabel */);
- }
- if (mWebContentsAccessibility == null) {
- mWebContentsAccessibility = WebContentsAccessibility.fromWebContents(mWebContents);
- }
- if (mDatalistPopup == null) {
- if (ContextUtils.activityFromContext(mContext) == null) return;
- ViewAndroidDelegate delegate = mWebContents.getViewAndroidDelegate();
- if (mAnchorView == null) mAnchorView = delegate.acquireView();
- setAnchorViewRect(bounds);
- try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
- mDatalistPopup = new AutofillPopup(mContext, mAnchorView, new AutofillDelegate() {
- @Override
- public void dismissed() {
- onDatalistPopupDismissed();
- }
-
- @Override
- public void suggestionSelected(int listIndex) {
- onSuggestionSelected(mDatalistSuggestions[listIndex].getLabel());
- }
-
- @Override
- public void deleteSuggestion(int listIndex) {}
-
- @Override
- public void accessibilityFocusCleared() {
- mWebContentsAccessibility.onAutofillPopupAccessibilityFocusCleared();
- }
- });
- } catch (RuntimeException e) {
- // Deliberately swallowing exception because bad framework implementation can
- // throw exceptions in ListPopupWindow constructor.
- onDatalistPopupDismissed();
- return;
- }
- }
- mDatalistPopup.filterAndShow(mDatalistSuggestions, isRtl, false);
- if (mWebContentsAccessibility != null) {
- mWebContentsAccessibility.onAutofillPopupDisplayed(mDatalistPopup.getListView());
- }
- }
-
- private void onDatalistPopupDismissed() {
- ViewAndroidDelegate delegate = mWebContents.getViewAndroidDelegate();
- delegate.removeView(mAnchorView);
- mAnchorView = null;
- }
-
- private void onSuggestionSelected(String value) {
- acceptDataListSuggestion(mNativeAutofillProvider, value);
- hidePopup();
- }
-
- private void setAnchorViewRect(RectF rect) {
- setAnchorViewRect(mNativeAutofillProvider, mAnchorView, rect);
- }
-
- /**
- * Invoked when current query need to be reset.
- */
- @CalledByNative
- protected void reset() {
- // We don't need to reset anything here, it should be safe to cancel
- // current autofill session when new one starts in
- // startAutofillSession().
- }
-
- @CalledByNative
- protected void setNativeAutofillProvider(long nativeAutofillProvider) {
- if (nativeAutofillProvider == mNativeAutofillProvider) return;
- // Setting the mNativeAutofillProvider to 0 may occur as a
- // result of WebView.destroy, or because a WebView has been
- // gc'ed. In the former case we can go ahead and clean up the
- // frameworks autofill manager, but in the latter case the
- // binder connection has already been dropped in a framework
- // finalizer, and so the methods we call will throw. It's not
- // possible to know which case we're in, so just catch the exception
- // in AutofillManagerWrapper.destroy().
- if (mNativeAutofillProvider != 0) mRequest = null;
- mNativeAutofillProvider = nativeAutofillProvider;
- if (nativeAutofillProvider == 0) mAutofillManager.destroy();
- }
-
- public void setWebContents(WebContents webContents) {
- if (webContents == mWebContents) return;
- if (mWebContents != null) mRequest = null;
- mWebContents = webContents;
- }
-
- @CalledByNative
- protected void onDidFillAutofillFormData() {
- // The changes were caused by the autofill service autofill form,
- // notified it about the result.
- forceNotifyFormValues();
- }
-
- @CalledByNative
- private void onQueryDone(boolean success) {
- mRequest.onQueryDone(success);
- mAutofillUMA.onServerTypeAvailable(
- success ? mRequest.mFormData : null, /*afterSessionStarted*/ true);
- mAutofillManager.onQueryDone(success);
- }
-
- public static boolean isQueryServerFieldTypesEnabled() {
- if (sIsQueryServerFieldTypesEnabled == null) {
- sIsQueryServerFieldTypesEnabled =
- AutofillProviderJni.get().isQueryServerFieldTypesEnabled();
- }
- return sIsQueryServerFieldTypesEnabled;
- }
-
- private void forceNotifyFormValues() {
- if (mRequest == null) return;
- for (int i = 0; i < mRequest.getFieldCount(); ++i) {
- notifyVirtualValueChanged(i, /* forceNotify = */ true);
- }
- }
-
- @VisibleForTesting
- public AutofillPopup getDatalistPopupForTesting() {
- return mDatalistPopup;
- }
-
- private Rect transformToWindowBounds(RectF rect) {
- // Refer to crbug.com/1085294 for the reason of offset.
- // The current version of Mockito didn't support mock static method, adding extra method so
- // the transform can be tested.
- return transformToWindowBoundsWithOffsetY(
- rect, RenderCoordinates.fromWebContents(mWebContents).getContentOffsetYPixInt());
- }
-
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- public Rect transformToWindowBoundsWithOffsetY(RectF rect, int offsetY) {
- // Convert bounds to device pixel.
- WindowAndroid windowAndroid = mWebContents.getTopLevelNativeWindow();
- DisplayAndroid displayAndroid = windowAndroid.getDisplay();
- float dipScale = displayAndroid.getDipScale();
- RectF bounds = new RectF(rect);
- Matrix matrix = new Matrix();
- matrix.setScale(dipScale, dipScale);
- int[] location = new int[2];
- mContainerView.getLocationOnScreen(location);
- location[1] += offsetY;
- matrix.postTranslate(location[0], location[1]);
- matrix.mapRect(bounds);
- return new Rect(
- (int) bounds.left, (int) bounds.top, (int) bounds.right, (int) bounds.bottom);
- }
-
- /**
- * Transform FormFieldData's bounds to ContainView's coordinates and update the bounds with the
- * transformed one.
- *
- * @param formData the form need to be transformed.
- */
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- public void transformFormFieldToContainViewCoordinates(FormData formData) {
- WindowAndroid windowAndroid = mWebContents.getTopLevelNativeWindow();
- DisplayAndroid displayAndroid = windowAndroid.getDisplay();
- float dipScale = displayAndroid.getDipScale();
- Matrix matrix = new Matrix();
- matrix.setScale(dipScale, dipScale);
- matrix.postTranslate(mContainerView.getScrollX(), mContainerView.getScrollY());
-
- for (FormFieldData field : formData.mFields) {
- RectF bounds = new RectF();
- matrix.mapRect(bounds, field.getBounds());
- field.setBoundsInContainerViewCoordinates(bounds);
- }
- }
-
- /**
- * Send form to renderer for filling.
- *
- * @param nativeAutofillProvider the native autofill provider.
- * @param formData the form to fill.
- */
- private void autofill(long nativeAutofillProvider, FormData formData) {
- AutofillProviderJni.get().onAutofillAvailable(
- nativeAutofillProvider, AutofillProvider.this, formData);
- }
-
- private void acceptDataListSuggestion(long nativeAutofillProvider, String value) {
- AutofillProviderJni.get().onAcceptDataListSuggestion(
- nativeAutofillProvider, AutofillProvider.this, value);
- }
-
- private void setAnchorViewRect(long nativeAutofillProvider, View anchorView, RectF rect) {
- AutofillProviderJni.get().setAnchorViewRect(nativeAutofillProvider, AutofillProvider.this,
- anchorView, rect.left, rect.top, rect.width(), rect.height());
- }
-
- @NativeMethods
- interface Natives {
- void onAutofillAvailable(
- long nativeAutofillProviderAndroid, AutofillProvider caller, FormData formData);
-
- void onAcceptDataListSuggestion(
- long nativeAutofillProviderAndroid, AutofillProvider caller, String value);
-
- void setAnchorViewRect(long nativeAutofillProviderAndroid, AutofillProvider caller,
- View anchorView, float x, float y, float width, float height);
-
- boolean isQueryServerFieldTypesEnabled();
- }
-}
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProviderUMA.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProviderUMA.java
deleted file mode 100644
index 3f4ea071c87..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProviderUMA.java
+++ /dev/null
@@ -1,363 +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.autofill;
-
-import android.content.Context;
-import android.os.Build;
-
-import org.chromium.autofill.mojom.SubmissionSource;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.metrics.RecordHistogram;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * The class for AutofillProvider-related UMA. Note that most of the concrete histogram
- * names include "WebView"; when this class was originally developed it was WebView-specific,
- * and when generalizing it we did not change these names to maintain continuity when
- * analyzing the histograms.
- */
-public class AutofillProviderUMA {
- // Records whether the Autofill service is enabled or not.
- public static final String UMA_AUTOFILL_ENABLED = "Autofill.WebView.Enabled";
-
- // Records whether the Autofill provider is created by activity context or not.
- public static final String UMA_AUTOFILL_CREATED_BY_ACTIVITY_CONTEXT =
- "Autofill.WebView.CreatedByActivityContext";
-
- // Records whether the current autofill service is AwG.
- public static final String UMA_AUTOFILL_AWG_IS_CURRENT_SERVICE =
- "Autofill.WebView.AwGIsCurrentService";
-
- // Records what happened in an autofill session.
- public static final String UMA_AUTOFILL_AUTOFILL_SESSION = "Autofill.WebView.AutofillSession";
- // The possible value of UMA_AUTOFILL_AUTOFILL_SESSION.
- public static final int SESSION_UNKNOWN = 0;
- public static final int NO_CALLBACK_FORM_FRAMEWORK = 1;
- public static final int NO_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED = 2;
- public static final int NO_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED = 3;
- public static final int NO_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED = 4;
- public static final int NO_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED = 5;
- public static final int USER_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED = 6;
- public static final int USER_SELECT_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED = 7;
- public static final int USER_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED = 8;
- public static final int USER_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED = 9;
- public static final int USER_NOT_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED = 10;
- public static final int USER_NOT_SELECT_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED = 11;
- public static final int USER_NOT_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED = 12;
- public static final int USER_NOT_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED = 13;
- public static final int AUTOFILL_SESSION_HISTOGRAM_COUNT = 14;
-
- // The possible values for the server prediction availability.
- public static final String UMA_AUTOFILL_SERVER_PREDICTION_AVAILABILITY =
- "Autofill.WebView.ServerPredicton.PredictionAvailability";
- public static final int SERVER_PREDICTION_NOT_AVAILABLE = 0;
- public static final int SERVER_PREDICTION_AVAILABLE_ON_SESSION_STARTS = 1;
- public static final int SERVER_PREDICTION_AVAILABLE_AFTER_SESSION_STARTS = 2;
- public static final int SERVER_PREDICTION_AVAILABLE_COUNT = 3;
-
- // The possible values for the AwG suggestion availability.
- public static final String UMA_AUTOFILL_AWG_SUGGSTION_AVAILABILITY =
- "Autofill.WebView.ServerPrediction.AwGSuggestionAvailability";
- public static final int AWG_NO_SUGGESTION = 0;
- public static final int AWG_HAS_SUGGESTION_NO_AUTOFILL = 1;
- public static final int AWG_HAS_SUGGESTION_AUTOFILLED = 2;
- public static final int AWG_SUGGSTION_AVAILABLE_COUNT = 3;
-
- public static final String UMA_AUTOFILL_VALID_SERVER_PREDICTION =
- "Autofill.WebView.ServerPredicton.HasValidServerPrediction";
-
- // Records whether user changed autofilled field if user ever changed the form. The action isn't
- // recorded if user didn't change form at all.
- public static final String UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD =
- "Autofill.WebView.UserChangedAutofilledField";
-
- public static final String UMA_AUTOFILL_SUBMISSION_SOURCE = "Autofill.WebView.SubmissionSource";
- // The possible value of UMA_AUTOFILL_SUBMISSION_SOURCE.
- public static final int SAME_DOCUMENT_NAVIGATION = 0;
- public static final int XHR_SUCCEEDED = 1;
- public static final int FRAME_DETACHED = 2;
- public static final int DOM_MUTATION_AFTER_XHR = 3;
- public static final int PROBABLY_FORM_SUBMITTED = 4;
- public static final int FORM_SUBMISSION = 5;
- public static final int SUBMISSION_SOURCE_HISTOGRAM_COUNT = 6;
-
- // The million seconds from user touched the field to the autofill session starting.
- public static final String UMA_AUTOFILL_TRIGGERING_TIME = "Autofill.WebView.TriggeringTime";
-
- // The million seconds from the autofill session starting to the suggestion being displayed.
- public static final String UMA_AUTOFILL_SUGGESTION_TIME = "Autofill.WebView.SuggestionTime";
-
- // The expected time range of time is from 10ms to 2 seconds, and 50 buckets is sufficient.
- private static final long MIN_TIME_MILLIS = 10;
- private static final long MAX_TIME_MILLIS = TimeUnit.SECONDS.toMillis(2);
- private static final int NUM_OF_BUCKETS = 50;
-
- private static void recordTimesHistogram(String name, long durationMillis) {
- RecordHistogram.recordCustomTimesHistogram(
- name, durationMillis, MIN_TIME_MILLIS, MAX_TIME_MILLIS, NUM_OF_BUCKETS);
- }
-
- private static class SessionRecorder {
- public static final int EVENT_VIRTUAL_STRUCTURE_PROVIDED = 0x1 << 0;
- public static final int EVENT_SUGGESTION_DISPLAYED = 0x1 << 1;
- public static final int EVENT_FORM_AUTOFILLED = 0x1 << 2;
- public static final int EVENT_USER_CHANGED_FIELD_VALUE = 0x1 << 3;
- public static final int EVENT_FORM_SUBMITTED = 0x1 << 4;
- public static final int EVENT_USER_CHANGED_AUTOFILLED_FIELD = 0x1 << 5;
-
- private Long mSuggestionTimeMillis;
-
- public void record(int event) {
- // Not record any event until we get EVENT_VIRTUAL_STRUCTURE_PROVIDED which makes the
- // following events meaningful.
- if (event != EVENT_VIRTUAL_STRUCTURE_PROVIDED && mState == 0) return;
- if (EVENT_USER_CHANGED_FIELD_VALUE == event && mUserChangedAutofilledField == null) {
- mUserChangedAutofilledField = Boolean.valueOf(false);
- } else if (EVENT_USER_CHANGED_AUTOFILLED_FIELD == event) {
- if (mUserChangedAutofilledField == null) {
- mUserChangedAutofilledField = Boolean.valueOf(true);
- }
- mUserChangedAutofilledField = true;
- event = EVENT_USER_CHANGED_FIELD_VALUE;
- }
- mState |= event;
- }
-
- public void setSuggestionTimeMillis(long suggestionTimeMillis) {
- // Only record first suggestion.
- if (mSuggestionTimeMillis == null) {
- mSuggestionTimeMillis = Long.valueOf(suggestionTimeMillis);
- }
- }
-
- public void recordHistogram() {
- RecordHistogram.recordEnumeratedHistogram(UMA_AUTOFILL_AUTOFILL_SESSION,
- toUMAAutofillSessionValue(), AUTOFILL_SESSION_HISTOGRAM_COUNT);
- // Only record if user ever changed form.
- if (mUserChangedAutofilledField != null) {
- RecordHistogram.recordBooleanHistogram(
- UMA_AUTOFILL_USER_CHANGED_AUTOFILLED_FIELD, mUserChangedAutofilledField);
- }
- if (mSuggestionTimeMillis != null) {
- recordTimesHistogram(UMA_AUTOFILL_SUGGESTION_TIME, mSuggestionTimeMillis);
- }
- if (!mServerPredictionAvailable && AutofillProvider.isQueryServerFieldTypesEnabled()) {
- RecordHistogram.recordEnumeratedHistogram(
- UMA_AUTOFILL_SERVER_PREDICTION_AVAILABILITY,
- SERVER_PREDICTION_NOT_AVAILABLE, SERVER_PREDICTION_AVAILABLE_COUNT);
- }
- }
-
- public void onServerTypeAvailable(FormData formData, boolean afterSessionStarted) {
- if (!AutofillProvider.isQueryServerFieldTypesEnabled()) return;
- mServerPredictionAvailable = true;
- RecordHistogram.recordEnumeratedHistogram(UMA_AUTOFILL_SERVER_PREDICTION_AVAILABILITY,
- afterSessionStarted ? SERVER_PREDICTION_AVAILABLE_AFTER_SESSION_STARTS
- : SERVER_PREDICTION_AVAILABLE_ON_SESSION_STARTS,
- SERVER_PREDICTION_AVAILABLE_COUNT);
- if (formData != null) {
- boolean hasValidServerData = false;
- for (FormFieldData fieldData : formData.mFields) {
- if (!fieldData.getServerType().equals("NO_SERVER_DATA")) {
- hasValidServerData = true;
- break;
- }
- }
- RecordHistogram.recordBooleanHistogram(
- UMA_AUTOFILL_VALID_SERVER_PREDICTION, hasValidServerData);
- }
- }
-
- private int toUMAAutofillSessionValue() {
- if (mState == 0) {
- return NO_CALLBACK_FORM_FRAMEWORK;
- } else if (mState == EVENT_VIRTUAL_STRUCTURE_PROVIDED) {
- return NO_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED;
- } else if (mState
- == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_USER_CHANGED_FIELD_VALUE)) {
- return NO_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED;
- } else if (mState == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_FORM_SUBMITTED)) {
- return NO_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED;
- } else if (mState
- == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_USER_CHANGED_FIELD_VALUE
- | EVENT_FORM_SUBMITTED)) {
- return NO_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED;
- } else if (mState
- == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_SUGGESTION_DISPLAYED
- | EVENT_FORM_AUTOFILLED)) {
- return USER_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED;
- } else if (mState
- == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_SUGGESTION_DISPLAYED
- | EVENT_FORM_AUTOFILLED | EVENT_FORM_SUBMITTED)) {
- return USER_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED;
- } else if (mState
- == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_SUGGESTION_DISPLAYED
- | EVENT_FORM_AUTOFILLED | EVENT_USER_CHANGED_FIELD_VALUE
- | EVENT_FORM_SUBMITTED)) {
- return USER_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED;
- } else if (mState
- == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_SUGGESTION_DISPLAYED
- | EVENT_FORM_AUTOFILLED | EVENT_USER_CHANGED_FIELD_VALUE)) {
- return USER_SELECT_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED;
- } else if (mState == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_SUGGESTION_DISPLAYED)) {
- return USER_NOT_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_NO_FORM_SUBMITTED;
- } else if (mState
- == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_SUGGESTION_DISPLAYED
- | EVENT_FORM_SUBMITTED)) {
- return USER_NOT_SELECT_SUGGESTION_USER_NOT_CHANGE_FORM_FORM_SUBMITTED;
- } else if (mState
- == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_SUGGESTION_DISPLAYED
- | EVENT_USER_CHANGED_FIELD_VALUE | EVENT_FORM_SUBMITTED)) {
- return USER_NOT_SELECT_SUGGESTION_USER_CHANGE_FORM_FORM_SUBMITTED;
- } else if (mState
- == (EVENT_VIRTUAL_STRUCTURE_PROVIDED | EVENT_SUGGESTION_DISPLAYED
- | EVENT_USER_CHANGED_FIELD_VALUE)) {
- return USER_NOT_SELECT_SUGGESTION_USER_CHANGE_FORM_NO_FORM_SUBMITTED;
- } else {
- return SESSION_UNKNOWN;
- }
- }
-
- private int mState;
- private Boolean mUserChangedAutofilledField;
-
- // Indicates whether the server prediction arrives.
- private boolean mServerPredictionAvailable;
- }
-
- /**
- * The class to record Autofill.WebView.ServerPrediction.AwGSuggestion, is only instantiated
- * when the Android platform AutofillServcie is AwG, This will give us more actual result in
- * A/B experiment while only AwG supports the server prediction.
- */
- private static class ServerPredictionRecorder {
- private boolean mHasSuggestions;
- private boolean mAutofilled;
- private boolean mRecorded;
-
- public void onSuggestionDisplayed() {
- mHasSuggestions = true;
- }
-
- public void onAutofill() {
- mAutofilled = true;
- }
-
- public void recordHistograms() {
- if (mRecorded) return;
- mRecorded = true;
- int sample = AWG_NO_SUGGESTION;
- if (mHasSuggestions) {
- sample = mAutofilled ? AWG_HAS_SUGGESTION_AUTOFILLED
- : AWG_HAS_SUGGESTION_NO_AUTOFILL;
- }
- RecordHistogram.recordEnumeratedHistogram(
- UMA_AUTOFILL_AWG_SUGGSTION_AVAILABILITY, sample, AWG_SUGGSTION_AVAILABLE_COUNT);
- }
- }
-
- private SessionRecorder mRecorder;
- private Boolean mAutofillDisabled;
-
- private final boolean mIsAwGCurrentAutofillService;
- private ServerPredictionRecorder mServerPredictionRecorder;
-
- public AutofillProviderUMA(Context context, boolean isAwGCurrentAutofillService) {
- RecordHistogram.recordBooleanHistogram(UMA_AUTOFILL_CREATED_BY_ACTIVITY_CONTEXT,
- ContextUtils.activityFromContext(context) != null);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
- RecordHistogram.recordBooleanHistogram(
- UMA_AUTOFILL_AWG_IS_CURRENT_SERVICE, isAwGCurrentAutofillService);
- }
- mIsAwGCurrentAutofillService = isAwGCurrentAutofillService;
- }
-
- public void onFormSubmitted(int submissionSource) {
- if (mRecorder != null) mRecorder.record(SessionRecorder.EVENT_FORM_SUBMITTED);
- recordSession();
- if (mServerPredictionRecorder != null) mServerPredictionRecorder.recordHistograms();
- // We record this no matter autofill service is disabled or not.
- RecordHistogram.recordEnumeratedHistogram(UMA_AUTOFILL_SUBMISSION_SOURCE,
- toUMASubmissionSource(submissionSource), SUBMISSION_SOURCE_HISTOGRAM_COUNT);
- }
-
- public void onSessionStarted(boolean autofillDisabled) {
- // Record autofill status once per instance and only if user triggers the autofill.
- if (mAutofillDisabled == null || mAutofillDisabled.booleanValue() != autofillDisabled) {
- RecordHistogram.recordBooleanHistogram(UMA_AUTOFILL_ENABLED, !autofillDisabled);
- mAutofillDisabled = Boolean.valueOf(autofillDisabled);
- }
-
- if (mRecorder != null) recordSession();
- mRecorder = new SessionRecorder();
- if (mIsAwGCurrentAutofillService) {
- mServerPredictionRecorder = new ServerPredictionRecorder();
- }
- }
-
- public void onVirtualStructureProvided() {
- if (mRecorder != null) mRecorder.record(SessionRecorder.EVENT_VIRTUAL_STRUCTURE_PROVIDED);
- }
-
- public void onSuggestionDisplayed(long suggestionTimeMillis) {
- if (mRecorder != null) {
- mRecorder.record(SessionRecorder.EVENT_SUGGESTION_DISPLAYED);
- mRecorder.setSuggestionTimeMillis(suggestionTimeMillis);
- }
- if (mServerPredictionRecorder != null) mServerPredictionRecorder.onSuggestionDisplayed();
- }
-
- public void onAutofill() {
- if (mRecorder != null) mRecorder.record(SessionRecorder.EVENT_FORM_AUTOFILLED);
- if (mServerPredictionRecorder != null) mServerPredictionRecorder.onAutofill();
- }
-
- public void onUserChangeFieldValue(boolean isPreviouslyAutofilled) {
- if (mRecorder == null) return;
- if (isPreviouslyAutofilled) {
- mRecorder.record(SessionRecorder.EVENT_USER_CHANGED_AUTOFILLED_FIELD);
- } else {
- mRecorder.record(SessionRecorder.EVENT_USER_CHANGED_FIELD_VALUE);
- }
- }
-
- /**
- * Invoked when the server query was done or has arrived when the autofill sension starts.
- *
- * @param formData the form of the current session, is null if the query failed.
- * @param afterSessionStarted true if the server type predication arrive after the session
- * starts.
- */
- public void onServerTypeAvailable(FormData formData, boolean afterSessionStarted) {
- mRecorder.onServerTypeAvailable(formData, afterSessionStarted);
- }
-
- private void recordSession() {
- if (mAutofillDisabled != null && !mAutofillDisabled.booleanValue() && mRecorder != null) {
- mRecorder.recordHistogram();
- }
- mRecorder = null;
- }
-
- private int toUMASubmissionSource(int source) {
- switch (source) {
- case SubmissionSource.SAME_DOCUMENT_NAVIGATION:
- return SAME_DOCUMENT_NAVIGATION;
- case SubmissionSource.XHR_SUCCEEDED:
- return XHR_SUCCEEDED;
- case SubmissionSource.FRAME_DETACHED:
- return FRAME_DETACHED;
- case SubmissionSource.DOM_MUTATION_AFTER_XHR:
- return DOM_MUTATION_AFTER_XHR;
- case SubmissionSource.PROBABLY_FORM_SUBMITTED:
- return PROBABLY_FORM_SUBMITTED;
- case SubmissionSource.FORM_SUBMISSION:
- return FORM_SUBMISSION;
- default:
- return SUBMISSION_SOURCE_HISTOGRAM_COUNT;
- }
- }
-}
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormData.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormData.java
deleted file mode 100644
index 8069aa887b6..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormData.java
+++ /dev/null
@@ -1,56 +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.autofill;
-
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.NativeMethods;
-
-import java.util.ArrayList;
-
-/**
- * The wrap class of native autofill::FormDataAndroid.
- */
-@JNINamespace("autofill")
-public class FormData {
- public final String mName;
- public final String mHost;
- public final ArrayList<FormFieldData> mFields;
-
- @CalledByNative
- private static FormData createFormData(
- long nativeObj, String name, String origin, int fieldCount) {
- return new FormData(nativeObj, name, origin, fieldCount);
- }
-
- private static ArrayList<FormFieldData> popupFormFields(long nativeObj, int fieldCount) {
- FormFieldData formFieldData = FormDataJni.get().getNextFormFieldData(nativeObj);
- ArrayList<FormFieldData> fields = new ArrayList<FormFieldData>(fieldCount);
- while (formFieldData != null) {
- fields.add(formFieldData);
- formFieldData = FormDataJni.get().getNextFormFieldData(nativeObj);
- }
- assert fields.size() == fieldCount;
- return fields;
- }
-
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- public FormData(String name, String host, ArrayList<FormFieldData> fields) {
- mName = name;
- mHost = host;
- mFields = fields;
- }
-
- private FormData(long nativeObj, String name, String host, int fieldCount) {
- this(name, host, popupFormFields(nativeObj, fieldCount));
- }
-
- @NativeMethods
- interface Natives {
- FormFieldData getNextFormFieldData(long nativeFormDataAndroid);
- }
-}
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormFieldData.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormFieldData.java
deleted file mode 100644
index 77f65ef7324..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormFieldData.java
+++ /dev/null
@@ -1,206 +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.autofill;
-
-import android.graphics.RectF;
-import android.view.autofill.AutofillId;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * The wrap class of native autofill::FormFieldDataAndroid.
- */
-@JNINamespace("autofill")
-public class FormFieldData {
- /**
- * Define the control types supported by android.view.autofill.AutofillValue.
- *
- * Android doesn't have DATALIST control, it is sent to the Autofill service as
- * View.AUTOFILL_TYPE_TEXT with AutofillOptions.
- */
- @IntDef({ControlType.TEXT, ControlType.TOGGLE, ControlType.LIST, ControlType.DATALIST})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ControlType {
- int TEXT = 0;
- int TOGGLE = 1;
- int LIST = 2;
- int DATALIST = 3;
- }
-
- public final String mLabel;
- public final String mName;
- public final String mAutocompleteAttr;
- public final boolean mShouldAutocomplete;
- public final String mPlaceholder;
- public final String mType;
- public final String mId;
- public final String[] mOptionValues;
- public final String[] mOptionContents;
- public final @ControlType int mControlType;
- public final int mMaxLength;
- public final String mHeuristicType;
- public final String[] mDatalistValues;
- public final String[] mDatalistLabels;
- public final boolean mVisible;
-
- // The bounds in the viewport's coordinates
- private final RectF mBounds;
- // The bounds in the container view's coordinates.
- private RectF mBoundsInContainerViewCoordinates;
-
- private boolean mIsChecked;
- private String mValue;
- // Indicates whether mValue is autofilled.
- private boolean mAutofilled;
- // Indicates whether this fields was autofilled, but changed by user.
- private boolean mPreviouslyAutofilled;
-
- // Provides the field type along with mHeuristicType, but could be changed
- // after the object instantiated.
- private String mServerType;
- private String mComputedType;
- private String[] mServerPredictions;
- private AutofillId mAutofillId;
-
- private FormFieldData(String name, String label, String value, String autocompleteAttr,
- boolean shouldAutocomplete, String placeholder, String type, String id,
- String[] optionValues, String[] optionContents, boolean isCheckField, boolean isChecked,
- int maxLength, String heuristicType, String serverType, String computedType,
- String[] serverPredictions, float left, float top, float right, float bottom,
- String[] datalistValues, String[] datalistLabels, boolean visible) {
- mName = name;
- mLabel = label;
- mValue = value;
- mAutocompleteAttr = autocompleteAttr;
- mShouldAutocomplete = shouldAutocomplete;
- mPlaceholder = placeholder;
- mType = type;
- mId = id;
- mOptionValues = optionValues;
- mOptionContents = optionContents;
- mIsChecked = isChecked;
- mDatalistLabels = datalistLabels;
- mDatalistValues = datalistValues;
- if (mOptionValues != null && mOptionValues.length != 0) {
- mControlType = ControlType.LIST;
- } else if (mDatalistValues != null && mDatalistValues.length != 0) {
- mControlType = ControlType.DATALIST;
- } else if (isCheckField) {
- mControlType = ControlType.TOGGLE;
- } else {
- mControlType = ControlType.TEXT;
- }
- mMaxLength = maxLength;
- mHeuristicType = heuristicType;
- mServerType = serverType;
- mServerPredictions = serverPredictions;
- mComputedType = computedType;
- mBounds = new RectF(left, top, right, bottom);
- mVisible = visible;
- }
-
- public @ControlType int getControlType() {
- return mControlType;
- }
-
- public RectF getBounds() {
- return mBounds;
- }
-
- public void setBoundsInContainerViewCoordinates(RectF bounds) {
- mBoundsInContainerViewCoordinates = bounds;
- }
-
- public RectF getBoundsInContainerViewCoordinates() {
- return mBoundsInContainerViewCoordinates;
- }
-
- /**
- * @return value of field.
- */
- @CalledByNative
- public String getValue() {
- return mValue;
- }
-
- public void setAutofillValue(String value) {
- mValue = value;
- updateAutofillState(true);
- }
-
- public void setChecked(boolean checked) {
- mIsChecked = checked;
- updateAutofillState(true);
- }
-
- @CalledByNative
- private void updateValue(String value) {
- mValue = value;
- updateAutofillState(false);
- }
-
- @CalledByNative
- private void updateFieldTypes(
- String serverType, String computedType, String[] serverPredictions) {
- mServerType = serverType;
- mComputedType = computedType;
- mServerPredictions = serverPredictions;
- }
-
- public String getServerType() {
- return mServerType;
- }
-
- public String getComputedType() {
- return mComputedType;
- }
-
- public String[] getServerPredictions() {
- return mServerPredictions;
- }
-
- @CalledByNative
- public boolean isChecked() {
- return mIsChecked;
- }
-
- public boolean hasPreviouslyAutofilled() {
- return mPreviouslyAutofilled;
- }
-
- private void updateAutofillState(boolean autofilled) {
- if (mAutofilled && !autofilled) mPreviouslyAutofilled = true;
- mAutofilled = autofilled;
- }
-
- public void setAutofillId(AutofillId id) {
- mAutofillId = id;
- }
-
- public AutofillId getAutofillId() {
- return mAutofillId;
- }
-
- @CalledByNative
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- public static FormFieldData createFormFieldData(String name, String label, String value,
- String autocompleteAttr, boolean shouldAutocomplete, String placeholder, String type,
- String id, String[] optionValues, String[] optionContents, boolean isCheckField,
- boolean isChecked, int maxLength, String heuristicType, String serverType,
- String computedType, String[] serverPredictions, float left, float top, float right,
- float bottom, String[] datalistValues, String[] datalistLabels, boolean visible) {
- return new FormFieldData(name, label, value, autocompleteAttr, shouldAutocomplete,
- placeholder, type, id, optionValues, optionContents, isCheckField, isChecked,
- maxLength, heuristicType, serverType, computedType, serverPredictions, left, top,
- right, bottom, datalistValues, datalistLabels, visible);
- }
-}
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/IAutofillHintsService.aidl b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/IAutofillHintsService.aidl
deleted file mode 100644
index dd5dd191b39..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/IAutofillHintsService.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.autofill_public;
-
-import android.os.Bundle;
-
-import org.chromium.components.autofill_public.IViewTypeCallback;
-
-/**
- * Interface to provide the autofill hints that are unable to be supported
- * by Android framework.
- *
- * The autofill service could get the binder from ViewStructure.
- * Bundle bundle = viewStructure.getExtras();
- * IBinder binder = bundle.getBinder("AUTOFILL_HINTS_SERVICE");
- */
-interface IAutofillHintsService {
- // Register the IViewTypeCallback to get the server prediction type.
- void registerViewTypeCallback(IViewTypeCallback callback);
-}
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/IViewTypeCallback.aidl b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/IViewTypeCallback.aidl
deleted file mode 100644
index 70fa902c55d..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/IViewTypeCallback.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.autofill_public;
-
-import android.os.Bundle;
-
-import org.chromium.components.autofill_public.ViewType;
-
-/**
- * The interface for AutofillHintsService to provide the type of view.
- */
-interface IViewTypeCallback {
- // Invoked when the query succeeds, though the server might not have the
- // prediction of the views.
- void onViewTypeAvailable(in List<ViewType> viewTypes);
-
- // Invoked when the query fails, mostly because of the connection or server
- // error.
- void onQueryFailed();
-}
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/OWNERS b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/OWNERS
deleted file mode 100644
index 8f094e0099e..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-per-file *.aidl=set noparent
-per-file *.aidl=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/README.md b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/README.md
deleted file mode 100644
index 7e77e096932..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/README.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# How to integrate the AutofillHintsService
-
-1. Add all files of this directory to your project.
-2. Get the binder in your autofill service as below
-
- ```java
- public void processNode(AssistStructure.ViewNode node) {
- Bundle bundle = node.getExtras();
- if (bundle != null) {
- IBinder binder = bundle.getBinder("AUTOFILL_HINTS_SERVICE");
- if (binder != null) {
- callViewTypeService(binder);
- } else {
- Log.e("MyAutofillService", "binder is null.");
- }
- } else {
- Log.e("MyAutofillService", "bundle is null.");
- }
- }
- ```
-
-3. Register the ViewTypeCallback
-
- ```java
- private void callViewTypeService(IBinder binder) {
- IViewTypeService viewTypeService = IViewTypeService.Stub.asInterface(binder);
- if (viewTypeService != null) {
- try {
- if (mViewTypeCallback == null) mViewTypeCallback = new ViewTypeCallback();
- viewTypeService.registerViewTypeCallback(mViewTypeCallback.getBinder());
- Log.d("MyAutofillService", " registerViewTypeCallback ");
- } catch (Exception e) {
- Log.e("MyAutofillService", " registerViewTypeCallback exception", e);
- }
- } else {
- Log.e("MyAutofillService", "viewTypeService is null.");
- }
- }
- ```
-
-4. A list of ViewType will be returned from ViewTypeCallback when they are available.
-
- ```java
- public void onViewTypeAvailable(List<ViewType> viewTypeList) {
- for(ViewType viewType : viewTypeList) {
- if (viewType.getServerPredictions() ! = null) {
- // Uses server predictions if they are available.
- } else {
- // otherwise, uses viewType.mServerType.
- }
- }
- }
- ```
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/ViewType.aidl b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/ViewType.aidl
deleted file mode 100644
index 6a7398d38a4..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/ViewType.aidl
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.autofill_public;
-
-parcelable ViewType;
diff --git a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/ViewType.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/ViewType.java
deleted file mode 100644
index fe0d9e18e28..00000000000
--- a/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill_public/ViewType.java
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.components.autofill_public;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.autofill.AutofillId;
-
-import org.chromium.base.annotations.VerifiesOnO;
-
-/**
- * This class is used to send the server and computed view type to the autofill service.
- * The valid types are listed in the two FieldTypeToStringPiece() functions in
- * components/autofill/core/browser/field_types.cc. Note that the list of possibly returned strings
- * can and will change in the future.
- */
-@TargetApi(Build.VERSION_CODES.O)
-@VerifiesOnO
-public class ViewType implements Parcelable {
- /**
- * The AutofillId of the view that types are for.
- */
- public final AutofillId mAutofillId;
-
- /**
- * The type from Chrome autofill server.
- */
- public final String mServerType;
-
- /**
- * The type computed overall type. The valid types are the same as for mServerType.
- */
- public final String mComputedType;
-
- private String[] mServerPredictions;
-
- public static final Parcelable.Creator<ViewType> CREATOR = new Parcelable.Creator<ViewType>() {
- @Override
- public ViewType createFromParcel(Parcel in) {
- return new ViewType(in);
- }
-
- @Override
- public ViewType[] newArray(int size) {
- return new ViewType[size];
- }
- };
-
- public ViewType(
- AutofillId id, String serverType, String computedType, String[] serverPredictions) {
- mAutofillId = id;
- mServerType = serverType;
- mComputedType = computedType;
- mServerPredictions = serverPredictions;
- }
-
- private ViewType(Parcel in) {
- mAutofillId = AutofillId.CREATOR.createFromParcel(in);
- mServerType = in.readString();
- mComputedType = in.readString();
- in.readStringArray(mServerPredictions);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- mAutofillId.writeToParcel(parcel, flags);
- parcel.writeString(mServerType);
- parcel.writeString(mComputedType);
- parcel.writeStringArray(mServerPredictions);
- }
-
- /**
- * @return the server predictions, they are in the order of the confidence. The mServerType
- * shall be used if the server predictions aren't available.
- */
- public String[] getServerPredictions() {
- return mServerPredictions;
- }
-}
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.cc b/chromium/components/autofill/content/browser/content_autofill_driver.cc
index e470c7ee0f7..e2fca077a58 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.cc
@@ -4,6 +4,7 @@
#include "components/autofill/content/browser/content_autofill_driver.h"
+#include <memory>
#include <tuple>
#include <utility>
#include <vector>
@@ -13,8 +14,7 @@
#include "build/build_config.h"
#include "components/autofill/content/browser/content_autofill_driver_factory.h"
#include "components/autofill/core/browser/autofill_client.h"
-#include "components/autofill/core/browser/autofill_handler_proxy.h"
-#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/payments/payments_service_url.h"
#include "components/autofill/core/common/autofill_features.h"
@@ -36,9 +36,12 @@
#include "content/public/common/origin_util.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "ui/accessibility/ax_tree_id.h"
#include "ui/gfx/geometry/size_f.h"
#include "url/origin.h"
+namespace autofill {
+
namespace {
bool ShouldEnableHeavyFormDataScraping(const version_info::Channel channel) {
@@ -55,26 +58,39 @@ bool ShouldEnableHeavyFormDataScraping(const version_info::Channel channel) {
return false;
}
-} // namespace
+GURL StripAuthAndParams(const GURL& gurl) {
+ GURL::Replacements rep;
+ rep.ClearUsername();
+ rep.ClearPassword();
+ rep.ClearQuery();
+ rep.ClearRef();
+ return gurl.ReplaceComponents(rep);
+}
-namespace autofill {
+} // namespace
ContentAutofillDriver::ContentAutofillDriver(
content::RenderFrameHost* render_frame_host,
AutofillClient* client,
const std::string& app_locale,
- AutofillHandler::AutofillDownloadManagerState enable_download_manager,
- AutofillProvider* provider)
+ AutofillManager::AutofillDownloadManagerState enable_download_manager,
+ AutofillManager::AutofillManagerFactoryCallback
+ autofill_manager_factory_callback)
: render_frame_host_(render_frame_host),
- autofill_manager_(nullptr),
+ browser_autofill_manager_(nullptr),
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) {
- SetAutofillProvider(provider, client, enable_download_manager);
+ if (autofill_manager_factory_callback) {
+ autofill_manager_ = autofill_manager_factory_callback.Run(
+ this, client, app_locale, enable_download_manager);
+ GetAutofillAgent()->SetUserGestureRequired(false);
+ GetAutofillAgent()->SetSecureContextRequired(true);
+ GetAutofillAgent()->SetFocusRequiresScroll(false);
+ GetAutofillAgent()->SetQueryPasswordSuggestion(true);
} else {
- SetAutofillManager(std::make_unique<AutofillManager>(
+ SetBrowserAutofillManager(std::make_unique<BrowserAutofillManager>(
this, client, app_locale, enable_download_manager));
}
if (client && ShouldEnableHeavyFormDataScraping(client->GetChannel())) {
@@ -104,15 +120,14 @@ bool ContentAutofillDriver::IsIncognito() const {
// TODO(https://crbug.com/1125474): Consider renaming this function to
// |IsOffTheRecord| after deprecation of off-the-record or ephemeral Guest
// profiles.
- if (autofill_manager_ &&
- autofill_manager_->client()->GetProfileType() ==
- profile_metrics::BrowserProfileType::kEphemeralGuest) {
+ auto* browser_context =
+ render_frame_host_->GetSiteInstance()->GetBrowserContext();
+ if (profile_metrics::GetBrowserProfileType(browser_context) ==
+ profile_metrics::BrowserProfileType::kEphemeralGuest) {
return true;
}
- return render_frame_host_->GetSiteInstance()
- ->GetBrowserContext()
- ->IsOffTheRecord();
+ return browser_context->IsOffTheRecord();
}
bool ContentAutofillDriver::IsInMainFrame() const {
@@ -132,8 +147,9 @@ ui::AXTreeID ContentAutofillDriver::GetAxTreeId() const {
scoped_refptr<network::SharedURLLoaderFactory>
ContentAutofillDriver::GetURLLoaderFactory() {
- return content::BrowserContext::GetDefaultStoragePartition(
- render_frame_host_->GetSiteInstance()->GetBrowserContext())
+ return render_frame_host_->GetSiteInstance()
+ ->GetBrowserContext()
+ ->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess();
}
@@ -143,11 +159,11 @@ bool ContentAutofillDriver::RendererIsAvailable() {
InternalAuthenticator*
ContentAutofillDriver::GetOrCreateCreditCardInternalAuthenticator() {
- if (!authenticator_impl_ && autofill_manager_ &&
- autofill_manager_->client()) {
+ if (!authenticator_impl_ && browser_autofill_manager_ &&
+ browser_autofill_manager_->client()) {
authenticator_impl_ =
- autofill_manager_->client()->CreateCreditCardInternalAuthenticator(
- render_frame_host_);
+ browser_autofill_manager_->client()
+ ->CreateCreditCardInternalAuthenticator(render_frame_host_);
}
return authenticator_impl_.get();
}
@@ -171,10 +187,11 @@ void ContentAutofillDriver::SendFormDataToRenderer(
void ContentAutofillDriver::PropagateAutofillPredictions(
const std::vector<FormStructure*>& forms) {
- AutofillHandler* handler =
- autofill_manager_ ? autofill_manager_ : autofill_handler_.get();
- DCHECK(handler);
- handler->PropagateAutofillPredictions(render_frame_host_, forms);
+ AutofillManager* manager = browser_autofill_manager_
+ ? browser_autofill_manager_
+ : autofill_manager_.get();
+ DCHECK(manager);
+ manager->PropagateAutofillPredictions(render_frame_host_, forms);
}
void ContentAutofillDriver::HandleParsedForms(
@@ -186,12 +203,21 @@ void ContentAutofillDriver::SendAutofillTypePredictionsToRenderer(
const std::vector<FormStructure*>& forms) {
if (!RendererIsAvailable())
return;
-
+ // TODO(crbug.com/1185232) Send the FormDataPredictions object only if the
+ // debugging flag is enabled.
std::vector<FormDataPredictions> type_predictions =
FormStructure::GetFieldTypePredictions(forms);
GetAutofillAgent()->FieldTypePredictionsAvailable(type_predictions);
}
+void ContentAutofillDriver::SendFieldsEligibleForManualFillingToRenderer(
+ const std::vector<FieldRendererId>& fields) {
+ if (!RendererIsAvailable())
+ return;
+
+ GetAutofillAgent()->SetFieldsEligibleForManualFilling(fields);
+}
+
void ContentAutofillDriver::RendererShouldAcceptDataListSuggestion(
const FieldGlobalId& field,
const std::u16string& value) {
@@ -239,7 +265,8 @@ void ContentAutofillDriver::RendererShouldSetSuggestionAvailability(
void ContentAutofillDriver::PopupHidden() {
// If the unmask prompt is showing, keep showing the preview. The preview
// will be cleared when the prompt closes.
- if (autofill_manager_ && autofill_manager_->ShouldClearPreviewedForm())
+ if (browser_autofill_manager_ &&
+ browser_autofill_manager_->ShouldClearPreviewedForm())
RendererShouldClearPreviewedForm();
}
@@ -260,13 +287,19 @@ net::IsolationInfo ContentAutofillDriver::IsolationInfo() {
return render_frame_host_->GetPendingIsolationInfoForSubresources();
}
-void ContentAutofillDriver::FormsSeen(const std::vector<FormData>& forms) {
- autofill_handler_->OnFormsSeen(forms);
+void ContentAutofillDriver::SetFormToBeProbablySubmitted(
+ const absl::optional<FormData>& raw_form) {
+ potentially_submitted_form_ =
+ raw_form ? absl::make_optional<FormData>(
+ GetFormWithFrameAndFormMetaData(*raw_form))
+ : absl::nullopt;
}
-void ContentAutofillDriver::SetFormToBeProbablySubmitted(
- const base::Optional<FormData>& form) {
- potentially_submitted_form_ = form;
+void ContentAutofillDriver::FormsSeen(const std::vector<FormData>& raw_forms) {
+ std::vector<FormData> forms = raw_forms;
+ for (auto& form : forms)
+ SetFrameAndFormMetaData(form);
+ autofill_manager_->OnFormsSeen(forms);
}
void ContentAutofillDriver::ProbablyFormSubmitted() {
@@ -276,7 +309,7 @@ void ContentAutofillDriver::ProbablyFormSubmitted() {
}
}
-void ContentAutofillDriver::FormSubmitted(const FormData& form,
+void ContentAutofillDriver::FormSubmitted(const FormData& raw_form,
bool known_success,
mojom::SubmissionSource source) {
// Omit duplicate form submissions. It may be reasonable to take |source|
@@ -286,72 +319,86 @@ void ContentAutofillDriver::FormSubmitted(const FormData& form,
features::kAutofillProbableFormSubmissionInBrowser) &&
!base::FeatureList::IsEnabled(
features::kAutofillAllowDuplicateFormSubmissions) &&
- !submitted_forms_.insert(form.unique_renderer_id).second) {
+ !submitted_forms_.insert(raw_form.unique_renderer_id).second) {
return;
}
- autofill_handler_->OnFormSubmitted(form, known_success, source);
+ autofill_manager_->OnFormSubmitted(GetFormWithFrameAndFormMetaData(raw_form),
+ known_success, source);
}
-void ContentAutofillDriver::TextFieldDidChange(const FormData& form,
- const FormFieldData& field,
+void ContentAutofillDriver::TextFieldDidChange(const FormData& raw_form,
+ const FormFieldData& raw_field,
const gfx::RectF& bounding_box,
base::TimeTicks timestamp) {
- autofill_handler_->OnTextFieldDidChange(form, field, bounding_box, timestamp);
+ autofill_manager_->OnTextFieldDidChange(
+ GetFormWithFrameAndFormMetaData(raw_form),
+ GetFieldWithFrameAndFormMetaData(raw_field), bounding_box, timestamp);
}
-void ContentAutofillDriver::TextFieldDidScroll(const FormData& form,
- const FormFieldData& field,
+void ContentAutofillDriver::TextFieldDidScroll(const FormData& raw_form,
+ const FormFieldData& raw_field,
const gfx::RectF& bounding_box) {
- autofill_handler_->OnTextFieldDidScroll(form, field, bounding_box);
+ autofill_manager_->OnTextFieldDidScroll(
+ GetFormWithFrameAndFormMetaData(raw_form),
+ GetFieldWithFrameAndFormMetaData(raw_field), bounding_box);
}
void ContentAutofillDriver::SelectControlDidChange(
- const FormData& form,
- const FormFieldData& field,
+ const FormData& raw_form,
+ const FormFieldData& raw_field,
const gfx::RectF& bounding_box) {
- autofill_handler_->OnSelectControlDidChange(form, field, bounding_box);
+ autofill_manager_->OnSelectControlDidChange(
+ GetFormWithFrameAndFormMetaData(raw_form),
+ GetFieldWithFrameAndFormMetaData(raw_field), bounding_box);
}
void ContentAutofillDriver::QueryFormFieldAutofill(
int32_t id,
- const FormData& form,
- const FormFieldData& field,
+ const FormData& raw_form,
+ const FormFieldData& raw_field,
const gfx::RectF& bounding_box,
bool autoselect_first_suggestion) {
- autofill_handler_->OnQueryFormFieldAutofill(id, form, field, bounding_box,
- autoselect_first_suggestion);
+ autofill_manager_->OnQueryFormFieldAutofill(
+ id, GetFormWithFrameAndFormMetaData(raw_form),
+ GetFieldWithFrameAndFormMetaData(raw_field), bounding_box,
+ autoselect_first_suggestion);
}
void ContentAutofillDriver::HidePopup() {
- autofill_handler_->OnHidePopup();
+ autofill_manager_->OnHidePopup();
}
void ContentAutofillDriver::FocusNoLongerOnForm(bool had_interacted_form) {
- autofill_handler_->OnFocusNoLongerOnForm(had_interacted_form);
+ autofill_manager_->OnFocusNoLongerOnForm(had_interacted_form);
}
-void ContentAutofillDriver::FocusOnFormField(const FormData& form,
- const FormFieldData& field,
+void ContentAutofillDriver::FocusOnFormField(const FormData& raw_form,
+ const FormFieldData& raw_field,
const gfx::RectF& bounding_box) {
- autofill_handler_->OnFocusOnFormField(form, field, bounding_box);
+ autofill_manager_->OnFocusOnFormField(
+ GetFormWithFrameAndFormMetaData(raw_form),
+ GetFieldWithFrameAndFormMetaData(raw_field), bounding_box);
}
-void ContentAutofillDriver::DidFillAutofillFormData(const FormData& form,
+void ContentAutofillDriver::DidFillAutofillFormData(const FormData& raw_form,
base::TimeTicks timestamp) {
- autofill_handler_->OnDidFillAutofillFormData(form, timestamp);
+ autofill_manager_->OnDidFillAutofillFormData(
+ GetFormWithFrameAndFormMetaData(raw_form), timestamp);
}
void ContentAutofillDriver::DidPreviewAutofillFormData() {
- autofill_handler_->OnDidPreviewAutofillFormData();
+ autofill_manager_->OnDidPreviewAutofillFormData();
}
void ContentAutofillDriver::DidEndTextFieldEditing() {
- autofill_handler_->OnDidEndTextFieldEditing();
+ autofill_manager_->OnDidEndTextFieldEditing();
}
-void ContentAutofillDriver::SelectFieldOptionsDidChange(const FormData& form) {
- autofill_handler_->SelectFieldOptionsDidChange(form);
+void ContentAutofillDriver::SelectFieldOptionsDidChange(
+ const FormData& raw_form) {
+ autofill_manager_->SelectFieldOptionsDidChange(
+ GetFormWithFrameAndFormMetaData(raw_form));
}
void ContentAutofillDriver::DidNavigateFrame(
@@ -359,8 +406,8 @@ void ContentAutofillDriver::DidNavigateFrame(
if (navigation_handle->IsSameDocument()) {
// On page refresh, reset the rate limiter for fetching authentication
// details for credit card unmasking.
- if (autofill_manager_) {
- autofill_manager_->credit_card_access_manager()
+ if (browser_autofill_manager_) {
+ browser_autofill_manager_->credit_card_access_manager()
->SignalCanFetchUnmaskDetails();
}
return;
@@ -369,24 +416,25 @@ void ContentAutofillDriver::DidNavigateFrame(
ShowOfferNotificationIfApplicable(navigation_handle);
// When IsServedFromBackForwardCache, the form data is not parsed
- // again. So, we should keep and use the autofill handler's
+ // again. So, we should keep and use the autofill manager's
// form_structures from BFCache for form submit.
if (navigation_handle->IsServedFromBackForwardCache())
return;
submitted_forms_.clear();
- autofill_handler_->Reset();
+ autofill_manager_->Reset();
}
-void ContentAutofillDriver::SetAutofillManager(
- std::unique_ptr<AutofillManager> manager) {
- autofill_handler_ = std::move(manager);
- autofill_manager_ = static_cast<AutofillManager*>(autofill_handler_.get());
+void ContentAutofillDriver::SetBrowserAutofillManager(
+ std::unique_ptr<BrowserAutofillManager> manager) {
+ autofill_manager_ = std::move(manager);
+ browser_autofill_manager_ =
+ static_cast<BrowserAutofillManager*>(autofill_manager_.get());
}
ContentAutofillDriver::ContentAutofillDriver()
: render_frame_host_(nullptr),
- autofill_manager_(nullptr),
+ browser_autofill_manager_(nullptr),
key_press_handler_manager_(this),
log_manager_(nullptr) {}
@@ -426,16 +474,38 @@ void ContentAutofillDriver::RemoveHandler(
view->GetRenderWidgetHost()->RemoveKeyPressEventCallback(handler);
}
-void ContentAutofillDriver::SetAutofillProvider(
- AutofillProvider* provider,
- AutofillClient* client,
- AutofillHandler::AutofillDownloadManagerState enable_download_manager) {
- autofill_handler_ = std::make_unique<AutofillHandlerProxy>(
- this, client, provider, enable_download_manager);
- GetAutofillAgent()->SetUserGestureRequired(false);
- GetAutofillAgent()->SetSecureContextRequired(true);
- GetAutofillAgent()->SetFocusRequiresScroll(false);
- GetAutofillAgent()->SetQueryPasswordSuggestion(true);
+void ContentAutofillDriver::SetFrameAndFormMetaData(
+ FormFieldData& field) const {
+ field.host_frame =
+ LocalFrameToken(render_frame_host_->GetFrameToken().value());
+}
+
+void ContentAutofillDriver::SetFrameAndFormMetaData(FormData& form) const {
+ form.host_frame =
+ LocalFrameToken(render_frame_host_->GetFrameToken().value());
+
+ form.url = StripAuthAndParams(render_frame_host_->GetLastCommittedURL());
+ form.full_url = render_frame_host_->GetLastCommittedURL();
+
+ if (auto* main_rfh = render_frame_host_->GetMainFrame())
+ form.main_frame_origin = main_rfh->GetLastCommittedOrigin();
+ else
+ form.main_frame_origin = url::Origin();
+
+ for (FormFieldData& field : form.fields)
+ SetFrameAndFormMetaData(field);
+}
+
+FormFieldData ContentAutofillDriver::GetFieldWithFrameAndFormMetaData(
+ FormFieldData field) const {
+ SetFrameAndFormMetaData(field);
+ return field;
+}
+
+FormData ContentAutofillDriver::GetFormWithFrameAndFormMetaData(
+ FormData form) const {
+ SetFrameAndFormMetaData(form);
+ return form;
}
bool ContentAutofillDriver::DocumentUsedWebOTP() const {
@@ -443,14 +513,15 @@ bool ContentAutofillDriver::DocumentUsedWebOTP() const {
}
void ContentAutofillDriver::MaybeReportAutofillWebOTPMetrics() {
- // In tests, the autofill_manager_ may be unset or destroyed before |this|.
- if (!autofill_manager_)
+ // In tests, the browser_autofill_manager_ may be unset or destroyed before
+ // |this|.
+ if (!browser_autofill_manager_)
return;
// It's possible that a frame without any form uses WebOTP. e.g. a server may
// send the verification code to a phone number that was collected beforehand
// and uses the WebOTP API for authentication purpose without user manually
// entering the code.
- if (!autofill_manager_->has_parsed_forms() && !DocumentUsedWebOTP())
+ if (!browser_autofill_manager_->has_parsed_forms() && !DocumentUsedWebOTP())
return;
ReportAutofillWebOTPMetrics(DocumentUsedWebOTP());
@@ -458,15 +529,17 @@ void ContentAutofillDriver::MaybeReportAutofillWebOTPMetrics() {
void ContentAutofillDriver::ReportAutofillWebOTPMetrics(
bool document_used_webotp) {
- if (autofill_manager_->has_observed_phone_number_field())
+ if (browser_autofill_manager_->has_observed_phone_number_field())
phone_collection_metric_state_ |= phone_collection_metric::kPhoneCollected;
- if (autofill_manager_->has_observed_one_time_code_field())
+ if (browser_autofill_manager_->has_observed_one_time_code_field())
phone_collection_metric_state_ |= phone_collection_metric::kOTCUsed;
if (document_used_webotp)
phone_collection_metric_state_ |= phone_collection_metric::kWebOTPUsed;
- ukm::UkmRecorder* recorder = autofill_manager_->client()->GetUkmRecorder();
- ukm::SourceId source_id = autofill_manager_->client()->GetUkmSourceId();
+ ukm::UkmRecorder* recorder =
+ browser_autofill_manager_->client()->GetUkmRecorder();
+ ukm::SourceId source_id =
+ browser_autofill_manager_->client()->GetUkmSourceId();
AutofillMetrics::LogWebOTPPhoneCollectionMetricStateUkm(
recorder, source_id, phone_collection_metric_state_);
@@ -475,52 +548,45 @@ void ContentAutofillDriver::ReportAutofillWebOTPMetrics(
static_cast<PhoneCollectionMetricState>(phone_collection_metric_state_));
}
-void ContentAutofillDriver::SetAutofillProviderForTesting(
- AutofillProvider* provider,
- AutofillClient* client) {
- SetAutofillProvider(provider, client,
- AutofillHandler::AutofillDownloadManagerState::
- DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
- // AutofillManager isn't used if provider is valid.
- autofill_manager_ = nullptr;
-}
-
void ContentAutofillDriver::ShowOfferNotificationIfApplicable(
content::NavigationHandle* navigation_handle) {
if (!navigation_handle->IsInMainFrame())
return;
- // TODO(crbug.com/1093057): Android webview does not have |autofill_manager_|,
- // so flow is not enabled in Android Webview.
+ // TODO(crbug.com/1093057): Android webview does not have
+ // |browser_autofill_manager_|, so flow is not enabled in Android Webview.
if (!base::FeatureList::IsEnabled(
features::kAutofillEnableOfferNotification) ||
- !autofill_manager_) {
+ !browser_autofill_manager_) {
return;
}
- AutofillOfferManager* offer_manager = autofill_manager_->offer_manager();
+ AutofillOfferManager* offer_manager =
+ browser_autofill_manager_->offer_manager();
// This happens in the Incognito mode.
if (!offer_manager)
return;
- GURL url = autofill_manager_->client()->GetLastCommittedURL();
+ GURL url = browser_autofill_manager_->client()->GetLastCommittedURL();
if (!offer_manager->IsUrlEligible(url))
return;
// Try to show offer notification when the last committed URL has the domain
// that an offer is applicable for.
- std::tuple<std::vector<GURL>, GURL, CreditCard*> result =
- offer_manager->GetEligibleDomainsAndCardForOfferForUrl(url);
- std::vector<GURL>& domains = std::get<0>(result);
- GURL offer_details_url = std::get<1>(result);
- CreditCard* card = std::get<2>(result);
- // TODO(crbug.com/1093057): Update return condition once we introduce the
- // promo offers.
- if (domains.empty() || !card)
+ // TODO(crbug.com/1203811): GetOfferForUrl needs to know whether to give
+ // precedence to card-linked offers or promo code offers. Eventually, promo
+ // code offers should take precedence if a bubble is shown. Currently, if a
+ // url has both types of offers and the promo code offer is selected, no
+ // bubble will end up being shown (due to not yet being implemented).
+ AutofillOfferData* offer = offer_manager->GetOfferForUrl(url);
+
+ if (!offer || offer->merchant_domain.empty() ||
+ (offer->IsCardLinkedOffer() && offer->eligible_instrument_id.empty()) ||
+ (offer->IsPromoCodeOffer() && offer->promo_code.empty())) {
return;
+ }
- autofill_manager_->client()->ShowOfferNotificationIfApplicable(
- domains, offer_details_url, card);
+ browser_autofill_manager_->client()->ShowOfferNotificationIfApplicable(offer);
}
} // namespace autofill
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver.h b/chromium/components/autofill/content/browser/content_autofill_driver.h
index 5ca780e8cc7..8558721409b 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver.h
@@ -16,7 +16,7 @@
#include "components/autofill/content/common/mojom/autofill_agent.mojom.h"
#include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
#include "components/autofill/core/browser/autofill_driver.h"
-#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/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"
@@ -29,7 +29,6 @@ class RenderFrameHost;
namespace autofill {
class AutofillClient;
-class AutofillProvider;
class LogManager;
// Use <Phone><WebOTP><OTC> as the bit pattern to identify the metrics state.
@@ -62,8 +61,9 @@ class ContentAutofillDriver : public AutofillDriver,
content::RenderFrameHost* render_frame_host,
AutofillClient* client,
const std::string& app_locale,
- AutofillHandler::AutofillDownloadManagerState enable_download_manager,
- AutofillProvider* provider);
+ AutofillManager::AutofillDownloadManagerState enable_download_manager,
+ AutofillManager::AutofillManagerFactoryCallback
+ autofill_manager_factory_callback);
~ContentAutofillDriver() override;
// Gets the driver for |render_frame_host|.
@@ -106,10 +106,12 @@ class ContentAutofillDriver : public AutofillDriver,
gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) override;
net::IsolationInfo IsolationInfo() override;
+ void SendFieldsEligibleForManualFillingToRenderer(
+ const std::vector<FieldRendererId>& fields) override;
// mojom::AutofillDriver:
void SetFormToBeProbablySubmitted(
- const base::Optional<FormData>& form) override;
+ const absl::optional<FormData>& form) override;
void FormsSeen(const std::vector<FormData>& forms) override;
void FormSubmitted(const FormData& form,
bool known_success,
@@ -146,8 +148,10 @@ class ContentAutofillDriver : public AutofillDriver,
// navigation occurs in that specific frame.
void DidNavigateFrame(content::NavigationHandle* navigation_handle);
- AutofillManager* autofill_manager() { return autofill_manager_; }
- AutofillHandler* autofill_handler() { return autofill_handler_.get(); }
+ BrowserAutofillManager* browser_autofill_manager() {
+ return browser_autofill_manager_;
+ }
+ AutofillManager* autofill_manager() { return autofill_manager_.get(); }
content::RenderFrameHost* render_frame_host() { return render_frame_host_; }
const mojo::AssociatedRemote<mojom::AutofillAgent>& GetAutofillAgent();
@@ -157,15 +161,14 @@ class ContentAutofillDriver : public AutofillDriver,
const content::RenderWidgetHost::KeyPressEventCallback& handler);
void RemoveKeyPressHandler();
- void SetAutofillProviderForTesting(AutofillProvider* provider,
- AutofillClient* client);
-
// Sets the manager to |manager|. Takes ownership of |manager|.
- void SetAutofillManager(std::unique_ptr<AutofillManager> manager);
+ void SetBrowserAutofillManager(
+ std::unique_ptr<BrowserAutofillManager> manager);
// Reports whether a document collects phone numbers, uses one time code, uses
// WebOTP. There are cases that the reporting is not expected:
- // 1. some unit tests do not set necessary members, |autofill_manager_|
+ // 1. some unit tests do not set necessary members,
+ // |browser_autofill_manager_|
// 2. there is no form and WebOTP is not used
// |MaybeReportAutofillWebOTPMetrics| is to exclude the cases above.
// |ReportAutofillWebOTPMetrics| is visible for unit tests where the
@@ -174,20 +177,29 @@ class ContentAutofillDriver : public AutofillDriver,
void ReportAutofillWebOTPMetrics(bool document_used_webotp);
protected:
- // Constructor for tests.
+ // Constructor for TestAutofillDriver.
ContentAutofillDriver();
private:
+ friend class ContentAutofillDriverTestApi;
+
// KeyPressHandlerManager::Delegate:
void AddHandler(
const content::RenderWidgetHost::KeyPressEventCallback& handler) override;
void RemoveHandler(
const content::RenderWidgetHost::KeyPressEventCallback& handler) override;
- void SetAutofillProvider(
- AutofillProvider* provider,
- AutofillClient* client,
- AutofillHandler::AutofillDownloadManagerState enable_download_manager);
+ // Sets parameters of |form| and |field| that can be extracted from
+ // |render_frame_host_|.
+ //
+ // These functions must be called for every FormData and FormFieldData
+ // received from the renderer.
+ void SetFrameAndFormMetaData(FormFieldData& field) const;
+ void SetFrameAndFormMetaData(FormData& form) const;
+ FormFieldData GetFieldWithFrameAndFormMetaData(FormFieldData field) const
+ WARN_UNUSED_RESULT;
+ FormData GetFormWithFrameAndFormMetaData(FormData form) const
+ WARN_UNUSED_RESULT;
// Returns whether navigator.credentials.get({otp: {transport:"sms"}}) has
// been used.
@@ -205,20 +217,20 @@ class ContentAutofillDriver : public AutofillDriver,
// The form pushed from the AutofillAgent to the AutofillDriver. When the
// ProbablyFormSubmitted() event is fired, this form is considered the
// submitted one.
- base::Optional<FormData> potentially_submitted_form_;
+ absl::optional<FormData> potentially_submitted_form_;
// Keeps track of the forms for which FormSubmitted() event has been triggered
// to avoid duplicates fired by AutofillAgent.
std::set<FormRendererId> submitted_forms_;
- // AutofillHandler instance via which this object drives the shared Autofill
+ // AutofillManager instance via which this object drives the shared Autofill
// code.
- std::unique_ptr<AutofillHandler> autofill_handler_;
+ std::unique_ptr<AutofillManager> autofill_manager_;
- // The pointer to autofill_handler_ if it is AutofillManager instance.
- // TODO: unify autofill_handler_ and autofill_manager_ to a single pointer to
- // a common root.
- AutofillManager* autofill_manager_;
+ // The pointer to autofill_manager_ if it is BrowserAutofillManager instance.
+ // TODO: unify autofill_manager_ and browser_autofill_manager_ to a single
+ // pointer to a common root.
+ BrowserAutofillManager* browser_autofill_manager_;
// Pointer to an implementation of InternalAuthenticator.
std::unique_ptr<InternalAuthenticator> authenticator_impl_;
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc b/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
index e09ac529cfb..34d4ea9b810 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.cc
@@ -12,7 +12,7 @@
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
-#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/common/autofill_features.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/navigation_handle.h"
@@ -28,10 +28,13 @@ std::unique_ptr<AutofillDriver> CreateDriver(
content::RenderFrameHost* render_frame_host,
AutofillClient* client,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager,
- AutofillProvider* provider) {
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager,
+ AutofillManager::AutofillManagerFactoryCallback
+ autofill_manager_factory_callback) {
return std::make_unique<ContentAutofillDriver>(
- render_frame_host, client, app_locale, enable_download_manager, provider);
+ render_frame_host, client, app_locale, enable_download_manager,
+ std::move(autofill_manager_factory_callback));
}
} // namespace
@@ -47,24 +50,29 @@ void ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
content::WebContents* contents,
AutofillClient* client,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager) {
- CreateForWebContentsAndDelegate(contents, client, app_locale,
- enable_download_manager, nullptr);
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager) {
+ CreateForWebContentsAndDelegate(
+ contents, client, app_locale, enable_download_manager,
+ AutofillManager::AutofillManagerFactoryCallback());
}
void ContentAutofillDriverFactory::CreateForWebContentsAndDelegate(
content::WebContents* contents,
AutofillClient* client,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager,
- AutofillProvider* provider) {
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager,
+ AutofillManager::AutofillManagerFactoryCallback
+ autofill_manager_factory_callback) {
if (FromWebContents(contents))
return;
contents->SetUserData(
kContentAutofillDriverFactoryWebContentsUserDataKey,
std::make_unique<ContentAutofillDriverFactory>(
- contents, client, app_locale, enable_download_manager, provider));
+ contents, client, app_locale, enable_download_manager,
+ std::move(autofill_manager_factory_callback)));
}
// static
@@ -102,13 +110,16 @@ ContentAutofillDriverFactory::ContentAutofillDriverFactory(
content::WebContents* web_contents,
AutofillClient* client,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager,
- AutofillProvider* provider)
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager,
+ AutofillManager::AutofillManagerFactoryCallback
+ autofill_manager_factory_callback)
: AutofillDriverFactory(client),
content::WebContentsObserver(web_contents),
app_locale_(app_locale),
enable_download_manager_(enable_download_manager),
- provider_(provider) {}
+ autofill_manager_factory_callback_(
+ std::move(autofill_manager_factory_callback)) {}
ContentAutofillDriver* ContentAutofillDriverFactory::DriverForFrame(
content::RenderFrameHost* render_frame_host) {
@@ -116,10 +127,10 @@ ContentAutofillDriver* ContentAutofillDriverFactory::DriverForFrame(
// ContentAutofillDriver are created on demand here.
if (!driver) {
- AddForKey(
- render_frame_host,
- base::BindRepeating(CreateDriver, render_frame_host, client(),
- app_locale_, enable_download_manager_, provider_));
+ AddForKey(render_frame_host,
+ base::BindRepeating(CreateDriver, render_frame_host, client(),
+ app_locale_, enable_download_manager_,
+ autofill_manager_factory_callback_));
driver = DriverForKey(render_frame_host);
}
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver_factory.h b/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
index 31f4637eec5..58c3da47721 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_factory.h
@@ -11,6 +11,7 @@
#include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
#include "components/autofill/core/browser/autofill_driver_factory.h"
#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
@@ -21,7 +22,6 @@ class RenderFrameHost;
namespace autofill {
class ContentAutofillDriver;
-class AutofillProvider;
// Manages lifetime of ContentAutofillDriver. One Factory per WebContents
// creates one Driver per RenderFrame.
@@ -35,8 +35,10 @@ class ContentAutofillDriverFactory : public AutofillDriverFactory,
content::WebContents* web_contents,
AutofillClient* client,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager,
- AutofillProvider* provider);
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager,
+ AutofillManager::AutofillManagerFactoryCallback
+ autofill_manager_factory_callback);
~ContentAutofillDriverFactory() override;
@@ -44,14 +46,17 @@ class ContentAutofillDriverFactory : public AutofillDriverFactory,
content::WebContents* contents,
AutofillClient* client,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager);
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager);
static void CreateForWebContentsAndDelegate(
content::WebContents* contents,
AutofillClient* client,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager,
- AutofillProvider* provider);
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager,
+ AutofillManager::AutofillManagerFactoryCallback
+ autofill_manager_factory_callback);
static ContentAutofillDriverFactory* FromWebContents(
content::WebContents* contents);
@@ -76,8 +81,9 @@ class ContentAutofillDriverFactory : public AutofillDriverFactory,
private:
std::string app_locale_;
- AutofillManager::AutofillDownloadManagerState enable_download_manager_;
- AutofillProvider* provider_;
+ BrowserAutofillManager::AutofillDownloadManagerState enable_download_manager_;
+ AutofillManager::AutofillManagerFactoryCallback
+ autofill_manager_factory_callback_;
};
} // namespace autofill
diff --git a/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc b/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
index 8c09abea008..b3d2b862235 100644
--- a/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/chromium/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -17,11 +17,12 @@
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
-#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/form_data_predictions.h"
+#include "components/autofill/core/common/unique_ids.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/ssl_status.h"
@@ -40,8 +41,8 @@ namespace autofill {
namespace {
const char kAppLocale[] = "en-US";
-const AutofillManager::AutofillDownloadManagerState kDownloadState =
- AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER;
+const BrowserAutofillManager::AutofillDownloadManagerState kDownloadState =
+ BrowserAutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER;
class FakeAutofillAgent : public mojom::AutofillAgent {
public:
@@ -228,48 +229,77 @@ class FakeAutofillAgent : public mojom::AutofillAgent {
void SetQueryPasswordSuggestion(bool query) override {}
- void GetElementFormAndFieldData(
- const std::vector<std::string>& selectors,
- GetElementFormAndFieldDataCallback callback) override {}
+ void GetElementFormAndFieldDataAtIndex(
+ const std::string& selector,
+ int index,
+ GetElementFormAndFieldDataAtIndexCallback callback) override {}
void SetAssistantActionState(bool running) override {}
+ void SetFieldsEligibleForManualFilling(
+ const std::vector<FieldRendererId>& fields) override {}
+
mojo::AssociatedReceiverSet<mojom::AutofillAgent> receivers_;
base::OnceClosure quit_closure_;
// Records data received from FillForm() call.
int32_t fill_form_id_;
- base::Optional<FormData> fill_form_form_;
+ absl::optional<FormData> fill_form_form_;
// Records data received from PreviewForm() call.
int32_t preview_form_id_;
- base::Optional<FormData> preview_form_form_;
+ absl::optional<FormData> preview_form_form_;
// Records data received from FieldTypePredictionsAvailable() call.
- base::Optional<std::vector<FormDataPredictions>> predictions_;
+ absl::optional<std::vector<FormDataPredictions>> predictions_;
// Records whether ClearSection() got called.
bool called_clear_section_;
// Records whether ClearPreviewedForm() got called.
bool called_clear_previewed_form_;
// Records the ID received from FillFieldWithValue(), PreviewFieldWithValue(),
// SetSuggestionAvailability(), or AcceptDataListSuggestion().
- base::Optional<FieldRendererId> value_renderer_id_;
+ absl::optional<FieldRendererId> value_renderer_id_;
// Records string received from FillFieldWithValue() call.
- base::Optional<std::u16string> value_fill_field_;
+ absl::optional<std::u16string> value_fill_field_;
// Records string received from PreviewFieldWithValue() call.
- base::Optional<std::u16string> value_preview_field_;
+ absl::optional<std::u16string> value_preview_field_;
// Records string received from AcceptDataListSuggestion() call.
- base::Optional<std::u16string> value_accept_data_;
+ absl::optional<std::u16string> value_accept_data_;
// Records bool received from SetSuggestionAvailability() call.
bool suggestions_available_;
};
} // namespace
-class MockAutofillManager : public AutofillManager {
+class ContentAutofillDriverTestApi {
public:
- MockAutofillManager(AutofillDriver* driver, AutofillClient* client)
- : AutofillManager(driver, client, kAppLocale, kDownloadState) {}
- ~MockAutofillManager() override {}
+ explicit ContentAutofillDriverTestApi(ContentAutofillDriver* driver)
+ : driver_(driver) {}
+
+ void SetFrameAndFormMetaData(FormFieldData& field) const {
+ driver_->SetFrameAndFormMetaData(field);
+ }
+
+ void SetFrameAndFormMetaData(FormData& form) const {
+ driver_->SetFrameAndFormMetaData(form);
+ }
+
+ FormFieldData GetFieldWithFrameAndFormMetaData(FormFieldData field) const {
+ return driver_->GetFieldWithFrameAndFormMetaData(field);
+ }
+
+ FormData GetFormWithFrameAndFormMetaData(FormData form) const {
+ return driver_->GetFormWithFrameAndFormMetaData(form);
+ }
+
+ private:
+ ContentAutofillDriver* driver_;
+};
+
+class MockBrowserAutofillManager : public BrowserAutofillManager {
+ public:
+ MockBrowserAutofillManager(AutofillDriver* driver, AutofillClient* client)
+ : BrowserAutofillManager(driver, client, kAppLocale, kDownloadState) {}
+ ~MockBrowserAutofillManager() override {}
MOCK_METHOD0(Reset, void());
};
@@ -283,19 +313,20 @@ class TestContentAutofillDriver : public ContentAutofillDriver {
public:
TestContentAutofillDriver(content::RenderFrameHost* rfh,
AutofillClient* client)
- : ContentAutofillDriver(rfh,
- client,
- kAppLocale,
- kDownloadState,
- nullptr) {
- std::unique_ptr<AutofillManager> autofill_manager(
- new MockAutofillManager(this, client));
- SetAutofillManager(std::move(autofill_manager));
+ : ContentAutofillDriver(
+ rfh,
+ client,
+ kAppLocale,
+ kDownloadState,
+ AutofillManager::AutofillManagerFactoryCallback()) {
+ std::unique_ptr<BrowserAutofillManager> autofill_manager(
+ new MockBrowserAutofillManager(this, client));
+ SetBrowserAutofillManager(std::move(autofill_manager));
}
~TestContentAutofillDriver() override {}
- virtual MockAutofillManager* mock_autofill_manager() {
- return static_cast<MockAutofillManager*>(autofill_manager());
+ virtual MockBrowserAutofillManager* mock_browser_autofill_manager() {
+ return static_cast<MockBrowserAutofillManager*>(browser_autofill_manager());
}
using ContentAutofillDriver::DidNavigateFrame;
@@ -344,20 +375,65 @@ class ContentAutofillDriverTest : public content::RenderViewHostTestHarness {
};
TEST_F(ContentAutofillDriverTest, NavigatedMainFrameDifferentDocument) {
- EXPECT_CALL(*driver_->mock_autofill_manager(), Reset());
+ EXPECT_CALL(*driver_->mock_browser_autofill_manager(), Reset());
Navigate(/*same_document=*/false);
}
TEST_F(ContentAutofillDriverTest, NavigatedMainFrameSameDocument) {
- EXPECT_CALL(*driver_->mock_autofill_manager(), Reset()).Times(0);
+ EXPECT_CALL(*driver_->mock_browser_autofill_manager(), Reset()).Times(0);
Navigate(/*same_document=*/true);
}
TEST_F(ContentAutofillDriverTest, NavigatedMainFrameFromBackForwardCache) {
- EXPECT_CALL(*driver_->mock_autofill_manager(), Reset()).Times(0);
+ EXPECT_CALL(*driver_->mock_browser_autofill_manager(), Reset()).Times(0);
Navigate(/*same_document=*/false, /*from_bfcache=*/true);
}
+TEST_F(ContentAutofillDriverTest, SetFrameAndFormMetaDataOfForm) {
+ NavigateAndCommit(GURL("https://username:password@hostname/path?query#hash"));
+ FormData form;
+ form.fields.push_back(FormFieldData());
+ FormData form2 = ContentAutofillDriverTestApi(driver_.get())
+ .GetFormWithFrameAndFormMetaData(form);
+ ContentAutofillDriverTestApi(driver_.get()).SetFrameAndFormMetaData(form);
+
+ EXPECT_EQ(
+ form.host_frame,
+ LocalFrameToken(web_contents()->GetMainFrame()->GetFrameToken().value()));
+ EXPECT_EQ(form.url, GURL("https://hostname/path"));
+ EXPECT_EQ(form.full_url,
+ GURL("https://username:password@hostname/path?query#hash"));
+ EXPECT_EQ(form.main_frame_origin,
+ web_contents()->GetMainFrame()->GetLastCommittedOrigin());
+ EXPECT_EQ(form.main_frame_origin,
+ url::Origin::CreateFromNormalizedTuple("https", "hostname", 443));
+ ASSERT_EQ(form.fields.size(), 1u);
+ EXPECT_EQ(
+ form.fields.front().host_frame,
+ LocalFrameToken(web_contents()->GetMainFrame()->GetFrameToken().value()));
+
+ EXPECT_EQ(form2.host_frame, form.host_frame);
+ EXPECT_EQ(form2.url, form.url);
+ EXPECT_EQ(form2.full_url, form.full_url);
+ EXPECT_EQ(form2.main_frame_origin, form.main_frame_origin);
+ ASSERT_EQ(form2.fields.size(), 1u);
+ EXPECT_EQ(form2.fields.front().host_frame, form2.fields.front().host_frame);
+}
+
+TEST_F(ContentAutofillDriverTest, SetFrameAndFormMetaDataOfField) {
+ NavigateAndCommit(GURL("https://username:password@hostname/path?query#hash"));
+ FormFieldData field;
+ FormFieldData field2 = ContentAutofillDriverTestApi(driver_.get())
+ .GetFieldWithFrameAndFormMetaData(field);
+ ContentAutofillDriverTestApi(driver_.get()).SetFrameAndFormMetaData(field);
+
+ EXPECT_EQ(
+ field.host_frame,
+ LocalFrameToken(web_contents()->GetMainFrame()->GetFrameToken().value()));
+
+ EXPECT_EQ(field2.host_frame, field.host_frame);
+}
+
TEST_F(ContentAutofillDriverTest, FormDataSentToRenderer_FillForm) {
int input_page_id = 42;
FormData input_form_data;
diff --git a/chromium/components/autofill/content/browser/risk/fingerprint.cc b/chromium/components/autofill/content/browser/risk/fingerprint.cc
index 2607d63a434..c6deb746a42 100644
--- a/chromium/components/autofill/content/browser/risk/fingerprint.cc
+++ b/chromium/components/autofill/content/browser/risk/fingerprint.cc
@@ -89,7 +89,7 @@ std::string GetOperatingSystemVersion() {
// Adds the list of |fonts| to the |machine|.
void AddFontsToFingerprint(const base::ListValue& fonts,
Fingerprint::MachineCharacteristics* machine) {
- for (const auto& it : fonts) {
+ for (const auto& it : fonts.GetList()) {
// Each item in the list is a two-element list such that the first element
// is the font family and the second is the font name.
const base::ListValue* font_description = nullptr;
diff --git a/chromium/components/autofill/content/browser/webauthn/internal_authenticator_impl.h b/chromium/components/autofill/content/browser/webauthn/internal_authenticator_impl.h
index f85097829de..9811f10f145 100644
--- a/chromium/components/autofill/content/browser/webauthn/internal_authenticator_impl.h
+++ b/chromium/components/autofill/content/browser/webauthn/internal_authenticator_impl.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <memory>
-#include <string>
#include "base/macros.h"
#include "components/autofill/core/browser/payments/internal_authenticator.h"
diff --git a/chromium/components/autofill/content/common/mojom/autofill_agent.mojom b/chromium/components/autofill/content/common/mojom/autofill_agent.mojom
index 4624e53f457..1e8bab83e27 100644
--- a/chromium/components/autofill/content/common/mojom/autofill_agent.mojom
+++ b/chromium/components/autofill/content/common/mojom/autofill_agent.mojom
@@ -74,9 +74,10 @@ interface AutofillAgent {
// Configures whether AutofillAgent will query password field autofill suggestions. The default is false.
SetQueryPasswordSuggestion(bool query);
- // Get form element's form and field data.
- // The form field is given by an path defined by an array of CSS selectors.
- GetElementFormAndFieldData(array<string> selectors) => (
+ // Get form element's form and field data. The form field is given by a
+ // selector returning an arbitrary number of results and an index for
+ // selecting the specified result.
+ GetElementFormAndFieldDataAtIndex(string selector, int32 index) => (
autofill.mojom.FormData form, autofill.mojom.FormFieldData field);
// Set whether or not an assistant action is currently running an action.
@@ -85,6 +86,9 @@ interface AutofillAgent {
// Allows heavy scraping of form data (e.g., button titles for
// unowned forms).
EnableHeavyFormDataScraping();
+
+ // Update fields that are eligible to show manual filling on form interaction.
+ SetFieldsEligibleForManualFilling(array<FieldRendererId> fields);
};
// There is one instance of this interface per render frame in the render
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.cc b/chromium/components/autofill/content/renderer/autofill_agent.cc
index 5c3cbd6acfe..ee34b7b637a 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/autofill_agent.cc
@@ -16,7 +16,6 @@
#include "base/i18n/case_conversion.h"
#include "base/location.h"
#include "base/metrics/field_trial.h"
-#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
@@ -49,6 +48,7 @@
#include "content/public/renderer/render_view.h"
#include "net/cert/cert_status_flags.h"
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -422,6 +422,9 @@ void AutofillAgent::FillForm(int32_t id, const FormData& form) {
if (!element_.Form().IsNull())
UpdateLastInteractedForm(element_.Form());
+ // TODO(crbug.com/1198811): Inform the BrowserAutofillManager about the fields
+ // that were actually filled. It's possible that the form has changed since
+ // the time filling was triggered.
GetAutofillDriver()->DidFillAutofillFormData(form,
AutofillTickClock::NowTicks());
@@ -698,19 +701,29 @@ void AutofillAgent::SetFocusRequiresScroll(bool require) {
focus_requires_scroll_ = require;
}
-void AutofillAgent::GetElementFormAndFieldData(
- const std::vector<std::string>& selectors,
- GetElementFormAndFieldDataCallback callback) {
+void AutofillAgent::GetElementFormAndFieldDataAtIndex(
+ const std::string& selector,
+ int index,
+ GetElementFormAndFieldDataAtIndexCallback callback) {
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
if (!frame)
return;
+ blink::WebElement target_element;
+ blink::WebVector<blink::WebElement> elements =
+ render_frame()->GetWebFrame()->GetDocument().QuerySelectorAll(
+ blink::WebString::FromUTF8(selector));
+ if (index >= 0 && static_cast<size_t>(index) < elements.size()) {
+ target_element = elements[index];
+ }
+
FormData form;
FormFieldData field;
- form.host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
- field.host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
+ if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer)) {
+ form.host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
+ field.host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
+ }
- blink::WebElement target_element = FindUniqueWebElement(selectors);
if (target_element.IsNull() || !target_element.IsFormControlElement()) {
return std::move(callback).Run(form, field);
}
@@ -730,42 +743,6 @@ void AutofillAgent::GetElementFormAndFieldData(
return std::move(callback).Run(form, field);
}
-blink::WebElement AutofillAgent::FindUniqueWebElement(
- const std::vector<std::string>& selectors) {
- DCHECK(selectors.size() > 0);
-
- blink::WebVector<blink::WebElement> elements =
- render_frame()->GetWebFrame()->GetDocument().QuerySelectorAll(
- blink::WebString::FromUTF8(selectors[0]));
- if (elements.size() != 1) {
- return blink::WebElement();
- }
-
- // Get the unique element in |elements| and match the next selector inside it
- // if there are remaining selectors haven't been matched.
- blink::WebElement query_element = elements[0];
- for (size_t i = 1; i < selectors.size(); i++) {
- elements = query_element.QuerySelectorAll(
- blink::WebString::FromUTF8(selectors[i]));
-
- // Query shadow DOM if necessary.
- if (elements.size() == 0 && !query_element.ShadowRoot().IsNull()) {
- // TODO(806868): Query shadow dom when Autofill is available for forms in
- // shadow DOM (crbug.com/746593).
- return blink::WebElement();
- }
-
- // Return an empty element if there are multiple matching elements.
- if (elements.size() != 1) {
- return blink::WebElement();
- }
-
- query_element = elements[0];
- }
-
- return query_element;
-}
-
void AutofillAgent::SetAssistantActionState(bool running) {
DCHECK(autofill_assistant_agent_);
if (running) {
@@ -779,6 +756,11 @@ void AutofillAgent::EnableHeavyFormDataScraping() {
is_heavy_form_data_scraping_enabled_ = true;
}
+void AutofillAgent::SetFieldsEligibleForManualFilling(
+ const std::vector<FieldRendererId>& fields) {
+ form_cache_.SetFieldsEligibleForManualFilling(fields);
+}
+
void AutofillAgent::QueryAutofillSuggestions(
const WebFormControlElement& element,
bool autoselect_first_suggestion) {
@@ -798,10 +780,13 @@ void AutofillAgent::QueryAutofillSuggestions(
static_cast<ExtractMask>(form_util::EXTRACT_BOUNDS |
GetExtractDatalistMask()),
&form, &field)) {
- // |form| may be only partially initialized and may be sent to the browser
- // in this state. Set at least the |host_frame| because sending an empty
- // base::UnguessableToken is illegal.
- form.host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillAugmentFormsInRenderer)) {
+ // |form| may be only partially initialized and may be sent to the browser
+ // in this state. Set at least the |host_frame| because sending an empty
+ // base::UnguessableToken is illegal.
+ form.host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
+ }
// If we didn't find the cached form, at least let autocomplete have a shot
// at providing suggestions.
WebFormControlElementToFormField(
@@ -1053,7 +1038,7 @@ void AutofillAgent::OnProvisionallySaveForm(
}
formless_elements_user_edited_.insert(
FieldRendererId(element.UniqueRendererFormControlId()));
- provisionally_saved_form_ = base::make_optional<FormData>();
+ provisionally_saved_form_ = absl::make_optional<FormData>();
if (!CollectFormlessElements(&provisionally_saved_form_.value())) {
provisionally_saved_form_.reset();
} else {
@@ -1079,7 +1064,7 @@ void AutofillAgent::OnProvisionallySaveForm(
}
void AutofillAgent::OnProbablyFormSubmitted() {
- base::Optional<FormData> form_data = GetSubmittedForm();
+ absl::optional<FormData> form_data = GetSubmittedForm();
if (form_data.has_value()) {
FireHostSubmitEvents(form_data.value(), /*known_success=*/false,
SubmissionSource::PROBABLY_FORM_SUBMITTED);
@@ -1119,7 +1104,7 @@ void AutofillAgent::OnInferredFormSubmission(SubmissionSource source) {
FireHostSubmitEvents(provisionally_saved_form_.value(),
/*known_success=*/true, source);
} else {
- base::Optional<FormData> form_data = GetSubmittedForm();
+ absl::optional<FormData> form_data = GetSubmittedForm();
if (form_data.has_value())
FireHostSubmitEvents(form_data.value(), /*known_success=*/true, source);
}
@@ -1141,14 +1126,14 @@ void AutofillAgent::TrackAutofilledElement(
form_tracker_.TrackAutofilledElement(element);
}
-base::Optional<FormData> AutofillAgent::GetSubmittedForm() const {
+absl::optional<FormData> AutofillAgent::GetSubmittedForm() const {
if (!last_interacted_form_.IsNull()) {
FormData form;
if (form_util::ExtractFormData(last_interacted_form_,
*field_data_manager_.get(), &form)) {
- return base::make_optional(form);
+ return absl::make_optional(form);
} else if (provisionally_saved_form_.has_value()) {
- return base::make_optional(provisionally_saved_form_.value());
+ return absl::make_optional(provisionally_saved_form_.value());
}
} else if (formless_elements_user_edited_.size() != 0 &&
!form_util::IsSomeControlElementVisible(
@@ -1160,12 +1145,12 @@ base::Optional<FormData> AutofillAgent::GetSubmittedForm() const {
// construct form.
FormData form;
if (CollectFormlessElements(&form)) {
- return base::make_optional(form);
+ return absl::make_optional(form);
} else if (provisionally_saved_form_.has_value()) {
- return base::make_optional(provisionally_saved_form_.value());
+ return absl::make_optional(provisionally_saved_form_.value());
}
}
- return base::nullopt;
+ return absl::nullopt;
}
void AutofillAgent::SendPotentiallySubmittedFormToBrowser() {
@@ -1181,7 +1166,7 @@ void AutofillAgent::ResetLastInteractedElements() {
void AutofillAgent::UpdateLastInteractedForm(blink::WebFormElement form) {
last_interacted_form_ = form;
- provisionally_saved_form_ = base::make_optional<FormData>();
+ provisionally_saved_form_ = absl::make_optional<FormData>();
if (!form_util::ExtractFormData(last_interacted_form_,
*field_data_manager_.get(),
&provisionally_saved_form_.value())) {
diff --git a/chromium/components/autofill/content/renderer/autofill_agent.h b/chromium/components/autofill/content/renderer/autofill_agent.h
index c0d6d29dad7..39f99446dbf 100644
--- a/chromium/components/autofill/content/renderer/autofill_agent.h
+++ b/chromium/components/autofill/content/renderer/autofill_agent.h
@@ -12,8 +12,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
-#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/autofill/content/common/mojom/autofill_agent.mojom.h"
#include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
@@ -23,6 +21,7 @@
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_form_control_element.h"
@@ -100,11 +99,14 @@ class AutofillAgent : public content::RenderFrameObserver,
void SetSecureContextRequired(bool required) override;
void SetFocusRequiresScroll(bool require) override;
void SetQueryPasswordSuggestion(bool required) override;
- void GetElementFormAndFieldData(
- const std::vector<std::string>& selectors,
- GetElementFormAndFieldDataCallback callback) override;
+ void GetElementFormAndFieldDataAtIndex(
+ const std::string& selector,
+ int index,
+ GetElementFormAndFieldDataAtIndexCallback callback) override;
void SetAssistantActionState(bool running) override;
void EnableHeavyFormDataScraping() override;
+ void SetFieldsEligibleForManualFilling(
+ const std::vector<FieldRendererId>& fields) override;
void FormControlElementClicked(const blink::WebFormControlElement& element,
bool was_focused);
@@ -252,7 +254,7 @@ class AutofillAgent : public content::RenderFrameObserver,
// Attempt to get submitted FormData from last_interacted_form_ or
// provisionally_saved_form_, return true if |form| is set.
- base::Optional<FormData> GetSubmittedForm() const;
+ absl::optional<FormData> GetSubmittedForm() const;
// Pushes the value of GetSubmittedForm() to the AutofillDriver.
void SendPotentiallySubmittedFormToBrowser();
@@ -287,12 +289,6 @@ class AutofillAgent : public content::RenderFrameObserver,
// label, visibility, control type) have changed after an autofill.
void TriggerRefillIfNeeded(const FormData& form);
- // Find the unique element given by |selectors| in the associated web frame.
- // Empty blink::WebElement is returned if there is no matching element or
- // there are multiple matching elements.
- blink::WebElement FindUniqueWebElement(
- const std::vector<std::string>& selectors);
-
// Formerly cached forms for all frames, now only caches forms for the current
// frame.
FormCache form_cache_;
@@ -323,7 +319,7 @@ class AutofillAgent : public content::RenderFrameObserver,
// The form user interacted, it is used if last_interacted_form_ or formless
// form can't be converted to FormData at the time of form submission.
- base::Optional<FormData> provisionally_saved_form_;
+ absl::optional<FormData> provisionally_saved_form_;
// Keeps track of the forms for which form submitted event has been sent to
// AutofillDriver. We use it to avoid fire duplicated submission event when
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.cc b/chromium/components/autofill/content/renderer/form_autofill_util.cc
index f180dedb1d0..e5c3d389874 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.cc
@@ -16,6 +16,8 @@
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
#include "base/i18n/case_conversion.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
@@ -55,6 +57,7 @@ using blink::WebElement;
using blink::WebElementCollection;
using blink::WebFormControlElement;
using blink::WebFormElement;
+using blink::WebFrame;
using blink::WebInputElement;
using blink::WebLabelElement;
using blink::WebLocalFrame;
@@ -278,18 +281,27 @@ std::u16string FindChildTextWithIgnoreList(
return node_text;
}
-bool IsLabelValid(base::StringPiece16 inferred_label,
- const std::vector<char16_t>& stop_words) {
- // If |inferred_label| has any character other than those in |stop_words|.
- auto* first_non_stop_word = std::find_if(
- inferred_label.begin(), inferred_label.end(),
- [&stop_words](char16_t c) { return !base::Contains(stop_words, c); });
- return first_non_stop_word != inferred_label.end();
+bool IsLabelValid(base::StringPiece16 inferred_label) {
+ // List of characters a label can't be entirely made of (this list can grow).
+ auto IsStopWord = [](char16_t c) {
+ switch (c) {
+ case u' ':
+ case u'*':
+ case u':':
+ case u'-':
+ case u'–': // U+2013
+ case u'(':
+ case u')':
+ return true;
+ default:
+ return false;
+ }
+ };
+ return !base::ranges::all_of(inferred_label, IsStopWord);
}
// Shared function for InferLabelFromPrevious() and InferLabelFromNext().
bool InferLabelFromSibling(const WebFormControlElement& element,
- const std::vector<char16_t>& stop_words,
bool forward,
std::u16string* label,
FormFieldData::LabelSource* label_source) {
@@ -361,7 +373,7 @@ bool InferLabelFromSibling(const WebFormControlElement& element,
}
base::TrimWhitespace(inferred_label, base::TRIM_ALL, &inferred_label);
- if (IsLabelValid(inferred_label, stop_words)) {
+ if (IsLabelValid(inferred_label)) {
*label = std::move(inferred_label);
*label_source = inferred_label_source;
return true;
@@ -417,7 +429,7 @@ void FindElementsWithButtonFeatures(const WebElementCollection& elements,
continue;
if (only_formless_elements &&
IsElementInsideFormOrFieldSet(item,
- false /* consider_fieldset_tags */)) {
+ /*consider_fieldset_tags=*/false)) {
continue;
}
std::u16string title =
@@ -440,21 +452,17 @@ void FindElementsWithButtonFeatures(const WebElementCollection& elements,
// or Some Text <img><input ...>
// or <b>Some Text</b><br/> <input ...>.
bool InferLabelFromPrevious(const WebFormControlElement& element,
- const std::vector<char16_t>& stop_words,
std::u16string* label,
FormFieldData::LabelSource* label_source) {
- return InferLabelFromSibling(element, stop_words, false /* forward? */, label,
- label_source);
+ return InferLabelFromSibling(element, /*forward=*/false, label, label_source);
}
// Same as InferLabelFromPrevious(), but in the other direction.
// Useful for cases like: <span><input type="checkbox">Label For Checkbox</span>
bool InferLabelFromNext(const WebFormControlElement& element,
- const std::vector<char16_t>& stop_words,
std::u16string* label,
FormFieldData::LabelSource* label_source) {
- return InferLabelFromSibling(element, stop_words, true /* forward? */, label,
- label_source);
+ return InferLabelFromSibling(element, /*forward=*/true, label, label_source);
}
// Helper for |InferLabelForElement()| that infers a label, if possible, from
@@ -778,20 +786,19 @@ std::vector<std::string> AncestorTagNames(
// Infers corresponding label for |element| from surrounding context in the DOM,
// e.g. the contents of the preceding <p> tag or text element.
bool InferLabelForElement(const WebFormControlElement& element,
- const std::vector<char16_t>& stop_words,
std::u16string* label,
FormFieldData::LabelSource* label_source) {
if (IsCheckableElement(ToWebInputElement(&element))) {
- if (InferLabelFromNext(element, stop_words, label, label_source))
+ if (InferLabelFromNext(element, label, label_source))
return true;
}
- if (InferLabelFromPrevious(element, stop_words, label, label_source))
+ if (InferLabelFromPrevious(element, label, label_source))
return true;
// If we didn't find a label, check for placeholder text.
std::u16string inferred_label = InferLabelFromPlaceholder(element);
- if (IsLabelValid(inferred_label, stop_words)) {
+ if (IsLabelValid(inferred_label)) {
*label_source = FormFieldData::LabelSource::kPlaceHolder;
*label = std::move(inferred_label);
return true;
@@ -799,7 +806,7 @@ bool InferLabelForElement(const WebFormControlElement& element,
// If we didn't find a placeholder, check for aria-label text.
inferred_label = InferLabelFromAriaLabel(element);
- if (IsLabelValid(inferred_label, stop_words)) {
+ if (IsLabelValid(inferred_label)) {
*label_source = FormFieldData::LabelSource::kAriaLabel;
*label = std::move(inferred_label);
return true;
@@ -825,7 +832,7 @@ bool InferLabelForElement(const WebFormControlElement& element,
} else if (tag_name == "TD") {
ancestor_label_source = FormFieldData::LabelSource::kTdTag;
inferred_label = InferLabelFromTableColumn(element);
- if (!IsLabelValid(inferred_label, stop_words))
+ if (!IsLabelValid(inferred_label))
inferred_label = InferLabelFromTableRow(element);
} else if (tag_name == "DD") {
ancestor_label_source = FormFieldData::LabelSource::kDdTag;
@@ -837,7 +844,7 @@ bool InferLabelForElement(const WebFormControlElement& element,
break;
}
- if (IsLabelValid(inferred_label, stop_words)) {
+ if (IsLabelValid(inferred_label)) {
*label_source = ancestor_label_source;
*label = std::move(inferred_label);
return true;
@@ -846,7 +853,7 @@ bool InferLabelForElement(const WebFormControlElement& element,
// If we didn't find a label, check the value attr used as the placeholder.
inferred_label = InferLabelFromValueAttr(element);
- if (IsLabelValid(inferred_label, stop_words)) {
+ if (IsLabelValid(inferred_label)) {
*label_source = FormFieldData::LabelSource::kValue;
*label = std::move(inferred_label);
return true;
@@ -933,7 +940,7 @@ ButtonTitleList InferButtonTitlesForForm(const WebElement& root_element) {
}
if (only_formless_elements &&
IsElementInsideFormOrFieldSet(item,
- false /* consider_fieldset_tags */)) {
+ /*consider_fieldset_tags=*/false)) {
continue;
}
bool is_submit_type = type_attribute.IsNull() || type_attribute == *kSubmit;
@@ -946,13 +953,13 @@ ButtonTitleList InferButtonTitlesForForm(const WebElement& root_element) {
}
FindElementsWithButtonFeatures(
root_element.GetElementsByHTMLTagName(*kA), only_formless_elements,
- ButtonTitleType::HYPERLINK, true /* extract_value_attribute */, &result);
+ ButtonTitleType::HYPERLINK, /*extract_value_attribute=*/true, &result);
FindElementsWithButtonFeatures(root_element.GetElementsByHTMLTagName(*kDiv),
only_formless_elements, ButtonTitleType::DIV,
- false /* extract_value_attribute */, &result);
+ /*extract_value_attribute=*/false, &result);
FindElementsWithButtonFeatures(root_element.GetElementsByHTMLTagName(*kSpan),
only_formless_elements, ButtonTitleType::SPAN,
- false /* extract_value_attribute */, &result);
+ /*extract_value_attribute=*/false, &result);
RemoveDuplicatesAndLimitTotalLength(&result);
return result;
}
@@ -985,40 +992,62 @@ void GetOptionStringsFromElement(const WebSelectElement& select_element,
}
}
+// Use insertion sort to sort the almost sorted |elements|.
+void SortByFieldRendererIds(std::vector<WebFormControlElement>& elements) {
+ for (auto it = elements.begin(); it != elements.end(); it++) {
+ // insertion_point will point to the first element that is greater than
+ // to_be_inserted.
+ const auto& to_be_inserted = *it;
+ const auto insertion_point = base::ranges::upper_bound(
+ elements.begin(), it, to_be_inserted.UniqueRendererFormControlId(),
+ base::ranges::less{},
+ &WebFormControlElement::UniqueRendererFormControlId);
+
+ // Shift all elements from [insertion_point, it) right and move |it| to the
+ // front.
+ std::rotate(insertion_point, it, it + 1);
+ }
+}
+
+std::vector<WebFormControlElement>::iterator SearchInSortedVector(
+ const FormFieldData& field,
+ std::vector<WebFormControlElement>& sorted_elements) {
+ auto get_field_renderer_id = [](const WebFormControlElement& e) {
+ return FieldRendererId(e.UniqueRendererFormControlId());
+ };
+ // Find the first element whose unique renderer ID is greater or equal to
+ // |fields|.
+ auto it = base::ranges::lower_bound(
+ sorted_elements.begin(), sorted_elements.end(), field.unique_renderer_id,
+ base::ranges::less{}, get_field_renderer_id);
+ if (it == sorted_elements.end() ||
+ FieldRendererId(it->UniqueRendererFormControlId()) !=
+ field.unique_renderer_id) {
+ return sorted_elements.end();
+ }
+ return it;
+}
+
// The callback type used by |ForEachMatchingFormField()|.
typedef void (*Callback)(const FormFieldData&,
bool, /* is_initiating_element */
blink::WebFormControlElement*);
+// Note that the order of elements in |control_elements| may be changed by this
+// function. Also the returned WebFormControlElements won't appear in DOM
+// traversal order.
std::vector<WebFormControlElement> ForEachMatchingFormFieldCommon(
- std::vector<WebFormControlElement>* control_elements,
+ std::vector<WebFormControlElement>& control_elements,
const WebElement& initiating_element,
const FormData& data,
FieldFilterMask filters,
bool force_override,
bool is_preview,
const Callback& callback) {
- DCHECK(control_elements);
-
- std::vector<WebFormControlElement> matching_fields;
- matching_fields.reserve(control_elements->size());
-
const bool num_elements_matches_num_fields =
- control_elements->size() == data.fields.size();
+ control_elements.size() == data.fields.size();
UMA_HISTOGRAM_BOOLEAN("Autofill.NumElementsMatchesNumFields",
num_elements_matches_num_fields);
- if (!num_elements_matches_num_fields) {
- // http://crbug.com/841784
- // This pathological case was only thought to be reachable iff the fields
- // are added/removed from the form while the user is interacting with the
- // autofill popup.
- //
- // Is is also reachable for formless non-checkout forms when checkout
- // restrictions are applied.
- //
- // TODO(crbug/847221): Add a UKM to capture these events.
- return matching_fields;
- }
// The intended behaviour is:
// * Autofill the currently focused element.
@@ -1027,51 +1056,57 @@ std::vector<WebFormControlElement> ForEachMatchingFormFieldCommon(
// * Send the focus event for the initially focused element.
WebFormControlElement* initially_focused_element = nullptr;
- // This container stores the indexes of non-focused elements to be autofilled.
- std::vector<size_t> autofillable_elements_index;
+ // This container stores the pairs of autofillable WebFormControlElement* and
+ // the corresponding indexes of |data.fields| that are used to fill this
+ // element.
+ std::vector<std::pair<WebFormControlElement*, size_t>>
+ autofillable_elements_index_pairs;
- // It's possible that the site has injected fields into the form after the
- // page has loaded, so we can't assert that the size of the cached control
- // elements is equal to the size of the fields in |form|. Fortunately, the
- // one case in the wild where this happens, paypal.com signup form, the fields
- // are appended to the end of the form and are not visible.
- for (size_t i = 0; i < control_elements->size(); ++i) {
- WebFormControlElement* element = &(*control_elements)[i];
- element->SetAutofillSection(WebString::FromUTF8(data.fields[i].section));
+ std::vector<WebFormControlElement> matching_fields;
+ matching_fields.reserve(control_elements.size());
+
+ // Prepare for binary search.
+ SortByFieldRendererIds(control_elements);
+
+ for (size_t i = 0; i < data.fields.size(); ++i) {
+ if (matching_fields.size() == control_elements.size())
+ break; // All possible matches are already found.
+
+ auto it = SearchInSortedVector(data.fields[i], control_elements);
+ if (it == control_elements.end())
+ continue;
- bool is_initiating_element = (*element == initiating_element);
+ WebFormControlElement& element = *it;
+
+ element.SetAutofillSection(WebString::FromUTF8(data.fields[i].section));
// Only autofill empty fields (or those with the field's default value
// attribute) and the field that initiated the filling, i.e. the field the
// user is currently editing and interacting with.
- const WebInputElement* input_element = ToWebInputElement(element);
+ const WebInputElement* input_element = ToWebInputElement(&element);
static base::NoDestructor<WebString> kValue("value");
static base::NoDestructor<WebString> kPlaceholder("placeholder");
- if (FieldRendererId(element->UniqueRendererFormControlId()) !=
- data.fields[i].unique_renderer_id) {
- continue;
- }
-
- if (((filters & FILTER_DISABLED_ELEMENTS) && !element->IsEnabled()) ||
- ((filters & FILTER_READONLY_ELEMENTS) && element->IsReadOnly()) ||
+ if (((filters & FILTER_DISABLED_ELEMENTS) && !element.IsEnabled()) ||
+ ((filters & FILTER_READONLY_ELEMENTS) && element.IsReadOnly()) ||
// See description for FILTER_NON_FOCUSABLE_ELEMENTS.
- ((filters & FILTER_NON_FOCUSABLE_ELEMENTS) && !element->IsFocusable() &&
- !IsSelectElement(*element))) {
+ ((filters & FILTER_NON_FOCUSABLE_ELEMENTS) && !element.IsFocusable() &&
+ !IsSelectElement(element))) {
continue;
}
// Autofill the initiating element.
+ bool is_initiating_element = (element == initiating_element);
if (is_initiating_element) {
- if (!is_preview && element->Focused())
- initially_focused_element = element;
+ if (!is_preview && element.Focused())
+ initially_focused_element = &element;
- matching_fields.push_back(*element);
- callback(data.fields[i], is_initiating_element, element);
+ matching_fields.push_back(element);
+ callback(data.fields[i], is_initiating_element, &element);
continue;
}
- if (element->GetAutofillState() == WebAutofillState::kAutofilled)
+ if (element.GetAutofillState() == WebAutofillState::kAutofilled)
continue;
if (!force_override &&
@@ -1084,32 +1119,32 @@ std::vector<WebFormControlElement> ForEachMatchingFormFieldCommon(
// field is not skipped. Nevertheless the below condition does not hold
// for sites set the |kValue| attribute to the user-input value.
(IsAutofillableInputElement(input_element) ||
- IsTextAreaElement(*element)) &&
- element->UserHasEditedTheField() &&
- !SanitizedFieldIsEmpty(element->Value().Utf16()) &&
- (!element->HasAttribute(*kValue) ||
- element->GetAttribute(*kValue) != element->Value()) &&
- (!element->HasAttribute(*kPlaceholder) ||
- base::i18n::ToLower(element->GetAttribute(*kPlaceholder).Utf16()) !=
- base::i18n::ToLower(element->Value().Utf16()))) {
+ IsTextAreaElement(element)) &&
+ element.UserHasEditedTheField() &&
+ !SanitizedFieldIsEmpty(element.Value().Utf16()) &&
+ (!element.HasAttribute(*kValue) ||
+ element.GetAttribute(*kValue) != element.Value()) &&
+ (!element.HasAttribute(*kPlaceholder) ||
+ base::i18n::ToLower(element.GetAttribute(*kPlaceholder).Utf16()) !=
+ base::i18n::ToLower(element.Value().Utf16()))) {
continue;
}
// Check if we should autofill/preview/clear a select element or leave it.
- if (!force_override && IsSelectElement(*element) &&
- element->UserHasEditedTheField() &&
- !SanitizedFieldIsEmpty(element->Value().Utf16())) {
+ if (!force_override && IsSelectElement(element) &&
+ element.UserHasEditedTheField() &&
+ !SanitizedFieldIsEmpty(element.Value().Utf16())) {
continue;
}
// Storing the indexes of non-initiating elements to be autofilled after
// triggering the blur event for the initiating element.
- autofillable_elements_index.push_back(i);
+ autofillable_elements_index_pairs.emplace_back(&element, i);
}
// If there is no other field to be autofilled, sending the blur event and
// then the focus event for the initiating element does not make sense.
- if (autofillable_elements_index.empty())
+ if (autofillable_elements_index_pairs.empty())
return matching_fields;
// A blur event is emitted for the focused element if it is the initiating
@@ -1118,9 +1153,11 @@ std::vector<WebFormControlElement> ForEachMatchingFormFieldCommon(
initially_focused_element->DispatchBlurEvent();
// Autofill the non-initiating elements.
- for (const auto& index : autofillable_elements_index) {
- matching_fields.push_back((*control_elements)[index]);
- callback(data.fields[index], false, &(*control_elements)[index]);
+ for (const auto& pair : autofillable_elements_index_pairs) {
+ WebFormControlElement* filled_element = pair.first;
+ size_t index_in_data_fields = pair.second;
+ matching_fields.push_back(*filled_element);
+ callback(data.fields[index_in_data_fields], false, filled_element);
}
// A focus event is emitted for the initiating element after autofilling is
@@ -1143,7 +1180,7 @@ std::vector<WebFormControlElement> ForEachMatchingFormField(
const Callback& callback) {
std::vector<WebFormControlElement> control_elements =
ExtractAutofillableElementsInForm(form_element);
- return ForEachMatchingFormFieldCommon(&control_elements, initiating_element,
+ return ForEachMatchingFormFieldCommon(control_elements, initiating_element,
data, filters, force_override,
is_preview, callback);
}
@@ -1167,7 +1204,7 @@ std::vector<WebFormControlElement> ForEachMatchingUnownedFormField(
if (!IsElementInControlElementSet(initiating_element, control_elements))
return {};
- return ForEachMatchingFormFieldCommon(&control_elements, initiating_element,
+ return ForEachMatchingFormFieldCommon(control_elements, initiating_element,
data, filters, force_override,
is_preview, callback);
}
@@ -1250,59 +1287,41 @@ void PreviewFormField(const FormFieldData& data,
}
}
-// Extracts the fields from |control_elements| with |extract_mask| to
-// |form_fields|. The extracted fields are also placed in |element_map|.
-// |form_fields| and |element_map| should start out empty.
-// |fields_extracted| should have as many elements as |control_elements|,
-// initialized to false.
-// Returns true if the number of fields extracted is within
-// [1, kMaxParseableFields].
-bool ExtractFieldsFromControlElements(
- const WebVector<WebFormControlElement>& control_elements,
- const FieldDataManager* field_data_manager,
- ExtractMask extract_mask,
- std::vector<std::unique_ptr<FormFieldData>>* form_fields,
- std::vector<bool>* fields_extracted,
- std::map<WebFormControlElement, FormFieldData*>* element_map) {
- DCHECK(form_fields->empty());
- DCHECK(element_map->empty());
- DCHECK_EQ(control_elements.size(), fields_extracted->size());
-
- for (size_t i = 0; i < control_elements.size(); ++i) {
- const WebFormControlElement& control_element = control_elements[i];
-
- if (!IsAutofillableElement(control_element))
- continue;
-
- // Create a new FormFieldData, fill it out and map it to the field's name.
- auto form_field = std::make_unique<FormFieldData>();
- WebFormControlElementToFormField(control_element, field_data_manager,
- extract_mask, form_field.get());
- (*element_map)[control_element] = form_field.get();
- form_fields->push_back(std::move(form_field));
- (*fields_extracted)[i] = true;
-
- // To avoid overly expensive computation, we impose a maximum number of
- // allowable fields.
- if (form_fields->size() > kMaxParseableFields)
- return false;
+// A less-than comparator for FormFieldDatas pointer by their FieldRendererId.
+// It also supports direct comparison of a FieldRendererId with a FormFieldData
+// pointer.
+struct CompareByRendererId {
+ using is_transparent = void;
+ constexpr bool operator()(const FormFieldData* f,
+ const FormFieldData* g) const {
+ DCHECK(f && g);
+ return f->unique_renderer_id < g->unique_renderer_id;
}
+ constexpr bool operator()(const FieldRendererId f,
+ const FormFieldData* g) const {
+ DCHECK(g);
+ return f < g->unique_renderer_id;
+ }
+ constexpr bool operator()(const FormFieldData* f, FieldRendererId g) const {
+ DCHECK(f);
+ return f->unique_renderer_id < g;
+ }
+};
- // Succeeded if fields were extracted.
- return !form_fields->empty();
-}
-
-// For each label element, get the corresponding form control element, use the
-// form control element's name as a key into the
-// <WebFormControlElement, FormFieldData> map to find the previously created
-// FormFieldData and set the FormFieldData's label to the
-// label.firstChild().nodeValue() of the label element.
+// Updates the FormFieldData::label of each field in `field_set` according to
+// the <label> descendant of |form_or_fieldset|, if there is any. The extracted
+// label is label.firstChild().nodeValue() of the label element.
void MatchLabelsAndFields(
- const WebElementCollection& labels,
- std::map<WebFormControlElement, FormFieldData*>* element_map) {
+ const WebElement& form_or_fieldset,
+ const base::flat_set<FormFieldData*, CompareByRendererId>& field_set) {
+ static base::NoDestructor<WebString> kLabel("label");
static base::NoDestructor<WebString> kFor("for");
static base::NoDestructor<WebString> kHidden("hidden");
+ WebElementCollection labels =
+ form_or_fieldset.GetElementsByHTMLTagName(*kLabel);
+ DCHECK(!labels.IsNull());
+
for (WebElement item = labels.FirstItem(); !item.IsNull();
item = labels.NextItem()) {
WebLabelElement label = item.To<WebLabelElement>();
@@ -1315,27 +1334,28 @@ void MatchLabelsAndFields(
std::u16string element_name = label.GetAttribute(*kFor).Utf16();
if (element_name.empty())
continue;
- // Look through the list for elements with this name. There can actually
+ // Look through the field set with this name. There can actually
// be more than one. In this case, the label may not be particularly
// useful, so just discard it.
- for (const auto& iter : *element_map) {
- if (iter.second->name == element_name) {
+ for (FormFieldData* field : field_set) {
+ if (field->name == element_name) {
if (field_data) {
field_data = nullptr;
break;
}
- field_data = iter.second;
+ field_data = field;
}
}
} else if (control.IsFormControlElement()) {
WebFormControlElement form_control = control.To<WebFormControlElement>();
if (form_control.FormControlTypeForAutofill() == *kHidden)
continue;
- // Typical case: look up |field_data| in |element_map|.
- auto iter = element_map->find(form_control);
- if (iter == element_map->end())
+ // Typical case: look up |field_data| in |field_set|.
+ auto iter = field_set.find(
+ FieldRendererId(form_control.UniqueRendererFormControlId()));
+ if (iter == field_set.end())
continue;
- field_data = iter->second;
+ field_data = *iter;
}
if (!field_data)
@@ -1367,82 +1387,75 @@ bool FormOrFieldsetsToFormData(
ExtractMask extract_mask,
FormData* form,
FormFieldData* field) {
- static base::NoDestructor<WebString> kLabel("label");
-
DCHECK(!form_element || fieldsets.empty());
DCHECK(!field || form_control_element);
+ DCHECK(form->fields.empty());
- // A map from a FormFieldData's name to the FormFieldData itself.
- std::map<WebFormControlElement, FormFieldData*> element_map;
-
- // The extracted FormFields. We use pointers so we can store them in
- // |element_map|.
- std::vector<std::unique_ptr<FormFieldData>> form_fields;
+ form->fields.reserve(control_elements.size());
// A vector of bools that indicate whether each field in the form meets the
// requirements and thus will be in the resulting |form|.
std::vector<bool> fields_extracted(control_elements.size(), false);
- if (!ExtractFieldsFromControlElements(control_elements, field_data_manager,
- extract_mask, &form_fields,
- &fields_extracted, &element_map)) {
- return false;
- }
+ // Extracts the fields from |control_elements| with |extract_mask| to
+ // |form_fields|. |fields_extracted| should have as many elements as
+ // |control_elements|, initialized to false. Returns true if the number of
+ // fields extracted is within [1, kMaxParseableFields].
+ for (size_t i = 0; i < control_elements.size(); ++i) {
+ const WebFormControlElement& control_element = control_elements[i];
- if (form_element) {
- // Loop through the label elements inside the form element. For each label
- // element, get the corresponding form control element, use the form control
- // element's name as a key into the <name, FormFieldData> map to find the
- // previously created FormFieldData and set the FormFieldData's label to the
- // label.firstChild().nodeValue() of the label element.
- WebElementCollection labels =
- form_element->GetElementsByHTMLTagName(*kLabel);
- DCHECK(!labels.IsNull());
- MatchLabelsAndFields(labels, &element_map);
- } else {
- // Same as the if block, but for all the labels in fieldsets.
- for (size_t i = 0; i < fieldsets.size(); ++i) {
- WebElementCollection labels =
- fieldsets[i].GetElementsByHTMLTagName(*kLabel);
- DCHECK(!labels.IsNull());
- MatchLabelsAndFields(labels, &element_map);
+ if (!IsAutofillableElement(control_element))
+ continue;
+
+ form->fields.push_back(FormFieldData());
+ WebFormControlElementToFormField(control_element, field_data_manager,
+ extract_mask, &form->fields.back());
+ fields_extracted[i] = true;
+
+ // To reduce computational costs, we impose a maximum number of allowable
+ // fields.
+ if (form->fields.size() > kMaxParseableFields) {
+ form->fields.clear();
+ return false;
}
}
- // List of characters a label can't be entirely made of (this list can grow).
- // Since the term |stop_words| is a known text processing concept we use here
- // it to refer to such characters. They are not to be confused with words.
- std::vector<char16_t> stop_words;
- stop_words.push_back(u' ');
- stop_words.push_back(u'*');
- stop_words.push_back(u':');
- stop_words.push_back(u'-');
- stop_words.push_back(u'–'); // U+2013
- stop_words.push_back(u'(');
- stop_words.push_back(u')');
+ {
+ std::vector<FormFieldData*> items;
+ for (FormFieldData& field : form->fields)
+ items.push_back(&field);
+ base::flat_set<FormFieldData*, CompareByRendererId> field_set(
+ std::move(items));
+
+ if (form_element) {
+ MatchLabelsAndFields(*form_element, field_set);
+ } else {
+ for (const WebElement& fieldset : fieldsets)
+ MatchLabelsAndFields(fieldset, field_set);
+ }
+ }
// Loop through the form control elements, extracting the label text from
// the DOM. We use the |fields_extracted| vector to make sure we assign the
// extracted label to the correct field, as it's possible |form_fields| will
// not contain all of the elements in |control_elements|.
bool found_field = false;
- for (size_t i = 0, field_idx = 0;
- i < control_elements.size() && field_idx < form_fields.size(); ++i) {
+ DCHECK(form->fields.size() <= control_elements.size());
+ for (size_t i = 0, field_idx = 0; i < control_elements.size(); ++i) {
// This field didn't meet the requirements, so don't try to find a label
// for it.
if (!fields_extracted[i])
continue;
const WebFormControlElement& control_element = control_elements[i];
- if (form_fields[field_idx]->label.empty()) {
- InferLabelForElement(control_element, stop_words,
- &(form_fields[field_idx]->label),
- &(form_fields[field_idx]->label_source));
+ if (form->fields[field_idx].label.empty()) {
+ InferLabelForElement(control_element, &form->fields[field_idx].label,
+ &form->fields[field_idx].label_source);
}
- TruncateString(&form_fields[field_idx]->label, kMaxDataLength);
+ TruncateString(&form->fields[field_idx].label, kMaxDataLength);
if (field && *form_control_element == control_element) {
- *field = *form_fields[field_idx];
+ *field = form->fields[field_idx];
found_field = true;
}
@@ -1452,13 +1465,16 @@ bool FormOrFieldsetsToFormData(
// The form_control_element was not found in control_elements. This can
// happen if elements are dynamically removed from the form while it is
// being processed. See http://crbug.com/849870
- if (field && !found_field)
+ if (field && !found_field) {
+ form->fields.clear();
return false;
+ }
- // Copy the created FormFields into the resulting FormData object.
- for (const auto& field : form_fields)
- form->fields.push_back(*field);
- return true;
+ const bool success =
+ !form->fields.empty() && form->fields.size() < kMaxParseableFields;
+ if (!success)
+ form->fields.clear();
+ return success;
}
// Check if a script modified username is suitable for Password Manager to
@@ -1512,6 +1528,16 @@ GURL StripAuthAndParams(const GURL& gurl) {
return gurl.ReplaceComponents(rep);
}
+// Build a map from entries in |form_control_renderer_ids| to their indices,
+// for more efficient lookup.
+base::flat_map<FieldRendererId, size_t> BuildRendererIdToIndex(
+ const std::vector<FieldRendererId>& form_control_renderer_ids) {
+ std::vector<std::pair<FieldRendererId, size_t>> items;
+ for (size_t i = 0; i < form_control_renderer_ids.size(); i++)
+ items.emplace_back(form_control_renderer_ids[i], i);
+ return base::flat_map<FieldRendererId, size_t>(std::move(items));
+}
+
} // namespace
void GetDataListSuggestions(const WebInputElement& element,
@@ -1729,8 +1755,10 @@ void WebFormControlElementToFormField(
field->name = element.NameForAutofill().Utf16();
field->id_attribute = element.GetIdAttribute().Utf16();
field->name_attribute = element.GetAttribute(*kName).Utf16();
- field->host_frame = LocalFrameToken(
- element.GetDocument().GetFrame()->GetLocalFrameToken().value());
+ if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer)) {
+ field->host_frame = LocalFrameToken(
+ element.GetDocument().GetFrame()->GetLocalFrameToken().value());
+ }
field->unique_renderer_id =
FieldRendererId(element.UniqueRendererFormControlId());
field->form_control_ax_id = element.GetAxId();
@@ -1867,15 +1895,20 @@ bool WebFormElementToFormData(
return false;
form->name = GetFormIdentifier(form_element);
- form->host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
+ if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer))
+ form->host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
form->unique_renderer_id =
FormRendererId(form_element.UniqueRendererFormId());
- form->url = GetCanonicalOriginForDocument(frame->GetDocument());
+ if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer))
+ form->url = GetCanonicalOriginForDocument(frame->GetDocument());
form->action = GetCanonicalActionForForm(form_element);
form->is_action_empty =
form_element.Action().IsNull() || form_element.Action().IsEmpty();
if (frame->Top()) {
- form->main_frame_origin = frame->Top()->GetSecurityOrigin();
+ if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer))
+ form->main_frame_origin = frame->Top()->GetSecurityOrigin();
+ else
+ form->main_frame_origin = url::Origin();
} else {
form->main_frame_origin = url::Origin();
NOTREACHED();
@@ -1906,7 +1939,7 @@ std::vector<WebFormControlElement> GetUnownedFormFieldElements(
if (fieldsets && element.HasHTMLTagName("fieldset") &&
!IsElementInsideFormOrFieldSet(element,
- true /* consider_fieldset_tags */)) {
+ /*consider_fieldset_tags=*/true)) {
fieldsets->push_back(element);
}
}
@@ -1933,10 +1966,13 @@ bool UnownedFormElementsAndFieldSetsToFormData(
if (!frame)
return false;
- form->host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
+ if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer))
+ form->host_frame = LocalFrameToken(frame->GetLocalFrameToken().value());
form->unique_renderer_id = FormRendererId();
- form->url = GetCanonicalOriginForDocument(document);
- if (frame->Top()) {
+ if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer))
+ form->url = GetCanonicalOriginForDocument(document);
+ if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer) &&
+ frame->Top()) {
form->main_frame_origin = frame->Top()->GetSecurityOrigin();
} else {
form->main_frame_origin = url::Origin();
@@ -2157,10 +2193,9 @@ std::u16string FindChildTextWithIgnoreListForTesting(
}
bool InferLabelForElementForTesting(const WebFormControlElement& element,
- const std::vector<char16_t>& stop_words,
std::u16string* label,
FormFieldData::LabelSource* label_source) {
- return InferLabelForElement(element, stop_words, label, label_source);
+ return InferLabelForElement(element, label, label_source);
}
WebFormElement FindFormByUniqueRendererId(WebDocument doc,
@@ -2196,20 +2231,17 @@ std::vector<WebFormControlElement> FindFormControlElementsByUniqueRendererId(
WebElementCollection elements = doc.All();
std::vector<WebFormControlElement> result(form_control_renderer_ids.size());
- // Build a map from entries in |form_control_renderer_ids| to their indices,
- // for more efficient lookup.
- std::map<FieldRendererId, size_t> renderer_id_to_index;
- for (size_t i = 0; i < form_control_renderer_ids.size(); i++)
- renderer_id_to_index[form_control_renderer_ids[i]] = i;
+ auto renderer_id_to_index_map =
+ BuildRendererIdToIndex(form_control_renderer_ids);
for (WebElement element = elements.FirstItem(); !element.IsNull();
element = elements.NextItem()) {
if (!element.IsFormControlElement())
continue;
WebFormControlElement control = element.To<WebFormControlElement>();
- auto it = renderer_id_to_index.find(
+ auto it = renderer_id_to_index_map.find(
FieldRendererId(control.UniqueRendererFormControlId()));
- if (it == renderer_id_to_index.end())
+ if (it == renderer_id_to_index_map.end())
continue;
result[it->second] = control;
}
@@ -2226,16 +2258,13 @@ std::vector<WebFormControlElement> FindFormControlElementsByUniqueRendererId(
if (form.IsNull())
return result;
- // Build a map from entries in |form_control_renderer_ids| to their indices,
- // for more efficient lookup.
- std::map<FieldRendererId, size_t> renderer_id_to_index;
- for (size_t i = 0; i < form_control_renderer_ids.size(); i++)
- renderer_id_to_index[form_control_renderer_ids[i]] = i;
+ auto renderer_id_to_index_map =
+ BuildRendererIdToIndex(form_control_renderer_ids);
for (const auto& field : form.GetFormControlElements()) {
- auto it = renderer_id_to_index.find(
+ auto it = renderer_id_to_index_map.find(
FieldRendererId(field.UniqueRendererFormControlId()));
- if (it == renderer_id_to_index.end())
+ if (it == renderer_id_to_index_map.end())
continue;
result[it->second] = field;
}
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util.h b/chromium/components/autofill/content/renderer/form_autofill_util.h
index 9a9846441d7..e85e0b74c0d 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util.h
+++ b/chromium/components/autofill/content/renderer/form_autofill_util.h
@@ -259,10 +259,10 @@ void ClearPreviewedElements(
// This kind of webpage is considered as empty:
// <html>
// <head>
-// <head/>
+// </head>
// <body>
-// <body/>
-// <html/>
+// </body>
+// </html>
// Meta, script and title tags don't influence the emptiness of a webpage.
bool IsWebpageEmpty(const blink::WebLocalFrame* frame);
@@ -301,7 +301,6 @@ std::u16string FindChildTextWithIgnoreListForTesting(
const blink::WebNode& node,
const std::set<blink::WebNode>& divs_to_skip);
bool InferLabelForElementForTesting(const blink::WebFormControlElement& element,
- const std::vector<char16_t>& stop_words,
std::u16string* label,
FormFieldData::LabelSource* label_source);
diff --git a/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
index 73849ce490c..0b613eb99c5 100644
--- a/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
+++ b/chromium/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -50,7 +50,7 @@ struct AutofillFieldLabelSourceCase {
struct AutofillFieldUtilCase {
const char* description;
const char* html;
- const char* expected_label;
+ const char16_t* expected_label;
};
const char kElevenChildren[] =
@@ -67,8 +67,8 @@ const char kElevenChildren[] =
"<div>child9</div>"
"<div>child10</div>"
"</div>";
-const char kElevenChildrenExpected[] =
- "child0child1child2child3child4child5child6child7child8";
+const char16_t kElevenChildrenExpected[] =
+ u"child0child1child2child3child4child5child6child7child8";
const char kElevenChildrenNested[] =
"<div id='target'>"
@@ -85,7 +85,8 @@ const char kElevenChildrenNested[] =
"<div>child10"
"</div></div></div></div></div></div></div></div></div></div></div></div>";
// Take 10 elements -1 for target element, -1 as text is a leaf element.
-const char kElevenChildrenNestedExpected[] = "child0child1child2child3child4";
+const char16_t kElevenChildrenNestedExpected[] =
+ u"child0child1child2child3child4";
const char kSkipElement[] =
"<div id='target'>"
@@ -94,13 +95,13 @@ const char kSkipElement[] =
"<div>child2</div>"
"</div>";
// TODO(crbug.com/796918): Should be child0child2
-const char kSkipElementExpected[] = "child0";
+const char16_t kSkipElementExpected[] = u"child0";
const char kDivTableExample1[] =
"<div>"
"<div>label</div><div><input id='target'/></div>"
"</div>";
-const char kDivTableExample1Expected[] = "label";
+const char16_t kDivTableExample1Expected[] = u"label";
const char kDivTableExample2[] =
"<div>"
@@ -108,7 +109,7 @@ const char kDivTableExample2[] =
"<div>should be skipped<input/></div>"
"<div><input id='target'/></div>"
"</div>";
-const char kDivTableExample2Expected[] = "label";
+const char16_t kDivTableExample2Expected[] = u"label";
const char kDivTableExample3[] =
"<div>"
@@ -116,7 +117,7 @@ const char kDivTableExample3[] =
"<div>label</div>"
"<div><input id='target'/></div>"
"</div>";
-const char kDivTableExample3Expected[] = "label";
+const char16_t kDivTableExample3Expected[] = u"label";
const char kDivTableExample4[] =
"<div>"
@@ -125,21 +126,21 @@ const char kDivTableExample4[] =
"<div><input id='target'/></div>"
"</div>";
// TODO(crbug.com/796918): Should be label
-const char kDivTableExample4Expected[] = "";
+const char16_t kDivTableExample4Expected[] = u"";
const char kDivTableExample5[] =
"<div>"
"<div>label<div><input id='target'/></div>behind</div>"
"</div>";
// TODO(crbug.com/796918): Should be label
-const char kDivTableExample5Expected[] = "labelbehind";
+const char16_t kDivTableExample5Expected[] = u"labelbehind";
const char kDivTableExample6[] =
"<div>"
"<div>label<div><div>-<div><input id='target'/></div></div>"
"</div>";
// TODO(crbug.com/796918): Should be "label" or "label-"
-const char kDivTableExample6Expected[] = "";
+const char16_t kDivTableExample6Expected[] = u"";
void VerifyButtonTitleCache(const WebFormElement& form_target,
const ButtonTitleList& expected_button_titles,
@@ -163,13 +164,13 @@ class FormAutofillUtilsTest : public content::RenderViewTest {
TEST_F(FormAutofillUtilsTest, FindChildTextTest) {
static const AutofillFieldUtilCase test_cases[] = {
- {"simple test", "<div id='target'>test</div>", "test"},
+ {"simple test", "<div id='target'>test</div>", u"test"},
{"Concatenate test", "<div id='target'><span>one</span>two</div>",
- "onetwo"},
+ u"onetwo"},
// TODO(crbug.com/796918): should be "onetwo"
{"Ignore input", "<div id='target'>one<input value='test'/>two</div>",
- "one"},
- {"Trim", "<div id='target'> one<span>two </span></div>", "onetwo"},
+ u"one"},
+ {"Trim", "<div id='target'> one<span>two </span></div>", u"onetwo"},
{"eleven children", kElevenChildren, kElevenChildrenExpected},
// TODO(crbug.com/796918): Depth is only 5 elements
{"eleven children nested", kElevenChildrenNested,
@@ -182,8 +183,7 @@ TEST_F(FormAutofillUtilsTest, FindChildTextTest) {
ASSERT_NE(nullptr, web_frame);
WebElement target = web_frame->GetDocument().GetElementById("target");
ASSERT_FALSE(target.IsNull());
- EXPECT_EQ(base::UTF8ToUTF16(test_case.expected_label),
- FindChildText(target));
+ EXPECT_EQ(test_case.expected_label, FindChildText(target));
}
}
@@ -205,14 +205,12 @@ TEST_F(FormAutofillUtilsTest, FindChildTextSkipElementTest) {
to_skip.insert(web_to_skip[i]);
}
- EXPECT_EQ(base::UTF8ToUTF16(test_case.expected_label),
+ EXPECT_EQ(test_case.expected_label,
FindChildTextWithIgnoreListForTesting(target, to_skip));
}
}
TEST_F(FormAutofillUtilsTest, InferLabelForElementTest) {
- std::vector<char16_t> stop_words;
- stop_words.push_back(u'-');
static const AutofillFieldUtilCase test_cases[] = {
{"DIV table test 1", kDivTableExample1, kDivTableExample1Expected},
{"DIV table test 2", kDivTableExample2, kDivTableExample2Expected},
@@ -235,14 +233,13 @@ TEST_F(FormAutofillUtilsTest, InferLabelForElementTest) {
FormFieldData::LabelSource label_source =
FormFieldData::LabelSource::kUnknown;
std::u16string label;
- InferLabelForElementForTesting(form_target, stop_words, &label,
- &label_source);
- EXPECT_EQ(base::UTF8ToUTF16(test_case.expected_label), label);
+ InferLabelForElementForTesting(form_target, &label, &label_source);
+ EXPECT_EQ(test_case.expected_label, label);
}
}
TEST_F(FormAutofillUtilsTest, InferLabelSourceTest) {
- const char kLabelSourceExpectedLabel[] = "label";
+ const char16_t kLabelSourceExpectedLabel[] = u"label";
static const AutofillFieldLabelSourceCase test_cases[] = {
{"<div><div>label</div><div><input id='target'/></div></div>",
FormFieldData::LabelSource::kDivTable},
@@ -265,8 +262,6 @@ TEST_F(FormAutofillUtilsTest, InferLabelSourceTest) {
{"<dl><dt>label</dt><dd><input id='target'></dd></dl>",
FormFieldData::LabelSource::kDdTag},
};
- std::vector<char16_t> stop_words;
- stop_words.push_back(u'-');
for (auto test_case : test_cases) {
SCOPED_TRACE(testing::Message() << test_case.label_source);
@@ -283,8 +278,8 @@ TEST_F(FormAutofillUtilsTest, InferLabelSourceTest) {
FormFieldData::LabelSource::kUnknown;
std::u16string label;
EXPECT_TRUE(autofill::form_util::InferLabelForElementForTesting(
- form_target, stop_words, &label, &label_source));
- EXPECT_EQ(base::UTF8ToUTF16(kLabelSourceExpectedLabel), label);
+ form_target, &label, &label_source));
+ EXPECT_EQ(kLabelSourceExpectedLabel, label);
EXPECT_EQ(test_case.label_source, label_source);
}
}
@@ -446,19 +441,18 @@ TEST_F(FormAutofillUtilsTest, IsEnabled) {
dummy_fieldsets, control_elements, nullptr, web_frame->GetDocument(),
nullptr, EXTRACT_NONE, &target, nullptr));
const struct {
- const char* const name;
+ const char16_t* const name;
bool enabled;
} kExpectedFields[] = {
- {"name1", true},
- {"name2", false},
- {"name3", true},
- {"name4", false},
+ {u"name1", true},
+ {u"name2", false},
+ {u"name3", true},
+ {u"name4", false},
};
const size_t number_of_cases = base::size(kExpectedFields);
ASSERT_EQ(number_of_cases, target.fields.size());
for (size_t i = 0; i < number_of_cases; ++i) {
- EXPECT_EQ(base::UTF8ToUTF16(kExpectedFields[i].name),
- target.fields[i].name);
+ EXPECT_EQ(kExpectedFields[i].name, target.fields[i].name);
EXPECT_EQ(kExpectedFields[i].enabled, target.fields[i].is_enabled);
}
}
@@ -487,19 +481,18 @@ TEST_F(FormAutofillUtilsTest, IsReadonly) {
dummy_fieldsets, control_elements, nullptr, web_frame->GetDocument(),
nullptr, EXTRACT_NONE, &target, nullptr));
const struct {
- const char* const name;
+ const char16_t* const name;
bool readonly;
} kExpectedFields[] = {
- {"name1", false},
- {"name2", true},
- {"name3", false},
- {"name4", true},
+ {u"name1", false},
+ {u"name2", true},
+ {u"name3", false},
+ {u"name4", true},
};
const size_t number_of_cases = base::size(kExpectedFields);
ASSERT_EQ(number_of_cases, target.fields.size());
for (size_t i = 0; i < number_of_cases; ++i) {
- EXPECT_EQ(base::UTF8ToUTF16(kExpectedFields[i].name),
- target.fields[i].name);
+ EXPECT_EQ(kExpectedFields[i].name, target.fields[i].name);
EXPECT_EQ(kExpectedFields[i].readonly, target.fields[i].is_readonly);
}
}
diff --git a/chromium/components/autofill/content/renderer/form_cache.cc b/chromium/components/autofill/content/renderer/form_cache.cc
index d37ee4d8b36..4e50f9d735e 100644
--- a/chromium/components/autofill/content/renderer/form_cache.cc
+++ b/chromium/components/autofill/content/renderer/form_cache.cc
@@ -19,7 +19,6 @@
#include "base/strings/string_piece.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 "components/autofill/content/renderer/form_autofill_util.h"
#include "components/autofill/content/renderer/page_form_analyser_logger.h"
@@ -228,6 +227,7 @@ void FormCache::Reset() {
parsed_forms_.clear();
initial_select_values_.clear();
initial_checked_state_.clear();
+ fields_eligible_for_manual_filling_.clear();
}
void FormCache::ClearElement(WebFormControlElement& control_element,
@@ -423,6 +423,19 @@ bool FormCache::ShowPredictions(const FormDataPredictions& form,
return true;
}
+bool FormCache::IsFormElementEligibleForManualFilling(
+ const blink::WebFormControlElement& control_element) {
+ return fields_eligible_for_manual_filling_.find(
+ FieldRendererId(control_element.UniqueRendererFormControlId())) !=
+ fields_eligible_for_manual_filling_.end();
+}
+
+void FormCache::SetFieldsEligibleForManualFilling(
+ const std::vector<FieldRendererId>& fields_eligible_for_manual_filling) {
+ fields_eligible_for_manual_filling_ = base::flat_set<FieldRendererId>(
+ std::move(fields_eligible_for_manual_filling));
+}
+
size_t FormCache::ScanFormControlElements(
const std::vector<WebFormControlElement>& control_elements,
bool log_deprecation_messages) {
diff --git a/chromium/components/autofill/content/renderer/form_cache.h b/chromium/components/autofill/content/renderer/form_cache.h
index c2458830d07..d3fd4d21f80 100644
--- a/chromium/components/autofill/content/renderer/form_cache.h
+++ b/chromium/components/autofill/content/renderer/form_cache.h
@@ -16,6 +16,7 @@
#include "base/macros.h"
#include "components/autofill/core/common/field_data_manager.h"
#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/form_data_predictions.h"
#include "components/autofill/core/common/unique_ids.h"
namespace blink {
@@ -55,6 +56,16 @@ class FormCache {
bool ShowPredictions(const FormDataPredictions& form,
bool attach_predictions_to_dom);
+ // For a given |control_element| check whether it is eligible for manual
+ // filling on form interaction.
+ bool IsFormElementEligibleForManualFilling(
+ const blink::WebFormControlElement& control_element);
+
+ // Stores the FieldRendererId of the fields that are eligible for manual
+ // filling in a set.
+ void SetFieldsEligibleForManualFilling(
+ const std::vector<FieldRendererId>& fields_eligible_for_manual_filling);
+
private:
FRIEND_TEST_ALL_PREFIXES(FormCacheTest,
ShouldShowAutocompleteConsoleWarnings_Enabled);
@@ -108,6 +119,9 @@ class FormCache {
// keyed by the unique_renderer_form_control_id of the WebInputElements.
std::map<FieldRendererId, bool> initial_checked_state_;
+ // Fields that are eligible to show manual filling on form interaction.
+ base::flat_set<FieldRendererId> fields_eligible_for_manual_filling_;
+
DISALLOW_COPY_AND_ASSIGN(FormCache);
};
diff --git a/chromium/components/autofill/content/renderer/form_cache_browsertest.cc b/chromium/components/autofill/content/renderer/form_cache_browsertest.cc
index 7ed7e510c8e..1e21a2254d0 100644
--- a/chromium/components/autofill/content/renderer/form_cache_browsertest.cc
+++ b/chromium/components/autofill/content/renderer/form_cache_browsertest.cc
@@ -327,4 +327,41 @@ TEST_F(FormCacheBrowserTest, ClearFormSelectElementEditedStateReset) {
EXPECT_TRUE(select_month.UserHasEditedTheField());
}
+TEST_F(FormCacheBrowserTest, IsFormElementEligibleForManualFilling) {
+ // Load a form.
+ LoadHTML(
+ "<html><form id='myForm'>"
+ "<label>First Name:</label><input id='fname' name='0'/><br/>"
+ "<label>Middle Name:</label> <input id='mname' name='1'/><br/>"
+ "<label>Last Name:</label> <input id='lname' name='2'/><br/>"
+ "</form></html>");
+
+ WebDocument doc = GetMainFrame()->GetDocument();
+ auto first_name_element = doc.GetElementById("fname").To<WebInputElement>();
+ auto middle_name_element = doc.GetElementById("mname").To<WebInputElement>();
+ auto last_name_element = doc.GetElementById("lname").To<WebInputElement>();
+
+ FormCache form_cache(GetMainFrame());
+ std::vector<FormData> forms =
+ form_cache.ExtractNewForms(/*field_data_manager=*/nullptr);
+ const FormData* form_data = GetFormByName(forms, "myForm");
+ EXPECT_EQ(3u, form_data->fields.size());
+
+ // Set the first_name and last_name fields as eligible for manual filling.
+ std::vector<FieldRendererId> fields_eligible_for_manual_filling;
+ fields_eligible_for_manual_filling.push_back(
+ form_data->fields[0].unique_renderer_id);
+ fields_eligible_for_manual_filling.push_back(
+ form_data->fields[2].unique_renderer_id);
+ form_cache.SetFieldsEligibleForManualFilling(
+ fields_eligible_for_manual_filling);
+
+ EXPECT_TRUE(
+ form_cache.IsFormElementEligibleForManualFilling(first_name_element));
+ EXPECT_FALSE(
+ form_cache.IsFormElementEligibleForManualFilling(middle_name_element));
+ EXPECT_TRUE(
+ form_cache.IsFormElementEligibleForManualFilling(last_name_element));
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/content/renderer/form_tracker.cc b/chromium/components/autofill/content/renderer/form_tracker.cc
index 0afae7d2a75..482da9b0689 100644
--- a/chromium/components/autofill/content/renderer/form_tracker.cc
+++ b/chromium/components/autofill/content/renderer/form_tracker.cc
@@ -155,7 +155,7 @@ void FormTracker::DidFinishSameDocumentNavigation() {
void FormTracker::DidStartNavigation(
const GURL& url,
- base::Optional<blink::WebNavigationType> navigation_type) {
+ absl::optional<blink::WebNavigationType> navigation_type) {
DCHECK_CALLED_ON_VALID_SEQUENCE(form_tracker_sequence_checker_);
blink::WebLocalFrame* navigated_frame = render_frame()->GetWebFrame();
// Ony handle main frame.
diff --git a/chromium/components/autofill/content/renderer/form_tracker.h b/chromium/components/autofill/content/renderer/form_tracker.h
index ea0e7ca31aa..38e5eb7a6d4 100644
--- a/chromium/components/autofill/content/renderer/form_tracker.h
+++ b/chromium/components/autofill/content/renderer/form_tracker.h
@@ -97,7 +97,7 @@ class FormTracker : public content::RenderFrameObserver {
void DidFinishSameDocumentNavigation() override;
void DidStartNavigation(
const GURL& url,
- base::Optional<blink::WebNavigationType> navigation_type) override;
+ absl::optional<blink::WebNavigationType> navigation_type) override;
void WillDetach() override;
void WillSendSubmitEvent(const blink::WebFormElement& form) override;
void WillSubmitForm(const blink::WebFormElement& form) override;
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 06b68187fcb..ade04b6c882 100644
--- a/chromium/components/autofill/content/renderer/html_based_username_detector.cc
+++ b/chromium/components/autofill/content/renderer/html_based_username_detector.cc
@@ -30,7 +30,8 @@ namespace autofill {
namespace {
// List of separators that can appear in HTML attribute values.
-constexpr char kDelimiters[] = "$\"\'?%*@!\\/&^#:+~`;,>|<.[](){}-_ 0123456789";
+constexpr char16_t kDelimiters[] =
+ u"$\"\'?%*@!\\/&^#:+~`;,>|<.[](){}-_ 0123456789";
// Minimum length of a word, in order not to be considered short word. Short
// words will not be searched in attribute values (especially after delimiters
@@ -89,10 +90,9 @@ void AppendValueAndShortTokens(
std::u16string* field_data_value,
base::flat_set<std::u16string>* field_data_short_tokens) {
const std::u16string lowercase_value = base::i18n::ToLower(raw_value);
- const std::u16string delimiters = base::ASCIIToUTF16(kDelimiters);
std::vector<base::StringPiece16> tokens =
- base::SplitStringPiece(lowercase_value, delimiters, base::TRIM_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY);
+ base::SplitStringPiece(lowercase_value, kDelimiters,
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
// When computing the developer value, '$' safety guard is being added
// between field name and id, so that forming of accidental words is
diff --git a/chromium/components/autofill/content/renderer/password_autofill_agent.cc b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
index 4c680070c9d..b73c6620568 100644
--- a/chromium/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_autofill_agent.cc
@@ -1108,12 +1108,15 @@ void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
HasPasswordField(*frame)) {
// Set everything that |FormDigest| needs.
password_forms_data.push_back(FormData());
- password_forms_data.back().host_frame =
- autofill::LocalFrameToken(frame->GetLocalFrameToken().value());
- password_forms_data.back().url =
- form_util::GetCanonicalOriginForDocument(frame->GetDocument());
- password_forms_data.back().full_url =
- form_util::GetDocumentUrlWithoutAuth(frame->GetDocument());
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillAugmentFormsInRenderer)) {
+ password_forms_data.back().host_frame =
+ autofill::LocalFrameToken(frame->GetLocalFrameToken().value());
+ password_forms_data.back().url =
+ form_util::GetCanonicalOriginForDocument(frame->GetDocument());
+ password_forms_data.back().full_url =
+ form_util::GetDocumentUrlWithoutAuth(frame->GetDocument());
+ }
}
if (!password_forms_data.empty()) {
sent_request_to_store_ = true;
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 b4fd8f42516..d1a6353f012 100644
--- a/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/chromium/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -10,6 +10,7 @@
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "components/autofill/content/renderer/html_based_username_detector.h"
+#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/unique_ids.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/url_util.h"
@@ -132,10 +133,12 @@ std::unique_ptr<FormData> CreateFormDataFromWebForm(
return nullptr;
auto form_data = std::make_unique<FormData>();
- form_data->url =
- form_util::GetCanonicalOriginForDocument(web_form.GetDocument());
- form_data->full_url =
- form_util::GetDocumentUrlWithoutAuth(web_form.GetDocument());
+ if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer)) {
+ form_data->url =
+ form_util::GetCanonicalOriginForDocument(web_form.GetDocument());
+ form_data->full_url =
+ form_util::GetDocumentUrlWithoutAuth(web_form.GetDocument());
+ }
form_data->is_gaia_with_skip_save_password_form =
IsGaiaWithSkipSavePasswordForm(web_form) ||
IsGaiaReauthenticationForm(web_form);
@@ -178,10 +181,12 @@ std::unique_ptr<FormData> CreateFormDataFromUnownedInputElements(
return nullptr;
}
- form_data->url =
- form_util::GetCanonicalOriginForDocument(frame.GetDocument());
- form_data->full_url =
- form_util::GetDocumentUrlWithoutAuth(frame.GetDocument());
+ if (base::FeatureList::IsEnabled(features::kAutofillAugmentFormsInRenderer)) {
+ form_data->url =
+ form_util::GetCanonicalOriginForDocument(frame.GetDocument());
+ form_data->full_url =
+ form_util::GetDocumentUrlWithoutAuth(frame.GetDocument());
+ }
form_data->username_predictions = GetUsernamePredictions(
control_elements, *form_data, username_detector_cache);
form_data->button_titles = form_util::GetButtonTitles(
diff --git a/chromium/components/autofill/content/renderer/password_generation_agent.cc b/chromium/components/autofill/content/renderer/password_generation_agent.cc
index 361fb1a0cfc..c26014a2557 100644
--- a/chromium/components/autofill/content/renderer/password_generation_agent.cc
+++ b/chromium/components/autofill/content/renderer/password_generation_agent.cc
@@ -234,7 +234,7 @@ void PasswordGenerationAgent::GeneratedPasswordAccepted(
password_agent_->TrackAutofilledElement(password_element);
// Advance focus to the next input field. We assume password fields in
// an account creation form are always adjacent.
- render_frame()->GetRenderView()->GetWebView()->AdvanceFocus(false);
+ render_frame()->GetWebView()->AdvanceFocus(false);
}
std::unique_ptr<FormData> presaved_form_data(CreateFormDataToPresave());
@@ -316,7 +316,7 @@ void PasswordGenerationAgent::TriggeredGeneratePassword(
std::move(callback).Run(std::move(password_generation_ui_data));
current_generation_item_->generation_popup_shown_ = true;
} else {
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
}
}
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 ec85d0d57c2..9ea4dd6962c 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
@@ -4,7 +4,6 @@
#include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
@@ -13,6 +12,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -86,7 +86,7 @@ class FakeContentPasswordManagerDriver : public mojom::PasswordManagerDriver {
// Records whether RecordSavePasswordProgress() gets called.
bool called_record_save_;
// Records data received via RecordSavePasswordProgress() call.
- base::Optional<std::string> log_;
+ absl::optional<std::string> log_;
mojo::Receiver<mojom::PasswordManagerDriver> receiver_{this};
};
diff --git a/chromium/components/autofill/core/browser/BUILD.gn b/chromium/components/autofill/core/browser/BUILD.gn
index b947cefc2be..f47429dd1ac 100644
--- a/chromium/components/autofill/core/browser/BUILD.gn
+++ b/chromium/components/autofill/core/browser/BUILD.gn
@@ -42,6 +42,8 @@ static_library("browser") {
"address_rewriter.h",
"autocomplete_history_manager.cc",
"autocomplete_history_manager.h",
+ "autofill_ablation_study.cc",
+ "autofill_ablation_study.h",
"autofill_address_policy_handler.cc",
"autofill_address_policy_handler.h",
"autofill_address_util.cc",
@@ -65,25 +67,24 @@ static_library("browser") {
"autofill_external_delegate.h",
"autofill_field.cc",
"autofill_field.h",
- "autofill_handler.cc",
- "autofill_handler.h",
- "autofill_handler_proxy.cc",
- "autofill_handler_proxy.h",
"autofill_manager.cc",
"autofill_manager.h",
- "autofill_manager_test_delegate.h",
"autofill_metrics.cc",
"autofill_metrics.h",
"autofill_observer.cc",
"autofill_observer.h",
+ "autofill_profile_import_process.cc",
+ "autofill_profile_import_process.h",
+ "autofill_profile_save_strike_database.cc",
+ "autofill_profile_save_strike_database.h",
"autofill_profile_sync_util.cc",
"autofill_profile_sync_util.h",
+ "autofill_profile_update_strike_database.cc",
+ "autofill_profile_update_strike_database.h",
"autofill_profile_validation_util.cc",
"autofill_profile_validation_util.h",
"autofill_profile_validator.cc",
"autofill_profile_validator.h",
- "autofill_provider.cc",
- "autofill_provider.h",
"autofill_regex_constants.cc",
"autofill_regex_constants.h",
"autofill_regexes.cc",
@@ -92,6 +93,9 @@ static_library("browser") {
"autofill_subject.h",
"autofill_type.cc",
"autofill_type.h",
+ "browser_autofill_manager.cc",
+ "browser_autofill_manager.h",
+ "browser_autofill_manager_test_delegate.h",
"data_model/address.cc",
"data_model/address.h",
"data_model/autofill_data_model.cc",
@@ -122,6 +126,8 @@ static_library("browser") {
"data_model/contact_info.h",
"data_model/credit_card.cc",
"data_model/credit_card.h",
+ "data_model/credit_card_art_image.cc",
+ "data_model/credit_card_art_image.h",
"data_model/credit_card_cloud_token_data.cc",
"data_model/credit_card_cloud_token_data.h",
"data_model/data_model_utils.cc",
@@ -243,12 +249,8 @@ static_library("browser") {
"payments/payments_util.cc",
"payments/payments_util.h",
"payments/risk_data_loader.h",
- "payments/strike_database.cc",
- "payments/strike_database.h",
- "payments/strike_database_integrator_base.cc",
- "payments/strike_database_integrator_base.h",
- "payments/strike_database_integrator_test_strike_database.cc",
- "payments/strike_database_integrator_test_strike_database.h",
+ "payments/wait_for_signal_or_timeout.cc",
+ "payments/wait_for_signal_or_timeout.h",
"payments/webauthn_callback_types.h",
"personal_data_manager.cc",
"personal_data_manager.h",
@@ -259,6 +261,14 @@ static_library("browser") {
"randomized_encoder.h",
"rationalization_util.cc",
"rationalization_util.h",
+ "strike_database.cc",
+ "strike_database.h",
+ "strike_database_base.cc",
+ "strike_database_base.h",
+ "strike_database_integrator_base.cc",
+ "strike_database_integrator_base.h",
+ "strike_database_integrator_test_strike_database.cc",
+ "strike_database_integrator_test_strike_database.h",
"sync_utils.h",
"ui/accessory_sheet_data.cc",
"ui/accessory_sheet_data.h",
@@ -345,6 +355,8 @@ static_library("browser") {
if (is_ios) {
sources += [
+ "autofill_save_update_address_profile_delegate_ios.cc",
+ "autofill_save_update_address_profile_delegate_ios.h",
"keyboard_accessory_metrics_logger.h",
"keyboard_accessory_metrics_logger.mm",
]
@@ -352,8 +364,6 @@ static_library("browser") {
if (is_ios || is_android) {
sources += [
- "autofill_save_address_profile_delegate_ios.cc",
- "autofill_save_address_profile_delegate_ios.h",
"payments/autofill_credit_card_filling_infobar_delegate_mobile.cc",
"payments/autofill_credit_card_filling_infobar_delegate_mobile.h",
"payments/autofill_offer_notification_infobar_delegate_mobile.cc",
@@ -516,20 +526,21 @@ static_library("test_support") {
"test_autofill_driver.h",
"test_autofill_external_delegate.cc",
"test_autofill_external_delegate.h",
- "test_autofill_manager.cc",
- "test_autofill_manager.h",
"test_autofill_profile_validator.cc",
"test_autofill_profile_validator.h",
"test_autofill_profile_validator_delayed.cc",
"test_autofill_profile_validator_delayed.h",
- "test_autofill_provider.h",
"test_autofill_tick_clock.cc",
"test_autofill_tick_clock.h",
+ "test_browser_autofill_manager.cc",
+ "test_browser_autofill_manager.h",
"test_event_waiter.h",
"test_form_data_importer.cc",
"test_form_data_importer.h",
"test_form_structure.cc",
"test_form_structure.h",
+ "test_inmemory_strike_database.cc",
+ "test_inmemory_strike_database.h",
"test_personal_data_manager.cc",
"test_personal_data_manager.h",
"ui/suggestion_test_helpers.h",
@@ -638,23 +649,27 @@ source_set("unit_tests") {
"address_profile_save_manager_unittest.cc",
"address_rewriter_unittest.cc",
"autocomplete_history_manager_unittest.cc",
+ "autofill_ablation_study_unittest.cc",
"autofill_address_policy_handler_unittest.cc",
+ "autofill_address_util_unittest.cc",
"autofill_credit_card_policy_handler_unittest.cc",
"autofill_data_util_unittest.cc",
"autofill_download_manager_unittest.cc",
"autofill_driver_factory_unittest.cc",
"autofill_experiments_unittest.cc",
"autofill_external_delegate_unittest.cc",
- "autofill_manager_unittest.cc",
"autofill_merge_unittest.cc",
"autofill_metrics_unittest.cc",
+ "autofill_profile_import_process_unittest.cc",
+ "autofill_profile_save_strike_database_unittest.cc",
"autofill_profile_sync_util_unittest.cc",
+ "autofill_profile_update_strike_database_unittest.cc",
"autofill_profile_validation_util_unittest.cc",
"autofill_profile_validator_unittest.cc",
- "autofill_provider_unittest.cc",
"autofill_regexes_unittest.cc",
"autofill_subject_unittest.cc",
"autofill_type_unittest.cc",
+ "browser_autofill_manager_unittest.cc",
"data_model/address_unittest.cc",
"data_model/autofill_data_model_unittest.cc",
"data_model/autofill_profile_comparator_unittest.cc",
@@ -708,11 +723,14 @@ source_set("unit_tests") {
"payments/payments_client_unittest.cc",
"payments/payments_service_url_unittest.cc",
"payments/payments_util_unittest.cc",
- "payments/strike_database_integrator_test_strike_database_unittest.cc",
- "payments/strike_database_unittest.cc",
+ "payments/wait_for_signal_or_timeout_unittest.cc",
"personal_data_manager_unittest.cc",
"randomized_encoder_unittest.cc",
"rationalization_util_unittest.cc",
+ "strike_database_integrator_test_strike_database_unittest.cc",
+ "strike_database_unittest.cc",
+ "test_utils/test_profiles.cc",
+ "test_utils/test_profiles.h",
"ui/address_combobox_model_unittest.cc",
"ui/country_combobox_model_unittest.cc",
"ui/payments/card_unmask_prompt_controller_impl_unittest.cc",
@@ -734,9 +752,13 @@ source_set("unit_tests") {
sources += [ "autofill_ie_toolbar_import_win_unittest.cc" ]
}
+ if (is_ios) {
+ sources +=
+ [ "autofill_save_update_address_profile_delegate_ios_unittest.cc" ]
+ }
+
if (is_ios || is_android) {
sources += [
- "autofill_save_address_profile_delegate_ios_unittest.cc",
"ui/mobile_label_formatter_unittest.cc",
"ui/payments/card_expiration_date_fix_flow_controller_impl_unittest.cc",
"ui/payments/card_name_fix_flow_controller_impl_unittest.cc",
diff --git a/chromium/components/autofill/core/browser/DEPS b/chromium/components/autofill/core/browser/DEPS
index 69082786805..5af68a671f3 100644
--- a/chromium/components/autofill/core/browser/DEPS
+++ b/chromium/components/autofill/core/browser/DEPS
@@ -51,14 +51,14 @@ specific_include_rules = {
"+device/fido/authenticator_selection_criteria.h",
"+device/fido/fido_constants.h",
"+device/fido/fido_types.h",
- "+third_party/blink/public/mojom/webauthn/authenticator.mojom.h",
+ "+third_party/blink/public/mojom/webauthn",
],
"(test_)?internal_authenticator\.h": [
"+device/fido/fido_constants.h",
- "+third_party/blink/public/mojom/webauthn/authenticator.mojom.h",
+ "+third_party/blink/public/mojom/webauthn",
],
"autofill_driver\.h": [
- "+third_party/blink/public/mojom/webauthn/internal_authenticator.mojom.h"
+ "+third_party/blink/public/mojom/webauthn",
],
"test_autofill_driver\.h": [
"+components/autofill/content/browser/content_autofill_driver.h"
diff --git a/chromium/components/autofill/core/browser/address_profile_save_manager.cc b/chromium/components/autofill/core/browser/address_profile_save_manager.cc
index 4272c8e7eb1..bf785e31f64 100644
--- a/chromium/components/autofill/core/browser/address_profile_save_manager.cc
+++ b/chromium/components/autofill/core/browser/address_profile_save_manager.cc
@@ -4,12 +4,15 @@
#include "components/autofill/core/browser/address_profile_save_manager.h"
+#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/common/autofill_features.h"
namespace autofill {
+using UserDecision = AutofillClient::SaveAddressProfileOfferUserDecision;
+
AddressProfileSaveManager::AddressProfileSaveManager(
AutofillClient* client,
PersonalDataManager* personal_data_manager)
@@ -17,38 +20,137 @@ AddressProfileSaveManager::AddressProfileSaveManager(
AddressProfileSaveManager::~AddressProfileSaveManager() = default;
-void AddressProfileSaveManager::SaveProfile(const AutofillProfile& profile) {
+void AddressProfileSaveManager::ImportProfileFromForm(
+ const AutofillProfile& observed_profile,
+ const std::string& app_locale,
+ const GURL& url) {
+ // Without a personal data manager, profile storage is not possible.
if (!personal_data_manager_)
return;
- if (base::FeatureList::IsEnabled(
+ // If the explicit save prompts are not enabled, revert back to the legacy
+ // behavior and directly import the observed profile without recording any
+ // additional metrics.
+ if (!base::FeatureList::IsEnabled(
features::kAutofillAddressProfileSavePrompt)) {
- client_->ConfirmSaveAddressProfile(
- profile,
- base::BindOnce(&AddressProfileSaveManager::SaveProfilePromptCallback,
- weak_ptr_factory_.GetWeakPtr()));
+ personal_data_manager_->SaveImportedProfile(observed_profile);
return;
}
- SaveProfileInternal(profile);
+
+ auto process_ptr = std::make_unique<ProfileImportProcess>(
+ observed_profile, app_locale, url, personal_data_manager_);
+
+ MaybeOfferSavePrompt(std::move(process_ptr));
+}
+
+void AddressProfileSaveManager::MaybeOfferSavePrompt(
+ std::unique_ptr<ProfileImportProcess> import_process) {
+ switch (import_process->import_type()) {
+ // If the import was a duplicate, only results in silent updates or if the
+ // import of a new profile or a profile update is blocked, finish the
+ // process without initiating a user prompt
+ case AutofillProfileImportType::kDuplicateImport:
+ case AutofillProfileImportType::kSilentUpdate:
+ case AutofillProfileImportType::kSuppressedNewProfile:
+ case AutofillProfileImportType::kSuppressedConfirmableMergeAndSilentUpdate:
+ case AutofillProfileImportType::kSuppressedConfirmableMerge:
+ import_process->AcceptWithoutPrompt();
+ FinalizeProfileImport(std::move(import_process));
+ return;
+
+ // Both the import of a new profile, or a merge with an existing profile
+ // that changes a settings-visible value of an existing profile triggers a
+ // user prompt.
+ case AutofillProfileImportType::kNewProfile:
+ case AutofillProfileImportType::kConfirmableMerge:
+ case AutofillProfileImportType::kConfirmableMergeAndSilentUpdate:
+ OfferSavePrompt(std::move(import_process));
+ return;
+
+ case AutofillProfileImportType::kImportTypeUnspecified:
+ NOTREACHED();
+ return;
+ }
+}
+
+void AddressProfileSaveManager::OfferSavePrompt(
+ std::unique_ptr<ProfileImportProcess> import_process) {
+ // The prompt should not have been shown yet.
+ DCHECK(!import_process->prompt_shown());
+
+ // TODO(crbug.com/1175693): Pass the correct SaveAddressProfilePromptOptions
+ // below.
+
+ // TODO(crbug.com/1175693): Check import_process->set_prompt_was_shown() is
+ // always correct even in cases where it conflicts with
+ // SaveAddressProfilePromptOptions
+
+ // Initiate the prompt and mark it as shown.
+ // The import process that carries to state of the current import process is
+ // attached to the callback.
+ import_process->set_prompt_was_shown();
+ ProfileImportProcess* process_ptr = import_process.get();
+ client_->ConfirmSaveAddressProfile(
+ process_ptr->import_candidate().value(),
+ base::OptionalOrNullptr(process_ptr->merge_candidate()),
+ AutofillClient::SaveAddressProfilePromptOptions{.show_prompt = true},
+ base::BindOnce(&AddressProfileSaveManager::OnUserDecision,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(import_process)));
}
-void AddressProfileSaveManager::SaveProfileInternal(
- const AutofillProfile& profile) {
- personal_data_manager_->SaveImportedProfile(profile);
+void AddressProfileSaveManager::OnUserDecision(
+ std::unique_ptr<ProfileImportProcess> import_process,
+ UserDecision decision,
+ AutofillProfile edited_profile) {
+ DCHECK(import_process->prompt_shown());
+
+ import_process->SetUserDecision(decision, edited_profile);
+ FinalizeProfileImport(std::move(import_process));
}
-void AddressProfileSaveManager::SaveProfilePromptCallback(
- AutofillClient::SaveAddressProfileOfferUserDecision user_decision,
- AutofillProfile profile) {
- switch (user_decision) {
- case AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted:
- case AutofillClient::SaveAddressProfileOfferUserDecision::kEdited:
- personal_data_manager_->SaveImportedProfile(profile);
- break;
- case AutofillClient::SaveAddressProfileOfferUserDecision::kDeclined:
- case AutofillClient::SaveAddressProfileOfferUserDecision::kIgnored:
- break;
+void AddressProfileSaveManager::FinalizeProfileImport(
+ std::unique_ptr<ProfileImportProcess> import_process) {
+ DCHECK(personal_data_manager_);
+
+ // If the profiles changed at all, reset the full list of AutofillProfiles in
+ // the personal data manager.
+ if (import_process->ProfilesChanged()) {
+ std::vector<AutofillProfile> resulting_profiles =
+ import_process->GetResultingProfiles();
+ personal_data_manager_->SetProfiles(&resulting_profiles);
}
+
+ AutofillProfileImportType import_type = import_process->import_type();
+
+ // If the import of a new profile was declined, add a strike for this source
+ // url. If it was accepted, reset the potentially existing strikes.
+ if (import_type == AutofillProfileImportType::kNewProfile) {
+ if (import_process->UserDeclined()) {
+ personal_data_manager_->AddStrikeToBlockNewProfileImportForDomain(
+ import_process->form_source_url());
+ } else if (import_process->UserAccepted()) {
+ personal_data_manager_->RemoveStrikesToBlockNewProfileImportForDomain(
+ import_process->form_source_url());
+ }
+ } else if (import_type == AutofillProfileImportType::kConfirmableMerge ||
+ import_type ==
+ AutofillProfileImportType::kConfirmableMergeAndSilentUpdate) {
+ DCHECK(import_process->merge_candidate().has_value());
+ if (import_process->UserDeclined()) {
+ personal_data_manager_->AddStrikeToBlockProfileUpdate(
+ import_process->merge_candidate()->guid());
+ } else if (import_process->UserAccepted()) {
+ personal_data_manager_->RemoveStrikesToBlockProfileUpdate(
+ import_process->merge_candidate()->guid());
+ }
+ }
+
+ import_process->CollectMetrics();
+ ClearPendingImport(std::move(import_process));
}
+void AddressProfileSaveManager::ClearPendingImport(
+ std::unique_ptr<ProfileImportProcess> import_process) {}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/address_profile_save_manager.h b/chromium/components/autofill/core/browser/address_profile_save_manager.h
index 0eec8bf5ae5..55c9bb8e7a5 100644
--- a/chromium/components/autofill/core/browser/address_profile_save_manager.h
+++ b/chromium/components/autofill/core/browser/address_profile_save_manager.h
@@ -9,6 +9,7 @@
#include "base/memory/weak_ptr.h"
#include "components/autofill/core/browser/autofill_client.h"
+#include "components/autofill/core/browser/autofill_profile_import_process.h"
namespace autofill {
@@ -25,22 +26,59 @@ class AddressProfileSaveManager {
AddressProfileSaveManager(const AddressProfileSaveManager&) = delete;
AddressProfileSaveManager& operator=(const AddressProfileSaveManager&) =
delete;
+
virtual ~AddressProfileSaveManager();
- // Saves `profile` using the `personal_data_manager_`.
- void SaveProfile(const AutofillProfile& profile);
+ // This method initiates the import process that is started when an importable
+ // `profile` is observed in a form submission on `url`. Depending on the
+ // scenario, the method will have no effect if `profile` resembles an already
+ // existing profile. If the import corresponds to a new profile, or to a
+ // change of an existing profile that must be confirmed by the user, a UI
+ // prompt will be initiated. At the end of the process, metrics will be
+ // recorded.
+ void ImportProfileFromForm(const AutofillProfile& profile,
+ const std::string& app_locale,
+ const GURL& url);
+
+ protected:
+ // Initiates showing the prompt to the user.
+ // This function is virtual to be mocked in tests.
+ virtual void OfferSavePrompt(
+ std::unique_ptr<ProfileImportProcess> import_process);
+
+ // Clears the pending import. This method can be overloaded to store the
+ // history of import processes for testing purposes.
+ virtual void ClearPendingImport(
+ std::unique_ptr<ProfileImportProcess> import_process);
+
+ // Called after the user interaction with the UI is done.
+ void OnUserDecision(
+ std::unique_ptr<ProfileImportProcess> import_process,
+ AutofillClient::SaveAddressProfileOfferUserDecision decision,
+ AutofillProfile edited_profile);
+
+ PersonalDataManager* personal_data_manager() {
+ return personal_data_manager_;
+ }
private:
- void SaveProfilePromptCallback(
- AutofillClient::SaveAddressProfileOfferUserDecision user_decision,
- AutofillProfile profile);
- void SaveProfileInternal(const AutofillProfile& profile);
+ // Called to initiate the actual storing of a profile.
+ // Verifies that the profile was actually imported.
+ void FinalizeProfileImport(
+ std::unique_ptr<ProfileImportProcess> import_process);
+
+ // Called to make the final decision if the UI should be shown, or if the
+ // import process should be continued silently.
+ void MaybeOfferSavePrompt(
+ std::unique_ptr<ProfileImportProcess> import_process);
+ // A pointer to the autofill client. It is assumed that the client outlives
+ // the instance of this class
AutofillClient* const client_;
// The personal data manager, used to save and load personal data to/from the
// web database.
- PersonalDataManager* const personal_data_manager_;
+ PersonalDataManager* const personal_data_manager_{nullptr};
base::WeakPtrFactory<AddressProfileSaveManager> weak_ptr_factory_{this};
};
diff --git a/chromium/components/autofill/core/browser/address_profile_save_manager_unittest.cc b/chromium/components/autofill/core/browser/address_profile_save_manager_unittest.cc
index 19b9037b57e..899be5c7e6e 100644
--- a/chromium/components/autofill/core/browser/address_profile_save_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/address_profile_save_manager_unittest.cc
@@ -4,11 +4,16 @@
#include "components/autofill/core/browser/address_profile_save_manager.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/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/data_model/autofill_structured_address_test_utils.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/autofill/core/browser/test_utils/test_profiles.h"
+#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -16,24 +21,946 @@
namespace autofill {
namespace {
+
+using UserDecision = AutofillClient::SaveAddressProfileOfferUserDecision;
+
+using structured_address::VerificationStatus;
+
+// Names of histrogram used for metric collection.
+constexpr char kProfileImportTypeHistogram[] =
+ "Autofill.ProfileImport.ProfileImportType";
+constexpr char kNewProfileEditsHistogram[] =
+ "Autofill.ProfileImport.NewProfileEditedType";
+constexpr char kProfileUpdateEditsHistogram[] =
+ "Autofill.ProfileImport.UpdateProfileEditedType";
+constexpr char kProfileUpdateAffectedTypesHistogram[] =
+ "Autofill.ProfileImport.UpdateProfileAffectedType";
+constexpr char kNewProfileDecisionHistogram[] =
+ "Autofill.ProfileImport.NewProfileDecision";
+constexpr char kProfileUpdateDecisionHistogram[] =
+ "Autofill.ProfileImport.UpdateProfileDecision";
+constexpr char kNewProfileNumberOfEditsHistogram[] =
+ "Autofill.ProfileImport.NewProfileNumberOfEditedFields";
+constexpr char kProfileUpdateNumberOfEditsHistogram[] =
+ "Autofill.ProfileImport.UpdateProfileNumberOfEditedFields";
+constexpr char kProfileUpdateNumberOfAffectedTypesHistogram[] =
+ "Autofill.ProfileImport.UpdateProfileNumberOfAffectedFields";
+
class MockPersonalDataManager : public TestPersonalDataManager {
public:
MockPersonalDataManager() = default;
~MockPersonalDataManager() override = default;
+
MOCK_METHOD(std::string,
SaveImportedProfile,
(const AutofillProfile&),
(override));
};
+// This derived version of the AddressProfileSaveManager stores the last import
+// for testing purposes and mocks the UI request.
+class TestAddressProfileSaveManager : public AddressProfileSaveManager {
+ public:
+ // The parameters should outlive the AddressProfileSaveManager.
+ TestAddressProfileSaveManager(AutofillClient* client,
+ PersonalDataManager* personal_data_manager);
+
+ // Mocks the function that initiates the UI prompt for testing purposes.
+ MOCK_METHOD(void,
+ OfferSavePrompt,
+ (std::unique_ptr<ProfileImportProcess>),
+ (override));
+
+ // Returns a copy of the last finished import process or 'absl::nullopt' if no
+ // import process was finished.
+ ProfileImportProcess* last_import();
+
+ void OnUserDecisionForTesting(
+ std::unique_ptr<ProfileImportProcess> import_process,
+ UserDecision decision,
+ AutofillProfile edited_profile) {
+ if (profile_added_while_waiting_for_user_response_) {
+ personal_data_manager()->AddProfile(
+ profile_added_while_waiting_for_user_response_.value());
+ }
+
+ import_process->set_prompt_was_shown();
+ OnUserDecision(std::move(import_process), decision, edited_profile);
+ }
+
+ void SetProfileThatIsAddedInWhileWaitingForUserResponse(
+ const AutofillProfile& profile) {
+ profile_added_while_waiting_for_user_response_ = profile;
+ }
+
+ protected:
+ void ClearPendingImport(
+ std::unique_ptr<ProfileImportProcess> import_process) override;
+ // Profile that is passed from the emulated UI respones in case the user
+ // edited the import candidate.
+ std::unique_ptr<ProfileImportProcess> last_import_;
+
+ // If set, this is a profile that is added in between the import operation
+ // while the response from the user is pending.
+ absl::optional<AutofillProfile>
+ profile_added_while_waiting_for_user_response_;
+};
+
+TestAddressProfileSaveManager::TestAddressProfileSaveManager(
+ AutofillClient* client,
+ PersonalDataManager* personal_data_manager)
+ : AddressProfileSaveManager(client, personal_data_manager) {}
+
+void TestAddressProfileSaveManager::ClearPendingImport(
+ std::unique_ptr<ProfileImportProcess> import_process) {
+ last_import_ = std::move(import_process);
+ AddressProfileSaveManager::ClearPendingImport(std::move(import_process));
+}
+
+ProfileImportProcess* TestAddressProfileSaveManager::last_import() {
+ return last_import_.get();
+}
+
+// Definition of a test scenario.
+struct ImportScenarioTestCase {
+ std::vector<AutofillProfile> existing_profiles;
+ AutofillProfile observed_profile;
+ bool is_prompt_expected;
+ UserDecision user_decision;
+ AutofillProfile edited_profile;
+ AutofillProfileImportType expected_import_type;
+ bool is_profile_change_expected;
+ absl::optional<AutofillProfile> merge_candidate;
+ absl::optional<AutofillProfile> import_candidate;
+ std::vector<AutofillProfile> expected_final_profiles;
+ std::vector<AutofillMetrics::SettingsVisibleFieldTypeForMetrics>
+ expected_edited_types_for_metrics;
+ std::vector<AutofillMetrics::SettingsVisibleFieldTypeForMetrics>
+ expected_affeceted_types_in_merge_for_metrics;
+ bool new_profiles_suppresssed_for_domain;
+ std::vector<std::string> blocked_guids_for_updates;
+ absl::optional<AutofillProfile> profile_to_be_added_while_waiting;
+};
+
class AddressProfileSaveManagerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ // Enable both explicit save prompts and structured names.
+ // The latter is needed to test the concept of silent updates.
+ scoped_feature_list_.InitWithFeatures(
+ {features::kAutofillAddressProfileSavePrompt,
+ features::kAutofillEnableSupportForMoreStructureInNames},
+ {});
+ }
+
+ void BlockProfileForUpdates(const std::string& guid) {
+ while (!mock_personal_data_manager_.IsProfileUpdateBlocked(guid)) {
+ mock_personal_data_manager_.AddStrikeToBlockProfileUpdate(guid);
+ }
+ }
+
+ // Tests the |test_scenario|.
+ void TestImportScenario(ImportScenarioTestCase& test_scenario);
+
protected:
base::test::TaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
MockPersonalDataManager mock_personal_data_manager_;
+ base::test::ScopedFeatureList scoped_feature_list_;
};
-} // namespace
+void AddressProfileSaveManagerTest::TestImportScenario(
+ ImportScenarioTestCase& test_scenario) {
+ static const GURL url("https://www.importmyform.com/index.html");
+
+ // Assert that there is not a single profile stored in the personal data
+ // manager.
+ ASSERT_TRUE(mock_personal_data_manager_.GetProfiles().empty());
+
+ TestAddressProfileSaveManager save_manager(&autofill_client_,
+ &mock_personal_data_manager_);
+ base::HistogramTester histogram_tester;
+
+ if (test_scenario.profile_to_be_added_while_waiting) {
+ save_manager.SetProfileThatIsAddedInWhileWaitingForUserResponse(
+ test_scenario.profile_to_be_added_while_waiting.value());
+ }
+
+ // If the domain is blocked for new imports, use the defined limit for the
+ // initial strikes. Otherwise, use 1.
+ int initial_strikes =
+ test_scenario.new_profiles_suppresssed_for_domain
+ ? mock_personal_data_manager_.GetProfileSaveStrikeDatabase()
+ ->GetMaxStrikesLimit()
+ : 1;
+ mock_personal_data_manager_.GetProfileSaveStrikeDatabase()->AddStrikes(
+ initial_strikes, url.host());
+ ASSERT_EQ(mock_personal_data_manager_.IsNewProfileImportBlockedForDomain(url),
+ test_scenario.new_profiles_suppresssed_for_domain);
+
+ // Add one strike for each existing profile and the maximum number of strikes
+ // for blocked profiles.
+ for (const AutofillProfile& profile : test_scenario.existing_profiles) {
+ mock_personal_data_manager_.AddStrikeToBlockProfileUpdate(profile.guid());
+ }
+ for (const std::string& guid : test_scenario.blocked_guids_for_updates) {
+ BlockProfileForUpdates(guid);
+ }
+
+ // Set up the expectation and response for if a prompt should be shown.
+ if (test_scenario.is_prompt_expected) {
+ EXPECT_CALL(save_manager, OfferSavePrompt(testing::_))
+ .Times(1)
+ .WillOnce(testing::WithArgs<0>(
+ [&](std::unique_ptr<ProfileImportProcess> import_process) {
+ save_manager.OnUserDecisionForTesting(
+ std::move(import_process), test_scenario.user_decision,
+ test_scenario.edited_profile);
+ }));
+ } else {
+ EXPECT_CALL(save_manager, OfferSavePrompt).Times(0);
+ }
+
+ // Set the existing profiles to the personal data manager.
+ mock_personal_data_manager_.SetProfiles(&test_scenario.existing_profiles);
+
+ // Initiate the profile import.
+ save_manager.ImportProfileFromForm(test_scenario.observed_profile, "en-US",
+ url);
+
+ // Assert that there is a finished import process on record.
+ ASSERT_NE(save_manager.last_import(), nullptr);
+ ProfileImportProcess* last_import = save_manager.last_import();
+
+ EXPECT_EQ(test_scenario.expected_import_type, last_import->import_type());
+
+ // Make a copy of the final profiles in the personal data manager for
+ // comparison.
+ std::vector<AutofillProfile> final_profiles;
+ final_profiles.reserve(test_scenario.expected_final_profiles.size());
+ for (const auto* profile : mock_personal_data_manager_.GetProfiles())
+ final_profiles.push_back(*profile);
+
+ EXPECT_THAT(test_scenario.expected_final_profiles,
+ testing::UnorderedElementsAreArray(final_profiles));
+
+ // Test that the merge and import candidates are correct.
+ EXPECT_EQ(test_scenario.merge_candidate, last_import->merge_candidate());
+ EXPECT_EQ(test_scenario.import_candidate, last_import->import_candidate());
+
+ // Test the collection of metrics.
+ histogram_tester.ExpectUniqueSample(kProfileImportTypeHistogram,
+ test_scenario.expected_import_type, 1);
+
+ const bool is_new_profile = test_scenario.expected_import_type ==
+ AutofillProfileImportType::kNewProfile;
+ const bool is_confirmable_merge =
+ test_scenario.expected_import_type ==
+ AutofillProfileImportType::kConfirmableMerge ||
+ test_scenario.expected_import_type ==
+ AutofillProfileImportType::kConfirmableMergeAndSilentUpdate;
+
+ // If the import was neither a new profile or a confirmable merge, test that
+ // the corresponding updates are unchanged.
+ if (!is_new_profile && !is_confirmable_merge) {
+ histogram_tester.ExpectTotalCount(kNewProfileEditsHistogram, 0);
+ histogram_tester.ExpectTotalCount(kNewProfileDecisionHistogram, 0);
+ histogram_tester.ExpectTotalCount(kProfileUpdateEditsHistogram, 0);
+ histogram_tester.ExpectTotalCount(kProfileUpdateDecisionHistogram, 0);
+ } else {
+ DCHECK(!is_new_profile || !is_confirmable_merge);
+
+ const std::string affected_decision_histo =
+ is_new_profile ? kNewProfileDecisionHistogram
+ : kProfileUpdateDecisionHistogram;
+ const std::string unaffected_decision_histo =
+ !is_new_profile ? kNewProfileDecisionHistogram
+ : kProfileUpdateDecisionHistogram;
+
+ const std::string affected_edits_histo = is_new_profile
+ ? kNewProfileEditsHistogram
+ : kProfileUpdateEditsHistogram;
+ const std::string unaffected_edits_histo =
+ !is_new_profile ? kNewProfileEditsHistogram
+ : kProfileUpdateEditsHistogram;
+
+ const std::string affected_number_of_edits_histo =
+ is_new_profile ? kNewProfileNumberOfEditsHistogram
+ : kProfileUpdateNumberOfEditsHistogram;
+ const std::string unaffected_number_of_edits_histo =
+ !is_new_profile ? kNewProfileNumberOfEditsHistogram
+ : kProfileUpdateNumberOfEditsHistogram;
+
+ histogram_tester.ExpectTotalCount(unaffected_decision_histo, 0);
+ histogram_tester.ExpectTotalCount(unaffected_edits_histo, 0);
+
+ histogram_tester.ExpectUniqueSample(affected_decision_histo,
+ test_scenario.user_decision, 1);
+ histogram_tester.ExpectTotalCount(
+ affected_edits_histo,
+ test_scenario.expected_edited_types_for_metrics.size());
+
+ for (auto edited_type : test_scenario.expected_edited_types_for_metrics) {
+ histogram_tester.ExpectBucketCount(affected_edits_histo, edited_type, 1);
+ }
+
+ if (test_scenario.user_decision == UserDecision::kEditAccepted) {
+ histogram_tester.ExpectUniqueSample(
+ affected_number_of_edits_histo,
+ test_scenario.expected_edited_types_for_metrics.size(), 1);
+ histogram_tester.ExpectTotalCount(unaffected_number_of_edits_histo, 0);
+ }
+
+ if (is_confirmable_merge &&
+ test_scenario.user_decision == UserDecision::kAccepted) {
+ histogram_tester.ExpectTotalCount(
+ kProfileUpdateAffectedTypesHistogram,
+ test_scenario.expected_affeceted_types_in_merge_for_metrics.size());
+
+ for (auto changed_type :
+ test_scenario.expected_affeceted_types_in_merge_for_metrics) {
+ histogram_tester.ExpectBucketCount(kProfileUpdateAffectedTypesHistogram,
+ changed_type, 1);
+ }
+
+ histogram_tester.ExpectUniqueSample(
+ kProfileUpdateNumberOfAffectedTypesHistogram,
+ test_scenario.expected_affeceted_types_in_merge_for_metrics.size(),
+ 1);
+ }
+ }
+
+ // Check that the strike count was incremented if the import of a new profile
+ // was declined.
+ if (is_new_profile && last_import->UserDeclined()) {
+ EXPECT_EQ(2, mock_personal_data_manager_.GetProfileSaveStrikeDatabase()
+ ->GetStrikes(url.host()));
+ } else if (is_new_profile && last_import->UserAccepted()) {
+ // If the import of a new profile was accepted, the count should have been
+ // reset.
+ EXPECT_EQ(0, mock_personal_data_manager_.GetProfileSaveStrikeDatabase()
+ ->GetStrikes(url.host()));
+ } else {
+ // In all other cases, the number of strikes should be unaltered.
+ EXPECT_EQ(
+ initial_strikes,
+ mock_personal_data_manager_.GetProfileSaveStrikeDatabase()->GetStrikes(
+ url.host()));
+ }
+
+ // Check that the strike count for profile updates is reset if a profile was
+ // updated.
+ if (is_confirmable_merge &&
+ (test_scenario.user_decision == UserDecision::kAccepted ||
+ test_scenario.user_decision == UserDecision::kEditAccepted)) {
+ EXPECT_EQ(0, mock_personal_data_manager_.GetProfileUpdateStrikeDatabase()
+ ->GetStrikes(test_scenario.merge_candidate->guid()));
+ } else if (is_confirmable_merge &&
+ (test_scenario.user_decision == UserDecision::kDeclined ||
+ test_scenario.user_decision == UserDecision::kMessageDeclined)) {
+ // Or that it is incremented if the update was declined.
+ EXPECT_EQ(2, mock_personal_data_manager_.GetProfileUpdateStrikeDatabase()
+ ->GetStrikes(test_scenario.merge_candidate->guid()));
+ } else if (test_scenario.merge_candidate.has_value()) {
+ // In all other cases, the number of strikes should be unaltered.
+ EXPECT_EQ(1, mock_personal_data_manager_.GetProfileUpdateStrikeDatabase()
+ ->GetStrikes(test_scenario.merge_candidate->guid()));
+ }
+}
+
+// Test that a profile is correctly imported when no other profile is stored
+// yet.
+TEST_F(AddressProfileSaveManagerTest, SaveNewProfile) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kAccepted,
+ .expected_import_type = AutofillProfileImportType::kNewProfile,
+ .is_profile_change_expected = true,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = observed_profile,
+ .expected_final_profiles = {observed_profile}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test that a profile is correctly imported when no other profile is stored
+// yet but another profile is added while waiting for the user response.
+TEST_F(AddressProfileSaveManagerTest, SaveNewProfile_ProfileAddedWhileWaiting) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile profile_added_while_waiting =
+ test::DifferentFromStandardProfile();
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kAccepted,
+ .expected_import_type = AutofillProfileImportType::kNewProfile,
+ .is_profile_change_expected = true,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = observed_profile,
+ .expected_final_profiles = {observed_profile,
+ profile_added_while_waiting},
+ .profile_to_be_added_while_waiting = profile_added_while_waiting};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test that a profile is not imported and that the user is not prompted if the
+// domain is blocked for imorting new profiles.
+TEST_F(AddressProfileSaveManagerTest, SaveNewProfileOnBlockedDomain) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = false,
+ .user_decision = UserDecision::kUserNotAsked,
+ .expected_import_type = AutofillProfileImportType::kSuppressedNewProfile,
+ .is_profile_change_expected = false,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = absl::nullopt,
+ .expected_final_profiles = {},
+ .new_profiles_suppresssed_for_domain = true};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test that a profile is correctly imported when no other profile is stored
+// yet. Here, `kUserNotAsked` is supplied which is done as a fallback in case
+// the UI is unavailable for technical reasons.
+TEST_F(AddressProfileSaveManagerTest, SaveNewProfile_UserNotAskedFallback) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kUserNotAsked,
+ .expected_import_type = AutofillProfileImportType::kNewProfile,
+ .is_profile_change_expected = true,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = observed_profile,
+ .expected_final_profiles = {observed_profile}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test that a profile is correctly imported when no other profile is stored
+// yet. Here, the profile is edited by the user.
+TEST_F(AddressProfileSaveManagerTest, SaveNewProfile_Edited) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile edited_profile = test::DifferentFromStandardProfile();
+ // The edited profile must have the same GUID then the observed one.
+ test::CopyGUID(observed_profile, &edited_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kEditAccepted,
+ .edited_profile = edited_profile,
+ .expected_import_type = AutofillProfileImportType::kNewProfile,
+ .is_profile_change_expected = true,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = observed_profile,
+ .expected_final_profiles = {edited_profile},
+ .expected_edited_types_for_metrics = {
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kName,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kStreetAddress,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kCity,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kZip}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test that a decline to import a new profile is handled correctly.
+TEST_F(AddressProfileSaveManagerTest, SaveNewProfile_Declined) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kDeclined,
+ .expected_import_type = AutofillProfileImportType::kNewProfile,
+ .is_profile_change_expected = false,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = observed_profile,
+ .expected_final_profiles = {}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test that a decline to import a new profile in the message UI is handled
+// correctly.
+TEST_F(AddressProfileSaveManagerTest, SaveNewProfile_MessageDeclined) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kMessageDeclined,
+ .expected_import_type = AutofillProfileImportType::kNewProfile,
+ .is_profile_change_expected = false,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = observed_profile,
+ .expected_final_profiles = {}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test that the observation of a duplicate profile has no effect.
+TEST_F(AddressProfileSaveManagerTest, ImportDuplicateProfile) {
+ // Note that the profile is created twice to enforce different GUIDs.
+ AutofillProfile existing_profile = test::StandardProfile();
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {existing_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = false,
+ .user_decision = UserDecision::kAccepted,
+ .expected_import_type = AutofillProfileImportType::kDuplicateImport,
+ .is_profile_change_expected = false,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = absl::nullopt,
+ .expected_final_profiles = {existing_profile}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test that the observation of quasi identical profile that has a different
+// structure in the name will result in a silent update.
+TEST_F(AddressProfileSaveManagerTest, SilentlyUpdateProfile) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+ AutofillProfile final_profile = observed_profile;
+ test::CopyGUID(updateable_profile, &final_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {updateable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = false,
+ .expected_import_type = AutofillProfileImportType::kSilentUpdate,
+ .is_profile_change_expected = true,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = absl::nullopt,
+ .expected_final_profiles = {final_profile}};
+ TestImportScenario(test_scenario);
+}
+
+// Test that the observation of quasi identical profile that has a different
+// structure in the name will result in a silent update even though the domain
+// is blocked for new profile imports.
+TEST_F(AddressProfileSaveManagerTest, SilentlyUpdateProfileOnBlockedDomain) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+ AutofillProfile final_profile = observed_profile;
+ test::CopyGUID(updateable_profile, &final_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {updateable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = false,
+ .expected_import_type = AutofillProfileImportType::kSilentUpdate,
+ .is_profile_change_expected = true,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = absl::nullopt,
+ .expected_final_profiles = {final_profile},
+ .new_profiles_suppresssed_for_domain = true};
+ TestImportScenario(test_scenario);
+}
+
+// Test that the observation of quasi identical profile that has a different
+// structure in the name will result in a silent update even when the profile
+// has the legacy property of being verified.
+TEST_F(AddressProfileSaveManagerTest, SilentlyUpdateVerifiedProfile) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+ updateable_profile.set_origin(kSettingsOrigin);
+ ASSERT_TRUE(updateable_profile.IsVerified());
+
+ AutofillProfile final_profile = observed_profile;
+ test::CopyGUID(updateable_profile, &final_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {updateable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = false,
+ .expected_import_type = AutofillProfileImportType::kSilentUpdate,
+ .is_profile_change_expected = true,
+ .merge_candidate = absl::nullopt,
+ .import_candidate = absl::nullopt,
+ .expected_final_profiles = {final_profile}};
+ TestImportScenario(test_scenario);
+}
+
+// Test the observation of a profile that can only be merged with a
+// settings-visible change. Here, `kUserNotAsked` is returned as the fallback
+// mechanism when the UI is not available for technical reasons.
+TEST_F(AddressProfileSaveManagerTest,
+ UserConfirmableMerge_UserNotAskedFallback) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+ AutofillProfile final_profile = observed_profile;
+ test::CopyGUID(mergeable_profile, &final_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {mergeable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kUserNotAsked,
+ .expected_import_type = AutofillProfileImportType::kConfirmableMerge,
+ .is_profile_change_expected = true,
+ .merge_candidate = mergeable_profile,
+ .import_candidate = final_profile,
+ .expected_final_profiles = {final_profile}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test the observation of a profile that can only be merged with a
+// settings-visible change.
+TEST_F(AddressProfileSaveManagerTest, UserConfirmableMerge) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+ AutofillProfile final_profile = observed_profile;
+ test::CopyGUID(mergeable_profile, &final_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {mergeable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kAccepted,
+ .expected_import_type = AutofillProfileImportType::kConfirmableMerge,
+ .is_profile_change_expected = true,
+ .merge_candidate = mergeable_profile,
+ .import_candidate = final_profile,
+ .expected_final_profiles = {final_profile},
+ .expected_affeceted_types_in_merge_for_metrics = {
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kZip,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kCity}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test the observation of a profile that can only be merged with a
+// settings-visible change but the mergeable profile is blocked for updates.
+TEST_F(AddressProfileSaveManagerTest, UserConfirmableMerge_BlockedProfile) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+ AutofillProfile final_profile = observed_profile;
+ test::CopyGUID(mergeable_profile, &final_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {mergeable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = false,
+ .user_decision = UserDecision::kUserNotAsked,
+ .expected_import_type =
+ AutofillProfileImportType::kSuppressedConfirmableMerge,
+ .is_profile_change_expected = false,
+ .expected_final_profiles = {mergeable_profile},
+ .blocked_guids_for_updates = {mergeable_profile.guid()}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test the observation of a profile that can only be merged with a
+// settings-visible change. The existing profile has the legacy property of
+// being verified.
+TEST_F(AddressProfileSaveManagerTest, UserConfirmableMerge_VerifiedProfile) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+ mergeable_profile.set_origin(kSettingsOrigin);
+ ASSERT_TRUE(mergeable_profile.IsVerified());
+
+ AutofillProfile final_profile = observed_profile;
+ test::CopyGUID(mergeable_profile, &final_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {mergeable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kAccepted,
+ .expected_import_type = AutofillProfileImportType::kConfirmableMerge,
+ .is_profile_change_expected = true,
+ .merge_candidate = mergeable_profile,
+ .import_candidate = final_profile,
+ .expected_final_profiles = {final_profile},
+ .expected_affeceted_types_in_merge_for_metrics = {
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kZip,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kCity}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test the observation of a profile that can only be merged with a
+// settings-visible change.
+TEST_F(AddressProfileSaveManagerTest, UserConfirmableMerge_Edited) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+ AutofillProfile edited_profile = test::DifferentFromStandardProfile();
+
+ AutofillProfile import_candidate = observed_profile;
+ test::CopyGUID(mergeable_profile, &import_candidate);
+ test::CopyGUID(mergeable_profile, &edited_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {mergeable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kEditAccepted,
+ .edited_profile = edited_profile,
+ .expected_import_type = AutofillProfileImportType::kConfirmableMerge,
+ .is_profile_change_expected = true,
+ .merge_candidate = mergeable_profile,
+ .import_candidate = import_candidate,
+ .expected_final_profiles = {edited_profile},
+ .expected_edited_types_for_metrics = {
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kName,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kStreetAddress,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kCity,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kZip}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test the observation of a profile that can only be merged with a
+// settings-visible change but the import is declined by the user.
+TEST_F(AddressProfileSaveManagerTest, UserConfirmableMerge_Declined) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+ AutofillProfile final_profile = observed_profile;
+ test::CopyGUID(mergeable_profile, &final_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {mergeable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kDeclined,
+ .expected_import_type = AutofillProfileImportType::kConfirmableMerge,
+ .is_profile_change_expected = false,
+ .merge_candidate = mergeable_profile,
+ .import_candidate = final_profile,
+ .expected_final_profiles = {mergeable_profile}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test a mixed scenario in which a duplicate profile already exists, but a
+// another profile is mergeable with the observed profile.
+TEST_F(AddressProfileSaveManagerTest, UserConfirmableMergeAndDuplicate) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile existing_duplicate = test::StandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ AutofillProfile merged_profile = observed_profile;
+ test::CopyGUID(mergeable_profile, &merged_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {existing_duplicate, mergeable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kAccepted,
+ .expected_import_type = AutofillProfileImportType::kConfirmableMerge,
+ .is_profile_change_expected = true,
+ .merge_candidate = mergeable_profile,
+ .import_candidate = merged_profile,
+ .expected_final_profiles = {existing_duplicate, merged_profile},
+ .expected_affeceted_types_in_merge_for_metrics = {
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kZip,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kCity}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test a mixed scenario in which a duplicate profile already exists, but a
+// another profile is mergeable with the observed profile. The result should not
+// be affected by the fact that the domain is blocked for the import of new
+// profiles.
+TEST_F(AddressProfileSaveManagerTest,
+ UserConfirmableMergeAndDuplicateOnBlockedDomain) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile existing_duplicate = test::StandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ AutofillProfile merged_profile = observed_profile;
+ test::CopyGUID(mergeable_profile, &merged_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {existing_duplicate, mergeable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kAccepted,
+ .expected_import_type = AutofillProfileImportType::kConfirmableMerge,
+ .is_profile_change_expected = true,
+ .merge_candidate = mergeable_profile,
+ .import_candidate = merged_profile,
+ .expected_final_profiles = {existing_duplicate, merged_profile},
+ .expected_affeceted_types_in_merge_for_metrics =
+ {AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kZip,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kCity},
+ .new_profiles_suppresssed_for_domain = true};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test a mixed scenario in which a duplicate profile already exists, but a
+// another profile is mergeable with the observed profile and yet another
+// profile can be silently updated.
+TEST_F(AddressProfileSaveManagerTest,
+ UserConfirmableMergeAndUpdateAndDuplicate) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile existing_duplicate = test::StandardProfile();
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ // Both the mergeable and updateable profile should have the same values as
+ // the observed profile.
+ AutofillProfile merged_profile = observed_profile;
+ AutofillProfile updated_profile = observed_profile;
+ // However, the GUIDs must be maintained.
+ test::CopyGUID(updateable_profile, &updated_profile);
+ test::CopyGUID(mergeable_profile, &merged_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {existing_duplicate, mergeable_profile,
+ updateable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kAccepted,
+ .expected_import_type =
+ AutofillProfileImportType::kConfirmableMergeAndSilentUpdate,
+ .is_profile_change_expected = true,
+ .merge_candidate = mergeable_profile,
+ .import_candidate = merged_profile,
+ .expected_final_profiles = {existing_duplicate, updated_profile,
+ merged_profile},
+ .expected_affeceted_types_in_merge_for_metrics = {
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kZip,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kCity}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Same as above, but the merge candidate is blocked for updates.
+TEST_F(AddressProfileSaveManagerTest,
+ UserConfirmableMergeAndUpdateAndDuplicate_Blocked) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile existing_duplicate = test::StandardProfile();
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ // Both the mergeable and updateable profile should have the same values as
+ // the observed profile.
+ AutofillProfile merged_profile = observed_profile;
+ AutofillProfile updated_profile = observed_profile;
+ // However, the GUIDs must be maintained.
+ test::CopyGUID(updateable_profile, &updated_profile);
+ test::CopyGUID(mergeable_profile, &merged_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {existing_duplicate, mergeable_profile,
+ updateable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = false,
+ .user_decision = UserDecision::kUserNotAsked,
+ .expected_import_type =
+ AutofillProfileImportType::kSuppressedConfirmableMergeAndSilentUpdate,
+ .is_profile_change_expected = true,
+ .expected_final_profiles = {existing_duplicate, mergeable_profile,
+ updated_profile},
+ .blocked_guids_for_updates = {mergeable_profile.guid()}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test a mixed scenario in which a duplicate profile already exists, but a
+// another profile is mergeable with the observed profile and yet another
+// profile can be silently updated. Here, the merge is declined.
+TEST_F(AddressProfileSaveManagerTest,
+ UserConfirmableMergeAndUpdateAndDuplicate_Declined) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile existing_duplicate = test::StandardProfile();
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ // Both the mergeable and updateable profile should have the same values as
+ // the observed profile.
+ AutofillProfile merged_profile = observed_profile;
+ AutofillProfile updated_profile = observed_profile;
+ // However, the GUIDs must be maintained.
+ test::CopyGUID(updateable_profile, &updated_profile);
+ test::CopyGUID(mergeable_profile, &merged_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {existing_duplicate, mergeable_profile,
+ updateable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kDeclined,
+ .expected_import_type =
+ AutofillProfileImportType::kConfirmableMergeAndSilentUpdate,
+ .is_profile_change_expected = true,
+ .merge_candidate = mergeable_profile,
+ .import_candidate = merged_profile,
+ .expected_final_profiles = {existing_duplicate, updated_profile,
+ mergeable_profile}};
+
+ TestImportScenario(test_scenario);
+}
+
+// Test a mixed scenario in which a duplicate profile already exists, but a
+// another profile is mergeable with the observed profile and yet another
+// profile can be silently updated. Here, the merge is accepted with edits.
+TEST_F(AddressProfileSaveManagerTest,
+ UserConfirmableMergeAndUpdateAndDuplicate_Edited) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ AutofillProfile existing_duplicate = test::StandardProfile();
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+ AutofillProfile edited_profile = test::DifferentFromStandardProfile();
+
+ // Both the mergeable and updateable profile should have the same values as
+ // the observed profile.
+ AutofillProfile merged_profile = observed_profile;
+ AutofillProfile updated_profile = observed_profile;
+ // However, the GUIDs must be maintained.
+ test::CopyGUID(updateable_profile, &updated_profile);
+ test::CopyGUID(mergeable_profile, &merged_profile);
+ test::CopyGUID(mergeable_profile, &edited_profile);
+
+ ImportScenarioTestCase test_scenario{
+ .existing_profiles = {existing_duplicate, mergeable_profile,
+ updateable_profile},
+ .observed_profile = observed_profile,
+ .is_prompt_expected = true,
+ .user_decision = UserDecision::kEditAccepted,
+ .edited_profile = edited_profile,
+ .expected_import_type =
+ AutofillProfileImportType::kConfirmableMergeAndSilentUpdate,
+ .is_profile_change_expected = true,
+ .merge_candidate = mergeable_profile,
+ .import_candidate = merged_profile,
+ .expected_final_profiles = {existing_duplicate, updated_profile,
+ edited_profile},
+ .expected_edited_types_for_metrics = {
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kName,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kStreetAddress,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kCity,
+ AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kZip}};
+
+ TestImportScenario(test_scenario);
+}
TEST_F(AddressProfileSaveManagerTest, SaveProfileWhenNoSavePrompt) {
base::test::ScopedFeatureList scoped_feature_list;
@@ -44,6 +971,10 @@ TEST_F(AddressProfileSaveManagerTest, SaveProfileWhenNoSavePrompt) {
&mock_personal_data_manager_);
AutofillProfile test_profile = test::GetFullProfile();
EXPECT_CALL(mock_personal_data_manager_, SaveImportedProfile(test_profile));
- save_manager.SaveProfile(test_profile);
+ save_manager.ImportProfileFromForm(test_profile, "en_US",
+ GURL("https://www.noprompt.com"));
}
+
+} // namespace
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/address_rewriter.cc b/chromium/components/autofill/core/browser/address_rewriter.cc
index 5f53bc4c0da..cfe54dd826c 100644
--- a/chromium/components/autofill/core/browser/address_rewriter.cc
+++ b/chromium/components/autofill/core/browser/address_rewriter.cc
@@ -10,6 +10,7 @@
#include "base/i18n/case_conversion.h"
#include "base/memory/singleton.h"
#include "base/strings/strcat.h"
+#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/grit/autofill_address_rewriter_resources_map.h"
#include "third_party/re2/src/re2/re2.h"
@@ -68,7 +69,7 @@ void CompileRulesFromData(const std::string& data_string,
data.remove_prefix(token_end + 1);
token_end = data.find('\n');
- std::string rewrite_string = data.substr(0, token_end).as_string();
+ std::string rewrite_string(data.substr(0, token_end));
compiled_rules->emplace_back(std::move(pattern), std::move(rewrite_string));
data.remove_prefix(token_end + 1);
}
diff --git a/chromium/components/autofill/core/browser/address_rewriter_unittest.cc b/chromium/components/autofill/core/browser/address_rewriter_unittest.cc
index fdd1ead86a0..35df50d6a6f 100644
--- a/chromium/components/autofill/core/browser/address_rewriter_unittest.cc
+++ b/chromium/components/autofill/core/browser/address_rewriter_unittest.cc
@@ -7,7 +7,6 @@
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::UTF8ToUTF16;
using autofill::AddressRewriter;
TEST(AddressRewriterTest, InvalidCountryCode) {
@@ -41,8 +40,7 @@ TEST(AddressRewriterTest, AD) {
TEST(AddressRewriterTest, AR) {
AddressRewriter ar = AddressRewriter::ForCountryCode(u"ar");
- EXPECT_EQ(ar.Rewrite(UTF8ToUTF16(
- "tierra del fuego antartida e islas del atlantico sur")),
+ EXPECT_EQ(ar.Rewrite(u"tierra del fuego antartida e islas del atlantico sur"),
ar.Rewrite(u"tierra del fuego"));
EXPECT_EQ(ar.Rewrite(u"ciudad autonoma de buenos aires"),
ar.Rewrite(u"capital federal"));
@@ -158,7 +156,7 @@ TEST(AddressRewriterTest, IN) {
EXPECT_EQ(in.Rewrite(u"cross-road"), in.Rewrite(u"xrd"));
EXPECT_EQ(in.Rewrite(u"j & k"), in.Rewrite(u"j&k"));
EXPECT_EQ(in.Rewrite(u"i.n.d.i.a"), in.Rewrite(u"india"));
- EXPECT_NE(in.Rewrite(UTF8ToUTF16("i\\_n\\_d\\_i\\_a")), in.Rewrite(u"india"));
+ EXPECT_NE(in.Rewrite(u"i\\_n\\_d\\_i\\_a"), in.Rewrite(u"india"));
}
TEST(AddressRewriterTest, IT) {
diff --git a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
index e860b3027c7..b89f0b44940 100644
--- a/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
+++ b/chromium/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -56,8 +56,7 @@ bool IsMeaningfulFieldName(const std::u16string& name) {
return true;
}
return !MatchesPattern(
- name,
- base::UTF8ToUTF16("^(((field|input)(_|-)?\\d+)|tan|otp|title|captcha)$"));
+ name, u"^(((field|input)(_|-)?\\d+)|tan|otp|title|captcha)$");
}
} // namespace
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 9f13c0aaf34..67348321ac4 100644
--- a/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
@@ -35,7 +35,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect.h"
-using base::ASCIIToUTF16;
using testing::_;
using testing::Eq;
using testing::Field;
@@ -291,7 +290,7 @@ TEST_F(AutocompleteHistoryManagerTest, InvalidValues) {
// Tests that text entered into fields specifying autocomplete="off" is not sent
// to the WebDatabase to be saved. Note this is also important as the mechanism
// for preventing CVCs from being saved.
-// See AutofillManagerTest.DontSaveCvcInAutocompleteHistory
+// See BrowserAutofillManagerTest.DontSaveCvcInAutocompleteHistory
TEST_F(AutocompleteHistoryManagerTest, FieldWithAutocompleteOff) {
FormData form;
form.name = u"MyForm";
@@ -449,8 +448,8 @@ TEST_F(AutocompleteHistoryManagerTest,
auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
int test_query_id = 2;
- auto test_name = ASCIIToUTF16("Some Field Name");
- auto test_prefix = ASCIIToUTF16("SomePrefix");
+ std::u16string test_name = u"Some Field Name";
+ std::u16string test_prefix = u"SomePrefix";
std::vector<AutofillEntry> expected_values;
@@ -490,8 +489,8 @@ TEST_F(AutocompleteHistoryManagerTest,
auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
int test_query_id = 2;
- auto test_name = ASCIIToUTF16("input_123");
- auto test_prefix = ASCIIToUTF16("");
+ std::u16string test_name = u"input_123";
+ std::u16string test_prefix;
// Only expect a call when the name is not filtered out.
EXPECT_CALL(*web_data_service_,
@@ -523,8 +522,8 @@ TEST_F(AutocompleteHistoryManagerTest,
auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
int test_query_id = 2;
- auto test_name = ASCIIToUTF16("addressline_1");
- auto test_prefix = ASCIIToUTF16("");
+ std::u16string test_name = u"addressline_1";
+ std::u16string test_prefix;
int mocked_db_query_id = 100;
std::vector<AutofillEntry> expected_values;
@@ -559,8 +558,8 @@ TEST_F(AutocompleteHistoryManagerTest,
auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
int test_query_id = 2;
- auto test_name = ASCIIToUTF16("Some Field Name");
- auto test_prefix = ASCIIToUTF16("SomePrefix");
+ std::u16string test_name = u"Some Field Name";
+ std::u16string test_prefix = u"SomePrefix";
std::vector<AutofillEntry> expected_values = {
GetAutofillEntry(test_name, u"SomePrefixOne")};
@@ -599,8 +598,8 @@ TEST_F(AutocompleteHistoryManagerTest,
auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
int test_query_id = 2;
- auto test_name = ASCIIToUTF16("Some Field Name");
- auto test_prefix = ASCIIToUTF16("SomePrefix");
+ std::u16string test_name = u"Some Field Name";
+ std::u16string test_prefix = u"SomePrefix";
std::vector<AutofillEntry> expected_values = {
GetAutofillEntry(test_name, u"SomePrefixOne")};
@@ -639,8 +638,8 @@ TEST_F(AutocompleteHistoryManagerTest,
auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
int test_query_id = 2;
- auto test_name = ASCIIToUTF16("Some Field Name");
- auto test_prefix = ASCIIToUTF16("SomePrefix");
+ std::u16string test_name = u"Some Field Name";
+ std::u16string test_prefix = u"SomePrefix";
std::vector<AutofillEntry> expected_values = {
GetAutofillEntry(test_name, test_prefix)};
@@ -678,8 +677,8 @@ TEST_F(AutocompleteHistoryManagerTest,
auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
int test_query_id = 2;
- auto test_name = ASCIIToUTF16("Some Field Name");
- auto test_prefix = ASCIIToUTF16("SomePrefix");
+ std::u16string test_name = u"Some Field Name";
+ std::u16string test_prefix = u"SomePrefix";
std::vector<AutofillEntry> expected_values = {
GetAutofillEntry(test_name, u"someprefix")};
@@ -718,10 +717,10 @@ TEST_F(AutocompleteHistoryManagerTest,
auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
int test_query_id = 2;
- auto test_name = ASCIIToUTF16("Some Field Name");
- auto test_prefix = ASCIIToUTF16("SomePrefix");
- auto test_value = ASCIIToUTF16("SomePrefixOne");
- auto other_test_value = ASCIIToUTF16("SomePrefixOne");
+ std::u16string test_name = u"Some Field Name";
+ std::u16string test_prefix = u"SomePrefix";
+ std::u16string test_value = u"SomePrefixOne";
+ std::u16string other_test_value = u"SomePrefixOne";
int days_since_last_use = 10;
std::vector<AutofillEntry> expected_values = {
@@ -772,8 +771,8 @@ TEST_F(AutocompleteHistoryManagerTest,
auto suggestions_handler = std::make_unique<MockSuggestionsHandler>();
int test_query_id_first = 2;
int test_query_id_second = 3;
- auto test_name = ASCIIToUTF16("Some Field Name");
- auto test_prefix = ASCIIToUTF16("SomePrefix");
+ std::u16string test_name = u"Some Field Name";
+ std::u16string test_prefix = u"SomePrefix";
std::vector<AutofillEntry> expected_values_first = {
GetAutofillEntry(test_name, u"SomePrefixOne")};
@@ -841,8 +840,8 @@ TEST_F(AutocompleteHistoryManagerTest,
auto suggestions_handler_second = std::make_unique<MockSuggestionsHandler>();
int test_query_id_first = 2;
int test_query_id_second = 3;
- auto test_name = ASCIIToUTF16("Some Field Name");
- auto test_prefix = ASCIIToUTF16("SomePrefix");
+ std::u16string test_name = u"Some Field Name";
+ std::u16string test_prefix = u"SomePrefix";
std::vector<AutofillEntry> expected_values_first = {
GetAutofillEntry(test_name, u"SomePrefixOne")};
@@ -901,8 +900,8 @@ TEST_F(AutocompleteHistoryManagerTest,
TEST_F(AutocompleteHistoryManagerTest,
SuggestionsReturned_CancelOne_ReturnOne) {
- auto test_name = ASCIIToUTF16("Some Field Name");
- auto test_prefix = ASCIIToUTF16("SomePrefix");
+ std::u16string test_name = u"Some Field Name";
+ std::u16string test_prefix = u"SomePrefix";
// Initialize variables for the first handler, which is the one that will be
// cancelled.
@@ -1068,8 +1067,8 @@ TEST_F(AutocompleteHistoryManagerTest, DestructorCancelsRequests) {
auto suggestions_handler_second = std::make_unique<MockSuggestionsHandler>();
int test_query_id_first = 2;
int test_query_id_second = 3;
- auto test_name = ASCIIToUTF16("Some Field Name");
- auto test_prefix = ASCIIToUTF16("SomePrefix");
+ std::u16string test_name = u"Some Field Name";
+ std::u16string test_prefix = u"SomePrefix";
EXPECT_CALL(*web_data_service_,
GetFormValuesForElementName(test_name, test_prefix, _,
diff --git a/chromium/components/autofill/core/browser/autofill_ablation_study.cc b/chromium/components/autofill/core/browser/autofill_ablation_study.cc
new file mode 100644
index 00000000000..39a9f656373
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_ablation_study.cc
@@ -0,0 +1,164 @@
+// Copyright 2021 The Chromium Authors. 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_ablation_study.h"
+
+#include "base/check_op.h"
+#include "base/command_line.h"
+#include "base/hash/md5.h"
+#include "base/metrics/field_trial.h"
+#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/sys_byteorder.h"
+#include "base/time/time.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "third_party/icu/source/i18n/unicode/timezone.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace autofill {
+
+using autofill::features::kAutofillAblationStudyAblationWeightPerMilleParam;
+using autofill::features::kAutofillAblationStudyEnabledForAddressesParam;
+using autofill::features::kAutofillAblationStudyEnabledForPaymentsParam;
+using autofill::features::kAutofillEnableAblationStudy;
+using autofill::features::kAutofillShowTypePredictions;
+
+namespace {
+
+// Converts the 8-byte prefix of an MD5 hash into a uint64_t value.
+inline uint64_t DigestToUInt64(const base::MD5Digest& digest) {
+ uint64_t value;
+ DCHECK_GE(sizeof(digest.a), sizeof(value));
+ memcpy(&value, digest.a, sizeof(value));
+ return base::NetToHost64(value);
+}
+
+} // namespace
+
+// Number of bytes that we use to randomly seed the MD5Sum. This seed is stable
+// for the life time of the AutofillAblationStudy.
+constexpr size_t kSeedLengthInBytes = 8;
+
+// Returns the number of days since Windows epoch but aligns timezones so that
+// the first day starts at midnight in the local timezone (ignoring daylight
+// saving time).
+int DaysSinceLocalWindowsEpoch(const base::Time& now) {
+ base::TimeDelta delta = now.ToDeltaSinceWindowsEpoch();
+
+ // Windows Epoch coincides with 1601-01-01 00:00:00 UTC.
+ // If on 1601-01-01 some settler on the East Cost of North America (UTC+6)
+ // turned on their computer at midnight, their base::Time::now() was
+ // 1601-01-01 00:00:00 UTC+06, i.e. 6 * 60 * 60 seconds after UTC midnight but
+ // 0 seconds after local midnight. For that reason, we should decrease delta
+ // by the timeoffset of the timezone.
+ std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
+
+ // We don't take daylight saving into account. The complexity is not worth it.
+ int32_t raw_offset_in_ms = zone->getRawOffset();
+
+ // The time offset for EST is negative. Therefore, we add the negative number.
+ delta += base::TimeDelta::FromMilliseconds(raw_offset_in_ms);
+
+ return delta.InDays();
+}
+
+// Returns a 64 bit hash of |seed|, the site and the current day, which is can
+// be used to decide whether a form impression should be exposed to autofill
+// ablation.
+uint64_t GetAblationHash(const std::string& seed,
+ const GURL& url,
+ const base::Time& now) {
+ // Derive a random number from |seed|, |url|'s security origin and today's
+ // date.
+ base::MD5Context ctx;
+ base::MD5Init(&ctx);
+
+ // Incorporate |seed| into the MD5Sum. This ensures that on each browser
+ // start the behavior is shuffled.
+ base::MD5Update(&ctx, seed);
+
+ // Incorporate |url|'s security origin into the MD5Sum. This ensures that
+ // different sites can have different behavior but the behavior on a single
+ // site remains consistent.
+ // Invalid and non-standard origins are parsed as opaque origins, which
+ // serialize as the string "null". This makes all of them identical. Given
+ // that we expect |url| to be a mainframe URL this should be sufficiently rare
+ // so that individual users don't experience an excessive amount of ablation
+ // cases.
+ url::Origin origin = url::Origin::Create(url);
+ base::MD5Update(&ctx, origin.Serialize());
+
+ // Incorporate the date into MD5Sum. This ensures that the behavior can change
+ // from one day to another but stays the same for the day. Daylight saving
+ // time is not considered. This means that a day may wrap at 11pm.
+ int days_since_epoch = DaysSinceLocalWindowsEpoch(now);
+ std::string serialized_days_since_epoch =
+ base::NumberToString(days_since_epoch);
+ base::MD5Update(&ctx, serialized_days_since_epoch);
+
+ // Derive 64 bit hash.
+ base::MD5Digest digest;
+ base::MD5Final(&digest, &ctx);
+ return DigestToUInt64(digest);
+}
+
+AutofillAblationStudy::AutofillAblationStudy()
+ : seed_(base::RandBytesAsString(kSeedLengthInBytes)) {}
+
+AutofillAblationStudy::~AutofillAblationStudy() = default;
+
+AblationGroup AutofillAblationStudy::GetAblationGroup(
+ const GURL& url,
+ FormTypeForAblationStudy form_type) const {
+ if (!base::FeatureList::IsEnabled(kAutofillEnableAblationStudy)) {
+ return AblationGroup::kDefault;
+ }
+ if (base::FeatureList::IsEnabled(kAutofillShowTypePredictions)) {
+ // Disable ablation study while debugging.
+ return AblationGroup::kDefault;
+ }
+
+ // Exit early if the ablation study is not enabled for a certain form type.
+ switch (form_type) {
+ case FormTypeForAblationStudy::kOther:
+ return AblationGroup::kDefault;
+ case FormTypeForAblationStudy::kAddress:
+ if (!kAutofillAblationStudyEnabledForAddressesParam.Get()) {
+ return AblationGroup::kDefault;
+ }
+ break;
+ case FormTypeForAblationStudy::kPayment:
+ if (!kAutofillAblationStudyEnabledForPaymentsParam.Get()) {
+ return AblationGroup::kDefault;
+ }
+ break;
+ }
+
+ // Do some basic checks for plausibility. Note that for testing purposes we
+ // allow that ablation_weight == 1000. In this case 100% of forms are
+ // in the ablation case. In practice ablation_weight * 2 <= total_weight
+ // should be true to get meaningful results (have an equally sized ablation
+ // and control group).
+ int ablation_weight = kAutofillAblationStudyAblationWeightPerMilleParam.Get();
+ if (ablation_weight <= 0 || ablation_weight > 1000)
+ return AblationGroup::kDefault;
+ return GetAblationGroupImpl(url, AutofillClock::Now(), ablation_weight);
+}
+
+AblationGroup AutofillAblationStudy::GetAblationGroupImpl(
+ const GURL& url,
+ const base::Time& now,
+ uint32_t ablation_weight_per_mille) const {
+ uint64_t hash = GetAblationHash(seed_, url, now) % 1000;
+ if (hash < ablation_weight_per_mille)
+ return AblationGroup::kAblation;
+ if (hash < 2 * ablation_weight_per_mille)
+ return AblationGroup::kControl;
+ return AblationGroup::kDefault;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_ablation_study.h b/chromium/components/autofill/core/browser/autofill_ablation_study.h
new file mode 100644
index 00000000000..9ff3f7ad1a8
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_ablation_study.h
@@ -0,0 +1,74 @@
+// Copyright 2021 The Chromium Authors. 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_ABLATION_STUDY_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_ABLATION_STUDY_H_
+
+#include <string>
+
+class GURL;
+namespace base {
+class Time;
+}
+
+namespace autofill {
+
+// The ablation group of a specific [site * day * browsing session].
+enum class AblationGroup {
+ // Autofill (the drop down or chip in the keyboard accessory) is disabled.
+ kAblation,
+ // Default behavior but labeled as control group to partition traffic in
+ // shares such that the ablation and control group have the same size.
+ kControl,
+ kDefault,
+};
+
+// Distinction of form types. For ablation purposes, address and payment forms
+// can be configured for ablation independently. Today we don't offer autofill
+// for other form types. They would be put into the AblationGroup::kDefault.
+enum class FormTypeForAblationStudy {
+ kOther,
+ kAddress,
+ kPayment,
+};
+
+#if defined(UNIT_TEST)
+int DaysSinceLocalWindowsEpoch(const base::Time& now);
+uint64_t GetAblationHash(const std::string& seed,
+ const GURL& url,
+ const base::Time& now);
+#endif // defined(UNIT_TEST)
+
+// A class to control the ablation study. The decision whether a given form
+// is subject to an ablated experience is pseudorandomly derived from the
+// combination of [site * browsing session * day]: Different sites may have
+// ablation configurations. Restarting the browser or waiting for the next day
+// may lead to different ablation configurations as well.
+// The ablation is controlled by
+// autofill::features::kAutofillEnableAblationStudy.
+class AutofillAblationStudy {
+ public:
+ AutofillAblationStudy();
+ ~AutofillAblationStudy();
+ AutofillAblationStudy(const AutofillAblationStudy&) = delete;
+ AutofillAblationStudy& operator=(const AutofillAblationStudy&) = delete;
+
+ // Returns for a site and form type, whether autofill should give the ablated
+ // experience.
+ AblationGroup GetAblationGroup(const GURL& url,
+ FormTypeForAblationStudy form_type) const;
+
+ private:
+ AblationGroup GetAblationGroupImpl(const GURL& url,
+ const base::Time& now,
+ uint32_t ablation_weight_per_mille) const;
+
+ // Random seed so that different users (and browsing experiences) don't have
+ // correlated behavior.
+ const std::string seed_;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_ABLATION_STUDY_H_
diff --git a/chromium/components/autofill/core/browser/autofill_ablation_study_unittest.cc b/chromium/components/autofill/core/browser/autofill_ablation_study_unittest.cc
new file mode 100644
index 00000000000..3078559976a
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_ablation_study_unittest.cc
@@ -0,0 +1,242 @@
+// Copyright 2021 The Chromium Authors. 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_ablation_study.h"
+
+#include "base/strings/stringprintf.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/time/time.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/icu/source/common/unicode/unistr.h"
+#include "third_party/icu/source/i18n/unicode/timezone.h"
+#include "url/gurl.h"
+
+using autofill::features::kAutofillAblationStudyAblationWeightPerMilleParam;
+using autofill::features::kAutofillAblationStudyEnabledForAddressesParam;
+using autofill::features::kAutofillAblationStudyEnabledForPaymentsParam;
+using autofill::features::kAutofillEnableAblationStudy;
+
+namespace autofill {
+
+namespace {
+
+// Calls GetAblationGroup |n| times on different security origins and returns a
+// histogram of the number of times certain AblationGroups were returned.
+std::map<AblationGroup, int> RunNIterations(
+ const AutofillAblationStudy& study,
+ int n,
+ FormTypeForAblationStudy form_type) {
+ std::map<AblationGroup, int> result;
+ for (int i = 0; i < n; ++i) {
+ GURL url(base::StringPrintf("https://www.example%d.com", i));
+ AblationGroup ablation_group = study.GetAblationGroup(url, form_type);
+ result[ablation_group]++;
+ }
+ return result;
+}
+
+} // namespace
+
+class AutofillAblationStudyTest : public testing::Test {
+ public:
+ AutofillAblationStudyTest() = default;
+ ~AutofillAblationStudyTest() override = default;
+
+ base::Time GetDefaultTime() {
+ base::Time time;
+ CHECK(base::Time::FromString("Thu, 6 May 2021, 13:00:00 GMT", &time));
+ return time;
+ }
+
+ GURL GetDefaultUrl() { return GURL("https://www.example.com/home"); }
+};
+
+// Tests in UTC timezone.
+class AutofillAblationStudyTestInUTC : public AutofillAblationStudyTest {
+ public:
+ AutofillAblationStudyTestInUTC() = default;
+ ~AutofillAblationStudyTestInUTC() override = default;
+
+ void SetUp() override {
+ icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone("GMT"));
+
+ std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
+ ASSERT_EQ(0, zone->getRawOffset());
+ }
+
+ void TearDown() override { icu::TimeZone::adoptDefault(nullptr); }
+};
+
+TEST_F(AutofillAblationStudyTestInUTC, DaysSinceLocalWindowsEpoch) {
+ // Ensure that time zone alignment works out with the day boundaries of the
+ // loal timezone.
+ struct {
+ const char* time_string;
+ int expected_days_since_windows_epoch;
+ } kTests[] = {
+ {"Mon, 1 Jan 1601, 00:00:00 GMT", 0},
+ {"Mon, 1 Jan 1601, 01:00:00 GMT", 0},
+ {"Mon, 1 Jan 1601, 23:00:00 GMT", 0},
+ {"Tue, 2 Jan 1601, 00:00:00 GMT", 1},
+ {"Tue, 2 Jan 1601, 01:00:00 GMT", 1},
+ };
+ for (const auto& test : kTests) {
+ SCOPED_TRACE(test.time_string);
+ base::Time time;
+ ASSERT_TRUE(base::Time::FromString(test.time_string, &time));
+ EXPECT_EQ(test.expected_days_since_windows_epoch,
+ DaysSinceLocalWindowsEpoch(time));
+ }
+}
+
+// Tests in EST timezone.
+class AutofillAblationStudyTestInEST : public AutofillAblationStudyTest {
+ public:
+ AutofillAblationStudyTestInEST() = default;
+ ~AutofillAblationStudyTestInEST() override = default;
+
+ void SetUp() override {
+ icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone("EST"));
+
+ std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
+ ASSERT_EQ(-18000000, zone->getRawOffset());
+ }
+
+ void TearDown() override { icu::TimeZone::adoptDefault(nullptr); }
+};
+
+TEST_F(AutofillAblationStudyTestInEST, DaysSinceLocalWindowsEpoch) {
+ // Ensure that time zone alignment works out with the day boundaries of the
+ // loal timezone.
+ struct {
+ const char* time_string;
+ int expected_days_since_windows_epoch;
+ } kTests[] = {
+ {"Mon, 1 Jan 1601, 00:00:00 EST", 0},
+ {"Mon, 1 Jan 1601, 01:00:00 EST", 0},
+ {"Mon, 1 Jan 1601, 23:00:00 EST", 0},
+ {"Tue, 2 Jan 1601, 00:00:00 EST", 1},
+ {"Tue, 2 Jan 1601, 01:00:00 EST", 1},
+ };
+ for (const auto& test : kTests) {
+ SCOPED_TRACE(test.time_string);
+ base::Time time;
+ ASSERT_TRUE(base::Time::FromString(test.time_string, &time));
+ EXPECT_EQ(test.expected_days_since_windows_epoch,
+ DaysSinceLocalWindowsEpoch(time));
+ }
+}
+
+TEST_F(AutofillAblationStudyTestInUTC, GetAblationHash_IdenticalInput) {
+ EXPECT_EQ(GetAblationHash("seed1", GetDefaultUrl(), GetDefaultTime()),
+ GetAblationHash("seed1", GetDefaultUrl(), GetDefaultTime()));
+}
+
+TEST_F(AutofillAblationStudyTestInUTC, GetAblationHash_DependsOnSeed) {
+ // Different seeds produce different hashes.
+ EXPECT_NE(GetAblationHash("seed1", GetDefaultUrl(), GetDefaultTime()),
+ GetAblationHash("seed2", GetDefaultUrl(), GetDefaultTime()));
+}
+
+TEST_F(AutofillAblationStudyTestInUTC, GetAblationHash_DependsOnOrigin) {
+ // Different origins produce different hashes
+ base::Time t = GetDefaultTime();
+
+ // Different scheme
+ EXPECT_NE(GetAblationHash("seed", GURL("https://www.example.com"), t),
+ GetAblationHash("seed", GURL("http://www.example.com"), t));
+
+ // Different domain
+ EXPECT_NE(GetAblationHash("seed", GURL("https://www.example.com"), t),
+ GetAblationHash("seed", GURL("https://www.foo.com"), t));
+
+ // Different path makes no difference, the path is not part of the security
+ // origin.
+ EXPECT_EQ(GetAblationHash("seed", GURL("https://www.example.com"), t),
+ GetAblationHash("seed", GURL("https://www.example.com/a"), t));
+}
+
+TEST_F(AutofillAblationStudyTestInUTC, GetAblationHash_DependsOnDay) {
+ GURL url = GetDefaultUrl();
+ base::Time t = GetDefaultTime();
+
+ // 1 minute difference but not crossing the break of the day.
+ EXPECT_EQ(GetAblationHash("seed", url, t),
+ GetAblationHash("seed", url, t + base::TimeDelta::FromMinutes(1)));
+
+ // 1 day difference leads to crossing the break of the day.
+ EXPECT_NE(GetAblationHash("seed", url, t),
+ GetAblationHash("seed", url, t + base::TimeDelta::FromHours(24)));
+}
+
+// Ensure that if the feature is disabled, only kDefault is returned.
+TEST_F(AutofillAblationStudyTestInUTC, FeatureDisabled) {
+ base::test::ScopedFeatureList features;
+ features.InitAndDisableFeature(kAutofillEnableAblationStudy);
+ AutofillAblationStudy study;
+ auto result = RunNIterations(study, 100, FormTypeForAblationStudy::kAddress);
+ EXPECT_EQ(1u, result.size());
+ EXPECT_EQ(100, result[AblationGroup::kDefault]);
+}
+
+// Ensure that if the weight is invalid, only kDefault is returned.
+TEST_F(AutofillAblationStudyTestInUTC, InvalidParameters) {
+ base::test::ScopedFeatureList features;
+ AutofillAblationStudy study;
+ base::FieldTrialParams feature_parameters{
+ {kAutofillAblationStudyEnabledForAddressesParam.name, "true"},
+ {kAutofillAblationStudyEnabledForPaymentsParam.name, "true"},
+ // Ablation weight is > 1000 (the maximum)
+ {kAutofillAblationStudyAblationWeightPerMilleParam.name, "5000"},
+ };
+ features.InitAndEnableFeatureWithParameters(kAutofillEnableAblationStudy,
+ feature_parameters);
+ auto result = RunNIterations(study, 100, FormTypeForAblationStudy::kAddress);
+ EXPECT_EQ(1u, result.size());
+ EXPECT_EQ(100, result[AblationGroup::kDefault]);
+}
+
+// Ensure that if the feature is enabled but the individual form types are
+// disabled, only kDefault is returned.
+TEST_F(AutofillAblationStudyTestInUTC, FormTypesDisabled) {
+ base::test::ScopedFeatureList features;
+ base::FieldTrialParams feature_parameters{
+ {kAutofillAblationStudyEnabledForAddressesParam.name, "false"},
+ {kAutofillAblationStudyEnabledForPaymentsParam.name, "false"},
+ {kAutofillAblationStudyAblationWeightPerMilleParam.name, "1000"},
+ };
+ features.InitAndEnableFeatureWithParameters(kAutofillEnableAblationStudy,
+ feature_parameters);
+ AutofillAblationStudy study;
+ auto result = RunNIterations(study, 100, FormTypeForAblationStudy::kAddress);
+ EXPECT_EQ(1u, result.size());
+ EXPECT_EQ(100, result[AblationGroup::kDefault]);
+}
+
+// Perform some plausibility check if the feature is fully enabled.
+TEST_F(AutofillAblationStudyTestInUTC, IntegrationTest) {
+ base::test::ScopedFeatureList features;
+ base::FieldTrialParams feature_parameters{
+ {kAutofillAblationStudyEnabledForAddressesParam.name, "true"},
+ {kAutofillAblationStudyEnabledForPaymentsParam.name, "true"},
+ // 10% chance for ablation group, 10% chance for control group,
+ // 80% change for default group.
+ {kAutofillAblationStudyAblationWeightPerMilleParam.name, "100"},
+ };
+ features.InitAndEnableFeatureWithParameters(kAutofillEnableAblationStudy,
+ feature_parameters);
+ AutofillAblationStudy study;
+ auto result = RunNIterations(study, 1000, FormTypeForAblationStudy::kAddress);
+ EXPECT_EQ(3u, result.size());
+ // Note that these are not guaranteed but the chances are good enough that we
+ // can risk it.
+ EXPECT_NE(0, result[AblationGroup::kDefault]);
+ EXPECT_NE(0, result[AblationGroup::kAblation]);
+ EXPECT_NE(0, result[AblationGroup::kControl]);
+ EXPECT_LT(result[AblationGroup::kAblation] + result[AblationGroup::kControl],
+ result[AblationGroup::kDefault]);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_address_util.cc b/chromium/components/autofill/core/browser/autofill_address_util.cc
index 7add4dd0452..68585f86d93 100644
--- a/chromium/components/autofill/core/browser/autofill_address_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_address_util.cc
@@ -10,145 +10,226 @@
#include "base/check.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
+#include "base/ranges/algorithm.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
#include "components/autofill/core/browser/geo/autofill_country.h"
#include "components/autofill/core/browser/ui/country_combobox_model.h"
#include "components/autofill/core/common/autofill_features.h"
+#include "components/strings/grit/components_strings.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui_component.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/localization.h"
+#include "third_party/re2/src/re2/re2.h"
#include "ui/base/l10n/l10n_util.h"
using autofill::AutofillCountry;
using autofill::ServerFieldType;
+using i18n::addressinput::AddressField;
using i18n::addressinput::AddressUiComponent;
+using i18n::addressinput::Localization;
namespace autofill {
-// Dictionary keys for address components info.
-const char kFieldTypeKey[] = "field";
-const char kFieldLengthKey[] = "isLongField";
-const char kFieldNameKey[] = "fieldName";
-
-// Field names for the address components.
-const char kFullNameField[] = "FULL_NAME";
-const char kCompanyNameField[] = "COMPANY_NAME";
-const char kAddressLineField[] = "ADDRESS_LINES";
-const char kDependentLocalityField[] = "ADDRESS_LEVEL_3";
-const char kCityField[] = "ADDRESS_LEVEL_2";
-const char kStateField[] = "ADDRESS_LEVEL_1";
-const char kPostalCodeField[] = "POSTAL_CODE";
-const char kSortingCodeField[] = "SORTING_CODE";
-const char kCountryField[] = "COUNTY_CODE";
-
-// Address field length values.
-const bool kShortField = false;
-const bool kLongField = true;
-
-ServerFieldType GetFieldTypeFromString(const std::string& type) {
- if (type == kFullNameField)
- return NAME_FULL;
- if (type == kCompanyNameField)
- return COMPANY_NAME;
- if (type == kAddressLineField)
- return ADDRESS_HOME_STREET_ADDRESS;
- if (type == kDependentLocalityField)
- return ADDRESS_HOME_DEPENDENT_LOCALITY;
- if (type == kCityField)
- return ADDRESS_HOME_CITY;
- if (type == kStateField)
- return ADDRESS_HOME_STATE;
- if (type == kPostalCodeField)
- return ADDRESS_HOME_ZIP;
- if (type == kSortingCodeField)
- return ADDRESS_HOME_SORTING_CODE;
- if (type == kCountryField)
- return ADDRESS_HOME_COUNTRY;
+namespace {
+
+// Returns a vector of AddressUiComponent for `country_code` when using
+// `ui_language_code`. If no components are available for `country_code`, it
+// defaults back to the US. If `ui_language_code` is not valid, the default
+// format is returned.
+std::vector<AddressUiComponent> GetAddressComponents(
+ const std::string& country_code,
+ const std::string& ui_language_code,
+ std::string* components_language_code) {
+ DCHECK(components_language_code);
+
+ // Return strings in the current application locale.
+ Localization localization;
+ localization.SetGetter(l10n_util::GetStringUTF8);
+ for (const auto& country : {country_code, std::string("US")}) {
+ std::vector<AddressUiComponent> components =
+ ::i18n::addressinput::BuildComponentsWithLiterals(
+ country, localization, ui_language_code, components_language_code);
+ if (!components.empty())
+ return components;
+ }
NOTREACHED();
- return UNKNOWN_TYPE;
+ return {};
}
-// Fills |components| with the address UI components that should be used to
-// input an address for |country_code| when UI BCP 47 language code is
-// |ui_language_code|. If |components_language_code| is not NULL, then sets it
-// to the BCP 47 language code that should be used to format the address for
-// display.
-void GetAddressComponents(const std::string& country_code,
- const std::string& ui_language_code,
- base::ListValue* address_components,
- std::string* components_language_code) {
- DCHECK(address_components);
-
- ::i18n::addressinput::Localization localization;
- localization.SetGetter(l10n_util::GetStringUTF8);
- std::string not_used;
- std::vector<AddressUiComponent> components =
- ::i18n::addressinput::BuildComponents(
- country_code, localization, ui_language_code,
- components_language_code ? components_language_code : &not_used);
- if (components.empty()) {
- static const char kDefaultCountryCode[] = "US";
- components = ::i18n::addressinput::BuildComponents(
- kDefaultCountryCode, localization, ui_language_code,
- components_language_code ? components_language_code : &not_used);
+} // namespace
+
+ServerFieldType AddressFieldToServerFieldType(AddressField address_field) {
+ switch (address_field) {
+ case ::i18n::addressinput::COUNTRY:
+ return ADDRESS_HOME_COUNTRY;
+ case ::i18n::addressinput::ADMIN_AREA:
+ return ADDRESS_HOME_STATE;
+ case ::i18n::addressinput::LOCALITY:
+ return ADDRESS_HOME_CITY;
+ case ::i18n::addressinput::DEPENDENT_LOCALITY:
+ return ADDRESS_HOME_DEPENDENT_LOCALITY;
+ case ::i18n::addressinput::SORTING_CODE:
+ return ADDRESS_HOME_SORTING_CODE;
+ case ::i18n::addressinput::POSTAL_CODE:
+ return ADDRESS_HOME_ZIP;
+ case ::i18n::addressinput::STREET_ADDRESS:
+ return ADDRESS_HOME_STREET_ADDRESS;
+ case ::i18n::addressinput::ORGANIZATION:
+ return COMPANY_NAME;
+ case ::i18n::addressinput::RECIPIENT:
+ return NAME_FULL;
}
- DCHECK(!components.empty());
+}
- base::ListValue* line = nullptr;
- for (size_t i = 0; i < components.size(); ++i) {
- if (i == 0 ||
- components[i - 1].length_hint == AddressUiComponent::HINT_LONG ||
- components[i].length_hint == AddressUiComponent::HINT_LONG) {
- line = new base::ListValue;
- address_components->Append(std::unique_ptr<base::ListValue>(line));
- // |line| is invalidated at this point, so it needs to be reset.
- address_components->GetList(address_components->GetSize() - 1, &line);
+void GetAddressComponents(
+ const std::string& country_code,
+ const std::string& ui_language_code,
+ bool include_literals,
+ std::vector<std::vector<AddressUiComponent>>* address_components,
+ std::string* components_language_code) {
+ std::string not_used;
+ std::vector<AddressUiComponent> components = GetAddressComponents(
+ country_code, ui_language_code,
+ components_language_code ? components_language_code : &not_used);
+ std::vector<AddressUiComponent>* line_components = nullptr;
+ for (const AddressUiComponent& component : components) {
+ // Start a new line of this is the first line, or a new line literal exists.
+ if (!line_components || component.literal == "\n") {
+ address_components->push_back(std::vector<AddressUiComponent>());
+ line_components = &address_components->back();
}
- auto component = std::make_unique<base::DictionaryValue>();
- component->SetString(kFieldNameKey, components[i].name);
-
- switch (components[i].field) {
- case ::i18n::addressinput::COUNTRY:
- component->SetString(kFieldTypeKey, kCountryField);
- break;
- case ::i18n::addressinput::ADMIN_AREA:
- component->SetString(kFieldTypeKey, kStateField);
- break;
- case ::i18n::addressinput::LOCALITY:
- component->SetString(kFieldTypeKey, kCityField);
- break;
- case ::i18n::addressinput::DEPENDENT_LOCALITY:
- component->SetString(kFieldTypeKey, kDependentLocalityField);
- break;
- case ::i18n::addressinput::SORTING_CODE:
- component->SetString(kFieldTypeKey, kSortingCodeField);
- break;
- case ::i18n::addressinput::POSTAL_CODE:
- component->SetString(kFieldTypeKey, kPostalCodeField);
- break;
- case ::i18n::addressinput::STREET_ADDRESS:
- component->SetString(kFieldTypeKey, kAddressLineField);
- break;
- case ::i18n::addressinput::ORGANIZATION:
- component->SetString(kFieldTypeKey, kCompanyNameField);
- break;
- case ::i18n::addressinput::RECIPIENT:
- component->SetString(kFieldTypeKey, kFullNameField);
- break;
+ if (!component.literal.empty()) {
+ if (!include_literals)
+ continue;
+ // No need to return new line literals since components are split into
+ // different lines anyway (one line per vector).
+ if (component.literal == "\n")
+ continue;
}
- switch (components[i].length_hint) {
- case AddressUiComponent::HINT_LONG:
- component->SetBoolean(kFieldLengthKey, kLongField);
- break;
- case AddressUiComponent::HINT_SHORT:
- component->SetBoolean(kFieldLengthKey, kShortField);
- break;
+ line_components->push_back(component);
+ }
+}
+
+std::u16string GetEnvelopeStyleAddress(const AutofillProfile& profile,
+ const std::string& ui_language_code,
+ bool include_recipient,
+ bool include_country) {
+ const AutofillType kCountryCode(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE);
+ const std::u16string& country_code =
+ profile.GetInfo(kCountryCode, ui_language_code);
+
+ std::string not_used;
+ std::vector<AddressUiComponent> components = GetAddressComponents(
+ base::UTF16ToUTF8(country_code), ui_language_code, &not_used);
+
+ DCHECK(!components.empty());
+ std::string address;
+ for (const AddressUiComponent& component : components) {
+ // Add string literals directly.
+ if (!component.literal.empty()) {
+ address += component.literal;
+ continue;
+ }
+ if (!include_recipient &&
+ component.field == ::i18n::addressinput::RECIPIENT) {
+ continue;
}
+ ServerFieldType type =
+ autofill::AddressFieldToServerFieldType(component.field);
+ if (type == NAME_FULL)
+ type = NAME_FULL_WITH_HONORIFIC_PREFIX;
+ address += base::UTF16ToUTF8(profile.GetInfo(type, ui_language_code));
+ }
+ if (include_country) {
+ address += "\n";
+ address += base::UTF16ToUTF8(
+ profile.GetInfo(ADDRESS_HOME_COUNTRY, ui_language_code));
+ }
+
+ // Remove all white spaces and new lines from the beginning and the end of the
+ // address.
+ base::TrimString(address, base::kWhitespaceASCII, &address);
+
+ // Collapse new lines to remove empty lines.
+ re2::RE2::GlobalReplace(&address, re2::RE2("\\n+"), "\n");
+
+ // Collapse white spaces.
+ re2::RE2::GlobalReplace(&address, re2::RE2("[ ]+"), " ");
- line->Append(std::move(component));
+ return base::UTF8ToUTF16(address);
+}
+
+std::u16string GetProfileDescription(const AutofillProfile& profile,
+ const std::string& ui_language_code,
+ bool include_address_and_contacts) {
+ // All user-visible fields.
+ static constexpr ServerFieldType kDetailsFields[] = {
+ NAME_FULL,
+ ADDRESS_HOME_LINE1,
+ ADDRESS_HOME_LINE2,
+ ADDRESS_HOME_DEPENDENT_LOCALITY,
+ ADDRESS_HOME_CITY,
+ ADDRESS_HOME_STATE,
+ ADDRESS_HOME_ZIP,
+ EMAIL_ADDRESS,
+ PHONE_HOME_WHOLE_NUMBER,
+ COMPANY_NAME,
+ ADDRESS_HOME_COUNTRY};
+
+ if (!include_address_and_contacts) {
+ return profile.GetInfo(NAME_FULL, ui_language_code);
+ }
+
+ return profile.ConstructInferredLabel(
+ kDetailsFields, base::size(kDetailsFields),
+ /*num_fields_to_include=*/2, ui_language_code);
+}
+
+std::vector<ProfileValueDifference> GetProfileDifferenceForUi(
+ const AutofillProfile& first_profile,
+ const AutofillProfile& second_profile,
+ const std::string& app_locale) {
+ static constexpr ServerFieldType kTypeToCompare[] = {
+ NAME_FULL_WITH_HONORIFIC_PREFIX, ADDRESS_HOME_ADDRESS, EMAIL_ADDRESS,
+ PHONE_HOME_WHOLE_NUMBER};
+
+ base::flat_map<ServerFieldType, std::pair<std::u16string, std::u16string>>
+ differences = AutofillProfileComparator::GetProfileDifferenceMap(
+ first_profile, second_profile,
+ autofill::ServerFieldTypeSet(std::begin(kTypeToCompare),
+ std::end(kTypeToCompare)),
+ app_locale);
+
+ std::u16string first_address = GetEnvelopeStyleAddress(
+ first_profile, app_locale, /*include_recipient=*/false,
+ /*include_country=*/true);
+ std::u16string second_address = GetEnvelopeStyleAddress(
+ second_profile, app_locale, /*include_recipient=*/false,
+ /*include_country=*/true);
+
+ std::vector<ProfileValueDifference> differences_for_ui;
+ for (ServerFieldType type : kTypeToCompare) {
+ // Address is handled seprately.
+ if (type == ADDRESS_HOME_ADDRESS) {
+ if (first_address != second_address) {
+ differences_for_ui.emplace_back(
+ ProfileValueDifference{type, first_address, second_address});
+ }
+ continue;
+ }
+ auto it = differences.find(type);
+ if (it == differences.end())
+ continue;
+ differences_for_ui.emplace_back(
+ ProfileValueDifference{type, it->second.first, it->second.second});
}
+ return differences_for_ui;
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_address_util.h b/chromium/components/autofill/core/browser/autofill_address_util.h
index 1e8b93f76d0..54012523564 100644
--- a/chromium/components/autofill/core/browser/autofill_address_util.h
+++ b/chromium/components/autofill/core/browser/autofill_address_util.h
@@ -7,73 +7,77 @@
#include <string>
+#include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
#include "components/autofill/core/browser/field_types.h"
-
-namespace base {
-class ListValue;
-class DictionaryValue;
-}
+#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui_component.h"
namespace autofill {
+class AutofillProfile;
class PersonalDataManager;
-// Dictionary key for the field type.
-extern const char kFieldTypeKey[];
-
-// Dictionary key for the field length.
-extern const char kFieldLengthKey[];
-
-// Dictionary key for the field name.
-extern const char kFieldNameKey[];
-
-// Field name for autofill::NAME_FULL.
-extern const char kFullNameField[];
-
-// Field name for autofill::COMPANY_NAME.
-extern const char kCompanyNameField[];
-
-// Field name for autofill::ADDRESS_HOME_STREET_ADDRESS.
-extern const char kAddressLineField[];
-
-// Field name for autofill::ADDRESS_HOME_DEPENDENT_LOCALITY.
-extern const char kDependentLocalityField[];
-
-// Field name for autofill::ADDRESS_HOME_CITY.
-extern const char kCityField[];
-
-// Field name for autofill::ADDRESS_HOME_STATE.
-extern const char kStateField[];
-
-// Field name for autofill::ADDRESS_HOME_ZIP.
-extern const char kPostalCodeField[];
-
-// Field name for autofill::ADDRESS_HOME_SORTING_CODE.
-extern const char kSortingCodeField[];
-
-// Field name for autofill::ADDRESS_HOME_COUNTRY.
-extern const char kCountryField[];
-
-// AddressUiComponent::HINT_SHORT.
-extern const bool kShortField;
-
-// AddressUiComponent::HINT_LONG.
-extern const bool kLongField;
-
-// Converts a field type in string format as returned by
-// autofill::GetAddressComponents into the appropriate autofill::ServerFieldType
-// enum.
-ServerFieldType GetFieldTypeFromString(const std::string& type);
+ServerFieldType AddressFieldToServerFieldType(
+ ::i18n::addressinput::AddressField address_field);
-// Fills |components| with the address UI components that should be used to
-// input an address for |country_code| when UI BCP 47 language code is
+// |address_components| is a 2D array for the address components in each line.
+// Fills |address_components| with the address UI components that should be used
+// to input an address for |country_code| when UI BCP 47 language code is
// |ui_language_code|. If |components_language_code| is not NULL, then sets it
// to the BCP 47 language code that should be used to format the address for
-// display.
-void GetAddressComponents(const std::string& country_code,
- const std::string& ui_language_code,
- base::ListValue* address_components,
- std::string* components_language_code);
+// display. If no components are available for |country_code|, it defaults back
+// to the US. |include_literals| controls whether formatting literals such as
+// ", " and "-" should be returned.
+void GetAddressComponents(
+ const std::string& country_code,
+ const std::string& ui_language_code,
+ bool include_literals,
+ std::vector<std::vector<::i18n::addressinput::AddressUiComponent>>*
+ address_components,
+ std::string* components_language_code);
+
+// Returns the address stored in `profile` when UI BCP 47 language code is
+// `ui_language_code`. If the format of the country in `profile` isn't known,
+// the US address format is used instead. If `ui_language_code` is not valid,
+// the default format is returned. If `include_recipient` is true, the recipient
+// full name will be included. If `include_country` is true, the country
+// will be appended in a separate line at the end.
+std::u16string GetEnvelopeStyleAddress(const AutofillProfile& profile,
+ const std::string& ui_language_code,
+ bool include_recipient,
+ bool include_country);
+
+// Returns a one-line `profile` description, listing (at max) 2 significant
+// user-visible fields with respect to UI BCP 47 language code in
+// `ui_language_code`. If `include_address_and_contacts` is false, only full
+// name is included, and the returned string can be empty if the name is not
+// present.
+std::u16string GetProfileDescription(const AutofillProfile& profile,
+ const std::string& ui_language_code,
+ bool include_address_and_contacts);
+
+// Fields in order they should appear in differences for AutofillProfile update.
+static constexpr ServerFieldType kVisibleTypesForProfileDifferences[] = {
+ NAME_FULL_WITH_HONORIFIC_PREFIX,
+ COMPANY_NAME,
+ ADDRESS_HOME_STREET_ADDRESS,
+ ADDRESS_HOME_DEPENDENT_LOCALITY,
+ ADDRESS_HOME_CITY,
+ ADDRESS_HOME_STATE,
+ ADDRESS_HOME_ZIP,
+ ADDRESS_HOME_COUNTRY,
+ EMAIL_ADDRESS,
+ PHONE_HOME_WHOLE_NUMBER};
+
+// Gets the difference of two profiles in name, address, email and phone number
+// in that order. Differences in name, email and phone number are computed and
+// keyed by NAME_FULL_WITH_HONORIFIC_PREFIX, EMAIL_ADDRESS and
+// PHONE_HOME_WHOLE_NUMBER respectively. Address differences are computed by
+// difference in the envelope style address of both profile, and keyed by
+// ADDRESS_HOME_ADDRESS. All computations are done against `app_locale`.
+std::vector<ProfileValueDifference> GetProfileDifferenceForUi(
+ const AutofillProfile& first_profile,
+ const AutofillProfile& second_profile,
+ const std::string& app_locale);
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_address_util_unittest.cc b/chromium/components/autofill/core/browser/autofill_address_util_unittest.cc
new file mode 100644
index 00000000000..eb2c215a755
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_address_util_unittest.cc
@@ -0,0 +1,189 @@
+// Copyright 2021 The Chromium Authors. 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_address_util.h"
+
+#include "base/guid.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace autofill {
+
+using ::testing::ElementsAre;
+
+class GetEnvelopeStyleAddressTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ orig_resource_bundle_ =
+ ui::ResourceBundle::SwapSharedInstanceForTesting(nullptr);
+ ui::ResourceBundle::InitSharedInstanceWithLocale(
+ GetLocale(), /*delegate=*/nullptr,
+ ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES);
+ }
+
+ void TearDown() override {
+ ui::ResourceBundle::CleanupSharedInstance();
+ ui::ResourceBundle::SwapSharedInstanceForTesting(orig_resource_bundle_);
+ }
+
+ std::string GetLocale() { return "en-US"; }
+
+ private:
+ ui::ResourceBundle* orig_resource_bundle_;
+};
+
+TEST_F(GetEnvelopeStyleAddressTest, Sanity) {
+ AutofillProfile profile = test::GetFullProfile();
+ std::u16string address =
+ GetEnvelopeStyleAddress(profile, GetLocale(), /*include_recipient=*/true,
+ /*include_country=*/true);
+
+ // The exact format of the address depends on the format in the
+ // libaddressinput library. Let's avoid testing the exact format, but test
+ // some more highlevel conditions that are less probable to change.
+
+ // The full name should be part of the envelope style address.
+ EXPECT_NE(address.find(
+ profile.GetInfo(NAME_FULL_WITH_HONORIFIC_PREFIX, GetLocale())),
+ std::string::npos);
+
+ // City should be part of the envelope style address.
+ EXPECT_NE(address.find(profile.GetInfo(ADDRESS_HOME_CITY, GetLocale())),
+ std::string::npos);
+
+ // Check that some literals are properly returned.
+ // The US envelope style address should contain a comma.
+ EXPECT_NE(address.find(u","), std::string::npos);
+
+ // The US envelope style address should contains at least one newline.
+ EXPECT_NE(address.find(u"\n"), std::string::npos);
+
+ // The country should be returned.
+ EXPECT_NE(address.find(u"United States"), std::string::npos);
+
+ // The country shouldn't be returned when include_country=false.
+ EXPECT_EQ(
+ GetEnvelopeStyleAddress(profile, GetLocale(), /*include_recipient=*/true,
+ /*include_country=*/false)
+ .find(u"United States"),
+ std::string::npos);
+
+ // The recipient shouldn't be returned when include_recipient=false.
+ EXPECT_EQ(
+ GetEnvelopeStyleAddress(profile, GetLocale(), /*include_recipient=*/false,
+ /*include_country=*/true)
+ .find(u"John H. Doe"),
+ std::string::npos);
+}
+
+TEST_F(GetEnvelopeStyleAddressTest, EmptyFullname) {
+ AutofillProfile profile(base::GenerateGUID(), /*origin=*/"");
+ test::SetProfileInfo(&profile, /*first_name=*/"", /*middle_name=*/"",
+ /*last_name=*/"", "johndoe@hades.com", "Underworld",
+ "666 Erebus St.", "Apt 8", "Elysium", "CA", "91111",
+ "US", "16502111111");
+
+ std::u16string address =
+ GetEnvelopeStyleAddress(profile, GetLocale(), /*include_recipient=*/true,
+ /*include_country=*/true);
+ // The US envelope style address should *not* start with a new line.
+ EXPECT_NE(address.front(), '\n');
+}
+
+// Tests that when the company is empty, the envelope style address doesn't
+// contain empty lines.
+TEST_F(GetEnvelopeStyleAddressTest, EmptyCompanyShouldHaveNoEmptyLines) {
+ AutofillProfile profile(base::GenerateGUID(), /*origin=*/"");
+ test::SetProfileInfo(&profile, "FirstName", "MiddleName", "LastName",
+ "johndoe@hades.com", /*company=*/"", "666 Erebus St.",
+ "Apt 8", "Elysium", "CA", "91111", "US", "16502111111");
+
+ std::u16string address =
+ GetEnvelopeStyleAddress(profile, GetLocale(), /*include_recipient=*/true,
+ /*include_country=*/true);
+ // There should be no consecutive new lines.
+ EXPECT_EQ(address.find(u"\n\n"), std::string::npos);
+}
+
+// Tests that when the state is empty, the envelope style address doesn't
+// contains consecutive white spaces.
+TEST_F(GetEnvelopeStyleAddressTest,
+ EmptyStateShouldHaveNoConsecutiveWhitespaces) {
+ AutofillProfile profile(base::GenerateGUID(), /*origin=*/"");
+ test::SetProfileInfo(&profile, "FirstName", "MiddleName", "LastName",
+ "johndoe@hades.com", "Underworld", "666 Erebus St.",
+ "Apt 8", "Elysium", /*state=*/"", "91111", "US",
+ "16502111111");
+
+ std::u16string address =
+ GetEnvelopeStyleAddress(profile, GetLocale(), /*include_recipient=*/true,
+ /*include_country=*/true);
+ // There should be no consecutive white spaces.
+ EXPECT_EQ(address.find(u" "), std::string::npos);
+}
+
+TEST_F(GetEnvelopeStyleAddressTest, NoDifferencesBetweenIdenticalProfiles) {
+ AutofillProfile profile = test::GetFullProfile();
+ EXPECT_TRUE(GetProfileDifferenceForUi(profile, profile, "en-US").empty());
+}
+
+TEST_F(GetEnvelopeStyleAddressTest, DiffereceInUiWhenFullnameDiffers) {
+ AutofillProfile profile1 = test::GetFullProfile();
+ profile1.SetInfo(NAME_FULL, u"John H. Doe", "en-US");
+
+ AutofillProfile profile2 = profile1;
+ profile2.SetInfo(NAME_FULL, u"John Doe", "en-US");
+
+ EXPECT_THAT(
+ GetProfileDifferenceForUi(profile1, profile2, "en-US"),
+ ElementsAre(ProfileValueDifference{NAME_FULL_WITH_HONORIFIC_PREFIX,
+ u"John H. Doe", u"John Doe"}));
+}
+
+TEST_F(GetEnvelopeStyleAddressTest, DiffereceInUiWhenZipcodeDiffers) {
+ AutofillProfile profile1 = test::GetFullProfile();
+ profile1.SetInfo(ADDRESS_HOME_ZIP, u"91111", "en-US");
+
+ AutofillProfile profile2 = profile1;
+ profile2.SetInfo(ADDRESS_HOME_ZIP, u"90000", "en-US");
+
+ EXPECT_THAT(GetProfileDifferenceForUi(profile1, profile2, "en-US"),
+ ElementsAre(ProfileValueDifference{
+ ADDRESS_HOME_ADDRESS,
+ GetEnvelopeStyleAddress(profile1, "en-US",
+ /*include_recipient=*/false,
+ /*include_country=*/true),
+ GetEnvelopeStyleAddress(profile2, "en-US",
+ /*include_recipient=*/false,
+ /*include_country=*/true)}));
+}
+
+TEST(GetProfileDescription, NameAndAddress) {
+ AutofillProfile profile = test::GetFullProfile();
+ std::u16string description = GetProfileDescription(
+ profile, "en-US", /*include_address_and_contacts=*/true);
+ // Should contain full name and address line 1.
+ EXPECT_EQ(description, u"John H. Doe, 666 Erebus St.");
+}
+
+TEST(GetProfileDescription, EmptyName) {
+ AutofillProfile profile = test::GetFullProfile();
+ profile.SetInfo(NAME_FULL, u"", "en-US");
+ std::u16string description = GetProfileDescription(
+ profile, "en-US", /*include_address_and_contacts=*/true);
+ // Should contain 2 address components: address lines 1 & 2.
+ EXPECT_EQ(description, u"666 Erebus St., Apt 8");
+}
+
+TEST(GetProfileDescription, NotIncludeAddressAndContacts) {
+ AutofillProfile profile = test::GetFullProfile();
+ std::u16string description = GetProfileDescription(
+ profile, "en-US", /*include_address_and_contacts=*/false);
+ // Should contain full name only.
+ EXPECT_EQ(description, u"John H. Doe");
+}
+
+} // namespace autofill
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 d1c504917a3..0cb9484f6ce 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
@@ -134,6 +134,14 @@ html {
background-color: #BFFBF2;
}
+.log-entry[scope='CreditCardUploadStatus'] {
+ background-color: #4DB6AC;
+}
+
+.log-entry[scope='CardUploadDecision'] {
+ background-color: #4DD0E1;
+}
+
/*
* Checkboxes add/remove hide-<Scope> classes to the #log-entries. Hiding of the
@@ -180,6 +188,16 @@ html {
display: none;
}
+.hide-CreditCardUploadStatus .log-entry[scope='CreditCardUploadStatus'],
+.hide-CreditCardUploadStatus .log-entry[scope='CreditCardUploadStatus'] + hr {
+ display: none;
+}
+
+.hide-CardUploadDecision .log-entry[scope='CardUploadDecision'],
+.hide-CardUploadDecision .log-entry[scope='CardUploadDecision'] + hr {
+ display: none;
+}
+
.form {
border: 1px black solid;
margin: 3px;
diff --git a/chromium/components/autofill/core/browser/autofill_client.cc b/chromium/components/autofill/core/browser/autofill_client.cc
index 1f72eb155c4..a13ad2619bc 100644
--- a/chromium/components/autofill/core/browser/autofill_client.cc
+++ b/chromium/components/autofill/core/browser/autofill_client.cc
@@ -4,7 +4,9 @@
#include "components/autofill/core/browser/autofill_client.h"
+#include "base/no_destructor.h"
#include "base/stl_util.h"
+#include "components/autofill/core/browser/autofill_ablation_study.h"
#include "components/autofill/core/browser/ui/suggestion.h"
#include "components/version_info/channel.h"
@@ -59,11 +61,15 @@ AutofillClient::CreateCreditCardInternalAuthenticator(
#endif
void AutofillClient::ShowOfferNotificationIfApplicable(
- const std::vector<GURL>& domains_to_display_bubble,
- const GURL& offer_details_url,
- const CreditCard* card) {
+ const AutofillOfferData* offer) {
// This is overridden by platform subclasses. Currently only
- // ChromeAutofillClient (Chrome Desktop and Clank) implement this.
+ // ChromeAutofillClient (Chrome Desktop and Clank) implements this.
+}
+
+void AutofillClient::OnVirtualCardFetched(const CreditCard* credit_card,
+ const std::u16string& cvc) {
+ // This is overridden by platform subclasses. Currently only
+ // ChromeAutofillClient (Chrome Desktop & Android) implements this.
}
bool AutofillClient::IsAutofillAssistantShowing() {
@@ -74,4 +80,10 @@ LogManager* AutofillClient::GetLogManager() const {
return nullptr;
}
+const AutofillAblationStudy& AutofillClient::GetAblationStudy() const {
+ // As finch configs are profile independent we can use a static instance here.
+ static base::NoDestructor<AutofillAblationStudy> ablation_study;
+ return *ablation_study;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_client.h b/chromium/components/autofill/core/browser/autofill_client.h
index 36894e498b2..98c2b6cb3b7 100644
--- a/chromium/components/autofill/core/browser/autofill_client.h
+++ b/chromium/components/autofill/core/browser/autofill_client.h
@@ -15,7 +15,6 @@
#include "base/i18n/rtl.h"
#include "base/memory/weak_ptr.h"
#include "base/types/strong_alias.h"
-#include "base/values.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/payments/legal_message_line.h"
#include "components/autofill/core/browser/payments/risk_data_loader.h"
@@ -58,6 +57,7 @@ enum class Channel;
namespace autofill {
class AddressNormalizer;
+class AutofillAblationStudy;
class AutofillProfile;
class AutocompleteHistoryManager;
class AutofillOfferManager;
@@ -72,6 +72,7 @@ class PersonalDataManager;
class StrikeDatabase;
enum class WebauthnDialogCallbackType;
enum class WebauthnDialogState;
+struct AutofillOfferData;
struct Suggestion;
namespace payments {
@@ -82,9 +83,9 @@ class PaymentsClient;
// embedder.
//
// Each client instance is associated with a given context within which an
-// AutofillManager is used (e.g. a single tab), so when we say "for the client"
-// below, we mean "in the execution context the client is associated with" (e.g.
-// for the tab the AutofillManager is attached to).
+// BrowserAutofillManager is used (e.g. a single tab), so when we say "for the
+// client" below, we mean "in the execution context the client is associated
+// with" (e.g. for the tab the BrowserAutofillManager is attached to).
class AutofillClient : public RiskDataLoader {
public:
enum PaymentsRpcResult {
@@ -136,10 +137,32 @@ class AutofillClient : public RiskDataLoader {
};
enum class SaveAddressProfileOfferUserDecision {
+ kUndefined,
+ // No prompt is shown and no decision is needed to proceed with the process.
+ kUserNotAsked,
+ // The user accepted the save/update flow from the initial prompt.
kAccepted,
- kEdited,
+ // The user declined the save/update flow from the initial prompt.
kDeclined,
+ // The user accepted the save/update flow from the edit dialog.
+ kEditAccepted,
+ // The user declined the save/update flow from the edit dialog.
+ kEditDeclined,
+ // The user selected to never save a new profile on a given domain or update
+ // a specific profile (currently not supported).
+ kNever,
+ // The user ignored the prompt.
kIgnored,
+ // The save/update message timed out before the user interacted. This is
+ // only relevant on mobile.
+ kMessageTimeout,
+ // The user swipes away the save/update Message. This is only relevant on
+ // mobile.
+ kMessageDeclined,
+ // The prompt is suppressed most likely because there is already another
+ // prompt shown on the same tab.
+ kAutoDeclined,
+ kMaxValue = kAutoDeclined,
};
// Used for explicitly requesting the user to enter/confirm cardholder name,
@@ -185,6 +208,11 @@ class AutofillClient : public RiskDataLoader {
bool show_prompt = false;
};
+ // Used for options of save (and update) address profile prompt.
+ struct SaveAddressProfilePromptOptions {
+ bool show_prompt = true;
+ };
+
// Required arguments to create a dropdown showing autofill suggestions.
struct PopupOpenArgs {
using AutoselectFirstSuggestion =
@@ -313,8 +341,6 @@ class AutofillClient : public RiskDataLoader {
virtual std::string GetVariationConfigCountryCode() const;
// Returns the profile type of the session.
- // TODO(https://crbug.com/1169142): Replace by getting profile type directly
- // from BrowserContext.
virtual profile_metrics::BrowserProfileType GetProfileType() const;
#if !defined(OS_IOS)
@@ -456,10 +482,16 @@ class AutofillClient : public RiskDataLoader {
virtual void ConfirmCreditCardFillAssist(const CreditCard& card,
base::OnceClosure callback) = 0;
- // Shows the offer-to-save address profile bubble. Runs |callback| once the
- // user makes a decision with respect to the offer-to-save prompt.
+ // Shows the offer-to-save (or update) address profile bubble. If
+ // `original_profile` is nullptr, this renders a save prompt. Otherwise, it
+ // renders an update prompt where `original_profile` is the address profile
+ // that will be updated if the user accepts the update prompt. Runs `callback`
+ // once the user makes a decision with respect to the offer-to-save prompt.
+ // `options` carries extra configuration options for the prompt.
virtual void ConfirmSaveAddressProfile(
const AutofillProfile& profile,
+ const AutofillProfile* original_profile,
+ AutofillClient::SaveAddressProfilePromptOptions options,
AddressProfileSavePromptCallback callback) = 0;
// Returns true if both the platform and the device support scanning credit
@@ -509,14 +541,14 @@ class AutofillClient : public RiskDataLoader {
// Will show a bubble or infobar indicating that the current web domain has an
// eligible offer or reward if no other notification bubble is currently
// visible. See bubble controller for details. The bubble is sticky over a set
- // of domains given in |domains_to_display_bubble|. The bubble displays the
- // information of the |card| if the offer is card-related. On mobile, the
- // bubble also shows the |offer_details_url| as a link which has more
- // information about the offer.
+ // of domains given in the offer.
virtual void ShowOfferNotificationIfApplicable(
- const std::vector<GURL>& domains_to_display_bubble,
- const GURL& offer_details_url,
- const CreditCard* card);
+ const AutofillOfferData* offer);
+
+ // Indicates that the virtual card was fetched in order to allow the user to
+ // manually fill payment form with the fetched |credit_card| and |cvc|.
+ virtual void OnVirtualCardFetched(const CreditCard* credit_card,
+ const std::u16string& cvc);
// Returns true if the Autofill Assistant UI is currently being shown.
virtual bool IsAutofillAssistantShowing();
@@ -552,8 +584,10 @@ class AutofillClient : public RiskDataLoader {
// this.
virtual LogManager* GetLogManager() const;
+ virtual const AutofillAblationStudy& GetAblationStudy() const;
+
#if defined(OS_IOS)
- // Checks whether the qurrent query is the most recent one.
+ // Checks whether the current query is the most recent one.
virtual bool IsQueryIDRelevant(int query_id) = 0;
#endif
};
diff --git a/chromium/components/autofill/core/browser/autofill_download_manager.cc b/chromium/components/autofill/core/browser/autofill_download_manager.cc
index b7fa97bf3b0..a204abac8a6 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager.cc
@@ -100,7 +100,7 @@ const char kDefaultAutofillServerURL[] =
// The default number of days after which to reset the registry of autofill
// events for which an upload has been sent.
-constexpr base::FeatureParam<int> kAutofillUploadThrottlingPeriodInDays(
+const base::FeatureParam<int> kAutofillUploadThrottlingPeriodInDays(
&features::kAutofillUploadThrottling,
switches::kAutofillUploadThrottlingPeriodInDays,
28);
@@ -114,7 +114,7 @@ constexpr char kGoogEncodeResponseIfExecutable[] =
constexpr char kDefaultAPIKey[] = "";
// The maximum number of attempts for a given autofill request.
-constexpr base::FeatureParam<int> kAutofillMaxServerAttempts(
+const base::FeatureParam<int> kAutofillMaxServerAttempts(
&features::kAutofillServerCommunication,
"max-attempts",
5);
@@ -778,8 +778,7 @@ std::tuple<GURL, std::string> AutofillDownloadManager::GetRequestURLAndMethod(
std::string query_str;
if (request_data.request_type == AutofillDownloadManager::REQUEST_QUERY) {
- if (request_data.payload.length() <= kMaxQueryGetSize &&
- base::FeatureList::IsEnabled(features::kAutofillCacheQueryResponses)) {
+ if (request_data.payload.length() <= kMaxQueryGetSize) {
method = "GET";
std::string base64_payload;
base::Base64UrlEncode(request_data.payload,
@@ -808,8 +807,7 @@ AutofillDownloadManager::GetRequestURLAndMethodForApi(
std::string method = "POST";
if (request_data.request_type == AutofillDownloadManager::REQUEST_QUERY) {
- if (GetPayloadLength(request_data.payload) <= kMaxAPIQueryGetSize &&
- base::FeatureList::IsEnabled(features::kAutofillCacheQueryResponses)) {
+ if (GetPayloadLength(request_data.payload) <= kMaxAPIQueryGetSize) {
resource_id = request_data.payload;
method = "GET";
UMA_HISTOGRAM_BOOLEAN("Autofill.Query.ApiUrlIsTooLong", false);
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 ddaf6fd8c7f..1f742aa0b98 100644
--- a/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -257,9 +257,6 @@ class AutofillDownloadManagerTest : public AutofillDownloadManager::Observer,
};
TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
- base::test::ScopedFeatureList fl;
- fl.InitAndEnableFeature(features::kAutofillCacheQueryResponses);
-
FormData form;
FormFieldData field;
@@ -495,28 +492,6 @@ TEST_F(AutofillDownloadManagerTest, QueryAndUploadTest) {
AutofillDownloadManagerTest::QUERY_SUCCESSFULL);
responses_.pop_front();
histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_HIT, 1);
-
- // Test query with caching disabled.
- base::test::ScopedFeatureList fl2;
- fl2.InitAndDisableFeature(features::kAutofillCacheQueryResponses);
-
- // Don't hit the in-mem cache.
- field.label = u"Address line 3";
- field.name = u"address3";
- field.form_control_type = "text";
- form.fields.push_back(field);
- form_structures.push_back(std::make_unique<FormStructure>(form));
-
- // Request with id 6
- EXPECT_TRUE(
- download_manager.StartQueryRequest(ToRawPointerVector(form_structures)));
- histogram.ExpectBucketCount("Autofill.ServerQueryResponse",
- AutofillMetrics::QUERY_SENT, 4);
- histogram.ExpectBucketCount("Autofill.Query.Method", METHOD_POST, 1);
- request = test_url_loader_factory_.GetPendingRequest(6);
- test_url_loader_factory_.SimulateResponseWithoutRemovingFromPendingList(
- request, responses[0]);
- histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_MISS, 2);
}
TEST_F(AutofillDownloadManagerTest, QueryAPITest) {
@@ -631,7 +606,6 @@ TEST_F(AutofillDownloadManagerTest, QueryAPITestWhenTooLongUrl) {
std::vector<std::unique_ptr<FormStructure>> form_structures;
{
auto form_structure = std::make_unique<FormStructure>(form);
- form_structure->set_is_rich_query_enabled(true);
form_structures.push_back(std::move(form_structure));
}
@@ -1395,8 +1369,7 @@ class AutofillServerCommunicationTest
scoped_feature_list_1_.InitWithFeatures(
// Enabled
- {features::kAutofillCacheQueryResponses,
- features::kAutofillUploadThrottling},
+ {features::kAutofillUploadThrottling},
// Disabled
{});
@@ -1785,7 +1758,7 @@ TEST_P(AutofillQueryTest, ExpiredCacheInResponse) {
}
}
-TEST_P(AutofillQueryTest, RichMetadata_Enabled) {
+TEST_P(AutofillQueryTest, Metadata) {
// Initialize a form. Note that this state is post-parse.
FormData form;
form.url = GURL("https://origin.com");
@@ -1836,109 +1809,6 @@ TEST_P(AutofillQueryTest, RichMetadata_Enabled) {
std::vector<std::unique_ptr<FormStructure>> form_structures;
form_structures.push_back(std::make_unique<FormStructure>(form));
- // Turn on rich query encoding.
- form_structures.front()->set_is_rich_query_enabled(true);
-
- // Generate a query request.
- ASSERT_TRUE(SendQueryRequest(form_structures));
- EXPECT_EQ(1u, call_count_);
-
- // We should have intercepted exactly on query request. Parse it.
- ASSERT_EQ(1u, payloads_.size());
- AutofillPageQueryRequest query;
- ASSERT_TRUE(query.ParseFromString(payloads_.front()));
-
- // Validate that we have one form in the query.
- ASSERT_EQ(query.forms_size(), 1);
- const auto& query_form = query.forms(0);
-
- // The form should have metadata, and the metadata value should be equal
- // those initialized above.
- ASSERT_TRUE(query_form.has_metadata());
- EXPECT_EQ(UTF8ToUTF16(query_form.metadata().id().encoded_bits()),
- form.id_attribute);
- EXPECT_EQ(UTF8ToUTF16(query_form.metadata().name().encoded_bits()),
- form.name_attribute);
-
- // The form should have 3 fields, and their metadata value should be equal
- // those initialized above.
- ASSERT_EQ(3, query_form.fields_size());
- ASSERT_EQ(static_cast<int>(form.fields.size()), query_form.fields_size());
- for (int i = 0; i < query_form.fields_size(); ++i) {
- const auto& query_field = query_form.fields(i);
- const auto& form_field = form.fields[i];
- ASSERT_TRUE(query_field.has_metadata());
- const auto& meta = query_field.metadata();
- EXPECT_EQ(UTF8ToUTF16(meta.id().encoded_bits()), form_field.id_attribute);
- EXPECT_EQ(UTF8ToUTF16(meta.name().encoded_bits()),
- form_field.name_attribute);
- EXPECT_EQ(meta.type().encoded_bits(), form_field.form_control_type);
- EXPECT_EQ(UTF8ToUTF16(meta.label().encoded_bits()), form_field.label);
- EXPECT_EQ(UTF8ToUTF16(meta.aria_label().encoded_bits()),
- form_field.aria_label);
- EXPECT_EQ(UTF8ToUTF16(meta.aria_description().encoded_bits()),
- form_field.aria_description);
- EXPECT_EQ(UTF8ToUTF16(meta.css_class().encoded_bits()),
- form_field.css_classes);
- EXPECT_EQ(UTF8ToUTF16(meta.placeholder().encoded_bits()),
- form_field.placeholder);
- }
-}
-
-TEST_P(AutofillQueryTest, RichMetadata_Disabled) {
- // Initialize a form. Note that this state is post-parse.
- FormData form;
- form.url = GURL("https://origin.com");
- form.action = GURL("https://origin.com/submit-me");
- form.id_attribute = u"form-id-attribute";
- form.name_attribute = u"form-name-attribute";
- form.name = form.name_attribute;
-
- // Add field 0.
- FormFieldData field;
- field.id_attribute = u"field-id-attribute-1";
- field.name_attribute = u"field-name-attribute-1";
- field.name = field.name_attribute;
- field.label = u"field-label";
- field.aria_label = u"field-aria-label";
- field.aria_description = u"field-aria-description";
- field.form_control_type = "text";
- field.css_classes = u"field-css-classes";
- field.placeholder = u"field-placeholder";
- form.fields.push_back(field);
-
- // Add field 1.
- field.id_attribute = u"field-id-attribute-2";
- field.name_attribute = u"field-name-attribute-2";
- field.name = field.name_attribute;
- field.label = u"field-label";
- field.aria_label = u"field-aria-label";
- field.aria_description = u"field-aria-description";
- field.form_control_type = "text";
- field.css_classes = u"field-css-classes";
- field.placeholder = u"field-placeholder";
- form.fields.push_back(field);
-
- // Add field 2.
- field.id_attribute = u"field-id-attribute-3";
- field.name_attribute = u"field-name-attribute-3";
- field.name = field.name_attribute;
- field.label = u"field-label";
- field.aria_label = u"field-aria-label";
- field.aria_description = u"field-aria-description";
- field.form_control_type = "text";
- field.css_classes = u"field-css-classes";
- field.placeholder = u"field-placeholder";
- form.fields.push_back(field);
-
- // Setup the form structures to query.
- AutofillDownloadManager download_manager(driver_.get(), this);
- std::vector<std::unique_ptr<FormStructure>> form_structures;
- form_structures.push_back(std::make_unique<FormStructure>(form));
-
- // Turn off rich query encoding.
- form_structures.front()->set_is_rich_query_enabled(false);
-
// Generate a query request.
ASSERT_TRUE(SendQueryRequest(form_structures));
EXPECT_EQ(1u, call_count_);
diff --git a/chromium/components/autofill/core/browser/autofill_driver.h b/chromium/components/autofill/core/browser/autofill_driver.h
index 7e2d219b99d..9eef8679904 100644
--- a/chromium/components/autofill/core/browser/autofill_driver.h
+++ b/chromium/components/autofill/core/browser/autofill_driver.h
@@ -133,6 +133,11 @@ class AutofillDriver {
const gfx::RectF& bounding_box) = 0;
virtual net::IsolationInfo IsolationInfo() = 0;
+
+ // Tells the renderer about the form fields that are eligible for triggering
+ // manual filling on form interaction.
+ virtual void SendFieldsEligibleForManualFillingToRenderer(
+ const std::vector<FieldRendererId>& fields) = 0;
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_driver_factory.h b/chromium/components/autofill/core/browser/autofill_driver_factory.h
index 07767b5df43..68f8be84612 100644
--- a/chromium/components/autofill/core/browser/autofill_driver_factory.h
+++ b/chromium/components/autofill/core/browser/autofill_driver_factory.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 AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_FACTORY_H_
-#define AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_FACTORY_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_FACTORY_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_FACTORY_H_
#include <memory>
#include <unordered_map>
@@ -61,4 +61,4 @@ class AutofillDriverFactory {
} // namespace autofill
-#endif // AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_FACTORY_H_
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_DRIVER_FACTORY_H_
diff --git a/chromium/components/autofill/core/browser/autofill_experiments.cc b/chromium/components/autofill/core/browser/autofill_experiments.cc
index e4d9536d62d..419c1267c47 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments.cc
@@ -19,6 +19,7 @@
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/ui/suggestion.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_payments_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
@@ -35,6 +36,22 @@
#include "ui/base/ui_base_features.h"
namespace autofill {
+namespace {
+void LogCardUploadDisabled(LogManager* log_manager, std::string context) {
+ if (log_manager) {
+ log_manager->Log() << LoggingScope::kCreditCardUploadStatus
+ << LogMessage::kCreditCardUploadDisabled << context
+ << CTag{};
+ }
+}
+
+void LogCardUploadEnabled(LogManager* log_manager) {
+ if (log_manager) {
+ log_manager->Log() << LoggingScope::kCreditCardUploadStatus
+ << LogMessage::kCreditCardUploadEnabled << CTag{};
+ }
+}
+} // namespace
bool IsCreditCardUploadEnabled(const PrefService* pref_service,
const syncer::SyncService* sync_service,
@@ -46,8 +63,7 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
AutofillMetrics::LogCardUploadEnabledMetric(
AutofillMetrics::CardUploadEnabledMetric::SYNC_SERVICE_NULL,
sync_state);
- if (log_manager)
- log_manager->Log() << LoggingScope::kContext << "SYNC_SERVICE_NULL";
+ LogCardUploadDisabled(log_manager, "SYNC_SERVICE_NULL");
return false;
}
@@ -56,10 +72,7 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
AutofillMetrics::CardUploadEnabledMetric::
SYNC_SERVICE_PERSISTENT_AUTH_ERROR,
sync_state);
- if (log_manager) {
- log_manager->Log() << LoggingScope::kContext
- << "SYNC_SERVICE_PERSISTENT_ERROR";
- }
+ LogCardUploadDisabled(log_manager, "SYNC_SERVICE_PERSISTENT_ERROR");
return false;
}
@@ -68,11 +81,8 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
AutofillMetrics::CardUploadEnabledMetric::
SYNC_SERVICE_MISSING_AUTOFILL_WALLET_DATA_ACTIVE_TYPE,
sync_state);
- if (log_manager) {
- log_manager->Log()
- << LoggingScope::kContext
- << "SYNC_SERVICE_MISSING_AUTOFILL_WALLET_ACTIVE_DATA_TYPE";
- }
+ LogCardUploadDisabled(
+ log_manager, "SYNC_SERVICE_MISSING_AUTOFILL_WALLET_ACTIVE_DATA_TYPE");
return false;
}
@@ -84,11 +94,9 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
AutofillMetrics::CardUploadEnabledMetric::
SYNC_SERVICE_MISSING_AUTOFILL_PROFILE_ACTIVE_TYPE,
sync_state);
- if (log_manager) {
- log_manager->Log()
- << LoggingScope::kContext
- << "SYNC_SERVICE_MISSING_AUTOFILL_PROFILE_ACTIVE_DATA_TYPE";
- }
+ LogCardUploadDisabled(
+ log_manager,
+ "SYNC_SERVICE_MISSING_AUTOFILL_PROFILE_ACTIVE_DATA_TYPE");
return false;
}
} else {
@@ -98,19 +106,16 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
features::kAutofillEnableAccountWalletStorage));
}
- // Also don't offer upload for users that have a secondary sync passphrase.
+ // Also don't offer upload for users that have an explicit sync passphrase.
// Users who have enabled a passphrase have chosen to not make their sync
// information accessible to Google. Since upload makes credit card data
// available to other Google systems, disable it for passphrase users.
- if (sync_service->GetUserSettings()->IsUsingSecondaryPassphrase()) {
+ if (sync_service->GetUserSettings()->IsUsingExplicitPassphrase()) {
AutofillMetrics::LogCardUploadEnabledMetric(
AutofillMetrics::CardUploadEnabledMetric::
- USING_SECONDARY_SYNC_PASSPHRASE,
+ USING_EXPLICIT_SYNC_PASSPHRASE,
sync_state);
- if (log_manager) {
- log_manager->Log() << LoggingScope::kContext
- << "USER_HAS_SECONDARY_SYNC_PASSPHRASE";
- }
+ LogCardUploadDisabled(log_manager, "USER_HAS_EXPLICIT_SYNC_PASSPHRASE");
return false;
}
@@ -120,10 +125,7 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
AutofillMetrics::LogCardUploadEnabledMetric(
AutofillMetrics::CardUploadEnabledMetric::LOCAL_SYNC_ENABLED,
sync_state);
- if (log_manager) {
- log_manager->Log() << LoggingScope::kContext
- << "USER_ONLY_SYNCING_LOCALLY";
- }
+ LogCardUploadDisabled(log_manager, "USER_ONLY_SYNCING_LOCALLY");
return false;
}
@@ -132,10 +134,7 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
AutofillMetrics::LogCardUploadEnabledMetric(
AutofillMetrics::CardUploadEnabledMetric::PAYMENTS_INTEGRATION_DISABLED,
sync_state);
- if (log_manager) {
- log_manager->Log() << LoggingScope::kContext
- << "PAYMENTS_INTEGRATION_DISABLED";
- }
+ LogCardUploadDisabled(log_manager, "PAYMENTS_INTEGRATION_DISABLED");
return false;
}
@@ -143,8 +142,7 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
if (user_email.empty()) {
AutofillMetrics::LogCardUploadEnabledMetric(
AutofillMetrics::CardUploadEnabledMetric::EMAIL_EMPTY, sync_state);
- if (log_manager)
- log_manager->Log() << LoggingScope::kContext << "USER_EMAIL_EMPTY";
+ LogCardUploadDisabled(log_manager, "USER_EMAIL_EMPTY");
return false;
}
@@ -162,10 +160,7 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
AutofillMetrics::LogCardUploadEnabledMetric(
AutofillMetrics::CardUploadEnabledMetric::EMAIL_DOMAIN_NOT_SUPPORTED,
sync_state);
- if (log_manager) {
- log_manager->Log() << LoggingScope::kContext
- << "USER_EMAIL_DOMAIN_NOT_SUPPORTED";
- }
+ LogCardUploadDisabled(log_manager, "USER_EMAIL_DOMAIN_NOT_SUPPORTED");
return false;
}
@@ -173,16 +168,14 @@ bool IsCreditCardUploadEnabled(const PrefService* pref_service,
AutofillMetrics::LogCardUploadEnabledMetric(
AutofillMetrics::CardUploadEnabledMetric::AUTOFILL_UPSTREAM_DISABLED,
sync_state);
- if (log_manager) {
- log_manager->Log() << LoggingScope::kContext
- << "AUTOFILL_UPSTREAM_NOT_ENABLED";
- }
+ LogCardUploadDisabled(log_manager, "AUTOFILL_UPSTREAM_NOT_ENABLED");
return false;
}
AutofillMetrics::LogCardUploadEnabledMetric(
AutofillMetrics::CardUploadEnabledMetric::CARD_UPLOAD_ENABLED,
sync_state);
+ LogCardUploadEnabled(log_manager);
return true;
}
diff --git a/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc b/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
index 7e0893d3adb..eba6ec44021 100644
--- a/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_experiments_unittest.cc
@@ -130,18 +130,18 @@ TEST_F(AutofillExperimentsTest,
}
TEST_F(AutofillExperimentsTest,
- IsCardUploadEnabled_SyncServiceUsingSecondaryPassphrase) {
+ IsCardUploadEnabled_SyncServiceUsingExplicitPassphrase) {
scoped_feature_list_.InitAndEnableFeature(features::kAutofillUpstream);
- sync_service_.SetIsUsingSecondaryPassphrase(true);
+ sync_service_.SetIsUsingExplicitPassphrase(true);
EXPECT_FALSE(IsCreditCardUploadEnabled(
AutofillSyncSigninState::kSignedInAndSyncFeatureEnabled));
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadEnabled",
- AutofillMetrics::CardUploadEnabledMetric::USING_SECONDARY_SYNC_PASSPHRASE,
+ AutofillMetrics::CardUploadEnabledMetric::USING_EXPLICIT_SYNC_PASSPHRASE,
1);
histogram_tester.ExpectUniqueSample(
"Autofill.CardUploadEnabled.SignedInAndSyncFeatureEnabled",
- AutofillMetrics::CardUploadEnabledMetric::USING_SECONDARY_SYNC_PASSPHRASE,
+ AutofillMetrics::CardUploadEnabledMetric::USING_EXPLICIT_SYNC_PASSPHRASE,
1);
}
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.cc b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
index cebe4690427..0590f5d4f42 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.cc
@@ -21,8 +21,8 @@
#include "build/build_config.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
#include "components/autofill/core/browser/autofill_driver.h"
-#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/browser/ui/popup_item_ids.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_payments_features.h"
@@ -53,8 +53,9 @@ bool IsAutofillWarningEntry(int frontend_id) {
} // namespace
-AutofillExternalDelegate::AutofillExternalDelegate(AutofillManager* manager,
- AutofillDriver* driver)
+AutofillExternalDelegate::AutofillExternalDelegate(
+ BrowserAutofillManager* manager,
+ AutofillDriver* driver)
: manager_(manager), driver_(driver) {
DCHECK(manager);
}
diff --git a/chromium/components/autofill/core/browser/autofill_external_delegate.h b/chromium/components/autofill/core/browser/autofill_external_delegate.h
index 06d94d9eaea..ff21029f5d7 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate.h
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate.h
@@ -22,7 +22,7 @@
namespace autofill {
class AutofillDriver;
-class AutofillManager;
+class BrowserAutofillManager;
class CreditCard;
// TODO(csharp): A lot of the logic in this class is copied from autofillagent.
@@ -32,9 +32,10 @@ class CreditCard;
// Delegate for in-browser Autocomplete and Autofill display and selection.
class AutofillExternalDelegate : public AutofillPopupDelegate {
public:
- // Creates an AutofillExternalDelegate for the specified AutofillManager and
- // AutofillDriver.
- AutofillExternalDelegate(AutofillManager* manager, AutofillDriver* driver);
+ // Creates an AutofillExternalDelegate for the specified
+ // BrowserAutofillManager and AutofillDriver.
+ AutofillExternalDelegate(BrowserAutofillManager* manager,
+ AutofillDriver* driver);
virtual ~AutofillExternalDelegate();
// AutofillPopupDelegate implementation.
@@ -144,7 +145,7 @@ class AutofillExternalDelegate : public AutofillPopupDelegate {
// Returns the text (i.e. |Suggestion| value) for Chrome autofill options.
std::u16string GetSettingsSuggestionValue() const;
- AutofillManager* const manager_; // weak.
+ BrowserAutofillManager* const manager_; // weak.
// Provides driver-level context to the shared code of the component. Must
// outlive this object.
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 721f0c648c2..643ddc26f46 100644
--- a/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -17,9 +17,9 @@
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
-#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/ui/popup_item_ids.h"
@@ -37,7 +37,6 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
-using base::ASCIIToUTF16;
using testing::_;
namespace autofill {
@@ -100,14 +99,14 @@ class MockAutofillClient : public TestAutofillClient {
DISALLOW_COPY_AND_ASSIGN(MockAutofillClient);
};
-class MockAutofillManager : public AutofillManager {
+class MockBrowserAutofillManager : public BrowserAutofillManager {
public:
- MockAutofillManager(AutofillDriver* driver, MockAutofillClient* client)
+ MockBrowserAutofillManager(AutofillDriver* driver, MockAutofillClient* client)
// Force to use the constructor designated for unit test.
- : AutofillManager(driver,
- client,
- client->GetPersonalDataManager(),
- client->GetAutocompleteHistoryManager()) {}
+ : BrowserAutofillManager(driver,
+ client,
+ client->GetPersonalDataManager(),
+ client->GetAutocompleteHistoryManager()) {}
PopupType GetPopupType(const FormData& form,
const FormFieldData& field) override {
@@ -155,7 +154,7 @@ class MockAutofillManager : public AutofillManager {
private:
bool should_show_cards_from_account_option_ = false;
- DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
+ DISALLOW_COPY_AND_ASSIGN(MockBrowserAutofillManager);
};
} // namespace
@@ -165,16 +164,16 @@ class AutofillExternalDelegateUnitTest : public testing::Test {
void SetUp() override {
autofill_driver_ =
std::make_unique<testing::NiceMock<MockAutofillDriver>>();
- autofill_manager_ = std::make_unique<MockAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<MockBrowserAutofillManager>(
autofill_driver_.get(), &autofill_client_);
external_delegate_ = std::make_unique<AutofillExternalDelegate>(
- autofill_manager_.get(), autofill_driver_.get());
+ browser_autofill_manager_.get(), autofill_driver_.get());
}
void TearDown() override {
- // Order of destruction is important as AutofillManager relies on
+ // Order of destruction is important as BrowserAutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
- autofill_manager_.reset();
+ browser_autofill_manager_.reset();
external_delegate_.reset();
autofill_driver_.reset();
}
@@ -205,21 +204,21 @@ class AutofillExternalDelegateUnitTest : public testing::Test {
testing::NiceMock<MockAutofillClient> autofill_client_;
std::unique_ptr<testing::NiceMock<MockAutofillDriver>> autofill_driver_;
- std::unique_ptr<MockAutofillManager> autofill_manager_;
+ std::unique_ptr<MockBrowserAutofillManager> browser_autofill_manager_;
std::unique_ptr<AutofillExternalDelegate> external_delegate_;
FormGlobalId form_id_ = test::MakeFormGlobalId();
FieldGlobalId field_id_ = test::MakeFieldGlobalId();
};
-// Variant for use in cases when we expect the AutofillManager would normally
-// set the |should_show_cards_from_account_option_| bit.
+// Variant for use in cases when we expect the BrowserAutofillManager would
+// normally set the |should_show_cards_from_account_option_| bit.
class AutofillExternalDelegateCardsFromAccountTest
: public AutofillExternalDelegateUnitTest {
protected:
void SetUp() override {
AutofillExternalDelegateUnitTest::SetUp();
- autofill_manager_->ShowCardsFromAccountOption();
+ browser_autofill_manager_->ShowCardsFromAccountOption();
}
};
@@ -245,7 +244,7 @@ TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) {
EXPECT_EQ(open_args.popup_type, PopupType::kPersonalInformation);
EXPECT_CALL(
- *autofill_manager_,
+ *browser_autofill_manager_,
FillOrPreviewForm(AutofillDriver::FORM_DATA_ACTION_FILL, _, _, _, _));
EXPECT_CALL(autofill_client_,
HideAutofillPopup(PopupHidingReason::kAcceptSuggestion));
@@ -260,7 +259,7 @@ TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) {
// separator in the popup items when there are suggestions.
TEST_F(AutofillExternalDelegateUnitTest,
TestSigninPromoIsNotAdded_WithSuggestions) {
- EXPECT_CALL(*autofill_manager_, ShouldShowCreditCardSigninPromo(_, _))
+ EXPECT_CALL(*browser_autofill_manager_, ShouldShowCreditCardSigninPromo(_, _))
.WillOnce(testing::Return(true));
IssueOnQuery(kRecentQueryId);
@@ -287,7 +286,7 @@ TEST_F(AutofillExternalDelegateUnitTest,
EXPECT_EQ(open_args.popup_type, PopupType::kPersonalInformation);
EXPECT_CALL(
- *autofill_manager_,
+ *browser_autofill_manager_,
FillOrPreviewForm(AutofillDriver::FORM_DATA_ACTION_FILL, _, _, _, _));
EXPECT_CALL(autofill_client_,
HideAutofillPopup(PopupHidingReason::kAcceptSuggestion));
@@ -302,7 +301,7 @@ TEST_F(AutofillExternalDelegateUnitTest,
// separator in the dropdown, when there are no suggestions.
TEST_F(AutofillExternalDelegateUnitTest,
TestSigninPromoIsAdded_WithNoSuggestions) {
- EXPECT_CALL(*autofill_manager_, ShouldShowCreditCardSigninPromo(_, _))
+ EXPECT_CALL(*browser_autofill_manager_, ShouldShowCreditCardSigninPromo(_, _))
.WillOnce(testing::Return(true));
IssueOnQuery(kRecentQueryId);
@@ -586,14 +585,16 @@ TEST_F(AutofillExternalDelegateUnitTest,
// negative unique id.
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateInvalidUniqueId) {
// Ensure it doesn't try to preview the negative id.
- EXPECT_CALL(*autofill_manager_, FillOrPreviewForm(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*browser_autofill_manager_, FillOrPreviewForm(_, _, _, _, _))
+ .Times(0);
EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm()).Times(1);
external_delegate_->DidSelectSuggestion(std::u16string(), -1);
// Ensure it doesn't try to fill the form in with the negative id.
EXPECT_CALL(autofill_client_,
HideAutofillPopup(PopupHidingReason::kAcceptSuggestion));
- EXPECT_CALL(*autofill_manager_, FillOrPreviewForm(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*browser_autofill_manager_, FillOrPreviewForm(_, _, _, _, _))
+ .Times(0);
external_delegate_->DidAcceptSuggestion(std::u16string(), -1, 0);
}
@@ -608,7 +609,7 @@ TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearPreviewedForm) {
POPUP_ITEM_ID_PASSWORD_ENTRY);
EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm()).Times(1);
EXPECT_CALL(
- *autofill_manager_,
+ *browser_autofill_manager_,
FillOrPreviewForm(AutofillDriver::FORM_DATA_ACTION_PREVIEW, _, _, _, _));
external_delegate_->DidSelectSuggestion(u"baz foo", 1);
@@ -616,8 +617,8 @@ TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearPreviewedForm) {
// get cleared.
EXPECT_CALL(*autofill_driver_, RendererShouldClearPreviewedForm()).Times(1);
EXPECT_CALL(*autofill_driver_, RendererShouldPreviewFieldWithValue(
- field_id_, ASCIIToUTF16("baz foo")));
- external_delegate_->DidSelectSuggestion(ASCIIToUTF16("baz foo"),
+ field_id_, std::u16string(u"baz foo")));
+ external_delegate_->DidSelectSuggestion(u"baz foo",
POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY);
}
@@ -652,7 +653,7 @@ TEST_F(AutofillExternalDelegateUnitTest,
EXPECT_CALL(autofill_client_,
HideAutofillPopup(PopupHidingReason::kAcceptSuggestion));
std::u16string dummy_string(u"John Legend");
- EXPECT_CALL(*autofill_manager_,
+ EXPECT_CALL(*browser_autofill_manager_,
FillOrPreviewForm(AutofillDriver::FORM_DATA_ACTION_FILL, _, _, _,
kAutofillProfileId));
external_delegate_->DidAcceptSuggestion(dummy_string, kAutofillProfileId,
@@ -673,7 +674,7 @@ TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearForm) {
// Test that the client is directed to hide the autofill popup after being
// notified that the user clicked "Hide suggestions" menu item.
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateHideSuggestions) {
- EXPECT_CALL(*autofill_manager_, OnUserHideSuggestions(_, _));
+ EXPECT_CALL(*browser_autofill_manager_, OnUserHideSuggestions(_, _));
EXPECT_CALL(autofill_client_,
HideAutofillPopup(PopupHidingReason::kAcceptSuggestion));
@@ -694,7 +695,7 @@ TEST_F(AutofillExternalDelegateUnitTest, ScanCreditCardMenuItem) {
TEST_F(AutofillExternalDelegateUnitTest, ScanCreditCardPromptMetricsTest) {
// Log that the scan card item was shown, although nothing was selected.
{
- EXPECT_CALL(*autofill_manager_, ShouldShowScanCreditCard(_, _))
+ EXPECT_CALL(*browser_autofill_manager_, ShouldShowScanCreditCard(_, _))
.WillOnce(testing::Return(true));
base::HistogramTester histogram;
IssueOnQuery(kRecentQueryId);
@@ -705,7 +706,7 @@ TEST_F(AutofillExternalDelegateUnitTest, ScanCreditCardPromptMetricsTest) {
}
// Log that the scan card item was selected.
{
- EXPECT_CALL(*autofill_manager_, ShouldShowScanCreditCard(_, _))
+ EXPECT_CALL(*browser_autofill_manager_, ShouldShowScanCreditCard(_, _))
.WillOnce(testing::Return(true));
base::HistogramTester histogram;
IssueOnQuery(kRecentQueryId);
@@ -723,7 +724,7 @@ TEST_F(AutofillExternalDelegateUnitTest, ScanCreditCardPromptMetricsTest) {
}
// Log that something else was selected.
{
- EXPECT_CALL(*autofill_manager_, ShouldShowScanCreditCard(_, _))
+ EXPECT_CALL(*browser_autofill_manager_, ShouldShowScanCreditCard(_, _))
.WillOnce(testing::Return(true));
base::HistogramTester histogram;
IssueOnQuery(kRecentQueryId);
@@ -741,7 +742,7 @@ TEST_F(AutofillExternalDelegateUnitTest, ScanCreditCardPromptMetricsTest) {
}
// Nothing is logged when the item isn't shown.
{
- EXPECT_CALL(*autofill_manager_, ShouldShowScanCreditCard(_, _))
+ EXPECT_CALL(*browser_autofill_manager_, ShouldShowScanCreditCard(_, _))
.WillOnce(testing::Return(false));
base::HistogramTester histogram;
IssueOnQuery(kRecentQueryId);
@@ -772,7 +773,7 @@ TEST_F(AutofillExternalDelegateUnitTest, FillCreditCardForm) {
CreditCard card;
test::SetCreditCardInfo(&card, "Alice", "4111", "1", "3000", "1");
EXPECT_CALL(
- *autofill_manager_,
+ *browser_autofill_manager_,
FillCreditCardForm(_, _, _, CreditCardMatches(card), std::u16string()));
external_delegate_->OnCreditCardScanned(card);
}
diff --git a/chromium/components/autofill/core/browser/autofill_field.h b/chromium/components/autofill/core/browser/autofill_field.h
index 257f457c8d3..a497ce9090a 100644
--- a/chromium/components/autofill/core/browser/autofill_field.h
+++ b/chromium/components/autofill/core/browser/autofill_field.h
@@ -13,7 +13,6 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/field_types.h"
@@ -21,6 +20,7 @@
#include "components/autofill/core/browser/proto/password_requirements.pb.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/signatures.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -158,7 +158,7 @@ class AutofillField : public FormFieldData {
bool IsFieldFillable() const;
void set_initial_value_hash(uint32_t value) { initial_value_hash_ = value; }
- base::Optional<uint32_t> initial_value_hash() { return initial_value_hash_; }
+ absl::optional<uint32_t> initial_value_hash() { return initial_value_hash_; }
void set_credit_card_number_offset(size_t position) {
credit_card_number_offset_ = position;
@@ -191,7 +191,7 @@ class AutofillField : public FormFieldData {
}
void SetPasswordRequirements(PasswordRequirementsSpec spec);
- const base::Optional<PasswordRequirementsSpec>& password_requirements()
+ const absl::optional<PasswordRequirementsSpec>& password_requirements()
const {
return password_requirements_;
}
@@ -219,7 +219,7 @@ class AutofillField : public FormFieldData {
// Whether the heuristics or server predict a credit card field.
bool IsCreditCardPrediction() const;
- base::Optional<FieldSignature> field_signature_;
+ absl::optional<FieldSignature> field_signature_;
// The unique name of this field, generated by Autofill.
std::u16string unique_name_;
@@ -241,7 +241,7 @@ class AutofillField : public FormFieldData {
// Requirements the site imposes to passwords (for password generation).
// Corresponds to the requirements determined by the Autofill server.
- base::Optional<PasswordRequirementsSpec> password_requirements_;
+ absl::optional<PasswordRequirementsSpec> password_requirements_;
// The type of the field, as determined by the local heuristics.
ServerFieldType heuristic_type_ = UNKNOWN_TYPE;
@@ -270,7 +270,7 @@ class AutofillField : public FormFieldData {
// A low-entropy hash of the field's initial value before user-interactions or
// automatic fillings. This field is used to detect static placeholders.
- base::Optional<uint32_t> initial_value_hash_;
+ absl::optional<uint32_t> initial_value_hash_;
// Used to hold the position of the first digit to be copied as a substring
// from credit card number.
diff --git a/chromium/components/autofill/core/browser/autofill_form_test_utils.cc b/chromium/components/autofill/core/browser/autofill_form_test_utils.cc
index fae59e22149..8ef93d17166 100644
--- a/chromium/components/autofill/core/browser/autofill_form_test_utils.cc
+++ b/chromium/components/autofill/core/browser/autofill_form_test_utils.cc
@@ -4,11 +4,8 @@
#include "components/autofill/core/browser/autofill_form_test_utils.h"
-#include "base/optional.h"
-#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/form_structure.h"
-
-using base::ASCIIToUTF16;
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -93,7 +90,7 @@ FormData GetFormData(const TestFormAttributes& test_form_attributes) {
form_data.url = GURL(test_form_attributes.url);
form_data.action = GURL(test_form_attributes.action);
- form_data.name = ASCIIToUTF16(test_form_attributes.name);
+ form_data.name = test_form_attributes.name.data();
static int field_count = 0;
if (test_form_attributes.unique_renderer_id)
form_data.unique_renderer_id = *test_form_attributes.unique_renderer_id;
@@ -102,16 +99,18 @@ FormData GetFormData(const TestFormAttributes& test_form_attributes) {
for (const FieldDataDescription& field_description :
test_form_attributes.fields) {
FormFieldData field = CreateFieldByRole(field_description.role);
- field.form_control_type = field_description.form_control_type;
+ field.form_control_type = field_description.form_control_type.data();
field.is_focusable = field_description.is_focusable;
- if (field_description.autocomplete_attribute)
- field.autocomplete_attribute = field_description.autocomplete_attribute;
- if (ASCIIToUTF16(field_description.label) != ASCIIToUTF16(kLabelText))
- field.label = ASCIIToUTF16(field_description.label);
- if (ASCIIToUTF16(field_description.name) != ASCIIToUTF16(kNameText))
- field.name = ASCIIToUTF16(field_description.name);
+ if (!field_description.autocomplete_attribute.empty()) {
+ field.autocomplete_attribute =
+ field_description.autocomplete_attribute.data();
+ }
+ if (field_description.label != kLabelText)
+ field.label = field_description.label.data();
+ if (field_description.name != kNameText)
+ field.name = field_description.name.data();
if (field_description.value)
- field.value = ASCIIToUTF16(*field_description.value);
+ field.value = *field_description.value;
if (field_description.is_autofilled)
field.is_autofilled = *field_description.is_autofilled;
field.unique_renderer_id = FieldRendererId(field_count++);
diff --git a/chromium/components/autofill/core/browser/autofill_form_test_utils.h b/chromium/components/autofill/core/browser/autofill_form_test_utils.h
index 660cbcb86c5..415f78593ca 100644
--- a/chromium/components/autofill/core/browser/autofill_form_test_utils.h
+++ b/chromium/components/autofill/core/browser/autofill_form_test_utils.h
@@ -7,12 +7,13 @@
#include <vector>
-#include "base/optional.h"
+#include "base/strings/string_piece.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
namespace test {
@@ -20,10 +21,10 @@ namespace test {
namespace {
// Default label assigned to fields.
-constexpr char kLabelText[] = "label";
+constexpr char16_t kLabelText[] = u"label";
// Default name attribute assigned to fields.
-constexpr char kNameText[] = "name";
+constexpr char16_t kNameText[] = u"name";
// Default form url.
constexpr char kFormUrl[] = "http://example.com/form.html";
@@ -40,25 +41,25 @@ template <typename = void>
struct FieldDataDescription {
ServerFieldType role = ServerFieldType::EMPTY_TYPE;
bool is_focusable = true;
- const char* label = kLabelText;
- const char* name = kNameText;
- base::Optional<const char*> value = base::nullopt;
- const char* autocomplete_attribute = nullptr;
- const char* form_control_type = "text";
+ const base::StringPiece16 label = kLabelText;
+ const base::StringPiece16 name = kNameText;
+ absl::optional<const char16_t*> value;
+ const base::StringPiece autocomplete_attribute;
+ const base::StringPiece form_control_type = "text";
bool should_autocomplete = true;
- base::Optional<bool> is_autofilled = base::nullopt;
+ absl::optional<bool> is_autofilled;
};
// Attributes provided to the test form.
template <typename = void>
struct TestFormAttributes {
- const char* description_for_logging;
+ const base::StringPiece description_for_logging;
std::vector<FieldDataDescription<>> fields;
- base::Optional<FormRendererId> unique_renderer_id = base::nullopt;
- const char* name = "TestForm";
- const char* url = kFormUrl;
- const char* action = kFormActionUrl;
- base::Optional<url::Origin> main_frame_origin = base::nullopt;
+ absl::optional<FormRendererId> unique_renderer_id;
+ const base::StringPiece16 name = u"TestForm";
+ const base::StringPiece url = kFormUrl;
+ const base::StringPiece action = kFormActionUrl;
+ absl::optional<url::Origin> main_frame_origin;
bool is_form_tag = true;
};
@@ -79,11 +80,11 @@ struct TestFormFlags {
// first value denotes whether the comparison is to be done while second
// denotes EXPECT_TRUE for true and EXPECT_FALSE for false.
std::pair<bool, bool> is_complete_credit_card_form = {false, false};
- // base::nullopt means no checking.
- base::Optional<int> field_count = base::nullopt;
- base::Optional<int> autofill_count = base::nullopt;
- base::Optional<int> section_count = base::nullopt;
- base::Optional<int> response_field_count = base::nullopt;
+ // The implicit default value `absl::nullopt` means no checking.
+ absl::optional<int> field_count;
+ absl::optional<int> autofill_count;
+ absl::optional<int> section_count;
+ absl::optional<int> response_field_count;
};
// Expected field type values to be verified with the test form.
diff --git a/chromium/components/autofill/core/browser/autofill_handler.cc b/chromium/components/autofill/core/browser/autofill_handler.cc
deleted file mode 100644
index 7e017bd8693..00000000000
--- a/chromium/components/autofill/core/browser/autofill_handler.cc
+++ /dev/null
@@ -1,562 +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/autofill_handler.h"
-
-#include "base/bind.h"
-#include "base/containers/adapters.h"
-#include "base/feature_list.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread_task_runner_handle.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_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_payments_features.h"
-#include "components/autofill/core/common/autofill_switches.h"
-#include "components/autofill/core/common/autofill_tick_clock.h"
-#include "components/translate/core/common/language_detection_details.h"
-#include "google_apis/google_api_keys.h"
-#include "ui/gfx/geometry/rect_f.h"
-
-namespace autofill {
-
-namespace {
-
-// Set a conservative upper bound on the number of forms we are willing to
-// cache, simply to prevent unbounded memory consumption.
-const size_t kAutofillHandlerMaxFormCacheSize = 100;
-
-// Returns the AutofillField* corresponding to |field| in |form| or nullptr,
-// if not found.
-AutofillField* FindAutofillFillField(const FormStructure& form,
- const FormFieldData& field) {
- for (const auto& f : form) {
- if (field.global_id() == f->global_id())
- return f.get();
- }
- for (const auto& cur_field : form) {
- if (cur_field->SameFieldAs(field)) {
- return cur_field.get();
- }
- }
- return nullptr;
-}
-
-// Returns true if |live_form| does not match |cached_form|, assuming that
-// |live_form|'s language is |live_form_language|.
-bool CachedFormNeedsUpdate(const FormData& live_form,
- const FormStructure& cached_form) {
- if (live_form.fields.size() != cached_form.field_count())
- return true;
-
- for (size_t i = 0; i < cached_form.field_count(); ++i) {
- if (!cached_form.field(i)->SameFieldAs(live_form.fields[i]))
- return true;
- }
-
- return false;
-}
-
-std::string GetAPIKeyForUrl(version_info::Channel channel) {
- // First look if we can get API key from command line flag.
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kAutofillAPIKey))
- return command_line.GetSwitchValueASCII(switches::kAutofillAPIKey);
-
- // Get the API key from Chrome baked keys.
- if (channel == version_info::Channel::STABLE)
- return google_apis::GetAPIKey();
- return google_apis::GetNonStableAPIKey();
-}
-
-} // namespace
-
-using base::TimeTicks;
-
-// static
-void AutofillHandler::LogAutofillTypePredictionsAvailable(
- LogManager* log_manager,
- const std::vector<FormStructure*>& forms) {
- if (VLOG_IS_ON(1)) {
- VLOG(1) << "Parsed forms:";
- for (FormStructure* form : forms)
- VLOG(1) << *form;
- }
-
- if (!log_manager || !log_manager->IsLoggingActive())
- return;
-
- LogBuffer buffer;
- for (FormStructure* form : forms)
- buffer << *form;
-
- log_manager->Log() << LoggingScope::kParsing << LogMessage::kParsedForms
- << std::move(buffer);
-}
-
-// static
-bool AutofillHandler::IsRichQueryEnabled(version_info::Channel channel) {
- return base::FeatureList::IsEnabled(features::kAutofillRichMetadataQueries) &&
- channel != version_info::Channel::STABLE &&
- channel != version_info::Channel::BETA;
-}
-
-// static
-bool AutofillHandler::IsRawMetadataUploadingEnabled(
- version_info::Channel channel) {
- return channel == version_info::Channel::CANARY ||
- channel == version_info::Channel::DEV;
-}
-
-AutofillHandler::AutofillHandler(
- AutofillDriver* driver,
- AutofillClient* client,
- AutofillDownloadManagerState enable_download_manager)
- : AutofillHandler(driver,
- client,
- enable_download_manager,
- client->GetChannel()) {
- DCHECK(driver);
- DCHECK(client);
-}
-
-AutofillHandler::AutofillHandler(
- AutofillDriver* driver,
- AutofillClient* client,
- AutofillDownloadManagerState enable_download_manager,
- version_info::Channel channel)
- : driver_(driver),
- client_(client),
- log_manager_(client ? client->GetLogManager() : nullptr),
- form_interactions_ukm_logger_(CreateFormInteractionsUkmLogger()),
- is_rich_query_enabled_(IsRichQueryEnabled(channel)) {
- if (enable_download_manager == ENABLE_AUTOFILL_DOWNLOAD_MANAGER) {
- download_manager_ = std::make_unique<AutofillDownloadManager>(
- driver, this, GetAPIKeyForUrl(channel),
- AutofillDownloadManager::IsRawMetadataUploadingEnabled(
- IsRawMetadataUploadingEnabled(channel)),
- log_manager_);
- }
- if (client) {
- translate::TranslateDriver* translate_driver = client->GetTranslateDriver();
- if (translate_driver) {
- translate_observation_.Observe(translate_driver);
- }
- }
-}
-
-AutofillHandler::~AutofillHandler() {
- translate_observation_.Reset();
- if (!query_result_delay_task_.IsCancelled())
- query_result_delay_task_.Cancel();
-}
-
-void AutofillHandler::OnLanguageDetermined(
- const translate::LanguageDetectionDetails& details) {
- if (!base::FeatureList::IsEnabled(
- features::kAutofillParsingPatternsLanguageDetection)) {
- return;
- }
- for (auto& p : form_structures_) {
- std::unique_ptr<FormStructure>& form_structure = p.second;
- form_structure->set_current_page_language(
- LanguageCode(details.adopted_language));
- form_structure->DetermineHeuristicTypes(form_interactions_ukm_logger(),
- log_manager_);
- }
-}
-
-void AutofillHandler::OnTranslateDriverDestroyed(
- translate::TranslateDriver* translate_driver) {
- translate_observation_.Reset();
-}
-
-LanguageCode AutofillHandler::GetCurrentPageLanguage() const {
- DCHECK(client_);
- const translate::LanguageState* language_state = client_->GetLanguageState();
- if (!language_state)
- return LanguageCode();
- return LanguageCode(language_state->current_language());
-}
-
-void AutofillHandler::OnFormSubmitted(const FormData& form,
- bool known_success,
- mojom::SubmissionSource source) {
- if (IsValidFormData(form))
- OnFormSubmittedImpl(form, known_success, source);
-}
-
-void AutofillHandler::OnFormsSeen(const std::vector<FormData>& forms) {
- if (!IsValidFormDataVector(forms) || !driver_->RendererIsAvailable())
- return;
-
- // This should be called even forms is empty, AutofillProviderAndroid uses
- // this event to detect form submission.
- if (!ShouldParseForms(forms))
- return;
-
- if (forms.empty())
- return;
-
- std::vector<const FormData*> new_forms;
- for (const FormData& form : forms) {
- const auto parse_form_start_time = AutofillTickClock::NowTicks();
- FormStructure* cached_form_structure =
- FindCachedFormByRendererId(form.global_id());
-
- // Not updating signatures of credit card forms is legacy behaviour. We
- // believe that the signatures are kept stable for voting purposes.
- bool update_form_signature = false;
- if (cached_form_structure) {
- const DenseSet<FormType>& form_types =
- cached_form_structure->GetFormTypes();
- update_form_signature =
- form_types.size() > form_types.count(FormType::kCreditCardForm);
- }
-
- FormStructure* form_structure = ParseForm(form, cached_form_structure);
- if (!form_structure)
- continue;
- DCHECK(form_structure);
-
- if (update_form_signature)
- form_structure->set_form_signature(CalculateFormSignature(form));
-
- new_forms.push_back(&form);
- AutofillMetrics::LogParseFormTiming(AutofillTickClock::NowTicks() -
- parse_form_start_time);
- }
-
- if (new_forms.empty())
- return;
- OnFormsParsed(new_forms);
-}
-
-void AutofillHandler::OnFormsParsed(const std::vector<const FormData*>& forms) {
- DCHECK(!forms.empty());
- OnBeforeProcessParsedForms();
-
- driver()->HandleParsedForms(forms);
-
- std::vector<FormStructure*> non_queryable_forms;
- std::vector<FormStructure*> queryable_forms;
- DenseSet<FormType> form_types;
- for (const FormData* form : forms) {
- FormStructure* form_structure =
- FindCachedFormByRendererId(form->global_id());
- if (!form_structure) {
- NOTREACHED();
- continue;
- }
-
- form_types.insert_all(form_structure->GetFormTypes());
-
- // Configure the query encoding for this form and add it to the appropriate
- // collection of forms: queryable vs non-queryable.
- form_structure->set_is_rich_query_enabled(is_rich_query_enabled_);
- if (form_structure->ShouldBeQueried())
- queryable_forms.push_back(form_structure);
- else
- non_queryable_forms.push_back(form_structure);
-
- OnFormProcessed(*form, *form_structure);
- }
-
- if (!queryable_forms.empty() || !non_queryable_forms.empty()) {
- OnAfterProcessParsedForms(form_types);
- }
-
- // Send the current type predictions to the renderer. For non-queryable forms
- // this is all the information about them that will ever be available. The
- // queryable forms will be updated once the field type query is complete.
- driver()->SendAutofillTypePredictionsToRenderer(non_queryable_forms);
- driver()->SendAutofillTypePredictionsToRenderer(queryable_forms);
- LogAutofillTypePredictionsAvailable(log_manager_, non_queryable_forms);
- LogAutofillTypePredictionsAvailable(log_manager_, queryable_forms);
-
- // Query the server if at least one of the forms was parsed.
- if (!queryable_forms.empty() && download_manager()) {
- download_manager()->StartQueryRequest(queryable_forms);
- }
-}
-
-void AutofillHandler::OnTextFieldDidChange(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box,
- const TimeTicks timestamp) {
- if (!IsValidFormData(form) || !IsValidFormFieldData(field))
- return;
-
- gfx::RectF transformed_box =
- driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
-
- OnTextFieldDidChangeImpl(form, field, transformed_box, timestamp);
-}
-
-void AutofillHandler::OnTextFieldDidScroll(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) {
- if (!IsValidFormData(form) || !IsValidFormFieldData(field))
- return;
-
- gfx::RectF transformed_box =
- driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
-
- OnTextFieldDidScrollImpl(form, field, transformed_box);
-}
-
-void AutofillHandler::OnSelectControlDidChange(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) {
- if (!IsValidFormData(form) || !IsValidFormFieldData(field))
- return;
-
- gfx::RectF transformed_box =
- driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
-
- OnSelectControlDidChangeImpl(form, field, transformed_box);
-}
-
-void AutofillHandler::OnQueryFormFieldAutofill(
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box,
- bool autoselect_first_suggestion) {
- if (!IsValidFormData(form) || !IsValidFormFieldData(field))
- return;
-
- gfx::RectF transformed_box =
- driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
-
- OnQueryFormFieldAutofillImpl(query_id, form, field, transformed_box,
- autoselect_first_suggestion);
-}
-
-void AutofillHandler::OnFocusOnFormField(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) {
- if (!IsValidFormData(form) || !IsValidFormFieldData(field))
- return;
-
- gfx::RectF transformed_box =
- driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
-
- OnFocusOnFormFieldImpl(form, field, transformed_box);
-}
-
-void AutofillHandler::SendFormDataToRenderer(
- int query_id,
- AutofillDriver::RendererFormDataAction action,
- const FormData& data) {
- driver_->SendFormDataToRenderer(query_id, action, data);
-}
-
-// Returns true if |live_form| does not match |cached_form|.
-bool AutofillHandler::GetCachedFormAndField(const FormData& form,
- const FormFieldData& field,
- FormStructure** form_structure,
- AutofillField** autofill_field) {
- // Maybe find an existing FormStructure that corresponds to |form|.
- FormStructure* cached_form = FindCachedFormByRendererId(form.global_id());
- if (cached_form) {
- DCHECK(cached_form);
- if (!CachedFormNeedsUpdate(form, *cached_form)) {
- // There is no data to return if there are no auto-fillable fields.
- if (!cached_form->autofill_count())
- return false;
-
- // Return the cached form and matching field, if any.
- *form_structure = cached_form;
- *autofill_field = FindAutofillFillField(**form_structure, field);
- return *autofill_field != nullptr;
- }
- }
-
- // The form is new or updated, parse it and discard |cached_form|.
- // i.e., |cached_form| is no longer valid after this call.
- *form_structure = ParseForm(form, cached_form);
- if (!*form_structure)
- return false;
-
- // Annotate the updated form with its predicted types.
- driver()->SendAutofillTypePredictionsToRenderer({*form_structure});
-
- // There is no data to return if there are no auto-fillable fields.
- if (!(*form_structure)->autofill_count())
- return false;
-
- // Find the AutofillField that corresponds to |field|.
- *autofill_field = FindAutofillFillField(**form_structure, field);
- return *autofill_field != nullptr;
-}
-
-std::unique_ptr<AutofillMetrics::FormInteractionsUkmLogger>
-AutofillHandler::CreateFormInteractionsUkmLogger() {
- if (!client())
- return nullptr;
-
- return std::make_unique<AutofillMetrics::FormInteractionsUkmLogger>(
- client()->GetUkmRecorder(), client()->GetUkmSourceId());
-}
-
-size_t AutofillHandler::FindCachedFormsBySignature(
- FormSignature form_signature,
- std::vector<FormStructure*>* form_structures) const {
- size_t hits_num = 0;
- for (const auto& p : form_structures_) {
- if (p.second->form_signature() == form_signature) {
- ++hits_num;
- if (form_structures)
- form_structures->push_back(p.second.get());
- }
- }
- return hits_num;
-}
-
-FormStructure* AutofillHandler::FindCachedFormByRendererId(
- FormGlobalId form_id) const {
- auto it = form_structures_.find(form_id);
- return it != form_structures_.end() ? it->second.get() : nullptr;
-}
-
-FormStructure* AutofillHandler::ParseForm(const FormData& form,
- const FormStructure* cached_form) {
- if (form_structures_.size() >= kAutofillHandlerMaxFormCacheSize) {
- if (log_manager_) {
- log_manager_->Log() << LoggingScope::kAbortParsing
- << LogMessage::kAbortParsingTooManyForms << form;
- }
- return nullptr;
- }
-
- auto form_structure = std::make_unique<FormStructure>(form);
- form_structure->ParseFieldTypesFromAutocompleteAttributes();
- if (!form_structure->ShouldBeParsed(log_manager_))
- return nullptr;
-
- if (cached_form) {
- // We need to keep the server data if available. We need to use them while
- // determining the heuristics.
- form_structure->RetrieveFromCache(*cached_form,
- /*should_keep_cached_value=*/true,
- /*only_server_and_autofill_state=*/true);
- if (observer_for_testing_)
- observer_for_testing_->OnFormParsed();
-
- if (form_structure.get()->value_from_dynamic_change_form())
- value_from_dynamic_change_form_ = true;
- }
-
- form_structure->set_current_page_language(GetCurrentPageLanguage());
-
- form_structure->DetermineHeuristicTypes(form_interactions_ukm_logger(),
- log_manager_);
-
- // Hold the parsed_form_structure we intend to return. We can use this to
- // reference the form_signature when transferring ownership below.
- FormStructure* parsed_form_structure = form_structure.get();
-
- // Ownership is transferred to |form_structures_| which maintains it until
- // the form is parsed again or the AutofillHandler is destroyed.
- //
- // Note that this insert/update takes ownership of the new form structure
- // and also destroys the previously cached form structure.
- form_structures_[parsed_form_structure->global_id()] =
- std::move(form_structure);
-
- return parsed_form_structure;
-}
-
-void AutofillHandler::Reset() {
- form_structures_.clear();
- form_interactions_ukm_logger_ = CreateFormInteractionsUkmLogger();
-}
-
-void AutofillHandler::OnLoadedServerPredictions(
- std::string response,
- const std::vector<FormSignature>& queried_form_signatures) {
- // Get the current valid FormStructures represented by
- // |queried_form_signatures|.
- std::vector<FormStructure*> queried_forms;
- queried_forms.reserve(queried_form_signatures.size());
- for (const auto& form_signature : queried_form_signatures) {
- FindCachedFormsBySignature(form_signature, &queried_forms);
- }
-
- // Each form signature in |queried_form_signatures| is supposed to be unique,
- // and therefore appear only once. This ensures that
- // FindCachedFormsBySignature() produces an output without duplicates in the
- // forms.
- // TODO(crbug/1064709): |queried_forms| could be a set data structure; their
- // order should be irrelevant.
- DCHECK_EQ(queried_forms.size(),
- std::set<FormStructure*>(queried_forms.begin(), queried_forms.end())
- .size());
-
- // If there are no current forms corresponding to the queried signatures, drop
- // the query response.
- if (queried_forms.empty())
- return;
-
- // Parse and store the server predictions.
- FormStructure::ParseApiQueryResponse(std::move(response), queried_forms,
- queried_form_signatures,
- form_interactions_ukm_logger());
-
- // Will log quality metrics for each FormStructure based on the presence of
- // autocomplete attributes, if available.
- if (auto* logger = form_interactions_ukm_logger()) {
- for (FormStructure* cur_form : queried_forms) {
- cur_form->LogQualityMetricsBasedOnAutocomplete(logger);
- }
- }
-
- // Send field type predictions to the renderer so that it can possibly
- // annotate forms with the predicted types or add console warnings.
- driver()->SendAutofillTypePredictionsToRenderer(queried_forms);
-
- LogAutofillTypePredictionsAvailable(log_manager_, queried_forms);
-
- // TODO(crbug.com/1176816): Remove the test code after initial integration.
- int delay = 0;
- if (auto* cmd = base::CommandLine::ForCurrentProcess()) {
- // This command line helps to simulate query result arriving after autofill
- // is triggered and shall be used for manual test only.
- std::string value = cmd->GetSwitchValueASCII(
- "autofill-server-query-result-delay-in-seconds");
- if (!base::StringToInt(value, &delay))
- delay = 0;
- }
-
- if (delay > 0) {
- query_result_delay_task_.Reset(
- base::BindOnce(&AutofillHandler::PropagateAutofillPredictionsToDriver,
- base::Unretained(this)));
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(query_result_delay_task_.callback(), queried_forms),
- base::TimeDelta::FromSeconds(delay));
- } else {
- PropagateAutofillPredictionsToDriver(queried_forms);
- }
-}
-
-void AutofillHandler::PropagateAutofillPredictionsToDriver(
- const std::vector<FormStructure*>& queried_forms) {
- // Forward form structures to the password generation manager to detect
- // account creation forms.
- driver()->PropagateAutofillPredictions(queried_forms);
-}
-
-void AutofillHandler::OnServerRequestError(
- FormSignature form_signature,
- AutofillDownloadManager::RequestType request_type,
- int http_error) {}
-
-} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_handler.h b/chromium/components/autofill/core/browser/autofill_handler.h
deleted file mode 100644
index 5f1345c5216..00000000000
--- a/chromium/components/autofill/core/browser/autofill_handler.h
+++ /dev/null
@@ -1,378 +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_AUTOFILL_CORE_BROWSER_AUTOFILL_HANDLER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_HANDLER_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/cancelable_callback.h"
-#include "base/compiler_specific.h"
-#include "base/scoped_observation.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "components/autofill/core/browser/autofill_download_manager.h"
-#include "components/autofill/core/browser/autofill_driver.h"
-#include "components/autofill/core/browser/autofill_metrics.h"
-#include "components/autofill/core/common/dense_set.h"
-#include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/language_code.h"
-#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
-#include "components/autofill/core/common/signatures.h"
-#include "components/autofill/core/common/unique_ids.h"
-#include "components/translate/core/browser/translate_driver.h"
-#include "components/version_info/channel.h"
-
-namespace gfx {
-class RectF;
-}
-
-namespace autofill {
-
-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.
-class AutofillHandler
- : public AutofillDownloadManager::Observer,
- public translate::TranslateDriver::LanguageDetectionObserver {
- public:
- enum AutofillDownloadManagerState {
- ENABLE_AUTOFILL_DOWNLOAD_MANAGER,
- DISABLE_AUTOFILL_DOWNLOAD_MANAGER,
- };
-
- // An observer class used by browsertests that gets notified whenever
- // particular actions occur.
- class ObserverForTest {
- public:
- virtual void OnFormParsed() = 0;
- };
-
- // Rich queries are enabled by feature flag iff this chrome instance is
- // neither on the STABLE nor BETA release channel.
- static bool IsRichQueryEnabled(version_info::Channel channel);
-
- // Raw metadata uploading enabled iff this Chrome instance is on Canary or Dev
- // channel.
- static bool IsRawMetadataUploadingEnabled(version_info::Channel channel);
-
- // TODO(crbug.com/1151542): Move to anonymous namespace once
- // AutofillManager::OnLoadedServerPredictions() moves to AutofillHandler.
- static void LogAutofillTypePredictionsAvailable(
- LogManager* log_manager,
- const std::vector<FormStructure*>& forms);
-
- ~AutofillHandler() override;
-
- AutofillClient* client() { return client_; }
- const AutofillClient* client() const { return client_; }
-
- // Invoked when the value of textfield is changed.
- void OnTextFieldDidChange(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box,
- const base::TimeTicks timestamp);
-
- // Invoked when the textfield is scrolled.
- void OnTextFieldDidScroll(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box);
-
- // Invoked when the value of select is changed.
- void OnSelectControlDidChange(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box);
-
- // Invoked when the |form| needs to be autofilled, the |bounding_box| is
- // a window relative value of |field|.
- void OnQueryFormFieldAutofill(int query_id,
- const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box,
- bool autoselect_first_suggestion);
-
- // Invoked when |form|'s |field| has focus.
- void OnFocusOnFormField(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box);
-
- // Invoked when |form| has been submitted.
- // Processes the submitted |form|, saving any new Autofill data to the user's
- // personal profile.
- void OnFormSubmitted(const FormData& form,
- bool known_success,
- mojom::SubmissionSource source);
-
- // Invoked when |forms| has been detected.
- void OnFormsSeen(const std::vector<FormData>& forms);
-
- // Invoked when focus is no longer on form. |had_interacted_form| indicates
- // whether focus was previously on a form with which the user had interacted.
- virtual void OnFocusNoLongerOnForm(bool had_interacted_form) = 0;
-
- // Invoked when |form| has been filled with the value given by
- // SendFormDataToRenderer.
- virtual void OnDidFillAutofillFormData(const FormData& form,
- const base::TimeTicks timestamp) = 0;
-
- // Invoked when preview autofill value has been shown.
- virtual void OnDidPreviewAutofillFormData() = 0;
-
- // Invoked when textfeild editing ended
- virtual void OnDidEndTextFieldEditing() = 0;
-
- // Invoked when popup window should be hidden.
- virtual void OnHidePopup() = 0;
-
- // Invoked when the options of a select element in the |form| changed.
- virtual void SelectFieldOptionsDidChange(const FormData& form) = 0;
-
- // Invoked when the field type predictions are downloaded from the autofill
- // server.
- virtual void PropagateAutofillPredictions(
- content::RenderFrameHost* rfh,
- const std::vector<FormStructure*>& forms) = 0;
-
- // Resets cache.
- virtual void Reset();
-
- // translate::TranslateDriver::LanguageDetectionObserver:
- void OnTranslateDriverDestroyed(
- translate::TranslateDriver* translate_driver) override;
- // Invoked when the language has been detected by the Translate component.
- // As this usually happens after Autofill has parsed the forms for the first
- // time, the heuristics need to be re-run by this function in order to run
- // use language-specific patterns.
- void OnLanguageDetermined(
- const translate::LanguageDetectionDetails& details) override;
-
- // Send the form |data| to renderer for the specified |action|.
- void SendFormDataToRenderer(int query_id,
- AutofillDriver::RendererFormDataAction action,
- const FormData& data);
-
- // Fills |form_structure| and |autofill_field| with the cached elements
- // corresponding to |form| and |field|. This might have the side-effect of
- // updating the cache. Returns false if the |form| is not autofillable, or if
- // it is not already present in the cache and the cache is full.
- bool GetCachedFormAndField(const FormData& form,
- const FormFieldData& field,
- FormStructure** form_structure,
- AutofillField** autofill_field) WARN_UNUSED_RESULT;
-
- // Returns nullptr if no cached form structure is found with a matching
- // |form_id|. Runs in logarithmic time.
- FormStructure* FindCachedFormByRendererId(FormGlobalId form_id) const;
-
- // Returns the number of forms this Autofill handler is aware of.
- size_t NumFormsDetected() const { return form_structures_.size(); }
-
- void SetEventObserverForTesting(ObserverForTest* observer) {
- observer_for_testing_ = observer;
- }
-
- // Returns the present form structures seen by Autofill handler.
- const std::map<FormGlobalId, std::unique_ptr<FormStructure>>&
- form_structures() const {
- return form_structures_;
- }
-
- AutofillDriver* driver() { return driver_; }
-
- AutofillDownloadManager* download_manager() {
- return download_manager_.get();
- }
-
- // The return value shouldn't be cached, retrieve it as needed.
- AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger() {
- return form_interactions_ukm_logger_.get();
- }
-
- // A public wrapper that calls |OnLoadedServerPredictions| for testing
- // purposes only, it is used by WebView integration test and unit test, so it
- // can't be in #ifdef UNIT_TEST.
- void OnLoadedServerPredictionsForTest(
- std::string response,
- const std::vector<FormSignature>& queried_form_signatures) {
- OnLoadedServerPredictions(response, queried_form_signatures);
- }
- void OnServerRequestErrorForTest(
- FormSignature form_signature,
- AutofillDownloadManager::RequestType request_type,
- int http_error) {
- OnServerRequestError(form_signature, request_type, http_error);
- }
-#ifdef UNIT_TEST
- // A public wrapper that calls |mutable_form_structures| for testing purposes
- // only.
- std::map<FormGlobalId, std::unique_ptr<FormStructure>>*
- mutable_form_structures_for_test() {
- return mutable_form_structures();
- }
-
- // A public wrapper that calls |ParseForm| for testing purposes only.
- FormStructure* ParseFormForTest(const FormData& form) {
- return ParseForm(form, nullptr);
- }
-
-#endif // UNIT_TEST
-
- protected:
- AutofillHandler(AutofillDriver* driver,
- AutofillClient* client,
- AutofillDownloadManagerState enable_download_manager);
- AutofillHandler(AutofillDriver* driver,
- AutofillClient* client,
- AutofillDownloadManagerState enable_download_manager,
- version_info::Channel channel);
-
- LogManager* log_manager() { return log_manager_; }
-
- // Retrieves the page language from |client_|
- LanguageCode GetCurrentPageLanguage() const;
-
- virtual void OnFormSubmittedImpl(const FormData& form,
- bool known_success,
- mojom::SubmissionSource source) = 0;
-
- virtual void OnTextFieldDidChangeImpl(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box,
- const base::TimeTicks timestamp) = 0;
-
- virtual void OnTextFieldDidScrollImpl(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) = 0;
-
- virtual void OnQueryFormFieldAutofillImpl(
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box,
- bool autoselect_first_suggestion) = 0;
-
- virtual void OnFocusOnFormFieldImpl(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) = 0;
-
- virtual void OnSelectControlDidChangeImpl(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) = 0;
-
- // Return whether the |forms| from OnFormSeen() should be parsed to
- // form_structures.
- virtual bool ShouldParseForms(const std::vector<FormData>& forms) = 0;
-
- // Invoked before parsing the forms.
- virtual void OnBeforeProcessParsedForms() = 0;
-
- // Invoked when the given |form| has been processed to the given
- // |form_structure|.
- virtual void OnFormProcessed(const FormData& form,
- const FormStructure& form_structure) = 0;
- // Invoked after all forms have been processed, |form_types| is a set of
- // FormType found.
- virtual void OnAfterProcessParsedForms(
- const DenseSet<FormType>& form_types) = 0;
-
- // Returns the number of FormStructures with the given |form_signature| and
- // appends them to |form_structures|. Runs in linear time.
- size_t FindCachedFormsBySignature(
- FormSignature form_signature,
- std::vector<FormStructure*>* form_structures) const;
-
- // Parses the |form| with the server data retrieved from the |cached_form|
- // (if any). Returns nullptr if the form should not be parsed. Otherwise, adds
- // the returned form structure to the |form_structures_|.
- FormStructure* ParseForm(const FormData& form,
- const FormStructure* cached_form);
-
- bool value_from_dynamic_change_form_ = false;
-
- std::map<FormGlobalId, std::unique_ptr<FormStructure>>*
- mutable_form_structures() {
- return &form_structures_;
- }
-
-#ifdef UNIT_TEST
- // Exposed for testing.
- void set_download_manager_for_test(
- std::unique_ptr<AutofillDownloadManager> manager) {
- download_manager_ = std::move(manager);
- }
-
- // Exposed for testing.
- bool is_rich_query_enabled() const { return is_rich_query_enabled_; }
-#endif // UNIT_TEST
-
- private:
- // AutofillDownloadManager::Observer:
- void OnLoadedServerPredictions(
- std::string response,
- const std::vector<FormSignature>& queried_form_signatures) override;
- void OnServerRequestError(FormSignature form_signature,
- AutofillDownloadManager::RequestType request_type,
- int http_error) override;
-
- // Invoked when forms from OnFormsSeen() have been parsed to
- // |form_structures|.
- void OnFormsParsed(const std::vector<const FormData*>& forms);
-
- void PropagateAutofillPredictionsToDriver(
- const std::vector<FormStructure*>& forms);
-
- std::unique_ptr<AutofillMetrics::FormInteractionsUkmLogger>
- CreateFormInteractionsUkmLogger();
-
- // Provides driver-level context to the shared code of the component. Must
- // outlive this object.
- AutofillDriver* const driver_;
-
- AutofillClient* const client_;
-
- LogManager* const log_manager_;
-
- // Observer needed to re-run heuristics when the language has been detected.
- base::ScopedObservation<
- translate::TranslateDriver,
- translate::TranslateDriver::LanguageDetectionObserver,
- &translate::TranslateDriver::AddLanguageDetectionObserver,
- &translate::TranslateDriver::RemoveLanguageDetectionObserver>
- translate_observation_{this};
-
- // Our copy of the form data.
- std::map<FormGlobalId, std::unique_ptr<FormStructure>> form_structures_;
-
- // Handles queries and uploads to Autofill servers. Will be nullptr if
- // the download manager functionality is disabled.
- std::unique_ptr<AutofillDownloadManager> download_manager_;
-
- // Utility for logging URL keyed metrics.
- std::unique_ptr<AutofillMetrics::FormInteractionsUkmLogger>
- form_interactions_ukm_logger_;
-
- // Tracks whether or not rich query encoding is enabled for this client.
- const bool is_rich_query_enabled_ = false;
-
- // Task to delay propagate the query result to driver for testing.
- base::CancelableOnceCallback<void(const std::vector<FormStructure*>&)>
- query_result_delay_task_;
-
- // Will be not null only for |SaveCardBubbleViewsFullFormBrowserTest|.
- ObserverForTest* observer_for_testing_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(AutofillHandler);
-};
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_HANDLER_H_
diff --git a/chromium/components/autofill/core/browser/autofill_handler_proxy.cc b/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
deleted file mode 100644
index 8698501e79c..00000000000
--- a/chromium/components/autofill/core/browser/autofill_handler_proxy.cc
+++ /dev/null
@@ -1,115 +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/autofill_handler_proxy.h"
-
-#include "components/autofill/core/browser/autofill_provider.h"
-
-namespace autofill {
-
-using base::TimeTicks;
-
-AutofillHandlerProxy::AutofillHandlerProxy(
- AutofillDriver* driver,
- AutofillClient* client,
- AutofillProvider* provider,
- AutofillHandler::AutofillDownloadManagerState enable_download_manager)
- : AutofillHandler(driver,
- client,
- enable_download_manager,
- version_info::Channel::UNKNOWN),
- provider_(provider) {}
-
-AutofillHandlerProxy::~AutofillHandlerProxy() {}
-
-void AutofillHandlerProxy::OnFormSubmittedImpl(const FormData& form,
- bool known_success,
- mojom::SubmissionSource source) {
- provider_->OnFormSubmitted(this, form, known_success, source);
-}
-
-void AutofillHandlerProxy::OnTextFieldDidChangeImpl(
- const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box,
- const TimeTicks timestamp) {
- provider_->OnTextFieldDidChange(this, form, field, bounding_box, timestamp);
-}
-
-void AutofillHandlerProxy::OnTextFieldDidScrollImpl(
- const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) {
- provider_->OnTextFieldDidScroll(this, form, field, bounding_box);
-}
-
-void AutofillHandlerProxy::OnQueryFormFieldAutofillImpl(
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box,
- bool autoselect_first_suggestion) {
- provider_->OnQueryFormFieldAutofill(this, query_id, form, field, bounding_box,
- autoselect_first_suggestion);
-}
-
-void AutofillHandlerProxy::OnFocusOnFormFieldImpl(
- const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) {
- provider_->OnFocusOnFormField(this, form, field, bounding_box);
-}
-
-void AutofillHandlerProxy::OnSelectControlDidChangeImpl(
- const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) {
- provider_->OnSelectControlDidChange(this, form, field, bounding_box);
-}
-
-bool AutofillHandlerProxy::ShouldParseForms(
- const std::vector<FormData>& forms) {
- provider_->OnFormsSeen(this, forms);
- // Need to parse the |forms| to FormStructure, so heuristic_type can be
- // retrieved later.
- return true;
-}
-
-void AutofillHandlerProxy::OnFocusNoLongerOnForm(bool had_interacted_form) {
- provider_->OnFocusNoLongerOnForm(this, had_interacted_form);
-}
-
-void AutofillHandlerProxy::OnDidFillAutofillFormData(
- const FormData& form,
- const base::TimeTicks timestamp) {
- provider_->OnDidFillAutofillFormData(this, form, timestamp);
-}
-
-void AutofillHandlerProxy::OnHidePopup() {
- provider_->OnHidePopup(this);
-}
-
-void AutofillHandlerProxy::SelectFieldOptionsDidChange(const FormData& form) {}
-
-void AutofillHandlerProxy::PropagateAutofillPredictions(
- content::RenderFrameHost* rfh,
- const std::vector<FormStructure*>& forms) {
- has_server_prediction_ = true;
- provider_->OnServerPredictionsAvailable(this);
-}
-
-void AutofillHandlerProxy::OnServerRequestError(
- FormSignature form_signature,
- AutofillDownloadManager::RequestType request_type,
- int http_error) {
- provider_->OnServerQueryRequestError(this, form_signature);
-}
-
-void AutofillHandlerProxy::Reset() {
- AutofillHandler::Reset();
- has_server_prediction_ = false;
- provider_->Reset(this);
-}
-
-} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_manager.cc b/chromium/components/autofill/core/browser/autofill_manager.cc
index b7d457b8fa9..ec4b069c3f7 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/autofill_manager.cc
@@ -1,2714 +1,566 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// 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/autofill_manager.h"
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <limits>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
#include "base/bind.h"
-#include "base/check_op.h"
-#include "base/command_line.h"
#include "base/containers/adapters.h"
-#include "base/containers/flat_map.h"
#include "base/feature_list.h"
-#include "base/files/file_util.h"
-#include "base/guid.h"
-#include "base/i18n/rtl.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/notreached.h"
-#include "base/path_service.h"
-#include "base/ranges/algorithm.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
-#include "base/task/thread_pool.h"
-#include "base/threading/thread_restrictions.h"
-#include "build/build_config.h"
-#include "build/chromeos_buildflags.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"
-#include "components/autofill/core/browser/autofill_field.h"
-#include "components/autofill/core/browser/autofill_manager_test_delegate.h"
-#include "components/autofill/core/browser/autofill_metrics.h"
-#include "components/autofill/core/browser/autofill_type.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/autofill_profile_comparator.h"
-#include "components/autofill/core/browser/data_model/credit_card.h"
-#include "components/autofill/core/browser/data_model/phone_number.h"
-#include "components/autofill/core/browser/field_types.h"
-#include "components/autofill/core/browser/form_data_importer.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill/core/browser/form_structure.h"
-#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/form_events.h"
-#include "components/autofill/core/browser/payments/autofill_offer_manager.h"
-#include "components/autofill/core/browser/payments/credit_card_access_manager.h"
-#include "components/autofill/core/browser/payments/payments_client.h"
-#include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/randomized_encoder.h"
-#include "components/autofill/core/browser/ui/popup_item_ids.h"
-#include "components/autofill/core/browser/validation.h"
-#include "components/autofill/core/common/autofill_clock.h"
-#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/autofill_data_validation.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_payments_features.h"
-#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/autofill_tick_clock.h"
-#include "components/autofill/core/common/autofill_util.h"
-#include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/form_data_predictions.h"
-#include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/password_form_fill_data.h"
-#include "components/autofill/core/common/signatures.h"
-#include "components/pref_registry/pref_registry_syncable.h"
-#include "components/prefs/pref_service.h"
-#include "components/security_interstitials/core/pref_names.h"
-#include "components/security_state/core/security_state.h"
-#include "components/strings/grit/components_strings.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/geometry/rect.h"
-#include "url/gurl.h"
-
-#if defined(OS_IOS)
-#include "components/autofill/core/browser/keyboard_accessory_metrics_logger.h"
-#endif
+#include "components/translate/core/common/language_detection_details.h"
+#include "google_apis/google_api_keys.h"
+#include "ui/gfx/geometry/rect_f.h"
namespace autofill {
-using base::StartsWith;
-using base::TimeTicks;
-using mojom::SubmissionSource;
-
-constexpr int kCreditCardSigninPromoImpressionLimit = 3;
-
namespace {
-const size_t kMaxRecentFormSignaturesToRemember = 3;
-
-// Time to wait, in ms, after a dynamic form change before triggering a refill.
-// This is used for sites that change multiple things consecutively.
-const size_t kWaitTimeForDynamicFormsMs = 200;
-
-// The time limit, in ms, between a fill and when a refill can happen.
-const int kLimitBeforeRefillMs = 1000;
-
-// Returns the credit card field |value| trimmed from whitespace and with stop
-// characters removed.
-std::u16string SanitizeCreditCardFieldValue(const std::u16string& value) {
- std::u16string sanitized;
- // We remove whitespace as well as some invisible unicode characters.
- base::TrimWhitespace(value, base::TRIM_ALL, &sanitized);
- base::TrimString(sanitized,
- std::u16string({base::i18n::kRightToLeftMark,
- base::i18n::kLeftToRightMark}),
- &sanitized);
- // Some sites have ____-____-____-____ in their credit card number fields, for
- // example.
- base::RemoveChars(sanitized, u"-_", &sanitized);
- return sanitized;
-}
-
-// Returns whether the |field| is predicted as being any kind of name.
-bool IsNameType(const AutofillField& field) {
- return field.Type().group() == FieldTypeGroup::kName ||
- field.Type().group() == FieldTypeGroup::kNameBilling ||
- field.Type().GetStorableType() == CREDIT_CARD_NAME_FULL ||
- field.Type().GetStorableType() == CREDIT_CARD_NAME_FIRST ||
- field.Type().GetStorableType() == CREDIT_CARD_NAME_LAST;
-}
+// Set a conservative upper bound on the number of forms we are willing to
+// cache, simply to prevent unbounded memory consumption.
+const size_t kAutofillManagerMaxFormCacheSize = 100;
-// Selects the right name type from the |old_types| to insert into the
-// |types_to_keep| based on |is_credit_card|. This is called when we have
-// multiple possible types.
-void SelectRightNameType(AutofillField* field, bool is_credit_card) {
- DCHECK(field);
- // Currently, there can be up to four possible types for a field.
- DCHECK_GE(4U, field->possible_types().size());
- DCHECK_LE(2U, field->possible_types().size());
-
- ServerFieldTypeSet types_to_keep;
- const auto& old_types = field->possible_types();
-
- for (auto type : old_types) {
- FieldTypeGroup group = AutofillType(type).group();
- if ((is_credit_card && group == FieldTypeGroup::kCreditCard) ||
- (!is_credit_card && group == FieldTypeGroup::kName)) {
- types_to_keep.insert(type);
- }
+// Returns the AutofillField* corresponding to |field| in |form| or nullptr,
+// if not found.
+AutofillField* FindAutofillFillField(const FormStructure& form,
+ const FormFieldData& field) {
+ for (const auto& f : form) {
+ if (field.global_id() == f->global_id())
+ return f.get();
}
-
- ServerFieldTypeValidityStatesMap new_types_validities;
- // Since the disambiguation takes place when we up to four possible types,
- // here we can add up to three remaining types when only one is removed.
- for (auto type_to_keep : types_to_keep) {
- new_types_validities[type_to_keep] =
- field->get_validities_for_possible_type(type_to_keep);
- }
- field->set_possible_types(types_to_keep);
- field->set_possible_types_validities(new_types_validities);
-}
-
-void LogDeveloperEngagementUkm(ukm::UkmRecorder* ukm_recorder,
- ukm::SourceId source_id,
- const FormStructure& form_structure) {
- if (form_structure.developer_engagement_metrics()) {
- AutofillMetrics::LogDeveloperEngagementUkm(
- ukm_recorder, source_id, form_structure.main_frame_origin().GetURL(),
- form_structure.IsCompleteCreditCardForm(),
- form_structure.GetFormTypes(),
- form_structure.developer_engagement_metrics(),
- form_structure.form_signature());
- }
-}
-
-ValuePatternsMetric GetValuePattern(const std::u16string& value) {
- if (IsUPIVirtualPaymentAddress(value))
- return ValuePatternsMetric::kUpiVpa;
- if (IsInternationalBankAccountNumber(value))
- return ValuePatternsMetric::kIban;
- return ValuePatternsMetric::kNoPatternFound;
-}
-
-void LogValuePatternsMetric(const FormData& form) {
- for (const FormFieldData& field : form.fields) {
- if (!field.IsVisible()) {
- // Ignore hidden fields.
- continue;
+ for (const auto& cur_field : form) {
+ if (cur_field->SameFieldAs(field)) {
+ return cur_field.get();
}
- std::u16string value;
- base::TrimWhitespace(field.value, base::TRIM_ALL, &value);
- if (value.empty())
- continue;
- base::UmaHistogramEnumeration("Autofill.SubmittedValuePatterns",
- GetValuePattern(value));
}
+ return nullptr;
}
-void LogLanguageMetrics(const translate::LanguageState* language_state) {
- if (language_state) {
- AutofillMetrics::LogFieldParsingTranslatedFormLanguageMetric(
- language_state->current_language());
- AutofillMetrics::LogFieldParsingPageTranslationStatusMetric(
- language_state->IsPageTranslated());
- }
-}
+// Returns true if |live_form| does not match |cached_form|, assuming that
+// |live_form|'s language is |live_form_language|.
+bool CachedFormNeedsUpdate(const FormData& live_form,
+ const FormStructure& cached_form) {
+ if (live_form.fields.size() != cached_form.field_count())
+ return true;
-bool IsAddressForm(FieldTypeGroup field_type_group) {
- switch (field_type_group) {
- case FieldTypeGroup::kName:
- case FieldTypeGroup::kNameBilling:
- case FieldTypeGroup::kEmail:
- case FieldTypeGroup::kCompany:
- case FieldTypeGroup::kAddressHome:
- case FieldTypeGroup::kAddressBilling:
- case FieldTypeGroup::kPhoneHome:
- case FieldTypeGroup::kPhoneBilling:
+ for (size_t i = 0; i < cached_form.field_count(); ++i) {
+ if (!cached_form.field(i)->SameFieldAs(live_form.fields[i]))
return true;
- case FieldTypeGroup::kCreditCard:
- case FieldTypeGroup::kTransaction:
- case FieldTypeGroup::kPasswordField:
- case FieldTypeGroup::kUsernameField:
- case FieldTypeGroup::kNoGroup:
- case FieldTypeGroup::kUnfillable:
- return false;
}
- NOTREACHED();
- return false;
-}
-// Finds the first field in |form_structure| with |field.value|=|value|.
-AutofillField* FindFirstFieldWithValue(const FormStructure& form_structure,
- const std::u16string& value) {
- for (const auto& field : form_structure) {
- std::u16string trimmed_value;
- base::TrimWhitespace(field->value, base::TRIM_ALL, &trimmed_value);
- if (trimmed_value == value)
- return field.get();
- }
- return nullptr;
+ return false;
}
-// Heuristically identifies all possible credit card verification fields.
-AutofillField* HeuristicallyFindCVCFieldForUpload(
- 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());
-
- std::u16string 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;
+std::string GetAPIKeyForUrl(version_info::Channel channel) {
+ // First look if we can get API key from command line flag.
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kAutofillAPIKey))
+ return command_line.GetSwitchValueASCII(switches::kAutofillAPIKey);
- return field.get();
- }
- return nullptr;
+ // Get the API key from Chrome baked keys.
+ if (channel == version_info::Channel::STABLE)
+ return google_apis::GetAPIKey();
+ return google_apis::GetNonStableAPIKey();
}
-// Iff the CVC of the credit card is known, find the first field with this
-// value (also set |properties_mask| to |kKnownValue|). Otherwise, heuristically
-// search for the CVC field if any.
-AutofillField* GetBestPossibleCVCFieldForUpload(
- const FormStructure& form_structure,
- std::u16string 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::kKnownValue;
- return result;
- }
-
- return HeuristicallyFindCVCFieldForUpload(form_structure);
-}
+} // namespace
-// Some autofill types are detected based on values and not based on form
-// features. We may decide that it's an autofill form after submission.
-bool ContainsAutofillableValue(const autofill::FormStructure& form) {
- return base::ranges::any_of(form, [](const auto& field) {
- return base::Contains(field->possible_types(), UPI_VPA) ||
- IsUPIVirtualPaymentAddress(field->value);
- });
-}
+using base::TimeTicks;
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
-// Retrieves all valid credit card candidates for virtual card selection. A
-// valid candidate must have exactly one cloud token.
-std::vector<CreditCard*> GetVirtualCardCandidates(
- PersonalDataManager* personal_data_manager) {
- DCHECK(personal_data_manager);
- std::vector<CreditCard*> candidates =
- personal_data_manager->GetServerCreditCards();
- const std::vector<CreditCardCloudTokenData*> cloud_token_data =
- personal_data_manager->GetCreditCardCloudTokenData();
-
- // Constructs map.
- std::unordered_map<std::string, int> id_count;
- for (CreditCardCloudTokenData* data : cloud_token_data) {
- const auto& iterator = id_count.find(data->masked_card_id);
- if (iterator == id_count.end())
- id_count.emplace(data->masked_card_id, 1);
- else
- iterator->second += 1;
+// static
+void AutofillManager::LogAutofillTypePredictionsAvailable(
+ LogManager* log_manager,
+ const std::vector<FormStructure*>& forms) {
+ if (VLOG_IS_ON(1)) {
+ VLOG(1) << "Parsed forms:";
+ for (FormStructure* form : forms)
+ VLOG(1) << *form;
}
- // Remove the card from the vector that either has multiple cloud token data
- // or has no cloud token data.
- base::EraseIf(candidates, [&](const auto& card) {
- const auto& iterator = id_count.find(card->server_id());
- return iterator == id_count.end() || iterator->second > 1;
- });
+ if (!log_manager || !log_manager->IsLoggingActive())
+ return;
- // Returns the remaining valid cards.
- return candidates;
-}
-#endif
-
-const char* SubmissionSourceToString(SubmissionSource source) {
- switch (source) {
- case SubmissionSource::NONE:
- return "NONE";
- case SubmissionSource::SAME_DOCUMENT_NAVIGATION:
- return "SAME_DOCUMENT_NAVIGATION";
- case SubmissionSource::XHR_SUCCEEDED:
- return "XHR_SUCCEEDED";
- case SubmissionSource::FRAME_DETACHED:
- return "FRAME_DETACHED";
- case SubmissionSource::DOM_MUTATION_AFTER_XHR:
- return "DOM_MUTATION_AFTER_XHR";
- case SubmissionSource::PROBABLY_FORM_SUBMITTED:
- return "PROBABLY_FORM_SUBMITTED";
- case SubmissionSource::FORM_SUBMISSION:
- return "FORM_SUBMISSION";
- }
- return "Unknown";
-}
+ LogBuffer buffer;
+ for (FormStructure* form : forms)
+ buffer << *form;
-// Returns how many fields with type |field_type| may be filled in a form at
-// maximum.
-size_t TypeValueFormFillingLimit(ServerFieldType field_type) {
- switch (field_type) {
- case CREDIT_CARD_NUMBER:
- return kCreditCardTypeValueFormFillingLimit;
- case ADDRESS_HOME_STATE:
- return kStateTypeValueFormFillingLimit;
- default:
- return kTypeValueFormFillingLimit;
- }
+ log_manager->Log() << LoggingScope::kParsing << LogMessage::kParsedForms
+ << std::move(buffer);
}
-} // namespace
-
-AutofillManager::FillingContext::FillingContext(
- const AutofillField& field,
- absl::variant<const AutofillProfile*, const CreditCard*>
- profile_or_credit_card,
- const std::u16string* optional_cvc)
- : filled_field_id(field.global_id()),
- filled_field_signature(field.GetFieldSignature()),
- filled_field_unique_name(field.unique_name()),
- original_fill_time(AutofillTickClock::NowTicks()) {
- DCHECK(absl::holds_alternative<const CreditCard*>(profile_or_credit_card) ||
- !optional_cvc);
-
- if (absl::holds_alternative<const AutofillProfile*>(profile_or_credit_card)) {
- profile_or_credit_card_with_cvc =
- *absl::get<const AutofillProfile*>(profile_or_credit_card);
- } else if (absl::holds_alternative<const CreditCard*>(
- profile_or_credit_card)) {
- profile_or_credit_card_with_cvc =
- std::make_pair(*absl::get<const CreditCard*>(profile_or_credit_card),
- optional_cvc ? *optional_cvc : std::u16string());
- }
+// static
+bool AutofillManager::IsRawMetadataUploadingEnabled(
+ version_info::Channel channel) {
+ return channel == version_info::Channel::CANARY ||
+ channel == version_info::Channel::DEV;
}
-AutofillManager::FillingContext::~FillingContext() = default;
-
AutofillManager::AutofillManager(
AutofillDriver* driver,
AutofillClient* client,
- const std::string& app_locale,
AutofillDownloadManagerState enable_download_manager)
: AutofillManager(driver,
client,
- client->GetPersonalDataManager(),
- client->GetAutocompleteHistoryManager(),
- app_locale,
- enable_download_manager) {}
+ enable_download_manager,
+ client->GetChannel()) {
+ DCHECK(driver);
+ DCHECK(client);
+}
AutofillManager::AutofillManager(
AutofillDriver* driver,
AutofillClient* client,
- PersonalDataManager* personal_data,
- AutocompleteHistoryManager* autocomplete_history_manager,
- const std::string app_locale,
AutofillDownloadManagerState enable_download_manager,
- std::unique_ptr<CreditCardAccessManager> cc_access_manager)
- : AutofillHandler(driver, client, enable_download_manager),
- external_delegate_(
- std::make_unique<AutofillExternalDelegate>(this, driver)),
- app_locale_(app_locale),
- personal_data_(personal_data),
- field_filler_(app_locale, client->GetAddressNormalizer()),
- autocomplete_history_manager_(
- autocomplete_history_manager->GetWeakPtr()) {
- address_form_event_logger_ = std::make_unique<AddressFormEventLogger>(
- driver->IsInMainFrame(), form_interactions_ukm_logger(), client);
- credit_card_form_event_logger_ = std::make_unique<CreditCardFormEventLogger>(
- driver->IsInMainFrame(), form_interactions_ukm_logger(), personal_data_,
- 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());
- CountryNames::SetLocaleString(app_locale_);
- offer_manager_ = client->GetAutofillOfferManager();
-}
-
-AutofillManager::~AutofillManager() {
- if (has_parsed_forms_) {
- base::UmaHistogramBoolean(
- "Autofill.WebOTP.PhoneNumberCollection.ParseResult",
- has_observed_phone_number_field_);
- base::UmaHistogramBoolean("Autofill.WebOTP.OneTimeCode.FromAutocomplete",
- has_observed_one_time_code_field_);
- }
-
- if (autocomplete_history_manager_) {
- autocomplete_history_manager_->CancelPendingQueries(this);
- }
-}
-
-void AutofillManager::ShowAutofillSettings(bool show_credit_card_settings) {
- client()->ShowAutofillSettings(show_credit_card_settings);
-}
-
-bool AutofillManager::ShouldShowScanCreditCard(const FormData& form,
- const FormFieldData& field) {
- if (!client()->HasCreditCardScanFeature())
- return false;
-
- AutofillField* autofill_field = GetAutofillField(form, field);
- if (!autofill_field)
- return false;
-
- bool is_card_number_field =
- autofill_field->Type().GetStorableType() == CREDIT_CARD_NUMBER &&
- base::ContainsOnlyChars(CreditCard::StripSeparators(field.value),
- u"0123456789");
-
- if (!is_card_number_field)
- return false;
-
- if (IsFormNonSecure(form))
- return false;
-
- static const int kShowScanCreditCardMaxValueLength = 6;
- return field.value.size() <= kShowScanCreditCardMaxValueLength;
-}
-
-PopupType AutofillManager::GetPopupType(const FormData& form,
- const FormFieldData& field) {
- const AutofillField* autofill_field = GetAutofillField(form, field);
- if (!autofill_field)
- return PopupType::kUnspecified;
-
- switch (autofill_field->Type().group()) {
- case FieldTypeGroup::kNoGroup:
- case FieldTypeGroup::kPasswordField:
- case FieldTypeGroup::kTransaction:
- case FieldTypeGroup::kUsernameField:
- case FieldTypeGroup::kUnfillable:
- return PopupType::kUnspecified;
-
- case FieldTypeGroup::kCreditCard:
- return PopupType::kCreditCards;
-
- case FieldTypeGroup::kAddressHome:
- case FieldTypeGroup::kAddressBilling:
- return PopupType::kAddresses;
-
- case FieldTypeGroup::kName:
- case FieldTypeGroup::kNameBilling:
- case FieldTypeGroup::kEmail:
- case FieldTypeGroup::kCompany:
- case FieldTypeGroup::kPhoneHome:
- case FieldTypeGroup::kPhoneBilling:
- return FormHasAddressField(form) ? PopupType::kAddresses
- : PopupType::kPersonalInformation;
-
- default:
- NOTREACHED();
- }
-}
-
-bool AutofillManager::ShouldShowCreditCardSigninPromo(
- const FormData& form,
- const FormFieldData& field) {
- // Check whether we are dealing with a credit card field and whether it's
- // appropriate to show the promo (e.g. the platform is supported).
- AutofillField* autofill_field = GetAutofillField(form, field);
- if (!autofill_field ||
- autofill_field->Type().group() != FieldTypeGroup::kCreditCard ||
- !client()->ShouldShowSigninPromo())
- return false;
-
- if (IsFormNonSecure(form))
- return false;
-
- // The last step is checking if we are under the limit of impressions.
- int impression_count = client()->GetPrefs()->GetInteger(
- prefs::kAutofillCreditCardSigninPromoImpressionCount);
- if (impression_count < kCreditCardSigninPromoImpressionLimit) {
- // The promo will be shown. Increment the impression count.
- client()->GetPrefs()->SetInteger(
- prefs::kAutofillCreditCardSigninPromoImpressionCount,
- impression_count + 1);
- return true;
+ version_info::Channel channel)
+ : driver_(driver),
+ client_(client),
+ log_manager_(client ? client->GetLogManager() : nullptr),
+ form_interactions_ukm_logger_(CreateFormInteractionsUkmLogger()) {
+ if (enable_download_manager == ENABLE_AUTOFILL_DOWNLOAD_MANAGER) {
+ download_manager_ = std::make_unique<AutofillDownloadManager>(
+ driver, this, GetAPIKeyForUrl(channel),
+ AutofillDownloadManager::IsRawMetadataUploadingEnabled(
+ IsRawMetadataUploadingEnabled(channel)),
+ log_manager_);
}
-
- return false;
-}
-
-bool AutofillManager::ShouldShowCardsFromAccountOption(
- const FormData& form,
- const FormFieldData& field) {
- // Check whether we are dealing with a credit card field.
- AutofillField* autofill_field = GetAutofillField(form, field);
- if (!autofill_field ||
- autofill_field->Type().group() != FieldTypeGroup::kCreditCard ||
- // Exclude CVC and card type fields, because these will not have
- // suggestions available after the user opts in.
- autofill_field->Type().GetStorableType() ==
- CREDIT_CARD_VERIFICATION_CODE ||
- autofill_field->Type().GetStorableType() == CREDIT_CARD_TYPE) {
- return false;
+ if (client) {
+ translate::TranslateDriver* translate_driver = client->GetTranslateDriver();
+ if (translate_driver) {
+ translate_observation_.Observe(translate_driver);
+ }
}
-
- if (IsFormNonSecure(form))
- return false;
-
- return personal_data_->ShouldShowCardsFromAccountOption();
-}
-
-void AutofillManager::OnUserAcceptedCardsFromAccountOption() {
- personal_data_->OnUserAcceptedCardsFromAccountOption();
-}
-
-void AutofillManager::RefetchCardsAndUpdatePopup(
- int query_id,
- const FormData& form,
- const FormFieldData& field_data) {
- AutofillField* autofill_field = GetAutofillField(form, field_data);
- AutofillType type = autofill_field ? autofill_field->Type()
- : AutofillType(CREDIT_CARD_NUMBER);
-
- DCHECK_EQ(FieldTypeGroup::kCreditCard, type.group());
-
- bool should_display_gpay_logo;
- auto cards =
- GetCreditCardSuggestions(field_data, type, &should_display_gpay_logo);
-
- DCHECK(!cards.empty());
-
- external_delegate_->OnSuggestionsReturned(
- query_id, cards,
- /*autoselect_first_suggestion=*/false, should_display_gpay_logo);
-}
-
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
-void AutofillManager::FetchVirtualCardCandidates() {
- const std::vector<CreditCard*>& candidates =
- GetVirtualCardCandidates(personal_data_);
- // Make sure the |candidates| is not empty, otherwise the check in
- // ShouldShowVirtualCardOption() should fail.
- DCHECK(!candidates.empty());
-
- client()->OfferVirtualCardOptions(
- candidates,
- base::BindOnce(&AutofillManager::OnVirtualCardCandidateSelected,
- weak_ptr_factory_.GetWeakPtr()));
}
-void AutofillManager::OnVirtualCardCandidateSelected(
- const std::string& selected_card_id) {
- // TODO(crbug.com/1020740): Implement this and the following flow in a
- // separate CL. The following flow will be sending a request to Payments
- // to fetched the up-to-date cloud token data for the selected card and fill
- // the information in the form.
-}
-#endif
-
-bool AutofillManager::ShouldParseForms(const std::vector<FormData>& forms) {
- bool autofill_enabled = IsAutofillEnabled();
- sync_state_ = personal_data_ ? personal_data_->GetSyncSigninState()
- : AutofillSyncSigninState::kNumSyncStates;
- if (!has_logged_autofill_enabled_) {
- AutofillMetrics::LogIsAutofillEnabledAtPageLoad(autofill_enabled,
- sync_state_);
- AutofillMetrics::LogIsAutofillProfileEnabledAtPageLoad(
- IsAutofillProfileEnabled(), sync_state_);
- AutofillMetrics::LogIsAutofillCreditCardEnabledAtPageLoad(
- IsAutofillCreditCardEnabled(), sync_state_);
- has_logged_autofill_enabled_ = true;
- }
-
- return autofill_enabled;
+AutofillManager::~AutofillManager() {
+ translate_observation_.Reset();
+ if (!query_result_delay_task_.IsCancelled())
+ query_result_delay_task_.Cancel();
}
-void AutofillManager::OnFormSubmittedImpl(const FormData& form,
- bool known_success,
- SubmissionSource source) {
- base::UmaHistogramEnumeration("Autofill.FormSubmission.PerProfileType",
- client()->GetProfileType());
- if (log_manager()) {
- log_manager()->Log() << LoggingScope::kSubmission
- << LogMessage::kFormSubmissionDetected << Br{}
- << "known_success: " << known_success << Br{}
- << "source: " << SubmissionSourceToString(source)
- << Br{} << form;
- }
-
- // Always upload page language metrics.
- LogLanguageMetrics(client()->GetLanguageState());
-
- // Always let the value patterns metric upload data.
- LogValuePatternsMetric(form);
-
- // We will always give Autocomplete a chance to save the data.
- std::unique_ptr<FormStructure> submitted_form = ValidateSubmittedForm(form);
- if (!submitted_form) {
- autocomplete_history_manager_->OnWillSubmitForm(
- form, client()->IsAutocompleteEnabled());
- return;
- }
-
- // However, if Autofill has recognized a field as CVC, that shouldn't be
- // saved.
- FormData form_for_autocomplete = submitted_form->ToFormData();
- for (size_t i = 0; i < submitted_form->field_count(); ++i) {
- if (submitted_form->field(i)->Type().GetStorableType() ==
- CREDIT_CARD_VERIFICATION_CODE) {
- form_for_autocomplete.fields[i].should_autocomplete = false;
- }
- }
- autocomplete_history_manager_->OnWillSubmitForm(
- form_for_autocomplete, client()->IsAutocompleteEnabled());
-
- if (IsAutofillProfileEnabled()) {
- address_form_event_logger_->OnWillSubmitForm(sync_state_, *submitted_form);
- }
- if (IsAutofillCreditCardEnabled()) {
- credit_card_form_event_logger_->OnWillSubmitForm(sync_state_,
- *submitted_form);
- }
-
- submitted_form->set_submission_source(source);
- MaybeStartVoteUploadProcess(std::move(submitted_form),
- /*observed_submission=*/true);
-
- // TODO(crbug.com/803334): Add FormStructure::Clone() method.
- // Create another FormStructure instance.
- submitted_form = ValidateSubmittedForm(form);
- DCHECK(submitted_form);
- if (!submitted_form)
+void AutofillManager::OnLanguageDetermined(
+ const translate::LanguageDetectionDetails& details) {
+ if (!base::FeatureList::IsEnabled(
+ features::kAutofillParsingPatternsLanguageDetection)) {
return;
-
- submitted_form->set_submission_source(source);
-
- if (IsAutofillProfileEnabled()) {
- address_form_event_logger_->OnFormSubmitted(/*force_logging=*/false,
- sync_state_, *submitted_form);
}
- if (IsAutofillCreditCardEnabled()) {
- credit_card_form_event_logger_->OnFormSubmitted(
- enable_ablation_logging_, sync_state_, *submitted_form);
+ for (auto& p : form_structures_) {
+ std::unique_ptr<FormStructure>& form_structure = p.second;
+ form_structure->set_current_page_language(
+ LanguageCode(details.adopted_language));
+ form_structure->DetermineHeuristicTypes(form_interactions_ukm_logger(),
+ log_manager_);
}
-
- if (!submitted_form->IsAutofillable() &&
- !ContainsAutofillableValue(*submitted_form)) {
- return;
- }
-
- // Update Personal Data with the form's submitted data.
- // Also triggers offering local/upload credit card save, if applicable.
- client()->GetFormDataImporter()->ImportFormData(
- *submitted_form, IsAutofillProfileEnabled(),
- IsAutofillCreditCardEnabled());
}
-bool AutofillManager::MaybeStartVoteUploadProcess(
- std::unique_ptr<FormStructure> form_structure,
- bool observed_submission) {
- // It is possible for |personal_data_| to be null, such as when used in the
- // Android webview.
- if (!personal_data_)
- return false;
-
- // Only upload server statistics and UMA metrics if at least some local data
- // is available to use as a baseline.
- std::vector<AutofillProfile*> profiles = personal_data_->GetProfiles();
- personal_data_->UpdateProfilesServerValidityMapsIfNeeded(profiles);
- if (observed_submission && form_structure->IsAutofillable()) {
- AutofillMetrics::LogNumberOfProfilesAtAutofillableFormSubmission(
- personal_data_->GetProfiles().size());
- }
-
- const std::vector<CreditCard*>& credit_cards =
- credit_card_access_manager_->GetCreditCards();
-
- if (profiles.empty() && credit_cards.empty())
- return false;
-
- if (form_structure->field_count() * (profiles.size() + credit_cards.size()) >=
- kMaxTypeMatchingCalls)
- return false;
-
- // Copy the profile and credit card data, so that it can be accessed on a
- // separate thread.
- std::vector<AutofillProfile> copied_profiles;
- copied_profiles.reserve(profiles.size());
- for (const AutofillProfile* profile : profiles)
- copied_profiles.push_back(*profile);
-
- std::vector<CreditCard> copied_credit_cards;
- copied_credit_cards.reserve(credit_cards.size());
- for (const CreditCard* card : credit_cards)
- copied_credit_cards.push_back(*card);
-
- // Annotate the form with the source language of the page.
- form_structure->set_current_page_language(GetCurrentPageLanguage());
-
- // Attach the Randomized Encoder.
- form_structure->set_randomized_encoder(
- RandomizedEncoder::Create(client()->GetPrefs()));
-
- // Determine |ADDRESS_HOME_STATE| as a possible types for the fields in the
- // |form_structure| with the help of |AlternativeStateNameMap|.
- // |AlternativeStateNameMap| can only be accessed on the main UI thread.
- PreProcessStateMatchingTypes(copied_profiles, form_structure.get());
-
- // Note that ownership of |form_structure| is passed to the second task,
- // using |base::Owned|. We MUST temporarily hang on to the raw form pointer
- // 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::ThreadPool::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::MayBlock(), base::TaskPriority::USER_VISIBLE},
- base::BindOnce(&AutofillManager::DeterminePossibleFieldTypesForUpload,
- 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()),
- initial_interaction_timestamp_,
- AutofillTickClock::NowTicks(), observed_submission));
- return true;
+void AutofillManager::OnTranslateDriverDestroyed(
+ translate::TranslateDriver* translate_driver) {
+ translate_observation_.Reset();
}
-void AutofillManager::UpdatePendingForm(const FormData& form) {
- // Process the current pending form if different than supplied |form|.
- if (pending_form_data_ && !pending_form_data_->SameFormAs(form)) {
- ProcessPendingFormForUpload();
- }
- // A new pending form is assigned.
- pending_form_data_ = std::make_unique<FormData>(form);
+LanguageCode AutofillManager::GetCurrentPageLanguage() const {
+ DCHECK(client_);
+ const translate::LanguageState* language_state = client_->GetLanguageState();
+ if (!language_state)
+ return LanguageCode();
+ return LanguageCode(language_state->current_language());
}
-void AutofillManager::ProcessPendingFormForUpload() {
- if (!pending_form_data_)
- return;
-
- // We get the FormStructure corresponding to |pending_form_data_|, used in the
- // upload process. |pending_form_data_| is reset.
- std::unique_ptr<FormStructure> upload_form =
- ValidateSubmittedForm(*pending_form_data_);
- pending_form_data_.reset();
- if (!upload_form)
- return;
-
- MaybeStartVoteUploadProcess(std::move(upload_form),
- /*observed_submission=*/false);
+void AutofillManager::OnFormSubmitted(const FormData& form,
+ bool known_success,
+ mojom::SubmissionSource source) {
+ if (IsValidFormData(form))
+ OnFormSubmittedImpl(form, known_success, source);
}
-void AutofillManager::DidSuppressPopup(const FormData& form,
- const FormFieldData& field) {
- FormStructure* form_structure = nullptr;
- AutofillField* autofill_field = nullptr;
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms) {
+ if (!IsValidFormDataVector(forms) || !driver_->RendererIsAvailable())
return;
- auto* logger = GetEventFormLogger(autofill_field->Type().group());
- if (logger)
- logger->OnPopupSuppressed(*form_structure, *autofill_field);
-}
-
-void AutofillManager::OnTextFieldDidChangeImpl(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box,
- const TimeTicks timestamp) {
- if (test_delegate_)
- test_delegate_->OnTextFieldChanged();
-
- FormStructure* form_structure = nullptr;
- AutofillField* autofill_field = nullptr;
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ // This should be called even forms is empty, AutofillProviderAndroid uses
+ // this event to detect form submission.
+ if (!ShouldParseForms(forms))
return;
- UpdatePendingForm(form);
-
- uint32_t profile_form_bitmask = 0;
- if (!user_did_type_ || autofill_field->is_autofilled) {
- form_interactions_ukm_logger()->LogTextFieldDidChange(*form_structure,
- *autofill_field);
- profile_form_bitmask = data_util::DetermineGroups(*form_structure);
- }
-
- if (!autofill_field->is_autofilled) {
- auto* logger = GetEventFormLogger(autofill_field->Type().group());
- if (logger)
- logger->OnTypedIntoNonFilledField();
- }
-
- if (!user_did_type_) {
- user_did_type_ = true;
- AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::USER_DID_TYPE, autofill_field->Type().group(),
- client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
- }
-
- if (autofill_field->is_autofilled) {
- autofill_field->is_autofilled = false;
- autofill_field->set_previously_autofilled(true);
- AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD,
- autofill_field->Type().group(),
- client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
-
- auto* logger = GetEventFormLogger(autofill_field->Type().group());
- if (logger)
- logger->OnEditedAutofilledField();
-
- if (!user_did_edit_autofilled_field_) {
- user_did_edit_autofilled_field_ = true;
- AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD_ONCE,
- autofill_field->Type().group(),
- client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
- }
- }
-
- UpdateInitialInteractionTimestamp(timestamp);
-}
-
-bool AutofillManager::IsFormNonSecure(const FormData& form) const {
- return IsFormOrClientNonSecure(client(), form);
-}
-
-void AutofillManager::OnQueryFormFieldAutofillImpl(
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& transformed_box,
- bool autoselect_first_suggestion) {
- if (base::FeatureList::IsEnabled(features::kAutofillDisableFilling)) {
+ if (forms.empty())
return;
- }
-
- SetDataList(field.datalist_values, field.datalist_labels);
- external_delegate_->OnQuery(query_id, form, field, transformed_box);
- std::vector<Suggestion> suggestions;
- SuggestionsContext context;
- GetAvailableSuggestions(form, field, &suggestions, &context);
+ std::vector<const FormData*> new_forms;
+ for (const FormData& form : forms) {
+ const auto parse_form_start_time = AutofillTickClock::NowTicks();
+ FormStructure* cached_form_structure =
+ FindCachedFormByRendererId(form.global_id());
- if (context.is_autofill_available) {
- switch (context.suppress_reason) {
- case SuppressReason::kNotSuppressed:
- break;
+ // Not updating signatures of credit card forms is legacy behaviour. We
+ // believe that the signatures are kept stable for voting purposes.
+ bool update_form_signature = false;
+ if (cached_form_structure) {
+ const DenseSet<FormType>& form_types =
+ cached_form_structure->GetFormTypes();
+ update_form_signature =
+ form_types.size() > form_types.count(FormType::kCreditCardForm);
+ }
- case SuppressReason::kCreditCardsAblation:
- enable_ablation_logging_ = true;
- autocomplete_history_manager_->CancelPendingQueries(this);
- external_delegate_->OnSuggestionsReturned(query_id, suggestions,
- autoselect_first_suggestion);
- return;
+ FormStructure* form_structure = ParseForm(form, cached_form_structure);
+ if (!form_structure)
+ continue;
+ DCHECK(form_structure);
- case SuppressReason::kInsecureForm:
- case SuppressReason::kAutocompleteOff:
- return;
- }
+ if (update_form_signature)
+ form_structure->set_form_signature(CalculateFormSignature(form));
- if (!suggestions.empty()) {
- if (context.is_filling_credit_card) {
- AutofillMetrics::LogIsQueriedCreditCardFormSecure(
- context.is_context_secure);
- }
-
- // The first time we show suggestions on this page, log the number of
- // suggestions available.
- // TODO(mathp): Differentiate between number of suggestions available
- // (current metric) and number shown to the user.
- if (!has_logged_address_suggestions_count_) {
- AutofillMetrics::LogAddressSuggestionsCount(suggestions.size());
- has_logged_address_suggestions_count_ = true;
- }
- }
+ new_forms.push_back(&form);
+ AutofillMetrics::LogParseFormTiming(AutofillTickClock::NowTicks() -
+ parse_form_start_time);
}
- // If there are no Autofill suggestions, consider showing Autocomplete
- // suggestions. We will not show Autocomplete suggestions for a field that
- // specifies autocomplete=off (or an unrecognized type), a field for which we
- // will show the credit card signin promo, a field that we think is a
- // credit card expiration, cvc or number, or on forms displayed on secure
- // (i.e. HTTPS) sites that submit insecurely (over HTTP).
- if (suggestions.empty() && !ShouldShowCreditCardSigninPromo(form, field) &&
- field.should_autocomplete &&
- !(context.focused_field &&
- (autofill::data_util::IsCreditCardExpirationType(
- context.focused_field->Type().GetStorableType()) ||
- context.focused_field->Type().html_type() == HTML_TYPE_UNRECOGNIZED ||
- context.focused_field->Type().GetStorableType() ==
- CREDIT_CARD_NUMBER ||
- context.focused_field->Type().GetStorableType() ==
- CREDIT_CARD_VERIFICATION_CODE)) &&
- context.suppress_reason != SuppressReason::kInsecureForm) {
- // Suggestions come back asynchronously, so the Autocomplete manager will
- // handle sending the results back to the renderer.
- autocomplete_history_manager_->OnGetAutocompleteSuggestions(
- query_id, client()->IsAutocompleteEnabled(),
- autoselect_first_suggestion, field.name, field.value,
- field.form_control_type, weak_ptr_factory_.GetWeakPtr());
+ if (new_forms.empty())
return;
- }
-
- // Send Autofill suggestions (could be an empty list).
- autocomplete_history_manager_->CancelPendingQueries(this);
- external_delegate_->OnSuggestionsReturned(query_id, suggestions,
- autoselect_first_suggestion,
- context.should_display_gpay_logo);
+ OnFormsParsed(new_forms);
}
-bool AutofillManager::WillFillCreditCardNumber(const FormData& form,
- const FormFieldData& field) {
- FormStructure* form_structure = nullptr;
- AutofillField* autofill_field = nullptr;
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
- return false;
+void AutofillManager::OnFormsParsed(const std::vector<const FormData*>& forms) {
+ DCHECK(!forms.empty());
+ OnBeforeProcessParsedForms();
- if (autofill_field->Type().GetStorableType() == CREDIT_CARD_NUMBER)
- return true;
+ driver()->HandleParsedForms(forms);
- DCHECK_EQ(form_structure->field_count(), form.fields.size());
- for (size_t i = 0; i < form_structure->field_count(); ++i) {
- if (form_structure->field(i)->section == autofill_field->section &&
- form_structure->field(i)->Type().GetStorableType() ==
- CREDIT_CARD_NUMBER &&
- form.fields[i].value.empty() && !form.fields[i].is_autofilled) {
- return true;
+ std::vector<FormStructure*> non_queryable_forms;
+ std::vector<FormStructure*> queryable_forms;
+ DenseSet<FormType> form_types;
+ for (const FormData* form : forms) {
+ FormStructure* form_structure =
+ FindCachedFormByRendererId(form->global_id());
+ if (!form_structure) {
+ NOTREACHED();
+ continue;
}
- }
-
- return false;
-}
-
-void AutofillManager::FillOrPreviewCreditCardForm(
- AutofillDriver::RendererFormDataAction action,
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- const CreditCard* credit_card) {
- FormStructure* form_structure = nullptr;
- AutofillField* autofill_field = nullptr;
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
- return;
-
- credit_card_ = credit_card ? *credit_card : CreditCard();
- bool is_preview = action != AutofillDriver::FORM_DATA_ACTION_FILL;
- bool should_fetch_card = !is_preview && WillFillCreditCardNumber(form, field);
- if (should_fetch_card) {
- credit_card_form_event_logger_->OnDidSelectCardSuggestion(
- credit_card_, *form_structure, sync_state_);
+ form_types.insert_all(form_structure->GetFormTypes());
- credit_card_action_ = action;
- credit_card_query_id_ = query_id;
- credit_card_form_ = form;
- credit_card_field_ = field;
+ // Configure the query encoding for this form and add it to the appropriate
+ // collection of forms: queryable vs non-queryable.
+ if (form_structure->ShouldBeQueried())
+ queryable_forms.push_back(form_structure);
+ else
+ non_queryable_forms.push_back(form_structure);
- // CreditCardAccessManager::FetchCreditCard() will call
- // OnCreditCardFetched() in this class after successfully fetching the card.
- credit_card_access_manager_->FetchCreditCard(
- credit_card, weak_ptr_factory_.GetWeakPtr(),
- form_structure->form_parsed_timestamp());
- return;
+ OnFormProcessed(*form, *form_structure);
}
- if (!is_preview) {
- credit_card_form_event_logger_->OnDidFillSuggestion(
- credit_card_, *form_structure, *autofill_field, sync_state_);
+ if (!queryable_forms.empty() || !non_queryable_forms.empty()) {
+ OnAfterProcessParsedForms(form_types);
}
- FillOrPreviewDataModelForm(action, query_id, form, field, &credit_card_,
- /*cvc=*/nullptr, form_structure, autofill_field);
-}
+ // Send the current type predictions to the renderer. For non-queryable forms
+ // this is all the information about them that will ever be available. The
+ // queryable forms will be updated once the field type query is complete.
+ driver()->SendAutofillTypePredictionsToRenderer(non_queryable_forms);
+ driver()->SendAutofillTypePredictionsToRenderer(queryable_forms);
+ // Send the fields that are eligible for manual filling to the renderer. If
+ // server predictions are not yet available for these forms, the eligible
+ // fields would be updated again once they are available.
+ driver()->SendFieldsEligibleForManualFillingToRenderer(
+ FormStructure::FindFieldsEligibleForManualFilling(non_queryable_forms));
+ driver()->SendFieldsEligibleForManualFillingToRenderer(
+ FormStructure::FindFieldsEligibleForManualFilling(queryable_forms));
+ LogAutofillTypePredictionsAvailable(log_manager_, non_queryable_forms);
+ LogAutofillTypePredictionsAvailable(log_manager_, queryable_forms);
-void AutofillManager::FillOrPreviewProfileForm(
- AutofillDriver::RendererFormDataAction action,
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- const AutofillProfile& profile) {
- FormStructure* form_structure = nullptr;
- AutofillField* autofill_field = nullptr;
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
- return;
- if (action == AutofillDriver::FORM_DATA_ACTION_FILL) {
- address_form_event_logger_->OnDidFillSuggestion(
- profile, *form_structure, *autofill_field, sync_state_);
+ // Query the server if at least one of the forms was parsed.
+ if (!queryable_forms.empty() && download_manager()) {
+ download_manager()->StartQueryRequest(queryable_forms);
}
-
- FillOrPreviewDataModelForm(action, query_id, form, field, &profile,
- /*cvc=*/nullptr, form_structure, autofill_field);
}
-void AutofillManager::FillOrPreviewForm(
- AutofillDriver::RendererFormDataAction action,
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- int unique_id) {
+void AutofillManager::OnTextFieldDidChange(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box,
+ const TimeTicks timestamp) {
if (!IsValidFormData(form) || !IsValidFormFieldData(field))
return;
- // NOTE: RefreshDataModels may invalidate |data_model|. Thus it must come
- // before GetProfile or GetCreditCard.
- if (!RefreshDataModels() || !driver()->RendererIsAvailable())
- return;
-
- const AutofillProfile* profile = GetProfile(unique_id);
- const CreditCard* credit_card = GetCreditCard(unique_id);
+ gfx::RectF transformed_box =
+ driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
- if (credit_card)
- FillOrPreviewCreditCardForm(action, query_id, form, field, credit_card);
- else if (profile)
- FillOrPreviewProfileForm(action, query_id, form, field, *profile);
+ OnTextFieldDidChangeImpl(form, field, transformed_box, timestamp);
}
-void AutofillManager::FillCreditCardForm(int query_id,
- const FormData& form,
- const FormFieldData& field,
- const CreditCard& credit_card,
- const std::u16string& cvc) {
- if (!IsValidFormData(form) || !IsValidFormFieldData(field) ||
- !driver()->RendererIsAvailable()) {
- return;
- }
-
- FormStructure* form_structure = nullptr;
- AutofillField* autofill_field = nullptr;
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+void AutofillManager::OnTextFieldDidScroll(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) {
+ if (!IsValidFormData(form) || !IsValidFormFieldData(field))
return;
- FillOrPreviewDataModelForm(AutofillDriver::FORM_DATA_ACTION_FILL, query_id,
- form, field, &credit_card, &cvc, form_structure,
- autofill_field);
-}
+ gfx::RectF transformed_box =
+ driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
-void AutofillManager::FillProfileForm(const autofill::AutofillProfile& profile,
- const FormData& form,
- const FormFieldData& field) {
- FillOrPreviewProfileForm(AutofillDriver::FORM_DATA_ACTION_FILL,
- /*query_id=*/-1, form, field, profile);
+ OnTextFieldDidScrollImpl(form, field, transformed_box);
}
-void AutofillManager::OnFocusNoLongerOnForm(bool had_interacted_form) {
- // For historical reasons, Chrome takes action on this message only if focus
- // was previously on a form with which the user had interacted.
- // TODO(crbug.com/1140473): Remove need for this short-circuit.
- if (!had_interacted_form)
+void AutofillManager::OnSelectControlDidChange(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) {
+ if (!IsValidFormData(form) || !IsValidFormFieldData(field))
return;
- ProcessPendingFormForUpload();
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
- // There is no way of determining whether ChromeVox is in use, so assume it's
- // being used.
- external_delegate_->OnAutofillAvailabilityEvent(
- mojom::AutofillState::kNoSuggestions);
-#else
- if (external_delegate_->HasActiveScreenReader()) {
- external_delegate_->OnAutofillAvailabilityEvent(
- mojom::AutofillState::kNoSuggestions);
- }
-#endif
-}
+ gfx::RectF transformed_box =
+ driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
-void AutofillManager::OnFocusOnFormFieldImpl(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) {
- // Notify installed screen readers if the focus is on a field for which there
- // are suggestions to present. Ignore if a screen reader is not present. If
- // the platform is ChromeOS, then assume ChromeVox is in use as there is no
- // way of determining whether it's being used from this point in the code.
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
- if (!external_delegate_->HasActiveScreenReader())
- return;
-#endif
-
- // TODO(https://crbug.com/848427): Add metrics for performance impact.
- std::vector<Suggestion> suggestions;
- SuggestionsContext context;
- GetAvailableSuggestions(form, field, &suggestions, &context);
-
- external_delegate_->OnAutofillAvailabilityEvent(
- (context.suppress_reason == SuppressReason::kNotSuppressed &&
- !suggestions.empty())
- ? mojom::AutofillState::kAutofillAvailable
- : mojom::AutofillState::kNoSuggestions);
+ OnSelectControlDidChangeImpl(form, field, transformed_box);
}
-void AutofillManager::OnSelectControlDidChangeImpl(
+void AutofillManager::OnQueryFormFieldAutofill(
+ int query_id,
const FormData& form,
const FormFieldData& field,
- const gfx::RectF& bounding_box) {
- // TODO(crbug.com/814961): Handle select control change.
-}
-
-void AutofillManager::OnDidPreviewAutofillFormData() {
- if (test_delegate_)
- test_delegate_->DidPreviewFormData();
-}
-
-void AutofillManager::OnDidFillAutofillFormData(const FormData& form,
- const TimeTicks timestamp) {
- if (test_delegate_)
- test_delegate_->DidFillFormData();
-
- UpdatePendingForm(form);
-
- // Find the FormStructure that corresponds to |form|. Use default form type if
- // form is not present in our cache, which will happen rarely.
-
- FormStructure* form_structure = FindCachedFormByRendererId(form.global_id());
- DenseSet<FormType> form_types;
- if (form_structure) {
- form_types = form_structure->GetFormTypes();
- }
-
- uint32_t profile_form_bitmask =
- form_structure ? data_util::DetermineGroups(*form_structure) : 0;
-
- AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::USER_DID_AUTOFILL, form_types,
- client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
- if (!user_did_autofill_) {
- user_did_autofill_ = true;
- AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::USER_DID_AUTOFILL_ONCE, form_types,
- client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
- }
-
- UpdateInitialInteractionTimestamp(timestamp);
-}
-
-void AutofillManager::DidShowSuggestions(bool has_autofill_suggestions,
- const FormData& form,
- const FormFieldData& field) {
- if (test_delegate_)
- test_delegate_->DidShowSuggestions();
-
- if (!has_autofill_suggestions) {
- // If suggestions are not from Autofill, then it means they are from
- // Autocomplete.
- AutofillMetrics::OnAutocompleteSuggestionsShown();
- return;
- }
-
- FormStructure* form_structure = nullptr;
- AutofillField* autofill_field = nullptr;
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
- return;
-
- uint32_t profile_form_bitmask = data_util::DetermineGroups(*form_structure);
- AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::SUGGESTIONS_SHOWN, autofill_field->Type().group(),
- client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
-
- if (!did_show_suggestions_) {
- did_show_suggestions_ = true;
- AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::SUGGESTIONS_SHOWN_ONCE, autofill_field->Type().group(),
- client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
- }
-
- auto* logger = GetEventFormLogger(autofill_field->Type().group());
- if (logger) {
- logger->OnDidShowSuggestions(*form_structure, *autofill_field,
- form_structure->form_parsed_timestamp(),
- sync_state_, driver()->IsIncognito());
- }
-
- if (autofill_field->Type().group() == FieldTypeGroup::kCreditCard &&
- base::FeatureList::IsEnabled(
- features::kAutofillCreditCardAuthentication)) {
- credit_card_access_manager_->PrepareToFetchCreditCard();
- }
-}
-
-void AutofillManager::OnHidePopup() {
- if (!IsAutofillEnabled())
- return;
-
- autocomplete_history_manager_->CancelPendingQueries(this);
- client()->HideAutofillPopup(PopupHidingReason::kRendererEvent);
-}
-
-bool AutofillManager::GetDeletionConfirmationText(const std::u16string& value,
- int identifier,
- std::u16string* title,
- std::u16string* body) {
- if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) {
- if (title)
- title->assign(value);
- if (body) {
- body->assign(l10n_util::GetStringUTF16(
- IDS_AUTOFILL_DELETE_AUTOCOMPLETE_SUGGESTION_CONFIRMATION_BODY));
- }
-
- return true;
- }
-
- if (identifier < 0)
- return false;
-
- const CreditCard* credit_card = GetCreditCard(identifier);
- const AutofillProfile* profile = GetProfile(identifier);
-
- if (credit_card) {
- return credit_card_access_manager_->GetDeletionConfirmationText(
- credit_card, title, body);
- }
-
- if (profile) {
- if (profile->record_type() != AutofillProfile::LOCAL_PROFILE)
- return false;
-
- if (title) {
- std::u16string street_address = profile->GetRawInfo(ADDRESS_HOME_CITY);
- if (!street_address.empty())
- title->swap(street_address);
- else
- title->assign(value);
- }
- if (body) {
- body->assign(l10n_util::GetStringUTF16(
- IDS_AUTOFILL_DELETE_PROFILE_SUGGESTION_CONFIRMATION_BODY));
- }
-
- return true;
- }
-
- NOTREACHED();
- return false;
-}
-
-bool AutofillManager::RemoveAutofillProfileOrCreditCard(int unique_id) {
- const CreditCard* credit_card = GetCreditCard(unique_id);
- if (credit_card) {
- return credit_card_access_manager_->DeleteCard(credit_card);
- }
-
- const AutofillProfile* profile = GetProfile(unique_id);
- if (profile) {
- bool is_local = profile->record_type() == AutofillProfile::LOCAL_PROFILE;
- if (is_local)
- personal_data_->RemoveByGUID(profile->guid());
-
- return is_local;
- }
-
- NOTREACHED();
- return false;
-}
-
-void AutofillManager::RemoveAutocompleteEntry(const std::u16string& name,
- const std::u16string& value) {
- autocomplete_history_manager_->OnRemoveAutocompleteEntry(name, value);
-}
-
-void AutofillManager::OnAutocompleteEntrySelected(const std::u16string& value) {
- autocomplete_history_manager_->OnAutocompleteEntrySelected(value);
-}
-
-void AutofillManager::OnUserHideSuggestions(const FormData& form,
- const FormFieldData& field) {
- FormStructure* form_structure = nullptr;
- AutofillField* autofill_field = nullptr;
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
- return;
-
- auto* logger = GetEventFormLogger(autofill_field->Type().group());
- if (logger)
- logger->OnUserHideSuggestions(*form_structure, *autofill_field);
-}
-
-bool AutofillManager::ShouldClearPreviewedForm() {
- return credit_card_access_manager_->ShouldClearPreviewedForm();
-}
-
-payments::FullCardRequest* AutofillManager::GetOrCreateFullCardRequest() {
- return credit_card_access_manager_->GetOrCreateCVCAuthenticator()
- ->GetFullCardRequest();
-}
-
-base::WeakPtr<payments::FullCardRequest::UIDelegate>
-AutofillManager::GetAsFullCardRequestUIDelegate() {
- return credit_card_access_manager_->GetOrCreateCVCAuthenticator()
- ->GetAsFullCardRequestUIDelegate();
-}
-
-void AutofillManager::SetTestDelegate(AutofillManagerTestDelegate* delegate) {
- test_delegate_ = delegate;
-}
-
-void AutofillManager::SetDataList(const std::vector<std::u16string>& values,
- const std::vector<std::u16string>& labels) {
- if (!IsValidString16Vector(values) || !IsValidString16Vector(labels) ||
- values.size() != labels.size())
- return;
-
- external_delegate_->SetCurrentDataListValues(values, labels);
-}
-
-void AutofillManager::SelectFieldOptionsDidChange(const FormData& form) {
- // Look for a cached version of the form. It will be a null pointer if none is
- // found, which is fine.
- FormStructure* cached_form = FindCachedFormByRendererId(form.global_id());
-
- FormStructure* form_structure = ParseForm(form, cached_form);
- if (!form_structure)
+ const gfx::RectF& bounding_box,
+ bool autoselect_first_suggestion) {
+ if (!IsValidFormData(form) || !IsValidFormFieldData(field))
return;
- if (ShouldTriggerRefill(*form_structure))
- TriggerRefill(form);
-}
+ gfx::RectF transformed_box =
+ driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
-void AutofillManager::PropagateAutofillPredictions(
- content::RenderFrameHost* rfh,
- const std::vector<FormStructure*>& forms) {
- client()->PropagateAutofillPredictions(rfh, forms);
+ OnQueryFormFieldAutofillImpl(query_id, form, field, transformed_box,
+ autoselect_first_suggestion);
}
-void AutofillManager::OnCreditCardFetched(bool did_succeed,
- const CreditCard* credit_card,
- const std::u16string& cvc) {
- if (!did_succeed) {
- driver()->RendererShouldClearPreviewedForm();
- return;
- }
-
- last_unlocked_credit_card_cvc_ = cvc;
-
- FormStructure* form_structure = nullptr;
- AutofillField* autofill_field = nullptr;
- if (!GetCachedFormAndField(credit_card_form_, credit_card_field_,
- &form_structure, &autofill_field))
+void AutofillManager::OnFocusOnFormField(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) {
+ if (!IsValidFormData(form) || !IsValidFormFieldData(field))
return;
- // The originally selected masked card is |credit_card_|. So we must log
- // |credit_card_| as opposed to |credit_card| to correctly indicate that the
- // user filled the form using a masked card suggestion.
- credit_card_form_event_logger_->OnDidFillSuggestion(
- credit_card_, *form_structure, *autofill_field, sync_state_);
-
- DCHECK(credit_card);
- FillCreditCardForm(credit_card_query_id_, credit_card_form_,
- credit_card_field_, *credit_card, cvc);
- if (credit_card->record_type() == CreditCard::FULL_SERVER_CARD) {
- credit_card_access_manager_->CacheUnmaskedCardInfo(*credit_card, cvc);
- }
-}
-
-void AutofillManager::OnDidEndTextFieldEditing() {
- external_delegate_->DidEndTextFieldEditing();
-}
+ gfx::RectF transformed_box =
+ driver_->TransformBoundingBoxToViewportCoordinates(bounding_box);
-bool AutofillManager::IsAutofillEnabled() const {
- return IsAutofillProfileEnabled() || IsAutofillCreditCardEnabled();
+ OnFocusOnFormFieldImpl(form, field, transformed_box);
}
-bool AutofillManager::IsAutofillProfileEnabled() const {
- return ::autofill::prefs::IsAutofillProfileEnabled(client()->GetPrefs());
-}
-
-bool AutofillManager::IsAutofillCreditCardEnabled() const {
- return ::autofill::prefs::IsAutofillCreditCardEnabled(client()->GetPrefs());
-}
-
-const FormData& AutofillManager::last_query_form() const {
- return external_delegate_->query_form();
-}
-
-bool AutofillManager::ShouldUploadForm(const FormStructure& form) {
- return IsAutofillEnabled() && !driver()->IsIncognito() &&
- form.ShouldBeUploaded();
-}
-
-// AutocompleteHistoryManager::SuggestionsHandler implementation
-void AutofillManager::OnSuggestionsReturned(
+void AutofillManager::SendFormDataToRenderer(
int query_id,
- bool autoselect_first_suggestion,
- const std::vector<Suggestion>& suggestions) {
- external_delegate_->OnSuggestionsReturned(query_id, suggestions,
- autoselect_first_suggestion);
-}
-
-// Note that |submitted_form| is passed as a pointer rather than as a reference
-// so that we can get memory management right across threads. Note also that we
-// explicitly pass in all the time stamps of interest, as the cached ones might
-// get reset before this method executes.
-void AutofillManager::UploadFormDataAsyncCallback(
- const FormStructure* submitted_form,
- const TimeTicks& interaction_time,
- const TimeTicks& submission_time,
- bool observed_submission) {
- if (submitted_form->ShouldRunHeuristics() ||
- submitted_form->ShouldBeQueried()) {
- submitted_form->LogQualityMetrics(
- submitted_form->form_parsed_timestamp(), interaction_time,
- submission_time, form_interactions_ukm_logger(), did_show_suggestions_,
- observed_submission);
- }
- if (submitted_form->ShouldBeUploaded())
- UploadFormData(*submitted_form, observed_submission);
+ AutofillDriver::RendererFormDataAction action,
+ const FormData& data) {
+ driver_->SendFormDataToRenderer(query_id, action, data);
}
-void AutofillManager::UploadFormData(const FormStructure& submitted_form,
- bool observed_submission) {
- if (!download_manager())
- return;
+// Returns true if |live_form| does not match |cached_form|.
+bool AutofillManager::GetCachedFormAndField(const FormData& form,
+ const FormFieldData& field,
+ FormStructure** form_structure,
+ AutofillField** autofill_field) {
+ // Maybe find an existing FormStructure that corresponds to |form|.
+ FormStructure* cached_form = FindCachedFormByRendererId(form.global_id());
+ if (cached_form) {
+ DCHECK(cached_form);
+ if (!CachedFormNeedsUpdate(form, *cached_form)) {
+ // There is no data to return if there are no auto-fillable fields.
+ if (!cached_form->autofill_count())
+ return false;
- // Check if the form is among the forms that were recently auto-filled.
- bool was_autofilled = false;
- std::string form_signature = submitted_form.FormSignatureAsStr();
- for (const std::string& cur_sig : autofilled_form_signatures_) {
- if (cur_sig == form_signature) {
- was_autofilled = true;
- break;
+ // Return the cached form and matching field, if any.
+ *form_structure = cached_form;
+ *autofill_field = FindAutofillFillField(**form_structure, field);
+ return *autofill_field != nullptr;
}
}
- 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,
- /*login_form_signature=*/std::string(), observed_submission,
- client()->GetPrefs());
-}
-
-void AutofillManager::Reset() {
- // Note that upload_request_ is not reset here because the prompt to
- // save a card is shown after page navigation.
- ProcessPendingFormForUpload();
- DCHECK(!pending_form_data_);
- AutofillHandler::Reset();
- address_form_event_logger_ = std::make_unique<AddressFormEventLogger>(
- driver()->IsInMainFrame(), form_interactions_ukm_logger(), client());
- credit_card_form_event_logger_ = std::make_unique<CreditCardFormEventLogger>(
- driver()->IsInMainFrame(), form_interactions_ukm_logger(), personal_data_,
- client());
- credit_card_access_manager_ = std::make_unique<CreditCardAccessManager>(
- driver(), client(), personal_data_, credit_card_form_event_logger_.get());
-
- has_logged_autofill_enabled_ = false;
- has_logged_address_suggestions_count_ = false;
- did_show_suggestions_ = false;
- user_did_type_ = false;
- user_did_autofill_ = false;
- user_did_edit_autofilled_field_ = false;
- enable_ablation_logging_ = false;
- credit_card_ = CreditCard();
- 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();
- filling_context_by_global_id_.clear();
- filling_context_by_unique_name_.clear();
-}
-
-bool AutofillManager::RefreshDataModels() {
- if (!IsAutofillEnabled())
+ // The form is new or updated, parse it and discard |cached_form|.
+ // i.e., |cached_form| is no longer valid after this call.
+ *form_structure = ParseForm(form, cached_form);
+ if (!*form_structure)
return false;
- // No autofill data to return if the profiles are empty.
- const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
- credit_card_access_manager_->UpdateCreditCardFormEventLogger();
-
- // Updating the FormEventLogger for addresses.
- {
- size_t server_record_type_count = 0;
- size_t local_record_type_count = 0;
- for (AutofillProfile* profile : profiles) {
- if (profile->record_type() == AutofillProfile::LOCAL_PROFILE)
- local_record_type_count++;
- else if (profile->record_type() == AutofillProfile::SERVER_PROFILE)
- server_record_type_count++;
- }
- address_form_event_logger_->set_server_record_type_count(
- server_record_type_count);
- address_form_event_logger_->set_local_record_type_count(
- local_record_type_count);
- }
-
- return !profiles.empty() ||
- !credit_card_access_manager_->GetCreditCards().empty();
-}
-
-CreditCard* AutofillManager::GetCreditCard(int unique_id) {
- // Unpack the |unique_id| into component parts.
- std::string credit_card_id;
- std::string profile_id;
- SplitFrontendID(unique_id, &credit_card_id, &profile_id);
- return credit_card_access_manager_->GetCreditCard(credit_card_id);
-}
-
-AutofillProfile* AutofillManager::GetProfile(int unique_id) {
- // Unpack the |unique_id| into component parts.
- std::string credit_card_id;
- std::string profile_id;
- SplitFrontendID(unique_id, &credit_card_id, &profile_id);
-
- if (base::IsValidGUID(profile_id))
- return personal_data_->GetProfileByGUID(profile_id);
- return nullptr;
-}
-
-void AutofillManager::FillOrPreviewDataModelForm(
- AutofillDriver::RendererFormDataAction action,
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- absl::variant<const AutofillProfile*, const CreditCard*>
- profile_or_credit_card,
- const std::u16string* optional_cvc,
- FormStructure* form_structure,
- AutofillField* autofill_field,
- bool is_refill) {
- bool is_credit_card =
- absl::holds_alternative<const CreditCard*>(profile_or_credit_card);
-
- DCHECK(is_credit_card || !optional_cvc);
- DCHECK(form_structure);
- DCHECK(autofill_field);
-
- LogBuffer buffer;
- buffer << "is credit card section: " << is_credit_card << Br{};
- buffer << "is refill: " << is_refill << Br{};
- buffer << *form_structure << Br{};
- buffer << Tag{"table"};
-
- form_structure->RationalizePhoneNumbersInSection(autofill_field->section);
-
- FormData result = form;
-
- // TODO(crbug/1203667#c9): Skip if the form has changed in the meantime, which
- // may happen with refills.
- if (form_structure->field_count() != form.fields.size())
- return;
-
- if (action == AutofillDriver::FORM_DATA_ACTION_FILL && !is_refill) {
- SetFillingContext(
- *form_structure,
- std::make_unique<FillingContext>(*autofill_field,
- profile_or_credit_card, optional_cvc));
- }
-
- // Only record the types that are filled for an eventual refill if all the
- // following are satisfied:
- // The refilling feature is enabled.
- // A form with the given name is already filled.
- // A refill has not been attempted for that form yet.
- // This fill is not a refill attempt.
- FillingContext* filling_context = GetFillingContext(*form_structure);
- bool could_attempt_refill = filling_context != nullptr &&
- !filling_context->attempted_refill && !is_refill;
-
- // Count the number of times the value of a specific type was filled into the
- // form.
- base::flat_map<ServerFieldType, size_t> type_filling_count;
- type_filling_count.reserve(form_structure->field_count());
-
- for (size_t i = 0; i < form_structure->field_count(); ++i) {
- std::string field_number = base::StringPrintf("Field %zu", i);
-
- // On the renderer, the section is used regardless of the autofill status.
- result.fields[i].section = form_structure->field(i)->section;
-
- if (form_structure->field(i)->section != autofill_field->section) {
- buffer << Tr{} << field_number << "Skipped: not part of filled section";
- continue;
- }
-
- if (form_structure->field(i)->only_fill_when_focused() &&
- !form_structure->field(i)->SameFieldAs(field)) {
- buffer << Tr{} << field_number << "Skipped: only fill when focused";
- continue;
- }
-
- // TODO(crbug/1203667#c9): Skip if the form has changed in the meantime,
- // which may happen with refills.
- if (!form_structure->field(i)->SameFieldAs(result.fields[i]))
- continue;
-
- AutofillField* cached_field = form_structure->field(i);
- FieldTypeGroup field_group_type = cached_field->Type().group();
-
- // Don't fill hidden fields, with the exception of <select> fields, for
- // the sake of filling the synthetic fields.
- if (!cached_field->IsVisible()) {
- bool skip = result.fields[i].form_control_type != "select-one";
- form_interactions_ukm_logger()
- ->LogHiddenRepresentationalFieldSkipDecision(*form_structure,
- *cached_field, skip);
- if (skip) {
- buffer << Tr{} << field_number << "Skipped: invisible field";
- continue;
- }
- }
-
- // Do not fill fields that have been edited by the user, except if the field
- // is empty and its initial value (= cached value) was empty as well. A
- // similar check is done in ForEachMatchingFormFieldCommon(), which
- // frequently has false negatives.
- if ((form.fields[i].properties_mask & kUserTyped) &&
- (!form.fields[i].value.empty() ||
- !form_structure->field(i)->value.empty()) &&
- !cached_field->SameFieldAs(field)) {
- buffer << Tr{} << field_number
- << "Skipped: don't fill user-filled fields";
- continue;
- }
-
- // Don't fill previously autofilled fields except the initiating field or
- // when it's a refill.
- if (result.fields[i].is_autofilled && !cached_field->SameFieldAs(field) &&
- !is_refill) {
- buffer << Tr{} << field_number
- << "Skipped: don't fill previously filled fields unless during a "
- "refill";
- continue;
- }
-
- if (field_group_type == FieldTypeGroup::kNoGroup) {
- buffer << Tr{} << field_number
- << "Skipped: field type has no fillable group";
- continue;
- }
-
- // On a refill, only fill fields from type groups that were present during
- // the initial fill.
- if (is_refill &&
- !base::Contains(filling_context->type_groups_originally_filled,
- field_group_type)) {
- buffer << Tr{} << field_number
- << "Skipped: in a refill, only fields from the group that was "
- "filled in the initial fill may be filled";
- continue;
- }
-
- ServerFieldType field_type = cached_field->Type().GetStorableType();
-
- // Don't fill expired cards expiration date.
- if (data_util::IsCreditCardExpirationType(field_type) &&
- (is_credit_card && absl::get<const CreditCard*>(profile_or_credit_card)
- ->IsExpired(AutofillClock::Now()))) {
- buffer << Tr{} << field_number
- << "Skipped: don't fill expiration date of expired cards";
- continue;
- }
-
- // A field with a specific type is only allowed to be filled a limited
- // number of times given by |TypeValueFormFillingLimit(field_type)|.
- if (++type_filling_count[field_type] >
- TypeValueFormFillingLimit(field_type)) {
- buffer << Tr{} << field_number
- << "Skipped: field-type filling-limit reached";
- continue;
- }
-
- if (could_attempt_refill)
- filling_context->type_groups_originally_filled.insert(field_group_type);
-
- // Must match ForEachMatchingFormField() in form_autofill_util.cc.
- // Only notify autofilling of empty fields and the field that initiated
- // the filling (note that "select-one" controls may not be empty but will
- // still be autofilled).
- bool should_notify = !is_credit_card &&
- (result.fields[i].SameFieldAs(field) ||
- result.fields[i].form_control_type == "select-one" ||
- result.fields[i].value.empty());
-
- bool has_value_before = !result.fields[i].value.empty();
- bool is_autofilled_before = result.fields[i].is_autofilled;
-
- const std::u16string kEmptyCvc{};
- std::string failure_to_fill; // Reason for failing to fill.
-
- // Fill the non-empty value from |profile_or_credit_card| into the result
- // vector, which will be sent to the renderer.
- FillFieldWithValue(cached_field, profile_or_credit_card, &result.fields[i],
- should_notify, optional_cvc ? *optional_cvc : kEmptyCvc,
- data_util::DetermineGroups(*form_structure),
- &failure_to_fill);
-
- bool has_value_after = !result.fields[i].value.empty();
- bool is_autofilled_after = result.fields[i].is_autofilled;
-
- buffer << Tr{} << field_number
- << base::StringPrintf(
- "Fillable - has value: %d->%d; autofilled: %d->%d. %s",
- has_value_before, is_autofilled_before, has_value_after,
- is_autofilled_after, failure_to_fill.c_str());
-
- if (!cached_field->IsVisible() && result.fields[i].is_autofilled)
- AutofillMetrics::LogHiddenOrPresentationalSelectFieldsFilled();
- }
- buffer << CTag{"table"};
-
- autofilled_form_signatures_.push_front(form_structure->FormSignatureAsStr());
- // Only remember the last few forms that we've seen, both to avoid false
- // positives and to avoid wasting memory.
- if (autofilled_form_signatures_.size() > kMaxRecentFormSignaturesToRemember)
- autofilled_form_signatures_.pop_back();
-
- // Note that this may invalidate |profile_or_credit_card|.
- if (action == AutofillDriver::FORM_DATA_ACTION_FILL && !is_refill)
- personal_data_->RecordUseOf(profile_or_credit_card);
-
- if (log_manager()) {
- log_manager()->Log() << LoggingScope::kFilling
- << LogMessage::kSendFillingData << Br{}
- << std::move(buffer);
- }
- driver()->SendFormDataToRenderer(query_id, action, result);
-}
-
-std::unique_ptr<FormStructure> AutofillManager::ValidateSubmittedForm(
- const FormData& form) {
- // Ignore forms not present in our cache. These are typically forms with
- // wonky JavaScript that also makes them not auto-fillable.
- FormStructure* cached_submitted_form =
- FindCachedFormByRendererId(form.global_id());
- if (!cached_submitted_form || !ShouldUploadForm(*cached_submitted_form)) {
- return nullptr;
- }
-
- auto submitted_form = std::make_unique<FormStructure>(form);
- submitted_form->RetrieveFromCache(*cached_submitted_form,
- /*should_keep_cached_value=*/false,
- /*only_server_and_autofill_state=*/false);
- if (value_from_dynamic_change_form_) {
- submitted_form->set_value_from_dynamic_change_form(true);
- }
+ // Annotate the updated form with its predicted types.
+ driver()->SendAutofillTypePredictionsToRenderer({*form_structure});
+ // Update the renderer with the latest set of fields eligible for manual
+ // filling.
+ driver()->SendFieldsEligibleForManualFillingToRenderer(
+ FormStructure::FindFieldsEligibleForManualFilling({*form_structure}));
+ // There is no data to return if there are no auto-fillable fields.
+ if (!(*form_structure)->autofill_count())
+ return false;
- return submitted_form;
+ // Find the AutofillField that corresponds to |field|.
+ *autofill_field = FindAutofillFillField(**form_structure, field);
+ return *autofill_field != nullptr;
}
-AutofillField* AutofillManager::GetAutofillField(const FormData& form,
- const FormFieldData& field) {
- if (!personal_data_)
- return nullptr;
-
- FormStructure* form_structure = nullptr;
- AutofillField* autofill_field = nullptr;
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+std::unique_ptr<AutofillMetrics::FormInteractionsUkmLogger>
+AutofillManager::CreateFormInteractionsUkmLogger() {
+ if (!client())
return nullptr;
- if (!form_structure->IsAutofillable())
- return nullptr;
-
- return autofill_field;
+ return std::make_unique<AutofillMetrics::FormInteractionsUkmLogger>(
+ client()->GetUkmRecorder(), client()->GetUkmSourceId());
}
-bool AutofillManager::FormHasAddressField(const FormData& form) {
- for (const FormFieldData& field : form.fields) {
- const AutofillField* autofill_field = GetAutofillField(form, field);
- if (autofill_field &&
- (autofill_field->Type().group() == FieldTypeGroup::kAddressHome ||
- autofill_field->Type().group() == FieldTypeGroup::kAddressBilling)) {
- return true;
+size_t AutofillManager::FindCachedFormsBySignature(
+ FormSignature form_signature,
+ std::vector<FormStructure*>* form_structures) const {
+ size_t hits_num = 0;
+ for (const auto& p : form_structures_) {
+ if (p.second->form_signature() == form_signature) {
+ ++hits_num;
+ if (form_structures)
+ form_structures->push_back(p.second.get());
}
}
-
- return false;
-}
-
-std::vector<Suggestion> AutofillManager::GetProfileSuggestions(
- const FormStructure& form,
- const FormFieldData& field,
- const AutofillField& autofill_field) const {
- address_form_event_logger_->OnDidPollSuggestions(field, sync_state_);
-
- std::vector<ServerFieldType> field_types(form.field_count());
- for (size_t i = 0; i < form.field_count(); ++i) {
- field_types.push_back(form.field(i)->Type().GetStorableType());
- }
-
- std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
- autofill_field.Type(), field.value, field.is_autofilled, field_types);
-
- // Adjust phone number to display in prefix/suffix case.
- if (autofill_field.Type().group() == FieldTypeGroup::kPhoneHome) {
- for (auto& suggestion : suggestions) {
- const AutofillProfile* profile =
- personal_data_->GetProfileByGUID(suggestion.backend_id);
- if (profile) {
- const std::u16string phone_home_city_and_number =
- profile->GetInfo(PHONE_HOME_CITY_AND_NUMBER, app_locale_);
- suggestion.value =
- FieldFiller::GetPhoneNumberValue(autofill_field, suggestion.value,
- phone_home_city_and_number, field);
- }
- }
- }
-
- for (size_t i = 0; i < suggestions.size(); ++i) {
- suggestions[i].frontend_id =
- MakeFrontendID(std::string(), suggestions[i].backend_id);
- }
- return suggestions;
-}
-
-std::vector<Suggestion> AutofillManager::GetCreditCardSuggestions(
- const FormFieldData& field,
- const AutofillType& type,
- bool* should_display_gpay_logo) const {
- credit_card_form_event_logger_->OnDidPollSuggestions(field, sync_state_);
-
- // The field value is sanitized before attempting to match it to the user's
- // data.
- std::vector<Suggestion> suggestions =
- personal_data_->GetCreditCardSuggestions(
- type, SanitizeCreditCardFieldValue(field.value),
- client()->AreServerCardsSupported());
- if (base::FeatureList::IsEnabled(
- features::kAutofillEnableOffersInDownstream) &&
- offer_manager_) {
- offer_manager_->UpdateSuggestionsWithOffers(client()->GetLastCommittedURL(),
- suggestions);
- }
- *should_display_gpay_logo =
- credit_card_access_manager_->ShouldDisplayGPayLogo();
-
- for (size_t i = 0; i < suggestions.size(); i++) {
- suggestions[i].frontend_id =
- MakeFrontendID(suggestions[i].backend_id, std::string());
- }
-
- credit_card_form_event_logger_->set_suggestions(suggestions);
- return suggestions;
+ return hits_num;
}
-void AutofillManager::OnBeforeProcessParsedForms() {
- has_parsed_forms_ = true;
-
- // Record the current sync state to be used for metrics on this page.
- sync_state_ = personal_data_->GetSyncSigninState();
-
- // Setup the url for metrics that we will collect for this form.
- form_interactions_ukm_logger()->OnFormsParsed(client()->GetUkmSourceId());
+FormStructure* AutofillManager::FindCachedFormByRendererId(
+ FormGlobalId form_id) const {
+ auto it = form_structures_.find(form_id);
+ return it != form_structures_.end() ? it->second.get() : nullptr;
}
-void AutofillManager::OnFormProcessed(const FormData& form,
- const FormStructure& form_structure) {
- if (data_util::ContainsPhone(data_util::DetermineGroups(form_structure))) {
- has_observed_phone_number_field_ = true;
- }
-
- // TODO(crbug.com/869482): avoid logging developer engagement multiple
- // times for a given form if it or other forms on the page are dynamic.
- LogDeveloperEngagementUkm(client()->GetUkmRecorder(),
- client()->GetUkmSourceId(), form_structure);
-
- // Log the type of form that was parsed.
- bool card_form = false;
- bool address_form = false;
- for (const auto& field : form_structure) {
- if (field->Type().group() == FieldTypeGroup::kCreditCard) {
- card_form = true;
- } else if (IsAddressForm(field->Type().group())) {
- address_form = true;
- } else if (field->Type().html_type() == HTML_TYPE_ONE_TIME_CODE) {
- has_observed_one_time_code_field_ = true;
+FormStructure* AutofillManager::ParseForm(const FormData& form,
+ const FormStructure* cached_form) {
+ if (form_structures_.size() >= kAutofillManagerMaxFormCacheSize) {
+ if (log_manager_) {
+ log_manager_->Log() << LoggingScope::kAbortParsing
+ << LogMessage::kAbortParsingTooManyForms << form;
}
+ return nullptr;
}
- if (card_form) {
- credit_card_form_event_logger_->OnDidParseForm(form_structure);
- }
- if (address_form) {
- address_form_event_logger_->OnDidParseForm(form_structure);
- }
-
- // If a form with the same name was previously filled, and there has not
- // been a refill attempt on that form yet, start the process of triggering a
- // refill.
- if (ShouldTriggerRefill(form_structure)) {
- FillingContext* filling_context = GetFillingContext(form_structure);
- DCHECK(filling_context != nullptr);
-
- // If a timer for the refill was already running, it means the form
- // changed again. Stop the timer and start it again.
- if (filling_context->on_refill_timer.IsRunning())
- filling_context->on_refill_timer.AbandonAndStop();
-
- // Start a new timer to trigger refill.
- filling_context->on_refill_timer.Start(
- FROM_HERE,
- base::TimeDelta::FromMilliseconds(kWaitTimeForDynamicFormsMs),
- base::BindRepeating(&AutofillManager::TriggerRefill,
- weak_ptr_factory_.GetWeakPtr(), form));
- }
-}
-
-void AutofillManager::OnAfterProcessParsedForms(
- const DenseSet<FormType>& form_types) {
- AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::FORMS_LOADED, form_types,
- client()->GetSecurityLevelForUmaHistograms(),
- /*profile_form_bitmask=*/0);
-#if defined(OS_IOS)
- // Log this from same location as AutofillMetrics::FORMS_LOADED to ensure
- // that KeyboardAccessoryButtonsIOS and UserHappiness UMA metrics will be
- // directly comparable.
- KeyboardAccessoryMetricsLogger::OnFormsLoaded();
-#endif
-}
-
-int AutofillManager::BackendIDToInt(const std::string& backend_id) const {
- if (!base::IsValidGUID(backend_id))
- return 0;
-
- const auto found = backend_to_int_map_.find(backend_id);
- if (found == backend_to_int_map_.end()) {
- // Unknown one, make a new entry.
- int int_id = backend_to_int_map_.size() + 1;
- backend_to_int_map_[backend_id] = int_id;
- int_to_backend_map_[int_id] = backend_id;
- return int_id;
- }
- return found->second;
-}
-
-std::string AutofillManager::IntToBackendID(int int_id) const {
- if (int_id == 0)
- return std::string();
-
- const auto found = int_to_backend_map_.find(int_id);
- if (found == int_to_backend_map_.end()) {
- NOTREACHED();
- return std::string();
- }
- return found->second;
-}
-
-// When sending IDs (across processes) to the renderer we pack credit card and
-// profile IDs into a single integer. Credit card IDs are sent in the high
-// word and profile IDs are sent in the low word.
-int AutofillManager::MakeFrontendID(
- const std::string& cc_backend_id,
- const std::string& profile_backend_id) const {
- int cc_int_id = BackendIDToInt(cc_backend_id);
- int profile_int_id = BackendIDToInt(profile_backend_id);
-
- // Should fit in signed 16-bit integers. We use 16-bits each when combining
- // below, and negative frontend IDs have special meaning so we can never use
- // the high bit.
- DCHECK(cc_int_id <= std::numeric_limits<int16_t>::max());
- DCHECK(profile_int_id <= std::numeric_limits<int16_t>::max());
-
- // Put CC in the high half of the bits.
- return (cc_int_id << std::numeric_limits<uint16_t>::digits) | profile_int_id;
-}
-
-// When receiving IDs (across processes) from the renderer we unpack credit card
-// and profile IDs from a single integer. Credit card IDs are stored in the
-// high word and profile IDs are stored in the low word.
-void AutofillManager::SplitFrontendID(int frontend_id,
- std::string* cc_backend_id,
- std::string* profile_backend_id) const {
- int cc_int_id = (frontend_id >> std::numeric_limits<uint16_t>::digits) &
- std::numeric_limits<uint16_t>::max();
- int profile_int_id = frontend_id & std::numeric_limits<uint16_t>::max();
-
- *cc_backend_id = IntToBackendID(cc_int_id);
- *profile_backend_id = IntToBackendID(profile_int_id);
-}
-
-void AutofillManager::UpdateInitialInteractionTimestamp(
- const TimeTicks& interaction_timestamp) {
- if (initial_interaction_timestamp_.is_null() ||
- interaction_timestamp < initial_interaction_timestamp_) {
- initial_interaction_timestamp_ = interaction_timestamp;
- }
-}
-
-// static
-void AutofillManager::DeterminePossibleFieldTypesForUpload(
- const std::vector<AutofillProfile>& profiles,
- const std::vector<CreditCard>& credit_cards,
- const std::u16string& 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.
- DCHECK_EQ(1u, field->possible_types().size());
- DCHECK_EQ(PASSWORD, *field->possible_types().begin());
- continue;
- }
-
- ServerFieldTypeSet matching_types;
- std::u16string value;
- base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
-
- for (const AutofillProfile& profile : profiles) {
- ServerFieldTypeValidityStateMap matching_types_validities;
- profile.GetMatchingTypesAndValidities(value, app_locale, &matching_types,
- &matching_types_validities);
- field->add_possible_types_validities(matching_types_validities);
- }
-
- // TODO(crbug/880531) set possible_types_validities for credit card too.
- for (const CreditCard& card : credit_cards) {
- card.GetMatchingTypes(value, app_locale, &matching_types);
- }
-
- if (IsUPIVirtualPaymentAddress(value))
- matching_types.insert(UPI_VPA);
-
- if (field->state_is_a_matching_type())
- matching_types.insert(ADDRESS_HOME_STATE);
-
- if (matching_types.empty()) {
- matching_types.insert(UNKNOWN_TYPE);
- ServerFieldTypeValidityStateMap matching_types_validities;
- matching_types_validities[UNKNOWN_TYPE] = AutofillDataModel::UNVALIDATED;
- field->add_possible_types_validities(matching_types_validities);
- }
-
- field->set_possible_types(matching_types);
- }
-
- // As CVCs are not stored, run special heuristics to detect CVC-like values.
- AutofillField* cvc_field = GetBestPossibleCVCFieldForUpload(
- *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);
-}
-
-// static
-void AutofillManager::DisambiguateUploadTypes(FormStructure* form) {
- for (size_t i = 0; i < form->field_count(); ++i) {
- AutofillField* field = form->field(i);
- const ServerFieldTypeSet& upload_types = field->possible_types();
-
- if (upload_types.size() == 2) {
- if (upload_types.count(ADDRESS_HOME_LINE1) &&
- upload_types.count(ADDRESS_HOME_STREET_ADDRESS)) {
- AutofillManager::DisambiguateAddressUploadTypes(form, i);
- } else if (upload_types.count(PHONE_HOME_CITY_AND_NUMBER) &&
- upload_types.count(PHONE_HOME_WHOLE_NUMBER)) {
- AutofillManager::DisambiguatePhoneUploadTypes(form, i);
- }
- }
-
- // In case for credit cards and names there are many other possibilities
- // because a field can be of type NAME_FULL, NAME_LAST,
- // NAME_LAST_FIRST/SECOND at the same time.
- int credit_card_type_count = 0;
- int name_type_count = 0;
-
- bool undisambiuatable_types = false;
- for (const auto& type : upload_types) {
- switch (AutofillType(type).group()) {
- case FieldTypeGroup::kCreditCard:
- ++credit_card_type_count;
- break;
- case FieldTypeGroup::kName:
- ++name_type_count;
- break;
- // If there is any other type left, do not disambiguate.
- default:
- undisambiuatable_types = true;
- }
- if (undisambiuatable_types)
- break;
- }
- if (undisambiuatable_types)
- continue;
-
- if (credit_card_type_count == 1 && name_type_count >= 1)
- AutofillManager::DisambiguateNameUploadTypes(form, i, upload_types);
- }
-}
-
-// static
-void AutofillManager::DisambiguateAddressUploadTypes(FormStructure* form,
- size_t current_index) {
- // This happens when we have exactly two possible types, and the profile
- // has only one address line. Therefore the address line one and the street
- // address (the whole address) have the same value and match.
-
- // If the field is followed by a field that is predicted to be an
- // address line two and is empty, we can safely assume that this field
- // is an address line one field. Otherwise it's a whole address field.
-
- ServerFieldTypeSet matching_types;
- ServerFieldTypeValidityStatesMap matching_types_validities;
- AutofillField* field = form->field(current_index);
-
- size_t next_index = current_index + 1;
- if (next_index < form->field_count() &&
- form->field(next_index)->Type().GetStorableType() == ADDRESS_HOME_LINE2 &&
- form->field(next_index)->possible_types().count(EMPTY_TYPE)) {
- matching_types.insert(ADDRESS_HOME_LINE1);
- matching_types_validities[ADDRESS_HOME_LINE1] =
- field->get_validities_for_possible_type(ADDRESS_HOME_LINE1);
- } else {
- matching_types.insert(ADDRESS_HOME_STREET_ADDRESS);
- matching_types_validities[ADDRESS_HOME_STREET_ADDRESS] =
- field->get_validities_for_possible_type(ADDRESS_HOME_STREET_ADDRESS);
- }
-
- field->set_possible_types(matching_types);
- field->set_possible_types_validities(matching_types_validities);
-}
-
-// static
-void AutofillManager::DisambiguatePhoneUploadTypes(FormStructure* form,
- size_t current_index) {
- // This case happens when we have exactly two possible types, and only for
- // profiles that have no country code saved. Therefore, both the whole number
- // and the city code and number have the same value and match.
-
- // Since the form was submitted, it is safe to assume that the form
- // didn't require a country code. Thus, only PHONE_HOME_CITY_AND_NUMBER
- // needs to be uploaded.
-
- ServerFieldTypeSet matching_types;
- ServerFieldTypeValidityStatesMap matching_types_validities;
- AutofillField* field = form->field(current_index);
-
- matching_types.insert(PHONE_HOME_CITY_AND_NUMBER);
- matching_types_validities[PHONE_HOME_CITY_AND_NUMBER] =
- field->get_validities_for_possible_type(PHONE_HOME_CITY_AND_NUMBER);
-
- field->set_possible_types(matching_types);
- field->set_possible_types_validities(matching_types_validities);
-}
-
-// static
-void AutofillManager::DisambiguateNameUploadTypes(
- FormStructure* form,
- size_t current_index,
- const ServerFieldTypeSet& upload_types) {
- // This case happens when both a profile and a credit card have the same
- // name, and when we have exactly two possible types.
-
- // If the ambiguous field has either a previous or next field that is
- // not name related, use that information to determine whether the field
- // is a name or a credit card name.
- // If the ambiguous field has both a previous or next field that is not
- // name related, if they are both from the same group, use that group to
- // decide this field's type. Otherwise, there is no safe way to
- // disambiguate.
-
- // Look for a previous non name related field.
- bool has_found_previous_type = false;
- bool is_previous_credit_card = false;
- size_t index = current_index;
- while (index != 0 && !has_found_previous_type) {
- --index;
- AutofillField* prev_field = form->field(index);
- if (!IsNameType(*prev_field)) {
- has_found_previous_type = true;
- is_previous_credit_card =
- prev_field->Type().group() == FieldTypeGroup::kCreditCard;
- }
- }
-
- // Look for a next non name related field.
- bool has_found_next_type = false;
- bool is_next_credit_card = false;
- index = current_index;
- while (++index < form->field_count() && !has_found_next_type) {
- AutofillField* next_field = form->field(index);
- if (!IsNameType(*next_field)) {
- has_found_next_type = true;
- is_next_credit_card =
- next_field->Type().group() == FieldTypeGroup::kCreditCard;
- }
- }
-
- // At least a previous or next field type must have been found in order to
- // disambiguate this field.
- if (has_found_previous_type || has_found_next_type) {
- // If both a previous type and a next type are found and not from the same
- // name group there is no sure way to disambiguate.
- if (has_found_previous_type && has_found_next_type &&
- (is_previous_credit_card != is_next_credit_card)) {
- return;
- }
-
- // Otherwise, use the previous (if it was found) or next field group to
- // decide whether the field is a name or a credit card name.
- if (has_found_previous_type) {
- SelectRightNameType(form->field(current_index), is_previous_credit_card);
- } else {
- SelectRightNameType(form->field(current_index), is_next_credit_card);
- }
- }
-}
-
-void AutofillManager::FillFieldWithValue(
- AutofillField* autofill_field,
- absl::variant<const AutofillProfile*, const CreditCard*>
- profile_or_credit_card,
- FormFieldData* field_data,
- bool should_notify,
- const std::u16string& cvc,
- uint32_t profile_form_bitmask,
- std::string* failure_to_fill) {
- if (field_filler_.FillFormField(*autofill_field, profile_or_credit_card,
- field_data, cvc, failure_to_fill)) {
- if (failure_to_fill)
- *failure_to_fill = "Decided to fill";
- // Mark the cached field as autofilled, so that we can detect when a
- // user edits an autofilled field (for metrics).
- autofill_field->is_autofilled = true;
-
- // Mark the field as autofilled when a non-empty value is assigned to
- // it. This allows the renderer to distinguish autofilled fields from
- // fields with non-empty values, such as select-one fields.
- field_data->is_autofilled = true;
- AutofillMetrics::LogUserHappinessMetric(
- AutofillMetrics::FIELD_WAS_AUTOFILLED, autofill_field->Type().group(),
- client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
-
- if (should_notify) {
- DCHECK(absl::holds_alternative<const AutofillProfile*>(
- profile_or_credit_card));
- const AutofillProfile* profile =
- absl::get<const AutofillProfile*>(profile_or_credit_card);
- client()->DidFillOrPreviewField(
- /*value=*/profile->GetInfo(autofill_field->Type(), app_locale_),
- /*profile_full_name=*/profile->GetInfo(AutofillType(NAME_FULL),
- app_locale_));
- }
- }
-}
-
-// TODO(crbug/896689): Remove code duplication once experiment is finished.
-void AutofillManager::SetFillingContext(
- const FormStructure& form,
- std::unique_ptr<FillingContext> context) {
- if (base::FeatureList::IsEnabled(features::kAutofillRefillWithRendererIds)) {
- filling_context_by_global_id_[form.global_id()] = std::move(context);
- } else {
- filling_context_by_unique_name_[form.GetIdentifierForRefill()] =
- std::move(context);
- }
-}
-
-// TODO(crbug/896689): Remove code duplication once experiment is finished.
-AutofillManager::FillingContext* AutofillManager::GetFillingContext(
- const FormStructure& form) {
- if (base::FeatureList::IsEnabled(features::kAutofillRefillWithRendererIds)) {
- auto it = filling_context_by_global_id_.find(form.global_id());
- return it != filling_context_by_global_id_.end() ? it->second.get()
- : nullptr;
- } else {
- auto it =
- filling_context_by_unique_name_.find(form.GetIdentifierForRefill());
- return it != filling_context_by_unique_name_.end() ? it->second.get()
- : nullptr;
- }
-}
-
-bool AutofillManager::ShouldTriggerRefill(const FormStructure& form_structure) {
- // Should not refill if a form with the same FormGlobalId has not been
- // filled before.
- FillingContext* filling_context = GetFillingContext(form_structure);
- if (filling_context == nullptr)
- return false;
-
- address_form_event_logger_->OnDidSeeFillableDynamicForm(sync_state_,
- form_structure);
+ auto form_structure = std::make_unique<FormStructure>(form);
+ form_structure->ParseFieldTypesFromAutocompleteAttributes();
+ if (!form_structure->ShouldBeParsed(log_manager_))
+ return nullptr;
- base::TimeTicks now = AutofillTickClock::NowTicks();
- base::TimeDelta delta = now - filling_context->original_fill_time;
+ if (cached_form) {
+ // We need to keep the server data if available. We need to use them while
+ // determining the heuristics.
+ form_structure->RetrieveFromCache(*cached_form,
+ /*should_keep_cached_value=*/true,
+ /*only_server_and_autofill_state=*/true);
+ if (observer_for_testing_)
+ observer_for_testing_->OnFormParsed();
- if (filling_context->attempted_refill &&
- delta.InMilliseconds() < kLimitBeforeRefillMs) {
- address_form_event_logger_->OnSubsequentRefillAttempt(sync_state_,
- form_structure);
+ if (form_structure.get()->value_from_dynamic_change_form())
+ value_from_dynamic_change_form_ = true;
}
- return !filling_context->attempted_refill &&
- delta.InMilliseconds() < kLimitBeforeRefillMs;
-}
-
-void AutofillManager::TriggerRefill(const FormData& form) {
- FormStructure* form_structure = FindCachedFormByRendererId(form.global_id());
- if (!form_structure)
- return;
-
- DCHECK(form_structure);
-
- address_form_event_logger_->OnDidRefill(sync_state_, *form_structure);
-
- FillingContext* filling_context = GetFillingContext(*form_structure);
-
- // Since GetIdentifierForRefill() is not stable across dynamic changes,
- // |filling_context_by_unique_name_| may not contain the element anymore.
- // TODO(crbug/896689): Can be replaced with DCHECK once experiment is over.
- if (filling_context == nullptr)
- return;
+ form_structure->set_current_page_language(GetCurrentPageLanguage());
- // The refill attempt can happen from different paths, some of which happen
- // after waiting for a while. Therefore, although this condition has been
- // checked prior to calling TriggerRefill, it may not hold, when we get
- // here.
- if (filling_context->attempted_refill)
- return;
+ form_structure->DetermineHeuristicTypes(form_interactions_ukm_logger(),
+ log_manager_);
- filling_context->attempted_refill = true;
-
- // Try to find the field from which the original field originated.
- // Precedence is given to look up by |filled_field_id|.
- // If that is unsuccessful, look up is done by |filled_field_signature|.
- // TODO(crbug/896689): Clean up after feature launch.
- AutofillField* autofill_field = nullptr;
- for (const std::unique_ptr<AutofillField>& field : *form_structure) {
- // TODO(crbug/896689): Clean up once experiment is over.
- if (((base::FeatureList::IsEnabled(
- features::kAutofillRefillWithRendererIds) &&
- field->global_id() == filling_context->filled_field_id) ||
- (!base::FeatureList::IsEnabled(
- features::kAutofillRefillWithRendererIds) &&
- field->unique_name() == filling_context->filled_field_unique_name))) {
- autofill_field = field.get();
- break;
- }
- }
+ // Hold the parsed_form_structure we intend to return. We can use this to
+ // reference the form_signature when transferring ownership below.
+ FormStructure* parsed_form_structure = form_structure.get();
- // If the field was deleted, look for one with a matching signature. Prefer
- // visible and newer fields over invisible or older ones.
- if (base::FeatureList::IsEnabled(features::kAutofillRefillWithRendererIds) &&
- autofill_field == nullptr) {
- auto is_better = [](const AutofillField& f, const AutofillField& g) {
- return std::forward_as_tuple(f.IsVisible(),
- f.unique_renderer_id.value()) >
- std::forward_as_tuple(g.IsVisible(), g.unique_renderer_id.value());
- };
-
- for (const std::unique_ptr<AutofillField>& field : *form_structure) {
- if (field->GetFieldSignature() ==
- filling_context->filled_field_signature) {
- if (autofill_field == nullptr || is_better(*field, *autofill_field)) {
- autofill_field = field.get();
- }
- }
- }
- }
-
- // If it was not found cancel the refill.
- if (!autofill_field)
- return;
+ // Ownership is transferred to |form_structures_| which maintains it until
+ // the form is parsed again or the AutofillManager is destroyed.
+ //
+ // Note that this insert/update takes ownership of the new form structure
+ // and also destroys the previously cached form structure.
+ form_structures_[parsed_form_structure->global_id()] =
+ std::move(form_structure);
- FormFieldData field = *autofill_field;
- if (absl::holds_alternative<std::pair<CreditCard, std::u16string>>(
- filling_context->profile_or_credit_card_with_cvc)) {
- FillOrPreviewDataModelForm(
- AutofillDriver::RendererFormDataAction::FORM_DATA_ACTION_FILL,
- /*query_id=*/-1, form, field,
- &absl::get<std::pair<CreditCard, std::u16string>>(
- filling_context->profile_or_credit_card_with_cvc)
- .first,
- &absl::get<std::pair<CreditCard, std::u16string>>(
- filling_context->profile_or_credit_card_with_cvc)
- .second,
- form_structure, autofill_field,
- /*is_refill=*/true);
- }
- if (absl::holds_alternative<AutofillProfile>(
- filling_context->profile_or_credit_card_with_cvc)) {
- FillOrPreviewDataModelForm(
- AutofillDriver::RendererFormDataAction::FORM_DATA_ACTION_FILL,
- /*query_id=*/-1, form, field,
- &absl::get<AutofillProfile>(
- filling_context->profile_or_credit_card_with_cvc),
- /*cvc=*/nullptr, form_structure, autofill_field, /*is_refill=*/true);
- }
+ return parsed_form_structure;
}
-void AutofillManager::GetAvailableSuggestions(
- const FormData& form,
- const FormFieldData& field,
- std::vector<Suggestion>* suggestions,
- SuggestionsContext* context) {
- DCHECK(suggestions);
- DCHECK(context);
-
- // Need to refresh models before using the form_event_loggers.
- bool is_autofill_possible = RefreshDataModels();
-
- bool got_autofillable_form =
- GetCachedFormAndField(form, field, &context->form_structure,
- &context->focused_field) &&
- // Don't send suggestions or track forms that should not be parsed.
- context->form_structure->ShouldBeParsed();
-
- // Log interactions of forms that are autofillable.
- if (got_autofillable_form) {
- if (context->focused_field->Type().group() == FieldTypeGroup::kCreditCard) {
- context->is_filling_credit_card = true;
- }
- auto* logger = GetEventFormLogger(context->focused_field->Type().group());
- if (logger) {
- logger->OnDidInteractWithAutofillableForm(*(context->form_structure),
- sync_state_);
- }
- }
-
- // If the feature is enabled and this is a mixed content form, we show a
- // warning message and don't offer autofill. The warning is shown even if
- // there are no autofill suggestions available.
- if (IsFormMixedContent(client(), form) &&
- base::FeatureList::IsEnabled(
- features::kAutofillPreventMixedFormsFilling) &&
- client()->GetPrefs()->GetBoolean(::prefs::kMixedFormsWarningsEnabled)) {
- suggestions->clear();
- // If the user begins typing, we interpret that as dismissing the warning.
- // No suggestions are allowed, but the warning is no longer shown.
- if (field.DidUserType()) {
- context->suppress_reason = SuppressReason::kInsecureForm;
- } else {
- Suggestion warning_suggestion(
- l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_MIXED_FORM));
- warning_suggestion.frontend_id = POPUP_ITEM_ID_MIXED_FORM_MESSAGE;
- suggestions->emplace_back(warning_suggestion);
- }
- return;
- }
-
- context->is_context_secure = !IsFormNonSecure(form);
-
- // TODO(rogerm): Early exit here on !driver()->RendererIsAvailable()?
- // We skip populating autofill data, but might generate warnings and or
- // signin promo to show over the unavailable renderer. That seems a mistake.
-
- if (!is_autofill_possible || !driver()->RendererIsAvailable() ||
- !got_autofillable_form)
- return;
-
- context->is_autofill_available = true;
-
- if (context->is_filling_credit_card) {
- *suggestions =
- GetCreditCardSuggestions(field, context->focused_field->Type(),
- &context->should_display_gpay_logo);
-
- // Logic for disabling/ablating credit card autofill.
- if (base::FeatureList::IsEnabled(
- features::kAutofillCreditCardAblationExperiment) &&
- !suggestions->empty()) {
- context->suppress_reason = SuppressReason::kCreditCardsAblation;
- suggestions->clear();
- return;
- }
+void AutofillManager::Reset() {
+ form_structures_.clear();
+ form_interactions_ukm_logger_ = CreateFormInteractionsUkmLogger();
+}
+
+void AutofillManager::OnLoadedServerPredictions(
+ std::string response,
+ const std::vector<FormSignature>& queried_form_signatures) {
+ // Get the current valid FormStructures represented by
+ // |queried_form_signatures|.
+ std::vector<FormStructure*> queried_forms;
+ queried_forms.reserve(queried_form_signatures.size());
+ for (const auto& form_signature : queried_form_signatures) {
+ FindCachedFormsBySignature(form_signature, &queried_forms);
+ }
+
+ // Each form signature in |queried_form_signatures| is supposed to be unique,
+ // and therefore appear only once. This ensures that
+ // FindCachedFormsBySignature() produces an output without duplicates in the
+ // forms.
+ // TODO(crbug/1064709): |queried_forms| could be a set data structure; their
+ // order should be irrelevant.
+ DCHECK_EQ(queried_forms.size(),
+ std::set<FormStructure*>(queried_forms.begin(), queried_forms.end())
+ .size());
+
+ // If there are no current forms corresponding to the queried signatures, drop
+ // the query response.
+ if (queried_forms.empty())
+ return;
+
+ // Parse and store the server predictions.
+ FormStructure::ParseApiQueryResponse(std::move(response), queried_forms,
+ queried_form_signatures,
+ form_interactions_ukm_logger());
+
+ // Will log quality metrics for each FormStructure based on the presence of
+ // autocomplete attributes, if available.
+ if (auto* logger = form_interactions_ukm_logger()) {
+ for (FormStructure* cur_form : queried_forms) {
+ cur_form->LogQualityMetricsBasedOnAutocomplete(logger);
+ }
+ }
+
+ // Send field type predictions to the renderer so that it can possibly
+ // annotate forms with the predicted types or add console warnings.
+ driver()->SendAutofillTypePredictionsToRenderer(queried_forms);
+
+ driver()->SendFieldsEligibleForManualFillingToRenderer(
+ FormStructure::FindFieldsEligibleForManualFilling(queried_forms));
+
+ LogAutofillTypePredictionsAvailable(log_manager_, queried_forms);
+
+ // TODO(crbug.com/1176816): Remove the test code after initial integration.
+ int delay = 0;
+ if (auto* cmd = base::CommandLine::ForCurrentProcess()) {
+ // This command line helps to simulate query result arriving after autofill
+ // is triggered and shall be used for manual test only.
+ std::string value = cmd->GetSwitchValueASCII(
+ "autofill-server-query-result-delay-in-seconds");
+ if (!base::StringToInt(value, &delay))
+ delay = 0;
+ }
+
+ if (delay > 0) {
+ query_result_delay_task_.Reset(
+ base::BindOnce(&AutofillManager::PropagateAutofillPredictionsToDriver,
+ base::Unretained(this)));
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(query_result_delay_task_.callback(), queried_forms),
+ base::TimeDelta::FromSeconds(delay));
} else {
- *suggestions = GetProfileSuggestions(*context->form_structure, field,
- *context->focused_field);
- }
-
- // Returns early if no suggestion is available or suggestions are not for
- // cards.
- if (suggestions->empty() || !context->is_filling_credit_card)
- return;
-
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
- // This section adds the "Use a virtual card number" option in the autofill
- // dropdown menu, if applicable.
- if (ShouldShowVirtualCardOption(context->form_structure)) {
- suggestions->emplace_back(l10n_util::GetStringUTF16(
- IDS_AUTOFILL_CLOUD_TOKEN_DROPDOWN_OPTION_LABEL));
- suggestions->back().frontend_id = POPUP_ITEM_ID_USE_VIRTUAL_CARD;
- }
-#endif
-
- // Don't provide credit card suggestions for non-secure pages, but do
- // provide them for secure pages with passive mixed content (see
- // implementation of IsContextSecure).
- if (!context->is_context_secure) {
- // Replace the suggestion content with a warning message explaining why
- // Autofill is disabled for a website. The string is different if the
- // credit card autofill HTTP warning experiment is enabled.
- Suggestion warning_suggestion(
- l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION));
- warning_suggestion.frontend_id =
- POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE;
- suggestions->assign(1, warning_suggestion);
+ PropagateAutofillPredictionsToDriver(queried_forms);
}
}
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
-// TODO(crbug.com/1020740): Add metrics logging.
-bool AutofillManager::ShouldShowVirtualCardOption(
- FormStructure* form_structure) {
- // If experiment is disabled, return false.
- if (!base::FeatureList::IsEnabled(features::kAutofillEnableVirtualCard))
- return false;
-
- // If credit card upload is disabled, return false.
- if (!IsAutofillCreditCardEnabled())
- return false;
-
- // If merchant is not allowed, return false.
- std::vector<std::string> allowed_merchants =
- client()->GetAllowedMerchantsForVirtualCards();
- if (std::find(allowed_merchants.begin(), allowed_merchants.end(),
- form_structure->source_url().spec()) ==
- allowed_merchants.end()) {
- return false;
- }
-
- // If no credit card candidate has related cloud token data available,
- // return false.
- if (GetVirtualCardCandidates(personal_data_).empty())
- return false;
-
- // If card number field or expiration date field is not detected, return
- // false.
- if (!form_structure->IsCompleteCreditCardForm())
- return false;
-
- // If CVC field is detected, then all requirements are met, otherwise return
- // false.
- for (auto& field : *form_structure) {
- if (field->Type().GetStorableType() == CREDIT_CARD_VERIFICATION_CODE)
- return true;
- }
- return false;
-}
-#endif
-
-FormEventLoggerBase* AutofillManager::GetEventFormLogger(
- FieldTypeGroup field_type_group) const {
- switch (field_type_group) {
- case FieldTypeGroup::kName:
- case FieldTypeGroup::kNameBilling:
- case FieldTypeGroup::kEmail:
- case FieldTypeGroup::kCompany:
- case FieldTypeGroup::kAddressHome:
- case FieldTypeGroup::kAddressBilling:
- case FieldTypeGroup::kPhoneHome:
- case FieldTypeGroup::kPhoneBilling:
- return address_form_event_logger_.get();
- case FieldTypeGroup::kCreditCard:
- return credit_card_form_event_logger_.get();
- case FieldTypeGroup::kTransaction:
- case FieldTypeGroup::kPasswordField:
- case FieldTypeGroup::kUsernameField:
- case FieldTypeGroup::kNoGroup:
- case FieldTypeGroup::kUnfillable:
- return nullptr;
- }
- NOTREACHED();
- return nullptr;
+void AutofillManager::PropagateAutofillPredictionsToDriver(
+ const std::vector<FormStructure*>& queried_forms) {
+ // Forward form structures to the password generation manager to detect
+ // account creation forms.
+ driver()->PropagateAutofillPredictions(queried_forms);
}
-void AutofillManager::PreProcessStateMatchingTypes(
- const std::vector<AutofillProfile>& profiles,
- FormStructure* form_structure) {
- if (!base::FeatureList::IsEnabled(
- features::kAutofillUseAlternativeStateNameMap)) {
- return;
- }
-
- for (const auto& profile : profiles) {
- base::Optional<AlternativeStateNameMap::CanonicalStateName>
- canonical_state_name_from_profile =
- profile.GetAddress().GetCanonicalizedStateName();
-
- if (!canonical_state_name_from_profile)
- continue;
-
- const AutofillType kCountryCode(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE);
- const std::u16string& country_code =
- profile.GetInfo(kCountryCode, app_locale_);
-
- for (auto& field : *form_structure) {
- if (field->state_is_a_matching_type())
- continue;
-
- base::Optional<AlternativeStateNameMap::CanonicalStateName>
- canonical_state_name_from_text =
- AlternativeStateNameMap::GetCanonicalStateName(
- base::UTF16ToUTF8(country_code), field->value);
-
- if (canonical_state_name_from_text &&
- canonical_state_name_from_text.value() ==
- canonical_state_name_from_profile.value()) {
- field->set_state_is_a_matching_type();
- }
- }
- }
-}
+void AutofillManager::OnServerRequestError(
+ FormSignature form_signature,
+ AutofillDownloadManager::RequestType request_type,
+ int http_error) {}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_manager.h b/chromium/components/autofill/core/browser/autofill_manager.h
index ddaffb1a0e4..963b907b3dd 100644
--- a/chromium/components/autofill/core/browser/autofill_manager.h
+++ b/chromium/components/autofill/core/browser/autofill_manager.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// 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.
@@ -7,40 +7,25 @@
#include <map>
#include <memory>
-#include <set>
#include <string>
#include <vector>
-#include "base/callback_forward.h"
+#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
-#include "base/containers/circular_deque.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
+#include "base/scoped_observation.h"
#include "base/time/time.h"
-#include "base/timer/timer.h"
#include "build/build_config.h"
-#include "components/autofill/core/browser/autocomplete_history_manager.h"
-#include "components/autofill/core/browser/autofill_client.h"
+#include "components/autofill/core/browser/autofill_download_manager.h"
#include "components/autofill/core/browser/autofill_driver.h"
-#include "components/autofill/core/browser/autofill_external_delegate.h"
-#include "components/autofill/core/browser/autofill_handler.h"
-#include "components/autofill/core/browser/field_filler.h"
-#include "components/autofill/core/browser/form_types.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/payments/autofill_offer_manager.h"
-#include "components/autofill/core/browser/payments/card_unmask_delegate.h"
-#include "components/autofill/core/browser/payments/credit_card_access_manager.h"
-#include "components/autofill/core/browser/payments/full_card_request.h"
-#include "components/autofill/core/browser/personal_data_manager.h"
-#include "components/autofill/core/browser/sync_utils.h"
-#include "components/autofill/core/browser/ui/popup_types.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/common/dense_set.h"
#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/language_code.h"
+#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/signatures.h"
-#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "components/autofill/core/common/unique_ids.h"
+#include "components/translate/core/browser/translate_driver.h"
+#include "components/version_info/channel.h"
namespace gfx {
class RectF;
@@ -49,680 +34,342 @@ class RectF;
namespace autofill {
class AutofillField;
-class AutofillClient;
-class AutofillManagerTestDelegate;
-class AutofillProfile;
-class AutofillType;
-class CreditCard;
-class FormStructureBrowserTest;
-
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.
+class AutofillManager
+ : public AutofillDownloadManager::Observer,
+ public translate::TranslateDriver::LanguageDetectionObserver {
+ public:
+ enum AutofillDownloadManagerState {
+ ENABLE_AUTOFILL_DOWNLOAD_MANAGER,
+ DISABLE_AUTOFILL_DOWNLOAD_MANAGER,
+ };
-// We show the credit card signin promo only a certain number of times.
-extern const int kCreditCardSigninPromoImpressionLimit;
+ // An observer class used by browsertests that gets notified whenever
+ // particular actions occur.
+ class ObserverForTest {
+ public:
+ virtual void OnFormParsed() = 0;
+ };
-// Enum for the value patterns metric. Don't renumerate existing value. They are
-// used for metrics.
-enum class ValuePatternsMetric {
- kNoPatternFound = 0,
- kUpiVpa = 1, // UPI virtual payment address.
- kIban = 2, // International Bank Account Number.
- kMaxValue = kIban,
-};
+ // The factory method for the embedder to create the subclass of
+ // AutofillManager in ContentAutofillDriver.
+ using AutofillManagerFactoryCallback =
+ base::RepeatingCallback<std::unique_ptr<AutofillManager>(
+ AutofillDriver*,
+ AutofillClient*,
+ const std::string& app_locale,
+ AutofillManager::AutofillDownloadManagerState)>;
+
+ // Raw metadata uploading enabled iff this Chrome instance is on Canary or Dev
+ // channel.
+ static bool IsRawMetadataUploadingEnabled(version_info::Channel channel);
+
+ // TODO(crbug.com/1151542): Move to anonymous namespace once
+ // BrowserAutofillManager::OnLoadedServerPredictions() moves to
+ // AutofillManager.
+ static void LogAutofillTypePredictionsAvailable(
+ LogManager* log_manager,
+ const std::vector<FormStructure*>& forms);
-// Manages saving and restoring the user's personal information entered into web
-// forms. One per frame; owned by the AutofillDriver.
-class AutofillManager : public AutofillHandler,
- public AutocompleteHistoryManager::SuggestionsHandler,
- public CreditCardAccessManager::Accessor {
- public:
- AutofillManager(AutofillDriver* driver,
- AutofillClient* client,
- const std::string& app_locale,
- AutofillDownloadManagerState enable_download_manager);
~AutofillManager() override;
- void ShowAutofillSettings(bool show_credit_card_settings);
-
- // Whether the |field| should show an entry to scan a credit card.
- virtual bool ShouldShowScanCreditCard(const FormData& form,
- const FormFieldData& field);
-
- // Returns the type of the popup being shown.
- virtual PopupType GetPopupType(const FormData& form,
- const FormFieldData& field);
-
- // Whether we should show the signin promo, based on the triggered |field|
- // inside the |form|.
- virtual bool ShouldShowCreditCardSigninPromo(const FormData& form,
- const FormFieldData& field);
-
- // 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.
- virtual bool ShouldShowCardsFromAccountOption(const FormData& form,
- const FormFieldData& field);
- virtual void OnUserAcceptedCardsFromAccountOption();
- virtual void RefetchCardsAndUpdatePopup(int query_id,
- const FormData& form,
- const FormFieldData& field_data);
-
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
- // Returns the list of credit cards that have associated cloud token data.
- virtual void FetchVirtualCardCandidates();
-
- // Callback invoked when an actual card is selected. |selected_card_id| will
- // be used to identify the card. The selected card's cloud token data will be
- // fetched from the server.
- // TODO(crbug.com/1020740): Passes card server id for now. In the future when
- // one actual credit card can have multiple virtual cards, passes instrument
- // token instead. Design TBD.
- virtual void OnVirtualCardCandidateSelected(
- const std::string& selected_card_id);
-#endif
-
- // Called from our external delegate so they cannot be private.
- virtual void FillOrPreviewForm(AutofillDriver::RendererFormDataAction action,
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- int unique_id);
- virtual void FillCreditCardForm(int query_id,
- const FormData& form,
- const FormFieldData& field,
- const CreditCard& credit_card,
- const std::u16string& cvc);
- void DidShowSuggestions(bool has_autofill_suggestions,
- const FormData& form,
- const FormFieldData& field);
-
- // Called from autofill assistant.
- virtual void FillProfileForm(const autofill::AutofillProfile& profile,
- const FormData& form,
- const FormFieldData& field);
-
- // Returns true if the value/identifier is deletable. Fills out
- // |title| and |body| with relevant user-facing text.
- bool GetDeletionConfirmationText(const std::u16string& value,
- int identifier,
- std::u16string* title,
- std::u16string* body);
-
- // Remove the credit card or Autofill profile that matches |unique_id|
- // from the database. Returns true if deletion is allowed.
- bool RemoveAutofillProfileOrCreditCard(int unique_id);
-
- // Remove the specified Autocomplete entry.
- void RemoveAutocompleteEntry(const std::u16string& name,
- const std::u16string& value);
-
- // Invoked when the user selected |value| in the Autocomplete drop-down.
- void OnAutocompleteEntrySelected(const std::u16string& value);
-
- // Invoked when the user selects the "Hide Suggestions" item in the
- // Autocomplete drop-down.
- virtual void OnUserHideSuggestions(const FormData& form,
- const FormFieldData& field);
-
- // Returns true only if the previewed form should be cleared.
- bool ShouldClearPreviewedForm();
-
- AutofillOfferManager* offer_manager() { return offer_manager_; }
-
- CreditCardAccessManager* credit_card_access_manager() {
- return credit_card_access_manager_.get();
- }
+ AutofillClient* client() { return client_; }
+ const AutofillClient* client() const { return client_; }
- payments::FullCardRequest* GetOrCreateFullCardRequest();
-
- base::WeakPtr<payments::FullCardRequest::UIDelegate>
- GetAsFullCardRequestUIDelegate();
-
- const std::string& app_locale() const { return app_locale_; }
-
- // Only for testing.
- void SetTestDelegate(AutofillManagerTestDelegate* delegate);
-
- // Will send an upload based on the |form_structure| data and the local
- // Autofill profile data. |observed_submission| is specified if the upload
- // follows an observed submission event. Returns false if the upload couldn't
- // start.
- virtual bool MaybeStartVoteUploadProcess(
- std::unique_ptr<FormStructure> form_structure,
- bool observed_submission);
-
- // Update the pending form with |form|, possibly processing the current
- // pending form for upload.
- void UpdatePendingForm(const FormData& form);
-
- // Upload the current pending form.
- void ProcessPendingFormForUpload();
-
- // Invoked when the popup view can't be created. Main usage is to collect
- // metrics.
- void DidSuppressPopup(const FormData& form, const FormFieldData& field);
-
- // AutofillHandler:
- void OnFocusNoLongerOnForm(bool had_interacted_form) override;
- void OnFocusOnFormFieldImpl(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) override;
- void OnDidFillAutofillFormData(const FormData& form,
- const base::TimeTicks timestamp) override;
- void OnDidPreviewAutofillFormData() override;
- void OnDidEndTextFieldEditing() override;
- void OnHidePopup() override;
- void SelectFieldOptionsDidChange(const FormData& form) override;
- void PropagateAutofillPredictions(
- content::RenderFrameHost* rfh,
- const std::vector<FormStructure*>& forms) override;
- void Reset() override;
+ // Invoked when the value of textfield is changed.
+ void OnTextFieldDidChange(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box,
+ const base::TimeTicks timestamp);
- // AutocompleteHistoryManager::SuggestionsHandler:
- void OnSuggestionsReturned(
- int query_id,
- bool autoselect_first_suggestion,
- const std::vector<Suggestion>& suggestions) override;
+ // Invoked when the textfield is scrolled.
+ void OnTextFieldDidScroll(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box);
- // Returns true if either Profile or CreditCard Autofill is enabled.
- virtual bool IsAutofillEnabled() const;
+ // Invoked when the value of select is changed.
+ void OnSelectControlDidChange(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box);
- // Returns true if the value of the AutofillProfileEnabled pref is true and
- // the client supports Autofill.
- virtual bool IsAutofillProfileEnabled() const;
+ // Invoked when the |form| needs to be autofilled, the |bounding_box| is
+ // a window relative value of |field|.
+ void OnQueryFormFieldAutofill(int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box,
+ bool autoselect_first_suggestion);
- // Returns true if the value of the AutofillCreditCardEnabled pref is true and
- // the client supports Autofill.
- virtual bool IsAutofillCreditCardEnabled() const;
+ // Invoked when |form|'s |field| has focus.
+ void OnFocusOnFormField(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box);
- // Shared code to determine if |form| should be uploaded to the Autofill
- // server. It verifies that uploading is allowed and |form| meets conditions
- // to be uploadable. Exposed for testing.
- bool ShouldUploadForm(const FormStructure& form);
+ // Invoked when |form| has been submitted.
+ // Processes the submitted |form|, saving any new Autofill data to the user's
+ // personal profile.
+ void OnFormSubmitted(const FormData& form,
+ bool known_success,
+ mojom::SubmissionSource source);
- // Returns the last form the autofill manager considered in this frame.
- virtual const FormData& last_query_form() const;
+ // Invoked when |forms| has been detected.
+ void OnFormsSeen(const std::vector<FormData>& forms);
- // Exposed to ContentAutofillDriver to help with recording WebOTP metrics.
- bool has_parsed_forms() const { return has_parsed_forms_; }
- bool has_observed_phone_number_field() const {
- return has_observed_phone_number_field_;
- }
- bool has_observed_one_time_code_field() const {
- return has_observed_one_time_code_field_;
+ // Invoked when focus is no longer on form. |had_interacted_form| indicates
+ // whether focus was previously on a form with which the user had interacted.
+ virtual void OnFocusNoLongerOnForm(bool had_interacted_form) = 0;
+
+ // Invoked when |form| has been filled with the value given by
+ // SendFormDataToRenderer.
+ virtual void OnDidFillAutofillFormData(const FormData& form,
+ const base::TimeTicks timestamp) = 0;
+
+ // Invoked when preview autofill value has been shown.
+ virtual void OnDidPreviewAutofillFormData() = 0;
+
+ // Invoked when textfeild editing ended
+ virtual void OnDidEndTextFieldEditing() = 0;
+
+ // Invoked when popup window should be hidden.
+ virtual void OnHidePopup() = 0;
+
+ // Invoked when the options of a select element in the |form| changed.
+ virtual void SelectFieldOptionsDidChange(const FormData& form) = 0;
+
+ // Invoked when the field type predictions are downloaded from the autofill
+ // server.
+ virtual void PropagateAutofillPredictions(
+ content::RenderFrameHost* rfh,
+ const std::vector<FormStructure*>& forms) = 0;
+
+ // Resets cache.
+ virtual void Reset();
+
+ // translate::TranslateDriver::LanguageDetectionObserver:
+ void OnTranslateDriverDestroyed(
+ translate::TranslateDriver* translate_driver) override;
+ // Invoked when the language has been detected by the Translate component.
+ // As this usually happens after Autofill has parsed the forms for the first
+ // time, the heuristics need to be re-run by this function in order to run
+ // use language-specific patterns.
+ void OnLanguageDetermined(
+ const translate::LanguageDetectionDetails& details) override;
+
+ // Send the form |data| to renderer for the specified |action|.
+ void SendFormDataToRenderer(int query_id,
+ AutofillDriver::RendererFormDataAction action,
+ const FormData& data);
+
+ // Fills |form_structure| and |autofill_field| with the cached elements
+ // corresponding to |form| and |field|. This might have the side-effect of
+ // updating the cache. Returns false if the |form| is not autofillable, or if
+ // it is not already present in the cache and the cache is full.
+ bool GetCachedFormAndField(const FormData& form,
+ const FormFieldData& field,
+ FormStructure** form_structure,
+ AutofillField** autofill_field) WARN_UNUSED_RESULT;
+
+ // Returns nullptr if no cached form structure is found with a matching
+ // |form_id|. Runs in logarithmic time.
+ FormStructure* FindCachedFormByRendererId(FormGlobalId form_id) const;
+
+ // Returns the number of forms this Autofill handler is aware of.
+ size_t NumFormsDetected() const { return form_structures_.size(); }
+
+ void SetEventObserverForTesting(ObserverForTest* observer) {
+ observer_for_testing_ = observer;
}
-#if defined(UNIT_TEST)
- void SetExternalDelegateForTest(
- std::unique_ptr<AutofillExternalDelegate> external_delegate) {
- external_delegate_ = std::move(external_delegate);
+ // Returns the present form structures seen by Autofill handler.
+ const std::map<FormGlobalId, std::unique_ptr<FormStructure>>&
+ form_structures() const {
+ return form_structures_;
}
- // A public wrapper that calls |DeterminePossibleFieldTypesForUpload| for
- // testing purposes only.
- static void DeterminePossibleFieldTypesForUploadForTest(
- const std::vector<AutofillProfile>& profiles,
- const std::vector<CreditCard>& credit_cards,
- const std::u16string& last_unlocked_credit_card_cvc,
- const std::string& app_locale,
- FormStructure* submitted_form) {
- DeterminePossibleFieldTypesForUpload(profiles, credit_cards,
- last_unlocked_credit_card_cvc,
- app_locale, submitted_form);
+ AutofillDriver* driver() { return driver_; }
+
+ AutofillDownloadManager* download_manager() {
+ return download_manager_.get();
}
- // A public wrapper that calls |MakeFrontendID| for testing purposes only.
- int MakeFrontendIDForTest(const std::string& cc_backend_id,
- const std::string& profile_backend_id) const {
- return MakeFrontendID(cc_backend_id, profile_backend_id);
+ // The return value shouldn't be cached, retrieve it as needed.
+ AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger() {
+ return form_interactions_ukm_logger_.get();
}
- // A public wrapper that calls |ShouldTriggerRefill| for testing purposes
+ // A public wrapper that calls |OnLoadedServerPredictions| for testing
+ // purposes only, it is used by WebView integration test and unit test, so it
+ // can't be in #ifdef UNIT_TEST.
+ void OnLoadedServerPredictionsForTest(
+ std::string response,
+ const std::vector<FormSignature>& queried_form_signatures) {
+ OnLoadedServerPredictions(response, queried_form_signatures);
+ }
+ void OnServerRequestErrorForTest(
+ FormSignature form_signature,
+ AutofillDownloadManager::RequestType request_type,
+ int http_error) {
+ OnServerRequestError(form_signature, request_type, http_error);
+ }
+#ifdef UNIT_TEST
+ // A public wrapper that calls |mutable_form_structures| for testing purposes
// only.
- bool ShouldTriggerRefillForTest(const FormStructure& form_structure) {
- return ShouldTriggerRefill(form_structure);
+ std::map<FormGlobalId, std::unique_ptr<FormStructure>>*
+ mutable_form_structures_for_test() {
+ return mutable_form_structures();
}
- // A public wrapper that calls |TriggerRefill| for testing purposes only.
- void TriggerRefillForTest(const FormData& form) { TriggerRefill(form); }
-
- // A public wrapper that calls |PreProcessStateMatchingTypes| for testing
- // purposes.
- void PreProcessStateMatchingTypesForTest(
- const std::vector<AutofillProfile>& profiles,
- FormStructure* form_structure) {
- PreProcessStateMatchingTypes(profiles, form_structure);
+ // A public wrapper that calls |ParseForm| for testing purposes only.
+ FormStructure* ParseFormForTest(const FormData& form) {
+ return ParseForm(form, nullptr);
}
-#endif
+
+#endif // UNIT_TEST
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,
- 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.
- virtual void UploadFormData(const FormStructure& submitted_form,
- bool observed_submission);
-
- // Logs quality metrics for the |submitted_form| and uploads the form data
- // to the crowdsourcing server, if appropriate. |observed_submission|
- // indicates whether the upload is a result of an observed submission event.
- virtual void UploadFormDataAsyncCallback(
- const FormStructure* submitted_form,
- const base::TimeTicks& interaction_time,
- const base::TimeTicks& submission_time,
- bool observed_submission);
-
- // Maps suggestion backend ID to and from an integer identifying it. Two of
- // these intermediate integers are packed by MakeFrontendID to make the IDs
- // that this class generates for the UI and for IPC.
- virtual int BackendIDToInt(const std::string& backend_id) const;
- virtual std::string IntToBackendID(int int_id) const;
-
- // Methods for packing and unpacking credit card and profile IDs for sending
- // and receiving to and from the renderer process.
- int MakeFrontendID(const std::string& cc_backend_id,
- const std::string& profile_backend_id) const;
- void SplitFrontendID(int frontend_id,
- std::string* cc_backend_id,
- std::string* profile_backend_id) const;
-
- // AutofillHandler:
- void OnFormSubmittedImpl(const FormData& form,
- bool known_success,
- mojom::SubmissionSource source) override;
- void OnTextFieldDidChangeImpl(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box,
- const base::TimeTicks timestamp) override;
- void OnTextFieldDidScrollImpl(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) override {}
- void OnQueryFormFieldAutofillImpl(int query_id,
- const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& transformed_box,
- bool autoselect_first_suggestion) override;
- void OnSelectControlDidChangeImpl(const FormData& form,
- const FormFieldData& field,
- const gfx::RectF& bounding_box) override;
- bool ShouldParseForms(const std::vector<FormData>& forms) override;
- void OnBeforeProcessParsedForms() override;
- void OnFormProcessed(const FormData& form,
- const FormStructure& form_structure) override;
- void OnAfterProcessParsedForms(const DenseSet<FormType>& form_types) override;
+ AutofillManager(AutofillDriver* driver,
+ AutofillClient* client,
+ AutofillDownloadManagerState enable_download_manager);
+ AutofillManager(AutofillDriver* driver,
+ AutofillClient* client,
+ AutofillDownloadManagerState enable_download_manager,
+ version_info::Channel channel);
- // Exposed for testing.
- FormData* pending_form_data() { return pending_form_data_.get(); }
+ LogManager* log_manager() { return log_manager_; }
- private:
- FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, PageLanguageGetsCorrectlySet);
- FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest,
- PageLanguageGetsCorrectlyDetected);
- FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, DoNotFillIfFormFieldChanged);
- FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, DoNotFillIfFormFieldRemoved);
-
- // Keeps track of the filling context for a form, used to make refill attemps.
- struct FillingContext {
- // |profile_or_credit_card| contains either AutofillProfile or CreditCard
- // and must be non-null.
- // If |profile_or_credit_card| contains a CreditCard, |optional_cvc| may be
- // non-null.
- FillingContext(const AutofillField& field,
- absl::variant<const AutofillProfile*, const CreditCard*>
- profile_or_credit_card,
- const std::u16string* optional_cvc);
- ~FillingContext();
-
- // Whether a refill attempt was made.
- bool attempted_refill = false;
- // The profile or credit card that was used for the initial fill.
- // The std::string associated with the credit card is the CVC, which may be
- // empty.
- absl::variant<AutofillProfile, std::pair<CreditCard, std::u16string>>
- profile_or_credit_card_with_cvc;
- // Possible identifiers of the field that was focused when the form was
- // initially filled. A refill shall be triggered from the same field.
- // TODO(crbug/896689): Remove |filled_field_unique_name|.
- const FieldGlobalId filled_field_id;
- const FieldSignature filled_field_signature;
- const std::u16string filled_field_unique_name;
- // The security origin from which the field was filled.
- url::Origin filled_origin;
- // The time at which the initial fill occurred.
- const base::TimeTicks original_fill_time;
- // The timer used to trigger a refill.
- base::OneShotTimer on_refill_timer;
- // The field type groups that were initially filled.
- std::set<FieldTypeGroup> type_groups_originally_filled;
- };
+ // Retrieves the page language from |client_|
+ LanguageCode GetCurrentPageLanguage() const;
- // Indicates the reason why autofill suggestions are suppressed.
- enum class SuppressReason {
- kNotSuppressed,
- // Credit card suggestions are not shown because an ablation experiment is
- // enabled.
- kCreditCardsAblation,
- // Address suggestions are not shown because the field is annotated with
- // autocomplete=off and the directive is being observed by the browser.
- kAutocompleteOff,
- // Suggestions are not shown because this form is on a secure site, but
- // submits insecurely. This is only used when the user has started typing,
- // otherwise a warning is shown.
- kInsecureForm,
- };
+ virtual void OnFormSubmittedImpl(const FormData& form,
+ bool known_success,
+ mojom::SubmissionSource source) = 0;
- // The context for the list of suggestions available for a given field to be
- // returned by GetAvailableSuggestions().
- struct SuggestionsContext {
- FormStructure* form_structure = nullptr;
- AutofillField* focused_field = nullptr;
- bool is_autofill_available = false;
- bool is_context_secure = false;
- bool is_filling_credit_card = false;
- // Flag to indicate whether all suggestions come from Google Payments.
- bool should_display_gpay_logo = false;
- SuppressReason suppress_reason = SuppressReason::kNotSuppressed;
- };
+ virtual void OnTextFieldDidChangeImpl(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box,
+ const base::TimeTicks timestamp) = 0;
- // CreditCardAccessManager::Accessor
- void OnCreditCardFetched(
- bool did_succeed,
- const CreditCard* credit_card = nullptr,
- const std::u16string& cvc = std::u16string()) override;
-
- // Returns false if Autofill is disabled or if no Autofill data is available.
- bool RefreshDataModels();
-
- // Gets the card referred to by the guid |unique_id|. Returns |nullptr| if
- // card does not exist.
- CreditCard* GetCreditCard(int unique_id);
-
- // Gets the profile referred to by the guid |unique_id|. Returns |nullptr| if
- // profile does not exist.
- AutofillProfile* GetProfile(int unique_id);
-
- // Determines whether a fill on |form| initiated from |field| will wind up
- // filling a credit card number. This is useful to determine if we will need
- // to unmask a card.
- bool WillFillCreditCardNumber(const FormData& form,
- const FormFieldData& field);
-
- // Fills or previews the credit card form.
- // Assumes the form and field are valid.
- void FillOrPreviewCreditCardForm(
- AutofillDriver::RendererFormDataAction action,
+ virtual void OnTextFieldDidScrollImpl(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) = 0;
+
+ virtual void OnQueryFormFieldAutofillImpl(
int query_id,
const FormData& form,
const FormFieldData& field,
- const CreditCard* credit_card);
+ const gfx::RectF& bounding_box,
+ bool autoselect_first_suggestion) = 0;
+
+ virtual void OnFocusOnFormFieldImpl(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) = 0;
+
+ virtual void OnSelectControlDidChangeImpl(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) = 0;
+
+ // Return whether the |forms| from OnFormSeen() should be parsed to
+ // form_structures.
+ virtual bool ShouldParseForms(const std::vector<FormData>& forms) = 0;
+
+ // Invoked before parsing the forms.
+ virtual void OnBeforeProcessParsedForms() = 0;
+
+ // Invoked when the given |form| has been processed to the given
+ // |form_structure|.
+ virtual void OnFormProcessed(const FormData& form,
+ const FormStructure& form_structure) = 0;
+ // Invoked after all forms have been processed, |form_types| is a set of
+ // FormType found.
+ virtual void OnAfterProcessParsedForms(
+ const DenseSet<FormType>& form_types) = 0;
+
+ // Returns the number of FormStructures with the given |form_signature| and
+ // appends them to |form_structures|. Runs in linear time.
+ size_t FindCachedFormsBySignature(
+ FormSignature form_signature,
+ std::vector<FormStructure*>* form_structures) const;
+
+ // Parses the |form| with the server data retrieved from the |cached_form|
+ // (if any). Returns nullptr if the form should not be parsed. Otherwise, adds
+ // the returned form structure to the |form_structures_|.
+ FormStructure* ParseForm(const FormData& form,
+ const FormStructure* cached_form);
+
+ bool value_from_dynamic_change_form_ = false;
+
+ std::map<FormGlobalId, std::unique_ptr<FormStructure>>*
+ mutable_form_structures() {
+ return &form_structures_;
+ }
- // Fills or previews the profile form.
- // Assumes the form and field are valid.
- void FillOrPreviewProfileForm(AutofillDriver::RendererFormDataAction action,
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- const AutofillProfile& profile);
+#ifdef UNIT_TEST
+ // Exposed for testing.
+ void set_download_manager_for_test(
+ std::unique_ptr<AutofillDownloadManager> manager) {
+ download_manager_ = std::move(manager);
+ }
+#endif // UNIT_TEST
- // Fills or previews |data_model| in the |form|.
- void FillOrPreviewDataModelForm(
- AutofillDriver::RendererFormDataAction action,
- int query_id,
- const FormData& form,
- const FormFieldData& field,
- absl::variant<const AutofillProfile*, const CreditCard*>
- profile_or_credit_card,
- const std::u16string* optional_cvc,
- FormStructure* form_structure,
- AutofillField* autofill_field,
- bool is_refill = false);
-
- // Creates a FormStructure using the FormData received from the renderer. Will
- // return an empty scoped_ptr if the data should not be processed for upload
- // or personal data.
- std::unique_ptr<FormStructure> ValidateSubmittedForm(const FormData& form);
-
- // Returns the field corresponding to |form| and |field| that can be
- // autofilled. Returns NULL if the field cannot be autofilled.
- AutofillField* GetAutofillField(const FormData& form,
- const FormFieldData& field)
- WARN_UNUSED_RESULT;
-
- // Returns true if any form in the field corresponds to an address
- // |FieldTypeGroup|.
- bool FormHasAddressField(const FormData& form) WARN_UNUSED_RESULT;
-
- // Returns Suggestions corresponding to both the |autofill_field| type and
- // stored profiles whose values match the contents of |field|. |form| stores
- // data about the form with which the user is interacting, e.g. the number and
- // types of form fields.
- std::vector<Suggestion> GetProfileSuggestions(
- const FormStructure& form,
- const FormFieldData& field,
- const AutofillField& autofill_field) const;
+ private:
+ // AutofillDownloadManager::Observer:
+ void OnLoadedServerPredictions(
+ std::string response,
+ const std::vector<FormSignature>& queried_form_signatures) override;
+ void OnServerRequestError(FormSignature form_signature,
+ AutofillDownloadManager::RequestType request_type,
+ int http_error) override;
+
+ // Invoked when forms from OnFormsSeen() have been parsed to
+ // |form_structures|.
+ void OnFormsParsed(const std::vector<const FormData*>& forms);
+
+ void PropagateAutofillPredictionsToDriver(
+ const std::vector<FormStructure*>& forms);
+
+ std::unique_ptr<AutofillMetrics::FormInteractionsUkmLogger>
+ CreateFormInteractionsUkmLogger();
+
+ // Provides driver-level context to the shared code of the component. Must
+ // outlive this object.
+ AutofillDriver* const driver_;
+
+ AutofillClient* const client_;
+
+ LogManager* const log_manager_;
+
+ // Observer needed to re-run heuristics when the language has been detected.
+ base::ScopedObservation<
+ translate::TranslateDriver,
+ translate::TranslateDriver::LanguageDetectionObserver,
+ &translate::TranslateDriver::AddLanguageDetectionObserver,
+ &translate::TranslateDriver::RemoveLanguageDetectionObserver>
+ translate_observation_{this};
+
+ // Our copy of the form data.
+ std::map<FormGlobalId, std::unique_ptr<FormStructure>> form_structures_;
+
+ // Handles queries and uploads to Autofill servers. Will be nullptr if
+ // the download manager functionality is disabled.
+ std::unique_ptr<AutofillDownloadManager> download_manager_;
+
+ // Utility for logging URL keyed metrics.
+ std::unique_ptr<AutofillMetrics::FormInteractionsUkmLogger>
+ form_interactions_ukm_logger_;
+
+ // Task to delay propagate the query result to driver for testing.
+ base::CancelableOnceCallback<void(const std::vector<FormStructure*>&)>
+ query_result_delay_task_;
+
+ // Will be not null only for |SaveCardBubbleViewsFullFormBrowserTest|.
+ ObserverForTest* observer_for_testing_ = nullptr;
- // Returns a list of values from the stored credit cards that match |type| and
- // the value of |field| and returns the labels of the matching credit cards.
- // |should_display_gpay_logo| will be set to true if there is no credit card
- // suggestions or all suggestions come from Payments server.
- std::vector<Suggestion> GetCreditCardSuggestions(
- const FormFieldData& field,
- const AutofillType& type,
- bool* should_display_gpay_logo) const;
-
- // If |initial_interaction_timestamp_| is unset or is set to a later time than
- // |interaction_timestamp|, updates the cached timestamp. The latter check is
- // needed because IPC messages can arrive out of order.
- void UpdateInitialInteractionTimestamp(
- const base::TimeTicks& interaction_timestamp);
-
- // Examines |form| and returns true if it is in a non-secure context or
- // its action attribute targets a HTTP url.
- bool IsFormNonSecure(const FormData& form) const;
-
- // Uses the existing personal data in |profiles| and |credit_cards| to
- // determine possible field types for the |submitted_form|. This is
- // potentially expensive -- on the order of 50ms even for a small set of
- // |stored_data|. Hence, it should not run on the UI thread -- to avoid
- // locking up the UI -- nor on the IO thread -- to avoid blocking IPC calls.
- static void DeterminePossibleFieldTypesForUpload(
- const std::vector<AutofillProfile>& profiles,
- const std::vector<CreditCard>& credit_cards,
- const std::u16string& last_unlocked_credit_card_cvc,
- const std::string& app_locale,
- FormStructure* submitted_form);
-
- // Uses context about previous and next fields to select the appropriate type
- // for fields with ambiguous upload types.
- static void DisambiguateUploadTypes(FormStructure* form);
-
- // Disambiguates address field upload types.
- static void DisambiguateAddressUploadTypes(FormStructure* form,
- size_t current_index);
-
- // Disambiguates phone field upload types.
- static void DisambiguatePhoneUploadTypes(FormStructure* form,
- size_t current_index);
-
- // Disambiguates name field upload types.
- static void DisambiguateNameUploadTypes(
- FormStructure* form,
- size_t current_index,
- const ServerFieldTypeSet& upload_types);
-
- void FillFieldWithValue(
- AutofillField* autofill_field,
- absl::variant<const AutofillProfile*, const CreditCard*>
- profile_or_credit_card,
- FormFieldData* field_data,
- bool should_notify,
- const std::u16string& cvc,
- uint32_t profile_form_bitmask,
- std::string* failure_to_fill);
-
- // TODO(crbug/896689): Remove code duplication once experiment is finished.
- void SetFillingContext(const FormStructure& form,
- std::unique_ptr<FillingContext> context);
-
- // TODO(crbug/896689): Remove code duplication once experiment is finished.
- FillingContext* GetFillingContext(const FormStructure& form);
-
- // Whether there should be an attempts to refill the form. Returns true if all
- // the following are satisfied:
- // There have been no refill on that page yet.
- // A non empty form name was recorded in a previous fill
- // That form name matched the currently parsed form name
- // It's been less than kLimitBeforeRefillMs since the original fill.
- bool ShouldTriggerRefill(const FormStructure& form_structure);
-
- // Attempts to refill the form that was changed dynamically. Should only be
- // called if ShouldTriggerRefill returns true.
- void TriggerRefill(const FormData& form);
-
- // Replaces the contents of |suggestions| with available suggestions for
- // |field|. |context| will contain additional information about the
- // suggestions, such as if they correspond to credit card suggestions and
- // if the context is secure.
- void GetAvailableSuggestions(const FormData& form,
- const FormFieldData& field,
- std::vector<Suggestion>* suggestions,
- SuggestionsContext* context);
-
- // For each submitted field in the |form_structure|, it determines whether
- // |ADDRESS_HOME_STATE| is a possible matching type.
- // This method is intended to run matching type detection on the browser UI
- // thread.
- void PreProcessStateMatchingTypes(
- const std::vector<AutofillProfile>& profiles,
- FormStructure* form_structure);
-
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
- // Whether to show the option to use virtual card in the autofill popup.
- bool ShouldShowVirtualCardOption(FormStructure* form_structure);
-#endif
-
- // Returns an appropriate EventFormLogger for the given |field_type_group|.
- // May return nullptr.
- FormEventLoggerBase* GetEventFormLogger(
- FieldTypeGroup field_type_group) const;
-
- void SetDataList(const std::vector<std::u16string>& values,
- const std::vector<std::u16string>& labels);
-
- // Delegate to perform external processing (display, selection) on
- // our behalf.
- std::unique_ptr<AutofillExternalDelegate> external_delegate_;
-
- std::string app_locale_;
-
- // The personal data manager, used to save and load personal data to/from the
- // web database. This is overridden by the AutofillManagerTest.
- // Weak reference.
- // May be NULL. NULL indicates OTR.
- PersonalDataManager* personal_data_;
-
- // Used to help fill data into fields.
- FieldFiller field_filler_;
-
- base::circular_deque<std::string> autofilled_form_signatures_;
-
- // Handles single-field autocomplete form data.
- // May be NULL. NULL indicates OTR.
- base::WeakPtr<AutocompleteHistoryManager> autocomplete_history_manager_;
-
- // Utilities for logging form events.
- std::unique_ptr<AddressFormEventLogger> address_form_event_logger_;
- std::unique_ptr<CreditCardFormEventLogger> credit_card_form_event_logger_;
-
- // Have we logged whether Autofill is enabled for this page load?
- bool has_logged_autofill_enabled_ = false;
- // Have we logged an address suggestions count metric for this page?
- bool has_logged_address_suggestions_count_ = false;
- // Have we shown Autofill suggestions at least once?
- bool did_show_suggestions_ = false;
- // Has the user manually edited at least one form field among the autofillable
- // ones?
- bool user_did_type_ = false;
- // Has the user autofilled a form on this page?
- bool user_did_autofill_ = false;
- // Has the user edited a field that was previously autofilled?
- bool user_did_edit_autofilled_field_ = false;
-
- // Does |this| have any parsed forms?
- bool has_parsed_forms_ = false;
- // Is there a field with autocomplete="one-time-code" observed?
- bool has_observed_one_time_code_field_ = false;
- // Is there a field with phone number collection observed?
- bool has_observed_phone_number_field_ = false;
-
- // When the user first interacted with a potentially fillable form on this
- // page.
- base::TimeTicks initial_interaction_timestamp_;
-
- // A copy of the currently interacted form data.
- std::unique_ptr<FormData> pending_form_data_;
-
- // The credit card access manager, used to access local and server cards.
- std::unique_ptr<CreditCardAccessManager> credit_card_access_manager_;
-
- // The autofill offer manager, used to to retrieve offers for card
- // suggestions. Initialized when AutofillManager is created. |offer_manager_|
- // is never null.
- AutofillOfferManager* offer_manager_;
-
- // Collected information about the autofill form where a credit card will be
- // filled.
- AutofillDriver::RendererFormDataAction credit_card_action_;
- int credit_card_query_id_ = -1;
- FormData credit_card_form_;
- FormFieldData credit_card_field_;
- CreditCard credit_card_;
- std::u16string last_unlocked_credit_card_cvc_;
-
- // Ablation experiment turns off autofill, but logging still has to be kept
- // for metrics analysis.
- bool enable_ablation_logging_ = false;
-
- // Suggestion backend ID to ID mapping. We keep two maps to convert back and
- // forth. These should be used only by BackendIDToInt and IntToBackendID.
- // Note that the integers are not frontend IDs.
- mutable std::map<std::string, int> backend_to_int_map_;
- mutable std::map<int, std::string> int_to_backend_map_;
-
- // Delegate used in test to get notifications on certain events.
- AutofillManagerTestDelegate* test_delegate_ = nullptr;
-
- // A map of form names to FillingContext instances used to make refill
- // attempts for dynamic forms.
- // TODO(crbug/896689): Remove code duplication once experiment is finished.
- std::map<FormGlobalId, std::unique_ptr<FillingContext>>
- filling_context_by_global_id_;
- std::map<std::u16string, std::unique_ptr<FillingContext>>
- filling_context_by_unique_name_;
-
- // Used to record metrics. This should be set at the beginning of the
- // interaction and re-used throughout the context of this manager.
- AutofillSyncSigninState sync_state_ = AutofillSyncSigninState::kNumSyncStates;
-
- base::WeakPtrFactory<AutofillManager> weak_ptr_factory_{this};
-
- friend class AutofillAssistantTest;
- friend class AutofillManagerTest;
- friend class AutofillMetricsTest;
- friend class FormStructureBrowserTest;
- friend class GetMatchingTypesTest;
- friend class CreditCardAccessoryControllerTest;
DISALLOW_COPY_AND_ASSIGN(AutofillManager);
};
diff --git a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
index 39df0b8f98e..cf2d1f6107b 100644
--- a/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -292,7 +292,7 @@ void AutofillMergeTest::MergeProfiles(const std::string& profiles,
// Import the profile.
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> unused_imported_upi_id;
+ absl::optional<std::string> unused_imported_upi_id;
form_data_importer_->ImportFormData(form_structure,
true, // address autofill enabled,
true, // credit card autofill enabled
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.cc b/chromium/components/autofill/core/browser/autofill_metrics.cc
index 0aa01bd33cb..c71ef671bb2 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics.cc
@@ -8,12 +8,14 @@
#include <utility>
#include <vector>
+#include "base/containers/fixed_flat_map.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
+#include "base/strings/string_piece_forward.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/autofill_field.h"
@@ -39,6 +41,29 @@ namespace {
// Exponential bucket spacing for UKM event data.
constexpr double kAutofillEventDataBucketSpacing = 2.0;
+// Translates structured name types into simple names that are used for
+// naming histograms.
+constexpr auto kStructuredNameTypeToNameMap =
+ base::MakeFixedFlatMap<ServerFieldType, base::StringPiece>(
+ {{NAME_FULL, "Full"},
+ {NAME_FIRST, "First"},
+ {NAME_MIDDLE, "Middle"},
+ {NAME_LAST, "Last"},
+ {NAME_LAST_FIRST, "FirstLast"},
+ {NAME_LAST_SECOND, "SecondLast"}});
+
+// Translates structured address types into simple names that are used for
+// naming histograms.
+constexpr auto kStructuredAddressTypeToNameMap =
+ base::MakeFixedFlatMap<ServerFieldType, base::StringPiece>(
+ {{ADDRESS_HOME_STREET_ADDRESS, "StreetAddress"},
+ {ADDRESS_HOME_STREET_NAME, "StreetName"},
+ {ADDRESS_HOME_HOUSE_NUMBER, "HouseNumber"},
+ {ADDRESS_HOME_FLOOR, "FloorNumber"},
+ {ADDRESS_HOME_APT_NUM, "ApartmentNumber"},
+ {ADDRESS_HOME_PREMISE_NAME, "Premise"},
+ {ADDRESS_HOME_SUBPREMISE, "SubPremise"}});
+
// Note: if adding an enum value here, update the corresponding description for
// AutofillFieldPredictionQualityByFieldType in
// tools/metrics/histograms/enums.xml.
@@ -102,6 +127,61 @@ std::string PreviousSaveCreditCardPromptUserDecisionToString(
return previous_response;
}
+// Converts a server field type that can be edited in the settings to an enum
+// used for metrics.
+AutofillMetrics::SettingsVisibleFieldTypeForMetrics
+ConvertSettingsVisibleFieldTypeForMetrics(ServerFieldType field_type) {
+ switch (field_type) {
+ case ServerFieldType::NAME_FULL:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kName;
+ break;
+
+ case ServerFieldType::EMAIL_ADDRESS:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kEmailAddress;
+ break;
+
+ case ServerFieldType::PHONE_HOME_WHOLE_NUMBER:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kPhoneNumber;
+ break;
+
+ case ServerFieldType::ADDRESS_HOME_CITY:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kCity;
+ break;
+
+ case ServerFieldType::ADDRESS_HOME_COUNTRY:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kCountry;
+ break;
+
+ case ServerFieldType::ADDRESS_HOME_ZIP:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kZip;
+ break;
+
+ case ServerFieldType::ADDRESS_HOME_STATE:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kState;
+ break;
+
+ case ServerFieldType::ADDRESS_HOME_STREET_ADDRESS:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::
+ kStreetAddress;
+ break;
+
+ case ServerFieldType::ADDRESS_HOME_DEPENDENT_LOCALITY:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::
+ kDependentLocality;
+ break;
+
+ case ServerFieldType::NAME_HONORIFIC_PREFIX:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::
+ kHonorificPrefix;
+ break;
+
+ default:
+ return AutofillMetrics::SettingsVisibleFieldTypeForMetrics::kUndefined;
+ NOTREACHED();
+ break;
+ }
+}
+
} // namespace
// First, translates |field_type| to the corresponding logical |group| from
@@ -1823,6 +1903,9 @@ void AutofillMetrics::LogStoredCreditCardMetrics(
num_unmasked_cards += 1;
num_disused_unmasked_cards += disused_delta;
break;
+ case CreditCard::VIRTUAL_CARD:
+ // This card type is not persisted in Chrome.
+ break;
}
}
@@ -1873,6 +1956,16 @@ void AutofillMetrics::LogStoredCreditCardMetrics(
"Autofill.StoredCreditCardDisusedCount.Server.Unmasked",
num_disused_unmasked_cards);
}
+
+ // Log the number of server cards that are enrolled with virtual cards.
+ size_t virtual_card_enabled_card_count = base::ranges::count_if(
+ server_cards, [](const std::unique_ptr<CreditCard>& card) {
+ return card->virtual_card_enrollment_state() ==
+ CreditCard::VirtualCardEnrollmentState::ENROLLED;
+ });
+ base::UmaHistogramCounts1000(
+ "Autofill.StoredCreditCardCount.Server.WithVirtualCardMetadata",
+ virtual_card_enabled_card_count);
}
// static
@@ -2586,4 +2679,109 @@ void AutofillMetrics::LogNumberOfAutofilledFieldsAtSubmission(
"Autofill.NumberOfAutofilledFieldsAtSubmission.Corrected",
number_of_corrected_fields, 50);
}
+
+void AutofillMetrics::LogProfileImportType(
+ AutofillProfileImportType import_type) {
+ base::UmaHistogramEnumeration("Autofill.ProfileImport.ProfileImportType",
+ import_type);
+}
+
+void AutofillMetrics::LogNewProfileImportDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision decision) {
+ base::UmaHistogramEnumeration("Autofill.ProfileImport.NewProfileDecision",
+ decision);
+}
+
+void AutofillMetrics::LogNewProfileEditedType(ServerFieldType edited_type) {
+ base::UmaHistogramEnumeration(
+ "Autofill.ProfileImport.NewProfileEditedType",
+ ConvertSettingsVisibleFieldTypeForMetrics(edited_type));
+}
+
+void AutofillMetrics::LogNewProfileNumberOfEditedFields(
+ int number_of_edited_fields) {
+ base::UmaHistogramExactLinear(
+ "Autofill.ProfileImport.NewProfileNumberOfEditedFields",
+ number_of_edited_fields, /*exclusive_max=*/15);
+}
+
+void AutofillMetrics::LogProfileUpdateImportDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision decision) {
+ base::UmaHistogramEnumeration("Autofill.ProfileImport.UpdateProfileDecision",
+ decision);
+}
+
+void AutofillMetrics::LogProfileUpdateAffectedType(
+ ServerFieldType affected_type) {
+ base::UmaHistogramEnumeration(
+ "Autofill.ProfileImport.UpdateProfileAffectedType",
+ ConvertSettingsVisibleFieldTypeForMetrics(affected_type));
+}
+
+void AutofillMetrics::LogProfileUpdateEditedType(ServerFieldType edited_type) {
+ base::UmaHistogramEnumeration(
+ "Autofill.ProfileImport.UpdateProfileEditedType",
+ ConvertSettingsVisibleFieldTypeForMetrics(edited_type));
+}
+
+void AutofillMetrics::LogUpdateProfileNumberOfEditedFields(
+ int number_of_edited_fields) {
+ base::UmaHistogramExactLinear(
+ "Autofill.ProfileImport.UpdateProfileNumberOfEditedFields",
+ number_of_edited_fields, /*exclusive_max=*/15);
+}
+
+void AutofillMetrics::LogUpdateProfileNumberOfAffectedFields(
+ int number_of_edited_fields) {
+ base::UmaHistogramExactLinear(
+ "Autofill.ProfileImport.UpdateProfileNumberOfAffectedFields",
+ number_of_edited_fields, /*exclusive_max=*/15);
+}
+
+void AutofillMetrics::LogVerificationStatusOfNameTokensOnProfileUsage(
+ const AutofillProfile& profile) {
+ constexpr base::StringPiece base_histogram_name =
+ "Autofill.NameTokenVerificationStatusAtProfileUsage.";
+
+ for (const auto& type_name_pair : kStructuredNameTypeToNameMap) {
+ // Do not record the status for empty values.
+ if (profile.GetRawInfo(type_name_pair.first).empty()) {
+ continue;
+ }
+
+ structured_address::VerificationStatus status =
+ profile.GetVerificationStatus(type_name_pair.first);
+ base::UmaHistogramEnumeration(
+ base::StrCat({base_histogram_name, type_name_pair.second}), status);
+ base::UmaHistogramEnumeration(base::StrCat({base_histogram_name, "Any"}),
+ status);
+ }
+}
+
+void AutofillMetrics::LogVerificationStatusOfAddressTokensOnProfileUsage(
+ const AutofillProfile& profile) {
+ constexpr base::StringPiece base_histogram_name =
+ "Autofill.AddressTokenVerificationStatusAtProfileUsage.";
+
+ for (const auto& type_name_pair : kStructuredAddressTypeToNameMap) {
+ // Do not record the status for empty values.
+ if (profile.GetRawInfo(type_name_pair.first).empty()) {
+ continue;
+ }
+
+ structured_address::VerificationStatus status =
+ profile.GetVerificationStatus(type_name_pair.first);
+ base::UmaHistogramEnumeration(
+ base::StrCat({base_histogram_name, type_name_pair.second}), status);
+ base::UmaHistogramEnumeration(base::StrCat({base_histogram_name, "Any"}),
+ status);
+ }
+}
+
+// static
+void AutofillMetrics::LogVirtualCardMetadataSynced(bool existing_card) {
+ base::UmaHistogramBoolean("Autofill.VirtualCard.MetadataSynced",
+ existing_card);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_metrics.h b/chromium/components/autofill/core/browser/autofill_metrics.h
index b2c0772525a..3214942f8b6 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics.h
+++ b/chromium/components/autofill/core/browser/autofill_metrics.h
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_client.h"
+#include "components/autofill/core/browser/autofill_profile_import_process.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/field_types.h"
@@ -174,6 +175,25 @@ class AutofillMetrics {
NUM_SUBMITTED_CARD_STATE_METRICS,
};
+ // These values are persisted to UMA logs. Entries should not be renumbered
+ // and numeric values should never be reused. This is the subset of field
+ // types that can be changed in a profile change/store dialog or are affected
+ // in a profile merge operation.
+ enum class SettingsVisibleFieldTypeForMetrics {
+ kUndefined = 0,
+ kName = 1,
+ kEmailAddress = 2,
+ kPhoneNumber = 3,
+ kCity = 4,
+ kCountry = 5,
+ kZip = 6,
+ kState = 7,
+ kStreetAddress = 8,
+ kDependentLocality = 9,
+ kHonorificPrefix = 10,
+ kMaxValue = kHonorificPrefix
+ };
+
// Metric to measure if a submitted card's expiration date matches the same
// server card's expiration date (unmasked or not). Cards are considered to
// be the same if they have the same card number (if unmasked) or if they have
@@ -869,7 +889,7 @@ class AutofillMetrics {
SYNC_SERVICE_MISSING_AUTOFILL_WALLET_DATA_ACTIVE_TYPE = 2,
SYNC_SERVICE_MISSING_AUTOFILL_PROFILE_ACTIVE_TYPE = 3,
// Deprecated: ACCOUNT_WALLET_STORAGE_UPLOAD_DISABLED = 4,
- USING_SECONDARY_SYNC_PASSPHRASE = 5,
+ USING_EXPLICIT_SYNC_PASSPHRASE = 5,
LOCAL_SYNC_ENABLED = 6,
PAYMENTS_INTEGRATION_DISABLED = 7,
EMAIL_EMPTY = 8,
@@ -1579,11 +1599,58 @@ class AutofillMetrics {
size_t number_of_accepted_fields,
size_t number_of_corrected_fields);
- private:
- static void Log(AutocompleteEvent event);
+ // Logs the type of a profile import.
+ static void LogProfileImportType(AutofillProfileImportType import_type);
+
+ // Logs the user decision for importing a new profile
+ static void LogNewProfileImportDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision decision);
+
+ // Logs that a specific type was edited in a save prompt.
+ static void LogNewProfileEditedType(ServerFieldType edited_type);
+
+ // Logs the number of edited fields for an accepted profile save.
+ static void LogNewProfileNumberOfEditedFields(int number_of_edited_fields);
+
+ // Logs the user decision for updating an exiting profile.
+ static void LogProfileUpdateImportDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision decision);
+
+ // Logs that a specific type changed in a profile update which was accepted
+ // without manual edits.
+ static void LogProfileUpdateAffectedType(ServerFieldType affected_type);
+ // Logs that a specific type was edited in an update prompt.
+ static void LogProfileUpdateEditedType(ServerFieldType edited_type);
+
+ // Logs the number of edited fields for an accepted profile update.
+ static void LogUpdateProfileNumberOfEditedFields(int number_of_edited_fields);
+
+ // Logs the number of changed fields for a profile update that is accepted
+ // without manual edits.
+ static void LogUpdateProfileNumberOfAffectedFields(
+ int number_of_affected_fields);
+
+ // Logs when the virtual card metadata for one card have been updated.
+ static void LogVirtualCardMetadataSynced(bool existing_card);
+
+ // Logs the verification status of non-empty name-related profile tokens when
+ // a profile is used to fill a form.
+ static void LogVerificationStatusOfNameTokensOnProfileUsage(
+ const AutofillProfile& profile);
+
+ // Logs the verification status of non-empty address-related profile tokens
+ // when a profile is used to fill a form.
+ static void LogVerificationStatusOfAddressTokensOnProfileUsage(
+ const AutofillProfile& profile);
+
+ // The total number of values in the |CardUploadDecisionMetric| enum. Must be
+ // updated each time a new value is added.
static const int kNumCardUploadDecisionMetrics = 19;
+ private:
+ static void Log(AutocompleteEvent event);
+
DISALLOW_IMPLICIT_CONSTRUCTORS(AutofillMetrics);
};
diff --git a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
index aa595f3fd47..d2b3be2aca9 100644
--- a/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -17,6 +17,7 @@
#include "base/macros.h"
#include "base/metrics/metrics_hashes.h"
#include "base/metrics/statistics_recorder.h"
+#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
@@ -39,8 +40,8 @@
#include "components/autofill/core/browser/sync_utils.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_autofill_manager.h"
#include "components/autofill/core/browser/test_autofill_tick_clock.h"
+#include "components/autofill/core/browser/test_browser_autofill_manager.h"
#include "components/autofill/core/browser/test_form_data_importer.h"
#include "components/autofill/core/browser/test_form_structure.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
@@ -374,7 +375,7 @@ class AutofillMetricsTest : public testing::Test {
ukm::TestUkmRecorder* test_ukm_recorder_;
syncer::TestSyncService sync_service_;
std::unique_ptr<TestAutofillDriver> autofill_driver_;
- std::unique_ptr<TestAutofillManager> autofill_manager_;
+ std::unique_ptr<TestBrowserAutofillManager> browser_autofill_manager_;
std::unique_ptr<TestPersonalDataManager> personal_data_;
std::unique_ptr<MockAutocompleteHistoryManager> autocomplete_history_manager_;
AutofillExternalDelegate* external_delegate_;
@@ -390,9 +391,9 @@ AutofillMetricsTest::AutofillMetricsTest() {
}
AutofillMetricsTest::~AutofillMetricsTest() {
- // Order of destruction is important as AutofillManager relies on
+ // Order of destruction is important as BrowserAutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
- autofill_manager_.reset();
+ browser_autofill_manager_.reset();
}
void AutofillMetricsTest::SetUp() {
@@ -424,16 +425,17 @@ void AutofillMetricsTest::SetUp() {
autofill_client_.set_autofill_offer_manager(
std::make_unique<AutofillOfferManager>(personal_data_.get()));
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &autofill_client_, personal_data_.get(),
autocomplete_history_manager_.get());
auto external_delegate = std::make_unique<AutofillExternalDelegate>(
- autofill_manager_.get(), autofill_driver_.get());
+ browser_autofill_manager_.get(), autofill_driver_.get());
external_delegate_ = external_delegate.get();
- autofill_manager_->SetExternalDelegateForTest(std::move(external_delegate));
+ browser_autofill_manager_->SetExternalDelegateForTest(
+ std::move(external_delegate));
#if !defined(OS_IOS)
- autofill_manager_->credit_card_access_manager()
+ browser_autofill_manager_->credit_card_access_manager()
->set_fido_authenticator_for_testing(
std::make_unique<TestCreditCardFIDOAuthenticator>(
autofill_driver_.get(), &autofill_client_));
@@ -444,10 +446,10 @@ void AutofillMetricsTest::SetUp() {
}
void AutofillMetricsTest::TearDown() {
- // Order of destruction is important as AutofillManager and
+ // Order of destruction is important as BrowserAutofillManager and
// AutofillOfferManager rely on PersonalDataManager to be around when they
// gets destroyed.
- autofill_manager_.reset();
+ browser_autofill_manager_.reset();
autofill_driver_.reset();
autofill_client_.set_autofill_offer_manager(nullptr);
personal_data_.reset();
@@ -455,7 +457,7 @@ void AutofillMetricsTest::TearDown() {
}
void AutofillMetricsTest::PurgeUKM() {
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
test_ukm_recorder_->Purge();
autofill_client_.InitializeUKMSources();
}
@@ -491,7 +493,7 @@ void AutofillMetricsTest::RecreateProfile(bool is_server) {
void AutofillMetricsTest::SetFidoEligibility(bool is_verifiable) {
CreditCardAccessManager* access_manager =
- autofill_manager_->credit_card_access_manager();
+ browser_autofill_manager_->credit_card_access_manager();
#if !defined(OS_IOS)
static_cast<TestCreditCardFIDOAuthenticator*>(
access_manager->GetOrCreateFIDOAuthenticator())
@@ -502,14 +504,14 @@ void AutofillMetricsTest::SetFidoEligibility(bool is_verifiable) {
->AllowFidoRegistration(true);
access_manager->is_authentication_in_progress_ = false;
access_manager->can_fetch_unmask_details_.Signal();
- access_manager->is_user_verifiable_ = base::nullopt;
+ access_manager->is_user_verifiable_ = absl::nullopt;
}
void AutofillMetricsTest::OnDidGetRealPan(
AutofillClient::PaymentsRpcResult result,
const std::string& real_pan) {
payments::FullCardRequest* full_card_request =
- autofill_manager_->credit_card_access_manager_
+ browser_autofill_manager_->credit_card_access_manager_
->GetOrCreateCVCAuthenticator()
->full_card_request_.get();
DCHECK(full_card_request);
@@ -579,7 +581,7 @@ void AutofillMetricsTest::AddMaskedServerCreditCardWithOffer(
offer_data.merchant_domain = {url};
offer_data.eligible_instrument_id = {
masked_server_credit_card.instrument_id()};
- personal_data_->AddCreditCardOfferData(offer_data);
+ personal_data_->AddAutofillOfferData(offer_data);
personal_data_->Refresh();
}
@@ -627,29 +629,29 @@ TEST_F(AutofillMetricsTest, NumberOfAutofilledFieldsAtSubmission) {
// Set up our form data with two autofilled fields.
FormData form =
test::GetFormData({.description_for_logging = "NumberOfAutofilledFields",
- .fields = {{.label = "Autofilled",
- .name = "autofilled",
- .value = "Elvis Aaron Presley",
+ .fields = {{.label = u"Autofilled",
+ .name = u"autofilled",
+ .value = u"Elvis Aaron Presley",
.is_autofilled = true},
- {.label = "Autofilled but corrected",
- .name = "autofillfailed",
- .value = "buddy@gmail.com",
+ {.label = u"Autofilled but corrected",
+ .name = u"autofillfailed",
+ .value = u"buddy@gmail.com",
.is_autofilled = true},
- {.label = "Empty",
- .name = "empty",
- .value = "",
+ {.label = u"Empty",
+ .name = u"empty",
+ .value = u"",
.is_autofilled = false},
- {.label = "Unknown",
- .name = "unknown",
- .value = "garbage",
+ {.label = u"Unknown",
+ .name = u"unknown",
+ .value = u"garbage",
.is_autofilled = false},
- {.label = "Select",
- .name = "select",
- .value = "USA",
+ {.label = u"Select",
+ .name = u"select",
+ .value = u"USA",
.form_control_type = "select-one",
.is_autofilled = false},
{.role = ServerFieldType::PHONE_HOME_NUMBER,
- .value = "2345678901",
+ .value = u"2345678901",
.form_control_type = "tel",
.is_autofilled = true}},
.unique_renderer_id = test::MakeFormRendererId(),
@@ -664,17 +666,17 @@ TEST_F(AutofillMetricsTest, NumberOfAutofilledFieldsAtSubmission) {
EMAIL_ADDRESS, NO_SERVER_DATA, PHONE_HOME_CITY_AND_NUMBER};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
// Simulate user changing the second field of the form.
- autofill_manager_->OnTextFieldDidChange(form, form.fields[1], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[1],
+ gfx::RectF(), TimeTicks());
form.fields.at(1).is_autofilled = false;
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Test that the correct bucket for the number of filled fields received a
// count while the others remain at zero counts.
@@ -701,29 +703,29 @@ TEST_F(AutofillMetricsTest, QualityMetrics) {
// Set up our form data.
FormData form =
test::GetFormData({.description_for_logging = "QualityMetrics",
- .fields = {{.label = "Autofilled",
- .name = "autofilled",
- .value = "Elvis Aaron Presley",
+ .fields = {{.label = u"Autofilled",
+ .name = u"autofilled",
+ .value = u"Elvis Aaron Presley",
.is_autofilled = true},
- {.label = "Autofill Failed",
- .name = "autofillfailed",
- .value = "buddy@gmail.com",
+ {.label = u"Autofill Failed",
+ .name = u"autofillfailed",
+ .value = u"buddy@gmail.com",
.is_autofilled = false},
- {.label = "Empty",
- .name = "empty",
- .value = "",
+ {.label = u"Empty",
+ .name = u"empty",
+ .value = u"",
.is_autofilled = false},
- {.label = "Unknown",
- .name = "unknown",
- .value = "garbage",
+ {.label = u"Unknown",
+ .name = u"unknown",
+ .value = u"garbage",
.is_autofilled = false},
- {.label = "Select",
- .name = "select",
- .value = "USA",
+ {.label = u"Select",
+ .name = u"select",
+ .value = u"USA",
.form_control_type = "select-one",
.is_autofilled = false},
{.role = ServerFieldType::PHONE_HOME_NUMBER,
- .value = "2345678901",
+ .value = u"2345678901",
.form_control_type = "tel",
.is_autofilled = true}},
.unique_renderer_id = test::MakeFormRendererId(),
@@ -738,12 +740,12 @@ TEST_F(AutofillMetricsTest, QualityMetrics) {
EMAIL_ADDRESS, NO_SERVER_DATA, PHONE_HOME_CITY_AND_NUMBER};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Heuristic predictions.
{
@@ -881,17 +883,18 @@ TEST_F(AutofillMetricsTest, ProfileImportStatus_NoImport) {
FormData form = test::GetFormData(
{.description_for_logging = "ProfileImportStatus_NoImport",
.fields = {
- {.role = ServerFieldType::NAME_FULL, .value = "Elvis Aaron Presley"},
+ {.role = ServerFieldType::NAME_FULL,
+ .value = u"Elvis Aaron Presley"},
{.role = ServerFieldType::ADDRESS_HOME_LINE1,
- .value = "3734 Elvis Presley Blvd."},
- {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = "New York"},
- {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = "2345678901"},
+ .value = u"3734 Elvis Presley Blvd."},
+ {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = u"New York"},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = u"2345678901"},
{.role = ServerFieldType::ADDRESS_HOME_STATE,
- .value = "Invalid State"},
+ .value = u"Invalid State"},
{.role = ServerFieldType::ADDRESS_HOME_ZIP,
- .value = "00000000000000000"},
+ .value = u"00000000000000000"},
{.role = ServerFieldType::ADDRESS_HOME_COUNTRY,
- .value = "NoACountry"}}});
+ .value = u"NoACountry"}}});
std::vector<ServerFieldType> heuristic_types = {
NAME_FULL, ADDRESS_HOME_LINE1,
@@ -905,16 +908,16 @@ TEST_F(AutofillMetricsTest, ProfileImportStatus_NoImport) {
ADDRESS_HOME_COUNTRY};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
std::string histogram = "Autofill.AddressProfileImportStatus";
histogram_tester.ExpectBucketCount(
@@ -935,14 +938,15 @@ TEST_F(AutofillMetricsTest, ProfileImportStatus_RegularImport) {
FormData form = test::GetFormData(
{.description_for_logging = "ProfileImportStatus_RegularImport",
.fields = {
- {.role = ServerFieldType::NAME_FULL, .value = "Elvis Aaron Presley"},
+ {.role = ServerFieldType::NAME_FULL,
+ .value = u"Elvis Aaron Presley"},
{.role = ServerFieldType::ADDRESS_HOME_LINE1,
- .value = "3734 Elvis Presley Blvd."},
- {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = "New York"},
- {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = "2345678901"},
- {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = "CA"},
- {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = "37373"},
- {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = "USA"}}});
+ .value = u"3734 Elvis Presley Blvd."},
+ {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = u"New York"},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = u"2345678901"},
+ {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = u"CA"},
+ {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = u"37373"},
+ {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = u"USA"}}});
std::vector<ServerFieldType> heuristic_types = {
NAME_FULL, ADDRESS_HOME_LINE1,
@@ -956,16 +960,16 @@ TEST_F(AutofillMetricsTest, ProfileImportStatus_RegularImport) {
ADDRESS_HOME_COUNTRY};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
std::string histogram = "Autofill.AddressProfileImportStatus";
histogram_tester.ExpectBucketCount(
@@ -986,18 +990,19 @@ TEST_F(AutofillMetricsTest, ProfileImportStatus_UnionImport) {
FormData form = test::GetFormData(
{.description_for_logging = "ProfileImportStatus_UnionImport",
.fields = {
- {.role = ServerFieldType::NAME_FULL, .value = "Elvis Aaron Presley"},
+ {.role = ServerFieldType::NAME_FULL,
+ .value = u"Elvis Aaron Presley"},
{.role = ServerFieldType::ADDRESS_HOME_LINE1,
- .value = "3734 Elvis Presley Blvd."},
- {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = "37373"},
- {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = "USA"},
- {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = "2345678901"},
+ .value = u"3734 Elvis Presley Blvd."},
+ {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = u"37373"},
+ {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = u"USA"},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = u"2345678901"},
{.role = ServerFieldType::ADDRESS_HOME_CITY,
- .value = "New York",
+ .value = u"New York",
.autocomplete_attribute = "section-billing locality"},
// Add the last field of the form into a new section.
{.role = ServerFieldType::ADDRESS_HOME_STATE,
- .value = "CA",
+ .value = u"CA",
.autocomplete_attribute = "section-shipping address-level1"}}});
// Set the heuristic types.
@@ -1019,17 +1024,17 @@ TEST_F(AutofillMetricsTest, ProfileImportStatus_UnionImport) {
ADDRESS_HOME_STATE};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
base::HistogramTester histogram_tester;
std::string histogram = "Autofill.AddressProfileImportStatus";
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Verify that one profile was imported using the union of the two sections.
histogram_tester.ExpectBucketCount(
@@ -1051,14 +1056,15 @@ TEST_F(AutofillMetricsTest, ProfileImportRequirements_AllFulfilled) {
FormData form = test::GetFormData(
{.description_for_logging = "ProfileImportRequirements_AllFulfilled",
.fields = {
- {.role = ServerFieldType::NAME_FULL, .value = "Elvis Aaron Presley"},
+ {.role = ServerFieldType::NAME_FULL,
+ .value = u"Elvis Aaron Presley"},
{.role = ServerFieldType::ADDRESS_HOME_LINE1,
- .value = "3734 Elvis Presley Blvd."},
- {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = "New York"},
- {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = "2345678901"},
- {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = "CA"},
- {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = "37373"},
- {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = "USA"}}});
+ .value = u"3734 Elvis Presley Blvd."},
+ {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = u"New York"},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = u"2345678901"},
+ {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = u"CA"},
+ {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = u"37373"},
+ {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = u"USA"}}});
std::vector<ServerFieldType> heuristic_types = {
NAME_FULL, ADDRESS_HOME_LINE1,
@@ -1072,16 +1078,16 @@ TEST_F(AutofillMetricsTest, ProfileImportRequirements_AllFulfilled) {
ADDRESS_HOME_COUNTRY};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
std::vector<AddressProfileImportRequirementExpectations> expectations = {
{AddressImportRequirements::STATE_VALID_REQUIREMENT_FULFILLED, true},
@@ -1131,13 +1137,14 @@ TEST_F(AutofillMetricsTest, ProfileImportRequirements_MissingHomeLineOne) {
{.description_for_logging =
"ProfileImportRequirements_MissingHomeLineOne",
.fields = {
- {.role = ServerFieldType::NAME_FULL, .value = "Elvis Aaron Presley"},
- {.role = ServerFieldType::ADDRESS_HOME_LINE1, .value = ""},
- {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = "New York"},
- {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = "2345678901"},
- {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = "CA"},
- {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = "37373"},
- {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = "USA"}}});
+ {.role = ServerFieldType::NAME_FULL,
+ .value = u"Elvis Aaron Presley"},
+ {.role = ServerFieldType::ADDRESS_HOME_LINE1, .value = u""},
+ {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = u"New York"},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = u"2345678901"},
+ {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = u"CA"},
+ {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = u"37373"},
+ {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = u"USA"}}});
std::vector<ServerFieldType> heuristic_types = {
NAME_FULL, ADDRESS_HOME_LINE1,
@@ -1151,16 +1158,16 @@ TEST_F(AutofillMetricsTest, ProfileImportRequirements_MissingHomeLineOne) {
ADDRESS_HOME_COUNTRY};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
std::vector<AddressProfileImportRequirementExpectations> expectations = {
{AddressImportRequirements::STATE_VALID_REQUIREMENT_FULFILLED, true},
@@ -1212,15 +1219,16 @@ TEST_F(AutofillMetricsTest,
{.description_for_logging =
"ProfileImportRequirements_AllFulfilledForNonStateCountry",
.fields = {
- {.role = ServerFieldType::NAME_FULL, .value = "Elvis Aaron Presley"},
+ {.role = ServerFieldType::NAME_FULL,
+ .value = u"Elvis Aaron Presley"},
{.role = ServerFieldType::ADDRESS_HOME_LINE1,
- .value = "3734 Elvis Presley Blvd."},
- {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = "New York"},
- {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = "2345678901"},
- {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = ""},
- {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = "37373"},
+ .value = u"3734 Elvis Presley Blvd."},
+ {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = u"New York"},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = u"2345678901"},
+ {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = u""},
+ {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = u"37373"},
{.role = ServerFieldType::ADDRESS_HOME_COUNTRY,
- .value = "Germany"}}});
+ .value = u"Germany"}}});
std::vector<ServerFieldType> heuristic_types = {
NAME_FULL, ADDRESS_HOME_LINE1,
@@ -1234,16 +1242,16 @@ TEST_F(AutofillMetricsTest,
ADDRESS_HOME_COUNTRY};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
std::vector<AddressProfileImportRequirementExpectations> expectations = {
{AddressImportRequirements::STATE_VALID_REQUIREMENT_FULFILLED, true},
@@ -1293,17 +1301,18 @@ TEST_F(AutofillMetricsTest,
{.description_for_logging =
"ProfileImportRequirements_FilledButInvalidZipEmailAndState",
.fields = {
- {.role = ServerFieldType::NAME_FULL, .value = "Elvis Aaron Presley"},
+ {.role = ServerFieldType::NAME_FULL,
+ .value = u"Elvis Aaron Presley"},
{.role = ServerFieldType::ADDRESS_HOME_LINE1,
- .value = "3734 Elvis Presley Blvd."},
- {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = "New York"},
- {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = "2345678901"},
+ .value = u"3734 Elvis Presley Blvd."},
+ {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = u"New York"},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = u"2345678901"},
{.role = ServerFieldType::ADDRESS_HOME_STATE,
- .value = "DefNotAState"},
- {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = "1234567890"},
- {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = "USA"},
+ .value = u"DefNotAState"},
+ {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = u"1234567890"},
+ {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = u"USA"},
{.role = ServerFieldType::EMAIL_ADDRESS,
- .value = "test_noat_test.io"}}});
+ .value = u"test_noat_test.io"}}});
std::vector<ServerFieldType> heuristic_types = {NAME_FULL,
ADDRESS_HOME_LINE1,
@@ -1323,16 +1332,16 @@ TEST_F(AutofillMetricsTest,
EMAIL_ADDRESS};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
std::vector<AddressProfileImportRequirementExpectations> expectations = {
{AddressImportRequirements::STATE_VALID_REQUIREMENT_FULFILLED, false},
@@ -1381,19 +1390,20 @@ TEST_F(AutofillMetricsTest, ProfileImportRequirements_NonUniqueEmail) {
FormData form = test::GetFormData(
{.description_for_logging = "ProfileImportRequirements_NonUniqueEmail",
.fields = {
- {.role = ServerFieldType::NAME_FULL, .value = "Elvis Aaron Presley"},
+ {.role = ServerFieldType::NAME_FULL,
+ .value = u"Elvis Aaron Presley"},
{.role = ServerFieldType::ADDRESS_HOME_LINE1,
- .value = "3734 Elvis Presley Blvd."},
- {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = "New York"},
- {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = "2345678901"},
- {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = "CA"},
- {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = "37373"},
- {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = "USA"},
+ .value = u"3734 Elvis Presley Blvd."},
+ {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = u"New York"},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = u"2345678901"},
+ {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = u"CA"},
+ {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = u"37373"},
+ {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = u"USA"},
{.role = ServerFieldType::EMAIL_ADDRESS,
- .value = "test_noat_test.io"},
- {.label = "Email1",
- .name = ".email1",
- .value = "not_test@test.io"}}});
+ .value = u"test_noat_test.io"},
+ {.label = u"Email1",
+ .name = u".email1",
+ .value = u"not_test@test.io"}}});
std::vector<ServerFieldType> heuristic_types = {NAME_FULL,
ADDRESS_HOME_LINE1,
@@ -1415,16 +1425,16 @@ TEST_F(AutofillMetricsTest, ProfileImportRequirements_NonUniqueEmail) {
EMAIL_ADDRESS};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
std::vector<AddressProfileImportRequirementExpectations> expectations = {
{AddressImportRequirements::STATE_VALID_REQUIREMENT_FULFILLED, true},
@@ -1474,14 +1484,15 @@ TEST_F(AutofillMetricsTest, ProfileImportRequirements_OnlyAddressLineOne) {
{.description_for_logging =
"ProfileImportRequirements_OnlyAddressLineOne",
.fields = {
- {.role = ServerFieldType::NAME_FULL, .value = "Elvis Aaron Presley"},
+ {.role = ServerFieldType::NAME_FULL,
+ .value = u"Elvis Aaron Presley"},
{.role = ServerFieldType::ADDRESS_HOME_LINE1,
- .value = "3734 Elvis Presley Blvd."},
- {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = ""},
- {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = ""},
- {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = ""},
- {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = ""},
- {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = ""}}});
+ .value = u"3734 Elvis Presley Blvd."},
+ {.role = ServerFieldType::ADDRESS_HOME_CITY, .value = u""},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER, .value = u""},
+ {.role = ServerFieldType::ADDRESS_HOME_STATE, .value = u""},
+ {.role = ServerFieldType::ADDRESS_HOME_ZIP, .value = u""},
+ {.role = ServerFieldType::ADDRESS_HOME_COUNTRY, .value = u""}}});
std::vector<ServerFieldType> heuristic_types = {
NAME_FULL, ADDRESS_HOME_LINE1,
@@ -1495,16 +1506,16 @@ TEST_F(AutofillMetricsTest, ProfileImportRequirements_OnlyAddressLineOne) {
ADDRESS_HOME_COUNTRY};
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
std::vector<AddressProfileImportRequirementExpectations> expectations = {
{AddressImportRequirements::STATE_VALID_REQUIREMENT_FULFILLED, true},
@@ -1605,19 +1616,19 @@ TEST_F(AutofillMetricsTest,
base::UserActionTester user_action_tester;
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
// Trigger phone number rationalization at filling time.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
EXPECT_EQ(
1, user_action_tester.GetActionCount("Autofill_FilledProfileSuggestion"));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Rationalization quality.
{
@@ -1672,19 +1683,19 @@ TEST_F(AutofillMetricsTest,
base::UserActionTester user_action_tester;
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
// Trigger phone number rationalization at filling time.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
EXPECT_EQ(
1, user_action_tester.GetActionCount("Autofill_FilledProfileSuggestion"));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Rationalization quality.
{
@@ -1751,16 +1762,16 @@ TEST_F(AutofillMetricsTest, LogHiddenRepresentationalFieldSkipDecision) {
FormSignature form_signature = Collapse(CalculateFormSignature(form));
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate filling form.
{
base::UserActionTester user_action_tester;
std::string guid(kTestGuid); // local profile.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
}
VerifyUkm(
@@ -1897,8 +1908,8 @@ TEST_F(AutofillMetricsTest, LogRepeatedAddressTypeRationalized) {
field_types.push_back(UNKNOWN_TYPE);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
AutofillQueryResponse response;
auto* form_suggestion = response.add_form_suggestions();
@@ -1911,7 +1922,7 @@ TEST_F(AutofillMetricsTest, LogRepeatedAddressTypeRationalized) {
std::string response_string = SerializeAndEncode(response);
FormStructure::ParseApiQueryResponse(
response_string, forms, test::GetEncodedSignatures(forms),
- autofill_manager_->form_interactions_ukm_logger());
+ browser_autofill_manager_->form_interactions_ukm_logger());
ASSERT_EQ(test_ukm_recorder_
->GetEntriesByName(
@@ -2014,8 +2025,8 @@ TEST_F(AutofillMetricsTest, LogRepeatedStateCountryTypeRationalized) {
field_types.push_back(UNKNOWN_TYPE);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
AutofillQueryResponse response;
auto* form_suggestion = response.add_form_suggestions();
@@ -2030,7 +2041,7 @@ TEST_F(AutofillMetricsTest, LogRepeatedStateCountryTypeRationalized) {
std::string response_string = SerializeAndEncode(response);
FormStructure::ParseApiQueryResponse(
response_string, forms, test::GetEncodedSignatures(forms),
- autofill_manager_->form_interactions_ukm_logger());
+ browser_autofill_manager_->form_interactions_ukm_logger());
ASSERT_EQ(test_ukm_recorder_
->GetEntriesByName(
@@ -2147,19 +2158,19 @@ TEST_F(AutofillMetricsTest,
base::UserActionTester user_action_tester;
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
// Trigger phone number rationalization at filling time.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
EXPECT_EQ(
1, user_action_tester.GetActionCount("Autofill_FilledProfileSuggestion"));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Rationalization quality.
{
@@ -2230,19 +2241,19 @@ TEST_F(AutofillMetricsTest,
base::UserActionTester user_action_tester;
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
std::string guid(kTestGuid);
// Trigger phone number rationalization at filling time.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
EXPECT_EQ(
1, user_action_tester.GetActionCount("Autofill_FilledProfileSuggestion"));
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// Rationalization quality.
{
@@ -2528,12 +2539,12 @@ TEST_P(QualityMetricsTest, Classification) {
actual_types.push_back(actual_field_type);
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
// Run the form submission code while tracking the histograms.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
ExpectedUkmMetrics expected_ukm_metrics;
AppendFieldTypeUkm(form, heuristic_types, server_types, actual_types,
@@ -2689,7 +2700,7 @@ TEST_F(AutofillMetricsTest, TimingMetrics) {
// Simulate a OnFormsSeen() call that should trigger the recording.
std::vector<FormData> forms;
forms.push_back(form);
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
// Because these metrics are related to timing, it is not possible to know in
// advance which bucket the sample will fall into, so we just need to make
@@ -2755,16 +2766,16 @@ TEST_F(AutofillMetricsTest, QualityMetrics_NoSubmission) {
server_types.push_back(PHONE_HOME_CITY_AND_NUMBER);
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
// Simulate text input on one of the fields.
- autofill_manager_->OnTextFieldDidChange(form, form.fields[0], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[0],
+ gfx::RectF(), TimeTicks());
// Trigger a form upload and metrics by Resetting the manager.
base::HistogramTester histogram_tester;
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
// Heuristic predictions.
{
@@ -2931,7 +2942,7 @@ TEST_F(AutofillMetricsTest, QualityMetrics_BasedOnAutocomplete) {
TestFormStructure* form_structure_ptr = form_structure.get();
form_structure->DetermineHeuristicTypes(nullptr, nullptr);
ASSERT_TRUE(
- autofill_manager_->mutable_form_structures_for_test()
+ browser_autofill_manager_->mutable_form_structures_for_test()
->emplace(form_structure_ptr->global_id(), std::move(form_structure))
.second);
@@ -2948,7 +2959,7 @@ TEST_F(AutofillMetricsTest, QualityMetrics_BasedOnAutocomplete) {
std::string response_string = SerializeAndEncode(response);
base::HistogramTester histogram_tester;
- autofill_manager_->OnLoadedServerPredictionsForTest(
+ browser_autofill_manager_->OnLoadedServerPredictionsForTest(
response_string, test::GetEncodedSignatures(*form_structure_ptr));
// Verify that FormStructure::ParseApiQueryResponse was called (here and
@@ -3045,12 +3056,12 @@ TEST_F(AutofillMetricsTest, UpiVirtualPaymentAddress) {
server_types.push_back(ADDRESS_HOME_LINE1);
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.UserHappiness", AutofillMetrics::USER_DID_ENTER_UPI_VPA, 1);
@@ -3103,8 +3114,8 @@ TEST_F(AutofillMetricsTest, SaneMetricsWithCacheMismatch) {
server_types.push_back(UNKNOWN_TYPE);
// Simulate having seen this form with the desired heuristic and server types.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
// Add a field and re-arrange the remaining form fields before submitting.
std::vector<FormFieldData> cached_fields = form.fields;
@@ -3119,8 +3130,8 @@ TEST_F(AutofillMetricsTest, SaneMetricsWithCacheMismatch) {
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
for (const std::string source : {"Heuristic", "Server", "Overall"}) {
std::string aggregate_histogram =
@@ -3191,9 +3202,9 @@ TEST_F(AutofillMetricsTest, StoredProfileCountAutofillableFormSubmission) {
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// An autofillable form was submitted, and the number of stored profiles is
// logged.
@@ -3225,9 +3236,9 @@ TEST_F(AutofillMetricsTest, StoredProfileCountNonAutofillableFormSubmission) {
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// A non-autofillable form was submitted, and number of stored profiles is NOT
// logged.
@@ -3269,7 +3280,7 @@ TEST_F(AutofillMetricsTest, TypeOfEditedAutofilledFieldsUkmLogging) {
heuristic_types.push_back(PHONE_HOME_CITY_AND_NUMBER);
server_types.push_back(PHONE_HOME_CITY_AND_NUMBER);
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
// Verify that there are no counts before form submission.
@@ -3277,12 +3288,12 @@ TEST_F(AutofillMetricsTest, TypeOfEditedAutofilledFieldsUkmLogging) {
base::HistogramTester histogram_tester;
// Simulate text input in the first and second fields.
- autofill_manager_->OnTextFieldDidChange(form, form.fields[0], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[0],
+ gfx::RectF(), TimeTicks());
// Simulate form submission.
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
ExpectedUkmMetricsRecord name_field_ukm_record{
{UkmEditedAutofilledFieldAtSubmission::kFieldSignatureName,
Collapse(CalculateFieldSignatureForField(form.fields[0])).value()},
@@ -3330,18 +3341,18 @@ TEST_F(AutofillMetricsTest, TypeOfEditedAutofilledFieldsUmaLogging) {
heuristic_types.push_back(PHONE_HOME_CITY_AND_NUMBER);
server_types.push_back(PHONE_HOME_CITY_AND_NUMBER);
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
base::HistogramTester histogram_tester;
// Simulate text input in the first and second fields.
- autofill_manager_->OnTextFieldDidChange(form, form.fields[0], gfx::RectF(),
- TimeTicks());
- autofill_manager_->OnTextFieldDidChange(form, form.fields[1], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[0],
+ gfx::RectF(), TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[1],
+ gfx::RectF(), TimeTicks());
// Simulate form submission.
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// The |NAME_FULL| field was edited (bucket 112).
histogram_tester.ExpectBucketCount(
@@ -3410,18 +3421,18 @@ TEST_F(AutofillMetricsTest, NumberOfEditedAutofilledFields) {
heuristic_types.push_back(PHONE_HOME_CITY_AND_NUMBER);
server_types.push_back(PHONE_HOME_CITY_AND_NUMBER);
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
base::HistogramTester histogram_tester;
// Simulate text input in the first and second fields.
- autofill_manager_->OnTextFieldDidChange(form, form.fields[0], gfx::RectF(),
- TimeTicks());
- autofill_manager_->OnTextFieldDidChange(form, form.fields[1], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[0],
+ gfx::RectF(), TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[1],
+ gfx::RectF(), TimeTicks());
// Simulate form submission.
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
// An autofillable form was submitted, and the number of edited autofilled
// fields is logged.
@@ -3465,15 +3476,15 @@ TEST_F(AutofillMetricsTest, NumberOfEditedAutofilledFields_NoSubmission) {
heuristic_types.push_back(PHONE_HOME_CITY_AND_NUMBER);
server_types.push_back(PHONE_HOME_CITY_AND_NUMBER);
- autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
+ browser_autofill_manager_->AddSeenForm(form, heuristic_types, server_types);
base::HistogramTester histogram_tester;
// Simulate text input in the first field.
- autofill_manager_->OnTextFieldDidChange(form, form.fields[0], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[0],
+ gfx::RectF(), TimeTicks());
// We expect metrics to be logged when the manager is reset.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
// An autofillable form was uploaded, and the number of edited autofilled
// fields is logged.
@@ -3504,8 +3515,8 @@ TEST_F(AutofillMetricsTest, DeveloperEngagement) {
// number of fields enforced).
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->Reset();
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->Reset();
histogram_tester.ExpectTotalCount("Autofill.DeveloperEngagement", 0);
}
@@ -3516,8 +3527,8 @@ TEST_F(AutofillMetricsTest, DeveloperEngagement) {
// Expect the "form parsed without hints" metric to be logged.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->Reset();
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->Reset();
histogram_tester.ExpectUniqueSample(
"Autofill.DeveloperEngagement",
AutofillMetrics::FILLABLE_FORM_PARSED_WITHOUT_TYPE_HINTS, 1);
@@ -3541,8 +3552,8 @@ TEST_F(AutofillMetricsTest, DeveloperEngagement) {
// Expect the "form parsed with field type hints" metric to be logged.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->Reset();
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->Reset();
histogram_tester.ExpectBucketCount(
"Autofill.DeveloperEngagement",
AutofillMetrics::FILLABLE_FORM_PARSED_WITH_TYPE_HINTS, 1);
@@ -3561,8 +3572,8 @@ TEST_F(AutofillMetricsTest, DeveloperEngagement) {
// "author-specified upi-vpa type" metric to be logged.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->Reset();
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->Reset();
histogram_tester.ExpectBucketCount(
"Autofill.DeveloperEngagement",
AutofillMetrics::FILLABLE_FORM_PARSED_WITH_TYPE_HINTS, 1);
@@ -3595,8 +3606,8 @@ TEST_F(AutofillMetricsTest,
// Ensure no entries are logged when loading a non-fillable form.
{
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->Reset();
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->Reset();
EXPECT_EQ(0ul, test_ukm_recorder_->entries_count());
}
@@ -3608,8 +3619,8 @@ TEST_F(AutofillMetricsTest,
// Expect the "form parsed without field type hints" metric and the
// "form loaded" form interaction event to be logged.
{
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->Reset();
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->Reset();
VerifyDeveloperEngagementUkm(
test_ukm_recorder_, forms.back(), /*is_for_credit_card=*/false,
@@ -3660,8 +3671,8 @@ TEST_F(AutofillMetricsTest,
// Expect the "form parsed without field type hints" metric and the
// "form loaded" form interaction event to be logged.
{
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->Reset();
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->Reset();
VerifyDeveloperEngagementUkm(
test_ukm_recorder_, forms.back(), /*is_for_credit_card=*/false,
@@ -3697,7 +3708,7 @@ TEST_F(AutofillMetricsTest, UkmDeveloperEngagement_LogUpiVpaTypeHint) {
{
SCOPED_TRACE("VPA and other autocomplete hint present");
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
VerifyDeveloperEngagementUkm(
test_ukm_recorder_, forms.back(), /*is_for_credit_card=*/false,
@@ -3926,6 +3937,7 @@ TEST_F(AutofillMetricsTest, AutofillProfileIsEnabledAtStartup) {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
histogram_tester.ExpectUniqueSample("Autofill.Address.IsEnabled.Startup",
true, 1);
@@ -3942,6 +3954,7 @@ TEST_F(AutofillMetricsTest, AutofillProfileIsDisabledAtStartup) {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
histogram_tester.ExpectUniqueSample("Autofill.Address.IsEnabled.Startup",
false, 1);
@@ -3958,6 +3971,7 @@ TEST_F(AutofillMetricsTest, AutofillCreditCardIsEnabledAtStartup) {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
histogram_tester.ExpectUniqueSample("Autofill.CreditCard.IsEnabled.Startup",
true, 1);
@@ -3974,6 +3988,7 @@ TEST_F(AutofillMetricsTest, AutofillCreditCardIsDisabledAtStartup) {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
histogram_tester.ExpectUniqueSample("Autofill.CreditCard.IsEnabled.Startup",
false, 1);
@@ -4003,13 +4018,13 @@ TEST_F(AutofillMetricsTest, AddressSuggestionsCount) {
field_types.push_back(PHONE_HOME_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulate activating the autofill popup for the phone field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample("Autofill.AddressSuggestionsCount", 2,
1);
@@ -4020,33 +4035,33 @@ TEST_F(AutofillMetricsTest, AddressSuggestionsCount) {
// No new metric should be logged, since we're still on the same page.
test::CreateTestFormField("Email", "email", "b", "email", &field);
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectTotalCount("Autofill.AddressSuggestionsCount", 0);
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulate activating the autofill popup for the email field after typing.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample("Autofill.AddressSuggestionsCount", 1,
1);
}
// Reset the autofill manager state again.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulate activating the autofill popup for the email field after a fill.
form.fields[0].is_autofilled = true;
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectTotalCount("Autofill.AddressSuggestionsCount", 1);
}
@@ -4077,13 +4092,13 @@ TEST_F(AutofillMetricsTest, CompanyNameSuggestions) {
field_types.push_back(COMPANY_NAME);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulate activating the autofill popup for the phone field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample("Autofill.AddressSuggestionsCount", 2,
@@ -4119,13 +4134,13 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
field_types.push_back(CREDIT_CARD_EXP_MONTH);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate an Autofill query on a credit card field.
{
base::UserActionTester user_action_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_PolledCreditCardSuggestions"));
@@ -4134,8 +4149,8 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
// Simulate showing a credit card suggestion polled from "Name on card" field.
{
base::UserActionTester user_action_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_ShowedCreditCardSuggestions"));
}
@@ -4144,8 +4159,8 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
// field.
{
base::UserActionTester user_action_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[1]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[1]);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_ShowedCreditCardSuggestions"));
}
@@ -4156,7 +4171,8 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
std::string guid("10000000-0000-0000-0000-000000000001"); // local card
external_delegate_->OnQuery(0, form, form.fields.front(), gfx::RectF());
external_delegate_->DidAcceptSuggestion(
- u"Test", autofill_manager_->MakeFrontendIDForTest(guid, std::string()),
+ u"Test",
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()),
0);
EXPECT_EQ(1,
user_action_tester.GetActionCount("Autofill_SelectedSuggestion"));
@@ -4166,8 +4182,8 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
// field along with a "Clear form" footer suggestion.
{
base::UserActionTester user_action_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[1]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[1]);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_ShowedCreditCardSuggestions"));
}
@@ -4186,8 +4202,8 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
// field, this time to submit the form.
{
base::UserActionTester user_action_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[1]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[1]);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_ShowedCreditCardSuggestions"));
}
@@ -4198,7 +4214,8 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
std::string guid("10000000-0000-0000-0000-000000000001"); // local card
external_delegate_->OnQuery(0, form, form.fields.front(), gfx::RectF());
external_delegate_->DidAcceptSuggestion(
- u"Test", autofill_manager_->MakeFrontendIDForTest(guid, std::string()),
+ u"Test",
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()),
0);
EXPECT_EQ(1,
user_action_tester.GetActionCount("Autofill_SelectedSuggestion"));
@@ -4208,9 +4225,9 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
{
base::UserActionTester user_action_tester;
std::string guid("10000000-0000-0000-0000-000000000001"); // local card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_FilledCreditCardSuggestion"));
}
@@ -4218,10 +4235,10 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
// Simulate submitting the credit card form.
{
base::UserActionTester user_action_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
EXPECT_EQ(1,
user_action_tester.GetActionCount("Autofill_OnWillSubmitForm"));
EXPECT_EQ(1, user_action_tester.GetActionCount(
@@ -4254,7 +4271,7 @@ TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) {
// Expect 3 |FORM_EVENT_LOCAL_SUGGESTION_FILLED| events. First, from
// call to |external_delegate_->DidAcceptSuggestion|. Second and third, from
- // ExpectedUkmMetrics |autofill_manager_->FillOrPreviewForm|.
+ // ExpectedUkmMetrics |browser_autofill_manager_->FillOrPreviewForm|.
ExpectedUkmMetricsRecord from_did_accept_suggestion{
{UkmSuggestionFilledType::kRecordTypeName, CreditCard::LOCAL_CARD},
{UkmSuggestionFilledType::kMillisecondsSinceFormParsedName, 0},
@@ -4300,7 +4317,7 @@ TEST_F(AutofillMetricsTest, UpiVpaUkmTest) {
std::vector<FormData> forms(1, form);
{
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
VerifySubmitFormUkm(test_ukm_recorder_, forms.back(),
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
@@ -4339,13 +4356,13 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate an Autofill query on a profile field.
{
base::UserActionTester user_action_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_PolledProfileSuggestions"));
@@ -4354,8 +4371,8 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
// Simulate showing a profile suggestion polled from "State" field.
{
base::UserActionTester user_action_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_ShowedProfileSuggestions"));
}
@@ -4363,8 +4380,8 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
// Simulate showing a profile suggestion polled from "City" field.
{
base::UserActionTester user_action_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[1]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[1]);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_ShowedProfileSuggestions"));
}
@@ -4375,7 +4392,8 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
std::string guid(kTestGuid); // local profile.
external_delegate_->OnQuery(0, form, form.fields.front(), gfx::RectF());
external_delegate_->DidAcceptSuggestion(
- u"Test", autofill_manager_->MakeFrontendIDForTest(std::string(), guid),
+ u"Test",
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid),
0);
EXPECT_EQ(1,
user_action_tester.GetActionCount("Autofill_SelectedSuggestion"));
@@ -4385,9 +4403,9 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
{
base::UserActionTester user_action_tester;
std::string guid(kTestGuid); // local profile.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_FilledProfileSuggestion"));
}
@@ -4395,10 +4413,10 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
// Simulate submitting the profile form.
{
base::UserActionTester user_action_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
EXPECT_EQ(1,
user_action_tester.GetActionCount("Autofill_OnWillSubmitForm"));
EXPECT_EQ(1, user_action_tester.GetActionCount(
@@ -4425,7 +4443,7 @@ TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) {
Collapse(CalculateFormSignature(form)).value()}}});
// Expect 2 |FORM_EVENT_LOCAL_SUGGESTION_FILLED| events. First, from
// call to |external_delegate_->DidAcceptSuggestion|. Second, from call to
- // |autofill_manager_->FillOrPreviewForm|.
+ // |browser_autofill_manager_->FillOrPreviewForm|.
VerifyUkm(test_ukm_recorder_, form, UkmSuggestionFilledType::kEntryName,
{{{UkmSuggestionFilledType::kRecordTypeName,
AutofillProfile::LOCAL_PROFILE},
@@ -4480,12 +4498,12 @@ TEST_F(AutofillMetricsTest, PolledCreditCardSuggestions_DebounceLogs) {
field_types.push_back(CREDIT_CARD_EXP_MONTH);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate an Autofill query on a credit card field. A poll should be logged.
base::UserActionTester user_action_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, form.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
EXPECT_EQ(1, user_action_tester.GetActionCount(
@@ -4493,14 +4511,14 @@ TEST_F(AutofillMetricsTest, PolledCreditCardSuggestions_DebounceLogs) {
// Simulate a second query on the same field. There should still only be one
// logged poll.
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, form.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_PolledCreditCardSuggestions"));
// Simulate a query to another field. There should be a second poll logged.
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, form.fields[1], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
EXPECT_EQ(2, user_action_tester.GetActionCount(
@@ -4508,7 +4526,7 @@ TEST_F(AutofillMetricsTest, PolledCreditCardSuggestions_DebounceLogs) {
// Simulate a query back to the initial field. There should be a third poll
// logged.
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, form.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
EXPECT_EQ(3, user_action_tester.GetActionCount(
@@ -4560,12 +4578,12 @@ TEST_F(AutofillMetricsTest, QueriedCreditCardFormIsSecure) {
client_form_origin.ReplaceComponents(replacements));
form.main_frame_origin =
url::Origin::Create(autofill_client_.form_origin());
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate an Autofill query on a credit card field (HTTP, non-secure
// form).
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, form.fields[1], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample(
@@ -4576,18 +4594,18 @@ TEST_F(AutofillMetricsTest, QueriedCreditCardFormIsSecure) {
{
// Simulate having seen this secure form on page load.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
form.host_frame = test::GetLocalFrameToken();
form.unique_renderer_id = test::MakeFormRendererId();
form.url = GURL("https://example.com/form.html");
form.action = GURL("https://example.com/submit.html");
form.main_frame_origin =
url::Origin::Create(autofill_client_.form_origin());
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate an Autofill query on a credit card field (HTTPS form).
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, form.fields[1], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample(
@@ -4622,12 +4640,12 @@ TEST_F(AutofillMetricsTest, PolledProfileSuggestions_DebounceLogs) {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate an Autofill query on a profile field. A poll should be logged.
base::UserActionTester user_action_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, form.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
EXPECT_EQ(1, user_action_tester.GetActionCount(
@@ -4635,14 +4653,14 @@ TEST_F(AutofillMetricsTest, PolledProfileSuggestions_DebounceLogs) {
// Simulate a second query on the same field. There should still only be poll
// logged.
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, form.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_PolledProfileSuggestions"));
// Simulate a query to another field. There should be a second poll logged.
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, form.fields[1], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
EXPECT_EQ(2, user_action_tester.GetActionCount(
@@ -4650,7 +4668,7 @@ TEST_F(AutofillMetricsTest, PolledProfileSuggestions_DebounceLogs) {
// Simulate a query back to the initial field. There should be a third poll
// logged.
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, form.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
EXPECT_EQ(3, user_action_tester.GetActionCount(
@@ -4685,7 +4703,7 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardParsedFormEvents) {
forms.push_back(form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
histogram_tester.ExpectUniqueSample(
"Autofill.FormEvents.CreditCard.WithNoData", FORM_EVENT_DID_PARSE_FORM,
1);
@@ -4715,13 +4733,13 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardInteractedFormEvents) {
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulate activating the autofill popup for the credit card field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample("Autofill.FormEvents.CreditCard",
FORM_EVENT_INTERACTED_ONCE, 1);
@@ -4731,15 +4749,15 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardInteractedFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulate activating the autofill popup for the credit card field twice.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
1, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample("Autofill.FormEvents.CreditCard",
FORM_EVENT_INTERACTED_ONCE, 1);
@@ -4773,13 +4791,13 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardPopupSuppressedFormEvents) {
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating popup being suppressed.
base::HistogramTester histogram_tester;
- autofill_manager_->DidSuppressPopup(form, field);
+ browser_autofill_manager_->DidSuppressPopup(form, field);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_POPUP_SUPPRESSED, 1);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
@@ -4790,14 +4808,14 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardPopupSuppressedFormEvents) {
FORM_EVENT_POPUP_SUPPRESSED_ONCE, 1);
}
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating popup being suppressed.
base::HistogramTester histogram_tester;
- autofill_manager_->DidSuppressPopup(form, field);
- autofill_manager_->DidSuppressPopup(form, field);
+ browser_autofill_manager_->DidSuppressPopup(form, field);
+ browser_autofill_manager_->DidSuppressPopup(form, field);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_POPUP_SUPPRESSED, 2);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
@@ -4833,13 +4851,14 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardShownFormEvents) {
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating new popup being shown.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_,
@@ -4851,14 +4870,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardShownFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating two popups in the same page load.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTIONS_SHOWN, 2);
histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_,
@@ -4870,14 +4891,14 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardShownFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating same popup being refreshed.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(false /* is_new_popup */, form,
- field);
+ browser_autofill_manager_->DidShowSuggestions(false /* is_new_popup */,
+ form, field);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTIONS_SHOWN, 0);
histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_,
@@ -4917,17 +4938,17 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSelectedFormEvents) {
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating selecting a masked card server suggestion.
base::HistogramTester histogram_tester;
std::string guid(
"10000000-0000-0000-0000-000000000002"); // masked server card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields[2],
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 1);
@@ -4943,20 +4964,20 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSelectedFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating selecting multiple times a masked card server.
base::HistogramTester histogram_tester;
std::string guid(
"10000000-0000-0000-0000-000000000002"); // masked server card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields[2],
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields[2],
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 2);
@@ -5000,16 +5021,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) {
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating filling a local card suggestion.
base::HistogramTester histogram_tester;
std::string guid("10000000-0000-0000-0000-000000000001"); // local card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1);
histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_,
@@ -5023,20 +5044,20 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating filling a masked card server suggestion.
base::HistogramTester histogram_tester;
std::string guid(
"10000000-0000-0000-0000-000000000002"); // masked server card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::SUCCESS, "6011000990139424");
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1);
@@ -5058,17 +5079,17 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) {
true /* include_full_server_credit_card */);
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating filling a full card server suggestion.
base::HistogramTester histogram_tester;
std::string guid(
"10000000-0000-0000-0000-000000000003"); // full server card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_SERVER_SUGGESTION_FILLED, 1);
histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_,
@@ -5082,19 +5103,19 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardFilledFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating filling multiple times.
base::HistogramTester histogram_tester;
std::string guid("10000000-0000-0000-0000-000000000001"); // local card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_LOCAL_SUGGESTION_FILLED, 2);
histogram_tester.ExpectBucketCount(credit_card_form_events_frame_histogram_,
@@ -5126,8 +5147,8 @@ TEST_F(AutofillMetricsTest, CreditCardUnmaskingPreflightCall) {
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Create local cards and set user as eligible for FIDO authentication.
@@ -5136,8 +5157,8 @@ TEST_F(AutofillMetricsTest, CreditCardUnmaskingPreflightCall) {
false /* include_masked_server_credit_card */,
false /* include_full_server_credit_card */);
SetFidoEligibility(true);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
// If no masked server cards are available, then no preflight call is made.
histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
@@ -5151,8 +5172,8 @@ TEST_F(AutofillMetricsTest, CreditCardUnmaskingPreflightCall) {
true /* include_masked_server_credit_card */,
false /* include_full_server_credit_card */);
SetFidoEligibility(false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
// If user is not verifiable, then no preflight call is made.
histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
@@ -5166,8 +5187,8 @@ TEST_F(AutofillMetricsTest, CreditCardUnmaskingPreflightCall) {
false /* include_masked_server_credit_card */,
true /* include_full_server_credit_card */);
SetFidoEligibility(false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
// If no masked server cards are available, then no preflight call is made.
histogram_tester.ExpectTotalCount(preflight_call_metric, 0);
histogram_tester.ExpectTotalCount(preflight_latency_metric, 0);
@@ -5181,13 +5202,13 @@ TEST_F(AutofillMetricsTest, CreditCardUnmaskingPreflightCall) {
true /* include_masked_server_credit_card */,
false /* include_full_server_credit_card */);
SetFidoEligibility(true);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
std::string guid(
"10000000-0000-0000-0000-000000000002"); // masked server card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
// Preflight call is made only if a masked server card is available and the
// user is eligible for FIDO authentication (except iOS).
#if defined(OS_IOS)
@@ -5207,13 +5228,13 @@ TEST_F(AutofillMetricsTest, CreditCardUnmaskingPreflightCall) {
true /* include_masked_server_credit_card */,
true /* include_full_server_credit_card */);
SetFidoEligibility(true);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
std::string guid(
"10000000-0000-0000-0000-000000000002"); // masked server card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
// Preflight call is made only if a masked server card is available and the
// user is eligible for FIDO authentication (except iOS).
#if defined(OS_IOS)
@@ -5254,17 +5275,17 @@ TEST_F(AutofillMetricsTest, CreditCardGetRealPanDuration) {
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating filling a masked card server suggestion.
base::HistogramTester histogram_tester;
// Masked server card.
std::string guid("10000000-0000-0000-0000-000000000002");
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::SUCCESS, "6011000990139424");
histogram_tester.ExpectTotalCount(
"Autofill.UnmaskPrompt.GetRealPanDuration", 1);
@@ -5273,8 +5294,8 @@ TEST_F(AutofillMetricsTest, CreditCardGetRealPanDuration) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Creating masked card
RecreateCreditCards(false /* include_local_credit_card */,
true /* include_masked_server_credit_card */,
@@ -5285,9 +5306,9 @@ TEST_F(AutofillMetricsTest, CreditCardGetRealPanDuration) {
base::HistogramTester histogram_tester;
// Masked server card.
std::string guid("10000000-0000-0000-0000-000000000002");
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::PERMANENT_FAILURE, std::string());
histogram_tester.ExpectTotalCount(
"Autofill.UnmaskPrompt.GetRealPanDuration", 1);
@@ -5325,16 +5346,17 @@ TEST_F(AutofillMetricsTest,
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulating submission with suggestion shown, but not selected.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, 1);
@@ -5368,16 +5390,17 @@ TEST_P(AutofillMetricsIFrameTest,
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulating submission with suggestion shown, but not selected.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_WRONG_SIZE_CARD, 1);
@@ -5415,16 +5438,17 @@ TEST_P(AutofillMetricsIFrameTest,
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulating submission with suggestion shown, but not selected.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_FAIL_LUHN_CHECK_CARD, 1);
@@ -5463,16 +5487,17 @@ TEST_P(AutofillMetricsIFrameTest,
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulating submission with suggestion shown, but not selected.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_UNKNOWN_CARD, 1);
@@ -5511,16 +5536,17 @@ TEST_P(AutofillMetricsIFrameTest,
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulating submission with suggestion shown, but not selected.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 1);
@@ -5559,21 +5585,22 @@ TEST_P(AutofillMetricsIFrameTest,
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulating submission with suggestion shown and selected.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
std::string guid("10000000-0000-0000-0000-000000000001");
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_KNOWN_CARD, 0);
@@ -5619,16 +5646,17 @@ TEST_F(AutofillMetricsTest, ShouldNotLogFormEventNoCardForAddressForm) {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulating submission with no filled data.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_SUBMIT_WITHOUT_SELECTING_SUGGESTIONS_NO_CARD, 0);
@@ -5662,16 +5690,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with no filled data.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
@@ -5696,16 +5724,17 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
// Reset the autofill manager state and purge UKM logs.
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with suggestion shown.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1);
@@ -5740,20 +5769,21 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
// Reset the autofill manager state and purge UKM logs.
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with suggestion shown. Form is submmitted and
// autofill manager is reset before UploadFormDataAsyncCallback is
// triggered.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
// Trigger UploadFormDataAsyncCallback.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 1);
@@ -5788,19 +5818,19 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
// Reset the autofill manager state and purge UKM logs.
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with filled local data.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
std::string guid("10000000-0000-0000-0000-000000000001"); // local card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -5834,20 +5864,20 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
// Reset the autofill manager state and purge UKM logs.
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with filled server data.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
std::string guid(
"10000000-0000-0000-0000-000000000003"); // full server card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -5881,19 +5911,19 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
// Reset the autofill manager state and purge UKM logs.
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with a masked card server suggestion.
base::HistogramTester histogram_tester;
std::string guid(
"10000000-0000-0000-0000-000000000002"); // masked server card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::SUCCESS, "6011000990139424");
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_FILLED, 1);
@@ -5934,16 +5964,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
true /* include_full_server_credit_card */);
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating multiple submissions.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
VerifySubmitFormUkm(test_ukm_recorder_, form,
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA,
@@ -5951,8 +5981,8 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
/* has_upi_vpa_field=*/false,
{FormType::kCreditCardForm});
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
VerifyUkm(
test_ukm_recorder_, form, UkmFormSubmittedType::kEntryName,
@@ -6040,15 +6070,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardSubmittedFormEvents) {
// Reset the autofill manager state and purge UKM logs.
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with suggestion shown but without previous
// interaction.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
@@ -6158,16 +6189,16 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with no filled data.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -6183,17 +6214,18 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with suggestion shown.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
@@ -6209,20 +6241,20 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with filled local data.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
std::string guid("10000000-0000-0000-0000-000000000001"); // local card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -6238,21 +6270,21 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with filled server data.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
// Full server card.
std::string guid("10000000-0000-0000-0000-000000000003");
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SERVER_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -6268,17 +6300,17 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with a masked card server suggestion.
base::HistogramTester histogram_tester;
// Masked server card.
std::string guid("10000000-0000-0000-0000-000000000002");
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::SUCCESS, "6011000990139424");
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
@@ -6301,18 +6333,18 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
true /* include_full_server_credit_card */);
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating multiple submissions.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -6376,16 +6408,17 @@ TEST_P(AutofillMetricsIFrameTest, CreditCardWillSubmitFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with suggestion shown but without previous
// interaction.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, 0);
@@ -6479,19 +6512,20 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
true /* include_full_server_credit_card */);
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating activating the autofill popup for the credit card field, new
// popup being shown and filling a local card suggestion.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
std::string guid("10000000-0000-0000-0000-000000000001"); // local card
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
@@ -6523,8 +6557,8 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
AddMaskedServerCreditCardWithOffer(guid, "$4", autofill_client_.form_origin(),
/*id=*/0x4fff);
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// A masked server card with linked offers.
@@ -6533,16 +6567,17 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
// submitting the form. Verify that all related form events are correctly
// logged to offer sub-histogram.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
// Select the masked server card with the linked offer.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::SUCCESS, "6011000990139424");
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard.WithOffer",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -6578,8 +6613,8 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// A masked server card with linked offers.
@@ -6588,18 +6623,19 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
// submitting the form. Verify that all related form events are correctly
// logged to offer sub-histogram.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
// Select another card, and still log to offer
// sub-histogram because user has another masked server card with offer.
guid = "10000000-0000-0000-0000-000000000002";
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::SUCCESS, "6011000990139424");
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard.WithOffer",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -6643,24 +6679,25 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
/*id=*/0x3fff, /*expired=*/true);
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating activating the autofill popup for the credit card field,
// new popup being shown and filling a local card suggestion.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
// Select the card with linked offer, though metrics should not record it
// since the offer is expired.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::SUCCESS, "6011000990139424");
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
// Histograms without ".WithOffer" should be recorded.
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -6711,8 +6748,8 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
/*id=*/0x5fff);
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// A masked server card with linked offers.
@@ -6723,22 +6760,24 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
// sub-histogram. Making suggestions reappear tests confirmation of a fix
// for crbug/1198751.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
// Select the masked server card with the linked offer.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::SUCCESS, "6011000990139424");
// Simulate user showing suggestions but then submitting form with
// previously filled card info.
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard.WithOffer",
FORM_EVENT_SUGGESTIONS_SHOWN, 2);
@@ -6768,14 +6807,14 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
// Should track card was selected and form was submitted with that card.
histogram_tester.ExpectBucketCount("Autofill.Offer.SelectedCardHasOffer",
- true, 1);
+ /*selected=*/true, 1);
histogram_tester.ExpectUniqueSample("Autofill.Offer.SubmittedCardHasOffer",
- true, 1);
+ /*submitted=*/true, 1);
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// A masked server card with linked offers.
@@ -6784,19 +6823,20 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
// failing the CVC check and submitting the form anyways. Verify that all
// related form events are correctly logged to offer sub-histogram.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
// Select the masked server card with the linked offer, but fail the CVC
// check.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::PERMANENT_FAILURE, std::string());
// Submitting the form without the filled suggestion.
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard.WithOffer",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -6826,14 +6866,14 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
// Should track card was selected once, but not submitted.
histogram_tester.ExpectUniqueSample("Autofill.Offer.SelectedCardHasOffer",
- true, 1);
+ /*selected=*/true, 1);
histogram_tester.ExpectBucketCount("Autofill.Offer.SubmittedCardHasOffer",
- true, 0);
+ /*submitted=*/true, 0);
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// A masked server card with linked offers.
@@ -6844,24 +6884,26 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
base::HistogramTester histogram_tester;
// Show suggestions and select the card with offer.
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
OnDidGetRealPan(AutofillClient::SUCCESS, "6011000990139424");
// Show suggestions again, and select a local card instead.
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
guid = "10000000-0000-0000-0000-000000000001";
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.back(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.CreditCard.WithOffer",
FORM_EVENT_SUGGESTIONS_SHOWN, 2);
@@ -6890,11 +6932,11 @@ TEST_F(AutofillMetricsTest, LogServerOfferFormEvents) {
// Should track card was only selected once.
histogram_tester.ExpectBucketCount("Autofill.Offer.SelectedCardHasOffer",
- true, 1);
+ /*selected=*/true, 1);
histogram_tester.ExpectBucketCount("Autofill.Offer.SelectedCardHasOffer",
- false, 1);
+ /*selected=*/false, 1);
histogram_tester.ExpectUniqueSample("Autofill.Offer.SubmittedCardHasOffer",
- false, 1);
+ /*submitted=*/false, 1);
}
}
@@ -6935,7 +6977,7 @@ TEST_F(AutofillMetricsTest, MixedParsedFormEvents) {
forms.push_back(form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
histogram_tester.ExpectUniqueSample("Autofill.FormEvents.Address.WithNoData",
FORM_EVENT_DID_PARSE_FORM, 1);
histogram_tester.ExpectUniqueSample(
@@ -6971,7 +7013,7 @@ TEST_F(AutofillMetricsTest, AddressParsedFormEvents) {
forms.push_back(form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
histogram_tester.ExpectUniqueSample("Autofill.FormEvents.Address.WithNoData",
FORM_EVENT_DID_PARSE_FORM, 1);
@@ -7011,13 +7053,13 @@ TEST_F(AutofillMetricsTest, AddressInteractedFormEvents) {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulate activating the autofill popup for the street field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample("Autofill.FormEvents.Address",
FORM_EVENT_INTERACTED_ONCE, 1);
@@ -7036,16 +7078,16 @@ TEST_F(AutofillMetricsTest, AddressInteractedFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulate activating the autofill popup for the street field twice.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
1, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample("Autofill.FormEvents.Address",
FORM_EVENT_INTERACTED_ONCE, 1);
@@ -7089,13 +7131,13 @@ TEST_F(AutofillMetricsTest, AddressSuppressedFormEvents) {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating new popup being shown.
base::HistogramTester histogram_tester;
- autofill_manager_->DidSuppressPopup(form, field);
+ browser_autofill_manager_->DidSuppressPopup(form, field);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_POPUP_SUPPRESSED, 1);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
@@ -7120,15 +7162,15 @@ TEST_F(AutofillMetricsTest, AddressSuppressedFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating two popups in the same page load.
base::HistogramTester histogram_tester;
- autofill_manager_->DidSuppressPopup(form, field);
- autofill_manager_->DidSuppressPopup(form, field);
+ browser_autofill_manager_->DidSuppressPopup(form, field);
+ browser_autofill_manager_->DidSuppressPopup(form, field);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_POPUP_SUPPRESSED, 2);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
@@ -7184,13 +7226,14 @@ TEST_F(AutofillMetricsTest, AddressShownFormEvents) {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating new popup being shown.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
@@ -7214,15 +7257,17 @@ TEST_F(AutofillMetricsTest, AddressShownFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating two popups in the same page load.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_SUGGESTIONS_SHOWN, 2);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
@@ -7251,15 +7296,15 @@ TEST_F(AutofillMetricsTest, AddressShownFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating same popup being refreshed.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(false /* is_new_popup */, form,
- field);
+ browser_autofill_manager_->DidShowSuggestions(false /* is_new_popup */,
+ form, field);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_SUGGESTIONS_SHOWN, 0);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
@@ -7297,16 +7342,16 @@ TEST_F(AutofillMetricsTest, AddressFilledFormEvents) {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating selecting/filling a local profile suggestion.
base::HistogramTester histogram_tester;
std::string guid(kTestGuid); // local profile
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_LOCAL_SUGGESTION_FILLED, 1);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
@@ -7331,20 +7376,20 @@ TEST_F(AutofillMetricsTest, AddressFilledFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating selecting/filling a local profile suggestion more than once.
base::HistogramTester histogram_tester;
std::string guid(kTestGuid); // local profile
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_LOCAL_SUGGESTION_FILLED, 2);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
@@ -7354,16 +7399,16 @@ TEST_F(AutofillMetricsTest, AddressFilledFormEvents) {
// Create a server profile and reset the autofill manager state.
RecreateProfile(/*is_server=*/true);
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulate selecting/filling a server profile suggestion.
base::HistogramTester histogram_tester;
std::string guid(kTestGuid); // server profile
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_SERVER_SUGGESTION_FILLED, 1);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
@@ -7371,19 +7416,19 @@ TEST_F(AutofillMetricsTest, AddressFilledFormEvents) {
1);
}
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulate selecting/filling a server profile suggestion more than once.
base::HistogramTester histogram_tester;
std::string guid(kTestGuid); // server profile
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_SERVER_SUGGESTION_FILLED, 2);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
@@ -7418,16 +7463,16 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with no filled data.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -7444,19 +7489,19 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
// Reset the autofill manager state and purge UKM logs.
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with no filled data. Form is submmitted and
// autofill manager is reset before UploadFormDataAsyncCallback is
// triggered.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
// Trigger UploadFormDataAsyncCallback.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -7473,16 +7518,17 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
// Reset the autofill manager state and purge UKM logs.
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with suggestion shown.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
@@ -7492,21 +7538,21 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with filled local data.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
std::string guid(kTestGuid); // local profile
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -7516,18 +7562,18 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating multiple submissions.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -7556,17 +7602,18 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with suggestion show but without previous
// interaction.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
@@ -7632,16 +7679,16 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with no filled data.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -7651,18 +7698,19 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with suggestion shown.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 1);
@@ -7672,21 +7720,21 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with filled local data.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
std::string guid(kTestGuid); // local profile
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_LOCAL_SUGGESTION_WILL_SUBMIT_ONCE, 1);
@@ -7696,19 +7744,19 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating multiple submissions.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
@@ -7746,17 +7794,18 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
{
// Simulating submission with suggestion shown but without previous
// interaction.
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form, field);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ field);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address",
FORM_EVENT_SUGGESTION_SHOWN_WILL_SUBMIT_ONCE, 0);
@@ -7810,10 +7859,10 @@ TEST_F(AutofillMetricsTest, RecordStandalonePhoneField) {
test::CreateTestFormField("Phone", "phone", "", "tel", &field);
form.fields.push_back(field);
field_types.push_back(PHONE_HOME_NUMBER);
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.PhoneOnly",
FORM_EVENT_INTERACTED_ONCE, 1);
@@ -7843,8 +7892,8 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
field_types.push_back(CREDIT_CARD_NUMBER);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
RecreateCreditCards(false /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
false /* include_full_server_credit_card */);
@@ -7852,7 +7901,7 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
{
// Simulate activating the autofill popup for the credit card field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample(
"Autofill.FormEvents.CreditCard.WithNoData", FORM_EVENT_INTERACTED_ONCE,
@@ -7860,9 +7909,9 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
RecreateCreditCards(true /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
false /* include_full_server_credit_card */);
@@ -7870,7 +7919,7 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
{
// Simulate activating the autofill popup for the credit card field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample(
"Autofill.FormEvents.CreditCard.WithOnlyLocalData",
@@ -7878,9 +7927,9 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
RecreateCreditCards(false /* include_local_credit_card */,
true /* include_masked_server_credit_card */,
false /* include_full_server_credit_card */);
@@ -7888,7 +7937,7 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
{
// Simulate activating the autofill popup for the credit card field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample(
"Autofill.FormEvents.CreditCard.WithOnlyServerData",
@@ -7896,9 +7945,9 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
RecreateCreditCards(false /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
true /* include_full_server_credit_card */);
@@ -7906,7 +7955,7 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
{
// Simulate activating the autofill popup for the credit card field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample(
"Autofill.FormEvents.CreditCard.WithOnlyServerData",
@@ -7914,9 +7963,9 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
PurgeUKM();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
RecreateCreditCards(true /* include_local_credit_card */,
false /* include_masked_server_credit_card */,
true /* include_full_server_credit_card */);
@@ -7924,7 +7973,7 @@ TEST_F(AutofillMetricsTest, CreditCardFormEventsAreSegmented) {
{
// Simulate activating the autofill popup for the credit card field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample(
"Autofill.FormEvents.CreditCard.WithBothServerAndLocalData",
@@ -7956,14 +8005,14 @@ TEST_F(AutofillMetricsTest, AddressFormEventsAreSegmented) {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
personal_data_->ClearProfiles();
{
// Simulate activating the autofill popup for the street field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample(
"Autofill.FormEvents.Address.WithNoData", FORM_EVENT_INTERACTED_ONCE,
@@ -7971,14 +8020,14 @@ TEST_F(AutofillMetricsTest, AddressFormEventsAreSegmented) {
}
// Reset the autofill manager state.
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
RecreateProfile(/*is_server=*/false);
{
// Simulate activating the autofill popup for the street field.
base::HistogramTester histogram_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
histogram_tester.ExpectUniqueSample(
"Autofill.FormEvents.Address.WithOnlyLocalData",
@@ -7989,8 +8038,8 @@ TEST_F(AutofillMetricsTest, AddressFormEventsAreSegmented) {
// Test that we log that Profile Autofill is enabled when filling a form.
TEST_F(AutofillMetricsTest, AutofillProfileIsEnabledAtPageLoad) {
base::HistogramTester histogram_tester;
- autofill_manager_->SetAutofillProfileEnabled(true);
- autofill_manager_->OnFormsSeen(std::vector<FormData>());
+ browser_autofill_manager_->SetAutofillProfileEnabled(true);
+ browser_autofill_manager_->OnFormsSeen(std::vector<FormData>());
histogram_tester.ExpectUniqueSample("Autofill.Address.IsEnabled.PageLoad",
true, 1);
}
@@ -7998,8 +8047,8 @@ TEST_F(AutofillMetricsTest, AutofillProfileIsEnabledAtPageLoad) {
// Test that we log that Profile Autofill is disabled when filling a form.
TEST_F(AutofillMetricsTest, AutofillProfileIsDisabledAtPageLoad) {
base::HistogramTester histogram_tester;
- autofill_manager_->SetAutofillProfileEnabled(false);
- autofill_manager_->OnFormsSeen(std::vector<FormData>());
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
+ browser_autofill_manager_->OnFormsSeen(std::vector<FormData>());
histogram_tester.ExpectUniqueSample("Autofill.Address.IsEnabled.PageLoad",
false, 1);
}
@@ -8007,8 +8056,8 @@ TEST_F(AutofillMetricsTest, AutofillProfileIsDisabledAtPageLoad) {
// Test that we log that CreditCard Autofill is enabled when filling a form.
TEST_F(AutofillMetricsTest, AutofillCreditCardIsEnabledAtPageLoad) {
base::HistogramTester histogram_tester;
- autofill_manager_->SetAutofillCreditCardEnabled(true);
- autofill_manager_->OnFormsSeen(std::vector<FormData>());
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(true);
+ browser_autofill_manager_->OnFormsSeen(std::vector<FormData>());
histogram_tester.ExpectUniqueSample("Autofill.CreditCard.IsEnabled.PageLoad",
true, 1);
}
@@ -8016,8 +8065,8 @@ TEST_F(AutofillMetricsTest, AutofillCreditCardIsEnabledAtPageLoad) {
// Test that we log that CreditCard Autofill is disabled when filling a form.
TEST_F(AutofillMetricsTest, AutofillCreditCardIsDisabledAtPageLoad) {
base::HistogramTester histogram_tester;
- autofill_manager_->SetAutofillCreditCardEnabled(false);
- autofill_manager_->OnFormsSeen(std::vector<FormData>());
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->OnFormsSeen(std::vector<FormData>());
histogram_tester.ExpectUniqueSample("Autofill.CreditCard.IsEnabled.PageLoad",
false, 1);
}
@@ -8043,6 +8092,95 @@ TEST_F(AutofillMetricsTest, DaysSinceLastUse_Profile) {
1);
}
+// Test that we log the verification status of name tokens.
+TEST_F(AutofillMetricsTest, LogVerificationStatusesOfNameTokens) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillEnableSupportForMoreStructureInNames);
+
+ base::HistogramTester histogram_tester;
+ AutofillProfile profile;
+ profile.SetRawInfoWithVerificationStatus(
+ NAME_FULL, u"First Last",
+ structured_address::VerificationStatus::kObserved);
+ profile.SetRawInfoWithVerificationStatus(
+ NAME_FIRST, u"First", structured_address::VerificationStatus::kParsed);
+ profile.SetRawInfoWithVerificationStatus(
+ NAME_LAST, u"Last", structured_address::VerificationStatus::kParsed);
+ profile.SetRawInfoWithVerificationStatus(
+ NAME_LAST_SECOND, u"Last",
+ structured_address::VerificationStatus::kParsed);
+
+ AutofillMetrics::LogVerificationStatusOfNameTokensOnProfileUsage(profile);
+
+ std::string base_histo =
+ "Autofill.NameTokenVerificationStatusAtProfileUsage.";
+
+ histogram_tester.ExpectUniqueSample(
+ base_histo + "Full", structured_address::VerificationStatus::kObserved,
+ 1);
+ histogram_tester.ExpectUniqueSample(
+ base_histo + "First", structured_address::VerificationStatus::kParsed, 1);
+ histogram_tester.ExpectUniqueSample(
+ base_histo + "Last", structured_address::VerificationStatus::kParsed, 1);
+ histogram_tester.ExpectUniqueSample(
+ base_histo + "SecondLast",
+ structured_address::VerificationStatus::kParsed, 1);
+
+ histogram_tester.ExpectTotalCount(base_histo + "Middle", 0);
+ histogram_tester.ExpectTotalCount(base_histo + "FirstLast", 0);
+
+ histogram_tester.ExpectTotalCount(base_histo + "Any", 4);
+ histogram_tester.ExpectBucketCount(
+ base_histo + "Any", structured_address::VerificationStatus::kObserved, 1);
+ histogram_tester.ExpectBucketCount(
+ base_histo + "Any", structured_address::VerificationStatus::kParsed, 3);
+}
+
+// Test that we log the verification status of address tokens..
+TEST_F(AutofillMetricsTest, LogVerificationStatusesOfAddressTokens) {
+ scoped_feature_list_.InitAndEnableFeature(
+ features::kAutofillEnableSupportForMoreStructureInAddresses);
+
+ base::HistogramTester histogram_tester;
+ AutofillProfile profile;
+ profile.SetRawInfoWithVerificationStatus(
+ ADDRESS_HOME_STREET_ADDRESS, u"123 StreetName",
+ structured_address::VerificationStatus::kFormatted);
+ profile.SetRawInfoWithVerificationStatus(
+ ADDRESS_HOME_HOUSE_NUMBER, u"123",
+ structured_address::VerificationStatus::kObserved);
+ profile.SetRawInfoWithVerificationStatus(
+ ADDRESS_HOME_STREET_NAME, u"StreetName",
+ structured_address::VerificationStatus::kObserved);
+
+ AutofillMetrics::LogVerificationStatusOfAddressTokensOnProfileUsage(profile);
+
+ std::string base_histo =
+ "Autofill.AddressTokenVerificationStatusAtProfileUsage.";
+
+ histogram_tester.ExpectUniqueSample(
+ base_histo + "StreetAddress",
+ structured_address::VerificationStatus::kFormatted, 1);
+ histogram_tester.ExpectUniqueSample(
+ base_histo + "StreetName",
+ structured_address::VerificationStatus::kObserved, 1);
+ histogram_tester.ExpectUniqueSample(
+ base_histo + "HouseNumber",
+ structured_address::VerificationStatus::kObserved, 1);
+
+ histogram_tester.ExpectTotalCount(base_histo + "FloorNumber", 0);
+ histogram_tester.ExpectTotalCount(base_histo + "ApartmentNumber", 0);
+ histogram_tester.ExpectTotalCount(base_histo + "Premise", 0);
+ histogram_tester.ExpectTotalCount(base_histo + "SubPremise", 0);
+
+ histogram_tester.ExpectTotalCount(base_histo + "Any", 3);
+ histogram_tester.ExpectBucketCount(
+ base_histo + "Any", structured_address::VerificationStatus::kFormatted,
+ 1);
+ histogram_tester.ExpectBucketCount(
+ base_histo + "Any", structured_address::VerificationStatus::kObserved, 2);
+}
+
// Verify that we correctly log the submitted form's state.
TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
// Start with a form with insufficiently many fields.
@@ -8068,7 +8206,7 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
// Expect no notifications when the form is first seen.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
histogram_tester.ExpectTotalCount("Autofill.FormSubmittedState", 0);
VerifyDeveloperEngagementUkm(
@@ -8084,8 +8222,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, 1);
@@ -8119,8 +8257,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::NON_FILLABLE_FORM_OR_NEW_DATA, 1);
@@ -8156,8 +8294,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_NONE_DID_NOT_SHOW_SUGGESTIONS,
@@ -8187,12 +8325,12 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
}
// Autofilled none with suggestions shown.
- autofill_manager_->DidShowSuggestions(true, form, form.fields[2]);
+ browser_autofill_manager_->DidShowSuggestions(true, form, form.fields[2]);
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_NONE_DID_SHOW_SUGGESTIONS, 1);
@@ -8239,8 +8377,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_SOME, 1);
@@ -8275,8 +8413,8 @@ TEST_F(AutofillMetricsTest, AutofillFormSubmittedState) {
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL, 1);
@@ -8338,7 +8476,7 @@ TEST_F(
{
base::HistogramTester histogram_tester;
base::UserActionTester user_action_tester;
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
VerifyDeveloperEngagementUkm(
test_ukm_recorder_, form, /*is_for_credit_card=*/false,
{FormType::kAddressForm},
@@ -8352,8 +8490,8 @@ TEST_F(
form.fields[2].value = u"12345678901";
form.fields[2].is_autofilled = true;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FormSubmittedState",
AutofillMetrics::FILLABLE_FORM_AUTOFILLED_ALL, 1);
@@ -8462,7 +8600,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_EmptyForm) {
// Expect a notification when the form is first seen.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
histogram_tester.ExpectTotalCount("Autofill.UserHappiness", 0);
histogram_tester.ExpectTotalCount("Autofill.UserHappiness.CreditCard", 0);
histogram_tester.ExpectTotalCount("Autofill.UserHappiness.Address", 0);
@@ -8504,7 +8642,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_CreditCardForm) {
{
SCOPED_TRACE("First seen");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::FORMS_LOADED, 1);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.CreditCard",
@@ -8515,23 +8653,23 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_CreditCardForm) {
{
SCOPED_TRACE("Initial typing");
base::HistogramTester histogram_tester;
- autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
- gfx::RectF(), TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
+ gfx::RectF(), TimeTicks());
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::USER_DID_TYPE, 1);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.CreditCard",
AutofillMetrics::USER_DID_TYPE, 1);
}
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate suggestions shown twice with separate popups.
{
SCOPED_TRACE("Separate pop-ups");
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true, form, field);
- autofill_manager_->DidShowSuggestions(true, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true, form, field);
histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
AutofillMetrics::SUGGESTIONS_SHOWN, 2);
histogram_tester.ExpectBucketCount(
@@ -8543,16 +8681,16 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_CreditCardForm) {
1);
}
- autofill_manager_->Reset();
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate suggestions shown twice for a single edit (i.e. multiple
// keystrokes in a single field).
{
SCOPED_TRACE("Multiple keystrokes");
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true, form, field);
- autofill_manager_->DidShowSuggestions(false, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true, form, field);
+ browser_autofill_manager_->DidShowSuggestions(false, form, field);
histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
AutofillMetrics::SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount(
@@ -8568,7 +8706,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_CreditCardForm) {
{
SCOPED_TRACE("Different field");
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true, form, form.fields[1]);
+ browser_autofill_manager_->DidShowSuggestions(true, form, form.fields[1]);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.CreditCard",
@@ -8579,7 +8717,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_CreditCardForm) {
{
SCOPED_TRACE("Invoke autofill");
base::HistogramTester histogram_tester;
- autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
+ browser_autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
AutofillMetrics::USER_DID_AUTOFILL, 1);
histogram_tester.ExpectBucketCount(
@@ -8596,14 +8734,14 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_CreditCardForm) {
SCOPED_TRACE("Edit autofilled field");
base::HistogramTester histogram_tester;
std::string guid("10000000-0000-0000-0000-000000000001");
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
- autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
- gfx::RectF(), TimeTicks());
+ browser_autofill_manager_->MakeFrontendIDForTest(guid, std::string()));
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
+ gfx::RectF(), TimeTicks());
// Simulate a second keystroke; make sure we don't log the metric twice.
- autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
- gfx::RectF(), TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
+ gfx::RectF(), TimeTicks());
histogram_tester.ExpectBucketCount(
"Autofill.UserHappiness",
AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
@@ -8622,7 +8760,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_CreditCardForm) {
{
SCOPED_TRACE("Invoke autofill again");
base::HistogramTester histogram_tester;
- autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
+ browser_autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::USER_DID_AUTOFILL, 1);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.CreditCard",
@@ -8633,8 +8771,8 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_CreditCardForm) {
{
SCOPED_TRACE("Edit another autofilled field");
base::HistogramTester histogram_tester;
- autofill_manager_->OnTextFieldDidChange(form, form.fields[1], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[1],
+ gfx::RectF(), TimeTicks());
histogram_tester.ExpectUniqueSample(
"Autofill.UserHappiness",
AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
@@ -8669,7 +8807,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
// Expect a notification when the form is first seen.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::FORMS_LOADED, 1);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.Address",
@@ -8679,8 +8817,8 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
// Simulate typing.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
- gfx::RectF(), TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
+ gfx::RectF(), TimeTicks());
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::USER_DID_TYPE, 1);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.Address",
@@ -8690,8 +8828,8 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
// Simulate suggestions shown twice with separate popups.
{
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true, form, field);
- autofill_manager_->DidShowSuggestions(true, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true, form, field);
histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
AutofillMetrics::SUGGESTIONS_SHOWN, 2);
histogram_tester.ExpectBucketCount(
@@ -8703,14 +8841,14 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
1);
}
- autofill_manager_->Reset();
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->Reset();
+ browser_autofill_manager_->OnFormsSeen(forms);
// Simulate suggestions shown twice for a single edit (i.e. multiple
// keystrokes in a single field).
{
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true, form, field);
- autofill_manager_->DidShowSuggestions(false, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true, form, field);
+ browser_autofill_manager_->DidShowSuggestions(false, form, field);
histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
AutofillMetrics::SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount(
@@ -8725,7 +8863,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
// Simulate suggestions shown for a different field.
{
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(true, form, form.fields[1]);
+ browser_autofill_manager_->DidShowSuggestions(true, form, form.fields[1]);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.Address",
@@ -8735,7 +8873,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
// Simulate invoking autofill.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
+ browser_autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
AutofillMetrics::USER_DID_AUTOFILL, 1);
histogram_tester.ExpectBucketCount(
@@ -8751,14 +8889,14 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
{
base::HistogramTester histogram_tester;
std::string guid(kTestGuid);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
- autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
- gfx::RectF(), TimeTicks());
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
+ gfx::RectF(), TimeTicks());
// Simulate a second keystroke; make sure we don't log the metric twice.
- autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
- gfx::RectF(), TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields.front(),
+ gfx::RectF(), TimeTicks());
histogram_tester.ExpectBucketCount(
"Autofill.UserHappiness",
AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
@@ -8776,7 +8914,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
// Simulate invoking autofill again.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
+ browser_autofill_manager_->OnDidFillAutofillFormData(form, TimeTicks());
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness",
AutofillMetrics::USER_DID_AUTOFILL, 1);
histogram_tester.ExpectUniqueSample("Autofill.UserHappiness.Address",
@@ -8786,8 +8924,8 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
// Simulate editing another autofilled field.
{
base::HistogramTester histogram_tester;
- autofill_manager_->OnTextFieldDidChange(form, form.fields[1], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[1],
+ gfx::RectF(), TimeTicks());
histogram_tester.ExpectUniqueSample(
"Autofill.UserHappiness",
AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
@@ -8796,7 +8934,7 @@ TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_AddressForm) {
AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD, 1);
}
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
VerifyUkm(test_ukm_recorder_, form, UkmInteractedWithFormType::kEntryName,
{{{UkmInteractedWithFormType::kIsForCreditCardName, false},
@@ -8950,13 +9088,13 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
{
SCOPED_TRACE("Test 1");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- base::TimeTicks parse_time = autofill_manager_->form_structures()
+ browser_autofill_manager_->OnFormsSeen(forms);
+ base::TimeTicks parse_time = browser_autofill_manager_->form_structures()
.begin()
->second->form_parsed_timestamp();
test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectTotalCount(
"Autofill.FillDuration.FromLoad.WithAutofill", 0);
@@ -8967,23 +9105,23 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
histogram_tester.ExpectTotalCount(
"Autofill.FillDuration.FromInteraction.WithoutAutofill", 0);
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
}
// Expect metric to be logged if the user manually edited a form field.
{
SCOPED_TRACE("Test 2");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- base::TimeTicks parse_time = autofill_manager_->form_structures()
+ browser_autofill_manager_->OnFormsSeen(forms);
+ base::TimeTicks parse_time = browser_autofill_manager_->form_structures()
.begin()
->second->form_parsed_timestamp();
- autofill_manager_->OnTextFieldDidChange(
+ browser_autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(),
parse_time + base::TimeDelta::FromMicroseconds(3));
test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectTotalCount(
"Autofill.FillDuration.FromLoad.WithAutofill", 0);
@@ -8995,7 +9133,7 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
"Autofill.FillDuration.FromInteraction.WithoutAutofill", 14, 1);
// We expected an upload to be triggered when the manager is reset.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
}
// Expect metric to be logged if the user autofilled the form.
@@ -9003,15 +9141,15 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
{
SCOPED_TRACE("Test 3");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- base::TimeTicks parse_time = autofill_manager_->form_structures()
+ browser_autofill_manager_->OnFormsSeen(forms);
+ base::TimeTicks parse_time = browser_autofill_manager_->form_structures()
.begin()
->second->form_parsed_timestamp();
- autofill_manager_->OnDidFillAutofillFormData(
+ browser_autofill_manager_->OnDidFillAutofillFormData(
form, parse_time + base::TimeDelta::FromMicroseconds(5));
test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FillDuration.FromLoad.WithAutofill", 16, 1);
@@ -9023,7 +9161,7 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
"Autofill.FillDuration.FromInteraction.WithoutAutofill", 0);
// We expected an upload to be triggered when the manager is reset.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
}
// Expect metric to be logged if the user both manually filled some fields
@@ -9033,19 +9171,19 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
SCOPED_TRACE("Test 4");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- base::TimeTicks parse_time = autofill_manager_->form_structures()
+ browser_autofill_manager_->OnFormsSeen(forms);
+ base::TimeTicks parse_time = browser_autofill_manager_->form_structures()
.begin()
->second->form_parsed_timestamp();
- autofill_manager_->OnDidFillAutofillFormData(
+ browser_autofill_manager_->OnDidFillAutofillFormData(
form, parse_time + base::TimeDelta::FromMicroseconds(5));
- autofill_manager_->OnTextFieldDidChange(
+ browser_autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(),
parse_time + base::TimeDelta::FromMicroseconds(3));
test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FillDuration.FromLoad.WithAutofill", 16, 1);
@@ -9057,7 +9195,7 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
"Autofill.FillDuration.FromInteraction.WithoutAutofill", 0);
// We expected an upload to be triggered when the manager is reset.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
}
// Make sure that loading another form doesn't affect metrics from the first
@@ -9065,19 +9203,19 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
{
SCOPED_TRACE("Test 5");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- base::TimeTicks parse_time = autofill_manager_->form_structures()
+ browser_autofill_manager_->OnFormsSeen(forms);
+ base::TimeTicks parse_time = browser_autofill_manager_->form_structures()
.begin()
->second->form_parsed_timestamp();
- autofill_manager_->OnFormsSeen(second_forms);
- autofill_manager_->OnDidFillAutofillFormData(
+ browser_autofill_manager_->OnFormsSeen(second_forms);
+ browser_autofill_manager_->OnDidFillAutofillFormData(
form, parse_time + base::TimeDelta::FromMicroseconds(5));
- autofill_manager_->OnTextFieldDidChange(
+ browser_autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(),
parse_time + base::TimeDelta::FromMicroseconds(3));
test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.FillDuration.FromLoad.WithAutofill", 16, 1);
@@ -9089,7 +9227,7 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
"Autofill.FillDuration.FromInteraction.WithoutAutofill", 0);
// We expected an upload to be triggered when the manager is reset.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
}
// Make sure that submitting a form that was loaded later will report the
@@ -9097,16 +9235,16 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
{
SCOPED_TRACE("Test 6");
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->OnFormsSeen(second_forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(second_forms);
base::TimeTicks parse_time{};
- for (const auto& kv : autofill_manager_->form_structures()) {
+ for (const auto& kv : browser_autofill_manager_->form_structures()) {
if (kv.second->form_parsed_timestamp() > parse_time)
parse_time = kv.second->form_parsed_timestamp();
}
test_clock.SetNowTicks(parse_time + base::TimeDelta::FromMicroseconds(17));
- autofill_manager_->OnFormSubmitted(second_form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ second_form, false, SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectTotalCount(
"Autofill.FillDuration.FromLoad.WithAutofill", 0);
@@ -9117,7 +9255,7 @@ TEST_F(AutofillMetricsTest, FormFillDuration) {
histogram_tester.ExpectTotalCount(
"Autofill.FillDuration.FromInteraction.WithoutAutofill", 0);
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
}
}
@@ -9407,9 +9545,9 @@ TEST_F(AutofillMetricsTest, ProfileActionOnFormSubmitted) {
// Expect to log NEW_PROFILE_CREATED for the metric since a new profile is
// submitted.
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
AutofillMetrics::NEW_PROFILE_CREATED, 1);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -9420,9 +9558,9 @@ TEST_F(AutofillMetricsTest, ProfileActionOnFormSubmitted) {
// Expect to log EXISTING_PROFILE_USED for the metric since the same profile
// is submitted.
- autofill_manager_->OnFormsSeen(second_forms);
- autofill_manager_->OnFormSubmitted(second_form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormsSeen(second_forms);
+ browser_autofill_manager_->OnFormSubmitted(second_form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
AutofillMetrics::NEW_PROFILE_CREATED, 1);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -9433,9 +9571,9 @@ TEST_F(AutofillMetricsTest, ProfileActionOnFormSubmitted) {
// Expect to log NEW_PROFILE_CREATED for the metric since a new profile is
// submitted.
- autofill_manager_->OnFormsSeen(third_forms);
- autofill_manager_->OnFormSubmitted(third_form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormsSeen(third_forms);
+ browser_autofill_manager_->OnFormSubmitted(third_form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
AutofillMetrics::NEW_PROFILE_CREATED, 2);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -9446,9 +9584,9 @@ TEST_F(AutofillMetricsTest, ProfileActionOnFormSubmitted) {
// Expect to log EXISTING_PROFILE_UPDATED for the metric since the profile was
// updated.
- autofill_manager_->OnFormsSeen(fourth_forms);
- autofill_manager_->OnFormSubmitted(fourth_form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormsSeen(fourth_forms);
+ browser_autofill_manager_->OnFormSubmitted(fourth_form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
AutofillMetrics::NEW_PROFILE_CREATED, 2);
histogram_tester.ExpectBucketCount("Autofill.ProfileActionOnFormSubmitted",
@@ -9640,13 +9778,13 @@ TEST_F(AutofillMetricsTest, NonsecureCreditCardForm) {
field_types.push_back(CREDIT_CARD_EXP_MONTH);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate an Autofill query on a credit card field.
{
base::UserActionTester user_action_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_PolledCreditCardSuggestions"));
@@ -9655,8 +9793,8 @@ TEST_F(AutofillMetricsTest, NonsecureCreditCardForm) {
// Simulate submitting the credit card form.
{
base::HistogramTester histograms;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histograms.ExpectBucketCount(
"Autofill.FormEvents.CreditCard.OnNonsecurePage",
FORM_EVENT_NO_SUGGESTION_SUBMITTED_ONCE, 1);
@@ -9701,13 +9839,13 @@ TEST_F(AutofillMetricsTest,
field_types.push_back(CREDIT_CARD_EXP_MONTH);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ // |form_structure| will be owned by |browser_autofill_manager_|.
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate an Autofill query on a credit card field.
{
base::UserActionTester user_action_tester;
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form, field, gfx::RectF(), /*autoselect_first_suggestion=*/false);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Autofill_PolledCreditCardSuggestions"));
@@ -9716,8 +9854,8 @@ TEST_F(AutofillMetricsTest,
// Simulate submitting the credit card form.
{
base::HistogramTester histograms;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
histograms.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_NO_SUGGESTION_WILL_SUBMIT_ONCE, 1);
histograms.ExpectBucketCount("Autofill.FormEvents.CreditCard",
@@ -9824,11 +9962,11 @@ TEST_F(AutofillMetricsTest, DISABLED_AutofillSuggestionShownTest) {
test::CreateTestFormField("Month", "card_month", "", "text", &field);
form.fields.push_back(field);
field_types.push_back(CREDIT_CARD_EXP_MONTH);
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
// Simulate and Autofill query on credit card name field.
- autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(true /* is_new_popup */, form,
+ form.fields[0]);
VerifyUkm(
test_ukm_recorder_, form, UkmSuggestionsShownType::kEntryName,
{{{UkmSuggestionsShownType::kMillisecondsSinceFormParsedName, 0},
@@ -9863,23 +10001,23 @@ TEST_F(AutofillMetricsTest, DynamicFormMetrics) {
// Simulate seeing.
base::HistogramTester histogram_tester;
- autofill_manager_->AddSeenForm(form, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form, field_types, field_types);
std::string guid(kTestGuid);
// Simulate checking whether to fill a dynamic form before the form was filled
// initially.
FormStructure form_structure(form);
- autofill_manager_->ShouldTriggerRefillForTest(form_structure);
+ browser_autofill_manager_->ShouldTriggerRefillForTest(form_structure);
histogram_tester.ExpectTotalCount("Autofill.FormEvents.Address", 0);
// Simulate filling the form.
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form, form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(), guid));
// Simulate checking whether to fill a dynamic form after the form was filled
// initially.
- autofill_manager_->ShouldTriggerRefillForTest(form_structure);
+ browser_autofill_manager_->ShouldTriggerRefillForTest(form_structure);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM,
1);
@@ -9889,7 +10027,7 @@ TEST_F(AutofillMetricsTest, DynamicFormMetrics) {
FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, 0);
// Trigger a refill, the refill metric should be updated.
- autofill_manager_->TriggerRefillForTest(form);
+ browser_autofill_manager_->TriggerRefillForTest(form);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM,
1);
@@ -9899,7 +10037,7 @@ TEST_F(AutofillMetricsTest, DynamicFormMetrics) {
FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL, 0);
// Trigger a check to see whether a refill should happen. The
- autofill_manager_->ShouldTriggerRefillForTest(form_structure);
+ browser_autofill_manager_->ShouldTriggerRefillForTest(form_structure);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM,
2);
@@ -9991,7 +10129,7 @@ TEST_F(AutofillMetricsTest, LogUserHappinessBySecurityLevel_FromFormEvents) {
base::HistogramTester histogram_tester;
autofill_client_.set_security_level(
security_state::SecurityLevel::DANGEROUS);
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
histogram_tester.ExpectBucketCount(
"Autofill.UserHappiness.Address.DANGEROUS",
AutofillMetrics::FORMS_LOADED, 1);
@@ -10001,8 +10139,8 @@ TEST_F(AutofillMetricsTest, LogUserHappinessBySecurityLevel_FromFormEvents) {
{
base::HistogramTester histogram_tester;
autofill_client_.set_security_level(security_state::SecurityLevel::WARNING);
- autofill_manager_->DidShowSuggestions(true, form, field);
- autofill_manager_->DidShowSuggestions(true, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true, form, field);
+ browser_autofill_manager_->DidShowSuggestions(true, form, field);
histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address.WARNING",
AutofillMetrics::SUGGESTIONS_SHOWN, 2);
histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address.WARNING",
@@ -10265,7 +10403,7 @@ TEST_F(AutofillMetricsTest,
// frame has no form.
TEST_F(AutofillMetricsTest, FrameHasNoForm) {
base::HistogramTester histogram_tester;
- autofill_manager_.reset();
+ browser_autofill_manager_.reset();
histogram_tester.ExpectTotalCount(
"Autofill.WebOTP.OneTimeCode.FromAutocomplete", 0);
}
@@ -10292,8 +10430,8 @@ TEST_F(AutofillMetricsTest, FrameHasAutocompleteOneTimeCode) {
forms_with_one_time_code.back().fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms_with_one_time_code);
- autofill_manager_.reset();
+ browser_autofill_manager_->OnFormsSeen(forms_with_one_time_code);
+ browser_autofill_manager_.reset();
// Verifies that autocomplete="one-time-code" in a form is correctly recorded.
histogram_tester.ExpectBucketCount(
"Autofill.WebOTP.OneTimeCode.FromAutocomplete",
@@ -10321,8 +10459,8 @@ TEST_F(AutofillMetricsTest, FrameDoesNotHaveAutocompleteOneTimeCode) {
forms_without_one_time_code.back().fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms_without_one_time_code);
- autofill_manager_.reset();
+ browser_autofill_manager_->OnFormsSeen(forms_without_one_time_code);
+ browser_autofill_manager_.reset();
histogram_tester.ExpectBucketCount(
"Autofill.WebOTP.OneTimeCode.FromAutocomplete",
/* has_one_time_code */ 0,
@@ -10356,8 +10494,8 @@ TEST_F(AutofillMetricsTest, FrameHasPhoneNumberFieldWithoutAutocomplete) {
forms_with_phone_number.back().fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms_with_phone_number);
- autofill_manager_.reset();
+ browser_autofill_manager_->OnFormsSeen(forms_with_phone_number);
+ browser_autofill_manager_.reset();
histogram_tester.ExpectBucketCount(
"Autofill.WebOTP.PhoneNumberCollection.ParseResult",
/* has_phone_number_field */ 1,
@@ -10386,8 +10524,8 @@ TEST_F(AutofillMetricsTest, FrameHasSinglePhoneNumberFieldWithoutAutocomplete) {
forms_with_single_phone_number_field.back().fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms_with_single_phone_number_field);
- autofill_manager_.reset();
+ browser_autofill_manager_->OnFormsSeen(forms_with_single_phone_number_field);
+ browser_autofill_manager_.reset();
histogram_tester.ExpectBucketCount(
"Autofill.WebOTP.PhoneNumberCollection.ParseResult",
/* has_phone_number_field */ 0,
@@ -10405,8 +10543,8 @@ TEST_F(AutofillMetricsTest, FrameHasPhoneNumberFieldWithAutocomplete) {
std::vector<FormData> forms_with_phone_number(1, form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms_with_phone_number);
- autofill_manager_.reset();
+ browser_autofill_manager_->OnFormsSeen(forms_with_phone_number);
+ browser_autofill_manager_.reset();
histogram_tester.ExpectBucketCount(
"Autofill.WebOTP.PhoneNumberCollection.ParseResult",
/* has_phone_number_field */ 1,
@@ -10433,8 +10571,8 @@ TEST_F(AutofillMetricsTest, FrameDoesNotHavePhoneNumberField) {
forms_without_phone_number.back().fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms_without_phone_number);
- autofill_manager_.reset();
+ browser_autofill_manager_->OnFormsSeen(forms_without_phone_number);
+ browser_autofill_manager_.reset();
histogram_tester.ExpectBucketCount(
"Autofill.WebOTP.PhoneNumberCollection.ParseResult",
/* has_phone_number_field */ 0,
@@ -10454,8 +10592,9 @@ TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStateNone) {
std::vector<FormData> forms(1, form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+ browser_autofill_manager_->OnFormsSeen(forms);
+ autofill_driver_->SetBrowserAutofillManager(
+ std::move(browser_autofill_manager_));
static_cast<ContentAutofillDriver*>(autofill_driver_.get())
->ReportAutofillWebOTPMetrics(false);
histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
@@ -10472,8 +10611,9 @@ TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStateOTC) {
std::vector<FormData> forms(1, form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+ browser_autofill_manager_->OnFormsSeen(forms);
+ autofill_driver_->SetBrowserAutofillManager(
+ std::move(browser_autofill_manager_));
static_cast<ContentAutofillDriver*>(autofill_driver_.get())
->ReportAutofillWebOTPMetrics(false);
histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
@@ -10487,7 +10627,8 @@ TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStateWebOTP) {
// If WebOTP is used, even if there is no form on the page we still need to
// report it.
base::HistogramTester histogram_tester;
- autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+ autofill_driver_->SetBrowserAutofillManager(
+ std::move(browser_autofill_manager_));
static_cast<ContentAutofillDriver*>(autofill_driver_.get())
->ReportAutofillWebOTPMetrics(true);
histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
@@ -10504,8 +10645,9 @@ TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStateWebOTPPlusOTC) {
std::vector<FormData> forms(1, form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+ browser_autofill_manager_->OnFormsSeen(forms);
+ autofill_driver_->SetBrowserAutofillManager(
+ std::move(browser_autofill_manager_));
static_cast<ContentAutofillDriver*>(autofill_driver_.get())
->ReportAutofillWebOTPMetrics(true);
histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
@@ -10523,8 +10665,9 @@ TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStatePhone) {
std::vector<FormData> forms(1, form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+ browser_autofill_manager_->OnFormsSeen(forms);
+ autofill_driver_->SetBrowserAutofillManager(
+ std::move(browser_autofill_manager_));
static_cast<ContentAutofillDriver*>(autofill_driver_.get())
->ReportAutofillWebOTPMetrics(false);
histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
@@ -10542,8 +10685,9 @@ TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStatePhonePlusOTC) {
std::vector<FormData> forms(1, form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+ browser_autofill_manager_->OnFormsSeen(forms);
+ autofill_driver_->SetBrowserAutofillManager(
+ std::move(browser_autofill_manager_));
static_cast<ContentAutofillDriver*>(autofill_driver_.get())
->ReportAutofillWebOTPMetrics(false);
histogram_tester.ExpectBucketCount("Autofill.WebOTP.PhonePlusWebOTPPlusOTC",
@@ -10561,8 +10705,9 @@ TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStatePhonePlusWebOTP) {
std::vector<FormData> forms(1, form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+ browser_autofill_manager_->OnFormsSeen(forms);
+ autofill_driver_->SetBrowserAutofillManager(
+ std::move(browser_autofill_manager_));
static_cast<ContentAutofillDriver*>(autofill_driver_.get())
->ReportAutofillWebOTPMetrics(true);
histogram_tester.ExpectBucketCount(
@@ -10583,8 +10728,9 @@ TEST_F(AutofillMetricsTest,
std::vector<FormData> forms(1, form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+ browser_autofill_manager_->OnFormsSeen(forms);
+ autofill_driver_->SetBrowserAutofillManager(
+ std::move(browser_autofill_manager_));
static_cast<ContentAutofillDriver*>(autofill_driver_.get())
->ReportAutofillWebOTPMetrics(true);
histogram_tester.ExpectBucketCount(
@@ -10609,8 +10755,9 @@ TEST_F(AutofillMetricsTest, WebOTPPhoneCollectionMetricsStateLoggedToUKM) {
std::vector<FormData> forms(1, form);
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormsSeen(forms);
- autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+ browser_autofill_manager_->OnFormsSeen(forms);
+ autofill_driver_->SetBrowserAutofillManager(
+ std::move(browser_autofill_manager_));
static_cast<ContentAutofillDriver*>(autofill_driver_.get())
->ReportAutofillWebOTPMetrics(/* Document uses WebOTP */ true);
@@ -10730,8 +10877,8 @@ TEST_F(AutofillMetricsTest, FormEventMetrics_BySyncState) {
FormData form;
FormStructure form_structure(form);
std::vector<FormData> forms(1, form);
- autofill_manager_->OnFormsSeen(forms);
- autofill_manager_->Reset();
+ browser_autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->Reset();
{
base::HistogramTester histogram_tester;
@@ -10852,7 +10999,7 @@ TEST_P(AutofillMetricsFunnelTest, LogFunnelMetrics) {
const bool user_submitted_form = GetParam() >= 4;
// Simulate that the autofill manager has seen this form on page load.
- autofill_manager_->OnFormsSeen({form});
+ browser_autofill_manager_->OnFormsSeen({form});
if (!user_saw_suggestion) {
// Remove the profile to prevent suggestion from being shown.
@@ -10861,33 +11008,34 @@ TEST_P(AutofillMetricsFunnelTest, LogFunnelMetrics) {
// Simulate interacting with the form.
if (user_interacted_with_form) {
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
/*query_id=*/0, form, form.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
}
// Simulate seeing a suggestion.
if (user_saw_suggestion) {
- autofill_manager_->DidShowSuggestions(
+ browser_autofill_manager_->DidShowSuggestions(
/*has_autofill_suggestions=*/true, form, form.fields[0]);
}
// Simulate filling the form.
if (user_accepted_suggestion) {
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, /*query_id=*/0, form,
form.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), kTestGuid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(),
+ kTestGuid));
}
// Simulate form submission.
if (user_submitted_form) {
- autofill_manager_->OnFormSubmitted(form, /*known_success=*/false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, /*known_success=*/false, SubmissionSource::FORM_SUBMISSION);
}
- // Reset |autofill_manager_| to commit UMA metrics.
- autofill_manager_.reset();
+ // Reset |browser_autofill_manager_| to commit UMA metrics.
+ browser_autofill_manager_.reset();
// Phase 2: Validate Funnel expectations.
histogram_tester.ExpectBucketCount("Autofill.Funnel.ParsedAsType.Address", 1,
@@ -10961,6 +11109,83 @@ TEST_P(AutofillMetricsFunnelTest, LogFunnelMetrics) {
}
}
+// Verify that no key metrics are logged in the ablation state.
+TEST_F(AutofillMetricsFunnelTest, AblationState) {
+ base::FieldTrialParams feature_parameters{
+ {features::kAutofillAblationStudyEnabledForAddressesParam.name, "true"},
+ {features::kAutofillAblationStudyEnabledForPaymentsParam.name, "true"},
+ {features::kAutofillAblationStudyAblationWeightPerMilleParam.name,
+ "1000"},
+ };
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeatureWithParameters(
+ features::kAutofillEnableAblationStudy, feature_parameters);
+
+ // Create a profile.
+ RecreateProfile(/*is_server=*/false);
+
+ // Load a fillable form.
+ FormData form;
+ form.host_frame = test::GetLocalFrameToken();
+ form.unique_renderer_id = test::MakeFormRendererId();
+ form.name = u"TestForm";
+ form.url = GURL("https://example.com/form.html");
+ form.action = GURL("https://example.com/submit.html");
+ form.main_frame_origin = url::Origin::Create(autofill_client_.form_origin());
+
+ FormFieldData field;
+ std::vector<ServerFieldType> field_types;
+ test::CreateTestFormField("State", "state", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(ADDRESS_HOME_STATE);
+ test::CreateTestFormField("City", "city", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(ADDRESS_HOME_CITY);
+ test::CreateTestFormField("Street", "street", "", "text", &field);
+ form.fields.push_back(field);
+ field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
+
+ base::HistogramTester histogram_tester;
+
+ // Simulate that the autofill manager has seen this form on page load.
+ browser_autofill_manager_->OnFormsSeen({form});
+
+ // Simulate interacting with the form.
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
+ /*query_id=*/0, form, form.fields[0], gfx::RectF(),
+ /*autoselect_first_suggestion=*/false);
+
+ // Don't simulate a suggestion but simulate the user typing.
+ browser_autofill_manager_->OnTextFieldDidChange(form, form.fields[0],
+ gfx::RectF(), TimeTicks());
+
+ // Simulate form submission.
+ browser_autofill_manager_->OnFormSubmitted(form, /*known_success=*/false,
+ SubmissionSource::FORM_SUBMISSION);
+
+ // Reset |browser_autofill_manager_| to commit UMA metrics.
+ browser_autofill_manager_.reset();
+
+ // Phase 2: Validate Funnel expectations.
+ const char* kMetrics[] = {
+ "Autofill.Funnel.ParsedAsType",
+ "Autofill.Funnel.InteractionAfterParsedAsType",
+ "Autofill.Funnel.SuggestionAfterInteraction",
+ "Autofill.Funnel.FillAfterSuggestion",
+ "Autofill.Funnel.SubmissionAfterFill",
+ "Autofill.KeyMetrics.FillingReadiness",
+ "Autofill.KeyMetrics.FillingAcceptance",
+ "Autofill.KeyMetrics.FillingCorrectness",
+ "Autofill.KeyMetrics.FillingAssistance",
+ "Autofill.Autocomplete.NotOff.FillingAcceptance",
+ "Autofill.Autocomplete.Off.FillingAcceptance",
+ };
+ for (const char* metric : kMetrics) {
+ histogram_tester.ExpectTotalCount(base::StrCat({metric, ".Address"}), 0);
+ histogram_tester.ExpectTotalCount(base::StrCat({metric, ".CreditCard"}), 0);
+ }
+}
+
// Tests for Autofill.KeyMetrics.* metrics.
class AutofillMetricsKeyMetricsTest : public AutofillMetricsTest {
public:
@@ -10999,7 +11224,7 @@ void AutofillMetricsKeyMetricsTest::SetUp() {
field_types.push_back(ADDRESS_HOME_STREET_ADDRESS);
// Simulate having seen this form on page load.
- autofill_manager_->AddSeenForm(form_, field_types, field_types);
+ browser_autofill_manager_->AddSeenForm(form_, field_types, field_types);
}
// Validate Autofill.KeyMetrics.* in case the user submits the empty form.
@@ -11009,17 +11234,17 @@ TEST_F(AutofillMetricsKeyMetricsTest, LogEmptyForm) {
base::HistogramTester histogram_tester;
// Simulate page load.
- autofill_manager_->OnFormsSeen({form_});
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnFormsSeen({form_});
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form_, form_.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
// Simulate form submission.
- autofill_manager_->OnFormSubmitted(form_, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form_, false,
+ SubmissionSource::FORM_SUBMISSION);
- // Reset |autofill_manager_| to commit UMA metrics.
- autofill_manager_.reset();
+ // Reset |browser_autofill_manager_| to commit UMA metrics.
+ browser_autofill_manager_.reset();
histogram_tester.ExpectBucketCount(
"Autofill.KeyMetrics.FillingReadiness.Address", 1, 1);
@@ -11040,23 +11265,23 @@ TEST_F(AutofillMetricsKeyMetricsTest, LogNoProfile) {
// Simulate that no data is available.
personal_data_->ClearProfiles();
- autofill_manager_->OnFormsSeen({form_});
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnFormsSeen({form_});
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form_, form_.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
// Simulate user typing the address.
- autofill_manager_->OnTextFieldDidChange(form_, form_.fields[0], gfx::RectF(),
- TimeTicks());
- autofill_manager_->OnTextFieldDidChange(form_, form_.fields[1], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form_, form_.fields[0],
+ gfx::RectF(), TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form_, form_.fields[1],
+ gfx::RectF(), TimeTicks());
// Simulate form submission.
- autofill_manager_->OnFormSubmitted(form_, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form_, false,
+ SubmissionSource::FORM_SUBMISSION);
- // Reset |autofill_manager_| to commit UMA metrics.
- autofill_manager_.reset();
+ // Reset |browser_autofill_manager_| to commit UMA metrics.
+ browser_autofill_manager_.reset();
histogram_tester.ExpectBucketCount(
"Autofill.KeyMetrics.FillingReadiness.Address", 0, 1);
@@ -11075,25 +11300,25 @@ TEST_F(AutofillMetricsKeyMetricsTest, LogUserDoesNotAcceptSuggestion) {
base::HistogramTester histogram_tester;
// Simulate that suggestion is shown but user does not accept it.
- autofill_manager_->OnFormsSeen({form_});
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnFormsSeen({form_});
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form_, form_.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(
+ browser_autofill_manager_->DidShowSuggestions(
/*has_autofill_suggestions=*/true, form_, form_.fields[0]);
// Simulate user typing the address.
- autofill_manager_->OnTextFieldDidChange(form_, form_.fields[0], gfx::RectF(),
- TimeTicks());
- autofill_manager_->OnTextFieldDidChange(form_, form_.fields[1], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form_, form_.fields[0],
+ gfx::RectF(), TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form_, form_.fields[1],
+ gfx::RectF(), TimeTicks());
// Simulate form submission.
- autofill_manager_->OnFormSubmitted(form_, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form_, false,
+ SubmissionSource::FORM_SUBMISSION);
- // Reset |autofill_manager_| to commit UMA metrics.
- autofill_manager_.reset();
+ // Reset |browser_autofill_manager_| to commit UMA metrics.
+ browser_autofill_manager_.reset();
histogram_tester.ExpectBucketCount(
"Autofill.KeyMetrics.FillingReadiness.Address", 1, 1);
@@ -11112,26 +11337,27 @@ TEST_F(AutofillMetricsKeyMetricsTest, LogUserFixesFilledData) {
base::HistogramTester histogram_tester;
// Simulate that suggestion is shown and user accepts it.
- autofill_manager_->OnFormsSeen({form_});
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnFormsSeen({form_});
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form_, form_.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(
+ browser_autofill_manager_->DidShowSuggestions(
/*has_autofill_suggestions=*/true, form_, form_.fields[0]);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form_, form_.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), kTestGuid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(),
+ kTestGuid));
// Simulate user fixing the address.
- autofill_manager_->OnTextFieldDidChange(form_, form_.fields[1], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form_, form_.fields[1],
+ gfx::RectF(), TimeTicks());
// Simulate form submission.
- autofill_manager_->OnFormSubmitted(form_, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form_, false,
+ SubmissionSource::FORM_SUBMISSION);
- // Reset |autofill_manager_| to commit UMA metrics.
- autofill_manager_.reset();
+ // Reset |browser_autofill_manager_| to commit UMA metrics.
+ browser_autofill_manager_.reset();
histogram_tester.ExpectBucketCount(
"Autofill.KeyMetrics.FillingReadiness.Address", 1, 1);
@@ -11151,24 +11377,25 @@ TEST_F(AutofillMetricsKeyMetricsTest, LogUserFixesFilledDataButDoesNotSubmit) {
base::HistogramTester histogram_tester;
// Simulate that suggestion is shown and user accepts it.
- autofill_manager_->OnFormsSeen({form_});
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnFormsSeen({form_});
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
0, form_, form_.fields[0], gfx::RectF(),
/*autoselect_first_suggestion=*/false);
- autofill_manager_->DidShowSuggestions(
+ browser_autofill_manager_->DidShowSuggestions(
/*has_autofill_suggestions=*/true, form_, form_.fields[0]);
- autofill_manager_->FillOrPreviewForm(
+ browser_autofill_manager_->FillOrPreviewForm(
AutofillDriver::FORM_DATA_ACTION_FILL, 0, form_, form_.fields.front(),
- autofill_manager_->MakeFrontendIDForTest(std::string(), kTestGuid));
+ browser_autofill_manager_->MakeFrontendIDForTest(std::string(),
+ kTestGuid));
// Simulate user fixing the address.
- autofill_manager_->OnTextFieldDidChange(form_, form_.fields[1], gfx::RectF(),
- TimeTicks());
+ browser_autofill_manager_->OnTextFieldDidChange(form_, form_.fields[1],
+ gfx::RectF(), TimeTicks());
// Don't submit form.
- // Reset |autofill_manager_| to commit UMA metrics.
- autofill_manager_.reset();
+ // Reset |browser_autofill_manager_| to commit UMA metrics.
+ browser_autofill_manager_.reset();
histogram_tester.ExpectTotalCount(
"Autofill.KeyMetrics.FillingReadiness.Address", 0);
@@ -11205,15 +11432,15 @@ TEST_F(AutofillMetricsTest, PageLanguageMetricsExpectedCase) {
// Set up language state.
translate::LanguageDetectionDetails language_detection_details;
language_detection_details.adopted_language = "ub";
- autofill_manager_->OnLanguageDetermined(language_detection_details);
- autofill_client_.GetLanguageState()->SetOriginalLanguage("ub");
+ browser_autofill_manager_->OnLanguageDetermined(language_detection_details);
+ autofill_client_.GetLanguageState()->SetSourceLanguage("ub");
autofill_client_.GetLanguageState()->SetCurrentLanguage("ub");
int language_code = 'u' * 256 + 'b';
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.ParsedFieldTypesUsingTranslatedPageLanguage", language_code, 1);
@@ -11230,14 +11457,14 @@ TEST_F(AutofillMetricsTest, PageLanguageMetricsInvalidLanguage) {
// Set up language state.
translate::LanguageDetectionDetails language_detection_details;
language_detection_details.adopted_language = "en";
- autofill_manager_->OnLanguageDetermined(language_detection_details);
- autofill_client_.GetLanguageState()->SetOriginalLanguage("en");
+ browser_autofill_manager_->OnLanguageDetermined(language_detection_details);
+ autofill_client_.GetLanguageState()->SetSourceLanguage("en");
autofill_client_.GetLanguageState()->SetCurrentLanguage("other");
// Simulate form submission.
base::HistogramTester histogram_tester;
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
histogram_tester.ExpectUniqueSample(
"Autofill.ParsedFieldTypesUsingTranslatedPageLanguage", 0, 1);
diff --git a/chromium/components/autofill/core/browser/autofill_profile_import_process.cc b/chromium/components/autofill/core/browser/autofill_profile_import_process.cc
new file mode 100644
index 00000000000..1f627d5e18e
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_profile_import_process.cc
@@ -0,0 +1,380 @@
+// Copyright 2021 The Chromium Authors. 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_profile_import_process.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/common/autofill_clock.h"
+
+namespace autofill {
+
+namespace {
+
+using UserDecision = AutofillClient::SaveAddressProfileOfferUserDecision;
+
+// Returns a unique import id.
+AutofillProfileImportId GetImportId() {
+ static AutofillProfileImportId next_import_id(0);
+ next_import_id.value()++;
+ return next_import_id;
+}
+
+} // namespace
+
+ProfileImportProcess::ProfileImportProcess(
+ const AutofillProfile& observed_profile,
+ const std::string& app_locale,
+ const GURL& form_source_url,
+ const PersonalDataManager* personal_data_manager)
+ : import_id_(GetImportId()),
+ observed_profile_(observed_profile),
+ app_locale_(app_locale),
+ form_source_url_(form_source_url),
+ personal_data_manager_(personal_data_manager) {
+ DetermineProfileImportType();
+}
+
+ProfileImportProcess::ProfileImportProcess(const ProfileImportProcess&) =
+ default;
+
+ProfileImportProcess& ProfileImportProcess::operator=(
+ const ProfileImportProcess& other) = default;
+
+ProfileImportProcess::~ProfileImportProcess() = default;
+
+bool ProfileImportProcess::prompt_shown() const {
+ return prompt_shown_;
+}
+
+bool ProfileImportProcess::UserDeclined() const {
+ return user_decision_ == UserDecision::kDeclined ||
+ user_decision_ == UserDecision::kEditDeclined ||
+ user_decision_ == UserDecision::kMessageDeclined;
+ ;
+}
+
+bool ProfileImportProcess::UserAccepted() const {
+ return user_decision_ == UserDecision::kAccepted ||
+ user_decision_ == UserDecision::kEditAccepted;
+}
+
+void ProfileImportProcess::DetermineProfileImportType() {
+ AutofillProfileComparator comparator(app_locale_);
+ bool is_mergeable_with_existing_profile = false;
+
+ new_profiles_suppressed_for_domain_ =
+ personal_data_manager_
+ ? personal_data_manager_->IsNewProfileImportBlockedForDomain(
+ form_source_url_)
+ : false;
+
+ int number_of_unchanged_profiles = 0;
+
+ const std::vector<AutofillProfile*> existing_profiles =
+ personal_data_manager_->GetProfiles();
+
+ for (const auto* existing_profile : existing_profiles) {
+ // If the existing profile is not mergeable with the observed profile, the
+ // existing profile is not altered by this import.
+ if (!comparator.AreMergeable(*existing_profile, observed_profile_)) {
+ ++number_of_unchanged_profiles;
+ continue;
+ }
+
+ // The observed profile is mergeable with an existing profile.
+ // This information is used to determine if the observed profile classifies
+ // as an import of a new profile or the import of a duplicate profile.
+ is_mergeable_with_existing_profile = true;
+
+ // Make a copy of the existing profile and merge it with the observation.
+ // The return value of |MergeDataFrom()| indicates if the existing profile
+ // was changed at all during that merge.
+ AutofillProfile merged_profile = *existing_profile;
+ if (!merged_profile.MergeDataFrom(observed_profile_, app_locale_)) {
+ ++number_of_unchanged_profiles;
+ continue;
+ }
+
+ // At this point, the observed profile was merged with the existing profile
+ // which changed in some way.
+ // Now, determine if the merge alters any settings-visible value, or if the
+ // merge can be considered as a silent update that does not need to get
+ // user confirmation.
+ if (AutofillProfileComparator::ProfilesHaveDifferentSettingsVisibleValues(
+ *existing_profile, merged_profile)) {
+ // Determine if the existing profile is blocked for updates.
+ // If the personal data manager is not available the profile is considered
+ // as not blocked.
+ bool is_blocked_for_update =
+ personal_data_manager_
+ ? personal_data_manager_->IsProfileUpdateBlocked(
+ existing_profile->guid())
+ : false;
+ if (is_blocked_for_update) {
+ ++number_of_blocked_profile_updates_;
+ }
+
+ // If a settings-visible value changed, the existing profile is the merge
+ // candidate if no other merge candidate has already been found and if the
+ // existing profile is not blocked for updates.
+ if (!merge_candidate_.has_value() && !is_blocked_for_update) {
+ merge_candidate_ = *existing_profile;
+ import_candidate_ = merged_profile;
+ } else {
+ // If there is already a merge candidate, the existing profile is not
+ // supposed to be changed.
+ ++number_of_unchanged_profiles;
+ }
+ continue;
+ }
+ // If the profile changed but all settings-visible values are maintained,
+ // the profile can be updated silently.
+ merged_profile.set_modification_date(AutofillClock::Now());
+ updated_profiles_.emplace_back(merged_profile);
+ }
+
+ // If the profile is not mergeable with an existing profile, the import
+ // corresponds to a new profile.
+ if (!is_mergeable_with_existing_profile) {
+ // There should be no import candidate yet.
+ DCHECK(!import_candidate_.has_value());
+ if (new_profiles_suppressed_for_domain_) {
+ import_type_ = AutofillProfileImportType::kSuppressedNewProfile;
+ } else {
+ import_type_ = AutofillProfileImportType::kNewProfile;
+ import_candidate_ = observed_profile();
+ }
+ } else {
+ bool silent_updates_present = updated_profiles_.size() > 0;
+
+ if (merge_candidate_.has_value()) {
+ import_type_ =
+ silent_updates_present
+ ? AutofillProfileImportType::kConfirmableMergeAndSilentUpdate
+ : AutofillProfileImportType::kConfirmableMerge;
+ } else if (number_of_blocked_profile_updates_ > 0) {
+ import_type_ =
+ silent_updates_present
+ ? AutofillProfileImportType::
+ kSuppressedConfirmableMergeAndSilentUpdate
+ : AutofillProfileImportType::kSuppressedConfirmableMerge;
+ } else {
+ import_type_ = silent_updates_present
+ ? AutofillProfileImportType::kSilentUpdate
+ : AutofillProfileImportType::kDuplicateImport;
+ }
+ }
+
+ if (import_candidate_.has_value()) {
+ import_candidate_->set_modification_date(AutofillClock::Now());
+ }
+
+ // At this point, all existing profiles are either unchanged, updated and/or
+ // one is the merge candidate.
+ DCHECK_EQ(existing_profiles.size(),
+ number_of_unchanged_profiles + updated_profiles_.size() +
+ (merge_candidate_.has_value() ? 1 : 0));
+ DCHECK_NE(import_type_, AutofillProfileImportType::kImportTypeUnspecified);
+}
+
+std::vector<AutofillProfile> ProfileImportProcess::GetResultingProfiles() {
+ // At this point, a user decision must have been supplied.
+ DCHECK_NE(user_decision_, UserDecision::kUndefined);
+
+ std::vector<AutofillProfile> resulting_profiles;
+ std::set<std::string> guids_of_changed_profiles;
+
+ // Add all updated profiles.
+ for (const auto& updated_profile : updated_profiles_) {
+ resulting_profiles.push_back(updated_profile);
+ guids_of_changed_profiles.insert(updated_profile.guid());
+ }
+
+ // If there is a confirmed import candidate, add it.
+ if (confirmed_import_candidate_.has_value()) {
+ resulting_profiles.emplace_back(confirmed_import_candidate_.value());
+ guids_of_changed_profiles.insert(confirmed_import_candidate_->guid());
+ }
+
+ // Add all other profiles that are currently available in the personal data
+ // manager.
+ for (const auto* unchanged_profile : personal_data_manager_->GetProfiles()) {
+ if (guids_of_changed_profiles.count(unchanged_profile->guid()) == 0) {
+ resulting_profiles.push_back(*unchanged_profile);
+ }
+ }
+
+ return resulting_profiles;
+}
+
+void ProfileImportProcess::SetUserDecision(
+ UserDecision decision,
+ absl::optional<AutofillProfile> edited_profile) {
+ // A user decision should only be supplied once.
+ DCHECK_EQ(user_decision_, UserDecision::kUndefined);
+ DCHECK(!confirmed_import_candidate_.has_value());
+
+ user_decision_ = decision;
+ switch (user_decision_) {
+ // If the import was accepted either with or without a prompt, the import
+ // candidate gets confired.
+ case UserDecision::kUserNotAsked:
+ case UserDecision::kAccepted:
+ confirmed_import_candidate_ = import_candidate_;
+ break;
+
+ case UserDecision::kEditAccepted:
+ // If the import candidate is supplied, the 'edited_profile' must be
+ // supplied.
+ DCHECK(edited_profile.has_value());
+
+ // Make sure the verification status of all settings-visible non-empty
+ // fields in the edited profile are set to kUserVerified.
+ for (auto type : GetUserVisibleTypes()) {
+ std::u16string value = edited_profile->GetRawInfo(type);
+ if (!value.empty() &&
+ edited_profile->GetVerificationStatus(type) ==
+ structured_address::VerificationStatus::kNoStatus) {
+ edited_profile->SetRawInfoWithVerificationStatus(
+ type, value,
+ structured_address::VerificationStatus::kUserVerified);
+ };
+ }
+
+ edited_profile->FinalizeAfterImport();
+ edited_profile->set_modification_date(AutofillClock::Now());
+ // The `edited_profile` has to have the same `guid` as the original import
+ // candidate.
+ DCHECK_EQ(import_candidate_.value().guid(), edited_profile->guid());
+ confirmed_import_candidate_ = std::move(edited_profile);
+ break;
+
+ // If the confirmable merge was declided or ignored, the original merge
+ // candidate should be maintined. Note that the decline/ignore does not mean
+ // that silent updates are not performed.
+ case UserDecision::kDeclined:
+ case UserDecision::kEditDeclined:
+ case UserDecision::kMessageDeclined:
+ case UserDecision::kMessageTimeout:
+ case UserDecision::kIgnored:
+ case UserDecision::kAutoDeclined:
+ confirmed_import_candidate_ = merge_candidate_;
+ break;
+
+ case UserDecision::kNever:
+ break;
+
+ case UserDecision::kUndefined:
+ NOTREACHED();
+ break;
+ }
+}
+
+void ProfileImportProcess::AcceptWithoutPrompt() {
+ SetUserDecision(UserDecision::kUserNotAsked);
+}
+
+void ProfileImportProcess::AcceptWithoutEdits() {
+ SetUserDecision(UserDecision::kAccepted);
+}
+
+void ProfileImportProcess::AcceptWithEdits(AutofillProfile edited_profile) {
+ SetUserDecision(UserDecision::kEditAccepted,
+ absl::make_optional(edited_profile));
+}
+
+void ProfileImportProcess::Declined() {
+ SetUserDecision(UserDecision::kDeclined);
+}
+
+void ProfileImportProcess::Ignore() {
+ SetUserDecision(UserDecision::kIgnored);
+}
+
+bool ProfileImportProcess::ProfilesChanged() const {
+ // At this point, a user decision must have been supplied.
+ DCHECK_NE(user_decision_, UserDecision::kUndefined);
+
+ // If there are any updated profiles, return true.
+ if (updated_profiles_.size() > 0) {
+ return true;
+ }
+
+ // If there is no confirmed import candidate there are no changes.
+ if (!confirmed_import_candidate_.has_value()) {
+ return false;
+ }
+
+ // If the import was accepted, return true.
+ if (user_decision_ == UserDecision::kAccepted ||
+ user_decision_ == UserDecision::kEditAccepted ||
+ user_decision_ == UserDecision::kUserNotAsked) {
+ return true;
+ }
+
+ return false;
+}
+
+void ProfileImportProcess::set_prompt_was_shown() {
+ prompt_shown_ = true;
+}
+
+void ProfileImportProcess::CollectMetrics() const {
+ // Metrics should only be recorded after a user decision was supplied.
+ DCHECK_NE(user_decision_, UserDecision::kUndefined);
+
+ // For any finished import process record the type of the import.
+ AutofillMetrics::LogProfileImportType(import_type_);
+
+ // For an import process that involves prompting the user, record the
+ // decision.
+ if (import_type_ == AutofillProfileImportType::kNewProfile) {
+ AutofillMetrics::LogNewProfileImportDecision(user_decision_);
+ } else if (import_type_ == AutofillProfileImportType::kConfirmableMerge ||
+ import_type_ ==
+ AutofillProfileImportType::kConfirmableMergeAndSilentUpdate) {
+ AutofillMetrics::LogProfileUpdateImportDecision(user_decision_);
+
+ if (user_decision_ == UserDecision::kAccepted) {
+ DCHECK(merge_candidate_.has_value() && import_candidate_.has_value());
+
+ const std::vector<ProfileValueDifference> merge_difference =
+ AutofillProfileComparator::GetSettingsVisibleProfileDifference(
+ import_candidate_.value(), merge_candidate_.value(), app_locale_);
+
+ for (const auto& difference : merge_difference) {
+ AutofillMetrics::LogProfileUpdateAffectedType(difference.type);
+ }
+
+ AutofillMetrics::LogUpdateProfileNumberOfAffectedFields(
+ merge_difference.size());
+ }
+ }
+
+ // If the profile was edited by the user, record a histogram of edited types.
+ if (user_decision_ == UserDecision::kEditAccepted) {
+ const std::vector<ProfileValueDifference> edit_difference =
+ AutofillProfileComparator::GetSettingsVisibleProfileDifference(
+ import_candidate_.value(), confirmed_import_candidate_.value(),
+ app_locale_);
+ for (const auto& difference : edit_difference) {
+ if (import_type_ == AutofillProfileImportType::kNewProfile) {
+ AutofillMetrics::LogNewProfileEditedType(difference.type);
+ } else {
+ AutofillMetrics::LogProfileUpdateEditedType(difference.type);
+ }
+ }
+ if (import_type_ == AutofillProfileImportType::kNewProfile) {
+ AutofillMetrics::LogNewProfileNumberOfEditedFields(
+ edit_difference.size());
+ } else {
+ AutofillMetrics::LogUpdateProfileNumberOfEditedFields(
+ edit_difference.size());
+ }
+ }
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile_import_process.h b/chromium/components/autofill/core/browser/autofill_profile_import_process.h
new file mode 100644
index 00000000000..fe9282fa4c1
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_profile_import_process.h
@@ -0,0 +1,215 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_IMPORT_PROCESS_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_IMPORT_PROCESS_H_
+
+#include <vector>
+
+#include "base/util/type_safety/id_type.h"
+#include "components/autofill/core/browser/autofill_client.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+
+namespace autofill {
+
+// The id of an ongoing profile import process.
+using AutofillProfileImportId =
+ ::util::IdTypeU64<class AutofillProfileImportIdMarker>;
+
+// Specifies the type of a profile form import.
+enum class AutofillProfileImportType {
+ // Type is unspecified.
+ kImportTypeUnspecified,
+ // The observed profile corresponds to a new profile because there are no
+ // mergeable or updateable profiles.
+ kNewProfile,
+ // The imported profile is a subset of an already existing profile.
+ kDuplicateImport,
+ // The imported profile can be integrated into an already existing profile
+ // without any changes to settings-visible values.
+ kSilentUpdate,
+ // The imported profile changes settings-visible values which is only imported
+ // after explicit user confirmation.
+ kConfirmableMerge,
+ // The observed profile corresponds to a new profile because there are no
+ // mergeable or updateable profiles but imports are suppressed for this
+ // domain.
+ kSuppressedNewProfile,
+ // The observed profile resulted both in a confirmable merge and in a silent
+ // update.
+ kConfirmableMergeAndSilentUpdate,
+ // The observed profile resulted in one or more confirmable merges that are
+ // all suppressed with no additional silent updates.
+ kSuppressedConfirmableMerge,
+ // The observed profile resulted in one or more suppressed confirmable merges
+ // but with additional silent updates.
+ kSuppressedConfirmableMergeAndSilentUpdate,
+ kMaxValue = kSuppressedConfirmableMergeAndSilentUpdate
+};
+
+// This class holds the state associated with the import of an AutofillProfile
+// observed in a form submission and should be used as the follows:
+//
+// * An instance is created by supplying the observed profile, all already
+// existing profiles and the used locale.
+//
+// * Now, the import process awaits either a user decision or a
+// confirmation that the user wasn't prompted at all. This confirmation is
+// supplied by either calling `AcceptWithoutPrompt()`, `AcceptWithoutEdits()`,
+// `AcceptWithEdits()`, `Declined()` or `Ignore()`.
+//
+// * Finally, `GetResultingProfiles()` should be used to get the complete set of
+// resulting AutofillProfiles.
+//
+// The instance of this class should contain all information needed to record
+// metrics once an import process is finished.
+class ProfileImportProcess {
+ public:
+ ProfileImportProcess(const AutofillProfile& observed_profile,
+ const std::string& app_locale,
+ const GURL& form_source_url,
+ const PersonalDataManager* personal_data_manager);
+
+ ProfileImportProcess(const ProfileImportProcess&);
+ ProfileImportProcess& operator=(const ProfileImportProcess& other);
+
+ ~ProfileImportProcess();
+
+ // Returns true if showing the prompt was initiated for this import process.
+ bool prompt_shown() const;
+
+ const absl::optional<AutofillProfile>& import_candidate() const {
+ return import_candidate_;
+ }
+
+ const absl::optional<AutofillProfile>& merge_candidate() const {
+ return merge_candidate_;
+ }
+
+ const std::vector<AutofillProfile>& updated_profiles() const {
+ return updated_profiles_;
+ }
+
+ const AutofillProfileImportId& import_id() const { return import_id_; }
+
+ const AutofillProfile& observed_profile() const { return observed_profile_; }
+
+ AutofillProfileImportType import_type() const { return import_type_; }
+
+ AutofillClient::SaveAddressProfileOfferUserDecision user_decision() const {
+ return user_decision_;
+ }
+
+ // Returns true if the user actively declined the save of update without
+ // differentiating between the actual type of decline.
+ // If no decision is available yet, return false.
+ bool UserDeclined() const;
+
+ // Returns true if the user actively accepted the save of update without
+ // differentiating if there have been additional edits by the user.
+ // If no decision is available yet, return false.
+ bool UserAccepted() const;
+
+ const GURL& form_source_url() const { return form_source_url_; }
+
+ // Returns a vector containing all unchanged, updated, merged and new
+ // profiles.
+ std::vector<AutofillProfile> GetResultingProfiles();
+
+ // Returns false if the import does not result in any change to the stored
+ // profiles. This function can only be evaluated after a decision was
+ // supplied. Note that this function allows for a false positive if a user
+ // accepts a merge, but edits the profile back to its initial state.
+ bool ProfilesChanged() const;
+
+ // No prompt is shown to the user.
+ void AcceptWithoutPrompt();
+
+ // The import is accepted by the user without additional edits.
+ void AcceptWithoutEdits();
+
+ // The import is accepted but only with additional edits contained in
+ // `edited_profile`.
+ void AcceptWithEdits(AutofillProfile edited_profile);
+
+ // The import was declined.
+ void Declined();
+
+ // The prompt was ignored.
+ void Ignore();
+
+ // Set the prompt as being shown.
+ void set_prompt_was_shown();
+
+ // Supply a user |decision| for the import process. The option
+ // |edited_profile| reflect user edits to the import candidate.
+ void SetUserDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision decision,
+ absl::optional<AutofillProfile> edited_profile = absl::nullopt);
+
+ // Records UMA metrics. Should only be called after a user decision was
+ // supplied.
+ void CollectMetrics() const;
+
+ private:
+ // Determines the import type of |observed_profile_| with respect to
+ // |existing_profiles|. Only the first profile in |existing_profiles| becomes
+ // a merge candidate in case there is a confirmable merge.
+ void DetermineProfileImportType();
+
+ // An id to identify an import request.
+ AutofillProfileImportId import_id_;
+
+ // Indicates if the user is already prompted.
+ bool prompt_shown_{false};
+
+ // The profile as it has been observed on form submission.
+ AutofillProfile observed_profile_;
+
+ // Profiles that are silently updateable with the observed profile.
+ std::vector<AutofillProfile> updated_profiles_;
+
+ // A profile in its original state that can be merged with the observed
+ // profile.
+ absl::optional<AutofillProfile> merge_candidate_;
+
+ // The import candidate that is presented to the user.
+ absl::optional<AutofillProfile> import_candidate_;
+
+ // The type of the import indicates if the profile is just a duplicate of an
+ // existing profile, if an existing profile can be silently updated, or if
+ // the user must be prompted either because a merge would alter stored values,
+ // or because the profile is completely new.
+ AutofillProfileImportType import_type_{
+ AutofillProfileImportType::kImportTypeUnspecified};
+
+ // The profile as it was confirmed by the user or as it should be imported if
+ // user interactions are disabled.
+ absl::optional<AutofillProfile> confirmed_import_candidate_;
+
+ // The decision the user made when prompted.
+ AutofillClient::SaveAddressProfileOfferUserDecision user_decision_{
+ AutofillClient::SaveAddressProfileOfferUserDecision::kUndefined};
+
+ // The appplication locale used for this import process.
+ std::string app_locale_;
+
+ // The url of the form.
+ GURL form_source_url_;
+
+ // Indicates if saving a new profile is blocked for the domain the profile
+ // was observed on.
+ bool new_profiles_suppressed_for_domain_;
+
+ // A pointer to the persona data manager that is used to retrieve additional
+ // information about existing profiles.
+ const PersonalDataManager* personal_data_manager_;
+
+ // Counts the number of blocked profile updates.
+ int number_of_blocked_profile_updates_{0};
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_IMPORT_PROCESS_H_
diff --git a/chromium/components/autofill/core/browser/autofill_profile_import_process_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_import_process_unittest.cc
new file mode 100644
index 00000000000..997b8561a84
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_profile_import_process_unittest.cc
@@ -0,0 +1,669 @@
+// Copyright 2021 The Chromium Authors. 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_profile_import_process.h"
+
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/data_model/autofill_structured_address_test_utils.h"
+#include "components/autofill/core/browser/test_autofill_client.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
+#include "components/autofill/core/browser/test_personal_data_manager.h"
+#include "components/autofill/core/browser/test_utils/test_profiles.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+using structured_address::VerificationStatus;
+
+namespace {
+
+class AutofillProfileImportProcessTest : public testing::Test {
+ protected:
+ void BlockProfileForUpdates(const AutofillProfile& profile) {
+ while (!personal_data_manager_.IsProfileUpdateBlocked(profile.guid())) {
+ personal_data_manager_.AddStrikeToBlockProfileUpdate(profile.guid());
+ }
+ }
+
+ void BlockDomainForNewProfiles(GURL url) {
+ while (!personal_data_manager_.IsNewProfileImportBlockedForDomain(url)) {
+ personal_data_manager_.AddStrikeToBlockNewProfileImportForDomain(url);
+ }
+ }
+
+ TestPersonalDataManager personal_data_manager_;
+ GURL url_{"https://www.import.me/now.html"};
+};
+
+// Test that two subsequently created `ProfileImportProcess`s have distinct ids.
+TEST_F(AutofillProfileImportProcessTest, DistinctIds) {
+ AutofillProfile empty_profile;
+ ProfileImportProcess import_data1(empty_profile, "en_US", url_,
+ &personal_data_manager_);
+ ProfileImportProcess import_data2(empty_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // The import ids should be distinct.
+ EXPECT_NE(import_data1.import_id(), import_data2.import_id());
+
+ // In fact, the import id is incremented for every initiated
+ // `ProfileImportData`.
+ EXPECT_EQ(import_data1.import_id().value() + 1,
+ import_data2.import_id().value());
+}
+
+// Tests the import process for the scenario, that the user accepts the import
+// of their first profile.
+TEST_F(AutofillProfileImportProcessTest, ImportFirstProfile_UserAccepts) {
+ TestAutofillClock test_clock;
+
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ std::vector<AutofillProfile> existing_profiles = {};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Advance the test clock to make sure that the modification date of the new
+ // profile gets updated.
+ test_clock.Advance(base::TimeDelta::FromDays(1));
+ base::Time current_time = AutofillClock::Now();
+
+ // Create the import process for the scenario that there aren't any other
+ // stored profiles yet.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Simulate the acceptance of the save prompt.
+ import_data.AcceptWithoutEdits();
+
+ // This operation should result in a profile change, and the type of the
+ // import corresponds to the creation of a new profile.
+ EXPECT_TRUE(import_data.ProfilesChanged());
+ EXPECT_EQ(import_data.import_type(), AutofillProfileImportType::kNewProfile);
+
+ std::vector<AutofillProfile> resulting_profiles =
+ import_data.GetResultingProfiles();
+ ASSERT_EQ(resulting_profiles.size(), 1U);
+ EXPECT_THAT(resulting_profiles,
+ testing::UnorderedElementsAre(observed_profile));
+ EXPECT_EQ(resulting_profiles.at(0).modification_date(), current_time);
+}
+
+// Tests the import process for the scenario, that the import of a new profile
+// is blocked.
+TEST_F(AutofillProfileImportProcessTest, ImportFirstProfile_ImportIsBlocked) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ std::vector<AutofillProfile> existing_profiles = {};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ BlockDomainForNewProfiles(url_);
+
+ // Create the import process for the scenario that there aren't any other
+ // stored profiles yet.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // The user is not asked.
+ import_data.AcceptWithoutPrompt();
+
+ // This operation should not result in a profile change.
+ EXPECT_FALSE(import_data.ProfilesChanged());
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kSuppressedNewProfile);
+
+ EXPECT_THAT(import_data.GetResultingProfiles(),
+ testing::UnorderedElementsAre());
+}
+
+// Tests the import process for the scenario, that the user accepts the import
+// of their first profile but with additional edits..
+TEST_F(AutofillProfileImportProcessTest,
+ ImportFirstProfile_UserAcceptsWithEdits) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ std::vector<AutofillProfile> existing_profiles = {};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process for the scenario that there aren't any other
+ // stored profiles yet.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Simulate that the user accepts the save prompt but only after editing the
+ // profile. Note, that the `guid` of the edited profile must match the `guid`
+ // of the initial import candidate.
+ AutofillProfile edited_profile = test::DifferentFromStandardProfile();
+ test::CopyGUID(observed_profile, &edited_profile);
+ import_data.AcceptWithEdits(edited_profile);
+
+ // This operation should result in a profile change, and the type of the
+ // import corresponds to the creation of a new profile.
+ EXPECT_TRUE(import_data.ProfilesChanged());
+ EXPECT_EQ(import_data.import_type(), AutofillProfileImportType::kNewProfile);
+
+ EXPECT_THAT(import_data.GetResultingProfiles(),
+ testing::UnorderedElementsAre(edited_profile));
+}
+
+// Tests the import process for the scenario, that the user declines the import
+// of their first profile.
+TEST_F(AutofillProfileImportProcessTest, ImportFirstProfile_UserRejects) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ std::vector<AutofillProfile> existing_profiles = {};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process for the scenario that there aren't any other
+ // stored profiles yet.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Simulate the decline of the user.
+ import_data.Declined();
+
+ // Since the user declined, there should be no change to the profiles.
+ EXPECT_FALSE(import_data.ProfilesChanged());
+ // The type of import was nevertheless corresponds to the creation of a new
+ // profile.
+ EXPECT_EQ(import_data.import_type(), AutofillProfileImportType::kNewProfile);
+
+ EXPECT_THAT(import_data.GetResultingProfiles(),
+ testing::UnorderedElementsAre());
+}
+
+// Tests the import of a profile that is an exact duplicate of the only already
+// existing profile.
+TEST_F(AutofillProfileImportProcessTest, ImportDuplicateProfile) {
+ AutofillProfile observed_profile = test::StandardProfile();
+
+ std::vector<AutofillProfile> existing_profiles = {observed_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process for the scenario that the observed profile is an
+ // exact copy of an already existing one.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Test that the import of a duplicate is determined correctly.
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kDuplicateImport);
+
+ // In this scenario, the user should not be queried and the process is
+ // silently accepted.
+ import_data.AcceptWithoutPrompt();
+
+ // There should be no change to the profiles.
+ EXPECT_FALSE(import_data.ProfilesChanged());
+
+ EXPECT_THAT(import_data.GetResultingProfiles(),
+ testing::UnorderedElementsAre(existing_profiles.at(0)));
+}
+
+// Tests the import of a profile that is an exact duplicate of an already
+// existing profile along with other profiles that are not mergeable or
+// updateable with the observed profile.
+TEST_F(AutofillProfileImportProcessTest,
+ ImportDuplicateProfile_OutOfMultipleProfiles) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ // This already existing profile is an exact duplicate of the observed one.
+ AutofillProfile duplicate_existing_profile = observed_profile;
+ // This already existing profile is neither mergeable nor updateable with the
+ // observed one.
+ AutofillProfile distinct_existing_profile =
+ test::DifferentFromStandardProfile();
+
+ std::vector<AutofillProfile> existing_profiles = {duplicate_existing_profile,
+ distinct_existing_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process for the two already existing profiles.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Test that the type of import was determined correctly.
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kDuplicateImport);
+
+ // In this scenario, the user should not be queried and the process is
+ // silently accepted.
+ import_data.AcceptWithoutPrompt();
+
+ // Verify that this operation does not result in a change of the profiles.
+ EXPECT_FALSE(import_data.ProfilesChanged());
+
+ EXPECT_THAT(import_data.GetResultingProfiles(),
+ testing::UnorderedElementsAre(duplicate_existing_profile,
+ distinct_existing_profile));
+}
+
+// Tests the accepted import of a profile that is mergeable with an already
+// existing profile.
+TEST_F(AutofillProfileImportProcessTest, MergeWithExistingProfile_Accepted) {
+ TestAutofillClock test_clock;
+
+ AutofillProfile observed_profile = test::StandardProfile();
+ // The profile should be mergeable with the observed profile.
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ // Set a modification date and subsequently advance the test clock.
+ mergeable_profile.set_modification_date(AutofillClock::Now());
+ test_clock.Advance(base::TimeDelta::FromDays(1));
+ base::Time current_time = AutofillClock::Now();
+
+ std::vector<AutofillProfile> existing_profiles = {mergeable_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process for the scenario that a profile that is mergeable
+ // with the observed profile already exists.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Test that the type of import was determined correctly.
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kConfirmableMerge);
+
+ // There should be a merge candidate that is the existing profile.
+ ASSERT_TRUE(import_data.merge_candidate().has_value());
+ EXPECT_EQ(import_data.merge_candidate(), mergeable_profile);
+
+ // Simulate that the user accepts this import without edits.
+ import_data.AcceptWithoutEdits();
+
+ // And verify that this correctly translates to a change of the stored
+ // profiles.
+ EXPECT_TRUE(import_data.ProfilesChanged());
+
+ // Explicitly check the content of the stored profiles. The final profile
+ // should have the same content as the observed profile, but the `guid` of the
+ // `mergeable_profile`.
+ AutofillProfile final_profile = test::StandardProfile();
+ test::CopyGUID(mergeable_profile, &final_profile);
+
+ std::vector<AutofillProfile> resulting_profiles =
+ import_data.GetResultingProfiles();
+ ASSERT_EQ(resulting_profiles.size(), 1U);
+ EXPECT_THAT(resulting_profiles, testing::UnorderedElementsAre(final_profile));
+ EXPECT_EQ(resulting_profiles.at(0).modification_date(), current_time);
+}
+
+// Tests the accepted import of a profile that is mergeable with an already
+// existing profile for the scenario that the user introduced additional edits.
+TEST_F(AutofillProfileImportProcessTest,
+ MergeWithExistingProfile_AcceptWithEdits) {
+ TestAutofillClock test_clock;
+
+ AutofillProfile observed_profile = test::StandardProfile();
+ // The profile should be mergeable with the observed profile.
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ // Set a modification date and subsequently advance the test clock.
+ mergeable_profile.set_modification_date(AutofillClock::Now());
+ test_clock.Advance(base::TimeDelta::FromDays(1));
+ base::Time current_time = AutofillClock::Now();
+
+ std::vector<AutofillProfile> existing_profiles = {mergeable_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process for the scenario that a profile that is mergeable
+ // with the observed profile already exists.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Test that the type of import was determined correctly.
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kConfirmableMerge);
+ // There should be merge candidate that is the existing profile.
+ ASSERT_TRUE(import_data.merge_candidate().has_value());
+ EXPECT_EQ(import_data.merge_candidate(), mergeable_profile);
+
+ // Simulate that the user accepts this import with additional edits.
+ AutofillProfile edited_profile = test::DifferentFromStandardProfile();
+ // Note that it is necessary to maintain the `guid` of the initial import
+ // candidate.
+ test::CopyGUID(mergeable_profile, &edited_profile);
+ import_data.AcceptWithEdits(edited_profile);
+
+ // This should result in a change of stored profiles.
+ EXPECT_TRUE(import_data.ProfilesChanged());
+
+ std::vector<AutofillProfile> resulting_profiles =
+ import_data.GetResultingProfiles();
+ ASSERT_EQ(resulting_profiles.size(), 1U);
+ EXPECT_THAT(resulting_profiles,
+ testing::UnorderedElementsAre(edited_profile));
+ EXPECT_EQ(resulting_profiles.at(0).modification_date(), current_time);
+}
+
+// Tests the accepted import of a profile that is mergeable with an already
+// existing profile for the scenario that there are multiple profiles stored.
+TEST_F(AutofillProfileImportProcessTest,
+ MergeWithExistingProfile_MultipleStoredProfiles_Accepted) {
+ AutofillProfile observed_profile = test::StandardProfile();
+ // The profile should be mergeable with the observed profile.
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+ // This is just another completely different profile.
+ AutofillProfile distinct_profile = test::DifferentFromStandardProfile();
+
+ std::vector<AutofillProfile> existing_profiles = {mergeable_profile,
+ distinct_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create an import data instance for the observed profile and determine the
+ // import type for the case that there are no already existing profiles.
+ ProfileImportProcess import_data(observed_profile,
+ "en_US", url_, &personal_data_manager_);
+
+ // Test that the type of import was determined correctly.
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kConfirmableMerge);
+ // There should be merge candidate that is the existing profile.
+ ASSERT_TRUE(import_data.merge_candidate().has_value());
+ EXPECT_EQ(import_data.merge_candidate(), mergeable_profile);
+
+ // Simulate that the user accepts the operation without further edits.
+ import_data.AcceptWithoutEdits();
+
+ // This should result in the change of at least on profile.
+ EXPECT_TRUE(import_data.ProfilesChanged());
+
+ // Test that the user decision translates correctly to the expected end
+ // result.
+ AutofillProfile merged_profile = test::StandardProfile();
+ test::CopyGUID(mergeable_profile, &merged_profile);
+
+ EXPECT_THAT(import_data.GetResultingProfiles(),
+ testing::UnorderedElementsAre(merged_profile, distinct_profile));
+}
+
+// Tests the rejection of the merge of the observed profile with an already
+// existing one.
+TEST_F(AutofillProfileImportProcessTest, MergeWithExistingProfile_Rejected) {
+ TestAutofillClock test_clock;
+
+ AutofillProfile observed_profile = test::StandardProfile();
+ // The profile should be mergeable with the observed profile.
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ // Set a modification date and subsequently advance the test clock.
+ // Since the merge is not accepted, the `modification_date` should not be
+ // changed.
+ mergeable_profile.set_modification_date(AutofillClock::Now());
+ base::Time earlier_time = AutofillClock::Now();
+ test_clock.Advance(base::TimeDelta::FromDays(1));
+
+ std::vector<AutofillProfile> existing_profiles = {mergeable_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create an import data instance for the observed profile and determine the
+ // import type for the case that there are no already existing profiles.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Test that the type of import was determined correctly.
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kConfirmableMerge);
+ // There should be merge candidate that is the existing profile.
+ ASSERT_TRUE(import_data.merge_candidate().has_value());
+ EXPECT_EQ(import_data.merge_candidate(), mergeable_profile);
+ // But there should be no further updates profiles.
+ EXPECT_EQ(import_data.updated_profiles().size(), 0u);
+
+ // Simulate the decline by the user.
+ import_data.Declined();
+
+ // Since there are no additional updates, this should result in no overall
+ // changes.
+ EXPECT_FALSE(import_data.ProfilesChanged());
+
+ std::vector<AutofillProfile> resulting_profiles =
+ import_data.GetResultingProfiles();
+ ASSERT_EQ(resulting_profiles.size(), 1U);
+ EXPECT_THAT(resulting_profiles,
+ testing::UnorderedElementsAre(mergeable_profile));
+ EXPECT_EQ(resulting_profiles.at(0).modification_date(), earlier_time);
+}
+
+// Tests the scenario in which the observed profile results in a silent update
+// of the only already existing profile.
+TEST_F(AutofillProfileImportProcessTest, SilentlyUpdateProfile) {
+ TestAutofillClock test_clock;
+
+ // Silent updates need structured names to be enabled.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kAutofillEnableSupportForMoreStructureInNames);
+
+ AutofillProfile observed_profile = test::StandardProfile();
+ // The profile should be updateable with the observed profile.
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+
+ // Set a modification date and subsequently advance the test clock.
+ updateable_profile.set_modification_date(AutofillClock::Now());
+ test_clock.Advance(base::TimeDelta::FromDays(1));
+ base::Time current_time = AutofillClock::Now();
+
+ std::vector<AutofillProfile> existing_profiles = {updateable_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process for the scenario that there is an existing
+ // profile that is updateable with the observed profile.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Test that the type of import was determined correctly.
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kSilentUpdate);
+ // There should be no merge candidate since this is only a silent update.
+ EXPECT_FALSE(import_data.merge_candidate().has_value());
+ // But there should be one updated profiles.
+ EXPECT_EQ(import_data.updated_profiles().size(), 1u);
+
+ // In this scenario, the user should not be prompted.
+ import_data.AcceptWithoutPrompt();
+
+ // The operation should result in a change of the profiles
+ EXPECT_TRUE(import_data.ProfilesChanged());
+
+ // Test that the existing profile was correctly updated.
+ AutofillProfile updated_profile = test::StandardProfile();
+ updated_profile.set_guid(updateable_profile.guid());
+
+ std::vector<AutofillProfile> resulting_profiles =
+ import_data.GetResultingProfiles();
+ ASSERT_EQ(resulting_profiles.size(), 1U);
+ EXPECT_THAT(resulting_profiles,
+ testing::UnorderedElementsAre(updated_profile));
+ EXPECT_EQ(resulting_profiles.at(0).modification_date(), current_time);
+}
+
+// Tests the scenario in which an observed profile can be merged with an
+// existing profile while another already existing profile can be silently
+// updated. In this test, the users accepts the merge.
+TEST_F(AutofillProfileImportProcessTest, BothMergeAndSilentUpdate_Accepted) {
+ // Silent updates need structured names to be enabled.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kAutofillEnableSupportForMoreStructureInNames);
+
+ AutofillProfile observed_profile = test::StandardProfile();
+ // The profile should be updateable with the observed profile.
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+ // This profile should be mergeable with the observed profile.
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ std::vector<AutofillProfile> existing_profiles = {updateable_profile,
+ mergeable_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process with a mergeable and a updateable profile..
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Test that the type of import was determined correctly.
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kConfirmableMergeAndSilentUpdate);
+ // There should be a merge candidate.
+ ASSERT_TRUE(import_data.merge_candidate().has_value());
+ EXPECT_EQ(import_data.merge_candidate(), mergeable_profile);
+ // And also an updated profile.
+ EXPECT_EQ(import_data.updated_profiles().size(), 1u);
+
+ // Simulate that the user accepts the prompt without edits.
+ import_data.AcceptWithoutEdits();
+
+ // This should result in a change of the stored profiles.
+ EXPECT_TRUE(import_data.ProfilesChanged());
+
+ AutofillProfile updated_profile = observed_profile;
+ test::CopyGUID(updateable_profile, &updated_profile);
+ AutofillProfile merged_profile = observed_profile;
+ test::CopyGUID(mergeable_profile, &merged_profile);
+
+ EXPECT_THAT(import_data.GetResultingProfiles(),
+ testing::UnorderedElementsAre(merged_profile, updated_profile));
+}
+
+// Tests the scenario in which an observed profile can be merged with an
+// existing profile while another already existing profile can be silently
+// updated. In this test, the users declines the merge.
+TEST_F(AutofillProfileImportProcessTest, BothMergeAndSilentUpdate_Rejected) {
+ // Silent updates need structured names to be enabled.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kAutofillEnableSupportForMoreStructureInNames);
+
+ AutofillProfile observed_profile = test::StandardProfile();
+ // The profile should be updateable with the observed profile.
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+ // This profile should be mergeable with the observed profile.
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ std::vector<AutofillProfile> existing_profiles = {updateable_profile,
+ mergeable_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process with a mergeable and a updateable profile..
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Test that the type of import was determined correctly.
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kConfirmableMergeAndSilentUpdate);
+ // There should be a merge candidate.
+ ASSERT_TRUE(import_data.merge_candidate().has_value());
+ EXPECT_EQ(import_data.merge_candidate(), mergeable_profile);
+ // And also an updated profile.
+ EXPECT_EQ(import_data.updated_profiles().size(), 1u);
+
+ // Simulate that the user declines the merge.
+ import_data.Declined();
+
+ // The silent update should be performed unconditionally. Therefore, there
+ // should be a change to the stored profiles nevertheless.
+ EXPECT_TRUE(import_data.ProfilesChanged());
+
+ AutofillProfile updated_profile = observed_profile;
+ test::CopyGUID(updateable_profile, &updated_profile);
+
+ EXPECT_THAT(
+ import_data.GetResultingProfiles(),
+ testing::UnorderedElementsAre(mergeable_profile, updated_profile));
+}
+
+// Tests the scenario in which an observed profile can be merged with an
+// existing profile for which updates are blocked while another already existing
+// profile can be silently updated.
+TEST_F(AutofillProfileImportProcessTest, BlockedMergeAndSilentUpdate) {
+ // Silent updates need structured names to be enabled.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kAutofillEnableSupportForMoreStructureInNames);
+
+ AutofillProfile observed_profile = test::StandardProfile();
+ // The profile should be updateable with the observed profile.
+ AutofillProfile updateable_profile = test::UpdateableStandardProfile();
+ // This profile should be mergeable with the observed profile.
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ BlockProfileForUpdates(mergeable_profile);
+
+ std::vector<AutofillProfile> existing_profiles = {updateable_profile,
+ mergeable_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process with a mergeable and an updateable profile..
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Test that the type of import was determined correctly.
+ EXPECT_EQ(
+ import_data.import_type(),
+ AutofillProfileImportType::kSuppressedConfirmableMergeAndSilentUpdate);
+ // There should be no merge candidate because the only potential candidate is
+ // blocked but there should be a silent update.
+ EXPECT_FALSE(import_data.merge_candidate().has_value());
+ EXPECT_EQ(import_data.updated_profiles().size(), 1u);
+
+ // The user should not be asked.
+ import_data.AcceptWithoutPrompt();
+
+ // The silent update should be performed unconditionally. Therefore, there
+ // should be a change to the stored profiles nevertheless.
+ EXPECT_TRUE(import_data.ProfilesChanged());
+
+ AutofillProfile updated_profile = observed_profile;
+ test::CopyGUID(updateable_profile, &updated_profile);
+
+ EXPECT_THAT(
+ import_data.GetResultingProfiles(),
+ testing::UnorderedElementsAre(mergeable_profile, updated_profile));
+}
+
+// Tests the scenario in which an observed profile can be merged with an
+// existing profile for which updates are blocked.
+TEST_F(AutofillProfileImportProcessTest, BlockedMerge) {
+ // Silent updates need structured names to be enabled.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kAutofillEnableSupportForMoreStructureInNames);
+
+ AutofillProfile observed_profile = test::StandardProfile();
+ // This profile should be mergeable with the observed profile.
+ AutofillProfile mergeable_profile = test::SubsetOfStandardProfile();
+
+ BlockProfileForUpdates(mergeable_profile);
+
+ std::vector<AutofillProfile> existing_profiles = {mergeable_profile};
+ personal_data_manager_.SetProfiles(&existing_profiles);
+
+ // Create the import process with a mergeable profile.
+ ProfileImportProcess import_data(observed_profile, "en_US", url_,
+ &personal_data_manager_);
+
+ // Test that the type of import was determined correctly.
+ EXPECT_EQ(import_data.import_type(),
+ AutofillProfileImportType::kSuppressedConfirmableMerge);
+
+ // There should be no merge candidate because the only potential candidate is
+ // blocked and also no silent update.
+ EXPECT_FALSE(import_data.merge_candidate().has_value());
+ EXPECT_EQ(import_data.updated_profiles().size(), 0u);
+
+ // The user should not be asked.
+ import_data.AcceptWithoutPrompt();
+
+ EXPECT_FALSE(import_data.ProfilesChanged());
+
+ EXPECT_THAT(import_data.GetResultingProfiles(),
+ testing::UnorderedElementsAre(mergeable_profile));
+}
+
+} // namespace
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile_save_strike_database.cc b/chromium/components/autofill/core/browser/autofill_profile_save_strike_database.cc
new file mode 100644
index 00000000000..f93fb3fe7f3
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_profile_save_strike_database.cc
@@ -0,0 +1,100 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/autofill_profile_save_strike_database.h"
+
+#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/autofill/core/common/autofill_features.h"
+#include "url/gurl.h"
+
+namespace autofill {
+
+// Limit the number of domains for which the import of new profiles is disabled.
+constexpr size_t kMaxStrikeEntities = 200;
+
+// Once the limit of domains is reached, delete 50 to create a bit of headroom.
+constexpr size_t kMaxStrikeEntitiesAfterCleanup = 150;
+
+AutofillProfileSaveStrikeDatabase::AutofillProfileSaveStrikeDatabase(
+ StrikeDatabaseBase* strike_database)
+ : StrikeDatabaseIntegratorBase(strike_database) {
+ RemoveExpiredStrikes();
+}
+
+AutofillProfileSaveStrikeDatabase::~AutofillProfileSaveStrikeDatabase() =
+ default;
+
+absl::optional<size_t> AutofillProfileSaveStrikeDatabase::GetMaximumEntries()
+ const {
+ return absl::make_optional(kMaxStrikeEntities);
+}
+
+absl::optional<size_t>
+AutofillProfileSaveStrikeDatabase::GetMaximumEntriesAfterCleanup() const {
+ return absl::make_optional(kMaxStrikeEntitiesAfterCleanup);
+}
+
+std::string AutofillProfileSaveStrikeDatabase::GetProjectPrefix() const {
+ return "AutofillProfileSave";
+}
+
+int AutofillProfileSaveStrikeDatabase::GetMaxStrikesLimit() const {
+ // The default limit for strikes is 3.
+ return features::kAutofillAutoBlockSaveAddressProfilePromptStrikeLimit.Get();
+}
+
+absl::optional<base::TimeDelta>
+AutofillProfileSaveStrikeDatabase::GetExpiryTimeDelta() const {
+ // Expiry time is 180 days by default.
+ return base::TimeDelta::FromDays(
+ features::kAutofillAutoBlockSaveAddressProfilePromptExpirationDays.Get());
+}
+
+bool AutofillProfileSaveStrikeDatabase::UniqueIdsRequired() const {
+ return true;
+}
+
+void AutofillProfileSaveStrikeDatabase::ClearStrikesByOrigin(
+ const std::set<std::string>& hosts_to_delete) {
+ ClearStrikesByOriginAndTimeInternal(hosts_to_delete, base::Time::Min(),
+ base::Time::Max());
+}
+
+void AutofillProfileSaveStrikeDatabase::ClearStrikesByOriginAndTimeInternal(
+ const std::set<std::string>& hosts_to_delete,
+ base::Time delete_begin,
+ base::Time delete_end) {
+ if (delete_begin.is_null()) {
+ delete_begin = base::Time::Min();
+ }
+
+ if (delete_end.is_null()) {
+ delete_end = base::Time::Max();
+ }
+
+ std::vector<std::string> keys_to_delete;
+ keys_to_delete.reserve(GetStrikeCache().size());
+
+ for (auto const& entry : GetStrikeCache()) {
+ std::string strike_id = GetIdFromKey(entry.first);
+ if (strike_id.empty()) {
+ continue;
+ }
+
+ base::Time last_update = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(
+ entry.second.last_update_timestamp()));
+
+ // Check if the time stamp of the record is within deletion range and if the
+ // domain is deleted.
+ if (last_update >= delete_begin && last_update <= delete_end &&
+ hosts_to_delete.count(strike_id) != 0) {
+ keys_to_delete.push_back(entry.first);
+ }
+ }
+
+ ClearStrikesForKeys(keys_to_delete);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile_save_strike_database.h b/chromium/components/autofill/core/browser/autofill_profile_save_strike_database.h
new file mode 100644
index 00000000000..9a17152e7a7
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_profile_save_strike_database.h
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_SAVE_STRIKE_DATABASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_SAVE_STRIKE_DATABASE_H_
+
+#include <stdint.h>
+#include <set>
+#include <string>
+
+#include "components/autofill/core/browser/strike_database_base.h"
+#include "components/autofill/core/browser/strike_database_integrator_base.h"
+
+namespace autofill {
+
+// Implementation of StrikeDatabaseIntegratorBase for autofill profile imports.
+class AutofillProfileSaveStrikeDatabase : public StrikeDatabaseIntegratorBase {
+ public:
+ explicit AutofillProfileSaveStrikeDatabase(
+ StrikeDatabaseBase* strike_database);
+ ~AutofillProfileSaveStrikeDatabase() override;
+
+ void ClearStrikesByOriginAndTimeInternal(
+ const std::set<std::string>& hosts_to_delete,
+ base::Time delete_begin,
+ base::Time delete_end);
+
+ void ClearStrikesByOrigin(const std::set<std::string>& hosts_to_delete);
+
+ absl::optional<size_t> GetMaximumEntries() const override;
+ absl::optional<size_t> GetMaximumEntriesAfterCleanup() const override;
+
+ std::string GetProjectPrefix() const override;
+ int GetMaxStrikesLimit() const override;
+ absl::optional<base::TimeDelta> GetExpiryTimeDelta() const override;
+ bool UniqueIdsRequired() const override;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_SAVE_STRIKE_DATABASE_H_
diff --git a/chromium/components/autofill/core/browser/autofill_profile_save_strike_database_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_save_strike_database_unittest.cc
new file mode 100644
index 00000000000..b8262dc77df
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_profile_save_strike_database_unittest.cc
@@ -0,0 +1,157 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/strike_database_integrator_test_strike_database.h"
+
+#include <utility>
+#include <vector>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/autofill/core/browser/autofill_profile_save_strike_database.h"
+#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/autofill/core/browser/test_autofill_clock.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/leveldb_proto/public/proto_database.h"
+#include "components/leveldb_proto/public/proto_database_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace autofill {
+
+namespace {
+
+class AutofillProfileSaveStrikeDatabaseTest : public ::testing::Test {
+ public:
+ AutofillProfileSaveStrikeDatabaseTest() = default;
+
+ void SetUp() override {
+ EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ db_provider_ = std::make_unique<leveldb_proto::ProtoDatabaseProvider>(
+ temp_dir_.GetPath());
+
+ strike_database_service_ = std::make_unique<StrikeDatabase>(
+ db_provider_.get(), temp_dir_.GetPath());
+
+ strike_database_ = std::make_unique<AutofillProfileSaveStrikeDatabase>(
+ strike_database_service_.get());
+ }
+
+ void TearDown() override {
+ // The destruction of |strike_database_service_|'s components is posted
+ // to a task runner, requires running the loop to complete.
+ strike_database_.reset();
+ strike_database_service_.reset();
+ db_provider_.reset();
+ task_environment_.RunUntilIdle();
+ }
+
+ protected:
+ base::ScopedTempDir temp_dir_;
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<leveldb_proto::ProtoDatabaseProvider> db_provider_;
+ std::unique_ptr<StrikeDatabase> strike_database_service_;
+ std::unique_ptr<AutofillProfileSaveStrikeDatabase> strike_database_;
+
+ std::string test_host1 = "https://www.strikedhost.com";
+ std::string test_host2 = "https://www.otherhost.com";
+ std::string test_host3 = "https://www.justanotherhost.com";
+
+ std::set<std::string> delete_first_host_set = {test_host1};
+ std::set<std::string> delete_all_hosts_set = {test_host1, test_host2,
+ test_host3};
+};
+
+TEST_F(AutofillProfileSaveStrikeDatabaseTest, AddAndRemoveStrikes) {
+ strike_database_->AddStrike(test_host1);
+ EXPECT_EQ(strike_database_->GetStrikes(test_host1), 1);
+ EXPECT_FALSE(strike_database_->IsMaxStrikesLimitReached(test_host1));
+
+ strike_database_->AddStrikes(2, test_host1);
+ EXPECT_EQ(strike_database_->GetStrikes(test_host1), 3);
+ EXPECT_TRUE(strike_database_->IsMaxStrikesLimitReached(test_host1));
+
+ strike_database_->RemoveStrike(test_host1);
+ EXPECT_EQ(strike_database_->GetStrikes(test_host1), 2);
+ EXPECT_FALSE(strike_database_->IsMaxStrikesLimitReached(test_host1));
+}
+
+TEST_F(AutofillProfileSaveStrikeDatabaseTest,
+ RemoveStrikesByOriginWithinDeletionWindow) {
+ base::Time start_time = AutofillClock::Now();
+ // Both strikes are added within the deletion window, but the second should
+ // be ruled out by the filter.
+ strike_database_->AddStrike(test_host1);
+ strike_database_->AddStrike(test_host2);
+ base::Time end_time = AutofillClock::Now();
+
+ EXPECT_EQ(strike_database_->GetStrikes(test_host1), 1);
+ EXPECT_EQ(strike_database_->GetStrikes(test_host2), 1);
+
+ strike_database_->ClearStrikesByOriginAndTimeInternal(delete_first_host_set,
+ start_time, end_time);
+
+ EXPECT_EQ(strike_database_->GetStrikes(test_host1), 0);
+ EXPECT_EQ(strike_database_->GetStrikes(test_host2), 1);
+}
+
+TEST_F(AutofillProfileSaveStrikeDatabaseTest, RemoveStrikesByOrigin) {
+ strike_database_->AddStrike(test_host1);
+ strike_database_->AddStrike(test_host2);
+
+ EXPECT_EQ(strike_database_->GetStrikes(test_host1), 1);
+ EXPECT_EQ(strike_database_->GetStrikes(test_host2), 1);
+
+ strike_database_->ClearStrikesByOrigin(delete_first_host_set);
+
+ EXPECT_EQ(strike_database_->GetStrikes(test_host1), 0);
+ EXPECT_EQ(strike_database_->GetStrikes(test_host2), 1);
+}
+
+TEST_F(AutofillProfileSaveStrikeDatabaseTest,
+ DoNotRemoveStrikeAfterDeletionWindow) {
+ TestAutofillClock test_autofill_clock;
+ test_autofill_clock.SetNow(AutofillClock::Now());
+
+ base::Time start_time = AutofillClock::Now();
+ strike_database_->AddStrike(test_host1);
+ test_autofill_clock.Advance(base::TimeDelta::FromMinutes(1));
+ base::Time end_time = AutofillClock::Now();
+ test_autofill_clock.Advance(base::TimeDelta::FromMinutes(1));
+
+ // Now update the time stamp of this entry by adding another strike.
+ // By this, the entry should not be deleted.
+ strike_database_->AddStrike(test_host1);
+
+ strike_database_->ClearStrikesByOriginAndTimeInternal(delete_all_hosts_set,
+ start_time, end_time);
+ EXPECT_EQ(strike_database_->GetStrikes(test_host1), 2);
+}
+
+TEST_F(AutofillProfileSaveStrikeDatabaseTest,
+ DoNotRemoveStrikeBeforeDeletionWindow) {
+ // The strike is added before the deletion window.
+ TestAutofillClock test_autofill_clock;
+ test_autofill_clock.SetNow(AutofillClock::Now());
+
+ strike_database_->AddStrike(test_host1);
+ test_autofill_clock.Advance(base::TimeDelta::FromMinutes(1));
+
+ base::Time start_time = AutofillClock::Now();
+ test_autofill_clock.Advance(base::TimeDelta::FromMinutes(1));
+ base::Time end_time = AutofillClock::Now();
+
+ strike_database_->ClearStrikesByOriginAndTimeInternal(delete_all_hosts_set,
+ start_time, end_time);
+
+ EXPECT_EQ(strike_database_->GetStrikes(test_host1), 1);
+}
+
+} // namespace
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile_sync_util.cc b/chromium/components/autofill/core/browser/autofill_profile_sync_util.cc
index 0c2feccab94..db5b7bebe6e 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_sync_util.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_sync_util.cc
@@ -94,6 +94,11 @@ std::unique_ptr<EntityData> CreateEntityDataFromAutofillProfile(
specifics->set_guid(entry.guid());
specifics->set_origin(entry.origin());
+ if (!entry.profile_label().empty())
+ specifics->set_profile_label(entry.profile_label());
+
+ specifics->set_disallow_settings_visible_updates(
+ entry.disallow_settings_visible_updates());
specifics->set_use_count(entry.use_count());
specifics->set_use_date(entry.use_date().ToTimeT());
specifics->set_address_home_language_code(
@@ -253,6 +258,15 @@ std::unique_ptr<AutofillProfile> CreateAutofillProfileFromSpecifics(
profile->SetClientValidityFromBitfieldValue(
specifics.validity_state_bitfield());
+ // Set the profile label if it exists.
+ if (specifics.has_profile_label())
+ profile->set_profile_label(specifics.profile_label());
+
+ // Set the `disallow_settings_visible_updates state` if it exists.
+ if (specifics.has_disallow_settings_visible_updates())
+ profile->set_disallow_settings_visible_updates(
+ specifics.disallow_settings_visible_updates());
+
// Set repeated fields.
profile->SetRawInfoWithVerificationStatus(
NAME_HONORIFIC_PREFIX,
diff --git a/chromium/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
index 3db6a4ae3d2..f765af17a97 100644
--- a/chromium/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
+++ b/chromium/components/autofill/core/browser/autofill_profile_sync_util_unittest.cc
@@ -42,6 +42,9 @@ AutofillProfile ConstructCompleteProfile() {
profile.set_use_count(7);
profile.set_use_date(base::Time::FromTimeT(1423182152));
+ profile.set_profile_label("profile_label");
+ profile.set_disallow_settings_visible_updates(true);
+
// Set testing values and statuses for the name.
profile.SetRawInfoWithVerificationStatus(NAME_HONORIFIC_PREFIX, u"Dr.",
VerificationStatus::kObserved);
@@ -69,11 +72,10 @@ AutofillProfile ConstructCompleteProfile() {
profile.SetRawInfo(EMAIL_ADDRESS, u"user@example.com");
profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"1.800.555.1234");
profile.SetRawInfo(COMPANY_NAME, u"Google, Inc.");
- profile.SetRawInfoWithVerificationStatus(
- ADDRESS_HOME_STREET_ADDRESS,
- ASCIIToUTF16("123 Fake St. Dep Premise\n"
- "Apt. 10 Floor 2"),
- VerificationStatus::kObserved);
+ profile.SetRawInfoWithVerificationStatus(ADDRESS_HOME_STREET_ADDRESS,
+ u"123 Fake St. Dep Premise\n"
+ u"Apt. 10 Floor 2",
+ VerificationStatus::kObserved);
// Set testing values and statuses for the address.
EXPECT_EQ(u"123 Fake St. Dep Premise",
@@ -134,6 +136,8 @@ AutofillProfileSpecifics ConstructCompleteSpecifics() {
specifics.set_origin("https://www.example.com/");
specifics.set_use_count(7);
specifics.set_use_date(1423182152);
+ specifics.set_profile_label("profile_label");
+ specifics.set_disallow_settings_visible_updates(true);
// Set values and statuses for the names.
specifics.add_name_honorific("Dr.");
diff --git a/chromium/components/autofill/core/browser/autofill_profile_update_strike_database.cc b/chromium/components/autofill/core/browser/autofill_profile_update_strike_database.cc
new file mode 100644
index 00000000000..f08d69f2d12
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_profile_update_strike_database.cc
@@ -0,0 +1,59 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/autofill_profile_update_strike_database.h"
+
+#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/autofill/core/common/autofill_features.h"
+
+namespace autofill {
+
+// Limit the number of profiles for which an update os blocked.
+constexpr size_t kMaxStrikeEntities = 100;
+
+// Once the limit of profiles is reached, delete 30 to create a bit of headroom.
+constexpr size_t kMaxStrikeEntitiesAfterCleanup = 70;
+
+AutofillProfileUpdateStrikeDatabase::AutofillProfileUpdateStrikeDatabase(
+ StrikeDatabaseBase* strike_database)
+ : StrikeDatabaseIntegratorBase(strike_database) {
+ RemoveExpiredStrikes();
+}
+
+AutofillProfileUpdateStrikeDatabase::~AutofillProfileUpdateStrikeDatabase() =
+ default;
+
+absl::optional<size_t> AutofillProfileUpdateStrikeDatabase::GetMaximumEntries()
+ const {
+ return absl::make_optional(kMaxStrikeEntities);
+}
+
+absl::optional<size_t>
+AutofillProfileUpdateStrikeDatabase::GetMaximumEntriesAfterCleanup() const {
+ return absl::make_optional(kMaxStrikeEntitiesAfterCleanup);
+}
+
+std::string AutofillProfileUpdateStrikeDatabase::GetProjectPrefix() const {
+ return "AutofillProfileUpdate";
+}
+
+int AutofillProfileUpdateStrikeDatabase::GetMaxStrikesLimit() const {
+ // The default limit for strikes is 3.
+ return features::kAutofillAutoBlockUpdateAddressProfilePromptStrikeLimit
+ .Get();
+}
+
+absl::optional<base::TimeDelta>
+AutofillProfileUpdateStrikeDatabase::GetExpiryTimeDelta() const {
+ // Expiry time is 180 days by default.
+ return base::TimeDelta::FromDays(
+ features::kAutofillAutoBlockUpdateAddressProfilePromptExpirationDays
+ .Get());
+}
+
+bool AutofillProfileUpdateStrikeDatabase::UniqueIdsRequired() const {
+ return true;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_profile_update_strike_database.h b/chromium/components/autofill/core/browser/autofill_profile_update_strike_database.h
new file mode 100644
index 00000000000..9956bb362ad
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_profile_update_strike_database.h
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_UPDATE_STRIKE_DATABASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_UPDATE_STRIKE_DATABASE_H_
+
+#include <stdint.h>
+#include <string>
+
+#include "components/autofill/core/browser/strike_database_base.h"
+#include "components/autofill/core/browser/strike_database_integrator_base.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace autofill {
+
+// Implementation of StrikeDatabaseIntegratorBase for autofill profile updates.
+class AutofillProfileUpdateStrikeDatabase
+ : public StrikeDatabaseIntegratorBase {
+ public:
+ explicit AutofillProfileUpdateStrikeDatabase(
+ StrikeDatabaseBase* strike_database);
+ ~AutofillProfileUpdateStrikeDatabase() override;
+
+ absl::optional<size_t> GetMaximumEntries() const override;
+ absl::optional<size_t> GetMaximumEntriesAfterCleanup() const override;
+
+ std::string GetProjectPrefix() const override;
+ int GetMaxStrikesLimit() const override;
+ absl::optional<base::TimeDelta> GetExpiryTimeDelta() const override;
+ bool UniqueIdsRequired() const override;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_PROFILE_UPDATE_STRIKE_DATABASE_H_
diff --git a/chromium/components/autofill/core/browser/autofill_profile_update_strike_database_unittest.cc b/chromium/components/autofill/core/browser/autofill_profile_update_strike_database_unittest.cc
new file mode 100644
index 00000000000..d1b23d3b7ad
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_profile_update_strike_database_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/strike_database_integrator_test_strike_database.h"
+
+#include <memory>
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/test/task_environment.h"
+#include "components/autofill/core/browser/autofill_profile_update_strike_database.h"
+#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/leveldb_proto/public/proto_database_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace autofill {
+
+namespace {
+
+class AutofillProfileUpdateStrikeDatabaseTest : public ::testing::Test {
+ public:
+ AutofillProfileUpdateStrikeDatabaseTest() = default;
+
+ void SetUp() override {
+ EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ db_provider_ = std::make_unique<leveldb_proto::ProtoDatabaseProvider>(
+ temp_dir_.GetPath());
+
+ strike_database_service_ = std::make_unique<StrikeDatabase>(
+ db_provider_.get(), temp_dir_.GetPath());
+
+ strike_database_ = std::make_unique<AutofillProfileUpdateStrikeDatabase>(
+ strike_database_service_.get());
+ }
+
+ void TearDown() override {
+ // The destruction of |strike_database_service_|'s components is posted
+ // to a task runner, requires running the loop to complete.
+ strike_database_.reset();
+ strike_database_service_.reset();
+ db_provider_.reset();
+ task_environment_.RunUntilIdle();
+ }
+
+ protected:
+ base::ScopedTempDir temp_dir_;
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<leveldb_proto::ProtoDatabaseProvider> db_provider_;
+ std::unique_ptr<StrikeDatabase> strike_database_service_;
+ std::unique_ptr<AutofillProfileUpdateStrikeDatabase> strike_database_;
+};
+
+TEST_F(AutofillProfileUpdateStrikeDatabaseTest, AddAndRemoveStrikes) {
+ std::string test_guid = "a21f010a-eac1-41fc-aee9-c06bbedfb292";
+ strike_database_->AddStrike(test_guid);
+ EXPECT_EQ(strike_database_->GetStrikes(test_guid), 1);
+ EXPECT_FALSE(strike_database_->IsMaxStrikesLimitReached(test_guid));
+
+ strike_database_->AddStrikes(2, test_guid);
+ EXPECT_EQ(strike_database_->GetStrikes(test_guid), 3);
+ EXPECT_TRUE(strike_database_->IsMaxStrikesLimitReached(test_guid));
+
+ strike_database_->RemoveStrike(test_guid);
+ EXPECT_EQ(strike_database_->GetStrikes(test_guid), 2);
+ EXPECT_FALSE(strike_database_->IsMaxStrikesLimitReached(test_guid));
+}
+
+} // namespace
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_regex_constants.cc b/chromium/components/autofill/core/browser/autofill_regex_constants.cc
index b561b56d45c..c140328c3cc 100644
--- a/chromium/components/autofill/core/browser/autofill_regex_constants.cc
+++ b/chromium/components/autofill/core/browser/autofill_regex_constants.cc
@@ -221,14 +221,14 @@ const char16_t kNameOnCardRe[] =
u"|æŒå¡äººå§“å"; // zh-TW
const char16_t kNameOnCardContextualRe[] = u"name";
const char16_t kCardNumberRe[] =
- u"(add)?(?:card|cc|acct).?(?:number|#|no|num|field)"
- u"|(?<!telefon|haus|person|fødsels)nummer" // de-DE, sv-SE, no
- u"|カード番å·" // ja-JP
- u"|Ðомер.*карты" // ru
- u"|no.*kartu" // id
- u"|信用å¡å·|信用å¡å·ç " // zh-CN
- u"|信用å¡å¡è™Ÿ" // zh-TW
- u"|카드" // ko-KR
+ u"(add)?(?:card|cc|acct).?(?:number|#|no|num|field|pan)"
+ u"|(?<!telefon|haus|person|fødsels|kunden)nummer" // de-DE, sv-SE, no
+ u"|カード番å·" // ja-JP
+ u"|Ðомер.*карты" // ru
+ u"|no.*kartu" // id
+ u"|信用å¡å·|信用å¡å·ç " // zh-CN
+ u"|信用å¡å¡è™Ÿ" // zh-TW
+ u"|카드" // ko-KR
// es/pt/fr
u"|(numero|número|numéro)(?!.*(document|fono|phone|réservation))";
diff --git a/chromium/components/autofill/core/browser/autofill_regexes.cc b/chromium/components/autofill/core/browser/autofill_regexes.cc
index d644ead4ca0..b5c2d9e420c 100644
--- a/chromium/components/autofill/core/browser/autofill_regexes.cc
+++ b/chromium/components/autofill/core/browser/autofill_regexes.cc
@@ -18,6 +18,10 @@
namespace {
+// Maximum length of the string to match to avoid causing an icu::RegexMatcher
+// stack overflow. (crbug.com/1198219)
+constexpr int kMaxStringLength = 5000;
+
// A thread-local class that serves as a cache of compiled regex patterns.
//
// The regexp state can be accessed from multiple threads in single process
@@ -67,6 +71,9 @@ bool MatchesPattern(const base::StringPiece16& input,
const base::StringPiece16& pattern,
std::u16string* match,
int32_t group_to_be_captured) {
+ if (input.size() > kMaxStringLength)
+ return false;
+
static base::NoDestructor<AutofillRegexes> g_autofill_regexes;
static base::NoDestructor<base::Lock> g_lock;
base::AutoLock lock(*g_lock);
diff --git a/chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios.cc b/chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios.cc
deleted file mode 100644
index 9846405d391..00000000000
--- a/chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/core/browser/autofill_save_address_profile_delegate_ios.h"
-
-#include <utility>
-
-#include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/common/autofill_constants.h"
-#include "components/grit/components_scaled_resources.h"
-#include "components/infobars/core/infobar.h"
-#include "components/infobars/core/infobar_manager.h"
-#include "components/strings/grit/components_strings.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace autofill {
-
-AutofillSaveAddressProfileDelegateIOS::AutofillSaveAddressProfileDelegateIOS(
- const AutofillProfile& profile,
- AutofillClient::AddressProfileSavePromptCallback callback)
- : profile_(profile),
- address_profile_save_prompt_callback_(std::move(callback)) {}
-
-AutofillSaveAddressProfileDelegateIOS::
- ~AutofillSaveAddressProfileDelegateIOS() = default;
-
-// static
-AutofillSaveAddressProfileDelegateIOS*
-AutofillSaveAddressProfileDelegateIOS::FromInfobarDelegate(
- infobars::InfoBarDelegate* delegate) {
- return delegate->GetIdentifier() ==
- AUTOFILL_ADDRESS_PROFILE_INFOBAR_DELEGATE_IOS
- ? static_cast<AutofillSaveAddressProfileDelegateIOS*>(delegate)
- : nullptr;
-}
-
-std::u16string
-AutofillSaveAddressProfileDelegateIOS::GetMessageDescriptionText() const {
- // TODO(crbug.com/1167062): Replace with proper localized string.
- return std::u16string(u"Fill forms faster in Chrome");
-}
-
-std::u16string AutofillSaveAddressProfileDelegateIOS::GetMessageActionText()
- const {
- // TODO(crbug.com/1167062): Replace with proper localized string.
- return std::u16string(u"Save...");
-}
-
-const autofill::AutofillProfile*
-AutofillSaveAddressProfileDelegateIOS::GetProfile() const {
- return &profile_;
-}
-
-bool AutofillSaveAddressProfileDelegateIOS::Accept() {
- RunSaveAddressProfilePromptCallback(
- AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted);
- return true;
-}
-
-void AutofillSaveAddressProfileDelegateIOS::InfoBarDismissed() {
- // If the address profile modal dialog is presented, the user will be asked to
- // save or cancel the address profile. In case the user cancels, then
- // InfoBarDismissed() will be called.
- if (modal_is_shown_ && !modal_is_dismissed_)
- return;
-
- RunSaveAddressProfilePromptCallback(
- AutofillClient::SaveAddressProfileOfferUserDecision::kDeclined);
-}
-
-bool AutofillSaveAddressProfileDelegateIOS::Cancel() {
- RunSaveAddressProfilePromptCallback(
- AutofillClient::SaveAddressProfileOfferUserDecision::kDeclined);
- return true;
-}
-
-int AutofillSaveAddressProfileDelegateIOS::GetIconId() const {
- // TODO(crbug.com/1167062): Replace with proper icon.
- return IDR_INFOBAR_AUTOFILL_CC;
-}
-
-std::u16string AutofillSaveAddressProfileDelegateIOS::GetMessageText() const {
- // TODO(crbug.com/1167062): Replace with proper localized string.
- return std::u16string(u"Save address?");
-}
-
-infobars::InfoBarDelegate::InfoBarIdentifier
-AutofillSaveAddressProfileDelegateIOS::GetIdentifier() const {
- return AUTOFILL_ADDRESS_PROFILE_INFOBAR_DELEGATE_IOS;
-}
-
-bool AutofillSaveAddressProfileDelegateIOS::ShouldExpire(
- const NavigationDetails& details) const {
- // Expire the Infobar unless the navigation was triggered by the form that
- // presented the Infobar, or the navigation is a redirect.
- return !details.is_form_submission && !details.is_redirect;
-}
-
-int AutofillSaveAddressProfileDelegateIOS::GetButtons() const {
- return BUTTON_OK | BUTTON_CANCEL;
-}
-
-std::u16string AutofillSaveAddressProfileDelegateIOS::GetButtonLabel(
- InfoBarButton button) const {
- if (button == BUTTON_OK) {
- // TODO(crbug.com/1167062): Replace with proper localized string.
- return std::u16string(u"Save");
- }
-
- if (button == BUTTON_CANCEL) {
- // TODO(crbug.com/1167062): Replace with proper localized string.
- return std::u16string(u"No Thanks");
- }
-
- NOTREACHED() << "Unsupported button label requested.";
- return std::u16string();
-}
-
-void AutofillSaveAddressProfileDelegateIOS::RunSaveAddressProfilePromptCallback(
- AutofillClient::SaveAddressProfileOfferUserDecision decision) {
- std::move(address_profile_save_prompt_callback_).Run(decision, profile_);
-
- // Reset the modal dialog flags.
- modal_is_shown_ = false;
- modal_is_dismissed_ = false;
-}
-
-} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios.h b/chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios.h
deleted file mode 100644
index f059a88849e..00000000000
--- a/chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_SAVE_ADDRESS_PROFILE_DELEGATE_IOS_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_SAVE_ADDRESS_PROFILE_DELEGATE_IOS_H_
-
-#include <memory>
-
-#include "base/callback.h"
-#include "components/autofill/core/browser/autofill_client.h"
-#include "components/autofill/core/browser/data_model/autofill_profile.h"
-#include "components/infobars/core/confirm_infobar_delegate.h"
-
-namespace autofill {
-
-// A delegate for the prompt that enables the user to allow or deny storing
-// an address profile gathered from a form submission. Only used on iOS.
-class AutofillSaveAddressProfileDelegateIOS : public ConfirmInfoBarDelegate {
- public:
- AutofillSaveAddressProfileDelegateIOS(
- const AutofillProfile& profile,
- AutofillClient::AddressProfileSavePromptCallback callback);
- AutofillSaveAddressProfileDelegateIOS(
- const AutofillSaveAddressProfileDelegateIOS&) = delete;
- AutofillSaveAddressProfileDelegateIOS& operator=(
- const AutofillSaveAddressProfileDelegateIOS&) = delete;
- ~AutofillSaveAddressProfileDelegateIOS() override;
-
- // Returns |delegate| as an AutofillSaveAddressProfileDelegateIOS, or nullptr
- // if it is of another type.
- static AutofillSaveAddressProfileDelegateIOS* FromInfobarDelegate(
- infobars::InfoBarDelegate* delegate);
-
- std::u16string GetMessageDescriptionText() const;
- std::u16string GetMessageActionText() const;
- const autofill::AutofillProfile* GetProfile() const;
- void set_modal_is_shown_to_true() { modal_is_shown_ = true; }
-
- void set_modal_is_dismissed_to_true() { modal_is_dismissed_ = true; }
-
- // ConfirmInfoBarDelegate
- int GetIconId() const override;
- std::u16string GetMessageText() const override;
- infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
- bool ShouldExpire(const NavigationDetails& details) const override;
- void InfoBarDismissed() override;
- int GetButtons() const override;
- std::u16string GetButtonLabel(InfoBarButton button) const override;
- bool Accept() override;
- bool Cancel() override;
-
- private:
- // Fires the |address_profile_save_prompt_callback_| callback.
- void RunSaveAddressProfilePromptCallback(
- AutofillClient::SaveAddressProfileOfferUserDecision decision);
-
- // The profile that will be saved if the user accepts.
- AutofillProfile profile_;
-
- // The callback to run once the user makes a decision.
- AutofillClient::AddressProfileSavePromptCallback
- address_profile_save_prompt_callback_;
-
- // True if the AddressProfile modal dialog is shown.
- bool modal_is_shown_ = false;
-
- // True if the modal dialog was presented and then dismissed by the user.
- bool modal_is_dismissed_ = false;
-};
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_SAVE_ADDRESS_PROFILE_DELEGATE_IOS_H_
diff --git a/chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios_unittest.cc b/chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios_unittest.cc
deleted file mode 100644
index c003f597d38..00000000000
--- a/chromium/components/autofill/core/browser/autofill_save_address_profile_delegate_ios_unittest.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/autofill/core/browser/autofill_save_address_profile_delegate_ios.h"
-
-#include <memory>
-
-#include "base/test/mock_callback.h"
-#include "components/autofill/core/browser/autofill_client.h"
-#include "components/autofill/core/browser/autofill_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace autofill {
-
-TEST(AutofillSaveAddressProfileDelegateIOSTest, HandleUserAction_Accepted) {
- AutofillProfile profile = test::GetFullProfile();
- base::MockCallback<AutofillClient::AddressProfileSavePromptCallback> callback;
- auto delegate = std::make_unique<AutofillSaveAddressProfileDelegateIOS>(
- profile, callback.Get());
-
- EXPECT_CALL(
- callback,
- Run(AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted,
- profile));
- delegate->Accept();
-}
-
-} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios.cc b/chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios.cc
new file mode 100644
index 00000000000..c43af8e384a
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios.cc
@@ -0,0 +1,233 @@
+// Copyright 2021 The Chromium Authors. 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_save_update_address_profile_delegate_ios.h"
+
+#include <utility>
+
+#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_address_util.h"
+#include "components/autofill/core/common/autofill_constants.h"
+#include "components/grit/components_scaled_resources.h"
+#include "components/infobars/core/infobar.h"
+#include "components/infobars/core/infobar_manager.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace autofill {
+
+AutofillSaveUpdateAddressProfileDelegateIOS::
+ AutofillSaveUpdateAddressProfileDelegateIOS(
+ const AutofillProfile& profile,
+ const AutofillProfile* original_profile,
+ const std::string& locale,
+ AutofillClient::AddressProfileSavePromptCallback callback)
+ : locale_(locale),
+ profile_(profile),
+ original_profile_(base::OptionalFromPtr(original_profile)),
+ address_profile_save_prompt_callback_(std::move(callback)) {}
+
+AutofillSaveUpdateAddressProfileDelegateIOS::
+ ~AutofillSaveUpdateAddressProfileDelegateIOS() {
+ // If the user has navigated away without saving the modal, then the
+ // |address_profile_save_prompt_callback_| is run here.
+ if (!address_profile_save_prompt_callback_.is_null()) {
+ DCHECK(
+ user_decision_ !=
+ AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted &&
+ user_decision_ !=
+ AutofillClient::SaveAddressProfileOfferUserDecision::kEditAccepted);
+ RunSaveAddressProfilePromptCallback();
+ }
+}
+
+// static
+AutofillSaveUpdateAddressProfileDelegateIOS*
+AutofillSaveUpdateAddressProfileDelegateIOS::FromInfobarDelegate(
+ infobars::InfoBarDelegate* delegate) {
+ return delegate->GetIdentifier() ==
+ AUTOFILL_ADDRESS_PROFILE_INFOBAR_DELEGATE_IOS
+ ? static_cast<AutofillSaveUpdateAddressProfileDelegateIOS*>(
+ delegate)
+ : nullptr;
+}
+
+std::u16string
+AutofillSaveUpdateAddressProfileDelegateIOS::GetEnvelopeStyleAddress() const {
+ return ::autofill::GetEnvelopeStyleAddress(profile_, locale_,
+ /*include_recipient=*/true,
+ /*include_country=*/true);
+}
+
+std::u16string AutofillSaveUpdateAddressProfileDelegateIOS::GetPhoneNumber()
+ const {
+ return GetProfileInfo(PHONE_HOME_WHOLE_NUMBER);
+}
+
+std::u16string AutofillSaveUpdateAddressProfileDelegateIOS::GetEmailAddress()
+ const {
+ return GetProfileInfo(EMAIL_ADDRESS);
+}
+
+std::u16string AutofillSaveUpdateAddressProfileDelegateIOS::GetDescription()
+ const {
+ return GetProfileDescription(
+ original_profile_ ? *original_profile_ : profile_, locale_,
+ /*include_address_and_contacts=*/true);
+}
+
+std::u16string AutofillSaveUpdateAddressProfileDelegateIOS::GetSubtitle() {
+ DCHECK(original_profile_);
+ std::vector<ProfileValueDifference> differences =
+ GetProfileDifferenceForUi(original_profile_.value(), profile_, locale_);
+ bool address_updated =
+ std::find_if(differences.begin(), differences.end(),
+ [](const ProfileValueDifference& diff) {
+ return diff.type == ADDRESS_HOME_ADDRESS;
+ }) != differences.end();
+ return GetProfileDescription(
+ original_profile_.value(), locale_,
+ /*include_address_and_contacts=*/!address_updated);
+}
+
+std::u16string
+AutofillSaveUpdateAddressProfileDelegateIOS::GetMessageActionText() const {
+ return l10n_util::GetStringUTF16(
+ original_profile_ ? IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_PRIMARY_ACTION
+ : IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_PRIMARY_ACTION);
+}
+
+const autofill::AutofillProfile*
+AutofillSaveUpdateAddressProfileDelegateIOS::GetProfile() const {
+ return &profile_;
+}
+
+const autofill::AutofillProfile*
+AutofillSaveUpdateAddressProfileDelegateIOS::GetOriginalProfile() const {
+ return base::OptionalOrNullptr(original_profile_);
+}
+
+std::u16string AutofillSaveUpdateAddressProfileDelegateIOS::GetProfileInfo(
+ ServerFieldType type) const {
+ return profile_.GetInfo(type, locale_);
+}
+
+std::vector<ProfileValueDifference>
+AutofillSaveUpdateAddressProfileDelegateIOS::GetProfileDiff() const {
+ return GetProfileDifferenceForUi(*GetProfile(), *GetOriginalProfile(),
+ locale_);
+}
+
+void AutofillSaveUpdateAddressProfileDelegateIOS::EditAccepted() {
+ user_decision_ =
+ AutofillClient::SaveAddressProfileOfferUserDecision::kEditAccepted;
+ RunSaveAddressProfilePromptCallback();
+}
+
+void AutofillSaveUpdateAddressProfileDelegateIOS::EditDeclined() {
+ SetUserDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision::kEditDeclined);
+}
+
+void AutofillSaveUpdateAddressProfileDelegateIOS::MessageTimeout() {
+ SetUserDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision::kMessageTimeout);
+}
+
+void AutofillSaveUpdateAddressProfileDelegateIOS::MessageDeclined() {
+ SetUserDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision::kMessageDeclined);
+}
+
+void AutofillSaveUpdateAddressProfileDelegateIOS::SetProfileInfo(
+ const ServerFieldType& type,
+ const std::u16string& value) {
+ // Since the country field is a text field, we should use SetInfo() to make
+ // sure they get converted to country codes.
+ if (type == autofill::ADDRESS_HOME_COUNTRY) {
+ profile_.SetInfoWithVerificationStatus(
+ type, value, locale_,
+ autofill::structured_address::VerificationStatus::kUserVerified);
+ return;
+ }
+
+ profile_.SetRawInfoWithVerificationStatus(
+ type, value,
+ autofill::structured_address::VerificationStatus::kUserVerified);
+}
+
+bool AutofillSaveUpdateAddressProfileDelegateIOS::Accept() {
+ user_decision_ =
+ AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted;
+ RunSaveAddressProfilePromptCallback();
+ return true;
+}
+
+bool AutofillSaveUpdateAddressProfileDelegateIOS::Cancel() {
+ SetUserDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision::kDeclined);
+ return true;
+}
+
+bool AutofillSaveUpdateAddressProfileDelegateIOS::EqualsDelegate(
+ infobars::InfoBarDelegate* delegate) const {
+ return delegate->GetIdentifier() == GetIdentifier();
+}
+
+int AutofillSaveUpdateAddressProfileDelegateIOS::GetIconId() const {
+ NOTREACHED();
+ return IDR_INFOBAR_AUTOFILL_CC;
+}
+
+std::u16string AutofillSaveUpdateAddressProfileDelegateIOS::GetMessageText()
+ const {
+ return l10n_util::GetStringUTF16(
+ original_profile_ ? IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_TITLE
+ : IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_TITLE);
+}
+
+infobars::InfoBarDelegate::InfoBarIdentifier
+AutofillSaveUpdateAddressProfileDelegateIOS::GetIdentifier() const {
+ return AUTOFILL_ADDRESS_PROFILE_INFOBAR_DELEGATE_IOS;
+}
+
+bool AutofillSaveUpdateAddressProfileDelegateIOS::ShouldExpire(
+ const NavigationDetails& details) const {
+ // Expire the Infobar unless the navigation was triggered by the form that
+ // presented the Infobar, or the navigation is a redirect.
+ // Also, expire the infobar if the navigation is to a different page.
+ return !details.is_form_submission && !details.is_redirect &&
+ ConfirmInfoBarDelegate::ShouldExpire(details);
+}
+
+void AutofillSaveUpdateAddressProfileDelegateIOS::
+ RunSaveAddressProfilePromptCallback() {
+ std::move(address_profile_save_prompt_callback_)
+ .Run(user_decision_, profile_);
+}
+
+void AutofillSaveUpdateAddressProfileDelegateIOS::SetUserDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision user_decision) {
+ if (user_decision == AutofillClient::SaveAddressProfileOfferUserDecision::
+ kMessageTimeout &&
+ user_decision_ == AutofillClient::SaveAddressProfileOfferUserDecision::
+ kMessageDeclined) {
+ // |SaveAddressProfileInfobarBannerInteractionHandler::InfobarVisibilityChanged|
+ // would be called even when the banner is explicitly dismissed by the
+ // user. In that case, do not change the |user_decision_|.
+ return;
+ }
+ if (user_decision_ ==
+ AutofillClient::SaveAddressProfileOfferUserDecision::kEditAccepted ||
+ user_decision_ ==
+ AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted) {
+ // The infobar has already been saved. So, cancel should not change the
+ // |user_decision_| now.
+ return;
+ }
+ user_decision_ = user_decision;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios.h b/chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios.h
new file mode 100644
index 00000000000..4f542d2b735
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios.h
@@ -0,0 +1,123 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_SAVE_UPDATE_ADDRESS_PROFILE_DELEGATE_IOS_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_SAVE_UPDATE_ADDRESS_PROFILE_DELEGATE_IOS_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "components/autofill/core/browser/autofill_client.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
+#include "components/infobars/core/confirm_infobar_delegate.h"
+
+namespace autofill {
+
+// A delegate for the prompt that enables the user to allow or deny storing
+// an address profile gathered from a form submission. Only used on iOS.
+class AutofillSaveUpdateAddressProfileDelegateIOS
+ : public ConfirmInfoBarDelegate {
+ public:
+ AutofillSaveUpdateAddressProfileDelegateIOS(
+ const AutofillProfile& profile,
+ const AutofillProfile* original_profile,
+ const std::string& locale,
+ AutofillClient::AddressProfileSavePromptCallback callback);
+ AutofillSaveUpdateAddressProfileDelegateIOS(
+ const AutofillSaveUpdateAddressProfileDelegateIOS&) = delete;
+ AutofillSaveUpdateAddressProfileDelegateIOS& operator=(
+ const AutofillSaveUpdateAddressProfileDelegateIOS&) = delete;
+ ~AutofillSaveUpdateAddressProfileDelegateIOS() override;
+
+ // Returns |delegate| as an AutofillSaveUpdateAddressProfileDelegateIOS, or
+ // nullptr if it is of another type.
+ static AutofillSaveUpdateAddressProfileDelegateIOS* FromInfobarDelegate(
+ infobars::InfoBarDelegate* delegate);
+
+ // Returns the address in envelope style in the |profile_|.
+ std::u16string GetEnvelopeStyleAddress() const;
+
+ // Returns the phone number in the |profile_|.
+ std::u16string GetPhoneNumber() const;
+
+ // Returns the email address in the |profile_|.
+ std::u16string GetEmailAddress() const;
+
+ // Returns the subtitle text to be displayed in the save/update banner.
+ std::u16string GetDescription() const;
+
+ // Returns subtitle for the update modal.
+ std::u16string GetSubtitle();
+
+ // Returns the message button text.
+ std::u16string GetMessageActionText() const;
+
+ // Returns the data stored in the |profile_| corresponding to |type|.
+ std::u16string GetProfileInfo(ServerFieldType type) const;
+
+ // Returns the profile difference map between |profile_| and
+ // |original_profile_|.
+ std::vector<ProfileValueDifference> GetProfileDiff() const;
+
+ virtual void EditAccepted();
+ void EditDeclined();
+ void MessageTimeout();
+ void MessageDeclined();
+
+ // Updates |profile_| |type| value to |value|.
+ void SetProfileInfo(const ServerFieldType& type, const std::u16string& value);
+
+ const autofill::AutofillProfile* GetProfile() const;
+ const autofill::AutofillProfile* GetOriginalProfile() const;
+
+ // ConfirmInfoBarDelegate
+ int GetIconId() const override;
+ std::u16string GetMessageText() const override;
+ infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
+ bool ShouldExpire(const NavigationDetails& details) const override;
+ bool Accept() override;
+ bool Cancel() override;
+ bool EqualsDelegate(infobars::InfoBarDelegate* delegate) const override;
+
+#if defined(UNIT_TEST)
+ // Getter for |user_decision_|. Used for the testing purposes.
+ AutofillClient::SaveAddressProfileOfferUserDecision user_decision() const {
+ return user_decision_;
+ }
+#endif
+
+ private:
+ // Fires the |address_profile_save_prompt_callback_| callback with
+ // |user_decision_|.
+ void RunSaveAddressProfilePromptCallback();
+
+ // Sets |user_decision_| based on |user_decision|.
+ void SetUserDecision(
+ AutofillClient::SaveAddressProfileOfferUserDecision user_decision);
+
+ // The application locale.
+ std::string locale_;
+
+ // The profile that will be saved if the user accepts.
+ AutofillProfile profile_;
+
+ // The original profile that will be updated if the user accepts the update
+ // prompt. NULL if saving a new profile.
+ absl::optional<AutofillProfile> original_profile_;
+
+ // The callback to run once the user makes a decision.
+ AutofillClient::AddressProfileSavePromptCallback
+ address_profile_save_prompt_callback_;
+
+ // Records the last user decision based on the interactions with the
+ // banner/modal to be sent with |address_profile_save_prompt_callback_|.
+ AutofillClient::SaveAddressProfileOfferUserDecision user_decision_ =
+ AutofillClient::SaveAddressProfileOfferUserDecision::kIgnored;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_SAVE_UPDATE_ADDRESS_PROFILE_DELEGATE_IOS_H_
diff --git a/chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios_unittest.cc b/chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios_unittest.cc
new file mode 100644
index 00000000000..39217418cea
--- /dev/null
+++ b/chromium/components/autofill/core/browser/autofill_save_update_address_profile_delegate_ios_unittest.cc
@@ -0,0 +1,118 @@
+// Copyright 2021 The Chromium Authors. 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_save_update_address_profile_delegate_ios.h"
+
+#include <memory>
+
+#include "base/test/mock_callback.h"
+#include "components/autofill/core/browser/autofill_client.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/strings/grit/components_strings.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace autofill {
+
+TEST(AutofillSaveUpdateAddressProfileDelegateIOSTest,
+ HandleUserAction_Accepted) {
+ AutofillProfile profile = test::GetFullProfile();
+ base::MockCallback<AutofillClient::AddressProfileSavePromptCallback> callback;
+ auto delegate = std::make_unique<AutofillSaveUpdateAddressProfileDelegateIOS>(
+ profile, /*original_profile=*/nullptr, /*locale=*/"en-US",
+ callback.Get());
+
+ EXPECT_CALL(
+ callback,
+ Run(AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted,
+ profile));
+ delegate->Accept();
+}
+
+// Tests that the delegate returns Save Address profile strings when the
+// original_profile is supplied as nullptr to the delegate.
+TEST(AutofillSaveUpdateAddressProfileDelegateIOSTest, TestSaveAddressStrings) {
+ AutofillProfile profile = test::GetFullProfile();
+ base::MockCallback<AutofillClient::AddressProfileSavePromptCallback> callback;
+ auto delegate = std::make_unique<AutofillSaveUpdateAddressProfileDelegateIOS>(
+ profile, /*original_profile=*/nullptr, /*locale=*/"en-US",
+ callback.Get());
+
+ EXPECT_EQ(delegate->GetMessageActionText(),
+ l10n_util::GetStringUTF16(
+ IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_PRIMARY_ACTION));
+ EXPECT_EQ(
+ delegate->GetMessageText(),
+ l10n_util::GetStringUTF16(IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_TITLE));
+ EXPECT_EQ(delegate->GetDescription(),
+ std::u16string(u"John H. Doe, 666 Erebus St."));
+}
+
+// Tests that the delegate returns Update Address profile strings when the
+// original_profile is supplied to the delegate.
+TEST(AutofillSaveUpdateAddressProfileDelegateIOSTest,
+ TestUpdateAddressStrings) {
+ AutofillProfile profile = test::GetFullProfile();
+ AutofillProfile original_profile = test::GetFullProfile();
+ original_profile.SetInfo(NAME_FULL, u"John Doe", "en-US");
+ base::MockCallback<AutofillClient::AddressProfileSavePromptCallback> callback;
+ auto delegate = std::make_unique<AutofillSaveUpdateAddressProfileDelegateIOS>(
+ profile, &original_profile, /*locale=*/"en-US", callback.Get());
+
+ EXPECT_EQ(delegate->GetMessageActionText(),
+ l10n_util::GetStringUTF16(
+ IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_PRIMARY_ACTION));
+ EXPECT_EQ(
+ delegate->GetMessageText(),
+ l10n_util::GetStringUTF16(IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_TITLE));
+ EXPECT_EQ(delegate->GetDescription(),
+ std::u16string(u"John Doe, 666 Erebus St."));
+}
+
+// Tests that the callback is run with kDeclined on destruction.
+TEST(AutofillSaveUpdateAddressProfileDelegateIOSTest,
+ TestCallbackOnDestruction) {
+ AutofillProfile profile = test::GetFullProfile();
+ base::MockCallback<AutofillClient::AddressProfileSavePromptCallback> callback;
+ auto delegate = std::make_unique<AutofillSaveUpdateAddressProfileDelegateIOS>(
+ profile, /*original_profile=*/nullptr, /*locale=*/"en-US",
+ callback.Get());
+
+ delegate->Cancel();
+ EXPECT_CALL(
+ callback,
+ Run(AutofillClient::SaveAddressProfileOfferUserDecision::kDeclined,
+ testing::_));
+ // The callback should run in the destructor.
+ delegate.reset();
+}
+
+// Tests that the callback is run with kAccepted on Accept.
+TEST(AutofillSaveUpdateAddressProfileDelegateIOSTest, TestCallbackOnSave) {
+ AutofillProfile profile = test::GetFullProfile();
+ base::MockCallback<AutofillClient::AddressProfileSavePromptCallback> callback;
+ EXPECT_CALL(
+ callback,
+ Run(AutofillClient::SaveAddressProfileOfferUserDecision::kAccepted,
+ testing::_));
+ AutofillSaveUpdateAddressProfileDelegateIOS(
+ profile, /*original_profile=*/nullptr, /*locale=*/"en-US", callback.Get())
+ .Accept();
+}
+
+// Tests that the callback is run with kEditAccepted on EditAccepted.
+TEST(AutofillSaveUpdateAddressProfileDelegateIOSTest,
+ TestCallbackOnEditAccepted) {
+ AutofillProfile profile = test::GetFullProfile();
+ base::MockCallback<AutofillClient::AddressProfileSavePromptCallback> callback;
+ EXPECT_CALL(
+ callback,
+ Run(AutofillClient::SaveAddressProfileOfferUserDecision::kEditAccepted,
+ testing::_));
+ AutofillSaveUpdateAddressProfileDelegateIOS(
+ profile, /*original_profile=*/nullptr, /*locale=*/"en-US", callback.Get())
+ .EditAccepted();
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/autofill_subject.cc b/chromium/components/autofill/core/browser/autofill_subject.cc
index d67961074fb..80b5eefd331 100644
--- a/chromium/components/autofill/core/browser/autofill_subject.cc
+++ b/chromium/components/autofill/core/browser/autofill_subject.cc
@@ -6,7 +6,6 @@
#include <vector>
-#include "base/callback_forward.h"
#include "base/observer_list.h"
#include "components/autofill/core/browser/autofill_observer.h"
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.cc b/chromium/components/autofill/core/browser/autofill_test_utils.cc
index 8ab8fe79845..ee84d856b6a 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.cc
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.cc
@@ -631,11 +631,15 @@ CreditCardCloudTokenData GetCreditCardCloudTokenData2() {
AutofillOfferData GetCardLinkedOfferData1() {
AutofillOfferData data;
data.offer_id = 111;
- data.offer_reward_amount = "5%";
// Sets the expiry to be 45 days later.
data.expiry = AutofillClock::Now() + base::TimeDelta::FromDays(45);
data.offer_details_url = GURL("http://www.example1.com");
data.merchant_domain.emplace_back("http://www.example1.com");
+ data.display_strings.value_prop_text = "Get 5% off your purchase";
+ data.display_strings.see_details_text = "See details";
+ data.display_strings.usage_instructions_text =
+ "Check out with this card to activate";
+ data.offer_reward_amount = "5%";
data.eligible_instrument_id.emplace_back(111111);
return data;
}
@@ -643,15 +647,34 @@ AutofillOfferData GetCardLinkedOfferData1() {
AutofillOfferData GetCardLinkedOfferData2() {
AutofillOfferData data;
data.offer_id = 222;
- data.offer_reward_amount = "$10";
// Sets the expiry to be 40 days later.
data.expiry = AutofillClock::Now() + base::TimeDelta::FromDays(40);
data.offer_details_url = GURL("http://www.example2.com");
data.merchant_domain.emplace_back("http://www.example2.com");
+ data.display_strings.value_prop_text = "Get $10 off your purchase";
+ data.display_strings.see_details_text = "See details";
+ data.display_strings.usage_instructions_text =
+ "Check out with this card to activate";
+ data.offer_reward_amount = "$10";
data.eligible_instrument_id.emplace_back(222222);
return data;
}
+AutofillOfferData GetPromoCodeOfferData() {
+ AutofillOfferData data;
+ data.offer_id = 333;
+ // Sets the expiry to be 35 days later.
+ data.expiry = AutofillClock::Now() + base::TimeDelta::FromDays(35);
+ data.offer_details_url = GURL("http://www.example.com");
+ data.merchant_domain.emplace_back("http://www.example.com");
+ data.display_strings.value_prop_text = "5% off on shoes. Up to $50.";
+ data.display_strings.see_details_text = "See details";
+ data.display_strings.usage_instructions_text =
+ "Click the promo code field at checkout to autofill it.";
+ data.promo_code = "5PCTOFFSHOES";
+ return data;
+}
+
void SetProfileInfo(AutofillProfile* profile,
const char* first_name,
const char* middle_name,
diff --git a/chromium/components/autofill/core/browser/autofill_test_utils.h b/chromium/components/autofill/core/browser/autofill_test_utils.h
index 75b89b53556..568e8485806 100644
--- a/chromium/components/autofill/core/browser/autofill_test_utils.h
+++ b/chromium/components/autofill/core/browser/autofill_test_utils.h
@@ -221,13 +221,16 @@ CreditCardCloudTokenData GetCreditCardCloudTokenData1();
// one above.
CreditCardCloudTokenData GetCreditCardCloudTokenData2();
-// Returns an autofill card linked offer data full of dummy info.
+// Returns an Autofill card-linked offer data full of dummy info.
AutofillOfferData GetCardLinkedOfferData1();
-// Returns an autofill card linked offer data full of dummy info, different from
+// Returns an Autofill card-linked offer data full of dummy info, different from
// the one above.
AutofillOfferData GetCardLinkedOfferData2();
+// Returns an Autofill promo code offer data full of dummy info.
+AutofillOfferData GetPromoCodeOfferData();
+
// A unit testing utility that is common to a number of the Autofill unit
// tests. |SetProfileInfo| provides a quick way to populate a profile with
// c-strings.
diff --git a/chromium/components/autofill/core/browser/autofill_type.cc b/chromium/components/autofill/core/browser/autofill_type.cc
index 9b583bf8d65..6647aa97ad1 100644
--- a/chromium/components/autofill/core/browser/autofill_type.cc
+++ b/chromium/components/autofill/core/browser/autofill_type.cc
@@ -477,12 +477,12 @@ std::string AutofillType::ToString() const {
if (server_type_ != UNKNOWN_TYPE)
return ServerFieldTypeToString(server_type_);
- return FieldTypeToStringPiece(html_type_).as_string();
+ return std::string(FieldTypeToStringPiece(html_type_));
}
// static
std::string AutofillType::ServerFieldTypeToString(ServerFieldType type) {
- return FieldTypeToStringPiece(type).as_string();
+ return std::string(FieldTypeToStringPiece(type));
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/browser_autofill_manager.cc b/chromium/components/autofill/core/browser/browser_autofill_manager.cc
new file mode 100644
index 00000000000..55789c8006e
--- /dev/null
+++ b/chromium/components/autofill/core/browser/browser_autofill_manager.cc
@@ -0,0 +1,2781 @@
+// 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/autofill/core/browser/browser_autofill_manager.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <limits>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/check_op.h"
+#include "base/command_line.h"
+#include "base/containers/adapters.h"
+#include "base/containers/flat_map.h"
+#include "base/feature_list.h"
+#include "base/files/file_util.h"
+#include "base/guid.h"
+#include "base/i18n/rtl.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/notreached.h"
+#include "base/path_service.h"
+#include "base/ranges/algorithm.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.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/post_task.h"
+#include "base/task/thread_pool.h"
+#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
+#include "build/chromeos_buildflags.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"
+#include "components/autofill/core/browser/autofill_field.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/browser_autofill_manager_test_delegate.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/autofill_profile_comparator.h"
+#include "components/autofill/core/browser/data_model/credit_card.h"
+#include "components/autofill/core/browser/data_model/phone_number.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/form_data_importer.h"
+#include "components/autofill/core/browser/form_structure.h"
+#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/form_events.h"
+#include "components/autofill/core/browser/payments/autofill_offer_manager.h"
+#include "components/autofill/core/browser/payments/credit_card_access_manager.h"
+#include "components/autofill/core/browser/payments/payments_client.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/randomized_encoder.h"
+#include "components/autofill/core/browser/ui/popup_item_ids.h"
+#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_data_validation.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_payments_features.h"
+#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
+#include "components/autofill/core/common/autofill_util.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/form_data_predictions.h"
+#include "components/autofill/core/common/form_field_data.h"
+#include "components/autofill/core/common/password_form_fill_data.h"
+#include "components/autofill/core/common/signatures.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_service.h"
+#include "components/security_interstitials/core/pref_names.h"
+#include "components/security_state/core/security_state.h"
+#include "components/strings/grit/components_strings.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/geometry/rect.h"
+#include "url/gurl.h"
+
+#if defined(OS_IOS)
+#include "components/autofill/core/browser/keyboard_accessory_metrics_logger.h"
+#endif
+
+namespace autofill {
+
+using base::StartsWith;
+using base::TimeTicks;
+using mojom::SubmissionSource;
+
+constexpr int kCreditCardSigninPromoImpressionLimit = 3;
+
+namespace {
+
+const size_t kMaxRecentFormSignaturesToRemember = 3;
+
+// Time to wait, in ms, after a dynamic form change before triggering a refill.
+// This is used for sites that change multiple things consecutively.
+const size_t kWaitTimeForDynamicFormsMs = 200;
+
+// The time limit, in ms, between a fill and when a refill can happen.
+const int kLimitBeforeRefillMs = 1000;
+
+// Returns the credit card field |value| trimmed from whitespace and with stop
+// characters removed.
+std::u16string SanitizeCreditCardFieldValue(const std::u16string& value) {
+ std::u16string sanitized;
+ // We remove whitespace as well as some invisible unicode characters.
+ base::TrimWhitespace(value, base::TRIM_ALL, &sanitized);
+ base::TrimString(sanitized,
+ std::u16string({base::i18n::kRightToLeftMark,
+ base::i18n::kLeftToRightMark}),
+ &sanitized);
+ // Some sites have ____-____-____-____ in their credit card number fields, for
+ // example.
+ base::RemoveChars(sanitized, u"-_", &sanitized);
+ return sanitized;
+}
+
+// Returns whether the |field| is predicted as being any kind of name.
+bool IsNameType(const AutofillField& field) {
+ return field.Type().group() == FieldTypeGroup::kName ||
+ field.Type().group() == FieldTypeGroup::kNameBilling ||
+ field.Type().GetStorableType() == CREDIT_CARD_NAME_FULL ||
+ field.Type().GetStorableType() == CREDIT_CARD_NAME_FIRST ||
+ field.Type().GetStorableType() == CREDIT_CARD_NAME_LAST;
+}
+
+// Selects the right name type from the |old_types| to insert into the
+// |types_to_keep| based on |is_credit_card|. This is called when we have
+// multiple possible types.
+void SelectRightNameType(AutofillField* field, bool is_credit_card) {
+ DCHECK(field);
+ // Currently, there can be up to four possible types for a field.
+ DCHECK_GE(4U, field->possible_types().size());
+ DCHECK_LE(2U, field->possible_types().size());
+
+ ServerFieldTypeSet types_to_keep;
+ const auto& old_types = field->possible_types();
+
+ for (auto type : old_types) {
+ FieldTypeGroup group = AutofillType(type).group();
+ if ((is_credit_card && group == FieldTypeGroup::kCreditCard) ||
+ (!is_credit_card && group == FieldTypeGroup::kName)) {
+ types_to_keep.insert(type);
+ }
+ }
+
+ ServerFieldTypeValidityStatesMap new_types_validities;
+ // Since the disambiguation takes place when we up to four possible types,
+ // here we can add up to three remaining types when only one is removed.
+ for (auto type_to_keep : types_to_keep) {
+ new_types_validities[type_to_keep] =
+ field->get_validities_for_possible_type(type_to_keep);
+ }
+ field->set_possible_types(types_to_keep);
+ field->set_possible_types_validities(new_types_validities);
+}
+
+void LogDeveloperEngagementUkm(ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ const FormStructure& form_structure) {
+ if (form_structure.developer_engagement_metrics()) {
+ AutofillMetrics::LogDeveloperEngagementUkm(
+ ukm_recorder, source_id, form_structure.main_frame_origin().GetURL(),
+ form_structure.IsCompleteCreditCardForm(),
+ form_structure.GetFormTypes(),
+ form_structure.developer_engagement_metrics(),
+ form_structure.form_signature());
+ }
+}
+
+ValuePatternsMetric GetValuePattern(const std::u16string& value) {
+ if (IsUPIVirtualPaymentAddress(value))
+ return ValuePatternsMetric::kUpiVpa;
+ if (IsInternationalBankAccountNumber(value))
+ return ValuePatternsMetric::kIban;
+ return ValuePatternsMetric::kNoPatternFound;
+}
+
+void LogValuePatternsMetric(const FormData& form) {
+ for (const FormFieldData& field : form.fields) {
+ if (!field.IsVisible()) {
+ // Ignore hidden fields.
+ continue;
+ }
+ std::u16string value;
+ base::TrimWhitespace(field.value, base::TRIM_ALL, &value);
+ if (value.empty())
+ continue;
+ base::UmaHistogramEnumeration("Autofill.SubmittedValuePatterns",
+ GetValuePattern(value));
+ }
+}
+
+void LogLanguageMetrics(const translate::LanguageState* language_state) {
+ if (language_state) {
+ AutofillMetrics::LogFieldParsingTranslatedFormLanguageMetric(
+ language_state->current_language());
+ AutofillMetrics::LogFieldParsingPageTranslationStatusMetric(
+ language_state->IsPageTranslated());
+ }
+}
+
+// Finds the first field in |form_structure| with |field.value|=|value|.
+AutofillField* FindFirstFieldWithValue(const FormStructure& form_structure,
+ const std::u16string& value) {
+ for (const auto& field : form_structure) {
+ std::u16string 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* HeuristicallyFindCVCFieldForUpload(
+ 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());
+
+ std::u16string 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 |kKnownValue|). Otherwise, heuristically
+// search for the CVC field if any.
+AutofillField* GetBestPossibleCVCFieldForUpload(
+ const FormStructure& form_structure,
+ std::u16string 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::kKnownValue;
+ return result;
+ }
+
+ return HeuristicallyFindCVCFieldForUpload(form_structure);
+}
+
+// Some autofill types are detected based on values and not based on form
+// features. We may decide that it's an autofill form after submission.
+bool ContainsAutofillableValue(const autofill::FormStructure& form) {
+ return base::ranges::any_of(form, [](const auto& field) {
+ return base::Contains(field->possible_types(), UPI_VPA) ||
+ IsUPIVirtualPaymentAddress(field->value);
+ });
+}
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+// Retrieves all valid credit card candidates for virtual card selection. A
+// valid candidate must have exactly one cloud token.
+std::vector<CreditCard*> GetVirtualCardCandidates(
+ PersonalDataManager* personal_data_manager) {
+ DCHECK(personal_data_manager);
+ std::vector<CreditCard*> candidates =
+ personal_data_manager->GetServerCreditCards();
+ const std::vector<CreditCardCloudTokenData*> cloud_token_data =
+ personal_data_manager->GetCreditCardCloudTokenData();
+
+ // Constructs map.
+ std::unordered_map<std::string, int> id_count;
+ for (CreditCardCloudTokenData* data : cloud_token_data) {
+ const auto& iterator = id_count.find(data->masked_card_id);
+ if (iterator == id_count.end())
+ id_count.emplace(data->masked_card_id, 1);
+ else
+ iterator->second += 1;
+ }
+
+ // Remove the card from the vector that either has multiple cloud token data
+ // or has no cloud token data.
+ base::EraseIf(candidates, [&](const auto& card) {
+ const auto& iterator = id_count.find(card->server_id());
+ return iterator == id_count.end() || iterator->second > 1;
+ });
+
+ // Returns the remaining valid cards.
+ return candidates;
+}
+#endif
+
+const char* SubmissionSourceToString(SubmissionSource source) {
+ switch (source) {
+ case SubmissionSource::NONE:
+ return "NONE";
+ case SubmissionSource::SAME_DOCUMENT_NAVIGATION:
+ return "SAME_DOCUMENT_NAVIGATION";
+ case SubmissionSource::XHR_SUCCEEDED:
+ return "XHR_SUCCEEDED";
+ case SubmissionSource::FRAME_DETACHED:
+ return "FRAME_DETACHED";
+ case SubmissionSource::DOM_MUTATION_AFTER_XHR:
+ return "DOM_MUTATION_AFTER_XHR";
+ case SubmissionSource::PROBABLY_FORM_SUBMITTED:
+ return "PROBABLY_FORM_SUBMITTED";
+ case SubmissionSource::FORM_SUBMISSION:
+ return "FORM_SUBMISSION";
+ }
+ return "Unknown";
+}
+
+// Returns how many fields with type |field_type| may be filled in a form at
+// maximum.
+size_t TypeValueFormFillingLimit(ServerFieldType field_type) {
+ switch (field_type) {
+ case CREDIT_CARD_NUMBER:
+ return kCreditCardTypeValueFormFillingLimit;
+ case ADDRESS_HOME_STATE:
+ return kStateTypeValueFormFillingLimit;
+ default:
+ return kTypeValueFormFillingLimit;
+ }
+}
+
+// Logs the reason for suppressing autofill suggestions to
+// chrome://autofill-internals.
+void LogSuppressReason(LogManager* log_manager, const std::string& reason) {
+ if (!log_manager)
+ return;
+ log_manager->Log() << LoggingScope::kFilling
+ << LogMessage::kSuggestionSuppressed
+ << " Reason: " << reason;
+}
+
+} // namespace
+
+BrowserAutofillManager::FillingContext::FillingContext(
+ const AutofillField& field,
+ absl::variant<const AutofillProfile*, const CreditCard*>
+ profile_or_credit_card,
+ const std::u16string* optional_cvc)
+ : filled_field_id(field.global_id()),
+ filled_field_signature(field.GetFieldSignature()),
+ filled_field_unique_name(field.unique_name()),
+ original_fill_time(AutofillTickClock::NowTicks()) {
+ DCHECK(absl::holds_alternative<const CreditCard*>(profile_or_credit_card) ||
+ !optional_cvc);
+
+ if (absl::holds_alternative<const AutofillProfile*>(profile_or_credit_card)) {
+ profile_or_credit_card_with_cvc =
+ *absl::get<const AutofillProfile*>(profile_or_credit_card);
+ } else if (absl::holds_alternative<const CreditCard*>(
+ profile_or_credit_card)) {
+ profile_or_credit_card_with_cvc =
+ std::make_pair(*absl::get<const CreditCard*>(profile_or_credit_card),
+ optional_cvc ? *optional_cvc : std::u16string());
+ }
+}
+
+BrowserAutofillManager::FillingContext::~FillingContext() = default;
+
+BrowserAutofillManager::BrowserAutofillManager(
+ AutofillDriver* driver,
+ AutofillClient* client,
+ const std::string& app_locale,
+ AutofillDownloadManagerState enable_download_manager)
+ : BrowserAutofillManager(driver,
+ client,
+ client->GetPersonalDataManager(),
+ client->GetAutocompleteHistoryManager(),
+ app_locale,
+ enable_download_manager) {}
+
+BrowserAutofillManager::BrowserAutofillManager(
+ AutofillDriver* driver,
+ AutofillClient* client,
+ PersonalDataManager* personal_data,
+ AutocompleteHistoryManager* autocomplete_history_manager,
+ const std::string app_locale,
+ AutofillDownloadManagerState enable_download_manager,
+ std::unique_ptr<CreditCardAccessManager> cc_access_manager)
+ : AutofillManager(driver, client, enable_download_manager),
+ external_delegate_(
+ std::make_unique<AutofillExternalDelegate>(this, driver)),
+ app_locale_(app_locale),
+ personal_data_(personal_data),
+ field_filler_(app_locale, client->GetAddressNormalizer()),
+ autocomplete_history_manager_(
+ autocomplete_history_manager->GetWeakPtr()) {
+ address_form_event_logger_ = std::make_unique<AddressFormEventLogger>(
+ driver->IsInMainFrame(), form_interactions_ukm_logger(), client);
+ credit_card_form_event_logger_ = std::make_unique<CreditCardFormEventLogger>(
+ driver->IsInMainFrame(), form_interactions_ukm_logger(), personal_data_,
+ 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());
+ CountryNames::SetLocaleString(app_locale_);
+ offer_manager_ = client->GetAutofillOfferManager();
+}
+
+BrowserAutofillManager::~BrowserAutofillManager() {
+ if (has_parsed_forms_) {
+ base::UmaHistogramBoolean(
+ "Autofill.WebOTP.PhoneNumberCollection.ParseResult",
+ has_observed_phone_number_field_);
+ base::UmaHistogramBoolean("Autofill.WebOTP.OneTimeCode.FromAutocomplete",
+ has_observed_one_time_code_field_);
+ }
+
+ if (autocomplete_history_manager_) {
+ autocomplete_history_manager_->CancelPendingQueries(this);
+ }
+}
+
+void BrowserAutofillManager::ShowAutofillSettings(
+ bool show_credit_card_settings) {
+ client()->ShowAutofillSettings(show_credit_card_settings);
+}
+
+bool BrowserAutofillManager::ShouldShowScanCreditCard(
+ const FormData& form,
+ const FormFieldData& field) {
+ if (!client()->HasCreditCardScanFeature())
+ return false;
+
+ AutofillField* autofill_field = GetAutofillField(form, field);
+ if (!autofill_field)
+ return false;
+
+ bool is_card_number_field =
+ autofill_field->Type().GetStorableType() == CREDIT_CARD_NUMBER &&
+ base::ContainsOnlyChars(CreditCard::StripSeparators(field.value),
+ u"0123456789");
+
+ if (!is_card_number_field)
+ return false;
+
+ if (IsFormNonSecure(form))
+ return false;
+
+ static const int kShowScanCreditCardMaxValueLength = 6;
+ return field.value.size() <= kShowScanCreditCardMaxValueLength;
+}
+
+PopupType BrowserAutofillManager::GetPopupType(const FormData& form,
+ const FormFieldData& field) {
+ const AutofillField* autofill_field = GetAutofillField(form, field);
+ if (!autofill_field)
+ return PopupType::kUnspecified;
+
+ switch (autofill_field->Type().group()) {
+ case FieldTypeGroup::kNoGroup:
+ case FieldTypeGroup::kPasswordField:
+ case FieldTypeGroup::kTransaction:
+ case FieldTypeGroup::kUsernameField:
+ case FieldTypeGroup::kUnfillable:
+ return PopupType::kUnspecified;
+
+ case FieldTypeGroup::kCreditCard:
+ return PopupType::kCreditCards;
+
+ case FieldTypeGroup::kAddressHome:
+ case FieldTypeGroup::kAddressBilling:
+ return PopupType::kAddresses;
+
+ case FieldTypeGroup::kName:
+ case FieldTypeGroup::kNameBilling:
+ case FieldTypeGroup::kEmail:
+ case FieldTypeGroup::kCompany:
+ case FieldTypeGroup::kPhoneHome:
+ case FieldTypeGroup::kPhoneBilling:
+ return FormHasAddressField(form) ? PopupType::kAddresses
+ : PopupType::kPersonalInformation;
+
+ default:
+ NOTREACHED();
+ }
+}
+
+bool BrowserAutofillManager::ShouldShowCreditCardSigninPromo(
+ const FormData& form,
+ const FormFieldData& field) {
+ // Check whether we are dealing with a credit card field and whether it's
+ // appropriate to show the promo (e.g. the platform is supported).
+ AutofillField* autofill_field = GetAutofillField(form, field);
+ if (!autofill_field ||
+ autofill_field->Type().group() != FieldTypeGroup::kCreditCard ||
+ !client()->ShouldShowSigninPromo())
+ return false;
+
+ if (IsFormNonSecure(form))
+ return false;
+
+ // The last step is checking if we are under the limit of impressions.
+ int impression_count = client()->GetPrefs()->GetInteger(
+ prefs::kAutofillCreditCardSigninPromoImpressionCount);
+ if (impression_count < kCreditCardSigninPromoImpressionLimit) {
+ // The promo will be shown. Increment the impression count.
+ client()->GetPrefs()->SetInteger(
+ prefs::kAutofillCreditCardSigninPromoImpressionCount,
+ impression_count + 1);
+ return true;
+ }
+
+ return false;
+}
+
+bool BrowserAutofillManager::ShouldShowCardsFromAccountOption(
+ const FormData& form,
+ const FormFieldData& field) {
+ // Check whether we are dealing with a credit card field.
+ AutofillField* autofill_field = GetAutofillField(form, field);
+ if (!autofill_field ||
+ autofill_field->Type().group() != FieldTypeGroup::kCreditCard ||
+ // Exclude CVC and card type fields, because these will not have
+ // suggestions available after the user opts in.
+ autofill_field->Type().GetStorableType() ==
+ CREDIT_CARD_VERIFICATION_CODE ||
+ autofill_field->Type().GetStorableType() == CREDIT_CARD_TYPE) {
+ return false;
+ }
+
+ if (IsFormNonSecure(form))
+ return false;
+
+ return personal_data_->ShouldShowCardsFromAccountOption();
+}
+
+void BrowserAutofillManager::OnUserAcceptedCardsFromAccountOption() {
+ personal_data_->OnUserAcceptedCardsFromAccountOption();
+}
+
+void BrowserAutofillManager::RefetchCardsAndUpdatePopup(
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field_data) {
+ AutofillField* autofill_field = GetAutofillField(form, field_data);
+ AutofillType type = autofill_field ? autofill_field->Type()
+ : AutofillType(CREDIT_CARD_NUMBER);
+
+ DCHECK_EQ(FieldTypeGroup::kCreditCard, type.group());
+
+ bool should_display_gpay_logo;
+ auto cards =
+ GetCreditCardSuggestions(field_data, type, &should_display_gpay_logo);
+
+ DCHECK(!cards.empty());
+
+ external_delegate_->OnSuggestionsReturned(
+ query_id, cards,
+ /*autoselect_first_suggestion=*/false, should_display_gpay_logo);
+}
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+void BrowserAutofillManager::FetchVirtualCardCandidates() {
+ const std::vector<CreditCard*>& candidates =
+ GetVirtualCardCandidates(personal_data_);
+ // Make sure the |candidates| is not empty, otherwise the check in
+ // ShouldShowVirtualCardOption() should fail.
+ DCHECK(!candidates.empty());
+
+ client()->OfferVirtualCardOptions(
+ candidates,
+ base::BindOnce(&BrowserAutofillManager::OnVirtualCardCandidateSelected,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BrowserAutofillManager::OnVirtualCardCandidateSelected(
+ const std::string& selected_card_id) {
+ // TODO(crbug.com/1020740): Implement this and the following flow in a
+ // separate CL. The following flow will be sending a request to Payments
+ // to fetched the up-to-date cloud token data for the selected card and fill
+ // the information in the form.
+}
+#endif
+
+bool BrowserAutofillManager::ShouldParseForms(
+ const std::vector<FormData>& forms) {
+ bool autofill_enabled = IsAutofillEnabled();
+ sync_state_ = personal_data_ ? personal_data_->GetSyncSigninState()
+ : AutofillSyncSigninState::kNumSyncStates;
+ if (!has_logged_autofill_enabled_) {
+ AutofillMetrics::LogIsAutofillEnabledAtPageLoad(autofill_enabled,
+ sync_state_);
+ AutofillMetrics::LogIsAutofillProfileEnabledAtPageLoad(
+ IsAutofillProfileEnabled(), sync_state_);
+ AutofillMetrics::LogIsAutofillCreditCardEnabledAtPageLoad(
+ IsAutofillCreditCardEnabled(), sync_state_);
+ has_logged_autofill_enabled_ = true;
+ }
+
+ return autofill_enabled;
+}
+
+void BrowserAutofillManager::OnFormSubmittedImpl(const FormData& form,
+ bool known_success,
+ SubmissionSource source) {
+ base::UmaHistogramEnumeration("Autofill.FormSubmission.PerProfileType",
+ client()->GetProfileType());
+ if (log_manager()) {
+ log_manager()->Log() << LoggingScope::kSubmission
+ << LogMessage::kFormSubmissionDetected << Br{}
+ << "known_success: " << known_success << Br{}
+ << "source: " << SubmissionSourceToString(source)
+ << Br{} << form;
+ }
+
+ // Always upload page language metrics.
+ LogLanguageMetrics(client()->GetLanguageState());
+
+ // Always let the value patterns metric upload data.
+ LogValuePatternsMetric(form);
+
+ // We will always give Autocomplete a chance to save the data.
+ std::unique_ptr<FormStructure> submitted_form = ValidateSubmittedForm(form);
+ if (!submitted_form) {
+ autocomplete_history_manager_->OnWillSubmitForm(
+ form, client()->IsAutocompleteEnabled());
+ return;
+ }
+
+ // Log interaction time metrics for the ablation study.
+ if (!initial_interaction_timestamp_.is_null()) {
+ base::TimeDelta time_from_interaction_to_submission =
+ AutofillTickClock::NowTicks() - initial_interaction_timestamp_;
+ DenseSet<FormType> form_types = submitted_form->GetFormTypes();
+ bool card_form = base::Contains(form_types, FormType::kCreditCardForm);
+ bool address_form = base::Contains(form_types, FormType::kAddressForm);
+ if (card_form) {
+ credit_card_form_event_logger_->SetTimeFromInteractionToSubmission(
+ time_from_interaction_to_submission);
+ }
+ if (address_form) {
+ address_form_event_logger_->SetTimeFromInteractionToSubmission(
+ time_from_interaction_to_submission);
+ }
+ }
+
+ // However, if Autofill has recognized a field as CVC, that shouldn't be
+ // saved.
+ FormData form_for_autocomplete = submitted_form->ToFormData();
+ for (size_t i = 0; i < submitted_form->field_count(); ++i) {
+ if (submitted_form->field(i)->Type().GetStorableType() ==
+ CREDIT_CARD_VERIFICATION_CODE) {
+ form_for_autocomplete.fields[i].should_autocomplete = false;
+ }
+ }
+ autocomplete_history_manager_->OnWillSubmitForm(
+ form_for_autocomplete, client()->IsAutocompleteEnabled());
+
+ if (IsAutofillProfileEnabled()) {
+ address_form_event_logger_->OnWillSubmitForm(sync_state_, *submitted_form);
+ }
+ if (IsAutofillCreditCardEnabled()) {
+ credit_card_form_event_logger_->OnWillSubmitForm(sync_state_,
+ *submitted_form);
+ }
+
+ submitted_form->set_submission_source(source);
+ MaybeStartVoteUploadProcess(std::move(submitted_form),
+ /*observed_submission=*/true);
+
+ // TODO(crbug.com/803334): Add FormStructure::Clone() method.
+ // Create another FormStructure instance.
+ submitted_form = ValidateSubmittedForm(form);
+ DCHECK(submitted_form);
+ if (!submitted_form)
+ return;
+
+ submitted_form->set_submission_source(source);
+
+ if (IsAutofillProfileEnabled()) {
+ address_form_event_logger_->OnFormSubmitted(sync_state_, *submitted_form);
+ }
+ if (IsAutofillCreditCardEnabled()) {
+ credit_card_form_event_logger_->OnFormSubmitted(sync_state_,
+ *submitted_form);
+ }
+
+ if (!submitted_form->IsAutofillable() &&
+ !ContainsAutofillableValue(*submitted_form)) {
+ return;
+ }
+
+ // Update Personal Data with the form's submitted data.
+ // Also triggers offering local/upload credit card save, if applicable.
+ client()->GetFormDataImporter()->ImportFormData(
+ *submitted_form, IsAutofillProfileEnabled(),
+ IsAutofillCreditCardEnabled());
+}
+
+bool BrowserAutofillManager::MaybeStartVoteUploadProcess(
+ std::unique_ptr<FormStructure> form_structure,
+ bool observed_submission) {
+ // It is possible for |personal_data_| to be null, such as when used in the
+ // Android webview.
+ if (!personal_data_)
+ return false;
+
+ // Only upload server statistics and UMA metrics if at least some local data
+ // is available to use as a baseline.
+ std::vector<AutofillProfile*> profiles = personal_data_->GetProfiles();
+ personal_data_->UpdateProfilesServerValidityMapsIfNeeded(profiles);
+ if (observed_submission && form_structure->IsAutofillable()) {
+ AutofillMetrics::LogNumberOfProfilesAtAutofillableFormSubmission(
+ personal_data_->GetProfiles().size());
+ }
+
+ const std::vector<CreditCard*>& credit_cards =
+ credit_card_access_manager_->GetCreditCards();
+
+ if (profiles.empty() && credit_cards.empty())
+ return false;
+
+ if (form_structure->field_count() * (profiles.size() + credit_cards.size()) >=
+ kMaxTypeMatchingCalls)
+ return false;
+
+ // Copy the profile and credit card data, so that it can be accessed on a
+ // separate thread.
+ std::vector<AutofillProfile> copied_profiles;
+ copied_profiles.reserve(profiles.size());
+ for (const AutofillProfile* profile : profiles)
+ copied_profiles.push_back(*profile);
+
+ std::vector<CreditCard> copied_credit_cards;
+ copied_credit_cards.reserve(credit_cards.size());
+ for (const CreditCard* card : credit_cards)
+ copied_credit_cards.push_back(*card);
+
+ // Annotate the form with the source language of the page.
+ form_structure->set_current_page_language(GetCurrentPageLanguage());
+
+ // Attach the Randomized Encoder.
+ form_structure->set_randomized_encoder(
+ RandomizedEncoder::Create(client()->GetPrefs()));
+
+ // Determine |ADDRESS_HOME_STATE| as a possible types for the fields in the
+ // |form_structure| with the help of |AlternativeStateNameMap|.
+ // |AlternativeStateNameMap| can only be accessed on the main UI thread.
+ PreProcessStateMatchingTypes(copied_profiles, form_structure.get());
+
+ // Note that ownership of |form_structure| is passed to the second task,
+ // using |base::Owned|. We MUST temporarily hang on to the raw form pointer
+ // 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::ThreadPool::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::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(
+ &BrowserAutofillManager::DeterminePossibleFieldTypesForUpload,
+ copied_profiles, copied_credit_cards, last_unlocked_credit_card_cvc_,
+ app_locale_, raw_form),
+ base::BindOnce(&BrowserAutofillManager::UploadFormDataAsyncCallback,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(form_structure.release()),
+ initial_interaction_timestamp_,
+ AutofillTickClock::NowTicks(), observed_submission));
+ return true;
+}
+
+void BrowserAutofillManager::UpdatePendingForm(const FormData& form) {
+ // Process the current pending form if different than supplied |form|.
+ if (pending_form_data_ && !pending_form_data_->SameFormAs(form)) {
+ ProcessPendingFormForUpload();
+ }
+ // A new pending form is assigned.
+ pending_form_data_ = std::make_unique<FormData>(form);
+}
+
+void BrowserAutofillManager::ProcessPendingFormForUpload() {
+ if (!pending_form_data_)
+ return;
+
+ // We get the FormStructure corresponding to |pending_form_data_|, used in the
+ // upload process. |pending_form_data_| is reset.
+ std::unique_ptr<FormStructure> upload_form =
+ ValidateSubmittedForm(*pending_form_data_);
+ pending_form_data_.reset();
+ if (!upload_form)
+ return;
+
+ MaybeStartVoteUploadProcess(std::move(upload_form),
+ /*observed_submission=*/false);
+}
+
+void BrowserAutofillManager::DidSuppressPopup(const FormData& form,
+ const FormFieldData& field) {
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return;
+
+ auto* logger = GetEventFormLogger(autofill_field->Type().group());
+ if (logger)
+ logger->OnPopupSuppressed(*form_structure, *autofill_field);
+}
+
+void BrowserAutofillManager::OnTextFieldDidChangeImpl(
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box,
+ const TimeTicks timestamp) {
+ if (test_delegate_)
+ test_delegate_->OnTextFieldChanged();
+
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return;
+
+ UpdatePendingForm(form);
+
+ uint32_t profile_form_bitmask = 0;
+ if (!user_did_type_ || autofill_field->is_autofilled) {
+ form_interactions_ukm_logger()->LogTextFieldDidChange(*form_structure,
+ *autofill_field);
+ profile_form_bitmask = data_util::DetermineGroups(*form_structure);
+ }
+
+ if (!autofill_field->is_autofilled) {
+ auto* logger = GetEventFormLogger(autofill_field->Type().group());
+ if (logger)
+ logger->OnTypedIntoNonFilledField();
+ }
+
+ if (!user_did_type_) {
+ user_did_type_ = true;
+ AutofillMetrics::LogUserHappinessMetric(
+ AutofillMetrics::USER_DID_TYPE, autofill_field->Type().group(),
+ client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
+ }
+
+ if (autofill_field->is_autofilled) {
+ autofill_field->is_autofilled = false;
+ autofill_field->set_previously_autofilled(true);
+ AutofillMetrics::LogUserHappinessMetric(
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD,
+ autofill_field->Type().group(),
+ client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
+
+ auto* logger = GetEventFormLogger(autofill_field->Type().group());
+ if (logger)
+ logger->OnEditedAutofilledField();
+
+ if (!user_did_edit_autofilled_field_) {
+ user_did_edit_autofilled_field_ = true;
+ AutofillMetrics::LogUserHappinessMetric(
+ AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD_ONCE,
+ autofill_field->Type().group(),
+ client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
+ }
+ }
+
+ UpdateInitialInteractionTimestamp(timestamp);
+}
+
+bool BrowserAutofillManager::IsFormNonSecure(const FormData& form) const {
+ return IsFormOrClientNonSecure(client(), form);
+}
+
+void BrowserAutofillManager::OnQueryFormFieldAutofillImpl(
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& transformed_box,
+ bool autoselect_first_suggestion) {
+ if (base::FeatureList::IsEnabled(features::kAutofillDisableFilling)) {
+ return;
+ }
+
+ SetDataList(field.datalist_values, field.datalist_labels);
+ external_delegate_->OnQuery(query_id, form, field, transformed_box);
+
+ std::vector<Suggestion> suggestions;
+ SuggestionsContext context;
+ GetAvailableSuggestions(form, field, &suggestions, &context);
+
+ if (context.is_autofill_available) {
+ switch (context.suppress_reason) {
+ case SuppressReason::kNotSuppressed:
+ break;
+
+ case SuppressReason::kAblation:
+ autocomplete_history_manager_->CancelPendingQueries(this);
+ external_delegate_->OnSuggestionsReturned(query_id, suggestions,
+ autoselect_first_suggestion);
+ LogSuppressReason(log_manager(), "Ablation experiment");
+ return;
+
+ case SuppressReason::kInsecureForm:
+ LogSuppressReason(log_manager(), "Insecure form");
+ return;
+ case SuppressReason::kAutocompleteOff:
+ LogSuppressReason(log_manager(), "autocomplete=off");
+ return;
+ }
+
+ if (!suggestions.empty()) {
+ if (context.is_filling_credit_card) {
+ AutofillMetrics::LogIsQueriedCreditCardFormSecure(
+ context.is_context_secure);
+ }
+
+ // The first time we show suggestions on this page, log the number of
+ // suggestions available.
+ // TODO(mathp): Differentiate between number of suggestions available
+ // (current metric) and number shown to the user.
+ if (!has_logged_address_suggestions_count_) {
+ AutofillMetrics::LogAddressSuggestionsCount(suggestions.size());
+ has_logged_address_suggestions_count_ = true;
+ }
+ }
+ }
+
+ // If there are no Autofill suggestions, consider showing Autocomplete
+ // suggestions. We will not show Autocomplete suggestions for a field that
+ // specifies autocomplete=off (or an unrecognized type), a field for which we
+ // will show the credit card signin promo, a field that we think is a
+ // credit card expiration, cvc or number, or on forms displayed on secure
+ // (i.e. HTTPS) sites that submit insecurely (over HTTP).
+ if (suggestions.empty() && !ShouldShowCreditCardSigninPromo(form, field) &&
+ field.should_autocomplete &&
+ !(context.focused_field &&
+ (autofill::data_util::IsCreditCardExpirationType(
+ context.focused_field->Type().GetStorableType()) ||
+ context.focused_field->Type().html_type() == HTML_TYPE_UNRECOGNIZED ||
+ context.focused_field->Type().GetStorableType() ==
+ CREDIT_CARD_NUMBER ||
+ context.focused_field->Type().GetStorableType() ==
+ CREDIT_CARD_VERIFICATION_CODE)) &&
+ context.suppress_reason != SuppressReason::kInsecureForm) {
+ // Suggestions come back asynchronously, so the Autocomplete manager will
+ // handle sending the results back to the renderer.
+ autocomplete_history_manager_->OnGetAutocompleteSuggestions(
+ query_id, client()->IsAutocompleteEnabled(),
+ autoselect_first_suggestion, field.name, field.value,
+ field.form_control_type, weak_ptr_factory_.GetWeakPtr());
+ return;
+ }
+
+ // Send Autofill suggestions (could be an empty list).
+ autocomplete_history_manager_->CancelPendingQueries(this);
+ external_delegate_->OnSuggestionsReturned(query_id, suggestions,
+ autoselect_first_suggestion,
+ context.should_display_gpay_logo);
+}
+
+bool BrowserAutofillManager::WillFillCreditCardNumber(
+ const FormData& form,
+ const FormFieldData& field) {
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return false;
+
+ if (autofill_field->Type().GetStorableType() == CREDIT_CARD_NUMBER)
+ return true;
+
+ DCHECK_EQ(form_structure->field_count(), form.fields.size());
+ for (size_t i = 0; i < form_structure->field_count(); ++i) {
+ if (form_structure->field(i)->section == autofill_field->section &&
+ form_structure->field(i)->Type().GetStorableType() ==
+ CREDIT_CARD_NUMBER &&
+ form.fields[i].value.empty() && !form.fields[i].is_autofilled) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void BrowserAutofillManager::FillOrPreviewCreditCardForm(
+ AutofillDriver::RendererFormDataAction action,
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const CreditCard* credit_card) {
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return;
+
+ credit_card_ = credit_card ? *credit_card : CreditCard();
+ bool is_preview = action != AutofillDriver::FORM_DATA_ACTION_FILL;
+ bool should_fetch_card = !is_preview && WillFillCreditCardNumber(form, field);
+
+ if (should_fetch_card) {
+ credit_card_form_event_logger_->OnDidSelectCardSuggestion(
+ credit_card_, *form_structure, sync_state_);
+
+ credit_card_action_ = action;
+ credit_card_query_id_ = query_id;
+ credit_card_form_ = form;
+ credit_card_field_ = field;
+
+ // CreditCardAccessManager::FetchCreditCard() will call
+ // OnCreditCardFetched() in this class after successfully fetching the card.
+ credit_card_access_manager_->FetchCreditCard(
+ credit_card, weak_ptr_factory_.GetWeakPtr(),
+ form_structure->form_parsed_timestamp());
+ return;
+ }
+
+ if (!is_preview) {
+ credit_card_form_event_logger_->OnDidFillSuggestion(
+ credit_card_, *form_structure, *autofill_field, sync_state_);
+ }
+
+ FillOrPreviewDataModelForm(action, query_id, form, field, &credit_card_,
+ /*cvc=*/nullptr, form_structure, autofill_field);
+}
+
+void BrowserAutofillManager::FillOrPreviewProfileForm(
+ AutofillDriver::RendererFormDataAction action,
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const AutofillProfile& profile) {
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return;
+ if (action == AutofillDriver::FORM_DATA_ACTION_FILL) {
+ address_form_event_logger_->OnDidFillSuggestion(
+ profile, *form_structure, *autofill_field, sync_state_);
+ }
+
+ FillOrPreviewDataModelForm(action, query_id, form, field, &profile,
+ /*cvc=*/nullptr, form_structure, autofill_field);
+}
+
+void BrowserAutofillManager::FillOrPreviewForm(
+ AutofillDriver::RendererFormDataAction action,
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ int unique_id) {
+ if (!IsValidFormData(form) || !IsValidFormFieldData(field))
+ return;
+
+ // NOTE: RefreshDataModels may invalidate |data_model|. Thus it must come
+ // before GetProfile or GetCreditCard.
+ if (!RefreshDataModels() || !driver()->RendererIsAvailable())
+ return;
+
+ const AutofillProfile* profile = GetProfile(unique_id);
+ const CreditCard* credit_card = GetCreditCard(unique_id);
+
+ if (credit_card)
+ FillOrPreviewCreditCardForm(action, query_id, form, field, credit_card);
+ else if (profile)
+ FillOrPreviewProfileForm(action, query_id, form, field, *profile);
+}
+
+void BrowserAutofillManager::FillCreditCardForm(int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const CreditCard& credit_card,
+ const std::u16string& cvc) {
+ if (!IsValidFormData(form) || !IsValidFormFieldData(field) ||
+ !driver()->RendererIsAvailable()) {
+ return;
+ }
+
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return;
+
+ FillOrPreviewDataModelForm(AutofillDriver::FORM_DATA_ACTION_FILL, query_id,
+ form, field, &credit_card, &cvc, form_structure,
+ autofill_field);
+}
+
+void BrowserAutofillManager::FillProfileForm(
+ const autofill::AutofillProfile& profile,
+ const FormData& form,
+ const FormFieldData& field) {
+ FillOrPreviewProfileForm(AutofillDriver::FORM_DATA_ACTION_FILL,
+ /*query_id=*/-1, form, field, profile);
+}
+
+void BrowserAutofillManager::OnFocusNoLongerOnForm(bool had_interacted_form) {
+ // For historical reasons, Chrome takes action on this message only if focus
+ // was previously on a form with which the user had interacted.
+ // TODO(crbug.com/1140473): Remove need for this short-circuit.
+ if (!had_interacted_form)
+ return;
+
+ ProcessPendingFormForUpload();
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ // There is no way of determining whether ChromeVox is in use, so assume it's
+ // being used.
+ external_delegate_->OnAutofillAvailabilityEvent(
+ mojom::AutofillState::kNoSuggestions);
+#else
+ if (external_delegate_->HasActiveScreenReader()) {
+ external_delegate_->OnAutofillAvailabilityEvent(
+ mojom::AutofillState::kNoSuggestions);
+ }
+#endif
+}
+
+void BrowserAutofillManager::OnFocusOnFormFieldImpl(
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) {
+ // Notify installed screen readers if the focus is on a field for which there
+ // are suggestions to present. Ignore if a screen reader is not present. If
+ // the platform is ChromeOS, then assume ChromeVox is in use as there is no
+ // way of determining whether it's being used from this point in the code.
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+ if (!external_delegate_->HasActiveScreenReader())
+ return;
+#endif
+
+ // TODO(https://crbug.com/848427): Add metrics for performance impact.
+ std::vector<Suggestion> suggestions;
+ SuggestionsContext context;
+ GetAvailableSuggestions(form, field, &suggestions, &context);
+
+ external_delegate_->OnAutofillAvailabilityEvent(
+ (context.suppress_reason == SuppressReason::kNotSuppressed &&
+ !suggestions.empty())
+ ? mojom::AutofillState::kAutofillAvailable
+ : mojom::AutofillState::kNoSuggestions);
+}
+
+void BrowserAutofillManager::OnSelectControlDidChangeImpl(
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) {
+ // TODO(crbug.com/814961): Handle select control change.
+}
+
+void BrowserAutofillManager::OnDidPreviewAutofillFormData() {
+ if (test_delegate_)
+ test_delegate_->DidPreviewFormData();
+}
+
+void BrowserAutofillManager::OnDidFillAutofillFormData(
+ const FormData& form,
+ const TimeTicks timestamp) {
+ if (test_delegate_)
+ test_delegate_->DidFillFormData();
+
+ UpdatePendingForm(form);
+
+ // Find the FormStructure that corresponds to |form|. Use default form type if
+ // form is not present in our cache, which will happen rarely.
+
+ FormStructure* form_structure = FindCachedFormByRendererId(form.global_id());
+ DenseSet<FormType> form_types;
+ if (form_structure) {
+ form_types = form_structure->GetFormTypes();
+ }
+
+ uint32_t profile_form_bitmask =
+ form_structure ? data_util::DetermineGroups(*form_structure) : 0;
+
+ AutofillMetrics::LogUserHappinessMetric(
+ AutofillMetrics::USER_DID_AUTOFILL, form_types,
+ client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
+ if (!user_did_autofill_) {
+ user_did_autofill_ = true;
+ AutofillMetrics::LogUserHappinessMetric(
+ AutofillMetrics::USER_DID_AUTOFILL_ONCE, form_types,
+ client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
+ }
+
+ UpdateInitialInteractionTimestamp(timestamp);
+}
+
+void BrowserAutofillManager::DidShowSuggestions(bool has_autofill_suggestions,
+ const FormData& form,
+ const FormFieldData& field) {
+ if (test_delegate_)
+ test_delegate_->DidShowSuggestions();
+
+ if (!has_autofill_suggestions) {
+ // If suggestions are not from Autofill, then it means they are from
+ // Autocomplete.
+ AutofillMetrics::OnAutocompleteSuggestionsShown();
+ return;
+ }
+
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return;
+
+ uint32_t profile_form_bitmask = data_util::DetermineGroups(*form_structure);
+ AutofillMetrics::LogUserHappinessMetric(
+ AutofillMetrics::SUGGESTIONS_SHOWN, autofill_field->Type().group(),
+ client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
+
+ if (!did_show_suggestions_) {
+ did_show_suggestions_ = true;
+ AutofillMetrics::LogUserHappinessMetric(
+ AutofillMetrics::SUGGESTIONS_SHOWN_ONCE, autofill_field->Type().group(),
+ client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
+ }
+
+ auto* logger = GetEventFormLogger(autofill_field->Type().group());
+ if (logger) {
+ logger->OnDidShowSuggestions(*form_structure, *autofill_field,
+ form_structure->form_parsed_timestamp(),
+ sync_state_, driver()->IsIncognito());
+ }
+
+ if (autofill_field->Type().group() == FieldTypeGroup::kCreditCard &&
+ base::FeatureList::IsEnabled(
+ features::kAutofillCreditCardAuthentication)) {
+ credit_card_access_manager_->PrepareToFetchCreditCard();
+ }
+}
+
+void BrowserAutofillManager::OnHidePopup() {
+ if (!IsAutofillEnabled())
+ return;
+
+ autocomplete_history_manager_->CancelPendingQueries(this);
+ client()->HideAutofillPopup(PopupHidingReason::kRendererEvent);
+}
+
+bool BrowserAutofillManager::GetDeletionConfirmationText(
+ const std::u16string& value,
+ int identifier,
+ std::u16string* title,
+ std::u16string* body) {
+ if (identifier == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) {
+ if (title)
+ title->assign(value);
+ if (body) {
+ body->assign(l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_DELETE_AUTOCOMPLETE_SUGGESTION_CONFIRMATION_BODY));
+ }
+
+ return true;
+ }
+
+ if (identifier < 0)
+ return false;
+
+ const CreditCard* credit_card = GetCreditCard(identifier);
+ const AutofillProfile* profile = GetProfile(identifier);
+
+ if (credit_card) {
+ return credit_card_access_manager_->GetDeletionConfirmationText(
+ credit_card, title, body);
+ }
+
+ if (profile) {
+ if (profile->record_type() != AutofillProfile::LOCAL_PROFILE)
+ return false;
+
+ if (title) {
+ std::u16string street_address = profile->GetRawInfo(ADDRESS_HOME_CITY);
+ if (!street_address.empty())
+ title->swap(street_address);
+ else
+ title->assign(value);
+ }
+ if (body) {
+ body->assign(l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_DELETE_PROFILE_SUGGESTION_CONFIRMATION_BODY));
+ }
+
+ return true;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+bool BrowserAutofillManager::RemoveAutofillProfileOrCreditCard(int unique_id) {
+ const CreditCard* credit_card = GetCreditCard(unique_id);
+ if (credit_card) {
+ return credit_card_access_manager_->DeleteCard(credit_card);
+ }
+
+ const AutofillProfile* profile = GetProfile(unique_id);
+ if (profile) {
+ bool is_local = profile->record_type() == AutofillProfile::LOCAL_PROFILE;
+ if (is_local)
+ personal_data_->RemoveByGUID(profile->guid());
+
+ return is_local;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+void BrowserAutofillManager::RemoveAutocompleteEntry(
+ const std::u16string& name,
+ const std::u16string& value) {
+ autocomplete_history_manager_->OnRemoveAutocompleteEntry(name, value);
+}
+
+void BrowserAutofillManager::OnAutocompleteEntrySelected(
+ const std::u16string& value) {
+ autocomplete_history_manager_->OnAutocompleteEntrySelected(value);
+}
+
+void BrowserAutofillManager::OnUserHideSuggestions(const FormData& form,
+ const FormFieldData& field) {
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return;
+
+ auto* logger = GetEventFormLogger(autofill_field->Type().group());
+ if (logger)
+ logger->OnUserHideSuggestions(*form_structure, *autofill_field);
+}
+
+bool BrowserAutofillManager::ShouldClearPreviewedForm() {
+ return credit_card_access_manager_->ShouldClearPreviewedForm();
+}
+
+payments::FullCardRequest*
+BrowserAutofillManager::GetOrCreateFullCardRequest() {
+ return credit_card_access_manager_->GetOrCreateCVCAuthenticator()
+ ->GetFullCardRequest();
+}
+
+base::WeakPtr<payments::FullCardRequest::UIDelegate>
+BrowserAutofillManager::GetAsFullCardRequestUIDelegate() {
+ return credit_card_access_manager_->GetOrCreateCVCAuthenticator()
+ ->GetAsFullCardRequestUIDelegate();
+}
+
+void BrowserAutofillManager::SetTestDelegate(
+ BrowserAutofillManagerTestDelegate* delegate) {
+ test_delegate_ = delegate;
+}
+
+void BrowserAutofillManager::SetDataList(
+ const std::vector<std::u16string>& values,
+ const std::vector<std::u16string>& labels) {
+ if (!IsValidString16Vector(values) || !IsValidString16Vector(labels) ||
+ values.size() != labels.size())
+ return;
+
+ external_delegate_->SetCurrentDataListValues(values, labels);
+}
+
+void BrowserAutofillManager::SelectFieldOptionsDidChange(const FormData& form) {
+ // Look for a cached version of the form. It will be a null pointer if none is
+ // found, which is fine.
+ FormStructure* cached_form = FindCachedFormByRendererId(form.global_id());
+
+ FormStructure* form_structure = ParseForm(form, cached_form);
+ if (!form_structure)
+ return;
+
+ if (ShouldTriggerRefill(*form_structure))
+ TriggerRefill(form);
+}
+
+void BrowserAutofillManager::PropagateAutofillPredictions(
+ content::RenderFrameHost* rfh,
+ const std::vector<FormStructure*>& forms) {
+ client()->PropagateAutofillPredictions(rfh, forms);
+}
+
+void BrowserAutofillManager::OnCreditCardFetched(bool did_succeed,
+ const CreditCard* credit_card,
+ const std::u16string& cvc) {
+ if (!did_succeed) {
+ driver()->RendererShouldClearPreviewedForm();
+ return;
+ }
+
+ last_unlocked_credit_card_cvc_ = cvc;
+
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!GetCachedFormAndField(credit_card_form_, credit_card_field_,
+ &form_structure, &autofill_field)) {
+ return;
+ }
+
+ // The originally selected masked card is |credit_card_|. So we must log
+ // |credit_card_| as opposed to |credit_card| to correctly indicate that the
+ // user filled the form using a masked card suggestion.
+ credit_card_form_event_logger_->OnDidFillSuggestion(
+ credit_card_, *form_structure, *autofill_field, sync_state_);
+
+ DCHECK(credit_card);
+
+ // If synced down card is a virtual card, let the client know so that it can
+ // show the UI to help user to manually fill the form, if needed.
+ if (credit_card->record_type() == CreditCard::VIRTUAL_CARD)
+ client()->OnVirtualCardFetched(credit_card, cvc);
+
+ FillCreditCardForm(credit_card_query_id_, credit_card_form_,
+ credit_card_field_, *credit_card, cvc);
+ if (credit_card->record_type() == CreditCard::FULL_SERVER_CARD ||
+ credit_card->record_type() == CreditCard::VIRTUAL_CARD) {
+ credit_card_access_manager_->CacheUnmaskedCardInfo(*credit_card, cvc);
+ }
+}
+
+void BrowserAutofillManager::OnDidEndTextFieldEditing() {
+ external_delegate_->DidEndTextFieldEditing();
+}
+
+bool BrowserAutofillManager::IsAutofillEnabled() const {
+ return IsAutofillProfileEnabled() || IsAutofillCreditCardEnabled();
+}
+
+bool BrowserAutofillManager::IsAutofillProfileEnabled() const {
+ return ::autofill::prefs::IsAutofillProfileEnabled(client()->GetPrefs());
+}
+
+bool BrowserAutofillManager::IsAutofillCreditCardEnabled() const {
+ return ::autofill::prefs::IsAutofillCreditCardEnabled(client()->GetPrefs());
+}
+
+const FormData& BrowserAutofillManager::last_query_form() const {
+ return external_delegate_->query_form();
+}
+
+bool BrowserAutofillManager::ShouldUploadForm(const FormStructure& form) {
+ return IsAutofillEnabled() && !driver()->IsIncognito() &&
+ form.ShouldBeUploaded();
+}
+
+// AutocompleteHistoryManager::SuggestionsHandler implementation
+void BrowserAutofillManager::OnSuggestionsReturned(
+ int query_id,
+ bool autoselect_first_suggestion,
+ const std::vector<Suggestion>& suggestions) {
+ external_delegate_->OnSuggestionsReturned(query_id, suggestions,
+ autoselect_first_suggestion);
+}
+
+// Note that |submitted_form| is passed as a pointer rather than as a reference
+// so that we can get memory management right across threads. Note also that we
+// explicitly pass in all the time stamps of interest, as the cached ones might
+// get reset before this method executes.
+void BrowserAutofillManager::UploadFormDataAsyncCallback(
+ const FormStructure* submitted_form,
+ const TimeTicks& interaction_time,
+ const TimeTicks& submission_time,
+ bool observed_submission) {
+ if (submitted_form->ShouldRunHeuristics() ||
+ submitted_form->ShouldBeQueried()) {
+ submitted_form->LogQualityMetrics(
+ submitted_form->form_parsed_timestamp(), interaction_time,
+ submission_time, form_interactions_ukm_logger(), did_show_suggestions_,
+ observed_submission);
+ }
+ if (submitted_form->ShouldBeUploaded())
+ UploadFormData(*submitted_form, observed_submission);
+}
+
+void BrowserAutofillManager::UploadFormData(const FormStructure& submitted_form,
+ bool observed_submission) {
+ if (!download_manager())
+ return;
+
+ // Check if the form is among the forms that were recently auto-filled.
+ bool was_autofilled = false;
+ std::string form_signature = submitted_form.FormSignatureAsStr();
+ for (const std::string& cur_sig : autofilled_form_signatures_) {
+ if (cur_sig == form_signature) {
+ was_autofilled = true;
+ break;
+ }
+ }
+
+ 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,
+ /*login_form_signature=*/std::string(), observed_submission,
+ client()->GetPrefs());
+}
+
+void BrowserAutofillManager::Reset() {
+ // Note that upload_request_ is not reset here because the prompt to
+ // save a card is shown after page navigation.
+ ProcessPendingFormForUpload();
+ DCHECK(!pending_form_data_);
+ AutofillManager::Reset();
+ address_form_event_logger_ = std::make_unique<AddressFormEventLogger>(
+ driver()->IsInMainFrame(), form_interactions_ukm_logger(), client());
+ credit_card_form_event_logger_ = std::make_unique<CreditCardFormEventLogger>(
+ driver()->IsInMainFrame(), form_interactions_ukm_logger(), personal_data_,
+ client());
+ credit_card_access_manager_ = std::make_unique<CreditCardAccessManager>(
+ driver(), client(), personal_data_, credit_card_form_event_logger_.get());
+
+ has_logged_autofill_enabled_ = false;
+ has_logged_address_suggestions_count_ = false;
+ did_show_suggestions_ = false;
+ user_did_type_ = false;
+ user_did_autofill_ = false;
+ user_did_edit_autofilled_field_ = false;
+ credit_card_ = CreditCard();
+ 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();
+ filling_context_by_global_id_.clear();
+ filling_context_by_unique_name_.clear();
+}
+
+bool BrowserAutofillManager::RefreshDataModels() {
+ if (!IsAutofillEnabled())
+ return false;
+
+ // No autofill data to return if the profiles are empty.
+ const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
+ credit_card_access_manager_->UpdateCreditCardFormEventLogger();
+
+ // Updating the FormEventLogger for addresses.
+ {
+ size_t server_record_type_count = 0;
+ size_t local_record_type_count = 0;
+ for (AutofillProfile* profile : profiles) {
+ if (profile->record_type() == AutofillProfile::LOCAL_PROFILE)
+ local_record_type_count++;
+ else if (profile->record_type() == AutofillProfile::SERVER_PROFILE)
+ server_record_type_count++;
+ }
+ address_form_event_logger_->set_server_record_type_count(
+ server_record_type_count);
+ address_form_event_logger_->set_local_record_type_count(
+ local_record_type_count);
+ }
+
+ return !profiles.empty() ||
+ !credit_card_access_manager_->GetCreditCards().empty();
+}
+
+CreditCard* BrowserAutofillManager::GetCreditCard(int unique_id) {
+ // Unpack the |unique_id| into component parts.
+ std::string credit_card_id;
+ std::string profile_id;
+ SplitFrontendID(unique_id, &credit_card_id, &profile_id);
+ return credit_card_access_manager_->GetCreditCard(credit_card_id);
+}
+
+AutofillProfile* BrowserAutofillManager::GetProfile(int unique_id) {
+ // Unpack the |unique_id| into component parts.
+ std::string credit_card_id;
+ std::string profile_id;
+ SplitFrontendID(unique_id, &credit_card_id, &profile_id);
+
+ if (base::IsValidGUID(profile_id))
+ return personal_data_->GetProfileByGUID(profile_id);
+ return nullptr;
+}
+
+void BrowserAutofillManager::FillOrPreviewDataModelForm(
+ AutofillDriver::RendererFormDataAction action,
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ absl::variant<const AutofillProfile*, const CreditCard*>
+ profile_or_credit_card,
+ const std::u16string* optional_cvc,
+ FormStructure* form_structure,
+ AutofillField* autofill_field,
+ bool is_refill) {
+ bool is_credit_card =
+ absl::holds_alternative<const CreditCard*>(profile_or_credit_card);
+
+ DCHECK(is_credit_card || !optional_cvc);
+ DCHECK(form_structure);
+ DCHECK(autofill_field);
+
+ LogBuffer buffer;
+ buffer << "is credit card section: " << is_credit_card << Br{};
+ buffer << "is refill: " << is_refill << Br{};
+ buffer << *form_structure << Br{};
+ buffer << Tag{"table"};
+
+ form_structure->RationalizePhoneNumbersInSection(autofill_field->section);
+
+ FormData result = form;
+
+ // TODO(crbug/1203667#c9): Skip if the form has changed in the meantime, which
+ // may happen with refills.
+ if (form_structure->field_count() != form.fields.size())
+ return;
+
+ if (action == AutofillDriver::FORM_DATA_ACTION_FILL && !is_refill) {
+ SetFillingContext(
+ *form_structure,
+ std::make_unique<FillingContext>(*autofill_field,
+ profile_or_credit_card, optional_cvc));
+ }
+
+ // Only record the types that are filled for an eventual refill if all the
+ // following are satisfied:
+ // The refilling feature is enabled.
+ // A form with the given name is already filled.
+ // A refill has not been attempted for that form yet.
+ // This fill is not a refill attempt.
+ FillingContext* filling_context = GetFillingContext(*form_structure);
+ bool could_attempt_refill = filling_context != nullptr &&
+ !filling_context->attempted_refill && !is_refill;
+
+ // Count the number of times the value of a specific type was filled into the
+ // form.
+ base::flat_map<ServerFieldType, size_t> type_filling_count;
+ type_filling_count.reserve(form_structure->field_count());
+
+ for (size_t i = 0; i < form_structure->field_count(); ++i) {
+ std::string field_number = base::StringPrintf("Field %zu", i);
+
+ // On the renderer, the section is used regardless of the autofill status.
+ result.fields[i].section = form_structure->field(i)->section;
+
+ if (form_structure->field(i)->section != autofill_field->section) {
+ buffer << Tr{} << field_number << "Skipped: not part of filled section";
+ continue;
+ }
+
+ if (form_structure->field(i)->only_fill_when_focused() &&
+ !form_structure->field(i)->SameFieldAs(field)) {
+ buffer << Tr{} << field_number << "Skipped: only fill when focused";
+ continue;
+ }
+
+ // TODO(crbug/1203667#c9): Skip if the form has changed in the meantime,
+ // which may happen with refills.
+ if (!form_structure->field(i)->SameFieldAs(result.fields[i]))
+ continue;
+
+ AutofillField* cached_field = form_structure->field(i);
+ FieldTypeGroup field_group_type = cached_field->Type().group();
+
+ // Don't fill hidden fields, with the exception of <select> fields, for
+ // the sake of filling the synthetic fields.
+ if (!cached_field->IsVisible()) {
+ bool skip = result.fields[i].form_control_type != "select-one";
+ form_interactions_ukm_logger()
+ ->LogHiddenRepresentationalFieldSkipDecision(*form_structure,
+ *cached_field, skip);
+ if (skip) {
+ buffer << Tr{} << field_number << "Skipped: invisible field";
+ continue;
+ }
+ }
+
+ // Do not fill fields that have been edited by the user, except if the field
+ // is empty and its initial value (= cached value) was empty as well. A
+ // similar check is done in ForEachMatchingFormFieldCommon(), which
+ // frequently has false negatives.
+ if ((form.fields[i].properties_mask & kUserTyped) &&
+ (!form.fields[i].value.empty() ||
+ !form_structure->field(i)->value.empty()) &&
+ !cached_field->SameFieldAs(field)) {
+ buffer << Tr{} << field_number
+ << "Skipped: don't fill user-filled fields";
+ continue;
+ }
+
+ // Don't fill previously autofilled fields except the initiating field or
+ // when it's a refill.
+ if (result.fields[i].is_autofilled && !cached_field->SameFieldAs(field) &&
+ !is_refill) {
+ buffer << Tr{} << field_number
+ << "Skipped: don't fill previously filled fields unless during a "
+ "refill";
+ continue;
+ }
+
+ if (field_group_type == FieldTypeGroup::kNoGroup) {
+ buffer << Tr{} << field_number
+ << "Skipped: field type has no fillable group";
+ continue;
+ }
+
+ // On a refill, only fill fields from type groups that were present during
+ // the initial fill.
+ if (is_refill &&
+ !base::Contains(filling_context->type_groups_originally_filled,
+ field_group_type)) {
+ buffer << Tr{} << field_number
+ << "Skipped: in a refill, only fields from the group that was "
+ "filled in the initial fill may be filled";
+ continue;
+ }
+
+ ServerFieldType field_type = cached_field->Type().GetStorableType();
+
+ // Don't fill expired cards expiration date.
+ if (data_util::IsCreditCardExpirationType(field_type) &&
+ (is_credit_card && absl::get<const CreditCard*>(profile_or_credit_card)
+ ->IsExpired(AutofillClock::Now()))) {
+ buffer << Tr{} << field_number
+ << "Skipped: don't fill expiration date of expired cards";
+ continue;
+ }
+
+ // A field with a specific type is only allowed to be filled a limited
+ // number of times given by |TypeValueFormFillingLimit(field_type)|.
+ if (++type_filling_count[field_type] >
+ TypeValueFormFillingLimit(field_type)) {
+ buffer << Tr{} << field_number
+ << "Skipped: field-type filling-limit reached";
+ continue;
+ }
+
+ if (could_attempt_refill)
+ filling_context->type_groups_originally_filled.insert(field_group_type);
+
+ // Must match ForEachMatchingFormField() in form_autofill_util.cc.
+ // Only notify autofilling of empty fields and the field that initiated
+ // the filling (note that "select-one" controls may not be empty but will
+ // still be autofilled).
+ bool should_notify = !is_credit_card &&
+ (result.fields[i].SameFieldAs(field) ||
+ result.fields[i].form_control_type == "select-one" ||
+ result.fields[i].value.empty());
+
+ bool has_value_before = !result.fields[i].value.empty();
+ bool is_autofilled_before = result.fields[i].is_autofilled;
+
+ const std::u16string kEmptyCvc{};
+ std::string failure_to_fill; // Reason for failing to fill.
+
+ // Fill the non-empty value from |profile_or_credit_card| into the result
+ // vector, which will be sent to the renderer.
+ FillFieldWithValue(cached_field, profile_or_credit_card, &result.fields[i],
+ should_notify, optional_cvc ? *optional_cvc : kEmptyCvc,
+ data_util::DetermineGroups(*form_structure),
+ &failure_to_fill);
+
+ bool has_value_after = !result.fields[i].value.empty();
+ bool is_autofilled_after = result.fields[i].is_autofilled;
+
+ buffer << Tr{} << field_number
+ << base::StringPrintf(
+ "Fillable - has value: %d->%d; autofilled: %d->%d. %s",
+ has_value_before, is_autofilled_before, has_value_after,
+ is_autofilled_after, failure_to_fill.c_str());
+
+ if (!cached_field->IsVisible() && result.fields[i].is_autofilled)
+ AutofillMetrics::LogHiddenOrPresentationalSelectFieldsFilled();
+ }
+ buffer << CTag{"table"};
+
+ autofilled_form_signatures_.push_front(form_structure->FormSignatureAsStr());
+ // Only remember the last few forms that we've seen, both to avoid false
+ // positives and to avoid wasting memory.
+ if (autofilled_form_signatures_.size() > kMaxRecentFormSignaturesToRemember)
+ autofilled_form_signatures_.pop_back();
+
+ // Note that this may invalidate |profile_or_credit_card|.
+ if (action == AutofillDriver::FORM_DATA_ACTION_FILL && !is_refill)
+ personal_data_->RecordUseOf(profile_or_credit_card);
+
+ if (log_manager()) {
+ log_manager()->Log() << LoggingScope::kFilling
+ << LogMessage::kSendFillingData << Br{}
+ << std::move(buffer);
+ }
+ driver()->SendFormDataToRenderer(query_id, action, result);
+}
+
+std::unique_ptr<FormStructure> BrowserAutofillManager::ValidateSubmittedForm(
+ const FormData& form) {
+ // Ignore forms not present in our cache. These are typically forms with
+ // wonky JavaScript that also makes them not auto-fillable.
+ FormStructure* cached_submitted_form =
+ FindCachedFormByRendererId(form.global_id());
+ if (!cached_submitted_form || !ShouldUploadForm(*cached_submitted_form)) {
+ return nullptr;
+ }
+
+ auto submitted_form = std::make_unique<FormStructure>(form);
+ submitted_form->RetrieveFromCache(*cached_submitted_form,
+ /*should_keep_cached_value=*/false,
+ /*only_server_and_autofill_state=*/false);
+ if (value_from_dynamic_change_form_) {
+ submitted_form->set_value_from_dynamic_change_form(true);
+ }
+
+ return submitted_form;
+}
+
+AutofillField* BrowserAutofillManager::GetAutofillField(
+ const FormData& form,
+ const FormFieldData& field) {
+ if (!personal_data_)
+ return nullptr;
+
+ FormStructure* form_structure = nullptr;
+ AutofillField* autofill_field = nullptr;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return nullptr;
+
+ if (!form_structure->IsAutofillable())
+ return nullptr;
+
+ return autofill_field;
+}
+
+bool BrowserAutofillManager::FormHasAddressField(const FormData& form) {
+ for (const FormFieldData& field : form.fields) {
+ const AutofillField* autofill_field = GetAutofillField(form, field);
+ if (autofill_field &&
+ (autofill_field->Type().group() == FieldTypeGroup::kAddressHome ||
+ autofill_field->Type().group() == FieldTypeGroup::kAddressBilling)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+std::vector<Suggestion> BrowserAutofillManager::GetProfileSuggestions(
+ const FormStructure& form,
+ const FormFieldData& field,
+ const AutofillField& autofill_field) const {
+ address_form_event_logger_->OnDidPollSuggestions(field, sync_state_);
+
+ std::vector<ServerFieldType> field_types(form.field_count());
+ for (size_t i = 0; i < form.field_count(); ++i) {
+ field_types.push_back(form.field(i)->Type().GetStorableType());
+ }
+
+ std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
+ autofill_field.Type(), field.value, field.is_autofilled, field_types);
+
+ // Adjust phone number to display in prefix/suffix case.
+ if (autofill_field.Type().group() == FieldTypeGroup::kPhoneHome) {
+ for (auto& suggestion : suggestions) {
+ const AutofillProfile* profile =
+ personal_data_->GetProfileByGUID(suggestion.backend_id);
+ if (profile) {
+ const std::u16string phone_home_city_and_number =
+ profile->GetInfo(PHONE_HOME_CITY_AND_NUMBER, app_locale_);
+ suggestion.value =
+ FieldFiller::GetPhoneNumberValue(autofill_field, suggestion.value,
+ phone_home_city_and_number, field);
+ }
+ }
+ }
+
+ for (size_t i = 0; i < suggestions.size(); ++i) {
+ suggestions[i].frontend_id =
+ MakeFrontendID(std::string(), suggestions[i].backend_id);
+ }
+ return suggestions;
+}
+
+std::vector<Suggestion> BrowserAutofillManager::GetCreditCardSuggestions(
+ const FormFieldData& field,
+ const AutofillType& type,
+ bool* should_display_gpay_logo) const {
+ credit_card_form_event_logger_->OnDidPollSuggestions(field, sync_state_);
+
+ // The field value is sanitized before attempting to match it to the user's
+ // data.
+ std::vector<Suggestion> suggestions =
+ personal_data_->GetCreditCardSuggestions(
+ type, SanitizeCreditCardFieldValue(field.value),
+ client()->AreServerCardsSupported());
+ if (base::FeatureList::IsEnabled(
+ features::kAutofillEnableOffersInDownstream) &&
+ offer_manager_) {
+ offer_manager_->UpdateSuggestionsWithOffers(client()->GetLastCommittedURL(),
+ suggestions);
+ }
+ *should_display_gpay_logo =
+ credit_card_access_manager_->ShouldDisplayGPayLogo();
+
+ for (size_t i = 0; i < suggestions.size(); i++) {
+ suggestions[i].frontend_id =
+ MakeFrontendID(suggestions[i].backend_id, std::string());
+ }
+
+ credit_card_form_event_logger_->set_suggestions(suggestions);
+ return suggestions;
+}
+
+void BrowserAutofillManager::OnBeforeProcessParsedForms() {
+ has_parsed_forms_ = true;
+
+ // Record the current sync state to be used for metrics on this page.
+ sync_state_ = personal_data_->GetSyncSigninState();
+
+ // Setup the url for metrics that we will collect for this form.
+ form_interactions_ukm_logger()->OnFormsParsed(client()->GetUkmSourceId());
+}
+
+void BrowserAutofillManager::OnFormProcessed(
+ const FormData& form,
+ const FormStructure& form_structure) {
+ if (data_util::ContainsPhone(data_util::DetermineGroups(form_structure))) {
+ has_observed_phone_number_field_ = true;
+ }
+
+ // TODO(crbug.com/869482): avoid logging developer engagement multiple
+ // times for a given form if it or other forms on the page are dynamic.
+ LogDeveloperEngagementUkm(client()->GetUkmRecorder(),
+ client()->GetUkmSourceId(), form_structure);
+
+ for (const auto& field : form_structure) {
+ if (field->Type().html_type() == HTML_TYPE_ONE_TIME_CODE) {
+ has_observed_one_time_code_field_ = true;
+ break;
+ }
+ }
+
+ // Log the type of form that was parsed.
+ DenseSet<FormType> form_types = form_structure.GetFormTypes();
+ bool card_form = base::Contains(form_types, FormType::kCreditCardForm);
+ bool address_form = base::Contains(form_types, FormType::kAddressForm);
+ if (card_form) {
+ credit_card_form_event_logger_->OnDidParseForm(form_structure);
+ }
+ if (address_form) {
+ address_form_event_logger_->OnDidParseForm(form_structure);
+ }
+
+ // If a form with the same name was previously filled, and there has not
+ // been a refill attempt on that form yet, start the process of triggering a
+ // refill.
+ if (ShouldTriggerRefill(form_structure)) {
+ FillingContext* filling_context = GetFillingContext(form_structure);
+ DCHECK(filling_context != nullptr);
+
+ // If a timer for the refill was already running, it means the form
+ // changed again. Stop the timer and start it again.
+ if (filling_context->on_refill_timer.IsRunning())
+ filling_context->on_refill_timer.AbandonAndStop();
+
+ // Start a new timer to trigger refill.
+ filling_context->on_refill_timer.Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kWaitTimeForDynamicFormsMs),
+ base::BindRepeating(&BrowserAutofillManager::TriggerRefill,
+ weak_ptr_factory_.GetWeakPtr(), form));
+ }
+}
+
+void BrowserAutofillManager::OnAfterProcessParsedForms(
+ const DenseSet<FormType>& form_types) {
+ AutofillMetrics::LogUserHappinessMetric(
+ AutofillMetrics::FORMS_LOADED, form_types,
+ client()->GetSecurityLevelForUmaHistograms(),
+ /*profile_form_bitmask=*/0);
+#if defined(OS_IOS)
+ // Log this from same location as AutofillMetrics::FORMS_LOADED to ensure
+ // that KeyboardAccessoryButtonsIOS and UserHappiness UMA metrics will be
+ // directly comparable.
+ KeyboardAccessoryMetricsLogger::OnFormsLoaded();
+#endif
+}
+
+int BrowserAutofillManager::BackendIDToInt(
+ const std::string& backend_id) const {
+ if (!base::IsValidGUID(backend_id))
+ return 0;
+
+ const auto found = backend_to_int_map_.find(backend_id);
+ if (found == backend_to_int_map_.end()) {
+ // Unknown one, make a new entry.
+ int int_id = backend_to_int_map_.size() + 1;
+ backend_to_int_map_[backend_id] = int_id;
+ int_to_backend_map_[int_id] = backend_id;
+ return int_id;
+ }
+ return found->second;
+}
+
+std::string BrowserAutofillManager::IntToBackendID(int int_id) const {
+ if (int_id == 0)
+ return std::string();
+
+ const auto found = int_to_backend_map_.find(int_id);
+ if (found == int_to_backend_map_.end()) {
+ NOTREACHED();
+ return std::string();
+ }
+ return found->second;
+}
+
+// When sending IDs (across processes) to the renderer we pack credit card and
+// profile IDs into a single integer. Credit card IDs are sent in the high
+// word and profile IDs are sent in the low word.
+int BrowserAutofillManager::MakeFrontendID(
+ const std::string& cc_backend_id,
+ const std::string& profile_backend_id) const {
+ int cc_int_id = BackendIDToInt(cc_backend_id);
+ int profile_int_id = BackendIDToInt(profile_backend_id);
+
+ // Should fit in signed 16-bit integers. We use 16-bits each when combining
+ // below, and negative frontend IDs have special meaning so we can never use
+ // the high bit.
+ DCHECK(cc_int_id <= std::numeric_limits<int16_t>::max());
+ DCHECK(profile_int_id <= std::numeric_limits<int16_t>::max());
+
+ // Put CC in the high half of the bits.
+ return (cc_int_id << std::numeric_limits<uint16_t>::digits) | profile_int_id;
+}
+
+// When receiving IDs (across processes) from the renderer we unpack credit card
+// and profile IDs from a single integer. Credit card IDs are stored in the
+// high word and profile IDs are stored in the low word.
+void BrowserAutofillManager::SplitFrontendID(
+ int frontend_id,
+ std::string* cc_backend_id,
+ std::string* profile_backend_id) const {
+ int cc_int_id = (frontend_id >> std::numeric_limits<uint16_t>::digits) &
+ std::numeric_limits<uint16_t>::max();
+ int profile_int_id = frontend_id & std::numeric_limits<uint16_t>::max();
+
+ *cc_backend_id = IntToBackendID(cc_int_id);
+ *profile_backend_id = IntToBackendID(profile_int_id);
+}
+
+void BrowserAutofillManager::UpdateInitialInteractionTimestamp(
+ const TimeTicks& interaction_timestamp) {
+ if (initial_interaction_timestamp_.is_null() ||
+ interaction_timestamp < initial_interaction_timestamp_) {
+ initial_interaction_timestamp_ = interaction_timestamp;
+ }
+}
+
+// static
+void BrowserAutofillManager::DeterminePossibleFieldTypesForUpload(
+ const std::vector<AutofillProfile>& profiles,
+ const std::vector<CreditCard>& credit_cards,
+ const std::u16string& 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.
+ DCHECK_EQ(1u, field->possible_types().size());
+ DCHECK_EQ(PASSWORD, *field->possible_types().begin());
+ continue;
+ }
+
+ ServerFieldTypeSet matching_types;
+ std::u16string value;
+ base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
+
+ for (const AutofillProfile& profile : profiles) {
+ ServerFieldTypeValidityStateMap matching_types_validities;
+ profile.GetMatchingTypesAndValidities(value, app_locale, &matching_types,
+ &matching_types_validities);
+ field->add_possible_types_validities(matching_types_validities);
+ }
+
+ // TODO(crbug/880531) set possible_types_validities for credit card too.
+ for (const CreditCard& card : credit_cards) {
+ card.GetMatchingTypes(value, app_locale, &matching_types);
+ }
+
+ if (IsUPIVirtualPaymentAddress(value))
+ matching_types.insert(UPI_VPA);
+
+ if (field->state_is_a_matching_type())
+ matching_types.insert(ADDRESS_HOME_STATE);
+
+ if (matching_types.empty()) {
+ matching_types.insert(UNKNOWN_TYPE);
+ ServerFieldTypeValidityStateMap matching_types_validities;
+ matching_types_validities[UNKNOWN_TYPE] = AutofillDataModel::UNVALIDATED;
+ field->add_possible_types_validities(matching_types_validities);
+ }
+
+ field->set_possible_types(matching_types);
+ }
+
+ // As CVCs are not stored, run special heuristics to detect CVC-like values.
+ AutofillField* cvc_field = GetBestPossibleCVCFieldForUpload(
+ *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);
+ }
+
+ BrowserAutofillManager::DisambiguateUploadTypes(submitted_form);
+}
+
+// static
+void BrowserAutofillManager::DisambiguateUploadTypes(FormStructure* form) {
+ for (size_t i = 0; i < form->field_count(); ++i) {
+ AutofillField* field = form->field(i);
+ const ServerFieldTypeSet& upload_types = field->possible_types();
+
+ if (upload_types.size() == 2) {
+ if (upload_types.count(ADDRESS_HOME_LINE1) &&
+ upload_types.count(ADDRESS_HOME_STREET_ADDRESS)) {
+ BrowserAutofillManager::DisambiguateAddressUploadTypes(form, i);
+ } else if (upload_types.count(PHONE_HOME_CITY_AND_NUMBER) &&
+ upload_types.count(PHONE_HOME_WHOLE_NUMBER)) {
+ BrowserAutofillManager::DisambiguatePhoneUploadTypes(form, i);
+ }
+ }
+
+ // In case for credit cards and names there are many other possibilities
+ // because a field can be of type NAME_FULL, NAME_LAST,
+ // NAME_LAST_FIRST/SECOND at the same time.
+ int credit_card_type_count = 0;
+ int name_type_count = 0;
+
+ bool undisambiuatable_types = false;
+ for (const auto& type : upload_types) {
+ switch (AutofillType(type).group()) {
+ case FieldTypeGroup::kCreditCard:
+ ++credit_card_type_count;
+ break;
+ case FieldTypeGroup::kName:
+ ++name_type_count;
+ break;
+ // If there is any other type left, do not disambiguate.
+ default:
+ undisambiuatable_types = true;
+ }
+ if (undisambiuatable_types)
+ break;
+ }
+ if (undisambiuatable_types)
+ continue;
+
+ if (credit_card_type_count == 1 && name_type_count >= 1)
+ BrowserAutofillManager::DisambiguateNameUploadTypes(form, i,
+ upload_types);
+ }
+}
+
+// static
+void BrowserAutofillManager::DisambiguateAddressUploadTypes(
+ FormStructure* form,
+ size_t current_index) {
+ // This happens when we have exactly two possible types, and the profile
+ // has only one address line. Therefore the address line one and the street
+ // address (the whole address) have the same value and match.
+
+ // If the field is followed by a field that is predicted to be an
+ // address line two and is empty, we can safely assume that this field
+ // is an address line one field. Otherwise it's a whole address field.
+
+ ServerFieldTypeSet matching_types;
+ ServerFieldTypeValidityStatesMap matching_types_validities;
+ AutofillField* field = form->field(current_index);
+
+ size_t next_index = current_index + 1;
+ if (next_index < form->field_count() &&
+ form->field(next_index)->Type().GetStorableType() == ADDRESS_HOME_LINE2 &&
+ form->field(next_index)->possible_types().count(EMPTY_TYPE)) {
+ matching_types.insert(ADDRESS_HOME_LINE1);
+ matching_types_validities[ADDRESS_HOME_LINE1] =
+ field->get_validities_for_possible_type(ADDRESS_HOME_LINE1);
+ } else {
+ matching_types.insert(ADDRESS_HOME_STREET_ADDRESS);
+ matching_types_validities[ADDRESS_HOME_STREET_ADDRESS] =
+ field->get_validities_for_possible_type(ADDRESS_HOME_STREET_ADDRESS);
+ }
+
+ field->set_possible_types(matching_types);
+ field->set_possible_types_validities(matching_types_validities);
+}
+
+// static
+void BrowserAutofillManager::DisambiguatePhoneUploadTypes(
+ FormStructure* form,
+ size_t current_index) {
+ // This case happens when we have exactly two possible types, and only for
+ // profiles that have no country code saved. Therefore, both the whole number
+ // and the city code and number have the same value and match.
+
+ // Since the form was submitted, it is safe to assume that the form
+ // didn't require a country code. Thus, only PHONE_HOME_CITY_AND_NUMBER
+ // needs to be uploaded.
+
+ ServerFieldTypeSet matching_types;
+ ServerFieldTypeValidityStatesMap matching_types_validities;
+ AutofillField* field = form->field(current_index);
+
+ matching_types.insert(PHONE_HOME_CITY_AND_NUMBER);
+ matching_types_validities[PHONE_HOME_CITY_AND_NUMBER] =
+ field->get_validities_for_possible_type(PHONE_HOME_CITY_AND_NUMBER);
+
+ field->set_possible_types(matching_types);
+ field->set_possible_types_validities(matching_types_validities);
+}
+
+// static
+void BrowserAutofillManager::DisambiguateNameUploadTypes(
+ FormStructure* form,
+ size_t current_index,
+ const ServerFieldTypeSet& upload_types) {
+ // This case happens when both a profile and a credit card have the same
+ // name, and when we have exactly two possible types.
+
+ // If the ambiguous field has either a previous or next field that is
+ // not name related, use that information to determine whether the field
+ // is a name or a credit card name.
+ // If the ambiguous field has both a previous or next field that is not
+ // name related, if they are both from the same group, use that group to
+ // decide this field's type. Otherwise, there is no safe way to
+ // disambiguate.
+
+ // Look for a previous non name related field.
+ bool has_found_previous_type = false;
+ bool is_previous_credit_card = false;
+ size_t index = current_index;
+ while (index != 0 && !has_found_previous_type) {
+ --index;
+ AutofillField* prev_field = form->field(index);
+ if (!IsNameType(*prev_field)) {
+ has_found_previous_type = true;
+ is_previous_credit_card =
+ prev_field->Type().group() == FieldTypeGroup::kCreditCard;
+ }
+ }
+
+ // Look for a next non name related field.
+ bool has_found_next_type = false;
+ bool is_next_credit_card = false;
+ index = current_index;
+ while (++index < form->field_count() && !has_found_next_type) {
+ AutofillField* next_field = form->field(index);
+ if (!IsNameType(*next_field)) {
+ has_found_next_type = true;
+ is_next_credit_card =
+ next_field->Type().group() == FieldTypeGroup::kCreditCard;
+ }
+ }
+
+ // At least a previous or next field type must have been found in order to
+ // disambiguate this field.
+ if (has_found_previous_type || has_found_next_type) {
+ // If both a previous type and a next type are found and not from the same
+ // name group there is no sure way to disambiguate.
+ if (has_found_previous_type && has_found_next_type &&
+ (is_previous_credit_card != is_next_credit_card)) {
+ return;
+ }
+
+ // Otherwise, use the previous (if it was found) or next field group to
+ // decide whether the field is a name or a credit card name.
+ if (has_found_previous_type) {
+ SelectRightNameType(form->field(current_index), is_previous_credit_card);
+ } else {
+ SelectRightNameType(form->field(current_index), is_next_credit_card);
+ }
+ }
+}
+
+void BrowserAutofillManager::FillFieldWithValue(
+ AutofillField* autofill_field,
+ absl::variant<const AutofillProfile*, const CreditCard*>
+ profile_or_credit_card,
+ FormFieldData* field_data,
+ bool should_notify,
+ const std::u16string& cvc,
+ uint32_t profile_form_bitmask,
+ std::string* failure_to_fill) {
+ if (field_filler_.FillFormField(*autofill_field, profile_or_credit_card,
+ field_data, cvc, failure_to_fill)) {
+ if (failure_to_fill)
+ *failure_to_fill = "Decided to fill";
+ // Mark the cached field as autofilled, so that we can detect when a
+ // user edits an autofilled field (for metrics).
+ autofill_field->is_autofilled = true;
+
+ // Mark the field as autofilled when a non-empty value is assigned to
+ // it. This allows the renderer to distinguish autofilled fields from
+ // fields with non-empty values, such as select-one fields.
+ field_data->is_autofilled = true;
+ AutofillMetrics::LogUserHappinessMetric(
+ AutofillMetrics::FIELD_WAS_AUTOFILLED, autofill_field->Type().group(),
+ client()->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
+
+ if (should_notify) {
+ DCHECK(absl::holds_alternative<const AutofillProfile*>(
+ profile_or_credit_card));
+ const AutofillProfile* profile =
+ absl::get<const AutofillProfile*>(profile_or_credit_card);
+ client()->DidFillOrPreviewField(
+ /*value=*/profile->GetInfo(autofill_field->Type(), app_locale_),
+ /*profile_full_name=*/profile->GetInfo(AutofillType(NAME_FULL),
+ app_locale_));
+ }
+ }
+}
+
+// TODO(crbug/896689): Remove code duplication once experiment is finished.
+void BrowserAutofillManager::SetFillingContext(
+ const FormStructure& form,
+ std::unique_ptr<FillingContext> context) {
+ if (base::FeatureList::IsEnabled(features::kAutofillRefillWithRendererIds)) {
+ filling_context_by_global_id_[form.global_id()] = std::move(context);
+ } else {
+ filling_context_by_unique_name_[form.GetIdentifierForRefill()] =
+ std::move(context);
+ }
+}
+
+// TODO(crbug/896689): Remove code duplication once experiment is finished.
+BrowserAutofillManager::FillingContext*
+BrowserAutofillManager::GetFillingContext(const FormStructure& form) {
+ if (base::FeatureList::IsEnabled(features::kAutofillRefillWithRendererIds)) {
+ auto it = filling_context_by_global_id_.find(form.global_id());
+ return it != filling_context_by_global_id_.end() ? it->second.get()
+ : nullptr;
+ } else {
+ auto it =
+ filling_context_by_unique_name_.find(form.GetIdentifierForRefill());
+ return it != filling_context_by_unique_name_.end() ? it->second.get()
+ : nullptr;
+ }
+}
+
+bool BrowserAutofillManager::ShouldTriggerRefill(
+ const FormStructure& form_structure) {
+ // Should not refill if a form with the same FormGlobalId has not been
+ // filled before.
+ FillingContext* filling_context = GetFillingContext(form_structure);
+ if (filling_context == nullptr)
+ return false;
+
+ address_form_event_logger_->OnDidSeeFillableDynamicForm(sync_state_,
+ form_structure);
+
+ base::TimeTicks now = AutofillTickClock::NowTicks();
+ base::TimeDelta delta = now - filling_context->original_fill_time;
+
+ if (filling_context->attempted_refill &&
+ delta.InMilliseconds() < kLimitBeforeRefillMs) {
+ address_form_event_logger_->OnSubsequentRefillAttempt(sync_state_,
+ form_structure);
+ }
+
+ return !filling_context->attempted_refill &&
+ delta.InMilliseconds() < kLimitBeforeRefillMs;
+}
+
+void BrowserAutofillManager::TriggerRefill(const FormData& form) {
+ FormStructure* form_structure = FindCachedFormByRendererId(form.global_id());
+ if (!form_structure)
+ return;
+
+ DCHECK(form_structure);
+
+ address_form_event_logger_->OnDidRefill(sync_state_, *form_structure);
+
+ FillingContext* filling_context = GetFillingContext(*form_structure);
+
+ // Since GetIdentifierForRefill() is not stable across dynamic changes,
+ // |filling_context_by_unique_name_| may not contain the element anymore.
+ // TODO(crbug/896689): Can be replaced with DCHECK once experiment is over.
+ if (filling_context == nullptr)
+ return;
+
+ // The refill attempt can happen from different paths, some of which happen
+ // after waiting for a while. Therefore, although this condition has been
+ // checked prior to calling TriggerRefill, it may not hold, when we get
+ // here.
+ if (filling_context->attempted_refill)
+ return;
+
+ filling_context->attempted_refill = true;
+
+ // Try to find the field from which the original field originated.
+ // Precedence is given to look up by |filled_field_id|.
+ // If that is unsuccessful, look up is done by |filled_field_signature|.
+ // TODO(crbug/896689): Clean up after feature launch.
+ AutofillField* autofill_field = nullptr;
+ for (const std::unique_ptr<AutofillField>& field : *form_structure) {
+ // TODO(crbug/896689): Clean up once experiment is over.
+ if (((base::FeatureList::IsEnabled(
+ features::kAutofillRefillWithRendererIds) &&
+ field->global_id() == filling_context->filled_field_id) ||
+ (!base::FeatureList::IsEnabled(
+ features::kAutofillRefillWithRendererIds) &&
+ field->unique_name() == filling_context->filled_field_unique_name))) {
+ autofill_field = field.get();
+ break;
+ }
+ }
+
+ // If the field was deleted, look for one with a matching signature. Prefer
+ // visible and newer fields over invisible or older ones.
+ if (base::FeatureList::IsEnabled(features::kAutofillRefillWithRendererIds) &&
+ autofill_field == nullptr) {
+ auto is_better = [](const AutofillField& f, const AutofillField& g) {
+ return std::forward_as_tuple(f.IsVisible(),
+ f.unique_renderer_id.value()) >
+ std::forward_as_tuple(g.IsVisible(), g.unique_renderer_id.value());
+ };
+
+ for (const std::unique_ptr<AutofillField>& field : *form_structure) {
+ if (field->GetFieldSignature() ==
+ filling_context->filled_field_signature) {
+ if (autofill_field == nullptr || is_better(*field, *autofill_field)) {
+ autofill_field = field.get();
+ }
+ }
+ }
+ }
+
+ // If it was not found cancel the refill.
+ if (!autofill_field)
+ return;
+
+ FormFieldData field = *autofill_field;
+ if (absl::holds_alternative<std::pair<CreditCard, std::u16string>>(
+ filling_context->profile_or_credit_card_with_cvc)) {
+ FillOrPreviewDataModelForm(
+ AutofillDriver::RendererFormDataAction::FORM_DATA_ACTION_FILL,
+ /*query_id=*/-1, form, field,
+ &absl::get<std::pair<CreditCard, std::u16string>>(
+ filling_context->profile_or_credit_card_with_cvc)
+ .first,
+ &absl::get<std::pair<CreditCard, std::u16string>>(
+ filling_context->profile_or_credit_card_with_cvc)
+ .second,
+ form_structure, autofill_field,
+ /*is_refill=*/true);
+ }
+ if (absl::holds_alternative<AutofillProfile>(
+ filling_context->profile_or_credit_card_with_cvc)) {
+ FillOrPreviewDataModelForm(
+ AutofillDriver::RendererFormDataAction::FORM_DATA_ACTION_FILL,
+ /*query_id=*/-1, form, field,
+ &absl::get<AutofillProfile>(
+ filling_context->profile_or_credit_card_with_cvc),
+ /*cvc=*/nullptr, form_structure, autofill_field, /*is_refill=*/true);
+ }
+}
+
+void BrowserAutofillManager::GetAvailableSuggestions(
+ const FormData& form,
+ const FormFieldData& field,
+ std::vector<Suggestion>* suggestions,
+ SuggestionsContext* context) {
+ DCHECK(suggestions);
+ DCHECK(context);
+
+ // Need to refresh models before using the form_event_loggers.
+ RefreshDataModels();
+
+ bool got_autofillable_form =
+ GetCachedFormAndField(form, field, &context->form_structure,
+ &context->focused_field) &&
+ // Don't send suggestions or track forms that should not be parsed.
+ context->form_structure->ShouldBeParsed();
+
+ // Log interactions of forms that are autofillable.
+ if (got_autofillable_form) {
+ if (context->focused_field->Type().group() == FieldTypeGroup::kCreditCard) {
+ context->is_filling_credit_card = true;
+ }
+ auto* logger = GetEventFormLogger(context->focused_field->Type().group());
+ if (logger) {
+ logger->OnDidInteractWithAutofillableForm(*(context->form_structure),
+ sync_state_);
+ }
+ }
+
+ // If the feature is enabled and this is a mixed content form, we show a
+ // warning message and don't offer autofill. The warning is shown even if
+ // there are no autofill suggestions available.
+ if (IsFormMixedContent(client(), form) &&
+ base::FeatureList::IsEnabled(
+ features::kAutofillPreventMixedFormsFilling) &&
+ client()->GetPrefs()->GetBoolean(::prefs::kMixedFormsWarningsEnabled)) {
+ suggestions->clear();
+ // If the user begins typing, we interpret that as dismissing the warning.
+ // No suggestions are allowed, but the warning is no longer shown.
+ if (field.DidUserType()) {
+ context->suppress_reason = SuppressReason::kInsecureForm;
+ } else {
+ Suggestion warning_suggestion(
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_MIXED_FORM));
+ warning_suggestion.frontend_id = POPUP_ITEM_ID_MIXED_FORM_MESSAGE;
+ suggestions->emplace_back(warning_suggestion);
+ }
+ return;
+ }
+
+ context->is_context_secure = !IsFormNonSecure(form);
+
+ // TODO(rogerm): Early exit here on !driver()->RendererIsAvailable()?
+ // We skip populating autofill data, but might generate warnings and or
+ // signin promo to show over the unavailable renderer. That seems a mistake.
+
+ if (!driver()->RendererIsAvailable() || !got_autofillable_form ||
+ !IsAutofillEnabled()) {
+ return;
+ }
+
+ context->is_autofill_available = true;
+
+ if (context->is_filling_credit_card) {
+ *suggestions =
+ GetCreditCardSuggestions(field, context->focused_field->Type(),
+ &context->should_display_gpay_logo);
+ } else {
+ *suggestions = GetProfileSuggestions(*context->form_structure, field,
+ *context->focused_field);
+ }
+
+ // Ablation experiment:
+ FormTypeForAblationStudy form_type = context->is_filling_credit_card
+ ? FormTypeForAblationStudy::kPayment
+ : FormTypeForAblationStudy::kAddress;
+ // If ablation_group is AblationGroup::kDefault or AblationGroup::kControl,
+ // no ablation happens in the following.
+ AblationGroup ablation_group = client()->GetAblationStudy().GetAblationGroup(
+ client()->GetLastCommittedURL(), form_type);
+ context->ablation_group = ablation_group;
+ // Note that we don't set the ablation group if there are no suggestions.
+ // In that case we stick to kDefault.
+ context->conditional_ablation_group =
+ !suggestions->empty() ? ablation_group : AblationGroup::kDefault;
+
+ // In both cases (credit card and address forms), we inform the other event
+ // logger also about the ablation.
+ // This prevents for example that for an encountered address form we log a
+ // sample Autofill.Funnel.ParsedAsType.CreditCard = 0 (which would be recorded
+ // by the credit_card_form_event_logger_).
+ // For the complementary event logger, the conditional ablation status is
+ // logged as kDefault to not imply that data would be filled without ablation.
+ if (context->is_filling_credit_card) {
+ credit_card_form_event_logger_->SetAblationStatus(
+ context->ablation_group, context->conditional_ablation_group);
+ address_form_event_logger_->SetAblationStatus(context->ablation_group,
+ AblationGroup::kDefault);
+ } else {
+ address_form_event_logger_->SetAblationStatus(
+ context->ablation_group, context->conditional_ablation_group);
+ credit_card_form_event_logger_->SetAblationStatus(context->ablation_group,
+ AblationGroup::kDefault);
+ }
+
+ if (!suggestions->empty() && ablation_group == AblationGroup::kAblation) {
+ // Logic for disabling/ablating autofill.
+ context->suppress_reason = SuppressReason::kAblation;
+ suggestions->clear();
+ return;
+ }
+
+ // Returns early if no suggestion is available or suggestions are not for
+ // cards.
+ if (suggestions->empty() || !context->is_filling_credit_card)
+ return;
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ // This section adds the "Use a virtual card number" option in the autofill
+ // dropdown menu, if applicable.
+ if (ShouldShowVirtualCardOption(context->form_structure)) {
+ suggestions->emplace_back(l10n_util::GetStringUTF16(
+ IDS_AUTOFILL_CLOUD_TOKEN_DROPDOWN_OPTION_LABEL));
+ suggestions->back().frontend_id = POPUP_ITEM_ID_USE_VIRTUAL_CARD;
+ }
+#endif
+
+ // Don't provide credit card suggestions for non-secure pages, but do
+ // provide them for secure pages with passive mixed content (see
+ // implementation of IsContextSecure).
+ if (!context->is_context_secure) {
+ // Replace the suggestion content with a warning message explaining why
+ // Autofill is disabled for a website. The string is different if the
+ // credit card autofill HTTP warning experiment is enabled.
+ Suggestion warning_suggestion(
+ l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_INSECURE_CONNECTION));
+ warning_suggestion.frontend_id =
+ POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE;
+ suggestions->assign(1, warning_suggestion);
+ }
+}
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+// TODO(crbug.com/1020740): Add metrics logging.
+bool BrowserAutofillManager::ShouldShowVirtualCardOption(
+ FormStructure* form_structure) {
+ // If experiment is disabled, return false.
+ if (!base::FeatureList::IsEnabled(features::kAutofillEnableVirtualCard))
+ return false;
+
+ // If credit card upload is disabled, return false.
+ if (!IsAutofillCreditCardEnabled())
+ return false;
+
+ // If merchant is not allowed, return false.
+ std::vector<std::string> allowed_merchants =
+ client()->GetAllowedMerchantsForVirtualCards();
+ if (std::find(allowed_merchants.begin(), allowed_merchants.end(),
+ form_structure->source_url().spec()) ==
+ allowed_merchants.end()) {
+ return false;
+ }
+
+ // If no credit card candidate has related cloud token data available,
+ // return false.
+ if (GetVirtualCardCandidates(personal_data_).empty())
+ return false;
+
+ // If card number field or expiration date field is not detected, return
+ // false.
+ if (!form_structure->IsCompleteCreditCardForm())
+ return false;
+
+ // If CVC field is detected, then all requirements are met, otherwise return
+ // false.
+ for (auto& field : *form_structure) {
+ if (field->Type().GetStorableType() == CREDIT_CARD_VERIFICATION_CODE)
+ return true;
+ }
+ return false;
+}
+#endif
+
+FormEventLoggerBase* BrowserAutofillManager::GetEventFormLogger(
+ FieldTypeGroup field_type_group) const {
+ switch (field_type_group) {
+ case FieldTypeGroup::kName:
+ case FieldTypeGroup::kNameBilling:
+ case FieldTypeGroup::kEmail:
+ case FieldTypeGroup::kCompany:
+ case FieldTypeGroup::kAddressHome:
+ case FieldTypeGroup::kAddressBilling:
+ case FieldTypeGroup::kPhoneHome:
+ case FieldTypeGroup::kPhoneBilling:
+ return address_form_event_logger_.get();
+ case FieldTypeGroup::kCreditCard:
+ return credit_card_form_event_logger_.get();
+ case FieldTypeGroup::kTransaction:
+ case FieldTypeGroup::kPasswordField:
+ case FieldTypeGroup::kUsernameField:
+ case FieldTypeGroup::kNoGroup:
+ case FieldTypeGroup::kUnfillable:
+ return nullptr;
+ }
+ NOTREACHED();
+ return nullptr;
+}
+
+void BrowserAutofillManager::PreProcessStateMatchingTypes(
+ const std::vector<AutofillProfile>& profiles,
+ FormStructure* form_structure) {
+ if (!base::FeatureList::IsEnabled(
+ features::kAutofillUseAlternativeStateNameMap)) {
+ return;
+ }
+
+ for (const auto& profile : profiles) {
+ absl::optional<AlternativeStateNameMap::CanonicalStateName>
+ canonical_state_name_from_profile =
+ profile.GetAddress().GetCanonicalizedStateName();
+
+ if (!canonical_state_name_from_profile)
+ continue;
+
+ const AutofillType kCountryCode(HTML_TYPE_COUNTRY_CODE, HTML_MODE_NONE);
+ const std::u16string& country_code =
+ profile.GetInfo(kCountryCode, app_locale_);
+
+ for (auto& field : *form_structure) {
+ if (field->state_is_a_matching_type())
+ continue;
+
+ absl::optional<AlternativeStateNameMap::CanonicalStateName>
+ canonical_state_name_from_text =
+ AlternativeStateNameMap::GetCanonicalStateName(
+ base::UTF16ToUTF8(country_code), field->value);
+
+ if (canonical_state_name_from_text &&
+ canonical_state_name_from_text.value() ==
+ canonical_state_name_from_profile.value()) {
+ field->set_state_is_a_matching_type();
+ }
+ }
+ }
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/browser_autofill_manager.h b/chromium/components/autofill/core/browser/browser_autofill_manager.h
new file mode 100644
index 00000000000..bb094ae9fab
--- /dev/null
+++ b/chromium/components/autofill/core/browser/browser_autofill_manager.h
@@ -0,0 +1,751 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_BROWSER_AUTOFILL_MANAGER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_BROWSER_AUTOFILL_MANAGER_H_
+
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
+#include "base/containers/circular_deque.h"
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "build/build_config.h"
+#include "components/autofill/core/browser/autocomplete_history_manager.h"
+#include "components/autofill/core/browser/autofill_ablation_study.h"
+#include "components/autofill/core/browser/autofill_client.h"
+#include "components/autofill/core/browser/autofill_driver.h"
+#include "components/autofill/core/browser/autofill_external_delegate.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/field_filler.h"
+#include "components/autofill/core/browser/form_types.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/payments/autofill_offer_manager.h"
+#include "components/autofill/core/browser/payments/card_unmask_delegate.h"
+#include "components/autofill/core/browser/payments/credit_card_access_manager.h"
+#include "components/autofill/core/browser/payments/full_card_request.h"
+#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/sync_utils.h"
+#include "components/autofill/core/browser/ui/popup_types.h"
+#include "components/autofill/core/common/dense_set.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/signatures.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+
+namespace gfx {
+class RectF;
+}
+
+namespace autofill {
+
+class AutofillField;
+class AutofillClient;
+class BrowserAutofillManagerTestDelegate;
+class AutofillProfile;
+class AutofillType;
+class CreditCard;
+class FormStructureBrowserTest;
+
+struct FormData;
+struct FormFieldData;
+
+// We show the credit card signin promo only a certain number of times.
+extern const int kCreditCardSigninPromoImpressionLimit;
+
+// Enum for the value patterns metric. Don't renumerate existing value. They are
+// used for metrics.
+enum class ValuePatternsMetric {
+ kNoPatternFound = 0,
+ kUpiVpa = 1, // UPI virtual payment address.
+ kIban = 2, // International Bank Account Number.
+ kMaxValue = kIban,
+};
+
+// Manages saving and restoring the user's personal information entered into web
+// forms. One per frame; owned by the AutofillDriver.
+class BrowserAutofillManager
+ : public AutofillManager,
+ public AutocompleteHistoryManager::SuggestionsHandler,
+ public CreditCardAccessManager::Accessor {
+ public:
+ BrowserAutofillManager(AutofillDriver* driver,
+ AutofillClient* client,
+ const std::string& app_locale,
+ AutofillDownloadManagerState enable_download_manager);
+ ~BrowserAutofillManager() override;
+
+ void ShowAutofillSettings(bool show_credit_card_settings);
+
+ // Whether the |field| should show an entry to scan a credit card.
+ virtual bool ShouldShowScanCreditCard(const FormData& form,
+ const FormFieldData& field);
+
+ // Returns the type of the popup being shown.
+ virtual PopupType GetPopupType(const FormData& form,
+ const FormFieldData& field);
+
+ // Whether we should show the signin promo, based on the triggered |field|
+ // inside the |form|.
+ virtual bool ShouldShowCreditCardSigninPromo(const FormData& form,
+ const FormFieldData& field);
+
+ // 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.
+ virtual bool ShouldShowCardsFromAccountOption(const FormData& form,
+ const FormFieldData& field);
+ virtual void OnUserAcceptedCardsFromAccountOption();
+ virtual void RefetchCardsAndUpdatePopup(int query_id,
+ const FormData& form,
+ const FormFieldData& field_data);
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ // Returns the list of credit cards that have associated cloud token data.
+ virtual void FetchVirtualCardCandidates();
+
+ // Callback invoked when an actual card is selected. |selected_card_id| will
+ // be used to identify the card. The selected card's cloud token data will be
+ // fetched from the server.
+ // TODO(crbug.com/1020740): Passes card server id for now. In the future when
+ // one actual credit card can have multiple virtual cards, passes instrument
+ // token instead. Design TBD.
+ virtual void OnVirtualCardCandidateSelected(
+ const std::string& selected_card_id);
+#endif
+
+ // Called from our external delegate so they cannot be private.
+ virtual void FillOrPreviewForm(AutofillDriver::RendererFormDataAction action,
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ int unique_id);
+ virtual void FillCreditCardForm(int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const CreditCard& credit_card,
+ const std::u16string& cvc);
+ void DidShowSuggestions(bool has_autofill_suggestions,
+ const FormData& form,
+ const FormFieldData& field);
+
+ // Called from autofill assistant.
+ virtual void FillProfileForm(const autofill::AutofillProfile& profile,
+ const FormData& form,
+ const FormFieldData& field);
+
+ // Returns true if the value/identifier is deletable. Fills out
+ // |title| and |body| with relevant user-facing text.
+ bool GetDeletionConfirmationText(const std::u16string& value,
+ int identifier,
+ std::u16string* title,
+ std::u16string* body);
+
+ // Remove the credit card or Autofill profile that matches |unique_id|
+ // from the database. Returns true if deletion is allowed.
+ bool RemoveAutofillProfileOrCreditCard(int unique_id);
+
+ // Remove the specified Autocomplete entry.
+ void RemoveAutocompleteEntry(const std::u16string& name,
+ const std::u16string& value);
+
+ // Invoked when the user selected |value| in the Autocomplete drop-down.
+ void OnAutocompleteEntrySelected(const std::u16string& value);
+
+ // Invoked when the user selects the "Hide Suggestions" item in the
+ // Autocomplete drop-down.
+ virtual void OnUserHideSuggestions(const FormData& form,
+ const FormFieldData& field);
+
+ // Returns true only if the previewed form should be cleared.
+ bool ShouldClearPreviewedForm();
+
+ AutofillOfferManager* offer_manager() { return offer_manager_; }
+
+ CreditCardAccessManager* credit_card_access_manager() {
+ return credit_card_access_manager_.get();
+ }
+
+ payments::FullCardRequest* GetOrCreateFullCardRequest();
+
+ base::WeakPtr<payments::FullCardRequest::UIDelegate>
+ GetAsFullCardRequestUIDelegate();
+
+ const std::string& app_locale() const { return app_locale_; }
+
+ // Only for testing.
+ void SetTestDelegate(BrowserAutofillManagerTestDelegate* delegate);
+
+ // Will send an upload based on the |form_structure| data and the local
+ // Autofill profile data. |observed_submission| is specified if the upload
+ // follows an observed submission event. Returns false if the upload couldn't
+ // start.
+ virtual bool MaybeStartVoteUploadProcess(
+ std::unique_ptr<FormStructure> form_structure,
+ bool observed_submission);
+
+ // Update the pending form with |form|, possibly processing the current
+ // pending form for upload.
+ void UpdatePendingForm(const FormData& form);
+
+ // Upload the current pending form.
+ void ProcessPendingFormForUpload();
+
+ // Invoked when the popup view can't be created. Main usage is to collect
+ // metrics.
+ void DidSuppressPopup(const FormData& form, const FormFieldData& field);
+
+ // AutofillManager:
+ void OnFocusNoLongerOnForm(bool had_interacted_form) override;
+ void OnFocusOnFormFieldImpl(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) override;
+ void OnDidFillAutofillFormData(const FormData& form,
+ const base::TimeTicks timestamp) override;
+ void OnDidPreviewAutofillFormData() override;
+ void OnDidEndTextFieldEditing() override;
+ void OnHidePopup() override;
+ void SelectFieldOptionsDidChange(const FormData& form) override;
+ void PropagateAutofillPredictions(
+ content::RenderFrameHost* rfh,
+ const std::vector<FormStructure*>& forms) override;
+ void Reset() override;
+
+ // AutocompleteHistoryManager::SuggestionsHandler:
+ void OnSuggestionsReturned(
+ int query_id,
+ bool autoselect_first_suggestion,
+ const std::vector<Suggestion>& suggestions) override;
+
+ // Returns true if either Profile or CreditCard Autofill is enabled.
+ virtual bool IsAutofillEnabled() const;
+
+ // Returns true if the value of the AutofillProfileEnabled pref is true and
+ // the client supports Autofill.
+ virtual bool IsAutofillProfileEnabled() const;
+
+ // Returns true if the value of the AutofillCreditCardEnabled pref is true and
+ // the client supports Autofill.
+ virtual bool IsAutofillCreditCardEnabled() const;
+
+ // Shared code to determine if |form| should be uploaded to the Autofill
+ // server. It verifies that uploading is allowed and |form| meets conditions
+ // to be uploadable. Exposed for testing.
+ bool ShouldUploadForm(const FormStructure& form);
+
+ // Returns the last form the autofill manager considered in this frame.
+ virtual const FormData& last_query_form() const;
+
+ // Exposed to ContentAutofillDriver to help with recording WebOTP metrics.
+ bool has_parsed_forms() const { return has_parsed_forms_; }
+ bool has_observed_phone_number_field() const {
+ return has_observed_phone_number_field_;
+ }
+ bool has_observed_one_time_code_field() const {
+ return has_observed_one_time_code_field_;
+ }
+
+#if defined(UNIT_TEST)
+ void SetExternalDelegateForTest(
+ std::unique_ptr<AutofillExternalDelegate> external_delegate) {
+ external_delegate_ = std::move(external_delegate);
+ }
+
+ // A public wrapper that calls |DeterminePossibleFieldTypesForUpload| for
+ // testing purposes only.
+ static void DeterminePossibleFieldTypesForUploadForTest(
+ const std::vector<AutofillProfile>& profiles,
+ const std::vector<CreditCard>& credit_cards,
+ const std::u16string& last_unlocked_credit_card_cvc,
+ const std::string& app_locale,
+ FormStructure* submitted_form) {
+ DeterminePossibleFieldTypesForUpload(profiles, credit_cards,
+ last_unlocked_credit_card_cvc,
+ app_locale, submitted_form);
+ }
+
+ // A public wrapper that calls |MakeFrontendID| for testing purposes only.
+ int MakeFrontendIDForTest(const std::string& cc_backend_id,
+ const std::string& profile_backend_id) const {
+ return MakeFrontendID(cc_backend_id, profile_backend_id);
+ }
+
+ // A public wrapper that calls |ShouldTriggerRefill| for testing purposes
+ // only.
+ bool ShouldTriggerRefillForTest(const FormStructure& form_structure) {
+ return ShouldTriggerRefill(form_structure);
+ }
+
+ // A public wrapper that calls |TriggerRefill| for testing purposes only.
+ void TriggerRefillForTest(const FormData& form) { TriggerRefill(form); }
+
+ // A public wrapper that calls |PreProcessStateMatchingTypes| for testing
+ // purposes.
+ void PreProcessStateMatchingTypesForTest(
+ const std::vector<AutofillProfile>& profiles,
+ FormStructure* form_structure) {
+ PreProcessStateMatchingTypes(profiles, form_structure);
+ }
+#endif
+
+ protected:
+ // Test code should prefer to use this constructor.
+ BrowserAutofillManager(
+ 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.
+ virtual void UploadFormData(const FormStructure& submitted_form,
+ bool observed_submission);
+
+ // Logs quality metrics for the |submitted_form| and uploads the form data
+ // to the crowdsourcing server, if appropriate. |observed_submission|
+ // indicates whether the upload is a result of an observed submission event.
+ virtual void UploadFormDataAsyncCallback(
+ const FormStructure* submitted_form,
+ const base::TimeTicks& interaction_time,
+ const base::TimeTicks& submission_time,
+ bool observed_submission);
+
+ // Maps suggestion backend ID to and from an integer identifying it. Two of
+ // these intermediate integers are packed by MakeFrontendID to make the IDs
+ // that this class generates for the UI and for IPC.
+ virtual int BackendIDToInt(const std::string& backend_id) const;
+ virtual std::string IntToBackendID(int int_id) const;
+
+ // Methods for packing and unpacking credit card and profile IDs for sending
+ // and receiving to and from the renderer process.
+ int MakeFrontendID(const std::string& cc_backend_id,
+ const std::string& profile_backend_id) const;
+ void SplitFrontendID(int frontend_id,
+ std::string* cc_backend_id,
+ std::string* profile_backend_id) const;
+
+ // AutofillManager:
+ void OnFormSubmittedImpl(const FormData& form,
+ bool known_success,
+ mojom::SubmissionSource source) override;
+ void OnTextFieldDidChangeImpl(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box,
+ const base::TimeTicks timestamp) override;
+ void OnTextFieldDidScrollImpl(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) override {}
+ void OnQueryFormFieldAutofillImpl(int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& transformed_box,
+ bool autoselect_first_suggestion) override;
+ void OnSelectControlDidChangeImpl(const FormData& form,
+ const FormFieldData& field,
+ const gfx::RectF& bounding_box) override;
+ bool ShouldParseForms(const std::vector<FormData>& forms) override;
+ void OnBeforeProcessParsedForms() override;
+ void OnFormProcessed(const FormData& form,
+ const FormStructure& form_structure) override;
+ void OnAfterProcessParsedForms(const DenseSet<FormType>& form_types) override;
+
+ // Exposed for testing.
+ FormData* pending_form_data() { return pending_form_data_.get(); }
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(BrowserAutofillManagerTest,
+ DoNotFillIfFormFieldChanged);
+ FRIEND_TEST_ALL_PREFIXES(BrowserAutofillManagerTest,
+ DoNotFillIfFormFieldRemoved);
+ FRIEND_TEST_ALL_PREFIXES(BrowserAutofillManagerTest,
+ PageLanguageGetsCorrectlySet);
+ FRIEND_TEST_ALL_PREFIXES(BrowserAutofillManagerTest,
+ PageLanguageGetsCorrectlyDetected);
+
+ // Keeps track of the filling context for a form, used to make refill attemps.
+ struct FillingContext {
+ // |profile_or_credit_card| contains either AutofillProfile or CreditCard
+ // and must be non-null.
+ // If |profile_or_credit_card| contains a CreditCard, |optional_cvc| may be
+ // non-null.
+ FillingContext(const AutofillField& field,
+ absl::variant<const AutofillProfile*, const CreditCard*>
+ profile_or_credit_card,
+ const std::u16string* optional_cvc);
+ ~FillingContext();
+
+ // Whether a refill attempt was made.
+ bool attempted_refill = false;
+ // The profile or credit card that was used for the initial fill.
+ // The std::string associated with the credit card is the CVC, which may be
+ // empty.
+ absl::variant<AutofillProfile, std::pair<CreditCard, std::u16string>>
+ profile_or_credit_card_with_cvc;
+ // Possible identifiers of the field that was focused when the form was
+ // initially filled. A refill shall be triggered from the same field.
+ // TODO(crbug/896689): Remove |filled_field_unique_name|.
+ const FieldGlobalId filled_field_id;
+ const FieldSignature filled_field_signature;
+ const std::u16string filled_field_unique_name;
+ // The security origin from which the field was filled.
+ url::Origin filled_origin;
+ // The time at which the initial fill occurred.
+ const base::TimeTicks original_fill_time;
+ // The timer used to trigger a refill.
+ base::OneShotTimer on_refill_timer;
+ // The field type groups that were initially filled.
+ std::set<FieldTypeGroup> type_groups_originally_filled;
+ };
+
+ // Indicates the reason why autofill suggestions are suppressed.
+ enum class SuppressReason {
+ kNotSuppressed,
+ // Suggestions are not shown because an ablation experiment is enabled.
+ kAblation,
+ // Address suggestions are not shown because the field is annotated with
+ // autocomplete=off and the directive is being observed by the browser.
+ kAutocompleteOff,
+ // Suggestions are not shown because this form is on a secure site, but
+ // submits insecurely. This is only used when the user has started typing,
+ // otherwise a warning is shown.
+ kInsecureForm,
+ };
+
+ // The context for the list of suggestions available for a given field to be
+ // returned by GetAvailableSuggestions().
+ struct SuggestionsContext {
+ FormStructure* form_structure = nullptr;
+ AutofillField* focused_field = nullptr;
+ bool is_autofill_available = false;
+ bool is_context_secure = false;
+ bool is_filling_credit_card = false;
+ // Flag to indicate whether all suggestions come from Google Payments.
+ bool should_display_gpay_logo = false;
+ SuppressReason suppress_reason = SuppressReason::kNotSuppressed;
+ // Indicates whether the form filling is under ablation, meaning that
+ // autofill popups are suppressed.
+ AblationGroup ablation_group = AblationGroup::kDefault;
+ // Indicates whether the form filling is under ablation, under the condition
+ // that the user has data to fill on file. All users that don't have data
+ // to fill are in the AbationGroup::kDefault.
+ // Note that it is possible (due to implementation details) that this is
+ // incorrectly set to kDefault: If the user has typed some characters into a
+ // text field, it may look like no suggestions are available, but in
+ // practice the suggestions are just filtered out (Autofill only suggests
+ // matches that start with the typed prefix). Any consumers of the
+ // conditional_ablation_group attribute should monitor it over time.
+ // Any transitions of conditional_ablation_group from {kAblation,
+ // kControl} to kDefault should just be ignored and the previously reported
+ // value should be used. As the ablation experience is stable within a day,
+ // such a transition typically indicates that the user has type a prefix
+ // which led to the filtering of all autofillable data. In short: once
+ // either kAblation or kControl were reported, consumers should stick to
+ // that.
+ AblationGroup conditional_ablation_group = AblationGroup::kDefault;
+ };
+
+ // CreditCardAccessManager::Accessor
+ void OnCreditCardFetched(
+ bool did_succeed,
+ const CreditCard* credit_card = nullptr,
+ const std::u16string& cvc = std::u16string()) override;
+
+ // Returns false if Autofill is disabled or if no Autofill data is available.
+ bool RefreshDataModels();
+
+ // Gets the card referred to by the guid |unique_id|. Returns |nullptr| if
+ // card does not exist.
+ CreditCard* GetCreditCard(int unique_id);
+
+ // Gets the profile referred to by the guid |unique_id|. Returns |nullptr| if
+ // profile does not exist.
+ AutofillProfile* GetProfile(int unique_id);
+
+ // Determines whether a fill on |form| initiated from |field| will wind up
+ // filling a credit card number. This is useful to determine if we will need
+ // to unmask a card.
+ bool WillFillCreditCardNumber(const FormData& form,
+ const FormFieldData& field);
+
+ // Fills or previews the credit card form.
+ // Assumes the form and field are valid.
+ void FillOrPreviewCreditCardForm(
+ AutofillDriver::RendererFormDataAction action,
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const CreditCard* credit_card);
+
+ // Fills or previews the profile form.
+ // Assumes the form and field are valid.
+ void FillOrPreviewProfileForm(AutofillDriver::RendererFormDataAction action,
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const AutofillProfile& profile);
+
+ // Fills or previews |data_model| in the |form|.
+ void FillOrPreviewDataModelForm(
+ AutofillDriver::RendererFormDataAction action,
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ absl::variant<const AutofillProfile*, const CreditCard*>
+ profile_or_credit_card,
+ const std::u16string* optional_cvc,
+ FormStructure* form_structure,
+ AutofillField* autofill_field,
+ bool is_refill = false);
+
+ // Creates a FormStructure using the FormData received from the renderer. Will
+ // return an empty scoped_ptr if the data should not be processed for upload
+ // or personal data.
+ std::unique_ptr<FormStructure> ValidateSubmittedForm(const FormData& form);
+
+ // Returns the field corresponding to |form| and |field| that can be
+ // autofilled. Returns NULL if the field cannot be autofilled.
+ AutofillField* GetAutofillField(const FormData& form,
+ const FormFieldData& field)
+ WARN_UNUSED_RESULT;
+
+ // Returns true if any form in the field corresponds to an address
+ // |FieldTypeGroup|.
+ bool FormHasAddressField(const FormData& form) WARN_UNUSED_RESULT;
+
+ // Returns Suggestions corresponding to both the |autofill_field| type and
+ // stored profiles whose values match the contents of |field|. |form| stores
+ // data about the form with which the user is interacting, e.g. the number and
+ // types of form fields.
+ std::vector<Suggestion> GetProfileSuggestions(
+ const FormStructure& form,
+ const FormFieldData& field,
+ const AutofillField& autofill_field) const;
+
+ // Returns a list of values from the stored credit cards that match |type| and
+ // the value of |field| and returns the labels of the matching credit cards.
+ // |should_display_gpay_logo| will be set to true if there is no credit card
+ // suggestions or all suggestions come from Payments server.
+ std::vector<Suggestion> GetCreditCardSuggestions(
+ const FormFieldData& field,
+ const AutofillType& type,
+ bool* should_display_gpay_logo) const;
+
+ // If |initial_interaction_timestamp_| is unset or is set to a later time than
+ // |interaction_timestamp|, updates the cached timestamp. The latter check is
+ // needed because IPC messages can arrive out of order.
+ void UpdateInitialInteractionTimestamp(
+ const base::TimeTicks& interaction_timestamp);
+
+ // Examines |form| and returns true if it is in a non-secure context or
+ // its action attribute targets a HTTP url.
+ bool IsFormNonSecure(const FormData& form) const;
+
+ // Uses the existing personal data in |profiles| and |credit_cards| to
+ // determine possible field types for the |submitted_form|. This is
+ // potentially expensive -- on the order of 50ms even for a small set of
+ // |stored_data|. Hence, it should not run on the UI thread -- to avoid
+ // locking up the UI -- nor on the IO thread -- to avoid blocking IPC calls.
+ static void DeterminePossibleFieldTypesForUpload(
+ const std::vector<AutofillProfile>& profiles,
+ const std::vector<CreditCard>& credit_cards,
+ const std::u16string& last_unlocked_credit_card_cvc,
+ const std::string& app_locale,
+ FormStructure* submitted_form);
+
+ // Uses context about previous and next fields to select the appropriate type
+ // for fields with ambiguous upload types.
+ static void DisambiguateUploadTypes(FormStructure* form);
+
+ // Disambiguates address field upload types.
+ static void DisambiguateAddressUploadTypes(FormStructure* form,
+ size_t current_index);
+
+ // Disambiguates phone field upload types.
+ static void DisambiguatePhoneUploadTypes(FormStructure* form,
+ size_t current_index);
+
+ // Disambiguates name field upload types.
+ static void DisambiguateNameUploadTypes(
+ FormStructure* form,
+ size_t current_index,
+ const ServerFieldTypeSet& upload_types);
+
+ void FillFieldWithValue(
+ AutofillField* autofill_field,
+ absl::variant<const AutofillProfile*, const CreditCard*>
+ profile_or_credit_card,
+ FormFieldData* field_data,
+ bool should_notify,
+ const std::u16string& cvc,
+ uint32_t profile_form_bitmask,
+ std::string* failure_to_fill);
+
+ // TODO(crbug/896689): Remove code duplication once experiment is finished.
+ void SetFillingContext(const FormStructure& form,
+ std::unique_ptr<FillingContext> context);
+
+ // TODO(crbug/896689): Remove code duplication once experiment is finished.
+ FillingContext* GetFillingContext(const FormStructure& form);
+
+ // Whether there should be an attempts to refill the form. Returns true if all
+ // the following are satisfied:
+ // There have been no refill on that page yet.
+ // A non empty form name was recorded in a previous fill
+ // That form name matched the currently parsed form name
+ // It's been less than kLimitBeforeRefillMs since the original fill.
+ bool ShouldTriggerRefill(const FormStructure& form_structure);
+
+ // Attempts to refill the form that was changed dynamically. Should only be
+ // called if ShouldTriggerRefill returns true.
+ void TriggerRefill(const FormData& form);
+
+ // Replaces the contents of |suggestions| with available suggestions for
+ // |field|. |context| will contain additional information about the
+ // suggestions, such as if they correspond to credit card suggestions and
+ // if the context is secure.
+ void GetAvailableSuggestions(const FormData& form,
+ const FormFieldData& field,
+ std::vector<Suggestion>* suggestions,
+ SuggestionsContext* context);
+
+ // For each submitted field in the |form_structure|, it determines whether
+ // |ADDRESS_HOME_STATE| is a possible matching type.
+ // This method is intended to run matching type detection on the browser UI
+ // thread.
+ void PreProcessStateMatchingTypes(
+ const std::vector<AutofillProfile>& profiles,
+ FormStructure* form_structure);
+
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+ // Whether to show the option to use virtual card in the autofill popup.
+ bool ShouldShowVirtualCardOption(FormStructure* form_structure);
+#endif
+
+ // Returns an appropriate EventFormLogger for the given |field_type_group|.
+ // May return nullptr.
+ FormEventLoggerBase* GetEventFormLogger(
+ FieldTypeGroup field_type_group) const;
+
+ void SetDataList(const std::vector<std::u16string>& values,
+ const std::vector<std::u16string>& labels);
+
+ // Delegate to perform external processing (display, selection) on
+ // our behalf.
+ std::unique_ptr<AutofillExternalDelegate> external_delegate_;
+
+ std::string app_locale_;
+
+ // The personal data manager, used to save and load personal data to/from the
+ // web database. This is overridden by the BrowserAutofillManagerTest.
+ // Weak reference.
+ // May be NULL. NULL indicates OTR.
+ PersonalDataManager* personal_data_;
+
+ // Used to help fill data into fields.
+ FieldFiller field_filler_;
+
+ base::circular_deque<std::string> autofilled_form_signatures_;
+
+ // Handles single-field autocomplete form data.
+ // May be NULL. NULL indicates OTR.
+ base::WeakPtr<AutocompleteHistoryManager> autocomplete_history_manager_;
+
+ // Utilities for logging form events.
+ std::unique_ptr<AddressFormEventLogger> address_form_event_logger_;
+ std::unique_ptr<CreditCardFormEventLogger> credit_card_form_event_logger_;
+
+ // Have we logged whether Autofill is enabled for this page load?
+ bool has_logged_autofill_enabled_ = false;
+ // Have we logged an address suggestions count metric for this page?
+ bool has_logged_address_suggestions_count_ = false;
+ // Have we shown Autofill suggestions at least once?
+ bool did_show_suggestions_ = false;
+ // Has the user manually edited at least one form field among the autofillable
+ // ones?
+ bool user_did_type_ = false;
+ // Has the user autofilled a form on this page?
+ bool user_did_autofill_ = false;
+ // Has the user edited a field that was previously autofilled?
+ bool user_did_edit_autofilled_field_ = false;
+
+ // Does |this| have any parsed forms?
+ bool has_parsed_forms_ = false;
+ // Is there a field with autocomplete="one-time-code" observed?
+ bool has_observed_one_time_code_field_ = false;
+ // Is there a field with phone number collection observed?
+ bool has_observed_phone_number_field_ = false;
+
+ // When the user first interacted with a potentially fillable form on this
+ // page.
+ base::TimeTicks initial_interaction_timestamp_;
+
+ // A copy of the currently interacted form data.
+ std::unique_ptr<FormData> pending_form_data_;
+
+ // The credit card access manager, used to access local and server cards.
+ std::unique_ptr<CreditCardAccessManager> credit_card_access_manager_;
+
+ // The autofill offer manager, used to to retrieve offers for card
+ // suggestions. Initialized when BrowserAutofillManager is created.
+ // |offer_manager_| is never null.
+ AutofillOfferManager* offer_manager_;
+
+ // Collected information about the autofill form where a credit card will be
+ // filled.
+ AutofillDriver::RendererFormDataAction credit_card_action_;
+ int credit_card_query_id_ = -1;
+ FormData credit_card_form_;
+ FormFieldData credit_card_field_;
+ CreditCard credit_card_;
+ std::u16string last_unlocked_credit_card_cvc_;
+
+ // Suggestion backend ID to ID mapping. We keep two maps to convert back and
+ // forth. These should be used only by BackendIDToInt and IntToBackendID.
+ // Note that the integers are not frontend IDs.
+ mutable std::map<std::string, int> backend_to_int_map_;
+ mutable std::map<int, std::string> int_to_backend_map_;
+
+ // Delegate used in test to get notifications on certain events.
+ BrowserAutofillManagerTestDelegate* test_delegate_ = nullptr;
+
+ // A map of form names to FillingContext instances used to make refill
+ // attempts for dynamic forms.
+ // TODO(crbug/896689): Remove code duplication once experiment is finished.
+ std::map<FormGlobalId, std::unique_ptr<FillingContext>>
+ filling_context_by_global_id_;
+ std::map<std::u16string, std::unique_ptr<FillingContext>>
+ filling_context_by_unique_name_;
+
+ // Used to record metrics. This should be set at the beginning of the
+ // interaction and re-used throughout the context of this manager.
+ AutofillSyncSigninState sync_state_ = AutofillSyncSigninState::kNumSyncStates;
+
+ base::WeakPtrFactory<BrowserAutofillManager> weak_ptr_factory_{this};
+
+ friend class AutofillAssistantTest;
+ friend class BrowserAutofillManagerTest;
+ friend class AutofillMetricsTest;
+ friend class FormStructureBrowserTest;
+ friend class GetMatchingTypesTest;
+ friend class CreditCardAccessoryControllerTest;
+ DISALLOW_COPY_AND_ASSIGN(BrowserAutofillManager);
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_BROWSER_AUTOFILL_MANAGER_H_
diff --git a/chromium/components/autofill/core/browser/autofill_manager_test_delegate.h b/chromium/components/autofill/core/browser/browser_autofill_manager_test_delegate.h
index 3e2ad09fa27..9973ee2efb6 100644
--- a/chromium/components/autofill/core/browser/autofill_manager_test_delegate.h
+++ b/chromium/components/autofill/core/browser/browser_autofill_manager_test_delegate.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_MANAGER_TEST_DELEGATE_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_MANAGER_TEST_DELEGATE_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_BROWSER_AUTOFILL_MANAGER_TEST_DELEGATE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_BROWSER_AUTOFILL_MANAGER_TEST_DELEGATE_H_
namespace autofill {
-class AutofillManagerTestDelegate {
+class BrowserAutofillManagerTestDelegate {
public:
- virtual ~AutofillManagerTestDelegate() {}
+ virtual ~BrowserAutofillManagerTestDelegate() {}
// Called when a form is previewed with Autofill suggestions.
virtual void DidPreviewFormData() = 0;
@@ -26,4 +26,4 @@ class AutofillManagerTestDelegate {
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_MANAGER_TEST_DELEGATE_H_
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_BROWSER_AUTOFILL_MANAGER_TEST_DELEGATE_H_
diff --git a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc b/chromium/components/autofill/core/browser/browser_autofill_manager_unittest.cc
index 2d39c7208bb..5173f09788c 100644
--- a/chromium/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/browser_autofill_manager_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/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
#include <stddef.h>
@@ -20,6 +20,7 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/metrics_hashes.h"
#include "base/stl_util.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -44,11 +45,11 @@
#include "components/autofill/core/browser/payments/test_payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/test_autofill_client.h"
-#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/test_autofill_download_manager.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
#include "components/autofill/core/browser/test_autofill_external_delegate.h"
-#include "components/autofill/core/browser/test_autofill_manager.h"
+#include "components/autofill/core/browser/test_autofill_tick_clock.h"
+#include "components/autofill/core/browser/test_browser_autofill_manager.h"
#include "components/autofill/core/browser/test_form_data_importer.h"
#include "components/autofill/core/browser/test_form_structure.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
@@ -83,7 +84,6 @@
#include "url/gurl.h"
#include "url/url_canon.h"
-using base::ASCIIToUTF16;
using base::UTF8ToUTF16;
using testing::_;
using testing::AnyOf;
@@ -107,6 +107,7 @@ namespace {
const int kDefaultPageID = 137;
const std::string kArbitraryNickname = "Grocery Card";
+const std::u16string kArbitraryNickname16 = u"Grocery Card";
class MockAutofillClient : public TestAutofillClient {
public:
@@ -313,13 +314,15 @@ class MockAutofillDriver : public TestAutofillDriver {
MOCK_METHOD1(SendAutofillTypePredictionsToRenderer,
void(const std::vector<FormStructure*>& forms));
+ MOCK_METHOD1(SendFieldsEligibleForManualFillingToRenderer,
+ void(const std::vector<FieldRendererId>& fields));
};
} // namespace
-class AutofillManagerTest : public testing::Test {
+class BrowserAutofillManagerTest : public testing::Test {
public:
- AutofillManagerTest() = default;
+ BrowserAutofillManagerTest() = default;
void SetUp() override {
autofill_client_.SetPrefs(test::PrefServiceForTesting());
@@ -330,6 +333,7 @@ class AutofillManagerTest : public testing::Test {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
personal_data_.SetPrefService(autofill_client_.GetPrefs());
@@ -358,21 +362,22 @@ class AutofillManagerTest : public testing::Test {
autofill_client_.set_test_form_data_importer(
std::unique_ptr<autofill::TestFormDataImporter>(
test_form_data_importer));
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &autofill_client_, &personal_data_,
autocomplete_history_manager_.get());
auto download_manager = std::make_unique<MockAutofillDownloadManager>(
- autofill_driver_.get(), autofill_manager_.get());
+ autofill_driver_.get(), browser_autofill_manager_.get());
download_manager_ = download_manager.get();
- autofill_manager_->set_download_manager_for_test(
+ browser_autofill_manager_->set_download_manager_for_test(
std::move(download_manager));
auto external_delegate = std::make_unique<TestAutofillExternalDelegate>(
- autofill_manager_.get(), autofill_driver_.get(),
+ browser_autofill_manager_.get(), autofill_driver_.get(),
/*call_parent_methods=*/false);
external_delegate_ = external_delegate.get();
- autofill_manager_->SetExternalDelegateForTest(std::move(external_delegate));
+ browser_autofill_manager_->SetExternalDelegateForTest(
+ std::move(external_delegate));
auto test_strike_database = std::make_unique<TestStrikeDatabase>();
strike_database_ = test_strike_database.get();
@@ -432,9 +437,9 @@ class AutofillManagerTest : public testing::Test {
}
void TearDown() override {
- // Order of destruction is important as AutofillManager relies on
+ // Order of destruction is important as BrowserAutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
- autofill_manager_.reset();
+ browser_autofill_manager_.reset();
personal_data_.SetPrefService(nullptr);
personal_data_.ClearCreditCards();
@@ -443,7 +448,7 @@ class AutofillManagerTest : public testing::Test {
void GetAutofillSuggestions(int query_id,
const FormData& form,
const FormFieldData& field) {
- autofill_manager_->OnQueryFormFieldAutofill(
+ browser_autofill_manager_->OnQueryFormFieldAutofill(
query_id, form, field, gfx::RectF(),
/*autoselect_first_suggestion=*/false);
}
@@ -461,32 +466,33 @@ class AutofillManagerTest : public testing::Test {
std::back_inserter(suggestions),
[](auto result) { return Suggestion(result); });
- autofill_manager_->OnSuggestionsReturned(
+ browser_autofill_manager_->OnSuggestionsReturned(
query_id, /*autoselect_first_suggestion=*/false, suggestions);
}
void FormsSeen(const std::vector<FormData>& forms) {
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
}
void FormSubmitted(const FormData& form) {
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(
+ form, false, SubmissionSource::FORM_SUBMISSION);
}
void FillAutofillFormData(int query_id,
const FormData& form,
const FormFieldData& field,
int unique_id) {
- autofill_manager_->FillOrPreviewForm(AutofillDriver::FORM_DATA_ACTION_FILL,
- query_id, form, field, unique_id);
+ browser_autofill_manager_->FillOrPreviewForm(
+ AutofillDriver::FORM_DATA_ACTION_FILL, query_id, form, field,
+ unique_id);
}
- // Calls |autofill_manager_->OnFillAutofillFormData()| with the specified
- // input parameters after setting up the expectation that the mock driver's
- // |SendFormDataToRenderer()| method will be called and saving the parameters
- // of that call into the |response_query_id| and |response_data| output
- // parameters.
+ // Calls |browser_autofill_manager_->OnFillAutofillFormData()| with the
+ // specified input parameters after setting up the expectation that the mock
+ // driver's |SendFormDataToRenderer()| method will be called and saving the
+ // parameters of that call into the |response_query_id| and |response_data|
+ // output parameters.
void FillAutofillFormDataAndSaveResults(int input_query_id,
const FormData& input_form,
const FormFieldData& input_field,
@@ -501,12 +507,12 @@ class AutofillManagerTest : public testing::Test {
int MakeFrontendID(const std::string& cc_sid,
const std::string& profile_sid) const {
- return autofill_manager_->MakeFrontendID(cc_sid, profile_sid);
+ return browser_autofill_manager_->MakeFrontendID(cc_sid, profile_sid);
}
bool WillFillCreditCardNumber(const FormData& form,
const FormFieldData& field) {
- return autofill_manager_->WillFillCreditCardNumber(form, field);
+ return browser_autofill_manager_->WillFillCreditCardNumber(form, field);
}
// Populates |form| with data corresponding to a simple credit card form.
@@ -567,7 +573,7 @@ class AutofillManagerTest : public testing::Test {
EXPECT_CALL(*autofill_driver_, SendFormDataToRenderer(_, _, _))
.Times(AtLeast(1));
- autofill_manager_->FillOrPreviewCreditCardForm(
+ browser_autofill_manager_->FillOrPreviewCreditCardForm(
AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, *form,
form->fields[0], card);
}
@@ -575,8 +581,8 @@ class AutofillManagerTest : public testing::Test {
void OnDidGetRealPan(AutofillClient::PaymentsRpcResult result,
const std::string& real_pan) {
payments::FullCardRequest* full_card_request =
- autofill_manager_->credit_card_access_manager_->cvc_authenticator_
- ->full_card_request_.get();
+ browser_autofill_manager_->credit_card_access_manager_
+ ->cvc_authenticator_->full_card_request_.get();
DCHECK(full_card_request);
// Mock user response.
@@ -593,16 +599,27 @@ class AutofillManagerTest : public testing::Test {
// Convenience method to cast the FullCardRequest into a CardUnmaskDelegate.
CardUnmaskDelegate* full_card_unmask_delegate() {
payments::FullCardRequest* full_card_request =
- autofill_manager_->credit_card_access_manager_
+ browser_autofill_manager_->credit_card_access_manager_
->GetOrCreateCVCAuthenticator()
->full_card_request_.get();
DCHECK(full_card_request);
return static_cast<CardUnmaskDelegate*>(full_card_request);
}
- void DisableCreditCardAutofill() {
- scoped_feature_list_.InitAndEnableFeature(
- features::kAutofillCreditCardAblationExperiment);
+ void DisableAutofillViaAblation(
+ base::test::ScopedFeatureList& scoped_feature_list,
+ bool for_addresses,
+ bool for_credit_cards) {
+ base::FieldTrialParams feature_parameters{
+ {features::kAutofillAblationStudyEnabledForAddressesParam.name,
+ for_addresses ? "true" : "false"},
+ {features::kAutofillAblationStudyEnabledForPaymentsParam.name,
+ for_credit_cards ? "true" : "false"},
+ {features::kAutofillAblationStudyAblationWeightPerMilleParam.name,
+ "1000"},
+ };
+ scoped_feature_list.InitAndEnableFeatureWithParameters(
+ features::kAutofillEnableAblationStudy, feature_parameters);
}
// Wrappers around the TestAutofillExternalDelegate::GetSuggestions call that
@@ -638,7 +655,7 @@ class AutofillManagerTest : public testing::Test {
base::test::TaskEnvironment task_environment_;
MockAutofillClient autofill_client_;
std::unique_ptr<MockAutofillDriver> autofill_driver_;
- std::unique_ptr<TestAutofillManager> autofill_manager_;
+ std::unique_ptr<TestBrowserAutofillManager> browser_autofill_manager_;
TestAutofillExternalDelegate* external_delegate_;
scoped_refptr<AutofillWebDataService> database_;
MockAutofillDownloadManager* download_manager_;
@@ -708,19 +725,19 @@ class AutofillManagerTest : public testing::Test {
}
};
-// Subclass of AutofillManagerTest that parameterizes the finch flag to enable
-// structured names.
+// Subclass of BrowserAutofillManagerTest that parameterizes the finch flag to
+// enable structured names.
// TODO(crbug.com/1103421): Clean legacy implementation once structured names
// are fully launched. Here, the changes applied in CL 2333204 must be reverted
-// by deleting this class and use TEST_F(AutofillManagerTest, ) for all test
-// cases again.
-class AutofillManagerStructuredProfileTest
- : public AutofillManagerTest,
+// by deleting this class and use TEST_F(BrowserAutofillManagerTest, ) for all
+// test cases again.
+class BrowserAutofillManagerStructuredProfileTest
+ : public BrowserAutofillManagerTest,
public testing::WithParamInterface<bool> {
protected:
void SetUp() override {
InitializeFeatures();
- AutofillManagerTest::SetUp();
+ BrowserAutofillManagerTest::SetUp();
}
void InitializeFeatures();
@@ -734,7 +751,7 @@ class AutofillManagerStructuredProfileTest
base::test::ScopedFeatureList scoped_features_;
};
-void AutofillManagerStructuredProfileTest::InitializeFeatures() {
+void BrowserAutofillManagerStructuredProfileTest::InitializeFeatures() {
structured_names_and_addresses_ = GetParam();
std::vector<base::Feature> features = {
@@ -748,11 +765,11 @@ void AutofillManagerStructuredProfileTest::InitializeFeatures() {
}
class SuggestionMatchingTest
- : public AutofillManagerTest,
+ : public BrowserAutofillManagerTest,
public testing::WithParamInterface<std::tuple<bool, std::string>> {
protected:
void SetUp() override {
- AutofillManagerTest::SetUp();
+ BrowserAutofillManagerTest::SetUp();
InitializeFeatures();
}
@@ -818,13 +835,13 @@ std::string SuggestionMatchingTest::MakeMobileLabel(
}
// Credit card suggestion tests related with keyboard accessory.
-class CreditCardSuggestionTest : public AutofillManagerTest,
+class CreditCardSuggestionTest : public BrowserAutofillManagerTest,
public testing::WithParamInterface<bool> {
protected:
CreditCardSuggestionTest() : is_keyboard_accessory_enabled_(GetParam()) {}
void SetUp() override {
- AutofillManagerTest::SetUp();
+ BrowserAutofillManagerTest::SetUp();
features_.InitWithFeatureState(features::kAutofillKeyboardAccessory,
is_keyboard_accessory_enabled_);
}
@@ -837,7 +854,7 @@ class CreditCardSuggestionTest : public AutofillManagerTest,
// Test that calling OnFormsSeen with an empty set of forms (such as when
// reloading a page or when the renderer processes a set of forms but detects
// no changes) does not load the forms again.
-TEST_P(AutofillManagerStructuredProfileTest, OnFormsSeen_Empty) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, OnFormsSeen_Empty) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -857,7 +874,7 @@ TEST_P(AutofillManagerStructuredProfileTest, OnFormsSeen_Empty) {
// Test that calling OnFormsSeen consecutively with a different set of forms
// will query for each separately.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
OnFormsSeen_DifferentFormStructures) {
// Set up our form data.
FormData form;
@@ -895,7 +912,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that when forms are seen, the renderer is updated with the predicted
// field types
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
OnFormsSeen_SendAutofillTypePredictionsToRenderer) {
// Set up a queryable form.
FormData form1;
@@ -921,9 +938,38 @@ TEST_P(AutofillManagerStructuredProfileTest,
FormsSeen(forms);
}
+// Test that when forms are seen, the renderer is sent the fields that are
+// eligible for manual filling.
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ OnFormsSeen_SendFieldsEligibleForManualFillingToRenderer) {
+ // Set up a queryable form.
+ FormData form1;
+ CreateTestCreditCardFormData(&form1, true, false);
+
+ // Set up a non-queryable form.
+ FormData form2;
+ FormFieldData field;
+ test::CreateTestFormField("Querty", "qwerty", "", "text", &field);
+ form2.host_frame = test::GetLocalFrameToken();
+ form2.unique_renderer_id = test::MakeFormRendererId();
+ form2.name = u"NonQueryable";
+ form2.url = form1.url;
+ form2.action = GURL("https://myform.com/submit.html");
+ form2.fields.push_back(field);
+
+ // Package the forms for observation.
+ std::vector<FormData> forms{form1, form2};
+
+ // Set up expectations.
+ EXPECT_CALL(*autofill_driver_,
+ SendFieldsEligibleForManualFillingToRenderer(_))
+ .Times(2);
+ FormsSeen(forms);
+}
+
// Test that no autofill suggestions are returned for a field with an
// unrecognized autocomplete attribute.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetProfileSuggestions_UnrecognizedAttribute) {
// Set up our form data.
FormData form;
@@ -966,7 +1012,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that when small forms are disabled (min required fields enforced) no
// suggestions are returned when there are less than three fields and none of
// them have an autocomplete attribute.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetProfileSuggestions_MinFieldsEnforced_NoAutocomplete) {
// Set up our form data.
FormData form;
@@ -997,7 +1043,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that when small forms are disabled (min required fields enforced)
// for a form with two fields with one that has an autocomplete attribute,
// suggestions are only made for the one that has the attribute.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetProfileSuggestions_MinFieldsEnforced_WithOneAutocomplete) {
// Set up our form data.
FormData form;
@@ -1030,7 +1076,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that for a form with two fields with autocomplete attributes,
// suggestions are made for both fields. This is true even if a minimum number
// of fields is enforced.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetProfileSuggestions_SmallFormWithTwoAutocomplete) {
// Set up our form data.
FormData form;
@@ -1060,13 +1106,14 @@ TEST_P(AutofillManagerStructuredProfileTest,
}
// Test that the call is properly forwarded to AutocompleteHistoryManager.
-TEST_P(AutofillManagerStructuredProfileTest, OnAutocompleteEntrySelected) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ OnAutocompleteEntrySelected) {
std::u16string test_value = u"TestValue";
EXPECT_CALL(*autocomplete_history_manager_.get(),
OnAutocompleteEntrySelected(test_value))
.Times(1);
- autofill_manager_->OnAutocompleteEntrySelected(test_value);
+ browser_autofill_manager_->OnAutocompleteEntrySelected(test_value);
}
// Test that we return all address profile suggestions when all form fields
@@ -1234,7 +1281,7 @@ TEST_P(SuggestionMatchingTest,
}
// Test that we return no suggestions when the form has no relevant fields.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetProfileSuggestions_UnknownFields) {
// Set up our form data.
FormData form;
@@ -1307,7 +1354,7 @@ TEST_P(SuggestionMatchingTest, GetProfileSuggestions_WithDuplicates) {
}
// Test that we return no suggestions when autofill is disabled.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetProfileSuggestions_AutofillDisabledByUser) {
// Set up our form data.
FormData form;
@@ -1316,29 +1363,29 @@ TEST_P(AutofillManagerStructuredProfileTest,
FormsSeen(forms);
// Disable Autofill.
- autofill_manager_->SetAutofillProfileEnabled(false);
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
const FormFieldData& field = form.fields[0];
GetAutofillSuggestions(form, field);
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
OnSuggestionsReturned_CallsExternalDelegate) {
std::vector<Suggestion> suggestions = {
Suggestion("Charles", "123 Apple St.", "", 1),
Suggestion("Elvis", "3734 Elvis Presley Blvd.", "", 2)};
{
- autofill_manager_->OnSuggestionsReturned(
+ browser_autofill_manager_->OnSuggestionsReturned(
kDefaultPageID, /*autoselect_first_suggestion=*/false, suggestions);
EXPECT_FALSE(external_delegate_->autoselect_first_suggestion());
CheckSuggestions(kDefaultPageID, suggestions[0], suggestions[1]);
}
{
- autofill_manager_->OnSuggestionsReturned(
+ browser_autofill_manager_->OnSuggestionsReturned(
kDefaultPageID, /*autoselect_first_suggestion=*/true, suggestions);
EXPECT_TRUE(external_delegate_->autoselect_first_suggestion());
@@ -1348,7 +1395,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we return all credit card profile suggestions when all form fields
// are empty.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_EmptyValue) {
// Set up our form data.
FormData form;
@@ -1372,16 +1419,17 @@ TEST_P(AutofillManagerStructuredProfileTest,
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
- visa_label, kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
+ visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
master_card_label, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ browser_autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
// field has whitespace in it.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_Whitespace) {
// Set up our form data.
FormData form;
@@ -1406,16 +1454,17 @@ TEST_P(AutofillManagerStructuredProfileTest,
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
- visa_label, kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
+ visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
master_card_label, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ browser_autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
// field has stop characters in it, which should be removed.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_StopCharsOnly) {
// Set up our form data.
FormData form;
@@ -1440,16 +1489,17 @@ TEST_P(AutofillManagerStructuredProfileTest,
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
- visa_label, kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
+ visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
master_card_label, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ browser_autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
// field has some invisible unicode characters in it.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_InvisibleUnicodeOnly) {
// Set up our form data.
FormData form;
@@ -1474,16 +1524,17 @@ TEST_P(AutofillManagerStructuredProfileTest,
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
- visa_label, kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
+ visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
master_card_label, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ browser_autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card profile suggestions when the triggering
// field has stop characters in it and some input.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_StopCharsWithInput) {
// Add a credit card with particular numbers that we will attempt to recall.
CreditCard credit_card;
@@ -1511,16 +1562,17 @@ TEST_P(AutofillManagerStructuredProfileTest,
#endif
// Test that we sent the right value to the external delegate.
- CheckSuggestions(kDefaultPageID,
- Suggestion(std::string("Mastercard ") +
- test::ObfuscatedCardDigitsAsUTF8("3123"),
- master_card_label, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(7)));
+ CheckSuggestions(
+ kDefaultPageID,
+ Suggestion(std::string("Mastercard ") +
+ test::ObfuscatedCardDigitsAsUTF8("3123"),
+ master_card_label, kMasterCard,
+ browser_autofill_manager_->GetPackedCreditCardID(7)));
}
// Test that we return only matching credit card profile suggestions when the
// selected form field has been partially filled out.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_MatchCharacter) {
// Set up our form data.
FormData form;
@@ -1543,7 +1595,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
- visa_label, kVisaCard, autofill_manager_->GetPackedCreditCardID(4)));
+ visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)));
}
// Test that we return credit card profile suggestions when the selected form
@@ -1577,11 +1630,12 @@ TEST_P(CreditCardSuggestionTest, GetCreditCardSuggestions_CCNumber) {
#endif
// Test that we sent the right values to the external delegate.
- CheckSuggestions(kDefaultPageID,
- Suggestion(visa_value, visa_label, kVisaCard,
- autofill_manager_->GetPackedCreditCardID(4)),
- Suggestion(master_card_value, master_card_label, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ CheckSuggestions(
+ kDefaultPageID,
+ Suggestion(visa_value, visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)),
+ Suggestion(master_card_value, master_card_label, kMasterCard,
+ browser_autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return credit card profile suggestions when the selected form
@@ -1636,14 +1690,15 @@ TEST_P(CreditCardSuggestionTest, GetCreditCardSuggestions_NonCCNumber) {
#endif
// Test that we sent the right values to the external delegate.
- CheckSuggestions(kDefaultPageID,
- Suggestion("Elvis Presley", visa_label, kVisaCard,
- autofill_manager_->GetPackedCreditCardID(4)),
- Suggestion("Buddy Holly", master_card_label, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ CheckSuggestions(
+ kDefaultPageID,
+ Suggestion("Elvis Presley", visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)),
+ Suggestion("Buddy Holly", master_card_label, kMasterCard,
+ browser_autofill_manager_->GetPackedCreditCardID(5)));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_GoogleIssuedCard_CCNumber) {
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(
@@ -1676,13 +1731,14 @@ TEST_P(AutofillManagerStructuredProfileTest,
GetAutofillSuggestions(form, credit_card_number_field);
- CheckSuggestions(kDefaultPageID,
- Suggestion(google_issued_card_value,
- google_issued_card_label, kGoogleIssuedCard,
- autofill_manager_->GetPackedCreditCardID(7)));
+ CheckSuggestions(
+ kDefaultPageID,
+ Suggestion(google_issued_card_value, google_issued_card_label,
+ kGoogleIssuedCard,
+ browser_autofill_manager_->GetPackedCreditCardID(7)));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_GoogleIssuedCard_NonCCNumber) {
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(
@@ -1723,10 +1779,10 @@ TEST_P(AutofillManagerStructuredProfileTest,
CheckSuggestions(
kDefaultPageID,
Suggestion("Lorem Ispium", google_issued_card_label, kGoogleIssuedCard,
- autofill_manager_->GetPackedCreditCardID(7)));
+ browser_autofill_manager_->GetPackedCreditCardID(7)));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_GoogleIssuedCardNotPresent_ExpOff) {
base::test::ScopedFeatureList features;
features.InitAndDisableFeature(
@@ -1760,7 +1816,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we will eventually return the credit card signin promo when there
// are no credit card suggestions and the promo is active. See the tests in
// AutofillExternalDelegateTest that test whether the promo is added.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_OnlySigninPromo) {
personal_data_.ClearCreditCards();
@@ -1774,7 +1830,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
ON_CALL(autofill_client_, ShouldShowSigninPromo())
.WillByDefault(Return(true));
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo()).Times(2);
- EXPECT_TRUE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ EXPECT_TRUE(
+ browser_autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
// Autocomplete suggestions are not queried.
EXPECT_CALL(*(autocomplete_history_manager_.get()),
@@ -1793,7 +1850,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we return a warning explaining that credit card profile suggestions
// are unavailable when the page is secure, but the form action URL is valid but
// not secure.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_SecureContext_FormActionNotHTTPS) {
// Set up our form data.
FormData form;
@@ -1824,7 +1881,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we return credit card suggestions for secure pages that have an
// empty form action target URL.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_SecureContext_EmptyFormAction) {
// Set up our form data.
FormData form;
@@ -1850,16 +1907,17 @@ TEST_P(AutofillManagerStructuredProfileTest,
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
- visa_label, kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
+ visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
master_card_label, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ browser_autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return credit card suggestions for secure pages that have a
// form action set to "javascript:something".
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_SecureContext_JavascriptFormAction) {
// Set up our form data.
FormData form;
@@ -1885,16 +1943,17 @@ TEST_P(AutofillManagerStructuredProfileTest,
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
- visa_label, kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
+ visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
master_card_label, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ browser_autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that we return all credit card suggestions in the case that two cards
// have the same obfuscated number.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_RepeatedObfuscatedNumber) {
// Add a credit card with the same obfuscated number as Elvis's.
// |credit_card| will be owned by the mock PersonalDataManager.
@@ -1931,15 +1990,16 @@ TEST_P(AutofillManagerStructuredProfileTest,
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
- visa_label, kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
+ visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
master_card_label1, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)),
+ browser_autofill_manager_->GetPackedCreditCardID(5)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("3456"),
master_card_label2, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(7)));
+ browser_autofill_manager_->GetPackedCreditCardID(7)));
}
// Test that we return profile and credit card suggestions for combined forms.
@@ -2001,18 +2061,19 @@ TEST_P(SuggestionMatchingTest, GetAddressAndCreditCardSuggestions) {
kPageID2,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
- visa_label, kVisaCard, autofill_manager_->GetPackedCreditCardID(4)),
+ visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)),
Suggestion(std::string("Mastercard ") +
test::ObfuscatedCardDigitsAsUTF8("8765"),
master_card_label, kMasterCard,
- autofill_manager_->GetPackedCreditCardID(5)));
+ browser_autofill_manager_->GetPackedCreditCardID(5)));
}
// Test that for non-https forms with both address and credit card fields, we
// only return address suggestions. Instead of credit card suggestions, we
// should return a warning explaining that credit card profile suggestions are
// unavailable when the form is not https.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetAddressAndCreditCardSuggestionsNonHttps) {
// Set up our form data.
FormData form;
@@ -2043,11 +2104,11 @@ TEST_P(AutofillManagerStructuredProfileTest,
external_delegate_->CheckNoSuggestions(kDefaultPageID);
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
ShouldShowAddressSuggestionsIfCreditCardAutofillDisabled) {
base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(
- features::kAutofillCreditCardAblationExperiment);
+ DisableAutofillViaAblation(features, /*for_addresses=*/false,
+ /*for_credit_cards=*/true);
// Set up our form data.
FormData form;
@@ -2061,8 +2122,26 @@ TEST_P(AutofillManagerStructuredProfileTest,
EXPECT_TRUE(external_delegate_->on_suggestions_returned_seen());
}
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ ShouldShowCreditCardSuggestionsIfAddressAutofillDisabled) {
+ base::test::ScopedFeatureList features;
+ DisableAutofillViaAblation(features, /*for_addresses=*/true,
+ /*for_credit_cards=*/false);
+
+ // Set up our form data.
+ FormData form;
+ CreateTestCreditCardFormData(&form, true, false);
+ std::vector<FormData> forms(1, form);
+ FormsSeen(forms);
+ FormFieldData field = form.fields[0];
+
+ GetAutofillSuggestions(form, field);
+ // Verify that suggestions are returned.
+ EXPECT_TRUE(external_delegate_->on_suggestions_returned_seen());
+}
+
// Test that the correct section is filled.
-TEST_F(AutofillManagerTest, FillTriggeredSection) {
+TEST_F(BrowserAutofillManagerTest, FillTriggeredSection) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -2076,7 +2155,7 @@ TEST_F(AutofillManagerTest, FillTriggeredSection) {
{
FormStructure* form_structure;
AutofillField* autofill_field;
- bool found = autofill_manager_->GetCachedFormAndField(
+ bool found = browser_autofill_manager_->GetCachedFormAndField(
form, form.fields[index_of_trigger_field], &form_structure,
&autofill_field);
ASSERT_TRUE(found);
@@ -2121,14 +2200,14 @@ MATCHER_P(HasValue, value, "") {
// Test that if the form cache is outdated because a field has changed, filling
// is aborted after that field.
-TEST_F(AutofillManagerTest, DoNotFillIfFormFieldChanged) {
+TEST_F(BrowserAutofillManagerTest, DoNotFillIfFormFieldChanged) {
FormData form;
test::CreateTestAddressFormData(&form);
FormsSeen({form});
FormStructure* form_structure = nullptr;
AutofillField* autofill_field = nullptr;
- ASSERT_TRUE(autofill_manager_->GetCachedFormAndField(
+ ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField(
form, form.fields.front(), &form_structure, &autofill_field));
// Modify |form| so that it doesn't match |form_structure| anymore.
@@ -2145,7 +2224,7 @@ TEST_F(AutofillManagerTest, DoNotFillIfFormFieldChanged) {
EXPECT_CALL(*autofill_driver_, SendFormDataToRenderer(_, _, _))
.WillOnce((DoAll(testing::SaveArg<0>(&response_query_id),
testing::SaveArg<2>(&response_data))));
- autofill_manager_->FillOrPreviewDataModelForm(
+ browser_autofill_manager_->FillOrPreviewDataModelForm(
AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, form,
form.fields.front(), profile, nullptr, form_structure, autofill_field);
std::vector<FormFieldData> filled_fields(response_data.fields.begin(),
@@ -2159,14 +2238,14 @@ TEST_F(AutofillManagerTest, DoNotFillIfFormFieldChanged) {
// Test that if the form cache is outdated because a field was removed, filling
// is aborted.
-TEST_F(AutofillManagerTest, DoNotFillIfFormFieldRemoved) {
+TEST_F(BrowserAutofillManagerTest, DoNotFillIfFormFieldRemoved) {
FormData form;
test::CreateTestAddressFormData(&form);
FormsSeen({form});
FormStructure* form_structure = nullptr;
AutofillField* autofill_field = nullptr;
- ASSERT_TRUE(autofill_manager_->GetCachedFormAndField(
+ ASSERT_TRUE(browser_autofill_manager_->GetCachedFormAndField(
form, form.fields.front(), &form_structure, &autofill_field));
// Modify |form| so that it doesn't match |form_structure| anymore.
@@ -2180,28 +2259,30 @@ TEST_F(AutofillManagerTest, DoNotFillIfFormFieldRemoved) {
EXPECT_CALL(*autofill_driver_, SendFormDataToRenderer(_, _, _)).Times(0);
}
-// Tests that AutofillManager ignores loss of focus events sent from the
+// Tests that BrowserAutofillManager ignores loss of focus events sent from the
// renderer if the renderer did not have a previously-interacted form.
// TODO(crbug.com/1140473): Remove this test when workaround is no longer
// needed.
-TEST_F(AutofillManagerTest,
+TEST_F(BrowserAutofillManagerTest,
ShouldIgnoreLossOfFocusWithNoPreviouslyInteractedForm) {
FormData form;
test::CreateTestAddressFormData(&form);
- autofill_manager_->UpdatePendingForm(form);
- ASSERT_TRUE(autofill_manager_->pending_form_data()->SameFormAs(form));
+ browser_autofill_manager_->UpdatePendingForm(form);
+ ASSERT_TRUE(browser_autofill_manager_->pending_form_data()->SameFormAs(form));
// Receiving a notification that focus is no longer on the form *without* the
// renderer having a previously-interacted form should not result in
// any changes to the pending form.
- autofill_manager_->OnFocusNoLongerOnForm(/*had_interacted_form=*/false);
- EXPECT_TRUE(autofill_manager_->pending_form_data()->SameFormAs(form));
+ browser_autofill_manager_->OnFocusNoLongerOnForm(
+ /*had_interacted_form=*/false);
+ EXPECT_TRUE(browser_autofill_manager_->pending_form_data()->SameFormAs(form));
}
-TEST_F(AutofillManagerTest,
+TEST_F(BrowserAutofillManagerTest,
ShouldNotShowCreditCardsSuggestionsIfCreditCardAutofillDisabled) {
- DisableCreditCardAutofill();
+ DisableAutofillViaAblation(scoped_feature_list_, /*for_addresses=*/false,
+ /*for_credit_cards=*/true);
// Set up our form data.
FormData form;
@@ -2216,28 +2297,219 @@ TEST_F(AutofillManagerTest,
external_delegate_->CheckNoSuggestions(kDefaultPageID);
}
-TEST_F(AutofillManagerTest,
- ShouldLogFormSubmitEventIfCreditCardAutofillDisabled) {
- DisableCreditCardAutofill();
+TEST_F(BrowserAutofillManagerTest,
+ ShouldNotShowAddressSuggestionsIfAddressAutofillDisabled) {
+ DisableAutofillViaAblation(scoped_feature_list_, /*for_addresses=*/true,
+ /*for_credit_cards=*/false);
// Set up our form data.
FormData form;
- CreateTestCreditCardFormData(&form, true, false);
+ test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
FormsSeen(forms);
FormFieldData field = form.fields[0];
GetAutofillSuggestions(form, field);
+ // Check that credit card suggestions will not be available.
+ external_delegate_->CheckNoSuggestions(kDefaultPageID);
+}
+
+struct LogAblationTestParams {
+ const char* description;
+ // Whether any autofillable data is stored.
+ bool run_with_data_on_file = true;
+ // If true, the credit card owner name field is filled with value that is not
+ // a prefix of any stored credit card and then autofill suggestions are
+ // queried a second time.
+ bool second_query_for_suggestions_with_typed_prefix = false;
+ // Whether the form should be submitted before validating the metrics.
+ bool submit_form = true;
+};
+
+enum class LogAblationFormType {
+ kAddress,
+ kPayment,
+ kMixed, // address fields followed by payment fields
+};
+
+class BrowserAutofillManagerLogAblationTest
+ : public BrowserAutofillManagerTest,
+ public testing::WithParamInterface<
+ std::tuple<LogAblationTestParams, LogAblationFormType>> {
+ public:
+ BrowserAutofillManagerLogAblationTest() = default;
+ ~BrowserAutofillManagerLogAblationTest() override = default;
+};
+
+// Validate that UMA logging works correctly for ablation studies.
+INSTANTIATE_TEST_SUITE_P(
+ All,
+ BrowserAutofillManagerLogAblationTest,
+ testing::Combine(
+ testing::Values(
+ // Test that if autofillable data is stored and the ablation is
+ // enabled, we record metrics as expected.
+ LogAblationTestParams{.description = "Having data to fill"},
+ // Test that if NO autofillable data is stored and the ablation is
+ // enabled, we record "UnconditionalAblation" metrics but no
+ // "ConditionalAblation" metrics. The latter only recoded on the
+ // condition that we have data to fill.
+ LogAblationTestParams{.description = "Having NO data to fill",
+ .run_with_data_on_file = false},
+ // In this test we trigger the GetAutofillSuggestions call twice. By
+ // the second time the user has typed a value that is not the prefix
+ // of any existing autofill data. This means that autofill would not
+ // create any suggestions. We still want to consider this a
+ // conditional ablation (the condition to have fillable data on file
+ // is met).
+ LogAblationTestParams{
+ .description = "Typed unknown prefix",
+ .second_query_for_suggestions_with_typed_prefix = false},
+ // Test that the right events are recorded in case the user
+ // interacts with a form but does not submit it.
+ LogAblationTestParams{.description = "No form submission",
+ .submit_form = false}),
+ testing::Values(LogAblationFormType::kAddress,
+ LogAblationFormType::kPayment,
+ LogAblationFormType::kMixed)));
+
+TEST_P(BrowserAutofillManagerLogAblationTest, TestLogging) {
+ const LogAblationTestParams& params = std::get<0>(GetParam());
+ LogAblationFormType form_type = std::get<1>(GetParam());
+
+ SCOPED_TRACE(testing::Message() << params.description << " Form type: "
+ << static_cast<int>(form_type));
+
+ if (!params.run_with_data_on_file) {
+ personal_data_.ClearAllServerData();
+ personal_data_.ClearAllLocalData();
+ }
+
+ DisableAutofillViaAblation(scoped_feature_list_, /*for_addresses=*/true,
+ /*for_credit_cards=*/true);
+ TestAutofillTickClock clock;
+ clock.SetNowTicks(base::TimeTicks::Now());
base::HistogramTester histogram_tester;
- FormSubmitted(form);
- histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
- FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE,
- 1);
+
+ // Set up our form data. In the kMixed case the form will contain the fields
+ // of an address form followed by the fields of fields of a payment form. The
+ // triggering for autofill suggestions will happen on an address field in this
+ // case.
+ FormData form;
+ if (form_type == LogAblationFormType::kAddress ||
+ form_type == LogAblationFormType::kMixed) {
+ test::CreateTestAddressFormData(&form);
+ }
+ if (form_type == LogAblationFormType::kPayment ||
+ form_type == LogAblationFormType::kMixed) {
+ CreateTestCreditCardFormData(&form, true, false);
+ }
+ std::vector<FormData> forms(1, form);
+ FormsSeen(forms);
+
+ // Simulate retrieving autofill suggestions with the first field as a trigger
+ // script. This should emit signals that lead to recorded metrics later on.
+ FormFieldData field = form.fields[0];
+ GetAutofillSuggestions(form, field);
+
+ // Simulate user typing into field (due to the ablation we would not fill).
+ field.value = u"Unknown User";
+ browser_autofill_manager_->OnTextFieldDidChange(
+ form, field, gfx::RectF(), AutofillTickClock::NowTicks());
+
+ if (params.second_query_for_suggestions_with_typed_prefix) {
+ // Do another lookup. We won't have any suggestions because they would not
+ // be compatible with the "Unknown User" username.
+ GetAutofillSuggestions(form, field);
+ }
+
+ // Advance time and possibly submit the form.
+ base::TimeDelta time_delta = base::TimeDelta::FromSeconds(42);
+ clock.Advance(time_delta);
+ if (params.submit_form)
+ FormSubmitted(form);
+
+ // Flush FormEventLoggers.
+ browser_autofill_manager_->Reset();
+
+ // Validate the recorded metrics.
+ std::string form_type_str = (form_type == LogAblationFormType::kAddress ||
+ form_type == LogAblationFormType::kMixed)
+ ? "Address"
+ : "CreditCard";
+
+ // If data was on file, we expect conditional ablation metrics.
+ if (params.run_with_data_on_file) {
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.Ablation.FormSubmissionAfterInteraction." + form_type_str +
+ ".ConditionalAblation",
+ /*sample=*/params.submit_form ? 1 : 0,
+ /*expected_bucket_count=*/1);
+ } else {
+ histogram_tester.ExpectTotalCount(
+ "Autofill.Ablation.FormSubmissionAfterInteraction." + form_type_str +
+ ".ConditionalAblation",
+ /*count=*/0);
+ }
+ // Only if data was on file an a submission happened, we can record the
+ // duration from interaction to submission.
+ if (params.run_with_data_on_file && params.submit_form) {
+ histogram_tester.ExpectUniqueTimeSample(
+ "Autofill.Ablation.FillDurationSinceInteraction." + form_type_str +
+ ".ConditionalAblation",
+ time_delta,
+ /*expected_bucket_count=*/1);
+ } else {
+ histogram_tester.ExpectTotalCount(
+ "Autofill.Ablation.FillDurationSinceInteraction." + form_type_str +
+ ".ConditionalAblation",
+ /*count=*/0);
+ }
+ // The unconditional ablation metrics should always be logged as this the
+ // ablation study is always enabled.
+ histogram_tester.ExpectUniqueSample(
+ "Autofill.Ablation.FormSubmissionAfterInteraction." + form_type_str +
+ ".UnconditionalAblation",
+ /*sample=*/params.submit_form ? 1 : 0,
+ /*expected_bucket_count=*/1);
+ // Expect a time from interaction to submission the form was submitted.
+ if (params.submit_form) {
+ histogram_tester.ExpectUniqueTimeSample(
+ "Autofill.Ablation.FillDurationSinceInteraction." + form_type_str +
+ ".UnconditionalAblation",
+ time_delta,
+ /*expected_bucket_count=*/1);
+ } else {
+ histogram_tester.ExpectTotalCount(
+ "Autofill.Ablation.FillDurationSinceInteraction." + form_type_str +
+ ".UnconditionalAblation",
+ /*count=*/0);
+ }
+
+ // Ensure that no metrics are recorded for the complementary form type.
+ // I.e. if the trigger element is of an address form, the credit card form
+ // should have no metrics.
+ std::string complementary_form_type_str =
+ (form_type == LogAblationFormType::kAddress ||
+ form_type == LogAblationFormType::kMixed)
+ ? "CreditCard"
+ : "Address";
+ for (const char* metric :
+ {"FormSubmissionAfterInteraction", "FillDurationSinceInteraction"}) {
+ for (const char* ablation_type :
+ {"UnconditionalAblation", "ConditionalAblation"}) {
+ histogram_tester.ExpectTotalCount(
+ base::StrCat({"Autofill.Ablation.", metric, ".",
+ complementary_form_type_str.c_str(), ".",
+ ablation_type}),
+ /*count=*/0);
+ }
+ }
}
// Test that we properly match typed values to stored state data.
-TEST_F(AutofillManagerTest, DetermineStateFieldTypeForUpload) {
+TEST_F(BrowserAutofillManagerTest, DetermineStateFieldTypeForUpload) {
base::test::ScopedFeatureList feature;
feature.InitAndEnableFeature(features::kAutofillUseAlternativeStateNameMap);
@@ -2264,8 +2536,8 @@ TEST_F(AutofillManagerTest, DetermineStateFieldTypeForUpload) {
FormStructure form_structure(form);
EXPECT_EQ(form_structure.field_count(), 2U);
- autofill_manager_->PreProcessStateMatchingTypesForTest({profile},
- &form_structure);
+ browser_autofill_manager_->PreProcessStateMatchingTypesForTest(
+ {profile}, &form_structure);
EXPECT_TRUE(form_structure.field(1)->state_is_a_matching_type());
}
@@ -2285,8 +2557,8 @@ TEST_F(AutofillManagerTest, DetermineStateFieldTypeForUpload) {
FormStructure form_structure(form);
EXPECT_EQ(form_structure.field_count(), 2U);
- autofill_manager_->PreProcessStateMatchingTypesForTest({profile},
- &form_structure);
+ browser_autofill_manager_->PreProcessStateMatchingTypesForTest(
+ {profile}, &form_structure);
EXPECT_FALSE(form_structure.field(1)->state_is_a_matching_type());
}
@@ -2311,8 +2583,8 @@ TEST_F(AutofillManagerTest, DetermineStateFieldTypeForUpload) {
FormStructure form_structure(form);
EXPECT_EQ(form_structure.field_count(), 2U);
- autofill_manager_->PreProcessStateMatchingTypesForTest({profile},
- &form_structure);
+ browser_autofill_manager_->PreProcessStateMatchingTypesForTest(
+ {profile}, &form_structure);
EXPECT_TRUE(form_structure.field(1)->state_is_a_matching_type());
}
@@ -2363,7 +2635,7 @@ TEST_P(SuggestionMatchingTest, GetFieldSuggestionsWhenFormIsAutofilled) {
// Test that nothing breaks when there are autocomplete suggestions but no
// autofill suggestions.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetFieldSuggestionsForAutocompleteOnly) {
// Set up our form data.
FormData form;
@@ -2492,7 +2764,7 @@ TEST_P(SuggestionMatchingTest, GetProfileSuggestions_FancyPhone) {
Suggestion(value3, label3, "", 3));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetProfileSuggestions_ForPhonePrefixOrSuffix) {
// Set up our form data.
FormData form;
@@ -2545,7 +2817,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Tests that the suggestion consists of phone number without the country code
// when a length limit is imposed in the field due to which filling with
// country code is not possible.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetProfileSuggestions_ForPhoneField) {
FormData form;
test::CreateTestAddressFormData(&form);
@@ -2569,7 +2841,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Tests that we return email profile suggestions values
// when the email field with username autocomplete attribute exist.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetProfileSuggestions_ForEmailFieldWithUserNameAutocomplete) {
// Set up our form data.
FormData form;
@@ -2614,7 +2886,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
}
// Test that we correctly fill an address form.
-TEST_P(AutofillManagerStructuredProfileTest, FillAddressForm) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, FillAddressForm) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -2639,7 +2911,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillAddressForm) {
EXPECT_NE(base::Time(), profile->use_date());
}
-TEST_P(AutofillManagerStructuredProfileTest, WillFillCreditCardNumber) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, WillFillCreditCardNumber) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
@@ -2684,7 +2956,7 @@ TEST_P(AutofillManagerStructuredProfileTest, WillFillCreditCardNumber) {
}
// Test that we correctly log FIELD_WAS_AUTOFILLED event in UserHappiness.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillCreditCardForm_LogFieldWasAutofill) {
// Set up our form data.
FormData form;
@@ -2708,7 +2980,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
}
// Test that we correctly fill a credit card form.
-TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_Simple) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, FillCreditCardForm_Simple) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
@@ -2726,7 +2998,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_Simple) {
}
// Test that whitespace is stripped from the credit card number.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillCreditCardForm_StripCardNumberWhitespace) {
// Same as the SetUp(), but generate Elvis card with whitespace in credit
// card number. |credit_card| will be owned by the TestPersonalDataManager.
@@ -2754,7 +3026,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
}
// Test that separator characters are stripped from the credit card number.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillCreditCardForm_StripCardNumberSeparators) {
// Same as the SetUp(), but generate Elvis card with separator characters in
// credit card number. |credit_card| will be owned by the
@@ -2784,7 +3056,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we correctly fill a credit card form with month input type.
// Test 1 of 4: Empty month, empty year
-TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_NoYearNoMonth) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillCreditCardForm_NoYearNoMonth) {
personal_data_.ClearCreditCards();
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "Miku Hatsune",
@@ -2810,7 +3083,8 @@ TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_NoYearNoMonth) {
// Test that we correctly fill a credit card form with month input type.
// Test 2 of 4: Non-empty month, empty year
-TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_NoYearMonth) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillCreditCardForm_NoYearMonth) {
personal_data_.ClearCreditCards();
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "Miku Hatsune",
@@ -2836,7 +3110,8 @@ TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_NoYearMonth) {
// Test that we correctly fill a credit card form with month input type.
// Test 3 of 4: Empty month, non-empty year
-TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_YearNoMonth) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillCreditCardForm_YearNoMonth) {
// Same as the SetUp(), but generate 4 credit cards with year month
// combination.
personal_data_.ClearCreditCards();
@@ -2864,7 +3139,8 @@ TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_YearNoMonth) {
// Test that we correctly fill a credit card form with month input type.
// Test 4 of 4: Non-empty month, non-empty year
-TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_YearMonth) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillCreditCardForm_YearMonth) {
personal_data_.ClearCreditCards();
CreditCard credit_card;
test::SetCreditCardInfo(&credit_card, "Miku Hatsune",
@@ -2889,7 +3165,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_YearMonth) {
}
// Test that only the first 16 credit card number fields are filled.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillOnlyFirstNineteenCreditCardNumberFields) {
// Set up our form data.
FormData form;
@@ -2943,7 +3219,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
}
// Test that only the first 16 of identical fields are filled.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillOnlyFirstSixteenIdenticalCreditCardNumberFields) {
// Set up our form data.
FormData form;
@@ -2993,7 +3269,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
}
// Test the credit card number is filled correctly into single-digit fields.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillCreditCardNumberIntoSingleDigitFields) {
// Set up our form data.
FormData form;
@@ -3051,7 +3327,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we correctly fill a credit card form with first and last cardholder
// name.
-TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_SplitName) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillCreditCardForm_SplitName) {
// Set up our form data.
FormData form;
form.name = u"MyForm";
@@ -3086,7 +3363,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_SplitName) {
}
// Test that only filled selection boxes are counted for the type filling limit.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
OnlyCountFilledSelectionBoxesForTypeFillingLimit) {
test::PopulateAlternativeStateNameMapForTesting(
"US", "Tennessee",
@@ -3191,7 +3468,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
}
// Test that we correctly fill a combined address and credit card form.
-TEST_P(AutofillManagerStructuredProfileTest, FillAddressAndCreditCardForm) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillAddressAndCreditCardForm) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -3227,7 +3505,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillAddressAndCreditCardForm) {
}
// Test that a field with an unrecognized autocomplete attribute is not filled.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillAddressForm_UnrecognizedAttribute) {
FormData address_form;
address_form.name = u"MyForm";
@@ -3271,7 +3549,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that non credit card related fields with the autocomplete attribute set
// to off are filled on all platforms when the feature to autofill all addresses
// is enabled (default).
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillAddressForm_AutocompleteOffNotRespected) {
FormData address_form;
address_form.name = u"MyForm";
@@ -3313,7 +3591,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that if a company is of a format of a birthyear and the relevant feature
// is enabled, we would not fill it.
-TEST_P(AutofillManagerStructuredProfileTest, FillAddressForm_CompanyBirthyear) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillAddressForm_CompanyBirthyear) {
// Set up our form data.
FormData address_form;
address_form.name = u"MyForm";
@@ -3359,7 +3638,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillAddressForm_CompanyBirthyear) {
}
// Test that a field with a value equal to it's placeholder attribute is filled.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillAddressForm_PlaceholderEqualsValue) {
FormData address_form;
address_form.name = u"MyForm";
@@ -3401,7 +3680,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that a credit card field with an unrecognized autocomplete attribute
// gets filled.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillCreditCardForm_UnrecognizedAttribute) {
// Set up the form data.
FormData form;
@@ -3445,7 +3724,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that credit card fields are filled even if they have the autocomplete
// attribute set to off.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillCreditCardForm_AutocompleteOff) {
// Set up our form data.
FormData form;
@@ -3472,7 +3751,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that selecting an expired credit card fills everything except the
// expiration date.
-TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_ExpiredCard) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillCreditCardForm_ExpiredCard) {
personal_data_.ClearCreditCards();
CreditCard expired_card;
test::SetCreditCardInfo(&expired_card, "Homer Simpson",
@@ -3534,7 +3814,8 @@ TEST_P(AutofillManagerStructuredProfileTest, FillCreditCardForm_ExpiredCard) {
// Test that non-focusable field is ignored while inferring boundaries between
// sections, but not filled.
-TEST_P(AutofillManagerStructuredProfileTest, FillFormWithNonFocusableFields) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillFormWithNonFocusableFields) {
// Create a form with both focusable and non-focusable fields.
FormData form;
form.name = u"MyForm";
@@ -3590,7 +3871,8 @@ TEST_P(AutofillManagerStructuredProfileTest, FillFormWithNonFocusableFields) {
// Test that we correctly fill a form that has multiple logical sections, e.g.
// both a billing and a shipping address.
-TEST_P(AutofillManagerStructuredProfileTest, FillFormWithMultipleSections) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillFormWithMultipleSections) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -3660,7 +3942,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillFormWithMultipleSections) {
// Test that we correctly fill a form that has author-specified sections, which
// might not match our expected section breakdown.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillFormWithAuthorSpecifiedSections) {
// Create a form with a billing section and an unnamed section, interleaved.
// The billing section includes both address and credit card fields.
@@ -3812,7 +4094,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we correctly fill a form that has a single logical section with
// multiple email address fields.
-TEST_P(AutofillManagerStructuredProfileTest, FillFormWithMultipleEmails) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillFormWithMultipleEmails) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -3841,7 +4124,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillFormWithMultipleEmails) {
}
// Test that we correctly fill a previously auto-filled form.
-TEST_P(AutofillManagerStructuredProfileTest, FillAutofilledForm) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, FillAutofilledForm) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -3901,7 +4184,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillAutofilledForm) {
}
// Test that we correctly fill a previously partly auto-filled form.
-TEST_P(AutofillManagerStructuredProfileTest, FillPartlyAutofilledForm) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, FillPartlyAutofilledForm) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -3946,7 +4229,8 @@ TEST_P(AutofillManagerStructuredProfileTest, FillPartlyAutofilledForm) {
}
// Test that we correctly fill a previously partly auto-filled form.
-TEST_P(AutofillManagerStructuredProfileTest, FillPartlyManuallyFilledForm) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillPartlyManuallyFilledForm) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -3997,7 +4281,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillPartlyManuallyFilledForm) {
}
// Test that we correctly fill a phone number split across multiple fields.
-TEST_P(AutofillManagerStructuredProfileTest, FillPhoneNumber) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, FillPhoneNumber) {
// In one form, rely on the max length attribute to imply US phone number
// parts. In the other form, rely on the autocomplete type attribute.
FormData form_with_us_number_max_length;
@@ -4117,7 +4401,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FillPhoneNumber) {
EXPECT_EQ(std::u16string(), response_data4.fields[4].value);
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillFirstPhoneNumber_ComponentizedNumbers) {
AutofillProfile* work_profile =
personal_data_.GetProfileWithGUID("00000000-0000-0000-0000-000000000002");
@@ -4185,7 +4469,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
EXPECT_EQ(std::u16string(), response_data.fields[7].value);
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillFirstPhoneNumber_WholeNumbers) {
AutofillProfile* work_profile =
personal_data_.GetProfileWithGUID("00000000-0000-0000-0000-000000000002");
@@ -4235,7 +4519,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
EXPECT_EQ(std::u16string(), response_data.fields[3].value);
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillFirstPhoneNumber_FillPartsOnceOnly) {
AutofillProfile* work_profile =
personal_data_.GetProfileWithGUID("00000000-0000-0000-0000-000000000002");
@@ -4308,7 +4592,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Verify when extension is misclassified, and there is a complete
// phone field, we do not fill anything to extension field.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillFirstPhoneNumber_NotFillMisclassifiedExtention) {
AutofillProfile* work_profile =
personal_data_.GetProfileWithGUID("00000000-0000-0000-0000-000000000002");
@@ -4368,7 +4652,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
}
// Verify when no complete number can be found, we do best-effort filling.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillFirstPhoneNumber_BestEfforFilling) {
AutofillProfile* work_profile =
personal_data_.GetProfileWithGUID("00000000-0000-0000-0000-000000000002");
@@ -4425,7 +4709,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// When the focus is on second phone field explicitly, we will fill the
// entire form, both first phone field and second phone field included.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillFirstPhoneNumber_FocusOnSecondPhoneNumber) {
AutofillProfile* work_profile =
personal_data_.GetProfileWithGUID("00000000-0000-0000-0000-000000000002");
@@ -4478,7 +4762,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
EXPECT_EQ(u"6505554567", response_data.fields[3].value);
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillFirstPhoneNumber_HiddenFieldShouldNotCount) {
AutofillProfile* work_profile =
personal_data_.GetProfileWithGUID("00000000-0000-0000-0000-000000000002");
@@ -4533,7 +4817,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// The hidden and the presentational fields should be filled, only if their
// control type is 'select-one'. This exception is made to support synthetic
// fields.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FormWithHiddenOrPresentationalSelects) {
FormData form;
form.name = u"MyForm";
@@ -4602,7 +4886,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
response_data.fields[5]);
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FillFirstPhoneNumber_MultipleSectionFilledCorrectly) {
AutofillProfile* work_profile =
personal_data_.GetProfileWithGUID("00000000-0000-0000-0000-000000000002");
@@ -4694,7 +4978,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
}
// Test that we can still fill a form when a field has been removed from it.
-TEST_P(AutofillManagerStructuredProfileTest, FormChangesRemoveField) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, FormChangesRemoveField) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -4721,7 +5005,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FormChangesRemoveField) {
}
// Test that we can still fill a form when a field has been added to it.
-TEST_P(AutofillManagerStructuredProfileTest, FormChangesAddField) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, FormChangesAddField) {
// The offset of the phone field in the address form.
const int kPhoneFieldOffset = 9;
@@ -4752,7 +5036,8 @@ TEST_P(AutofillManagerStructuredProfileTest, FormChangesAddField) {
// Test that we can still fill a form when the visibility of some fields
// changes.
-TEST_P(AutofillManagerStructuredProfileTest, FormChangesVisibilityOfFields) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FormChangesVisibilityOfFields) {
// Set up our form data.
FormData form;
form.url = GURL("https://www.foo.com/");
@@ -4826,7 +5111,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FormChangesVisibilityOfFields) {
}
// Test that we are able to save form data when forms are submitted.
-TEST_P(AutofillManagerStructuredProfileTest, FormSubmitted) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, FormSubmitted) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -4850,7 +5135,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FormSubmitted) {
}
// Test that we are saving form data when the FormSubmitted event is sent.
-TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedSaveData) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, FormSubmittedSaveData) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -4867,20 +5152,21 @@ TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedSaveData) {
ExpectFilledAddressFormElvis(response_page_id, response_data, kDefaultPageID,
false);
- autofill_manager_->OnFormSubmitted(response_data, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(response_data, false,
+ SubmissionSource::FORM_SUBMISSION);
EXPECT_EQ(1, personal_data_.num_times_save_imported_profile_called());
}
// Test that when Autocomplete is enabled and Autofill is disabled, form
// submissions are still received by AutocompleteHistoryManager.
-TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedAutocompleteEnabled) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FormSubmittedAutocompleteEnabled) {
TestAutofillClient client;
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &client, &personal_data_,
autocomplete_history_manager_.get());
- autofill_manager_->SetAutofillProfileEnabled(false);
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
// Set up our form data.
FormData form;
@@ -4892,7 +5178,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedAutocompleteEnabled) {
}
// Test that the value patterns metric is reported.
-TEST_P(AutofillManagerStructuredProfileTest, ValuePatternsMetric) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, ValuePatternsMetric) {
struct ValuePatternTestCase {
const char* value;
autofill::ValuePatternsMetric pattern;
@@ -4922,19 +5208,20 @@ TEST_P(AutofillManagerStructuredProfileTest, ValuePatternsMetric) {
// Test that when Autofill is disabled, Autocomplete suggestions are still
// queried.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
AutocompleteSuggestions_SomeWhenAutofillDisabled) {
TestAutofillClient client;
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &client, &personal_data_,
autocomplete_history_manager_.get());
- autofill_manager_->SetAutofillProfileEnabled(false);
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
auto external_delegate = std::make_unique<TestAutofillExternalDelegate>(
- autofill_manager_.get(), autofill_driver_.get(),
+ browser_autofill_manager_.get(), autofill_driver_.get(),
/*call_parent_methods=*/false);
external_delegate_ = external_delegate.get();
- autofill_manager_->SetExternalDelegateForTest(std::move(external_delegate));
+ browser_autofill_manager_->SetExternalDelegateForTest(
+ std::move(external_delegate));
// Set up our form data.
FormData form;
@@ -4952,19 +5239,20 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that when Autofill is disabled and the field should not autocomplete,
// autocomplete is not queried for suggestions.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
AutocompleteSuggestions_AutofillDisabledAndFieldShouldNotAutocomplete) {
TestAutofillClient client;
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &client, &personal_data_,
autocomplete_history_manager_.get());
- autofill_manager_->SetAutofillProfileEnabled(false);
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
auto external_delegate = std::make_unique<TestAutofillExternalDelegate>(
- autofill_manager_.get(), autofill_driver_.get(),
+ browser_autofill_manager_.get(), autofill_driver_.get(),
/*call_parent_methods=*/false);
external_delegate_ = external_delegate.get();
- autofill_manager_->SetExternalDelegateForTest(std::move(external_delegate));
+ browser_autofill_manager_->SetExternalDelegateForTest(
+ std::move(external_delegate));
// Set up our form data.
FormData form;
@@ -4985,7 +5273,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we do not query for Autocomplete suggestions when there are
// Autofill suggestions available.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
AutocompleteSuggestions_NoneWhenAutofillPresent) {
// Set up our form data.
FormData form;
@@ -5006,7 +5294,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we query for Autocomplete suggestions when there are no Autofill
// suggestions available.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
AutocompleteSuggestions_SomeWhenAutofillEmpty) {
// Set up our form data.
FormData form;
@@ -5028,7 +5316,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that when Autofill is disabled and the field is a credit card name
// field,
// autocomplete is queried for suggestions.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
AutocompleteSuggestions_CreditCardNameFieldShouldAutocomplete) {
TestAutofillClient client;
// Since we are testing a form that submits over HTTP, we also need to set
@@ -5038,16 +5326,17 @@ TEST_P(AutofillManagerStructuredProfileTest,
replacements.SetScheme(url::kHttpScheme,
url::Component(0, strlen(url::kHttpScheme)));
client.set_form_origin(client.form_origin().ReplaceComponents(replacements));
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &client, &personal_data_,
autocomplete_history_manager_.get());
- autofill_manager_->SetAutofillProfileEnabled(false);
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
auto external_delegate = std::make_unique<TestAutofillExternalDelegate>(
- autofill_manager_.get(), autofill_driver_.get(),
+ browser_autofill_manager_.get(), autofill_driver_.get(),
/*call_parent_methods=*/false);
external_delegate_ = external_delegate.get();
- autofill_manager_->SetExternalDelegateForTest(std::move(external_delegate));
+ browser_autofill_manager_->SetExternalDelegateForTest(
+ std::move(external_delegate));
// Set up our form data.
FormData form;
@@ -5067,7 +5356,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that when Autofill is disabled and the field is a credit card number
// field, autocomplete is not queried for suggestions.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
AutocompleteSuggestions_CreditCardNumberShouldNotAutocomplete) {
TestAutofillClient client;
// Since we are testing a form that submits over HTTP, we also need to set
@@ -5077,16 +5366,17 @@ TEST_P(AutofillManagerStructuredProfileTest,
replacements.SetScheme(url::kHttpScheme,
url::Component(0, strlen(url::kHttpScheme)));
client.set_form_origin(client.form_origin().ReplaceComponents(replacements));
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &client, &personal_data_,
autocomplete_history_manager_.get());
- autofill_manager_->SetAutofillProfileEnabled(false);
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
auto external_delegate = std::make_unique<TestAutofillExternalDelegate>(
- autofill_manager_.get(), autofill_driver_.get(),
+ browser_autofill_manager_.get(), autofill_driver_.get(),
/*call_parent_methods=*/false);
external_delegate_ = external_delegate.get();
- autofill_manager_->SetExternalDelegateForTest(std::move(external_delegate));
+ browser_autofill_manager_->SetExternalDelegateForTest(
+ std::move(external_delegate));
// Set up our form data.
FormData form;
@@ -5108,7 +5398,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we do not query for Autocomplete suggestions when there are no
// Autofill suggestions available, and that the field should not autocomplete.
TEST_F(
- AutofillManagerTest,
+ BrowserAutofillManagerTest,
AutocompleteSuggestions_NoneWhenAutofillEmptyFieldShouldNotAutocomplete) {
// Set up our form data.
FormData form;
@@ -5129,19 +5419,20 @@ TEST_F(
GetAutofillSuggestions(form, field);
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
AutocompleteOffRespectedForAutocomplete) {
TestAutofillClient client;
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &client, &personal_data_,
autocomplete_history_manager_.get());
- autofill_manager_->SetAutofillProfileEnabled(false);
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
auto external_delegate = std::make_unique<TestAutofillExternalDelegate>(
- autofill_manager_.get(), autofill_driver_.get(),
+ browser_autofill_manager_.get(), autofill_driver_.get(),
/*call_parent_methods=*/false);
external_delegate_ = external_delegate.get();
- autofill_manager_->SetExternalDelegateForTest(std::move(external_delegate));
+ browser_autofill_manager_->SetExternalDelegateForTest(
+ std::move(external_delegate));
EXPECT_CALL(*(autocomplete_history_manager_.get()),
OnGetAutocompleteSuggestions)
@@ -5157,20 +5448,20 @@ TEST_P(AutofillManagerStructuredProfileTest,
GetAutofillSuggestions(form, *field);
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DestructorCancelsAutocompleteQueries) {
EXPECT_CALL(*(autocomplete_history_manager_.get()), CancelPendingQueries)
.Times(1);
- autofill_manager_.reset();
+ browser_autofill_manager_.reset();
}
// Make sure that we don't error out when AutocompleteHistoryManager was
-// destroyed before AutofillManager.
-TEST_P(AutofillManagerStructuredProfileTest,
+// destroyed before BrowserAutofillManager.
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
Destructor_DeletedAutocomplete_Works) {
// The assertion here is that no exceptions will be thrown.
autocomplete_history_manager_.reset();
- autofill_manager_.reset();
+ browser_autofill_manager_.reset();
}
// Test that OnLoadedServerPredictions can obtain the FormStructure with the
@@ -5178,7 +5469,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// What we test here:
// * The API response parser is used.
// * The query can be processed with a response from the API.
-TEST_P(AutofillManagerStructuredProfileTest, OnLoadedServerPredictionsFromApi) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ OnLoadedServerPredictionsFromApi) {
// First form on the page.
FormData form;
form.host_frame = test::GetLocalFrameToken();
@@ -5197,12 +5489,13 @@ TEST_P(AutofillManagerStructuredProfileTest, OnLoadedServerPredictionsFromApi) {
/*value=*/"", /*type=*/"text", /*field=*/&field);
form.fields.push_back(field);
// Simulate having seen this form on page load.
- // |form_structure_instance| will be owned by |autofill_manager_|.
+ // |form_structure_instance| will be owned by |browser_autofill_manager_|.
auto form_structure_instance = std::make_unique<TestFormStructure>(form);
// This pointer is valid as long as autofill manager lives.
TestFormStructure* form_structure = form_structure_instance.get();
form_structure->DetermineHeuristicTypes(nullptr, nullptr);
- autofill_manager_->AddSeenFormStructure(std::move(form_structure_instance));
+ browser_autofill_manager_->AddSeenFormStructure(
+ std::move(form_structure_instance));
// Second form on the page.
FormData form2;
@@ -5221,7 +5514,8 @@ TEST_P(AutofillManagerStructuredProfileTest, OnLoadedServerPredictionsFromApi) {
// This pointer is valid as long as autofill manager lives.
TestFormStructure* form_structure2 = form_structure_instance2.get();
form_structure2->DetermineHeuristicTypes(nullptr, nullptr);
- autofill_manager_->AddSeenFormStructure(std::move(form_structure_instance2));
+ browser_autofill_manager_->AddSeenFormStructure(
+ std::move(form_structure_instance2));
// Make API response with suggestions.
AutofillQueryResponse response;
@@ -5253,8 +5547,8 @@ TEST_P(AutofillManagerStructuredProfileTest, OnLoadedServerPredictionsFromApi) {
// Run method under test.
base::HistogramTester histogram_tester;
- autofill_manager_->OnLoadedServerPredictionsForTest(encoded_response_string,
- signatures);
+ browser_autofill_manager_->OnLoadedServerPredictionsForTest(
+ encoded_response_string, signatures);
// Verify whether the relevant histograms were updated.
histogram_tester.ExpectBucketCount("Autofill.ServerQueryResponse",
@@ -5280,21 +5574,21 @@ TEST_P(AutofillManagerStructuredProfileTest, OnLoadedServerPredictionsFromApi) {
}
// Test that OnLoadedServerPredictions does not call ParseQueryResponse if the
-// AutofillManager has been reset between the time the query was sent and the
-// response received.
-TEST_P(AutofillManagerStructuredProfileTest,
+// BrowserAutofillManager has been reset between the time the query was sent and
+// the response received.
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
OnLoadedServerPredictions_ResetManager) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
+ // |form_structure| will be owned by |browser_autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
form_structure->DetermineHeuristicTypes(nullptr, nullptr);
std::vector<FormSignature> signatures =
test::GetEncodedSignatures(*form_structure);
- autofill_manager_->AddSeenFormStructure(
+ browser_autofill_manager_->AddSeenFormStructure(
std::unique_ptr<TestFormStructure>(form_structure));
AutofillQueryResponse response;
@@ -5314,11 +5608,11 @@ TEST_P(AutofillManagerStructuredProfileTest,
base::Base64Encode(response_string, &response_string_base64);
// Reset the manager (such as during a navigation).
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
base::HistogramTester histogram_tester;
- autofill_manager_->OnLoadedServerPredictionsForTest(response_string_base64,
- signatures);
+ browser_autofill_manager_->OnLoadedServerPredictionsForTest(
+ response_string_base64, signatures);
// Verify that FormStructure::ParseQueryResponse was NOT called.
histogram_tester.ExpectTotalCount("Autofill.ServerQueryResponse", 0);
@@ -5326,7 +5620,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that when server predictions disagree with the heuristic ones, the
// overall types and sections would be set based on the server one.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DetermineHeuristicsWithOverallPrediction) {
// Set up our form data.
FormData form;
@@ -5349,10 +5643,10 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
+ // |form_structure| will be owned by |browser_autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
form_structure->DetermineHeuristicTypes(nullptr, nullptr);
- autofill_manager_->AddSeenFormStructure(
+ browser_autofill_manager_->AddSeenFormStructure(
std::unique_ptr<TestFormStructure>(form_structure));
AutofillQueryResponse response;
@@ -5375,7 +5669,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
base::Base64Encode(response_string, &response_string_base64);
base::HistogramTester histogram_tester;
- autofill_manager_->OnLoadedServerPredictionsForTest(
+ browser_autofill_manager_->OnLoadedServerPredictionsForTest(
response_string_base64, test::GetEncodedSignatures(*form_structure));
// Verify that FormStructure::ParseQueryResponse was called (here and below).
histogram_tester.ExpectBucketCount("Autofill.ServerQueryResponse",
@@ -5416,14 +5710,14 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we are able to save form data when forms are submitted and we only
// have server data for the field types.
-TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedServerTypes) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, FormSubmittedServerTypes) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
FormsSeen(std::vector<FormData>(1, form));
// Simulate having seen this form on page load.
- // |form_structure| will be owned by |autofill_manager_|.
+ // |form_structure| will be owned by |browser_autofill_manager_|.
TestFormStructure* form_structure = new TestFormStructure(form);
form_structure->DetermineHeuristicTypes(nullptr, nullptr);
@@ -5434,7 +5728,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedServerTypes) {
server_types.push_back(form_structure->field(i)->heuristic_type());
}
form_structure->SetFieldTypes(heuristic_types, server_types);
- autofill_manager_->AddSeenFormStructure(
+ browser_autofill_manager_->AddSeenFormStructure(
std::unique_ptr<TestFormStructure>(form_structure));
// Fill the form.
@@ -5456,7 +5750,7 @@ TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedServerTypes) {
// Test that we are able to save form data after the possible types have been
// determined. We do two submissions and verify that only at the second
// submission are the possible types able to be inferred.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FormSubmittedPossibleTypesTwoSubmissions) {
// Set up our form data.
FormData form;
@@ -5493,19 +5787,20 @@ TEST_P(AutofillManagerStructuredProfileTest,
type_set.insert(UNKNOWN_TYPE);
std::vector<ServerFieldTypeSet> unknown_types(expected_types.size(),
type_set);
- autofill_manager_->SetExpectedSubmittedFieldTypes(unknown_types);
+ browser_autofill_manager_->SetExpectedSubmittedFieldTypes(unknown_types);
FormSubmitted(response_data);
ASSERT_EQ(1u, personal_data_.GetProfiles().size());
// The second submission should now have data by which to infer types.
- autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
+ browser_autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
FormSubmitted(response_data);
ASSERT_EQ(1u, personal_data_.GetProfiles().size());
}
// Test that the form signature for an uploaded form always matches the form
// signature from the query.
-TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedWithDifferentFields) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FormSubmittedWithDifferentFields) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -5525,12 +5820,13 @@ TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedWithDifferentFields) {
// Simulate form submission.
FormSubmitted(form);
- EXPECT_EQ(signature, autofill_manager_->GetSubmittedFormSignature());
+ EXPECT_EQ(signature, browser_autofill_manager_->GetSubmittedFormSignature());
}
// Test that we do not save form data when submitted fields contain default
// values.
-TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedWithDefaultValues) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FormSubmittedWithDefaultValues) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -5568,14 +5864,14 @@ TEST_P(AutofillManagerStructuredProfileTest, FormSubmittedWithDefaultValues) {
}
struct ProfileMatchingTypesTestCase {
- const char* input_value; // The value to input in the field.
+ const char* input_value; // The value to input in the field.
ServerFieldTypeSet field_types; // The expected field types to be determined.
ServerFieldTypeSet
structured_field_types; // The expected field types to be determined.
};
class ProfileMatchingTypesTest
- : public AutofillManagerTest,
+ : public BrowserAutofillManagerTest,
public ::testing::WithParamInterface<
std::tuple<ProfileMatchingTypesTestCase,
int, // AutofillDataModel::ValidityState
@@ -5583,7 +5879,7 @@ class ProfileMatchingTypesTest
bool>> { // kAutofillEnableSupportForMoreStructureInNames
protected:
void SetUp() override {
- AutofillManagerTest::SetUp();
+ BrowserAutofillManagerTest::SetUp();
InitializeFeatures();
}
@@ -5808,7 +6104,7 @@ TEST_P(ProfileMatchingTypesTest, DeterminePossibleFieldTypesForUpload) {
FormStructure form_structure(form);
base::HistogramTester histogram_tester;
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, credit_cards, std::u16string(), "en-us", &form_structure);
ASSERT_EQ(1U, form_structure.field_count());
@@ -5835,7 +6131,7 @@ TEST_P(ProfileMatchingTypesTest, DeterminePossibleFieldTypesForUpload) {
// Tests that DeterminePossibleFieldTypesForUpload is called when a form is
// submitted.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DeterminePossibleFieldTypesForUpload_IsTriggered) {
FormData form;
form.name = u"MyForm";
@@ -5881,13 +6177,13 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields[i].value = expected_values[i];
}
- autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
+ browser_autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
FormSubmitted(form);
}
// Test that the possible field types with multiple validities are determined
// correctly.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DeterminePossibleFieldTypesWithMultipleValidities) {
// Set up the user's profiles.
std::vector<AutofillProfile> profiles;
@@ -5915,7 +6211,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Set up the test cases:
typedef struct {
- std::string input_value;
+ std::u16string input_value;
ServerFieldType field_type;
std::vector<AutofillDataModel::ValidityState> expected_validity_states;
} TestFieldData;
@@ -5927,15 +6223,15 @@ TEST_P(AutofillManagerStructuredProfileTest,
// the corresponding validity of that type would include both VALID and
// INVALID.
test_cases[0].push_back(
- {"Tennessee",
+ {u"Tennessee",
ADDRESS_HOME_STATE,
{AutofillDataModel::VALID, AutofillDataModel::INVALID}});
// Alice appears only in the second profile as a NAME_FIRST, and it's
// UNVALIDATED.
test_cases[1].push_back(
- {"Alice", NAME_FIRST, {AutofillDataModel::UNVALIDATED}});
+ {u"Alice", NAME_FIRST, {AutofillDataModel::UNVALIDATED}});
// An UNKNOWN type is always UNVALIDATED.
- test_cases[2].push_back({"What a beautiful day!",
+ test_cases[2].push_back({u"What a beautiful day!",
UNKNOWN_TYPE,
{AutofillDataModel::UNVALIDATED}});
@@ -5951,7 +6247,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
ServerFieldTypeValidityStatesMap possible_types_validities;
for (const TestFieldData& test_field : test_fields) {
test::CreateTestFormField("", "1", "", "text", &field);
- field.value = ASCIIToUTF16(test_field.input_value);
+ field.value = test_field.input_value;
form.fields.push_back(field);
}
@@ -5961,7 +6257,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
form_structure.field(i)->set_server_type(test_fields[i].field_type);
}
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, {}, std::u16string(), "en-us", &form_structure);
ASSERT_EQ(test_fields.size(), form_structure.field_count());
@@ -5992,7 +6288,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
}
// Tests that DisambiguateUploadTypes makes the correct choices.
-TEST_P(AutofillManagerStructuredProfileTest, DisambiguateUploadTypes) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, DisambiguateUploadTypes) {
// Set up the test profile.
std::vector<AutofillProfile> profiles;
AutofillProfile profile;
@@ -6012,7 +6308,7 @@ TEST_P(AutofillManagerStructuredProfileTest, DisambiguateUploadTypes) {
credit_cards.push_back(credit_card);
typedef struct {
- std::string input_value;
+ std::u16string input_value;
ServerFieldType predicted_type;
bool expect_disambiguation;
ServerFieldType expected_upload_type;
@@ -6023,30 +6319,30 @@ TEST_P(AutofillManagerStructuredProfileTest, DisambiguateUploadTypes) {
// Address disambiguation.
// An ambiguous address line followed by a field predicted as a line 2 and
// that is empty should be disambiguated as an ADDRESS_HOME_LINE1.
- test_cases[0].push_back({"3734 Elvis Presley Blvd.", ADDRESS_HOME_LINE1, true,
- ADDRESS_HOME_LINE1});
- test_cases[0].push_back({"", ADDRESS_HOME_LINE2, true, EMPTY_TYPE});
+ test_cases[0].push_back({u"3734 Elvis Presley Blvd.", ADDRESS_HOME_LINE1,
+ true, ADDRESS_HOME_LINE1});
+ test_cases[0].push_back({u"", ADDRESS_HOME_LINE2, true, EMPTY_TYPE});
// An ambiguous address line followed by a field predicted as a line 2 but
// filled with another know profile value should be disambiguated as an
// ADDRESS_HOME_STREET_ADDRESS.
- test_cases[1].push_back({"3734 Elvis Presley Blvd.",
+ test_cases[1].push_back({u"3734 Elvis Presley Blvd.",
ADDRESS_HOME_STREET_ADDRESS, true,
ADDRESS_HOME_STREET_ADDRESS});
test_cases[1].push_back(
- {"38116", ADDRESS_HOME_LINE2, true, ADDRESS_HOME_ZIP});
+ {u"38116", ADDRESS_HOME_LINE2, true, ADDRESS_HOME_ZIP});
// An ambiguous address line followed by an empty field predicted as
// something other than a line 2 should be disambiguated as an
// ADDRESS_HOME_STREET_ADDRESS.
- test_cases[2].push_back({"3734 Elvis Presley Blvd.",
+ test_cases[2].push_back({u"3734 Elvis Presley Blvd.",
ADDRESS_HOME_STREET_ADDRESS, true,
ADDRESS_HOME_STREET_ADDRESS});
- test_cases[2].push_back({"", ADDRESS_HOME_ZIP, true, EMPTY_TYPE});
+ test_cases[2].push_back({u"", ADDRESS_HOME_ZIP, true, EMPTY_TYPE});
// An ambiguous address line followed by no other field should be
// disambiguated as an ADDRESS_HOME_STREET_ADDRESS.
- test_cases[3].push_back({"3734 Elvis Presley Blvd.",
+ test_cases[3].push_back({u"3734 Elvis Presley Blvd.",
ADDRESS_HOME_STREET_ADDRESS, true,
ADDRESS_HOME_STREET_ADDRESS});
@@ -6054,7 +6350,7 @@ TEST_P(AutofillManagerStructuredProfileTest, DisambiguateUploadTypes) {
// A field with possible types PHONE_HOME_CITY_AND_NUMBER and
// PHONE_HOME_WHOLE_NUMBER should be disambiguated as
// PHONE_HOME_CITY_AND_NUMBER
- test_cases[4].push_back({"2345678901", PHONE_HOME_WHOLE_NUMBER, true,
+ test_cases[4].push_back({u"2345678901", PHONE_HOME_WHOLE_NUMBER, true,
PHONE_HOME_CITY_AND_NUMBER});
// Name disambiguation.
@@ -6062,71 +6358,73 @@ TEST_P(AutofillManagerStructuredProfileTest, DisambiguateUploadTypes) {
// a non credit card field should be disambiguated as a non credit card
// name.
test_cases[5].push_back(
- {"Memphis", ADDRESS_HOME_CITY, true, ADDRESS_HOME_CITY});
- test_cases[5].push_back({"Elvis", CREDIT_CARD_NAME_FIRST, true, NAME_FIRST});
- test_cases[5].push_back({"Presley", CREDIT_CARD_NAME_LAST, true, NAME_LAST});
+ {u"Memphis", ADDRESS_HOME_CITY, true, ADDRESS_HOME_CITY});
+ test_cases[5].push_back({u"Elvis", CREDIT_CARD_NAME_FIRST, true, NAME_FIRST});
+ test_cases[5].push_back({u"Presley", CREDIT_CARD_NAME_LAST, true, NAME_LAST});
// An ambiguous name field that has no next field and that is preceded by
// a credit card field should be disambiguated as a credit card name.
test_cases[6].push_back(
- {"4234-5678-9012-3456", CREDIT_CARD_NUMBER, true, CREDIT_CARD_NUMBER});
- test_cases[6].push_back({"Elvis", NAME_FIRST, true, CREDIT_CARD_NAME_FIRST});
- test_cases[6].push_back({"Presley", NAME_LAST, true, CREDIT_CARD_NAME_LAST});
+ {u"4234-5678-9012-3456", CREDIT_CARD_NUMBER, true, CREDIT_CARD_NUMBER});
+ test_cases[6].push_back({u"Elvis", NAME_FIRST, true, CREDIT_CARD_NAME_FIRST});
+ test_cases[6].push_back({u"Presley", NAME_LAST, true, CREDIT_CARD_NAME_LAST});
// An ambiguous name field that has no previous field and that is
// followed by a non credit card field should be disambiguated as a non
// credit card name.
- test_cases[7].push_back({"Elvis", CREDIT_CARD_NAME_FIRST, true, NAME_FIRST});
- test_cases[7].push_back({"Presley", CREDIT_CARD_NAME_LAST, true, NAME_LAST});
+ test_cases[7].push_back({u"Elvis", CREDIT_CARD_NAME_FIRST, true, NAME_FIRST});
+ test_cases[7].push_back({u"Presley", CREDIT_CARD_NAME_LAST, true, NAME_LAST});
test_cases[7].push_back(
- {"Memphis", ADDRESS_HOME_CITY, true, ADDRESS_HOME_CITY});
+ {u"Memphis", ADDRESS_HOME_CITY, true, ADDRESS_HOME_CITY});
// An ambiguous name field that has no previous field and that is followed
// by a credit card field should be disambiguated as a credit card name.
- test_cases[8].push_back({"Elvis", NAME_FIRST, true, CREDIT_CARD_NAME_FIRST});
- test_cases[8].push_back({"Presley", NAME_LAST, true, CREDIT_CARD_NAME_LAST});
+ test_cases[8].push_back({u"Elvis", NAME_FIRST, true, CREDIT_CARD_NAME_FIRST});
+ test_cases[8].push_back({u"Presley", NAME_LAST, true, CREDIT_CARD_NAME_LAST});
test_cases[8].push_back(
- {"4234-5678-9012-3456", CREDIT_CARD_NUMBER, true, CREDIT_CARD_NUMBER});
+ {u"4234-5678-9012-3456", CREDIT_CARD_NUMBER, true, CREDIT_CARD_NUMBER});
// An ambiguous name field that is preceded and followed by non credit
// card fields should be disambiguated as a non credit card name.
test_cases[9].push_back(
- {"Memphis", ADDRESS_HOME_CITY, true, ADDRESS_HOME_CITY});
- test_cases[9].push_back({"Elvis", CREDIT_CARD_NAME_FIRST, true, NAME_FIRST});
- test_cases[9].push_back({"Presley", CREDIT_CARD_NAME_LAST, true, NAME_LAST});
+ {u"Memphis", ADDRESS_HOME_CITY, true, ADDRESS_HOME_CITY});
+ test_cases[9].push_back({u"Elvis", CREDIT_CARD_NAME_FIRST, true, NAME_FIRST});
+ test_cases[9].push_back({u"Presley", CREDIT_CARD_NAME_LAST, true, NAME_LAST});
test_cases[9].push_back(
- {"Tennessee", ADDRESS_HOME_STATE, true, ADDRESS_HOME_STATE});
+ {u"Tennessee", ADDRESS_HOME_STATE, true, ADDRESS_HOME_STATE});
// An ambiguous name field that is preceded and followed by credit card
// fields should be disambiguated as a credit card name.
test_cases[10].push_back(
- {"4234-5678-9012-3456", CREDIT_CARD_NUMBER, true, CREDIT_CARD_NUMBER});
- test_cases[10].push_back({"Elvis", NAME_FIRST, true, CREDIT_CARD_NAME_FIRST});
- test_cases[10].push_back({"Presley", NAME_LAST, true, CREDIT_CARD_NAME_LAST});
- test_cases[10].push_back({"2999", CREDIT_CARD_EXP_4_DIGIT_YEAR, true,
+ {u"4234-5678-9012-3456", CREDIT_CARD_NUMBER, true, CREDIT_CARD_NUMBER});
+ test_cases[10].push_back(
+ {u"Elvis", NAME_FIRST, true, CREDIT_CARD_NAME_FIRST});
+ test_cases[10].push_back(
+ {u"Presley", NAME_LAST, true, CREDIT_CARD_NAME_LAST});
+ test_cases[10].push_back({u"2999", CREDIT_CARD_EXP_4_DIGIT_YEAR, true,
CREDIT_CARD_EXP_4_DIGIT_YEAR});
// An ambiguous name field that is preceded by a non credit card field and
// followed by a credit card field should not be disambiguated.
test_cases[11].push_back(
- {"Memphis", ADDRESS_HOME_CITY, true, ADDRESS_HOME_CITY});
+ {u"Memphis", ADDRESS_HOME_CITY, true, ADDRESS_HOME_CITY});
test_cases[11].push_back(
- {"Elvis", NAME_FIRST, false, CREDIT_CARD_NAME_FIRST});
+ {u"Elvis", NAME_FIRST, false, CREDIT_CARD_NAME_FIRST});
test_cases[11].push_back(
- {"Presley", NAME_LAST, false, CREDIT_CARD_NAME_LAST});
- test_cases[11].push_back({"2999", CREDIT_CARD_EXP_4_DIGIT_YEAR, true,
+ {u"Presley", NAME_LAST, false, CREDIT_CARD_NAME_LAST});
+ test_cases[11].push_back({u"2999", CREDIT_CARD_EXP_4_DIGIT_YEAR, true,
CREDIT_CARD_EXP_4_DIGIT_YEAR});
// An ambiguous name field that is preceded by a credit card field and
// followed by a non credit card field should not be disambiguated.
- test_cases[12].push_back({"2999", CREDIT_CARD_EXP_4_DIGIT_YEAR, true,
+ test_cases[12].push_back({u"2999", CREDIT_CARD_EXP_4_DIGIT_YEAR, true,
CREDIT_CARD_EXP_4_DIGIT_YEAR});
test_cases[12].push_back(
- {"Elvis", NAME_FIRST, false, CREDIT_CARD_NAME_FIRST});
+ {u"Elvis", NAME_FIRST, false, CREDIT_CARD_NAME_FIRST});
test_cases[12].push_back(
- {"Presley", NAME_LAST, false, CREDIT_CARD_NAME_LAST});
+ {u"Presley", NAME_LAST, false, CREDIT_CARD_NAME_LAST});
test_cases[12].push_back(
- {"Memphis", ADDRESS_HOME_CITY, true, ADDRESS_HOME_CITY});
+ {u"Memphis", ADDRESS_HOME_CITY, true, ADDRESS_HOME_CITY});
for (const std::vector<TestFieldData>& test_fields : test_cases) {
FormData form;
@@ -6138,7 +6436,7 @@ TEST_P(AutofillManagerStructuredProfileTest, DisambiguateUploadTypes) {
FormFieldData field;
for (const TestFieldData& test_field : test_fields) {
test::CreateTestFormField("", "1", "", "text", &field);
- field.value = ASCIIToUTF16(test_field.input_value);
+ field.value = test_field.input_value;
form.fields.push_back(field);
}
@@ -6147,7 +6445,7 @@ TEST_P(AutofillManagerStructuredProfileTest, DisambiguateUploadTypes) {
for (size_t i = 0; i < test_fields.size(); ++i)
form_structure.field(i)->set_server_type(test_fields[i].predicted_type);
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, credit_cards, std::u16string(), "en-us", &form_structure);
ASSERT_EQ(test_fields.size(), form_structure.field_count());
@@ -6187,7 +6485,7 @@ TEST_P(AutofillManagerStructuredProfileTest, DisambiguateUploadTypes) {
// When a field contains fields with UPI ID values, a crowdsourcing vote should
// be uploaded.
-TEST_P(AutofillManagerStructuredProfileTest, CrowdsourceUPIVPA) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, CrowdsourceUPIVPA) {
std::vector<AutofillProfile> profiles;
std::vector<CreditCard> credit_cards;
@@ -6199,7 +6497,7 @@ TEST_P(AutofillManagerStructuredProfileTest, CrowdsourceUPIVPA) {
form.fields.push_back(field);
FormStructure form_structure(form);
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, credit_cards, std::u16string(), "en-us", &form_structure);
EXPECT_THAT(form_structure.field(0)->possible_types(), ElementsAre(UPI_VPA));
@@ -6208,41 +6506,42 @@ TEST_P(AutofillManagerStructuredProfileTest, CrowdsourceUPIVPA) {
}
// 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_P(AutofillManagerStructuredProfileTest, CrowdsourceCVCFieldByValue) {
+// BrowserAutofillManager reuses the CVC value to identify a potentially
+// existing CVC form field to cast a |CREDIT_CARD_VERIFICATION_CODE|-type vote.
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ 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";
+ const char kCvc[] = "1234";
+ const char16_t kCvc16[] = u"1234";
+ const char kFourDigitButNotCvc[] = "6676";
+ const char kCreditCardNumber[] = "4234-5678-9012-3456";
FormData form;
FormFieldData field1;
- test::CreateTestFormField("number", "number", credit_card_number, "text",
+ test::CreateTestFormField("number", "number", kCreditCardNumber, "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);
+ test::CreateTestFormField("not_cvc", "not_cvc", kFourDigitButNotCvc, "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);
+ test::CreateTestFormField("c_v_c", "c_v_c", kCvc, "text", &field3);
form.fields.push_back(field3);
FormStructure form_structure(form);
form_structure.field(0)->set_possible_types({CREDIT_CARD_NUMBER});
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
- profiles, credit_cards, base::ASCIIToUTF16(cvc), "en-us",
- &form_structure);
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ profiles, credit_cards, kCvc16, "en-us", &form_structure);
CheckThatOnlyFieldByIndexHasThisPossibleType(
form_structure, 2, CREDIT_CARD_VERIFICATION_CODE,
@@ -6251,7 +6550,7 @@ TEST_P(AutofillManagerStructuredProfileTest, CrowdsourceCVCFieldByValue) {
// Expiration year field was detected by the server. The other field with a
// 4-digit value should be detected as CVC.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
CrowdsourceCVCFieldAfterInvalidExpDateByHeuristics) {
FormData form;
FormFieldData field;
@@ -6294,7 +6593,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Set up the test profiles.
std::vector<AutofillProfile> profiles;
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, credit_cards, std::u16string(), "en-us", &form_structure);
CheckThatOnlyFieldByIndexHasThisPossibleType(form_structure, 2,
@@ -6305,7 +6604,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// 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_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
CrowdsourceCVCFieldAfterExpDateByHeuristics) {
FormData form;
FormFieldData field;
@@ -6348,7 +6647,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Set up the test profiles.
std::vector<AutofillProfile> profiles;
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, credit_cards, std::u16string(), "en-us", &form_structure);
CheckThatOnlyFieldByIndexHasThisPossibleType(form_structure, 2,
@@ -6358,7 +6657,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Tests if the CVC field is heuristically detected if it contains a value which
// is not a valid expiration year.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
CrowdsourceCVCFieldBeforeExpDateByHeuristics) {
FormData form;
FormFieldData field;
@@ -6402,7 +6701,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Set up the test profiles.
std::vector<AutofillProfile> profiles;
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, credit_cards, std::u16string(), "en-us", &form_structure);
CheckThatOnlyFieldByIndexHasThisPossibleType(form_structure, 1,
@@ -6412,7 +6711,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Tests if no CVC field is heuristically detected due to the missing of a
// credit card number field.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
CrowdsourceNoCVCFieldDueToMissingCreditCardNumber) {
FormData form;
FormFieldData field;
@@ -6456,14 +6755,14 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Set up the test profiles.
std::vector<AutofillProfile> profiles;
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, credit_cards, std::u16string(), "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_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
CrowdsourceNoCVCDueToInvalidCandidateValue) {
FormData form;
FormFieldData field;
@@ -6507,14 +6806,14 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Set up the test profiles.
std::vector<AutofillProfile> profiles;
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, credit_cards, std::u16string(), "en-us", &form_structure);
CheckThatNoFieldHasThisPossibleType(form_structure,
CREDIT_CARD_VERIFICATION_CODE);
}
-TEST_P(AutofillManagerStructuredProfileTest, RemoveProfile) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, RemoveProfile) {
// Add and remove an Autofill profile.
AutofillProfile profile;
const char guid[] = "00000000-0000-0000-0000-000000000102";
@@ -6523,12 +6822,12 @@ TEST_P(AutofillManagerStructuredProfileTest, RemoveProfile) {
int id = MakeFrontendID(std::string(), guid);
- autofill_manager_->RemoveAutofillProfileOrCreditCard(id);
+ browser_autofill_manager_->RemoveAutofillProfileOrCreditCard(id);
EXPECT_FALSE(personal_data_.GetProfileWithGUID(guid));
}
-TEST_P(AutofillManagerStructuredProfileTest, RemoveCreditCard) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, RemoveCreditCard) {
// Add and remove an Autofill credit card.
CreditCard credit_card;
const char guid[] = "00000000-0000-0000-0000-000000100007";
@@ -6537,13 +6836,13 @@ TEST_P(AutofillManagerStructuredProfileTest, RemoveCreditCard) {
int id = MakeFrontendID(guid, std::string());
- autofill_manager_->RemoveAutofillProfileOrCreditCard(id);
+ browser_autofill_manager_->RemoveAutofillProfileOrCreditCard(id);
EXPECT_FALSE(personal_data_.GetCreditCardWithGUID(guid));
}
// Test our external delegate is called at the right time.
-TEST_P(AutofillManagerStructuredProfileTest, TestExternalDelegate) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, TestExternalDelegate) {
FormData form;
test::CreateTestAddressFormData(&form);
std::vector<FormData> forms(1, form);
@@ -6556,7 +6855,7 @@ TEST_P(AutofillManagerStructuredProfileTest, TestExternalDelegate) {
// Test that unfocusing a filled form sends an upload with types matching the
// fields.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
OnTextFieldDidChangeAndUnfocus_Upload) {
// Set up our form data (it's already filled out with user data).
FormData form;
@@ -6594,8 +6893,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// We will expect these types in the upload and no observed submission (the
// callback initiated by WaitForAsyncUploadProcess checks these expectations.)
- autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
- autofill_manager_->SetExpectedObservedSubmission(false);
+ browser_autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
+ browser_autofill_manager_->SetExpectedObservedSubmission(false);
// The fields are edited after calling FormsSeen on them. This is because
// default values are not used for upload comparisons.
@@ -6603,16 +6902,16 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields[1].value = u"Presley";
form.fields[2].value = u"theking@gmail.com";
// Simulate editing a field.
- autofill_manager_->OnTextFieldDidChange(
+ browser_autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(), AutofillTickClock::NowTicks());
// Simulate lost of focus on the form.
- autofill_manager_->OnFocusNoLongerOnForm(true);
+ browser_autofill_manager_->OnFocusNoLongerOnForm(true);
}
// Test that navigating with a filled form sends an upload with types matching
// the fields.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
OnTextFieldDidChangeAndNavigation_Upload) {
// Set up our form data (it's already filled out with user data).
FormData form;
@@ -6647,8 +6946,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// We will expect these types in the upload and no observed submission. (the
// callback initiated by WaitForAsyncUploadProcess checks these expectations.)
- autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
- autofill_manager_->SetExpectedObservedSubmission(false);
+ browser_autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
+ browser_autofill_manager_->SetExpectedObservedSubmission(false);
// The fields are edited after calling FormsSeen on them. This is because
// default values are not used for upload comparisons.
@@ -6656,16 +6955,16 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields[1].value = u"Presley";
form.fields[2].value = u"theking@gmail.com";
// Simulate editing a field.
- autofill_manager_->OnTextFieldDidChange(
+ browser_autofill_manager_->OnTextFieldDidChange(
form, form.fields.front(), gfx::RectF(), AutofillTickClock::NowTicks());
// Simulate a navigation so that the pending form is uploaded.
- autofill_manager_->Reset();
+ browser_autofill_manager_->Reset();
}
// Test that unfocusing a filled form sends an upload with types matching the
// fields.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
OnDidFillAutofillFormDataAndUnfocus_Upload) {
// Set up our form data (empty).
FormData form;
@@ -6701,24 +7000,24 @@ TEST_P(AutofillManagerStructuredProfileTest,
// We will expect these types in the upload and no observed submission. (the
// callback initiated by WaitForAsyncUploadProcess checks these expectations.)
- autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
- autofill_manager_->SetExpectedObservedSubmission(false);
+ browser_autofill_manager_->SetExpectedSubmittedFieldTypes(expected_types);
+ browser_autofill_manager_->SetExpectedObservedSubmission(false);
// Form was autofilled with user data.
form.fields[0].value = u"Elvis";
form.fields[1].value = u"Presley";
form.fields[2].value = u"theking@gmail.com";
- autofill_manager_->OnDidFillAutofillFormData(form,
- AutofillTickClock::NowTicks());
+ browser_autofill_manager_->OnDidFillAutofillFormData(
+ form, AutofillTickClock::NowTicks());
// Simulate lost of focus on the form.
- autofill_manager_->OnFocusNoLongerOnForm(true);
+ browser_autofill_manager_->OnFocusNoLongerOnForm(true);
}
// Test that suggestions are returned for credit card fields with an
// unrecognized
// autocomplete attribute.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_UnrecognizedAttribute) {
// Set up the form data.
FormData form;
@@ -6756,7 +7055,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test to verify suggestions appears for forms having credit card number split
// across fields.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_ForNumberSplitAcrossFields) {
// Set up our form data with credit card number split across fields.
FormData form;
@@ -6816,12 +7115,14 @@ TEST_P(AutofillManagerStructuredProfileTest,
kDefaultPageID,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
- visa_label, kVisaCard, autofill_manager_->GetPackedCreditCardID(4)));
+ visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(4)));
}
// Test that inputs detected to be CVC inputs are forced to
// !should_autocomplete for AutocompleteHistoryManager::OnWillSubmitForm.
-TEST_P(AutofillManagerStructuredProfileTest, DontSaveCvcInAutocompleteHistory) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ DontSaveCvcInAutocompleteHistory) {
FormData form_seen_by_ahm;
EXPECT_CALL(*(autocomplete_history_manager_.get()), OnWillSubmitForm(_, true))
.WillOnce(SaveArg<0>(&form_seen_by_ahm));
@@ -6862,7 +7163,8 @@ TEST_P(AutofillManagerStructuredProfileTest, DontSaveCvcInAutocompleteHistory) {
}
}
-TEST_P(AutofillManagerStructuredProfileTest, DontOfferToSavePaymentsCard) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ DontOfferToSavePaymentsCard) {
FormData form;
CreditCard card;
PrepareForRealPanResponse(&form, &card);
@@ -6884,11 +7186,12 @@ TEST_P(AutofillManagerStructuredProfileTest, DontOfferToSavePaymentsCard) {
details.cvc = u"123";
full_card_unmask_delegate()->OnUnmaskPromptAccepted(details);
OnDidGetRealPan(AutofillClient::SUCCESS, "4012888888881881");
- autofill_manager_->OnFormSubmitted(form, false,
- SubmissionSource::FORM_SUBMISSION);
+ browser_autofill_manager_->OnFormSubmitted(form, false,
+ SubmissionSource::FORM_SUBMISSION);
}
-TEST_P(AutofillManagerStructuredProfileTest, FillInUpdatedExpirationDate) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ FillInUpdatedExpirationDate) {
FormData form;
CreditCard card;
PrepareForRealPanResponse(&form, &card);
@@ -6902,9 +7205,9 @@ TEST_P(AutofillManagerStructuredProfileTest, FillInUpdatedExpirationDate) {
OnDidGetRealPan(AutofillClient::SUCCESS, "4012888888881881");
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
ProfileDisabledDoesNotFillFormData) {
- autofill_manager_->SetAutofillProfileEnabled(false);
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
// Set up our form data.
FormData form;
@@ -6921,8 +7224,9 @@ TEST_P(AutofillManagerStructuredProfileTest,
MakeFrontendID(std::string(), guid));
}
-TEST_P(AutofillManagerStructuredProfileTest, ProfileDisabledDoesNotSuggest) {
- autofill_manager_->SetAutofillProfileEnabled(false);
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ ProfileDisabledDoesNotSuggest) {
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
// Set up our form data.
FormData form;
@@ -6938,9 +7242,9 @@ TEST_P(AutofillManagerStructuredProfileTest, ProfileDisabledDoesNotSuggest) {
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
CreditCardDisabledDoesNotFillFormData) {
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
// Set up our form data.
FormData form;
@@ -6957,8 +7261,9 @@ TEST_P(AutofillManagerStructuredProfileTest,
MakeFrontendID(guid, std::string()));
}
-TEST_P(AutofillManagerStructuredProfileTest, CreditCardDisabledDoesNotSuggest) {
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ CreditCardDisabledDoesNotSuggest) {
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
// Set up our form data.
FormData form;
@@ -7064,7 +7369,7 @@ TEST_P(SuggestionMatchingTest,
// Verify that typing "mail" will not match any of the "@gmail.com" email
// addresses when substring matching is enabled.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
NoSuggestionForNonPrefixTokenMatch) {
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(features::kAutofillTokenPrefixMatching);
@@ -7104,7 +7409,7 @@ TEST_P(CreditCardSuggestionTest,
"4444555566667777", // Visa
"01", "2030", "1");
credit_card.set_guid(guid);
- credit_card.SetNickname(ASCIIToUTF16(kArbitraryNickname));
+ credit_card.SetNickname(kArbitraryNickname16);
personal_data_.AddCreditCard(credit_card);
#if defined(OS_ANDROID)
@@ -7135,7 +7440,7 @@ TEST_P(CreditCardSuggestionTest,
// Verify that typing "lvis" will not match any of the credit card name when
// substring matching is enabled.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
NoCreditCardSuggestionsForNonPrefixTokenMatch) {
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(features::kAutofillTokenPrefixMatching);
@@ -7154,7 +7459,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
EXPECT_FALSE(external_delegate_->on_suggestions_returned_seen());
}
-TEST_P(AutofillManagerStructuredProfileTest, GetPopupType_CreditCardForm) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ GetPopupType_CreditCardForm) {
// Set up our form data.
FormData form;
CreateTestCreditCardFormData(&form, true, false);
@@ -7163,11 +7469,11 @@ TEST_P(AutofillManagerStructuredProfileTest, GetPopupType_CreditCardForm) {
for (const FormFieldData& field : form.fields) {
EXPECT_EQ(PopupType::kCreditCards,
- autofill_manager_->GetPopupType(form, field));
+ browser_autofill_manager_->GetPopupType(form, field));
}
}
-TEST_P(AutofillManagerStructuredProfileTest, GetPopupType_AddressForm) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, GetPopupType_AddressForm) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -7176,11 +7482,11 @@ TEST_P(AutofillManagerStructuredProfileTest, GetPopupType_AddressForm) {
for (const FormFieldData& field : form.fields) {
EXPECT_EQ(PopupType::kAddresses,
- autofill_manager_->GetPopupType(form, field));
+ browser_autofill_manager_->GetPopupType(form, field));
}
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetPopupType_PersonalInformationForm) {
// Set up our form data.
FormData form;
@@ -7190,13 +7496,13 @@ TEST_P(AutofillManagerStructuredProfileTest,
for (const FormFieldData& field : form.fields) {
EXPECT_EQ(PopupType::kPersonalInformation,
- autofill_manager_->GetPopupType(form, field));
+ browser_autofill_manager_->GetPopupType(form, field));
}
}
// Test that ShouldShowCreditCardSigninPromo behaves as expected for a credit
// card form with an impression limit of three and no impressions yet.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
ShouldShowCreditCardSigninPromo_CreditCardField_UnmetLimit) {
// No impressions yet.
ASSERT_EQ(0, autofill_client_.GetPrefs()->GetInteger(
@@ -7215,7 +7521,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// creating an impression, and false below, preventing an impression.
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(true));
- EXPECT_TRUE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ EXPECT_TRUE(
+ browser_autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
// Expect to now have an impression.
EXPECT_EQ(1, autofill_client_.GetPrefs()->GetInteger(
@@ -7223,7 +7530,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(false));
- EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
// No additional impression.
EXPECT_EQ(1, autofill_client_.GetPrefs()->GetInteger(
@@ -7232,7 +7540,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that ShouldShowCreditCardSigninPromo behaves as expected for a credit
// card form with an impression limit that has been attained already.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
ShouldShowCreditCardSigninPromo_CreditCardField_WithAttainedLimit) {
// Set up our form data.
FormData form;
@@ -7252,11 +7560,13 @@ TEST_P(AutofillManagerStructuredProfileTest,
// ShouldShowSigninPromo().
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(true));
- EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(false));
- EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
// Number of impressions stay the same.
EXPECT_EQ(kCreditCardSigninPromoImpressionLimit,
@@ -7266,7 +7576,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that ShouldShowCreditCardSigninPromo behaves as expected for a credit
// card form on a non-secure page.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
ShouldShowCreditCardSigninPromo_CreditCardField_NonSecureContext) {
// Set up our form data.
FormData form;
@@ -7284,11 +7594,13 @@ TEST_P(AutofillManagerStructuredProfileTest,
// ShouldShowSigninPromo().
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(true));
- EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(false));
- EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
// Number of impressions should remain at zero.
EXPECT_EQ(0, autofill_client_.GetPrefs()->GetInteger(
@@ -7297,7 +7609,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that ShouldShowCreditCardSigninPromo behaves as expected for a credit
// card form targeting a non-secure page.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
ShouldShowCreditCardSigninPromo_CreditCardField_NonSecureAction) {
// Set up our form data.
FormData form;
@@ -7314,11 +7626,13 @@ TEST_P(AutofillManagerStructuredProfileTest,
// ShouldShowSigninPromo().
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(true));
- EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo())
.WillOnce(testing::Return(false));
- EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
// Number of impressions should remain at zero.
EXPECT_EQ(0, autofill_client_.GetPrefs()->GetInteger(
@@ -7327,7 +7641,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that ShouldShowCreditCardSigninPromo behaves as expected for an address
// form.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
ShouldShowCreditCardSigninPromo_AddressField) {
// Set up our form data.
FormData form;
@@ -7340,7 +7654,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Call will now return false, because it is initiated from an address field.
EXPECT_CALL(autofill_client_, ShouldShowSigninPromo()).Times(0);
- EXPECT_FALSE(autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldShowCreditCardSigninPromo(form, field));
}
// Verify that typing "S" into the middle name field will match and order middle
@@ -7395,7 +7710,7 @@ TEST_P(SuggestionMatchingTest,
Suggestion("Adam Smith", label2, "", 2));
}
-TEST_P(AutofillManagerStructuredProfileTest, ShouldUploadForm) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest, ShouldUploadForm) {
// Note: The enforcement of a minimum number of required fields for upload
// is disabled by default. This tests validates both the disabled and enabled
// scenarios.
@@ -7405,44 +7720,46 @@ TEST_P(AutofillManagerStructuredProfileTest, ShouldUploadForm) {
form.action = GURL("https://example.com/submit.html");
// Empty Form.
- EXPECT_FALSE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldUploadForm(FormStructure(form)));
// Add a field to the form.
FormFieldData field;
test::CreateTestFormField("Name", "name", "", "text", &field);
form.fields.push_back(field);
- EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
+ EXPECT_TRUE(browser_autofill_manager_->ShouldUploadForm(FormStructure(form)));
// Add a second field to the form.
test::CreateTestFormField("Email", "email", "", "text", &field);
form.fields.push_back(field);
- EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
+ EXPECT_TRUE(browser_autofill_manager_->ShouldUploadForm(FormStructure(form)));
// Has less than 3 fields but has autocomplete attribute.
form.fields[0].autocomplete_attribute = "given-name";
- EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
+ EXPECT_TRUE(browser_autofill_manager_->ShouldUploadForm(FormStructure(form)));
// Has more than 3 fields, no autocomplete attribute.
form.fields[0].autocomplete_attribute = "";
test::CreateTestFormField("Country", "country", "", "text", &field);
form.fields.push_back(field);
FormStructure form_structure_3(form);
- EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
+ EXPECT_TRUE(browser_autofill_manager_->ShouldUploadForm(FormStructure(form)));
// Has more than 3 fields and at least one autocomplete attribute.
form.fields[0].autocomplete_attribute = "given-name";
- EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
+ EXPECT_TRUE(browser_autofill_manager_->ShouldUploadForm(FormStructure(form)));
// Is off the record.
autofill_driver_->SetIsIncognito(true);
- EXPECT_FALSE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldUploadForm(FormStructure(form)));
// Make sure it's reset for the next test case.
autofill_driver_->SetIsIncognito(false);
- EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
+ EXPECT_TRUE(browser_autofill_manager_->ShouldUploadForm(FormStructure(form)));
// Has one field which is appears to be a password field.
form.fields.clear();
@@ -7450,17 +7767,18 @@ TEST_P(AutofillManagerStructuredProfileTest, ShouldUploadForm) {
form.fields.push_back(field);
// With min required fields disabled.
- EXPECT_TRUE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
+ EXPECT_TRUE(browser_autofill_manager_->ShouldUploadForm(FormStructure(form)));
// Autofill disabled.
- autofill_manager_->SetAutofillProfileEnabled(false);
- autofill_manager_->SetAutofillCreditCardEnabled(false);
- EXPECT_FALSE(autofill_manager_->ShouldUploadForm(FormStructure(form)));
+ browser_autofill_manager_->SetAutofillProfileEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
+ EXPECT_FALSE(
+ browser_autofill_manager_->ShouldUploadForm(FormStructure(form)));
}
// Verify that no suggestions are shown on desktop for non credit card related
// fields if the initiating field has the "autocomplete" attribute set to off.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DisplaySuggestions_AutocompleteOffNotRespected_AddressField) {
// Set up an address form.
FormData mixed_form;
@@ -7495,7 +7813,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Verify that suggestions are shown on desktop for credit card related fields
// even if the initiating field field has the "autocomplete" attribute set to
// off.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DisplaySuggestions_AutocompleteOff_CreditCardField) {
// Set up a credit card form.
FormData mixed_form;
@@ -7526,7 +7844,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Tests that a form with server only types is still autofillable if the form
// gets updated in cache.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DisplaySuggestionsForUpdatedServerTypedForm) {
// Create a form with unknown heuristic fields.
FormData form;
@@ -7556,7 +7874,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
const std::vector<ServerFieldType> server_types{NAME_FIRST, NAME_MIDDLE,
NAME_LAST};
form_structure->SetFieldTypes(heuristic_types, server_types);
- autofill_manager_->AddSeenFormStructure(std::move(form_structure));
+ browser_autofill_manager_->AddSeenFormStructure(std::move(form_structure));
// Make sure the form can be autofilled.
for (const FormFieldData& field : form.fields) {
@@ -7587,7 +7905,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Tests that a form with <select> field is accepted if <option> value (not
// content) is quite long. Some websites use value to propagate long JSON to
// JS-backed logic.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
FormWithLongOptionValuesIsAcceptable) {
FormData form;
form.name = u"MyForm";
@@ -7620,7 +7938,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that is_all_server_suggestions is true if there are only
// full_server_card and masked_server_card on file.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_IsAllServerSuggestionsTrue) {
// Create server credit cards.
CreateTestServerCreditCards();
@@ -7640,7 +7958,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that is_all_server_suggestions is false if there is at least one
// local_card on file.
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
GetCreditCardSuggestions_IsAllServerSuggestionsFalse) {
// Create server and local credit cards.
CreateTestServerAndLocalCreditCards();
@@ -7658,66 +7976,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
ASSERT_FALSE(external_delegate_->is_all_server_suggestions());
}
-// If the rich query feature is enabled, the IsRichQueryEnabled methods only
-// returns true if the channel is neither STABLE not BETA.
-TEST_P(AutofillManagerStructuredProfileTest,
- IsRichQueryEnabled_FeatureEnabled) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(
- features::kAutofillRichMetadataQueries);
-
- for (auto channel :
- {version_info::Channel::STABLE, version_info::Channel::BETA,
- version_info::Channel::CANARY, version_info::Channel::DEV,
- version_info::Channel::UNKNOWN}) {
- SCOPED_TRACE(::testing::Message()
- << "Channel " << static_cast<int>(channel));
- // One more call is from TestAutofillManager constructor.
- EXPECT_CALL(autofill_client_, GetChannel()).WillRepeatedly(Return(channel));
- TestAutofillManager test_instance(autofill_driver_.get(), &autofill_client_,
- &personal_data_,
- autocomplete_history_manager_.get());
- switch (channel) {
- case version_info::Channel::STABLE:
- case version_info::Channel::BETA:
- EXPECT_FALSE(AutofillManager::IsRichQueryEnabled(channel));
- EXPECT_FALSE(test_instance.is_rich_query_enabled());
- break;
- case version_info::Channel::CANARY:
- case version_info::Channel::DEV:
- case version_info::Channel::UNKNOWN:
- EXPECT_TRUE(AutofillManager::IsRichQueryEnabled(channel));
- EXPECT_TRUE(test_instance.is_rich_query_enabled());
- break;
- }
- }
-}
-
-// No matter what the channel, IsRichQueryEnabled returns false if the feature
-// is disabled.
-TEST_P(AutofillManagerStructuredProfileTest,
- IsRichQueryEnabled_FeatureDisabled) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndDisableFeature(
- features::kAutofillRichMetadataQueries);
-
- for (auto channel :
- {version_info::Channel::STABLE, version_info::Channel::BETA,
- version_info::Channel::CANARY, version_info::Channel::DEV,
- version_info::Channel::UNKNOWN}) {
- SCOPED_TRACE(::testing::Message()
- << "Channel " << static_cast<int>(channel));
- EXPECT_FALSE(AutofillManager::IsRichQueryEnabled(channel));
- // One more call is from TestAutofillManager constructor.
- EXPECT_CALL(autofill_client_, GetChannel()).WillRepeatedly(Return(channel));
- TestAutofillManager test_instance(autofill_driver_.get(), &autofill_client_,
- &personal_data_,
- autocomplete_history_manager_.get());
- EXPECT_FALSE(test_instance.is_rich_query_enabled());
- }
-}
-
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogAutocompleteShownMetric) {
FormData form;
form.name = u"NothingSpecial";
@@ -7727,8 +7986,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/false,
- form, field);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/false, form, field);
histogram_tester.ExpectBucketCount(
"Autocomplete.Events", AutofillMetrics::AUTOCOMPLETE_SUGGESTIONS_SHOWN,
1);
@@ -7741,14 +8000,14 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.CreditCard"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogAutofillAddressShownMetric) {
FormData form;
test::CreateTestAddressFormData(&form);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
AutofillMetrics::SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount("Autofill.UserHappiness.Address",
@@ -7770,7 +8029,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.CreditCard"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_AddressOnly) {
// Create a form with name and address fields.
FormData form;
@@ -7792,8 +8051,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.AddressOnly",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -7814,7 +8073,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_AddressOnlyWithoutName) {
// Create a form with address fields.
FormData form;
@@ -7836,8 +8095,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.AddressOnly",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -7858,7 +8117,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_ContactOnly) {
// Create a form with name and contact fields.
FormData form;
@@ -7880,8 +8139,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.ContactOnly",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.ContactOnly",
@@ -7901,7 +8160,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_ContactOnlyWithoutName) {
// Create a form with contact fields.
FormData form;
@@ -7923,8 +8182,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.ContactOnly",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.ContactOnly",
@@ -7944,7 +8203,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_PhoneOnly) {
// Create a form with phone field.
FormData form;
@@ -7966,8 +8225,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.PhoneOnly",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.PhoneOnly",
@@ -7987,7 +8246,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_Other) {
// Create a form with name fields.
FormData form;
@@ -8009,8 +8268,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.Other",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address.Other",
@@ -8030,7 +8289,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.ContactOnly"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_AddressPlusEmail) {
// Create a form with name, address, and email fields.
FormData form;
@@ -8054,8 +8313,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address.AddressPlusEmail",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -8082,7 +8341,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_AddressPlusEmailWithoutName) {
// Create a form with address and email fields.
FormData form;
@@ -8104,8 +8363,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address.AddressPlusEmail",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -8132,7 +8391,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_AddressPlusPhone) {
// Create a form with name fields.
FormData form;
@@ -8156,8 +8415,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address.AddressPlusPhone",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -8184,7 +8443,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_AddressPlusPhoneWithoutName) {
// Create a form with name, address, and phone fields.
FormData form;
@@ -8206,8 +8465,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address.AddressPlusPhone",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -8234,7 +8493,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_AddressPlusEmailPlusPhone) {
// Create a form with name, address, phone, and email fields.
FormData form;
@@ -8260,8 +8519,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address.AddressPlusEmailPlusPhone",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -8287,7 +8546,7 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogByType_AddressPlusEmailPlusPhoneWithoutName) {
// Create a form with address, phone, and email fields.
FormData form;
@@ -8309,8 +8568,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
form.fields.push_back(field);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount(
"Autofill.FormEvents.Address.AddressPlusEmailPlusPhone",
FORM_EVENT_SUGGESTIONS_SHOWN, 1);
@@ -8336,14 +8595,14 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address.Other"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidShowSuggestions_LogAutofillCreditCardShownMetric) {
FormData form;
CreateTestCreditCardFormData(&form, true, false);
base::HistogramTester histogram_tester;
- autofill_manager_->DidShowSuggestions(/*has_autofill_suggestions=*/true, form,
- form.fields[0]);
+ browser_autofill_manager_->DidShowSuggestions(
+ /*has_autofill_suggestions=*/true, form, form.fields[0]);
histogram_tester.ExpectBucketCount("Autofill.UserHappiness",
AutofillMetrics::SUGGESTIONS_SHOWN, 1);
histogram_tester.ExpectBucketCount("Autofill.UserHappiness.CreditCard",
@@ -8364,13 +8623,13 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.Address"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidSuppressPopup_LogAutofillAddressPopupSuppressed) {
FormData form;
test::CreateTestAddressFormData(&form);
base::HistogramTester histogram_tester;
- autofill_manager_->DidSuppressPopup(form, form.fields[0]);
+ browser_autofill_manager_->DidSuppressPopup(form, form.fields[0]);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.Address",
FORM_EVENT_POPUP_SUPPRESSED, 1);
@@ -8382,13 +8641,13 @@ TEST_P(AutofillManagerStructuredProfileTest,
HasSubstr("Autofill.FormEvents.CreditCard"))));
}
-TEST_P(AutofillManagerStructuredProfileTest,
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
DidSuppressPopup_LogAutofillCreditCardPopupSuppressed) {
FormData form;
CreateTestCreditCardFormData(&form, true, false);
base::HistogramTester histogram_tester;
- autofill_manager_->DidSuppressPopup(form, form.fields[0]);
+ browser_autofill_manager_->DidSuppressPopup(form, form.fields[0]);
histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard",
FORM_EVENT_POPUP_SUPPRESSED, 1);
@@ -8401,7 +8660,8 @@ TEST_P(AutofillManagerStructuredProfileTest,
// Test that we import data when the field type is determined by the value and
// without any heuristics on the attributes.
-TEST_P(AutofillManagerStructuredProfileTest, ImportDataWhenValueDetected) {
+TEST_P(BrowserAutofillManagerStructuredProfileTest,
+ ImportDataWhenValueDetected) {
const std::string test_upi_id_value = "user@indianbank";
base::test::ScopedFeatureList scoped_feature_list;
@@ -8423,9 +8683,9 @@ TEST_P(AutofillManagerStructuredProfileTest, ImportDataWhenValueDetected) {
form.fields.push_back(field);
FormsSeen({form});
- autofill_manager_->SetExpectedSubmittedFieldTypes({{UPI_VPA}});
- autofill_manager_->SetExpectedObservedSubmission(true);
- autofill_manager_->SetCallParentUploadFormData(true);
+ browser_autofill_manager_->SetExpectedSubmittedFieldTypes({{UPI_VPA}});
+ browser_autofill_manager_->SetExpectedObservedSubmission(true);
+ browser_autofill_manager_->SetCallParentUploadFormData(true);
form.submission_event =
mojom::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION;
@@ -8441,7 +8701,7 @@ TEST_P(AutofillManagerStructuredProfileTest, ImportDataWhenValueDetected) {
}
// Test that we do not import UPI data when in incognito.
-TEST_F(AutofillManagerTest, DontImportUpiIdWhenIncognito) {
+TEST_F(BrowserAutofillManagerTest, DontImportUpiIdWhenIncognito) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kAutofillSaveAndFillVPA);
autofill_driver_->SetIsIncognito(true);
@@ -8456,9 +8716,9 @@ TEST_F(AutofillManagerTest, DontImportUpiIdWhenIncognito) {
form.fields.push_back(field);
FormsSeen({form});
- autofill_manager_->SetExpectedSubmittedFieldTypes({{UPI_VPA}});
- autofill_manager_->SetExpectedObservedSubmission(true);
- autofill_manager_->SetCallParentUploadFormData(true);
+ browser_autofill_manager_->SetExpectedSubmittedFieldTypes({{UPI_VPA}});
+ browser_autofill_manager_->SetExpectedObservedSubmission(true);
+ browser_autofill_manager_->SetCallParentUploadFormData(true);
form.submission_event =
mojom::SubmissionIndicatorEvent::SAME_DOCUMENT_NAVIGATION;
@@ -8469,7 +8729,7 @@ TEST_F(AutofillManagerTest, DontImportUpiIdWhenIncognito) {
}
// Tests the vote generation for the address enhancement types.
-TEST_F(AutofillManagerTest, PossibleFieldTypesForEnhancementVotes) {
+TEST_F(BrowserAutofillManagerTest, PossibleFieldTypesForEnhancementVotes) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatures(
{features::kAutofillAddressEnhancementVotes},
@@ -8497,7 +8757,7 @@ TEST_F(AutofillManagerTest, PossibleFieldTypesForEnhancementVotes) {
FormStructure form_structure(form);
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, {}, std::u16string(), "en-us", &form_structure);
ASSERT_EQ(4U, form_structure.field_count());
@@ -8516,7 +8776,7 @@ TEST_F(AutofillManagerTest, PossibleFieldTypesForEnhancementVotes) {
scoped_feature_list.InitAndDisableFeature(
features::kAutofillAddressEnhancementVotes);
- AutofillManager::DeterminePossibleFieldTypesForUploadForTest(
+ BrowserAutofillManager::DeterminePossibleFieldTypesForUploadForTest(
profiles, {}, std::u16string(), "en-us", &form_structure);
ASSERT_EQ(4U, form_structure.field_count());
@@ -8531,26 +8791,27 @@ TEST_F(AutofillManagerTest, PossibleFieldTypesForEnhancementVotes) {
ServerFieldTypeSet({UNKNOWN_TYPE}));
}
-TEST_F(AutofillManagerTest, PageLanguageGetsCorrectlySet) {
+TEST_F(BrowserAutofillManagerTest, PageLanguageGetsCorrectlySet) {
FormData form;
test::CreateTestAddressFormData(&form);
- autofill_manager_->OnFormsSeen({form});
+ browser_autofill_manager_->OnFormsSeen({form});
FormStructure* parsed_form =
- autofill_manager_->FindCachedFormByRendererId(form.global_id());
+ browser_autofill_manager_->FindCachedFormByRendererId(form.global_id());
ASSERT_TRUE(parsed_form);
ASSERT_EQ(LanguageCode(), parsed_form->current_page_language());
autofill_client_.GetLanguageState()->SetCurrentLanguage("zh");
- autofill_manager_->OnFormsSeen({form});
- parsed_form = autofill_manager_->FindCachedFormByRendererId(form.global_id());
+ browser_autofill_manager_->OnFormsSeen({form});
+ parsed_form =
+ browser_autofill_manager_->FindCachedFormByRendererId(form.global_id());
ASSERT_EQ(LanguageCode("zh"), parsed_form->current_page_language());
}
-TEST_F(AutofillManagerTest, PageLanguageGetsCorrectlyDetected) {
+TEST_F(BrowserAutofillManagerTest, PageLanguageGetsCorrectlyDetected) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
features::kAutofillParsingPatternsLanguageDetection);
@@ -8558,30 +8819,31 @@ TEST_F(AutofillManagerTest, PageLanguageGetsCorrectlyDetected) {
FormData form;
test::CreateTestAddressFormData(&form);
- autofill_manager_->OnFormsSeen({form});
+ browser_autofill_manager_->OnFormsSeen({form});
FormStructure* parsed_form =
- autofill_manager_->FindCachedFormByRendererId(form.global_id());
+ browser_autofill_manager_->FindCachedFormByRendererId(form.global_id());
ASSERT_TRUE(parsed_form);
ASSERT_EQ(LanguageCode(), parsed_form->current_page_language());
translate::LanguageDetectionDetails language_detection_details;
language_detection_details.adopted_language = "zh";
- autofill_manager_->OnLanguageDetermined(language_detection_details);
+ browser_autofill_manager_->OnLanguageDetermined(language_detection_details);
autofill_client_.GetLanguageState()->SetCurrentLanguage("zh");
- parsed_form = autofill_manager_->FindCachedFormByRendererId(form.global_id());
+ parsed_form =
+ browser_autofill_manager_->FindCachedFormByRendererId(form.global_id());
ASSERT_EQ(LanguageCode("zh"), parsed_form->current_page_language());
}
-// AutofillManagerTest with different browser profile types.
-class AutofillManagerProfileMetricsTest
- : public AutofillManagerTest,
+// BrowserAutofillManagerTest with different browser profile types.
+class BrowserAutofillManagerProfileMetricsTest
+ : public BrowserAutofillManagerTest,
public testing::WithParamInterface<profile_metrics::BrowserProfileType> {
public:
- AutofillManagerProfileMetricsTest() : profile_type_(GetParam()) {
+ BrowserAutofillManagerProfileMetricsTest() : profile_type_(GetParam()) {
EXPECT_CALL(autofill_client_, GetProfileType())
.WillRepeatedly(Return(profile_type_));
}
@@ -8591,7 +8853,8 @@ class AutofillManagerProfileMetricsTest
// Tests if submitting a form in different browser profile types records correct
// |Autofill.FormSubmission.PerProfileType| metric.
-TEST_P(AutofillManagerProfileMetricsTest, FormSubmissionPerProfileTypeMetrics) {
+TEST_P(BrowserAutofillManagerProfileMetricsTest,
+ FormSubmissionPerProfileTypeMetrics) {
// Set up our form data.
FormData form;
test::CreateTestAddressFormData(&form);
@@ -8611,20 +8874,21 @@ TEST_P(AutofillManagerProfileMetricsTest, FormSubmissionPerProfileTypeMetrics) {
INSTANTIATE_TEST_SUITE_P(
All,
- AutofillManagerProfileMetricsTest,
+ BrowserAutofillManagerProfileMetricsTest,
testing::ValuesIn({profile_metrics::BrowserProfileType::kRegular,
profile_metrics::BrowserProfileType::kIncognito,
profile_metrics::BrowserProfileType::kGuest,
profile_metrics::BrowserProfileType::kEphemeralGuest}));
-// AutofillManagerTest with kAutofillDisabledMixedForms feature enabled.
-class AutofillManagerTestWithMixedForms : public AutofillManagerTest {
+// BrowserAutofillManagerTest with kAutofillDisabledMixedForms feature enabled.
+class BrowserAutofillManagerTestWithMixedForms
+ : public BrowserAutofillManagerTest {
protected:
- AutofillManagerTestWithMixedForms() = default;
- ~AutofillManagerTestWithMixedForms() override = default;
+ BrowserAutofillManagerTestWithMixedForms() = default;
+ ~BrowserAutofillManagerTestWithMixedForms() override = default;
void SetUp() override {
- AutofillManagerTest::SetUp();
+ BrowserAutofillManagerTest::SetUp();
scoped_feature_list_.InitAndEnableFeature(
features::kAutofillPreventMixedFormsFilling);
@@ -8633,7 +8897,7 @@ class AutofillManagerTestWithMixedForms : public AutofillManagerTest {
// Test that if a form is mixed content we show a warning instead of any
// suggestions.
-TEST_F(AutofillManagerTestWithMixedForms, GetSuggestions_MixedForm) {
+TEST_F(BrowserAutofillManagerTestWithMixedForms, GetSuggestions_MixedForm) {
// Set up our form data.
FormData form;
form.name = u"MyForm";
@@ -8654,7 +8918,7 @@ TEST_F(AutofillManagerTestWithMixedForms, GetSuggestions_MixedForm) {
// Test that if a form is mixed content we do not show a warning if the opt out
// polcy is set.
-TEST_F(AutofillManagerTestWithMixedForms,
+TEST_F(BrowserAutofillManagerTestWithMixedForms,
GetSuggestions_MixedFormOptoutPolicy) {
// Set pref to disabled.
autofill_client_.GetPrefs()->SetBoolean(::prefs::kMixedFormsWarningsEnabled,
@@ -8675,7 +8939,8 @@ TEST_F(AutofillManagerTestWithMixedForms,
}
// Test that we dismiss the mixed form warning if user starts typing.
-TEST_F(AutofillManagerTestWithMixedForms, GetSuggestions_MixedFormUserTyped) {
+TEST_F(BrowserAutofillManagerTestWithMixedForms,
+ GetSuggestions_MixedFormUserTyped) {
// Set up our form data.
FormData form;
form.name = u"MyForm";
@@ -8702,7 +8967,8 @@ TEST_F(AutofillManagerTestWithMixedForms, GetSuggestions_MixedFormUserTyped) {
// Test that we don't treat javascript scheme target URLs as mixed forms.
// Regression test for crbug.com/1135173
-TEST_F(AutofillManagerTestWithMixedForms, GetSuggestions_JavascriptUrlTarget) {
+TEST_F(BrowserAutofillManagerTestWithMixedForms,
+ GetSuggestions_JavascriptUrlTarget) {
// Set up our form data, using a javascript scheme target URL.
FormData form;
form.name = u"MyForm";
@@ -8718,7 +8984,8 @@ TEST_F(AutofillManagerTestWithMixedForms, GetSuggestions_JavascriptUrlTarget) {
}
// Test that we don't treat about:blank target URLs as mixed forms.
-TEST_F(AutofillManagerTestWithMixedForms, GetSuggestions_AboutBlankTarget) {
+TEST_F(BrowserAutofillManagerTestWithMixedForms,
+ GetSuggestions_AboutBlankTarget) {
// Set up our form data, using a javascript scheme target URL.
FormData form;
form.name = u"MyForm";
@@ -8735,13 +9002,14 @@ TEST_F(AutofillManagerTestWithMixedForms, GetSuggestions_AboutBlankTarget) {
// Desktop only tests.
#if !defined(OS_ANDROID) && !defined(OS_IOS)
-class AutofillManagerTestForVirtualCardOption : public AutofillManagerTest {
+class BrowserAutofillManagerTestForVirtualCardOption
+ : public BrowserAutofillManagerTest {
protected:
- AutofillManagerTestForVirtualCardOption() = default;
- ~AutofillManagerTestForVirtualCardOption() override = default;
+ BrowserAutofillManagerTestForVirtualCardOption() = default;
+ ~BrowserAutofillManagerTestForVirtualCardOption() override = default;
void SetUp() override {
- AutofillManagerTest::SetUp();
+ BrowserAutofillManagerTest::SetUp();
// The URL should always matche the form URL in
// CreateTestCreditCardFormData() to have the allowlist work correctly.
@@ -8788,17 +9056,18 @@ class AutofillManagerTestForVirtualCardOption : public AutofillManagerTest {
external_delegate_->CheckSuggestionCount(kDefaultPageID, 1);
// Suggestion details need to match the credit card added in the SetUp()
// above.
- CheckSuggestions(kDefaultPageID,
- Suggestion(std::string("Visa ") +
- test::ObfuscatedCardDigitsAsUTF8("3456"),
- "Expires on 04/99", kVisaCard,
- autofill_manager_->GetPackedCreditCardID(7)));
+ CheckSuggestions(
+ kDefaultPageID,
+ Suggestion(
+ std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
+ "Expires on 04/99", kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(7)));
}
};
// Ensures the "Use a virtual card number" option should not be shown when
// experiment is disabled.
-TEST_F(AutofillManagerTestForVirtualCardOption,
+TEST_F(BrowserAutofillManagerTestForVirtualCardOption,
ShouldNotShowDueToExperimentDisabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(
@@ -8810,9 +9079,9 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
// Ensures the "Use a virtual card number" option should not be shown when the
// preference for credit card upload is set to disabled.
-TEST_F(AutofillManagerTestForVirtualCardOption,
+TEST_F(BrowserAutofillManagerTestForVirtualCardOption,
ShouldNotShowDueToCreditCardUploadPrefDisabled) {
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
CreateCompleteFormAndGetSuggestions();
external_delegate_->CheckSuggestionCount(kDefaultPageID, 0);
@@ -8820,7 +9089,7 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
// Ensures the "Use a virtual card number" option should not be shown when
// merchant is not allowlisted.
-TEST_F(AutofillManagerTestForVirtualCardOption,
+TEST_F(BrowserAutofillManagerTestForVirtualCardOption,
ShouldNotShowDueToMerchantNotAllowlisted) {
// Adds a different URL in the allowlist.
autofill_client_.set_allowed_merchants(
@@ -8832,7 +9101,7 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
// Ensures the "Use a virtual card number" option should not be shown when card
// number field is not detected.
-TEST_F(AutofillManagerTestForVirtualCardOption,
+TEST_F(BrowserAutofillManagerTestForVirtualCardOption,
ShouldNotShowDueToFormNotHavingCardNumberField) {
// Creates an incomplete form without card number field.
FormData form;
@@ -8861,14 +9130,15 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
base::JoinString({"Visa ", test::ObfuscatedCardDigitsAsUTF8("3456"),
", expires on 04/99"},
"");
- CheckSuggestions(kDefaultPageID,
- Suggestion("Elvis Presley", visa_label, kVisaCard,
- autofill_manager_->GetPackedCreditCardID(7)));
+ CheckSuggestions(
+ kDefaultPageID,
+ Suggestion("Elvis Presley", visa_label, kVisaCard,
+ browser_autofill_manager_->GetPackedCreditCardID(7)));
}
// Ensures the "Use a virtual card number" option should not be shown when there
// is no cloud token data for the card.
-TEST_F(AutofillManagerTestForVirtualCardOption,
+TEST_F(BrowserAutofillManagerTestForVirtualCardOption,
ShouldNotShowDueToNoCloudTokenData) {
CreateCompleteFormAndGetSuggestions();
@@ -8877,7 +9147,7 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
// Ensures the "Use a virtual card number" option should not be shown when there
// is multiple cloud token data for the card.
-TEST_F(AutofillManagerTestForVirtualCardOption,
+TEST_F(BrowserAutofillManagerTestForVirtualCardOption,
ShouldNotShowDueToMultipleCloudTokenData) {
CreateCloudTokenDataForDefaultCard();
CreditCardCloudTokenData data2 = test::GetCreditCardCloudTokenData2();
@@ -8890,7 +9160,7 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
// Ensures the "Use a virtual card number" option should not be shown when card
// expiration date field is not detected.
-TEST_F(AutofillManagerTestForVirtualCardOption,
+TEST_F(BrowserAutofillManagerTestForVirtualCardOption,
ShouldNotShowDueToFormNotHavingExpirationDateField) {
// Creates an incomplete form without expiration date field.
FormData form;
@@ -8917,7 +9187,7 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
// Ensures the "Use a virtual card number" option should not be shown when card
// cvc field is not detected.
-TEST_F(AutofillManagerTestForVirtualCardOption,
+TEST_F(BrowserAutofillManagerTestForVirtualCardOption,
ShouldNotShowDueToFormNotHavingCvcField) {
// Creates an incomplete form without cvc field.
FormData form;
@@ -8946,7 +9216,7 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
// Ensures the "Use a virtual card number" option should be shown when all
// requirements are met.
-TEST_F(AutofillManagerTestForVirtualCardOption,
+TEST_F(BrowserAutofillManagerTestForVirtualCardOption,
ShouldShowVirtualCardOption_OneCard) {
CreateCloudTokenDataForDefaultCard();
CreateCompleteFormAndGetSuggestions();
@@ -8958,7 +9228,7 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"Expires on 04/99", kVisaCard,
- autofill_manager_->GetPackedCreditCardID(7)),
+ browser_autofill_manager_->GetPackedCreditCardID(7)),
Suggestion(l10n_util::GetStringUTF8(
IDS_AUTOFILL_CLOUD_TOKEN_DROPDOWN_OPTION_LABEL),
"", "", PopupItemId::POPUP_ITEM_ID_USE_VIRTUAL_CARD));
@@ -8966,7 +9236,7 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
// Ensures the "Use a virtual card number" option should be shown when there are
// multiple cards and at least one card meets requirements.
-TEST_F(AutofillManagerTestForVirtualCardOption,
+TEST_F(BrowserAutofillManagerTestForVirtualCardOption,
ShouldShowVirtualCardOption_MultipleCards) {
CreateCloudTokenDataForDefaultCard();
@@ -8998,11 +9268,11 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("1111"),
"Expires on 04/99", kVisaCard,
- autofill_manager_->GetPackedCreditCardID(8)),
+ browser_autofill_manager_->GetPackedCreditCardID(8)),
Suggestion(
std::string("Visa ") + test::ObfuscatedCardDigitsAsUTF8("3456"),
"Expires on 04/99", kVisaCard,
- autofill_manager_->GetPackedCreditCardID(7)),
+ browser_autofill_manager_->GetPackedCreditCardID(7)),
Suggestion(l10n_util::GetStringUTF8(
IDS_AUTOFILL_CLOUD_TOKEN_DROPDOWN_OPTION_LABEL),
"", "", PopupItemId::POPUP_ITEM_ID_USE_VIRTUAL_CARD));
@@ -9010,14 +9280,14 @@ TEST_F(AutofillManagerTestForVirtualCardOption,
#endif
// Test param indicates if there is an active screen reader.
-class OnFocusOnFormFieldTest : public AutofillManagerTest,
+class OnFocusOnFormFieldTest : public BrowserAutofillManagerTest,
public testing::WithParamInterface<bool> {
protected:
OnFocusOnFormFieldTest() = default;
~OnFocusOnFormFieldTest() override = default;
void SetUp() override {
- AutofillManagerTest::SetUp();
+ BrowserAutofillManagerTest::SetUp();
has_active_screen_reader_ = GetParam();
external_delegate_->set_has_active_screen_reader(has_active_screen_reader_);
@@ -9025,7 +9295,7 @@ class OnFocusOnFormFieldTest : public AutofillManagerTest,
void TearDown() override {
external_delegate_->set_has_active_screen_reader(false);
- AutofillManagerTest::TearDown();
+ BrowserAutofillManagerTest::TearDown();
}
void CheckSuggestionsAvailableIfScreenReaderRunning() {
@@ -9069,12 +9339,14 @@ TEST_P(OnFocusOnFormFieldTest, AddressSuggestions) {
FormsSeen(forms);
// Suggestions should be returned for the first field.
- autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[0], gfx::RectF());
+ browser_autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[0],
+ gfx::RectF());
CheckSuggestionsAvailableIfScreenReaderRunning();
// No suggestions should be provided for the second field because of its
// unrecognized autocomplete attribute.
- autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1], gfx::RectF());
+ browser_autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1],
+ gfx::RectF());
CheckNoSuggestionsAvailableOnFieldFocus();
}
@@ -9095,10 +9367,28 @@ TEST_P(OnFocusOnFormFieldTest, AddressSuggestions_AutocompleteOffNotRespected) {
std::vector<FormData> forms(1, form);
FormsSeen(forms);
- autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1], gfx::RectF());
+ browser_autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1],
+ gfx::RectF());
CheckSuggestionsAvailableIfScreenReaderRunning();
}
+TEST_P(OnFocusOnFormFieldTest, AddressSuggestions_Ablation) {
+ DisableAutofillViaAblation(scoped_feature_list_, /*for_addresses=*/true,
+ /*for_credit_cards=*/false);
+
+ // Set up our form data.
+ FormData form;
+ test::CreateTestAddressFormData(&form);
+ // Clear the form action.
+ form.action = GURL();
+ std::vector<FormData> forms(1, form);
+ FormsSeen(forms);
+
+ browser_autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1],
+ gfx::RectF());
+ CheckNoSuggestionsAvailableOnFieldFocus();
+}
+
TEST_P(OnFocusOnFormFieldTest, CreditCardSuggestions_SecureContext) {
// Set up our form data.
FormData form;
@@ -9108,7 +9398,8 @@ TEST_P(OnFocusOnFormFieldTest, CreditCardSuggestions_SecureContext) {
std::vector<FormData> forms(1, form);
FormsSeen(forms);
- autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1], gfx::RectF());
+ browser_autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1],
+ gfx::RectF());
CheckSuggestionsAvailableIfScreenReaderRunning();
}
@@ -9121,16 +9412,16 @@ TEST_P(OnFocusOnFormFieldTest, CreditCardSuggestions_NonSecureContext) {
std::vector<FormData> forms(1, form);
FormsSeen(forms);
- autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1], gfx::RectF());
+ browser_autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1],
+ gfx::RectF());
// In a non-HTTPS context, there will be a warning indicating the page is
// insecure.
CheckSuggestionsAvailableIfScreenReaderRunning();
}
TEST_P(OnFocusOnFormFieldTest, CreditCardSuggestions_Ablation) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(
- features::kAutofillCreditCardAblationExperiment);
+ DisableAutofillViaAblation(scoped_feature_list_, /*for_addresses=*/false,
+ /*for_credit_cards=*/true);
// Set up our form data.
FormData form;
@@ -9140,12 +9431,13 @@ TEST_P(OnFocusOnFormFieldTest, CreditCardSuggestions_Ablation) {
std::vector<FormData> forms(1, form);
FormsSeen(forms);
- autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1], gfx::RectF());
+ browser_autofill_manager_->OnFocusOnFormFieldImpl(form, form.fields[1],
+ gfx::RectF());
CheckNoSuggestionsAvailableOnFieldFocus();
}
INSTANTIATE_TEST_SUITE_P(
- AutofillManagerTest,
+ BrowserAutofillManagerTest,
ProfileMatchingTypesTest,
testing::Combine(
testing::ValuesIn(kProfileMatchingTypesTestCases),
@@ -9159,7 +9451,7 @@ INSTANTIATE_TEST_SUITE_P(All, OnFocusOnFormFieldTest, testing::Bool());
// Runs the suite with the feature |kAutofillSupportForMoreStructuredNames|
// enabled and disabled.
INSTANTIATE_TEST_SUITE_P(,
- AutofillManagerStructuredProfileTest,
+ BrowserAutofillManagerStructuredProfileTest,
testing::Bool());
#if defined(OS_IOS) || defined(OS_ANDROID)
diff --git a/chromium/components/autofill/core/browser/data_model/address.cc b/chromium/components/autofill/core/browser/data_model/address.cc
index 9e68a112868..2be86ef6a28 100644
--- a/chromium/components/autofill/core/browser/data_model/address.cc
+++ b/chromium/components/autofill/core/browser/data_model/address.cc
@@ -54,9 +54,9 @@ bool Address::operator==(const Address& other) const {
!are_states_equal) {
// If the canonical state name exists for |state_| and |other.state_|, they
// are compared otherwise.
- base::Optional<AlternativeStateNameMap::CanonicalStateName>
+ absl::optional<AlternativeStateNameMap::CanonicalStateName>
canonical_state_name_cur = GetCanonicalizedStateName();
- base::Optional<AlternativeStateNameMap::CanonicalStateName>
+ absl::optional<AlternativeStateNameMap::CanonicalStateName>
canonical_state_name_other = other.GetCanonicalizedStateName();
if (canonical_state_name_cur && canonical_state_name_other) {
are_states_equal =
@@ -102,7 +102,7 @@ bool Address::MergeStructuredAddress(const Address& newer,
newer_was_more_recently_used);
}
-base::Optional<AlternativeStateNameMap::CanonicalStateName>
+absl::optional<AlternativeStateNameMap::CanonicalStateName>
Address::GetCanonicalizedStateName() const {
return AlternativeStateNameMap::GetCanonicalStateName(
base::UTF16ToUTF8(GetRawInfo(ADDRESS_HOME_COUNTRY)),
diff --git a/chromium/components/autofill/core/browser/data_model/address.h b/chromium/components/autofill/core/browser/data_model/address.h
index 83348474381..f518549c2be 100644
--- a/chromium/components/autofill/core/browser/data_model/address.h
+++ b/chromium/components/autofill/core/browser/data_model/address.h
@@ -55,7 +55,7 @@ class Address : public FormGroup {
// Fetches the canonical state name for the current address object if
// possible.
- base::Optional<AlternativeStateNameMap::CanonicalStateName>
+ absl::optional<AlternativeStateNameMap::CanonicalStateName>
GetCanonicalizedStateName() const;
// For structured addresses, returns true if |this| is mergeable with |newer|.
diff --git a/chromium/components/autofill/core/browser/data_model/address_unittest.cc b/chromium/components/autofill/core/browser/data_model/address_unittest.cc
index b81c20a03bd..afeda7b873d 100644
--- a/chromium/components/autofill/core/browser/data_model/address_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/address_unittest.cc
@@ -429,30 +429,34 @@ TEST_P(AddressTest, GetStreetAddress) {
EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE3).empty());
- EXPECT_EQ(ASCIIToUTF16("123 Example Ave.\n"
- "Apt. 42"),
- address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
- EXPECT_EQ(ASCIIToUTF16("123 Example Ave.\n"
- "Apt. 42"),
- address.GetInfo(type, "en-US"));
+ EXPECT_EQ(
+ u"123 Example Ave.\n"
+ u"Apt. 42",
+ address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ EXPECT_EQ(
+ u"123 Example Ave.\n"
+ u"Apt. 42",
+ address.GetInfo(type, "en-US"));
// A wild third line appears.
address.SetRawInfo(ADDRESS_HOME_LINE3, u"Living room couch");
EXPECT_EQ(u"Living room couch", address.GetRawInfo(ADDRESS_HOME_LINE3));
- EXPECT_EQ(ASCIIToUTF16("123 Example Ave.\n"
- "Apt. 42\n"
- "Living room couch"),
- address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ EXPECT_EQ(
+ u"123 Example Ave.\n"
+ u"Apt. 42\n"
+ u"Living room couch",
+ address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
// The second line vanishes.
address.SetRawInfo(ADDRESS_HOME_LINE2, std::u16string());
EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty());
EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty());
EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE3).empty());
- EXPECT_EQ(ASCIIToUTF16("123 Example Ave.\n"
- "\n"
- "Living room couch"),
- address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ EXPECT_EQ(
+ u"123 Example Ave.\n"
+ u"\n"
+ u"Living room couch",
+ address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
}
// Verifies that overwriting an address with N lines with one that has fewer
@@ -477,10 +481,10 @@ TEST_P(AddressTest, GetStreetAddressAfterOverwritingLongAddressWithShorterOne) {
TEST_P(AddressTest, SetRawStreetAddress) {
const std::u16string empty_street_address;
const std::u16string short_street_address = u"456 Nowhere Ln.";
- const std::u16string long_street_address = ASCIIToUTF16(
- "123 Example Ave.\n"
- "Apt. 42\n"
- "(The one with the blue door)");
+ const std::u16string long_street_address =
+ u"123 Example Ave.\n"
+ u"Apt. 42\n"
+ u"(The one with the blue door)";
Address address;
EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE1));
@@ -507,10 +511,10 @@ TEST_P(AddressTest, SetRawStreetAddress) {
// Street addresses should be set properly.
TEST_P(AddressTest, SetStreetAddress) {
const std::u16string empty_street_address;
- const std::u16string multi_line_street_address = ASCIIToUTF16(
- "789 Fancy Pkwy.\n"
- "Unit 3.14\n"
- "Box 9");
+ const std::u16string multi_line_street_address =
+ u"789 Fancy Pkwy.\n"
+ u"Unit 3.14\n"
+ u"Box 9";
const std::u16string single_line_street_address = u"123 Main, Apt 7";
const AutofillType type = AutofillType(ADDRESS_HOME_STREET_ADDRESS);
@@ -561,9 +565,9 @@ TEST_P(AddressTest, SetStreetAddressRejectsAddressesWithInteriorBlankLines) {
// Attempting to set an address with interior blank lines should fail, and
// clear out the previously stored address.
EXPECT_FALSE(address.SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS),
- ASCIIToUTF16("Address line 1\n"
- "\n"
- "Address line 3"),
+ u"Address line 1\n"
+ u"\n"
+ u"Address line 3",
"en-US"));
EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE1));
EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2));
@@ -584,9 +588,9 @@ TEST_P(AddressTest, SetStreetAddressRejectsAddressesWithLeadingBlankLines) {
// Attempting to set an address with leading blank lines should fail, and
// clear out the previously stored address.
EXPECT_FALSE(address.SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS),
- ASCIIToUTF16("\n"
- "Address line 2"
- "Address line 3"),
+ u"\n"
+ u"Address line 2"
+ u"Address line 3",
"en-US"));
EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE1));
EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2));
@@ -607,9 +611,9 @@ TEST_P(AddressTest, SetStreetAddressRejectsAddressesWithTrailingBlankLines) {
// Attempting to set an address with leading blank lines should fail, and
// clear out the previously stored address.
EXPECT_FALSE(address.SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS),
- ASCIIToUTF16("Address line 1"
- "Address line 2"
- "\n"),
+ u"Address line 1"
+ u"Address line 2"
+ u"\n",
"en-US"));
EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE1));
EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2));
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_offer_data.cc b/chromium/components/autofill/core/browser/data_model/autofill_offer_data.cc
index 35efef462e0..9fba505f834 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_offer_data.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_offer_data.cc
@@ -71,7 +71,36 @@ int AutofillOfferData::Compare(
if (eligible_instrument_id_copy > other_eligible_instrument_id_copy)
return 1;
+ comparison = promo_code.compare(other_offer_data.promo_code);
+ if (comparison != 0)
+ return comparison;
+
+ comparison = display_strings.value_prop_text.compare(
+ other_offer_data.display_strings.value_prop_text);
+ if (comparison != 0)
+ return comparison;
+
+ comparison = display_strings.see_details_text.compare(
+ other_offer_data.display_strings.see_details_text);
+ if (comparison != 0)
+ return comparison;
+
+ comparison = display_strings.usage_instructions_text.compare(
+ other_offer_data.display_strings.usage_instructions_text);
+ if (comparison != 0)
+ return comparison;
+
return 0;
}
+bool AutofillOfferData::IsCardLinkedOffer() const {
+ // Card-linked offers have at least one |eligible_instrument_id|.
+ return !eligible_instrument_id.empty();
+}
+
+bool AutofillOfferData::IsPromoCodeOffer() const {
+ // Promo code offers have the promo code field populated.
+ return !promo_code.empty();
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_offer_data.h b/chromium/components/autofill/core/browser/data_model/autofill_offer_data.h
index d45263de731..99d084a38d1 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_offer_data.h
+++ b/chromium/components/autofill/core/browser/data_model/autofill_offer_data.h
@@ -13,9 +13,23 @@
namespace autofill {
-// Represents an offer for certain merchants redeemable with certain cards.
-// Merchants are determined by |merchant_domain| and the unique ids of cards are
-// stored in |eligible_instrument_id|.
+// Server-driven strings for certain Offer UI elements.
+struct DisplayStrings {
+ // Explains the value of the offer. For example,
+ // "5% off on shoes. Up to $50.".
+ std::string value_prop_text;
+ // A message implying or linking to additional details, usually "See details"
+ // or "Terms apply", depending on the platform.
+ std::string see_details_text;
+ // Instructs the user on how they can redeem the offer, such as clicking into
+ // a merchant's promo code field to trigger Autofill.
+ std::string usage_instructions_text;
+};
+
+// Represents an offer for certain merchants. Card-linked offers are redeemable
+// with certain cards, and the unique ids of those cards are stored in
+// |eligible_instrument_id|. Promo code offers are redeemable with autofillable
+// promo codes. Merchants are determined by |merchant_domain|.
struct AutofillOfferData {
public:
AutofillOfferData();
@@ -30,13 +44,15 @@ struct AutofillOfferData {
// result of first found difference.
int Compare(const AutofillOfferData& other_offer_data) const;
+ // Returns true if the current offer is a card-linked offer.
+ bool IsCardLinkedOffer() const;
+
+ // Returns true if the current offer is a promo code offer.
+ bool IsPromoCodeOffer() const;
+
// The unique server ID for this offer data.
int64_t offer_id;
- // The string including the reward details of the offer. Could be either
- // percentage off (XXX%) or fixed amount off ($XXX).
- std::string offer_reward_amount;
-
// The timestamp when the offer will expire. Expired offers will not be shown
// in the frontend.
base::Time expiry;
@@ -47,8 +63,24 @@ struct AutofillOfferData {
// The merchants' URLs where this offer can be redeemed.
std::vector<GURL> merchant_domain;
+ // Optional server-driven strings for certain offer elements. Generally most
+ // useful for promo code offers, but could potentially apply to card-linked
+ // offers as well.
+ DisplayStrings display_strings;
+
+ /* Card-linked offer-specific fields */
+
+ // The string including the reward details of the offer. Could be either
+ // percentage off (XXX%) or fixed amount off ($XXX).
+ std::string offer_reward_amount;
+
// The ids of the cards this offer can be applied to.
std::vector<int64_t> eligible_instrument_id;
+
+ /* Promo code offer-specific fields */
+
+ // A promo/gift/coupon code that can be applied at checkout with the merchant.
+ std::string promo_code;
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile.cc b/chromium/components/autofill/core/browser/data_model/autofill_profile.cc
index abe400343a8..d387796eb0f 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -269,6 +269,8 @@ AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) {
if (this == &profile)
return *this;
+ set_disallow_settings_visible_updates(
+ profile.disallow_settings_visible_updates());
set_use_count(profile.use_count());
set_use_date(profile.use_date());
set_previous_use_date(profile.previous_use_date());
@@ -277,6 +279,8 @@ AutofillProfile& AutofillProfile::operator=(const AutofillProfile& profile) {
set_guid(profile.guid());
set_origin(profile.origin());
+ set_profile_label(profile.profile_label());
+
record_type_ = profile.record_type_;
name_ = profile.name_;
@@ -691,7 +695,11 @@ bool AutofillProfile::MergeStructuredDataFrom(const AutofillProfile& profile,
bool AutofillProfile::MergeDataFrom(const AutofillProfile& profile,
const std::string& app_locale) {
// Verified profiles should never be overwritten with unverified data.
- DCHECK(!IsVerified() || profile.IsVerified());
+ // This is not true anymore when explicit save prompts are used.
+ DCHECK(!IsVerified() || profile.IsVerified() ||
+ base::FeatureList::IsEnabled(
+ features::kAutofillAddressProfileSavePrompt));
+
AutofillProfileComparator comparator(app_locale);
DCHECK(comparator.AreMergeable(*this, profile));
@@ -956,6 +964,12 @@ void AutofillProfile::RecordAndLogUse() {
UMA_HISTOGRAM_COUNTS_1000("Autofill.DaysSinceLastUse.Profile",
(AutofillClock::Now() - use_date()).InDays());
RecordUse();
+ LogVerificationStatuses();
+}
+
+void AutofillProfile::LogVerificationStatuses() {
+ AutofillMetrics::LogVerificationStatusOfNameTokensOnProfileUsage(*this);
+ AutofillMetrics::LogVerificationStatusOfAddressTokensOnProfileUsage(*this);
}
bool AutofillProfile::HasGreaterFrescocencyThan(
@@ -1314,7 +1328,10 @@ FormGroup* AutofillProfile::MutableFormGroupForType(const AutofillType& type) {
bool AutofillProfile::EqualsSansGuid(const AutofillProfile& profile) const {
return origin() == profile.origin() &&
- language_code() == profile.language_code() && Compare(profile) == 0;
+ disallow_settings_visible_updates() ==
+ profile.disallow_settings_visible_updates() &&
+ language_code() == profile.language_code() &&
+ profile_label() == profile.profile_label() && Compare(profile) == 0;
}
std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
@@ -1323,6 +1340,7 @@ std::ostream& operator<<(std::ostream& os, const AutofillProfile& profile) {
: base::HexEncode(profile.server_id().data(),
profile.server_id().size()))
<< " " << profile.origin() << " "
+ << "label: " << profile.profile_label() << " "
<< profile.GetClientValidityBitfieldValue() << " "
<< profile.has_converted() << " " << profile.use_count() << " "
<< profile.use_date() << " " << profile.language_code() << std::endl;
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile.h b/chromium/components/autofill/core/browser/data_model/autofill_profile.h
index cb82d28b473..c43a5193e10 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile.h
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile.h
@@ -207,8 +207,13 @@ class AutofillProfile : public AutofillDataModel {
// Logs the number of days since the profile was last used, records its
// use and updates |previous_use_date_| to the last value of |use_date_|.
+ // Also initiates the logging of the structured token verification statuses.
void RecordAndLogUse();
+ // Logs the verification status of non-empty structured name and address
+ // tokens. Should be called when a profile is used to fill a form.
+ void LogVerificationStatuses();
+
// Returns true if the current profile has greater frescocency than the
// |other|. Frescocency is a combination of validation score and frecency to
// determine the relevance of the profile. Frescocency is a total order: it
@@ -299,6 +304,19 @@ class AutofillProfile : public AutofillDataModel {
// Returns a constant reference to the |address_| field.
const Address& GetAddress() const { return address_; }
+ // Returns the label of the profile.
+ const std::string& profile_label() const { return profile_label_; }
+
+ // Sets the label of the profile.
+ void set_profile_label(const std::string& label) { profile_label_ = label; }
+
+ bool disallow_settings_visible_updates() const {
+ return disallow_settings_visible_updates_;
+ }
+ void set_disallow_settings_visible_updates(bool disallow) {
+ disallow_settings_visible_updates_ = disallow;
+ }
+
private:
// FormGroup:
std::u16string GetInfoImpl(const AutofillType& type,
@@ -346,9 +364,21 @@ class AutofillProfile : public AutofillDataModel {
PhoneNumber phone_number_;
Address address_;
+ // The label is chosen by the user and can contain an arbitrary value.
+ // However, there are two labels that play a special role to indicate that an
+ // address is either a 'HOME' or a 'WORK' address. In this case, the value of
+ // the label is '$HOME$' or '$WORK$', respectively.
+ std::string profile_label_;
+
// The BCP 47 language code that can be used to format |address_| for display.
std::string language_code_;
+ // The state indicates if the profile qualifies to get merged with a
+ // profile observed in a form submission. If true, the profile can still be
+ // updated silently, but it should not be considered for merges that need to
+ // involve user interactions.
+ bool disallow_settings_visible_updates_{false};
+
// ID used for identifying this profile. Only set for SERVER_PROFILEs. This is
// a hash of the contents.
std::string server_id_;
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.cc b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.cc
index de6ffefc991..162eac57330 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.cc
@@ -10,7 +10,6 @@
#include "base/i18n/case_conversion.h"
#include "base/i18n/char_iterator.h"
#include "base/i18n/unicodestring.h"
-#include "base/optional.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversion_utils.h"
@@ -23,6 +22,7 @@
#include "components/autofill/core/browser/geo/state_names.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_features.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/libphonenumber/phonenumber_api.h"
using base::UTF16ToUTF8;
@@ -220,12 +220,96 @@ void SortProfilesByFrecency(std::vector<AutofillProfile*>* profiles) {
} // namespace
+// The values corresponding to those types are visible in the settings.
+ServerFieldTypeSet GetUserVisibleTypes() {
+ static const ServerFieldTypeSet user_visibe_type = {
+ NAME_FULL,
+ NAME_HONORIFIC_PREFIX,
+ ADDRESS_HOME_STREET_ADDRESS,
+ ADDRESS_HOME_CITY,
+ ADDRESS_HOME_DEPENDENT_LOCALITY,
+ ADDRESS_HOME_STATE,
+ ADDRESS_HOME_ZIP,
+ ADDRESS_HOME_COUNTRY,
+ EMAIL_ADDRESS,
+ PHONE_HOME_WHOLE_NUMBER,
+ COMPANY_NAME};
+ return user_visibe_type;
+}
+
+bool ProfileValueDifference::operator==(
+ const ProfileValueDifference& right) const {
+ return (type == right.type) && (first_value == right.first_value) &&
+ (second_value == right.second_value);
+}
+
AutofillProfileComparator::AutofillProfileComparator(
const base::StringPiece& app_locale)
: app_locale_(app_locale.data(), app_locale.size()) {}
AutofillProfileComparator::~AutofillProfileComparator() = default;
+std::vector<ProfileValueDifference>
+AutofillProfileComparator::GetProfileDifference(
+ const AutofillProfile& first_profile,
+ const AutofillProfile& second_profile,
+ ServerFieldTypeSet types,
+ const std::string& app_locale) {
+ std::vector<ProfileValueDifference> difference;
+ difference.reserve(types.size());
+
+ for (auto type : types) {
+ const std::u16string& first_value = first_profile.GetInfo(type, app_locale);
+ const std::u16string& second_value =
+ second_profile.GetInfo(type, app_locale);
+ if (first_value != second_value) {
+ difference.emplace_back(
+ ProfileValueDifference{type, first_value, second_value});
+ }
+ }
+ return difference;
+}
+
+base::flat_map<ServerFieldType, std::pair<std::u16string, std::u16string>>
+AutofillProfileComparator::GetProfileDifferenceMap(
+ const AutofillProfile& first_profile,
+ const AutofillProfile& second_profile,
+ ServerFieldTypeSet types,
+ const std::string& app_locale) {
+ std::vector<
+ std::pair<ServerFieldType, std::pair<std::u16string, std::u16string>>>
+ result;
+ result.reserve(types.size());
+
+ for (auto& diff : AutofillProfileComparator::GetProfileDifference(
+ first_profile, second_profile, types, app_locale)) {
+ result.push_back(
+ {diff.type,
+ {std::move(diff.first_value), std::move(diff.second_value)}});
+ }
+ return base::flat_map<ServerFieldType,
+ std::pair<std::u16string, std::u16string>>(
+ std::move(result));
+}
+
+std::vector<ProfileValueDifference>
+AutofillProfileComparator::GetSettingsVisibleProfileDifference(
+ const AutofillProfile& first_profile,
+ const AutofillProfile& second_profile,
+ const std::string& app_locale) {
+ return GetProfileDifference(first_profile, second_profile,
+ GetUserVisibleTypes(), app_locale);
+}
+
+base::flat_map<ServerFieldType, std::pair<std::u16string, std::u16string>>
+AutofillProfileComparator::GetSettingsVisibleProfileDifferenceMap(
+ const AutofillProfile& first_profile,
+ const AutofillProfile& second_profile,
+ const std::string& app_locale) {
+ return GetProfileDifferenceMap(first_profile, second_profile,
+ GetUserVisibleTypes(), app_locale);
+}
+
bool AutofillProfileComparator::Compare(base::StringPiece16 text1,
base::StringPiece16 text2,
WhitespaceSpec whitespace_spec) const {
@@ -916,15 +1000,10 @@ bool AutofillProfileComparator::MergeAddresses(const AutofillProfile& p1,
bool AutofillProfileComparator::ProfilesHaveDifferentSettingsVisibleValues(
const AutofillProfile& p1,
const AutofillProfile& p2) {
- // The values corresponding to those types are visible in the settings.
- static const ServerFieldTypeSet kUserVisibleTypes = {
- NAME_FULL, NAME_HONORIFIC_PREFIX, ADDRESS_HOME_STREET_ADDRESS,
- ADDRESS_HOME_CITY, ADDRESS_HOME_ZIP, ADDRESS_HOME_COUNTRY,
- EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER};
// Return true if at least one value corresponding to the settings visible
// types is different between the two profiles.
- return base::ranges::any_of(kUserVisibleTypes, [&](const auto type) {
+ return base::ranges::any_of(GetUserVisibleTypes(), [&](const auto type) {
return p1.GetRawInfo(type) != p2.GetRawInfo(type);
});
}
@@ -953,7 +1032,7 @@ bool AutofillProfileComparator::IsMergeCandidate(
}
// static
-base::Optional<AutofillProfile>
+absl::optional<AutofillProfile>
AutofillProfileComparator::GetAutofillProfileMergeCandidate(
const AutofillProfile& new_profile,
const std::vector<AutofillProfile*>& existing_profiles,
@@ -966,7 +1045,7 @@ AutofillProfileComparator::GetAutofillProfileMergeCandidate(
SortProfilesByFrecency(&existing_profiles_copies);
// Find and return the first profile that classifies as a merge candidate. If
- // not profile classifies, return |base::nullopt|.
+ // not profile classifies, return |absl::nullopt|.
AutofillProfileComparator comparator(app_locale);
auto merge_candidate = base::ranges::find_if(
existing_profiles_copies, [&](const AutofillProfile* existing_profile) {
@@ -975,8 +1054,8 @@ AutofillProfileComparator::GetAutofillProfileMergeCandidate(
});
return merge_candidate != existing_profiles_copies.end()
- ? base::make_optional(**merge_candidate)
- : base::nullopt;
+ ? absl::make_optional(**merge_candidate)
+ : absl::nullopt;
}
// static
@@ -1280,9 +1359,9 @@ bool AutofillProfileComparator::HaveMergeableAddresses(
bool use_alternative_state_name_map_enabled = base::FeatureList::IsEnabled(
features::kAutofillUseAlternativeStateNameMap);
if (use_alternative_state_name_map_enabled) {
- base::Optional<AlternativeStateNameMap::CanonicalStateName>
+ absl::optional<AlternativeStateNameMap::CanonicalStateName>
canonical_name_state1 = p1.GetAddress().GetCanonicalizedStateName();
- base::Optional<AlternativeStateNameMap::CanonicalStateName>
+ absl::optional<AlternativeStateNameMap::CanonicalStateName>
canonical_name_state2 = p2.GetAddress().GetCanonicalizedStateName();
if (canonical_name_state1 && canonical_name_state2) {
if (canonical_name_state1.value() == canonical_name_state2.value())
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.h b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.h
index 2ba6086bb63..32d3ba53075 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.h
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator.h
@@ -9,6 +9,7 @@
#include <set>
#include <string>
+#include "base/containers/flat_map.h"
#include "base/strings/string_piece.h"
#include "components/autofill/core/browser/data_model/address.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -18,6 +19,18 @@
namespace autofill {
+struct ProfileValueDifference {
+ // The type of the field that is different.
+ ServerFieldType type;
+ // The original value.
+ std::u16string first_value;
+ // The new value.
+ std::u16string second_value;
+ bool operator==(const ProfileValueDifference& right) const;
+};
+
+ServerFieldTypeSet GetUserVisibleTypes();
+
// A utility class to assist in the comparison of AutofillProfile data.
class AutofillProfileComparator {
public:
@@ -45,9 +58,9 @@ class AutofillProfileComparator {
WhitespaceSpec whitespace_spec = DISCARD_WHITESPACE) const;
// Returns the first merge candidate from |existing_profiles| for
- // |new_profile| as an optional. If no merge candidate exists |base::nullopt|
+ // |new_profile| as an optional. If no merge candidate exists |absl::nullopt|
// is returned.
- static base::Optional<AutofillProfile> GetAutofillProfileMergeCandidate(
+ static absl::optional<AutofillProfile> GetAutofillProfileMergeCandidate(
const AutofillProfile& new_profile,
const std::vector<AutofillProfile*>& existing_profiles,
const std::string& app_locale);
@@ -69,6 +82,40 @@ class AutofillProfileComparator {
// character is skippable if it is punctuation or white space.
bool HasOnlySkippableCharacters(base::StringPiece16 text) const;
+ // Get the difference in 'types' of two profiles. The difference is determined
+ // with respect to the provided `app_locale`.
+ static std::vector<ProfileValueDifference> GetProfileDifference(
+ const AutofillProfile& first_profile,
+ const AutofillProfile& second_profile,
+ ServerFieldTypeSet types,
+ const std::string& app_locale);
+
+ // Same as `GetProfileDifference()` but returns a map that maps the type to a
+ // pair of strings that contain the corresponding value from the first and
+ // second profile.
+ static base::flat_map<ServerFieldType,
+ std::pair<std::u16string, std::u16string>>
+ GetProfileDifferenceMap(const AutofillProfile& first_profile,
+ const AutofillProfile& second_profile,
+ ServerFieldTypeSet types,
+ const std::string& app_locale);
+
+ // Get the difference of two profiles for settings-visible values.
+ // The difference is determined with respect to the provided `app_locale`.
+ static std::vector<ProfileValueDifference>
+ GetSettingsVisibleProfileDifference(const AutofillProfile& first_profile,
+ const AutofillProfile& second_profile,
+ const std::string& app_locale);
+
+ // Same as `GetSettingsVisibleProfileDifference()` but returns a map that maps
+ // the type to a pair of strings that contain the corresponding value from the
+ // first and second profile.
+ static base::flat_map<ServerFieldType,
+ std::pair<std::u16string, std::u16string>>
+ GetSettingsVisibleProfileDifferenceMap(const AutofillProfile& first_profile,
+ const AutofillProfile& second_profile,
+ const std::string& app_locale);
+
// Returns a copy of |text| with uppercase converted to lowercase and
// diacritics removed.
//
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc
index 6f1614f46b2..416d34ec42e 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile_comparator_unittest.cc
@@ -56,7 +56,6 @@ using autofill::EmailInfo;
using autofill::NameInfo;
using autofill::PhoneNumber;
using autofill::ServerFieldType;
-using base::UTF8ToUTF16;
namespace {
@@ -93,22 +92,22 @@ class AutofillProfileComparatorTest
autofill::CountryNames::SetLocaleString(kLocale);
}
- NameInfo CreateNameInfo(const char* first,
- const char* middle,
- const char* last,
- const char* full) {
+ NameInfo CreateNameInfo(const char16_t* first,
+ const char16_t* middle,
+ const char16_t* last,
+ const char16_t* full) {
NameInfo name;
name.SetRawInfoWithVerificationStatus(
- NAME_FIRST, base::UTF8ToUTF16(first),
+ NAME_FIRST, first,
autofill::structured_address::VerificationStatus::kObserved);
name.SetRawInfoWithVerificationStatus(
- NAME_MIDDLE, base::UTF8ToUTF16(middle),
+ NAME_MIDDLE, middle,
autofill::structured_address::VerificationStatus::kObserved);
name.SetRawInfoWithVerificationStatus(
- NAME_LAST, base::UTF8ToUTF16(last),
+ NAME_LAST, last,
autofill::structured_address::VerificationStatus::kObserved);
name.SetRawInfoWithVerificationStatus(
- NAME_FULL, base::UTF8ToUTF16(full),
+ NAME_FULL, full,
autofill::structured_address::VerificationStatus::kObserved);
return name;
}
@@ -181,10 +180,10 @@ class AutofillProfileComparatorTest
AutofillProfile CopyAndModify(
const AutofillProfile& profile,
- const std::vector<std::pair<ServerFieldType, const char*>>& updates) {
+ const std::vector<std::pair<ServerFieldType, const char16_t*>>& updates) {
AutofillProfile new_profile = profile;
for (const auto& update : updates) {
- new_profile.SetRawInfo(update.first, UTF8ToUTF16(update.second));
+ new_profile.SetRawInfo(update.first, update.second);
}
new_profile.FinalizeAfterImport();
return new_profile;
@@ -233,7 +232,7 @@ class AutofillProfileComparatorTest
void MergePhoneNumbersAndExpect(const AutofillProfile& a,
const AutofillProfile& b,
- const std::string& expected_str) {
+ const std::u16string& expected_str) {
AutofillProfile dummy;
// Merge the phone numbers.
@@ -242,7 +241,7 @@ class AutofillProfileComparatorTest
// Construct the expected value.
PhoneNumber expected(&dummy);
- expected.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, UTF8ToUTF16(expected_str));
+ expected.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, expected_str);
// Validate that we get what we expect.
EXPECT_EQ(expected.GetRawInfo(PHONE_HOME_WHOLE_NUMBER),
@@ -472,10 +471,9 @@ TEST_P(AutofillProfileComparatorTest, Compare) {
EXPECT_TRUE(
comparator_.Compare(u"Mid\x2013Island\x2003 Plaza", u"mid island plaza",
AutofillProfileComparator::RETAIN_WHITESPACE));
- EXPECT_TRUE(
- comparator_.Compare(UTF8ToUTF16("1600 amphitheatre pkwy \n App. 2"),
- u"1600 amphitheatre pkwy app 2",
- AutofillProfileComparator::RETAIN_WHITESPACE));
+ EXPECT_TRUE(comparator_.Compare(
+ u"1600 amphitheatre pkwy \n App. 2", u"1600 amphitheatre pkwy app 2",
+ AutofillProfileComparator::RETAIN_WHITESPACE));
EXPECT_TRUE(comparator_.Compare(
u"ã¾Ã©Ã–ä정", u"ã¾eoaì •", AutofillProfileComparator::RETAIN_WHITESPACE));
EXPECT_TRUE(comparator_.Compare(
@@ -507,9 +505,9 @@ TEST_P(AutofillProfileComparatorTest, NormalizeForComparison) {
comparator_.NormalizeForComparison(u"Mid\x2013Island\x2003 Plaza"));
// Newline character removed.
- EXPECT_EQ(u"1600 amphitheatre pkwy app 2",
- comparator_.NormalizeForComparison(
- UTF8ToUTF16("1600 amphitheatre pkwy \n App. 2")));
+ EXPECT_EQ(
+ u"1600 amphitheatre pkwy app 2",
+ comparator_.NormalizeForComparison(u"1600 amphitheatre pkwy \n App. 2"));
// Diacritics removed.
EXPECT_EQ(u"ã¾eoaì •", comparator_.NormalizeForComparison(u"ã¾Ã©Ã–ä정"));
@@ -704,20 +702,20 @@ TEST_P(AutofillProfileComparatorTest, HaveMergeableAddresses) {
"Carver City", "ca", "", "us");
AutofillProfile differentCountry =
- CopyAndModify(p1, {{ADDRESS_HOME_COUNTRY, "CA"}});
+ CopyAndModify(p1, {{ADDRESS_HOME_COUNTRY, u"CA"}});
AutofillProfile differentZip =
- CopyAndModify(p1, {{ADDRESS_HOME_ZIP, "32145"}});
+ CopyAndModify(p1, {{ADDRESS_HOME_ZIP, u"32145"}});
AutofillProfile differentState = CopyAndModify(
- p1, {{ADDRESS_HOME_ZIP, ""}, {ADDRESS_HOME_STATE, "Florida"}});
+ p1, {{ADDRESS_HOME_ZIP, u""}, {ADDRESS_HOME_STATE, u"Florida"}});
AutofillProfile differentCity = CopyAndModify(
- p1, {{ADDRESS_HOME_ZIP, ""}, {ADDRESS_HOME_CITY, "Metropolis"}});
+ p1, {{ADDRESS_HOME_ZIP, u""}, {ADDRESS_HOME_CITY, u"Metropolis"}});
AutofillProfile differentAddress =
- CopyAndModify(p1, {{ADDRESS_HOME_LINE1, "17 Park Lane"},
- {ADDRESS_HOME_LINE2, "Suite 150"}});
+ CopyAndModify(p1, {{ADDRESS_HOME_LINE1, u"17 Park Lane"},
+ {ADDRESS_HOME_LINE2, u"Suite 150"}});
AutofillProfile differentLocality =
- CopyAndModify(p1, {{ADDRESS_HOME_DEPENDENT_LOCALITY, "Funky Chicken"}});
+ CopyAndModify(p1, {{ADDRESS_HOME_DEPENDENT_LOCALITY, u"Funky Chicken"}});
AutofillProfile differentSortingCode =
- CopyAndModify(p1, {{ADDRESS_HOME_SORTING_CODE, "98000 Monaco"}});
+ CopyAndModify(p1, {{ADDRESS_HOME_SORTING_CODE, u"98000 Monaco"}});
EXPECT_TRUE(comparator_.HaveMergeableAddresses(p1, empty));
EXPECT_TRUE(comparator_.HaveMergeableAddresses(empty, p2));
@@ -750,26 +748,26 @@ TEST_P(AutofillProfileComparatorTest, AreMergeable) {
"+1 (234) 567-8910", /*finalize=*/false);
AutofillProfile mergeable =
- CopyAndModify(p, {{NAME_FIRST, "MÃRÃÕÑ"},
- {NAME_MIDDLE, "M."},
- {EMAIL_ADDRESS, "MARION@ME.XYZ"},
- {COMPANY_NAME, "Fox Industries Inc."},
- {ADDRESS_HOME_LINE1, "123 zoo st. w., #5"},
- {ADDRESS_HOME_LINE1, ""},
- {ADDRESS_HOME_STATE, "california"},
- {PHONE_HOME_WHOLE_NUMBER, "5678910 ext. 77"}});
+ CopyAndModify(p, {{NAME_FIRST, u"MÃRÃÕÑ"},
+ {NAME_MIDDLE, u"M."},
+ {EMAIL_ADDRESS, u"MARION@ME.XYZ"},
+ {COMPANY_NAME, u"Fox Industries Inc."},
+ {ADDRESS_HOME_LINE1, u"123 zoo st. w., #5"},
+ {ADDRESS_HOME_LINE1, u""},
+ {ADDRESS_HOME_STATE, u"california"},
+ {PHONE_HOME_WHOLE_NUMBER, u"5678910 ext. 77"}});
AutofillProfile not_mergeable_by_name =
- CopyAndModify(p, {{NAME_FIRST, "Steven"},
- {NAME_FULL, ""},
- {autofill::NAME_LAST_SECOND, ""}});
+ CopyAndModify(p, {{NAME_FIRST, u"Steven"},
+ {NAME_FULL, u""},
+ {autofill::NAME_LAST_SECOND, u""}});
AutofillProfile not_mergeable_by_email_address =
- CopyAndModify(p, {{EMAIL_ADDRESS, "marion.morrision@me.xyz"}});
+ CopyAndModify(p, {{EMAIL_ADDRESS, u"marion.morrision@me.xyz"}});
AutofillProfile not_mergeable_by_company_name =
- CopyAndModify(p, {{COMPANY_NAME, "Hound Corp"}});
+ CopyAndModify(p, {{COMPANY_NAME, u"Hound Corp"}});
AutofillProfile not_mergeable_by_address =
- CopyAndModify(p, {{ADDRESS_HOME_LINE2, "Unit 7"}});
+ CopyAndModify(p, {{ADDRESS_HOME_LINE2, u"Unit 7"}});
AutofillProfile not_mergeable_by_phone_number =
- CopyAndModify(p, {{PHONE_HOME_WHOLE_NUMBER, "555-1234"}});
+ CopyAndModify(p, {{PHONE_HOME_WHOLE_NUMBER, u"555-1234"}});
// Finalize the initial profile.
// Note, all other profiles are already finalized.
@@ -913,15 +911,15 @@ TEST_P(AutofillProfileComparatorTest, MergeNames) {
TEST_P(AutofillProfileComparatorTest, MergeCJKNames) {
// Korean names that are all mergeable, but constructed differently.
- NameInfo name1 = CreateNameInfo("호", "", "ì´ì˜", "ì´ì˜ 호");
- NameInfo name2 = CreateNameInfo("ì´ì˜í˜¸", "", "", "ì´ì˜í˜¸");
- NameInfo name3 = CreateNameInfo("ì˜í˜¸", "", "ì´", "ì´ì˜í˜¸");
- NameInfo name4 = CreateNameInfo("ì˜í˜¸", "", "ì´", "");
- NameInfo name5 = CreateNameInfo("ì˜í˜¸", "", "ì´", "ì´ ì˜í˜¸");
+ NameInfo name1 = CreateNameInfo(u"호", u"", u"ì´ì˜", u"ì´ì˜ 호");
+ NameInfo name2 = CreateNameInfo(u"ì´ì˜í˜¸", u"", u"", u"ì´ì˜í˜¸");
+ NameInfo name3 = CreateNameInfo(u"ì˜í˜¸", u"", u"ì´", u"ì´ì˜í˜¸");
+ NameInfo name4 = CreateNameInfo(u"ì˜í˜¸", u"", u"ì´", u"");
+ NameInfo name5 = CreateNameInfo(u"ì˜í˜¸", u"", u"ì´", u"ì´ ì˜í˜¸");
// Mergeable foreign name in Japanese with a 'KATAKANA MIDDLE DOT'.
- NameInfo name6 = CreateNameInfo("", "", "", "ゲイツ・ビル");
- NameInfo name7 = CreateNameInfo("ビル", "", "ゲイツ", "");
+ NameInfo name6 = CreateNameInfo(u"", u"", u"", u"ゲイツ・ビル");
+ NameInfo name7 = CreateNameInfo(u"ビル", u"", u"ゲイツ", u"");
// Set the use dates for the profiles, because |MergeCJKNames()| tries to use
// the most recent profile if there is a conflict. The ordering is
@@ -941,10 +939,10 @@ TEST_P(AutofillProfileComparatorTest, MergeCJKNames) {
AutofillProfile p7 = CreateProfileWithName(name7);
// Because |p1| is the most recent, it always wins over others.
- MergeNamesAndExpect(p1, p2, CreateNameInfo("호", "", "ì´ì˜", "ì´ì˜ 호"));
- MergeNamesAndExpect(p1, p3, CreateNameInfo("호", "", "ì´ì˜", "ì´ì˜ 호"));
- MergeNamesAndExpect(p1, p4, CreateNameInfo("호", "", "ì´ì˜", "ì´ì˜ 호"));
- MergeNamesAndExpect(p1, p5, CreateNameInfo("호", "", "ì´ì˜", "ì´ì˜ 호"));
+ MergeNamesAndExpect(p1, p2, CreateNameInfo(u"호", u"", u"ì´ì˜", u"ì´ì˜ 호"));
+ MergeNamesAndExpect(p1, p3, CreateNameInfo(u"호", u"", u"ì´ì˜", u"ì´ì˜ 호"));
+ MergeNamesAndExpect(p1, p4, CreateNameInfo(u"호", u"", u"ì´ì˜", u"ì´ì˜ 호"));
+ MergeNamesAndExpect(p1, p5, CreateNameInfo(u"호", u"", u"ì´ì˜", u"ì´ì˜ 호"));
// The following tests are not applicable to the logic of the new structured
// name. Because we consider not having a surname a valid option for the user.
@@ -955,34 +953,36 @@ TEST_P(AutofillProfileComparatorTest, MergeCJKNames) {
// |p2| is more recent than |p3|, |p4|, and |p5|. However, it does not
// have a surname entry (it was probably parsed with the old logic), so
// the other profiles are used as the source for given/surname.
- MergeNamesAndExpect(p2, p3, CreateNameInfo("ì˜í˜¸", "", "ì´", "ì´ì˜í˜¸"));
- MergeNamesAndExpect(p2, p4, CreateNameInfo("ì˜í˜¸", "", "ì´", "ì´ì˜í˜¸"));
- MergeNamesAndExpect(p2, p5, CreateNameInfo("ì˜í˜¸", "", "ì´", "ì´ì˜í˜¸"));
+ MergeNamesAndExpect(p2, p3, CreateNameInfo(u"ì˜í˜¸", u"", u"ì´", u"ì´ì˜í˜¸"));
+ MergeNamesAndExpect(p2, p4, CreateNameInfo(u"ì˜í˜¸", u"", u"ì´", u"ì´ì˜í˜¸"));
+ MergeNamesAndExpect(p2, p5, CreateNameInfo(u"ì˜í˜¸", u"", u"ì´", u"ì´ì˜í˜¸"));
}
// |p3| is more recent than |p4| and |p5|.
- MergeNamesAndExpect(p3, p4, CreateNameInfo("ì˜í˜¸", "", "ì´", "ì´ì˜í˜¸"));
- MergeNamesAndExpect(p3, p5, CreateNameInfo("ì˜í˜¸", "", "ì´", "ì´ì˜í˜¸"));
+ MergeNamesAndExpect(p3, p4, CreateNameInfo(u"ì˜í˜¸", u"", u"ì´", u"ì´ì˜í˜¸"));
+ MergeNamesAndExpect(p3, p5, CreateNameInfo(u"ì˜í˜¸", u"", u"ì´", u"ì´ì˜í˜¸"));
// |p4| is more recent than |p5|. However, it does not have an explicit
// full name, so use the one from |p5|.
- MergeNamesAndExpect(p4, p5, CreateNameInfo("ì˜í˜¸", "", "ì´", "ì´ ì˜í˜¸"));
+ MergeNamesAndExpect(p4, p5, CreateNameInfo(u"ì˜í˜¸", u"", u"ì´", u"ì´ ì˜í˜¸"));
// There is no conflict between |p6| and |p7|, so use the parts from both.
MergeNamesAndExpect(p6, p7,
- CreateNameInfo("ビル", "", "ゲイツ", "ゲイツ・ビル"));
+ CreateNameInfo(u"ビル", u"", u"ゲイツ", u"ゲイツ・ビル"));
}
TEST_P(AutofillProfileComparatorTest, MergeEmailAddresses) {
static const char kEmailA[] = "testaccount@domain.net";
+ static const char16_t kEmailA16[] = u"testaccount@domain.net";
static const char kEmailB[] = "TestAccount@Domain.Net";
+ static const char16_t kEmailB16[] = u"TestAccount@Domain.Net";
EmailInfo email_a;
- email_a.SetRawInfo(EMAIL_ADDRESS, UTF8ToUTF16(kEmailA));
+ email_a.SetRawInfo(EMAIL_ADDRESS, kEmailA16);
AutofillProfile profile_a = CreateProfileWithEmail(kEmailA);
profile_a.set_use_date(AutofillClock::Now());
EmailInfo email_b;
- email_b.SetRawInfo(EMAIL_ADDRESS, UTF8ToUTF16(kEmailB));
+ email_b.SetRawInfo(EMAIL_ADDRESS, kEmailB16);
AutofillProfile profile_b = CreateProfileWithEmail(kEmailB);
profile_b.set_use_date(profile_a.use_date() + base::TimeDelta::FromDays(1));
@@ -994,32 +994,36 @@ TEST_P(AutofillProfileComparatorTest, MergeEmailAddresses) {
TEST_P(AutofillProfileComparatorTest, MergeCompanyNames) {
static const char kCompanyA[] = "Some Company";
+ static const char16_t kCompanyA16[] = u"Some Company";
static const char kCompanyB[] = "SÔMÈ ÇÖMPÃÑÃ";
+ static const char16_t kCompanyB16[] = u"SÔMÈ ÇÖMPÃÑÃ";
static const char kCompanyC[] = "SÔMÈ ÇÖMPÃÑà A.G.";
+ static const char16_t kCompanyC16[] = u"SÔMÈ ÇÖMPÃÑà A.G.";
static const char kCompanyD[] = "1987";
+ static const char16_t kCompanyD16[] = u"1987";
CompanyInfo company_a;
- company_a.SetRawInfo(COMPANY_NAME, UTF8ToUTF16(kCompanyA));
+ company_a.SetRawInfo(COMPANY_NAME, kCompanyA16);
AutofillProfile profile_a = CreateProfileWithCompanyName(kCompanyA);
profile_a.set_use_date(AutofillClock::Now());
// Company Name B is post_normalization identical to Company Name A. The use
// date will be used to choose between them.
CompanyInfo company_b;
- company_b.SetRawInfo(COMPANY_NAME, UTF8ToUTF16(kCompanyB));
+ company_b.SetRawInfo(COMPANY_NAME, kCompanyB16);
AutofillProfile profile_b = CreateProfileWithCompanyName(kCompanyB);
profile_b.set_use_date(profile_a.use_date() + base::TimeDelta::FromDays(1));
// Company Name C is the most complete. Even though it has the earliest use
// date, it will be preferred to the other two.
CompanyInfo company_c;
- company_c.SetRawInfo(COMPANY_NAME, UTF8ToUTF16(kCompanyC));
+ company_c.SetRawInfo(COMPANY_NAME, kCompanyC16);
AutofillProfile profile_c = CreateProfileWithCompanyName(kCompanyC);
profile_c.set_use_date(profile_a.use_date() - base::TimeDelta::FromDays(1));
// Company Name D is in the format of a birthyear, invalid and non-verified.
CompanyInfo company_d;
- company_d.SetRawInfo(COMPANY_NAME, UTF8ToUTF16(kCompanyD));
+ company_d.SetRawInfo(COMPANY_NAME, kCompanyD16);
AutofillProfile profile_d = CreateProfileWithCompanyName(kCompanyD);
profile_a.set_use_date(AutofillClock::Now());
@@ -1046,16 +1050,23 @@ TEST_P(AutofillProfileComparatorTest, MergeCompanyNames) {
TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_NA) {
static const char kPhoneA[] = "5550199";
+ static const char16_t kPhoneA16[] = u"5550199";
static const char kPhoneB[] = "555.0199";
+ static const char16_t kPhoneB16[] = u"555.0199";
static const char kPhoneC[] = "555-0199 ext321";
+ static const char16_t kPhoneC16[] = u"555-0199 ext321";
static const char kPhoneD[] = "8005550199";
+ static const char16_t kPhoneD16[] = u"8005550199";
static const char kPhoneE[] = "800-555-0199 #321";
+ static const char16_t kPhoneE16[] = u"800-555-0199 #321";
static const char kPhoneF[] = "1-800-555-0199 #321";
+ static const char16_t kPhoneF16[] = u"1-800-555-0199 #321";
static const char kPhoneG[] = "+1 (800) 555.0199;ext=321";
- static const char kMergedShortNumber[] = "5550199";
- static const char kMergedShortNumberExt[] = "5550199 ext. 321";
- static const char kMergedFullNumber[] = "+1 800-555-0199";
- static const char kMergedFullNumberExt[] = "+1 800-555-0199 ext. 321";
+ static const char16_t kPhoneG16[] = u"+1 (800) 555.0199;ext=321";
+ static const char16_t kMergedShortNumber[] = u"5550199";
+ static const char16_t kMergedShortNumberExt[] = u"5550199 ext. 321";
+ static const char16_t kMergedFullNumber[] = u"+1 800-555-0199";
+ static const char16_t kMergedFullNumberExt[] = u"+1 800-555-0199 ext. 321";
AutofillProfile profile_a = CreateProfileWithPhoneNumber(kPhoneA);
AutofillProfile profile_b = CreateProfileWithPhoneNumber(kPhoneB);
@@ -1066,7 +1077,7 @@ TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_NA) {
AutofillProfile profile_g = CreateProfileWithPhoneNumber(kPhoneG);
// Profile A
- MergePhoneNumbersAndExpect(profile_a, profile_a, kPhoneA);
+ MergePhoneNumbersAndExpect(profile_a, profile_a, kPhoneA16);
MergePhoneNumbersAndExpect(profile_a, profile_b, kMergedShortNumber);
MergePhoneNumbersAndExpect(profile_a, profile_c, kMergedShortNumberExt);
MergePhoneNumbersAndExpect(profile_a, profile_d, kMergedFullNumber);
@@ -1076,7 +1087,7 @@ TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_NA) {
// Profile B
MergePhoneNumbersAndExpect(profile_b, profile_a, kMergedShortNumber);
- MergePhoneNumbersAndExpect(profile_b, profile_b, kPhoneB);
+ MergePhoneNumbersAndExpect(profile_b, profile_b, kPhoneB16);
MergePhoneNumbersAndExpect(profile_b, profile_c, kMergedShortNumberExt);
MergePhoneNumbersAndExpect(profile_b, profile_d, kMergedFullNumber);
MergePhoneNumbersAndExpect(profile_b, profile_e, kMergedFullNumberExt);
@@ -1086,7 +1097,7 @@ TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_NA) {
// Profile C
MergePhoneNumbersAndExpect(profile_c, profile_a, kMergedShortNumberExt);
MergePhoneNumbersAndExpect(profile_c, profile_b, kMergedShortNumberExt);
- MergePhoneNumbersAndExpect(profile_c, profile_c, kPhoneC);
+ MergePhoneNumbersAndExpect(profile_c, profile_c, kPhoneC16);
MergePhoneNumbersAndExpect(profile_c, profile_d, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_c, profile_e, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_c, profile_f, kMergedFullNumberExt);
@@ -1096,7 +1107,7 @@ TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_NA) {
MergePhoneNumbersAndExpect(profile_d, profile_a, kMergedFullNumber);
MergePhoneNumbersAndExpect(profile_d, profile_b, kMergedFullNumber);
MergePhoneNumbersAndExpect(profile_d, profile_c, kMergedFullNumberExt);
- MergePhoneNumbersAndExpect(profile_d, profile_d, kPhoneD);
+ MergePhoneNumbersAndExpect(profile_d, profile_d, kPhoneD16);
MergePhoneNumbersAndExpect(profile_d, profile_e, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_d, profile_f, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_d, profile_g, kMergedFullNumberExt);
@@ -1106,7 +1117,7 @@ TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_NA) {
MergePhoneNumbersAndExpect(profile_e, profile_b, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_e, profile_c, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_e, profile_d, kMergedFullNumberExt);
- MergePhoneNumbersAndExpect(profile_e, profile_e, kPhoneE);
+ MergePhoneNumbersAndExpect(profile_e, profile_e, kPhoneE16);
MergePhoneNumbersAndExpect(profile_e, profile_f, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_e, profile_g, kMergedFullNumberExt);
@@ -1116,7 +1127,7 @@ TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_NA) {
MergePhoneNumbersAndExpect(profile_f, profile_c, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_f, profile_d, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_f, profile_e, kMergedFullNumberExt);
- MergePhoneNumbersAndExpect(profile_f, profile_f, kPhoneF);
+ MergePhoneNumbersAndExpect(profile_f, profile_f, kPhoneF16);
MergePhoneNumbersAndExpect(profile_f, profile_g, kMergedFullNumberExt);
// Profile G
@@ -1126,7 +1137,7 @@ TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_NA) {
MergePhoneNumbersAndExpect(profile_g, profile_d, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_g, profile_e, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_g, profile_f, kMergedFullNumberExt);
- MergePhoneNumbersAndExpect(profile_g, profile_g, kPhoneG);
+ MergePhoneNumbersAndExpect(profile_g, profile_g, kPhoneG16);
}
TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_Intl) {
@@ -1134,11 +1145,15 @@ TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_Intl) {
const AutofillType kCountry(ADDRESS_HOME_COUNTRY);
static const char kPhoneA[] = "+49492180185611";
+ static const char16_t kPhoneA16[] = u"+49492180185611";
static const char kPhoneB[] = "+49 4921 801 856-11";
+ static const char16_t kPhoneB16[] = u"+49 4921 801 856-11";
static const char kPhoneC[] = "+49 4921 8018 5611;ext=22";
+ static const char16_t kPhoneC16[] = u"+49 4921 8018 5611;ext=22";
static const char kPhoneD[] = "04921 80185611"; // National Format.
- static const char kMergedFullNumber[] = "+49 4921 80185611";
- static const char kMergedFullNumberExt[] = "+49 4921 80185611 ext. 22";
+ static const char16_t kPhoneD16[] = u"04921 80185611"; // National Format.
+ static const char16_t kMergedFullNumber[] = u"+49 4921 80185611";
+ static const char16_t kMergedFullNumberExt[] = u"+49 4921 80185611 ext. 22";
AutofillProfile profile_a = CreateProfileWithPhoneNumber(kPhoneA);
AutofillProfile profile_b = CreateProfileWithPhoneNumber(kPhoneB);
@@ -1151,25 +1166,25 @@ TEST_P(AutofillProfileComparatorTest, MergePhoneNumbers_Intl) {
profile_d.SetInfo(kCountry, kGermany, kLocale);
// Profile A
- MergePhoneNumbersAndExpect(profile_a, profile_a, kPhoneA);
+ MergePhoneNumbersAndExpect(profile_a, profile_a, kPhoneA16);
MergePhoneNumbersAndExpect(profile_a, profile_b, kMergedFullNumber);
MergePhoneNumbersAndExpect(profile_a, profile_c, kMergedFullNumberExt);
// Profile B
MergePhoneNumbersAndExpect(profile_b, profile_a, kMergedFullNumber);
- MergePhoneNumbersAndExpect(profile_b, profile_b, kPhoneB);
+ MergePhoneNumbersAndExpect(profile_b, profile_b, kPhoneB16);
MergePhoneNumbersAndExpect(profile_b, profile_c, kMergedFullNumberExt);
// Profile C
MergePhoneNumbersAndExpect(profile_c, profile_a, kMergedFullNumberExt);
MergePhoneNumbersAndExpect(profile_c, profile_b, kMergedFullNumberExt);
- MergePhoneNumbersAndExpect(profile_c, profile_c, kPhoneC);
+ MergePhoneNumbersAndExpect(profile_c, profile_c, kPhoneC16);
// Profile D
MergePhoneNumbersAndExpect(profile_d, profile_a, kMergedFullNumber);
MergePhoneNumbersAndExpect(profile_d, profile_b, kMergedFullNumber);
MergePhoneNumbersAndExpect(profile_d, profile_c, kMergedFullNumberExt);
- MergePhoneNumbersAndExpect(profile_d, profile_d, kPhoneD);
+ MergePhoneNumbersAndExpect(profile_d, profile_d, kPhoneD16);
}
TEST_P(AutofillProfileComparatorTest, MergeAddresses) {
@@ -1434,6 +1449,128 @@ TEST_P(AutofillProfileComparatorTest,
existing_profile, new_profile));
}
+TEST_P(AutofillProfileComparatorTest, GetProfileDifference) {
+ AutofillProfile existing_profile(base::GenerateGUID(),
+ "http://www.example.com/");
+ autofill::test::SetProfileInfo(
+ &existing_profile, "firstName", "middleName", "lastName", "mail@mail.com",
+ "company", "line1", "line2", "city", "state", "zip", "US", "phone");
+
+ // Change the zip code of the second profile.
+ AutofillProfile second_existing_profile = existing_profile;
+ second_existing_profile.SetRawInfo(ADDRESS_HOME_ZIP, u"another_zip");
+
+ // There should be no difference in NAME_FULL type.
+ EXPECT_TRUE(
+ AutofillProfileComparator::GetProfileDifference(
+ existing_profile, second_existing_profile, {NAME_FULL}, kLocale)
+ .empty());
+
+ // But there should be difference in ADDRESS_HOME_ZIP type.
+ std::vector<autofill::ProfileValueDifference> expected_difference = {
+ {ADDRESS_HOME_ZIP, u"zip", u"another_zip"}};
+
+ EXPECT_EQ(AutofillProfileComparator::GetProfileDifference(
+ existing_profile, second_existing_profile, {ADDRESS_HOME_ZIP},
+ kLocale),
+ expected_difference);
+}
+
+TEST_P(AutofillProfileComparatorTest, GetProfileDifferenceMap) {
+ AutofillProfile existing_profile(base::GenerateGUID(),
+ "http://www.example.com/");
+ autofill::test::SetProfileInfo(
+ &existing_profile, "firstName", "middleName", "lastName", "mail@mail.com",
+ "company", "line1", "line2", "city", "state", "zip", "US", "phone");
+
+ // Change the zip code of the second profile.
+ AutofillProfile second_existing_profile = existing_profile;
+ second_existing_profile.SetRawInfo(ADDRESS_HOME_ZIP, u"another_zip");
+
+ // There should be no difference in NAME_FULL type.
+ EXPECT_TRUE(
+ AutofillProfileComparator::GetProfileDifferenceMap(
+ existing_profile, second_existing_profile, {NAME_FULL}, kLocale)
+ .empty());
+
+ // But there should be difference in ADDRESS_HOME_ZIP type.
+ base::flat_map<ServerFieldType, std::pair<std::u16string, std::u16string>>
+ expected_difference;
+ expected_difference.insert({ADDRESS_HOME_ZIP, {u"zip", u"another_zip"}});
+
+ EXPECT_EQ(AutofillProfileComparator::GetProfileDifferenceMap(
+ existing_profile, second_existing_profile, {ADDRESS_HOME_ZIP},
+ kLocale),
+ expected_difference);
+}
+
+TEST_P(AutofillProfileComparatorTest, GetSettingsVisibleProfileDifference) {
+ AutofillProfile existing_profile(base::GenerateGUID(),
+ "http://www.example.com/");
+ autofill::test::SetProfileInfo(
+ &existing_profile, "firstName", "middleName", "lastName", "mail@mail.com",
+ "company", "line1", "line2", "city", "state", "zip", "US", "phone");
+
+ // Make a copy of the existing profile.
+ AutofillProfile second_existing_profile = existing_profile;
+
+ // There should be no difference in the profiles.
+ EXPECT_TRUE(AutofillProfileComparator::GetSettingsVisibleProfileDifference(
+ existing_profile, second_existing_profile, kLocale)
+ .empty());
+
+ // Change the zip code of the second profile and test the difference.
+ second_existing_profile.SetRawInfo(ADDRESS_HOME_ZIP, u"another_zip");
+ std::vector<autofill::ProfileValueDifference> expected_difference = {
+ {ADDRESS_HOME_ZIP, u"zip", u"another_zip"}};
+ EXPECT_EQ(AutofillProfileComparator::GetSettingsVisibleProfileDifference(
+ existing_profile, second_existing_profile, kLocale),
+ expected_difference);
+
+ // Change a second value and check the expectations.
+ second_existing_profile.SetRawInfo(autofill::ADDRESS_HOME_CITY,
+ u"another_city");
+ expected_difference.emplace(expected_difference.begin(),
+ autofill::ProfileValueDifference{
+ ADDRESS_HOME_CITY, u"city", u"another_city"});
+ EXPECT_EQ(AutofillProfileComparator::GetSettingsVisibleProfileDifference(
+ existing_profile, second_existing_profile, kLocale),
+ expected_difference);
+}
+
+TEST_P(AutofillProfileComparatorTest, GetSettingsVisibleProfileDifferenceMap) {
+ AutofillProfile existing_profile(base::GenerateGUID(),
+ "http://www.example.com/");
+ autofill::test::SetProfileInfo(
+ &existing_profile, "firstName", "middleName", "lastName", "mail@mail.com",
+ "company", "line1", "line2", "city", "state", "zip", "US", "phone");
+
+ // Make a copy of the existing profile.
+ AutofillProfile second_existing_profile = existing_profile;
+
+ // There should be no difference in the profiles.
+ EXPECT_TRUE(AutofillProfileComparator::GetSettingsVisibleProfileDifferenceMap(
+ existing_profile, second_existing_profile, kLocale)
+ .empty());
+
+ // Change the zip code of the second profile and test the difference.
+ second_existing_profile.SetRawInfo(ADDRESS_HOME_ZIP, u"another_zip");
+ base::flat_map<ServerFieldType, std::pair<std::u16string, std::u16string>>
+ expected_difference;
+ expected_difference.insert({ADDRESS_HOME_ZIP, {u"zip", u"another_zip"}});
+ EXPECT_EQ(AutofillProfileComparator::GetSettingsVisibleProfileDifferenceMap(
+ existing_profile, second_existing_profile, kLocale),
+ expected_difference);
+
+ // Change a second value and check the expectations.
+ second_existing_profile.SetRawInfo(autofill::ADDRESS_HOME_CITY,
+ u"another_city");
+ expected_difference.insert({ADDRESS_HOME_CITY, {u"city", u"another_city"}});
+ EXPECT_EQ(AutofillProfileComparator::GetSettingsVisibleProfileDifferenceMap(
+ existing_profile, second_existing_profile, kLocale),
+ expected_difference);
+}
+
TEST_P(AutofillProfileComparatorTest, IsMergeCandidate) {
AutofillProfile existing_profile(base::GenerateGUID(),
"http://www.example.com/");
@@ -1501,7 +1638,7 @@ TEST_P(AutofillProfileComparatorTest, GetMergeCandidate) {
// are the same.
EXPECT_EQ(AutofillProfileComparator::GetAutofillProfileMergeCandidate(
existing_profile, {&existing_profile}, "en_US"),
- base::nullopt);
+ absl::nullopt);
// Create a new profile that is not mergeable because it has a completely
// different name.
@@ -1509,7 +1646,7 @@ TEST_P(AutofillProfileComparatorTest, GetMergeCandidate) {
new_profile.SetRawInfo(NAME_FULL, u"JustAnotherName");
EXPECT_EQ(AutofillProfileComparator::GetAutofillProfileMergeCandidate(
new_profile, {&existing_profile}, "en_US"),
- base::nullopt);
+ absl::nullopt);
// Use a city name that is a superset of the existing city name. It should be
// mergeable and the profile should be updated to the new value.
@@ -1517,7 +1654,7 @@ TEST_P(AutofillProfileComparatorTest, GetMergeCandidate) {
new_profile.SetRawInfoWithVerificationStatus(
ADDRESS_HOME_CITY, u"the City",
autofill::structured_address::VerificationStatus::kObserved);
- base::Optional<AutofillProfile> optional_merge_candidate =
+ absl::optional<AutofillProfile> optional_merge_candidate =
AutofillProfileComparator::GetAutofillProfileMergeCandidate(
new_profile, {&existing_profile}, "en_US");
ASSERT_TRUE(optional_merge_candidate.has_value());
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_profile_unittest.cc b/chromium/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
index 7a8b029f5e9..52d8748f0fd 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_profile_unittest.cc
@@ -13,7 +13,6 @@
#include "base/format_macros.h"
#include "base/guid.h"
#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
@@ -28,7 +27,6 @@
#include "components/autofill/core/common/form_field_data.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::ASCIIToUTF16;
using base::UTF8ToUTF16;
namespace autofill {
@@ -38,7 +36,7 @@ constexpr VerificationStatus kObserved = VerificationStatus::kObserved;
namespace {
-std::u16string GetLabel(AutofillProfile* profile) {
+std::u16string GetSuggestionLabel(AutofillProfile* profile) {
std::vector<AutofillProfile*> profiles;
profiles.push_back(profile);
std::vector<std::u16string> labels;
@@ -95,7 +93,7 @@ TEST_P(AutofillProfileTest, PreviewSummaryString) {
// Case 0/null: ""
AutofillProfile profile0(base::GenerateGUID(), test::kEmptyOrigin);
// Empty profile - nothing to update.
- std::u16string summary0 = GetLabel(&profile0);
+ std::u16string summary0 = GetSuggestionLabel(&profile0);
EXPECT_EQ(std::u16string(), summary0);
// Case 0a/empty name and address, so the first two fields of the rest of the
@@ -103,7 +101,7 @@ TEST_P(AutofillProfileTest, PreviewSummaryString) {
AutofillProfile profile00(base::GenerateGUID(), test::kEmptyOrigin);
test::SetProfileInfo(&profile00, "", "", "", "johnwayne@me.xyz", "Fox", "",
"", "Hollywood", "CA", "91601", "US", "16505678910");
- std::u16string summary00 = GetLabel(&profile00);
+ std::u16string summary00 = GetSuggestionLabel(&profile00);
EXPECT_EQ(u"Hollywood, CA", summary00);
// Case 1: "<address>" without line 2.
@@ -111,7 +109,7 @@ TEST_P(AutofillProfileTest, PreviewSummaryString) {
test::SetProfileInfo(&profile1, "", "", "", "johnwayne@me.xyz", "Fox",
"123 Zoo St.", "", "Hollywood", "CA", "91601", "US",
"16505678910");
- std::u16string summary1 = GetLabel(&profile1);
+ std::u16string summary1 = GetSuggestionLabel(&profile1);
EXPECT_EQ(u"123 Zoo St., Hollywood", summary1);
// Case 1a: "<address>" with line 2.
@@ -119,7 +117,7 @@ TEST_P(AutofillProfileTest, PreviewSummaryString) {
test::SetProfileInfo(&profile1a, "", "", "", "johnwayne@me.xyz", "Fox",
"123 Zoo St.", "unit 5", "Hollywood", "CA", "91601",
"US", "16505678910");
- std::u16string summary1a = GetLabel(&profile1a);
+ std::u16string summary1a = GetSuggestionLabel(&profile1a);
EXPECT_EQ(u"123 Zoo St., unit 5", summary1a);
// Case 2: "<lastname>"
@@ -127,7 +125,7 @@ TEST_P(AutofillProfileTest, PreviewSummaryString) {
test::SetProfileInfo(&profile2, "", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "", "", "Hollywood", "CA",
"91601", "US", "16505678910");
- std::u16string summary2 = GetLabel(&profile2);
+ std::u16string summary2 = GetSuggestionLabel(&profile2);
// Summary includes full name, to the maximal extent available.
EXPECT_EQ(u"Mitchell Morrison, Hollywood", summary2);
@@ -136,7 +134,7 @@ TEST_P(AutofillProfileTest, PreviewSummaryString) {
test::SetProfileInfo(&profile3, "", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "",
"Hollywood", "CA", "91601", "US", "16505678910");
- std::u16string summary3 = GetLabel(&profile3);
+ std::u16string summary3 = GetSuggestionLabel(&profile3);
EXPECT_EQ(u"Mitchell Morrison, 123 Zoo St.", summary3);
// Case 4: "<firstname>"
@@ -144,7 +142,7 @@ TEST_P(AutofillProfileTest, PreviewSummaryString) {
test::SetProfileInfo(&profile4, "Marion", "Mitchell", "", "johnwayne@me.xyz",
"Fox", "", "", "Hollywood", "CA", "91601", "US",
"16505678910");
- std::u16string summary4 = GetLabel(&profile4);
+ std::u16string summary4 = GetSuggestionLabel(&profile4);
EXPECT_EQ(u"Marion Mitchell, Hollywood", summary4);
// Case 5: "<firstname>, <address>"
@@ -152,7 +150,7 @@ TEST_P(AutofillProfileTest, PreviewSummaryString) {
test::SetProfileInfo(&profile5, "Marion", "Mitchell", "", "johnwayne@me.xyz",
"Fox", "123 Zoo St.", "unit 5", "Hollywood", "CA",
"91601", "US", "16505678910");
- std::u16string summary5 = GetLabel(&profile5);
+ std::u16string summary5 = GetSuggestionLabel(&profile5);
EXPECT_EQ(u"Marion Mitchell, 123 Zoo St.", summary5);
// Case 6: "<firstname> <lastname>"
@@ -160,7 +158,7 @@ TEST_P(AutofillProfileTest, PreviewSummaryString) {
test::SetProfileInfo(&profile6, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "", "", "Hollywood", "CA",
"91601", "US", "16505678910");
- std::u16string summary6 = GetLabel(&profile6);
+ std::u16string summary6 = GetSuggestionLabel(&profile6);
EXPECT_EQ(u"Marion Mitchell Morrison, Hollywood", summary6);
// Case 7: "<firstname> <lastname>, <address>"
@@ -168,7 +166,7 @@ TEST_P(AutofillProfileTest, PreviewSummaryString) {
test::SetProfileInfo(&profile7, "Marion", "Mitchell", "Morrison",
"johnwayne@me.xyz", "Fox", "123 Zoo St.", "unit 5",
"Hollywood", "CA", "91601", "US", "16505678910");
- std::u16string summary7 = GetLabel(&profile7);
+ std::u16string summary7 = GetSuggestionLabel(&profile7);
EXPECT_EQ(u"Marion Mitchell Morrison, 123 Zoo St.", summary7);
// Case 7a: "<firstname> <lastname>, <address>" - same as #7, except for
@@ -277,11 +275,9 @@ TEST_P(AutofillProfileTest, AdjustInferredLabels) {
ASSERT_EQ(5U, labels.size());
EXPECT_EQ(u"John Doe, 666 Erebus St., CA", labels[0]);
EXPECT_EQ(u"Jane Doe, 123 Letha Shore.", labels[1]);
- EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., CO, johndoe@hades.com,"
- " 16502111111"),
+ EXPECT_EQ(u"John Doe, 666 Erebus St., CO, johndoe@hades.com, 16502111111",
labels[2]);
- EXPECT_EQ(ASCIIToUTF16("John Doe, 666 Erebus St., CO, johndoe@hades.com,"
- " 16504444444"),
+ EXPECT_EQ(u"John Doe, 666 Erebus St., CO, johndoe@hades.com, 16504444444",
labels[3]);
// This one differs from other ones by unique e-mail, so no need for extra
// information.
@@ -1325,23 +1321,26 @@ TEST_P(AutofillProfileTest, IsPresentButInvalid) {
TEST_P(AutofillProfileTest, SetRawInfoPreservesLineBreaks) {
AutofillProfile profile(base::GenerateGUID(), test::kEmptyOrigin);
- profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("123 Super St.\n"
- "Apt. #42"));
- EXPECT_EQ(ASCIIToUTF16("123 Super St.\n"
- "Apt. #42"),
- profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
+ u"123 Super St.\n"
+ u"Apt. #42");
+ EXPECT_EQ(
+ u"123 Super St.\n"
+ u"Apt. #42",
+ profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
}
TEST_P(AutofillProfileTest, SetInfoPreservesLineBreaks) {
AutofillProfile profile(base::GenerateGUID(), test::kEmptyOrigin);
profile.SetInfo(ADDRESS_HOME_STREET_ADDRESS,
- ASCIIToUTF16("123 Super St.\n"
- "Apt. #42"),
+ u"123 Super St.\n"
+ u"Apt. #42",
"en-US");
- EXPECT_EQ(ASCIIToUTF16("123 Super St.\n"
- "Apt. #42"),
- profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
+ EXPECT_EQ(
+ u"123 Super St.\n"
+ u"Apt. #42",
+ profile.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
}
TEST_P(AutofillProfileTest, SetRawInfoDoesntTrimWhitespace) {
@@ -1366,11 +1365,11 @@ TEST_P(AutofillProfileTest, FullAddress) {
AutofillType full_address(HTML_TYPE_FULL_ADDRESS, HTML_MODE_NONE);
std::u16string formatted_address(
- ASCIIToUTF16("Marion Mitchell Morrison\n"
- "Fox\n"
- "123 Zoo St.\n"
- "unit 5\n"
- "Hollywood, CA 91601"));
+ u"Marion Mitchell Morrison\n"
+ u"Fox\n"
+ u"123 Zoo St.\n"
+ u"unit 5\n"
+ u"Hollywood, CA 91601");
EXPECT_EQ(formatted_address, profile.GetInfo(full_address, "en-US"));
// This should fail and leave the profile unchanged.
EXPECT_FALSE(profile.SetInfo(full_address, u"foobar", "en-US"));
@@ -1379,11 +1378,12 @@ TEST_P(AutofillProfileTest, FullAddress) {
// Some things can be missing...
profile.SetInfo(ADDRESS_HOME_LINE2, std::u16string(), "en-US");
profile.SetInfo(EMAIL_ADDRESS, std::u16string(), "en-US");
- EXPECT_EQ(ASCIIToUTF16("Marion Mitchell Morrison\n"
- "Fox\n"
- "123 Zoo St.\n"
- "Hollywood, CA 91601"),
- profile.GetInfo(full_address, "en-US"));
+ EXPECT_EQ(
+ u"Marion Mitchell Morrison\n"
+ u"Fox\n"
+ u"123 Zoo St.\n"
+ u"Hollywood, CA 91601",
+ profile.GetInfo(full_address, "en-US"));
// ...but nothing comes out if a required field is missing.
profile.SetInfo(ADDRESS_HOME_STATE, std::u16string(), "en-US");
@@ -2085,6 +2085,60 @@ TEST(AutofillProfileTest,
EXPECT_FALSE(profile.IsValidByClient());
}
+// Test that the label is correctly set and retrieved from the profile.
+TEST_P(AutofillProfileTest, SetAndGetProfileLabels) {
+ AutofillProfile p;
+ EXPECT_EQ(p.profile_label(), std::string());
+
+ p.set_profile_label("my label");
+ EXPECT_EQ(p.profile_label(), "my label");
+}
+
+TEST_P(AutofillProfileTest, LabelsInAssignmentAndComparisonOperator) {
+ AutofillProfile p1;
+ p1.set_profile_label("my label");
+
+ AutofillProfile p2;
+ p2 = p1;
+
+ // Check that the label was assigned correctly to p2.
+ EXPECT_EQ(p2.profile_label(), "my label");
+
+ // Now test that the comparison returns false if the label is not the same.
+ ASSERT_EQ(p1, p2);
+ p2.set_profile_label("another label");
+ EXPECT_NE(p1, p2);
+}
+
+// Test that the state to disallow confirmable merges is correctly set and
+// retrieved from the profile.
+TEST_P(AutofillProfileTest, SetAndGetProfileDisallowConfirmableMergestate) {
+ AutofillProfile p;
+ EXPECT_EQ(p.disallow_settings_visible_updates(), false);
+
+ p.set_disallow_settings_visible_updates(true);
+ EXPECT_EQ(p.disallow_settings_visible_updates(), true);
+}
+
+TEST_P(AutofillProfileTest, LockStateInAssignmentAndComparisonOperator) {
+ AutofillProfile p1;
+ p1.set_disallow_settings_visible_updates(true);
+
+ AutofillProfile p2;
+ EXPECT_EQ(p2.disallow_settings_visible_updates(), false);
+
+ p2 = p1;
+
+ // Check that the lock state was assigned correctly to p2.
+ EXPECT_EQ(p2.disallow_settings_visible_updates(), true);
+
+ // Now test that the comparison returns false if the lock state is not the
+ // same.
+ ASSERT_EQ(p1, p2);
+ p2.set_disallow_settings_visible_updates(false);
+ EXPECT_NE(p1, p2);
+}
+
TEST_P(AutofillProfileTest, SetClientValidityFromBitfieldValue_Email) {
AutofillProfile profile;
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_structured_address.cc b/chromium/components/autofill/core/browser/data_model/autofill_structured_address.cc
index 863e605ce3a..0fbedb8762f 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_structured_address.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_structured_address.cc
@@ -150,31 +150,27 @@ std::u16string StreetAddress::GetBestFormatString() const {
base::UTF16ToUTF8(GetRootNode().GetValueForType(ADDRESS_HOME_COUNTRY));
if (country_code == "BR") {
- return base::UTF8ToUTF16(
- "${ADDRESS_HOME_STREET_NAME}${ADDRESS_HOME_HOUSE_NUMBER;, }"
- "${ADDRESS_HOME_FLOOR;, ;º andar}${ADDRESS_HOME_APT_NUM;, apto ;}");
+ return u"${ADDRESS_HOME_STREET_NAME}${ADDRESS_HOME_HOUSE_NUMBER;, }"
+ u"${ADDRESS_HOME_FLOOR;, ;º andar}${ADDRESS_HOME_APT_NUM;, apto ;}";
}
if (country_code == "DE") {
- return base::ASCIIToUTF16(
- "${ADDRESS_HOME_STREET_NAME} ${ADDRESS_HOME_HOUSE_NUMBER}"
- "${ADDRESS_HOME_FLOOR;, ;. Stock}${ADDRESS_HOME_APT_NUM;, ;. Wohnung}");
+ return u"${ADDRESS_HOME_STREET_NAME} ${ADDRESS_HOME_HOUSE_NUMBER}"
+ u"${ADDRESS_HOME_FLOOR;, ;. Stock}${ADDRESS_HOME_APT_NUM;, ;. "
+ u"Wohnung}";
}
if (country_code == "MX") {
- return base::ASCIIToUTF16(
- "${ADDRESS_HOME_STREET_NAME} ${ADDRESS_HOME_HOUSE_NUMBER}"
- "${ADDRESS_HOME_FLOOR; - Piso ;}${ADDRESS_HOME_APT_NUM; - ;}");
+ return u"${ADDRESS_HOME_STREET_NAME} ${ADDRESS_HOME_HOUSE_NUMBER}"
+ u"${ADDRESS_HOME_FLOOR; - Piso ;}${ADDRESS_HOME_APT_NUM; - ;}";
}
if (country_code == "ES") {
- return base::UTF8ToUTF16(
- "${ADDRESS_HOME_STREET_NAME} ${ADDRESS_HOME_HOUSE_NUMBER}"
- "${ADDRESS_HOME_FLOOR;, ;º}${ADDRESS_HOME_APT_NUM;, ;ª}");
+ return u"${ADDRESS_HOME_STREET_NAME} ${ADDRESS_HOME_HOUSE_NUMBER}"
+ u"${ADDRESS_HOME_FLOOR;, ;º}${ADDRESS_HOME_APT_NUM;, ;ª}";
}
// Use the format for US/UK as the default.
- return base::ASCIIToUTF16(
- "${ADDRESS_HOME_HOUSE_NUMBER} ${ADDRESS_HOME_STREET_NAME} "
- "${ADDRESS_HOME_FLOOR;FL } ${ADDRESS_HOME_APT_NUM;APT }");
+ return u"${ADDRESS_HOME_HOUSE_NUMBER} ${ADDRESS_HOME_STREET_NAME} "
+ u"${ADDRESS_HOME_FLOOR;FL } ${ADDRESS_HOME_APT_NUM;APT }";
}
void StreetAddress::UnsetValue() {
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_structured_address_component.h b/chromium/components/autofill/core/browser/data_model/autofill_structured_address_component.h
index f1e1f256088..b97444f7fc6 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_structured_address_component.h
+++ b/chromium/components/autofill/core/browser/data_model/autofill_structured_address_component.h
@@ -9,9 +9,9 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "components/autofill/core/browser/field_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace re2 {
class RE2;
@@ -39,6 +39,7 @@ enum class VerificationStatus {
kUserVerified = 4,
// The token was parsed by the server.
kServerParsed = 5,
+ kMaxValue = kServerParsed
};
// Prints the string representation of |status| to |os|.
@@ -552,7 +553,7 @@ class AddressComponent {
bool ParseValueAndAssignSubcomponentsByRegularExpressions();
// The unstructured value of this component.
- base::Optional<std::u16string> value_;
+ absl::optional<std::u16string> value_;
// The verification status of |value_| indicates the certainty of the value
// to be correct.
@@ -568,7 +569,7 @@ class AddressComponent {
// meaning that it was converted to lower case and diacritics have been
// removed. |value_| is tokenized by splitting the string by white spaces and
// commas. It is calculated when |value_| is set.
- base::Optional<std::vector<AddressToken>> sorted_normalized_tokens_;
+ absl::optional<std::vector<AddressToken>> sorted_normalized_tokens_;
// A pointer to the parent node. It is set to nullptr if the node is the root
// node of the AddressComponent tree.
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_structured_address_name_unittest.cc b/chromium/components/autofill/core/browser/data_model/autofill_structured_address_name_unittest.cc
index 44a4d0752e3..af37c503ffb 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_structured_address_name_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_structured_address_name_unittest.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/feature_list.h"
+#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/data_model/autofill_structured_address_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_structured_address_utils.h"
diff --git a/chromium/components/autofill/core/browser/data_model/autofill_structured_address_unittest.cc b/chromium/components/autofill/core/browser/data_model/autofill_structured_address_unittest.cc
index 4b1a2f33a66..c608c723073 100644
--- a/chromium/components/autofill/core/browser/data_model/autofill_structured_address_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/autofill_structured_address_unittest.cc
@@ -25,12 +25,12 @@ namespace structured_address {
using AddressComponentTestValues = std::vector<AddressComponentTestValue>;
struct AddressLineParsingTestCase {
- std::string country_code = "";
- std::string street_address = "";
- std::string street_name = "";
- std::string house_number = "";
- std::string floor = "";
- std::string apartment = "";
+ std::string country_code;
+ std::string street_address;
+ std::string street_name;
+ std::string house_number;
+ std::string floor;
+ std::string apartment;
};
std::ostream& operator<<(std::ostream& out,
diff --git a/chromium/components/autofill/core/browser/data_model/borrowed_transliterator.h b/chromium/components/autofill/core/browser/data_model/borrowed_transliterator.h
index 110c7d437f5..d3cd1617e3d 100644
--- a/chromium/components/autofill/core/browser/data_model/borrowed_transliterator.h
+++ b/chromium/components/autofill/core/browser/data_model/borrowed_transliterator.h
@@ -7,6 +7,7 @@
#include "base/i18n/unicodestring.h"
#include "base/no_destructor.h"
+#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
#include "third_party/icu/source/common/unicode/unistr.h"
#include "third_party/icu/source/i18n/unicode/translit.h"
diff --git a/chromium/components/autofill/core/browser/data_model/contact_info.cc b/chromium/components/autofill/core/browser/data_model/contact_info.cc
index 8155e9fe99b..c85a292b482 100644
--- a/chromium/components/autofill/core/browser/data_model/contact_info.cc
+++ b/chromium/components/autofill/core/browser/data_model/contact_info.cc
@@ -101,16 +101,21 @@ bool NameInfo::operator==(const NameInfo& other) const {
std::u16string NameInfo::GetRawInfo(ServerFieldType type) const {
DCHECK_EQ(FieldTypeGroup::kName, AutofillType(type).group());
+ // TODO(crbug.com/1141460): Remove once honorific prefixes are launched.
+ if (type == NAME_FULL_WITH_HONORIFIC_PREFIX &&
+ !structured_address::HonorificPrefixEnabled()) {
+ type = NAME_FULL;
+ }
// TODO(crbug.com/1103421): Clean legacy implementation once structured names
// are fully launched.
if (structured_address::StructuredNamesEnabled()) {
// Without the second generation of the structured name tree, honorific
// prefixes and the name including the prefix are unsupported types.
- if ((type == NAME_HONORIFIC_PREFIX ||
- type == NAME_FULL_WITH_HONORIFIC_PREFIX) &&
+ if (type == NAME_HONORIFIC_PREFIX &&
!structured_address::HonorificPrefixEnabled()) {
return std::u16string();
}
+
return name_->GetValueForType(type);
}
switch (type) {
diff --git a/chromium/components/autofill/core/browser/data_model/contact_info_unittest.cc b/chromium/components/autofill/core/browser/data_model/contact_info_unittest.cc
index 97790e6d3df..6f153a696aa 100644
--- a/chromium/components/autofill/core/browser/data_model/contact_info_unittest.cc
+++ b/chromium/components/autofill/core/browser/data_model/contact_info_unittest.cc
@@ -9,7 +9,6 @@
#include "base/format_macros.h"
#include "base/macros.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
diff --git a/chromium/components/autofill/core/browser/data_model/credit_card.cc b/chromium/components/autofill/core/browser/data_model/credit_card.cc
index e7281177b5a..7b3a1ab55f2 100644
--- a/chromium/components/autofill/core/browser/data_model/credit_card.cc
+++ b/chromium/components/autofill/core/browser/data_model/credit_card.cc
@@ -331,7 +331,7 @@ bool CreditCard::IsNicknameValid(const std::u16string& nickname) {
void CreditCard::SetNetworkForMaskedCard(base::StringPiece network) {
DCHECK_EQ(MASKED_SERVER_CARD, record_type());
- network_ = network.as_string();
+ network_ = std::string(network);
}
void CreditCard::SetServerStatus(ServerStatus status) {
@@ -570,6 +570,8 @@ void CreditCard::operator=(const CreditCard& credit_card) {
nickname_ = credit_card.nickname_;
card_issuer_ = credit_card.card_issuer_;
instrument_id_ = credit_card.instrument_id_;
+ virtual_card_enrollment_state_ = credit_card.virtual_card_enrollment_state_;
+ card_art_url_ = GURL(credit_card.card_art_url_);
set_guid(credit_card.guid());
set_origin(credit_card.origin());
@@ -664,6 +666,19 @@ int CreditCard::Compare(const CreditCard& credit_card) const {
return 1;
}
+ if (static_cast<int>(virtual_card_enrollment_state_) <
+ static_cast<int>(credit_card.virtual_card_enrollment_state_)) {
+ return -1;
+ }
+ if (static_cast<int>(virtual_card_enrollment_state_) >
+ static_cast<int>(credit_card.virtual_card_enrollment_state_)) {
+ return 1;
+ }
+
+ comparison = card_art_url_.spec().compare(credit_card.card_art_url_.spec());
+ if (comparison != 0)
+ return comparison;
+
// Do not distinguish masked server cards from full server cards as this is
// not needed and not desired - we want to identify masked server card from
// sync with the (potential) full server card stored locally.
@@ -1067,7 +1082,9 @@ std::ostream& operator<<(std::ostream& os, const CreditCard& credit_card) {
<< credit_card.use_count() << " " << credit_card.use_date() << " "
<< credit_card.billing_address_id() << " " << credit_card.nickname()
<< " " << credit_card.card_issuer() << " "
- << credit_card.instrument_id();
+ << credit_card.instrument_id() << " "
+ << credit_card.virtual_card_enrollment_state() << " "
+ << credit_card.card_art_url().spec();
}
void CreditCard::SetNameOnCardFromSeparateParts() {
diff --git a/chromium/components/autofill/core/browser/data_model/credit_card.h b/chromium/components/autofill/core/browser/data_model/credit_card.h
index ce2d224dfde..f4a862b3c8c 100644
--- a/chromium/components/autofill/core/browser/data_model/credit_card.h
+++ b/chromium/components/autofill/core/browser/data_model/credit_card.h
@@ -16,6 +16,7 @@
#include "build/build_config.h"
#include "components/autofill/core/browser/data_model/autofill_data_model.h"
#include "components/sync/protocol/sync.pb.h"
+#include "url/gurl.h"
namespace autofill {
@@ -51,6 +52,10 @@ class CreditCard : public AutofillDataModel {
// A card from the Wallet server with full information store locally. This
// card is not locally editable.
FULL_SERVER_CARD,
+
+ // A card generated from a server card by the card issuer. This card is not
+ // persisted in Chrome.
+ VIRTUAL_CARD,
};
// The status of this card. Only used for server cards.
@@ -59,12 +64,25 @@ class CreditCard : public AutofillDataModel {
OK,
};
- // The Issuer for the card.
+ // The Issuer for the card. This must stay in sync with the proto enum in
+ // autofill_specifics.proto.
enum Issuer {
ISSUER_UNKNOWN = 0,
GOOGLE = 1,
};
+ // Whether the card has been enrolled in the virtual card feature. This must
+ // stay in sync with the proto enum in autofill_specifics.proto.
+ enum VirtualCardEnrollmentState {
+ // State unspecified. This is the default value of this enum. Should not be
+ // ever used with cards.
+ UNSPECIFIED = 0,
+ // Card is not enrolled and does not have related virtual card.
+ UNENROLLED = 1,
+ // Card is enrolled and has related virtual cards.
+ ENROLLED = 2,
+ };
+
CreditCard(const std::string& guid, const std::string& origin);
// Creates a server card. The type must be MASKED_SERVER_CARD or
@@ -309,6 +327,19 @@ class CreditCard : public AutofillDataModel {
// Should be used ONLY by tests.
std::u16string NicknameAndLastFourDigitsForTesting() const;
+ VirtualCardEnrollmentState virtual_card_enrollment_state() const {
+ return virtual_card_enrollment_state_;
+ }
+ void set_virtual_card_enrollment_state(
+ VirtualCardEnrollmentState virtual_card_enrollment_state) {
+ virtual_card_enrollment_state_ = virtual_card_enrollment_state;
+ }
+
+ const GURL& card_art_url() const { return card_art_url_; }
+ void set_card_art_url(const GURL& card_art_url) {
+ card_art_url_ = card_art_url;
+ }
+
private:
FRIEND_TEST_ALL_PREFIXES(CreditCardTest, SetExpirationDateFromString);
FRIEND_TEST_ALL_PREFIXES(CreditCardTest, SetExpirationYearFromString);
@@ -389,6 +420,13 @@ class CreditCard : public AutofillDataModel {
// identify this card. |server_id_| is the legacy version of this.
// TODO(crbug.com/1121806): remove server_id_ after full deprecation
int64_t instrument_id_;
+
+ // The virtual card enrollment state of this card. If it is ENROLLED, then
+ // this card has virtual cards linked to it.
+ VirtualCardEnrollmentState virtual_card_enrollment_state_ = UNSPECIFIED;
+
+ // The url to fetch the rich card art image.
+ GURL card_art_url_;
};
// So we can compare CreditCards with EXPECT_EQ().
diff --git a/chromium/components/autofill/core/browser/data_model/credit_card_art_image.cc b/chromium/components/autofill/core/browser/data_model/credit_card_art_image.cc
new file mode 100644
index 00000000000..e63ac3a8bab
--- /dev/null
+++ b/chromium/components/autofill/core/browser/data_model/credit_card_art_image.cc
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/data_model/credit_card_art_image.h"
+
+namespace autofill {
+
+CreditCardArtImage::CreditCardArtImage() = default;
+
+CreditCardArtImage::CreditCardArtImage(const std::string& id,
+ int64_t instrument_id,
+ std::vector<uint8_t> card_art_image) {
+ this->id = id;
+ this->instrument_id = instrument_id;
+ this->card_art_image = std::move(card_art_image);
+}
+
+CreditCardArtImage::~CreditCardArtImage() = default;
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/data_model/credit_card_art_image.h b/chromium/components/autofill/core/browser/data_model/credit_card_art_image.h
new file mode 100644
index 00000000000..4ae25d20154
--- /dev/null
+++ b/chromium/components/autofill/core/browser/data_model/credit_card_art_image.h
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_CREDIT_CARD_ART_IMAGE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_CREDIT_CARD_ART_IMAGE_H_
+
+#include <string>
+#include <vector>
+
+namespace autofill {
+
+// Represents an rich card art image for the server credit card.
+struct CreditCardArtImage {
+ public:
+ CreditCardArtImage();
+ CreditCardArtImage(const std::string& id,
+ int64_t instrument_id,
+ std::vector<uint8_t> card_art_image);
+ ~CreditCardArtImage();
+ CreditCardArtImage(const CreditCardArtImage&) = delete;
+ CreditCardArtImage& operator=(const CreditCardArtImage&) = delete;
+
+ // The server id for the related credit card.
+ std::string id;
+
+ // The instrument id for the related credit card.
+ int64_t instrument_id;
+
+ // The customized card art image. Stored as an raw PNG-encoded data.
+ std::vector<uint8_t> card_art_image;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_CREDIT_CARD_ART_IMAGE_H_
diff --git a/chromium/components/autofill/core/browser/field_filler.cc b/chromium/components/autofill/core/browser/field_filler.cc
index 11756bd8d73..1ecbb7eae66 100644
--- a/chromium/components/autofill/core/browser/field_filler.cc
+++ b/chromium/components/autofill/core/browser/field_filler.cc
@@ -53,7 +53,9 @@ bool SetSelectControlValue(const std::u16string& value,
DCHECK_EQ(field->option_values.size(), field->option_contents.size());
std::u16string best_match;
- for (size_t i = 0; i < field->option_values.size(); ++i) {
+ size_t items_count =
+ std::min(field->option_contents.size(), field->option_values.size());
+ for (size_t i = 0; i < items_count; ++i) {
if (value == field->option_values[i] ||
value == field->option_contents[i]) {
// An exact match, use it.
@@ -116,8 +118,9 @@ bool SetSelectControlValueTokenMatch(const std::u16string& value,
std::vector<std::u16string> tokenized;
DCHECK_EQ(field->option_values.size(), field->option_contents.size());
l10n::CaseInsensitiveCompare compare;
-
- for (size_t i = 0; i < field->option_values.size(); ++i) {
+ size_t items_count =
+ std::min(field->option_contents.size(), field->option_values.size());
+ for (size_t i = 0; i < items_count; ++i) {
tokenized =
base::SplitString(field->option_values[i], base::kWhitespaceASCIIAs16,
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
@@ -230,7 +233,9 @@ bool FillNumericSelectControl(int value,
FormFieldData* field,
std::string* failure_to_fill) {
DCHECK_EQ(field->option_values.size(), field->option_contents.size());
- for (size_t i = 0; i < field->option_values.size(); ++i) {
+ size_t items_count =
+ std::min(field->option_contents.size(), field->option_values.size());
+ for (size_t i = 0; i < items_count; ++i) {
int option;
if ((StringToInt(field->option_values[i], &option) && option == value) ||
(StringToInt(field->option_contents[i], &option) && option == value)) {
@@ -257,7 +262,7 @@ bool FillStateSelectControl(const std::u16string& value,
if (base::FeatureList::IsEnabled(
features::kAutofillUseAlternativeStateNameMap)) {
// Fetch the corresponding entry from AlternativeStateNameMap.
- base::Optional<StateEntry> state_entry =
+ absl::optional<StateEntry> state_entry =
AlternativeStateNameMap::GetInstance()->GetEntry(
AlternativeStateNameMap::CountryCode(country_code),
AlternativeStateNameMap::StateName(value));
@@ -463,7 +468,9 @@ bool FillYearSelectControl(const std::u16string& value,
}
DCHECK_EQ(field->option_values.size(), field->option_contents.size());
- for (size_t i = 0; i < field->option_values.size(); ++i) {
+ size_t items_count =
+ std::min(field->option_contents.size(), field->option_values.size());
+ for (size_t i = 0; i < items_count; ++i) {
if (LastTwoDigitsMatch(value, field->option_values[i]) ||
LastTwoDigitsMatch(value, field->option_contents[i])) {
field->value = field->option_values[i];
@@ -640,7 +647,7 @@ bool FillStateText(const std::u16string& value,
if (base::FeatureList::IsEnabled(
features::kAutofillUseAlternativeStateNameMap)) {
- base::Optional<StateEntry> state =
+ absl::optional<StateEntry> state =
AlternativeStateNameMap::GetInstance()->GetEntry(
AlternativeStateNameMap::CountryCode(country_code),
AlternativeStateNameMap::StateName(value));
@@ -979,8 +986,9 @@ int FieldFiller::FindShortestSubstringMatchInSelect(
ignore_whitespace ? RemoveWhitespace(value) : value;
base::i18n::FixedPatternStringSearchIgnoringCaseAndAccents searcher(
value_stripped);
-
- for (size_t i = 0; i < field->option_values.size(); ++i) {
+ size_t items_count =
+ std::min(field->option_contents.size(), field->option_values.size());
+ for (size_t i = 0; i < items_count; ++i) {
std::u16string option_value =
ignore_whitespace ? RemoveWhitespace(field->option_values[i])
: field->option_values[i];
diff --git a/chromium/components/autofill/core/browser/field_filler_unittest.cc b/chromium/components/autofill/core/browser/field_filler_unittest.cc
index f550a9c6202..b359e40293e 100644
--- a/chromium/components/autofill/core/browser/field_filler_unittest.cc
+++ b/chromium/components/autofill/core/browser/field_filler_unittest.cc
@@ -36,9 +36,7 @@
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/storage.h"
#include "third_party/libaddressinput/src/cpp/test/testdata_source.h"
-using base::ASCIIToUTF16;
using base::StringToInt;
-using base::UTF8ToUTF16;
namespace autofill {
@@ -136,10 +134,10 @@ void TestFillingInvalidFields(const std::u16string& state,
}
struct CreditCardTestCase {
- std::string card_number_;
+ std::u16string card_number_;
size_t total_splits_;
std::vector<int> splits_;
- std::vector<std::string> expected_results_;
+ std::vector<std::u16string> expected_results_;
};
// Returns the offset to be set within the credit card number field.
@@ -539,23 +537,23 @@ TEST_F(AutofillFieldFillerTest, FillFormField_Validity_CountryEmpty) {
struct AutofillFieldFillerTestCase {
HtmlFieldType field_type;
size_t field_max_length;
- std::string expected_value;
+ std::u16string expected_value;
AutofillFieldFillerTestCase(HtmlFieldType field_type,
size_t field_max_length,
- std::string expected_value)
+ std::u16string expected_value)
: field_type(field_type),
field_max_length(field_max_length),
expected_value(expected_value) {}
};
struct AutofillPhoneFieldFillerTestCase : public AutofillFieldFillerTestCase {
- std::string phone_home_whole_number_value;
+ std::u16string phone_home_whole_number_value;
AutofillPhoneFieldFillerTestCase(HtmlFieldType field_type,
size_t field_max_length,
- std::string expected_value,
- std::string phone_home_whole_number_value)
+ std::u16string expected_value,
+ std::u16string phone_home_whole_number_value)
: AutofillFieldFillerTestCase(field_type,
field_max_length,
expected_value),
@@ -576,10 +574,10 @@ TEST_P(PhoneNumberTest, FillPhoneNumber) {
AutofillProfile address;
address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
- ASCIIToUTF16(test_case.phone_home_whole_number_value));
+ test_case.phone_home_whole_number_value);
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
filler.FillFormField(field, &address, &field, /*cvc=*/std::u16string());
- EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value);
+ EXPECT_EQ(test_case.expected_value, field.value);
}
INSTANTIATE_TEST_SUITE_P(
@@ -588,43 +586,43 @@ INSTANTIATE_TEST_SUITE_P(
testing::Values(
// Filling a prefix type field should just fill the prefix.
AutofillPhoneFieldFillerTestCase{HTML_TYPE_TEL_LOCAL_PREFIX,
- /*field_max_length=*/0, "555",
- "+15145554578"},
+ /*field_max_length=*/0, u"555",
+ u"+15145554578"},
// Filling a suffix type field with a phone number of 7 digits should
// just fill the suffix.
AutofillPhoneFieldFillerTestCase{HTML_TYPE_TEL_LOCAL_SUFFIX,
- /*field_max_length=*/0, "4578",
- "+15145554578"},
+ /*field_max_length=*/0, u"4578",
+ u"+15145554578"},
// Filling a phone type field with a max length of 3 should fill only
// the prefix.
AutofillPhoneFieldFillerTestCase{HTML_TYPE_TEL_LOCAL,
- /*field_max_length=*/3, "555",
- "+15145554578"},
+ /*field_max_length=*/3, u"555",
+ u"+15145554578"},
// TODO(crbug.com/581485): There should be a test case where the full
// number is requested (HTML_TYPE_TEL) but a field_max_length of 3 would
// fill the prefix.
// Filling a phone type field with a max length of 4 should fill only
// the suffix.
AutofillPhoneFieldFillerTestCase{HTML_TYPE_TEL,
- /*field_max_length=*/4, "4578",
- "+15145554578"},
+ /*field_max_length=*/4, u"4578",
+ u"+15145554578"},
// Filling a phone type field with a max length of 10 with a phone
// number including the country code should fill the phone number
// without the country code.
AutofillPhoneFieldFillerTestCase{HTML_TYPE_TEL,
- /*field_max_length=*/10, "5145554578",
- "+15145554578"},
+ /*field_max_length=*/10, u"5145554578",
+ u"+15145554578"},
// Filling a phone type field with a max length of 5 with a phone number
// should fill with the last 5 digits of that phone number.
AutofillPhoneFieldFillerTestCase{HTML_TYPE_TEL,
- /*field_max_length=*/5, "54578",
- "+15145554578"},
+ /*field_max_length=*/5, u"54578",
+ u"+15145554578"},
// Filling a phone type field with a max length of 10 with a phone
// number including the country code should fill the phone number
// without the country code.
AutofillPhoneFieldFillerTestCase{HTML_TYPE_TEL,
- /*field_max_length=*/10, "123456789",
- "+886123456789"}));
+ /*field_max_length=*/10, u"123456789",
+ u"+886123456789"}));
class ExpirationYearTest
: public testing::TestWithParam<AutofillFieldFillerTestCase> {
@@ -643,7 +641,7 @@ TEST_P(ExpirationYearTest, FillExpirationYearInput) {
card.SetExpirationDateFromString(u"12/2023");
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
filler.FillFormField(field, &card, &field, /*cvc=*/std::u16string());
- EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value);
+ EXPECT_EQ(test_case.expected_value, field.value);
}
INSTANTIATE_TEST_SUITE_P(
@@ -654,37 +652,37 @@ INSTANTIATE_TEST_SUITE_P(
// 2 digits of the expiration year if the field has an unspecified max
// length (0) or if it's greater than 1.
AutofillFieldFillerTestCase{HTML_TYPE_CREDIT_CARD_EXP_2_DIGIT_YEAR,
- /* default value */ 0, "23"},
+ /* default value */ 0, u"23"},
AutofillFieldFillerTestCase{HTML_TYPE_CREDIT_CARD_EXP_2_DIGIT_YEAR, 2,
- "23"},
+ u"23"},
AutofillFieldFillerTestCase{HTML_TYPE_CREDIT_CARD_EXP_2_DIGIT_YEAR, 12,
- "23"},
+ u"23"},
// A field predicted as a 2 digit expiration year should fill the last
// digit of the expiration year if the field has a max length of 1.
AutofillFieldFillerTestCase{HTML_TYPE_CREDIT_CARD_EXP_2_DIGIT_YEAR, 1,
- "3"},
+ u"3"},
// A field predicted as a 4 digit expiration year should fill the 4
// digits of the expiration year if the field has an unspecified max
// length (0) or if it's greater than 3 .
AutofillFieldFillerTestCase{HTML_TYPE_CREDIT_CARD_EXP_4_DIGIT_YEAR,
- /* default value */ 0, "2023"},
+ /* default value */ 0, u"2023"},
AutofillFieldFillerTestCase{HTML_TYPE_CREDIT_CARD_EXP_4_DIGIT_YEAR, 4,
- "2023"},
+ u"2023"},
AutofillFieldFillerTestCase{HTML_TYPE_CREDIT_CARD_EXP_4_DIGIT_YEAR, 12,
- "2023"},
+ u"2023"},
// A field predicted as a 4 digits expiration year should fill the last
// 2 digits of the expiration year if the field has a max length of 2.
AutofillFieldFillerTestCase{HTML_TYPE_CREDIT_CARD_EXP_4_DIGIT_YEAR, 2,
- "23"},
+ u"23"},
// A field predicted as a 4 digits expiration year should fill the last
// digit of the expiration year if the field has a max length of 1.
AutofillFieldFillerTestCase{HTML_TYPE_CREDIT_CARD_EXP_4_DIGIT_YEAR, 1,
- "3"}));
+ u"3"}));
struct FillUtilExpirationDateTestCase {
HtmlFieldType field_type;
size_t field_max_length;
- std::string expected_value;
+ std::u16string expected_value;
bool expected_response;
};
@@ -706,7 +704,7 @@ TEST_P(ExpirationDateTest, FillExpirationDateInput) {
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
bool response =
filler.FillFormField(field, &card, &field, /*cvc=*/std::u16string());
- EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value);
+ EXPECT_EQ(test_case.expected_value, field.value);
EXPECT_EQ(response, test_case.expected_response);
}
@@ -721,30 +719,30 @@ INSTANTIATE_TEST_SUITE_P(
// 7: Use format MM/YYYY
FillUtilExpirationDateTestCase{
HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
- /* default value */ 0, "03/22", true},
+ /* default value */ 0, u"03/22", true},
// Unsupported max lengths of 1-3, fail
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 1, "", false},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 1, u"", false},
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 2, "", false},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 2, u"", false},
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 3, "", false},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 3, u"", false},
// A max length of 4 indicates a format of MMYY.
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 4, "0322", true},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 4, u"0322", true},
// A max length of 6 indicates a format of MMYYYY, the 21st century is
// assumed.
// Desired case of proper max length >= 5
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 5, "03/22", true},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 5, u"03/22", true},
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 6, "032022", true},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 6, u"032022", true},
// A max length of 7 indicates a format of MM/YYYY, the 21st century is
// assumed.
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 7, "03/2022", true},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 7, u"03/2022", true},
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 12, "03/22", true},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, 12, u"03/22", true},
// A field predicted as a expiration date w/ 4 digit year should fill
// with a format of MM/YYYY unless it has max-length of:
@@ -753,28 +751,29 @@ INSTANTIATE_TEST_SUITE_P(
// 6: Use format MMYYYY
FillUtilExpirationDateTestCase{
HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
- /* default value */ 0, "03/2022", true},
+ /* default value */ 0, u"03/2022", true},
// Unsupported max lengths of 1-3, fail
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 1, "", false},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 1, u"", false},
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 2, "", false},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 2, u"", false},
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 3, "", false},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 3, u"", false},
// A max length of 4 indicates a format of MMYY.
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 4, "0322", true},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 4, u"0322", true},
// A max length of 5 indicates a format of MM/YY.
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 5, "03/22", true},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 5, u"03/22", true},
// A max length of 6 indicates a format of MMYYYY.
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 6, "032022", true},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 6, u"032022", true},
// Desired case of proper max length >= 7
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 7, "03/2022", true},
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 7, u"03/2022", true},
FillUtilExpirationDateTestCase{
- HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 12, "03/2022", true}));
+ HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, 12, u"03/2022",
+ true}));
TEST_F(AutofillFieldFillerTest, FillSelectControlByValue) {
std::vector<const char*> kOptions = {
@@ -823,9 +822,9 @@ TEST_F(AutofillFieldFillerTest, FillSelectControlByContents) {
struct FillSelectTestCase {
std::vector<const char*> select_values;
- const char* input_value;
- const char* expected_value_without_normalization;
- const char* expected_value_with_normalization = nullptr;
+ const char16_t* input_value;
+ const char16_t* expected_value_without_normalization;
+ const char16_t* expected_value_with_normalization = nullptr;
};
class AutofillSelectWithStatesTest
@@ -880,19 +879,17 @@ TEST_P(AutofillSelectWithStatesTest, FillSelectWithStates) {
// Without a normalizer.
AutofillProfile address = test::GetFullProfile();
- address.SetRawInfo(ADDRESS_HOME_STATE, UTF8ToUTF16(test_case.input_value));
+ address.SetRawInfo(ADDRESS_HOME_STATE, test_case.input_value);
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
filler.FillFormField(field, &address, &field, /*cvc=*/std::u16string());
// nullptr means we expect them not to match without normalization.
if (test_case.expected_value_without_normalization != nullptr) {
- EXPECT_EQ(UTF8ToUTF16(test_case.expected_value_without_normalization),
- field.value);
+ EXPECT_EQ(test_case.expected_value_without_normalization, field.value);
}
// With a normalizer.
AutofillProfile canadian_address = test::GetFullCanadianProfile();
- canadian_address.SetRawInfo(ADDRESS_HOME_STATE,
- UTF8ToUTF16(test_case.input_value));
+ canadian_address.SetRawInfo(ADDRESS_HOME_STATE, test_case.input_value);
// Fill a first time without loading the rules for the region.
FieldFiller canadian_filler(/*app_locale=*/"en-US", normalizer());
canadian_filler.FillFormField(field, &canadian_address, &field,
@@ -900,20 +897,17 @@ TEST_P(AutofillSelectWithStatesTest, FillSelectWithStates) {
// If the expectation with normalization is nullptr, this means that the same
// result than without a normalizer is expected.
if (test_case.expected_value_with_normalization == nullptr) {
- EXPECT_EQ(UTF8ToUTF16(test_case.expected_value_without_normalization),
- field.value);
+ EXPECT_EQ(test_case.expected_value_without_normalization, field.value);
} else {
// We needed a normalizer with loaded rules. The first fill should have
// failed.
- EXPECT_NE(UTF8ToUTF16(test_case.expected_value_with_normalization),
- field.value);
+ EXPECT_NE(test_case.expected_value_with_normalization, field.value);
// Load the rules and try again.
normalizer()->LoadRulesForRegion("CA");
canadian_filler.FillFormField(field, &canadian_address, &field,
/*cvc=*/std::u16string());
- EXPECT_EQ(UTF8ToUTF16(test_case.expected_value_with_normalization),
- field.value);
+ EXPECT_EQ(test_case.expected_value_with_normalization, field.value);
}
}
@@ -922,54 +916,54 @@ INSTANTIATE_TEST_SUITE_P(
AutofillSelectWithStatesTest,
testing::Values(
// Filling the abbreviation.
- FillSelectTestCase{{"Alabama", "California"}, "CA", "California"},
+ FillSelectTestCase{{"Alabama", "California"}, u"CA", u"California"},
// Attempting to fill the full name in a select full of abbreviations.
- FillSelectTestCase{{"AL", "CA"}, "California", "CA"},
+ FillSelectTestCase{{"AL", "CA"}, u"California", u"CA"},
// Different case and diacritics.
- FillSelectTestCase{{"QUÉBEC", "ALBERTA"}, "Quebec", "QUÉBEC"},
+ FillSelectTestCase{{"QUÉBEC", "ALBERTA"}, u"Quebec", u"QUÉBEC"},
// The value and the field options are different but normalize to the
// same (NB).
FillSelectTestCase{{"Nouveau-Brunswick", "Alberta"},
- "New Brunswick",
+ u"New Brunswick",
nullptr,
- "Nouveau-Brunswick"},
- FillSelectTestCase{{"NB", "AB"}, "New Brunswick", nullptr, "NB"},
- FillSelectTestCase{{"NB", "AB"}, "Nouveau-Brunswick", nullptr, "NB"},
+ u"Nouveau-Brunswick"},
+ FillSelectTestCase{{"NB", "AB"}, u"New Brunswick", nullptr, u"NB"},
+ FillSelectTestCase{{"NB", "AB"}, u"Nouveau-Brunswick", nullptr, u"NB"},
FillSelectTestCase{{"Nouveau-Brunswick", "Alberta"},
- "NB",
+ u"NB",
nullptr,
- "Nouveau-Brunswick"},
+ u"Nouveau-Brunswick"},
FillSelectTestCase{{"New Brunswick", "Alberta"},
- "NB",
+ u"NB",
nullptr,
- "New Brunswick"},
+ u"New Brunswick"},
// Inexact state names.
FillSelectTestCase{
{"SC - South Carolina", "CA - California", "NC - North Carolina"},
- "California",
- "CA - California"},
+ u"California",
+ u"CA - California"},
// Don't accidentally match "Virginia" to "West Virginia".
FillSelectTestCase{
{"WV - West Virginia", "VA - Virginia", "NV - North Virginia"},
- "Virginia",
- "VA - Virginia"},
+ u"Virginia",
+ u"VA - Virginia"},
// Do accidentally match "Virginia" to "West Virginia".
// TODO(crbug.com/624770): This test should not pass, but it does
// because "Virginia" is a substring of "West Virginia".
FillSelectTestCase{{"WV - West Virginia", "TX - Texas"},
- "Virginia",
- "WV - West Virginia"},
+ u"Virginia",
+ u"WV - West Virginia"},
// Tests that substring matches work for full state names (a full token
// match isn't required). Also tests that matches work for states with
// whitespace in the middle.
FillSelectTestCase{{"California.", "North Carolina."},
- "North Carolina",
- "North Carolina."},
+ u"North Carolina",
+ u"North Carolina."},
FillSelectTestCase{{"NC - North Carolina", "CA - California"},
- "CA",
- "CA - California"},
+ u"CA",
+ u"CA - California"},
// These are not states.
- FillSelectTestCase{{"NCNCA", "SCNCA"}, "NC", ""}));
+ FillSelectTestCase{{"NCNCA", "SCNCA"}, u"NC", u""}));
TEST_F(AutofillFieldFillerTest, FillSelectWithCountries) {
AutofillField field;
@@ -1278,16 +1272,12 @@ TEST_F(AutofillFieldFillerTest, FillStreetAddressTextArea) {
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
field.set_heuristic_type(ADDRESS_HOME_STREET_ADDRESS);
- std::u16string value = ASCIIToUTF16(
- "123 Fake St.\n"
- "Apt. 42");
+ std::u16string value = u"123 Fake St.\nApt. 42";
address()->SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), value, "en-US");
filler.FillFormField(field, address(), &field, /*cvc=*/std::u16string());
EXPECT_EQ(value, field.value);
- std::u16string ja_value = UTF8ToUTF16(
- "桜丘町26-1\n"
- "セルリアンタワー6階");
+ std::u16string ja_value = u"桜丘町26-1\nセルリアンタワー6階";
address()->SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), ja_value,
"ja-JP");
address()->set_language_code("ja-JP");
@@ -1301,16 +1291,12 @@ TEST_F(AutofillFieldFillerTest, FillStreetAddressTextField) {
field.set_server_type(ADDRESS_HOME_STREET_ADDRESS);
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
- std::u16string value = ASCIIToUTF16(
- "123 Fake St.\n"
- "Apt. 42");
+ std::u16string value = u"123 Fake St.\nApt. 42";
address()->SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), value, "en-US");
filler.FillFormField(field, address(), &field, /*cvc=*/std::u16string());
EXPECT_EQ(u"123 Fake St., Apt. 42", field.value);
- std::u16string ja_value = UTF8ToUTF16(
- "桜丘町26-1\n"
- "セルリアンタワー6階");
+ std::u16string ja_value = u"桜丘町26-1\nセルリアンタワー6階";
address()->SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), ja_value,
"ja-JP");
address()->set_language_code("ja-JP");
@@ -1336,13 +1322,11 @@ TEST_F(AutofillFieldFillerTest, FillCreditCardNumberWithoutSplits) {
TEST_F(AutofillFieldFillerTest, FillCreditCardNumberWithEqualSizeSplits) {
// Case 2: card number broken up into four equal groups, of length 4.
CreditCardTestCase test;
- test.card_number_ = "5187654321098765";
+ test.card_number_ = u"5187654321098765";
test.total_splits_ = 4;
int splits[] = {4, 4, 4, 4};
test.splits_ = std::vector<int>(splits, splits + base::size(splits));
- std::string results[] = {"5187", "6543", "2109", "8765"};
- test.expected_results_ =
- std::vector<std::string>(results, results + base::size(results));
+ test.expected_results_ = {u"5187", u"6543", u"2109", u"8765"};
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
for (size_t i = 0; i < test.total_splits_; ++i) {
@@ -1352,12 +1336,12 @@ TEST_F(AutofillFieldFillerTest, FillCreditCardNumberWithEqualSizeSplits) {
cc_number_part.set_credit_card_number_offset(4 * i);
// Fill with a card-number; should fill just the card_number_part.
- credit_card()->SetNumber(ASCIIToUTF16(test.card_number_));
+ credit_card()->SetNumber(test.card_number_);
filler.FillFormField(cc_number_part, credit_card(), &cc_number_part,
/*cvc=*/std::u16string());
// Verify for expected results.
- EXPECT_EQ(ASCIIToUTF16(test.expected_results_[i]),
+ EXPECT_EQ(test.expected_results_[i],
cc_number_part.value.substr(0, cc_number_part.max_length));
EXPECT_EQ(4 * i, cc_number_part.credit_card_number_offset());
}
@@ -1366,25 +1350,23 @@ TEST_F(AutofillFieldFillerTest, FillCreditCardNumberWithEqualSizeSplits) {
AutofillField cc_number_full;
cc_number_full.set_heuristic_type(CREDIT_CARD_NUMBER);
- credit_card()->SetNumber(ASCIIToUTF16(test.card_number_));
+ credit_card()->SetNumber(test.card_number_);
filler.FillFormField(cc_number_full, credit_card(), &cc_number_full,
/*cvc=*/std::u16string());
// Verify for expected results.
- EXPECT_EQ(ASCIIToUTF16(test.card_number_), cc_number_full.value);
+ EXPECT_EQ(test.card_number_, cc_number_full.value);
}
TEST_F(AutofillFieldFillerTest, FillCreditCardNumberWithUnequalSizeSplits) {
// Case 3: card with 15 digits number, broken up into three unequal groups, of
// lengths 4, 6, and 5.
CreditCardTestCase test;
- test.card_number_ = "423456789012345";
+ test.card_number_ = u"423456789012345";
test.total_splits_ = 3;
int splits[] = {4, 6, 5};
test.splits_ = std::vector<int>(splits, splits + base::size(splits));
- std::string results[] = {"4234", "567890", "12345"};
- test.expected_results_ =
- std::vector<std::string>(results, results + base::size(results));
+ test.expected_results_ = {u"4234", u"567890", u"12345"};
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
// Start executing test cases to verify parts and full credit card number.
@@ -1395,12 +1377,12 @@ TEST_F(AutofillFieldFillerTest, FillCreditCardNumberWithUnequalSizeSplits) {
cc_number_part.set_credit_card_number_offset(GetNumberOffset(i, test));
// Fill with a card-number; should fill just the card_number_part.
- credit_card()->SetNumber(ASCIIToUTF16(test.card_number_));
+ credit_card()->SetNumber(test.card_number_);
filler.FillFormField(cc_number_part, credit_card(), &cc_number_part,
/*cvc=*/std::u16string());
// Verify for expected results.
- EXPECT_EQ(ASCIIToUTF16(test.expected_results_[i]),
+ EXPECT_EQ(test.expected_results_[i],
cc_number_part.value.substr(0, cc_number_part.max_length));
EXPECT_EQ(GetNumberOffset(i, test),
cc_number_part.credit_card_number_offset());
@@ -1409,12 +1391,12 @@ TEST_F(AutofillFieldFillerTest, FillCreditCardNumberWithUnequalSizeSplits) {
// Verify that full card-number shall get fill properly as well.
AutofillField cc_number_full;
cc_number_full.set_heuristic_type(CREDIT_CARD_NUMBER);
- credit_card()->SetNumber(ASCIIToUTF16(test.card_number_));
+ credit_card()->SetNumber(test.card_number_);
filler.FillFormField(cc_number_full, credit_card(), &cc_number_full,
/*cvc=*/std::u16string());
// Verify for expected results.
- EXPECT_EQ(ASCIIToUTF16(test.card_number_), cc_number_full.value);
+ EXPECT_EQ(test.card_number_, cc_number_full.value);
}
TEST_F(AutofillFieldFillerTest, FindShortestSubstringMatchInSelect) {
@@ -1464,8 +1446,8 @@ TEST_F(AutofillFieldFillerTest, FindShortestSubstringMatchInSelect) {
struct FillStateTextTestCase {
HtmlFieldType field_type;
size_t field_max_length;
- std::string value_to_fill;
- std::string expected_value;
+ std::u16string value_to_fill;
+ std::u16string expected_value;
bool should_fill;
};
@@ -1483,12 +1465,12 @@ TEST_P(AutofillStateTextTest, FillStateText) {
FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
AutofillProfile address = test::GetFullProfile();
- address.SetRawInfo(ADDRESS_HOME_STATE, UTF8ToUTF16(test_case.value_to_fill));
+ address.SetRawInfo(ADDRESS_HOME_STATE, test_case.value_to_fill);
bool has_filled =
filler.FillFormField(field, &address, &field, /*cvc=*/std::u16string());
EXPECT_EQ(test_case.should_fill, has_filled);
- EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value);
+ EXPECT_EQ(test_case.expected_value, field.value);
}
INSTANTIATE_TEST_SUITE_P(
@@ -1499,28 +1481,28 @@ INSTANTIATE_TEST_SUITE_P(
// should
// fill the state value as is.
FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, /* default value */ 0,
- "New York", "New York", true},
+ u"New York", u"New York", true},
FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, /* default value */ 0,
- "NY", "NY", true},
+ u"NY", u"NY", true},
// Filling a state to a text field with a maxlength value equal to the
// value's length should fill the state value as is.
- FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 8, "New York",
- "New York", true},
+ FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 8, u"New York",
+ u"New York", true},
// Filling a state to a text field with a maxlength value lower than the
// value's length but higher than the value's abbreviation should fill
// the state abbreviation.
- FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 2, "New York", "NY",
+ FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 2, u"New York", u"NY",
true},
- FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 2, "NY", "NY", true},
+ FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 2, u"NY", u"NY", true},
// Filling a state to a text field with a maxlength value lower than the
// value's length and the value's abbreviation should not fill at all.
- FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 1, "New York", "",
+ FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 1, u"New York", u"",
false},
- FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 1, "NY", "", false},
+ FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 1, u"NY", u"", false},
// Filling a state to a text field with a maxlength value lower than the
// value's length and that has no associated abbreviation should not
// fill at all.
- FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 3, "Quebec", "",
+ FillStateTextTestCase{HTML_TYPE_ADDRESS_LEVEL1, 3, u"Quebec", u"",
false}));
// Tests that the correct option is chosen in the selection box when one of the
diff --git a/chromium/components/autofill/core/browser/field_types.h b/chromium/components/autofill/core/browser/field_types.h
index a0feacceb22..7a03f0b5fc4 100644
--- a/chromium/components/autofill/core/browser/field_types.h
+++ b/chromium/components/autofill/core/browser/field_types.h
@@ -5,10 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_FIELD_TYPES_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_FIELD_TYPES_H_
-#include <map>
-#include <set>
-#include <string>
-
#include "base/strings/string_piece_forward.h"
#include "components/autofill/core/common/dense_set.h"
diff --git a/chromium/components/autofill/core/browser/form_data_importer.cc b/chromium/components/autofill/core/browser/form_data_importer.cc
index a074a6d95f7..c62d775623a 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer.cc
@@ -262,7 +262,7 @@ void FormDataImporter::ImportFormData(const FormStructure& submitted_form,
bool profile_autofill_enabled,
bool credit_card_autofill_enabled) {
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> detected_upi_id;
+ absl::optional<std::string> detected_upi_id;
bool is_credit_card_upstream_enabled =
credit_card_save_manager_->IsCreditCardUploadEnabled();
@@ -424,7 +424,7 @@ bool FormDataImporter::ImportFormData(
bool credit_card_autofill_enabled,
bool should_return_local_card,
std::unique_ptr<CreditCard>* imported_credit_card,
- base::Optional<std::string>* imported_upi_id) {
+ absl::optional<std::string>* imported_upi_id) {
// We try the same |form| for both credit card and address import/update.
// - ImportCreditCard may update an existing card, or fill
// |imported_credit_card| with an extracted card. See .h for details of
@@ -557,6 +557,15 @@ bool FormDataImporter::ImportAddressProfileForSection(
// Go through each |form| field and attempt to constitute a valid profile.
for (const auto& field : form) {
+ // TODO(crbug/1213301): Remove this. This hack replaces the UNKNOWN_TYPE
+ // (due to autocomplete) of fields of a specific signature with their server
+ // or heuristic type. The changed value is reset below.
+ bool is_autocomplete_workaround =
+ base::FeatureList::IsEnabled(
+ features::kAutofillIgnoreAutocompleteForImport) &&
+ field->GetFieldSignature() == FieldSignature(2281611779) &&
+ field->Type().IsUnknown();
+
// Reject fields that are not within the specified |section|.
// If section is empty, use all fields.
if (field->section != section && !section.empty())
@@ -573,10 +582,17 @@ bool FormDataImporter::ImportAddressProfileForSection(
!field->is_focusable &&
!base::FeatureList::IsEnabled(
features::kAutofillProfileImportFromUnfocusableFields);
- if (!field->IsFieldFillable() || skip_unfocussable_field || value.empty())
+ if ((!is_autocomplete_workaround && !field->IsFieldFillable()) ||
+ skip_unfocussable_field || value.empty()) {
continue;
+ }
AutofillType field_type = field->Type();
+ if (is_autocomplete_workaround) {
+ field_type = AutofillType(field->server_type() != NO_SERVER_DATA
+ ? field->server_type()
+ : field->heuristic_type());
+ }
// Credit card fields are handled by ImportCreditCard().
if (field_type.group() == FieldTypeGroup::kCreditCard)
@@ -645,7 +661,7 @@ bool FormDataImporter::ImportAddressProfileForSection(
const translate::LanguageState* language_state =
client_->GetLanguageState();
if (language_state)
- page_language = language_state->original_language();
+ page_language = language_state->source_language();
// Retry to set the country of there is known page language.
if (!page_language.empty()) {
candidate_profile.SetInfoWithVerificationStatus(
@@ -731,7 +747,8 @@ bool FormDataImporter::ImportAddressProfileForSection(
// incognito mode but the import is not triggered if the browser is in the
// incognito mode.
DCHECK(!personal_data_manager_->IsOffTheRecord());
- address_profile_save_manager_->SaveProfile(candidate_profile);
+ address_profile_save_manager_->ImportProfileFromForm(
+ candidate_profile, app_locale_, form.source_url());
return true;
}
@@ -902,7 +919,9 @@ CreditCard FormDataImporter::ExtractCreditCardFromForm(
// month. Attempt to save with the option value. First find the index of the
// option text in the select options and try the corresponding value.
if (!saved && server_field_type == CREDIT_CARD_EXP_MONTH) {
- for (size_t i = 0; i < field->option_contents.size(); ++i) {
+ size_t items_count =
+ std::min(field->option_contents.size(), field->option_values.size());
+ for (size_t i = 0; i < items_count; ++i) {
if (value == field->option_contents[i]) {
candidate_credit_card.SetInfo(field_type, field->option_values[i],
app_locale_);
@@ -915,13 +934,13 @@ CreditCard FormDataImporter::ExtractCreditCardFromForm(
return candidate_credit_card;
}
-base::Optional<std::string> FormDataImporter::ImportUpiId(
+absl::optional<std::string> FormDataImporter::ImportUpiId(
const FormStructure& form) {
for (const auto& field : form) {
if (IsUPIVirtualPaymentAddress(field->value))
return base::UTF16ToUTF8(field->value);
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_data_importer.h b/chromium/components/autofill/core/browser/form_data_importer.h
index a368708103f..6df10de01a4 100644
--- a/chromium/components/autofill/core/browser/form_data_importer.h
+++ b/chromium/components/autofill/core/browser/form_data_importer.h
@@ -28,7 +28,7 @@ class AddressProfileSaveManager;
// Manages logic for importing address profiles and credit card information from
// web forms into the user's Autofill profile via the PersonalDataManager.
-// Owned by AutofillManager.
+// Owned by BrowserAutofillManager.
class FormDataImporter {
public:
// Record type of the credit card imported from the form, if one exists.
@@ -107,7 +107,7 @@ class FormDataImporter {
bool credit_card_autofill_enabled,
bool should_return_local_card,
std::unique_ptr<CreditCard>* imported_credit_card,
- base::Optional<std::string>* imported_upi_id);
+ absl::optional<std::string>* imported_upi_id);
// Go through the |form| fields and attempt to extract and import valid
// address profiles. Returns true on extraction success of at least one
@@ -139,7 +139,7 @@ class FormDataImporter {
// Go through the |form| fields and find a UPI ID to import. The return value
// will be empty if no UPI ID was found.
- base::Optional<std::string> ImportUpiId(const FormStructure& form);
+ absl::optional<std::string> ImportUpiId(const FormStructure& form);
// Whether a dynamic change form is imported.
bool from_dynamic_change_form_ = false;
@@ -166,7 +166,7 @@ class FormDataImporter {
#endif // #if !defined(OS_ANDROID) && !defined(OS_IOS)
// The personal data manager, used to save and load personal data to/from the
- // web database. This is overridden by the AutofillManagerTest.
+ // web database. This is overridden by the BrowserAutofillManagerTest.
// Weak reference.
// May be NULL. NULL indicates OTR.
PersonalDataManager* personal_data_manager_;
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 15c03e94c12..fd7d47e1adf 100644
--- a/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -127,6 +127,7 @@ class FormDataImporterTestBase {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/(user_mode == USER_MODE_INCOGNITO));
personal_data_manager_->AddObserver(&personal_data_observer_);
personal_data_manager_->OnSyncServiceInitialized(nullptr);
@@ -280,7 +281,7 @@ class FormDataImporterTest
}
void TearDown() override {
- // Order of destruction is important as AutofillManager relies on
+ // Order of destruction is important as BrowserAutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
test::ReenableSystemServices();
OSCryptMocker::TearDown();
@@ -615,6 +616,60 @@ TEST_P(FormDataImporterTest, ImportAddressProfiles) {
EXPECT_EQ(0, expected.Compare(*results[0]));
}
+// Tests that even if the the autocomplete prevents filling, it does not prevent
+// import. For now, this is limited to the field with the signature 2281611779.
+TEST_P(FormDataImporterTest, ImportAddressProfilesDespiteAutocomplete) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ features::kAutofillIgnoreAutocompleteForImport);
+
+ FormData form;
+ form.url = GURL("https://wwww.foo.com");
+
+ FormFieldData field;
+ test::CreateTestFormField("First name:", "first_name", "George", "text",
+ &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("Last name:", "last_name", "Washington", "text",
+ &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("Email:", "email", "theprez@gmail.com", "text",
+ &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("Address:", "checkout[shipping_address][address1]",
+ "21 Laussat St", "text", &field);
+ field.autocomplete_attribute = "none";
+ form.fields.push_back(field);
+ field.autocomplete_attribute = "";
+ test::CreateTestFormField("City:", "city", "San Francisco", "text", &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("State:", "state", "California", "text", &field);
+ form.fields.push_back(field);
+ test::CreateTestFormField("Zip:", "zip", "94102", "text", &field);
+ form.fields.push_back(field);
+ FormStructure form_structure(form);
+ form_structure.DetermineHeuristicTypes(nullptr, nullptr);
+ ImportAddressProfiles(/*extraction_successful=*/true, form_structure);
+
+ ASSERT_EQ(form_structure.field(3)->GetFieldSignature(),
+ FieldSignature(2281611779));
+ ASSERT_EQ(form_structure.field(3)->Type().GetStorableType(), UNKNOWN_TYPE);
+
+ AutofillProfile expected(base::GenerateGUID(), test::kEmptyOrigin);
+ test::SetProfileInfo(&expected, "George", nullptr, "Washington",
+ "theprez@gmail.com", nullptr, "21 Laussat St", nullptr,
+ nullptr, "San Francisco", "California", "94102", nullptr,
+ nullptr);
+ const std::vector<AutofillProfile*>& results =
+ personal_data_manager_->GetProfiles();
+ ASSERT_EQ(1U, results.size());
+ EXPECT_EQ(0, expected.Compare(*results[0]));
+
+ ASSERT_EQ(form_structure.field(3)->GetFieldSignature(),
+ FieldSignature(2281611779));
+ ASSERT_EQ(form_structure.field(3)->Type().GetStorableType(), UNKNOWN_TYPE);
+}
+
TEST_P(FormDataImporterTest, ImportAddressProfileFromUnifiedSection) {
FormData form;
form.url = GURL("https://wwww.foo.com");
@@ -2014,7 +2069,7 @@ TEST_P(FormDataImporterTest, ImportAddressProfiles_LocalizedCountryName) {
form.fields.push_back(field);
// Set up language state mock.
- autofill_client_->GetLanguageState()->SetOriginalLanguage("");
+ autofill_client_->GetLanguageState()->SetSourceLanguage("");
// Verify that the country code is not determined from the country value if
// the page language is not set.
@@ -2026,7 +2081,7 @@ TEST_P(FormDataImporterTest, ImportAddressProfiles_LocalizedCountryName) {
ASSERT_EQ(0U, personal_data_manager_->GetCreditCards().size());
// Set the page language to match the localized country value and try again.
- autofill_client_->GetLanguageState()->SetOriginalLanguage("de");
+ autofill_client_->GetLanguageState()->SetSourceLanguage("de");
ImportAddressProfiles(/*extraction_successful=*/true, form_structure);
@@ -2865,7 +2920,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -2953,7 +3008,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -2992,7 +3047,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -3031,7 +3086,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -3069,7 +3124,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -3094,7 +3149,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -3121,7 +3176,7 @@ TEST_P(
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -3164,7 +3219,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -3213,7 +3268,7 @@ TEST_P(FormDataImporterTest, ImportFormData_OneAddressOneCreditCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
@@ -3301,7 +3356,7 @@ TEST_P(FormDataImporterTest, ImportFormData_TwoAddressesOneCreditCard) {
.WillRepeatedly(QuitMessageLoop(&run_loop));
EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
.Times(testing::AnyNumber());
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
// Still returns true because the credit card import was successful.
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -3418,7 +3473,7 @@ TEST_P(FormDataImporterTest, ImportFormData_AddressesDisabledOneCreditCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/false,
/*credit_card_autofill_enabled=*/true,
@@ -3476,7 +3531,7 @@ TEST_P(FormDataImporterTest, ImportFormData_OneAddressCreditCardDisabled) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
@@ -3538,7 +3593,7 @@ TEST_P(FormDataImporterTest, ImportFormData_AddressCreditCardDisabled) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/false,
@@ -3595,7 +3650,7 @@ TEST_P(FormDataImporterTest, DontDuplicateMaskedServerCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -3634,7 +3689,7 @@ TEST_P(FormDataImporterTest, ImportFormData_HiddenCreditCardFormAfterEntered) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
// Still returns true because the credit card import was successful.
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
@@ -3670,7 +3725,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -3719,7 +3774,7 @@ TEST_P(FormDataImporterTest, DontDuplicateFullServerCard) {
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
@@ -3764,7 +3819,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
@@ -3813,7 +3868,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
@@ -3859,7 +3914,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
@@ -3906,7 +3961,7 @@ TEST_P(
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
@@ -3952,7 +4007,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
@@ -4001,7 +4056,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure,
/*profile_autofill_enabled=*/true,
@@ -4051,7 +4106,7 @@ TEST_P(FormDataImporterTest,
FormStructure form_structure(form);
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card;
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/true,
/*credit_card_autofill_enabled=*/true,
@@ -4076,7 +4131,7 @@ TEST_P(FormDataImporterTest, ImportUpiId) {
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card; // Discarded.
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_TRUE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/false,
@@ -4101,7 +4156,7 @@ TEST_P(FormDataImporterTest, ImportUpiIdDisabled) {
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card; // Discarded.
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/false,
@@ -4125,7 +4180,7 @@ TEST_P(FormDataImporterTest, ImportUpiIdIgnoreNonUpiId) {
form_structure.DetermineHeuristicTypes(nullptr, nullptr);
std::unique_ptr<CreditCard> imported_credit_card; // Discarded.
- base::Optional<std::string> imported_upi_id;
+ absl::optional<std::string> imported_upi_id;
EXPECT_FALSE(form_data_importer_->ImportFormData(
form_structure, /*profile_autofill_enabled=*/false,
diff --git a/chromium/components/autofill/core/browser/form_parsing/autofill_parsing_utils.h b/chromium/components/autofill/core/browser/form_parsing/autofill_parsing_utils.h
index b6890a13bd4..22e3c10c48b 100644
--- a/chromium/components/autofill/core/browser/form_parsing/autofill_parsing_utils.h
+++ b/chromium/components/autofill/core/browser/form_parsing/autofill_parsing_utils.h
@@ -7,8 +7,8 @@
#include <string>
-#include "base/optional.h"
#include "components/autofill/core/common/language_code.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -63,4 +63,4 @@ struct MatchingPattern {
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_DATA_MODEL_AUTOFILL_PARSING_UTILS_H_
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PARSING_AUTOFILL_PARSING_UTILS_H_
diff --git a/chromium/components/autofill/core/browser/form_parsing/autofill_scanner.h b/chromium/components/autofill/core/browser/form_parsing/autofill_scanner.h
index 53179b4b1c6..52d90906dc5 100644
--- a/chromium/components/autofill/core/browser/form_parsing/autofill_scanner.h
+++ b/chromium/components/autofill/core/browser/form_parsing/autofill_scanner.h
@@ -8,7 +8,6 @@
#include <stddef.h>
#include <memory>
-#include <string>
#include <vector>
#include "base/macros.h"
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 f816d1b1c12..745e8a5dbd7 100644
--- a/chromium/components/autofill/core/browser/form_parsing/form_field.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/form_field.cc
@@ -14,7 +14,6 @@
#include "base/feature_list.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_regexes.h"
#include "components/autofill/core/browser/autofill_type.h"
diff --git a/chromium/components/autofill/core/browser/form_parsing/form_field_unittest.cc b/chromium/components/autofill/core/browser/form_parsing/form_field_unittest.cc
index 54e0c2e6524..2d04f202ede 100644
--- a/chromium/components/autofill/core/browser/form_parsing/form_field_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_parsing/form_field_unittest.cc
@@ -15,7 +15,6 @@
#include "testing/gtest/include/gtest/gtest.h"
using autofill::features::kAutofillFixFillableFieldTypes;
-using base::ASCIIToUTF16;
namespace autofill {
@@ -26,9 +25,9 @@ FieldRendererId MakeFieldRendererId() {
}
// Sets both the field label and parseable label to |label|.
-void SetFieldLabels(AutofillField* field, const std::string& label) {
- field->label = base::UTF8ToUTF16(label);
- field->set_parseable_label(base::UTF8ToUTF16(label));
+void SetFieldLabels(AutofillField* field, const std::u16string& label) {
+ field->label = label;
+ field->set_parseable_label(label);
}
} // namespace
@@ -40,76 +39,76 @@ TEST(FormFieldTest, Match) {
EXPECT_TRUE(FormField::Match(&field, std::u16string(), MATCH_LABEL));
// Empty pattern matches non-empty string.
- SetFieldLabels(&field, "a");
+ SetFieldLabels(&field, u"a");
EXPECT_TRUE(FormField::Match(&field, std::u16string(), MATCH_LABEL));
// Strictly empty pattern matches empty string.
- SetFieldLabels(&field, "");
+ SetFieldLabels(&field, u"");
EXPECT_TRUE(FormField::Match(&field, u"^$", MATCH_LABEL));
// Strictly empty pattern does not match non-empty string.
- SetFieldLabels(&field, "a");
+ SetFieldLabels(&field, u"a");
EXPECT_FALSE(FormField::Match(&field, u"^$", MATCH_LABEL));
// Non-empty pattern doesn't match empty string.
- SetFieldLabels(&field, "");
+ SetFieldLabels(&field, u"");
EXPECT_FALSE(FormField::Match(&field, u"a", MATCH_LABEL));
// Beginning of line.
- SetFieldLabels(&field, "head_tail");
+ SetFieldLabels(&field, u"head_tail");
EXPECT_TRUE(FormField::Match(&field, u"^head", MATCH_LABEL));
EXPECT_FALSE(FormField::Match(&field, u"^tail", MATCH_LABEL));
// End of line.
- SetFieldLabels(&field, "head_tail");
+ SetFieldLabels(&field, u"head_tail");
EXPECT_FALSE(FormField::Match(&field, u"head$", MATCH_LABEL));
EXPECT_TRUE(FormField::Match(&field, u"tail$", MATCH_LABEL));
// Exact.
- SetFieldLabels(&field, "head_tail");
+ SetFieldLabels(&field, u"head_tail");
EXPECT_FALSE(FormField::Match(&field, u"^head$", MATCH_LABEL));
EXPECT_FALSE(FormField::Match(&field, u"^tail$", MATCH_LABEL));
EXPECT_TRUE(FormField::Match(&field, u"^head_tail$", MATCH_LABEL));
// Escaped dots.
- SetFieldLabels(&field, "m.i.");
+ SetFieldLabels(&field, u"m.i.");
// Note: This pattern is misleading as the "." characters are wild cards.
EXPECT_TRUE(FormField::Match(&field, u"m.i.", MATCH_LABEL));
EXPECT_TRUE(FormField::Match(&field, u"m\\.i\\.", MATCH_LABEL));
- SetFieldLabels(&field, "mXiX");
+ SetFieldLabels(&field, u"mXiX");
EXPECT_TRUE(FormField::Match(&field, u"m.i.", MATCH_LABEL));
EXPECT_FALSE(FormField::Match(&field, u"m\\.i\\.", MATCH_LABEL));
// Repetition.
- SetFieldLabels(&field, "headtail");
+ SetFieldLabels(&field, u"headtail");
EXPECT_TRUE(FormField::Match(&field, u"head.*tail", MATCH_LABEL));
- SetFieldLabels(&field, "headXtail");
+ SetFieldLabels(&field, u"headXtail");
EXPECT_TRUE(FormField::Match(&field, u"head.*tail", MATCH_LABEL));
- SetFieldLabels(&field, "headXXXtail");
+ SetFieldLabels(&field, u"headXXXtail");
EXPECT_TRUE(FormField::Match(&field, u"head.*tail", MATCH_LABEL));
- SetFieldLabels(&field, "headtail");
+ SetFieldLabels(&field, u"headtail");
EXPECT_FALSE(FormField::Match(&field, u"head.+tail", MATCH_LABEL));
- SetFieldLabels(&field, "headXtail");
+ SetFieldLabels(&field, u"headXtail");
EXPECT_TRUE(FormField::Match(&field, u"head.+tail", MATCH_LABEL));
- SetFieldLabels(&field, "headXXXtail");
+ SetFieldLabels(&field, u"headXXXtail");
EXPECT_TRUE(FormField::Match(&field, u"head.+tail", MATCH_LABEL));
// Alternation.
- SetFieldLabels(&field, "head_tail");
+ SetFieldLabels(&field, u"head_tail");
EXPECT_TRUE(FormField::Match(&field, u"head|other", MATCH_LABEL));
EXPECT_TRUE(FormField::Match(&field, u"tail|other", MATCH_LABEL));
EXPECT_FALSE(FormField::Match(&field, u"bad|good", MATCH_LABEL));
// Case sensitivity.
- SetFieldLabels(&field, "xxxHeAd_tAiLxxx");
+ SetFieldLabels(&field, u"xxxHeAd_tAiLxxx");
EXPECT_TRUE(FormField::Match(&field, u"head_tail", MATCH_LABEL));
// Word boundaries.
- SetFieldLabels(&field, "contains word:");
+ SetFieldLabels(&field, u"contains word:");
EXPECT_TRUE(FormField::Match(&field, u"\\bword\\b", MATCH_LABEL));
EXPECT_FALSE(FormField::Match(&field, u"\\bcon\\b", MATCH_LABEL));
- // Make sure the circumflex in 'crepe' is not treated as a word boundary.
- field.label = base::UTF8ToUTF16("cr\xC3\xAApe");
+ // Make sure the circumflex in 'crêpe' is not treated as a word boundary.
+ field.label = u"crêpe";
EXPECT_FALSE(FormField::Match(&field, u"\\bcr\\b", MATCH_LABEL));
}
diff --git a/chromium/components/autofill/core/browser/form_processing/label_processing_util.cc b/chromium/components/autofill/core/browser/form_processing/label_processing_util.cc
index 6cfc0008ea9..4a4f1c45a45 100644
--- a/chromium/components/autofill/core/browser/form_processing/label_processing_util.cc
+++ b/chromium/components/autofill/core/browser/form_processing/label_processing_util.cc
@@ -17,7 +17,7 @@ const int kMaxNumberOfFieldsToShareALabel = 3;
// The maximum length of a label that can be shared among fields.
const int kMaxLengthOfShareableLabel = 40;
-base::Optional<std::vector<std::u16string>> GetParseableLabels(
+absl::optional<std::vector<std::u16string>> GetParseableLabels(
const LabelPieces& labels) {
// Make a copy of the labels.
LabelPieces shared_labels = labels;
@@ -92,7 +92,7 @@ base::Optional<std::vector<std::u16string>> GetParseableLabels(
}
if (!shared_labels_found) {
- return base::nullopt;
+ return absl::nullopt;
}
// Otherwise convert the shared label string pieces into strings for memory
@@ -101,7 +101,7 @@ base::Optional<std::vector<std::u16string>> GetParseableLabels(
result.reserve(shared_labels.size());
base::ranges::transform(shared_labels, std::back_inserter(result),
[](auto& s) { return std::u16string(s); });
- return base::make_optional(std::move(result));
+ return absl::make_optional(std::move(result));
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_processing/label_processing_util.h b/chromium/components/autofill/core/browser/form_processing/label_processing_util.h
index c79fa295720..32e59e5b153 100644
--- a/chromium/components/autofill/core/browser/form_processing/label_processing_util.h
+++ b/chromium/components/autofill/core/browser/form_processing/label_processing_util.h
@@ -6,17 +6,17 @@
#define COMPONENTS_AUTOFILL_CORE_BROWSER_FORM_PROCESSING_LABEL_PROCESSING_UTIL_H_
#include <vector>
-#include "base/optional.h"
#include "base/strings/string_piece.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
// If parseable labels can be derived from |labels|, a vector of
// |std::u16string| is return that is aligned with |labels|.
// Parseable labels can be derived by splitting one label between multiple
-// adjacent fields. If there aren't any changes to the labels, |base::nullopt|
+// adjacent fields. If there aren't any changes to the labels, |absl::nullopt|
// is returned.
-base::Optional<std::vector<std::u16string>> GetParseableLabels(
+absl::optional<std::vector<std::u16string>> GetParseableLabels(
const std::vector<base::StringPiece16>& labels);
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/form_processing/label_processing_util_unittest.cc b/chromium/components/autofill/core/browser/form_processing/label_processing_util_unittest.cc
index 6cd10b21b97..584ac357e2b 100644
--- a/chromium/components/autofill/core/browser/form_processing/label_processing_util_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_processing/label_processing_util_unittest.cc
@@ -34,7 +34,7 @@ TEST(LabelProcessingUtil, GetParseableNameStringPieces) {
labels.push_back(u"");
labels.push_back(u"Zip");
- auto expectation = base::make_optional(std::vector<std::u16string>());
+ auto expectation = absl::make_optional(std::vector<std::u16string>());
expectation->push_back(u"City");
expectation->push_back(u"Street");
expectation->push_back(u"House Number");
@@ -51,7 +51,7 @@ TEST(LabelProcessingUtil, GetParseableNameStringPieces_ThreeComponents) {
labels.push_back(u"");
labels.push_back(u"Zip");
- auto expectation = base::make_optional(std::vector<std::u16string>());
+ auto expectation = absl::make_optional(std::vector<std::u16string>());
expectation->push_back(u"City");
expectation->push_back(u"Street");
expectation->push_back(u"House Number");
@@ -70,7 +70,7 @@ TEST(LabelProcessingUtil, GetParseableNameStringPieces_TooManyComponents) {
labels.push_back(u"");
labels.push_back(u"Zip");
- base::Optional<std::vector<std::u16string>> expectation = base::nullopt;
+ absl::optional<std::vector<std::u16string>> expectation = absl::nullopt;
;
EXPECT_EQ(GetParseableLabels(StringsToStringPieces(labels)), expectation);
@@ -83,7 +83,7 @@ TEST(LabelProcessingUtil, GetParseableNameStringPieces_UnmachtingComponents) {
labels.push_back(u"");
labels.push_back(u"Zip");
- base::Optional<std::vector<std::u16string>> expectation = base::nullopt;
+ absl::optional<std::vector<std::u16string>> expectation = absl::nullopt;
EXPECT_EQ(GetParseableLabels(StringsToStringPieces(labels)), expectation);
}
@@ -95,7 +95,7 @@ TEST(LabelProcessingUtil, GetParseableNameStringPieces_SplitableLabelAtEnd) {
labels.push_back(u"Zip");
labels.push_back(u"Street & House Number & Floor");
- base::Optional<std::vector<std::u16string>> expectation = base::nullopt;
+ absl::optional<std::vector<std::u16string>> expectation = absl::nullopt;
EXPECT_EQ(GetParseableLabels(StringsToStringPieces(labels)), expectation);
}
@@ -104,12 +104,12 @@ TEST(LabelProcessingUtil, GetParseableNameStringPieces_TooLongLabel) {
std::vector<std::u16string> labels;
labels.push_back(u"City");
labels.push_back(
- ASCIIToUTF16("Street & House Number with a lot of additional text that "
- "exceeds 40 characters by far"));
+ u"Street & House Number with a lot of additional text that exceeds 40 "
+ u"characters by far");
labels.push_back(u"");
labels.push_back(u"Zip");
- base::Optional<std::vector<std::u16string>> expectation = base::nullopt;
+ absl::optional<std::vector<std::u16string>> expectation = absl::nullopt;
EXPECT_EQ(GetParseableLabels(StringsToStringPieces(labels)), expectation);
}
diff --git a/chromium/components/autofill/core/browser/form_processing/name_processing_util.cc b/chromium/components/autofill/core/browser/form_processing/name_processing_util.cc
index 29140ba4570..b6c5dffeaad 100644
--- a/chromium/components/autofill/core/browser/form_processing/name_processing_util.cc
+++ b/chromium/components/autofill/core/browser/form_processing/name_processing_util.cc
@@ -28,10 +28,10 @@ constexpr int kMinCommonNameAffixLength = 3;
constexpr int kMinCommonNameLongPrefixLength = 16;
// Regular expression for checking if |parseable_name| is valid after stripping
// affixes.
-constexpr char kParseableNameValidationRe[] = "\\D";
+constexpr char16_t kParseableNameValidationRe[] = u"\\D";
using NamePieces = std::vector<base::StringPiece16>;
-using OptionalNamePieces = base::Optional<NamePieces>;
+using OptionalNamePieces = absl::optional<NamePieces>;
// Returns the length of the longest common prefix.
// If |findCommonSuffix| is set, the length of the longest common suffix is
@@ -85,13 +85,13 @@ size_t FindLongestCommonPrefixLengthInStringsWithMinimalLength(
// is the |autofill::kParseableNameValidationRe| regex.
bool IsValidParseableName(const base::StringPiece16 parseable_name) {
static const std::u16string kParseableNameValidationPattern =
- base::UTF8ToUTF16(kParseableNameValidationRe);
+ kParseableNameValidationRe;
return MatchesPattern(parseable_name, kParseableNameValidationPattern);
}
// Tries to strip |offset_left| and |offset_right| from entriees in
// |field_names| and checks if the resulting names are still valid parseable
-// names. If not possible, return |base::nullopt|.
+// names. If not possible, return |absl::nullopt|.
OptionalNamePieces GetStrippedParseableNamesIfValid(
const NamePieces& field_names,
size_t offset_left,
@@ -110,15 +110,15 @@ OptionalNamePieces GetStrippedParseableNamesIfValid(
: parseable_name);
if (!IsValidParseableName(stripped_names.back()))
- return base::nullopt;
+ return absl::nullopt;
}
- return base::make_optional(stripped_names);
+ return absl::make_optional(stripped_names);
}
// Tries to remove common affixes from |field_names| and returns the result. If
// neither a common affix exists, or if one or more of the resulting strings is
-// not a valid parseable name, |base::nullopt| is returned.
+// not a valid parseable name, |absl::nullopt| is returned.
// The number of names in |field_names| must exceed
// |kCommonNameAffixRemovalFieldNumberThreshold| in order to make the affix
// removal possible. Also, the length of an affix must exceed
@@ -128,7 +128,7 @@ OptionalNamePieces RemoveCommonAffixesIfPossible(
// Updates the field name parsed by heuristics if several criteria are met.
// Several fields must be present in the form.
if (field_names.size() < kCommonNameAffixRemovalFieldNumberThreshold)
- return base::nullopt;
+ return absl::nullopt;
size_t longest_prefix_length =
FindLongestCommonAffixLength(field_names, false);
@@ -144,7 +144,7 @@ OptionalNamePieces RemoveCommonAffixesIfPossible(
// If neither a common prefix of suffix was found return false.
if (longest_prefix_length == 0 && longest_suffix_length == 0) {
- return base::nullopt;
+ return absl::nullopt;
}
// Otherwise try to reduce the names.
@@ -155,7 +155,7 @@ OptionalNamePieces RemoveCommonAffixesIfPossible(
// Tries to remove common prefixes from |field_names| and returns the result. If
// neither a common prefix exists, or if one or more of the resulting strings is
-// not a valid parseable name, |base::nullopt| is returned.
+// not a valid parseable name, |absl::nullopt| is returned.
// The number of names in |field_names| must exceed
// |kCommonNamePrefixRemovalFieldThreshold| in order to make the prefix
// removal possible. Also, the length of a prefix must exceed
@@ -164,14 +164,14 @@ OptionalNamePieces RemoveCommonPrefixIfPossible(const NamePieces& field_names) {
// Updates the field name parsed by heuristics if several criteria are met.
// Several fields must be present in the form.
if (field_names.size() < kCommonNamePrefixRemovalFieldThreshold)
- return base::nullopt;
+ return absl::nullopt;
size_t longest_prefix_length =
FindLongestCommonAffixLength(field_names, false);
// Don't remove the common affix if it's not long enough.
if (longest_prefix_length < kMinCommonNamePrefixLength)
- return base::nullopt;
+ return absl::nullopt;
// Otherwise try to reduce the names.
return GetStrippedParseableNamesIfValid(
@@ -191,13 +191,13 @@ OptionalNamePieces RemoveCommonPrefixForNamesWithMinimalLengthIfPossible(
// Update the field name parsed by heuristics if several criteria are met.
// Several fields must be present in the form.
if (field_names.size() < kCommonNamePrefixRemovalFieldThreshold)
- return base::nullopt;
+ return absl::nullopt;
const size_t longest_prefix =
FindLongestCommonPrefixLengthInStringsWithMinimalLength(
field_names, kMinCommonNameLongPrefixLength);
if (longest_prefix < kMinCommonNameLongPrefixLength) {
- return base::nullopt;
+ return absl::nullopt;
}
return GetStrippedParseableNamesIfValid(field_names, longest_prefix, 0,
@@ -205,7 +205,7 @@ OptionalNamePieces RemoveCommonPrefixForNamesWithMinimalLengthIfPossible(
}
std::vector<std::u16string> GetParseableNames(const NamePieces& field_names) {
- OptionalNamePieces parseable_names = base::nullopt;
+ OptionalNamePieces parseable_names = absl::nullopt;
std::vector<std::u16string> result;
result.reserve(field_names.size());
diff --git a/chromium/components/autofill/core/browser/form_processing/name_processing_util.h b/chromium/components/autofill/core/browser/form_processing/name_processing_util.h
index 41cd63f714f..6c644d5e411 100644
--- a/chromium/components/autofill/core/browser/form_processing/name_processing_util.h
+++ b/chromium/components/autofill/core/browser/form_processing/name_processing_util.h
@@ -7,11 +7,11 @@
#include <vector>
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_regexes.h"
#include "components/autofill/core/browser/form_structure.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -22,24 +22,24 @@ size_t FindLongestCommonAffixLength(
bool IsValidParseableName(const base::StringPiece16 parseable_name);
-base::Optional<std::vector<base::StringPiece16>> RemoveCommonAffixesIfPossible(
+absl::optional<std::vector<base::StringPiece16>> RemoveCommonAffixesIfPossible(
const std::vector<base::StringPiece16>& field_names);
size_t FindLongestCommonPrefixLengthInStringsWithMinimalLength(
const std::vector<base::StringPiece16>& strings,
size_t minimal_length);
-base::Optional<std::vector<base::StringPiece16>>
+absl::optional<std::vector<base::StringPiece16>>
GetStrippedParseableNamesIfValid(
const std::vector<base::StringPiece16>& field_names,
size_t offset_left,
size_t offset_right,
size_t minimal_string_length_to_strip);
-base::Optional<std::vector<base::StringPiece16>> RemoveCommonPrefixIfPossible(
+absl::optional<std::vector<base::StringPiece16>> RemoveCommonPrefixIfPossible(
const std::vector<base::StringPiece16>& field_names);
-base::Optional<std::vector<base::StringPiece16>>
+absl::optional<std::vector<base::StringPiece16>>
RemoveCommonPrefixForNamesWithMinimalLengthIfPossible(
const std::vector<base::StringPiece16>& field_names);
#endif
diff --git a/chromium/components/autofill/core/browser/form_processing/name_processing_util_unittest.cc b/chromium/components/autofill/core/browser/form_processing/name_processing_util_unittest.cc
index 8c808ee37d0..cd09fb325ac 100644
--- a/chromium/components/autofill/core/browser/form_processing/name_processing_util_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_processing/name_processing_util_unittest.cc
@@ -10,9 +10,12 @@
#include "components/autofill/core/common/autofill_features.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::ASCIIToUTF16;
-
namespace {
+
+size_t strlen16(const char16_t* str) {
+ return std::char_traits<char16_t>::length(str);
+}
+
std::vector<base::StringPiece16> StringsToStringPieces(
const std::vector<std::u16string>& strings) {
std::vector<base::StringPiece16> string_pieces;
@@ -55,7 +58,7 @@ TEST(NameProcessingUtil, FindLongestCommonAffixLength) {
strings.push_back(u"1234567XXX901234567890");
String16ToStringPiece16(strings, stringPieces);
size_t affixLength = FindLongestCommonAffixLength(stringPieces, false);
- EXPECT_EQ(ASCIIToUTF16("123456").size(), affixLength);
+ EXPECT_EQ(strlen16(u"123456"), affixLength);
// Normal suffix case.
strings.clear();
@@ -65,7 +68,7 @@ TEST(NameProcessingUtil, FindLongestCommonAffixLength) {
strings.push_back(u"1234567890123456_city_address");
String16ToStringPiece16(strings, stringPieces);
affixLength = FindLongestCommonAffixLength(stringPieces, true);
- EXPECT_EQ(ASCIIToUTF16("dress").size(), affixLength);
+ EXPECT_EQ(strlen16(u"dress"), affixLength);
// Handles no common prefix.
strings.clear();
@@ -74,7 +77,7 @@ TEST(NameProcessingUtil, FindLongestCommonAffixLength) {
strings.push_back(u"7890123456789012");
String16ToStringPiece16(strings, stringPieces);
affixLength = FindLongestCommonAffixLength(stringPieces, false);
- EXPECT_EQ(ASCIIToUTF16("").size(), affixLength);
+ EXPECT_EQ(strlen16(u""), affixLength);
// Handles no common suffix.
strings.clear();
@@ -83,33 +86,33 @@ TEST(NameProcessingUtil, FindLongestCommonAffixLength) {
strings.push_back(u"7890123456789012");
String16ToStringPiece16(strings, stringPieces);
affixLength = FindLongestCommonAffixLength(stringPieces, true);
- EXPECT_EQ(ASCIIToUTF16("").size(), affixLength);
+ EXPECT_EQ(strlen16(u""), affixLength);
// Only one string, prefix case.
strings.clear();
strings.push_back(u"1234567890");
String16ToStringPiece16(strings, stringPieces);
affixLength = FindLongestCommonAffixLength(stringPieces, false);
- EXPECT_EQ(ASCIIToUTF16("1234567890").size(), affixLength);
+ EXPECT_EQ(strlen16(u"1234567890"), affixLength);
// Only one string, suffix case.
strings.clear();
strings.push_back(u"1234567890");
String16ToStringPiece16(strings, stringPieces);
affixLength = FindLongestCommonAffixLength(stringPieces, true);
- EXPECT_EQ(ASCIIToUTF16("1234567890").size(), affixLength);
+ EXPECT_EQ(strlen16(u"1234567890"), affixLength);
// Empty vector, prefix case.
strings.clear();
String16ToStringPiece16(strings, stringPieces);
affixLength = FindLongestCommonAffixLength(stringPieces, false);
- EXPECT_EQ(ASCIIToUTF16("").size(), affixLength);
+ EXPECT_EQ(strlen16(u""), affixLength);
// Empty vector, suffix case.
strings.clear();
String16ToStringPiece16(strings, stringPieces);
affixLength = FindLongestCommonAffixLength(stringPieces, true);
- EXPECT_EQ(ASCIIToUTF16("").size(), affixLength);
+ EXPECT_EQ(strlen16(u""), affixLength);
}
// Tests the determination of the length of the longest common prefix for
@@ -129,7 +132,7 @@ TEST(NameProcessingUtil,
0U);
}
-// Tests that a |base::nullopt| is returned if no common affix was removed.
+// Tests that a |absl::nullopt| is returned if no common affix was removed.
TEST(NameProcessingUtil, RemoveCommonAffixesIfPossible_NotPossible) {
std::vector<std::u16string> strings;
strings.push_back(u"abc");
@@ -138,7 +141,7 @@ TEST(NameProcessingUtil, RemoveCommonAffixesIfPossible_NotPossible) {
strings.push_back(u"abcdef");
EXPECT_EQ(RemoveCommonAffixesIfPossible(StringsToStringPieces(strings)),
- base::nullopt);
+ absl::nullopt);
}
// Tests that both the prefix and the suffix are removed.
@@ -157,7 +160,7 @@ TEST(NameProcessingUtil, RemoveCommonAffixesIfPossible) {
StringsToStringPieces(expectation));
}
-// Tests that a |base::nullopt| is returned if no common prefix was removed.
+// Tests that a |absl::nullopt| is returned if no common prefix was removed.
TEST(NameProcessingUtil, RemoveCommonPrefixIfPossible_NotPossible) {
std::vector<std::u16string> strings;
strings.push_back(u"abc");
@@ -166,7 +169,7 @@ TEST(NameProcessingUtil, RemoveCommonPrefixIfPossible_NotPossible) {
strings.push_back(u"abcdef");
EXPECT_EQ(RemoveCommonPrefixIfPossible(StringsToStringPieces(strings)),
- base::nullopt);
+ absl::nullopt);
}
// Tests that prefix is removed correctly.
@@ -214,7 +217,7 @@ TEST(NameProcessingUtil, RemoveCommonPrefixIfPossible_TooShort) {
strings.push_back(u"abccczzz");
EXPECT_EQ(RemoveCommonPrefixIfPossible(StringsToStringPieces(strings)),
- base::nullopt);
+ absl::nullopt);
}
// Tests that the strings are correctly stripped.
@@ -234,7 +237,7 @@ TEST(NameProcessingUtil, GetStrippedParseableNamesIfValid) {
StringsToStringPieces(expectation));
}
-// Tests that a |base::nullopt| is returned if one of stripped names is not
+// Tests that a |absl::nullopt| is returned if one of stripped names is not
// valid.
TEST(NameProcessingUtil, GetStrippedParseableNamesIfValid_NotValid) {
std::vector<std::u16string> strings;
@@ -250,7 +253,7 @@ TEST(NameProcessingUtil, GetStrippedParseableNamesIfValid_NotValid) {
EXPECT_EQ(
GetStrippedParseableNamesIfValid(StringsToStringPieces(strings), 3, 2, 1),
- base::nullopt);
+ absl::nullopt);
}
// Tests that the parseable names are returned correctly.
diff --git a/chromium/components/autofill/core/browser/form_structure.cc b/chromium/components/autofill/core/browser/form_structure.cc
index 18ec46fce12..dc40c1554e6 100644
--- a/chromium/components/autofill/core/browser/form_structure.cc
+++ b/chromium/components/autofill/core/browser/form_structure.cc
@@ -527,34 +527,6 @@ void PopulateRandomizedFieldMetadata(
}
}
-void EncodeFormMetadataForQuery(const FormStructure& form,
- AutofillRandomizedFormMetadata* metadata) {
- DCHECK(metadata);
- metadata->mutable_id()->set_encoded_bits(
- base::UTF16ToUTF8(form.id_attribute()));
- metadata->mutable_name()->set_encoded_bits(
- base::UTF16ToUTF8(form.name_attribute()));
-}
-
-void EncodeFieldMetadataForQuery(const FormFieldData& field,
- AutofillRandomizedFieldMetadata* metadata) {
- DCHECK(metadata);
- metadata->mutable_id()->set_encoded_bits(
- base::UTF16ToUTF8(field.id_attribute));
- metadata->mutable_name()->set_encoded_bits(
- base::UTF16ToUTF8(field.name_attribute));
- metadata->mutable_type()->set_encoded_bits(field.form_control_type);
- metadata->mutable_label()->set_encoded_bits(base::UTF16ToUTF8(field.label));
- metadata->mutable_aria_label()->set_encoded_bits(
- base::UTF16ToUTF8(field.aria_label));
- metadata->mutable_aria_description()->set_encoded_bits(
- base::UTF16ToUTF8(field.aria_description));
- metadata->mutable_css_class()->set_encoded_bits(
- base::UTF16ToUTF8(field.css_classes));
- metadata->mutable_placeholder()->set_encoded_bits(
- base::UTF16ToUTF8(field.placeholder));
-}
-
// Creates the type relationship rules map. The keys represent the type that has
// rules, and the value represents the list of required types for the given
// key. In order to respect the rule, only one of the required types is needed.
@@ -858,7 +830,7 @@ void FormStructure::ProcessQueryResponse(
bool query_response_overrode_heuristics = false;
std::map<std::pair<FormSignature, FieldSignature>,
- AutofillQueryResponse::FormSuggestion::FieldSuggestion>
+ std::deque<AutofillQueryResponse::FormSuggestion::FieldSuggestion>>
field_types;
for (int form_idx = 0;
form_idx < std::min(response.form_suggestions_size(),
@@ -868,7 +840,7 @@ void FormStructure::ProcessQueryResponse(
for (const auto& field :
response.form_suggestions(form_idx).field_suggestions()) {
FieldSignature field_sig(field.field_signature());
- field_types[std::make_pair(form_sig, field_sig)] = field;
+ field_types[std::make_pair(form_sig, field_sig)].push_back(field);
}
}
@@ -881,7 +853,13 @@ void FormStructure::ProcessQueryResponse(
if (it == field_types.end())
continue;
- const auto& current_field = it->second;
+ // Get the next suggestion for this signature. If this is the last
+ // suggestion, keep it for all subsequent fields with this signature.
+ DCHECK(!it->second.empty());
+ AutofillQueryResponse::FormSuggestion::FieldSuggestion current_field =
+ it->second.front();
+ if (it->second.size() > 1)
+ it->second.pop_front();
ServerFieldType field_type =
static_cast<ServerFieldType>(current_field.primary_type_prediction());
@@ -974,6 +952,29 @@ std::vector<FormDataPredictions> FormStructure::GetFieldTypePredictions(
return forms;
}
+// static
+std::vector<FieldRendererId> FormStructure::FindFieldsEligibleForManualFilling(
+ const std::vector<FormStructure*>& forms) {
+ std::vector<FieldRendererId> fields_eligible_for_manual_filling;
+ for (const auto* form : forms) {
+ for (const auto& field : form->fields_) {
+ FieldTypeGroup field_type_group =
+ autofill::GroupTypeOfServerFieldType(field->server_type());
+ // In order to trigger the payments bottom sheet that assists users to
+ // manually fill the form, credit card form fields are marked eligible for
+ // manual filling. Also, if a field is not classified to a type, we can
+ // assume that the prediction failed and thus mark it eligible for manual
+ // filling. As more form types support manual filling on form interaction,
+ // this list may expand in the future.
+ if (field_type_group == FieldTypeGroup::kCreditCard ||
+ field_type_group == FieldTypeGroup::kNoGroup) {
+ fields_eligible_for_manual_filling.push_back(field->unique_renderer_id);
+ }
+ }
+ }
+ return fields_eligible_for_manual_filling;
+}
+
std::unique_ptr<FormStructure> FormStructure::CreateForPasswordManagerUpload(
FormSignature form_signature,
const std::vector<FieldSignature>& field_signatures) {
@@ -1962,10 +1963,6 @@ void FormStructure::EncodeFormForQuery(
query_form->set_signature(form_signature().value());
queried_form_signatures->push_back(form_signature());
- if (is_rich_query_enabled_) {
- EncodeFormMetadataForQuery(*this, query_form->mutable_metadata());
- }
-
for (const auto& field : fields_) {
if (ShouldSkipField(*field))
continue;
@@ -1973,10 +1970,6 @@ void FormStructure::EncodeFormForQuery(
AutofillPageQueryRequest::Form::Field* added_field =
query_form->add_fields();
added_field->set_signature(field->GetFieldSignature().value());
-
- if (is_rich_query_enabled_) {
- EncodeFieldMetadataForQuery(*field, added_field->mutable_metadata());
- }
}
}
@@ -2425,7 +2418,7 @@ void FormStructure::ExtractParseableFieldLabels() {
}
// Determine the parsable labels and write them back.
- base::Optional<std::vector<std::u16string>> parsable_labels =
+ absl::optional<std::vector<std::u16string>> parsable_labels =
GetParseableLabels(field_labels);
// If not single label was split, the function can return, because the
// |parsable_label_| is assigned to |label| by default.
diff --git a/chromium/components/autofill/core/browser/form_structure.h b/chromium/components/autofill/core/browser/form_structure.h
index 1dd3023b975..ca182fd29f1 100644
--- a/chromium/components/autofill/core/browser/form_structure.h
+++ b/chromium/components/autofill/core/browser/form_structure.h
@@ -16,7 +16,6 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_metrics.h"
@@ -28,6 +27,7 @@
#include "components/autofill/core/common/language_code.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/unique_ids.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -211,6 +211,11 @@ class FormStructure {
// * NAME_LAST_SECOND heuristic predictions are unconditionally used.
void OverrideServerPredictionsWithHeuristics();
+ // Returns the FieldRendererId for fields that are eligible for Manual Filling
+ // on form interaction.
+ static std::vector<FieldRendererId> FindFieldsEligibleForManualFilling(
+ const std::vector<FormStructure*>& forms);
+
const AutofillField* field(size_t index) const;
AutofillField* field(size_t index);
size_t field_count() const;
@@ -295,7 +300,7 @@ class FormStructure {
password_attributes_vote_ = vote;
}
- base::Optional<std::pair<PasswordAttribute, bool>>
+ absl::optional<std::pair<PasswordAttribute, bool>>
get_password_attributes_vote() const {
return password_attributes_vote_;
}
@@ -332,6 +337,13 @@ class FormStructure {
if (field_index < fields_.size() && type > 0 && type < MAX_VALID_FIELD_TYPE)
fields_[field_index]->set_heuristic_type(type);
}
+ // Set the server field type for |fields_[field_index]| to |type| for testing
+ // purposes.
+ void set_server_field_type_for_testing(size_t field_index,
+ ServerFieldType type) {
+ if (field_index < fields_.size() && type > 0 && type < MAX_VALID_FIELD_TYPE)
+ fields_[field_index]->set_server_type(type);
+ }
#endif
void set_password_symbol_vote(int noisified_symbol) {
@@ -367,8 +379,6 @@ class FormStructure {
void set_randomized_encoder(std::unique_ptr<RandomizedEncoder> encoder);
- void set_is_rich_query_enabled(bool v) { is_rich_query_enabled_ = v; }
-
const LanguageCode& current_page_language() const {
return current_page_language_;
}
@@ -618,7 +628,7 @@ class FormStructure {
// The vote about password attributes (e.g. whether the password has a numeric
// character).
- base::Optional<std::pair<PasswordAttribute, bool>> password_attributes_vote_;
+ absl::optional<std::pair<PasswordAttribute, bool>> password_attributes_vote_;
// If |password_attribute_vote_| contains (kHasSpecialSymbol, true), this
// field contains nosified information about a special symbol in a
diff --git a/chromium/components/autofill/core/browser/form_structure_unittest.cc b/chromium/components/autofill/core/browser/form_structure_unittest.cc
index 9fb90540051..1d69fb87738 100644
--- a/chromium/components/autofill/core/browser/form_structure_unittest.cc
+++ b/chromium/components/autofill/core/browser/form_structure_unittest.cc
@@ -129,14 +129,14 @@ class ParameterizedFormStructureTest
TEST_F(FormStructureTestImpl, FieldCount) {
CheckFormStructureTestData({{{.description_for_logging = "FieldCount",
.fields = {{.role = ServerFieldType::USERNAME},
- {.label = "Password",
- .name = "password",
+ {.label = u"Password",
+ .name = u"password",
.form_control_type = "password"},
- {.label = "Submit",
- .name = "",
+ {.label = u"Submit",
+ .name = u"",
.form_control_type = "submit"},
- {.label = "address1",
- .name = "address1",
+ {.label = u"address1",
+ .name = u"address1",
.should_autocomplete = false}}},
{
.determine_heuristic_type = true,
@@ -148,16 +148,17 @@ TEST_F(FormStructureTestImpl, FieldCount) {
TEST_F(FormStructureTestImpl, AutofillCount) {
CheckFormStructureTestData(
{{{.description_for_logging = "AutofillCount",
- .fields =
- {{.role = ServerFieldType::USERNAME},
- {.label = "Password",
- .name = "password",
- .form_control_type = "password"},
- {.role = ServerFieldType::EMAIL_ADDRESS},
- {.role = ServerFieldType::ADDRESS_HOME_CITY},
- {.role = ServerFieldType::ADDRESS_HOME_STATE,
- .form_control_type = "select-one"},
- {.label = "Submit", .name = "", .form_control_type = "submit"}}},
+ .fields = {{.role = ServerFieldType::USERNAME},
+ {.label = u"Password",
+ .name = u"password",
+ .form_control_type = "password"},
+ {.role = ServerFieldType::EMAIL_ADDRESS},
+ {.role = ServerFieldType::ADDRESS_HOME_CITY},
+ {.role = ServerFieldType::ADDRESS_HOME_STATE,
+ .form_control_type = "select-one"},
+ {.label = u"Submit",
+ .name = u"",
+ .form_control_type = "submit"}}},
{
.determine_heuristic_type = true,
.autofill_count = 3,
@@ -167,16 +168,16 @@ TEST_F(FormStructureTestImpl, AutofillCount) {
{{.description_for_logging = "AutofillCountWithNonFillableField",
.fields =
{{.role = ServerFieldType::USERNAME},
- {.label = "Password",
- .name = "password",
+ {.label = u"Password",
+ .name = u"password",
.form_control_type = "password"},
{.role = ServerFieldType::EMAIL_ADDRESS},
{.role = ServerFieldType::ADDRESS_HOME_CITY},
{.role = ServerFieldType::ADDRESS_HOME_STATE,
.form_control_type = "select-one"},
- {.label = "Submit", .name = "", .form_control_type = "submit"},
- {.label = "address1",
- .name = "address1",
+ {.label = u"Submit", .name = u"", .form_control_type = "submit"},
+ {.label = u"address1",
+ .name = u"address1",
.should_autocomplete = false}}},
{
.determine_heuristic_type = true,
@@ -487,8 +488,8 @@ TEST_F(FormStructureTestImpl, ShouldBeParsed_TwoFields_HasAutocomplete) {
TEST_F(FormStructureTestImpl, DetermineHeuristicTypes_AutocompleteFalse) {
CheckFormStructureTestData(
{{{.description_for_logging = "DetermineHeuristicTypes_AutocompleteFalse",
- .fields = {{.label = "Name",
- .name = "name",
+ .fields = {{.label = u"Name",
+ .name = u"name",
.autocomplete_attribute = "false"},
{.role = ServerFieldType::EMAIL_ADDRESS,
.autocomplete_attribute = "false"},
@@ -507,16 +508,17 @@ TEST_F(FormStructureTestImpl, DetermineHeuristicTypes_AutocompleteFalse) {
TEST_F(FormStructureTestImpl, HeuristicsContactInfo) {
CheckFormStructureTestData(
{{{.description_for_logging = "HeuristicsContactInfo",
- .fields =
- {{.role = ServerFieldType::NAME_FIRST},
- {.role = ServerFieldType::NAME_LAST},
- {.role = ServerFieldType::EMAIL_ADDRESS},
- {.role = ServerFieldType::PHONE_HOME_NUMBER},
- {.label = "Ext:", .name = "phoneextension"},
- {.label = "Address", .name = "address"},
- {.role = ServerFieldType::ADDRESS_HOME_CITY},
- {.role = ServerFieldType::ADDRESS_HOME_ZIP},
- {.label = "Submit", .name = "", .form_control_type = "submit"}}},
+ .fields = {{.role = ServerFieldType::NAME_FIRST},
+ {.role = ServerFieldType::NAME_LAST},
+ {.role = ServerFieldType::EMAIL_ADDRESS},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER},
+ {.label = u"Ext:", .name = u"phoneextension"},
+ {.label = u"Address", .name = u"address"},
+ {.role = ServerFieldType::ADDRESS_HOME_CITY},
+ {.role = ServerFieldType::ADDRESS_HOME_ZIP},
+ {.label = u"Submit",
+ .name = u"",
+ .form_control_type = "submit"}}},
{
.determine_heuristic_type = true,
.field_count = 9,
@@ -532,17 +534,17 @@ TEST_F(FormStructureTestImpl, HeuristicsContactInfo) {
TEST_F(FormStructureTestImpl, HeuristicsAutocompleteAttribute) {
CheckFormStructureTestData(
{{{.description_for_logging = "HeuristicsAutocompleteAttribute",
- .fields = {{.label = "",
- .name = "field1",
+ .fields = {{.label = u"",
+ .name = u"field1",
.autocomplete_attribute = "given-name"},
- {.label = "",
- .name = "field2",
+ {.label = u"",
+ .name = u"field2",
.autocomplete_attribute = "family-name"},
- {.label = "",
- .name = "field3",
+ {.label = u"",
+ .name = u"field3",
.autocomplete_attribute = "email"},
- {.label = "",
- .name = "field4",
+ {.label = u"",
+ .name = u"field4",
.autocomplete_attribute = "upi-vpa"}}},
{
.determine_heuristic_type = true,
@@ -819,18 +821,18 @@ TEST_F(FormStructureTestImpl,
TEST_F(FormStructureTestImpl, StripCommonNamePrefix) {
CheckFormStructureTestData(
{{{.description_for_logging = "StripCommonNamePrefix",
- .fields = {{.role = ServerFieldType::NAME_FIRST,
- .name =
- "ctl01$ctl00$ShippingAddressCreditPhone$firstname"},
- {.role = ServerFieldType::NAME_LAST,
- .name = "ctl01$ctl00$ShippingAddressCreditPhone$lastname"},
- {.role = ServerFieldType::EMAIL_ADDRESS,
- .name = "ctl01$ctl00$ShippingAddressCreditPhone$email"},
- {.role = ServerFieldType::PHONE_HOME_NUMBER,
- .name = "ctl01$ctl00$ShippingAddressCreditPhone$phone"},
- {.label = "Submit",
- .name = "ctl01$ctl00$ShippingAddressCreditPhone$submit",
- .form_control_type = "submit"}}},
+ .fields =
+ {{.role = ServerFieldType::NAME_FIRST,
+ .name = u"ctl01$ctl00$ShippingAddressCreditPhone$firstname"},
+ {.role = ServerFieldType::NAME_LAST,
+ .name = u"ctl01$ctl00$ShippingAddressCreditPhone$lastname"},
+ {.role = ServerFieldType::EMAIL_ADDRESS,
+ .name = u"ctl01$ctl00$ShippingAddressCreditPhone$email"},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER,
+ .name = u"ctl01$ctl00$ShippingAddressCreditPhone$phone"},
+ {.label = u"Submit",
+ .name = u"ctl01$ctl00$ShippingAddressCreditPhone$submit",
+ .form_control_type = "submit"}}},
{.determine_heuristic_type = true,
.is_autofillable = true,
.field_count = 5,
@@ -844,9 +846,9 @@ TEST_F(FormStructureTestImpl, StripCommonNamePrefix) {
TEST_F(FormStructureTestImpl, StripCommonNamePrefix_SmallPrefix) {
CheckFormStructureTestData(
{{{.description_for_logging = "StripCommonNamePrefix_SmallPrefix",
- .fields = {{.label = "Address 1", .name = "address1"},
- {.label = "Address 2", .name = "address2"},
- {.label = "Address 3", .name = "address3"}}},
+ .fields = {{.label = u"Address 1", .name = u"address1"},
+ {.label = u"Address 2", .name = u"address2"},
+ {.label = u"Address 3", .name = u"address3"}}},
{.determine_heuristic_type = true,
.is_autofillable = true,
.field_count = 3,
@@ -859,7 +861,7 @@ TEST_F(FormStructureTestImpl, IsCompleteCreditCardForm_Minimal) {
CheckFormStructureTestData(
{{{.description_for_logging = "IsCompleteCreditCardForm_Minimal",
.fields = {{.role = ServerFieldType::CREDIT_CARD_NUMBER},
- {.label = "Expiration", .name = "cc_exp"},
+ {.label = u"Expiration", .name = u"cc_exp"},
{.role = ServerFieldType::ADDRESS_HOME_ZIP}}},
{.determine_heuristic_type = true,
.is_complete_credit_card_form = {true, true}},
@@ -869,13 +871,13 @@ TEST_F(FormStructureTestImpl, IsCompleteCreditCardForm_Minimal) {
TEST_F(FormStructureTestImpl, IsCompleteCreditCardForm_Full) {
CheckFormStructureTestData(
{{{.description_for_logging = "IsCompleteCreditCardForm_Full",
- .fields = {{.label = "Name on Card", .name = "name_on_card"},
+ .fields = {{.label = u"Name on Card", .name = u"name_on_card"},
{.role = ServerFieldType::CREDIT_CARD_NUMBER},
- {.label = "Exp Month", .name = "ccmonth"},
- {.label = "Exp Year", .name = "ccyear"},
- {.label = "Verification", .name = "verification"},
- {.label = "Submit",
- .name = "submit",
+ {.label = u"Exp Month", .name = u"ccmonth"},
+ {.label = u"Exp Year", .name = u"ccyear"},
+ {.label = u"Verification", .name = u"verification"},
+ {.label = u"Submit",
+ .name = u"submit",
.form_control_type = "submit"}}},
{.determine_heuristic_type = true,
.is_complete_credit_card_form = {true, true}},
@@ -896,13 +898,13 @@ TEST_F(FormStructureTestImpl, IsCompleteCreditCardForm_OnlyCCNumber) {
TEST_F(FormStructureTestImpl, IsCompleteCreditCardForm_AddressForm) {
CheckFormStructureTestData(
{{{.description_for_logging = "IsCompleteCreditCardForm_AddressForm",
- .fields = {{.role = ServerFieldType::NAME_FIRST, .name = ""},
- {.role = ServerFieldType::NAME_LAST, .name = ""},
- {.role = ServerFieldType::EMAIL_ADDRESS, .name = ""},
- {.role = ServerFieldType::PHONE_HOME_NUMBER, .name = ""},
- {.label = "Address", .name = ""},
- {.label = "Address", .name = ""},
- {.role = ServerFieldType::ADDRESS_HOME_ZIP, .name = ""}}},
+ .fields = {{.role = ServerFieldType::NAME_FIRST, .name = u""},
+ {.role = ServerFieldType::NAME_LAST, .name = u""},
+ {.role = ServerFieldType::EMAIL_ADDRESS, .name = u""},
+ {.role = ServerFieldType::PHONE_HOME_NUMBER, .name = u""},
+ {.label = u"Address", .name = u""},
+ {.label = u"Address", .name = u""},
+ {.role = ServerFieldType::ADDRESS_HOME_ZIP, .name = u""}}},
{.determine_heuristic_type = true,
.is_complete_credit_card_form = {true, false}},
{}}});
@@ -913,14 +915,14 @@ TEST_F(FormStructureTestImpl, IsCompleteCreditCardForm_AddressForm) {
TEST_F(FormStructureTestImpl, HeuristicsAutocompleteAttributePhoneTypes) {
CheckFormStructureTestData(
{{{.description_for_logging = "HeuristicsAutocompleteAttributePhoneTypes",
- .fields = {{.label = "",
- .name = "field1",
+ .fields = {{.label = u"",
+ .name = u"field1",
.autocomplete_attribute = "tel-local"},
- {.label = "",
- .name = "field2",
+ {.label = u"",
+ .name = u"field2",
.autocomplete_attribute = "tel-local-prefix"},
- {.label = "",
- .name = "field3",
+ {.label = u"",
+ .name = u"field3",
.autocomplete_attribute = "tel-local-suffix"}}},
{.determine_heuristic_type = true,
.is_autofillable = true,
@@ -983,7 +985,7 @@ TEST_F(FormStructureTestImpl,
"UnrecognizedAutocompleteAttribute",
.fields = {{.role = ServerFieldType::NAME_FIRST,
.autocomplete_attribute = "unrecognized"},
- {.label = "Middle Name", .name = "middlename"},
+ {.label = u"Middle Name", .name = u"middlename"},
{.role = ServerFieldType::NAME_LAST},
{.role = ServerFieldType::EMAIL_ADDRESS}},
},
@@ -5005,11 +5007,11 @@ TEST_F(FormStructureTestImpl, EncodeQueryRequest_WithLongLabels) {
form.fields.push_back(field);
// This label will be truncated in the XML request.
- field.label = ASCIIToUTF16(
- "Enter Your Really Really Really (Really!) Long Email Address Which We "
- "Hope To Get In Order To Send You Unwanted Publicity Because That's What "
- "Marketers Do! We Know That Your Email Address Has The Possibility Of "
- "Exceeding A Certain Number Of Characters...");
+ field.label =
+ u"Enter Your Really Really Really (Really!) Long Email Address Which We "
+ u"Hope To Get In Order To Send You Unwanted Publicity Because That's "
+ u"What Marketers Do! We Know That Your Email Address Has The Possibility "
+ u"Of Exceeding A Certain Number Of Characters...";
field.name = u"email";
field.form_control_type = "text";
field.unique_renderer_id = MakeFieldRendererId();
@@ -7684,6 +7686,109 @@ TEST_P(RationalizationFieldTypeRelationshipsTest,
forms[0]->field(3)->Type().GetStorableType());
}
+// When two fields have the same signature and the server response has multiple
+// predictions for that signature, apply the server predictions in the order
+// that they were received.
+TEST_F(FormStructureTestImpl, ParseQueryResponse_RankEqualSignatures) {
+ FormData form_data;
+ FormFieldData field;
+ form_data.url = GURL("http://foo.com");
+ field.form_control_type = "text";
+
+ field.label = u"First Name";
+ field.name = u"name";
+ field.unique_renderer_id = MakeFieldRendererId();
+ form_data.fields.push_back(field);
+
+ field.label = u"Last Name";
+ field.name = u"name";
+ field.unique_renderer_id = MakeFieldRendererId();
+ form_data.fields.push_back(field);
+
+ field.label = u"email";
+ field.name = u"email";
+ field.autocomplete_attribute = "address-level2";
+ field.unique_renderer_id = MakeFieldRendererId();
+ form_data.fields.push_back(field);
+
+ ASSERT_EQ(CalculateFieldSignatureForField(form_data.fields[0]),
+ CalculateFieldSignatureForField(form_data.fields[1]));
+
+ FormStructure form(form_data);
+ form.DetermineHeuristicTypes(nullptr, nullptr);
+
+ // Setup the query response.
+ AutofillQueryResponse response;
+ auto* form_suggestion = response.add_form_suggestions();
+ AddFieldSuggestionToForm(form_suggestion, form_data.fields[0], NAME_FIRST);
+ AddFieldSuggestionToForm(form_suggestion, form_data.fields[1], NAME_LAST);
+ AddFieldSuggestionToForm(form_suggestion, form_data.fields[2], EMAIL_ADDRESS);
+
+ std::string response_string = SerializeAndEncode(response);
+
+ // Parse the response and update the field type predictions.
+ std::vector<FormStructure*> forms{&form};
+ FormStructure::ParseApiQueryResponse(
+ response_string, forms, test::GetEncodedSignatures(forms), nullptr);
+ ASSERT_EQ(form.field_count(), 3U);
+
+ EXPECT_EQ(NAME_FIRST, form.field(0)->server_type());
+ EXPECT_EQ(NAME_LAST, form.field(1)->server_type());
+ EXPECT_EQ(EMAIL_ADDRESS, form.field(2)->server_type());
+}
+
+// When two fields have the same signature and the server response has one
+// prediction, apply the prediction to every field with that signature.
+TEST_F(FormStructureTestImpl,
+ ParseQueryResponse_EqualSignaturesFewerPredictions) {
+ FormData form_data;
+ FormFieldData field;
+ form_data.url = GURL("http://foo.com");
+ field.form_control_type = "text";
+
+ field.label = u"First Name";
+ field.name = u"name";
+ field.unique_renderer_id = MakeFieldRendererId();
+ form_data.fields.push_back(field);
+
+ field.label = u"Last Name";
+ field.name = u"name";
+ field.unique_renderer_id = MakeFieldRendererId();
+ form_data.fields.push_back(field);
+
+ field.label = u"email";
+ field.name = u"email";
+ field.autocomplete_attribute = "address-level2";
+ field.unique_renderer_id = MakeFieldRendererId();
+ form_data.fields.push_back(field);
+
+ ASSERT_EQ(CalculateFieldSignatureForField(form_data.fields[0]),
+ CalculateFieldSignatureForField(form_data.fields[1]));
+
+ FormStructure form(form_data);
+ form.DetermineHeuristicTypes(nullptr, nullptr);
+
+ // Setup the query response.
+ AutofillQueryResponse response;
+ auto* form_suggestion = response.add_form_suggestions();
+ AddFieldSuggestionToForm(form_suggestion, form_data.fields[0], NAME_FIRST);
+ AddFieldSuggestionToForm(form_suggestion, form_data.fields[2], EMAIL_ADDRESS);
+
+ std::string response_string = SerializeAndEncode(response);
+
+ // Parse the response and update the field type predictions.
+ std::vector<FormStructure*> forms{&form};
+ FormStructure::ParseApiQueryResponse(
+ response_string, forms, test::GetEncodedSignatures(forms), nullptr);
+ ASSERT_EQ(form.field_count(), 3U);
+
+ EXPECT_EQ(NAME_FIRST, form.field(0)->server_type());
+ // This field gets the same signature as the previous one, because they have
+ // the same signature.
+ EXPECT_EQ(NAME_FIRST, form.field(1)->server_type());
+ EXPECT_EQ(EMAIL_ADDRESS, form.field(2)->server_type());
+}
+
TEST_F(FormStructureTestImpl, AllowBigForms) {
FormData form;
form.url = GURL("http://foo.com");
@@ -8285,4 +8390,48 @@ TEST_F(FormStructureTestImpl, IgnoreAribtraryAutocompleteSectionName) {
EXPECT_EQ("blue-shipping-default", form_structure.field(1)->section);
}
+TEST_F(FormStructureTestImpl, FindFieldsEligibleForManualFilling) {
+ FormData form;
+ form.url = GURL("http://foo.com");
+ FormFieldData field;
+ field.form_control_type = "text";
+ field.max_length = 10000;
+
+ FieldRendererId full_name_renderer_id = MakeFieldRendererId();
+ field.label = u"Full Name";
+ field.name = u"fullName";
+ field.unique_renderer_id = full_name_renderer_id;
+ form.fields.push_back(field);
+
+ FieldRendererId country_renderer_id = MakeFieldRendererId();
+ field.label = u"Country";
+ field.name = u"country";
+ field.unique_renderer_id = country_renderer_id;
+ form.fields.push_back(field);
+
+ FieldRendererId unknown_renderer_id = MakeFieldRendererId();
+ field.label = u"Unknown";
+ field.name = u"unknown";
+ field.unique_renderer_id = unknown_renderer_id;
+ form.fields.push_back(field);
+
+ FormStructure form_structure(form);
+
+ form_structure.set_server_field_type_for_testing(0, CREDIT_CARD_NAME_FULL);
+ form_structure.set_server_field_type_for_testing(1, ADDRESS_HOME_COUNTRY);
+ form_structure.set_server_field_type_for_testing(2, UNKNOWN_TYPE);
+
+ std::vector<FormStructure*> forms;
+ forms.push_back(&form_structure);
+
+ form_structure.identify_sections_for_testing();
+ std::vector<FieldRendererId> expected_result;
+ // Only credit card related and unknown fields are elible for manual filling.
+ expected_result.push_back(full_name_renderer_id);
+ expected_result.push_back(unknown_renderer_id);
+
+ EXPECT_EQ(expected_result,
+ FormStructure::FindFieldsEligibleForManualFilling(forms));
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/geo/alternative_state_name_map.cc b/chromium/components/autofill/core/browser/geo/alternative_state_name_map.cc
index a6c9e3ad499..5b5add9d56b 100644
--- a/chromium/components/autofill/core/browser/geo/alternative_state_name_map.cc
+++ b/chromium/components/autofill/core/browser/geo/alternative_state_name_map.cc
@@ -16,7 +16,7 @@ namespace {
constexpr int kMaxMapSize = 500;
// The characters to be removed from the state strings before the comparison.
-constexpr char kCharsToStrip[] = ".- ";
+constexpr char16_t kCharsToStrip[] = u".- ";
} // namespace
@@ -31,13 +31,12 @@ AlternativeStateNameMap* AlternativeStateNameMap::GetInstance() {
AlternativeStateNameMap::StateName AlternativeStateNameMap::NormalizeStateName(
const StateName& text) {
std::u16string normalized_text;
- base::RemoveChars(text.value(), base::ASCIIToUTF16(kCharsToStrip),
- &normalized_text);
+ base::RemoveChars(text.value(), kCharsToStrip, &normalized_text);
return StateName(normalized_text);
}
// static
-base::Optional<AlternativeStateNameMap::CanonicalStateName>
+absl::optional<AlternativeStateNameMap::CanonicalStateName>
AlternativeStateNameMap::GetCanonicalStateName(
const std::string& country_code,
const std::u16string& state_name) {
@@ -48,7 +47,7 @@ AlternativeStateNameMap::GetCanonicalStateName(
AlternativeStateNameMap::AlternativeStateNameMap() = default;
-base::Optional<AlternativeStateNameMap::CanonicalStateName>
+absl::optional<AlternativeStateNameMap::CanonicalStateName>
AlternativeStateNameMap::GetCanonicalStateName(
const CountryCode& country_code,
const StateName& state_name,
@@ -78,17 +77,17 @@ AlternativeStateNameMap::GetCanonicalStateName(
if (it != localized_state_names_reverse_lookup_map_.end())
return it->second;
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<StateEntry> AlternativeStateNameMap::GetEntry(
+absl::optional<StateEntry> AlternativeStateNameMap::GetEntry(
const CountryCode& country_code,
const StateName& state_string_from_profile) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
StateName normalized_state_string_from_profile =
NormalizeStateName(state_string_from_profile);
- base::Optional<CanonicalStateName> canonical_state_name =
+ absl::optional<CanonicalStateName> canonical_state_name =
GetCanonicalStateName(country_code, normalized_state_string_from_profile,
/*is_state_name_normalized=*/true);
@@ -99,7 +98,7 @@ base::Optional<StateEntry> AlternativeStateNameMap::GetEntry(
return it->second;
}
- return base::nullopt;
+ return absl::nullopt;
}
void AlternativeStateNameMap::AddEntry(
diff --git a/chromium/components/autofill/core/browser/geo/alternative_state_name_map.h b/chromium/components/autofill/core/browser/geo/alternative_state_name_map.h
index 0b3687e2aee..002d0a54f72 100644
--- a/chromium/components/autofill/core/browser/geo/alternative_state_name_map.h
+++ b/chromium/components/autofill/core/browser/geo/alternative_state_name_map.h
@@ -7,15 +7,15 @@
#include <string>
-#include "components/autofill/core/browser/proto/states.pb.h"
-
#include "base/i18n/case_conversion.h"
#include "base/no_destructor.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/types/strong_alias.h"
+#include "components/autofill/core/browser/proto/states.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
+
// AlternativeStateNameMap encapsulates mappings from state names in the
// profiles to their localized and the abbreviated names.
//
@@ -88,7 +88,7 @@ class AlternativeStateNameMap {
// Calls |GetCanonicalStateName()| member method of AlternativeStateNameMap
// and returns the canonical state name corresponding to |country_code| and
// |state_name| if present.
- static base::Optional<AlternativeStateNameMap::CanonicalStateName>
+ static absl::optional<AlternativeStateNameMap::CanonicalStateName>
GetCanonicalStateName(const std::string& country_code,
const std::u16string& state_name);
@@ -101,15 +101,15 @@ class AlternativeStateNameMap {
// (|country_code|, |state_name|).
// |is_state_name_normalized| denotes whether the |state_name| has been
// normalized or not.
- base::Optional<CanonicalStateName> GetCanonicalStateName(
+ absl::optional<CanonicalStateName> GetCanonicalStateName(
const CountryCode& country_code,
const StateName& state_name,
bool is_state_name_normalized = false) const;
// Returns the value present in |localized_state_names_map_| corresponding
// to (|country_code|, |state_string_from_profile|). In case, the entry does
- // not exist in the map, base::nullopt is returned.
- base::Optional<StateEntry> GetEntry(
+ // not exist in the map, absl::nullopt is returned.
+ absl::optional<StateEntry> GetEntry(
const CountryCode& country_code,
const StateName& state_string_from_profile) const;
diff --git a/chromium/components/autofill/core/browser/geo/alternative_state_name_map_test_utils.h b/chromium/components/autofill/core/browser/geo/alternative_state_name_map_test_utils.h
index 29cfa66220a..131a61869fa 100644
--- a/chromium/components/autofill/core/browser/geo/alternative_state_name_map_test_utils.h
+++ b/chromium/components/autofill/core/browser/geo/alternative_state_name_map_test_utils.h
@@ -5,9 +5,9 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_GEO_ALTERNATIVE_STATE_NAME_MAP_TEST_UTILS_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_GEO_ALTERNATIVE_STATE_NAME_MAP_TEST_UTILS_H_
-#include "base/optional.h"
#include "components/autofill/core/browser/geo/alternative_state_name_map.h"
#include "components/autofill/core/browser/proto/states.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
diff --git a/chromium/components/autofill/core/browser/geo/alternative_state_name_map_unittest.cc b/chromium/components/autofill/core/browser/geo/alternative_state_name_map_unittest.cc
index 15cea81e118..b80cae2ae3c 100644
--- a/chromium/components/autofill/core/browser/geo/alternative_state_name_map_unittest.cc
+++ b/chromium/components/autofill/core/browser/geo/alternative_state_name_map_unittest.cc
@@ -31,15 +31,15 @@ TEST(AlternativeStateNameMapTest, StateCanonicalString) {
SCOPED_TRACE(valid_match);
EXPECT_NE(AlternativeStateNameMap::GetCanonicalStateName(
"DE", base::ASCIIToUTF16(valid_match)),
- base::nullopt);
+ absl::nullopt);
}
EXPECT_EQ(AlternativeStateNameMap::GetCanonicalStateName("US", u"Bavaria"),
- base::nullopt);
+ absl::nullopt);
EXPECT_EQ(AlternativeStateNameMap::GetCanonicalStateName("DE", u""),
- base::nullopt);
+ absl::nullopt);
EXPECT_EQ(AlternativeStateNameMap::GetCanonicalStateName("", u""),
- base::nullopt);
+ absl::nullopt);
}
// Tests that the separate entries are created in the map for the different
@@ -49,9 +49,9 @@ TEST(AlternativeStateNameMapTest, SeparateEntryForDifferentCounties) {
test::PopulateAlternativeStateNameMapForTesting("DE");
test::PopulateAlternativeStateNameMapForTesting("US");
EXPECT_NE(AlternativeStateNameMap::GetCanonicalStateName("DE", u"Bavaria"),
- base::nullopt);
+ absl::nullopt);
EXPECT_NE(AlternativeStateNameMap::GetCanonicalStateName("US", u"Bavaria"),
- base::nullopt);
+ absl::nullopt);
}
// Tests that |AlternativeStateNameMap::NormalizeStateName()| removes "-", " "
@@ -84,11 +84,11 @@ TEST(AlternativeStateNameMapTest, GetEntry) {
EXPECT_EQ(alternative_state_name_map->GetEntry(
AlternativeStateNameMap::CountryCode("DE"),
AlternativeStateNameMap::StateName(u"Random")),
- base::nullopt);
+ absl::nullopt);
auto entry = alternative_state_name_map->GetEntry(
AlternativeStateNameMap::CountryCode("DE"),
AlternativeStateNameMap::StateName(u"Bavaria"));
- EXPECT_NE(entry, base::nullopt);
+ EXPECT_NE(entry, absl::nullopt);
ASSERT_TRUE(entry->has_canonical_name());
EXPECT_EQ(entry->canonical_name(), "Bavaria");
EXPECT_THAT(entry->abbreviations(),
diff --git a/chromium/components/autofill/core/browser/geo/alternative_state_name_map_updater.h b/chromium/components/autofill/core/browser/geo/alternative_state_name_map_updater.h
index 9e1868dd570..3b16be24793 100644
--- a/chromium/components/autofill/core/browser/geo/alternative_state_name_map_updater.h
+++ b/chromium/components/autofill/core/browser/geo/alternative_state_name_map_updater.h
@@ -5,8 +5,11 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_GEO_ALTERNATIVE_STATE_NAME_MAP_UPDATER_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_GEO_ALTERNATIVE_STATE_NAME_MAP_UPDATER_H_
+#include <map>
#include <memory>
+#include <set>
#include <string>
+#include <utility>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/components/autofill/core/browser/geo/alternative_state_name_map_updater_unittest.cc b/chromium/components/autofill/core/browser/geo/alternative_state_name_map_updater_unittest.cc
index 3a520a2f1e5..84f56f46a48 100644
--- a/chromium/components/autofill/core/browser/geo/alternative_state_name_map_updater_unittest.cc
+++ b/chromium/components/autofill/core/browser/geo/alternative_state_name_map_updater_unittest.cc
@@ -7,7 +7,6 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
@@ -22,6 +21,7 @@
#include "components/prefs/testing_pref_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using base::ASCIIToUTF16;
using base::UTF8ToUTF16;
@@ -66,6 +66,7 @@ class AlternativeStateNameMapUpdaterTest : public ::testing::Test {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
alternative_state_name_map_updater_ =
std::make_unique<AlternativeStateNameMapUpdater>(
@@ -114,7 +115,7 @@ TEST_F(AlternativeStateNameMapUpdaterTest, EntryAddedToStateMap) {
for (size_t i = 0; i < test_strings.size(); i++) {
SCOPED_TRACE(test_strings[i]);
EXPECT_EQ(AlternativeStateNameMap::GetCanonicalStateName(
- "DE", test_strings[i].value()) != base::nullopt,
+ "DE", test_strings[i].value()) != absl::nullopt,
state_data_present[i]);
}
}
@@ -137,7 +138,7 @@ TEST_F(AlternativeStateNameMapUpdaterTest, TestLoadStatesData) {
run_loop.Run();
EXPECT_NE(AlternativeStateNameMap::GetCanonicalStateName("DE", u"Bavaria"),
- base::nullopt);
+ absl::nullopt);
}
// Tests that there is no insertion in the AlternativeStateNameMap when a
@@ -186,22 +187,22 @@ TEST_F(AlternativeStateNameMapUpdaterTest, TestLoadStatesDataUTF8) {
run_loop.QuitClosure());
run_loop.Run();
- base::Optional<StateEntry> entry1 =
+ absl::optional<StateEntry> entry1 =
AlternativeStateNameMap::GetInstance()->GetEntry(
AlternativeStateNameMap::CountryCode("ES"),
AlternativeStateNameMap::StateName(u"Paraná"));
- EXPECT_NE(entry1, base::nullopt);
+ EXPECT_NE(entry1, absl::nullopt);
EXPECT_EQ(entry1->canonical_name(), "Paraná");
EXPECT_THAT(entry1->abbreviations(),
testing::UnorderedElementsAreArray({"PR"}));
EXPECT_THAT(entry1->alternative_names(), testing::UnorderedElementsAreArray(
{"Parana", "State of Parana"}));
- base::Optional<StateEntry> entry2 =
+ absl::optional<StateEntry> entry2 =
AlternativeStateNameMap::GetInstance()->GetEntry(
AlternativeStateNameMap::CountryCode("ES"),
AlternativeStateNameMap::StateName(u"Parana"));
- EXPECT_NE(entry2, base::nullopt);
+ EXPECT_NE(entry2, absl::nullopt);
EXPECT_EQ(entry2->canonical_name(), "Paraná");
EXPECT_THAT(entry2->abbreviations(),
testing::UnorderedElementsAreArray({"PR"}));
@@ -238,22 +239,22 @@ TEST_F(AlternativeStateNameMapUpdaterTest,
run_loop.QuitClosure());
run_loop.Run();
- base::Optional<StateEntry> entry1 =
+ absl::optional<StateEntry> entry1 =
AlternativeStateNameMap::GetInstance()->GetEntry(
AlternativeStateNameMap::CountryCode("ES"),
AlternativeStateNameMap::StateName(u"Paraná"));
- EXPECT_NE(entry1, base::nullopt);
+ EXPECT_NE(entry1, absl::nullopt);
EXPECT_EQ(entry1->canonical_name(), "Paraná");
EXPECT_THAT(entry1->abbreviations(),
testing::UnorderedElementsAreArray({"PR"}));
EXPECT_THAT(entry1->alternative_names(), testing::UnorderedElementsAreArray(
{"Parana", "State of Parana"}));
- base::Optional<StateEntry> entry2 =
+ absl::optional<StateEntry> entry2 =
AlternativeStateNameMap::GetInstance()->GetEntry(
AlternativeStateNameMap::CountryCode("DE"),
AlternativeStateNameMap::StateName(u"Bavaria"));
- EXPECT_NE(entry2, base::nullopt);
+ EXPECT_NE(entry2, absl::nullopt);
EXPECT_EQ(entry2->canonical_name(), "Bavaria");
EXPECT_THAT(entry2->abbreviations(),
testing::UnorderedElementsAreArray({"BY"}));
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 5b5148fb6fc..9139a8e9943 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
@@ -15,9 +15,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libphonenumber/phonenumber_api.h"
-using base::ASCIIToUTF16;
-using base::UTF8ToUTF16;
-
namespace autofill {
using i18n::ConstructPhoneNumber;
@@ -26,20 +23,15 @@ using i18n::ParsePhoneNumber;
using i18n::PhoneNumbersMatch;
TEST(PhoneNumberI18NTest, NormalizePhoneNumber) {
- // "Large" digits.
- std::u16string phone1(
- UTF8ToUTF16("\xEF\xBC\x91\xEF\xBC\x96\xEF\xBC\x95\xEF\xBC\x90"
- "\xEF\xBC\x97\xEF\xBC\x94\xEF\xBC\x99\xEF\xBC\x98"
- "\xEF\xBC\x93\xEF\xBC\x92\xEF\xBC\x93"));
+ // "Large" digits; these are not ASCII.
+ std::u16string phone1(u"165ï¼ï¼—498323");
EXPECT_EQ(NormalizePhoneNumber(phone1, "US"), u"16507498323");
// Devanagari script digits.
- std::u16string phone2(
- UTF8ToUTF16("\xD9\xA1\xD9\xA6\xD9\xA5\xD9\xA0\xD9\xA8\xD9\xA3"
- "\xD9\xA2\xD9\xA3\xD9\xA7\xD9\xA4\xD9\xA9"));
+ std::u16string phone2(u"١٦٥٠٨٣٢٣٧٤٩");
EXPECT_EQ(NormalizePhoneNumber(phone2, "US"), u"16508323749");
- std::u16string phone3(UTF8ToUTF16("16503334\xef\xbc\x92\x35\xd9\xa5"));
+ std::u16string phone3(u"16503334ï¼’5Ù¥");
EXPECT_EQ(NormalizePhoneNumber(phone3, "US"), u"16503334255");
std::u16string phone4(u"+1(650)2346789");
@@ -53,20 +45,20 @@ struct ParseNumberTestCase {
// Expected parsing result.
bool isPossibleNumber;
// Inputs.
- std::string input;
+ std::u16string input;
std::string assumed_region;
// Further expectations.
- std::string number;
- std::string city_code;
- std::string country_code;
+ std::u16string number;
+ std::u16string city_code;
+ std::u16string country_code;
std::string deduced_region;
};
namespace {
// Returns a string which is too long to be considered a phone number.
-std::string GenerateTooLongString() {
- return std::string(i18n::kMaxPhoneNumberSize + 1, '7');
+std::u16string GenerateTooLongString() {
+ return std::u16string(i18n::kMaxPhoneNumberSize + 1, u'7');
}
} // namespace
@@ -75,19 +67,18 @@ class ParseNumberTest : public testing::TestWithParam<ParseNumberTestCase> {};
TEST_P(ParseNumberTest, ParsePhoneNumber) {
auto test_case = GetParam();
- SCOPED_TRACE("Testing phone number " + test_case.input);
+ SCOPED_TRACE(test_case.input.c_str());
std::u16string country_code, city_code, number;
std::string deduced_region;
::i18n::phonenumbers::PhoneNumber unused_i18n_number;
- EXPECT_EQ(
- test_case.isPossibleNumber,
- ParsePhoneNumber(UTF8ToUTF16(test_case.input), test_case.assumed_region,
- &country_code, &city_code, &number, &deduced_region,
- &unused_i18n_number));
- EXPECT_EQ(ASCIIToUTF16(test_case.number), number);
- EXPECT_EQ(ASCIIToUTF16(test_case.city_code), city_code);
- EXPECT_EQ(ASCIIToUTF16(test_case.country_code), country_code);
+ EXPECT_EQ(test_case.isPossibleNumber,
+ ParsePhoneNumber(test_case.input, test_case.assumed_region,
+ &country_code, &city_code, &number,
+ &deduced_region, &unused_i18n_number));
+ EXPECT_EQ(test_case.number, number);
+ EXPECT_EQ(test_case.city_code, city_code);
+ EXPECT_EQ(test_case.country_code, country_code);
EXPECT_EQ(test_case.deduced_region, deduced_region);
}
@@ -96,99 +87,93 @@ INSTANTIATE_TEST_SUITE_P(
ParseNumberTest,
testing::Values(
// Test for empty string. Should give back empty strings.
- ParseNumberTestCase{false, "", "US"},
+ ParseNumberTestCase{false, u"", "US"},
// Test for string with less than 7 digits. Should give back empty
// strings.
- ParseNumberTestCase{false, "1234", "US"},
+ ParseNumberTestCase{false, u"1234", "US"},
// Too long strings should not be parsed.
ParseNumberTestCase{false, GenerateTooLongString(), "US"},
// Test for string with exactly 7 digits. It is too short.
// Should fail parsing in US.
- ParseNumberTestCase{false, "17134567", "US"},
+ ParseNumberTestCase{false, u"17134567", "US"},
// Does not have area code, but still a possible number with
// unknown("ZZ") deduced region.
- ParseNumberTestCase{true, "7134567", "US", "7134567", "", "", "ZZ"},
+ ParseNumberTestCase{true, u"7134567", "US", u"7134567", u"", u"", "ZZ"},
// Valid Canadian toll-free number.
- ParseNumberTestCase{true, "3101234", "CA", "3101234", "", "", "ZZ"},
+ ParseNumberTestCase{true, u"3101234", "CA", u"3101234", u"", u"", "ZZ"},
// Test for string with greater than 7 digits but less than 10 digits.
// Should fail parsing in US.
- ParseNumberTestCase{false, "123456789", "US"},
+ ParseNumberTestCase{false, u"123456789", "US"},
// Test for string with greater than 7 digits but less than 10 digits
// and
// separators.
// Should fail parsing in US.
- ParseNumberTestCase{false, "12.345-6789", "US"},
+ ParseNumberTestCase{false, u"12.345-6789", "US"},
// Non-printable ASCII.
- ParseNumberTestCase{false, "123\x11", "US"},
- ParseNumberTestCase{false,
- "123\x7F"
- "567",
- "US"},
+ ParseNumberTestCase{false, u"123", "US"},
+ ParseNumberTestCase{false, u"123\u007f567", "US"},
// Unicode noncharacters.
- ParseNumberTestCase{false,
- "1\xEF\xB7\xAF"
- "23",
- "US"},
- // Invalid UTF8.
- ParseNumberTestCase{false, "1\xC0", "US"},
+ ParseNumberTestCase{false, u"1\ufdef23", "US"},
+ // Invalid UTF16.
+ ParseNumberTestCase{false, u"1\xdfff", "US"},
// Test for string with exactly 10 digits.
// Should give back phone number and city code.
// This one has an incorrect area code but could still be a possible
// number with unknown("ZZ") deducted region.
- ParseNumberTestCase{true, "1234567890", "US", "1234567890", "", "",
+ ParseNumberTestCase{true, u"1234567890", "US", u"1234567890", u"", u"",
"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").
- ParseNumberTestCase{true, "6501567890", "US", "1567890", "650", "",
+ ParseNumberTestCase{true, u"6501567890", "US", u"1567890", u"650", u"",
"ZZ"},
- ParseNumberTestCase{true, "6504567890", "US", "4567890", "650", "",
+ ParseNumberTestCase{true, u"6504567890", "US", u"4567890", u"650", u"",
"US"},
// Test for string with exactly 10 digits and separators.
// Should give back phone number and city code.
- ParseNumberTestCase{true, "(650) 456-7890", "US", "4567890", "650", "",
- "US"},
+ ParseNumberTestCase{true, u"(650) 456-7890", "US", u"4567890", u"650",
+ u"", "US"},
// Tests for string with over 10 digits.
// 01 is incorrect prefix in the USA, we interpret 011 as prefix, and
// rest is parsed as a Singapore number(country code "SG").
- ParseNumberTestCase{true, "0116504567890", "US", "04567890", "", "65",
- "SG"},
+ ParseNumberTestCase{true, u"0116504567890", "US", u"04567890", u"",
+ u"65", "SG"},
// 011 is a correct "dial out" prefix in the USA - the parsing should
// succeed.
- ParseNumberTestCase{true, "01116504567890", "US", "4567890", "650", "1",
- "US"},
+ ParseNumberTestCase{true, u"01116504567890", "US", u"4567890", u"650",
+ u"1", "US"},
// 011 is a correct "dial out" prefix in the USA but the rest of the
// number
// can't parse as a US number.
- ParseNumberTestCase{true, "01178124567890", "US", "4567890", "812", "7",
- "RU"},
+ ParseNumberTestCase{true, u"01178124567890", "US", u"4567890", u"812",
+ u"7", "RU"},
// Test for string with over 10 digits with separator characters.
// Should give back phone number, city code, and country code. "011" is
// US "dial out" code, which is discarded.
- ParseNumberTestCase{true, "(0111) 650-456.7890", "US", "4567890", "650",
- "1", "US"},
+ ParseNumberTestCase{true, u"(0111) 650-456.7890", "US", u"4567890",
+ u"650", u"1", "US"},
// Now try phone from Czech republic - it has 00 dial out code, 420
// country
// code and variable length area codes.
- ParseNumberTestCase{true, "+420 27-89.10.112", "US", "910112", "278",
- "420", "CZ"},
- ParseNumberTestCase{false, "27-89.10.112", "US"},
- ParseNumberTestCase{true, "27-89.10.112", "CZ", "910112", "278", "",
+ ParseNumberTestCase{true, u"+420 27-89.10.112", "US", u"910112", u"278",
+ u"420", "CZ"},
+ ParseNumberTestCase{false, u"27-89.10.112", "US"},
+ ParseNumberTestCase{true, u"27-89.10.112", "CZ", u"910112", u"278", u"",
"CZ"},
- ParseNumberTestCase{false, "420 57-89.10.112", "US"},
- ParseNumberTestCase{true, "420 57-89.10.112", "CZ", "910112", "578",
- "420", "CZ"},
+ ParseNumberTestCase{false, u"420 57-89.10.112", "US"},
+ ParseNumberTestCase{true, u"420 57-89.10.112", "CZ", u"910112", u"578",
+ u"420", "CZ"},
// Parses vanity numbers.
- ParseNumberTestCase{true, "1-650-FLOWERS", "US", "3569377", "650", "1",
- "US"},
+ ParseNumberTestCase{true, u"1-650-FLOWERS", "US", u"3569377", u"650",
+ u"1", "US"},
// 800 is not an area code, but the destination code. In our library
// these
// codes should be treated the same as area codes.
- ParseNumberTestCase{true, "1-800-FLOWERS", "US", "3569377", "800", "1",
- "US"},
+ ParseNumberTestCase{true, u"1-800-FLOWERS", "US", u"3569377", u"800",
+ u"1", "US"},
// Don't add a country code where there was none.
- ParseNumberTestCase{true, "(08) 450 777 7777", "DE", "7777777", "8450",
- "", "DE"}));
+ ParseNumberTestCase{true, u"(08) 450 777 7777", "DE", u"7777777",
+ u"8450", u"", "DE"}));
TEST(PhoneNumberI18NTest, ConstructPhoneNumber) {
std::u16string number;
@@ -316,18 +301,18 @@ TEST(PhoneNumberUtilTest, FormatPhoneForDisplay) {
// Test for the GetFormattedPhoneNumberForDisplay method.
struct PhoneNumberFormatCase {
- PhoneNumberFormatCase(const char* phone,
- const char* country,
- const char* expected_format,
+ PhoneNumberFormatCase(const char16_t* phone,
+ const char16_t* country,
+ const char16_t* expected_format,
const char* locale = "")
: phone(phone),
country(country),
expected_format(expected_format),
locale(locale) {}
- const char* phone;
- const char* country;
- const char* expected_format;
+ const char16_t* phone;
+ const char16_t* country;
+ const char16_t* expected_format;
const char* locale;
};
@@ -337,13 +322,10 @@ class GetFormattedPhoneNumberForDisplayTest
TEST_P(GetFormattedPhoneNumberForDisplayTest,
GetFormattedPhoneNumberForDisplay) {
AutofillProfile profile;
- profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
- base::UTF8ToUTF16(GetParam().phone));
- profile.SetRawInfo(ADDRESS_HOME_COUNTRY,
- base::UTF8ToUTF16(GetParam().country));
- EXPECT_EQ(GetParam().expected_format,
- base::UTF16ToUTF8(i18n::GetFormattedPhoneNumberForDisplay(
- profile, GetParam().locale)));
+ profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, GetParam().phone);
+ profile.SetRawInfo(ADDRESS_HOME_COUNTRY, GetParam().country);
+ EXPECT_EQ(GetParam().expected_format, i18n::GetFormattedPhoneNumberForDisplay(
+ profile, GetParam().locale));
}
INSTANTIATE_TEST_SUITE_P(
@@ -354,104 +336,104 @@ INSTANTIATE_TEST_SUITE_P(
// US phone in US.
//////////////////////////
// Formatted phone numbers.
- PhoneNumberFormatCase("+1 415-555-5555", "US", "+1 415-555-5555"),
- PhoneNumberFormatCase("1 415-555-5555", "US", "+1 415-555-5555"),
- PhoneNumberFormatCase("415-555-5555", "US", "+1 415-555-5555"),
+ PhoneNumberFormatCase(u"+1 415-555-5555", u"US", u"+1 415-555-5555"),
+ PhoneNumberFormatCase(u"1 415-555-5555", u"US", u"+1 415-555-5555"),
+ PhoneNumberFormatCase(u"415-555-5555", u"US", u"+1 415-555-5555"),
// Raw phone numbers.
- PhoneNumberFormatCase("+14155555555", "US", "+1 415-555-5555"),
- PhoneNumberFormatCase("14155555555", "US", "+1 415-555-5555"),
- PhoneNumberFormatCase("4155555555", "US", "+1 415-555-5555"),
+ PhoneNumberFormatCase(u"+14155555555", u"US", u"+1 415-555-5555"),
+ PhoneNumberFormatCase(u"14155555555", u"US", u"+1 415-555-5555"),
+ PhoneNumberFormatCase(u"4155555555", u"US", u"+1 415-555-5555"),
//////////////////////////
// US phone in CA.
//////////////////////////
// Formatted phone numbers.
- PhoneNumberFormatCase("+1 415-555-5555", "CA", "+1 415-555-5555"),
- PhoneNumberFormatCase("1 415-555-5555", "CA", "+1 415-555-5555"),
- PhoneNumberFormatCase("415-555-5555", "CA", "+1 415-555-5555"),
+ PhoneNumberFormatCase(u"+1 415-555-5555", u"CA", u"+1 415-555-5555"),
+ PhoneNumberFormatCase(u"1 415-555-5555", u"CA", u"+1 415-555-5555"),
+ PhoneNumberFormatCase(u"415-555-5555", u"CA", u"+1 415-555-5555"),
// Raw phone numbers.
- PhoneNumberFormatCase("+14155555555", "CA", "+1 415-555-5555"),
- PhoneNumberFormatCase("14155555555", "CA", "+1 415-555-5555"),
- PhoneNumberFormatCase("4155555555", "CA", "+1 415-555-5555"),
+ PhoneNumberFormatCase(u"+14155555555", u"CA", u"+1 415-555-5555"),
+ PhoneNumberFormatCase(u"14155555555", u"CA", u"+1 415-555-5555"),
+ PhoneNumberFormatCase(u"4155555555", u"CA", u"+1 415-555-5555"),
//////////////////////////
// US phone in AU.
//////////////////////////
// A US phone with the country code is correctly formatted as an US
// number.
- PhoneNumberFormatCase("+1 415-555-5555", "AU", "+1 415-555-5555"),
- PhoneNumberFormatCase("1 415-555-5555", "AU", "+1 415-555-5555"),
+ PhoneNumberFormatCase(u"+1 415-555-5555", u"AU", u"+1 415-555-5555"),
+ PhoneNumberFormatCase(u"1 415-555-5555", u"AU", u"+1 415-555-5555"),
// Without a country code, the phone is formatted for the profile's
// country, if it's valid.
- PhoneNumberFormatCase("2 9374 4000", "AU", "+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"2 9374 4000", u"AU", u"+61 2 9374 4000"),
// Without a country code, formatting returns the number as entered by
// user, if it's invalid.
- PhoneNumberFormatCase("415-555-5555", "AU", "4155555555"),
+ PhoneNumberFormatCase(u"415-555-5555", u"AU", u"4155555555"),
//////////////////////////
// US phone in MX.
//////////////////////////
// A US phone with the country code is correctly formatted as an US
// number.
- PhoneNumberFormatCase("+1 415-555-5555", "MX", "+1 415-555-5555"),
+ PhoneNumberFormatCase(u"+1 415-555-5555", u"MX", u"+1 415-555-5555"),
// "+52 415 555 5555" is a valid number for Mexico,
- PhoneNumberFormatCase("1 415-555-5555", "MX", "+52 415 555 5555"),
+ PhoneNumberFormatCase(u"1 415-555-5555", u"MX", u"+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"),
+ PhoneNumberFormatCase(u"415-555-5555", u"MX", u"+52 415 555 5555"),
//////////////////////////
// AU phone in AU.
//////////////////////////
// Formatted phone numbers.
- PhoneNumberFormatCase("+61 2 9374 4000", "AU", "+61 2 9374 4000"),
- PhoneNumberFormatCase("61 2 9374 4000", "AU", "+61 2 9374 4000"),
- PhoneNumberFormatCase("02 9374 4000", "AU", "+61 2 9374 4000"),
- PhoneNumberFormatCase("2 9374 4000", "AU", "+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"+61 2 9374 4000", u"AU", u"+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"61 2 9374 4000", u"AU", u"+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"02 9374 4000", u"AU", u"+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"2 9374 4000", u"AU", u"+61 2 9374 4000"),
// Raw phone numbers.
- PhoneNumberFormatCase("+61293744000", "AU", "+61 2 9374 4000"),
- PhoneNumberFormatCase("61293744000", "AU", "+61 2 9374 4000"),
- PhoneNumberFormatCase("0293744000", "AU", "+61 2 9374 4000"),
- PhoneNumberFormatCase("293744000", "AU", "+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"+61293744000", u"AU", u"+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"61293744000", u"AU", u"+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"0293744000", u"AU", u"+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"293744000", u"AU", u"+61 2 9374 4000"),
//////////////////////////
// AU phone in US.
//////////////////////////
// An AU phone with the country code is correctly formatted as an AU
// number.
- PhoneNumberFormatCase("+61 2 9374 4000", "US", "+61 2 9374 4000"),
- PhoneNumberFormatCase("61 2 9374 4000", "US", "+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"+61 2 9374 4000", u"US", u"+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"61 2 9374 4000", u"US", u"+61 2 9374 4000"),
// Without a country code, the phone is formatted for the profile's
// country.
// This local AU number is associated with US profile, the number is
// not a valid US number, therefore formatting will just return what
// user entered.
- PhoneNumberFormatCase("02 9374 4000", "US", "0293744000"),
+ PhoneNumberFormatCase(u"02 9374 4000", u"US", u"0293744000"),
// This local GR(Greece) number is formatted as an US number, if it's
// valid US number.
- PhoneNumberFormatCase("22 6800 0090", "US", "+1 226-800-0090"),
+ PhoneNumberFormatCase(u"22 6800 0090", u"US", u"+1 226-800-0090"),
//////////////////////////
// MX phone in MX.
//////////////////////////
// Formatted phone numbers.
- PhoneNumberFormatCase("+52 55 5342 8400", "MX", "+52 55 5342 8400"),
- PhoneNumberFormatCase("52 55 5342 8400", "MX", "+52 55 5342 8400"),
- PhoneNumberFormatCase("55 5342 8400", "MX", "+52 55 5342 8400"),
+ PhoneNumberFormatCase(u"+52 55 5342 8400", u"MX", u"+52 55 5342 8400"),
+ PhoneNumberFormatCase(u"52 55 5342 8400", u"MX", u"+52 55 5342 8400"),
+ PhoneNumberFormatCase(u"55 5342 8400", u"MX", u"+52 55 5342 8400"),
// Raw phone numbers.
- PhoneNumberFormatCase("+525553428400", "MX", "+52 55 5342 8400"),
- PhoneNumberFormatCase("525553428400", "MX", "+52 55 5342 8400"),
- PhoneNumberFormatCase("5553428400", "MX", "+52 55 5342 8400"),
+ PhoneNumberFormatCase(u"+525553428400", u"MX", u"+52 55 5342 8400"),
+ PhoneNumberFormatCase(u"525553428400", u"MX", u"+52 55 5342 8400"),
+ PhoneNumberFormatCase(u"5553428400", u"MX", u"+52 55 5342 8400"),
//////////////////////////
// MX phone in US.
//////////////////////////
// A MX phone with the country code is correctly formatted as a MX
// number.
- PhoneNumberFormatCase("+52 55 5342 8400", "US", "+52 55 5342 8400"),
- PhoneNumberFormatCase("52 55 5342 8400", "US", "+52 55 5342 8400"),
+ PhoneNumberFormatCase(u"+52 55 5342 8400", u"US", u"+52 55 5342 8400"),
+ PhoneNumberFormatCase(u"52 55 5342 8400", u"US", u"+52 55 5342 8400"),
// This number is not a valid US number, we won't try to format.
- PhoneNumberFormatCase("55 5342 8400", "US", "5553428400")));
+ PhoneNumberFormatCase(u"55 5342 8400", u"US", u"5553428400")));
INSTANTIATE_TEST_SUITE_P(
GetFormattedPhoneNumberForDisplay_EdgeCases,
@@ -461,31 +443,40 @@ INSTANTIATE_TEST_SUITE_P(
// No country.
//////////////////////////
// Fallback to locale if no country is set.
- PhoneNumberFormatCase("52 55 5342 8400",
- "",
- "+52 55 5342 8400",
+ PhoneNumberFormatCase(u"52 55 5342 8400",
+ u"",
+ u"+52 55 5342 8400",
+ "es_MX"),
+ PhoneNumberFormatCase(u"55 5342 8400",
+ u"",
+ u"+52 55 5342 8400",
"es_MX"),
- PhoneNumberFormatCase("55 5342 8400", "", "+52 55 5342 8400", "es_MX"),
- PhoneNumberFormatCase("61 2 9374 4000", "", "+61 2 9374 4000", "en_AU"),
- PhoneNumberFormatCase("02 9374 4000", "", "+61 2 9374 4000", "en_AU"),
+ PhoneNumberFormatCase(u"61 2 9374 4000",
+ u"",
+ u"+61 2 9374 4000",
+ "en_AU"),
+ PhoneNumberFormatCase(u"02 9374 4000",
+ u"",
+ u"+61 2 9374 4000",
+ "en_AU"),
// Numbers in local format yet are invalid with user locale, user might
// be trying to enter a foreign number, calling formatting will just
// return what the user entered.
- PhoneNumberFormatCase("55 5342 8400", "", "5553428400", "en_US"),
- PhoneNumberFormatCase("55 5342 8400", "", "5553428400"),
- PhoneNumberFormatCase("226 123 1234", "", "2261231234", "en_US"),
- PhoneNumberFormatCase("293744000", "", "293744000"),
- PhoneNumberFormatCase("02 9374 4000", "", "0293744000"),
+ PhoneNumberFormatCase(u"55 5342 8400", u"", u"5553428400", "en_US"),
+ PhoneNumberFormatCase(u"55 5342 8400", u"", u"5553428400"),
+ PhoneNumberFormatCase(u"226 123 1234", u"", u"2261231234", "en_US"),
+ PhoneNumberFormatCase(u"293744000", u"", u"293744000"),
+ PhoneNumberFormatCase(u"02 9374 4000", u"", u"0293744000"),
//////////////////////////
// No country or locale.
//////////////////////////
// Format according to the country code.
- PhoneNumberFormatCase("61 2 9374 4000", "", "+61 2 9374 4000"),
- PhoneNumberFormatCase("52 55 5342 8400", "", "+52 55 5342 8400"),
- PhoneNumberFormatCase("1 415 555 5555", "", "+1 415-555-5555"),
+ PhoneNumberFormatCase(u"61 2 9374 4000", u"", u"+61 2 9374 4000"),
+ PhoneNumberFormatCase(u"52 55 5342 8400", u"", u"+52 55 5342 8400"),
+ PhoneNumberFormatCase(u"1 415 555 5555", u"", u"+1 415-555-5555"),
// If no country code is found, formats for US.
- PhoneNumberFormatCase("415-555-5555", "", "+1 415-555-5555")));
+ PhoneNumberFormatCase(u"415-555-5555", u"", u"+1 415-555-5555")));
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/geo/state_names.cc b/chromium/components/autofill/core/browser/geo/state_names.cc
index deecc9ae400..a20508c90ea 100644
--- a/chromium/components/autofill/core/browser/geo/state_names.cc
+++ b/chromium/components/autofill/core/browser/geo/state_names.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include "base/macros.h"
+#include "base/ranges/algorithm.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -18,81 +19,77 @@ namespace {
// TODO(jhawkins): Add more states/provinces. See http://crbug.com/45039.
struct StateData {
- const char* const name;
- const char abbreviation[3];
+ const char16_t* const name;
+ const char16_t abbreviation[3];
};
const StateData kStateData[] = {
- {"alabama", "al"},
- {"alaska", "ak"},
- {"arizona", "az"},
- {"arkansas", "ar"},
- {"california", "ca"},
- {"colorado", "co"},
- {"connecticut", "ct"},
- {"delaware", "de"},
- {"district of columbia", "dc"},
- {"florida", "fl"},
- {"georgia", "ga"},
- {"hawaii", "hi"},
- {"idaho", "id"},
- {"illinois", "il"},
- {"indiana", "in"},
- {"iowa", "ia"},
- {"kansas", "ks"},
- {"kentucky", "ky"},
- {"louisiana", "la"},
- {"maine", "me"},
- {"maryland", "md"},
- {"massachusetts", "ma"},
- {"michigan", "mi"},
- {"minnesota", "mn"},
- {"mississippi", "ms"},
- {"missouri", "mo"},
- {"montana", "mt"},
- {"nebraska", "ne"},
- {"nevada", "nv"},
- {"new hampshire", "nh"},
- {"new jersey", "nj"},
- {"new mexico", "nm"},
- {"new york", "ny"},
- {"north carolina", "nc"},
- {"north dakota", "nd"},
- {"ohio", "oh"},
- {"oklahoma", "ok"},
- {"oregon", "or"},
- {"pennsylvania", "pa"},
- {"puerto rico", "pr"},
- {"rhode island", "ri"},
- {"south carolina", "sc"},
- {"south dakota", "sd"},
- {"tennessee", "tn"},
- {"texas", "tx"},
- {"utah", "ut"},
- {"vermont", "vt"},
- {"virginia", "va"},
- {"washington", "wa"},
- {"west virginia", "wv"},
- {"wisconsin", "wi"},
- {"wyoming", "wy"},
+ {u"alabama", u"al"},
+ {u"alaska", u"ak"},
+ {u"arizona", u"az"},
+ {u"arkansas", u"ar"},
+ {u"california", u"ca"},
+ {u"colorado", u"co"},
+ {u"connecticut", u"ct"},
+ {u"delaware", u"de"},
+ {u"district of columbia", u"dc"},
+ {u"florida", u"fl"},
+ {u"georgia", u"ga"},
+ {u"hawaii", u"hi"},
+ {u"idaho", u"id"},
+ {u"illinois", u"il"},
+ {u"indiana", u"in"},
+ {u"iowa", u"ia"},
+ {u"kansas", u"ks"},
+ {u"kentucky", u"ky"},
+ {u"louisiana", u"la"},
+ {u"maine", u"me"},
+ {u"maryland", u"md"},
+ {u"massachusetts", u"ma"},
+ {u"michigan", u"mi"},
+ {u"minnesota", u"mn"},
+ {u"mississippi", u"ms"},
+ {u"missouri", u"mo"},
+ {u"montana", u"mt"},
+ {u"nebraska", u"ne"},
+ {u"nevada", u"nv"},
+ {u"new hampshire", u"nh"},
+ {u"new jersey", u"nj"},
+ {u"new mexico", u"nm"},
+ {u"new york", u"ny"},
+ {u"north carolina", u"nc"},
+ {u"north dakota", u"nd"},
+ {u"ohio", u"oh"},
+ {u"oklahoma", u"ok"},
+ {u"oregon", u"or"},
+ {u"pennsylvania", u"pa"},
+ {u"puerto rico", u"pr"},
+ {u"rhode island", u"ri"},
+ {u"south carolina", u"sc"},
+ {u"south dakota", u"sd"},
+ {u"tennessee", u"tn"},
+ {u"texas", u"tx"},
+ {u"utah", u"ut"},
+ {u"vermont", u"vt"},
+ {u"virginia", u"va"},
+ {u"washington", u"wa"},
+ {u"west virginia", u"wv"},
+ {u"wisconsin", u"wi"},
+ {u"wyoming", u"wy"},
};
} // namespace
std::u16string GetAbbreviationForName(const std::u16string& name) {
- for (const StateData& state : kStateData) {
- if (base::LowerCaseEqualsASCII(name, state.name))
- return base::ASCIIToUTF16(state.abbreviation);
- }
- return std::u16string();
+ auto* it = base::ranges::find(kStateData, base::ToLowerASCII(name),
+ &StateData::name);
+ return it != std::end(kStateData) ? it->abbreviation : std::u16string();
}
std::u16string GetNameForAbbreviation(const std::u16string& abbreviation) {
- for (const StateData& state : kStateData) {
- if (base::LowerCaseEqualsASCII(abbreviation, state.abbreviation))
- return base::ASCIIToUTF16(state.name);
- }
- return std::u16string();
+ auto* it = base::ranges::find(kStateData, base::ToLowerASCII(abbreviation),
+ &StateData::abbreviation);
+ return it != std::end(kStateData) ? it->name : std::u16string();
}
void GetNameAndAbbreviation(const std::u16string& value,
diff --git a/chromium/components/autofill/core/browser/metrics/form_event_logger_base.cc b/chromium/components/autofill/core/browser/metrics/form_event_logger_base.cc
index 4b42968d295..924a995e8fa 100644
--- a/chromium/components/autofill/core/browser/metrics/form_event_logger_base.cc
+++ b/chromium/components/autofill/core/browser/metrics/form_event_logger_base.cc
@@ -17,6 +17,24 @@ using base::UmaHistogramBoolean;
namespace autofill {
+namespace {
+
+// The default group is mapped to nullptr, as this does not get logged as a
+// histogram sample.
+const char* AblationGroupToString(AblationGroup ablation_group) {
+ switch (ablation_group) {
+ case AblationGroup::kAblation:
+ return "Ablation";
+ case AblationGroup::kControl:
+ return "Control";
+ case AblationGroup::kDefault:
+ return nullptr;
+ }
+ return nullptr;
+}
+
+} // namespace
+
FormEventLoggerBase::FormEventLoggerBase(
const std::string& form_type_name,
bool is_in_main_frame,
@@ -28,7 +46,11 @@ FormEventLoggerBase::FormEventLoggerBase(
log_manager_(log_manager) {}
FormEventLoggerBase::~FormEventLoggerBase() {
- RecordFunnelAndKeyMetrics();
+ // Don't record Funnel and Key metrics for the ablation group as they don't
+ // represent the true quality metrics.
+ if (ablation_group_ != AblationGroup::kAblation)
+ RecordFunnelAndKeyMetrics();
+ RecordAblationMetrics();
}
void FormEventLoggerBase::OnDidInteractWithAutofillableForm(
@@ -102,6 +124,25 @@ void FormEventLoggerBase::OnDidShowSuggestions(
RecordShowSuggestions();
}
+void FormEventLoggerBase::SetAblationStatus(
+ AblationGroup ablation_group,
+ AblationGroup conditional_ablation_group) {
+ ablation_group_ = ablation_group;
+ // For each form, the ablation group should be stable (except in the rare
+ // event that a day boundary is crossed). In practice, it is possible,
+ // however, that a the condtional_ablation_group is reported as kDefault
+ // because the user has typed a prefix into an input element that filtered
+ // all filling options. In this case, we should still consider this an
+ // ablation experience if suggestions were available when the field was empty.
+ if (conditional_ablation_group != AblationGroup::kDefault)
+ conditional_ablation_group_ = conditional_ablation_group;
+}
+
+void FormEventLoggerBase::SetTimeFromInteractionToSubmission(
+ base::TimeDelta time_from_interaction_to_submission) {
+ time_from_interaction_to_submission_ = time_from_interaction_to_submission;
+}
+
void FormEventLoggerBase::OnWillSubmitForm(AutofillSyncSigninState sync_state,
const FormStructure& form) {
sync_state_ = sync_state;
@@ -123,8 +164,7 @@ void FormEventLoggerBase::OnWillSubmitForm(AutofillSyncSigninState sync_state,
base::RecordAction(base::UserMetricsAction("Autofill_OnWillSubmitForm"));
}
-void FormEventLoggerBase::OnFormSubmitted(bool force_logging,
- AutofillSyncSigninState sync_state,
+void FormEventLoggerBase::OnFormSubmitted(AutofillSyncSigninState sync_state,
const FormStructure& form) {
sync_state_ = sync_state;
// Not logging this kind of form if we haven't logged a user interaction.
@@ -138,7 +178,7 @@ void FormEventLoggerBase::OnFormSubmitted(bool force_logging,
LogFormSubmitted(form);
- if (has_logged_suggestions_shown_ || force_logging) {
+ if (has_logged_suggestions_shown_) {
Log(FORM_EVENT_SUGGESTION_SHOWN_SUBMITTED_ONCE, form);
OnSuggestionsShownSubmittedOnce(form);
}
@@ -321,4 +361,54 @@ void FormEventLoggerBase::RecordFunnelAndKeyMetrics() {
}
}
+void FormEventLoggerBase::RecordAblationMetrics() {
+ if (!has_logged_interacted_)
+ return;
+
+ // Record whether the form was submitted.
+
+ // AblationGroup::kDefault is mapped to nullptr.
+ const char* conditional_ablation_group_string =
+ AblationGroupToString(conditional_ablation_group_);
+ if (conditional_ablation_group_string) {
+ UmaHistogramBoolean(
+ base::StrCat({"Autofill.Ablation.FormSubmissionAfterInteraction.",
+ form_type_name_.c_str(), ".Conditional",
+ conditional_ablation_group_string}),
+ has_logged_will_submit_);
+ }
+
+ // AblationGroup::kDefault is mapped to nullptr.
+ const char* ablation_group_string = AblationGroupToString(ablation_group_);
+ if (ablation_group_string) {
+ UmaHistogramBoolean(
+ base::StrCat({"Autofill.Ablation.FormSubmissionAfterInteraction.",
+ form_type_name_.c_str(), ".Unconditional",
+ ablation_group_string}),
+ has_logged_will_submit_);
+ }
+
+ // Record the submission time since interaction.
+ if (time_from_interaction_to_submission_) {
+ if (conditional_ablation_group_string) {
+ base::UmaHistogramCustomTimes(
+ base::StrCat({"Autofill.Ablation.FillDurationSinceInteraction.",
+ form_type_name_.c_str(), ".Conditional",
+ conditional_ablation_group_string}),
+ *time_from_interaction_to_submission_,
+ base::TimeDelta::FromMilliseconds(100),
+ base::TimeDelta::FromMinutes(10), 50);
+ }
+ if (ablation_group_string) {
+ base::UmaHistogramCustomTimes(
+ base::StrCat({"Autofill.Ablation.FillDurationSinceInteraction.",
+ form_type_name_.c_str(), ".Unconditional",
+ ablation_group_string}),
+ *time_from_interaction_to_submission_,
+ base::TimeDelta::FromMilliseconds(100),
+ base::TimeDelta::FromMinutes(10), 50);
+ }
+ }
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/metrics/form_event_logger_base.h b/chromium/components/autofill/core/browser/metrics/form_event_logger_base.h
index 130c04e0e90..0338151f599 100644
--- a/chromium/components/autofill/core/browser/metrics/form_event_logger_base.h
+++ b/chromium/components/autofill/core/browser/metrics/form_event_logger_base.h
@@ -7,12 +7,15 @@
#include <string>
+#include "base/time/time.h"
+#include "components/autofill/core/browser/autofill_ablation_study.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"
#include "components/autofill/core/browser/metrics/form_events.h"
#include "components/autofill/core/browser/sync_utils.h"
#include "components/autofill/core/common/form_field_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -58,13 +61,19 @@ class FormEventLoggerBase {
void OnWillSubmitForm(AutofillSyncSigninState sync_state,
const FormStructure& form);
- void OnFormSubmitted(bool force_logging,
- AutofillSyncSigninState sync_state,
+ void OnFormSubmitted(AutofillSyncSigninState sync_state,
const FormStructure& form);
void OnTypedIntoNonFilledField();
void OnEditedAutofilledField();
+ // See BrowserAutofillManager::SuggestionContext for the definitions of the
+ // AblationGroup parameters.
+ void SetAblationStatus(AblationGroup ablation_group,
+ AblationGroup conditional_ablation_group);
+ void SetTimeFromInteractionToSubmission(
+ base::TimeDelta time_from_interaction_to_submission);
+
protected:
virtual ~FormEventLoggerBase();
@@ -97,6 +106,11 @@ class FormEventLoggerBase {
// because it is called in the destructor.
void RecordFunnelAndKeyMetrics();
+ // Records UMA metrics if this form submission happened as part of an ablation
+ // study or the corresponding control group. This is not virtual because it is
+ // called in the destructor.
+ void RecordAblationMetrics();
+
// Constructor parameters.
std::string form_type_name_;
bool is_in_main_frame_;
@@ -116,6 +130,9 @@ class FormEventLoggerBase {
bool logged_suggestion_filled_was_server_data_ = false;
bool has_logged_typed_into_non_filled_field_ = false;
bool has_logged_edited_autofilled_field_ = false;
+ AblationGroup ablation_group_ = AblationGroup::kDefault;
+ AblationGroup conditional_ablation_group_ = AblationGroup::kDefault;
+ absl::optional<base::TimeDelta> time_from_interaction_to_submission_;
// The last field that was polled for suggestions.
FormFieldData last_polled_field_;
diff --git a/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc b/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc
index 90a25140693..bb9adbe8f4a 100644
--- a/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc
+++ b/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc
@@ -42,11 +42,11 @@ bool ParseMatchingPattern(PatternProvider::Map& patterns,
value.FindStringKey(kPositivePatternKey);
const std::string* negative_pattern =
value.FindStringKey(kNegativePatternKey);
- base::Optional<double> positive_score =
+ absl::optional<double> positive_score =
value.FindDoubleKey(kPositiveScoreKey);
- base::Optional<int> match_field_attributes =
+ absl::optional<int> match_field_attributes =
value.FindIntKey(kMatchFieldAttributesKey);
- base::Optional<int> match_field_input_types =
+ absl::optional<int> match_field_input_types =
value.FindIntKey(kMatchFieldInputTypesKey);
if (!positive_pattern || !positive_score || !match_field_attributes ||
@@ -95,7 +95,7 @@ void OnJsonParsed(data_decoder::DataDecoder::ValueOrError result) {
}
base::Version version = ExtractVersionFromJsonObject(result.value.value());
- base::Optional<PatternProvider::Map> patterns =
+ absl::optional<PatternProvider::Map> patterns =
GetConfigurationFromJsonObject(result.value.value());
if (patterns && version.IsValid()) {
@@ -110,13 +110,13 @@ void OnJsonParsed(data_decoder::DataDecoder::ValueOrError result) {
} // namespace
-base::Optional<PatternProvider::Map> GetConfigurationFromJsonObject(
+absl::optional<PatternProvider::Map> GetConfigurationFromJsonObject(
const base::Value& root) {
PatternProvider::Map patterns;
if (!root.is_dict()) {
DVLOG(1) << "JSON object is not a dictionary.";
- return base::nullopt;
+ return absl::nullopt;
}
for (const auto& kv : root.DictItems()) {
@@ -125,7 +125,7 @@ base::Optional<PatternProvider::Map> GetConfigurationFromJsonObject(
if (!field_type_dict->is_dict()) {
DVLOG(1) << "|" << field_type << "| does not contain a dictionary.";
- return base::nullopt;
+ return absl::nullopt;
}
for (const auto& value : field_type_dict->DictItems()) {
@@ -135,7 +135,7 @@ base::Optional<PatternProvider::Map> GetConfigurationFromJsonObject(
if (!inner_list->is_list()) {
DVLOG(1) << "Language |" << language << "| in |" << field_type
<< "| does not contain a list.";
- return base::nullopt;
+ return absl::nullopt;
}
for (const auto& matchingPatternObj : inner_list->GetList()) {
@@ -144,20 +144,20 @@ base::Optional<PatternProvider::Map> GetConfigurationFromJsonObject(
if (!success) {
DVLOG(1) << "Found incorrect |MatchingPattern| object in list |"
<< field_type << "|, language |" << language.value() << "|.";
- return base::nullopt;
+ return absl::nullopt;
}
}
}
}
- return base::make_optional(patterns);
+ return absl::make_optional(patterns);
}
base::Version ExtractVersionFromJsonObject(base::Value& root) {
if (!root.is_dict())
return base::Version("0");
- base::Optional<base::Value> version_str = root.ExtractKey(kVersionKey);
+ absl::optional<base::Value> version_str = root.ExtractKey(kVersionKey);
if (!version_str || !version_str.value().is_string())
return base::Version("0");
@@ -173,23 +173,23 @@ void PopulateFromJsonString(std::string json_string) {
base::BindOnce(&OnJsonParsed));
}
-base::Optional<PatternProvider::Map>
+absl::optional<PatternProvider::Map>
GetPatternsFromResourceBundleSynchronously() {
if (!ui::ResourceBundle::HasSharedInstance()) {
VLOG(1) << "Resource Bundle unavailable to load Autofill Matching Pattern "
"definitions.";
- return base::nullopt;
+ return absl::nullopt;
}
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
std::string resource_string =
bundle.LoadDataResourceString(IDR_AUTOFILL_REGEX_JSON);
- base::Optional<base::Value> json_object =
+ absl::optional<base::Value> json_object =
base::JSONReader::Read(resource_string);
// Discard version, since this is the only getter used in unit tests.
base::Version version = ExtractVersionFromJsonObject(json_object.value());
- base::Optional<PatternProvider::Map> configuration_map =
+ absl::optional<PatternProvider::Map> configuration_map =
GetConfigurationFromJsonObject(json_object.value());
return configuration_map;
diff --git a/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h b/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h
index 78dc78ca275..2e961fbda4c 100644
--- a/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h
+++ b/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h
@@ -37,7 +37,7 @@ base::Version ExtractVersionFromJsonObject(base::Value& root);
// }
// }
// An example can be found in the relative resources folder.
-base::Optional<PatternProvider::Map> GetConfigurationFromJsonObject(
+absl::optional<PatternProvider::Map> GetConfigurationFromJsonObject(
const base::Value& root);
// Tries to get and parse the default configuration in the resource bundle
@@ -51,11 +51,11 @@ void PopulateFromResourceBundle(
void PopulateFromJsonString(std::string json_string);
// Synchronous getter used to set up a test fixture.
-base::Optional<PatternProvider::Map>
+absl::optional<PatternProvider::Map>
GetPatternsFromResourceBundleSynchronously();
} // namespace field_type_parsing
} // namespace autofill
-#endif
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_PATTERN_CONFIGURATION_PARSER_H_
diff --git a/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser_unittest.cc b/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser_unittest.cc
index 71094b51f2f..32ed87e0611 100644
--- a/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser_unittest.cc
+++ b/chromium/components/autofill/core/browser/pattern_provider/pattern_configuration_parser_unittest.cc
@@ -61,13 +61,13 @@ TEST(PatternConfigurationParserTest, WellFormedParsedCorrectly) {
]
}
})";
- base::Optional<base::Value> json_object =
+ absl::optional<base::Value> json_object =
base::JSONReader::Read(json_message);
ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";
base::Version version = ExtractVersionFromJsonObject(json_object.value());
- base::Optional<PatternProvider::Map> optional_patterns =
+ absl::optional<PatternProvider::Map> optional_patterns =
GetConfigurationFromJsonObject(json_object.value());
ASSERT_TRUE(version.IsValid());
@@ -126,12 +126,12 @@ TEST(PatternConfigurationParserTest, MalformedMissingProperty) {
]
}
})";
- base::Optional<base::Value> json_object =
+ absl::optional<base::Value> json_object =
base::JSONReader::Read(json_message);
ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";
- base::Optional<PatternProvider::Map> optional_patterns =
+ absl::optional<PatternProvider::Map> optional_patterns =
GetConfigurationFromJsonObject(json_object.value());
ASSERT_FALSE(optional_patterns);
@@ -154,7 +154,7 @@ TEST(PatternConfigurationParserTest, MalformedMissingVersion) {
]
}
})";
- base::Optional<base::Value> json_object =
+ absl::optional<base::Value> json_object =
base::JSONReader::Read(json_message);
ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";
@@ -179,12 +179,12 @@ TEST(PatternConfigurationParserTest, MalformedNotList) {
}
}
})";
- base::Optional<base::Value> json_object =
+ absl::optional<base::Value> json_object =
base::JSONReader::Read(json_message);
ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string.";
- base::Optional<PatternProvider::Map> optional_patterns =
+ absl::optional<PatternProvider::Map> optional_patterns =
GetConfigurationFromJsonObject(json_object.value());
ASSERT_FALSE(optional_patterns);
diff --git a/chromium/components/autofill/core/browser/pattern_provider/pattern_provider.h b/chromium/components/autofill/core/browser/pattern_provider/pattern_provider.h
index 767ad35788e..129aa3d4518 100644
--- a/chromium/components/autofill/core/browser/pattern_provider/pattern_provider.h
+++ b/chromium/components/autofill/core/browser/pattern_provider/pattern_provider.h
@@ -5,15 +5,14 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_PATTERN_PROVIDER_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_PATTERN_PROVIDER_H_
+#include <map>
#include <string>
+#include <vector>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/sequence_checker.h"
-#include "base/types/strong_alias.h"
#include "base/version.h"
-#include "components/autofill/core/browser/autofill_regex_constants.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_parsing/autofill_parsing_utils.h"
#include "components/autofill/core/common/language_code.h"
@@ -76,5 +75,7 @@ class PatternProvider {
// Version for keeping track which pattern set is currently used.
base::Version pattern_version_;
};
+
} // namespace autofill
+
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PATTERN_PROVIDER_PATTERN_PROVIDER_H_
diff --git a/chromium/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc b/chromium/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc
index 0adb4c4a298..a51a6df6942 100644
--- a/chromium/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc
+++ b/chromium/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc
@@ -78,7 +78,7 @@ void OnJsonParsed(base::OnceClosure done_callback,
data_decoder::DataDecoder::ValueOrError result) {
base::Version version =
field_type_parsing::ExtractVersionFromJsonObject(result.value.value());
- base::Optional<PatternProvider::Map> patterns =
+ absl::optional<PatternProvider::Map> patterns =
field_type_parsing::GetConfigurationFromJsonObject(result.value.value());
ASSERT_TRUE(patterns);
ASSERT_TRUE(version.IsValid());
diff --git a/chromium/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json b/chromium/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json
index 6dc7780d233..bcf66ebf664 100644
--- a/chromium/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json
+++ b/chromium/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json
@@ -1563,7 +1563,7 @@
"en": [
{
"pattern_identifier": "en_card_number_preserving",
- "positive_pattern": "(add)?(?:card|cc|acct).?(?:number|#|no|num|field)",
+ "positive_pattern": "(add)?(?:card|cc|acct).?(?:number|#|no|num|field|pan)",
"positive_score": 1.0,
"negative_pattern": null,
"match_field_attributes": 3,
@@ -1573,7 +1573,7 @@
"de": [
{
"pattern_identifier": "de_card_number_preserving",
- "positive_pattern": "(?<!telefon|haus|person|fødsels)nummer",
+ "positive_pattern": "(?<!telefon|haus|person|fødsels|kunden)nummer",
"positive_score": 1.0,
"negative_pattern": null,
"match_field_attributes": 3,
diff --git a/chromium/components/autofill/core/browser/payments/account_info_getter.h b/chromium/components/autofill/core/browser/payments/account_info_getter.h
index 8e91ad1dda6..383f144f9fe 100644
--- a/chromium/components/autofill/core/browser/payments/account_info_getter.h
+++ b/chromium/components/autofill/core/browser/payments/account_info_getter.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_ACCOUNT_INFO_GETTER_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_ACCOUNT_INFO_GETTER_H_
-#include <string>
-
#include "components/signin/public/identity_manager/account_info.h"
namespace autofill {
diff --git a/chromium/components/autofill/core/browser/payments/autofill_offer_manager.cc b/chromium/components/autofill/core/browser/payments/autofill_offer_manager.cc
index 595d94665c1..e9fc38da344 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_offer_manager.cc
+++ b/chromium/components/autofill/core/browser/payments/autofill_offer_manager.cc
@@ -58,7 +58,7 @@ void AutofillOfferManager::UpdateSuggestionsWithOffers(
}
AutofillOfferManager::OffersMap eligible_offers_map =
- CreateOffersMap(last_committed_url_origin);
+ CreateCardLinkedOffersMap(last_committed_url_origin);
// Update |offer_label| for each suggestion.
for (auto& suggestion : suggestions) {
@@ -91,46 +91,19 @@ bool AutofillOfferManager::IsUrlEligible(const GURL& last_committed_url) {
eligible_merchant_domains_.count(last_committed_url.GetOrigin());
}
-std::tuple<std::vector<GURL>, GURL, CreditCard*>
-AutofillOfferManager::GetEligibleDomainsAndCardForOfferForUrl(
+AutofillOfferData* AutofillOfferManager::GetOfferForUrl(
const GURL& last_committed_url) {
- std::vector<GURL> linked_domains;
- std::vector<AutofillOfferData*> offers =
- personal_data_->GetCreditCardOffers();
- CreditCard* card = nullptr;
- // Initialize to an empty url.
- GURL offer_details_url = GURL();
-
- // Check which offer is eligible on current domain, then return the full set
- // of domains for that offer.
- for (auto* offer : offers) {
+ for (AutofillOfferData* offer : personal_data_->GetAutofillOffers()) {
if (IsOfferEligible(*offer, last_committed_url.GetOrigin())) {
- for (auto& domain : offer->merchant_domain) {
- linked_domains.emplace_back(domain);
- }
- // Pick first card in the vector. The UI shows only one card's
- // information.
- card = offer->eligible_instrument_id.empty()
- ? nullptr
- : personal_data_->GetCreditCardByInstrumentId(
- offer->eligible_instrument_id[0]);
- offer_details_url = GURL(offer->offer_details_url);
- break;
+ return offer;
}
}
-
- // Remove duplicates in domains.
- base::ranges::sort(linked_domains);
- linked_domains.erase(base::ranges::unique(linked_domains),
- linked_domains.end());
-
- return std::make_tuple(linked_domains, offer_details_url, card);
+ return nullptr;
}
void AutofillOfferManager::UpdateEligibleMerchantDomains() {
eligible_merchant_domains_.clear();
- std::vector<AutofillOfferData*> offers =
- personal_data_->GetCreditCardOffers();
+ std::vector<AutofillOfferData*> offers = personal_data_->GetAutofillOffers();
for (auto* offer : offers) {
for (auto& domain : offer->merchant_domain) {
@@ -139,12 +112,11 @@ void AutofillOfferManager::UpdateEligibleMerchantDomains() {
}
}
-AutofillOfferManager::OffersMap AutofillOfferManager::CreateOffersMap(
+AutofillOfferManager::OffersMap AutofillOfferManager::CreateCardLinkedOffersMap(
const GURL& last_committed_url_origin) const {
AutofillOfferManager::OffersMap offers_map;
- std::vector<AutofillOfferData*> offers =
- personal_data_->GetCreditCardOffers();
+ std::vector<AutofillOfferData*> offers = personal_data_->GetAutofillOffers();
std::vector<CreditCard*> cards = personal_data_->GetCreditCards();
for (auto* offer : offers) {
@@ -152,6 +124,10 @@ AutofillOfferManager::OffersMap AutofillOfferManager::CreateOffersMap(
if (!IsOfferEligible(*offer, last_committed_url_origin)) {
continue;
}
+ // Ensure the offer is a card-linked offer.
+ if (!offer->IsCardLinkedOffer()) {
+ continue;
+ }
// Find card with corresponding instrument ID and add its guid to the map.
for (const auto* card : cards) {
diff --git a/chromium/components/autofill/core/browser/payments/autofill_offer_manager.h b/chromium/components/autofill/core/browser/payments/autofill_offer_manager.h
index e330f35d8d7..e18d76b7450 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_offer_manager.h
+++ b/chromium/components/autofill/core/browser/payments/autofill_offer_manager.h
@@ -11,7 +11,6 @@
#include <tuple>
#include <vector>
-#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/data_model/autofill_offer_data.h"
@@ -22,10 +21,8 @@
namespace autofill {
-class CreditCard;
-
// Manages all Autofill related offers. One per frame; owned by the
-// AutofillManager.
+// BrowserAutofillManager.
class AutofillOfferManager : public KeyedService,
public PersonalDataManagerObserver {
public:
@@ -47,23 +44,23 @@ class AutofillOfferManager : public KeyedService,
// Returns true only if the domain of |last_committed_url| has an offer.
bool IsUrlEligible(const GURL& last_committed_url);
- // Returns the set of domains and the card linked to a specific offer that
- // contains the domain of |last_committed_url|. Also return the
- // offer_details_url which redirects to a GPay surface with more details about
- // the offer.
- std::tuple<std::vector<GURL>, GURL, CreditCard*>
- GetEligibleDomainsAndCardForOfferForUrl(const GURL& last_committed_url);
+ // Returns the offer that contains the domain of |last_committed_url|.
+ AutofillOfferData* GetOfferForUrl(const GURL& last_committed_url);
private:
+ FRIEND_TEST_ALL_PREFIXES(
+ AutofillOfferManagerTest,
+ CreateCardLinkedOffersMap_ReturnsOnlyCardLinkedOffers);
FRIEND_TEST_ALL_PREFIXES(AutofillOfferManagerTest, IsUrlEligible);
// Queries |personal_data_| to reset the elements of
// |eligible_merchant_domains_|
void UpdateEligibleMerchantDomains();
- // Creates a mapping from Suggestion Backend ID's to eligible Credit Card
- // Offers.
- OffersMap CreateOffersMap(const GURL& last_committed_url_origin) const;
+ // Creates a mapping from Suggestion Backend ID's to eligible card-linked
+ // offers.
+ OffersMap CreateCardLinkedOffersMap(
+ const GURL& last_committed_url_origin) const;
PersonalDataManager* personal_data_;
std::set<GURL> eligible_merchant_domains_ = {};
diff --git a/chromium/components/autofill/core/browser/payments/autofill_offer_manager_unittest.cc b/chromium/components/autofill/core/browser/payments/autofill_offer_manager_unittest.cc
index 24bac17c4c1..e692c64b2fe 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_offer_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/autofill_offer_manager_unittest.cc
@@ -50,6 +50,7 @@ class AutofillOfferManagerTest : public testing::Test {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
personal_data_manager_.SetPrefService(autofill_client_.GetPrefs());
autofill_offer_manager_ =
@@ -90,19 +91,34 @@ class AutofillOfferManagerTest : public testing::Test {
return offer_data;
}
+ AutofillOfferData CreatePromoCodeOffer(std::vector<GURL> domains = {
+ GURL(kTestUrl)}) {
+ AutofillOfferData offer_data;
+ offer_data.offer_id = 5555;
+ offer_data.expiry = AutofillClock::Now() + base::TimeDelta::FromDays(2);
+ offer_data.merchant_domain = std::move(domains);
+ offer_data.offer_details_url = GURL(kOfferDetailsUrl);
+ offer_data.promo_code = "5PCTOFFSHOES";
+ offer_data.display_strings.value_prop_text = "5% off on shoes. Up to $50.";
+ offer_data.display_strings.see_details_text = "See details";
+ offer_data.display_strings.usage_instructions_text =
+ "Click the promo code field at checkout to autofill it.";
+ return offer_data;
+ }
+
protected:
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
TestAutofillClient autofill_client_;
scoped_refptr<AutofillWebDataService> database_;
TestPersonalDataManager personal_data_manager_;
- std::unique_ptr<AutofillOfferManager> autofill_offer_manager_ = nullptr;
+ std::unique_ptr<AutofillOfferManager> autofill_offer_manager_;
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_F(AutofillOfferManagerTest, UpdateSuggestionsWithOffers_EligibleCashback) {
CreditCard card = CreateCreditCard(kTestGuid);
- personal_data_manager_.AddCreditCardOfferData(
+ personal_data_manager_.AddAutofillOfferData(
CreateCreditCardOfferForCard(card, "5%"));
std::vector<Suggestion> suggestions = {Suggestion()};
@@ -116,7 +132,7 @@ TEST_F(AutofillOfferManagerTest, UpdateSuggestionsWithOffers_EligibleCashback) {
TEST_F(AutofillOfferManagerTest, UpdateSuggestionsWithOffers_ExpiredOffer) {
CreditCard card = CreateCreditCard(kTestGuid);
- personal_data_manager_.AddCreditCardOfferData(
+ personal_data_manager_.AddAutofillOfferData(
CreateCreditCardOfferForCard(card, "5%", /*expired=*/true));
std::vector<Suggestion> suggestions = {Suggestion()};
@@ -129,7 +145,7 @@ TEST_F(AutofillOfferManagerTest, UpdateSuggestionsWithOffers_ExpiredOffer) {
TEST_F(AutofillOfferManagerTest, UpdateSuggestionsWithOffers_WrongUrl) {
CreditCard card = CreateCreditCard(kTestGuid);
- personal_data_manager_.AddCreditCardOfferData(
+ personal_data_manager_.AddAutofillOfferData(
CreateCreditCardOfferForCard(card, "5%"));
std::vector<Suggestion> suggestions = {Suggestion()};
@@ -145,7 +161,7 @@ TEST_F(AutofillOfferManagerTest,
CreditCard cardWithoutOffer = CreateCreditCard(kTestGuid);
CreditCard cardWithOffer =
CreateCreditCard(kTestGuid2, "4111111111111111", 100);
- personal_data_manager_.AddCreditCardOfferData(
+ personal_data_manager_.AddAutofillOfferData(
CreateCreditCardOfferForCard(cardWithOffer, "5%"));
std::vector<Suggestion> suggestions = {Suggestion(), Suggestion()};
@@ -170,7 +186,7 @@ TEST_F(AutofillOfferManagerTest,
CreditCard cardWithoutOffer = CreateCreditCard(kTestGuid);
CreditCard cardWithOffer =
CreateCreditCard(kTestGuid2, "4111111111111111", 100);
- personal_data_manager_.AddCreditCardOfferData(
+ personal_data_manager_.AddAutofillOfferData(
CreateCreditCardOfferForCard(cardWithOffer, "5%"));
std::vector<Suggestion> suggestions = {Suggestion(), Suggestion()};
@@ -191,9 +207,9 @@ TEST_F(AutofillOfferManagerTest,
UpdateSuggestionsWithOffer_SuggestionsNotSortedIfAllCardsHaveOffers) {
CreditCard card1 = CreateCreditCard(kTestGuid, kTestNumber, 100);
CreditCard card2 = CreateCreditCard(kTestGuid2, "4111111111111111", 101);
- personal_data_manager_.AddCreditCardOfferData(
+ personal_data_manager_.AddAutofillOfferData(
CreateCreditCardOfferForCard(card1, "5%"));
- personal_data_manager_.AddCreditCardOfferData(
+ personal_data_manager_.AddAutofillOfferData(
CreateCreditCardOfferForCard(card2, "5%"));
std::vector<Suggestion> suggestions = {Suggestion(), Suggestion()};
@@ -209,10 +225,10 @@ TEST_F(AutofillOfferManagerTest,
TEST_F(AutofillOfferManagerTest, IsUrlEligible) {
CreditCard card1 = CreateCreditCard(kTestGuid, kTestNumber, 100);
CreditCard card2 = CreateCreditCard(kTestGuid2, "4111111111111111", 101);
- personal_data_manager_.AddCreditCardOfferData(CreateCreditCardOfferForCard(
+ personal_data_manager_.AddAutofillOfferData(CreateCreditCardOfferForCard(
card1, "5%", /*expired=*/false,
{GURL("http://www.google.com"), GURL("http://www.youtube.com")}));
- personal_data_manager_.AddCreditCardOfferData(CreateCreditCardOfferForCard(
+ personal_data_manager_.AddAutofillOfferData(CreateCreditCardOfferForCard(
card2, "10%", /*expired=*/false, {GURL("http://maps.google.com")}));
autofill_offer_manager_->UpdateEligibleMerchantDomains();
@@ -224,66 +240,63 @@ TEST_F(AutofillOfferManagerTest, IsUrlEligible) {
autofill_offer_manager_->IsUrlEligible(GURL("http://maps.google.com")));
}
-TEST_F(AutofillOfferManagerTest,
- GetEligibleDomainsAndCardForOfferForUrl_ReturnNothingWhenFindNoMatch) {
+TEST_F(AutofillOfferManagerTest, GetOfferForUrl_ReturnNothingWhenFindNoMatch) {
CreditCard card1 = CreateCreditCard(kTestGuid, kTestNumber, 100);
- personal_data_manager_.AddCreditCardOfferData(CreateCreditCardOfferForCard(
+ personal_data_manager_.AddAutofillOfferData(CreateCreditCardOfferForCard(
card1, "5%", /*expired=*/false,
{GURL("http://www.google.com"), GURL("http://www.youtube.com")}));
- auto result =
- autofill_offer_manager_->GetEligibleDomainsAndCardForOfferForUrl(
- GURL("http://www.example.com"));
- EXPECT_EQ(0U, std::get<0>(result).size());
- EXPECT_EQ(GURL(), std::get<1>(result));
- EXPECT_EQ(nullptr, std::get<2>(result));
+ AutofillOfferData* result =
+ autofill_offer_manager_->GetOfferForUrl(GURL("http://www.example.com"));
+ EXPECT_EQ(nullptr, result);
}
TEST_F(AutofillOfferManagerTest,
- GetEligibleDomainsAndCardForOfferForUrl_ReturnCorrectSetWhenFindMatch) {
+ GetOfferForUrl_ReturnCorrectOfferWhenFindMatch) {
CreditCard card1 = CreateCreditCard(kTestGuid, kTestNumber, 100);
CreditCard card2 = CreateCreditCard(kTestGuid2, "4111111111111111", 101);
- personal_data_manager_.AddCreditCardOfferData(CreateCreditCardOfferForCard(
+ AutofillOfferData offer1 = CreateCreditCardOfferForCard(
card1, "5%", /*expired=*/false,
/*domains=*/
- {GURL("http://www.google.com"), GURL("http://www.youtube.com")}));
- personal_data_manager_.AddCreditCardOfferData(CreateCreditCardOfferForCard(
- card2, "5%", /*expired=*/false,
+ {GURL("http://www.google.com"), GURL("http://www.youtube.com")});
+ AutofillOfferData offer2 = CreateCreditCardOfferForCard(
+ card2, "10%", /*expired=*/false,
/*domains=*/
- {GURL("http://www.example.com"), GURL("http://www.example2.com")}));
-
- auto result =
- autofill_offer_manager_->GetEligibleDomainsAndCardForOfferForUrl(
- GURL("http://www.example.com"));
- std::vector<GURL> eligible_domain = std::get<0>(result);
- EXPECT_EQ(2U, eligible_domain.size());
- EXPECT_NE(eligible_domain.end(),
- std::find(eligible_domain.begin(), eligible_domain.end(),
- GURL("http://www.example.com")));
- EXPECT_NE(eligible_domain.end(),
- std::find(eligible_domain.begin(), eligible_domain.end(),
- GURL("http://www.example2.com")));
- EXPECT_EQ(GURL(kOfferDetailsUrl), std::get<1>(result));
- EXPECT_EQ(101, std::get<2>(result)->instrument_id());
+ {GURL("http://www.example.com"), GURL("http://www.example2.com")});
+ personal_data_manager_.AddAutofillOfferData(offer1);
+ personal_data_manager_.AddAutofillOfferData(offer2);
+
+ AutofillOfferData* result =
+ autofill_offer_manager_->GetOfferForUrl(GURL("http://www.example.com"));
+ EXPECT_EQ(offer2, *result);
}
-TEST_F(
- AutofillOfferManagerTest,
- GetEligibleDomainsAndCardForOfferForUrl_ReturnNoCardWhenFindNoMatchedCardData) {
+TEST_F(AutofillOfferManagerTest,
+ CreateCardLinkedOffersMap_ReturnsOnlyCardLinkedOffers) {
CreditCard card1 = CreateCreditCard(kTestGuid, kTestNumber, 100);
- AutofillOfferData offer_data1 = CreateCreditCardOfferForCard(
+ CreditCard card2 = CreateCreditCard(kTestGuid2, "4111111111111111", 101);
+
+ AutofillOfferData offer1 = CreateCreditCardOfferForCard(
card1, "5%", /*expired=*/false,
+ /*domains=*/
{GURL("http://www.google.com"), GURL("http://www.youtube.com")});
- offer_data1.eligible_instrument_id.clear();
- personal_data_manager_.AddCreditCardOfferData(offer_data1);
-
- auto result =
- autofill_offer_manager_->GetEligibleDomainsAndCardForOfferForUrl(
- GURL("http://www.google.com"));
- EXPECT_EQ(2U, std::get<0>(result).size());
- EXPECT_EQ(GURL(kOfferDetailsUrl), std::get<1>(result));
- EXPECT_EQ(nullptr, std::get<2>(result));
+ AutofillOfferData offer2 = CreateCreditCardOfferForCard(
+ card2, "10%", /*expired=*/false,
+ /*domains=*/
+ {GURL("http://www.example.com"), GURL("http://www.example2.com")});
+ AutofillOfferData offer3 =
+ CreatePromoCodeOffer(/*domains=*/
+ {GURL("http://www.example.com"),
+ GURL("http://www.example2.com")});
+ personal_data_manager_.AddAutofillOfferData(offer1);
+ personal_data_manager_.AddAutofillOfferData(offer2);
+ personal_data_manager_.AddAutofillOfferData(offer3);
+
+ auto result = autofill_offer_manager_->CreateCardLinkedOffersMap(
+ GURL("http://www.example.com"));
+ EXPECT_EQ(result.size(), 1UL);
+ EXPECT_EQ(*result[card2.guid()], offer2);
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_mobile.h b/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_mobile.h
index 99d93d80d3e..b2cc5ea41c4 100644
--- a/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_mobile.h
+++ b/chromium/components/autofill/core/browser/payments/autofill_save_card_infobar_mobile.h
@@ -22,7 +22,7 @@ class AutofillSaveCardInfoBarDelegateMobile;
// shown at the bottom of the Infobar.
std::unique_ptr<infobars::InfoBar> CreateSaveCardInfoBarMobile(
std::unique_ptr<AutofillSaveCardInfoBarDelegateMobile> delegate,
- base::Optional<AccountInfo> accountInfo);
+ absl::optional<AccountInfo> accountInfo);
} // namespace autofill
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 0ca6a1d2065..00e638a006d 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
@@ -107,7 +107,7 @@ bool AutofillWalletModelTypeController::ShouldRunInTransportOnlyMode() const {
autofill::features::kAutofillEnableAccountWalletStorage)) {
return false;
}
- if (sync_service_->GetUserSettings()->IsUsingSecondaryPassphrase() &&
+ if (sync_service_->GetUserSettings()->IsUsingExplicitPassphrase() &&
!base::FeatureList::IsEnabled(
switches::kSyncAllowWalletDataInTransportModeWithCustomPassphrase)) {
return false;
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 8a016e00805..d1ba2b5bc7b 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
@@ -6,7 +6,6 @@
#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_AUTOFILL_WALLET_MODEL_TYPE_CONTROLLER_H_
#include <memory>
-#include <string>
#include "base/macros.h"
#include "components/prefs/pref_change_registrar.h"
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 eb7dbae6a4f..b7a9247c621 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
@@ -17,12 +17,11 @@
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
-#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_driver.h"
-#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h"
#include "components/autofill/core/browser/payments/payments_client.h"
@@ -45,12 +44,8 @@ constexpr int64_t kUnmaskDetailsResponseTimeoutMs = 3 * 1000; // 3 sec
// 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(kUnmaskDetailsResponseTimeoutMs));
-}
+// Suffix for server IDs in the cache indicating that a card is a virtual card.
+const char kVirtualCardIdentifier[] = "_vcn";
} // namespace
CreditCardAccessManager::CreditCardAccessManager(
@@ -63,9 +58,6 @@ CreditCardAccessManager::CreditCardAccessManager(
payments_client_(client_->GetPaymentsClient()),
personal_data_manager_(personal_data_manager),
form_event_logger_(form_event_logger),
- ready_to_start_authentication_(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
can_fetch_unmask_details_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::SIGNALED) {
}
@@ -112,6 +104,20 @@ bool CreditCardAccessManager::UnmaskedCardCacheIsEmpty() {
return unmasked_card_cache_.empty();
}
+std::vector<const CachedServerCardInfo*>
+CreditCardAccessManager::GetCachedUnmaskedCards() const {
+ std::vector<const CachedServerCardInfo*> unmasked_cards;
+ for (auto const& iter : unmasked_card_cache_) {
+ unmasked_cards.push_back(&iter.second);
+ }
+ return unmasked_cards;
+}
+
+bool CreditCardAccessManager::IsCardPresentInUnmaskedCache(
+ const std::string& server_id) const {
+ return unmasked_card_cache_.find(server_id) != unmasked_card_cache_.end();
+}
+
bool CreditCardAccessManager::ServerCardsAvailable() {
for (const CreditCard* credit_card : GetCreditCardsToSuggest()) {
if (!IsLocalCard(credit_card))
@@ -259,14 +265,19 @@ void CreditCardAccessManager::FetchCreditCard(
}
// If card has been previously unmasked, use cached data.
+ std::string identifier = card->record_type() == CreditCard::VIRTUAL_CARD
+ ? card->server_id() + kVirtualCardIdentifier
+ : card->server_id();
std::unordered_map<std::string, CachedServerCardInfo>::iterator it =
- unmasked_card_cache_.find(card->server_id());
+ unmasked_card_cache_.find(identifier);
if (it != unmasked_card_cache_.end()) { // key is in cache
accessor->OnCreditCardFetched(/*did_succeed=*/true,
/*credit_card=*/&it->second.card,
/*cvc=*/it->second.cvc);
- base::UmaHistogramCounts1000("Autofill.UsedCachedServerCard",
- ++it->second.cache_uses);
+ std::string metrics_name = card->record_type() == CreditCard::VIRTUAL_CARD
+ ? "Autofill.UsedCachedVirtualCard"
+ : "Autofill.UsedCachedServerCard";
+ base::UmaHistogramCounts1000(metrics_name, ++it->second.cache_uses);
return;
}
@@ -328,12 +339,10 @@ void CreditCardAccessManager::FetchCreditCard(
// Wait for |ready_to_start_authentication_| to be signaled by
// OnDidGetUnmaskDetails() or until timeout before calling Authenticate().
- auto task_runner = base::ThreadPool::CreateTaskRunner({base::MayBlock()});
- cancelable_authenticate_task_tracker_.PostTaskAndReplyWithResult(
- task_runner.get(), FROM_HERE,
- base::BindOnce(&WaitForEvent, &ready_to_start_authentication_),
+ ready_to_start_authentication_.OnEventOrTimeOut(
base::BindOnce(&CreditCardAccessManager::Authenticate,
- weak_ptr_factory_.GetWeakPtr()));
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kUnmaskDetailsResponseTimeoutMs));
} else {
Authenticate(get_unmask_details_returned);
}
@@ -370,9 +379,13 @@ void CreditCardAccessManager::SignalCanFetchUnmaskDetails() {
void CreditCardAccessManager::CacheUnmaskedCardInfo(const CreditCard& card,
const std::u16string& cvc) {
- DCHECK_EQ(card.record_type(), CreditCard::FULL_SERVER_CARD);
- CachedServerCardInfo card_info = {card, cvc, 0};
- unmasked_card_cache_[card.server_id()] = card_info;
+ DCHECK(card.record_type() == CreditCard::FULL_SERVER_CARD ||
+ card.record_type() == CreditCard::VIRTUAL_CARD);
+ std::string identifier = card.record_type() == CreditCard::VIRTUAL_CARD
+ ? card.server_id() + kVirtualCardIdentifier
+ : card.server_id();
+ CachedServerCardInfo card_info = {card, cvc, /*cache_uses=*/0};
+ unmasked_card_cache_[identifier] = card_info;
}
UnmaskAuthFlowType CreditCardAccessManager::GetAuthenticationType(
@@ -418,7 +431,7 @@ void CreditCardAccessManager::Authenticate(bool get_unmask_details_returned) {
card_selected_without_unmask_details_timestamp_.value());
AutofillMetrics::LogUserPerceivedLatencyOnCardSelectionTimedOut(
/*did_time_out=*/!get_unmask_details_returned);
- card_selected_without_unmask_details_timestamp_ = base::nullopt;
+ card_selected_without_unmask_details_timestamp_ = absl::nullopt;
}
unmask_auth_flow_type_ = GetAuthenticationType(get_unmask_details_returned);
@@ -496,7 +509,7 @@ void CreditCardAccessManager::OnCVCAuthenticationComplete(
// Store request options temporarily if given. They will be used for
// AdditionallyPerformFidoAuth.
- base::Optional<base::Value> request_options = base::nullopt;
+ absl::optional<base::Value> request_options = absl::nullopt;
if (unmask_details_.fido_request_options.has_value()) {
// For opted-in user (CVC then FIDO case), request options are returned in
// unmask detail response.
@@ -698,7 +711,6 @@ void CreditCardAccessManager::HandleDialogUserResponse(
case WebauthnDialogCallbackType::kVerificationCancelled:
// TODO(crbug.com/949269): Add tests and logging for canceling verify
// pending dialog.
- cancelable_authenticate_task_tracker_.TryCancelAll();
payments_client_->CancelRequest();
SignalCanFetchUnmaskDetails();
ready_to_start_authentication_.Reset();
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 28436a7dfd2..d1e3f84ecab 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
@@ -21,6 +21,7 @@
#include "components/autofill/core/browser/metrics/credit_card_form_event_logger.h"
#include "components/autofill/core/browser/payments/credit_card_cvc_authenticator.h"
#include "components/autofill/core/browser/payments/payments_client.h"
+#include "components/autofill/core/browser/payments/wait_for_signal_or_timeout.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#if !defined(OS_IOS)
@@ -29,7 +30,7 @@
namespace autofill {
-class AutofillManager;
+class BrowserAutofillManager;
enum class WebauthnDialogCallbackType;
// Flow type denotes which card unmask authentication method was used.
@@ -57,7 +58,7 @@ struct CachedServerCardInfo {
};
// Manages logic for accessing credit cards either stored locally or stored
-// with Google Payments. Owned by AutofillManager.
+// with Google Payments. Owned by BrowserAutofillManager.
#if defined(OS_IOS)
class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester {
#else
@@ -131,6 +132,14 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
// TODO(crbug/1069929): Add browsertests for this.
void CacheUnmaskedCardInfo(const CreditCard& card, const std::u16string& cvc);
+ // Return the info for the server cards present in the
+ // |unamsked_cards_cache_|.
+ std::vector<const CachedServerCardInfo*> GetCachedUnmaskedCards() const;
+
+ // Returns true if a |unmasked_cards_cache| contains an entry for the card
+ // with |server_id|.
+ bool IsCardPresentInUnmaskedCache(const std::string& server_id) const;
+
CreditCardCVCAuthenticator* GetOrCreateCVCAuthenticator();
#if !defined(OS_IOS)
@@ -143,7 +152,7 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
FRIEND_TEST_ALL_PREFIXES(CreditCardAccessManagerTest,
PreflightCallRateLimited);
friend class AutofillAssistantTest;
- friend class AutofillManagerTest;
+ friend class BrowserAutofillManagerTest;
friend class AutofillMetricsTest;
friend class CreditCardAccessManagerTest;
@@ -268,15 +277,15 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
base::TimeTicks preflight_call_timestamp_;
// Timestamp used for user-perceived latency metrics.
- base::Optional<base::TimeTicks>
- card_selected_without_unmask_details_timestamp_ = base::nullopt;
+ absl::optional<base::TimeTicks>
+ card_selected_without_unmask_details_timestamp_;
// Meant for histograms recorded in FullCardRequest.
base::TimeTicks form_parsed_timestamp_;
// Timestamp for when fido_authenticator_->IsUserVerifiable() is called.
- base::Optional<base::TimeTicks> is_user_verifiable_called_timestamp_ =
- base::nullopt;
+ absl::optional<base::TimeTicks> is_user_verifiable_called_timestamp_ =
+ absl::nullopt;
// Authenticators for card unmasking.
std::unique_ptr<CreditCardCVCAuthenticator> cvc_authenticator_;
@@ -294,11 +303,7 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
// Resets when PrepareToFetchCreditCard() is called, if not already reset.
// Signaled when OnDidGetUnmaskDetails() is called or after timeout.
// Authenticate() is called when signaled.
- base::WaitableEvent ready_to_start_authentication_;
-
- // Tracks the Authenticate() task that is signaled by
- // |ready_to_start_authentication_|, allowing it to be canceled if necessary.
- base::CancelableTaskTracker cancelable_authenticate_task_tracker_;
+ WaitForSignalOrTimeout ready_to_start_authentication_;
// Required to avoid any unnecessary preflight calls to Payments servers.
// Initial state is signaled. Resets when PrepareToFetchCreditCard() is
@@ -317,7 +322,7 @@ class CreditCardAccessManager : public CreditCardCVCAuthenticator::Requester,
// Set to true only if user has a verifying platform authenticator.
// e.g. Touch/Face ID, Windows Hello, Android fingerprint, etc., is available
// and enabled.
- base::Optional<bool> is_user_verifiable_;
+ absl::optional<bool> is_user_verifiable_;
// True only if currently waiting on unmask details. This avoids making
// unnecessary calls to payments.
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 57c84e78c77..aa18e5b4775 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
@@ -23,7 +23,6 @@
#include "base/stl_util.h"
#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"
@@ -44,7 +43,7 @@
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
-#include "components/autofill/core/browser/test_autofill_manager.h"
+#include "components/autofill/core/browser/test_browser_autofill_manager.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
@@ -81,10 +80,16 @@ namespace autofill {
namespace {
const char kTestGUID[] = "00000000-0000-0000-0000-000000000001";
+const char kTestGUID2[] = "00000000-0000-0000-0000-000000000002";
const char kTestNumber[] = "4234567890123456"; // Visa
-const char kTestCvc[] = "123";
+const char kTestNumber2[] = "5454545454545454";
+const char16_t kTestNumber16[] = u"4234567890123456";
+const char16_t kTestCvc16[] = u"123";
+const char kTestServerId[] = "server_id_1";
+const char kTestServerId2[] = "server_id_2";
#if !defined(OS_IOS)
+const char kTestCvc[] = "123";
// Base64 encoding of "This is a test challenge".
constexpr char kTestChallenge[] = "VGhpcyBpcyBhIHRlc3QgY2hhbGxlbmdl";
// Base64 encoding of "This is a test Credential ID".
@@ -138,8 +143,23 @@ class CreditCardAccessManagerTest : public testing::Test {
public:
CreditCardAccessManagerTest()
: task_environment_(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME,
base::test::TaskEnvironment::MainThreadType::DEFAULT,
- base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED) {
+ // Advance the mock clock to 2021-01-01, 00:00:00.000.
+ base::Time year_2021;
+ CHECK(base::Time::FromUTCExploded({.year = 2021,
+ .month = 1,
+ .day_of_week = 4,
+ .day_of_month = 1,
+ .hour = 0,
+ .minute = 0,
+ .second = 0,
+ .millisecond = 0},
+ &year_2021));
+ task_environment_.AdvanceClock(year_2021 -
+ task_environment_.GetMockClock()->Now());
+ }
void SetUp() override {
autofill_client_.SetPrefs(test::PrefServiceForTesting());
@@ -150,6 +170,7 @@ class CreditCardAccessManagerTest : public testing::Test {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
personal_data_manager_.SetPrefService(autofill_client_.GetPrefs());
autocomplete_history_manager_ =
@@ -165,14 +186,15 @@ class CreditCardAccessManagerTest : public testing::Test {
std::unique_ptr<payments::TestPaymentsClient>(payments_client_));
autofill_client_.set_test_strike_database(
std::make_unique<TestStrikeDatabase>());
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &autofill_client_, &personal_data_manager_,
autocomplete_history_manager_.get());
credit_card_access_manager_ =
- autofill_manager_->credit_card_access_manager();
+ browser_autofill_manager_->credit_card_access_manager();
#if !defined(OS_IOS)
- autofill_driver_->SetAutofillManager(std::move(autofill_manager_));
+ autofill_driver_->SetBrowserAutofillManager(
+ std::move(browser_autofill_manager_));
autofill_driver_->SetAuthenticator(new TestInternalAuthenticator());
credit_card_access_manager_->set_fido_authenticator_for_testing(
std::make_unique<TestCreditCardFIDOAuthenticator>(
@@ -197,7 +219,7 @@ class CreditCardAccessManagerTest : public testing::Test {
// Resets all variables related to credit card fetching.
credit_card_access_manager_->is_authentication_in_progress_ = false;
credit_card_access_manager_->can_fetch_unmask_details_.Signal();
- credit_card_access_manager_->is_user_verifiable_ = base::nullopt;
+ credit_card_access_manager_->is_user_verifiable_ = absl::nullopt;
}
void ClearCards() { personal_data_manager_.ClearCreditCards(); }
@@ -215,7 +237,8 @@ class CreditCardAccessManagerTest : public testing::Test {
void CreateServerCard(std::string guid,
std::string number = std::string(),
- bool masked = true) {
+ bool masked = true,
+ std::string server_id = std::string()) {
CreditCard server_card = CreditCard();
test::SetCreditCardInfo(&server_card, "Elvis Presley", number.c_str(),
test::NextMonth().c_str(), test::NextYear().c_str(),
@@ -223,7 +246,7 @@ class CreditCardAccessManagerTest : public testing::Test {
server_card.set_guid(guid);
server_card.set_record_type(masked ? CreditCard::MASKED_SERVER_CARD
: CreditCard::FULL_SERVER_CARD);
-
+ server_card.set_server_id(server_id);
personal_data_manager_.AddServerCreditCard(server_card);
}
@@ -231,7 +254,7 @@ class CreditCardAccessManagerTest : public testing::Test {
return credit_card_access_manager_->GetOrCreateCVCAuthenticator();
}
- void MockUserResponseForCvcAuth(std::string cvc, bool enable_fido) {
+ void MockUserResponseForCvcAuth(std::u16string cvc, bool enable_fido) {
payments::FullCardRequest* full_card_request =
GetCVCAuthenticator()->full_card_request_.get();
if (!full_card_request)
@@ -239,7 +262,7 @@ class CreditCardAccessManagerTest : public testing::Test {
// Mock user response.
payments::FullCardRequest::UserProvidedUnmaskDetails details;
- details.cvc = base::ASCIIToUTF16(cvc);
+ details.cvc = cvc;
#if defined(OS_ANDROID)
details.enable_fido_auth = enable_fido;
#endif
@@ -258,7 +281,7 @@ class CreditCardAccessManagerTest : public testing::Test {
if (!full_card_request)
return false;
- MockUserResponseForCvcAuth(kTestCvc, follow_with_fido_auth);
+ MockUserResponseForCvcAuth(kTestCvc16, follow_with_fido_auth);
payments::PaymentsClient::UnmaskResponseDetails response;
#if !defined(OS_IOS)
@@ -399,7 +422,7 @@ class CreditCardAccessManagerTest : public testing::Test {
TestPersonalDataManager personal_data_manager_;
std::unique_ptr<MockAutocompleteHistoryManager> autocomplete_history_manager_;
base::test::ScopedFeatureList scoped_feature_list_;
- std::unique_ptr<AutofillManager> autofill_manager_;
+ std::unique_ptr<BrowserAutofillManager> browser_autofill_manager_;
CreditCardAccessManager* credit_card_access_manager_;
};
@@ -483,7 +506,7 @@ TEST_F(CreditCardAccessManagerTest, FetchLocalCardSuccess) {
credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr());
EXPECT_TRUE(accessor_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
}
// Ensures that FetchCreditCard() reports a failure when a card does not exist.
@@ -516,8 +539,8 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardCVCSuccess) {
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
EXPECT_TRUE(accessor_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
histogram_tester.ExpectBucketCount(
flow_events_histogram_name,
@@ -569,8 +592,8 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardCVCTryAgainFailure) {
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
EXPECT_TRUE(accessor_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
}
// Ensures that CardUnmaskPreflightCalled metrics are logged correctly.
@@ -694,7 +717,7 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOSuccess) {
EXPECT_EQ(kCredentialId,
BytesToBase64(GetFIDOAuthenticator()->GetCredentialId()));
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
histogram_tester.ExpectUniqueSample(
unmask_decision_histogram_name,
@@ -746,8 +769,8 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOSuccessWithDcvv) {
// Expect accessor to successfully retrieve the DCVV.
EXPECT_TRUE(accessor_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
}
// Ensures that CVC prompt is invoked after WebAuthn fails.
@@ -795,8 +818,8 @@ TEST_F(CreditCardAccessManagerTest,
GetFIDOAuthenticator()->current_flow());
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
EXPECT_TRUE(accessor_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
histogram_tester.ExpectUniqueSample(
webauthn_result_histogram_name,
@@ -844,8 +867,8 @@ TEST_F(CreditCardAccessManagerTest,
GetFIDOAuthenticator()->current_flow());
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
EXPECT_TRUE(accessor_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
histogram_tester.ExpectUniqueSample(
histogram_name, AutofillMetrics::WebauthnResultMetric::kSuccess, 1);
@@ -880,8 +903,8 @@ TEST_F(CreditCardAccessManagerTest,
// Followed by a fallback to CVC.
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
EXPECT_TRUE(accessor_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
}
// Ensures that CVC prompt is invoked when the pre-flight call to Google
@@ -898,8 +921,8 @@ TEST_F(CreditCardAccessManagerTest, FetchServerCardFIDOTimeoutCVCFallback) {
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
EXPECT_TRUE(accessor_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
}
// Ensures the existence of user-perceived latency during the preflight call is
@@ -929,6 +952,7 @@ TEST_F(CreditCardAccessManagerTest,
ResetFetchCreditCard();
credit_card_access_manager_->PrepareToFetchCreditCard();
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
WaitForCallbacks();
credit_card_access_manager_->FetchCreditCard(local_card,
@@ -949,6 +973,7 @@ TEST_F(CreditCardAccessManagerTest,
credit_card_access_manager_->PrepareToFetchCreditCard();
credit_card_access_manager_->FetchCreditCard(server_card,
accessor_->GetWeakPtr());
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
@@ -1022,6 +1047,8 @@ TEST_F(CreditCardAccessManagerTest, Metrics_LoggingTimedOutCvcFallback) {
// Mock a delayed response.
InvokeDelayedGetUnmaskDetailsResponse();
+
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
@@ -1043,6 +1070,7 @@ TEST_F(CreditCardAccessManagerTest, Metrics_LoggingTimedOutCvcFallback) {
credit_card_access_manager_->PrepareToFetchCreditCard();
credit_card_access_manager_->FetchCreditCard(server_card,
accessor_->GetWeakPtr());
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(4));
WaitForCallbacks();
histogram_tester.ExpectUniqueSample(
@@ -1105,8 +1133,8 @@ TEST_F(CreditCardAccessManagerTest, FIDONewCardAuthorization) {
/*did_succeed=*/true);
// Ensure that form is filled after user verification (OnCreditCardFetched is
// called).
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
// Mock OptChange payments call.
OptChange(AutofillClient::SUCCESS, true);
@@ -1142,8 +1170,8 @@ TEST_F(CreditCardAccessManagerTest, FetchExpiredServerCardInvokesCvcPrompt) {
// Expect CVC prompt to be invoked.
EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber));
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
}
#if defined(OS_ANDROID)
@@ -1183,8 +1211,8 @@ TEST_F(CreditCardAccessManagerTest, FIDOOptInSuccess_Android) {
/*did_succeed=*/true);
// Ensure that form is filled after user verification (OnCreditCardFetched is
// called).
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
// Mock OptChange payments call.
OptChange(AutofillClient::SUCCESS, /*user_is_opted_in=*/true);
@@ -1232,8 +1260,8 @@ TEST_F(CreditCardAccessManagerTest, FIDOOptInUserVerificationFailure) {
// Ensure that form is still filled even if user verification fails
// (OnCreditCardFetched is called). Note that this is different behavior than
// registering a new card.
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
@@ -1271,8 +1299,8 @@ TEST_F(CreditCardAccessManagerTest, FIDOOptInServerFailure) {
/*did_succeed=*/true);
// Ensure that form is filled after user verification (OnCreditCardFetched is
// called).
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
OptChange(AutofillClient::PERMANENT_FAILURE, false);
EXPECT_FALSE(GetFIDOAuthenticator()->IsUserOptedIn());
@@ -1296,8 +1324,8 @@ TEST_F(CreditCardAccessManagerTest, FIDOOptIn_CheckboxDeclined) {
/*fido_opt_in=*/false,
/*follow_with_fido_auth=*/false));
// Ensure that form is filled (OnCreditCardFetched is called).
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), accessor_->number());
- EXPECT_EQ(ASCIIToUTF16(kTestCvc), accessor_->cvc());
+ EXPECT_EQ(kTestNumber16, accessor_->number());
+ EXPECT_EQ(kTestCvc16, accessor_->cvc());
// Check current flow to ensure CreditCardFIDOAuthenticator::Authorize is
// never called.
EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::NONE_FLOW,
@@ -1324,7 +1352,7 @@ TEST_F(CreditCardAccessManagerTest, FIDOSettingsPageOptInSuccess_Android) {
InvokeUnmaskDetailsTimeout();
WaitForCallbacks();
- MockUserResponseForCvcAuth(kTestCvc, /*enable_fido=*/false);
+ MockUserResponseForCvcAuth(kTestCvc16, /*enable_fido=*/false);
// Although the checkbox was hidden and |enable_fido_auth| was set to false in
// the user request, because of the previous opt-in intention, the client must
@@ -1842,8 +1870,8 @@ TEST_F(CreditCardAccessManagerTest, FetchCreditCardUsesUnmaskedCardCache) {
CreateServerCard(kTestGUID, kTestNumber, /*masked=*/false);
CreditCard* unmasked_card =
credit_card_access_manager_->GetCreditCard(kTestGUID);
- credit_card_access_manager_->CacheUnmaskedCardInfo(
- *unmasked_card, base::UTF8ToUTF16(kTestCvc));
+ credit_card_access_manager_->CacheUnmaskedCardInfo(*unmasked_card,
+ kTestCvc16);
CreateServerCard(kTestGUID, kTestNumber, /*masked=*/true);
CreditCard* masked_card =
@@ -1852,10 +1880,58 @@ TEST_F(CreditCardAccessManagerTest, FetchCreditCardUsesUnmaskedCardCache) {
credit_card_access_manager_->FetchCreditCard(masked_card,
accessor_->GetWeakPtr());
histogram_tester.ExpectBucketCount("Autofill.UsedCachedServerCard", 1, 1);
-
credit_card_access_manager_->FetchCreditCard(masked_card,
accessor_->GetWeakPtr());
histogram_tester.ExpectBucketCount("Autofill.UsedCachedServerCard", 2, 1);
+
+ // Create a virtual card.
+ CreditCard virtual_card = CreditCard();
+ test::SetCreditCardInfo(&virtual_card, "Elvis Presley", kTestNumber,
+ test::NextMonth().c_str(), test::NextYear().c_str(),
+ "1");
+ virtual_card.set_record_type(CreditCard::VIRTUAL_CARD);
+ credit_card_access_manager_->CacheUnmaskedCardInfo(virtual_card, kTestCvc16);
+
+ // Mocks that user selects the virtual card option of the masked card.
+ masked_card->set_record_type(CreditCard::VIRTUAL_CARD);
+ credit_card_access_manager_->FetchCreditCard(masked_card,
+ accessor_->GetWeakPtr());
+
+ histogram_tester.ExpectBucketCount("Autofill.UsedCachedVirtualCard", 1, 1);
+}
+
+TEST_F(CreditCardAccessManagerTest, GetCachedUnmaskedCards) {
+ // Assert that there are no cards cached initially.
+ EXPECT_EQ(0U, credit_card_access_manager_->GetCachedUnmaskedCards().size());
+
+ CreateServerCard(kTestGUID, kTestNumber, /*masked=*/false, kTestServerId);
+ CreateServerCard(kTestGUID2, kTestNumber2, /*masked=*/true, kTestServerId2);
+ // Add a card to the cache.
+ CreditCard* unmasked_card =
+ credit_card_access_manager_->GetCreditCard(kTestGUID);
+ credit_card_access_manager_->CacheUnmaskedCardInfo(*unmasked_card,
+ kTestCvc16);
+
+ // Verify that only the card added to the cache is returned.
+ ASSERT_EQ(1U, credit_card_access_manager_->GetCachedUnmaskedCards().size());
+ EXPECT_EQ(*unmasked_card,
+ credit_card_access_manager_->GetCachedUnmaskedCards()[0]->card);
+}
+
+TEST_F(CreditCardAccessManagerTest, IsCardPresentInUnmaskedCache) {
+ CreateServerCard(kTestGUID, kTestNumber, /*masked=*/false, kTestServerId);
+ CreateServerCard(kTestGUID2, kTestNumber2, /*masked=*/true, kTestServerId2);
+ // Add a card to the cache.
+ CreditCard* unmasked_card =
+ credit_card_access_manager_->GetCreditCard(kTestGUID);
+ credit_card_access_manager_->CacheUnmaskedCardInfo(*unmasked_card,
+ kTestCvc16);
+
+ // Verify that only one card is present in the cache.
+ EXPECT_TRUE(credit_card_access_manager_->IsCardPresentInUnmaskedCache(
+ unmasked_card->server_id()));
+ EXPECT_FALSE(credit_card_access_manager_->IsCardPresentInUnmaskedCache(
+ credit_card_access_manager_->GetCreditCard(kTestGUID2)->server_id()));
}
} // namespace autofill
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 42b4fa3a733..5036c381187 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
@@ -39,12 +39,12 @@ class CreditCardCVCAuthenticator
return *this;
}
CVCAuthenticationResponse& with_creation_options(
- base::Optional<base::Value> v) {
+ absl::optional<base::Value> v) {
creation_options = std::move(v);
return *this;
}
CVCAuthenticationResponse& with_request_options(
- base::Optional<base::Value> v) {
+ absl::optional<base::Value> v) {
request_options = std::move(v);
return *this;
}
@@ -55,8 +55,8 @@ class CreditCardCVCAuthenticator
bool did_succeed = false;
const CreditCard* card = nullptr;
std::u16string cvc = std::u16string();
- base::Optional<base::Value> creation_options = base::nullopt;
- base::Optional<base::Value> request_options = base::nullopt;
+ absl::optional<base::Value> creation_options;
+ absl::optional<base::Value> request_options;
std::string card_authorization_token = std::string();
};
class Requester {
@@ -116,7 +116,7 @@ class CreditCardCVCAuthenticator
private:
friend class AutofillAssistantTest;
- friend class AutofillManagerTest;
+ friend class BrowserAutofillManagerTest;
friend class AutofillMetricsTest;
friend class CreditCardAccessManagerTest;
friend class CreditCardCVCAuthenticatorTest;
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 af0930d6522..32d081726cc 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
@@ -22,7 +22,6 @@
#include "base/stl_util.h"
#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"
@@ -65,13 +64,12 @@
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
-using base::ASCIIToUTF16;
-
namespace autofill {
namespace {
const char kTestGUID[] = "00000000-0000-0000-0000-000000000001";
const char kTestNumber[] = "4234567890123456"; // Visa
+const char16_t kTestNumber16[] = u"4234567890123456";
} // namespace
@@ -88,6 +86,7 @@ class CreditCardCVCAuthenticatorTest : public testing::Test {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
personal_data_manager_.SetPrefService(autofill_client_.GetPrefs());
@@ -165,7 +164,7 @@ TEST_F(CreditCardCVCAuthenticatorTest, AuthenticateServerCardSuccess) {
OnDidGetRealPan(AutofillClient::SUCCESS, kTestNumber);
EXPECT_TRUE(requester_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), requester_->number());
+ EXPECT_EQ(kTestNumber16, requester_->number());
}
TEST_F(CreditCardCVCAuthenticatorTest, AuthenticateServerCardNetworkError) {
@@ -202,7 +201,7 @@ TEST_F(CreditCardCVCAuthenticatorTest, AuthenticateServerCardTryAgainFailure) {
OnDidGetRealPan(AutofillClient::SUCCESS, kTestNumber);
EXPECT_TRUE(requester_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), requester_->number());
+ EXPECT_EQ(kTestNumber16, requester_->number());
}
} // namespace autofill
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 897c4429b7a..fdf4a7984c2 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
@@ -582,7 +582,7 @@ CreditCardFIDOAuthenticator::ParseCreationOptions(
->GetPrimaryAccountInfo(signin::ConsentLevel::kSync)
.email;
- base::Optional<AccountInfo> account_info =
+ absl::optional<AccountInfo> account_info =
autofill_client_->GetIdentityManager()
->FindExtendedAccountInfoForAccountWithRefreshToken(
autofill_client_->GetPersonalDataManager()
@@ -659,7 +659,7 @@ CreditCardFIDOAuthenticator::ParseCredentialDescriptor(
"authenticator_transport_support", base::Value::Type::LIST);
if (transports && !transports->GetList().empty()) {
for (const base::Value& transport_type : transports->GetList()) {
- base::Optional<FidoTransportProtocol> protocol =
+ absl::optional<FidoTransportProtocol> protocol =
device::ConvertToFidoTransportProtocol(
base::ToLowerASCII(transport_type.GetString()));
if (protocol.has_value())
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 2846aaa461d..ac4ce6c9a5c 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
@@ -18,7 +18,7 @@
#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/authenticator.mojom.h"
+#include "third_party/blink/public/mojom/webauthn/authenticator.mojom-forward.h"
namespace autofill {
@@ -144,7 +144,7 @@ class CreditCardFIDOAuthenticator
Flow current_flow() { return current_flow_; }
private:
- friend class AutofillManagerTest;
+ friend class BrowserAutofillManagerTest;
friend class CreditCardAccessManagerTest;
friend class CreditCardFIDOAuthenticatorTest;
friend class TestCreditCardFIDOAuthenticator;
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 7a719920bd5..eae33666d34 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
@@ -22,7 +22,6 @@
#include "base/stl_util.h"
#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"
@@ -72,13 +71,12 @@
#include "components/autofill/core/browser/payments/payments_service_url.h"
-using base::ASCIIToUTF16;
-
namespace autofill {
namespace {
const char kTestGUID[] = "00000000-0000-0000-0000-000000000001";
const char kTestNumber[] = "4234567890123456"; // Visa
+const char16_t kTestNumber16[] = u"4234567890123456";
const char kTestRelyingPartyId[] = "google.com";
// Base64 encoding of "This is a test challenge".
constexpr char kTestChallenge[] = "VGhpcyBpcyBhIHRlc3QgY2hhbGxlbmdl";
@@ -117,6 +115,7 @@ class CreditCardFIDOAuthenticatorTest : public testing::Test {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
personal_data_manager_.SetPrefService(autofill_client_.GetPrefs());
@@ -457,7 +456,7 @@ TEST_F(CreditCardFIDOAuthenticatorTest, AuthenticateCard_Success) {
GetRealPan(AutofillClient::PaymentsRpcResult::SUCCESS, kTestNumber);
EXPECT_TRUE(requester_->did_succeed());
- EXPECT_EQ(ASCIIToUTF16(kTestNumber), requester_->number());
+ EXPECT_EQ(kTestNumber16, requester_->number());
}
TEST_F(CreditCardFIDOAuthenticatorTest, OptIn_PaymentsResponseError) {
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 0013bafed2b..aa9cda76fbe 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
@@ -32,14 +32,17 @@
#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/form_structure.h"
+#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/payments/payments_util.h"
-#include "components/autofill/core/browser/payments/strike_database.h"
#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/strike_database.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_clock.h"
#include "components/autofill/core/common/autofill_constants.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_payments_features.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/autofill/core/common/autofill_util.h"
@@ -949,6 +952,94 @@ void CreditCardSaveManager::LogCardUploadDecisions(
client_->GetUkmRecorder(), client_->GetUkmSourceId(),
pending_upload_request_origin_.GetURL(), upload_decision_metrics);
pending_upload_request_origin_ = url::Origin();
+ LogCardUploadDecisionsToAutofillInternals(upload_decision_metrics);
+}
+
+void CreditCardSaveManager::LogCardUploadDecisionsToAutofillInternals(
+ int upload_decision_metrics) {
+ LogManager* log_manager = client_->GetLogManager();
+ if (!log_manager)
+ return;
+
+ auto final_decision =
+ (upload_decision_metrics_ & AutofillMetrics::UPLOAD_OFFERED)
+ ? LogMessage::kCardUploadDecisionUploadOffered
+ : LogMessage::kCardUploadDecisionUploadNotOffered;
+
+ auto buffer = log_manager->Log();
+ buffer << LoggingScope::kCardUploadDecision << final_decision;
+ buffer << Tag{"div"} << Attrib{"class", "form"} << Tag{"tr"} << Tag{"td"}
+ << "Decision Metrics:" << CTag{"td"} << Tag{"td"} << Tag{"table"};
+
+ for (int i = 0; i < AutofillMetrics::kNumCardUploadDecisionMetrics; i++) {
+ AutofillMetrics::CardUploadDecisionMetric currentBitmaskValue =
+ static_cast<AutofillMetrics::CardUploadDecisionMetric>(1 << i);
+ if (!(upload_decision_metrics & currentBitmaskValue))
+ continue;
+
+ std::string result;
+ switch (currentBitmaskValue) {
+ case AutofillMetrics::UPLOAD_OFFERED:
+ result = "UPLOAD_OFFERED";
+ break;
+ case AutofillMetrics::CVC_FIELD_NOT_FOUND:
+ result = "CVC_FIELD_NOT_FOUND";
+ break;
+ case AutofillMetrics::CVC_VALUE_NOT_FOUND:
+ result = "CVC_VALUE_NOT_FOUND";
+ break;
+ case AutofillMetrics::INVALID_CVC_VALUE:
+ result = "INVALID_CVC_VALUE";
+ break;
+ case AutofillMetrics::FOUND_POSSIBLE_CVC_VALUE_IN_NON_CVC_FIELD:
+ result = "FOUND_POSSIBLE_CVC_VALUE_IN_NON_CVC_FIELD";
+ break;
+ case AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ADDRESS_PROFILE:
+ result = "UPLOAD_NOT_OFFERED_NO_ADDRESS_PROFILE";
+ break;
+ case AutofillMetrics::UPLOAD_NOT_OFFERED_NO_RECENTLY_USED_ADDRESS:
+ result = "UPLOAD_NOT_OFFERED_NO_RECENTLY_USED_ADDRESS";
+ break;
+ case AutofillMetrics::UPLOAD_NOT_OFFERED_NO_ZIP_CODE:
+ result = "UPLOAD_NOT_OFFERED_NO_ZIP_CODE";
+ break;
+ case AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_ZIPS:
+ result = "UPLOAD_NOT_OFFERED_CONFLICTING_ZIPS";
+ break;
+ case AutofillMetrics::UPLOAD_NOT_OFFERED_NO_NAME:
+ result = "UPLOAD_NOT_OFFERED_NO_NAME";
+ break;
+ case AutofillMetrics::UPLOAD_NOT_OFFERED_CONFLICTING_NAMES:
+ result = "UPLOAD_NOT_OFFERED_CONFLICTING_NAMES";
+ break;
+ case AutofillMetrics::UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED:
+ result = "UPLOAD_NOT_OFFERED_GET_UPLOAD_DETAILS_FAILED";
+ break;
+ case AutofillMetrics::USER_REQUESTED_TO_PROVIDE_CARDHOLDER_NAME:
+ result = "USER_REQUESTED_TO_PROVIDE_CARDHOLDER_NAME";
+ break;
+ case AutofillMetrics::UPLOAD_NOT_OFFERED_MAX_STRIKES_ON_MOBILE:
+ result = "UPLOAD_NOT_OFFERED_MAX_STRIKES_ON_MOBILE";
+ break;
+ case AutofillMetrics::USER_REQUESTED_TO_PROVIDE_EXPIRATION_DATE:
+ result = "USER_REQUESTED_TO_PROVIDE_EXPIRATION_DATE";
+ break;
+ case AutofillMetrics::UPLOAD_OFFERED_FROM_NON_FOCUSABLE_FIELD:
+ result = "UPLOAD_OFFERED_FROM_NON_FOCUSABLE_FIELD";
+ break;
+ case AutofillMetrics::UPLOAD_NOT_OFFERED_UNSUPPORTED_BIN_RANGE:
+ result = "UPLOAD_NOT_OFFERED_UNSUPPORTED_BIN_RANGE";
+ break;
+ case AutofillMetrics::UPLOAD_OFFERED_FROM_DYNAMIC_CHANGE_FORM:
+ result = "UPLOAD_OFFERED_FROM_DYNAMIC_CHANGE_FORM";
+ break;
+ case AutofillMetrics::UPLOAD_NOT_OFFERED_INVALID_LEGAL_MESSAGE:
+ result = "UPLOAD_NOT_OFFERED_INVALID_LEGAL_MESSAGE";
+ break;
+ }
+ buffer << Tr{} << result;
+ }
+ buffer << CTag{"table"} << CTag{"td"} << CTag{"tr"} << CTag{"div"};
}
void CreditCardSaveManager::LogSaveCardRequestExpirationDateReasonMetric() {
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 affdd8893b2..c1715660bc2 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
@@ -11,7 +11,6 @@
#include <utility>
#include <vector>
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_metrics.h"
@@ -22,6 +21,7 @@
#include "components/autofill/core/browser/payments/local_card_migration_strike_database.h"
#include "components/autofill/core/browser/payments/payments_client.h"
#include "components/autofill/core/browser/personal_data_manager.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
class SaveCardOfferObserver;
@@ -269,6 +269,9 @@ class CreditCardSaveManager {
// |AutofillMetrics::CardUploadDecisionMetric|.
void LogCardUploadDecisions(int upload_decision_metrics);
+ // Logs the card upload decisions bitmask to chrome://autofill-internals.
+ void LogCardUploadDecisionsToAutofillInternals(int upload_decision_metrics);
+
// Logs the reason why expiration date was explicitly requested.
void LogSaveCardRequestExpirationDateReasonMetric();
@@ -280,13 +283,13 @@ class CreditCardSaveManager {
AutofillClient* const client_;
// Handles Payments service requests.
- // Owned by AutofillManager.
+ // Owned by BrowserAutofillManager.
payments::PaymentsClient* payments_client_;
std::string app_locale_;
// The personal data manager, used to save and load personal data to/from the
- // web database. This is overridden by the AutofillManagerTest.
+ // web database. This is overridden by the BrowserAutofillManagerTest.
// Weak reference.
// May be NULL. NULL indicates OTR.
PersonalDataManager* personal_data_manager_;
@@ -303,8 +306,8 @@ class CreditCardSaveManager {
int upload_decision_metrics_ = 0;
// |true| if the offer-to-save bubble/infobar should pop-up, |false| if not.
- // Will be base::nullopt until data has been retrieved from the StrikeSystem.
- base::Optional<bool> show_save_prompt_;
+ // Will be absl::nullopt until data has been retrieved from the StrikeSystem.
+ absl::optional<bool> show_save_prompt_;
// |true| if the card being offered for upload is already a local card on the
// device; |false| otherwise.
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 6e56702b3b4..691ed980420 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
@@ -38,7 +38,7 @@
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
-#include "components/autofill/core/browser/test_autofill_manager.h"
+#include "components/autofill/core/browser/test_browser_autofill_manager.h"
#include "components/autofill/core/browser/test_form_data_importer.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/browser/validation.h"
@@ -113,8 +113,8 @@ struct CreditCardFormOptions {
class MockPersonalDataManager : public TestPersonalDataManager {
public:
- MockPersonalDataManager() {}
- ~MockPersonalDataManager() override {}
+ MockPersonalDataManager() = default;
+ ~MockPersonalDataManager() override = default;
MOCK_METHOD0(OnUserAcceptedUpstreamOffer, void());
};
@@ -133,6 +133,7 @@ class CreditCardSaveManagerTest : public testing::Test {
/*identity_manager=*/nullptr,
/*client_profile_validator=*/nullptr,
/*history_service=*/nullptr,
+ /*strike_database=*/nullptr,
/*is_off_the_record=*/false);
personal_data_.SetSyncServiceForTest(&sync_service_);
autocomplete_history_manager_.Init(
@@ -156,16 +157,16 @@ class CreditCardSaveManagerTest : public testing::Test {
autofill_client_.set_test_form_data_importer(
std::unique_ptr<TestFormDataImporter>(test_form_data_importer));
autofill_client_.GetStrikeDatabase();
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &autofill_client_, &personal_data_,
&autocomplete_history_manager_);
- autofill_manager_->SetExpectedObservedSubmission(true);
+ browser_autofill_manager_->SetExpectedObservedSubmission(true);
}
void TearDown() override {
- // Order of destruction is important as AutofillManager relies on
+ // Order of destruction is important as BrowserAutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
- autofill_manager_.reset();
+ browser_autofill_manager_.reset();
autofill_driver_.reset();
personal_data_.SetPrefService(nullptr);
@@ -173,11 +174,11 @@ class CreditCardSaveManagerTest : public testing::Test {
}
void FormsSeen(const std::vector<FormData>& forms) {
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
}
void FormSubmitted(const FormData& form) {
- autofill_manager_->OnFormSubmitted(
+ browser_autofill_manager_->OnFormSubmitted(
form, false, mojom::SubmissionSource::FORM_SUBMISSION);
}
@@ -339,7 +340,7 @@ class CreditCardSaveManagerTest : public testing::Test {
base::test::TaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
std::unique_ptr<TestAutofillDriver> autofill_driver_;
- std::unique_ptr<TestAutofillManager> autofill_manager_;
+ std::unique_ptr<TestBrowserAutofillManager> browser_autofill_manager_;
scoped_refptr<AutofillWebDataService> database_;
MockPersonalDataManager personal_data_;
MockAutocompleteHistoryManager autocomplete_history_manager_;
@@ -438,7 +439,7 @@ TEST_F(CreditCardSaveManagerTest, InvalidCreditCardNumberIsNotSaved) {
}
TEST_F(CreditCardSaveManagerTest, CreditCardDisabledDoesNotSave) {
- autofill_manager_->SetAutofillCreditCardEnabled(false);
+ browser_autofill_manager_->SetAutofillCreditCardEnabled(false);
// Create, fill and submit an address form in order to establish a recent
// profile which can be selected for the upload request.
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_save_strike_database.cc b/chromium/components/autofill/core/browser/payments/credit_card_save_strike_database.cc
index 438e7e594f3..8e42e62b75c 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_save_strike_database.cc
+++ b/chromium/components/autofill/core/browser/payments/credit_card_save_strike_database.cc
@@ -14,22 +14,23 @@ CreditCardSaveStrikeDatabase::CreditCardSaveStrikeDatabase(
RemoveExpiredStrikes();
}
-CreditCardSaveStrikeDatabase::~CreditCardSaveStrikeDatabase() {}
+CreditCardSaveStrikeDatabase::~CreditCardSaveStrikeDatabase() = default;
-std::string CreditCardSaveStrikeDatabase::GetProjectPrefix() {
+std::string CreditCardSaveStrikeDatabase::GetProjectPrefix() const {
return "CreditCardSave";
}
-int CreditCardSaveStrikeDatabase::GetMaxStrikesLimit() {
+int CreditCardSaveStrikeDatabase::GetMaxStrikesLimit() const {
return 3;
}
-base::Optional<int64_t> CreditCardSaveStrikeDatabase::GetExpiryTimeMicros() {
+absl::optional<base::TimeDelta>
+CreditCardSaveStrikeDatabase::GetExpiryTimeDelta() const {
// Expiry time is 6 months.
- return (int64_t)1000000 * 60 * 60 * 24 * 180;
+ return base::TimeDelta::FromDays(183);
}
-bool CreditCardSaveStrikeDatabase::UniqueIdsRequired() {
+bool CreditCardSaveStrikeDatabase::UniqueIdsRequired() const {
return true;
}
diff --git a/chromium/components/autofill/core/browser/payments/credit_card_save_strike_database.h b/chromium/components/autofill/core/browser/payments/credit_card_save_strike_database.h
index 6ce21bee328..4d58100a0c4 100644
--- a/chromium/components/autofill/core/browser/payments/credit_card_save_strike_database.h
+++ b/chromium/components/autofill/core/browser/payments/credit_card_save_strike_database.h
@@ -8,8 +8,8 @@
#include <stdint.h>
#include <string>
-#include "components/autofill/core/browser/payments/strike_database.h"
-#include "components/autofill/core/browser/payments/strike_database_integrator_base.h"
+#include "components/autofill/core/browser/strike_database.h"
+#include "components/autofill/core/browser/strike_database_integrator_base.h"
namespace autofill {
@@ -17,13 +17,13 @@ namespace autofill {
// local and upload).
class CreditCardSaveStrikeDatabase : public StrikeDatabaseIntegratorBase {
public:
- CreditCardSaveStrikeDatabase(StrikeDatabase* strike_database);
+ explicit CreditCardSaveStrikeDatabase(StrikeDatabase* strike_database);
~CreditCardSaveStrikeDatabase() override;
- std::string GetProjectPrefix() override;
- int GetMaxStrikesLimit() override;
- base::Optional<int64_t> GetExpiryTimeMicros() override;
- bool UniqueIdsRequired() override;
+ std::string GetProjectPrefix() const override;
+ int GetMaxStrikesLimit() const override;
+ absl::optional<base::TimeDelta> GetExpiryTimeDelta() const override;
+ bool UniqueIdsRequired() const override;
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.cc b/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.cc
index 08926ea170e..41c85091698 100644
--- a/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.cc
+++ b/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.cc
@@ -20,23 +20,23 @@ FidoAuthenticationStrikeDatabase::FidoAuthenticationStrikeDatabase(
RemoveExpiredStrikes();
}
-FidoAuthenticationStrikeDatabase::~FidoAuthenticationStrikeDatabase() {}
+FidoAuthenticationStrikeDatabase::~FidoAuthenticationStrikeDatabase() = default;
-std::string FidoAuthenticationStrikeDatabase::GetProjectPrefix() {
+std::string FidoAuthenticationStrikeDatabase::GetProjectPrefix() const {
return "FidoAuthentication";
}
-int FidoAuthenticationStrikeDatabase::GetMaxStrikesLimit() {
+int FidoAuthenticationStrikeDatabase::GetMaxStrikesLimit() const {
return 3;
}
-base::Optional<int64_t>
-FidoAuthenticationStrikeDatabase::GetExpiryTimeMicros() {
+absl::optional<base::TimeDelta>
+FidoAuthenticationStrikeDatabase::GetExpiryTimeDelta() const {
// Expiry time is six months.
- return (int64_t)1000000 * 60 * 60 * 24 * 30 * 6;
+ return base::TimeDelta::FromDays(183);
}
-bool FidoAuthenticationStrikeDatabase::UniqueIdsRequired() {
+bool FidoAuthenticationStrikeDatabase::UniqueIdsRequired() const {
return false;
}
diff --git a/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.h b/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.h
index 5ee994ea02e..2ca8ba5f4eb 100644
--- a/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.h
+++ b/chromium/components/autofill/core/browser/payments/fido_authentication_strike_database.h
@@ -8,8 +8,8 @@
#include <stdint.h>
#include <string>
-#include "components/autofill/core/browser/payments/strike_database.h"
-#include "components/autofill/core/browser/payments/strike_database_integrator_base.h"
+#include "components/autofill/core/browser/strike_database.h"
+#include "components/autofill/core/browser/strike_database_integrator_base.h"
namespace autofill {
@@ -17,7 +17,7 @@ namespace autofill {
// authentication for card unmasking.
class FidoAuthenticationStrikeDatabase : public StrikeDatabaseIntegratorBase {
public:
- FidoAuthenticationStrikeDatabase(StrikeDatabase* strike_database);
+ explicit FidoAuthenticationStrikeDatabase(StrikeDatabase* strike_database);
~FidoAuthenticationStrikeDatabase() override;
// Strikes to add when user declines opt-in offer.
@@ -28,10 +28,10 @@ class FidoAuthenticationStrikeDatabase : public StrikeDatabaseIntegratorBase {
// Strikes to add when user opts-out from settings page.
static const int kStrikesToAddWhenUserOptsOut;
- std::string GetProjectPrefix() override;
- int GetMaxStrikesLimit() override;
- base::Optional<int64_t> GetExpiryTimeMicros() override;
- bool UniqueIdsRequired() override;
+ std::string GetProjectPrefix() const override;
+ int GetMaxStrikesLimit() const override;
+ absl::optional<base::TimeDelta> GetExpiryTimeDelta() const override;
+ bool UniqueIdsRequired() const override;
};
} // namespace autofill
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 11354c420df..6db87391a9a 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request.cc
+++ b/chromium/components/autofill/core/browser/payments/full_card_request.cc
@@ -55,7 +55,7 @@ void FullCardRequest::GetFullCard(const CreditCard& card,
base::WeakPtr<UIDelegate> ui_delegate) {
DCHECK(ui_delegate);
GetFullCard(card, reason, result_delegate, ui_delegate,
- /*fido_assertion_info=*/base::nullopt);
+ /*fido_assertion_info=*/absl::nullopt);
}
void FullCardRequest::GetFullCardViaFIDO(
@@ -73,7 +73,7 @@ void FullCardRequest::GetFullCard(
AutofillClient::UnmaskCardReason reason,
base::WeakPtr<ResultDelegate> result_delegate,
base::WeakPtr<UIDelegate> ui_delegate,
- base::Optional<base::Value> fido_assertion_info) {
+ absl::optional<base::Value> fido_assertion_info) {
// Retrieval of card information should happen via CVC auth or FIDO, but not
// both. Use |ui_delegate|'s existence as evidence of doing CVC auth and
// |fido_assertion_info| as evidence of doing FIDO auth.
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 fa41ba8cd10..33d92a0ada5 100644
--- a/chromium/components/autofill/core/browser/payments/full_card_request.h
+++ b/chromium/components/autofill/core/browser/payments/full_card_request.h
@@ -18,7 +18,7 @@
namespace autofill {
-class AutofillManagerTest;
+class BrowserAutofillManagerTest;
class AutofillMetricsTest;
class CreditCardAccessManagerTest;
class CreditCardCVCAuthenticatorTest;
@@ -143,7 +143,7 @@ class FullCardRequest final : public CardUnmaskDelegate {
}
private:
- friend class autofill::AutofillManagerTest;
+ friend class autofill::BrowserAutofillManagerTest;
friend class autofill::AutofillMetricsTest;
friend class autofill::CreditCardAccessManagerTest;
friend class autofill::CreditCardCVCAuthenticatorTest;
@@ -163,7 +163,7 @@ class FullCardRequest final : public CardUnmaskDelegate {
AutofillClient::UnmaskCardReason reason,
base::WeakPtr<ResultDelegate> result_delegate,
base::WeakPtr<UIDelegate> ui_delegate,
- base::Optional<base::Value> fido_assertion_info);
+ absl::optional<base::Value> fido_assertion_info);
// CardUnmaskDelegate:
void OnUnmaskPromptAccepted(
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 5f756f7e621..bae3894714e 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
@@ -164,7 +164,7 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCardViaCvc) {
OnFullCardRequestSucceeded(
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
@@ -189,7 +189,7 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndDcvvForMaskedServerCardViaDcvv) {
OnFullCardRequestSucceeded(
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
- base::ASCIIToUTF16("321")));
+ testing::Eq(u"321")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
@@ -214,7 +214,7 @@ TEST_F(FullCardRequestTest, GetFullCardPanForMaskedServerCardWithoutDcvv) {
OnFullCardRequestSucceeded(
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
@@ -239,7 +239,7 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndUseCvcInUnmaskResponse) {
OnFullCardRequestSucceeded(
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
- base::ASCIIToUTF16("321")));
+ testing::Eq(u"321")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
@@ -264,7 +264,7 @@ TEST_F(FullCardRequestTest, GetFullCardPanWithoutCvcInUnmaskResponse) {
OnFullCardRequestSucceeded(
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
@@ -282,11 +282,11 @@ TEST_F(FullCardRequestTest, GetFullCardPanWithoutCvcInUnmaskResponse) {
// Verify getting the full PAN for a masked server card.
TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForMaskedServerCardViaFido) {
- EXPECT_CALL(*result_delegate(),
- OnFullCardRequestSucceeded(
- testing::Ref(*request()),
- CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
- base::ASCIIToUTF16("")));
+ EXPECT_CALL(
+ *result_delegate(),
+ OnFullCardRequestSucceeded(
+ testing::Ref(*request()),
+ CardMatches(CreditCard::FULL_SERVER_CARD, "4111"), testing::Eq(u"")));
request()->GetFullCardViaFIDO(
CreditCard(CreditCard::MASKED_SERVER_CARD, "server_id"),
@@ -301,7 +301,7 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForLocalCard) {
*result_delegate(),
OnFullCardRequestSucceeded(testing::Ref(*request()),
CardMatches(CreditCard::LOCAL_CARD, "4111"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
@@ -323,7 +323,7 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForFullServerCard) {
OnFullCardRequestSucceeded(
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
@@ -348,7 +348,7 @@ TEST_F(FullCardRequestTest,
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD,
"4111", "12", "2051"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*personal_data(), UpdateServerCreditCard(_)).Times(0);
EXPECT_CALL(*ui_delegate(),
@@ -377,7 +377,7 @@ TEST_F(FullCardRequestTest, GetFullCardPanAndCvcForExpiredFullServerCard) {
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD,
"4111", "12", "2051"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*personal_data(), UpdateServerCreditCard(_)).Times(0);
EXPECT_CALL(*ui_delegate(),
@@ -427,7 +427,7 @@ TEST_F(FullCardRequestTest, SecondRequestOkAfterFirstFinished) {
*result_delegate(),
OnFullCardRequestSucceeded(testing::Ref(*request()),
CardMatches(CreditCard::LOCAL_CARD, "4111"),
- base::ASCIIToUTF16("123")))
+ testing::Eq(u"123")))
.Times(2);
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _)).Times(2);
EXPECT_CALL(*ui_delegate(),
@@ -538,7 +538,7 @@ TEST_F(FullCardRequestTest, TryAgainFailureRetry) {
OnFullCardRequestSucceeded(
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::TRY_AGAIN_FAILURE));
@@ -565,7 +565,7 @@ TEST_F(FullCardRequestTest, UpdateExpDateForMaskedServerCard) {
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD,
"4111", "12", "2050"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
@@ -589,7 +589,7 @@ TEST_F(FullCardRequestTest, UpdateExpDateForFullServerCard) {
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD,
"4111", "12", "2050"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
@@ -615,7 +615,7 @@ TEST_F(FullCardRequestTest, UpdateExpDateForLocalCard) {
OnFullCardRequestSucceeded(
testing::Ref(*request()),
CardMatches(CreditCard::LOCAL_CARD, "4111", "12", "2051"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*personal_data(),
UpdateCreditCard(
@@ -646,7 +646,7 @@ TEST_F(FullCardRequestTest, SaveRealPan) {
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD,
"4111", "12", "2050"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*personal_data(),
UpdateServerCreditCard(CardMatches(CreditCard::FULL_SERVER_CARD,
@@ -674,7 +674,7 @@ TEST_F(FullCardRequestTest, UnmaskForPaymentRequest) {
OnFullCardRequestSucceeded(
testing::Ref(*request()),
CardMatches(CreditCard::FULL_SERVER_CARD, "4111"),
- base::ASCIIToUTF16("123")));
+ testing::Eq(u"123")));
EXPECT_CALL(*ui_delegate(), ShowUnmaskPrompt(_, _, _));
EXPECT_CALL(*ui_delegate(),
OnUnmaskVerificationResult(AutofillClient::SUCCESS));
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 1234667a475..1c4cfcccdb9 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
@@ -308,7 +308,7 @@ class LegalMessageLineTest : public ::testing::TestWithParam<int> {
// Verifies that legal message parsing is correct.
TEST_P(LegalMessageLineTest, Parsing) {
const TestCase& test_case = TestCaseData()[GetParam()];
- base::Optional<base::Value> value(
+ absl::optional<base::Value> value(
base::JSONReader::Read(test_case.message_json));
ASSERT_TRUE(value);
ASSERT_TRUE(value->is_dict());
diff --git a/chromium/components/autofill/core/browser/payments/local_card_migration_manager.h b/chromium/components/autofill/core/browser/payments/local_card_migration_manager.h
index 9604d5debe3..d90bc79f818 100644
--- a/chromium/components/autofill/core/browser/payments/local_card_migration_manager.h
+++ b/chromium/components/autofill/core/browser/payments/local_card_migration_manager.h
@@ -168,7 +168,7 @@ class LocalCardMigrationManager {
AutofillClient* const client_;
// Handles Payments service requests.
- // Owned by AutofillManager.
+ // Owned by BrowserAutofillManager.
payments::PaymentsClient* payments_client_;
private:
@@ -216,13 +216,13 @@ class LocalCardMigrationManager {
std::string app_locale_;
// The personal data manager, used to save and load personal data to/from the
- // web database. This is overridden by the AutofillManagerTest.
+ // web database. This is overridden by the BrowserAutofillManagerTest.
// Weak reference.
// May be NULL. NULL indicates OTR.
PersonalDataManager* personal_data_manager_;
// The imported credit card number from the form submission.
- base::Optional<std::u16string> imported_credit_card_number_;
+ absl::optional<std::u16string> imported_credit_card_number_;
// The imported credit card record type from the form submission.
int imported_credit_card_record_type_;
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 ef074d4b21b..5bf60a7c721 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
@@ -37,7 +37,7 @@
#include "components/autofill/core/browser/test_autofill_client.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/test_autofill_driver.h"
-#include "components/autofill/core/browser/test_autofill_manager.h"
+#include "components/autofill/core/browser/test_browser_autofill_manager.h"
#include "components/autofill/core/browser/test_form_data_importer.h"
#include "components/autofill/core/browser/test_personal_data_manager.h"
#include "components/autofill/core/browser/validation.h"
@@ -93,16 +93,16 @@ class LocalCardMigrationManagerTest : public testing::Test {
local_card_migration_manager_));
autofill_client_.set_test_form_data_importer(
std::unique_ptr<TestFormDataImporter>(test_form_data_importer));
- autofill_manager_ = std::make_unique<TestAutofillManager>(
+ browser_autofill_manager_ = std::make_unique<TestBrowserAutofillManager>(
autofill_driver_.get(), &autofill_client_, &personal_data_,
&autocomplete_history_manager_);
- autofill_manager_->SetExpectedObservedSubmission(true);
+ browser_autofill_manager_->SetExpectedObservedSubmission(true);
}
void TearDown() override {
- // Order of destruction is important as AutofillManager relies on
+ // Order of destruction is important as BrowserAutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
- autofill_manager_.reset();
+ browser_autofill_manager_.reset();
autofill_driver_.reset();
personal_data_.SetPrefService(nullptr);
@@ -110,11 +110,11 @@ class LocalCardMigrationManagerTest : public testing::Test {
}
void FormsSeen(const std::vector<FormData>& forms) {
- autofill_manager_->OnFormsSeen(forms);
+ browser_autofill_manager_->OnFormsSeen(forms);
}
void FormSubmitted(const FormData& form) {
- autofill_manager_->OnFormSubmitted(
+ browser_autofill_manager_->OnFormSubmitted(
form, false, mojom::SubmissionSource::FORM_SUBMISSION);
}
@@ -138,13 +138,13 @@ class LocalCardMigrationManagerTest : public testing::Test {
const char* expiration_month,
const char* expiration_year,
const std::string& billing_address_id,
- const std::string& guid) {
+ const base::GUID& guid) {
CreditCard local_card;
test::SetCreditCardInfo(&local_card, name_on_card, card_number,
expiration_month, expiration_year,
billing_address_id);
local_card.set_record_type(CreditCard::LOCAL_CARD);
- local_card.set_guid(guid);
+ local_card.set_guid(guid.AsLowercaseString());
personal_data.AddCreditCard(local_card);
}
@@ -173,11 +173,13 @@ class LocalCardMigrationManagerTest : public testing::Test {
// Add a local credit card (but it will not match what we will enter below).
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card (but it will not match what we will enter
// below).
AddLocalCreditCard(personal_data_, "Flo Master", "4444333322221111", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -199,10 +201,12 @@ class LocalCardMigrationManagerTest : public testing::Test {
// Add a local credit card whose |TypeAndLastFourDigits| matches what we
// will enter below.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card.
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -224,13 +228,16 @@ class LocalCardMigrationManagerTest : public testing::Test {
// Add a local credit card whose |TypeAndLastFourDigits| matches what we
// will enter below.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add other invalid local credit cards (invalid card number or expired), so
// it will not trigger migration.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111112", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::LastYear().c_str(), "1", "guid3");
+ test::LastYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -259,7 +266,8 @@ class LocalCardMigrationManagerTest : public testing::Test {
personal_data_.AddServerCreditCard(credit_card);
// Add one valid local credit card, so it will trigger migration
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -289,9 +297,11 @@ class LocalCardMigrationManagerTest : public testing::Test {
// Add other invalid local credit cards (invalid card number or expired), so
// it will not trigger migration.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111112", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::LastYear().c_str(), "1", "guid2");
+ test::LastYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -308,7 +318,7 @@ class LocalCardMigrationManagerTest : public testing::Test {
base::test::TaskEnvironment task_environment_;
TestAutofillClient autofill_client_;
std::unique_ptr<TestAutofillDriver> autofill_driver_;
- std::unique_ptr<TestAutofillManager> autofill_manager_;
+ std::unique_ptr<TestBrowserAutofillManager> browser_autofill_manager_;
TestPersonalDataManager personal_data_;
MockAutocompleteHistoryManager autocomplete_history_manager_;
syncer::TestSyncService sync_service_;
@@ -334,7 +344,8 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card whose |TypeAndLastFourDigits| matches what we will
// enter below.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -416,10 +427,12 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_NoPaymentsAccount) {
// Add a local credit card whose |TypeAndLastFourDigits| matches what we will
// enter below.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card.
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -452,10 +465,12 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local card whose |TypeAndLastFourDigits| matches a masked server
// card.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -485,10 +500,12 @@ TEST_F(LocalCardMigrationManagerTest,
personal_data_.AddServerCreditCard(server_card);
// Add a local credit card whose number matches a full server card.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -512,10 +529,12 @@ TEST_F(LocalCardMigrationManagerTest, GetDetectedValues_AllWithCardHolderName) {
// Add a local credit card whose |TypeAndLastFourDigits| matches what we will
// enter below.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card with a different cardholder name.
AddLocalCreditCard(personal_data_, "John Smith", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -543,10 +562,12 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card whose |TypeAndLastFourDigits| matches what we will
// enter below.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card without card holder name.
AddLocalCreditCard(personal_data_, "", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
test::CreateTestCreditCardFormData(&credit_card_form, true, false);
@@ -605,7 +626,8 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card. One migratable credit card will still trigger
// migration on settings page.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Do the same operation as we bridge back from the settings page.
local_card_migration_manager_->GetMigratableCreditCards();
@@ -632,7 +654,8 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card. One migratable credit card will still trigger
// migration on settings page.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Do the same operation as we bridge back from the settings page.
local_card_migration_manager_->GetMigratableCreditCards();
@@ -663,7 +686,8 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_MigrationSuccess) {
// Add a local credit card for migration.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Verify that it exists in the local database.
EXPECT_TRUE(personal_data_.GetCreditCardByNumber("4111111111111111"));
@@ -704,7 +728,8 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card. One migratable credit card will still trigger
// migration on settings page.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Verify that it exists in local database.
EXPECT_TRUE(personal_data_.GetCreditCardByNumber("4111111111111111"));
@@ -746,7 +771,8 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card. One migratable credit card will still trigger
// migration on settings page.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Verify that it exists in local database.
EXPECT_TRUE(personal_data_.GetCreditCardByNumber("4111111111111111"));
@@ -778,10 +804,14 @@ TEST_F(LocalCardMigrationManagerTest,
// Verify selected cards are correctly passed to manager.
TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_ToggleIsChosen) {
+ const base::GUID guid1 = base::GUID::GenerateRandomV4();
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1", guid1);
+
+ const base::GUID guid2 = base::GUID::GenerateRandomV4();
AddLocalCreditCard(personal_data_, "Flo Master", "5454545454545454", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1", guid2);
+
// Set the billing_customer_number to designate existence of a Payments
// account.
personal_data_.SetPaymentsCustomerData(
@@ -790,7 +820,7 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_ToggleIsChosen) {
local_card_migration_manager_->GetMigratableCreditCards();
autofill_client_.set_migration_card_selections(
- std::vector<std::string>{"guid1"});
+ std::vector<std::string>{guid1.AsLowercaseString()});
local_card_migration_manager_->AttemptToOfferLocalCardMigration(true);
EXPECT_EQ(static_cast<int>(
@@ -799,19 +829,21 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_ToggleIsChosen) {
EXPECT_EQ(local_card_migration_manager_->migratable_credit_cards_[0]
.credit_card()
.guid(),
- "guid1");
+ guid1.AsLowercaseString());
}
TEST_F(LocalCardMigrationManagerTest, DeleteLocalCardViaMigrationDialog) {
+ const base::GUID guid = base::GUID::GenerateRandomV4();
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1", guid);
- EXPECT_TRUE(personal_data_.GetCreditCardWithGUID("guid1"));
+ const std::string guid_str = guid.AsLowercaseString();
+ EXPECT_TRUE(personal_data_.GetCreditCardWithGUID(guid_str.c_str()));
local_card_migration_manager_->OnUserDeletedLocalCardViaMigrationDialog(
- "guid1");
+ guid_str);
- EXPECT_FALSE(personal_data_.GetCreditCardWithGUID("guid1"));
+ EXPECT_FALSE(personal_data_.GetCreditCardWithGUID(guid_str.c_str()));
}
// Use one local card with more valid local cards available, don't show prompt
@@ -867,10 +899,14 @@ TEST_F(LocalCardMigrationManagerTest,
// When local card migration is accepted, UMA metrics for LocalCardMigration
// strike count is logged.
TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_StrikeCountUMALogged) {
+ const base::GUID guid1 = base::GUID::GenerateRandomV4();
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1", guid1);
+
+ const base::GUID guid2 = base::GUID::GenerateRandomV4();
AddLocalCreditCard(personal_data_, "Flo Master", "5454545454545454", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1", guid2);
+
// Set the billing_customer_number to designate existence of a Payments
// account.
personal_data_.SetPaymentsCustomerData(
@@ -886,8 +922,8 @@ TEST_F(LocalCardMigrationManagerTest, MigrateCreditCard_StrikeCountUMALogged) {
base::HistogramTester histogram_tester;
// Select the cards.
- autofill_client_.set_migration_card_selections(
- std::vector<std::string>{"guid1", "guid2"});
+ autofill_client_.set_migration_card_selections(std::vector<std::string>{
+ guid1.AsLowercaseString(), guid2.AsLowercaseString()});
local_card_migration_manager_->AttemptToOfferLocalCardMigration(true);
// Verify that the strike count was logged when card migration accepted.
@@ -908,10 +944,12 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card whose |TypeAndLastFourDigits| matches what we will
// enter below.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card.
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -943,10 +981,12 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card whose |TypeAndLastFourDigits| matches what we will
// enter below.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card.
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up the supported card bin ranges so that the used local card is the
// only supported card.
@@ -993,7 +1033,8 @@ TEST_F(
personal_data_.AddServerCreditCard(credit_card);
// Add one valid local credit card, so it will trigger migration
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up the supported card bin ranges so that the used server card is
// unsupported but the one left is supported.
@@ -1033,7 +1074,8 @@ TEST_F(
personal_data_.AddServerCreditCard(credit_card);
// Add one valid local credit card, so it will trigger migration
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up the supported card bin ranges so that the used server card is
// supported while the one left is unsupported.
@@ -1140,7 +1182,8 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card. One migratable credit card will still trigger
// migration on settings page.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
base::HistogramTester histogram_tester;
// Do the same operation as we bridge back from the settings page.
@@ -1183,10 +1226,12 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card whose |TypeAndLastFourDigits| matches what we will
// enter below.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card.
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up our credit card form data.
FormData credit_card_form;
@@ -1277,10 +1322,12 @@ TEST_F(LocalCardMigrationManagerTest,
// Add a local credit card whose |TypeAndLastFourDigits| matches what we will
// enter below.
AddLocalCreditCard(personal_data_, "Flo Master", "4111111111111111", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Add another local credit card.
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid2");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
base::HistogramTester histogram_tester;
// Set up our credit card form data.
@@ -1323,7 +1370,8 @@ TEST_F(LocalCardMigrationManagerTest,
personal_data_.AddServerCreditCard(credit_card);
// Add one valid local credit card, so it will trigger migration
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up the supported card bin ranges so that the used server card is
// supported while the one left is unsupported.
@@ -1366,7 +1414,8 @@ TEST_F(LocalCardMigrationManagerTest,
personal_data_.AddServerCreditCard(credit_card);
// Add one valid local credit card, so it will trigger migration
AddLocalCreditCard(personal_data_, "Flo Master", "5555555555554444", "11",
- test::NextYear().c_str(), "1", "guid1");
+ test::NextYear().c_str(), "1",
+ base::GUID::GenerateRandomV4());
// Set up the supported card bin ranges so that the used server card and local
// cards are all unsupported.
diff --git a/chromium/components/autofill/core/browser/payments/local_card_migration_strike_database.cc b/chromium/components/autofill/core/browser/payments/local_card_migration_strike_database.cc
index f277e8944b4..5526f050912 100644
--- a/chromium/components/autofill/core/browser/payments/local_card_migration_strike_database.cc
+++ b/chromium/components/autofill/core/browser/payments/local_card_migration_strike_database.cc
@@ -20,25 +20,25 @@ LocalCardMigrationStrikeDatabase::LocalCardMigrationStrikeDatabase(
RemoveExpiredStrikes();
}
-LocalCardMigrationStrikeDatabase::~LocalCardMigrationStrikeDatabase() {}
+LocalCardMigrationStrikeDatabase::~LocalCardMigrationStrikeDatabase() = default;
-std::string LocalCardMigrationStrikeDatabase::GetProjectPrefix() {
+std::string LocalCardMigrationStrikeDatabase::GetProjectPrefix() const {
return "LocalCardMigration";
}
-int LocalCardMigrationStrikeDatabase::GetMaxStrikesLimit() {
+int LocalCardMigrationStrikeDatabase::GetMaxStrikesLimit() const {
return 6;
}
-base::Optional<int64_t>
-LocalCardMigrationStrikeDatabase::GetExpiryTimeMicros() {
+absl::optional<base::TimeDelta>
+LocalCardMigrationStrikeDatabase::GetExpiryTimeDelta() const {
// Ideally, we should be able to annotate cards deselected at migration time
// as cards the user is not interested in uploading. Until then, we have been
// asked to not expire local card migration strikes.
- return base::nullopt;
+ return absl::nullopt;
}
-bool LocalCardMigrationStrikeDatabase::UniqueIdsRequired() {
+bool LocalCardMigrationStrikeDatabase::UniqueIdsRequired() const {
return false;
}
diff --git a/chromium/components/autofill/core/browser/payments/local_card_migration_strike_database.h b/chromium/components/autofill/core/browser/payments/local_card_migration_strike_database.h
index 5f732c05928..c689c8404ec 100644
--- a/chromium/components/autofill/core/browser/payments/local_card_migration_strike_database.h
+++ b/chromium/components/autofill/core/browser/payments/local_card_migration_strike_database.h
@@ -8,15 +8,15 @@
#include <stdint.h>
#include <string>
-#include "components/autofill/core/browser/payments/strike_database.h"
-#include "components/autofill/core/browser/payments/strike_database_integrator_base.h"
+#include "components/autofill/core/browser/strike_database.h"
+#include "components/autofill/core/browser/strike_database_integrator_base.h"
namespace autofill {
// Implementation of StrikeDatabaseIntegratorBase for local card migrations.
class LocalCardMigrationStrikeDatabase : public StrikeDatabaseIntegratorBase {
public:
- LocalCardMigrationStrikeDatabase(StrikeDatabase* strike_database);
+ explicit LocalCardMigrationStrikeDatabase(StrikeDatabase* strike_database);
~LocalCardMigrationStrikeDatabase() override;
// Strikes to remove when user adds new local card.
@@ -29,10 +29,10 @@ class LocalCardMigrationStrikeDatabase : public StrikeDatabaseIntegratorBase {
// migration.
static const int kStrikesToAddWhenCardsDeselectedAtMigration;
- std::string GetProjectPrefix() override;
- int GetMaxStrikesLimit() override;
- base::Optional<int64_t> GetExpiryTimeMicros() override;
- bool UniqueIdsRequired() override;
+ std::string GetProjectPrefix() const override;
+ int GetMaxStrikesLimit() const override;
+ absl::optional<base::TimeDelta> GetExpiryTimeDelta() const override;
+ bool UniqueIdsRequired() const override;
};
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.cc b/chromium/components/autofill/core/browser/payments/payments_client.cc
index 80a30d17034..e74170961e6 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client.cc
@@ -1269,7 +1269,7 @@ void PaymentsClient::OnSimpleLoaderCompleteInternal(int response_code,
// Valid response.
case net::HTTP_OK: {
std::string error_code;
- base::Optional<base::Value> message_value = base::JSONReader::Read(data);
+ absl::optional<base::Value> message_value = base::JSONReader::Read(data);
if (message_value && message_value->is_dict()) {
const auto* found = message_value->FindPathOfType(
{"error", "code"}, base::Value::Type::STRING);
diff --git a/chromium/components/autofill/core/browser/payments/payments_client.h b/chromium/components/autofill/core/browser/payments/payments_client.h
index 3fc99c7b258..c40ffa24f17 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client.h
+++ b/chromium/components/autofill/core/browser/payments/payments_client.h
@@ -8,11 +8,13 @@
#include <set>
#include <string>
#include <utility>
+#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/values.h"
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
@@ -20,6 +22,7 @@
#include "components/signin/public/identity_manager/access_token_fetcher.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "google_apis/gaia/google_service_auth_error.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace signin {
class IdentityManager;
@@ -83,7 +86,7 @@ class PaymentsClient {
bool offer_fido_opt_in = false;
// Public Key Credential Request Options required for authentication.
// https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialrequestoptions
- base::Optional<base::Value> fido_request_options = base::nullopt;
+ absl::optional<base::Value> fido_request_options;
// Set of credit cards ids that are eligible for FIDO Authentication.
std::set<std::string> fido_eligible_card_ids;
};
@@ -100,7 +103,7 @@ class PaymentsClient {
CreditCard card;
std::string risk_data;
CardUnmaskDelegate::UserProvidedUnmaskDetails user_response;
- base::Optional<base::Value> fido_assertion_info = base::nullopt;
+ absl::optional<base::Value> fido_assertion_info;
};
// Information retrieved from an UnmaskRequest.
@@ -124,10 +127,10 @@ class PaymentsClient {
std::string dcvv;
// Challenge required for enrolling user into FIDO authentication for future
// card unmasking.
- base::Optional<base::Value> fido_creation_options = base::nullopt;
+ absl::optional<base::Value> fido_creation_options;
// Challenge required for authorizing user for FIDO authentication for
// future card unmasking.
- base::Optional<base::Value> fido_request_options = base::nullopt;
+ absl::optional<base::Value> fido_request_options;
// An opaque token used to logically chain consecutive UnmaskCard and
// OptChange calls together.
std::string card_authorization_token = std::string();
@@ -159,7 +162,7 @@ class PaymentsClient {
Reason reason;
// Signature required for enrolling user into FIDO authentication for future
// card unmasking.
- base::Optional<base::Value> fido_authenticator_response = base::nullopt;
+ absl::optional<base::Value> fido_authenticator_response;
// An opaque token used to logically chain consecutive UnmaskCard and
// OptChange calls together.
std::string card_authorization_token = std::string();
@@ -173,13 +176,13 @@ class PaymentsClient {
// Unset if response failed. True if user is opted-in for FIDO
// authentication for card unmasking. False otherwise.
- base::Optional<bool> user_is_opted_in;
+ absl::optional<bool> user_is_opted_in;
// Challenge required for enrolling user into FIDO authentication for future
// card unmasking.
- base::Optional<base::Value> fido_creation_options = base::nullopt;
+ absl::optional<base::Value> fido_creation_options;
// Challenge required for authorizing user for FIDO authentication for
// future card unmasking.
- base::Optional<base::Value> fido_request_options = base::nullopt;
+ absl::optional<base::Value> fido_request_options;
};
// A collection of the information required to make a credit card upload
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 de72a4e15ec..5919a01274f 100644
--- a/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_client_unittest.cc
@@ -366,13 +366,14 @@ class PaymentsClientTest : public testing::Test {
base::StringPiece phone_number) {
AutofillProfile profile;
- profile.SetInfo(NAME_FIRST, ASCIIToUTF16(first_name), "en-US");
- profile.SetInfo(NAME_LAST, ASCIIToUTF16(last_name), "en-US");
- profile.SetInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16(address_line), "en-US");
- profile.SetInfo(ADDRESS_HOME_CITY, ASCIIToUTF16(city), "en-US");
- profile.SetInfo(ADDRESS_HOME_STATE, ASCIIToUTF16(state), "en-US");
- profile.SetInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16(zip), "en-US");
- profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16(phone_number),
+ profile.SetInfo(NAME_FIRST, base::ASCIIToUTF16(first_name), "en-US");
+ profile.SetInfo(NAME_LAST, base::ASCIIToUTF16(last_name), "en-US");
+ profile.SetInfo(ADDRESS_HOME_LINE1, base::ASCIIToUTF16(address_line),
+ "en-US");
+ profile.SetInfo(ADDRESS_HOME_CITY, base::ASCIIToUTF16(city), "en-US");
+ profile.SetInfo(ADDRESS_HOME_STATE, base::ASCIIToUTF16(state), "en-US");
+ profile.SetInfo(ADDRESS_HOME_ZIP, base::ASCIIToUTF16(zip), "en-US");
+ profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16(phone_number),
"en-US");
profile.FinalizeAfterImport();
return profile;
diff --git a/chromium/components/autofill/core/browser/payments/payments_service_url.cc b/chromium/components/autofill/core/browser/payments/payments_service_url.cc
index 442f7fa25ca..d76574f73cb 100644
--- a/chromium/components/autofill/core/browser/payments/payments_service_url.cc
+++ b/chromium/components/autofill/core/browser/payments/payments_service_url.cc
@@ -11,7 +11,6 @@
#include "base/metrics/field_trial.h"
#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 "components/autofill/core/common/autofill_switches.h"
#include "google_apis/gaia/gaia_urls.h"
diff --git a/chromium/components/autofill/core/browser/payments/strike_database_integrator_base.cc b/chromium/components/autofill/core/browser/payments/strike_database_integrator_base.cc
deleted file mode 100644
index 30f94046132..00000000000
--- a/chromium/components/autofill/core/browser/payments/strike_database_integrator_base.cc
+++ /dev/null
@@ -1,109 +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/core/browser/payments/strike_database_integrator_base.h"
-
-#include <algorithm>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/task/post_task.h"
-#include "base/time/time.h"
-#include "components/autofill/core/browser/proto/strike_data.pb.h"
-#include "components/autofill/core/common/autofill_clock.h"
-#include "components/leveldb_proto/public/proto_database_provider.h"
-
-namespace autofill {
-
-StrikeDatabaseIntegratorBase::StrikeDatabaseIntegratorBase(
- StrikeDatabase* strike_database)
- : strike_database_(strike_database) {}
-
-StrikeDatabaseIntegratorBase::~StrikeDatabaseIntegratorBase() {}
-
-bool StrikeDatabaseIntegratorBase::IsMaxStrikesLimitReached(
- const std::string& id) {
- CheckIdUniqueness(id);
- return GetStrikes(id) >= GetMaxStrikesLimit();
-}
-
-int StrikeDatabaseIntegratorBase::AddStrike(const std::string& id) {
- CheckIdUniqueness(id);
- return AddStrikes(1, id);
-}
-
-int StrikeDatabaseIntegratorBase::AddStrikes(int strikes_increase,
- const std::string& id) {
- CheckIdUniqueness(id);
- int num_strikes = strike_database_->AddStrikes(strikes_increase, GetKey(id));
- base::UmaHistogramCounts1000(
- "Autofill.StrikeDatabase.NthStrikeAdded." + GetProjectPrefix(),
- num_strikes);
- return num_strikes;
-}
-
-int StrikeDatabaseIntegratorBase::RemoveStrike(const std::string& id) {
- CheckIdUniqueness(id);
- return strike_database_->RemoveStrikes(1, GetKey(id));
-}
-
-int StrikeDatabaseIntegratorBase::RemoveStrikes(int strike_decrease,
- const std::string& id) {
- CheckIdUniqueness(id);
- return strike_database_->RemoveStrikes(strike_decrease, GetKey(id));
-}
-
-int StrikeDatabaseIntegratorBase::GetStrikes(const std::string& id) {
- CheckIdUniqueness(id);
- return strike_database_->GetStrikes(GetKey(id));
-}
-
-void StrikeDatabaseIntegratorBase::ClearStrikes(const std::string& id) {
- CheckIdUniqueness(id);
- strike_database_->ClearStrikes(GetKey(id));
-}
-
-void StrikeDatabaseIntegratorBase::ClearAllStrikes() {
- strike_database_->ClearAllStrikesForProject(GetProjectPrefix());
-}
-
-void StrikeDatabaseIntegratorBase::RemoveExpiredStrikes() {
- if (!GetExpiryTimeMicros().has_value()) {
- // Strikes don't expire.
- return;
- }
- std::vector<std::string> expired_keys;
- for (auto entry : strike_database_->strike_map_cache_) {
- if (AutofillClock::Now().ToDeltaSinceWindowsEpoch().InMicroseconds() -
- entry.second.last_update_timestamp() >
- GetExpiryTimeMicros().value()) {
- if (strike_database_->GetStrikes(entry.first) > 0) {
- expired_keys.push_back(entry.first);
- base::UmaHistogramCounts1000(
- "Autofill.StrikeDatabase.StrikesPresentWhenStrikeExpired." +
- strike_database_->GetPrefixFromKey(entry.first),
- strike_database_->GetStrikes(entry.first));
- }
- }
- }
- for (std::string key : expired_keys) {
- int strikes_to_remove = 1;
- // If the key is already over the limit, remove additional strikes to
- // emulate setting it back to the limit. These are done together to avoid
- // multiple calls to the file system ProtoDatabase.
- strikes_to_remove +=
- std::max(0, strike_database_->GetStrikes(key) - GetMaxStrikesLimit());
- strike_database_->RemoveStrikes(strikes_to_remove, key);
- }
-}
-
-std::string StrikeDatabaseIntegratorBase::GetKey(const std::string& id) {
- return GetProjectPrefix() + kKeyDeliminator + id;
-}
-
-} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database.h b/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database.h
deleted file mode 100644
index c26e36af08f..00000000000
--- a/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database.h
+++ /dev/null
@@ -1,44 +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_AUTOFILL_CORE_BROWSER_PAYMENTS_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_
-
-#include <stdint.h>
-#include <string>
-
-#include "components/autofill/core/browser/payments/strike_database.h"
-#include "components/autofill/core/browser/payments/strike_database_integrator_base.h"
-
-namespace autofill {
-
-// Mock per-project implementation of StrikeDatabase to test the functions in
-// StrikeDatabaseIntegrator.
-class StrikeDatabaseIntegratorTestStrikeDatabase
- : public StrikeDatabaseIntegratorBase {
- public:
- StrikeDatabaseIntegratorTestStrikeDatabase(
- StrikeDatabase* strike_database,
- base::Optional<int64_t> expiry_time_micros);
- explicit StrikeDatabaseIntegratorTestStrikeDatabase(
- StrikeDatabase* strike_database);
- ~StrikeDatabaseIntegratorTestStrikeDatabase() override;
-
- std::string GetProjectPrefix() override;
- int GetMaxStrikesLimit() override;
- base::Optional<int64_t> GetExpiryTimeMicros() override;
- bool UniqueIdsRequired() override;
-
- void SetUniqueIdsRequired(bool unique_ids_required);
-
- private:
- bool unique_ids_required_ = false;
- base::Optional<int64_t> expiry_time_micros_ =
- static_cast<int64_t>(1000000) * 60 * 60 * 24 *
- 365; // Default expiry time is 1 year.
-};
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_
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 b17dc78377c..056299658ea 100644
--- a/chromium/components/autofill/core/browser/payments/test_authentication_requester.h
+++ b/chromium/components/autofill/core/browser/payments/test_authentication_requester.h
@@ -56,7 +56,7 @@ class TestAuthenticationRequester
base::WeakPtr<TestAuthenticationRequester> GetWeakPtr();
- base::Optional<bool> is_user_verifiable() { return is_user_verifiable_; }
+ absl::optional<bool> is_user_verifiable() { return is_user_verifiable_; }
bool did_succeed() { return did_succeed_; }
@@ -64,7 +64,7 @@ class TestAuthenticationRequester
private:
// Set when CreditCardFIDOAuthenticator invokes IsUserVerifiableCallback().
- base::Optional<bool> is_user_verifiable_;
+ absl::optional<bool> is_user_verifiable_;
// Is set to true if authentication was successful.
bool did_succeed_ = false;
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 893a1a4b95e..36dc7d427f7 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
@@ -14,7 +14,6 @@
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/browser/payments/credit_card_fido_authenticator.h"
#include "components/autofill/core/browser/payments/payments_client.h"
-#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
namespace autofill {
@@ -55,7 +54,7 @@ class TestCreditCardFIDOAuthenticator : public CreditCardFIDOAuthenticator {
bool IsOptOutCalled() { return opt_out_called_; }
private:
- friend class AutofillManagerTest;
+ friend class BrowserAutofillManagerTest;
friend class CreditCardAccessManagerTest;
PublicKeyCredentialRequestOptionsPtr request_options_;
diff --git a/chromium/components/autofill/core/browser/payments/test_strike_database.h b/chromium/components/autofill/core/browser/payments/test_strike_database.h
index 7fb5fb53a06..61adfa3aad2 100644
--- a/chromium/components/autofill/core/browser/payments/test_strike_database.h
+++ b/chromium/components/autofill/core/browser/payments/test_strike_database.h
@@ -11,8 +11,8 @@
#include <utility>
#include <vector>
-#include "components/autofill/core/browser/payments/strike_database.h"
#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/autofill/core/browser/strike_database.h"
namespace autofill {
diff --git a/chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.h b/chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.h
index 6a00772d178..212b43b6feb 100644
--- a/chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.h
+++ b/chromium/components/autofill/core/browser/payments/upi_vpa_save_manager.h
@@ -30,7 +30,7 @@ class UpiVpaSaveManager {
AutofillClient* client_;
// The personal data manager, used to save and load personal data to/from the
- // web database. This is overridden by the AutofillManagerTest.
+ // web database. This is overridden by the BrowserAutofillManagerTest.
// Weak reference. May be nullptr, which indicates OTR.
PersonalDataManager* personal_data_manager_;
diff --git a/chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout.cc b/chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout.cc
new file mode 100644
index 00000000000..713a53e0f00
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout.cc
@@ -0,0 +1,78 @@
+// Copyright 2021 The Chromium Authors. 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/wait_for_signal_or_timeout.h"
+
+#include "base/threading/sequenced_task_runner_handle.h"
+
+WaitForSignalOrTimeout::WaitForSignalOrTimeout() = default;
+WaitForSignalOrTimeout::~WaitForSignalOrTimeout() = default;
+
+void WaitForSignalOrTimeout::Signal() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+ SignalHandler(/*triggered_by_signal=*/true);
+}
+
+bool WaitForSignalOrTimeout::IsSignaled() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+ return state_ == State::kSignalReceived || state_ == State::kDone;
+}
+
+void WaitForSignalOrTimeout::OnEventOrTimeOut(Callback callback,
+ base::TimeDelta timeout) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+ switch (state_) {
+ case State::kInitialState:
+ callback_ = std::move(callback);
+ ++generation_id_; // Invalidate previous OnTimeOut tasks.
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&WaitForSignalOrTimeout::OnTimeOut,
+ weak_factory_.GetWeakPtr(), generation_id_),
+ timeout);
+ break;
+
+ case State::kSignalReceived:
+ state_ = State::kDone;
+ std::move(callback).Run(
+ /*triggered_by_signal=*/in_state_signal_received_due_to_signal_call_);
+ break;
+
+ case State::kDone:
+ Reset();
+ OnEventOrTimeOut(std::move(callback), timeout);
+ break;
+ }
+}
+
+void WaitForSignalOrTimeout::Reset() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+ state_ = State::kInitialState;
+ ++generation_id_;
+ callback_ = Callback();
+}
+
+void WaitForSignalOrTimeout::OnTimeOut(int generation_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
+ if (generation_id == generation_id_)
+ SignalHandler(/*triggered_by_signal=*/false);
+}
+
+void WaitForSignalOrTimeout::SignalHandler(bool triggered_by_signal) {
+ switch (state_) {
+ case State::kInitialState:
+ if (callback_.is_null()) {
+ state_ = State::kSignalReceived;
+ in_state_signal_received_due_to_signal_call_ = triggered_by_signal;
+ } else {
+ state_ = State::kDone;
+ std::move(callback_).Run(triggered_by_signal);
+ }
+ break;
+
+ case State::kSignalReceived:
+ case State::kDone:
+ break;
+ }
+}
diff --git a/chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout.h b/chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout.h
new file mode 100644
index 00000000000..6b2c4512454
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout.h
@@ -0,0 +1,100 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WAIT_FOR_SIGNAL_OR_TIMEOUT_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WAIT_FOR_SIGNAL_OR_TIMEOUT_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/time/time.h"
+
+// A WaitForSignalOrTimeout waits for Signal() or a time out and calls a
+// callback when either of these happens for the first time.
+//
+// The WaitForSignalOrTimeout is Reset()-able and ensures that the callback will
+// be called at most once (unless Reset() resets the state). The
+// WaitForSignalOrTimeout can be destroyed at any time without negative
+// side-effects. The callback won't be called in this case. If the Signal()
+// arrives before a call for OnEventOrTimeOut(), the callback will be called
+// immediately. If a second Signal() arrives, nothing happens. The
+// WaitForSignalOrTimeout must be used on single task sequence.
+//
+// This class provides the bare minimum needed for a Payment task. If there are
+// more use cases, feel free to spice it up and move it to base/.
+class WaitForSignalOrTimeout {
+ public:
+ // The passed boolean is true if the callback happened by a call of Signal()
+ // (as opposed to a timeout).
+ using Callback = base::OnceCallback<void(bool)>;
+
+ WaitForSignalOrTimeout();
+ ~WaitForSignalOrTimeout();
+ WaitForSignalOrTimeout(const WaitForSignalOrTimeout&) = delete;
+ WaitForSignalOrTimeout& operator=(const WaitForSignalOrTimeout&) = delete;
+
+ // Triggers |callback_| if it has not been called before, or registers that
+ // the signal occurred, so that |callback| of OnEventOrTimeOut() can be
+ // called immediately.
+ void Signal();
+
+ // Returns whether Signal() was called at least once or a timeout happened,
+ // and Reset() has not been called afterwards. Note that this function does
+ // not discriminate whether Signal() was called or a timeout happened.
+ // The |callback_|'s parameter has this distinction, though.
+ bool IsSignaled() const;
+
+ // Registers the |callback| and calls it immediately if Signal() was called
+ // already. Starts a timeout task, so that |callback| is called if no call of
+ // Signal() is observed within |timeout|. A previous timeout is replaced by a
+ // new one.
+ void OnEventOrTimeOut(Callback callback, base::TimeDelta timeout);
+
+ // Resets the state machine so that no Signal() was observed, no callback is
+ // registered and no timeout task is running.
+ void Reset();
+
+ private:
+ enum class State {
+ // Signal() has not been called, yet.
+ kInitialState,
+ // Signal() has been called, but callback is not specified.
+ kSignalReceived,
+ // callback has been called.
+ kDone,
+ };
+
+ // Internal callback for the timeout. |generation_id| is a generation counter
+ // to ensure that old, delayed timeout tasks are ignored.
+ void OnTimeOut(int generation_id);
+
+ // Handler for Signal() and OnTimeOut(). Calls |callback_| if appropriate.
+ // The parameter is true if this function is called via Signal() and false if
+ // the function is called via OnTimeOut(). This parameter is passed to
+ // callback.
+ void SignalHandler(bool triggered_by_signal);
+
+ State state_ = State::kInitialState;
+
+ // This variable is only valid if state_ == State::kSignalReceived. It is
+ // true if we moved into this state due to a Signal() call, and false if
+ // we moved into this state due to an OnTimeOut() call.
+ bool in_state_signal_received_due_to_signal_call_;
+
+ // As the base::ThreadPool does not support cancelable tasks, we just rely on
+ // a generation counter. Every time Reset() or OnEventOrTimeOut() are called,
+ // the generation id is incremented. If outdated delayed OnTimeOut() tasks
+ // trickle in, we recognize them as tasks for which the |generation_id|
+ // parameter is less than the current generation_id_ and ignore them.
+ int generation_id_ = 0;
+
+ // Callback to be called in case of a Signal() or a time out.
+ Callback callback_;
+
+ SEQUENCE_CHECKER(my_sequence_checker_);
+
+ base::WeakPtrFactory<WaitForSignalOrTimeout> weak_factory_{this};
+};
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_WAIT_FOR_SIGNAL_OR_TIMEOUT_H_
diff --git a/chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout_unittest.cc b/chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout_unittest.cc
new file mode 100644
index 00000000000..eda3fd36222
--- /dev/null
+++ b/chromium/components/autofill/core/browser/payments/wait_for_signal_or_timeout_unittest.cc
@@ -0,0 +1,188 @@
+// Copyright 2021 The Chromium Authors. 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/wait_for_signal_or_timeout.h"
+
+#include "base/test/task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class WaitForSignalOrTimeoutTest : public testing::Test {
+ public:
+ WaitForSignalOrTimeoutTest() = default;
+ ~WaitForSignalOrTimeoutTest() override = default;
+
+ WaitForSignalOrTimeout::Callback GetCallback() {
+ return base::BindOnce(&WaitForSignalOrTimeoutTest::Callback,
+ base::Unretained(this));
+ }
+
+ protected:
+ void Callback(bool triggered_by_signal) {
+ callbacks_++;
+ last_callback_triggered_by_signal_ = triggered_by_signal;
+ }
+
+ // Number of observed callbacks.
+ int callbacks_ = 0;
+
+ bool last_callback_triggered_by_signal_ = false;
+
+ base::test::TaskEnvironment task_env_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+};
+
+// WaitForSignalOrTimeout is initialized with a callback and then the Signal()
+// happens.
+TEST_F(WaitForSignalOrTimeoutTest, InitThenSignal) {
+ WaitForSignalOrTimeout wait;
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_EQ(0, callbacks_);
+ EXPECT_FALSE(wait.IsSignaled());
+ wait.Signal();
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
+
+ // Another signal call should be ignored.
+ wait.Signal();
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_TRUE(wait.IsSignaled());
+
+ // Also the pending timeout should not trigger further callbacks.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+}
+
+// A Signal() is registered before the callback.
+TEST_F(WaitForSignalOrTimeoutTest, SignalThenInit) {
+ WaitForSignalOrTimeout wait;
+ EXPECT_FALSE(wait.IsSignaled());
+
+ // Trigger the signal before a callback handler is registered.
+ wait.Signal();
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(0, callbacks_);
+
+ // Once the callback handler is registered, it should be called immediately.
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
+
+ // Another signal call should be ignored.
+ wait.Signal();
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+
+ // Also the pending timeout should not trigger further callbacks.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+}
+
+// A timeout occurs before Signal() is called.
+TEST_F(WaitForSignalOrTimeoutTest, InitThenTimeout) {
+ WaitForSignalOrTimeout wait;
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_FALSE(wait.IsSignaled());
+ EXPECT_EQ(0, callbacks_);
+
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
+
+ // A late signal will be ignored.
+ wait.Signal();
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_EQ(1, callbacks_);
+}
+
+// The WaitForSignalOrTimeout gets destroyed before a Signal() or timeout
+// happens.
+TEST_F(WaitForSignalOrTimeoutTest, DestroyedBeforeSignal) {
+ {
+ WaitForSignalOrTimeout wait;
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ }
+ EXPECT_EQ(0, callbacks_);
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
+ EXPECT_EQ(0, callbacks_);
+}
+
+// The WaitForSignalOrTimeout gets signaled, reset, and signaled again.
+TEST_F(WaitForSignalOrTimeoutTest, Reset) {
+ WaitForSignalOrTimeout wait;
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_EQ(0, callbacks_);
+ wait.Signal();
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
+
+ wait.Reset();
+
+ EXPECT_FALSE(wait.IsSignaled());
+
+ // This signal does not trigger a callback because none is registered.
+ wait.Signal();
+ EXPECT_EQ(1, callbacks_);
+ // Now the callback happens immediately.
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_EQ(2, callbacks_);
+ EXPECT_TRUE(last_callback_triggered_by_signal_);
+
+ wait.Reset();
+
+ // Finally, we simulate a timeout after the reset.
+ EXPECT_FALSE(wait.IsSignaled());
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(35));
+ EXPECT_EQ(3, callbacks_);
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
+}
+
+TEST_F(WaitForSignalOrTimeoutTest, OnEventOrTimeOutCalledTwice) {
+ WaitForSignalOrTimeout wait;
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+ EXPECT_EQ(0, callbacks_);
+
+ // Wait some time but not long enough for the timeout to trigger.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(25));
+ EXPECT_EQ(0, callbacks_);
+ EXPECT_FALSE(wait.IsSignaled());
+
+ // This resets the state machine (currently waiting for a signal or timeout)
+ // and starts a new wait.
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+
+ // Wait some time but not long enough for the timeout to trigger.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(25));
+ // The first timeout should not have triggered anything.
+ EXPECT_EQ(0, callbacks_);
+ EXPECT_FALSE(wait.IsSignaled());
+
+ // Wait some more time for the second timeout to kick in.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(10));
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
+
+ // This resets the state machine (currently in done state) once more and
+ // starts a new wait.
+ wait.OnEventOrTimeOut(GetCallback(), base::TimeDelta::FromSeconds(30));
+
+ // Wait some time but not long enough for the timeout to trigger.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(25));
+ // The first timeout should not have triggered anything.
+ EXPECT_EQ(1, callbacks_);
+ EXPECT_FALSE(wait.IsSignaled());
+
+ // Wait some more time for the second timeout to kick in.
+ task_env_.FastForwardBy(base::TimeDelta::FromSeconds(10));
+ EXPECT_EQ(2, callbacks_);
+ EXPECT_TRUE(wait.IsSignaled());
+ EXPECT_FALSE(last_callback_triggered_by_signal_);
+}
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.cc b/chromium/components/autofill/core/browser/personal_data_manager.cc
index 9d898ef1676..0f854f8fe19 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager.cc
@@ -24,7 +24,6 @@
#include "base/stl_util.h"
#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 "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -33,6 +32,7 @@
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/autofill_profile_save_strike_database.h"
#include "components/autofill/core/browser/data_model/autofill_profile_comparator.h"
#include "components/autofill/core/browser/data_model/phone_number.h"
#include "components/autofill/core/browser/form_structure.h"
@@ -274,6 +274,7 @@ void PersonalDataManager::Init(
signin::IdentityManager* identity_manager,
AutofillProfileValidator* client_profile_validator,
history::HistoryService* history_service,
+ StrikeDatabaseBase* strike_database,
bool is_off_the_record) {
CountryNames::SetLocaleString(app_locale_);
database_helper_->Init(profile_database, account_database);
@@ -313,6 +314,13 @@ void PersonalDataManager::Init(
client_profile_validator_ = client_profile_validator;
+ if (strike_database) {
+ profile_save_strike_database_ =
+ std::make_unique<AutofillProfileSaveStrikeDatabase>(strike_database);
+ profile_update_strike_database_ =
+ std::make_unique<AutofillProfileUpdateStrikeDatabase>(strike_database);
+ }
+
// WebDataService may not be available in tests.
if (!database_helper_->GetLocalDatabase()) {
return;
@@ -393,6 +401,26 @@ void PersonalDataManager::OnURLsDeleted(
if (!deletion_info.is_from_expiration() && deletion_info.IsAllHistory()) {
AutofillDownloadManager::ClearUploadHistory(pref_service_);
}
+
+ if (profile_save_strike_database_) {
+ if (deletion_info.IsAllHistory()) {
+ // If the whole history is deleted, clear all strikes.
+ profile_save_strike_database_->ClearAllStrikes();
+ } else {
+ std::set<std::string> deleted_hosts;
+ for (const auto& url_row : deletion_info.deleted_rows()) {
+ deleted_hosts.insert(url_row.url().host());
+ }
+ if (deletion_info.time_range().IsValid() &&
+ !deletion_info.time_range().IsAllTime()) {
+ profile_save_strike_database_->ClearStrikesByOriginAndTimeInternal(
+ deleted_hosts, deletion_info.time_range().begin(),
+ deletion_info.time_range().end());
+ } else {
+ profile_save_strike_database_->ClearStrikesByOrigin(deleted_hosts);
+ }
+ }
+ }
}
void PersonalDataManager::OnWebDataServiceRequestDone(
@@ -1162,8 +1190,7 @@ PersonalDataManager::GetCreditCardCloudTokenData() const {
return result;
}
-std::vector<AutofillOfferData*> PersonalDataManager::GetCreditCardOffers()
- const {
+std::vector<AutofillOfferData*> PersonalDataManager::GetAutofillOffers() const {
if (!IsAutofillWalletImportEnabled())
return {};
@@ -1180,7 +1207,7 @@ void PersonalDataManager::Refresh() {
LoadCreditCardCloudTokenData();
LoadPaymentsCustomerData();
LoadUpiIds();
- LoadCreditCardOffers();
+ LoadAutofillOffers();
}
std::vector<AutofillProfile*> PersonalDataManager::GetProfilesToSuggest()
@@ -1596,6 +1623,82 @@ void PersonalDataManager::SetProfiles(std::vector<AutofillProfile>* profiles) {
}
}
+bool PersonalDataManager::IsNewProfileImportBlockedForDomain(
+ const GURL& url) const {
+ if (!GetProfileSaveStrikeDatabase() || !url.is_valid() || !url.has_host() ||
+ !features::kAutofillAutoBlockSaveAddressProfilePrompt.Get()) {
+ return false;
+ }
+
+ return GetProfileSaveStrikeDatabase()->IsMaxStrikesLimitReached(url.host());
+}
+
+void PersonalDataManager::AddStrikeToBlockNewProfileImportForDomain(
+ const GURL& url) {
+ if (!GetProfileSaveStrikeDatabase() || !url.is_valid() || !url.has_host() ||
+ !features::kAutofillAutoBlockSaveAddressProfilePrompt.Get()) {
+ return;
+ }
+ GetProfileSaveStrikeDatabase()->AddStrike(url.host());
+}
+
+void PersonalDataManager::RemoveStrikesToBlockNewProfileImportForDomain(
+ const GURL& url) {
+ if (!GetProfileSaveStrikeDatabase() || !url.is_valid() || !url.has_host()) {
+ return;
+ }
+ GetProfileSaveStrikeDatabase()->ClearStrikes(url.host());
+}
+
+bool PersonalDataManager::IsProfileUpdateBlocked(
+ const std::string& guid) const {
+ if (!GetProfileUpdateStrikeDatabase() ||
+ !features::kAutofillAutoBlockUpdateAddressProfilePrompt.Get()) {
+ return false;
+ }
+
+ return GetProfileUpdateStrikeDatabase()->IsMaxStrikesLimitReached(guid);
+}
+
+void PersonalDataManager::AddStrikeToBlockProfileUpdate(
+ const std::string& guid) {
+ if (!GetProfileUpdateStrikeDatabase() ||
+ !features::kAutofillAutoBlockUpdateAddressProfilePrompt.Get()) {
+ return;
+ }
+ GetProfileUpdateStrikeDatabase()->AddStrike(guid);
+}
+
+void PersonalDataManager::RemoveStrikesToBlockProfileUpdate(
+ const std::string& guid) {
+ if (!GetProfileUpdateStrikeDatabase()) {
+ return;
+ }
+ GetProfileUpdateStrikeDatabase()->ClearStrikes(guid);
+}
+
+AutofillProfileSaveStrikeDatabase*
+PersonalDataManager::GetProfileSaveStrikeDatabase() {
+ return const_cast<AutofillProfileSaveStrikeDatabase*>(
+ base::as_const(*this).GetProfileSaveStrikeDatabase());
+}
+
+const AutofillProfileSaveStrikeDatabase*
+PersonalDataManager::GetProfileSaveStrikeDatabase() const {
+ return profile_save_strike_database_.get();
+}
+
+AutofillProfileUpdateStrikeDatabase*
+PersonalDataManager::GetProfileUpdateStrikeDatabase() {
+ return const_cast<AutofillProfileUpdateStrikeDatabase*>(
+ base::as_const(*this).GetProfileUpdateStrikeDatabase());
+}
+
+const AutofillProfileUpdateStrikeDatabase*
+PersonalDataManager::GetProfileUpdateStrikeDatabase() const {
+ return profile_update_strike_database_.get();
+}
+
void PersonalDataManager::SetCreditCards(
std::vector<CreditCard>* credit_cards) {
if (is_off_the_record_)
@@ -1692,14 +1795,14 @@ void PersonalDataManager::LoadUpiIds() {
database_helper_->GetLocalDatabase()->GetAllUpiIds(this);
}
-void PersonalDataManager::LoadCreditCardOffers() {
+void PersonalDataManager::LoadAutofillOffers() {
if (!database_helper_->GetServerDatabase())
return;
CancelPendingServerQuery(&pending_offer_data_query_);
pending_offer_data_query_ =
- database_helper_->GetServerDatabase()->GetCreditCardOffers(this);
+ database_helper_->GetServerDatabase()->GetAutofillOffers(this);
}
void PersonalDataManager::CancelPendingLocalQuery(
diff --git a/chromium/components/autofill/core/browser/personal_data_manager.h b/chromium/components/autofill/core/browser/personal_data_manager.h
index a4f87f76bfc..d4397d9cd3a 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/personal_data_manager.h
@@ -19,6 +19,8 @@
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "build/build_config.h"
+#include "components/autofill/core/browser/autofill_profile_save_strike_database.h"
+#include "components/autofill/core/browser/autofill_profile_update_strike_database.h"
#include "components/autofill/core/browser/autofill_profile_validator.h"
#include "components/autofill/core/browser/data_model/autofill_offer_data.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -30,6 +32,7 @@
#include "components/autofill/core/browser/payments/payments_customer_data.h"
#include "components/autofill/core/browser/personal_data_manager_cleaner.h"
#include "components/autofill/core/browser/proto/server.pb.h"
+#include "components/autofill/core/browser/strike_database_base.h"
#include "components/autofill/core/browser/sync_utils.h"
#include "components/autofill/core/browser/ui/suggestion.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
@@ -99,6 +102,7 @@ class PersonalDataManager : public KeyedService,
signin::IdentityManager* identity_manager,
AutofillProfileValidator* client_profile_validator,
history::HistoryService* history_service,
+ StrikeDatabaseBase* strike_database,
bool is_off_the_record);
// KeyedService:
@@ -276,8 +280,8 @@ class PersonalDataManager : public KeyedService,
virtual std::vector<CreditCardCloudTokenData*> GetCreditCardCloudTokenData()
const;
- // Returns the credit card offer data.
- virtual std::vector<AutofillOfferData*> GetCreditCardOffers() const;
+ // Returns autofill offer data, including card-linked and promo code offers.
+ virtual std::vector<AutofillOfferData*> GetAutofillOffers() const;
// Updates the validity states of |profiles| according to server validity map.
void UpdateProfilesServerValidityMapsIfNeeded(
@@ -438,6 +442,39 @@ class PersonalDataManager : public KeyedService,
// Returns true if the PDM is in the off-the-record mode.
bool IsOffTheRecord() { return is_off_the_record_; }
+ // Sets |web_profiles_| to the contents of |profiles| and updates the web
+ // database by adding, updating and removing profiles. |web_profiles_| need to
+ // be updated at the end of the function, since some tasks cannot tolerate
+ // database delays.
+ virtual void SetProfiles(std::vector<AutofillProfile>* profiles);
+
+ // Returns true if the import of new profiles should be blocked on `url`.
+ // Returns false if the strike database is not available, the `url` is not
+ // valid or has no host.
+ bool IsNewProfileImportBlockedForDomain(const GURL& url) const;
+
+ // Add a strike for blocking the import of new profiles on `url`.
+ // Does nothing if the strike database is not available, the `url` is not
+ // valid or has no host.
+ void AddStrikeToBlockNewProfileImportForDomain(const GURL& url);
+
+ // Removes potential strikes for the import of new profiles from `url`.
+ // Does nothing if the strike database is not available, the `url` is not
+ // valid or has no host.
+ void RemoveStrikesToBlockNewProfileImportForDomain(const GURL& url);
+
+ // Returns true if a profile identified by its `guid` is blocked for updates.
+ // Returns false if the database is not available.
+ bool IsProfileUpdateBlocked(const std::string& guid) const;
+
+ // Adds a strike to block a profile identified by its `guid` for updates.
+ // Does nothing if the strike database is not available.
+ void AddStrikeToBlockProfileUpdate(const std::string& guid);
+
+ // Removes potential strikes to block a profile identified by its `guid` for
+ // updates. Does nothing if the strike database is not available.
+ void RemoveStrikesToBlockProfileUpdate(const std::string& guid);
+
protected:
// Only PersonalDataManagerFactory and certain tests can create instances of
// PersonalDataManager.
@@ -534,11 +571,17 @@ class PersonalDataManager : public KeyedService,
friend void SetTestProfiles(Profile* base_profile,
std::vector<AutofillProfile>* profiles);
- // Sets |web_profiles_| to the contents of |profiles| and updates the web
- // database by adding, updating and removing profiles. |web_profiles_| need to
- // be updated at the end of the function, since some tasks cannot tolerate
- // database delays.
- virtual void SetProfiles(std::vector<AutofillProfile>* profiles);
+ // Used to get a pointer to the strike database for importing new profiles.
+ // Note, the result can be a nullptr.
+ AutofillProfileSaveStrikeDatabase* GetProfileSaveStrikeDatabase();
+ virtual const AutofillProfileSaveStrikeDatabase*
+ GetProfileSaveStrikeDatabase() const;
+
+ // Used to get a pointer to the strike database for updating existing
+ // profiles. Note, the result can be a nullptr.
+ AutofillProfileUpdateStrikeDatabase* GetProfileUpdateStrikeDatabase();
+ virtual const AutofillProfileUpdateStrikeDatabase*
+ GetProfileUpdateStrikeDatabase() const;
// Sets |credit_cards_| to the contents of |credit_cards| and updates the web
// database by adding, updating and removing credit cards.
@@ -559,8 +602,8 @@ class PersonalDataManager : public KeyedService,
// Loads the saved UPI IDs from the web database.
virtual void LoadUpiIds();
- // Loads the offer data from the web database.
- virtual void LoadCreditCardOffers();
+ // Loads the autofill offer data from the web database.
+ virtual void LoadAutofillOffers();
// Cancels a pending query to the local web database. |handle| is a pointer
// to the query handle.
@@ -823,6 +866,16 @@ class PersonalDataManager : public KeyedService,
// An observer to listen for changes to prefs::kAutofillWalletImportEnabled.
std::unique_ptr<BooleanPrefMember> wallet_enabled_pref_;
+ // The database that is used to count domain-keyed strikes to suppress the
+ // import of new profiles.
+ std::unique_ptr<AutofillProfileSaveStrikeDatabase>
+ profile_save_strike_database_;
+
+ // The database that is used to count guid-keyed strikes to suppress updates
+ // of existing profiles.
+ std::unique_ptr<AutofillProfileUpdateStrikeDatabase>
+ profile_update_strike_database_;
+
// Whether sync should be considered on in a test.
bool is_syncing_for_test_ = false;
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 289083e0e15..5dc16893f90 100644
--- a/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/chromium/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -44,6 +44,7 @@
#include "components/autofill/core/browser/sync_utils.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
#include "components/autofill/core/browser/test_autofill_profile_validator.h"
+#include "components/autofill/core/browser/test_inmemory_strike_database.h"
#include "components/autofill/core/browser/ui/label_formatter_utils.h"
#include "components/autofill/core/browser/ui/suggestion_selection.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
@@ -78,6 +79,7 @@ using structured_address::StructuredNamesEnabled;
namespace {
const char kPrimaryAccountEmail[] = "syncuser@example.com";
+const char16_t kPrimaryAccountEmail16[] = u"syncuser@example.com";
const char kSyncTransportAccountEmail[] = "transport@example.com";
enum UserMode { USER_MODE_NORMAL, USER_MODE_INCOGNITO };
@@ -93,8 +95,8 @@ ACTION_P(QuitMessageLoop, loop) {
class PersonalDataLoadedObserverMock : public PersonalDataManagerObserver {
public:
- PersonalDataLoadedObserverMock() {}
- ~PersonalDataLoadedObserverMock() override {}
+ PersonalDataLoadedObserverMock() = default;
+ ~PersonalDataLoadedObserverMock() override = default;
MOCK_METHOD0(OnPersonalDataChanged, void());
MOCK_METHOD0(OnPersonalDataFinishedProfileTasks, void());
@@ -176,7 +178,7 @@ class PersonalDataManagerTestBase {
PersonalDataManagerTestBase()
: scoped_features_(
PersonalDataManagerTestBase::GetDefaultEnabledFeatures(),
- /*additioanal_enabled_features=*/{}),
+ /*additional_enabled_features=*/{}),
identity_test_env_(&test_url_loader_factory_) {}
explicit PersonalDataManagerTestBase(
@@ -217,11 +219,13 @@ class PersonalDataManagerTestBase {
base::ThreadTaskRunnerHandle::Get());
account_database_service_->Init(base::NullCallback());
+ strike_database_ = std::make_unique<TestInMemoryStrikeDatabase>();
+
test::DisableSystemServices(prefs_.get());
}
void TearDownTest() {
- // Order of destruction is important as AutofillManager relies on
+ // Order of destruction is important as BrowserAutofillManager relies on
// PersonalDataManager to be around when it gets destroyed.
test::ReenableSystemServices();
OSCryptMocker::TearDown();
@@ -240,7 +244,7 @@ class PersonalDataManagerTestBase {
: nullptr,
prefs_.get(), prefs_.get(), identity_test_env_.identity_manager(),
TestAutofillProfileValidator::GetInstance(),
- /*history_service=*/nullptr, is_incognito);
+ /*history_service=*/nullptr, strike_database_.get(), is_incognito);
personal_data->AddObserver(&personal_data_observer_);
AccountInfo account_info;
@@ -317,9 +321,7 @@ class PersonalDataManagerTestBase {
sync_service_.SetIsAuthenticatedAccountPrimary(false);
return account_info;
}
-
- base::test::SingleThreadTaskEnvironment task_environment_{
- base::test::SingleThreadTaskEnvironment::MainThreadType::UI};
+ base::test::TaskEnvironment task_environment_;
std::unique_ptr<PrefService> prefs_;
ScopedFeatureListWrapper scoped_features_;
network::TestURLLoaderFactory test_url_loader_factory_;
@@ -331,6 +333,7 @@ class PersonalDataManagerTestBase {
scoped_refptr<WebDatabaseService> account_web_database_;
AutofillTable* profile_autofill_table_; // weak ref
AutofillTable* account_autofill_table_; // weak ref
+ std::unique_ptr<StrikeDatabaseBase> strike_database_;
PersonalDataLoadedObserverMock personal_data_observer_;
};
@@ -614,7 +617,7 @@ class PersonalDataManagerMockTest : public PersonalDataManagerTestBase,
personal_data_ =
std::make_unique<PersonalDataManagerMock>("en", std::string());
PersonalDataManagerTestBase::ResetPersonalDataManager(
- user_mode, /*use_account_server_storage=*/true, personal_data_.get());
+ user_mode, /*use_sync_transport_mode=*/true, personal_data_.get());
}
bool TurnOnSyncFeature() {
@@ -2573,8 +2576,8 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_ProfileAutofillDisabled) {
// Add a different server profile.
std::vector<AutofillProfile> server_profiles;
- server_profiles.push_back(
- AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
+ server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
+ kServerAddressId);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "",
"ACME Corp", "500 Oak View", "Apt 8", "Houston", "TX",
"77401", "US", "");
@@ -2619,8 +2622,8 @@ TEST_F(PersonalDataManagerTest,
// Add a different server profile.
std::vector<AutofillProfile> server_profiles;
- server_profiles.push_back(
- AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
+ server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
+ kServerAddressId);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "",
"ACME Corp", "500 Oak View", "Apt 8", "Houston", "TX",
"77401", "US", "");
@@ -2809,10 +2812,10 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_FormWithOneProfile) {
AutofillType(NAME_FULL), std::u16string(), false,
std::vector<ServerFieldType>{NAME_FULL, ADDRESS_HOME_STREET_ADDRESS,
EMAIL_ADDRESS, PHONE_HOME_WHOLE_NUMBER}),
- ElementsAre(AllOf(testing::Field(&Suggestion::label,
- ConstructLabelLine({base::ASCIIToUTF16(
- "401 Merrimack St")})),
- testing::Field(&Suggestion::icon, ""))));
+ ElementsAre(
+ AllOf(testing::Field(&Suggestion::label,
+ ConstructLabelLine({u"401 Merrimack St"})),
+ testing::Field(&Suggestion::icon, ""))));
}
#endif // #if !defined(OS_ANDROID) && !defined(OS_IOS)
@@ -2991,7 +2994,7 @@ TEST_F(PersonalDataManagerTest, GetProfileSuggestions_MobileShowAll) {
TEST_F(PersonalDataManagerTest, IsKnownCard_MatchesMaskedServerCard) {
// Add a masked server card.
std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b459"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
"2110" /* last 4 digits */, "12", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
@@ -3011,7 +3014,7 @@ TEST_F(PersonalDataManagerTest, IsKnownCard_MatchesMaskedServerCard) {
TEST_F(PersonalDataManagerTest, IsKnownCard_MatchesFullServerCard) {
// Add a full server card.
std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "b459"));
+ server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
"4234567890122110" /* Visa */, "12", "2999", "1");
@@ -3084,7 +3087,7 @@ TEST_F(PersonalDataManagerTest, IsKnownCard_LastFourDoesNotMatch) {
TEST_F(PersonalDataManagerTest, IsServerCard_DuplicateOfFullServerCard) {
// Add a full server card.
std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "b459"));
+ server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
"4234567890122110" /* Visa */, "12", "2999", "1");
@@ -3111,7 +3114,7 @@ TEST_F(PersonalDataManagerTest, IsServerCard_DuplicateOfFullServerCard) {
TEST_F(PersonalDataManagerTest, IsServerCard_DuplicateOfMaskedServerCard) {
// Add a masked server card.
std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b459"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton",
"2110" /* last 4 digits */, "12", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
@@ -3233,7 +3236,7 @@ TEST_F(PersonalDataManagerTest,
// Add some server cards.
std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b459"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton", "2110", "12",
"2999", "1");
server_cards.back().set_use_count(2);
@@ -3241,7 +3244,7 @@ TEST_F(PersonalDataManagerTest,
base::TimeDelta::FromDays(1));
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
- server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "b460"));
+ server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "b460");
test::SetCreditCardInfo(&server_cards.back(), "Jesse James", "2109", "12",
"2999", "1");
server_cards.back().set_use_count(6);
@@ -3278,7 +3281,7 @@ TEST_F(PersonalDataManagerTest,
// Add some server cards.
std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b459"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton", "2110", "12",
"2999", "1");
server_cards.back().set_use_count(2);
@@ -3286,7 +3289,7 @@ TEST_F(PersonalDataManagerTest,
base::TimeDelta::FromDays(1));
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
- server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "b460"));
+ server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "b460");
test::SetCreditCardInfo(&server_cards.back(), "Jesse James", "2109", "12",
"2999", "1");
server_cards.back().set_use_count(6);
@@ -3324,7 +3327,7 @@ TEST_F(PersonalDataManagerTest,
// Add some server cards.
std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b459"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "b459");
test::SetCreditCardInfo(&server_cards.back(), "Emmet Dalton", "2110", "12",
"2999", "1");
server_cards.back().set_use_count(2);
@@ -3332,7 +3335,7 @@ TEST_F(PersonalDataManagerTest,
base::TimeDelta::FromDays(1));
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
- server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "b460"));
+ server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "b460");
test::SetCreditCardInfo(&server_cards.back(), "Jesse James", "2109", "12",
"2999", "1");
server_cards.back().set_use_count(6);
@@ -3637,7 +3640,7 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ServerDuplicates) {
// This server card matches a local card, except the local card is missing the
// number. This should count as a dupe and thus not be shown in the
// suggestions since the locally saved card takes precedence.
- server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "a123");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"3456" /* Visa */, "01", "2999", "1");
server_cards.back().set_use_count(2);
@@ -3648,7 +3651,7 @@ TEST_F(PersonalDataManagerTest, GetCreditCardSuggestions_ServerDuplicates) {
// This unmasked server card is an exact dupe of a local card. Therefore only
// this card should appear in the suggestions as full server cards have
// precedence over local cards.
- server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
+ server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
@@ -3697,7 +3700,7 @@ TEST_F(PersonalDataManagerTest,
std::vector<CreditCard> server_cards;
// This unmasked server card is an exact dupe of a local card. Therefore only
// the local card should appear in the suggestions.
- server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
+ server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
@@ -3933,7 +3936,7 @@ TEST_F(PersonalDataManagerTest, RecordUseOf) {
TEST_F(PersonalDataManagerTest, ClearAllServerData) {
// Add a server card.
std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "a123"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "a123");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"3456" /* Visa */, "01", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
@@ -3975,7 +3978,7 @@ TEST_F(PersonalDataManagerTest, ClearAllLocalData) {
// merge logic works correctly.
typedef struct {
autofill::ServerFieldType field_type;
- std::string field_value;
+ std::u16string field_value;
} ProfileField;
typedef std::vector<ProfileField> ProfileFields;
@@ -4036,7 +4039,7 @@ TEST_P(SaveImportedProfileTest, SaveImportedProfile) {
// Apply changes to the original profile (if applicable).
for (ProfileField change : test_case.changes_to_original) {
original_profile.SetRawInfoWithVerificationStatus(
- change.field_type, base::UTF8ToUTF16(change.field_value),
+ change.field_type, change.field_value,
structured_address::VerificationStatus::kObserved);
}
@@ -4052,7 +4055,7 @@ TEST_P(SaveImportedProfileTest, SaveImportedProfile) {
// Apply changes to the second profile (if applicable).
for (ProfileField change : test_case.changes_to_new) {
profile2.SetRawInfoWithVerificationStatus(
- change.field_type, base::UTF8ToUTF16(change.field_value),
+ change.field_type, change.field_value,
structured_address::VerificationStatus::kObserved);
}
@@ -4085,7 +4088,7 @@ TEST_P(SaveImportedProfileTest, SaveImportedProfile) {
// Make sure the new information was merged correctly.
for (ProfileField changed_field : test_case.changed_field_values) {
- EXPECT_EQ(base::UTF8ToUTF16(changed_field.field_value),
+ EXPECT_EQ(changed_field.field_value,
saved_profiles.front()->GetRawInfo(changed_field.field_type));
}
// Verify that the merged profile's use count, use date and modification
@@ -4121,66 +4124,66 @@ INSTANTIATE_TEST_SUITE_P(
// Test that saving an identical profile except for the name results
// in two profiles being saved.
SaveImportedProfileTestCase{ProfileFields(),
- {{NAME_FIRST, "Marionette"}}},
+ {{NAME_FIRST, u"Marionette"}}},
// Test that saving an identical profile except with the middle name
// initial instead of the full middle name results in the profiles
// getting merged and the full middle name being kept.
SaveImportedProfileTestCase{
ProfileFields(),
- {{NAME_MIDDLE, "M"}},
- {{NAME_MIDDLE, "Mitchell"},
- {NAME_FULL, "Marion Mitchell Morrison"}}},
+ {{NAME_MIDDLE, u"M"}},
+ {{NAME_MIDDLE, u"Mitchell"},
+ {NAME_FULL, u"Marion Mitchell Morrison"}}},
// Test that saving an identical profile except with the full middle
// name instead of the middle name initial results in the profiles
// getting merged and the full middle name replacing the initial.
- SaveImportedProfileTestCase{{{NAME_MIDDLE, "M"}},
- {{NAME_MIDDLE, "Mitchell"}},
- {{NAME_MIDDLE, "Mitchell"}}},
+ SaveImportedProfileTestCase{{{NAME_MIDDLE, u"M"}},
+ {{NAME_MIDDLE, u"Mitchell"}},
+ {{NAME_MIDDLE, u"Mitchell"}}},
// Test that saving an identical profile except with no middle name
// results in the profiles getting merged and the full middle name
// being kept.
SaveImportedProfileTestCase{ProfileFields(),
- {{NAME_MIDDLE, ""}},
- {{NAME_MIDDLE, "Mitchell"}}},
+ {{NAME_MIDDLE, u""}},
+ {{NAME_MIDDLE, u"Mitchell"}}},
// Test that saving an identical profile except with a middle name
// initial results in the profiles getting merged and the middle
// name initial being saved.
- SaveImportedProfileTestCase{{{NAME_MIDDLE, ""}},
- {{NAME_MIDDLE, "M"}},
- {{NAME_MIDDLE, "M"}}},
+ SaveImportedProfileTestCase{{{NAME_MIDDLE, u""}},
+ {{NAME_MIDDLE, u"M"}},
+ {{NAME_MIDDLE, u"M"}}},
// Test that saving an identical profile except with a middle name
// results in the profiles getting merged and the full middle name
// being saved.
- SaveImportedProfileTestCase{{{NAME_MIDDLE, ""}},
- {{NAME_MIDDLE, "Mitchell"}},
- {{NAME_MIDDLE, "Mitchell"}}},
+ SaveImportedProfileTestCase{{{NAME_MIDDLE, u""}},
+ {{NAME_MIDDLE, u"Mitchell"}},
+ {{NAME_MIDDLE, u"Mitchell"}}},
// Test that saving a identical profile except with the full name
// set instead of the name parts results in the two profiles being
// merged and all the name parts kept and the full name being added.
SaveImportedProfileTestCase{
{
- {NAME_FIRST, "Marion"},
- {NAME_MIDDLE, "Mitchell"},
- {NAME_LAST, "Morrison"},
- {NAME_FULL, ""},
+ {NAME_FIRST, u"Marion"},
+ {NAME_MIDDLE, u"Mitchell"},
+ {NAME_LAST, u"Morrison"},
+ {NAME_FULL, u""},
},
{
- {NAME_FIRST, ""},
- {NAME_MIDDLE, ""},
- {NAME_LAST, ""},
- {NAME_FULL, "Marion Mitchell Morrison"},
+ {NAME_FIRST, u""},
+ {NAME_MIDDLE, u""},
+ {NAME_LAST, u""},
+ {NAME_FULL, u"Marion Mitchell Morrison"},
},
{
- {NAME_FIRST, "Marion"},
- {NAME_MIDDLE, "Mitchell"},
- {NAME_LAST, "Morrison"},
- {NAME_FULL, "Marion Mitchell Morrison"},
+ {NAME_FIRST, u"Marion"},
+ {NAME_MIDDLE, u"Mitchell"},
+ {NAME_LAST, u"Morrison"},
+ {NAME_FULL, u"Marion Mitchell Morrison"},
},
},
@@ -4190,22 +4193,22 @@ INSTANTIATE_TEST_SUITE_P(
// added.
SaveImportedProfileTestCase{
{
- {NAME_FIRST, ""},
- {NAME_MIDDLE, ""},
- {NAME_LAST, ""},
- {NAME_FULL, "Marion Mitchell Morrison"},
+ {NAME_FIRST, u""},
+ {NAME_MIDDLE, u""},
+ {NAME_LAST, u""},
+ {NAME_FULL, u"Marion Mitchell Morrison"},
},
{
- {NAME_FIRST, "Marion"},
- {NAME_MIDDLE, "Mitchell"},
- {NAME_LAST, "Morrison"},
- {NAME_FULL, ""},
+ {NAME_FIRST, u"Marion"},
+ {NAME_MIDDLE, u"Mitchell"},
+ {NAME_LAST, u"Morrison"},
+ {NAME_FULL, u""},
},
{
- {NAME_FIRST, "Marion"},
- {NAME_MIDDLE, "Mitchell"},
- {NAME_LAST, "Morrison"},
- {NAME_FULL, "Marion Mitchell Morrison"},
+ {NAME_FIRST, u"Marion"},
+ {NAME_MIDDLE, u"Mitchell"},
+ {NAME_LAST, u"Morrison"},
+ {NAME_FULL, u"Marion Mitchell Morrison"},
},
},
@@ -4214,16 +4217,16 @@ INSTANTIATE_TEST_SUITE_P(
// names are different.
SaveImportedProfileTestCase{
{
- {NAME_FIRST, "Marion"},
- {NAME_MIDDLE, "Mitchell"},
- {NAME_LAST, "Morrison"},
- {NAME_FULL, ""},
+ {NAME_FIRST, u"Marion"},
+ {NAME_MIDDLE, u"Mitchell"},
+ {NAME_LAST, u"Morrison"},
+ {NAME_FULL, u""},
},
{
- {NAME_FIRST, ""},
- {NAME_MIDDLE, ""},
- {NAME_LAST, ""},
- {NAME_FULL, "John Thompson Smith"},
+ {NAME_FIRST, u""},
+ {NAME_MIDDLE, u""},
+ {NAME_LAST, u""},
+ {NAME_FULL, u"John Thompson Smith"},
},
},
@@ -4232,16 +4235,16 @@ INSTANTIATE_TEST_SUITE_P(
// names are different.
SaveImportedProfileTestCase{
{
- {NAME_FIRST, ""},
- {NAME_MIDDLE, ""},
- {NAME_LAST, ""},
- {NAME_FULL, "John Thompson Smith"},
+ {NAME_FIRST, u""},
+ {NAME_MIDDLE, u""},
+ {NAME_LAST, u""},
+ {NAME_FULL, u"John Thompson Smith"},
},
{
- {NAME_FIRST, "Marion"},
- {NAME_MIDDLE, "Mitchell"},
- {NAME_LAST, "Morrison"},
- {NAME_FULL, ""},
+ {NAME_FIRST, u"Marion"},
+ {NAME_MIDDLE, u"Mitchell"},
+ {NAME_LAST, u"Morrison"},
+ {NAME_FULL, u""},
},
},
@@ -4249,146 +4252,147 @@ INSTANTIATE_TEST_SUITE_P(
// address line results in two profiles being saved.
SaveImportedProfileTestCase{
ProfileFields(),
- {{ADDRESS_HOME_LINE1, "123 Aquarium St."}}},
+ {{ADDRESS_HOME_LINE1, u"123 Aquarium St."}}},
// Test that saving an identical profile except for the second
// address line results in two profiles being saved.
SaveImportedProfileTestCase{ProfileFields(),
- {{ADDRESS_HOME_LINE2, "unit 7"}}},
+ {{ADDRESS_HOME_LINE2, u"unit 7"}}},
// Tests that saving an identical profile that has a new piece of
// information (company name) results in a merge and that the
// original empty value gets overwritten by the new information.
- SaveImportedProfileTestCase{{{COMPANY_NAME, ""}},
+ SaveImportedProfileTestCase{{{COMPANY_NAME, u""}},
ProfileFields(),
- {{COMPANY_NAME, "Fox"}}},
+ {{COMPANY_NAME, u"Fox"}}},
// Tests that saving an identical profile except a loss of
// information results in a merge but the original value is not
// overwritten (no information loss).
SaveImportedProfileTestCase{ProfileFields(),
- {{COMPANY_NAME, ""}},
- {{COMPANY_NAME, "Fox"}}},
+ {{COMPANY_NAME, u""}},
+ {{COMPANY_NAME, u"Fox"}}},
// Tests that saving an identical profile except a slightly
// different postal code results in a merge with the new value kept.
- SaveImportedProfileTestCase{{{ADDRESS_HOME_ZIP, "R2C 0A1"}},
- {{ADDRESS_HOME_ZIP, "R2C0A1"}},
- {{ADDRESS_HOME_ZIP, "R2C0A1"}}},
- SaveImportedProfileTestCase{{{ADDRESS_HOME_ZIP, "R2C0A1"}},
- {{ADDRESS_HOME_ZIP, "R2C 0A1"}},
- {{ADDRESS_HOME_ZIP, "R2C 0A1"}}},
- SaveImportedProfileTestCase{{{ADDRESS_HOME_ZIP, "r2c 0a1"}},
- {{ADDRESS_HOME_ZIP, "R2C0A1"}},
- {{ADDRESS_HOME_ZIP, "R2C0A1"}}},
+ SaveImportedProfileTestCase{{{ADDRESS_HOME_ZIP, u"R2C 0A1"}},
+ {{ADDRESS_HOME_ZIP, u"R2C0A1"}},
+ {{ADDRESS_HOME_ZIP, u"R2C0A1"}}},
+ SaveImportedProfileTestCase{{{ADDRESS_HOME_ZIP, u"R2C0A1"}},
+ {{ADDRESS_HOME_ZIP, u"R2C 0A1"}},
+ {{ADDRESS_HOME_ZIP, u"R2C 0A1"}}},
+ SaveImportedProfileTestCase{{{ADDRESS_HOME_ZIP, u"r2c 0a1"}},
+ {{ADDRESS_HOME_ZIP, u"R2C0A1"}},
+ {{ADDRESS_HOME_ZIP, u"R2C0A1"}}},
// Tests that saving an identical profile plus a new piece of
// information on the address line 2 results in a merge and that the
// original empty value gets overwritten by the new information.
- SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE2, ""}},
+ SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE2, u""}},
ProfileFields(),
- {{ADDRESS_HOME_LINE2, "unit 5"}}},
+ {{ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical profile except a loss of
// information on the address line 2 results in a merge but that the
// original value gets not overwritten (no information loss).
SaveImportedProfileTestCase{ProfileFields(),
- {{ADDRESS_HOME_LINE2, ""}},
- {{ADDRESS_HOME_LINE2, "unit 5"}}},
+ {{ADDRESS_HOME_LINE2, u""}},
+ {{ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical except with more punctuation in
// the fist address line, while the second is empty, results in a
// merge and that the original address gets overwritten.
- SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE2, ""}},
- {{ADDRESS_HOME_LINE2, ""},
- {ADDRESS_HOME_LINE1, "123, Zoo St."}},
- {{ADDRESS_HOME_LINE1, "123, Zoo St."}}},
+ SaveImportedProfileTestCase{
+ {{ADDRESS_HOME_LINE2, u""}},
+ {{ADDRESS_HOME_LINE2, u""},
+ {ADDRESS_HOME_LINE1, u"123, Zoo St."}},
+ {{ADDRESS_HOME_LINE1, u"123, Zoo St."}}},
// Tests that saving an identical profile except with less
// punctuation in the fist address line, while the second is empty,
// results in a merge and that the longer address is retained.
- SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE2, ""},
- {ADDRESS_HOME_LINE1, "123, Zoo St."}},
- {{ADDRESS_HOME_LINE2, ""}},
- {{ADDRESS_HOME_LINE1, "123 Zoo St"}}},
+ SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE2, u""},
+ {ADDRESS_HOME_LINE1, u"123, Zoo St."}},
+ {{ADDRESS_HOME_LINE2, u""}},
+ {{ADDRESS_HOME_LINE1, u"123 Zoo St"}}},
// Tests that saving an identical profile except additional
// punctuation in the two address lines results in a merge and that
// the newer address is retained.
SaveImportedProfileTestCase{ProfileFields(),
- {{ADDRESS_HOME_LINE1, "123, Zoo St."},
- {ADDRESS_HOME_LINE2, "unit. 5"}},
- {{ADDRESS_HOME_LINE1, "123, Zoo St."},
- {ADDRESS_HOME_LINE2, "unit. 5"}}},
+ {{ADDRESS_HOME_LINE1, u"123, Zoo St."},
+ {ADDRESS_HOME_LINE2, u"unit. 5"}},
+ {{ADDRESS_HOME_LINE1, u"123, Zoo St."},
+ {ADDRESS_HOME_LINE2, u"unit. 5"}}},
// Tests that saving an identical profile except less punctuation in
// the two address lines results in a merge and that the newer
// address is retained.
- SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE1, "123, Zoo St."},
- {ADDRESS_HOME_LINE2, "unit. 5"}},
+ SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE1, u"123, Zoo St."},
+ {ADDRESS_HOME_LINE2, u"unit. 5"}},
ProfileFields(),
- {{ADDRESS_HOME_LINE1, "123 Zoo St"},
- {ADDRESS_HOME_LINE2, "unit 5"}}},
+ {{ADDRESS_HOME_LINE1, u"123 Zoo St"},
+ {ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical profile with accented characters
// in the two address lines results in a merge and that the newer
// address is retained.
SaveImportedProfileTestCase{ProfileFields(),
- {{ADDRESS_HOME_LINE1, "123 Zôö St"},
- {ADDRESS_HOME_LINE2, "üñìt 5"}},
- {{ADDRESS_HOME_LINE1, "123 Zôö St"},
- {ADDRESS_HOME_LINE2, "üñìt 5"}}},
+ {{ADDRESS_HOME_LINE1, u"123 Zôö St"},
+ {ADDRESS_HOME_LINE2, u"üñìt 5"}},
+ {{ADDRESS_HOME_LINE1, u"123 Zôö St"},
+ {ADDRESS_HOME_LINE2, u"üñìt 5"}}},
// Tests that saving an identical profile without accented
// characters in the two address lines results in a merge and that
// the newer address is retained.
- SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE1, "123 Zôö St"},
- {ADDRESS_HOME_LINE2, "üñìt 5"}},
+ SaveImportedProfileTestCase{{{ADDRESS_HOME_LINE1, u"123 Zôö St"},
+ {ADDRESS_HOME_LINE2, u"üñìt 5"}},
ProfileFields(),
- {{ADDRESS_HOME_LINE1, "123 Zoo St"},
- {ADDRESS_HOME_LINE2, "unit 5"}}},
+ {{ADDRESS_HOME_LINE1, u"123 Zoo St"},
+ {ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical profile except that the address
// line 1 is in the address line 2 results in a merge and that the
// multi-lne address is retained.
SaveImportedProfileTestCase{
ProfileFields(),
- {{ADDRESS_HOME_LINE1, "123 Zoo St, unit 5"},
- {ADDRESS_HOME_LINE2, ""}},
- {{ADDRESS_HOME_LINE1, "123 Zoo St"},
- {ADDRESS_HOME_LINE2, "unit 5"}}},
+ {{ADDRESS_HOME_LINE1, u"123 Zoo St, unit 5"},
+ {ADDRESS_HOME_LINE2, u""}},
+ {{ADDRESS_HOME_LINE1, u"123 Zoo St"},
+ {ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical profile except that the address
// line 2 contains part of the old address line 1 results in a merge
// and that the original address lines of the reference profile get
// overwritten.
SaveImportedProfileTestCase{
- {{ADDRESS_HOME_LINE1, "123 Zoo St, unit 5"},
- {ADDRESS_HOME_LINE2, ""}},
+ {{ADDRESS_HOME_LINE1, u"123 Zoo St, unit 5"},
+ {ADDRESS_HOME_LINE2, u""}},
ProfileFields(),
- {{ADDRESS_HOME_LINE1, "123 Zoo St"},
- {ADDRESS_HOME_LINE2, "unit 5"}}},
+ {{ADDRESS_HOME_LINE1, u"123 Zoo St"},
+ {ADDRESS_HOME_LINE2, u"unit 5"}}},
// Tests that saving an identical profile except that the state is
// the abbreviation instead of the full form results in a merge and
// that the original state gets overwritten.
- SaveImportedProfileTestCase{{{ADDRESS_HOME_STATE, "California"}},
+ SaveImportedProfileTestCase{{{ADDRESS_HOME_STATE, u"California"}},
ProfileFields(),
- {{ADDRESS_HOME_STATE, "CA"}}},
+ {{ADDRESS_HOME_STATE, u"CA"}}},
// Tests that saving an identical profile except that the state is
// the full form instead of the abbreviation results in a merge and
// that the abbreviated state is retained.
SaveImportedProfileTestCase{ProfileFields(),
- {{ADDRESS_HOME_STATE, "California"}},
- {{ADDRESS_HOME_STATE, "CA"}}},
+ {{ADDRESS_HOME_STATE, u"California"}},
+ {{ADDRESS_HOME_STATE, u"CA"}}},
// Tests that saving and identical profile except that the company
// name has different punctuation and case results in a merge and
// that the syntax of the new profile replaces the old one.
- SaveImportedProfileTestCase{{{COMPANY_NAME, "Stark inc"}},
- {{COMPANY_NAME, "Stark Inc."}},
- {{COMPANY_NAME, "Stark Inc."}}})));
+ SaveImportedProfileTestCase{{{COMPANY_NAME, u"Stark inc"}},
+ {{COMPANY_NAME, u"Stark Inc."}},
+ {{COMPANY_NAME, u"Stark Inc."}}})));
// Tests that MergeProfile tries to merge the imported profile into the
// existing profile in decreasing order of frecency.
@@ -5667,8 +5671,7 @@ TEST_F(PersonalDataManagerTest,
// Make sure that the added address has the email address of the currently
// signed-in user.
- EXPECT_EQ(base::UTF8ToUTF16(kPrimaryAccountEmail),
- profiles[0]->GetRawInfo(EMAIL_ADDRESS));
+ EXPECT_EQ(kPrimaryAccountEmail16, profiles[0]->GetRawInfo(EMAIL_ADDRESS));
}
// Tests that the converted wallet address is merged into an existing local
@@ -5697,8 +5700,8 @@ TEST_F(PersonalDataManagerTest,
// Add a different server profile.
std::vector<AutofillProfile> server_profiles;
- server_profiles.push_back(
- AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
+ server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
+ kServerAddressId);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "", "Fox",
"1212 Center", "Bld. 5", "Orlando", "FL", "", "US", "");
// Wallet only provides a full name, so the above first and last names
@@ -5718,8 +5721,7 @@ TEST_F(PersonalDataManagerTest,
personal_data_->AddCreditCard(local_card);
std::vector<CreditCard> server_cards;
- server_cards.push_back(
- CreditCard(CreditCard::MASKED_SERVER_CARD, "server_card1"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "server_card1");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1111" /* Visa */, "01", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
@@ -5832,8 +5834,8 @@ TEST_F(
// Add a server profile.
std::vector<AutofillProfile> server_profiles;
- server_profiles.push_back(
- AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
+ server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
+ kServerAddressId);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "", "",
"1212 Center", "Bld. 5", "Orlando", "FL", "32801", "US",
"");
@@ -5847,8 +5849,8 @@ TEST_F(
server_profiles.back().set_use_count(100);
// Add a similar server profile.
- server_profiles.push_back(
- AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId2));
+ server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
+ kServerAddressId2);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe",
"john@doe.com", "Fox", "1212 Center", "Bld. 5",
"Orlando", "FL", "", "US", "");
@@ -5870,8 +5872,7 @@ TEST_F(
WaitForOnPersonalDataChanged();
std::vector<CreditCard> server_cards;
- server_cards.push_back(
- CreditCard(CreditCard::MASKED_SERVER_CARD, "server_card1"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "server_card1");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1111" /* Visa */, "01", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
@@ -5942,8 +5943,8 @@ TEST_F(
// Add a server profile.
std::vector<AutofillProfile> server_profiles;
- server_profiles.push_back(
- AutofillProfile(AutofillProfile::SERVER_PROFILE, kServerAddressId));
+ server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
+ kServerAddressId);
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "", "Fox",
"1212 Center", "Bld. 5", "Orlando", "FL", "", "US", "");
// Wallet only provides a full name, so the above first and last names
@@ -5954,8 +5955,7 @@ TEST_F(
// Add a server card that have the server address as billing address.
std::vector<CreditCard> server_cards;
- server_cards.push_back(
- CreditCard(CreditCard::MASKED_SERVER_CARD, "server_card1"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "server_card1");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1111" /* Visa */, "01", "2999", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
@@ -5985,8 +5985,7 @@ TEST_F(
personal_data_->GetCreditCards()[0]->billing_address_id());
// Add a new server card that has the same billing address as the old one.
- server_cards.push_back(
- CreditCard(CreditCard::MASKED_SERVER_CARD, "server_card2"));
+ server_cards.emplace_back(CreditCard::MASKED_SERVER_CARD, "server_card2");
test::SetCreditCardInfo(&server_cards.back(), "John Dillinger",
"1112" /* Visa */, "01", "2888", "1");
server_cards.back().SetNetworkForMaskedCard(kVisaCard);
@@ -6027,7 +6026,7 @@ TEST_F(PersonalDataManagerTest, DoNotConvertWalletAddressesInEphemeralStorage) {
// Setup.
///////////////////////////////////////////////////////////////////////
ResetPersonalDataManager(USER_MODE_NORMAL,
- /*use_sync_transport_mode=*/true);
+ /*use_account_server_storage=*/true);
ASSERT_FALSE(personal_data_->IsSyncFeatureEnabled());
// Add a local profile.
@@ -6039,15 +6038,15 @@ TEST_F(PersonalDataManagerTest, DoNotConvertWalletAddressesInEphemeralStorage) {
// Add two server profiles: The first is unique, the second is similar to the
// local one but has some additional info.
std::vector<AutofillProfile> server_profiles;
- server_profiles.push_back(
- AutofillProfile(AutofillProfile::SERVER_PROFILE, "server_address1"));
+ server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
+ "server_address1");
test::SetProfileInfo(&server_profiles.back(), "John", "", "Doe", "", "",
"1212 Center", "Bld. 5", "Orlando", "FL", "32801", "US",
"");
server_profiles.back().SetRawInfo(NAME_FULL, u"John Doe");
- server_profiles.push_back(
- AutofillProfile(AutofillProfile::SERVER_PROFILE, "server_address2"));
+ server_profiles.emplace_back(AutofillProfile::SERVER_PROFILE,
+ "server_address2");
test::SetProfileInfo(&server_profiles.back(), "Josephine", "Alicia", "Saenz",
"joewayne@me.xyz", "Fox", "1212 Center.", "Bld. 5",
"Orlando", "FL", "32801", "US", "19482937549");
@@ -6251,6 +6250,10 @@ TEST_F(PersonalDataManagerTest, LogStoredCreditCardMetrics) {
}
}
+ // Sets the virtual card enrollment state for the first card.
+ server_cards[0].set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::ENROLLED);
+
SetServerCards(server_cards);
// SetServerCards modifies the metadata (use_count and use_date)
@@ -6289,6 +6292,8 @@ TEST_F(PersonalDataManagerTest, LogStoredCreditCardMetrics) {
"Autofill.StoredCreditCardCount.Server.Masked", 2, 1);
histogram_tester.ExpectBucketCount(
"Autofill.StoredCreditCardCount.Server.Unmasked", 2, 1);
+ histogram_tester.ExpectTotalCount(
+ "Autofill.StoredCreditCardCount.Server.WithVirtualCardMetadata", 1);
}
TEST_F(PersonalDataManagerTest, RemoveExpiredCreditCardsNotUsedSinceTimestamp) {
@@ -6622,7 +6627,7 @@ TEST_F(PersonalDataManagerTest, ExcludeServerSideCards) {
TEST_F(PersonalDataManagerTest, ServerCardsShowInTransportMode) {
// Set up PersonalDataManager in transport mode.
ResetPersonalDataManager(USER_MODE_NORMAL,
- /*use_sync_transport_mode=*/true);
+ /*use_account_server_storage=*/true);
SetUpThreeCardTypes();
AccountInfo active_info = SetActiveSecondaryAccount();
@@ -6655,7 +6660,7 @@ TEST_F(PersonalDataManagerTest, ServerCardsShowInTransportMode) {
TEST_F(PersonalDataManagerTest, ServerCardsShowInTransportMode_NeedOptIn) {
// Set up PersonalDataManager in transport mode.
ResetPersonalDataManager(USER_MODE_NORMAL,
- /*use_sync_transport_mode=*/true);
+ /*use_account_server_storage=*/true);
SetUpThreeCardTypes();
AccountInfo active_info = SetActiveSecondaryAccount();
@@ -6866,7 +6871,7 @@ TEST_F(
// cards still works.
TEST_F(PersonalDataManagerTest, UsePersistentServerStorage) {
ResetPersonalDataManager(USER_MODE_NORMAL,
- /*use_sync_transport_mode=*/false);
+ /*use_account_server_storage=*/false);
SetUpThreeCardTypes();
// include_server_cards is set to false, therefore no server cards should be
@@ -6884,7 +6889,7 @@ TEST_F(PersonalDataManagerTest, UsePersistentServerStorage) {
TEST_F(PersonalDataManagerTest, SwitchServerStorages) {
// Start with account storage.
ResetPersonalDataManager(USER_MODE_NORMAL,
- /*use_sync_transport_mode=*/true);
+ /*use_account_server_storage=*/true);
SetUpThreeCardTypes();
// Check that we do have 2 server cards, as expected.
@@ -6921,7 +6926,7 @@ TEST_F(PersonalDataManagerTest, SwitchServerStorages) {
// cards still works.
TEST_F(PersonalDataManagerTest, UseCorrectStorageForDifferentCards) {
ResetPersonalDataManager(USER_MODE_NORMAL,
- /*use_sync_transport_mode=*/true);
+ /*use_account_server_storage=*/true);
// Add a server card.
CreditCard server_card;
@@ -7384,6 +7389,128 @@ TEST_F(PersonalDataManagerTest, OnAccountsCookieDeletedByUserAction) {
prefs_->GetDictionary(prefs::kAutofillSyncTransportOptIn)->DictEmpty());
}
+TEST_F(PersonalDataManagerTest, SaveProfileUpdateStrikes) {
+ std::string guid = "a21f010a-eac1-41fc-aee9-c06bbedfb292";
+
+ EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(guid));
+
+ personal_data_->AddStrikeToBlockProfileUpdate(guid);
+ EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(guid));
+
+ personal_data_->AddStrikeToBlockProfileUpdate(guid);
+ EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(guid));
+
+ // After the third strike, the guid should be blocked.
+ personal_data_->AddStrikeToBlockProfileUpdate(guid);
+ EXPECT_TRUE(personal_data_->IsProfileUpdateBlocked(guid));
+
+ // Until the strikes are removed again.
+ personal_data_->RemoveStrikesToBlockProfileUpdate(guid);
+ EXPECT_FALSE(personal_data_->IsProfileUpdateBlocked(guid));
+}
+
+TEST_F(PersonalDataManagerTest, SaveProfileSaveStrikes) {
+ GURL domain("https://www.block.me/index.html");
+
+ EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
+
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
+ EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
+
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
+ EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
+
+ // After the third strike, the domain should be blocked.
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
+ EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
+
+ // Until the strikes are removed again.
+ personal_data_->RemoveStrikesToBlockNewProfileImportForDomain(domain);
+ EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
+}
+
+TEST_F(PersonalDataManagerTest, ClearFullBrowsingHistory) {
+ GURL domain("https://www.block.me/index.html");
+
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(domain);
+ EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
+
+ history::DeletionInfo deletion_info = history::DeletionInfo::ForAllHistory();
+
+ personal_data_->OnURLsDeleted(/*history_service=*/nullptr, deletion_info);
+
+ EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(domain));
+}
+
+TEST_F(PersonalDataManagerTest, ClearUrlsFromBrowsingHistory) {
+ GURL first_url("https://www.block.me/index.html");
+ GURL second_url("https://www.block.too/index.html");
+
+ // Add strikes to block both domains.
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
+ EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(first_url));
+
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
+ EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(second_url));
+
+ history::URLRows deleted_urls = {history::URLRow(first_url)};
+
+ history::DeletionInfo deletion_info =
+ history::DeletionInfo::ForUrls(deleted_urls, {});
+
+ personal_data_->OnURLsDeleted(/*history_service=*/nullptr, deletion_info);
+
+ // The strikes for `domain` should be deleted, but the strikes for
+ // `another_domain` should not.
+ EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(first_url));
+ EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(second_url));
+}
+
+TEST_F(PersonalDataManagerTest, ClearUrlsFromBrowsingHistoryInTimeRange) {
+ GURL first_url("https://www.block.me/index.html");
+ GURL second_url("https://www.block.too/index.html");
+
+ TestAutofillClock test_clock;
+
+ // Add strikes to block both domains.
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(first_url);
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
+ EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(first_url));
+
+ test_clock.Advance(base::TimeDelta::FromHours(1));
+ base::Time end_of_deletion = AutofillClock::Now();
+ test_clock.Advance(base::TimeDelta::FromHours(1));
+
+ personal_data_->AddStrikeToBlockNewProfileImportForDomain(second_url);
+ EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(second_url));
+
+ history::URLRows deleted_urls = {history::URLRow(first_url),
+ history::URLRow(second_url)};
+
+ history::DeletionInfo deletion_info(
+ history::DeletionTimeRange(base::Time::Min(), end_of_deletion), false,
+ deleted_urls, {},
+ absl::make_optional<std::set<GURL>>({first_url, second_url}));
+
+ personal_data_->OnURLsDeleted(/*history_service=*/nullptr, deletion_info);
+
+ // The strikes for `first_url` should be deleted because the strikes have been
+ // added within the deletion time range.
+ EXPECT_FALSE(personal_data_->IsNewProfileImportBlockedForDomain(first_url));
+ // The last strike for 'second_url' was collected after the deletion time
+ // range and therefore, the blocking should prevail.
+ EXPECT_TRUE(personal_data_->IsNewProfileImportBlockedForDomain(second_url));
+}
+
// On mobile, no dedicated opt-in is required for WalletSyncTransport - the
// user is always considered opted-in and thus this test doesn't make sense.
#if !defined(OS_ANDROID) && !defined(OS_IOS)
@@ -7418,7 +7545,7 @@ TEST_F(PersonalDataManagerTest, ShouldShowCardsFromAccountOption) {
// independently, one by one.
// Set everything up so that the proposition should be shown.
- // Set an an active secondary account.
+ // Set an active secondary account.
AccountInfo active_info;
active_info.email = kPrimaryAccountEmail;
active_info.account_id = CoreAccountId("account_id");
@@ -7427,7 +7554,7 @@ TEST_F(PersonalDataManagerTest, ShouldShowCardsFromAccountOption) {
// Set a server credit card.
std::vector<CreditCard> server_cards;
- server_cards.push_back(CreditCard(CreditCard::FULL_SERVER_CARD, "c789"));
+ server_cards.emplace_back(CreditCard::FULL_SERVER_CARD, "c789");
test::SetCreditCardInfo(&server_cards.back(), "Clyde Barrow",
"378282246310005" /* American Express */, "04",
"2999", "1");
@@ -7833,16 +7960,16 @@ TEST_F(PersonalDataManagerTest, AddAndGetUpiId) {
}
struct ShareNicknameTestParam {
- std::string local_nickname;
- std::string server_nickname;
- std::string expected_nickname;
+ std::u16string local_nickname;
+ std::u16string server_nickname;
+ std::u16string expected_nickname;
};
const ShareNicknameTestParam kShareNicknameTestParam[] = {
- {"", "", ""},
- {"", "server nickname", "server nickname"},
- {"local nickname", "", "local nickname"},
- {"local nickname", "server nickname", "local nickname"},
+ {u"", u"", u""},
+ {u"", u"server nickname", u"server nickname"},
+ {u"local nickname", u"", u"local nickname"},
+ {u"local nickname", u"server nickname", u"local nickname"},
};
class PersonalDataManagerTestForSharingNickname
@@ -7850,9 +7977,9 @@ class PersonalDataManagerTestForSharingNickname
public testing::WithParamInterface<ShareNicknameTestParam> {
public:
PersonalDataManagerTestForSharingNickname()
- : local_nickname_(base::UTF8ToUTF16(GetParam().local_nickname)),
- server_nickname_(base::UTF8ToUTF16(GetParam().server_nickname)),
- expected_nickname_(base::UTF8ToUTF16(GetParam().expected_nickname)) {}
+ : local_nickname_(GetParam().local_nickname),
+ server_nickname_(GetParam().server_nickname),
+ expected_nickname_(GetParam().expected_nickname) {}
CreditCard GetLocalCard() {
CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
diff --git a/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc b/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc
index 982fe71a51b..0109d9dd101 100644
--- a/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc
+++ b/chromium/components/autofill/core/browser/randomized_encoder_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "components/autofill/core/browser/randomized_encoder.h"
+#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "components/autofill/core/common/signatures.h"
#include "components/unified_consent/pref_names.h"
@@ -33,7 +34,7 @@ std::string ReferenceEncodeImpl(base::StringPiece coins,
size_t bit_offset,
size_t bit_stride) {
// Encode all of the bits.
- std::string all_bits = noise.as_string();
+ std::string all_bits(noise);
size_t value_length = std::min(value.length(), noise.length());
for (size_t i = 0; i < value_length; ++i) {
all_bits[i] = (value[i] & coins[i]) | (all_bits[i] & ~coins[i]);
diff --git a/chromium/components/autofill/core/browser/payments/strike_database.cc b/chromium/components/autofill/core/browser/strike_database.cc
index a4acdfcbdb8..dbd8aeeba14 100644
--- a/chromium/components/autofill/core/browser/payments/strike_database.cc
+++ b/chromium/components/autofill/core/browser/strike_database.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/autofill/core/browser/payments/strike_database.h"
+#include "components/autofill/core/browser/strike_database.h"
#include <algorithm>
#include <string>
@@ -46,10 +46,10 @@ StrikeDatabase::StrikeDatabase(
weak_ptr_factory_.GetWeakPtr()));
}
-StrikeDatabase::~StrikeDatabase() {}
+StrikeDatabase::~StrikeDatabase() = default;
int StrikeDatabase::AddStrikes(int strikes_increase, const std::string& key) {
- DCHECK(strikes_increase > 0);
+ DCHECK_GT(strikes_increase, 0);
int num_strikes =
strike_map_cache_.count(key) // Cache has entry for |key|.
? strike_map_cache_[key].num_strikes() + strikes_increase
@@ -76,16 +76,45 @@ void StrikeDatabase::ClearStrikes(const std::string& key) {
ClearAllProtoStrikesForKey(key, base::DoNothing());
}
-void StrikeDatabase::ClearAllStrikesForProject(
+std::map<std::string, StrikeData>& StrikeDatabase::GetStrikeCache() {
+ return strike_map_cache_;
+}
+
+void StrikeDatabase::SetStrikeData(const std::string& key, int num_strikes) {
+ if (num_strikes == 0) {
+ ClearStrikes(key);
+ return;
+ }
+ StrikeData data;
+ data.set_num_strikes(num_strikes);
+ data.set_last_update_timestamp(
+ AutofillClock::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
+ UpdateCache(key, data);
+ SetProtoStrikeData(key, data, base::DoNothing());
+}
+
+std::vector<std::string> StrikeDatabase::GetAllStrikeKeysForProject(
const std::string& project_prefix) {
- std::vector<std::string> keys_to_delete;
+ std::vector<std::string> project_keys;
for (std::pair<std::string, StrikeData> entry : strike_map_cache_) {
if (entry.first.find(project_prefix) == 0) {
- keys_to_delete.push_back(entry.first);
+ project_keys.push_back(entry.first);
}
}
- for (std::string key : keys_to_delete)
- ClearStrikes(key);
+ return project_keys;
+}
+
+void StrikeDatabase::ClearAllStrikesForProject(
+ const std::string& project_prefix) {
+ ClearStrikesForKeys(GetAllStrikeKeysForProject(project_prefix));
+}
+
+void StrikeDatabase::ClearStrikesForKeys(
+ const std::vector<std::string>& keys_to_remove) {
+ for (const auto& key : keys_to_remove) {
+ strike_map_cache_.erase(key);
+ }
+ ClearAllProtoStrikesForKeys(keys_to_remove, base::DoNothing());
}
void StrikeDatabase::ClearAllStrikes() {
@@ -93,6 +122,10 @@ void StrikeDatabase::ClearAllStrikes() {
ClearAllProtoStrikes(base::DoNothing());
}
+std::string StrikeDatabase::GetPrefixFromKey(const std::string& key) const {
+ return key.substr(0, key.find(KeyDeliminator()));
+}
+
StrikeDatabase::StrikeDatabase() : db_(nullptr) {}
void StrikeDatabase::OnDatabaseInit(leveldb_proto::Enums::InitStatus status) {
@@ -123,19 +156,6 @@ void StrikeDatabase::OnDatabaseLoadKeysAndEntries(
strike_map_cache_.insert(entries->begin(), entries->end());
}
-void StrikeDatabase::SetStrikeData(const std::string& key, int num_strikes) {
- if (num_strikes == 0) {
- ClearStrikes(key);
- return;
- }
- StrikeData data;
- data.set_num_strikes(num_strikes);
- data.set_last_update_timestamp(
- AutofillClock::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
- UpdateCache(key, data);
- SetProtoStrikeData(key, data, base::DoNothing());
-}
-
void StrikeDatabase::GetProtoStrikes(const std::string& key,
const StrikesCallback& outer_callback) {
if (!database_initialized_) {
@@ -161,8 +181,8 @@ void StrikeDatabase::ClearAllProtoStrikes(
outer_callback);
}
-void StrikeDatabase::ClearAllProtoStrikesForKey(
- const std::string& key,
+void StrikeDatabase::ClearAllProtoStrikesForKeys(
+ const std::vector<std::string>& keys,
const ClearStrikesCallback& outer_callback) {
if (!database_initialized_) {
outer_callback.Run(false);
@@ -170,13 +190,20 @@ void StrikeDatabase::ClearAllProtoStrikesForKey(
}
std::unique_ptr<std::vector<std::string>> keys_to_remove(
new std::vector<std::string>());
- keys_to_remove->push_back(key);
+ *keys_to_remove = keys;
db_->UpdateEntries(
/*entries_to_save=*/std::make_unique<
leveldb_proto::ProtoDatabase<StrikeData>::KeyEntryVector>(),
/*keys_to_remove=*/std::move(keys_to_remove), outer_callback);
}
+void StrikeDatabase::ClearAllProtoStrikesForKey(
+ const std::string& key,
+ const ClearStrikesCallback& outer_callback) {
+ std::vector<std::string> keys_to_delete({key});
+ ClearAllProtoStrikesForKeys(keys_to_delete, outer_callback);
+}
+
void StrikeDatabase::GetProtoStrikeData(const std::string& key,
const GetValueCallback& callback) {
if (!database_initialized_) {
@@ -221,8 +248,4 @@ void StrikeDatabase::UpdateCache(const std::string& key,
strike_map_cache_[key] = data;
}
-std::string StrikeDatabase::GetPrefixFromKey(const std::string& key) {
- return key.substr(0, key.find(kKeyDeliminator));
-}
-
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/strike_database.h b/chromium/components/autofill/core/browser/strike_database.h
index 0a2dd30890c..9d54f898248 100644
--- a/chromium/components/autofill/core/browser/payments/strike_database.h
+++ b/chromium/components/autofill/core/browser/strike_database.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_PAYMENTS_STRIKE_DATABASE_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_STRIKE_DATABASE_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_H_
#include <map>
#include <memory>
@@ -13,6 +13,7 @@
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
+#include "components/autofill/core/browser/strike_database_base.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/leveldb_proto/public/proto_database.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
@@ -21,12 +22,6 @@ namespace autofill {
extern const base::FilePath::StringPieceType kStrikeDatabaseFileName;
-namespace {
-const char kKeyDeliminator[] = "__";
-} // namespace
-
-class StrikeData;
-
// Manages data on whether different Autofill opportunities should be offered to
// the user. Projects can earn strikes in a number of ways; for instance, if a
// user ignores or declines a prompt, or if a user accepts a prompt but the task
@@ -35,7 +30,7 @@ class StrikeData;
// projects. It should not be used directly, but rather by implementing the
// StrikeDatabaseIntegratorBase (which contains a pointer to StrikeDatabase)
// for specific projects.
-class StrikeDatabase : public KeyedService {
+class StrikeDatabase : public StrikeDatabaseBase {
public:
using ClearStrikesCallback = base::RepeatingCallback<void(bool success)>;
@@ -57,28 +52,19 @@ class StrikeDatabase : public KeyedService {
base::FilePath profile_path);
~StrikeDatabase() override;
- // Increases in-memory cache by |strikes_increase| and updates underlying
- // ProtoDatabase.
- int AddStrikes(int strikes_increase, const std::string& key);
-
- // Removes |strikes_decrease| in-memory cache strikes, updates
- // last_update_timestamp, and updates underlying ProtoDatabase.
- int RemoveStrikes(int strikes_decrease, const std::string& key);
-
- // Returns strike count from in-memory cache.
- int GetStrikes(const std::string& key);
-
- // Removes database entry for |key| from in-memory cache and underlying
- // ProtoDatabase.
- void ClearStrikes(const std::string& key);
-
- // Removes all database entries from in-memory cache and underlying
- // ProtoDatabase for the whole project.
- void ClearAllStrikesForProject(const std::string& project_prefix);
-
- // Removes all database entries from in-memory cache and underlying
- // ProtoDatabase.
- void ClearAllStrikes();
+ // StrikeDatabaseBase:
+ int AddStrikes(int strikes_increase, const std::string& key) override;
+ int RemoveStrikes(int strikes_decrease, const std::string& key) override;
+ int GetStrikes(const std::string& key) override;
+ void ClearStrikes(const std::string& key) override;
+ std::vector<std::string> GetAllStrikeKeysForProject(
+ const std::string& project_prefix) override;
+ void ClearStrikesForKeys(
+ const std::vector<std::string>& keys_to_remove) override;
+ void ClearAllStrikesForProject(const std::string& project_prefix) override;
+ void ClearAllStrikes() override;
+ std::string GetPrefixFromKey(const std::string& key) const override;
+ void SetStrikeData(const std::string& key, int num_strikes) override;
protected:
friend class StrikeDatabaseIntegratorBase;
@@ -98,6 +84,9 @@ class StrikeDatabase : public KeyedService {
// Number of attempts at initializing the ProtoDatabase.
int num_init_attempts_ = 0;
+ // StrikeDatabaseBase:
+ std::map<std::string, StrikeData>& GetStrikeCache() override;
+
private:
FRIEND_TEST_ALL_PREFIXES(ChromeBrowsingDataRemoverDelegateTest,
StrikeDatabaseEmptyOnAutofillRemoveEverything);
@@ -117,10 +106,6 @@ class StrikeDatabase : public KeyedService {
bool success,
std::unique_ptr<std::map<std::string, StrikeData>> entries);
- // Updates the StrikeData for |key| in the cache and ProtoDatabase to have
- // |num_strikes|, and the current time as timestamp.
- void SetStrikeData(const std::string& key, int num_strikes);
-
// Passes the number of strikes for |key| to |outer_callback|. In the case
// that the database fails to retrieve the strike update or if no entry is
// found for |key|, 0 is passed.
@@ -138,6 +123,11 @@ class StrikeDatabase : public KeyedService {
const std::string& key,
const ClearStrikesCallback& outer_callback);
+ // Same as |ClearAllProtoStrikesForKey()| but for a vector of |keys|.
+ virtual void ClearAllProtoStrikesForKeys(
+ const std::vector<std::string>& keys,
+ const ClearStrikesCallback& outer_callback);
+
// Passes success status and StrikeData entry for |key| to |inner_callback|.
void GetProtoStrikeData(const std::string& key,
const GetValueCallback& inner_callback);
@@ -159,12 +149,9 @@ class StrikeDatabase : public KeyedService {
// Sets the entry for |key| in |strike_map_cache_| to |data|.
void UpdateCache(const std::string& key, const StrikeData& data);
- // Extracts per-project prefix from |key|.
- std::string GetPrefixFromKey(const std::string& key);
-
base::WeakPtrFactory<StrikeDatabase> weak_ptr_factory_{this};
};
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_STRIKE_DATABASE_H_
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_H_
diff --git a/chromium/components/autofill/core/browser/strike_database_base.cc b/chromium/components/autofill/core/browser/strike_database_base.cc
new file mode 100644
index 00000000000..1c9399d620a
--- /dev/null
+++ b/chromium/components/autofill/core/browser/strike_database_base.cc
@@ -0,0 +1,17 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/strike_database_base.h"
+
+namespace autofill {
+
+StrikeDatabaseBase::StrikeDatabaseBase() = default;
+
+StrikeDatabaseBase::~StrikeDatabaseBase() = default;
+
+std::string StrikeDatabaseBase::KeyDeliminator() {
+ return kKeyDeliminator;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/strike_database_base.h b/chromium/components/autofill/core/browser/strike_database_base.h
new file mode 100644
index 00000000000..08423295a96
--- /dev/null
+++ b/chromium/components/autofill/core/browser/strike_database_base.h
@@ -0,0 +1,83 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_BASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_BASE_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "components/keyed_service/core/keyed_service.h"
+
+namespace autofill {
+
+namespace {
+const char kKeyDeliminator[] = "__";
+} // namespace
+
+class StrikeData;
+
+// Interface for the StrikeDatabase which is used by the
+// StrikeDatabaseIntegratorBase that is oblivious to the underlying database
+// specifics. This class is also used to allow for simpler testing.
+class StrikeDatabaseBase : public KeyedService {
+ public:
+ StrikeDatabaseBase();
+ ~StrikeDatabaseBase() override;
+
+ // Increases in-memory cache by |strikes_increase| and updates underlying
+ // ProtoDatabase.
+ virtual int AddStrikes(int strikes_increase, const std::string& key) = 0;
+
+ // Removes |strikes_decrease| in-memory cache strikes, updates
+ // last_update_timestamp, and updates underlying ProtoDatabase.
+ virtual int RemoveStrikes(int strikes_decrease, const std::string& key) = 0;
+
+ // Returns strike count from in-memory cache.
+ virtual int GetStrikes(const std::string& key) = 0;
+
+ // Removes database entry for |key| from in-memory cache and underlying
+ // ProtoDatabase.
+ virtual void ClearStrikes(const std::string& key) = 0;
+
+ // Returns all strike keys for |project_prefix|.
+ // The returned keys still contain the |project_prefix|.
+ virtual std::vector<std::string> GetAllStrikeKeysForProject(
+ const std::string& project_prefix) = 0;
+
+ // Removes database entry for keys in |keys_to_remove| from in-memory cache
+ // and the underlying ProtoDatabase.
+ virtual void ClearStrikesForKeys(
+ const std::vector<std::string>& keys_to_remove) = 0;
+
+ // Removes all database entries from in-memory cache and underlying
+ // ProtoDatabase for the whole project.
+ virtual void ClearAllStrikesForProject(const std::string& project_prefix) = 0;
+
+ // Removes all database entries from in-memory cache and underlying
+ // ProtoDatabase.
+ virtual void ClearAllStrikes() = 0;
+
+ // Extracts per-project prefix from |key|.
+ virtual std::string GetPrefixFromKey(const std::string& key) const = 0;
+
+ // Updates the StrikeData for |key| in the cache and ProtoDatabase to have
+ // |num_strikes|, and the current time as timestamp.
+ virtual void SetStrikeData(const std::string& key, int num_strikes) = 0;
+
+ protected:
+ friend class StrikeDatabaseIntegratorBase;
+
+ // Returns a pointer to the internal cache.
+ virtual std::map<std::string, StrikeData>& GetStrikeCache() = 0;
+
+ // Returns the deliminator that separates the project identifier and the id in
+ // the strike key.
+ static std::string KeyDeliminator();
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_BASE_H_
diff --git a/chromium/components/autofill/core/browser/strike_database_integrator_base.cc b/chromium/components/autofill/core/browser/strike_database_integrator_base.cc
new file mode 100644
index 00000000000..6d63e2ee4c8
--- /dev/null
+++ b/chromium/components/autofill/core/browser/strike_database_integrator_base.cc
@@ -0,0 +1,202 @@
+// Copyright 2018 The Chromium Authors. 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/strike_database_integrator_base.h"
+
+#include <algorithm>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/task/post_task.h"
+#include "base/time/time.h"
+#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/autofill/core/common/autofill_clock.h"
+#include "components/leveldb_proto/public/proto_database_provider.h"
+
+namespace autofill {
+
+StrikeDatabaseIntegratorBase::StrikeDatabaseIntegratorBase(
+ StrikeDatabaseBase* strike_database)
+ : strike_database_(strike_database) {}
+
+StrikeDatabaseIntegratorBase::~StrikeDatabaseIntegratorBase() = default;
+
+bool StrikeDatabaseIntegratorBase::IsMaxStrikesLimitReached(
+ const std::string& id) const {
+ CheckIdUniqueness(id);
+ return GetStrikes(id) >= GetMaxStrikesLimit();
+}
+
+int StrikeDatabaseIntegratorBase::AddStrike(const std::string& id) {
+ CheckIdUniqueness(id);
+ return AddStrikes(1, id);
+}
+
+int StrikeDatabaseIntegratorBase::AddStrikes(int strikes_increase,
+ const std::string& id) {
+ CheckIdUniqueness(id);
+ int num_strikes = strike_database_->AddStrikes(strikes_increase, GetKey(id));
+ // If a new strike entry was created, run the routine to limit the number of
+ // stored entries. This is a noop for most strike counters.
+ if (num_strikes == strikes_increase) {
+ LimitNumberOfStoredEntries();
+ }
+
+ base::UmaHistogramCounts1000(
+ "Autofill.StrikeDatabase.NthStrikeAdded." + GetProjectPrefix(),
+ num_strikes);
+ return num_strikes;
+}
+
+int StrikeDatabaseIntegratorBase::RemoveStrike(const std::string& id) {
+ CheckIdUniqueness(id);
+ return strike_database_->RemoveStrikes(1, GetKey(id));
+}
+
+int StrikeDatabaseIntegratorBase::RemoveStrikes(int strike_decrease,
+ const std::string& id) {
+ CheckIdUniqueness(id);
+ return strike_database_->RemoveStrikes(strike_decrease, GetKey(id));
+}
+
+int StrikeDatabaseIntegratorBase::GetStrikes(const std::string& id) const {
+ CheckIdUniqueness(id);
+ return strike_database_->GetStrikes(GetKey(id));
+}
+
+void StrikeDatabaseIntegratorBase::ClearStrikes(const std::string& id) {
+ CheckIdUniqueness(id);
+ strike_database_->ClearStrikes(GetKey(id));
+}
+
+void StrikeDatabaseIntegratorBase::ClearAllStrikes() {
+ strike_database_->ClearAllStrikesForProject(GetProjectPrefix());
+}
+
+size_t StrikeDatabaseIntegratorBase::CountEntries() const {
+ return base::ranges::count_if(GetStrikeCache(), [&](const auto& entry) {
+ return strike_database_->GetPrefixFromKey(entry.first) ==
+ GetProjectPrefix();
+ });
+}
+
+void StrikeDatabaseIntegratorBase::LimitNumberOfStoredEntries() {
+ if (!NumberOfEntriesExceedsLimits()) {
+ return;
+ }
+
+ DCHECK(GetMaximumEntries().has_value());
+ DCHECK(!GetMaximumEntriesAfterCleanup().has_value() ||
+ GetMaximumEntriesAfterCleanup() <= GetMaximumEntries());
+
+ size_t maximum_size = GetMaximumEntriesAfterCleanup().has_value()
+ ? GetMaximumEntriesAfterCleanup().value()
+ : GetMaximumEntries().value();
+
+ std::vector<std::pair<std::string, int64_t>> entries;
+ entries.reserve(GetStrikeCache().size());
+ for (const auto& entry : GetStrikeCache()) {
+ if (strike_database_->GetPrefixFromKey(entry.first) != GetProjectPrefix()) {
+ continue;
+ }
+ entries.emplace_back(entry.first, entry.second.last_update_timestamp());
+ }
+
+ if (entries.size() <= maximum_size) {
+ return;
+ }
+ size_t elements_to_delete = entries.size() - maximum_size;
+
+ std::vector<std::string> keys_to_delete;
+
+ // Sort by timestamp.
+ std::sort(entries.begin(), entries.end(),
+ [](auto& a, auto& b) { return a.second < b.second; });
+
+ for (size_t i = 0; i < elements_to_delete; i++) {
+ keys_to_delete.push_back(entries.at(i).first);
+ }
+
+ ClearStrikesForKeys(keys_to_delete);
+}
+
+bool StrikeDatabaseIntegratorBase::NumberOfEntriesExceedsLimits() const {
+ if (!GetMaximumEntries().has_value()) {
+ return false;
+ }
+
+ return CountEntries() > GetMaximumEntries();
+}
+
+void StrikeDatabaseIntegratorBase::RemoveExpiredStrikes() {
+ if (!GetExpiryTimeDelta().has_value()) {
+ // Strikes don't expire.
+ return;
+ }
+ std::vector<std::string> expired_keys;
+ for (auto entry : strike_database_->GetStrikeCache()) {
+ // Only consider keys from the current strike database integrator.
+ if (strike_database_->GetPrefixFromKey(entry.first) != GetProjectPrefix()) {
+ continue;
+ }
+ if (GetEntryAge(entry.second) > GetExpiryTimeDelta().value()) {
+ if (strike_database_->GetStrikes(entry.first) > 0) {
+ expired_keys.push_back(entry.first);
+ base::UmaHistogramCounts1000(
+ "Autofill.StrikeDatabase.StrikesPresentWhenStrikeExpired." +
+ strike_database_->GetPrefixFromKey(entry.first),
+ strike_database_->GetStrikes(entry.first));
+ }
+ }
+ }
+ for (std::string key : expired_keys) {
+ int strikes_to_remove = 1;
+ // If the key is already over the limit, remove additional strikes to
+ // emulate setting it back to the limit. These are done together to avoid
+ // multiple calls to the file system ProtoDatabase.
+ strikes_to_remove +=
+ std::max(0, strike_database_->GetStrikes(key) - GetMaxStrikesLimit());
+ strike_database_->RemoveStrikes(strikes_to_remove, key);
+ }
+}
+
+void StrikeDatabaseIntegratorBase::ClearStrikesForKeys(
+ const std::vector<std::string>& keys) {
+ strike_database_->ClearStrikesForKeys(keys);
+}
+
+std::string StrikeDatabaseIntegratorBase::GetIdFromKey(
+ const std::string& key) const {
+ std::string prefix = GetProjectPrefix() + kKeyDeliminator;
+ if (!base::StartsWith(key, prefix)) {
+ return std::string();
+ }
+ return key.substr(prefix.length(), std::string::npos);
+}
+
+base::TimeDelta StrikeDatabaseIntegratorBase::GetEntryAge(
+ const StrikeData& strike_data) {
+ return AutofillClock::Now() - base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMicroseconds(
+ strike_data.last_update_timestamp()));
+}
+
+std::string StrikeDatabaseIntegratorBase::GetKey(const std::string& id) const {
+ return GetProjectPrefix() + kKeyDeliminator + id;
+}
+
+absl::optional<size_t> StrikeDatabaseIntegratorBase::GetMaximumEntries() const {
+ return absl::nullopt;
+}
+
+absl::optional<size_t>
+StrikeDatabaseIntegratorBase::GetMaximumEntriesAfterCleanup() const {
+ return absl::nullopt;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/strike_database_integrator_base.h b/chromium/components/autofill/core/browser/strike_database_integrator_base.h
index 60538eaed43..af0c1946564 100644
--- a/chromium/components/autofill/core/browser/payments/strike_database_integrator_base.h
+++ b/chromium/components/autofill/core/browser/strike_database_integrator_base.h
@@ -2,12 +2,18 @@
// 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_STRIKE_DATABASE_INTEGRATOR_BASE_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_STRIKE_DATABASE_INTEGRATOR_BASE_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_BASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_BASE_H_
#include <stdint.h>
+#include <map>
+#include <string>
+#include <vector>
-#include "components/autofill/core/browser/payments/strike_database.h"
+#include "base/gtest_prod_util.h"
+#include "base/time/time.h"
+#include "components/autofill/core/browser/strike_database_base.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -21,12 +27,12 @@ static const char kSharedId[] = "shared_id";
// be loaded once per browser session.
class StrikeDatabaseIntegratorBase {
public:
- StrikeDatabaseIntegratorBase(StrikeDatabase* strike_database);
+ explicit StrikeDatabaseIntegratorBase(StrikeDatabaseBase* strike_database);
virtual ~StrikeDatabaseIntegratorBase();
// Returns whether or not strike count for |id| has reached the strike limit
// set by GetMaxStrikesLimit().
- bool IsMaxStrikesLimitReached(const std::string& id = kSharedId);
+ bool IsMaxStrikesLimitReached(const std::string& id = kSharedId) const;
// Increments in-memory cache and updates underlying ProtoDatabase.
int AddStrike(const std::string& id = kSharedId);
@@ -44,7 +50,7 @@ class StrikeDatabaseIntegratorBase {
int RemoveStrikes(int strikes_decrease, const std::string& id = kSharedId);
// Returns strike count from in-memory cache.
- int GetStrikes(const std::string& id = kSharedId);
+ int GetStrikes(const std::string& id = kSharedId) const;
// Removes all database entries from in-memory cache and underlying
// ProtoDatabase.
@@ -54,59 +60,100 @@ class StrikeDatabaseIntegratorBase {
// ProtoDatabase for the whole project.
void ClearAllStrikes();
+ // Count strike entries for this project.
+ size_t CountEntries() const;
+
protected:
- // Removes all strikes in which it has been longer than GetExpiryTimeMicros()
- // past |last_update_timestamp|.
+ // Runs a cleanup routine to remove the stored strike elements with the oldest
+ // update timestamps when `NumberOfEntriesExceedsLimits()`. The number of
+ // elements should be reduced to `GetMaximumEntriesAfterCleanup()`.
+ void LimitNumberOfStoredEntries();
+
+ // Returns true if the number of stored entries exceeds the limit.
+ bool NumberOfEntriesExceedsLimits() const;
+
+ // Removes one strike for each key where it has been longer than
+ // GetExpiryTimeMicros() since |last_update_timestamp|.
void RemoveExpiredStrikes();
+ // Removes all database entries from in-memory cache and underlying
+ // ProtoDatabase for keys in `keys`.
+ void ClearStrikesForKeys(const std::vector<std::string>& keys);
+
+ // Get a readonly reference to the cache.
+ const std::map<std::string, StrikeData>& GetStrikeCache() const {
+ return strike_database_->GetStrikeCache();
+ }
+
+ // Returns the id the key was built from with `GetKey(id)`.
+ std::string GetIdFromKey(const std::string& key) const;
+
+ // Returns the age of a strike entry.
+ static base::TimeDelta GetEntryAge(const StrikeData& strike_data);
+
private:
FRIEND_TEST_ALL_PREFIXES(ChromeBrowsingDataRemoverDelegateTest,
StrikeDatabaseEmptyOnAutofillRemoveEverything);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
+ ClearStrikesForKeys);
+ FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
+ GetKeyForStrikeDatabaseIntegratorUniqueIdTest);
+ FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
+ IdFromKey);
+ FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
NonExpiringStrikesDoNotExpire);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
+ RemoveExpiredStrikesOnlyConsidersCurrentIntegrator);
+ FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
RemoveExpiredStrikesTest);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
- GetKeyForStrikeDatabaseIntegratorUniqueIdTest);
+ RemoveExpiredStrikesTestLogsUMA);
FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
RemoveExpiredStrikesUniqueIdTest);
- FRIEND_TEST_ALL_PREFIXES(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
- RemoveExpiredStrikesTestLogsUMA);
friend class SaveCardInfobarEGTestHelper;
friend class StrikeDatabaseTest;
friend class StrikeDatabaseTester;
- StrikeDatabase* strike_database_;
+ StrikeDatabaseBase* strike_database_;
// For projects in which strikes don't have unique identifiers, the
// id suffix is set to |kSharedId|. This makes sure that projects requiring
// unique IDs always specify |id| instead of relying on the default shared
// value, while projects where unique IDs are unnecessary always fall back to
// the default shared value.
- void CheckIdUniqueness(std::string id) {
+ void CheckIdUniqueness(const std::string& id) const {
DCHECK(UniqueIdsRequired() == (id != kSharedId));
}
// Generates key based on project-specific string identifier.
- std::string GetKey(const std::string& id);
+ std::string GetKey(const std::string& id) const;
+
+ // Returns the maximum number of entries that should be stored for this
+ // project prefix. absl::nullopt means that there is no limit.
+ virtual absl::optional<size_t> GetMaximumEntries() const;
+
+ // Returns the maximum number of entries that should remain after a cleanup.
+ // This number should be smaller then `GetMaximumEntries()` to create some
+ // headroom. absl::nullopt means that `GetMaximumEntries()` should be used.
+ virtual absl::optional<size_t> GetMaximumEntriesAfterCleanup() const;
// Returns a prefix unique to each project, which will be used to create
// database key.
- virtual std::string GetProjectPrefix() = 0;
+ virtual std::string GetProjectPrefix() const = 0;
// Returns the maximum number of strikes after which the project's Autofill
// opportunity stops being offered.
- virtual int GetMaxStrikesLimit() = 0;
+ virtual int GetMaxStrikesLimit() const = 0;
- // Returns the time after which the most recent strike should expire. If the
- // Optional is empty, then strikes don't expire.
- virtual base::Optional<int64_t> GetExpiryTimeMicros() = 0;
+ // Returns the time delta after which the most recent strike should expire.
+ // If the Optional is empty, then strikes don't expire.
+ virtual absl::optional<base::TimeDelta> GetExpiryTimeDelta() const = 0;
// Returns whether or not a unique string identifier is required for every
// strike in this project.
- virtual bool UniqueIdsRequired() = 0;
+ virtual bool UniqueIdsRequired() const = 0;
};
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_STRIKE_DATABASE_INTEGRATOR_BASE_H_
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_BASE_H_
diff --git a/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database.cc b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.cc
index 6cb36f3bfc4..a3e5b9039e4 100644
--- a/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database.cc
+++ b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.cc
@@ -2,21 +2,20 @@
// 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/strike_database_integrator_test_strike_database.h"
+#include "components/autofill/core/browser/strike_database_integrator_test_strike_database.h"
#include "components/autofill/core/browser/proto/strike_data.pb.h"
namespace autofill {
-const char kProjectPrefix[] = "StrikeDatabaseIntegratorTest";
const int kMaxStrikesLimit = 6;
StrikeDatabaseIntegratorTestStrikeDatabase::
StrikeDatabaseIntegratorTestStrikeDatabase(
StrikeDatabase* strike_database,
- base::Optional<int64_t> expiry_time_micros)
+ absl::optional<base::TimeDelta> expiry_time_delta)
: StrikeDatabaseIntegratorTestStrikeDatabase(strike_database) {
- expiry_time_micros_ = expiry_time_micros;
+ expiry_time_delta_ = expiry_time_delta;
}
StrikeDatabaseIntegratorTestStrikeDatabase::
@@ -26,22 +25,33 @@ StrikeDatabaseIntegratorTestStrikeDatabase::
}
StrikeDatabaseIntegratorTestStrikeDatabase::
- ~StrikeDatabaseIntegratorTestStrikeDatabase() {}
+ StrikeDatabaseIntegratorTestStrikeDatabase(
+ StrikeDatabase* strike_database,
+ absl::optional<base::TimeDelta> expiry_time_delta,
+ std::string& project_prefix)
+ : StrikeDatabaseIntegratorTestStrikeDatabase(strike_database,
+ expiry_time_delta) {
+ project_prefix_ = project_prefix;
+}
+
+StrikeDatabaseIntegratorTestStrikeDatabase::
+ ~StrikeDatabaseIntegratorTestStrikeDatabase() = default;
-std::string StrikeDatabaseIntegratorTestStrikeDatabase::GetProjectPrefix() {
- return kProjectPrefix;
+std::string StrikeDatabaseIntegratorTestStrikeDatabase::GetProjectPrefix()
+ const {
+ return project_prefix_;
}
-int StrikeDatabaseIntegratorTestStrikeDatabase::GetMaxStrikesLimit() {
+int StrikeDatabaseIntegratorTestStrikeDatabase::GetMaxStrikesLimit() const {
return kMaxStrikesLimit;
}
-base::Optional<int64_t>
-StrikeDatabaseIntegratorTestStrikeDatabase::GetExpiryTimeMicros() {
- return expiry_time_micros_;
+absl::optional<base::TimeDelta>
+StrikeDatabaseIntegratorTestStrikeDatabase::GetExpiryTimeDelta() const {
+ return expiry_time_delta_;
}
-bool StrikeDatabaseIntegratorTestStrikeDatabase::UniqueIdsRequired() {
+bool StrikeDatabaseIntegratorTestStrikeDatabase::UniqueIdsRequired() const {
return unique_ids_required_;
}
@@ -50,4 +60,14 @@ void StrikeDatabaseIntegratorTestStrikeDatabase::SetUniqueIdsRequired(
unique_ids_required_ = unique_ids_required;
}
+absl::optional<size_t>
+StrikeDatabaseIntegratorTestStrikeDatabase::GetMaximumEntries() const {
+ return maximum_entries_;
+}
+
+absl::optional<size_t>
+StrikeDatabaseIntegratorTestStrikeDatabase::GetMaximumEntriesAfterCleanup()
+ const {
+ return maximum_entries_after_cleanup_;
+}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.h b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.h
new file mode 100644
index 00000000000..33053e76ed1
--- /dev/null
+++ b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database.h
@@ -0,0 +1,56 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_
+
+#include <stdint.h>
+#include <string>
+
+#include "components/autofill/core/browser/strike_database.h"
+#include "components/autofill/core/browser/strike_database_integrator_base.h"
+
+namespace autofill {
+
+// Mock per-project implementation of StrikeDatabase to test the functions in
+// StrikeDatabaseIntegrator.
+class StrikeDatabaseIntegratorTestStrikeDatabase
+ : public StrikeDatabaseIntegratorBase {
+ public:
+ StrikeDatabaseIntegratorTestStrikeDatabase(
+ StrikeDatabase* strike_database,
+ absl::optional<base::TimeDelta> expiry_time_delta);
+ explicit StrikeDatabaseIntegratorTestStrikeDatabase(
+ StrikeDatabase* strike_database);
+ // This constructor initializes the TestStrikeDatabase with a non-default
+ // project prefix.
+ StrikeDatabaseIntegratorTestStrikeDatabase(
+ StrikeDatabase* strike_database,
+ absl::optional<base::TimeDelta> expiry_time_delta,
+ std::string& project_prefix);
+ ~StrikeDatabaseIntegratorTestStrikeDatabase() override;
+
+ absl::optional<size_t> GetMaximumEntries() const override;
+ absl::optional<size_t> GetMaximumEntriesAfterCleanup() const override;
+
+ std::string GetProjectPrefix() const override;
+ int GetMaxStrikesLimit() const override;
+ absl::optional<base::TimeDelta> GetExpiryTimeDelta() const override;
+ bool UniqueIdsRequired() const override;
+
+ void SetUniqueIdsRequired(bool unique_ids_required);
+
+ private:
+ bool unique_ids_required_ = false;
+ absl::optional<base::TimeDelta> expiry_time_delta_ =
+ base::TimeDelta::FromDays(365);
+
+ absl::optional<size_t> maximum_entries_ = 10;
+ absl::optional<size_t> maximum_entries_after_cleanup_ = 5;
+ std::string project_prefix_ = "StrikeDatabaseIntegratorTest";
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_STRIKE_DATABASE_INTEGRATOR_TEST_STRIKE_DATABASE_H_
diff --git a/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database_unittest.cc b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database_unittest.cc
index e87e7df4a68..5182966e9c5 100644
--- a/chromium/components/autofill/core/browser/payments/strike_database_integrator_test_strike_database_unittest.cc
+++ b/chromium/components/autofill/core/browser/strike_database_integrator_test_strike_database_unittest.cc
@@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/autofill/core/browser/payments/strike_database_integrator_test_strike_database.h"
+#include "components/autofill/core/browser/strike_database_integrator_test_strike_database.h"
#include <utility>
#include <vector>
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -23,7 +24,7 @@ namespace autofill {
class StrikeDatabaseIntegratorTestStrikeDatabaseTest : public ::testing::Test {
public:
- StrikeDatabaseIntegratorTestStrikeDatabaseTest() {}
+ StrikeDatabaseIntegratorTestStrikeDatabaseTest() = default;
void SetUp() override {
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
@@ -38,7 +39,7 @@ class StrikeDatabaseIntegratorTestStrikeDatabaseTest : public ::testing::Test {
strike_database_service_.get());
no_expiry_strike_database_ =
std::make_unique<StrikeDatabaseIntegratorTestStrikeDatabase>(
- strike_database_service_.get(), base::nullopt);
+ strike_database_service_.get(), absl::nullopt);
}
void TearDown() override {
@@ -141,8 +142,8 @@ TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
EXPECT_EQ(2, strike_database_->GetStrikes());
// Advance clock to past expiry time.
- test_clock.Advance(base::TimeDelta::FromMicroseconds(
- strike_database_->GetExpiryTimeMicros().value() + 1));
+ test_clock.Advance(strike_database_->GetExpiryTimeDelta().value() +
+ base::TimeDelta::FromMicroseconds(1));
// One strike should be removed.
strike_database_->RemoveExpiredStrikes();
@@ -153,8 +154,8 @@ TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
EXPECT_EQ(11, strike_database_->GetStrikes());
// Advance clock to past expiry time.
- test_clock.Advance(base::TimeDelta::FromMicroseconds(
- strike_database_->GetExpiryTimeMicros().value() + 1));
+ test_clock.Advance(strike_database_->GetExpiryTimeDelta().value() +
+ base::TimeDelta::FromMicroseconds(1));
// Strike count should be one less than the max limit.
strike_database_->RemoveExpiredStrikes();
@@ -169,8 +170,8 @@ TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
EXPECT_EQ(2, strike_database_->GetStrikes());
// Advance clock to past expiry time.
- test_clock.Advance(base::TimeDelta::FromMicroseconds(
- strike_database_->GetExpiryTimeMicros().value() + 1));
+ test_clock.Advance(strike_database_->GetExpiryTimeDelta().value() +
+ base::TimeDelta::FromMicroseconds(1));
// One strike should be removed.
strike_database_->RemoveExpiredStrikes();
@@ -181,8 +182,8 @@ TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
EXPECT_EQ(11, strike_database_->GetStrikes());
// Advance clock to past expiry time.
- test_clock.Advance(base::TimeDelta::FromMicroseconds(
- strike_database_->GetExpiryTimeMicros().value() + 1));
+ test_clock.Advance(strike_database_->GetExpiryTimeDelta().value() +
+ base::TimeDelta::FromMicroseconds(1));
// Strike count should be one less than the max limit.
strike_database_->RemoveExpiredStrikes();
@@ -205,6 +206,38 @@ TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
11, 1);
}
+// This test verifies correctness of http://crbug/1206176.
+TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
+ RemoveExpiredStrikesOnlyConsidersCurrentIntegrator) {
+ autofill::TestAutofillClock test_clock;
+ test_clock.SetNow(AutofillClock::Now());
+ // Create a second test integrator, but with a different project prefix name,
+ // and whose strikes explicitly do not expire.
+ std::string other_project_prefix = "DifferentProjectPrefix";
+ std::unique_ptr<StrikeDatabaseIntegratorTestStrikeDatabase>
+ other_strike_database =
+ std::make_unique<StrikeDatabaseIntegratorTestStrikeDatabase>(
+ strike_database_service_.get(),
+ /*expiry_time_micros=*/absl::nullopt, other_project_prefix);
+
+ // Add a strike to both integrators.
+ strike_database_->AddStrike();
+ EXPECT_EQ(1, strike_database_->GetStrikes());
+ other_strike_database->AddStrike();
+ EXPECT_EQ(1, other_strike_database->GetStrikes());
+
+ // Advance clock to past expiry time for |strike_database_|.
+ test_clock.Advance(strike_database_->GetExpiryTimeDelta().value() +
+ base::TimeDelta::FromMicroseconds(1));
+
+ // Attempt to expire strikes. Only |strike_database_|'s keys should be
+ // affected.
+ strike_database_->RemoveExpiredStrikes();
+ other_strike_database->RemoveExpiredStrikes();
+ EXPECT_EQ(0, strike_database_->GetStrikes());
+ EXPECT_EQ(1, other_strike_database->GetStrikes());
+}
+
TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
GetKeyForStrikeDatabaseIntegratorUniqueIdTest) {
strike_database_->SetUniqueIdsRequired(true);
@@ -303,8 +336,8 @@ TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
strike_database_->AddStrike(unique_id_1);
// Advance clock to past the entry for |unique_id_1|'s expiry time.
- test_clock.Advance(base::TimeDelta::FromMicroseconds(
- strike_database_->GetExpiryTimeMicros().value() + 1));
+ test_clock.Advance(strike_database_->GetExpiryTimeDelta().value() +
+ base::TimeDelta::FromMicroseconds(1));
strike_database_->AddStrike(unique_id_2);
strike_database_->RemoveExpiredStrikes();
@@ -315,8 +348,8 @@ TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
EXPECT_EQ(1, strike_database_->GetStrikes(unique_id_2));
// Advance clock to past |unique_id_2|'s expiry time.
- test_clock.Advance(base::TimeDelta::FromMicroseconds(
- strike_database_->GetExpiryTimeMicros().value() + 1));
+ test_clock.Advance(strike_database_->GetExpiryTimeDelta().value() +
+ base::TimeDelta::FromMicroseconds(1));
strike_database_->RemoveExpiredStrikes();
@@ -325,4 +358,73 @@ TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
EXPECT_EQ(0, strike_database_->GetStrikes(unique_id_2));
}
+TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, CountEntries) {
+ strike_database_->SetUniqueIdsRequired(true);
+ const std::string unique_id_1 = "111";
+ const std::string unique_id_2 = "222";
+ const std::string unique_id_3 = "333";
+
+ EXPECT_EQ(0U, strike_database_->CountEntries());
+ strike_database_->AddStrike(unique_id_1);
+ EXPECT_EQ(1U, strike_database_->CountEntries());
+ strike_database_->AddStrike(unique_id_1);
+ EXPECT_EQ(1U, strike_database_->CountEntries());
+
+ strike_database_->AddStrike(unique_id_2);
+ strike_database_->AddStrike(unique_id_3);
+ EXPECT_EQ(3U, strike_database_->CountEntries());
+}
+
+TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, ClearStrikesForKeys) {
+ strike_database_->SetUniqueIdsRequired(true);
+ const std::string unique_id_1 = "111";
+ const std::string unique_id_2 = "222";
+ const std::string unique_id_3 = "333";
+
+ strike_database_->AddStrike(unique_id_1);
+ strike_database_->AddStrike(unique_id_2);
+ strike_database_->AddStrike(unique_id_3);
+ EXPECT_EQ(3U, strike_database_->CountEntries());
+
+ std::vector<std::string> keys_to_clear = {
+ strike_database_->GetKey(unique_id_1),
+ strike_database_->GetKey(unique_id_2)};
+ strike_database_->ClearStrikesForKeys(keys_to_clear);
+
+ EXPECT_EQ(1U, strike_database_->CountEntries());
+
+ EXPECT_EQ(0, strike_database_->GetStrikes(unique_id_1));
+ EXPECT_EQ(0, strike_database_->GetStrikes(unique_id_2));
+ EXPECT_EQ(1, strike_database_->GetStrikes(unique_id_3));
+}
+
+TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest, IdFromKey) {
+ strike_database_->SetUniqueIdsRequired(true);
+ const std::string unique_id = "111";
+ std::string key = strike_database_->GetKey(unique_id);
+ ASSERT_EQ(key, "StrikeDatabaseIntegratorTest__111");
+ EXPECT_EQ(unique_id, strike_database_->GetIdFromKey(key));
+}
+
+TEST_F(StrikeDatabaseIntegratorTestStrikeDatabaseTest,
+ LimitTheNumberOfElements) {
+ strike_database_->SetUniqueIdsRequired(true);
+ for (size_t i = 1; i <= 10; i++) {
+ strike_database_->AddStrike(base::NumberToString(i));
+ EXPECT_EQ(i, strike_database_->CountEntries());
+ }
+ // Once the 11th element is added the cleanup should reduce the number of
+ // elements to 5. Note that the index here is chosen to be smaller than the
+ // previous indices. The purpose is to ensure that the deletion is actually
+ // done in the order of time stamp and not index.
+ strike_database_->AddStrike(base::NumberToString(0));
+ EXPECT_EQ(5U, strike_database_->CountEntries());
+
+ // Verify that the oldest 6 elements have been deleted.
+ for (size_t i = 1; i <= 10; i++) {
+ EXPECT_EQ(i <= 6 ? 0 : 1,
+ strike_database_->GetStrikes(base::NumberToString(i)));
+ }
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/payments/strike_database_unittest.cc b/chromium/components/autofill/core/browser/strike_database_unittest.cc
index 1fa2338b11e..872746ac044 100644
--- a/chromium/components/autofill/core/browser/payments/strike_database_unittest.cc
+++ b/chromium/components/autofill/core/browser/strike_database_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/autofill/core/browser/payments/strike_database.h"
+#include "components/autofill/core/browser/strike_database.h"
#include <utility>
#include <vector>
@@ -57,7 +57,7 @@ class TestStrikeDatabase : public StrikeDatabase {
// ProtoDatabase.
class StrikeDatabaseTest : public ::testing::Test {
public:
- StrikeDatabaseTest() {}
+ StrikeDatabaseTest() = default;
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
@@ -114,6 +114,20 @@ class StrikeDatabaseTest : public ::testing::Test {
run_loop.Run();
}
+ void OnClearAllProtoStrikesForKeys(base::RepeatingClosure run_loop_closure,
+ bool success) {
+ run_loop_closure.Run();
+ }
+
+ void ClearAllProtoStrikesForKeys(const std::vector<std::string>& keys) {
+ base::RunLoop run_loop;
+ strike_database_->ClearAllProtoStrikesForKeys(
+ keys,
+ base::BindRepeating(&StrikeDatabaseTest::OnClearAllProtoStrikesForKeys,
+ base::Unretained(this), run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+
void OnClearAllProtoStrikes(base::RepeatingClosure run_loop_closure,
bool success) {
run_loop_closure.Run();
@@ -152,7 +166,7 @@ TEST_F(StrikeDatabaseTest, GetStrikeForNonZeroStrikesTest) {
std::vector<std::pair<std::string, StrikeData>> entries;
StrikeData data;
data.set_num_strikes(3);
- entries.push_back(std::make_pair(key, data));
+ entries.emplace_back(key, data);
AddProtoEntries(entries);
int strikes = GetProtoStrikes(key);
@@ -172,7 +186,7 @@ TEST_F(StrikeDatabaseTest, ClearStrikesForNonZeroStrikesTest) {
std::vector<std::pair<std::string, StrikeData>> entries;
StrikeData data;
data.set_num_strikes(3);
- entries.push_back(std::make_pair(key, data));
+ entries.emplace_back(key, data);
AddProtoEntries(entries);
int strikes = GetProtoStrikes(key);
@@ -182,6 +196,30 @@ TEST_F(StrikeDatabaseTest, ClearStrikesForNonZeroStrikesTest) {
EXPECT_EQ(0, strikes);
}
+TEST_F(StrikeDatabaseTest, ClearStrikesForMultipleNonZeroStrikesTest) {
+ // Set up database with 3 pre-existing strikes for three different keys.
+ const std::string key1 = "12345";
+ const std::string key2 = "67890";
+ const std::string key3 = "99000";
+ std::vector<std::pair<std::string, StrikeData>> entries;
+ StrikeData data;
+ data.set_num_strikes(3);
+ entries.emplace_back(key1, data);
+ entries.emplace_back(key2, data);
+ entries.emplace_back(key3, data);
+ AddProtoEntries(entries);
+
+ EXPECT_EQ(3, GetProtoStrikes(key1));
+ EXPECT_EQ(3, GetProtoStrikes(key2));
+ EXPECT_EQ(3, GetProtoStrikes(key3));
+ std::vector<std::string> keys_to_clear({key1, key2});
+ ClearAllProtoStrikesForKeys(keys_to_clear);
+ EXPECT_EQ(0, GetProtoStrikes(key1));
+ EXPECT_EQ(0, GetProtoStrikes(key2));
+ // The strikes for the third key should not have been reset.
+ EXPECT_EQ(3, GetProtoStrikes(key3));
+}
+
TEST_F(StrikeDatabaseTest, ClearStrikesForMultipleNonZeroStrikesEntriesTest) {
// Set up database with 3 pre-existing strikes at |key1|, and 5 pre-existing
// strikes at |key2|.
@@ -190,10 +228,10 @@ TEST_F(StrikeDatabaseTest, ClearStrikesForMultipleNonZeroStrikesEntriesTest) {
std::vector<std::pair<std::string, StrikeData>> entries;
StrikeData data1;
data1.set_num_strikes(3);
- entries.push_back(std::make_pair(key1, data1));
+ entries.emplace_back(key1, data1);
StrikeData data2;
data2.set_num_strikes(5);
- entries.push_back(std::make_pair(key2, data2));
+ entries.emplace_back(key2, data2);
AddProtoEntries(entries);
int strikes = GetProtoStrikes(key1);
@@ -228,4 +266,37 @@ TEST_F(StrikeDatabaseTest, ClearAllProtoStrikesTest) {
EXPECT_EQ(0, GetProtoStrikes(key2));
}
+TEST_F(StrikeDatabaseTest, GetAllStrikeKeysForProject) {
+ const std::string key1 = "project_12345";
+ const std::string key2 = "project_13579";
+ const std::string key3 = "otherproject_13579";
+ strike_database_->AddStrikes(1, key1);
+ strike_database_->AddStrikes(2, key2);
+ strike_database_->AddStrikes(2, key3);
+ std::vector<std::string> expected_keys({key1, key2});
+ EXPECT_EQ(strike_database_->GetAllStrikeKeysForProject("project"),
+ expected_keys);
+ expected_keys = {key3};
+ EXPECT_EQ(strike_database_->GetAllStrikeKeysForProject("otherproject"),
+ expected_keys);
+ ClearAllProtoStrikes();
+}
+
+TEST_F(StrikeDatabaseTest, ClearStrikesForKeys) {
+ const std::string key1 = "project_12345";
+ const std::string key2 = "project_13579";
+ const std::string key3 = "otherproject_13579";
+ strike_database_->AddStrikes(1, key1);
+ strike_database_->AddStrikes(2, key2);
+ strike_database_->AddStrikes(2, key3);
+ strike_database_->ClearStrikesForKeys(std::vector<std::string>({key1, key2}));
+ std::vector<std::string> expected_keys({});
+ EXPECT_EQ(strike_database_->GetAllStrikeKeysForProject("project"),
+ expected_keys);
+ expected_keys.emplace_back(key3);
+ EXPECT_EQ(strike_database_->GetAllStrikeKeysForProject("otherproject"),
+ expected_keys);
+ ClearAllProtoStrikes();
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.cc b/chromium/components/autofill/core/browser/test_autofill_client.cc
index a9a3deccf41..77d9a2dc4a2 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_client.cc
@@ -222,6 +222,8 @@ void TestAutofillClient::ConfirmCreditCardFillAssist(
void TestAutofillClient::ConfirmSaveAddressProfile(
const AutofillProfile& profile,
+ const AutofillProfile* original_profile,
+ SaveAddressProfilePromptOptions options,
AddressProfileSavePromptCallback callback) {}
bool TestAutofillClient::HasCreditCardScanFeature() {
diff --git a/chromium/components/autofill/core/browser/test_autofill_client.h b/chromium/components/autofill/core/browser/test_autofill_client.h
index d04af4ef608..9ae2bafe421 100644
--- a/chromium/components/autofill/core/browser/test_autofill_client.h
+++ b/chromium/components/autofill/core/browser/test_autofill_client.h
@@ -124,6 +124,8 @@ class TestAutofillClient : public AutofillClient {
base::OnceClosure callback) override;
void ConfirmSaveAddressProfile(
const AutofillProfile& profile,
+ const AutofillProfile* original_profile,
+ SaveAddressProfilePromptOptions options,
AddressProfileSavePromptCallback callback) override;
bool HasCreditCardScanFeature() override;
void ScanCreditCard(CreditCardScanCallback callback) override;
@@ -270,16 +272,16 @@ class TestAutofillClient : public AutofillClient {
bool confirm_save_credit_card_locally_called_ = false;
// Populated if save was offered. True if bubble was shown, false otherwise.
- base::Optional<bool> offer_to_save_credit_card_bubble_was_shown_;
+ absl::optional<bool> offer_to_save_credit_card_bubble_was_shown_;
// Populated if name fix flow was offered. True if bubble was shown, false
// otherwise.
- base::Optional<bool> credit_card_name_fix_flow_bubble_was_shown_;
+ absl::optional<bool> credit_card_name_fix_flow_bubble_was_shown_;
version_info::Channel channel_for_testing_ = version_info::Channel::UNKNOWN;
// Populated if local save or upload was offered.
- base::Optional<SaveCreditCardOptions> save_credit_card_options_;
+ absl::optional<SaveCreditCardOptions> save_credit_card_options_;
std::vector<std::string> migration_card_selection_;
diff --git a/chromium/components/autofill/core/browser/test_autofill_clock.h b/chromium/components/autofill/core/browser/test_autofill_clock.h
index 19ea0a8962b..73adc815260 100644
--- a/chromium/components/autofill/core/browser/test_autofill_clock.h
+++ b/chromium/components/autofill/core/browser/test_autofill_clock.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_CLOCK_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_CLOCK_H_
-#include <memory>
-
#include "base/macros.h"
#include "base/test/simple_test_clock.h"
diff --git a/chromium/components/autofill/core/browser/test_autofill_driver.cc b/chromium/components/autofill/core/browser/test_autofill_driver.cc
index 1577b463e7f..683bc93acf7 100644
--- a/chromium/components/autofill/core/browser/test_autofill_driver.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_driver.cc
@@ -103,6 +103,9 @@ net::IsolationInfo TestAutofillDriver::IsolationInfo() {
return isolation_info_;
}
+void TestAutofillDriver::SendFieldsEligibleForManualFillingToRenderer(
+ const std::vector<FieldRendererId>& fields) {}
+
void TestAutofillDriver::SetIsIncognito(bool is_incognito) {
is_incognito_ = is_incognito;
}
diff --git a/chromium/components/autofill/core/browser/test_autofill_driver.h b/chromium/components/autofill/core/browser/test_autofill_driver.h
index 0f43f44eca2..a3a298dcdb6 100644
--- a/chromium/components/autofill/core/browser/test_autofill_driver.h
+++ b/chromium/components/autofill/core/browser/test_autofill_driver.h
@@ -65,6 +65,8 @@ class TestAutofillDriver : public ContentAutofillDriver {
gfx::RectF TransformBoundingBoxToViewportCoordinates(
const gfx::RectF& bounding_box) override;
net::IsolationInfo IsolationInfo() override;
+ void SendFieldsEligibleForManualFillingToRenderer(
+ const std::vector<FieldRendererId>& fields) override;
// Methods unique to TestAutofillDriver that tests can use to specialize
// functionality.
diff --git a/chromium/components/autofill/core/browser/test_autofill_external_delegate.cc b/chromium/components/autofill/core/browser/test_autofill_external_delegate.cc
index d97cfccf5c2..71339b17087 100644
--- a/chromium/components/autofill/core/browser/test_autofill_external_delegate.cc
+++ b/chromium/components/autofill/core/browser/test_autofill_external_delegate.cc
@@ -12,7 +12,7 @@
namespace autofill {
TestAutofillExternalDelegate::TestAutofillExternalDelegate(
- AutofillManager* autofill_manager,
+ BrowserAutofillManager* autofill_manager,
AutofillDriver* autofill_driver,
bool call_parent_methods)
: AutofillExternalDelegate(autofill_manager, autofill_driver),
diff --git a/chromium/components/autofill/core/browser/test_autofill_external_delegate.h b/chromium/components/autofill/core/browser/test_autofill_external_delegate.h
index 2aa50399df6..d9752bbe5ad 100644
--- a/chromium/components/autofill/core/browser/test_autofill_external_delegate.h
+++ b/chromium/components/autofill/core/browser/test_autofill_external_delegate.h
@@ -14,9 +14,10 @@ namespace autofill {
class TestAutofillExternalDelegate : public AutofillExternalDelegate {
public:
- explicit TestAutofillExternalDelegate(AutofillManager* autofill_manager,
- AutofillDriver* autofill_driver,
- bool call_parent_methods);
+ explicit TestAutofillExternalDelegate(
+ BrowserAutofillManager* autofill_manager,
+ AutofillDriver* autofill_driver,
+ bool call_parent_methods);
~TestAutofillExternalDelegate() override;
// AutofillExternalDelegate overrides.
diff --git a/chromium/components/autofill/core/browser/test_autofill_tick_clock.h b/chromium/components/autofill/core/browser/test_autofill_tick_clock.h
index 481d493725c..1a15e289844 100644
--- a/chromium/components/autofill/core/browser/test_autofill_tick_clock.h
+++ b/chromium/components/autofill/core/browser/test_autofill_tick_clock.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_TICK_CLOCK_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_TICK_CLOCK_H_
-#include <memory>
-
#include "base/macros.h"
#include "base/test/simple_test_tick_clock.h"
diff --git a/chromium/components/autofill/core/browser/test_autofill_manager.cc b/chromium/components/autofill/core/browser/test_browser_autofill_manager.cc
index 82fe61d895a..47676a19450 100644
--- a/chromium/components/autofill/core/browser/test_autofill_manager.cc
+++ b/chromium/components/autofill/core/browser/test_browser_autofill_manager.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/autofill/core/browser/test_autofill_manager.h"
+#include "components/autofill/core/browser/test_browser_autofill_manager.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -15,55 +15,56 @@
namespace autofill {
-TestAutofillManager::TestAutofillManager(
+TestBrowserAutofillManager::TestBrowserAutofillManager(
AutofillDriver* driver,
AutofillClient* client,
TestPersonalDataManager* personal_data,
MockAutocompleteHistoryManager* autocomplete_history_manager)
- : AutofillManager(driver,
- client,
- personal_data,
- autocomplete_history_manager),
+ : BrowserAutofillManager(driver,
+ client,
+ personal_data,
+ autocomplete_history_manager),
personal_data_(personal_data) {}
-TestAutofillManager::~TestAutofillManager() {}
+TestBrowserAutofillManager::~TestBrowserAutofillManager() {}
-bool TestAutofillManager::IsAutofillProfileEnabled() const {
+bool TestBrowserAutofillManager::IsAutofillProfileEnabled() const {
return autofill_profile_enabled_;
}
-bool TestAutofillManager::IsAutofillCreditCardEnabled() const {
+bool TestBrowserAutofillManager::IsAutofillCreditCardEnabled() const {
return autofill_credit_card_enabled_;
}
-void TestAutofillManager::UploadFormData(const FormStructure& submitted_form,
- bool observed_submission) {
+void TestBrowserAutofillManager::UploadFormData(
+ const FormStructure& submitted_form,
+ bool observed_submission) {
submitted_form_signature_ = submitted_form.FormSignatureAsStr();
if (call_parent_upload_form_data_)
- AutofillManager::UploadFormData(submitted_form, observed_submission);
+ BrowserAutofillManager::UploadFormData(submitted_form, observed_submission);
}
-bool TestAutofillManager::MaybeStartVoteUploadProcess(
+bool TestBrowserAutofillManager::MaybeStartVoteUploadProcess(
std::unique_ptr<FormStructure> form_structure,
bool observed_submission) {
run_loop_ = std::make_unique<base::RunLoop>();
- if (AutofillManager::MaybeStartVoteUploadProcess(std::move(form_structure),
- observed_submission)) {
+ if (BrowserAutofillManager::MaybeStartVoteUploadProcess(
+ std::move(form_structure), observed_submission)) {
run_loop_->Run();
return true;
}
return false;
}
-void TestAutofillManager::UploadFormDataAsyncCallback(
+void TestBrowserAutofillManager::UploadFormDataAsyncCallback(
const FormStructure* submitted_form,
const base::TimeTicks& interaction_time,
const base::TimeTicks& submission_time,
bool observed_submission) {
run_loop_->Quit();
- if (expected_observed_submission_ != base::nullopt)
+ if (expected_observed_submission_ != absl::nullopt)
EXPECT_EQ(expected_observed_submission_, observed_submission);
// If we have expected field types set, make sure they match.
@@ -86,18 +87,18 @@ void TestAutofillManager::UploadFormDataAsyncCallback(
}
}
- AutofillManager::UploadFormDataAsyncCallback(
+ BrowserAutofillManager::UploadFormDataAsyncCallback(
submitted_form, interaction_time, submission_time, observed_submission);
}
-int TestAutofillManager::GetPackedCreditCardID(int credit_card_id) {
+int TestBrowserAutofillManager::GetPackedCreditCardID(int credit_card_id) {
std::string credit_card_guid =
base::StringPrintf("00000000-0000-0000-0000-%012d", credit_card_id);
return MakeFrontendID(credit_card_guid, std::string());
}
-void TestAutofillManager::AddSeenForm(
+void TestBrowserAutofillManager::AddSeenForm(
const FormData& form,
const std::vector<ServerFieldType>& heuristic_types,
const std::vector<ServerFieldType>& server_types) {
@@ -115,21 +116,21 @@ void TestAutofillManager::AddSeenForm(
form_interactions_ukm_logger()->OnFormsParsed(client()->GetUkmSourceId());
}
-void TestAutofillManager::AddSeenFormStructure(
+void TestBrowserAutofillManager::AddSeenFormStructure(
std::unique_ptr<FormStructure> form_structure) {
const auto id = form_structure->global_id();
(*mutable_form_structures())[id] = std::move(form_structure);
}
-void TestAutofillManager::ClearFormStructures() {
+void TestBrowserAutofillManager::ClearFormStructures() {
mutable_form_structures()->clear();
}
-const std::string TestAutofillManager::GetSubmittedFormSignature() {
+const std::string TestBrowserAutofillManager::GetSubmittedFormSignature() {
return submitted_form_signature_;
}
-void TestAutofillManager::SetAutofillProfileEnabled(
+void TestBrowserAutofillManager::SetAutofillProfileEnabled(
bool autofill_profile_enabled) {
autofill_profile_enabled_ = autofill_profile_enabled;
if (!autofill_profile_enabled_)
@@ -137,7 +138,7 @@ void TestAutofillManager::SetAutofillProfileEnabled(
personal_data_->ClearProfiles();
}
-void TestAutofillManager::SetAutofillCreditCardEnabled(
+void TestBrowserAutofillManager::SetAutofillCreditCardEnabled(
bool autofill_credit_card_enabled) {
autofill_credit_card_enabled_ = autofill_credit_card_enabled;
if (!autofill_credit_card_enabled_)
@@ -145,16 +146,16 @@ void TestAutofillManager::SetAutofillCreditCardEnabled(
personal_data_->ClearCreditCards();
}
-void TestAutofillManager::SetExpectedSubmittedFieldTypes(
+void TestBrowserAutofillManager::SetExpectedSubmittedFieldTypes(
const std::vector<ServerFieldTypeSet>& expected_types) {
expected_submitted_field_types_ = expected_types;
}
-void TestAutofillManager::SetExpectedObservedSubmission(bool expected) {
+void TestBrowserAutofillManager::SetExpectedObservedSubmission(bool expected) {
expected_observed_submission_ = expected;
}
-void TestAutofillManager::SetCallParentUploadFormData(bool value) {
+void TestBrowserAutofillManager::SetCallParentUploadFormData(bool value) {
call_parent_upload_form_data_ = value;
}
diff --git a/chromium/components/autofill/core/browser/test_autofill_manager.h b/chromium/components/autofill/core/browser/test_browser_autofill_manager.h
index 2a5b103953c..55fb7a86d00 100644
--- a/chromium/components/autofill/core/browser/test_autofill_manager.h
+++ b/chromium/components/autofill/core/browser/test_browser_autofill_manager.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_MANAGER_H_
-#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_MANAGER_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_BROWSER_AUTOFILL_MANAGER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_BROWSER_AUTOFILL_MANAGER_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
-#include "base/optional.h"
#include "base/run_loop.h"
-#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using base::TimeTicks;
@@ -24,16 +24,16 @@ class FormStructure;
class TestPersonalDataManager;
class MockAutocompleteHistoryManager;
-class TestAutofillManager : public AutofillManager {
+class TestBrowserAutofillManager : public BrowserAutofillManager {
public:
- TestAutofillManager(
+ TestBrowserAutofillManager(
AutofillDriver* driver,
AutofillClient* client,
TestPersonalDataManager* personal_data,
MockAutocompleteHistoryManager* autocomplete_history_manager);
- ~TestAutofillManager() override;
+ ~TestBrowserAutofillManager() override;
- // AutofillManager overrides.
+ // BrowserAutofillManager overrides.
bool IsAutofillProfileEnabled() const override;
bool IsAutofillCreditCardEnabled() const override;
void UploadFormData(const FormStructure& submitted_form,
@@ -46,7 +46,7 @@ class TestAutofillManager : public AutofillManager {
const base::TimeTicks& submission_time,
bool observed_submission) override;
- // Unique to TestAutofillManager:
+ // Unique to TestBrowserAutofillManager:
int GetPackedCreditCardID(int credit_card_id);
@@ -71,24 +71,23 @@ class TestAutofillManager : public AutofillManager {
void SetCallParentUploadFormData(bool value);
- using AutofillManager::is_rich_query_enabled;
- using AutofillManager::pending_form_data;
+ using BrowserAutofillManager::pending_form_data;
private:
TestPersonalDataManager* personal_data_; // Weak reference.
bool autofill_profile_enabled_ = true;
bool autofill_credit_card_enabled_ = true;
bool call_parent_upload_form_data_ = false;
- base::Optional<bool> expected_observed_submission_;
+ absl::optional<bool> expected_observed_submission_;
std::unique_ptr<base::RunLoop> run_loop_;
std::string submitted_form_signature_;
std::vector<ServerFieldTypeSet> expected_submitted_field_types_;
- DISALLOW_COPY_AND_ASSIGN(TestAutofillManager);
+ DISALLOW_COPY_AND_ASSIGN(TestBrowserAutofillManager);
};
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_AUTOFILL_MANAGER_H_
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_BROWSER_AUTOFILL_MANAGER_H_
diff --git a/chromium/components/autofill/core/browser/test_inmemory_strike_database.cc b/chromium/components/autofill/core/browser/test_inmemory_strike_database.cc
new file mode 100644
index 00000000000..81d85f58dcd
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_inmemory_strike_database.cc
@@ -0,0 +1,101 @@
+// Copyright 2021 The Chromium Authors. 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/test_inmemory_strike_database.h"
+
+#include <algorithm>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/metrics/histogram_functions.h"
+#include "base/time/time.h"
+#include "components/autofill/core/browser/proto/strike_data.pb.h"
+#include "components/autofill/core/common/autofill_clock.h"
+
+namespace autofill {
+
+TestInMemoryStrikeDatabase::TestInMemoryStrikeDatabase() = default;
+
+TestInMemoryStrikeDatabase::~TestInMemoryStrikeDatabase() = default;
+
+int TestInMemoryStrikeDatabase::AddStrikes(int strikes_increase,
+ const std::string& key) {
+ DCHECK_GT(strikes_increase, 0);
+ int num_strikes =
+ strike_map_cache_.count(key) // Cache has entry for |key|.
+ ? strike_map_cache_[key].num_strikes() + strikes_increase
+ : strikes_increase;
+ SetStrikeData(key, num_strikes);
+ return num_strikes;
+}
+
+int TestInMemoryStrikeDatabase::RemoveStrikes(int strikes_decrease,
+ const std::string& key) {
+ int num_strikes = GetStrikes(key);
+ num_strikes = std::max(0, num_strikes - strikes_decrease);
+ SetStrikeData(key, num_strikes);
+ return num_strikes;
+}
+
+int TestInMemoryStrikeDatabase::GetStrikes(const std::string& key) {
+ auto iter = strike_map_cache_.find(key);
+ return (iter != strike_map_cache_.end()) ? iter->second.num_strikes() : 0;
+}
+
+void TestInMemoryStrikeDatabase::ClearStrikes(const std::string& key) {
+ strike_map_cache_.erase(key);
+}
+
+std::map<std::string, StrikeData>&
+TestInMemoryStrikeDatabase::GetStrikeCache() {
+ return strike_map_cache_;
+}
+
+std::vector<std::string> TestInMemoryStrikeDatabase::GetAllStrikeKeysForProject(
+ const std::string& project_prefix) {
+ std::vector<std::string> project_keys;
+ for (std::pair<std::string, StrikeData> entry : strike_map_cache_) {
+ if (entry.first.find(project_prefix) == 0) {
+ project_keys.push_back(entry.first);
+ }
+ }
+ return project_keys;
+}
+
+void TestInMemoryStrikeDatabase::ClearAllStrikesForProject(
+ const std::string& project_prefix) {
+ ClearStrikesForKeys(GetAllStrikeKeysForProject(project_prefix));
+}
+
+void TestInMemoryStrikeDatabase::ClearStrikesForKeys(
+ const std::vector<std::string>& keys_to_remove) {
+ for (const auto& key : keys_to_remove) {
+ strike_map_cache_.erase(key);
+ }
+}
+
+void TestInMemoryStrikeDatabase::ClearAllStrikes() {
+ strike_map_cache_.clear();
+}
+
+std::string TestInMemoryStrikeDatabase::GetPrefixFromKey(
+ const std::string& key) const {
+ return key.substr(0, key.find(kKeyDeliminator));
+}
+
+void TestInMemoryStrikeDatabase::SetStrikeData(const std::string& key,
+ int num_strikes) {
+ if (num_strikes == 0) {
+ ClearStrikes(key);
+ return;
+ }
+ StrikeData data;
+ data.set_num_strikes(num_strikes);
+ data.set_last_update_timestamp(
+ AutofillClock::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
+ strike_map_cache_[key] = data;
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_inmemory_strike_database.h b/chromium/components/autofill/core/browser/test_inmemory_strike_database.h
new file mode 100644
index 00000000000..f7261a16849
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_inmemory_strike_database.h
@@ -0,0 +1,52 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_INMEMORY_STRIKE_DATABASE_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_INMEMORY_STRIKE_DATABASE_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "components/autofill/core/browser/strike_database_base.h"
+
+namespace autofill {
+
+class StrikeData;
+
+// Simplified implementation of the StrikeDatabase that only uses a local
+// cache for testing purposes.
+class TestInMemoryStrikeDatabase : public StrikeDatabaseBase {
+ public:
+ TestInMemoryStrikeDatabase();
+ ~TestInMemoryStrikeDatabase() override;
+
+ // StrikeDatabaseBase:
+ int AddStrikes(int strikes_increase, const std::string& key) override;
+ int RemoveStrikes(int strikes_decrease, const std::string& key) override;
+ int GetStrikes(const std::string& key) override;
+ void ClearStrikes(const std::string& key) override;
+ std::vector<std::string> GetAllStrikeKeysForProject(
+ const std::string& project_prefix) override;
+ void ClearStrikesForKeys(
+ const std::vector<std::string>& keys_to_remove) override;
+ void ClearAllStrikesForProject(const std::string& project_prefix) override;
+ void ClearAllStrikes() override;
+ std::string GetPrefixFromKey(const std::string& key) const override;
+ void SetStrikeData(const std::string& key, int num_strikes) override;
+
+ protected:
+ friend class StrikeDatabaseIntegratorBase;
+
+ // Cached StrikeDatabase entries.
+ std::map<std::string, StrikeData> strike_map_cache_;
+
+ // StrikeDatabaseBase:
+ std::map<std::string, StrikeData>& GetStrikeCache() override;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_INMEMORY_STRIKE_DATABASE_H_
diff --git a/chromium/components/autofill/core/browser/test_personal_data_manager.cc b/chromium/components/autofill/core/browser/test_personal_data_manager.cc
index 0913a4a265d..732b7985a85 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.cc
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.cc
@@ -12,7 +12,7 @@ namespace autofill {
TestPersonalDataManager::TestPersonalDataManager()
: PersonalDataManager("en-US", "US") {}
-TestPersonalDataManager::~TestPersonalDataManager() {}
+TestPersonalDataManager::~TestPersonalDataManager() = default;
void TestPersonalDataManager::OnSyncServiceInitialized(
syncer::SyncService* sync_service) {
@@ -291,6 +291,16 @@ CoreAccountInfo TestPersonalDataManager::GetAccountInfoForPaymentsServer()
return account_info_;
}
+const AutofillProfileSaveStrikeDatabase*
+TestPersonalDataManager::GetProfileSaveStrikeDatabase() const {
+ return &inmemory_profile_save_strike_database_;
+}
+
+const AutofillProfileUpdateStrikeDatabase*
+TestPersonalDataManager::GetProfileUpdateStrikeDatabase() const {
+ return &inmemory_profile_update_strike_database_;
+}
+
void TestPersonalDataManager::ClearProfiles() {
web_profiles_.clear();
}
@@ -340,7 +350,7 @@ void TestPersonalDataManager::AddCloudTokenData(
NotifyPersonalDataObserver();
}
-void TestPersonalDataManager::AddCreditCardOfferData(
+void TestPersonalDataManager::AddAutofillOfferData(
const AutofillOfferData& offer_data) {
std::unique_ptr<AutofillOfferData> data =
std::make_unique<AutofillOfferData>(offer_data);
diff --git a/chromium/components/autofill/core/browser/test_personal_data_manager.h b/chromium/components/autofill/core/browser/test_personal_data_manager.h
index 6524c6b87d5..2706a629b37 100644
--- a/chromium/components/autofill/core/browser/test_personal_data_manager.h
+++ b/chromium/components/autofill/core/browser/test_personal_data_manager.h
@@ -10,12 +10,13 @@
#include <utility>
#include <vector>
-#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/core/browser/payments/payments_customer_data.h"
#include "components/autofill/core/browser/personal_data_manager.h"
+#include "components/autofill/core/browser/test_inmemory_strike_database.h"
#include "components/signin/public/identity_manager/account_info.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -25,6 +26,8 @@ class TestPersonalDataManager : public PersonalDataManager {
TestPersonalDataManager();
~TestPersonalDataManager() override;
+ using PersonalDataManager::GetProfileSaveStrikeDatabase;
+ using PersonalDataManager::GetProfileUpdateStrikeDatabase;
using PersonalDataManager::SetPrefService;
// PersonalDataManager overrides. These functions are overridden as needed
@@ -64,6 +67,10 @@ class TestPersonalDataManager : public PersonalDataManager {
bool IsDataLoaded() const override;
bool IsSyncFeatureEnabled() const override;
CoreAccountInfo GetAccountInfoForPaymentsServer() const override;
+ const AutofillProfileSaveStrikeDatabase* GetProfileSaveStrikeDatabase()
+ const override;
+ const AutofillProfileUpdateStrikeDatabase* GetProfileUpdateStrikeDatabase()
+ const override;
// Unique to TestPersonalDataManager:
@@ -93,7 +100,7 @@ class TestPersonalDataManager : public PersonalDataManager {
void AddCloudTokenData(const CreditCardCloudTokenData& cloud_token_data);
// Adds offer data to |autofill_offer_data_|.
- void AddCreditCardOfferData(const AutofillOfferData& offer_data);
+ void AddAutofillOfferData(const AutofillOfferData& offer_data);
// Sets a local/server card's nickname based on the provided |guid|.
void SetNicknameForCardWithGUID(const char* guid,
@@ -153,15 +160,21 @@ class TestPersonalDataManager : public PersonalDataManager {
int num_times_save_imported_profile_called_ = 0;
int num_times_save_imported_credit_card_called_ = 0;
int num_times_save_upi_id_called_ = 0;
- base::Optional<bool> autofill_profile_enabled_;
- base::Optional<bool> autofill_credit_card_enabled_;
- base::Optional<bool> autofill_wallet_import_enabled_;
+ absl::optional<bool> autofill_profile_enabled_;
+ absl::optional<bool> autofill_credit_card_enabled_;
+ absl::optional<bool> autofill_wallet_import_enabled_;
bool sync_feature_enabled_ = false;
AutofillSyncSigninState sync_and_signin_state_ =
AutofillSyncSigninState::kSignedInAndSyncFeatureEnabled;
bool sync_service_initialized_ = false;
CoreAccountInfo account_info_;
+ TestInMemoryStrikeDatabase inmemory_strike_database_;
+ AutofillProfileSaveStrikeDatabase inmemory_profile_save_strike_database_{
+ &inmemory_strike_database_};
+ AutofillProfileUpdateStrikeDatabase inmemory_profile_update_strike_database_{
+ &inmemory_strike_database_};
+
DISALLOW_COPY_AND_ASSIGN(TestPersonalDataManager);
};
diff --git a/chromium/components/autofill/core/browser/test_utils/test_profiles.cc b/chromium/components/autofill/core/browser/test_utils/test_profiles.cc
new file mode 100644
index 00000000000..deb3fee781f
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_utils/test_profiles.cc
@@ -0,0 +1,123 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill/core/browser/test_utils/test_profiles.h"
+#include "base/feature_list.h"
+#include "components/autofill/core/common/autofill_features.h"
+
+namespace autofill {
+
+namespace test {
+
+void SetProfileTestValues(AutofillProfile* profile,
+ const std::vector<ProfileTestData>& profile_test_data,
+ bool finalize) {
+ DCHECK(profile);
+
+ base::ranges::for_each(
+ profile_test_data, [&](const ProfileTestData& test_data) {
+ profile->SetRawInfoWithVerificationStatus(
+ test_data.field_type, base::UTF8ToUTF16(test_data.value),
+ test_data.verification_status);
+ });
+
+ if (finalize) {
+ profile->FinalizeAfterImport();
+ }
+
+ // If structured names are not enabled, the first, middle and last names must
+ // be derived from the full name if they are not explicitly set.
+ if (!base::FeatureList::IsEnabled(
+ features::kAutofillEnableSupportForMoreStructureInNames)) {
+ if (profile->GetRawInfo(NAME_FULL).empty()) {
+ return;
+ }
+ // If first, middle and last names are empty, use the 'SetInfo()' method to
+ // trigger the completion.
+ if (profile->GetRawInfo(NAME_FIRST).empty() &&
+ profile->GetRawInfo(NAME_MIDDLE).empty() &&
+ profile->GetRawInfo(NAME_LAST).empty()) {
+ profile->SetInfo(NAME_FULL, profile->GetRawInfo(NAME_FULL), "en_US");
+ }
+ }
+}
+
+void CopyGUID(const AutofillProfile& from, AutofillProfile* to) {
+ to->set_guid(from.guid());
+}
+
+void SetProfileObservedTestValues(AutofillProfile* profile,
+ const std::vector<ProfileTestData>& test_data,
+ bool finalize) {
+ // Make a copy of the test data with all verification statuses replaced with
+ // 'kObserved'.
+ std::vector<ProfileTestData> observed_test_data;
+ base::ranges::for_each(test_data, [&](const ProfileTestData& entry) {
+ observed_test_data.emplace_back(ProfileTestData{
+ entry.field_type, entry.value, VerificationStatus::kObserved});
+ });
+
+ // Set this data to the profile.
+ SetProfileTestValues(profile, observed_test_data, finalize);
+}
+
+AutofillProfile StandardProfile() {
+ AutofillProfile profile;
+ const std::vector<ProfileTestData> observed_profile_test_data = {
+ {NAME_FULL, "Pablo Diego de la Ruiz y Picasso",
+ VerificationStatus::kUserVerified},
+ {ADDRESS_HOME_STREET_ADDRESS, "123 Mainstreet",
+ VerificationStatus::kObserved},
+ {ADDRESS_HOME_COUNTRY, "US", VerificationStatus::kObserved},
+ {ADDRESS_HOME_STATE, "CA", VerificationStatus::kObserved},
+ {ADDRESS_HOME_ZIP, "98765", VerificationStatus::kObserved},
+ {ADDRESS_HOME_CITY, "Mountainview", VerificationStatus::kObserved}};
+ SetProfileTestValues(&profile, observed_profile_test_data);
+ return profile;
+}
+
+AutofillProfile UpdateableStandardProfile() {
+ AutofillProfile profile;
+ const std::vector<ProfileTestData> observed_profile_test_data = {
+ {NAME_FULL, "Pablo Diego de la Ruiz y Picasso",
+ VerificationStatus::kObserved},
+ {ADDRESS_HOME_STREET_ADDRESS, "123 Mainstreet",
+ VerificationStatus::kObserved},
+ {ADDRESS_HOME_COUNTRY, "US", VerificationStatus::kObserved},
+ {ADDRESS_HOME_STATE, "CA", VerificationStatus::kObserved},
+ {ADDRESS_HOME_ZIP, "98765", VerificationStatus::kObserved},
+ {ADDRESS_HOME_CITY, "Mountainview", VerificationStatus::kObserved}};
+ SetProfileTestValues(&profile, observed_profile_test_data);
+ return profile;
+}
+
+AutofillProfile SubsetOfStandardProfile() {
+ AutofillProfile profile;
+ const std::vector<ProfileTestData> observed_profile_test_data = {
+ {NAME_FULL, "Pablo Diego de la Ruiz y Picasso"},
+ {ADDRESS_HOME_STREET_ADDRESS, "123 Mainstreet"},
+ {ADDRESS_HOME_COUNTRY, "US"},
+ {ADDRESS_HOME_STATE, "CA"},
+ {ADDRESS_HOME_ZIP, ""},
+ {ADDRESS_HOME_CITY, ""}};
+ SetProfileObservedTestValues(&profile, observed_profile_test_data);
+ return profile;
+}
+
+AutofillProfile DifferentFromStandardProfile() {
+ AutofillProfile profile;
+ const std::vector<ProfileTestData> observed_profile_test_data = {
+ {NAME_FULL, "Neo Anderson"},
+ {ADDRESS_HOME_STREET_ADDRESS, "119 Some Avenue"},
+ {ADDRESS_HOME_COUNTRY, "US"},
+ {ADDRESS_HOME_STATE, "CA"},
+ {ADDRESS_HOME_ZIP, "99666"},
+ {ADDRESS_HOME_CITY, "Los Angeles"}};
+ SetProfileObservedTestValues(&profile, observed_profile_test_data);
+ return profile;
+}
+
+} // namespace test
+
+} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/test_utils/test_profiles.h b/chromium/components/autofill/core/browser/test_utils/test_profiles.h
new file mode 100644
index 00000000000..b2741e9a687
--- /dev/null
+++ b/chromium/components/autofill/core/browser/test_utils/test_profiles.h
@@ -0,0 +1,65 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_UTILS_TEST_PROFILES_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_UTILS_TEST_PROFILES_H_
+
+#include "base/ranges/ranges.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_model/autofill_structured_address_test_utils.h"
+
+namespace autofill {
+
+using structured_address::VerificationStatus;
+
+namespace test {
+
+// Defines the |value| and |verification_status| for a specific Autofill
+// |field_type|
+struct ProfileTestData {
+ ServerFieldType field_type;
+ std::string value;
+ structured_address::VerificationStatus verification_status =
+ structured_address::VerificationStatus::kNoStatus;
+};
+
+// Set the values and verification statuses for the field types in
+// |profile_test_data|. If |finalize|, the finalization routine of the
+// AutofillProfile is called subsequently.
+void SetProfileTestValues(AutofillProfile* profile,
+ const std::vector<ProfileTestData>& profile_test_data,
+ bool finalize = true);
+
+// Copies the GUID from |from| to |to|.
+void CopyGUID(const AutofillProfile& from, AutofillProfile* to);
+
+// Convenience function to set the test data but with a verification status that
+// is set to |kObserved| for all values.
+void SetProfileObservedTestValues(AutofillProfile* profile,
+ const std::vector<ProfileTestData>& test_data,
+ bool finalize = true);
+
+// A standard AutofillProfile. All subsequent profiles are defined with respect
+// to this one.
+AutofillProfile StandardProfile();
+
+// This profile is similar to the standard profile defined above.
+// Here, the verification status for the name is 'only' observed. When merged
+// with the `StandardProfile()`, this should result in a silent update.
+AutofillProfile UpdateableStandardProfile();
+
+// This profile is similar to the standard profile defined above.
+// This profile is both lacking a city and a ZIP code and should be merged with
+// the `StandardProfile(}`.
+AutofillProfile SubsetOfStandardProfile();
+
+// This profile that is not similar to the standard profile.
+AutofillProfile DifferentFromStandardProfile();
+
+} // namespace test
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_TEST_UTILS_TEST_PROFILES_H_
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 17e3910630c..a7b717b2f4c 100644
--- a/chromium/components/autofill/core/browser/ui/accessory_sheet_data.cc
+++ b/chromium/components/autofill/core/browser/ui/accessory_sheet_data.cc
@@ -185,8 +185,8 @@ std::ostream& operator<<(std::ostream& os, const AccessoryTabType& type) {
return os << "Payments sheet";
case AccessoryTabType::ADDRESSES:
return os << "Address sheet";
- case AccessoryTabType::TOUCH_TO_FILL:
- return os << "Touch to Fill sheet";
+ case AccessoryTabType::OBSOLETE_TOUCH_TO_FILL:
+ return os << "(obsolete) Touch to Fill sheet";
case AccessoryTabType::ALL:
return os << "All sheets";
case AccessoryTabType::COUNT:
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 80c900b067c..a6a057ccdeb 100644
--- a/chromium/components/autofill/core/browser/ui/accessory_sheet_data.h
+++ b/chromium/components/autofill/core/browser/ui/accessory_sheet_data.h
@@ -9,9 +9,9 @@
#include <utility>
#include <vector>
-#include "base/optional.h"
#include "base/types/strong_alias.h"
#include "components/autofill/core/browser/ui/accessory_sheet_enums.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
class IsPublicSuffixMatchTag;
@@ -211,7 +211,7 @@ class AccessorySheetData {
void set_option_toggle(OptionToggle toggle) {
option_toggle_ = std::move(toggle);
}
- const base::Optional<OptionToggle>& option_toggle() const {
+ const absl::optional<OptionToggle>& option_toggle() const {
return option_toggle_;
}
@@ -243,7 +243,7 @@ class AccessorySheetData {
AccessoryTabType sheet_type_;
std::u16string title_;
std::u16string warning_;
- base::Optional<OptionToggle> option_toggle_;
+ absl::optional<OptionToggle> option_toggle_;
std::vector<UserInfo> user_info_list_;
std::vector<FooterCommand> footer_commands_;
};
diff --git a/chromium/components/autofill/core/browser/ui/accessory_sheet_enums.h b/chromium/components/autofill/core/browser/ui/accessory_sheet_enums.h
index a6d5fa16a09..2d59aa8c33b 100644
--- a/chromium/components/autofill/core/browser/ui/accessory_sheet_enums.h
+++ b/chromium/components/autofill/core/browser/ui/accessory_sheet_enums.h
@@ -18,7 +18,7 @@ enum class AccessoryTabType {
PASSWORDS = 1,
CREDIT_CARDS = 2,
ADDRESSES = 3,
- TOUCH_TO_FILL = 4,
+ OBSOLETE_TOUCH_TO_FILL = 4,
COUNT,
};
diff --git a/chromium/components/autofill/core/browser/ui/address_form_label_formatter_unittest.cc b/chromium/components/autofill/core/browser/ui/address_form_label_formatter_unittest.cc
index c77fd7f0888..04f396f190b 100644
--- a/chromium/components/autofill/core/browser/ui/address_form_label_formatter_unittest.cc
+++ b/chromium/components/autofill/core/browser/ui/address_form_label_formatter_unittest.cc
@@ -175,9 +175,8 @@ TEST(AddressFormLabelFormatterTest, GetLabelsForBRProfilesAndFocusedName) {
LabelFormatter::Create(profiles, "pt-BR", NAME_FIRST, GetFieldTypes());
EXPECT_THAT(formatter->GetLabels(),
- ElementsAre(base::UTF8ToUTF16(
- "Av. Pedro Ãlvares Cabral, 1301, Vila Mariana, São "
- "Paulo-SP, 04094-050")));
+ ElementsAre(u"Av. Pedro Ãlvares Cabral, 1301, Vila Mariana, São "
+ u"Paulo-SP, 04094-050"));
}
TEST(AddressFormLabelFormatterTest, GetLabelsForFormWithoutName) {
diff --git a/chromium/components/autofill/core/browser/ui/mobile_label_formatter_unittest.cc b/chromium/components/autofill/core/browser/ui/mobile_label_formatter_unittest.cc
index 62d377d0a4e..b2ba07baf5b 100644
--- a/chromium/components/autofill/core/browser/ui/mobile_label_formatter_unittest.cc
+++ b/chromium/components/autofill/core/browser/ui/mobile_label_formatter_unittest.cc
@@ -301,10 +301,8 @@ TEST(MobileLabelFormatterTest, GetLabels_DistinctProfiles_ShowAll) {
profiles, "en-US", NAME_FIRST, GetAddressPlusContactFieldTypes());
EXPECT_THAT(
formatter->GetLabels(),
- ElementsAre(base::ASCIIToUTF16(
- "address1A, address2A, (617) 666-0000, emailA@gmail.com"),
- base::ASCIIToUTF16(
- "address1B, address2B, (518) 555-0000, emailB@gmail.com"),
+ ElementsAre(u"address1A, address2A, (617) 666-0000, emailA@gmail.com",
+ u"address1B, address2B, (518) 555-0000, emailB@gmail.com",
std::u16string()));
// Like the previous test, but focuses on an address field rather than a name
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_controller_impl_unittest.cc b/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_controller_impl_unittest.cc
index 7311e96d216..134dc6479b3 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_controller_impl_unittest.cc
+++ b/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_controller_impl_unittest.cc
@@ -64,9 +64,9 @@ class CardExpirationDateFixFlowControllerImplTest
~CardExpirationDateFixFlowControllerImplTest() override {}
void SetUp() override {
- test_card_expiration_date_fix_flow_view_.reset(
- new TestCardExpirationDateFixFlowView());
- controller_.reset(new CardExpirationDateFixFlowControllerImpl());
+ test_card_expiration_date_fix_flow_view_ =
+ std::make_unique<TestCardExpirationDateFixFlowView>();
+ controller_ = std::make_unique<CardExpirationDateFixFlowControllerImpl>();
}
private:
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view.h b/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view.h
index 62ffd492f9a..b3e16143c1d 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view.h
+++ b/chromium/components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_view.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_EXPIRATION_DATE_FIX_FLOW_VIEW_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_EXPIRATION_DATE_FIX_FLOW_VIEW_H_
-#include <string>
-
#include "base/macros.h"
namespace autofill {
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl_unittest.cc b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl_unittest.cc
index 0a424d2dc78..a6008cc4d03 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl_unittest.cc
+++ b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl_unittest.cc
@@ -72,8 +72,8 @@ class CardNameFixFlowControllerImplTest
~CardNameFixFlowControllerImplTest() override {}
void SetUp() override {
- test_card_name_fix_flow_view_.reset(new TestCardNameFixFlowView());
- controller_.reset(new CardNameFixFlowControllerImpl());
+ test_card_name_fix_flow_view_ = std::make_unique<TestCardNameFixFlowView>();
+ controller_ = std::make_unique<CardNameFixFlowControllerImpl>();
}
private:
diff --git a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h
index 2d8dd0ad6aa..f9e41212712 100644
--- a/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h
+++ b/chromium/components/autofill/core/browser/ui/payments/card_name_fix_flow_view.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_VIEW_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_CARD_NAME_FIX_FLOW_VIEW_H_
-#include <string>
-
#include "base/macros.h"
namespace autofill {
diff --git a/chromium/components/autofill/core/browser/ui/payments/local_card_migration_bubble_controller.h b/chromium/components/autofill/core/browser/ui/payments/local_card_migration_bubble_controller.h
index dc0374e01e2..0833468fc28 100644
--- a/chromium/components/autofill/core/browser/ui/payments/local_card_migration_bubble_controller.h
+++ b/chromium/components/autofill/core/browser/ui/payments/local_card_migration_bubble_controller.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_LOCAL_CARD_MIGRATION_BUBBLE_CONTROLLER_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_UI_PAYMENTS_LOCAL_CARD_MIGRATION_BUBBLE_CONTROLLER_H_
-#include <string>
-
#include "base/macros.h"
#include "components/autofill/core/browser/ui/payments/payments_bubble_closed_reasons.h"
diff --git a/chromium/components/autofill/core/browser/ui/region_combobox_model_unittest.cc b/chromium/components/autofill/core/browser/ui/region_combobox_model_unittest.cc
index 40f0d28e30f..3c018e2e55c 100644
--- a/chromium/components/autofill/core/browser/ui/region_combobox_model_unittest.cc
+++ b/chromium/components/autofill/core/browser/ui/region_combobox_model_unittest.cc
@@ -20,8 +20,10 @@ namespace autofill {
// Strings used in more than one place and must be the same everywhere.
const char kQuebecCode[] = "QC";
const char kQuebecName[] = "Quebec";
+const char16_t kQuebecName16[] = u"Quebec";
const char kOntarioCode[] = "ON";
const char kOntarioName[] = "Ontario";
+const char16_t kOntarioName16[] = u"Ontario";
// Make sure the two regions returned by the source are properly set in the
// model.
@@ -38,8 +40,8 @@ TEST(RegionComboboxModelTest, QuebecOntarioRegions) {
EXPECT_EQ(3, model.GetItemCount());
EXPECT_EQ(u"---", model.GetItemAt(0));
- EXPECT_EQ(base::ASCIIToUTF16(kQuebecName), model.GetItemAt(1));
- EXPECT_EQ(base::ASCIIToUTF16(kOntarioName), model.GetItemAt(2));
+ EXPECT_EQ(kQuebecName16, model.GetItemAt(1));
+ EXPECT_EQ(kOntarioName16, model.GetItemAt(2));
EXPECT_FALSE(model.failed_to_load_data());
}
diff --git a/chromium/components/autofill/core/browser/validation_unittest.cc b/chromium/components/autofill/core/browser/validation_unittest.cc
index 5df65f13c75..a75b73382e4 100644
--- a/chromium/components/autofill/core/browser/validation_unittest.cc
+++ b/chromium/components/autofill/core/browser/validation_unittest.cc
@@ -17,8 +17,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
-using base::ASCIIToUTF16;
-
namespace autofill {
namespace {
@@ -33,30 +31,30 @@ struct IntExpirationDate {
};
struct SecurityCodeCardTypePair {
- const char* security_code;
+ const char16_t* security_code;
const char* card_network;
};
// 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",
- "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
+const char16_t* const kValidNumbers[] = {
+ u"378282246310005", u"3714 4963 5398 431", u"3787-3449-3671-000",
+ u"5610591081018250", u"3056 9309 0259 04", u"3852-0000-0232-37",
+ u"6011111111111117", u"6011 0009 9013 9424", u"3530-1113-3330-0000",
+ u"3566002020360505",
+ u"5555 5555 5555 4444", // Mastercard.
+ u"5105-1051-0510-5100",
+ u"4111111111111111", // Visa.
+ u"4012 8888 8888 1881", u"4222-2222-2222-2", u"5019717010103742",
+ u"6331101999990016", u"6247130048162403",
+ u"4532261615476013542", // Visa, 19 digits.
+ u"6362970000457013", // Elo
};
-const char* const kInvalidNumbers[] = {
- "4111 1111 112", /* too short */
- "41111111111111111115", /* too long */
- "4111-1111-1111-1110", /* wrong Luhn checksum */
- "3056 9309 0259 04aa", /* non-digit characters */
+const char16_t* const kInvalidNumbers[] = {
+ u"4111 1111 112", /* too short */
+ u"41111111111111111115", /* too long */
+ u"4111-1111-1111-1110", /* wrong Luhn checksum */
+ u"3056 9309 0259 04aa", /* non-digit characters */
};
const char kCurrentDate[] = "1 May 2013";
const IntExpirationDate kValidCreditCardIntExpirationDate[] = {
@@ -71,71 +69,67 @@ 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.
+ {u"323", kGenericCard}, // 3-digit CSC.
+ {u"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.
+ {u"32", kGenericCard}, // CSC too short.
+ {u"323", kAmericanExpressCard}, // CSC too short.
+ {u"3234", kGenericCard}, // CSC too long.
+ {u"12345", kAmericanExpressCard}, // CSC too long.
+ {u"asd", kGenericCard}, // non-numeric CSC.
};
-const char* const kValidEmailAddress[] = {
- "user@example",
- "user@example.com",
- "user@subdomain.example.com",
- "user+postfix@example.com",
+const char16_t* const kValidEmailAddress[] = {
+ u"user@example",
+ u"user@example.com",
+ u"user@subdomain.example.com",
+ u"user+postfix@example.com",
};
-const char* const kInvalidEmailAddress[] = {"user", "foo.com", "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"};
+const char16_t* const kInvalidEmailAddress[] = {u"user", u"foo.com", u"user@",
+ u"user@=example.com"};
+const char16_t* const kUnplausibleCreditCardExpirationYears[] = {
+ u"2009", u"2134", u"1111", u"abcd", u"2101"};
+const char16_t* const kPlausibleCreditCardExpirationYears[] = {
+ u"2018", u"2099", u"2010", u"2050"};
+const char16_t* const kUnplausibleCreditCardCVCNumbers[] = {u"abc", u"21",
+ u"11111", u"21a1"};
+const char16_t* const kPlausibleCreditCardCVCNumbers[] = {u"1234", u"2099",
+ u"111", u"982"};
} // namespace
TEST(AutofillValidation, IsValidCreditCardNumber) {
- for (const char* valid_number : kValidNumbers) {
+ for (const char16_t* valid_number : kValidNumbers) {
SCOPED_TRACE(valid_number);
- EXPECT_TRUE(IsValidCreditCardNumber(ASCIIToUTF16(valid_number)));
+ EXPECT_TRUE(IsValidCreditCardNumber(valid_number));
}
- for (const char* invalid_number : kInvalidNumbers) {
+ for (const char16_t* invalid_number : kInvalidNumbers) {
SCOPED_TRACE(invalid_number);
- EXPECT_FALSE(IsValidCreditCardNumber(ASCIIToUTF16(invalid_number)));
+ EXPECT_FALSE(IsValidCreditCardNumber(invalid_number));
}
}
// 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)))
+ for (const char16_t* plausible_year : kPlausibleCreditCardExpirationYears) {
+ EXPECT_TRUE(IsPlausible4DigitExpirationYear(plausible_year))
<< plausible_year;
}
- for (const char* unplausible_year : kUnplausibleCreditCardExpirationYears) {
- EXPECT_FALSE(
- IsPlausible4DigitExpirationYear(base::ASCIIToUTF16(unplausible_year)))
+ for (const char16_t* unplausible_year :
+ kUnplausibleCreditCardExpirationYears) {
+ EXPECT_FALSE(IsPlausible4DigitExpirationYear(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 char16_t* plausible_cvc : kPlausibleCreditCardCVCNumbers) {
+ EXPECT_TRUE(IsPlausibleCreditCardCVCNumber(plausible_cvc)) << plausible_cvc;
}
- for (const char* unplausible_cvc : kUnplausibleCreditCardCVCNumbers) {
- EXPECT_FALSE(
- IsPlausibleCreditCardCVCNumber(base::ASCIIToUTF16(unplausible_cvc)))
+ for (const char16_t* unplausible_cvc : kUnplausibleCreditCardCVCNumbers) {
+ EXPECT_FALSE(IsPlausibleCreditCardCVCNumber(unplausible_cvc))
<< unplausible_cvc;
}
}
@@ -160,30 +154,30 @@ TEST(AutofillValidation, IsValidCreditCardSecurityCode) {
for (const auto data : kValidSecurityCodeCardTypePairs) {
SCOPED_TRACE(data.security_code);
SCOPED_TRACE(data.card_network);
- EXPECT_TRUE(IsValidCreditCardSecurityCode(ASCIIToUTF16(data.security_code),
- data.card_network));
+ EXPECT_TRUE(
+ IsValidCreditCardSecurityCode(data.security_code, data.card_network));
}
for (const auto data : kInvalidSecurityCodeCardTypePairs) {
SCOPED_TRACE(data.security_code);
SCOPED_TRACE(data.card_network);
- EXPECT_FALSE(IsValidCreditCardSecurityCode(ASCIIToUTF16(data.security_code),
- data.card_network));
+ EXPECT_FALSE(
+ IsValidCreditCardSecurityCode(data.security_code, data.card_network));
}
}
TEST(AutofillValidation, IsValidEmailAddress) {
- for (const char* valid_email : kValidEmailAddress) {
+ for (const char16_t* valid_email : kValidEmailAddress) {
SCOPED_TRACE(valid_email);
- EXPECT_TRUE(IsValidEmailAddress(ASCIIToUTF16(valid_email)));
+ EXPECT_TRUE(IsValidEmailAddress(valid_email));
}
- for (const char* invalid_email : kInvalidEmailAddress) {
+ for (const char16_t* invalid_email : kInvalidEmailAddress) {
SCOPED_TRACE(invalid_email);
- EXPECT_FALSE(IsValidEmailAddress(ASCIIToUTF16(invalid_email)));
+ EXPECT_FALSE(IsValidEmailAddress(invalid_email));
}
}
struct ValidationCase {
- ValidationCase(const char* value,
+ ValidationCase(const char16_t* value,
ServerFieldType field_type,
bool expected_valid,
int expected_error_id)
@@ -193,7 +187,7 @@ struct ValidationCase {
expected_error_id(expected_error_id) {}
~ValidationCase() {}
- const char* const value;
+ const char16_t* const value;
const ServerFieldType field_type;
const bool expected_valid;
const int expected_error_id;
@@ -204,9 +198,9 @@ class AutofillTypeValidationTest
TEST_P(AutofillTypeValidationTest, IsValidForType) {
std::u16string error_message;
- EXPECT_EQ(GetParam().expected_valid,
- IsValidForType(ASCIIToUTF16(GetParam().value),
- GetParam().field_type, &error_message))
+ EXPECT_EQ(
+ GetParam().expected_valid,
+ IsValidForType(GetParam().value, GetParam().field_type, &error_message))
<< "Failed to validate " << GetParam().value << " (type "
<< GetParam().field_type << ")";
if (!GetParam().expected_valid) {
@@ -219,41 +213,41 @@ INSTANTIATE_TEST_SUITE_P(
CreditCardExpDate,
AutofillTypeValidationTest,
testing::Values(
- ValidationCase("05/2087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
- ValidationCase("05-2087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
- ValidationCase("052087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
- ValidationCase("05|2087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
+ ValidationCase(u"05/2087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
+ ValidationCase(u"05-2087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
+ ValidationCase(u"052087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
+ ValidationCase(u"05|2087", CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, true, 0),
- ValidationCase("05/2012",
+ ValidationCase(u"05/2012",
CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED),
- ValidationCase("MM/2012",
+ ValidationCase(u"MM/2012",
CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
false,
IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE),
- ValidationCase("05/12",
+ ValidationCase(u"05/12",
CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
false,
IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE),
- ValidationCase("05/45",
+ ValidationCase(u"05/45",
CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
false,
IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE),
- ValidationCase("05/1987",
+ ValidationCase(u"05/1987",
CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR,
false,
IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE),
- ValidationCase("05/87", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
- ValidationCase("05-87", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
- ValidationCase("0587", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
- ValidationCase("05|87", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
- ValidationCase("05/1987",
+ ValidationCase(u"05/87", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
+ ValidationCase(u"05-87", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
+ ValidationCase(u"0587", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
+ ValidationCase(u"05|87", CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR, true, 0),
+ ValidationCase(u"05/1987",
CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
false,
IDS_PAYMENTS_CARD_EXPIRATION_INVALID_VALIDATION_MESSAGE),
- ValidationCase("05/12",
+ ValidationCase(u"05/12",
CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED)));
@@ -262,21 +256,21 @@ INSTANTIATE_TEST_SUITE_P(
CreditCardMonth,
AutofillTypeValidationTest,
testing::Values(
- ValidationCase("01", CREDIT_CARD_EXP_MONTH, true, 0),
- ValidationCase("1", CREDIT_CARD_EXP_MONTH, true, 0),
- ValidationCase("12", CREDIT_CARD_EXP_MONTH, true, 0),
+ ValidationCase(u"01", CREDIT_CARD_EXP_MONTH, true, 0),
+ ValidationCase(u"1", CREDIT_CARD_EXP_MONTH, true, 0),
+ ValidationCase(u"12", CREDIT_CARD_EXP_MONTH, true, 0),
ValidationCase(
- "0",
+ u"0",
CREDIT_CARD_EXP_MONTH,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_MONTH),
ValidationCase(
- "-1",
+ u"-1",
CREDIT_CARD_EXP_MONTH,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_MONTH),
ValidationCase(
- "13",
+ u"13",
CREDIT_CARD_EXP_MONTH,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_MONTH)));
@@ -286,63 +280,63 @@ INSTANTIATE_TEST_SUITE_P(
AutofillTypeValidationTest,
testing::Values(
/* 2-digit year */
- ValidationCase("87", CREDIT_CARD_EXP_2_DIGIT_YEAR, true, 0),
- // These are considered expired in the context of this millenium.
- ValidationCase("02",
+ ValidationCase(u"87", CREDIT_CARD_EXP_2_DIGIT_YEAR, true, 0),
+ // These are considered expired in the context of this millennium.
+ ValidationCase(u"02",
CREDIT_CARD_EXP_2_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED),
- ValidationCase("15",
+ ValidationCase(u"15",
CREDIT_CARD_EXP_2_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED),
// Invalid formats.
ValidationCase(
- "1",
+ u"1",
CREDIT_CARD_EXP_2_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR),
ValidationCase(
- "123",
+ u"123",
CREDIT_CARD_EXP_2_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR),
ValidationCase(
- "2087",
+ u"2087",
CREDIT_CARD_EXP_2_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR),
/* 4-digit year */
- ValidationCase("2087", CREDIT_CARD_EXP_4_DIGIT_YEAR, true, 0),
+ ValidationCase(u"2087", CREDIT_CARD_EXP_4_DIGIT_YEAR, true, 0),
// Expired.
- ValidationCase("2000",
+ ValidationCase(u"2000",
CREDIT_CARD_EXP_4_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED),
- ValidationCase("2015",
+ ValidationCase(u"2015",
CREDIT_CARD_EXP_4_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRED),
// Invalid formats.
ValidationCase(
- "00",
+ u"00",
CREDIT_CARD_EXP_4_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR),
ValidationCase(
- "123",
+ u"123",
CREDIT_CARD_EXP_4_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR),
ValidationCase(
- "87",
+ u"87",
CREDIT_CARD_EXP_4_DIGIT_YEAR,
false,
IDS_PAYMENTS_VALIDATION_INVALID_CREDIT_CARD_EXPIRATION_YEAR)));
struct CCNumberCase {
- CCNumberCase(const char* value,
+ CCNumberCase(const char16_t* value,
const std::set<std::string> supported_basic_card_networks,
bool expected_valid,
int expected_error_id)
@@ -352,7 +346,7 @@ struct CCNumberCase {
expected_error_id(expected_error_id) {}
~CCNumberCase() {}
- const char* const value;
+ const char16_t* const value;
const std::set<std::string> supported_basic_card_networks;
const bool expected_valid;
const int expected_error_id;
@@ -365,8 +359,8 @@ TEST_P(AutofillCCNumberValidationTest, IsValidCreditCardNumber) {
std::u16string error_message;
EXPECT_EQ(GetParam().expected_valid,
IsValidCreditCardNumberForBasicCardNetworks(
- ASCIIToUTF16(GetParam().value),
- GetParam().supported_basic_card_networks, &error_message))
+ GetParam().value, GetParam().supported_basic_card_networks,
+ &error_message))
<< "Failed to validate CC number " << GetParam().value;
if (!GetParam().expected_valid) {
EXPECT_EQ(l10n_util::GetStringUTF16(GetParam().expected_error_id),
@@ -477,53 +471,50 @@ INSTANTIATE_TEST_SUITE_P(
GetCvcLengthForCardTypeCase{kVisaCard, GENERAL_CVC_LENGTH}));
class AutofillIsUPIVirtualPaymentAddress
- : public testing::TestWithParam<std::string> {};
+ : public testing::TestWithParam<std::u16string> {};
TEST_P(AutofillIsUPIVirtualPaymentAddress, IsUPIVirtualPaymentAddress_Banks) {
// Expected format is user@bank
- EXPECT_TRUE(
- IsUPIVirtualPaymentAddress(ASCIIToUTF16("user.name-1@" + GetParam())));
+ EXPECT_TRUE(IsUPIVirtualPaymentAddress(u"user.name-1@" + GetParam()));
// Deviations should not match: bank, @bank, user@prefixbank, user@banksuffix,
// disallowed symbols.
- EXPECT_FALSE(IsUPIVirtualPaymentAddress(ASCIIToUTF16(GetParam())));
- EXPECT_FALSE(IsUPIVirtualPaymentAddress(ASCIIToUTF16(GetParam() + "@")));
- EXPECT_FALSE(IsUPIVirtualPaymentAddress(ASCIIToUTF16("@" + GetParam())));
- EXPECT_FALSE(
- IsUPIVirtualPaymentAddress(ASCIIToUTF16("user@invalid" + GetParam())));
- EXPECT_FALSE(
- IsUPIVirtualPaymentAddress(ASCIIToUTF16("user@" + GetParam() + ".com")));
- EXPECT_FALSE(IsUPIVirtualPaymentAddress(ASCIIToUTF16("~user@" + GetParam())));
+ EXPECT_FALSE(IsUPIVirtualPaymentAddress(GetParam()));
+ EXPECT_FALSE(IsUPIVirtualPaymentAddress(GetParam() + u"@"));
+ EXPECT_FALSE(IsUPIVirtualPaymentAddress(u"@" + GetParam()));
+ EXPECT_FALSE(IsUPIVirtualPaymentAddress(u"user@invalid" + GetParam()));
+ EXPECT_FALSE(IsUPIVirtualPaymentAddress(u"user@" + GetParam() + u".com"));
+ EXPECT_FALSE(IsUPIVirtualPaymentAddress(u"~user@" + GetParam()));
}
INSTANTIATE_TEST_SUITE_P(UPIVirtualPaymentAddress,
AutofillIsUPIVirtualPaymentAddress,
- testing::Values("upi",
- "allbank",
- "andb",
- "axisbank",
- "barodampay",
- "mahb",
- "cnrb",
- "csbpay",
- "dcb",
- "federal",
- "hdfcbank",
- "pockets",
- "icici",
- "idfcbank",
- "indus",
- "kbl",
- "kaypay",
- "pnb",
- "sib",
- "sbi",
- "tjsb",
- "uco",
- "unionbank",
- "united",
- "vijb",
- "ybl"));
+ testing::Values(u"upi",
+ u"allbank",
+ u"andb",
+ u"axisbank",
+ u"barodampay",
+ u"mahb",
+ u"cnrb",
+ u"csbpay",
+ u"dcb",
+ u"federal",
+ u"hdfcbank",
+ u"pockets",
+ u"icici",
+ u"idfcbank",
+ u"indus",
+ u"kbl",
+ u"kaypay",
+ u"pnb",
+ u"sib",
+ u"sbi",
+ u"tjsb",
+ u"uco",
+ u"unionbank",
+ u"united",
+ u"vijb",
+ u"ybl"));
TEST(AutofillValidation, IsUPIVirtualPaymentAddress_Others) {
EXPECT_TRUE(IsUPIVirtualPaymentAddress(u"12345@HDFC0000001.ifsc.npci"));
@@ -533,31 +524,28 @@ TEST(AutofillValidation, IsUPIVirtualPaymentAddress_Others) {
}
class AutofillIsInternationalBankAccountNumber
- : public testing::TestWithParam<std::string> {};
+ : public testing::TestWithParam<std::u16string> {};
INSTANTIATE_TEST_SUITE_P(InternationalBankAccountNumber,
AutofillIsInternationalBankAccountNumber,
- testing::Values("MT84MALT011000012345MTLCAST001S",
- "SC18SSCB11010000000000001497USD",
- "MD24AG000225100013104168",
- "BH67BMAG00001299123456",
- "LI21088100002324013AA",
- "NO9386011117947",
- "FR1420041010050500013M02606",
- "LB62099900000001001901229114"));
+ testing::Values(u"MT84MALT011000012345MTLCAST001S",
+ u"SC18SSCB11010000000000001497USD",
+ u"MD24AG000225100013104168",
+ u"BH67BMAG00001299123456",
+ u"LI21088100002324013AA",
+ u"NO9386011117947",
+ u"FR1420041010050500013M02606",
+ u"LB62099900000001001901229114"));
TEST_P(AutofillIsInternationalBankAccountNumber,
IsInternationalBankAccountNumber) {
- EXPECT_TRUE(IsInternationalBankAccountNumber(ASCIIToUTF16(GetParam())))
- << GetParam();
- EXPECT_TRUE(
- IsInternationalBankAccountNumber(ASCIIToUTF16(" " + GetParam() + " ")));
- EXPECT_FALSE(
- IsInternationalBankAccountNumber(ASCIIToUTF16("DE" + GetParam())));
- EXPECT_FALSE(
- IsInternationalBankAccountNumber(ASCIIToUTF16(GetParam() + ".")));
+ EXPECT_TRUE(IsInternationalBankAccountNumber(GetParam()))
+ << base::StringPiece16(GetParam());
+ EXPECT_TRUE(IsInternationalBankAccountNumber(u" " + GetParam() + u" "));
+ EXPECT_FALSE(IsInternationalBankAccountNumber(u"DE" + GetParam()));
+ EXPECT_FALSE(IsInternationalBankAccountNumber(GetParam() + u"."));
EXPECT_FALSE(IsInternationalBankAccountNumber(
- ASCIIToUTF16(GetParam() + "0000000000000000000000000000000000000")));
+ GetParam() + u"0000000000000000000000000000000000000"));
}
} // namespace autofill
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 eaa0208daf3..b95f546ddd4 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.cc
@@ -25,7 +25,7 @@
#include "components/sync/model/sync_metadata_store_change_list.h"
#include "net/base/escape.h"
-using base::Optional;
+using absl::optional;
using base::Time;
using sync_pb::AutofillSpecifics;
using syncer::ClientTagBasedModelTypeProcessor;
@@ -47,7 +47,7 @@ const char kAutocompleteTagDelimiter[] = "|";
// Simplify checking for optional errors and returning only when present.
#define RETURN_IF_ERROR(x) \
- if (Optional<ModelError> ret_val = x) { \
+ if (optional<ModelError> ret_val = x) { \
return ret_val; \
}
@@ -129,7 +129,7 @@ class SyncDifferenceTracker {
public:
explicit SyncDifferenceTracker(AutofillTable* table) : table_(table) {}
- Optional<ModelError> IncorporateRemoteSpecifics(
+ optional<ModelError> IncorporateRemoteSpecifics(
const std::string& storage_key,
const AutofillSpecifics& specifics) {
if (!specifics.has_value()) {
@@ -144,7 +144,7 @@ class SyncDifferenceTracker {
const AutofillEntry remote = CreateAutofillEntry(specifics);
DCHECK_EQ(storage_key, GetStorageKeyFromModel(remote.key()));
- Optional<AutofillEntry> local;
+ optional<AutofillEntry> local;
if (!ReadEntry(remote.key(), &local))
return ModelError(FROM_HERE, "Failed reading from WebDatabase.");
@@ -167,7 +167,7 @@ class SyncDifferenceTracker {
return {};
}
- Optional<ModelError> IncorporateRemoteDelete(const std::string& storage_key) {
+ optional<ModelError> IncorporateRemoteDelete(const std::string& storage_key) {
AutofillKey key;
if (!ParseStorageKey(storage_key, &key)) {
return ModelError(FROM_HERE, "Failed parsing storage key.");
@@ -176,7 +176,7 @@ class SyncDifferenceTracker {
return {};
}
- Optional<ModelError> FlushToLocal(AutofillWebDataBackend* web_data_backend) {
+ optional<ModelError> FlushToLocal(AutofillWebDataBackend* web_data_backend) {
for (const AutofillKey& key : delete_from_local_) {
if (!table_->RemoveFormElement(key.name(), key.value())) {
return ModelError(FROM_HERE, "Failed deleting from WebDatabase");
@@ -191,7 +191,7 @@ class SyncDifferenceTracker {
return {};
}
- Optional<ModelError> FlushToSync(
+ optional<ModelError> FlushToSync(
bool include_local_only,
std::unique_ptr<MetadataChangeList> metadata_change_list,
ModelTypeChangeProcessor* change_processor) {
@@ -226,7 +226,7 @@ class SyncDifferenceTracker {
// 1. An error is encountered reading from the db, false is returned.
// 2. The entry is not found, |entry| will not be touched.
// 3. The entry is found, |entry| will be set.
- bool ReadEntry(const AutofillKey& key, Optional<AutofillEntry>* entry) {
+ bool ReadEntry(const AutofillKey& key, optional<AutofillEntry>* entry) {
if (!InitializeIfNeeded()) {
return false;
}
@@ -322,7 +322,7 @@ AutocompleteSyncBridge::CreateMetadataChangeList() {
GetAutofillTable(), syncer::AUTOFILL);
}
-Optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData(
+optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_data) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -343,7 +343,7 @@ Optional<syncer::ModelError> AutocompleteSyncBridge::MergeSyncData(
return {};
}
-Optional<ModelError> AutocompleteSyncBridge::ApplySyncChanges(
+optional<ModelError> AutocompleteSyncBridge::ApplySyncChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_changes) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -463,7 +463,7 @@ void AutocompleteSyncBridge::ActOnLocalChanges(
// committed by the AutofillWebDataService when the original local write
// operation (that triggered this notification to the bridge) finishes.
- if (Optional<ModelError> error = metadata_change_list->TakeError())
+ if (optional<ModelError> error = metadata_change_list->TakeError())
change_processor()->ReportError(*error);
}
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 a700a7aba1a..4e98599b7b3 100644
--- a/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
+++ b/chromium/components/autofill/core/browser/webdata/autocomplete_sync_bridge.h
@@ -9,7 +9,6 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "base/supports_user_data.h"
#include "base/threading/thread_checker.h"
@@ -20,6 +19,7 @@
#include "components/sync/model/model_error.h"
#include "components/sync/model/model_type_change_processor.h"
#include "components/sync/model/model_type_sync_bridge.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -47,10 +47,10 @@ class AutocompleteSyncBridge
// syncer::ModelTypeSyncBridge implementation.
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
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 a92f3ca3166..449e23c3a22 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
@@ -155,8 +155,7 @@ class AutocompleteSyncBridgeTest : public testing::Test {
void ResetProcessor() {
real_processor_ =
std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
- syncer::AUTOFILL, /*dump_stack=*/base::DoNothing(),
- /*commit_only=*/false);
+ syncer::AUTOFILL, /*dump_stack=*/base::DoNothing());
mock_processor_.DelegateCallsByDefaultTo(real_processor_.get());
}
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 02d8bc8b044..40bc8bdb6dc 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
@@ -29,7 +29,7 @@
#include "components/sync/model/mutable_data_batch.h"
#include "components/sync/model/sync_metadata_store_change_list.h"
-using base::Optional;
+using absl::optional;
using base::UTF16ToUTF8;
using sync_pb::AutofillProfileSpecifics;
using syncer::EntityData;
@@ -42,7 +42,7 @@ namespace {
// Simplify checking for optional errors and returning only when present.
#define RETURN_IF_ERROR(x) \
- if (Optional<ModelError> ret_val = x) { \
+ if (optional<ModelError> ret_val = x) { \
return ret_val; \
}
@@ -98,7 +98,7 @@ AutofillProfileSyncBridge::CreateMetadataChangeList() {
GetAutofillTable(), syncer::AUTOFILL_PROFILE);
}
-Optional<syncer::ModelError> AutofillProfileSyncBridge::MergeSyncData(
+optional<syncer::ModelError> AutofillProfileSyncBridge::MergeSyncData(
std::unique_ptr<MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -129,10 +129,10 @@ Optional<syncer::ModelError> AutofillProfileSyncBridge::MergeSyncData(
web_data_backend_->CommitChanges();
web_data_backend_->NotifyThatSyncHasStarted(syncer::AUTOFILL_PROFILE);
- return base::nullopt;
+ return absl::nullopt;
}
-Optional<ModelError> AutofillProfileSyncBridge::ApplySyncChanges(
+optional<ModelError> AutofillProfileSyncBridge::ApplySyncChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -160,7 +160,7 @@ Optional<ModelError> AutofillProfileSyncBridge::ApplySyncChanges(
RETURN_IF_ERROR(FlushSyncTracker(std::move(metadata_change_list), &tracker));
web_data_backend_->CommitChanges();
- return base::nullopt;
+ return absl::nullopt;
}
void AutofillProfileSyncBridge::GetData(StorageKeyList storage_keys,
@@ -237,12 +237,12 @@ void AutofillProfileSyncBridge::ActOnLocalChange(
// committed by the AutofillWebDataService when the original local write
// operation (that triggered this notification to the bridge) finishes.
- if (Optional<ModelError> error = metadata_change_list->TakeError()) {
+ if (optional<ModelError> error = metadata_change_list->TakeError()) {
change_processor()->ReportError(*error);
}
}
-base::Optional<syncer::ModelError> AutofillProfileSyncBridge::FlushSyncTracker(
+absl::optional<syncer::ModelError> AutofillProfileSyncBridge::FlushSyncTracker(
std::unique_ptr<MetadataChangeList> metadata_change_list,
AutofillProfileSyncDifferenceTracker* tracker) {
DCHECK(tracker);
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 be44a88d238..6be00c7abaf 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
@@ -9,7 +9,6 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "base/supports_user_data.h"
#include "base/threading/thread_checker.h"
@@ -17,6 +16,7 @@
#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"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace syncer {
class MetadataChangeList;
@@ -66,10 +66,10 @@ class AutofillProfileSyncBridge
// syncer::ModelTypeSyncBridge implementation.
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
@@ -89,7 +89,7 @@ class AutofillProfileSyncBridge
void ActOnLocalChange(const AutofillProfileChange& change);
// Flushes changes accumulated within |tracker| both to local and to sync.
- base::Optional<syncer::ModelError> FlushSyncTracker(
+ absl::optional<syncer::ModelError> FlushSyncTracker(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
AutofillProfileSyncDifferenceTracker* tracker);
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 ea2ba7b87ce..b8d20b8276a 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
@@ -47,7 +47,6 @@
namespace autofill {
-using base::ASCIIToUTF16;
using base::ScopedTempDir;
using base::UTF16ToUTF8;
using base::UTF8ToUTF16;
@@ -161,8 +160,7 @@ AutofillProfile ConstructCompleteProfile() {
profile.SetRawInfo(EMAIL_ADDRESS, u"user@example.com");
profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"1.800.555.1234");
- profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("123 Fake St.\n"
- "Apt. 42"));
+ profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, u"123 Fake St.\nApt. 42");
EXPECT_EQ(u"123 Fake St.", profile.GetRawInfo(ADDRESS_HOME_LINE1));
EXPECT_EQ(u"Apt. 42", profile.GetRawInfo(ADDRESS_HOME_LINE2));
@@ -281,8 +279,7 @@ class AutofillProfileSyncBridgeTestBase : public testing::Test {
void ResetProcessor() {
real_processor_ =
std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
- syncer::AUTOFILL_PROFILE, /*dump_stack=*/base::DoNothing(),
- /*commit_only=*/false);
+ syncer::AUTOFILL_PROFILE, /*dump_stack=*/base::DoNothing());
mock_processor_.DelegateCallsByDefaultTo(real_processor_.get());
}
@@ -315,7 +312,7 @@ class AutofillProfileSyncBridgeTestBase : public testing::Test {
}
void ApplySyncChanges(EntityChangeList changes) {
- const base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ const absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), std::move(changes));
EXPECT_FALSE(error) << error->ToString();
}
@@ -1081,8 +1078,7 @@ TEST_P(AutofillProfileSyncBridgeTest, ApplySyncChanges_OmitsInvalidSpecifics) {
// address line 1 and line 2 fields.
TEST_P(AutofillProfileSyncBridgeTest, StreetAddress_SplitAutomatically) {
AutofillProfile local;
- local.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, ASCIIToUTF16("123 Example St.\n"
- "Apt. 42"));
+ local.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, u"123 Example St.\nApt. 42");
EXPECT_EQ(u"123 Example St.", local.GetRawInfo(ADDRESS_HOME_LINE1));
EXPECT_EQ(u"Apt. 42", local.GetRawInfo(ADDRESS_HOME_LINE2));
@@ -1101,8 +1097,7 @@ TEST_P(AutofillProfileSyncBridgeTest, StreetAddress_JointAutomatically) {
AutofillProfile local;
local.SetRawInfo(ADDRESS_HOME_LINE1, u"123 Example St.");
local.SetRawInfo(ADDRESS_HOME_LINE2, u"Apt. 42");
- EXPECT_EQ(ASCIIToUTF16("123 Example St.\n"
- "Apt. 42"),
+ EXPECT_EQ(u"123 Example St.\nApt. 42",
local.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS));
// The same does _not_ work for profile specifics.
@@ -1134,9 +1129,7 @@ TEST_P(AutofillProfileSyncBridgeTest,
// Verify that full street address takes precedence over address lines.
AutofillProfile local(kGuidA, kHttpsOrigin);
local.SetRawInfoWithVerificationStatus(
- ADDRESS_HOME_STREET_ADDRESS,
- ASCIIToUTF16("456 El Camino Real\n"
- "Suite #1337"),
+ ADDRESS_HOME_STREET_ADDRESS, u"456 El Camino Real\nSuite #1337",
structured_address::VerificationStatus::kObserved);
local.SetRawInfoWithVerificationStatus(
ADDRESS_HOME_LINE1, u"456 El Camino Real",
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.cc b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.cc
index d31aa724c7d..1582ac242cc 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.cc
@@ -16,7 +16,7 @@
namespace autofill {
-using base::Optional;
+using absl::optional;
using syncer::ModelError;
AutofillProfileSyncDifferenceTracker::AutofillProfileSyncDifferenceTracker(
@@ -25,7 +25,7 @@ AutofillProfileSyncDifferenceTracker::AutofillProfileSyncDifferenceTracker(
AutofillProfileSyncDifferenceTracker::~AutofillProfileSyncDifferenceTracker() {}
-Optional<ModelError>
+optional<ModelError>
AutofillProfileSyncDifferenceTracker::IncorporateRemoteProfile(
std::unique_ptr<AutofillProfile> remote) {
const std::string remote_storage_key =
@@ -35,7 +35,7 @@ AutofillProfileSyncDifferenceTracker::IncorporateRemoteProfile(
return ModelError(FROM_HERE, "Failed reading from WebDatabase.");
}
- Optional<AutofillProfile> local_with_same_storage_key =
+ optional<AutofillProfile> local_with_same_storage_key =
ReadEntry(remote_storage_key);
if (local_with_same_storage_key) {
@@ -46,7 +46,7 @@ AutofillProfileSyncDifferenceTracker::IncorporateRemoteProfile(
// We ignore remote updates to a verified profile because we want to keep
// the exact version that the user edited by hand.
if (local_with_same_storage_key->IsVerified() && !remote->IsVerified()) {
- return base::nullopt;
+ return absl::nullopt;
}
updated->OverwriteDataFrom(*remote);
// TODO(crbug.com/1117022l): if |updated| deviates from |remote|, we should
@@ -73,7 +73,7 @@ AutofillProfileSyncDifferenceTracker::IncorporateRemoteProfile(
update_to_local_.push_back(std::move(updated));
}
GetLocalOnlyEntries()->erase(remote_storage_key);
- return base::nullopt;
+ return absl::nullopt;
}
// Check if profile appears under a different storage key to be de-duplicated.
@@ -154,24 +154,24 @@ AutofillProfileSyncDifferenceTracker::IncorporateRemoteProfile(
}
delete_from_sync_.insert(remote_storage_key);
}
- return base::nullopt;
+ return absl::nullopt;
}
}
// If no duplicate was found, just add the remote profile.
add_to_local_.push_back(std::move(remote));
- return base::nullopt;
+ return absl::nullopt;
}
-Optional<ModelError>
+optional<ModelError>
AutofillProfileSyncDifferenceTracker::IncorporateRemoteDelete(
const std::string& storage_key) {
DCHECK(!storage_key.empty());
DeleteFromLocal(storage_key);
- return base::nullopt;
+ return absl::nullopt;
}
-Optional<ModelError> AutofillProfileSyncDifferenceTracker::FlushToLocal(
+optional<ModelError> AutofillProfileSyncDifferenceTracker::FlushToLocal(
base::OnceClosure autofill_changes_callback) {
for (const std::string& storage_key : delete_from_local_) {
if (!table_->RemoveAutofillProfile(storage_key)) {
@@ -192,10 +192,10 @@ Optional<ModelError> AutofillProfileSyncDifferenceTracker::FlushToLocal(
!update_to_local_.empty()) {
std::move(autofill_changes_callback).Run();
}
- return base::nullopt;
+ return absl::nullopt;
}
-Optional<ModelError> AutofillProfileSyncDifferenceTracker::FlushToSync(
+optional<ModelError> AutofillProfileSyncDifferenceTracker::FlushToSync(
std::vector<std::unique_ptr<AutofillProfile>>* profiles_to_upload_to_sync,
std::vector<std::string>* profiles_to_delete_from_sync) {
for (std::unique_ptr<AutofillProfile>& entry : save_to_sync_) {
@@ -204,17 +204,17 @@ Optional<ModelError> AutofillProfileSyncDifferenceTracker::FlushToSync(
for (const std::string& entry : delete_from_sync_) {
profiles_to_delete_from_sync->push_back(std::move(entry));
}
- return base::nullopt;
+ return absl::nullopt;
}
-Optional<AutofillProfile> AutofillProfileSyncDifferenceTracker::ReadEntry(
+optional<AutofillProfile> AutofillProfileSyncDifferenceTracker::ReadEntry(
const std::string& storage_key) {
DCHECK(GetLocalOnlyEntries());
auto iter = GetLocalOnlyEntries()->find(storage_key);
if (iter != GetLocalOnlyEntries()->end()) {
return *iter->second;
}
- return base::nullopt;
+ return absl::nullopt;
}
void AutofillProfileSyncDifferenceTracker::DeleteFromLocal(
@@ -259,15 +259,15 @@ AutofillProfileInitialSyncDifferenceTracker::
AutofillProfileInitialSyncDifferenceTracker::
~AutofillProfileInitialSyncDifferenceTracker() {}
-Optional<ModelError>
+optional<ModelError>
AutofillProfileInitialSyncDifferenceTracker::IncorporateRemoteDelete(
const std::string& storage_key) {
// Remote delete is not allowed in initial sync.
NOTREACHED();
- return base::nullopt;
+ return absl::nullopt;
}
-Optional<ModelError> AutofillProfileInitialSyncDifferenceTracker::FlushToSync(
+optional<ModelError> AutofillProfileInitialSyncDifferenceTracker::FlushToSync(
std::vector<std::unique_ptr<AutofillProfile>>* profiles_to_upload_to_sync,
std::vector<std::string>* profiles_to_delete_from_sync) {
// First, flush standard updates to sync.
@@ -284,10 +284,10 @@ Optional<ModelError> AutofillProfileInitialSyncDifferenceTracker::FlushToSync(
DCHECK(delete_from_local_.count(storage_key) == 0);
profiles_to_upload_to_sync->push_back(std::move(pair.second));
}
- return base::nullopt;
+ return absl::nullopt;
}
-Optional<ModelError>
+optional<ModelError>
AutofillProfileInitialSyncDifferenceTracker::MergeSimilarEntriesForInitialSync(
const std::string& app_locale) {
if (!GetLocalOnlyEntries()) {
@@ -308,7 +308,7 @@ AutofillProfileInitialSyncDifferenceTracker::MergeSimilarEntriesForInitialSync(
// non-const reference because we want to update |remote| in place if
// needed.
for (std::unique_ptr<AutofillProfile>& remote : add_to_local_) {
- Optional<AutofillProfile> local =
+ optional<AutofillProfile> local =
FindMergeableLocalEntry(*remote, comparator);
if (!local) {
continue;
@@ -337,10 +337,10 @@ AutofillProfileInitialSyncDifferenceTracker::MergeSimilarEntriesForInitialSync(
DeleteFromLocal(GetStorageKeyFromAutofillProfile(*local));
}
- return base::nullopt;
+ return absl::nullopt;
}
-Optional<AutofillProfile>
+optional<AutofillProfile>
AutofillProfileInitialSyncDifferenceTracker::FindMergeableLocalEntry(
const AutofillProfile& remote,
const AutofillProfileComparator& comparator) {
@@ -349,7 +349,7 @@ AutofillProfileInitialSyncDifferenceTracker::FindMergeableLocalEntry(
// Both the remote and the local entry need to be non-verified to be
// mergeable.
if (remote.IsVerified()) {
- return base::nullopt;
+ return absl::nullopt;
}
// Check if there is a mergeable local profile.
@@ -360,7 +360,7 @@ AutofillProfileInitialSyncDifferenceTracker::FindMergeableLocalEntry(
return local_candidate;
}
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h
index 2ef173660fe..6d2050d7736 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_profile_sync_difference_tracker.h
@@ -13,7 +13,7 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace syncer {
class ModelError;
@@ -36,36 +36,36 @@ class AutofillProfileSyncDifferenceTracker {
// Adds a new |remote| entry to the diff tracker, originating from the sync
// server. The provided |remote| entry must be valid.
- base::Optional<syncer::ModelError> IncorporateRemoteProfile(
+ absl::optional<syncer::ModelError> IncorporateRemoteProfile(
std::unique_ptr<AutofillProfile> remote);
// Informs the diff tracker that the entry with |storage_key| has been deleted
// from the sync server. |storage_key| must be non-empty.
- virtual base::Optional<syncer::ModelError> IncorporateRemoteDelete(
+ virtual absl::optional<syncer::ModelError> IncorporateRemoteDelete(
const std::string& storage_key);
// Writes all local changes to the provided autofill |table_|. After flushing,
// not further remote changes should get incorporated.
- base::Optional<syncer::ModelError> FlushToLocal(
+ absl::optional<syncer::ModelError> FlushToLocal(
base::OnceClosure autofill_changes_callback);
// Writes into |profiles_to_upload_to_sync| all autofill profiles to be sent
// to the sync server, and into |profiles_to_delete_from_sync| the storage
// keys of all profiles to be deleted from the server. After flushing, no
// further remote changes should get incorporated.
- virtual base::Optional<syncer::ModelError> FlushToSync(
+ virtual absl::optional<syncer::ModelError> FlushToSync(
std::vector<std::unique_ptr<AutofillProfile>>* profiles_to_upload_to_sync,
std::vector<std::string>* profiles_to_delete_from_sync);
protected:
- // If the entry is found, |entry| will be return, otherwise base::nullopt is
+ // If the entry is found, |entry| will be return, otherwise absl::nullopt is
// returned.
- base::Optional<AutofillProfile> ReadEntry(const std::string& storage_key);
+ absl::optional<AutofillProfile> ReadEntry(const std::string& storage_key);
// Tries to find a local entry that is mergeable with |remote| (according to
// |comparator|). If such an entry is found, it is returned. Otherwise,
- // base::nullopt is returned.
- base::Optional<AutofillProfile> FindMergeableLocalEntry(
+ // absl::nullopt is returned.
+ absl::optional<AutofillProfile> FindMergeableLocalEntry(
const AutofillProfile& remote,
const AutofillProfileComparator& comparator);
@@ -117,23 +117,23 @@ class AutofillProfileInitialSyncDifferenceTracker
explicit AutofillProfileInitialSyncDifferenceTracker(AutofillTable* table);
~AutofillProfileInitialSyncDifferenceTracker() override;
- base::Optional<syncer::ModelError> IncorporateRemoteDelete(
+ absl::optional<syncer::ModelError> IncorporateRemoteDelete(
const std::string& storage_key) override;
- base::Optional<syncer::ModelError> FlushToSync(
+ absl::optional<syncer::ModelError> FlushToSync(
std::vector<std::unique_ptr<AutofillProfile>>* profiles_to_upload_to_sync,
std::vector<std::string>* profiles_to_delete_from_sync) override;
// Performs an additional pass through remote entries incorporated from sync
// to find any similarities with local entries. Should be run after all
// entries get incorporated but before flushing results to local/sync.
- base::Optional<syncer::ModelError> MergeSimilarEntriesForInitialSync(
+ absl::optional<syncer::ModelError> MergeSimilarEntriesForInitialSync(
const std::string& app_locale);
private:
// Returns a local entry that is mergeable with |remote| if it exists.
- // Otherwise, returns base::nullopt.
- base::Optional<AutofillProfile> FindMergeableLocalEntry(
+ // Otherwise, returns absl::nullopt.
+ absl::optional<AutofillProfile> FindMergeableLocalEntry(
const AutofillProfile& remote,
const AutofillProfileComparator& comparator);
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 bc6f729a475..9098947b871 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
@@ -66,18 +66,18 @@ class AutofillProfileSyncDifferenceTrackerTestBase : public testing::Test {
}
void IncorporateRemoteProfile(const AutofillProfile& profile) {
- EXPECT_EQ(base::nullopt, tracker()->IncorporateRemoteProfile(
+ EXPECT_EQ(absl::nullopt, tracker()->IncorporateRemoteProfile(
std::make_unique<AutofillProfile>(profile)));
}
UpdatesToSync FlushToSync() {
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
tracker()->FlushToLocal(
/*autofill_changes_callback=*/base::DoNothing()));
UpdatesToSync updates;
std::vector<std::unique_ptr<AutofillProfile>> vector_of_unique_ptrs;
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
tracker()->FlushToSync(
/*profiles_to_upload_to_sync=*/&vector_of_unique_ptrs,
/*profiles_to_delete_from_sync=*/&updates
@@ -347,7 +347,7 @@ TEST_F(AutofillProfileSyncDifferenceTrackerTest,
MockCallback<base::OnceClosure> autofill_changes_callback;
EXPECT_CALL(autofill_changes_callback, Run()).Times(0);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
tracker()->FlushToLocal(autofill_changes_callback.Get()));
}
@@ -360,7 +360,7 @@ TEST_F(AutofillProfileSyncDifferenceTrackerTest,
MockCallback<base::OnceClosure> autofill_changes_callback;
EXPECT_CALL(autofill_changes_callback, Run()).Times(1);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
tracker()->FlushToLocal(autofill_changes_callback.Get()));
// On top of that, the profile should also get deleted.
@@ -374,7 +374,7 @@ TEST_F(AutofillProfileSyncDifferenceTrackerTest,
MockCallback<base::OnceClosure> autofill_changes_callback;
EXPECT_CALL(autofill_changes_callback, Run()).Times(1);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
tracker()->FlushToLocal(autofill_changes_callback.Get()));
// On top of that, the profile should also get added.
@@ -393,7 +393,7 @@ TEST_F(AutofillProfileSyncDifferenceTrackerTest,
MockCallback<base::OnceClosure> autofill_changes_callback;
EXPECT_CALL(autofill_changes_callback, Run()).Times(1);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
tracker()->FlushToLocal(autofill_changes_callback.Get()));
// On top of that, the profile with key kSmallerGuid should also get updated.
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc
index 374a557d888..64c5af2f54b 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util.cc
@@ -8,6 +8,7 @@
#include "base/pickle.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill/core/browser/data_model/autofill_offer_data.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -99,11 +100,38 @@ CreditCard CardFromSpecifics(const sync_pb::WalletMaskedCreditCard& card) {
result.SetExpirationMonth(card.exp_month());
result.SetExpirationYear(card.exp_year());
result.set_billing_address_id(card.billing_address_id());
- result.set_card_issuer(
- static_cast<CreditCard::Issuer>(card.card_issuer().issuer()));
+
+ CreditCard::Issuer issuer = CreditCard::ISSUER_UNKNOWN;
+ switch (card.card_issuer().issuer()) {
+ case sync_pb::CardIssuer::ISSUER_UNKNOWN:
+ issuer = CreditCard::ISSUER_UNKNOWN;
+ break;
+ case sync_pb::CardIssuer::GOOGLE:
+ issuer = CreditCard::GOOGLE;
+ break;
+ }
+ result.set_card_issuer(issuer);
+
if (!card.nickname().empty())
result.SetNickname(base::UTF8ToUTF16(card.nickname()));
result.set_instrument_id(card.instrument_id());
+
+ CreditCard::VirtualCardEnrollmentState state = CreditCard::UNSPECIFIED;
+ switch (card.virtual_card_enrollment_state()) {
+ case sync_pb::WalletMaskedCreditCard::UNENROLLED:
+ state = CreditCard::UNENROLLED;
+ break;
+ case sync_pb::WalletMaskedCreditCard::ENROLLED:
+ state = CreditCard::ENROLLED;
+ break;
+ case sync_pb::WalletMaskedCreditCard::UNSPECIFIED:
+ state = CreditCard::UNSPECIFIED;
+ break;
+ }
+ result.set_virtual_card_enrollment_state(state);
+
+ if (!card.card_art_url().empty())
+ result.set_card_art_url(GURL(card.card_art_url()));
return result;
}
@@ -246,9 +274,37 @@ void SetAutofillWalletSpecificsFromServerCard(
wallet_card->set_exp_year(card.expiration_year());
if (!card.nickname().empty())
wallet_card->set_nickname(base::UTF16ToUTF8(card.nickname()));
- wallet_card->mutable_card_issuer()->set_issuer(
- static_cast<sync_pb::CardIssuer::Issuer>(card.card_issuer()));
+
+ sync_pb::CardIssuer::Issuer issuer = sync_pb::CardIssuer::ISSUER_UNKNOWN;
+ switch (card.card_issuer()) {
+ case CreditCard::ISSUER_UNKNOWN:
+ issuer = sync_pb::CardIssuer::ISSUER_UNKNOWN;
+ break;
+ case CreditCard::GOOGLE:
+ issuer = sync_pb::CardIssuer::GOOGLE;
+ break;
+ }
+ wallet_card->mutable_card_issuer()->set_issuer(issuer);
+
wallet_card->set_instrument_id(card.instrument_id());
+
+ sync_pb::WalletMaskedCreditCard::VirtualCardEnrollmentState state =
+ sync_pb::WalletMaskedCreditCard::UNSPECIFIED;
+ switch (card.virtual_card_enrollment_state()) {
+ case CreditCard::UNENROLLED:
+ state = sync_pb::WalletMaskedCreditCard::UNENROLLED;
+ break;
+ case CreditCard::ENROLLED:
+ state = sync_pb::WalletMaskedCreditCard::ENROLLED;
+ break;
+ case CreditCard::UNSPECIFIED:
+ state = sync_pb::WalletMaskedCreditCard::UNSPECIFIED;
+ break;
+ }
+ wallet_card->set_virtual_card_enrollment_state(state);
+
+ if (!card.card_art_url().is_empty())
+ wallet_card->set_card_art_url(card.card_art_url().spec());
}
void SetAutofillWalletSpecificsFromPaymentsCustomerData(
@@ -291,6 +347,7 @@ void SetAutofillWalletSpecificsFromCreditCardCloudTokenData(
void SetAutofillOfferSpecificsFromOfferData(
const AutofillOfferData& offer_data,
sync_pb::AutofillOfferSpecifics* offer_specifics) {
+ // General offer data:
offer_specifics->set_id(offer_data.offer_id);
offer_specifics->set_offer_details_url(offer_data.offer_details_url.spec());
for (const GURL& domain : offer_data.merchant_domain) {
@@ -298,16 +355,42 @@ void SetAutofillOfferSpecificsFromOfferData(
}
offer_specifics->set_offer_expiry_date(
(offer_data.expiry - base::Time::UnixEpoch()).InSeconds());
- for (int64_t instrument_id : offer_data.eligible_instrument_id) {
- offer_specifics->mutable_card_linked_offer_data()->add_instrument_id(
- instrument_id);
- }
- if (offer_data.offer_reward_amount.find("%") != std::string::npos) {
- offer_specifics->mutable_percentage_reward()->set_percentage(
- offer_data.offer_reward_amount);
+ offer_specifics->mutable_display_strings()->set_value_prop_text(
+ offer_data.display_strings.value_prop_text);
+#if defined(OS_ANDROID) || defined(OS_IOS)
+ offer_specifics->mutable_display_strings()->set_see_details_text_mobile(
+ offer_data.display_strings.see_details_text);
+ offer_specifics->mutable_display_strings()
+ ->set_usage_instructions_text_mobile(
+ offer_data.display_strings.usage_instructions_text);
+#else
+ offer_specifics->mutable_display_strings()->set_see_details_text_desktop(
+ offer_data.display_strings.see_details_text);
+ offer_specifics->mutable_display_strings()
+ ->set_usage_instructions_text_desktop(
+ offer_data.display_strings.usage_instructions_text);
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+
+ // Because card_linked_offer_data and promo_code_offer_data are a oneof,
+ // setting one will clear the other. We should figure out which one we care
+ // about.
+ if (offer_data.promo_code == "") {
+ // Card-linked offer fields (promo code is empty):
+ for (int64_t instrument_id : offer_data.eligible_instrument_id) {
+ offer_specifics->mutable_card_linked_offer_data()->add_instrument_id(
+ instrument_id);
+ }
+ if (offer_data.offer_reward_amount.find("%") != std::string::npos) {
+ offer_specifics->mutable_percentage_reward()->set_percentage(
+ offer_data.offer_reward_amount);
+ } else {
+ offer_specifics->mutable_fixed_amount_reward()->set_amount(
+ offer_data.offer_reward_amount);
+ }
} else {
- offer_specifics->mutable_fixed_amount_reward()->set_amount(
- offer_data.offer_reward_amount);
+ // Promo code offer fields:
+ offer_specifics->mutable_promo_code_offer_data()->set_promo_code(
+ offer_data.promo_code);
}
}
@@ -315,14 +398,9 @@ AutofillOfferData AutofillOfferDataFromOfferSpecifics(
const sync_pb::AutofillOfferSpecifics& offer_specifics) {
DCHECK(IsOfferSpecificsValid(offer_specifics));
AutofillOfferData offer_data;
+
+ // General offer data:
offer_data.offer_id = offer_specifics.id();
- if (offer_specifics.has_percentage_reward()) {
- offer_data.offer_reward_amount =
- offer_specifics.percentage_reward().percentage();
- } else {
- offer_data.offer_reward_amount =
- offer_specifics.fixed_amount_reward().amount();
- }
offer_data.expiry =
base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(offer_specifics.offer_expiry_date());
@@ -331,10 +409,33 @@ AutofillOfferData AutofillOfferDataFromOfferSpecifics(
if (GURL(domain).is_valid())
offer_data.merchant_domain.emplace_back(domain);
}
+ offer_data.display_strings.value_prop_text =
+ offer_specifics.display_strings().value_prop_text();
+#if defined(OS_ANDROID) || defined(OS_IOS)
+ offer_data.display_strings.see_details_text =
+ offer_specifics.display_strings().see_details_text_mobile();
+ offer_data.display_strings.usage_instructions_text =
+ offer_specifics.display_strings().usage_instructions_text_mobile();
+#else
+ offer_data.display_strings.see_details_text =
+ offer_specifics.display_strings().see_details_text_desktop();
+ offer_data.display_strings.usage_instructions_text =
+ offer_specifics.display_strings().usage_instructions_text_desktop();
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+
+ // Card-linked offer fields:
+ offer_data.offer_reward_amount =
+ offer_specifics.has_percentage_reward()
+ ? offer_specifics.percentage_reward().percentage()
+ : offer_specifics.fixed_amount_reward().amount();
for (int64_t instrument_id :
offer_specifics.card_linked_offer_data().instrument_id()) {
offer_data.eligible_instrument_id.push_back(instrument_id);
}
+
+ // Promo code offer fields:
+ offer_data.promo_code = offer_specifics.promo_code_offer_data().promo_code();
+
return offer_data;
}
@@ -518,24 +619,24 @@ bool IsOfferSpecificsValid(const sync_pb::AutofillOfferSpecifics specifics) {
return false;
}
- // A valid offer has at least one linked card instrument id.
- if (!specifics.has_card_linked_offer_data() ||
- specifics.card_linked_offer_data().instrument_id().size() == 0) {
- return false;
- }
-
- // A valid offer must have either a percentage reward or a fixed amount
- // reward.
- if (!specifics.has_percentage_reward() ||
- !specifics.percentage_reward().has_percentage()) {
- return specifics.has_fixed_amount_reward() &&
- specifics.fixed_amount_reward().has_amount();
- } else if (specifics.percentage_reward().percentage().find('%') ==
- std::string::npos) {
- return false;
- }
-
- return true;
+ // Card-linked offers must have at least one linked card instrument ID, and
+ // fixed_amount_reward or percentage_reward. Promo code offers must have a
+ // promo code.
+ bool has_instrument_id =
+ specifics.has_card_linked_offer_data() &&
+ specifics.card_linked_offer_data().instrument_id().size() != 0;
+ bool has_fixed_or_percentage_reward =
+ (specifics.has_fixed_amount_reward() &&
+ specifics.fixed_amount_reward().has_amount()) ||
+ (specifics.has_percentage_reward() &&
+ specifics.percentage_reward().has_percentage() &&
+ specifics.percentage_reward().percentage().find('%') !=
+ std::string::npos);
+ bool has_promo_code = specifics.has_promo_code_offer_data() &&
+ specifics.promo_code_offer_data().promo_code() != "";
+
+ return (has_instrument_id && has_fixed_or_percentage_reward) ||
+ has_promo_code;
}
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc
index ac068999eca..0d0d5bf91c6 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_sync_bridge_util_unittest.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/data_model/autofill_offer_data.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -84,6 +85,9 @@ TEST_F(AutofillSyncBridgeUtilTest, PopulateWalletTypesFromSyncData) {
CreateAutofillWalletSpecificsForCard(
/*id=*/credit_card_id_1,
/*billing_address_id=*/address_id);
+ wallet_specifics_card1.mutable_masked_card()
+ ->set_virtual_card_enrollment_state(
+ sync_pb::WalletMaskedCreditCard::UNENROLLED);
// Add the second card that has nickname.
std::string nickname("Grocery card");
sync_pb::AutofillWalletSpecifics wallet_specifics_card2 =
@@ -94,6 +98,11 @@ TEST_F(AutofillSyncBridgeUtilTest, PopulateWalletTypesFromSyncData) {
wallet_specifics_card2.mutable_masked_card()
->mutable_card_issuer()
->set_issuer(sync_pb::CardIssuer::GOOGLE);
+ wallet_specifics_card2.mutable_masked_card()
+ ->set_virtual_card_enrollment_state(
+ sync_pb::WalletMaskedCreditCard::ENROLLED);
+ wallet_specifics_card2.mutable_masked_card()->set_card_art_url(
+ "https://www.example.com/card.png");
entity_data.push_back(EntityChange::CreateAdd(
credit_card_id_1,
SpecificsToEntity(wallet_specifics_card1, /*client_tag=*/"card-card1")));
@@ -140,6 +149,17 @@ TEST_F(AutofillSyncBridgeUtilTest, PopulateWalletTypesFromSyncData) {
// Verify that the card_issuer is set correctly.
EXPECT_EQ(wallet_cards.front().card_issuer(), CreditCard::ISSUER_UNKNOWN);
EXPECT_EQ(wallet_cards.back().card_issuer(), CreditCard::GOOGLE);
+
+ // Verify that the virtual_card_enrollment_state is set correctly.
+ EXPECT_EQ(wallet_cards.front().virtual_card_enrollment_state(),
+ CreditCard::UNENROLLED);
+ EXPECT_EQ(wallet_cards.back().virtual_card_enrollment_state(),
+ CreditCard::ENROLLED);
+
+ // Verify that the card_art_url is set correctly.
+ EXPECT_TRUE(wallet_cards.front().card_art_url().is_empty());
+ EXPECT_EQ(wallet_cards.back().card_art_url().spec(),
+ "https://www.example.com/card.png");
}
// Verify that the billing address id from the card saved on disk is kept if it
@@ -239,8 +259,8 @@ TEST_F(AutofillSyncBridgeUtilTest,
EXPECT_EQ(disk_time, wallet_cards.back().use_date());
}
-// Test to ensure the an AutofillOfferData is correctly converted to an
-// AutofillOfferSpecifics.
+// Test to ensure the general-purpose fields from an AutofillOfferData are
+// correctly converted to an AutofillOfferSpecifics.
TEST_F(AutofillSyncBridgeUtilTest, OfferSpecificsFromOfferData) {
sync_pb::AutofillOfferSpecifics offer_specifics;
AutofillOfferData offer_data = test::GetCardLinkedOfferData1();
@@ -250,16 +270,38 @@ TEST_F(AutofillSyncBridgeUtilTest, OfferSpecificsFromOfferData) {
EXPECT_EQ(offer_specifics.offer_details_url(), offer_data.offer_details_url);
EXPECT_EQ(offer_specifics.offer_expiry_date(),
(offer_data.expiry - base::Time::UnixEpoch()).InSeconds());
- EXPECT_TRUE(offer_specifics.percentage_reward().percentage() ==
- offer_data.offer_reward_amount ||
- offer_specifics.fixed_amount_reward().amount() ==
- offer_data.offer_reward_amount);
EXPECT_EQ(offer_specifics.merchant_domain().size(),
(int)offer_data.merchant_domain.size());
for (int i = 0; i < offer_specifics.merchant_domain().size(); i++) {
EXPECT_EQ(offer_specifics.merchant_domain(i),
offer_data.merchant_domain[i].GetOrigin().spec());
}
+ EXPECT_EQ(offer_specifics.display_strings().value_prop_text(),
+ offer_data.display_strings.value_prop_text);
+#if defined(OS_ANDROID) || defined(OS_IOS)
+ EXPECT_EQ(offer_specifics.display_strings().see_details_text_mobile(),
+ offer_data.display_strings.see_details_text);
+ EXPECT_EQ(offer_specifics.display_strings().usage_instructions_text_mobile(),
+ offer_data.display_strings.usage_instructions_text);
+#else
+ EXPECT_EQ(offer_specifics.display_strings().see_details_text_desktop(),
+ offer_data.display_strings.see_details_text);
+ EXPECT_EQ(offer_specifics.display_strings().usage_instructions_text_desktop(),
+ offer_data.display_strings.usage_instructions_text);
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+}
+
+// Test to ensure the card-linked offer-specific fields from an
+// AutofillOfferData are correctly converted to an AutofillOfferSpecifics.
+TEST_F(AutofillSyncBridgeUtilTest, OfferSpecificsFromCardLinkedOfferData) {
+ sync_pb::AutofillOfferSpecifics offer_specifics;
+ AutofillOfferData offer_data = test::GetCardLinkedOfferData1();
+ SetAutofillOfferSpecificsFromOfferData(offer_data, &offer_specifics);
+
+ EXPECT_TRUE(offer_specifics.percentage_reward().percentage() ==
+ offer_data.offer_reward_amount ||
+ offer_specifics.fixed_amount_reward().amount() ==
+ offer_data.offer_reward_amount);
EXPECT_EQ(offer_specifics.card_linked_offer_data().instrument_id().size(),
(int)offer_data.eligible_instrument_id.size());
for (int i = 0;
@@ -270,6 +312,17 @@ TEST_F(AutofillSyncBridgeUtilTest, OfferSpecificsFromOfferData) {
}
}
+// Test to ensure the promo code offer-specific fields from an AutofillOfferData
+// are correctly converted to an AutofillOfferSpecifics.
+TEST_F(AutofillSyncBridgeUtilTest, OfferSpecificsFromPromoCodeOfferData) {
+ sync_pb::AutofillOfferSpecifics offer_specifics;
+ AutofillOfferData offer_data = test::GetPromoCodeOfferData();
+ SetAutofillOfferSpecificsFromOfferData(offer_data, &offer_specifics);
+
+ EXPECT_EQ(offer_specifics.promo_code_offer_data().promo_code(),
+ offer_data.promo_code);
+}
+
// Ensures that the ShouldResetAutofillWalletData function works correctly, if
// the two given data sets have the same size.
TEST_F(AutofillSyncBridgeUtilTest,
@@ -309,7 +362,7 @@ TEST_F(AutofillSyncBridgeUtilTest, IsOfferSpecificsValid) {
sync_pb::AutofillOfferSpecifics specifics;
SetAutofillOfferSpecificsFromOfferData(test::GetCardLinkedOfferData1(),
&specifics);
- // Expects default specifics is valid.
+ // Expects default card-linked offer specifics is valid.
EXPECT_TRUE(IsOfferSpecificsValid(specifics));
specifics.clear_id();
@@ -328,23 +381,35 @@ TEST_F(AutofillSyncBridgeUtilTest, IsOfferSpecificsValid) {
SetAutofillOfferSpecificsFromOfferData(test::GetCardLinkedOfferData1(),
&specifics);
specifics.mutable_card_linked_offer_data()->clear_instrument_id();
- // Expects specifics without linked card instrument id to be invalid.
+ // Expects card-linked offer specifics without linked card instrument id to be
+ // invalid.
EXPECT_FALSE(IsOfferSpecificsValid(specifics));
specifics.clear_card_linked_offer_data();
- // Expects specifics without card linked offer data to be invalid.
+ // Expects specifics without card linked offer data or promo code offer data
+ // to be invalid.
EXPECT_FALSE(IsOfferSpecificsValid(specifics));
SetAutofillOfferSpecificsFromOfferData(test::GetCardLinkedOfferData1(),
&specifics);
specifics.mutable_percentage_reward()->set_percentage("5");
- // Expects specifics without correct reward text to be invalid.
+ // Expects card-linked offer specifics without correct reward text to be
+ // invalid.
EXPECT_FALSE(IsOfferSpecificsValid(specifics));
specifics.clear_percentage_reward();
- // Expects specifics without reward text to be invalid.
+ // Expects card-linked offer specifics without reward text to be invalid.
EXPECT_FALSE(IsOfferSpecificsValid(specifics));
specifics.mutable_fixed_amount_reward()->set_amount("$5");
- // Expects specifics with only fixed amount reward text to be valid.
+ // Expects card-linked offer specifics with only fixed amount reward text to
+ // be valid.
+ EXPECT_TRUE(IsOfferSpecificsValid(specifics));
+
+ SetAutofillOfferSpecificsFromOfferData(test::GetPromoCodeOfferData(),
+ &specifics);
+ // Expects default promo code offer specifics is valid.
EXPECT_TRUE(IsOfferSpecificsValid(specifics));
+ // Expects promo code offer specifics without promo code to be invalid.
+ specifics.mutable_promo_code_offer_data()->clear_promo_code();
+ EXPECT_FALSE(IsOfferSpecificsValid(specifics));
}
} // namespace
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.cc b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
index 563a4c9780f..c60f08bf434 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.cc
@@ -28,6 +28,7 @@
#include "components/autofill/core/browser/data_model/autofill_offer_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/browser/data_model/credit_card_art_image.h"
#include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h"
#include "components/autofill/core/browser/geo/autofill_country.h"
#include "components/autofill/core/browser/payments/payments_customer_data.h"
@@ -103,6 +104,8 @@ void BindAutofillProfileToStatement(const AutofillProfile& profile,
s->BindString(index++, profile.language_code());
s->BindInt64(index++, profile.GetClientValidityBitfieldValue());
s->BindBool(index++, profile.is_client_validity_states_updated());
+ s->BindString(index++, profile.profile_label());
+ s->BindBool(index++, profile.disallow_settings_visible_updates());
}
void AddAutofillProfileDetailsFromStatement(const sql::Statement& s,
@@ -124,6 +127,8 @@ void AddAutofillProfileDetailsFromStatement(const sql::Statement& s,
profile->set_language_code(s.ColumnString(index++));
profile->SetClientValidityFromBitfieldValue(s.ColumnInt64(index++));
profile->set_is_client_validity_states_updated(s.ColumnBool(index++));
+ profile->set_profile_label(s.ColumnString(index++));
+ profile->set_disallow_settings_visible_updates(s.ColumnBool(index++));
}
void BindEncryptedCardToColumn(sql::Statement* s,
@@ -682,7 +687,8 @@ bool AutofillTable::CreateTablesIfNecessary() {
InitAutofillSyncMetadataTable() && InitModelTypeStateTable() &&
InitPaymentsCustomerDataTable() && InitPaymentsUPIVPATable() &&
InitServerCreditCardCloudTokenDataTable() && InitOfferDataTable() &&
- InitOfferEligibleInstrumentTable() && InitOfferMerchantDomainTable());
+ InitOfferEligibleInstrumentTable() &&
+ InitOfferMerchantDomainTable() && InitCreditCardArtImagesTable());
}
bool AutofillTable::IsSyncable() {
@@ -786,6 +792,17 @@ bool AutofillTable::MigrateToVersion(int version,
case 92:
*update_compatible_version = false;
return MigrateToVersion92AddNewPrefixedNameColumn();
+ case 93:
+ *update_compatible_version = false;
+ return MigrateToVersion93AddAutofillProfileLabelColumn();
+ case 94:
+ *update_compatible_version = false;
+ return MigrateToVersion94AddPromoCodeColumnsToOfferData();
+ case 95:
+ *update_compatible_version = false;
+ return MigrateToVersion95AddVirtualCardMetadata();
+ case 96:
+ return MigrateToVersion96AddAutofillProfileDisallowConfirmableMergesColumn();
}
return true;
}
@@ -1128,8 +1145,9 @@ bool AutofillTable::AddAutofillProfile(const AutofillProfile& profile) {
"(guid, company_name, street_address, dependent_locality, city, state,"
" zipcode, sorting_code, country_code, use_count, use_date, "
" date_modified, origin, language_code, validity_bitfield, "
- " is_client_validity_states_updated)"
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+ " is_client_validity_states_updated, label, "
+ " disallow_settings_visible_updates) "
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
BindAutofillProfileToStatement(profile, AutofillClock::Now(), &s);
if (!s.Run())
@@ -1159,14 +1177,15 @@ bool AutofillTable::UpdateAutofillProfile(const AutofillProfile& profile) {
" city=?, state=?, zipcode=?, sorting_code=?, country_code=?, "
" use_count=?, use_date=?, date_modified=?, origin=?, "
" language_code=?, validity_bitfield=?, "
- " is_client_validity_states_updated=?"
+ " is_client_validity_states_updated=?, "
+ " label=?, disallow_settings_visible_updates=? "
"WHERE guid=?"));
BindAutofillProfileToStatement(profile,
update_modification_date
? AutofillClock::Now()
: old_profile->modification_date(),
&s);
- s.BindString(16, profile.guid());
+ s.BindString(18, profile.guid());
bool result = s.Run();
DCHECK_GT(db_->GetLastChangeCount(), 0);
@@ -1210,7 +1229,8 @@ std::unique_ptr<AutofillProfile> AutofillTable::GetAutofillProfile(
"SELECT guid, company_name, street_address, dependent_locality, city,"
" state, zipcode, sorting_code, country_code, use_count, use_date,"
" date_modified, origin, language_code, validity_bitfield,"
- " is_client_validity_states_updated "
+ " is_client_validity_states_updated, label,"
+ " disallow_settings_visible_updates "
"FROM autofill_profiles "
"WHERE guid=?"));
s.BindString(0, guid);
@@ -1218,7 +1238,7 @@ std::unique_ptr<AutofillProfile> AutofillTable::GetAutofillProfile(
if (!s.Step())
return nullptr;
- std::unique_ptr<AutofillProfile> profile(new AutofillProfile);
+ auto profile = std::make_unique<AutofillProfile>();
profile->set_guid(s.ColumnString(0));
DCHECK(base::IsValidGUID(profile->guid()));
@@ -1493,7 +1513,7 @@ std::unique_ptr<CreditCard> AutofillTable::GetCreditCard(
s.BindString(0, guid);
if (!s.Step())
- return std::unique_ptr<CreditCard>();
+ return nullptr;
return CreditCardFromStatement(s, *autofill_table_encryptor_);
}
@@ -1523,21 +1543,23 @@ bool AutofillTable::GetServerCreditCards(
sql::Statement s(db_->GetUniqueStatement(
"SELECT "
- "card_number_encrypted, " // 0
- "last_four," // 1
- "masked.id," // 2
- "metadata.use_count," // 3
- "metadata.use_date," // 4
- "network," // 5
- "status," // 6
- "name_on_card," // 7
- "exp_month," // 8
- "exp_year," // 9
- "metadata.billing_address_id," // 10
- "bank_name," // 11
- "nickname," // 12
- "card_issuer," // 13
- "instrument_id " // 14
+ "card_number_encrypted, " // 0
+ "last_four," // 1
+ "masked.id," // 2
+ "metadata.use_count," // 3
+ "metadata.use_date," // 4
+ "network," // 5
+ "status," // 6
+ "name_on_card," // 7
+ "exp_month," // 8
+ "exp_year," // 9
+ "metadata.billing_address_id," // 10
+ "bank_name," // 11
+ "nickname," // 12
+ "card_issuer," // 13
+ "instrument_id, " // 14
+ "virtual_card_enrollment_state, " // 15
+ "card_art_url " // 16
"FROM masked_credit_cards masked "
"LEFT OUTER JOIN unmasked_credit_cards USING (id) "
"LEFT OUTER JOIN server_card_metadata metadata USING (id)"));
@@ -1584,6 +1606,10 @@ bool AutofillTable::GetServerCreditCards(
card->set_card_issuer(
static_cast<CreditCard::Issuer>(s.ColumnInt(index++)));
card->set_instrument_id(s.ColumnInt64(index++));
+ card->set_virtual_card_enrollment_state(
+ static_cast<CreditCard::VirtualCardEnrollmentState>(
+ s.ColumnInt(index++)));
+ card->set_card_art_url(GURL(s.ColumnString(index++)));
credit_cards->push_back(std::move(card));
}
return s.Succeeded();
@@ -1834,18 +1860,20 @@ void AutofillTable::SetServerCardsData(
// Add all the masked cards.
sql::Statement masked_insert(
db_->GetUniqueStatement("INSERT INTO masked_credit_cards("
- "id," // 0
- "network," // 1
- "status," // 2
- "name_on_card," // 3
- "last_four," // 4
- "exp_month," // 5
- "exp_year," // 6
- "bank_name," // 7
- "nickname," // 8
- "card_issuer," // 9
- "instrument_id)" // 10
- "VALUES (?,?,?,?,?,?,?,?,?,?,?)"));
+ "id," // 0
+ "network," // 1
+ "status," // 2
+ "name_on_card," // 3
+ "last_four," // 4
+ "exp_month," // 5
+ "exp_year," // 6
+ "bank_name," // 7
+ "nickname," // 8
+ "card_issuer," // 9
+ "instrument_id," // 10
+ "virtual_card_enrollment_state," // 11
+ "card_art_url) " // 12
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
int index;
for (const CreditCard& card : credit_cards) {
DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type());
@@ -1863,6 +1891,9 @@ void AutofillTable::SetServerCardsData(
masked_insert.BindString16(index++, card.nickname());
masked_insert.BindInt(index++, static_cast<int>(card.card_issuer()));
masked_insert.BindInt64(index++, card.instrument_id());
+ masked_insert.BindInt(
+ index++, static_cast<int>(card.virtual_card_enrollment_state()));
+ masked_insert.BindString(index++, card.card_art_url().spec());
masked_insert.Run();
masked_insert.Reset(true);
}
@@ -1997,6 +2028,61 @@ bool AutofillTable::GetCreditCardCloudTokenData(
return s.Succeeded();
}
+bool AutofillTable::AddCreditCardArtImage(
+ const CreditCardArtImage& credit_card_art_image) {
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin())
+ return false;
+
+ sql::Statement s(db_->GetUniqueStatement(
+ "INSERT INTO credit_card_art_images(id, instrument_id, card_art_image)"
+ "VALUES (?,?,?)"));
+ s.BindString(0, credit_card_art_image.id);
+ s.BindInt64(1, credit_card_art_image.instrument_id);
+ s.BindBlob(2, credit_card_art_image.card_art_image.data(),
+ credit_card_art_image.card_art_image.size());
+ s.Run();
+
+ return transaction.Commit();
+}
+
+bool AutofillTable::GetCreditCardArtImages(
+ std::vector<std::unique_ptr<CreditCardArtImage>>* credit_card_art_images) {
+ credit_card_art_images->clear();
+
+ sql::Statement s(
+ db_->GetUniqueStatement("SELECT "
+ "id, " // 0
+ "instrument_id, " // 1
+ "card_art_image " // 2
+ "FROM credit_card_art_images"));
+
+ while (s.Step()) {
+ std::vector<uint8_t> card_art_image;
+ if (s.ColumnBlobAsVector(2, &card_art_image)) {
+ std::unique_ptr<CreditCardArtImage> data =
+ std::make_unique<CreditCardArtImage>(
+ s.ColumnString(0), s.ColumnInt64(1), std::move(card_art_image));
+ credit_card_art_images->push_back(std::move(data));
+ }
+ }
+
+ return s.Succeeded();
+}
+
+bool AutofillTable::ClearCreditCardArtImage(const std::string& id) {
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin())
+ return false;
+
+ sql::Statement s(db_->GetUniqueStatement(
+ "DELETE FROM credit_card_art_images WHERE id = ?"));
+ s.BindString(0, id);
+ s.Run();
+
+ return transaction.Commit();
+}
+
void AutofillTable::SetPaymentsCustomerData(
const PaymentsCustomerData* customer_data) {
sql::Transaction transaction(db_);
@@ -2030,7 +2116,7 @@ bool AutofillTable::GetPaymentsCustomerData(
return s.Succeeded();
}
-void AutofillTable::SetCreditCardOffers(
+void AutofillTable::SetAutofillOffers(
const std::vector<AutofillOfferData>& autofill_offer_data) {
sql::Transaction transaction(db_);
if (!transaction.Begin())
@@ -2050,11 +2136,15 @@ void AutofillTable::SetCreditCardOffers(
// Insert new values.
sql::Statement insert_offers(
db_->GetUniqueStatement("INSERT INTO offer_data("
- "offer_id, " // 0
- "offer_reward_amount, " // 1
- "expiry, " // 2
- "offer_details_url) " // 3
- "VALUES (?,?,?,?)"));
+ "offer_id, " // 0
+ "offer_reward_amount, " // 1
+ "expiry, " // 2
+ "offer_details_url, " // 3
+ "promo_code, " // 4
+ "value_prop_text, " // 5
+ "see_details_text, " // 6
+ "usage_instructions_text) " // 7
+ "VALUES (?,?,?,?,?,?,?,?)"));
for (const AutofillOfferData& data : autofill_offer_data) {
insert_offers.BindInt64(0, data.offer_id);
@@ -2062,6 +2152,10 @@ void AutofillTable::SetCreditCardOffers(
insert_offers.BindInt64(
2, data.expiry.ToDeltaSinceWindowsEpoch().InMilliseconds());
insert_offers.BindString(3, data.offer_details_url.spec());
+ insert_offers.BindString(4, data.promo_code);
+ insert_offers.BindString(5, data.display_strings.value_prop_text);
+ insert_offers.BindString(6, data.display_strings.see_details_text);
+ insert_offers.BindString(7, data.display_strings.usage_instructions_text);
insert_offers.Run();
insert_offers.Reset(true);
@@ -2095,16 +2189,20 @@ void AutofillTable::SetCreditCardOffers(
transaction.Commit();
}
-bool AutofillTable::GetCreditCardOffers(
+bool AutofillTable::GetAutofillOffers(
std::vector<std::unique_ptr<AutofillOfferData>>* autofill_offer_data) {
autofill_offer_data->clear();
sql::Statement s(
db_->GetUniqueStatement("SELECT "
- "offer_id, " // 0
- "offer_reward_amount, " // 1
- "expiry, " // 2
- "offer_details_url " // 3
+ "offer_id, " // 0
+ "offer_reward_amount, " // 1
+ "expiry, " // 2
+ "offer_details_url, " // 3
+ "promo_code, " // 4
+ "value_prop_text, " // 5
+ "see_details_text, " // 6
+ "usage_instructions_text " // 7
"FROM offer_data"));
while (s.Step()) {
@@ -2116,6 +2214,10 @@ bool AutofillTable::GetCreditCardOffers(
data->expiry = base::Time::FromDeltaSinceWindowsEpoch(
base::TimeDelta::FromMilliseconds(s.ColumnInt64(index++)));
data->offer_details_url = GURL(s.ColumnString(index++));
+ data->promo_code = s.ColumnString(index++);
+ data->display_strings.value_prop_text = s.ColumnString(index++);
+ data->display_strings.see_details_text = s.ColumnString(index++);
+ data->display_strings.usage_instructions_text = s.ColumnString(index++);
sql::Statement s_offer_eligible_instrument(
db_->GetUniqueStatement("SELECT "
@@ -2233,6 +2335,11 @@ bool AutofillTable::ClearAllServerData() {
autofill_offer_merchant_domain.Run();
changed |= db_->GetLastChangeCount() > 0;
+ sql::Statement credit_card_art_images(
+ db_->GetUniqueStatement("DELETE FROM credit_card_art_images"));
+ credit_card_art_images.Run();
+ changed |= db_->GetLastChangeCount() > 0;
+
transaction.Commit();
return changed;
}
@@ -3393,6 +3500,26 @@ bool AutofillTable::MigrateToVersion91AddMoreStructuredAddressColumns() {
return true;
}
+bool AutofillTable::MigrateToVersion93AddAutofillProfileLabelColumn() {
+ if (!db_->DoesTableExist("autofill_profiles"))
+ InitProfileAddressesTable();
+
+ return db_->DoesColumnExist("autofill_profiles", "label") ||
+ db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN label VARCHAR");
+}
+
+bool AutofillTable::
+ MigrateToVersion96AddAutofillProfileDisallowConfirmableMergesColumn() {
+ if (!db_->DoesTableExist("autofill_profiles"))
+ InitProfileAddressesTable();
+
+ return db_->DoesColumnExist("autofill_profiles",
+ "disallow_settings_visible_updates") ||
+ db_->Execute(
+ "ALTER TABLE autofill_profiles ADD COLUMN "
+ "disallow_settings_visible_updates INTEGER NOT NULL DEFAULT 0");
+}
+
bool AutofillTable::
MigrateToVersion89AddInstrumentIdColumnToMaskedCreditCard() {
// Add the new instrument_id column to the masked_credit_cards table and set
@@ -3404,6 +3531,57 @@ bool AutofillTable::
"DEFAULT 0");
}
+bool AutofillTable::MigrateToVersion94AddPromoCodeColumnsToOfferData() {
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin())
+ return false;
+
+ if (!db_->DoesTableExist("offer_data"))
+ InitOfferDataTable();
+
+ // Add the new promo_code and DisplayStrings text columns to the offer_data
+ // table.
+ for (const char* column : {"promo_code", "value_prop_text",
+ "see_details_text", "usage_instructions_text"}) {
+ if (!db_->DoesColumnExist("offer_data", column) &&
+ !db_->Execute(base::StrCat({"ALTER TABLE offer_data ADD COLUMN ",
+ column, " VARCHAR"})
+ .c_str())) {
+ return false;
+ }
+ }
+ return transaction.Commit();
+}
+
+bool AutofillTable::MigrateToVersion95AddVirtualCardMetadata() {
+ sql::Transaction transaction(db_);
+ if (!transaction.Begin())
+ return false;
+
+ if (!db_->DoesTableExist("masked_credit_cards"))
+ InitMaskedCreditCardsTable();
+
+ if (!db_->DoesTableExist("credit_card_art_images"))
+ InitCreditCardArtImagesTable();
+
+ // Add virtual_card_enrollment_state to masked_credit_cards.
+ if (!db_->DoesColumnExist("masked_credit_cards",
+ "virtual_card_enrollment_state") &&
+ !db_->Execute("ALTER TABLE masked_credit_cards ADD COLUMN "
+ "virtual_card_enrollment_state INTEGER DEFAULT 0")) {
+ return false;
+ }
+
+ // Add card_art_url to masked_credit_cards.
+ if (!db_->DoesColumnExist("masked_credit_cards", "card_art_url") &&
+ !db_->Execute("ALTER TABLE masked_credit_cards ADD COLUMN "
+ "card_art_url VARCHAR")) {
+ return false;
+ }
+
+ return transaction.Commit();
+}
+
bool AutofillTable::AddFormFieldValuesTime(
const std::vector<FormFieldData>& elements,
std::vector<AutofillChange>* changes,
@@ -3564,18 +3742,20 @@ void AutofillTable::AddMaskedCreditCards(
DCHECK_GT(db_->transaction_nesting(), 0);
sql::Statement masked_insert(
db_->GetUniqueStatement("INSERT INTO masked_credit_cards("
- "id," // 0
- "network," // 1
- "status," // 2
- "name_on_card," // 3
- "last_four," // 4
- "exp_month," // 5
- "exp_year," // 6
- "bank_name," // 7
- "nickname," // 8
- "card_issuer," // 9
- "instrument_id)" // 10
- "VALUES (?,?,?,?,?,?,?,?,?,?,?)"));
+ "id," // 0
+ "network," // 1
+ "status," // 2
+ "name_on_card," // 3
+ "last_four," // 4
+ "exp_month," // 5
+ "exp_year," // 6
+ "bank_name," // 7
+ "nickname," // 8
+ "card_issuer," // 9
+ "instrument_id," // 10
+ "virtual_card_enrollment_state, " // 11
+ "card_art_url) " // 12
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)"));
int index;
for (const CreditCard& card : credit_cards) {
DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type());
@@ -3593,6 +3773,8 @@ void AutofillTable::AddMaskedCreditCards(
masked_insert.BindString16(index++, card.nickname());
masked_insert.BindInt(index++, static_cast<int>(card.card_issuer()));
masked_insert.BindInt64(index++, card.instrument_id());
+ masked_insert.BindInt(index++, card.virtual_card_enrollment_state());
+ masked_insert.BindString(index++, card.card_art_url().spec());
masked_insert.Run();
masked_insert.Reset(true);
@@ -3680,24 +3862,27 @@ bool AutofillTable::InitCreditCardsTable() {
bool AutofillTable::InitProfilesTable() {
if (!db_->DoesTableExist("autofill_profiles")) {
- if (!db_->Execute("CREATE TABLE autofill_profiles ( "
- "guid VARCHAR PRIMARY KEY, "
- "company_name VARCHAR, "
- "street_address VARCHAR, "
- "dependent_locality VARCHAR, "
- "city VARCHAR, "
- "state VARCHAR, "
- "zipcode VARCHAR, "
- "sorting_code VARCHAR, "
- "country_code VARCHAR, "
- "date_modified INTEGER NOT NULL DEFAULT 0, "
- "origin VARCHAR DEFAULT '', "
- "language_code VARCHAR, "
- "use_count INTEGER NOT NULL DEFAULT 0, "
- "use_date INTEGER NOT NULL DEFAULT 0, "
- "validity_bitfield UNSIGNED NOT NULL DEFAULT 0, "
- "is_client_validity_states_updated BOOL NOT NULL DEFAULT "
- "FALSE) ")) {
+ if (!db_->Execute(
+ "CREATE TABLE autofill_profiles ( "
+ "guid VARCHAR PRIMARY KEY, "
+ "company_name VARCHAR, "
+ "street_address VARCHAR, "
+ "dependent_locality VARCHAR, "
+ "city VARCHAR, "
+ "state VARCHAR, "
+ "zipcode VARCHAR, "
+ "sorting_code VARCHAR, "
+ "country_code VARCHAR, "
+ "date_modified INTEGER NOT NULL DEFAULT 0, "
+ "origin VARCHAR DEFAULT '', "
+ "language_code VARCHAR, "
+ "use_count INTEGER NOT NULL DEFAULT 0, "
+ "use_date INTEGER NOT NULL DEFAULT 0, "
+ "validity_bitfield UNSIGNED NOT NULL DEFAULT 0, "
+ "is_client_validity_states_updated BOOL NOT NULL DEFAULT "
+ "FALSE, "
+ "label VARCHAR, "
+ "disallow_settings_visible_updates INTEGER NOT NULL DEFAULT 0)")) {
NOTREACHED();
return false;
}
@@ -3826,7 +4011,9 @@ bool AutofillTable::InitMaskedCreditCardsTable() {
"bank_name VARCHAR, "
"nickname VARCHAR, "
"card_issuer INTEGER DEFAULT 0, "
- "instrument_id INTEGER DEFAULT 0)")) {
+ "instrument_id INTEGER DEFAULT 0, "
+ "virtual_card_enrollment_state INTEGER DEFAULT 0, "
+ "card_art_url VARCHAR)")) {
NOTREACHED();
return false;
}
@@ -3970,7 +4157,11 @@ bool AutofillTable::InitOfferDataTable() {
"offer_reward_amount VARCHAR, "
"expiry UNSIGNED LONG, "
"offer_details_url VARCHAR, "
- "merchant_domain VARCHAR)")) {
+ "merchant_domain VARCHAR, "
+ "promo_code VARCHAR, "
+ "value_prop_text VARCHAR, "
+ "see_details_text VARCHAR, "
+ "usage_instructions_text VARCHAR)")) {
NOTREACHED();
return false;
}
@@ -4002,4 +4193,17 @@ bool AutofillTable::InitOfferMerchantDomainTable() {
return true;
}
+bool AutofillTable::InitCreditCardArtImagesTable() {
+ if (!db_->DoesTableExist("credit_card_art_images")) {
+ if (!db_->Execute("CREATE TABLE credit_card_art_images ( "
+ "id VARCHAR NOT NULL DEFAULT 0, "
+ "instrument_id INTEGER DEFAULT 0, "
+ "card_art_image BLOB)")) {
+ NOTREACHED();
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table.h b/chromium/components/autofill/core/browser/webdata/autofill_table.h
index 518bde702a0..223991cdd7c 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table.h
@@ -35,6 +35,7 @@ class AutofillProfile;
class AutofillTableEncryptor;
class AutofillTableTest;
class CreditCard;
+struct CreditCardArtImage;
struct CreditCardCloudTokenData;
struct FormFieldData;
struct PaymentsCustomerData;
@@ -63,6 +64,10 @@ struct PaymentsCustomerData;
//
// guid A guid string to uniquely identify the profile.
// Added in version 31.
+// label A user-chosen and user-visible label for the profile to
+// help identifying the semantics of the profile. The user
+// can choose an arbitrary string in principle, but the
+// values '$HOME$' and '$WORK$' indicate a special meaning.
// company_name
// street_address The combined lines of the street address.
// Added in version 54.
@@ -97,6 +102,9 @@ struct PaymentsCustomerData;
// A flag indicating whether the validity states of
// different fields according to the client validity api is
// updated or not. Added in version 80.
+// disallow_settings_visible_updates
+// If true, a profile does not qualify to get merged with
+// a profile observed in a form submission.
//
// autofill_profile_addresses
// guid The guid string that identifies the profile to which
@@ -264,6 +272,13 @@ struct PaymentsCustomerData;
// instrument_id Credit card id assigned by the server to identify this
// card. This is opaque to the client, and |id| is the
// legacy version of this.
+// virtual_card_enrollment_state
+// An enum indicating the virtual card enrollment state of
+// this card. UNSPECIFIED is the default value. UNENROLLED
+// means this card has not been enrolled to have virtual
+// cards. ENROLLED means the card has been enrolled and
+// has related virtual credit cards.
+// card_art_url URL to generate the card art image for this card.
//
// unmasked_credit_cards
// When a masked credit credit card is unmasked and the
@@ -377,8 +392,8 @@ struct PaymentsCustomerData;
//
// vpa_id A string representing the UPI ID (a.k.a. VPA) value.
//
-// offer_data The data for credit card offers which will be presented
-// in payments autofill flows.
+// offer_data The data for Autofill offers which will be presented in
+// payments autofill flows.
//
// offer_id The unique server ID for this offer data.
// offer_reward_amount
@@ -388,6 +403,14 @@ struct PaymentsCustomerData;
// expiry The timestamp when the offer will go expired. Expired
// offers will not be shown in the frontend.
// offer_details_url The link leading to the offer details page on Gpay app.
+// promo_code The promo code to be autofilled for a promo code offer.
+// value_prop_text Server-driven UI string to explain the value of the
+// offer.
+// see_details_text Server-driven UI string to imply or link additional
+// details.
+// usage_instructions_text
+// Server-driven UI string to instruct the user on how they
+// can redeem the offer.
//
// offer_eligible_instrument
// Contains the mapping of credit cards and card linked
@@ -406,6 +429,13 @@ struct PaymentsCustomerData;
// offer_id in the offer_data table.
// merchant_domain List of full origins for merchant websites on which
// this offer would apply.
+// credit_card_art_images
+// Contains the card art image for the server credit card.
+//
+// id The server id of the credit card.
+// instrument_id The non-legacy server instrument id of the card.
+// card_art_image The customized card art image. Stored in the form of
+// BLOB.
class AutofillTable : public WebDatabaseTable,
public syncer::SyncMetadataStore {
@@ -566,6 +596,12 @@ class AutofillTable : public WebDatabaseTable,
std::vector<std::unique_ptr<CreditCardCloudTokenData>>*
credit_card_cloud_token_data);
+ // Setters and getters related to the credit card art images.
+ bool AddCreditCardArtImage(const CreditCardArtImage& credit_card_art_image);
+ bool GetCreditCardArtImages(
+ std::vector<std::unique_ptr<CreditCardArtImage>>* credit_card_art_images);
+ bool ClearCreditCardArtImage(const std::string& id);
+
// Setters and getters related to the Google Payments customer data.
// Passing null to the setter will clear the data.
void SetPaymentsCustomerData(const PaymentsCustomerData* customer_data);
@@ -576,9 +612,9 @@ class AutofillTable : public WebDatabaseTable,
// |autofill_offer_data| must include all existing offers, since table will
// be completely overwritten.
- void SetCreditCardOffers(
+ void SetAutofillOffers(
const std::vector<AutofillOfferData>& autofill_offer_data);
- bool GetCreditCardOffers(
+ bool GetAutofillOffers(
std::vector<std::unique_ptr<AutofillOfferData>>* autofill_offer_data);
// Adds |upi_id| to the saved UPI IDs.
@@ -683,6 +719,10 @@ class AutofillTable : public WebDatabaseTable,
bool MigrateToVersion90AddNewStructuredAddressColumns();
bool MigrateToVersion91AddMoreStructuredAddressColumns();
bool MigrateToVersion92AddNewPrefixedNameColumn();
+ bool MigrateToVersion93AddAutofillProfileLabelColumn();
+ bool MigrateToVersion94AddPromoCodeColumnsToOfferData();
+ bool MigrateToVersion95AddVirtualCardMetadata();
+ bool MigrateToVersion96AddAutofillProfileDisallowConfirmableMergesColumn();
// Max data length saved in the table, AKA the maximum length allowed for
// form data.
@@ -795,6 +835,7 @@ class AutofillTable : public WebDatabaseTable,
bool InitOfferDataTable();
bool InitOfferEligibleInstrumentTable();
bool InitOfferMerchantDomainTable();
+ bool InitCreditCardArtImagesTable();
std::unique_ptr<AutofillTableEncryptor> autofill_table_encryptor_;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
index 3e1088216f7..1afd6949cd3 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_table_unittest.cc
@@ -8,7 +8,6 @@
#include <memory>
#include <set>
#include <string>
-#include <tuple>
#include <utility>
#include "base/command_line.h"
@@ -28,6 +27,7 @@
#include "components/autofill/core/browser/data_model/autofill_offer_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/browser/data_model/credit_card_art_image.h"
#include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h"
#include "components/autofill/core/browser/payments/payments_customer_data.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
@@ -46,7 +46,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::ASCIIToUTF16;
using base::Time;
using base::TimeDelta;
using sync_pb::EntityMetadata;
@@ -103,14 +102,13 @@ bool CompareAutofillEntries(const AutofillEntry& a, const AutofillEntry& b) {
b.date_last_used());
}
-AutofillEntry MakeAutofillEntry(const std::string& name,
- const std::string& value,
+AutofillEntry MakeAutofillEntry(const std::u16string& name,
+ const std::u16string& value,
time_t date_created,
time_t date_last_used) {
if (date_last_used < 0)
date_last_used = date_created;
- return AutofillEntry(AutofillKey(ASCIIToUTF16(name), ASCIIToUTF16(value)),
- Time::FromTimeT(date_created),
+ return AutofillEntry(AutofillKey(name, value), Time::FromTimeT(date_created),
Time::FromTimeT(date_last_used));
}
@@ -331,16 +329,16 @@ TEST_F(AutofillTableTest, Autofill_GetCountOfValuesContainedBetween) {
TimeDelta second = TimeDelta::FromSeconds(1);
struct Entry {
- const char* name;
- const char* value;
- } entries[] = {{"Alter ego", "Superman"}, {"Name", "Superman"},
- {"Name", "Clark Kent"}, {"Name", "Superman"},
- {"Name", "Clark Sutter"}, {"Nomen", "Clark Kent"}};
+ const char16_t* name;
+ const char16_t* value;
+ } entries[] = {{u"Alter ego", u"Superman"}, {u"Name", u"Superman"},
+ {u"Name", u"Clark Kent"}, {u"Name", u"Superman"},
+ {u"Name", u"Clark Sutter"}, {u"Nomen", u"Clark Kent"}};
for (Entry entry : entries) {
FormFieldData field;
- field.name = ASCIIToUTF16(entry.name);
- field.value = ASCIIToUTF16(entry.value);
+ field.name = entry.name;
+ field.value = entry.value;
ASSERT_TRUE(table_->AddFormFieldValueTime(field, &changes, now));
now += second;
}
@@ -438,7 +436,7 @@ TEST_F(AutofillTableTest, Autofill_AddChanges) {
}
TEST_F(AutofillTableTest, Autofill_UpdateOneWithOneTimestamp) {
- AutofillEntry entry(MakeAutofillEntry("foo", "bar", 1, -1));
+ AutofillEntry entry(MakeAutofillEntry(u"foo", u"bar", 1, -1));
std::vector<AutofillEntry> entries;
entries.push_back(entry);
ASSERT_TRUE(table_->UpdateAutofillEntries(entries));
@@ -452,7 +450,7 @@ TEST_F(AutofillTableTest, Autofill_UpdateOneWithOneTimestamp) {
}
TEST_F(AutofillTableTest, Autofill_UpdateOneWithTwoTimestamps) {
- AutofillEntry entry(MakeAutofillEntry("foo", "bar", 1, 2));
+ AutofillEntry entry(MakeAutofillEntry(u"foo", u"bar", 1, 2));
std::vector<AutofillEntry> entries;
entries.push_back(entry);
ASSERT_TRUE(table_->UpdateAutofillEntries(entries));
@@ -466,7 +464,7 @@ TEST_F(AutofillTableTest, Autofill_UpdateOneWithTwoTimestamps) {
}
TEST_F(AutofillTableTest, Autofill_GetAutofillTimestamps) {
- AutofillEntry entry(MakeAutofillEntry("foo", "bar", 1, 2));
+ AutofillEntry entry(MakeAutofillEntry(u"foo", u"bar", 1, 2));
std::vector<AutofillEntry> entries;
entries.push_back(entry);
ASSERT_TRUE(table_->UpdateAutofillEntries(entries));
@@ -479,8 +477,8 @@ TEST_F(AutofillTableTest, Autofill_GetAutofillTimestamps) {
}
TEST_F(AutofillTableTest, Autofill_UpdateTwo) {
- AutofillEntry entry0(MakeAutofillEntry("foo", "bar0", 1, -1));
- AutofillEntry entry1(MakeAutofillEntry("foo", "bar1", 2, 3));
+ AutofillEntry entry0(MakeAutofillEntry(u"foo", u"bar0", 1, -1));
+ AutofillEntry entry1(MakeAutofillEntry(u"foo", u"bar1", 2, 3));
std::vector<AutofillEntry> entries;
entries.push_back(entry0);
entries.push_back(entry1);
@@ -491,10 +489,10 @@ TEST_F(AutofillTableTest, Autofill_UpdateTwo) {
}
TEST_F(AutofillTableTest, Autofill_UpdateNullTerminated) {
- const char kName[] = "foo";
- const char kValue[] = "bar";
+ const char16_t kName[] = u"foo";
+ const char16_t kValue[] = u"bar";
// A value which contains terminating character.
- std::string value(kValue, base::size(kValue));
+ std::u16string value(kValue, base::size(kValue));
AutofillEntry entry0(MakeAutofillEntry(kName, kValue, 1, -1));
AutofillEntry entry1(MakeAutofillEntry(kName, value, 2, 3));
@@ -503,10 +501,8 @@ TEST_F(AutofillTableTest, Autofill_UpdateNullTerminated) {
entries.push_back(entry1);
ASSERT_TRUE(table_->UpdateAutofillEntries(entries));
- EXPECT_EQ(1, GetAutofillEntryCount(ASCIIToUTF16(kName), ASCIIToUTF16(kValue),
- db_.get()));
- EXPECT_EQ(2, GetAutofillEntryCount(ASCIIToUTF16(kName), ASCIIToUTF16(value),
- db_.get()));
+ EXPECT_EQ(1, GetAutofillEntryCount(kName, kValue, db_.get()));
+ EXPECT_EQ(2, GetAutofillEntryCount(kName, value, db_.get()));
std::vector<AutofillEntry> all_entries;
ASSERT_TRUE(table_->GetAllAutofillEntries(&all_entries));
@@ -523,7 +519,7 @@ TEST_F(AutofillTableTest, Autofill_UpdateReplace) {
field.value = u"Superman";
EXPECT_TRUE(table_->AddFormFieldValue(field, &changes));
- AutofillEntry entry(MakeAutofillEntry("Name", "Superman", 1, 2));
+ AutofillEntry entry(MakeAutofillEntry(u"Name", u"Superman", 1, 2));
std::vector<AutofillEntry> entries;
entries.push_back(entry);
ASSERT_TRUE(table_->UpdateAutofillEntries(entries));
@@ -537,7 +533,7 @@ TEST_F(AutofillTableTest, Autofill_UpdateReplace) {
TEST_F(AutofillTableTest, Autofill_UpdateDontReplace) {
Time t = AutofillClock::Now();
AutofillEntry existing(
- MakeAutofillEntry("Name", "Superman", t.ToTimeT(), -1));
+ MakeAutofillEntry(u"Name", u"Superman", t.ToTimeT(), -1));
AutofillChangeList changes;
// Add a form field. This will NOT be replaced.
@@ -545,7 +541,7 @@ TEST_F(AutofillTableTest, Autofill_UpdateDontReplace) {
field.name = existing.key().name();
field.value = existing.key().value();
EXPECT_TRUE(table_->AddFormFieldValueTime(field, &changes, t));
- AutofillEntry entry(MakeAutofillEntry("Name", "Clark Kent", 1, 2));
+ AutofillEntry entry(MakeAutofillEntry(u"Name", u"Clark Kent", 1, 2));
std::vector<AutofillEntry> entries;
entries.push_back(entry);
ASSERT_TRUE(table_->UpdateAutofillEntries(entries));
@@ -1299,6 +1295,7 @@ TEST_F(AutofillTableTest, AutofillProfile_StructuredNames) {
home_profile.SetRawInfo(ADDRESS_HOME_SORTING_CODE, u"MAGIC ###");
home_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, u"US");
home_profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"18181234567");
+ home_profile.set_disallow_settings_visible_updates(true);
home_profile.set_language_code("en");
home_profile.SetClientValidityFromBitfieldValue(6);
home_profile.set_is_client_validity_states_updated(true);
@@ -2462,6 +2459,8 @@ TEST_F(AutofillTableTest, SetGetServerCards) {
inputs[0].SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, u"2020");
inputs[0].SetRawInfo(CREDIT_CARD_NUMBER, u"4111111111111111");
inputs[0].set_instrument_id(321);
+ inputs[0].set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::UNENROLLED);
inputs.push_back(CreditCard(CreditCard::MASKED_SERVER_CARD, "b456"));
inputs[1].SetRawInfo(CREDIT_CARD_NAME_FULL, u"Rick Roman");
@@ -2474,6 +2473,9 @@ TEST_F(AutofillTableTest, SetGetServerCards) {
inputs[1].SetNickname(nickname);
inputs[1].set_card_issuer(CreditCard::Issuer::GOOGLE);
inputs[1].set_instrument_id(123);
+ inputs[1].set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::ENROLLED);
+ inputs[1].set_card_art_url(GURL("https://www.example.com"));
test::SetServerCreditCards(table_.get(), inputs);
@@ -2507,6 +2509,14 @@ TEST_F(AutofillTableTest, SetGetServerCards) {
EXPECT_EQ(321, outputs[0]->instrument_id());
EXPECT_EQ(123, outputs[1]->instrument_id());
+
+ EXPECT_EQ(CreditCard::VirtualCardEnrollmentState::UNENROLLED,
+ outputs[0]->virtual_card_enrollment_state());
+ EXPECT_EQ(CreditCard::VirtualCardEnrollmentState::ENROLLED,
+ outputs[1]->virtual_card_enrollment_state());
+
+ EXPECT_EQ(GURL(), outputs[0]->card_art_url());
+ EXPECT_EQ(GURL("https://www.example.com"), outputs[1]->card_art_url());
}
TEST_F(AutofillTableTest, SetGetRemoveServerCardMetadata) {
@@ -2717,6 +2727,9 @@ TEST_F(AutofillTableTest, SetServerCardsData) {
inputs[0].SetServerStatus(CreditCard::EXPIRED);
inputs[0].SetNickname(u"Grocery card");
inputs[0].set_instrument_id(1);
+ inputs[0].set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::ENROLLED);
+ inputs[0].set_card_art_url(GURL("https://www.example.com"));
table_->SetServerCardsData(inputs);
// Make sure the card was added correctly.
@@ -2733,6 +2746,11 @@ TEST_F(AutofillTableTest, SetServerCardsData) {
EXPECT_EQ(inputs[0], *outputs[0]);
EXPECT_EQ(CreditCard::EXPIRED, outputs[0]->GetServerStatus());
+ EXPECT_EQ(CreditCard::VirtualCardEnrollmentState::ENROLLED,
+ outputs[0]->virtual_card_enrollment_state());
+
+ EXPECT_EQ(GURL("https://www.example.com"), outputs[0]->card_art_url());
+
// Make sure no metadata was added.
std::map<std::string, AutofillMetadata> metadata_map;
ASSERT_TRUE(table_->GetServerCardsMetadata(&metadata_map));
@@ -3239,10 +3257,10 @@ TEST_F(AutofillTableTest, GetCreditCardCloudData_NoData) {
const size_t kMaxCount = 2;
struct GetFormValuesTestCase {
- const char* const field_suggestion[kMaxCount];
- const char* const field_contents;
+ const char16_t* const field_suggestion[kMaxCount];
+ const char16_t* const field_contents;
size_t expected_suggestion_count;
- const char* const expected_suggestion[kMaxCount];
+ const char16_t* const expected_suggestion[kMaxCount];
};
class GetFormValuesTest : public testing::TestWithParam<GetFormValuesTestCase> {
@@ -3288,18 +3306,16 @@ TEST_P(GetFormValuesTest, GetFormValuesForElementName_SubstringMatchEnabled) {
FormFieldData field;
for (size_t k = 0; k < kMaxCount; ++k) {
field.name = u"Name";
- field.value = ASCIIToUTF16(test_case.field_suggestion[k]);
+ field.value = test_case.field_suggestion[k];
table_->AddFormFieldValue(field, &changes);
}
std::vector<AutofillEntry> v;
- table_->GetFormValuesForElementName(
- u"Name", ASCIIToUTF16(test_case.field_contents), &v, 6);
+ table_->GetFormValuesForElementName(u"Name", test_case.field_contents, &v, 6);
EXPECT_EQ(test_case.expected_suggestion_count, v.size());
for (size_t j = 0; j < test_case.expected_suggestion_count; ++j) {
- EXPECT_EQ(ASCIIToUTF16(test_case.expected_suggestion[j]),
- v[j].key().value());
+ EXPECT_EQ(test_case.expected_suggestion[j], v[j].key().value());
}
changes.clear();
@@ -3309,36 +3325,36 @@ TEST_P(GetFormValuesTest, GetFormValuesForElementName_SubstringMatchEnabled) {
INSTANTIATE_TEST_SUITE_P(
AutofillTableTest,
GetFormValuesTest,
- testing::Values(GetFormValuesTestCase{{"user.test", "test_user"},
- "TEST",
+ testing::Values(GetFormValuesTestCase{{u"user.test", u"test_user"},
+ u"TEST",
2,
- {"test_user", "user.test"}},
- GetFormValuesTestCase{{"user test", "test-user"},
- "user",
+ {u"test_user", u"user.test"}},
+ GetFormValuesTestCase{{u"user test", u"test-user"},
+ u"user",
2,
- {"user test", "test-user"}},
- GetFormValuesTestCase{{"user test", "test-rest"},
- "user",
+ {u"user test", u"test-user"}},
+ GetFormValuesTestCase{{u"user test", u"test-rest"},
+ u"user",
1,
- {"user test", nullptr}},
- GetFormValuesTestCase{{"user@test", "test_user"},
- "user@t",
+ {u"user test", nullptr}},
+ GetFormValuesTestCase{{u"user@test", u"test_user"},
+ u"user@t",
1,
- {"user@test", nullptr}},
- GetFormValuesTestCase{{"user.test", "test_user"},
- "er.tes",
+ {u"user@test", nullptr}},
+ GetFormValuesTestCase{{u"user.test", u"test_user"},
+ u"er.tes",
0,
{nullptr, nullptr}},
- GetFormValuesTestCase{{"user test", "test_user"},
- "_ser",
+ GetFormValuesTestCase{{u"user test", u"test_user"},
+ u"_ser",
0,
{nullptr, nullptr}},
- GetFormValuesTestCase{{"user.test", "test_user"},
- "%ser",
+ GetFormValuesTestCase{{u"user.test", u"test_user"},
+ u"%ser",
0,
{nullptr, nullptr}},
- GetFormValuesTestCase{{"user.test", "test_user"},
- "; DROP TABLE autofill;",
+ GetFormValuesTestCase{{u"user.test", u"test_user"},
+ u"; DROP TABLE autofill;",
0,
{nullptr, nullptr}}));
@@ -3641,10 +3657,12 @@ TEST_F(AutofillTableTest, SetAndGetCreditCardOfferData) {
credit_card_offer_2.offer_id = 2;
credit_card_offer_3.offer_id = 3;
- // Set reward amounts.
+ // Set reward amounts for card-linked offers on offer 1 and 2.
credit_card_offer_1.offer_reward_amount = "$5";
credit_card_offer_2.offer_reward_amount = "10%";
- credit_card_offer_3.offer_reward_amount = "5%";
+
+ // Set promo code for offer 3.
+ credit_card_offer_3.promo_code = "5PCTOFFSHOES";
// Set expiry.
credit_card_offer_1.expiry = base::Time::FromDoubleT(1000);
@@ -3675,15 +3693,28 @@ TEST_F(AutofillTableTest, SetAndGetCreditCardOfferData) {
credit_card_offer_3.merchant_domain.emplace_back(
"http://www.merchant_domain_3_2.com/");
- // Set eligible instrument ID for offer 1.
+ // Set display strings for all 3 offers.
+ credit_card_offer_1.display_strings.value_prop_text = "$5 off your purchase";
+ credit_card_offer_2.display_strings.value_prop_text = "10% off your purchase";
+ credit_card_offer_3.display_strings.value_prop_text =
+ "5% off shoes. Up to $50.";
+ credit_card_offer_1.display_strings.see_details_text = "Terms apply.";
+ credit_card_offer_2.display_strings.see_details_text = "Terms apply.";
+ credit_card_offer_3.display_strings.see_details_text = "See details.";
+ credit_card_offer_1.display_strings.usage_instructions_text =
+ "Check out with this card to activate.";
+ credit_card_offer_2.display_strings.usage_instructions_text =
+ "Check out with this card to activate.";
+ credit_card_offer_3.display_strings.usage_instructions_text =
+ "Click the promo code field at checkout to autofill it.";
+
+ // Set eligible card-linked instrument ID for offer 1.
credit_card_offer_1.eligible_instrument_id.push_back(10);
credit_card_offer_1.eligible_instrument_id.push_back(11);
- // Set eligible instrument ID for offer 2.
+ // Set eligible card-linked instrument ID for offer 2.
credit_card_offer_2.eligible_instrument_id.push_back(20);
credit_card_offer_2.eligible_instrument_id.push_back(21);
credit_card_offer_2.eligible_instrument_id.push_back(22);
- // Set eligible instrument ID for offer 3.
- credit_card_offer_3.eligible_instrument_id.push_back(30);
// Create vector of offer data.
std::vector<AutofillOfferData> autofill_offer_data;
@@ -3691,11 +3722,11 @@ TEST_F(AutofillTableTest, SetAndGetCreditCardOfferData) {
autofill_offer_data.push_back(credit_card_offer_2);
autofill_offer_data.push_back(credit_card_offer_3);
- table_->SetCreditCardOffers(autofill_offer_data);
+ table_->SetAutofillOffers(autofill_offer_data);
std::vector<std::unique_ptr<AutofillOfferData>> output_offer_data;
- EXPECT_TRUE(table_->GetCreditCardOffers(&output_offer_data));
+ EXPECT_TRUE(table_->GetAutofillOffers(&output_offer_data));
EXPECT_EQ(autofill_offer_data.size(), output_offer_data.size());
for (const auto& data : autofill_offer_data) {
@@ -3715,9 +3746,18 @@ TEST_F(AutofillTableTest, SetAndGetCreditCardOfferData) {
EXPECT_EQ(data.offer_id, output_offer_data[output_index]->offer_id);
EXPECT_EQ(data.offer_reward_amount,
output_offer_data[output_index]->offer_reward_amount);
+ EXPECT_EQ(data.promo_code, output_offer_data[output_index]->promo_code);
EXPECT_EQ(data.expiry, output_offer_data[output_index]->expiry);
EXPECT_EQ(data.offer_details_url.spec(),
output_offer_data[output_index]->offer_details_url.spec());
+ EXPECT_EQ(data.display_strings.value_prop_text,
+ output_offer_data[output_index]->display_strings.value_prop_text);
+ EXPECT_EQ(
+ data.display_strings.see_details_text,
+ output_offer_data[output_index]->display_strings.see_details_text);
+ EXPECT_EQ(data.display_strings.usage_instructions_text,
+ output_offer_data[output_index]
+ ->display_strings.usage_instructions_text);
ASSERT_THAT(data.merchant_domain,
testing::UnorderedElementsAreArray(
output_offer_data[output_index]->merchant_domain));
@@ -3727,4 +3767,34 @@ TEST_F(AutofillTableTest, SetAndGetCreditCardOfferData) {
}
}
+TEST_F(AutofillTableTest, SetAndGetAndClearCreditCardArtImage) {
+ CreditCardArtImage image1("image1", 1, {UINT8_MAX});
+ table_->AddCreditCardArtImage(image1);
+ CreditCardArtImage image2("image2", 2, {UINT8_MAX});
+ table_->AddCreditCardArtImage(image2);
+
+ std::vector<std::unique_ptr<CreditCardArtImage>> output;
+ EXPECT_TRUE(table_->GetCreditCardArtImages(&output));
+ EXPECT_EQ(2U, output.size());
+ EXPECT_EQ("image1", output[0]->id);
+ EXPECT_EQ(1, output[0]->instrument_id);
+ EXPECT_EQ(UINT8_MAX, output[0]->card_art_image[0]);
+ EXPECT_EQ("image2", output[1]->id);
+ EXPECT_EQ(2, output[1]->instrument_id);
+ EXPECT_EQ(UINT8_MAX, output[1]->card_art_image[0]);
+
+ EXPECT_TRUE(table_->ClearCreditCardArtImage("image1"));
+ output.clear();
+ EXPECT_TRUE(table_->GetCreditCardArtImages(&output));
+ EXPECT_EQ(1U, output.size());
+ EXPECT_EQ("image2", output[0]->id);
+ EXPECT_EQ(2, output[0]->instrument_id);
+ EXPECT_EQ(UINT8_MAX, output[0]->card_art_image[0]);
+
+ EXPECT_TRUE(table_->ClearAllServerData());
+ output.clear();
+ EXPECT_TRUE(table_->GetCreditCardArtImages(&output));
+ EXPECT_EQ(0U, output.size());
+}
+
} // namespace autofill
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 746f529720b..ec28a04e5bf 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
@@ -13,7 +13,6 @@
#include "base/callback_helpers.h"
#include "base/check_op.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/pickle.h"
#include "components/autofill/core/browser/data_model/autofill_metadata.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
@@ -27,6 +26,7 @@
#include "components/sync/model/client_tag_based_model_type_processor.h"
#include "components/sync/model/mutable_data_batch.h"
#include "components/sync/model/sync_metadata_store_change_list.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -299,6 +299,28 @@ bool UpdateServerMetadata(AutofillTable* table,
}
}
+bool IsSyncedWalletAddress(const AutofillProfile* profile) {
+ switch (profile->record_type()) {
+ case AutofillProfile::LOCAL_PROFILE:
+ return false;
+ case AutofillProfile::SERVER_PROFILE:
+ return true;
+ }
+}
+
+bool IsSyncedWalletCard(const CreditCard* card) {
+ switch (card->record_type()) {
+ case CreditCard::LOCAL_CARD:
+ return false;
+ case CreditCard::MASKED_SERVER_CARD:
+ return true;
+ case CreditCard::FULL_SERVER_CARD:
+ return true;
+ case CreditCard::VIRTUAL_CARD:
+ return false;
+ }
+}
+
} // namespace
// static
@@ -348,7 +370,7 @@ AutofillWalletMetadataSyncBridge::CreateMetadataChangeList() {
GetAutofillTable(), syncer::AUTOFILL_WALLET_METADATA);
}
-base::Optional<syncer::ModelError>
+absl::optional<syncer::ModelError>
AutofillWalletMetadataSyncBridge::MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
@@ -360,7 +382,7 @@ AutofillWalletMetadataSyncBridge::MergeSyncData(
std::move(entity_data));
}
-base::Optional<syncer::ModelError>
+absl::optional<syncer::ModelError>
AutofillWalletMetadataSyncBridge::ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
@@ -380,7 +402,7 @@ void AutofillWalletMetadataSyncBridge::GetData(StorageKeyList storage_keys,
void AutofillWalletMetadataSyncBridge::GetAllDataForDebugging(
DataCallback callback) {
// Get all data by not providing any |storage_keys| filter.
- GetDataImpl(/*storage_keys=*/base::nullopt, std::move(callback));
+ GetDataImpl(/*storage_keys=*/absl::nullopt, std::move(callback));
}
std::string AutofillWalletMetadataSyncBridge::GetClientTag(
@@ -431,8 +453,7 @@ void AutofillWalletMetadataSyncBridge::ApplyStopSyncChanges(
void AutofillWalletMetadataSyncBridge::AutofillProfileChanged(
const AutofillProfileChange& change) {
- // Skip local profiles.
- if (change.data_model()->record_type() != AutofillProfile::SERVER_PROFILE) {
+ if (!IsSyncedWalletAddress(change.data_model())) {
return;
}
LocalMetadataChanged(WalletMetadataSpecifics::ADDRESS, change);
@@ -440,6 +461,11 @@ void AutofillWalletMetadataSyncBridge::AutofillProfileChanged(
void AutofillWalletMetadataSyncBridge::CreditCardChanged(
const CreditCardChange& change) {
+ // TODO(crbug.com/1206306): Clean up old metadata for local cards, this early
+ // return was missing for quite a while in production.
+ if (!IsSyncedWalletCard(change.data_model())) {
+ return;
+ }
LocalMetadataChanged(WalletMetadataSpecifics::CARD, change);
}
@@ -548,7 +574,7 @@ void AutofillWalletMetadataSyncBridge::DeleteOldOrphanMetadata() {
}
void AutofillWalletMetadataSyncBridge::GetDataImpl(
- base::Optional<std::unordered_set<std::string>> storage_keys_set,
+ absl::optional<std::unordered_set<std::string>> storage_keys_set,
DataCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -593,7 +619,7 @@ void AutofillWalletMetadataSyncBridge::UploadInitialLocalData(
}
}
-base::Optional<syncer::ModelError>
+absl::optional<syncer::ModelError>
AutofillWalletMetadataSyncBridge::MergeRemoteChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
@@ -612,7 +638,7 @@ AutofillWalletMetadataSyncBridge::MergeRemoteChanges(
AutofillMetadata remote =
CreateAutofillMetadataFromWalletMetadataSpecifics(specifics);
auto it = cache_.find(change->storage_key());
- base::Optional<AutofillMetadata> local = base::nullopt;
+ absl::optional<AutofillMetadata> local = absl::nullopt;
if (it != cache_.end()) {
local = it->second;
}
@@ -701,7 +727,7 @@ void AutofillWalletMetadataSyncBridge::LocalMetadataChanged(
AutofillMetadata new_entry = change.data_model()->GetMetadata();
auto it = cache_.find(storage_key);
- base::Optional<AutofillMetadata> existing_entry = base::nullopt;
+ absl::optional<AutofillMetadata> existing_entry = absl::nullopt;
if (it != cache_.end()) {
existing_entry = it->second;
}
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 e66390b84e1..8085137ce3b 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
@@ -60,10 +60,10 @@ class AutofillWalletMetadataSyncBridge
// ModelTypeSyncBridge implementation.
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
@@ -100,7 +100,7 @@ class AutofillWalletMetadataSyncBridge
// |callback|. If |storage_keys_set| is not set, it returns all data entries.
// Otherwise, it returns only entries with storage key in |storage_keys_set|.
void GetDataImpl(
- base::Optional<std::unordered_set<std::string>> storage_keys_set,
+ absl::optional<std::unordered_set<std::string>> storage_keys_set,
DataCallback callback);
// Uploads local data that is not part of |entity_data| sent from the server
@@ -111,7 +111,7 @@ class AutofillWalletMetadataSyncBridge
// Merges remote changes, specified in |entity_data|, with the local DB and,
// potentially, writes changes to the local DB and/or commits updates of
// entities from |entity_data| up to sync.
- base::Optional<syncer::ModelError> MergeRemoteChanges(
+ absl::optional<syncer::ModelError> MergeRemoteChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data);
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 b26bee02309..bea0a2dec04 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
@@ -29,6 +29,7 @@
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/mock_autofill_webdata_backend.h"
#include "components/autofill/core/common/autofill_constants.h"
+#include "components/os_crypt/os_crypt_mocker.h"
#include "components/sync/base/client_tag_hash.h"
#include "components/sync/engine/entity_data.h"
#include "components/sync/model/client_tag_based_model_type_processor.h"
@@ -181,6 +182,24 @@ CreditCard CreateServerCreditCardWithDetails(
return card;
}
+AutofillProfile CreateLocalProfileWithDetails(size_t use_count,
+ int64_t use_date) {
+ AutofillProfile profile;
+ DCHECK_EQ(profile.record_type(), AutofillProfile::LOCAL_PROFILE);
+ profile.set_use_count(use_count);
+ profile.set_use_date(UseDateFromProtoValue(use_date));
+ return profile;
+}
+
+CreditCard CreateLocalCreditCardWithDetails(size_t use_count,
+ int64_t use_date) {
+ CreditCard card;
+ DCHECK_EQ(card.record_type(), CreditCard::LOCAL_CARD);
+ card.set_use_count(use_count);
+ card.set_use_date(UseDateFromProtoValue(use_date));
+ return card;
+}
+
AutofillProfile CreateServerProfileFromSpecifics(
const WalletMetadataSpecifics& specifics) {
return CreateServerProfileWithDetails(
@@ -280,8 +299,7 @@ class AutofillWalletMetadataSyncBridgeTest : public testing::Test {
void ResetProcessor() {
real_processor_ =
std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
- syncer::AUTOFILL_WALLET_METADATA, /*dump_stack=*/base::DoNothing(),
- /*commit_only=*/false);
+ syncer::AUTOFILL_WALLET_METADATA, /*dump_stack=*/base::DoNothing());
mock_processor_.DelegateCallsByDefaultTo(real_processor_.get());
}
@@ -867,6 +885,63 @@ TEST_F(AutofillWalletMetadataSyncBridgeTest,
EXPECT_THAT(GetAllLocalDataInclRestart(), IsEmpty());
}
+// Verify that updates of local (non-sync) addresses are ignored.
+TEST_F(AutofillWalletMetadataSyncBridgeTest, DoNotPropagateNonSyncAddresses) {
+ // Add local data.
+ AutofillProfile existing_profile =
+ CreateLocalProfileWithDetails(/*use_count=*/10, /*use_date=*/20);
+ table()->AddAutofillProfile(existing_profile);
+ ResetBridge();
+
+ // Check that there is no metadata, from start on.
+ ASSERT_THAT(GetAllLocalDataInclRestart(), IsEmpty());
+
+ EXPECT_CALL(mock_processor(), Put).Times(0);
+ // Local changes should not cause local DB writes.
+ EXPECT_CALL(*backend(), CommitChanges()).Times(0);
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()).Times(0);
+
+ existing_profile.set_use_count(11);
+ existing_profile.set_use_date(UseDateFromProtoValue(21));
+ bridge()->AutofillProfileChanged(
+ AutofillProfileChange(AutofillProfileChange::UPDATE,
+ existing_profile.guid(), &existing_profile));
+
+ // Check that there is also no metadata at the end.
+ EXPECT_THAT(GetAllLocalDataInclRestart(), IsEmpty());
+}
+
+// Verify that updates of local (non-sync) credit cards are ignored.
+// Regression test for crbug.com/1206306.
+TEST_F(AutofillWalletMetadataSyncBridgeTest, DoNotPropagateNonSyncCards) {
+ // Local credit cards need crypto for storage.
+ OSCryptMocker::SetUp();
+
+ // Add local data.
+ CreditCard existing_card =
+ CreateLocalCreditCardWithDetails(/*use_count=*/30, /*use_date=*/40);
+ table()->AddCreditCard(existing_card);
+ ResetBridge();
+
+ // Check that there is no metadata, from start on.
+ ASSERT_THAT(GetAllLocalDataInclRestart(), IsEmpty());
+
+ EXPECT_CALL(mock_processor(), Put).Times(0);
+ // Local changes should not cause local DB writes.
+ EXPECT_CALL(*backend(), CommitChanges()).Times(0);
+ EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges()).Times(0);
+
+ existing_card.set_use_count(31);
+ existing_card.set_use_date(UseDateFromProtoValue(41));
+ bridge()->CreditCardChanged(CreditCardChange(
+ AutofillProfileChange::UPDATE, existing_card.guid(), &existing_card));
+
+ // Check that there is also no metadata at the end.
+ EXPECT_THAT(GetAllLocalDataInclRestart(), IsEmpty());
+
+ OSCryptMocker::TearDown();
+}
+
// Verify that old orphan metadata gets deleted on startup.
TEST_F(AutofillWalletMetadataSyncBridgeTest, DeleteOldOrphanMetadataOnStartup) {
WalletMetadataSpecifics profile =
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc
index 36a70eb8898..6d442092df1 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc
@@ -81,12 +81,12 @@ AutofillWalletOfferSyncBridge::CreateMetadataChangeList() {
GetAutofillTable(), syncer::AUTOFILL_WALLET_OFFER);
}
-base::Optional<syncer::ModelError> AutofillWalletOfferSyncBridge::MergeSyncData(
+absl::optional<syncer::ModelError> AutofillWalletOfferSyncBridge::MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// All metadata changes have been already written, return early for an error.
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
static_cast<syncer::SyncMetadataStoreChangeList*>(
metadata_change_list.get())
->TakeError();
@@ -95,17 +95,17 @@ base::Optional<syncer::ModelError> AutofillWalletOfferSyncBridge::MergeSyncData(
}
MergeRemoteData(std::move(entity_data));
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<syncer::ModelError>
+absl::optional<syncer::ModelError>
AutofillWalletOfferSyncBridge::ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
// This bridge does not support incremental updates, so whenever this is
// called, the change list should be empty.
DCHECK(entity_data.empty()) << "Received an unsupported incremental update.";
- return base::nullopt;
+ return absl::nullopt;
}
void AutofillWalletOfferSyncBridge::GetData(StorageKeyList storage_keys,
@@ -147,7 +147,7 @@ void AutofillWalletOfferSyncBridge::GetAllDataImpl(DataCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::vector<std::unique_ptr<AutofillOfferData>> offers;
- if (!GetAutofillTable()->GetCreditCardOffers(&offers)) {
+ if (!GetAutofillTable()->GetAutofillOffers(&offers)) {
change_processor()->ReportError(
{FROM_HERE, "Failed to load offer data from table."});
return;
@@ -189,11 +189,11 @@ void AutofillWalletOfferSyncBridge::MergeRemoteData(
// Only do a write operation if there is any difference between server data
// and local data.
std::vector<std::unique_ptr<AutofillOfferData>> existing_offers;
- table->GetCreditCardOffers(&existing_offers);
+ table->GetAutofillOffers(&existing_offers);
bool offer_data_changed = AreAnyItemsDifferent(existing_offers, offer_data);
if (offer_data_changed) {
- table->SetCreditCardOffers(offer_data);
+ table->SetAutofillOffers(offer_data);
}
// Commit the transaction to make sure the data and the metadata with the
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.h b/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.h
index df1f4d1b18d..f18e3997fd7 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.h
@@ -47,10 +47,10 @@ class AutofillWalletOfferSyncBridge : public base::SupportsUserData::Data,
// ModelTypeSyncBridge
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge_unittest.cc b/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge_unittest.cc
index 4a115fccd10..abad6755458 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge_unittest.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge_unittest.cc
@@ -17,6 +17,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
+#include "build/build_config.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
#include "components/autofill/core/browser/geo/country_names.h"
#include "components/autofill/core/browser/test_autofill_clock.h"
@@ -64,10 +65,12 @@ std::string AutofillOfferSpecificsAsDebugString(
const AutofillOfferSpecifics& specifics) {
std::ostringstream output;
- std::string offer_reward_amount_string =
- specifics.has_percentage_reward()
- ? specifics.percentage_reward().percentage()
- : specifics.fixed_amount_reward().amount();
+ std::string offer_reward_amount_string;
+ if (specifics.has_percentage_reward()) {
+ offer_reward_amount_string = specifics.percentage_reward().percentage();
+ } else if (specifics.has_fixed_amount_reward()) {
+ offer_reward_amount_string = specifics.fixed_amount_reward().amount();
+ }
std::string domain_string;
for (std::string merchant_domain : specifics.merchant_domain()) {
@@ -82,11 +85,25 @@ std::string AutofillOfferSpecificsAsDebugString(
}
output << "[id: " << specifics.id()
- << ", offer_reward_amount: " << offer_reward_amount_string
<< ", offer_expiry_date: " << specifics.offer_expiry_date()
<< ", offer_details_url: " << specifics.offer_details_url()
- << ", merchant_domain: " << domain_string
- << ", eligible_instrument_id: " << instrument_id_string << "]";
+ << ", merchant_domain: " << domain_string << ", value_prop_text: "
+ << specifics.display_strings().value_prop_text()
+#if defined(OS_ANDROID) || defined(OS_IOS)
+ << ", see_details_text: "
+ << specifics.display_strings().see_details_text_mobile()
+ << ", usage_instructions_text: "
+ << specifics.display_strings().usage_instructions_text_mobile()
+#else
+ << ", see_details_text: "
+ << specifics.display_strings().see_details_text_desktop()
+ << ", usage_instructions_text: "
+ << specifics.display_strings().usage_instructions_text_desktop()
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+ << ", offer_reward_amount: " << offer_reward_amount_string
+ << ", eligible_instrument_id: " << instrument_id_string
+ << ", promo_code: " << specifics.promo_code_offer_data().promo_code()
+ << "]";
return output.str();
}
@@ -127,8 +144,7 @@ class AutofillWalletOfferSyncBridgeTest : public testing::Test {
void ResetProcessor() {
real_processor_ =
std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
- syncer::AUTOFILL_WALLET_OFFER, /*dump_stack=*/base::DoNothing(),
- /*commit_only=*/false);
+ syncer::AUTOFILL_WALLET_OFFER, /*dump_stack=*/base::DoNothing());
mock_processor_.DelegateCallsByDefaultTo(real_processor_.get());
}
@@ -237,11 +253,11 @@ TEST_F(AutofillWalletOfferSyncBridgeTest, VerifyGetStorageKey) {
TEST_F(AutofillWalletOfferSyncBridgeTest, MergeSyncData_NewData) {
// Create one offer data in the client table.
AutofillOfferData old_data = test::GetCardLinkedOfferData1();
- table()->SetCreditCardOffers({old_data});
+ table()->SetAutofillOffers({old_data});
// Create a different one on the server.
AutofillOfferSpecifics offer_specifics;
- SetAutofillOfferSpecificsFromOfferData(test::GetCardLinkedOfferData2(),
+ SetAutofillOfferSpecificsFromOfferData(test::GetPromoCodeOfferData(),
&offer_specifics);
EXPECT_CALL(*backend(), CommitChanges());
@@ -258,7 +274,7 @@ TEST_F(AutofillWalletOfferSyncBridgeTest, MergeSyncData_NewData) {
TEST_F(AutofillWalletOfferSyncBridgeTest, MergeSyncData_NoData) {
// Create one offer data in the client table.
AutofillOfferData client_data = test::GetCardLinkedOfferData1();
- table()->SetCreditCardOffers({client_data});
+ table()->SetAutofillOffers({client_data});
EXPECT_CALL(*backend(), CommitChanges());
EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
@@ -293,7 +309,7 @@ TEST_F(AutofillWalletOfferSyncBridgeTest, MergeSyncData_LogDataValidity) {
TEST_F(AutofillWalletOfferSyncBridgeTest, ApplyStopSyncChanges_ClearAllData) {
// Create one offer data in the client table.
AutofillOfferData client_data = test::GetCardLinkedOfferData1();
- table()->SetCreditCardOffers({client_data});
+ table()->SetAutofillOffers({client_data});
EXPECT_CALL(*backend(), CommitChanges());
EXPECT_CALL(*backend(), NotifyOfMultipleAutofillChanges());
@@ -312,7 +328,7 @@ TEST_F(AutofillWalletOfferSyncBridgeTest, ApplyStopSyncChanges_ClearAllData) {
TEST_F(AutofillWalletOfferSyncBridgeTest, ApplyStopSyncChanges_KeepAllData) {
// Create one offer data in the client table.
AutofillOfferData client_data = test::GetCardLinkedOfferData1();
- table()->SetCreditCardOffers({client_data});
+ table()->SetAutofillOffers({client_data});
// We do not write to DB at all, so we should not commit any changes.
EXPECT_CALL(*backend(), CommitChanges()).Times(0);
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 04421a3e523..41e3de12846 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
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_profile_sync_util.h"
#include "components/autofill/core/browser/data_model/autofill_profile.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
@@ -135,6 +136,35 @@ std::unique_ptr<EntityData> CreateEntityDataFromCreditCardCloudTokenData(
return entity_data;
}
+// Checks whether the virtual card metadata for cards is updated, if so, logs
+// accordingly.
+void LogVirtualCardMetadataChanges(
+ const std::vector<std::unique_ptr<CreditCard>>& old_data,
+ const std::vector<CreditCard>& new_data) {
+ for (CreditCard new_card : new_data) {
+ if (new_card.virtual_card_enrollment_state() ==
+ CreditCard::VirtualCardEnrollmentState::ENROLLED) {
+ // Find the old card with same server id.
+ auto old_data_iterator = std::find_if(
+ old_data.begin(), old_data.end(),
+ [&new_card](const std::unique_ptr<CreditCard>& old_card) {
+ return new_card.server_id() == old_card->server_id();
+ });
+ if (old_data_iterator != old_data.end()) {
+ // If the virtual card metadata has changed, log the updated sync.
+ if ((*old_data_iterator)->virtual_card_enrollment_state() !=
+ new_card.virtual_card_enrollment_state() ||
+ (*old_data_iterator)->card_art_url() != new_card.card_art_url()) {
+ AutofillMetrics::LogVirtualCardMetadataSynced(/*existing_card*/ true);
+ }
+ } else {
+ // No existing card with the same ID found; log the newly-synced card.
+ AutofillMetrics::LogVirtualCardMetadataSynced(/*existing_card*/ false);
+ }
+ }
+ }
+}
+
} // namespace
// static
@@ -180,11 +210,11 @@ AutofillWalletSyncBridge::CreateMetadataChangeList() {
GetAutofillTable(), syncer::AUTOFILL_WALLET_DATA);
}
-base::Optional<syncer::ModelError> AutofillWalletSyncBridge::MergeSyncData(
+absl::optional<syncer::ModelError> AutofillWalletSyncBridge::MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
// All metadata changes have been already written, return early for an error.
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
static_cast<syncer::SyncMetadataStoreChangeList*>(
metadata_change_list.get())
->TakeError();
@@ -198,16 +228,16 @@ base::Optional<syncer::ModelError> AutofillWalletSyncBridge::MergeSyncData(
// TODO(crbug.com/853688): Update the AutofillTable API to know about write
// errors and report them here.
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<syncer::ModelError> AutofillWalletSyncBridge::ApplySyncChanges(
+absl::optional<syncer::ModelError> AutofillWalletSyncBridge::ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
// This bridge does not support incremental updates, so whenever this is
// called, the change list should be empty.
DCHECK(entity_data.empty()) << "Received an unsupported incremental update.";
- return base::nullopt;
+ return absl::nullopt;
}
void AutofillWalletSyncBridge::GetData(StorageKeyList storage_keys,
@@ -356,6 +386,10 @@ bool AutofillWalletSyncBridge::SetWalletCards(
ComputeAutofillWalletDiff(existing_cards, wallet_cards);
if (!diff.IsEmpty()) {
+ // Check if there is any update on cards' virtual card metadata. If so log
+ // it.
+ LogVirtualCardMetadataChanges(existing_cards, wallet_cards);
+
table->SetServerCardsData(wallet_cards);
if (notify_metadata_bridge) {
for (const CreditCardChange& change : diff.changes) {
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 4f4975bf700..cb9cbe26c94 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
@@ -52,10 +52,10 @@ class AutofillWalletSyncBridge : public base::SupportsUserData::Data,
// ModelTypeSyncBridge implementation.
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
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 5a55f0240a0..99b82c3931b 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
@@ -15,6 +15,7 @@
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
@@ -228,8 +229,7 @@ class AutofillWalletSyncBridgeTest : public testing::Test {
void ResetProcessor() {
real_processor_ =
std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
- syncer::AUTOFILL_WALLET_DATA, /*dump_stack=*/base::DoNothing(),
- /*commit_only=*/false);
+ syncer::AUTOFILL_WALLET_DATA, /*dump_stack=*/base::DoNothing());
mock_processor_.DelegateCallsByDefaultTo(real_processor_.get());
}
@@ -406,8 +406,13 @@ TEST_F(AutofillWalletSyncBridgeTest,
CreditCard card1 = test::GetMaskedServerCard();
// Set the card issuer to Google.
card1.set_card_issuer(CreditCard::Issuer::GOOGLE);
+ card1.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::UNENROLLED);
+ card1.set_card_art_url(GURL("https://www.example.com/card.png"));
CreditCard card2 = test::GetMaskedServerCardAmex();
CreditCard card_with_nickname = test::GetMaskedServerCardWithNickname();
+ card2.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::ENROLLED);
table()->SetServerCreditCards({card1, card2, card_with_nickname});
PaymentsCustomerData customer_data{/*customer_id=*/kCustomerDataId};
table()->SetPaymentsCustomerData(&customer_data);
@@ -444,6 +449,14 @@ TEST_F(AutofillWalletSyncBridgeTest,
card_specifics1.masked_card().card_issuer().issuer());
EXPECT_EQ(sync_pb::CardIssuer::ISSUER_UNKNOWN,
card_specifics2.masked_card().card_issuer().issuer());
+ EXPECT_EQ(sync_pb::WalletMaskedCreditCard::UNENROLLED,
+ card_specifics1.masked_card().virtual_card_enrollment_state());
+ EXPECT_EQ(sync_pb::WalletMaskedCreditCard::ENROLLED,
+ card_specifics2.masked_card().virtual_card_enrollment_state());
+ EXPECT_EQ("https://www.example.com/card.png",
+ card_specifics1.masked_card().card_art_url());
+ EXPECT_TRUE(card_specifics2.masked_card().card_art_url().empty());
+
// Read local Wallet Data from Autofill table, and compare with expected
// wallet specifics.
EXPECT_THAT(
@@ -488,6 +501,9 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) {
AutofillProfile address1 = test::GetServerProfile();
table()->SetServerProfiles({address1});
CreditCard card1 = test::GetMaskedServerCard();
+ card1.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::UNENROLLED);
+ card1.set_card_art_url(GURL("https://www.example.com/card.png"));
table()->SetServerCreditCards({card1});
PaymentsCustomerData customer_data{/*customer_id=*/kCustomerDataId};
table()->SetPaymentsCustomerData(&customer_data);
@@ -500,6 +516,9 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_NewWalletAddressAndCard) {
AutofillWalletSpecifics profile_specifics2;
SetAutofillWalletSpecificsFromServerProfile(address2, &profile_specifics2);
CreditCard card2 = test::GetMaskedServerCardAmex();
+ card2.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::ENROLLED);
+ card2.set_card_art_url(GURL("https://www.test.com/card.png"));
AutofillWalletSpecifics card_specifics2;
SetAutofillWalletSpecificsFromServerCard(card2, &card_specifics2);
AutofillWalletSpecifics customer_data_specifics;
@@ -714,6 +733,9 @@ TEST_F(AutofillWalletSyncBridgeTest,
AutofillProfile profile = test::GetServerProfile();
table()->SetServerProfiles({profile});
CreditCard card = test::GetMaskedServerCard();
+ card.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::UNENROLLED);
+ card.set_card_art_url(GURL("https://www.example.com/card.png"));
table()->SetServerCreditCards({card});
PaymentsCustomerData customer_data{/*customer_id=*/kCustomerDataId};
table()->SetPaymentsCustomerData(&customer_data);
@@ -856,6 +878,9 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) {
card.SetNickname(u"Grocery card");
// Set the card issuer to Google.
card.set_card_issuer(CreditCard::Issuer::GOOGLE);
+ card.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::UNENROLLED);
+ card.set_card_art_url(GURL("https://www.example.com/card.png"));
AutofillWalletSpecifics card_specifics;
SetAutofillWalletSpecificsFromServerCard(card, &card_specifics);
@@ -882,6 +907,9 @@ TEST_F(AutofillWalletSyncBridgeTest, MergeSyncData_SetsAllWalletCardData) {
EXPECT_EQ(card.nickname(), cards[0]->nickname());
EXPECT_EQ(card.card_issuer(), cards[0]->card_issuer());
EXPECT_EQ(card.instrument_id(), cards[0]->instrument_id());
+ EXPECT_EQ(card.virtual_card_enrollment_state(),
+ cards[0]->virtual_card_enrollment_state());
+ EXPECT_EQ(card.card_art_url(), cards[0]->card_art_url());
// Also make sure that those types are not empty, to exercice all the code
// paths.
@@ -1006,4 +1034,71 @@ TEST_F(AutofillWalletSyncBridgeTest,
EXPECT_EQ(INT64_MAX, cards[0]->instrument_id());
}
+// Test that it logs correctly when new cards with virtual card metadata are
+// synced.
+TEST_F(AutofillWalletSyncBridgeTest, SetWalletCards_LogVirtualMetadataSynced) {
+ // Initial data:
+ // Card 1: has virtual cards.
+ CreditCard card1 = test::GetMaskedServerCard();
+ card1.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::ENROLLED);
+ card1.set_server_id("card1_server_id");
+ card1.set_card_art_url(GURL("https://www.example.com/card1.png"));
+ // Card 2: has virtual cards.
+ CreditCard card2 = test::GetMaskedServerCard();
+ card2.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::ENROLLED);
+ card2.set_server_id("card2_server_id");
+ card2.set_card_art_url(GURL("https://www.example.com/card2.png"));
+ // Card 3: has no virtual cards
+ CreditCard card3 = test::GetMaskedServerCard();
+ card3.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::UNENROLLED);
+ card3.set_server_id("card3_server_id");
+
+ table()->SetServerCreditCards({card1, card2, card3});
+
+ // Trigger sync:
+ // Card 1: Same as old card 1. No data changed; should not log.
+ AutofillWalletSpecifics card1_specifics;
+ SetAutofillWalletSpecificsFromServerCard(card1, &card1_specifics);
+ // Card 2: Updated the card art url; should log for existing card.
+ AutofillWalletSpecifics card2_specifics;
+ card2.set_card_art_url(GURL("https://www.example.com/card2-new.png"));
+ SetAutofillWalletSpecificsFromServerCard(card2, &card2_specifics);
+ // Card 3: Existed card newly-enrolled in virtual cards; should log for new
+ // card.
+ AutofillWalletSpecifics card3_specifics;
+ card3.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::ENROLLED);
+ card3.set_card_art_url(GURL("https://www.example.com/card3.png"));
+ SetAutofillWalletSpecificsFromServerCard(card3, &card3_specifics);
+ // Card 4: New card enrolled in virtual cards; should log for new card
+ AutofillWalletSpecifics card4_specifics;
+ CreditCard card4 = test::GetMaskedServerCard();
+ card4.set_virtual_card_enrollment_state(
+ CreditCard::VirtualCardEnrollmentState::ENROLLED);
+ card4.set_server_id("card4_server_id");
+ card4.set_card_art_url(GURL("https://www.example.com/card4.png"));
+ SetAutofillWalletSpecificsFromServerCard(card4, &card4_specifics);
+
+ // This bridge does not store metadata, i.e. billing_address_id. Strip it
+ // off so that the expectations below pass.
+ card1_specifics.mutable_masked_card()->set_billing_address_id(std::string());
+ card2_specifics.mutable_masked_card()->set_billing_address_id(std::string());
+ card3_specifics.mutable_masked_card()->set_billing_address_id(std::string());
+ card4_specifics.mutable_masked_card()->set_billing_address_id(std::string());
+
+ // Trigger sync.
+ base::HistogramTester histogram_tester;
+ StartSyncing(
+ {card1_specifics, card2_specifics, card3_specifics, card4_specifics});
+
+ // Verify the histogram logs.
+ histogram_tester.ExpectBucketCount("Autofill.VirtualCard.MetadataSynced",
+ /*existing_card*/ false, 1);
+ histogram_tester.ExpectBucketCount("Autofill.VirtualCard.MetadataSynced",
+ /*existing_card*/ true, 2);
+}
+
} // namespace autofill
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
index f713cf17449..d3fbed72ad5 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -570,11 +570,11 @@ AutofillWebDataBackendImpl::GetCreditCardCloudTokenData(WebDatabase* db) {
AUTOFILL_CLOUDTOKEN_RESULT, std::move(cloud_token_data));
}
-std::unique_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetCreditCardOffers(
+std::unique_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetAutofillOffers(
WebDatabase* db) {
DCHECK(owning_task_runner()->RunsTasksInCurrentSequence());
std::vector<std::unique_ptr<AutofillOfferData>> offers;
- AutofillTable::FromWebDatabase(db)->GetCreditCardOffers(&offers);
+ AutofillTable::FromWebDatabase(db)->GetAutofillOffers(&offers);
return std::make_unique<
WDResult<std::vector<std::unique_ptr<AutofillOfferData>>>>(
AUTOFILL_OFFER_DATA, std::move(offers));
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
index 58cee22454a..7d404fc71e5 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h
@@ -199,7 +199,7 @@ class AutofillWebDataBackendImpl
std::unique_ptr<WDTypedResult> GetCreditCardCloudTokenData(WebDatabase* db);
// Returns Credit Card Offers Data from the database.
- std::unique_ptr<WDTypedResult> GetCreditCardOffers(WebDatabase* db);
+ std::unique_ptr<WDTypedResult> GetAutofillOffers(WebDatabase* db);
WebDatabase::State ClearAllServerData(WebDatabase* db);
WebDatabase::State ClearAllLocalData(WebDatabase* db);
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
index fd53c37ec2a..522e871dd34 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -280,11 +280,11 @@ WebDataServiceBase::Handle AutofillWebDataService::GetCreditCardCloudTokenData(
consumer);
}
-WebDataServiceBase::Handle AutofillWebDataService::GetCreditCardOffers(
+WebDataServiceBase::Handle AutofillWebDataService::GetAutofillOffers(
WebDataServiceConsumer* consumer) {
return wdbs_->ScheduleDBTaskWithResult(
FROM_HERE,
- base::BindOnce(&AutofillWebDataBackendImpl::GetCreditCardOffers,
+ base::BindOnce(&AutofillWebDataBackendImpl::GetAutofillOffers,
autofill_backend_),
consumer);
}
diff --git a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
index d2badf987a7..d0c5eb7fb88 100644
--- a/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
+++ b/chromium/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -159,11 +159,11 @@ class AutofillWebDataService : public WebDataServiceBase {
WebDataServiceBase::Handle GetCreditCardCloudTokenData(
WebDataServiceConsumer* consumer);
- // Initiates the request for credit card offer data. The method
+ // Initiates the request for autofill offer data. The method
// OnWebDataServiceRequestDone of |consumer| gets called when the request is
// finished, with the offer data included in the argument |result|. The
// consumer owns the data.
- WebDataServiceBase::Handle GetCreditCardOffers(
+ WebDataServiceBase::Handle GetAutofillOffers(
WebDataServiceConsumer* consumer);
void ClearAllServerData();
diff --git a/chromium/components/autofill/core/common/BUILD.gn b/chromium/components/autofill/core/common/BUILD.gn
index 5f5ebd9505a..637d7e77754 100644
--- a/chromium/components/autofill/core/common/BUILD.gn
+++ b/chromium/components/autofill/core/common/BUILD.gn
@@ -10,8 +10,6 @@ static_library("common") {
"autofill_constants.h",
"autofill_data_validation.cc",
"autofill_data_validation.h",
- "autofill_features.cc",
- "autofill_features.h",
"autofill_internals/log_message.cc",
"autofill_internals/log_message.h",
"autofill_internals/logging_scope.cc",
@@ -57,6 +55,8 @@ static_library("common") {
"unique_ids.h",
]
+ public_deps = [ ":features" ]
+
deps = [
"//base",
"//base:i18n",
@@ -77,6 +77,17 @@ static_library("common") {
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
}
+component("features") {
+ output_name = "autofill_core_common_features"
+ defines = [ "IS_AUTOFILL_IMPL" ]
+ sources = [
+ "autofill_features.cc",
+ "autofill_features.h",
+ ]
+
+ deps = [ "//base" ]
+}
+
source_set("unit_tests") {
testonly = true
sources = [
diff --git a/chromium/components/autofill/core/common/autofill_features.cc b/chromium/components/autofill/core/common/autofill_features.cc
index 0ef82d887be..f9f478b47d0 100644
--- a/chromium/components/autofill/core/common/autofill_features.cc
+++ b/chromium/components/autofill/core/common/autofill_features.cc
@@ -4,21 +4,6 @@
#include "components/autofill/core/common/autofill_features.h"
-#include <string>
-
-#include "base/command_line.h"
-#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "build/chromeos_buildflags.h"
-#include "components/autofill/core/common/autofill_prefs.h"
-#include "components/autofill/core/common/autofill_switches.h"
-#include "components/prefs/pref_service.h"
-#include "ui/base/l10n/l10n_util.h"
-
namespace autofill {
namespace features {
@@ -28,6 +13,11 @@ namespace features {
const base::Feature kAutocompleteFilterForMeaningfulNames{
"AutocompleteFilterForMeaningfulNames", base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether to flatten and fill cross-iframe forms.
+// TODO(crbug.com/1187842) Remove once launched.
+const base::Feature kAutofillAcrossIframes{"AutofillAcrossIframes",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls if Autofill sends votes for the new address types.
const base::Feature kAutofillAddressEnhancementVotes{
"kAutofillAddressEnhancementVotes", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -38,6 +28,45 @@ const base::Feature kAutofillAddressEnhancementVotes{
// storing any detected address profile.
const base::Feature kAutofillAddressProfileSavePrompt{
"AutofillAddressProfileSavePrompt", base::FEATURE_DISABLED_BY_DEFAULT};
+// This parameter controls if save profile prompts are automatically blocked for
+// a given domain after N (default is 3) subsequent declines.
+const base::FeatureParam<bool> kAutofillAutoBlockSaveAddressProfilePrompt{
+ &kAutofillAddressProfileSavePrompt, "save_profile_prompt_auto_block", true};
+// The auto blocking feature is based on a strike model. This parameter defines
+// the months before such strikes expire.
+const base::FeatureParam<int>
+ kAutofillAutoBlockSaveAddressProfilePromptExpirationDays{
+ &kAutofillAddressProfileSavePrompt,
+ "save_profile_prompt_auto_block_strike_expiration_days", 180};
+// The number of strikes before the prompt gets blocked.
+const base::FeatureParam<int>
+ kAutofillAutoBlockSaveAddressProfilePromptStrikeLimit{
+ &kAutofillAddressProfileSavePrompt,
+ "save_profile_prompt_auto_block_strike_limit", 3};
+
+// Same as above but for update bubbles.
+const base::FeatureParam<bool> kAutofillAutoBlockUpdateAddressProfilePrompt{
+ &kAutofillAddressProfileSavePrompt, "update_profile_prompt_auto_block",
+ true};
+// Same as above but for update bubbles.
+const base::FeatureParam<int>
+ kAutofillAutoBlockUpdateAddressProfilePromptExpirationDays{
+ &kAutofillAddressProfileSavePrompt,
+ "update_profile_prompt_auto_block_strike_expiration_days", 180};
+// Same as above but for update bubbles.
+const base::FeatureParam<int>
+ kAutofillAutoBlockUpdateAddressProfilePromptStrikeLimit{
+ &kAutofillAddressProfileSavePrompt,
+ "update_profile_prompt_auto_block_strike_limit", 3};
+
+// TODO(crbug.com/1135188): Remove this feature flag after the explicit save
+// prompts for address profiles is complete.
+// When enabled, address profile save problem will contain a dropdown for
+// assigning a nickname to the address profile. Relevant only if the
+// AutofillAddressProfileSavePrompt feature is enabled.
+const base::Feature kAutofillAddressProfileSavePromptNicknameSupport{
+ "AutofillAddressProfileSavePromptNicknameSupport",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// By default, AutofillAgent and, if |kAutofillProbableFormSubmissionInBrowser|
// is enabled, also ContentAutofillDriver omit duplicate form submissions, even
@@ -53,10 +82,12 @@ const base::Feature kAutofillAllowDuplicateFormSubmissions{
const base::Feature kAutofillAllowNonHttpActivation{
"AutofillAllowNonHttpActivation", base::FEATURE_DISABLED_BY_DEFAULT};
-// Controls the use of GET (instead of POST) to fetch cacheable autofill query
-// responses.
-const base::Feature kAutofillCacheQueryResponses{
- "AutofillCacheQueryResponses", base::FEATURE_ENABLED_BY_DEFAULT};
+// Controls whether some members of FormData are retrieved in the renderer
+// instead of being extracted in the browser.
+// TODO(crbug/1206049): Disable and remove once the extraction code has been
+// migrated to the browser.
+const base::Feature kAutofillAugmentFormsInRenderer{
+ "AutofillAugmentFormsInRenderer", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kAutofillCreateDataForTest{
"AutofillCreateDataForTest", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -157,7 +188,7 @@ const base::Feature kAutofillEnableProfileDeduplication{
// TODO(crbug.com/1098943): Remove once launched.
const base::Feature kAutofillEnableSupportForMoreStructureInNames{
"AutofillEnableSupportForMoreStructureInNames",
- base::FEATURE_ENABLED_BY_DEFAULT};
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Controls if Autofill supports new structure in addresses.
// TODO(crbug.com/1098943): Remove once launched.
@@ -193,6 +224,13 @@ const base::Feature kAutofillExtractAllDatalists{
const base::Feature kAutofillFixFillableFieldTypes{
"AutofillFixFillableFieldTypes", base::FEATURE_DISABLED_BY_DEFAULT};
+// The autocomplete attribute may prevent Autofill import, crbug/1213301. This
+// feature addresses the issue. For now, the fix only concerns fields with the
+// signature 2281611779.
+// TODO(crbug/1213301): Remove this.
+const base::Feature kAutofillIgnoreAutocompleteForImport{
+ "AutofillIgnoreAutocompleteForImport", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Controls if a server prediction with a prediction source |OVERRIDE| is
// granted precedence over html type attributes.
// TODO(crbug.com/1170384) Remove once launched
@@ -280,13 +318,6 @@ const base::Feature kAutofillRetrieveOverallPredictionsFromCache{
"AutofillRetrieveOverallPredictionsFromCache",
base::FEATURE_DISABLED_BY_DEFAULT};
-// On Canary and Dev channels only, this feature flag instructs chrome to send
-// rich form/field metadata with queries. This will trigger the use of richer
-// field-type predictions model on the server, for testing/evaluation of those
-// models prior to a client-push.
-const base::Feature kAutofillRichMetadataQueries{
- "AutofillRichMetadataQueries", base::FEATURE_DISABLED_BY_DEFAULT};
-
// Controls whether UPI/VPA values will be saved and filled into payment forms.
const base::Feature kAutofillSaveAndFillVPA{"AutofillSaveAndFillVPA",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -349,6 +380,21 @@ const base::Feature kAutofillUseImprovedLabelDisambiguation{
const base::Feature kAutofillUseNewSectioningMethod{
"AutofillUseNewSectioningMethod", base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls an ablation study in which autofill for addresses and payment data
+// can be suppressed.
+const base::Feature kAutofillEnableAblationStudy{
+ "AutofillEnableAblationStudy", base::FEATURE_DISABLED_BY_DEFAULT};
+// The following parameters are only effective if the study is enabled.
+const base::FeatureParam<bool> kAutofillAblationStudyEnabledForAddressesParam{
+ &kAutofillEnableAblationStudy, "enabled_for_addresses", false};
+const base::FeatureParam<bool> kAutofillAblationStudyEnabledForPaymentsParam{
+ &kAutofillEnableAblationStudy, "enabled_for_payments", false};
+// The ratio of ablation_weight_per_mille / 1000 determines the chance of
+// autofill being disabled on a given combination of site * day * browser
+// session.
+const base::FeatureParam<int> kAutofillAblationStudyAblationWeightPerMilleParam{
+ &kAutofillEnableAblationStudy, "ablation_weight_per_mille", 10};
+
#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 f4f8e229560..d55725ae014 100644
--- a/chromium/components/autofill/core/common/autofill_features.h
+++ b/chromium/components/autofill/core/common/autofill_features.h
@@ -5,107 +5,195 @@
#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_FEATURES_H_
#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_FEATURES_H_
-#include <string>
-
+#include "base/component_export.h"
#include "base/feature_list.h"
#include "build/build_config.h"
-class PrefService;
-
-namespace base {
-struct Feature;
-}
-
namespace autofill {
namespace features {
// All features in alphabetical order.
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutocompleteFilterForMeaningfulNames;
+COMPONENT_EXPORT(AUTOFILL) extern const base::Feature kAutofillAcrossIframes;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillAddressEnhancementVotes;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillAddressProfileSavePrompt;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::FeatureParam<bool>
+ kAutofillAutoBlockSaveAddressProfilePrompt;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::FeatureParam<int>
+ kAutofillAutoBlockSaveAddressProfilePromptExpirationDays;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::FeatureParam<int>
+ kAutofillAutoBlockSaveAddressProfilePromptStrikeLimit;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::FeatureParam<bool>
+ kAutofillAutoBlockUpdateAddressProfilePrompt;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::FeatureParam<int>
+ kAutofillAutoBlockUpdateAddressProfilePromptExpirationDays;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::FeatureParam<int>
+ kAutofillAutoBlockUpdateAddressProfilePromptStrikeLimit;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::Feature kAutofillAddressProfileSavePromptNicknameSupport;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillAllowDuplicateFormSubmissions;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillAllowNonHttpActivation;
-extern const base::Feature kAutofillCacheQueryResponses;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::Feature kAutofillAugmentFormsInRenderer;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillCreateDataForTest;
-extern const base::Feature kAutofillDisableFilling;
+COMPONENT_EXPORT(AUTOFILL) extern const base::Feature kAutofillDisableFilling;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillDisableAddressImport;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableAccountWalletStorage;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableAugmentedPhoneCountryCode;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableDependentLocalityParsing;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableHideSuggestionsUI;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableImportWhenMultiplePhoneNumbers;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature
kAutofillEnableInfoBarAccountIndicationFooterForSingleAccountUsers;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature
kAutofillEnableInfoBarAccountIndicationFooterForSyncUsers;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature
kAutofillEnablePasswordInfoBarAccountIndicationFooter;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableSupportForApartmentNumbers;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableLabelPrecedenceForTurkishAddresses;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableProfileDeduplication;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableSupportForParsingWithSharedLabels;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableSupportForMoreStructureInNames;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableSupportForMoreStructureInAddresses;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableSupportForMergingSubsetNames;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillEnableSupportForHonorificPrefixes;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillExtractAllDatalists;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillFixFillableFieldTypes;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::Feature kAutofillIgnoreAutocompleteForImport;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillServerTypeTakesPrecedence;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillRefillWithRendererIds;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillNameSectionsWithRendererIds;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillKeyboardAccessory;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillLabelAffixRemoval;
-extern const base::Feature kAutofillPruneSuggestions;
-extern const base::Feature kAutofillMetadataUploads;
+COMPONENT_EXPORT(AUTOFILL) extern const base::Feature kAutofillPruneSuggestions;
+COMPONENT_EXPORT(AUTOFILL) extern const base::Feature kAutofillMetadataUploads;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillParsingPatternsFromRemote;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillParsingPatternsLanguageDetection;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillParsingPatternsNegativeMatching;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillParsingPatternsLanguageDependent;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillPreventMixedFormsFilling;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillProbableFormSubmissionInBrowser;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillProfileClientValidation;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillProfileImportFromUnfocusableFields;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillProfileServerValidation;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillRetrieveOverallPredictionsFromCache;
-extern const base::Feature kAutofillRichMetadataQueries;
-extern const base::Feature kAutofillSaveAndFillVPA;
+COMPONENT_EXPORT(AUTOFILL) extern const base::Feature kAutofillSaveAndFillVPA;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillSectionUponRedundantNameInfo;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillServerCommunication;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillShowTypePredictions;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillSkipComparingInferredLabels;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillStrictContextualCardNameConditions;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillTokenPrefixMatching;
-extern const base::Feature kAutofillUploadThrottling;
+COMPONENT_EXPORT(AUTOFILL) extern const base::Feature kAutofillUploadThrottling;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillUseAlternativeStateNameMap;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillUseImprovedLabelDisambiguation;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillUseNewSectioningMethod;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::Feature kAutofillEnableAblationStudy;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::FeatureParam<bool>
+ kAutofillAblationStudyEnabledForAddressesParam;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::FeatureParam<bool>
+ kAutofillAblationStudyEnabledForPaymentsParam;
+COMPONENT_EXPORT(AUTOFILL)
+extern const base::FeatureParam<int>
+ kAutofillAblationStudyAblationWeightPerMilleParam;
+
#if defined(OS_ANDROID)
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillManualFallbackAndroid;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillRefreshStyleAndroid;
#endif // OS_ANDROID
#if defined(OS_ANDROID) || defined(OS_IOS)
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillUseMobileLabelDisambiguation;
+COMPONENT_EXPORT(AUTOFILL)
extern const char kAutofillUseMobileLabelDisambiguationParameterName[];
+COMPONENT_EXPORT(AUTOFILL)
extern const char kAutofillUseMobileLabelDisambiguationParameterShowOne[];
+COMPONENT_EXPORT(AUTOFILL)
extern const char kAutofillUseMobileLabelDisambiguationParameterShowAll[];
#endif // defined(OS_ANDROID) || defined(OS_IOS)
#if defined(OS_APPLE)
// Returns true if whether the views autofill popup feature is enabled or the
// we're using the views browser.
+COMPONENT_EXPORT(AUTOFILL)
bool IsMacViewsAutofillPopupExperimentEnabled();
#endif // defined(OS_APPLE)
#if defined(OS_IOS)
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAutofillUseUniqueRendererIDsOnIOS;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature
kAutofillEnableNewAddressProfileCreationInSettingsOnIOS;
#endif // OS_IOS
#if defined(OS_ANDROID)
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kAndroidAutofillQueryServerFieldTypes;
+COMPONENT_EXPORT(AUTOFILL)
extern const base::Feature kWalletRequiresFirstSyncSetupComplete;
#endif
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 2ace25c3f08..c54f5f5104b 100644
--- a/chromium/components/autofill/core/common/autofill_internals/log_message.h
+++ b/chromium/components/autofill/core/common/autofill_internals/log_message.h
@@ -46,7 +46,12 @@ class LogBuffer;
T(ImportAddressProfileFromFormAddressRequirements, \
"Requirements for the address import: ") \
T(FormSubmissionDetected, "Form submission detected: ") \
- T(SendFillingData, "Sending data to fill to renderer: ")
+ T(SendFillingData, "Sending data to fill to renderer: ") \
+ T(CreditCardUploadEnabled, "Credit card upload is enabled.") \
+ T(CreditCardUploadDisabled, "Credit card upload is disabled. Reason: ") \
+ T(CardUploadDecisionUploadOffered, "Credit card upload was offered.") \
+ T(CardUploadDecisionUploadNotOffered, "Credit card upload was not offered.") \
+ T(SuggestionSuppressed, "Autofill suggestion(s) suppressed.")
// Log messages for chrome://autofill-internals.
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 a590127d062..7fe9cd04782 100644
--- a/chromium/components/autofill/core/common/autofill_internals/logging_scope.h
+++ b/chromium/components/autofill/core/common/autofill_internals/logging_scope.h
@@ -30,7 +30,11 @@ class LogBuffer;
/* Metrics collection. */ \
T(Metrics) \
/* Import of address profiles from form submissions. */ \
- T(AddressProfileFormImport)
+ T(AddressProfileFormImport) \
+ /* If credit card upload is either enabled or disabled. */ \
+ T(CreditCardUploadStatus) \
+ /* Whether or not card upload was offered to the user. */ \
+ T(CardUploadDecision)
// 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 6604f5614e9..68df963d163 100644
--- a/chromium/components/autofill/core/common/autofill_payments_features.cc
+++ b/chromium/components/autofill/core/common/autofill_payments_features.cc
@@ -30,8 +30,11 @@ const base::Feature kAutofillAlwaysReturnCloudTokenizedCard{
"AutofillAlwaysReturnCloudTokenizedCard",
base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kAutofillCreditCardAblationExperiment{
- "AutofillCreditCardAblationExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
+// When enabled, manual fallback will be auto-triggered on form interaction in
+// the case where autofill failed to fill a credit card form accurately.
+const base::Feature kAutofillAutoTriggerManualFallbackForCards{
+ "AutofillAutoTriggerManualFallbackForCards",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Enables the use of platform authenticators through WebAuthn to retrieve
// credit cards from Google payments.
@@ -60,6 +63,12 @@ const base::Feature kAutofillDownstreamCvcPromptUseGooglePayLogo{
const base::Feature kAutofillEnableGoogleIssuedCard{
"AutofillEnableGoogleIssuedCard", base::FEATURE_DISABLED_BY_DEFAULT};
+// When enabled, merchant bound virtual cards will be offered when users
+// interact with a payment form.
+const base::Feature kAutofillEnableMerchantBoundVirtualCards{
+ "AutofillEnableMerchantBoundVirtualCards",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// When enabled, a notification will be displayed on page navigation if the
// domain has an eligible credit card linked offer or reward.
const base::Feature kAutofillEnableOfferNotification{
@@ -88,6 +97,12 @@ const base::Feature kAutofillEnableSaveCardInfoBarAccountIndicationFooter{
"AutofillEnableSaveCardInfoBarAccountIndicationFooter",
base::FEATURE_DISABLED_BY_DEFAULT};
+// When enabled, if the user interacts with the manual fallback bottom sheet
+// on Android, it'll remain sticky until the user dismisses it.
+const base::Feature kAutofillEnableStickyManualFallbackForCards{
+ "AutofillEnableStickyManualFallbackForCards",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// When enabled, Autofill data related icons will be shown in the status
// chip in toolbar along with the avatar toolbar button.
const base::Feature kAutofillEnableToolbarStatusChip{
@@ -116,11 +131,23 @@ const base::Feature kAutofillSaveCardDismissOnNavigation{
const base::Feature kAutofillSaveCardInfobarEditSupport{
"AutofillSaveCardInfobarEditSupport", base::FEATURE_ENABLED_BY_DEFAULT};
+// When enabled, the entire PAN and the CVC details of the unmasked cached card
+// will be shown in the manual filling view.
+const base::Feature kAutofillShowUnmaskedCachedCardInManualFillingView{
+ "AutofillShowUnmaskedCachedCardInManualFillingView",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// When enabled, suggestions with offers will be shown at the top.
const base::Feature kAutofillSortSuggestionsBasedOnOfferPresence{
"AutofillSortSuggestionsBasedOnOfferPresence",
base::FEATURE_ENABLED_BY_DEFAULT};
+// When enabled, merchant bound virtual cards will be suggested only if we
+// detect all of the card number, exp date and CVC fields in the payment form.
+const base::Feature kAutofillSuggestVirtualCardsOnlyOnFullFormDetection{
+ "AutofillSuggestVirtualCardsOnlyOnFullFormDetection",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// When enabled, if the Autofill Assistant is running, credit card save (both
// local and upload) will not be offered.
const base::Feature kAutofillSuppressCreditCardSaveForAssistant{
@@ -140,6 +167,11 @@ const base::Feature kAutofillUpstream{"AutofillUpstream",
const base::Feature kAutofillUpstreamAllowAllEmailDomains{
"AutofillUpstreamAllowAllEmailDomains", base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether we should use the new header images for the save card
+// bubble.
+const base::Feature kAutofillUseNewHeaderForSaveCardBubble{
+ "AutofillUseNewHeaderForSaveCardBubble", base::FEATURE_ENABLED_BY_DEFAULT};
+
bool ShouldShowImprovedUserConsentForCreditCardSave() {
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
diff --git a/chromium/components/autofill/core/common/autofill_payments_features.h b/chromium/components/autofill/core/common/autofill_payments_features.h
index 3fcd9327e2e..b45f3dcedf8 100644
--- a/chromium/components/autofill/core/common/autofill_payments_features.h
+++ b/chromium/components/autofill/core/common/autofill_payments_features.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_PAYMENTS_FEATURES_H_
#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_PAYMENTS_FEATURES_H_
-#include <string>
-
#include "base/feature_list.h"
#include "build/build_config.h"
@@ -19,27 +17,32 @@ namespace features {
// All features in alphabetical order.
extern const base::Feature kAutofillAlwaysReturnCloudTokenizedCard;
-extern const base::Feature kAutofillCreditCardAblationExperiment;
+extern const base::Feature kAutofillAutoTriggerManualFallbackForCards;
extern const base::Feature kAutofillCreditCardAuthentication;
extern const base::Feature kAutofillCreditCardUploadFeedback;
extern const base::Feature kAutofillDownstreamCvcPromptUseGooglePayLogo;
extern const base::Feature kAutofillEnableGoogleIssuedCard;
+extern const base::Feature kAutofillEnableMerchantBoundVirtualCards;
extern const base::Feature kAutofillEnableOfferNotification;
extern const base::Feature kAutofillEnableOfferNotificationCrossTabTracking;
extern const base::Feature kAutofillEnableOffersInClankKeyboardAccessory;
extern const base::Feature kAutofillEnableOffersInDownstream;
extern const base::Feature
kAutofillEnableSaveCardInfoBarAccountIndicationFooter;
+extern const base::Feature kAutofillEnableStickyManualFallbackForCards;
extern const base::Feature kAutofillEnableToolbarStatusChip;
extern const base::Feature kAutofillEnableVirtualCard;
extern const base::Feature kAutofillFixOfferInIncognito;
extern const base::Feature kAutofillParseMerchantPromoCodeFields;
extern const base::Feature kAutofillSaveCardDismissOnNavigation;
extern const base::Feature kAutofillSaveCardInfobarEditSupport;
+extern const base::Feature kAutofillShowUnmaskedCachedCardInManualFillingView;
extern const base::Feature kAutofillSortSuggestionsBasedOnOfferPresence;
+extern const base::Feature kAutofillSuggestVirtualCardsOnlyOnFullFormDetection;
extern const base::Feature kAutofillSuppressCreditCardSaveForAssistant;
extern const base::Feature kAutofillUpstream;
extern const base::Feature kAutofillUpstreamAllowAllEmailDomains;
+extern const base::Feature kAutofillUseNewHeaderForSaveCardBubble;
// Return whether a [No thanks] button and new messaging is shown in the save
// card bubbles. This will be called only on desktop platforms.
diff --git a/chromium/components/autofill/core/common/autofill_util.cc b/chromium/components/autofill/core/common/autofill_util.cc
index 8c12f454c7c..9e48205874a 100644
--- a/chromium/components/autofill/core/common/autofill_util.cc
+++ b/chromium/components/autofill/core/common/autofill_util.cc
@@ -30,7 +30,7 @@ using mojom::SubmissionSource;
namespace {
-const char kSplitCharacters[] = " .,-_@";
+constexpr base::StringPiece16 kSplitCharacters = u" .,-_@";
template <typename Char>
struct Compare : base::CaseInsensitiveCompareASCII<Char> {
@@ -97,8 +97,6 @@ bool IsPrefixOfEmailEndingWithAtSign(const std::u16string& full_string,
size_t GetTextSelectionStart(const std::u16string& suggestion,
const std::u16string& field_contents,
bool case_sensitive) {
- const std::u16string kSplitChars = base::ASCIIToUTF16(kSplitCharacters);
-
// Loop until we find either the |field_contents| is a prefix of |suggestion|
// or character right before the match is one of the splitting characters.
for (std::u16string::const_iterator it = suggestion.begin();
@@ -108,7 +106,7 @@ size_t GetTextSelectionStart(const std::u16string& suggestion,
suggestion.end();
++it) {
if (it == suggestion.begin() ||
- kSplitChars.find(*(it - 1)) != std::string::npos) {
+ kSplitCharacters.find(it[-1]) != std::string::npos) {
// Returns the character position right after the |field_contents| within
// |suggestion| text as a caret position for text selection.
return it - suggestion.begin() + field_contents.size();
@@ -119,14 +117,6 @@ size_t GetTextSelectionStart(const std::u16string& suggestion,
return std::u16string::npos;
}
-bool IsDesktopPlatform() {
-#if defined(OS_ANDROID) || defined(OS_IOS)
- return false;
-#else
- return true;
-#endif
-}
-
bool IsCheckable(const FormFieldData::CheckStatus& check_status) {
return check_status != FormFieldData::CheckStatus::kNotCheckable;
}
diff --git a/chromium/components/autofill/core/common/autofill_util.h b/chromium/components/autofill/core/common/autofill_util.h
index ade30dd21aa..909a18edc5a 100644
--- a/chromium/components/autofill/core/common/autofill_util.h
+++ b/chromium/components/autofill/core/common/autofill_util.h
@@ -62,10 +62,6 @@ size_t GetTextSelectionStart(const std::u16string& suggestion,
const std::u16string& field_contents,
bool case_sensitive);
-// Returns true if running on a desktop platform. Any platform that is not
-// Android or iOS is considered desktop.
-bool IsDesktopPlatform();
-
bool IsCheckable(const FormFieldData::CheckStatus& check_status);
bool IsChecked(const FormFieldData::CheckStatus& check_status);
void SetCheckStatus(FormFieldData* form_field_data,
diff --git a/chromium/components/autofill/core/common/dense_set.h b/chromium/components/autofill/core/common/dense_set.h
index 3f4897d74dc..7cf444f3c59 100644
--- a/chromium/components/autofill/core/common/dense_set.h
+++ b/chromium/components/autofill/core/common/dense_set.h
@@ -296,4 +296,4 @@ class DenseSet {
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CORE_COMMON_BITSET_H_
+#endif // COMPONENTS_AUTOFILL_CORE_COMMON_DENSE_SET_H_
diff --git a/chromium/components/autofill/core/common/field_data_manager.cc b/chromium/components/autofill/core/common/field_data_manager.cc
index 32951c679c3..588964443bd 100644
--- a/chromium/components/autofill/core/common/field_data_manager.cc
+++ b/chromium/components/autofill/core/common/field_data_manager.cc
@@ -53,11 +53,11 @@ void FieldDataManager::UpdateFieldDataMap(FieldRendererId id,
FieldPropertiesMask mask) {
if (HasFieldData(id)) {
field_value_and_properties_map_.at(id).first =
- base::Optional<std::u16string>(value);
+ absl::optional<std::u16string>(value);
field_value_and_properties_map_.at(id).second |= mask;
} else {
field_value_and_properties_map_[id] =
- std::make_pair(base::Optional<std::u16string>(value), mask);
+ std::make_pair(absl::optional<std::u16string>(value), mask);
}
// Reset kUserTyped and kAutofilled flags if the value is empty.
if (value.empty()) {
@@ -72,7 +72,7 @@ void FieldDataManager::UpdateFieldDataMapWithNullValue(
if (HasFieldData(id))
field_value_and_properties_map_.at(id).second |= mask;
else
- field_value_and_properties_map_[id] = std::make_pair(base::nullopt, mask);
+ field_value_and_properties_map_[id] = std::make_pair(absl::nullopt, mask);
}
bool FieldDataManager::DidUserType(FieldRendererId id) const {
diff --git a/chromium/components/autofill/core/common/field_data_manager.h b/chromium/components/autofill/core/common/field_data_manager.h
index 4eb5c2441e6..6326d2e59f1 100644
--- a/chromium/components/autofill/core/common/field_data_manager.h
+++ b/chromium/components/autofill/core/common/field_data_manager.h
@@ -8,9 +8,9 @@
#include <map>
#include <string>
-#include "base/optional.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/unique_ids.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
@@ -20,7 +20,7 @@ class FieldDataManager : public base::RefCounted<FieldDataManager> {
public:
using FieldDataMap =
std::map<FieldRendererId,
- std::pair<base::Optional<std::u16string>, FieldPropertiesMask>>;
+ std::pair<absl::optional<std::u16string>, FieldPropertiesMask>>;
FieldDataManager();
diff --git a/chromium/components/autofill/core/common/logging/log_buffer.cc b/chromium/components/autofill/core/common/logging/log_buffer.cc
index 0020815cf30..caa66a1f6ff 100644
--- a/chromium/components/autofill/core/common/logging/log_buffer.cc
+++ b/chromium/components/autofill/core/common/logging/log_buffer.cc
@@ -238,9 +238,8 @@ LogTableRowBuffer&& operator<<(LogTableRowBuffer&& buf, Attrib&& attrib) {
namespace {
// Highlights the first |needle| in |haystack| by wrapping it in <b> tags.
-template <typename CharT>
-LogBuffer HighlightValueInternal(base::BasicStringPiece<CharT> haystack,
- base::BasicStringPiece<CharT> needle) {
+template <typename T, typename CharT = typename T::value_type>
+LogBuffer HighlightValueInternal(T haystack, T needle) {
using StringPieceT = base::BasicStringPiece<CharT>;
LogBuffer buffer;
size_t pos = haystack.find(needle);
diff --git a/chromium/components/autofill/core/common/save_password_progress_logger_unittest.cc b/chromium/components/autofill/core/common/save_password_progress_logger_unittest.cc
index 550f2e9479a..6699885aa24 100644
--- a/chromium/components/autofill/core/common/save_password_progress_logger_unittest.cc
+++ b/chromium/components/autofill/core/common/save_password_progress_logger_unittest.cc
@@ -9,7 +9,6 @@
#include <limits>
#include "base/bind.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
diff --git a/chromium/components/autofill/core/common/signatures.h b/chromium/components/autofill/core/common/signatures.h
index 0244be2573f..21257dc7dbf 100644
--- a/chromium/components/autofill/core/common/signatures.h
+++ b/chromium/components/autofill/core/common/signatures.h
@@ -8,8 +8,6 @@
#include <stddef.h>
#include <stdint.h>
-#include <string>
-
#include "base/strings/string_piece.h"
#include "base/util/type_safety/id_type.h"
diff --git a/chromium/components/autofill/ios/browser/BUILD.gn b/chromium/components/autofill/ios/browser/BUILD.gn
index 33d2a1fa30a..66b7657dd55 100644
--- a/chromium/components/autofill/ios/browser/BUILD.gn
+++ b/chromium/components/autofill/ios/browser/BUILD.gn
@@ -19,8 +19,6 @@ source_set("browser") {
"autofill_java_script_feature.mm",
"autofill_switches.cc",
"autofill_switches.h",
- "autofill_util.h",
- "autofill_util.mm",
"credit_card_util.h",
"credit_card_util.mm",
"form_suggestion.h",
@@ -28,18 +26,22 @@ source_set("browser") {
"form_suggestion_provider.h",
"form_suggestion_provider_query.h",
"form_suggestion_provider_query.mm",
- "js_suggestion_manager.h",
- "js_suggestion_manager.mm",
"personal_data_manager_observer_bridge.h",
"personal_data_manager_observer_bridge.mm",
+ "suggestion_controller_java_script_feature.h",
+ "suggestion_controller_java_script_feature.mm",
]
deps = [
":autofill_js",
+ ":suggestion_controller_js",
+ ":util",
"//base",
"//components/autofill/core/browser",
"//components/autofill/core/common",
"//components/autofill/ios/form_util",
+ "//components/autofill/ios/form_util:form_handler_feature",
+ "//components/autofill/ios/form_util:form_util_feature",
"//components/prefs:prefs",
"//components/prefs/ios",
"//components/ukm/ios:ukm_url_recorder",
@@ -57,11 +59,33 @@ source_set("browser") {
]
}
+source_set("util") {
+ configs += [ "//build/config/compiler:enable_arc" ]
+ sources = [
+ "autofill_util.h",
+ "autofill_util.mm",
+ ]
+ deps = [
+ "//base",
+ "//components/autofill/core/browser",
+ "//components/autofill/core/common",
+ "//ios/web/public",
+ "//ios/web/public/js_messaging",
+ "//ios/web/public/security",
+ "//url",
+ ]
+}
+
js_compile_bundle("autofill_js") {
closure_entry_point = "__crWeb.autofill"
sources = [ "resources/autofill_controller.js" ]
}
+js_compile_bundle("suggestion_controller_js") {
+ closure_entry_point = "__crWeb.suggestion"
+ sources = [ "resources/suggestion_controller.js" ]
+}
+
source_set("test_support") {
testonly = true
configs += [ "//build/config/compiler:enable_arc" ]
@@ -93,10 +117,12 @@ source_set("unit_tests") {
]
deps = [
":browser",
+ ":util",
"//base",
"//base/test:test_support",
"//components/autofill/core/browser:test_support",
"//components/autofill/ios/form_util",
+ "//components/autofill/ios/form_util:form_handler_feature",
"//components/leveldb_proto:leveldb_proto",
"//components/prefs",
"//ios/web/public",
diff --git a/chromium/components/autofill/ios/browser/autofill_agent.h b/chromium/components/autofill/ios/browser/autofill_agent.h
index a26190d0f81..20d7e7f608d 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent.h
+++ b/chromium/components/autofill/ios/browser/autofill_agent.h
@@ -1,8 +1,8 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_AGENT_H
-#define COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_AGENT_H
+#ifndef COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_AGENT_H_
+#define COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_AGENT_H_
#import <Foundation/Foundation.h>
@@ -17,9 +17,9 @@ class WebState;
}
// Handles autofill form suggestions. Reads forms from the page, sends them to
-// AutofillManager for metrics and to retrieve suggestions, and fills forms in
-// response to user interaction with suggestions. This is the iOS counterpart
-// to the upstream class autofill::AutofillAgent.
+// BrowserAutofillManager for metrics and to retrieve suggestions, and fills
+// forms in response to user interaction with suggestions. This is the iOS
+// counterpart to the upstream class autofill::AutofillAgent.
@interface AutofillAgent : NSObject <AutofillClientIOSBridge,
AutofillDriverIOSBridge,
FormSuggestionProvider>
@@ -34,4 +34,4 @@ class WebState;
@end
-#endif // COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_AGENT_H
+#endif // COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_AGENT_H_
diff --git a/chromium/components/autofill/ios/browser/autofill_agent.mm b/chromium/components/autofill/ios/browser/autofill_agent.mm
index 6637040ddd6..a3ba1b8fedf 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent.mm
@@ -23,8 +23,8 @@
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "components/autofill/core/browser/autofill_field.h"
-#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_metrics.h"
+#include "components/autofill/core/browser/browser_autofill_manager.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/keyboard_accessory_metrics_logger.h"
@@ -46,6 +46,7 @@
#import "components/autofill/ios/browser/form_suggestion_provider.h"
#import "components/autofill/ios/form_util/form_activity_observer_bridge.h"
#include "components/autofill/ios/form_util/form_activity_params.h"
+#import "components/autofill/ios/form_util/form_handlers_java_script_feature.h"
#include "components/autofill/ios/form_util/unique_id_data_tab_helper.h"
#import "components/prefs/ios/pref_observer_bridge.h"
#include "components/prefs/pref_change_registrar.h"
@@ -101,8 +102,8 @@ void GetFormField(autofill::FormFieldData* field,
// Hack to get suggestions from select input elements.
if (field->form_control_type == "select-one") {
- // Any value set will cause the AutofillManager to filter suggestions (only
- // show suggestions that begin the same as the current value) with the
+ // Any value set will cause the BrowserAutofillManager to filter suggestions
+ // (only show suggestions that begin the same as the current value) with the
// effect that one only suggestion would be returned; the value itself.
field->value = std::u16string();
}
@@ -146,7 +147,7 @@ void GetFormField(autofill::FormFieldData* field,
// Popup delegate for the most recent suggestions.
// The reference is weak because a weak pointer is sent to our
- // AutofillManagerDelegate.
+ // BrowserAutofillManagerDelegate.
base::WeakPtr<autofill::AutofillPopupDelegate> _popupDelegate;
// The autofill data that needs to be send when the |webState_| is shown.
@@ -165,11 +166,11 @@ void GetFormField(autofill::FormFieldData* field,
// AutofillDriverIOSWebFrame will keep a refcountable AutofillDriverIOS.
// This is a workaround crbug.com/892612. On submission,
- // AutofillDownloadManager and CreditCardSaveManager expect AutofillManager
- // and AutofillDriver to live after web frame deletion so AutofillAgent will
- // keep the latest submitted AutofillDriver alive.
+ // AutofillDownloadManager and CreditCardSaveManager expect
+ // BrowserAutofillManager and AutofillDriver to live after web frame deletion
+ // so AutofillAgent will keep the latest submitted AutofillDriver alive.
// TODO(crbug.com/892612): remove this workaround once life cycle of
- // AutofillManager is fixed.
+ // BrowserAutofillManager is fixed.
scoped_refptr<autofill::AutofillDriverIOSRefCountable>
_last_submitted_autofill_driver;
@@ -223,9 +224,9 @@ void GetFormField(autofill::FormFieldData* field,
// Returns nullptr if there is no autofill manager associated anymore, this can
// happen when |close| has been called on the |webState|. Also returns nullptr
// if -webStateDestroyed: has been called.
-- (autofill::AutofillManager*)
-autofillManagerFromWebState:(web::WebState*)webState
- webFrame:(web::WebFrame*)webFrame {
+- (autofill::BrowserAutofillManager*)
+ autofillManagerFromWebState:(web::WebState*)webState
+ webFrame:(web::WebFrame*)webFrame {
if (!webState || !_webStateObserverBridge)
return nullptr;
return autofill::AutofillDriverIOS::FromWebStateAndWebFrame(webState,
@@ -234,17 +235,19 @@ autofillManagerFromWebState:(web::WebState*)webState
}
// Notifies the autofill manager when forms are detected on a page.
-- (void)notifyAutofillManager:(autofill::AutofillManager*)autofillManager
- ofFormsSeen:(const FormDataVector&)forms {
+- (void)notifyBrowserAutofillManager:
+ (autofill::BrowserAutofillManager*)autofillManager
+ ofFormsSeen:(const FormDataVector&)forms {
DCHECK(autofillManager);
DCHECK(!forms.empty());
autofillManager->OnFormsSeen(forms);
}
// Notifies the autofill manager when forms are submitted.
-- (void)notifyAutofillManager:(autofill::AutofillManager*)autofillManager
- ofFormsSubmitted:(const FormDataVector&)forms
- userInitiated:(BOOL)userInitiated {
+- (void)notifyBrowserAutofillManager:
+ (autofill::BrowserAutofillManager*)autofillManager
+ ofFormsSubmitted:(const FormDataVector&)forms
+ userInitiated:(BOOL)userInitiated {
DCHECK(autofillManager);
// Exactly one form should be extracted.
DCHECK_EQ(1U, forms.size());
@@ -255,7 +258,7 @@ autofillManagerFromWebState:(web::WebState*)webState
}
// Invokes the form extraction script in |frame| and loads the output into the
-// format expected by the AutofillManager.
+// format expected by the BrowserAutofillManager.
// If |filtered| is NO, all forms are extracted.
// If |filtered| is YES,
// - if |formName| is non-empty, only a form of that name is extracted.
@@ -298,8 +301,8 @@ autofillManagerFromWebState:(web::WebState*)webState
#pragma mark - FormSuggestionProvider
-// Sends a request to AutofillManager to retrieve suggestions for the specified
-// form and field.
+// Sends a request to BrowserAutofillManager to retrieve suggestions for the
+// specified form and field.
- (void)queryAutofillForForm:(const autofill::FormData&)form
fieldIdentifier:(NSString*)fieldIdentifier
type:(NSString*)type
@@ -309,7 +312,7 @@ autofillManagerFromWebState:(web::WebState*)webState
completionHandler:(SuggestionsAvailableCompletion)completion {
web::WebFrame* frame =
GetWebFrameWithId(webState, SysNSStringToUTF8(frameID));
- autofill::AutofillManager* autofillManager =
+ autofill::BrowserAutofillManager* autofillManager =
[self autofillManagerFromWebState:webState webFrame:frame];
if (!autofillManager)
return;
@@ -322,7 +325,7 @@ autofillManagerFromWebState:(web::WebState*)webState
_suggestionsAvailableCompletion = [completion copy];
_typedValue = [typedValue copy];
- // Query the AutofillManager for suggestions. Results will arrive in
+ // Query the BrowserAutofillManager for suggestions. Results will arrive in
// -showAutofillPopup:popupDelegate:.
autofillManager->OnQueryFormFieldAutofill(
++_lastQueryID, form, field, gfx::RectF(),
@@ -357,7 +360,7 @@ autofillManagerFromWebState:(web::WebState*)webState
}
// Once the active form and field are extracted, send a query to the
- // AutofillManager for suggestions.
+ // BrowserAutofillManager for suggestions.
__weak AutofillAgent* weakSelf = self;
id completionHandler = ^(BOOL success, const FormDataVector& forms) {
if (success && forms.size() == 1) {
@@ -420,10 +423,23 @@ autofillManagerFromWebState:(web::WebState*)webState
_popupDelegate->DidAcceptSuggestion(SysNSStringToUTF16(suggestion.value),
suggestion.identifier, 0);
}
- } else if (suggestion.identifier ==
- autofill::POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) {
- web::WebFrame* frame =
- web::GetWebFrameWithId(_webState, SysNSStringToUTF8(frameID));
+ return;
+ }
+
+ web::WebFrame* frame =
+ web::GetWebFrameWithId(_webState, SysNSStringToUTF8(frameID));
+ if (!frame) {
+ // The frame no longer exists, so the field can not be filled.
+ if (_suggestionHandledCompletion) {
+ SuggestionHandledCompletion suggestionHandledCompletionCopy =
+ [_suggestionHandledCompletion copy];
+ _suggestionHandledCompletion = nil;
+ suggestionHandledCompletionCopy();
+ }
+ return;
+ }
+
+ if (suggestion.identifier == autofill::POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY) {
// FormSuggestion is a simple, single value that can be filled out now.
[self fillField:SysNSStringToUTF8(fieldIdentifier)
uniqueFieldID:uniqueFieldID
@@ -431,8 +447,6 @@ autofillManagerFromWebState:(web::WebState*)webState
value:SysNSStringToUTF16(suggestion.value)
inFrame:frame];
} else if (suggestion.identifier == autofill::POPUP_ITEM_ID_CLEAR_FORM) {
- web::WebFrame* frame =
- web::GetWebFrameWithId(_webState, SysNSStringToUTF8(frameID));
__weak AutofillAgent* weakSelf = self;
SuggestionHandledCompletion suggestionHandledCompletionCopy =
[_suggestionHandledCompletion copy];
@@ -450,9 +464,7 @@ autofillManagerFromWebState:(web::WebState*)webState
} else if (suggestion.identifier ==
autofill::POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS) {
- web::WebFrame* frame =
- GetWebFrameWithId(_webState, SysNSStringToUTF8(frameID));
- autofill::AutofillManager* autofillManager =
+ autofill::BrowserAutofillManager* autofillManager =
[self autofillManagerFromWebState:_webState webFrame:frame];
if (autofillManager) {
autofillManager->OnUserAcceptedCardsFromAccountOption();
@@ -507,7 +519,7 @@ autofillManagerFromWebState:(web::WebState*)webState
[self sendData:std::move(autofillData) toFrame:frame];
}
- autofill::AutofillManager* autofillManager =
+ autofill::BrowserAutofillManager* autofillManager =
[self autofillManagerFromWebState:_webState webFrame:frame];
if (autofillManager)
autofillManager->OnDidFillAutofillFormData(
@@ -716,19 +728,18 @@ autofillManagerFromWebState:(web::WebState*)webState
_typedValue = nil;
}
- std::vector<base::Value> formMutationsParameters;
+ autofill::FormHandlersJavaScriptFeature* formHandlerFeature =
+ autofill::FormHandlersJavaScriptFeature::GetInstance();
+
// Use a delay of 200ms when tracking form mutations to reduce the
// communication overhead (as mutations are likely to come in batch).
constexpr int kMutationTrackingEnabledDelayInMs = 200;
- formMutationsParameters.push_back(
- base::Value(kMutationTrackingEnabledDelayInMs));
- frame->CallJavaScriptFunction("formHandlers.trackFormMutations",
- formMutationsParameters);
+ formHandlerFeature->TrackFormMutations(frame,
+ kMutationTrackingEnabledDelayInMs);
- std::vector<base::Value> trackUserEditedFieldsParameters;
- trackUserEditedFieldsParameters.push_back(base::Value(true));
- frame->CallJavaScriptFunction("formHandlers.toggleTrackingUserEditedFields",
- trackUserEditedFieldsParameters);
+ formHandlerFeature->ToggleTrackingUserEditedFields(
+ frame,
+ /*track_user_edited_fields=*/true);
[self scanFormsInWebState:webState inFrame:frame];
}
@@ -740,11 +751,11 @@ autofillManagerFromWebState:(web::WebState*)webState
AutofillAgent* strongSelf = weakSelf;
if (!strongSelf || !success)
return;
- autofill::AutofillManager* autofillManager =
+ autofill::BrowserAutofillManager* autofillManager =
[strongSelf autofillManagerFromWebState:webState webFrame:webFrame];
if (!autofillManager || forms.empty())
return;
- [strongSelf notifyAutofillManager:autofillManager ofFormsSeen:forms];
+ [strongSelf notifyBrowserAutofillManager:autofillManager ofFormsSeen:forms];
};
// The document has now been fully loaded. Scan for forms to be extracted.
size_t min_required_fields =
@@ -764,6 +775,7 @@ autofillManagerFromWebState:(web::WebState*)webState
- (void)webState:(web::WebState*)webState
didRegisterFormActivity:(const autofill::FormActivityParams&)params
inFrame:(web::WebFrame*)frame {
+ DCHECK_EQ(_webState, webState);
if (![self isAutofillEnabled])
return;
@@ -795,24 +807,22 @@ autofillManagerFromWebState:(web::WebState*)webState
return;
}
- // Necessary so the string can be used inside the block.
- std::string fieldIdentifier = params.field_identifier;
-
+ // The completion block is executed asynchronously, thus it cannot refer
+ // directly to `params.field_identifier` (as params is passed by reference
+ // and may have been destroyed by the point the block is executed) nor to
+ // web::WebFrame* (as it can be deallocated before the block execution).
+ //
+ // Copy the `field_identifier` to a local variable that can be captured
+ // and save the frame identifier that will be used to get the WebFrame in
+ // -onFormsFetched:formsData:webFrameId:fieldIdentifier.
__weak AutofillAgent* weakSelf = self;
- id completionHandler = ^(BOOL success, const FormDataVector& forms) {
- if (!success || forms.size() != 1)
- return;
-
- DCHECK_EQ(_webState, webState);
- autofill::AutofillManager* autofillManager =
- [weakSelf autofillManagerFromWebState:webState webFrame:frame];
- if (!autofillManager)
- return;
-
- autofill::FormFieldData field;
- GetFormField(&field, forms[0], base::UTF8ToUTF16(fieldIdentifier));
- autofillManager->OnTextFieldDidChange(
- forms[0], field, gfx::RectF(), autofill::AutofillTickClock::NowTicks());
+ __block const std::string webFrameId = frame->GetFrameId();
+ __block const std::string fieldIdentifier = params.field_identifier;
+ auto completionHandler = ^(BOOL success, const FormDataVector& forms) {
+ [weakSelf onFormsFetched:success
+ formsData:forms
+ webFrameId:webFrameId
+ fieldIdentifier:fieldIdentifier];
};
// Extract the active form and field only. There is no minimum field
@@ -840,26 +850,26 @@ autofillManagerFromWebState:(web::WebState*)webState
base::SysUTF8ToNSString(formData), true, base::UTF8ToUTF16(formName),
webState->GetLastCommittedURL(), frame->GetSecurityOrigin(), &forms);
- autofill::AutofillManager* autofillManager =
+ autofill::BrowserAutofillManager* autofillManager =
[self autofillManagerFromWebState:webState webFrame:frame];
if (!autofillManager || !success || forms.empty())
return;
// AutofillDriverIOSWebFrame will keep a refcountable AutofillDriverIOS.
// This is a workaround crbug.com/892612. On submission,
- // AutofillDownloadManager and CreditCardSaveManager expect AutofillManager
- // and AutofillDriver to live after web frame deletion so AutofillAgent will
- // keep the latest submitted AutofillDriver alive.
+ // AutofillDownloadManager and CreditCardSaveManager expect
+ // BrowserAutofillManager and AutofillDriver to live after web frame deletion
+ // so AutofillAgent will keep the latest submitted AutofillDriver alive.
// TODO(crbug.com/892612): remove this workaround once life cycle of
- // AutofillManager is fixed.
+ // BrowserAutofillManager is fixed.
DCHECK(frame);
_last_submitted_autofill_driver =
autofill::AutofillDriverIOSWebFrame::FromWebFrame(frame)
->GetRetainableDriver();
DCHECK(_last_submitted_autofill_driver);
DCHECK(forms.size() <= 1) << "Only one form should be extracted.";
- [self notifyAutofillManager:autofillManager
- ofFormsSubmitted:forms
- userInitiated:hasUserGesture];
+ [self notifyBrowserAutofillManager:autofillManager
+ ofFormsSubmitted:forms
+ userInitiated:hasUserGesture];
}
#pragma mark - PrefObserverDelegate
@@ -962,4 +972,35 @@ autofillManagerFromWebState:(web::WebState*)webState
}));
}
+// Helper method used to implement the aynchronous completion block of
+// -webState:didRegisterFormActivity:inFrame:. Due to the asynchronous
+// invocation, WebState* and WebFrame* may both have been destroyed, so
+// the method needs to check for those edge cases.
+- (void)onFormsFetched:(BOOL)success
+ formsData:(const FormDataVector&)forms
+ webFrameId:(const std::string&)webFrameId
+ fieldIdentifier:(const std::string&)fieldIdentifier {
+ if (!success || forms.size() != 1)
+ return;
+
+ if (!_webState)
+ return;
+
+ DCHECK(_webState->GetWebFramesManager());
+ web::WebFrame* webFrame =
+ _webState->GetWebFramesManager()->GetFrameWithId(webFrameId);
+ if (!webFrame)
+ return;
+
+ autofill::BrowserAutofillManager* autofillManager =
+ [self autofillManagerFromWebState:_webState webFrame:webFrame];
+ if (!autofillManager)
+ return;
+
+ autofill::FormFieldData field;
+ GetFormField(&field, forms[0], base::UTF8ToUTF16(fieldIdentifier));
+ autofillManager->OnTextFieldDidChange(
+ forms[0], field, gfx::RectF(), autofill::AutofillTickClock::NowTicks());
+}
+
@end
diff --git a/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm b/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
index 6cf0608d02e..eb0a0621555 100644
--- a/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
+++ b/chromium/components/autofill/ios/browser/autofill_agent_unittests.mm
@@ -17,6 +17,7 @@
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/ios/browser/autofill_driver_ios.h"
#import "components/autofill/ios/browser/autofill_java_script_feature.h"
+#import "components/autofill/ios/form_util/form_handlers_java_script_feature.h"
#include "components/autofill/ios/form_util/unique_id_data_tab_helper.h"
#include "components/prefs/pref_service.h"
#include "ios/web/public/js_messaging/web_frame_util.h"
@@ -70,7 +71,8 @@ class AutofillAgentTests : public web::WebTest {
web::WebTest::SetUp();
OverrideJavaScriptFeatures(
- {autofill::AutofillJavaScriptFeature::GetInstance()});
+ {autofill::AutofillJavaScriptFeature::GetInstance(),
+ autofill::FormHandlersJavaScriptFeature::GetInstance()});
fake_web_state_.SetBrowserState(GetBrowserState());
fake_web_state_.SetContentIsHTML(true);
@@ -132,7 +134,7 @@ TEST_F(AutofillAgentTests, OnFormDataFilledTestWithFrameMessaging) {
std::string locale("en");
autofill::AutofillDriverIOS::PrepareForWebStateWebFrameAndDelegate(
&fake_web_state_, &client_, nil, locale,
- autofill::AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
+ autofill::BrowserAutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
autofill::FormData form;
form.url = GURL("https://myform.com");
@@ -204,7 +206,7 @@ TEST_F(AutofillAgentTests,
std::string locale("en");
autofill::AutofillDriverIOS::PrepareForWebStateWebFrameAndDelegate(
&fake_web_state_, &client_, nil, locale,
- autofill::AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
+ autofill::BrowserAutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
autofill::FormData form;
form.url = GURL("https://myform.com");
@@ -275,7 +277,7 @@ TEST_F(AutofillAgentTests,
std::string locale("en");
autofill::AutofillDriverIOS::PrepareForWebStateWebFrameAndDelegate(
&fake_web_state_, &client_, nil, locale,
- autofill::AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
+ autofill::BrowserAutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
autofill::FormData form;
form.url = GURL("https://myform.com");
@@ -506,7 +508,7 @@ TEST_F(AutofillAgentTests, FrameInitializationOrderFrames) {
std::string locale("en");
autofill::AutofillDriverIOS::PrepareForWebStateWebFrameAndDelegate(
&fake_web_state_, &client_, nil, locale,
- autofill::AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
+ autofill::BrowserAutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
// Remove the current main frame.
RemoveWebFrame(fake_main_frame_->GetFrameId());
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.h b/chromium/components/autofill/ios/browser/autofill_driver_ios.h
index 44b5e4f598c..8b3426c272f 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.h
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.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_AUTOFILL_CONTENT_BROWSER_AUTOFILL_DRIVER_IOS_H_
-#define COMPONENTS_AUTOFILL_CONTENT_BROWSER_AUTOFILL_DRIVER_IOS_H_
+#ifndef COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_DRIVER_IOS_H_
+#define COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_DRIVER_IOS_H_
#include <string>
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/autofill_driver.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
-#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
namespace web {
class WebFrame;
@@ -32,7 +32,8 @@ class AutofillDriverIOS : public AutofillDriver {
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager);
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager);
static AutofillDriverIOS* FromWebStateAndWebFrame(web::WebState* web_state,
web::WebFrame* web_frame);
@@ -57,8 +58,12 @@ class AutofillDriverIOS : public AutofillDriver {
void RendererShouldAcceptDataListSuggestion(
const FieldGlobalId& field,
const std::u16string& value) override;
+ void SendFieldsEligibleForManualFillingToRenderer(
+ const std::vector<FieldRendererId>& fields) override;
- AutofillManager* autofill_manager() { return &autofill_manager_; }
+ BrowserAutofillManager* autofill_manager() {
+ return &browser_autofill_manager_;
+ }
void RendererShouldFillFieldWithValue(const FieldGlobalId& field,
const std::u16string& value) override;
@@ -77,13 +82,13 @@ class AutofillDriverIOS : public AutofillDriver {
void set_processed(bool processed) { processed_ = processed; }
protected:
- AutofillDriverIOS(
- web::WebState* web_state,
- web::WebFrame* web_frame,
- AutofillClient* client,
- id<AutofillDriverIOSBridge> bridge,
- const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager);
+ AutofillDriverIOS(web::WebState* web_state,
+ web::WebFrame* web_frame,
+ AutofillClient* client,
+ id<AutofillDriverIOSBridge> bridge,
+ const std::string& app_locale,
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager);
private:
// The WebState with which this object is associated.
@@ -100,11 +105,11 @@ class AutofillDriverIOS : public AutofillDriver {
// been enabled and the forms have been extracted).
bool processed_ = false;
- // AutofillManager instance via which this object drives the shared Autofill
- // code.
- AutofillManager autofill_manager_;
+ // BrowserAutofillManager instance via which this object drives the shared
+ // Autofill code.
+ BrowserAutofillManager browser_autofill_manager_;
};
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CONTENT_BROWSER_AUTOFILL_DRIVER_IOS_H_
+#endif // COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_DRIVER_IOS_H_
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios.mm b/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
index f2779c88ad7..683cf1404cb 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios.mm
@@ -28,7 +28,8 @@ void AutofillDriverIOS::PrepareForWebStateWebFrameAndDelegate(
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager) {
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager) {
// By the time this method is called, no web_frame is available. This method
// only prepares the factory and the AutofillDriverIOS will be created in the
// first call to FromWebStateAndWebFrame.
@@ -51,10 +52,14 @@ AutofillDriverIOS::AutofillDriverIOS(
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager)
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager)
: web_state_(web_state),
bridge_(bridge),
- autofill_manager_(this, client, app_locale, enable_download_manager) {
+ browser_autofill_manager_(this,
+ client,
+ app_locale,
+ enable_download_manager) {
web_frame_id_ = web::GetWebFrameId(web_frame);
}
@@ -101,13 +106,14 @@ void AutofillDriverIOS::SendFormDataToRenderer(
void AutofillDriverIOS::PropagateAutofillPredictions(
const std::vector<autofill::FormStructure*>& forms) {
- autofill_manager_.client()->PropagateAutofillPredictions(nullptr, forms);
+ browser_autofill_manager_.client()->PropagateAutofillPredictions(nullptr,
+ forms);
}
void AutofillDriverIOS::HandleParsedForms(
const std::vector<const FormData*>& forms) {
const std::map<FormGlobalId, std::unique_ptr<FormStructure>>& map =
- autofill_manager_.form_structures();
+ browser_autofill_manager_.form_structures();
std::vector<FormStructure*> form_structures;
form_structures.reserve(forms.size());
for (const FormData* form : forms) {
@@ -137,6 +143,9 @@ void AutofillDriverIOS::RendererShouldAcceptDataListSuggestion(
const FieldGlobalId& field,
const std::u16string& value) {}
+void AutofillDriverIOS::SendFieldsEligibleForManualFillingToRenderer(
+ const std::vector<FieldRendererId>& fields) {}
+
void AutofillDriverIOS::RendererShouldClearFilledSection() {}
void AutofillDriverIOS::RendererShouldClearPreviewedForm() {
diff --git a/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h b/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h
index 99e6f83f7bc..ad55589f43b 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.h
@@ -31,7 +31,8 @@ class AutofillDriverIOSWebFrameFactory
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager);
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager);
~AutofillDriverIOSWebFrameFactory() override;
AutofillDriverIOSWebFrameFactory(
@@ -39,7 +40,8 @@ class AutofillDriverIOSWebFrameFactory
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager);
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager);
// Returns a AutofillDriverIOSFromWebFrame for |web_frame|, creating it if
// needed.
@@ -53,7 +55,7 @@ class AutofillDriverIOSWebFrameFactory
AutofillClient* client_ = nullptr;
id<AutofillDriverIOSBridge> bridge_ = nil;
std::string app_locale_;
- AutofillManager::AutofillDownloadManagerState enable_download_manager_;
+ BrowserAutofillManager::AutofillDownloadManagerState enable_download_manager_;
WEB_STATE_USER_DATA_KEY_DECL();
};
@@ -74,7 +76,8 @@ class AutofillDriverIOSRefCountable
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager);
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager);
private:
friend class base::RefCountedThreadSafe<AutofillDriverIOSRefCountable>;
@@ -93,22 +96,23 @@ class AutofillDriverIOSWebFrame
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager);
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager);
~AutofillDriverIOSWebFrame() override;
AutofillDriverIOS* driver() { return driver_.get(); }
scoped_refptr<AutofillDriverIOSRefCountable> GetRetainableDriver();
- AutofillDriverIOSWebFrame(
- web::WebState* web_state,
- web::WebFrame* web_frame,
- AutofillClient* client,
- id<AutofillDriverIOSBridge> bridge,
- const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager);
+ AutofillDriverIOSWebFrame(web::WebState* web_state,
+ web::WebFrame* web_frame,
+ AutofillClient* client,
+ id<AutofillDriverIOSBridge> bridge,
+ const std::string& app_locale,
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager);
scoped_refptr<AutofillDriverIOSRefCountable> driver_;
};
} // namespace autofill
-#endif // COMPONENTS_AUTOFILL_CONTENT_BROWSER_AUTOFILL_DRIVER_IOS_WEBSTATE_H_
+#endif // COMPONENTS_AUTOFILL_IOS_BROWSER_AUTOFILL_DRIVER_IOS_WEBFRAME_H_
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 5260665f970..67b30cf60dc 100644
--- a/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm
+++ b/chromium/components/autofill/ios/browser/autofill_driver_ios_webframe.mm
@@ -12,7 +12,8 @@ void AutofillDriverIOSWebFrameFactory::CreateForWebStateAndDelegate(
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager) {
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager) {
if (FromWebState(web_state))
return;
@@ -27,7 +28,8 @@ AutofillDriverIOSWebFrameFactory::AutofillDriverIOSWebFrameFactory(
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager)
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager)
: web_state_(web_state),
client_(client),
bridge_(bridge),
@@ -52,7 +54,8 @@ void AutofillDriverIOSWebFrame::CreateForWebFrameAndDelegate(
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager) {
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager) {
if (FromWebFrame(web_frame))
return;
@@ -68,7 +71,8 @@ AutofillDriverIOSRefCountable::AutofillDriverIOSRefCountable(
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager)
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager)
: AutofillDriverIOS(web_state,
web_frame,
@@ -83,7 +87,8 @@ AutofillDriverIOSWebFrame::AutofillDriverIOSWebFrame(
AutofillClient* client,
id<AutofillDriverIOSBridge> bridge,
const std::string& app_locale,
- AutofillManager::AutofillDownloadManagerState enable_download_manager)
+ BrowserAutofillManager::AutofillDownloadManagerState
+ enable_download_manager)
: driver_(base::MakeRefCounted<AutofillDriverIOSRefCountable>(
web_state,
web_frame,
diff --git a/chromium/components/autofill/ios/browser/autofill_java_script_feature.mm b/chromium/components/autofill/ios/browser/autofill_java_script_feature.mm
index 1a294375c75..df6d3711ec0 100644
--- a/chromium/components/autofill/ios/browser/autofill_java_script_feature.mm
+++ b/chromium/components/autofill/ios/browser/autofill_java_script_feature.mm
@@ -14,6 +14,7 @@
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/ios/browser/autofill_switches.h"
#import "components/autofill/ios/browser/autofill_util.h"
+#import "components/autofill/ios/form_util/form_util_java_script_feature.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
@@ -45,7 +46,7 @@ AutofillJavaScriptFeature::AutofillJavaScriptFeature()
FeatureScript::InjectionTime::kDocumentStart,
FeatureScript::TargetFrames::kAllFrames,
FeatureScript::ReinjectionBehavior::kInjectOncePerWindow)},
- {}) {}
+ {FormUtilJavaScriptFeature::GetInstance()}) {}
AutofillJavaScriptFeature::~AutofillJavaScriptFeature() = default;
diff --git a/chromium/components/autofill/ios/browser/autofill_util.h b/chromium/components/autofill/ios/browser/autofill_util.h
index c02ef2a5dcf..cb13e01a2ea 100644
--- a/chromium/components/autofill/ios/browser/autofill_util.h
+++ b/chromium/components/autofill/ios/browser/autofill_util.h
@@ -31,7 +31,7 @@ bool IsContextSecureForWebState(web::WebState* web_state);
std::unique_ptr<base::Value> ParseJson(NSString* json_string);
// Processes the JSON form data extracted from the page into the format expected
-// by AutofillManager and fills it in |forms_data|.
+// by BrowserAutofillManager and fills it in |forms_data|.
// |forms_data| cannot be nil.
// |filtered| and |form_name| limit the field that will be returned in
// |forms_data|.
diff --git a/chromium/components/autofill/ios/browser/autofill_util.mm b/chromium/components/autofill/ios/browser/autofill_util.mm
index 3e917132e5f..7d441df8987 100644
--- a/chromium/components/autofill/ios/browser/autofill_util.mm
+++ b/chromium/components/autofill/ios/browser/autofill_util.mm
@@ -77,7 +77,7 @@ bool IsContextSecureForWebState(web::WebState* web_state) {
}
std::unique_ptr<base::Value> ParseJson(NSString* json_string) {
- base::Optional<base::Value> json_value =
+ absl::optional<base::Value> json_value =
base::JSONReader::Read(base::SysNSStringToUTF8(json_string));
if (!json_value)
return nullptr;
@@ -101,8 +101,8 @@ bool ExtractFormsData(NSString* forms_json,
return false;
// Iterate through all the extracted forms and copy the data from JSON into
- // AutofillManager structures.
- for (const auto& form_dict : *forms_list) {
+ // BrowserAutofillManager structures.
+ for (const auto& form_dict : forms_list->GetList()) {
autofill::FormData form;
if (ExtractFormData(form_dict, filtered, form_name, main_frame_url,
frame_origin, &form))
@@ -165,7 +165,7 @@ bool ExtractFormData(const base::Value& form_value,
const base::ListValue* fields_list = nullptr;
if (!form_dictionary->GetList("fields", &fields_list))
return false;
- for (const auto& field_dict : *fields_list) {
+ for (const auto& field_dict : fields_list->GetList()) {
const base::DictionaryValue* field;
autofill::FormFieldData field_data;
if (field_dict.GetAsDictionary(&field) &&
@@ -228,7 +228,7 @@ bool ExtractFormFieldData(const base::DictionaryValue& field,
// Load option values where present.
const base::ListValue* option_values = nullptr;
if (field.GetList("option_values", &option_values)) {
- for (const auto& optionValue : *option_values) {
+ for (const auto& optionValue : option_values->GetList()) {
std::u16string value;
if (optionValue.GetAsString(&value))
field_data->option_values.push_back(std::move(value));
@@ -238,7 +238,7 @@ bool ExtractFormFieldData(const base::DictionaryValue& field,
// Load option contents where present.
const base::ListValue* option_contents = nullptr;
if (field.GetList("option_contents", &option_contents)) {
- for (const auto& option_content : *option_contents) {
+ for (const auto& option_content : option_contents->GetList()) {
std::u16string content;
if (option_content.GetAsString(&content))
field_data->option_contents.push_back(std::move(content));
@@ -304,7 +304,7 @@ bool ExtractIDs(NSString* json_string, std::vector<uint32_t>* ids) {
if (!ids_value->GetAsList(&ids_list))
return false;
- for (const auto& unique_id : *ids_list) {
+ for (const auto& unique_id : ids_list->GetList()) {
std::string id_string;
if (!unique_id.GetAsString(&id_string))
return false;
diff --git a/chromium/components/autofill/ios/browser/fake_autofill_agent.mm b/chromium/components/autofill/ios/browser/fake_autofill_agent.mm
index 23b40b006a6..cda3c27adb5 100644
--- a/chromium/components/autofill/ios/browser/fake_autofill_agent.mm
+++ b/chromium/components/autofill/ios/browser/fake_autofill_agent.mm
@@ -68,24 +68,24 @@ using autofill::FieldRendererId;
webState:(web::WebState*)webState
completionHandler:
(SuggestionsAvailableCompletion)completion {
- base::PostTask(
- FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
- NSString* key = [self keyForFormName:formQuery.formName
- fieldIdentifier:formQuery.fieldIdentifier
- frameID:formQuery.frameID];
- completion([_suggestionsByFormAndFieldName[key] count] ? YES : NO);
- }));
+ base::PostTask(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
+ NSArray<FormSuggestion*>* formSuggestions =
+ [self suggestionsForFormName:formQuery.formName
+ fieldIdentifier:formQuery.fieldIdentifier
+ frameID:formQuery.frameID];
+ completion([formSuggestions count] ? YES : NO);
+ }));
}
- (void)retrieveSuggestionsForForm:(FormSuggestionProviderQuery*)formQuery
webState:(web::WebState*)webState
completionHandler:(SuggestionsReadyCompletion)completion {
base::PostTask(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
- NSString* key =
- [self keyForFormName:formQuery.formName
- fieldIdentifier:formQuery.fieldIdentifier
- frameID:formQuery.frameID];
- completion(_suggestionsByFormAndFieldName[key], self);
+ NSArray<FormSuggestion*>* formSuggestions =
+ [self suggestionsForFormName:formQuery.formName
+ fieldIdentifier:formQuery.fieldIdentifier
+ frameID:formQuery.frameID];
+ completion(formSuggestions, self);
}));
}
@@ -97,10 +97,10 @@ using autofill::FieldRendererId;
frameID:(NSString*)frameID
completionHandler:(SuggestionHandledCompletion)completion {
base::PostTask(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
- NSString* key = [self keyForFormName:formName
- fieldIdentifier:fieldIdentifier
- frameID:frameID];
- _selectedSuggestionByFormAndFieldName[key] = suggestion;
+ [self selectSuggestion:suggestion
+ forFormName:formName
+ fieldIdentifier:fieldIdentifier
+ frameID:frameID];
completion();
}));
}
@@ -115,4 +115,23 @@ using autofill::FieldRendererId;
stringWithFormat:@"%@ %@ %@", formName, fieldIdentifier, frameID];
}
+- (NSArray<FormSuggestion*>*)suggestionsForFormName:(NSString*)formName
+ fieldIdentifier:(NSString*)fieldIdentifier
+ frameID:(NSString*)frameID {
+ NSString* key = [self keyForFormName:formName
+ fieldIdentifier:fieldIdentifier
+ frameID:frameID];
+ return _suggestionsByFormAndFieldName[key];
+}
+
+- (void)selectSuggestion:(FormSuggestion*)formSuggestion
+ forFormName:(NSString*)formName
+ fieldIdentifier:(NSString*)fieldIdentifier
+ frameID:(NSString*)frameID {
+ NSString* key = [self keyForFormName:formName
+ fieldIdentifier:fieldIdentifier
+ frameID:frameID];
+ _selectedSuggestionByFormAndFieldName[key] = formSuggestion;
+}
+
@end
diff --git a/chromium/components/autofill/ios/browser/js_suggestion_manager.h b/chromium/components/autofill/ios/browser/js_suggestion_manager.h
deleted file mode 100644
index 425e4ae9cb8..00000000000
--- a/chromium/components/autofill/ios/browser/js_suggestion_manager.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_AUTOFILL_IOS_BROWSER_JS_SUGGESTION_MANAGER_H_
-#define COMPONENTS_AUTOFILL_IOS_BROWSER_JS_SUGGESTION_MANAGER_H_
-
-#include "base/callback.h"
-#include "base/memory/weak_ptr.h"
-#import "ios/web/public/web_state_user_data.h"
-
-namespace base {
-class Value;
-} // namespace base
-
-namespace web {
-class WebFrame;
-class WebState;
-} // namespace web
-
-namespace autofill {
-
-class JsSuggestionManager : public web::WebStateUserData<JsSuggestionManager> {
- public:
- ~JsSuggestionManager() override;
-
- static JsSuggestionManager* GetOrCreateForWebState(web::WebState* web_state);
-
- // Focuses the next focusable element in tab order inside the web frame with
- // frame id |frame_ID|. No action if there is no such element.
- void SelectNextElementInFrameWithID(const std::string& frame_ID);
-
- // Focuses the next focusable element in tab order after the element specified
- // by |form_name| and |field_name| in tab order inside the web frame with
- // frame id |frame_ID|. No action if there is no such element.
- void SelectNextElementInFrameWithID(const std::string& frame_ID,
- const std::string& form_name,
- const std::string& field_name);
-
- // Focuses the previous focusable element in tab order inside the web frame
- // with frame id |frame_ID|. No action if there is no such element.
- void SelectPreviousElementInFrameWithID(const std::string& frame_ID);
-
- // Focuses the previous focusable element in tab order from the element
- // specified by |form_name| and |field_name| in tab order inside the web frame
- // with frame id |frame_ID|. No action if there is no such element.
- void SelectPreviousElementInFrameWithID(const std::string& frame_ID,
- const std::string& form_name,
- const std::string& field_name);
-
- // Checks if the frame with frame id |frame_ID| contains a next and previous
- // element. |completionHandler| is called with 2 bools, the first indicating
- // if a previous element was found, and the second indicating if a next
- // element was found. |completionHcompletion_handlerandler| cannot be nil.
- void FetchPreviousAndNextElementsPresenceInFrameWithID(
- const std::string& frame_ID,
- base::OnceCallback<void(bool, bool)> completion_handler);
-
- // Checks if the frame with frame id |frame_ID| contains a next and previous
- // element starting from the field specified by |form_name| and |field_name|.
- // |completionHandler| is called with 2 BOOLs, the first indicating if a
- // previous element was found, and the second indicating if a next element was
- // found. |completion_handler| cannot be nil.
- void FetchPreviousAndNextElementsPresenceInFrameWithID(
- const std::string& frame_ID,
- const std::string& form_name,
- const std::string& field_name,
- base::OnceCallback<void(bool, bool)> completion_handler);
-
- // Closes the keyboard and defocuses the active input element in the frame
- // with frame id |frame_ID|.
- void CloseKeyboardForFrameWithID(const std::string& frame_ID);
-
- private:
- explicit JsSuggestionManager(web::WebState* web_state);
-
- void PreviousAndNextElementsPresenceResult(
- base::OnceCallback<void(bool, bool)> completion_handler,
- const base::Value* res);
-
- web::WebFrame* GetFrameWithFrameID(const std::string& frame_ID);
-
- web::WebState* web_state_;
-
- base::WeakPtrFactory<JsSuggestionManager> weak_ptr_factory_;
-
- friend class web::WebStateUserData<JsSuggestionManager>;
-
- WEB_STATE_USER_DATA_KEY_DECL();
-};
-
-} // namespace autofill
-
-#endif // COMPONENTS_AUTOFILL_IOS_BROWSER_JS_SUGGESTION_MANAGER_H_
diff --git a/chromium/components/autofill/ios/browser/js_suggestion_manager.mm b/chromium/components/autofill/ios/browser/js_suggestion_manager.mm
deleted file mode 100644
index 2b207468e32..00000000000
--- a/chromium/components/autofill/ios/browser/js_suggestion_manager.mm
+++ /dev/null
@@ -1,146 +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.
-
-#import "components/autofill/ios/browser/js_suggestion_manager.h"
-
-#import <Foundation/Foundation.h>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/check.h"
-#include "base/format_macros.h"
-#include "base/json/string_escape.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/values.h"
-#import "components/autofill/ios/browser/autofill_util.h"
-#include "ios/web/public/js_messaging/web_frame.h"
-#include "ios/web/public/js_messaging/web_frames_manager.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace autofill {
-
-JsSuggestionManager::JsSuggestionManager(web::WebState* web_state)
- : web_state_(web_state), weak_ptr_factory_(this) {}
-
-JsSuggestionManager::~JsSuggestionManager() = default;
-
-// static
-JsSuggestionManager* JsSuggestionManager::GetOrCreateForWebState(
- web::WebState* web_state) {
- JsSuggestionManager* helper = FromWebState(web_state);
- if (!helper) {
- CreateForWebState(web_state);
- helper = FromWebState(web_state);
- DCHECK(helper);
- }
- return helper;
-}
-
-void JsSuggestionManager::SelectNextElementInFrameWithID(
- const std::string& frame_ID) {
- SelectNextElementInFrameWithID(frame_ID, "", "");
-}
-
-void JsSuggestionManager::SelectNextElementInFrameWithID(
- const std::string& frame_ID,
- const std::string& form_name,
- const std::string& field_name) {
- std::vector<base::Value> parameters;
- parameters.push_back(base::Value(form_name));
- parameters.push_back(base::Value(field_name));
- autofill::ExecuteJavaScriptFunction("suggestion.selectNextElement",
- parameters, GetFrameWithFrameID(frame_ID),
- autofill::JavaScriptResultCallback());
-}
-
-void JsSuggestionManager::SelectPreviousElementInFrameWithID(
- const std::string& frame_ID) {
- SelectPreviousElementInFrameWithID(frame_ID, "", "");
-}
-
-void JsSuggestionManager::SelectPreviousElementInFrameWithID(
- const std::string& frame_ID,
- const std::string& form_name,
- const std::string& field_name) {
- std::vector<base::Value> parameters;
- parameters.push_back(base::Value(form_name));
- parameters.push_back(base::Value(field_name));
- autofill::ExecuteJavaScriptFunction("suggestion.selectPreviousElement",
- parameters, GetFrameWithFrameID(frame_ID),
- autofill::JavaScriptResultCallback());
-}
-
-void JsSuggestionManager::FetchPreviousAndNextElementsPresenceInFrameWithID(
- const std::string& frame_ID,
- base::OnceCallback<void(bool, bool)> completion_handler) {
- FetchPreviousAndNextElementsPresenceInFrameWithID(
- frame_ID, "", "", std::move(completion_handler));
-}
-
-void JsSuggestionManager::FetchPreviousAndNextElementsPresenceInFrameWithID(
- const std::string& frame_ID,
- const std::string& form_name,
- const std::string& field_name,
- base::OnceCallback<void(bool, bool)> completion_handler) {
- DCHECK(completion_handler);
- std::vector<base::Value> parameters;
- parameters.push_back(base::Value(form_name));
- parameters.push_back(base::Value(field_name));
- autofill::ExecuteJavaScriptFunction(
- "suggestion.hasPreviousNextElements", parameters,
- GetFrameWithFrameID(frame_ID),
- base::BindOnce(
- &JsSuggestionManager::PreviousAndNextElementsPresenceResult,
- weak_ptr_factory_.GetWeakPtr(), std::move(completion_handler)));
-}
-
-void JsSuggestionManager::PreviousAndNextElementsPresenceResult(
- base::OnceCallback<void(bool, bool)> completion_handler,
- const base::Value* res) {
- NSString* result = nil;
- if (res && res->is_string()) {
- result = base::SysUTF8ToNSString(res->GetString());
- }
- // The result maybe an empty string here due to 2 reasons:
- // 1) When there is an exception running the JS
- // 2) There is a race when the page is changing due to which
- // JSSuggestionManager has not yet injected __gCrWeb.suggestion
- // object Handle this case gracefully. If a page has overridden
- // Array.toString, the string returned may not contain a ",",
- // hence this is a defensive measure to early return.
- NSArray* components = [result componentsSeparatedByString:@","];
- if (components.count != 2) {
- std::move(completion_handler).Run(false, false);
- return;
- }
-
- DCHECK([components[0] isEqualToString:@"true"] ||
- [components[0] isEqualToString:@"false"]);
- bool has_previous_element = [components[0] isEqualToString:@"true"];
- DCHECK([components[1] isEqualToString:@"true"] ||
- [components[1] isEqualToString:@"false"]);
- bool has_next_element = [components[1] isEqualToString:@"true"];
- std::move(completion_handler).Run(has_previous_element, has_next_element);
-}
-
-void JsSuggestionManager::CloseKeyboardForFrameWithID(
- const std::string& frame_ID) {
- std::vector<base::Value> parameters;
- autofill::ExecuteJavaScriptFunction("suggestion.blurActiveElement",
- parameters, GetFrameWithFrameID(frame_ID),
- autofill::JavaScriptResultCallback());
-}
-
-web::WebFrame* JsSuggestionManager::GetFrameWithFrameID(
- const std::string& frame_ID) {
- return web_state_->GetWebFramesManager()->GetFrameWithId(frame_ID);
-}
-
-WEB_STATE_USER_DATA_KEY_IMPL(JsSuggestionManager)
-
-} // namspace autofill
diff --git a/chromium/components/autofill/ios/browser/suggestion_controller_java_script_feature.h b/chromium/components/autofill/ios/browser/suggestion_controller_java_script_feature.h
new file mode 100644
index 00000000000..217e7947a22
--- /dev/null
+++ b/chromium/components/autofill/ios/browser/suggestion_controller_java_script_feature.h
@@ -0,0 +1,84 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_IOS_BROWSER_SUGGESTION_CONTROLLER_JAVA_SCRIPT_FEATURE_H_
+#define COMPONENTS_AUTOFILL_IOS_BROWSER_SUGGESTION_CONTROLLER_JAVA_SCRIPT_FEATURE_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/no_destructor.h"
+#include "ios/web/public/js_messaging/java_script_feature.h"
+
+namespace web {
+class WebFrame;
+} // namespace web
+
+namespace autofill {
+
+class SuggestionControllerJavaScriptFeature : public web::JavaScriptFeature {
+ public:
+ // This feature holds no state, so only a single static instance is ever
+ // needed.
+ static SuggestionControllerJavaScriptFeature* GetInstance();
+
+ // Focuses the next focusable element in tab order inside |frame|. No action
+ // if there is no such element.
+ void SelectNextElementInFrame(web::WebFrame* frame);
+
+ // Focuses the next focusable element in tab order after the element specified
+ // by |form_name| and |field_name| in tab order inside |frame|. No action if
+ // there is no such element.
+ void SelectNextElementInFrame(web::WebFrame* frame,
+ const std::string& form_name,
+ const std::string& field_name);
+
+ // Focuses the previous focusable element in tab order inside |frame|. No
+ // action if there is no such element.
+ void SelectPreviousElementInFrame(web::WebFrame* frame);
+
+ // Focuses the previous focusable element in tab order from the element
+ // specified by |form_name| and |field_name| in tab order inside |frame|. No
+ // action if there is no such element.
+ void SelectPreviousElementInFrame(web::WebFrame* frame,
+ const std::string& form_name,
+ const std::string& field_name);
+
+ // Checks if |frame| contains a next and previous element.
+ // |completionHandler| is called with 2 bools, the first indicating if a
+ // previous element was found, and the second indicating if a next element was
+ // found. |completion_handler| cannot be nil.
+ void FetchPreviousAndNextElementsPresenceInFrame(
+ web::WebFrame* frame,
+ base::OnceCallback<void(bool, bool)> completion_handler);
+
+ // Checks if |frame| contains a next and previous element starting from the
+ // field specified by |form_name| and |field_name|.
+ // |completionHandler| is called with 2 BOOLs, the first indicating if a
+ // previous element was found, and the second indicating if a next element was
+ // found. |completion_handler| cannot be nil.
+ void FetchPreviousAndNextElementsPresenceInFrame(
+ web::WebFrame* frame,
+ const std::string& form_name,
+ const std::string& field_name,
+ base::OnceCallback<void(bool, bool)> completion_handler);
+
+ // Closes the keyboard and defocuses the active input element in |frame|.
+ void CloseKeyboardForFrame(web::WebFrame* frame);
+
+ private:
+ friend class base::NoDestructor<SuggestionControllerJavaScriptFeature>;
+
+ SuggestionControllerJavaScriptFeature();
+ ~SuggestionControllerJavaScriptFeature() override;
+
+ SuggestionControllerJavaScriptFeature(
+ const SuggestionControllerJavaScriptFeature&) = delete;
+ SuggestionControllerJavaScriptFeature& operator=(
+ const SuggestionControllerJavaScriptFeature&) = delete;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_IOS_BROWSER_SUGGESTION_CONTROLLER_JAVA_SCRIPT_FEATURE_H_
diff --git a/chromium/components/autofill/ios/browser/suggestion_controller_java_script_feature.mm b/chromium/components/autofill/ios/browser/suggestion_controller_java_script_feature.mm
new file mode 100644
index 00000000000..eadf5e4584f
--- /dev/null
+++ b/chromium/components/autofill/ios/browser/suggestion_controller_java_script_feature.mm
@@ -0,0 +1,141 @@
+// Copyright 2021 The Chromium 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 "components/autofill/ios/browser/suggestion_controller_java_script_feature.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/bind.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/values.h"
+#import "components/autofill/ios/browser/autofill_java_script_feature.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace autofill {
+
+namespace {
+
+const char kScriptName[] = "suggestion_controller_js";
+
+// The timeout for any JavaScript call in this file.
+const int64_t kJavaScriptExecutionTimeoutInSeconds = 5;
+
+void ProcessPreviousAndNextElementsPresenceResult(
+ base::OnceCallback<void(bool, bool)> completion_handler,
+ const base::Value* res) {
+ NSString* result = nil;
+ if (res && res->is_string()) {
+ result = base::SysUTF8ToNSString(res->GetString());
+ }
+ // The result maybe an empty string here due to 2 reasons:
+ // 1) When there is an exception running the JS
+ // 2) There is a race when the page is changing due to which
+ // SuggestionControllerJavaScriptFeature has not yet injected the
+ // __gCrWeb.suggestion object.
+ // Handle this case gracefully. If a page has overridden
+ // Array.toString, the string returned may not contain a ",",
+ // hence this is a defensive measure to early return.
+ NSArray* components = [result componentsSeparatedByString:@","];
+ if (components.count != 2) {
+ std::move(completion_handler).Run(false, false);
+ return;
+ }
+
+ DCHECK([components[0] isEqualToString:@"true"] ||
+ [components[0] isEqualToString:@"false"]);
+ bool has_previous_element = [components[0] isEqualToString:@"true"];
+ DCHECK([components[1] isEqualToString:@"true"] ||
+ [components[1] isEqualToString:@"false"]);
+ bool has_next_element = [components[1] isEqualToString:@"true"];
+ std::move(completion_handler).Run(has_previous_element, has_next_element);
+}
+
+} // namespace
+
+// static
+SuggestionControllerJavaScriptFeature*
+SuggestionControllerJavaScriptFeature::GetInstance() {
+ static base::NoDestructor<SuggestionControllerJavaScriptFeature> instance;
+ return instance.get();
+}
+
+SuggestionControllerJavaScriptFeature::SuggestionControllerJavaScriptFeature()
+ : web::JavaScriptFeature(
+ // TODO(crbug.com/1175793): Move autofill code to kAnyContentWorld
+ // once all scripts are converted to JavaScriptFeatures.
+ ContentWorld::kPageContentWorld,
+ {FeatureScript::CreateWithFilename(
+ kScriptName,
+ FeatureScript::InjectionTime::kDocumentStart,
+ FeatureScript::TargetFrames::kAllFrames,
+ FeatureScript::ReinjectionBehavior::kInjectOncePerWindow)},
+ {AutofillJavaScriptFeature::GetInstance()}) {}
+
+SuggestionControllerJavaScriptFeature::
+ ~SuggestionControllerJavaScriptFeature() = default;
+
+void SuggestionControllerJavaScriptFeature::SelectNextElementInFrame(
+ web::WebFrame* frame) {
+ SelectNextElementInFrame(frame, "", "");
+}
+
+void SuggestionControllerJavaScriptFeature::SelectNextElementInFrame(
+ web::WebFrame* frame,
+ const std::string& form_name,
+ const std::string& field_name) {
+ std::vector<base::Value> parameters;
+ parameters.push_back(base::Value(form_name));
+ parameters.push_back(base::Value(field_name));
+ CallJavaScriptFunction(frame, "suggestion.selectNextElement", parameters);
+}
+
+void SuggestionControllerJavaScriptFeature::SelectPreviousElementInFrame(
+ web::WebFrame* frame) {
+ SelectPreviousElementInFrame(frame, "", "");
+}
+
+void SuggestionControllerJavaScriptFeature::SelectPreviousElementInFrame(
+ web::WebFrame* frame,
+ const std::string& form_name,
+ const std::string& field_name) {
+ std::vector<base::Value> parameters;
+ parameters.push_back(base::Value(form_name));
+ parameters.push_back(base::Value(field_name));
+ CallJavaScriptFunction(frame, "suggestion.selectPreviousElement", parameters);
+}
+
+void SuggestionControllerJavaScriptFeature::
+ FetchPreviousAndNextElementsPresenceInFrame(
+ web::WebFrame* frame,
+ base::OnceCallback<void(bool, bool)> completion_handler) {
+ FetchPreviousAndNextElementsPresenceInFrame(frame, "", "",
+ std::move(completion_handler));
+}
+
+void SuggestionControllerJavaScriptFeature::
+ FetchPreviousAndNextElementsPresenceInFrame(
+ web::WebFrame* frame,
+ const std::string& form_name,
+ const std::string& field_name,
+ base::OnceCallback<void(bool, bool)> completion_handler) {
+ DCHECK(completion_handler);
+ std::vector<base::Value> parameters;
+ parameters.push_back(base::Value(form_name));
+ parameters.push_back(base::Value(field_name));
+ CallJavaScriptFunction(
+ frame, "suggestion.hasPreviousNextElements", parameters,
+ base::BindOnce(&ProcessPreviousAndNextElementsPresenceResult,
+ std::move(completion_handler)),
+ base::TimeDelta::FromSeconds(kJavaScriptExecutionTimeoutInSeconds));
+}
+
+void SuggestionControllerJavaScriptFeature::CloseKeyboardForFrame(
+ web::WebFrame* frame) {
+ CallJavaScriptFunction(frame, "suggestion.blurActiveElement", {});
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/ios/form_util/BUILD.gn b/chromium/components/autofill/ios/form_util/BUILD.gn
index b301fe33247..979d86492b4 100644
--- a/chromium/components/autofill/ios/form_util/BUILD.gn
+++ b/chromium/components/autofill/ios/form_util/BUILD.gn
@@ -26,6 +26,51 @@ source_set("form_util") {
]
}
+source_set("form_util_feature") {
+ configs += [ "//build/config/compiler:enable_arc" ]
+ sources = [
+ "form_util_java_script_feature.h",
+ "form_util_java_script_feature.mm",
+ ]
+ deps = [
+ ":fill_js",
+ ":form_js",
+ "//base",
+ "//ios/web/public/js_messaging",
+ ]
+}
+
+source_set("form_handler_feature") {
+ configs += [ "//build/config/compiler:enable_arc" ]
+ sources = [
+ "form_handlers_java_script_feature.h",
+ "form_handlers_java_script_feature.mm",
+ ]
+ deps = [
+ ":form_handlers_js",
+ ":form_util",
+ ":form_util_feature",
+ "//base",
+ "//components/password_manager/ios:password_manager_feature",
+ "//ios/web/public/js_messaging",
+ ]
+}
+
+js_compile_bundle("fill_js") {
+ closure_entry_point = "__crWeb.fill"
+ sources = [ "resources/fill.js" ]
+}
+
+js_compile_bundle("form_js") {
+ closure_entry_point = "__crWeb.form"
+ sources = [ "resources/form.js" ]
+}
+
+js_compile_bundle("form_handlers_js") {
+ closure_entry_point = "__crWeb.formHandlers"
+ sources = [ "resources/form_handlers.js" ]
+}
+
source_set("test_support") {
testonly = true
configs += [ "//build/config/compiler:enable_arc" ]
@@ -55,10 +100,11 @@ source_set("unit_tests") {
]
deps = [
":form_util",
- ":form_util_js",
+ ":form_util_feature",
":test_support",
"//base",
"//base/test:test_support",
+ "//components/autofill/ios/form_util:form_handler_feature",
"//ios/web/public/js_messaging",
"//ios/web/public/test",
"//ios/web/public/test/fakes",
@@ -66,16 +112,3 @@ source_set("unit_tests") {
"//testing/gtest",
]
}
-
-js_compile_bundle("form_util_js") {
- visibility = [ ":unit_tests" ]
- testonly = true
-
- # Form_handlers depends on form and fill.
- closure_entry_point = "__crWeb.formHandlers"
- sources = [
- "resources/fill.js",
- "resources/form.js",
- "resources/form_handlers.js",
- ]
-}
diff --git a/chromium/components/autofill/ios/form_util/DEPS b/chromium/components/autofill/ios/form_util/DEPS
new file mode 100644
index 00000000000..ec2df8a7516
--- /dev/null
+++ b/chromium/components/autofill/ios/form_util/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+components/password_manager/ios",
+]
diff --git a/chromium/components/autofill/ios/form_util/fill_js_unittest.mm b/chromium/components/autofill/ios/form_util/fill_js_unittest.mm
index 980a5315b96..1542bd27203 100644
--- a/chromium/components/autofill/ios/form_util/fill_js_unittest.mm
+++ b/chromium/components/autofill/ios/form_util/fill_js_unittest.mm
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h"
-#import "ios/web/public/test/web_js_test.h"
+#import "components/autofill/ios/form_util/form_util_java_script_feature.h"
#import "ios/web/public/test/web_test_with_web_state.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
@@ -18,10 +18,17 @@
#endif
namespace {
-class FillJsTest : public web::WebJsTest<web::WebTestWithWebState> {
+
+class FillJsTest : public web::WebTestWithWebState {
public:
- FillJsTest()
- : web::WebJsTest<web::WebTestWithWebState>(@[ @"form_util_js" ]) {}
+ FillJsTest() : web::WebTestWithWebState() {}
+
+ void SetUp() override {
+ web::WebTestWithWebState::SetUp();
+
+ OverrideJavaScriptFeatures(
+ {autofill::FormUtilJavaScriptFeature::GetInstance()});
+ }
};
} // namespace
@@ -57,7 +64,7 @@ TEST_F(FillJsTest, GetCanonicalActionForForm) {
"</body></html>",
html_action];
- LoadHtmlAndInject(html);
+ LoadHtml(html);
id result = ExecuteJavaScript(
@"__gCrWeb.fill.getCanonicalActionForForm(document.body.children[0])");
NSString* base_url = base::SysUTF8ToNSString(BaseUrl());
@@ -72,7 +79,7 @@ TEST_F(FillJsTest, GetCanonicalActionForForm) {
// Tests the extraction of the aria-label attribute.
TEST_F(FillJsTest, GetAriaLabel) {
- LoadHtmlAndInject(@"<input id='input' type='text' aria-label='the label'/>");
+ LoadHtml(@"<input id='input' type='text' aria-label='the label'/>");
id result = ExecuteJavaScript(
@"__gCrWeb.fill.getAriaLabel(document.getElementById('input'));");
@@ -82,14 +89,13 @@ TEST_F(FillJsTest, GetAriaLabel) {
// Tests that aria-labelledby works. Simple case: only one id referenced.
TEST_F(FillJsTest, GetAriaLabelledBySingle) {
- LoadHtmlAndInject(
- @"<html><body>"
- "<div id='billing'>Billing</div>"
- "<div>"
- " <div id='name'>Name</div>"
- " <input id='input' type='text' aria-labelledby='name'/>"
- "</div>"
- "</body></html>");
+ LoadHtml(@"<html><body>"
+ "<div id='billing'>Billing</div>"
+ "<div>"
+ " <div id='name'>Name</div>"
+ " <input id='input' type='text' aria-labelledby='name'/>"
+ "</div>"
+ "</body></html>");
id result = ExecuteJavaScript(
@"__gCrWeb.fill.getAriaLabel(document.getElementById('input'));");
@@ -99,14 +105,13 @@ TEST_F(FillJsTest, GetAriaLabelledBySingle) {
// Tests that aria-labelledby works: Complex case: multiple ids referenced.
TEST_F(FillJsTest, GetAriaLabelledByMulti) {
- LoadHtmlAndInject(
- @"<html><body>"
- "<div id='billing'>Billing</div>"
- "<div>"
- " <div id='name'>Name</div>"
- " <input id='input' type='text' aria-labelledby='billing name'/>"
- "</div>"
- "</body></html>");
+ LoadHtml(@"<html><body>"
+ "<div id='billing'>Billing</div>"
+ "<div>"
+ " <div id='name'>Name</div>"
+ " <input id='input' type='text' aria-labelledby='billing name'/>"
+ "</div>"
+ "</body></html>");
id result = ExecuteJavaScript(
@"__gCrWeb.fill.getAriaLabel(document.getElementById('input'));");
@@ -116,15 +121,14 @@ TEST_F(FillJsTest, GetAriaLabelledByMulti) {
// Tests that aria-labelledby takes precedence over aria-label
TEST_F(FillJsTest, GetAriaLabelledByTakesPrecedence) {
- LoadHtmlAndInject(
- @"<html><body>"
- "<div id='billing'>Billing</div>"
- "<div>"
- " <div id='name'>Name</div>"
- " <input id='input' type='text' aria-label='ignored' "
- " aria-labelledby='name'/>"
- "</div>"
- "</body></html>");
+ LoadHtml(@"<html><body>"
+ "<div id='billing'>Billing</div>"
+ "<div>"
+ " <div id='name'>Name</div>"
+ " <input id='input' type='text' aria-label='ignored' "
+ " aria-labelledby='name'/>"
+ "</div>"
+ "</body></html>");
id result = ExecuteJavaScript(
@"__gCrWeb.fill.getAriaLabel(document.getElementById('input'));");
@@ -135,14 +139,13 @@ TEST_F(FillJsTest, GetAriaLabelledByTakesPrecedence) {
// Tests that an invalid aria-labelledby reference gets ignored (as opposed to
// crashing, for example).
TEST_F(FillJsTest, GetAriaLabelledByInvalid) {
- LoadHtmlAndInject(
- @"<html><body>"
- "<div id='billing'>Billing</div>"
- "<div>"
- " <div id='name'>Name</div>"
- " <input id='input' type='text' aria-labelledby='div1 div2'/>"
- "</div>"
- "</body></html>");
+ LoadHtml(@"<html><body>"
+ "<div id='billing'>Billing</div>"
+ "<div>"
+ " <div id='name'>Name</div>"
+ " <input id='input' type='text' aria-labelledby='div1 div2'/>"
+ "</div>"
+ "</body></html>");
id result = ExecuteJavaScript(
@"__gCrWeb.fill.getAriaLabel(document.getElementById('input'));");
@@ -152,15 +155,14 @@ TEST_F(FillJsTest, GetAriaLabelledByInvalid) {
// Tests that invalid aria-labelledby references fall back to aria-label.
TEST_F(FillJsTest, GetAriaLabelledByFallback) {
- LoadHtmlAndInject(
- @"<html><body>"
- "<div id='billing'>Billing</div>"
- "<div>"
- " <div id='name'>Name</div>"
- " <input id='input' type='text' aria-label='valid' "
- " aria-labelledby='div1 div2'/>"
- "</div>"
- "</body></html>");
+ LoadHtml(@"<html><body>"
+ "<div id='billing'>Billing</div>"
+ "<div>"
+ " <div id='name'>Name</div>"
+ " <input id='input' type='text' aria-label='valid' "
+ " aria-labelledby='div1 div2'/>"
+ "</div>"
+ "</body></html>");
id result = ExecuteJavaScript(
@"__gCrWeb.fill.getAriaLabel(document.getElementById('input'));");
@@ -170,11 +172,10 @@ TEST_F(FillJsTest, GetAriaLabelledByFallback) {
// Tests that aria-describedby works: Simple case: a single id referenced.
TEST_F(FillJsTest, GetAriaDescriptionSingle) {
- LoadHtmlAndInject(
- @"<html><body>"
- "<input id='input' type='text' aria-describedby='div1'/>"
- "<div id='div1'>aria description</div>"
- "</body></html>");
+ LoadHtml(@"<html><body>"
+ "<input id='input' type='text' aria-describedby='div1'/>"
+ "<div id='div1'>aria description</div>"
+ "</body></html>");
id result = ExecuteJavaScript(
@"__gCrWeb.fill.getAriaDescription(document.getElementById('input'));");
@@ -184,12 +185,11 @@ TEST_F(FillJsTest, GetAriaDescriptionSingle) {
// Tests that aria-describedby works: Complex case: multiple ids referenced.
TEST_F(FillJsTest, GetAriaDescriptionMulti) {
- LoadHtmlAndInject(
- @"<html><body>"
- "<input id='input' type='text' aria-describedby='div1 div2'/>"
- "<div id='div2'>description</div>"
- "<div id='div1'>aria</div>"
- "</body></html>");
+ LoadHtml(@"<html><body>"
+ "<input id='input' type='text' aria-describedby='div1 div2'/>"
+ "<div id='div2'>description</div>"
+ "<div id='div1'>aria</div>"
+ "</body></html>");
id result = ExecuteJavaScript(
@"__gCrWeb.fill.getAriaDescription(document.getElementById('input'));");
@@ -199,10 +199,9 @@ TEST_F(FillJsTest, GetAriaDescriptionMulti) {
// Tests that invalid aria-describedby returns the empty string.
TEST_F(FillJsTest, GetAriaDescriptionInvalid) {
- LoadHtmlAndInject(
- @"<html><body>"
- "<input id='input' type='text' aria-describedby='invalid'/>"
- "</body></html>");
+ LoadHtml(@"<html><body>"
+ "<input id='input' type='text' aria-describedby='invalid'/>"
+ "</body></html>");
id result = ExecuteJavaScript(
@"__gCrWeb.fill.getAriaDescription(document.getElementById('input'));");
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 72461af86fd..8ec5596ab1c 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
@@ -7,25 +7,32 @@
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/values.h"
#include "ios/web/public/web_state_observer.h"
#import "ios/web/public/web_state_user_data.h"
+namespace web {
+class ScriptMessage;
+class WebState;
+} // namespace web
+
namespace autofill {
class FormActivityObserver;
-// Observes user activity on web page forms and forwards form activity event to
-// FormActivityObserver.
+// Processes user activity messages for web page forms and forwards the form
+// activity event to FormActivityObserver.
class FormActivityTabHelper
- : public web::WebStateObserver,
- public web::WebStateUserData<FormActivityTabHelper> {
+ : public web::WebStateUserData<FormActivityTabHelper> {
public:
~FormActivityTabHelper() override;
static FormActivityTabHelper* GetOrCreateForWebState(
web::WebState* web_state);
+ // Handler for "form.*" JavaScript command. Dispatch to more specific handler.
+ void OnFormMessageReceived(web::WebState* web_state,
+ const web::ScriptMessage& message);
+
// Observer registration methods.
virtual void AddObserver(FormActivityObserver* observer);
virtual void RemoveObserver(FormActivityObserver* observer);
@@ -40,37 +47,17 @@ class FormActivityTabHelper
explicit FormActivityTabHelper(web::WebState* web_state);
- // WebStateObserver implementation.
- void WebStateDestroyed(web::WebState* web_state) override;
-
- // Handler for "form.activity" JavaScript command.
- bool HandleFormActivity(const base::DictionaryValue& message,
- bool has_user_gesture,
- bool form_in_main_frame,
- web::WebFrame* sender_frame);
+ // Handler for form activity.
+ void HandleFormActivity(web::WebState* web_state,
+ const web::ScriptMessage& message);
- // Handler for "form.submit" JavaScript command.
- bool FormSubmissionHandler(const base::DictionaryValue& message,
- bool has_user_gesture,
- bool form_in_main_frame,
- web::WebFrame* sender_frame);
-
- // Handler for "form.*" JavaScript command. Dispatch to more specific handler.
- void OnFormCommand(const base::DictionaryValue& message,
- const GURL& url,
- bool user_is_interacting,
- web::WebFrame* sender_frame);
-
- // The WebState this instance is observing. Will be null after
- // WebStateDestroyed has been called.
- web::WebState* web_state_ = nullptr;
+ // Handler for the submission of a form.
+ void FormSubmissionHandler(web::WebState* web_state,
+ const web::ScriptMessage& message);
// The observers.
base::ObserverList<FormActivityObserver>::Unchecked observers_;
- // Subscription for JS message.
- base::CallbackListSubscription subscription_;
-
WEB_STATE_USER_DATA_KEY_DECL();
DISALLOW_COPY_AND_ASSIGN(FormActivityTabHelper);
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 7ed8e8fd2fa..2a36c2646ba 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
@@ -12,7 +12,9 @@
#include "base/values.h"
#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/script_message.h"
#include "ios/web/public/js_messaging/web_frame.h"
+#include "ios/web/public/js_messaging/web_frame_util.h"
#import "ios/web/public/ui/crw_web_view_proxy.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -24,12 +26,6 @@ using base::StringToUint;
namespace autofill {
-namespace {
-// Prefix for the form activity event commands. Must be kept in sync with
-// form.js.
-const char kCommandPrefix[] = "form";
-}
-
// static
FormActivityTabHelper* FormActivityTabHelper::GetOrCreateForWebState(
web::WebState* web_state) {
@@ -42,21 +38,8 @@ FormActivityTabHelper* FormActivityTabHelper::GetOrCreateForWebState(
return helper;
}
-FormActivityTabHelper::FormActivityTabHelper(web::WebState* web_state)
- : web_state_(web_state) {
- web_state_->AddObserver(this);
- subscription_ = web_state_->AddScriptCommandCallback(
- base::BindRepeating(&FormActivityTabHelper::OnFormCommand,
- base::Unretained(this)),
- kCommandPrefix);
-}
-
-FormActivityTabHelper::~FormActivityTabHelper() {
- if (web_state_) {
- web_state_->RemoveObserver(this);
- web_state_ = nullptr;
- }
-}
+FormActivityTabHelper::FormActivityTabHelper(web::WebState* web_state) {}
+FormActivityTabHelper::~FormActivityTabHelper() = default;
void FormActivityTabHelper::AddObserver(FormActivityObserver* observer) {
observers_.AddObserver(observer);
@@ -66,84 +49,108 @@ void FormActivityTabHelper::RemoveObserver(FormActivityObserver* observer) {
observers_.RemoveObserver(observer);
}
-void FormActivityTabHelper::OnFormCommand(const base::DictionaryValue& message,
- const GURL& url,
- bool user_is_interacting,
- web::WebFrame* sender_frame) {
+void FormActivityTabHelper::OnFormMessageReceived(
+ web::WebState* web_state,
+ const web::ScriptMessage& message) {
+ base::DictionaryValue* message_body;
+ if (!message.body() || !message.body()->is_dict() ||
+ !message.body()->GetAsDictionary(&message_body)) {
+ // Ignore invalid message.
+ return;
+ }
+
std::string command;
- if (!message.GetString("command", &command)) {
+ if (!message_body->GetString("command", &command)) {
DLOG(WARNING) << "JS message parameter not found: command";
} else if (command == "form.submit") {
- FormSubmissionHandler(message, user_is_interacting,
- sender_frame->IsMainFrame(), sender_frame);
+ FormSubmissionHandler(web_state, message);
} else if (command == "form.activity") {
- HandleFormActivity(message, user_is_interacting,
- sender_frame->IsMainFrame(), sender_frame);
+ HandleFormActivity(web_state, message);
}
}
-bool FormActivityTabHelper::HandleFormActivity(
- const base::DictionaryValue& message,
- bool has_user_gesture,
- bool form_in_main_frame,
- web::WebFrame* sender_frame) {
+void FormActivityTabHelper::HandleFormActivity(
+ web::WebState* web_state,
+ const web::ScriptMessage& message) {
+ base::DictionaryValue* message_body;
+ if (!message.body() || !message.body()->is_dict() ||
+ !message.body()->GetAsDictionary(&message_body)) {
+ // Ignore invalid message.
+ return;
+ }
+
+ std::string frame_id;
+ if (!message_body->GetString("frameID", &frame_id)) {
+ return;
+ }
+
+ web::WebFrame* sender_frame = GetWebFrameWithId(web_state, frame_id);
+ if (!sender_frame) {
+ return;
+ }
+
FormActivityParams params;
+ params.frame_id = frame_id;
std::string unique_form_id;
std::string unique_field_id;
- if (!message.GetString("formName", &params.form_name) ||
- !message.GetString("uniqueFormID", &unique_form_id) ||
- !message.GetString("fieldIdentifier", &params.field_identifier) ||
- !message.GetString("uniqueFieldID", &unique_field_id) ||
- !message.GetString("fieldType", &params.field_type) ||
- !message.GetString("type", &params.type) ||
- !message.GetString("value", &params.value) ||
- !message.GetBoolean("hasUserGesture", &params.has_user_gesture)) {
+ if (!message_body->GetString("formName", &params.form_name) ||
+ !message_body->GetString("uniqueFormID", &unique_form_id) ||
+ !message_body->GetString("fieldIdentifier", &params.field_identifier) ||
+ !message_body->GetString("uniqueFieldID", &unique_field_id) ||
+ !message_body->GetString("fieldType", &params.field_type) ||
+ !message_body->GetString("type", &params.type) ||
+ !message_body->GetString("value", &params.value) ||
+ !message_body->GetBoolean("hasUserGesture", &params.has_user_gesture)) {
params.input_missing = true;
}
StringToUint(unique_form_id, &params.unique_form_id.value());
StringToUint(unique_field_id, &params.unique_field_id.value());
- params.is_main_frame = form_in_main_frame;
- if (!sender_frame) {
- return false;
- }
- params.frame_id = sender_frame->GetFrameId();
+ params.is_main_frame = message.is_main_frame();
+
for (auto& observer : observers_)
- observer.FormActivityRegistered(web_state_, sender_frame, params);
- return true;
+ observer.FormActivityRegistered(web_state, sender_frame, params);
}
-bool FormActivityTabHelper::FormSubmissionHandler(
- const base::DictionaryValue& message,
- bool has_user_gesture,
- bool form_in_main_frame,
- web::WebFrame* sender_frame) {
+void FormActivityTabHelper::FormSubmissionHandler(
+ web::WebState* web_state,
+ const web::ScriptMessage& message) {
+ base::DictionaryValue* message_body;
+ if (!message.body() || !message.body()->is_dict() ||
+ !message.body()->GetAsDictionary(&message_body)) {
+ // Ignore invalid message.
+ return;
+ }
+
+ std::string frame_id;
+ if (!message_body->GetString("frameID", &frame_id)) {
+ return;
+ }
+
+ web::WebFrame* sender_frame = GetWebFrameWithId(web_state, frame_id);
+ if (!sender_frame) {
+ return;
+ }
+
std::string href;
- if (!message.GetString("href", &href)) {
+ if (!message_body->GetString("href", &href)) {
DLOG(WARNING) << "JS message parameter not found: href";
- return false;
+ return;
}
std::string form_name;
- message.GetString("formName", &form_name);
+ message_body->GetString("formName", &form_name);
std::string form_data;
- message.GetString("formData", &form_data);
+ message_body->GetString("formData", &form_data);
// We decide the form is user-submitted if the user has interacted with
// the main page (using logic from the popup blocker), or if the keyboard
// is visible.
- BOOL submitted_by_user =
- has_user_gesture || [web_state_->GetWebViewProxy() keyboardAccessory];
+ BOOL submitted_by_user = message.is_user_interacting() ||
+ [web_state->GetWebViewProxy() keyboardAccessory];
for (auto& observer : observers_)
- observer.DocumentSubmitted(web_state_, sender_frame, form_name, form_data,
- submitted_by_user, form_in_main_frame);
- return true;
-}
-
-void FormActivityTabHelper::WebStateDestroyed(web::WebState* web_state) {
- DCHECK_EQ(web_state_, web_state);
- web_state_->RemoveObserver(this);
- web_state_ = nullptr;
+ observer.DocumentSubmitted(web_state, sender_frame, form_name, form_data,
+ submitted_by_user, message.is_main_frame());
}
WEB_STATE_USER_DATA_KEY_IMPL(FormActivityTabHelper)
diff --git a/chromium/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm b/chromium/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm
index 0a58c7f33ff..1ee7a8145ec 100644
--- a/chromium/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm
+++ b/chromium/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm
@@ -6,36 +6,36 @@
#import "base/test/ios/wait_util.h"
#import "components/autofill/ios/form_util/form_activity_observer.h"
+#import "components/autofill/ios/form_util/form_handlers_java_script_feature.h"
+#import "components/autofill/ios/form_util/form_util_java_script_feature.h"
#import "components/autofill/ios/form_util/test_form_activity_observer.h"
#include "ios/web/public/js_messaging/web_frame.h"
#import "ios/web/public/js_messaging/web_frames_manager.h"
#import "ios/web/public/test/fakes/fake_web_client.h"
#import "ios/web/public/test/fakes/fake_web_state_observer_util.h"
#import "ios/web/public/test/js_test_util.h"
-#import "ios/web/public/test/web_js_test.h"
#import "ios/web/public/test/web_test_with_web_state.h"
#include "testing/platform_test.h"
+using base::test::ios::kWaitForJSCompletionTimeout;
+using base::test::ios::WaitUntilConditionOrTimeout;
using web::WebFrame;
-class FormTestClient : public web::FakeWebClient {
- public:
- NSString* GetDocumentStartScriptForAllFrames(
- web::BrowserState* browser_state) const override {
- return web::test::GetPageScript(@"form_util_js");
- }
-};
-
// Tests fixture for autofill::FormActivityTabHelper class.
-class FormActivityTabHelperTest
- : public web::WebJsTest<web::WebTestWithWebState> {
+class FormActivityTabHelperTest : public web::WebTestWithWebState {
public:
FormActivityTabHelperTest()
- : web::WebJsTest<web::WebTestWithWebState>(
- std::make_unique<FormTestClient>()) {}
+ : web::WebTestWithWebState(std::make_unique<web::FakeWebClient>()) {
+ web::FakeWebClient* web_client =
+ static_cast<web::FakeWebClient*>(GetWebClient());
+ web_client->SetJavaScriptFeatures(
+ {autofill::FormUtilJavaScriptFeature::GetInstance(),
+ autofill::FormHandlersJavaScriptFeature::GetInstance()});
+ }
void SetUp() override {
- web::WebJsTest<web::WebTestWithWebState>::SetUp();
+ web::WebTestWithWebState::SetUp();
+
autofill::FormActivityTabHelper* tab_helper =
autofill::FormActivityTabHelper::GetOrCreateForWebState(web_state());
observer_ =
@@ -47,24 +47,44 @@ class FormActivityTabHelperTest
autofill::FormActivityTabHelper* tab_helper =
autofill::FormActivityTabHelper::GetOrCreateForWebState(web_state());
tab_helper->RemoveObserver(observer_.get());
- web::WebJsTest<web::WebTestWithWebState>::TearDown();
+ web::WebTestWithWebState::TearDown();
}
protected:
+ WebFrame* WaitForMainFrame() {
+ __block WebFrame* main_frame = nullptr;
+ EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+ main_frame = web_state()->GetWebFramesManager()->GetMainWebFrame();
+ return main_frame != nullptr;
+ }));
+ return main_frame;
+ }
+
std::unique_ptr<autofill::TestFormActivityObserver> observer_;
};
// Tests that observer is called on form submission using submit control.
TEST_F(FormActivityTabHelperTest, TestObserverDocumentSubmitted) {
- LoadHtmlAndInject(
- @"<form name='form-name'>"
- "<input type='submit' id='submit'/>"
- "</form>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);");
+ LoadHtml(@"<form name='form-name'>"
+ "<input type='submit' id='submit'/>"
+ "</form>");
+
+ WebFrame* main_frame = WaitForMainFrame();
+ ASSERT_TRUE(main_frame);
+
+ uint32_t next_available_id = 1;
+ autofill::FormUtilJavaScriptFeature::GetInstance()
+ ->SetUpForUniqueIDsWithInitialState(main_frame, next_available_id);
+
+ // Wait for |SetUpForUniqueIDsWithInitialState| to complete.
+ EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+ return [ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]") intValue] ==
+ int{next_available_id};
+ }));
+
ASSERT_FALSE(observer_->submit_document_info());
const std::string kTestFormName("form-name");
- WebFrame* main_frame = web_state()->GetWebFramesManager()->GetMainWebFrame();
std::string mainFrameID = main_frame->GetFrameId();
const std::string kTestFormData =
std::string("[{\"name\":\"form-name\",\"origin\":\"https://chromium.test/"
@@ -73,36 +93,39 @@ TEST_F(FormActivityTabHelperTest, TestObserverDocumentSubmitted) {
"\"unique_renderer_id\":\"1\",\"frame_id\":\"") +
mainFrameID + std::string("\"}]");
- bool has_user_gesture = false;
- bool form_in_main_frame = true;
- EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
- base::test::ios::kWaitForJSCompletionTimeout, ^bool {
- return web_state()->GetWebFramesManager()->GetMainWebFrame() != nullptr;
- }));
-
ExecuteJavaScript(@"document.getElementById('submit').click();");
ASSERT_TRUE(observer_->submit_document_info());
EXPECT_EQ(web_state(), observer_->submit_document_info()->web_state);
EXPECT_EQ(main_frame, observer_->submit_document_info()->sender_frame);
EXPECT_EQ(kTestFormName, observer_->submit_document_info()->form_name);
EXPECT_EQ(kTestFormData, observer_->submit_document_info()->form_data);
- EXPECT_EQ(has_user_gesture,
- observer_->submit_document_info()->has_user_gesture);
- EXPECT_EQ(form_in_main_frame,
- observer_->submit_document_info()->form_in_main_frame);
+
+ EXPECT_FALSE(observer_->submit_document_info()->has_user_gesture);
+ EXPECT_TRUE(observer_->submit_document_info()->form_in_main_frame);
}
// Tests that observer is called on form submission using submit() method.
TEST_F(FormActivityTabHelperTest, TestFormSubmittedHook) {
- LoadHtmlAndInject(
- @"<form name='form-name' id='form'>"
- "<input type='submit'/>"
- "</form>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);");
+ LoadHtml(@"<form name='form-name' id='form'>"
+ "<input type='submit'/>"
+ "</form>");
+
+ WebFrame* main_frame = WaitForMainFrame();
+ ASSERT_TRUE(main_frame);
+
+ uint32_t next_available_id = 1;
+ autofill::FormUtilJavaScriptFeature::GetInstance()
+ ->SetUpForUniqueIDsWithInitialState(main_frame, next_available_id);
+
+ // Wait for |SetUpForUniqueIDsWithInitialState| to complete.
+ EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+ return [ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]") intValue] ==
+ int{next_available_id};
+ }));
+
ASSERT_FALSE(observer_->submit_document_info());
const std::string kTestFormName("form-name");
- WebFrame* main_frame = web_state()->GetWebFramesManager()->GetMainWebFrame();
std::string mainFrameID = main_frame->GetFrameId();
const std::string kTestFormData =
std::string("[{\"name\":\"form-name\",\"origin\":\"https://chromium.test/"
@@ -111,44 +134,42 @@ TEST_F(FormActivityTabHelperTest, TestFormSubmittedHook) {
"\"unique_renderer_id\":\"1\",\"frame_id\":\"") +
mainFrameID + std::string("\"}]");
- bool has_user_gesture = false;
- bool form_in_main_frame = true;
- EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
- base::test::ios::kWaitForJSCompletionTimeout, ^bool {
- return web_state()->GetWebFramesManager()->GetMainWebFrame() != nullptr;
- }));
-
ExecuteJavaScript(@"document.getElementById('form').submit();");
ASSERT_TRUE(observer_->submit_document_info());
EXPECT_EQ(web_state(), observer_->submit_document_info()->web_state);
EXPECT_EQ(main_frame, observer_->submit_document_info()->sender_frame);
EXPECT_EQ(kTestFormName, observer_->submit_document_info()->form_name);
EXPECT_EQ(kTestFormData, observer_->submit_document_info()->form_data);
- EXPECT_EQ(has_user_gesture,
- observer_->submit_document_info()->has_user_gesture);
- EXPECT_EQ(form_in_main_frame,
- observer_->submit_document_info()->form_in_main_frame);
+ EXPECT_FALSE(observer_->submit_document_info()->has_user_gesture);
+ EXPECT_TRUE(observer_->submit_document_info()->form_in_main_frame);
}
// Tests that observer is called on form activity (input event).
TEST_F(FormActivityTabHelperTest, TestObserverFormActivityFrameMessaging) {
- LoadHtmlAndInject(
- @"<form name='form-name'>"
- "<input type='input' name='field-name' id='fieldid'/>"
- "</form>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);");
- EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
- base::test::ios::kWaitForJSCompletionTimeout, ^bool {
- return web_state()->GetWebFramesManager()->GetMainWebFrame() != nullptr;
- }));
- WebFrame* main_frame = web_state()->GetWebFramesManager()->GetMainWebFrame();
+ LoadHtml(@"<form name='form-name'>"
+ "<input type='input' name='field-name' id='fieldid'/>"
+ "</form>");
+
+ WebFrame* main_frame = WaitForMainFrame();
+ ASSERT_TRUE(main_frame);
+
+ uint32_t next_available_id = 1;
+ autofill::FormUtilJavaScriptFeature::GetInstance()
+ ->SetUpForUniqueIDsWithInitialState(main_frame, next_available_id);
+
+ // Wait for |SetUpForUniqueIDsWithInitialState| to complete.
+ EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+ return [ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]") intValue] ==
+ int{next_available_id};
+ }));
+
ASSERT_FALSE(observer_->form_activity_info());
// First call will set document.activeElement (which is usually set by user
// action. Second call will trigger the message.
ExecuteJavaScript(@"document.getElementById('fieldid').focus();");
ASSERT_FALSE(observer_->form_activity_info());
ExecuteJavaScript(@"document.getElementById('fieldid').focus();");
- EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+ ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
base::test::ios::kWaitForJSCompletionTimeout, ^bool {
return observer_->form_activity_info() != nullptr;
}));
diff --git a/chromium/components/autofill/ios/form_util/form_handlers_java_script_feature.h b/chromium/components/autofill/ios/form_util/form_handlers_java_script_feature.h
new file mode 100644
index 00000000000..2c61cd71d4c
--- /dev/null
+++ b/chromium/components/autofill/ios/form_util/form_handlers_java_script_feature.h
@@ -0,0 +1,52 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_IOS_FORM_UTIL_FORM_HANDLERS_JAVA_SCRIPT_FEATURE_H_
+#define COMPONENTS_AUTOFILL_IOS_FORM_UTIL_FORM_HANDLERS_JAVA_SCRIPT_FEATURE_H_
+
+#include "base/no_destructor.h"
+#import "ios/web/public/js_messaging/java_script_feature.h"
+
+namespace web {
+class WebFrame;
+class WebState;
+} // namespace web
+
+namespace autofill {
+
+// Registers listeners that are used to handle forms, enabling autofill and the
+// replacement method to dismiss the keyboard needed because of the Autofill
+// keyboard accessory.
+class FormHandlersJavaScriptFeature : public web::JavaScriptFeature {
+ public:
+ // This feature holds no state, so only a single static instance is ever
+ // needed.
+ static FormHandlersJavaScriptFeature* GetInstance();
+
+ // Toggles tracking form related changes in the frame.
+ void TrackFormMutations(web::WebFrame* frame, int mutation_tracking_delay);
+
+ // Toggles tracking the source of the input events in the frame.
+ void ToggleTrackingUserEditedFields(web::WebFrame* frame,
+ bool track_user_edited_fields);
+
+ private:
+ friend class base::NoDestructor<FormHandlersJavaScriptFeature>;
+
+ // web::JavaScriptFeature
+ absl::optional<std::string> GetScriptMessageHandlerName() const override;
+ void ScriptMessageReceived(web::WebState* web_state,
+ const web::ScriptMessage& message) override;
+
+ FormHandlersJavaScriptFeature();
+ ~FormHandlersJavaScriptFeature() override;
+
+ FormHandlersJavaScriptFeature(const FormHandlersJavaScriptFeature&) = delete;
+ FormHandlersJavaScriptFeature& operator=(
+ const FormHandlersJavaScriptFeature&) = delete;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_IOS_FORM_UTIL_FORM_HANDLERS_JAVA_SCRIPT_FEATURE_H_
diff --git a/chromium/components/autofill/ios/form_util/form_handlers_java_script_feature.mm b/chromium/components/autofill/ios/form_util/form_handlers_java_script_feature.mm
new file mode 100644
index 00000000000..777227f9f24
--- /dev/null
+++ b/chromium/components/autofill/ios/form_util/form_handlers_java_script_feature.mm
@@ -0,0 +1,78 @@
+// Copyright 2021 The Chromium 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 "components/autofill/ios/form_util/form_handlers_java_script_feature.h"
+
+#include "base/values.h"
+#include "components/autofill/ios/form_util/form_activity_tab_helper.h"
+#import "components/autofill/ios/form_util/form_util_java_script_feature.h"
+#import "components/password_manager/ios/password_manager_java_script_feature.h"
+#include "ios/web/public/js_messaging/java_script_feature_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+constexpr char kScriptName[] = "form_handlers_js";
+constexpr char kScriptMessageName[] = "FormHandlersMessage";
+} // namespace
+
+namespace autofill {
+
+// static
+FormHandlersJavaScriptFeature* FormHandlersJavaScriptFeature::GetInstance() {
+ static base::NoDestructor<FormHandlersJavaScriptFeature> instance;
+ return instance.get();
+}
+
+FormHandlersJavaScriptFeature::FormHandlersJavaScriptFeature()
+ : web::JavaScriptFeature(
+ // TODO(crbug.com/1175793): Move autofill code to kAnyContentWorld
+ // once all scripts are converted to JavaScriptFeatures.
+ ContentWorld::kPageContentWorld,
+ {FeatureScript::CreateWithFilename(
+ kScriptName,
+ FeatureScript::InjectionTime::kDocumentStart,
+ FeatureScript::TargetFrames::kAllFrames,
+ FeatureScript::ReinjectionBehavior::
+ kReinjectOnDocumentRecreation)},
+ {web::java_script_features::GetCommonJavaScriptFeature(),
+ autofill::FormUtilJavaScriptFeature::GetInstance(),
+ password_manager::PasswordManagerJavaScriptFeature::GetInstance()}) {
+}
+
+FormHandlersJavaScriptFeature::~FormHandlersJavaScriptFeature() = default;
+
+void FormHandlersJavaScriptFeature::TrackFormMutations(
+ web::WebFrame* frame,
+ int mutation_tracking_delay) {
+ std::vector<base::Value> parameters;
+ parameters.push_back(base::Value(mutation_tracking_delay));
+ CallJavaScriptFunction(frame, "formHandlers.trackFormMutations", parameters);
+}
+
+void FormHandlersJavaScriptFeature::ToggleTrackingUserEditedFields(
+ web::WebFrame* frame,
+ bool track_user_edited_fields) {
+ std::vector<base::Value> parameters;
+ parameters.push_back(base::Value(track_user_edited_fields));
+ CallJavaScriptFunction(frame, "formHandlers.toggleTrackingUserEditedFields",
+ parameters);
+}
+
+absl::optional<std::string>
+FormHandlersJavaScriptFeature::GetScriptMessageHandlerName() const {
+ return kScriptMessageName;
+}
+
+void FormHandlersJavaScriptFeature::ScriptMessageReceived(
+ web::WebState* web_state,
+ const web::ScriptMessage& message) {
+ FormActivityTabHelper* helper =
+ FormActivityTabHelper::GetOrCreateForWebState(web_state);
+ helper->OnFormMessageReceived(web_state, message);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/ios/form_util/form_unittest.mm b/chromium/components/autofill/ios/form_util/form_unittest.mm
index 77f4ed757a4..4fb62d0be90 100644
--- a/chromium/components/autofill/ios/form_util/form_unittest.mm
+++ b/chromium/components/autofill/ios/form_util/form_unittest.mm
@@ -4,11 +4,14 @@
#import "base/test/ios/wait_util.h"
#include "components/autofill/ios/form_util/form_activity_tab_helper.h"
+#import "components/autofill/ios/form_util/form_handlers_java_script_feature.h"
+#import "components/autofill/ios/form_util/form_util_java_script_feature.h"
#include "components/autofill/ios/form_util/test_form_activity_observer.h"
#import "ios/web/public/browser_state.h"
+#import "ios/web/public/js_messaging/web_frame_util.h"
+#import "ios/web/public/js_messaging/web_frames_manager.h"
#import "ios/web/public/test/fakes/fake_web_client.h"
#import "ios/web/public/test/js_test_util.h"
-#import "ios/web/public/test/web_js_test.h"
#import "ios/web/public/test/web_test_with_web_state.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -19,23 +22,24 @@
using base::test::ios::WaitUntilConditionOrTimeout;
using base::test::ios::kWaitForJSCompletionTimeout;
-class FormTestClient : public web::FakeWebClient {
- public:
- NSString* GetDocumentStartScriptForAllFrames(
- web::BrowserState* browser_state) const override {
- return web::test::GetPageScript(@"form_util_js");
- }
-};
+namespace {
+const int kTrackFormMutationsDelayInMs = 10;
+}
// Text fixture to test password controller.
-class FormJsTest : public web::WebJsTest<web::WebTestWithWebState> {
+class FormJsTest : public web::WebTestWithWebState {
public:
FormJsTest()
- : web::WebJsTest<web::WebTestWithWebState>(
- std::make_unique<FormTestClient>()) {}
+ : web::WebTestWithWebState(std::make_unique<web::FakeWebClient>()) {
+ web::FakeWebClient* web_client =
+ static_cast<web::FakeWebClient*>(GetWebClient());
+ web_client->SetJavaScriptFeatures(
+ {autofill::FormUtilJavaScriptFeature::GetInstance(),
+ autofill::FormHandlersJavaScriptFeature::GetInstance()});
+ }
void SetUp() override {
- web::WebJsTest<web::WebTestWithWebState>::SetUp();
+ web::WebTestWithWebState::SetUp();
observer_ =
std::make_unique<autofill::TestFormActivityObserver>(web_state());
autofill::FormActivityTabHelper::GetOrCreateForWebState(web_state())
@@ -45,10 +49,41 @@ class FormJsTest : public web::WebJsTest<web::WebTestWithWebState> {
void TearDown() override {
autofill::FormActivityTabHelper::GetOrCreateForWebState(web_state())
->RemoveObserver(observer_.get());
- web::WebJsTest<web::WebTestWithWebState>::TearDown();
+ web::WebTestWithWebState::TearDown();
}
protected:
+ web::WebFrame* WaitForMainFrame() {
+ __block web::WebFrame* main_frame = nullptr;
+ EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+ main_frame = web_state()->GetWebFramesManager()->GetMainWebFrame();
+ return main_frame != nullptr;
+ }));
+ return main_frame;
+ }
+
+ void TrackFormMutations(web::WebFrame* frame) {
+ // Override |__gCrWeb.formHandlers.trackFormMutations| to set a boolean
+ // trackFormMutationsComplete after the function is called.
+ ExecuteJavaScript(
+ @"var trackFormMutationsComplete = false;"
+ @"var originalTrackFormMutations = "
+ @"__gCrWeb.formHandlers.trackFormMutations;"
+ @"__gCrWeb.formHandlers.trackFormMutations = function() {"
+ @" var result = originalTrackFormMutations.apply(this, arguments);"
+ @" trackFormMutationsComplete = true;"
+ @" return result;"
+ @"};");
+
+ autofill::FormHandlersJavaScriptFeature::GetInstance()->TrackFormMutations(
+ frame, kTrackFormMutationsDelayInMs);
+
+ // Wait for |TrackFormMutations| to add form listeners.
+ ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{
+ return [ExecuteJavaScript(@"trackFormMutationsComplete") boolValue];
+ }));
+ }
+
std::unique_ptr<autofill::TestFormActivityObserver> observer_;
};
@@ -164,9 +199,23 @@ TEST_F(FormJsTest, FormSameOriginIFrame) {
// Tests that a new form triggers form_changed event.
TEST_F(FormJsTest, AddForm) {
LoadHtml(@"<body></body>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);");
+
+ web::WebFrame* main_frame = WaitForMainFrame();
+ ASSERT_TRUE(main_frame);
+
+ uint32_t next_available_id = 1;
+ autofill::FormUtilJavaScriptFeature::GetInstance()
+ ->SetUpForUniqueIDsWithInitialState(main_frame, next_available_id);
+
+ // Wait for |SetUpForUniqueIDsWithInitialState| to complete.
+ ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+ return [ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]") intValue] ==
+ int{next_available_id};
+ }));
+
+ TrackFormMutations(main_frame);
+
ExecuteJavaScript(
- @"__gCrWeb.formHandlers.trackFormMutations(10);"
@"var form = document.createElement('form');"
@"document.body.appendChild(form);");
autofill::TestFormActivityObserver* block_observer = observer_.get();
@@ -183,8 +232,11 @@ TEST_F(FormJsTest, AddForm) {
TEST_F(FormJsTest, AddInput) {
LoadHtml(@"<form id='formId'/>");
+ web::WebFrame* main_frame = WaitForMainFrame();
+ ASSERT_TRUE(main_frame);
+ TrackFormMutations(main_frame);
+
ExecuteJavaScript(
- @"__gCrWeb.formHandlers.trackFormMutations(10);"
@"var input = document.createElement('input');"
@"document.getElementById('formId').appendChild(input);");
autofill::TestFormActivityObserver* block_observer = observer_.get();
@@ -201,8 +253,11 @@ TEST_F(FormJsTest, AddInput) {
TEST_F(FormJsTest, AddSelect) {
LoadHtml(@"<form id='formId'/>");
+ web::WebFrame* main_frame = WaitForMainFrame();
+ ASSERT_TRUE(main_frame);
+ TrackFormMutations(main_frame);
+
ExecuteJavaScript(
- @"__gCrWeb.formHandlers.trackFormMutations(10);"
@"var select = document.createElement('select');"
@"document.getElementById('formId').appendChild(select);");
autofill::TestFormActivityObserver* block_observer = observer_.get();
@@ -222,8 +277,11 @@ TEST_F(FormJsTest, AddOption) {
"<select id='select1'><option value='CA'>CA</option></select>"
"</form>");
+ web::WebFrame* main_frame = WaitForMainFrame();
+ ASSERT_TRUE(main_frame);
+ TrackFormMutations(main_frame);
+
ExecuteJavaScript(
- @"__gCrWeb.formHandlers.trackFormMutations(10);"
@"var option = document.createElement('option');"
@"document.getElementById('select1').appendChild(option);");
autofill::TestFormActivityObserver* block_observer = observer_.get();
@@ -243,9 +301,22 @@ TEST_F(FormJsTest, RemoveForm) {
"<input type=\"password\" name=\"password\" id=\"id2\">"
"<input type=\"submit\" id=\"submit_input\"/>"
"</form>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);"
- @"__gCrWeb.formHandlers.trackFormMutations(10);"
- @"var form1 = document.getElementById('form1');"
+
+ web::WebFrame* main_frame = WaitForMainFrame();
+ ASSERT_TRUE(main_frame);
+
+ uint32_t next_available_id = 1;
+ autofill::FormUtilJavaScriptFeature::GetInstance()
+ ->SetUpForUniqueIDsWithInitialState(main_frame, next_available_id);
+
+ // Wait for |SetUpForUniqueIDsWithInitialState| to complete.
+ ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+ return [ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]") intValue] ==
+ int{next_available_id};
+ }));
+
+ TrackFormMutations(main_frame);
+ ExecuteJavaScript(@"var form1 = document.getElementById('form1');"
@"__gCrWeb.fill.setUniqueIDIfNeeded(form1);"
@"form1.parentNode.removeChild(form1);");
autofill::TestFormActivityObserver* block_observer = observer_.get();
diff --git a/chromium/components/autofill/ios/form_util/form_util_java_script_feature.h b/chromium/components/autofill/ios/form_util/form_util_java_script_feature.h
new file mode 100644
index 00000000000..66060a96a23
--- /dev/null
+++ b/chromium/components/autofill/ios/form_util/form_util_java_script_feature.h
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_IOS_FORM_UTIL_FORM_UTIL_JAVA_SCRIPT_FEATURE_H_
+#define COMPONENTS_AUTOFILL_IOS_FORM_UTIL_FORM_UTIL_JAVA_SCRIPT_FEATURE_H_
+
+#include "base/no_destructor.h"
+#import "ios/web/public/js_messaging/java_script_feature.h"
+
+namespace web {
+class WebFrame;
+} // namespace web
+
+namespace autofill {
+
+// Communicates with the JavaScript file, fill.js, which contains form util
+// functions.
+class FormUtilJavaScriptFeature : public web::JavaScriptFeature {
+ public:
+ // This feature holds no state, so only a single static instance is ever
+ // needed.
+ static FormUtilJavaScriptFeature* GetInstance();
+
+ // Sets up the next available unique ID value in a document.
+ void SetUpForUniqueIDsWithInitialState(web::WebFrame* frame,
+ uint32_t next_available_id);
+
+ private:
+ friend class base::NoDestructor<FormUtilJavaScriptFeature>;
+
+ FormUtilJavaScriptFeature();
+ ~FormUtilJavaScriptFeature() override;
+
+ FormUtilJavaScriptFeature(const FormUtilJavaScriptFeature&) = delete;
+ FormUtilJavaScriptFeature& operator=(const FormUtilJavaScriptFeature&) =
+ delete;
+};
+
+} // namespace autofill
+
+#endif // COMPONENTS_AUTOFILL_IOS_FORM_UTIL_FORM_UTIL_JAVA_SCRIPT_FEATURE_H_
diff --git a/chromium/components/autofill/ios/form_util/form_util_java_script_feature.mm b/chromium/components/autofill/ios/form_util/form_util_java_script_feature.mm
new file mode 100644
index 00000000000..6b5752909ef
--- /dev/null
+++ b/chromium/components/autofill/ios/form_util/form_util_java_script_feature.mm
@@ -0,0 +1,55 @@
+// Copyright 2021 The Chromium 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 "components/autofill/ios/form_util/form_util_java_script_feature.h"
+
+#include "base/values.h"
+#import "ios/web/public/js_messaging/java_script_feature_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+const char kFillScriptName[] = "fill_js";
+const char kFormScriptName[] = "form_js";
+} // namespace
+
+namespace autofill {
+
+// static
+FormUtilJavaScriptFeature* FormUtilJavaScriptFeature::GetInstance() {
+ static base::NoDestructor<FormUtilJavaScriptFeature> instance;
+ return instance.get();
+}
+
+FormUtilJavaScriptFeature::FormUtilJavaScriptFeature()
+ : web::JavaScriptFeature(
+ // TODO(crbug.com/1175793): Move autofill code to kAnyContentWorld
+ // once all scripts are converted to JavaScriptFeatures.
+ ContentWorld::kPageContentWorld,
+ {FeatureScript::CreateWithFilename(
+ kFillScriptName,
+ FeatureScript::InjectionTime::kDocumentStart,
+ FeatureScript::TargetFrames::kAllFrames,
+ FeatureScript::ReinjectionBehavior::kInjectOncePerWindow),
+ FeatureScript::CreateWithFilename(
+ kFormScriptName,
+ FeatureScript::InjectionTime::kDocumentStart,
+ FeatureScript::TargetFrames::kAllFrames,
+ FeatureScript::ReinjectionBehavior::kInjectOncePerWindow)},
+ {web::java_script_features::GetCommonJavaScriptFeature(),
+ web::java_script_features::GetMessageJavaScriptFeature()}) {}
+
+FormUtilJavaScriptFeature::~FormUtilJavaScriptFeature() = default;
+
+void FormUtilJavaScriptFeature::SetUpForUniqueIDsWithInitialState(
+ web::WebFrame* frame,
+ uint32_t next_available_id) {
+ std::vector<base::Value> parameters;
+ parameters.emplace_back(int{next_available_id});
+ CallJavaScriptFunction(frame, "fill.setUpForUniqueIDs", parameters);
+}
+
+} // namespace autofill
diff --git a/chromium/components/autofill/ios/form_util/resources/fill.js b/chromium/components/autofill/ios/form_util/resources/fill.js
index 308feef0dfa..0aec72ea5de 100644
--- a/chromium/components/autofill/ios/form_util/resources/fill.js
+++ b/chromium/components/autofill/ios/form_util/resources/fill.js
@@ -6,7 +6,7 @@
goog.provide('__crWeb.fill');
-goog.require('__crWeb.form');
+// Requires __crWeb.form.
/**
* @typedef {{
diff --git a/chromium/components/autofill/ios/form_util/resources/form.js b/chromium/components/autofill/ios/form_util/resources/form.js
index 135f3dbfd2f..0fb7851a7ce 100644
--- a/chromium/components/autofill/ios/form_util/resources/form.js
+++ b/chromium/components/autofill/ios/form_util/resources/form.js
@@ -277,6 +277,9 @@ __gCrWeb.form.getFormElementFromIdentifier = function(name) {
* @return {HTMLFormElement} The original form element, if it can be determined.
*/
__gCrWeb.form.getFormElementFromUniqueFormId = function(identifier) {
+ if (identifier.toString() === __gCrWeb.fill.RENDERER_ID_NOT_SET) {
+ return null;
+ }
const forms = document.forms;
for (let i = 0; i < forms.length; i++) {
const form = forms[i];
diff --git a/chromium/components/autofill/ios/form_util/resources/form_handlers.js b/chromium/components/autofill/ios/form_util/resources/form_handlers.js
index 81344804475..342bd956cce 100644
--- a/chromium/components/autofill/ios/form_util/resources/form_handlers.js
+++ b/chromium/components/autofill/ios/form_util/resources/form_handlers.js
@@ -10,8 +10,7 @@
goog.provide('__crWeb.formHandlers');
-goog.require('__crWeb.fill');
-goog.require('__crWeb.form');
+// Requires __crWeb.fill and __crWeb.form.
/**
* Namespace for this file. It depends on |__gCrWeb| having already been
@@ -62,7 +61,7 @@ let formSubmitOriginalFunction = null;
function sendMessageOnNextLoop_(mesg) {
if (!messageToSend) {
setTimeout(function() {
- __gCrWeb.message.invokeOnHost(messageToSend);
+ __gCrWeb.common.sendWebKitMessage('FormHandlersMessage', messageToSend);
messageToSend = null;
}, 0);
}
@@ -127,6 +126,7 @@ function trackPasswordField_(field) {
if (target.value === '') {
const msg = {
'command': 'form.activity',
+ 'frameID': __gCrWeb.message.getFrameId(),
'formName': '',
'uniqueFormID': '',
'fieldIdentifier': '',
@@ -222,6 +222,7 @@ function formActivity_(evt) {
const msg = {
'command': 'form.activity',
+ 'frameID': __gCrWeb.message.getFrameId(),
'formName': __gCrWeb.form.getFormIdentifier(form),
'uniqueFormID': formUniqueId,
'fieldIdentifier': __gCrWeb.form.getFieldIdentifier(field),
@@ -251,8 +252,9 @@ function submitHandler_(evt) {
function formSubmitted_(form) {
// Default action is to re-submit to same page.
const action = form.getAttribute('action') || document.location.href;
- __gCrWeb.message.invokeOnHost({
+ __gCrWeb.common.sendWebKitMessage('FormHandlersMessage', {
'command': 'form.submit',
+ 'frameID': __gCrWeb.message.getFrameId(),
'formName': __gCrWeb.form.getFormIdentifier(form),
'href': getFullyQualifiedUrl_(action),
'formData': __gCrWeb.fill.autofillSubmissionData(form)
@@ -268,7 +270,8 @@ function sendFormMutationMessageAfterDelay_(msg, delay) {
formMutationMessageToSend = msg;
setTimeout(function() {
- __gCrWeb.message.invokeOnHost(formMutationMessageToSend);
+ __gCrWeb.common.sendWebKitMessage(
+ 'FormHandlersMessage', formMutationMessageToSend);
formMutationMessageToSend = null;
}, delay);
}
@@ -357,6 +360,7 @@ __gCrWeb.formHandlers['trackFormMutations'] = function(delay) {
if (formChanged) {
const msg = {
'command': 'form.activity',
+ 'frameID': __gCrWeb.message.getFrameId(),
'formName': '',
'uniqueFormID': '',
'fieldIdentifier': '',
@@ -395,6 +399,7 @@ __gCrWeb.formHandlers['trackFormMutations'] = function(delay) {
if (formGone) {
const msg = {
'command': 'form.activity',
+ 'frameID': __gCrWeb.message.getFrameId(),
'formName': '',
'uniqueFormID': uniqueFormId,
'fieldIdentifier': '',
@@ -422,9 +427,5 @@ __gCrWeb.formHandlers['toggleTrackingUserEditedFields'] = function(track) {
__gCrWeb.form.wasEditedByUser = null;
}
};
-/** Flush the message queue. */
-if (__gCrWeb.message) {
- __gCrWeb.message.invokeQueues();
-}
}()); // End of anonymous object
diff --git a/chromium/components/autofill_assistant/README.md b/chromium/components/autofill_assistant/README.md
new file mode 100644
index 00000000000..bb3af82c145
--- /dev/null
+++ b/chromium/components/autofill_assistant/README.md
@@ -0,0 +1,16 @@
+# Autofill Assistant
+
+## Overview
+Autofill Assistant is an execution engine to run user journeys on websites
+given a set of actions. These actions include clicking on buttons or
+scrolling to an element. They also provide a way to interact with the user
+or get input to advance in the flow.
+
+## Internal links
+For a design overview see [this link](http://go/autofill-assistant-doc).
+More information about the team can be found
+[here](http://go/autofill-assistant-internal).
+
+## Contact
+The bug component is [UI>Browser>Autofill>Assistant](https://bugs.chromium.org/p/chromium/issues/list?q=component:UI%3EBrowser%3EAutofill%3EAssistant)
+and the team email `autofill_assistant@google.com`.
diff --git a/chromium/components/autofill_assistant/browser/BUILD.gn b/chromium/components/autofill_assistant/browser/BUILD.gn
index 228e0c03b7f..7498c5f33dd 100644
--- a/chromium/components/autofill_assistant/browser/BUILD.gn
+++ b/chromium/components/autofill_assistant/browser/BUILD.gn
@@ -27,6 +27,12 @@ static_library("browser") {
"actions/action_delegate.h",
"actions/action_delegate_util.cc",
"actions/action_delegate_util.h",
+ "actions/check_element_tag_action.cc",
+ "actions/check_element_tag_action.h",
+ "actions/check_option_element_action.cc",
+ "actions/check_option_element_action.h",
+ "actions/clear_persistent_ui_action.cc",
+ "actions/clear_persistent_ui_action.h",
"actions/click_action.cc",
"actions/click_action.h",
"actions/collect_user_data_action.cc",
@@ -69,6 +75,8 @@ static_library("browser") {
"actions/set_attribute_action.h",
"actions/set_form_field_value_action.cc",
"actions/set_form_field_value_action.h",
+ "actions/set_persistent_ui_action.cc",
+ "actions/set_persistent_ui_action.h",
"actions/show_cast_action.cc",
"actions/show_cast_action.h",
"actions/show_details_action.cc",
@@ -190,6 +198,8 @@ static_library("browser") {
"service/simple_url_loader_factory.h",
"starter.cc",
"starter.h",
+ "starter_heuristic.cc",
+ "starter_heuristic.h",
"starter_platform_delegate.h",
"startup_util.cc",
"startup_util.h",
@@ -229,6 +239,8 @@ static_library("browser") {
"wait_for_dom_observer.h",
"web/check_on_top_worker.cc",
"web/check_on_top_worker.h",
+ "web/click_or_tap_worker.cc",
+ "web/click_or_tap_worker.h",
"web/element.cc",
"web/element.h",
"web/element_finder.cc",
@@ -271,6 +283,7 @@ static_library("browser") {
"//components/signin/public/identity_manager",
"//components/strings:components_strings_grit",
"//components/ukm/content:content",
+ "//components/url_matcher",
"//components/version_info",
"//content/public/browser",
"//google_apis",
@@ -327,6 +340,9 @@ source_set("unit_tests") {
"actions/action_test_utils.cc",
"actions/action_test_utils.h",
"actions/action_unittest.cc",
+ "actions/check_element_tag_action_unittest.cc",
+ "actions/check_option_element_action_unittest.cc",
+ "actions/clear_persistent_ui_action_unittest.cc",
"actions/click_action_unittest.cc",
"actions/collect_user_data_action_unittest.cc",
"actions/configure_bottom_sheet_action_unittest.cc",
@@ -345,6 +361,7 @@ source_set("unit_tests") {
"actions/select_option_action_unittest.cc",
"actions/set_attribute_action_unittest.cc",
"actions/set_form_field_value_action_unittest.cc",
+ "actions/set_persistent_ui_action_unittest.cc",
"actions/show_cast_action_unittest.cc",
"actions/show_details_action_unittest.cc",
"actions/show_generic_ui_action_unittest.cc",
@@ -391,6 +408,7 @@ source_set("unit_tests") {
"service/service_impl_unittest.cc",
"service/service_request_sender_impl_unittest.cc",
"service/service_request_sender_local_impl_unittest.cc",
+ "starter_heuristic_unittest.cc",
"starter_unittest.cc",
"startup_util_unittest.cc",
"string_conversions_util_unittest.cc",
@@ -402,6 +420,8 @@ source_set("unit_tests") {
"trigger_scripts/mock_dynamic_trigger_conditions.h",
"trigger_scripts/mock_static_trigger_conditions.cc",
"trigger_scripts/mock_static_trigger_conditions.h",
+ "trigger_scripts/mock_trigger_script_ui_delegate.cc",
+ "trigger_scripts/mock_trigger_script_ui_delegate.h",
"trigger_scripts/static_trigger_conditions_unittest.cc",
"trigger_scripts/trigger_script_coordinator_unittest.cc",
"trigger_scripts/trigger_script_unittest.cc",
@@ -427,6 +447,7 @@ source_set("unit_tests") {
"//components/strings:components_strings_grit",
"//components/ukm:test_support",
"//components/ukm/content:content",
+ "//components/url_matcher",
"//components/version_info",
"//content/test:test_support",
"//services/network:test_support",
diff --git a/chromium/components/autofill_assistant/browser/DEPS b/chromium/components/autofill_assistant/browser/DEPS
index 39dc10e3783..9adb618ff89 100644
--- a/chromium/components/autofill_assistant/browser/DEPS
+++ b/chromium/components/autofill_assistant/browser/DEPS
@@ -7,6 +7,7 @@ include_rules = [
"+components/password_manager/core/browser",
"+components/password_manager/core/common",
"+components/ukm",
+ "+components/url_matcher",
"+components/version_info",
"+content/public/browser",
"+content/public/test",
diff --git a/chromium/components/autofill_assistant/browser/action_value.proto b/chromium/components/autofill_assistant/browser/action_value.proto
index 4ea533fd8db..80ea145fc81 100644
--- a/chromium/components/autofill_assistant/browser/action_value.proto
+++ b/chromium/components/autofill_assistant/browser/action_value.proto
@@ -10,37 +10,57 @@ option java_multiple_files = true;
package autofill_assistant;
-message AutofillValue {
- message Profile { optional string identifier = 1; }
+// An Autofill profile stored on the client. This requires to be selected by
+// the user in a CollectUserData step first.
+message AutofillProfile {
+ optional string identifier = 1;
+}
+
+// A value expression.
+message ValueExpression {
+ message Chunk {
+ oneof chunk {
+ // An integer representation to resolve a piece of Autofill information.
+ // The key is an integer corresponding to entries from field_types.h or
+ // |AutofillFormatProto::AutofillAssistantCustomField|.
+ // Note that the set of actually available fields are outside of our
+ // control and are retrieved automatically from the provided profile.
+ int32 key = 1;
+ // A plain text.
+ string text = 2;
+ }
+ }
+ repeated Chunk chunk = 1;
+}
+
+// A value expression to be used as a regular expression.
+message ValueExpressionRegexp {
+ optional ValueExpression value_expression = 1;
+
+ // If true, the |value_expression| will be checked case sensitively.
+ // Default is case insensitive.
+ optional bool case_sensitive = 4;
+}
+message AutofillValue {
// The profile to be used. This has to be requested with a
// |CollectUserDataAction| first.
- optional Profile profile = 1;
-
- // A string containing any number of "${key}" placeholders, where the key is
- // an integer corresponding to entries from field_types.h or
- // |AutofillFormatProto::AutofillAssistantCustomField|.
- // Note that the set of actually available fields are outside of our
- // control and are retrieved automatically from the provided profile.
- optional string value_expression = 2;
+ optional AutofillProfile profile = 1;
+
+ // The value expression.
+ optional ValueExpression value_expression = 5;
+
+ reserved 2 to 4;
}
message AutofillValueRegexp {
- message Profile { optional string identifier = 1; }
-
// The profile to be used. This has to be requested with a
// |CollectUserDataAction| first.
- optional Profile profile = 1;
-
- // A string containing any number of "${key}" placeholders, where the key is
- // an integer corresponding to entries from field_types.h or
- // |AutofillFormatProto::AutofillAssistantCustomField|.
- // Note that the set of actually available fields are outside of our
- // control and are retrieved automatically from the provided profile.
- // The |value_expression| needs to escape all text outside of placeholders,
- // e.g. a pattern like "+${12}" needs to escape the "+". The pattern keys
- // ("${12}") should not be escaped, this will be handled during replacement.
- optional TextFilter value_expression = 2;
+ optional AutofillProfile profile = 1;
+
+ optional ValueExpressionRegexp value_expression_re2 = 3;
+
+ reserved 2;
}
// A wrapper for regular expressions, e.g. used for filtering elements by their
diff --git a/chromium/components/autofill_assistant/browser/actions/action.cc b/chromium/components/autofill_assistant/browser/actions/action.cc
index 9ba44a79d8c..152b445ec09 100644
--- a/chromium/components/autofill_assistant/browser/actions/action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/action.cc
@@ -16,6 +16,10 @@ Action::Action(ActionDelegate* delegate, const ActionProto& proto)
Action::~Action() {}
+bool Action::ShouldInterruptOnPause() const {
+ return false;
+}
+
void Action::ProcessAction(ProcessActionCallback callback) {
action_stopwatch_.StartActiveTime();
processed_action_proto_ = std::make_unique<ProcessedActionProto>();
@@ -218,6 +222,21 @@ std::ostream& operator<<(std::ostream& out,
case ActionProto::ActionInfoCase::kSendKeyEvent:
out << "SendKeyEvent";
break;
+ case ActionProto::ActionInfoCase::kSelectOptionElement:
+ out << "SelectOptionElement";
+ break;
+ case ActionProto::ActionInfoCase::kCheckElementTag:
+ out << "CheckElementTag";
+ break;
+ case ActionProto::ActionInfoCase::kCheckOptionElement:
+ out << "CheckOptionElement";
+ break;
+ case ActionProto::ActionInfoCase::kSetPersistentUi:
+ out << "SetPersistentUi";
+ break;
+ case ActionProto::ActionInfoCase::kClearPersistentUi:
+ out << "ClearPersistentUi";
+ break;
case ActionProto::ActionInfoCase::ACTION_INFO_NOT_SET:
out << "ACTION_INFO_NOT_SET";
break;
diff --git a/chromium/components/autofill_assistant/browser/actions/action.h b/chromium/components/autofill_assistant/browser/actions/action.h
index 4675bf2ea5b..97676f85bd1 100644
--- a/chromium/components/autofill_assistant/browser/actions/action.h
+++ b/chromium/components/autofill_assistant/browser/actions/action.h
@@ -36,6 +36,10 @@ class Action {
const ActionProto& proto() const { return proto_; }
+ // Actions that can manipulate the UserActions should be interrupted, such
+ // that they do not overwrite the paused state.
+ virtual bool ShouldInterruptOnPause() const;
+
protected:
// |delegate| must remain valid for the lifetime of this instance.
explicit Action(ActionDelegate* delegate, const ActionProto& proto);
diff --git a/chromium/components/autofill_assistant/browser/actions/action_delegate.h b/chromium/components/autofill_assistant/browser/actions/action_delegate.h
index 023fc2978df..958ecd577a9 100644
--- a/chromium/components/autofill_assistant/browser/actions/action_delegate.h
+++ b/chromium/components/autofill_assistant/browser/actions/action_delegate.h
@@ -22,7 +22,6 @@
#include "components/autofill_assistant/browser/viewport_mode.h"
#include "components/autofill_assistant/browser/wait_for_dom_observer.h"
#include "components/autofill_assistant/browser/web/element_finder.h"
-#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
#include "third_party/icu/source/common/unicode/umachine.h"
class GURL;
@@ -132,12 +131,6 @@ class ActionDelegate {
virtual void FindAllElements(const Selector& selector,
ElementFinder::Callback callback) const = 0;
- // Click or tap the |element|.
- virtual void ClickOrTapElement(
- ClickType click_type,
- const ElementFinder::Result& element,
- base::OnceCallback<void(const ClientStatus&)> callback) = 0;
-
// Have the UI enter the prompt mode and make the given actions available.
//
// While a prompt is in progress, the UI looks the same as it does between
@@ -397,7 +390,7 @@ class ActionDelegate {
// Show |generic_ui| to the user and call |end_action_callback| when done.
// Note that this callback needs to be tied to one or multiple interactions
// specified in |generic_ui|, as otherwise it will never be called.
- // |view_inflation_finished_callback| should be called immediately after
+ // |view_inflation_finished_callback| will be called immediately after
// view inflation, with a status indicating whether view inflation succeeded.
virtual void SetGenericUi(
std::unique_ptr<GenericUserInterfaceProto> generic_ui,
@@ -405,11 +398,24 @@ class ActionDelegate {
base::OnceCallback<void(const ClientStatus&)>
view_inflation_finished_callback) = 0;
+ // Show |generic_ui| to the user.
+ // |view_inflation_finished_callback| will be called immediately after
+ // view inflation, with a status indicating whether view inflation succeeded.
+ virtual void SetPersistentGenericUi(
+ std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) = 0;
+
// Clears the generic UI. This will remove all corresponding views from the
// view hierarchy and remove all corresponding interactions. Note that
// |user_model| will persist and will not be affected by this call.
virtual void ClearGenericUi() = 0;
+ // Clears the persistent generic UI. This will remove all corresponding views
+ // from the view hierarchy and remove all corresponding interactions. Note
+ // that |user_model| will persist and will not be affected by this call.
+ virtual void ClearPersistentGenericUi() = 0;
+
// Sets the OverlayBehavior.
virtual void SetOverlayBehavior(
ConfigureUiStateProto::OverlayBehavior overlay_behavior) = 0;
diff --git a/chromium/components/autofill_assistant/browser/actions/action_delegate_util.cc b/chromium/components/autofill_assistant/browser/actions/action_delegate_util.cc
index 38b3d5decea..5033cdb2bc5 100644
--- a/chromium/components/autofill_assistant/browser/actions/action_delegate_util.cc
+++ b/chromium/components/autofill_assistant/browser/actions/action_delegate_util.cc
@@ -13,6 +13,7 @@
#include "components/autofill_assistant/browser/string_conversions_util.h"
#include "components/autofill_assistant/browser/user_data_util.h"
#include "components/autofill_assistant/browser/web/element_finder.h"
+#include "components/autofill_assistant/browser/web/element_store.h"
#include "components/autofill_assistant/browser/web/web_controller.h"
namespace autofill_assistant {
@@ -137,7 +138,11 @@ void AddClickOrTapSequence(const ActionDelegate* delegate,
actions->emplace_back(
base::BindOnce(&WebController::ScrollIntoView,
delegate->GetWebController()->GetWeakPtr(), true));
- if (click_type != ClickType::JAVASCRIPT) {
+ if (click_type == ClickType::JAVASCRIPT) {
+ actions->emplace_back(
+ base::BindOnce(&WebController::JsClickElement,
+ delegate->GetWebController()->GetWeakPtr()));
+ } else {
AddStepIgnoreTiming(
base::BindOnce(&WebController::WaitUntilElementIsStable,
delegate->GetWebController()->GetWeakPtr(),
@@ -148,12 +153,13 @@ void AddClickOrTapSequence(const ActionDelegate* delegate,
base::BindOnce(&WebController::CheckOnTop,
delegate->GetWebController()->GetWeakPtr()),
actions);
+ actions->emplace_back(
+ base::BindOnce(&WebController::ClickOrTapElement,
+ delegate->GetWebController()->GetWeakPtr(), click_type));
}
- actions->emplace_back(base::BindOnce(&ActionDelegate::ClickOrTapElement,
- delegate->GetWeakPtr(), click_type));
}
-void OnGetPasswordManagerValue(
+void OnResolveTextValue(
base::OnceCallback<void(const std::string&,
const ElementFinder::Result&,
base::OnceCallback<void(const ClientStatus&)>)>
@@ -189,43 +195,34 @@ void PerformWithTextValue(
perform,
const ElementFinder::Result& element,
base::OnceCallback<void(const ClientStatus&)> done) {
- std::string value;
- switch (text_value.value_case()) {
- case TextValue::kText:
- value = text_value.text();
- break;
- case TextValue::kAutofillValue: {
- ClientStatus autofill_status = GetFormattedAutofillValue(
- text_value.autofill_value(), delegate->GetUserData(), &value);
- if (!autofill_status.ok()) {
- std::move(done).Run(autofill_status);
- return;
- }
- break;
- }
- case TextValue::kPasswordManagerValue: {
- GetPasswordManagerValue(
- text_value.password_manager_value(), element, delegate->GetUserData(),
- delegate->GetWebsiteLoginManager(),
- base::BindOnce(&OnGetPasswordManagerValue, std::move(perform),
- element, std::move(done)));
- return;
- }
- case TextValue::kClientMemoryKey: {
- ClientStatus client_memory_status = GetClientMemoryStringValue(
- text_value.client_memory_key(), delegate->GetUserData(), &value);
- if (!client_memory_status.ok()) {
- std::move(done).Run(client_memory_status);
- return;
- }
- break;
- }
- case TextValue::VALUE_NOT_SET:
- std::move(done).Run(ClientStatus(INVALID_ACTION));
- return;
+ ResolveTextValue(text_value, element, delegate,
+ base::BindOnce(&OnResolveTextValue, std::move(perform),
+ element, std::move(done)));
+}
+
+void PerformWithElementValue(
+ const ActionDelegate* delegate,
+ const ClientIdProto& client_id,
+ base::OnceCallback<void(const ElementFinder::Result&,
+ const ElementFinder::Result&,
+ base::OnceCallback<void(const ClientStatus&)>)>
+ perform,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> done) {
+ std::unique_ptr<ElementFinder::Result> element_result =
+ std::make_unique<ElementFinder::Result>();
+ ElementFinder::Result* element_result_ptr = element_result.get();
+ ClientStatus element_status = delegate->GetElementStore()->GetElement(
+ client_id.identifier(), element_result_ptr);
+ if (!element_status.ok()) {
+ std::move(done).Run(element_status);
+ return;
}
- std::move(perform).Run(value, element, std::move(done));
+ std::move(perform).Run(
+ *element_result_ptr, element,
+ base::BindOnce(&RetainElementAndExecuteCallback,
+ std::move(element_result), std::move(done)));
}
void AddOptionalStep(OptionalStep optional_step,
@@ -325,7 +322,7 @@ void PerformSendKeyboardInput(
base::BindOnce(&WebController::FocusField,
delegate->GetWebController()->GetWeakPtr()));
} else {
- AddClickOrTapSequence(delegate, ClickType::CLICK, /* on_top=*/SKIP_STEP,
+ AddClickOrTapSequence(delegate, ClickType::TAP, /* on_top=*/SKIP_STEP,
actions.get());
}
actions->emplace_back(base::BindOnce(
diff --git a/chromium/components/autofill_assistant/browser/actions/action_delegate_util.h b/chromium/components/autofill_assistant/browser/actions/action_delegate_util.h
index 681979f885d..29f9038abd1 100644
--- a/chromium/components/autofill_assistant/browser/actions/action_delegate_util.h
+++ b/chromium/components/autofill_assistant/browser/actions/action_delegate_util.h
@@ -98,6 +98,19 @@ void PerformWithTextValue(
const ElementFinder::Result& element,
base::OnceCallback<void(const ClientStatus&)> done);
+// Resolve the |client_id| and run the |perform| callback. Run the |done|
+// callback with an error status if the |client_id| could not be resolved.
+// Run the |done| callback with the result status of |perform| otherwise.
+void PerformWithElementValue(
+ const ActionDelegate* delegate,
+ const ClientIdProto& client_id,
+ base::OnceCallback<void(const ElementFinder::Result&,
+ const ElementFinder::Result&,
+ base::OnceCallback<void(const ClientStatus&)>)>
+ perform,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> done);
+
// Adds an optional step to the |actions|. If the step is |SKIP_STEP|, it does
// not add it. For |REPORT_STEP_RESULT| it adds the step ignoring a potential
// failure. For |REQUIRE_STEP_SUCCESS| it binds the step as is.
diff --git a/chromium/components/autofill_assistant/browser/actions/action_delegate_util_unittest.cc b/chromium/components/autofill_assistant/browser/actions/action_delegate_util_unittest.cc
index 43fc713ae59..e28afcf3b7e 100644
--- a/chromium/components/autofill_assistant/browser/actions/action_delegate_util_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/action_delegate_util_unittest.cc
@@ -18,7 +18,10 @@
#include "components/autofill_assistant/browser/mock_website_login_manager.h"
#include "components/autofill_assistant/browser/selector.h"
#include "components/autofill_assistant/browser/user_data.h"
-#include "content/public/test/navigation_simulator.h"
+#include "components/autofill_assistant/browser/user_model.h"
+#include "components/autofill_assistant/browser/web/element_store.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -33,16 +36,13 @@ using ::testing::_;
using ::testing::InSequence;
using ::testing::Return;
-class ActionDelegateUtilTest : public content::RenderViewHostTestHarness {
+class ActionDelegateUtilTest : public testing::Test {
public:
- ActionDelegateUtilTest()
- : RenderViewHostTestHarness(
- base::test::TaskEnvironment::MainThreadType::UI,
- base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
- ~ActionDelegateUtilTest() override {}
+ ActionDelegateUtilTest() {}
void SetUp() override {
- RenderViewHostTestHarness::SetUp();
+ web_contents_ = content::WebContentsTester::CreateTestWebContents(
+ &browser_context_, nullptr);
ON_CALL(mock_action_delegate_, GetUserData)
.WillByDefault(Return(&user_data_));
@@ -74,9 +74,19 @@ class ActionDelegateUtilTest : public content::RenderViewHostTestHarness {
const ElementFinder::Result& element,
base::OnceCallback<void(const ClientStatus&)> done));
+ MOCK_METHOD3(MockElementAction,
+ void(const ElementFinder::Result& parameter_element,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> done));
+
protected:
+ content::BrowserTaskEnvironment task_environment_;
+ content::RenderViewHostTestEnabler rvh_test_enabler_;
+ content::TestBrowserContext browser_context_;
+ std::unique_ptr<content::WebContents> web_contents_;
MockActionDelegate mock_action_delegate_;
UserData user_data_;
+ UserModel user_model_;
MockWebsiteLoginManager mock_website_login_manager_;
};
@@ -309,16 +319,16 @@ TEST_F(ActionDelegateUtilTest, PerformWithAutofillValue) {
autofill::test::kEmptyOrigin);
autofill::test::SetProfileInfo(contact.get(), "John", /* middle name */ "",
"Doe", "", "", "", "", "", "", "", "", "");
- user_data_.selected_addresses_["contact"] = std::move(contact);
+ user_model_.SetSelectedAutofillProfile("contact", std::move(contact),
+ &user_data_);
TextValue text_value;
- auto* autofill_value = text_value.mutable_autofill_value();
- autofill_value->mutable_profile()->set_identifier("contact");
- autofill_value->set_value_expression(
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}"}));
+ text_value.mutable_autofill_value()->mutable_profile()->set_identifier(
+ "contact");
+ text_value.mutable_autofill_value()
+ ->mutable_value_expression()
+ ->add_chunk()
+ ->set_key(static_cast<int>(autofill::ServerFieldType::NAME_FIRST));
PerformWithTextValue(&mock_action_delegate_, text_value,
base::BindOnce(&ActionDelegateUtilTest::MockValueAction,
@@ -330,11 +340,11 @@ TEST_F(ActionDelegateUtilTest, PerformWithAutofillValue) {
TEST_F(ActionDelegateUtilTest, PerformWithPasswordManagerValue) {
auto element = std::make_unique<ElementFinder::Result>();
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL("https://www.example.com"), web_contents()->GetMainFrame());
- element->container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("https://www.example.com"));
+ element->container_frame_host = web_contents_->GetMainFrame();
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL("https://www.example.com"), "username");
EXPECT_CALL(*this, MockValueAction("username", _, _))
@@ -355,11 +365,11 @@ TEST_F(ActionDelegateUtilTest, PerformWithPasswordManagerValue) {
TEST_F(ActionDelegateUtilTest, PerformWithFailingPasswordManagerValue) {
auto element = std::make_unique<ElementFinder::Result>();
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL("https://www.other.com"), web_contents()->GetMainFrame());
- element->container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("https://www.other.com"));
+ element->container_frame_host = web_contents_->GetMainFrame();
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL("https://www.example.com"), "username");
EXPECT_CALL(*this, MockValueAction("username", _, _)).Times(0);
@@ -399,6 +409,48 @@ TEST_F(ActionDelegateUtilTest, PerformWithClientMemoryKey) {
base::Unretained(this)));
}
+TEST_F(ActionDelegateUtilTest, PerformWithExistingElementValue) {
+ auto element = std::make_unique<ElementFinder::Result>();
+
+ ElementFinder::Result option;
+ option.dom_object.object_data.object_id = "option";
+ mock_action_delegate_.GetElementStore()->AddElement("o", option.dom_object);
+
+ EXPECT_CALL(*this, MockElementAction(EqualsElement(option), _, _))
+ .WillOnce(RunOnceCallback<2>(OkClientStatus()));
+ EXPECT_CALL(*this, MockDone(EqualsStatus(OkClientStatus())));
+
+ ClientIdProto option_id;
+ option_id.set_identifier("o");
+
+ PerformWithElementValue(
+ &mock_action_delegate_, option_id,
+ base::BindOnce(&ActionDelegateUtilTest::MockElementAction,
+ base::Unretained(this)),
+ *element,
+ base::BindOnce(&ActionDelegateUtilTest::MockDone,
+ base::Unretained(this)));
+}
+
+TEST_F(ActionDelegateUtilTest, PerformWithMissingElementValue) {
+ auto element = std::make_unique<ElementFinder::Result>();
+
+ EXPECT_CALL(*this, MockElementAction(_, _, _)).Times(0);
+ EXPECT_CALL(
+ *this, MockDone(EqualsStatus(ClientStatus(CLIENT_ID_RESOLUTION_FAILED))));
+
+ ClientIdProto option_id;
+ option_id.set_identifier("o");
+
+ PerformWithElementValue(
+ &mock_action_delegate_, option_id,
+ base::BindOnce(&ActionDelegateUtilTest::MockElementAction,
+ base::Unretained(this)),
+ *element,
+ base::BindOnce(&ActionDelegateUtilTest::MockDone,
+ base::Unretained(this)));
+}
+
} // namespace
} // namespace action_delegate_util
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/action_test_utils.cc b/chromium/components/autofill_assistant/browser/actions/action_test_utils.cc
index 1533284343b..7151cb12274 100644
--- a/chromium/components/autofill_assistant/browser/actions/action_test_utils.cc
+++ b/chromium/components/autofill_assistant/browser/actions/action_test_utils.cc
@@ -69,5 +69,28 @@ ElementFinder::Result MockFindElement(MockWebController& web_controller,
return expected_result;
}
+ValueExpressionBuilder::ValueExpressionBuilder() = default;
+
+ValueExpressionBuilder& ValueExpressionBuilder::addChunk(
+ const std::string& text) {
+ value_expression.add_chunk()->set_text(text);
+ return *this;
+}
+
+ValueExpressionBuilder& ValueExpressionBuilder::addChunk(int key) {
+ value_expression.add_chunk()->set_key(key);
+ return *this;
+}
+
+ValueExpressionBuilder& ValueExpressionBuilder::addChunk(
+ autofill::ServerFieldType field) {
+ value_expression.add_chunk()->set_key(static_cast<int>(field));
+ return *this;
+}
+
+ValueExpression ValueExpressionBuilder::toProto() {
+ return value_expression;
+}
+
} // namespace test_util
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/action_test_utils.h b/chromium/components/autofill_assistant/browser/actions/action_test_utils.h
index 2f5d3bb975f..d9fc6b1b96c 100644
--- a/chromium/components/autofill_assistant/browser/actions/action_test_utils.h
+++ b/chromium/components/autofill_assistant/browser/actions/action_test_utils.h
@@ -5,6 +5,8 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_ACTION_TEST_UTILS_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_ACTION_TEST_UTILS_H_
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill_assistant/browser/action_value.pb.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
#include "components/autofill_assistant/browser/selector.h"
#include "components/autofill_assistant/browser/web/element_finder.h"
@@ -43,7 +45,24 @@ ElementFinder::Result MockFindElement(MockWebController& web_controller,
const Selector& selector,
int times = 1);
+struct ValueExpressionBuilder {
+ public:
+ ValueExpressionBuilder();
+
+ ValueExpressionBuilder(const ValueExpressionBuilder&) = delete;
+ ValueExpressionBuilder& operator=(const ValueExpressionBuilder&) = delete;
+
+ ValueExpressionBuilder& addChunk(const std::string& text);
+ ValueExpressionBuilder& addChunk(int key);
+ ValueExpressionBuilder& addChunk(autofill::ServerFieldType field);
+
+ ValueExpression toProto();
+
+ private:
+ ValueExpression value_expression;
+};
+
} // namespace test_util
} // namespace autofill_assistant
-#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_ACTION_UNITTEST_HELPER_H_
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_ACTION_TEST_UTILS_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/action_unittest.cc
index ef61427185d..b10b3f9e411 100644
--- a/chromium/components/autofill_assistant/browser/actions/action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/action_unittest.cc
@@ -6,6 +6,7 @@
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
+#include "base/time/time_override.h"
#include "components/autofill_assistant/browser/actions/action_test_utils.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
#include "components/autofill_assistant/browser/selector.h"
@@ -117,4 +118,4 @@ TEST_F(FakeActionTest, SlowWarningShownTest) {
}
} // namespace
-} // namespace autofill_assistant \ No newline at end of file
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/check_element_tag_action.cc b/chromium/components/autofill_assistant/browser/actions/check_element_tag_action.cc
new file mode 100644
index 00000000000..287142fc3e0
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/check_element_tag_action.cc
@@ -0,0 +1,71 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/check_element_tag_action.h"
+
+#include "base/strings/string_util.h"
+#include "components/autofill_assistant/browser/actions/action_delegate.h"
+#include "components/autofill_assistant/browser/client_status.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/element_store.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
+
+namespace autofill_assistant {
+
+CheckElementTagAction::CheckElementTagAction(ActionDelegate* delegate,
+ const ActionProto& proto)
+ : Action(delegate, proto) {
+ DCHECK(proto_.has_check_element_tag());
+}
+
+CheckElementTagAction::~CheckElementTagAction() = default;
+
+void CheckElementTagAction::InternalProcessAction(
+ ProcessActionCallback callback) {
+ callback_ = std::move(callback);
+
+ ClientStatus element_status = delegate_->GetElementStore()->GetElement(
+ proto_.check_element_tag().client_id().identifier(), &element_);
+ if (!element_status.ok()) {
+ EndAction(element_status);
+ return;
+ }
+
+ delegate_->GetWebController()->GetElementTag(
+ element_, base::BindOnce(&CheckElementTagAction::OnGetElementTag,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CheckElementTagAction::OnGetElementTag(const ClientStatus& status,
+ const std::string& actual_tag) {
+ if (!status.ok()) {
+ EndAction(status);
+ return;
+ }
+
+ std::string lower_tag = base::ToLowerASCII(actual_tag);
+ for (const std::string& tag : proto_.check_element_tag().any_of_tag()) {
+ if (base::ToLowerASCII(tag) == lower_tag) {
+ EndAction(OkClientStatus());
+ return;
+ }
+ }
+
+ VLOG(2) << "Expected " << proto_.check_element_tag().client_id().identifier()
+ << " to have one of the following tags: "
+ << base::JoinString(
+ std::vector<std::string>(
+ proto_.check_element_tag().any_of_tag().begin(),
+ proto_.check_element_tag().any_of_tag().end()),
+ ", ")
+ << ", but was " << actual_tag;
+ EndAction(ClientStatus(ELEMENT_MISMATCH));
+}
+
+void CheckElementTagAction::EndAction(const ClientStatus& status) {
+ UpdateProcessedAction(status);
+ std::move(callback_).Run(std::move(processed_action_proto_));
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/check_element_tag_action.h b/chromium/components/autofill_assistant/browser/actions/check_element_tag_action.h
new file mode 100644
index 00000000000..2c1d84a49d7
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/check_element_tag_action.h
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CHECK_ELEMENT_TAG_ACTION_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CHECK_ELEMENT_TAG_ACTION_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "components/autofill_assistant/browser/actions/action.h"
+#include "components/autofill_assistant/browser/client_status.h"
+#include "components/autofill_assistant/browser/dom_action.pb.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/element_finder.h"
+
+namespace autofill_assistant {
+
+// Action to check whether or not an element matches the expected set of tags.
+class CheckElementTagAction : public Action {
+ public:
+ explicit CheckElementTagAction(ActionDelegate* delegate,
+ const ActionProto& proto);
+ ~CheckElementTagAction() override;
+
+ CheckElementTagAction(const CheckElementTagAction&) = delete;
+ CheckElementTagAction& operator=(const CheckElementTagAction&) = delete;
+
+ private:
+ // Overrides Action:
+ void InternalProcessAction(ProcessActionCallback callback) override;
+
+ void OnGetElementTag(const ClientStatus& status, const std::string& tag);
+
+ void EndAction(const ClientStatus& status);
+
+ ElementFinder::Result element_;
+ ProcessActionCallback callback_;
+
+ base::WeakPtrFactory<CheckElementTagAction> weak_ptr_factory_{this};
+};
+
+} // namespace autofill_assistant
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CHECK_ELEMENT_TAG_ACTION_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/check_element_tag_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/check_element_tag_action_unittest.cc
new file mode 100644
index 00000000000..63cc0d7a73f
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/check_element_tag_action_unittest.cc
@@ -0,0 +1,98 @@
+// Copyright 2021 The Chromium Authors. 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/check_element_tag_action.h"
+
+#include "base/guid.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "components/autofill_assistant/browser/actions/action_test_utils.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/dom_action.pb.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/element_finder.h"
+#include "components/autofill_assistant/browser/web/element_store.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+namespace {
+
+using ::base::test::RunOnceCallback;
+using ::testing::_;
+using ::testing::Pointee;
+using ::testing::Property;
+using ::testing::Return;
+
+const char kClientId[] = "select";
+
+class CheckElementTagActionTest : public testing::Test {
+ public:
+ CheckElementTagActionTest() {}
+
+ void SetUp() override {
+ ON_CALL(mock_action_delegate_, GetWebController)
+ .WillByDefault(Return(&mock_web_controller_));
+
+ proto_.mutable_client_id()->set_identifier(kClientId);
+ }
+
+ protected:
+ void Run() {
+ ActionProto action_proto;
+ *action_proto.mutable_check_element_tag() = proto_;
+ CheckElementTagAction action(&mock_action_delegate_, action_proto);
+ action.ProcessAction(callback_.Get());
+ }
+
+ MockActionDelegate mock_action_delegate_;
+ MockWebController mock_web_controller_;
+ base::MockCallback<Action::ProcessActionCallback> callback_;
+ CheckElementTagProto proto_;
+};
+
+TEST_F(CheckElementTagActionTest, UnknownElementFails) {
+ EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
+ CLIENT_ID_RESOLUTION_FAILED))));
+ Run();
+}
+
+TEST_F(CheckElementTagActionTest, SucceedsForMatchingTagCaseInsensitive) {
+ ElementFinder::Result element;
+ element.dom_object.object_data.object_id = "e";
+ mock_action_delegate_.GetElementStore()->AddElement(kClientId,
+ element.dom_object);
+
+ EXPECT_CALL(mock_web_controller_, GetElementTag(EqualsElement(element), _))
+ .WillOnce(RunOnceCallback<1>(OkClientStatus(), "TAG"));
+
+ proto_.add_any_of_tag("other");
+ proto_.add_any_of_tag("tag");
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ Run();
+}
+
+TEST_F(CheckElementTagActionTest, FailsForNoMatchingTags) {
+ ElementFinder::Result element;
+ element.dom_object.object_data.object_id = "e";
+ mock_action_delegate_.GetElementStore()->AddElement(kClientId,
+ element.dom_object);
+
+ EXPECT_CALL(mock_web_controller_, GetElementTag(EqualsElement(element), _))
+ .WillOnce(RunOnceCallback<1>(OkClientStatus(), "TAG"));
+
+ proto_.add_any_of_tag("DIV");
+ proto_.add_any_of_tag("P");
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ELEMENT_MISMATCH))));
+ Run();
+}
+
+} // namespace
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/check_option_element_action.cc b/chromium/components/autofill_assistant/browser/actions/check_option_element_action.cc
new file mode 100644
index 00000000000..848c5929fb2
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/check_option_element_action.cc
@@ -0,0 +1,61 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/check_option_element_action.h"
+
+#include "components/autofill_assistant/browser/actions/action_delegate.h"
+#include "components/autofill_assistant/browser/client_status.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/element_store.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
+
+namespace autofill_assistant {
+
+CheckOptionElementAction::CheckOptionElementAction(ActionDelegate* delegate,
+ const ActionProto& proto)
+ : Action(delegate, proto) {
+ DCHECK(proto_.has_check_option_element());
+}
+
+CheckOptionElementAction::~CheckOptionElementAction() = default;
+
+void CheckOptionElementAction::InternalProcessAction(
+ ProcessActionCallback callback) {
+ callback_ = std::move(callback);
+
+ ClientStatus select_status = delegate_->GetElementStore()->GetElement(
+ proto_.check_option_element().select_id().identifier(), &select_);
+ if (!select_status.ok()) {
+ EndAction(select_status);
+ return;
+ }
+
+ ClientStatus option_status = delegate_->GetElementStore()->GetElement(
+ proto_.check_option_element().option_id().identifier(), &option_);
+ if (!option_status.ok()) {
+ EndAction(option_status);
+ return;
+ }
+
+ delegate_->GetWebController()->CheckSelectedOptionElement(
+ option_, select_,
+ base::BindOnce(&CheckOptionElementAction::OnCheckSelectedOptionElement,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CheckOptionElementAction::OnCheckSelectedOptionElement(
+ const ClientStatus& status) {
+ processed_action_proto_->mutable_check_option_element_result()->set_match(
+ status.ok());
+ EndAction(proto_.check_option_element().mismatch_should_fail()
+ ? status
+ : OkClientStatus());
+}
+
+void CheckOptionElementAction::EndAction(const ClientStatus& status) {
+ UpdateProcessedAction(status);
+ std::move(callback_).Run(std::move(processed_action_proto_));
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/check_option_element_action.h b/chromium/components/autofill_assistant/browser/actions/check_option_element_action.h
new file mode 100644
index 00000000000..dae59b427c5
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/check_option_element_action.h
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CHECK_OPTION_ELEMENT_ACTION_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CHECK_OPTION_ELEMENT_ACTION_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "components/autofill_assistant/browser/actions/action.h"
+#include "components/autofill_assistant/browser/client_status.h"
+#include "components/autofill_assistant/browser/dom_action.pb.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/element_finder.h"
+
+namespace autofill_assistant {
+
+// Action to check an <option> element inside a <select> element.
+class CheckOptionElementAction : public Action {
+ public:
+ explicit CheckOptionElementAction(ActionDelegate* delegate,
+ const ActionProto& proto);
+ ~CheckOptionElementAction() override;
+
+ CheckOptionElementAction(const CheckOptionElementAction&) = delete;
+ CheckOptionElementAction& operator=(const CheckOptionElementAction&) = delete;
+
+ private:
+ // Overrides Action:
+ void InternalProcessAction(ProcessActionCallback callback) override;
+
+ void OnCheckSelectedOptionElement(const ClientStatus& status);
+
+ void EndAction(const ClientStatus& status);
+
+ ElementFinder::Result select_;
+ ElementFinder::Result option_;
+ ProcessActionCallback callback_;
+
+ base::WeakPtrFactory<CheckOptionElementAction> weak_ptr_factory_{this};
+};
+
+} // namespace autofill_assistant
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CHECK_OPTION_ELEMENT_ACTION_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/check_option_element_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/check_option_element_action_unittest.cc
new file mode 100644
index 00000000000..f18f4b9985d
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/check_option_element_action_unittest.cc
@@ -0,0 +1,153 @@
+// Copyright 2021 The Chromium Authors. 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/check_option_element_action.h"
+
+#include "base/guid.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "components/autofill_assistant/browser/actions/action_test_utils.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/dom_action.pb.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/element_finder.h"
+#include "components/autofill_assistant/browser/web/element_store.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+namespace {
+
+using ::base::test::RunOnceCallback;
+using ::testing::_;
+using ::testing::Pointee;
+using ::testing::Property;
+using ::testing::Return;
+
+const char kSelectId[] = "select";
+const char kOptionId[] = "option";
+
+class CheckOptionElementActionTest : public testing::Test {
+ public:
+ CheckOptionElementActionTest() {}
+
+ void SetUp() override {
+ ON_CALL(mock_action_delegate_, GetWebController)
+ .WillByDefault(Return(&mock_web_controller_));
+
+ proto_.mutable_select_id()->set_identifier(kSelectId);
+ proto_.mutable_option_id()->set_identifier(kOptionId);
+ }
+
+ protected:
+ void Run() {
+ ActionProto action_proto;
+ *action_proto.mutable_check_option_element() = proto_;
+ CheckOptionElementAction action(&mock_action_delegate_, action_proto);
+ action.ProcessAction(callback_.Get());
+ }
+
+ MockActionDelegate mock_action_delegate_;
+ MockWebController mock_web_controller_;
+ base::MockCallback<Action::ProcessActionCallback> callback_;
+ CheckOptionElementProto proto_;
+};
+
+TEST_F(CheckOptionElementActionTest, UnknownSelectElementFails) {
+ EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
+ CLIENT_ID_RESOLUTION_FAILED))));
+ Run();
+}
+
+TEST_F(CheckOptionElementActionTest, UnknownOptionElementFails) {
+ ElementFinder::Result select;
+ mock_action_delegate_.GetElementStore()->AddElement(kSelectId,
+ select.dom_object);
+
+ EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
+ CLIENT_ID_RESOLUTION_FAILED))));
+ Run();
+}
+
+TEST_F(CheckOptionElementActionTest, SucceedsForMatchingOption) {
+ ElementFinder::Result select;
+ select.dom_object.object_data.object_id = "select";
+ mock_action_delegate_.GetElementStore()->AddElement(kSelectId,
+ select.dom_object);
+ ElementFinder::Result option;
+ option.dom_object.object_data.object_id = "option";
+ mock_action_delegate_.GetElementStore()->AddElement(kOptionId,
+ option.dom_object);
+
+ EXPECT_CALL(mock_web_controller_,
+ CheckSelectedOptionElement(EqualsElement(option),
+ EqualsElement(select), _))
+ .WillOnce(RunOnceCallback<2>(OkClientStatus()));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(
+ AllOf(Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(&ProcessedActionProto::check_option_element_result,
+ AllOf(Property(&CheckOptionElementProto::Result::match,
+ true)))))));
+ Run();
+}
+
+TEST_F(CheckOptionElementActionTest, DoesNotFailForMismatch) {
+ ElementFinder::Result select;
+ select.dom_object.object_data.object_id = "select";
+ mock_action_delegate_.GetElementStore()->AddElement(kSelectId,
+ select.dom_object);
+ ElementFinder::Result option;
+ option.dom_object.object_data.object_id = "option";
+ mock_action_delegate_.GetElementStore()->AddElement(kOptionId,
+ option.dom_object);
+
+ EXPECT_CALL(mock_web_controller_,
+ CheckSelectedOptionElement(EqualsElement(option),
+ EqualsElement(select), _))
+ .WillOnce(RunOnceCallback<2>(ClientStatus(ELEMENT_MISMATCH)));
+
+ proto_.set_mismatch_should_fail(false);
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(
+ AllOf(Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(&ProcessedActionProto::check_option_element_result,
+ AllOf(Property(&CheckOptionElementProto::Result::match,
+ false)))))));
+ Run();
+}
+
+TEST_F(CheckOptionElementActionTest, FailsForMismatchIfSpecified) {
+ ElementFinder::Result select;
+ select.dom_object.object_data.object_id = "select";
+ mock_action_delegate_.GetElementStore()->AddElement(kSelectId,
+ select.dom_object);
+ ElementFinder::Result option;
+ option.dom_object.object_data.object_id = "option";
+ mock_action_delegate_.GetElementStore()->AddElement(kOptionId,
+ option.dom_object);
+
+ EXPECT_CALL(mock_web_controller_,
+ CheckSelectedOptionElement(EqualsElement(option),
+ EqualsElement(select), _))
+ .WillOnce(RunOnceCallback<2>(ClientStatus(ELEMENT_MISMATCH)));
+
+ proto_.set_mismatch_should_fail(true);
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(
+ AllOf(Property(&ProcessedActionProto::status, ELEMENT_MISMATCH),
+ Property(&ProcessedActionProto::check_option_element_result,
+ AllOf(Property(&CheckOptionElementProto::Result::match,
+ false)))))));
+ Run();
+}
+
+} // namespace
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action.cc b/chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action.cc
new file mode 100644
index 00000000000..312c58227c4
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action.cc
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/clear_persistent_ui_action.h"
+#include "components/autofill_assistant/browser/actions/action_delegate.h"
+#include "components/autofill_assistant/browser/client_status.h"
+
+namespace autofill_assistant {
+
+ClearPersistentUiAction::ClearPersistentUiAction(ActionDelegate* delegate,
+ const ActionProto& proto)
+ : Action(delegate, proto) {
+ DCHECK(proto_.has_clear_persistent_ui());
+}
+
+ClearPersistentUiAction::~ClearPersistentUiAction() = default;
+
+void ClearPersistentUiAction::InternalProcessAction(
+ ProcessActionCallback callback) {
+ delegate_->ClearPersistentGenericUi();
+ UpdateProcessedAction(OkClientStatus());
+ std::move(callback).Run(std::move(processed_action_proto_));
+}
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action.h b/chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action.h
new file mode 100644
index 00000000000..efacf7405dc
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action.h
@@ -0,0 +1,29 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CLEAR_PERSISTENT_UI_ACTION_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CLEAR_PERSISTENT_UI_ACTION_H_
+
+#include "base/callback.h"
+#include "components/autofill_assistant/browser/actions/action.h"
+
+namespace autofill_assistant {
+
+// Action to show generic UI in the sheet until dismissed.
+class ClearPersistentUiAction : public Action {
+ public:
+ explicit ClearPersistentUiAction(ActionDelegate* delegate,
+ const ActionProto& proto);
+ ~ClearPersistentUiAction() override;
+
+ ClearPersistentUiAction(const ClearPersistentUiAction&) = delete;
+ ClearPersistentUiAction& operator=(const ClearPersistentUiAction&) = delete;
+
+ private:
+ // Overrides Action:
+ void InternalProcessAction(ProcessActionCallback callback) override;
+};
+
+} // namespace autofill_assistant
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CLEAR_PERSISTENT_UI_ACTION_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action_unittest.cc
new file mode 100644
index 00000000000..d999b931384
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/clear_persistent_ui_action_unittest.cc
@@ -0,0 +1,45 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/clear_persistent_ui_action.h"
+
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+namespace {
+
+using ::testing::Pointee;
+using ::testing::Property;
+
+class ClearPersistentUiActionTest : public testing::Test {
+ public:
+ ClearPersistentUiActionTest() {}
+
+ protected:
+ void Run() {
+ ActionProto action_proto;
+ action_proto.mutable_clear_persistent_ui();
+ auto action = std::make_unique<ClearPersistentUiAction>(
+ &mock_action_delegate_, action_proto);
+ action->ProcessAction(callback_.Get());
+ }
+
+ MockActionDelegate mock_action_delegate_;
+ base::MockCallback<Action::ProcessActionCallback> callback_;
+};
+
+TEST_F(ClearPersistentUiActionTest, ClearUi) {
+ EXPECT_CALL(mock_action_delegate_, ClearPersistentGenericUi);
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+
+ Run();
+}
+} // namespace
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/click_action.h b/chromium/components/autofill_assistant/browser/actions/click_action.h
index e5809fafb8f..9cf0da04fa4 100644
--- a/chromium/components/autofill_assistant/browser/actions/click_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/click_action.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CLICK_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_CLICK_ACTION_H_
-#include <string>
-#include <vector>
-
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/actions/action.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/click_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/click_action_unittest.cc
index 07d9e130f83..5da446d82bf 100644
--- a/chromium/components/autofill_assistant/browser/actions/click_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/click_action_unittest.cc
@@ -43,8 +43,10 @@ class ClickActionTest : public testing::Test {
base::TimeDelta::FromSeconds(0)));
ON_CALL(mock_web_controller_, CheckOnTop(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus()));
- ON_CALL(mock_action_delegate_, ClickOrTapElement(_, _, _))
+ ON_CALL(mock_web_controller_, ClickOrTapElement(_, _, _))
.WillByDefault(RunOnceCallback<2>(OkClientStatus()));
+ ON_CALL(mock_web_controller_, JsClickElement(_, _))
+ .WillByDefault(RunOnceCallback<1>(OkClientStatus()));
}
protected:
@@ -105,7 +107,7 @@ TEST_F(ClickActionTest, CheckExpectedCallChain) {
.WillOnce(RunOnceCallback<3>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
EXPECT_CALL(
- mock_action_delegate_,
+ mock_web_controller_,
ClickOrTapElement(ClickType::CLICK, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(
@@ -126,10 +128,9 @@ TEST_F(ClickActionTest, JavaScriptClickSkipsWaitForElementStable) {
EXPECT_CALL(mock_web_controller_, WaitUntilElementIsStable(_, _, _, _))
.Times(0);
EXPECT_CALL(mock_web_controller_, CheckOnTop(_, _)).Times(0);
- EXPECT_CALL(mock_action_delegate_,
- ClickOrTapElement(ClickType::JAVASCRIPT,
- EqualsElement(expected_element), _))
- .WillOnce(RunOnceCallback<2>(OkClientStatus()));
+ EXPECT_CALL(mock_web_controller_,
+ JsClickElement(EqualsElement(expected_element), _))
+ .WillOnce(RunOnceCallback<1>(OkClientStatus()));
EXPECT_CALL(
callback_,
@@ -170,7 +171,7 @@ TEST_F(ClickActionTest, RequireCheckOnTop) {
EXPECT_CALL(mock_web_controller_,
CheckOnTop(EqualsElement(expected_element), _));
EXPECT_CALL(
- mock_action_delegate_,
+ mock_web_controller_,
ClickOrTapElement(ClickType::TAP, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
@@ -196,7 +197,7 @@ TEST_F(ClickActionTest, OptionalCheckOnTop) {
EXPECT_CALL(mock_web_controller_,
CheckOnTop(EqualsElement(expected_element), _));
EXPECT_CALL(
- mock_action_delegate_,
+ mock_web_controller_,
ClickOrTapElement(ClickType::TAP, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
@@ -221,7 +222,7 @@ TEST_F(ClickActionTest, RequiredCheckOnTopFails) {
.WillOnce(RunOnceCallback<1>(NotOnTopStatus()));
// The action must not tap.
- EXPECT_CALL(mock_action_delegate_, ClickOrTapElement(_, _, _)).Times(0);
+ EXPECT_CALL(mock_web_controller_, ClickOrTapElement(_, _, _)).Times(0);
ProcessedActionProto result;
EXPECT_CALL(callback_, Run(_)).WillOnce(testing::SaveArgPointee<0>(&result));
@@ -249,7 +250,7 @@ TEST_F(ClickActionTest, OptionalCheckOnTopFails) {
// The action must tap anyway.
EXPECT_CALL(
- mock_action_delegate_,
+ mock_web_controller_,
ClickOrTapElement(ClickType::TAP, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
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
index bbe01848c3a..ac694f3e124 100644
--- a/chromium/components/autofill_assistant/browser/actions/collect_user_data_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/collect_user_data_action.cc
@@ -152,10 +152,10 @@ bool IsValidDateTimeRangeProto(
}
bool IsValidDateTimeRange(
- const base::Optional<autofill_assistant::DateProto>& start_date,
- const base::Optional<int> start_timeslot,
- const base::Optional<autofill_assistant::DateProto> end_date,
- const base::Optional<int> end_timeslot,
+ const absl::optional<autofill_assistant::DateProto>& start_date,
+ const absl::optional<int> start_timeslot,
+ const absl::optional<autofill_assistant::DateProto> end_date,
+ const absl::optional<int> end_timeslot,
const CollectUserDataOptions& collect_user_data_options) {
if (!collect_user_data_options.request_date_time_range) {
return true;
@@ -441,6 +441,10 @@ CollectUserDataAction::~CollectUserDataAction() {
}
}
+bool CollectUserDataAction::ShouldInterruptOnPause() const {
+ return true;
+}
+
void CollectUserDataAction::InternalProcessAction(
ProcessActionCallback callback) {
callback_ = std::move(callback);
@@ -506,12 +510,12 @@ void CollectUserDataAction::OnGetLogins(
login_option.sublabel_accessibility_hint(),
login_option.preselection_priority(),
login_option.has_info_popup()
- ? base::make_optional(login_option.info_popup())
- : base::nullopt,
+ ? absl::make_optional(login_option.info_popup())
+ : absl::nullopt,
login_option.has_edit_button_content_description()
- ? base::make_optional(
+ ? absl::make_optional(
login_option.edit_button_content_description())
- : base::nullopt);
+ : absl::nullopt);
login_details_map_.emplace(
identifier, std::make_unique<LoginDetails>(
login_option.choose_automatically_if_no_stored_login(),
@@ -595,14 +599,16 @@ void CollectUserDataAction::OnShowToUser(UserData* user_data,
// Clear previously selected info, if requested.
if (proto_.collect_user_data().clear_previous_credit_card_selection()) {
- user_data->selected_card_.reset();
+ delegate_->GetUserModel()->SetSelectedCreditCard(/* card= */ nullptr,
+ user_data);
}
if (proto_.collect_user_data().clear_previous_login_selection()) {
user_data->selected_login_.reset();
}
for (const auto& profile_name :
proto_.collect_user_data().clear_previous_profile_selection()) {
- user_data->selected_addresses_.erase(profile_name);
+ delegate_->GetUserModel()->SetSelectedAutofillProfile(
+ profile_name, /* profile= */ nullptr, user_data);
}
// Add available profiles and start listening.
@@ -804,19 +810,19 @@ bool CollectUserDataAction::CreateOptionsFromProto() {
login_option.custom().label(),
login_option.sublabel(),
login_option.has_sublabel_accessibility_hint()
- ? base::make_optional(
+ ? absl::make_optional(
login_option.sublabel_accessibility_hint())
- : base::nullopt,
+ : absl::nullopt,
login_option.has_preselection_priority()
? login_option.preselection_priority()
: -1,
login_option.has_info_popup()
- ? base::make_optional(login_option.info_popup())
- : base::nullopt,
+ ? absl::make_optional(login_option.info_popup())
+ : absl::nullopt,
login_option.has_edit_button_content_description()
- ? base::make_optional(
+ ? absl::make_optional(
login_option.edit_button_content_description())
- : base::nullopt};
+ : absl::nullopt};
collect_user_data_options_->login_choices.emplace_back(
std::move(choice));
login_details_map_.emplace(
@@ -1019,7 +1025,7 @@ bool CollectUserDataAction::IsUserDataComplete(
user_data.selected_address(options.shipping_address_name);
return IsCompleteContact(selected_profile, options) &&
IsCompleteShippingAddress(shipping_address, options) &&
- IsCompleteCreditCard(user_data.selected_card_.get(), billing_address,
+ IsCompleteCreditCard(user_data.selected_card(), billing_address,
options) &&
IsValidLoginChoice(user_data.login_choice_identifier_, options) &&
IsValidTermsChoice(user_data.terms_and_conditions_, options) &&
@@ -1050,10 +1056,10 @@ int CollectUserDataAction::CompareDates(const DateProto& first,
// TODO(b/148448649): Move to dedicated helper namespace.
// static
bool CollectUserDataAction::SanitizeDateTimeRange(
- base::Optional<DateProto>* start_date,
- base::Optional<int>* start_timeslot,
- base::Optional<DateProto>* end_date,
- base::Optional<int>* end_timeslot,
+ absl::optional<DateProto>* start_date,
+ absl::optional<int>* start_timeslot,
+ absl::optional<DateProto>* end_date,
+ absl::optional<int>* end_timeslot,
const CollectUserDataOptions& collect_user_data_options,
bool change_start) {
if (!collect_user_data_options.request_date_time_range) {
@@ -1119,10 +1125,10 @@ bool CollectUserDataAction::SanitizeDateTimeRange(
void CollectUserDataAction::WriteProcessedAction(UserData* user_data,
const UserModel* user_model) {
if (proto().collect_user_data().request_payment_method() &&
- user_data->selected_card_) {
+ user_data->selected_card()) {
std::string card_issuer_network =
autofill::data_util::GetPaymentRequestData(
- user_data->selected_card_->network())
+ user_data->selected_card()->network())
.basic_card_issuer_network;
processed_action_proto_->mutable_collect_user_data_result()
->set_card_issuer_network(card_issuer_network);
@@ -1275,11 +1281,9 @@ void CollectUserDataAction::UpdatePersonalDataManagerProfiles(
}
if (!found_profile && selected_profile != nullptr) {
- auto it = user_data->selected_addresses_.find(
- collect_user_data_options_->contact_details_name);
- if (it != user_data->selected_addresses_.end()) {
- user_data->selected_addresses_.erase(it);
- }
+ delegate_->GetUserModel()->SetSelectedAutofillProfile(
+ collect_user_data_options_->contact_details_name,
+ /* profile= */ nullptr, user_data);
}
if (!user_data->has_selected_address(
@@ -1290,19 +1294,18 @@ void CollectUserDataAction::UpdatePersonalDataManagerProfiles(
int default_selection = GetDefaultContactProfile(
*collect_user_data_options_, user_data->available_profiles_);
if (default_selection != -1) {
- user_data->selected_addresses_.emplace(
+ delegate_->GetUserModel()->SetSelectedAutofillProfile(
collect_user_data_options_->contact_details_name,
MakeUniqueFromProfile(
- *(user_data->available_profiles_[default_selection])));
+ *(user_data->available_profiles_[default_selection])),
+ user_data);
}
}
if (!found_shipping_address && shipping_address != nullptr) {
- auto it = user_data->selected_addresses_.find(
- collect_user_data_options_->shipping_address_name);
- if (it != user_data->selected_addresses_.end()) {
- user_data->selected_addresses_.erase(it);
- }
+ delegate_->GetUserModel()->SetSelectedAutofillProfile(
+ collect_user_data_options_->shipping_address_name,
+ /* profile= */ nullptr, user_data);
}
if (!user_data->has_selected_address(
collect_user_data_options_->shipping_address_name) &&
@@ -1310,10 +1313,11 @@ void CollectUserDataAction::UpdatePersonalDataManagerProfiles(
int default_selection = GetDefaultAddressProfile(
*collect_user_data_options_, user_data->available_profiles_);
if (default_selection != -1) {
- user_data->selected_addresses_.emplace(
+ delegate_->GetUserModel()->SetSelectedAutofillProfile(
collect_user_data_options_->shipping_address_name,
MakeUniqueFromProfile(
- *(user_data->available_profiles_[default_selection])));
+ *(user_data->available_profiles_[default_selection])),
+ user_data);
}
}
@@ -1354,35 +1358,37 @@ void CollectUserDataAction::UpdatePersonalDataManagerCards(
user_data->available_payment_instruments_.emplace_back(
std::move(payment_instrument));
- if (user_data->selected_card_ != nullptr &&
- card->Compare(*user_data->selected_card_) == 0) {
+ if (user_data->selected_card() != nullptr &&
+ card->Compare(*user_data->selected_card()) == 0) {
found_card = true;
}
}
}
if (!found_card) {
- user_data->selected_card_.reset();
- auto it = user_data->selected_addresses_.find(
- collect_user_data_options_->billing_address_name);
- if (it != user_data->selected_addresses_.end()) {
- user_data->selected_addresses_.erase(it);
- }
+ delegate_->GetUserModel()->SetSelectedCreditCard(/* card= */ nullptr,
+ user_data);
+ delegate_->GetUserModel()->SetSelectedAutofillProfile(
+ collect_user_data_options_->billing_address_name,
+ /* profile= */ nullptr, user_data);
}
- if (user_data->selected_card_ == nullptr &&
+ if (user_data->selected_card() == nullptr &&
collect_user_data_options_->request_payment_method) {
int default_selection = GetDefaultPaymentInstrument(
*collect_user_data_options_, user_data->available_payment_instruments_);
if (default_selection != -1) {
const auto& default_payment_instrument =
user_data->available_payment_instruments_[default_selection];
- user_data->selected_card_ = std::make_unique<autofill::CreditCard>(
- *(default_payment_instrument->card));
+ delegate_->GetUserModel()->SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(
+ *(default_payment_instrument->card)),
+ user_data);
if (default_payment_instrument->billing_address != nullptr) {
- user_data->selected_addresses_.emplace(
+ delegate_->GetUserModel()->SetSelectedAutofillProfile(
collect_user_data_options_->billing_address_name,
std::make_unique<autofill::AutofillProfile>(
- *(default_payment_instrument->billing_address)));
+ *(default_payment_instrument->billing_address)),
+ user_data);
}
}
}
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
index d5e75b7f782..efb42492955 100644
--- a/chromium/components/autofill_assistant/browser/actions/collect_user_data_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/collect_user_data_action.h
@@ -11,13 +11,13 @@
#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_assistant/browser/actions/action.h"
#include "components/autofill_assistant/browser/user_data.h"
#include "components/autofill_assistant/browser/user_model.h"
#include "components/autofill_assistant/browser/website_login_manager.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
class UserModel;
@@ -30,6 +30,9 @@ class CollectUserDataAction : public Action,
const ActionProto& proto);
~CollectUserDataAction() override;
+ // Overrides Action:
+ bool ShouldInterruptOnPause() const override;
+
// From autofill::PersonalDataManagerObserver.
void OnPersonalDataChanged() override;
@@ -41,10 +44,10 @@ class CollectUserDataAction : public Action,
// Ensures that |end| is > |start| by modifying either |start| or |end|,
// depending on |change_start|. Returns true if changes were performed.
static bool SanitizeDateTimeRange(
- base::Optional<DateProto>* start_date,
- base::Optional<int>* start_timeslot,
- base::Optional<DateProto>* end_date,
- base::Optional<int>* end_timeslot,
+ absl::optional<DateProto>* start_date,
+ absl::optional<int>* start_timeslot,
+ absl::optional<DateProto>* end_date,
+ absl::optional<int>* end_timeslot,
const CollectUserDataOptions& collect_user_data_options,
bool change_start);
@@ -63,7 +66,7 @@ class CollectUserDataAction : public Action,
bool choose_automatically_if_no_stored_login;
std::string payload;
// Only for Chrome PWM login details.
- base::Optional<WebsiteLoginManager::Login> login;
+ absl::optional<WebsiteLoginManager::Login> login;
};
void InternalProcessAction(ProcessActionCallback callback) override;
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
index c801ae1ce86..a3e768eb5ec 100644
--- 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
@@ -18,8 +18,11 @@
#include "components/autofill_assistant/browser/mock_personal_data_manager.h"
#include "components/autofill_assistant/browser/mock_website_login_manager.h"
#include "components/autofill_assistant/browser/test_util.h"
+#include "components/autofill_assistant/browser/user_data_util.h"
#include "components/autofill_assistant/browser/user_model.h"
#include "components/strings/grit/components_strings.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -48,16 +51,20 @@ using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::Invoke;
using ::testing::IsSupersetOf;
+using ::testing::NotNull;
using ::testing::Property;
using ::testing::Return;
using ::testing::SizeIs;
using ::testing::StrEq;
using ::testing::UnorderedElementsAre;
-class CollectUserDataActionTest : public content::RenderViewHostTestHarness {
+class CollectUserDataActionTest : public testing::Test {
public:
void SetUp() override {
- RenderViewHostTestHarness::SetUp();
+ web_contents_ = content::WebContentsTester::CreateTestWebContents(
+ &browser_context_, nullptr);
+ content::WebContentsTester::For(web_contents_.get())
+ ->SetLastCommittedURL(GURL(kFakeUrl));
ON_CALL(mock_action_delegate_, GetPersonalDataManager)
.WillByDefault(Return(&mock_personal_data_manager_));
@@ -65,6 +72,8 @@ class CollectUserDataActionTest : public content::RenderViewHostTestHarness {
.WillByDefault(Return(&mock_website_login_manager_));
ON_CALL(mock_action_delegate_, GetUserData)
.WillByDefault(Return(&user_data_));
+ ON_CALL(mock_action_delegate_, GetUserModel)
+ .WillByDefault(Return(&user_model_));
ON_CALL(mock_action_delegate_, WriteUserData(_))
.WillByDefault(Invoke(
[this](base::OnceCallback<void(UserData*, UserData::FieldChange*)>
@@ -78,21 +87,46 @@ class CollectUserDataActionTest : public content::RenderViewHostTestHarness {
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, &user_model_);
}));
-
ON_CALL(mock_website_login_manager_, OnGetLoginsForUrl(_, _))
.WillByDefault(
RunOnceCallback<1>(std::vector<WebsiteLoginManager::Login>{
WebsiteLoginManager::Login(GURL(kFakeUrl), kFakeUsername)}));
ON_CALL(mock_website_login_manager_, OnGetPasswordForLogin(_, _))
.WillByDefault(RunOnceCallback<1>(true, kFakePassword));
-
- content::WebContentsTester::For(web_contents())
- ->SetLastCommittedURL(GURL(kFakeUrl));
ON_CALL(mock_action_delegate_, GetWebContents())
- .WillByDefault(Return(web_contents()));
+ .WillByDefault(Return(web_contents_.get()));
+ }
+
+ void ExpectSelectedProfileMatches(const std::string& profile_name,
+ const autofill::AutofillProfile* profile) {
+ if (profile == nullptr) {
+ EXPECT_EQ(user_data_.selected_address(profile_name), nullptr);
+ EXPECT_EQ(user_model_.GetSelectedAutofillProfile(profile_name), nullptr);
+ return;
+ }
+
+ EXPECT_EQ(user_data_.selected_address(profile_name)->Compare(*profile), 0);
+ EXPECT_EQ(
+ user_model_.GetSelectedAutofillProfile(profile_name)->Compare(*profile),
+ 0);
+ }
+
+ void ExpectSelectedCardMatches(const autofill::CreditCard* card) {
+ if (card == nullptr) {
+ EXPECT_EQ(user_data_.selected_card(), nullptr);
+ EXPECT_EQ(user_model_.GetSelectedCreditCard(), nullptr);
+ return;
+ }
+
+ EXPECT_EQ(user_data_.selected_card()->Compare(*card), 0);
+ EXPECT_EQ(user_model_.GetSelectedCreditCard()->Compare(*card), 0);
}
protected:
+ content::BrowserTaskEnvironment task_environment_;
+ content::RenderViewHostTestEnabler rvh_test_enabler_;
+ content::TestBrowserContext browser_context_;
+ std::unique_ptr<content::WebContents> web_contents_;
base::MockCallback<Action::ProcessActionCallback> callback_;
MockPersonalDataManager mock_personal_data_manager_;
MockWebsiteLoginManager mock_website_login_manager_;
@@ -607,8 +641,10 @@ TEST_F(CollectUserDataActionTest, SelectContactDetails) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- user_data_.selected_addresses_[kMemoryLocation] =
- std::make_unique<autofill::AutofillProfile>(contact_profile);
+ user_model_.SetSelectedAutofillProfile(
+ kMemoryLocation,
+ std::make_unique<autofill::AutofillProfile>(contact_profile),
+ &user_data_);
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, &user_model_);
}));
@@ -738,10 +774,13 @@ TEST_F(CollectUserDataActionTest, SelectPaymentMethod) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- user_data_.selected_card_ =
- std::make_unique<autofill::CreditCard>(credit_card);
- user_data_.selected_addresses_["billing_address"] =
- std::make_unique<autofill::AutofillProfile>(billing_profile);
+ user_model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(credit_card),
+ &user_data_);
+ user_model_.SetSelectedAutofillProfile(
+ "billing_address",
+ std::make_unique<autofill::AutofillProfile>(billing_profile),
+ &user_data_);
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, &user_model_);
}));
@@ -768,8 +807,7 @@ TEST_F(CollectUserDataActionTest, SelectPaymentMethod) {
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
- EXPECT_EQ(user_data_.selected_card_.get() != nullptr, true);
- EXPECT_THAT(user_data_.selected_card_->Compare(credit_card), Eq(0));
+ ExpectSelectedCardMatches(&credit_card);
}
TEST_F(CollectUserDataActionTest, SelectShippingAddress) {
@@ -787,8 +825,10 @@ TEST_F(CollectUserDataActionTest, SelectShippingAddress) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- user_data_.selected_addresses_[kMemoryLocation] =
- std::make_unique<autofill::AutofillProfile>(shipping_address);
+ user_model_.SetSelectedAutofillProfile(
+ kMemoryLocation,
+ std::make_unique<autofill::AutofillProfile>(shipping_address),
+ &user_data_);
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, &user_model_);
}));
@@ -814,9 +854,9 @@ TEST_F(CollectUserDataActionTest, SelectShippingAddress) {
action.ProcessAction(callback_.Get());
EXPECT_TRUE(user_data_.has_selected_address(kMemoryLocation));
- EXPECT_EQ(user_data_.selected_addresses_[kMemoryLocation]->Compare(
- shipping_address),
- 0);
+ EXPECT_EQ(
+ user_data_.selected_address(kMemoryLocation)->Compare(shipping_address),
+ 0);
}
TEST_F(CollectUserDataActionTest, MandatoryPostalCodeWithoutErrorMessageFails) {
@@ -842,42 +882,36 @@ TEST_F(CollectUserDataActionTest, ContactDetailsCanHandleUtf8) {
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"));
+ contact_profile.SetRawInfo(autofill::ServerFieldType::NAME_FULL, u"艾丽森");
+ contact_profile.SetRawInfo(autofill::ServerFieldType::EMAIL_ADDRESS,
+ u"艾丽森@example.com");
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- user_data_.selected_addresses_[kMemoryLocation] =
- std::make_unique<autofill::AutofillProfile>(contact_profile);
+ user_model_.SetSelectedAutofillProfile(
+ kMemoryLocation,
+ std::make_unique<autofill::AutofillProfile>(contact_profile),
+ &user_data_);
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, &user_model_);
}));
- 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"))))));
+ EXPECT_CALL(callback_,
+ Run(Pointee(AllOf(
+ Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(&ProcessedActionProto::collect_user_data_result,
+ Property(&CollectUserDataResultProto::payer_email,
+ "艾丽森@example.com"))))));
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
EXPECT_EQ(user_data_.has_selected_address(kMemoryLocation), true);
auto* profile = user_data_.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"));
+ EXPECT_EQ(profile->GetRawInfo(autofill::NAME_FULL), u"艾丽森");
+ EXPECT_EQ(profile->GetRawInfo(autofill::EMAIL_ADDRESS),
+ u"艾丽森@example.com");
}
TEST_F(CollectUserDataActionTest, UserDataComplete_Contact) {
@@ -887,15 +921,20 @@ TEST_F(CollectUserDataActionTest, UserDataComplete_Contact) {
options));
options.contact_details_name = "profile";
- user_data.selected_addresses_["profile"] =
- std::make_unique<autofill::AutofillProfile>(base::GenerateGUID(),
- kFakeUrl);
+ autofill::AutofillProfile profile(base::GenerateGUID(), kFakeUrl);
+ user_model_.SetSelectedAutofillProfile(
+ "profile", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
+
options.request_payer_email = true;
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
- user_data.selected_addresses_["profile"]->SetRawInfo(
- autofill::ServerFieldType::EMAIL_ADDRESS, u"joedoe@example.com");
+ profile.SetRawInfo(autofill::ServerFieldType::EMAIL_ADDRESS,
+ u"joedoe@example.com");
+ user_model_.SetSelectedAutofillProfile(
+ "profile", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
@@ -903,8 +942,10 @@ TEST_F(CollectUserDataActionTest, UserDataComplete_Contact) {
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
- user_data.selected_addresses_["profile"]->SetRawInfo(
- autofill::ServerFieldType::NAME_FULL, u"Joe Doe");
+ profile.SetRawInfo(autofill::ServerFieldType::NAME_FULL, u"Joe Doe");
+ user_model_.SetSelectedAutofillProfile(
+ "profile", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
@@ -912,8 +953,11 @@ TEST_F(CollectUserDataActionTest, UserDataComplete_Contact) {
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
- user_data.selected_addresses_["profile"]->SetRawInfo(
- autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER, u"+1 23 456 789 01");
+ profile.SetRawInfo(autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER,
+ u"+1 23 456 789 01");
+ user_model_.SetSelectedAutofillProfile(
+ "profile", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
}
@@ -928,39 +972,49 @@ TEST_F(CollectUserDataActionTest, UserDataComplete_Payment) {
options));
// Valid credit card, but no billing address.
- user_data.selected_card_ =
- std::make_unique<autofill::CreditCard>(base::GenerateGUID(), kFakeUrl);
- autofill::test::SetCreditCardInfo(user_data.selected_card_.get(),
- "Marion Mitchell", "4111 1111 1111 1111",
- "01", "2050",
+ autofill::CreditCard card(base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetCreditCardInfo(&card, "Marion Mitchell",
+ "4111 1111 1111 1111", "01", "2050",
/* billing_address_id = */ "");
+ user_model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(card), &user_data);
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
// Incomplete billing address.
- user_data.selected_addresses_["billing_address"] =
- std::make_unique<autofill::AutofillProfile>(base::GenerateGUID(),
- kFakeUrl);
- autofill::test::SetProfileInfo(
- user_data.selected_addresses_["billing_address"].get(), "Marion",
- "Mitchell", "Morrison", "marion@me.xyz", "Fox", "123 Zoo St.", "unit 5",
- "Hollywood", "CA",
- /* zipcode = */ "", "US", "16505678910");
- user_data.selected_card_->set_billing_address_id(
- user_data.selected_addresses_["billing_address"]->guid());
+ autofill::AutofillProfile profile(base::GenerateGUID(), kFakeUrl);
+ user_model_.SetSelectedAutofillProfile(
+ "billing_address", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
+
+ autofill::test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
+ "marion@me.xyz", "Fox", "123 Zoo St.",
+ "unit 5", "Hollywood", "CA",
+ /* zipcode = */ "", "US", "16505678910");
+
+ user_model_.SetSelectedAutofillProfile(
+ "billing_address", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
+ card.set_billing_address_id(
+ user_data.selected_address("billing_address")->guid());
+ user_model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(card), &user_data);
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
- user_data.selected_addresses_["billing_address"]->SetRawInfo(
- autofill::ADDRESS_HOME_ZIP, u"91601");
+ profile.SetRawInfo(autofill::ADDRESS_HOME_ZIP, u"91601");
+ user_model_.SetSelectedAutofillProfile(
+ "billing_address", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
// Zip code is optional in Argentinian address.
- user_data.selected_addresses_["billing_address"]->SetRawInfo(
- autofill::ADDRESS_HOME_ZIP, u"");
- user_data.selected_addresses_["billing_address"]->SetRawInfo(
- autofill::ADDRESS_HOME_COUNTRY, u"AR");
+ profile.SetRawInfo(autofill::ADDRESS_HOME_ZIP, u"");
+ profile.SetRawInfo(autofill::ADDRESS_HOME_COUNTRY, u"AR");
+ user_model_.SetSelectedAutofillProfile(
+ "billing_address", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
@@ -968,14 +1022,17 @@ TEST_F(CollectUserDataActionTest, UserDataComplete_Payment) {
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
- user_data.selected_addresses_["billing_address"]->SetRawInfo(
- autofill::ADDRESS_HOME_ZIP, u"B1675");
+ profile.SetRawInfo(autofill::ADDRESS_HOME_ZIP, u"B1675");
+ user_model_.SetSelectedAutofillProfile(
+ "billing_address", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
// Expired credit card.
- user_data.selected_card_->SetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR,
- u"2019");
+ card.SetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR, u"2019");
+ user_model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(card), &user_data);
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
}
@@ -1019,19 +1076,24 @@ TEST_F(CollectUserDataActionTest, UserDataComplete_ShippingAddress) {
options));
// Incomplete address.
- user_data.selected_addresses_["shipping_address"] =
- std::make_unique<autofill::AutofillProfile>(base::GenerateGUID(),
- kFakeUrl);
- autofill::test::SetProfileInfo(
- user_data.selected_addresses_["shipping_address"].get(), "Marion",
- "Mitchell", "Morrison", "marion@me.xyz", "Fox", "123 Zoo St.", "unit 5",
- "Hollywood", "CA",
- /* zipcode = */ "", "US", "16505678910");
+ autofill::AutofillProfile profile(base::GenerateGUID(), kFakeUrl);
+ user_model_.SetSelectedAutofillProfile(
+ "shipping_address", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
+ autofill::test::SetProfileInfo(&profile, "Marion", "Mitchell", "Morrison",
+ "marion@me.xyz", "Fox", "123 Zoo St.",
+ "unit 5", "Hollywood", "CA",
+ /* zipcode = */ "", "US", "16505678910");
+ user_model_.SetSelectedAutofillProfile(
+ "shipping_address", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
EXPECT_FALSE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
- user_data.selected_addresses_["shipping_address"]->SetRawInfo(
- autofill::ADDRESS_HOME_ZIP, u"91601");
+ profile.SetRawInfo(autofill::ADDRESS_HOME_ZIP, u"91601");
+ user_model_.SetSelectedAutofillProfile(
+ "shipping_address", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
EXPECT_TRUE(CollectUserDataAction::IsUserDataComplete(user_data, user_model_,
options));
}
@@ -1468,21 +1530,21 @@ TEST_F(CollectUserDataActionTest, AllowedBasicCardNetworks) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([this](CollectUserDataOptions* collect_user_data_options) {
- user_data_.selected_addresses_["billing_address"] =
- std::make_unique<autofill::AutofillProfile>(
- base::GenerateGUID(), kFakeUrl);
- autofill::test::SetProfileInfo(
- user_data_.selected_addresses_["billing_address"].get(),
- "Marion", "Mitchell", "Morrison", "marion@me.xyz", "Fox",
- "123 Zoo St.", "unit 5", "Hollywood", "CA", "96043", "US",
- "16505678910");
-
- user_data_.selected_card_ = std::make_unique<autofill::CreditCard>(
- base::GenerateGUID(), kFakeUrl);
+ autofill::AutofillProfile profile(base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetProfileInfo(&profile, "Marion", "Mitchell",
+ "Morrison", "marion@me.xyz", "Fox",
+ "123 Zoo St.", "unit 5", "Hollywood",
+ "CA", "96043", "US", "16505678910");
+ user_model_.SetSelectedAutofillProfile(
+ "billing_address",
+ std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data_);
+ autofill::CreditCard card(base::GenerateGUID(), kFakeUrl);
autofill::test::SetCreditCardInfo(
- user_data_.selected_card_.get(), "Marion Mitchell",
- "4111 1111 1111 1111", "01", "2050",
- user_data_.selected_addresses_["billing_address"]->guid());
+ &card, "Marion Mitchell", "4111 1111 1111 1111", "01", "2050",
+ user_data_.selected_address("billing_address")->guid());
+ user_model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(card), &user_data_);
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, &user_model_);
@@ -1582,8 +1644,10 @@ TEST_F(CollectUserDataActionTest, AttachesProfiles) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- user_data_.selected_addresses_[kMemoryLocation] =
- std::make_unique<autofill::AutofillProfile>(profile);
+ user_model_.SetSelectedAutofillProfile(
+ kMemoryLocation,
+ std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data_);
EXPECT_THAT(user_data_.available_profiles_, SizeIs(1));
EXPECT_EQ(user_data_.available_profiles_[0]->Compare(profile), 0);
@@ -1622,12 +1686,8 @@ TEST_F(CollectUserDataActionTest, InitialSelectsProfileAndShippingAddress) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- EXPECT_EQ(
- user_data_.selected_addresses_["profile"]->Compare(profile), 0);
- EXPECT_EQ(
- user_data_.selected_addresses_["shipping-address"]->Compare(
- profile),
- 0);
+ ExpectSelectedProfileMatches("profile", &profile);
+ ExpectSelectedProfileMatches("shipping-address", &profile);
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, nullptr);
@@ -1745,9 +1805,7 @@ TEST_F(CollectUserDataActionTest, InitialSelectsProfileFromDefaultEmail) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- EXPECT_EQ(
- user_data_.selected_addresses_["profile"]->Compare(profile_b),
- 0);
+ ExpectSelectedProfileMatches("profile", &profile_b);
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, nullptr);
@@ -1787,12 +1845,8 @@ TEST_F(CollectUserDataActionTest, KeepsSelectedProfileAndShippingAddress) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- EXPECT_EQ(
- user_data_.selected_addresses_["profile"]->Compare(profile), 0);
- EXPECT_EQ(
- user_data_.selected_addresses_["shipping_address"]->Compare(
- profile),
- 0);
+ ExpectSelectedProfileMatches("profile", &profile);
+ ExpectSelectedProfileMatches("shipping_address", &profile);
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, nullptr);
@@ -1807,10 +1861,12 @@ TEST_F(CollectUserDataActionTest, KeepsSelectedProfileAndShippingAddress) {
contact_details->set_contact_details_name("profile");
// Set previous user data.
- user_data_.selected_addresses_["profile"] =
- std::make_unique<autofill::AutofillProfile>(profile);
- user_data_.selected_addresses_["shipping_address"] =
- std::make_unique<autofill::AutofillProfile>(profile);
+ user_model_.SetSelectedAutofillProfile(
+ "profile", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data_);
+ user_model_.SetSelectedAutofillProfile(
+ "shipping_address", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data_);
EXPECT_CALL(
callback_,
@@ -1835,11 +1891,8 @@ TEST_F(CollectUserDataActionTest, ResetsContactAndShippingIfNoLongerInList) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- EXPECT_EQ(user_data_.selected_addresses_["profile"], nullptr);
- EXPECT_EQ(
- user_data_.selected_addresses_["shipping_address"]->Compare(
- profile),
- 0);
+ ExpectSelectedProfileMatches("profile", nullptr);
+ ExpectSelectedProfileMatches("shipping_address", &profile);
// Do not call the callback. We're only interested in the state.
}));
@@ -1858,10 +1911,13 @@ TEST_F(CollectUserDataActionTest, ResetsContactAndShippingIfNoLongerInList) {
"berta.west@gmail.com", "", "", "", "", "", "",
"", "");
- user_data_.selected_addresses_["profile"] =
- std::make_unique<autofill::AutofillProfile>(selected_profile);
- user_data_.selected_addresses_["shipping_address"] =
- std::make_unique<autofill::AutofillProfile>(selected_profile);
+ user_model_.SetSelectedAutofillProfile(
+ "profile", std::make_unique<autofill::AutofillProfile>(selected_profile),
+ &user_data_);
+ user_model_.SetSelectedAutofillProfile(
+ "shipping_address",
+ std::make_unique<autofill::AutofillProfile>(selected_profile),
+ &user_data_);
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
@@ -2026,11 +2082,8 @@ TEST_F(CollectUserDataActionTest, InitialSelectsCardAndAddress) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- EXPECT_EQ(user_data_.selected_card_->Compare(card_with_address), 0);
- EXPECT_EQ(
- user_data_.selected_addresses_["billing_address"]->Compare(
- billing_address),
- 0);
+ ExpectSelectedCardMatches(&card_with_address);
+ ExpectSelectedProfileMatches("billing_address", &billing_address);
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, nullptr);
@@ -2076,11 +2129,8 @@ TEST_F(CollectUserDataActionTest, KeepsSelectedCardAndAddress) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- EXPECT_EQ(user_data_.selected_card_->Compare(card_with_address), 0);
- EXPECT_EQ(
- user_data_.selected_addresses_["billing_address"]->Compare(
- billing_address),
- 0);
+ ExpectSelectedCardMatches(&card_with_address);
+ ExpectSelectedProfileMatches("billing_address", &billing_address);
std::move(collect_user_data_options->confirm_callback)
.Run(&user_data_, nullptr);
@@ -2093,10 +2143,13 @@ TEST_F(CollectUserDataActionTest, KeepsSelectedCardAndAddress) {
collect_user_data->set_billing_address_name("billing_address");
// Set previous user data.
- user_data_.selected_card_ =
- std::make_unique<autofill::CreditCard>(card_with_address);
- user_data_.selected_addresses_["billing_address"] =
- std::make_unique<autofill::AutofillProfile>(billing_address);
+ user_model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(card_with_address), &user_data_);
+
+ user_model_.SetSelectedAutofillProfile(
+ "billing_address",
+ std::make_unique<autofill::AutofillProfile>(billing_address),
+ &user_data_);
EXPECT_CALL(
callback_,
@@ -2131,9 +2184,8 @@ TEST_F(CollectUserDataActionTest, ResetsCardAndAddressIfNoLongerInList) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- EXPECT_EQ(user_data_.selected_card_, nullptr);
- EXPECT_EQ(user_data_.selected_addresses_["billing_address"],
- nullptr);
+ ExpectSelectedCardMatches(nullptr);
+ ExpectSelectedProfileMatches("billing_address", nullptr);
// Do not call the callback. We're only interested in the state.
}));
@@ -2154,10 +2206,12 @@ TEST_F(CollectUserDataActionTest, ResetsCardAndAddressIfNoLongerInList) {
&selected_address, "Berta", "", "West", "berta.west@gmail.com", "",
"Baker Street 221b", "", "London", "", "WC2N 5DU", "UK", "+44");
- user_data_.selected_card_ =
- std::make_unique<autofill::CreditCard>(selected_card);
- user_data_.selected_addresses_["billing_address"] =
- std::make_unique<autofill::AutofillProfile>(selected_address);
+ user_model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(selected_card), &user_data_);
+ user_model_.SetSelectedAutofillProfile(
+ "billing_address",
+ std::make_unique<autofill::AutofillProfile>(selected_address),
+ &user_data_);
CollectUserDataAction action(&mock_action_delegate_, action_proto);
action.ProcessAction(callback_.Get());
@@ -2275,17 +2329,11 @@ TEST_F(CollectUserDataActionTest, ClearUserDataIfRequested) {
ON_CALL(mock_action_delegate_, CollectUserData(_))
.WillByDefault(
Invoke([=](CollectUserDataOptions* collect_user_data_options) {
- EXPECT_EQ(user_data_.selected_card_->Compare(card_a), 0);
- EXPECT_EQ(
- user_data_.selected_addresses_["billing"]->Compare(address_a),
- 0);
- EXPECT_EQ(
- user_data_.selected_addresses_["contact"]->Compare(address_a),
- 0);
- EXPECT_EQ(
- user_data_.selected_addresses_["shipping"]->Compare(address_a),
- 0);
- EXPECT_EQ(user_data_.selected_login_, base::nullopt);
+ ExpectSelectedCardMatches(&card_a);
+ ExpectSelectedProfileMatches("billing", &address_a);
+ ExpectSelectedProfileMatches("contact", &address_a);
+ ExpectSelectedProfileMatches("shipping", &address_a);
+ EXPECT_EQ(user_data_.selected_login_, absl::nullopt);
// Do not call the callback. We're only interested in the state.
}));
@@ -2308,13 +2356,17 @@ TEST_F(CollectUserDataActionTest, ClearUserDataIfRequested) {
// Set previous user data to the second card/profile. If clear works
// correctly, the action should default to the first card/profile.
- user_data_.selected_card_ = std::make_unique<autofill::CreditCard>(card_b);
- user_data_.selected_addresses_["billing"] =
- std::make_unique<autofill::AutofillProfile>(address_b);
- user_data_.selected_addresses_["contact"] =
- std::make_unique<autofill::AutofillProfile>(address_b);
- user_data_.selected_addresses_["shipping"] =
- std::make_unique<autofill::AutofillProfile>(address_b);
+ user_model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(card_b), &user_data_);
+ user_model_.SetSelectedAutofillProfile(
+ "billing", std::make_unique<autofill::AutofillProfile>(address_b),
+ &user_data_);
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(address_b),
+ &user_data_);
+ user_model_.SetSelectedAutofillProfile(
+ "shipping", std::make_unique<autofill::AutofillProfile>(address_b),
+ &user_data_);
user_data_.selected_login_ =
WebsiteLoginManager::Login(GURL("http://www.example.com"), "username");
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 c4f0e50cd20..bab9c0d7621 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
@@ -44,9 +44,9 @@ class ConfigureBottomSheetActionTest : public testing::Test {
Invoke([this](ConfigureBottomSheetProto::PeekMode peek_mode) {
peek_mode_ = peek_mode;
}));
- ON_CALL(mock_action_delegate_, OnWaitForWindowHeightChange(_))
+ ON_CALL(mock_action_delegate_, WaitForWindowHeightChange(_))
.WillByDefault(Invoke(
- [this](base::OnceCallback<void(const ClientStatus&)>& callback) {
+ [this](base::OnceCallback<void(const ClientStatus&)> callback) {
on_resize_cb_ = std::move(callback);
}));
}
@@ -62,11 +62,10 @@ class ConfigureBottomSheetActionTest : public testing::Test {
*action_proto.mutable_configure_bottom_sheet() = proto_;
action_ = std::make_unique<ConfigureBottomSheetAction>(
&mock_action_delegate_, action_proto);
- action_->ProcessAction(
- base::BindOnce(base::BindLambdaForTesting(
- [&](std::unique_ptr<ProcessedActionProto> result) {
- processed_action_ = *result;
- })));
+ action_->ProcessAction(base::BindOnce(base::BindLambdaForTesting(
+ [&](std::unique_ptr<ProcessedActionProto> result) {
+ processed_action_ = *result;
+ })));
}
// Runs an action that waits for a resize.
diff --git a/chromium/components/autofill_assistant/browser/actions/dispatch_js_event_action.h b/chromium/components/autofill_assistant/browser/actions/dispatch_js_event_action.h
index 64dceb655be..3281076539d 100644
--- a/chromium/components/autofill_assistant/browser/actions/dispatch_js_event_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/dispatch_js_event_action.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_DISPATCH_JS_EVENT_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_DISPATCH_JS_EVENT_ACTION_H_
-#include <string>
-#include <vector>
-
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/actions/action.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/dispatch_js_event_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/dispatch_js_event_action_unittest.cc
index dff5ee69a60..13af1181b8f 100644
--- a/chromium/components/autofill_assistant/browser/actions/dispatch_js_event_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/dispatch_js_event_action_unittest.cc
@@ -22,7 +22,7 @@ class DispatchJsEventActionTest : public testing::Test {
DispatchJsEventActionTest() {}
void SetUp() override {
- ON_CALL(mock_action_delegate_, OnDispatchJsEvent(_))
+ ON_CALL(mock_action_delegate_, DispatchJsEvent(_))
.WillByDefault(RunOnceCallback<0>(OkClientStatus()));
}
@@ -40,7 +40,7 @@ class DispatchJsEventActionTest : public testing::Test {
};
TEST_F(DispatchJsEventActionTest, EmptyProtoSetsMessageDoesNothing) {
- EXPECT_CALL(mock_action_delegate_, OnDispatchJsEvent(_));
+ EXPECT_CALL(mock_action_delegate_, DispatchJsEvent(_));
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
diff --git a/chromium/components/autofill_assistant/browser/actions/expect_navigation_action.h b/chromium/components/autofill_assistant/browser/actions/expect_navigation_action.h
index 827026e7705..c254065afc4 100644
--- a/chromium/components/autofill_assistant/browser/actions/expect_navigation_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/expect_navigation_action.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_EXPECT_NAVIGATION_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_EXPECT_NAVIGATION_ACTION_H_
-#include <string>
-
#include "base/macros.h"
#include "components/autofill_assistant/browser/actions/action.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field.cc b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field.cc
index 1a12d5b8696..102f9e53a81 100644
--- a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field.cc
+++ b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field.cc
@@ -12,13 +12,24 @@ RequiredField::~RequiredField() = default;
RequiredField::RequiredField(const RequiredField& copy) = default;
+void RequiredField::FromProto(const RequiredFieldProto& required_field_proto) {
+ selector = Selector(required_field_proto.element());
+ proto = required_field_proto;
+}
+
bool RequiredField::ShouldFallback(bool apply_fallback) const {
- return (status == EMPTY && !value_expression.empty() &&
- !fallback_click_element.has_value()) ||
- (status != EMPTY && value_expression.empty() &&
- !fallback_click_element.has_value()) ||
- (forced && apply_fallback) ||
- (fallback_click_element.has_value() && apply_fallback);
+ return (status == EMPTY && HasValue() &&
+ !proto.has_option_element_to_click() &&
+ !(proto.is_optional() && !apply_fallback)) ||
+ (status != EMPTY && !HasValue() &&
+ !proto.has_option_element_to_click()) ||
+ (proto.forced() && apply_fallback) ||
+ (proto.has_option_element_to_click() && apply_fallback);
+}
+
+bool RequiredField::HasValue() const {
+ return !proto.value_expression().chunk().empty() ||
+ proto.has_option_comparison_value_expression_re2();
}
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field.h b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field.h
index f5713c2ff03..42fd42f642e 100644
--- a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field.h
+++ b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_FALLBACK_HANDLER_REQUIRED_FIELD_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_FALLBACK_HANDLER_REQUIRED_FIELD_H_
-#include "base/optional.h"
#include "components/autofill_assistant/browser/selector.h"
#include "components/autofill_assistant/browser/service.pb.h"
@@ -20,60 +19,21 @@ struct RequiredField {
RequiredField();
RequiredField(const RequiredField& copy);
- template <typename T>
- void FromProto(const T& required_field_proto) {
- selector = Selector(required_field_proto.element());
- value_expression = required_field_proto.value_expression();
- forced = required_field_proto.forced();
- fill_strategy = required_field_proto.fill_strategy();
- delay_in_millisecond = required_field_proto.delay_in_millisecond();
- select_strategy = required_field_proto.select_strategy();
+ void FromProto(const RequiredFieldProto& required_field_proto);
- if (required_field_proto.has_option_element_to_click()) {
- fallback_click_element =
- Selector(required_field_proto.option_element_to_click());
- click_type = required_field_proto.click_type();
- }
- }
+ // Returns true if fallback is required for this field.
+ bool ShouldFallback(bool apply_fallback) const;
+
+ // Returns whether this field has a value to fill the field with.
+ bool HasValue() const;
// The selector of the field that must be filled.
Selector selector;
- // The value expression to be filled into the field. This gets evaluated with
- // the provided data.
- std::string value_expression;
+ RequiredFieldProto proto;
// Defines whether the field is currently considered to be filled or not.
FieldValueStatus status = UNKNOWN;
-
- // This defines whether or not to overwrite a field initially filled by
- // Autofill in an attempt to fix it. Mostly used in combination with key
- // strokes for fields that e.g. have JavaScript listeners attached.
- bool forced = false;
-
- // Keyboard strategy for <input> elements to use. E.g. whether or not to use
- // key strokes.
- KeyboardValueFillStrategy fill_strategy =
- KeyboardValueFillStrategy::UNSPECIFIED_KEYBAORD_STRATEGY;
- // Optional. Only used in combination with a key strokes filling strategy.
- // Adds an artificial delay between each key stroke.
- int delay_in_millisecond = 0;
-
- // Dropdown strategy for <select> elements to use. E.g. whether to match the
- // label or the value.
- DropdownSelectStrategy select_strategy =
- DropdownSelectStrategy::UNSPECIFIED_SELECT_STRATEGY;
-
- // For JavaScript driven dropdowns. This defines the option to be clicked.
- // The selector must match a generic option, a |inner_text_pattern| will be
- // attached for matching to a unique option.
- base::Optional<Selector> fallback_click_element = base::nullopt;
- // Optional. The click type to be used for clicking JavaScript driven
- // dropdown elements.
- ClickType click_type = ClickType::NOT_SET;
-
- // Returns true if fallback is required for this field.
- bool ShouldFallback(bool apply_fallback) const;
};
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field_unittest.cc b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field_unittest.cc
index 8e285aa4a1a..2a907a3f219 100644
--- a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_field_unittest.cc
@@ -15,10 +15,27 @@ class RequiredFieldTest : public testing::Test {
void SetUp() override {}
};
+TEST_F(RequiredFieldTest, HasValue) {
+ RequiredField required_field;
+ EXPECT_FALSE(required_field.HasValue());
+
+ required_field.proto.mutable_value_expression()->add_chunk()->set_text(
+ "value");
+ EXPECT_TRUE(required_field.HasValue());
+
+ required_field.proto.mutable_value_expression()->clear_chunk();
+ ValueExpressionRegexp value_expression_re2;
+ value_expression_re2.mutable_value_expression()->add_chunk()->set_text("^$");
+ *required_field.proto.mutable_option_comparison_value_expression_re2() =
+ value_expression_re2;
+ EXPECT_TRUE(required_field.HasValue());
+}
+
TEST_F(RequiredFieldTest, ShouldFallbackForNotEmpty) {
RequiredField required_field;
required_field.status = RequiredField::NOT_EMPTY;
- required_field.value_expression = "value";
+ required_field.proto.mutable_value_expression()->add_chunk()->set_text(
+ "value");
EXPECT_FALSE(required_field.ShouldFallback(true));
EXPECT_FALSE(required_field.ShouldFallback(false));
@@ -27,7 +44,6 @@ TEST_F(RequiredFieldTest, ShouldFallbackForNotEmpty) {
TEST_F(RequiredFieldTest, ShouldFallbackForNotEmptyToBeCleared) {
RequiredField required_field;
required_field.status = RequiredField::NOT_EMPTY;
- required_field.value_expression = std::string();
EXPECT_TRUE(required_field.ShouldFallback(true));
EXPECT_TRUE(required_field.ShouldFallback(false));
@@ -36,7 +52,8 @@ TEST_F(RequiredFieldTest, ShouldFallbackForNotEmptyToBeCleared) {
TEST_F(RequiredFieldTest, ShouldFallbackForEmpty) {
RequiredField required_field;
required_field.status = RequiredField::EMPTY;
- required_field.value_expression = "value";
+ required_field.proto.mutable_value_expression()->add_chunk()->set_text(
+ "value");
EXPECT_TRUE(required_field.ShouldFallback(true));
EXPECT_TRUE(required_field.ShouldFallback(false));
@@ -44,9 +61,10 @@ TEST_F(RequiredFieldTest, ShouldFallbackForEmpty) {
TEST_F(RequiredFieldTest, ShouldFallbackForNotEmptyForced) {
RequiredField required_field;
- required_field.forced = true;
+ required_field.proto.set_forced(true);
required_field.status = RequiredField::NOT_EMPTY;
- required_field.value_expression = "value";
+ required_field.proto.mutable_value_expression()->add_chunk()->set_text(
+ "value");
EXPECT_TRUE(required_field.ShouldFallback(true));
EXPECT_FALSE(required_field.ShouldFallback(false));
@@ -55,9 +73,45 @@ TEST_F(RequiredFieldTest, ShouldFallbackForNotEmptyForced) {
TEST_F(RequiredFieldTest, ShouldFallbackForEmptyWithClick) {
RequiredField required_field;
required_field.status = RequiredField::EMPTY;
- required_field.fallback_click_element = Selector({"#element"});
+ *required_field.proto.mutable_option_element_to_click() =
+ ToSelectorProto("#element");
+
+ EXPECT_TRUE(required_field.ShouldFallback(true));
+ EXPECT_FALSE(required_field.ShouldFallback(false));
+}
+
+TEST_F(RequiredFieldTest, ShouldFallbackForEmptyOptional) {
+ RequiredField required_field;
+ required_field.proto.set_is_optional(true);
+ required_field.status = RequiredField::EMPTY;
+ required_field.proto.mutable_value_expression()->add_chunk()->set_text(
+ "value");
+
+ EXPECT_TRUE(required_field.ShouldFallback(true));
+ EXPECT_FALSE(required_field.ShouldFallback(false));
+}
+
+TEST_F(RequiredFieldTest, ShouldFallbackForEmptyWithOptionComparison) {
+ RequiredField required_field;
+ required_field.status = RequiredField::EMPTY;
+ ValueExpressionRegexp value_expression_re2;
+ value_expression_re2.mutable_value_expression()->add_chunk()->set_text("^$");
+ *required_field.proto.mutable_option_comparison_value_expression_re2() =
+ value_expression_re2;
EXPECT_TRUE(required_field.ShouldFallback(true));
+ EXPECT_TRUE(required_field.ShouldFallback(false));
+}
+
+TEST_F(RequiredFieldTest, ShouldFallbackForNotEmptyWithOptionComparison) {
+ RequiredField required_field;
+ required_field.status = RequiredField::NOT_EMPTY;
+ ValueExpressionRegexp value_expression_re2;
+ value_expression_re2.mutable_value_expression()->add_chunk()->set_text("^$");
+ *required_field.proto.mutable_option_comparison_value_expression_re2() =
+ value_expression_re2;
+
+ EXPECT_FALSE(required_field.ShouldFallback(true));
EXPECT_FALSE(required_field.ShouldFallback(false));
}
diff --git a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.cc b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.cc
index 189aad89e3d..2809d86da40 100644
--- a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.cc
+++ b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.cc
@@ -31,7 +31,9 @@ AutofillErrorInfoProto::AutofillFieldError* AddAutofillError(
->mutable_autofill_error_info()
->add_autofill_field_error();
*field_error->mutable_field() = required_field.selector.proto;
- field_error->set_value_expression(required_field.value_expression);
+ field_error->set_value_expression(
+ field_formatter::GetHumanReadableValueExpression(
+ required_field.proto.value_expression()));
return field_error;
}
@@ -61,13 +63,60 @@ void FillStatusDetailsWithNotClearedField(const RequiredField& required_field,
field_error->set_filled_after_clear(true);
}
-ClientStatus& UpdateClientStatusForIncomplete(ClientStatus& status) {
+ClientStatus& ErrorStatusWithDefault(ClientStatus& status) {
if (status.ok()) {
status.set_proto_status(AUTOFILL_INCOMPLETE);
}
return status;
}
+ClientStatus GetRe2Value(const RequiredField& required_field,
+ const std::map<std::string, std::string>& mappings,
+ bool use_contains,
+ std::string* re2_value,
+ bool* case_sensitive) {
+ if (required_field.proto.has_option_comparison_value_expression_re2()) {
+ ClientStatus status = field_formatter::FormatExpression(
+ required_field.proto.option_comparison_value_expression_re2()
+ .value_expression(),
+ mappings,
+ /* quote_meta= */ true, re2_value);
+ if (!status.ok()) {
+ return status;
+ }
+ *case_sensitive =
+ required_field.proto.option_comparison_value_expression_re2()
+ .case_sensitive();
+ return OkClientStatus();
+ }
+
+ std::string re2;
+ ClientStatus status =
+ field_formatter::FormatExpression(required_field.proto.value_expression(),
+ mappings, /* quote_meta= */ true, &re2);
+ if (!status.ok()) {
+ return status;
+ }
+
+ if (use_contains) {
+ re2_value->assign(re2);
+ } else {
+ switch (required_field.proto.select_strategy()) {
+ case UNSPECIFIED_SELECT_STRATEGY:
+ case LABEL_STARTS_WITH:
+ // This is the legacy default.
+ re2_value->assign(base::StrCat({"^", re2}));
+ break;
+ case VALUE_MATCH:
+ case LABEL_MATCH:
+ re2_value->assign(base::StrCat({"^", re2, "$"}));
+ break;
+ }
+ }
+ *case_sensitive = false;
+ return OkClientStatus();
+}
+
} // namespace
RequiredFieldsFallbackHandler::~RequiredFieldsFallbackHandler() = default;
@@ -113,7 +162,7 @@ void RequiredFieldsFallbackHandler::CheckAllRequiredFields(
// First run (with fallback) we skip checking forced fields, since we
// overwrite them anyway. Second run (without fallback) forced fields should
// be checked.
- if (required_fields_[i].forced && apply_fallback) {
+ if (required_fields_[i].proto.forced() && apply_fallback) {
continue;
}
@@ -121,7 +170,7 @@ void RequiredFieldsFallbackHandler::CheckAllRequiredFields(
// elements are JS driven structures that in most cases lack a "value"
// attribute. We define a successful click on the element as successfully
// filling the form field.
- if (required_fields_[i].fallback_click_element.has_value()) {
+ if (required_fields_[i].proto.has_option_element_to_click()) {
continue;
}
@@ -156,7 +205,7 @@ void RequiredFieldsFallbackHandler::OnCheckRequiredFieldsDone(
if (required_field.ShouldFallback(apply_fallback)) {
should_fallback = true;
if (!apply_fallback) {
- if (required_field.value_expression.empty()) {
+ if (required_field.proto.value_expression().chunk().empty()) {
VLOG(1) << "Field was filled after attempting to clear it: "
<< required_field.selector;
FillStatusDetailsWithNotClearedField(required_field, &client_status_);
@@ -166,7 +215,6 @@ void RequiredFieldsFallbackHandler::OnCheckRequiredFieldsDone(
FillStatusDetailsWithEmptyField(required_field, &client_status_);
}
}
- break;
}
}
@@ -178,37 +226,26 @@ void RequiredFieldsFallbackHandler::OnCheckRequiredFieldsDone(
if (!apply_fallback) {
// Validation failed and we don't want to try the fallback.
std::move(status_update_callback_)
- .Run(UpdateClientStatusForIncomplete(client_status_));
+ .Run(ErrorStatusWithDefault(client_status_));
return;
}
- // If there are any fallbacks for the empty fields, set them, otherwise fail
- // immediately.
- bool has_fallbacks = false;
- bool has_empty_value = false;
for (const RequiredField& required_field : required_fields_) {
- if (!required_field.ShouldFallback(/* apply_fallback= */ true)) {
+ if (required_field.proto.value_expression().chunk().empty() ||
+ !required_field.ShouldFallback(/* apply_fallback= */ true)) {
continue;
}
- if (required_field.value_expression.empty()) {
- has_fallbacks = true;
- } else if (field_formatter::FormatString(required_field.value_expression,
- fallback_values_)
- .has_value()) {
- has_fallbacks = true;
- } else {
- VLOG(3) << "Field has no fallback data: " << required_field.selector
- << " " << required_field.value_expression;
+ std::string tmp;
+ if (!field_formatter::FormatExpression(
+ required_field.proto.value_expression(), fallback_values_,
+ /* quote_meta= */ false, &tmp)
+ .ok()) {
+ DVLOG(3) << "Field has no fallback data: " << required_field.selector
+ << " " << required_field.proto.value_expression();
FillStatusDetailsWithMissingFallbackData(required_field, &client_status_);
- has_empty_value = true;
}
}
- if (!has_fallbacks || has_empty_value) {
- std::move(status_update_callback_)
- .Run(UpdateClientStatusForIncomplete(client_status_));
- return;
- }
// Set the fallback values and check again.
SetFallbackFieldValuesSequentially(0);
@@ -238,42 +275,38 @@ void RequiredFieldsFallbackHandler::SetFallbackFieldValuesSequentially(
&RequiredFieldsFallbackHandler::SetFallbackFieldValuesSequentially,
weak_ptr_factory_.GetWeakPtr(), required_fields_index + 1);
- if (required_field.value_expression.empty()) {
- action_delegate_util::SetFieldValue(
- action_delegate_, required_field.selector, "",
- required_field.fill_strategy, required_field.delay_in_millisecond,
- base::BindOnce(&RequiredFieldsFallbackHandler::OnSetFallbackFieldValue,
- weak_ptr_factory_.GetWeakPtr(), required_field,
- std::move(set_next_field),
- /* element= */ nullptr));
+ std::string fallback_value;
+ ClientStatus format_status = field_formatter::FormatExpression(
+ required_field.proto.value_expression(), fallback_values_,
+ /* quote_meta= */ false, &fallback_value);
+ if (!format_status.ok()) {
+ // Skip optional field, fail otherwise.
+ if (required_field.proto.is_optional()) {
+ std::move(set_next_field).Run();
+ } else {
+ std::move(status_update_callback_)
+ .Run(ErrorStatusWithDefault(client_status_));
+ }
return;
}
- auto fallback_value = field_formatter::FormatString(
- required_field.value_expression, fallback_values_);
- DCHECK(fallback_value.has_value());
-
- if (required_field.fallback_click_element.has_value()) {
- ClickType click_type = required_field.click_type;
- if (click_type == ClickType::NOT_SET) {
- // default: TAP
- click_type = ClickType::TAP;
- }
- action_delegate_util::ClickOrTapElement(
- action_delegate_, required_field.selector, click_type,
- /* on_top= */ SKIP_STEP,
- base::BindOnce(
- &RequiredFieldsFallbackHandler::OnClickOrTapFallbackElement,
- weak_ptr_factory_.GetWeakPtr(), *fallback_value, required_field,
- std::move(set_next_field)));
- return;
+ if (required_field.proto.has_option_element_to_click()) {
+ FillJsDrivenDropdown(fallback_value, required_field,
+ std::move(set_next_field));
+ } else {
+ FillFormField(fallback_value, required_field, std::move(set_next_field));
}
+}
+void RequiredFieldsFallbackHandler::FillFormField(
+ const std::string& value,
+ const RequiredField& required_field,
+ base::OnceCallback<void()> set_next_field) {
action_delegate_->FindElement(
required_field.selector,
base::BindOnce(&RequiredFieldsFallbackHandler::OnFindElement,
- weak_ptr_factory_.GetWeakPtr(), *fallback_value,
- required_field, std::move(set_next_field)));
+ weak_ptr_factory_.GetWeakPtr(), value, required_field,
+ std::move(set_next_field)));
}
void RequiredFieldsFallbackHandler::OnFindElement(
@@ -286,9 +319,15 @@ void RequiredFieldsFallbackHandler::OnFindElement(
FillStatusDetailsWithError(required_field, element_status.proto_status(),
&client_status_);
- // Fallback failed: we stop the script without checking the other fields.
- std::move(status_update_callback_)
- .Run(UpdateClientStatusForIncomplete(client_status_));
+ // Element to operate on does not exist. We either continue or stop the
+ // script without checking the other fields.
+ if (required_field.proto.is_optional() &&
+ element_status.proto_status() == ELEMENT_RESOLUTION_FAILED) {
+ std::move(set_next_field).Run();
+ } else {
+ std::move(status_update_callback_)
+ .Run(ErrorStatusWithDefault(client_status_));
+ }
return;
}
@@ -312,51 +351,91 @@ void RequiredFieldsFallbackHandler::OnGetFallbackFieldElementTag(
DVLOG(3) << "Status for element tag was "
<< element_tag_status.proto_status();
}
+ const ElementFinder::Result* element_ptr = element.get();
+ base::OnceCallback<void(const ClientStatus&)> on_set_field_value =
+ base::BindOnce(&RequiredFieldsFallbackHandler::OnSetFallbackFieldValue,
+ weak_ptr_factory_.GetWeakPtr(), required_field,
+ std::move(set_next_field), std::move(element));
- VLOG(3) << "Setting fallback value for " << required_field.selector << " ("
- << element_tag << ")";
+ DVLOG(3) << "Setting fallback value for " << required_field.selector << " ("
+ << element_tag << ")";
if (element_tag == kSelectElementTag) {
- SelectOptionProto::OptionComparisonAttribute option_comparison_attribute;
- std::string re2;
- switch (required_field.select_strategy) {
- case UNSPECIFIED_SELECT_STRATEGY:
- case LABEL_STARTS_WITH:
- // This is the legacy default.
- option_comparison_attribute = SelectOptionProto::LABEL;
- re2 = base::StrCat({"^", re2::RE2::QuoteMeta(value)});
- break;
- case LABEL_MATCH:
- option_comparison_attribute = SelectOptionProto::LABEL;
- re2 = base::StrCat({"^", re2::RE2::QuoteMeta(value), "$"});
- break;
- case VALUE_MATCH:
- option_comparison_attribute = SelectOptionProto::VALUE;
- re2 = base::StrCat({"^", re2::RE2::QuoteMeta(value), "$"});
- break;
+ std::string re2_value;
+ bool case_sensitive = false;
+ ClientStatus re2_status =
+ GetRe2Value(required_field, fallback_values_, /* use_contains= */ false,
+ &re2_value, &case_sensitive);
+ if (!re2_status.ok() || re2_value.empty()) {
+ // TODO(b/184814284): Selecting an empty value of a dropdown is somewhat
+ // undefined behaviour. Set the value attribute as a best guess.
+ action_delegate_->GetWebController()->SetValueAttribute(
+ std::string(), *element_ptr, std::move(on_set_field_value));
+ return;
+ }
+
+ SelectOptionProto::OptionComparisonAttribute option_comparison_attribute =
+ required_field.proto.option_comparison_attribute();
+ if (option_comparison_attribute == SelectOptionProto::NOT_SET) {
+ switch (required_field.proto.select_strategy()) {
+ case UNSPECIFIED_SELECT_STRATEGY:
+ case LABEL_STARTS_WITH:
+ case LABEL_MATCH:
+ option_comparison_attribute = SelectOptionProto::LABEL;
+ break;
+ case VALUE_MATCH:
+ option_comparison_attribute = SelectOptionProto::VALUE;
+ break;
+ }
}
- const ElementFinder::Result* element_ptr = element.get();
action_delegate_->GetWebController()->SelectOption(
- re2, /* case_sensitive= */ false, option_comparison_attribute,
- *element_ptr,
- base::BindOnce(&RequiredFieldsFallbackHandler::OnSetFallbackFieldValue,
- weak_ptr_factory_.GetWeakPtr(), required_field,
- std::move(set_next_field), std::move(element)));
+ re2_value, case_sensitive, option_comparison_attribute,
+ /* strict= */ false, *element_ptr, std::move(on_set_field_value));
return;
}
- const ElementFinder::Result* element_ptr = element.get();
action_delegate_util::PerformSetFieldValue(
- action_delegate_, value, required_field.fill_strategy,
- required_field.delay_in_millisecond, *element_ptr,
- base::BindOnce(&RequiredFieldsFallbackHandler::OnSetFallbackFieldValue,
- weak_ptr_factory_.GetWeakPtr(), required_field,
- std::move(set_next_field), std::move(element)));
+ action_delegate_, value, required_field.proto.fill_strategy(),
+ required_field.proto.delay_in_millisecond(), *element_ptr,
+ std::move(on_set_field_value));
}
-void RequiredFieldsFallbackHandler::OnClickOrTapFallbackElement(
+void RequiredFieldsFallbackHandler::FillJsDrivenDropdown(
const std::string& value,
const RequiredField& required_field,
+ base::OnceCallback<void()> set_next_field) {
+ DCHECK(required_field.proto.has_option_element_to_click());
+
+ std::string re2_value;
+ bool case_sensitive = false;
+ ClientStatus re2_status =
+ GetRe2Value(required_field, fallback_values_, /* use_contains= */ true,
+ &re2_value, &case_sensitive);
+ if (!re2_status.ok() || re2_value.empty()) {
+ // TODO(b/184814284): Selecting an empty value in a JS driven dropdown is
+ // undefined behaviour. Do nothing.
+ std::move(set_next_field).Run();
+ return;
+ }
+
+ ClickType click_type = required_field.proto.click_type();
+ if (click_type == ClickType::NOT_SET) {
+ // default: TAP
+ click_type = ClickType::TAP;
+ }
+ action_delegate_util::ClickOrTapElement(
+ action_delegate_, required_field.selector, click_type,
+ /* on_top= */ SKIP_STEP,
+ base::BindOnce(
+ &RequiredFieldsFallbackHandler::OnClickOrTapFallbackElement,
+ weak_ptr_factory_.GetWeakPtr(), re2_value, case_sensitive,
+ required_field, std::move(set_next_field)));
+}
+
+void RequiredFieldsFallbackHandler::OnClickOrTapFallbackElement(
+ const std::string& re2_value,
+ bool case_sensitive,
+ const RequiredField& required_field,
base::OnceCallback<void()> set_next_field,
const ClientStatus& element_click_status) {
if (!element_click_status.ok()) {
@@ -365,13 +444,14 @@ void RequiredFieldsFallbackHandler::OnClickOrTapFallbackElement(
// Fallback failed: we stop the script without checking the other fields.
std::move(status_update_callback_)
- .Run(UpdateClientStatusForIncomplete(client_status_));
+ .Run(ErrorStatusWithDefault(client_status_));
return;
}
- DCHECK(required_field.fallback_click_element.has_value());
- Selector value_selector = required_field.fallback_click_element.value();
- value_selector.MatchingInnerText(re2::RE2::QuoteMeta(value));
+ DCHECK(required_field.proto.has_option_element_to_click());
+ Selector value_selector =
+ Selector(required_field.proto.option_element_to_click());
+ value_selector.MatchingInnerText(re2_value, case_sensitive);
action_delegate_->ShortWaitForElementWithSlowWarning(
value_selector,
@@ -393,11 +473,11 @@ void RequiredFieldsFallbackHandler::OnShortWaitForElement(
// Fallback failed: we stop the script without checking the other fields.
std::move(status_update_callback_)
- .Run(UpdateClientStatusForIncomplete(client_status_));
+ .Run(ErrorStatusWithDefault(client_status_));
return;
}
- ClickType click_type = required_field.click_type;
+ ClickType click_type = required_field.proto.click_type();
if (click_type == ClickType::NOT_SET) {
// default: TAP
click_type = ClickType::TAP;
@@ -423,7 +503,7 @@ void RequiredFieldsFallbackHandler::OnSetFallbackFieldValue(
// Fallback failed: we stop the script without checking the other fields.
std::move(status_update_callback_)
- .Run(UpdateClientStatusForIncomplete(client_status_));
+ .Run(ErrorStatusWithDefault(client_status_));
return;
}
diff --git a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.h b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.h
index 2b1b2ef7e90..4889744b193 100644
--- a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.h
+++ b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.h
@@ -60,6 +60,11 @@ class RequiredFieldsFallbackHandler {
// Sets fallback field values for empty fields.
void SetFallbackFieldValuesSequentially(size_t required_fields_index);
+ // Fill an HTML form field.
+ void FillFormField(const std::string& value,
+ const RequiredField& required_field,
+ base::OnceCallback<void()> set_next_field);
+
// Called after attempting to find one of the elements to execute a fallback
// action on.
void OnFindElement(const std::string& value,
@@ -77,8 +82,14 @@ class RequiredFieldsFallbackHandler {
const ClientStatus& element_tag_status,
const std::string& element_tag);
+ // Fill a JS driven dropdown.
+ void FillJsDrivenDropdown(const std::string& value,
+ const RequiredField& required_field,
+ base::OnceCallback<void()> set_next_field);
+
// Called after clicking a fallback element.
- void OnClickOrTapFallbackElement(const std::string& value,
+ void OnClickOrTapFallbackElement(const std::string& re2_value,
+ bool case_sensitive,
const RequiredField& required_field,
base::OnceCallback<void()> set_next_field,
const ClientStatus& element_click_status);
diff --git a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler_unittest.cc b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler_unittest.cc
index 97714ddbfca..9c6f1111c7f 100644
--- a/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler_unittest.cc
@@ -12,6 +12,7 @@
#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_assistant/browser/action_value.pb.h"
#include "components/autofill_assistant/browser/actions/action_test_utils.h"
#include "components/autofill_assistant/browser/actions/fallback_handler/required_field.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
@@ -31,10 +32,19 @@ using ::testing::InSequence;
using ::testing::Invoke;
using ::testing::Return;
-RequiredField CreateRequiredField(const std::string& value_expression,
+RequiredField CreateRequiredField(int key,
const std::vector<std::string>& selector) {
RequiredField required_field;
- required_field.value_expression = value_expression;
+ required_field.proto.mutable_value_expression()->add_chunk()->set_key(key);
+ required_field.selector = Selector(selector);
+ required_field.status = RequiredField::EMPTY;
+ return required_field;
+}
+
+RequiredField CreateRequiredField(const ValueExpression& value_expression,
+ const std::vector<std::string>& selector) {
+ RequiredField required_field;
+ *required_field.proto.mutable_value_expression() = value_expression;
required_field.selector = Selector(selector);
required_field.status = RequiredField::EMPTY;
return required_field;
@@ -90,7 +100,7 @@ TEST_F(RequiredFieldsFallbackHandlerTest, AutofillFailureGetsForwarded) {
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "value"));
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${51}", {"#card_name"})};
+ CreateRequiredField(51, {"#card_name"})};
RequiredFieldsFallbackHandler fallback_handler(required_fields, {},
&mock_action_delegate_);
@@ -111,7 +121,7 @@ TEST_F(RequiredFieldsFallbackHandlerTest,
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), std::string()));
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${51}", {"#card_name"})};
+ CreateRequiredField(51, {"#card_name"})};
RequiredFieldsFallbackHandler fallback_handler(required_fields, {},
&mock_action_delegate_);
@@ -149,9 +159,9 @@ TEST_F(RequiredFieldsFallbackHandlerTest,
.WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${51}", {"#card_name"}),
- CreateRequiredField("${52}", {"#card_number"}),
- CreateRequiredField("${-3}", {"#card_network"})};
+ CreateRequiredField(51, {"#card_name"}),
+ CreateRequiredField(52, {"#card_number"}),
+ CreateRequiredField(-3, {"#card_network"})};
std::map<std::string, std::string> fallback_values = {
{base::NumberToString(
@@ -201,8 +211,8 @@ TEST_F(RequiredFieldsFallbackHandlerTest, AddsFirstFieldFillingError) {
.WillByDefault(RunOnceCallback<2>(ClientStatus(OTHER_ACTION_STATUS)));
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${51}", {"#card_name"}),
- CreateRequiredField("${52}", {"#card_number"})};
+ CreateRequiredField(51, {"#card_name"}),
+ CreateRequiredField(52, {"#card_number"})};
std::map<std::string, std::string> fallback_values = {
{base::NumberToString(
@@ -243,8 +253,8 @@ TEST_F(RequiredFieldsFallbackHandlerTest,
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), ""));
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${51}", {"#card_name"}),
- CreateRequiredField("${52}", {"#card_number"})};
+ CreateRequiredField(51, {"#card_name"}),
+ CreateRequiredField(52, {"#card_number"})};
std::map<std::string, std::string> fallback_values = {
{base::NumberToString(
@@ -284,7 +294,7 @@ TEST_F(RequiredFieldsFallbackHandlerTest, DoesNotFallbackIfFieldsAreFilled) {
EXPECT_CALL(mock_web_controller_, SetValueAttribute(_, _, _)).Times(0);
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${51}", {"#card_name"})};
+ CreateRequiredField(51, {"#card_name"})};
RequiredFieldsFallbackHandler fallback_handler(required_fields, {},
&mock_action_delegate_);
@@ -311,7 +321,7 @@ TEST_F(RequiredFieldsFallbackHandlerTest, FillsEmptyRequiredField) {
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "John Doe"));
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${51}", {"#card_name"})};
+ CreateRequiredField(51, {"#card_name"})};
std::map<std::string, std::string> fallback_values = {
{base::NumberToString(
@@ -338,8 +348,8 @@ TEST_F(RequiredFieldsFallbackHandlerTest, FallsBackForForcedFilledField) {
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${51}", {"#card_name"})};
- required_fields[0].forced = true;
+ CreateRequiredField(51, {"#card_name"})};
+ required_fields[0].proto.set_forced(true);
std::map<std::string, std::string> fallback_values = {
{base::NumberToString(
@@ -360,8 +370,8 @@ TEST_F(RequiredFieldsFallbackHandlerTest, FailsIfForcedFieldDidNotGetFilled) {
EXPECT_CALL(mock_web_controller_, SetValueAttribute(_, _, _)).Times(0);
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${51}", {"#card_name"})};
- required_fields[0].forced = true;
+ CreateRequiredField(51, {"#card_name"})};
+ required_fields[0].proto.set_forced(true);
RequiredFieldsFallbackHandler fallback_handler(required_fields, {},
&mock_action_delegate_);
@@ -403,8 +413,12 @@ TEST_F(RequiredFieldsFallbackHandlerTest, FillsFieldWithPattern) {
.After(set_value)
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
+ ValueExpression value_expression;
+ value_expression.add_chunk()->set_key(53);
+ value_expression.add_chunk()->set_text("/");
+ value_expression.add_chunk()->set_key(55);
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${53}/${55}", {"#card_expiry"})};
+ CreateRequiredField(value_expression, {"#card_expiry"})};
std::map<std::string, std::string> fallback_values = {
{base::NumberToString(
@@ -430,8 +444,8 @@ TEST_F(RequiredFieldsFallbackHandlerTest,
EXPECT_CALL(mock_web_controller_, SetValueAttribute(_, _, _)).Times(0);
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${53}", {"#card_expiry"}),
- CreateRequiredField("${-3}", {"#card_network"})};
+ CreateRequiredField(53, {"#card_expiry"}),
+ CreateRequiredField(-3, {"#card_network"})};
std::map<std::string, std::string> fallback_values;
fallback_values.emplace(base::NumberToString(static_cast<int>(
@@ -474,7 +488,7 @@ TEST_F(RequiredFieldsFallbackHandlerTest,
TEST_F(RequiredFieldsFallbackHandlerTest, UsesSelectOptionForDropdowns) {
InSequence sequence;
- Selector expected_selector({"#year"});
+ Selector expected_selector({"#exp"});
// First validation fails.
EXPECT_CALL(mock_web_controller_,
@@ -490,24 +504,83 @@ TEST_F(RequiredFieldsFallbackHandlerTest, UsesSelectOptionForDropdowns) {
GetElementTag(EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), "SELECT"));
EXPECT_CALL(mock_web_controller_,
- SelectOption("^2050", false, SelectOptionProto::LABEL,
+ SelectOption("^05\\/2050$", /* case_sensitive= */ false,
+ SelectOptionProto::VALUE, /* strict= */ false,
EqualsElement(expected_element), _))
- .WillOnce(RunOnceCallback<4>(OkClientStatus()));
+ .WillOnce(RunOnceCallback<5>(OkClientStatus()));
// Second validation succeeds.
EXPECT_CALL(mock_web_controller_,
GetFieldValue(EqualsElement(test_util::MockFindElement(
mock_web_controller_, expected_selector)),
_))
- .WillOnce(RunOnceCallback<1>(OkClientStatus(), "2050"));
+ .WillOnce(RunOnceCallback<1>(OkClientStatus(), "05/2050"));
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${55}", {"#year"})};
+ CreateRequiredField(57, {"#exp"})};
+ required_fields[0].proto.set_select_strategy(
+ DropdownSelectStrategy::VALUE_MATCH);
std::map<std::string, std::string> fallback_values = {
{base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::CREDIT_CARD_EXP_4_DIGIT_YEAR)),
- "2050"}};
+ autofill::ServerFieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR)),
+ "05/2050"}};
+
+ RequiredFieldsFallbackHandler fallback_handler(
+ required_fields, fallback_values, &mock_action_delegate_);
+ fallback_handler.CheckAndFallbackRequiredFields(
+ OkClientStatus(), base::BindOnce([](const ClientStatus& status) {
+ EXPECT_EQ(status.proto_status(), ACTION_APPLIED);
+ }));
+}
+
+TEST_F(RequiredFieldsFallbackHandlerTest,
+ UsesSelectOptionForFullDropdownDefinition) {
+ InSequence sequence;
+
+ Selector expected_selector({"#exp"});
+
+ // First validation fails.
+ EXPECT_CALL(mock_web_controller_,
+ GetFieldValue(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
+ .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
+
+ // Fill field.
+ const ElementFinder::Result& expected_element =
+ test_util::MockFindElement(mock_action_delegate_, expected_selector);
+ EXPECT_CALL(mock_web_controller_,
+ GetElementTag(EqualsElement(expected_element), _))
+ .WillOnce(RunOnceCallback<1>(OkClientStatus(), "SELECT"));
+ EXPECT_CALL(mock_web_controller_,
+ SelectOption("^05\\/2050", /* case_sensitive= */ true,
+ SelectOptionProto::VALUE, /* strict= */ false,
+ EqualsElement(expected_element), _))
+ .WillOnce(RunOnceCallback<5>(OkClientStatus()));
+
+ // Second validation succeeds.
+ EXPECT_CALL(mock_web_controller_,
+ GetFieldValue(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
+ .WillOnce(RunOnceCallback<1>(OkClientStatus(), "05/2050"));
+
+ RequiredField required_field = CreateRequiredField(57, {"#exp"});
+ required_field.proto.set_option_comparison_attribute(
+ SelectOptionProto::VALUE);
+ ValueExpressionRegexp value_expression_re2;
+ value_expression_re2.mutable_value_expression()->add_chunk()->set_text("^");
+ value_expression_re2.mutable_value_expression()->add_chunk()->set_key(57);
+ value_expression_re2.set_case_sensitive(true);
+ *required_field.proto.mutable_option_comparison_value_expression_re2() =
+ value_expression_re2;
+ std::vector<RequiredField> required_fields = {required_field};
+
+ std::map<std::string, std::string> fallback_values = {
+ {base::NumberToString(static_cast<int>(
+ autofill::ServerFieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR)),
+ "05/2050"}};
RequiredFieldsFallbackHandler fallback_handler(
required_fields, fallback_values, &mock_action_delegate_);
@@ -522,20 +595,21 @@ TEST_F(RequiredFieldsFallbackHandlerTest, ClicksOnCustomDropdown) {
EXPECT_CALL(mock_web_controller_, SetValueAttribute(_, _, _)).Times(0);
Selector expected_main_selector({"#card_expiry"});
EXPECT_CALL(
- mock_action_delegate_,
+ mock_web_controller_,
ClickOrTapElement(ClickType::TAP,
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, expected_main_selector)),
_))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
Selector expected_option_selector({".option"});
- expected_option_selector.MatchingInnerText("08");
+ expected_option_selector.MatchingInnerText("05\\/2050",
+ /* case_sensitive= */ false);
EXPECT_CALL(mock_action_delegate_,
OnShortWaitForElement(expected_option_selector, _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
EXPECT_CALL(
- mock_action_delegate_,
+ mock_web_controller_,
ClickOrTapElement(ClickType::TAP,
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, expected_option_selector)),
@@ -543,13 +617,14 @@ TEST_F(RequiredFieldsFallbackHandlerTest, ClicksOnCustomDropdown) {
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${53}", {"#card_expiry"})};
- required_fields[0].fallback_click_element = Selector({".option"});
+ CreateRequiredField(57, {"#card_expiry"})};
+ *required_fields[0].proto.mutable_option_element_to_click() =
+ ToSelectorProto(".option");
std::map<std::string, std::string> fallback_values = {
- {base::NumberToString(
- static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH)),
- "08"}};
+ {base::NumberToString(static_cast<int>(
+ autofill::ServerFieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR)),
+ "05/2050"}};
RequiredFieldsFallbackHandler fallback_handler(
required_fields, fallback_values, &mock_action_delegate_);
@@ -565,14 +640,15 @@ TEST_F(RequiredFieldsFallbackHandlerTest, CustomDropdownClicksStopOnError) {
Selector expected_main_selector({"#card_expiry"});
Expectation main_click =
EXPECT_CALL(
- mock_action_delegate_,
+ mock_web_controller_,
ClickOrTapElement(ClickType::TAP,
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, expected_main_selector)),
_))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
Selector expected_option_selector({".option"});
- expected_option_selector.MatchingInnerText("08");
+ expected_option_selector.MatchingInnerText("05\\/2050",
+ /* case_sensitive= */ false);
EXPECT_CALL(mock_action_delegate_,
OnShortWaitForElement(expected_option_selector, _))
.WillOnce(RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED),
@@ -580,18 +656,19 @@ TEST_F(RequiredFieldsFallbackHandlerTest, CustomDropdownClicksStopOnError) {
EXPECT_CALL(mock_action_delegate_, FindElement(_, _))
.Times(0)
.After(main_click);
- EXPECT_CALL(mock_action_delegate_, ClickOrTapElement(_, _, _))
+ EXPECT_CALL(mock_web_controller_, ClickOrTapElement(_, _, _))
.Times(0)
.After(main_click);
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${53}", {"#card_expiry"})};
- required_fields[0].fallback_click_element = Selector({".option"});
+ CreateRequiredField(57, {"#card_expiry"})};
+ *required_fields[0].proto.mutable_option_element_to_click() =
+ ToSelectorProto(".option");
std::map<std::string, std::string> fallback_values = {
- {base::NumberToString(
- static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH)),
- "08"}};
+ {base::NumberToString(static_cast<int>(
+ autofill::ServerFieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR)),
+ "05/2050"}};
RequiredFieldsFallbackHandler fallback_handler(
required_fields, fallback_values, &mock_action_delegate_);
@@ -629,7 +706,7 @@ TEST_F(RequiredFieldsFallbackHandlerTest, ClearsFilledField) {
.WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), std::string()));
std::vector<RequiredField> required_fields = {
- CreateRequiredField(std::string(), {"#field"})};
+ CreateRequiredField(ValueExpression(), {"#field"})};
std::map<std::string, std::string> fallback_values;
RequiredFieldsFallbackHandler fallback_handler(
@@ -664,8 +741,10 @@ TEST_F(RequiredFieldsFallbackHandlerTest, SkipsForcedFieldCheckOnFirstRun) {
_))
.WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "value"));
- auto forced_field = CreateRequiredField("value", {"#forced_field"});
- forced_field.forced = true;
+ ValueExpression value_expression;
+ value_expression.add_chunk()->set_text("value");
+ auto forced_field = CreateRequiredField(value_expression, {"#forced_field"});
+ forced_field.proto.set_forced(true);
std::vector<RequiredField> required_fields = {forced_field};
std::map<std::string, std::string> fallback_values;
@@ -695,15 +774,15 @@ TEST_F(RequiredFieldsFallbackHandlerTest,
.Times(2)
.WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "value"));
EXPECT_CALL(mock_web_controller_,
- SetValueAttribute(_,
+ SetValueAttribute("John Doe",
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, card_name_selector)),
_))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
std::vector<RequiredField> required_fields = {
- CreateRequiredField("${51}", {"#card_name"}),
- CreateRequiredField("${52}", {"#card_number"})};
+ CreateRequiredField(51, {"#card_name"}),
+ CreateRequiredField(52, {"#card_number"})};
std::map<std::string, std::string> fallback_values = {
{base::NumberToString(
@@ -725,5 +804,127 @@ TEST_F(RequiredFieldsFallbackHandlerTest,
std::move(callback));
}
+TEST_F(RequiredFieldsFallbackHandlerTest,
+ AddsMissingFallbackValueToDetailsForOptionalFieldsWithoutFailing) {
+ Selector card_name_selector({"#card_name"});
+ Selector card_number_selector({"#card_number"});
+ auto card_name_element =
+ test_util::MockFindElement(mock_web_controller_, card_name_selector, 2);
+ EXPECT_CALL(mock_web_controller_,
+ GetFieldValue(EqualsElement(card_name_element), _))
+ .Times(2)
+ .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), std::string()));
+ EXPECT_CALL(mock_web_controller_, SetValueAttribute(_, _, _)).Times(0);
+ auto card_number_element =
+ test_util::MockFindElement(mock_web_controller_, card_number_selector, 2);
+ EXPECT_CALL(mock_web_controller_,
+ GetFieldValue(EqualsElement(card_number_element), _))
+ .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()))
+ .WillOnce(RunOnceCallback<1>(OkClientStatus(), "4111111111111111"));
+ EXPECT_CALL(
+ mock_web_controller_,
+ SetValueAttribute("4111111111111111",
+ EqualsElement(test_util::MockFindElement(
+ mock_action_delegate_, card_number_selector)),
+ _))
+ .WillOnce(RunOnceCallback<2>(OkClientStatus()));
+
+ std::vector<RequiredField> required_fields = {
+ CreateRequiredField(51, {"#card_name"}),
+ CreateRequiredField(52, {"#card_number"})};
+ required_fields[0].proto.set_is_optional(true);
+
+ std::map<std::string, std::string> fallback_values = {
+ {base::NumberToString(
+ static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NUMBER)),
+ "4111111111111111"}};
+
+ RequiredFieldsFallbackHandler fallback_handler(
+ required_fields, fallback_values, &mock_action_delegate_);
+
+ base::OnceCallback<void(const ClientStatus&)> callback =
+ base::BindOnce([](const ClientStatus& status) {
+ EXPECT_TRUE(status.ok());
+ ASSERT_EQ(
+ status.details().autofill_error_info().autofill_field_error_size(),
+ 1);
+ EXPECT_EQ(status.details()
+ .autofill_error_info()
+ .autofill_field_error(0)
+ .value_expression(),
+ "${51}");
+ EXPECT_TRUE(status.details()
+ .autofill_error_info()
+ .autofill_field_error(0)
+ .no_fallback_value());
+ });
+
+ fallback_handler.CheckAndFallbackRequiredFields(OkClientStatus(),
+ std::move(callback));
+}
+
+TEST_F(RequiredFieldsFallbackHandlerTest,
+ AddsNotFoundElementToDetailsForOptionalFieldsWithoutFailing) {
+ Selector card_name_selector({"#card_name"});
+ Selector card_number_selector({"#card_number"});
+ EXPECT_CALL(mock_web_controller_, OnFindElement(card_name_selector, _))
+ .Times(2)
+ .WillRepeatedly(
+ RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED), nullptr));
+ EXPECT_CALL(mock_action_delegate_, FindElement(card_name_selector, _))
+ .WillOnce(
+ RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED), nullptr));
+ auto card_number_element =
+ test_util::MockFindElement(mock_web_controller_, card_number_selector, 2);
+ EXPECT_CALL(mock_web_controller_,
+ GetFieldValue(EqualsElement(card_number_element), _))
+ .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()))
+ .WillOnce(RunOnceCallback<1>(OkClientStatus(), "4111111111111111"));
+ EXPECT_CALL(
+ mock_web_controller_,
+ SetValueAttribute("4111111111111111",
+ EqualsElement(test_util::MockFindElement(
+ mock_action_delegate_, card_number_selector)),
+ _))
+ .WillOnce(RunOnceCallback<2>(OkClientStatus()));
+
+ std::vector<RequiredField> required_fields = {
+ CreateRequiredField(51, {"#card_name"}),
+ CreateRequiredField(52, {"#card_number"})};
+ required_fields[0].proto.set_is_optional(true);
+
+ std::map<std::string, std::string> fallback_values = {
+ {base::NumberToString(
+ static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL)),
+ "John Doe"},
+ {base::NumberToString(
+ static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NUMBER)),
+ "4111111111111111"}};
+
+ RequiredFieldsFallbackHandler fallback_handler(
+ required_fields, fallback_values, &mock_action_delegate_);
+
+ base::OnceCallback<void(const ClientStatus&)> callback =
+ base::BindOnce([](const ClientStatus& status) {
+ EXPECT_TRUE(status.ok());
+ ASSERT_EQ(
+ status.details().autofill_error_info().autofill_field_error_size(),
+ 1);
+ EXPECT_EQ(status.details()
+ .autofill_error_info()
+ .autofill_field_error(0)
+ .value_expression(),
+ "${51}");
+ EXPECT_EQ(status.details()
+ .autofill_error_info()
+ .autofill_field_error(0)
+ .status(),
+ ELEMENT_RESOLUTION_FAILED);
+ });
+
+ fallback_handler.CheckAndFallbackRequiredFields(OkClientStatus(),
+ std::move(callback));
+}
+
} // namespace
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/generate_password_for_form_field_action.cc b/chromium/components/autofill_assistant/browser/actions/generate_password_for_form_field_action.cc
index aaecfbba1be..8d98d8d0658 100644
--- a/chromium/components/autofill_assistant/browser/actions/generate_password_for_form_field_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/generate_password_for_form_field_action.cc
@@ -5,7 +5,7 @@
#include "components/autofill_assistant/browser/actions/generate_password_for_form_field_action.h"
#include <utility>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/generate_password_for_form_field_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/generate_password_for_form_field_action_unittest.cc
index 05d07313573..5037406084e 100644
--- a/chromium/components/autofill_assistant/browser/actions/generate_password_for_form_field_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/generate_password_for_form_field_action_unittest.cc
@@ -47,7 +47,7 @@ class GeneratePasswordForFormFieldActionTest : public testing::Test {
.WillByDefault(Return(kGeneratedPassword));
user_data_.selected_login_ =
- base::make_optional<WebsiteLoginManager::Login>(GURL(kFakeUrl),
+ absl::make_optional<WebsiteLoginManager::Login>(GURL(kFakeUrl),
kFakeUsername);
}
@@ -60,7 +60,7 @@ class GeneratePasswordForFormFieldActionTest : public testing::Test {
};
TEST_F(GeneratePasswordForFormFieldActionTest, GeneratedPassword) {
- ON_CALL(mock_action_delegate_, OnRetrieveElementFormAndFieldData)
+ ON_CALL(mock_action_delegate_, RetrieveElementFormAndFieldData)
.WillByDefault(RunOnceCallback<1>(ClientStatus(ACTION_APPLIED),
autofill::FormData(),
autofill::FormFieldData()));
@@ -82,7 +82,7 @@ TEST_F(GeneratePasswordForFormFieldActionTest, GeneratedPassword) {
}
TEST_F(GeneratePasswordForFormFieldActionTest, FormDataIsNotRetrieved) {
- ON_CALL(mock_action_delegate_, OnRetrieveElementFormAndFieldData)
+ ON_CALL(mock_action_delegate_, RetrieveElementFormAndFieldData)
.WillByDefault(RunOnceCallback<1>(ClientStatus(INVALID_SELECTOR),
autofill::FormData(),
autofill::FormFieldData()));
diff --git a/chromium/components/autofill_assistant/browser/actions/get_element_status_action.cc b/chromium/components/autofill_assistant/browser/actions/get_element_status_action.cc
index c808d3ca29b..4aec6660a5c 100644
--- a/chromium/components/autofill_assistant/browser/actions/get_element_status_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/get_element_status_action.cc
@@ -131,13 +131,24 @@ void GetElementStatusAction::OnWaitForElement(
delegate_->FindElement(
selector_,
- base::BindOnce(
- &action_delegate_util::TakeElementAndGetProperty<std::string>,
- base::BindOnce(&WebController::GetStringAttribute,
- delegate_->GetWebController()->GetWeakPtr(),
- attribute_list),
- base::BindOnce(&GetElementStatusAction::OnGetStringAttribute,
- weak_ptr_factory_.GetWeakPtr())));
+ base::BindOnce(&GetElementStatusAction::OnFindElement,
+ weak_ptr_factory_.GetWeakPtr(), attribute_list));
+}
+
+void GetElementStatusAction::OnFindElement(
+ const std::vector<std::string>& attribute_list,
+ const ClientStatus& status,
+ std::unique_ptr<ElementFinder::Result> element) {
+ if (!status.ok()) {
+ EndAction(status);
+ return;
+ }
+ element_ = std::move(element);
+
+ delegate_->GetWebController()->GetStringAttribute(
+ attribute_list, *element_,
+ base::BindOnce(&GetElementStatusAction::OnGetStringAttribute,
+ weak_ptr_factory_.GetWeakPtr()));
}
void GetElementStatusAction::OnGetStringAttribute(const ClientStatus& status,
@@ -149,29 +160,42 @@ void GetElementStatusAction::OnGetStringAttribute(const ClientStatus& status,
const auto& expected_match =
proto_.get_element_status().expected_value_match().text_match();
- MaybeRe2 expected_re2;
switch (expected_match.value_source_case()) {
- case GetElementStatusProto::TextMatch::kValue:
- expected_re2.value = expected_match.value();
- break;
- case GetElementStatusProto::TextMatch::kAutofillValue: {
- ClientStatus autofill_status = GetFormattedAutofillValue(
- expected_match.autofill_value(), delegate_->GetUserData(),
- &expected_re2.value);
- if (!autofill_status.ok()) {
- EndAction(autofill_status);
- return;
- }
- break;
- }
case GetElementStatusProto::TextMatch::kRe2:
- expected_re2.value = expected_match.re2();
- expected_re2.is_re2 = true;
- break;
+ CompareResult(text, expected_match.re2(), /* is_re2= */ true);
+ return;
+ case GetElementStatusProto::TextMatch::kTextValue:
+ ResolveTextValue(
+ expected_match.text_value(), *element_, delegate_,
+ base::BindOnce(&GetElementStatusAction::OnResolveTextValue,
+ weak_ptr_factory_.GetWeakPtr(), text));
+ return;
case GetElementStatusProto::TextMatch::VALUE_SOURCE_NOT_SET:
EndAction(ClientStatus(INVALID_ACTION));
return;
}
+}
+
+void GetElementStatusAction::OnResolveTextValue(const std::string& text,
+ const ClientStatus& status,
+ const std::string& value) {
+ if (!status.ok()) {
+ EndAction(status);
+ return;
+ }
+
+ CompareResult(text, value, /* is_re2= */ false);
+}
+
+void GetElementStatusAction::CompareResult(const std::string& text,
+ const std::string& expected_value,
+ bool is_re2) {
+ MaybeRe2 expected_re2;
+ expected_re2.value = expected_value;
+ expected_re2.is_re2 = is_re2;
+
+ const auto& expected_match =
+ proto_.get_element_status().expected_value_match().text_match();
auto* result = processed_action_proto_->mutable_get_element_status_result();
result->set_not_empty(!text.empty());
diff --git a/chromium/components/autofill_assistant/browser/actions/get_element_status_action.h b/chromium/components/autofill_assistant/browser/actions/get_element_status_action.h
index f4f54f318a7..c0fd2a7f245 100644
--- a/chromium/components/autofill_assistant/browser/actions/get_element_status_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/get_element_status_action.h
@@ -10,6 +10,7 @@
#include "components/autofill_assistant/browser/actions/action.h"
#include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/element_finder.h"
namespace autofill_assistant {
@@ -28,11 +29,22 @@ class GetElementStatusAction : public Action {
void InternalProcessAction(ProcessActionCallback callback) override;
void OnWaitForElement(const ClientStatus& element_status);
+ void OnFindElement(const std::vector<std::string>& attribute_list,
+ const ClientStatus& status,
+ std::unique_ptr<ElementFinder::Result> element);
void OnGetStringAttribute(const ClientStatus& status,
const std::string& text);
+ void OnResolveTextValue(const std::string& text,
+ const ClientStatus& status,
+ const std::string& value);
+ void CompareResult(const std::string& text,
+ const std::string& value,
+ bool is_re2);
void EndAction(const ClientStatus& status);
+ std::unique_ptr<ElementFinder::Result> element_;
+
Selector selector_;
ProcessActionCallback callback_;
base::WeakPtrFactory<GetElementStatusAction> weak_ptr_factory_{this};
diff --git a/chromium/components/autofill_assistant/browser/actions/get_element_status_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/get_element_status_action_unittest.cc
index 1297e2ca216..dc1a5cb6fcc 100644
--- a/chromium/components/autofill_assistant/browser/actions/get_element_status_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/get_element_status_action_unittest.cc
@@ -14,10 +14,17 @@
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill_assistant/browser/actions/action_test_utils.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/mock_website_login_manager.h"
#include "components/autofill_assistant/browser/selector.h"
#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/user_model.h"
#include "components/autofill_assistant/browser/web/mock_web_controller.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_renderer_host.h"
+#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "url/gurl.h"
namespace autofill_assistant {
namespace {
@@ -30,6 +37,7 @@ using ::testing::Property;
using ::testing::Return;
using ::testing::SizeIs;
using ::testing::UnorderedElementsAre;
+using ::testing::WithArgs;
const char kValue[] = "Some Value";
@@ -38,10 +46,15 @@ class GetElementStatusActionTest : public testing::Test {
GetElementStatusActionTest() {}
void SetUp() override {
+ web_contents_ = content::WebContentsTester::CreateTestWebContents(
+ &browser_context_, nullptr);
+
ON_CALL(mock_action_delegate_, GetUserData)
.WillByDefault(Return(&user_data_));
ON_CALL(mock_action_delegate_, GetWebController)
.WillByDefault(Return(&mock_web_controller_));
+ ON_CALL(mock_action_delegate_, GetWebsiteLoginManager)
+ .WillByDefault(Return(&mock_website_login_manager_));
ON_CALL(mock_action_delegate_, OnShortWaitForElement(_, _))
.WillByDefault(RunOnceCallback<1>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
@@ -60,11 +73,17 @@ class GetElementStatusActionTest : public testing::Test {
action.ProcessAction(callback_.Get());
}
+ content::BrowserTaskEnvironment task_environment_;
+ content::RenderViewHostTestEnabler rvh_test_enabler_;
+ content::TestBrowserContext browser_context_;
+ std::unique_ptr<content::WebContents> web_contents_;
MockActionDelegate mock_action_delegate_;
MockWebController mock_web_controller_;
base::MockCallback<Action::ProcessActionCallback> callback_;
GetElementStatusProto proto_;
UserData user_data_;
+ UserModel user_model_;
+ MockWebsiteLoginManager mock_website_login_manager_;
};
TEST_F(GetElementStatusActionTest, EmptySelectorFails) {
@@ -77,8 +96,10 @@ TEST_F(GetElementStatusActionTest, EmptySelectorFails) {
TEST_F(GetElementStatusActionTest, ActionFailsForNonExistentElement) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- kValue);
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text(kValue);
EXPECT_CALL(mock_action_delegate_, OnShortWaitForElement(selector, _))
.WillOnce(RunOnceCallback<1>(ClientStatus(TIMED_OUT),
@@ -92,8 +113,10 @@ TEST_F(GetElementStatusActionTest, ActionFailsForNonExistentElement) {
TEST_F(GetElementStatusActionTest, ActionReportsAllVariations) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- kValue);
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text(kValue);
EXPECT_CALL(
callback_,
@@ -110,8 +133,10 @@ TEST_F(GetElementStatusActionTest, ActionReportsAllVariations) {
TEST_F(GetElementStatusActionTest, ActionFailsForMismatchIfRequired) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- "other");
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text("other");
proto_.mutable_expected_value_match()
->mutable_text_match()
->mutable_match_expectation()
@@ -133,8 +158,10 @@ TEST_F(GetElementStatusActionTest, ActionFailsForMismatchIfRequired) {
TEST_F(GetElementStatusActionTest, ActionSucceedsForMismatchIfAllowed) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- "other");
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text("other");
proto_.mutable_expected_value_match()
->mutable_text_match()
->mutable_match_expectation()
@@ -155,8 +182,10 @@ TEST_F(GetElementStatusActionTest, ActionSucceedsForMismatchIfAllowed) {
TEST_F(GetElementStatusActionTest, ActionSucceedsForNoExpectation) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- "other");
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text("other");
proto_.set_mismatch_should_fail(true);
EXPECT_CALL(
@@ -172,8 +201,10 @@ TEST_F(GetElementStatusActionTest, ActionSucceedsForNoExpectation) {
TEST_F(GetElementStatusActionTest, ActionSucceedsForCaseSensitiveFullMatch) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- kValue);
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text(kValue);
proto_.mutable_expected_value_match()
->mutable_text_match()
->mutable_match_expectation()
@@ -207,8 +238,10 @@ TEST_F(GetElementStatusActionTest, ActionSucceedsForCaseSensitiveFullMatch) {
TEST_F(GetElementStatusActionTest, ActionSucceedsForCaseSensitiveContains) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- "me Va");
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text("me Va");
proto_.mutable_expected_value_match()
->mutable_text_match()
->mutable_match_expectation()
@@ -235,8 +268,10 @@ TEST_F(GetElementStatusActionTest, ActionSucceedsForCaseSensitiveContains) {
TEST_F(GetElementStatusActionTest, ActionSucceedsForCaseSensitiveStartsWith) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- "Some");
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text("Some");
proto_.mutable_expected_value_match()
->mutable_text_match()
->mutable_match_expectation()
@@ -263,8 +298,10 @@ TEST_F(GetElementStatusActionTest, ActionSucceedsForCaseSensitiveStartsWith) {
TEST_F(GetElementStatusActionTest, ActionSucceedsForCaseSensitiveEndsWith) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- "Value");
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text("Value");
proto_.mutable_expected_value_match()
->mutable_text_match()
->mutable_match_expectation()
@@ -291,8 +328,10 @@ TEST_F(GetElementStatusActionTest, ActionSucceedsForCaseSensitiveEndsWith) {
TEST_F(GetElementStatusActionTest, ActionSucceedsForCaseInsensitiveFullMatch) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- "sOmE vAlUe");
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text("sOmE vAlUe");
proto_.mutable_expected_value_match()
->mutable_text_match()
->mutable_match_expectation()
@@ -319,8 +358,10 @@ TEST_F(GetElementStatusActionTest, ActionSucceedsForCaseInsensitiveFullMatch) {
TEST_F(GetElementStatusActionTest, ActionSucceedsForFullMatchWithoutSpaces) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- "S o m eV a l u e");
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text("S o m eV a l u e");
proto_.mutable_expected_value_match()
->mutable_text_match()
->mutable_match_expectation()
@@ -355,8 +396,10 @@ TEST_F(GetElementStatusActionTest, EmptyTextForEmptyValueIsSuccess) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- std::string());
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text(std::string());
proto_.mutable_expected_value_match()
->mutable_text_match()
->mutable_match_expectation()
@@ -380,8 +423,10 @@ TEST_F(GetElementStatusActionTest, EmptyTextForEmptyValueIsSuccess) {
TEST_F(GetElementStatusActionTest, InnerTextLookupSuccess) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(
- kValue);
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text(kValue);
proto_.set_value_source(GetElementStatusProto::INNER_TEXT);
proto_.mutable_expected_value_match()
->mutable_text_match()
@@ -517,7 +562,10 @@ TEST_F(GetElementStatusActionTest, BlankTextWithRemovingSpacesIsExpectedEmpty) {
Selector selector({"#element"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_expected_value_match()->mutable_text_match()->set_value(" ");
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_text(" ");
proto_.mutable_expected_value_match()
->mutable_text_match()
->mutable_match_expectation()
@@ -546,5 +594,124 @@ TEST_F(GetElementStatusActionTest, BlankTextWithRemovingSpacesIsExpectedEmpty) {
Run();
}
+TEST_F(GetElementStatusActionTest, SucceedsWithAutofillValue) {
+ autofill::AutofillProfile contact(base::GenerateGUID(),
+ autofill::test::kEmptyOrigin);
+ autofill::test::SetProfileInfo(&contact, "John", /* middle name */ "", "Doe",
+ "", "", "", "", "", "", "", "", "");
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(contact),
+ &user_data_);
+
+ AutofillValue autofill_value;
+ autofill_value.mutable_profile()->set_identifier("contact");
+ autofill_value.mutable_value_expression()->add_chunk()->set_key(
+ static_cast<int>(autofill::ServerFieldType::NAME_FIRST));
+ autofill_value.mutable_value_expression()->add_chunk()->set_text(" ");
+ autofill_value.mutable_value_expression()->add_chunk()->set_key(
+ static_cast<int>(autofill::ServerFieldType::NAME_LAST));
+
+ Selector selector({"#element"});
+ *proto_.mutable_element() = selector.proto;
+ *proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->mutable_autofill_value() = autofill_value;
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_match_expectation();
+ proto_.set_mismatch_should_fail(true);
+
+ EXPECT_CALL(mock_web_controller_, GetStringAttribute(_, _, _))
+ .WillOnce(RunOnceCallback<2>(OkClientStatus(), "John Doe"));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(AllOf(
+ Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(
+ &ProcessedActionProto::get_element_status_result,
+ AllOf(Property(&GetElementStatusProto::Result::not_empty, true),
+ Property(&GetElementStatusProto::Result::match_success,
+ true)))))));
+ Run();
+}
+
+TEST_F(GetElementStatusActionTest, SucceedsWithPasswordManagerValue) {
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
+ GURL("https://www.example.com"), "username");
+
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("https://www.example.com"));
+
+ PasswordManagerValue password_manager_value;
+ password_manager_value.set_credential_type(PasswordManagerValue::PASSWORD);
+
+ Selector selector({"#element"});
+ *proto_.mutable_element() = selector.proto;
+ *proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->mutable_password_manager_value() = password_manager_value;
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_match_expectation();
+ proto_.set_mismatch_should_fail(true);
+
+ EXPECT_CALL(mock_action_delegate_, FindElement(_, _))
+ .WillOnce(WithArgs<1>([this](auto&& callback) {
+ std::unique_ptr<ElementFinder::Result> element =
+ std::make_unique<ElementFinder::Result>();
+ element->container_frame_host = web_contents_->GetMainFrame();
+ std::move(callback).Run(OkClientStatus(), std::move(element));
+ }));
+ EXPECT_CALL(mock_website_login_manager_, OnGetPasswordForLogin(_, _))
+ .WillOnce(RunOnceCallback<1>(true, "password"));
+ EXPECT_CALL(mock_web_controller_, GetStringAttribute(_, _, _))
+ .WillOnce(RunOnceCallback<2>(OkClientStatus(), "password"));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(AllOf(
+ Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(
+ &ProcessedActionProto::get_element_status_result,
+ AllOf(Property(&GetElementStatusProto::Result::not_empty, true),
+ Property(&GetElementStatusProto::Result::match_success,
+ true)))))));
+ Run();
+}
+
+TEST_F(GetElementStatusActionTest, SucceedsWithClientMemoryValue) {
+ ValueProto value_proto;
+ value_proto.mutable_strings()->add_values("password");
+ user_data_.additional_values_["__password__"] = value_proto;
+
+ Selector selector({"#element"});
+ *proto_.mutable_element() = selector.proto;
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_text_value()
+ ->set_client_memory_key("__password__");
+ proto_.mutable_expected_value_match()
+ ->mutable_text_match()
+ ->mutable_match_expectation();
+ proto_.set_mismatch_should_fail(true);
+
+ EXPECT_CALL(mock_web_controller_, GetStringAttribute(_, _, _))
+ .WillOnce(RunOnceCallback<2>(OkClientStatus(), "password"));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(AllOf(
+ Property(&ProcessedActionProto::status, ACTION_APPLIED),
+ Property(
+ &ProcessedActionProto::get_element_status_result,
+ AllOf(Property(&GetElementStatusProto::Result::not_empty, true),
+ Property(&GetElementStatusProto::Result::match_success,
+ true)))))));
+ Run();
+}
+
} // namespace
} // namespace autofill_assistant
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 6720f31acd9..ed5c909e133 100644
--- a/chromium/components/autofill_assistant/browser/actions/highlight_element_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/highlight_element_action.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_HIGHLIGHT_ELEMENT_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_HIGHLIGHT_ELEMENT_ACTION_H_
-#include <string>
-#include <vector>
-
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/actions/action.h"
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 9744c2468c9..bd9d664eb25 100644
--- a/chromium/components/autofill_assistant/browser/actions/mock_action_delegate.h
+++ b/chromium/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -42,135 +42,69 @@ class MockActionDelegate : public ActionDelegate {
override {
OnShortWaitForElement(selector, callback);
}
- MOCK_METHOD2(
- OnShortWaitForElement,
- void(const Selector& selector,
- base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>&));
-
void ShortWaitForElementWithSlowWarning(
const Selector& selector,
- base::OnceCallback<void(const ClientStatus&, base::TimeDelta)> callback)
- override {
+ base::OnceCallback<void(const ClientStatus&, base::TimeDelta)> callback) {
OnShortWaitForElement(selector, callback);
}
MOCK_METHOD2(
- OnShortWaitForElementWithSlowWarning,
+ OnShortWaitForElement,
void(const Selector& selector,
base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>&));
- void WaitForDom(
- base::TimeDelta max_wait_time,
- bool allow_interrupt,
- WaitForDomObserver* observer,
- base::RepeatingCallback<
- void(BatchElementChecker*,
+ MOCK_METHOD5(
+ WaitForDom,
+ void(base::TimeDelta max_wait_time,
+ bool allow_interrupt,
+ WaitForDomObserver* observer,
+ base::RepeatingCallback<void(
+ BatchElementChecker*,
base::OnceCallback<void(const ClientStatus&)>)> check_elements,
- base::OnceCallback<void(const ClientStatus&, base::TimeDelta)> callback)
- override {
- OnWaitForDom(max_wait_time, allow_interrupt, check_elements, callback);
- }
- MOCK_METHOD4(
- OnWaitForDom,
- void(base::TimeDelta,
- bool,
- base::RepeatingCallback<
- void(BatchElementChecker*,
- base::OnceCallback<void(const ClientStatus&)>)>&,
- base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>&));
-
- void WaitForDomWithSlowWarning(
- base::TimeDelta max_wait_time,
- bool allow_interrupt,
- WaitForDomObserver* observer,
- base::RepeatingCallback<
- void(BatchElementChecker*,
+ base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>
+ callback));
+ MOCK_METHOD5(
+ WaitForDomWithSlowWarning,
+ void(base::TimeDelta max_wait_time,
+ bool allow_interrupt,
+ WaitForDomObserver* observer,
+ base::RepeatingCallback<void(
+ BatchElementChecker*,
base::OnceCallback<void(const ClientStatus&)>)> check_elements,
- base::OnceCallback<void(const ClientStatus&, base::TimeDelta)> callback)
- override {
- OnWaitForDom(max_wait_time, allow_interrupt, check_elements, callback);
- }
- MOCK_METHOD4(
- OnWaitForDomWithSlowWarning,
- void(base::TimeDelta,
- bool,
- base::RepeatingCallback<
- void(BatchElementChecker*,
- base::OnceCallback<void(const ClientStatus&)>)>&,
- base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>&));
-
+ base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>
+ callback));
MOCK_METHOD1(SetStatusMessage, void(const std::string& message));
-
MOCK_METHOD0(GetStatusMessage, std::string());
-
MOCK_METHOD1(SetBubbleMessage, void(const std::string& message));
-
MOCK_METHOD0(GetBubbleMessage, std::string());
-
MOCK_CONST_METHOD2(FindElement,
void(const Selector& selector, ElementFinder::Callback));
-
MOCK_CONST_METHOD2(FindAllElements,
void(const Selector& selector,
ElementFinder::Callback callback));
-
- MOCK_METHOD3(ClickOrTapElement,
- void(ClickType click_type,
- const ElementFinder::Result& element,
- base::OnceCallback<void(const ClientStatus&)> callback));
-
MOCK_METHOD5(Prompt,
void(std::unique_ptr<std::vector<UserAction>> user_actions,
bool disable_force_expand_sheet,
base::OnceCallback<void()> end_on_navigation_callback,
bool browse_mode,
bool browse_mode_invisible));
-
MOCK_METHOD0(CleanUpAfterPrompt, void());
-
MOCK_METHOD1(SetBrowseDomainsAllowlist,
void(std::vector<std::string> domains));
-
- void FillAddressForm(
- const autofill::AutofillProfile* profile,
- const Selector& selector,
- base::OnceCallback<void(const ClientStatus&)> callback) override {
- OnFillAddressForm(profile, selector, callback);
- }
- MOCK_METHOD3(OnFillAddressForm,
+ MOCK_METHOD3(FillAddressForm,
void(const autofill::AutofillProfile* profile,
const Selector& selector,
- base::OnceCallback<void(const ClientStatus&)>& callback));
-
- void FillCardForm(
- std::unique_ptr<autofill::CreditCard> card,
- const std::u16string& cvc,
- const Selector& selector,
- base::OnceCallback<void(const ClientStatus&)> callback) override {
- OnFillCardForm(card.get(), cvc, selector, callback);
- }
-
- void RetrieveElementFormAndFieldData(
- const Selector& selector,
- base::OnceCallback<void(const ClientStatus&,
- const autofill::FormData&,
- const autofill::FormFieldData&)> callback)
- override {
- OnRetrieveElementFormAndFieldData(selector, callback);
- }
-
+ base::OnceCallback<void(const ClientStatus&)> callback));
+ MOCK_METHOD4(FillCardForm,
+ void(std::unique_ptr<autofill::CreditCard> card,
+ const std::u16string& cvc,
+ const Selector& selector,
+ base::OnceCallback<void(const ClientStatus&)> callback));
MOCK_METHOD2(
- OnRetrieveElementFormAndFieldData,
+ RetrieveElementFormAndFieldData,
void(const Selector& selector,
base::OnceCallback<void(const ClientStatus&,
const autofill::FormData&,
- const autofill::FormFieldData&)>& callback));
-
- MOCK_METHOD4(OnFillCardForm,
- void(const autofill::CreditCard* card,
- const std::u16string& cvc,
- const Selector& selector,
- base::OnceCallback<void(const ClientStatus&)>& callback));
-
+ const autofill::FormFieldData&)> callback));
MOCK_METHOD5(ScrollToElementPosition,
void(const Selector& selector,
const TopPadding& top_padding,
@@ -239,72 +173,45 @@ class MockActionDelegate : public ActionDelegate {
base::OnceCallback<void(const ClientStatus&)> cancel_callback));
MOCK_METHOD0(GetUserModel, UserModel*());
MOCK_METHOD0(GetEventHandler, EventHandler*());
-
- void WaitForWindowHeightChange(
- base::OnceCallback<void(const ClientStatus&)> callback) override {
- OnWaitForWindowHeightChange(callback);
- }
-
- MOCK_METHOD1(OnWaitForWindowHeightChange,
- void(base::OnceCallback<void(const ClientStatus&)>& callback));
-
- MOCK_METHOD3(OnWaitForDocumentReadyState,
- void(DocumentReadyState,
- const ElementFinder::Result&,
+ MOCK_METHOD1(WaitForWindowHeightChange,
+ void(base::OnceCallback<void(const ClientStatus&)> callback));
+ MOCK_METHOD4(WaitForDocumentReadyState,
+ void(base::TimeDelta max_wait_time,
+ DocumentReadyState min_ready_state,
+ const ElementFinder::Result& optional_frame_element,
base::OnceCallback<void(const ClientStatus&,
DocumentReadyState,
- base::TimeDelta)>&));
-
- void WaitForDocumentReadyState(
- base::TimeDelta max_wait_time,
- DocumentReadyState min_ready_state,
- const ElementFinder::Result& optional_frame_element,
- base::OnceCallback<void(const ClientStatus&,
- DocumentReadyState,
- base::TimeDelta)> callback) override {
- OnWaitForDocumentReadyState(min_ready_state, optional_frame_element,
- callback);
- }
-
+ base::TimeDelta)> callback));
MOCK_METHOD4(
WaitUntilDocumentIsInReadyState,
void(base::TimeDelta,
DocumentReadyState,
const ElementFinder::Result&,
base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>));
-
MOCK_METHOD0(RequireUI, void());
MOCK_METHOD0(SetExpandSheetForPromptAction, bool());
-
MOCK_METHOD3(
- OnSetGenericUi,
+ SetGenericUi,
void(std::unique_ptr<GenericUserInterfaceProto> generic_ui,
- base::OnceCallback<void(const ClientStatus&)>& end_action_callback,
- base::OnceCallback<void(const ClientStatus&)>&
+ base::OnceCallback<void(const ClientStatus&)> end_action_callback,
+ base::OnceCallback<void(const ClientStatus&)>
view_inflation_finished_callback));
- void SetGenericUi(
- std::unique_ptr<GenericUserInterfaceProto> generic_ui,
- base::OnceCallback<void(const ClientStatus&)> end_action_callback,
- base::OnceCallback<void(const ClientStatus&)>
- view_inflation_finished_callback) override {
- OnSetGenericUi(std::move(generic_ui), end_action_callback,
- view_inflation_finished_callback);
- }
+ MOCK_METHOD2(SetPersistentGenericUi,
+ void(std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback));
+
MOCK_METHOD0(ClearGenericUi, void());
+ MOCK_METHOD0(ClearPersistentGenericUi, void());
MOCK_METHOD1(SetOverlayBehavior,
void(ConfigureUiStateProto::OverlayBehavior));
-
MOCK_METHOD1(MaybeShowSlowWebsiteWarning,
void(base::OnceCallback<void(bool)>));
MOCK_METHOD0(MaybeShowSlowConnectionWarning, void());
-
- MOCK_CONST_METHOD1(OnDispatchJsEvent,
- void(base::OnceCallback<void(const ClientStatus&)>));
- void DispatchJsEvent(
- base::OnceCallback<void(const ClientStatus&)> callback) const override {
- OnDispatchJsEvent(std::move(callback));
- }
+ MOCK_CONST_METHOD1(
+ DispatchJsEvent,
+ void(base::OnceCallback<void(const ClientStatus&)> callback));
base::WeakPtr<ActionDelegate> GetWeakPtr() const override {
return weak_ptr_factory_.GetWeakPtr();
diff --git a/chromium/components/autofill_assistant/browser/actions/navigate_action.h b/chromium/components/autofill_assistant/browser/actions/navigate_action.h
index 5a6e7a892f9..bfa867f979a 100644
--- a/chromium/components/autofill_assistant/browser/actions/navigate_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/navigate_action.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_NAVIGATE_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_NAVIGATE_ACTION_H_
-#include <string>
-
#include "base/macros.h"
#include "components/autofill_assistant/browser/actions/action.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action.cc b/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action.cc
index af56e7a8689..26c66ab2d8c 100644
--- a/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action.cc
@@ -5,7 +5,7 @@
#include "components/autofill_assistant/browser/actions/presave_generated_password_action.h"
#include <utility>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action.h b/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action.h
index e48b8789ab1..6a118e01180 100644
--- a/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action.h
@@ -5,10 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_PRESAVE_GENERATED_PASSWORD_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_PRESAVE_GENERATED_PASSWORD_ACTION_H_
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/actions/action.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action_unittest.cc
index e403c9ec9d3..5858309ff59 100644
--- a/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/presave_generated_password_action_unittest.cc
@@ -50,7 +50,7 @@ class PresaveGeneratedPasswordActionTest : public testing::Test {
};
TEST_F(PresaveGeneratedPasswordActionTest, PresaveGeneratedPassword) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL(kFakeUrl), kFakeUsername);
user_data_.additional_values_[kMemoryKeyForGeneratedPassword] =
SimpleValue(std::string(kGeneratedPassword));
@@ -87,7 +87,7 @@ TEST_F(PresaveGeneratedPasswordActionTest, LoginDataMissing) {
}
TEST_F(PresaveGeneratedPasswordActionTest, GeneratedPasswordMissing) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL(kFakeUrl), kFakeUsername);
user_data_.password_form_data_ = autofill::FormData();
@@ -104,7 +104,7 @@ TEST_F(PresaveGeneratedPasswordActionTest, GeneratedPasswordMissing) {
}
TEST_F(PresaveGeneratedPasswordActionTest, FormDataMissing) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL(kFakeUrl), kFakeUsername);
user_data_.additional_values_[kMemoryKeyForGeneratedPassword] =
SimpleValue(std::string(kGeneratedPassword));
diff --git a/chromium/components/autofill_assistant/browser/actions/prompt_action.cc b/chromium/components/autofill_assistant/browser/actions/prompt_action.cc
index 936eb3d3a45..8f2e10ddfcb 100644
--- a/chromium/components/autofill_assistant/browser/actions/prompt_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/prompt_action.cc
@@ -27,6 +27,10 @@ PromptAction::PromptAction(ActionDelegate* delegate, const ActionProto& proto)
PromptAction::~PromptAction() {}
+bool PromptAction::ShouldInterruptOnPause() const {
+ return true;
+}
+
void PromptAction::InternalProcessAction(ProcessActionCallback callback) {
callback_ = std::move(callback);
if (proto_.prompt().choices_size() == 0) {
diff --git a/chromium/components/autofill_assistant/browser/actions/prompt_action.h b/chromium/components/autofill_assistant/browser/actions/prompt_action.h
index 6c1ced34f54..cc8e8e3d46f 100644
--- a/chromium/components/autofill_assistant/browser/actions/prompt_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/prompt_action.h
@@ -28,6 +28,9 @@ class PromptAction : public Action {
explicit PromptAction(ActionDelegate* delegate, const ActionProto& proto);
~PromptAction() override;
+ // Overrides Action:
+ bool ShouldInterruptOnPause() const override;
+
private:
// Overrides Action:
void InternalProcessAction(ProcessActionCallback callback) override;
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 27fb21612a4..a94e00f590e 100644
--- a/chromium/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
@@ -15,6 +15,7 @@
#include "base/test/test_simple_task_runner.h"
#include "base/timer/timer.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/wait_for_dom_observer.h"
#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -44,7 +45,7 @@ class PromptActionTest : public testing::Test {
ON_CALL(mock_web_controller_, OnFindElement(_, _))
.WillByDefault(RunOnceCallback<1>(
ClientStatus(ELEMENT_RESOLUTION_FAILED), nullptr));
- EXPECT_CALL(mock_action_delegate_, OnWaitForDom(_, _, _, _))
+ EXPECT_CALL(mock_action_delegate_, WaitForDom(_, _, _, _, _))
.WillRepeatedly(Invoke(this, &PromptActionTest::FakeWaitForDom));
ON_CALL(mock_action_delegate_, Prompt(_, _, _, _, _))
.WillByDefault(
@@ -65,10 +66,11 @@ class PromptActionTest : public testing::Test {
void FakeWaitForDom(
base::TimeDelta max_wait_time,
bool allow_interrupt,
+ WaitForDomObserver* observer,
base::RepeatingCallback<
void(BatchElementChecker*,
- base::OnceCallback<void(const ClientStatus&)>)>& check_elements,
- base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>&
+ base::OnceCallback<void(const ClientStatus&)>)> check_elements,
+ base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>
done_waiting_callback) {
fake_wait_for_dom_done_ = std::move(done_waiting_callback);
RunFakeWaitForDom(check_elements);
diff --git a/chromium/components/autofill_assistant/browser/actions/release_elements_action.h b/chromium/components/autofill_assistant/browser/actions/release_elements_action.h
index 9f0c29d48fc..28a5cd8d23c 100644
--- a/chromium/components/autofill_assistant/browser/actions/release_elements_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/release_elements_action.h
@@ -34,4 +34,4 @@ class ReleaseElementsAction : public Action {
};
} // namespace autofill_assistant
-#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_RELEASE_ELEMEMENTS_ACTION_H_
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_RELEASE_ELEMENTS_ACTION_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/save_generated_password_action.cc b/chromium/components/autofill_assistant/browser/actions/save_generated_password_action.cc
index 0d64dabd299..020965b5ff5 100644
--- a/chromium/components/autofill_assistant/browser/actions/save_generated_password_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/save_generated_password_action.cc
@@ -5,7 +5,7 @@
#include "components/autofill_assistant/browser/actions/save_generated_password_action.h"
#include <utility>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "components/autofill_assistant/browser/actions/action_delegate.h"
#include "components/autofill_assistant/browser/client_status.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/save_generated_password_action.h b/chromium/components/autofill_assistant/browser/actions/save_generated_password_action.h
index d0514b614de..78d8b134b76 100644
--- a/chromium/components/autofill_assistant/browser/actions/save_generated_password_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/save_generated_password_action.h
@@ -5,10 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SAVE_GENERATED_PASSWORD_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SAVE_GENERATED_PASSWORD_ACTION_H_
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/actions/action.h"
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 da352dda15b..3bf4a27f655 100644
--- a/chromium/components/autofill_assistant/browser/actions/select_option_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/select_option_action.cc
@@ -53,15 +53,17 @@ void SelectOptionAction::InternalProcessAction(ProcessActionCallback callback) {
value_ = select_option.text_filter_value().re2();
case_sensitive_ = select_option.text_filter_value().case_sensitive();
break;
- case SelectOptionProto::kAutofillValue: {
- ClientStatus autofill_status = GetFormattedAutofillValue(
- select_option.autofill_value(), delegate_->GetUserData(), &value_);
+ case SelectOptionProto::kAutofillRegexpValue: {
+ ClientStatus autofill_status =
+ GetFormattedAutofillValue(select_option.autofill_regexp_value(),
+ delegate_->GetUserData(), &value_);
if (!autofill_status.ok()) {
EndAction(autofill_status);
return;
}
- case_sensitive_ =
- select_option.autofill_value().value_expression().case_sensitive();
+ case_sensitive_ = select_option.autofill_regexp_value()
+ .value_expression_re2()
+ .case_sensitive();
break;
}
default:
@@ -92,7 +94,8 @@ void SelectOptionAction::OnWaitForElement(const Selector& selector,
base::BindOnce(&WebController::SelectOption,
delegate_->GetWebController()->GetWeakPtr(), value_,
case_sensitive_,
- proto_.select_option().option_comparison_attribute()),
+ proto_.select_option().option_comparison_attribute(),
+ proto_.select_option().strict()),
base::BindOnce(&SelectOptionAction::EndAction,
weak_ptr_factory_.GetWeakPtr()));
}
diff --git a/chromium/components/autofill_assistant/browser/actions/select_option_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/select_option_action_unittest.cc
index 81100d4ce85..f25b7a56e83 100644
--- a/chromium/components/autofill_assistant/browser/actions/select_option_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/select_option_action_unittest.cc
@@ -16,6 +16,7 @@
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
#include "components/autofill_assistant/browser/selector.h"
#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/user_model.h"
#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -56,6 +57,7 @@ class SelectOptionActionTest : public testing::Test {
base::MockCallback<Action::ProcessActionCallback> callback_;
SelectOptionProto proto_;
UserData user_data_;
+ UserModel user_model_;
};
TEST_F(SelectOptionActionTest, NoValueToSelectFails) {
@@ -80,7 +82,7 @@ TEST_F(SelectOptionActionTest, EmptyTextFilterValueFails) {
TEST_F(SelectOptionActionTest, EmptyAutofillValueFails) {
Selector selector({"#select"});
*proto_.mutable_element() = selector.proto;
- proto_.mutable_autofill_value();
+ proto_.mutable_autofill_regexp_value();
EXPECT_CALL(
callback_,
Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
@@ -111,6 +113,7 @@ TEST_F(SelectOptionActionTest, CheckExpectedCallChain) {
Selector selector({"#select"});
*proto_.mutable_element() = selector.proto;
proto_.mutable_text_filter_value()->set_re2("option");
+ proto_.set_strict(true);
Selector expected_selector = selector;
EXPECT_CALL(mock_action_delegate_,
@@ -120,9 +123,9 @@ TEST_F(SelectOptionActionTest, CheckExpectedCallChain) {
auto expected_element =
test_util::MockFindElement(mock_action_delegate_, expected_selector);
EXPECT_CALL(mock_web_controller_,
- SelectOption("option", false, SelectOptionProto::VALUE,
+ SelectOption("option", false, SelectOptionProto::VALUE, true,
EqualsElement(expected_element), _))
- .WillOnce(RunOnceCallback<4>(OkClientStatus()));
+ .WillOnce(RunOnceCallback<5>(OkClientStatus()));
EXPECT_CALL(
callback_,
@@ -133,9 +136,12 @@ TEST_F(SelectOptionActionTest, CheckExpectedCallChain) {
TEST_F(SelectOptionActionTest, RequestDataFromUnknownProfile) {
Selector selector({"#select"});
*proto_.mutable_element() = selector.proto;
- auto* value = proto_.mutable_autofill_value();
+ auto* value = proto_.mutable_autofill_regexp_value();
value->mutable_profile()->set_identifier("none");
- value->mutable_value_expression()->set_re2("value");
+ value->mutable_value_expression_re2()
+ ->mutable_value_expression()
+ ->add_chunk()
+ ->set_text("value");
EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
PRECONDITION_FAILED))));
Run();
@@ -147,18 +153,19 @@ TEST_F(SelectOptionActionTest, RequestUnknownDataFromProfile) {
// Middle name is expected to be empty.
autofill::test::SetProfileInfo(&contact, "John", /* middle name */ "", "Doe",
"", "", "", "", "", "", "", "", "");
- user_data_.selected_addresses_["contact"] =
- std::make_unique<autofill::AutofillProfile>(contact);
+
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(contact),
+ &user_data_);
Selector selector({"#select"});
*proto_.mutable_element() = selector.proto;
- auto* value = proto_.mutable_autofill_value();
+ auto* value = proto_.mutable_autofill_regexp_value();
value->mutable_profile()->set_identifier("contact");
- value->mutable_value_expression()->set_re2(
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_MIDDLE)),
- "}"}));
+ value->mutable_value_expression_re2()
+ ->mutable_value_expression()
+ ->add_chunk()
+ ->set_key(static_cast<int>(autofill::ServerFieldType::NAME_MIDDLE));
EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
AUTOFILL_INFO_NOT_AVAILABLE))));
@@ -170,20 +177,20 @@ TEST_F(SelectOptionActionTest, SelectOptionFromProfileValue) {
autofill::test::kEmptyOrigin);
autofill::test::SetProfileInfo(&contact, "John", "", "Doe", "", "", "", "",
"", "", "", "", "");
- user_data_.selected_addresses_["contact"] =
- std::make_unique<autofill::AutofillProfile>(contact);
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(contact),
+ &user_data_);
InSequence sequence;
Selector selector({"#select"});
*proto_.mutable_element() = selector.proto;
- auto* value = proto_.mutable_autofill_value();
+ auto* value = proto_.mutable_autofill_regexp_value();
value->mutable_profile()->set_identifier("contact");
- value->mutable_value_expression()->set_re2(
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}"}));
+ value->mutable_value_expression_re2()
+ ->mutable_value_expression()
+ ->add_chunk()
+ ->set_key(static_cast<int>(autofill::ServerFieldType::NAME_FIRST));
Selector expected_selector = selector;
EXPECT_CALL(mock_action_delegate_,
@@ -191,11 +198,11 @@ TEST_F(SelectOptionActionTest, SelectOptionFromProfileValue) {
.WillOnce(RunOnceCallback<1>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
EXPECT_CALL(mock_web_controller_,
- SelectOption("John", false, SelectOptionProto::VALUE,
+ SelectOption("John", false, SelectOptionProto::VALUE, false,
EqualsElement(test_util::MockFindElement(
mock_action_delegate_, expected_selector)),
_))
- .WillOnce(RunOnceCallback<4>(OkClientStatus()));
+ .WillOnce(RunOnceCallback<5>(OkClientStatus()));
EXPECT_CALL(
callback_,
@@ -219,9 +226,9 @@ TEST_F(SelectOptionActionTest, SelectRegularExpressionValue) {
auto expected_element =
test_util::MockFindElement(mock_action_delegate_, expected_selector);
EXPECT_CALL(mock_web_controller_,
- SelectOption("^option$", true, SelectOptionProto::VALUE,
+ SelectOption("^option$", true, SelectOptionProto::VALUE, false,
EqualsElement(expected_element), _))
- .WillOnce(RunOnceCallback<4>(OkClientStatus()));
+ .WillOnce(RunOnceCallback<5>(OkClientStatus()));
EXPECT_CALL(
callback_,
@@ -234,33 +241,36 @@ TEST_F(SelectOptionActionTest, EscapeRegularExpressionAutofillValue) {
autofill::test::kEmptyOrigin);
autofill::test::SetProfileInfo(&contact, "John", "", "Doe", "", "", "", "",
"", "", "", "", "+41791234567");
- user_data_.selected_addresses_["contact"] =
- std::make_unique<autofill::AutofillProfile>(contact);
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(contact),
+ &user_data_);
InSequence sequence;
Selector selector({"#select"});
*proto_.mutable_element() = selector.proto;
- auto* value = proto_.mutable_autofill_value();
+ auto* value = proto_.mutable_autofill_regexp_value();
value->mutable_profile()->set_identifier("contact");
- value->mutable_value_expression()->set_re2(
- base::StrCat({"^${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER)),
- "}$"}));
- value->mutable_value_expression()->set_case_sensitive(true);
+ *value->mutable_value_expression_re2()->mutable_value_expression() =
+ test_util::ValueExpressionBuilder()
+ .addChunk("^")
+ .addChunk(autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER)
+ .addChunk("$")
+ .toProto();
+ value->mutable_value_expression_re2()->set_case_sensitive(true);
Selector expected_selector = selector;
EXPECT_CALL(mock_action_delegate_,
OnShortWaitForElement(expected_selector, _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
- EXPECT_CALL(mock_web_controller_,
- SelectOption("^\\+41791234567$", true, SelectOptionProto::VALUE,
- EqualsElement(test_util::MockFindElement(
- mock_action_delegate_, expected_selector)),
- _))
- .WillOnce(RunOnceCallback<4>(OkClientStatus()));
+ EXPECT_CALL(
+ mock_web_controller_,
+ SelectOption("^\\+41791234567$", true, SelectOptionProto::VALUE, false,
+ EqualsElement(test_util::MockFindElement(
+ mock_action_delegate_, expected_selector)),
+ _))
+ .WillOnce(RunOnceCallback<5>(OkClientStatus()));
EXPECT_CALL(
callback_,
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 a7fd41e389a..d11684add6a 100644
--- a/chromium/components/autofill_assistant/browser/actions/set_attribute_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/set_attribute_action.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SET_ATTRIBUTE_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SET_ATTRIBUTE_ACTION_H_
-#include <string>
-#include <vector>
-
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/autofill_assistant/browser/actions/action.h"
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 f8f86c991b8..329ae43b814 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
@@ -42,7 +42,7 @@ class SetFormFieldValueAction : public Action {
// The keys to press if either |keycode| or |keyboard_input| is set, else
// nullptr.
- std::unique_ptr<std::vector<UChar32>> keyboard_input = nullptr;
+ std::unique_ptr<std::vector<UChar32>> keyboard_input;
// If the action is about passwords, the field describes whether to use
// password or username.
PasswordManagerValue password_manager_value;
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
index a4c1638962d..78bded62cc3 100644
--- 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
@@ -21,9 +21,12 @@
#include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/mock_website_login_manager.h"
#include "components/autofill_assistant/browser/string_conversions_util.h"
+#include "components/autofill_assistant/browser/user_model.h"
#include "components/autofill_assistant/browser/web/mock_web_controller.h"
-#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_browser_context.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 autofill_assistant {
@@ -45,16 +48,13 @@ using ::testing::Property;
using ::testing::Return;
using ::testing::WithArgs;
-class SetFormFieldValueActionTest : public content::RenderViewHostTestHarness {
+class SetFormFieldValueActionTest : public testing::Test {
public:
- SetFormFieldValueActionTest()
- : RenderViewHostTestHarness(
- base::test::TaskEnvironment::MainThreadType::UI,
- base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
- ~SetFormFieldValueActionTest() override {}
+ SetFormFieldValueActionTest() {}
void SetUp() override {
- RenderViewHostTestHarness::SetUp();
+ web_contents_ = content::WebContentsTester::CreateTestWebContents(
+ &browser_context_, nullptr);
ON_CALL(mock_action_delegate_, GetWebController)
.WillByDefault(Return(&mock_web_controller_));
@@ -87,7 +87,7 @@ class SetFormFieldValueActionTest : public content::RenderViewHostTestHarness {
ON_CALL(mock_web_controller_, WaitUntilElementIsStable(_, _, _, _))
.WillByDefault(RunOnceCallback<3>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
- ON_CALL(mock_action_delegate_, ClickOrTapElement(_, _, _))
+ ON_CALL(mock_web_controller_, ClickOrTapElement(_, _, _))
.WillByDefault(RunOnceCallback<2>(OkClientStatus()));
ON_CALL(mock_web_controller_, SendKeyboardInput(_, _, _, _))
.WillByDefault(RunOnceCallback<3>(OkClientStatus()));
@@ -96,6 +96,10 @@ class SetFormFieldValueActionTest : public content::RenderViewHostTestHarness {
}
protected:
+ content::BrowserTaskEnvironment task_environment_;
+ content::RenderViewHostTestEnabler rvh_test_enabler_;
+ content::TestBrowserContext browser_context_;
+ std::unique_ptr<content::WebContents> web_contents_;
Selector fake_selector_;
MockActionDelegate mock_action_delegate_;
MockWebController mock_web_controller_;
@@ -104,6 +108,7 @@ class SetFormFieldValueActionTest : public content::RenderViewHostTestHarness {
ActionProto proto_;
SetFormFieldValueProto* set_form_field_proto_;
UserData user_data_;
+ UserModel user_model_;
};
TEST_F(SetFormFieldValueActionTest, RequestedUsernameButNoLoginInClientMemory) {
@@ -131,15 +136,15 @@ TEST_F(SetFormFieldValueActionTest, RequestedPasswordButNoLoginInClientMemory) {
}
TEST_F(SetFormFieldValueActionTest, RequestedPasswordButPasswordNotAvailable) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL(kFakeUrl), kFakeUsername);
EXPECT_CALL(mock_action_delegate_, FindElement(fake_selector_, _))
.WillOnce(testing::WithArgs<1>([this](auto&& callback) {
auto element_result = std::make_unique<ElementFinder::Result>();
element_result->dom_object.object_data.object_id = "fake_object_id";
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL(kFakeUrl), web_contents()->GetMainFrame());
- element_result->container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL(kFakeUrl));
+ element_result->container_frame_host = web_contents_->GetMainFrame();
std::move(callback).Run(OkClientStatus(), std::move(element_result));
}));
@@ -164,15 +169,15 @@ TEST_F(SetFormFieldValueActionTest, NonAsciiKeycode) {
}
TEST_F(SetFormFieldValueActionTest, UsernameToFill) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL(kFakeUrl), kFakeUsername);
EXPECT_CALL(mock_action_delegate_, FindElement(fake_selector_, _))
.WillOnce(testing::WithArgs<1>([this](auto&& callback) {
auto element_result = std::make_unique<ElementFinder::Result>();
element_result->dom_object.object_data.object_id = "fake_object_id";
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL(kFakeUrl), web_contents()->GetMainFrame());
- element_result->container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL(kFakeUrl));
+ element_result->container_frame_host = web_contents_->GetMainFrame();
std::move(callback).Run(OkClientStatus(), std::move(element_result));
}));
ElementFinder::Result expected_element;
@@ -196,15 +201,15 @@ TEST_F(SetFormFieldValueActionTest, UsernameToFill) {
}
TEST_F(SetFormFieldValueActionTest, UsernameFillingFailsForMismatchingOrigin) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL("http://www.example.com/"), kFakeUsername);
EXPECT_CALL(mock_action_delegate_, FindElement(fake_selector_, _))
.WillOnce(testing::WithArgs<1>([this](auto&& callback) {
auto element_result = std::make_unique<ElementFinder::Result>();
element_result->dom_object.object_data.object_id = "fake_object_id";
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL("http://not-real.com/"), web_contents()->GetMainFrame());
- element_result->container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("http://not-real.com"));
+ element_result->container_frame_host = web_contents_->GetMainFrame();
std::move(callback).Run(OkClientStatus(), std::move(element_result));
}));
@@ -220,15 +225,15 @@ TEST_F(SetFormFieldValueActionTest, UsernameFillingFailsForMismatchingOrigin) {
}
TEST_F(SetFormFieldValueActionTest, PasswordToFill) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL(kFakeUrl), kFakeUsername);
EXPECT_CALL(mock_action_delegate_, FindElement(fake_selector_, _))
.WillOnce(testing::WithArgs<1>([this](auto&& callback) {
auto element_result = std::make_unique<ElementFinder::Result>();
element_result->dom_object.object_data.object_id = "fake_object_id";
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL(kFakeUrl), web_contents()->GetMainFrame());
- element_result->container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL(kFakeUrl));
+ element_result->container_frame_host = web_contents_->GetMainFrame();
std::move(callback).Run(OkClientStatus(), std::move(element_result));
}));
@@ -253,15 +258,16 @@ TEST_F(SetFormFieldValueActionTest, PasswordToFill) {
}
TEST_F(SetFormFieldValueActionTest, PasswordFillingFailsForMismatchingOrigin) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL("http://www.example.com/"), kFakeUsername);
EXPECT_CALL(mock_action_delegate_, FindElement(fake_selector_, _))
.WillOnce(testing::WithArgs<1>([this](auto&& callback) {
auto element_result = std::make_unique<ElementFinder::Result>();
element_result->dom_object.object_data.object_id = "fake_object_id";
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL("http://not-real.com/"), web_contents()->GetMainFrame());
- element_result->container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("http://not-real.com"));
+ ;
+ element_result->container_frame_host = web_contents_->GetMainFrame();
std::move(callback).Run(OkClientStatus(), std::move(element_result));
}));
@@ -277,15 +283,15 @@ TEST_F(SetFormFieldValueActionTest, PasswordFillingFailsForMismatchingOrigin) {
}
TEST_F(SetFormFieldValueActionTest, PasswordFillingSucceedsForSubdomain) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL("http://www.example.com/"), kFakeUsername);
EXPECT_CALL(mock_action_delegate_, FindElement(fake_selector_, _))
.WillOnce(testing::WithArgs<1>([this](auto&& callback) {
auto element_result = std::make_unique<ElementFinder::Result>();
element_result->dom_object.object_data.object_id = "fake_object_id";
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL("http://login.example.com/"), web_contents()->GetMainFrame());
- element_result->container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("http://login.example.com/"));
+ element_result->container_frame_host = web_contents_->GetMainFrame();
std::move(callback).Run(OkClientStatus(), std::move(element_result));
}));
@@ -310,15 +316,15 @@ TEST_F(SetFormFieldValueActionTest, PasswordFillingSucceedsForSubdomain) {
}
TEST_F(SetFormFieldValueActionTest, PasswordIsClearedFromMemory) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL(kFakeUrl), kFakeUsername);
EXPECT_CALL(mock_action_delegate_, FindElement(fake_selector_, _))
.WillOnce(testing::WithArgs<1>([this](auto&& callback) {
auto element_result = std::make_unique<ElementFinder::Result>();
element_result->dom_object.object_data.object_id = "fake_object_id";
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL(kFakeUrl), web_contents()->GetMainFrame());
- element_result->container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL(kFakeUrl));
+ element_result->container_frame_host = web_contents_->GetMainFrame();
std::move(callback).Run(OkClientStatus(), std::move(element_result));
}));
@@ -389,8 +395,8 @@ TEST_F(SetFormFieldValueActionTest, KeyboardInputHasExpectedCallChain) {
ScrollIntoView(true, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(
- mock_action_delegate_,
- ClickOrTapElement(ClickType::CLICK, EqualsElement(expected_element), _))
+ mock_web_controller_,
+ ClickOrTapElement(ClickType::TAP, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(mock_web_controller_,
SendKeyboardInput(UTF8ToUnicode(keyboard_input), _,
@@ -450,7 +456,7 @@ TEST_F(SetFormFieldValueActionTest, TextWithKeystrokeHasExpectedCallChain) {
ScrollIntoView(true, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(
- mock_action_delegate_,
+ mock_web_controller_,
ClickOrTapElement(ClickType::CLICK, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(mock_web_controller_,
@@ -591,15 +597,15 @@ TEST_F(SetFormFieldValueActionTest, FallbackToSimulateKeystrokes) {
TEST_F(SetFormFieldValueActionTest, FallbackForPassword) {
InSequence sequence;
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL(kFakeUrl), kFakeUsername);
EXPECT_CALL(mock_action_delegate_, FindElement(fake_selector_, _))
.WillOnce(testing::WithArgs<1>([this](auto&& callback) {
auto element_result = std::make_unique<ElementFinder::Result>();
element_result->dom_object.object_data.object_id = "fake_object_id";
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL(kFakeUrl), web_contents()->GetMainFrame());
- element_result->container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL(kFakeUrl));
+ element_result->container_frame_host = web_contents_->GetMainFrame();
std::move(callback).Run(OkClientStatus(), std::move(element_result));
}));
ElementFinder::Result expected_element;
@@ -703,7 +709,7 @@ TEST_F(SetFormFieldValueActionTest, EmptyProfileValueFails) {
TEST_F(SetFormFieldValueActionTest, RequestDataFromUnknownProfile) {
auto* value = set_form_field_proto_->add_value()->mutable_autofill_value();
value->mutable_profile()->set_identifier("none");
- value->set_value_expression("value");
+ value->mutable_value_expression()->add_chunk()->set_text("value");
SetFormFieldValueAction action(&mock_action_delegate_, proto_);
EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
@@ -717,16 +723,14 @@ TEST_F(SetFormFieldValueActionTest, RequestUnknownDataFromProfile) {
// Middle name is expected to be empty.
autofill::test::SetProfileInfo(&contact, "John", /* middle name */ "", "Doe",
"", "", "", "", "", "", "", "", "");
- user_data_.selected_addresses_["contact"] =
- std::make_unique<autofill::AutofillProfile>(contact);
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(contact),
+ &user_data_);
auto* value = set_form_field_proto_->add_value()->mutable_autofill_value();
value->mutable_profile()->set_identifier("contact");
- value->set_value_expression(
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_MIDDLE)),
- "}"}));
+ value->mutable_value_expression()->add_chunk()->set_key(
+ static_cast<int>(autofill::ServerFieldType::NAME_MIDDLE));
SetFormFieldValueAction action(&mock_action_delegate_, proto_);
EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status,
@@ -739,16 +743,14 @@ TEST_F(SetFormFieldValueActionTest, SetFieldFromProfileValue) {
autofill::test::kEmptyOrigin);
autofill::test::SetProfileInfo(&contact, "John", "", "Doe", "", "", "", "",
"", "", "", "", "");
- user_data_.selected_addresses_["contact"] =
- std::make_unique<autofill::AutofillProfile>(contact);
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(contact),
+ &user_data_);
auto* value = set_form_field_proto_->add_value()->mutable_autofill_value();
value->mutable_profile()->set_identifier("contact");
- value->set_value_expression(
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}"}));
+ value->mutable_value_expression()->add_chunk()->set_key(
+ static_cast<int>(autofill::ServerFieldType::NAME_FIRST));
SetFormFieldValueAction action(&mock_action_delegate_, proto_);
const ElementFinder::Result& expected_element =
diff --git a/chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action.cc b/chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action.cc
new file mode 100644
index 00000000000..923720b96f2
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action.cc
@@ -0,0 +1,83 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/actions/set_persistent_ui_action.h"
+#include "components/autofill_assistant/browser/actions/action_delegate.h"
+#include "components/autofill_assistant/browser/client_status.h"
+
+namespace autofill_assistant {
+namespace {
+bool IsCallbackAllowed(const CallbackProto::KindCase kind) {
+ switch (kind) {
+ case CallbackProto::kEndAction:
+ case CallbackProto::kToggleUserAction:
+ case CallbackProto::kSetUserActions:
+ case CallbackProto::KIND_NOT_SET:
+ return false;
+ case CallbackProto::kSetValue:
+ case CallbackProto::kShowInfoPopup:
+ case CallbackProto::kShowListPopup:
+ case CallbackProto::kShowCalendarPopup:
+ case CallbackProto::kComputeValue:
+ case CallbackProto::kSetText:
+ case CallbackProto::kSetViewVisibility:
+ case CallbackProto::kSetViewEnabled:
+ case CallbackProto::kShowGenericPopup:
+ case CallbackProto::kCreateNestedUi:
+ case CallbackProto::kClearViewContainer:
+ case CallbackProto::kForEach:
+ return true;
+ // Intentionally no default case to ensure a compilation error for new
+ // cases added to the proto.
+ }
+}
+} // namespace
+
+SetPersistentUiAction::SetPersistentUiAction(ActionDelegate* delegate,
+ const ActionProto& proto)
+ : Action(delegate, proto) {
+ DCHECK(proto_.has_set_persistent_ui());
+}
+
+SetPersistentUiAction::~SetPersistentUiAction() = default;
+
+void SetPersistentUiAction::InternalProcessAction(
+ ProcessActionCallback callback) {
+ callback_ = std::move(callback);
+
+ if (!proto_.set_persistent_ui().has_generic_user_interface()) {
+ VLOG(1) << "Invalid action: missing |generic user interface|";
+ EndAction(ClientStatus(INVALID_ACTION));
+ return;
+ }
+
+ for (const auto& interaction : proto_.set_persistent_ui()
+ .generic_user_interface()
+ .interactions()
+ .interactions()) {
+ for (const auto& interaction_callback : interaction.callbacks()) {
+ if (!IsCallbackAllowed(interaction_callback.kind_case())) {
+ VLOG(1) << "Invalid action: interaction contains unsupported callback";
+ EndAction(ClientStatus(INVALID_ACTION));
+ return;
+ }
+ }
+ }
+
+ delegate_->SetPersistentGenericUi(
+ std::make_unique<GenericUserInterfaceProto>(
+ proto_.set_persistent_ui().generic_user_interface()),
+ base::BindOnce(&SetPersistentUiAction::EndAction,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void SetPersistentUiAction::EndAction(const ClientStatus& status) {
+ if (!callback_)
+ return;
+
+ UpdateProcessedAction(status);
+ std::move(callback_).Run(std::move(processed_action_proto_));
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action.h b/chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action.h
new file mode 100644
index 00000000000..49e595453fc
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action.h
@@ -0,0 +1,34 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SET_PERSISTENT_UI_ACTION_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SET_PERSISTENT_UI_ACTION_H_
+
+#include "base/callback.h"
+#include "components/autofill_assistant/browser/actions/action.h"
+
+namespace autofill_assistant {
+
+// Action to show generic UI in the sheet until dismissed.
+class SetPersistentUiAction : public Action {
+ public:
+ explicit SetPersistentUiAction(ActionDelegate* delegate,
+ const ActionProto& proto);
+ ~SetPersistentUiAction() override;
+
+ SetPersistentUiAction(const SetPersistentUiAction&) = delete;
+ SetPersistentUiAction& operator=(const SetPersistentUiAction&) = delete;
+
+ private:
+ // Overrides Action:
+ void InternalProcessAction(ProcessActionCallback callback) override;
+
+ void EndAction(const ClientStatus& status);
+
+ ProcessActionCallback callback_;
+ base::WeakPtrFactory<SetPersistentUiAction> weak_ptr_factory_{this};
+};
+
+} // namespace autofill_assistant
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SET_PERSISTENT_UI_ACTION_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action_unittest.cc
new file mode 100644
index 00000000000..1879b57d91f
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/actions/set_persistent_ui_action_unittest.cc
@@ -0,0 +1,124 @@
+// Copyright 2021 The Chromium Authors. 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_persistent_ui_action.h"
+
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+namespace {
+
+using ::base::test::RunOnceCallback;
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Pointee;
+using ::testing::Property;
+
+class SetPersistentUiActionTest : public testing::Test {
+ public:
+ SetPersistentUiActionTest() {}
+
+ protected:
+ void Run() {
+ ActionProto action_proto;
+ *action_proto.mutable_set_persistent_ui() = proto_;
+ auto action = std::make_unique<SetPersistentUiAction>(
+ &mock_action_delegate_, action_proto);
+ action->ProcessAction(callback_.Get());
+ }
+
+ MockActionDelegate mock_action_delegate_;
+ base::MockCallback<Action::ProcessActionCallback> callback_;
+ SetPersistentUiProto proto_;
+};
+
+TEST_F(SetPersistentUiActionTest, SetUi) {
+ EXPECT_CALL(mock_action_delegate_, SetPersistentGenericUi(_, _))
+ .WillOnce(RunOnceCallback<1>(ClientStatus(ACTION_APPLIED)));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+
+ proto_.mutable_generic_user_interface();
+ Run();
+}
+
+TEST_F(SetPersistentUiActionTest, FailedViewInflationEndsWithError) {
+ EXPECT_CALL(mock_action_delegate_, SetPersistentGenericUi(_, _))
+ .WillOnce(RunOnceCallback<1>(ClientStatus(INVALID_ACTION)));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))));
+
+ proto_.mutable_generic_user_interface();
+ Run();
+}
+
+TEST_F(SetPersistentUiActionTest, UnsupportedCallbackEndsActionWithError) {
+ InSequence sequence;
+
+ EXPECT_CALL(mock_action_delegate_, SetPersistentGenericUi).Times(0);
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION))))
+ .Times(3);
+
+ proto_.mutable_generic_user_interface()
+ ->mutable_interactions()
+ ->add_interactions()
+ ->add_callbacks()
+ ->mutable_end_action();
+ Run();
+
+ proto_.mutable_generic_user_interface()->clear_interactions();
+ proto_.mutable_generic_user_interface()
+ ->mutable_interactions()
+ ->add_interactions()
+ ->add_callbacks()
+ ->mutable_toggle_user_action();
+ Run();
+
+ proto_.mutable_generic_user_interface()->clear_interactions();
+ proto_.mutable_generic_user_interface()
+ ->mutable_interactions()
+ ->add_interactions()
+ ->add_callbacks()
+ ->mutable_set_user_actions();
+ Run();
+
+ // Other callbacks don't cause an error.
+ EXPECT_CALL(mock_action_delegate_, SetPersistentGenericUi(_, _))
+ .WillOnce(RunOnceCallback<1>(ClientStatus(ACTION_APPLIED)));
+
+ EXPECT_CALL(
+ callback_,
+ Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED))));
+ proto_.mutable_generic_user_interface()->clear_interactions();
+ auto* interaction = proto_.mutable_generic_user_interface()
+ ->mutable_interactions()
+ ->add_interactions();
+
+ interaction->add_callbacks()->mutable_set_value();
+ interaction->add_callbacks()->mutable_show_info_popup();
+ interaction->add_callbacks()->mutable_show_list_popup();
+ interaction->add_callbacks()->mutable_show_calendar_popup();
+ interaction->add_callbacks()->mutable_compute_value();
+ interaction->add_callbacks()->mutable_set_text();
+ interaction->add_callbacks()->mutable_set_view_visibility();
+ interaction->add_callbacks()->mutable_set_view_enabled();
+ interaction->add_callbacks()->mutable_show_generic_popup();
+ interaction->add_callbacks()->mutable_create_nested_ui();
+ interaction->add_callbacks()->mutable_clear_view_container();
+ interaction->add_callbacks()->mutable_for_each();
+ Run();
+}
+
+} // namespace
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/actions/show_details_action.cc b/chromium/components/autofill_assistant/browser/actions/show_details_action.cc
index d6f7f8319b8..ea319e79d9a 100644
--- a/chromium/components/autofill_assistant/browser/actions/show_details_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/show_details_action.cc
@@ -26,7 +26,7 @@ ShowDetailsAction::ShowDetailsAction(ActionDelegate* delegate,
ShowDetailsAction::~ShowDetailsAction() {}
void ShowDetailsAction::InternalProcessAction(ProcessActionCallback callback) {
- std::unique_ptr<Details> details = nullptr;
+ std::unique_ptr<Details> details;
bool details_valid = true;
switch (proto_.show_details().data_to_show_case()) {
diff --git a/chromium/components/autofill_assistant/browser/actions/show_details_action.h b/chromium/components/autofill_assistant/browser/actions/show_details_action.h
index b84c8c7d9af..e95c68a510b 100644
--- a/chromium/components/autofill_assistant/browser/actions/show_details_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/show_details_action.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SHOW_DETAILS_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SHOW_DETAILS_ACTION_H_
-#include <string>
-
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
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
index dfb40e021a5..2e0ef41c1c1 100644
--- a/chromium/components/autofill_assistant/browser/actions/show_details_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/show_details_action_unittest.cc
@@ -11,6 +11,7 @@
#include "components/autofill/core/browser/geo/country_names.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/user_model.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
@@ -57,6 +58,7 @@ class ShowDetailsActionTest : public testing::Test {
}
UserData user_data_;
+ UserModel user_model_;
CollectUserDataOptions user_data_options_;
MockActionDelegate mock_action_delegate_;
base::MockCallback<Action::ProcessActionCallback> callback_;
@@ -83,7 +85,8 @@ TEST_F(ShowDetailsActionTest, DetailsCase) {
TEST_F(ShowDetailsActionTest, ContactDetailsCase) {
proto_.set_contact_details("contact");
- user_data_.selected_addresses_["contact"] = MakeAutofillProfile();
+ user_model_.SetSelectedAutofillProfile("contact", MakeAutofillProfile(),
+ &user_data_);
user_data_options_.request_payer_name = true;
EXPECT_CALL(mock_action_delegate_, SetDetails(_, _));
@@ -95,7 +98,8 @@ TEST_F(ShowDetailsActionTest, ContactDetailsCase) {
TEST_F(ShowDetailsActionTest, ShippingAddressCase) {
proto_.set_shipping_address("shipping");
- user_data_.selected_addresses_["shipping"] = MakeAutofillProfile();
+ user_model_.SetSelectedAutofillProfile("shipping", MakeAutofillProfile(),
+ &user_data_);
EXPECT_CALL(mock_action_delegate_, SetDetails(_, _));
EXPECT_CALL(
@@ -106,7 +110,7 @@ TEST_F(ShowDetailsActionTest, ShippingAddressCase) {
TEST_F(ShowDetailsActionTest, CreditCardCase) {
proto_.set_credit_card(true);
- user_data_.selected_card_ = MakeCreditCard();
+ user_model_.SetSelectedCreditCard(MakeCreditCard(), &user_data_);
EXPECT_CALL(mock_action_delegate_, SetDetails(_, _));
EXPECT_CALL(
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 aa34dfcf241..e76fefd0fd7 100644
--- a/chromium/components/autofill_assistant/browser/actions/show_form_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/show_form_action.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SHOW_FORM_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_SHOW_FORM_ACTION_H_
-#include <string>
-
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action.cc b/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action.cc
index 28e4b376fae..816677bb152 100644
--- a/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action.cc
@@ -7,13 +7,13 @@
#include <utility>
#include "base/containers/flat_map.h"
-#include "base/optional.h"
#include "components/autofill_assistant/browser/actions/action_delegate.h"
#include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/user_data_util.h"
#include "components/autofill_assistant/browser/user_model.h"
#include "components/autofill_assistant/browser/web/element.h"
#include "content/public/browser/web_contents.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -113,6 +113,10 @@ ShowGenericUiAction::~ShowGenericUiAction() {
delegate_->GetPersonalDataManager()->RemoveObserver(this);
}
+bool ShowGenericUiAction::ShouldInterruptOnPause() const {
+ return true;
+}
+
void ShowGenericUiAction::InternalProcessAction(
ProcessActionCallback callback) {
callback_ = std::move(callback);
diff --git a/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action.h b/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action.h
index 9ce2f26e0f1..d00c1c9a72c 100644
--- a/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action.h
@@ -31,6 +31,9 @@ class ShowGenericUiAction : public Action,
ShowGenericUiAction(const ShowGenericUiAction&) = delete;
ShowGenericUiAction& operator=(const ShowGenericUiAction&) = delete;
+ // Overrides Action:
+ bool ShouldInterruptOnPause() const override;
+
// Overrides WaitForDomObserver:
void OnInterruptStarted() override;
void OnInterruptFinished() override;
diff --git a/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action_unittest.cc
index 469beb5c5fe..3e817fa823f 100644
--- a/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/show_generic_ui_action_unittest.cc
@@ -14,6 +14,8 @@
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/user_model.h"
#include "components/autofill_assistant/browser/value_util.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -36,19 +38,20 @@ using ::testing::SizeIs;
using ::testing::UnorderedElementsAre;
using ::testing::UnorderedElementsAreArray;
-class ShowGenericUiActionTest : public content::RenderViewHostTestHarness {
+class ShowGenericUiActionTest : public testing::Test {
public:
- ShowGenericUiActionTest() {}
-
void SetUp() override {
- RenderViewHostTestHarness::SetUp();
+ web_contents_ = content::WebContentsTester::CreateTestWebContents(
+ &browser_context_, nullptr);
+ content::WebContentsTester::For(web_contents_.get())
+ ->SetLastCommittedURL(GURL(kFakeUrl));
- ON_CALL(mock_action_delegate_, OnSetGenericUi(_, _, _))
+ ON_CALL(mock_action_delegate_, SetGenericUi(_, _, _))
.WillByDefault(
Invoke([&](std::unique_ptr<GenericUserInterfaceProto> generic_ui,
- base::OnceCallback<void(const ClientStatus&)>&
+ base::OnceCallback<void(const ClientStatus&)>
end_action_callback,
- base::OnceCallback<void(const ClientStatus&)>&
+ base::OnceCallback<void(const ClientStatus&)>
view_inflation_finished_callback) {
std::move(view_inflation_finished_callback)
.Run(ClientStatus(ACTION_APPLIED));
@@ -67,10 +70,8 @@ class ShowGenericUiActionTest : public content::RenderViewHostTestHarness {
.WillByDefault(
RunOnceCallback<1>(std::vector<WebsiteLoginManager::Login>{
WebsiteLoginManager::Login(GURL(kFakeUrl), kFakeUsername)}));
- content::WebContentsTester::For(web_contents())
- ->SetLastCommittedURL(GURL(kFakeUrl));
ON_CALL(mock_action_delegate_, GetWebContents())
- .WillByDefault(Return(web_contents()));
+ .WillByDefault(Return(web_contents_.get()));
}
protected:
@@ -85,6 +86,10 @@ class ShowGenericUiActionTest : public content::RenderViewHostTestHarness {
return action;
}
+ content::BrowserTaskEnvironment task_environment_;
+ content::RenderViewHostTestEnabler rvh_test_enabler_;
+ content::TestBrowserContext browser_context_;
+ std::unique_ptr<content::WebContents> web_contents_;
UserData user_data_;
UserModel user_model_;
MockPersonalDataManager mock_personal_data_manager_;
@@ -95,13 +100,12 @@ class ShowGenericUiActionTest : public content::RenderViewHostTestHarness {
};
TEST_F(ShowGenericUiActionTest, FailedViewInflationEndsAction) {
- ON_CALL(mock_action_delegate_, OnSetGenericUi(_, _, _))
- .WillByDefault(
- Invoke([&](std::unique_ptr<GenericUserInterfaceProto> generic_ui,
- base::OnceCallback<void(const ClientStatus&)>&
- end_action_callback,
- base::OnceCallback<void(const ClientStatus&)>&
- view_inflation_finished_callback) {
+ ON_CALL(mock_action_delegate_, SetGenericUi(_, _, _))
+ .WillByDefault(Invoke(
+ [&](std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)> end_action_callback,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) {
std::move(view_inflation_finished_callback)
.Run(ClientStatus(INVALID_ACTION));
}));
@@ -117,7 +121,7 @@ TEST_F(ShowGenericUiActionTest, FailedViewInflationEndsAction) {
TEST_F(ShowGenericUiActionTest, GoesIntoPromptState) {
InSequence seq;
EXPECT_CALL(mock_action_delegate_, Prompt(_, _, _, _, _)).Times(1);
- EXPECT_CALL(mock_action_delegate_, OnSetGenericUi(_, _, _)).Times(1);
+ EXPECT_CALL(mock_action_delegate_, SetGenericUi(_, _, _)).Times(1);
EXPECT_CALL(mock_action_delegate_, ClearGenericUi()).Times(1);
EXPECT_CALL(mock_action_delegate_, CleanUpAfterPrompt()).Times(1);
EXPECT_CALL(
@@ -157,13 +161,13 @@ TEST_F(ShowGenericUiActionTest, NonEmptyOutputModel) {
proto_.add_output_model_identifiers("value_2");
- ON_CALL(mock_action_delegate_, OnSetGenericUi(_, _, _))
- .WillByDefault(
- Invoke([this](std::unique_ptr<GenericUserInterfaceProto> generic_ui,
- base::OnceCallback<void(const ClientStatus&)>&
- end_action_callback,
- base::OnceCallback<void(const ClientStatus&)>&
- view_inflation_finished_callback) {
+ ON_CALL(mock_action_delegate_, SetGenericUi(_, _, _))
+ .WillByDefault(Invoke(
+ [this](
+ std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)> end_action_callback,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) {
std::move(view_inflation_finished_callback)
.Run(ClientStatus(ACTION_APPLIED));
user_model_.SetValue("value_2", SimpleValue(std::string("change")));
@@ -200,7 +204,7 @@ TEST_F(ShowGenericUiActionTest, OutputModelNotSubsetOfInputModel) {
proto_.add_output_model_identifiers("value_2");
proto_.add_output_model_identifiers("value_3");
- EXPECT_CALL(mock_action_delegate_, OnSetGenericUi(_, _, _)).Times(0);
+ EXPECT_CALL(mock_action_delegate_, SetGenericUi(_, _, _)).Times(0);
EXPECT_CALL(mock_action_delegate_, ClearGenericUi()).Times(1);
EXPECT_CALL(
callback_,
@@ -250,6 +254,9 @@ TEST_F(ShowGenericUiActionTest, RequestProfiles) {
autofill::test::SetProfileInfo(
&profile_a, "Marion", "Mitchell", "Morrison", "marion@me.xyz", "Fox",
"123 Zoo St.", "unit 5", "Hollywood", "CA", "91601", "US", "16505678910");
+ AutofillProfileProto profile_a_proto;
+ profile_a_proto.set_guid(profile_a.guid());
+
ON_CALL(mock_personal_data_manager_, IsAutofillProfileEnabled)
.WillByDefault(Return(true));
ON_CALL(mock_personal_data_manager_, GetProfiles)
@@ -260,7 +267,7 @@ TEST_F(ShowGenericUiActionTest, RequestProfiles) {
// Keep action alive by storing it in local variable.
auto action = Run();
- EXPECT_THAT(user_model_.GetProfile(profile_a.guid())->Compare(profile_a),
+ EXPECT_THAT(user_model_.GetProfile(profile_a_proto)->Compare(profile_a),
Eq(0));
ValueProto expected_value;
expected_value.set_is_client_side_only(true);
@@ -273,13 +280,15 @@ TEST_F(ShowGenericUiActionTest, RequestProfiles) {
"editor@gmail.com", "", "203 Barfield Lane",
"", "Mountain View", "CA", "94043", "US",
"+12345678901");
+ AutofillProfileProto profile_b_proto;
+ profile_b_proto.set_guid(profile_b.guid());
ON_CALL(mock_personal_data_manager_, GetProfiles)
.WillByDefault(Return(
std::vector<autofill::AutofillProfile*>({&profile_a, &profile_b})));
mock_personal_data_manager_.NotifyPersonalDataObserver();
- EXPECT_THAT(user_model_.GetProfile(profile_a.guid())->Compare(profile_a),
+ EXPECT_THAT(user_model_.GetProfile(profile_a_proto)->Compare(profile_a),
Eq(0));
- EXPECT_THAT(user_model_.GetProfile(profile_b.guid())->Compare(profile_b),
+ EXPECT_THAT(user_model_.GetProfile(profile_b_proto)->Compare(profile_b),
Eq(0));
expected_value.mutable_profiles()->add_values()->set_guid(profile_b.guid());
EXPECT_THAT(user_model_.GetValue("profiles")->profiles().values(),
@@ -290,8 +299,8 @@ TEST_F(ShowGenericUiActionTest, RequestProfiles) {
.WillByDefault(
Return(std::vector<autofill::AutofillProfile*>({&profile_b})));
mock_personal_data_manager_.NotifyPersonalDataObserver();
- EXPECT_EQ(user_model_.GetProfile(profile_a.guid()), nullptr);
- EXPECT_THAT(user_model_.GetProfile(profile_b.guid())->Compare(profile_b),
+ EXPECT_EQ(user_model_.GetProfile(profile_a_proto), nullptr);
+ EXPECT_THAT(user_model_.GetProfile(profile_b_proto)->Compare(profile_b),
Eq(0));
expected_value.Clear();
expected_value.set_is_client_side_only(true);
@@ -305,8 +314,8 @@ TEST_F(ShowGenericUiActionTest, RequestProfiles) {
.WillByDefault(Return(
std::vector<autofill::AutofillProfile*>({&profile_a, &profile_b})));
mock_personal_data_manager_.NotifyPersonalDataObserver();
- EXPECT_EQ(user_model_.GetProfile(profile_a.guid()), nullptr);
- EXPECT_THAT(user_model_.GetProfile(profile_b.guid())->Compare(profile_b),
+ EXPECT_EQ(user_model_.GetProfile(profile_a_proto), nullptr);
+ EXPECT_THAT(user_model_.GetProfile(profile_b_proto)->Compare(profile_b),
Eq(0));
expected_value.Clear();
expected_value.set_is_client_side_only(true);
@@ -332,6 +341,8 @@ TEST_F(ShowGenericUiActionTest, RequestCreditCards) {
autofill::test::SetCreditCardInfo(&credit_card_a, "Marion Mitchell",
"4111 1111 1111 1111", "01", "2050",
profile_a.guid());
+ AutofillCreditCardProto credit_card_a_proto;
+ credit_card_a_proto.set_guid(credit_card_a.guid());
ON_CALL(mock_personal_data_manager_, GetCreditCards)
.WillByDefault(
Return(std::vector<autofill::CreditCard*>({&credit_card_a})));
@@ -341,7 +352,7 @@ TEST_F(ShowGenericUiActionTest, RequestCreditCards) {
auto action = Run();
EXPECT_THAT(
- user_model_.GetCreditCard(credit_card_a.guid())->Compare(credit_card_a),
+ user_model_.GetCreditCard(credit_card_a_proto)->Compare(credit_card_a),
Eq(0));
ValueProto expected_value;
expected_value.set_is_client_side_only(true);
@@ -359,15 +370,17 @@ TEST_F(ShowGenericUiActionTest, RequestCreditCards) {
autofill::test::SetCreditCardInfo(&credit_card_b, "John Doe",
"4111 1111 1111 1111", "01", "2050",
profile_b.guid());
+ AutofillCreditCardProto credit_card_b_proto;
+ credit_card_b_proto.set_guid(credit_card_b.guid());
ON_CALL(mock_personal_data_manager_, GetCreditCards)
.WillByDefault(Return(std::vector<autofill::CreditCard*>(
{&credit_card_a, &credit_card_b})));
mock_personal_data_manager_.NotifyPersonalDataObserver();
EXPECT_THAT(
- user_model_.GetCreditCard(credit_card_a.guid())->Compare(credit_card_a),
+ user_model_.GetCreditCard(credit_card_a_proto)->Compare(credit_card_a),
Eq(0));
EXPECT_THAT(
- user_model_.GetCreditCard(credit_card_b.guid())->Compare(credit_card_b),
+ user_model_.GetCreditCard(credit_card_b_proto)->Compare(credit_card_b),
Eq(0));
expected_value.mutable_credit_cards()->add_values()->set_guid(
credit_card_b.guid());
@@ -380,9 +393,9 @@ TEST_F(ShowGenericUiActionTest, RequestCreditCards) {
.WillByDefault(
Return(std::vector<autofill::CreditCard*>({&credit_card_b})));
mock_personal_data_manager_.NotifyPersonalDataObserver();
- EXPECT_EQ(user_model_.GetCreditCard(credit_card_a.guid()), nullptr);
+ EXPECT_EQ(user_model_.GetCreditCard(credit_card_a_proto), nullptr);
EXPECT_THAT(
- user_model_.GetCreditCard(credit_card_b.guid())->Compare(credit_card_b),
+ user_model_.GetCreditCard(credit_card_b_proto)->Compare(credit_card_b),
Eq(0));
expected_value.Clear();
expected_value.set_is_client_side_only(true);
@@ -398,9 +411,9 @@ TEST_F(ShowGenericUiActionTest, RequestCreditCards) {
.WillByDefault(Return(std::vector<autofill::CreditCard*>(
{&credit_card_a, &credit_card_b})));
mock_personal_data_manager_.NotifyPersonalDataObserver();
- EXPECT_EQ(user_model_.GetCreditCard(credit_card_a.guid()), nullptr);
+ EXPECT_EQ(user_model_.GetCreditCard(credit_card_a_proto), nullptr);
EXPECT_THAT(
- user_model_.GetCreditCard(credit_card_b.guid())->Compare(credit_card_b),
+ user_model_.GetCreditCard(credit_card_b_proto)->Compare(credit_card_b),
Eq(0));
expected_value.Clear();
expected_value.set_is_client_side_only(true);
@@ -445,7 +458,7 @@ TEST_F(ShowGenericUiActionTest, ElementPreconditionMissesIdentifier) {
->add_filters()
->set_css_selector("selector");
- EXPECT_CALL(mock_action_delegate_, OnSetGenericUi(_, _, _)).Times(0);
+ EXPECT_CALL(mock_action_delegate_, SetGenericUi(_, _, _)).Times(0);
EXPECT_CALL(mock_action_delegate_, ClearGenericUi()).Times(1);
EXPECT_CALL(
callback_,
@@ -459,13 +472,12 @@ TEST_F(ShowGenericUiActionTest, ElementPreconditionMissesIdentifier) {
}
TEST_F(ShowGenericUiActionTest, EndActionOnNavigation) {
- ON_CALL(mock_action_delegate_, OnSetGenericUi(_, _, _))
- .WillByDefault(
- Invoke([&](std::unique_ptr<GenericUserInterfaceProto> generic_ui,
- base::OnceCallback<void(const ClientStatus&)>&
- end_action_callback,
- base::OnceCallback<void(const ClientStatus&)>&
- view_inflation_finished_callback) {
+ ON_CALL(mock_action_delegate_, SetGenericUi(_, _, _))
+ .WillByDefault(Invoke(
+ [&](std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)> end_action_callback,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) {
std::move(view_inflation_finished_callback)
.Run(ClientStatus(ACTION_APPLIED));
}));
@@ -498,13 +510,12 @@ TEST_F(ShowGenericUiActionTest, BreakingNavigationBeforeUiIsSet) {
bool browse_mode, bool browse_mode_invisible) {
std::move(end_navigation_callback).Run();
});
- ON_CALL(mock_action_delegate_, OnSetGenericUi(_, _, _))
- .WillByDefault(
- Invoke([&](std::unique_ptr<GenericUserInterfaceProto> generic_ui,
- base::OnceCallback<void(const ClientStatus&)>&
- end_action_callback,
- base::OnceCallback<void(const ClientStatus&)>&
- view_inflation_finished_callback) {
+ ON_CALL(mock_action_delegate_, SetGenericUi(_, _, _))
+ .WillByDefault(Invoke(
+ [&](std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)> end_action_callback,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) {
std::move(view_inflation_finished_callback)
.Run(ClientStatus(ACTION_APPLIED));
// Also end action when UI is set. At this point, the action should
diff --git a/chromium/components/autofill_assistant/browser/actions/stop_action.h b/chromium/components/autofill_assistant/browser/actions/stop_action.h
index 33276a57b96..e1e11cc72c9 100644
--- a/chromium/components/autofill_assistant/browser/actions/stop_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/stop_action.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_STOP_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_STOP_ACTION_H_
-#include <string>
-
#include "base/macros.h"
#include "components/autofill_assistant/browser/actions/action.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/stopwatch.h b/chromium/components/autofill_assistant/browser/actions/stopwatch.h
index 403ba4c0243..64f7fd2a83e 100644
--- a/chromium/components/autofill_assistant/browser/actions/stopwatch.h
+++ b/chromium/components/autofill_assistant/browser/actions/stopwatch.h
@@ -6,7 +6,6 @@
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_STOPWATCH_H_
#include <ostream>
-#include <string>
#include "base/time/time.h"
@@ -91,4 +90,4 @@ class ActionStopwatch {
};
} // namespace autofill_assistant
-#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_ACTION_TIMER_H_
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_STOPWATCH_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/tell_action.h b/chromium/components/autofill_assistant/browser/actions/tell_action.h
index 857444a6849..1463fdd4641 100644
--- a/chromium/components/autofill_assistant/browser/actions/tell_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/tell_action.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_TELL_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_TELL_ACTION_H_
-#include <string>
-
#include "base/macros.h"
#include "components/autofill_assistant/browser/actions/action.h"
diff --git a/chromium/components/autofill_assistant/browser/actions/use_address_action.cc b/chromium/components/autofill_assistant/browser/actions/use_address_action.cc
index 5dad3b63d02..7cc22428a31 100644
--- a/chromium/components/autofill_assistant/browser/actions/use_address_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/use_address_action.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_data_util.h"
#include "components/autofill_assistant/browser/actions/action_delegate.h"
@@ -20,6 +19,7 @@
#include "components/autofill_assistant/browser/user_data_util.h"
#include "components/autofill_assistant/browser/user_model.h"
#include "components/autofill_assistant/browser/value_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -96,9 +96,9 @@ void UseAddressAction::InternalProcessAction(
return;
}
auto* profile = delegate_->GetUserModel()->GetProfile(
- profile_value->profiles().values(0).guid());
+ profile_value->profiles().values(0));
if (profile == nullptr) {
- VLOG(1) << "UseAddress failed: profile not found for guid "
+ VLOG(1) << "UseAddress failed: profile not found for: "
<< *profile_value;
EndAction(ClientStatus(PRECONDITION_FAILED));
return;
diff --git a/chromium/components/autofill_assistant/browser/actions/use_address_action.h b/chromium/components/autofill_assistant/browser/actions/use_address_action.h
index 03dfa2c8cac..2c145c1b705 100644
--- a/chromium/components/autofill_assistant/browser/actions/use_address_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/use_address_action.h
@@ -6,7 +6,6 @@
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_USE_ADDRESS_ACTION_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/callback.h"
@@ -56,4 +55,4 @@ class UseAddressAction : public Action {
};
} // namespace autofill_assistant
-#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_AUTOFILL_ACTION_H_
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_USE_ADDRESS_ACTION_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/use_address_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/use_address_action_unittest.cc
index 71c8e4a3b0c..3410f169e94 100644
--- a/chromium/components/autofill_assistant/browser/actions/use_address_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/use_address_action_unittest.cc
@@ -50,8 +50,9 @@ class UseAddressActionTest : public testing::Test {
autofill::test::SetProfileInfo(&profile_, kFirstName, "", kLastName, kEmail,
"", "", "", "", "", "", "", kPhoneNumber);
// Store copies of |profile_| in |user_data_| and |user_model_|.
- user_data_.selected_addresses_[kAddressName] =
- std::make_unique<autofill::AutofillProfile>(profile_);
+ user_model_.SetSelectedAutofillProfile(
+ kAddressName, std::make_unique<autofill::AutofillProfile>(profile_),
+ &user_data_);
auto profiles = std::make_unique<
std::vector<std::unique_ptr<autofill::AutofillProfile>>>();
profiles->emplace_back(
@@ -88,11 +89,12 @@ class UseAddressActionTest : public testing::Test {
return action;
}
- UseAddressProto::RequiredField* AddRequiredField(ActionProto* action,
- std::string value_expression,
- std::string selector) {
+ RequiredFieldProto* AddRequiredField(ActionProto* action,
+ autofill::ServerFieldType field,
+ const std::string& selector) {
auto* required_field = action->mutable_use_address()->add_required_fields();
- required_field->set_value_expression(value_expression);
+ required_field->mutable_value_expression()->add_chunk()->set_key(
+ static_cast<int>(field));
*required_field->mutable_element() = ToSelectorProto(selector);
return required_field;
}
@@ -173,7 +175,7 @@ TEST_F(UseAddressActionTest, ResolveProfileByNameSucceeds) {
*use_address->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
use_address->set_name(kAddressName);
EXPECT_CALL(mock_action_delegate_,
- OnFillAddressForm(Pointee(Eq(profile_)), _, _))
+ FillAddressForm(Pointee(Eq(profile_)), _, _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED, ProcessAction(action));
}
@@ -208,7 +210,7 @@ TEST_F(UseAddressActionTest, ResolveProfileByModelIdentifierSucceeds) {
*use_address->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
use_address->set_model_identifier(kModelIdentifier);
EXPECT_CALL(mock_action_delegate_,
- OnFillAddressForm(Pointee(Eq(profile_)), _, _))
+ FillAddressForm(Pointee(Eq(profile_)), _, _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED, ProcessAction(action));
}
@@ -217,8 +219,12 @@ TEST_F(UseAddressActionTest, PreconditionFailedPopulatesUnexpectedErrorInfo) {
InSequence seq;
ActionProto action_proto = CreateUseAddressAction();
- user_data_.selected_addresses_[kAddressName] = nullptr;
- user_data_.selected_addresses_["one_more"] = nullptr;
+ user_model_.SetSelectedAutofillProfile(kAddressName, nullptr, &user_data_);
+ user_model_.SetSelectedAutofillProfile(
+ "one_more",
+ std::make_unique<autofill::AutofillProfile>(base::GenerateGUID(),
+ "www.example.com"),
+ &user_data_);
UseAddressAction action(&mock_action_delegate_, action_proto);
@@ -230,8 +236,7 @@ TEST_F(UseAddressActionTest, PreconditionFailedPopulatesUnexpectedErrorInfo) {
processed_action.status());
const auto& 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("one_more", error_info.client_memory_address_key_names());
EXPECT_EQ(kAddressName, error_info.address_key_requested());
EXPECT_TRUE(error_info.address_pointee_was_null());
}
@@ -244,7 +249,7 @@ TEST_F(UseAddressActionTest, ShortWaitForElementVisible) {
ActionProto action_proto = CreateUseAddressAction();
// Autofill succeeds.
- EXPECT_CALL(mock_action_delegate_, OnFillAddressForm(NotNull(), _, _))
+ EXPECT_CALL(mock_action_delegate_, FillAddressForm(NotNull(), _, _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Validation succeeds.
@@ -259,28 +264,16 @@ TEST_F(UseAddressActionTest, ValidationSucceeds) {
InSequence seq;
ActionProto action_proto = CreateUseAddressAction();
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::NAME_FIRST,
"#first_name");
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_LAST)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::NAME_LAST,
"#last_name");
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::EMAIL_ADDRESS)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::EMAIL_ADDRESS,
"#email");
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_,
- OnFillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
+ FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Validation succeeds.
@@ -296,23 +289,11 @@ TEST_F(UseAddressActionTest, FallbackFails) {
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseAddressAction();
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::NAME_FIRST,
"#first_name");
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_LAST)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::NAME_LAST,
"#last_name");
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::EMAIL_ADDRESS)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::EMAIL_ADDRESS,
"#email");
Selector email_selector({"#email"});
@@ -321,7 +302,7 @@ TEST_F(UseAddressActionTest, FallbackFails) {
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_,
- OnFillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
+ FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Validation fails when getting FIRST_NAME.
@@ -376,23 +357,11 @@ TEST_F(UseAddressActionTest, FillAddressWithFallback) {
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseAddressAction();
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::NAME_FIRST,
"#first_name");
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_LAST)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::NAME_LAST,
"#last_name");
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::EMAIL_ADDRESS)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::EMAIL_ADDRESS,
"#email");
Selector first_name_selector({"#first_name"});
@@ -401,7 +370,7 @@ TEST_F(UseAddressActionTest, FillAddressWithFallback) {
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_,
- OnFillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
+ FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// First validation fails with an empty value, called once for each field.
@@ -443,7 +412,7 @@ TEST_F(UseAddressActionTest, AutofillFailureWithoutRequiredFieldsIsFatal) {
ActionProto action_proto = CreateUseAddressAction();
EXPECT_CALL(mock_action_delegate_,
- OnFillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
+ FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(ClientStatus(OTHER_ACTION_STATUS)));
ProcessedActionProto processed_action;
@@ -465,17 +434,13 @@ TEST_F(UseAddressActionTest,
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseAddressAction();
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::NAME_FIRST,
"#first_name");
Selector first_name_selector({"#first_name"});
EXPECT_CALL(mock_action_delegate_,
- OnFillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
+ FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(ClientStatus(OTHER_ACTION_STATUS)));
// First validation fails.
@@ -519,13 +484,24 @@ TEST_F(UseAddressActionTest, FallbackForPhoneSucceeds) {
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseAddressAction();
- AddRequiredField(&action_proto, "(+${12}) (${11}) ${10}", "#phone_number");
+ auto* required_field =
+ action_proto.mutable_use_address()->add_required_fields();
+ *required_field->mutable_value_expression() =
+ test_util::ValueExpressionBuilder()
+ .addChunk("(+")
+ .addChunk(autofill::ServerFieldType::PHONE_HOME_COUNTRY_CODE)
+ .addChunk(") (")
+ .addChunk(autofill::ServerFieldType::PHONE_HOME_CITY_CODE)
+ .addChunk(") ")
+ .addChunk(autofill::ServerFieldType::PHONE_HOME_NUMBER)
+ .toProto();
+ *required_field->mutable_element() = ToSelectorProto("#phone_number");
Selector phone_number_selector({"#phone_number"});
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_,
- OnFillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
+ FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Validation fails when getting phone number.
@@ -563,12 +539,7 @@ TEST_F(UseAddressActionTest, ForcedFallbackWithKeystrokes) {
ActionProto action_proto = CreateUseAddressAction();
auto* name_required = AddRequiredField(
- &action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}"}),
- "#first_name");
+ &action_proto, autofill::ServerFieldType::NAME_FIRST, "#first_name");
name_required->set_forced(true);
name_required->set_fill_strategy(SIMULATE_KEY_PRESSES);
name_required->set_delay_in_millisecond(1000);
@@ -577,7 +548,7 @@ TEST_F(UseAddressActionTest, ForcedFallbackWithKeystrokes) {
// Autofill succeeds.
EXPECT_CALL(mock_action_delegate_,
- OnFillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
+ FillAddressForm(NotNull(), Eq(Selector({kFakeSelector})), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
// Do not check required field.
@@ -601,7 +572,7 @@ TEST_F(UseAddressActionTest, ForcedFallbackWithKeystrokes) {
.WillOnce(RunOnceCallback<3>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
EXPECT_CALL(
- mock_action_delegate_,
+ mock_web_controller_,
ClickOrTapElement(ClickType::CLICK, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(mock_web_controller_,
@@ -628,18 +599,14 @@ TEST_F(UseAddressActionTest, SkippingAutofill) {
ActionProto action_proto;
action_proto.mutable_use_address()->set_name(kAddressName);
- AddRequiredField(&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}"}),
+ AddRequiredField(&action_proto, autofill::ServerFieldType::NAME_FIRST,
"#first_name");
action_proto.mutable_use_address()->set_skip_autofill(true);
Selector first_name_selector({"#first_name"});
EXPECT_CALL(mock_action_delegate_, OnShortWaitForElement(_, _)).Times(0);
- EXPECT_CALL(mock_action_delegate_, OnFillAddressForm(_, _, _)).Times(0);
+ EXPECT_CALL(mock_action_delegate_, FillAddressForm(_, _, _)).Times(0);
// First validation fails.
EXPECT_CALL(mock_web_controller_,
diff --git a/chromium/components/autofill_assistant/browser/actions/use_credit_card_action.cc b/chromium/components/autofill_assistant/browser/actions/use_credit_card_action.cc
index d3411fdb68e..d7949db7167 100644
--- a/chromium/components/autofill_assistant/browser/actions/use_credit_card_action.cc
+++ b/chromium/components/autofill_assistant/browser/actions/use_credit_card_action.cc
@@ -10,9 +10,7 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_data_util.h"
@@ -24,6 +22,7 @@
#include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/field_formatter.h"
#include "components/autofill_assistant/browser/user_model.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -74,16 +73,16 @@ void UseCreditCardAction::InternalProcessAction(
<< *credit_card_value;
}
auto* credit_card = delegate_->GetUserModel()->GetCreditCard(
- credit_card_value->credit_cards().values(0).guid());
+ credit_card_value->credit_cards().values(0));
if (credit_card == nullptr) {
- VLOG(1) << "UseCreditCard failed: card not found for guid "
+ VLOG(1) << "UseCreditCard failed: card not found for: "
<< *credit_card_value;
EndAction(ClientStatus(PRECONDITION_FAILED));
return;
}
credit_card_ = std::make_unique<autofill::CreditCard>(*credit_card);
} else {
- auto* credit_card = delegate_->GetUserData()->selected_card_.get();
+ const auto* credit_card = delegate_->GetUserData()->selected_card();
if (credit_card == nullptr) {
VLOG(1) << "UseCreditCard failed: card not found in user_data";
EndAction(ClientStatus(PRECONDITION_FAILED));
diff --git a/chromium/components/autofill_assistant/browser/actions/use_credit_card_action.h b/chromium/components/autofill_assistant/browser/actions/use_credit_card_action.h
index 1f25170a2c0..2f291de9c4a 100644
--- a/chromium/components/autofill_assistant/browser/actions/use_credit_card_action.h
+++ b/chromium/components/autofill_assistant/browser/actions/use_credit_card_action.h
@@ -61,4 +61,4 @@ class UseCreditCardAction : public Action {
};
} // namespace autofill_assistant
-#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_AUTOFILL_ACTION_H_
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_USE_CREDIT_CARD_ACTION_H_
diff --git a/chromium/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc b/chromium/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc
index da735a92b35..0a527eb041d 100644
--- a/chromium/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc
@@ -25,6 +25,7 @@ namespace autofill_assistant {
namespace {
const char kFakeSelector[] = "#selector";
const char kFakeCvc[] = "123";
+const char16_t kFakeCvc16[] = u"123";
const char kModelIdentifier[] = "identifier";
const char kCardName[] = "Adam West";
const char kCardNumber[] = "4111111111111111";
@@ -49,8 +50,8 @@ class UseCreditCardActionTest : public testing::Test {
/* billing_address_id= */ "");
// Store copies of |credit_card_| in |user_data_| and |user_model_|.
- user_data_.selected_card_ =
- std::make_unique<autofill::CreditCard>(credit_card_);
+ user_model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(credit_card_), &user_data_);
auto cards =
std::make_unique<std::vector<std::unique_ptr<autofill::CreditCard>>>();
cards->emplace_back(std::make_unique<autofill::CreditCard>(credit_card_));
@@ -87,7 +88,7 @@ class UseCreditCardActionTest : public testing::Test {
credit_card
? std::make_unique<autofill::CreditCard>(*credit_card)
: nullptr,
- base::UTF8ToUTF16(kFakeCvc));
+ kFakeCvc16);
});
test_util::MockFindAnyElement(mock_web_controller_);
}
@@ -100,12 +101,11 @@ class UseCreditCardActionTest : public testing::Test {
return action;
}
- UseCreditCardProto::RequiredField* AddRequiredField(
- ActionProto* action,
- std::string value_expression,
- std::string selector) {
+ RequiredFieldProto* AddRequiredField(ActionProto* action,
+ int key,
+ const std::string& selector) {
auto* required_field = action->mutable_use_card()->add_required_fields();
- required_field->set_value_expression(value_expression);
+ required_field->mutable_value_expression()->add_chunk()->set_key(key);
*required_field->mutable_element() = ToSelectorProto(selector);
return required_field;
}
@@ -153,7 +153,7 @@ TEST_F(UseCreditCardActionTest, PreconditionFailedNoCreditCardInUserData) {
ActionProto action;
auto* use_card = action.mutable_use_card();
*use_card->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
- user_data_.selected_card_.reset();
+ user_model_.SetSelectedCreditCard(nullptr, &user_data_);
EXPECT_EQ(ProcessedActionStatusProto::PRECONDITION_FAILED,
ProcessAction(action));
}
@@ -168,10 +168,9 @@ TEST_F(UseCreditCardActionTest, CreditCardInUserDataSucceeds) {
ActionProto action;
auto* use_card = action.mutable_use_card();
*use_card->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
- EXPECT_CALL(
- mock_action_delegate_,
- OnFillCardForm(Pointee(Eq(credit_card_)), base::UTF8ToUTF16(kFakeCvc),
- Selector({kFakeSelector}), _))
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(Pointee(Eq(credit_card_)),
+ std::u16string(kFakeCvc16),
+ Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<3>(OkClientStatus()));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED, ProcessAction(action));
}
@@ -205,10 +204,9 @@ TEST_F(UseCreditCardActionTest, CreditCardInUserModelSucceeds) {
auto* use_card = action.mutable_use_card();
*use_card->mutable_form_field_element() = ToSelectorProto(kFakeSelector);
use_card->set_model_identifier(kModelIdentifier);
- EXPECT_CALL(
- mock_action_delegate_,
- OnFillCardForm(Pointee(Eq(credit_card_)), base::UTF8ToUTF16(kFakeCvc),
- Selector({kFakeSelector}), _))
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(Pointee(Eq(credit_card_)),
+ std::u16string(kFakeCvc16),
+ Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<3>(OkClientStatus()));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED, ProcessAction(action));
}
@@ -216,10 +214,10 @@ TEST_F(UseCreditCardActionTest, CreditCardInUserModelSucceeds) {
TEST_F(UseCreditCardActionTest, FillCreditCard) {
ActionProto action = CreateUseCreditCardAction();
- user_data_.selected_card_ = std::make_unique<autofill::CreditCard>();
- EXPECT_CALL(mock_action_delegate_,
- OnFillCardForm(_, base::UTF8ToUTF16(kFakeCvc),
- Selector({kFakeSelector}), _))
+ user_model_.SetSelectedCreditCard(std::make_unique<autofill::CreditCard>(),
+ &user_data_);
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(_, std::u16string(kFakeCvc16),
+ Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<3>(OkClientStatus()));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED, ProcessAction(action));
@@ -231,19 +229,19 @@ TEST_F(UseCreditCardActionTest, FillCreditCardRequiredFieldsFilled) {
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
ActionProto action = CreateUseCreditCardAction();
- AddRequiredField(&action,
- base::NumberToString(static_cast<int>(
- AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE)),
- "#cvc");
- AddRequiredField(&action,
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH)),
- "#expmonth");
+ AddRequiredField(
+ &action,
+ static_cast<int>(AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE),
+ "#cvc");
+ AddRequiredField(
+ &action,
+ static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH),
+ "#expmonth");
- user_data_.selected_card_ = std::make_unique<autofill::CreditCard>();
- EXPECT_CALL(mock_action_delegate_,
- OnFillCardForm(_, base::UTF8ToUTF16(kFakeCvc),
- Selector({kFakeSelector}), _))
+ user_model_.SetSelectedCreditCard(std::make_unique<autofill::CreditCard>(),
+ &user_data_);
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(_, std::u16string(kFakeCvc16),
+ Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<3>(OkClientStatus()));
EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED, ProcessAction(action));
@@ -258,58 +256,33 @@ TEST_F(UseCreditCardActionTest, FillCreditCardWithFallback) {
ActionProto action = CreateUseCreditCardAction();
AddRequiredField(
&action,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE)),
- "}"}),
+ static_cast<int>(AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE),
"#cvc");
AddRequiredField(
&action,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH)),
- "}"}),
+ static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH),
"#expmonth");
AddRequiredField(
&action,
- base::StrCat(
- {"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::CREDIT_CARD_EXP_2_DIGIT_YEAR)),
- "}"}),
+ static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_2_DIGIT_YEAR),
"#expyear2");
AddRequiredField(
&action,
- base::StrCat(
- {"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::CREDIT_CARD_EXP_4_DIGIT_YEAR)),
- "}"}),
+ static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_EXP_4_DIGIT_YEAR),
"#expyear4");
AddRequiredField(
&action,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::CREDIT_CARD_NAME_FULL)),
- "}"}),
+ static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NAME_FULL),
"#card_name");
AddRequiredField(
- &action,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::CREDIT_CARD_NUMBER)),
- "}"}),
+ &action, static_cast<int>(autofill::ServerFieldType::CREDIT_CARD_NUMBER),
"#card_number");
AddRequiredField(&action,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- AutofillFormatProto::CREDIT_CARD_NETWORK)),
- "}"}),
+ static_cast<int>(AutofillFormatProto::CREDIT_CARD_NETWORK),
"#network");
- EXPECT_CALL(mock_action_delegate_,
- OnFillCardForm(_, base::UTF8ToUTF16(kFakeCvc),
- Selector({kFakeSelector}), _))
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(_, std::u16string(kFakeCvc16),
+ Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<3>(OkClientStatus()));
Selector cvc_selector({"#cvc"});
@@ -390,19 +363,16 @@ TEST_F(UseCreditCardActionTest, ForcedFallbackWithKeystrokes) {
ActionProto action = CreateUseCreditCardAction();
auto* cvc_required = AddRequiredField(
&action,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE)),
- "}"}),
+ static_cast<int>(AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE),
"#cvc");
cvc_required->set_forced(true);
cvc_required->set_fill_strategy(SIMULATE_KEY_PRESSES);
cvc_required->set_delay_in_millisecond(1000);
- user_data_.selected_card_ = std::make_unique<autofill::CreditCard>();
- EXPECT_CALL(mock_action_delegate_,
- OnFillCardForm(_, base::UTF8ToUTF16(kFakeCvc),
- Selector({kFakeSelector}), _))
+ user_model_.SetSelectedCreditCard(std::make_unique<autofill::CreditCard>(),
+ &user_data_);
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(_, std::u16string(kFakeCvc16),
+ Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<3>(OkClientStatus()));
// Do not check required field.
@@ -427,7 +397,7 @@ TEST_F(UseCreditCardActionTest, ForcedFallbackWithKeystrokes) {
.WillOnce(RunOnceCallback<3>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
EXPECT_CALL(
- mock_action_delegate_,
+ mock_web_controller_,
ClickOrTapElement(ClickType::CLICK, EqualsElement(expected_element), _))
.WillOnce(RunOnceCallback<2>(OkClientStatus()));
EXPECT_CALL(mock_web_controller_,
@@ -454,17 +424,14 @@ TEST_F(UseCreditCardActionTest, SkippingAutofill) {
ActionProto action;
AddRequiredField(
&action,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE)),
- "}"}),
+ static_cast<int>(AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE),
"#cvc");
action.mutable_use_card()->set_skip_autofill(true);
Selector cvc_selector({"#cvc"});
EXPECT_CALL(mock_action_delegate_, OnShortWaitForElement(_, _)).Times(0);
- EXPECT_CALL(mock_action_delegate_, OnFillCardForm(_, _, _, _)).Times(0);
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(_, _, _, _)).Times(0);
// First validation fails.
EXPECT_CALL(mock_web_controller_,
@@ -492,10 +459,10 @@ TEST_F(UseCreditCardActionTest, SkippingAutofill) {
TEST_F(UseCreditCardActionTest, AutofillFailureWithoutRequiredFieldsIsFatal) {
ActionProto action_proto = CreateUseCreditCardAction();
- user_data_.selected_card_ = std::make_unique<autofill::CreditCard>();
- EXPECT_CALL(mock_action_delegate_,
- OnFillCardForm(_, base::UTF8ToUTF16(kFakeCvc),
- Selector({kFakeSelector}), _))
+ user_model_.SetSelectedCreditCard(std::make_unique<autofill::CreditCard>(),
+ &user_data_);
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(_, std::u16string(kFakeCvc16),
+ Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<3>(ClientStatus(OTHER_ACTION_STATUS)));
ProcessedActionProto processed_action;
@@ -519,18 +486,15 @@ TEST_F(UseCreditCardActionTest,
ActionProto action_proto = CreateUseCreditCardAction();
AddRequiredField(
&action_proto,
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE)),
- "}"}),
+ static_cast<int>(AutofillFormatProto::CREDIT_CARD_VERIFICATION_CODE),
"#cvc");
Selector cvc_selector({"#cvc"});
- user_data_.selected_card_ = std::make_unique<autofill::CreditCard>();
- EXPECT_CALL(mock_action_delegate_,
- OnFillCardForm(_, base::UTF8ToUTF16(kFakeCvc),
- Selector({kFakeSelector}), _))
+ user_model_.SetSelectedCreditCard(std::make_unique<autofill::CreditCard>(),
+ &user_data_);
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(_, std::u16string(kFakeCvc16),
+ Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<3>(ClientStatus(OTHER_ACTION_STATUS)));
// First validation fails.
@@ -573,14 +537,20 @@ TEST_F(UseCreditCardActionTest, FallbackForCardExpirationSucceeds) {
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseCreditCardAction();
- AddRequiredField(&action_proto, "${53} - ${55}", "#expiration_date");
+ auto* required_field = action_proto.mutable_use_card()->add_required_fields();
+ *required_field->mutable_value_expression() =
+ test_util::ValueExpressionBuilder()
+ .addChunk(autofill::ServerFieldType::CREDIT_CARD_EXP_MONTH)
+ .addChunk(" - ")
+ .addChunk(autofill::ServerFieldType::CREDIT_CARD_EXP_4_DIGIT_YEAR)
+ .toProto();
+ *required_field->mutable_element() = ToSelectorProto("#expiration_date");
Selector expiration_date_selector({"#expiration_date"});
// Autofill succeeds.
- EXPECT_CALL(mock_action_delegate_,
- OnFillCardForm(_, base::UTF8ToUTF16(kFakeCvc),
- Selector({kFakeSelector}), _))
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(_, std::u16string(kFakeCvc16),
+ Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<3>(OkClientStatus()));
// Validation fails when getting expiration date.
@@ -617,14 +587,17 @@ TEST_F(UseCreditCardActionTest, FallbackFails) {
.WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
ActionProto action_proto = CreateUseCreditCardAction();
- AddRequiredField(&action_proto, "${57}", "#expiration_date");
+ AddRequiredField(
+ &action_proto,
+ static_cast<int>(
+ autofill::ServerFieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR),
+ "#expiration_date");
Selector expiration_date_selector({"#expiration_date"});
// Autofill succeeds.
- EXPECT_CALL(mock_action_delegate_,
- OnFillCardForm(_, base::UTF8ToUTF16(kFakeCvc),
- Selector({kFakeSelector}), _))
+ EXPECT_CALL(mock_action_delegate_, FillCardForm(_, std::u16string(kFakeCvc16),
+ Selector({kFakeSelector}), _))
.WillOnce(RunOnceCallback<3>(OkClientStatus()));
// Validation fails when getting expiration date.
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 e7df447b8c4..7575d96c383 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
@@ -41,8 +41,8 @@ class WaitForDocumentActionTest : public testing::Test {
void SetUp() override {
ON_CALL(mock_action_delegate_, GetWebController)
.WillByDefault(Return(&mock_web_controller_));
- ON_CALL(mock_action_delegate_, OnWaitForDocumentReadyState(_, _, _))
- .WillByDefault(RunOnceCallback<2>(OkClientStatus(), DOCUMENT_COMPLETE,
+ ON_CALL(mock_action_delegate_, WaitForDocumentReadyState(_, _, _, _))
+ .WillByDefault(RunOnceCallback<3>(OkClientStatus(), DOCUMENT_COMPLETE,
base::TimeDelta::FromSeconds(0)));
}
@@ -138,8 +138,8 @@ TEST_F(WaitForDocumentActionTest, WaitForDocumentInteractive) {
EXPECT_CALL(mock_web_controller_, GetDocumentReadyState(_, _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), DOCUMENT_LOADING));
EXPECT_CALL(mock_action_delegate_,
- OnWaitForDocumentReadyState(DOCUMENT_INTERACTIVE, _, _))
- .WillOnce(RunOnceCallback<2>(OkClientStatus(), DOCUMENT_INTERACTIVE,
+ WaitForDocumentReadyState(_, DOCUMENT_INTERACTIVE, _, _))
+ .WillOnce(RunOnceCallback<3>(OkClientStatus(), DOCUMENT_INTERACTIVE,
base::TimeDelta::FromSeconds(0)));
proto_.set_timeout_ms(1000);
Run();
@@ -157,8 +157,8 @@ TEST_F(WaitForDocumentActionTest, WaitForDocumentInteractiveTimesOut) {
EXPECT_CALL(mock_web_controller_, GetDocumentReadyState(_, _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), DOCUMENT_LOADING));
EXPECT_CALL(mock_action_delegate_,
- OnWaitForDocumentReadyState(DOCUMENT_COMPLETE, _, _))
- .WillOnce(RunOnceCallback<2>(ClientStatus(TIMED_OUT),
+ WaitForDocumentReadyState(_, DOCUMENT_COMPLETE, _, _))
+ .WillOnce(RunOnceCallback<3>(ClientStatus(TIMED_OUT),
DOCUMENT_UNKNOWN_READY_STATE,
base::TimeDelta::FromSeconds(0)));
// The second time the document is reported interactive.
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 f2ad62cfc70..c5b4cc45d37 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
@@ -12,6 +12,7 @@
#include "base/test/mock_callback.h"
#include "components/autofill_assistant/browser/actions/action_test_utils.h"
#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
+#include "components/autofill_assistant/browser/wait_for_dom_observer.h"
#include "components/autofill_assistant/browser/web/element.h"
#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -36,7 +37,7 @@ class WaitForDomActionTest : public testing::Test {
.WillByDefault(RunOnceCallback<1>(
ClientStatus(ELEMENT_RESOLUTION_FAILED), nullptr));
- EXPECT_CALL(mock_action_delegate_, OnWaitForDom(_, _, _, _))
+ EXPECT_CALL(mock_action_delegate_, WaitForDomWithSlowWarning(_, _, _, _, _))
.WillRepeatedly(Invoke(this, &WaitForDomActionTest::FakeWaitForDom));
}
@@ -45,11 +46,11 @@ class WaitForDomActionTest : public testing::Test {
void FakeWaitForDom(
base::TimeDelta max_wait_time,
bool allow_interrupt,
+ WaitForDomObserver* observer,
base::RepeatingCallback<
void(BatchElementChecker*,
- base::OnceCallback<void(const ClientStatus&)>)>& check_elements,
- base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>&
- callback) {
+ base::OnceCallback<void(const ClientStatus&)>)> check_elements,
+ base::OnceCallback<void(const ClientStatus&, base::TimeDelta)> callback) {
checker_ = std::make_unique<BatchElementChecker>();
has_check_elements_result_ = false;
check_elements.Run(
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 525b08af0f3..f5f5803d05f 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
@@ -5,11 +5,8 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_WAIT_FOR_NAVIGATION_ACTION_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ACTIONS_WAIT_FOR_NAVIGATION_ACTION_H_
-#include <string>
-
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/autofill_assistant/browser/actions/action.h"
diff --git a/chromium/components/autofill_assistant/browser/autofill_assistant_onboarding_fetcher.cc b/chromium/components/autofill_assistant/browser/autofill_assistant_onboarding_fetcher.cc
index 83025ae3891..aee95644688 100644
--- a/chromium/components/autofill_assistant/browser/autofill_assistant_onboarding_fetcher.cc
+++ b/chromium/components/autofill_assistant/browser/autofill_assistant_onboarding_fetcher.cc
@@ -129,7 +129,7 @@ AutofillAssistantOnboardingFetcher::ParseResponse(
base::JSONReader::ValueWithError data =
base::JSONReader::ReadAndReturnValueWithError(*response_body);
- if (data.value == base::nullopt) {
+ if (data.value == absl::nullopt) {
DVLOG(1) << "Parse error: " << data.error_message;
return ResultStatus::kInvalidJson;
}
diff --git a/chromium/components/autofill_assistant/browser/basic_interactions.cc b/chromium/components/autofill_assistant/browser/basic_interactions.cc
index 15ecb97a3c2..161b6434886 100644
--- a/chromium/components/autofill_assistant/browser/basic_interactions.cc
+++ b/chromium/components/autofill_assistant/browser/basic_interactions.cc
@@ -156,52 +156,55 @@ bool ValueToString(UserModel* user_model,
break;
}
case ValueProto::kCreditCards: {
- if (proto.autofill_format().pattern().empty()) {
+ if (proto.autofill_format().value_expression().chunk().empty()) {
DVLOG(2) << "Error evaluating " << __func__ << ": pattern not set";
return false;
}
auto* credit_card =
- user_model->GetCreditCard(value->credit_cards().values(i).guid());
+ user_model->GetCreditCard(value->credit_cards().values(i));
if (!credit_card) {
DVLOG(2) << "Error evaluating " << __func__
<< ": credit card not found";
return false;
}
- auto formatted_string = field_formatter::FormatString(
- proto.autofill_format().pattern(),
+ std::string formatted_string;
+ auto format_status = field_formatter::FormatExpression(
+ proto.autofill_format().value_expression(),
field_formatter::CreateAutofillMappings(
- *credit_card, proto.autofill_format().locale()));
- if (!formatted_string.has_value()) {
+ *credit_card, proto.autofill_format().locale()),
+ /* quote_meta= */ false, &formatted_string);
+ if (!format_status.ok()) {
DVLOG(2) << "Error evaluating " << __func__
<< ": error formatting pattern '"
- << proto.autofill_format().pattern() << "'";
+ << proto.autofill_format().value_expression() << "'";
return false;
}
- result.mutable_strings()->add_values(*formatted_string);
+ result.mutable_strings()->add_values(formatted_string);
break;
}
case ValueProto::kProfiles: {
- if (proto.autofill_format().pattern().empty()) {
+ if (proto.autofill_format().value_expression().chunk().empty()) {
DVLOG(2) << "Error evaluating " << __func__ << ": pattern not set";
return false;
}
- auto* profile =
- user_model->GetProfile(value->profiles().values(i).guid());
+ auto* profile = user_model->GetProfile(value->profiles().values(i));
if (!profile) {
DVLOG(2) << "Error evaluating " << __func__ << ": profile not found";
return false;
}
- auto formatted_string = field_formatter::FormatString(
- proto.autofill_format().pattern(),
+ std::string formatted_string;
+ auto format_status = field_formatter::FormatExpression(
+ proto.autofill_format().value_expression(),
field_formatter::CreateAutofillMappings(
- *profile, proto.autofill_format().locale()));
- if (!formatted_string.has_value()) {
+ *profile, proto.autofill_format().locale()),
+ /* quote_meta= */ false, &formatted_string);
+ if (!format_status.ok()) {
DVLOG(2) << "Error evaluating " << __func__
<< ": error formatting pattern '"
- << proto.autofill_format().pattern() << "'";
+ << proto.autofill_format().value_expression() << "'";
return false;
}
- result.mutable_strings()->add_values(*formatted_string);
+ result.mutable_strings()->add_values(formatted_string);
break;
}
case ValueProto::kUserActions:
@@ -347,7 +350,7 @@ bool CreateCreditCardResponse(UserModel* user_model,
}
auto* credit_card =
- user_model->GetCreditCard(value->credit_cards().values(0).guid());
+ user_model->GetCreditCard(value->credit_cards().values(0));
if (!credit_card) {
DVLOG(2) << "Error evaluating " << __func__ << ": card not found for guid "
<< value->credit_cards().values(0).guid();
@@ -620,11 +623,24 @@ bool BasicInteractions::NotifyViewInflationFinished(
return true;
}
+bool BasicInteractions::NotifyPersistentViewInflationFinished(
+ const ClientStatus& status) {
+ if (!persistent_view_inflation_finished_callback_) {
+ return false;
+ }
+ std::move(persistent_view_inflation_finished_callback_).Run(status);
+ return true;
+}
+
void BasicInteractions::ClearCallbacks() {
end_action_callback_.Reset();
view_inflation_finished_callback_.Reset();
}
+void BasicInteractions::ClearPersistentUiCallbacks() {
+ persistent_view_inflation_finished_callback_.Reset();
+}
+
void BasicInteractions::SetEndActionCallback(
base::OnceCallback<void(const ClientStatus&)> end_action_callback) {
end_action_callback_ = std::move(end_action_callback);
@@ -637,6 +653,13 @@ void BasicInteractions::SetViewInflationFinishedCallback(
std::move(view_inflation_finished_callback);
}
+void BasicInteractions::SetPersistentViewInflationFinishedCallback(
+ base::OnceCallback<void(const ClientStatus&)>
+ persistent_view_inflation_finished_callback) {
+ persistent_view_inflation_finished_callback_ =
+ std::move(persistent_view_inflation_finished_callback);
+}
+
bool BasicInteractions::RunConditionalCallback(
const std::string& condition_identifier,
base::RepeatingCallback<void()> callback) {
diff --git a/chromium/components/autofill_assistant/browser/basic_interactions.h b/chromium/components/autofill_assistant/browser/basic_interactions.h
index fc14adf85f4..bc737c5c418 100644
--- a/chromium/components/autofill_assistant/browser/basic_interactions.h
+++ b/chromium/components/autofill_assistant/browser/basic_interactions.h
@@ -49,6 +49,11 @@ class BasicInteractions {
// inflation has finished. Can only be called during a ShowGenericUiAction.
bool NotifyViewInflationFinished(const ClientStatus& status);
+ // Runs |persistent_view_inflation_finished_callback_| to notify its owner
+ // that view inflation has finished. Can only be called during a
+ // SetPersistentUiAction.
+ bool NotifyPersistentViewInflationFinished(const ClientStatus& status);
+
// Sets the callback to end the current ShowGenericUiAction.
void SetEndActionCallback(
base::OnceCallback<void(const ClientStatus&)> end_action_callback);
@@ -58,9 +63,18 @@ class BasicInteractions {
base::OnceCallback<void(const ClientStatus&)>
view_inflation_finished_callback);
+ // Sets the callback to indicate whether view inflation of the persistent Ui
+ // was successful or not.
+ void SetPersistentViewInflationFinishedCallback(
+ base::OnceCallback<void(const ClientStatus&)>
+ persistent_view_inflation_finished_callback);
+
// Clears all callbacks associated with the current ShowGenericUi action.
void ClearCallbacks();
+ // Clears all callbacks associated with the current ConfigureGenericUi action.
+ void ClearPersistentUiCallbacks();
+
// Runs |callback| if |condition_identifier| points to a single boolean set to
// 'true'. Returns true on success (i.e., condition was evaluated
// successfully), false on failure.
@@ -73,6 +87,9 @@ class BasicInteractions {
base::OnceCallback<void(const ClientStatus&)> end_action_callback_;
base::OnceCallback<void(const ClientStatus&)>
view_inflation_finished_callback_;
+ // Set during a SetPersistentUiAction.
+ base::OnceCallback<void(const ClientStatus&)>
+ persistent_view_inflation_finished_callback_;
base::WeakPtrFactory<BasicInteractions> weak_ptr_factory_{this};
};
diff --git a/chromium/components/autofill_assistant/browser/basic_interactions_unittest.cc b/chromium/components/autofill_assistant/browser/basic_interactions_unittest.cc
index 00f3ace5a84..2f1fb9c3640 100644
--- a/chromium/components/autofill_assistant/browser/basic_interactions_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/basic_interactions_unittest.cc
@@ -8,6 +8,7 @@
#include "base/test/icu_test_util.h"
#include "base/test/mock_callback.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill_assistant/browser/actions/action_test_utils.h"
#include "components/autofill_assistant/browser/fake_script_executor_delegate.h"
#include "components/autofill_assistant/browser/generic_ui.pb.h"
#include "components/autofill_assistant/browser/user_model.h"
@@ -242,12 +243,24 @@ TEST_F(BasicInteractionsTest, ComputeValueToString) {
credit_cards_value.mutable_credit_cards()->add_values()->set_guid(
credit_card_b.guid());
user_model_.SetValue("value", credit_cards_value);
- // Formatting credit cards fails if pattern or locale are not set.
+ // Formatting credit cards fails if value_expression or locale are not set.
proto.mutable_to_string()->mutable_autofill_format()->set_locale("en-US");
EXPECT_FALSE(basic_interactions_.ComputeValue(proto));
// {name} {network} **** {last-4-digits} ({month/year})
- proto.mutable_to_string()->mutable_autofill_format()->set_pattern(
- "${51}. ${-5} **** ${-4} (${53}/${54})");
+ *proto.mutable_to_string()
+ ->mutable_autofill_format()
+ ->mutable_value_expression() = test_util::ValueExpressionBuilder()
+ .addChunk(51)
+ .addChunk(". ")
+ .addChunk(-5)
+ .addChunk(" **** ")
+ .addChunk(-4)
+ .addChunk(" (")
+ .addChunk(53)
+ .addChunk("/")
+ .addChunk(54)
+ .addChunk(")")
+ .toProto();
EXPECT_TRUE(basic_interactions_.ComputeValue(proto));
ValueProto expected_result;
expected_result.mutable_strings()->add_values(
@@ -279,11 +292,24 @@ TEST_F(BasicInteractionsTest, ComputeValueToString) {
profiles_value.mutable_profiles()->add_values()->set_guid(profile_a.guid());
profiles_value.mutable_profiles()->add_values()->set_guid(profile_b.guid());
user_model_.SetValue("value", profiles_value);
- // Formatting profiles fails if pattern is not set.
+ // Formatting profiles fails if value_expression is empty.
EXPECT_FALSE(basic_interactions_.ComputeValue(proto));
// {name_full}, {address_line_1} {address_line_2} {zip code} {city} {country}
- proto.mutable_to_string()->mutable_autofill_format()->set_pattern(
- "${7} ${30} ${31} ${35} ${33} ${36}");
+ *proto.mutable_to_string()
+ ->mutable_autofill_format()
+ ->mutable_value_expression() = test_util::ValueExpressionBuilder()
+ .addChunk(7)
+ .addChunk(" ")
+ .addChunk(30)
+ .addChunk(" ")
+ .addChunk(31)
+ .addChunk(" ")
+ .addChunk(35)
+ .addChunk(" ")
+ .addChunk(33)
+ .addChunk(" ")
+ .addChunk(36)
+ .toProto();
EXPECT_TRUE(basic_interactions_.ComputeValue(proto));
expected_result.Clear();
expected_result.mutable_strings()->add_values(
diff --git a/chromium/components/autofill_assistant/browser/client.h b/chromium/components/autofill_assistant/browser/client.h
index 8a5a4a69bf2..bd16e5abe5c 100644
--- a/chromium/components/autofill_assistant/browser/client.h
+++ b/chromium/components/autofill_assistant/browser/client.h
@@ -73,7 +73,7 @@ class Client {
virtual bool IsAccessibilityEnabled() const = 0;
// Returns the width and height of the window.
- virtual base::Optional<std::pair<int, int>> GetWindowSize() const = 0;
+ virtual absl::optional<std::pair<int, int>> GetWindowSize() const = 0;
// Returns the orientation of the screen.
virtual ClientContextProto::ScreenOrientation GetScreenOrientation()
diff --git a/chromium/components/autofill_assistant/browser/client_context.cc b/chromium/components/autofill_assistant/browser/client_context.cc
index 1fcacaeebea..e3cbab6677e 100644
--- a/chromium/components/autofill_assistant/browser/client_context.cc
+++ b/chromium/components/autofill_assistant/browser/client_context.cc
@@ -49,6 +49,9 @@ void ClientContextImpl::Update(const TriggerContext& trigger_context) {
if (trigger_context.GetDirectAction()) {
proto_.set_is_direct_action(true);
}
+ if (trigger_context.GetInChromeTriggered()) {
+ proto_.set_is_in_chrome_triggered(true);
+ }
// TODO(b/156882027): Add an integration test for accounts handling.
auto caller_email = trigger_context.GetScriptParameters().GetCallerEmail();
diff --git a/chromium/components/autofill_assistant/browser/client_context_unittest.cc b/chromium/components/autofill_assistant/browser/client_context_unittest.cc
index 7a5834f5009..19ae5176ee4 100644
--- a/chromium/components/autofill_assistant/browser/client_context_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/client_context_unittest.cc
@@ -102,13 +102,15 @@ TEST_F(ClientContextTest, UpdateWithTriggerContext) {
/* is_cct = */ true,
/* onboarding_shown = */ true,
/* is_direct_action = */ true,
- /* initial_url = */ "https://www.example.com"});
+ /* initial_url = */ "https://www.example.com",
+ /* is_in_chrome_triggered = */ true});
auto actual_client_context = client_context.AsProto();
EXPECT_THAT(actual_client_context.experiment_ids(), Eq("1,2,3"));
EXPECT_THAT(actual_client_context.is_cct(), Eq(true));
EXPECT_THAT(actual_client_context.is_onboarding_shown(), Eq(true));
EXPECT_THAT(actual_client_context.is_direct_action(), Eq(true));
+ EXPECT_THAT(actual_client_context.is_in_chrome_triggered(), Eq(true));
EXPECT_THAT(actual_client_context.accessibility_enabled(), Eq(true));
EXPECT_THAT(actual_client_context.experiment_ids(), Eq("1,2,3"));
EXPECT_THAT(actual_client_context.signed_into_chrome_status(),
@@ -128,7 +130,7 @@ TEST_F(ClientContextTest, WindowSizeIsClearedIfNoLongerAvailable) {
ClientContextImpl client_context(&mock_client_);
// When we update the context, there is no window size anymore.
- EXPECT_CALL(mock_client_, GetWindowSize()).WillOnce(Return(base::nullopt));
+ EXPECT_CALL(mock_client_, GetWindowSize()).WillOnce(Return(absl::nullopt));
auto actual_client_context = client_context.AsProto();
EXPECT_THAT(actual_client_context.window_size().width_pixels(), Eq(1080));
EXPECT_THAT(actual_client_context.window_size().height_pixels(), Eq(1920));
@@ -138,7 +140,8 @@ TEST_F(ClientContextTest, WindowSizeIsClearedIfNoLongerAvailable) {
/* is_cct = */ true,
/* onboarding_shown = */ true,
/* is_direct_action = */ true,
- /* initial_url = */ "https://www.example.com"});
+ /* initial_url = */ "https://www.example.com",
+ /* is_in_chrome_triggered = */ false});
actual_client_context = client_context.AsProto();
EXPECT_FALSE(actual_client_context.has_window_size());
@@ -159,7 +162,8 @@ TEST_F(ClientContextTest, AccountMatching) {
/* is_cct = */ false,
/* onboarding_shown = */ false,
/* is_direct_action = */ false,
- /* initial_url = */ "https://www.example.com"});
+ /* initial_url = */ "https://www.example.com",
+ /* is_in_chrome_triggered = */ false});
EXPECT_THAT(client_context.AsProto().accounts_matching_status(),
Eq(ClientContextProto::ACCOUNTS_MATCHING));
@@ -170,7 +174,8 @@ TEST_F(ClientContextTest, AccountMatching) {
/* is_cct = */ false,
/* onboarding_shown = */ false,
/* is_direct_action = */ false,
- /* initial_url = */ "https://www.example.com"});
+ /* initial_url = */ "https://www.example.com",
+ /* is_in_chrome_triggered = */ false});
EXPECT_THAT(client_context.AsProto().accounts_matching_status(),
Eq(ClientContextProto::ACCOUNTS_NOT_MATCHING));
}
diff --git a/chromium/components/autofill_assistant/browser/client_settings.h b/chromium/components/autofill_assistant/browser/client_settings.h
index 3471a120843..40207b6a181 100644
--- a/chromium/components/autofill_assistant/browser/client_settings.h
+++ b/chromium/components/autofill_assistant/browser/client_settings.h
@@ -6,10 +6,10 @@
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_CLIENT_SETTINGS_H_
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/strings/grit/components_strings.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -78,17 +78,17 @@ struct ClientSettings {
base::TimeDelta tap_shutdown_delay = base::TimeDelta::FromSeconds(5);
// Optional image drawn on top of overlays.
- base::Optional<OverlayImageProto> overlay_image;
+ absl::optional<OverlayImageProto> overlay_image;
// Optional settings intended for integration tests.
- base::Optional<ClientSettingsProto::IntegrationTestSettings>
+ absl::optional<ClientSettingsProto::IntegrationTestSettings>
integration_test_settings;
float talkback_sheet_size_fraction = 0.5f;
// Optional settings to enable back button error in BottomSheet instead of
// Snackbar.
- base::Optional<ClientSettingsProto::BackButtonSettings> back_button_settings;
+ absl::optional<ClientSettingsProto::BackButtonSettings> back_button_settings;
// Whether to show warnings related to a slow connection to the user.
bool enable_slow_connection_warnings = false;
diff --git a/chromium/components/autofill_assistant/browser/client_status.cc b/chromium/components/autofill_assistant/browser/client_status.cc
index 6e833a1646e..4ff1de0942a 100644
--- a/chromium/components/autofill_assistant/browser/client_status.cc
+++ b/chromium/components/autofill_assistant/browser/client_status.cc
@@ -142,6 +142,12 @@ std::ostream& operator<<(std::ostream& out,
case ProcessedActionStatusProto::PASSWORD_ORIGIN_MISMATCH:
out << "PASSWORD_ORIGIN_MISMATCH";
break;
+ case ProcessedActionStatusProto::TOO_MANY_OPTION_VALUES_FOUND:
+ out << "TOO_MANY_OPTION_VALUES_FOUND";
+ break;
+ case ProcessedActionStatusProto::INVALID_TARGET:
+ out << "INVALID_TARGET";
+ 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 11447bd1b27..99bbca8d782 100644
--- a/chromium/components/autofill_assistant/browser/controller.cc
+++ b/chromium/components/autofill_assistant/browser/controller.cc
@@ -23,6 +23,7 @@
#include "components/autofill_assistant/browser/trigger_context.h"
#include "components/autofill_assistant/browser/url_utils.h"
#include "components/autofill_assistant/browser/user_data.h"
+#include "components/autofill_assistant/browser/user_data_util.h"
#include "components/autofill_assistant/browser/view_layout.pb.h"
#include "components/autofill_assistant/browser/web/element_store.h"
#include "components/google/core/common/google_util.h"
@@ -253,11 +254,11 @@ int Controller::GetProgress() const {
return progress_;
}
-base::Optional<int> Controller::GetProgressActiveStep() const {
+absl::optional<int> Controller::GetProgressActiveStep() const {
return progress_active_step_;
}
-base::Optional<ShowProgressBarProto::StepProgressBarConfiguration>
+absl::optional<ShowProgressBarProto::StepProgressBarConfiguration>
Controller::GetStepProgressBarConfiguration() const {
return step_progress_bar_configuration_;
}
@@ -401,12 +402,22 @@ void Controller::SetUserActions(
SetVisibilityAndUpdateUserActions();
}
+bool Controller::ShouldChipsBeVisible() {
+ return !(is_keyboard_showing_ && is_focus_on_bottom_sheet_text_input_);
+}
+
+bool Controller::ShouldUpdateChipVisibility() {
+ return are_chips_visible_ != ShouldChipsBeVisible();
+}
+
void Controller::SetVisibilityAndUpdateUserActions() {
- // All non-cancel chips should be hidden while the keyboard is showing.
+ // All non-cancel chips should be hidden while the keyboard is showing to fill
+ // an input text field in the bottom sheet.
+ are_chips_visible_ = ShouldChipsBeVisible();
if (user_actions_) {
for (UserAction& user_action : *user_actions_) {
if (user_action.chip().type != CANCEL_ACTION) {
- user_action.chip().visible = !is_keyboard_showing_;
+ user_action.chip().visible = are_chips_visible_;
}
}
}
@@ -453,6 +464,19 @@ void Controller::SetGenericUi(
}
}
+void Controller::SetPersistentGenericUi(
+ std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) {
+ persistent_generic_user_interface_ = std::move(generic_ui);
+ basic_interactions_.SetPersistentViewInflationFinishedCallback(
+ std::move(view_inflation_finished_callback));
+ for (ControllerObserver& observer : observers_) {
+ observer.OnPersistentGenericUserInterfaceChanged(
+ persistent_generic_user_interface_.get());
+ }
+}
+
void Controller::ClearGenericUi() {
generic_user_interface_.reset();
basic_interactions_.ClearCallbacks();
@@ -461,6 +485,14 @@ void Controller::ClearGenericUi() {
}
}
+void Controller::ClearPersistentGenericUi() {
+ persistent_generic_user_interface_.reset();
+ basic_interactions_.ClearPersistentUiCallbacks();
+ for (ControllerObserver& observer : observers_) {
+ observer.OnPersistentGenericUserInterfaceChanged(nullptr);
+ }
+}
+
void Controller::SetBrowseModeInvisible(bool invisible) {
browse_mode_invisible_ = invisible;
}
@@ -699,6 +731,11 @@ const GenericUserInterfaceProto* Controller::GetGenericUiProto() const {
return generic_user_interface_.get();
}
+const GenericUserInterfaceProto* Controller::GetPersistentGenericUiProto()
+ const {
+ return persistent_generic_user_interface_.get();
+}
+
void Controller::AddObserver(ControllerObserver* observer) {
observers_.AddObserver(observer);
}
@@ -1168,7 +1205,7 @@ void Controller::InitFromParameters() {
if (details->UpdateFromParameters(trigger_context_->GetScriptParameters()))
SetDetails(std::move(details), base::TimeDelta());
- const base::Optional<std::string> overlay_color =
+ const absl::optional<std::string> overlay_color =
trigger_context_->GetScriptParameters().GetOverlayColors();
if (overlay_color) {
std::unique_ptr<OverlayColors> colors = std::make_unique<OverlayColors>();
@@ -1186,7 +1223,7 @@ void Controller::InitFromParameters() {
SetOverlayColors(std::move(colors));
}
- const base::Optional<std::string> password_change_username =
+ const absl::optional<std::string> password_change_username =
trigger_context_->GetScriptParameters().GetPasswordChangeUsername();
if (password_change_username) {
DCHECK(GetDeeplinkURL().is_valid()); // |deeplink_url_| must be set.
@@ -1366,7 +1403,7 @@ void Controller::OnFormActionLinkClicked(int link) {
}
void Controller::SetDateTimeRangeStartDate(
- const base::Optional<DateProto>& date) {
+ const absl::optional<DateProto>& date) {
if (!user_data_)
return;
@@ -1399,7 +1436,7 @@ void Controller::SetDateTimeRangeStartDate(
}
void Controller::SetDateTimeRangeStartTimeSlot(
- const base::Optional<int>& timeslot_index) {
+ const absl::optional<int>& timeslot_index) {
if (!user_data_)
return;
@@ -1432,7 +1469,7 @@ void Controller::SetDateTimeRangeStartTimeSlot(
}
void Controller::SetDateTimeRangeEndDate(
- const base::Optional<DateProto>& date) {
+ const absl::optional<DateProto>& date) {
if (!user_data_)
return;
@@ -1465,7 +1502,7 @@ void Controller::SetDateTimeRangeEndDate(
}
void Controller::SetDateTimeRangeEndTimeSlot(
- const base::Optional<int>& timeslot_index) {
+ const absl::optional<int>& timeslot_index) {
if (!user_data_)
return;
@@ -1545,7 +1582,7 @@ void Controller::SetCreditCard(
DCHECK(!collect_user_data_options_->billing_address_name.empty());
- user_data_->selected_card_ = std::move(card);
+ user_model_.SetSelectedCreditCard(std::move(card), user_data_.get());
for (ControllerObserver& observer : observers_) {
observer.OnUserDataChanged(user_data_.get(), UserData::FieldChange::CARD);
}
@@ -1562,13 +1599,8 @@ void Controller::SetProfile(
return;
}
- auto it = user_data_->selected_addresses_.find(key);
- if (it != user_data_->selected_addresses_.end()) {
- user_data_->selected_addresses_.erase(it);
- }
- if (profile != nullptr) {
- user_data_->selected_addresses_.emplace(key, std::move(profile));
- }
+ user_model_.SetSelectedAutofillProfile(key, std::move(profile),
+ user_data_.get());
for (ControllerObserver& observer : observers_) {
observer.OnUserDataChanged(user_data_.get(), field_change);
@@ -1726,7 +1758,7 @@ void Controller::PerformDelayedShutdownIfNecessary() {
if (delayed_shutdown_reason_ &&
script_url_.host() != GetCurrentURL().host()) {
Metrics::DropOutReason reason = delayed_shutdown_reason_.value();
- delayed_shutdown_reason_ = base::nullopt;
+ delayed_shutdown_reason_ = absl::nullopt;
tracking_ = false;
client_->Shutdown(reason);
}
@@ -2084,7 +2116,18 @@ bool Controller::StateNeedsUI(AutofillAssistantState state) {
void Controller::OnKeyboardVisibilityChanged(bool visible) {
is_keyboard_showing_ = visible;
- SetVisibilityAndUpdateUserActions();
+
+ if (ShouldUpdateChipVisibility()) {
+ SetVisibilityAndUpdateUserActions();
+ }
+}
+
+void Controller::OnInputTextFocusChanged(bool is_text_focused) {
+ is_focus_on_bottom_sheet_text_input_ = is_text_focused;
+
+ if (ShouldUpdateChipVisibility()) {
+ SetVisibilityAndUpdateUserActions();
+ }
}
ElementArea* Controller::touchable_element_area() {
diff --git a/chromium/components/autofill_assistant/browser/controller.h b/chromium/components/autofill_assistant/browser/controller.h
index 3b60d944aa2..61a790ee441 100644
--- a/chromium/components/autofill_assistant/browser/controller.h
+++ b/chromium/components/autofill_assistant/browser/controller.h
@@ -12,7 +12,6 @@
#include "base/callback_helpers.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/autofill_assistant/browser/basic_interactions.h"
#include "components/autofill_assistant/browser/bottom_sheet_state.h"
#include "components/autofill_assistant/browser/client.h"
@@ -36,6 +35,7 @@
#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"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class RenderFrameHost;
@@ -152,7 +152,12 @@ class Controller : public ScriptExecutorDelegate,
base::OnceCallback<void(const ClientStatus&)> end_action_callback,
base::OnceCallback<void(const ClientStatus&)>
view_inflation_finished_callback) override;
+ void SetPersistentGenericUi(
+ std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) override;
void ClearGenericUi() override;
+ void ClearPersistentGenericUi() override;
void SetBrowseModeInvisible(bool invisible) override;
bool ShouldShowWarning() override;
void SetShowFeedbackChip(bool show_feedback_chip) override;
@@ -193,10 +198,10 @@ class Controller : public ScriptExecutorDelegate,
std::vector<Details> GetDetails() const override;
const InfoBox* GetInfoBox() const override;
int GetProgress() const override;
- base::Optional<int> GetProgressActiveStep() const override;
+ absl::optional<int> GetProgressActiveStep() const override;
bool GetProgressVisible() const override;
bool GetProgressBarErrorState() const override;
- base::Optional<ShowProgressBarProto::StepProgressBarConfiguration>
+ absl::optional<ShowProgressBarProto::StepProgressBarConfiguration>
GetStepProgressBarConfiguration() const override;
const std::vector<UserAction>& GetUserActions() const override;
bool PerformUserActionWithContext(
@@ -218,12 +223,12 @@ class Controller : public ScriptExecutorDelegate,
void OnTextLinkClicked(int link) override;
void OnFormActionLinkClicked(int link) override;
void SetDateTimeRangeStartDate(
- const base::Optional<DateProto>& date) override;
+ const absl::optional<DateProto>& date) override;
void SetDateTimeRangeStartTimeSlot(
- const base::Optional<int>& timeslot_index) override;
- void SetDateTimeRangeEndDate(const base::Optional<DateProto>& date) override;
+ const absl::optional<int>& timeslot_index) override;
+ void SetDateTimeRangeEndDate(const absl::optional<DateProto>& date) override;
void SetDateTimeRangeEndTimeSlot(
- const base::Optional<int>& timeslot_index) override;
+ const absl::optional<int>& timeslot_index) override;
void SetAdditionalValue(const std::string& client_memory_key,
const ValueProto& value) override;
void GetTouchableArea(std::vector<RectF>* area) const override;
@@ -257,9 +262,11 @@ class Controller : public ScriptExecutorDelegate,
bool ShouldPromptActionExpandSheet() const override;
BasicInteractions* GetBasicInteractions() override;
const GenericUserInterfaceProto* GetGenericUiProto() const override;
+ const GenericUserInterfaceProto* GetPersistentGenericUiProto() const override;
bool ShouldShowOverlay() const override;
void ShutdownIfNecessary() override;
void OnKeyboardVisibilityChanged(bool visible) override;
+ void OnInputTextFocusChanged(bool is_text_focused) override;
private:
friend ControllerTest;
@@ -396,6 +403,8 @@ class Controller : public ScriptExecutorDelegate,
bool StateNeedsUI(AutofillAssistantState state);
+ bool ShouldChipsBeVisible();
+ bool ShouldUpdateChipVisibility();
void SetVisibilityAndUpdateUserActions();
void MakeDetailsVisible(size_t details_index);
@@ -464,12 +473,12 @@ class Controller : public ScriptExecutorDelegate,
// Current progress.
int progress_ = 0;
- base::Optional<int> progress_active_step_;
+ absl::optional<int> progress_active_step_;
// Current visibility of the progress bar. It is initially visible.
bool progress_visible_ = true;
bool progress_bar_error_state_ = false;
- base::Optional<ShowProgressBarProto::StepProgressBarConfiguration>
+ absl::optional<ShowProgressBarProto::StepProgressBarConfiguration>
step_progress_bar_configuration_;
// Current set of user actions. May be null, but never empty.
@@ -562,7 +571,7 @@ class Controller : public ScriptExecutorDelegate,
// If set, the controller entered the STOPPED state but shutdown was delayed
// until the browser has left the |script_url_.host()| for which the decision
// was taken.
- base::Optional<Metrics::DropOutReason> delayed_shutdown_reason_;
+ absl::optional<Metrics::DropOutReason> delayed_shutdown_reason_;
EventHandler event_handler_;
UserModel user_model_;
@@ -572,11 +581,15 @@ class Controller : public ScriptExecutorDelegate,
std::vector<std::string> browse_domains_allowlist_;
bool browse_mode_invisible_ = false;
bool is_keyboard_showing_ = false;
+ bool is_focus_on_bottom_sheet_text_input_ = false;
bool show_feedback_chip_on_graceful_shutdown_ = false;
+ bool are_chips_visible_ = true;
// Only set during a ShowGenericUiAction.
std::unique_ptr<GenericUserInterfaceProto> generic_user_interface_;
+ std::unique_ptr<GenericUserInterfaceProto> persistent_generic_user_interface_;
+
base::WeakPtrFactory<Controller> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Controller);
diff --git a/chromium/components/autofill_assistant/browser/controller_observer.h b/chromium/components/autofill_assistant/browser/controller_observer.h
index e99dda4e748..4b3b9eb069d 100644
--- a/chromium/components/autofill_assistant/browser/controller_observer.h
+++ b/chromium/components/autofill_assistant/browser/controller_observer.h
@@ -9,7 +9,6 @@
#include <string>
#include <vector>
-#include "base/callback_forward.h"
#include "base/observer_list.h"
#include "components/autofill_assistant/browser/details.h"
#include "components/autofill_assistant/browser/info_box.h"
@@ -20,7 +19,6 @@
#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"
namespace autofill_assistant {
@@ -129,6 +127,11 @@ class ControllerObserver : public base::CheckedObserver {
virtual void OnGenericUserInterfaceChanged(
const GenericUserInterfaceProto* generic_ui) = 0;
+ // Called when the persistent generic user interface to show has been changed
+ // or cleared.
+ virtual void OnPersistentGenericUserInterfaceChanged(
+ const GenericUserInterfaceProto* generic_ui) = 0;
+
// Called when the desired overlay behavior has changed.
virtual void OnShouldShowOverlayChanged(bool should_show) = 0;
};
diff --git a/chromium/components/autofill_assistant/browser/controller_unittest.cc b/chromium/components/autofill_assistant/browser/controller_unittest.cc
index 3bdc1976818..379987585fc 100644
--- a/chromium/components/autofill_assistant/browser/controller_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/controller_unittest.cc
@@ -2088,9 +2088,10 @@ TEST_F(ControllerTest, UserDataFormCreditCard) {
controller_->SetCreditCard(
std::make_unique<autofill::CreditCard>(*credit_card),
std::make_unique<autofill::AutofillProfile>(*billing_address));
- EXPECT_THAT(GetUserData()->selected_card_->Compare(*credit_card), Eq(0));
- EXPECT_THAT(GetUserData()->selected_addresses_["billing_address"]->Compare(
- *billing_address),
+ EXPECT_THAT(GetUserData()->selected_card()->Compare(*credit_card), Eq(0));
+ EXPECT_THAT(GetUserData()
+ ->selected_address("billing_address")
+ ->Compare(*billing_address),
Eq(0));
}
@@ -2130,11 +2131,11 @@ TEST_F(ControllerTest, UserDataChangesByOutOfLoopWrite) {
Property(&UserAction::enabled, Eq(false)))))
.Times(1);
// Can be called by a PDM update.
- controller_->WriteUserData(base::BindOnce(
- [](UserData* user_data, UserData::FieldChange* field_change) {
- auto it = user_data->selected_addresses_.find("selected_profile");
- if (it != user_data->selected_addresses_.end()) {
- user_data->selected_addresses_.erase(it);
+ controller_->WriteUserData(base::BindLambdaForTesting(
+ [this](UserData* user_data, UserData::FieldChange* field_change) {
+ if (user_data->has_selected_address("selected_profile")) {
+ controller_->GetUserModel()->SetSelectedAutofillProfile(
+ "selected_profile", nullptr, user_data);
*field_change = UserData::FieldChange::CONTACT_PROFILE;
}
}));
@@ -2213,8 +2214,9 @@ TEST_F(ControllerTest, SetShippingAddress) {
.Times(1);
controller_->SetShippingAddress(
std::make_unique<autofill::AutofillProfile>(*shipping_address));
- EXPECT_THAT(GetUserData()->selected_addresses_["shipping_address"]->Compare(
- *shipping_address),
+ EXPECT_THAT(GetUserData()
+ ->selected_address("shipping_address")
+ ->Compare(*shipping_address),
Eq(0));
}
@@ -2381,7 +2383,7 @@ TEST_F(ControllerTest, SetDateTimeRangeStartDateAfterEndDate) {
1);
EXPECT_EQ(controller_->GetUserData()->date_time_range_start_date_->day(), 21);
EXPECT_EQ(controller_->GetUserData()->date_time_range_end_date_,
- base::nullopt);
+ absl::nullopt);
}
TEST_F(ControllerTest, SetDateTimeRangeEndDateBeforeStartDate) {
@@ -2421,7 +2423,7 @@ TEST_F(ControllerTest, SetDateTimeRangeEndDateBeforeStartDate) {
EXPECT_EQ(controller_->GetUserData()->date_time_range_end_date_->month(), 1);
EXPECT_EQ(controller_->GetUserData()->date_time_range_end_date_->day(), 19);
EXPECT_EQ(controller_->GetUserData()->date_time_range_start_date_,
- base::nullopt);
+ absl::nullopt);
}
TEST_F(ControllerTest, SetDateTimeRangeSameDatesStartTimeAfterEndTime) {
@@ -2458,7 +2460,7 @@ TEST_F(ControllerTest, SetDateTimeRangeSameDatesStartTimeAfterEndTime) {
controller_->SetDateTimeRangeStartTimeSlot(1);
EXPECT_EQ(*controller_->GetUserData()->date_time_range_start_timeslot_, 1);
EXPECT_EQ(controller_->GetUserData()->date_time_range_end_timeslot_,
- base::nullopt);
+ absl::nullopt);
}
TEST_F(ControllerTest, SetDateTimeRangeSameDatesEndTimeBeforeStartTime) {
@@ -2495,7 +2497,7 @@ TEST_F(ControllerTest, SetDateTimeRangeSameDatesEndTimeBeforeStartTime) {
controller_->SetDateTimeRangeEndTimeSlot(0);
EXPECT_EQ(*controller_->GetUserData()->date_time_range_end_timeslot_, 0);
EXPECT_EQ(controller_->GetUserData()->date_time_range_start_timeslot_,
- base::nullopt);
+ absl::nullopt);
}
TEST_F(ControllerTest, SetDateTimeRangeSameDateValidTime) {
@@ -3004,4 +3006,37 @@ TEST_F(ControllerTest, OnScriptErrorWillAppendVanishingFeedbackChip) {
EXPECT_TRUE(controller_->PerformUserAction(0));
}
+// The chip should be hidden if and only if the keyboard is visible and the
+// focus is on a bottom sheet input text.
+TEST_F(ControllerTest, UpdateChipVisibility) {
+ InSequence seq;
+
+ UserAction user_action(ChipProto(), DirectActionProto(), true, std::string());
+ EXPECT_CALL(mock_observer_,
+ OnUserActionsChanged(UnorderedElementsAre(Property(
+ &UserAction::chip, Field(&Chip::visible, Eq(true))))))
+ .Times(1);
+ auto user_actions = std::make_unique<std::vector<UserAction>>();
+ user_actions->emplace_back(std::move(user_action));
+ controller_->SetUserActions(std::move(user_actions));
+
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(_)).Times(0);
+ controller_->OnKeyboardVisibilityChanged(true);
+
+ EXPECT_CALL(mock_observer_,
+ OnUserActionsChanged(UnorderedElementsAre(Property(
+ &UserAction::chip, Field(&Chip::visible, Eq(false))))))
+ .Times(1);
+ controller_->OnInputTextFocusChanged(true);
+
+ EXPECT_CALL(mock_observer_,
+ OnUserActionsChanged(UnorderedElementsAre(Property(
+ &UserAction::chip, Field(&Chip::visible, Eq(true))))))
+ .Times(1);
+ controller_->OnKeyboardVisibilityChanged(false);
+
+ EXPECT_CALL(mock_observer_, OnUserActionsChanged(_)).Times(0);
+ controller_->OnInputTextFocusChanged(false);
+}
+
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/details.cc b/chromium/components/autofill_assistant/browser/details.cc
index 0e05021ee69..c632b348d85 100644
--- a/chromium/components/autofill_assistant/browser/details.cc
+++ b/chromium/components/autofill_assistant/browser/details.cc
@@ -160,12 +160,12 @@ bool Details::UpdateFromShippingAddress(const ShowDetailsProto& proto,
bool Details::UpdateFromSelectedCreditCard(const ShowDetailsProto& proto,
const UserData* user_data,
Details* details) {
- if (user_data->selected_card_.get() == nullptr || !proto.credit_card()) {
+ if (!user_data->selected_card() || !proto.credit_card()) {
return false;
}
ShowDetailsProto updated_proto = proto;
- auto* card = user_data->selected_card_.get();
+ const auto* card = user_data->selected_card();
auto* details_proto = updated_proto.mutable_details();
details_proto->set_title(
l10n_util::GetStringUTF8(IDS_PAYMENTS_METHOD_OF_PAYMENT_LABEL));
@@ -229,7 +229,7 @@ base::Value Details::GetDebugContext() const {
}
bool Details::UpdateFromParameters(const ScriptParameters& script_parameters) {
- base::Optional<bool> show_initial = script_parameters.GetDetailsShowInitial();
+ absl::optional<bool> show_initial = script_parameters.GetDetailsShowInitial();
if (show_initial.has_value() && !*show_initial) {
return false;
}
@@ -239,48 +239,48 @@ bool Details::UpdateFromParameters(const ScriptParameters& script_parameters) {
proto_.mutable_placeholders()->set_show_image_placeholder(true);
bool details_updated = false;
- base::Optional<std::string> title = script_parameters.GetDetailsTitle();
+ absl::optional<std::string> title = script_parameters.GetDetailsTitle();
if (title) {
proto_.set_title(title.value());
details_updated = true;
}
- base::Optional<std::string> description_line_1 =
+ absl::optional<std::string> description_line_1 =
script_parameters.GetDetailsDescriptionLine1();
if (description_line_1) {
proto_.set_description_line_1(description_line_1.value());
details_updated = true;
}
- base::Optional<std::string> description_line_2 =
+ absl::optional<std::string> description_line_2 =
script_parameters.GetDetailsDescriptionLine2();
if (description_line_2) {
proto_.set_description_line_2(description_line_2.value());
details_updated = true;
}
- base::Optional<std::string> description_line_3 =
+ absl::optional<std::string> description_line_3 =
script_parameters.GetDetailsDescriptionLine3();
if (description_line_3) {
proto_.set_description_line_3(description_line_3.value());
details_updated = true;
}
- base::Optional<std::string> image_url =
+ absl::optional<std::string> image_url =
script_parameters.GetDetailsImageUrl();
if (image_url) {
proto_.set_image_url(image_url.value());
details_updated = true;
}
- base::Optional<std::string> image_accessibility_hint =
+ absl::optional<std::string> image_accessibility_hint =
script_parameters.GetDetailsImageAccessibilityHint();
if (image_accessibility_hint) {
proto_.set_image_accessibility_hint(image_accessibility_hint.value());
details_updated = true;
}
- base::Optional<std::string> image_clickthrough_url =
+ absl::optional<std::string> image_clickthrough_url =
script_parameters.GetDetailsImageClickthroughUrl();
if (image_clickthrough_url) {
proto_.mutable_image_clickthrough_data()->set_allow_clickthrough(true);
@@ -289,14 +289,14 @@ bool Details::UpdateFromParameters(const ScriptParameters& script_parameters) {
details_updated = true;
}
- base::Optional<std::string> total_price_label =
+ absl::optional<std::string> total_price_label =
script_parameters.GetDetailsTotalPriceLabel();
if (total_price_label) {
proto_.set_total_price_label(total_price_label.value());
details_updated = true;
}
- base::Optional<std::string> total_price =
+ absl::optional<std::string> total_price =
script_parameters.GetDetailsTotalPrice();
if (total_price) {
proto_.set_total_price(total_price.value());
@@ -322,11 +322,11 @@ const std::string Details::imageUrl() const {
return proto_.image_url();
}
-const base::Optional<std::string> Details::imageAccessibilityHint() const {
+const absl::optional<std::string> Details::imageAccessibilityHint() const {
if (proto_.has_image_accessibility_hint()) {
return proto_.image_accessibility_hint();
}
- return base::nullopt;
+ return absl::nullopt;
}
bool Details::imageAllowClickthrough() const {
diff --git a/chromium/components/autofill_assistant/browser/details.h b/chromium/components/autofill_assistant/browser/details.h
index 1d9faa9b8b6..d5675c2e301 100644
--- a/chromium/components/autofill_assistant/browser/details.h
+++ b/chromium/components/autofill_assistant/browser/details.h
@@ -62,7 +62,7 @@ class Details {
const std::string title() const;
const std::string imageUrl() const;
- const base::Optional<std::string> imageAccessibilityHint() const;
+ const absl::optional<std::string> imageAccessibilityHint() const;
bool imageAllowClickthrough() const;
const std::string imageDescription() const;
const std::string imagePositiveText() const;
diff --git a/chromium/components/autofill_assistant/browser/details_unittest.cc b/chromium/components/autofill_assistant/browser/details_unittest.cc
index a0d1e064119..e289abacf21 100644
--- a/chromium/components/autofill_assistant/browser/details_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/details_unittest.cc
@@ -11,6 +11,7 @@
#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/autofill_assistant/browser/user_model.h"
#include "components/strings/grit/components_strings.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/base/l10n/l10n_util.h"
@@ -59,6 +60,7 @@ class DetailsTest : public testing::Test {
}
UserData user_data_;
+ UserModel user_model_;
CollectUserDataOptions user_data_options_;
};
@@ -140,7 +142,8 @@ TEST_F(DetailsTest, UpdateFromContactDetailsNoUserDataOptions) {
TEST_F(DetailsTest, UpdateFromContactDetailsNoContactInfoRequested) {
ShowDetailsProto proto;
proto.set_contact_details("contact");
- user_data_.selected_addresses_["contact"] = MakeAutofillProfile();
+ user_model_.SetSelectedAutofillProfile("contact", MakeAutofillProfile(),
+ &user_data_);
user_data_options_.request_payer_name = false;
user_data_options_.request_payer_email = false;
EXPECT_FALSE(Details::UpdateFromContactDetails(proto, &user_data_,
@@ -150,7 +153,8 @@ TEST_F(DetailsTest, UpdateFromContactDetailsNoContactInfoRequested) {
TEST_F(DetailsTest, UpdateFromContactDetails) {
ShowDetailsProto proto;
proto.set_contact_details("contact");
- user_data_.selected_addresses_["contact"] = MakeAutofillProfile();
+ user_model_.SetSelectedAutofillProfile("contact", MakeAutofillProfile(),
+ &user_data_);
user_data_options_.request_payer_name = true;
user_data_options_.request_payer_email = true;
@@ -167,7 +171,8 @@ TEST_F(DetailsTest, UpdateFromContactDetails) {
TEST_F(DetailsTest, UpdateFromContactOnlyName) {
ShowDetailsProto proto;
proto.set_contact_details("contact");
- user_data_.selected_addresses_["contact"] = MakeAutofillProfile();
+ user_model_.SetSelectedAutofillProfile("contact", MakeAutofillProfile(),
+ &user_data_);
user_data_options_.request_payer_name = true;
user_data_options_.request_payer_email = false;
@@ -184,7 +189,8 @@ TEST_F(DetailsTest, UpdateFromContactOnlyName) {
TEST_F(DetailsTest, UpdateFromContactOnlyEmail) {
ShowDetailsProto proto;
proto.set_contact_details("contact");
- user_data_.selected_addresses_["contact"] = MakeAutofillProfile();
+ user_model_.SetSelectedAutofillProfile("contact", MakeAutofillProfile(),
+ &user_data_);
user_data_options_.request_payer_name = false;
user_data_options_.request_payer_email = true;
@@ -206,7 +212,8 @@ TEST_F(DetailsTest, UpdateFromShippingAddressNoAddressInMemory) {
TEST_F(DetailsTest, UpdateFromShippingAddress) {
ShowDetailsProto proto;
proto.set_shipping_address("shipping");
- user_data_.selected_addresses_["shipping"] = MakeAutofillProfile();
+ user_model_.SetSelectedAutofillProfile("shipping", MakeAutofillProfile(),
+ &user_data_);
Details details;
EXPECT_TRUE(Details::UpdateFromShippingAddress(proto, &user_data_, &details));
@@ -229,7 +236,7 @@ TEST_F(DetailsTest, UpdateFromSelectedCreditCardEmptyMemory) {
TEST_F(DetailsTest, UpdateFromSelectedCreditCardNotRequested) {
ShowDetailsProto proto;
proto.set_credit_card(false);
- user_data_.selected_card_ = MakeCreditCard();
+ user_model_.SetSelectedCreditCard(MakeCreditCard(), &user_data_);
EXPECT_FALSE(Details::UpdateFromSelectedCreditCard(ShowDetailsProto(),
&user_data_, nullptr));
}
@@ -237,7 +244,7 @@ TEST_F(DetailsTest, UpdateFromSelectedCreditCardNotRequested) {
TEST_F(DetailsTest, UpdateFromCreditCard) {
ShowDetailsProto proto;
proto.set_credit_card(true);
- user_data_.selected_card_ = MakeCreditCard();
+ user_model_.SetSelectedCreditCard(MakeCreditCard(), &user_data_);
Details details;
EXPECT_TRUE(
diff --git a/chromium/components/autofill_assistant/browser/devtools/BUILD.gn b/chromium/components/autofill_assistant/browser/devtools/BUILD.gn
index 08a398a1b12..dcc65ba033e 100644
--- a/chromium/components/autofill_assistant/browser/devtools/BUILD.gn
+++ b/chromium/components/autofill_assistant/browser/devtools/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("//build/config/python.gni")
-
devtools_domains = [
"accessibility",
"animation",
@@ -53,8 +51,7 @@ foreach(domain, devtools_domains) {
]
}
-# TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
-python2_action("gen_devtools_client_api") {
+action("gen_devtools_client_api") {
script = "devtools_api/client_api_generator.py"
deps = [ "//third_party/blink/public/devtools_protocol:protocol_version" ]
inputs = [
diff --git a/chromium/components/autofill_assistant/browser/devtools/devtools_api/client_api_generator.py b/chromium/components/autofill_assistant/browser/devtools/devtools_api/client_api_generator.py
index 853b5b92480..72fed749231 100644
--- a/chromium/components/autofill_assistant/browser/devtools/devtools_api/client_api_generator.py
+++ b/chromium/components/autofill_assistant/browser/devtools/devtools_api/client_api_generator.py
@@ -435,7 +435,7 @@ def InitializeDomainDependencies(json_api):
if not isinstance(json, dict):
return
- for value in json.itervalues():
+ for value in json.values():
GetDomainDepsFromRefs(domain_name, value)
if '$ref' in json:
diff --git a/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_types_h.template b/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_types_h.template
index eb5312a4982..1ab94684d13 100644
--- a/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_types_h.template
+++ b/chromium/components/autofill_assistant/browser/devtools/devtools_api/domain_types_h.template
@@ -9,7 +9,7 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_DEVTOOLS_DEVTOOLS_DOMAINS_TYPES_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_DEVTOOLS_DEVTOOLS_DOMAINS_TYPES_{{domain.domain | camelcase_to_hacker_style | upper}}_H_
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "base/values.h"
{% for domain_name in domain.dependencies %}
#include "components/autofill_assistant/browser/devtools/devtools/internal/types_forward_declarations_{{domain_name | camelcase_to_hacker_style}}.h"
@@ -102,7 +102,7 @@ class {{type.id}} {
{% for property in type.properties %}
{% if property.optional %}
- base::Optional<{{resolve_type(property).type}}> {{property.name | camelcase_to_hacker_style}}_;
+ absl::optional<{{resolve_type(property).type}}> {{property.name | camelcase_to_hacker_style}}_;
{% else %}
{{resolve_type(property).type}} {{property.name | camelcase_to_hacker_style}}_;
{% endif %}
diff --git a/chromium/components/autofill_assistant/browser/devtools/devtools_client.cc b/chromium/components/autofill_assistant/browser/devtools/devtools_client.cc
index b997f81f074..36206a2cfb8 100644
--- a/chromium/components/autofill_assistant/browser/devtools/devtools_client.cc
+++ b/chromium/components/autofill_assistant/browser/devtools/devtools_client.cc
@@ -10,7 +10,6 @@
#include "components/autofill_assistant/browser/devtools/devtools_client.h"
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/strings/strcat.h"
diff --git a/chromium/components/autofill_assistant/browser/devtools/value_conversions.h b/chromium/components/autofill_assistant/browser/devtools/value_conversions.h
index 18d08347f77..078d7998b41 100644
--- a/chromium/components/autofill_assistant/browser/devtools/value_conversions.h
+++ b/chromium/components/autofill_assistant/browser/devtools/value_conversions.h
@@ -11,6 +11,7 @@
#include <memory>
+#include "base/values.h"
#include "components/autofill_assistant/browser/devtools/error_reporter.h"
namespace autofill_assistant {
@@ -135,7 +136,7 @@ template <>
struct FromValue<base::Value> {
static std::unique_ptr<base::Value> Parse(const base::Value& value,
ErrorReporter* errors) {
- return value.CreateDeepCopy();
+ return base::Value::ToUniquePtrValue(value.Clone());
}
};
diff --git a/chromium/components/autofill_assistant/browser/dom_action.proto b/chromium/components/autofill_assistant/browser/dom_action.proto
index 324365321ce..b7b75fc4b21 100644
--- a/chromium/components/autofill_assistant/browser/dom_action.proto
+++ b/chromium/components/autofill_assistant/browser/dom_action.proto
@@ -105,3 +105,36 @@ message SelectFieldValueProto {
message FocusFieldProto {
optional ClientIdProto client_id = 1;
}
+
+// Select the |option| of a |select| element. This only sets the option in JS,
+// it does not fire a "change" event. If a "change" event is required, use in
+// combination with |SendChangeEventProto|. If the element in |option| is
+// not an option of the element in |select|, an |OPTION_VALUE_NOT_FOUND| error
+// is returned. If the element in |select| is not an HTML <select> element, an
+// |OPTION_VALUE_NOT_FOUND| error is returned.
+message SelectOptionElementProto {
+ optional ClientIdProto select_id = 1;
+ optional ClientIdProto option_id = 2;
+}
+
+// Checks if any of the tags matches the element tag of the element in
+// |client_id|. Returns |ACTION_APPLIED| if there is a match and
+// |ELEMENT_MISMATCH| otherwise.
+message CheckElementTagProto {
+ optional ClientIdProto client_id = 1;
+ repeated string any_of_tag = 2;
+}
+
+// Check whether the element in |option_d| is selected in the element in
+// |select_id|.
+message CheckOptionElementProto {
+ optional ClientIdProto select_id = 1;
+ optional ClientIdProto option_id = 2;
+
+ // If set and a mismatch happens, the action will report a failure status
+ // with |ELEMENT_MISMATCH|. If this flag is set to false, the action will not
+ // fail and simply report the result.
+ optional bool mismatch_should_fail = 3;
+
+ message Result { optional bool match = 1; }
+}
diff --git a/chromium/components/autofill_assistant/browser/element_area.h b/chromium/components/autofill_assistant/browser/element_area.h
index 01c78e11c96..2652fa0cc04 100644
--- a/chromium/components/autofill_assistant/browser/element_area.h
+++ b/chromium/components/autofill_assistant/browser/element_area.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ELEMENT_AREA_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ELEMENT_AREA_H_
-#include <string>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/components/autofill_assistant/browser/element_area_unittest.cc b/chromium/components/autofill_assistant/browser/element_area_unittest.cc
index 30c1cd68e1c..62d06b2a883 100644
--- a/chromium/components/autofill_assistant/browser/element_area_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/element_area_unittest.cc
@@ -9,7 +9,6 @@
#include <ostream>
#include "base/bind.h"
-#include "base/strings/stringprintf.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
@@ -72,10 +71,10 @@ class ElementAreaTest : public testing::Test {
base::TimeDelta::FromMilliseconds(100);
test_util::MockFindAnyElement(mock_web_controller_);
- ON_CALL(mock_web_controller_, OnGetElementRect(_, _))
+ ON_CALL(mock_web_controller_, GetElementRect(_, _))
.WillByDefault(
RunOnceCallback<1>(ClientStatus(UNEXPECTED_JS_ERROR), RectF()));
- ON_CALL(mock_web_controller_, OnGetVisualViewport(_))
+ ON_CALL(mock_web_controller_, GetVisualViewport(_))
.WillByDefault(
RunOnceCallback<0>(OkClientStatus(), RectF(0, 0, 200, 400)));
@@ -149,9 +148,9 @@ TEST_F(ElementAreaTest, GetVisualViewport) {
TEST_F(ElementAreaTest, OneRectangle) {
Selector expected_selector({"#found"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(25, 25, 75, 75)));
SetElement("#found");
@@ -163,9 +162,9 @@ TEST_F(ElementAreaTest, OneRectangle) {
TEST_F(ElementAreaTest, CallOnUpdate) {
Selector expected_selector({"#found"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(25, 25, 75, 75)));
SetElement("#found");
@@ -177,9 +176,9 @@ TEST_F(ElementAreaTest, CallOnUpdate) {
TEST_F(ElementAreaTest, CallOnUpdateAfterSetFromProto) {
Selector expected_selector({"#found"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector, 2)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector, 2)),
+ _))
.Times(2)
.WillRepeatedly(
RunOnceCallback<1>(OkClientStatus(), RectF(25, 25, 75, 75)));
@@ -193,14 +192,13 @@ TEST_F(ElementAreaTest, CallOnUpdateAfterSetFromProto) {
TEST_F(ElementAreaTest, DontCallOnUpdateWhenViewportMissing) {
Selector expected_selector({"#found"});
- // Swallowing calls to OnGetVisualViewport guarantees that the viewport
+ // Swallowing calls to GetVisualViewport guarantees that the viewport
// position will never be known.
- EXPECT_CALL(mock_web_controller_, OnGetVisualViewport(_))
- .WillOnce(DoNothing());
+ EXPECT_CALL(mock_web_controller_, GetVisualViewport(_)).WillOnce(DoNothing());
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(25, 25, 75, 75)));
SetElement("#found");
@@ -208,7 +206,7 @@ TEST_F(ElementAreaTest, DontCallOnUpdateWhenViewportMissing) {
}
TEST_F(ElementAreaTest, CallOnUpdateWhenViewportMissingAndEmptyRect) {
- EXPECT_CALL(mock_web_controller_, OnGetVisualViewport(_))
+ EXPECT_CALL(mock_web_controller_, GetVisualViewport(_))
.WillRepeatedly(
RunOnceCallback<0>(ClientStatus(UNEXPECTED_JS_ERROR), RectF()));
@@ -229,15 +227,15 @@ TEST_F(ElementAreaTest, TwoRectangles) {
EXPECT_CALL(
mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_top_left)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_top_left)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(0, 0, 25, 25)));
- EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(
- EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_bottom_right)),
- _))
+ EXPECT_CALL(
+ mock_web_controller_,
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_bottom_right)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(25, 25, 100, 100)));
ElementAreaProto area_proto;
@@ -257,14 +255,14 @@ TEST_F(ElementAreaTest, OneRectangleTwoElements) {
Selector expected_selector_2({"#element2"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_1)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_1)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(1, 3, 2, 4)));
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_2)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_2)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(5, 2, 6, 5)));
ElementAreaProto area_proto;
@@ -281,18 +279,18 @@ TEST_F(ElementAreaTest, OneRectangleTwoElements) {
TEST_F(ElementAreaTest, DoNotReportIncompleteRectangles) {
Selector expected_selector_1({"#element1"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_1)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_1)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(1, 3, 2, 4)));
// Getting the position of #element2 neither succeeds nor fails, simulating an
// intermediate state which shouldn't be reported to the callback.
Selector expected_selector_2({"#element2"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_2)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_2)),
+ _))
.WillOnce(DoNothing()); // overrides default action
ElementAreaProto area_proto;
@@ -315,24 +313,24 @@ TEST_F(ElementAreaTest, OneRectangleFourElements) {
Selector expected_selector_4({"#element4"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_1)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_1)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(0, 0, 1, 1)));
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_2)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_2)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(9, 9, 100, 100)));
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_3)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_3)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(0, 9, 1, 100)));
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_4)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_4)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(9, 0, 100, 1)));
ElementAreaProto area_proto;
@@ -353,14 +351,14 @@ TEST_F(ElementAreaTest, OneRectangleMissingElementsReported) {
Selector expected_selector_2({"#element2"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_1)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_1)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(1, 1, 2, 2)));
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_2)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_2)),
+ _))
.WillOnce(RunOnceCallback<1>(ClientStatus(UNEXPECTED_JS_ERROR), RectF()));
ElementAreaProto area_proto;
@@ -381,16 +379,16 @@ TEST_F(ElementAreaTest, FullWidthRectangle) {
Selector expected_selector_2({"#element2"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_1)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_1)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(1, 3, 2, 4)));
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector_2)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector_2)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(5, 7, 6, 8)));
- EXPECT_CALL(mock_web_controller_, OnGetVisualViewport(_))
+ EXPECT_CALL(mock_web_controller_, GetVisualViewport(_))
.WillRepeatedly(
RunOnceCallback<0>(OkClientStatus(), RectF(100, 0, 200, 400)));
@@ -415,14 +413,14 @@ TEST_F(ElementAreaTest, ElementMovesAfterUpdate) {
Selector expected_selector({"#element"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(0, 25, 100, 50)));
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(0, 50, 100, 75)));
SetElement("#element");
@@ -449,19 +447,19 @@ TEST_F(ElementAreaTest, ElementMovesWithTime) {
Selector expected_selector({"#element"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(0, 25, 100, 50)));
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(0, 50, 100, 75)));
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(0, 50, 100, 75)));
SetElement("#element");
@@ -488,9 +486,9 @@ TEST_F(ElementAreaTest, RestrictedElement) {
Selector expected_selector({"#restricted_element"});
EXPECT_CALL(mock_web_controller_,
- OnGetElementRect(EqualsElement(test_util::MockFindElement(
- mock_web_controller_, expected_selector)),
- _))
+ GetElementRect(EqualsElement(test_util::MockFindElement(
+ mock_web_controller_, expected_selector)),
+ _))
.WillOnce(RunOnceCallback<1>(OkClientStatus(), RectF(25, 25, 75, 75)));
SetElement("#restricted_element", /* restricted= */ true);
diff --git a/chromium/components/autofill_assistant/browser/element_precondition.h b/chromium/components/autofill_assistant/browser/element_precondition.h
index 6946d8961b4..12c766faf42 100644
--- a/chromium/components/autofill_assistant/browser/element_precondition.h
+++ b/chromium/components/autofill_assistant/browser/element_precondition.h
@@ -12,12 +12,12 @@
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/selector.h"
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/web/element.h"
#include "components/autofill_assistant/browser/web/element_finder.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
class BatchElementChecker;
@@ -63,7 +63,7 @@ class ElementPrecondition {
// The identifier given to this result through the script. This identifier
// can be used to later find the element in the |ElementStore|.
- base::Optional<std::string> client_id;
+ absl::optional<std::string> client_id;
};
// Add selectors from |proto| to |results_|, doing a depth-first search.
diff --git a/chromium/components/autofill_assistant/browser/event_handler.cc b/chromium/components/autofill_assistant/browser/event_handler.cc
index 543d22d176b..2ff6ba0fdcc 100644
--- a/chromium/components/autofill_assistant/browser/event_handler.cc
+++ b/chromium/components/autofill_assistant/browser/event_handler.cc
@@ -28,62 +28,62 @@ void EventHandler::RemoveObserver(const Observer* observer) {
}
// static
-base::Optional<EventHandler::EventKey> EventHandler::CreateEventKeyFromProto(
+absl::optional<EventHandler::EventKey> EventHandler::CreateEventKeyFromProto(
const EventProto& proto) {
switch (proto.kind_case()) {
case EventProto::kOnValueChanged:
if (proto.on_value_changed().model_identifier().empty()) {
VLOG(1) << "Invalid OnValueChangedEventProto: no model_identifier "
"specified";
- return base::nullopt;
+ return absl::nullopt;
}
- return base::Optional<EventHandler::EventKey>(
+ return absl::optional<EventHandler::EventKey>(
{proto.kind_case(), proto.on_value_changed().model_identifier()});
case EventProto::kOnViewClicked:
if (proto.on_view_clicked().view_identifier().empty()) {
VLOG(1) << "Invalid OnViewClickedEventProto: no view_identifier "
"specified";
- return base::nullopt;
+ return absl::nullopt;
}
- return base::Optional<EventHandler::EventKey>(
+ return absl::optional<EventHandler::EventKey>(
{proto.kind_case(), proto.on_view_clicked().view_identifier()});
case EventProto::kOnUserActionCalled:
if (proto.on_user_action_called().user_action_identifier().empty()) {
VLOG(1) << "Invalid OnUserActionCalled: no user_action_identifier "
"specified";
- return base::nullopt;
+ return absl::nullopt;
}
- return base::Optional<EventHandler::EventKey>(
+ return absl::optional<EventHandler::EventKey>(
{proto.kind_case(),
proto.on_user_action_called().user_action_identifier()});
case EventProto::kOnTextLinkClicked:
if (!proto.on_text_link_clicked().has_text_link()) {
VLOG(1) << "Invalid OnTextLinkClickedProto: no text_link specified";
- return base::nullopt;
+ return absl::nullopt;
}
- return base::Optional<EventHandler::EventKey>(
+ return absl::optional<EventHandler::EventKey>(
{proto.kind_case(),
base::NumberToString(proto.on_text_link_clicked().text_link())});
case EventProto::kOnPopupDismissed:
if (proto.on_popup_dismissed().popup_identifier().empty()) {
VLOG(1)
<< "Invalid OnPopupDismissedProto: no popup_identifier specified";
- return base::nullopt;
+ return absl::nullopt;
}
- return base::Optional<EventHandler::EventKey>(
+ return absl::optional<EventHandler::EventKey>(
{proto.kind_case(), proto.on_popup_dismissed().popup_identifier()});
case EventProto::kOnViewContainerCleared:
if (proto.on_view_container_cleared().view_identifier().empty()) {
VLOG(1) << "Invalid OnViewContainerClearedProto: no view_identifier "
"specified";
- return base::nullopt;
+ return absl::nullopt;
}
- return base::Optional<EventHandler::EventKey>(
+ return absl::optional<EventHandler::EventKey>(
{proto.kind_case(),
proto.on_view_container_cleared().view_identifier()});
case EventProto::KIND_NOT_SET:
VLOG(1) << "Error creating event: kind not set";
- return base::nullopt;
+ return absl::nullopt;
}
}
diff --git a/chromium/components/autofill_assistant/browser/event_handler.h b/chromium/components/autofill_assistant/browser/event_handler.h
index 92ac4b96344..7f6dcad1a8e 100644
--- a/chromium/components/autofill_assistant/browser/event_handler.h
+++ b/chromium/components/autofill_assistant/browser/event_handler.h
@@ -10,9 +10,9 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/user_model.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -38,7 +38,7 @@ class EventHandler {
void DispatchEvent(const EventKey& key);
- static base::Optional<EventKey> CreateEventKeyFromProto(
+ static absl::optional<EventKey> CreateEventKeyFromProto(
const EventProto& proto);
void AddObserver(Observer* observer);
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 f4b8981f19b..6beef07bfcb 100644
--- a/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.cc
+++ b/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.cc
@@ -257,8 +257,19 @@ void FakeScriptExecutorDelegate::SetGenericUi(
base::OnceCallback<void(const ClientStatus&)>
view_inflation_finished_callback) {}
+void FakeScriptExecutorDelegate::SetPersistentGenericUi(
+ std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) {
+ persistent_generic_ui_ = std::move(generic_ui);
+}
+
void FakeScriptExecutorDelegate::ClearGenericUi() {}
+void FakeScriptExecutorDelegate::ClearPersistentGenericUi() {
+ persistent_generic_ui_.reset();
+}
+
void FakeScriptExecutorDelegate::SetOverlayBehavior(
ConfigureUiStateProto::OverlayBehavior overaly_behavior) {}
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 99af22292a2..ad93fc389d9 100644
--- a/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.h
+++ b/chromium/components/autofill_assistant/browser/fake_script_executor_delegate.h
@@ -96,7 +96,12 @@ class FakeScriptExecutorDelegate : public ScriptExecutorDelegate {
base::OnceCallback<void(const ClientStatus&)> end_action_callback,
base::OnceCallback<void(const ClientStatus&)>
view_inflation_finished_callback) override;
+ void SetPersistentGenericUi(
+ std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) override;
void ClearGenericUi() override;
+ void ClearPersistentGenericUi() override;
void SetOverlayBehavior(
ConfigureUiStateProto::OverlayBehavior overlay_behavior) override;
void SetBrowseModeInvisible(bool invisible) override;
@@ -134,6 +139,10 @@ class FakeScriptExecutorDelegate : public ScriptExecutorDelegate {
const std::vector<Details>& GetDetails() { return details_; }
+ const GenericUserInterfaceProto* GetPersistentGenericUi() {
+ return persistent_generic_ui_.get();
+ }
+
InfoBox* GetInfoBox() { return info_box_.get(); }
std::vector<UserAction>* GetUserActions() { return user_actions_.get(); }
@@ -183,6 +192,7 @@ class FakeScriptExecutorDelegate : public ScriptExecutorDelegate {
bool expand_sheet_for_prompt_ = true;
std::vector<std::string> browse_domains_;
UserModel* user_model_ = nullptr;
+ std::unique_ptr<GenericUserInterfaceProto> persistent_generic_ui_;
bool require_ui_ = false;
diff --git a/chromium/components/autofill_assistant/browser/fake_starter_platform_delegate.cc b/chromium/components/autofill_assistant/browser/fake_starter_platform_delegate.cc
index 9ddb3b405eb..ce2c50ba82d 100644
--- a/chromium/components/autofill_assistant/browser/fake_starter_platform_delegate.cc
+++ b/chromium/components/autofill_assistant/browser/fake_starter_platform_delegate.cc
@@ -9,6 +9,34 @@ namespace autofill_assistant {
FakeStarterPlatformDelegate::FakeStarterPlatformDelegate() = default;
FakeStarterPlatformDelegate::~FakeStarterPlatformDelegate() = default;
+std::unique_ptr<TriggerScriptCoordinator::UiDelegate>
+FakeStarterPlatformDelegate::CreateTriggerScriptUiDelegate() {
+ return std::move(trigger_script_ui_delegate_);
+}
+
+std::unique_ptr<ServiceRequestSender>
+FakeStarterPlatformDelegate::GetTriggerScriptRequestSenderToInject() {
+ return std::move(trigger_script_request_sender_for_test_);
+}
+
+void FakeStarterPlatformDelegate::StartRegularScript(
+ GURL url,
+ std::unique_ptr<TriggerContext> trigger_context,
+ const absl::optional<TriggerScriptProto>& trigger_script) {
+ if (start_regular_script_callback_) {
+ std::move(start_regular_script_callback_)
+ .Run(url, std::move(trigger_context), trigger_script);
+ }
+}
+
+bool FakeStarterPlatformDelegate::IsRegularScriptRunning() const {
+ return is_regular_script_running_;
+}
+
+bool FakeStarterPlatformDelegate::IsRegularScriptVisible() const {
+ return is_regular_script_visible_;
+}
+
WebsiteLoginManager* FakeStarterPlatformDelegate::GetWebsiteLoginManager()
const {
return website_login_manager_;
@@ -26,7 +54,7 @@ void FakeStarterPlatformDelegate::InstallFeatureModule(
bool show_ui,
base::OnceCallback<void(Metrics::FeatureModuleInstallation result)>
callback) {
- num_install_feature_module_called++;
+ num_install_feature_module_called_++;
std::move(callback).Run(feature_module_installation_result_);
}
@@ -50,23 +78,32 @@ void FakeStarterPlatformDelegate::ShowOnboarding(
bool use_dialog_onboarding,
const TriggerContext& trigger_context,
base::OnceCallback<void(bool shown, OnboardingResult result)> callback) {
- num_show_onboarding_called++;
- std::move(callback).Run(show_onboarding_result_shown, show_onboarding_result);
+ num_show_onboarding_called_++;
+ if (on_show_onboarding_callback_) {
+ std::move(on_show_onboarding_callback_).Run(std::move(callback));
+ return;
+ }
+ std::move(callback).Run(show_onboarding_result_shown_,
+ show_onboarding_result_);
}
void FakeStarterPlatformDelegate::HideOnboarding() {}
bool FakeStarterPlatformDelegate::GetProactiveHelpSettingEnabled() const {
- return proactive_help_enabled;
+ return proactive_help_enabled_;
}
void FakeStarterPlatformDelegate::SetProactiveHelpSettingEnabled(bool enabled) {
- proactive_help_enabled = enabled;
+ proactive_help_enabled_ = enabled;
}
bool FakeStarterPlatformDelegate::GetMakeSearchesAndBrowsingBetterEnabled()
const {
- return msbb_enabled;
+ return msbb_enabled_;
+}
+
+bool FakeStarterPlatformDelegate::GetIsCustomTab() const {
+ return is_custom_tab_;
}
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/fake_starter_platform_delegate.h b/chromium/components/autofill_assistant/browser/fake_starter_platform_delegate.h
index dee7eda9bd6..b2c9bc71f04 100644
--- a/chromium/components/autofill_assistant/browser/fake_starter_platform_delegate.h
+++ b/chromium/components/autofill_assistant/browser/fake_starter_platform_delegate.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_FAKE_STARTER_PLATFORM_DELEGATE_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_FAKE_STARTER_PLATFORM_DELEGATE_H_
+#include <memory>
#include "base/callback.h"
#include "components/autofill_assistant/browser/starter_platform_delegate.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -17,6 +18,16 @@ class FakeStarterPlatformDelegate : public StarterPlatformDelegate {
~FakeStarterPlatformDelegate() override;
// Implements StarterPlatformDelegate:
+ std::unique_ptr<TriggerScriptCoordinator::UiDelegate>
+ CreateTriggerScriptUiDelegate() override;
+ std::unique_ptr<ServiceRequestSender> GetTriggerScriptRequestSenderToInject()
+ override;
+ void StartRegularScript(
+ GURL url,
+ std::unique_ptr<TriggerContext> trigger_context,
+ const absl::optional<TriggerScriptProto>& trigger_script) override;
+ bool IsRegularScriptRunning() const override;
+ bool IsRegularScriptVisible() const override;
WebsiteLoginManager* GetWebsiteLoginManager() const override;
version_info::Channel GetChannel() const override;
bool GetFeatureModuleInstalled() const override;
@@ -37,7 +48,12 @@ class FakeStarterPlatformDelegate : public StarterPlatformDelegate {
bool GetProactiveHelpSettingEnabled() const override;
void SetProactiveHelpSettingEnabled(bool enabled) override;
bool GetMakeSearchesAndBrowsingBetterEnabled() const override;
+ bool GetIsCustomTab() const override;
+ // Intentionally public to give tests direct access.
+ std::unique_ptr<TriggerScriptCoordinator::UiDelegate>
+ trigger_script_ui_delegate_;
+ std::unique_ptr<ServiceRequestSender> trigger_script_request_sender_for_test_;
WebsiteLoginManager* website_login_manager_ = nullptr;
version_info::Channel channel_ = version_info::Channel::UNKNOWN;
bool feature_module_installed_ = true;
@@ -45,13 +61,24 @@ class FakeStarterPlatformDelegate : public StarterPlatformDelegate {
Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED;
bool is_first_time_user_ = false;
bool onboarding_accepted_ = true;
- bool show_onboarding_result_shown = false;
- OnboardingResult show_onboarding_result = OnboardingResult::ACCEPTED;
- bool proactive_help_enabled = true;
- bool msbb_enabled = true;
+ bool show_onboarding_result_shown_ = false;
+ OnboardingResult show_onboarding_result_ = OnboardingResult::ACCEPTED;
+ base::OnceCallback<void(
+ base::OnceCallback<void(bool, OnboardingResult)> result_callback)>
+ on_show_onboarding_callback_;
+ bool proactive_help_enabled_ = true;
+ bool msbb_enabled_ = true;
+ bool is_custom_tab_ = true;
+ base::OnceCallback<void(
+ GURL url,
+ std::unique_ptr<TriggerContext> trigger_context,
+ const absl::optional<TriggerScriptProto>& trigger_script)>
+ start_regular_script_callback_;
+ bool is_regular_script_running_ = false;
+ bool is_regular_script_visible_ = false;
- int num_install_feature_module_called = 0;
- int num_show_onboarding_called = 0;
+ int num_install_feature_module_called_ = 0;
+ int num_show_onboarding_called_ = 0;
};
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/features.cc b/chromium/components/autofill_assistant/browser/features.cc
index 8ab1acdd21b..2ec934a7a56 100644
--- a/chromium/components/autofill_assistant/browser/features.cc
+++ b/chromium/components/autofill_assistant/browser/features.cc
@@ -36,10 +36,19 @@ const base::Feature kAutofillAssistantDisableProactiveHelpTiedToMSBB{
"AutofillAssistantDisableProactiveHelpTiedToMSBB",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Whether Autofill Assistant should enable in-Chrome triggering, i.e., without
-// requiring first party trigger surfaces.
-const base::Feature kAutofillAssistantInChromeTriggering{
- "AutofillAssistantInChromeTriggering", base::FEATURE_DISABLED_BY_DEFAULT};
+// Whether Autofill Assistant should enable in-CCT triggering, i.e., requesting
+// and showing trigger scripts in CCTs without explicit user request. This
+// requires also specifying valid URL heuristics via
+// |kAutofillAssistantUrlHeuristics| to take effect.
+const base::Feature kAutofillAssistantInCCTTriggering{
+ "AutofillAssistantInCctTriggering", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Whether Autofill Assistant should enable in-tab triggering, i.e., requesting
+// and showing trigger scripts in regular tabs without explicit user request.
+// This requires also specifying valid URL heuristics via
+// |kAutofillAssistantUrlHeuristics| to take effect.
+const base::Feature kAutofillAssistantInTabTriggering{
+ "AutofillAssistantInTabTriggering", base::FEATURE_DISABLED_BY_DEFAULT};
// Controls whether to show the "Send feedback" chip while in an error state.
const base::Feature kAutofillAssistantFeedbackChip{
@@ -55,6 +64,12 @@ const base::Feature kAutofillAssistantLoadDFMForTriggerScripts{
const base::Feature kAutofillAssistantProactiveHelp{
"AutofillAssistantProactiveHelp", base::FEATURE_ENABLED_BY_DEFAULT};
+// Used to configure the start heuristics for
+// |kAutofillAssistantInCctTriggering| and/or
+// |kAutofillAssistantInTabTriggering|.
+const base::Feature kAutofillAssistantUrlHeuristics{
+ "AutofillAssistantUrlHeuristics", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Use Chrome's TabHelper system to deal with the life cycle of WebContent's
// depending Autofill Assistant objects.
const base::Feature kAutofillAssistantWithTabHelper{
diff --git a/chromium/components/autofill_assistant/browser/features.h b/chromium/components/autofill_assistant/browser/features.h
index aaf8c82917d..d25ae40fd06 100644
--- a/chromium/components/autofill_assistant/browser/features.h
+++ b/chromium/components/autofill_assistant/browser/features.h
@@ -19,10 +19,12 @@ extern const base::Feature kAutofillAssistantDialogOnboarding;
extern const base::Feature kAutofillAssistantDirectActions;
extern const base::Feature kAutofillAssistantDisableOnboardingFlow;
extern const base::Feature kAutofillAssistantDisableProactiveHelpTiedToMSBB;
-extern const base::Feature kAutofillAssistantInChromeTriggering;
+extern const base::Feature kAutofillAssistantInCCTTriggering;
+extern const base::Feature kAutofillAssistantInTabTriggering;
extern const base::Feature kAutofillAssistantFeedbackChip;
extern const base::Feature kAutofillAssistantLoadDFMForTriggerScripts;
extern const base::Feature kAutofillAssistantProactiveHelp;
+extern const base::Feature kAutofillAssistantUrlHeuristics;
extern const base::Feature kAutofillAssistantWithTabHelper;
} // namespace features
diff --git a/chromium/components/autofill_assistant/browser/field_formatter.cc b/chromium/components/autofill_assistant/browser/field_formatter.cc
index cb47cf53d8c..007c4020b1a 100644
--- a/chromium/components/autofill_assistant/browser/field_formatter.cc
+++ b/chromium/components/autofill_assistant/browser/field_formatter.cc
@@ -21,14 +21,14 @@ namespace {
// Regex to find placeholders of the form ${key}, where key is an arbitrary
// string that does not contain curly braces. The first capture group is for
// the prefix before the key, the second for the key itself.
-const char kPlaceholderExtractor[] = R"re(([^$]*)\$\{([^{}]+)\})re";
+const char kPlaceholderExtractor[] = R"re((.*?)\$\{([^{}]+)\})re";
-base::Optional<std::string> GetFieldValue(
+absl::optional<std::string> GetFieldValue(
const std::map<std::string, std::string>& mappings,
const std::string& key) {
auto it = mappings.find(key);
if (it == mappings.end()) {
- return base::nullopt;
+ return absl::nullopt;
}
return it->second;
}
@@ -52,7 +52,7 @@ std::map<std::string, std::string> CreateFormGroupMappings(
namespace autofill_assistant {
namespace field_formatter {
-base::Optional<std::string> FormatString(
+absl::optional<std::string> FormatString(
const std::string& pattern,
const std::map<std::string, std::string>& mappings,
bool strict) {
@@ -70,7 +70,7 @@ base::Optional<std::string> FormatString(
if (!rewrite_value.has_value()) {
if (strict) {
VLOG(2) << "No value for " << key << " in " << pattern;
- return base::nullopt;
+ return absl::nullopt;
}
// Leave placeholder unchanged.
rewrite_value = "${" + key + "}";
@@ -84,6 +84,57 @@ base::Optional<std::string> FormatString(
return out;
}
+ClientStatus FormatExpression(
+ const ValueExpression& value_expression,
+ const std::map<std::string, std::string>& mappings,
+ bool quote_meta,
+ std::string* out_value) {
+ out_value->clear();
+ for (const auto& chunk : value_expression.chunk()) {
+ switch (chunk.chunk_case()) {
+ case ValueExpression::Chunk::kText:
+ out_value->append(chunk.text());
+ break;
+ case ValueExpression::Chunk::kKey: {
+ auto rewrite_value =
+ GetFieldValue(mappings, base::NumberToString(chunk.key()));
+ if (!rewrite_value.has_value()) {
+ return ClientStatus(AUTOFILL_INFO_NOT_AVAILABLE);
+ }
+ if (quote_meta) {
+ out_value->append(re2::RE2::QuoteMeta(*rewrite_value));
+ } else {
+ out_value->append(*rewrite_value);
+ }
+ break;
+ }
+ case ValueExpression::Chunk::CHUNK_NOT_SET:
+ return ClientStatus(INVALID_ACTION);
+ }
+ }
+
+ return OkClientStatus();
+}
+
+std::string GetHumanReadableValueExpression(
+ const ValueExpression& value_expression) {
+ std::string out;
+ for (const auto& chunk : value_expression.chunk()) {
+ switch (chunk.chunk_case()) {
+ case ValueExpression::Chunk::kText:
+ out += chunk.text();
+ break;
+ case ValueExpression::Chunk::kKey:
+ out += "${" + base::NumberToString(chunk.key()) + "}";
+ break;
+ case ValueExpression::Chunk::CHUNK_NOT_SET:
+ out += "<CHUNK_NOT_SET>";
+ break;
+ }
+ }
+ return out;
+}
+
template <>
std::map<std::string, std::string>
CreateAutofillMappings<autofill::AutofillProfile>(
@@ -156,4 +207,11 @@ std::map<std::string, std::string> CreateAutofillMappings<autofill::CreditCard>(
}
} // namespace field_formatter
+
+std::ostream& operator<<(std::ostream& out,
+ const ValueExpression& value_expression) {
+ return out << field_formatter::GetHumanReadableValueExpression(
+ value_expression);
+}
+
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/field_formatter.h b/chromium/components/autofill_assistant/browser/field_formatter.h
index 74a9516ccc0..4f14be91175 100644
--- a/chromium/components/autofill_assistant/browser/field_formatter.h
+++ b/chromium/components/autofill_assistant/browser/field_formatter.h
@@ -7,9 +7,11 @@
#include <map>
#include <string>
-#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/action_value.pb.h"
+#include "components/autofill_assistant/browser/client_status.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
namespace field_formatter {
@@ -19,11 +21,25 @@ namespace field_formatter {
// does not contain curly braces. If |strict| is true, this will fail if any of
// the found placeholders is not in |mappings|. Otherwise, placeholders other
// than those from |mappings| will be left unchanged.
-base::Optional<std::string> FormatString(
+absl::optional<std::string> FormatString(
const std::string& input,
const std::map<std::string, std::string>& mappings,
bool strict = true);
+// Turns a |value_expression| into a string, replacing |key| chunks with
+// corresponding values in |mappings|. This will fail if any of the keys are
+// not in |mappings|. If |quote_meta| the replacement pieces will be quoted.
+ClientStatus FormatExpression(
+ const ValueExpression& value_expression,
+ const std::map<std::string, std::string>& mappings,
+ bool quote_meta,
+ std::string* out_value);
+
+// Returns a human-readable string representation of |value_expression| for
+// use in logging and error reporting.
+std::string GetHumanReadableValueExpression(
+ const ValueExpression& value_expression);
+
// Creates a lookup map for all non-empty autofill and custom
// AutofillFormatProto::AutofillAssistantCustomField field types in
// |autofill_data_model|.
@@ -34,6 +50,12 @@ std::map<std::string, std::string> CreateAutofillMappings(
const std::string& locale);
} // namespace field_formatter
+
+// Debug output operator for value expressions. The output is only useful in
+// debug builds.
+std::ostream& operator<<(std::ostream& out,
+ const ValueExpression& value_expression);
+
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_FIELD_FORMATTER_H_
diff --git a/chromium/components/autofill_assistant/browser/field_formatter_unittest.cc b/chromium/components/autofill_assistant/browser/field_formatter_unittest.cc
index f1afeda042b..d6d84fb08e9 100644
--- a/chromium/components/autofill_assistant/browser/field_formatter_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/field_formatter_unittest.cc
@@ -22,23 +22,78 @@ using ::testing::Eq;
using ::testing::IsSupersetOf;
TEST(FieldFormatterTest, FormatString) {
- std::map<std::string, std::string> mappings = {
- {"keyA", "valueA"}, {"keyB", "valueB"}, {"keyC", "valueC"}};
-
- EXPECT_EQ(FormatString("", mappings), "");
- EXPECT_EQ(FormatString("input", mappings), "input");
- EXPECT_EQ(FormatString("prefix ${keyA}", mappings), "prefix valueA");
- EXPECT_EQ(FormatString("prefix ${keyA}${keyB}${keyC} suffix", mappings),
+ std::map<std::string, std::string> mappings = {{"keyA", "valueA"},
+ {"keyB", "valueB"},
+ {"keyC", "valueC"},
+ {"keyD", "$30.5"},
+ {"keyE", "30.5$"}
+ /* keyF does not exist */};
+
+ EXPECT_EQ(*FormatString("", mappings), "");
+ EXPECT_EQ(*FormatString("input", mappings), "input");
+ EXPECT_EQ(*FormatString("prefix ${keyA}", mappings), "prefix valueA");
+ EXPECT_EQ(*FormatString("prefix ${keyA}${keyB}${keyC} suffix", mappings),
"prefix valueAvalueBvalueC suffix");
- EXPECT_EQ(FormatString("keyA = ${keyA}", mappings), "keyA = valueA");
- EXPECT_EQ(FormatString("${keyD}", mappings), base::nullopt);
- EXPECT_EQ(FormatString("${keyA}${keyD}", mappings), base::nullopt);
-
- EXPECT_EQ(FormatString("${keyD}", mappings, /*strict = */ false), "${keyD}");
- EXPECT_EQ(FormatString("${keyA}${keyD}", mappings, /*strict = */ false),
- "valueA${keyD}");
- EXPECT_EQ(FormatString("${keyD}${keyA}", mappings, /*strict = */ false),
- "${keyD}valueA");
+ EXPECT_EQ(*FormatString("keyA = ${keyA}", mappings), "keyA = valueA");
+ EXPECT_EQ(*FormatString("Price: $${keyA}", mappings), "Price: $valueA");
+ EXPECT_EQ(*FormatString("Price: ${keyD}", mappings), "Price: $30.5");
+ EXPECT_EQ(*FormatString("Price: ${keyE}", mappings), "Price: 30.5$");
+ EXPECT_EQ(FormatString("${keyF}", mappings), absl::nullopt);
+ EXPECT_EQ(FormatString("${keyA}${keyF}", mappings), absl::nullopt);
+
+ EXPECT_EQ(*FormatString("${keyF}", mappings, /*strict = */ false), "${keyF}");
+ EXPECT_EQ(*FormatString("${keyA}${keyF}", mappings, /*strict = */ false),
+ "valueA${keyF}");
+ EXPECT_EQ(*FormatString("${keyF}${keyA}", mappings, /*strict = */ false),
+ "${keyF}valueA");
+}
+
+TEST(FieldFormatterTest, FormatExpression) {
+ std::map<std::string, std::string> mappings = {{"1", "valueA"},
+ {"2", "val.ueB"}};
+ std::string result;
+
+ ValueExpression value_expression_1;
+ value_expression_1.add_chunk()->set_text("text");
+ value_expression_1.add_chunk()->set_text(" ");
+ value_expression_1.add_chunk()->set_key(1);
+ EXPECT_EQ(ACTION_APPLIED, FormatExpression(value_expression_1, mappings,
+ /* quote_meta=*/false, &result)
+ .proto_status());
+ EXPECT_EQ("text valueA", result);
+
+ ValueExpression value_expression_2;
+ value_expression_2.add_chunk()->set_text("^");
+ value_expression_2.add_chunk()->set_key(2);
+ value_expression_2.add_chunk()->set_text("$");
+ EXPECT_EQ(ACTION_APPLIED, FormatExpression(value_expression_2, mappings,
+ /* quote_meta= */ false, &result)
+ .proto_status());
+ EXPECT_EQ("^val.ueB$", result);
+ EXPECT_EQ(ACTION_APPLIED, FormatExpression(value_expression_2, mappings,
+ /* quote_meta= */ true, &result)
+ .proto_status());
+ EXPECT_EQ("^val\\.ueB$", result);
+
+ ValueExpression value_expression_3;
+ value_expression_3.add_chunk()->set_key(3);
+ EXPECT_EQ(AUTOFILL_INFO_NOT_AVAILABLE,
+ FormatExpression(value_expression_3, mappings,
+ /* quote_meta= */ false, &result)
+ .proto_status());
+
+ ValueExpression value_expression_4;
+ EXPECT_EQ(ACTION_APPLIED, FormatExpression(value_expression_4, mappings,
+ /* quote_meta= */ false, &result)
+ .proto_status());
+ EXPECT_EQ(std::string(), result);
+}
+
+TEST(FieldFormatterTest, GetHumanReadableValueExpression) {
+ ValueExpression value_expression;
+ value_expression.add_chunk()->set_text("+");
+ value_expression.add_chunk()->set_key(1);
+ EXPECT_EQ(GetHumanReadableValueExpression(value_expression), "+${1}");
}
TEST(FieldFormatterTest, AutofillProfile) {
@@ -81,14 +136,14 @@ TEST(FieldFormatterTest, AutofillProfile) {
"", "", "", "", "XY", "", "US", "");
EXPECT_EQ(FormatString("${34}", CreateAutofillMappings(unknown_state_profile,
"en-US")),
- base::nullopt);
+ absl::nullopt);
EXPECT_EQ(FormatString("${-6}", CreateAutofillMappings(unknown_state_profile,
"en-US")),
"XY");
// UNKNOWN_TYPE
EXPECT_EQ(FormatString("${1}", CreateAutofillMappings(profile, "en-US")),
- base::nullopt);
+ absl::nullopt);
}
TEST(FieldFormatterTest, CreditCard) {
@@ -138,12 +193,12 @@ TEST(FieldFormatterTest, SpecialCases) {
EXPECT_EQ(*FormatString("${3}", CreateAutofillMappings(profile, "en-US")),
"John");
EXPECT_EQ(FormatString("${-1}", CreateAutofillMappings(profile, "en-US")),
- base::nullopt);
+ absl::nullopt);
EXPECT_EQ(
FormatString(
"${" + base::NumberToString(autofill::MAX_VALID_FIELD_TYPE) + "}",
CreateAutofillMappings(profile, "en-US")),
- base::nullopt);
+ absl::nullopt);
// Second {} is not prefixed with $.
EXPECT_EQ(
diff --git a/chromium/components/autofill_assistant/browser/full_card_requester.cc b/chromium/components/autofill_assistant/browser/full_card_requester.cc
index 671776d6cc1..18f0465d5e2 100644
--- a/chromium/components/autofill_assistant/browser/full_card_requester.cc
+++ b/chromium/components/autofill_assistant/browser/full_card_requester.cc
@@ -44,10 +44,10 @@ void FullCardRequester::GetFullCard(
return;
}
- driver->autofill_manager()->GetOrCreateFullCardRequest()->GetFullCard(
+ driver->browser_autofill_manager()->GetOrCreateFullCardRequest()->GetFullCard(
*card, autofill::AutofillClient::UNMASK_FOR_AUTOFILL,
weak_ptr_factory_.GetWeakPtr(),
- driver->autofill_manager()->GetAsFullCardRequestUIDelegate());
+ driver->browser_autofill_manager()->GetAsFullCardRequestUIDelegate());
}
FullCardRequester::~FullCardRequester() = default;
diff --git a/chromium/components/autofill_assistant/browser/generic_ui.proto b/chromium/components/autofill_assistant/browser/generic_ui.proto
index 9f413da0832..c07e8d7dc78 100644
--- a/chromium/components/autofill_assistant/browser/generic_ui.proto
+++ b/chromium/components/autofill_assistant/browser/generic_ui.proto
@@ -10,6 +10,7 @@ option java_multiple_files = true;
package autofill_assistant;
+import "action_value.proto";
import "model.proto";
import "view_layout.proto";
@@ -203,13 +204,15 @@ message AutofillFormatProto {
ADDRESS_HOME_STATE_NAME = -6;
CREDIT_CARD_NON_PADDED_EXP_MONTH = -7;
}
- // The format string to use. May contain one or multiple "${key}"
+ // The format string to use. May contain one or multiple key
// placeholders, where the key is an integer corresponding to
// entries from field_types.h or AutofillAssistantCustomField.
- optional string pattern = 1;
+ optional ValueExpression value_expression = 3;
// The locale to use when stringifying data. Invalid locales will
// automatically default to "en-US".
optional string locale = 2;
+
+ reserved 1;
}
// A comparison of two values in the form |value_a| <mode> |value_b|. EQUAL and
diff --git a/chromium/components/autofill_assistant/browser/info_box.h b/chromium/components/autofill_assistant/browser/info_box.h
index 67fa522aec7..45c22249500 100644
--- a/chromium/components/autofill_assistant/browser/info_box.h
+++ b/chromium/components/autofill_assistant/browser/info_box.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_INFO_BOX_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_INFO_BOX_H_
-#include <map>
-#include <string>
-
#include "base/values.h"
#include "components/autofill_assistant/browser/service.pb.h"
diff --git a/chromium/components/autofill_assistant/browser/intent_strings.h b/chromium/components/autofill_assistant/browser/intent_strings.h
index 94ee0fa4911..0f54f136ff7 100644
--- a/chromium/components/autofill_assistant/browser/intent_strings.h
+++ b/chromium/components/autofill_assistant/browser/intent_strings.h
@@ -24,4 +24,4 @@ extern const char kShoppingAssistedCheckout[];
extern const char kTeleport[];
} // namespace autofill_assistant
-#endif
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_INTENT_STRINGS_H_
diff --git a/chromium/components/autofill_assistant/browser/metrics.cc b/chromium/components/autofill_assistant/browser/metrics.cc
index 08a5a0bbdd7..143fe417f34 100644
--- a/chromium/components/autofill_assistant/browser/metrics.cc
+++ b/chromium/components/autofill_assistant/browser/metrics.cc
@@ -21,6 +21,8 @@ const char* const kIntentNotSet = "NotSet";
namespace {
const char kDropOutEnumName[] = "Android.AutofillAssistant.DropOutReason";
const char kOnboardingEnumName[] = "Android.AutofillAssistant.OnBoarding";
+const char kFeatureModuleInstallationEnumName[] =
+ "Android.AutofillAssistant.FeatureModuleInstallation";
const char kPaymentRequestPrefilledName[] =
"Android.AutofillAssistant.PaymentRequest.Prefilled";
const char kPaymentRequestAutofillInfoChangedName[] =
@@ -147,88 +149,108 @@ void Metrics::RecordPaymentRequestMandatoryPostalCode(bool required,
}
// static
-void Metrics::RecordLiteScriptStarted(ukm::UkmRecorder* ukm_recorder,
- content::WebContents* web_contents,
- StartupUtil::StartupMode startup_mode,
- bool feature_module_installed,
- bool is_first_time_user) {
- LiteScriptStarted event;
+void Metrics::RecordTriggerScriptStarted(ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ TriggerScriptStarted event) {
+ ukm::builders::AutofillAssistant_LiteScriptStarted(source_id)
+ .SetLiteScriptStarted(static_cast<int64_t>(event))
+ .Record(ukm_recorder);
+}
+
+// static
+void Metrics::RecordTriggerScriptStarted(ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ StartupUtil::StartupMode startup_mode,
+ bool feature_module_installed,
+ bool is_first_time_user) {
+ TriggerScriptStarted event;
switch (startup_mode) {
case StartupUtil::StartupMode::FEATURE_DISABLED:
if (base::FeatureList::IsEnabled(
features::kAutofillAssistantProactiveHelp) &&
!feature_module_installed) {
- event = LiteScriptStarted::LITE_SCRIPT_DFM_UNAVAILABLE;
+ event = TriggerScriptStarted::DFM_UNAVAILABLE;
} else {
- event = LiteScriptStarted::LITE_SCRIPT_FEATURE_DISABLED;
+ event = TriggerScriptStarted::FEATURE_DISABLED;
}
break;
case StartupUtil::StartupMode::SETTING_DISABLED:
- event = LiteScriptStarted::LITE_SCRIPT_PROACTIVE_TRIGGERING_DISABLED;
+ event = TriggerScriptStarted::PROACTIVE_TRIGGERING_DISABLED;
break;
case StartupUtil::StartupMode::NO_INITIAL_URL:
- event = LiteScriptStarted::LITE_SCRIPT_NO_INITIAL_URL;
+ event = TriggerScriptStarted::NO_INITIAL_URL;
break;
case StartupUtil::StartupMode::MANDATORY_PARAMETERS_MISSING:
- event = LiteScriptStarted::LITE_SCRIPT_MANDATORY_PARAMETER_MISSING;
+ event = TriggerScriptStarted::MANDATORY_PARAMETER_MISSING;
break;
case StartupUtil::StartupMode::START_BASE64_TRIGGER_SCRIPT:
case StartupUtil::StartupMode::START_RPC_TRIGGER_SCRIPT:
- event = is_first_time_user
- ? LiteScriptStarted::LITE_SCRIPT_FIRST_TIME_USER
- : LiteScriptStarted::LITE_SCRIPT_RETURNING_USER;
+ event = is_first_time_user ? TriggerScriptStarted::FIRST_TIME_USER
+ : TriggerScriptStarted::RETURNING_USER;
break;
case StartupUtil::StartupMode::START_REGULAR:
- // Regular starts do not record impressions for |LiteScriptStarted|.
+ // Regular starts do not record impressions for |TriggerScriptStarted|.
return;
}
- ukm::builders::AutofillAssistant_LiteScriptStarted(
- ukm::GetSourceIdForWebContentsDocument(web_contents))
- .SetLiteScriptStarted(static_cast<int64_t>(event))
- .Record(ukm_recorder);
+ RecordTriggerScriptStarted(ukm_recorder, source_id, event);
}
// static
-void Metrics::RecordLiteScriptFinished(ukm::UkmRecorder* ukm_recorder,
- content::WebContents* web_contents,
- TriggerUIType trigger_ui_type,
- LiteScriptFinishedState event) {
- ukm::builders::AutofillAssistant_LiteScriptFinished(
- ukm::GetSourceIdForWebContentsDocument(web_contents))
+void Metrics::RecordTriggerScriptFinished(
+ ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ TriggerScriptProto::TriggerUIType trigger_ui_type,
+ TriggerScriptFinishedState event) {
+ ukm::builders::AutofillAssistant_LiteScriptFinished(source_id)
.SetTriggerUIType(static_cast<int64_t>(trigger_ui_type))
.SetLiteScriptFinished(static_cast<int64_t>(event))
.Record(ukm_recorder);
}
// static
-void Metrics::RecordLiteScriptShownToUser(ukm::UkmRecorder* ukm_recorder,
- content::WebContents* web_contents,
- TriggerUIType trigger_ui_type,
- LiteScriptShownToUser event) {
- ukm::builders::AutofillAssistant_LiteScriptShownToUser(
- ukm::GetSourceIdForWebContentsDocument(web_contents))
+void Metrics::RecordTriggerScriptShownToUser(
+ ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ TriggerScriptProto::TriggerUIType trigger_ui_type,
+ TriggerScriptShownToUser event) {
+ ukm::builders::AutofillAssistant_LiteScriptShownToUser(source_id)
.SetTriggerUIType(static_cast<int64_t>(trigger_ui_type))
.SetLiteScriptShownToUser(static_cast<int64_t>(event))
.Record(ukm_recorder);
}
// static
-void Metrics::RecordLiteScriptOnboarding(ukm::UkmRecorder* ukm_recorder,
- content::WebContents* web_contents,
- TriggerUIType trigger_ui_type,
- LiteScriptOnboarding event) {
- ukm::builders::AutofillAssistant_LiteScriptOnboarding(
- ukm::GetSourceIdForWebContentsDocument(web_contents))
+void Metrics::RecordTriggerScriptOnboarding(
+ ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ TriggerScriptProto::TriggerUIType trigger_ui_type,
+ TriggerScriptOnboarding event) {
+ ukm::builders::AutofillAssistant_LiteScriptOnboarding(source_id)
.SetTriggerUIType(static_cast<int64_t>(trigger_ui_type))
.SetLiteScriptOnboarding(static_cast<int64_t>(event))
.Record(ukm_recorder);
}
// static
+void Metrics::RecordInChromeTriggerAction(ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ InChromeTriggerAction event) {
+ ukm::builders::AutofillAssistant_InChromeTriggering(source_id)
+ .SetInChromeTriggerAction(static_cast<int64_t>(event))
+ .Record(ukm_recorder);
+}
+
+// static
void Metrics::RecordOnboardingResult(OnBoarding event) {
DCHECK_LE(event, OnBoarding::kMaxValue);
base::UmaHistogramEnumeration(kOnboardingEnumName, event);
}
+// static
+void Metrics::RecordFeatureModuleInstallation(FeatureModuleInstallation event) {
+ DCHECK_LE(event, FeatureModuleInstallation::kMaxValue);
+ base::UmaHistogramEnumeration(kFeatureModuleInstallationEnumName, event);
+}
+
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/metrics.h b/chromium/components/autofill_assistant/browser/metrics.h
index a5655791e3b..12f421f9a9b 100644
--- a/chromium/components/autofill_assistant/browser/metrics.h
+++ b/chromium/components/autofill_assistant/browser/metrics.h
@@ -8,7 +8,6 @@
#include <ostream>
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/startup_util.h"
-#include "content/public/browser/web_contents.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
namespace autofill_assistant {
@@ -61,7 +60,7 @@ class Metrics {
// The different ways that autofill assistant can stop. Note that this only
// covers regular onboarding. Trigger script onboarding is covered by
- // LiteScriptOnboarding.
+ // TriggerScriptOnboarding.
//
// GENERATED_JAVA_ENUM_PACKAGE: (
// org.chromium.chrome.browser.autofill_assistant.metrics)
@@ -150,195 +149,220 @@ class Metrics {
kMaxValue = DFM_ALREADY_INSTALLED
};
- // Whether a lite script was running invisibly or visible to the user.
- //
- // GENERATED_JAVA_ENUM_PACKAGE: (
- // org.chromium.chrome.browser.autofill_assistant.metrics)
- // GENERATED_JAVA_CLASS_NAME_OVERRIDE: LiteScriptShownToUser
+ // Whether a trigger script was running invisibly or visible to the user.
//
// This enum is used in UKM metrics, do not remove/renumber entries. Only add
// at the end and update kMaxValue. Also remember to update the
- // AutofillAssistantLiteScriptShownToUser enum listing in
+ // AutofillAssistantTriggerScriptShownToUser enum listing in
// tools/metrics/histograms/enums.xml and the description in
// tools/metrics/ukm/ukm.xml as necessary.
- enum class LiteScriptShownToUser {
- // The number of times a lite script was successfully fetched and started.
+ enum class TriggerScriptShownToUser {
+ // The number of times a trigger script was successfully fetched and
+ // started.
// Can happen multiple times per run (in case of tab switch).
- LITE_SCRIPT_RUNNING = 0,
- // The number of times a lite script was shown to the user. Can happen
+ RUNNING = 0,
+ // The number of times a trigger script was shown to the user. Can happen
// multiple times per run.
- LITE_SCRIPT_SHOWN_TO_USER = 1,
+ SHOWN_TO_USER = 1,
// Since Chrome M-88. The user tapped the 'not now' button. Can happen
// multiple times per run.
- LITE_SCRIPT_NOT_NOW = 2,
- // Since Chrome M-88. The lite script was automatically hidden due to the
+ NOT_NOW = 2,
+ // Since Chrome M-88. The trigger script was automatically hidden due to the
// trigger condition no longer being true. Can happen multiple times per
// run.
- LITE_SCRIPT_HIDE_ON_TRIGGER_CONDITION_NO_LONGER_TRUE = 3,
+ HIDE_ON_TRIGGER_CONDITION_NO_LONGER_TRUE = 3,
// Since Chrome M-88. The user swipe-dismissed the bottom sheet. Depending
// on configuration, this may happen multiple times per run.
- LITE_SCRIPT_SWIPE_DISMISSED = 4,
+ SWIPE_DISMISSED = 4,
- kMaxValue = LITE_SCRIPT_SWIPE_DISMISSED
+ kMaxValue = SWIPE_DISMISSED
};
- // The different ways a user might have opted out of the lite script
+ // The different ways a user might have opted out of the trigger script
// experience.
//
- // GENERATED_JAVA_ENUM_PACKAGE: (
- // org.chromium.chrome.browser.autofill_assistant.metrics)
- // GENERATED_JAVA_CLASS_NAME_OVERRIDE: LiteScriptStarted
- //
// This enum is used in UKM metrics, do not remove/renumber entries. Only add
// at the end and update kMaxValue. Also remember to update the
- // AutofillAssistantLiteScriptStarted enum listing in
+ // AutofillAssistantTriggerScriptStarted enum listing in
// tools/metrics/histograms/enums.xml and the description in
// tools/metrics/ukm/ukm.xml as necessary.
- enum class LiteScriptStarted {
+ enum class TriggerScriptStarted {
// Device did not have DFM downloaded.
- LITE_SCRIPT_DFM_UNAVAILABLE = 0,
- // User has not seen the lite script before and will see first time
+ DFM_UNAVAILABLE = 0,
+ // User has not seen the trigger script before and will see first time
// experience.
- LITE_SCRIPT_FIRST_TIME_USER = 3,
+ FIRST_TIME_USER = 3,
// User has seen the first-time experience before and will see returning
// user experience.
- LITE_SCRIPT_RETURNING_USER = 4,
+ RETURNING_USER = 4,
// Since Chrome M-88. The proactive trigger setting is disabled. The user
// has either chosen 'never show again' in the prompt or manually disabled
// the setting in Chrome settings.
- LITE_SCRIPT_PROACTIVE_TRIGGERING_DISABLED = 5,
+ PROACTIVE_TRIGGERING_DISABLED = 5,
// Since Chrome M-88. Intended as a catch-all. This is reported as soon as a
// lite-script intent is received (of course, only for people with MSBB
// enabled).
- LITE_SCRIPT_INTENT_RECEIVED = 6,
+ INTENT_RECEIVED = 6,
// Since Chrome M-91. A required Chrome feature was disabled.
- LITE_SCRIPT_FEATURE_DISABLED = 7,
+ FEATURE_DISABLED = 7,
// Since Chrome M-91. No initial url was set, neither in ORIGINAL_DEEPLINK
// nor in the intent data.
- LITE_SCRIPT_NO_INITIAL_URL = 8,
+ NO_INITIAL_URL = 8,
// Since Chrome M-91. A mandatory script parameter was missing.
- LITE_SCRIPT_MANDATORY_PARAMETER_MISSING = 9,
+ MANDATORY_PARAMETER_MISSING = 9,
+ // Since Chrome M-92. The user never navigated to a different domain.
+ NAVIGATED_AWAY = 10,
+ // Since Chrome M-92. The navigation to the target domain failed.
+ NAVIGATION_ERROR = 11,
// DEPRECATED, only sent by Chrome M-86 and M-87.
//
- // User has explicitly rejected the lite script two times and thus opted
+ // User has explicitly rejected the trigger script two times and thus opted
// out of the experience.
- LITE_SCRIPT_CANCELED_TWO_TIMES = 1,
+ CANCELED_TWO_TIMES = 1,
// User has rejected the onboarding and thus opted out of the experience.
- LITE_SCRIPT_ONBOARDING_REJECTED = 2,
+ ONBOARDING_REJECTED = 2,
- kMaxValue = LITE_SCRIPT_MANDATORY_PARAMETER_MISSING
+ kMaxValue = NAVIGATION_ERROR
};
- // The different ways in which a lite script may finish.
- //
- // GENERATED_JAVA_ENUM_PACKAGE: (
- // org.chromium.chrome.browser.autofill_assistant.metrics)
- // GENERATED_JAVA_CLASS_NAME_OVERRIDE: LiteScriptFinishedState
+ // The different ways in which a trigger script may finish.
//
// This enum is used in UKM metrics, do not remove/renumber entries. Only add
// at the end and update kMaxValue. Also remember to update the
- // AutofillAssistantLiteScriptFinished enum listing in
+ // AutofillAssistantTriggerScriptFinished enum listing in
// tools/metrics/histograms/enums.xml and the description in
// tools/metrics/ukm/ukm.xml as necessary.
- enum class LiteScriptFinishedState {
+ enum class TriggerScriptFinishedState {
// Communication with backend failed.
- LITE_SCRIPT_GET_ACTIONS_FAILED = 3,
+ GET_ACTIONS_FAILED = 3,
// Failed to parse the proto sent by the backend.
- LITE_SCRIPT_GET_ACTIONS_PARSE_ERROR = 4,
- // Lite script failed due to a navigation event to a non-allowed domain.
- LITE_SCRIPT_PROMPT_FAILED_NAVIGATE = 9,
- // Lite script succeeded. The user accepted the prompt.
- LITE_SCRIPT_PROMPT_SUCCEEDED = 13,
+ GET_ACTIONS_PARSE_ERROR = 4,
+ // Trigger script failed due to a navigation event to a non-allowed domain.
+ PROMPT_FAILED_NAVIGATE = 9,
+ // Trigger script succeeded. The user accepted the prompt.
+ PROMPT_SUCCEEDED = 13,
// Since Chrome M-88. The user tapped the 'cancel for this session' button.
- LITE_SCRIPT_PROMPT_FAILED_CANCEL_SESSION = 14,
+ PROMPT_FAILED_CANCEL_SESSION = 14,
// Since Chrome M-88. The user tapped the 'never show again' button.
- LITE_SCRIPT_PROMPT_FAILED_CANCEL_FOREVER = 15,
+ PROMPT_FAILED_CANCEL_FOREVER = 15,
// Since Chrome M-88. The trigger script has timed out. This indicates that
// trigger conditions were evaluated for >= timeout without success. Time is
- // only counted while the tab is visible and the lite script is invisible.
+ // only counted while the tab is visible and the trigger script is
+ // invisible.
// The timeout resets on tab change.
- LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT = 17,
+ TRIGGER_CONDITION_TIMEOUT = 17,
// Since Chrome M-88. A navigation error occurred, leading to Chrome showing
// an error page.
- LITE_SCRIPT_NAVIGATION_ERROR = 18,
+ NAVIGATION_ERROR = 18,
// Since Chrome M-88. The tab was closed while the prompt was visible.
- LITE_SCRIPT_WEB_CONTENTS_DESTROYED_WHILE_VISIBLE = 19,
+ WEB_CONTENTS_DESTROYED_WHILE_VISIBLE = 19,
// Since Chrome M-88. The tab was closed while the prompt was invisible.
- LITE_SCRIPT_WEB_CONTENTS_DESTROYED_WHILE_INVISIBLE = 20,
+ WEB_CONTENTS_DESTROYED_WHILE_INVISIBLE = 20,
// Since Chrome M-88. The RPC to fetch the trigger scripts returned with an
// empty response.
- LITE_SCRIPT_NO_TRIGGER_SCRIPT_AVAILABLE = 21,
+ NO_TRIGGER_SCRIPT_AVAILABLE = 21,
// Since Chrome M-88. The trigger script failed to show. This can happen,
// for example, if the activity was changed after triggering (e.g.,
// switching from CCT to regular tab).
- LITE_SCRIPT_FAILED_TO_SHOW = 22,
+ FAILED_TO_SHOW = 22,
// Since Chrome M-88. The proactive help switch was enabled at start, but
// then manually disabled in the Chrome settings.
- LITE_SCRIPT_DISABLED_PROACTIVE_HELP_SETTING = 23,
+ DISABLED_PROACTIVE_HELP_SETTING = 23,
// Since Chrome M-88. The client failed to base64-decode the trigger script
// specified in the script parameters.
- LITE_SCRIPT_BASE64_DECODING_ERROR = 24,
+ BASE64_DECODING_ERROR = 24,
// The user rejected the bottom sheet onboarding
- LITE_SCRIPT_BOTTOMSHEET_ONBOARDING_REJECTED = 25,
+ BOTTOMSHEET_ONBOARDING_REJECTED = 25,
+ // Transitioning from CCT to regular tab is currently not supported.
+ CCT_TO_TAB_NOT_SUPPORTED = 26,
+ // The current trigger script was canceled. This typically happens when a
+ // new startup request takes precedence.
+ CANCELED = 27,
// NOTE: All values in this block are DEPRECATED and will only be sent by
// Chrome M-86 and M-87.
//
- // The lite script failed for an unknown reason.
- LITE_SCRIPT_UNKNOWN_FAILURE = 0,
+ // The trigger script failed for an unknown reason.
+ UNKNOWN_FAILURE = 0,
// Can happen when users close the tab or similar.
- LITE_SCRIPT_SERVICE_DELETED = 1,
+ SERVICE_DELETED = 1,
// |GetActions| was asked to retrieve a wrong script path.
- LITE_SCRIPT_PATH_MISMATCH = 2,
+ PATH_MISMATCH = 2,
// One or multiple unsafe actions were contained in script.
- LITE_SCRIPT_UNSAFE_ACTIONS = 5,
+ UNSAFE_ACTIONS = 5,
// The mini script is invalid. A valid script must contain a prompt
// (browse=true) action and end in a prompt(browse=false) action.
- LITE_SCRIPT_INVALID_SCRIPT = 6,
+ INVALID_SCRIPT = 6,
// The prompt(browse) action failed due to a navigation event to a
// non-allowed domain.
- LITE_SCRIPT_BROWSE_FAILED_NAVIGATE = 7,
+ BROWSE_FAILED_NAVIGATE = 7,
// The prompt(browse) action failed for an unknown reason.
- LITE_SCRIPT_BROWSE_FAILED_OTHER = 8,
+ BROWSE_FAILED_OTHER = 8,
// The prompt(regular) action failed because the condition to show it was no
// longer true.
- LITE_SCRIPT_PROMPT_FAILED_CONDITION_NO_LONGER_TRUE = 10,
+ PROMPT_FAILED_CONDITION_NO_LONGER_TRUE = 10,
// The prompt(regular) action failed because the user tapped the close chip.
- LITE_SCRIPT_PROMPT_FAILED_CLOSE = 11,
+ PROMPT_FAILED_CLOSE = 11,
// The prompt(regular) action failed for an unknown reason.
- LITE_SCRIPT_PROMPT_FAILED_OTHER = 12,
+ PROMPT_FAILED_OTHER = 12,
// Since Chrome M-88. The bottom sheet was swipe-dismissed by the user.
- LITE_SCRIPT_PROMPT_SWIPE_DISMISSED = 16,
+ PROMPT_SWIPE_DISMISSED = 16,
- kMaxValue = LITE_SCRIPT_BOTTOMSHEET_ONBOARDING_REJECTED
+ kMaxValue = CANCELED
};
// The different ways a user who has successfully completed a light script may
// accept or reject the onboarding
//
- // GENERATED_JAVA_ENUM_PACKAGE: (
- // org.chromium.chrome.browser.autofill_assistant.metrics)
- // GENERATED_JAVA_CLASS_NAME_OVERRIDE: LiteScriptOnboarding
- //
// This enum is used in UKM metrics, do not remove/renumber entries. Only add
// at the end and update kMaxValue. Also remember to update the
- // AutofillAssistantLiteScriptOnboarding enum listing in
+ // AutofillAssistantTriggerScriptOnboarding enum listing in
// tools/metrics/histograms/enums.xml and the description in
// tools/metrics/ukm/ukm.xml as necessary.
- enum class LiteScriptOnboarding {
+ enum class TriggerScriptOnboarding {
// The user has seen and accepted the onboarding.
- LITE_SCRIPT_ONBOARDING_SEEN_AND_ACCEPTED = 0,
+ ONBOARDING_SEEN_AND_ACCEPTED = 0,
// The user has seen and rejected the onboarding.
- LITE_SCRIPT_ONBOARDING_SEEN_AND_REJECTED = 1,
+ ONBOARDING_SEEN_AND_REJECTED = 1,
// The user has already accepted the onboarding in the past.
- LITE_SCRIPT_ONBOARDING_ALREADY_ACCEPTED = 2,
+ ONBOARDING_ALREADY_ACCEPTED = 2,
// The user has seen and dismissed the onboarding.
- LITE_SCRIPT_ONBOARDING_SEEN_AND_DISMISSED = 3,
+ ONBOARDING_SEEN_AND_DISMISSED = 3,
// The onboarding was interrupted by a website navigation.
- LITE_SCRIPT_ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION = 4,
+ ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION = 4,
- kMaxValue = LITE_SCRIPT_ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION
+ kMaxValue = ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION
+ };
+
+ // Metric describing in-Chrome triggering. Only reported if the corresponding
+ // feature is enabled.
+ //
+ // This enum is used in UKM metrics, do not remove/renumber entries. Only add
+ // at the end and update kMaxValue. Also remember to update the
+ // AutofillAssistantInChromeTriggerAction enum listing in
+ // tools/metrics/histograms/enums.xml and the description in
+ // tools/metrics/ukm/ukm.xml as necessary.
+ enum class InChromeTriggerAction {
+ // No trigger script was requested for an unspecified reason. This is
+ // intended as a catch-all bucket and should ideally always be empty.
+ OTHER = 0,
+ // No trigger script was requested because the user has temporarily opted
+ // out of receiving implicit prompts for this domain (either until tab close
+ // or until the cache entry is stale, whichever is sooner).
+ USER_DENYLISTED_DOMAIN = 1,
+ // No trigger script was requested because an earlier request to the same
+ // domain failed and the cache was still fresh.
+ CACHE_HIT_UNSUPPORTED_DOMAIN = 2,
+ // No trigger script was requested because the heuristic response did not
+ // match any trigger intent.
+ NO_HEURISTIC_MATCH = 3,
+ // The heuristic reported a match and a trigger script was requested.
+ // Note that this does not indicate that a trigger script was fetched
+ // successfully, merely that it was requested.
+ TRIGGER_SCRIPT_REQUESTED = 4,
+
+ kMaxValue = TRIGGER_SCRIPT_REQUESTED
};
static void RecordDropOut(DropOutReason reason, const std::string& intent);
@@ -349,24 +373,34 @@ class Metrics {
static void RecordPaymentRequestMandatoryPostalCode(bool required,
bool initially_right,
bool success);
- static void RecordLiteScriptStarted(ukm::UkmRecorder* ukm_recorder,
- content::WebContents* web_contents,
- StartupUtil::StartupMode startup_mode,
- bool feature_module_installed,
- bool is_first_time_user);
- static void RecordLiteScriptFinished(ukm::UkmRecorder* ukm_recorder,
- content::WebContents* web_contents,
- TriggerUIType trigger_ui_type,
- LiteScriptFinishedState event);
- static void RecordLiteScriptShownToUser(ukm::UkmRecorder* ukm_recorder,
- content::WebContents* web_contents,
- TriggerUIType trigger_ui_type,
- LiteScriptShownToUser event);
- static void RecordLiteScriptOnboarding(ukm::UkmRecorder* ukm_recorder,
- content::WebContents* web_contents,
- TriggerUIType trigger_ui_type,
- LiteScriptOnboarding event);
+ static void RecordTriggerScriptStarted(ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ TriggerScriptStarted event);
+ static void RecordTriggerScriptStarted(ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ StartupUtil::StartupMode startup_mode,
+ bool feature_module_installed,
+ bool is_first_time_user);
+ static void RecordTriggerScriptFinished(
+ ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ TriggerScriptProto::TriggerUIType trigger_ui_type,
+ TriggerScriptFinishedState event);
+ static void RecordTriggerScriptShownToUser(
+ ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ TriggerScriptProto::TriggerUIType trigger_ui_type,
+ TriggerScriptShownToUser event);
+ static void RecordTriggerScriptOnboarding(
+ ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ TriggerScriptProto::TriggerUIType trigger_ui_type,
+ TriggerScriptOnboarding event);
+ static void RecordInChromeTriggerAction(ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId source_id,
+ InChromeTriggerAction event);
static void RecordOnboardingResult(OnBoarding event);
+ static void RecordFeatureModuleInstallation(FeatureModuleInstallation event);
// Intended for debugging: writes string representation of |reason| to |out|.
friend std::ostream& operator<<(std::ostream& out,
@@ -499,7 +533,7 @@ class Metrics {
}
friend std::ostream& operator<<(std::ostream& out,
- const LiteScriptFinishedState& state) {
+ const TriggerScriptFinishedState& state) {
#ifdef NDEBUG
// Non-debugging builds write the enum number.
out << static_cast<int>(state);
@@ -507,86 +541,90 @@ class Metrics {
#else
// Debugging builds write a string representation of |state|.
switch (state) {
- case LiteScriptFinishedState::LITE_SCRIPT_GET_ACTIONS_FAILED:
- out << "LITE_SCRIPT_GET_ACTIONS_FAILED";
+ case TriggerScriptFinishedState::GET_ACTIONS_FAILED:
+ out << "GET_ACTIONS_FAILED";
+ break;
+ case TriggerScriptFinishedState::GET_ACTIONS_PARSE_ERROR:
+ out << "GET_ACTIONS_PARSE_ERROR";
+ break;
+ case TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE:
+ out << "PROMPT_FAILED_NAVIGATE";
+ break;
+ case TriggerScriptFinishedState::PROMPT_SUCCEEDED:
+ out << "PROMPT_SUCCEEDED";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_GET_ACTIONS_PARSE_ERROR:
- out << "LITE_SCRIPT_GET_ACTIONS_PARSE_ERROR";
+ case TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_SESSION:
+ out << "PROMPT_FAILED_CANCEL_SESSION";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_NAVIGATE:
- out << "LITE_SCRIPT_PROMPT_FAILED_NAVIGATE";
+ case TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_FOREVER:
+ out << "PROMPT_FAILED_CANCEL_FOREVER";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SUCCEEDED:
- out << "LITE_SCRIPT_PROMPT_SUCCEEDED";
+ case TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT:
+ out << "TRIGGER_CONDITION_TIMEOUT";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_CANCEL_SESSION:
- out << "LITE_SCRIPT_PROMPT_FAILED_CANCEL_SESSION";
+ case TriggerScriptFinishedState::NAVIGATION_ERROR:
+ out << "NAVIGATION_ERROR";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_CANCEL_FOREVER:
- out << "LITE_SCRIPT_PROMPT_FAILED_CANCEL_FOREVER";
+ case TriggerScriptFinishedState::WEB_CONTENTS_DESTROYED_WHILE_VISIBLE:
+ out << "WEB_CONTENTS_DESTROYED_WHILE_VISIBLE";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT:
- out << "LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT";
+ case TriggerScriptFinishedState::WEB_CONTENTS_DESTROYED_WHILE_INVISIBLE:
+ out << "WEB_CONTENTS_DESTROYED_WHILE_INVISIBLE";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_NAVIGATION_ERROR:
- out << "LITE_SCRIPT_NAVIGATION_ERROR";
+ case TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE:
+ out << "NO_TRIGGER_SCRIPT_AVAILABLE";
break;
- case LiteScriptFinishedState::
- LITE_SCRIPT_WEB_CONTENTS_DESTROYED_WHILE_VISIBLE:
- out << "LITE_SCRIPT_WEB_CONTENTS_DESTROYED_WHILE_VISIBLE";
+ case TriggerScriptFinishedState::FAILED_TO_SHOW:
+ out << "FAILED_TO_SHOW";
break;
- case LiteScriptFinishedState::
- LITE_SCRIPT_WEB_CONTENTS_DESTROYED_WHILE_INVISIBLE:
- out << "LITE_SCRIPT_WEB_CONTENTS_DESTROYED_WHILE_INVISIBLE";
+ case TriggerScriptFinishedState::DISABLED_PROACTIVE_HELP_SETTING:
+ out << "DISABLED_PROACTIVE_HELP_SETTING";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_NO_TRIGGER_SCRIPT_AVAILABLE:
- out << "LITE_SCRIPT_NO_TRIGGER_SCRIPT_AVAILABLE";
+ case TriggerScriptFinishedState::BASE64_DECODING_ERROR:
+ out << "BASE64_DECODING_ERROR";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_FAILED_TO_SHOW:
- out << "LITE_SCRIPT_FAILED_TO_SHOW";
+ case TriggerScriptFinishedState::BOTTOMSHEET_ONBOARDING_REJECTED:
+ out << "BOTTOMSHEET_ONBOARDING_REJECTED";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_DISABLED_PROACTIVE_HELP_SETTING:
- out << "LITE_SCRIPT_DISABLED_PROACTIVE_HELP_SETTING";
+ case TriggerScriptFinishedState::UNKNOWN_FAILURE:
+ out << "UNKNOWN_FAILURE";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_BASE64_DECODING_ERROR:
- out << "LITE_SCRIPT_BASE64_DECODING_ERROR";
+ case TriggerScriptFinishedState::SERVICE_DELETED:
+ out << "SERVICE_DELETED";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_BOTTOMSHEET_ONBOARDING_REJECTED:
- out << "LITE_SCRIPT_BOTTOMSHEET_ONBOARDING_REJECTED";
+ case TriggerScriptFinishedState::PATH_MISMATCH:
+ out << "PATH_MISMATCH";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_UNKNOWN_FAILURE:
- out << "LITE_SCRIPT_UNKNOWN_FAILURE";
+ case TriggerScriptFinishedState::UNSAFE_ACTIONS:
+ out << "UNSAFE_ACTIONS";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_SERVICE_DELETED:
- out << "LITE_SCRIPT_SERVICE_DELETED";
+ case TriggerScriptFinishedState::INVALID_SCRIPT:
+ out << "INVALID_SCRIPT";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_PATH_MISMATCH:
- out << "LITE_SCRIPT_PATH_MISMATCH";
+ case TriggerScriptFinishedState::BROWSE_FAILED_NAVIGATE:
+ out << "BROWSE_FAILED_NAVIGATE";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_UNSAFE_ACTIONS:
- out << "LITE_SCRIPT_UNSAFE_ACTIONS";
+ case TriggerScriptFinishedState::BROWSE_FAILED_OTHER:
+ out << "BROWSE_FAILED_OTHER";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_INVALID_SCRIPT:
- out << "LITE_SCRIPT_INVALID_SCRIPT";
+ case TriggerScriptFinishedState::PROMPT_FAILED_CONDITION_NO_LONGER_TRUE:
+ out << "PROMPT_FAILED_CONDITION_NO_LONGER_TRUE";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_BROWSE_FAILED_NAVIGATE:
- out << "LITE_SCRIPT_BROWSE_FAILED_NAVIGATE";
+ case TriggerScriptFinishedState::PROMPT_FAILED_CLOSE:
+ out << "PROMPT_FAILED_CLOSE";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_BROWSE_FAILED_OTHER:
- out << "LITE_SCRIPT_BROWSE_FAILED_OTHER";
+ case TriggerScriptFinishedState::PROMPT_FAILED_OTHER:
+ out << "PROMPT_FAILED_OTHER";
break;
- case LiteScriptFinishedState::
- LITE_SCRIPT_PROMPT_FAILED_CONDITION_NO_LONGER_TRUE:
- out << "LITE_SCRIPT_PROMPT_FAILED_CONDITION_NO_LONGER_TRUE";
+ case TriggerScriptFinishedState::PROMPT_SWIPE_DISMISSED:
+ out << "PROMPT_SWIPE_DISMISSED";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_CLOSE:
- out << "LITE_SCRIPT_PROMPT_FAILED_CLOSE";
+ case TriggerScriptFinishedState::CCT_TO_TAB_NOT_SUPPORTED:
+ out << "CCT_TO_TAB_NOT_SUPPORTED";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_OTHER:
- out << "LITE_SCRIPT_PROMPT_FAILED_OTHER";
+ case TriggerScriptFinishedState::CANCELED:
+ out << "CANCELED";
break;
- case LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SWIPE_DISMISSED:
- out << "LITE_SCRIPT_PROMPT_SWIPE_DISMISSED";
// Do not add default case to force compilation error for new values.
}
return out;
diff --git a/chromium/components/autofill_assistant/browser/mock_client.h b/chromium/components/autofill_assistant/browser/mock_client.h
index 43cd27218b5..1c2d2685a98 100644
--- a/chromium/components/autofill_assistant/browser/mock_client.h
+++ b/chromium/components/autofill_assistant/browser/mock_client.h
@@ -26,7 +26,7 @@ class MockClient : public Client {
MOCK_CONST_METHOD0(GetLocale, std::string());
MOCK_CONST_METHOD0(GetCountryCode, std::string());
MOCK_CONST_METHOD0(GetDeviceContext, DeviceContext());
- MOCK_CONST_METHOD0(GetWindowSize, base::Optional<std::pair<int, int>>());
+ MOCK_CONST_METHOD0(GetWindowSize, absl::optional<std::pair<int, int>>());
MOCK_CONST_METHOD0(GetScreenOrientation,
ClientContextProto::ScreenOrientation());
MOCK_CONST_METHOD0(IsAccessibilityEnabled, bool());
diff --git a/chromium/components/autofill_assistant/browser/mock_controller_observer.h b/chromium/components/autofill_assistant/browser/mock_controller_observer.h
index 2ec11f55606..5c216c7ec64 100644
--- a/chromium/components/autofill_assistant/browser/mock_controller_observer.h
+++ b/chromium/components/autofill_assistant/browser/mock_controller_observer.h
@@ -61,6 +61,8 @@ class MockControllerObserver : public ControllerObserver {
MOCK_METHOD1(OnClientSettingsChanged, void(const ClientSettings& settings));
MOCK_METHOD1(OnGenericUserInterfaceChanged,
void(const GenericUserInterfaceProto* generic_ui));
+ MOCK_METHOD1(OnPersistentGenericUserInterfaceChanged,
+ void(const GenericUserInterfaceProto* generic_ui));
MOCK_METHOD1(OnShouldShowOverlayChanged, void(bool should_show));
MOCK_METHOD0(OnFeedbackFormRequested, void());
};
diff --git a/chromium/components/autofill_assistant/browser/model.proto b/chromium/components/autofill_assistant/browser/model.proto
index 8f5ea7c9495..1533088c25b 100644
--- a/chromium/components/autofill_assistant/browser/model.proto
+++ b/chromium/components/autofill_assistant/browser/model.proto
@@ -83,6 +83,10 @@ message LoginOptionList {
repeated LoginOptionProto values = 1;
}
+// Can be used to indicate the presence of a field, without the ambiguity that
+// a boolean field would have.
+message Empty {}
+
// Next: 29
enum ProcessedActionStatusProto {
UNKNOWN_ACTION_STATUS = 0;
@@ -210,6 +214,13 @@ enum ProcessedActionStatusProto {
// password's origin.
PASSWORD_ORIGIN_MISMATCH = 29;
+ // Selecting an option failed because more than one option matched.
+ TOO_MANY_OPTION_VALUES_FOUND = 30;
+
+ // The action's target did not fit the action. E.g. a |SelectOption| being
+ // called on any element other than <select>.
+ INVALID_TARGET = 31;
+
reserved 15, 23, 25;
}
@@ -354,8 +365,13 @@ message DateTimeProto {
}
message AutofillCreditCardProto {
- // The GUID of the card.
- optional string guid = 1;
+ oneof identifier {
+ // The GUID of the card.
+ string guid = 1;
+ // The currently selected credit card. Only works if a card was selected in
+ // a previous |CollectUserData| action.
+ Empty selected_credit_card = 2;
+ }
}
message CreditCardResponseProto {
@@ -363,8 +379,13 @@ message CreditCardResponseProto {
}
message AutofillProfileProto {
- // The GUID of the profile.
- optional string guid = 1;
+ oneof identifier {
+ // The GUID of the profile.
+ string guid = 1;
+ // The selected profile for the given profile name. Only works if a profile
+ // was selected in a previous |CollectUserData| action.
+ string selected_profile_name = 2;
+ }
}
message LoginOptionProto {
diff --git a/chromium/components/autofill_assistant/browser/onboarding_result.h b/chromium/components/autofill_assistant/browser/onboarding_result.h
index c5eee0a9f09..62ae111c24a 100644
--- a/chromium/components/autofill_assistant/browser/onboarding_result.h
+++ b/chromium/components/autofill_assistant/browser/onboarding_result.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ONBOARDING_RESULT_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_ONBOARDING_RESULT_H_
-#include <string>
-
namespace autofill_assistant {
// GENERATED_JAVA_ENUM_PACKAGE: (
diff --git a/chromium/components/autofill_assistant/browser/overlay_state.h b/chromium/components/autofill_assistant/browser/overlay_state.h
index 0c22d1c5e42..05de74981ec 100644
--- a/chromium/components/autofill_assistant/browser/overlay_state.h
+++ b/chromium/components/autofill_assistant/browser/overlay_state.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_OVERLAY_STATE_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_OVERLAY_STATE_H_
-#include <string>
-
#include "base/callback.h"
namespace autofill_assistant {
diff --git a/chromium/components/autofill_assistant/browser/protocol_utils.cc b/chromium/components/autofill_assistant/browser/protocol_utils.cc
index 0f6bb816666..25a344d206b 100644
--- a/chromium/components/autofill_assistant/browser/protocol_utils.cc
+++ b/chromium/components/autofill_assistant/browser/protocol_utils.cc
@@ -4,11 +4,15 @@
#include "components/autofill_assistant/browser/protocol_utils.h"
+#include <map>
#include <utility>
#include "base/feature_list.h"
#include "base/logging.h"
#include "components/autofill_assistant/browser/actions/action_delegate_util.h"
+#include "components/autofill_assistant/browser/actions/check_element_tag_action.h"
+#include "components/autofill_assistant/browser/actions/check_option_element_action.h"
+#include "components/autofill_assistant/browser/actions/clear_persistent_ui_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"
@@ -28,6 +32,7 @@
#include "components/autofill_assistant/browser/actions/select_option_action.h"
#include "components/autofill_assistant/browser/actions/set_attribute_action.h"
#include "components/autofill_assistant/browser/actions/set_form_field_value_action.h"
+#include "components/autofill_assistant/browser/actions/set_persistent_ui_action.h"
#include "components/autofill_assistant/browser/actions/show_cast_action.h"
#include "components/autofill_assistant/browser/actions/show_details_action.h"
#include "components/autofill_assistant/browser/actions/show_form_action.h"
@@ -112,7 +117,7 @@ std::string ProtocolUtils::CreateInitialScriptActionsRequest(
const std::string& script_payload,
const ClientContextProto& client_context,
const ScriptParameters& script_parameters,
- const base::Optional<ScriptStoreConfig>& script_store_config) {
+ const absl::optional<ScriptStoreConfig>& script_store_config) {
ScriptActionRequestProto request_proto;
InitialScriptActionsRequestProto* initial_request_proto =
request_proto.mutable_initial_request();
@@ -258,18 +263,20 @@ std::unique_ptr<Action> ProtocolUtils::CreateAction(ActionDelegate* delegate,
case ActionProto::ActionInfoCase::kSendClickEvent:
return PerformOnSingleElementAction::WithClientId(
delegate, action, action.send_click_event().client_id(),
- base::BindOnce(&ActionDelegate::ClickOrTapElement,
- delegate->GetWeakPtr(), ClickType::CLICK));
+ base::BindOnce(&WebController::ClickOrTapElement,
+ delegate->GetWebController()->GetWeakPtr(),
+ ClickType::CLICK));
case ActionProto::ActionInfoCase::kSendTapEvent:
return PerformOnSingleElementAction::WithClientId(
delegate, action, action.send_tap_event().client_id(),
- base::BindOnce(&ActionDelegate::ClickOrTapElement,
- delegate->GetWeakPtr(), ClickType::TAP));
+ base::BindOnce(&WebController::ClickOrTapElement,
+ delegate->GetWebController()->GetWeakPtr(),
+ ClickType::TAP));
case ActionProto::ActionInfoCase::kJsClick:
return PerformOnSingleElementAction::WithClientId(
delegate, action, action.js_click().client_id(),
- base::BindOnce(&ActionDelegate::ClickOrTapElement,
- delegate->GetWeakPtr(), ClickType::JAVASCRIPT));
+ base::BindOnce(&WebController::JsClickElement,
+ delegate->GetWebController()->GetWeakPtr()));
case ActionProto::ActionInfoCase::kSendKeystrokeEvents:
return PerformOnSingleElementAction::WithClientId(
delegate, action, action.send_keystroke_events().client_id(),
@@ -328,13 +335,28 @@ std::unique_ptr<Action> ProtocolUtils::CreateAction(ActionDelegate* delegate,
return std::make_unique<ReleaseElementsAction>(delegate, action);
case ActionProto::ActionInfoCase::kDispatchJsEvent:
return std::make_unique<DispatchJsEventAction>(delegate, action);
- case ActionProto::ActionInfoCase::kSendKeyEvent: {
+ case ActionProto::ActionInfoCase::kSendKeyEvent:
return PerformOnSingleElementAction::WithClientId(
delegate, action, action.send_key_event().client_id(),
base::BindOnce(&WebController::SendKeyEvent,
delegate->GetWebController()->GetWeakPtr(),
action.send_key_event().key_event()));
- }
+ case ActionProto::ActionInfoCase::kSelectOptionElement:
+ return PerformOnSingleElementAction::WithClientId(
+ delegate, action, action.select_option_element().select_id(),
+ base::BindOnce(
+ &action_delegate_util::PerformWithElementValue, delegate,
+ action.select_option_element().option_id(),
+ base::BindOnce(&WebController::SelectOptionElement,
+ delegate->GetWebController()->GetWeakPtr())));
+ case ActionProto::ActionInfoCase::kCheckElementTag:
+ return std::make_unique<CheckElementTagAction>(delegate, action);
+ case ActionProto::ActionInfoCase::kCheckOptionElement:
+ return std::make_unique<CheckOptionElementAction>(delegate, action);
+ case ActionProto::ActionInfoCase::kSetPersistentUi:
+ return std::make_unique<SetPersistentUiAction>(delegate, action);
+ case ActionProto::ActionInfoCase::kClearPersistentUi:
+ return std::make_unique<ClearPersistentUiAction>(delegate, action);
case ActionProto::ActionInfoCase::ACTION_INFO_NOT_SET: {
VLOG(1) << "Encountered action with ACTION_INFO_NOT_SET";
return std::make_unique<UnsupportedAction>(delegate, action);
@@ -396,7 +418,7 @@ std::string ProtocolUtils::CreateGetTriggerScriptsRequest(
GetTriggerScriptsRequestProto request_proto;
request_proto.set_url(url.spec());
*request_proto.mutable_client_context() = client_context;
- *request_proto.mutable_debug_script_parameters() =
+ *request_proto.mutable_script_parameters() =
script_parameters.ToProto(/* only_trigger_script_allowlisted = */ true);
std::string serialized_request_proto;
@@ -411,11 +433,13 @@ bool ProtocolUtils::ParseTriggerScripts(
std::vector<std::unique_ptr<TriggerScript>>* trigger_scripts,
std::vector<std::string>* additional_allowed_domains,
int* trigger_condition_check_interval_ms,
- base::Optional<int>* timeout_ms) {
+ absl::optional<int>* timeout_ms,
+ absl::optional<std::unique_ptr<ScriptParameters>>* script_parameters) {
DCHECK(trigger_scripts);
DCHECK(additional_allowed_domains);
DCHECK(trigger_condition_check_interval_ms);
DCHECK(timeout_ms);
+ DCHECK(script_parameters);
GetTriggerScriptsResponseProto response_proto;
if (!response_proto.ParseFromString(response)) {
@@ -450,6 +474,14 @@ bool ProtocolUtils::ParseTriggerScripts(
if (response_proto.has_timeout_ms()) {
*timeout_ms = response_proto.timeout_ms();
}
+
+ if (!response_proto.script_parameters().empty()) {
+ std::map<std::string, std::string> parameters;
+ for (const auto& param : response_proto.script_parameters()) {
+ parameters.emplace(param.name(), param.value());
+ }
+ *script_parameters = std::make_unique<ScriptParameters>(parameters);
+ }
return true;
}
diff --git a/chromium/components/autofill_assistant/browser/protocol_utils.h b/chromium/components/autofill_assistant/browser/protocol_utils.h
index 8c6198b7176..fb6dd7e6bba 100644
--- a/chromium/components/autofill_assistant/browser/protocol_utils.h
+++ b/chromium/components/autofill_assistant/browser/protocol_utils.h
@@ -11,12 +11,12 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "components/autofill_assistant/browser/actions/action.h"
#include "components/autofill_assistant/browser/script.h"
#include "components/autofill_assistant/browser/script_parameters.h"
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/trigger_scripts/trigger_script.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -47,7 +47,7 @@ class ProtocolUtils {
const std::string& script_payload,
const ClientContextProto& client_context,
const ScriptParameters& script_parameters,
- const base::Optional<ScriptStoreConfig>& script_store_config);
+ const absl::optional<ScriptStoreConfig>& script_store_config);
// Create request to get next sequence of actions for a script.
static std::string CreateNextScriptActionsRequest(
@@ -92,7 +92,8 @@ class ProtocolUtils {
std::vector<std::unique_ptr<TriggerScript>>* trigger_scripts,
std::vector<std::string>* additional_allowed_domains,
int* trigger_condition_check_interval_ms,
- base::Optional<int>* timeout_ms);
+ absl::optional<int>* timeout_ms,
+ absl::optional<std::unique_ptr<ScriptParameters>>* script_parameters);
private:
// Checks that the |trigger_condition| is well-formed (e.g. does not contain
diff --git a/chromium/components/autofill_assistant/browser/protocol_utils_unittest.cc b/chromium/components/autofill_assistant/browser/protocol_utils_unittest.cc
index 06f013811dc..297423f7277 100644
--- a/chromium/components/autofill_assistant/browser/protocol_utils_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/protocol_utils_unittest.cc
@@ -5,11 +5,11 @@
#include "components/autofill_assistant/browser/protocol_utils.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/autofill_assistant/browser/selector.h"
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace autofill_assistant {
@@ -17,7 +17,9 @@ namespace autofill_assistant {
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::IsEmpty;
+using ::testing::Ne;
using ::testing::Not;
+using ::testing::Optional;
using ::testing::Pair;
using ::testing::Pointee;
using ::testing::Property;
@@ -121,7 +123,7 @@ TEST_F(ProtocolUtilsTest, CreateInitialScriptActionsRequest) {
request.ParseFromString(ProtocolUtils::CreateInitialScriptActionsRequest(
"script_path", GURL("http://example.com/"), "global_payload",
"script_payload", client_context_proto_, parameters,
- base::Optional<ScriptStoreConfig>(config))));
+ absl::optional<ScriptStoreConfig>(config))));
const InitialScriptActionsRequestProto& initial = request.initial_request();
EXPECT_THAT(initial.query().script_path(), ElementsAre("script_path"));
@@ -324,10 +326,11 @@ TEST_F(ProtocolUtilsTest, ParseTriggerScriptsParseError) {
std::vector<std::unique_ptr<TriggerScript>> trigger_scripts;
std::vector<std::string> additional_allowed_domains;
int interval_ms;
- base::Optional<int> timeout_ms;
- EXPECT_FALSE(ProtocolUtils::ParseTriggerScripts("invalid", &trigger_scripts,
- &additional_allowed_domains,
- &interval_ms, &timeout_ms));
+ absl::optional<int> timeout_ms;
+ absl::optional<std::unique_ptr<ScriptParameters>> script_parameters;
+ EXPECT_FALSE(ProtocolUtils::ParseTriggerScripts(
+ "invalid", &trigger_scripts, &additional_allowed_domains, &interval_ms,
+ &timeout_ms, &script_parameters));
EXPECT_TRUE(trigger_scripts.empty());
}
@@ -340,7 +343,7 @@ TEST_F(ProtocolUtilsTest, CreateGetTriggerScriptsRequest) {
GURL("http://example.com/"), client_context_proto_, parameters)));
AssertClientContext(request.client_context());
- EXPECT_THAT(request.debug_script_parameters(),
+ EXPECT_THAT(request.script_parameters(),
UnorderedElementsAreArray(
ScriptParameters(std::map<std::string, std::string>{
{"DEBUG_BUNDLE_ID", "123"}})
@@ -356,6 +359,13 @@ TEST_F(ProtocolUtilsTest, ParseTriggerScriptsValid) {
proto.set_trigger_condition_check_interval_ms(2000);
proto.set_timeout_ms(500000);
+ auto* param_1 = proto.add_script_parameters();
+ param_1->set_name("param_1");
+ param_1->set_value("value_1");
+ auto* param_2 = proto.add_script_parameters();
+ param_2->set_name("param_2");
+ param_2->set_value("value_2");
+
TriggerScriptProto trigger_script_1;
*trigger_script_1.mutable_trigger_condition()->mutable_selector() =
ToSelectorProto("fake_element_1");
@@ -370,10 +380,11 @@ TEST_F(ProtocolUtilsTest, ParseTriggerScriptsValid) {
std::vector<std::unique_ptr<TriggerScript>> trigger_scripts;
std::vector<std::string> additional_allowed_domains;
int interval_ms;
- base::Optional<int> timeout_ms;
- EXPECT_TRUE(ProtocolUtils::ParseTriggerScripts(proto_str, &trigger_scripts,
- &additional_allowed_domains,
- &interval_ms, &timeout_ms));
+ absl::optional<int> timeout_ms;
+ absl::optional<std::unique_ptr<ScriptParameters>> script_parameters;
+ EXPECT_TRUE(ProtocolUtils::ParseTriggerScripts(
+ proto_str, &trigger_scripts, &additional_allowed_domains, &interval_ms,
+ &timeout_ms, &script_parameters));
EXPECT_THAT(
trigger_scripts,
ElementsAre(
@@ -383,6 +394,12 @@ TEST_F(ProtocolUtilsTest, ParseTriggerScriptsValid) {
ElementsAre("example.com", "other-example.com"));
EXPECT_EQ(interval_ms, 2000);
EXPECT_EQ(timeout_ms, 500000);
+ ASSERT_THAT(script_parameters, Ne(absl::nullopt));
+ EXPECT_THAT((*script_parameters)
+ ->ToProto(
+ /* only_trigger_script_allowlisted = */ false),
+ ElementsAre(std::make_pair("param_1", "value_1"),
+ std::make_pair("param_2", "value_2")));
}
TEST_F(ProtocolUtilsTest, TurnOffResizeVisualViewport) {
@@ -401,11 +418,11 @@ TEST_F(ProtocolUtilsTest, TurnOffResizeVisualViewport) {
std::vector<std::unique_ptr<TriggerScript>> trigger_scripts;
std::vector<std::string> additional_allowed_domains;
int interval_ms;
- base::Optional<int> timeout_ms;
-
- EXPECT_TRUE(ProtocolUtils::ParseTriggerScripts(proto_str, &trigger_scripts,
- &additional_allowed_domains,
- &interval_ms, &timeout_ms));
+ absl::optional<int> timeout_ms;
+ absl::optional<std::unique_ptr<ScriptParameters>> script_parameters;
+ EXPECT_TRUE(ProtocolUtils::ParseTriggerScripts(
+ proto_str, &trigger_scripts, &additional_allowed_domains, &interval_ms,
+ &timeout_ms, &script_parameters));
ASSERT_THAT(trigger_scripts, SizeIs(2));
EXPECT_TRUE(trigger_scripts[0]->AsProto().user_interface().scroll_to_hide());
@@ -434,11 +451,11 @@ TEST_F(ProtocolUtilsTest, ParseTriggerScriptsFailsOnInvalidConditions) {
std::vector<std::unique_ptr<TriggerScript>> trigger_scripts;
std::vector<std::string> additional_allowed_domains;
int interval_ms;
- base::Optional<int> timeout_ms;
-
- EXPECT_FALSE(ProtocolUtils::ParseTriggerScripts(proto_str, &trigger_scripts,
- &additional_allowed_domains,
- &interval_ms, &timeout_ms));
+ absl::optional<int> timeout_ms;
+ absl::optional<std::unique_ptr<ScriptParameters>> script_parameters;
+ EXPECT_FALSE(ProtocolUtils::ParseTriggerScripts(
+ proto_str, &trigger_scripts, &additional_allowed_domains, &interval_ms,
+ &timeout_ms, &script_parameters));
EXPECT_THAT(trigger_scripts, IsEmpty());
}
diff --git a/chromium/components/autofill_assistant/browser/public/mock_runtime_manager.h b/chromium/components/autofill_assistant/browser/public/mock_runtime_manager.h
index e7007b51296..a916a22d746 100644
--- a/chromium/components/autofill_assistant/browser/public/mock_runtime_manager.h
+++ b/chromium/components/autofill_assistant/browser/public/mock_runtime_manager.h
@@ -23,4 +23,4 @@ class MockRuntimeManager : public RuntimeManagerImpl {
} // namespace autofill_assistant
-#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_MOCK_CLIENT_H_
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_PUBLIC_MOCK_RUNTIME_MANAGER_H_
diff --git a/chromium/components/autofill_assistant/browser/script_executor.cc b/chromium/components/autofill_assistant/browser/script_executor.cc
index 5bbc42111f1..09cad3dbfb3 100644
--- a/chromium/components/autofill_assistant/browser/script_executor.cc
+++ b/chromium/components/autofill_assistant/browser/script_executor.cc
@@ -182,65 +182,11 @@ void ScriptExecutor::OnNavigationStateChanged() {
}
}
-bool ScriptExecutor::ShouldInterruptOnPause(const ActionProto& proto) {
- switch (proto.action_info_case()) {
- case ActionProto::ActionInfoCase::kPrompt:
- case ActionProto::ActionInfoCase::kCollectUserData:
- case ActionProto::ActionInfoCase::kShowGenericUi:
- return true;
- case ActionProto::ActionInfoCase::kClick:
- case ActionProto::ActionInfoCase::kTell:
- case ActionProto::ActionInfoCase::kShowCast:
- case ActionProto::ActionInfoCase::kUseAddress:
- case ActionProto::ActionInfoCase::kUseCard:
- case ActionProto::ActionInfoCase::kWaitForDom:
- case ActionProto::ActionInfoCase::kSelectOption:
- case ActionProto::ActionInfoCase::kNavigate:
- case ActionProto::ActionInfoCase::kStop:
- case ActionProto::ActionInfoCase::kHighlightElement:
- case ActionProto::ActionInfoCase::kUploadDom:
- case ActionProto::ActionInfoCase::kShowDetails:
- case ActionProto::ActionInfoCase::kSetFormValue:
- case ActionProto::ActionInfoCase::kShowProgressBar:
- case ActionProto::ActionInfoCase::kSetAttribute:
- case ActionProto::ActionInfoCase::kShowInfoBox:
- case ActionProto::ActionInfoCase::kExpectNavigation:
- case ActionProto::ActionInfoCase::kWaitForNavigation:
- case ActionProto::ActionInfoCase::kConfigureBottomSheet:
- case ActionProto::ActionInfoCase::kShowForm:
- case ActionProto::ActionInfoCase::kPopupMessage:
- case ActionProto::ActionInfoCase::kWaitForDocument:
- case ActionProto::ActionInfoCase::kGeneratePasswordForFormField:
- case ActionProto::ActionInfoCase::kSaveGeneratedPassword:
- case ActionProto::ActionInfoCase::kConfigureUiState:
- case ActionProto::ActionInfoCase::kPresaveGeneratedPassword:
- case ActionProto::ActionInfoCase::kGetElementStatus:
- case ActionProto::ActionInfoCase::kScrollIntoView:
- case ActionProto::ActionInfoCase::kWaitForDocumentToBecomeInteractive:
- case ActionProto::ActionInfoCase::kWaitForDocumentToBecomeComplete:
- case ActionProto::ActionInfoCase::kSendClickEvent:
- case ActionProto::ActionInfoCase::kSendTapEvent:
- case ActionProto::ActionInfoCase::kJsClick:
- case ActionProto::ActionInfoCase::kSendKeystrokeEvents:
- case ActionProto::ActionInfoCase::kSendChangeEvent:
- case ActionProto::ActionInfoCase::kSetElementAttribute:
- case ActionProto::ActionInfoCase::kSelectFieldValue:
- case ActionProto::ActionInfoCase::kFocusField:
- case ActionProto::ActionInfoCase::kWaitForElementToBecomeStable:
- case ActionProto::ActionInfoCase::kCheckElementIsOnTop:
- case ActionProto::ActionInfoCase::kReleaseElements:
- case ActionProto::ActionInfoCase::kDispatchJsEvent:
- case ActionProto::ActionInfoCase::kSendKeyEvent:
- case ActionProto::ActionInfoCase::ACTION_INFO_NOT_SET:
- return false;
- }
-}
-
void ScriptExecutor::OnPause(const std::string& message,
const std::string& button_label) {
if (current_action_index_.has_value()) {
DCHECK_LT(*current_action_index_, actions_.size());
- if (ShouldInterruptOnPause(actions_[*current_action_index_]->proto())) {
+ if (actions_[*current_action_index_]->ShouldInterruptOnPause()) {
actions_[*current_action_index_] = ProtocolUtils::CreateAction(
this, actions_[*current_action_index_]->proto());
current_action_data_ = CurrentActionData();
@@ -379,14 +325,6 @@ void ScriptExecutor::FindAllElements(const Selector& selector,
delegate_->GetWebController()->FindAllElements(selector, std::move(callback));
}
-void ScriptExecutor::ClickOrTapElement(
- ClickType click_type,
- const ElementFinder::Result& element,
- base::OnceCallback<void(const ClientStatus&)> callback) {
- delegate_->GetWebController()->ClickOrTapElement(element, click_type,
- std::move(callback));
-}
-
void ScriptExecutor::CollectUserData(
CollectUserDataOptions* collect_user_data_options) {
collect_user_data_options->confirm_callback = base::BindOnce(
@@ -798,10 +736,22 @@ void ScriptExecutor::SetGenericUi(
std::move(view_inflation_finished_callback));
}
+void ScriptExecutor::SetPersistentGenericUi(
+ std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) {
+ delegate_->SetPersistentGenericUi(
+ std::move(generic_ui), std::move(view_inflation_finished_callback));
+}
+
void ScriptExecutor::ClearGenericUi() {
delegate_->ClearGenericUi();
}
+void ScriptExecutor::ClearPersistentGenericUi() {
+ delegate_->ClearPersistentGenericUi();
+}
+
void ScriptExecutor::SetOverlayBehavior(
ConfigureUiStateProto::OverlayBehavior overlay_behavior) {
delegate_->SetOverlayBehavior(overlay_behavior);
@@ -966,6 +916,7 @@ void ScriptExecutor::ReportScriptsUpdateToListener(
void ScriptExecutor::RunCallback(bool success) {
if (should_clean_contextual_ui_on_finish_ || !success) {
SetDetails(nullptr, base::TimeDelta());
+ ClearPersistentGenericUi();
should_clean_contextual_ui_on_finish_ = false;
}
diff --git a/chromium/components/autofill_assistant/browser/script_executor.h b/chromium/components/autofill_assistant/browser/script_executor.h
index 4fb9b150443..6ff27c2e096 100644
--- a/chromium/components/autofill_assistant/browser/script_executor.h
+++ b/chromium/components/autofill_assistant/browser/script_executor.h
@@ -147,10 +147,6 @@ class ScriptExecutor : public ActionDelegate,
ElementFinder::Callback callback) const override;
void FindAllElements(const Selector& selector,
ElementFinder::Callback callback) const override;
- void ClickOrTapElement(
- ClickType click_type,
- const ElementFinder::Result& element,
- base::OnceCallback<void(const ClientStatus&)> callback) override;
void CollectUserData(
CollectUserDataOptions* collect_user_data_options) override;
void SetLastSuccessfulUserDataOptions(std::unique_ptr<CollectUserDataOptions>
@@ -252,7 +248,12 @@ class ScriptExecutor : public ActionDelegate,
base::OnceCallback<void(const ClientStatus&)> end_action_callback,
base::OnceCallback<void(const ClientStatus&)>
view_inflation_finished_callback) override;
+ void SetPersistentGenericUi(
+ std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) override;
void ClearGenericUi() override;
+ void ClearPersistentGenericUi() override;
void SetOverlayBehavior(
ConfigureUiStateProto::OverlayBehavior overlay_behavior) override;
void MaybeShowSlowWebsiteWarning(
@@ -447,10 +448,6 @@ class ScriptExecutor : public ActionDelegate,
base::TimeDelta wait_time);
void OnResume();
- // Actions that can manipulate the UserActions should be interrupted, such
- // that they do not overwrite the paused state.
- bool ShouldInterruptOnPause(const ActionProto& proto);
-
// Maybe shows the message specified in a callout, depending on the current
// state and client settings.
bool MaybeShowSlowWarning(const std::string& message, bool enabled);
@@ -521,7 +518,7 @@ class ScriptExecutor : public ActionDelegate,
base::OnceCallback<void()> end_prompt_on_navigation_callback;
};
CurrentActionData current_action_data_;
- base::Optional<size_t> current_action_index_;
+ absl::optional<size_t> current_action_index_;
const UserData* user_data_ = nullptr;
diff --git a/chromium/components/autofill_assistant/browser/script_executor_delegate.h b/chromium/components/autofill_assistant/browser/script_executor_delegate.h
index ea599e69904..1e0db3f5e47 100644
--- a/chromium/components/autofill_assistant/browser/script_executor_delegate.h
+++ b/chromium/components/autofill_assistant/browser/script_executor_delegate.h
@@ -186,9 +186,18 @@ class ScriptExecutorDelegate {
base::OnceCallback<void(const ClientStatus&)>
view_inflation_finished_callback) = 0;
+ // Sets the persistent generic UI to show to the user.
+ virtual void SetPersistentGenericUi(
+ std::unique_ptr<GenericUserInterfaceProto> generic_ui,
+ base::OnceCallback<void(const ClientStatus&)>
+ view_inflation_finished_callback) = 0;
+
// Clears the generic UI.
virtual void ClearGenericUi() = 0;
+ // Clears the persistent generic UI.
+ virtual void ClearPersistentGenericUi() = 0;
+
// Sets whether browse mode should be invisible or not. Must be set before
// calling |EnterState(BROWSE)| to take effect.
virtual void SetBrowseModeInvisible(bool invisible) = 0;
diff --git a/chromium/components/autofill_assistant/browser/script_executor_unittest.cc b/chromium/components/autofill_assistant/browser/script_executor_unittest.cc
index 0ba55fb0d25..8cfed84ec44 100644
--- a/chromium/components/autofill_assistant/browser/script_executor_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -75,7 +75,7 @@ class ScriptExecutorTest : public testing::Test,
// In this test, "tell" actions always succeed and "click" actions,
// always fail. The following makes a click action fail.
- ON_CALL(mock_web_controller_, OnWaitForDocumentReadyState(_, _, _))
+ ON_CALL(mock_web_controller_, WaitForDocumentReadyState(_, _, _))
.WillByDefault(RunOnceCallback<2>(OkClientStatus(), DOCUMENT_COMPLETE,
base::TimeDelta::FromSeconds(0)));
ON_CALL(mock_web_controller_, ScrollIntoView(_, _, _))
@@ -83,8 +83,8 @@ class ScriptExecutorTest : public testing::Test,
ON_CALL(mock_web_controller_, WaitUntilElementIsStable(_, _, _, _))
.WillByDefault(RunOnceCallback<3>(OkClientStatus(),
base::TimeDelta::FromSeconds(0)));
- ON_CALL(mock_web_controller_, OnClickOrTapElement(_, _))
- .WillByDefault(RunOnceCallback<1>(ClientStatus(UNEXPECTED_JS_ERROR)));
+ ON_CALL(mock_web_controller_, ClickOrTapElement(_, _, _))
+ .WillByDefault(RunOnceCallback<2>(ClientStatus(UNEXPECTED_JS_ERROR)));
}
protected:
@@ -2134,5 +2134,23 @@ TEST_F(ScriptExecutorTest, RoundtripTimingStats) {
EXPECT_EQ(1000, timing_stats.client_time_ms());
}
+TEST_F(ScriptExecutorTest, ClearPersistentUiOnError) {
+ ActionsResponseProto actions_response;
+ actions_response.add_actions()->mutable_tell()->set_message("1");
+ EXPECT_CALL(mock_service_, OnGetActions(_, _, _, _, _, _))
+ .WillOnce(RunOnceCallback<5>(net::HTTP_OK, Serialize(actions_response)));
+ EXPECT_CALL(mock_service_, OnGetNextActions(_, _, _, _, _, _))
+ .WillOnce(RunOnceCallback<5>(net::HTTP_UNAUTHORIZED, ""));
+ EXPECT_CALL(executor_callback_,
+ Run(Field(&ScriptExecutor::Result::success, false)));
+
+ // empty, but not null
+ delegate_.SetPersistentGenericUi(
+ std::make_unique<GenericUserInterfaceProto>(), base::DoNothing());
+ ASSERT_NE(nullptr, delegate_.GetPersistentGenericUi());
+ executor_->Run(&user_data_, executor_callback_.Get());
+ ASSERT_EQ(nullptr, delegate_.GetPersistentGenericUi());
+}
+
} // namespace
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/script_parameters.cc b/chromium/components/autofill_assistant/browser/script_parameters.cc
index b2677f76cb7..1b348caabc0 100644
--- a/chromium/components/autofill_assistant/browser/script_parameters.cc
+++ b/chromium/components/autofill_assistant/browser/script_parameters.cc
@@ -13,12 +13,12 @@ namespace {
// Converts a value to a target type. Returns nullopt for invalid or
// non-existent values. Expects bool parameters as 'false' and 'true'.
template <typename T>
-base::Optional<T> GetTypedParameter(
+absl::optional<T> GetTypedParameter(
const std::map<std::string, std::string> parameters,
const std::string& key) {
auto iter = parameters.find(key);
if (iter == parameters.end())
- return base::nullopt;
+ return absl::nullopt;
std::stringstream ss;
ss << iter->second;
@@ -26,7 +26,7 @@ base::Optional<T> GetTypedParameter(
if (!(ss >> std::boolalpha >> out)) {
LOG(ERROR) << "Error trying to convert parameter '" << key
<< "' with value '" << iter->second << "' to target type";
- return base::nullopt;
+ return absl::nullopt;
}
return out;
}
@@ -82,9 +82,9 @@ const char kIntent[] = "INTENT";
// The list of script parameters that trigger scripts are allowed to send to
// the backend.
-constexpr std::array<const char*, 5> kAllowlistedTriggerScriptParameters = {
- "DEBUG_BUNDLE_ID", "DEBUG_BUNDLE_VERSION", "DEBUG_SOCKET_ID",
- "FALLBACK_BUNDLE_ID", "FALLBACK_BUNDLE_VERSION"};
+constexpr std::array<const char*, 6> kAllowlistedTriggerScriptParameters = {
+ "DEBUG_BUNDLE_ID", "DEBUG_BUNDLE_VERSION", "DEBUG_SOCKET_ID",
+ "FALLBACK_BUNDLE_ID", "FALLBACK_BUNDLE_VERSION", kIntent};
// Parameters to specify details before the first backend roundtrip.
const char kDetailsShowInitialParameterName[] = "DETAILS_SHOW_INITIAL";
@@ -156,102 +156,102 @@ ScriptParameters::ToProto(bool only_trigger_script_allowlisted) const {
return out;
}
-base::Optional<std::string> ScriptParameters::GetParameter(
+absl::optional<std::string> ScriptParameters::GetParameter(
const std::string& name) const {
auto iter = parameters_.find(name);
if (iter == parameters_.end())
- return base::nullopt;
+ return absl::nullopt;
return iter->second;
}
-base::Optional<std::string> ScriptParameters::GetOverlayColors() const {
+absl::optional<std::string> ScriptParameters::GetOverlayColors() const {
return GetParameter(kOverlayColorParameterName);
}
-base::Optional<std::string> ScriptParameters::GetPasswordChangeUsername()
+absl::optional<std::string> ScriptParameters::GetPasswordChangeUsername()
const {
return GetParameter(kPasswordChangeUsernameParameterName);
}
-base::Optional<std::string>
+absl::optional<std::string>
ScriptParameters::GetBase64TriggerScriptsResponseProto() const {
return GetParameter(kBase64TriggerScriptsResponseProtoParameterName);
}
-base::Optional<bool> ScriptParameters::GetRequestsTriggerScript() const {
+absl::optional<bool> ScriptParameters::GetRequestsTriggerScript() const {
return GetTypedParameter<bool>(parameters_,
kRequestTriggerScriptParameterName);
}
-base::Optional<bool> ScriptParameters::GetStartImmediately() const {
+absl::optional<bool> ScriptParameters::GetStartImmediately() const {
return GetTypedParameter<bool>(parameters_, kStartImmediatelyParameterName);
}
-base::Optional<bool> ScriptParameters::GetEnabled() const {
+absl::optional<bool> ScriptParameters::GetEnabled() const {
return GetTypedParameter<bool>(parameters_, kEnabledParameterName);
}
-base::Optional<std::string> ScriptParameters::GetOriginalDeeplink() const {
+absl::optional<std::string> ScriptParameters::GetOriginalDeeplink() const {
return GetParameter(kOriginalDeeplinkParameterName);
}
-base::Optional<bool> ScriptParameters::GetTriggerScriptExperiment() const {
+absl::optional<bool> ScriptParameters::GetTriggerScriptExperiment() const {
return GetTypedParameter<bool>(parameters_,
kTriggerScriptExperimentParameterName);
}
-base::Optional<std::string> ScriptParameters::GetIntent() const {
+absl::optional<std::string> ScriptParameters::GetIntent() const {
return GetParameter(kIntent);
}
-base::Optional<std::string> ScriptParameters::GetCallerEmail() const {
+absl::optional<std::string> ScriptParameters::GetCallerEmail() const {
return GetParameter(kCallerEmailParameterName);
}
-base::Optional<bool> ScriptParameters::GetDetailsShowInitial() const {
+absl::optional<bool> ScriptParameters::GetDetailsShowInitial() const {
return GetTypedParameter<bool>(parameters_, kDetailsShowInitialParameterName);
}
-base::Optional<std::string> ScriptParameters::GetDetailsTitle() const {
+absl::optional<std::string> ScriptParameters::GetDetailsTitle() const {
return GetParameter(kDetailsTitleParameterName);
}
-base::Optional<std::string> ScriptParameters::GetDetailsDescriptionLine1()
+absl::optional<std::string> ScriptParameters::GetDetailsDescriptionLine1()
const {
return GetParameter(kDetailsDescriptionLine1ParameterName);
}
-base::Optional<std::string> ScriptParameters::GetDetailsDescriptionLine2()
+absl::optional<std::string> ScriptParameters::GetDetailsDescriptionLine2()
const {
return GetParameter(kDetailsDescriptionLine2ParameterName);
}
-base::Optional<std::string> ScriptParameters::GetDetailsDescriptionLine3()
+absl::optional<std::string> ScriptParameters::GetDetailsDescriptionLine3()
const {
return GetParameter(kDetailsDescriptionLine3ParameterName);
}
-base::Optional<std::string> ScriptParameters::GetDetailsImageUrl() const {
+absl::optional<std::string> ScriptParameters::GetDetailsImageUrl() const {
return GetParameter(kDetailsImageUrl);
}
-base::Optional<std::string> ScriptParameters::GetDetailsImageAccessibilityHint()
+absl::optional<std::string> ScriptParameters::GetDetailsImageAccessibilityHint()
const {
return GetParameter(kDetailsImageAccessibilityHint);
}
-base::Optional<std::string> ScriptParameters::GetDetailsImageClickthroughUrl()
+absl::optional<std::string> ScriptParameters::GetDetailsImageClickthroughUrl()
const {
return GetParameter(kDetailsImageClickthroughUrl);
}
-base::Optional<std::string> ScriptParameters::GetDetailsTotalPriceLabel()
+absl::optional<std::string> ScriptParameters::GetDetailsTotalPriceLabel()
const {
return GetParameter(kDetailsTotalPriceLabel);
}
-base::Optional<std::string> ScriptParameters::GetDetailsTotalPrice() const {
+absl::optional<std::string> ScriptParameters::GetDetailsTotalPrice() const {
return GetParameter(kDetailsTotalPrice);
}
diff --git a/chromium/components/autofill_assistant/browser/script_parameters.h b/chromium/components/autofill_assistant/browser/script_parameters.h
index dbf1d725a03..6cb4f5fb9f4 100644
--- a/chromium/components/autofill_assistant/browser/script_parameters.h
+++ b/chromium/components/autofill_assistant/browser/script_parameters.h
@@ -8,8 +8,8 @@
#include <map>
#include <string>
-#include "base/optional.h"
#include "components/autofill_assistant/browser/service.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -37,31 +37,31 @@ class ScriptParameters {
bool only_trigger_script_allowlisted = false) const;
// Getters for specific parameters.
- base::Optional<std::string> GetOverlayColors() const;
- base::Optional<std::string> GetPasswordChangeUsername() const;
- base::Optional<std::string> GetBase64TriggerScriptsResponseProto() const;
- base::Optional<bool> GetRequestsTriggerScript() const;
- base::Optional<bool> GetStartImmediately() const;
- base::Optional<bool> GetEnabled() const;
- base::Optional<std::string> GetOriginalDeeplink() const;
- base::Optional<bool> GetTriggerScriptExperiment() const;
- base::Optional<std::string> GetIntent() const;
- base::Optional<std::string> GetCallerEmail() const;
+ absl::optional<std::string> GetOverlayColors() const;
+ absl::optional<std::string> GetPasswordChangeUsername() const;
+ absl::optional<std::string> GetBase64TriggerScriptsResponseProto() const;
+ absl::optional<bool> GetRequestsTriggerScript() const;
+ absl::optional<bool> GetStartImmediately() const;
+ absl::optional<bool> GetEnabled() const;
+ absl::optional<std::string> GetOriginalDeeplink() const;
+ absl::optional<bool> GetTriggerScriptExperiment() const;
+ absl::optional<std::string> GetIntent() const;
+ absl::optional<std::string> GetCallerEmail() const;
// Details parameters.
- base::Optional<bool> GetDetailsShowInitial() const;
- base::Optional<std::string> GetDetailsTitle() const;
- base::Optional<std::string> GetDetailsDescriptionLine1() const;
- base::Optional<std::string> GetDetailsDescriptionLine2() const;
- base::Optional<std::string> GetDetailsDescriptionLine3() const;
- base::Optional<std::string> GetDetailsImageUrl() const;
- base::Optional<std::string> GetDetailsImageAccessibilityHint() const;
- base::Optional<std::string> GetDetailsImageClickthroughUrl() const;
- base::Optional<std::string> GetDetailsTotalPriceLabel() const;
- base::Optional<std::string> GetDetailsTotalPrice() const;
+ absl::optional<bool> GetDetailsShowInitial() const;
+ absl::optional<std::string> GetDetailsTitle() const;
+ absl::optional<std::string> GetDetailsDescriptionLine1() const;
+ absl::optional<std::string> GetDetailsDescriptionLine2() const;
+ absl::optional<std::string> GetDetailsDescriptionLine3() const;
+ absl::optional<std::string> GetDetailsImageUrl() const;
+ absl::optional<std::string> GetDetailsImageAccessibilityHint() const;
+ absl::optional<std::string> GetDetailsImageClickthroughUrl() const;
+ absl::optional<std::string> GetDetailsTotalPriceLabel() const;
+ absl::optional<std::string> GetDetailsTotalPrice() const;
private:
- base::Optional<std::string> GetParameter(const std::string& name) const;
+ absl::optional<std::string> GetParameter(const std::string& name) const;
std::map<std::string, std::string> parameters_;
};
diff --git a/chromium/components/autofill_assistant/browser/script_parameters_unittest.cc b/chromium/components/autofill_assistant/browser/script_parameters_unittest.cc
index 48a751bc4f3..bb659434275 100644
--- a/chromium/components/autofill_assistant/browser/script_parameters_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/script_parameters_unittest.cc
@@ -62,7 +62,8 @@ TEST(ScriptParametersTest, TriggerScriptAllowList) {
{"DEBUG_SOCKET_ID", "678"},
{"FALLBACK_BUNDLE_ID", "fallback_id"},
{"key_b", "value_b"},
- {"FALLBACK_BUNDLE_VERSION", "fallback_ver"}}};
+ {"FALLBACK_BUNDLE_VERSION", "fallback_ver"},
+ {"INTENT", "FAKE_INTENT"}}};
EXPECT_THAT(parameters.ToProto(/* only_trigger_script_allowlisted = */ false),
UnorderedElementsAreArray(std::map<std::string, std::string>(
@@ -72,7 +73,8 @@ TEST(ScriptParametersTest, TriggerScriptAllowList) {
{"DEBUG_SOCKET_ID", "678"},
{"FALLBACK_BUNDLE_ID", "fallback_id"},
{"key_b", "value_b"},
- {"FALLBACK_BUNDLE_VERSION", "fallback_ver"}})));
+ {"FALLBACK_BUNDLE_VERSION", "fallback_ver"},
+ {"INTENT", "FAKE_INTENT"}})));
EXPECT_THAT(parameters.ToProto(/* only_trigger_script_allowlisted = */ true),
UnorderedElementsAreArray(std::map<std::string, std::string>(
@@ -80,7 +82,8 @@ TEST(ScriptParametersTest, TriggerScriptAllowList) {
{"DEBUG_BUNDLE_VERSION", "version"},
{"DEBUG_SOCKET_ID", "678"},
{"FALLBACK_BUNDLE_ID", "fallback_id"},
- {"FALLBACK_BUNDLE_VERSION", "fallback_ver"}})));
+ {"FALLBACK_BUNDLE_VERSION", "fallback_ver"},
+ {"INTENT", "FAKE_INTENT"}})));
}
TEST(ScriptParametersTest, SpecialScriptParameters) {
diff --git a/chromium/components/autofill_assistant/browser/script_tracker.h b/chromium/components/autofill_assistant/browser/script_tracker.h
index 474f0cf7b70..d32651566d0 100644
--- a/chromium/components/autofill_assistant/browser/script_tracker.h
+++ b/chromium/components/autofill_assistant/browser/script_tracker.h
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
#include "base/values.h"
#include "components/autofill_assistant/browser/script.h"
#include "components/autofill_assistant/browser/script_executor.h"
diff --git a/chromium/components/autofill_assistant/browser/selector.cc b/chromium/components/autofill_assistant/browser/selector.cc
index 10ae93269cd..2bc25775735 100644
--- a/chromium/components/autofill_assistant/browser/selector.cc
+++ b/chromium/components/autofill_assistant/browser/selector.cc
@@ -198,69 +198,6 @@ bool Selector::empty() const {
return !has_css_selector;
}
-base::Optional<std::string> Selector::ExtractSingleCssSelectorForAutofill()
- const {
- int last_enter_frame_index = -1;
- for (int i = proto.filters().size() - 1; i >= 0; i--) {
- if (proto.filters(i).filter_case() == SelectorProto::Filter::kEnterFrame) {
- last_enter_frame_index = i;
- break;
- }
- }
- std::string css_selector;
- for (int i = last_enter_frame_index + 1; i < proto.filters().size(); i++) {
- const SelectorProto::Filter& filter = proto.filters(i);
- switch (filter.filter_case()) {
- case SelectorProto::Filter::kCssSelector:
- if (css_selector.empty()) {
- css_selector = filter.css_selector();
- } else {
- VLOG(1) << __func__
- << " Selector with multiple CSS selectors not supported for "
- "autofill: "
- << *this;
- return base::nullopt;
- }
- break;
-
- case SelectorProto::Filter::kBoundingBox:
- case SelectorProto::Filter::kNthMatch:
- if (filter.nth_match().index() == 0)
- break;
-
- FALLTHROUGH;
- case SelectorProto::Filter::kInnerText:
- case SelectorProto::Filter::kValue:
- case SelectorProto::Filter::kPseudoType:
- case SelectorProto::Filter::kPseudoElementContent:
- case SelectorProto::Filter::kCssStyle:
- case SelectorProto::Filter::kLabelled:
- case SelectorProto::Filter::kMatchCssSelector:
- case SelectorProto::Filter::kOnTop:
- VLOG(1) << __func__
- << " Selector feature not supported by autofill: " << *this;
- return base::nullopt;
-
- case SelectorProto::Filter::FILTER_NOT_SET:
- VLOG(1) << __func__ << " Unknown filter type in: " << *this;
- return base::nullopt;
-
- case SelectorProto::Filter::kEnterFrame:
- // This cannot possibly happen, since the iteration started after the
- // last enter_frame.
- NOTREACHED();
- break;
- }
- }
- if (css_selector.empty()) {
- VLOG(1) << __func__
- << " Selector without CSS selector not supported by autofill: "
- << *this;
- return base::nullopt;
- }
- return css_selector;
-}
-
std::ostream& operator<<(std::ostream& out, const Selector& selector) {
return out << selector.proto;
}
diff --git a/chromium/components/autofill_assistant/browser/selector.h b/chromium/components/autofill_assistant/browser/selector.h
index c79849f3b71..9ad3dedc906 100644
--- a/chromium/components/autofill_assistant/browser/selector.h
+++ b/chromium/components/autofill_assistant/browser/selector.h
@@ -10,9 +10,9 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/service.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -83,19 +83,6 @@ struct Selector {
proto.add_filters()->set_pseudo_type(pseudo_type);
return *this;
}
-
- // Returns a single CSS selector pointing to the element from the last frame,
- // to pass to autofill.
- //
- // This call returns nothing if the selector contains unsupported filters,
- // such as innerText or pseudo-element filters.
- //
- // AutofillAgent::GetElementFormAndFieldData takes a single CSS selector that
- // identifies the form. This means that form elements for autofill are limited
- // to one single CSS selector and no further filtering. TODO(b/155264465):
- // have ElementFinder specify the element it has found in a format that
- // Autofill can recognise.
- base::Optional<std::string> ExtractSingleCssSelectorForAutofill() const;
};
// Debug output operator for selectors. The output is only useful in
diff --git a/chromium/components/autofill_assistant/browser/service.proto b/chromium/components/autofill_assistant/browser/service.proto
index 32c48bdc948..c41cf9deec3 100644
--- a/chromium/components/autofill_assistant/browser/service.proto
+++ b/chromium/components/autofill_assistant/browser/service.proto
@@ -55,6 +55,14 @@ message ClientContextProto {
// True if the script was triggered by a direct action.
optional bool is_direct_action = 9;
+ // True if this an in-Chrome triggered flow, rather than an externally
+ // triggered one.
+ optional bool is_in_chrome_triggered = 17;
+
+ // The type of trigger script that was shown and accepted at the beginning of
+ // this flow, if any.
+ optional TriggerScriptProto.TriggerUIType trigger_ui_type = 18;
+
message DeviceContextProto {
message VersionProto {
// The Android SDK version of the device.
@@ -125,6 +133,18 @@ message SupportsScriptRequestProto {
optional ClientContextProto client_context = 3;
}
+// Parameters for testers and developers of implicit triggering. This proto can
+// be specified via the base64-encoded command line switch
+// --autofill-assistant-implicit-triggering-debug-parameters. Values will take
+// precedence over existing values in case of conflict.
+message ImplicitTriggeringDebugParametersProto {
+ // The list of additional script parameters to send to the backend. This is
+ // mainly intended to allow specifying DEBUG_SOCKET_ID and DEBUG_BUNDLE_ID.
+ // Note: only a small set of parameters is allowlisted for GetTriggerScripts,
+ // see components/autofill_assistant/browser/script_parameters.cc
+ repeated ScriptParameterProto additional_script_parameters = 1;
+}
+
message ScriptParameterProto {
// Parameter name, as found in the Intent, without prefix.
optional string name = 3;
@@ -517,10 +537,6 @@ message ActionsResponseProto {
reserved 1, 6 to 10;
}
-// Can be used to indicate the presence of a field, without the ambiguity that
-// a boolean field would have.
-message Empty {}
-
// RPC request to fetch the available trigger scripts for a particular domain.
message GetTriggerScriptsRequestProto {
// The exact url for which to fetch the trigger scripts.
@@ -529,8 +545,8 @@ message GetTriggerScriptsRequestProto {
// NOTE: Currently, this will only contain the Chrome version number for
// privacy reasons.
optional ClientContextProto client_context = 2;
- // Optional debug script parameters.
- repeated ScriptParameterProto debug_script_parameters = 3;
+ // Optional script parameters.
+ repeated ScriptParameterProto script_parameters = 3;
}
// The RPC response to a |GetTriggerScriptsRequestProto|.
@@ -545,7 +561,7 @@ message GetTriggerScriptsResponseProto {
// The amount of time a trigger script may evaluate trigger conditions while
// invisible. If a trigger script is invisible for this amount of time, it
- // will automatically finish with LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT.
+ // will automatically finish with TRIGGER_CONDITION_TIMEOUT.
// If not specified, there is no automatic timeout.
//
// This is only counted while no trigger script is shown, and the time is
@@ -557,6 +573,16 @@ message GetTriggerScriptsResponseProto {
// The amount of time between consecutive checks of trigger conditions. Should
// not be too small to limit performance impact.
optional int32 trigger_condition_check_interval_ms = 4 [default = 1000];
+
+ // The list of script parameters for the client to use. This can be different
+ // from the list the client sent in the GetTriggerScriptsRequest.
+ //
+ // For some flows, the GetTriggerScripts RPC is the first and only
+ // communication with the backend prior to the start of the regular flow. As
+ // such, the backend needs to send any additional script parameters (such as
+ // appropriate overlay colors) back to the client such that the regular flows
+ // are guaranteed to have a full set of script parameters when/if they start.
+ repeated ScriptParameterProto script_parameters = 5;
}
// A trigger script contains the full specification for a trigger script that is
@@ -581,6 +607,31 @@ message TriggerScriptProto {
ACCEPT = 5;
}
+ // Set of TriggerUIType to group UKM metrics by.
+ //
+ // The set of available values is defined by AutofillAssistantTriggerUIType in
+ // tools/metrics/histograms/enums.xml
+ enum TriggerUIType {
+ UNSPECIFIED_TRIGGER_UI_TYPE = 0;
+
+ // Explicit trigger requests by some external trigger surface, i.e., a link
+ // or button.
+ SHOPPING_CART_FIRST_TIME_USER = 1;
+ SHOPPING_CART_RETURNING_USER = 2;
+ SHOPPING_CHECKOUT_FIRST_TIME_USER = 3;
+ SHOPPING_CHECKOUT_RETURNING_USER = 4;
+ FOOD_ORDERING_CART_FIRST_TIME_USER = 9;
+ FOOD_ORDERING_CART_RETURNING_USER = 10;
+
+ // Implicit trigger requests started by Chrome itself.
+ IN_CHROME_SHOPPING_CART_FIRST_TIME_USER = 5;
+ IN_CHROME_SHOPPING_CART_RETURNING_USER = 6;
+ IN_CHROME_SHOPPING_CHECKOUT_FIRST_TIME_USER = 7;
+ IN_CHROME_SHOPPING_CHECKOUT_RETURNING_USER = 8;
+ IN_CHROME_FOOD_ORDERING_CART_FIRST_TIME_USER = 11;
+ IN_CHROME_FOOD_ORDERING_CART_RETURNING_USER = 12;
+ }
+
// The |trigger_condition| must be true for the script to trigger.
optional TriggerScriptConditionProto trigger_condition = 1;
@@ -592,21 +643,9 @@ message TriggerScriptProto {
[default = CANCEL_SESSION];
// An identifier for the type of trigger UI this trigger represents, for UKM.
- optional TriggerUIType trigger_ui_type = 5;
+ optional TriggerUIType trigger_ui_type = 7;
- reserved 2;
-}
-
-// Set of TriggerUIType to group UKM metrics by.
-//
-// The set of available values is defined by AutofillAssistantTriggerUIType in
-// tools/metrics/histograms/enums.xml
-enum TriggerUIType {
- UNSPECIFIED_TRIGGER_UI_TYPE = 0;
- CART_FIRST_TIME_USER = 1;
- CART_RETURNING_USER = 2;
- CHECKOUT_FIRST_TIME_USER = 3;
- CHECKOUT_RETURNING_USER = 4;
+ reserved 2, 5, 6;
}
message TriggerScriptConditionProto {
@@ -752,6 +791,11 @@ message ActionProto {
ReleaseElementsProto release_elements = 70;
DispatchJsEventProto dispatch_js_event = 72;
SendKeyEventProto send_key_event = 73;
+ SelectOptionElementProto select_option_element = 74;
+ CheckElementTagProto check_element_tag = 75;
+ CheckOptionElementProto check_option_element = 76;
+ SetPersistentUiProto set_persistent_ui = 77;
+ ClearPersistentUiProto clear_persistent_ui = 78;
}
// Set to true to make the client remove any contextual information if the
@@ -855,6 +899,8 @@ message ProcessedActionProto {
GetElementStatusProto.Result get_element_status_result = 31;
// Should be set as a result of UploadDomProto.
UploadDomProto.Result upload_dom_result = 33;
+ // Should be set as a result of CheckOptionElementProto.
+ CheckOptionElementProto.Result check_option_element_result = 35;
}
// Reports information about navigation that happened while
@@ -1110,6 +1156,15 @@ message WebControllerErrorInfoProto {
// Send a single key event.
SEND_KEY_EVENT = 21;
+
+ // Set the selected option of an element.
+ SELECT_OPTION_ELEMENT = 22;
+
+ // Send a JS click to the element.
+ JS_CLICK_ELEMENT = 23;
+
+ // Check the selected option of an element.
+ CHECK_OPTION_ELEMENT = 24;
}
// The web-action that failed. This is usually a step in an execution chain
@@ -1349,7 +1404,11 @@ enum OptionalStep {
REQUIRE_STEP_SUCCESS = 3;
}
-// Contain all arguments to perform a select option action.
+// Contain all arguments to perform a select option action. This action also
+// fires a "change" event on the element. If the option is not found, an
+// |OPTION_VALUE_NOT_FOUND| error is returned. If the action is used on an
+// element that is not an HTML <select> element, an |OPTION_VALUE_NOT_FOUND|
+// error is returned.
message SelectOptionProto {
// The drop down element on which to select an option.
optional SelectorProto element = 2;
@@ -1359,7 +1418,7 @@ message SelectOptionProto {
TextFilter text_filter_value = 7;
// A value from an Autofill source. Note that this must be preceded by a
// |CollectUserDataAction|.
- AutofillValueRegexp autofill_value = 8;
+ AutofillValueRegexp autofill_regexp_value = 8;
}
// Defines which attribute to use for comparing the option to the expected
@@ -1373,6 +1432,11 @@ message SelectOptionProto {
}
optional OptionComparisonAttribute option_comparison_attribute = 6;
+ // If |strict|, only one match is allowed. Multiple matches will return a
+ // |TOO_MANY_OPTION_VALUES_FOUND| error. If not |strict| and multiple matches
+ // are found, the first one is selected.
+ optional bool strict = 9;
+
reserved 1, 3 to 5;
}
@@ -1462,51 +1526,68 @@ message ElementAreaProto {
repeated Rectangle restricted = 2;
}
+// Message used to indicate what form fields should be filled with what
+// information coming from either the address or the credit card.
+message RequiredFieldProto {
+ // A value expression containing any number of |key| placeholders, where the
+ // |key| is an integer corresponding to entries from field_types.h or
+ // |AutofillFormatProto::AutofillAssistantCustomField|.
+ // Example:
+ // * 3 -> First name.
+ // * 51 -> Full card name.
+ // Note that the set of actually available fields are outside of our
+ // control and are retrieved automatically.
+ // An empty value expression will clear the field.
+ optional ValueExpression value_expression = 12;
+
+ // The element to fill.
+ optional SelectorProto element = 2;
+
+ // The strategy used to execute filling the value.
+ // This is only considered for text fields and ignored for dropdowns.
+ optional KeyboardValueFillStrategy fill_strategy = 7;
+
+ // Delay between two key presses when simlulating.
+ // This is only considered for text fields and ignored for dropdowns.
+ optional int32 delay_in_millisecond = 4 [default = 20];
+
+ // The strategy used to select a value option. If no
+ // |option_comparison_value_expression_re2| is set, this is used to
+ // differentiate between "starts with" and "match".
+ optional DropdownSelectStrategy select_strategy = 8;
+
+ // The attribute to compare for selecting an option.
+ // This is only considered for dropdowns and ignored for text fields. If set,
+ // takes precedence over |select_strategy|.
+ optional SelectOptionProto.OptionComparisonAttribute
+ option_comparison_attribute = 13;
+
+ // In case of a dropdown, this should be used instead of the
+ // |value_expression_proto|. If it's empty, |value_expression_proto| will be
+ // used. This is only considered for dropdowns and ignored for text fields.
+ optional ValueExpressionRegexp option_comparison_value_expression_re2 = 14;
+
+ // Fill in the value even if it's non-empty. This is useful to work around
+ // cases where the way Autofill sets the field doesn't work on the website.
+ optional bool forced = 5;
+
+ // The field is optional. If there is no value from Autofill available or
+ // the element is not found, the field will be skipped.
+ optional bool is_optional = 11;
+
+ // For JavaScript implemented dropdowns. This first clicks on the |element|,
+ // then waits for |option_element_to_click| to appear and clicks it. The
+ // selector must match a generic option, an |inner_text_pattern| will be
+ // added to this element reference to match a single option.
+ // Both clicks use the same |click_type|.
+ optional SelectorProto option_element_to_click = 9;
+ optional ClickType click_type = 10;
+
+ reserved 1, 3, 6;
+}
+
// Fill a form with an address if there is, otherwise fail this action.
message UseAddressProto {
- // Message used to indicate what form fields should be filled with what
- // information coming from the address.
- message RequiredField {
- // A string containing any number of "${key}" placeholders, where the key
- // is an integer corresponding to entries from field_types.h or
- // |AutofillFormatProto::AutofillAssistantCustomField|.
- // Example:
- // * "3" -> First name.
- // * "${3}" -> First name.
- // * "(+${12}) (${11}) ${10}" -> phone country code, city code, number,
- // e.g., (+41) (79) (1234567)
- // Note that the set of actually available fields are outside of our
- // control and are retrieved automatically from the provided profile.
- // An value expression set to an empty string will clear the field.
- optional string value_expression = 6;
-
- optional SelectorProto element = 2;
-
- // The strategy used to execute filling the value.
- optional KeyboardValueFillStrategy fill_strategy = 7;
-
- // The strategy used to select a value option.
- optional DropdownSelectStrategy select_strategy = 8;
-
- // Delay between two key presses when simlulating.
- optional int32 delay_in_millisecond = 4 [default = 20];
-
- // Fill in the fill even if it's non-empty. This is useful to work around
- // cases where the way autofill sets the field doesn't work on the website.
- // Usually used together with simulate_key_presses.
- optional bool forced = 5;
-
- // For JavaScript implemented dropdowns. This first clicks on the |element|,
- // then waits for |option_element_to_click| to appear and clicks it. The
- // selector must match a generic option, an |inner_text_pattern| will be
- // added to this element reference to match a single option.
- // Both clicks use the same |click_type|.
- optional SelectorProto option_element_to_click = 9;
- optional ClickType click_type = 10;
-
- reserved 1, 3;
- }
-
oneof address_source {
// The client memory key from which to retrieve the address.
string name = 1;
@@ -1518,7 +1599,7 @@ message UseAddressProto {
optional SelectorProto form_field_element = 4;
// An optional list of fields that should be filled by this action.
- repeated RequiredField required_fields = 6;
+ repeated RequiredFieldProto required_fields = 6;
// If true, this skips the Autofill step jumping straight to the
// |required_fields|.
@@ -1530,48 +1611,6 @@ message UseAddressProto {
// 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.
- message RequiredField {
- // A string containing any number of "${key}" placeholders, where the key
- // is an integer corresponding to entries from field_types.h or
- // |AutofillFormatProto::AutofillAssistantCustomField|.
- // Example:
- // * "51" -> Full name.
- // * "${51}" -> Full Name.
- // * "${53}/${55}" -> expiration month / expiration year
- // Note that the set of actually available fields are outside of our
- // control and are retrieved automatically from the provided credit card.
- // An value expression set to an empty string will clear the field.
- optional string value_expression = 6;
-
- optional SelectorProto element = 2;
-
- // The strategy used to execute filling the value.
- optional KeyboardValueFillStrategy fill_strategy = 7;
-
- // The strategy used to select a value option.
- optional DropdownSelectStrategy select_strategy = 8;
-
- // Delay between two key presses when simlulating.
- optional int32 delay_in_millisecond = 4 [default = 20];
-
- // Fill in the fill even if it's non-empty. This is useful to work around
- // cases where the way autofill sets the field doesn't work on the website.
- // Usually used together with simulate_key_presses.
- optional bool forced = 5;
-
- // For JavaScript implemented dropdowns. This first clicks on the |element|,
- // then waits for |option_element_to_click| to appear and clicks it. The
- // selector must match a generic option, an |inner_text_pattern| will be
- // added to this element reference to match a single option.
- // Both clicks use the same |click_type|.
- optional SelectorProto option_element_to_click = 9;
- optional ClickType click_type = 10;
-
- reserved 1, 3;
- }
-
// The client model identifier from which to retrieve the credit card.
// If not specified, will use the card stored in client memory instead.
optional string model_identifier = 4;
@@ -1579,7 +1618,7 @@ message UseCreditCardProto {
// A reference to the card number field in the form that should be filled.
optional SelectorProto form_field_element = 3;
- repeated RequiredField required_fields = 7;
+ repeated RequiredFieldProto required_fields = 7;
// If true, this skips the Autofill step jumping straight to the
// |required_fields|.
@@ -1914,6 +1953,31 @@ message ShowGenericUiProto {
reserved 10;
}
+// Show backend-specified user interface elements to the user until dismissed.
+//
+// The UI will be shown until cleared by ClearPersistentUi or overwritten
+// by a subsequent SetPersistentUi.
+// The Ui is also cleared at the end of the script if it ended in error or if
+// the last action had |clean_contextual_ui| = true.
+//
+// Client errors:
+// INVALID_ACTION if |generic_user_interface| was ill-defined or incomplete,
+// or if the client failed to instantiate the UI for some reason. The Chrome
+// log should contain additional information about the issue, if verbose
+// logging is enabled (suggested level: 2 or 3).
+message SetPersistentUiProto {
+ // Required. The generic user interface to show.
+ //
+ // The following interaction callbacks aren't supported:
+ // - SetUserActions
+ // - ToggleUserAction
+ // - EndAction
+ optional GenericUserInterfaceProto generic_user_interface = 1;
+}
+
+// Clears the Ui set by SetPersistentUi.
+message ClearPersistentUiProto {}
+
// Allow choosing one or more possibility. If ShowCast was called just
// before, allow interaction with the touchable element area, otherwise don't
// allow any interactions.
@@ -2854,7 +2918,7 @@ message GetElementStatusProto {
optional ValueMatch expected_value_match = 2;
optional ValueSource value_source = 4;
- // If set and a mismatch happens, the action will report an failure status
+ // If set and a mismatch happens, the action will report a failure status
// with |ELEMENT_MISMATCH|. If this flag is set to false, the action will not
// fail and simply report the result.
optional bool mismatch_should_fail = 3;
@@ -2900,18 +2964,18 @@ message GetElementStatusProto {
message TextMatch {
oneof value_source {
- // The value to check against.
- string value = 1;
- // A value from an Autofill source. Note that this must be preceded by a
- // |CollectUserDataAction|.
- AutofillValue autofill_value = 2;
// A regular expression.
string re2 = 4;
+ // A value resolvable to a text. May require to be preceded by a
+ // |CollectUserDataAction|.
+ TextValue text_value = 5;
}
// Optional. The expectations to declare this as a matching success. If
// left empty, the action will always be treated as successful.
optional MatchExpectation match_expectation = 3;
+
+ reserved 1, 2;
}
message ValueMatch { optional TextMatch text_match = 1; }
diff --git a/chromium/components/autofill_assistant/browser/service/mock_url_loader.h b/chromium/components/autofill_assistant/browser/service/mock_url_loader.h
index c8fcfd28d0b..50e54b80730 100644
--- a/chromium/components/autofill_assistant/browser/service/mock_url_loader.h
+++ b/chromium/components/autofill_assistant/browser/service/mock_url_loader.h
@@ -73,7 +73,7 @@ class MockURLLoader : public ::network::SimpleURLLoader {
MOCK_CONST_METHOD0(NetError, int());
MOCK_CONST_METHOD0(ResponseInfo, const ::network::mojom::URLResponseHead*());
MOCK_CONST_METHOD0(CompletionStatus,
- base::Optional<::network::URLLoaderCompletionStatus>&());
+ absl::optional<::network::URLLoaderCompletionStatus>&());
MOCK_CONST_METHOD0(GetFinalURL, const GURL&());
MOCK_CONST_METHOD0(LoadedFromCache, bool());
MOCK_CONST_METHOD0(GetContentSize, int64_t());
diff --git a/chromium/components/autofill_assistant/browser/service/service_impl.h b/chromium/components/autofill_assistant/browser/service/service_impl.h
index d23d7992469..44ce356cf31 100644
--- a/chromium/components/autofill_assistant/browser/service/service_impl.h
+++ b/chromium/components/autofill_assistant/browser/service/service_impl.h
@@ -95,7 +95,7 @@ class ServiceImpl : public Service {
// The script store config used for GetActions request. This is set by the
// controller, obtained from the GetScriptsForUrl's response.
- base::Optional<ScriptStoreConfig> script_store_config_;
+ absl::optional<ScriptStoreConfig> script_store_config_;
base::WeakPtrFactory<ServiceImpl> weak_ptr_factory_{this};
};
diff --git a/chromium/components/autofill_assistant/browser/service/service_request_sender_impl.cc b/chromium/components/autofill_assistant/browser/service/service_request_sender_impl.cc
index ececd87da77..e3312fdac5e 100644
--- a/chromium/components/autofill_assistant/browser/service/service_request_sender_impl.cc
+++ b/chromium/components/autofill_assistant/browser/service/service_request_sender_impl.cc
@@ -76,7 +76,7 @@ void SendRequestImpl(
#endif
auto* const loader_ptr = loader.get();
loader_ptr->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
- content::BrowserContext::GetDefaultStoragePartition(context)
+ context->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess()
.get(),
base::BindOnce(&OnURLLoaderComplete, std::move(callback),
diff --git a/chromium/components/autofill_assistant/browser/starter.cc b/chromium/components/autofill_assistant/browser/starter.cc
index 06bb9c97c9d..2bec98eb020 100644
--- a/chromium/components/autofill_assistant/browser/starter.cc
+++ b/chromium/components/autofill_assistant/browser/starter.cc
@@ -4,22 +4,185 @@
#include "components/autofill_assistant/browser/starter.h"
+#include <map>
+
+#include "base/base64url.h"
#include "base/bind.h"
#include "base/callback.h"
+#include "base/command_line.h"
#include "base/feature_list.h"
+#include "base/json/json_reader.h"
#include "base/logging.h"
+#include "base/metrics/field_trial.h"
+#include "base/no_destructor.h"
#include "components/autofill_assistant/browser/features.h"
+#include "components/autofill_assistant/browser/intent_strings.h"
+#include "components/autofill_assistant/browser/service/api_key_fetcher.h"
+#include "components/autofill_assistant/browser/service/server_url_fetcher.h"
+#include "components/autofill_assistant/browser/service/service_request_sender.h"
+#include "components/autofill_assistant/browser/service/service_request_sender_impl.h"
+#include "components/autofill_assistant/browser/service/service_request_sender_local_impl.h"
+#include "components/autofill_assistant/browser/service/simple_url_loader_factory.h"
+#include "components/autofill_assistant/browser/switches.h"
+#include "components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.h"
+#include "components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.h"
+#include "components/autofill_assistant/browser/url_utils.h"
+#include "components/ukm/content/source_url_recorder.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
namespace autofill_assistant {
using StartupMode = StartupUtil::StartupMode;
+namespace {
+
+// When starting trigger scripts, depending on incoming script parameters, we
+// mark users as being in either the control or the experiment group to allow
+// for aggregation of UKM metrics.
+const char kTriggerScriptExperimentSyntheticFieldTrialName[] =
+ "AutofillAssistantTriggerScriptExperiment";
+const char kTriggerScriptExperimentGroup[] = "Experiment";
+const char kTriggerScriptControlGroup[] = "Control";
+
+// The maximum number of items to be kept in the cache. If this number is
+// exceeded, the entry that hasn't been accessed the longest is automatically
+// removed.
+constexpr size_t kMaxFailedTriggerScriptsCacheSize = 100;
+constexpr size_t kMaxUserDenylistedCacheSize = 100;
+
+// The duration for which cache entries are considered fresh. Stale entries in
+// the cache are ignored.
+constexpr base::TimeDelta kMaxFailedTriggerScriptsCacheDuration =
+ base::TimeDelta::FromHours(1);
+constexpr base::TimeDelta kMaxUserDenylistedCacheDuration =
+ base::TimeDelta::FromHours(1);
+
+// Creates a service request sender that serves the pre-specified response.
+// Creation may fail (return null) if the parameter fails to decode.
+std::unique_ptr<ServiceRequestSender> CreateBase64TriggerScriptRequestSender(
+ const std::string& base64_trigger_script) {
+ std::string response;
+ if (!base::Base64UrlDecode(base64_trigger_script,
+ base::Base64UrlDecodePolicy::IGNORE_PADDING,
+ &response)) {
+ return nullptr;
+ }
+ return std::make_unique<ServiceRequestSenderLocalImpl>(response);
+}
+
+// Creates a service request sender that communicates with a remote endpoint.
+std::unique_ptr<ServiceRequestSender> CreateRpcTriggerScriptRequestSender(
+ content::BrowserContext* browser_context,
+ StarterPlatformDelegate* delegate) {
+ return std::make_unique<ServiceRequestSenderImpl>(
+ browser_context,
+ /* access_token_fetcher = */ nullptr,
+ std::make_unique<NativeURLLoaderFactory>(),
+ ApiKeyFetcher().GetAPIKey(delegate->GetChannel()),
+ /* auth_enabled = */ false,
+ /* disable_auth_if_no_access_token = */ true);
+}
+
+// Returns whether |trigger_context| contains either the REQUEST_TRIGGER_SCRIPT
+// or the TRIGGER_SCRIPTS_BASE64 script parameter.
+bool IsTriggerScriptContext(const TriggerContext& trigger_context) {
+ const auto& script_parameters = trigger_context.GetScriptParameters();
+ return script_parameters.GetRequestsTriggerScript() ||
+ script_parameters.GetBase64TriggerScriptsResponseProto();
+}
+
+// The heuristic is shared across all instances and initialized on first use. As
+// such, we do not support updating the heuristic while Chrome is running.
+const scoped_refptr<StarterHeuristic> GetOrCreateStarterHeuristic() {
+ static const base::NoDestructor<scoped_refptr<StarterHeuristic>>
+ starter_heuristic(
+ [] { return base::MakeRefCounted<StarterHeuristic>(); }());
+ return *starter_heuristic;
+}
+
+// The cache of failed trigger script fetches is shared across all instances and
+// initialized on first use.
+base::HashingMRUCache<std::string, base::TimeTicks>*
+GetOrCreateFailedTriggerScriptFetchesCache() {
+ static base::NoDestructor<base::HashingMRUCache<std::string, base::TimeTicks>>
+ cached_failed_trigger_script_fetches(kMaxFailedTriggerScriptsCacheSize);
+ return cached_failed_trigger_script_fetches.get();
+}
+
+// Goes through the |cache| and removes entries that have gone stale, i.e.,
+// entries that were added before |cutoff_ticks|.
+void ClearStaleCacheEntries(
+ base::HashingMRUCache<std::string, base::TimeTicks>* cache,
+ base::TimeTicks cutoff_ticks) {
+ // Go in reverse order until the oldest entry is younger than |cutoff_ticks|.
+ for (auto it = cache->rbegin(); it != cache->rend();) {
+ if (it->second > cutoff_ticks) {
+ return;
+ }
+ it = cache->Erase(it);
+ }
+}
+
+// Returns true if |cache| has an entry for |url| that is younger than
+// |cutoff_ticks|, false otherwise. Does not change the order of the cache.
+bool HasFreshCacheEntry(
+ const base::HashingMRUCache<std::string, base::TimeTicks>& cache,
+ const GURL& url,
+ base::TimeTicks cutoff_ticks) {
+ std::string domain = url_utils::GetOrganizationIdentifyingDomain(url);
+ auto it = cache.Peek(domain);
+ return (it != cache.end() && (it->second > cutoff_ticks));
+}
+
+// Returns the debug parameters for implicit triggering specified in the command
+// line, or the default proto if the command line switch was not specified or
+// invalid.
+ImplicitTriggeringDebugParametersProto
+GetImplicitTriggeringDebugParametersFromCommandLine() {
+ std::string parameters =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kAutofillAssistantImplicitTriggeringDebugParameters);
+ if (parameters.empty()) {
+ return {};
+ }
+
+ if (!base::Base64UrlDecode(parameters,
+ base::Base64UrlDecodePolicy::IGNORE_PADDING,
+ &parameters)) {
+ VLOG(1) << "Failed to base64-decode debug trigger parameters: "
+ << parameters;
+ return {};
+ }
+
+ ImplicitTriggeringDebugParametersProto proto;
+ if (!proto.ParseFromString(parameters)) {
+ VLOG(1) << "Failed to parse debug trigger parameters: " << parameters;
+ return {};
+ }
+ return proto;
+}
+
+} // namespace
+
Starter::Starter(content::WebContents* web_contents,
StarterPlatformDelegate* platform_delegate,
- ukm::UkmRecorder* ukm_recorder)
+ ukm::UkmRecorder* ukm_recorder,
+ base::WeakPtr<RuntimeManagerImpl> runtime_manager,
+ const base::TickClock* tick_clock)
: content::WebContentsObserver(web_contents),
+ current_ukm_source_id_(
+ ukm::GetSourceIdForWebContentsDocument(web_contents)),
+ cached_failed_trigger_script_fetches_(
+ GetOrCreateFailedTriggerScriptFetchesCache()),
+ user_denylisted_domains_(kMaxUserDenylistedCacheSize),
+ implicit_triggering_debug_parameters_(
+ GetImplicitTriggeringDebugParametersFromCommandLine()),
platform_delegate_(platform_delegate),
- ukm_recorder_(ukm_recorder) {
+ ukm_recorder_(ukm_recorder),
+ runtime_manager_(runtime_manager),
+ starter_heuristic_(GetOrCreateStarterHeuristic()),
+ tick_clock_(tick_clock) {
CheckSettings();
}
@@ -27,50 +190,227 @@ Starter::~Starter() = default;
void Starter::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
- if (!fetch_trigger_scripts_on_navigation_) {
+ if (!navigation_handle->IsInMainFrame()) {
+ return;
+ }
+
+ // Navigating away from the deeplink domain during startup OR ending up on an
+ // error page will break the flow, unless a trigger script is currently
+ // running (in which case, the trigger script will handle this event).
+ if (IsStartupPending() && navigation_handle->HasCommitted() &&
+ !trigger_script_coordinator_) {
+ bool navigated_to_target_domain = url_utils::IsSamePublicSuffixDomain(
+ navigation_handle->GetURL(),
+ StartupUtil()
+ .ChooseStartupUrlForIntent(*GetPendingTriggerContext())
+ .value_or(GURL()));
+
+ if (navigated_to_target_domain) {
+ current_ukm_source_id_ =
+ ukm::GetSourceIdForWebContentsDocument(web_contents());
+ if (waiting_for_deeplink_navigation_) {
+ Start(std::move(pending_trigger_context_));
+ }
+ // Ignore; navigations to the target domain during startup are allowed.
+ return;
+ }
+
+ if (waiting_for_deeplink_navigation_) {
+ if (navigated_to_target_domain) {
+ Start(std::move(pending_trigger_context_));
+ return;
+ }
+ // Note: this will record for the current domain, not the target domain.
+ // There seems to be no way to avoid this.
+ Metrics::RecordTriggerScriptStarted(
+ ukm_recorder_, ukm::GetSourceIdForWebContentsDocument(web_contents()),
+ navigation_handle->IsErrorPage()
+ ? Metrics::TriggerScriptStarted::NAVIGATION_ERROR
+ : Metrics::TriggerScriptStarted::NAVIGATED_AWAY);
+ CancelPendingStartup(absl::nullopt);
+ } else {
+ // Regular startup was interrupted (most likely during the onboarding).
+ Metrics::RecordDropOut(waiting_for_onboarding_
+ ? Metrics::DropOutReason::ONBOARDING_NAVIGATION
+ : Metrics::DropOutReason::NAVIGATION,
+ GetPendingTriggerContext()
+ ->GetScriptParameters()
+ .GetIntent()
+ .value_or(std::string()));
+ CancelPendingStartup(absl::nullopt);
+ }
+ // Note: do not early-return here. While the previous startup has failed, we
+ // may have navigated to a new supported domain and may need to start
+ // implicitly.
+ }
+
+ if (navigation_handle->HasCommitted() && !navigation_handle->IsErrorPage()) {
+ current_ukm_source_id_ =
+ ukm::GetSourceIdForWebContentsDocument(web_contents());
+ MaybeStartImplicitlyForUrl(
+ navigation_handle->GetURL(),
+ ukm::ConvertToSourceId(navigation_handle->GetNavigationId(),
+ ukm::SourceIdType::NAVIGATION_ID));
+ }
+}
+
+void Starter::MaybeStartImplicitlyForUrl(const GURL& url,
+ const ukm::SourceId source_id) {
+ if (!fetch_trigger_scripts_on_navigation_ || IsStartupPending() ||
+ platform_delegate_->IsRegularScriptRunning() || !url.is_valid()) {
+ return;
+ }
+
+ // If we have failed to fetch a trigger script for this domain before, or if
+ // the user has denylisted the domain, don't try again.
+ base::TimeTicks now_ticks = tick_clock_->NowTicks();
+ if (HasFreshCacheEntry(*cached_failed_trigger_script_fetches_, url,
+ now_ticks - kMaxFailedTriggerScriptsCacheDuration)) {
+ Metrics::RecordInChromeTriggerAction(
+ ukm_recorder_, source_id,
+ Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN);
+ return;
+ }
+ if (HasFreshCacheEntry(user_denylisted_domains_, url,
+ now_ticks - kMaxUserDenylistedCacheDuration)) {
+ Metrics::RecordInChromeTriggerAction(
+ ukm_recorder_, source_id,
+ Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN);
+ return;
+ }
+
+ // Run the heuristic in a separate task.
+ starter_heuristic_->RunHeuristicAsync(
+ url, base::BindOnce(&Starter::OnHeuristicMatch,
+ weak_ptr_factory_.GetWeakPtr(), url, source_id));
+}
+
+void Starter::OnHeuristicMatch(const GURL& url,
+ const ukm::SourceId source_id,
+ absl::optional<std::string> intent) {
+ if (!intent) {
+ Metrics::RecordInChromeTriggerAction(
+ ukm_recorder_, source_id,
+ Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH);
+ return;
+ }
+ if (IsStartupPending() || !fetch_trigger_scripts_on_navigation_) {
+ Metrics::RecordInChromeTriggerAction(ukm_recorder_, source_id,
+ Metrics::InChromeTriggerAction::OTHER);
return;
}
- // TODO(arbesser): fetch trigger scripts when appropriate.
+ Metrics::RecordInChromeTriggerAction(
+ ukm_recorder_, source_id,
+ Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED);
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"REQUEST_TRIGGER_SCRIPT", "true"},
+ {"ORIGINAL_DEEPLINK", url.spec()},
+ {"INTENT", *intent}};
+ // Add/overwrite with debug parameters if specified.
+ for (const auto& debug_param :
+ implicit_triggering_debug_parameters_.additional_script_parameters()) {
+ script_parameters[debug_param.name()] = debug_param.value();
+ }
+
+ Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{/* experiment_ids = */ std::string(),
+ /* is_cct = */ is_custom_tab_,
+ /* onboarding_shown = */ false,
+ /* is_direct_action = */ false,
+ /* initial_url = */ std::string(),
+ /* is_in_chrome_triggered = */ true}));
+}
+
+bool Starter::IsStartupPending() const {
+ return GetPendingTriggerContext() != nullptr;
+}
+
+TriggerContext* Starter::GetPendingTriggerContext() const {
+ if (trigger_script_coordinator_) {
+ return &trigger_script_coordinator_->GetTriggerContext();
+ }
+ return pending_trigger_context_.get();
+}
+
+void Starter::OnTabInteractabilityChanged(bool is_interactable) {
+ CheckSettings();
+ if (trigger_script_coordinator_) {
+ trigger_script_coordinator_->OnTabInteractabilityChanged(is_interactable);
+ }
}
void Starter::CheckSettings() {
+ bool prev_is_custom_tab = is_custom_tab_;
+ is_custom_tab_ = platform_delegate_->GetIsCustomTab();
+ bool switched_from_cct_to_tab = prev_is_custom_tab && !is_custom_tab_;
bool proactive_help_setting_enabled =
platform_delegate_->GetProactiveHelpSettingEnabled();
bool msbb_setting_enabled =
platform_delegate_->GetMakeSearchesAndBrowsingBetterEnabled();
bool feature_module_installed =
platform_delegate_->GetFeatureModuleInstalled();
+ bool prev_fetch_trigger_scripts_on_navigation =
+ fetch_trigger_scripts_on_navigation_;
fetch_trigger_scripts_on_navigation_ =
- base::FeatureList::IsEnabled(
- features::kAutofillAssistantInChromeTriggering) &&
+ ((base::FeatureList::IsEnabled(
+ features::kAutofillAssistantInCCTTriggering) &&
+ is_custom_tab_) ||
+ (base::FeatureList::IsEnabled(
+ features::kAutofillAssistantInTabTriggering) &&
+ !is_custom_tab_)) &&
proactive_help_setting_enabled && msbb_setting_enabled;
// If there is a pending startup, re-check that the settings are still
// allowing the startup to proceed. If not, cancel the startup.
- if (pending_callback_) {
+ if (IsStartupPending()) {
StartupMode startup_mode = StartupUtil().ChooseStartupModeForIntent(
- *pending_trigger_context_,
+ *GetPendingTriggerContext(),
{msbb_setting_enabled, proactive_help_setting_enabled,
feature_module_installed});
switch (startup_mode) {
+ case StartupMode::START_REGULAR:
+ return;
case StartupMode::START_BASE64_TRIGGER_SCRIPT:
case StartupMode::START_RPC_TRIGGER_SCRIPT:
- case StartupMode::START_REGULAR:
+ if (!switched_from_cct_to_tab) {
+ return;
+ }
+ // Trigger scripts are not allowed to persist when transitioning from
+ // CCT to regular tab.
+ CancelPendingStartup(
+ Metrics::TriggerScriptFinishedState::CCT_TO_TAB_NOT_SUPPORTED);
return;
default:
- CancelPendingStartup();
+ CancelPendingStartup(Metrics::TriggerScriptFinishedState::
+ DISABLED_PROACTIVE_HELP_SETTING);
+ return;
}
+ } else if (!prev_fetch_trigger_scripts_on_navigation &&
+ fetch_trigger_scripts_on_navigation_) {
+ MaybeStartImplicitlyForUrl(
+ web_contents()->GetLastCommittedURL(),
+ ukm::GetSourceIdForWebContentsDocument(web_contents()));
}
}
-void Starter::Start(std::unique_ptr<TriggerContext> trigger_context,
- StarterResultCallback callback) {
+void Starter::Start(std::unique_ptr<TriggerContext> trigger_context) {
DCHECK(trigger_context);
DCHECK(!trigger_context->GetDirectAction());
- CancelPendingStartup();
+ CancelPendingStartup(Metrics::TriggerScriptFinishedState::CANCELED);
pending_trigger_context_ = std::move(trigger_context);
- pending_callback_ = std::move(callback);
+
+ if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kAutofillAssistantForceOnboarding) == "true") {
+ platform_delegate_->SetOnboardingAccepted(false);
+ }
+ if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kAutofillAssistantForceFirstTimeUser) == "true") {
+ platform_delegate_->SetIsFirstTimeUser(true);
+ }
StartupMode startup_mode = StartupUtil().ChooseStartupModeForIntent(
*pending_trigger_context_,
@@ -78,14 +418,33 @@ void Starter::Start(std::unique_ptr<TriggerContext> trigger_context,
platform_delegate_->GetProactiveHelpSettingEnabled(),
platform_delegate_->GetFeatureModuleInstalled()});
+ // Trigger scripts may need to wait for navigation to the deeplink domain to
+ // ensure that UKMs are recorded for the right source-id.
+ auto startup_url =
+ StartupUtil().ChooseStartupUrlForIntent(*pending_trigger_context_);
+ if (IsTriggerScriptContext(*pending_trigger_context_) &&
+ !startup_url.has_value()) {
+ // Fail immediately if there is no deeplink domain to wait for.
+ // Note: this will record the impression for the current domain.
+ Metrics::RecordTriggerScriptStarted(
+ ukm_recorder_, current_ukm_source_id_,
+ Metrics::TriggerScriptStarted::NO_INITIAL_URL);
+ OnStartDone(/* start_regular_script = */ false);
+ return;
+ }
+ if (IsTriggerScriptContext(*pending_trigger_context_) &&
+ !url_utils::IsSamePublicSuffixDomain(
+ web_contents()->GetLastCommittedURL(),
+ startup_url.value_or(GURL()))) {
+ waiting_for_deeplink_navigation_ = true;
+ return;
+ }
+
// Record startup metrics for trigger scripts as soon as possible to establish
// a baseline.
- const auto& script_parameters =
- pending_trigger_context_->GetScriptParameters();
- if (script_parameters.GetRequestsTriggerScript() ||
- script_parameters.GetBase64TriggerScriptsResponseProto()) {
- Metrics::RecordLiteScriptStarted(
- ukm_recorder_, web_contents(), startup_mode,
+ if (IsTriggerScriptContext(*pending_trigger_context_)) {
+ Metrics::RecordTriggerScriptStarted(
+ ukm_recorder_, current_ukm_source_id_, startup_mode,
platform_delegate_->GetFeatureModuleInstalled(),
platform_delegate_->GetIsFirstTimeUser());
}
@@ -95,7 +454,7 @@ void Starter::Start(std::unique_ptr<TriggerContext> trigger_context,
case StartupMode::MANDATORY_PARAMETERS_MISSING:
case StartupMode::SETTING_DISABLED:
case StartupMode::NO_INITIAL_URL:
- RunCallback(/* start_regular_script = */ false);
+ OnStartDone(/* start_regular_script = */ false);
return;
case StartupMode::START_BASE64_TRIGGER_SCRIPT:
case StartupMode::START_RPC_TRIGGER_SCRIPT:
@@ -105,14 +464,23 @@ void Starter::Start(std::unique_ptr<TriggerContext> trigger_context,
}
}
-void Starter::CancelPendingStartup() {
- if (!pending_callback_) {
+void Starter::CancelPendingStartup(
+ absl::optional<Metrics::TriggerScriptFinishedState> state) {
+ if (!IsStartupPending()) {
return;
}
- pending_callback_.Reset();
- pending_trigger_context_ = nullptr;
platform_delegate_->HideOnboarding();
- // TODO(arbesser): stop trigger script if necessary.
+ if (waiting_for_onboarding_) {
+ Metrics::RecordOnboardingResult(Metrics::OnBoarding::OB_NO_ANSWER);
+ Metrics::RecordOnboardingResult(Metrics::OnBoarding::OB_SHOWN);
+ waiting_for_onboarding_ = false;
+ }
+ OnStartDone(/* start_regular_script = */ false);
+ if (trigger_script_coordinator_ && state) {
+ trigger_script_coordinator_->Stop(*state);
+ }
+ trigger_script_coordinator_.reset();
+ pending_trigger_context_.reset();
}
void Starter::MaybeInstallFeatureModule(StartupMode startup_mode) {
@@ -132,10 +500,15 @@ void Starter::MaybeInstallFeatureModule(StartupMode startup_mode) {
void Starter::OnFeatureModuleInstalled(
StartupMode startup_mode,
Metrics::FeatureModuleInstallation result) {
+ Metrics::RecordFeatureModuleInstallation(result);
if (result != Metrics::FeatureModuleInstallation::
DFM_FOREGROUND_INSTALLATION_SUCCEEDED &&
result != Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED) {
- RunCallback(/* start_regular_script = */ false);
+ Metrics::RecordDropOut(
+ Metrics::DropOutReason::DFM_INSTALL_FAILED,
+ pending_trigger_context_->GetScriptParameters().GetIntent().value_or(
+ std::string()));
+ OnStartDone(/* start_regular_script = */ false);
return;
}
@@ -149,55 +522,154 @@ void Starter::OnFeatureModuleInstalled(
return;
default:
DCHECK(false);
- RunCallback(/* start_regular_script = */ false);
+ OnStartDone(/* start_regular_script = */ false);
return;
}
}
void Starter::StartTriggerScript() {
- // TODO(arbesser): implement this.
- OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SUCCEEDED,
- base::nullopt);
+ const auto& script_parameters =
+ pending_trigger_context_->GetScriptParameters();
+ base::FieldTrialList::CreateFieldTrial(
+ kTriggerScriptExperimentSyntheticFieldTrialName,
+ script_parameters.GetTriggerScriptExperiment()
+ ? kTriggerScriptExperimentGroup
+ : kTriggerScriptControlGroup);
+
+ std::unique_ptr<ServiceRequestSender> service_request_sender =
+ platform_delegate_->GetTriggerScriptRequestSenderToInject();
+ if (!service_request_sender) {
+ if (script_parameters.GetBase64TriggerScriptsResponseProto().has_value()) {
+ service_request_sender = CreateBase64TriggerScriptRequestSender(
+ script_parameters.GetBase64TriggerScriptsResponseProto().value());
+ if (!service_request_sender) {
+ Metrics::RecordTriggerScriptFinished(
+ ukm_recorder_, current_ukm_source_id_,
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
+ Metrics::TriggerScriptFinishedState::BASE64_DECODING_ERROR);
+ OnTriggerScriptFinished(
+ Metrics::TriggerScriptFinishedState::BASE64_DECODING_ERROR,
+ std::move(pending_trigger_context_), absl::nullopt);
+ return;
+ }
+ } else if (script_parameters.GetRequestsTriggerScript().value_or(false)) {
+ service_request_sender = CreateRpcTriggerScriptRequestSender(
+ web_contents()->GetBrowserContext(), platform_delegate_);
+ } else {
+ // Should never happen.
+ DCHECK(false);
+ OnStartDone(/* start_regular_script = */ false);
+ return;
+ }
+ }
+ DCHECK(service_request_sender);
+
+ ServerUrlFetcher url_fetcher{ServerUrlFetcher::GetDefaultServerUrl()};
+ GURL startup_url = StartupUtil()
+ .ChooseStartupUrlForIntent(*pending_trigger_context_)
+ .value();
+ trigger_script_coordinator_ = std::make_unique<TriggerScriptCoordinator>(
+ platform_delegate_, web_contents(),
+ WebController::CreateForWebContents(web_contents()),
+ std::move(service_request_sender),
+ url_fetcher.GetTriggerScriptsEndpoint(),
+ std::make_unique<StaticTriggerConditions>(
+ platform_delegate_, pending_trigger_context_.get(), startup_url),
+ std::make_unique<DynamicTriggerConditions>(), ukm_recorder_,
+ current_ukm_source_id_);
+
+ // Note: for the duration of the trigger script, the trigger script
+ // coordinator will take ownership of the pending trigger context.
+ trigger_script_coordinator_->Start(
+ startup_url, std::move(pending_trigger_context_),
+ base::BindOnce(&Starter::OnTriggerScriptFinished,
+ weak_ptr_factory_.GetWeakPtr()));
}
void Starter::OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState state,
- base::Optional<TriggerScriptProto> trigger_script) {
- if (state != Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SUCCEEDED) {
- RunCallback(/* start_regular_script = */ false);
+ Metrics::TriggerScriptFinishedState state,
+ std::unique_ptr<TriggerContext> trigger_context,
+ absl::optional<TriggerScriptProto> trigger_script) {
+ // Update caches on error or user-cancel.
+ if (trigger_script_coordinator_) {
+ std::string domain = url_utils::GetOrganizationIdentifyingDomain(
+ trigger_script_coordinator_->GetDeeplink());
+ switch (state) {
+ case Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE:
+ case Metrics::TriggerScriptFinishedState::GET_ACTIONS_FAILED:
+ cached_failed_trigger_script_fetches_->Put(domain,
+ tick_clock_->NowTicks());
+ ClearStaleCacheEntries(
+ cached_failed_trigger_script_fetches_,
+ tick_clock_->NowTicks() - kMaxFailedTriggerScriptsCacheDuration);
+ break;
+ case Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_SESSION:
+ user_denylisted_domains_.Put(domain, tick_clock_->NowTicks());
+ ClearStaleCacheEntries(
+ &user_denylisted_domains_,
+ tick_clock_->NowTicks() - kMaxUserDenylistedCacheDuration);
+ break;
+ default: {
+ auto cache_it = cached_failed_trigger_script_fetches_->Peek(domain);
+ if (cache_it != cached_failed_trigger_script_fetches_->end()) {
+ cached_failed_trigger_script_fetches_->Erase(cache_it);
+ }
+ break;
+ }
+ }
+ }
+
+ // Delete the coordinator asynchronously, to give this notification time to
+ // end gracefully.
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&Starter::DeleteTriggerScriptCoordinator,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ if (state != Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED) {
+ OnStartDone(/* start_regular_script = */ false);
return;
}
+ // Take back ownership of the trigger context.
+ pending_trigger_context_ = std::move(trigger_context);
+
// Note: most trigger scripts show the onboarding on their own and log a
// different metric for the result. We need to be careful to only run the
// regular onboarding if necessary to avoid logging metrics more than once.
if (platform_delegate_->GetOnboardingAccepted()) {
- RunCallback(/* start_regular_script = */ true);
+ OnStartDone(/* start_regular_script = */ true, trigger_script);
return;
} else {
- MaybeShowOnboarding();
+ MaybeShowOnboarding(trigger_script);
}
}
-void Starter::MaybeShowOnboarding() {
+void Starter::MaybeShowOnboarding(
+ absl::optional<TriggerScriptProto> trigger_script) {
if (platform_delegate_->GetOnboardingAccepted()) {
- OnOnboardingFinished(/* shown = */ false, OnboardingResult::ACCEPTED);
+ OnOnboardingFinished(trigger_script, /* shown = */ false,
+ OnboardingResult::ACCEPTED);
return;
}
// Always use bottom sheet onboarding here. Trigger scripts may show a dialog
// onboarding, but if we have reached this part, we're already starting the
// regular script, where we don't offer dialog onboarding.
+ runtime_manager_->SetUIState(UIState::kShown);
+ waiting_for_onboarding_ = true;
platform_delegate_->ShowOnboarding(
- /* use_dialog_onboarding = */ false, *pending_trigger_context_,
+ /* use_dialog_onboarding = */ false, *GetPendingTriggerContext(),
base::BindOnce(&Starter::OnOnboardingFinished,
- weak_ptr_factory_.GetWeakPtr()));
+ weak_ptr_factory_.GetWeakPtr(), trigger_script));
}
-void Starter::OnOnboardingFinished(bool shown, OnboardingResult result) {
+void Starter::OnOnboardingFinished(
+ absl::optional<TriggerScriptProto> trigger_script,
+ bool shown,
+ OnboardingResult result) {
+ waiting_for_onboarding_ = false;
auto intent =
- pending_trigger_context_->GetScriptParameters().GetIntent().value_or(
+ GetPendingTriggerContext()->GetScriptParameters().GetIntent().value_or(
std::string());
switch (result) {
case OnboardingResult::DISMISSED:
@@ -222,31 +694,38 @@ void Starter::OnOnboardingFinished(bool shown, OnboardingResult result) {
: Metrics::OnBoarding::OB_NOT_SHOWN);
if (result != OnboardingResult::ACCEPTED) {
- RunCallback(/* start_regular_script = */ false);
+ runtime_manager_->SetUIState(UIState::kNotShown);
+ OnStartDone(/* start_regular_script = */ false);
return;
}
// Onboarding is the last step before regular startup.
platform_delegate_->SetOnboardingAccepted(true);
pending_trigger_context_->SetOnboardingShown(shown);
- RunCallback(/* start_regular_script = */ true);
+ OnStartDone(/* start_regular_script = */ true, trigger_script);
}
-void Starter::RunCallback(bool start_regular_script) {
- DCHECK(pending_callback_);
+void Starter::OnStartDone(bool start_regular_script,
+ absl::optional<TriggerScriptProto> trigger_script) {
if (!start_regular_script) {
- pending_trigger_context_ = nullptr;
- std::move(pending_callback_)
- .Run(/* start_regular_script = */ false, GURL(), nullptr);
+ // Catch-all to ensure that after a failed startup attempt we reset the
+ // UI state.
+ runtime_manager_->SetUIState(platform_delegate_->IsRegularScriptVisible()
+ ? UIState::kShown
+ : UIState::kNotShown);
+ pending_trigger_context_.reset();
return;
}
auto startup_url =
StartupUtil().ChooseStartupUrlForIntent(*pending_trigger_context_);
DCHECK(startup_url.has_value());
- std::move(pending_callback_)
- .Run(/* start_regular_script = */ true, *startup_url,
- std::move(pending_trigger_context_));
+ platform_delegate_->StartRegularScript(
+ *startup_url, std::move(pending_trigger_context_), trigger_script);
+}
+
+void Starter::DeleteTriggerScriptCoordinator() {
+ trigger_script_coordinator_.reset();
}
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/starter.h b/chromium/components/autofill_assistant/browser/starter.h
index d8699dc52fc..86928739026 100644
--- a/chromium/components/autofill_assistant/browser/starter.h
+++ b/chromium/components/autofill_assistant/browser/starter.h
@@ -7,14 +7,22 @@
#include <memory>
-#include "base/callback_forward.h"
+#include "base/containers/mru_cache.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
#include "components/autofill_assistant/browser/controller.h"
#include "components/autofill_assistant/browser/metrics.h"
+#include "components/autofill_assistant/browser/public/runtime_manager_impl.h"
+#include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/starter_heuristic.h"
#include "components/autofill_assistant/browser/starter_platform_delegate.h"
#include "components/autofill_assistant/browser/startup_util.h"
+#include "components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h"
#include "content/public/browser/web_contents_observer.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -22,16 +30,11 @@ namespace autofill_assistant {
// access platform-dependent features.
class Starter : public content::WebContentsObserver {
public:
- // Note: |url| and |trigger_context| are only valid and not null if
- // |start_regular_script| is true.
- using StarterResultCallback =
- base::OnceCallback<void(bool start_regular_script,
- GURL url,
- std::unique_ptr<TriggerContext> trigger_context)>;
-
explicit Starter(content::WebContents* web_contents,
StarterPlatformDelegate* platform_delegate,
- ukm::UkmRecorder* ukm_recorder);
+ ukm::UkmRecorder* ukm_recorder,
+ base::WeakPtr<RuntimeManagerImpl> runtime_manager,
+ const base::TickClock* tick_clock);
~Starter() override;
Starter(const Starter&) = delete;
Starter& operator=(const Starter&) = delete;
@@ -42,27 +45,40 @@ class Starter : public content::WebContentsObserver {
// - Install feature module if necessary
// - Run and wait for trigger script to finish if necessary
// - Show onboarding if necessary
- // - Invoke |callback| with the result. On success, the caller should start
- // the regular script. TODO(mcarlen): client startup should also be in
- // handled here, rather than in the caller.
+ // - Request the platform_delegate to start the regular script.
+ // TODO(mcarlen): client startup should also be handled here, rather than in
+ // the platform_delegate.
//
// Only one call to |Start| can be processed at any time. If this method is
// called before the previous call has finished, the previous call is
// cancelled.
- void Start(std::unique_ptr<TriggerContext> trigger_context,
- StarterResultCallback callback);
+ void Start(std::unique_ptr<TriggerContext> trigger_context);
// content::WebContentsObserver:
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
+ // Invoked when the tab interactability has changed.
+ void OnTabInteractabilityChanged(bool is_interactable);
+
// Re-check settings. This may cancel ongoing startup requests if the required
// settings are no longer enabled.
void CheckSettings();
private:
- // Cancels the currently pending startup request, if any.
- void CancelPendingStartup();
+ friend class StarterTest;
+
+ // Starts a flow for |url| if possible. Will fail (do nothing) if the feature
+ // is disabled or if there is already a pending startup.
+ void MaybeStartImplicitlyForUrl(const GURL& url,
+ const ukm::SourceId source_id);
+
+ // Cancels the currently pending startup request, if any. If a trigger script
+ // is currently running, this will record |state| as the reason for stopping.
+ // This will also hide any currently shown UI (such as a trigger script or the
+ // onboarding).
+ void CancelPendingStartup(
+ absl::optional<Metrics::TriggerScriptFinishedState> state);
// Installs the feature module if necessary, otherwise directly invokes
// |OnFeatureModuleInstalled|.
@@ -80,25 +96,81 @@ class Starter : public content::WebContentsObserver {
// Stops the startup if the trigger script failed or was user-cancelled.
// Otherwise, proceeds with the start of the regular script.
void OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState state,
- base::Optional<TriggerScriptProto> trigger_script);
+ Metrics::TriggerScriptFinishedState state,
+ std::unique_ptr<TriggerContext> trigger_context,
+ absl::optional<TriggerScriptProto> trigger_script);
// Shows the onboarding if necessary, otherwise directly invokes
// |OnOnboardingFinished|.
- void MaybeShowOnboarding();
+ void MaybeShowOnboarding(
+ absl::optional<TriggerScriptProto> trigger_script = absl::nullopt);
// Starts the regular script if onboarding was accepted. Stops the startup
// process if onboarding was rejected.
- void OnOnboardingFinished(bool shown, OnboardingResult result);
-
- // Internal helper to invoke the pending callback.
- void RunCallback(bool start_regular_script);
-
- StarterPlatformDelegate* platform_delegate_;
+ void OnOnboardingFinished(absl::optional<TriggerScriptProto> trigger_script,
+ bool shown,
+ OnboardingResult result);
+
+ // Called at the end of each |Start| invocation.
+ void OnStartDone(
+ bool start_regular_script,
+ absl::optional<TriggerScriptProto> trigger_script = absl::nullopt);
+
+ // Called when the heuristic result for |url| is available.
+ void OnHeuristicMatch(const GURL& url,
+ const ukm::SourceId source_id,
+ absl::optional<std::string> intent);
+
+ // Returns whether there is a currently pending call to |Start| or not.
+ bool IsStartupPending() const;
+
+ // Deletes the trigger script coordinator.
+ void DeleteTriggerScriptCoordinator();
+
+ // Returns a pointer to the currently pending trigger context, or nullptr.
+ // Use this method instead of directly accessing |pending_trigger_context_| in
+ // cases where the context could be temporarily owned by
+ // |trigger_script_coordinator_|.
+ TriggerContext* GetPendingTriggerContext() const;
+
+ // The UKM source id to use for UKM metrics.
+ ukm::SourceId current_ukm_source_id_ = ukm::kInvalidSourceId;
+
+ // Pointer to the global cache of trigger script requests that failed (one
+ // entry per organization-identifying domain), along with the time of entry.
+ // This is used to limit network traffic incurred for in-chrome triggering
+ // only. This cache does not affect explicit startup requests.
+ //
+ // This cache is shared across all tabs. It is size-limited and entries only
+ // last for a limited amount of time before they go stale. Made available in
+ // the header for easier unit-testing.
+ base::HashingMRUCache<std::string, base::TimeTicks>*
+ cached_failed_trigger_script_fetches_;
+
+ // The list of organization-identifying domains that a user has temporarily
+ // opted out of for receiving implicit autofill-assistant prompts, along
+ // with the time of entry.
+ //
+ // This is a per-tab cache. This cache does not affect explicit startup
+ // requests. The cache is size-limited and entries only last for a limited
+ // amount of time before they go stale.
+ base::HashingMRUCache<std::string, base::TimeTicks> user_denylisted_domains_;
+
+ // Debug parameters for in-CCT and in-Tab trigger scenarios. This is populated
+ // from the command line and intended only for debugging and testing.
+ ImplicitTriggeringDebugParametersProto implicit_triggering_debug_parameters_;
+
+ bool waiting_for_onboarding_ = false;
+ bool waiting_for_deeplink_navigation_ = false;
+ bool is_custom_tab_ = false;
+ StarterPlatformDelegate* platform_delegate_ = nullptr;
ukm::UkmRecorder* ukm_recorder_ = nullptr;
+ base::WeakPtr<RuntimeManagerImpl> runtime_manager_;
bool fetch_trigger_scripts_on_navigation_ = false;
std::unique_ptr<TriggerContext> pending_trigger_context_;
- StarterResultCallback pending_callback_;
+ std::unique_ptr<TriggerScriptCoordinator> trigger_script_coordinator_;
+ const scoped_refptr<StarterHeuristic> starter_heuristic_;
+ const base::TickClock* tick_clock_;
base::WeakPtrFactory<Starter> weak_ptr_factory_{this};
};
diff --git a/chromium/components/autofill_assistant/browser/starter_heuristic.cc b/chromium/components/autofill_assistant/browser/starter_heuristic.cc
new file mode 100644
index 00000000000..639c298e641
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/starter_heuristic.cc
@@ -0,0 +1,150 @@
+// Copyright 2021 The Chromium Authors. 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/starter_heuristic.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/json/json_reader.h"
+#include "base/logging.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/values.h"
+#include "components/autofill_assistant/browser/features.h"
+#include "components/autofill_assistant/browser/intent_strings.h"
+#include "components/autofill_assistant/browser/url_utils.h"
+#include "components/url_matcher/url_matcher_constants.h"
+
+namespace autofill_assistant {
+
+// String parameter containing the JSON-encoded parameter dictionary.
+const char kJsonParameterDictKey[] = "json_parameters";
+
+constexpr base::FeatureParam<std::string> kFieldTrialParams{
+ &features::kAutofillAssistantUrlHeuristics, kJsonParameterDictKey, ""};
+
+// Array of strings, containing the list of globally denylisted domains.
+const char kDenylistedDomainsKey[] = "denylistedDomains";
+// Array of heuristics, each with its own intent and conditions.
+const char kHeuristicsKey[] = "heuristics";
+// String. The intent associated with a specific heuristic.
+const char kHeuristicIntentKey[] = "intent";
+// UrlFilter dictionary. The URL condition set defining a specific intent's
+// heuristic. See also components/url_matcher/url_matcher_factory.h
+const char kHeuristicUrlConditionSetKey[] = "conditionSet";
+
+StarterHeuristic::StarterHeuristic() {
+ InitFromTrialParams();
+}
+
+StarterHeuristic::~StarterHeuristic() = default;
+
+void StarterHeuristic::InitFromTrialParams() {
+ DCHECK(matcher_id_to_intent_map_.empty())
+ << "Called after already initialized";
+
+ std::string parameters = kFieldTrialParams.Get();
+ if (parameters.empty()) {
+ return;
+ }
+ absl::optional<base::Value> dict = base::JSONReader::Read(parameters);
+ if (!dict || !dict->is_dict()) {
+ VLOG(1) << "Failed to parse field trial params as JSON object: "
+ << parameters;
+ if (VLOG_IS_ON(1)) {
+ auto err = base::JSONReader::ReadAndReturnValueWithError(parameters);
+ VLOG(1) << err.error_message << ", line: " << err.error_line
+ << ", col: " << err.error_column;
+ }
+ return;
+ }
+
+ // Read mandatory list of heuristics.
+ auto* heuristics = dict->FindListKey(kHeuristicsKey);
+ if (heuristics == nullptr || !heuristics->is_list()) {
+ VLOG(1) << "Field trial params did not contain heuristics";
+ return;
+ }
+ url_matcher::URLMatcherConditionSet::Vector condition_sets;
+ base::flat_map<url_matcher::URLMatcherConditionSet::ID, std::string> mapping;
+ url_matcher::URLMatcherConditionSet::ID next_condition_set_id = 0;
+ for (const auto& heuristic : heuristics->GetList()) {
+ auto* intent =
+ heuristic.FindKeyOfType(kHeuristicIntentKey, base::Value::Type::STRING);
+ auto* url_conditions = heuristic.FindKeyOfType(
+ kHeuristicUrlConditionSetKey, base::Value::Type::DICTIONARY);
+ if (!intent || !url_conditions) {
+ VLOG(1) << "Heuristic did not contain intent or url_conditions";
+ return;
+ }
+
+ std::string error;
+ const auto& url_conditions_dict =
+ base::Value::AsDictionaryValue(*url_conditions);
+ condition_sets.emplace_back(
+ url_matcher::URLMatcherFactory::CreateFromURLFilterDictionary(
+ url_matcher_.condition_factory(), &url_conditions_dict,
+ next_condition_set_id, &error));
+ if (!error.empty()) {
+ VLOG(1) << "Error pasing url conditions: " << error;
+ return;
+ }
+ mapping[next_condition_set_id++] = *intent->GetIfString();
+ }
+
+ // Read optional list of denylisted domains.
+ auto* denylisted_domains_value = dict->FindListKey(kDenylistedDomainsKey);
+ base::flat_set<std::string> denylisted_domains;
+ if (denylisted_domains_value != nullptr) {
+ for (const auto& domain : denylisted_domains_value->GetList()) {
+ if (!domain.is_string()) {
+ VLOG(1) << "Invalid type for denylisted domain";
+ return;
+ }
+ denylisted_domains.insert(*domain.GetIfString());
+ }
+ }
+
+ denylisted_domains_ = std::move(denylisted_domains);
+ url_matcher_.AddConditionSets(condition_sets);
+ matcher_id_to_intent_map_ = std::move(mapping);
+}
+
+absl::optional<std::string> StarterHeuristic::IsHeuristicMatch(
+ const GURL& url) const {
+ if (matcher_id_to_intent_map_.empty() || !url.is_valid()) {
+ return absl::nullopt;
+ }
+
+ if (denylisted_domains_.count(
+ url_utils::GetOrganizationIdentifyingDomain(url)) > 0) {
+ return absl::nullopt;
+ }
+
+ std::set<url_matcher::URLMatcherConditionSet::ID> matches =
+ url_matcher_.MatchURL(url);
+ if (matches.empty()) {
+ return absl::nullopt;
+ }
+ // Return the first matching intent.
+ auto first_matching_it = matcher_id_to_intent_map_.find(*matches.begin());
+ if (first_matching_it == matcher_id_to_intent_map_.end()) {
+ DCHECK(false);
+ return absl::nullopt;
+ }
+ return first_matching_it->second;
+}
+
+void StarterHeuristic::RunHeuristicAsync(
+ const GURL& url,
+ base::OnceCallback<void(absl::optional<std::string> intent)> callback)
+ const {
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+ base::BindOnce(&StarterHeuristic::IsHeuristicMatch,
+ base::RetainedRef(this), url),
+ std::move(callback));
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/starter_heuristic.h b/chromium/components/autofill_assistant/browser/starter_heuristic.h
new file mode 100644
index 00000000000..a05259eda21
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/starter_heuristic.h
@@ -0,0 +1,75 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_STARTER_HEURISTIC_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_STARTER_HEURISTIC_H_
+
+#include <string>
+#include "base/callback_forward.h"
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
+#include "base/memory/ref_counted.h"
+#include "components/url_matcher/url_matcher.h"
+#include "components/url_matcher/url_matcher_factory.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/gurl.h"
+
+namespace autofill_assistant {
+
+// Utility that implements a heuristic for autofill-assistant URLs.
+//
+// This class inherits from RefCountedThreadSafe to allow safe evaluation on
+// worker threads.
+class StarterHeuristic : public base::RefCountedThreadSafe<StarterHeuristic> {
+ public:
+ StarterHeuristic();
+ StarterHeuristic(const StarterHeuristic&) = delete;
+ StarterHeuristic& operator=(const StarterHeuristic&) = delete;
+
+ // Runs the heuristic against |url| and invokes the callback with the matching
+ // intent or absl::nullopt if there is none. Since we currently do not
+ // support intent disambiguation in cases where more than one intent is
+ // matching for a given URL, this will return the intent of the first matching
+ // condition-set specified in the config.
+ //
+ // Note that this method runs on a worker thread, not on the caller's thread.
+ // The callback will be invoked on the caller's sequence.
+ void RunHeuristicAsync(
+ const GURL& url,
+ base::OnceCallback<void(absl::optional<std::string> intent)> callback)
+ const;
+
+ private:
+ friend class base::RefCountedThreadSafe<StarterHeuristic>;
+ friend class StarterHeuristicTest;
+ ~StarterHeuristic();
+
+ // Initializes the heuristic from the heuristic trial parameters. If there is
+ // no trial or parsing fails, the heuristic will be empty and as such always
+ // report absl::nullopt. However, if you want to disable implicit startup,
+ // you should disable the dedicated in-CCT and/or in-Tab triggering trials
+ // instead to prevent the heuristic from being called in the first place.
+ void InitFromTrialParams();
+
+ // Runs the heuristic against |url|. Returns the matching intent or
+ // absl::nullopt if there is none.
+ absl::optional<std::string> IsHeuristicMatch(const GURL& url) const;
+
+ // The set of denylisted domains that will always return false before
+ // considering any of the intent heuristics.
+ base::flat_set<std::string> denylisted_domains_;
+
+ // The URL matcher containing one URLMatcherConditionSet per supported intent.
+ url_matcher::URLMatcher url_matcher_;
+
+ // Arbitrary mapping of matcher IDs to intent strings. This mapping is built
+ // dynamically to allow the heuristic to work on intents that are otherwise
+ // unknown to the client.
+ base::flat_map<url_matcher::URLMatcherConditionSet::ID, std::string>
+ matcher_id_to_intent_map_;
+};
+
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_STARTER_HEURISTIC_H_
diff --git a/chromium/components/autofill_assistant/browser/starter_heuristic_unittest.cc b/chromium/components/autofill_assistant/browser/starter_heuristic_unittest.cc
new file mode 100644
index 00000000000..179247f32dd
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/starter_heuristic_unittest.cc
@@ -0,0 +1,254 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/starter_heuristic.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "components/autofill_assistant/browser/features.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+
+using ::testing::Eq;
+using ::testing::Optional;
+
+class StarterHeuristicTest : public testing::Test {
+ public:
+ StarterHeuristicTest() = default;
+ ~StarterHeuristicTest() override = default;
+
+ // Synchronous evaluation of the heuristic for easier testing.
+ absl::optional<std::string> IsHeuristicMatchForTest(
+ const StarterHeuristic& starter_heuristic,
+ const GURL& url) {
+ return starter_heuristic.IsHeuristicMatch(url);
+ }
+};
+
+TEST_F(StarterHeuristicTest, SmokeTest) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeatureWithParameters(
+ features::kAutofillAssistantUrlHeuristics, {{"json_parameters", R"(
+ {
+ "heuristics":[
+ {
+ "intent":"FAKE_INTENT_CART",
+ "conditionSet":{
+ "urlContains":"cart"
+ }
+ }
+ ]
+ }
+ )"}});
+
+ auto starter_heuristic = base::MakeRefCounted<StarterHeuristic>();
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com/cart")),
+ Eq("FAKE_INTENT_CART"));
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com")),
+ Eq(absl::nullopt));
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic, GURL("invalid/cart")),
+ Eq(absl::nullopt));
+}
+
+TEST_F(StarterHeuristicTest, RunHeuristicAsync) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeatureWithParameters(
+ features::kAutofillAssistantUrlHeuristics, {{"json_parameters",
+ R"(
+ {
+ "heuristics":[
+ {
+ "intent":"FAKE_INTENT_CART",
+ "conditionSet":{
+ "urlContains":"cart"
+ }
+ }
+ ]
+ }
+ )"}});
+
+ base::test::TaskEnvironment task_environment;
+ base::MockCallback<base::OnceCallback<void(absl::optional<std::string>)>>
+ callback;
+ EXPECT_CALL(callback, Run(Optional(std::string("FAKE_INTENT_CART"))));
+ auto starter_heuristic = base::MakeRefCounted<StarterHeuristic>();
+ starter_heuristic->RunHeuristicAsync(GURL("https://www.example.com/cart"),
+ callback.Get());
+ task_environment.RunUntilIdle();
+}
+
+TEST_F(StarterHeuristicTest, MultipleIntentHeuristics) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeatureWithParameters(
+ features::kAutofillAssistantUrlHeuristics, {{"json_parameters",
+ R"(
+ {
+ "heuristics":[
+ {
+ "intent":"FAKE_INTENT_CART",
+ "conditionSet":{
+ "urlContains":"cart"
+ }
+ },
+ {
+ "intent":"FAKE_INTENT_OTHER",
+ "conditionSet":{
+ "urlMatches":".*other.*"
+ }
+ }
+ ]
+ }
+ )"}});
+
+ auto starter_heuristic = base::MakeRefCounted<StarterHeuristic>();
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com/cart")),
+ Eq("FAKE_INTENT_CART"));
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com/other")),
+ Eq("FAKE_INTENT_OTHER"));
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com")),
+ Eq(absl::nullopt));
+ // If both match, FAKE_INTENT_CART has precedence because it was specified
+ // first.
+ EXPECT_THAT(
+ IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com/cart/other")),
+ Eq("FAKE_INTENT_CART"));
+}
+
+TEST_F(StarterHeuristicTest, DenylistedDomains) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeatureWithParameters(
+ features::kAutofillAssistantUrlHeuristics, {{"json_parameters",
+ R"(
+ {
+ "denylistedDomains": ["example.com", "other-example.com"],
+ "heuristics":[
+ {
+ "intent":"FAKE_INTENT_CART",
+ "conditionSet":{
+ "urlContains":"cart"
+ }
+ }
+ ]
+ }
+ )"}});
+
+ // URLs on denylisted domains or subdomains thereof will always fail the
+ // heuristic even if they would otherwise match.
+ auto starter_heuristic = base::MakeRefCounted<StarterHeuristic>();
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com/cart")),
+ Eq(absl::nullopt));
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://example.com/cart")),
+ Eq(absl::nullopt));
+ EXPECT_THAT(
+ IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://subdomain.example.com/cart")),
+ Eq(absl::nullopt));
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com")),
+ Eq(absl::nullopt));
+ EXPECT_THAT(
+ IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.other-example.com/cart")),
+ Eq(absl::nullopt));
+
+ // URLs on non-denylisted domains still work.
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://allowed.com/cart")),
+ Eq("FAKE_INTENT_CART"));
+}
+
+TEST_F(StarterHeuristicTest, MultipleConditionSetsForSameIntent) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeatureWithParameters(
+ features::kAutofillAssistantUrlHeuristics, {{"json_parameters",
+ R"(
+ {
+ "heuristics":[
+ {
+ "intent":"FAKE_INTENT_CART",
+ "conditionSet":{
+ "urlContains":"cart"
+ }
+ },
+ {
+ "intent":"FAKE_INTENT_CART",
+ "conditionSet":{
+ "urlContains":"shopping-bag"
+ }
+ }
+ ]
+ }
+ )"}});
+
+ auto starter_heuristic = base::MakeRefCounted<StarterHeuristic>();
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://example.com/cart")),
+ Eq("FAKE_INTENT_CART"));
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://example.com/shopping-bag")),
+ Eq("FAKE_INTENT_CART"));
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com")),
+ Eq(absl::nullopt));
+}
+
+TEST_F(StarterHeuristicTest, FieldTrialNotSet) {
+ // Just a check that this does not crash.
+ auto starter_heuristic = base::MakeRefCounted<StarterHeuristic>();
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com/cart")),
+ Eq(absl::nullopt));
+}
+
+TEST_F(StarterHeuristicTest, FieldTrialInvalid) {
+ // Just a check that this does not crash.
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeatureWithParameters(
+ features::kAutofillAssistantUrlHeuristics,
+ {{"json_parameters", "invalid"}});
+ auto starter_heuristic = base::MakeRefCounted<StarterHeuristic>();
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com/cart")),
+ Eq(absl::nullopt));
+}
+
+TEST_F(StarterHeuristicTest, PartiallyInvalidFieldTrialsAreCompletelyIgnored) {
+ // |denylistedDomains| expects an array of strings. If specified but invalid,
+ // the entire configuration should be ignored.
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeatureWithParameters(
+ features::kAutofillAssistantUrlHeuristics, {{"json_parameters",
+ R"(
+ {
+ "denylistedDomains": [-1],
+ "heuristics":[
+ {
+ "intent":"FAKE_INTENT_CART",
+ "conditionSet":{
+ "urlContains":"cart"
+ }
+ }
+ ]
+ }
+ )"}});
+ auto starter_heuristic = base::MakeRefCounted<StarterHeuristic>();
+ EXPECT_THAT(IsHeuristicMatchForTest(*starter_heuristic,
+ GURL("https://www.example.com/cart")),
+ Eq(absl::nullopt));
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/starter_platform_delegate.h b/chromium/components/autofill_assistant/browser/starter_platform_delegate.h
index d059c54600a..5ff934245af 100644
--- a/chromium/components/autofill_assistant/browser/starter_platform_delegate.h
+++ b/chromium/components/autofill_assistant/browser/starter_platform_delegate.h
@@ -8,7 +8,9 @@
#include "base/callback_forward.h"
#include "components/autofill_assistant/browser/metrics.h"
#include "components/autofill_assistant/browser/onboarding_result.h"
+#include "components/autofill_assistant/browser/service/service_request_sender.h"
#include "components/autofill_assistant/browser/trigger_context.h"
+#include "components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h"
#include "components/autofill_assistant/browser/website_login_manager.h"
#include "components/version_info/version_info.h"
@@ -21,6 +23,24 @@ class StarterPlatformDelegate {
StarterPlatformDelegate() = default;
virtual ~StarterPlatformDelegate() = default;
+ // Asks the platform delegate to return a UI delegate for trigger scripts.
+ virtual std::unique_ptr<TriggerScriptCoordinator::UiDelegate>
+ CreateTriggerScriptUiDelegate() = 0;
+ // Allows integration tests to provide their own mocked trigger script request
+ // senders. Returns null if the default request sender should be used.
+ virtual std::unique_ptr<ServiceRequestSender>
+ GetTriggerScriptRequestSenderToInject() = 0;
+
+ // Requests the platform delegate to start the regular script.
+ virtual void StartRegularScript(
+ GURL url,
+ std::unique_ptr<TriggerContext> trigger_context,
+ const absl::optional<TriggerScriptProto>& trigger_script) = 0;
+ // Returns whether a regular script is currently running.
+ virtual bool IsRegularScriptRunning() const;
+ // Returns whether a regular script is currently showing UI to the user.
+ virtual bool IsRegularScriptVisible() const;
+
// Access to the login manager.
virtual WebsiteLoginManager* GetWebsiteLoginManager() const = 0;
// Returns the channel for the installation (canary, dev, beta, stable).
@@ -63,6 +83,8 @@ class StarterPlatformDelegate {
// TODO(arbesser): Move this out of the platform delegate.
// Returns whether the MSBB seetting is enabled.
virtual bool GetMakeSearchesAndBrowsingBetterEnabled() const = 0;
+ // Returns whether this is a custom tab or not.
+ virtual bool GetIsCustomTab() const = 0;
};
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/starter_unittest.cc b/chromium/components/autofill_assistant/browser/starter_unittest.cc
index 0eaa77d393f..fca44cca17f 100644
--- a/chromium/components/autofill_assistant/browser/starter_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/starter_unittest.cc
@@ -7,71 +7,365 @@
#include <map>
#include <memory>
#include <string>
+#include "base/base64url.h"
+#include "base/containers/mru_cache.h"
+#include "base/strings/string_piece.h"
#include "base/test/gmock_callback_support.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
+#include "base/time/tick_clock.h"
#include "components/autofill_assistant/browser/fake_starter_platform_delegate.h"
#include "components/autofill_assistant/browser/features.h"
+#include "components/autofill_assistant/browser/mock_website_login_manager.h"
+#include "components/autofill_assistant/browser/public/mock_runtime_manager.h"
#include "components/autofill_assistant/browser/script_parameters.h"
+#include "components/autofill_assistant/browser/service/mock_service_request_sender.h"
+#include "components/autofill_assistant/browser/switches.h"
+#include "components/autofill_assistant/browser/test_util.h"
#include "components/autofill_assistant/browser/trigger_context.h"
+#include "components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.h"
+#include "components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h"
#include "components/ukm/content/source_url_recorder.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
+#include "net/http/http_status_code.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace autofill_assistant {
-namespace {
+using ::base::test::RunOnceCallback;
using ::testing::_;
+using ::testing::AllOf;
using ::testing::Eq;
+using ::testing::IsEmpty;
+using ::testing::NiceMock;
+using ::testing::Optional;
+using ::testing::Pair;
+using ::testing::Pointee;
+using ::testing::Property;
+using ::testing::UnorderedElementsAre;
using ::testing::WithArg;
+using ::testing::WithArgs;
-const char kExampleUrl[] = "https://www.example.com";
+const char kExampleDeeplink[] = "https://www.example.com";
class StarterTest : public content::RenderViewHostTestHarness {
public:
+ StarterTest()
+ : content::RenderViewHostTestHarness(
+ base::test::TaskEnvironment::MainThreadType::UI,
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+ ~StarterTest() override = default;
+
void SetUp() override {
RenderViewHostTestHarness::SetUp();
ukm::InitializeSourceUrlRecorderForWebContents(web_contents());
content::WebContentsTester::For(web_contents())
- ->NavigateAndCommit(GURL(kExampleUrl));
+ ->NavigateAndCommit(GURL(kExampleDeeplink));
+ PrepareTriggerScriptUiDelegate();
+ PrepareTriggerScriptRequestSender();
+ fake_platform_delegate_.website_login_manager_ =
+ &mock_website_login_manager_;
+ ON_CALL(mock_website_login_manager_, OnGetLoginsForUrl)
+ .WillByDefault(
+ RunOnceCallback<1>(std::vector<WebsiteLoginManager::Login>()));
+
+ // Must be initialized before |starter_| is instantiated to take effect.
+ enable_fake_heuristic_ = std::make_unique<base::test::ScopedFeatureList>();
+ enable_fake_heuristic_->InitAndEnableFeatureWithParameters(
+ features::kAutofillAssistantUrlHeuristics, {{"json_parameters",
+ R"(
+ {
+ "heuristics":[
+ {
+ "intent":"FAKE_INTENT_CART",
+ "conditionSet":{
+ "urlContains":"cart"
+ }
+ }
+ ]
+ }
+ )"}});
starter_ = std::make_unique<Starter>(
- web_contents(), &fake_platform_delegate_, &ukm_recorder_);
+ web_contents(), &fake_platform_delegate_, &ukm_recorder_,
+ mock_runtime_manager_.GetWeakPtr(),
+ task_environment()->GetMockTickClock());
+ }
+
+ void TearDown() override {
+ // We need to clear the static cache to avoid cross-talk between tests.
+ GetFailedTriggerFetchesCacheForTest()->Clear();
+
+ // Note: it is important to reset the starter explicitly here to ensure that
+ // destructors are called on the right thread, as required by devtools.
+ starter_.reset();
+ RenderViewHostTestHarness::TearDown();
+ }
+
+ base::HashingMRUCache<std::string, base::TimeTicks>*
+ GetFailedTriggerFetchesCacheForTest() {
+ return starter_->cached_failed_trigger_script_fetches_;
+ }
+
+ base::HashingMRUCache<std::string, base::TimeTicks>*
+ GetUserDenylistedCacheForTest() const {
+ return &starter_->user_denylisted_domains_;
}
protected:
- void AssertRecordedStartedState(Metrics::LiteScriptStarted state) {
- auto entries =
- ukm_recorder_.GetEntriesByName("AutofillAssistant.LiteScriptStarted");
- ASSERT_THAT(entries.size(), Eq(1u));
- ukm_recorder_.ExpectEntrySourceHasUrl(
- entries[0], web_contents()->GetLastCommittedURL());
- EXPECT_EQ(*ukm_recorder_.GetEntryMetric(entries[0], "LiteScriptStarted"),
- static_cast<int64_t>(state));
+ void SetupPlatformDelegateForFirstTimeUser() {
+ fake_platform_delegate_.feature_module_installed_ = false;
+ fake_platform_delegate_.is_first_time_user_ = true;
+ fake_platform_delegate_.onboarding_accepted_ = false;
+ fake_platform_delegate_.feature_module_installation_result_ = Metrics::
+ FeatureModuleInstallation::DFM_FOREGROUND_INSTALLATION_SUCCEEDED;
+ fake_platform_delegate_.show_onboarding_result_shown_ = true;
+ fake_platform_delegate_.show_onboarding_result_ =
+ OnboardingResult::ACCEPTED;
+ }
+
+ void SetupPlatformDelegateForReturningUser() {
+ fake_platform_delegate_.feature_module_installed_ = true;
+ fake_platform_delegate_.is_first_time_user_ = false;
+ fake_platform_delegate_.onboarding_accepted_ = true;
+ }
+
+ // Returns a base64-encoded trigger script response, as created by
+ // |CreateTriggerScriptResponseForTest|.
+ std::string CreateBase64TriggerScriptResponseForTest() {
+ std::string serialized_get_trigger_scripts_response =
+ CreateTriggerScriptResponseForTest();
+ std::string base64_get_trigger_scripts_response;
+ base::Base64UrlEncode(serialized_get_trigger_scripts_response,
+ base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &base64_get_trigger_scripts_response);
+ return base64_get_trigger_scripts_response;
+ }
+
+ // Returns a serialized GetTriggerScriptsResponseProto containing a single
+ // trigger script without any trigger conditions. As such, it will be shown
+ // immediately upon startup.
+ std::string CreateTriggerScriptResponseForTest(
+ TriggerScriptProto::TriggerUIType trigger_ui_type =
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE) {
+ GetTriggerScriptsResponseProto get_trigger_scripts_response;
+ get_trigger_scripts_response.add_trigger_scripts()->set_trigger_ui_type(
+ trigger_ui_type);
+ std::string serialized_get_trigger_scripts_response;
+ get_trigger_scripts_response.SerializeToString(
+ &serialized_get_trigger_scripts_response);
+ return serialized_get_trigger_scripts_response;
+ }
+
+ // Returns true if all |expected_impressions| were recorded, and there were no
+ // other impressions for the same metric. |expected_impressions| may contain
+ // duplicate values if multiple equivalent impressions are expected.
+ // Impressions can be specified in any order.
+ bool RecordedUkmMetric(
+ base::StringPiece entry_name,
+ base::StringPiece metric_name,
+ const std::vector<std::pair<GURL, int64_t>>& expected_impressions) {
+ auto entries = ukm_recorder_.GetEntriesByName(entry_name);
+ if (entries.size() != expected_impressions.size()) {
+ LOG(ERROR) << "Expected " << expected_impressions.size()
+ << " impressions, but got " << entries.size();
+ return false;
+ }
+
+ auto remaining_impressions = expected_impressions;
+ while (!remaining_impressions.empty()) {
+ auto it =
+ std::find_if(entries.begin(), entries.end(), [&](const auto& entry) {
+ const ukm::UkmSource* src =
+ ukm_recorder_.GetSourceForSourceId(entry->source_id);
+ CHECK(src != nullptr);
+ return *ukm_recorder_.GetEntryMetric(entry, metric_name) ==
+ remaining_impressions.begin()->second &&
+ src->url() == remaining_impressions.begin()->first;
+ });
+ if (it == entries.end()) {
+ LOG(ERROR) << "Impression not recorded: "
+ << remaining_impressions.begin()->first << ": "
+ << remaining_impressions.begin()->second;
+ return false;
+ }
+
+ remaining_impressions.erase(remaining_impressions.begin());
+ }
+ return true;
+ }
+
+ // Returns whether anything was recorded for |entry_name|.
+ bool RecordedUkmMetric(base::StringPiece entry_name) {
+ return !ukm_recorder_.GetEntriesByName(entry_name).empty();
+ }
+
+ bool UkmTriggerScriptStarted(
+ Metrics::TriggerScriptStarted state,
+ const GURL& source_url = GURL(kExampleDeeplink)) {
+ return RecordedUkmMetric("AutofillAssistant.LiteScriptStarted",
+ "LiteScriptStarted",
+ {{source_url, static_cast<int64_t>(state)}});
+ }
+
+ bool UkmTriggerScriptFinished(
+ Metrics::TriggerScriptFinishedState state,
+ const GURL& source_url = GURL(kExampleDeeplink)) {
+ return RecordedUkmMetric("AutofillAssistant.LiteScriptFinished",
+ "LiteScriptFinished",
+ {{source_url, static_cast<int64_t>(state)}});
}
+ bool UkmTriggerScriptOnboarding(
+ Metrics::TriggerScriptOnboarding result,
+ const GURL& source_url = GURL(kExampleDeeplink)) {
+ return RecordedUkmMetric("AutofillAssistant.LiteScriptOnboarding",
+ "LiteScriptOnboarding",
+ {{source_url, static_cast<int64_t>(result)}});
+ }
+
+ bool UkmInChromeTriggerAction(
+ const std::vector<std::pair<GURL, Metrics::InChromeTriggerAction>>&
+ expected_impressions) {
+ std::vector<std::pair<GURL, int64_t>> transformed_expected_impressions;
+ std::transform(expected_impressions.begin(), expected_impressions.end(),
+ std::back_inserter(transformed_expected_impressions),
+ [&](const auto& impression) {
+ return std::make_pair(
+ impression.first,
+ static_cast<int64_t>(impression.second));
+ });
+
+ return RecordedUkmMetric("AutofillAssistant.InChromeTriggering",
+ "InChromeTriggerAction",
+ transformed_expected_impressions);
+ }
+
+ bool UkmTriggerScriptStarted() {
+ return RecordedUkmMetric("AutofillAssistant.LiteScriptStarted");
+ }
+
+ bool UkmTriggerScriptFinished() {
+ return RecordedUkmMetric("AutofillAssistant.LiteScriptFinished");
+ }
+
+ bool UkmTriggerScriptOnboarding() {
+ return RecordedUkmMetric("AutofillAssistant.LiteScriptOnboarding");
+ }
+
+ bool UkmInChromeTriggerAction() {
+ return RecordedUkmMetric("AutofillAssistant.InChromeTriggering");
+ }
+
+ // Simulates a navigation from the last committed URL to urls[size-1] along
+ // the intermediate redirect-hops in |urls|.
+ void SimulateRedirectToUrl(const std::vector<GURL>& urls) {
+ std::unique_ptr<content::NavigationSimulator> simulator =
+ content::NavigationSimulator::CreateRendererInitiated(
+ web_contents()->GetLastCommittedURL(),
+ web_contents()->GetMainFrame());
+ simulator->Start();
+ for (const auto& url : urls) {
+ simulator->Redirect(url);
+ }
+ simulator->Commit();
+ }
+
+ // Each request sender is only good for one trigger script. This call will
+ // create a new mock and prepare it to be used in the next call.
+ void PrepareTriggerScriptRequestSender() {
+ auto mock_trigger_script_service_request_sender =
+ std::make_unique<NiceMock<MockServiceRequestSender>>();
+ mock_trigger_script_service_request_sender_ =
+ mock_trigger_script_service_request_sender.get();
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ =
+ std::move(mock_trigger_script_service_request_sender);
+ }
+
+ // Each trigger script UI delegate is only good for one trigger script and
+ // must be prepared anew if a test needs to show more than one trigger script.
+ void PrepareTriggerScriptUiDelegate() {
+ auto mock_trigger_script_ui_delegate =
+ std::make_unique<NiceMock<MockTriggerScriptUiDelegate>>();
+ mock_trigger_script_ui_delegate_ = mock_trigger_script_ui_delegate.get();
+ fake_platform_delegate_.trigger_script_ui_delegate_ =
+ std::move(mock_trigger_script_ui_delegate);
+ fake_platform_delegate_.start_regular_script_callback_ =
+ mock_start_regular_script_callback_.Get();
+
+ ON_CALL(*mock_trigger_script_ui_delegate_, Attach)
+ .WillByDefault(WithArg<0>(
+ [&](TriggerScriptCoordinator* trigger_script_coordinator) {
+ trigger_script_coordinator_ = trigger_script_coordinator;
+ }));
+ ON_CALL(*mock_trigger_script_ui_delegate_, Detach).WillByDefault([&]() {
+ trigger_script_coordinator_ = nullptr;
+ });
+ }
+
+ NiceMock<MockTriggerScriptUiDelegate>* mock_trigger_script_ui_delegate_ =
+ nullptr;
+ NiceMock<MockServiceRequestSender>*
+ mock_trigger_script_service_request_sender_ = nullptr;
+ NiceMock<MockWebsiteLoginManager> mock_website_login_manager_;
+ // Only set while a trigger script is running.
+ TriggerScriptCoordinator* trigger_script_coordinator_ = nullptr;
FakeStarterPlatformDelegate fake_platform_delegate_;
ukm::TestAutoSetUkmRecorder ukm_recorder_;
+ MockRuntimeManager mock_runtime_manager_;
std::unique_ptr<Starter> starter_;
- base::MockCallback<Starter::StarterResultCallback> mock_callback_;
+ base::HistogramTester histogram_tester_;
+ base::MockCallback<base::OnceCallback<void(
+ GURL url,
+ std::unique_ptr<TriggerContext> trigger_context,
+ const absl::optional<TriggerScriptProto>& trigger_script)>>
+ mock_start_regular_script_callback_;
+ std::unique_ptr<base::test::ScopedFeatureList> enable_fake_heuristic_;
};
-TEST_F(StarterTest, FailWithoutInitialUrl) {
+TEST_F(StarterTest, RegularScriptFailsWithoutInitialUrl) {
+ std::map<std::string, std::string> params = {{"ENABLED", "true"},
+ {"START_IMMEDIATELY", "true"}};
+ TriggerContext::Options options;
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(params), options));
+
+ EXPECT_FALSE(UkmTriggerScriptStarted());
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectTotalCount(
+ "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, TriggerScriptFailsWithoutInitialUrl) {
std::map<std::string, std::string> params = {
{"ENABLED", "true"},
{"START_IMMEDIATELY", "false"},
{"TRIGGER_SCRIPTS_BASE64", "abc"}};
TriggerContext::Options options;
- EXPECT_CALL(mock_callback_, Run(/* start_regular_script = */ false, _, _));
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
starter_->Start(std::make_unique<TriggerContext>(
- std::make_unique<ScriptParameters>(params), options),
- mock_callback_.Get());
- AssertRecordedStartedState(
- Metrics::LiteScriptStarted::LITE_SCRIPT_NO_INITIAL_URL);
+ std::make_unique<ScriptParameters>(params), options));
+
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::NO_INITIAL_URL));
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectTotalCount(
+ "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
}
TEST_F(StarterTest, FailWithoutMandatoryScriptParameter) {
@@ -79,13 +373,20 @@ TEST_F(StarterTest, FailWithoutMandatoryScriptParameter) {
std::map<std::string, std::string> params = {
{"START_IMMEDIATELY", "false"}, {"TRIGGER_SCRIPTS_BASE64", "abc"}};
TriggerContext::Options options;
- options.initial_url = "https://www.example.com";
- EXPECT_CALL(mock_callback_, Run(/* start_regular_script = */ false, _, _));
+ options.initial_url = kExampleDeeplink;
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
starter_->Start(std::make_unique<TriggerContext>(
- std::make_unique<ScriptParameters>(params), options),
- mock_callback_.Get());
- AssertRecordedStartedState(
- Metrics::LiteScriptStarted::LITE_SCRIPT_MANDATORY_PARAMETER_MISSING);
+ std::make_unique<ScriptParameters>(params), options));
+
+ EXPECT_TRUE(UkmTriggerScriptStarted(
+ Metrics::TriggerScriptStarted::MANDATORY_PARAMETER_MISSING));
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectTotalCount(
+ "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
}
TEST_F(StarterTest, FailWhenFeatureDisabled) {
@@ -94,110 +395,1586 @@ TEST_F(StarterTest, FailWhenFeatureDisabled) {
{"START_IMMEDIATELY", "false"},
{"TRIGGER_SCRIPTS_BASE64", "abc"}};
TriggerContext::Options options;
- options.initial_url = "https://www.example.com";
+ options.initial_url = kExampleDeeplink;
auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
scoped_feature_list->InitAndDisableFeature(
features::kAutofillAssistantProactiveHelp);
- EXPECT_CALL(mock_callback_, Run(/* start_regular_script = */ false, _, _));
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
starter_->Start(std::make_unique<TriggerContext>(
- std::make_unique<ScriptParameters>(params), options),
- mock_callback_.Get());
- AssertRecordedStartedState(
- Metrics::LiteScriptStarted::LITE_SCRIPT_FEATURE_DISABLED);
+ std::make_unique<ScriptParameters>(params), options));
+
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::FEATURE_DISABLED));
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectTotalCount(
+ "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
}
TEST_F(StarterTest, RegularStartupForReturningUsersSucceeds) {
- fake_platform_delegate_.feature_module_installed_ = true;
- fake_platform_delegate_.is_first_time_user_ = false;
- fake_platform_delegate_.onboarding_accepted_ = true;
+ SetupPlatformDelegateForReturningUser();
std::map<std::string, std::string> script_parameters = {
{"ENABLED", "true"},
{"START_IMMEDIATELY", "true"},
- {"ORIGINAL_DEEPLINK", "https://www.example.com"}};
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
TriggerContext::Options options;
options.initial_url = "https://redirect.com/to/www/example/com";
- EXPECT_CALL(mock_callback_, Run(/* start_regular_script = */ true,
- GURL("https://www.example.com"), _))
- .WillOnce(WithArg<2>([](std::unique_ptr<TriggerContext> trigger_context) {
+ EXPECT_CALL(mock_start_regular_script_callback_,
+ Run(GURL(kExampleDeeplink), _, _))
+ .WillOnce(WithArg<1>([](std::unique_ptr<TriggerContext> trigger_context) {
EXPECT_THAT(trigger_context->GetOnboardingShown(), Eq(false));
}));
- starter_->Start(
- std::make_unique<TriggerContext>(
- std::make_unique<ScriptParameters>(script_parameters), options),
- mock_callback_.Get());
- EXPECT_THAT(fake_platform_delegate_.num_install_feature_module_called, Eq(0));
- EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called, Eq(0));
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters), options));
+
+ EXPECT_THAT(fake_platform_delegate_.num_install_feature_module_called_,
+ Eq(0));
+ EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(0));
EXPECT_THAT(fake_platform_delegate_.GetOnboardingAccepted(), Eq(true));
+ EXPECT_FALSE(UkmTriggerScriptStarted());
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_ACCEPTED, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_NOT_SHOWN, 1u);
}
TEST_F(StarterTest, RegularStartupForFirstTimeUsersSucceeds) {
- fake_platform_delegate_.feature_module_installed_ = false;
- fake_platform_delegate_.is_first_time_user_ = true;
- fake_platform_delegate_.onboarding_accepted_ = false;
- fake_platform_delegate_.feature_module_installation_result_ =
- Metrics::FeatureModuleInstallation::DFM_FOREGROUND_INSTALLATION_SUCCEEDED;
- fake_platform_delegate_.show_onboarding_result_shown = true;
- fake_platform_delegate_.show_onboarding_result = OnboardingResult::ACCEPTED;
+ SetupPlatformDelegateForFirstTimeUser();
std::map<std::string, std::string> script_parameters = {
{"ENABLED", "true"},
{"START_IMMEDIATELY", "true"},
- {"ORIGINAL_DEEPLINK", "https://www.example.com"}};
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
TriggerContext::Options options;
options.initial_url = "https://redirect.com/to/www/example/com";
- EXPECT_CALL(mock_callback_, Run(/* start_regular_script = */ true,
- GURL("https://www.example.com"), _))
- .WillOnce(WithArg<2>([](std::unique_ptr<TriggerContext> trigger_context) {
+ EXPECT_CALL(mock_start_regular_script_callback_,
+ Run(GURL(kExampleDeeplink), _, _))
+ .WillOnce(WithArg<1>([](std::unique_ptr<TriggerContext> trigger_context) {
EXPECT_THAT(trigger_context->GetOnboardingShown(), Eq(true));
}));
- starter_->Start(
- std::make_unique<TriggerContext>(
- std::make_unique<ScriptParameters>(script_parameters), options),
- mock_callback_.Get());
- EXPECT_THAT(fake_platform_delegate_.num_install_feature_module_called, Eq(1));
- EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called, Eq(1));
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters), options));
+
+ EXPECT_THAT(fake_platform_delegate_.num_install_feature_module_called_,
+ Eq(1));
+ EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(1));
EXPECT_THAT(fake_platform_delegate_.GetOnboardingAccepted(), Eq(true));
+ EXPECT_FALSE(UkmTriggerScriptStarted());
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_FOREGROUND_INSTALLATION_SUCCEEDED,
+ 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_ACCEPTED, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_SHOWN, 1u);
+}
+
+TEST_F(StarterTest, ForceOnboardingFlagForReturningUsersSucceeds) {
+ SetupPlatformDelegateForReturningUser();
+ base::MockCallback<base::OnceCallback<void(
+ base::OnceCallback<void(bool, OnboardingResult)>)>>
+ mock_onboarding_callback;
+ fake_platform_delegate_.on_show_onboarding_callback_ =
+ mock_onboarding_callback.Get();
+
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kAutofillAssistantForceOnboarding, "true");
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "true"},
+ {"ORIGINAL_DEEPLINK", "https://www.example.com"}};
+ EXPECT_CALL(mock_onboarding_callback, Run);
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options()));
+}
+
+TEST_F(StarterTest, ForceFirstTimeUserExperienceForReturningUser) {
+ GetTriggerScriptsResponseProto get_trigger_scripts_response;
+ auto* first_time_user_script =
+ get_trigger_scripts_response.add_trigger_scripts();
+ first_time_user_script->mutable_user_interface()->set_status_message(
+ "First time user");
+ first_time_user_script->mutable_trigger_condition()
+ ->mutable_is_first_time_user();
+ auto* returning_user_script =
+ get_trigger_scripts_response.add_trigger_scripts();
+ returning_user_script->mutable_user_interface()->set_status_message(
+ "Returning user");
+ returning_user_script->mutable_trigger_condition()
+ ->mutable_none_of()
+ ->add_conditions()
+ ->mutable_is_first_time_user();
+ std::string serialized_get_trigger_scripts_response;
+ get_trigger_scripts_response.SerializeToString(
+ &serialized_get_trigger_scripts_response);
+ std::string base64_get_trigger_scripts_response;
+ base::Base64UrlEncode(serialized_get_trigger_scripts_response,
+ base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &base64_get_trigger_scripts_response);
+
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ = nullptr;
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kAutofillAssistantForceFirstTimeUser, "true");
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"TRIGGER_SCRIPTS_BASE64", base64_get_trigger_scripts_response},
+ {"ORIGINAL_DEEPLINK", "https://www.example.com"}};
+
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_,
+ ShowTriggerScript(first_time_user_script->user_interface()));
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options()));
}
TEST_F(StarterTest, RegularStartupFailsIfDfmInstallationFails) {
- fake_platform_delegate_.feature_module_installed_ = false;
- fake_platform_delegate_.onboarding_accepted_ = false;
+ SetupPlatformDelegateForFirstTimeUser();
fake_platform_delegate_.feature_module_installation_result_ =
Metrics::FeatureModuleInstallation::DFM_FOREGROUND_INSTALLATION_FAILED;
std::map<std::string, std::string> script_parameters = {
{"ENABLED", "true"},
{"START_IMMEDIATELY", "true"},
- {"ORIGINAL_DEEPLINK", "https://www.example.com"}};
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
TriggerContext::Options options;
options.initial_url = "https://redirect.com/to/www/example/com";
- EXPECT_CALL(mock_callback_, Run(/* start_regular_script = */ false, _, _));
- starter_->Start(
- std::make_unique<TriggerContext>(
- std::make_unique<ScriptParameters>(script_parameters), options),
- mock_callback_.Get());
- EXPECT_THAT(fake_platform_delegate_.num_install_feature_module_called, Eq(1));
- EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called, Eq(0));
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters), options));
+
+ EXPECT_THAT(fake_platform_delegate_.num_install_feature_module_called_,
+ Eq(1));
+ EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(0));
EXPECT_THAT(fake_platform_delegate_.GetOnboardingAccepted(), Eq(false));
+ EXPECT_FALSE(UkmTriggerScriptStarted());
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_FOREGROUND_INSTALLATION_FAILED,
+ 1u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
}
TEST_F(StarterTest, RegularStartupFailsIfOnboardingRejected) {
+ SetupPlatformDelegateForFirstTimeUser();
fake_platform_delegate_.feature_module_installed_ = true;
- fake_platform_delegate_.is_first_time_user_ = false;
- fake_platform_delegate_.onboarding_accepted_ = false;
- fake_platform_delegate_.show_onboarding_result_shown = true;
- fake_platform_delegate_.show_onboarding_result = OnboardingResult::REJECTED;
+ fake_platform_delegate_.show_onboarding_result_ = OnboardingResult::REJECTED;
std::map<std::string, std::string> script_parameters = {
{"ENABLED", "true"},
{"START_IMMEDIATELY", "true"},
- {"ORIGINAL_DEEPLINK", "https://www.example.com"}};
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink},
+ {"INTENT", "SHOPPING_ASSISTED_CHECKOUT"}};
TriggerContext::Options options;
options.initial_url = "https://redirect.com/to/www/example/com";
- EXPECT_CALL(mock_callback_, Run(/* start_regular_script = */ false, _, _));
- starter_->Start(
- std::make_unique<TriggerContext>(
- std::make_unique<ScriptParameters>(script_parameters), options),
- mock_callback_.Get());
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters), options));
+
EXPECT_THAT(fake_platform_delegate_.GetOnboardingAccepted(), Eq(false));
+ EXPECT_FALSE(UkmTriggerScriptStarted());
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_CANCELLED, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_SHOWN, 1u);
+}
+
+TEST_F(StarterTest, RpcTriggerScriptFailsIfMsbbIsDisabled) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.msbb_enabled_ = false;
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"REQUEST_TRIGGER_SCRIPT", "true"},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, Attach).Times(0);
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options()));
+
+ EXPECT_TRUE(UkmTriggerScriptStarted(
+ Metrics::TriggerScriptStarted::PROACTIVE_TRIGGERING_DISABLED));
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectTotalCount(
+ "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, RpcTriggerScriptFailsIfProactiveHelpIsDisabled) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.proactive_help_enabled_ = false;
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"REQUEST_TRIGGER_SCRIPT", "true"},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, Attach).Times(0);
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options()));
+
+ EXPECT_TRUE(UkmTriggerScriptStarted(
+ Metrics::TriggerScriptStarted::PROACTIVE_TRIGGERING_DISABLED));
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectTotalCount(
+ "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, RpcTriggerScriptSucceeds) {
+ SetupPlatformDelegateForFirstTimeUser();
+ fake_platform_delegate_.feature_module_installed_ = true;
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"REQUEST_TRIGGER_SCRIPT", "true"},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ TriggerContext::Options options;
+ options.initial_url = "https://redirect.com/to/www/example/com";
+ options.onboarding_shown = false;
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript)
+ .WillOnce([&]() {
+ ASSERT_TRUE(trigger_script_coordinator_ != nullptr);
+ trigger_script_coordinator_->PerformTriggerScriptAction(
+ TriggerScriptProto::ACCEPT);
+ });
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_,
+ OnSendRequest(
+ GURL("https://automate-pa.googleapis.com/v1/triggers"), _, _))
+ .WillOnce(
+ WithArgs<1, 2>([&](const std::string& request_body,
+ ServiceRequestSender::ResponseCallback& callback) {
+ // Note that trigger scripts should be fetched for the
+ // ORIGINAL_DEEPLINK, not for the |initial_url|.
+ GetTriggerScriptsRequestProto request;
+ ASSERT_TRUE(request.ParseFromString(request_body));
+ EXPECT_THAT(request.url(), Eq(GURL(kExampleDeeplink)));
+ EXPECT_FALSE(request.client_context().is_in_chrome_triggered());
+ std::move(callback).Run(
+ net::HTTP_OK,
+ CreateTriggerScriptResponseForTest(
+ TriggerScriptProto::SHOPPING_CART_FIRST_TIME_USER));
+ }));
+ GetTriggerScriptsResponseProto get_trigger_scripts_response;
+ get_trigger_scripts_response.ParseFromString(
+ CreateTriggerScriptResponseForTest(
+ TriggerScriptProto::SHOPPING_CART_FIRST_TIME_USER));
+ EXPECT_CALL(
+ mock_start_regular_script_callback_,
+ Run(GURL(kExampleDeeplink),
+ Pointee(AllOf(
+ Property(&TriggerContext::GetOnboardingShown, true),
+ Property(&TriggerContext::GetInChromeTriggered, false),
+ Property(&TriggerContext::GetTriggerUIType,
+ TriggerScriptProto::SHOPPING_CART_FIRST_TIME_USER))),
+ Optional(get_trigger_scripts_response.trigger_scripts(0))));
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters), options));
+
+ EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(1));
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::FIRST_TIME_USER));
+ EXPECT_TRUE(UkmTriggerScriptFinished(
+ Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED));
+ EXPECT_TRUE(UkmTriggerScriptOnboarding(
+ Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED));
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, Base64TriggerScriptFailsForInvalidBase64) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ = nullptr;
+ mock_trigger_script_service_request_sender_ = nullptr;
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"TRIGGER_SCRIPTS_BASE64", "#invalid_hashtag"},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, Attach).Times(0);
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options()));
+
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::RETURNING_USER));
+ EXPECT_TRUE(UkmTriggerScriptFinished(
+ Metrics::TriggerScriptFinishedState::BASE64_DECODING_ERROR));
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, Base64TriggerScriptFailsIfProactiveHelpIsDisabled) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.proactive_help_enabled_ = false;
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ = nullptr;
+ mock_trigger_script_service_request_sender_ = nullptr;
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"TRIGGER_SCRIPTS_BASE64", CreateBase64TriggerScriptResponseForTest()},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, Attach).Times(0);
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options()));
+
+ EXPECT_TRUE(UkmTriggerScriptStarted(
+ Metrics::TriggerScriptStarted::PROACTIVE_TRIGGERING_DISABLED));
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectTotalCount(
+ "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, Base64TriggerScriptSucceeds) {
+ SetupPlatformDelegateForFirstTimeUser();
+ fake_platform_delegate_.feature_module_installed_ = true;
+ // Base64 trigger scripts should not require MSBB to be enabled.
+ fake_platform_delegate_.msbb_enabled_ = false;
+ // No need to inject a mock request sender for base64 trigger scripts, we can
+ // use the real one.
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ = nullptr;
+ mock_trigger_script_service_request_sender_ = nullptr;
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"TRIGGER_SCRIPTS_BASE64", CreateBase64TriggerScriptResponseForTest()},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ TriggerContext::Options options;
+ options.initial_url = "https://redirect.com/to/www/example/com";
+ options.onboarding_shown = false;
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript)
+ .WillOnce([&]() {
+ ASSERT_TRUE(trigger_script_coordinator_ != nullptr);
+ trigger_script_coordinator_->PerformTriggerScriptAction(
+ TriggerScriptProto::ACCEPT);
+ });
+ EXPECT_CALL(mock_start_regular_script_callback_,
+ Run(GURL(kExampleDeeplink),
+ Pointee(Property(&TriggerContext::GetOnboardingShown, true)),
+ testing::Ne(absl::nullopt)));
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters), options));
+
+ EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(1));
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::FIRST_TIME_USER));
+ EXPECT_TRUE(UkmTriggerScriptFinished(
+ Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED));
+ EXPECT_TRUE(UkmTriggerScriptOnboarding(
+ Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED));
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, CancelPendingTriggerScriptWhenTransitioningFromCctToTab) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.is_custom_tab_ = true;
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ = nullptr;
+ mock_trigger_script_service_request_sender_ = nullptr;
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"TRIGGER_SCRIPTS_BASE64", CreateBase64TriggerScriptResponseForTest()},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript);
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{}));
+
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, HideTriggerScript);
+ fake_platform_delegate_.is_custom_tab_ = false;
+ starter_->CheckSettings();
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::RETURNING_USER));
+ EXPECT_TRUE(UkmTriggerScriptFinished(
+ Metrics::TriggerScriptFinishedState::CCT_TO_TAB_NOT_SUPPORTED));
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+}
+
+TEST_F(StarterTest, CancelPendingTriggerScriptWhenHandlingNewStartupRequest) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ = nullptr;
+ mock_trigger_script_service_request_sender_ = nullptr;
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"TRIGGER_SCRIPTS_BASE64", CreateBase64TriggerScriptResponseForTest()},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript);
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{}));
+
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, HideTriggerScript);
+ PrepareTriggerScriptUiDelegate();
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{}));
+ EXPECT_TRUE(
+ UkmTriggerScriptFinished(Metrics::TriggerScriptFinishedState::CANCELED));
+}
+
+TEST_F(StarterTest, RegularStartupFailsIfNavigationDuringOnboarding) {
+ SetupPlatformDelegateForFirstTimeUser();
+ fake_platform_delegate_.feature_module_installed_ = true;
+ // Empty callback to keep the onboarding open indefinitely.
+ fake_platform_delegate_.on_show_onboarding_callback_ =
+ base::DoNothing::Once<base::OnceCallback<void(bool, OnboardingResult)>>();
+
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "true"},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{}));
+
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.different.com"));
+ EXPECT_FALSE(UkmTriggerScriptStarted());
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_NO_ANSWER, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_SHOWN, 1u);
+}
+
+TEST_F(StarterTest, TriggerScriptStartupFailsIfNavigationDuringOnboarding) {
+ SetupPlatformDelegateForFirstTimeUser();
+ fake_platform_delegate_.feature_module_installed_ = true;
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ = nullptr;
+ mock_trigger_script_service_request_sender_ = nullptr;
+ // Empty callback to keep the onboarding open indefinitely.
+ fake_platform_delegate_.on_show_onboarding_callback_ =
+ base::DoNothing::Once<base::OnceCallback<void(bool, OnboardingResult)>>();
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"TRIGGER_SCRIPTS_BASE64", CreateBase64TriggerScriptResponseForTest()},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript)
+ .WillOnce([&]() {
+ ASSERT_TRUE(trigger_script_coordinator_ != nullptr);
+ trigger_script_coordinator_->PerformTriggerScriptAction(
+ TriggerScriptProto::ACCEPT);
+ });
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{}));
+
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.different.com"));
+
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::FIRST_TIME_USER));
+ EXPECT_TRUE(UkmTriggerScriptFinished(
+ Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE));
+ EXPECT_TRUE(UkmTriggerScriptOnboarding(
+ Metrics::TriggerScriptOnboarding::
+ ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION));
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, RegularStartupAllowsCertainNavigationsDuringOnboarding) {
+ SetupPlatformDelegateForFirstTimeUser();
+ fake_platform_delegate_.feature_module_installed_ = true;
+ // Empty callback to keep the onboarding open indefinitely.
+ fake_platform_delegate_.on_show_onboarding_callback_ =
+ base::DoNothing::Once<base::OnceCallback<void(bool, OnboardingResult)>>();
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "true"},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{}));
+
+ // Expect that the onboarding is not interrupted by a navigation to a
+ // subdomain of the ORIGINAL_DEEPLINK, nor by redirects along the way.
+ SimulateRedirectToUrl(
+ {GURL("http://redirect.com/example"), GURL("https://login.example.com")});
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+
+ // Navigating to a different domain will cancel the onboarding.
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.different.com"));
+
+ EXPECT_FALSE(UkmTriggerScriptStarted());
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_NO_ANSWER, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_SHOWN, 1u);
+}
+
+TEST_F(StarterTest, RegularStartupIgnoresLastCommittedUrl) {
+ SetupPlatformDelegateForFirstTimeUser();
+ fake_platform_delegate_.feature_module_installed_ = true;
+ // Empty callback to keep the onboarding open indefinitely.
+ fake_platform_delegate_.on_show_onboarding_callback_ =
+ base::DoNothing::Once<base::OnceCallback<void(bool, OnboardingResult)>>();
+
+ // Note: the starter does not actually care about the last committed URL at
+ // the time of startup. All that matters is that it has received the startup
+ // intent, and that there is a valid ORIGINAL_DEEPLINK to expect.
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.ignored.com"));
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "true"},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{}));
+
+ EXPECT_FALSE(UkmTriggerScriptStarted());
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, ImplicitStartupOnSupportedDomain) {
+ SetupPlatformDelegateForReturningUser();
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_,
+ OnSendRequest(
+ GURL("https://automate-pa.googleapis.com/v1/triggers"), _, _))
+ .WillOnce(
+ WithArgs<1, 2>([&](const std::string& request_body,
+ ServiceRequestSender::ResponseCallback& callback) {
+ GetTriggerScriptsRequestProto request;
+ ASSERT_TRUE(request.ParseFromString(request_body));
+ EXPECT_THAT(request.url(),
+ Eq(GURL("https://www.some-website.com/cart")));
+ EXPECT_TRUE(request.client_context().is_in_chrome_triggered());
+ std::move(callback).Run(
+ net::HTTP_OK,
+ CreateTriggerScriptResponseForTest(
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER));
+ }));
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript)
+ .WillOnce([&]() {
+ ASSERT_TRUE(trigger_script_coordinator_ != nullptr);
+ trigger_script_coordinator_->PerformTriggerScriptAction(
+ TriggerScriptProto::ACCEPT);
+ });
+ EXPECT_CALL(
+ mock_start_regular_script_callback_,
+ Run(GURL("https://www.some-website.com/cart"),
+ Pointee(AllOf(
+ Property(&TriggerContext::GetOnboardingShown, false),
+ Property(&TriggerContext::GetInChromeTriggered, true),
+ Property(&TriggerContext::GetTriggerUIType,
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER))),
+ testing::Ne(absl::nullopt)));
+
+ // Implicit startup by navigating to an autofill-assistant-enabled site.
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::RETURNING_USER,
+ GURL("https://www.some-website.com/cart")));
+ EXPECT_TRUE(UkmTriggerScriptFinished(
+ Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED,
+ GURL("https://www.some-website.com/cart")));
+ EXPECT_TRUE(UkmTriggerScriptOnboarding(
+ Metrics::TriggerScriptOnboarding::ONBOARDING_ALREADY_ACCEPTED,
+ GURL("https://www.some-website.com/cart")));
+ EXPECT_TRUE(UkmInChromeTriggerAction(
+ {{GURL(kExampleDeeplink),
+ Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH},
+ {GURL("https://www.some-website.com/cart"),
+ Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}));
+
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, DoNotStartImplicitlyIfSettingDisabled) {
+ SetupPlatformDelegateForReturningUser();
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ fake_platform_delegate_.proactive_help_enabled_ = false;
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ EXPECT_FALSE(UkmInChromeTriggerAction());
+}
+
+TEST_F(StarterTest, ImplicitStartupOnCurrentUrlAfterSettingEnabled) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.proactive_help_enabled_ = false;
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_,
+ OnSendRequest(
+ GURL("https://automate-pa.googleapis.com/v1/triggers"), _, _))
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK,
+ CreateTriggerScriptResponseForTest()));
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript).Times(1);
+
+ // Implicit startup by enabling proactive help while already on an
+ // autofill-assistant-enabled site.
+ fake_platform_delegate_.proactive_help_enabled_ = true;
+ starter_->CheckSettings();
+ task_environment()->RunUntilIdle();
+
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::RETURNING_USER,
+ GURL("https://www.some-website.com/cart")));
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ EXPECT_TRUE(UkmInChromeTriggerAction(
+ {{GURL("https://www.some-website.com/cart"),
+ Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}));
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, StartTriggerScriptBeforeRedirectRecordsUkmForTargetUrl) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.feature_module_installed_ = true;
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ = nullptr;
+ mock_trigger_script_service_request_sender_ = nullptr;
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"TRIGGER_SCRIPTS_BASE64", CreateBase64TriggerScriptResponseForTest()},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ TriggerContext::Options options;
+ options.initial_url = "https://redirect.com/to/www/example/com";
+
+ // Simulate a real flow that starts on some trigger site, which then redirects
+ // to the deeplink.
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://some-trigger-site.com"));
+
+ // Start the flow before the trigger site has had a chance to navigate to the
+ // target domain. This commonly happens due to android intent handling
+ // happening before navigations are started.
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters), options));
+
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript);
+
+ std::unique_ptr<content::NavigationSimulator> simulator =
+ content::NavigationSimulator::CreateRendererInitiated(
+ web_contents()->GetLastCommittedURL(),
+ web_contents()->GetMainFrame());
+ simulator->Start();
+ simulator->Redirect(GURL("https://redirect.com/to/www/example/com"));
+ simulator->Redirect(GURL(kExampleDeeplink));
+ // To spice things up a bit more, we redirect to a subdomain of the target
+ // domain instead.
+ simulator->Redirect(GURL("https://signin.example.com"));
+ simulator->Commit();
+
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::RETURNING_USER,
+ GURL("https://signin.example.com")));
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, RedirectFailsDuringPendingTriggerScriptStart) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.feature_module_installed_ = true;
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ = nullptr;
+ mock_trigger_script_service_request_sender_ = nullptr;
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"TRIGGER_SCRIPTS_BASE64", CreateBase64TriggerScriptResponseForTest()},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ TriggerContext::Options options;
+ options.initial_url = "https://redirect.com/to/www/example/com";
+
+ // Simulate a real flow that starts on some trigger site, which then redirects
+ // to the deeplink.
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://some-trigger-site.com"));
+
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters), options));
+
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript).Times(0);
+
+ std::unique_ptr<content::NavigationSimulator> simulator =
+ content::NavigationSimulator::CreateRendererInitiated(
+ web_contents()->GetLastCommittedURL(),
+ web_contents()->GetMainFrame());
+ simulator->Start();
+ simulator->Redirect(GURL("https://redirect.com/to/www/example/com"));
+ simulator->Fail(net::ERR_BLOCKED_BY_CLIENT);
+ simulator->CommitErrorPage();
+
+ // Note that this impression is recorded for the last URL that a navigation-
+ // start event occurred for. We never reached the target domain, so this is
+ // unfortunately the best we can do.
+ EXPECT_TRUE(
+ UkmTriggerScriptStarted(Metrics::TriggerScriptStarted::NAVIGATION_ERROR,
+ GURL("https://redirect.com/to/www/example/com")));
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectTotalCount(
+ "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, StartTriggerScriptDuringRedirectRecordsUkmForTargetUrl) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.feature_module_installed_ = true;
+ fake_platform_delegate_.trigger_script_request_sender_for_test_ = nullptr;
+ mock_trigger_script_service_request_sender_ = nullptr;
+
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"TRIGGER_SCRIPTS_BASE64", CreateBase64TriggerScriptResponseForTest()},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ TriggerContext::Options options;
+ options.initial_url = "https://redirect.com/to/www/example/com";
+
+ // Simulate a real flow that starts on some trigger site, which then redirects
+ // to the deeplink.
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://some-trigger-site.com"));
+
+ // Begin a navigation, then start the flow before the navigation is committed.
+ // UKM should still be recorded for the final URL, not the redirect URL.
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript);
+ std::unique_ptr<content::NavigationSimulator> simulator =
+ content::NavigationSimulator::CreateRendererInitiated(
+ web_contents()->GetLastCommittedURL(),
+ web_contents()->GetMainFrame());
+ simulator->Start();
+ simulator->Redirect(GURL("https://redirect.com/to/www/example/com"));
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters), options));
+ simulator->Redirect(GURL(kExampleDeeplink));
+ simulator->Commit();
+
+ EXPECT_TRUE(UkmTriggerScriptStarted(
+ Metrics::TriggerScriptStarted::RETURNING_USER, GURL(kExampleDeeplink)));
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, RegularStartupDoesNotWaitForNavigationToFinish) {
+ SetupPlatformDelegateForReturningUser();
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "true"},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ TriggerContext::Options options;
+
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://some-trigger-site.com"));
+ std::unique_ptr<content::NavigationSimulator> simulator =
+ content::NavigationSimulator::CreateRendererInitiated(
+ web_contents()->GetLastCommittedURL(),
+ web_contents()->GetMainFrame());
+ simulator->Start();
+ simulator->Redirect(GURL("https://redirect.com/to/www/example/com"));
+
+ {
+ EXPECT_CALL(mock_start_regular_script_callback_,
+ Run(GURL(kExampleDeeplink), _, _));
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters), options));
+ }
+
+ simulator->Redirect(GURL(kExampleDeeplink));
+ simulator->Commit();
+
+ EXPECT_FALSE(UkmTriggerScriptStarted());
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ histogram_tester_.ExpectUniqueSample(
+ "Android.AutofillAssistant.FeatureModuleInstallation",
+ Metrics::FeatureModuleInstallation::DFM_ALREADY_INSTALLED, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_ACCEPTED, 1u);
+ histogram_tester_.ExpectBucketCount("Android.AutofillAssistant.OnBoarding",
+ Metrics::OnBoarding::OB_NOT_SHOWN, 1u);
+}
+
+TEST_F(StarterTest, DoNotStartImplicitlyIfAlreadyRunning) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.is_regular_script_running_ = true;
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "true"},
+ {"ORIGINAL_DEEPLINK", kExampleDeeplink}};
+ TriggerContext::Options options;
+
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+
+ task_environment()->RunUntilIdle();
+ EXPECT_FALSE(UkmTriggerScriptStarted());
+ EXPECT_FALSE(UkmTriggerScriptFinished());
+ EXPECT_FALSE(UkmTriggerScriptOnboarding());
+ EXPECT_FALSE(UkmInChromeTriggerAction());
+ histogram_tester_.ExpectTotalCount(
+ "Android.AutofillAssistant.FeatureModuleInstallation", 0u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+ histogram_tester_.ExpectTotalCount("Android.AutofillAssistant.OnBoarding",
+ 0u);
+}
+
+TEST_F(StarterTest, FailedTriggerScriptFetchesForImplicitStartupAreCached) {
+ SetupPlatformDelegateForReturningUser();
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_,
+ OnSendRequest(
+ GURL("https://automate-pa.googleapis.com/v1/triggers"), _, _))
+ .WillOnce(RunOnceCallback<2>(net::HTTP_FORBIDDEN, std::string()));
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript).Times(0);
+ EXPECT_CALL(mock_start_regular_script_callback_, Run).Times(0);
+
+ // Implicit startup by navigating to an autofill-assistant-enabled site.
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+ task_environment()->RunUntilIdle();
+ EXPECT_THAT(*GetFailedTriggerFetchesCacheForTest(),
+ UnorderedElementsAre(
+ Pair("some-website.com",
+ task_environment()->GetMockTickClock()->NowTicks())));
+
+ // Since we failed to communicate with the backend, we won't try again for the
+ // same domain or sub-domain.
+ PrepareTriggerScriptRequestSender();
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/checkout"));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://some-website.com/signin"));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://signin.some-website.com"));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ // Navigations to different autofill-assistant-enabled URLs will still trigger
+ // implicit startup.
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(1);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.different-website.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ EXPECT_TRUE(UkmInChromeTriggerAction(
+ {{GURL(kExampleDeeplink),
+ Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH},
+ {GURL("https://www.some-website.com/cart"),
+ Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED},
+ {GURL("https://www.some-website.com/checkout"),
+ Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
+ {GURL("https://some-website.com/signin"),
+ Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
+ {GURL("https://signin.some-website.com"),
+ Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
+ {GURL("https://www.some-website.com/cart"),
+ Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
+ {GURL("https://www.different-website.com/cart"),
+ Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}));
+}
+
+TEST_F(StarterTest,
+ CancelingTriggerScriptsDenylistsTheDomainForImplicitStartup) {
+ SetupPlatformDelegateForReturningUser();
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_,
+ OnSendRequest(
+ GURL("https://automate-pa.googleapis.com/v1/triggers"), _, _))
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK,
+ CreateTriggerScriptResponseForTest()));
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript)
+ .WillOnce([&]() {
+ ASSERT_TRUE(trigger_script_coordinator_ != nullptr);
+ trigger_script_coordinator_->PerformTriggerScriptAction(
+ TriggerScriptProto::CANCEL_SESSION);
+ });
+
+ // Implicit startup by navigating to an autofill-assistant-enabled site.
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+ task_environment()->RunUntilIdle();
+ EXPECT_THAT(*GetUserDenylistedCacheForTest(),
+ UnorderedElementsAre(
+ Pair("some-website.com",
+ task_environment()->GetMockTickClock()->NowTicks())));
+
+ // Since the user chose CANCEL_SESSION, subsequent navigations to the same
+ // domain or sub-domains should not trigger implicit startup.
+ PrepareTriggerScriptRequestSender();
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/checkout"));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://some-website.com/signin"));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://signin.some-website.com"));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ // Navigations to different autofill-assistant-enabled URLs will still trigger
+ // implicit startup.
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(1);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.different-website.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ EXPECT_TRUE(UkmInChromeTriggerAction(
+ {{GURL(kExampleDeeplink),
+ Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH},
+ {GURL("https://www.some-website.com/cart"),
+ Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED},
+ {GURL("https://www.some-website.com/checkout"),
+ Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN},
+ {GURL("https://some-website.com/signin"),
+ Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN},
+ {GURL("https://signin.some-website.com"),
+ Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN},
+ {GURL("https://www.some-website.com/cart"),
+ Metrics::InChromeTriggerAction::USER_DENYLISTED_DOMAIN},
+ {GURL("https://www.different-website.com/cart"),
+ Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}));
+}
+
+TEST_F(StarterTest, EmptyTriggerScriptFetchesForImplicitStartupAreCached) {
+ SetupPlatformDelegateForReturningUser();
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_,
+ OnSendRequest(
+ GURL("https://automate-pa.googleapis.com/v1/triggers"), _, _))
+ .WillOnce(
+ WithArg<2>([&](ServiceRequestSender::ResponseCallback& callback) {
+ // Empty response == no trigger scripts available.
+ std::move(callback).Run(net::HTTP_OK, std::string());
+ }));
+
+ // Implicit startup by navigating to an autofill-assistant-enabled site.
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+ task_environment()->RunUntilIdle();
+ EXPECT_THAT(*GetFailedTriggerFetchesCacheForTest(),
+ UnorderedElementsAre(
+ Pair("some-website.com",
+ task_environment()->GetMockTickClock()->NowTicks())));
+
+ // Subsequent navigations to the same domain should not talk to the backend
+ // again. This includes navigations to subdomains etc.
+ PrepareTriggerScriptRequestSender();
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/checkout"));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://some-website.com/signin"));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://signin.some-website.com"));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ // However, explicit requests still communicate with the backend.
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(1);
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"REQUEST_TRIGGER_SCRIPT", "true"},
+ {"ORIGINAL_DEEPLINK", "https://www.some-website.com/cart"}};
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{}));
+
+ EXPECT_TRUE(UkmInChromeTriggerAction(
+ {{GURL(kExampleDeeplink),
+ Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH},
+ {GURL("https://www.some-website.com/cart"),
+ Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED},
+ {GURL("https://www.some-website.com/checkout"),
+ Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
+ {GURL("https://some-website.com/signin"),
+ Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
+ {GURL("https://signin.some-website.com"),
+ Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN},
+ {GURL("https://www.some-website.com/cart"),
+ Metrics::InChromeTriggerAction::CACHE_HIT_UNSUPPORTED_DOMAIN}}));
+}
+
+TEST_F(StarterTest, FailedExplicitTriggerFetchesAreCached) {
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"REQUEST_TRIGGER_SCRIPT", "true"}};
+ std::vector<std::string> unsupported_sites = {
+ "https://www.example.com", "https://signing.example.com",
+ "https://different.com", "https://different.com/test?q=12345"};
+ for (const auto& url : unsupported_sites) {
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL(url));
+ PrepareTriggerScriptRequestSender();
+ PrepareTriggerScriptUiDelegate();
+ // Send empty response == no trigger script available. Note that explicit
+ // start requests like these will always attempt to talk to the backend, no
+ // matter the cache contents.
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK, std::string()));
+ script_parameters["ORIGINAL_DEEPLINK"] = url;
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{}));
+ }
+ // Cache should contain one entry per organization-identifying domain.
+ base::TimeTicks now_ticks =
+ task_environment()->GetMockTickClock()->NowTicks();
+ EXPECT_THAT(*GetFailedTriggerFetchesCacheForTest(),
+ UnorderedElementsAre(Pair("example.com", now_ticks),
+ Pair("different.com", now_ticks)));
+ EXPECT_FALSE(UkmInChromeTriggerAction());
+}
+
+TEST_F(StarterTest, FailedImplicitTriggerFetchesAreCached) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+
+ std::vector<std::string> implicit_unsupported_sites = {
+ "https://www.example-shopping-site.com/cart",
+ "https://different-shopping-site.com/cart"};
+ for (const auto& url : implicit_unsupported_sites) {
+ PrepareTriggerScriptRequestSender();
+ PrepareTriggerScriptUiDelegate();
+ // Send empty response == no trigger script available.
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK, std::string()));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL(url));
+ task_environment()->RunUntilIdle();
+ }
+ // Failed attempts to start implicitly are added to the cache.
+ base::TimeTicks now_ticks =
+ task_environment()->GetMockTickClock()->NowTicks();
+ EXPECT_THAT(
+ *GetFailedTriggerFetchesCacheForTest(),
+ UnorderedElementsAre(Pair("example-shopping-site.com", now_ticks),
+ Pair("different-shopping-site.com", now_ticks)));
+ EXPECT_TRUE(UkmInChromeTriggerAction(
+ {{GURL(kExampleDeeplink),
+ Metrics::InChromeTriggerAction::NO_HEURISTIC_MATCH},
+ {GURL("https://www.example-shopping-site.com/cart"),
+ Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED},
+ {GURL("https://different-shopping-site.com/cart"),
+ Metrics::InChromeTriggerAction::TRIGGER_SCRIPT_REQUESTED}}));
+}
+
+TEST_F(StarterTest, FailedTriggerFetchesCacheEntriesExpire) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+
+ GetFailedTriggerFetchesCacheForTest()->Put(
+ "example.com", task_environment()->GetMockTickClock()->NowTicks());
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK, std::string()));
+ task_environment()->FastForwardBy(base::TimeDelta::FromHours(1));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ // Since the request failed again, the cache entry should be updated with the
+ // new time.
+ EXPECT_THAT(
+ *GetFailedTriggerFetchesCacheForTest(),
+ UnorderedElementsAre(Pair(
+ "example.com", task_environment()->GetMockTickClock()->NowTicks())));
+}
+
+TEST_F(StarterTest, UserDenylistedCacheUpdateAndExpire) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK,
+ CreateTriggerScriptResponseForTest()));
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript)
+ .WillOnce([&]() {
+ trigger_script_coordinator_->PerformTriggerScriptAction(
+ TriggerScriptProto::CANCEL_SESSION);
+ });
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+ EXPECT_THAT(
+ *GetUserDenylistedCacheForTest(),
+ UnorderedElementsAre(Pair(
+ "example.com", task_environment()->GetMockTickClock()->NowTicks())));
+
+ PrepareTriggerScriptRequestSender();
+ PrepareTriggerScriptUiDelegate();
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK,
+ CreateTriggerScriptResponseForTest()));
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript)
+ .WillOnce([&]() {
+ trigger_script_coordinator_->PerformTriggerScriptAction(
+ TriggerScriptProto::CANCEL_SESSION);
+ });
+ task_environment()->FastForwardBy(base::TimeDelta::FromHours(1));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ // Since the request was cancelled again, the cache entry should have been
+ // updated with the new time.
+ EXPECT_THAT(
+ *GetUserDenylistedCacheForTest(),
+ UnorderedElementsAre(Pair(
+ "example.com", task_environment()->GetMockTickClock()->NowTicks())));
+}
+
+TEST_F(StarterTest, RemoveEntryFromCacheOnSuccessForExplicitRequest) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+ GetFailedTriggerFetchesCacheForTest()->Put(
+ "example.com", task_environment()->GetMockTickClock()->NowTicks());
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK,
+ CreateTriggerScriptResponseForTest()));
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript)
+ .WillOnce([&]() {
+ trigger_script_coordinator_->PerformTriggerScriptAction(
+ TriggerScriptProto::ACCEPT);
+ });
+ std::map<std::string, std::string> script_parameters = {
+ {"ENABLED", "true"},
+ {"START_IMMEDIATELY", "false"},
+ {"REQUEST_TRIGGER_SCRIPT", "true"},
+ {"ORIGINAL_DEEPLINK", "https://www.example.com"}};
+ starter_->Start(std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(script_parameters),
+ TriggerContext::Options{}));
+ EXPECT_THAT(*GetFailedTriggerFetchesCacheForTest(), IsEmpty());
+}
+
+TEST_F(StarterTest, ImplicitInCctTriggeringSmokeTest) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.is_custom_tab_ = true;
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+}
+
+TEST_F(StarterTest, ImplicitInTabTriggeringSmokeTest) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.is_custom_tab_ = false;
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInTabTriggering);
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+}
+
+TEST_F(StarterTest, ImplicitInCctTriggeringDoesNotTriggerInTab) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.is_custom_tab_ = false;
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+}
+
+TEST_F(StarterTest, ImplicitInTabTriggeringDoesNotTriggerInCct) {
+ SetupPlatformDelegateForReturningUser();
+ fake_platform_delegate_.is_custom_tab_ = true;
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInTabTriggering);
+ starter_->CheckSettings();
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .Times(0);
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+}
+
+TEST(MultipleStarterTest, HeuristicUsedByMultipleInstances) {
+ content::BrowserTaskEnvironment task_environment(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+ content::RenderViewHostTestEnabler rvh_test_enabler;
+ content::TestBrowserContext browser_context;
+ ukm::TestAutoSetUkmRecorder ukm_recorder;
+ FakeStarterPlatformDelegate fake_platform_delegate_01;
+ FakeStarterPlatformDelegate fake_platform_delegate_02;
+ MockRuntimeManager mock_runtime_manager;
+
+ auto web_contents_01 = content::WebContentsTester::CreateTestWebContents(
+ &browser_context, nullptr);
+ ukm::InitializeSourceUrlRecorderForWebContents(web_contents_01.get());
+ auto web_contents_02 = content::WebContentsTester::CreateTestWebContents(
+ &browser_context, nullptr);
+ ukm::InitializeSourceUrlRecorderForWebContents(web_contents_02.get());
+
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ auto enable_fake_heuristic =
+ std::make_unique<base::test::ScopedFeatureList>();
+ enable_fake_heuristic->InitAndEnableFeatureWithParameters(
+ features::kAutofillAssistantUrlHeuristics, {{"json_parameters",
+ R"(
+ {
+ "heuristics":[
+ {
+ "intent":"FAKE_INTENT_CART",
+ "conditionSet":{
+ "urlContains":"cart"
+ }
+ }
+ ]
+ }
+ )"}});
+ Starter starter_01(web_contents_01.get(), &fake_platform_delegate_01,
+ &ukm_recorder, mock_runtime_manager.GetWeakPtr(),
+ task_environment.GetMockTickClock());
+ Starter starter_02(web_contents_02.get(), &fake_platform_delegate_02,
+ &ukm_recorder, mock_runtime_manager.GetWeakPtr(),
+ task_environment.GetMockTickClock());
+
+ auto service_request_sender_01 =
+ std::make_unique<NiceMock<MockServiceRequestSender>>();
+ auto* service_request_sender_01_ptr = service_request_sender_01.get();
+ fake_platform_delegate_01.trigger_script_request_sender_for_test_ =
+ std::move(service_request_sender_01);
+ auto service_request_sender_02 =
+ std::make_unique<NiceMock<MockServiceRequestSender>>();
+ auto* service_request_sender_02_ptr = service_request_sender_02.get();
+ fake_platform_delegate_02.trigger_script_request_sender_for_test_ =
+ std::move(service_request_sender_02);
+
+ EXPECT_CALL(*service_request_sender_01_ptr, OnSendRequest).Times(1);
+ EXPECT_CALL(*service_request_sender_02_ptr, OnSendRequest).Times(1);
+ content::WebContentsTester::For(web_contents_01.get())
+ ->NavigateAndCommit(GURL("https://www.some-website.com/cart"));
+ content::WebContentsTester::For(web_contents_02.get())
+ ->NavigateAndCommit(GURL("https://www.some-other-website.com/cart"));
+ task_environment.RunUntilIdle();
+}
+
+TEST_F(StarterTest, StaleCacheEntriesAreRemovedOnInsertingNewEntries) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ starter_->CheckSettings();
+ base::TimeTicks t0 = task_environment()->GetMockTickClock()->NowTicks();
+ GetFailedTriggerFetchesCacheForTest()->Put("failed-t0.com", t0);
+ GetUserDenylistedCacheForTest()->Put("denylisted-t0.com", t0);
+
+ task_environment()->FastForwardBy(base::TimeDelta::FromMinutes(30));
+ base::TimeTicks t1 = task_environment()->GetMockTickClock()->NowTicks();
+ EXPECT_THAT(*GetFailedTriggerFetchesCacheForTest(),
+ UnorderedElementsAre(Pair("failed-t0.com", t0)));
+ EXPECT_THAT(*GetUserDenylistedCacheForTest(),
+ UnorderedElementsAre(Pair("denylisted-t0.com", t0)));
+ GetFailedTriggerFetchesCacheForTest()->Put("failed-t1.com", t1);
+ GetUserDenylistedCacheForTest()->Put("denylisted-t1.com", t1);
+
+ task_environment()->FastForwardBy(base::TimeDelta::FromMinutes(30));
+ base::TimeTicks t2 = task_environment()->GetMockTickClock()->NowTicks();
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK, std::string()));
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://www.example.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ // failed-t0.com should have been removed from the cache due to going stale.
+ EXPECT_THAT(
+ *GetFailedTriggerFetchesCacheForTest(),
+ UnorderedElementsAre(Pair("failed-t1.com", t1), Pair("example.com", t2)));
+ // denylisted-t0.com is stale and will be removed the next time a domain is
+ // denylisted.
+ EXPECT_THAT(*GetUserDenylistedCacheForTest(),
+ UnorderedElementsAre(Pair("denylisted-t0.com", t0),
+ Pair("denylisted-t1.com", t1)));
+
+ PrepareTriggerScriptRequestSender();
+ PrepareTriggerScriptUiDelegate();
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_, OnSendRequest)
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK,
+ CreateTriggerScriptResponseForTest()));
+ EXPECT_CALL(*mock_trigger_script_ui_delegate_, ShowTriggerScript)
+ .WillOnce([&]() {
+ ASSERT_TRUE(trigger_script_coordinator_ != nullptr);
+ trigger_script_coordinator_->PerformTriggerScriptAction(
+ TriggerScriptProto::CANCEL_SESSION);
+ });
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://supported.com/cart"));
+ task_environment()->RunUntilIdle();
+
+ // No change to the failed fetches cache.
+ EXPECT_THAT(
+ *GetFailedTriggerFetchesCacheForTest(),
+ UnorderedElementsAre(Pair("failed-t1.com", t1), Pair("example.com", t2)));
+ // denylisted-t0.com should have been removed due to going stale.
+ EXPECT_THAT(*GetUserDenylistedCacheForTest(),
+ UnorderedElementsAre(Pair("denylisted-t1.com", t1),
+ Pair("supported.com", t2)));
+}
+
+TEST_F(StarterTest, CommandLineScriptParametersAreAddedToImplicitTriggers) {
+ auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list->InitAndEnableFeature(
+ features::kAutofillAssistantInCCTTriggering);
+ ImplicitTriggeringDebugParametersProto proto;
+ auto* param = proto.add_additional_script_parameters();
+ param->set_name("DEBUG_SOCKET_ID");
+ param->set_value("FAKE_SOCKET_ID");
+
+ param = proto.add_additional_script_parameters();
+ param->set_name("DEBUG_BUNDLE_ID");
+ param->set_value("FAKE_BUNDLE_ID");
+
+ param = proto.add_additional_script_parameters();
+ param->set_name("INTENT");
+ param->set_value("NEW_INTENT");
+
+ param = proto.add_additional_script_parameters();
+ param->set_name("NOT_ALLOWLISTED");
+ param->set_value("SHOULD_NOT_BE_SENT_TO_BACKEND");
+
+ std::string implicit_triggering_debug_parameters;
+ proto.SerializeToString(&implicit_triggering_debug_parameters);
+ base::Base64UrlEncode(implicit_triggering_debug_parameters,
+ base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ &implicit_triggering_debug_parameters);
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kAutofillAssistantImplicitTriggeringDebugParameters,
+ implicit_triggering_debug_parameters);
+
+ // Create new instance of the starter to force the changed command line to
+ // take effect.
+ starter_ = std::make_unique<Starter>(web_contents(), &fake_platform_delegate_,
+ &ukm_recorder_,
+ mock_runtime_manager_.GetWeakPtr(),
+ task_environment()->GetMockTickClock());
+
+ EXPECT_CALL(*mock_trigger_script_service_request_sender_,
+ OnSendRequest(
+ GURL("https://automate-pa.googleapis.com/v1/triggers"), _, _))
+ .WillOnce(WithArg<1>([&](const std::string& request_body) {
+ GetTriggerScriptsRequestProto request;
+ ASSERT_TRUE(request.ParseFromString(request_body));
+ EXPECT_THAT(request.url(), Eq(GURL("https://example.com/cart")));
+ EXPECT_THAT(
+ request.script_parameters(),
+ UnorderedElementsAre(
+ AllOf(Property(&ScriptParameterProto::name, "DEBUG_SOCKET_ID"),
+ Property(&ScriptParameterProto::value, "FAKE_SOCKET_ID")),
+ AllOf(Property(&ScriptParameterProto::name, "DEBUG_BUNDLE_ID"),
+ Property(&ScriptParameterProto::value, "FAKE_BUNDLE_ID")),
+ AllOf(Property(&ScriptParameterProto::name, "INTENT"),
+ Property(&ScriptParameterProto::value, "NEW_INTENT"))));
+ }));
+
+ content::WebContentsTester::For(web_contents())
+ ->NavigateAndCommit(GURL("https://example.com/cart"));
+ task_environment()->RunUntilIdle();
}
-} // namespace
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/startup_util.cc b/chromium/components/autofill_assistant/browser/startup_util.cc
index 42479c21dd0..fde7b631fb4 100644
--- a/chromium/components/autofill_assistant/browser/startup_util.cc
+++ b/chromium/components/autofill_assistant/browser/startup_util.cc
@@ -100,7 +100,7 @@ StartupUtil::StartupMode StartupUtil::ChooseStartupModeForIntent(
return StartupMode::START_RPC_TRIGGER_SCRIPT;
}
-base::Optional<GURL> StartupUtil::ChooseStartupUrlForIntent(
+absl::optional<GURL> StartupUtil::ChooseStartupUrlForIntent(
const TriggerContext& trigger_context) const {
GURL url =
GURL(trigger_context.GetScriptParameters().GetOriginalDeeplink().value_or(
@@ -114,7 +114,7 @@ base::Optional<GURL> StartupUtil::ChooseStartupUrlForIntent(
return url;
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/startup_util.h b/chromium/components/autofill_assistant/browser/startup_util.h
index 1d4c2ecc8ba..6cdbf6e7e76 100644
--- a/chromium/components/autofill_assistant/browser/startup_util.h
+++ b/chromium/components/autofill_assistant/browser/startup_util.h
@@ -5,8 +5,8 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_STARTUP_UTIL_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_STARTUP_UTIL_H_
-#include "base/optional.h"
#include "components/autofill_assistant/browser/trigger_context.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace autofill_assistant {
@@ -57,8 +57,8 @@ class StartupUtil {
// Determines the startup URL. Preferably, the caller has passed this in
// via ORIGINAL_DEEPLINK. If they have not, we try to guess the url from the
- // initial url. If this fails, this will return base::nullopt.
- base::Optional<GURL> ChooseStartupUrlForIntent(
+ // initial url. If this fails, this will return absl::nullopt.
+ absl::optional<GURL> ChooseStartupUrlForIntent(
const TriggerContext& trigger_context) const;
};
diff --git a/chromium/components/autofill_assistant/browser/startup_util_unittest.cc b/chromium/components/autofill_assistant/browser/startup_util_unittest.cc
index 2ed301f16f5..16824794371 100644
--- a/chromium/components/autofill_assistant/browser/startup_util_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/startup_util_unittest.cc
@@ -82,10 +82,10 @@ const std::map<std::string, std::string> kBase64TriggerScript = {
{"ORIGINAL_DEEPLINK", "https://www.example.com"}};
const TriggerContext::Options kDefaultCCTOptions = {
- std::string(), /* is_cct = */ true, false, false, std::string()};
+ std::string(), /* is_cct = */ true, false, false, std::string(), false};
const TriggerContext::Options kDefaultNonCCTOptions = {
- std::string(), /* is_cct = */ false, false, false, std::string()};
+ std::string(), /* is_cct = */ false, false, false, std::string(), false};
// The set of feature combinations to test.
const TestFeatureConfig kTestFeatureConfigs[] = {
@@ -416,7 +416,7 @@ TEST_P(StartupUtilParametrizedTest, InvalidParameterCombinationsShouldFail) {
std::map<std::string, std::string>{
{"ENABLED", "true"}, {"START_IMMEDIATELY", "true"}}),
{std::string(), /* is_cct = */ true, false, false,
- /* initial_url = */ "https://www.example.com"}},
+ /* initial_url = */ "https://www.example.com", false}},
{.msbb_setting_enabled = true,
.proactive_help_setting_enabled = true,
.feature_module_installed = true}),
@@ -458,7 +458,7 @@ TEST_F(StartupUtilTest, ChooseStartupUrlForIntentFailsIfNotSpecified) {
EXPECT_THAT(
StartupUtil().ChooseStartupUrlForIntent(
{std::make_unique<ScriptParameters>(), TriggerContext::Options{}}),
- Eq(base::nullopt));
+ Eq(absl::nullopt));
}
} // namespace
diff --git a/chromium/components/autofill_assistant/browser/switches.cc b/chromium/components/autofill_assistant/browser/switches.cc
index da90dfb8f1c..4a7a0e683e5 100644
--- a/chromium/components/autofill_assistant/browser/switches.cc
+++ b/chromium/components/autofill_assistant/browser/switches.cc
@@ -7,6 +7,31 @@
namespace autofill_assistant {
namespace switches {
+// Disables authentication when set to false. This is only useful
+// during development, as prod instances require authentication.
+const char kAutofillAssistantAuth[] = "autofill-assistant-auth";
+
+// Forces first-time user experience if set to 'true'. This will overwrite the
+// AA preference by setting first time user to 'true' before each startup.
+// Does nothing if unset or is set to false. This is only useful during testing
+// and development.
+// This flag is only for trigger scripts, because first-time user experience
+// means that the user has not seen trigger script before.
+const char kAutofillAssistantForceFirstTimeUser[] =
+ "autofill-assistant-force-first-time-user";
+
+// Forces the onboarding to be shown if set to 'true'. This will overwrite the
+// AA preference by setting onboarding accepted to 'false' before each startup.
+// Does nothing if unset or is set to false. This is only useful during testing
+// and development.
+const char kAutofillAssistantForceOnboarding[] =
+ "autofill-assistant-force-onboarding";
+
+// Base64-encoded |ImplicitTriggeringDebugParametersProto| containing debug
+// parameters for in-CCT and in-Tab trigger scenarios.
+const char kAutofillAssistantImplicitTriggeringDebugParameters[] =
+ "autofill-assistant-implicit-triggering-debug-parameters";
+
// Sets the API key to be used instead of Chrome's default key when sending
// requests to the backend.
const char kAutofillAssistantServerKey[] = "autofill-assistant-key";
@@ -14,9 +39,5 @@ const char kAutofillAssistantServerKey[] = "autofill-assistant-key";
// Overrides the default backend URL.
const char kAutofillAssistantUrl[] = "autofill-assistant-url";
-// Disables authentication when set to false. This is only useful
-// during development, as prod instances require authentication.
-const char kAutofillAssistantAuth[] = "autofill-assistant-auth";
-
} // namespace switches
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/switches.h b/chromium/components/autofill_assistant/browser/switches.h
index b966fbc2971..a82a28644a2 100644
--- a/chromium/components/autofill_assistant/browser/switches.h
+++ b/chromium/components/autofill_assistant/browser/switches.h
@@ -8,9 +8,13 @@
namespace autofill_assistant {
namespace switches {
+// All switches in alphabetical order.
+extern const char kAutofillAssistantAuth[];
+extern const char kAutofillAssistantForceFirstTimeUser[];
+extern const char kAutofillAssistantForceOnboarding[];
+extern const char kAutofillAssistantImplicitTriggeringDebugParameters[];
extern const char kAutofillAssistantServerKey[];
extern const char kAutofillAssistantUrl[];
-extern const char kAutofillAssistantAuth[];
} // namespace switches
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/trigger_context.cc b/chromium/components/autofill_assistant/browser/trigger_context.cc
index b701ce9c53f..1263fcf32dc 100644
--- a/chromium/components/autofill_assistant/browser/trigger_context.cc
+++ b/chromium/components/autofill_assistant/browser/trigger_context.cc
@@ -12,12 +12,14 @@ TriggerContext::Options::Options(const std::string& _experiment_ids,
bool _is_cct,
bool _onboarding_shown,
bool _is_direct_action,
- const std::string& _initial_url)
+ const std::string& _initial_url,
+ bool _is_in_chrome_triggered)
: experiment_ids(_experiment_ids),
is_cct(_is_cct),
onboarding_shown(_onboarding_shown),
is_direct_action(_is_direct_action),
- initial_url(_initial_url) {}
+ initial_url(_initial_url),
+ is_in_chrome_triggered(_is_in_chrome_triggered) {}
TriggerContext::Options::Options() = default;
TriggerContext::Options::~Options() = default;
@@ -33,7 +35,8 @@ TriggerContext::TriggerContext(
options.is_cct,
options.onboarding_shown,
options.is_direct_action,
- options.initial_url) {}
+ options.initial_url,
+ options.is_in_chrome_triggered) {}
TriggerContext::TriggerContext(
std::unique_ptr<ScriptParameters> script_parameters,
@@ -41,12 +44,14 @@ TriggerContext::TriggerContext(
bool is_cct,
bool onboarding_shown,
bool is_direct_action,
- const std::string& initial_url)
+ const std::string& initial_url,
+ bool is_in_chrome_triggered)
: script_parameters_(std::move(script_parameters)),
experiment_ids_(std::move(experiment_ids)),
cct_(is_cct),
onboarding_shown_(onboarding_shown),
direct_action_(is_direct_action),
+ is_in_chrome_triggered_(is_in_chrome_triggered),
initial_url_(initial_url) {}
TriggerContext::TriggerContext(std::vector<const TriggerContext*> contexts)
@@ -67,16 +72,26 @@ TriggerContext::TriggerContext(std::vector<const TriggerContext*> contexts)
cct_ |= context->GetCCT();
onboarding_shown_ |= context->GetOnboardingShown();
direct_action_ |= context->GetDirectAction();
+ is_in_chrome_triggered_ |= context->GetInChromeTriggered();
if (initial_url_.empty()) {
initial_url_ = context->GetInitialUrl();
}
+ if (trigger_ui_type_ == TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE) {
+ trigger_ui_type_ = context->GetTriggerUIType();
+ }
}
}
TriggerContext::~TriggerContext() = default;
const ScriptParameters& TriggerContext::GetScriptParameters() const {
- return *script_parameters_.get();
+ return *script_parameters_;
+}
+
+void TriggerContext::SetScriptParameters(
+ std::unique_ptr<ScriptParameters> script_parameters) {
+ DCHECK(script_parameters);
+ script_parameters_ = std::move(script_parameters);
}
std::string TriggerContext::GetExperimentIds() const {
@@ -111,4 +126,17 @@ bool TriggerContext::GetDirectAction() const {
return direct_action_;
}
+bool TriggerContext::GetInChromeTriggered() const {
+ return is_in_chrome_triggered_;
+}
+
+TriggerScriptProto::TriggerUIType TriggerContext::GetTriggerUIType() const {
+ return trigger_ui_type_;
+}
+
+void TriggerContext::SetTriggerUIType(
+ TriggerScriptProto::TriggerUIType trigger_ui_type) {
+ trigger_ui_type_ = trigger_ui_type;
+}
+
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/trigger_context.h b/chromium/components/autofill_assistant/browser/trigger_context.h
index 9c3e397d863..7c6c7255f45 100644
--- a/chromium/components/autofill_assistant/browser/trigger_context.h
+++ b/chromium/components/autofill_assistant/browser/trigger_context.h
@@ -10,9 +10,9 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/autofill_assistant/browser/script_parameters.h"
#include "components/autofill_assistant/browser/service.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -25,7 +25,8 @@ class TriggerContext {
bool is_cct,
bool onboarding_shown,
bool is_direct_action,
- const std::string& initial_url);
+ const std::string& initial_url,
+ bool is_in_chrome_triggered);
Options();
~Options();
std::string experiment_ids;
@@ -33,6 +34,7 @@ class TriggerContext {
bool onboarding_shown = false;
bool is_direct_action = false;
std::string initial_url;
+ bool is_in_chrome_triggered = false;
};
// Creates an empty trigger context.
@@ -53,7 +55,8 @@ class TriggerContext {
bool is_cct,
bool onboarding_shown,
bool is_direct_action,
- const std::string& initial_url);
+ const std::string& initial_url,
+ bool is_in_chrome_triggered);
// Creates a trigger context that contains the merged contents of all input
// instances at the time of calling (does not reference |contexts| after
@@ -66,6 +69,10 @@ class TriggerContext {
// Returns a const reference to the script parameters.
virtual const ScriptParameters& GetScriptParameters() const;
+ // Replaces the current script parameters with |script_parameters|.
+ virtual void SetScriptParameters(
+ std::unique_ptr<ScriptParameters> script_parameters);
+
// Returns a comma-separated set of experiment ids.
virtual std::string GetExperimentIds() const;
@@ -92,6 +99,18 @@ class TriggerContext {
// Returns true if the current action was triggered by a direct action.
virtual bool GetDirectAction() const;
+ // Returns whether this trigger context is coming from an external surface,
+ // i.e., a button or link on a website, or whether this is from within Chrome.
+ virtual bool GetInChromeTriggered() const;
+
+ // Returns the trigger type of the trigger script that was shown and accepted
+ // at the beginning of the flow, if any.
+ virtual TriggerScriptProto::TriggerUIType GetTriggerUIType() const;
+
+ // Sets the trigger type of the shown trigger script.
+ virtual void SetTriggerUIType(
+ TriggerScriptProto::TriggerUIType trigger_ui_type);
+
private:
std::unique_ptr<ScriptParameters> script_parameters_;
@@ -102,9 +121,12 @@ class TriggerContext {
bool cct_ = false;
bool onboarding_shown_ = false;
bool direct_action_ = false;
+ bool is_in_chrome_triggered_ = false;
// The initial url at the time of triggering.
std::string initial_url_;
+ TriggerScriptProto::TriggerUIType trigger_ui_type_ =
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE;
};
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/trigger_context_unittest.cc b/chromium/components/autofill_assistant/browser/trigger_context_unittest.cc
index 616af358c76..b2200bf36a0 100644
--- a/chromium/components/autofill_assistant/browser/trigger_context_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/trigger_context_unittest.cc
@@ -33,7 +33,8 @@ TEST(TriggerContextTest, Create) {
/* is_cct = */ true,
/* onboarding_shown = */ true,
/* is_direct_action = */ true,
- /* initial_url = */ "https://www.example.com"};
+ /* initial_url = */ "https://www.example.com",
+ /* is_in_chrome_triggered = */ true};
EXPECT_THAT(context.GetScriptParameters().ToProto(),
UnorderedElementsAreArray(std::map<std::string, std::string>(
{{"key_a", "value_a"}, {"key_b", "value_b"}})));
@@ -42,9 +43,15 @@ TEST(TriggerContextTest, Create) {
EXPECT_TRUE(context.GetOnboardingShown());
EXPECT_TRUE(context.GetDirectAction());
EXPECT_EQ(context.GetInitialUrl(), "https://www.example.com");
+ EXPECT_TRUE(context.GetInChromeTriggered());
+ EXPECT_EQ(context.GetTriggerUIType(),
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE);
context.SetOnboardingShown(false);
EXPECT_FALSE(context.GetOnboardingShown());
+ context.SetTriggerUIType(TriggerScriptProto::SHOPPING_CART_FIRST_TIME_USER);
+ EXPECT_EQ(context.GetTriggerUIType(),
+ TriggerScriptProto::SHOPPING_CART_FIRST_TIME_USER);
}
TEST(TriggerContextTest, MergeEmpty) {
@@ -55,6 +62,9 @@ TEST(TriggerContextTest, MergeEmpty) {
EXPECT_FALSE(merged.GetCCT());
EXPECT_FALSE(merged.GetOnboardingShown());
EXPECT_FALSE(merged.GetDirectAction());
+ EXPECT_FALSE(merged.GetInChromeTriggered());
+ EXPECT_EQ(merged.GetTriggerUIType(),
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE);
}
TEST(TriggerContextTest, MergeEmptyWithNonEmpty) {
@@ -73,6 +83,9 @@ TEST(TriggerContextTest, MergeEmptyWithNonEmpty) {
EXPECT_FALSE(merged.GetCCT());
EXPECT_FALSE(merged.GetOnboardingShown());
EXPECT_FALSE(merged.GetDirectAction());
+ EXPECT_FALSE(merged.GetInChromeTriggered());
+ EXPECT_EQ(merged.GetTriggerUIType(),
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE);
}
TEST(TriggerContextTest, MergeNonEmptyWithNonEmpty) {
@@ -89,7 +102,10 @@ TEST(TriggerContextTest, MergeNonEmptyWithNonEmpty) {
/* is_cct = */ true,
/* onboarding_shown = */ true,
/* is_direct_action = */ true,
- /* initial_url = */ "https://www.example.com"};
+ /* initial_url = */ "https://www.example.com",
+ /* is_in_chrome_triggered = */ true};
+ context2.SetTriggerUIType(
+ TriggerScriptProto::SHOPPING_CHECKOUT_FIRST_TIME_USER);
// Adding empty to make sure empty contexts are properly skipped.
TriggerContext empty;
@@ -102,6 +118,9 @@ TEST(TriggerContextTest, MergeNonEmptyWithNonEmpty) {
EXPECT_TRUE(merged.GetOnboardingShown());
EXPECT_TRUE(merged.GetDirectAction());
EXPECT_EQ(merged.GetInitialUrl(), "https://www.example.com");
+ EXPECT_TRUE(merged.GetInChromeTriggered());
+ EXPECT_EQ(merged.GetTriggerUIType(),
+ TriggerScriptProto::SHOPPING_CHECKOUT_FIRST_TIME_USER);
}
TEST(TriggerContextTest, HasExperimentId) {
@@ -145,4 +164,14 @@ TEST(TriggerContextTest, HasExperimentId) {
EXPECT_TRUE(single_element.HasExperimentId("1"));
}
+TEST(TriggerContextTest, SetScriptParameters) {
+ TriggerContext::Options options;
+ TriggerContext context = {std::make_unique<ScriptParameters>(),
+ TriggerContext::Options()};
+ auto new_script_params = std::make_unique<ScriptParameters>();
+ auto* new_script_params_ptr = new_script_params.get();
+ context.SetScriptParameters(std::move(new_script_params));
+ EXPECT_THAT(&context.GetScriptParameters(), Eq(new_script_params_ptr));
+}
+
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.cc b/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.cc
index 0f78eb54a45..5b90f51b6bf 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.cc
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.cc
@@ -61,11 +61,11 @@ void DynamicTriggerConditions::ClearSelectors() {
selectors_.clear();
}
-base::Optional<bool> DynamicTriggerConditions::GetSelectorMatches(
+absl::optional<bool> DynamicTriggerConditions::GetSelectorMatches(
const Selector& selector) const {
auto it = selector_matches_.find(selector);
if (it == selector_matches_.end()) {
- return base::nullopt;
+ return absl::nullopt;
}
return it->second;
}
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.h b/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.h
index b9ffd645886..df0b7279b52 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.h
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.h
@@ -10,9 +10,9 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/autofill_assistant/browser/selector.h"
#include "components/autofill_assistant/browser/web/web_controller.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -34,7 +34,7 @@ class DynamicTriggerConditions {
// Returns whether |selector| currently matches the DOM tree. |Update| must
// be called prior to this method. Only selectors that have previously been
// added via |AddSelectorsFromTriggerScript| can be queried.
- virtual base::Optional<bool> GetSelectorMatches(
+ virtual absl::optional<bool> GetSelectorMatches(
const Selector& selector) const;
// Sets whether the keyboard is currently visible.
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions_unittest.cc b/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions_unittest.cc
index b21f2ded2ac..c510047772b 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions_unittest.cc
@@ -48,7 +48,7 @@ TEST_F(DynamicTriggerConditionsTest, UpdateWithoutSelectorsDoesNothing) {
TEST_F(DynamicTriggerConditionsTest, LookupInvalidSelectorsFails) {
EXPECT_EQ(dynamic_trigger_conditions_.GetSelectorMatches(
Selector(ToSelectorProto("not_evaluated"))),
- base::nullopt);
+ absl::nullopt);
}
TEST_F(DynamicTriggerConditionsTest, AddSelectorsFromTriggerScript) {
@@ -106,13 +106,13 @@ TEST_F(DynamicTriggerConditionsTest, Update) {
EXPECT_EQ(dynamic_trigger_conditions_.GetSelectorMatches(
Selector(ToSelectorProto("a"))),
- base::make_optional(true));
+ absl::make_optional(true));
EXPECT_EQ(dynamic_trigger_conditions_.GetSelectorMatches(
Selector(ToSelectorProto("b"))),
- base::make_optional(false));
+ absl::make_optional(false));
EXPECT_EQ(dynamic_trigger_conditions_.GetSelectorMatches(
Selector(ToSelectorProto("c"))),
- base::make_optional(true));
+ absl::make_optional(true));
}
TEST_F(DynamicTriggerConditionsTest, ClearSelectors) {
@@ -148,7 +148,7 @@ TEST_F(DynamicTriggerConditionsTest, HasResults) {
// previous results.
EXPECT_EQ(dynamic_trigger_conditions_.GetSelectorMatches(
Selector(ToSelectorProto("a"))),
- base::make_optional(true));
+ absl::make_optional(true));
std::move(callback).Run(ClientStatus(ELEMENT_RESOLUTION_FAILED),
nullptr);
});
@@ -158,7 +158,7 @@ TEST_F(DynamicTriggerConditionsTest, HasResults) {
// After the update, the new result is returned.
EXPECT_EQ(dynamic_trigger_conditions_.GetSelectorMatches(
Selector(ToSelectorProto("a"))),
- base::make_optional(false));
+ absl::make_optional(false));
}
TEST_F(DynamicTriggerConditionsTest, GetPathPatternMatches) {
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/mock_dynamic_trigger_conditions.h b/chromium/components/autofill_assistant/browser/trigger_scripts/mock_dynamic_trigger_conditions.h
index 48fb3f6ce20..9b62f4b8f77 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/mock_dynamic_trigger_conditions.h
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/mock_dynamic_trigger_conditions.h
@@ -16,7 +16,7 @@ class MockDynamicTriggerConditions : public DynamicTriggerConditions {
~MockDynamicTriggerConditions() override;
MOCK_CONST_METHOD1(GetSelectorMatches,
- base::Optional<bool>(const Selector& selector));
+ absl::optional<bool>(const Selector& selector));
MOCK_METHOD1(SetURL, void(const GURL& url));
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.cc b/chromium/components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.cc
index c9a3d1b57d0..8e450c8f945 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.cc
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.cc
@@ -3,10 +3,12 @@
// found in the LICENSE file.
#include "components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.h"
+#include "url/gurl.h"
namespace autofill_assistant {
-MockStaticTriggerConditions::MockStaticTriggerConditions() = default;
+MockStaticTriggerConditions::MockStaticTriggerConditions()
+ : StaticTriggerConditions(nullptr, nullptr, GURL()) {}
MockStaticTriggerConditions::~MockStaticTriggerConditions() = default;
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.h b/chromium/components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.h
index 46603dc8d15..867b7759dc9 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.h
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_TRIGGER_SCRIPTS_MOCK_STATIC_TRIGGER_CONDITIONS_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_TRIGGER_SCRIPTS_MOCK_STATIC_TRIGGER_CONDITIONS_H_
+#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -15,17 +16,12 @@ class MockStaticTriggerConditions : public StaticTriggerConditions {
MockStaticTriggerConditions();
~MockStaticTriggerConditions() override;
- MOCK_METHOD5(
- Init,
- void(WebsiteLoginManager* website_login_manager,
- base::RepeatingCallback<bool(void)> is_first_time_user_callback,
- const GURL& url,
- TriggerContext* trigger_context,
- base::OnceCallback<void(void)> callback));
- MOCK_METHOD1(set_is_first_time_user, void(bool));
+ MOCK_METHOD1(Update, void(base::OnceCallback<void(void)> callback));
MOCK_CONST_METHOD0(is_first_time_user, bool());
MOCK_CONST_METHOD0(has_stored_login_credentials, bool());
MOCK_CONST_METHOD1(is_in_experiment, bool(int experiment_id));
+ MOCK_CONST_METHOD1(script_parameter_matches,
+ bool(const ScriptParameterMatchProto&));
MOCK_CONST_METHOD0(has_results, bool());
};
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.cc b/chromium/components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.cc
new file mode 100644
index 00000000000..d29f008247c
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.cc
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.h"
+
+namespace autofill_assistant {
+
+MockTriggerScriptUiDelegate::MockTriggerScriptUiDelegate() = default;
+MockTriggerScriptUiDelegate::~MockTriggerScriptUiDelegate() = default;
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.h b/chromium/components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.h
new file mode 100644
index 00000000000..5b47a6e2424
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.h
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_TRIGGER_SCRIPTS_MOCK_TRIGGER_SCRIPT_UI_DELEGATE_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_TRIGGER_SCRIPTS_MOCK_TRIGGER_SCRIPT_UI_DELEGATE_H_
+
+#include "components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace autofill_assistant {
+
+class MockTriggerScriptUiDelegate
+ : public TriggerScriptCoordinator::UiDelegate {
+ public:
+ MockTriggerScriptUiDelegate();
+ ~MockTriggerScriptUiDelegate() override;
+
+ MOCK_METHOD1(ShowTriggerScript, void(const TriggerScriptUIProto&));
+ MOCK_METHOD0(HideTriggerScript, void());
+ MOCK_METHOD1(Attach, void(TriggerScriptCoordinator*));
+ MOCK_METHOD0(Detach, void());
+};
+
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_TRIGGER_SCRIPTS_MOCK_TRIGGER_SCRIPT_UI_DELEGATE_H_
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.cc b/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.cc
index 9f0f50f765f..4300965289c 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.cc
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.cc
@@ -7,35 +7,32 @@
#include "base/callback.h"
#include "base/strings/string_number_conversions.h"
#include "components/autofill_assistant/browser/script_parameters.h"
+#include "components/autofill_assistant/browser/starter_platform_delegate.h"
namespace autofill_assistant {
-StaticTriggerConditions::StaticTriggerConditions() = default;
+StaticTriggerConditions::StaticTriggerConditions(
+ StarterPlatformDelegate* delegate,
+ TriggerContext* trigger_context,
+ const GURL& deeplink_url)
+ : delegate_(delegate),
+ trigger_context_(trigger_context),
+ deeplink_url_(deeplink_url) {}
StaticTriggerConditions::~StaticTriggerConditions() = default;
-void StaticTriggerConditions::Init(
- WebsiteLoginManager* website_login_manager,
- base::RepeatingCallback<bool(void)> is_first_time_user_callback,
- const GURL& url,
- TriggerContext* trigger_context,
- base::OnceCallback<void(void)> callback) {
+void StaticTriggerConditions::Update(base::OnceCallback<void(void)> callback) {
DCHECK(!callback_)
- << "Call to Init while another call to Init was still pending";
+ << "Call to Update while another call to Update was still pending";
if (callback_) {
return;
}
- is_first_time_user_ = is_first_time_user_callback.Run();
- trigger_context_ = trigger_context;
- has_stored_login_credentials_ = false;
callback_ = std::move(callback);
- website_login_manager->GetLoginsForUrl(
- url, base::BindOnce(&StaticTriggerConditions::OnGetLogins,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void StaticTriggerConditions::set_is_first_time_user(bool first_time_user) {
- is_first_time_user_ = first_time_user;
+ is_first_time_user_ = delegate_->GetIsFirstTimeUser();
+ has_stored_login_credentials_ = false;
+ delegate_->GetWebsiteLoginManager()->GetLoginsForUrl(
+ deeplink_url_, base::BindOnce(&StaticTriggerConditions::OnGetLogins,
+ weak_ptr_factory_.GetWeakPtr()));
}
bool StaticTriggerConditions::is_first_time_user() const {
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.h b/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.h
index e8c877b58b4..412125b5e6a 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.h
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.h
@@ -9,30 +9,28 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
+#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/trigger_context.h"
#include "components/autofill_assistant/browser/website_login_manager.h"
#include "url/gurl.h"
namespace autofill_assistant {
+class StarterPlatformDelegate;
// Provides easy access to the values of static trigger conditions. Static
// trigger conditions do not depend on the current state of the DOM, as opposed
// to dynamic element conditions.
class StaticTriggerConditions {
public:
- StaticTriggerConditions();
+ // |delegate| and |trigger_context| must outlive this instance.
+ StaticTriggerConditions(StarterPlatformDelegate* delegate,
+ TriggerContext* trigger_context,
+ const GURL& deeplink_url);
virtual ~StaticTriggerConditions();
- // Initializes the field values using |website_login_manager| and
- // |is_first_time_user_callback|. Invokes |callback| when done. All parameters
- // must outlive this call.
- virtual void Init(
- WebsiteLoginManager* website_login_manager,
- base::RepeatingCallback<bool(void)> is_first_time_user_callback,
- const GURL& url,
- TriggerContext* trigger_context,
- base::OnceCallback<void(void)> callback);
- virtual void set_is_first_time_user(bool first_time_user);
+ // Updates/initializes the static trigger conditions. Invokes |callback| when
+ // done.
+ virtual void Update(base::OnceCallback<void(void)> callback);
virtual bool is_first_time_user() const;
virtual bool has_stored_login_credentials() const;
virtual bool is_in_experiment(int experiment_id) const;
@@ -50,9 +48,13 @@ class StaticTriggerConditions {
// collected. Only valid during calls of |Init|.
base::OnceCallback<void(void)> callback_;
bool has_results_ = false;
- bool is_first_time_user_ = true;
bool has_stored_login_credentials_ = false;
- TriggerContext* trigger_context_;
+ // Note: this is cached to ensure that the flag value is consistent until the
+ // next call to |Update|. See b/192220992.
+ bool is_first_time_user_ = false;
+ StarterPlatformDelegate* delegate_ = nullptr;
+ TriggerContext* trigger_context_ = nullptr;
+ GURL deeplink_url_;
base::WeakPtrFactory<StaticTriggerConditions> weak_ptr_factory_{this};
};
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions_unittest.cc b/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions_unittest.cc
index 260e0c7a22f..a57b36e6646 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions_unittest.cc
@@ -4,7 +4,9 @@
#include "components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.h"
+#include "components/autofill_assistant/browser/fake_starter_platform_delegate.h"
#include "components/autofill_assistant/browser/mock_website_login_manager.h"
+#include "components/autofill_assistant/browser/trigger_context.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
@@ -23,58 +25,53 @@ const char kFakeUrl[] = "https://www.example.com";
class StaticTriggerConditionsTest : public testing::Test {
public:
- StaticTriggerConditionsTest() = default;
+ StaticTriggerConditionsTest() {
+ fake_platform_delegate_.website_login_manager_ =
+ &mock_website_login_manager_;
+ }
+
~StaticTriggerConditionsTest() override = default;
protected:
- StaticTriggerConditions static_trigger_conditions_;
- base::MockCallback<base::RepeatingCallback<bool(void)>>
- mock_is_first_time_user_callback_;
base::MockCallback<base::OnceCallback<void(void)>> mock_callback_;
NiceMock<MockWebsiteLoginManager> mock_website_login_manager_;
+ FakeStarterPlatformDelegate fake_platform_delegate_;
};
-TEST_F(StaticTriggerConditionsTest, Init) {
+TEST_F(StaticTriggerConditionsTest, Update) {
TriggerContext::Options options;
options.experiment_ids = "1,2,4";
TriggerContext trigger_context = {std::make_unique<ScriptParameters>(),
options};
- EXPECT_CALL(mock_is_first_time_user_callback_, Run).WillOnce(Return(true));
+ StaticTriggerConditions static_trigger_conditions = {
+ &fake_platform_delegate_, &trigger_context, GURL(kFakeUrl)};
+ fake_platform_delegate_.is_first_time_user_ = true;
EXPECT_CALL(mock_website_login_manager_, OnGetLoginsForUrl(GURL(kFakeUrl), _))
.WillOnce(RunOnceCallback<1>(std::vector<WebsiteLoginManager::Login>{
WebsiteLoginManager::Login(GURL(kFakeUrl), "fake_username")}));
EXPECT_CALL(mock_callback_, Run).Times(1);
- static_trigger_conditions_.Init(
- &mock_website_login_manager_, mock_is_first_time_user_callback_.Get(),
- GURL(kFakeUrl), &trigger_context, mock_callback_.Get());
-
- EXPECT_TRUE(static_trigger_conditions_.is_first_time_user());
- EXPECT_TRUE(static_trigger_conditions_.has_stored_login_credentials());
- EXPECT_TRUE(static_trigger_conditions_.is_in_experiment(1));
- EXPECT_TRUE(static_trigger_conditions_.is_in_experiment(2));
- EXPECT_FALSE(static_trigger_conditions_.is_in_experiment(3));
- EXPECT_TRUE(static_trigger_conditions_.is_in_experiment(4));
-}
-
-TEST_F(StaticTriggerConditionsTest, SetIsFirstTimeUser) {
- EXPECT_TRUE(static_trigger_conditions_.is_first_time_user());
- static_trigger_conditions_.set_is_first_time_user(false);
- EXPECT_FALSE(static_trigger_conditions_.is_first_time_user());
+ static_trigger_conditions.Update(mock_callback_.Get());
+
+ EXPECT_TRUE(static_trigger_conditions.is_first_time_user());
+ EXPECT_TRUE(static_trigger_conditions.has_stored_login_credentials());
+ EXPECT_TRUE(static_trigger_conditions.is_in_experiment(1));
+ EXPECT_TRUE(static_trigger_conditions.is_in_experiment(2));
+ EXPECT_FALSE(static_trigger_conditions.is_in_experiment(3));
+ EXPECT_TRUE(static_trigger_conditions.is_in_experiment(4));
}
TEST_F(StaticTriggerConditionsTest, HasResults) {
- EXPECT_FALSE(static_trigger_conditions_.has_results());
-
TriggerContext trigger_context;
- EXPECT_CALL(mock_is_first_time_user_callback_, Run).WillOnce(Return(true));
+ StaticTriggerConditions static_trigger_conditions = {
+ &fake_platform_delegate_, &trigger_context, GURL(kFakeUrl)};
+ EXPECT_FALSE(static_trigger_conditions.has_results());
+
EXPECT_CALL(mock_website_login_manager_, OnGetLoginsForUrl(GURL(kFakeUrl), _))
.WillOnce(RunOnceCallback<1>(std::vector<WebsiteLoginManager::Login>{
WebsiteLoginManager::Login(GURL(kFakeUrl), "fake_username")}));
EXPECT_CALL(mock_callback_, Run).Times(1);
- static_trigger_conditions_.Init(
- &mock_website_login_manager_, mock_is_first_time_user_callback_.Get(),
- GURL(kFakeUrl), &trigger_context, mock_callback_.Get());
- EXPECT_TRUE(static_trigger_conditions_.has_results());
+ static_trigger_conditions.Update(mock_callback_.Get());
+ EXPECT_TRUE(static_trigger_conditions.has_results());
}
TEST_F(StaticTriggerConditionsTest, ScriptParameterMatches) {
@@ -82,20 +79,38 @@ TEST_F(StaticTriggerConditionsTest, ScriptParameterMatches) {
std::make_unique<ScriptParameters>(
std::map<std::string, std::string>{{"must_match", "matching_value"}}),
{}};
- static_trigger_conditions_.Init(
- &mock_website_login_manager_, mock_is_first_time_user_callback_.Get(),
- GURL(kFakeUrl), &trigger_context, mock_callback_.Get());
+ StaticTriggerConditions static_trigger_conditions = {
+ &fake_platform_delegate_, &trigger_context, GURL(kFakeUrl)};
ScriptParameterMatchProto must_match;
must_match.set_name("must_match");
must_match.set_value_equals("matching_value");
- EXPECT_TRUE(static_trigger_conditions_.script_parameter_matches(must_match));
+ EXPECT_TRUE(static_trigger_conditions.script_parameter_matches(must_match));
must_match.set_value_equals("not_matching_value");
- EXPECT_FALSE(static_trigger_conditions_.script_parameter_matches(must_match));
+ EXPECT_FALSE(static_trigger_conditions.script_parameter_matches(must_match));
// More comprehensive test in |script_parameters_unittest|.
}
+TEST_F(StaticTriggerConditionsTest, CachesFirstTimeUserFlag) {
+ TriggerContext trigger_context = {std::make_unique<ScriptParameters>(),
+ TriggerContext::Options{}};
+ StaticTriggerConditions static_trigger_conditions = {
+ &fake_platform_delegate_, &trigger_context, GURL(kFakeUrl)};
+ fake_platform_delegate_.is_first_time_user_ = true;
+ EXPECT_CALL(mock_website_login_manager_, OnGetLoginsForUrl)
+ .WillRepeatedly(
+ RunOnceCallback<1>(std::vector<WebsiteLoginManager::Login>{}));
+ static_trigger_conditions.Update(mock_callback_.Get());
+ EXPECT_TRUE(static_trigger_conditions.is_first_time_user());
+
+ fake_platform_delegate_.is_first_time_user_ = false;
+ EXPECT_TRUE(static_trigger_conditions.is_first_time_user());
+
+ static_trigger_conditions.Update(mock_callback_.Get());
+ EXPECT_FALSE(static_trigger_conditions.is_first_time_user());
+}
+
} // namespace
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script.h b/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script.h
index bf6b4f9b80a..54bf1bd3d82 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script.h
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script.h
@@ -33,7 +33,9 @@ class TriggerScript {
bool waiting_for_precondition_no_longer_true() const;
void waiting_for_precondition_no_longer_true(bool waiting);
- TriggerUIType trigger_ui_type() const { return proto_.trigger_ui_type(); }
+ TriggerScriptProto::TriggerUIType trigger_ui_type() const {
+ return proto_.trigger_ui_type();
+ }
private:
friend class TriggerScriptTest;
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc b/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc
index c7655f6594d..3da732423f1 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc
@@ -11,6 +11,7 @@
#include "components/autofill_assistant/browser/client_context.h"
#include "components/autofill_assistant/browser/features.h"
#include "components/autofill_assistant/browser/protocol_utils.h"
+#include "components/autofill_assistant/browser/starter_platform_delegate.h"
#include "components/autofill_assistant/browser/url_utils.h"
#include "components/ukm/content/source_url_recorder.h"
#include "components/version_info/version_info.h"
@@ -31,38 +32,46 @@ bool IsDialogOnboardingEnabled() {
namespace autofill_assistant {
TriggerScriptCoordinator::TriggerScriptCoordinator(
+ StarterPlatformDelegate* starter_delegate,
content::WebContents* web_contents,
- WebsiteLoginManager* website_login_manager,
- base::RepeatingCallback<bool(void)> is_first_time_user_callback,
std::unique_ptr<WebController> web_controller,
std::unique_ptr<ServiceRequestSender> request_sender,
const GURL& get_trigger_scripts_server,
std::unique_ptr<StaticTriggerConditions> static_trigger_conditions,
std::unique_ptr<DynamicTriggerConditions> dynamic_trigger_conditions,
- ukm::UkmRecorder* ukm_recorder)
+ ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId deeplink_ukm_source_id)
: content::WebContentsObserver(web_contents),
- website_login_manager_(website_login_manager),
- is_first_time_user_callback_(std::move(is_first_time_user_callback)),
+ starter_delegate_(starter_delegate),
+ ui_delegate_(starter_delegate->CreateTriggerScriptUiDelegate()),
request_sender_(std::move(request_sender)),
get_trigger_scripts_server_(get_trigger_scripts_server),
web_controller_(std::move(web_controller)),
static_trigger_conditions_(std::move(static_trigger_conditions)),
dynamic_trigger_conditions_(std::move(dynamic_trigger_conditions)),
- ukm_recorder_(ukm_recorder) {}
+ ukm_recorder_(ukm_recorder),
+ ukm_source_id_(deeplink_ukm_source_id) {}
TriggerScriptCoordinator::~TriggerScriptCoordinator() = default;
void TriggerScriptCoordinator::Start(
const GURL& deeplink_url,
- std::unique_ptr<TriggerContext> trigger_context) {
+ std::unique_ptr<TriggerContext> trigger_context,
+ base::OnceCallback<void(Metrics::TriggerScriptFinishedState,
+ std::unique_ptr<TriggerContext>,
+ absl::optional<TriggerScriptProto>)> callback) {
+ DCHECK(!callback_);
+ callback_ = std::move(callback);
deeplink_url_ = deeplink_url;
trigger_context_ = std::move(trigger_context);
- // Note: do not call ClientContext::Update here. We can only send the version
- // string in the ClientContext.
+ // Note: do not call ClientContext::Update here. We can only send the
+ // following approved fields:
ClientContextProto client_context;
client_context.mutable_chrome()->set_chrome_version(
version_info::GetProductNameAndVersionForUserAgent());
+ client_context.set_is_in_chrome_triggered(
+ trigger_context_->GetInChromeTriggered());
request_sender_->SendRequest(
get_trigger_scripts_server_,
@@ -77,25 +86,32 @@ void TriggerScriptCoordinator::OnGetTriggerScripts(
int http_status,
const std::string& response) {
if (http_status != net::HTTP_OK) {
- Stop(Metrics::LiteScriptFinishedState::LITE_SCRIPT_GET_ACTIONS_FAILED);
+ Stop(Metrics::TriggerScriptFinishedState::GET_ACTIONS_FAILED);
return;
}
trigger_scripts_.clear();
additional_allowed_domains_.clear();
- base::Optional<int> timeout_ms;
+ absl::optional<int> timeout_ms;
int check_interval_ms;
- if (!ProtocolUtils::ParseTriggerScripts(response, &trigger_scripts_,
- &additional_allowed_domains_,
- &check_interval_ms, &timeout_ms)) {
- Stop(Metrics::LiteScriptFinishedState::LITE_SCRIPT_GET_ACTIONS_PARSE_ERROR);
+ absl::optional<std::unique_ptr<ScriptParameters>> script_parameters;
+ if (!ProtocolUtils::ParseTriggerScripts(
+ response, &trigger_scripts_, &additional_allowed_domains_,
+ &check_interval_ms, &timeout_ms, &script_parameters)) {
+ Stop(Metrics::TriggerScriptFinishedState::GET_ACTIONS_PARSE_ERROR);
return;
}
if (trigger_scripts_.empty()) {
- Stop(Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_NO_TRIGGER_SCRIPT_AVAILABLE);
+ Stop(Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE);
return;
}
+ if (script_parameters.has_value()) {
+ // Note that we need to merge the new script parameters with the old set
+ // (the new values have precedence). This is because not all parameters were
+ // sent to the backend in the first place due to privacy considerations.
+ (*script_parameters)->MergeWith(trigger_context_->GetScriptParameters());
+ trigger_context_->SetScriptParameters(std::move(*script_parameters));
+ }
trigger_condition_check_interval_ =
base::TimeDelta::FromMilliseconds(check_interval_ms);
if (timeout_ms.has_value()) {
@@ -110,9 +126,11 @@ void TriggerScriptCoordinator::OnGetTriggerScripts(
remaining_trigger_condition_evaluations_ =
initial_trigger_condition_evaluations_;
- Metrics::RecordLiteScriptShownToUser(
- ukm_recorder_, web_contents(), UNSPECIFIED_TRIGGER_UI_TYPE,
- Metrics::LiteScriptShownToUser::LITE_SCRIPT_RUNNING);
+ Metrics::RecordTriggerScriptShownToUser(
+ ukm_recorder_, ukm_source_id_,
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
+ Metrics::TriggerScriptShownToUser::RUNNING);
+ ui_delegate_->Attach(this);
StartCheckingTriggerConditions();
}
@@ -121,21 +139,20 @@ void TriggerScriptCoordinator::PerformTriggerScriptAction(
switch (action) {
case TriggerScriptProto::NOT_NOW:
if (visible_trigger_script_ != -1) {
- Metrics::RecordLiteScriptShownToUser(
- ukm_recorder_, web_contents(), GetTriggerUiTypeForVisibleScript(),
- Metrics::LiteScriptShownToUser::LITE_SCRIPT_NOT_NOW);
+ Metrics::RecordTriggerScriptShownToUser(
+ ukm_recorder_, ukm_source_id_, GetTriggerUiTypeForVisibleScript(),
+ Metrics::TriggerScriptShownToUser::NOT_NOW);
trigger_scripts_[visible_trigger_script_]
->waiting_for_precondition_no_longer_true(true);
HideTriggerScript();
}
return;
case TriggerScriptProto::CANCEL_SESSION:
- Stop(Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_PROMPT_FAILED_CANCEL_SESSION);
+ Stop(Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_SESSION);
return;
case TriggerScriptProto::CANCEL_FOREVER:
- Stop(Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_PROMPT_FAILED_CANCEL_FOREVER);
+ starter_delegate_->SetProactiveHelpSettingEnabled(false);
+ Stop(Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_FOREVER);
return;
case TriggerScriptProto::SHOW_CANCEL_POPUP:
NOTREACHED();
@@ -145,9 +162,11 @@ void TriggerScriptCoordinator::PerformTriggerScriptAction(
NOTREACHED();
return;
}
- for (Observer& observer : observers_) {
- observer.OnOnboardingRequested(IsDialogOnboardingEnabled());
- }
+ waiting_for_onboarding_ = true;
+ starter_delegate_->ShowOnboarding(
+ IsDialogOnboardingEnabled(), *trigger_context_.get(),
+ base::BindOnce(&TriggerScriptCoordinator::OnOnboardingFinished,
+ weak_ptr_factory_.GetWeakPtr()));
return;
case TriggerScriptProto::UNDEFINED:
return;
@@ -158,52 +177,53 @@ void TriggerScriptCoordinator::OnOnboardingFinished(bool onboardingShown,
OnboardingResult result) {
// TODO(b/174445633): Replace -1 with a constant like kTriggerScriptNotVisible
// at all relevant places
+ waiting_for_onboarding_ = false;
if (visible_trigger_script_ != -1) {
- TriggerUIType trigger_ui_type = GetTriggerUiTypeForVisibleScript();
+ TriggerScriptProto::TriggerUIType trigger_ui_type =
+ GetTriggerUiTypeForVisibleScript();
if (onboardingShown) {
switch (result) {
case OnboardingResult::DISMISSED:
- Metrics::RecordLiteScriptOnboarding(
- ukm_recorder_, web_contents(), trigger_ui_type,
- Metrics::LiteScriptOnboarding::
- LITE_SCRIPT_ONBOARDING_SEEN_AND_DISMISSED);
+ Metrics::RecordTriggerScriptOnboarding(
+ ukm_recorder_, ukm_source_id_, trigger_ui_type,
+ Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_DISMISSED);
break;
case OnboardingResult::REJECTED:
- Metrics::RecordLiteScriptOnboarding(
- ukm_recorder_, web_contents(), trigger_ui_type,
- Metrics::LiteScriptOnboarding::
- LITE_SCRIPT_ONBOARDING_SEEN_AND_REJECTED);
+ Metrics::RecordTriggerScriptOnboarding(
+ ukm_recorder_, ukm_source_id_, trigger_ui_type,
+ Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_REJECTED);
break;
case OnboardingResult::NAVIGATION:
- Metrics::RecordLiteScriptOnboarding(
- ukm_recorder_, web_contents(), trigger_ui_type,
- Metrics::LiteScriptOnboarding::
- LITE_SCRIPT_ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION);
+ Metrics::RecordTriggerScriptOnboarding(
+ ukm_recorder_, ukm_source_id_, trigger_ui_type,
+ Metrics::TriggerScriptOnboarding::
+ ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION);
break;
case OnboardingResult::ACCEPTED:
- Metrics::RecordLiteScriptOnboarding(
- ukm_recorder_, web_contents(), trigger_ui_type,
- Metrics::LiteScriptOnboarding::
- LITE_SCRIPT_ONBOARDING_SEEN_AND_ACCEPTED);
+ Metrics::RecordTriggerScriptOnboarding(
+ ukm_recorder_, ukm_source_id_, trigger_ui_type,
+ Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED);
break;
}
} else {
- Metrics::RecordLiteScriptOnboarding(
- ukm_recorder_, web_contents(), trigger_ui_type,
- Metrics::LiteScriptOnboarding::
- LITE_SCRIPT_ONBOARDING_ALREADY_ACCEPTED);
+ Metrics::RecordTriggerScriptOnboarding(
+ ukm_recorder_, ukm_source_id_, trigger_ui_type,
+ Metrics::TriggerScriptOnboarding::ONBOARDING_ALREADY_ACCEPTED);
}
+ trigger_context_->SetOnboardingShown(onboardingShown);
if (result == OnboardingResult::ACCEPTED) {
// Do not hide the trigger script here, to facilitate a smooth
// transition to the regular flow.
StopCheckingTriggerConditions();
- NotifyOnTriggerScriptFinished(
- trigger_ui_type,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SUCCEEDED);
+ starter_delegate_->SetOnboardingAccepted(true);
+ ui_delegate_->Detach();
+ RunCallback(trigger_ui_type,
+ Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED,
+ trigger_scripts_[visible_trigger_script_]->AsProto());
} else if (!IsDialogOnboardingEnabled()) {
- Stop(Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_BOTTOMSHEET_ONBOARDING_REJECTED);
+ Stop(
+ Metrics::TriggerScriptFinishedState::BOTTOMSHEET_ONBOARDING_REJECTED);
}
}
}
@@ -211,12 +231,12 @@ void TriggerScriptCoordinator::OnOnboardingFinished(bool onboardingShown,
void TriggerScriptCoordinator::OnBottomSheetClosedWithSwipe() {
if (visible_trigger_script_ == -1) {
NOTREACHED();
- Stop(Metrics::LiteScriptFinishedState::LITE_SCRIPT_UNKNOWN_FAILURE);
+ Stop(Metrics::TriggerScriptFinishedState::UNKNOWN_FAILURE);
return;
}
- Metrics::RecordLiteScriptShownToUser(
- ukm_recorder_, web_contents(), GetTriggerUiTypeForVisibleScript(),
- Metrics::LiteScriptShownToUser::LITE_SCRIPT_SWIPE_DISMISSED);
+ Metrics::RecordTriggerScriptShownToUser(
+ ukm_recorder_, ukm_source_id_, GetTriggerUiTypeForVisibleScript(),
+ Metrics::TriggerScriptShownToUser::SWIPE_DISMISSED);
PerformTriggerScriptAction(trigger_scripts_[visible_trigger_script_]
->AsProto()
.on_swipe_to_dismiss());
@@ -241,34 +261,37 @@ void TriggerScriptCoordinator::OnKeyboardVisibilityChanged(bool visible) {
void TriggerScriptCoordinator::OnTriggerScriptShown(bool success) {
if (!success) {
- Stop(Metrics::LiteScriptFinishedState::LITE_SCRIPT_FAILED_TO_SHOW);
+ Stop(Metrics::TriggerScriptFinishedState::FAILED_TO_SHOW);
return;
}
+ // Note: do not update the static trigger conditions here! We should ignore
+ // this particular update to avoid hiding the first-time trigger script
+ // immediately after showing it.
+ starter_delegate_->SetIsFirstTimeUser(false);
}
-void TriggerScriptCoordinator::OnProactiveHelpSettingChanged(
- bool proactive_help_enabled) {
- if (!proactive_help_enabled) {
- Stop(Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_DISABLED_PROACTIVE_HELP_SETTING);
+void TriggerScriptCoordinator::Stop(Metrics::TriggerScriptFinishedState state) {
+ if (!callback_ || !trigger_context_) {
return;
}
-}
-
-void TriggerScriptCoordinator::Stop(Metrics::LiteScriptFinishedState state) {
VLOG(2) << "Stopping with status " << state;
- TriggerUIType trigger_ui_type = GetTriggerUiTypeForVisibleScript();
+ TriggerScriptProto::TriggerUIType trigger_ui_type =
+ GetTriggerUiTypeForVisibleScript();
HideTriggerScript();
StopCheckingTriggerConditions();
- NotifyOnTriggerScriptFinished(trigger_ui_type, state);
-}
+ ui_delegate_->Detach();
-void TriggerScriptCoordinator::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
+ if (waiting_for_onboarding_ &&
+ state == Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE) {
+ starter_delegate_->HideOnboarding();
+ Metrics::RecordTriggerScriptOnboarding(
+ ukm_recorder_, ukm_source_id_, trigger_ui_type,
+ Metrics::TriggerScriptOnboarding::
+ ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION);
+ }
+ waiting_for_onboarding_ = false;
-void TriggerScriptCoordinator::RemoveObserver(const Observer* observer) {
- observers_.RemoveObserver(observer);
+ RunCallback(trigger_ui_type, state, /* trigger_script = */ absl::nullopt);
}
void TriggerScriptCoordinator::DidFinishNavigation(
@@ -288,13 +311,13 @@ void TriggerScriptCoordinator::DidFinishNavigation(
// (e.g., network connection lost). This will cancel the current trigger
// script session.
if (navigation_handle->IsErrorPage()) {
- Stop(Metrics::LiteScriptFinishedState::LITE_SCRIPT_NAVIGATION_ERROR);
+ Stop(Metrics::TriggerScriptFinishedState::NAVIGATION_ERROR);
return;
}
// The user has navigated away from the target domain. This will cancel the
// current trigger script session.
- if (!url_utils::IsInDomainOrSubDomain(GetCurrentURL(), deeplink_url_) &&
+ if (!url_utils::IsSamePublicSuffixDomain(GetCurrentURL(), deeplink_url_) &&
!url_utils::IsInDomainOrSubDomain(GetCurrentURL(),
additional_allowed_domains_)) {
#ifndef NDEBUG
@@ -305,10 +328,11 @@ void TriggerScriptCoordinator::DidFinishNavigation(
VLOG(2) << "\t" << domain;
}
#endif
- Stop(Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_NAVIGATE);
+ Stop(Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE);
return;
}
+ ukm_source_id_ = ukm::GetSourceIdForWebContentsDocument(web_contents());
dynamic_trigger_conditions_->SetURL(GetCurrentURL());
RunOutOfScheduleTriggerConditionCheck();
}
@@ -331,6 +355,14 @@ void TriggerScriptCoordinator::OnTabInteractabilityChanged(bool interactable) {
OnEffectiveVisibilityChanged();
}
+TriggerContext& TriggerScriptCoordinator::GetTriggerContext() const {
+ return *trigger_context_;
+}
+
+const GURL& TriggerScriptCoordinator::GetDeeplink() const {
+ return deeplink_url_;
+}
+
void TriggerScriptCoordinator::OnEffectiveVisibilityChanged() {
bool visible = web_contents_visible_ && web_contents_interactable_;
if (visible) {
@@ -339,29 +371,31 @@ void TriggerScriptCoordinator::OnEffectiveVisibilityChanged() {
// script that was shown before is still available, hence we need to fetch
// it again.
DCHECK(visible_trigger_script_ == -1);
+ // While the tab was invisible, the user may have disabled proactive help.
+ if (!starter_delegate_->GetProactiveHelpSettingEnabled()) {
+ Stop(
+ Metrics::TriggerScriptFinishedState::DISABLED_PROACTIVE_HELP_SETTING);
+ return;
+ }
VLOG(2) << "Restarting after tab became visible again";
- Start(deeplink_url_, std::move(trigger_context_));
+ Start(deeplink_url_, std::move(trigger_context_), std::move(callback_));
} else {
// Hide UI on tab switch.
VLOG(2) << "Pausing after tab became invisible or non-interactable";
StopCheckingTriggerConditions();
HideTriggerScript();
}
-
- for (Observer& observer : observers_) {
- observer.OnVisibilityChanged(visible);
- }
}
void TriggerScriptCoordinator::WebContentsDestroyed() {
if (!finished_state_recorded_) {
- Metrics::RecordLiteScriptFinished(
- ukm_recorder_, web_contents(), GetTriggerUiTypeForVisibleScript(),
+ Metrics::RecordTriggerScriptFinished(
+ ukm_recorder_, ukm_source_id_, GetTriggerUiTypeForVisibleScript(),
visible_trigger_script_ == -1
- ? Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_WEB_CONTENTS_DESTROYED_WHILE_INVISIBLE
- : Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_WEB_CONTENTS_DESTROYED_WHILE_VISIBLE);
+ ? Metrics::TriggerScriptFinishedState::
+ WEB_CONTENTS_DESTROYED_WHILE_INVISIBLE
+ : Metrics::TriggerScriptFinishedState::
+ WEB_CONTENTS_DESTROYED_WHILE_VISIBLE);
finished_state_recorded_ = true;
}
}
@@ -373,9 +407,7 @@ void TriggerScriptCoordinator::StartCheckingTriggerConditions() {
dynamic_trigger_conditions_->AddSelectorsFromTriggerScript(
trigger_script->AsProto());
}
- static_trigger_conditions_->Init(
- website_login_manager_, is_first_time_user_callback_, deeplink_url_,
- trigger_context_.get(),
+ static_trigger_conditions_->Update(
base::BindOnce(&TriggerScriptCoordinator::CheckDynamicTriggerConditions,
weak_ptr_factory_.GetWeakPtr()));
}
@@ -403,13 +435,11 @@ void TriggerScriptCoordinator::ShowTriggerScript(int index) {
// GetTriggerUiTypeForVisibleScript() requires visible_trigger_script_ to be
// set first thing.
- Metrics::RecordLiteScriptShownToUser(
- ukm_recorder_, web_contents(), GetTriggerUiTypeForVisibleScript(),
- Metrics::LiteScriptShownToUser::LITE_SCRIPT_SHOWN_TO_USER);
- auto proto = trigger_scripts_[index]->AsProto().user_interface();
- for (Observer& observer : observers_) {
- observer.OnTriggerScriptShown(proto);
- }
+ Metrics::RecordTriggerScriptShownToUser(
+ ukm_recorder_, ukm_source_id_, GetTriggerUiTypeForVisibleScript(),
+ Metrics::TriggerScriptShownToUser::SHOWN_TO_USER);
+ ui_delegate_->ShowTriggerScript(
+ trigger_scripts_[index]->AsProto().user_interface());
}
void TriggerScriptCoordinator::HideTriggerScript() {
@@ -421,11 +451,13 @@ void TriggerScriptCoordinator::HideTriggerScript() {
// time a script was invisible is reset.
remaining_trigger_condition_evaluations_ =
initial_trigger_condition_evaluations_;
- static_trigger_conditions_->set_is_first_time_user(false);
visible_trigger_script_ = -1;
- for (Observer& observer : observers_) {
- observer.OnTriggerScriptHidden();
- }
+ ui_delegate_->HideTriggerScript();
+
+ // Now that the trigger script is hidden, we may need to update the
+ // static trigger conditions. This is done specifically to account for
+ // the |is_first_time_user| flag that might have changed.
+ static_trigger_conditions_->Update(base::DoNothing());
}
void TriggerScriptCoordinator::OnDynamicTriggerConditionsEvaluated(
@@ -450,10 +482,10 @@ void TriggerScriptCoordinator::OnDynamicTriggerConditionsEvaluated(
// Trigger condition for the currently shown trigger script is no longer true.
if (visible_trigger_script_ != -1 &&
!evaluated_trigger_conditions[visible_trigger_script_]) {
- Metrics::RecordLiteScriptShownToUser(
- ukm_recorder_, web_contents(), GetTriggerUiTypeForVisibleScript(),
- Metrics::LiteScriptShownToUser::
- LITE_SCRIPT_HIDE_ON_TRIGGER_CONDITION_NO_LONGER_TRUE);
+ Metrics::RecordTriggerScriptShownToUser(
+ ukm_recorder_, ukm_source_id_, GetTriggerUiTypeForVisibleScript(),
+ Metrics::TriggerScriptShownToUser::
+ HIDE_ON_TRIGGER_CONDITION_NO_LONGER_TRUE);
HideTriggerScript();
// Do not return here: a different trigger script may have become eligible
// at the same time.
@@ -501,8 +533,7 @@ void TriggerScriptCoordinator::OnDynamicTriggerConditionsEvaluated(
remaining_trigger_condition_evaluations_--;
}
if (remaining_trigger_condition_evaluations_ == 0) {
- Stop(Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT);
+ Stop(Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT);
return;
}
content::GetUIThreadTaskRunner({})->PostDelayedTask(
@@ -516,27 +547,28 @@ void TriggerScriptCoordinator::RunOutOfScheduleTriggerConditionCheck() {
OnDynamicTriggerConditionsEvaluated(/* is_out_of_schedule = */ true);
}
-void TriggerScriptCoordinator::NotifyOnTriggerScriptFinished(
- TriggerUIType trigger_ui_type,
- Metrics::LiteScriptFinishedState state) {
+void TriggerScriptCoordinator::RunCallback(
+ TriggerScriptProto::TriggerUIType trigger_ui_type,
+ Metrics::TriggerScriptFinishedState state,
+ const absl::optional<TriggerScriptProto>& trigger_script) {
+ DCHECK(callback_);
+ DCHECK(trigger_context_);
if (!finished_state_recorded_) {
finished_state_recorded_ = true;
- Metrics::RecordLiteScriptFinished(ukm_recorder_, web_contents(),
- trigger_ui_type, state);
- }
-
- for (Observer& observer : observers_) {
- observer.OnTriggerScriptFinished(state);
+ Metrics::RecordTriggerScriptFinished(ukm_recorder_, ukm_source_id_,
+ trigger_ui_type, state);
}
+ trigger_context_->SetTriggerUIType(trigger_ui_type);
+ std::move(callback_).Run(state, std::move(trigger_context_), trigger_script);
}
-TriggerUIType TriggerScriptCoordinator::GetTriggerUiTypeForVisibleScript()
- const {
+TriggerScriptProto::TriggerUIType
+TriggerScriptCoordinator::GetTriggerUiTypeForVisibleScript() const {
if (visible_trigger_script_ >= 0 &&
static_cast<size_t>(visible_trigger_script_) < trigger_scripts_.size()) {
return trigger_scripts_[visible_trigger_script_]->trigger_ui_type();
}
- return UNSPECIFIED_TRIGGER_UI_TYPE;
+ return TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE;
}
GURL TriggerScriptCoordinator::GetCurrentURL() const {
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h b/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h
index b66abab4103..c6dd1f351d0 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
@@ -27,50 +28,66 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace autofill_assistant {
+class StarterPlatformDelegate;
// Fetches and coordinates trigger scripts for a specific url. Similar in scope
// and responsibility to a regular |controller|, but for trigger scripts instead
// of regular scripts.
class TriggerScriptCoordinator : public content::WebContentsObserver {
public:
- // Observer interface for listeners interested in status updates of this
- // coordinator.
- class Observer : public base::CheckedObserver {
+ // Delegate that shows platform-specific UI.
+ class UiDelegate {
public:
- Observer() = default;
- ~Observer() override = default;
-
- virtual void OnTriggerScriptShown(const TriggerScriptUIProto& proto) = 0;
- virtual void OnTriggerScriptHidden() = 0;
- virtual void OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState state) = 0;
- virtual void OnVisibilityChanged(bool visible) = 0;
- virtual void OnOnboardingRequested(bool use_dialog_onboarding) = 0;
+ UiDelegate() = default;
+ virtual ~UiDelegate() = default;
+
+ // Displays |proto| to the user.
+ virtual void ShowTriggerScript(const TriggerScriptUIProto& proto) = 0;
+ // Hides the currently shown trigger script, if any.
+ virtual void HideTriggerScript() = 0;
+ // Attaches the UiDelegate to |trigger_script_coordinator|. The UiDelegate
+ // should notify the coordinator of relevant events.
+ virtual void Attach(
+ TriggerScriptCoordinator* trigger_script_coordinator) = 0;
+ // Detaches the UiDelegate, if attached.
+ virtual void Detach() = 0;
};
// |web_contents| must outlive this instance.
TriggerScriptCoordinator(
+ StarterPlatformDelegate* starter_delegate,
content::WebContents* web_contents,
- WebsiteLoginManager* website_login_manager,
- base::RepeatingCallback<bool(void)> is_first_time_user_callback,
std::unique_ptr<WebController> web_controller,
std::unique_ptr<ServiceRequestSender> request_sender,
const GURL& get_trigger_scripts_server,
std::unique_ptr<StaticTriggerConditions> static_trigger_conditions,
std::unique_ptr<DynamicTriggerConditions> dynamic_trigger_conditions,
- ukm::UkmRecorder* ukm_recorder);
+ ukm::UkmRecorder* ukm_recorder,
+ ukm::SourceId deeplink_ukm_source_id);
~TriggerScriptCoordinator() override;
TriggerScriptCoordinator(const TriggerScriptCoordinator&) = delete;
TriggerScriptCoordinator& operator=(const TriggerScriptCoordinator&) = delete;
// Retrieves all trigger scripts for |deeplink_url| and starts evaluating
- // their trigger conditions. Observers will be notified of all relevant status
- // updates.
+ // their trigger conditions. Invokes |callback| with the result. If a trigger
+ // script was shown to the user and accepted by the user, this will also
+ // return the shown trigger script and the potentially modified trigger
+ // context.
void Start(const GURL& deeplink_url,
- std::unique_ptr<TriggerContext> trigger_context);
+ std::unique_ptr<TriggerContext> trigger_context,
+ base::OnceCallback<void(
+ Metrics::TriggerScriptFinishedState result,
+ std::unique_ptr<TriggerContext> trigger_context,
+ absl::optional<TriggerScriptProto> trigger_script)> callback);
+
+ // Stops the currently running trigger script. Hides any currently shown UI
+ // (both trigger script UI and onboarding, if applicable) and returns |state|
+ // as the reason for stopping in the pending callback.
+ void Stop(Metrics::TriggerScriptFinishedState state);
// Performs |action|. This is usually invoked by the UI as a result of user
// interactions.
@@ -97,14 +114,11 @@ class TriggerScriptCoordinator : public content::WebContentsObserver {
// tab-switcher.
void OnTabInteractabilityChanged(bool interactable);
- // Called when the proactive help Chrome setting has changed.
- void OnProactiveHelpSettingChanged(bool proactive_help_enabled);
-
- void AddObserver(Observer* observer);
- void RemoveObserver(const Observer* observer);
+ // Access to the trigger context associated with this coordinator.
+ TriggerContext& GetTriggerContext() const;
- // Called when onboarding for trigger script is finished.
- void OnOnboardingFinished(bool onboardingShown, OnboardingResult result);
+ // Returns the deeplink that this coordinator was started on.
+ const GURL& GetDeeplink() const;
private:
friend class TriggerScriptCoordinatorTest;
@@ -122,31 +136,36 @@ class TriggerScriptCoordinator : public content::WebContentsObserver {
void CheckDynamicTriggerConditions();
void OnDynamicTriggerConditionsEvaluated(bool is_out_of_schedule);
void OnGetTriggerScripts(int http_status, const std::string& response);
- void Stop(Metrics::LiteScriptFinishedState state);
GURL GetCurrentURL() const;
void OnEffectiveVisibilityChanged();
- void OnboardingRequested();
+ void OnOnboardingFinished(bool onboardingShown, OnboardingResult result);
// Can be invoked to trigger an immediate check of the trigger condition,
// reusing the dynamic results of the last time. Does nothing if there are no
// previous results to reuse.
void RunOutOfScheduleTriggerConditionCheck();
- void NotifyOnTriggerScriptFinished(TriggerUIType trigger_ui_type,
- Metrics::LiteScriptFinishedState state);
+ void RunCallback(TriggerScriptProto::TriggerUIType trigger_ui_type,
+ Metrics::TriggerScriptFinishedState state,
+ const absl::optional<TriggerScriptProto>& trigger_script);
// Value of trigger_ui_type for the currently visible script, if there is one.
//
// When recording a hide or stop action, be sure to capture the type before
// hiding the script.
- TriggerUIType GetTriggerUiTypeForVisibleScript() const;
+ TriggerScriptProto::TriggerUIType GetTriggerUiTypeForVisibleScript() const;
- // Used to query login information for the current webcontents.
- WebsiteLoginManager* website_login_manager_;
+ // Delegate used to access settings and show the onboarding.
+ StarterPlatformDelegate* starter_delegate_ = nullptr;
- // Callback that can be used to query whether a user has seen the trigger
- // script UI at least once or not.
- base::RepeatingCallback<bool(void)> is_first_time_user_callback_;
+ // Delegate used to show and hide the UI.
+ std::unique_ptr<UiDelegate> ui_delegate_;
+
+ // The callback to run once the current trigger script flow has finished.
+ base::OnceCallback<void(Metrics::TriggerScriptFinishedState,
+ std::unique_ptr<TriggerContext> trigger_context,
+ absl::optional<TriggerScriptProto>)>
+ callback_;
// The original deeplink to request trigger scripts for.
GURL deeplink_url_;
@@ -186,9 +205,6 @@ class TriggerScriptCoordinator : public content::WebContentsObserver {
// The web controller to evaluate element conditions.
std::unique_ptr<WebController> web_controller_;
- // The list of currently registered observers.
- base::ObserverList<Observer> observers_;
-
// The list of trigger scripts that were fetched from the backend.
std::vector<std::unique_ptr<TriggerScript>> trigger_scripts_;
@@ -201,7 +217,7 @@ class TriggerScriptCoordinator : public content::WebContentsObserver {
base::TimeDelta::FromMilliseconds(1000);
// The number of times the trigger condition may be evaluated. If this reaches
- // 0, the trigger script stops with |LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT|.
+ // 0, the trigger script stops with |TRIGGER_CONDITION_TIMEOUT|.
// -1 means no limit.
//
// This number is defined by the timeout (specified in proto) divided by
@@ -213,12 +229,21 @@ class TriggerScriptCoordinator : public content::WebContentsObserver {
// |remaining_trigger_condition_evaluations_|.
int64_t initial_trigger_condition_evaluations_ = -1;
- // The UKM recorder used for metrics.
+ // The UKM recorder to use for metrics.
ukm::UkmRecorder* const ukm_recorder_;
- // Flag to ensure that we only get one LiteScriptFinished event per run.
+ // The UKM source id to record. This can change over time as the user
+ // navigates around, but will always point to a source-id on a supported
+ // domain. If the user leaves the supported domain, this will instead point to
+ // the last URL still on the supported domain.
+ ukm::SourceId ukm_source_id_;
+
+ // Flag to ensure that we only get one TriggerScriptFinished event per run.
bool finished_state_recorded_ = false;
+ // True while the onboarding is being displayed.
+ bool waiting_for_onboarding_ = false;
+
base::WeakPtrFactory<TriggerScriptCoordinator> weak_ptr_factory_{this};
};
diff --git a/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc b/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc
index 13eabcf131e..ed3f2fb9d83 100644
--- a/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc
@@ -9,12 +9,14 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
+#include "components/autofill_assistant/browser/fake_starter_platform_delegate.h"
#include "components/autofill_assistant/browser/features.h"
#include "components/autofill_assistant/browser/mock_website_login_manager.h"
#include "components/autofill_assistant/browser/service/mock_service_request_sender.h"
#include "components/autofill_assistant/browser/test_util.h"
#include "components/autofill_assistant/browser/trigger_scripts/mock_dynamic_trigger_conditions.h"
#include "components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.h"
+#include "components/autofill_assistant/browser/trigger_scripts/mock_trigger_script_ui_delegate.h"
#include "components/autofill_assistant/browser/web/mock_web_controller.h"
#include "components/ukm/content/source_url_recorder.h"
#include "components/ukm/test_ukm_recorder.h"
@@ -29,10 +31,12 @@ namespace autofill_assistant {
using ::base::test::RunOnceCallback;
using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::ElementsAreArray;
using ::testing::Eq;
-using ::testing::NaggyMock;
using ::testing::NiceMock;
using ::testing::Return;
+using ::testing::UnorderedElementsAre;
using ::testing::UnorderedElementsAreArray;
std::unique_ptr<base::test::ScopedFeatureList> CreateScopedFeatureList(
@@ -44,16 +48,6 @@ std::unique_ptr<base::test::ScopedFeatureList> CreateScopedFeatureList(
return scoped_feature_list;
}
-class MockObserver : public TriggerScriptCoordinator::Observer {
- public:
- MOCK_METHOD1(OnTriggerScriptShown, void(const TriggerScriptUIProto& proto));
- MOCK_METHOD0(OnTriggerScriptHidden, void());
- MOCK_METHOD1(OnTriggerScriptFinished,
- void(Metrics::LiteScriptFinishedState state));
- MOCK_METHOD1(OnVisibilityChanged, void(bool visible));
- MOCK_METHOD1(OnOnboardingRequested, void(bool use_dialog_onboarding));
-};
-
const char kFakeDeepLink[] = "https://example.com/q?data=test";
const char kFakeServerUrl[] =
"https://www.fake.backend.com/trigger_script_server";
@@ -83,25 +77,32 @@ class TriggerScriptCoordinatorTest : public content::RenderViewHostTestHarness {
auto mock_dynamic_trigger_conditions =
std::make_unique<NiceMock<MockDynamicTriggerConditions>>();
mock_dynamic_trigger_conditions_ = mock_dynamic_trigger_conditions.get();
+ auto mock_ui_delegate =
+ std::make_unique<NiceMock<MockTriggerScriptUiDelegate>>();
+ mock_ui_delegate_ = mock_ui_delegate.get();
+ fake_platform_delegate_.trigger_script_ui_delegate_ =
+ std::move(mock_ui_delegate);
ON_CALL(*mock_static_trigger_conditions, has_results)
.WillByDefault(Return(true));
+ ON_CALL(*mock_static_trigger_conditions_, Update)
+ .WillByDefault(RunOnceCallback<0>());
ON_CALL(*mock_dynamic_trigger_conditions, HasResults)
.WillByDefault(Return(true));
-
- coordinator_ = std::make_unique<TriggerScriptCoordinator>(
- web_contents(), &mock_website_login_manager_,
- mock_is_first_time_user_callback_.Get(), std::move(mock_web_controller),
- std::move(mock_request_sender), GURL(kFakeServerUrl),
- std::move(mock_static_trigger_conditions),
- std::move(mock_dynamic_trigger_conditions), &ukm_recorder_);
- coordinator_->AddObserver(&mock_observer_);
+ ON_CALL(*mock_ui_delegate_, ShowTriggerScript).WillByDefault([&]() {
+ coordinator_->OnTriggerScriptShown(true);
+ });
SimulateNavigateToUrl(GURL(kFakeDeepLink));
+ coordinator_ = std::make_unique<TriggerScriptCoordinator>(
+ &fake_platform_delegate_, web_contents(),
+ std::move(mock_web_controller), std::move(mock_request_sender),
+ GURL(kFakeServerUrl), std::move(mock_static_trigger_conditions),
+ std::move(mock_dynamic_trigger_conditions), &ukm_recorder_,
+ ukm::GetSourceIdForWebContentsDocument(web_contents()));
}
void TearDown() override {
- coordinator_->RemoveObserver(&mock_observer_);
coordinator_.reset();
RenderViewHostTestHarness::TearDown();
}
@@ -121,13 +122,13 @@ class TriggerScriptCoordinatorTest : public content::RenderViewHostTestHarness {
content::WebContentsTester::For(web_contents())->TestSetIsLoading(false);
}
- void AssertRecordedFinishedState(TriggerUIType type,
- Metrics::LiteScriptFinishedState state) {
+ void AssertRecordedFinishedState(TriggerScriptProto::TriggerUIType type,
+ Metrics::TriggerScriptFinishedState state,
+ GURL url = GURL(kFakeDeepLink)) {
auto entries =
ukm_recorder_.GetEntriesByName("AutofillAssistant.LiteScriptFinished");
ASSERT_THAT(entries.size(), Eq(1u));
- ukm_recorder_.ExpectEntrySourceHasUrl(
- entries[0], web_contents()->GetLastCommittedURL());
+ ukm_recorder_.ExpectEntrySourceHasUrl(entries[0], url);
EXPECT_EQ(*ukm_recorder_.GetEntryMetric(entries[0], "TriggerUIType"),
static_cast<int64_t>(type));
EXPECT_EQ(*ukm_recorder_.GetEntryMetric(entries[0], "LiteScriptFinished"),
@@ -136,13 +137,12 @@ class TriggerScriptCoordinatorTest : public content::RenderViewHostTestHarness {
// Make sure that an UKM entry with |state| has been recorded
// |expected_times|, and has been associated each time with |type|.
- void AssertRecordedShownToUserState(TriggerUIType type,
- Metrics::LiteScriptShownToUser state,
+ void AssertRecordedShownToUserState(TriggerScriptProto::TriggerUIType type,
+ Metrics::TriggerScriptShownToUser state,
int expected_times) {
auto entries = ukm_recorder_.GetEntriesByName(
"AutofillAssistant.LiteScriptShownToUser");
- ukm_recorder_.ExpectEntrySourceHasUrl(
- entries[0], web_contents()->GetLastCommittedURL());
+ ukm_recorder_.ExpectEntrySourceHasUrl(entries[0], GURL(kFakeDeepLink));
int actual_times = 0;
for (const auto* entry : entries) {
if (*ukm_recorder_.GetEntryMetric(entry, "LiteScriptShownToUser") ==
@@ -155,14 +155,13 @@ class TriggerScriptCoordinatorTest : public content::RenderViewHostTestHarness {
EXPECT_EQ(expected_times, actual_times);
}
- void AssertRecordedLiteScriptOnboardingState(
- TriggerUIType type,
- Metrics::LiteScriptOnboarding state,
+ void AssertRecordedTriggerScriptOnboardingState(
+ TriggerScriptProto::TriggerUIType type,
+ Metrics::TriggerScriptOnboarding state,
int expected_times) {
auto entries = ukm_recorder_.GetEntriesByName(
"AutofillAssistant.LiteScriptOnboarding");
- ukm_recorder_.ExpectEntrySourceHasUrl(
- entries[0], web_contents()->GetLastCommittedURL());
+ ukm_recorder_.ExpectEntrySourceHasUrl(entries[0], GURL(kFakeDeepLink));
int actual_times = 0;
for (const auto* entry : entries) {
if (*ukm_recorder_.GetEntryMetric(entry, "LiteScriptOnboarding") ==
@@ -179,10 +178,13 @@ class TriggerScriptCoordinatorTest : public content::RenderViewHostTestHarness {
ukm::TestAutoSetUkmRecorder ukm_recorder_;
NiceMock<MockServiceRequestSender>* mock_request_sender_;
NiceMock<MockWebController>* mock_web_controller_;
- NiceMock<MockWebsiteLoginManager> mock_website_login_manager_;
- base::MockCallback<base::RepeatingCallback<bool(void)>>
- mock_is_first_time_user_callback_;
- NaggyMock<MockObserver> mock_observer_;
+ base::MockCallback<base::OnceCallback<void(
+ Metrics::TriggerScriptFinishedState result,
+ std::unique_ptr<TriggerContext> trigger_context,
+ absl::optional<TriggerScriptProto> trigger_script)>>
+ mock_callback_;
+ FakeStarterPlatformDelegate fake_platform_delegate_;
+ NiceMock<MockTriggerScriptUiDelegate>* mock_ui_delegate_;
std::unique_ptr<TriggerScriptCoordinator> coordinator_;
NiceMock<MockStaticTriggerConditions>* mock_static_trigger_conditions_;
NiceMock<MockDynamicTriggerConditions>* mock_dynamic_trigger_conditions_;
@@ -214,7 +216,7 @@ TEST_F(TriggerScriptCoordinatorTest, StartSendsOnlyApprovedFields) {
EXPECT_THAT(request.url(), Eq(kFakeDeepLink));
std::map<std::string, std::string> params;
- for (const auto& param : request.debug_script_parameters()) {
+ for (const auto& param : request.script_parameters()) {
params[param.name()] = param.value();
}
EXPECT_THAT(params, UnorderedElementsAreArray(expected_script_params));
@@ -223,6 +225,7 @@ TEST_F(TriggerScriptCoordinatorTest, StartSendsOnlyApprovedFields) {
ClientContextProto expected_client_context;
expected_client_context.mutable_chrome()->set_chrome_version(
version_info::GetProductNameAndVersionForUserAgent());
+ expected_client_context.set_is_in_chrome_triggered(true);
EXPECT_THAT(request.client_context(), Eq(expected_client_context));
});
@@ -234,44 +237,49 @@ TEST_F(TriggerScriptCoordinatorTest, StartSendsOnlyApprovedFields) {
/* is_cct = */ true,
/* onboarding_shown = */ true,
/* is_direct_action = */ true,
- /* initial_url = */ "https://www.example.com"));
+ /* initial_url = */ "https://www.example.com",
+ /* is_in_chrome_triggered = */ true),
+ mock_callback_.Get());
}
TEST_F(TriggerScriptCoordinatorTest, StopOnBackendRequestFailed) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_FORBIDDEN, ""));
EXPECT_CALL(
- mock_observer_,
- OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_GET_ACTIONS_FAILED));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::GET_ACTIONS_FAILED, _, _));
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
AssertRecordedFinishedState(
- UNSPECIFIED_TRIGGER_UI_TYPE,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_GET_ACTIONS_FAILED);
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
+ Metrics::TriggerScriptFinishedState::GET_ACTIONS_FAILED);
}
TEST_F(TriggerScriptCoordinatorTest, StopOnParsingError) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, "invalid"));
- EXPECT_CALL(mock_observer_,
- OnTriggerScriptFinished(Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_GET_ACTIONS_PARSE_ERROR));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::GET_ACTIONS_PARSE_ERROR, _, _));
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
AssertRecordedFinishedState(
- UNSPECIFIED_TRIGGER_UI_TYPE,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_GET_ACTIONS_PARSE_ERROR);
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
+ Metrics::TriggerScriptFinishedState::GET_ACTIONS_PARSE_ERROR);
}
TEST_F(TriggerScriptCoordinatorTest, StopOnNoTriggerScriptsAvailable) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, ""));
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_NO_TRIGGER_SCRIPT_AVAILABLE));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
- AssertRecordedFinishedState(UNSPECIFIED_TRIGGER_UI_TYPE,
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_NO_TRIGGER_SCRIPT_AVAILABLE);
+ EXPECT_CALL(
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE, _,
+ _));
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
+ AssertRecordedFinishedState(
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
+ Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE);
}
TEST_F(TriggerScriptCoordinatorTest, StartChecksStaticAndDynamicConditions) {
@@ -287,8 +295,6 @@ TEST_F(TriggerScriptCoordinatorTest, StartChecksStaticAndDynamicConditions) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, ClearSelectors).Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
AddSelectorsFromTriggerScript(response.trigger_scripts(0)))
@@ -297,7 +303,8 @@ TEST_F(TriggerScriptCoordinatorTest, StartChecksStaticAndDynamicConditions) {
.WillByDefault(RunOnceCallback<1>());
ON_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillByDefault(Return(false));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
@@ -315,28 +322,28 @@ TEST_F(TriggerScriptCoordinatorTest, ShowAndHideTriggerScript) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
+
ON_CALL(*mock_dynamic_trigger_conditions_, OnUpdate(mock_web_controller_, _))
.WillByDefault(RunOnceCallback<1>());
ON_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillByDefault(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
- // Condition stays true, no further notification should be sent to observers.
+ // Condition stays true, trigger script should not be hidden.
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
- // Condition turns false, trigger script is hidden.
+ // Condition turns false, trigger script should be hidden.
ON_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillByDefault(Return(false));
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
- // Condition is true again, trigger script is shown again.
+ // Condition is true again, trigger script should be shown again.
ON_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillByDefault(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
}
@@ -350,20 +357,19 @@ TEST_F(TriggerScriptCoordinatorTest, PauseAndResumeOnTabVisibilityChange) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
+
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillOnce(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
// When a tab becomes invisible, the trigger script is hidden and trigger
// condition evaluation is suspended.
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(1);
- EXPECT_CALL(mock_observer_, OnVisibilityChanged(false)).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.Times(0);
@@ -373,15 +379,12 @@ TEST_F(TriggerScriptCoordinatorTest, PauseAndResumeOnTabVisibilityChange) {
// fetched again.
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillOnce(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- EXPECT_CALL(mock_observer_, OnVisibilityChanged(true)).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
SimulateWebContentsVisibilityChanged(content::Visibility::VISIBLE);
}
@@ -395,23 +398,22 @@ TEST_F(TriggerScriptCoordinatorTest, PerformTriggerScriptActionNotNow) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
ON_CALL(*mock_dynamic_trigger_conditions_, OnUpdate(mock_web_controller_, _))
.WillByDefault(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
coordinator_->PerformTriggerScriptAction(TriggerScriptProto::NOT_NOW);
// Despite the trigger condition still being true, the trigger script is not
// shown again until the condition has become first false and then true again.
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(0);
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(0);
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
@@ -420,7 +422,7 @@ TEST_F(TriggerScriptCoordinatorTest, PerformTriggerScriptActionNotNow) {
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
}
@@ -429,30 +431,29 @@ TEST_F(TriggerScriptCoordinatorTest, PerformTriggerScriptActionCancelSession) {
TriggerScriptProto* script = response.add_trigger_scripts();
*script->mutable_trigger_condition()->mutable_selector() =
ToSelectorProto("#selector");
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
ON_CALL(*mock_dynamic_trigger_conditions_, OnUpdate(mock_web_controller_, _))
.WillByDefault(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_PROMPT_FAILED_CANCEL_SESSION))
- .Times(1);
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(1);
+ EXPECT_CALL(
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_SESSION, _,
+ _));
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
coordinator_->PerformTriggerScriptAction(TriggerScriptProto::CANCEL_SESSION);
- AssertRecordedFinishedState(CART_RETURNING_USER,
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_PROMPT_FAILED_CANCEL_SESSION);
+ AssertRecordedFinishedState(
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_SESSION);
}
TEST_F(TriggerScriptCoordinatorTest, PerformTriggerScriptActionCancelForever) {
@@ -460,30 +461,29 @@ TEST_F(TriggerScriptCoordinatorTest, PerformTriggerScriptActionCancelForever) {
TriggerScriptProto* script = response.add_trigger_scripts();
*script->mutable_trigger_condition()->mutable_selector() =
ToSelectorProto("#selector");
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
ON_CALL(*mock_dynamic_trigger_conditions_, OnUpdate(mock_web_controller_, _))
.WillByDefault(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_PROMPT_FAILED_CANCEL_FOREVER))
- .Times(1);
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(1);
+ EXPECT_CALL(
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_FOREVER, _,
+ _));
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
coordinator_->PerformTriggerScriptAction(TriggerScriptProto::CANCEL_FOREVER);
- AssertRecordedFinishedState(CART_RETURNING_USER,
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_PROMPT_FAILED_CANCEL_FOREVER);
+ AssertRecordedFinishedState(
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptFinishedState::PROMPT_FAILED_CANCEL_FOREVER);
}
TEST_F(TriggerScriptCoordinatorTest, PerformTriggerScriptActionAccept) {
@@ -491,20 +491,20 @@ TEST_F(TriggerScriptCoordinatorTest, PerformTriggerScriptActionAccept) {
TriggerScriptProto* script = response.add_trigger_scripts();
*script->mutable_trigger_condition()->mutable_selector() =
ToSelectorProto("#selector");
- script->set_trigger_ui_type(CHECKOUT_RETURNING_USER);
+ script->set_trigger_ui_type(
+ TriggerScriptProto::SHOPPING_CHECKOUT_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
ON_CALL(*mock_dynamic_trigger_conditions_, OnUpdate(mock_web_controller_, _))
.WillByDefault(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
}
@@ -515,23 +515,22 @@ TEST_F(TriggerScriptCoordinatorTest, CancelOnNavigateAway) {
TriggerScriptProto* script = response.add_trigger_scripts();
*script->mutable_trigger_condition()->mutable_selector() =
ToSelectorProto("#selector");
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
ON_CALL(*mock_dynamic_trigger_conditions_, OnUpdate(mock_web_controller_, _))
.WillByDefault(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillRepeatedly(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
// Same-domain navigation is ok.
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished(_)).Times(0);
+ EXPECT_CALL(mock_callback_, Run).Times(0);
SimulateNavigateToUrl(GURL("https://example.com/cart"));
// Navigating to sub-domain of original domain is ok.
@@ -545,14 +544,14 @@ TEST_F(TriggerScriptCoordinatorTest, CancelOnNavigateAway) {
// Navigating to non-whitelisted domain is not ok.
EXPECT_CALL(
- mock_observer_,
- OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_NAVIGATE))
- .Times(1);
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE, _, _));
SimulateNavigateToUrl(GURL("https://example.different.com/page"));
+ // UKM is recorded for the last seen URL that was still on a supported domain.
AssertRecordedFinishedState(
- CART_RETURNING_USER,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_NAVIGATE);
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE,
+ GURL("https://subdomain.other-example.com/page"));
}
TEST_F(TriggerScriptCoordinatorTest, IgnoreNavigationEventsWhileNotStarted) {
@@ -560,25 +559,24 @@ TEST_F(TriggerScriptCoordinatorTest, IgnoreNavigationEventsWhileNotStarted) {
TriggerScriptProto* script = response.add_trigger_scripts();
*script->mutable_trigger_condition()->mutable_selector() =
ToSelectorProto("#selector");
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillOnce(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
// When a tab becomes invisible, navigation events are disregarded.
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(1);
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished).Times(0);
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
+ EXPECT_CALL(mock_callback_, Run).Times(0);
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.Times(0);
@@ -591,38 +589,37 @@ TEST_F(TriggerScriptCoordinatorTest, IgnoreNavigationEventsWhileNotStarted) {
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, /* response = */ ""));
// However, when the tab becomes visible again, the trigger script is
// restarted and thus fails if the tab is still on an unsupported domain.
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_NO_TRIGGER_SCRIPT_AVAILABLE))
- .Times(1);
+ EXPECT_CALL(
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE, _,
+ _));
SimulateWebContentsVisibilityChanged(content::Visibility::VISIBLE);
- AssertRecordedFinishedState(UNSPECIFIED_TRIGGER_UI_TYPE,
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_NO_TRIGGER_SCRIPT_AVAILABLE);
+ AssertRecordedFinishedState(
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
+ Metrics::TriggerScriptFinishedState::NO_TRIGGER_SCRIPT_AVAILABLE);
}
TEST_F(TriggerScriptCoordinatorTest, BottomSheetClosedWithSwipe) {
GetTriggerScriptsResponseProto response;
TriggerScriptProto* script = response.add_trigger_scripts();
script->set_on_swipe_to_dismiss(TriggerScriptProto::NOT_NOW);
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
ON_CALL(*mock_dynamic_trigger_conditions_, OnUpdate(mock_web_controller_, _))
.WillByDefault(RunOnceCallback<1>());
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
coordinator_->OnBottomSheetClosedWithSwipe();
AssertRecordedShownToUserState(
- CART_RETURNING_USER,
- Metrics::LiteScriptShownToUser::LITE_SCRIPT_SWIPE_DISMISSED, 1);
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptShownToUser::SWIPE_DISMISSED, 1);
}
TEST_F(TriggerScriptCoordinatorTest, TimeoutAfterInvisibleForTooLong) {
@@ -630,7 +627,8 @@ TEST_F(TriggerScriptCoordinatorTest, TimeoutAfterInvisibleForTooLong) {
TriggerScriptProto* script = response.add_trigger_scripts();
*script->mutable_trigger_condition()->mutable_selector() =
ToSelectorProto("#selector");
- script->set_trigger_ui_type(CHECKOUT_RETURNING_USER);
+ script->set_trigger_ui_type(
+ TriggerScriptProto::SHOPPING_CHECKOUT_RETURNING_USER);
response.set_timeout_ms(3000);
response.set_trigger_condition_check_interval_ms(1000);
std::string serialized_response;
@@ -638,8 +636,6 @@ TEST_F(TriggerScriptCoordinatorTest, TimeoutAfterInvisibleForTooLong) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
// Note: expect 4 calls: 1 initial plus 3 until timeout.
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
@@ -649,17 +645,19 @@ TEST_F(TriggerScriptCoordinatorTest, TimeoutAfterInvisibleForTooLong) {
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.Times(4)
.WillRepeatedly(Return(false));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT));
+ EXPECT_CALL(
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT, _,
+ _));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
AssertRecordedFinishedState(
- UNSPECIFIED_TRIGGER_UI_TYPE,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT);
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
+ Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT);
}
TEST_F(TriggerScriptCoordinatorTest, TimeoutResetsAfterTriggerScriptShown) {
@@ -667,7 +665,7 @@ TEST_F(TriggerScriptCoordinatorTest, TimeoutResetsAfterTriggerScriptShown) {
TriggerScriptProto* script = response.add_trigger_scripts();
*script->mutable_trigger_condition()->mutable_selector() =
ToSelectorProto("#selector");
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
response.set_timeout_ms(3000);
response.set_trigger_condition_check_interval_ms(1000);
std::string serialized_response;
@@ -675,37 +673,37 @@ TEST_F(TriggerScriptCoordinatorTest, TimeoutResetsAfterTriggerScriptShown) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillRepeatedly(RunOnceCallback<1>());
// While the trigger script is shown, the timeout is ignored.
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillRepeatedly(Return(true));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
// When the trigger script is hidden, the timeout resets.
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillRepeatedly(Return(false));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT));
+ EXPECT_CALL(
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT, _,
+ _));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
AssertRecordedFinishedState(
- UNSPECIFIED_TRIGGER_UI_TYPE,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT);
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
+ Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT);
}
TEST_F(TriggerScriptCoordinatorTest, NoTimeoutByDefault) {
@@ -718,16 +716,15 @@ TEST_F(TriggerScriptCoordinatorTest, NoTimeoutByDefault) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillRepeatedly(RunOnceCallback<1>());
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished).Times(0);
+ EXPECT_CALL(mock_callback_, Run).Times(0);
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillRepeatedly(Return(false));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
for (int i = 0; i < 10; ++i) {
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
}
@@ -745,14 +742,13 @@ TEST_F(TriggerScriptCoordinatorTest, KeyboardEventTriggersOutOfScheduleCheck) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillOnce(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(false));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
// While the next call to Update is pending, a keyboard visibility event will
// immediately trigger an out-of-schedule update (which does not count towards
@@ -774,25 +770,17 @@ TEST_F(TriggerScriptCoordinatorTest, KeyboardEventTriggersOutOfScheduleCheck) {
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT));
+ EXPECT_CALL(
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT, _,
+ _));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(1));
AssertRecordedFinishedState(
- UNSPECIFIED_TRIGGER_UI_TYPE,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_TRIGGER_CONDITION_TIMEOUT);
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
+ Metrics::TriggerScriptFinishedState::TRIGGER_CONDITION_TIMEOUT);
}
-// Flaky on Android. crbug.com/1192012.
-#if defined(OS_ANDROID)
-#define MAYBE_UrlChangeOutOfScheduleCheckPathMatch \
- DISABLED_UrlChangeOutOfScheduleCheckPathMatch
-#else
-#define MAYBE_UrlChangeOutOfScheduleCheckPathMatch \
- UrlChangeOutOfScheduleCheckPathMatch
-#endif
-TEST_F(TriggerScriptCoordinatorTest,
- MAYBE_UrlChangeOutOfScheduleCheckPathMatch) {
+TEST_F(TriggerScriptCoordinatorTest, UrlChangeOutOfScheduleCheckPathMatch) {
GetTriggerScriptsResponseProto response;
response.add_trigger_scripts()->mutable_trigger_condition()->set_path_pattern(
".*trigger_page.*");
@@ -801,54 +789,52 @@ TEST_F(TriggerScriptCoordinatorTest,
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillOnce(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, SetURL).Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetPathPatternMatches)
.WillOnce(Return(false));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
- SetURL(GURL("http://example.com/trigger_page")))
+ SetURL(GURL("https://example.com/trigger_page")))
.Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
GetPathPatternMatches(".*trigger_page.*"))
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- SimulateNavigateToUrl(GURL("http://example.com/trigger_page"));
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ SimulateNavigateToUrl(GURL("https://example.com/trigger_page"));
}
TEST_F(TriggerScriptCoordinatorTest, UrlChangeOutOfScheduleCheckDomainMatch) {
GetTriggerScriptsResponseProto response;
response.add_trigger_scripts()
->mutable_trigger_condition()
- ->set_domain_with_scheme("http://example.com");
+ ->set_domain_with_scheme("https://example.com");
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillOnce(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, SetURL).Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetDomainAndSchemeMatches)
.WillOnce(Return(false));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
- SetURL(GURL("http://example.com/trigger_page")))
+ SetURL(GURL("https://example.com/trigger_page")))
.Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
- GetDomainAndSchemeMatches(GURL("http://example.com")))
+ GetDomainAndSchemeMatches(GURL("https://example.com")))
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- SimulateNavigateToUrl(GURL("http://example.com/trigger_page"));
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ SimulateNavigateToUrl(GURL("https://example.com/trigger_page"));
}
TEST_F(TriggerScriptCoordinatorTest,
@@ -861,53 +847,48 @@ TEST_F(TriggerScriptCoordinatorTest,
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillOnce(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, SetURL).Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetPathPatternMatches)
.WillOnce(Return(false));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, SetURL).Times(0);
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetPathPatternMatches)
.Times(0);
+
EXPECT_CALL(
- mock_observer_,
- OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_NAVIGATE))
- .Times(1);
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::PROMPT_FAILED_NAVIGATE, _, _));
SimulateNavigateToUrl(GURL("http://example.different.com/page"));
}
TEST_F(TriggerScriptCoordinatorTest, OnTriggerScriptFailedToShow) {
GetTriggerScriptsResponseProto response;
TriggerScriptProto* script = response.add_trigger_scripts();
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillRepeatedly(RunOnceCallback<1>());
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).WillOnce([&]() {
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).WillOnce([&]() {
coordinator_->OnTriggerScriptShown(/* success = */ false);
});
- EXPECT_CALL(
- mock_observer_,
- OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_FAILED_TO_SHOW));
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::FAILED_TO_SHOW, _, _));
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
AssertRecordedFinishedState(
- CART_RETURNING_USER,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_FAILED_TO_SHOW);
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptFinishedState::FAILED_TO_SHOW);
}
TEST_F(TriggerScriptCoordinatorTest, OnProactiveHelpSettingDisabled) {
@@ -918,24 +899,24 @@ TEST_F(TriggerScriptCoordinatorTest, OnProactiveHelpSettingDisabled) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillRepeatedly(RunOnceCallback<1>());
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
EXPECT_CALL(
- mock_observer_,
- OnTriggerScriptFinished(Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_DISABLED_PROACTIVE_HELP_SETTING));
- coordinator_->OnProactiveHelpSettingChanged(
- /* proactive_help_enabled = */ false);
- AssertRecordedFinishedState(UNSPECIFIED_TRIGGER_UI_TYPE,
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_DISABLED_PROACTIVE_HELP_SETTING);
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::DISABLED_PROACTIVE_HELP_SETTING,
+ _, _));
+ fake_platform_delegate_.proactive_help_enabled_ = false;
+ SimulateWebContentsInteractabilityChanged(false);
+ SimulateWebContentsInteractabilityChanged(true);
+ AssertRecordedFinishedState(
+ TriggerScriptProto::UNSPECIFIED_TRIGGER_UI_TYPE,
+ Metrics::TriggerScriptFinishedState::DISABLED_PROACTIVE_HELP_SETTING);
}
TEST_F(TriggerScriptCoordinatorTest, PauseAndResumeOnTabSwitch) {
@@ -948,21 +929,19 @@ TEST_F(TriggerScriptCoordinatorTest, PauseAndResumeOnTabSwitch) {
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillOnce(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
// During tab switching, the tab becomes non-interactive. In this test, the
// same tab is then re-selected (otherwise, the original tab's visibility
// would change).
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(1);
- EXPECT_CALL(mock_observer_, OnVisibilityChanged(false)).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.Times(0);
@@ -972,204 +951,218 @@ TEST_F(TriggerScriptCoordinatorTest, PauseAndResumeOnTabSwitch) {
// must be fetched again.
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillOnce(RunOnceCallback<1>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_, GetSelectorMatches)
.WillOnce(Return(true));
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- EXPECT_CALL(mock_observer_, OnVisibilityChanged(true)).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
EXPECT_CALL(*mock_dynamic_trigger_conditions_, SetURL).Times(1);
SimulateWebContentsInteractabilityChanged(/* interactable = */ true);
}
-// Flaky on Android. crbug.com/1192012.
-#if defined(OS_ANDROID)
-#define MAYBE_OnboardingShownAndAccepted DISABLED_OnboardingShownAndAccepted
-#else
-#define MAYBE_OnboardingShownAndAccepted OnboardingShownAndAccepted
-#endif
-TEST_F(TriggerScriptCoordinatorTest, MAYBE_OnboardingShownAndAccepted) {
+TEST_F(TriggerScriptCoordinatorTest, OnboardingShownAndAccepted) {
GetTriggerScriptsResponseProto response;
auto* script = response.add_trigger_scripts();
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillRepeatedly(RunOnceCallback<1>());
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
-
- EXPECT_CALL(
- mock_observer_,
- OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SUCCEEDED))
- .Times(1);
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(0);
- coordinator_->OnOnboardingFinished(/* onboardingShown= */ true,
- /* result= */ OnboardingResult::ACCEPTED);
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ fake_platform_delegate_.is_first_time_user_ = false;
+ fake_platform_delegate_.show_onboarding_result_ = OnboardingResult::ACCEPTED;
+ fake_platform_delegate_.show_onboarding_result_shown_ = true;
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
+
+ EXPECT_CALL(mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED, _,
+ testing::Optional(response.trigger_scripts(0))));
+ coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
- AssertRecordedLiteScriptOnboardingState(
- CART_RETURNING_USER,
- Metrics::LiteScriptOnboarding::LITE_SCRIPT_ONBOARDING_SEEN_AND_ACCEPTED,
- 1);
+ EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(1));
+ AssertRecordedTriggerScriptOnboardingState(
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED, 1);
AssertRecordedFinishedState(
- CART_RETURNING_USER,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SUCCEEDED);
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED);
}
-// Flaky on Android. crbug.com/1192012.
-#if defined(OS_ANDROID)
-#define MAYBE_CancellingDialogOnboardingDoesNotStopTriggerScript \
- DISABLED_CancellingDialogOnboardingDoesNotStopTriggerScript
-#else
-#define MAYBE_CancellingDialogOnboardingDoesNotStopTriggerScript \
- CancellingDialogOnboardingDoesNotStopTriggerScript
-#endif
TEST_F(TriggerScriptCoordinatorTest,
- MAYBE_CancellingDialogOnboardingDoesNotStopTriggerScript) {
+ CancellingDialogOnboardingDoesNotStopTriggerScript) {
auto feature_list = CreateScopedFeatureList(/* dialog_onboarding= */ true);
GetTriggerScriptsResponseProto response;
auto* script = response.add_trigger_scripts();
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillRepeatedly(RunOnceCallback<1>());
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
-
- EXPECT_CALL(mock_observer_, OnTriggerScriptFinished).Times(0);
- coordinator_->OnOnboardingFinished(/* onboardingShown= */ true,
- /* result= */ OnboardingResult::REJECTED);
- coordinator_->OnOnboardingFinished(/* onboardingShown= */ true,
- /* result= */ OnboardingResult::DISMISSED);
- coordinator_->OnOnboardingFinished(
- /* onboardingShown= */ true,
- /* result= */ OnboardingResult::NAVIGATION);
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ fake_platform_delegate_.is_first_time_user_ = false;
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
+
+ EXPECT_CALL(mock_callback_, Run).Times(0);
+ fake_platform_delegate_.show_onboarding_result_ = OnboardingResult::REJECTED;
+ fake_platform_delegate_.show_onboarding_result_shown_ = true;
+ coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
- EXPECT_CALL(
- mock_observer_,
- OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SUCCEEDED))
- .Times(1);
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(0);
- coordinator_->OnOnboardingFinished(/* onboardingShown= */ true,
- /* result= */ OnboardingResult::ACCEPTED);
+ fake_platform_delegate_.show_onboarding_result_ = OnboardingResult::DISMISSED;
+ fake_platform_delegate_.show_onboarding_result_shown_ = true;
+ coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
- AssertRecordedLiteScriptOnboardingState(
- CART_RETURNING_USER,
- Metrics::LiteScriptOnboarding::LITE_SCRIPT_ONBOARDING_SEEN_AND_REJECTED,
- 1);
- AssertRecordedLiteScriptOnboardingState(
- CART_RETURNING_USER,
- Metrics::LiteScriptOnboarding::LITE_SCRIPT_ONBOARDING_SEEN_AND_ACCEPTED,
- 1);
- AssertRecordedLiteScriptOnboardingState(
- CART_RETURNING_USER,
- Metrics::LiteScriptOnboarding::
- LITE_SCRIPT_ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION,
+ fake_platform_delegate_.show_onboarding_result_ =
+ OnboardingResult::NAVIGATION;
+ fake_platform_delegate_.show_onboarding_result_shown_ = true;
+ coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
+
+ EXPECT_CALL(mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED, _,
+ testing::Optional(response.trigger_scripts(0))));
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(0);
+ fake_platform_delegate_.show_onboarding_result_ = OnboardingResult::ACCEPTED;
+ fake_platform_delegate_.show_onboarding_result_shown_ = true;
+ coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
+
+ EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(4));
+ AssertRecordedTriggerScriptOnboardingState(
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_REJECTED, 1);
+ AssertRecordedTriggerScriptOnboardingState(
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_ACCEPTED, 1);
+ AssertRecordedTriggerScriptOnboardingState(
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptOnboarding::
+ ONBOARDING_SEEN_AND_INTERRUPTED_BY_NAVIGATION,
1);
AssertRecordedFinishedState(
- CART_RETURNING_USER,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SUCCEEDED);
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED);
}
-// Flaky on Android. crbug.com/1192012.
-#if defined(OS_ANDROID)
-#define MAYBE_RejectingBottomSheetOnboardingStopsTriggerScript \
- DISABLED_RejectingBottomSheetOnboardingStopsTriggerScript
-#else
-#define MAYBE_RejectingBottomSheetOnboardingStopsTriggerScript \
- RejectingBottomSheetOnboardingStopsTriggerScript
-#endif
TEST_F(TriggerScriptCoordinatorTest,
- MAYBE_RejectingBottomSheetOnboardingStopsTriggerScript) {
+ RejectingBottomSheetOnboardingStopsTriggerScript) {
auto feature_list = CreateScopedFeatureList(/* dialog_onboarding= */ false);
GetTriggerScriptsResponseProto response;
auto* script = response.add_trigger_scripts();
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillRepeatedly(RunOnceCallback<1>());
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
EXPECT_CALL(
- mock_observer_,
- OnTriggerScriptFinished(Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_BOTTOMSHEET_ONBOARDING_REJECTED))
- .Times(1);
- EXPECT_CALL(mock_observer_, OnTriggerScriptHidden).Times(1);
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(0);
- coordinator_->OnOnboardingFinished(/* onboardingShown= */ true,
- /* result= */ OnboardingResult::REJECTED);
-
- AssertRecordedLiteScriptOnboardingState(
- CART_RETURNING_USER,
- Metrics::LiteScriptOnboarding::LITE_SCRIPT_ONBOARDING_SEEN_AND_REJECTED,
- 1);
- AssertRecordedFinishedState(CART_RETURNING_USER,
- Metrics::LiteScriptFinishedState::
- LITE_SCRIPT_BOTTOMSHEET_ONBOARDING_REJECTED);
+ mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::BOTTOMSHEET_ONBOARDING_REJECTED,
+ _, _));
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(0);
+ fake_platform_delegate_.show_onboarding_result_ = OnboardingResult::REJECTED;
+ fake_platform_delegate_.show_onboarding_result_shown_ = true;
+ coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
+
+ EXPECT_THAT(fake_platform_delegate_.num_show_onboarding_called_, Eq(1));
+ AssertRecordedTriggerScriptOnboardingState(
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptOnboarding::ONBOARDING_SEEN_AND_REJECTED, 1);
+ AssertRecordedFinishedState(
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptFinishedState::BOTTOMSHEET_ONBOARDING_REJECTED);
}
TEST_F(TriggerScriptCoordinatorTest, OnboardingNotShown) {
GetTriggerScriptsResponseProto response;
auto* script = response.add_trigger_scripts();
- script->set_trigger_ui_type(CART_RETURNING_USER);
+ script->set_trigger_ui_type(TriggerScriptProto::SHOPPING_CART_RETURNING_USER);
std::string serialized_response;
response.SerializeToString(&serialized_response);
EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
.WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
- EXPECT_CALL(*mock_static_trigger_conditions_, Init)
- .WillOnce(RunOnceCallback<4>());
EXPECT_CALL(*mock_dynamic_trigger_conditions_,
OnUpdate(mock_web_controller_, _))
.WillRepeatedly(RunOnceCallback<1>());
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(1);
- coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>());
-
- EXPECT_CALL(
- mock_observer_,
- OnTriggerScriptFinished(
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SUCCEEDED))
- .Times(1);
- EXPECT_CALL(mock_observer_, OnTriggerScriptShown).Times(0);
- coordinator_->OnOnboardingFinished(/* onboardingShown= */ false,
- /* result= */ OnboardingResult::ACCEPTED);
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(1);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
+
+ EXPECT_CALL(mock_callback_,
+ Run(Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED, _, _));
+ EXPECT_CALL(*mock_ui_delegate_, ShowTriggerScript).Times(0);
+ fake_platform_delegate_.onboarding_accepted_ = true;
+ fake_platform_delegate_.show_onboarding_result_shown_ = false;
+ coordinator_->PerformTriggerScriptAction(TriggerScriptProto::ACCEPT);
- AssertRecordedLiteScriptOnboardingState(
- CART_RETURNING_USER,
- Metrics::LiteScriptOnboarding::LITE_SCRIPT_ONBOARDING_ALREADY_ACCEPTED,
- 1);
+ AssertRecordedTriggerScriptOnboardingState(
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptOnboarding::ONBOARDING_ALREADY_ACCEPTED, 1);
AssertRecordedFinishedState(
- CART_RETURNING_USER,
- Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_SUCCEEDED);
+ TriggerScriptProto::SHOPPING_CART_RETURNING_USER,
+ Metrics::TriggerScriptFinishedState::PROMPT_SUCCEEDED);
+}
+
+TEST_F(TriggerScriptCoordinatorTest, BackendCanOverrideScriptParameters) {
+ GetTriggerScriptsResponseProto response;
+ response.add_trigger_scripts();
+ auto* param_1 = response.add_script_parameters();
+ param_1->set_name("name_1");
+ param_1->set_value("new_value_1");
+ auto* param_2 = response.add_script_parameters();
+ param_2->set_name("name_2");
+ param_2->set_value("new_value_2");
+ std::string serialized_response;
+ response.SerializeToString(&serialized_response);
+
+ EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
+ .WillOnce(RunOnceCallback<2>(net::HTTP_OK, serialized_response));
+
+ coordinator_->Start(
+ GURL(kFakeDeepLink),
+ std::make_unique<TriggerContext>(
+ std::make_unique<ScriptParameters>(std::map<std::string, std::string>{
+ {"name_1", "old_value_1"}, {"name_3", "value_3"}}),
+ TriggerContext::Options()),
+ mock_callback_.Get());
+ EXPECT_THAT(coordinator_->GetTriggerContext().GetScriptParameters().ToProto(),
+ UnorderedElementsAre(std::make_pair("name_1", "new_value_1"),
+ std::make_pair("name_2", "new_value_2"),
+ std::make_pair("name_3", "value_3")));
+}
+
+TEST_F(TriggerScriptCoordinatorTest, StoppingTwiceDoesNotCrash) {
+ EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _))
+ .WillOnce(RunOnceCallback<2>(net::HTTP_FORBIDDEN, ""));
+ EXPECT_CALL(*mock_ui_delegate_, Detach).Times(1);
+ EXPECT_CALL(*mock_ui_delegate_, HideTriggerScript).Times(0);
+ coordinator_->Start(GURL(kFakeDeepLink), std::make_unique<TriggerContext>(),
+ mock_callback_.Get());
+
+ // Stopping coordinator after it was already stopped by a failed request.
+ coordinator_->Stop(
+ Metrics::TriggerScriptFinishedState::CCT_TO_TAB_NOT_SUPPORTED);
+
+ // Nothing crashed.
}
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/ui_delegate.h b/chromium/components/autofill_assistant/browser/ui_delegate.h
index 35c5789ca8e..95f327fb2c5 100644
--- a/chromium/components/autofill_assistant/browser/ui_delegate.h
+++ b/chromium/components/autofill_assistant/browser/ui_delegate.h
@@ -9,7 +9,6 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "bottom_sheet_state.h"
#include "components/autofill_assistant/browser/client_settings.h"
#include "components/autofill_assistant/browser/event_handler.h"
@@ -19,6 +18,7 @@
#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/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
class ControllerObserver;
@@ -67,13 +67,13 @@ class UiDelegate {
virtual int GetProgress() const = 0;
// Returns the currently active progress step.
- virtual base::Optional<int> GetProgressActiveStep() const = 0;
+ virtual absl::optional<int> GetProgressActiveStep() const = 0;
// Returns whether the progress bar is visible.
virtual bool GetProgressVisible() const = 0;
// Returns the current configuration of the step progress bar.
- virtual base::Optional<ShowProgressBarProto::StepProgressBarConfiguration>
+ virtual absl::optional<ShowProgressBarProto::StepProgressBarConfiguration>
GetStepProgressBarConfiguration() const = 0;
// Returns whether the progress bar should show an error state.
@@ -143,19 +143,19 @@ class UiDelegate {
// Sets the start date of the date/time range.
virtual void SetDateTimeRangeStartDate(
- const base::Optional<DateProto>& date) = 0;
+ const absl::optional<DateProto>& date) = 0;
// Sets the start timeslot of the date/time range.
virtual void SetDateTimeRangeStartTimeSlot(
- const base::Optional<int>& timeslot_index) = 0;
+ const absl::optional<int>& timeslot_index) = 0;
// Sets the end date of the date/time range.
virtual void SetDateTimeRangeEndDate(
- const base::Optional<DateProto>& date) = 0;
+ const absl::optional<DateProto>& date) = 0;
// Sets the end timeslot of the date/time range.
virtual void SetDateTimeRangeEndTimeSlot(
- const base::Optional<int>& timeslot_index) = 0;
+ const absl::optional<int>& timeslot_index) = 0;
// Sets an additional value.
virtual void SetAdditionalValue(const std::string& client_memory_key,
@@ -255,6 +255,10 @@ class UiDelegate {
// The generic user interface to show, if any.
virtual const GenericUserInterfaceProto* GetGenericUiProto() const = 0;
+ // The persistent generic user interface to show, if any.
+ virtual const GenericUserInterfaceProto* GetPersistentGenericUiProto()
+ const = 0;
+
// Whether the overlay should be determined based on AA state or always
// hidden.
virtual bool ShouldShowOverlay() const = 0;
@@ -265,6 +269,10 @@ class UiDelegate {
// Called when the visibility of the keyboard has changed.
virtual void OnKeyboardVisibilityChanged(bool visible) = 0;
+ // Called when the user starts or finishes to focus an input text field in the
+ // bottom sheet.
+ virtual void OnInputTextFocusChanged(bool is_text_focused) = 0;
+
protected:
UiDelegate() = default;
};
diff --git a/chromium/components/autofill_assistant/browser/url_utils.cc b/chromium/components/autofill_assistant/browser/url_utils.cc
index ebf070b3aea..677ae8b83c0 100644
--- a/chromium/components/autofill_assistant/browser/url_utils.cc
+++ b/chromium/components/autofill_assistant/browser/url_utils.cc
@@ -18,12 +18,6 @@ bool IsInSubDomain(const GURL& url, const std::string& domain) {
base::CompareCase::INSENSITIVE_ASCII);
}
-std::string GetRegistryControlledDomain(const GURL& signon_realm) {
- return net::registry_controlled_domains::GetDomainAndRegistry(
- signon_realm,
- net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
-}
-
} // namespace
namespace autofill_assistant {
@@ -55,9 +49,8 @@ bool IsSamePublicSuffixDomain(const GURL& url1, const GURL& url2) {
return true;
}
- auto domain1 = GetRegistryControlledDomain(url1);
- auto domain2 = GetRegistryControlledDomain(url2);
-
+ auto domain1 = GetOrganizationIdentifyingDomain(url1);
+ auto domain2 = GetOrganizationIdentifyingDomain(url2);
if (domain1.empty() || domain2.empty()) {
return false;
}
@@ -65,5 +58,10 @@ bool IsSamePublicSuffixDomain(const GURL& url1, const GURL& url2) {
return url1.scheme() == url2.scheme() && domain1 == domain2;
}
+std::string GetOrganizationIdentifyingDomain(const GURL& url) {
+ return net::registry_controlled_domains::GetDomainAndRegistry(
+ url, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+}
+
} // namespace url_utils
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/url_utils.h b/chromium/components/autofill_assistant/browser/url_utils.h
index 7df2997e826..55fc1b820ce 100644
--- a/chromium/components/autofill_assistant/browser/url_utils.h
+++ b/chromium/components/autofill_assistant/browser/url_utils.h
@@ -27,6 +27,10 @@ bool IsInDomainOrSubDomain(const GURL& url,
// false.
bool IsSamePublicSuffixDomain(const GURL& url1, const GURL& url2);
+// Returns the organization-identifying domain for |url|. Returns the empty
+// string for invalid urls.
+std::string GetOrganizationIdentifyingDomain(const GURL& url);
+
} // namespace url_utils
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/url_utils_unittest.cc b/chromium/components/autofill_assistant/browser/url_utils_unittest.cc
index e76d9a3566d..d75fa044bf3 100644
--- a/chromium/components/autofill_assistant/browser/url_utils_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/url_utils_unittest.cc
@@ -9,6 +9,8 @@ namespace autofill_assistant {
namespace url_utils {
namespace {
+using testing::Eq;
+
TEST(UrlUtilsTest, IsInDomainOrSubDomain) {
std::vector<std::string> allowed_domains = {"example.com",
"other-example.com"};
@@ -57,6 +59,16 @@ TEST(UrlUtilsTest, IsSamePublicSuffixDomain) {
EXPECT_FALSE(IsSamePublicSuffixDomain(GURL("invalid"), GURL("invalid")));
}
+TEST(UrlUtilsTest, GetOrganizationIdentifyingDomain) {
+ EXPECT_THAT(GetOrganizationIdentifyingDomain(GURL("https://www.example.com")),
+ Eq("example.com"));
+ EXPECT_THAT(
+ GetOrganizationIdentifyingDomain(GURL("https://subdomain.example.com")),
+ Eq("example.com"));
+ EXPECT_THAT(GetOrganizationIdentifyingDomain(GURL("https://example.com")),
+ Eq("example.com"));
+}
+
} // namespace
} // namespace url_utils
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/user_data.cc b/chromium/components/autofill_assistant/browser/user_data.cc
index 6267839467f..9c85a296789 100644
--- a/chromium/components/autofill_assistant/browser/user_data.cc
+++ b/chromium/components/autofill_assistant/browser/user_data.cc
@@ -13,10 +13,10 @@ LoginChoice::LoginChoice(
const std::string& _identifier,
const std::string& _label,
const std::string& _sublabel,
- const base::Optional<std::string>& _sublabel_accessibility_hint,
+ const absl::optional<std::string>& _sublabel_accessibility_hint,
int _preselect_priority,
- const base::Optional<InfoPopupProto>& _info_popup,
- const base::Optional<std::string>& _edit_button_content_description)
+ const absl::optional<InfoPopupProto>& _info_popup,
+ const absl::optional<std::string>& _edit_button_content_description)
: identifier(_identifier),
label(_label),
sublabel(_sublabel),
@@ -58,6 +58,10 @@ const autofill::AutofillProfile* UserData::selected_address(
return it->second.get();
}
+const autofill::CreditCard* UserData::selected_card() const {
+ return selected_card_.get();
+}
+
const ValueProto* UserData::additional_value(const std::string& key) const {
auto it = additional_values_.find(key);
if (it == additional_values_.end()) {
diff --git a/chromium/components/autofill_assistant/browser/user_data.h b/chromium/components/autofill_assistant/browser/user_data.h
index e3fc8f0f0e4..931139d15cd 100644
--- a/chromium/components/autofill_assistant/browser/user_data.h
+++ b/chromium/components/autofill_assistant/browser/user_data.h
@@ -11,12 +11,12 @@
#include <vector>
#include "base/callback.h"
-#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/service.pb.h"
#include "components/autofill_assistant/browser/user_action.h"
#include "components/autofill_assistant/browser/website_login_manager.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
class AutofillProfile;
@@ -56,10 +56,10 @@ struct LoginChoice {
const std::string& id,
const std::string& label,
const std::string& sublabel,
- const base::Optional<std::string>& sublabel_accessibility_hint,
+ const absl::optional<std::string>& sublabel_accessibility_hint,
int priority,
- const base::Optional<InfoPopupProto>& info_popup,
- const base::Optional<std::string>& edit_button_content_description);
+ const absl::optional<InfoPopupProto>& info_popup,
+ const absl::optional<std::string>& edit_button_content_description);
LoginChoice(const LoginChoice& another);
~LoginChoice();
@@ -70,13 +70,13 @@ struct LoginChoice {
// The sublabel to display to the user.
std::string sublabel;
// The a11y hint for |sublabel|.
- base::Optional<std::string> sublabel_accessibility_hint;
+ absl::optional<std::string> sublabel_accessibility_hint;
// The priority to pre-select this choice (-1 == not set/automatic).
int preselect_priority = -1;
// The popup to show to provide more information about this login choice.
- base::Optional<InfoPopupProto> info_popup;
+ absl::optional<InfoPopupProto> info_popup;
// The a11y hint for the edit button.
- base::Optional<std::string> edit_button_content_description;
+ absl::optional<std::string> edit_button_content_description;
};
// Tuple for holding credit card and billing address;
@@ -112,13 +112,12 @@ class UserData {
AVAILABLE_PAYMENT_INSTRUMENTS,
};
- std::unique_ptr<autofill::CreditCard> selected_card_;
std::string login_choice_identifier_;
TermsAndConditionsState terms_and_conditions_ = NOT_SELECTED;
- base::Optional<DateProto> date_time_range_start_date_;
- base::Optional<DateProto> date_time_range_end_date_;
- base::Optional<int> date_time_range_start_timeslot_;
- base::Optional<int> date_time_range_end_timeslot_;
+ absl::optional<DateProto> date_time_range_start_date_;
+ absl::optional<DateProto> date_time_range_end_date_;
+ absl::optional<int> date_time_range_start_timeslot_;
+ absl::optional<int> date_time_range_end_timeslot_;
// A set of additional key/value pairs to be stored in client_memory.
std::map<std::string, ValueProto> additional_values_;
@@ -127,11 +126,7 @@ class UserData {
std::vector<std::unique_ptr<PaymentInstrument>>
available_payment_instruments_;
- // The address key requested by the autofill action.
- std::map<std::string, std::unique_ptr<autofill::AutofillProfile>>
- selected_addresses_;
-
- base::Optional<WebsiteLoginManager::Login> selected_login_;
+ absl::optional<WebsiteLoginManager::Login> selected_login_;
// Return true if address has been selected, otherwise return false.
// Note that selected_address() might return nullptr when
@@ -146,6 +141,9 @@ class UserData {
const autofill::AutofillProfile* selected_address(
const std::string& name) const;
+ // The selected card.
+ const autofill::CreditCard* selected_card() const;
+
// The additional value for |key|, or nullptr if it does not exist.
const ValueProto* additional_value(const std::string& key) const;
@@ -153,9 +151,20 @@ class UserData {
// password generation (GeneratePasswordForFormFieldProto) to allow a
// subsequent PresaveGeneratedPasswordProto to presave the password prior to
// submission.
- base::Optional<autofill::FormData> password_form_data_;
+ absl::optional<autofill::FormData> password_form_data_;
std::string GetAllAddressKeyNames() const;
+
+ private:
+ friend class UserModel;
+ // The address key requested by the autofill action.
+ // Written by |UserModel| to ensure that it stays in sync.
+ std::map<std::string, std::unique_ptr<autofill::AutofillProfile>>
+ selected_addresses_;
+
+ // The selected credit card.
+ // Written by |UserModel| to ensure that it stays in sync.
+ std::unique_ptr<autofill::CreditCard> selected_card_;
};
// Struct for holding the payment request options.
@@ -203,9 +212,9 @@ struct CollectUserDataOptions {
DateTimeRangeProto date_time_range;
std::vector<UserFormSectionProto> additional_prepended_sections;
std::vector<UserFormSectionProto> additional_appended_sections;
- base::Optional<GenericUserInterfaceProto> generic_user_interface_prepended;
- base::Optional<GenericUserInterfaceProto> generic_user_interface_appended;
- base::Optional<std::string> additional_model_identifier_to_check;
+ absl::optional<GenericUserInterfaceProto> generic_user_interface_prepended;
+ absl::optional<GenericUserInterfaceProto> generic_user_interface_appended;
+ absl::optional<std::string> additional_model_identifier_to_check;
base::OnceCallback<void(UserData*, const UserModel*)> confirm_callback;
base::OnceCallback<void(int, UserData*, const UserModel*)>
diff --git a/chromium/components/autofill_assistant/browser/user_data_util.cc b/chromium/components/autofill_assistant/browser/user_data_util.cc
index 67a5227db8c..196d5bcf1f7 100644
--- a/chromium/components/autofill_assistant/browser/user_data_util.cc
+++ b/chromium/components/autofill_assistant/browser/user_data_util.cc
@@ -159,15 +159,14 @@ bool IsCompleteAddress(const autofill::AutofillProfile* profile,
return true;
}
-template <typename T>
ClientStatus ExtractProfileAndFormatAutofillValue(
- const T& profile,
- const std::string& value_expression,
+ const AutofillProfile& profile,
+ const ValueExpression& value_expression,
const UserData* user_data,
bool quote_meta,
std::string* out_value) {
- if (profile.identifier().empty() || value_expression.empty()) {
- VLOG(1) << "|autofill_value| with empty "
+ if (profile.identifier().empty() || value_expression.chunk().empty()) {
+ VLOG(1) << "|value_expression| with empty "
"|profile.identifier| or |value_expression|";
return ClientStatus(INVALID_ACTION);
}
@@ -182,18 +181,12 @@ ClientStatus ExtractProfileAndFormatAutofillValue(
auto mappings =
field_formatter::CreateAutofillMappings(*address,
/* locale= */ "en-US");
- if (quote_meta) {
- for (const auto& it : mappings) {
- mappings[it.first] = re2::RE2::QuoteMeta(it.second);
- }
- }
- auto value = field_formatter::FormatString(value_expression, mappings,
- /* strict= */ true);
- if (!value.has_value()) {
- return ClientStatus(AUTOFILL_INFO_NOT_AVAILABLE);
+ ClientStatus format_status = field_formatter::FormatExpression(
+ value_expression, mappings, quote_meta, out_value);
+ if (!format_status.ok()) {
+ return format_status;
}
- out_value->assign(*value);
return OkClientStatus();
}
@@ -421,18 +414,20 @@ bool IsCompleteCreditCard(
ClientStatus GetFormattedAutofillValue(const AutofillValue& autofill_value,
const UserData* user_data,
std::string* out_value) {
- return ExtractProfileAndFormatAutofillValue<AutofillValue::Profile>(
+ return ExtractProfileAndFormatAutofillValue(
autofill_value.profile(), autofill_value.value_expression(), user_data,
/* quote_meta= */ false, out_value);
}
ClientStatus GetFormattedAutofillValue(
- const AutofillValueRegexp& autofill_value,
+ const AutofillValueRegexp& autofill_value_regexp,
const UserData* user_data,
std::string* out_value) {
- return ExtractProfileAndFormatAutofillValue<AutofillValueRegexp::Profile>(
- autofill_value.profile(), autofill_value.value_expression().re2(),
- user_data, /* quote_meta= */ true, out_value);
+ return ExtractProfileAndFormatAutofillValue(
+ autofill_value_regexp.profile(),
+ autofill_value_regexp.value_expression_re2().value_expression(),
+ user_data,
+ /* quote_meta= */ true, out_value);
}
void GetPasswordManagerValue(
@@ -491,4 +486,40 @@ ClientStatus GetClientMemoryStringValue(const std::string& client_memory_key,
return OkClientStatus();
}
+void ResolveTextValue(const TextValue& text_value,
+ const ElementFinder::Result& target_element,
+ const ActionDelegate* action_delegate,
+ base::OnceCallback<void(const ClientStatus&,
+ const std::string&)> callback) {
+ std::string value;
+ ClientStatus status = OkClientStatus();
+ switch (text_value.value_case()) {
+ case TextValue::kText:
+ value = text_value.text();
+ break;
+ case TextValue::kAutofillValue: {
+ status = GetFormattedAutofillValue(
+ text_value.autofill_value(), action_delegate->GetUserData(), &value);
+ break;
+ }
+ case TextValue::kPasswordManagerValue: {
+ GetPasswordManagerValue(text_value.password_manager_value(),
+ target_element, action_delegate->GetUserData(),
+ action_delegate->GetWebsiteLoginManager(),
+ std::move(callback));
+ return;
+ }
+ case TextValue::kClientMemoryKey: {
+ status =
+ GetClientMemoryStringValue(text_value.client_memory_key(),
+ action_delegate->GetUserData(), &value);
+ break;
+ }
+ case TextValue::VALUE_NOT_SET:
+ status = ClientStatus(INVALID_ACTION);
+ }
+
+ std::move(callback).Run(status, value);
+}
+
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/user_data_util.h b/chromium/components/autofill_assistant/browser/user_data_util.h
index aae6a1e0cd8..246cee44442 100644
--- a/chromium/components/autofill_assistant/browser/user_data_util.h
+++ b/chromium/components/autofill_assistant/browser/user_data_util.h
@@ -10,6 +10,7 @@
#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/action_value.pb.h"
+#include "components/autofill_assistant/browser/actions/action_delegate.h"
#include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/user_data.h"
@@ -89,7 +90,7 @@ ClientStatus GetFormattedAutofillValue(const AutofillValue& autofill_value,
const UserData* user_data,
std::string* out_value);
ClientStatus GetFormattedAutofillValue(
- const AutofillValueRegexp& autofill_value,
+ const AutofillValueRegexp& autofill_value_regexp,
const UserData* user_data,
std::string* out_value);
@@ -104,6 +105,14 @@ ClientStatus GetClientMemoryStringValue(const std::string& client_memory_key,
const UserData* user_data,
std::string* out_value);
+// Take a |text_value| and resolve its content to a string. Reports the result
+// through the |callback|.
+void ResolveTextValue(
+ const TextValue& text_value,
+ const ElementFinder::Result& target_element,
+ const ActionDelegate* action_delegate,
+ base::OnceCallback<void(const ClientStatus&, const std::string&)> callback);
+
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_USER_DATA_UTIL_H_
diff --git a/chromium/components/autofill_assistant/browser/user_data_util_unittest.cc b/chromium/components/autofill_assistant/browser/user_data_util_unittest.cc
index fabebeb21a7..fc0593f319f 100644
--- a/chromium/components/autofill_assistant/browser/user_data_util_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/user_data_util_unittest.cc
@@ -15,11 +15,14 @@
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill_assistant/browser/action_value.pb.h"
#include "components/autofill_assistant/browser/actions/action_test_utils.h"
+#include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
#include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/mock_website_login_manager.h"
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/user_data.h"
-#include "content/public/test/navigation_simulator.h"
+#include "components/autofill_assistant/browser/user_model.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -688,131 +691,133 @@ TEST(UserDataUtilTest, CompleteCreditCardWithBadNetwork) {
EXPECT_TRUE(IsCompleteCreditCard(&card, &address, payment_options_visa));
}
-TEST(UserDataUtilTest, RequestEmptyAutofillValue) {
- UserData user_data;
+class UserDataUtilTextValueTest : public testing::Test {
+ public:
+ UserDataUtilTextValueTest() {}
+
+ void SetUp() override {
+ web_contents_ = content::WebContentsTester::CreateTestWebContents(
+ &browser_context_, nullptr);
+
+ ON_CALL(mock_action_delegate_, GetUserData)
+ .WillByDefault(Return(&user_data_));
+ ON_CALL(mock_action_delegate_, GetWebsiteLoginManager)
+ .WillByDefault(Return(&mock_website_login_manager_));
+ }
+
+ MOCK_METHOD2(OnResult, void(const ClientStatus&, const std::string&));
+
+ protected:
+ content::BrowserTaskEnvironment task_environment_;
+ content::RenderViewHostTestEnabler rvh_test_enabler_;
+ content::TestBrowserContext browser_context_;
+ std::unique_ptr<content::WebContents> web_contents_;
+ MockActionDelegate mock_action_delegate_;
+ UserData user_data_;
+ UserModel user_model_;
+ MockWebsiteLoginManager mock_website_login_manager_;
+};
+
+TEST_F(UserDataUtilTextValueTest, RequestEmptyAutofillValue) {
AutofillValue autofill_value;
std::string result;
- EXPECT_EQ(GetFormattedAutofillValue(autofill_value, &user_data, &result)
+ EXPECT_EQ(GetFormattedAutofillValue(autofill_value, &user_data_, &result)
.proto_status(),
INVALID_ACTION);
EXPECT_EQ(result, "");
}
-TEST(UserDataUtilTest, RequestDataFromUnknownProfile) {
- UserData user_data;
+TEST_F(UserDataUtilTextValueTest, RequestDataFromUnknownProfile) {
AutofillValue autofill_value;
autofill_value.mutable_profile()->set_identifier("none");
- autofill_value.set_value_expression("value");
+ autofill_value.mutable_value_expression()->add_chunk()->set_text("text");
+
std::string result;
- EXPECT_EQ(GetFormattedAutofillValue(autofill_value, &user_data, &result)
+ EXPECT_EQ(GetFormattedAutofillValue(autofill_value, &user_data_, &result)
.proto_status(),
PRECONDITION_FAILED);
EXPECT_EQ(result, "");
}
-TEST(UserDataUtilTest, RequestUnknownDataFromKnownProfile) {
- UserData user_data;
+TEST_F(UserDataUtilTextValueTest, RequestUnknownDataFromKnownProfile) {
autofill::AutofillProfile contact(base::GenerateGUID(),
autofill::test::kEmptyOrigin);
// Middle name is expected to be empty.
autofill::test::SetProfileInfo(&contact, "John", /* middle name */ "", "Doe",
"", "", "", "", "", "", "", "", "");
- user_data.selected_addresses_["contact"] =
- std::make_unique<autofill::AutofillProfile>(contact);
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(contact),
+ &user_data_);
AutofillValue autofill_value;
autofill_value.mutable_profile()->set_identifier("contact");
- autofill_value.set_value_expression(
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_MIDDLE)),
- "}"}));
+ autofill_value.mutable_value_expression()->add_chunk()->set_key(
+ static_cast<int>(autofill::ServerFieldType::NAME_MIDDLE));
std::string result;
- EXPECT_EQ(GetFormattedAutofillValue(autofill_value, &user_data, &result)
+ EXPECT_EQ(GetFormattedAutofillValue(autofill_value, &user_data_, &result)
.proto_status(),
AUTOFILL_INFO_NOT_AVAILABLE);
EXPECT_EQ(result, "");
}
-TEST(UserDataUtilTest, RequestKnownDataFromKnownProfile) {
- UserData user_data;
+TEST_F(UserDataUtilTextValueTest, RequestKnownDataFromKnownProfile) {
autofill::AutofillProfile contact(base::GenerateGUID(),
autofill::test::kEmptyOrigin);
autofill::test::SetProfileInfo(&contact, "John", /* middle name */ "", "Doe",
"", "", "", "", "", "", "", "", "");
- user_data.selected_addresses_["contact"] =
- std::make_unique<autofill::AutofillProfile>(contact);
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(contact),
+ &user_data_);
AutofillValue autofill_value;
autofill_value.mutable_profile()->set_identifier("contact");
- autofill_value.set_value_expression(
- base::StrCat({"${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}"}));
+ autofill_value.mutable_value_expression()->add_chunk()->set_key(
+ static_cast<int>(autofill::ServerFieldType::NAME_FIRST));
std::string result;
EXPECT_TRUE(
- GetFormattedAutofillValue(autofill_value, &user_data, &result).ok());
+ GetFormattedAutofillValue(autofill_value, &user_data_, &result).ok());
EXPECT_EQ(result, "John");
}
-TEST(UserDataUtilTest, EscapeDataFromProfile) {
- UserData user_data;
+TEST_F(UserDataUtilTextValueTest, EscapeDataFromProfile) {
autofill::AutofillProfile contact(base::GenerateGUID(),
autofill::test::kEmptyOrigin);
autofill::test::SetProfileInfo(&contact, "Jo.h*n", /* middle name */ "",
"Doe", "", "", "", "", "", "", "", "", "");
- user_data.selected_addresses_["contact"] =
- std::make_unique<autofill::AutofillProfile>(contact);
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(contact),
+ &user_data_);
AutofillValueRegexp autofill_value;
autofill_value.mutable_profile()->set_identifier("contact");
- autofill_value.mutable_value_expression()->set_re2(
- base::StrCat({"^${",
- base::NumberToString(static_cast<int>(
- autofill::ServerFieldType::NAME_FIRST)),
- "}$"}));
+ *autofill_value.mutable_value_expression_re2()->mutable_value_expression() =
+ test_util::ValueExpressionBuilder()
+ .addChunk("^")
+ .addChunk(autofill::ServerFieldType::NAME_FIRST)
+ .addChunk("$")
+ .toProto();
std::string result;
EXPECT_TRUE(
- GetFormattedAutofillValue(autofill_value, &user_data, &result).ok());
+ GetFormattedAutofillValue(autofill_value, &user_data_, &result).ok());
EXPECT_EQ(result, "^Jo\\.h\\*n$");
}
-class UserDataPasswordManagerValueTest
- : public content::RenderViewHostTestHarness {
- public:
- UserDataPasswordManagerValueTest()
- : RenderViewHostTestHarness(
- base::test::TaskEnvironment::MainThreadType::UI,
- base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
- ~UserDataPasswordManagerValueTest() override {}
-
- void SetUp() override { RenderViewHostTestHarness::SetUp(); }
-
- MOCK_METHOD2(OnResult, void(const ClientStatus&, const std::string&));
-
- protected:
- UserData user_data_;
- MockWebsiteLoginManager mock_website_login_manager_;
-};
-
-TEST_F(UserDataPasswordManagerValueTest,
- GetCredentialsFromDifferentDomainFails) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+TEST_F(UserDataUtilTextValueTest, GetCredentialsFromDifferentDomainFails) {
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL("https://www.example.com"), "username");
ElementFinder::Result element;
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL("https://www.other.com"), web_contents()->GetMainFrame());
- element.container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("https://www.other.com"));
+ element.container_frame_host = web_contents_->GetMainFrame();
EXPECT_CALL(*this,
OnResult(EqualsStatus(ClientStatus(PASSWORD_ORIGIN_MISMATCH)),
@@ -822,49 +827,48 @@ TEST_F(UserDataPasswordManagerValueTest,
PasswordManagerValue password_value;
password_value.set_credential_type(PasswordManagerValue::PASSWORD);
- GetPasswordManagerValue(
- password_value, element, &user_data_, &mock_website_login_manager_,
- base::BindOnce(&UserDataPasswordManagerValueTest::OnResult,
- base::Unretained(this)));
+ GetPasswordManagerValue(password_value, element, &user_data_,
+ &mock_website_login_manager_,
+ base::BindOnce(&UserDataUtilTextValueTest::OnResult,
+ base::Unretained(this)));
PasswordManagerValue username_value;
username_value.set_credential_type(PasswordManagerValue::USERNAME);
- GetPasswordManagerValue(
- username_value, element, &user_data_, &mock_website_login_manager_,
- base::BindOnce(&UserDataPasswordManagerValueTest::OnResult,
- base::Unretained(this)));
+ GetPasswordManagerValue(username_value, element, &user_data_,
+ &mock_website_login_manager_,
+ base::BindOnce(&UserDataUtilTextValueTest::OnResult,
+ base::Unretained(this)));
}
-TEST_F(UserDataPasswordManagerValueTest, GetUsernameFromSameDomain) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+TEST_F(UserDataUtilTextValueTest, GetUsernameFromSameDomain) {
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL("https://www.example.com"), "username");
ElementFinder::Result element;
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL("https://www.example.com"), web_contents()->GetMainFrame());
- element.container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("https://www.example.com"));
+ element.container_frame_host = web_contents_->GetMainFrame();
PasswordManagerValue password_manager_value;
password_manager_value.set_credential_type(PasswordManagerValue::USERNAME);
EXPECT_CALL(*this, OnResult(EqualsStatus(OkClientStatus()), "username"));
- GetPasswordManagerValue(
- password_manager_value, element, &user_data_,
- &mock_website_login_manager_,
- base::BindOnce(&UserDataPasswordManagerValueTest::OnResult,
- base::Unretained(this)));
+ GetPasswordManagerValue(password_manager_value, element, &user_data_,
+ &mock_website_login_manager_,
+ base::BindOnce(&UserDataUtilTextValueTest::OnResult,
+ base::Unretained(this)));
}
-TEST_F(UserDataPasswordManagerValueTest, GetStoredPasswordFromSameDomain) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+TEST_F(UserDataUtilTextValueTest, GetStoredPasswordFromSameDomain) {
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL("https://www.example.com"), "username");
ElementFinder::Result element;
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL("https://www.example.com"), web_contents()->GetMainFrame());
- element.container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("https://www.example.com"));
+ element.container_frame_host = web_contents_->GetMainFrame();
PasswordManagerValue password_manager_value;
password_manager_value.set_credential_type(PasswordManagerValue::PASSWORD);
@@ -873,21 +877,20 @@ TEST_F(UserDataPasswordManagerValueTest, GetStoredPasswordFromSameDomain) {
.WillOnce(RunOnceCallback<1>(true, "password"));
EXPECT_CALL(*this, OnResult(EqualsStatus(OkClientStatus()), "password"));
- GetPasswordManagerValue(
- password_manager_value, element, &user_data_,
- &mock_website_login_manager_,
- base::BindOnce(&UserDataPasswordManagerValueTest::OnResult,
- base::Unretained(this)));
+ GetPasswordManagerValue(password_manager_value, element, &user_data_,
+ &mock_website_login_manager_,
+ base::BindOnce(&UserDataUtilTextValueTest::OnResult,
+ base::Unretained(this)));
}
-TEST_F(UserDataPasswordManagerValueTest, GetStoredPasswordFails) {
- user_data_.selected_login_ = base::make_optional<WebsiteLoginManager::Login>(
+TEST_F(UserDataUtilTextValueTest, GetStoredPasswordFails) {
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
GURL("https://www.example.com"), "username");
ElementFinder::Result element;
- content::NavigationSimulator::NavigateAndCommitFromDocument(
- GURL("https://www.example.com"), web_contents()->GetMainFrame());
- element.container_frame_host = web_contents()->GetMainFrame();
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("https://www.example.com"));
+ element.container_frame_host = web_contents_->GetMainFrame();
PasswordManagerValue password_manager_value;
password_manager_value.set_credential_type(PasswordManagerValue::PASSWORD);
@@ -898,41 +901,109 @@ TEST_F(UserDataPasswordManagerValueTest, GetStoredPasswordFails) {
OnResult(EqualsStatus(ClientStatus(AUTOFILL_INFO_NOT_AVAILABLE)),
std::string()));
- GetPasswordManagerValue(
- password_manager_value, element, &user_data_,
- &mock_website_login_manager_,
- base::BindOnce(&UserDataPasswordManagerValueTest::OnResult,
- base::Unretained(this)));
+ GetPasswordManagerValue(password_manager_value, element, &user_data_,
+ &mock_website_login_manager_,
+ base::BindOnce(&UserDataUtilTextValueTest::OnResult,
+ base::Unretained(this)));
}
-TEST(UserDataUtilTest, ClientMemoryKey) {
- UserData user_data;
+TEST_F(UserDataUtilTextValueTest, ClientMemoryKey) {
ValueProto value_proto;
value_proto.mutable_strings()->add_values("Hello World");
- user_data.additional_values_["key"] = value_proto;
+ user_data_.additional_values_["key"] = value_proto;
std::string result;
- EXPECT_TRUE(GetClientMemoryStringValue("key", &user_data, &result).ok());
+ EXPECT_TRUE(GetClientMemoryStringValue("key", &user_data_, &result).ok());
EXPECT_EQ(result, "Hello World");
}
-TEST(UserDataUtilTest, EmptyClientMemoryKey) {
- UserData user_data;
+TEST_F(UserDataUtilTextValueTest, EmptyClientMemoryKey) {
std::string result;
EXPECT_EQ(INVALID_ACTION,
- GetClientMemoryStringValue(std::string(), &user_data, &result)
+ GetClientMemoryStringValue(std::string(), &user_data_, &result)
.proto_status());
}
-TEST(UserDataUtilTest, NonExistingClientMemoryKey) {
- UserData user_data;
+TEST_F(UserDataUtilTextValueTest, NonExistingClientMemoryKey) {
std::string result;
EXPECT_EQ(
PRECONDITION_FAILED,
- GetClientMemoryStringValue("key", &user_data, &result).proto_status());
+ GetClientMemoryStringValue("key", &user_data_, &result).proto_status());
+}
+
+TEST_F(UserDataUtilTextValueTest, TextValueText) {
+ TextValue text_value;
+ text_value.set_text("text");
+
+ EXPECT_CALL(*this, OnResult(EqualsStatus(OkClientStatus()), "text"));
+
+ ResolveTextValue(text_value, ElementFinder::Result(), &mock_action_delegate_,
+ base::BindOnce(&UserDataUtilTextValueTest::OnResult,
+ base::Unretained(this)));
+}
+
+TEST_F(UserDataUtilTextValueTest, TextValueAutofillValue) {
+ autofill::AutofillProfile contact(base::GenerateGUID(),
+ autofill::test::kEmptyOrigin);
+ autofill::test::SetProfileInfo(&contact, "John", /* middle name */ "", "Doe",
+ "", "", "", "", "", "", "", "", "");
+ user_model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(contact),
+ &user_data_);
+
+ TextValue text_value;
+ text_value.mutable_autofill_value()->mutable_profile()->set_identifier(
+ "contact");
+ text_value.mutable_autofill_value()
+ ->mutable_value_expression()
+ ->add_chunk()
+ ->set_key(static_cast<int>(autofill::ServerFieldType::NAME_FIRST));
+
+ EXPECT_CALL(*this, OnResult(EqualsStatus(OkClientStatus()), "John"));
+
+ ResolveTextValue(text_value, ElementFinder::Result(), &mock_action_delegate_,
+ base::BindOnce(&UserDataUtilTextValueTest::OnResult,
+ base::Unretained(this)));
+}
+
+TEST_F(UserDataUtilTextValueTest, TextValuePasswordManagerValue) {
+ user_data_.selected_login_ = absl::make_optional<WebsiteLoginManager::Login>(
+ GURL("https://www.example.com"), "username");
+
+ ElementFinder::Result element;
+ content::WebContentsTester::For(web_contents_.get())
+ ->NavigateAndCommit(GURL("https://www.example.com"));
+ element.container_frame_host = web_contents_->GetMainFrame();
+
+ TextValue text_value;
+ text_value.mutable_password_manager_value()->set_credential_type(
+ PasswordManagerValue::PASSWORD);
+
+ EXPECT_CALL(mock_website_login_manager_, OnGetPasswordForLogin(_, _))
+ .WillOnce(RunOnceCallback<1>(true, "password"));
+ EXPECT_CALL(*this, OnResult(EqualsStatus(OkClientStatus()), "password"));
+
+ ResolveTextValue(text_value, element, &mock_action_delegate_,
+ base::BindOnce(&UserDataUtilTextValueTest::OnResult,
+ base::Unretained(this)));
+}
+
+TEST_F(UserDataUtilTextValueTest, TextValueClientMemoryKey) {
+ ValueProto value_proto;
+ value_proto.mutable_strings()->add_values("Hello World");
+ user_data_.additional_values_["key"] = value_proto;
+
+ TextValue text_value;
+ text_value.set_client_memory_key("key");
+
+ EXPECT_CALL(*this, OnResult(EqualsStatus(OkClientStatus()), "Hello World"));
+
+ ResolveTextValue(text_value, ElementFinder::Result(), &mock_action_delegate_,
+ base::BindOnce(&UserDataUtilTextValueTest::OnResult,
+ base::Unretained(this)));
}
} // namespace
diff --git a/chromium/components/autofill_assistant/browser/user_model.cc b/chromium/components/autofill_assistant/browser/user_model.cc
index f7c2c947ac5..7cc584b2ab3 100644
--- a/chromium/components/autofill_assistant/browser/user_model.cc
+++ b/chromium/components/autofill_assistant/browser/user_model.cc
@@ -19,10 +19,10 @@ static const char* const kExtractArraySubidentifierRegex = R"(^(\w+)\[(.+)\]$)";
// Simple wrapper around value_util::GetNthValue to unwrap the base::optional
// |value|.
-base::Optional<ValueProto> GetNthValue(const base::Optional<ValueProto>& value,
+absl::optional<ValueProto> GetNthValue(const absl::optional<ValueProto>& value,
int index) {
if (!value.has_value()) {
- return base::nullopt;
+ return absl::nullopt;
}
return GetNthValue(*value, index);
@@ -30,15 +30,15 @@ base::Optional<ValueProto> GetNthValue(const base::Optional<ValueProto>& value,
// Same as above, but expects |index_value| to point to a single integer value
// specifying the index to retrieve.
-base::Optional<ValueProto> GetNthValue(
- const base::Optional<ValueProto>& value,
- const base::Optional<ValueProto>& index_value) {
+absl::optional<ValueProto> GetNthValue(
+ const absl::optional<ValueProto>& value,
+ const absl::optional<ValueProto>& index_value) {
if (!value.has_value() || !index_value.has_value()) {
- return base::nullopt;
+ return absl::nullopt;
}
if (!AreAllValuesOfSize({*index_value}, 1) ||
!AreAllValuesOfType({*index_value}, ValueProto::kInts)) {
- return base::nullopt;
+ return absl::nullopt;
}
return GetNthValue(*value, index_value->ints().values().at(0));
@@ -73,7 +73,7 @@ void UserModel::SetValue(const std::string& identifier,
}
}
-base::Optional<ValueProto> UserModel::GetValue(
+absl::optional<ValueProto> UserModel::GetValue(
const std::string& identifier) const {
auto it = values_.find(identifier);
if (it != values_.end()) {
@@ -94,10 +94,10 @@ base::Optional<ValueProto> UserModel::GetValue(
}
}
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<ValueProto> UserModel::GetValue(
+absl::optional<ValueProto> UserModel::GetValue(
const ValueReferenceProto& reference) const {
switch (reference.kind_case()) {
case ValueReferenceProto::kValue:
@@ -105,7 +105,7 @@ base::Optional<ValueProto> UserModel::GetValue(
case ValueReferenceProto::kModelIdentifier:
return GetValue(reference.model_identifier());
case ValueReferenceProto::KIND_NOT_SET:
- return base::nullopt;
+ return absl::nullopt;
}
}
@@ -154,6 +154,17 @@ void UserModel::SetAutofillCreditCards(
credit_cards_[credit_card->guid()] = std::move(credit_card);
}
}
+void UserModel::SetSelectedCreditCard(
+ std::unique_ptr<autofill::CreditCard> card,
+ UserData* user_data) {
+ if (card == nullptr) {
+ selected_card_.reset();
+ user_data->selected_card_.reset();
+ return;
+ }
+ selected_card_ = std::make_unique<autofill::CreditCard>(*card);
+ user_data->selected_card_ = std::move(card);
+}
void UserModel::SetAutofillProfiles(
std::unique_ptr<std::vector<std::unique_ptr<autofill::AutofillProfile>>>
@@ -168,19 +179,74 @@ void UserModel::SetCurrentURL(GURL current_url) {
current_url_ = current_url;
}
+void UserModel::SetSelectedAutofillProfile(
+ const std::string& profile_name,
+ std::unique_ptr<autofill::AutofillProfile> profile,
+ UserData* user_data) {
+ // Set the profile in the UserModel.
+ auto user_model_it = selected_profiles_.find(profile_name);
+ if (user_model_it != selected_profiles_.end()) {
+ selected_profiles_.erase(user_model_it);
+ }
+ if (profile != nullptr) {
+ selected_profiles_.emplace(
+ profile_name, std::make_unique<autofill::AutofillProfile>(*profile));
+ }
+
+ // Set the profile in the UserData.
+ // TODO(b/187286050): migrate to UserModel so that we can avoid this
+ // duplication.
+ auto user_data_it = user_data->selected_addresses_.find(profile_name);
+ if (user_data_it != user_data->selected_addresses_.end()) {
+ user_data->selected_addresses_.erase(user_data_it);
+ }
+ if (profile != nullptr) {
+ user_data->selected_addresses_.emplace(profile_name, std::move(profile));
+ }
+}
+
const autofill::CreditCard* UserModel::GetCreditCard(
- const std::string& guid) const {
- auto it = credit_cards_.find(guid);
- if (it == credit_cards_.end()) {
- return nullptr;
+ const AutofillCreditCardProto& proto) const {
+ switch (proto.identifier_case()) {
+ case AutofillCreditCardProto::kGuid: {
+ auto it = credit_cards_.find(proto.guid());
+ if (it == credit_cards_.end()) {
+ return nullptr;
+ }
+ return it->second.get();
+ }
+ case AutofillCreditCardProto::kSelectedCreditCard:
+ return GetSelectedCreditCard();
+ case AutofillCreditCardProto::IDENTIFIER_NOT_SET:
+ return nullptr;
}
- return it->second.get();
+}
+
+const autofill::CreditCard* UserModel::GetSelectedCreditCard() const {
+ return selected_card_.get();
}
const autofill::AutofillProfile* UserModel::GetProfile(
- const std::string& guid) const {
- auto it = profiles_.find(guid);
- if (it == profiles_.end()) {
+ const AutofillProfileProto& proto) const {
+ switch (proto.identifier_case()) {
+ case AutofillProfileProto::kGuid: {
+ auto it = profiles_.find(proto.guid());
+ if (it == profiles_.end()) {
+ return nullptr;
+ }
+ return it->second.get();
+ }
+ case AutofillProfileProto::kSelectedProfileName:
+ return GetSelectedAutofillProfile(proto.selected_profile_name());
+ case AutofillProfileProto::IDENTIFIER_NOT_SET:
+ return nullptr;
+ }
+}
+
+const autofill::AutofillProfile* UserModel::GetSelectedAutofillProfile(
+ const std::string& profile_name) const {
+ auto it = selected_profiles_.find(profile_name);
+ if (it == selected_profiles_.end()) {
return nullptr;
}
return it->second.get();
diff --git a/chromium/components/autofill_assistant/browser/user_model.h b/chromium/components/autofill_assistant/browser/user_model.h
index c1c88811019..f920ae36701 100644
--- a/chromium/components/autofill_assistant/browser/user_model.h
+++ b/chromium/components/autofill_assistant/browser/user_model.h
@@ -12,11 +12,12 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#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/model.pb.h"
+#include "components/autofill_assistant/browser/user_data.h"
#include "components/autofill_assistant/browser/value_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace autofill_assistant {
@@ -54,22 +55,22 @@ class UserModel {
// replaced (see |AddIdentifierPlaceholders|).
// - Also supports the array operator to retrieve
// a specific element of a list, e.g., "identifier[0]" to get the first item.
- base::Optional<ValueProto> GetValue(const std::string& identifier) const;
+ absl::optional<ValueProto> GetValue(const std::string& identifier) const;
// Returns the value for |reference| or nullopt if there is no such value.
- base::Optional<ValueProto> GetValue(
+ absl::optional<ValueProto> GetValue(
const ValueReferenceProto& reference) const;
// Returns all specified values in a new std::vector. Returns nullopt if any
// of the requested values was not found.
template <class T>
- base::Optional<std::vector<ValueProto>> GetValues(
+ absl::optional<std::vector<ValueProto>> GetValues(
const T& value_references) const {
std::vector<ValueProto> values;
for (const auto& reference : value_references) {
auto value = GetValue(reference);
if (!value.has_value()) {
- return base::nullopt;
+ return absl::nullopt;
}
values.emplace_back(*value);
}
@@ -81,18 +82,44 @@ class UserModel {
std::unique_ptr<std::vector<std::unique_ptr<autofill::CreditCard>>>
credit_cards);
+ // Sets the selected credit card. A nullptr |card| will clear the selected
+ // card. This also sets it to |user_data|.
+ // TODO(b/187286050) complete the migration to UserModel and remove UserData.
+ void SetSelectedCreditCard(std::unique_ptr<autofill::CreditCard> card,
+ UserData* user_data);
+
// Replaces the set of available autofill profiles.
void SetAutofillProfiles(
std::unique_ptr<std::vector<std::unique_ptr<autofill::AutofillProfile>>>
profiles);
+ // Sets the selected autofill profile for |profile_name|. A nullptr |profile|
+ // will clear the entry. The profile is also set in |user_data|.
+ // TODO(b/187286050) complete the migration to UserModel and remove UserData.
+ void SetSelectedAutofillProfile(
+ const std::string& profile_name,
+ std::unique_ptr<autofill::AutofillProfile> profile,
+ UserData* user_data);
+
void SetCurrentURL(GURL current_url);
- // Returns the credit card with |guid| or nullptr if there is no such card.
- const autofill::CreditCard* GetCreditCard(const std::string& guid) const;
+ // Returns the credit card specified by |proto| or nullptr if there is no such
+ // card.
+ const autofill::CreditCard* GetCreditCard(
+ const AutofillCreditCardProto& proto) const;
+
+ // Returns the selected credit card or nullptr if no card has been selected.
+ const autofill::CreditCard* GetSelectedCreditCard() const;
- // Returns the profile with |guid| or nullptr if there is no such profile.
- const autofill::AutofillProfile* GetProfile(const std::string& guid) const;
+ // Returns the profile specified by |proto| or nullptr if there is no such
+ // profile.
+ const autofill::AutofillProfile* GetProfile(
+ const AutofillProfileProto& proto) const;
+
+ // Returns the selected profile for the specified |profile_name| or nullptr if
+ // there is no such profile.
+ const autofill::AutofillProfile* GetSelectedAutofillProfile(
+ const std::string& profile_name) const;
GURL GetCurrentURL() const;
@@ -113,8 +140,16 @@ class UserModel {
friend class UserModelTest;
std::map<std::string, ValueProto> values_;
+ // Guid to credit card map.
std::map<std::string, std::unique_ptr<autofill::CreditCard>> credit_cards_;
+ // The selected credit card.
+ std::unique_ptr<autofill::CreditCard> selected_card_;
+ // Guid to profile map.
std::map<std::string, std::unique_ptr<autofill::AutofillProfile>> profiles_;
+ // Profile name to profile map.
+ std::map<std::string, std::unique_ptr<autofill::AutofillProfile>>
+ selected_profiles_;
+
GURL current_url_;
base::ObserverList<Observer> observers_;
base::WeakPtrFactory<UserModel> weak_ptr_factory_{this};
diff --git a/chromium/components/autofill_assistant/browser/user_model_unittest.cc b/chromium/components/autofill_assistant/browser/user_model_unittest.cc
index 799d606e023..15c4262fbff 100644
--- a/chromium/components/autofill_assistant/browser/user_model_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/user_model_unittest.cc
@@ -14,6 +14,7 @@ const char kFakeUrl[] = "https://www.example.com";
using ::testing::_;
using ::testing::Eq;
using ::testing::InSequence;
+using ::testing::IsNull;
using ::testing::Pair;
using ::testing::Property;
using ::testing::SizeIs;
@@ -235,8 +236,8 @@ TEST_F(UserModelTest, SubscriptAccess) {
EXPECT_EQ(model_.GetValue("value[2]"), SimpleValue(std::string("c")));
EXPECT_EQ(model_.GetValue("value[001]"), SimpleValue(std::string("b")));
- EXPECT_EQ(model_.GetValue("value[3]"), base::nullopt);
- EXPECT_EQ(model_.GetValue("value[-1]"), base::nullopt);
+ EXPECT_EQ(model_.GetValue("value[3]"), absl::nullopt);
+ EXPECT_EQ(model_.GetValue("value[-1]"), absl::nullopt);
model_.SetValue("index", SimpleValue(0));
EXPECT_EQ(model_.GetValue("value[index]"), SimpleValue(std::string("a")));
@@ -245,14 +246,14 @@ TEST_F(UserModelTest, SubscriptAccess) {
model_.SetValue("index", SimpleValue(2));
EXPECT_EQ(model_.GetValue("value[index]"), SimpleValue(std::string("c")));
model_.SetValue("index", SimpleValue(3));
- EXPECT_EQ(model_.GetValue("value[index]"), base::nullopt);
+ EXPECT_EQ(model_.GetValue("value[index]"), absl::nullopt);
model_.SetValue("index", SimpleValue(-1));
- EXPECT_EQ(model_.GetValue("value[index]"), base::nullopt);
+ EXPECT_EQ(model_.GetValue("value[index]"), absl::nullopt);
model_.SetValue("index", SimpleValue(0));
EXPECT_EQ(model_.GetValue("value[index[0]]"), SimpleValue(std::string("a")));
model_.SetValue("index", SimpleValue(std::string("not an index")));
- EXPECT_EQ(model_.GetValue("value[index]"), base::nullopt);
+ EXPECT_EQ(model_.GetValue("value[index]"), absl::nullopt);
ValueProto indices;
indices.mutable_ints()->add_values(2);
@@ -298,23 +299,28 @@ TEST_F(UserModelTest, IrregularModelIdentifiers) {
// irregular characters (i.e., outside of \w+).
EXPECT_EQ(model_.GetValue("normal_identifier[1]"),
SimpleValue(std::string("b")));
- EXPECT_EQ(model_.GetValue("ends_in_bracket][1]"), base::nullopt);
- EXPECT_EQ(model_.GetValue("contains_[brackets][1]"), base::nullopt);
- EXPECT_EQ(model_.GetValue("[][0]"), base::nullopt);
- EXPECT_EQ(model_.GetValue("empty_brackets[1]"), base::nullopt);
- EXPECT_EQ(model_.GetValue("empty_brackets[][1]"), base::nullopt);
+ EXPECT_EQ(model_.GetValue("ends_in_bracket][1]"), absl::nullopt);
+ EXPECT_EQ(model_.GetValue("contains_[brackets][1]"), absl::nullopt);
+ EXPECT_EQ(model_.GetValue("[][0]"), absl::nullopt);
+ EXPECT_EQ(model_.GetValue("empty_brackets[1]"), absl::nullopt);
+ EXPECT_EQ(model_.GetValue("empty_brackets[][1]"), absl::nullopt);
// Subscript access into UTF-8 identifiers is not supported.
- EXPECT_EQ(model_.GetValue("utf_8_ü万𠜎[1]"), base::nullopt);
+ EXPECT_EQ(model_.GetValue("utf_8_ü万𠜎[1]"), absl::nullopt);
}
TEST_F(UserModelTest, SetCreditCards) {
autofill::CreditCard credit_card_a(base::GenerateGUID(), kFakeUrl);
autofill::test::SetCreditCardInfo(&credit_card_a, "Marion Mitchell",
"4111 1111 1111 1111", "01", "2050", "");
+ AutofillCreditCardProto credit_card_a_proto;
+ credit_card_a_proto.set_guid(credit_card_a.guid());
autofill::CreditCard credit_card_b(base::GenerateGUID(), kFakeUrl);
autofill::test::SetCreditCardInfo(&credit_card_b, "John Doe",
"4111 1111 1111 1111", "01", "2050", "");
+ AutofillCreditCardProto credit_card_b_proto;
+ credit_card_b_proto.set_guid(credit_card_b.guid());
+
auto credit_cards =
std::make_unique<std::vector<std::unique_ptr<autofill::CreditCard>>>();
credit_cards->emplace_back(
@@ -322,12 +328,10 @@ TEST_F(UserModelTest, SetCreditCards) {
credit_cards->emplace_back(
std::make_unique<autofill::CreditCard>(credit_card_b));
model_.SetAutofillCreditCards(std::move(credit_cards));
- EXPECT_THAT(
- model_.GetCreditCard(credit_card_a.guid())->Compare(credit_card_a),
- Eq(0));
- EXPECT_THAT(
- model_.GetCreditCard(credit_card_b.guid())->Compare(credit_card_b),
- Eq(0));
+ EXPECT_THAT(model_.GetCreditCard(credit_card_a_proto)->Compare(credit_card_a),
+ Eq(0));
+ EXPECT_THAT(model_.GetCreditCard(credit_card_b_proto)->Compare(credit_card_b),
+ Eq(0));
}
TEST_F(UserModelTest, SetProfiles) {
@@ -347,8 +351,13 @@ TEST_F(UserModelTest, SetProfiles) {
profiles->emplace_back(
std::make_unique<autofill::AutofillProfile>(profile_b));
model_.SetAutofillProfiles(std::move(profiles));
- EXPECT_THAT(model_.GetProfile(profile_a.guid())->Compare(profile_a), Eq(0));
- EXPECT_THAT(model_.GetProfile(profile_b.guid())->Compare(profile_b), Eq(0));
+ AutofillProfileProto profile_a_proto;
+ profile_a_proto.set_guid(profile_a.guid());
+ AutofillProfileProto profile_b_proto;
+ profile_b_proto.set_guid(profile_b.guid());
+
+ EXPECT_THAT(model_.GetProfile(profile_a_proto)->Compare(profile_a), Eq(0));
+ EXPECT_THAT(model_.GetProfile(profile_b_proto)->Compare(profile_b), Eq(0));
}
TEST_F(UserModelTest, ClientSideOnlyNotifications) {
@@ -366,4 +375,65 @@ TEST_F(UserModelTest, ClientSideOnlyNotifications) {
EXPECT_TRUE(GetValues().at("identifier").is_client_side_only());
}
+TEST_F(UserModelTest, SetSelectedAutofillProfile) {
+ autofill::AutofillProfile profile(base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetProfileInfo(
+ &profile, "Marion", "Mitchell", "Morrison", "marion@me.xyz", "Fox",
+ "123 Zoo St.", "unit 5", "Hollywood", "CA", "91601", "US", "16505678910");
+
+ UserData user_data;
+ model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
+ EXPECT_THAT(model_.GetSelectedAutofillProfile("contact")->Compare(profile),
+ Eq(0));
+ EXPECT_THAT(user_data.selected_address("contact")->Compare(profile), Eq(0));
+ model_.SetSelectedAutofillProfile("contact", nullptr, &user_data);
+ EXPECT_THAT(model_.GetSelectedAutofillProfile("contact"), IsNull());
+ EXPECT_THAT(user_data.selected_address("contact"), IsNull());
+}
+
+TEST_F(UserModelTest, GetProfileByProfileName) {
+ autofill::AutofillProfile profile(base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetProfileInfo(
+ &profile, "Marion", "Mitchell", "Morrison", "marion@me.xyz", "Fox",
+ "123 Zoo St.", "unit 5", "Hollywood", "CA", "91601", "US", "16505678910");
+
+ UserData user_data;
+ model_.SetSelectedAutofillProfile(
+ "contact", std::make_unique<autofill::AutofillProfile>(profile),
+ &user_data);
+ AutofillProfileProto profile_proto;
+ profile_proto.set_selected_profile_name("contact");
+ EXPECT_THAT(model_.GetProfile(profile_proto)->Compare(profile), Eq(0));
+}
+
+TEST_F(UserModelTest, GetSelectedCardWithProto) {
+ autofill::CreditCard credit_card(base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetCreditCardInfo(&credit_card, "Marion Mitchell",
+ "4111 1111 1111 1111", "01", "2050", "");
+ UserData user_data;
+ model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(credit_card), &user_data);
+ AutofillCreditCardProto credit_card_proto;
+ EXPECT_THAT(model_.GetCreditCard(credit_card_proto), IsNull());
+ credit_card_proto.mutable_selected_credit_card();
+ EXPECT_THAT(model_.GetCreditCard(credit_card_proto)->Compare(credit_card),
+ Eq(0));
+}
+
+TEST_F(UserModelTest, SetSelectedCreditCard) {
+ autofill::CreditCard credit_card(base::GenerateGUID(), kFakeUrl);
+ autofill::test::SetCreditCardInfo(&credit_card, "Marion Mitchell",
+ "4111 1111 1111 1111", "01", "2050", "");
+ UserData user_data;
+ model_.SetSelectedCreditCard(
+ std::make_unique<autofill::CreditCard>(credit_card), &user_data);
+ EXPECT_THAT(model_.GetSelectedCreditCard()->Compare(credit_card), Eq(0));
+ EXPECT_THAT(user_data.selected_card()->Compare(credit_card), Eq(0));
+ model_.SetSelectedCreditCard(nullptr, &user_data);
+ EXPECT_THAT(model_.GetSelectedCreditCard(), IsNull());
+ EXPECT_THAT(user_data.selected_card(), IsNull());
+}
+
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/value_util.cc b/chromium/components/autofill_assistant/browser/value_util.cc
index 453d6da6918..d701062fa44 100644
--- a/chromium/components/autofill_assistant/browser/value_util.cc
+++ b/chromium/components/autofill_assistant/browser/value_util.cc
@@ -163,12 +163,31 @@ bool operator<(const DateProto& value_a, const DateProto& value_b) {
bool operator==(const AutofillCreditCardProto& value_a,
const AutofillCreditCardProto& value_b) {
- return value_a.guid() == value_b.guid();
+ if (value_a.identifier_case() != value_b.identifier_case())
+ return false;
+
+ switch (value_a.identifier_case()) {
+ case AutofillCreditCardProto::kGuid:
+ return value_a.guid() == value_b.guid();
+ case AutofillCreditCardProto::kSelectedCreditCard:
+ case AutofillCreditCardProto::IDENTIFIER_NOT_SET:
+ return true;
+ }
}
bool operator==(const AutofillProfileProto& value_a,
const AutofillProfileProto& value_b) {
- return value_a.guid() == value_b.guid();
+ if (value_a.identifier_case() != value_b.identifier_case())
+ return false;
+
+ switch (value_a.identifier_case()) {
+ case AutofillProfileProto::kGuid:
+ return value_a.guid() == value_b.guid();
+ case AutofillProfileProto::kSelectedProfileName:
+ return value_a.selected_profile_name() == value_b.selected_profile_name();
+ case AutofillProfileProto::IDENTIFIER_NOT_SET:
+ return true;
+ }
}
bool operator==(const LoginOptionProto& value_a,
@@ -222,12 +241,30 @@ std::ostream& operator<<(std::ostream& out, const DateProto& value) {
std::ostream& operator<<(std::ostream& out,
const AutofillCreditCardProto& value) {
- out << value.guid();
+ switch (value.identifier_case()) {
+ case AutofillCreditCardProto::kGuid:
+ out << "guid:" << value.guid();
+ break;
+ case AutofillCreditCardProto::kSelectedCreditCard:
+ out << "selected credit card";
+ break;
+ case AutofillCreditCardProto::IDENTIFIER_NOT_SET:
+ break;
+ }
return out;
}
std::ostream& operator<<(std::ostream& out, const AutofillProfileProto& value) {
- out << value.guid();
+ switch (value.identifier_case()) {
+ case AutofillProfileProto::kGuid:
+ out << "guid:" << value.guid();
+ break;
+ case AutofillProfileProto::kSelectedProfileName:
+ out << "profile name:" << value.selected_profile_name();
+ break;
+ case AutofillProfileProto::IDENTIFIER_NOT_SET:
+ break;
+ }
return out;
}
@@ -409,12 +446,12 @@ int GetValueSize(const ValueProto& value) {
}
}
-base::Optional<ValueProto> GetNthValue(const ValueProto& value, int index) {
+absl::optional<ValueProto> GetNthValue(const ValueProto& value, int index) {
if (value == ValueProto()) {
- return base::nullopt;
+ return absl::nullopt;
}
if (index < 0 || index >= GetValueSize(value)) {
- return base::nullopt;
+ return absl::nullopt;
}
ValueProto nth_value;
if (value.is_client_side_only())
@@ -458,7 +495,7 @@ base::Optional<ValueProto> GetNthValue(const ValueProto& value, int index) {
DCHECK(index == 0);
return value;
case ValueProto::KIND_NOT_SET:
- return base::nullopt;
+ return absl::nullopt;
}
}
diff --git a/chromium/components/autofill_assistant/browser/value_util.h b/chromium/components/autofill_assistant/browser/value_util.h
index dae11fcae48..34cb0669cda 100644
--- a/chromium/components/autofill_assistant/browser/value_util.h
+++ b/chromium/components/autofill_assistant/browser/value_util.h
@@ -8,8 +8,8 @@
#include <ostream>
#include <string>
#include <vector>
-#include "base/optional.h"
#include "components/autofill_assistant/browser/model.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill_assistant {
@@ -94,7 +94,7 @@ int GetValueSize(const ValueProto& value);
// Returns the |index|'th item of |value| or nullopt if |index| is
// out-of-bounds.
-base::Optional<ValueProto> GetNthValue(const ValueProto& value, int index);
+absl::optional<ValueProto> GetNthValue(const ValueProto& value, int index);
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/value_util_unittest.cc b/chromium/components/autofill_assistant/browser/value_util_unittest.cc
index 996b2561743..149844b9400 100644
--- a/chromium/components/autofill_assistant/browser/value_util_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/value_util_unittest.cc
@@ -378,8 +378,8 @@ TEST_F(ValueUtilTest, TestGetNthValue) {
EXPECT_EQ(GetNthValue(value, 1), SimpleValue(std::string("b")));
EXPECT_EQ(GetNthValue(value, 2), SimpleValue(std::string("c")));
- EXPECT_EQ(GetNthValue(value, -1), base::nullopt);
- EXPECT_EQ(GetNthValue(value, 3), base::nullopt);
+ EXPECT_EQ(GetNthValue(value, -1), absl::nullopt);
+ EXPECT_EQ(GetNthValue(value, 3), absl::nullopt);
value.set_is_client_side_only(true);
EXPECT_EQ(GetNthValue(value, 0),
@@ -398,5 +398,60 @@ TEST_F(ValueUtilTest, TestContainsClientOnlyValues) {
EXPECT_FALSE(ContainsClientOnlyValue({value_a, value_c}));
}
+TEST_F(ValueUtilTest, TestEqualOperatorForAutofillProfile) {
+ AutofillProfileProto profile_a;
+ AutofillProfileProto profile_b;
+ EXPECT_TRUE(profile_a == profile_b);
+
+ profile_a.set_guid("guid_a");
+ EXPECT_FALSE(profile_a == profile_b);
+
+ profile_b.set_guid("guid_b");
+ EXPECT_FALSE(profile_a == profile_b);
+
+ profile_b.set_guid("guid_a");
+ EXPECT_TRUE(profile_a == profile_b);
+
+ profile_a.clear_guid();
+ profile_a.set_selected_profile_name("name_a");
+ EXPECT_FALSE(profile_a == profile_b);
+
+ profile_b.clear_guid();
+ profile_b.set_selected_profile_name("name_b");
+ EXPECT_FALSE(profile_a == profile_b);
+
+ profile_b.set_selected_profile_name("name_a");
+ EXPECT_TRUE(profile_a == profile_b);
+
+ profile_a.clear_selected_profile_name();
+ EXPECT_FALSE(profile_a == profile_b);
+}
+
+TEST_F(ValueUtilTest, TestEqualOperatorForAutofillCreditCard) {
+ AutofillCreditCardProto credit_card_a;
+ AutofillCreditCardProto credit_card_b;
+ EXPECT_TRUE(credit_card_a == credit_card_b);
+
+ credit_card_a.set_guid("guid_a");
+ EXPECT_FALSE(credit_card_a == credit_card_b);
+
+ credit_card_b.set_guid("guid_b");
+ EXPECT_FALSE(credit_card_a == credit_card_b);
+
+ credit_card_b.set_guid("guid_a");
+ EXPECT_TRUE(credit_card_a == credit_card_b);
+
+ credit_card_a.clear_guid();
+ credit_card_a.mutable_selected_credit_card();
+ EXPECT_FALSE(credit_card_a == credit_card_b);
+
+ credit_card_b.clear_guid();
+ credit_card_b.mutable_selected_credit_card();
+ EXPECT_TRUE(credit_card_a == credit_card_b);
+
+ credit_card_a.clear_selected_credit_card();
+ EXPECT_FALSE(credit_card_a == credit_card_b);
+}
+
} // namespace value_util
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/viewport_mode.h b/chromium/components/autofill_assistant/browser/viewport_mode.h
index f8fe8e2c28e..b81c6d145da 100644
--- a/chromium/components/autofill_assistant/browser/viewport_mode.h
+++ b/chromium/components/autofill_assistant/browser/viewport_mode.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_VIEWPORT_MODE_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_VIEWPORT_MODE_H_
-#include <string>
-
#include "base/callback.h"
namespace autofill_assistant {
diff --git a/chromium/components/autofill_assistant/browser/wait_for_document_operation_unittest.cc b/chromium/components/autofill_assistant/browser/wait_for_document_operation_unittest.cc
index 6ebafd82ea0..86ce41a99bf 100644
--- a/chromium/components/autofill_assistant/browser/wait_for_document_operation_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/wait_for_document_operation_unittest.cc
@@ -51,7 +51,7 @@ class WaitForDocumentOperationTest : public testing::Test {
TEST_F(WaitForDocumentOperationTest, ReportsSuccess) {
EXPECT_CALL(mock_web_controller_,
- OnWaitForDocumentReadyState(_, DOCUMENT_COMPLETE, _))
+ WaitForDocumentReadyState(_, DOCUMENT_COMPLETE, _))
.WillOnce(RunOnceCallback<2>(OkClientStatus(), DOCUMENT_COMPLETE,
base::TimeDelta::FromSeconds(0)));
EXPECT_CALL(mock_callback_,
@@ -62,7 +62,7 @@ TEST_F(WaitForDocumentOperationTest, ReportsSuccess) {
TEST_F(WaitForDocumentOperationTest, ReportsFailure) {
EXPECT_CALL(mock_web_controller_,
- OnWaitForDocumentReadyState(_, DOCUMENT_COMPLETE, _))
+ WaitForDocumentReadyState(_, DOCUMENT_COMPLETE, _))
.WillOnce(RunOnceCallback<2>(ClientStatus(TIMED_OUT),
DOCUMENT_UNKNOWN_READY_STATE,
base::TimeDelta::FromSeconds(0)));
@@ -76,11 +76,11 @@ TEST_F(WaitForDocumentOperationTest, TimesOutAfterWaiting) {
// Capture the call without answering it.
WaitForDocumentOperation::Callback captured_callback;
EXPECT_CALL(mock_web_controller_,
- OnWaitForDocumentReadyState(_, DOCUMENT_COMPLETE, _))
+ WaitForDocumentReadyState(_, DOCUMENT_COMPLETE, _))
.WillOnce(Invoke([&captured_callback](
const ElementFinder::Result& optional_frame_element,
DocumentReadyState min_ready_state,
- WaitForDocumentOperation::Callback& callback) {
+ WaitForDocumentOperation::Callback callback) {
captured_callback = std::move(callback);
}));
EXPECT_CALL(mock_callback_, Run(_, _, _)).Times(0);
@@ -99,7 +99,7 @@ TEST_F(WaitForDocumentOperationTest, TimesOutAfterWaiting) {
TEST_F(WaitForDocumentOperationTest, TimeoutIsIgnoredAfterSuccess) {
EXPECT_CALL(mock_web_controller_,
- OnWaitForDocumentReadyState(_, DOCUMENT_COMPLETE, _))
+ WaitForDocumentReadyState(_, DOCUMENT_COMPLETE, _))
.WillOnce(RunOnceCallback<2>(OkClientStatus(), DOCUMENT_COMPLETE,
base::TimeDelta::FromSeconds(0)));
EXPECT_CALL(mock_callback_, Run(_, _, _)).Times(0);
diff --git a/chromium/components/autofill_assistant/browser/web/click_or_tap_worker.cc b/chromium/components/autofill_assistant/browser/web/click_or_tap_worker.cc
new file mode 100644
index 00000000000..63570a21053
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/web/click_or_tap_worker.cc
@@ -0,0 +1,156 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/autofill_assistant/browser/web/click_or_tap_worker.h"
+
+#include "base/time/time.h"
+#include "components/autofill_assistant/browser/web/web_controller_util.h"
+
+namespace autofill_assistant {
+
+ClickOrTapWorker::ClickOrTapWorker(DevtoolsClient* devtools_client)
+ : devtools_client_(devtools_client) {}
+ClickOrTapWorker::~ClickOrTapWorker() = default;
+
+void ClickOrTapWorker::Start(const ElementFinder::Result& element,
+ ClickType click_type,
+ Callback callback) {
+ DCHECK(click_type == ClickType::CLICK || click_type == ClickType::TAP);
+ click_type_ = click_type;
+
+ DCHECK(!callback_);
+ callback_ = std::move(callback);
+
+ DCHECK(!element_position_getter_);
+ node_frame_id_ = element.node_frame_id();
+ element_position_getter_ = std::make_unique<ElementPositionGetter>(
+ devtools_client_, /* max_rounds= */ 1,
+ /* check_interval= */ base::TimeDelta::FromMilliseconds(0),
+ node_frame_id_);
+
+ element_position_getter_->Start(
+ element.container_frame_host, element.object_id(),
+ base::BindOnce(&ClickOrTapWorker::OnGetCoordinates,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ClickOrTapWorker::OnGetCoordinates(const ClientStatus& status) {
+ if (!status.ok()) {
+ VLOG(1) << __func__ << " Failed to get element position.";
+ std::move(callback_).Run(status);
+ return;
+ }
+
+ int x = element_position_getter_->x();
+ int y = element_position_getter_->y();
+
+ if (click_type_ == ClickType::CLICK) {
+ devtools_client_->GetInput()->DispatchMouseEvent(
+ input::DispatchMouseEventParams::Builder()
+ .SetX(x)
+ .SetY(y)
+ .SetClickCount(1)
+ .SetButton(input::MouseButton::LEFT)
+ .SetType(input::DispatchMouseEventType::MOUSE_PRESSED)
+ .Build(),
+ node_frame_id_,
+ base::BindOnce(&ClickOrTapWorker::OnDispatchPressMouseEvent,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
+ }
+
+ if (click_type_ == ClickType::TAP) {
+ std::vector<std::unique_ptr<::autofill_assistant::input::TouchPoint>>
+ touch_points;
+ touch_points.emplace_back(
+ input::TouchPoint::Builder().SetX(x).SetY(y).Build());
+ devtools_client_->GetInput()->DispatchTouchEvent(
+ input::DispatchTouchEventParams::Builder()
+ .SetType(input::DispatchTouchEventType::TOUCH_START)
+ .SetTouchPoints(std::move(touch_points))
+ .Build(),
+ node_frame_id_,
+ base::BindOnce(&ClickOrTapWorker::OnDispatchTouchEventStart,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
+ }
+
+ NOTREACHED();
+ std::move(callback_).Run(ClientStatus(INVALID_ACTION));
+}
+
+void ClickOrTapWorker::OnDispatchPressMouseEvent(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<input::DispatchMouseEventResult> result) {
+ if (!result) {
+ VLOG(1) << __func__
+ << " Failed to dispatch mouse left button pressed event.";
+ std::move(callback_).Run(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
+ return;
+ }
+
+ int x = element_position_getter_->x();
+ int y = element_position_getter_->y();
+
+ devtools_client_->GetInput()->DispatchMouseEvent(
+ input::DispatchMouseEventParams::Builder()
+ .SetX(x)
+ .SetY(y)
+ .SetClickCount(1)
+ .SetButton(input::MouseButton::LEFT)
+ .SetType(input::DispatchMouseEventType::MOUSE_RELEASED)
+ .Build(),
+ node_frame_id_,
+ base::BindOnce(&ClickOrTapWorker::OnDispatchReleaseMouseEvent,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ClickOrTapWorker::OnDispatchReleaseMouseEvent(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<input::DispatchMouseEventResult> result) {
+ if (!result) {
+ VLOG(1) << __func__ << " Failed to dispatch release mouse event.";
+ std::move(callback_).Run(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
+ return;
+ }
+ std::move(callback_).Run(OkClientStatus());
+}
+
+void ClickOrTapWorker::OnDispatchTouchEventStart(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<input::DispatchTouchEventResult> result) {
+ if (!result) {
+ VLOG(1) << __func__ << " Failed to dispatch touch start event.";
+ std::move(callback_).Run(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
+ return;
+ }
+
+ std::vector<std::unique_ptr<::autofill_assistant::input::TouchPoint>>
+ touch_points;
+ devtools_client_->GetInput()->DispatchTouchEvent(
+ input::DispatchTouchEventParams::Builder()
+ .SetType(input::DispatchTouchEventType::TOUCH_END)
+ .SetTouchPoints(std::move(touch_points))
+ .Build(),
+ node_frame_id_,
+ base::BindOnce(&ClickOrTapWorker::OnDispatchTouchEventEnd,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ClickOrTapWorker::OnDispatchTouchEventEnd(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<input::DispatchTouchEventResult> result) {
+ if (!result) {
+ VLOG(1) << __func__ << " Failed to dispatch touch end event.";
+ std::move(callback_).Run(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
+ return;
+ }
+ std::move(callback_).Run(OkClientStatus());
+}
+
+} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/web/click_or_tap_worker.h b/chromium/components/autofill_assistant/browser/web/click_or_tap_worker.h
new file mode 100644
index 00000000000..b4f0244497b
--- /dev/null
+++ b/chromium/components/autofill_assistant/browser/web/click_or_tap_worker.h
@@ -0,0 +1,67 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_CLICK_OR_TAP_WORKER_H_
+#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_CLICK_OR_TAP_WORKER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "components/autofill_assistant/browser/action_strategy.pb.h"
+#include "components/autofill_assistant/browser/client_status.h"
+#include "components/autofill_assistant/browser/devtools/devtools/domains/types_input.h"
+#include "components/autofill_assistant/browser/devtools/devtools_client.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"
+
+namespace autofill_assistant {
+
+// Worker class for sending click or tap events.
+class ClickOrTapWorker : public WebControllerWorker {
+ public:
+ // |devtools_client| must be valid for the lifetime of the instance.
+ ClickOrTapWorker(DevtoolsClient* devtools_client);
+ ~ClickOrTapWorker() override;
+
+ // Callback called when the worker is done.
+ using Callback = base::OnceCallback<void(const ClientStatus&)>;
+
+ // Send a click or tap event to the the |elemsent|.
+ void Start(const ElementFinder::Result& element,
+ ClickType click_type,
+ Callback callback);
+
+ private:
+ void OnGetCoordinates(const ClientStatus& status);
+
+ void OnDispatchPressMouseEvent(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<input::DispatchMouseEventResult> result);
+ void OnDispatchReleaseMouseEvent(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<input::DispatchMouseEventResult> result);
+
+ void OnDispatchTouchEventStart(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<input::DispatchTouchEventResult> result);
+ void OnDispatchTouchEventEnd(
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<input::DispatchTouchEventResult> result);
+
+ DevtoolsClient* const devtools_client_;
+ Callback callback_;
+ ClickType click_type_;
+ std::string node_frame_id_;
+
+ std::unique_ptr<ElementPositionGetter> element_position_getter_;
+
+ base::WeakPtrFactory<ClickOrTapWorker> weak_ptr_factory_{this};
+};
+} // namespace autofill_assistant
+
+#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_WEB_CLICK_OR_TAP_WORKER_H_
diff --git a/chromium/components/autofill_assistant/browser/web/element_finder.h b/chromium/components/autofill_assistant/browser/web/element_finder.h
index 1856d248983..5de6c9fcbaa 100644
--- a/chromium/components/autofill_assistant/browser/web/element_finder.h
+++ b/chromium/components/autofill_assistant/browser/web/element_finder.h
@@ -30,7 +30,10 @@ class RenderFrameHost;
namespace autofill_assistant {
class DevtoolsClient;
-// Worker class to find element(s) matching a selector.
+// Worker class to find element(s) matching a selector. This will keep entering
+// iFrames until the element is found in the last frame, then returns the
+// element together with the owning frame. All subsequent operations should
+// be performed on that frame.
class ElementFinder : public WebControllerWorker {
public:
enum ResultType {
diff --git a/chromium/components/autofill_assistant/browser/web/element_store_unittest.cc b/chromium/components/autofill_assistant/browser/web/element_store_unittest.cc
index 23b61827ba1..f638f59211d 100644
--- a/chromium/components/autofill_assistant/browser/web/element_store_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/web/element_store_unittest.cc
@@ -9,6 +9,8 @@
#include "components/autofill_assistant/browser/actions/action_test_utils.h"
#include "components/autofill_assistant/browser/client_status.h"
#include "components/autofill_assistant/browser/web/element_finder.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -16,18 +18,12 @@
namespace autofill_assistant {
namespace {
-class ElementStoreTest : public content::RenderViewHostTestHarness {
+class ElementStoreTest : public testing::Test {
public:
- ElementStoreTest()
- : RenderViewHostTestHarness(
- base::test::TaskEnvironment::MainThreadType::UI,
- base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
- ~ElementStoreTest() override {}
-
void SetUp() override {
- RenderViewHostTestHarness::SetUp();
-
- element_store_ = std::make_unique<ElementStore>(web_contents());
+ web_contents_ = content::WebContentsTester::CreateTestWebContents(
+ &browser_context_, nullptr);
+ element_store_ = std::make_unique<ElementStore>(web_contents_.get());
}
protected:
@@ -36,7 +32,7 @@ class ElementStoreTest : public content::RenderViewHostTestHarness {
auto element = std::make_unique<ElementFinder::Result>();
element->dom_object.object_data.object_id = object_id;
element->dom_object.object_data.node_frame_id =
- web_contents()->GetMainFrame()->GetDevToolsFrameToken().ToString();
+ web_contents_->GetMainFrame()->GetDevToolsFrameToken().ToString();
return element;
}
@@ -47,6 +43,10 @@ class ElementStoreTest : public content::RenderViewHostTestHarness {
element_store_->AddElement(client_id, element->dom_object);
}
+ content::BrowserTaskEnvironment task_environment_;
+ content::RenderViewHostTestEnabler rvh_test_enabler_;
+ content::TestBrowserContext browser_context_;
+ std::unique_ptr<content::WebContents> web_contents_;
std::unique_ptr<ElementStore> element_store_;
};
@@ -87,7 +87,7 @@ TEST_F(ElementStoreTest, GetElementFromStoreWithNoFrameId) {
ElementFinder::Result result;
EXPECT_EQ(ACTION_APPLIED,
element_store_->GetElement("1", &result).proto_status());
- EXPECT_EQ(web_contents()->GetMainFrame(), result.container_frame_host);
+ EXPECT_EQ(web_contents_->GetMainFrame(), result.container_frame_host);
}
TEST_F(ElementStoreTest, AddElementToStoreOverwrites) {
diff --git a/chromium/components/autofill_assistant/browser/web/mock_web_controller.h b/chromium/components/autofill_assistant/browser/web/mock_web_controller.h
index b0e45b67b3a..6decdf26fd0 100644
--- a/chromium/components/autofill_assistant/browser/web/mock_web_controller.h
+++ b/chromium/components/autofill_assistant/browser/web/mock_web_controller.h
@@ -42,11 +42,16 @@ class MockWebController : public WebController {
MOCK_METHOD2(CheckOnTop,
void(const ElementFinder::Result&,
base::OnceCallback<void(const ClientStatus&)>));
- MOCK_METHOD5(SelectOption,
+ MOCK_METHOD6(SelectOption,
void(const std::string& re2,
bool case_sensitive,
SelectOptionProto::OptionComparisonAttribute
option_comparison_attribute,
+ bool strict,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> callback));
+ MOCK_METHOD3(CheckSelectedOptionElement,
+ void(const ElementFinder::Result& option,
const ElementFinder::Result& element,
base::OnceCallback<void(const ClientStatus&)> callback));
MOCK_METHOD2(HighlightElement,
@@ -82,42 +87,21 @@ class MockWebController : public WebController {
const std::vector<std::string>&)> callback));
MOCK_METHOD4(WaitUntilElementIsStable,
void(int,
- base::TimeDelta,
+ base::TimeDelta wait_time,
const ElementFinder::Result& element,
base::OnceCallback<void(const ClientStatus&,
base::TimeDelta)> callback));
-
- void ClickOrTapElement(
- const ElementFinder::Result& element,
- ClickType click_type,
- base::OnceCallback<void(const ClientStatus&)> callback) override {
- // Transforming callback into a references allows using RunOnceCallback on
- // the argument.
- OnClickOrTapElement(element, callback);
- }
- MOCK_METHOD2(OnClickOrTapElement,
- void(const ElementFinder::Result&,
- base::OnceCallback<void(const ClientStatus&)>& callback));
-
- void ScrollToElementPosition(
- std::unique_ptr<ElementFinder::Result> scrollable_element,
- const ElementFinder::Result& element,
- const TopPadding& top_padding,
- base::OnceCallback<void(const ClientStatus&)> callback) override {
- OnScrollToElementPosition(std::move(scrollable_element), element,
- top_padding, callback);
- }
- MOCK_METHOD4(OnScrollToElementPosition,
- void(std::unique_ptr<ElementFinder::Result> scrollable_element,
+ MOCK_METHOD2(JsClickElement,
+ void(const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> callback));
+ MOCK_METHOD3(ClickOrTapElement,
+ void(ClickType click_type,
const ElementFinder::Result& element,
- const TopPadding& top_padding,
- base::OnceCallback<void(const ClientStatus&)>& callback));
-
+ base::OnceCallback<void(const ClientStatus&)> callback));
MOCK_METHOD2(GetFieldValue,
void(const ElementFinder::Result& element,
base::OnceCallback<void(const ClientStatus&,
const std::string&)> callback));
-
MOCK_METHOD3(
GetStringAttribute,
void(const std::vector<std::string>&,
@@ -132,49 +116,18 @@ class MockWebController : public WebController {
const std::string&,
const ElementFinder::Result&,
base::OnceCallback<void(const ClientStatus&)>));
-
- void GetVisualViewport(
- base::OnceCallback<void(const ClientStatus&, const RectF&)> callback)
- override {
- OnGetVisualViewport(callback);
- }
- MOCK_METHOD1(OnGetVisualViewport,
- void(base::OnceCallback<void(const ClientStatus&, const RectF&)>&
+ MOCK_METHOD1(GetVisualViewport,
+ void(base::OnceCallback<void(const ClientStatus&, const RectF&)>
callback));
-
- void GetElementRect(
- const ElementFinder::Result& element,
- ElementRectGetter::ElementRectCallback callback) override {
- OnGetElementRect(element, callback);
- }
- MOCK_METHOD2(OnGetElementRect,
+ MOCK_METHOD2(GetElementRect,
void(const ElementFinder::Result& element,
- ElementRectGetter::ElementRectCallback& callback));
-
- void WaitForWindowHeightChange(
- base::OnceCallback<void(const ClientStatus&)> callback) {
- OnWaitForWindowHeightChange(callback);
- }
-
- MOCK_METHOD1(OnWaitForWindowHeightChange,
- void(base::OnceCallback<void(const ClientStatus&)>& callback));
-
- MOCK_METHOD3(OnWaitForDocumentReadyState,
- void(const ElementFinder::Result&,
- DocumentReadyState,
+ ElementRectGetter::ElementRectCallback callback));
+ MOCK_METHOD3(WaitForDocumentReadyState,
+ void(const ElementFinder::Result& optional_frame_element,
+ DocumentReadyState min_ready_state,
base::OnceCallback<void(const ClientStatus&,
DocumentReadyState,
- base::TimeDelta)>&));
-
- void WaitForDocumentReadyState(
- const ElementFinder::Result& optional_frame_element,
- DocumentReadyState min_ready_state,
- base::OnceCallback<void(const ClientStatus&,
- DocumentReadyState,
- base::TimeDelta)> callback) override {
- OnWaitForDocumentReadyState(optional_frame_element, min_ready_state,
- callback);
- }
+ base::TimeDelta)> callback));
base::WeakPtr<WebController> GetWeakPtr() const override {
return weak_ptr_factory_.GetWeakPtr();
diff --git a/chromium/components/autofill_assistant/browser/web/send_keyboard_input_worker.cc b/chromium/components/autofill_assistant/browser/web/send_keyboard_input_worker.cc
index d336f603cab..c58f0b652ef 100644
--- a/chromium/components/autofill_assistant/browser/web/send_keyboard_input_worker.cc
+++ b/chromium/components/autofill_assistant/browser/web/send_keyboard_input_worker.cc
@@ -14,17 +14,17 @@
namespace autofill_assistant {
namespace {
-base::Optional<std::vector<std::string>> GetCommandForDomKey(
+absl::optional<std::vector<std::string>> GetCommandForDomKey(
ui::DomKey dom_key) {
if (dom_key == ui::DomKey::BACKSPACE) {
return std::vector<std::string>({"DeleteBackward"});
}
- return base::nullopt;
+ return absl::nullopt;
}
std::unique_ptr<input::DispatchKeyEventParams> CreateKeyEventParamsForKeyEvent(
input::DispatchKeyEventType type,
- base::Optional<base::Time> timestamp,
+ absl::optional<base::Time> timestamp,
const KeyEvent& key_event) {
auto params = input::DispatchKeyEventParams::Builder().SetType(type).Build();
if (timestamp) {
@@ -155,7 +155,7 @@ void SendKeyboardInputWorker::DispatchKeyboardTextDownEvent(size_t index) {
DCHECK_LT(index, key_events_.size());
devtools_client_->GetInput()->DispatchKeyEvent(
CreateKeyEventParamsForKeyEvent(input::DispatchKeyEventType::KEY_DOWN,
- base::nullopt, key_events_[index]),
+ absl::nullopt, key_events_[index]),
frame_id_,
base::BindOnce(&SendKeyboardInputWorker::DispatchKeyboardTextUpEvent,
weak_ptr_factory_.GetWeakPtr(), index));
@@ -178,7 +178,7 @@ void SendKeyboardInputWorker::DispatchKeyboardTextUpEvent(
DCHECK_LT(index, key_events_.size());
devtools_client_->GetInput()->DispatchKeyEvent(
CreateKeyEventParamsForKeyEvent(input::DispatchKeyEventType::KEY_UP,
- base::nullopt, key_events_[index]),
+ absl::nullopt, key_events_[index]),
frame_id_,
base::BindOnce(&SendKeyboardInputWorker::WaitBeforeNextKey,
weak_ptr_factory_.GetWeakPtr(), index + 1));
diff --git a/chromium/components/autofill_assistant/browser/web/send_keyboard_input_worker.h b/chromium/components/autofill_assistant/browser/web/send_keyboard_input_worker.h
index 6edb755f426..15979fb7731 100644
--- a/chromium/components/autofill_assistant/browser/web/send_keyboard_input_worker.h
+++ b/chromium/components/autofill_assistant/browser/web/send_keyboard_input_worker.h
@@ -21,7 +21,7 @@
namespace autofill_assistant {
-// Worker class to for sending keypress events.
+// Worker class for sending keypress events.
class SendKeyboardInputWorker : public WebControllerWorker {
public:
// |devtools_client| must be valid for the lifetime of the instance.
diff --git a/chromium/components/autofill_assistant/browser/web/web_controller.cc b/chromium/components/autofill_assistant/browser/web/web_controller.cc
index ae3d4129625..e9565670e9d 100644
--- a/chromium/components/autofill_assistant/browser/web/web_controller.cc
+++ b/chromium/components/autofill_assistant/browser/web/web_controller.cc
@@ -19,7 +19,7 @@
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
-#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/browser_autofill_manager.h"
#include "components/autofill/core/browser/data_model/credit_card.h"
#include "components/autofill/core/common/autofill_constants.h"
#include "components/autofill/core/common/form_data.h"
@@ -84,24 +84,53 @@ const char* const kScrollIntoViewScript =
// 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.
+// See |WebController::OnSelectOptionJavascriptResult| for result handling.
const char* const kSelectOptionScript =
- R"(function(re2, valueSourceAttribute, caseSensitive) {
+ R"(function(re2, valueSourceAttribute, caseSensitive, strict) {
+ if (this.options == null) return -1;
const regexp = RegExp(re2, caseSensitive ? '' : 'i');
- let found = false;
+ let numResults = 0;
+ let newIndex = -1;
for (let i = 0; i < this.options.length; ++i) {
if (regexp.test(this.options[i][valueSourceAttribute])) {
- this.options.selectedIndex = i;
- found = true;
- break;
+ ++numResults;
+ if (newIndex === -1) {
+ newIndex = i;
+ }
}
}
- if (!found) {
- return false;
+ if (numResults == 1 || (numResults > 1 && !strict)) {
+ this.options.selectedIndex = newIndex;
+ const e = document.createEvent('HTMLEvents');
+ e.initEvent('change', true, true);
+ this.dispatchEvent(e);
+ return 1;
}
- const e = document.createEvent('HTMLEvents');
- e.initEvent('change', true, true);
- this.dispatchEvent(e);
- return true;
+ return numResults;
+ })";
+
+// Javascript to select the option element in a select element. This does *not*
+// fire a "change" event.
+// See |WebController::OnSelectOptionJavascriptResult| for result handling.
+const char* const kSelectOptionElementScript =
+ R"(function(option) {
+ if (this.options == null) return -1;
+ for (let i = 0; i < this.options.length; ++i) {
+ if (this.options[i] === option) {
+ this.options.selectedIndex = i;
+ return 1;
+ }
+ }
+ return 0;
+ })";
+
+// Javascript to check the option element in a select element against an
+// expected match.
+// See |WebController::OnSelectOptionJavascriptResult| for result handling.
+const char* const kCheckOptionElementScript =
+ R"(function(option) {
+ if (this.options == null) return -1;
+ return (this.options[this.options.selectedIndex] === option) ? 1 : 0;
})";
// Javascript to highlight an element.
@@ -205,6 +234,13 @@ const char* const kDispatchEventToDocumentScript =
R"(const event = new Event('duplexweb');
document.dispatchEvent(event);)";
+// Find the index of the calling element (|this|) in the |nodeList| result of
+// the |querySelector|.
+const char* const kGetElementQueryIndexScript =
+ R"(function(querySelector) {
+ return [].indexOf.call(document.querySelectorAll(querySelector), this);
+ })";
+
// Converts a int that correspond to the DocumentReadyState enum into an
// equivalent quoted Javascript string.
std::string DocumentReadyStateToQuotedJsString(int state) {
@@ -334,11 +370,29 @@ void WebController::OnJavaScriptResult(
ClientStatus status =
CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok()) {
- VLOG(1) << __func__ << " Failed JavaScript with status: " << status;
+ DVLOG(1) << __func__ << " Failed JavaScript with status: " << status;
}
std::move(callback).Run(status);
}
+void WebController::OnJavaScriptResultForInt(
+ base::OnceCallback<void(const ClientStatus&, int)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<runtime::CallFunctionOnResult> result) {
+ int value;
+ ClientStatus status =
+ CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
+ if (!status.ok()) {
+ DVLOG(1) << __func__ << "Failed JavaScript with status: " << status;
+ }
+ if (!SafeGetIntValue(result->GetResult(), &value)) {
+ std::move(callback).Run(
+ UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__), 0);
+ return;
+ }
+ std::move(callback).Run(status, value);
+}
+
void WebController::OnJavaScriptResultForString(
base::OnceCallback<void(const ClientStatus&, const std::string&)> callback,
const DevtoolsClient::ReplyStatus& reply_status,
@@ -347,7 +401,7 @@ void WebController::OnJavaScriptResultForString(
ClientStatus status =
CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok()) {
- VLOG(1) << __func__ << "Failed JavaScript with status: " << status;
+ DVLOG(1) << __func__ << "Failed JavaScript with status: " << status;
}
SafeGetStringValue(result->GetResult(), &value);
std::move(callback).Run(status, value);
@@ -361,7 +415,7 @@ void WebController::OnJavaScriptResultForStringArray(
ClientStatus status =
CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok()) {
- VLOG(1) << __func__ << "Failed JavaScript with status: " << status;
+ DVLOG(1) << __func__ << "Failed JavaScript with status: " << status;
std::move(callback).Run(status, {});
return;
}
@@ -369,7 +423,7 @@ void WebController::OnJavaScriptResultForStringArray(
auto* remote_object = result->GetResult();
if (!remote_object || !remote_object->HasValue() ||
!remote_object->GetValue()->is_list()) {
- VLOG(1) << __func__ << "JavaScript result is not an array.";
+ DVLOG(1) << __func__ << "JavaScript result is not an array.";
std::move(callback).Run(
JavaScriptErrorStatus(reply_status, __FILE__, __LINE__,
/* exception= */ nullptr),
@@ -381,8 +435,8 @@ void WebController::OnJavaScriptResultForStringArray(
std::vector<std::string> v;
for (const base::Value& value : values) {
if (!value.is_string()) {
- VLOG(1) << __func__
- << "JavaScript array content is not a string: " << value.type();
+ DVLOG(1) << __func__
+ << "JavaScript array content is not a string: " << value.type();
std::move(callback).Run(
JavaScriptErrorStatus(reply_status, __FILE__, __LINE__,
/* exception= */ nullptr),
@@ -478,172 +532,62 @@ void WebController::OnWaitUntilElementIsStable(
std::move(callback).Run(end_status, base::TimeTicks::Now() - wait_start_time);
}
-void WebController::ClickOrTapElement(
+void WebController::JsClickElement(
const ElementFinder::Result& element,
- ClickType click_type,
base::OnceCallback<void(const ClientStatus&)> callback) {
auto wrapped_callback = GetAssistantActionRunningStateRetainingCallback(
element, std::move(callback));
- if (click_type == ClickType::JAVASCRIPT) {
- devtools_client_->GetRuntime()->CallFunctionOn(
- runtime::CallFunctionOnParams::Builder()
- .SetObjectId(element.object_id())
- .SetFunctionDeclaration(kClickElementScript)
- .Build(),
- element.node_frame_id(),
- base::BindOnce(
- &WebController::OnJavaScriptResult, weak_ptr_factory_.GetWeakPtr(),
- base::BindOnce(&DecorateWebControllerStatus,
- WebControllerErrorInfoProto::CLICK_OR_TAP_ELEMENT,
- std::move(wrapped_callback))));
+ devtools_client_->GetRuntime()->CallFunctionOn(
+ runtime::CallFunctionOnParams::Builder()
+ .SetObjectId(element.object_id())
+ .SetFunctionDeclaration(kClickElementScript)
+ .Build(),
+ element.node_frame_id(),
+ base::BindOnce(
+ &WebController::OnJavaScriptResult, weak_ptr_factory_.GetWeakPtr(),
+ base::BindOnce(&DecorateWebControllerStatus,
+ WebControllerErrorInfoProto::JS_CLICK_ELEMENT,
+ std::move(wrapped_callback))));
+}
+
+void WebController::ClickOrTapElement(
+ ClickType click_type,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> callback) {
+ if (click_type != ClickType::TAP && click_type != ClickType::CLICK) {
+ ClientStatus status(INVALID_ACTION);
+ FillWebControllerErrorInfo(
+ WebControllerErrorInfoProto::CLICK_OR_TAP_ELEMENT, &status);
+ std::move(callback).Run(status);
return;
}
- std::unique_ptr<ElementPositionGetter> getter =
- std::make_unique<ElementPositionGetter>(
- devtools_client_.get(), /* max_rounds= */ 1,
- /* check_interval= */ base::TimeDelta::FromMilliseconds(0),
- element.node_frame_id());
- auto* ptr = getter.get();
- pending_workers_.emplace_back(std::move(getter));
+ auto wrapped_callback = GetAssistantActionRunningStateRetainingCallback(
+ element, std::move(callback));
+
+ std::unique_ptr<ClickOrTapWorker> worker =
+ std::make_unique<ClickOrTapWorker>(devtools_client_.get());
+ auto* ptr = worker.get();
+ pending_workers_.emplace_back(std::move(worker));
ptr->Start(
- element.container_frame_host, element.object_id(),
+ element, click_type,
base::BindOnce(
- &WebController::TapOrClickOnCoordinates,
- weak_ptr_factory_.GetWeakPtr(), ptr, element.node_frame_id(),
- click_type,
+ &WebController::OnClickOrTapElement, weak_ptr_factory_.GetWeakPtr(),
+ ptr,
base::BindOnce(&DecorateWebControllerStatus,
WebControllerErrorInfoProto::CLICK_OR_TAP_ELEMENT,
std::move(wrapped_callback))));
}
-void WebController::TapOrClickOnCoordinates(
- ElementPositionGetter* getter_to_release,
- const std::string& node_frame_id,
- ClickType click_type,
+void WebController::OnClickOrTapElement(
+ ClickOrTapWorker* getter_to_release,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status) {
- int x = getter_to_release->x();
- int y = getter_to_release->y();
base::EraseIf(pending_workers_, [getter_to_release](const auto& worker) {
return worker.get() == getter_to_release;
});
-
- if (!status.ok()) {
- VLOG(1) << __func__ << " Failed to get element position.";
- std::move(callback).Run(status);
- return;
- }
-
- DCHECK(click_type == ClickType::TAP || click_type == ClickType::CLICK);
- if (click_type == ClickType::CLICK) {
- devtools_client_->GetInput()->DispatchMouseEvent(
- input::DispatchMouseEventParams::Builder()
- .SetX(x)
- .SetY(y)
- .SetClickCount(1)
- .SetButton(input::MouseButton::LEFT)
- .SetType(input::DispatchMouseEventType::MOUSE_PRESSED)
- .Build(),
- node_frame_id,
- base::BindOnce(&WebController::OnDispatchPressMouseEvent,
- weak_ptr_factory_.GetWeakPtr(), node_frame_id,
- std::move(callback), x, y));
- return;
- }
-
- std::vector<std::unique_ptr<::autofill_assistant::input::TouchPoint>>
- touch_points;
- touch_points.emplace_back(
- input::TouchPoint::Builder().SetX(x).SetY(y).Build());
- devtools_client_->GetInput()->DispatchTouchEvent(
- input::DispatchTouchEventParams::Builder()
- .SetType(input::DispatchTouchEventType::TOUCH_START)
- .SetTouchPoints(std::move(touch_points))
- .Build(),
- node_frame_id,
- base::BindOnce(&WebController::OnDispatchTouchEventStart,
- weak_ptr_factory_.GetWeakPtr(), node_frame_id,
- std::move(callback)));
-}
-
-void WebController::OnDispatchPressMouseEvent(
- const std::string& node_frame_id,
- base::OnceCallback<void(const ClientStatus&)> callback,
- int x,
- int y,
- const DevtoolsClient::ReplyStatus& reply_status,
- std::unique_ptr<input::DispatchMouseEventResult> result) {
- if (!result) {
- VLOG(1) << __func__
- << " Failed to dispatch mouse left button pressed event.";
- std::move(callback).Run(
- UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
- return;
- }
-
- devtools_client_->GetInput()->DispatchMouseEvent(
- input::DispatchMouseEventParams::Builder()
- .SetX(x)
- .SetY(y)
- .SetClickCount(1)
- .SetButton(input::MouseButton::LEFT)
- .SetType(input::DispatchMouseEventType::MOUSE_RELEASED)
- .Build(),
- node_frame_id,
- base::BindOnce(&WebController::OnDispatchReleaseMouseEvent,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
-}
-
-void WebController::OnDispatchReleaseMouseEvent(
- base::OnceCallback<void(const ClientStatus&)> callback,
- const DevtoolsClient::ReplyStatus& reply_status,
- std::unique_ptr<input::DispatchMouseEventResult> result) {
- if (!result) {
- VLOG(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(
- const std::string& node_frame_id,
- base::OnceCallback<void(const ClientStatus&)> callback,
- const DevtoolsClient::ReplyStatus& reply_status,
- std::unique_ptr<input::DispatchTouchEventResult> result) {
- if (!result) {
- VLOG(1) << __func__ << " Failed to dispatch touch start event.";
- std::move(callback).Run(
- UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
- return;
- }
-
- std::vector<std::unique_ptr<::autofill_assistant::input::TouchPoint>>
- touch_points;
- devtools_client_->GetInput()->DispatchTouchEvent(
- input::DispatchTouchEventParams::Builder()
- .SetType(input::DispatchTouchEventType::TOUCH_END)
- .SetTouchPoints(std::move(touch_points))
- .Build(),
- node_frame_id,
- base::BindOnce(&WebController::OnDispatchTouchEventEnd,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
-}
-
-void WebController::OnDispatchTouchEventEnd(
- base::OnceCallback<void(const ClientStatus&)> callback,
- const DevtoolsClient::ReplyStatus& reply_status,
- std::unique_ptr<input::DispatchTouchEventResult> result) {
- if (!result) {
- VLOG(1) << __func__ << " Failed to dispatch touch end event.";
- std::move(callback).Run(
- UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
- return;
- }
- std::move(callback).Run(OkClientStatus());
+ std::move(callback).Run(status);
}
void WebController::WaitForWindowHeightChange(
@@ -822,34 +766,111 @@ void WebController::OnFindElementForGetFormAndFieldData(
const ClientStatus& element_status,
std::unique_ptr<ElementFinder::Result> element_result) {
if (!element_status.ok()) {
- VLOG(1) << __func__
- << " Failed to find the element for getting Autofill data.";
+ DVLOG(1) << __func__
+ << " Failed to find the element for getting Autofill data.";
std::move(callback).Run(element_status, nullptr, autofill::FormData(),
autofill::FormFieldData());
return;
}
- ContentAutofillDriver* driver = ContentAutofillDriver::GetForRenderFrameHost(
- element_result->container_frame_host);
- if (driver == nullptr) {
- VLOG(1) << __func__ << " Failed to get the autofill driver.";
- std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__), nullptr,
- autofill::FormData(), autofill::FormFieldData());
+ const ElementFinder::Result* element_result_ptr = element_result.get();
+ GetUniqueElementSelector(
+ *element_result_ptr,
+ base::BindOnce(&WebController::OnGetUniqueSelectorForFormAndFieldData,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+ std::move(element_result)));
+}
+
+void WebController::GetUniqueElementSelector(
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&, const std::string&, int)>
+ callback) {
+ GetElementTag(element,
+ base::BindOnce(&WebController::OnGetElementTagForUniqueSelector,
+ weak_ptr_factory_.GetWeakPtr(), element,
+ std::move(callback)));
+}
+
+void WebController::OnGetElementTagForUniqueSelector(
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&, const std::string&, int)>
+ callback,
+ const ClientStatus& tag_status,
+ const std::string& tag) {
+ if (!tag_status.ok()) {
+ std::move(callback).Run(tag_status, std::string(), -1);
return;
}
- base::Optional<std::string> css_selector =
- selector.ExtractSingleCssSelectorForAutofill();
- if (!css_selector) {
- std::move(callback).Run(ClientStatus(INVALID_SELECTOR), nullptr,
+ GetElementQueryIndex(
+ tag, element,
+ base::BindOnce(&WebController::OnGetElementQueryIndexForUniqueSelector,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback), tag));
+}
+
+void WebController::GetElementQueryIndex(
+ const std::string& query_selector,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&, int)> callback) {
+ std::vector<std::unique_ptr<runtime::CallArgument>> argument;
+ AddRuntimeCallArgument(query_selector, &argument);
+ devtools_client_->GetRuntime()->CallFunctionOn(
+ runtime::CallFunctionOnParams::Builder()
+ .SetObjectId(element.object_id())
+ .SetArguments(std::move(argument))
+ .SetFunctionDeclaration(std::string(kGetElementQueryIndexScript))
+ .SetReturnByValue(true)
+ .Build(),
+ element.node_frame_id(),
+ base::BindOnce(&WebController::OnJavaScriptResultForInt,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void WebController::OnGetElementQueryIndexForUniqueSelector(
+ base::OnceCallback<void(const ClientStatus&, const std::string&, int)>
+ callback,
+ const std::string& query_selector,
+ const ClientStatus& index_status,
+ int index) {
+ if (index < 0) {
+ // TODO(b/181209327): This may happen if the element is in a shadow DOM. We
+ // currently do not support this.
+ std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__),
+ query_selector, -1);
+ return;
+ }
+ std::move(callback).Run(index_status, query_selector, index);
+}
+
+void WebController::OnGetUniqueSelectorForFormAndFieldData(
+ base::OnceCallback<void(const ClientStatus&,
+ ContentAutofillDriver* driver,
+ const autofill::FormData&,
+ const autofill::FormFieldData&)> callback,
+ std::unique_ptr<ElementFinder::Result> element,
+ const ClientStatus& selector_status,
+ const std::string& query_selector,
+ int index) {
+ if (!selector_status.ok()) {
+ std::move(callback).Run(selector_status, nullptr, autofill::FormData(),
+ autofill::FormFieldData());
+ return;
+ }
+
+ ContentAutofillDriver* driver = ContentAutofillDriver::GetForRenderFrameHost(
+ element->container_frame_host);
+ if (driver == nullptr) {
+ DVLOG(1) << __func__ << " Failed to get the autofill driver.";
+ std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__), nullptr,
autofill::FormData(), autofill::FormFieldData());
return;
}
- driver->GetAutofillAgent()->GetElementFormAndFieldData(
- {*css_selector}, base::BindOnce(&WebController::OnGetFormAndFieldData,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(callback), driver));
+ driver->GetAutofillAgent()->GetElementFormAndFieldDataAtIndex(
+ query_selector, index,
+ base::BindOnce(&WebController::OnGetFormAndFieldData,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+ driver));
}
void WebController::OnGetFormAndFieldData(
@@ -861,7 +882,7 @@ void WebController::OnGetFormAndFieldData(
const autofill::FormData& form_data,
const autofill::FormFieldData& form_field_data) {
if (form_data.fields.empty()) {
- VLOG(1) << __func__ << " Failed to get form data.";
+ DVLOG(1) << __func__ << " Failed to get form data.";
std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__), driver,
autofill::FormData(), autofill::FormFieldData());
return;
@@ -882,12 +903,12 @@ void WebController::OnGetFormAndFieldDataForFilling(
}
if (data_to_autofill->card) {
- driver->autofill_manager()->FillCreditCardForm(
+ driver->browser_autofill_manager()->FillCreditCardForm(
autofill::kNoQueryId, form_data, form_field, *data_to_autofill->card,
data_to_autofill->cvc);
} else {
- driver->autofill_manager()->FillProfileForm(*data_to_autofill->profile,
- form_data, form_field);
+ driver->browser_autofill_manager()->FillProfileForm(
+ *data_to_autofill->profile, form_data, form_field);
}
std::move(callback).Run(OkClientStatus());
@@ -909,6 +930,7 @@ void WebController::SelectOption(
const std::string& re2,
bool case_sensitive,
SelectOptionProto::OptionComparisonAttribute option_comparison_attribute,
+ bool strict,
const ElementFinder::Result& element,
base::OnceCallback<void(const ClientStatus&)> callback) {
#ifdef NDEBUG
@@ -938,6 +960,7 @@ void WebController::SelectOption(
return;
}
AddRuntimeCallArgument(case_sensitive, &arguments);
+ AddRuntimeCallArgument(strict, &arguments);
devtools_client_->GetRuntime()->CallFunctionOn(
runtime::CallFunctionOnParams::Builder()
@@ -947,33 +970,87 @@ void WebController::SelectOption(
.SetReturnByValue(true)
.Build(),
element.node_frame_id(),
- base::BindOnce(&WebController::OnSelectOption,
+ base::BindOnce(&WebController::OnSelectOptionJavascriptResult,
weak_ptr_factory_.GetWeakPtr(),
base::BindOnce(&DecorateWebControllerStatus,
WebControllerErrorInfoProto::SELECT_OPTION,
- std::move(callback))));
+ std::move(callback)),
+ /* status_if_false= */ OPTION_VALUE_NOT_FOUND));
+}
+
+void WebController::SelectOptionElement(
+ const ElementFinder::Result& option,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> callback) {
+ std::vector<std::unique_ptr<runtime::CallArgument>> argument;
+ AddRuntimeCallArgumentObjectId(option.object_id(), &argument);
+ devtools_client_->GetRuntime()->CallFunctionOn(
+ runtime::CallFunctionOnParams::Builder()
+ .SetObjectId(element.object_id())
+ .SetArguments(std::move(argument))
+ .SetFunctionDeclaration(std::string(kSelectOptionElementScript))
+ .SetReturnByValue(true)
+ .Build(),
+ element.node_frame_id(),
+ base::BindOnce(
+ &WebController::OnSelectOptionJavascriptResult,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::BindOnce(&DecorateWebControllerStatus,
+ WebControllerErrorInfoProto::SELECT_OPTION_ELEMENT,
+ std::move(callback)),
+ /* status_if_false= */ OPTION_VALUE_NOT_FOUND));
}
-void WebController::OnSelectOption(
+void WebController::CheckSelectedOptionElement(
+ const ElementFinder::Result& option,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> callback) {
+ std::vector<std::unique_ptr<runtime::CallArgument>> argument;
+ AddRuntimeCallArgumentObjectId(option.object_id(), &argument);
+ devtools_client_->GetRuntime()->CallFunctionOn(
+ runtime::CallFunctionOnParams::Builder()
+ .SetObjectId(element.object_id())
+ .SetArguments(std::move(argument))
+ .SetFunctionDeclaration(std::string(kCheckOptionElementScript))
+ .SetReturnByValue(true)
+ .Build(),
+ element.node_frame_id(),
+ base::BindOnce(
+ &WebController::OnSelectOptionJavascriptResult,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::BindOnce(&DecorateWebControllerStatus,
+ WebControllerErrorInfoProto::CHECK_OPTION_ELEMENT,
+ std::move(callback)),
+ /* status_if_false= */ ELEMENT_MISMATCH));
+}
+
+void WebController::OnSelectOptionJavascriptResult(
base::OnceCallback<void(const ClientStatus&)> callback,
+ ProcessedActionStatusProto status_if_zero,
const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result) {
ClientStatus status =
CheckJavaScriptResult(reply_status, result.get(), __FILE__, __LINE__);
if (!status.ok()) {
- VLOG(1) << __func__ << " Failed to select option.";
std::move(callback).Run(status);
return;
}
- bool found;
- if (!SafeGetBool(result->GetResult(), &found)) {
+ int int_result;
+ if (!SafeGetIntValue(result->GetResult(), &int_result)) {
std::move(callback).Run(
UnexpectedDevtoolsErrorStatus(reply_status, __FILE__, __LINE__));
return;
}
- if (!found) {
- VLOG(1) << __func__ << " Failed to find option.";
- std::move(callback).Run(ClientStatus(OPTION_VALUE_NOT_FOUND));
+ if (int_result < 0) {
+ std::move(callback).Run(ClientStatus(INVALID_TARGET));
+ return;
+ }
+ if (int_result == 0) {
+ std::move(callback).Run(ClientStatus(status_if_zero));
+ return;
+ }
+ if (int_result > 1) {
+ std::move(callback).Run(ClientStatus(TOO_MANY_OPTION_VALUES_FOUND));
return;
}
std::move(callback).Run(OkClientStatus());
diff --git a/chromium/components/autofill_assistant/browser/web/web_controller.h b/chromium/components/autofill_assistant/browser/web/web_controller.h
index e3c8f8e061e..de675244bc3 100644
--- a/chromium/components/autofill_assistant/browser/web/web_controller.h
+++ b/chromium/components/autofill_assistant/browser/web/web_controller.h
@@ -25,6 +25,7 @@
#include "components/autofill_assistant/browser/selector.h"
#include "components/autofill_assistant/browser/top_padding.h"
#include "components/autofill_assistant/browser/web/check_on_top_worker.h"
+#include "components/autofill_assistant/browser/web/click_or_tap_worker.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/element_rect_getter.h"
@@ -95,11 +96,16 @@ class WebController {
const ElementFinder::Result& element,
base::OnceCallback<void(const ClientStatus&)> callback);
+ // Send a JS click to the |element|.
+ virtual void JsClickElement(
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> callback);
+
// Perform a mouse left button click or a touch tap on the |element|
// return the result through callback.
virtual void ClickOrTapElement(
- const ElementFinder::Result& element,
ClickType click_type,
+ const ElementFinder::Result& element,
base::OnceCallback<void(const ClientStatus&)> callback);
// Get a stable position of the given element. Fail with ELEMENT_UNSTABLE if
@@ -145,6 +151,19 @@ class WebController {
const std::string& re2,
bool case_sensitive,
SelectOptionProto::OptionComparisonAttribute option_comparison_attribute,
+ bool strict,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> callback);
+
+ // Set the selected |option| of the |element|.
+ virtual void SelectOptionElement(
+ const ElementFinder::Result& option,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&)> callback);
+
+ // Check if the selected option of the |element| is the expected |option|.
+ virtual void CheckSelectedOptionElement(
+ const ElementFinder::Result& option,
const ElementFinder::Result& element,
base::OnceCallback<void(const ClientStatus&)> callback);
@@ -343,6 +362,10 @@ class WebController {
base::OnceCallback<void(const ClientStatus&)> callback,
const DevtoolsClient::ReplyStatus& reply_status,
std::unique_ptr<runtime::CallFunctionOnResult> result);
+ void OnJavaScriptResultForInt(
+ base::OnceCallback<void(const ClientStatus&, int)> callback,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<runtime::CallFunctionOnResult> result);
void OnJavaScriptResultForString(
base::OnceCallback<void(const ClientStatus&, const std::string&)>
callback,
@@ -361,32 +384,10 @@ class WebController {
base::TimeTicks wait_time_start,
base::OnceCallback<void(const ClientStatus&, base::TimeDelta)> callback,
const ClientStatus& status);
- void TapOrClickOnCoordinates(
- ElementPositionGetter* getter_to_release,
- const std::string& node_frame_id,
- ClickType click_type,
+ void OnClickOrTapElement(
+ ClickOrTapWorker* getter_to_release,
base::OnceCallback<void(const ClientStatus&)> callback,
const ClientStatus& status);
- void OnDispatchPressMouseEvent(
- const std::string& node_frame_id,
- 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(
- const std::string& node_frame_id,
- 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 OnWaitForWindowHeightChange(
base::OnceCallback<void(const ClientStatus&)> callback,
const DevtoolsClient::ReplyStatus& reply_status,
@@ -412,6 +413,35 @@ class WebController {
const autofill::FormFieldData&)> callback,
const ClientStatus& element_status,
std::unique_ptr<ElementFinder::Result> element_result);
+ void GetUniqueElementSelector(
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&, const std::string&, int)>
+ callback);
+ void OnGetElementTagForUniqueSelector(
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&, const std::string&, int)>
+ callback,
+ const ClientStatus& tag_status,
+ const std::string& tag);
+ void GetElementQueryIndex(
+ const std::string& query_selector,
+ const ElementFinder::Result& element,
+ base::OnceCallback<void(const ClientStatus&, int)> callback);
+ void OnGetElementQueryIndexForUniqueSelector(
+ base::OnceCallback<void(const ClientStatus&, const std::string&, int)>
+ callback,
+ const std::string& query_selector,
+ const ClientStatus& index_status,
+ int index);
+ void OnGetUniqueSelectorForFormAndFieldData(
+ base::OnceCallback<void(const ClientStatus&,
+ autofill::ContentAutofillDriver* driver,
+ const autofill::FormData&,
+ const autofill::FormFieldData&)> callback,
+ std::unique_ptr<ElementFinder::Result> element,
+ const ClientStatus& selector_status,
+ const std::string& query_selector,
+ int index);
void OnGetFormAndFieldData(
base::OnceCallback<void(const ClientStatus&,
autofill::ContentAutofillDriver* driver,
@@ -436,9 +466,17 @@ class WebController {
autofill::ContentAutofillDriver* driver,
const autofill::FormData& form_data,
const autofill::FormFieldData& form_field);
- void OnSelectOption(base::OnceCallback<void(const ClientStatus&)> callback,
- const DevtoolsClient::ReplyStatus& reply_status,
- std::unique_ptr<runtime::CallFunctionOnResult> result);
+ // Handling a JS result for a "SelectOption" action. This expects the JS
+ // result to contain an integer and returns the following status:
+ // * -1 -> INVALID_TARGET
+ // * 0 -> OPTION_ELEMENT_NOT_FOUND
+ // * 1 -> ACTION_APPLIED
+ // * n -> TOO_MANY_OPTION_VALUES_FOUND
+ void OnSelectOptionJavascriptResult(
+ base::OnceCallback<void(const ClientStatus&)> callback,
+ ProcessedActionStatusProto status_if_zero,
+ const DevtoolsClient::ReplyStatus& reply_status,
+ std::unique_ptr<runtime::CallFunctionOnResult> result);
void OnSendKeyboardInputDone(
SendKeyboardInputWorker* worker_to_release,
diff --git a/chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc b/chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc
index fa0c26d4328..8c6ae96583a 100644
--- a/chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc
+++ b/chromium/components/autofill_assistant/browser/web/web_controller_browsertest.cc
@@ -11,6 +11,7 @@
#include "base/callback_helpers.h"
#include "base/memory/ref_counted.h"
#include "base/strings/strcat.h"
+#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/time/time.h"
#include "components/autofill_assistant/browser/action_value.pb.h"
@@ -224,8 +225,12 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
return;
}
- web_controller_->ClickOrTapElement(element, click_type,
- std::move(callback));
+ if (click_type == ClickType::JAVASCRIPT) {
+ web_controller_->JsClickElement(element, std::move(callback));
+ } else {
+ web_controller_->ClickOrTapElement(click_type, element,
+ std::move(callback));
+ }
}
void WaitForElementRemove(const Selector& selector) {
@@ -317,11 +322,12 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
std::move(done_callback), result_output));
}
- ClientStatus SelectOption(const Selector& selector,
- const std::string& re2,
- bool case_sensitive,
- SelectOptionProto::OptionComparisonAttribute
- option_comparison_attribute) {
+ ClientStatus SelectOption(
+ const Selector& selector,
+ const std::string& re2,
+ bool case_sensitive,
+ SelectOptionProto::OptionComparisonAttribute option_comparison_attribute,
+ bool strict) {
base::RunLoop run_loop;
ClientStatus result;
@@ -330,7 +336,8 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
base::BindOnce(
&WebControllerBrowserTest::FindSelectOptionElementCallback,
base::Unretained(this), re2, case_sensitive,
- option_comparison_attribute, run_loop.QuitClosure(), &result));
+ option_comparison_attribute, strict, run_loop.QuitClosure(),
+ &result));
run_loop.Run();
return result;
@@ -340,6 +347,7 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
const std::string& re2,
bool case_sensitive,
SelectOptionProto::OptionComparisonAttribute option_comparison_attribute,
+ bool strict,
base::OnceClosure done_callback,
ClientStatus* result_output,
const ClientStatus& status,
@@ -353,12 +361,59 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
ASSERT_TRUE(element_result != nullptr);
const ElementFinder::Result* element_result_ptr = element_result.get();
web_controller_->SelectOption(
- re2, case_sensitive, option_comparison_attribute, *element_result_ptr,
+ re2, case_sensitive, option_comparison_attribute, strict,
+ *element_result_ptr,
+ base::BindOnce(&WebControllerBrowserTest::ElementRetainingCallback,
+ base::Unretained(this), std::move(element_result),
+ std::move(done_callback), result_output));
+ }
+
+ ClientStatus SelectOptionElement(const Selector& selector,
+ const ElementFinder::Result& option) {
+ base::RunLoop run_loop;
+ ClientStatus result;
+
+ web_controller_->FindElement(
+ selector, /* strict= */ true,
+ base::BindOnce(
+ &WebControllerBrowserTest::FindSelectOptionElementElementCallback,
+ base::Unretained(this), option, run_loop.QuitClosure(), &result));
+
+ run_loop.Run();
+ return result;
+ }
+
+ void FindSelectOptionElementElementCallback(
+ const ElementFinder::Result& option,
+ base::OnceClosure done_callback,
+ ClientStatus* result_output,
+ const ClientStatus& element_status,
+ std::unique_ptr<ElementFinder::Result> element_result) {
+ EXPECT_EQ(ACTION_APPLIED, element_status.proto_status());
+ ASSERT_TRUE(element_result != nullptr);
+ const ElementFinder::Result* element_result_ptr = element_result.get();
+ web_controller_->SelectOptionElement(
+ option, *element_result_ptr,
base::BindOnce(&WebControllerBrowserTest::ElementRetainingCallback,
base::Unretained(this), std::move(element_result),
std::move(done_callback), result_output));
}
+ ClientStatus CheckSelectedOptionElement(const ElementFinder::Result& select,
+ const ElementFinder::Result& option) {
+ base::RunLoop run_loop;
+ ClientStatus result;
+
+ web_controller_->CheckSelectedOptionElement(
+ option, select,
+ base::BindOnce(&WebControllerBrowserTest::OnClientStatus,
+ base::Unretained(this), run_loop.QuitClosure(),
+ &result));
+
+ run_loop.Run();
+ return result;
+ }
+
void OnClientStatus(base::OnceClosure done_callback,
ClientStatus* result_output,
const ClientStatus& status) {
@@ -1049,6 +1104,61 @@ class WebControllerBrowserTest : public content::ContentBrowserTest,
std::move(done_callback).Run();
}
+ ClientStatus GetElementQueryIndex(const std::string& query_selector,
+ const ElementFinder::Result& element,
+ int* index) {
+ ClientStatus status;
+
+ base::RunLoop run_loop;
+ web_controller_->GetElementQueryIndex(
+ query_selector, element,
+ base::BindOnce(&WebControllerBrowserTest::OnGetElementQueryIndex,
+ base::Unretained(this), run_loop.QuitClosure(), &status,
+ index));
+ run_loop.Run();
+
+ return status;
+ }
+
+ void OnGetElementQueryIndex(base::OnceClosure done_callback,
+ ClientStatus* result_output,
+ int* index_output,
+ const ClientStatus& query_status,
+ int index) {
+ *result_output = query_status;
+ *index_output = index;
+ std::move(done_callback).Run();
+ }
+
+ ClientStatus GetUniqueElementSelector(const ElementFinder::Result& element,
+ std::string* query,
+ int* index) {
+ ClientStatus status;
+
+ base::RunLoop run_loop;
+ web_controller_->GetUniqueElementSelector(
+ element,
+ base::BindOnce(&WebControllerBrowserTest::OnGetUniqueElementSelector,
+ base::Unretained(this), run_loop.QuitClosure(), &status,
+ query, index));
+ run_loop.Run();
+
+ return status;
+ }
+
+ void OnGetUniqueElementSelector(base::OnceClosure done_callback,
+ ClientStatus* result_output,
+ std::string* query_output,
+ int* index_output,
+ const ClientStatus& query_status,
+ const std::string& query,
+ int index) {
+ *result_output = query_status;
+ *query_output = query;
+ *index_output = index;
+ std::move(done_callback).Run();
+ }
+
// Show the overlay in the main page, which covers everything.
void ShowOverlay() {
EXPECT_TRUE(ExecJs(shell(),
@@ -1946,43 +2056,62 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SelectOption) {
select.options[select.selectedIndex].label;
)";
+ // Selecting on a non-<select> element.
+ EXPECT_EQ(INVALID_TARGET,
+ SelectOption(Selector({"#input1"}), std::string(),
+ /* case_sensitive= */ false, SelectOptionProto::LABEL,
+ /* strict= */ true)
+ .proto_status());
+
// Fails if no comparison attribute is set.
EXPECT_EQ(INVALID_ACTION,
SelectOption(selector, "one", /* case_sensitive= */ false,
- SelectOptionProto::NOT_SET)
+ SelectOptionProto::NOT_SET, /* strict= */ true)
.proto_status());
// Select value not matching anything.
EXPECT_EQ(OPTION_VALUE_NOT_FOUND,
SelectOption(selector, "incorrect label",
- /* case_sensitive= */ false, SelectOptionProto::LABEL)
+ /* case_sensitive= */ false, SelectOptionProto::LABEL,
+ /* strict= */ true)
.proto_status());
+ // Select value matching everything.
+ EXPECT_EQ(TOO_MANY_OPTION_VALUES_FOUND,
+ SelectOption(selector, ".*", /* case_sensitive= */ false,
+ SelectOptionProto::LABEL, /* strict= */ true)
+ .proto_status());
+ EXPECT_EQ(ACTION_APPLIED,
+ SelectOption(selector, ".*", /* case_sensitive= */ false,
+ SelectOptionProto::LABEL, /* strict= */ false)
+ .proto_status());
+ EXPECT_EQ("One", content::EvalJs(shell(), javascript));
+
// Select value matching the option's label.
EXPECT_EQ(ACTION_APPLIED,
SelectOption(selector, "^ZÃœRICH", /* case_sensitive= */ false,
- SelectOptionProto::LABEL)
+ SelectOptionProto::LABEL, /* strict= */ true)
.proto_status());
EXPECT_EQ("Zürich Hauptbahnhof", content::EvalJs(shell(), javascript));
// Select value matching the option's value.
EXPECT_EQ(ACTION_APPLIED,
SelectOption(selector, "^Aü万𠜎$", /* case_sensitive= */ false,
- SelectOptionProto::VALUE)
+ SelectOptionProto::VALUE, /* strict= */ true)
.proto_status());
EXPECT_EQ("Character Test Entry", content::EvalJs(shell(), javascript));
// With a regular expression matching the option's value.
EXPECT_EQ(ACTION_APPLIED,
SelectOption(selector, "^O.E$", /* case_sensitive= */ false,
- SelectOptionProto::VALUE)
+ SelectOptionProto::VALUE, /* strict= */ true)
.proto_status());
EXPECT_EQ("One", content::EvalJs(shell(), javascript));
// With a regular expression matching the option's value case sensitive.
EXPECT_EQ(OPTION_VALUE_NOT_FOUND,
SelectOption(selector, "^O.E$", /* case_sensitive= */ true,
- SelectOptionProto::VALUE)
+ SelectOptionProto::VALUE, /* strict= */ true)
.proto_status());
EXPECT_EQ("One", content::EvalJs(shell(), javascript));
}
@@ -1992,7 +2121,7 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SelectOptionInIFrame) {
Selector select_selector({"#iframe", "select[name=state]"});
EXPECT_EQ(ACTION_APPLIED,
SelectOption(select_selector, "^NY", /* case_sensitive= */ false,
- SelectOptionProto::LABEL)
+ SelectOptionProto::LABEL, /* strict= */ true)
.proto_status());
const std::string javascript = R"(
@@ -2007,7 +2136,7 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SelectOptionInIFrame) {
select_selector = Selector({"#iframeExternal", "select[name=pet]"});
EXPECT_EQ(ACTION_APPLIED,
SelectOption(select_selector, "^Cat", /* case_sensitive= */ false,
- SelectOptionProto::LABEL)
+ SelectOptionProto::LABEL, /* strict= */ true)
.proto_status());
Selector result_selector({"#iframeExternal", "#myPet"});
@@ -2195,6 +2324,18 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SendKeyboardInput) {
GetFieldsValue(selectors, {expected_output, expected_output});
}
+IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest,
+ SendKeyboardInputAndCheckPasswordField) {
+ auto input = UTF8ToUnicode("password");
+ std::string output;
+
+ Selector selector({"#input_password"});
+ EXPECT_EQ(ACTION_APPLIED, SendKeyboardInput(selector, input).proto_status());
+ EXPECT_EQ(ACTION_APPLIED,
+ GetStringAttribute(selector, {"value"}, &output).proto_status());
+ EXPECT_EQ("password", output);
+}
+
IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SendKeyboardInputWithDelay) {
Selector selector({"#input6"});
@@ -2764,4 +2905,87 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest,
EXPECT_EQ(UNEXPECTED_JS_ERROR, status.proto_status());
}
+IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ElementQueryIndex) {
+ ClientStatus element_status;
+ ElementFinder::Result element;
+ FindElement(Selector({"#input3"}), &element_status, &element);
+ ASSERT_EQ(ACTION_APPLIED, element_status.proto_status());
+
+ int index;
+ EXPECT_EQ(ACTION_APPLIED,
+ GetElementQueryIndex("input", element, &index).proto_status());
+ EXPECT_EQ(2, index);
+}
+
+IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, UniqueElementSelector) {
+ ClientStatus element_status;
+ ElementFinder::Result element;
+ FindElement(Selector({"#input3"}), &element_status, &element);
+ ASSERT_EQ(ACTION_APPLIED, element_status.proto_status());
+
+ std::string query;
+ int index;
+ EXPECT_EQ(ACTION_APPLIED,
+ GetUniqueElementSelector(element, &query, &index).proto_status());
+ EXPECT_EQ("INPUT", query);
+ EXPECT_EQ(2, index);
+}
+
+IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SelectOptionElement) {
+ ClientStatus option_status;
+ ElementFinder::Result option;
+ FindElement(Selector({"#select option:nth-child(2)"}), &option_status,
+ &option);
+ ASSERT_EQ(ACTION_APPLIED, option_status.proto_status());
+
+ Selector selector({"#select"});
+
+ GetFieldsValue({selector}, {"one"});
+ EXPECT_EQ(ACTION_APPLIED,
+ SelectOptionElement(selector, option).proto_status());
+ GetFieldsValue({selector}, {"two"});
+
+ // Using on a non-<select> element.
+ EXPECT_EQ(INVALID_TARGET,
+ SelectOptionElement(Selector({"#input1"}), option).proto_status());
+
+ // Random element that is certainly not an option in the <select>.
+ FindElement(Selector({"#input1"}), &option_status, &option);
+ ASSERT_EQ(ACTION_APPLIED, option_status.proto_status());
+ EXPECT_EQ(OPTION_VALUE_NOT_FOUND,
+ SelectOptionElement(selector, option).proto_status());
+}
+
+IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, CheckSelectedOptionElement) {
+ ClientStatus status;
+
+ ElementFinder::Result input;
+ FindElement(Selector({"#input1"}), &status, &input);
+ ASSERT_EQ(ACTION_APPLIED, status.proto_status());
+
+ ElementFinder::Result select;
+ FindElement(Selector({"#select"}), &status, &select);
+ ASSERT_EQ(ACTION_APPLIED, status.proto_status());
+
+ ElementFinder::Result selected_option;
+ FindElement(Selector({"#select option:nth-child(1)"}), &status,
+ &selected_option);
+ ASSERT_EQ(ACTION_APPLIED, status.proto_status());
+
+ ElementFinder::Result not_selected_option;
+ FindElement(Selector({"#select option:nth-child(2)"}), &status,
+ &not_selected_option);
+ ASSERT_EQ(ACTION_APPLIED, status.proto_status());
+
+ EXPECT_EQ(ACTION_APPLIED,
+ CheckSelectedOptionElement(select, selected_option).proto_status());
+ EXPECT_EQ(
+ ELEMENT_MISMATCH,
+ CheckSelectedOptionElement(select, not_selected_option).proto_status());
+
+ // Using on a non-<select> element.
+ EXPECT_EQ(INVALID_TARGET,
+ CheckSelectedOptionElement(input, selected_option).proto_status());
+}
+
} // namespace autofill_assistant
diff --git a/chromium/components/autofill_assistant/browser/website_login_manager_impl_unittest.cc b/chromium/components/autofill_assistant/browser/website_login_manager_impl_unittest.cc
index 363674e7772..9daa00b8a75 100644
--- a/chromium/components/autofill_assistant/browser/website_login_manager_impl_unittest.cc
+++ b/chromium/components/autofill_assistant/browser/website_login_manager_impl_unittest.cc
@@ -20,7 +20,6 @@
using autofill::FormData;
using autofill::FormFieldData;
-using base::ASCIIToUTF16;
using password_manager::PasswordForm;
using testing::_;
using testing::Invoke;
@@ -33,11 +32,13 @@ namespace autofill_assistant {
namespace {
const char kFakeUrl[] = "http://www.example.com/";
const char kFakeUsername[] = "user@example.com";
-const char kFakePassword[] = "old_password";
+const char16_t kFakeUsername16[] = u"user@example.com";
+const char16_t kFakePassword[] = u"old_password";
const char kFakeNewPassword[] = "new_password";
-const char kFormDataName[] = "the-form-name";
-const char kPasswordElement[] = "password-element";
-const char kUsernameElement[] = "username-element";
+const char16_t kFakeNewPassword16[] = u"new_password";
+const char16_t kFormDataName[] = u"the-form-name";
+const char16_t kPasswordElement[] = u"password-element";
+const char16_t kUsernameElement[] = u"username-element";
class MockPasswordManagerClient
: public password_manager::StubPasswordManagerClient {
@@ -55,13 +56,13 @@ FormData MakeFormDataWithPasswordField() {
FormData form_data;
form_data.url = GURL(kFakeUrl);
form_data.action = GURL(kFakeUrl);
- form_data.name = ASCIIToUTF16(kFormDataName);
+ form_data.name = kFormDataName;
FormFieldData field;
- field.name = ASCIIToUTF16(kPasswordElement);
+ field.name = kPasswordElement;
field.id_attribute = field.name;
field.name_attribute = field.name;
- field.value = ASCIIToUTF16(kFakeNewPassword);
+ field.value = kFakeNewPassword16;
field.form_control_type = "password";
form_data.fields.push_back(field);
@@ -72,10 +73,10 @@ PasswordForm MakeSimplePasswordForm() {
PasswordForm form;
form.url = GURL(kFakeUrl);
form.signon_realm = form.url.GetOrigin().spec();
- form.password_value = ASCIIToUTF16(kFakePassword);
- form.username_value = ASCIIToUTF16(kFakeUsername);
- form.username_element = ASCIIToUTF16(kUsernameElement);
- form.password_element = ASCIIToUTF16(kPasswordElement);
+ form.password_value = kFakePassword;
+ form.username_value = kFakeUsername16;
+ form.username_element = kUsernameElement;
+ form.password_element = kPasswordElement;
form.in_store = PasswordForm::Store::kProfileStore;
return form;
@@ -85,7 +86,7 @@ PasswordForm MakeSimplePasswordFormWithoutUsername() {
PasswordForm form;
form.url = GURL(kFakeUrl);
form.signon_realm = form.url.GetOrigin().spec();
- form.password_value = ASCIIToUTF16(kFakeNewPassword);
+ form.password_value = kFakeNewPassword16;
form.in_store = PasswordForm::Store::kProfileStore;
return form;
@@ -177,7 +178,7 @@ TEST_F(WebsiteLoginManagerImplTest, SaveGeneratedPassword) {
// Commit generated password.
EXPECT_TRUE(manager()->ReadyToCommitGeneratedPassword());
PasswordForm new_form = MakeSimplePasswordForm();
- new_form.password_value = ASCIIToUTF16(kFakeNewPassword);
+ new_form.password_value = kFakeNewPassword16;
// Check that additional data is populated correctly from matched form.
EXPECT_CALL(*store(), UpdateLoginWithPrimaryKey(FormMatches(new_form), _));
manager()->CommitGeneratedPassword();
diff --git a/chromium/components/autofill_assistant_strings.grdp b/chromium/components/autofill_assistant_strings.grdp
index 264972ede12..30c1712b145 100644
--- a/chromium/components/autofill_assistant_strings.grdp
+++ b/chromium/components/autofill_assistant_strings.grdp
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <message name="IDS_AUTOFILL_ASSISTANT_PAYMENT_INFO_CONFIRM" desc="Text on the payment request primary button to confirm payment information [CHAR-LIMIT=32]">
+ <message name="IDS_AUTOFILL_ASSISTANT_PAYMENT_INFO_CONFIRM" desc="Text on the payment request primary button to confirm payment information [CHAR_LIMIT=32]">
Continue
</message>
<message name="IDS_AUTOFILL_ASSISTANT_DEFAULT_ERROR" desc="Text label that is shown when autofill assistant cannot help anymore, because something went wrong.">
diff --git a/chromium/components/autofill_payments_strings.grdp b/chromium/components/autofill_payments_strings.grdp
index 8fc7173d95c..1684adc1410 100644
--- a/chromium/components/autofill_payments_strings.grdp
+++ b/chromium/components/autofill_payments_strings.grdp
@@ -93,6 +93,9 @@
<message name="IDS_AUTOFILL_SAVE_CARD_PROMPT_CONFIRM" desc="Text to show for the Autofill upload save credit card prompt accept button when more information (e.g., CVC) was needed in order to save the card and was entered." formatter_data="android_java">
Confirm
</message>
+ <message name="IDS_AUTOFILL_MOBILE_SAVE_CARD_TO_CLOUD_CONFIRMATION_DIALOG_TITLE" desc="This message appears as the title of a confirmation dialog in which the user can view/edit the information that will be saved to Google Payments, and only appears after the user has expressed interest in uploading the card.">
+ Save to Google Account
+ </message>
</if>
<if expr="is_ios">
<then>
@@ -223,7 +226,7 @@
<message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_CHECKBOX_UNCHECK_WARNING" desc="The warning text, after the user unchecks the checkbox, to indicate this card will still be saved on this device only, not to Google account.">
Saved on this device only
</message>
- <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_OFFER" desc="The body text for a dialog that offers to migrate local cards into the cloud. [CHAR-LIMIT=NONE] [ICU Syntax]">
+ <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_OFFER" desc="The body text for a dialog that offers to migrate local cards into the cloud. [CHAR_LIMIT=NONE] [ICU Syntax]">
{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">$1<ex>user@gmail.com</ex></ph>.}
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">$1<ex>user@gmail.com</ex></ph>.}}
@@ -393,7 +396,7 @@
<message name="IDS_AUTOFILL_CARD_UNMASK_NEW_CARD_LINK" desc="Text for link that prompts user to update their credit card after it may have been re-issued." formatter_data="android_java">
Update card
</message>
- <message name="IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC" desc="The placeholder/label text for credit card verification code in the requestAutocomplete dialog. The text field where this is presented can be very narrow, so please prefer to translate this to the most common abbreviated form. [CHAR-LIMIT=4]" meaning="Placeholder label for a very narrow CVC field that should preferably be translated to an abbreviated form.">
+ <message name="IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC" desc="The placeholder/label text for credit card verification code in the requestAutocomplete dialog. The text field where this is presented can be very narrow, so please prefer to translate this to the most common abbreviated form. [CHAR_LIMIT=4]" meaning="Placeholder label for a very narrow CVC field that should preferably be translated to an abbreviated form.">
CVC
</message>
@@ -471,7 +474,7 @@
From Google Pay
</message>
- <!-- Cloud token related strings (Desktop only) -->
+ <!-- virtual cards related strings -->
<if expr="not is_ios and not is_android">
<message name="IDS_AUTOFILL_CLOUD_TOKEN_DROPDOWN_OPTION_LABEL" desc="Text shown in the button in the Autofill dropdown menu when a credit card form field is queried, to offer the option to use a virtual card.">
Use a virtual card number...
@@ -492,6 +495,22 @@
<message name="IDS_AUTOFILL_VIRTUAL_CARD_SELECTION_DIALOG_CANCEL_BUTTON_LABEL" desc="Text shown in the Cancel button in the Autofill virtual card selection dialog. This dialog offers all available virtual credit cards for users to choose.">
Cancel
</message>
+ <message name="IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_TITLE" desc="The title shown in the Autofill virtual card manual fallback bubble on Desktop. This bubble shows the complete information for the virtual card selected to fill the form.">
+ Virtual card number
+ </message>
+ <message name="IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_CARD_NUMBER_LABEL" desc="Text shown next to the virtual card number in the virtual card manual fallback bubble on Desktop. This bubble shows the complete information for the virtual card selected to fill the form.">
+ Virtual number:
+ </message>
+ <message name="IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_EXP_DATE_LABEL" desc="Text shown next to the virtual card expiration date in the virtual card manual fallback bubble on Desktop. This bubble shows the complete information for the virtual card selected to fill the form.">
+ Month/Year:
+ </message>
+ <message name="IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_CVC_LABEL" desc="Text shown next to the virtual card CVC code in the virtual card manual fallback bubble on Desktop. This bubble shows the complete information for the virtual card selected to fill the form.">
+ CVC:
+ </message>
+ <!-- TODO(crbug.com/1020740): Update tooltip message with final wording -->
+ <message name="IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_ICON_TOOLTIP" desc="The tooltip message for the omnibox icon for the virtual card manual fallback bubble on Desktop. This bubble shows the complete information for the virtual card selected to fill the form.">
+ View virtual card details
+ </message>
</if>
<message name="IDS_AUTOFILL_SAVE_UPI_PROMPT_TITLE" desc="Title text for the prompt to save a UPI ID locally, which the user used in a page. UPI is an online payment method. A UPI ID is an email-like string.">
@@ -530,4 +549,14 @@
See details
</message>
</if>
+
+ <!-- Strings related to virtual card numbers -->
+ <if expr="is_android">
+ <message name="IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_MESSAGE_TEXT" desc="Text to be displayed in the snackbar shown after a virtual card number id autofilled.">
+ Your virtual card number is applied.
+ </message>
+ <message name="IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_ACTION_TEXT" desc="Text to be displayed as the snackbar action shown after a virtual card number id autofilled.">
+ View virtual card
+ </message>
+ </if>
</grit-part>
diff --git a/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_MOBILE_SAVE_CARD_TO_CLOUD_CONFIRMATION_DIALOG_TITLE.png.sha1 b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_MOBILE_SAVE_CARD_TO_CLOUD_CONFIRMATION_DIALOG_TITLE.png.sha1
new file mode 100644
index 00000000000..76813da0b20
--- /dev/null
+++ b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_MOBILE_SAVE_CARD_TO_CLOUD_CONFIRMATION_DIALOG_TITLE.png.sha1
@@ -0,0 +1 @@
+37c8c340a5db76c7b4183c3bf42f84a3b948074a \ No newline at end of file
diff --git a/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_CARD_NUMBER_LABEL.png.sha1 b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_CARD_NUMBER_LABEL.png.sha1
new file mode 100644
index 00000000000..67b260da9c3
--- /dev/null
+++ b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_CARD_NUMBER_LABEL.png.sha1
@@ -0,0 +1 @@
+162070d949f0497137ad125f4299973b3932ab79 \ No newline at end of file
diff --git a/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_CVC_LABEL.png.sha1 b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_CVC_LABEL.png.sha1
new file mode 100644
index 00000000000..67b260da9c3
--- /dev/null
+++ b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_CVC_LABEL.png.sha1
@@ -0,0 +1 @@
+162070d949f0497137ad125f4299973b3932ab79 \ No newline at end of file
diff --git a/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_EXP_DATE_LABEL.png.sha1 b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_EXP_DATE_LABEL.png.sha1
new file mode 100644
index 00000000000..67b260da9c3
--- /dev/null
+++ b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_EXP_DATE_LABEL.png.sha1
@@ -0,0 +1 @@
+162070d949f0497137ad125f4299973b3932ab79 \ No newline at end of file
diff --git a/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_TITLE.png.sha1 b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_TITLE.png.sha1
new file mode 100644
index 00000000000..67b260da9c3
--- /dev/null
+++ b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_BUBBLE_TITLE.png.sha1
@@ -0,0 +1 @@
+162070d949f0497137ad125f4299973b3932ab79 \ No newline at end of file
diff --git a/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_ICON_TOOLTIP.png.sha1 b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_ICON_TOOLTIP.png.sha1
new file mode 100644
index 00000000000..8f051688263
--- /dev/null
+++ b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_MANUAL_FALLBACK_ICON_TOOLTIP.png.sha1
@@ -0,0 +1 @@
+4b9f5a780c3a662c79041b21ccb347180cdb907a \ No newline at end of file
diff --git a/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_ACTION_TEXT.png.sha1 b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_ACTION_TEXT.png.sha1
new file mode 100644
index 00000000000..99202b1f042
--- /dev/null
+++ b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_ACTION_TEXT.png.sha1
@@ -0,0 +1 @@
+d2f6c9ac4746fcf9e4c6d723c809c421fa048536 \ No newline at end of file
diff --git a/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_MESSAGE_TEXT.png.sha1 b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_MESSAGE_TEXT.png.sha1
new file mode 100644
index 00000000000..99202b1f042
--- /dev/null
+++ b/chromium/components/autofill_payments_strings_grdp/IDS_AUTOFILL_VIRTUAL_CARD_NUMBER_SNACKBAR_MESSAGE_TEXT.png.sha1
@@ -0,0 +1 @@
+d2f6c9ac4746fcf9e4c6d723c809c421fa048536 \ No newline at end of file
diff --git a/chromium/components/autofill_strings.grdp b/chromium/components/autofill_strings.grdp
index bde78f4aad3..758cf5613ba 100644
--- a/chromium/components/autofill_strings.grdp
+++ b/chromium/components/autofill_strings.grdp
@@ -185,17 +185,17 @@
''' • '''</message>
<!-- Autofill credit card suggestion popup -->
- <message name="IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR" desc="Abbreviated label for credit card expiration date. [CHAR-LIMIT=32]">
+ <message name="IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR" desc="Abbreviated label for credit card expiration date. [CHAR_LIMIT=32]">
Exp: <ph name="EXPIRATION_MONTH">$1<ex>06</ex></ph>/<ph name="EXPIRATION_YEAR">$2<ex>17</ex></ph>
</message>
- <message name="IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR_V2" desc="Abbreviated label for credit card expiration date. Please translate the date as either YY/MM or MM/YY depending on how credit card expiration dates are more commonly presented in your locale. [CHAR-LIMIT=32]" meaning="Label for credit card expiration date for the save card dialog.">
+ <message name="IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR_V2" desc="Abbreviated label for credit card expiration date. Please translate the date as either YY/MM or MM/YY depending on how credit card expiration dates are more commonly presented in your locale. [CHAR_LIMIT=32]" meaning="Label for credit card expiration date for the save card dialog.">
<ph name="EXPIRATION_MONTH">$1<ex>06</ex></ph>/<ph name="EXPIRATION_YEAR">$2<ex>17</ex></ph>
</message>
- <message name="IDS_AUTOFILL_CREDIT_CARD_TWO_LINE_LABEL_FROM_NAME" desc="Second line label for the autofill credit card popup when the name is selected. This text will appear below the cardholder name. [CHAR-LIMIT=32]">
+ <message name="IDS_AUTOFILL_CREDIT_CARD_TWO_LINE_LABEL_FROM_NAME" desc="Second line label for the autofill credit card popup when the name is selected. This text will appear below the cardholder name. [CHAR_LIMIT=32]">
<ph name="CREDIT_CARD">$1<ex>Visa ••••5679</ex></ph>, expires on <ph name="EXPIRATION_DATE_ABBR">$2<ex>06/17</ex></ph>
</message>
- <message name="IDS_AUTOFILL_CREDIT_CARD_TWO_LINE_LABEL_FROM_CARD_NUMBER" desc="Second line label for the autofill credit card popup when the card number is selected. This text will appear below the credit card number. [CHAR-LIMIT=32]">
+ <message name="IDS_AUTOFILL_CREDIT_CARD_TWO_LINE_LABEL_FROM_CARD_NUMBER" desc="Second line label for the autofill credit card popup when the card number is selected. This text will appear below the credit card number. [CHAR_LIMIT=32]">
Expires on <ph name="EXPIRATION_DATE_ABBR">$1<ex>06/17</ex></ph>
</message>
@@ -316,4 +316,87 @@
</message>
</if>
+ <!-- Explicit save/update address prompt strings -->
+ <!-- Common on all platforms (platform-specific defined later): -->
+ <message name="IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_OK_BUTTON_LABEL" desc="Label of the OK button in the prompt that offers the user to save a new address.">
+ Save
+ </message>
+ <message name="IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_OK_BUTTON_LABEL" desc="Label of the OK button in the prompt that offers the user to update an existing address.">
+ Update
+ </message>
+ <message name="IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_NEW_VALUES_SECTION_LABEL" meaning="In the address update prompt" desc="Label shown next to the section that displays the new address values in the prompt that offers the user to update an existing address." formatter_data="android_java">
+ New
+ </message>
+ <message name="IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_OLD_VALUES_SECTION_LABEL" meaning="In the address update prompt" desc="Label shown next to the section that displays the old address values in the prompt that offers the user to update an existing address." formatter_data="android_java">
+ Old
+ </message>
+ <!-- Used on Android: -->
+ <if expr="is_android">
+ <message name="IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE" desc="Title shown at the top of prompt that offers the user to save a new address.">
+ Save address?
+ </message>
+ <message name="IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE" desc="Title shown at the top of prompt that offers the user to update an existing address.">
+ Update address?
+ </message>
+ <message name="IDS_ANDROID_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL" desc="Label of the negative button in the modal dialog that offers the user to save a new address.">
+ Cancel
+ </message>
+ <message name="IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_EDIT_BUTTON_TOOLTIP" desc="Tooltip of the Edit button in the prompt that offers the user to save a new address." formatter_data="android_java">
+ Edit address
+ </message>
+ <message name="IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_TITLE" desc="Title shown at the top of dialog that edits an address before saving it" formatter_data="android_java">
+ Edit address
+ </message>
+ </if>
+ <!-- Used on iOS: -->
+ <if expr="is_ios">
+ <message name="IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_TITLE" desc="In Title Case: Title shown in the message that offers the user to proceed with saving a new address." meaning="In Title Case for iOS">
+ Save Address?
+ </message>
+ <message name="IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_PRIMARY_ACTION" desc="Label of the primary action button in the message that offers the user to proceed with saving a new address.">
+ Save…
+ </message>
+ <message name="IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_TITLE" desc="In Title Case: Title shown in the message that offers the user to proceed with updating an existing address." meaning="In Title Case for iOS">
+ Update Address?
+ </message>
+ <message name="IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_PRIMARY_ACTION" desc="Label of the primary action button in the message that offers the user to proceed with updating an existing address.">
+ Update…
+ </message>
+ <message name="IDS_IOS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE" desc="In Title Case: Title shown at the top of modal dialog that offers the user to save a new address." meaning="In Title Case for iOS">
+ Save Address
+ </message>
+ <message name="IDS_IOS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE" desc="In Title Case: Title shown at the top of modal dialog that offers the user to update an existing address." meaning="In Title Case for iOS">
+ Update Address
+ </message>
+ </if>
+ <!-- Used on Desktop: -->
+ <if expr="not is_android and not is_ios">
+ <message name="IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE" desc="Title shown at the top of prompt that offers the user to save a new address.">
+ Save address?
+ </message>
+ <message name="IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL" desc="Label of the Cancel button in the prompt that offers the user to save a new address.">
+ No thanks
+ </message>
+ <message name="IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_EDIT_BUTTON_TOOLTIP" desc="Tooltip of the Edit button in the prompt that offers the user to save a new address.">
+ Edit address
+ </message>
+ <message name="IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE" desc="Title shown at the top of prompt that offers the user to update an existing address.">
+ Update address?
+ </message>
+ <message name="IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL" desc="Label of the Cancel button in the prompt that offers the user to update an existing address.">
+ No thanks
+ </message>
+ <message name="IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_TITLE" desc="Title shown at the top of dialog that edits an address before saving it">
+ Edit address
+ </message>
+ <message name="IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_SAVE" desc="Label of the OK button in the dialog that edits the address before saving it as a new address.">
+ Save
+ </message>
+ <message name="IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_UPDATE" desc="Label of the OK button in the dialog that edits the address before using it to update an existing address.">
+ Update
+ </message>
+ <message name="IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_CANCEL_BUTTON_LABEL" desc="Label of the Cancel button in the dialog that edits an address before saving it.">
+ Cancel
+ </message>
+ </if>
</grit-part>
diff --git a/chromium/components/autofill_strings_grdp/IDS_ANDROID_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_ANDROID_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha1
new file mode 100644
index 00000000000..51b3663c3c4
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_ANDROID_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+f3ebbd06ed833a22a584ee3031b0882f5ffaa9a8 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_CANCEL_BUTTON_LABEL.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_CANCEL_BUTTON_LABEL.png.sha1
new file mode 100644
index 00000000000..99ae39242e6
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_CANCEL_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+187e178e87ccc11b83208e0264733d3d813f9e75 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_SAVE.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_SAVE.png.sha1
new file mode 100644
index 00000000000..99ae39242e6
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_SAVE.png.sha1
@@ -0,0 +1 @@
+187e178e87ccc11b83208e0264733d3d813f9e75 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_UPDATE.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_UPDATE.png.sha1
new file mode 100644
index 00000000000..6b47f833b2e
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_OK_BUTTON_LABEL_UPDATE.png.sha1
@@ -0,0 +1 @@
+712e2e02bb3b80855bd44549d53c11ee7084263c \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_TITLE.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_TITLE.png.sha1
new file mode 100644
index 00000000000..99ae39242e6
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_EDIT_ADDRESS_DIALOG_TITLE.png.sha1
@@ -0,0 +1 @@
+187e178e87ccc11b83208e0264733d3d813f9e75 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha1
new file mode 100644
index 00000000000..430d465fd9b
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+205ee10a48b93ab135b8ff013336f41a9c414091 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_EDIT_BUTTON_TOOLTIP.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_EDIT_BUTTON_TOOLTIP.png.sha1
new file mode 100644
index 00000000000..430d465fd9b
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_EDIT_BUTTON_TOOLTIP.png.sha1
@@ -0,0 +1 @@
+205ee10a48b93ab135b8ff013336f41a9c414091 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_OK_BUTTON_LABEL.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_OK_BUTTON_LABEL.png.sha1
new file mode 100644
index 00000000000..430d465fd9b
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_OK_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+205ee10a48b93ab135b8ff013336f41a9c414091 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE.png.sha1
new file mode 100644
index 00000000000..430d465fd9b
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE.png.sha1
@@ -0,0 +1 @@
+205ee10a48b93ab135b8ff013336f41a9c414091 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha1
new file mode 100644
index 00000000000..e130d5ad595
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_CANCEL_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+84e751eaf9c2ec6fc565674944b97a8fb8f70361 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_NEW_VALUES_SECTION_LABEL.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_NEW_VALUES_SECTION_LABEL.png.sha1
new file mode 100644
index 00000000000..e130d5ad595
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_NEW_VALUES_SECTION_LABEL.png.sha1
@@ -0,0 +1 @@
+84e751eaf9c2ec6fc565674944b97a8fb8f70361 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_OK_BUTTON_LABEL.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_OK_BUTTON_LABEL.png.sha1
new file mode 100644
index 00000000000..e130d5ad595
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_OK_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+84e751eaf9c2ec6fc565674944b97a8fb8f70361 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_OLD_VALUES_SECTION_LABEL.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_OLD_VALUES_SECTION_LABEL.png.sha1
new file mode 100644
index 00000000000..e130d5ad595
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_OLD_VALUES_SECTION_LABEL.png.sha1
@@ -0,0 +1 @@
+84e751eaf9c2ec6fc565674944b97a8fb8f70361 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE.png.sha1
new file mode 100644
index 00000000000..e130d5ad595
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE.png.sha1
@@ -0,0 +1 @@
+84e751eaf9c2ec6fc565674944b97a8fb8f70361 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_PRIMARY_ACTION.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_PRIMARY_ACTION.png.sha1
new file mode 100644
index 00000000000..9e758daf15b
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_PRIMARY_ACTION.png.sha1
@@ -0,0 +1 @@
+9a7a9f643f7f8eff2243669712464e91c64180eb \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_TITLE.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_TITLE.png.sha1
new file mode 100644
index 00000000000..9e758daf15b
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_MESSAGE_TITLE.png.sha1
@@ -0,0 +1 @@
+9a7a9f643f7f8eff2243669712464e91c64180eb \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE.png.sha1
new file mode 100644
index 00000000000..24ad858263b
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_SAVE_ADDRESS_PROMPT_TITLE.png.sha1
@@ -0,0 +1 @@
+a821463ac6f6eb607114546ac35fe80dc4a67418 \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_PRIMARY_ACTION.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_PRIMARY_ACTION.png.sha1
new file mode 100644
index 00000000000..8594d5a7615
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_PRIMARY_ACTION.png.sha1
@@ -0,0 +1 @@
+2bf8eb1bb5f0554c06a157d0e767dcf7c9d2858d \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_TITLE.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_TITLE.png.sha1
new file mode 100644
index 00000000000..8594d5a7615
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_MESSAGE_TITLE.png.sha1
@@ -0,0 +1 @@
+2bf8eb1bb5f0554c06a157d0e767dcf7c9d2858d \ No newline at end of file
diff --git a/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE.png.sha1 b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE.png.sha1
new file mode 100644
index 00000000000..6c5969176c0
--- /dev/null
+++ b/chromium/components/autofill_strings_grdp/IDS_IOS_AUTOFILL_UPDATE_ADDRESS_PROMPT_TITLE.png.sha1
@@ -0,0 +1 @@
+89a78a7382c457c7f9433a697deded79702c13ab \ No newline at end of file
diff --git a/chromium/components/back_forward_cache/back_forward_cache_disable.cc b/chromium/components/back_forward_cache/back_forward_cache_disable.cc
index 6804a8f658a..1100ab4e946 100644
--- a/chromium/components/back_forward_cache/back_forward_cache_disable.cc
+++ b/chromium/components/back_forward_cache/back_forward_cache_disable.cc
@@ -29,6 +29,12 @@ std::string ReasonIdToString(DisabledReasonId reason_id) {
return "ChromePasswordManagerClient::BindCredentialManager";
case DisabledReasonId::kPermissionRequestManager:
return "PermissionRequestManager";
+ case DisabledReasonId::kModalDialog:
+ return "ModalDialog";
+ case DisabledReasonId::kExtensions:
+ return "Extensions";
+ case DisabledReasonId::kExtensionMessaging:
+ return "ExtensionMessaging";
default:
return "Unknown (default)";
}
diff --git a/chromium/components/back_forward_cache/back_forward_cache_disable.h b/chromium/components/back_forward_cache/back_forward_cache_disable.h
index de41fcad01e..4f81cef13f0 100644
--- a/chromium/components/back_forward_cache/back_forward_cache_disable.h
+++ b/chromium/components/back_forward_cache/back_forward_cache_disable.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_BACK_FORWARD_CACHE_BACK_FORWARD_CACHE_DISABLE_H_
#define COMPONENTS_BACK_FORWARD_CACHE_BACK_FORWARD_CACHE_DISABLE_H_
-#include <string>
-
#include "content/public/browser/back_forward_cache.h"
#include "content/public/browser/global_routing_id.h"
@@ -28,6 +26,11 @@ enum class DisabledReasonId : content::BackForwardCache::DisabledReasonType {
kOfflinePage = 8,
kChromePasswordManagerClient_BindCredentialManager = 9,
kPermissionRequestManager = 10,
+ // Modal dialog such as form resubmittion or http password dialog is shown for
+ // the page.
+ kModalDialog = 11,
+ kExtensions = 12,
+ kExtensionMessaging = 13,
// New reasons should be accompanied by a comment as to why BackForwardCache
// cannot be used in this case and a link to a bug to fix that if it is
// fixable.
diff --git a/chromium/components/background_fetch/background_fetch_delegate_base.cc b/chromium/components/background_fetch/background_fetch_delegate_base.cc
index 51bd9eb447a..c95e9cdd8d9 100644
--- a/chromium/components/background_fetch/background_fetch_delegate_base.cc
+++ b/chromium/components/background_fetch/background_fetch_delegate_base.cc
@@ -28,6 +28,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/data_pipe_getter.mojom.h"
#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom.h"
+#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "ui/gfx/geometry/size.h"
namespace background_fetch {
@@ -52,40 +53,6 @@ void BackgroundFetchDelegateBase::GetIconDisplaySize(
std::move(callback).Run(display_size);
}
-void BackgroundFetchDelegateBase::GetPermissionForOrigin(
- const url::Origin& origin,
- const content::WebContents::Getter& wc_getter,
- GetPermissionForOriginCallback callback) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- if (wc_getter) {
- // The fetch should be thought of as one download. So the origin will be
- // used as the URL, and the |request_method| is set to GET.
- content::BrowserContext::GetDownloadManager(context_)
- ->GetDelegate()
- ->CheckDownloadAllowed(
- wc_getter, origin.GetURL(), "GET", base::nullopt,
- false /* from_download_cross_origin_redirect */,
- true /* content_initiated */,
- base::BindOnce(&BackgroundFetchDelegateBase::
- DidGetPermissionFromDownloadRequestLimiter,
- weak_ptr_factory_.GetWeakPtr(),
- std::move(callback)));
- return;
- }
-
- GetPermissionForOriginWithoutWebContents(origin, std::move(callback));
-}
-
-void BackgroundFetchDelegateBase::DidGetPermissionFromDownloadRequestLimiter(
- GetPermissionForOriginCallback callback,
- bool has_permission) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- std::move(callback).Run(has_permission
- ? content::BackgroundFetchPermission::ALLOWED
- : content::BackgroundFetchPermission::BLOCKED);
-}
-
void BackgroundFetchDelegateBase::CreateDownloadJob(
base::WeakPtr<Client> client,
std::unique_ptr<content::BackgroundFetchDescription> fetch_description) {
@@ -143,11 +110,11 @@ void BackgroundFetchDelegateBase::DownloadUrl(
}
if (job_details->job_state == JobDetails::State::kStartedButPaused) {
- job_details->on_resume =
- base::BindOnce(&BackgroundFetchDelegateBase::StartDownload,
- GetWeakPtr(), job_id, params, has_request_body);
+ job_details->on_resume = base::BindOnce(
+ &BackgroundFetchDelegateBase::StartDownload, GetWeakPtr(), job_id,
+ std::move(params), has_request_body);
} else {
- StartDownload(job_id, params, has_request_body);
+ StartDownload(job_id, std::move(params), has_request_body);
}
DoUpdateUi(job_id);
@@ -229,15 +196,14 @@ JobDetails* BackgroundFetchDelegateBase::GetJobDetails(
return &job_details_iter->second;
}
-void BackgroundFetchDelegateBase::StartDownload(
- const std::string& job_id,
- const download::DownloadParams& params,
- bool has_request_body) {
+void BackgroundFetchDelegateBase::StartDownload(const std::string& job_id,
+ download::DownloadParams params,
+ bool has_request_body) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
GetJobDetails(job_id)->current_fetch_guids.emplace(params.guid,
has_request_body);
- GetDownloadService()->StartDownload(params);
+ GetDownloadService()->StartDownload(std::move(params));
}
void BackgroundFetchDelegateBase::Abort(const std::string& job_id) {
diff --git a/chromium/components/background_fetch/background_fetch_delegate_base.h b/chromium/components/background_fetch/background_fetch_delegate_base.h
index c45703f2fdf..4a0e1e50430 100644
--- a/chromium/components/background_fetch/background_fetch_delegate_base.h
+++ b/chromium/components/background_fetch/background_fetch_delegate_base.h
@@ -42,9 +42,6 @@ class BackgroundFetchDelegateBase : public content::BackgroundFetchDelegate {
// BackgroundFetchDelegate implementation:
void GetIconDisplaySize(GetIconDisplaySizeCallback callback) override;
- void GetPermissionForOrigin(const url::Origin& origin,
- const content::WebContents::Getter& wc_getter,
- GetPermissionForOriginCallback callback) override;
void CreateDownloadJob(base::WeakPtr<Client> client,
std::unique_ptr<content::BackgroundFetchDescription>
fetch_description) override;
@@ -108,12 +105,6 @@ class BackgroundFetchDelegateBase : public content::BackgroundFetchDelegate {
void OnUiFinished(const std::string& job_id, bool activated);
protected:
- // Called to determine the permission setting in the case where no associated
- // WebContents is provided.
- virtual void GetPermissionForOriginWithoutWebContents(
- const url::Origin& origin,
- GetPermissionForOriginCallback callback) = 0;
-
// Return the download service for `context_`.
virtual download::DownloadService* GetDownloadService() = 0;
@@ -142,17 +133,12 @@ class BackgroundFetchDelegateBase : public content::BackgroundFetchDelegate {
private:
// Starts a download according to `params` belonging to `job_id`.
void StartDownload(const std::string& job_id,
- const download::DownloadParams& params,
+ download::DownloadParams params,
bool has_request_body);
void OnDownloadReceived(const std::string& guid,
download::DownloadParams::StartResult result);
- // The callback passed to DownloadRequestLimiter::CanDownload().
- void DidGetPermissionFromDownloadRequestLimiter(
- GetPermissionForOriginCallback callback,
- bool has_permission);
-
void DidGetUploadData(const std::string& job_id,
const std::string& download_guid,
download::GetUploadDataCallback callback,
diff --git a/chromium/components/background_sync/background_sync_controller_impl.cc b/chromium/components/background_sync/background_sync_controller_impl.cc
index 6516787d2ee..b7ec44cbca6 100644
--- a/chromium/components/background_sync/background_sync_controller_impl.cc
+++ b/chromium/components/background_sync/background_sync_controller_impl.cc
@@ -78,9 +78,8 @@ void BackgroundSyncControllerImpl::OnContentSettingChanged(
if (!IsContentSettingBlocked(origin))
continue;
- auto* storage_partition =
- content::BrowserContext::GetStoragePartitionForUrl(
- browser_context_, origin.GetURL(), /* can_create= */ false);
+ auto* storage_partition = browser_context_->GetStoragePartitionForUrl(
+ origin.GetURL(), /* can_create= */ false);
if (!storage_partition)
continue;
diff --git a/chromium/components/background_sync/background_sync_delegate.h b/chromium/components/background_sync/background_sync_delegate.h
index 5a4566b8cdb..944250550f1 100644
--- a/chromium/components/background_sync/background_sync_delegate.h
+++ b/chromium/components/background_sync/background_sync_delegate.h
@@ -8,11 +8,11 @@
#include <set>
#include "base/callback.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/public/browser/background_sync_controller.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/background_sync/background_sync.mojom-forward.h"
#include "url/origin.h"
@@ -37,10 +37,10 @@ class BackgroundSyncDelegate {
#endif
// Gets the source_ID to log the UKM event for, and calls |callback| with that
- // source_id, or with base::nullopt if UKM recording is not allowed.
+ // source_id, or with absl::nullopt if UKM recording is not allowed.
virtual void GetUkmSourceId(
const url::Origin& origin,
- base::OnceCallback<void(base::Optional<ukm::SourceId>)> callback) = 0;
+ base::OnceCallback<void(absl::optional<ukm::SourceId>)> callback) = 0;
// Handles browser shutdown.
virtual void Shutdown() = 0;
diff --git a/chromium/components/background_sync/background_sync_metrics.cc b/chromium/components/background_sync/background_sync_metrics.cc
index b61e26bece3..7771cf3d703 100644
--- a/chromium/components/background_sync/background_sync_metrics.cc
+++ b/chromium/components/background_sync/background_sync_metrics.cc
@@ -83,7 +83,7 @@ void BackgroundSyncMetrics::MaybeRecordPeriodicSyncEventCompletion(
void BackgroundSyncMetrics::DidGetBackgroundSourceId(
RecordCallback record_callback,
- base::Optional<ukm::SourceId> source_id) {
+ absl::optional<ukm::SourceId> source_id) {
// This background event did not meet the requirements for the UKM service.
if (!source_id)
return;
diff --git a/chromium/components/background_sync/background_sync_metrics.h b/chromium/components/background_sync/background_sync_metrics.h
index fe5f9ff95e1..01f0ffcc052 100644
--- a/chromium/components/background_sync/background_sync_metrics.h
+++ b/chromium/components/background_sync/background_sync_metrics.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
namespace {
@@ -57,7 +58,7 @@ class BackgroundSyncMetrics {
friend class BackgroundSyncMetricsBrowserTest;
void DidGetBackgroundSourceId(RecordCallback record_callback,
- base::Optional<ukm::SourceId> source_id);
+ absl::optional<ukm::SourceId> source_id);
void RecordOneShotSyncRegistrationEvent(bool can_fire,
bool is_reregistered,
diff --git a/chromium/components/background_sync/background_sync_permission_context_unittest.cc b/chromium/components/background_sync/background_sync_permission_context_unittest.cc
index e15d89af8fe..5f8585d4507 100644
--- a/chromium/components/background_sync/background_sync_permission_context_unittest.cc
+++ b/chromium/components/background_sync/background_sync_permission_context_unittest.cc
@@ -43,9 +43,9 @@ class BackgroundSyncPermissionContextTest
permissions::PermissionRequestID::RequestLocalId());
permission_context->RequestPermission(
web_contents(), id, url, /* user_gesture= */ false,
- base::AdaptCallbackForRepeating(base::BindOnce(
+ base::BindOnce(
&BackgroundSyncPermissionContextTest::TrackPermissionDecision,
- base::Unretained(this), run_loop.QuitClosure())));
+ base::Unretained(this), run_loop.QuitClosure()));
run_loop.Run();
}
diff --git a/chromium/components/background_task_scheduler/task_info.h b/chromium/components/background_task_scheduler/task_info.h
index 68d52c31c9a..91d77d57675 100644
--- a/chromium/components/background_task_scheduler/task_info.h
+++ b/chromium/components/background_task_scheduler/task_info.h
@@ -9,8 +9,8 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/background_task_scheduler/task_ids.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace background_task {
@@ -74,9 +74,9 @@ struct TaskInfo {
bool update_current;
std::string extras;
- base::Optional<PeriodicInfo> periodic_info;
- base::Optional<OneOffInfo> one_off_info;
- base::Optional<ExactInfo> exact_info;
+ absl::optional<PeriodicInfo> periodic_info;
+ absl::optional<OneOffInfo> one_off_info;
+ absl::optional<ExactInfo> exact_info;
DISALLOW_COPY_AND_ASSIGN(TaskInfo);
};
diff --git a/chromium/components/blocked_content/BUILD.gn b/chromium/components/blocked_content/BUILD.gn
index a312dc9d400..e5f9e8a9e41 100644
--- a/chromium/components/blocked_content/BUILD.gn
+++ b/chromium/components/blocked_content/BUILD.gn
@@ -50,6 +50,7 @@ source_set("blocked_content") {
"android/popup_blocked_message_delegate.h",
]
deps += [
+ "//components/infobars/android",
"//components/infobars/content",
"//components/infobars/core",
"//components/messages/android",
diff --git a/chromium/components/blocked_content/android/DEPS b/chromium/components/blocked_content/android/DEPS
index 5c93f7b0b85..a1a32a7362b 100644
--- a/chromium/components/blocked_content/android/DEPS
+++ b/chromium/components/blocked_content/android/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/infobars/android",
"+components/infobars/content",
"+components/infobars/core",
"+components/resources/android",
diff --git a/chromium/components/blocked_content/android/popup_blocked_infobar_delegate.cc b/chromium/components/blocked_content/android/popup_blocked_infobar_delegate.cc
index af999a2b7f6..a66dd385f94 100644
--- a/chromium/components/blocked_content/android/popup_blocked_infobar_delegate.cc
+++ b/chromium/components/blocked_content/android/popup_blocked_infobar_delegate.cc
@@ -11,6 +11,7 @@
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/infobars/android/confirm_infobar.h"
#include "components/infobars/content/content_infobar_manager.h"
#include "components/infobars/core/infobar.h"
#include "components/prefs/pref_service.h"
@@ -27,11 +28,10 @@ bool PopupBlockedInfoBarDelegate::Create(
HostContentSettingsMap* settings_map,
base::OnceClosure on_accept_callback) {
const GURL& url = infobar_manager->web_contents()->GetURL();
- std::unique_ptr<infobars::InfoBar> infobar(
- infobar_manager->CreateConfirmInfoBar(
- std::unique_ptr<ConfirmInfoBarDelegate>(
- new PopupBlockedInfoBarDelegate(num_popups, url, settings_map,
- std::move(on_accept_callback)))));
+ auto infobar = std::make_unique<infobars::ConfirmInfoBar>(
+ base::WrapUnique<PopupBlockedInfoBarDelegate>(
+ new PopupBlockedInfoBarDelegate(num_popups, url, settings_map,
+ std::move(on_accept_callback))));
// See if there is an existing popup infobar already.
// TODO(dfalcantara) When triggering more than one popup the infobar
diff --git a/chromium/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc b/chromium/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc
index c5458365e38..8ec1f59c814 100644
--- a/chromium/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc
+++ b/chromium/components/blocked_content/android/popup_blocked_infobar_delegate_unittest.cc
@@ -22,21 +22,10 @@
namespace blocked_content {
namespace {
+
constexpr char kPageUrl[] = "http://example_page.test";
constexpr char kPopupUrl[] = "http://example_popup.test";
-class TestInfoBarManager : public infobars::ContentInfoBarManager {
- public:
- explicit TestInfoBarManager(content::WebContents* web_contents)
- : ContentInfoBarManager(web_contents) {}
-
- // infobars::InfoBarManager:
- std::unique_ptr<infobars::InfoBar> CreateConfirmInfoBar(
- std::unique_ptr<ConfirmInfoBarDelegate> delegate) override {
- return std::make_unique<infobars::InfoBar>(std::move(delegate));
- }
-};
-
} // namespace
class PopupBlockedInfoBarDelegateTest
@@ -67,14 +56,17 @@ class PopupBlockedInfoBarDelegateTest
PopupBlockerTabHelper::CreateForWebContents(web_contents());
helper_ = PopupBlockerTabHelper::FromWebContents(web_contents());
- infobar_manager_ = std::make_unique<TestInfoBarManager>(web_contents());
+ infobar_manager_ =
+ std::make_unique<infobars::ContentInfoBarManager>(web_contents());
NavigateAndCommit(GURL(kPageUrl));
}
PopupBlockerTabHelper* helper() { return helper_; }
- TestInfoBarManager* infobar_manager() { return infobar_manager_.get(); }
+ infobars::ContentInfoBarManager* infobar_manager() {
+ return infobar_manager_.get();
+ }
HostContentSettingsMap* settings_map() { return settings_map_.get(); }
@@ -83,7 +75,7 @@ class PopupBlockedInfoBarDelegateTest
PopupBlockerTabHelper* helper_ = nullptr;
sync_preferences::TestingPrefServiceSyncable pref_service_;
scoped_refptr<HostContentSettingsMap> settings_map_;
- std::unique_ptr<TestInfoBarManager> infobar_manager_;
+ std::unique_ptr<infobars::ContentInfoBarManager> infobar_manager_;
};
TEST_F(PopupBlockedInfoBarDelegateTest, ReplacesInfobarOnSecondPopup) {
diff --git a/chromium/components/blocked_content/android/popup_blocked_message_delegate.cc b/chromium/components/blocked_content/android/popup_blocked_message_delegate.cc
index d98b53ffe9f..7a96e200d04 100644
--- a/chromium/components/blocked_content/android/popup_blocked_message_delegate.cc
+++ b/chromium/components/blocked_content/android/popup_blocked_message_delegate.cc
@@ -31,13 +31,14 @@ bool PopupBlockedMessageDelegate::ShowMessage(
url_ = web_contents_->GetLastCommittedURL();
// Unretained is safe because |this| will always outlive |message_| which owns
// the callback.
- message_ = std::make_unique<messages::MessageWrapper>(
+ auto message = std::make_unique<messages::MessageWrapper>(
+ messages::MessageIdentifier::POPUP_BLOCKED,
base::BindOnce(&PopupBlockedMessageDelegate::HandleClick,
base::Unretained(this)),
base::BindOnce(&PopupBlockedMessageDelegate::HandleDismissCallback,
base::Unretained(this)));
- message_->SetTitle(l10n_util::GetPluralStringFUTF16(
+ message->SetTitle(l10n_util::GetPluralStringFUTF16(
IDS_POPUPS_BLOCKED_INFOBAR_TEXT, num_popups));
map_ = settings_map;
@@ -46,13 +47,20 @@ bool PopupBlockedMessageDelegate::ShowMessage(
// Don't allow the user to configure the setting in the UI if the setting
// is managed by policy.
int button_text_id = allow_settings_changes_ ? IDS_SHOW_CONTENT : IDS_OK;
- message_->SetPrimaryButtonText(l10n_util::GetStringUTF16(button_text_id));
- message_->SetIconResourceId(
+ message->SetPrimaryButtonText(l10n_util::GetStringUTF16(button_text_id));
+ message->SetIconResourceId(
resource_id_mapper.Run(IDR_ANDROID_INFOBAR_BLOCKED_POPUPS));
- messages::MessageDispatcherBridge::Get()->EnqueueMessage(
- message_.get(), web_contents_, messages::MessageScopeType::NAVIGATION);
+ // On rare occasions, such as the moment when activity is being recreated
+ // or destroyed, popup blocked message will not be displayed and the
+ // method will return false.
+ if (!messages::MessageDispatcherBridge::Get()->EnqueueMessage(
+ message.get(), web_contents_, messages::MessageScopeType::NAVIGATION,
+ messages::MessagePriority::kNormal)) {
+ return false;
+ }
+ message_ = std::move(message);
return true;
}
diff --git a/chromium/components/blocked_content/android/popup_blocked_message_delegate_unittest.cc b/chromium/components/blocked_content/android/popup_blocked_message_delegate_unittest.cc
index 97bcf4648d8..7a6032e6d4e 100644
--- a/chromium/components/blocked_content/android/popup_blocked_message_delegate_unittest.cc
+++ b/chromium/components/blocked_content/android/popup_blocked_message_delegate_unittest.cc
@@ -42,7 +42,9 @@ class PopupBlockedMessageDelegateTest
return base::BindRepeating(ResourceMap);
}
- void EnqueueMessage(int num_pops, base::OnceClosure on_accept_callback);
+ bool EnqueueMessage(int num_pops,
+ base::OnceClosure on_accept_callback,
+ bool success);
messages::MessageWrapper* GetMessageWrapper();
void TriggerMessageDismissedCallback(messages::DismissReason dismiss_reason);
@@ -98,12 +100,15 @@ messages::MessageWrapper* PopupBlockedMessageDelegateTest::GetMessageWrapper() {
return popup_blocked_message_delegate_->message_for_testing();
}
-void PopupBlockedMessageDelegateTest::EnqueueMessage(
+bool PopupBlockedMessageDelegateTest::EnqueueMessage(
int num_pops,
- base::OnceClosure on_accept_callback) {
- EXPECT_CALL(message_dispatcher_bridge_, EnqueueMessage).Times(1);
- GetDelegate()->ShowMessage(num_pops, settings_map(), GetResourceIdMapper(),
- std::move(on_accept_callback));
+ base::OnceClosure on_accept_callback,
+ bool success) {
+ EXPECT_CALL(message_dispatcher_bridge_, EnqueueMessage)
+ .WillOnce(testing::Return(success));
+ return GetDelegate()->ShowMessage(num_pops, settings_map(),
+ GetResourceIdMapper(),
+ std::move(on_accept_callback));
}
void PopupBlockedMessageDelegateTest::TriggerActionClick() {
@@ -121,7 +126,7 @@ void PopupBlockedMessageDelegateTest::TriggerMessageDismissedCallback(
// set correctly.
TEST_F(PopupBlockedMessageDelegateTest, MessagePropertyValues) {
int num_popups = 3;
- EnqueueMessage(num_popups, base::NullCallback());
+ EnqueueMessage(num_popups, base::NullCallback(), true);
EXPECT_EQ(l10n_util::GetPluralStringFUTF16(IDS_POPUPS_BLOCKED_INFOBAR_TEXT,
num_popups),
GetMessageWrapper()->GetTitle());
@@ -141,8 +146,12 @@ TEST_F(PopupBlockedMessageDelegateTest, MessagePropertyValues) {
// is already on the screen.
TEST_F(PopupBlockedMessageDelegateTest, ShowsBlockedPopups) {
bool on_accept_called = false;
- EnqueueMessage(1, base::BindLambdaForTesting(
- [&on_accept_called] { on_accept_called = true; }));
+ bool result =
+ EnqueueMessage(1, base::BindLambdaForTesting([&on_accept_called] {
+ on_accept_called = true;
+ }),
+ true);
+ EXPECT_TRUE(result);
TriggerActionClick();
EXPECT_TRUE(on_accept_called);
TriggerMessageDismissedCallback(messages::DismissReason::UNKNOWN);
@@ -151,4 +160,17 @@ TEST_F(PopupBlockedMessageDelegateTest, ShowsBlockedPopups) {
CONTENT_SETTING_ALLOW);
}
+// Tests that title updated when another popup is blocked and a message
+// is already on the screen.
+TEST_F(PopupBlockedMessageDelegateTest, FailToShowMessage) {
+ bool on_accept_called = false;
+ bool result =
+ EnqueueMessage(1, base::BindLambdaForTesting([&on_accept_called] {
+ on_accept_called = true;
+ }),
+ false);
+ EXPECT_FALSE(result);
+ EXPECT_FALSE(on_accept_called);
+}
+
} // namespace blocked_content
diff --git a/chromium/components/blocked_content/popup_blocker_tab_helper.cc b/chromium/components/blocked_content/popup_blocker_tab_helper.cc
index 38afcf6eea8..1570f7e488d 100644
--- a/chromium/components/blocked_content/popup_blocker_tab_helper.cc
+++ b/chromium/components/blocked_content/popup_blocker_tab_helper.cc
@@ -122,7 +122,7 @@ void PopupBlockerTabHelper::ShowBlockedPopup(
BlockedRequest* popup = it->second.get();
- base::Optional<WindowOpenDisposition> updated_disposition;
+ absl::optional<WindowOpenDisposition> updated_disposition;
if (disposition != WindowOpenDisposition::CURRENT_TAB)
updated_disposition = disposition;
diff --git a/chromium/components/blocked_content/popup_navigation_delegate.h b/chromium/components/blocked_content/popup_navigation_delegate.h
index 8c7cb02e33b..d3d51831afa 100644
--- a/chromium/components/blocked_content/popup_navigation_delegate.h
+++ b/chromium/components/blocked_content/popup_navigation_delegate.h
@@ -5,9 +5,7 @@
#ifndef COMPONENTS_BLOCKED_CONTENT_POPUP_NAVIGATION_DELEGATE_H_
#define COMPONENTS_BLOCKED_CONTENT_POPUP_NAVIGATION_DELEGATE_H_
-#include <memory>
-
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/window_features/window_features.mojom-forward.h"
#include "ui/base/window_open_disposition.h"
@@ -43,7 +41,7 @@ class PopupNavigationDelegate {
};
virtual NavigateResult NavigateWithGesture(
const blink::mojom::WindowFeatures& window_features,
- base::Optional<WindowOpenDisposition> updated_disposition) = 0;
+ absl::optional<WindowOpenDisposition> updated_disposition) = 0;
// Called when the navigation represented by this class was blocked.
virtual void OnPopupBlocked(content::WebContents* web_contents,
diff --git a/chromium/components/blocked_content/popup_opener_tab_helper.h b/chromium/components/blocked_content/popup_opener_tab_helper.h
index 2bd8b065fdf..3f8404ad339 100644
--- a/chromium/components/blocked_content/popup_opener_tab_helper.h
+++ b/chromium/components/blocked_content/popup_opener_tab_helper.h
@@ -8,12 +8,12 @@
#include <memory>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class TickClock;
@@ -73,7 +73,7 @@ class PopupOpenerTabHelper
// Visible time for this tab until a tab-under is detected. At which point it
// gets the visible time from the |visibility_tracker_|. Will be unset until a
// tab-under is detected.
- base::Optional<base::TimeDelta> visible_time_before_tab_under_;
+ absl::optional<base::TimeDelta> visible_time_before_tab_under_;
// The clock which is used by the visibility trackers.
const base::TickClock* tick_clock_;
diff --git a/chromium/components/blocked_content/popup_tracker.h b/chromium/components/blocked_content/popup_tracker.h
index 2321b3baa9f..182a2fa5cd7 100644
--- a/chromium/components/blocked_content/popup_tracker.h
+++ b/chromium/components/blocked_content/popup_tracker.h
@@ -6,7 +6,6 @@
#define COMPONENTS_BLOCKED_CONTENT_POPUP_TRACKER_H_
#include "base/macros.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer.h"
@@ -14,6 +13,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/scoped_visibility_tracker.h"
#include "ui/base/window_open_disposition.h"
@@ -74,10 +74,10 @@ class PopupTracker : public content::WebContentsObserver,
// Will be unset until the first navigation commits. Will be set to the total
// time the contents was visible at commit time.
- base::Optional<base::TimeDelta> first_load_visible_time_start_;
+ absl::optional<base::TimeDelta> first_load_visible_time_start_;
// Will be unset until the second navigation commits. Is the total time the
// contents is visible while the first document is loading (after commit).
- base::Optional<base::TimeDelta> first_load_visible_time_;
+ absl::optional<base::TimeDelta> first_load_visible_time_;
ui::ScopedVisibilityTracker visibility_tracker_;
diff --git a/chromium/components/blocked_content/pref_names.h b/chromium/components/blocked_content/pref_names.h
index 9d6050c92f6..37016998dc7 100644
--- a/chromium/components/blocked_content/pref_names.h
+++ b/chromium/components/blocked_content/pref_names.h
@@ -13,4 +13,4 @@ extern const char kAbusiveExperienceInterventionEnforce[];
} // namespace prefs
} // namespace blocked_content
-#endif // COMPONENTS_BLOCKED_CONTENT_PREF_NAMES_H
+#endif // COMPONENTS_BLOCKED_CONTENT_PREF_NAMES_H_
diff --git a/chromium/components/blocked_content/safe_browsing_triggered_popup_blocker.cc b/chromium/components/blocked_content/safe_browsing_triggered_popup_blocker.cc
index e03f8d3228c..52195435463 100644
--- a/chromium/components/blocked_content/safe_browsing_triggered_popup_blocker.cc
+++ b/chromium/components/blocked_content/safe_browsing_triggered_popup_blocker.cc
@@ -108,7 +108,7 @@ void SafeBrowsingTriggeredPopupBlocker::DidFinishNavigation(
if (!navigation_handle->IsInMainFrame())
return;
- base::Optional<SubresourceFilterLevel> level;
+ absl::optional<SubresourceFilterLevel> level;
level_for_next_committed_navigation_.swap(level);
// Only care about main frame navigations that commit.
@@ -160,7 +160,7 @@ void SafeBrowsingTriggeredPopupBlocker::OnSafeBrowsingChecksComplete(
const subresource_filter::SubresourceFilterSafeBrowsingClient::CheckResult&
result) {
DCHECK(navigation_handle->IsInMainFrame());
- base::Optional<safe_browsing::SubresourceFilterLevel> match_level;
+ absl::optional<safe_browsing::SubresourceFilterLevel> match_level;
if (result.threat_type ==
safe_browsing::SBThreatType::SB_THREAT_TYPE_SUBRESOURCE_FILTER) {
auto abusive = result.threat_metadata.subresource_filter_match.find(
diff --git a/chromium/components/blocked_content/safe_browsing_triggered_popup_blocker.h b/chromium/components/blocked_content/safe_browsing_triggered_popup_blocker.h
index 7a7bdb0f5bd..c7ef0edef4a 100644
--- a/chromium/components/blocked_content/safe_browsing_triggered_popup_blocker.h
+++ b/chromium/components/blocked_content/safe_browsing_triggered_popup_blocker.h
@@ -9,12 +9,12 @@
#include "base/feature_list.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "components/safe_browsing/core/db/util.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h"
#include "content/public/browser/web_contents_observer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class WebContents;
@@ -132,7 +132,7 @@ class SafeBrowsingTriggeredPopupBlocker
// Whether the next main frame navigation that commits should trigger the
// stronger popup blocker in enforce or warn mode.
- base::Optional<safe_browsing::SubresourceFilterLevel>
+ absl::optional<safe_browsing::SubresourceFilterLevel>
level_for_next_committed_navigation_;
// Should never be nullptr.
diff --git a/chromium/components/blocked_content_strings.grdp b/chromium/components/blocked_content_strings.grdp
index 799db71bd0c..d6b469cf70a 100644
--- a/chromium/components/blocked_content_strings.grdp
+++ b/chromium/components/blocked_content_strings.grdp
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
<if expr="is_android">
- <message name="IDS_POPUPS_BLOCKED_INFOBAR_BUTTON_SHOW" desc="Pop-up Blocking Show Button [CHAR-LIMIT=32]">
+ <message name="IDS_POPUPS_BLOCKED_INFOBAR_BUTTON_SHOW" desc="Pop-up Blocking Show Button [CHAR_LIMIT=32]">
Always show
</message>
- <message name="IDS_POPUPS_BLOCKED_INFOBAR_TEXT" desc="Pop-up Blocking Title [CHAR-LIMIT=32] [ICU Syntax]">
+ <message name="IDS_POPUPS_BLOCKED_INFOBAR_TEXT" desc="Pop-up Blocking Title [CHAR_LIMIT=32] [ICU Syntax]">
{NUM_POPUPS,plural,=1{Pop-up blocked} other{# pop-ups blocked}}
</message>
</if>
diff --git a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist.cc b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist.cc
index 0aa180dd92b..ee456cc7a46 100644
--- a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist.cc
+++ b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist.cc
@@ -7,12 +7,11 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram.h"
-#include "base/optional.h"
-#include "base/strings/stringprintf.h"
#include "base/time/clock.h"
#include "components/blocklist/opt_out_blocklist/opt_out_blocklist_delegate.h"
#include "components/blocklist/opt_out_blocklist/opt_out_blocklist_item.h"
#include "components/blocklist/opt_out_blocklist/opt_out_store.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace blocklist {
diff --git a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist.h b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist.h
index ece381483fe..822ad6dc68a 100644
--- a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist.h
+++ b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist.h
@@ -16,10 +16,10 @@
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "components/blocklist/opt_out_blocklist/opt_out_blocklist_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class Clock;
diff --git a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_data.cc b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_data.cc
index 711e409fd42..67a0d049bad 100644
--- a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_data.cc
+++ b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_data.cc
@@ -139,10 +139,10 @@ BlocklistReason BlocklistData::IsAllowed(
void BlocklistData::EvictOldestHost() {
DCHECK_LT(max_hosts_, block_list_item_host_map_.size());
- base::Optional<base::Time> oldest_opt_out;
+ absl::optional<base::Time> oldest_opt_out;
std::string key_to_delete;
for (auto& item : block_list_item_host_map_) {
- base::Optional<base::Time> most_recent_opt_out =
+ absl::optional<base::Time> most_recent_opt_out =
item.second.most_recent_opt_out_time();
if (!most_recent_opt_out) {
// If there is no opt out time, this is a good choice to evict.
diff --git a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_data.h b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_data.h
index 659d1e26c74..f07b089b8af 100644
--- a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_data.h
+++ b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_data.h
@@ -13,9 +13,9 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/blocklist/opt_out_blocklist/opt_out_blocklist_item.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace blocklist {
diff --git a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_item.h b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_item.h
index 1ad6c01c1e5..158260d6fb2 100644
--- a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_item.h
+++ b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_item.h
@@ -10,12 +10,11 @@
#include <map>
#include <memory>
#include <queue>
-#include <string>
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace blocklist {
@@ -39,7 +38,7 @@ class OptOutBlocklistItem {
// Whether the action corresponding to |this| should be disallowed.
bool IsBlockListed(base::Time now) const;
- base::Optional<base::Time> most_recent_opt_out_time() const {
+ absl::optional<base::Time> most_recent_opt_out_time() const {
return most_recent_opt_out_time_;
}
@@ -86,7 +85,7 @@ class OptOutBlocklistItem {
std::priority_queue<OptOutRecord> opt_out_records_;
// Time of the most recent opt out.
- base::Optional<base::Time> most_recent_opt_out_time_;
+ absl::optional<base::Time> most_recent_opt_out_time_;
// The total number of opt outs currently in |opt_out_records_|.
int total_opt_out_;
diff --git a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_item_unittest.cc b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_item_unittest.cc
index c54bc22dfea..68d495c1265 100644
--- a/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_item_unittest.cc
+++ b/chromium/components/blocklist/opt_out_blocklist/opt_out_blocklist_item_unittest.cc
@@ -6,9 +6,9 @@
#include <memory>
-#include "base/optional.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace {
diff --git a/chromium/components/bookmarks/browser/bookmark_codec_unittest.cc b/chromium/components/bookmarks/browser/bookmark_codec_unittest.cc
index 8346d0f1a74..f2dd8cef742 100644
--- a/chromium/components/bookmarks/browser/bookmark_codec_unittest.cc
+++ b/chromium/components/bookmarks/browser/bookmark_codec_unittest.cc
@@ -28,16 +28,16 @@ using base::ASCIIToUTF16;
namespace bookmarks {
namespace {
-const char kUrl1Title[] = "url1";
+const char16_t kUrl1Title[] = u"url1";
const char kUrl1Url[] = "http://www.url1.com";
-const char kUrl2Title[] = "url2";
+const char16_t kUrl2Title[] = u"url2";
const char kUrl2Url[] = "http://www.url2.com";
-const char kUrl3Title[] = "url3";
+const char16_t kUrl3Title[] = u"url3";
const char kUrl3Url[] = "http://www.url3.com";
-const char kUrl4Title[] = "url4";
+const char16_t kUrl4Title[] = u"url4";
const char kUrl4Url[] = "http://www.url4.com";
-const char kFolder1Title[] = "folder1";
-const char kFolder2Title[] = "folder2";
+const char16_t kFolder1Title[] = u"folder1";
+const char16_t kFolder2Title[] = u"folder2";
const base::FilePath& GetTestDataDir() {
static base::NoDestructor<base::FilePath> dir([]() {
@@ -96,58 +96,49 @@ class BookmarkCodecTest : public testing::Test {
BookmarkModel* CreateTestModel1() {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* bookmark_bar = model->bookmark_bar_node();
- model->AddURL(bookmark_bar, 0, ASCIIToUTF16(kUrl1Title), GURL(kUrl1Url));
+ model->AddURL(bookmark_bar, 0, kUrl1Title, GURL(kUrl1Url));
return model.release();
}
BookmarkModel* CreateTestModel2() {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* bookmark_bar = model->bookmark_bar_node();
- model->AddURL(bookmark_bar, 0, ASCIIToUTF16(kUrl1Title), GURL(kUrl1Url));
- model->AddURL(bookmark_bar, 1, ASCIIToUTF16(kUrl2Title), GURL(kUrl2Url));
+ model->AddURL(bookmark_bar, 0, kUrl1Title, GURL(kUrl1Url));
+ model->AddURL(bookmark_bar, 1, kUrl2Title, GURL(kUrl2Url));
return model.release();
}
BookmarkModel* CreateTestModel3() {
std::unique_ptr<BookmarkModel> model(TestBookmarkClient::CreateModel());
const BookmarkNode* bookmark_bar = model->bookmark_bar_node();
- model->AddURL(bookmark_bar, 0, ASCIIToUTF16(kUrl1Title), GURL(kUrl1Url));
+ model->AddURL(bookmark_bar, 0, kUrl1Title, GURL(kUrl1Url));
const BookmarkNode* folder1 =
- model->AddFolder(bookmark_bar, 1, ASCIIToUTF16(kFolder1Title));
- model->AddURL(folder1, 0, ASCIIToUTF16(kUrl2Title), GURL(kUrl2Url));
+ model->AddFolder(bookmark_bar, 1, kFolder1Title);
+ model->AddURL(folder1, 0, kUrl2Title, GURL(kUrl2Url));
return model.release();
}
void GetBookmarksBarChildValue(base::Value* value,
size_t index,
- base::DictionaryValue** result_value) {
- ASSERT_EQ(base::Value::Type::DICTIONARY, value->type());
-
- base::DictionaryValue* d_value = nullptr;
- value->GetAsDictionary(&d_value);
- base::Value* roots;
- ASSERT_TRUE(d_value->Get(BookmarkCodec::kRootsKey, &roots));
- ASSERT_EQ(base::Value::Type::DICTIONARY, roots->type());
-
- base::DictionaryValue* roots_d_value = nullptr;
- roots->GetAsDictionary(&roots_d_value);
- base::Value* bb_value;
- ASSERT_TRUE(
- roots_d_value->Get(BookmarkCodec::kRootFolderNameKey, &bb_value));
- ASSERT_EQ(base::Value::Type::DICTIONARY, bb_value->type());
-
- base::DictionaryValue* bb_d_value = nullptr;
- bb_value->GetAsDictionary(&bb_d_value);
- base::Value* bb_children_value;
- ASSERT_TRUE(
- bb_d_value->Get(BookmarkCodec::kChildrenKey, &bb_children_value));
- ASSERT_EQ(base::Value::Type::LIST, bb_children_value->type());
-
- base::ListValue* bb_children_l_value = nullptr;
- bb_children_value->GetAsList(&bb_children_l_value);
- base::Value* child_value;
- ASSERT_TRUE(bb_children_l_value->Get(index, &child_value));
- ASSERT_EQ(base::Value::Type::DICTIONARY, child_value->type());
-
- child_value->GetAsDictionary(result_value);
+ base::Value** result_value) {
+ ASSERT_TRUE(value->is_dict());
+
+ base::Value* roots = value->FindDictKey(BookmarkCodec::kRootsKey);
+ ASSERT_TRUE(roots);
+
+ base::Value* bb_value =
+ roots->FindDictKey(BookmarkCodec::kRootFolderNameKey);
+ ASSERT_TRUE(bb_value);
+
+ base::Value* bb_children_value =
+ bb_value->FindListKey(BookmarkCodec::kChildrenKey);
+ ASSERT_TRUE(bb_children_value);
+
+ base::Value::ListView bb_children_l_value = bb_children_value->GetList();
+ ASSERT_LT(index, bb_children_l_value.size());
+
+ base::Value& child_value = bb_children_l_value[index];
+ ASSERT_TRUE(child_value.is_dict());
+
+ *result_value = &child_value;
}
std::unique_ptr<base::Value> EncodeHelper(
@@ -283,11 +274,12 @@ TEST_F(BookmarkCodecTest, ChecksumManualEditTest) {
EXPECT_TRUE(value.get() != nullptr);
// Change something in the encoded value before decoding it.
- base::DictionaryValue* child1_value;
+ base::Value* child1_value = nullptr;
GetBookmarksBarChildValue(value.get(), 0, &child1_value);
- std::string title;
- ASSERT_TRUE(child1_value->GetString(BookmarkCodec::kNameKey, &title));
- child1_value->SetString(BookmarkCodec::kNameKey, title + "1");
+ std::string* title = child1_value->FindStringKey(BookmarkCodec::kNameKey);
+ ASSERT_TRUE(title);
+ std::string original_title = *title;
+ child1_value->SetStringKey(BookmarkCodec::kNameKey, original_title + "1");
std::string dec_checksum;
std::unique_ptr<BookmarkModel> decoded_model1 =
@@ -295,7 +287,7 @@ TEST_F(BookmarkCodecTest, ChecksumManualEditTest) {
/*sync_metadata_str=*/nullptr);
// Undo the change and make sure the checksum is same as original.
- child1_value->SetString(BookmarkCodec::kNameKey, title);
+ child1_value->SetStringKey(BookmarkCodec::kNameKey, original_title);
std::unique_ptr<BookmarkModel> decoded_model2 =
DecodeHelper(*value.get(), enc_checksum, &dec_checksum, false,
/*sync_metadata_str=*/nullptr);
@@ -318,12 +310,12 @@ TEST_F(BookmarkCodecTest, ChecksumManualEditIDsTest) {
EXPECT_TRUE(value.get() != nullptr);
// Change IDs for all children of bookmark bar to be 1.
- base::DictionaryValue* child_value;
+ base::Value* child_value = nullptr;
for (size_t i = 0; i < bb_child_count; ++i) {
GetBookmarksBarChildValue(value.get(), i, &child_value);
- std::string id;
- ASSERT_TRUE(child_value->GetString(BookmarkCodec::kIdKey, &id));
- child_value->SetString(BookmarkCodec::kIdKey, "1");
+ std::string* id = child_value->FindStringKey(BookmarkCodec::kIdKey);
+ ASSERT_TRUE(id);
+ child_value->SetStringKey(BookmarkCodec::kIdKey, "1");
}
std::string dec_checksum;
@@ -359,12 +351,10 @@ TEST_F(BookmarkCodecTest, PersistIDsTest) {
// ID persistence is working properly.
const BookmarkNode* bookmark_bar = decoded_model->bookmark_bar_node();
decoded_model->AddURL(bookmark_bar, bookmark_bar->children().size(),
- ASCIIToUTF16(kUrl3Title), GURL(kUrl3Url));
- const BookmarkNode* folder2_node =
- decoded_model->AddFolder(bookmark_bar, bookmark_bar->children().size(),
- ASCIIToUTF16(kFolder2Title));
- decoded_model->AddURL(
- folder2_node, 0, ASCIIToUTF16(kUrl4Title), GURL(kUrl4Url));
+ kUrl3Title, GURL(kUrl3Url));
+ const BookmarkNode* folder2_node = decoded_model->AddFolder(
+ bookmark_bar, bookmark_bar->children().size(), kFolder2Title);
+ decoded_model->AddURL(folder2_node, 0, kUrl4Title, GURL(kUrl4Url));
BookmarkCodec encoder2;
std::unique_ptr<base::Value> model_value2(
@@ -536,11 +526,12 @@ TEST_F(BookmarkCodecTest, ReassignEmptyGUID) {
EXPECT_FALSE(decoder1.guids_reassigned());
// Change GUID of child to be empty.
- base::DictionaryValue* child_value;
+ base::Value* child_value = nullptr;
GetBookmarksBarChildValue(value.get(), 0, &child_value);
- std::string guid_str;
- ASSERT_TRUE(child_value->GetString(BookmarkCodec::kGuidKey, &guid_str));
- child_value->SetString(BookmarkCodec::kGuidKey, "");
+ std::string* guid_str = child_value->FindStringKey(BookmarkCodec::kGuidKey);
+ ASSERT_TRUE(guid_str);
+ std::string original_guid_str = *guid_str;
+ child_value->SetStringKey(BookmarkCodec::kGuidKey, "");
std::unique_ptr<BookmarkModel> decoded_model2(
TestBookmarkClient::CreateModel());
@@ -548,7 +539,7 @@ TEST_F(BookmarkCodecTest, ReassignEmptyGUID) {
ASSERT_TRUE(Decode(&decoder2, *value.get(), decoded_model2.get(),
/*sync_metadata_str=*/nullptr));
- const base::GUID guid = base::GUID::ParseCaseInsensitive(guid_str);
+ const base::GUID guid = base::GUID::ParseCaseInsensitive(original_guid_str);
ASSERT_TRUE(guid.is_valid());
EXPECT_NE(guid, decoded_model2->bookmark_bar_node()->children()[0]->guid());
EXPECT_TRUE(
@@ -574,11 +565,12 @@ TEST_F(BookmarkCodecTest, ReassignMissingGUID) {
EXPECT_FALSE(decoder1.guids_reassigned());
// Change GUID of child to be missing.
- base::DictionaryValue* child_value;
+ base::Value* child_value = nullptr;
GetBookmarksBarChildValue(value.get(), 0, &child_value);
- std::string guid_str;
- ASSERT_TRUE(child_value->GetString(BookmarkCodec::kGuidKey, &guid_str));
- child_value->Remove(BookmarkCodec::kGuidKey, nullptr);
+ std::string* guid_str = child_value->FindStringKey(BookmarkCodec::kGuidKey);
+ ASSERT_TRUE(guid_str);
+ std::string original_guid_str = *guid_str;
+ child_value->RemoveKey(BookmarkCodec::kGuidKey);
std::unique_ptr<BookmarkModel> decoded_model2(
TestBookmarkClient::CreateModel());
@@ -586,7 +578,7 @@ TEST_F(BookmarkCodecTest, ReassignMissingGUID) {
ASSERT_TRUE(Decode(&decoder2, *value.get(), decoded_model2.get(),
/*sync_metadata_str=*/nullptr));
- const base::GUID guid = base::GUID::ParseCaseInsensitive(guid_str);
+ const base::GUID guid = base::GUID::ParseCaseInsensitive(original_guid_str);
ASSERT_TRUE(guid.is_valid());
EXPECT_NE(guid, decoded_model2->bookmark_bar_node()->children()[0]->guid());
EXPECT_TRUE(
@@ -607,13 +599,13 @@ TEST_F(BookmarkCodecTest, ReassignInvalidGUID) {
EXPECT_TRUE(value.get() != nullptr);
// Change GUID of child to be invalid.
- base::DictionaryValue* child_value;
+ base::Value* child_value = nullptr;
GetBookmarksBarChildValue(value.get(), 0, &child_value);
- child_value->SetString(BookmarkCodec::kGuidKey, kInvalidGuid);
+ child_value->SetStringKey(BookmarkCodec::kGuidKey, kInvalidGuid);
- std::string guid;
- ASSERT_TRUE(child_value->GetString(BookmarkCodec::kGuidKey, &guid));
- ASSERT_EQ(guid, kInvalidGuid);
+ std::string* guid = child_value->FindStringKey(BookmarkCodec::kGuidKey);
+ ASSERT_TRUE(guid);
+ ASSERT_EQ(*guid, kInvalidGuid);
std::unique_ptr<BookmarkModel> decoded_model(
TestBookmarkClient::CreateModel());
@@ -634,21 +626,23 @@ TEST_F(BookmarkCodecTest, ReassignDuplicateGUID) {
EXPECT_TRUE(value.get() != nullptr);
- base::DictionaryValue* child1_value;
+ base::Value* child1_value = nullptr;
GetBookmarksBarChildValue(value.get(), 0, &child1_value);
- std::string child1_guid;
- ASSERT_TRUE(child1_value->GetString(BookmarkCodec::kGuidKey, &child1_guid));
+ std::string* child1_guid =
+ child1_value->FindStringKey(BookmarkCodec::kGuidKey);
+ ASSERT_TRUE(child1_guid);
- base::DictionaryValue* child2_value;
+ base::Value* child2_value = nullptr;
GetBookmarksBarChildValue(value.get(), 1, &child2_value);
// Change GUID of child to be duplicate.
- child2_value->SetString(BookmarkCodec::kGuidKey, child1_guid);
+ child2_value->SetStringKey(BookmarkCodec::kGuidKey, *child1_guid);
- std::string child2_guid;
- ASSERT_TRUE(child2_value->GetString(BookmarkCodec::kGuidKey, &child2_guid));
- ASSERT_EQ(child1_guid, child2_guid);
+ std::string* child2_guid =
+ child2_value->FindStringKey(BookmarkCodec::kGuidKey);
+ ASSERT_TRUE(child2_guid);
+ ASSERT_EQ(*child1_guid, *child2_guid);
std::unique_ptr<BookmarkModel> decoded_model(
TestBookmarkClient::CreateModel());
@@ -669,15 +663,16 @@ TEST_F(BookmarkCodecTest, ReassignPermanentNodeDuplicateGUID) {
EXPECT_TRUE(value.get() != nullptr);
- base::DictionaryValue* child_value;
+ base::Value* child_value = nullptr;
GetBookmarksBarChildValue(value.get(), 0, &child_value);
// Change GUID of child to be the root node GUID.
- child_value->SetString(BookmarkCodec::kGuidKey, BookmarkNode::kRootNodeGuid);
+ child_value->SetStringKey(BookmarkCodec::kGuidKey,
+ BookmarkNode::kRootNodeGuid);
- std::string child_guid;
- ASSERT_TRUE(child_value->GetString(BookmarkCodec::kGuidKey, &child_guid));
- ASSERT_EQ(BookmarkNode::kRootNodeGuid, child_guid);
+ std::string* child_guid = child_value->FindStringKey(BookmarkCodec::kGuidKey);
+ ASSERT_TRUE(child_guid);
+ ASSERT_EQ(BookmarkNode::kRootNodeGuid, *child_guid);
std::unique_ptr<BookmarkModel> decoded_model(
TestBookmarkClient::CreateModel());
@@ -701,9 +696,9 @@ TEST_F(BookmarkCodecTest, CanonicalizeGUID) {
// Change a GUID to a capitalized form, which could have been produced by an
// older version of the browser, before canonicalization was enforced.
- base::DictionaryValue* child_value;
+ base::Value* child_value = nullptr;
GetBookmarksBarChildValue(value.get(), 0, &child_value);
- child_value->SetString(BookmarkCodec::kGuidKey, kUpperCaseGuid);
+ child_value->SetStringKey(BookmarkCodec::kGuidKey, kUpperCaseGuid);
std::unique_ptr<BookmarkModel> decoded_model2(
TestBookmarkClient::CreateModel());
diff --git a/chromium/components/bookmarks/browser/bookmark_expanded_state_tracker.cc b/chromium/components/bookmarks/browser/bookmark_expanded_state_tracker.cc
index 4ad2afa1f50..c879fc39746 100644
--- a/chromium/components/bookmarks/browser/bookmark_expanded_state_tracker.cc
+++ b/chromium/components/bookmarks/browser/bookmark_expanded_state_tracker.cc
@@ -48,11 +48,11 @@ BookmarkExpandedStateTracker::GetExpandedNodes() {
return nodes;
bool changed = false;
- for (auto i = value->begin(); i != value->end(); ++i) {
+ for (const auto& entry : value->GetList()) {
std::string value;
int64_t node_id;
const BookmarkNode* node;
- if (i->GetAsString(&value) && base::StringToInt64(value, &node_id) &&
+ if (entry.GetAsString(&value) && base::StringToInt64(value, &node_id) &&
(node = GetBookmarkNodeByID(bookmark_model_, node_id)) != nullptr &&
node->is_folder()) {
nodes.insert(node);
diff --git a/chromium/components/bookmarks/browser/bookmark_model.cc b/chromium/components/bookmarks/browser/bookmark_model.cc
index 8b44e07cda4..6c254cdd3f1 100644
--- a/chromium/components/bookmarks/browser/bookmark_model.cc
+++ b/chromium/components/bookmarks/browser/bookmark_model.cc
@@ -237,6 +237,7 @@ void BookmarkModel::Remove(const BookmarkNode* node) {
void BookmarkModel::RemoveAllUserBookmarks() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(loaded_);
std::set<GURL> removed_urls;
struct RemoveNodeData {
const BookmarkNode* parent;
@@ -579,7 +580,7 @@ const BookmarkNode* BookmarkModel::AddFolder(
size_t index,
const std::u16string& title,
const BookmarkNode::MetaInfoMap* meta_info,
- base::Optional<base::GUID> guid) {
+ absl::optional<base::GUID> guid) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(loaded_);
DCHECK(parent);
@@ -606,8 +607,8 @@ const BookmarkNode* BookmarkModel::AddURL(
const std::u16string& title,
const GURL& url,
const BookmarkNode::MetaInfoMap* meta_info,
- base::Optional<base::Time> creation_time,
- base::Optional<base::GUID> guid) {
+ absl::optional<base::Time> creation_time,
+ absl::optional<base::GUID> guid) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(loaded_);
DCHECK(url.is_valid());
diff --git a/chromium/components/bookmarks/browser/bookmark_model.h b/chromium/components/bookmarks/browser/bookmark_model.h
index 33c7167f6d7..2aa13d86486 100644
--- a/chromium/components/bookmarks/browser/bookmark_model.h
+++ b/chromium/components/bookmarks/browser/bookmark_model.h
@@ -211,7 +211,7 @@ class BookmarkModel : public BookmarkUndoProvider,
size_t index,
const std::u16string& title,
const BookmarkNode::MetaInfoMap* meta_info = nullptr,
- base::Optional<base::GUID> guid = base::nullopt);
+ absl::optional<base::GUID> guid = absl::nullopt);
// Adds a url at the specified position with the given |creation_time|,
// |meta_info| and |guid|. If no GUID is provided (i.e. nullopt), then a
@@ -222,8 +222,8 @@ class BookmarkModel : public BookmarkUndoProvider,
const std::u16string& title,
const GURL& url,
const BookmarkNode::MetaInfoMap* meta_info = nullptr,
- base::Optional<base::Time> creation_time = base::nullopt,
- base::Optional<base::GUID> guid = base::nullopt);
+ absl::optional<base::Time> creation_time = absl::nullopt,
+ absl::optional<base::GUID> guid = absl::nullopt);
// Sorts the children of |parent|, notifying observers by way of the
// BookmarkNodeChildrenReordered method.
diff --git a/chromium/components/bookmarks/browser/bookmark_node_data_unittest.cc b/chromium/components/bookmarks/browser/bookmark_node_data_unittest.cc
index bab2e3c28f8..ee93dd59436 100644
--- a/chromium/components/bookmarks/browser/bookmark_node_data_unittest.cc
+++ b/chromium/components/bookmarks/browser/bookmark_node_data_unittest.cc
@@ -355,7 +355,15 @@ TEST_F(BookmarkNodeDataTest, MAYBE_WriteToClipboardEmptyFolder) {
EXPECT_EQ(u"g1", clipboard_result);
}
-TEST_F(BookmarkNodeDataTest, WriteToClipboardFolderWithChildren) {
+// Test is flaky on LaCrOS: crbug.com/1010353
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#define MAYBE_WriteToClipboardFolderWithChildren \
+ DISABLED_WriteToClipboardFolderWithChildren
+#else
+#define MAYBE_WriteToClipboardFolderWithChildren \
+ WriteToClipboardFolderWithChildren
+#endif
+TEST_F(BookmarkNodeDataTest, MAYBE_WriteToClipboardFolderWithChildren) {
BookmarkNodeData data;
const BookmarkNode* root = model()->bookmark_bar_node();
const BookmarkNode* folder = model()->AddFolder(root, 0, u"g1");
diff --git a/chromium/components/bookmarks/browser/bookmark_storage.h b/chromium/components/bookmarks/browser/bookmark_storage.h
index d4657d366cf..ac2b55aa7ca 100644
--- a/chromium/components/bookmarks/browser/bookmark_storage.h
+++ b/chromium/components/bookmarks/browser/bookmark_storage.h
@@ -7,10 +7,6 @@
#include <stdint.h>
-#include <memory>
-#include <string>
-#include <vector>
-
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/files/important_file_writer.h"
diff --git a/chromium/components/bookmarks/browser/bookmark_utils_unittest.cc b/chromium/components/bookmarks/browser/bookmark_utils_unittest.cc
index 7d27eccb4cc..56ac5aae70e 100644
--- a/chromium/components/bookmarks/browser/bookmark_utils_unittest.cc
+++ b/chromium/components/bookmarks/browser/bookmark_utils_unittest.cc
@@ -276,7 +276,7 @@ TEST_F(BookmarkUtilsTest, DISABLED_PasteBookmarkFromURL) {
}
// TODO(https://crbug.com/1010182): Fix flakes and re-enable this test.
-#if defined(OS_WIN) || defined(OS_APPLE)
+#if defined(OS_WIN) || defined(OS_MAC)
#define MAYBE_CopyPaste DISABLED_CopyPaste
#else
#define MAYBE_CopyPaste CopyPaste
@@ -372,7 +372,7 @@ TEST_F(BookmarkUtilsTest, DISABLED_CopyPasteMetaInfo) {
EXPECT_EQ("someothervalue", value);
}
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_APPLE)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_MAC)
// http://crbug.com/396472
#define MAYBE_CutToClipboard DISABLED_CutToClipboard
#else
diff --git a/chromium/components/bookmarks/browser/titled_url_index.cc b/chromium/components/bookmarks/browser/titled_url_index.cc
index 3ecffe6393c..f4e9a8b3e35 100644
--- a/chromium/components/bookmarks/browser/titled_url_index.cc
+++ b/chromium/components/bookmarks/browser/titled_url_index.cc
@@ -106,7 +106,7 @@ std::vector<TitledUrlMatch> TitledUrlIndex::GetResultsMatching(
std::vector<TitledUrlMatch> results;
for (TitledUrlNodes::const_iterator i = sorted_nodes.begin();
i != sorted_nodes.end() && results.size() < max_count; ++i) {
- base::Optional<TitledUrlMatch> match =
+ absl::optional<TitledUrlMatch> match =
MatchTitledUrlNodeWithQuery(*i, query_nodes, match_ancestor_titles);
if (match)
results.push_back(match.value());
@@ -123,12 +123,12 @@ void TitledUrlIndex::SortMatches(const TitledUrlNodeSet& matches,
}
}
-base::Optional<TitledUrlMatch> TitledUrlIndex::MatchTitledUrlNodeWithQuery(
+absl::optional<TitledUrlMatch> TitledUrlIndex::MatchTitledUrlNodeWithQuery(
const TitledUrlNode* node,
const query_parser::QueryNodeVector& query_nodes,
bool match_ancestor_titles) {
if (!node) {
- return base::nullopt;
+ return absl::nullopt;
}
// Check that the result matches the query. The previous search
// was a simple per-word search, while the more complex matching
@@ -162,7 +162,7 @@ base::Optional<TitledUrlMatch> TitledUrlIndex::MatchTitledUrlNodeWithQuery(
query_has_ancestor_matches =
query_has_ancestor_matches || has_ancestor_matches;
if (!has_title_matches && !has_url_matches && !has_ancestor_matches)
- return base::nullopt;
+ return absl::nullopt;
query_parser::QueryParser::SortAndCoalesceMatchPositions(&title_matches);
query_parser::QueryParser::SortAndCoalesceMatchPositions(&url_matches);
}
diff --git a/chromium/components/bookmarks/browser/titled_url_index.h b/chromium/components/bookmarks/browser/titled_url_index.h
index 5348c0c17ff..6420879ddd9 100644
--- a/chromium/components/bookmarks/browser/titled_url_index.h
+++ b/chromium/components/bookmarks/browser/titled_url_index.h
@@ -13,9 +13,9 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/bookmarks/browser/titled_url_node_sorter.h"
#include "components/query_parser/query_parser.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace bookmarks {
@@ -82,7 +82,7 @@ class TitledUrlIndex {
// Finds |query_nodes| matches in |node| and returns a TitledUrlMatch
// containing |node| and the matches.
- base::Optional<TitledUrlMatch> MatchTitledUrlNodeWithQuery(
+ absl::optional<TitledUrlMatch> MatchTitledUrlNodeWithQuery(
const TitledUrlNode* node,
const query_parser::QueryNodeVector& query_nodes,
bool match_ancestor_titles);
diff --git a/chromium/components/bookmarks/browser/titled_url_match.h b/chromium/components/bookmarks/browser/titled_url_match.h
index a700977dd42..685cac05ad7 100644
--- a/chromium/components/bookmarks/browser/titled_url_match.h
+++ b/chromium/components/bookmarks/browser/titled_url_match.h
@@ -7,7 +7,6 @@
#include <stddef.h>
-#include <cstddef>
#include <utility>
#include <vector>
diff --git a/chromium/components/bookmarks/managed/managed_bookmarks_policy_handler.cc b/chromium/components/bookmarks/managed/managed_bookmarks_policy_handler.cc
index 58b808f959e..091113ec5be 100644
--- a/chromium/components/bookmarks/managed/managed_bookmarks_policy_handler.cc
+++ b/chromium/components/bookmarks/managed/managed_bookmarks_policy_handler.cc
@@ -49,7 +49,7 @@ void ManagedBookmarksPolicyHandler::ApplyPolicySettings(
std::string ManagedBookmarksPolicyHandler::GetFolderName(
const base::ListValue& list) {
// Iterate over the list, and try to find the FolderName.
- for (const auto& el : list) {
+ for (const auto& el : list.GetList()) {
const base::DictionaryValue* dict = nullptr;
if (!el.GetAsDictionary(&dict))
continue;
@@ -66,8 +66,8 @@ std::string ManagedBookmarksPolicyHandler::GetFolderName(
void ManagedBookmarksPolicyHandler::FilterBookmarks(base::ListValue* list) {
// Remove any non-conforming values found.
- auto it = list->begin();
- while (it != list->end()) {
+ auto it = list->GetList().begin();
+ while (it != list->GetList().end()) {
base::DictionaryValue* dict = nullptr;
if (!it->GetAsDictionary(&dict)) {
it = list->Erase(it, nullptr);
diff --git a/chromium/components/bookmarks/managed/managed_bookmarks_policy_handler_unittest.cc b/chromium/components/bookmarks/managed/managed_bookmarks_policy_handler_unittest.cc
index 394b68bf7c2..52a64997d31 100644
--- a/chromium/components/bookmarks/managed/managed_bookmarks_policy_handler_unittest.cc
+++ b/chromium/components/bookmarks/managed/managed_bookmarks_policy_handler_unittest.cc
@@ -96,7 +96,7 @@ TEST_F(ManagedBookmarksPolicyHandlerTest, ApplyPolicySettings) {
// Note the protocols and ending slashes added to urls, which were not in the
// value set earlier.
- base::Optional<base::Value> expected = base::JSONReader::Read(R"(
+ absl::optional<base::Value> expected = base::JSONReader::Read(R"(
[
{
"name": "Google",
@@ -162,7 +162,7 @@ TEST_F(ManagedBookmarksPolicyHandlerTest, ApplyPolicySettingsNoTitle) {
// Note the protocol and ending slash added to url, which was not in the value
// set earlier.
- base::Optional<base::Value> expected = base::JSONReader::Read(R"(
+ absl::optional<base::Value> expected = base::JSONReader::Read(R"(
[
{
"name": "Google",
@@ -209,7 +209,7 @@ TEST_F(ManagedBookmarksPolicyHandlerTest, UnknownKeys) {
// Note the protocol and ending slash added to url, which was not in the value
// set earlier.
- base::Optional<base::Value> expected = base::JSONReader::Read(R"(
+ absl::optional<base::Value> expected = base::JSONReader::Read(R"(
[
{
"name": "Google",
diff --git a/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc b/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
index 9d7b69f8450..73ad1cffccb 100644
--- a/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
+++ b/chromium/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
@@ -212,7 +212,8 @@ TEST_F(ManagedBookmarksTrackerTest, SwapNodes) {
// These two nodes should just be swapped.
const BookmarkNode* parent = managed_node();
EXPECT_CALL(observer_, BookmarkNodeMoved(model_.get(), parent, 1, parent, 0));
- prefs_.SetManagedPref(prefs::kManagedBookmarks, updated->CreateDeepCopy());
+ prefs_.SetManagedPref(prefs::kManagedBookmarks,
+ base::Value::ToUniquePtrValue(updated->Clone()));
Mock::VerifyAndClearExpectations(&observer_);
// Verify the final tree.
@@ -231,7 +232,8 @@ TEST_F(ManagedBookmarksTrackerTest, RemoveNode) {
const BookmarkNode* parent = managed_node();
EXPECT_CALL(observer_, BookmarkNodeRemoved(model_.get(), parent, 1, _, _));
- prefs_.SetManagedPref(prefs::kManagedBookmarks, updated->CreateDeepCopy());
+ prefs_.SetManagedPref(prefs::kManagedBookmarks,
+ base::Value::ToUniquePtrValue(updated->Clone()));
Mock::VerifyAndClearExpectations(&observer_);
// Verify the final tree.
@@ -254,7 +256,8 @@ TEST_F(ManagedBookmarksTrackerTest, CreateNewNodes) {
const BookmarkNode* parent = managed_node();
EXPECT_CALL(observer_, BookmarkNodeRemoved(model_.get(), parent, 1, _, _))
.Times(2);
- prefs_.SetManagedPref(prefs::kManagedBookmarks, updated->CreateDeepCopy());
+ prefs_.SetManagedPref(prefs::kManagedBookmarks,
+ base::Value::ToUniquePtrValue(updated->Clone()));
Mock::VerifyAndClearExpectations(&observer_);
// Verify the final tree.
diff --git a/chromium/components/breadcrumbs/DEPS b/chromium/components/breadcrumbs/DEPS
index 5cd0867c848..61e09432742 100644
--- a/chromium/components/breadcrumbs/DEPS
+++ b/chromium/components/breadcrumbs/DEPS
@@ -1,3 +1,4 @@
include_rules = [
"+base",
+ "+components/keyed_service/core",
]
diff --git a/chromium/components/breadcrumbs/core/BUILD.gn b/chromium/components/breadcrumbs/core/BUILD.gn
index f72b09b114a..e2a643afed7 100644
--- a/chromium/components/breadcrumbs/core/BUILD.gn
+++ b/chromium/components/breadcrumbs/core/BUILD.gn
@@ -6,11 +6,56 @@ source_set("core") {
sources = [
"breadcrumb_manager.cc",
"breadcrumb_manager.h",
+ "breadcrumb_manager_keyed_service.cc",
+ "breadcrumb_manager_keyed_service.h",
"breadcrumb_manager_observer.h",
+ "breadcrumb_persistent_storage_manager.cc",
+ "breadcrumb_persistent_storage_manager.h",
"breadcrumb_persistent_storage_util.cc",
"breadcrumb_persistent_storage_util.h",
"crash_reporter_breadcrumb_constants.h",
]
+ deps = [
+ "//base",
+ "//components/keyed_service/core",
+ ]
+}
+
+source_set("feature_flags") {
+ sources = [
+ "features.cc",
+ "features.h",
+ ]
deps = [ "//base" ]
}
+
+source_set("unit_tests") {
+ testonly = true
+ deps = [
+ ":core",
+ ":generate_not_user_triggered_actions",
+ "//base/test:test_support",
+ "//testing/gtest",
+ ]
+
+ sources = [
+ "application_breadcrumbs_not_user_action_unittest.cc",
+ "breadcrumb_manager_keyed_service_unittest.cc",
+ "breadcrumb_manager_observer_unittest.cc",
+ "breadcrumb_manager_unittest.cc",
+ "breadcrumb_persistent_storage_util_unittest.cc",
+ ]
+}
+
+action("generate_not_user_triggered_actions") {
+ script = "generate_not_user_triggered_actions.py"
+ sources = [ "//tools/metrics/actions/actions.xml" ]
+ outputs = [ "$target_gen_dir/application_breadcrumbs_not_user_action.inc" ]
+ args = [
+ "--actions",
+ rebase_path(sources[0], root_build_dir),
+ "--output",
+ rebase_path(outputs[0], root_build_dir),
+ ]
+}
diff --git a/chromium/components/breadcrumbs/core/application_breadcrumbs_not_user_action_unittest.cc b/chromium/components/breadcrumbs/core/application_breadcrumbs_not_user_action_unittest.cc
new file mode 100644
index 00000000000..2486185dfef
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/application_breadcrumbs_not_user_action_unittest.cc
@@ -0,0 +1,45 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/breadcrumbs/core/application_breadcrumbs_not_user_action.inc"
+
+#include <string>
+#include <vector>
+
+#include "testing/platform_test.h"
+
+// Tests that kNotUserTriggeredActions array was correctly generated by
+// generate_not_user_triggered_actions.py
+using ApplicationBreadcrumbsNotUserActions = PlatformTest;
+
+// Tests that kNotUserTriggeredActions array is not too big.
+TEST_F(ApplicationBreadcrumbsNotUserActions, Size) {
+ // At the time of writing this code there were 44 actions. It's better to fail
+ // the test if this list grows to 200 to verify that list is not unreasonably
+ // large.
+ EXPECT_LT(
+ std::end(kNotUserTriggeredActions) - std::begin(kNotUserTriggeredActions),
+ 200);
+}
+
+// Tests that each string in kNotUserTriggeredActions array is not too long but
+// longer than 0.
+TEST_F(ApplicationBreadcrumbsNotUserActions, StringLength) {
+ for (const char* action : kNotUserTriggeredActions) {
+ EXPECT_GT(strlen(action), 0U);
+ // At the time of writing this test the longest action had 54 characters.
+ // Action names longer than 100 characters seem unnecessary long or there
+ // might be a bug in generate_not_user_triggered_actions.py script.
+ EXPECT_LT(strlen(action), 100U) << " for " << action;
+ }
+}
+
+// Tests that kNotUserTriggeredActions array is sorted to make the binary search
+// possible.
+TEST_F(ApplicationBreadcrumbsNotUserActions, Sorting) {
+ // Use vector of strings, so std::is_sorted can compare strings, not pointers.
+ std::vector<std::string> actions(std::begin(kNotUserTriggeredActions),
+ std::end(kNotUserTriggeredActions));
+ EXPECT_TRUE(std::is_sorted(actions.begin(), actions.end()));
+}
diff --git a/chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service.cc b/chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service.cc
new file mode 100644
index 00000000000..cedb58092fa
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service.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/breadcrumbs/core/breadcrumb_manager_keyed_service.h"
+
+#include "base/strings/stringprintf.h"
+#include "components/breadcrumbs/core/breadcrumb_manager.h"
+#include "components/breadcrumbs/core/breadcrumb_persistent_storage_manager.h"
+
+namespace breadcrumbs {
+
+void BreadcrumbManagerKeyedService::AddEvent(const std::string& event) {
+ std::string event_log =
+ base::StringPrintf("%s%s", browsing_mode_.c_str(), event.c_str());
+ breadcrumb_manager_->AddEvent(event_log);
+}
+
+void BreadcrumbManagerKeyedService::AddObserver(
+ BreadcrumbManagerObserver* observer) {
+ breadcrumb_manager_->AddObserver(observer);
+}
+
+void BreadcrumbManagerKeyedService::RemoveObserver(
+ BreadcrumbManagerObserver* observer) {
+ breadcrumb_manager_->RemoveObserver(observer);
+}
+
+size_t BreadcrumbManagerKeyedService::GetEventCount() {
+ return breadcrumb_manager_->GetEventCount();
+}
+
+const std::list<std::string> BreadcrumbManagerKeyedService::GetEvents(
+ size_t event_count_limit) const {
+ return breadcrumb_manager_->GetEvents(event_count_limit);
+}
+
+void BreadcrumbManagerKeyedService::StartPersisting(
+ BreadcrumbPersistentStorageManager* persistent_storage_manager) {
+ DCHECK(persistent_storage_manager);
+
+ if (persistent_storage_manager_) {
+ StopPersisting();
+ }
+
+ persistent_storage_manager_ = persistent_storage_manager;
+ persistent_storage_manager_->MonitorBreadcrumbManagerService(this);
+}
+
+void BreadcrumbManagerKeyedService::StopPersisting() {
+ if (!persistent_storage_manager_) {
+ return;
+ }
+
+ persistent_storage_manager_->StopMonitoringBreadcrumbManagerService(this);
+ persistent_storage_manager_ = nullptr;
+}
+
+BreadcrumbPersistentStorageManager*
+BreadcrumbManagerKeyedService::GetPersistentStorageManager() {
+ return persistent_storage_manager_;
+}
+
+BreadcrumbManagerKeyedService::BreadcrumbManagerKeyedService(
+ bool is_off_the_record)
+ // Set "I" for Incognito (Chrome branded OffTheRecord implementation) and
+ // empty string for Normal browsing mode.
+ : browsing_mode_(is_off_the_record ? "I " : ""),
+ breadcrumb_manager_(std::make_unique<BreadcrumbManager>()) {}
+
+BreadcrumbManagerKeyedService::~BreadcrumbManagerKeyedService() = default;
+
+} // namespace breadcrumbs
diff --git a/chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service.h b/chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service.h
new file mode 100644
index 00000000000..892192b6f83
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service.h
@@ -0,0 +1,79 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_BREADCRUMBS_CORE_BREADCRUMB_MANAGER_KEYED_SERVICE_H_
+#define COMPONENTS_BREADCRUMBS_CORE_BREADCRUMB_MANAGER_KEYED_SERVICE_H_
+
+#include <list>
+#include <memory>
+#include <string>
+
+#include "components/keyed_service/core/keyed_service.h"
+
+namespace breadcrumbs {
+
+class BreadcrumbManager;
+class BreadcrumbManagerObserver;
+class BreadcrumbPersistentStorageManager;
+
+// Associates a BreadcrumbManager instance with a browser (BrowserState on iOS,
+// BrowserContext on Desktop) - either incognito or normal.
+class BreadcrumbManagerKeyedService : public KeyedService {
+ public:
+ explicit BreadcrumbManagerKeyedService(bool is_off_the_record);
+ ~BreadcrumbManagerKeyedService() override;
+
+ // Logs a breadcrumb |event| associated with the browser. Prepends the
+ // |browsing_mode_| identifier to the event before passing it to the
+ // |breadcrumb_manager_|.
+ void AddEvent(const std::string& event);
+
+ // Adds and removes observers to the underlying |breadcrumb_manager_|.
+ void AddObserver(BreadcrumbManagerObserver* observer);
+ void RemoveObserver(BreadcrumbManagerObserver* observer);
+
+ // Returns the number of collected breadcrumb events which are still relevant.
+ // See |BreadcrumbManager::GetEventCount| for details.
+ size_t GetEventCount();
+
+ // Returns up to |event_count_limit| events from the underlying
+ // |breadcrumb_manager|. See |BreadcrumbManager::GetEvents| for returned event
+ // details.
+ const std::list<std::string> GetEvents(size_t event_count_limit) const;
+
+ // Persists all events logged to |breadcrumb_manager_| to
+ // |persistent_storage_manager|. If StartPersisting has already been called,
+ // breadcrumbs will no longer be persisted to the previous
+ // |persistent_storage_manager|.
+ // NOTE: |persistent_storage_manager| must be non-null.
+ void StartPersisting(
+ BreadcrumbPersistentStorageManager* persistent_storage_manager);
+ // Stops persisting events to |persistent_storage_manager_|. No-op if
+ // |persistent_storage_manager_| is not set.
+ void StopPersisting();
+ // Returns the current |persistent_storage_manager_|.
+ BreadcrumbPersistentStorageManager* GetPersistentStorageManager();
+
+ private:
+ // A short string identifying the browser used to initialize the receiver. For
+ // example, "I" for "I"ncognito browsing mode. This value is prepended to
+ // events sent to |AddEvent| in order to differentiate the browser associated
+ // with each event.
+ // Note: Normal browsing mode uses an empty string in order to prevent
+ // prepending most events with the same static value.
+ std::string browsing_mode_;
+
+ // The associated BreadcrumbManager to store events added with |AddEvent|.
+ std::unique_ptr<BreadcrumbManager> breadcrumb_manager_;
+
+ // The current BreadcrumbPersistentStorageManager persisting events logged to
+ // |breadcrumb_manager_|, set by StartPersisting. May be null.
+ BreadcrumbPersistentStorageManager* persistent_storage_manager_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(BreadcrumbManagerKeyedService);
+};
+
+} // namespace breadcrumbs
+
+#endif // COMPONENTS_BREADCRUMBS_CORE_BREADCRUMB_MANAGER_KEYED_SERVICE_H_
diff --git a/chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service_unittest.cc b/chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service_unittest.cc
new file mode 100644
index 00000000000..be2c8e5fce9
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/breadcrumb_manager_keyed_service_unittest.cc
@@ -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.
+
+#include "components/breadcrumbs/core/breadcrumb_manager_keyed_service.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace breadcrumbs {
+
+// Test fixture for testing BreadcrumbManagerKeyedService class.
+typedef PlatformTest BreadcrumbManagerKeyedServiceTest;
+
+// Tests that events logged to Normal and OffTheRecord BrowserStates are
+// separately identifiable.
+TEST_F(BreadcrumbManagerKeyedServiceTest, EventsLabeledWithBrowserState) {
+ std::unique_ptr<BreadcrumbManagerKeyedService> breadcrumb_manager_service =
+ std::make_unique<BreadcrumbManagerKeyedService>(
+ /*is_off_the_record=*/false);
+ breadcrumb_manager_service->AddEvent("event");
+
+ std::string event = breadcrumb_manager_service->GetEvents(0).front();
+
+ std::unique_ptr<BreadcrumbManagerKeyedService>
+ otr_breadcrumb_manager_service =
+ std::make_unique<BreadcrumbManagerKeyedService>(
+ /*is_off_the_record=*/true);
+ otr_breadcrumb_manager_service->AddEvent("event");
+
+ std::string off_the_record_event =
+ otr_breadcrumb_manager_service->GetEvents(0).front();
+ // Event should indicate it was logged from an off-the-record "Incognito"
+ // browser state.
+ EXPECT_NE(std::string::npos, off_the_record_event.find(" I "));
+
+ EXPECT_STRNE(event.c_str(), off_the_record_event.c_str());
+}
+
+} // namespace breadcrumbs
diff --git a/chromium/components/breadcrumbs/core/breadcrumb_manager_observer_unittest.cc b/chromium/components/breadcrumbs/core/breadcrumb_manager_observer_unittest.cc
new file mode 100644
index 00000000000..1724183c877
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/breadcrumb_manager_observer_unittest.cc
@@ -0,0 +1,92 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/breadcrumbs/core/breadcrumb_manager_observer.h"
+
+#include <string>
+
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "components/breadcrumbs/core/breadcrumb_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace breadcrumbs {
+
+namespace {
+
+class FakeBreadcrumbManagerObserver : public BreadcrumbManagerObserver {
+ public:
+ FakeBreadcrumbManagerObserver() {}
+ ~FakeBreadcrumbManagerObserver() override = default;
+
+ FakeBreadcrumbManagerObserver(const FakeBreadcrumbManagerObserver&) = delete;
+ FakeBreadcrumbManagerObserver& operator=(
+ const FakeBreadcrumbManagerObserver&) = delete;
+
+ // BreadcrumbManagerObserver
+ void EventAdded(BreadcrumbManager* manager,
+ const std::string& event) override {
+ event_added_last_received_manager_ = manager;
+ event_added_last_received_event_ = event;
+ }
+
+ void OldEventsRemoved(BreadcrumbManager* manager) override {
+ old_events_removed_last_received_manager_ = manager;
+ }
+
+ BreadcrumbManager* event_added_last_received_manager_ = nullptr;
+ std::string event_added_last_received_event_;
+
+ BreadcrumbManager* old_events_removed_last_received_manager_ = nullptr;
+};
+
+} // namespace
+
+class BreadcrumbManagerObserverTest : public PlatformTest {
+ protected:
+ BreadcrumbManagerObserverTest() { manager_.AddObserver(&observer_); }
+
+ ~BreadcrumbManagerObserverTest() override {
+ manager_.RemoveObserver(&observer_);
+ }
+
+ base::test::TaskEnvironment task_env_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+
+ BreadcrumbManager manager_;
+ FakeBreadcrumbManagerObserver observer_;
+};
+
+// Tests that |BreadcrumbManagerObserver::EventAdded| is called when an event to
+// added to |manager_|.
+TEST_F(BreadcrumbManagerObserverTest, EventAdded) {
+ ASSERT_FALSE(observer_.event_added_last_received_manager_);
+ ASSERT_TRUE(observer_.event_added_last_received_event_.empty());
+
+ std::string event = "event";
+ manager_.AddEvent(event);
+
+ EXPECT_EQ(&manager_, observer_.event_added_last_received_manager_);
+ // A timestamp will be prepended to the event passed to |AddEvent|.
+ EXPECT_NE(std::string::npos,
+ observer_.event_added_last_received_event_.find(event));
+}
+
+// Tests that |BreadcumbManager::OldEventsRemoved| is called when old events are
+// dropped from |manager_|.
+TEST_F(BreadcrumbManagerObserverTest, OldEventsRemoved) {
+ ASSERT_FALSE(observer_.old_events_removed_last_received_manager_);
+
+ std::string event = "event";
+ manager_.AddEvent(event);
+ task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+ manager_.AddEvent(event);
+ task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+ manager_.AddEvent(event);
+
+ EXPECT_EQ(&manager_, observer_.old_events_removed_last_received_manager_);
+}
+
+} // namespace breadcrumbs
diff --git a/chromium/components/breadcrumbs/core/breadcrumb_manager_unittest.cc b/chromium/components/breadcrumbs/core/breadcrumb_manager_unittest.cc
new file mode 100644
index 00000000000..00ace5e29d9
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/breadcrumb_manager_unittest.cc
@@ -0,0 +1,92 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/breadcrumbs/core/breadcrumb_manager.h"
+
+#include <list>
+#include <string>
+
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+namespace breadcrumbs {
+
+// Test fixture for testing BreadcrumbManager class.
+class BreadcrumbManagerTest : public PlatformTest {
+ protected:
+ BreadcrumbManagerTest() = default;
+
+ base::test::TaskEnvironment task_env_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ BreadcrumbManager breadcrumb_manager_;
+};
+
+// Tests that an event is logged and returned.
+TEST_F(BreadcrumbManagerTest, AddEvent) {
+ std::string event_message = "event";
+ breadcrumb_manager_.AddEvent(event_message);
+ std::list<std::string> events = breadcrumb_manager_.GetEvents(0);
+ ASSERT_EQ(1ul, events.size());
+ // Events returned from |GetEvents| will have a timestamp prepended.
+ EXPECT_NE(std::string::npos, events.front().find(event_message));
+}
+
+// Tests that returned events returned by |GetEvents| are limited by the
+// |event_count_limit| parameter.
+TEST_F(BreadcrumbManagerTest, EventCountLimited) {
+ breadcrumb_manager_.AddEvent("event1");
+ breadcrumb_manager_.AddEvent("event2");
+ breadcrumb_manager_.AddEvent("event3");
+ breadcrumb_manager_.AddEvent("event4");
+
+ std::list<std::string> events = breadcrumb_manager_.GetEvents(2);
+ ASSERT_EQ(2ul, events.size());
+ EXPECT_NE(std::string::npos, events.front().find("event3"));
+ events.pop_front();
+ EXPECT_NE(std::string::npos, events.front().find("event4"));
+}
+
+// Tests that old event buckets are dropped.
+TEST_F(BreadcrumbManagerTest, OldEventsDropped) {
+ // Log an event from one and two hours ago.
+ breadcrumb_manager_.AddEvent("event1");
+ task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+ breadcrumb_manager_.AddEvent("event2");
+ task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+
+ // Log three events separated by three minutes to ensure they receive their
+ // own event bucket. Otherwise, some old events may be returned to ensure a
+ // minimum number of available events. See |MinimumEventsReturned| test below.
+ breadcrumb_manager_.AddEvent("event3");
+ task_env_.FastForwardBy(base::TimeDelta::FromMinutes(3));
+ breadcrumb_manager_.AddEvent("event4");
+ task_env_.FastForwardBy(base::TimeDelta::FromMinutes(3));
+ breadcrumb_manager_.AddEvent("event5");
+
+ std::list<std::string> events = breadcrumb_manager_.GetEvents(0);
+ ASSERT_EQ(3ul, events.size());
+ // Validate the three most recent events are the ones which were returned.
+ EXPECT_NE(std::string::npos, events.front().find("event3"));
+ events.pop_front();
+ EXPECT_NE(std::string::npos, events.front().find("event4"));
+ events.pop_front();
+ EXPECT_NE(std::string::npos, events.front().find("event5"));
+}
+
+// Tests that expired events are returned if not enough new events exist.
+TEST_F(BreadcrumbManagerTest, MinimumEventsReturned) {
+ // Log an event from one and two hours ago.
+ breadcrumb_manager_.AddEvent("event1");
+ task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+ breadcrumb_manager_.AddEvent("event2");
+ task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+ breadcrumb_manager_.AddEvent("event3");
+
+ std::list<std::string> events = breadcrumb_manager_.GetEvents(0);
+ EXPECT_EQ(2ul, events.size());
+}
+
+} // namespace breadcrumbs
diff --git a/chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc b/chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc
new file mode 100644
index 00000000000..69e1795f982
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc
@@ -0,0 +1,346 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/breadcrumbs/core/breadcrumb_persistent_storage_manager.h"
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/files/file_util.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
+#include "components/breadcrumbs/core/breadcrumb_manager.h"
+#include "components/breadcrumbs/core/breadcrumb_manager_keyed_service.h"
+#include "components/breadcrumbs/core/breadcrumb_persistent_storage_util.h"
+
+namespace breadcrumbs {
+
+namespace {
+
+const char kEventSeparator[] = "\n";
+
+// Minimum time between breadcrumb writes to disk.
+constexpr auto kMinDelayBetweenWrites = base::TimeDelta::FromMilliseconds(250);
+
+// Writes |events| to |file_path| at |position|.
+void DoInsertEventsIntoMemoryMappedFile(const base::FilePath& file_path,
+ const size_t position,
+ const std::string& events) {
+ auto file = std::make_unique<base::MemoryMappedFile>();
+ const base::MemoryMappedFile::Region region = {0, kPersistedFilesizeInBytes};
+ const bool file_valid = file->Initialize(
+ base::File(file_path, base::File::FLAG_OPEN_ALWAYS |
+ base::File::FLAG_READ | base::File::FLAG_WRITE),
+ region, base::MemoryMappedFile::READ_WRITE_EXTEND);
+
+ if (file_valid) {
+ char* data = reinterpret_cast<char*>(file->data());
+ std::strcpy(&data[position], events.data());
+ }
+}
+
+// Writes |events| to |file_path| overwriting any existing data.
+void DoWriteEventsToFile(const base::FilePath& file_path,
+ const std::string& events) {
+ const base::MemoryMappedFile::Region region = {0, kPersistedFilesizeInBytes};
+ base::MemoryMappedFile file;
+ const bool file_valid = file.Initialize(
+ base::File(file_path, base::File::FLAG_CREATE_ALWAYS |
+ base::File::FLAG_READ | base::File::FLAG_WRITE),
+ region, base::MemoryMappedFile::READ_WRITE_EXTEND);
+
+ if (file_valid) {
+ char* data = reinterpret_cast<char*>(file.data());
+ std::strcpy(data, events.data());
+ }
+}
+
+void DoReplaceFile(const base::FilePath& from_path,
+ const base::FilePath& to_path) {
+ base::ReplaceFile(from_path, to_path, nullptr);
+}
+
+// Returns breadcrumb events stored at |file_path|.
+std::vector<std::string> DoGetStoredEvents(const base::FilePath& file_path) {
+ base::File events_file(file_path,
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+ if (!events_file.IsValid()) {
+ // File may not yet exist.
+ return std::vector<std::string>();
+ }
+
+ size_t file_size = events_file.GetLength();
+ if (file_size <= 0) {
+ return std::vector<std::string>();
+ }
+
+ // Do not read more than |kPersistedFilesizeInBytes|, in case the file was
+ // corrupted. If |kPersistedFilesizeInBytes| has been reduced since the last
+ // breadcrumbs file was saved, this could result in a one time loss of the
+ // oldest breadcrumbs which is ok because the decision has already been made
+ // to reduce the size of the stored breadcrumbs.
+ if (file_size > kPersistedFilesizeInBytes) {
+ file_size = kPersistedFilesizeInBytes;
+ }
+
+ std::vector<uint8_t> data;
+ data.resize(file_size);
+ if (!events_file.ReadAndCheck(/*offset=*/0, data)) {
+ return std::vector<std::string>();
+ }
+ std::string persisted_events(data.begin(), data.end());
+ std::string all_events =
+ persisted_events.substr(/*pos=*/0, strlen(persisted_events.c_str()));
+ return base::SplitString(all_events, kEventSeparator, base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY);
+}
+
+// Returns the total length of stored breadcrumb events at |file_path|. The
+// file is opened and the length of the string contents calculated because
+// the file size is always constant. (Due to base::MemoryMappedFile filling the
+// unused space with \0s.
+size_t DoGetStoredEventsLength(const base::FilePath& file_path) {
+ base::File events_file(file_path,
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+ if (!events_file.IsValid()) {
+ return 0;
+ }
+
+ size_t file_size = events_file.GetLength();
+ if (file_size <= 0) {
+ return 0;
+ }
+
+ // Do not read more than |kPersistedFilesizeInBytes|, in case the file was
+ // corrupted. If |kPersistedFilesizeInBytes| has been reduced since the last
+ // breadcrumbs file was saved, this could result in a one time loss of the
+ // oldest breadcrumbs which is ok because the decision has already been made
+ // to reduce the size of the stored breadcrumbs.
+ if (file_size > kPersistedFilesizeInBytes) {
+ file_size = kPersistedFilesizeInBytes;
+ }
+
+ std::vector<uint8_t> data;
+ data.resize(file_size);
+ if (!events_file.ReadAndCheck(/*offset=*/0, data)) {
+ return 0;
+ }
+
+ std::string persisted_events(data.begin(), data.end());
+ return strlen(persisted_events.c_str());
+}
+
+// Renames breadcrumb files with the old filenames "iOS Breadcrumbs.*" to the
+// new filenames "Breadcrumbs.*", if present.
+void MigrateOldBreadcrumbFiles(
+ const base::FilePath& old_breadcrumbs_file_path,
+ const base::FilePath& old_breadcrumbs_temp_file_path,
+ const base::FilePath& breadcrumbs_file_path,
+ const base::FilePath& breadcrumbs_temp_file_path) {
+ if (base::PathExists(old_breadcrumbs_file_path))
+ base::Move(old_breadcrumbs_file_path, breadcrumbs_file_path);
+ if (base::PathExists(old_breadcrumbs_temp_file_path))
+ base::Move(old_breadcrumbs_temp_file_path, breadcrumbs_temp_file_path);
+}
+
+} // namespace
+
+BreadcrumbPersistentStorageManager::BreadcrumbPersistentStorageManager(
+ const base::FilePath& directory,
+ const absl::optional<base::FilePath>& old_breadcrumbs_file_path,
+ const absl::optional<base::FilePath>& old_breadcrumbs_temp_file_path)
+ : // Ensure first event will not be delayed by initializing with a time in
+ // the past.
+ last_written_time_(base::TimeTicks::Now() - kMinDelayBetweenWrites),
+ breadcrumbs_file_path_(GetBreadcrumbPersistentStorageFilePath(directory)),
+ breadcrumbs_temp_file_path_(
+ GetBreadcrumbPersistentStorageTempFilePath(directory)),
+ task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+ weak_ptr_factory_(this) {
+ // Rename breadcrumb files using the old filenames, if present. This must
+ // happen before the files are used, to ensure that old breadcrumbs are found.
+ // TODO(crbug.com/1187988): remove this and its unit test.
+ if (old_breadcrumbs_file_path && old_breadcrumbs_temp_file_path) {
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&MigrateOldBreadcrumbFiles,
+ old_breadcrumbs_file_path.value(),
+ old_breadcrumbs_temp_file_path.value(),
+ breadcrumbs_file_path_, breadcrumbs_temp_file_path_));
+ }
+ task_runner_->PostTaskAndReplyWithResult(
+ FROM_HERE,
+ base::BindOnce(&DoGetStoredEventsLength, breadcrumbs_file_path_),
+ base::BindOnce(
+ &BreadcrumbPersistentStorageManager::SetCurrentMappedFilePosition,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+BreadcrumbPersistentStorageManager::~BreadcrumbPersistentStorageManager() =
+ default;
+
+void BreadcrumbPersistentStorageManager::GetStoredEvents(
+ base::OnceCallback<void(std::vector<std::string>)> callback) {
+ task_runner_->PostTaskAndReplyWithResult(
+ FROM_HERE, base::BindOnce(&DoGetStoredEvents, breadcrumbs_file_path_),
+ std::move(callback));
+}
+
+void BreadcrumbPersistentStorageManager::MonitorBreadcrumbManager(
+ BreadcrumbManager* manager) {
+ manager->AddObserver(this);
+}
+
+void BreadcrumbPersistentStorageManager::MonitorBreadcrumbManagerService(
+ BreadcrumbManagerKeyedService* service) {
+ service->AddObserver(this);
+}
+
+void BreadcrumbPersistentStorageManager::StopMonitoringBreadcrumbManager(
+ BreadcrumbManager* manager) {
+ manager->RemoveObserver(this);
+}
+
+void BreadcrumbPersistentStorageManager::StopMonitoringBreadcrumbManagerService(
+ BreadcrumbManagerKeyedService* service) {
+ service->RemoveObserver(this);
+}
+
+void BreadcrumbPersistentStorageManager::CombineEventsAndRewriteAllBreadcrumbs(
+ const std::vector<std::string> pending_breadcrumbs,
+ std::vector<std::string> existing_events) {
+ // Add events which had not yet been written.
+ for (auto event : pending_breadcrumbs) {
+ existing_events.push_back(event);
+ }
+
+ std::vector<std::string> breadcrumbs;
+ for (auto event_it = existing_events.rbegin();
+ event_it != existing_events.rend(); ++event_it) {
+ // Reduce saved events to only fill the amount which would be included on
+ // a crash log. This allows future events to be appended individually up
+ // to |kPersistedFilesizeInBytes|, which is more efficient than writing
+ // out the
+ const int event_with_seperator_size =
+ event_it->size() + strlen(kEventSeparator);
+ if (event_with_seperator_size + current_mapped_file_position_.value() >=
+ kMaxDataLength) {
+ break;
+ }
+
+ breadcrumbs.push_back(kEventSeparator);
+ breadcrumbs.push_back(*event_it);
+ current_mapped_file_position_ =
+ current_mapped_file_position_.value() + event_with_seperator_size;
+ }
+
+ std::reverse(breadcrumbs.begin(), breadcrumbs.end());
+ std::string breadcrumbs_string = base::JoinString(breadcrumbs, "");
+
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&DoWriteEventsToFile, breadcrumbs_temp_file_path_,
+ std::string(breadcrumbs_string)));
+
+ task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&DoReplaceFile, breadcrumbs_temp_file_path_,
+ breadcrumbs_file_path_));
+}
+
+void BreadcrumbPersistentStorageManager::RewriteAllExistingBreadcrumbs() {
+ // Collect breadcrumbs which haven't been written yet to include in this full
+ // re-write.
+ std::vector<std::string> pending_breadcrumbs =
+ base::SplitString(pending_breadcrumbs_, kEventSeparator,
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ pending_breadcrumbs_.clear();
+ write_timer_.Stop();
+
+ last_written_time_ = base::TimeTicks::Now();
+ current_mapped_file_position_ = 0;
+
+ // Load persisted events directly from file because the correct order can not
+ // be reconstructed from the multiple BreadcrumbManagers with the partial
+ // timestamps embedded in each event.
+ GetStoredEvents(base::BindOnce(&BreadcrumbPersistentStorageManager::
+ CombineEventsAndRewriteAllBreadcrumbs,
+ weak_ptr_factory_.GetWeakPtr(),
+ pending_breadcrumbs));
+}
+
+void BreadcrumbPersistentStorageManager::WritePendingBreadcrumbs() {
+ if (pending_breadcrumbs_.empty()) {
+ return;
+ }
+
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(&DoInsertEventsIntoMemoryMappedFile,
+ breadcrumbs_file_path_,
+ current_mapped_file_position_.value(),
+ std::string(pending_breadcrumbs_)));
+
+ current_mapped_file_position_ =
+ current_mapped_file_position_.value() + pending_breadcrumbs_.size();
+ last_written_time_ = base::TimeTicks::Now();
+
+ pending_breadcrumbs_.clear();
+}
+
+void BreadcrumbPersistentStorageManager::EventAdded(BreadcrumbManager* manager,
+ const std::string& event) {
+ WriteEvent(event);
+}
+
+void BreadcrumbPersistentStorageManager::WriteEvent(const std::string& event) {
+ pending_breadcrumbs_ += event + kEventSeparator;
+
+ WriteEvents();
+}
+
+void BreadcrumbPersistentStorageManager::SetCurrentMappedFilePosition(
+ size_t file_size) {
+ current_mapped_file_position_ = file_size;
+}
+
+void BreadcrumbPersistentStorageManager::WriteEvents() {
+ write_timer_.Stop();
+
+ const base::TimeDelta time_delta_since_last_write =
+ base::TimeTicks::Now() - last_written_time_;
+ // Delay writing the event to disk if an event was just written or if the size
+ // of exisiting breadcrumbs is not yet known.
+ if (time_delta_since_last_write < kMinDelayBetweenWrites ||
+ !current_mapped_file_position_) {
+ write_timer_.Start(FROM_HERE,
+ kMinDelayBetweenWrites - time_delta_since_last_write,
+ this, &BreadcrumbPersistentStorageManager::WriteEvents);
+ } else {
+ // If the event does not fit within |kPersistedFilesizeInBytes|, rewrite the
+ // file to trim old events.
+ if ((current_mapped_file_position_.value() + pending_breadcrumbs_.size())
+ // Use >= here instead of > to allow space for \0 to terminate file.
+ >= kPersistedFilesizeInBytes) {
+ RewriteAllExistingBreadcrumbs();
+ return;
+ }
+
+ // Otherwise, simply append the pending breadcrumbs.
+ WritePendingBreadcrumbs();
+ }
+}
+
+void BreadcrumbPersistentStorageManager::OldEventsRemoved(
+ BreadcrumbManager* manager) {
+ RewriteAllExistingBreadcrumbs();
+}
+
+} // namespace breadcrumbs
diff --git a/chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.h b/chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.h
new file mode 100644
index 00000000000..884100a20f2
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.h
@@ -0,0 +1,128 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_BREADCRUMBS_CORE_BREADCRUMB_PERSISTENT_STORAGE_MANAGER_H_
+#define COMPONENTS_BREADCRUMBS_CORE_BREADCRUMB_PERSISTENT_STORAGE_MANAGER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/timer/timer.h"
+#include "components/breadcrumbs/core/breadcrumb_manager_observer.h"
+#include "components/breadcrumbs/core/crash_reporter_breadcrumb_constants.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace breadcrumbs {
+
+class BreadcrumbManager;
+class BreadcrumbManagerKeyedService;
+
+// The filesize for the file at |breadcrumbs_file_path_|. The file will always
+// be this constant size because it is accessed using a memory mapped file. The
+// file is twice as large as |kMaxDataLength| which leaves room for appending
+// breadcrumb events. Once the file is full of events, the contents will be
+// reduced to kMaxDataLength.
+constexpr size_t kPersistedFilesizeInBytes = kMaxDataLength * 2;
+
+// Stores breadcrumb events to and retrieves them from a file on disk.
+// Persisting these events allows access to breadcrumb events from previous
+// application sessions.
+class BreadcrumbPersistentStorageManager : public BreadcrumbManagerObserver {
+ public:
+ // Breadcrumbs will be stored in a file in |directory|. If
+ // |old_breadcrumbs_file_path| and |old_breadcrumbs_temp_file_path| are
+ // provided, the files at those paths will be migrated to the new filenames
+ // for breadcrumb files (only needed on iOS, which previously used different
+ // filenames).
+ explicit BreadcrumbPersistentStorageManager(
+ const base::FilePath& directory,
+ const absl::optional<base::FilePath>& old_breadcrumbs_file_path,
+ const absl::optional<base::FilePath>& old_breadcrumbs_temp_file_path);
+ ~BreadcrumbPersistentStorageManager() override;
+ BreadcrumbPersistentStorageManager(
+ const BreadcrumbPersistentStorageManager&) = delete;
+ BreadcrumbPersistentStorageManager& operator=(
+ const BreadcrumbPersistentStorageManager&) = delete;
+
+ // Returns the stored breadcrumb events from disk to |callback|.
+ void GetStoredEvents(
+ base::OnceCallback<void(std::vector<std::string>)> callback);
+
+ // Starts observing |manager| for events. Existing events will be persisted
+ // immediately.
+ void MonitorBreadcrumbManager(BreadcrumbManager* manager);
+ // Starts observing |service| for events. Existing events will be persisted
+ // immediately.
+ void MonitorBreadcrumbManagerService(BreadcrumbManagerKeyedService* service);
+
+ // Stops observing |manager|.
+ void StopMonitoringBreadcrumbManager(BreadcrumbManager* manager);
+ // Stops observing |service|.
+ void StopMonitoringBreadcrumbManagerService(
+ BreadcrumbManagerKeyedService* service);
+
+ private:
+ // Sets |current_mapped_file_position_| to |file_size|;
+ void SetCurrentMappedFilePosition(size_t file_size);
+
+ // Writes |pending_breadcrumbs_| to |breadcrumbs_file_| if it fits, otherwise
+ // rewrites the file. NOTE: Writing may be delayed if the file has recently
+ // been written into.
+ void WriteEvents();
+
+ // Appends events in |pending_breadcrumbs| to |existing events|, then writes
+ // the combined events to |breadcrumbs_file_|, overwriting any existing
+ // persisted breadcrumbs.
+ void CombineEventsAndRewriteAllBreadcrumbs(
+ const std::vector<std::string> pending_breadcrumbs,
+ std::vector<std::string> existing_events);
+
+ // Writes events from observed managers to |breadcrumbs_file_|, overwriting
+ // any existing persisted breadcrumbs.
+ void RewriteAllExistingBreadcrumbs();
+
+ // Writes breadcrumbs stored in |pending_breadcrumbs_| to |breadcrumbs_file_|.
+ void WritePendingBreadcrumbs();
+
+ // Writes |event| to |breadcrumbs_file_|.
+ // NOTE: Writing may be delayed if the file has recently been written into.
+ void WriteEvent(const std::string& event);
+
+ // BreadcrumbManagerObserver
+ void EventAdded(BreadcrumbManager* manager,
+ const std::string& event) override;
+ void OldEventsRemoved(BreadcrumbManager* manager) override;
+
+ // Individual breadcrumbs that have not yet been written to disk.
+ std::string pending_breadcrumbs_;
+
+ // The last time a breadcrumb was written to |breadcrumbs_file_|. This
+ // timestamp prevents breadcrumbs from being written to disk too often.
+ base::TimeTicks last_written_time_;
+
+ // A timer to delay writing to disk too often.
+ base::OneShotTimer write_timer_;
+
+ // The path to the file for storing persisted breadcrumbs.
+ base::FilePath breadcrumbs_file_path_;
+
+ // The path to the temporary file for writing persisted breadcrumbs.
+ base::FilePath breadcrumbs_temp_file_path_;
+
+ // The current size of breadcrumbs written to |breadcrumbs_file_path_|.
+ // NOTE: The optional will not have a value until the size of the existing
+ // file, if any, is retrieved.
+ absl::optional<size_t> current_mapped_file_position_;
+
+ // The SequencedTaskRunner on which File IO operations are performed.
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ base::WeakPtrFactory<BreadcrumbPersistentStorageManager> weak_ptr_factory_;
+};
+
+} // namespace breadcrumbs
+
+#endif // COMPONENTS_BREADCRUMBS_CORE_BREADCRUMB_PERSISTENT_STORAGE_MANAGER_H_
diff --git a/chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_util_unittest.cc b/chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_util_unittest.cc
new file mode 100644
index 00000000000..a28e6a8adbf
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/breadcrumb_persistent_storage_util_unittest.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/breadcrumbs/core/breadcrumb_persistent_storage_util.h"
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+// Test fixture to test BreadcrumbPersistentStorageUtil.
+typedef PlatformTest BreadcrumbPersistentStorageUtilTest;
+
+// Tests that the breadcrumb storage file path is different from the temp file
+// path.
+TEST_F(BreadcrumbPersistentStorageUtilTest, UniqueTempStorage) {
+ base::ScopedTempDir scoped_temp_directory;
+ EXPECT_TRUE(scoped_temp_directory.CreateUniqueTempDir());
+
+ base::FilePath directory = scoped_temp_directory.GetPath();
+ EXPECT_NE(breadcrumbs::GetBreadcrumbPersistentStorageFilePath(directory),
+ breadcrumbs::GetBreadcrumbPersistentStorageTempFilePath(directory));
+}
diff --git a/chromium/components/breadcrumbs/core/features.cc b/chromium/components/breadcrumbs/core/features.cc
new file mode 100644
index 00000000000..f4775e065f0
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/features.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/breadcrumbs/core/features.h"
+
+namespace breadcrumbs {
+
+const base::Feature kLogBreadcrumbs{"LogBreadcrumbs",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+} // namespace breadcrumbs
diff --git a/chromium/components/breadcrumbs/core/features.h b/chromium/components/breadcrumbs/core/features.h
new file mode 100644
index 00000000000..e14a57e014a
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/features.h
@@ -0,0 +1,17 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_BREADCRUMBS_CORE_FEATURES_H_
+#define COMPONENTS_BREADCRUMBS_CORE_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace breadcrumbs {
+
+// Feature flag to log breadcrumb events.
+extern const base::Feature kLogBreadcrumbs;
+
+} // namespace breadcrumbs
+
+#endif // COMPONENTS_BREADCRUMBS_CORE_FEATURES_H_
diff --git a/chromium/components/breadcrumbs/core/generate_not_user_triggered_actions.py b/chromium/components/breadcrumbs/core/generate_not_user_triggered_actions.py
new file mode 100644
index 00000000000..154379fa9d9
--- /dev/null
+++ b/chromium/components/breadcrumbs/core/generate_not_user_triggered_actions.py
@@ -0,0 +1,72 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Produces C++ file with sorted array of UMA User Actions strings."""
+
+import argparse
+import sys
+import os
+
+from xml.etree import ElementTree
+
+
+def not_user_triggered_actions(actions_file_path):
+ """Generates list of not-user triggered and non-obsolete UMA User Actions.
+
+ Args:
+ actions_file_path: path to actions.xml file
+ """
+ actions = ElementTree.parse(actions_file_path).getroot()
+
+ for action in actions:
+ if action.find('obsolete') is not None:
+ continue
+
+ if action.attrib.get('not_user_triggered') == 'true':
+ yield action.attrib['name']
+
+
+def main(actions_file_path, output_file_path):
+ """Produces C++ file with sorted array of UMA User Actions strings.
+
+ Array is a global kNotUserTriggeredActions constant in anonymous namespace.
+
+ Args:
+ actions_file_path: path to actions.xml file
+ output_file_path: path to output C++ file
+ """
+ actions = not_user_triggered_actions(actions_file_path)
+ if not actions:
+ sys.stderr.write(
+ 'There are no not-user triggered and non-obsolete in %s',
+ actions_file_path)
+ return -1
+
+
+ with open(output_file_path ,'w') as output_file:
+ output_file.write('// Generated by %s\n' % sys.argv[0])
+ output_file.write('namespace {\n')
+ output_file.write('const char* kNotUserTriggeredActions[] = {\n')
+
+ for action in sorted(actions):
+ output_file.write(' "%s",\n' % action)
+
+ output_file.write('};\n')
+ output_file.write('} // namespace\n')
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument(
+ '-a',
+ '--actions',
+ help='path to actions.xml file')
+ parser.add_argument(
+ '-o',
+ '--output',
+ help='path to output source file')
+
+ args = parser.parse_args()
+
+ sys.exit(main(args.actions, args.output))
diff --git a/chromium/components/breadcrumbs/ios/BUILD.gn b/chromium/components/breadcrumbs/ios/BUILD.gn
new file mode 100644
index 00000000000..28455ad6f5c
--- /dev/null
+++ b/chromium/components/breadcrumbs/ios/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("ios") {
+ sources = [
+ "breadcrumb_manager_observer_bridge.h",
+ "breadcrumb_manager_observer_bridge.mm",
+ ]
+
+ deps = [
+ "//base",
+ "//components/breadcrumbs/core",
+ ]
+
+ configs += [ "//build/config/compiler:enable_arc" ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [ "breadcrumb_manager_observer_bridge_unittest.mm" ]
+
+ deps = [
+ ":ios",
+ "//base/test:test_support",
+ "//components/breadcrumbs/core",
+ "//ios/web/public/test",
+ "//testing/gtest",
+ "//third_party/ocmock",
+ ]
+
+ configs += [ "//build/config/compiler:enable_arc" ]
+}
diff --git a/chromium/components/breadcrumbs/ios/DEPS b/chromium/components/breadcrumbs/ios/DEPS
new file mode 100644
index 00000000000..4dd63070bb3
--- /dev/null
+++ b/chromium/components/breadcrumbs/ios/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+ios/web/public",
+ "+third_party/ocmock",
+]
diff --git a/chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge.h b/chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge.h
new file mode 100644
index 00000000000..2cc36d90f77
--- /dev/null
+++ b/chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge.h
@@ -0,0 +1,66 @@
+// Copyright 2019 The Chromium Authors. 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_BREADCRUMBS_IOS_BREADCRUMB_MANAGER_OBSERVER_BRIDGE_H_
+#define COMPONENTS_BREADCRUMBS_IOS_BREADCRUMB_MANAGER_OBSERVER_BRIDGE_H_
+
+#import <Foundation/Foundation.h>
+
+#include <string>
+
+#include "components/breadcrumbs/core/breadcrumb_manager_observer.h"
+
+namespace breadcrumbs {
+class BreadcrumbManager;
+class BreadcrumbManagerKeyedService;
+}
+
+// Protocol mirroring BreadcrumbManagerObserver
+@protocol BreadcrumbManagerObserving <NSObject>
+@optional
+- (void)breadcrumbManager:(breadcrumbs::BreadcrumbManager*)manager
+ didAddEvent:(NSString*)string;
+
+- (void)breadcrumbManagerDidRemoveOldEvents:
+ (breadcrumbs::BreadcrumbManager*)manager;
+@end
+
+namespace breadcrumbs {
+
+// A C++ bridge class to handle receiving notifications from the C++ class
+// that observes the connection type.
+class BreadcrumbManagerObserverBridge : public BreadcrumbManagerObserver {
+ public:
+ // Constructs a new bridge instance adding |observer| as an observer of
+ // |breadcrumb_manager|.
+ BreadcrumbManagerObserverBridge(BreadcrumbManager* breadcrumb_manager,
+ id<BreadcrumbManagerObserving> observer);
+
+ // Constructs a new bridge instance adding |observer| as an observer of
+ // |breadcrumb_manager_service|.
+ BreadcrumbManagerObserverBridge(
+ BreadcrumbManagerKeyedService* breadcrumb_manager_service,
+ id<BreadcrumbManagerObserving> observer);
+
+ ~BreadcrumbManagerObserverBridge() override;
+
+ private:
+ BreadcrumbManagerObserverBridge(const BreadcrumbManagerObserverBridge&) =
+ delete;
+ BreadcrumbManagerObserverBridge& operator=(
+ const BreadcrumbManagerObserverBridge&) = delete;
+
+ // BreadcrumbManagerObserver implementation:
+ void EventAdded(BreadcrumbManager* manager,
+ const std::string& event) override;
+ void OldEventsRemoved(BreadcrumbManager* manager) override;
+
+ BreadcrumbManager* breadcrumb_manager_ = nullptr;
+ BreadcrumbManagerKeyedService* breadcrumb_manager_service_ = nullptr;
+ __weak id<BreadcrumbManagerObserving> observer_ = nil;
+};
+
+} // namespace breadcrumbs
+
+#endif // COMPONENTS_BREADCRUMBS_IOS_BREADCRUMB_MANAGER_OBSERVER_BRIDGE_H_
diff --git a/chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge.mm b/chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge.mm
new file mode 100644
index 00000000000..4c2f65831e6
--- /dev/null
+++ b/chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge.mm
@@ -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.
+
+#import "components/breadcrumbs/ios/breadcrumb_manager_observer_bridge.h"
+
+#include "base/check.h"
+#include "base/strings/sys_string_conversions.h"
+#include "components/breadcrumbs/core/breadcrumb_manager.h"
+#include "components/breadcrumbs/core/breadcrumb_manager_keyed_service.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace breadcrumbs {
+
+BreadcrumbManagerObserverBridge::BreadcrumbManagerObserverBridge(
+ BreadcrumbManager* breadcrumb_manager,
+ id<BreadcrumbManagerObserving> observer)
+ : breadcrumb_manager_(breadcrumb_manager), observer_(observer) {
+ DCHECK(observer_);
+ breadcrumb_manager_->AddObserver(this);
+}
+
+BreadcrumbManagerObserverBridge::BreadcrumbManagerObserverBridge(
+ BreadcrumbManagerKeyedService* breadcrumb_manager_service,
+ id<BreadcrumbManagerObserving> observer)
+ : breadcrumb_manager_service_(breadcrumb_manager_service),
+ observer_(observer) {
+ DCHECK(observer_);
+ breadcrumb_manager_service_->AddObserver(this);
+}
+
+BreadcrumbManagerObserverBridge::~BreadcrumbManagerObserverBridge() {
+ if (breadcrumb_manager_) {
+ breadcrumb_manager_->RemoveObserver(this);
+ }
+ if (breadcrumb_manager_service_) {
+ breadcrumb_manager_service_->RemoveObserver(this);
+ }
+}
+
+void BreadcrumbManagerObserverBridge::EventAdded(BreadcrumbManager* manager,
+ const std::string& event) {
+ if ([observer_ respondsToSelector:@selector(breadcrumbManager:
+ didAddEvent:)]) {
+ [observer_ breadcrumbManager:manager
+ didAddEvent:base::SysUTF8ToNSString(event)];
+ }
+}
+
+void BreadcrumbManagerObserverBridge::OldEventsRemoved(
+ BreadcrumbManager* manager) {
+ if ([observer_
+ respondsToSelector:@selector(breadcrumbManagerDidRemoveOldEvents:)]) {
+ [observer_ breadcrumbManagerDidRemoveOldEvents:manager];
+ }
+}
+
+} // namespace breadcrumbs
diff --git a/chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge_unittest.mm b/chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge_unittest.mm
new file mode 100644
index 00000000000..74a419cc066
--- /dev/null
+++ b/chromium/components/breadcrumbs/ios/breadcrumb_manager_observer_bridge_unittest.mm
@@ -0,0 +1,77 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "components/breadcrumbs/ios/breadcrumb_manager_observer_bridge.h"
+
+#include <memory>
+
+#import "base/strings/sys_string_conversions.h"
+#include "components/breadcrumbs/core/breadcrumb_manager.h"
+#import "ios/web/public/test/web_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#include "third_party/ocmock/gtest_support.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace breadcrumbs {
+
+// Test fixture to test BreadcrumbManagerObserverBridge class.
+class BreadcrumbManagerObserverBridgeTest : public PlatformTest {
+ protected:
+ BreadcrumbManagerObserverBridgeTest() {
+ mock_observer_ = OCMProtocolMock(@protocol(BreadcrumbManagerObserving));
+ observer_bridge_ = std::make_unique<BreadcrumbManagerObserverBridge>(
+ &breadcrumb_manager_, mock_observer_);
+ }
+
+ web::WebTaskEnvironment task_env_{
+ web::WebTaskEnvironment::Options::DEFAULT,
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ BreadcrumbManager breadcrumb_manager_;
+ id mock_observer_;
+ std::unique_ptr<BreadcrumbManagerObserverBridge> observer_bridge_;
+};
+
+// Tests |breadcrumbManager:didAddEvent:| forwarding.
+TEST_F(BreadcrumbManagerObserverBridgeTest, EventAdded) {
+ std::string event("sample event");
+
+ id event_parameter_validator = [OCMArg checkWithBlock:^BOOL(id value) {
+ // The manager will prepended a timestamp to the event so verify that the
+ // end matches |event|.
+ return [value isKindOfClass:[NSString class]] &&
+ [value hasSuffix:base::SysUTF8ToNSString(event)];
+ }];
+ OCMExpect([mock_observer_ breadcrumbManager:&breadcrumb_manager_
+ didAddEvent:event_parameter_validator]);
+
+ breadcrumb_manager_.AddEvent(event);
+
+ [mock_observer_ verify];
+}
+
+// Tests |breadcrumbManagerDidRemoveOldEvents:| forwarding.
+TEST_F(BreadcrumbManagerObserverBridgeTest, OldEventsRemoved) {
+ OCMExpect([mock_observer_ breadcrumbManager:&breadcrumb_manager_
+ didAddEvent:OCMOCK_ANY]);
+ OCMExpect([mock_observer_
+ breadcrumbManagerDidRemoveOldEvents:&breadcrumb_manager_]);
+
+ // Oldest event will be dropped becuase it is old enough and there are two
+ // newer buckets.
+ breadcrumb_manager_.AddEvent("event1");
+ task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+ breadcrumb_manager_.AddEvent("event2");
+ task_env_.FastForwardBy(base::TimeDelta::FromHours(1));
+ breadcrumb_manager_.AddEvent("event3");
+
+ [mock_observer_ verify];
+}
+
+} // namespace breadcrumbs
diff --git a/chromium/components/browser_sync/active_devices_provider_impl_unittest.cc b/chromium/components/browser_sync/active_devices_provider_impl_unittest.cc
index 20e72ad1847..5a3b546a85f 100644
--- a/chromium/components/browser_sync/active_devices_provider_impl_unittest.cc
+++ b/chromium/components/browser_sync/active_devices_provider_impl_unittest.cc
@@ -14,6 +14,7 @@
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
#include "components/browser_sync/browser_sync_switches.h"
+#include "components/sync/protocol/sync_enums.pb.h"
#include "components/sync_device_info/device_info_util.h"
#include "components/sync_device_info/fake_device_info_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -39,7 +40,7 @@ std::unique_ptr<DeviceInfo> CreateFakeDeviceInfo(
last_updated_timestamp,
base::TimeDelta::FromMinutes(kPulseIntervalMinutes),
/*send_tab_to_self_receiving_enabled=*/false,
- /*sharing_info=*/base::nullopt, /*paask_info=*/base::nullopt,
+ /*sharing_info=*/absl::nullopt, /*paask_info=*/absl::nullopt,
fcm_registration_token,
/*interested_data_types=*/syncer::ModelTypeSet());
}
diff --git a/chromium/components/browser_sync/browser_sync_switches.h b/chromium/components/browser_sync/browser_sync_switches.h
index 32345cdaaf7..7baea7fc4ea 100644
--- a/chromium/components/browser_sync/browser_sync_switches.h
+++ b/chromium/components/browser_sync/browser_sync_switches.h
@@ -6,6 +6,7 @@
#define COMPONENTS_BROWSER_SYNC_BROWSER_SYNC_SWITCHES_H_
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
#include "build/build_config.h"
namespace switches {
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 f93914effcc..e55b1882cb0 100644
--- a/chromium/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/chromium/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -430,8 +430,7 @@ ProfileSyncComponentsFactoryImpl::CreateSyncEngine(
base::Unretained(sync_client_)));
}
-void ProfileSyncComponentsFactoryImpl::
- ClearAllTransportDataExceptEncryptionBootstrapToken() {
+void ProfileSyncComponentsFactoryImpl::ClearAllTransportData() {
syncer::SyncTransportDataPrefs sync_transport_data_prefs(
sync_client_->GetPrefService());
@@ -448,7 +447,7 @@ void ProfileSyncComponentsFactoryImpl::
sync_client_->GetModelTypeStoreService()->GetSyncDataPath()));
}
- sync_transport_data_prefs.ClearAllExceptEncryptionBootstrapToken();
+ sync_transport_data_prefs.ClearAll();
sync_client_->OnLocalSyncTransportDataCleared();
}
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 e3f28deb9a6..0379c5d6b4e 100644
--- a/chromium/components/browser_sync/profile_sync_components_factory_impl.h
+++ b/chromium/components/browser_sync/profile_sync_components_factory_impl.h
@@ -82,7 +82,7 @@ class ProfileSyncComponentsFactoryImpl
const std::string& name,
invalidation::InvalidationService* invalidator,
syncer::SyncInvalidationsService* sync_invalidation_service) override;
- void ClearAllTransportDataExceptEncryptionBootstrapToken() override;
+ void ClearAllTransportData() override;
private:
// Factory function for ModelTypeController instances for models living on
diff --git a/chromium/components/browser_ui/bottomsheet/android/DIR_METADATA b/chromium/components/browser_ui/bottomsheet/android/DIR_METADATA
index 1a4392135e6..b87b2836e54 100644
--- a/chromium/components/browser_ui/bottomsheet/android/DIR_METADATA
+++ b/chromium/components/browser_ui/bottomsheet/android/DIR_METADATA
@@ -2,6 +2,3 @@ monorail {
component: "UI>Browser>Mobile>NavPanel"
}
-team_email: "clank-app-team@google.com"
-
-os: ANDROID
diff --git a/chromium/components/browser_ui/bottomsheet/android/internal/BUILD.gn b/chromium/components/browser_ui/bottomsheet/android/internal/BUILD.gn
index a12f26876cf..108bde46964 100644
--- a/chromium/components/browser_ui/bottomsheet/android/internal/BUILD.gn
+++ b/chromium/components/browser_ui/bottomsheet/android/internal/BUILD.gn
@@ -9,6 +9,7 @@ android_library("java") {
":*",
"../test:*",
"//chrome/android:chrome_all_java",
+ "//weblayer/browser/java:java",
]
sources = [
diff --git a/chromium/components/browser_ui/contacts_picker/android/contacts_picker_feature_list.cc b/chromium/components/browser_ui/contacts_picker/android/contacts_picker_feature_list.cc
index 95195ed3a1f..2d0d737a6eb 100644
--- a/chromium/components/browser_ui/contacts_picker/android/contacts_picker_feature_list.cc
+++ b/chromium/components/browser_ui/contacts_picker/android/contacts_picker_feature_list.cc
@@ -5,8 +5,6 @@
#include "base/android/jni_string.h"
#include "base/feature_list.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
-
#include "components/browser_ui/contacts_picker/android/contacts_picker_jni_headers/ContactsPickerFeatureList_jni.h"
#include "components/browser_ui/contacts_picker/android/features.h"
@@ -20,15 +18,15 @@ namespace {
// Array of features exposed through the Java ContentFeatureList API. Entries in
// this array may either refer to features defined in the header of this file or
// in other locations in the code base (e.g. content_features.h).
-const base::Feature* kFeaturesExposedToJava[] = {
+const base::Feature* const kFeaturesExposedToJava[] = {
&kContactsPickerSelectAll,
};
// TODO(crbug.com/1060097): Remove this once a generalized FeatureList exists.
const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
- for (size_t i = 0; i < base::size(kFeaturesExposedToJava); ++i) {
- if (kFeaturesExposedToJava[i]->name == feature_name)
- return kFeaturesExposedToJava[i];
+ for (const base::Feature* feature : kFeaturesExposedToJava) {
+ if (feature->name == feature_name)
+ return feature;
}
NOTREACHED() << "Queried feature not found in ContactsPickerFeatureList: "
<< feature_name;
diff --git a/chromium/components/browser_ui/media/OWNERS b/chromium/components/browser_ui/media/OWNERS
new file mode 100644
index 00000000000..168af18e795
--- /dev/null
+++ b/chromium/components/browser_ui/media/OWNERS
@@ -0,0 +1 @@
+file://media/OWNERS
diff --git a/chromium/components/browser_ui/notifications/android/DIR_METADATA b/chromium/components/browser_ui/notifications/android/DIR_METADATA
index 55fac6aa24e..0584aa3fe5c 100644
--- a/chromium/components/browser_ui/notifications/android/DIR_METADATA
+++ b/chromium/components/browser_ui/notifications/android/DIR_METADATA
@@ -4,4 +4,3 @@ monorail {
team_email: "chrome-notifications@google.com"
-os: ANDROID
diff --git a/chromium/components/browser_ui/photo_picker/android/BUILD.gn b/chromium/components/browser_ui/photo_picker/android/BUILD.gn
index dc18ede4119..02a83a91224 100644
--- a/chromium/components/browser_ui/photo_picker/android/BUILD.gn
+++ b/chromium/components/browser_ui/photo_picker/android/BUILD.gn
@@ -26,7 +26,9 @@ android_library("java") {
"java/src/org/chromium/components/browser_ui/photo_picker/DecoderServiceHost.java",
"java/src/org/chromium/components/browser_ui/photo_picker/FileEnumWorkerTask.java",
"java/src/org/chromium/components/browser_ui/photo_picker/ImageDecoder.java",
+ "java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDelegateBase.java",
"java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialog.java",
+ "java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerFeatures.java",
"java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerToolbar.java",
"java/src/org/chromium/components/browser_ui/photo_picker/PickerAdapter.java",
"java/src/org/chromium/components/browser_ui/photo_picker/PickerBitmap.java",
@@ -56,7 +58,10 @@ android_library("java") {
}
generate_jni("photo_picker_jni_headers") {
- sources = [ "java/src/org/chromium/components/browser_ui/photo_picker/ImageDecoder.java" ]
+ sources = [
+ "java/src/org/chromium/components/browser_ui/photo_picker/ImageDecoder.java",
+ "java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerFeatures.java",
+ ]
}
android_aidl("photo_picker_aidl") {
diff --git a/chromium/components/browser_ui/photo_picker/android/features.cc b/chromium/components/browser_ui/photo_picker/android/features.cc
index a5176983e3e..b71197e8ec5 100644
--- a/chromium/components/browser_ui/photo_picker/android/features.cc
+++ b/chromium/components/browser_ui/photo_picker/android/features.cc
@@ -4,11 +4,29 @@
#include "components/browser_ui/photo_picker/android/features.h"
+#include "components/browser_ui/photo_picker/android/photo_picker_jni_headers/PhotoPickerFeatures_jni.h"
+
namespace photo_picker {
namespace features {
+namespace {
+
+// Array of features exposed through the Java Features brdige class. Entries in
+// this array may either refer to features defined in the header of this file or
+// in other locations in the code base (e.g. content_features.h), and must be
+// replicated in the same order in PhotoPickerFeatures.java.
+const base::Feature* kFeaturesExposedToJava[] = {
+ &kPhotoPickerVideoSupport,
+};
+
+} // namespace
+
const base::Feature kPhotoPickerVideoSupport{"PhotoPickerVideoSupport",
base::FEATURE_DISABLED_BY_DEFAULT};
+static jlong JNI_PhotoPickerFeatures_GetFeature(JNIEnv* env, jint ordinal) {
+ return reinterpret_cast<jlong>(kFeaturesExposedToJava[ordinal]);
+}
+
} // namespace features
} // namespace photo_picker
diff --git a/chromium/components/browser_ui/share/DIR_METADATA b/chromium/components/browser_ui/share/DIR_METADATA
index 3e064095c61..3593292b7f8 100644
--- a/chromium/components/browser_ui/share/DIR_METADATA
+++ b/chromium/components/browser_ui/share/DIR_METADATA
@@ -2,4 +2,3 @@ monorail {
component: "UI>Browser>Sharing"
}
-os: ANDROID
diff --git a/chromium/components/browser_ui/site_settings/android/BUILD.gn b/chromium/components/browser_ui/site_settings/android/BUILD.gn
index 985f66e88a8..2215eea6cbc 100644
--- a/chromium/components/browser_ui/site_settings/android/BUILD.gn
+++ b/chromium/components/browser_ui/site_settings/android/BUILD.gn
@@ -97,6 +97,7 @@ android_library("java") {
"//third_party/androidx:androidx_preference_preference_java",
"//ui/android:ui_full_java",
"//ui/android:ui_utils_java",
+ "//url:gurl_java",
]
srcjar_deps =
[ "//components/content_settings/android:java_pref_names_srcjar" ]
diff --git a/chromium/components/browser_ui/site_settings/android/features.cc b/chromium/components/browser_ui/site_settings/android/features.cc
index 763945be79a..1ea52af8734 100644
--- a/chromium/components/browser_ui/site_settings/android/features.cc
+++ b/chromium/components/browser_ui/site_settings/android/features.cc
@@ -9,10 +9,7 @@
namespace browser_ui {
-const base::Feature kAppNotificationStatusMessaging{
- "AppNotificationStatusMessaging", base::FEATURE_DISABLED_BY_DEFAULT};
-
const base::Feature kActionableContentSettings{
- "ActionableContentSettings", base::FEATURE_DISABLED_BY_DEFAULT};
+ "ActionableContentSettings", base::FEATURE_ENABLED_BY_DEFAULT};
} // namespace browser_ui
diff --git a/chromium/components/browser_ui/site_settings/android/features.h b/chromium/components/browser_ui/site_settings/android/features.h
index cf329bce641..f2376b6fe6a 100644
--- a/chromium/components/browser_ui/site_settings/android/features.h
+++ b/chromium/components/browser_ui/site_settings/android/features.h
@@ -11,9 +11,6 @@ struct Feature;
namespace browser_ui {
-// Enables messaging in the site settings UI to tell users notifications are
-// disabled for the entire app
-extern const base::Feature kAppNotificationStatusMessaging;
// Enables toggles and slash through diabled icons for content settings.
extern const base::Feature kActionableContentSettings;
diff --git a/chromium/components/browser_ui/site_settings/android/site_settings_feature_list.cc b/chromium/components/browser_ui/site_settings/android/site_settings_feature_list.cc
index 71f54922486..e7f9952506a 100644
--- a/chromium/components/browser_ui/site_settings/android/site_settings_feature_list.cc
+++ b/chromium/components/browser_ui/site_settings/android/site_settings_feature_list.cc
@@ -5,8 +5,6 @@
#include "base/android/jni_string.h"
#include "base/feature_list.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
-
#include "components/browser_ui/site_settings/android/features.h"
#include "components/browser_ui/site_settings/android/site_settings_jni_headers/SiteSettingsFeatureList_jni.h"
@@ -20,16 +18,15 @@ namespace {
// Array of features exposed through the Java ContentFeatureList API. Entries in
// this array may either refer to features defined in the header of this file or
// in other locations in the code base (e.g. content_features.h).
-const base::Feature* kFeaturesExposedToJava[] = {
- &kAppNotificationStatusMessaging,
+const base::Feature* const kFeaturesExposedToJava[] = {
&kActionableContentSettings,
};
// TODO(crbug.com/1060097): Remove this once a generalized FeatureList exists.
const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
- for (size_t i = 0; i < base::size(kFeaturesExposedToJava); ++i) {
- if (kFeaturesExposedToJava[i]->name == feature_name)
- return kFeaturesExposedToJava[i];
+ for (const base::Feature* feature : kFeaturesExposedToJava) {
+ if (feature->name == feature_name)
+ return feature;
}
NOTREACHED() << "Queried feature not found in SiteSettingsFeatureList: "
<< feature_name;
diff --git a/chromium/components/browser_ui/site_settings/android/storage_info_fetcher.cc b/chromium/components/browser_ui/site_settings/android/storage_info_fetcher.cc
index 14ff1dfe39c..aa68b455f24 100644
--- a/chromium/components/browser_ui/site_settings/android/storage_info_fetcher.cc
+++ b/chromium/components/browser_ui/site_settings/android/storage_info_fetcher.cc
@@ -18,8 +18,7 @@ using content::BrowserThread;
namespace browser_ui {
StorageInfoFetcher::StorageInfoFetcher(content::BrowserContext* context) {
- quota_manager_ = content::BrowserContext::GetDefaultStoragePartition(context)
- ->GetQuotaManager();
+ quota_manager_ = context->GetDefaultStoragePartition()->GetQuotaManager();
}
StorageInfoFetcher::~StorageInfoFetcher() = default;
diff --git a/chromium/components/browser_ui/site_settings/android/website_preference_bridge.cc b/chromium/components/browser_ui/site_settings/android/website_preference_bridge.cc
index f47be15d3dd..a5316d02726 100644
--- a/chromium/components/browser_ui/site_settings/android/website_preference_bridge.cc
+++ b/chromium/components/browser_ui/site_settings/android/website_preference_bridge.cc
@@ -31,7 +31,7 @@
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/embedder_support/android/browser_context/browser_context_handle.h"
-#include "components/permissions/chooser_context_base.h"
+#include "components/permissions/object_permission_context_base.h"
#include "components/permissions/permission_decision_auto_blocker.h"
#include "components/permissions/permission_manager.h"
#include "components/permissions/permission_uma_util.h"
@@ -255,7 +255,7 @@ void SetSettingForOrigin(JNIEnv* env,
content_settings::LogWebSiteSettingsPermissionChange(content_type, setting);
}
-permissions::ChooserContextBase* GetChooserContext(
+permissions::ObjectPermissionContextBase* GetChooserContext(
const JavaParamRef<jobject>& jbrowser_context_handle,
ContentSettingsType type) {
BrowserContext* browser_context = unwrap(jbrowser_context_handle);
@@ -471,10 +471,10 @@ static void JNI_WebsitePreferenceBridge_GetChosenObjects(
const JavaParamRef<jobject>& list) {
ContentSettingsType type =
static_cast<ContentSettingsType>(content_settings_type);
- permissions::ChooserContextBase* context =
+ permissions::ObjectPermissionContextBase* context =
GetChooserContext(jbrowser_context_handle, type);
- // The ChooserContextBase can be null if the embedder doesn't support the
- // given ContentSettingsType.
+ // The ObjectPermissionContextBase can be null if the embedder doesn't support
+ // the given ContentSettingsType.
if (!context)
return;
for (const auto& object : context->GetAllGrantedObjects()) {
@@ -514,7 +514,7 @@ static void JNI_WebsitePreferenceBridge_RevokeObjectPermission(
std::unique_ptr<base::DictionaryValue> object = base::DictionaryValue::From(
base::JSONReader::ReadDeprecated(ConvertJavaStringToUTF8(env, jobject)));
DCHECK(object);
- permissions::ChooserContextBase* context = GetChooserContext(
+ permissions::ObjectPermissionContextBase* context = GetChooserContext(
jbrowser_context_handle,
static_cast<ContentSettingsType>(content_settings_type));
context->RevokeObjectPermission(url::Origin::Create(origin), *object);
@@ -675,8 +675,7 @@ static void JNI_WebsitePreferenceBridge_ClearCookieData(
BrowserContext* browser_context = unwrap(jbrowser_context_handle);
GURL url(ConvertJavaStringToUTF8(env, jorigin));
- auto* storage_partition =
- content::BrowserContext::GetDefaultStoragePartition(browser_context);
+ auto* storage_partition = browser_context->GetDefaultStoragePartition();
auto* cookie_manager = storage_partition->GetCookieManagerForBrowserProcess();
cookie_manager->GetAllCookies(
base::BindOnce(&OnCookiesReceived, cookie_manager, url));
@@ -716,6 +715,15 @@ static jboolean JNI_WebsitePreferenceBridge_IsPermissionControlledByDSE(
url::Origin::Create(GURL(ConvertJavaStringToUTF8(env, jorigin))));
}
+static jboolean JNI_WebsitePreferenceBridge_IsDSEOrigin(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& jbrowser_context_handle,
+ const JavaParamRef<jstring>& jorigin) {
+ return permissions::PermissionsClient::Get()->IsDseOrigin(
+ unwrap(jbrowser_context_handle),
+ url::Origin::Create(GURL(ConvertJavaStringToUTF8(env, jorigin))));
+}
+
static jboolean JNI_WebsitePreferenceBridge_GetAdBlockingActivated(
JNIEnv* env,
const JavaParamRef<jobject>& jbrowser_context_handle,
diff --git a/chromium/components/browser_ui/sms/android/sms_infobar.h b/chromium/components/browser_ui/sms/android/sms_infobar.h
index 54ad4cf3fe5..c38a2679a5a 100644
--- a/chromium/components/browser_ui/sms/android/sms_infobar.h
+++ b/chromium/components/browser_ui/sms/android/sms_infobar.h
@@ -30,7 +30,7 @@ class SmsInfoBar : public infobars::ConfirmInfoBar {
~SmsInfoBar() override;
// Creates an SMS receiver infobar and delegate and adds it to
- // |infobar_service|.
+ // |infobar_manager|.
static void Create(content::WebContents* web_contents,
infobars::InfoBarManager* manager,
const std::vector<url::Origin>& origin_list,
diff --git a/chromium/components/browser_ui/sms/android/sms_infobar_delegate_unittest.cc b/chromium/components/browser_ui/sms/android/sms_infobar_delegate_unittest.cc
index 5bcdd8a4581..043ce266c23 100644
--- a/chromium/components/browser_ui/sms/android/sms_infobar_delegate_unittest.cc
+++ b/chromium/components/browser_ui/sms/android/sms_infobar_delegate_unittest.cc
@@ -12,34 +12,22 @@
#include "content/public/test/test_renderer_host.h"
namespace sms {
-namespace {
-
-class TestInfoBarManager : public infobars::ContentInfoBarManager {
- public:
- explicit TestInfoBarManager(content::WebContents* web_contents)
- : ContentInfoBarManager(web_contents) {}
-
- // infobars::InfoBarManager:
- std::unique_ptr<infobars::InfoBar> CreateConfirmInfoBar(
- std::unique_ptr<ConfirmInfoBarDelegate> delegate) override {
- return std::make_unique<infobars::InfoBar>(std::move(delegate));
- }
-};
-
-} // namespace
class SmsInfoBarDelegateTest : public content::RenderViewHostTestHarness {
public:
// content::RenderViewHostTestHarness:
void SetUp() override {
content::RenderViewHostTestHarness::SetUp();
- infobar_manager_ = std::make_unique<TestInfoBarManager>(web_contents());
+ infobar_manager_ =
+ std::make_unique<infobars::ContentInfoBarManager>(web_contents());
}
- TestInfoBarManager* infobar_manager() { return infobar_manager_.get(); }
+ infobars::ContentInfoBarManager* infobar_manager() {
+ return infobar_manager_.get();
+ }
private:
- std::unique_ptr<TestInfoBarManager> infobar_manager_;
+ std::unique_ptr<infobars::ContentInfoBarManager> infobar_manager_;
};
TEST_F(SmsInfoBarDelegateTest, InfoBarForSingleFrame) {
@@ -78,4 +66,4 @@ TEST_F(SmsInfoBarDelegateTest, InfoBarForEmbeddedFrame) {
expected_message);
}
-} // namespace sms \ No newline at end of file
+} // namespace sms
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings.grd b/chromium/components/browser_ui/strings/android/browser_ui_strings.grd
index 57a516b30c6..04731069bb3 100644
--- a/chromium/components/browser_ui/strings/android/browser_ui_strings.grd
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings.grd
@@ -174,67 +174,67 @@
<message name="IDS_DELETED" desc='Text that announces to the user that something was deleted.'>
Deleted
</message>
- <message name="IDS_OK" desc="Label for a confirm button. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_OK" desc="Label for a confirm button. Used in multiple contexts. [CHAR_LIMIT=20]">
OK
</message>
- <message name="IDS_OK_GOT_IT" desc="Label of a button by which the user confirms that they read and understood the information or instructions. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_OK_GOT_IT" desc="Label of a button by which the user confirms that they read and understood the information or instructions. Used in multiple contexts. [CHAR_LIMIT=20]">
OK, got it
</message>
- <message name="IDS_CANCEL" desc="Label for a cancel button. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_CANCEL" desc="Label for a cancel button. Used in multiple contexts. [CHAR_LIMIT=20]">
Cancel
</message>
- <message name="IDS_SAVE" desc="Label for a button to save a change. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_SAVE" desc="Label for a button to save a change. Used in multiple contexts. [CHAR_LIMIT=20]">
Save
</message>
<message name="IDS_DETAILS_LINK" desc="In 1) Settings > Clean up computer (desktop), a link to open details of incompatible applications. In 2) Settings > Lite mode (mobile), static title for data usage breakdown." meaning="Short for 'view details'. Link; static title.">
Details
</message>
- <message name="IDS_CHANGE_LINK" desc="Any link text giving option to the user to edit some settings. [CHAR-LIMIT=20]">
+ <message name="IDS_CHANGE_LINK" desc="Any link text giving option to the user to edit some settings. [CHAR_LIMIT=20]">
Change
</message>
- <message name="IDS_DONE" desc="Label for a button to save a change or finish editing data. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_DONE" desc="Label for a button to save a change or finish editing data. Used in multiple contexts. [CHAR_LIMIT=20]">
Done
</message>
- <message name="IDS_DELETE" desc="Label for a delete button. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_DELETE" desc="Label for a delete button. Used in multiple contexts. [CHAR_LIMIT=20]">
Delete
</message>
- <message name="IDS_REMOVE" desc="Label for a button to remove an item (e.g. a bookmark) from a list. [CHAR-LIMIT=20]">
+ <message name="IDS_REMOVE" desc="Label for a button to remove an item (e.g. a bookmark) from a list. [CHAR_LIMIT=20]">
Remove
</message>
<message name="IDS_RESET" desc="Label for a button to reset information you are editing to a default.">
Reset
</message>
- <message name="IDS_TITLE" desc="Text indicating the title of a button or a textfield. Ued in multiple contexts. [CHAR-LIMIT=32]">
+ <message name="IDS_TITLE" desc="Text indicating the title of a button or a textfield. Ued in multiple contexts. [CHAR_LIMIT=32]">
Title
</message>
- <message name="IDS_TEXT_ON" desc="Text indicating that an option is turned on. [CHAR-LIMIT=20]">
+ <message name="IDS_TEXT_ON" desc="Text indicating that an option is turned on. [CHAR_LIMIT=20]">
On
</message>
- <message name="IDS_TEXT_OFF" desc="Text indicating that an option is turned off. [CHAR-LIMIT=20]">
+ <message name="IDS_TEXT_OFF" desc="Text indicating that an option is turned off. [CHAR_LIMIT=20]">
Off
</message>
- <message name="IDS_LEARN_MORE" desc="Generic label for menu item to learn more about a feature. [CHAR-LIMIT=32]">
+ <message name="IDS_LEARN_MORE" desc="Generic label for menu item to learn more about a feature. [CHAR_LIMIT=32]">
Learn more
</message>
- <message name="IDS_MORE" desc="Generic label for a button to show more items or options. [CHAR-LIMIT=20]">
+ <message name="IDS_MORE" desc="Generic label for a button to show more items or options. [CHAR_LIMIT=20]">
More
</message>
<message name="IDS_CLOSE" desc="Content description for a button to close a dialog or popup" >
Close
</message>
- <message name="IDS_RELOAD" desc="Label for a button that reloads the page. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_RELOAD" desc="Label for a button that reloads the page. Used in multiple contexts. [CHAR_LIMIT=20]">
Reload
</message>
- <message name="IDS_NO_THANKS" desc="Generic label to say no thanks for a feature. [CHAR-LIMIT=32]">
+ <message name="IDS_NO_THANKS" desc="Generic label to say no thanks for a feature. [CHAR_LIMIT=32]">
No thanks
</message>
- <message name="IDS_NEXT" desc="Generic label for a button to advance to the next item. [CHAR-LIMIT=20]">
+ <message name="IDS_NEXT" desc="Generic label for a button to advance to the next item. [CHAR_LIMIT=20]">
Next
</message>
- <message name="IDS_CONTINUE_BUTTON" desc="Generic label for a button to continue to the next screen. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_CONTINUE_BUTTON" desc="Generic label for a button to continue to the next screen. Used in multiple contexts. [CHAR_LIMIT=20]">
Continue
</message>
- <message name="IDS_SUBMIT" desc="Generic label for a button to submit data. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_SUBMIT" desc="Generic label for a button to submit data. Used in multiple contexts. [CHAR_LIMIT=20]">
Submit
</message>
<message name="IDS_UNDO" desc="Generic label for a button to undo the previous action.">
@@ -249,16 +249,16 @@
<message name="IDS_YESTERDAY" desc="Generic Label saying the date is yesterday.">
Yesterday
</message>
- <message name="IDS_SELECT" desc="Prompt for user to select something. [CHAR-LIMIT=20]">
+ <message name="IDS_SELECT" desc="Prompt for user to select something. [CHAR_LIMIT=20]">
Select
</message>
- <message name="IDS_ADD" desc="Prompt for the user to add something, like a new address. [CHAR-LIMIT=20]">
+ <message name="IDS_ADD" desc="Prompt for the user to add something, like a new address. [CHAR_LIMIT=20]">
Add
</message>
- <message name="IDS_CHANGE" desc="Prompt for the user to change something. [CHAR-LIMIT=20]">
+ <message name="IDS_CHANGE" desc="Prompt for the user to change something. [CHAR_LIMIT=20]">
Change
</message>
- <message name="IDS_SHARE" desc="Content description for a button to share item(s). [CHAR-LIMIT=20]">
+ <message name="IDS_SHARE" desc="Content description for a button to share item(s). [CHAR_LIMIT=20]">
Share
</message>
<message name="IDS_SEARCH" desc="The label for a search button.">
@@ -270,34 +270,34 @@
<message name="IDS_HIDE_INFO" desc="The label for a info button to hide info.">
Hide Info
</message>
- <message name="IDS_COPY_LINK" desc="The label for a menu item to copy a link. [CHAR-LIMIT=30]">
+ <message name="IDS_COPY_LINK" desc="The label for a menu item to copy a link. [CHAR_LIMIT=30]">
Copy link
</message>
<message name="IDS_COPIED" desc="Notification telling the user that something has been copied to the clipboard.">
Copied
</message>
- <message name="IDS_TRY_AGAIN" desc="The label for a button allowing the user to try an action again. [CHAR-LIMIT=20]">
+ <message name="IDS_TRY_AGAIN" desc="The label for a button allowing the user to try an action again. [CHAR_LIMIT=20]">
Try again
</message>
- <message name="IDS_BACK" desc="Label for a back button to return to a previous UI state or screen. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_BACK" desc="Label for a back button to return to a previous UI state or screen. Used in multiple contexts. [CHAR_LIMIT=20]">
Back
</message>
- <message name="IDS_CONFIRM" desc="Label for a confirm button. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_CONFIRM" desc="Label for a confirm button. Used in multiple contexts. [CHAR_LIMIT=20]">
Confirm
</message>
- <message name="IDS_SHOW" desc="Label for a show button. Used in multiple contexts. [CHAR-LIMIT=20]">
+ <message name="IDS_SHOW" desc="Label for a show button. Used in multiple contexts. [CHAR_LIMIT=20]">
Show
</message>
<message name="IDS_USER" desc="Generic label for UI elements with information about user.">
User
</message>
- <message name="IDS_MENU_ITEM_MOVE_UP" desc="Option in item menu. User can click the 'Move up' option to move the item up by one position in its list. [CHAR-LIMIT=24]">
+ <message name="IDS_MENU_ITEM_MOVE_UP" desc="Option in item menu. User can click the 'Move up' option to move the item up by one position in its list. [CHAR_LIMIT=24]">
Move up
</message>
- <message name="IDS_MENU_ITEM_MOVE_DOWN" desc="Option in item menu. User can click the 'Move down' option to move the item down by one position in its list. [CHAR-LIMIT=24]">
+ <message name="IDS_MENU_ITEM_MOVE_DOWN" desc="Option in item menu. User can click the 'Move down' option to move the item down by one position in its list. [CHAR_LIMIT=24]">
Move down
</message>
- <message name="IDS_MENU_ITEM_MOVE_TO_TOP" desc="Option in item menu. User can click the 'Move to top' option to move the item up to the top of its list. [CHAR-LIMIT=24]">
+ <message name="IDS_MENU_ITEM_MOVE_TO_TOP" desc="Option in item menu. User can click the 'Move to top' option to move the item up to the top of its list. [CHAR_LIMIT=24]">
Move to top
</message>
<message name="IDS_JUST_ONCE" desc="Generic label for a user to select an option for just once">
@@ -364,7 +364,7 @@
</message>
<!-- Certificate viewer -->
- <message name="IDS_CERTTITLE" desc="Dialog box title for viewing security certificates. [CHAR-LIMIT=32]">
+ <message name="IDS_CERTTITLE" desc="Dialog box title for viewing security certificates. [CHAR_LIMIT=32]">
Certificate viewer
</message>
@@ -387,7 +387,7 @@
<message name="IDS_ACCESSIBILITY_COLLAPSED_GROUP" desc="The accessibility text to read when the selected widget is collapsed.">
Collapsed - click to expand.
</message>
- <message name="IDS_MENU_HELP" desc="Menu item for opening the help page. [CHAR-LIMIT=27]">
+ <message name="IDS_MENU_HELP" desc="Menu item for opening the help page. [CHAR_LIMIT=27]">
Help &amp; feedback
</message>
<message name="IDS_AUTOMATICALLY_BLOCKED" desc="Description displayed next to an origin when it was placed under embargo by Chrome. This indicates to the user that the origin is blocked automatically instead of being the result of the user's decision.">
@@ -506,9 +506,6 @@
<message name="IDS_PAGE_INFO_INSTANT_APP_BUTTON" desc="Text in the button that opens an Android Instant app that is associated with the website's URL.">
Open Instant App
</message>
- <message name="IDS_PAGE_INFO_PREVIEW_MESSAGE" desc="This text is displayed in the page info bubble when the currently viewed page has been modified by Google to be a lighter and faster version of the original page. The word 'Lite' should match the translation in TC ID 1019734090540434451">
- Lite page provided by Google
- </message>
<message name="IDS_PAGE_INFO_LITE_MODE_HTTPS_IMAGE_COMPRESSION" desc="This text is displayed in the page info bubble when the currently viewed page has https images that were optimized by Google">
To save you data, this page's images have been optimized by Google.
</message>
@@ -518,9 +515,6 @@
<message name="IDS_PAGE_INFO_SITE_SETTINGS_BUTTON" desc="Text in the button that opens a website's Site Settings from the Page Info dialog.">
Site settings
</message>
- <message name="IDS_PAGE_INFO_FAST_SITE_SUMMARY" desc="A short summary phrase in the Page Info bubble (which shows when you click the lock icon) that indicates that pages on the current website should load quickly.">
- Site is fast
- </message>
<message name="IDS_PAGE_INFO_COOKIES_CLEAR" desc="Text on the button to clear cookies for a site.">
Clear cookies
</message>
@@ -541,9 +535,6 @@
=1 {1 cookie in use}
other {# cookies in use}}
</message>
- <message name="IDS_PAGE_INFO_FAST_SITE_MESSAGE" desc="A short paragraph that explains what is meant by labeling the current website as fast.">
- This site opens and responds quickly for most people
- </message>
<message name="IDS_PAGE_INFO_ANDROID_LOCATION_BLOCKED" desc="The label used in the Page Info dialog to indicate that location has been been disabled for the device in Android settings">
Turned off for this device
</message>
@@ -556,18 +547,6 @@
<message name="IDS_PAGE_INFO_ANDROID_AR_CAMERA_BLOCKED" desc="The label used in the Page Info dialog for the AR permission to indicate that Camera has been disabled for the device in Android settings">
Camera is turned off in Android settings
</message>
- <message name="IDS_PAGE_INFO_PERMISSION_ALLOWED" desc="The label used in the Page Info dialog to describe an allowed permission. Eg: Location - Allowed">
- Allowed
- </message>
- <message name="IDS_PAGE_INFO_PERMISSION_BLOCKED" desc="The label used in the Page Info dialog to describe a blocked permission. Eg: Location - Blocked">
- Blocked
- </message>
- <message name="IDS_PAGE_INFO_DSE_PERMISSION_ALLOWED" desc="The label used in the Page Info dialog to describe an allowed location permission for the current search engine. Eg: Location - Allowed for current search engine">
- Allowed for current search engine
- </message>
- <message name="IDS_PAGE_INFO_DSE_PERMISSION_BLOCKED" desc="The label used in the Page Info dialog to describe a blocked location permission for the current search engine. Eg: Location - Blocked for current search engine">
- Blocked for current search engine
- </message>
<message name="IDS_PAGE_INFO_URL_EXPANDED" desc="Accessibility announcement when the URL in PageInfo switches from truncated to full display">
URL expanded
</message>
@@ -575,7 +554,7 @@
URL truncated
</message>
- <message name="IDS_COOKIES_TITLE" desc="Title for the Cookies settings screen [CHAR-LIMIT=32]">
+ <message name="IDS_COOKIES_TITLE" desc="Title for the Cookies settings screen [CHAR_LIMIT=32]">
Cookies
</message>
<message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_SITE_INFO" desc="Content description for the page icon that gives more site information when clicked. The icon can be a magnifier for search result pages, or other icons representing the page state.">
@@ -598,32 +577,32 @@
<message name="IDS_MEDIA_CAPTURE_NOTIFICATION_CONTENT_TEXT" desc="Url of the current tab. The notification will display this text for the user to identify the tab to return to.">
Tap to return to <ph name="URL_OF_THE_CURRENT_TAB">%1$s<ex>https://apprtc.appspot.com</ex></ph>
</message>
- <message name="IDS_MEDIA_CAPTURE_NOTIFICATION_CONTENT_TEXT_INCOGNITO" desc="The notification will display this text for the user to return to the incognito tab which has created the notification.">
+ <message name="IDS_MEDIA_CAPTURE_NOTIFICATION_CONTENT_TEXT_INCOGNITO" desc="The notification will display this text for the user to return to the Incognito tab which has created the notification.">
Tap to return to the site
</message>
<message name="IDS_ACCESSIBILITY_STOP" desc="Accessible name for a button that stops playing or recording media.">
Stop
</message>
- <message name="IDS_NOTIFICATION_INCOGNITO_TAB" desc="Text used as notifications source when the notification is from incognito tabs.">
+ <message name="IDS_NOTIFICATION_INCOGNITO_TAB" desc="Text used as notifications source when the notification is from Incognito tabs.">
Incognito tab
</message>
- <message name="IDS_NOTIFICATION_CATEGORY_COMPLETED_DOWNLOADS" desc="Label for completed download notifications, within a list of notification categories. [CHAR-LIMIT=32]">
+ <message name="IDS_NOTIFICATION_CATEGORY_COMPLETED_DOWNLOADS" desc="Label for completed download notifications, within a list of notification categories. [CHAR_LIMIT=32]">
Completed downloads
</message>
- <message name="IDS_NOTIFICATION_CATEGORY_DOWNLOADS" desc="Label for notifications shown when something is downloading, within a list of notification categories. [CHAR-LIMIT=32]">
+ <message name="IDS_NOTIFICATION_CATEGORY_DOWNLOADS" desc="Label for notifications shown when something is downloading, within a list of notification categories. [CHAR_LIMIT=32]">
Active downloads
</message>
- <message name="IDS_NOTIFICATION_CATEGORY_MEDIA_PLAYBACK" desc="Label for media playback notifications, within a list of notification categories. [CHAR-LIMIT=32]">
+ <message name="IDS_NOTIFICATION_CATEGORY_MEDIA_PLAYBACK" desc="Label for media playback notifications, within a list of notification categories. [CHAR_LIMIT=32]">
Playing media
</message>
- <message name="IDS_NOTIFICATION_CATEGORY_WEBRTC_CAM_AND_MIC" desc="Label for notifications shown when media is being recorded from a camera or microphone, within a list of notification categories. [CHAR-LIMIT=32]">
+ <message name="IDS_NOTIFICATION_CATEGORY_WEBRTC_CAM_AND_MIC" desc="Label for notifications shown when media is being recorded from a camera or microphone, within a list of notification categories. [CHAR_LIMIT=32]">
Camera and microphone use
</message>
<message name="IDS_SCREEN_CAPTURE_NOTIFICATION_TITLE" desc="Text to be shown as a notification when screen capture is in progress.">
Sharing your screen
</message>
- <message name="IDS_SHARE_LINK_CHOOSER_TITLE" desc="title for the share dialog when sharing the current address [CHAR-LIMIT=27]">
+ <message name="IDS_SHARE_LINK_CHOOSER_TITLE" desc="title for the share dialog when sharing the current address [CHAR_LIMIT=27]">
Share via
</message>
@@ -646,7 +625,7 @@
<message name="IDS_ACCESSIBILITY_SEEK_BACKWARD" desc="The seek backward button that seeks media to an earlier position.">
Seek backward
</message>
- <message name="IDS_MEDIA_NOTIFICATION_INCOGNITO" desc="Text used as a placeholder for a media notification about playing media, when notification is shown from incognito tab.">
+ <message name="IDS_MEDIA_NOTIFICATION_INCOGNITO" desc="Text used as a placeholder for a media notification about playing media, when notification is shown from Incognito tab.">
A site is playing media
</message>
@@ -668,17 +647,17 @@
Options available near bottom of the screen
</message>
- <!-- Warning on sharing info with external apps in incognito mode -->
- <message name="IDS_EXTERNAL_APP_LEAVE_INCOGNITO_WARNING" desc="Alert dialog text warning the user (who is currently in incognito mode) that the site they are currently using is going to share data with an external application." formatter_data="android_java">
- This site is about to share information with an app outside of incognito mode.
+ <!-- Warning on sharing info with external apps in Incognito mode -->
+ <message name="IDS_EXTERNAL_APP_LEAVE_INCOGNITO_WARNING" desc="Alert dialog text warning the user (who is currently in Incognito mode) that the site they are currently using is going to share data with an external application." formatter_data="android_java">
+ This site is about to share information with an app outside of Incognito mode.
</message>
- <message name="IDS_EXTERNAL_APP_LEAVE_INCOGNITO_WARNING_TITLE" desc="Title for dialog asking if the user wants to leave incognito mode. [CHAR-LIMIT=32]" formatter_data="android_java">
- Leave incognito mode?
+ <message name="IDS_EXTERNAL_APP_LEAVE_INCOGNITO_WARNING_TITLE" desc="Title for dialog asking if the user wants to leave Incognito mode. [CHAR_LIMIT=32]" formatter_data="android_java">
+ Leave Incognito mode?
</message>
- <message name="IDS_EXTERNAL_APP_LEAVE_INCOGNITO_STAY" desc="Label for the dialog button to stay in incognito mode. [CHAR-LIMIT=20]" formatter_data="android_java">
+ <message name="IDS_EXTERNAL_APP_LEAVE_INCOGNITO_STAY" desc="Label for the dialog button to stay in Incognito mode. [CHAR_LIMIT=20]" formatter_data="android_java">
Stay
</message>
- <message name="IDS_EXTERNAL_APP_LEAVE_INCOGNITO_LEAVE" desc="Label for the dialog button to leave incognito mode. [CHAR-LIMIT=20]" formatter_data="android_java">
+ <message name="IDS_EXTERNAL_APP_LEAVE_INCOGNITO_LEAVE" desc="Label for the dialog button to leave Incognito mode. [CHAR_LIMIT=20]" formatter_data="android_java">
Leave
</message>
@@ -783,6 +762,38 @@
Drag from top and touch the back button to exit full screen.
</message>
+ <!-- WebApk name/icon update dialog -->
+ <message name="IDS_WEBAPK_UPDATE_DIALOG_TITLE_NAME" desc="The title at the top of the dialog when only the name changed.">
+ Update name on your homescreen?
+ </message>
+ <message name="IDS_WEBAPK_UPDATE_DIALOG_TITLE_ICON" desc="The title at the top of the dialog when only the icon changed.">
+ Update icon on your homescreen?
+ </message>
+ <message name="IDS_WEBAPK_UPDATE_DIALOG_TITLE_NAME_AND_ICON" desc="The title at the top of the dialog when the name and icon changed.">
+ Update name &amp; icon on your homescreen?
+ </message>
+ <message name="IDS_WEBAPK_UPDATE_EXPLANATION_NAME" desc="The text at the top of the dialog, explaining that an app has changed its name.">
+ A web app that you installed has changed its name.
+ </message>
+ <message name="IDS_WEBAPK_UPDATE_EXPLANATION_ICON" desc="The text at the top of the dialog, explaining that an app has changed its icon.">
+ A web app that you installed has changed its icon.
+ </message>
+ <message name="IDS_WEBAPK_UPDATE_EXPLANATION_NAME_AND_ICON" desc="The text at the top of the dialog, explaining that an app has changed its name and icon.">
+ A web app that you installed has changed its name and icon.
+ </message>
+ <message name="IDS_WEBAPK_UPDATE_BUTTON_UPDATE" desc="The text in the confirm button that starts an update of the WebApk.">
+ Update
+ </message>
+ <message name="IDS_WEBAPK_UPDATE_BUTTON_CLOSE" desc="The text for the cancel button, allowing the user to close and report the app to the abuse team.">
+ Close and report abuse
+ </message>
+ <message name="IDS_UPDATE_WEBAPK_CURRENT_ICON" desc="The accessibility string explaining which icon is the current icon.">
+ Current icon
+ </message>
+ <message name="IDS_UPDATE_WEBAPK_UPDATED_ICON" desc="The accessibility string explaining which icon is the new icon.">
+ New icon
+ </message>
+
<!-- Messages -->
<message name="IDS_MESSAGE_SCREEN_POSITION" desc="Accessibility label to inform users about the Message location">
Option available near top of the screen
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_FAST_SITE_MESSAGE.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_FAST_SITE_MESSAGE.png.sha1
deleted file mode 100644
index 7bcd7884fd0..00000000000
--- a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_FAST_SITE_MESSAGE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-beb4e1ece71346f8fc006b16a1ad5ce880167cfb \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_FAST_SITE_SUMMARY.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_FAST_SITE_SUMMARY.png.sha1
deleted file mode 100644
index 7bcd7884fd0..00000000000
--- a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_PAGE_INFO_FAST_SITE_SUMMARY.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-beb4e1ece71346f8fc006b16a1ad5ce880167cfb \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_UPDATE_WEBAPK_CURRENT_ICON.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_UPDATE_WEBAPK_CURRENT_ICON.png.sha1
new file mode 100644
index 00000000000..abbd7ffc9d5
--- /dev/null
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_UPDATE_WEBAPK_CURRENT_ICON.png.sha1
@@ -0,0 +1 @@
+486cf2f888e86268022ae78cfcafce0e77d8fb81 \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_UPDATE_WEBAPK_UPDATED_ICON.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_UPDATE_WEBAPK_UPDATED_ICON.png.sha1
new file mode 100644
index 00000000000..abbd7ffc9d5
--- /dev/null
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_UPDATE_WEBAPK_UPDATED_ICON.png.sha1
@@ -0,0 +1 @@
+486cf2f888e86268022ae78cfcafce0e77d8fb81 \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_BUTTON_CLOSE.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_BUTTON_CLOSE.png.sha1
new file mode 100644
index 00000000000..abbd7ffc9d5
--- /dev/null
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_BUTTON_CLOSE.png.sha1
@@ -0,0 +1 @@
+486cf2f888e86268022ae78cfcafce0e77d8fb81 \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_BUTTON_UPDATE.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_BUTTON_UPDATE.png.sha1
new file mode 100644
index 00000000000..abbd7ffc9d5
--- /dev/null
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_BUTTON_UPDATE.png.sha1
@@ -0,0 +1 @@
+486cf2f888e86268022ae78cfcafce0e77d8fb81 \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_ICON.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_ICON.png.sha1
new file mode 100644
index 00000000000..3a9ed5a2290
--- /dev/null
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_ICON.png.sha1
@@ -0,0 +1 @@
+f827a1c422903ccb691056fe1de1820dce493b41 \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_NAME.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_NAME.png.sha1
new file mode 100644
index 00000000000..09fc14ae058
--- /dev/null
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_NAME.png.sha1
@@ -0,0 +1 @@
+caa7951c95ac81e521d62554104f2595c1812d85 \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_NAME_AND_ICON.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_NAME_AND_ICON.png.sha1
new file mode 100644
index 00000000000..abbd7ffc9d5
--- /dev/null
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_DIALOG_TITLE_NAME_AND_ICON.png.sha1
@@ -0,0 +1 @@
+486cf2f888e86268022ae78cfcafce0e77d8fb81 \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_ICON.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_ICON.png.sha1
new file mode 100644
index 00000000000..3a9ed5a2290
--- /dev/null
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_ICON.png.sha1
@@ -0,0 +1 @@
+f827a1c422903ccb691056fe1de1820dce493b41 \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_NAME.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_NAME.png.sha1
new file mode 100644
index 00000000000..09fc14ae058
--- /dev/null
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_NAME.png.sha1
@@ -0,0 +1 @@
+caa7951c95ac81e521d62554104f2595c1812d85 \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_NAME_AND_ICON.png.sha1 b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_NAME_AND_ICON.png.sha1
new file mode 100644
index 00000000000..abbd7ffc9d5
--- /dev/null
+++ b/chromium/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_WEBAPK_UPDATE_EXPLANATION_NAME_AND_ICON.png.sha1
@@ -0,0 +1 @@
+486cf2f888e86268022ae78cfcafce0e77d8fb81 \ No newline at end of file
diff --git a/chromium/components/browser_ui/strings/android/site_settings.grdp b/chromium/components/browser_ui/strings/android/site_settings.grdp
index 2ffa99d93cd..0670d449c08 100644
--- a/chromium/components/browser_ui/strings/android/site_settings.grdp
+++ b/chromium/components/browser_ui/strings/android/site_settings.grdp
@@ -1,24 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
<!-- Site settings top level entry -->
- <message name="IDS_PREFS_SITE_SETTINGS" desc="Title of the Website Settings screen. [CHAR-LIMIT=32]">
+ <message name="IDS_PREFS_SITE_SETTINGS" desc="Title of the Website Settings screen. [CHAR_LIMIT=32]">
Site settings
</message>
<!-- Site settings categories -->
- <message name="IDS_ALL_SITES" desc='Title of the "All sites" settings screen that allows the user to see permissions for all websites. [CHAR-LIMIT=32]'>
+ <message name="IDS_ALL_SITES" desc='Title of the "All sites" settings screen that allows the user to see permissions for all websites. [CHAR_LIMIT=32]'>
All sites
</message>
- <message name="IDS_ADS_PERMISSION_TITLE" desc="Title for the ads permission [CHAR-LIMIT=32]">
+ <message name="IDS_ADS_PERMISSION_TITLE" desc="Title for the ads permission [CHAR_LIMIT=32]">
Ads
</message>
- <message name="IDS_AR_PERMISSION_TITLE" desc="Title of the permission to use Augmented Reality [CHAR-LIMIT=32]">
+ <message name="IDS_AR_PERMISSION_TITLE" desc="Title of the permission to use Augmented Reality [CHAR_LIMIT=32]">
Augmented reality
</message>
<message name="IDS_AUTOMATIC_DOWNLOADS_PERMISSION_TITLE" desc="Title of the permission that allows websites to download multiple files automatically.">
Automatic downloads
</message>
- <message name="IDS_BACKGROUND_SYNC_PERMISSION_TITLE" desc="Title of the permission that allows websites to queue an operation for the next time the device is online[CHAR-LIMIT=32]">
+ <message name="IDS_BACKGROUND_SYNC_PERMISSION_TITLE" desc="Title of the permission that allows websites to queue an operation for the next time the device is online[CHAR_LIMIT=32]">
Background sync
</message>
<message name="IDS_WEBSITE_SETTINGS_BLUETOOTH_SCANNING" desc="Title for Bluetooth scanning settings, which control whether websites can do Bluetooth scanning.">
@@ -27,13 +27,13 @@
<message name="IDS_WEBSITE_SETTINGS_USE_CAMERA" desc="The category filter 'Camera' for site settings.">
Camera
</message>
- <message name="IDS_CLIPBOARD_PERMISSION_TITLE" desc="Title of the permission to read from clipboard [CHAR-LIMIT=32]">
+ <message name="IDS_CLIPBOARD_PERMISSION_TITLE" desc="Title of the permission to read from clipboard [CHAR_LIMIT=32]">
Clipboard
</message>
- <message name="IDS_WEBSITE_SETTINGS_IDLE_DETECTION" desc="Title of the permission to detect user activity [CHAR-LIMIT=32]">
+ <message name="IDS_WEBSITE_SETTINGS_IDLE_DETECTION" desc="Title of the permission to detect user activity [CHAR_LIMIT=32]">
Your device use
</message>
- <message name="IDS_JAVASCRIPT_PERMISSION_TITLE" desc="Title of the permission to run javascript [CHAR-LIMIT=32]">
+ <message name="IDS_JAVASCRIPT_PERMISSION_TITLE" desc="Title of the permission to run javascript [CHAR_LIMIT=32]">
JavaScript
</message>
<message name="IDS_WEBSITE_SETTINGS_DEVICE_LOCATION" desc="Title for Location settings, which control which websites can access your location." meaning="Geolocation">
@@ -42,31 +42,31 @@
<message name="IDS_WEBSITE_SETTINGS_USE_MIC" desc="The category filter 'Mic' for site settings.">
Microphone
</message>
- <message name="IDS_MIDI_SYSEX_PERMISSION_TITLE" desc="Title of the permission that allows a website to get full control of MIDI devices [CHAR-LIMIT=32]">
+ <message name="IDS_MIDI_SYSEX_PERMISSION_TITLE" desc="Title of the permission that allows a website to get full control of MIDI devices [CHAR_LIMIT=32]">
Allow full control of MIDI devices
</message>
- <message name="IDS_MOTION_SENSORS_PERMISSION_TITLE" desc="Title of the permission to use device's motion sensors (accelerometer, gyroscope, magnetometer) [CHAR-LIMIT=32]">
+ <message name="IDS_MOTION_SENSORS_PERMISSION_TITLE" desc="Title of the permission to use device's motion sensors (accelerometer, gyroscope, magnetometer) [CHAR_LIMIT=32]">
Motion sensors
</message>
- <message name="IDS_SENSORS_PERMISSION_TITLE" desc="Title of the permission to use device's sensors [CHAR-LIMIT=32]">
+ <message name="IDS_SENSORS_PERMISSION_TITLE" desc="Title of the permission to use device's sensors [CHAR_LIMIT=32]">
Motion or light sensors
</message>
- <message name="IDS_NFC_PERMISSION_TITLE" desc="Title of the permission to use NFC [CHAR-LIMIT=32]">
+ <message name="IDS_NFC_PERMISSION_TITLE" desc="Title of the permission to use NFC [CHAR_LIMIT=32]">
NFC devices
</message>
- <message name="IDS_PUSH_NOTIFICATIONS_PERMISSION_TITLE" desc="Title for the permission for showing push notifications [CHAR-LIMIT=32]">
+ <message name="IDS_PUSH_NOTIFICATIONS_PERMISSION_TITLE" desc="Title for the permission for showing push notifications [CHAR_LIMIT=32]">
Notifications
</message>
- <message name="IDS_POPUP_PERMISSION_TITLE" desc="Title of the permission to display pop-up windows and redirects [CHAR-LIMIT=32]">
+ <message name="IDS_POPUP_PERMISSION_TITLE" desc="Title of the permission to display pop-up windows and redirects [CHAR_LIMIT=32]">
Pop-ups and redirects
</message>
- <message name="IDS_PROTECTED_CONTENT" desc="Title for link to protected content settings [CHAR-LIMIT=32]">
+ <message name="IDS_PROTECTED_CONTENT" desc="Title for link to protected content settings [CHAR_LIMIT=32]">
Protected content
</message>
- <message name="IDS_SOUND_PERMISSION_TITLE" desc="Title of the permission to play sound [CHAR-LIMIT=32]">
+ <message name="IDS_SOUND_PERMISSION_TITLE" desc="Title of the permission to play sound [CHAR_LIMIT=32]">
Sound
</message>
- <message name="IDS_VR_PERMISSION_TITLE" desc="Title of the permission to use Virtual Reality [CHAR-LIMIT=32]">
+ <message name="IDS_VR_PERMISSION_TITLE" desc="Title of the permission to use Virtual Reality [CHAR_LIMIT=32]">
Virtual reality
</message>
@@ -188,7 +188,7 @@
<message name="IDS_WEBSTORAGE_CLEAR_DATA_DIALOG_TITLE" desc="Title of the confirmation dialog when the user ask to clear all data for an origin">
Clear site data?
</message>
- <message name="IDS_WEBSTORAGE_CLEAR_DATA_DIALOG_OK_BUTTON" desc="Button confirming site data cleanup [CHAR-LIMIT=20]">
+ <message name="IDS_WEBSTORAGE_CLEAR_DATA_DIALOG_OK_BUTTON" desc="Button confirming site data cleanup [CHAR_LIMIT=20]">
Clear
</message>
<message name="IDS_WEBSTORAGE_CLEAR_DATA_DIALOG_MESSAGE_SINGLE" desc="Text of the confirmation dialog when the user asks to clear all data (and app) for a single origin">
@@ -212,7 +212,7 @@
<message name="IDS_WEBSTORAGE_CLEAR_DATA_DIALOG_SIGN_OUT_ALL_MESSAGE" desc="Text of the confirmation dialog, explaining that the user will be signed out of all sites being cleared.">
You'll be signed out of all sites.
</message>
- <message name="IDS_STORAGE_CLEAR_SITE_STORAGE_TITLE" desc="Title of clear storage dialogs used in a couple different places to confirm clearing site storage data. [CHAR-LIMIT=24]">
+ <message name="IDS_STORAGE_CLEAR_SITE_STORAGE_TITLE" desc="Title of clear storage dialogs used in a couple different places to confirm clearing site storage data. [CHAR_LIMIT=24]">
Clear site data?
</message>
<message name="IDS_STORAGE_CLEAR_DIALOG_CLEAR_STORAGE_OPTION" desc="Text of the button that will clear website storage.">
@@ -316,7 +316,7 @@
<message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_ALLOW_TITLE" desc="Text used to explain the allow cookies option in settings">
Allow cookies
</message>
- <message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_BLOCK_THIRD_PARTY_INCOGNITO_TITLE" desc="Text used to explain the block third-party cookies in incognito option in settings">
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_BLOCK_THIRD_PARTY_INCOGNITO_TITLE" desc="Text used to explain the block third-party cookies in Incognito option in settings">
Block third-party cookies in Incognito
</message>
<message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_BLOCK_THIRD_PARTY_TITLE" desc="Text used to explain the block third-party cookies option in settings">
@@ -489,7 +489,7 @@
<!-- Storage -->
- <message name="IDS_WEBSITE_SETTINGS_STORAGE" desc="Title for Storage settings which show how much data websites are storing on the user's device. [CHAR-LIMIT=32]">
+ <message name="IDS_WEBSITE_SETTINGS_STORAGE" desc="Title for Storage settings which show how much data websites are storing on the user's device. [CHAR_LIMIT=32]">
Data stored
</message>
<message name="IDS_NO_SAVED_WEBSITE_SETTINGS" desc="Text to display when there are no saved website settings.">
@@ -498,7 +498,7 @@
<message name="IDS_ORIGIN_SETTINGS_STORAGE_USAGE_BRIEF" desc="Explanation of how much local storage a website is using">
<ph name="STORAGE_AMOUNT">%1$s<ex>2 MB</ex></ph> stored data
</message>
- <message name="IDS_STORAGE_CLEAR_BUTTON_TITLE" desc="Title of a button in the storage UI used to clear all storage data. [CHAR-LIMIT=24]">
+ <message name="IDS_STORAGE_CLEAR_BUTTON_TITLE" desc="Title of a button in the storage UI used to clear all storage data. [CHAR_LIMIT=24]">
Clear all data
</message>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_af.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_af.xtb
index 50c35c43060..7253d2841f6 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_af.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_af.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="af">
<translation id="1006017844123154345">Maak aanlyn oop</translation>
<translation id="1044891598689252897">Werwe sal normaalweg werk</translation>
+<translation id="1100504063505580045">Huidige ikoon</translation>
<translation id="1124090076051167250">Dit sal <ph name="DATASIZE" /> se data en webkoekies uitvee wat deur werwe of deur programme op jou tuisskerm geberg is.</translation>
<translation id="1124772482545689468">Gebruiker</translation>
<translation id="1178581264944972037">Laat wag</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofoon</translation>
<translation id="3277252321222022663">Laat werwe toegang tot sensors toe (aanbeveel)</translation>
<translation id="3295602654194328831">Versteek inligting</translation>
+<translation id="3317660236277031814">'n Webprogram wat jy geïnstalleer het, het sy ikoon verander.</translation>
<translation id="3328801116991980348">Werfinligting</translation>
<translation id="3333961966071413176">Alle kontakte</translation>
<translation id="3386292677130313581">Vra voordat werwe toegelaat word om jou ligging te ken (aanbeveel)</translation>
+<translation id="345699454248713913">'n Webprogram wat jy geïnstalleer het, het sy naam verander.</translation>
<translation id="3538390592868664640">Verhoed werwe om 'n 3D-kaart van jou omgewing te skep of kameraposisie na te spoor</translation>
+<translation id="3551268116566418498">Verlaat Incognitomodus?</translation>
<translation id="3586500876634962664">Kamera- en mikrofoongebruik</translation>
<translation id="358794129225322306">Laat 'n werf toe om outomaties veelvuldige lêers af te laai</translation>
<translation id="3594780231884063836">Demp video</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Maak ligginginstellings oop</translation>
<translation id="4226663524361240545">Kennisgewings kan die toestel laat vibreer</translation>
<translation id="4259722352634471385">Navigasie is geblokkeer: <ph name="URL" /></translation>
+<translation id="4277239631747669329">'n Webprogram wat jy geïnstalleer het, het sy naam en ikoon verander.</translation>
<translation id="4278390842282768270">Toegelaat</translation>
<translation id="429312253194641664">'n Werf speel tans media</translation>
<translation id="42981349822642051">Vou uit</translation>
<translation id="4336434711095810371">Vee alle data uit</translation>
<translation id="4402755511846832236">Keer dat werwe weet wanneer jy hierdie toestel aktief gebruik</translation>
-<translation id="4433925000917964731">Ligte bladsy deur Google verskaf</translation>
<translation id="4434045419905280838">Opspringers en herleidings</translation>
<translation id="445467742685312942">Laat werwe toe om beskermde inhoud te speel</translation>
<translation id="4468959413250150279">Demp klank vir 'n spesifieke werf.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Deur jou ouer bestuur</translation>
<translation id="4670064810192446073">Virtuele realiteit</translation>
<translation id="4708011789095599544">Is jy seker jy wil webkoekies en ander werfdata vir hierdie webwerf uitvee?</translation>
+<translation id="473775607612524610">Dateer op</translation>
<translation id="4751476147751820511">Beweging- of ligsensors</translation>
<translation id="4836046166855586901">Vra as 'n werf wil weet wanneer jy hierdie toestel aktief gebruik</translation>
<translation id="4883854917563148705">Bestuurde instellings kan nie teruggestel word nie</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Deel via</translation>
<translation id="5039804452771397117">Laat toe</translation>
<translation id="5048398596102334565">Laat werwe toegang tot bewegingsensors toe (aanbeveel)</translation>
+<translation id="5050380848339752099">Hierdie werf is op die punt om inligting met 'n program buite Incognitomodus te deel.</translation>
<translation id="5063480226653192405">Gebruik</translation>
<translation id="5100237604440890931">Ingevou – klik om uit te vou.</translation>
<translation id="5123685120097942451">Incognito-oortjie</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Laat werwe toe om JavaScript te gebruik (aanbeveel)</translation>
<translation id="534295439873310000">NFC-toestelle</translation>
<translation id="5354152178998424783">Dit sal <ph name="DATASIZE" /> se data en webkoekies uitvee wat deur werwe geberg is.</translation>
-<translation id="5384883051496921101">Hierdie werf is op die punt om inligting met 'n program buite incognitomodus te deel.</translation>
+<translation id="536508626067510330">Dateer ikoon op jou tuisskerm op?</translation>
<translation id="5391532827096253100">Jou verbinding aan hierdie werf is nie veilig nie. Werfinligting</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ nog 1)}other{(+ nog #)}}</translation>
<translation id="5403592356182871684">Name</translation>
<translation id="5489227211564503167">Tyd verstreke is <ph name="ELAPSED_TIME" /> van <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blokkeer advertensies op werwe wat indringerige of misleidende advertensies wys</translation>
+<translation id="549957179819296104">Nuwe ikoon</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> word toegelaat. <ph name="PERMISSION_2" /> word geblokkeer.</translation>
<translation id="5505264765875738116">Werwe kan nie vra om kennisgewings te stuur nie</translation>
<translation id="5516455585884385570">Maak kennisgewinginstellings oop</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Toestemmings</translation>
<translation id="5860033963881614850">Af</translation>
<translation id="5876056640971328065">Onderbreek video</translation>
+<translation id="5904826301761575486">Dateer naam en ikoon op jou tuisskerm op?</translation>
<translation id="5916664084637901428">Aan</translation>
<translation id="5922853908706496913">Deel tans jou skerm</translation>
<translation id="5939518447894949180">Stel terug</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokkeer derdeparty-webkoekies</translation>
<translation id="6206551242102657620">Verbinding is veilig. Werfinligting</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" />-opsies</translation>
+<translation id="6260852843601447737">Maak toe en gee misbruik aan</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> en <ph name="PERMISSION_2" /> word geblokkeer.</translation>
<translation id="6270391203985052864">Werwe kan vra om kennisgewings te stuur</translation>
<translation id="6295158916970320988">Alle werwe</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Om <ph name="APP_NAME" /> toegang tot jou ligging te gee, moet jy ligging ook in <ph name="BEGIN_LINK" />Android-instellings<ph name="END_LINK" /> aanskakel.</translation>
<translation id="8447861592752582886">Herroep toesteltoestemming</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 webkoekie word tans gebruik}other{# webkoekies word tans gebruik}}</translation>
-<translation id="8463851957836045671">Werf is vinnig</translation>
<translation id="8487700953926739672">Vanlyn beskikbaar</translation>
<translation id="851751545965956758">Keer dat werwe aan toestelle koppel</translation>
<translation id="8525306231823319788">Volskerm</translation>
<translation id="857943718398505171">Toegelaat (aanbeveel)</translation>
<translation id="8609465669617005112">Skuif op</translation>
+<translation id="861748745608658996">Dateer naam op jou tuisskerm op?</translation>
<translation id="8676374126336081632">Vee invoer uit</translation>
<translation id="868929229000858085">Deursoek jou kontakte</translation>
<translation id="8702612070107455751">Enige vanlyn data sal uitgevee word.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Zoem in</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC is af vir hierdie toestel. Skakel dit aan in <ph name="BEGIN_LINK" />Android-instellings<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Hierdie werf maak vinnig oop en reageer vinnig vir die meeste mense</translation>
<translation id="8941729603749328384">www.voorbeeld.com</translation>
-<translation id="894871326938397531">Verlaat incognitomodus?</translation>
<translation id="8958424370300090006">Blokkeer webkoekies vir 'n spesifieke werf.</translation>
<translation id="8959122750345127698">Navigasie is onbereikbaar: <ph name="URL" /></translation>
<translation id="8986362086234534611">Vergeet</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb
index 6a4951a0b2e..8f85650b9af 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_am.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="am">
<translation id="1006017844123154345">መስመር ላይ ክáˆá‰µ</translation>
<translation id="1044891598689252897">ጣቢያዎች እንደተለመደዠሆáŠá‹ ይሠራሉ</translation>
+<translation id="1100504063505580045">የአáˆáŠ‘ አዶ</translation>
<translation id="1124090076051167250">ይህ በጣቢያዎች ወይሠበመáŠáˆ» ገጽዎ ላይ ባሉ መተáŒá‰ áˆªá‹«á‹Žá‰½ የተከማቹ <ph name="DATASIZE" /> á‹áˆ‚ብ እና ኩኩዎችን ያጸዳáˆá¢</translation>
<translation id="1124772482545689468">ተጠቃሚ</translation>
<translation id="1178581264944972037">ለአáታ አá‰áˆ</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">ማይክሮáŽáŠ•</translation>
<translation id="3277252321222022663">ጣቢያዎች ዳሳሾችን እንዲደርሱ á‹­áቀዱላቸዠ(የሚመከር)</translation>
<translation id="3295602654194328831">መረጃ ደብቅ</translation>
+<translation id="3317660236277031814">የጫኑት የድር መተáŒá‰ áˆªá‹« አዶá‹áŠ• ቀይሮታáˆá¢</translation>
<translation id="3328801116991980348">የጣቢያ መረጃ</translation>
<translation id="3333961966071413176">áˆáˆ‰áˆ እá‹á‰‚ያዎች</translation>
<translation id="3386292677130313581">ጣቢያዎች አካባቢዎን እንዲያá‹á‰ ከመáቀድዎ በáŠá‰µ ይጠይቅ (የሚመከር)</translation>
+<translation id="345699454248713913">የጫኑት የድር መተáŒá‰ áˆªá‹« ስሙን ቀይሯáˆá¢</translation>
<translation id="3538390592868664640">ጣቢያዎች የዙሪያዎ የ3ሠካርታ እንዳይáˆáŒ¥áˆ© ወይሠየካሜራ ቦታን እንዳይከታተሉ á‹«áŒá‹·á‰¸á‹</translation>
+<translation id="3551268116566418498">ከማንáŠá‰µ የማያሳá‹á‰… áˆáŠá‰³ á‹­á‹áŒ£?</translation>
<translation id="3586500876634962664">የካሜራ እና ማይክሮáŽáŠ• ጥቅáˆ</translation>
<translation id="358794129225322306">አንድ ጣቢያ በራስ-ሰር በርካታ á‹á‹­áˆŽá‰½áŠ• እንዲያወርድ á‹­áቀዱá¢</translation>
<translation id="3594780231884063836">ቪዲዮ ላይ ድáˆáŒ¸-ከሠአድርáŒ</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">የአካባቢ ቅንብሮችን ክáˆá‰µ</translation>
<translation id="4226663524361240545">ማሳወቂያዎች መሣሪያá‹áŠ• እንዲáŠá‹áˆ­ ሊያደርጉት ይችላሉ</translation>
<translation id="4259722352634471385">ዳሰሳ ታáŒá‹·áˆá¦ <ph name="URL" /></translation>
+<translation id="4277239631747669329">የጫኑት የድር መተáŒá‰ áˆªá‹« ስሙን እና አዶá‹áŠ• ቀይሮታáˆá¢</translation>
<translation id="4278390842282768270">ተáˆá‰…á‹·áˆ</translation>
<translation id="429312253194641664">አንድ ጣቢያ ሚዲያን በማጫወት ላይ áŠá‹</translation>
<translation id="42981349822642051">ዘርጋ</translation>
<translation id="4336434711095810371">áˆáˆ‰áŠ•áˆ á‹áˆ‚ብ አጽዳ</translation>
<translation id="4402755511846832236">እርስዎ ይህን መሣሪያ በንቃት ሲጠቀሙ ጣቢያዎች እንዳያá‹á‰ á‹«áŒá‹±</translation>
-<translation id="4433925000917964731">ቀላሠገጹ በGoogle ቀርቧáˆá¢</translation>
<translation id="4434045419905280838">ብቅ-ባዮች እና አቅጣጫ ማዞሮች</translation>
<translation id="445467742685312942">ጣቢያዎች የተጠበቀ ይዘትን እንዲያጫá‹á‰µ á‹­áቀዱ</translation>
<translation id="4468959413250150279">በአንድ የተወሰአጣቢያ ላይ ድáˆáŒ¸-ከሠአድርáŒá¢</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">በእርስዎ ወላጅ የሚቀናበር</translation>
<translation id="4670064810192446073">áˆáŠ“ባዊ እá‹áŠá‰³</translation>
<translation id="4708011789095599544">እርáŒáŒ áŠ› áŠá‹Žá‰µ ለዚህ ድር ጣቢያ ኩኪዎችን እና ሌላ የጣቢያ á‹áˆ‚ብን ማጽዳት á‹­áˆáˆáŒ‹áˆ‰?</translation>
+<translation id="473775607612524610">አዘáˆáŠ•</translation>
<translation id="4751476147751820511">የእንቅስቃሴ ወይሠየብርሃን ዳሳሾች</translation>
<translation id="4836046166855586901">እርስዎ ይህን መሣሪያ መቼ በንቃት እየተጠቀሙ እንደሆአአንድ ጣቢያ ማወቅ ሲáˆáˆáŒ ይጠይá‰</translation>
<translation id="4883854917563148705">የሚተዳደሩ ቅንብሮች ዳáŒáˆ ሊጀመሩ አይችሉáˆ</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">ያጋሩ በ</translation>
<translation id="5039804452771397117">áቀድ</translation>
<translation id="5048398596102334565">ጣቢያዎች የእንቅስቃሴ ዳሳሾችን እንዲደርሱባቸዠይáቀዱ (የሚመከር)</translation>
+<translation id="5050380848339752099">ይህ ጣቢያ ማንáŠá‰µ ከማያሳá‹á‰… áˆáŠá‰³ á‹áŒ­ ላለ መተáŒá‰ áˆªá‹« መረጃ ሊያጋራ áŠá‹á¢</translation>
<translation id="5063480226653192405">አጠቃቀáˆ</translation>
<translation id="5100237604440890931">ተሰብስቧሠ- ለመዘርጋት ጠቅ ያድርጉ</translation>
<translation id="5123685120097942451">ማንáŠá‰µ የማያሳá‹á‰… ትር</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">ጣቢያዎች ጃቫስክሪá•á‰µáŠ• እንዲያሄዱ áቀድላቸዠ(የሚመከር)</translation>
<translation id="534295439873310000">የNFC መሣሪያዎች</translation>
<translation id="5354152178998424783">ይህ በጣቢያዎች የተከማቹ <ph name="DATASIZE" /> á‹áˆ‚ብ እና ኩኪዎችን ያጸዳáˆá¢</translation>
-<translation id="5384883051496921101">ይህ ጣቢያ ማንáŠá‰µ ከማያሳá‹á‰… áˆáŠá‰³ á‹áŒ­ ላለ መተáŒá‰ áˆªá‹« መረጃ ሊያጋራ áŠá‹á¢</translation>
+<translation id="536508626067510330">በእርስዎ መáŠáˆ» ገጽ ላይ አዶ ይዘáˆáŠ•?</translation>
<translation id="5391532827096253100">ወደዚህ ጣቢያ á‹«áˆá‹Žá‰µ áŒáŠ•áŠ™áŠá‰µ ደህንáŠá‰± የተጠበቀ አይደለáˆá¢ የጣቢያ መረጃ</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 ተጨማሪ)}one{(+ # ተጨማሪ)}other{(+ # ተጨማሪ)}}</translation>
<translation id="5403592356182871684">ስሞች</translation>
<translation id="5489227211564503167">የጠá‹á‹ ጊዜ <ph name="ELAPSED_TIME" /> ከ<ph name="TOTAL_TIME" />á¢</translation>
<translation id="5494752089476963479">ረባሽ ወይሠአሳሳች ማስታወቂያዎችን ከሚያሳዩ ጣቢያዎች የሚመጡ ማስታወቂያዎችን አáŒá‹µ</translation>
+<translation id="549957179819296104">አዲስ አዶ</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> ተáˆá‰…ዶላቸዋáˆá£ <ph name="PERMISSION_2" /> ታáŒá‹°á‹‹áˆ</translation>
<translation id="5505264765875738116">ጣቢያዎች ማሳወቂያዎችን ለመላክ መጠየቅ አይችሉáˆ</translation>
<translation id="5516455585884385570">የማሳወቂያ ቅንብሮችን ክáˆá‰µ</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">áቃዶች</translation>
<translation id="5860033963881614850">አጥá‹</translation>
<translation id="5876056640971328065">ቪዲዮ ባለበት አá‰áˆ</translation>
+<translation id="5904826301761575486">በመáŠáˆ» ገጽዎ ላይ ስሠእና አዶ ይዘáˆáŠ•?</translation>
<translation id="5916664084637901428">በርቷáˆ</translation>
<translation id="5922853908706496913">ማያ ገጽዎን በማጋራት ላይ</translation>
<translation id="5939518447894949180">ዳáŒáˆ አስጀáˆáˆ­</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">የሦስተኛ ወገን ኩኪዎችን አáŒá‹µ</translation>
<translation id="6206551242102657620">áŒáŠ•áŠ™áŠá‰µ ደህንáŠá‰± የተጠበቀ áŠá‹á¢ የጣቢያ መረጃ</translation>
<translation id="6216432067784365534">የ<ph name="NAME_OF_LIST_ITEM" /> አማራጮች</translation>
+<translation id="6260852843601447737">á‹­á‹áŒ‰ እና አላáŒá‰£á‰¥ መጠቀáˆáŠ• ሪá–ርት ያድርጉ</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> እና <ph name="PERMISSION_2" /> ታáŒá‹°á‹‹áˆ</translation>
<translation id="6270391203985052864">ጣቢያዎች ማሳወቂያዎችን ለመላክ መጠየቅ ይችላሉ</translation>
<translation id="6295158916970320988">áˆáˆ‰áˆ ጣቢያዎች</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> የእርስዎን መገኛ አካባቢ እንዲደርስበት ለማድረáŒá£ በተጨማሪ በ <ph name="BEGIN_LINK" />Android ቅንብሮች<ph name="END_LINK" /> á‹áˆµáŒ¥ መገኛ አካባቢን ያብሩá¢</translation>
<translation id="8447861592752582886">የመሣሪያ áˆá‰ƒá‹µ ሻር</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{በጥቅሠላይ ያለ 1 ኩኪ}one{# ጥቅሠላይ የዋሉ ኩኪዎች}other{# ጥቅሠላይ የዋሉ ኩኪዎች}}</translation>
-<translation id="8463851957836045671">ጣቢያ áˆáŒ£áŠ• áŠá‹</translation>
<translation id="8487700953926739672">ከመስመር á‹áŒª ይገኛáˆ</translation>
<translation id="851751545965956758">ጣቢያዎች ከመሣሪያዎች ጋር እንዳይገናኙ አáŒá‹µ</translation>
<translation id="8525306231823319788">ሙሉ ማያ ገጽ</translation>
<translation id="857943718398505171">ተáˆá‰…ዷሠ(የሚመከር)</translation>
<translation id="8609465669617005112">ወደላይ አá‹áŒ£</translation>
+<translation id="861748745608658996">በመáŠáˆ» ገጽዎ ላይ ስሠይዘáˆáŠ•?</translation>
<translation id="8676374126336081632">áŒá‰¤á‰±áŠ• አጽዳ</translation>
<translation id="868929229000858085">እá‹á‰‚ያዎችዎን á‹­áˆáˆáŒ‰</translation>
<translation id="8702612070107455751">ማንኛá‹áˆ የመስመር á‹áŒ­ á‹áˆ‚ብ ይጸዳáˆá¢</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">አጉላ</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC ለዚህ መሣሪያ ጠáቷáˆá¢ በ<ph name="BEGIN_LINK" />Android ቅንበሮች<ph name="END_LINK" /> á‹áˆµáŒ¥ ያብሩትá¢</translation>
-<translation id="8929372349074745002">ይህ ጣቢያ ለአብዛኛዎቹ ሰዎች በáጥáŠá‰µ ይከáታሠእና áˆáˆ‹áˆ½ ይሰጣáˆ</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ከማንáŠá‰µ የማያሳá‹á‰… áˆáŠá‰³ á‹­á‹áŒ£?</translation>
<translation id="8958424370300090006">የአንድ የተወሰአጣቢያ ኩኪዎችን á‹«áŒá‹±á¢</translation>
<translation id="8959122750345127698">ዳሰሳ ሊደረስበት አይችáˆáˆá¦ <ph name="URL" /></translation>
<translation id="8986362086234534611">እርሳ</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ar.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ar.xtb
index 35fe8c4cf3d..40752b6355c 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ar.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ar.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ar">
<translation id="1006017844123154345">Ùتح على الإنترنت</translation>
<translation id="1044891598689252897">ستعمل المواقع الإلكترونية بشكل٠طبيعي.</translation>
+<translation id="1100504063505580045">الرمز الحالي</translation>
<translation id="1124090076051167250">سيؤدي هذا الإجراء إلى محو <ph name="DATASIZE" /> من البيانات وملÙات تعري٠الارتباط المÙخزّنة من خلال المواقع الإلكترونية أو التطبيقات على الشاشة الرئيسية.</translation>
<translation id="1124772482545689468">المستخدم</translation>
<translation id="1178581264944972037">الإيقا٠مؤقتًا</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">الميكروÙون</translation>
<translation id="3277252321222022663">يمكنك السماح للمواقع بالوصول إلى أجهزة الاستشعار (Ù…Ùقترَح).</translation>
<translation id="3295602654194328831">إخÙاء المعلومات</translation>
+<translation id="3317660236277031814">تم تغيير رمز أحد تطبيقات الويب التي ثبّتها.</translation>
<translation id="3328801116991980348">معلومات الموقع الإلكتروني</translation>
<translation id="3333961966071413176">جميع جهات الاتصال</translation>
<translation id="3386292677130313581">السؤال قبل السماح للمواقع الإلكترونية بمعرÙØ© الموقع الجغراÙÙŠ (موصى به)</translation>
+<translation id="345699454248713913">تم تغيير اسم أحد تطبيقات الويب التي ثبّتها.</translation>
<translation id="3538390592868664640">منع المواقع الإلكترونية من إنشاء خريطة ثلاثية الأبعاد للبيئة المحيطة بك أو تتبّÙع موضع الكاميرا</translation>
+<translation id="3551268116566418498">أتريد مغادرة وضع التصÙØ­ المتخÙي؟</translation>
<translation id="3586500876634962664">الكاميرا والميكروÙون قيد التشغيل</translation>
<translation id="358794129225322306">السماح لموقع إلكتروني بتنزيل عدة ملÙات تلقائيًا.</translation>
<translation id="3594780231884063836">كتم صوت الÙيديو</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Ùتح إعدادات الموقع الجغراÙÙŠ</translation>
<translation id="4226663524361240545">يمكن أن تؤدي الإشعارات إلى اهتزاز الجهاز</translation>
<translation id="4259722352634471385">التنقل محظور: <ph name="URL" /></translation>
+<translation id="4277239631747669329">تم تغيير اسم ورمز أحد تطبيقات الويب التي ثبّتها.</translation>
<translation id="4278390842282768270">منح الإذن</translation>
<translation id="429312253194641664">تÙعيل موقع إلكتروني للوسائط</translation>
<translation id="42981349822642051">توسيع</translation>
<translation id="4336434711095810371">محو جميع البيانات</translation>
<translation id="4402755511846832236">منع المواقع الإلكترونية من رصد استخدامك النشط لهذا الجهاز</translation>
-<translation id="4433925000917964731">â€Ù†Ø³Ø®Ø© Ø®ÙÙŠÙØ© تقدّÙمها Google</translation>
<translation id="4434045419905280838">النواÙØ° المنبثقة وإعادة التوجيه</translation>
<translation id="445467742685312942">السماح للمواقع الإلكترونية بتشغيل المحتوى المَحمي</translation>
<translation id="4468959413250150279">كتم صوت موقع إلكتروني معين.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">يديره والداك</translation>
<translation id="4670064810192446073">الواقع الاÙتراضي</translation>
<translation id="4708011789095599544">هل أنت متأكّد أنك تريد محو ملÙات تعري٠الارتباط والبيانات الأخرى لهذا الموقع الإلكتروني؟</translation>
+<translation id="473775607612524610">تحديث</translation>
<translation id="4751476147751820511">أجهزة استشعار الإضاءة أو الحركة</translation>
<translation id="4836046166855586901">طلب الإذن عندما يحاول أحد المواقع الإلكترونية رصد استخدامك النشط لهذا الجهاز</translation>
<translation id="4883854917563148705">يتعذّر إعادة ضبط الإعدادات التي تمت إدارتها</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">المشاركة عن طريق</translation>
<translation id="5039804452771397117">سماح</translation>
<translation id="5048398596102334565">السماح للمواقع الإلكترونية بالوصول إلى مستشعرات الحركة (Ù…Ùقترَح)</translation>
+<translation id="5050380848339752099">هذا الموقع الإلكتروني على وشك مشاركة معلومات مع أحد التطبيقات خارج وضع التصÙÙ‘ÙØ­ المتخÙÙŠ.</translation>
<translation id="5063480226653192405">الاستخدام</translation>
<translation id="5100237604440890931">تم التصغير - انقر للتوسيع.</translation>
<translation id="5123685120097942451">علامة تبويب "التصÙÙ‘ÙØ­ المتخÙÙŠ"</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">â€Ø§Ù„سماح للمواقع الإلكترونية بتشغيل JavaScript (موصى به)</translation>
<translation id="534295439873310000">â€Ø£Ø¬Ù‡Ø²Ø© NFC</translation>
<translation id="5354152178998424783">سيؤدي هذا الإجراء إلى محو <ph name="DATASIZE" /> من البيانات وملÙات تعري٠الارتباط المÙخزّنة من خلال المواقع الإلكترونية.</translation>
-<translation id="5384883051496921101">الموقع الإلكتروني هذا على وشك مشاركة معلومات مع أحد التطبيقات خارج وضع التصÙØ­ المتخÙÙŠ.</translation>
+<translation id="536508626067510330">هل تريد تعديل الرمز الظاهر على الشاشة الرئيسية؟</translation>
<translation id="5391532827096253100">إن اتصالك بهذا الموقع الإلكتروني غير آمن. معلومات الموقع الإلكتروني</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 آخر)}zero{(+ # آخر)}two{(+ اثنين (#) آخرين)}few{(+ # أخرى)}many{(+ # آخر)}other{(+ # آخر)}}</translation>
<translation id="5403592356182871684">الأسماء</translation>
<translation id="5489227211564503167">الوقت المنقضي <ph name="ELAPSED_TIME" /> من <ph name="TOTAL_TIME" /></translation>
<translation id="5494752089476963479">حظر الإعلانات ÙÙŠ المواقع الإلكترونية التي تعرض إعلانات مضلّÙلة أو غير مرغوب Ùيها</translation>
+<translation id="549957179819296104">رمز جديد</translation>
<translation id="5502860503640766021">تم السماح بالوصول إلى <ph name="PERMISSION_1" /> وحظر <ph name="PERMISSION_2" />.</translation>
<translation id="5505264765875738116">منع المواقع الإلكترونية من طلب إرسال إشعارات</translation>
<translation id="5516455585884385570">Ùتح إعدادات الإشعارات</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">الأذونات</translation>
<translation id="5860033963881614850">غير Ù…Ùعّل</translation>
<translation id="5876056640971328065">إيقا٠الÙيديو مؤقتًا</translation>
+<translation id="5904826301761575486">هل تريد تعديل الاسم والرمز الظاهرَين على الشاشة الرئيسية؟</translation>
<translation id="5916664084637901428">Ù…Ùعّل</translation>
<translation id="5922853908706496913">جار٠مشاركة شاشتك</translation>
<translation id="5939518447894949180">إعادة الضبط</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">حظر ملÙات تعري٠الارتباط للجهات الخارجية</translation>
<translation id="6206551242102657620">ÙŠÙعدّ٠اتصالك آمنًا. معلومات الموقع الإلكتروني</translation>
<translation id="6216432067784365534">خيارات <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">الإغلاق والإبلاغ عن إساءة استخدام</translation>
<translation id="6262279340360821358">تم حظر <ph name="PERMISSION_1" /> و<ph name="PERMISSION_2" />.</translation>
<translation id="6270391203985052864">السماح للمواقع الإلكترونية بطلب إرسال إشعارات</translation>
<translation id="6295158916970320988">جميع المواقع الإلكترونية</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">â€Ù„لسماح لتطبيق <ph name="APP_NAME" /> بالوصول إلى موقعك الجغراÙÙŠØŒ ÙŠÙرجى أيضًا تÙعيل الموقع الجغراÙÙŠ ÙÙŠ <ph name="BEGIN_LINK" />إعدادات Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">إبطال إذن الجهاز</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{مل٠تعري٠ارتباط واحد قيد الاستخدام}zero{# مل٠تعري٠ارتباط قيد الاستخدام}two{ملÙا تعري٠ارتباط قيد الاستخدام}few{# ملÙات تعري٠ارتباط قيد الاستخدام}many{# مل٠تعري٠ارتباط قيد الاستخدام}other{# مل٠تعري٠ارتباط قيد الاستخدام}}</translation>
-<translation id="8463851957836045671">الموقع الإلكتروني سريع</translation>
<translation id="8487700953926739672">التوÙر بلا إنترنت</translation>
<translation id="851751545965956758">حظر المواقع الإلكترونية من الاتصال بأجهزة</translation>
<translation id="8525306231823319788">ملء الشاشة</translation>
<translation id="857943718398505171">مسموح بها (موصى بها)</translation>
<translation id="8609465669617005112">الانتقال إلى الأعلى</translation>
+<translation id="861748745608658996">هل تريد تعديل الاسم الظاهر على الشاشة الرئيسية؟</translation>
<translation id="8676374126336081632">محو الإرسال</translation>
<translation id="868929229000858085">البحث ÙÙŠ جهات الاتصال</translation>
<translation id="8702612070107455751">سيتم محو أي بيانات متوÙّرة بلا اتصال بالإنترنت.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">تكبير</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">â€ØªÙ‚نية NFC غير Ù…Ùعّلة على هذا الجهاز. Ùعّلها ÙÙŠ<ph name="BEGIN_LINK" />إعدادات Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">ÙŠÙتح هذا الموقع الإلكتروني ويستجيب بشكل سريع لدى معظم الأشخاص.</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">أتريد مغادرة وضع التصÙØ­ المتخÙي؟</translation>
<translation id="8958424370300090006">حظر ملÙات تعري٠الارتباط لموقع إلكتروني Ù…Ùحدَّد.</translation>
<translation id="8959122750345127698">التنقل غير قابل للوصول: <ph name="URL" /></translation>
<translation id="8986362086234534611">حذÙ</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_as.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_as.xtb
index 0848ebd2612..88b384c78c7 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_as.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_as.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="as">
<translation id="1006017844123154345">অনলাইনত খোলক</translation>
<translation id="1044891598689252897">ছাইটসমূহে সà§à¦¬à¦¾à¦­à¦¾à§±à¦¿à¦•à¦­à¦¾à§±à§‡ কাম কৰিব</translation>
+<translation id="1100504063505580045">বৰà§à¦¤à¦®à¦¾à¦¨à§° চিহà§à¦¨</translation>
<translation id="1124090076051167250">à¦à¦‡à¦Ÿà§‹à§±à§‡ আপোনাৰ গৃহ সà§à¦•à§à¦°à§€à¦¨à¦¤ ছাইট অথবা à¦à¦ªà§â€Œà¦¸à¦®à§‚হে ষà§à¦Ÿâ€™à§° কৰা <ph name="DATASIZE" /> ডেটা আৰৠকà§à¦•à¦¿ মচিব।</translation>
<translation id="1124772482545689468">বà§à¦¯à§±à¦¹à¦¾à§°à¦•à¦¾à§°à§€</translation>
<translation id="1178581264944972037">পজ কৰক</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">মাইকà§à§°â€™à¦«â€™à¦¨</translation>
<translation id="3277252321222022663">ছেনà§à¦¸à§°à¦¸à¦®à§‚হলৈ à¦à¦•à§à¦¸à§‡à¦› পাবলৈ ছাইটসমূহক অনà§à¦®à¦¤à¦¿ দিয়ক (চà§à¦ªà¦¾à§°à¦¿à¦› কৰা)</translation>
<translation id="3295602654194328831">তথà§à¦¯ লà§à¦•à§à§±à¦¾à¦“ক</translation>
+<translation id="3317660236277031814">আপà§à¦¨à¦¿ ইনষà§à¦Ÿà¦² কৰা à¦à¦Ÿà¦¾ ৱেব à¦à¦ªà§‡ নিজৰ চিহà§à¦¨à¦Ÿà§‹ সলনি কৰিছে।</translation>
<translation id="3328801116991980348">ছাইটৰ তথà§à¦¯</translation>
<translation id="3333961966071413176">সকলো সমà§à¦ªà§°à§à¦•</translation>
<translation id="3386292677130313581">ছাইটসমূহে আপোনাৰ অৱসà§à¦¥à¦¾à¦¨ জনাৰ অনà§à¦®à¦¤à¦¿ দিয়াৰ পূৰà§à¦¬à§‡ সোধক (চà§à¦ªà¦¾à§°à¦¿à¦› কৰা হয়)</translation>
+<translation id="345699454248713913">আপà§à¦¨à¦¿ ইনষà§à¦Ÿà¦² কৰা à¦à¦Ÿà¦¾ ৱেব à¦à¦ªà§‡ নিজৰ নামটো সলনি কৰিছে।</translation>
<translation id="3538390592868664640">ছাইটসমূহক আপোনাৰ চৌপাশৰ à¦à¦–ন 3D মেপ সৃষà§à¦Ÿà¦¿ কৰাৰ পৰা অথবা কেমেৰাৰ সà§à¦¥à¦¾à¦¨ টà§à§°à§‡à¦• কৰাৰ পৰা অৱৰোধ কৰক</translation>
+<translation id="3551268116566418498">ইনক’গনিট’ ম’ডৰ পৰা বাহিৰ হ’বনে?</translation>
<translation id="3586500876634962664">কেমেৰা আৰৠমাইকà§à§°â€™à¦«â€™à¦¨à§° বà§à¦¯à§±à¦¹à¦¾à§°</translation>
<translation id="358794129225322306">à¦à¦Ÿà¦¾ ছাইটক à¦à¦•à¦¾à¦§à¦¿à¦• ফাইল সà§à¦¬à§Ÿà¦‚কà§à§°à¦¿à§Ÿà¦­à¦¾à§±à§‡ ডাউনল’ড কৰাৰ অনà§à¦®à¦¤à¦¿ দিয়ক।</translation>
<translation id="3594780231884063836">ভিডিঅ' মিউট কৰক</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">অৱসà§à¦¥à¦¾à¦¨à§° ছেটিংসমূহ খোলক</translation>
<translation id="4226663524361240545">জাননীয়ে ডিভাইচটো কমà§à¦ªà¦¨ কৰিব পাৰে</translation>
<translation id="4259722352634471385">নেভিগে’শà§à¦¬à¦¨ অৱৰোধ কৰা আছে: <ph name="URL" /></translation>
+<translation id="4277239631747669329">আপà§à¦¨à¦¿ ইনষà§à¦Ÿà¦² কৰা à¦à¦Ÿà¦¾ ৱেব à¦à¦ªà§‡ নিজৰ নাম আৰৠচিহà§à¦¨ সলনি কৰিছে।</translation>
<translation id="4278390842282768270">অনà§à¦®à¦¤à¦¿ দিয়া হৈছে</translation>
<translation id="429312253194641664">ছাইটটোৱে মিডিয়া পà§à¦²à§‡â€™ কৰি আছে</translation>
<translation id="42981349822642051">বিসà§à¦¤à¦¾à§° কৰক</translation>
<translation id="4336434711095810371">সকলো ডেটা মচক</translation>
<translation id="4402755511846832236">আপà§à¦¨à¦¿ à¦à¦‡ ডিভাইচটো সকà§à§°à¦¿à§Ÿà¦­à¦¾à§±à§‡ বà§à¦¯à§±à¦¹à¦¾à§° কৰি থকাৰ বিষয়ে ছাইটসমূহে জনাটো অৱৰোধ কৰক</translation>
-<translation id="4433925000917964731">Googleঠপà§à§°à¦¦à¦¾à¦¨ কৰা লাইট পৃষà§à¦ à¦¾</translation>
<translation id="4434045419905280838">পপ-আপ আৰৠপà§à¦¨à§° নিরà§à¦¦à§‡à¦¶</translation>
<translation id="445467742685312942">ছাইটসমূহক সà§à§°à¦•à§à¦·à¦¿à¦¤ সমল পà§à¦²à§‡' কৰিবলৈ অনà§à¦®à¦¤à¦¿ দিয়ক</translation>
<translation id="4468959413250150279">নিৰà§à¦¦à¦¿à¦·à§à¦Ÿ ছাইটৰ বাবে ধà§à¦¬à¦¨à¦¿ মিউট কৰক।</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">আপোনাৰ অভিভাৱকৰ দà§à¦¬à¦¾à§°à¦¾ পৰিচালিত</translation>
<translation id="4670064810192446073">ভাৰà§à¦šà§à§±à§‡à¦² ৰিয়েলিটি</translation>
<translation id="4708011789095599544">আপà§à¦¨à¦¿ à¦à¦‡ ৱেবছাইটটোৰ বাবে কà§à¦•à¦¿ আৰৠছাইটৰ অনà§à¦¯ ডেটা মচিবলৈ বিচাৰে বà§à¦²à¦¿ নিশà§à¦šà¦¿à¦¤à¦¨à§‡?</translation>
+<translation id="473775607612524610">আপডে'ট কৰক</translation>
<translation id="4751476147751820511">গতি বা পোহৰ ধৰা পেলাব পৰা ছেনà§à¦¸à§°</translation>
<translation id="4836046166855586901">আপà§à¦¨à¦¿ à¦à¦‡ ডিভাইচটো সকà§à§°à¦¿à§Ÿà¦­à¦¾à§±à§‡ বà§à¦¯à§±à¦¹à¦¾à§° কৰি থকাৰ বিষয়ে কোনো ছাইটে সেয়া জানিব বিচাৰিলে সোধক</translation>
<translation id="4883854917563148705">পৰিচালিত ছেটিংসমূহ ৰিছেট কৰিব নোৱাৰি</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">ইয়াৰ জৰিয়তে শà§à¦¬à§‡à§Ÿà¦¾à§° কৰক</translation>
<translation id="5039804452771397117">অনà§à¦®à¦¤à¦¿ দিয়ক</translation>
<translation id="5048398596102334565">ম'শà§à¦¬à¦¨ ছেনà§à¦¸à§°à¦¸à¦®à§‚হলৈ à¦à¦•à§à¦¸à§‡à¦› পাবলৈ ছাইটসমূহক অনà§à¦®à¦¤à¦¿ দিয়ক (চà§à¦ªà¦¾à§°à¦¿à¦› কৰা)</translation>
+<translation id="5050380848339752099">à¦à¦‡ ছাইটটোৱে ইনক’গনিট’ ম’ডৰ বাহিৰৰ à¦à¦Ÿà¦¾ à¦à¦ªà§° সৈতে তথà§à¦¯ শà§à¦¬à§‡à¦¯à¦¼à¦¾à§° কৰিবলৈ লৈছে।</translation>
<translation id="5063480226653192405">বà§à¦¯à§±à¦¹à¦¾à§°</translation>
<translation id="5100237604440890931">সংকà§à¦šà¦¿à¦¤ - সমà§à¦ªà§à§°à¦¸à¦¾à§°à¦£ কৰিবলৈ টিপক</translation>
<translation id="5123685120097942451">ইনক’গনিট’ টেব</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">JavaScript চলাবলৈ ছাইটক অনà§à¦®à¦¤à¦¿ দিয়ক (চà§à¦ªà¦¾à§°à¦¿à¦› কৰা)</translation>
<translation id="534295439873310000">NFC ডিভাইচসমূহ</translation>
<translation id="5354152178998424783">à¦à¦‡à¦Ÿà§‹à§±à§‡ ছাইটসমূহে ষà§à¦Ÿâ€™à§° কৰা <ph name="DATASIZE" /> ডেটা আৰৠকà§à¦•à¦¿ মচিব।</translation>
-<translation id="5384883051496921101">à¦à¦‡ ছাইটটোৱে ইনক'গনিট' ম'ডৰ বাহিৰৰ à¦à¦Ÿà¦¾ à¦à¦ªà§° সৈতে তথà§à¦¯ শà§à¦¬à§‡à¦¯à¦¼à¦¾à§° কৰিব ওলাইছে।</translation>
+<translation id="536508626067510330">আপোনাৰ গৃহ সà§à¦•à§à§°à§€à¦¨à¦¤ চিহà§à¦¨à¦Ÿà§‹ আপডে’ট কৰিবনে?</translation>
<translation id="5391532827096253100">à¦à¦‡ ছাইটলৈ থকা আপোনাৰ সংযোগ সà§à§°à¦•à§à¦·à¦¿à¦¤ নহয়। ছাইটৰ তথà§à¦¯</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(আৰৠ১টা)}one{(আৰৠ#টা)}other{(আৰৠ#টা)}}</translation>
<translation id="5403592356182871684">নামসমূহ</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" />ৰ ভিতৰত <ph name="ELAPSED_TIME" /> সময় পাৰ হৈছে।</translation>
<translation id="5494752089476963479">অননà§à¦®à§‹à¦¦à¦¿à¦¤ বা বিভà§à§°à¦¾à¦¨à§à¦¤à¦¿à¦•à§° বিজà§à¦žà¦¾à¦ªà¦¨ দেখà§à¦“ৱা ছাইটসমূহত বিজà§à¦žà¦¾à¦ªà¦¨ অৱৰোধ কৰক</translation>
+<translation id="549957179819296104">নতà§à¦¨ চিহà§à¦¨</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" />ৰ অনà§à¦®à¦¤à¦¿ দিয়া আছে, <ph name="PERMISSION_2" />ক অৱৰোধ কৰা আছে</translation>
<translation id="5505264765875738116">ছাইটসমূহে জাননী পঠিয়াবলৈ ক’ব নোৱাৰে</translation>
<translation id="5516455585884385570">জাননীৰ ছেটিংসমূহ খোলক</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">অনà§à¦®à¦¤à¦¿</translation>
<translation id="5860033963881614850">অফ আছে</translation>
<translation id="5876056640971328065">ভিডিঅ’ পজ কৰক</translation>
+<translation id="5904826301761575486">আপোনাৰ গৃহ সà§à¦•à§à§°à§€à¦¨à¦¤ নাম অথবা চিহà§à¦¨à¦Ÿà§‹ আপডে’ট কৰিবনে?</translation>
<translation id="5916664084637901428">অন আছে</translation>
<translation id="5922853908706496913">আপোনাৰ সà§à¦•à§à§°à§€à¦¨ শà§à¦¬à§‡à§Ÿà¦¾à§° কৰি থকা হৈছে</translation>
<translation id="5939518447894949180">ৰিছেট কৰক</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">তৃতীয়-পকà§à¦·à§° কà§à¦•à¦¿à¦¸à¦®à§‚হ অৱৰোধ কৰক</translation>
<translation id="6206551242102657620">সংযোগটো নিৰাপদ। ছাইটৰ তথà§à¦¯</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> বিকলà§à¦ª</translation>
+<translation id="6260852843601447737">বনà§à¦§ কৰক আৰৠদà§à§°à§à¦¬à§à¦¯à§±à¦¹à¦¾à§°à§° সমà§à¦ªà§°à§à¦•à§‡ অভিযোগ দিয়ক</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> আৰৠ<ph name="PERMISSION_2" />ক অৱৰোধ কৰা আছে</translation>
<translation id="6270391203985052864">ছাইটসমূহে জাননী পঠিয়াবলৈ ক’ব পাৰে</translation>
<translation id="6295158916970320988">সকলো ছাইট</translation>
@@ -281,12 +290,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" />ক আপোনাৰ অৱসà§à¦¥à¦¾à¦¨ à¦à¦•à§à¦¸à§‡à¦› কৰিবলৈ দিবলৈ <ph name="BEGIN_LINK" />Android ছেটিংসমূহ<ph name="END_LINK" />তো অৱসà§à¦¥à¦¾à¦¨ অন কৰক।</translation>
<translation id="8447861592752582886">ডিভাইচৰ অনà§à¦®à¦¤à¦¿ পà§à§°à¦¤à§à¦¯à¦¾à¦¹à¦¾à§° কৰক</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{১ টা কà§à¦•à¦¿ বà§à¦¯à§±à¦¹à¦¾à§° হৈ আছে}one{# টা কà§à¦•à¦¿ বà§à¦¯à§±à¦¹à¦¾à§° হৈ আছে}other{# টা কà§à¦•à¦¿ বà§à¦¯à§±à¦¹à¦¾à§° হৈ আছে}}</translation>
-<translation id="8463851957836045671">ছাইটটো দà§à§°à§à¦¤</translation>
<translation id="8487700953926739672">অফলাইনত উপলবà§à¦§</translation>
<translation id="851751545965956758">ডিভাইচৰ সৈতে সংযোগ কৰাৰ পৰা ছাইটসমূহক অৱৰোধ কৰক</translation>
<translation id="8525306231823319788">সমà§à¦ªà§‚রà§à¦£ সà§à¦•à§à§°à§€à¦£</translation>
<translation id="857943718398505171">অনà§à¦®à§‹à¦¦à¦¿à¦¤ (চà§à¦ªà¦¾à§°à¦¿à¦› কৰা)</translation>
<translation id="8609465669617005112">ওপৰলৈ নিয়ক</translation>
+<translation id="861748745608658996">আপোনাৰ গৃহ সà§à¦•à§à§°à§€à¦¨à¦¤ নামটো আপডে’ট কৰিবনে?</translation>
<translation id="8676374126336081632">ইনপà§à¦Ÿ মচক</translation>
<translation id="868929229000858085">সমà§à¦ªà§°à§à¦•à¦¸à§‚চীত থকা বà§à¦¯à¦•à§à¦¤à¦¿ সনà§à¦§à¦¾à¦¨ কৰক</translation>
<translation id="8702612070107455751">সকলো অফলাইন ডেটা মচা হ’ব।</translation>
@@ -301,9 +310,7 @@
<translation id="8903921497873541725">জà§à¦® ইন কৰক</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">à¦à¦‡ ডিভাইচটোৰ বাবে NFC অফ কৰা আছে। ইয়াক <ph name="BEGIN_LINK" />Android ছেটিংসমূহ<ph name="END_LINK" />লৈ গৈ অন কৰক।</translation>
-<translation id="8929372349074745002">সৰহভাগ লোকৰ বাবে à¦à¦‡ ছাইটটো খোল খায় তথা সেইটোৱে দà§à§°à§à¦¤à¦­à¦¾à§±à§‡ সà¦à¦¹à¦¾à§°à¦¿ দিয়ে</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ইনক’গনিট’ ম’ডৰ পৰা বাহিৰ হ’বনে?</translation>
<translation id="8958424370300090006">কোনো বিশেষ ছাইটৰ বাবে কà§à¦•à¦¿à¦¸à¦®à§‚হ অৱৰোধ কৰক।</translation>
<translation id="8959122750345127698">ইয়ালৈ নেভিগেশà§à¦¬à¦¨ পাব পৰা অৱসà§à¦¥à¦¾à¦¤ নাই: <ph name="URL" /></translation>
<translation id="8986362086234534611">পাহৰক</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_az.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_az.xtb
index be3592473a5..712624d1d89 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_az.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_az.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="az">
<translation id="1006017844123154345">Onlayn açın</translation>
<translation id="1044891598689252897">Saytlar normal qaydada işləyəcək</translation>
+<translation id="1100504063505580045">Cari iÅŸarÉ™</translation>
<translation id="1124090076051167250">Bununla Æsas ekranda saytlar vÉ™ ya tÉ™tbiqlÉ™r tÉ™rÉ™findÉ™n saxlanılan <ph name="DATASIZE" /> data vÉ™ kuki silinÉ™cÉ™k.</translation>
<translation id="1124772482545689468">İstifadəçi</translation>
<translation id="1178581264944972037">Durdurun</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Saytların sensorlara daxil olmasına icazə verin (tövsiyə edilir)</translation>
<translation id="3295602654194328831">Məlumatı gizlədin</translation>
+<translation id="3317660236277031814">Quraşdırdığınız veb tətbiq işarəsini dəyişdi.</translation>
<translation id="3328801116991980348">Sayt haqqında</translation>
<translation id="3333961966071413176">Bütün kontaktar</translation>
<translation id="3386292677130313581">Saytlara məkanınızı bilmək icazəsi verməmişdən əvvəl soruşun (tövsiyə olunur)</translation>
+<translation id="345699454248713913">Quraşdırdığınız veb tətbiq adını dəyişdi.</translation>
<translation id="3538390592868664640">Saytların ətrafınızdakı sahələrin 3D xəritəsini yaratmasına və ya kamera mövqeyini izləməsinə qarşı blok qoyun</translation>
+<translation id="3551268116566418498">Anonim rejimdən çıxılsın?</translation>
<translation id="3586500876634962664">Kamera vÉ™ mikrofondan istifadÉ™</translation>
<translation id="358794129225322306">Sayta çoxsaylı faylları avtomatik endirmək icazəsi verin.</translation>
<translation id="3594780231884063836">Videonu səssiz rejimə keçirin</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Məkan Ayarlarını açın</translation>
<translation id="4226663524361240545">Bildirişlər cihazı titrədə bilər</translation>
<translation id="4259722352634471385">Naviqasiya bloklandı: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Quraşdırdığınız veb tətbiq adını və işarəsini dəyişdi.</translation>
<translation id="4278390842282768270">Ä°cazÉ™ verilib</translation>
<translation id="429312253194641664">Sayt media oxudur</translation>
<translation id="42981349822642051">Genişləndirin</translation>
<translation id="4336434711095810371">Bütün datanı silin</translation>
<translation id="4402755511846832236">Saytların bu cihazdan nə zaman aktiv şəkildə istifadə etdiyinizi bilməsini bloklayın</translation>
-<translation id="4433925000917964731">Google'un dəstəklədiyi lite səhifəsi</translation>
<translation id="4434045419905280838">Popap və yönləndirmələr</translation>
<translation id="445467742685312942">Saytlara qorunan kontenti oxutmaÄŸa icazÉ™ verin</translation>
<translation id="4468959413250150279">Xüsusi saytı səsiz rejimə keçirin.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Valideyniniz tərəfindən idarə olunur</translation>
<translation id="4670064810192446073">Virtual reallıq</translation>
<translation id="4708011789095599544">Bu vebsayt üçün kukiləri və digər sayt datasını silmək istədiyinizə əminsiniz?</translation>
+<translation id="473775607612524610">Güncəlləşdirin</translation>
<translation id="4751476147751820511">Hərəkət və ışıq sensorları</translation>
<translation id="4836046166855586901">Sayt bu cihazdan nə zaman aktiv şəkildə istifadə etdiyinizi bilmək istədikdə icazə istəsin</translation>
<translation id="4883854917563148705">İdarə edilən ayarlar sıfırlana bilməz</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Paylaşma vasitəsi:</translation>
<translation id="5039804452771397117">Ä°cazÉ™ verin</translation>
<translation id="5048398596102334565">Saytların hərəkət sensorlarınıza daxil olmasına icazə verin (tövsiyə edilir)</translation>
+<translation id="5050380848339752099">Bu sayt Anonim rejimdə olmayan tətbiqlə məlumat paylaşmaq üzrədir.</translation>
<translation id="5063480226653192405">IstifadÉ™</translation>
<translation id="5100237604440890931">Yığcamlaşdırıldı - genişləndirmək üçün klikləyin.</translation>
<translation id="5123685120097942451">Aanonim tab</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Saytlara JavaScript işlətməyə icazə verin (tövsiyə olunur)</translation>
<translation id="534295439873310000">NFC cihazları</translation>
<translation id="5354152178998424783">Bununla saytlar tərəfindən saxlanılan <ph name="DATASIZE" /> data və kuki silinəcək.</translation>
-<translation id="5384883051496921101">Bu sayt gizli rejimdə olmayan tətbiqlə məlumat paylaşmaq üzrədir.</translation>
+<translation id="536508626067510330">Æsas ekranınızda iÅŸarÉ™ yenilÉ™nsin?</translation>
<translation id="5391532827096253100">Bu sayta bağlantınız güvənli deyil. Sayt barədə məlumat</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+1)}other{(+ #)}}</translation>
<translation id="5403592356182871684">Adlar</translation>
<translation id="5489227211564503167">Keçən vaxt: <ph name="ELAPSED_TIME" /> / <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">İntruziv və aldadıcı reklamlar göstərən saytlardakı reklamları bloklayın</translation>
+<translation id="549957179819296104">Yeni iÅŸarÉ™</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> üçün icazə verilib, <ph name="PERMISSION_2" /> bloklanın</translation>
<translation id="5505264765875738116">Saytlar bildiriş göndərilməsini tələb edə bilməz</translation>
<translation id="5516455585884385570">Bildiriş ayarlarını açın</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">İcazələr</translation>
<translation id="5860033963881614850">Deaktiv</translation>
<translation id="5876056640971328065">Videoya pauza verin</translation>
+<translation id="5904826301761575486">Æsas ekranınızda ad vÉ™ iÅŸarÉ™ güncÉ™llÉ™nsin?</translation>
<translation id="5916664084637901428">Aktiv</translation>
<translation id="5922853908706496913">Ekranınız paylaşılır</translation>
<translation id="5939518447894949180">Sıfırlayın</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Üçüncü tərəf kukiləri blok edin</translation>
<translation id="6206551242102657620">Bağlantınız güvənlidir. Sayt barədə məlumat</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> Seçimləri</translation>
+<translation id="6260852843601447737">Bağlayın və sui-istifadə barədə bildirin</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> və <ph name="PERMISSION_2" /> bloklanıb</translation>
<translation id="6270391203985052864">Saytlar bildiriş göndərilməsini tələb edə bilər</translation>
<translation id="6295158916970320988">Bütün saytlar</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> tətbiqinə məkanınıza giriş icazəsi vermək üçün <ph name="BEGIN_LINK" />Android Ayarlarında<ph name="END_LINK" /> məkanı da aktiv edin.</translation>
<translation id="8447861592752582886">Cihaz icazəsini ləğv edin</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 kuki istifadÉ™ olunur}other{# kuki istifadÉ™ olunur}}</translation>
-<translation id="8463851957836045671">Sayt sürətlidir</translation>
<translation id="8487700953926739672">Oflayn olaraq əlçatan</translation>
<translation id="851751545965956758">Saytların cihazlara qoşulmasını blok edin</translation>
<translation id="8525306231823319788">Tam ekran</translation>
<translation id="857943718398505171">İcazə verilib (tövsiyə olunur)</translation>
<translation id="8609465669617005112">Yuxarı köçürün</translation>
+<translation id="861748745608658996">Æsas ekranınızda ad güncÉ™llÉ™nsin?</translation>
<translation id="8676374126336081632">Daxiletməni silin</translation>
<translation id="868929229000858085">Kontaktlarda axtarın</translation>
<translation id="8702612070107455751">Bütün oflayn data silinəcək.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Zoom</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC bu cihazda deaktivdir. <ph name="BEGIN_LINK" />Android Ayarlarında<ph name="END_LINK" /> onu aktiv edin.</translation>
-<translation id="8929372349074745002">Bu sayt əksər insanlar üçün sürətli açılır və işləyir</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Gizli rejimdən çıxılsın?</translation>
<translation id="8958424370300090006">Xüsusi sayt üçün kukiləri blok edin.</translation>
<translation id="8959122750345127698">Naviqasiya əlçatmazdır: <ph name="URL" /></translation>
<translation id="8986362086234534611">Unudun</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_be.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_be.xtb
index 8f57d641f3b..abeccc5a1e1 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_be.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_be.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="be">
<translation id="1006017844123154345">Ðдкрыць у інтÑрнÑце</translation>
<translation id="1044891598689252897">Сайты будуць працаваць нармальна</translation>
+<translation id="1100504063505580045">БÑгучы значок</translation>
<translation id="1124090076051167250">Будуць выдалены файлы cookie Ñ– Ð´Ð°Ð½Ñ‹Ñ (<ph name="DATASIZE" />), Ð·Ð°Ñ…Ð°Ð²Ð°Ð½Ñ‹Ñ Ñайтамі або размешчанымі на галоўным Ñкране праграмамі.</translation>
<translation id="1124772482545689468">КарыÑтальнік</translation>
<translation id="1178581264944972037">Прыпыніць</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Мікрафон</translation>
<translation id="3277252321222022663">Дазволіць Ñайтам доÑтуп да датчыкаў (Ñ€Ñкамендуецца)</translation>
<translation id="3295602654194328831">Схаваць інфармацыю</translation>
+<translation id="3317660236277031814">УÑталÑÐ²Ð°Ð½Ð°Ñ Ð²Ð°Ð¼Ñ– вÑб-праграма змÑніла значок.</translation>
<translation id="3328801116991980348">ЗвеÑткі пра Ñайт</translation>
<translation id="3333961966071413176">УÑе кантакты</translation>
<translation id="3386292677130313581">Пытацца, перш чым дазволіць Ñайтам атрымліваць інфармацыю пра ваша меÑцазнаходжанне (Ñ€Ñкамендуецца)</translation>
+<translation id="345699454248713913">УÑталÑÐ²Ð°Ð½Ð°Ñ Ð²Ð°Ð¼Ñ– вÑб-праграма змÑніла назву.</translation>
<translation id="3538390592868664640">Забараніць Ñайтам Ñтвараць 3D-карту вашага аÑÑÑ€Ð¾Ð´Ð´Ð·Ñ Ñ– адÑочваць Ñтановішча камеры</translation>
+<translation id="3551268116566418498">ВыйÑці з Ñ€Ñжыму інкогніта?</translation>
<translation id="3586500876634962664">ВыкарыÑтанне камеры Ñ– мікрафона</translation>
<translation id="358794129225322306">Дазволіць Ñайту аўтаматычна Ñпампоўваць некалькі файлаў.</translation>
<translation id="3594780231884063836">Выключыць гук відÑа</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Ðдкрыць налады меÑцазнаходжаннÑ</translation>
<translation id="4226663524361240545">ÐпавÑшчÑнні могуць уключаць вібрацыю прылады</translation>
<translation id="4259722352634471385">Пераход па наÑтупным адраÑе заблакіраваны: <ph name="URL" /></translation>
+<translation id="4277239631747669329">УÑталÑÐ²Ð°Ð½Ð°Ñ Ð²Ð°Ð¼Ñ– вÑб-праграма змÑніла назву Ñ– значок.</translation>
<translation id="4278390842282768270">Дазволена</translation>
<translation id="429312253194641664">Сайт прайграе мультымедыÑ</translation>
<translation id="42981349822642051">Разгарнуць</translation>
<translation id="4336434711095810371">Выдаліць уÑе даныÑ</translation>
<translation id="4402755511846832236">Ðе даваць Ñайтам знаць, калі вы карыÑтаецеÑÑ Ð³Ñтай прыладай</translation>
-<translation id="4433925000917964731">Старонка, ÑÐ¿Ñ€Ð¾ÑˆÑ‡Ð°Ð½Ð°Ñ Ð°Ð»Ð³Ð°Ñ€Ñ‹Ñ‚Ð¼Ð°Ð¼Ñ– Google</translation>
<translation id="4434045419905280838">УÑплыв. вокны Ñ– перанакіраванні</translation>
<translation id="445467742685312942">Дазволіць Ñайтам прайграваць абароненае змеÑціва</translation>
<translation id="4468959413250150279">Выключыць гук на канкрÑтным Ñайце.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Пад кіраваннем вашых бацькоў</translation>
<translation id="4670064810192446073">Ð’Ñ–Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ Ñ€ÑальнаÑць</translation>
<translation id="4708011789095599544">Ð’Ñ‹ ўпÑўненыÑ, што хочаце выдаліць файлы cookie Ñ– Ñ–Ð½ÑˆÑ‹Ñ Ð´Ð°Ð½Ñ‹Ñ Ñайта Ð´Ð»Ñ Ð³Ñтага вÑб-Ñайта?</translation>
+<translation id="473775607612524610">Ðбнавіць</translation>
<translation id="4751476147751820511">Датчыкі руху або ÑвÑтла</translation>
<translation id="4836046166855586901">Дазволіць Ñайтам запытваць інфармацыю пра тое, калі вы карыÑтаецеÑÑ Ð³Ñтай прыладай</translation>
<translation id="4883854917563148705">Ðалады, ÑÐºÑ–Ñ Ð·Ð½Ð°Ñ…Ð¾Ð´Ð·Ñцца пад кіраваннем, Ñкінуць нельга</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Ðбагуліць праз</translation>
<translation id="5039804452771397117">Дазволіць</translation>
<translation id="5048398596102334565">ДазвалÑць Ñайтам доÑтуп да датчыкаў руху (Ñ€Ñкамендуецца)</translation>
+<translation id="5050380848339752099">ГÑÑ‚Ñ‹ Ñайт будзе абагульваць звеÑткі з праграмай па-за Ñ€Ñжымам інкогніта.</translation>
<translation id="5063480226653192405">ВыкарыÑтанне</translation>
<translation id="5100237604440890931">Згорнута – каб разгарнуць, націÑніце тут.</translation>
<translation id="5123685120097942451">Укладка інкогніта</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Дазволіць Ñайтам запуÑкаць JavaScript (Ñ€Ñкамендавана)</translation>
<translation id="534295439873310000">Прылады NFC</translation>
<translation id="5354152178998424783">Будуць выдалены файлы cookie Ñ– Ð´Ð°Ð½Ñ‹Ñ (<ph name="DATASIZE" />), Ð·Ð°Ñ…Ð°Ð²Ð°Ð½Ñ‹Ñ Ñайтамі.</translation>
-<translation id="5384883051496921101">ГÑÑ‚Ñ‹ Ñайт будзе абагульваць звеÑткі з праграмай па-за Ñ€Ñжымам інкогніта.</translation>
+<translation id="536508626067510330">Ðбнавіць значок на галоўным Ñкране?</translation>
<translation id="5391532827096253100">Ваша падключÑнне да гÑтага Ñайта небÑÑпечнае. ЗвеÑткі пра Ñайт</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(Ñ– ÑÑˆÑ‡Ñ 1)}one{(Ñ– ÑÑˆÑ‡Ñ #)}few{(Ñ– ÑÑˆÑ‡Ñ #)}many{(Ñ– ÑÑˆÑ‡Ñ #)}other{(Ñ– ÑÑˆÑ‡Ñ #)}}</translation>
<translation id="5403592356182871684">Імёны</translation>
<translation id="5489227211564503167">Прайшло чаÑу: <ph name="ELAPSED_TIME" /> з <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Блакіраваць Ñ€Ñкламу на Ñайтах, ÑÐºÑ–Ñ Ð¿Ð°ÐºÐ°Ð·Ð²Ð°ÑŽÑ†ÑŒ назойлівую Ñ€Ñкламу або Ñ€Ñкламу, ÑÐºÐ°Ñ ÑžÐ²Ð¾Ð´Ð·Ñ–Ñ†ÑŒ у зман</translation>
+<translation id="549957179819296104">Ðовы значок</translation>
<translation id="5502860503640766021">Дазволена: <ph name="PERMISSION_1" />. Заблакіравана: <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Сайтам забаронена запытваць дазвол на паказ апавÑшчÑннÑÑž</translation>
<translation id="5516455585884385570">Ðдкрыць налады апавÑшчÑннÑÑž</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Дазволы</translation>
<translation id="5860033963881614850">Выключана</translation>
<translation id="5876056640971328065">Прыпыніць відÑа</translation>
+<translation id="5904826301761575486">Ðбнавіць Ñ–Ð¼Ñ Ñ– значок на галоўным Ñкране?</translation>
<translation id="5916664084637901428">Уключана</translation>
<translation id="5922853908706496913">Ваш Ñкран абагульваецца</translation>
<translation id="5939518447894949180">Скінуць</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Блакіраваць ÑÑ‚Ð°Ñ€Ð¾Ð½Ð½Ñ–Ñ Ñ„Ð°Ð¹Ð»Ñ‹ cookie</translation>
<translation id="6206551242102657620">ПадключÑнне бÑÑпечнае. ЗвеÑткі пра Ñайт</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" />: параметры</translation>
+<translation id="6260852843601447737">Закрыць Ñ– паÑкардзіцца на парушÑнне</translation>
<translation id="6262279340360821358">Заблакіравана: <ph name="PERMISSION_1" /> і <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Сайтам дазволена запытваць дазвол на паказ апавÑшчÑннÑÑž</translation>
<translation id="6295158916970320988">УÑе Ñайты</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Каб даць праграме "<ph name="APP_NAME" />" доÑтуп да даных пра ваша меÑцазнаходжанне, уключыце Ð°Ð¿Ð¾ÑˆÐ½Ñ–Ñ Ñž <ph name="BEGIN_LINK" />Ðаладах Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Ðдклікаць дазвол на доÑтуп да прылады</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{ВыкарыÑтоўваецца 1 файл cookie}one{ВыкарыÑтоўваецца # файл cookie}few{ВыкарыÑтоўваюцца # файлы cookie}many{ВыкарыÑтоўваюцца # файлаў cookie}other{ВыкарыÑтоўваюцца # файла cookie}}</translation>
-<translation id="8463851957836045671">Сайт хуткі</translation>
<translation id="8487700953926739672">ДаÑтупна па-за Ñеткай</translation>
<translation id="851751545965956758">Блакіраваць Ñайтам падключÑнне да прылад</translation>
<translation id="8525306231823319788">ПоўнаÑкранны Ñ€Ñжым</translation>
<translation id="857943718398505171">Дазволена (Ñ€Ñкамендуецца)</translation>
<translation id="8609465669617005112">ПерамÑÑціць уверх</translation>
+<translation id="861748745608658996">Ðбнавіць Ñ–Ð¼Ñ Ð½Ð° галоўным Ñкране?</translation>
<translation id="8676374126336081632">ÐчыÑціць поле ўводу</translation>
<translation id="868929229000858085">Пошук у кантактах</translation>
<translation id="8702612070107455751">УÑе пазаÑÐµÑ‚ÐºÐ°Ð²Ñ‹Ñ Ð´Ð°Ð½Ñ‹Ñ Ð±ÑƒÐ´ÑƒÑ†ÑŒ выдалены.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">ПавÑлічыць маштаб</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">Ð¤ÑƒÐ½ÐºÑ†Ñ‹Ñ NFC выключана на гÑтай прыладзе. Уключыце Ñе Ñž <ph name="BEGIN_LINK" />Ðаладах Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">У большаÑці карыÑтальнікаў гÑÑ‚Ñ‹ Ñайт адкрываецца Ñ– працуе хутка</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ВыйÑці з Ñ€Ñжыму інкогніта?</translation>
<translation id="8958424370300090006">Блакіраваць файлы cookie Ð´Ð»Ñ Ð¿Ñўнага Ñайта.</translation>
<translation id="8959122750345127698">Пераход па наÑтупным адраÑе недаÑтупны: <ph name="URL" /></translation>
<translation id="8986362086234534611">Забыць</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bg.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bg.xtb
index 2525d091e06..389422e4c84 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bg.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bg.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="bg">
<translation id="1006017844123154345">ОтварÑне онлайн</translation>
<translation id="1044891598689252897">Сайтовете ще работÑÑ‚ нормално</translation>
+<translation id="1100504063505580045">ÐаÑтоÑща икона</translation>
<translation id="1124090076051167250">СъхранÑваните от Ñайтовете или приложениÑта на Ð½Ð°Ñ‡Ð°Ð»Ð½Ð¸Ñ ÐµÐºÑ€Ð°Ð½ данни и „биÑквитки“ в размер на <ph name="DATASIZE" /> ще бъдат изчиÑтени.</translation>
<translation id="1124772482545689468">Потребител</translation>
<translation id="1178581264944972037">Пауза</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Микрофон</translation>
<translation id="3277252321222022663">Разрешаване на доÑтъпа на Ñайтовете до Ñензорите (препоръчително)</translation>
<translation id="3295602654194328831">Скриване на информациÑта</translation>
+<translation id="3317660236277031814">Има промÑна в иконата на инÑталирано от Ð²Ð°Ñ ÑƒÐµÐ± приложение.</translation>
<translation id="3328801116991980348">Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° Ñайта</translation>
<translation id="3333961966071413176">Ð’Ñички контакти</translation>
<translation id="3386292677130313581">Извеждане на запитване, преди на Ñайтовете да Ñе разреши доÑтъп до меÑтоположението ви (препоръчително)</translation>
+<translation id="345699454248713913">Има промÑна в името на инÑталирано от Ð²Ð°Ñ ÑƒÐµÐ± приложение.</translation>
<translation id="3538390592868664640">Блокиране на Ñайтовете, така че да не могат да Ñъздават триизмерна карта на заобикалÑщата ви Ñреда или да ÑледÑÑ‚ позициÑта на камерата</translation>
+<translation id="3551268116566418498">Излизане от режим „инкогнито“?</translation>
<translation id="3586500876634962664">Ползване на камерата и микрофона</translation>
<translation id="358794129225322306">Разрешаване на Ñайт автоматично да Ð¸Ð·Ñ‚ÐµÐ³Ð»Ñ Ð½Ñколко файла.</translation>
<translation id="3594780231884063836">Без образ</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">ОтварÑне на наÑтройките за меÑтоположението</translation>
<translation id="4226663524361240545">Възможно е уÑтройÑтвото да вибрира при извеÑтиÑ</translation>
<translation id="4259722352634471385">Ðавигирането е блокирано: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Има промÑна в името и иконата на инÑталирано от Ð²Ð°Ñ ÑƒÐµÐ± приложение.</translation>
<translation id="4278390842282768270">Разрешено</translation>
<translation id="429312253194641664">Сайт възпроизвежда мултимедийно Ñъдържание</translation>
<translation id="42981349822642051">Разгъване</translation>
<translation id="4336434711095810371">ИзчиÑтване на вÑички данни</translation>
<translation id="4402755511846832236">Блокиране на Ñайтовете, така че да не знаÑÑ‚ дали това уÑтройÑтво Ñе използва активно</translation>
-<translation id="4433925000917964731">Олекотена Ñтраница, предоÑтавена от Google</translation>
<translation id="4434045419905280838">ИзÑкач. прозорци и пренаÑочваниÑ</translation>
<translation id="445467742685312942">Разрешаване на Ñайтовете да възпроизвеждат защитено Ñъдържание</translation>
<translation id="4468959413250150279">Спиране на звука за конкретен Ñайт.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">УправлÑва Ñе от ваш родител</translation>
<translation id="4670064810192446073">Виртуална реалноÑÑ‚</translation>
<translation id="4708011789095599544">ÐаиÑтина ли иÑкате да изчиÑтите „биÑквитките“ и другите данни за този уебÑайт?</translation>
+<translation id="473775607612524610">Ðктуализиране</translation>
<translation id="4751476147751820511">Сензори за движение или Ñветлина</translation>
<translation id="4836046166855586901">Извеждане на запитване, когато Ñайт иÑка да знае кога това уÑтройÑтво Ñе използва активно</translation>
<translation id="4883854917563148705">УправлÑваните наÑтройки не могат да Ñе зададат отново</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">СподелÑне чрез</translation>
<translation id="5039804452771397117">Разрешаване</translation>
<translation id="5048398596102334565">Разрешаване на доÑтъпа на Ñайтовете до Ñензорите за движение (препоръчително)</translation>
+<translation id="5050380848339752099">Този Ñайт е напът да Ñподели Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ðµ, което не е в режим „инкогнито“.</translation>
<translation id="5063480226653192405">Употреба</translation>
<translation id="5100237604440890931">Свито – кликнете за разгъване.</translation>
<translation id="5123685120097942451">Раздел в режим „инкогнито“</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Разрешаване на Ñайтовете да изпълнÑват JavaScript (препоръчително)</translation>
<translation id="534295439873310000">УÑтройÑтва Ñ NFC</translation>
<translation id="5354152178998424783">СъхранÑваните от Ñайтовете данни и „биÑквитки“ в размер на <ph name="DATASIZE" /> ще бъдат изчиÑтени.</translation>
-<translation id="5384883051496921101">Този Ñайт е напът да Ñподели Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ðµ, което не е в режим „инкогнито“.</translation>
+<translation id="536508626067510330">Да Ñе актуализира ли иконата на Ð½Ð°Ñ‡Ð°Ð»Ð½Ð¸Ñ ÐµÐºÑ€Ð°Ð½?</translation>
<translation id="5391532827096253100">Връзката ви Ñ Ñ‚Ð¾Ð·Ð¸ Ñайт не е защитена. Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° Ñайта</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(и още 1)}other{(и още #)}}</translation>
<translation id="5403592356182871684">Имена</translation>
<translation id="5489227211564503167">Изминало време: <ph name="ELAPSED_TIME" /> от <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Блокиране на рекламите от Ñайтове, на които Ñе показват натрапчиви или подвеждащи реклами</translation>
+<translation id="549957179819296104">Ðова икона</translation>
<translation id="5502860503640766021">ДоÑтъпът до <ph name="PERMISSION_1" /> е разрешен, а до <ph name="PERMISSION_2" /> е блокиран</translation>
<translation id="5505264765875738116">Сайтовете не могат да извеждат подкани за изпращане на извеÑтиÑ</translation>
<translation id="5516455585884385570">ОтварÑне на наÑтройките за извеÑтиÑ</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">РазрешениÑ</translation>
<translation id="5860033963881614850">Изключено</translation>
<translation id="5876056640971328065">ПоÑтавÑне на видеоклипа на пауза</translation>
+<translation id="5904826301761575486">Да Ñе актуализират ли името и иконата на Ð½Ð°Ñ‡Ð°Ð»Ð½Ð¸Ñ ÐµÐºÑ€Ð°Ð½?</translation>
<translation id="5916664084637901428">Включено</translation>
<translation id="5922853908706496913">Екранът ви Ñе ÑподелÑ</translation>
<translation id="5939518447894949180">Ðулиране</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Блокиране на „биÑквитките“ на трети Ñтрани</translation>
<translation id="6206551242102657620">Връзката е защитена. Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° Ñайта</translation>
<translation id="6216432067784365534">Опции за <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">ЗатварÑне и подаване на Ñигнал за злоупотреба</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> и <ph name="PERMISSION_2" /> Ñа блокирани</translation>
<translation id="6270391203985052864">Сайтовете могат да извеждат подкани за изпращане на извеÑтиÑ</translation>
<translation id="6295158916970320988">Ð’Ñички Ñайтове</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">За да разрешите на <ph name="APP_NAME" /> да оÑъщеÑтвÑва доÑтъп до меÑтоположението ви, то Ñ‚Ñ€Ñбва да бъде включено и от <ph name="BEGIN_LINK" />наÑтройките на Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">ОтмÑна на разрешението за доÑтъп до уÑтройÑтвото</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Използва Ñе 1 „биÑквитка“}other{Използват Ñе # „биÑквитки“}}</translation>
-<translation id="8463851957836045671">Сайтът е бърз</translation>
<translation id="8487700953926739672">Ðалице офлайн</translation>
<translation id="851751545965956758">Блокиране на Ñайтовете, така че да не Ñе Ñвързват Ñ ÑƒÑтройÑтва</translation>
<translation id="8525306231823319788">Ðа цÑл екран</translation>
<translation id="857943718398505171">Разрешено (препоръчително)</translation>
<translation id="8609465669617005112">Придвижване нагоре</translation>
+<translation id="861748745608658996">Да Ñе актуализира ли името на Ð½Ð°Ñ‡Ð°Ð»Ð½Ð¸Ñ ÐµÐºÑ€Ð°Ð½?</translation>
<translation id="8676374126336081632">ИзчиÑтване на въведеното</translation>
<translation id="868929229000858085">ТърÑене в контактите ви</translation>
<translation id="8702612070107455751">Ð’Ñички офлайн данни ще бъдат изчиÑтени.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Увеличаване на мащаба</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">ФункциÑта за NFC е изключена на това уÑтройÑтво. Включете Ñ Ð¾Ñ‚ <ph name="BEGIN_LINK" />наÑтройките на Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">За повечето хора този Ñайт Ñе Ð¾Ñ‚Ð²Ð°Ñ€Ñ Ð¸ реагира бързо</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Излизане от режим „инкогнито“?</translation>
<translation id="8958424370300090006">Блокиране на „биÑквитките“ за конкретен Ñайт.</translation>
<translation id="8959122750345127698">Ðавигирането не е възможно: <ph name="URL" /></translation>
<translation id="8986362086234534611">ЗабравÑне</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bn.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bn.xtb
index d167eacc96d..65d94995c7d 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bn.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bn.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="bn">
<translation id="1006017844123154345">অনলাইনে খà§à¦²à§à¦¨</translation>
<translation id="1044891598689252897">সাইট সà§à¦¬à¦¾à¦­à¦¾à¦¬à¦¿à¦•à¦­à¦¾à¦¬à§‡à¦‡ কাজ করবে</translation>
+<translation id="1100504063505580045">বরà§à¦¤à¦®à¦¾à¦¨ আইকন</translation>
<translation id="1124090076051167250">à¦à¦Ÿà¦¿ করলে, আপনার হোম সà§à¦•à§à¦°à¦¿à¦¨à§‡ সাইট বা অà§à¦¯à¦¾à¦ªà§‡à¦° মাধà§à¦¯à¦®à§‡ সেভ হওয়া <ph name="DATASIZE" /> ডেটা à¦à¦¬à¦‚ কà§à¦•à¦¿ মà§à¦›à§‡ যাবে।</translation>
<translation id="1124772482545689468">বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€</translation>
<translation id="1178581264944972037">বিরতি</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">মাইকà§à¦°à§‹à¦«à§‹à¦¨</translation>
<translation id="3277252321222022663">সাইটকে সেনà§à¦¸à¦° অà§à¦¯à¦¾à¦•à§à¦¸à§‡à¦¸ করার অনà§à¦®à¦¤à¦¿ দিন (সাজেসà§à¦Ÿ করা হয়)</translation>
<translation id="3295602654194328831">তথà§à¦¯ লà§à¦•à¦¾à¦¨</translation>
+<translation id="3317660236277031814">আপনার ইনসà§à¦Ÿà¦² করা ওয়েব অà§à¦¯à¦¾à¦ªà§‡à¦° আইকন পরিবরà§à¦¤à¦¨ করা হয়েছে।</translation>
<translation id="3328801116991980348">সাইট তথà§à¦¯</translation>
<translation id="3333961966071413176">সব পরিচিতি</translation>
<translation id="3386292677130313581">সাইটগà§à¦²à¦¿à¦•à§‡ আপনার লোকেশন জানতে দিতে মঞà§à¦œà§à¦°à¦¿ দেওয়ার আগে জিজà§à¦žà¦¾à¦¸à¦¾ করà§à¦¨ (পà§à¦°à¦¸à§à¦¤à¦¾à¦¬à¦¿à¦¤)</translation>
+<translation id="345699454248713913">আপনার ইনসà§à¦Ÿà¦² করা ওয়েব অà§à¦¯à¦¾à¦ªà§‡à¦° নাম পরিবরà§à¦¤à¦¨ করা হয়েছে।</translation>
<translation id="3538390592868664640">আপনার আশেপাশের à¦à¦²à¦¾à¦•à¦¾à¦° à¦à¦•à¦Ÿà¦¿ 3D মà§à¦¯à¦¾à¦ª তৈরি করা বা কà§à¦¯à¦¾à¦®à§‡à¦°à¦¾à¦° অবসà§à¦¥à¦¾à¦¨ টà§à¦°à§à¦¯à¦¾à¦• করার কাজে নিযà§à¦•à§à¦¤ সাইটগà§à¦²à¦¿à¦•à§‡ বà§à¦²à¦• করে দিন</translation>
+<translation id="3551268116566418498">ছদà§à¦®à¦¬à§‡à¦¶à§€ মোড ছেড়ে বেরিয়ে আসবেন?</translation>
<translation id="3586500876634962664">কà§à¦¯à¦¾à¦®à§‡à¦°à¦¾ ও মাইকà§à¦°à§‹à¦«à§‹à¦¨à§‡à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦°</translation>
<translation id="358794129225322306">à¦à¦•à¦Ÿà¦¿ সাইটকে à¦à¦•à¦¾à¦§à¦¿à¦• ফাইল অটোমেটিক ডাউনলোড করার অনà§à¦®à¦¤à¦¿ দিন।</translation>
<translation id="3594780231884063836">ভিডিওটি মিউট করà§à¦¨</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">লোকেশন সেটিংস খà§à¦²à§à¦¨</translation>
<translation id="4226663524361240545">বিজà§à¦žà¦ªà§à¦¤à¦¿ আসলে ডিভাইস ভাইবà§à¦°à§‡à¦Ÿ হতে পারে</translation>
<translation id="4259722352634471385">নেভিগেশন অবরà§à¦¦à§à¦§ করা হয়েছে: <ph name="URL" /></translation>
+<translation id="4277239631747669329">আপনার ইনসà§à¦Ÿà¦² করা ওয়েব অà§à¦¯à¦¾à¦ªà§‡à¦° নাম ও আইকন পরিবরà§à¦¤à¦¨ করা হয়েছে।</translation>
<translation id="4278390842282768270">মঞà§à¦œà§à¦°à¦¿à¦ªà§à¦°à¦¾à¦ªà§à¦¤</translation>
<translation id="429312253194641664">à¦à¦•à¦Ÿà¦¿ সাইট মিডিয়া চালাচà§à¦›à§‡</translation>
<translation id="42981349822642051">পà§à¦°à¦¸à¦¾à¦°à¦¿à¦¤ করà§à¦¨</translation>
<translation id="4336434711095810371">সব ডেটা মà§à¦›à§‡ ফেলà§à¦¨</translation>
<translation id="4402755511846832236">আপনি ডিভাইস কখন সকà§à¦°à¦¿à§Ÿà¦­à¦¾à¦¬à§‡ বà§à¦¯à¦¬à¦¹à¦¾à¦° করছেন, সাইট যাতে জানতে না পারে তার জনà§à¦¯ সাইট বà§à¦²à¦• করà§à¦¨</translation>
-<translation id="4433925000917964731">Google লাইট পৃষà§à¦ à¦¾ পাঠিয়েছে</translation>
<translation id="4434045419905280838">পপ-আপ à¦à¦¬à¦‚ রিডাইরেকà§à¦Ÿ</translation>
<translation id="445467742685312942">সাইটকে সà§à¦°à¦•à§à¦·à¦¿à¦¤ কনà§à¦Ÿà§‡à¦¨à§à¦Ÿ চালানোর জনà§à¦¯ অনà§à¦®à¦¤à¦¿ দিন</translation>
<translation id="4468959413250150279">নিরà§à¦¦à¦¿à¦·à§à¦Ÿ কোনও সাইটের জনà§à¦¯ সাউনà§à¦¡ মিউট করà§à¦¨à¥¤</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">আপনার পিতামাতার দà§à¦¬à¦¾à¦°à¦¾ পরিচালিত</translation>
<translation id="4670064810192446073">ভারà§à¦šà§à¦¯à¦¼à¦¾à¦² রিয়ালিটি</translation>
<translation id="4708011789095599544">আপনি কি সতà§à¦¯à¦¿à¦‡ à¦à¦‡ ওয়েবসাইটে কà§à¦•à¦¿ ও অনà§à¦¯à¦¾à¦¨à§à¦¯ সাইট ডেটা মà§à¦›à§‡ দিতে চান?</translation>
+<translation id="473775607612524610">আপডেট করà§à¦¨</translation>
<translation id="4751476147751820511">মোশন বা হালকা সেনà§à¦¸à¦°</translation>
<translation id="4836046166855586901">সাইটকে à¦à¦Ÿà¦¿ জানতে দিন যে à¦à¦‡ ডিভাইসের বà§à¦¯à¦¬à¦¹à¦¾à¦° আপনি সকà§à¦°à¦¿à§Ÿà¦­à¦¾à¦¬à§‡ কখন করেন</translation>
<translation id="4883854917563148705">মà§à¦¯à¦¾à¦¨à§‡à¦œ করা সেটিংস রিসেট করা যায় না</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">à¦à¦° মাধà§à¦¯à¦®à§‡ শেয়ার করà§à¦¨</translation>
<translation id="5039804452771397117">অনà§à¦®à¦¤à¦¿ দিন</translation>
<translation id="5048398596102334565">সাইটকে মোশন সেনà§à¦¸à¦° অà§à¦¯à¦¾à¦•à§à¦¸à§‡à¦¸ করার অনà§à¦®à¦¤à¦¿ দিন (সাজেসà§à¦Ÿ করা হয়)</translation>
+<translation id="5050380848339752099">à¦à¦‡ সাইট ছদà§à¦®à¦¬à§‡à¦¶à§€ মোডের বাইরে à¦à¦•à¦Ÿà¦¿ অà§à¦¯à¦¾à¦ªà§‡à¦° সাথে তথà§à¦¯ শেয়ার করতে চলেছে।</translation>
<translation id="5063480226653192405">বà§à¦¯à¦¬à¦¹à¦¾à¦°</translation>
<translation id="5100237604440890931">সঙà§à¦•à§à¦šà¦¿à¦¤ - পà§à¦°à¦¸à¦¾à¦°à¦¿à¦¤ করতে কà§à¦²à¦¿à¦• করà§à¦¨à§·</translation>
<translation id="5123685120097942451">ছদà§à¦®à¦¬à§‡à¦¶à§€ টà§à¦¯à¦¾à¦¬</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">সাইটগà§à¦²à¦¿à¦•à§‡ JavaScript চালানোর অনà§à¦®à¦¤à¦¿ দিন (পà§à¦°à¦¸à§à¦¤à¦¾à¦¬à¦¿à¦¤)</translation>
<translation id="534295439873310000">NFC ডিভাইস</translation>
<translation id="5354152178998424783">à¦à¦Ÿà¦¿ করলে, সাইটে সেভ থাকা <ph name="DATASIZE" /> ডেটা ও কà§à¦•à¦¿ মà§à¦›à§‡ যাবে।</translation>
-<translation id="5384883051496921101">à¦à¦‡ সাইটটি ছদà§à¦®à¦¬à§‡à¦¶à§€ মোডের বাইরের à¦à¦•à¦Ÿà¦¿ অà§à¦¯à¦¾à¦ªà§‡à¦° সাথে তথà§à¦¯ শেয়ার করতে চলেছে।</translation>
+<translation id="536508626067510330">আপনার হোম সà§à¦•à§à¦°à¦¿à¦¨à§‡ আইকন আপডেট করবেন?</translation>
<translation id="5391532827096253100">à¦à¦‡ সাইটে আপনার কানেকশন নিরাপদ নয়। সাইটের তথà§à¦¯</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(à¦à¦›à¦¾à¦¡à¦¼à¦¾ আরও ১টি)}one{(à¦à¦›à¦¾à¦¡à¦¼à¦¾ আরও #টি)}other{(à¦à¦›à¦¾à¦¡à¦¼à¦¾ আরও #টি)}}</translation>
<translation id="5403592356182871684">নাম</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" />-à¦à¦° মধà§à¦¯à§‡ <ph name="ELAPSED_TIME" /> সময় অতিবাহিত হয়েছে।</translation>
<translation id="5494752089476963479">সাইটে থাকা বà§à¦¯à¦¾à¦˜à¦¾à¦¤ সৃষà§à¦Ÿà¦¿à¦•à¦¾à¦°à§€ বা বিভà§à¦°à¦¾à¦¨à§à¦¤à¦¿à¦•à¦° বিজà§à¦žà¦¾à¦ªà¦¨ বà§à¦²à¦• করà§à¦¨</translation>
+<translation id="549957179819296104">নতà§à¦¨ আইকন</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> বà§à¦¯à¦¬à¦¹à¦¾à¦°à§‡à¦° অনà§à¦®à¦¤à¦¿ দেওয়া হয়েছে, <ph name="PERMISSION_2" /> বà§à¦²à¦• করা হয়েছে</translation>
<translation id="5505264765875738116">সাইট আপনাকে বিজà§à¦žà¦ªà§à¦¤à¦¿ পাঠাতে পারবে না</translation>
<translation id="5516455585884385570">বিজà§à¦žà¦ªà§à¦¤à¦¿à¦° সেটিংস খà§à¦²à§à¦¨</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">অনà§à¦®à¦¤à¦¿à¦—à§à¦²à¦¿</translation>
<translation id="5860033963881614850">বনà§à¦§ করà§à¦¨</translation>
<translation id="5876056640971328065">ভিডিও পজ করà§à¦¨</translation>
+<translation id="5904826301761575486">আপনার হোম সà§à¦•à§à¦°à¦¿à¦¨à§‡ নাম ও আইকন আপডেট করবেন?</translation>
<translation id="5916664084637901428">চালà§</translation>
<translation id="5922853908706496913">আপনার সà§à¦•à§à¦°à¦¿à¦¨ শেয়ার করা হচà§à¦›à§‡</translation>
<translation id="5939518447894949180">রিসেট করà§à¦¨</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">তৃতীয় পকà§à¦·à§‡à¦° কà§à¦•à¦¿à¦œ অবরà§à¦¦à§à¦§ করà§à¦¨</translation>
<translation id="6206551242102657620">কানেকশনটি নিরাপদ। সাইট তথà§à¦¯</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> à¦à¦° বিকলà§à¦ªà¦—à§à¦²à¦¿</translation>
+<translation id="6260852843601447737">বনà§à¦§ করà§à¦¨ à¦à¦¬à¦‚ অপবà§à¦¯à¦¬à¦¹à¦¾à¦°à§‡à¦° বিষয়ে অভিযোগ জানান</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> ও <ph name="PERMISSION_2" /> বà§à¦²à¦• করা হয়েছে</translation>
<translation id="6270391203985052864">সাইট আপনাকে বিজà§à¦žà¦ªà§à¦¤à¦¿ পাঠানোর আগে অনà§à¦®à¦¤à¦¿ চাইতে পারে</translation>
<translation id="6295158916970320988">সমসà§à¦¤ সাইট</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">তাছাড়া, যাতে <ph name="APP_NAME" /> আপনার লোকেশন অà§à¦¯à¦¾à¦•à§à¦¸à§‡à¦¸ করতে পারে, তার জনà§à¦¯ <ph name="BEGIN_LINK" />Android সেটিংসে<ph name="END_LINK" /> গিয়েও লোকেশন চালৠকরে দিন।</translation>
<translation id="8447861592752582886">ডিভাইসের অনà§à¦®à¦¤à¦¿ পà§à¦°à¦¤à§à¦¯à¦¾à¦¹à¦¾à¦° করà§à¦¨</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{১টি কà§à¦•à¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করা হচà§à¦›à§‡}one{#টি কà§à¦•à¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করা হচà§à¦›à§‡}other{#টি কà§à¦•à¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করা হচà§à¦›à§‡}}</translation>
-<translation id="8463851957836045671">সাইট খà§à¦¬ দà§à¦°à§à¦¤ লোড হয়</translation>
<translation id="8487700953926739672">অফলাইনে উপলবà§à¦§</translation>
<translation id="851751545965956758">সাইটকে ডিভাইসের সাথে কানেকà§à¦Ÿ করা থেকে বà§à¦²à¦• করà§à¦¨</translation>
<translation id="8525306231823319788">পূরà§à¦£ সà§à¦•à§à¦°à§€à¦£</translation>
<translation id="857943718398505171">অনà§à¦®à§‹à¦¦à¦¿à¦¤ (পà§à¦°à¦¸à§à¦¤à¦¾à¦¬à¦¿à¦¤)</translation>
<translation id="8609465669617005112">উপরে যান</translation>
+<translation id="861748745608658996">আপনার হোম সà§à¦•à§à¦°à¦¿à¦¨à§‡ নাম আপডেট করবেন?</translation>
<translation id="8676374126336081632">ইনপà§à¦Ÿ সাফ করà§à¦¨</translation>
<translation id="868929229000858085">আপনার পরিচিতি সারà§à¦š করà§à¦¨</translation>
<translation id="8702612070107455751">যেকোনও অফলাইন ডেটা মà§à¦›à§‡ ফেলা হবে।</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">জà§à¦® বাড়ান</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">à¦à¦‡ ডিভাইসে NFC বনà§à¦§ আছে। <ph name="BEGIN_LINK" />Android সেটিংস<ph name="END_LINK" /> থেকে à¦à¦Ÿà¦¿ চালৠকরà§à¦¨à¥¤</translation>
-<translation id="8929372349074745002">বেশিরভাগ লোকের কà§à¦·à§‡à¦¤à§à¦°à§‡ à¦à¦‡ সাইট খà§à¦¬ কম সময়ের মধà§à¦¯à§‡à¦‡ খà§à¦²à§‡à¦“ যায় à¦à¦¬à¦‚ à¦à¦–ান থেকে সব রকম উতà§à¦¤à¦°à¦“ পান</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ছদà§à¦®à¦¬à§‡à¦¶à§€ মোড ছেড়ে বেরোবেন?</translation>
<translation id="8958424370300090006">কোনও নিরà§à¦¦à¦¿à¦·à§à¦Ÿ সাইটের জনà§à¦¯ কà§à¦•à¦¿ বà§à¦²à¦• করà§à¦¨à¥¤</translation>
<translation id="8959122750345127698">নেভিগেশানে পৌছানো যাচà§à¦›à§‡ না: <ph name="URL" /></translation>
<translation id="8986362086234534611">ভà§à¦²à§‡ যান</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bs.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bs.xtb
index 23bbbe7c5dd..fd4342166e8 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bs.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_bs.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="bs">
<translation id="1006017844123154345">Otvori na mreži</translation>
<translation id="1044891598689252897">Web lokacije će normalno funkcionirati</translation>
+<translation id="1100504063505580045">Trenutna ikona</translation>
<translation id="1124090076051167250">Ovim će se obrisati <ph name="DATASIZE" /> podataka i kolaÄića koje su pohranile web lokacije ili aplikacije na poÄetnom ekranu.</translation>
<translation id="1124772482545689468">Korisnik</translation>
<translation id="1178581264944972037">Pauziraj</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Dozvolite web lokacijama pristup senzorima (preporuÄeno)</translation>
<translation id="3295602654194328831">Sakrij informacije</translation>
+<translation id="3317660236277031814">Ikona web aplikacije koju ste instalirali je promijenjena.</translation>
<translation id="3328801116991980348">Informacije o web lokaciji</translation>
<translation id="3333961966071413176">Svi kontakti</translation>
<translation id="3386292677130313581">Web lokacije moraju tražiti dozvolu za pristup lokaciji (preporuÄeno)</translation>
+<translation id="345699454248713913">Naziv web aplikacije koju ste instalirali je promijenjen.</translation>
<translation id="3538390592868664640">Web lokacijama je blokirano kreiranje 3D mape vašeg okruženja ili praćenje položaja kamere</translation>
+<translation id="3551268116566418498">Napustiti anonimni naÄina rada?</translation>
<translation id="3586500876634962664">Korištenje kamere i mikrofona</translation>
<translation id="358794129225322306">Dozvolite web lokaciji automatsko preuzimanje više fajlova.</translation>
<translation id="3594780231884063836">IskljuÄivanje zvuka videozapisa</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Otvaranje postavki lokacije</translation>
<translation id="4226663524361240545">Obavještenja mogu aktivirati vibraciju uređaja</translation>
<translation id="4259722352634471385">Navigacija je blokirana: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Naziv i ikona web aplikacije koju ste instalirali su promijenjeni.</translation>
<translation id="4278390842282768270">Dozvoljeno</translation>
<translation id="429312253194641664">Web lokacija reproducira medij</translation>
<translation id="42981349822642051">Proširi</translation>
<translation id="4336434711095810371">Obriši sve podatke</translation>
<translation id="4402755511846832236">Blokirajte web lokacijama informacije o vašem aktivnom korištenju ovog uređaja</translation>
-<translation id="4433925000917964731">Jednostavnu stranicu omogućava Google</translation>
<translation id="4434045419905280838">SkoÄni proz. i preusmjeravanja</translation>
<translation id="445467742685312942">Dozvoljava web lokacijama da reproduciraju zaštićen sadržaj</translation>
<translation id="4468959413250150279">IskljuÄen zvuk za odreÄ‘enu web lokaciju.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Upravlja roditelj</translation>
<translation id="4670064810192446073">Virtuelna realnost</translation>
<translation id="4708011789095599544">Jeste li sigurni da želite obrisati kolaÄiće i druge podatke za ovu web lokaciju?</translation>
+<translation id="473775607612524610">Ažuriraj</translation>
<translation id="4751476147751820511">Senzori pokreta ili svjetla</translation>
<translation id="4836046166855586901">Traži odobrenje kada web lokacija želi pristupiti informacijama o mom aktivnom korištenju ovog uređaja</translation>
<translation id="4883854917563148705">Upravljane postavke se ne mogu poništiti</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Dijeljenje koristeći</translation>
<translation id="5039804452771397117">Dozvoli</translation>
<translation id="5048398596102334565">Dozvoli web lokacijama pristup senzorima pokreta (preporuÄeno)</translation>
+<translation id="5050380848339752099">Ova web lokacija će podijeliti informacije s aplikacijom izvan anonimnog naÄina rada.</translation>
<translation id="5063480226653192405">Korištenje</translation>
<translation id="5100237604440890931">Suženo – kliknite da proširite.</translation>
<translation id="5123685120097942451">Anonimna kartica</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Web-lokacije mogu pokretati JavaScript (preporuÄeno)</translation>
<translation id="534295439873310000">NFC uređaji</translation>
<translation id="5354152178998424783">Ovim će se obrisati <ph name="DATASIZE" /> podataka i kolaÄića koje su pohranile web lokacije.</translation>
-<translation id="5384883051496921101">Ova stranica će podijeliti informacije s aplikacijom izvan anonimnog naÄina rada.</translation>
+<translation id="536508626067510330">Ažurirati ikonu na poÄetnom ekranu?</translation>
<translation id="5391532827096253100">Veza s web lokacijom nije sigurna. Informacije o web lokaciji</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(i još 1)}one{(i još #)}few{(i još #)}other{(i još #)}}</translation>
<translation id="5403592356182871684">Imena</translation>
<translation id="5489227211564503167">Proteklo vrijeme <ph name="ELAPSED_TIME" /> od <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blokiraj oglase na web lokacijama koje prikazuju nametljive ili obmanjujuće oglase</translation>
+<translation id="549957179819296104">Nova ikona</translation>
<translation id="5502860503640766021">Dozvoljeno: <ph name="PERMISSION_1" />, blokirano: <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Web lokacije ne mogu tražiti da šalju obavještenja</translation>
<translation id="5516455585884385570">Otvori postavke obavještenja</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Odobrenja</translation>
<translation id="5860033963881614850">Isklj.</translation>
<translation id="5876056640971328065">Pauziranje videozapisa</translation>
+<translation id="5904826301761575486">Ažurirati naziv i ikonu na poÄetnom ekranu?</translation>
<translation id="5916664084637901428">UkljuÄeno</translation>
<translation id="5922853908706496913">Dijeljenje ekrana</translation>
<translation id="5939518447894949180">Ponovno postavi</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokiraj kolaÄiće trećih strana</translation>
<translation id="6206551242102657620">Veza je sigurna. Informacije o web lokaciji</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> opcije</translation>
+<translation id="6260852843601447737">Zatvori i prijavi zloupotrebu</translation>
<translation id="6262279340360821358">Blokirano: <ph name="PERMISSION_1" /> i <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Web lokacije mogu tražiti da šalju obavještenja</translation>
<translation id="6295158916970320988">Sve web-lokacije</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Da dozvolite da <ph name="APP_NAME" /> pristupa vaÅ¡oj lokaciji, takoÄ‘er ukljuÄite lokaciju u <ph name="BEGIN_LINK" />Postavkama Androida<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Opozivanje dozvole za uređaj</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Koristi se 1 kolaÄić}one{Koristi se # kolaÄić}few{Koriste se # kolaÄića}other{Koristi se # kolaÄića}}</translation>
-<translation id="8463851957836045671">Web lokacija je brza</translation>
<translation id="8487700953926739672">Dostupno van mreže</translation>
<translation id="851751545965956758">Blokiraj povezivanje web-lokacija s uređajima</translation>
<translation id="8525306231823319788">Cijeli ekran</translation>
<translation id="857943718398505171">Dozvoljeno (preporuÄeno)</translation>
<translation id="8609465669617005112">Pomjeri nagore</translation>
+<translation id="861748745608658996">Ažurirati naziv na poÄetnom ekranu?</translation>
<translation id="8676374126336081632">Brisanje unosa</translation>
<translation id="868929229000858085">Pretražite kontakte</translation>
<translation id="8702612070107455751">Obrisat će se svi offline podaci.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Uvećaj</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC je iskljuÄen na ovom ureÄ‘aju. UkljuÄite ga u <ph name="BEGIN_LINK" />Postavkama Androida<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Ova web lokacija se otvara i reagira brzo kod većine korisnika</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Izaći iz anonimnog naÄina rada?</translation>
<translation id="8958424370300090006">Blokiranje kolaÄića za odreÄ‘enu web lokaciju.</translation>
<translation id="8959122750345127698">Navigacija je nedostupna: <ph name="URL" /></translation>
<translation id="8986362086234534611">Zaboravi</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ca.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ca.xtb
index 79e1a6713ad..64b7a67dcb0 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ca.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ca.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ca">
<translation id="1006017844123154345">Obre en línia</translation>
<translation id="1044891598689252897">Els llocs web funcionaran amb normalitat</translation>
+<translation id="1100504063505580045">Icona actual</translation>
<translation id="1124090076051167250">Amb aquesta acció s'esborraran dades i galetes emmagatzemades pels llocs web o les aplicacions de la pantalla d'inici (<ph name="DATASIZE" />).</translation>
<translation id="1124772482545689468">Usuari</translation>
<translation id="1178581264944972037">Posa en pausa</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Micròfon</translation>
<translation id="3277252321222022663">Permet que els llocs web accedeixin als sensors (opció recomanada)</translation>
<translation id="3295602654194328831">Amaga la informació</translation>
+<translation id="3317660236277031814">S'ha canviat la icona d'una aplicació web que has instal·lat.</translation>
<translation id="3328801116991980348">Informació del lloc web</translation>
<translation id="3333961966071413176">Tots els contactes</translation>
<translation id="3386292677130313581">Pregunta abans de permetre que els llocs web sàpiguen la teva ubicació (opció recomanada)</translation>
+<translation id="345699454248713913">S'ha canviat el nom d'una aplicació web que has instal·lat.</translation>
<translation id="3538390592868664640">Impedeix que els llocs web creïn un mapa en 3D del teu entorn o que facin un seguiment de la posició de la càmera</translation>
+<translation id="3551268116566418498">Vols sortir del mode d'incògnit?</translation>
<translation id="3586500876634962664">Ús de la càmera i el micròfon</translation>
<translation id="358794129225322306">Permet que un lloc web baixi diversos fitxers automàticament.</translation>
<translation id="3594780231884063836">Silencia el vídeo</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Obre la configuració d'ubicació</translation>
<translation id="4226663524361240545">És possible que les notificacions facin vibrar el dispositiu</translation>
<translation id="4259722352634471385">S'ha bloquejat la navegació: <ph name="URL" /></translation>
+<translation id="4277239631747669329">S'ha canviat el nom i la icona d'una aplicació web que has instal·lat.</translation>
<translation id="4278390842282768270">Permès</translation>
<translation id="429312253194641664">Un lloc web està reproduint contingut multimèdia</translation>
<translation id="42981349822642051">Desplega</translation>
<translation id="4336434711095810371">Esborra totes les dades</translation>
<translation id="4402755511846832236">Bloqueja els llocs web perquè no sàpiguen quan estàs utilitzant aquest dispositiu de manera activa</translation>
-<translation id="4433925000917964731">Pàgina en mode bàsic oferida per Google</translation>
<translation id="4434045419905280838">Finestres emergents i redireccions</translation>
<translation id="445467742685312942">Permet que els llocs web reprodueixin contingut protegit</translation>
<translation id="4468959413250150279">Silencia el so d'un lloc web concret.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Gestionat pels pares</translation>
<translation id="4670064810192446073">Realitat virtual</translation>
<translation id="4708011789095599544">Confirmes que vols esborrar les galetes i altres dades d'aquest lloc web?</translation>
+<translation id="473775607612524610">Actualitza</translation>
<translation id="4751476147751820511">Sensors de moviment o de llum</translation>
<translation id="4836046166855586901">Pregunta'm quan un lloc web vulgui saber quan estic utilitzant aquest dispositiu de manera activa</translation>
<translation id="4883854917563148705">Les opcions de configuració gestionades no es poden restablir</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Comparteix mitjançant</translation>
<translation id="5039804452771397117">Permet</translation>
<translation id="5048398596102334565">Permet que els llocs web accedeixin als sensors de moviment (opció recomanada)</translation>
+<translation id="5050380848339752099">Aquest lloc web està a punt de compartir informació amb una aplicació fora del mode d'incògnit.</translation>
<translation id="5063480226653192405">Ús</translation>
<translation id="5100237604440890931">Vista replegada (feu clic per desplegar-la)</translation>
<translation id="5123685120097942451">Pestanya d'incògnit</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Permet que els llocs web executin JavaScript (opció recomanada)</translation>
<translation id="534295439873310000">Dispositius amb NFC</translation>
<translation id="5354152178998424783">Amb aquesta acció s'esborraran dades i galetes (<ph name="DATASIZE" />) emmagatzemades per llocs web.</translation>
-<translation id="5384883051496921101">Aquest lloc està a punt de compartir informació amb una aplicació fora del mode d'incògnit.</translation>
+<translation id="536508626067510330">Vols actualitzar la icona a la pantalla d'inici?</translation>
<translation id="5391532827096253100">La connexió amb aquest lloc web no és segura. Informació del lloc web</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(i 1 més)}other{(i # més)}}</translation>
<translation id="5403592356182871684">Noms</translation>
<translation id="5489227211564503167">Temps transcorregut: <ph name="ELAPSED_TIME" /> de <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Bloqueja els anuncis als llocs web que mostren publicitat intrusiva o enganyosa</translation>
+<translation id="549957179819296104">Icona nova</translation>
<translation id="5502860503640766021">S'ha permès <ph name="PERMISSION_1" />. S'ha bloquejat <ph name="PERMISSION_2" />.</translation>
<translation id="5505264765875738116">Els llocs web no poden demanar-te permís per enviar-te notificacions</translation>
<translation id="5516455585884385570">Obre la configuració de notificacions</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Permisos</translation>
<translation id="5860033963881614850">Desactivat</translation>
<translation id="5876056640971328065">Posa en pausa el vídeo</translation>
+<translation id="5904826301761575486">Vols actualitzar el nom i la icona que apareixen a la pantalla d'inici?</translation>
<translation id="5916664084637901428">Activat</translation>
<translation id="5922853908706496913">S'està compartint la pantalla</translation>
<translation id="5939518447894949180">Restableix</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Bloqueja les galetes de tercers</translation>
<translation id="6206551242102657620">La connexió és segura. Informació del lloc web</translation>
<translation id="6216432067784365534">Opcions per a <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Tanca i informa d'un ús abusiu</translation>
<translation id="6262279340360821358">S'han bloquejat <ph name="PERMISSION_1" /> i <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Els llocs web poden demanar-te permís per enviar-te notificacions</translation>
<translation id="6295158916970320988">Tots els llocs web</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Perquè <ph name="APP_NAME" /> pugui accedir a la teva ubicació, també has d'activar-la a la <ph name="BEGIN_LINK" />configuració d'Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Revoca el permís d'accés al dispositiu</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 galeta en ús}other{# galetes en ús}}</translation>
-<translation id="8463851957836045671">El lloc web és ràpid</translation>
<translation id="8487700953926739672">Disponible sense connexió</translation>
<translation id="851751545965956758">Impedeix que els llocs web es connectin a dispositius</translation>
<translation id="8525306231823319788">Pantalla completa</translation>
<translation id="857943718398505171">Permès (opció recomanada)</translation>
<translation id="8609465669617005112">Desplaça cap amunt</translation>
+<translation id="861748745608658996">Vols actualitzar el nom que apareix a la pantalla d'inici?</translation>
<translation id="8676374126336081632">Esborra l'entrada</translation>
<translation id="868929229000858085">Cerca als contactes</translation>
<translation id="8702612070107455751">S'esborraran totes les dades sense connexió.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Amplia</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">L'NFC està desactivada en aquest dispositiu. Activa-la a la <ph name="BEGIN_LINK" />configuració d'Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Aquest lloc web s'obre i respon ràpidament per a la majoria de persones</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Vols sortir del mode d'incògnit?</translation>
<translation id="8958424370300090006">Bloqueja les galetes d'un lloc web concret.</translation>
<translation id="8959122750345127698">No es pot accedir a la navegació: <ph name="URL" /></translation>
<translation id="8986362086234534611">Oblida</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_cs.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_cs.xtb
index e9564f70d51..1014301ce71 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_cs.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_cs.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="cs">
<translation id="1006017844123154345">Otevřít online</translation>
<translation id="1044891598689252897">Weby budou fungovat normálně</translation>
+<translation id="1100504063505580045">Aktuální ikona</translation>
<translation id="1124090076051167250">Tímto vymažete <ph name="DATASIZE" /> dat a souborů cookie, které uložily weby nebo aplikace na ploše.</translation>
<translation id="1124772482545689468">Uživatel</translation>
<translation id="1178581264944972037">Pozastavit</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Povolit webům přístup k senzorům (doporuÄeno)</translation>
<translation id="3295602654194328831">Skrýt informace</translation>
+<translation id="3317660236277031814">Webová aplikace, kterou máte nainstalovanou, změnila svou ikonu.</translation>
<translation id="3328801116991980348">Informace o stránkách</translation>
<translation id="3333961966071413176">VÅ¡echny kontakty</translation>
<translation id="3386292677130313581">Pokud web bude chtít znát vaÅ¡i polohu, zobrazit dotaz (doporuÄeno)</translation>
+<translation id="345699454248713913">Webová aplikace, kterou máte nainstalovanou, se přejmenovala.</translation>
<translation id="3538390592868664640">Bránit webům ve vytváření 3D mapy okolí a ve sledování polohy kamery</translation>
+<translation id="3551268116566418498">UkonÄit anonymní režim?</translation>
<translation id="3586500876634962664">Využití fotoaparátu a mikrofonu</translation>
<translation id="358794129225322306">Povolit webu automaticky stáhnout několik souborů.</translation>
<translation id="3594780231884063836">Vypnout zvuk videa</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Otevřít nastavení polohy</translation>
<translation id="4226663524361240545">Oznámení mohou aktivovat vibraci</translation>
<translation id="4259722352634471385">Navigace je blokována: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Webová aplikace, kterou máte nainstalovanou, se přejmenovala a změnila svoji ikonu.</translation>
<translation id="4278390842282768270">Povoleno</translation>
<translation id="429312253194641664">Web přehrává média</translation>
<translation id="42981349822642051">Rozbalit</translation>
<translation id="4336434711095810371">Vymazat všechna data</translation>
<translation id="4402755511846832236">Nedovolit webům zjistit, kdy aktivně používáte toto zařízení</translation>
-<translation id="4433925000917964731">Zjednodušenou stránku poskytuje Google</translation>
<translation id="4434045419905280838">Vyskakovací okna a přesměrování</translation>
<translation id="445467742685312942">Povolit webům přehrávat chráněný obsah</translation>
<translation id="4468959413250150279">Vypne zvuk na konkrétním webu.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Spravováno vaším rodiÄem</translation>
<translation id="4670064810192446073">Virtuální realita</translation>
<translation id="4708011789095599544">Opravdu chcete vymazat soubory cookie a ostatní data tohoto webu?</translation>
+<translation id="473775607612524610">Aktualizovat</translation>
<translation id="4751476147751820511">Senzory pohybu nebo světla</translation>
<translation id="4836046166855586901">Zeptat se, když chce web zjistit, kdy aktivně používáte toto zařízení</translation>
<translation id="4883854917563148705">Spravovaná nastavení nelze resetovat</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Sdílet prostřednictvím</translation>
<translation id="5039804452771397117">Povolit</translation>
<translation id="5048398596102334565">Povolit webům přístup k senzorům pohybu (doporuÄeno)</translation>
+<translation id="5050380848339752099">Tento web chce sdílet informace s aplikací mimo anonymní režim.</translation>
<translation id="5063480226653192405">Použití</translation>
<translation id="5100237604440890931">Sbaleno – kliknutím rozbalíte</translation>
<translation id="5123685120097942451">Anonymní karta</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Povolit webům spouÅ¡tÄ›t JavaScript (doporuÄeno)</translation>
<translation id="534295439873310000">Zařízení NFC</translation>
<translation id="5354152178998424783">Tímto vymažete <ph name="DATASIZE" /> dat a souborů cookie, které uložily weby.</translation>
-<translation id="5384883051496921101">Tento web chce sdílet informace s aplikací mimo anonymní režim.</translation>
+<translation id="536508626067510330">Aktualizovat ikonu na ploše?</translation>
<translation id="5391532827096253100">Spojení s tímto webem není zabezpeÄené. Informace o webu</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 další)}few{(+ # další)}many{(+ # další)}other{(+ # dalších)}}</translation>
<translation id="5403592356182871684">Názvy</translation>
<translation id="5489227211564503167">Uplynulá doba: <ph name="ELAPSED_TIME" /> z <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blokovat reklamy na webech, které zobrazují obtěžující nebo zavádějící reklamy</translation>
+<translation id="549957179819296104">Nová ikona</translation>
<translation id="5502860503640766021">Oprávnění <ph name="PERMISSION_1" /> je povoleno, oprávnění <ph name="PERMISSION_2" /> je blokováno</translation>
<translation id="5505264765875738116">Weby nemohou žádat o oprávnění zasílat vám oznámení</translation>
<translation id="5516455585884385570">Otevřít nastavení oznámení</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Oprávnění</translation>
<translation id="5860033963881614850">Vypnuto</translation>
<translation id="5876056640971328065">Pozastavit video</translation>
+<translation id="5904826301761575486">Aktualizovat název a ikonu na ploše?</translation>
<translation id="5916664084637901428">Zapnuto</translation>
<translation id="5922853908706496913">Sdílíte obrazovku</translation>
<translation id="5939518447894949180">Resetovat</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokovat soubory cookie třetích stran</translation>
<translation id="6206551242102657620">PÅ™ipojení je zabezpeÄené. Informace o webu</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> – možnosti</translation>
+<translation id="6260852843601447737">Zavřít a nahlásit zneužití</translation>
<translation id="6262279340360821358">Oprávnění <ph name="PERMISSION_1" /> a <ph name="PERMISSION_2" /> jsou zablokována</translation>
<translation id="6270391203985052864">Weby mohou žádat o oprávnění zasílat vám oznámení</translation>
<translation id="6295158916970320988">VÅ¡echny weby</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Pokud aplikaci <ph name="APP_NAME" /> chcete povolit přístup ke své poloze, zapněte polohu také v <ph name="BEGIN_LINK" />Nastavení Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Zrušit oprávnění zařízení</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Je používán 1 soubor cookie}few{Jsou používány # soubory cookie}many{Je používáno # souboru cookie}other{Je používáno # souborů cookie}}</translation>
-<translation id="8463851957836045671">Web je rychlý</translation>
<translation id="8487700953926739672">Dostupné offline</translation>
<translation id="851751545965956758">Bránit webům v připojení k zařízením</translation>
<translation id="8525306231823319788">Celá obrazovka</translation>
<translation id="857943718398505171">Povoleno (doporuÄeno)</translation>
<translation id="8609465669617005112">Posunout nahoru</translation>
+<translation id="861748745608658996">Aktualizovat název na ploše?</translation>
<translation id="8676374126336081632">Vymazat vstup</translation>
<translation id="868929229000858085">Vyhledat v kontaktech</translation>
<translation id="8702612070107455751">Veškerá data offline budou vymazána.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Přiblížit</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">Funkce NFC je v tomto zařízení vypnutá. Zapnete ji v <ph name="BEGIN_LINK" />Nastavení Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Tato stránka se pro většinu uživatelů rychle otevírá a rychle reaguje</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">UkonÄit anonymní režim?</translation>
<translation id="8958424370300090006">Blokovat soubory cookie pro konkrétní web.</translation>
<translation id="8959122750345127698">Navigace není dosažitelná: <ph name="URL" /></translation>
<translation id="8986362086234534611">Odstranit</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_da.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_da.xtb
index 92ca55ea618..bccf0214bd6 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_da.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_da.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="da">
<translation id="1006017844123154345">Åbn på nettet</translation>
<translation id="1044891598689252897">Websites fungerer som normalt</translation>
+<translation id="1100504063505580045">Aktuelt ikon</translation>
<translation id="1124090076051167250">Dette rydder <ph name="DATASIZE" /> data og cookies, som er gemt af websites eller apps på din startskærm.</translation>
<translation id="1124772482545689468">Bruger</translation>
<translation id="1178581264944972037">Pause</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Tillad, at websites kan få adgang til sensorer (anbefales)</translation>
<translation id="3295602654194328831">Skjul oplysninger</translation>
+<translation id="3317660236277031814">En webapp, du har installeret, har ændret sit ikon.</translation>
<translation id="3328801116991980348">Webstedoplysninger</translation>
<translation id="3333961966071413176">Alle kontakter</translation>
<translation id="3386292677130313581">Spørg, om websites må få adgang til din placering (anbefales)</translation>
+<translation id="345699454248713913">En webapp, du har installeret, har ændret sit navn.</translation>
<translation id="3538390592868664640">Bloker oprettelsen af 3D-kort over dine omgivelser eller registrering af kamerapositionen for websites</translation>
+<translation id="3551268116566418498">Forlad inkognitotilstand?</translation>
<translation id="3586500876634962664">Brug af kamera og mikrofon</translation>
<translation id="358794129225322306">Tillad, at et website kan downloade flere filer automatisk.</translation>
<translation id="3594780231884063836">Slå lyden i videoen fra</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Ã…bn placeringsindstillinger</translation>
<translation id="4226663524361240545">Notifikationer kan få enheden til at vibrere</translation>
<translation id="4259722352634471385">Navigationen er blokeret: <ph name="URL" /></translation>
+<translation id="4277239631747669329">En webapp, du har installeret, har ændret sit navn og ikon.</translation>
<translation id="4278390842282768270">Tilladt</translation>
<translation id="429312253194641664">Et website afspiller medier</translation>
<translation id="42981349822642051">Udvid</translation>
<translation id="4336434711095810371">Ryd alle data</translation>
<translation id="4402755511846832236">Bloker websites fra at vide, hvornår du aktivt bruger denne enhed</translation>
-<translation id="4433925000917964731">Lite-side leveret af Google</translation>
<translation id="4434045419905280838">Pop op-vinduer og omdirigeringer</translation>
<translation id="445467742685312942">Tillad, at websites afspiller beskyttet indhold</translation>
<translation id="4468959413250150279">Slå lyden fra for et bestemt website.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Administreret af en af dine forældre</translation>
<translation id="4670064810192446073">Virtual reality</translation>
<translation id="4708011789095599544">Er du sikker på, at du vil rydde cookies og andre websitedata for dette website?</translation>
+<translation id="473775607612524610">Opdater</translation>
<translation id="4751476147751820511">Bevægelses- eller lyssensorer</translation>
<translation id="4836046166855586901">Spørg, når et website vil vide, hvornår du aktivt bruger denne enhed</translation>
<translation id="4883854917563148705">Administrerede indstillinger kan ikke nulstilles</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Del via</translation>
<translation id="5039804452771397117">Tillad</translation>
<translation id="5048398596102334565">Tillad, at websites kan få adgang til bevægelsessensorer (anbefales)</translation>
+<translation id="5050380848339752099">Dette website skal til at dele oplysninger med en app uden for inkognitotilstand.</translation>
<translation id="5063480226653192405">Databrug</translation>
<translation id="5100237604440890931">Skjult – klik for at udvide.</translation>
<translation id="5123685120097942451">Inkognitofane</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Tillad, at websites kører JavaScript (anbefales)</translation>
<translation id="534295439873310000">NFC-enheder</translation>
<translation id="5354152178998424783">Dette rydder <ph name="DATASIZE" /> data og cookies, som er gemt af websites.</translation>
-<translation id="5384883051496921101">Dette website skal til at dele oplysninger med en app uden for inkognitotilstand.</translation>
+<translation id="536508626067510330">Vil du opdatere ikonet på din startskærm?</translation>
<translation id="5391532827096253100">Din forbindelse til dette website er ikke sikker. Websiteoplysninger</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 anden)}one{(+ # anden)}other{(+ # andre)}}</translation>
<translation id="5403592356182871684">Navne</translation>
<translation id="5489227211564503167">Forløbet tid: <ph name="ELAPSED_TIME" /> af <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Bloker annoncer på websites, der viser påtrængende eller vildledende annoncer</translation>
+<translation id="549957179819296104">Nyt ikon</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> blev tilladt, <ph name="PERMISSION_2" /> blev blokeret</translation>
<translation id="5505264765875738116">Websites kan ikke spørge dig, om de må sende dig notifikationer</translation>
<translation id="5516455585884385570">Ã…bn indstillinger for notifikationer</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Tilladelser</translation>
<translation id="5860033963881614850">Fra</translation>
<translation id="5876056640971328065">Sæt video på pause</translation>
+<translation id="5904826301761575486">Vil du opdatere navnet og ikonet på din startskærm?</translation>
<translation id="5916664084637901428">Til</translation>
<translation id="5922853908706496913">Deling af din skærm</translation>
<translation id="5939518447894949180">Nulstil</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Bloker cookies fra tredjeparter</translation>
<translation id="6206551242102657620">Forbindelsen er sikker. Websiteoplysninger</translation>
<translation id="6216432067784365534">Valgmuligheder for <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Luk, og rapportér misbrug</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> og <ph name="PERMISSION_2" /> blev blokeret</translation>
<translation id="6270391203985052864">Websites kan spørge dig, om de må sende dig notifikationer</translation>
<translation id="6295158916970320988">Alle websites</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Aktivér også placering i <ph name="BEGIN_LINK" />Android-indstillingerne<ph name="END_LINK" /> for at give <ph name="APP_NAME" /> adgang til din placering.</translation>
<translation id="8447861592752582886">Tilbagekald adgangstilladelsen til enheden</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie er i brug}one{# cookie er i brug}other{# cookies er i brug}}</translation>
-<translation id="8463851957836045671">Websitet er hurtigt</translation>
<translation id="8487700953926739672">Tilgængelig offline</translation>
<translation id="851751545965956758">Bloker websites fra at oprette forbindelse til enheder</translation>
<translation id="8525306231823319788">Fuld skærm</translation>
<translation id="857943718398505171">Tilladt (anbefales)</translation>
<translation id="8609465669617005112">Flyt op</translation>
+<translation id="861748745608658996">Vil du opdatere navnet på din startskærm?</translation>
<translation id="8676374126336081632">Ryd indtastning</translation>
<translation id="868929229000858085">Søg blandt dine kontakter</translation>
<translation id="8702612070107455751">Alle offlinedata ryddes.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Zoom ind</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC er deaktiveret for denne enhed. Aktivér funktionen i <ph name="BEGIN_LINK" />Android-indstillingerne<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Dette website åbner og reagerer hurtigt hos de fleste brugere</translation>
<translation id="8941729603749328384">www.eksempel.dk</translation>
-<translation id="894871326938397531">Afslut inkognitotilstand?</translation>
<translation id="8958424370300090006">Bloker cookies for et bestemt website.</translation>
<translation id="8959122750345127698">Navigationen er ikke mulig: <ph name="URL" /></translation>
<translation id="8986362086234534611">Glem</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_de.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_de.xtb
index b3cdb9a4407..0be6da784b7 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_de.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_de.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="de">
<translation id="1006017844123154345">Online öffnen</translation>
<translation id="1044891598689252897">Websites funktionieren normal</translation>
+<translation id="1100504063505580045">Aktuelles Symbol</translation>
<translation id="1124090076051167250">Dadurch werden <ph name="DATASIZE" /> an von Websites oder Apps auf dem Startbildschirm gespeicherten Daten und Cookies gelöscht.</translation>
<translation id="1124772482545689468">Nutzer</translation>
<translation id="1178581264944972037">Pause</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Websites den Zugriff auf Sensoren erlauben (empfohlen)</translation>
<translation id="3295602654194328831">Informationen ausblenden</translation>
+<translation id="3317660236277031814">Das Symbol einer installierten Web-App wurde geändert.</translation>
<translation id="3328801116991980348">Websiteinformationen</translation>
<translation id="3333961966071413176">Alle Kontakte</translation>
<translation id="3386292677130313581">Nachfragen, bevor Websites mein Standort angezeigt wird (empfohlen)</translation>
+<translation id="345699454248713913">Der Name einer installierten Web-App wurde geändert.</translation>
<translation id="3538390592868664640">Websites daran hindern, eine 3D-Karte meiner Umgebung zu erstellen oder die Kameraposition zu verfolgen</translation>
+<translation id="3551268116566418498">Inkognitomodus deaktivieren?</translation>
<translation id="3586500876634962664">Kamera- und Mikrofonnutzung</translation>
<translation id="358794129225322306">Einer Website erlauben, automatisch mehrere Dateien herunterzuladen.</translation>
<translation id="3594780231884063836">Video stummschalten</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Standorteinstellungen öffnen</translation>
<translation id="4226663524361240545">Bei Benachrichtigungen kann das Gerät vibrieren</translation>
<translation id="4259722352634471385">Die Navigation zu <ph name="URL" /> ist blockiert.</translation>
+<translation id="4277239631747669329">Der Name und das Symbol einer installierten Web-App wurden geändert.</translation>
<translation id="4278390842282768270">Zugelassen</translation>
<translation id="429312253194641664">Eine Website gibt Medien wieder</translation>
<translation id="42981349822642051">Maximieren</translation>
<translation id="4336434711095810371">Alle Daten löschen</translation>
<translation id="4402755511846832236">Websites daran hindern, Informationen zu Ihrer aktiven Nutzung dieses Geräts abzurufen</translation>
-<translation id="4433925000917964731">Lite-Modus-Seite von Google bereitgestellt</translation>
<translation id="4434045419905280838">Pop-ups und Weiterleitungen</translation>
<translation id="445467742685312942">Websites erlauben, geschützte Inhalte wiederzugeben</translation>
<translation id="4468959413250150279">Eine bestimmte Website stummschalten.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Von deinen Eltern verwaltet</translation>
<translation id="4670064810192446073">Virtual Reality</translation>
<translation id="4708011789095599544">Möchten Sie Cookies und andere Daten für diese Website wirklich löschen?</translation>
+<translation id="473775607612524610">Aktualisieren</translation>
<translation id="4751476147751820511">Bewegungs- oder Lichtsensoren</translation>
<translation id="4836046166855586901">Nachfragen, wenn eine Website Informationen zu Ihrer aktiven Nutzung dieses Geräts abrufen möchte</translation>
<translation id="4883854917563148705">Verwaltete Einstellungen können nicht zurückgesetzt werden</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Teilen über</translation>
<translation id="5039804452771397117">Zulassen</translation>
<translation id="5048398596102334565">Websites den Zugriff auf Bewegungssensoren erlauben (empfohlen)</translation>
+<translation id="5050380848339752099">Diese Website ist im Begriff, Informationen mit einer Anwendung außerhalb des Inkognitomodus zu teilen.</translation>
<translation id="5063480226653192405">Verwendung</translation>
<translation id="5100237604440890931">Minimiert – zum Maximieren klicken</translation>
<translation id="5123685120097942451">Inkognitotab</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Ausführung von JavaScript durch Websites zulassen (empfohlen)</translation>
<translation id="534295439873310000">NFC-Geräte</translation>
<translation id="5354152178998424783">Dadurch werden <ph name="DATASIZE" /> an von Websites gespeicherten Daten und Cookies gelöscht.</translation>
-<translation id="5384883051496921101">Diese Website ist im Begriff, Informationen mit einer App außerhalb des Inkognitomodus zu teilen.</translation>
+<translation id="536508626067510330">Symbol auf dem Startbildschirm aktualisieren?</translation>
<translation id="5391532827096253100">Die Verbindung zu dieser Website ist nicht sicher. Websiteinformationen</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 weitere)}other{(+ # weitere)}}</translation>
<translation id="5403592356182871684">Namen</translation>
<translation id="5489227211564503167">Verstrichene Zeit: <ph name="ELAPSED_TIME" /> von <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Werbung auf Websites blockieren, auf denen aufdringliche oder irreführende Werbung angezeigt wird</translation>
+<translation id="549957179819296104">Neues Symbol</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> zugelassen, <ph name="PERMISSION_2" /> blockiert</translation>
<translation id="5505264765875738116">Websites können nicht fragen, ob Sie Benachrichtigungen erhalten möchten</translation>
<translation id="5516455585884385570">Benachrichtigungseinstellungen öffnen</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Berechtigungen</translation>
<translation id="5860033963881614850">Aus</translation>
<translation id="5876056640971328065">Video anhalten</translation>
+<translation id="5904826301761575486">Name und Symbol auf dem Startbildschirm aktualisieren?</translation>
<translation id="5916664084637901428">An</translation>
<translation id="5922853908706496913">Bildschirmfreigabe läuft</translation>
<translation id="5939518447894949180">Zurücksetzen</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Drittanbieter-Cookies blockieren</translation>
<translation id="6206551242102657620">Die Verbindung ist sicher. Websiteinformationen</translation>
<translation id="6216432067784365534">Optionen für <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Schließen und Missbrauch melden</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> und <ph name="PERMISSION_2" /> blockiert</translation>
<translation id="6270391203985052864">Websites können fragen, ob Sie Benachrichtigungen erhalten möchten</translation>
<translation id="6295158916970320988">Alle Websites</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Um <ph name="APP_NAME" /> Zugriff auf Ihren Standort zu gewähren, müssen Sie die Standortberechtigung auch in den <ph name="BEGIN_LINK" />Android-Einstellungen<ph name="END_LINK" /> aktivieren.</translation>
<translation id="8447861592752582886">Zugriffsberechtigung auf Gerät widerrufen</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 verwendeter Cookie}other{# verwendete Cookies}}</translation>
-<translation id="8463851957836045671">Website ist schnell</translation>
<translation id="8487700953926739672">Offline verfügbar</translation>
<translation id="851751545965956758">Verhindern, dass Websites eine Verbindung zu Geräten herstellen</translation>
<translation id="8525306231823319788">Vollbildmodus</translation>
<translation id="857943718398505171">Zugelassen (empfohlen)</translation>
<translation id="8609465669617005112">Nach oben</translation>
+<translation id="861748745608658996">Name auf dem Startbildschirm aktualisieren?</translation>
<translation id="8676374126336081632">Eingabe löschen</translation>
<translation id="868929229000858085">Kontakte durchsuchen</translation>
<translation id="8702612070107455751">Alle Offlinedaten werden gelöscht.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Vergrößern</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC ist für dieses Gerät deaktiviert. Sie können die Funktion in den <ph name="BEGIN_LINK" />Android-Einstellungen<ph name="END_LINK" /> aktivieren.</translation>
-<translation id="8929372349074745002">Diese Website lädt und reagiert meistens schnell</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Inkognitomodus deaktivieren?</translation>
<translation id="8958424370300090006">Cookies für eine bestimmte Website werden blockiert.</translation>
<translation id="8959122750345127698">Navigation nicht möglich: <ph name="URL" /> ist nicht erreichbar.</translation>
<translation id="8986362086234534611">Entfernen</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_el.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_el.xtb
index f5ae1bedcf1..12865fd3402 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_el.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_el.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="el">
<translation id="1006017844123154345">Άνοιγμα στο διαδίκτυο</translation>
<translation id="1044891598689252897">Οι ιστότοποι θα λειτουÏγοÏν κανονικά</translation>
+<translation id="1100504063505580045">ΤÏέχον εικονίδιο</translation>
<translation id="1124090076051167250">Αυτή η ενέÏγεια θα διαγÏάψει <ph name="DATASIZE" /> δεδομένων και cookie που έχουν αποθηκευτεί από ιστοτόπους ή εφαÏμογές στην αÏχική σας οθόνη.</translation>
<translation id="1124772482545689468">ΧÏήστης</translation>
<translation id="1178581264944972037">ΠαÏση</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">ΜικÏόφωνο</translation>
<translation id="3277252321222022663">Îα επιτÏέπεται στους ιστοτόπους η Ï€Ïόσβαση στους αισθητήÏες (συνιστάται)</translation>
<translation id="3295602654194328831">ΑπόκÏυψη πληÏοφοÏιών</translation>
+<translation id="3317660236277031814">Έγινε αλλαγή του εικονιδίου μιας εφαÏμογής Î¹ÏƒÏ„Î¿Ï Ï€Î¿Ï… έχετε εγκαταστήσει.</translation>
<translation id="3328801116991980348">ΠληÏοφοÏίες ιστοτόπου</translation>
<translation id="3333961966071413176">Όλες οι επαφές</translation>
<translation id="3386292677130313581">Îα γίνεται εÏώτηση Ï€ÏÎ¿Ï„Î¿Ï ÎµÏ€Î¹Ï„Ïαπεί η κοινοποίηση της τοποθεσίας σας σε ιστότοπους (συνιστάται)</translation>
+<translation id="345699454248713913">Έγινε αλλαγή του ονόματος μιας εφαÏμογής Î¹ÏƒÏ„Î¿Ï Ï€Î¿Ï… έχετε εγκαταστήσει.</translation>
<translation id="3538390592868664640">Αποκλείστε ιστοτόπους από τη δημιουÏγία ενός Ï„Ïισδιάστατου χάÏτη του πεÏιβάλλοντα χώÏου σας ή την παÏακολοÏθηση της θέσης της κάμεÏας.</translation>
+<translation id="3551268116566418498">Έξοδος από ανώνυμη πεÏιήγηση;</translation>
<translation id="3586500876634962664">ΧÏήση κάμεÏας και μικÏοφώνου</translation>
<translation id="358794129225322306">Îα επιτÏέπεται σε έναν ιστότοπο να κατεβάζει αυτόματα πολλά αÏχεία.</translation>
<translation id="3594780231884063836">Σίγαση βίντεο</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Άνοιγμα Ïυθμίσεων τοποθεσίας</translation>
<translation id="4226663524361240545">Κατά τη λήψη ειδοποιήσεων ενδέχεται να δονείται η συσκευή</translation>
<translation id="4259722352634471385">Αποκλείστηκε η μετάβαση στη διεÏθυνση: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Έγινε αλλαγή του ονόματος και του εικονιδίου μιας εφαÏμογής Î¹ÏƒÏ„Î¿Ï Ï€Î¿Ï… έχετε εγκαταστήσει.</translation>
<translation id="4278390842282768270">ΕπιτÏέπεται</translation>
<translation id="429312253194641664">Ένας ιστότοπος κάνει αναπαÏαγωγή μέσων</translation>
<translation id="42981349822642051">Επέκταση</translation>
<translation id="4336434711095810371">ΔιαγÏαφή όλων των δεδομένων</translation>
<translation id="4402755511846832236">Îα μην επιτÏέπεται σε ιστοτόπους να γνωÏίζουν πότε χÏησιμοποιείτε τη συσκευή ενεÏγά</translation>
-<translation id="4433925000917964731">Σελίδα Lite που παÏέχεται από την Google</translation>
<translation id="4434045419905280838">Αναδυόμενα παÏάθυÏα και ανακατευθÏνσεις</translation>
<translation id="445467742685312942">Îα επιτÏέπεται στους ιστοτόπους η αναπαÏαγωγή Ï€Ïοστατευμένου πεÏιεχομένου</translation>
<translation id="4468959413250150279">Σίγαση ήχου για συγκεκÏιμένο ιστότοπο.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">ΔιαχειÏίζεται από τους γονείς σου</translation>
<translation id="4670064810192446073">Εικονική Ï€Ïαγματικότητα</translation>
<translation id="4708011789095599544">Είστε βέβαιοι ότι θέλετε να διαγÏάψετε τα cookie και τα άλλα δεδομένα ιστοτόπου για αυτόν τον ιστότοπο;</translation>
+<translation id="473775607612524610">ΕνημέÏωση</translation>
<translation id="4751476147751820511">ΑισθητήÏες κίνησης ή φωτός</translation>
<translation id="4836046166855586901">Îα γίνεται εÏώτηση όταν ένας ιστότοπος θέλει να γνωÏίζει πότε χÏησιμοποιείτε ενεÏγά αυτήν τη συσκευή</translation>
<translation id="4883854917563148705">Δεν είναι δυνατή η επαναφοÏά των υπό διαχείÏιση Ïυθμίσεων</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">ΜοιÏαστείτε μέσω</translation>
<translation id="5039804452771397117">ΕπιτÏέπεται</translation>
<translation id="5048398596102334565">Îα επιτÏέπεται στους ιστοτόπους η Ï€Ïόσβαση στους αισθητήÏες κίνησης (συνιστάται)</translation>
+<translation id="5050380848339752099">Αυτός ο ιστότοπος Ï€Ïόκειται να κοινοποιήσει πληÏοφοÏίες σε μια εφαÏμογή εκτός της κατάστασης ανώνυμης πεÏιήγησης.</translation>
<translation id="5063480226653192405">ΧÏήση</translation>
<translation id="5100237604440890931">Συμπτυγμένη - Κάντε κλικ για ανάπτυξη</translation>
<translation id="5123685120097942451">ΚαÏτέλα ανώνυμης πεÏιήγησης</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Îα επιτÏέπεται στους ιστότοπους να εκτελοÏν JavaScript (συνιστάται)</translation>
<translation id="534295439873310000">Συσκευές NFC</translation>
<translation id="5354152178998424783">Αυτή η ενέÏγεια θα διαγÏάψει <ph name="DATASIZE" /> δεδομένων και cookie που έχουν αποθηκευτεί από ιστοτόπους.</translation>
-<translation id="5384883051496921101">Αυτός ο ιστότοπος Ï€Ïόκειται να κοινοποιήσει πληÏοφοÏίες με μια εφαÏμογή εκτός της κατάστασης ανώνυμης πεÏιήγησης.</translation>
+<translation id="536508626067510330">ΕνημέÏωση εικονιδίου στην αÏχική σας οθόνη;</translation>
<translation id="5391532827096253100">Η σÏνδεσή σας σε αυτόν τον ιστότοπο δεν είναι ασφαλής. ΠληÏοφοÏίες ιστοτόπου</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 ακόμη)}other{(+ # ακόμη)}}</translation>
<translation id="5403592356182871684">Ονόματα</translation>
<translation id="5489227211564503167">Έχουν πεÏάσει <ph name="ELAPSED_TIME" /> από <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Αποκλεισμός διαφημίσεων σε ιστοτόπους που εμφανίζουν παÏεμβατικές ή παÏαπλανητικές διαφημίσεις</translation>
+<translation id="549957179819296104">Îέο εικονίδιο</translation>
<translation id="5502860503640766021">Αποδοχή <ph name="PERMISSION_1" />, αποκλεισμός <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Οι ιστότοποι δεν μποÏοÏν να ζητοÏν να στέλνουν ειδοποιήσεις.</translation>
<translation id="5516455585884385570">Άνοιγμα Ïυθμίσεων ειδοποιήσεων</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Άδειες</translation>
<translation id="5860033963881614850">ΑπενεÏγοποιημένη</translation>
<translation id="5876056640971328065">ΠαÏση βίντεο</translation>
+<translation id="5904826301761575486">ΕνημέÏωση ονόματος και εικονιδίου στην αÏχική σας οθόνη;</translation>
<translation id="5916664084637901428">ΕνεÏγό</translation>
<translation id="5922853908706496913">Κοινή χÏήση της οθόνης σας</translation>
<translation id="5939518447894949180">ΕπαναφοÏά</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Αποκλεισμός cookie Ï„Ïίτων</translation>
<translation id="6206551242102657620">Η σÏνδεση είναι ασφαλής. ΠληÏοφοÏίες ιστοτόπου</translation>
<translation id="6216432067784365534">Επιλογές <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Κλείσιμο και αναφοÏά κατάχÏησης</translation>
<translation id="6262279340360821358">Οι άδειες <ph name="PERMISSION_1" /> και <ph name="PERMISSION_2" /> αποκλείστηκαν.</translation>
<translation id="6270391203985052864">Οι ιστότοποι μποÏοÏν να ζητοÏν να στέλνουν ειδοποιήσεις.</translation>
<translation id="6295158916970320988">Όλοι οι ιστότοποι</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Για να επιτÏέψετε στην εφαÏμογή <ph name="APP_NAME" /> να αποκτήσει Ï€Ïόσβαση στην τοποθεσία σας, ενεÏγοποιήστε επίσης την τοποθεσία στις <ph name="BEGIN_LINK" />Ρυθμίσεις Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Ανάκληση άδειας συσκευής</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{ΧÏησιμοποιείται 1 cookie}other{ΧÏησιμοποιοÏνται # cookie}}</translation>
-<translation id="8463851957836045671">Ο ιστότοπος είναι γÏήγοÏος</translation>
<translation id="8487700953926739672">Διαθέσιμο εκτός σÏνδεσης</translation>
<translation id="851751545965956758">Αποκλεισμός ιστοτόπων από τη σÏνδεση σε συσκευές</translation>
<translation id="8525306231823319788">ΠλήÏης οθόνη</translation>
<translation id="857943718398505171">ΕπιτÏέπεται (συνιστάται)</translation>
<translation id="8609465669617005112">Μετακίνηση Ï€Ïος τα επάνω</translation>
+<translation id="861748745608658996">ΕνημέÏωση ονόματος στην αÏχική σας οθόνη;</translation>
<translation id="8676374126336081632">ΔιαγÏαφή καταχώÏισης</translation>
<translation id="868929229000858085">Αναζήτηση στις επαφές σας</translation>
<translation id="8702612070107455751">Όλα τα δεδομένα εκτός σÏνδεσης θα διαγÏαφοÏν.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Μεγέθυνση</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">Το NFC είναι ανενεÏγό για αυτήν τη συσκευή. ΕνεÏγοποιήστε το στις <ph name="BEGIN_LINK" />Ρυθμίσεις Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Αυτός ο ιστότοπος ανοίγει και αποκÏίνεται γÏήγοÏα για τους πεÏισσότεÏους χÏήστες.</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Έξοδος από την κατάσταση ανώνυμης πεÏιήγησης;</translation>
<translation id="8958424370300090006">Αποκλεισμός cookie για έναν συγκεκÏιμένο ιστοτόπο.</translation>
<translation id="8959122750345127698">Δεν είναι δυνατή η μετάβαση στη διεÏθυνση: <ph name="URL" /></translation>
<translation id="8986362086234534611">ΔιαγÏαφή από τη μνήμη</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_en-GB.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_en-GB.xtb
index 6c4e84f7be4..48092fd5a4f 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_en-GB.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_en-GB.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="en-GB">
<translation id="1006017844123154345">Open Online</translation>
<translation id="1044891598689252897">Sites will work normally</translation>
+<translation id="1100504063505580045">Current icon</translation>
<translation id="1124090076051167250">This will clear <ph name="DATASIZE" /> of data and cookies stored by sites or by apps on your home screen.</translation>
<translation id="1124772482545689468">User</translation>
<translation id="1178581264944972037">Pause</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Microphone</translation>
<translation id="3277252321222022663">Allow sites to access sensors (recommended)</translation>
<translation id="3295602654194328831">Hide info</translation>
+<translation id="3317660236277031814">A web app that you installed has changed its icon.</translation>
<translation id="3328801116991980348">Site information</translation>
<translation id="3333961966071413176">All contacts</translation>
<translation id="3386292677130313581">Ask before allowing sites to know your location (recommended)</translation>
+<translation id="345699454248713913">A web app that you installed has changed its name.</translation>
<translation id="3538390592868664640">Block sites from creating a 3D map of your surroundings or tracking camera position</translation>
+<translation id="3551268116566418498">Leave Incognito mode?</translation>
<translation id="3586500876634962664">Camera and microphone use</translation>
<translation id="358794129225322306">Allow a site to download multiple files automatically.</translation>
<translation id="3594780231884063836">Mute video</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Open location settings</translation>
<translation id="4226663524361240545">Notifications may vibrate the device</translation>
<translation id="4259722352634471385">Navigation is blocked: <ph name="URL" /></translation>
+<translation id="4277239631747669329">A web app that you installed has changed its name and icon.</translation>
<translation id="4278390842282768270">Allowed</translation>
<translation id="429312253194641664">A site is playing media</translation>
<translation id="42981349822642051">Expand</translation>
<translation id="4336434711095810371">Clear all data</translation>
<translation id="4402755511846832236">Block sites from knowing when you're actively using this device</translation>
-<translation id="4433925000917964731">Lite page provided by Google</translation>
<translation id="4434045419905280838">Pop-ups and redirects</translation>
<translation id="445467742685312942">Allow sites to play protected content</translation>
<translation id="4468959413250150279">Mute sound for a specific site.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Managed by your parent</translation>
<translation id="4670064810192446073">Virtual reality</translation>
<translation id="4708011789095599544">Are you sure that you want to clear cookies and other site data for this website?</translation>
+<translation id="473775607612524610">Update</translation>
<translation id="4751476147751820511">Motion or light sensors</translation>
<translation id="4836046166855586901">Ask when a site wants to know when you're actively using this device</translation>
<translation id="4883854917563148705">Managed settings cannot be reset</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Share via</translation>
<translation id="5039804452771397117">Allow</translation>
<translation id="5048398596102334565">Allow sites to access motion sensors (recommended)</translation>
+<translation id="5050380848339752099">This site is about to share information with an app outside of Incognito mode.</translation>
<translation id="5063480226653192405">Usage</translation>
<translation id="5100237604440890931">Collapsed – click to expand.</translation>
<translation id="5123685120097942451">Incognito tab</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Allow sites to run JavaScript (recommended)</translation>
<translation id="534295439873310000">NFC devices</translation>
<translation id="5354152178998424783">This will clear <ph name="DATASIZE" /> of data and cookies stored by sites.</translation>
-<translation id="5384883051496921101">This site is about to share information with an app outside of incognito mode.</translation>
+<translation id="536508626067510330">Update icon on your homescreen?</translation>
<translation id="5391532827096253100">Your connection to this site is not secure. Site information</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 more)}other{(+ # more)}}</translation>
<translation id="5403592356182871684">Names</translation>
<translation id="5489227211564503167">Elapsed time <ph name="ELAPSED_TIME" /> of <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Block ads on sites that show intrusive or misleading ads</translation>
+<translation id="549957179819296104">New icon</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> allowed, <ph name="PERMISSION_2" /> blocked</translation>
<translation id="5505264765875738116">Sites can't ask to send notifications</translation>
<translation id="5516455585884385570">Open notification settings</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Permissions</translation>
<translation id="5860033963881614850">Off</translation>
<translation id="5876056640971328065">Pause video</translation>
+<translation id="5904826301761575486">Update name and icon on your homescreen?</translation>
<translation id="5916664084637901428">On</translation>
<translation id="5922853908706496913">Sharing your screen</translation>
<translation id="5939518447894949180">Reset</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Block third-party cookies</translation>
<translation id="6206551242102657620">Connection is secure. Site information</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> Options</translation>
+<translation id="6260852843601447737">Close and report abuse</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> and <ph name="PERMISSION_2" /> blocked</translation>
<translation id="6270391203985052864">Sites can ask to send notifications</translation>
<translation id="6295158916970320988">All sites</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">To let <ph name="APP_NAME" /> access your location, also turn on location in <ph name="BEGIN_LINK" />Android settings<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Revoke device permission</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie in use}other{# cookies in use}}</translation>
-<translation id="8463851957836045671">Site is fast</translation>
<translation id="8487700953926739672">Available offline</translation>
<translation id="851751545965956758">Block sites from connecting to devices</translation>
<translation id="8525306231823319788">Full screen</translation>
<translation id="857943718398505171">Allowed (recommended)</translation>
<translation id="8609465669617005112">Move up</translation>
+<translation id="861748745608658996">Update name on your homescreen?</translation>
<translation id="8676374126336081632">Clear input</translation>
<translation id="868929229000858085">Search your contacts</translation>
<translation id="8702612070107455751">Any offline data will be cleared.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Zoom in</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC is off for this device. Turn it on in <ph name="BEGIN_LINK" />Android settings<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">This site opens and responds quickly for most people</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Leave incognito mode?</translation>
<translation id="8958424370300090006">Block cookies for a specific site.</translation>
<translation id="8959122750345127698">Navigation is unreachable: <ph name="URL" /></translation>
<translation id="8986362086234534611">Forget</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_es-419.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_es-419.xtb
index bf09cb66d54..1431966c771 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_es-419.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_es-419.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="es-419">
<translation id="1006017844123154345">Abrir en línea</translation>
<translation id="1044891598689252897">Los sitios funcionarán normalmente</translation>
+<translation id="1100504063505580045">Ãcono actual</translation>
<translation id="1124090076051167250">Esta acción borrará <ph name="DATASIZE" /> de datos y cookies almacenados por los sitios o las apps que aparecen en la pantalla principal.</translation>
<translation id="1124772482545689468">Usuario</translation>
<translation id="1178581264944972037">Detener</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Micrófono</translation>
<translation id="3277252321222022663">Permitir que los sitios accedan a los sensores (recomendado)</translation>
<translation id="3295602654194328831">Ocultar información</translation>
+<translation id="3317660236277031814">Se cambió el ícono de una aplicación web que instalaste.</translation>
<translation id="3328801116991980348">Información del sitio</translation>
<translation id="3333961966071413176">Todos los contactos</translation>
<translation id="3386292677130313581">Preguntar antes de permitir que los sitios conozcan tu ubicación (recomendado)</translation>
+<translation id="345699454248713913">Se cambió el nombre de una aplicación web que instalaste.</translation>
<translation id="3538390592868664640">No permitir que los sitios creen un mapa 3D de tu entorno ni hagan un seguimiento de la posición de la cámara</translation>
+<translation id="3551268116566418498">¿Salir del modo Incógnito?</translation>
<translation id="3586500876634962664">Uso de la cámara y el micrófono</translation>
<translation id="358794129225322306">Permite que un sitio descargue varios archivos automáticamente.</translation>
<translation id="3594780231884063836">Silenciar video</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Abrir la configuración de la ubicación</translation>
<translation id="4226663524361240545">Es posible que las notificaciones hagan vibrar el dispositivo</translation>
<translation id="4259722352634471385">Navegación bloqueada: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Se cambió el nombre y el ícono de una aplicación web que instalaste.</translation>
<translation id="4278390842282768270">Permitido</translation>
<translation id="429312253194641664">Un sitio está reproduciendo contenido multimedia</translation>
<translation id="42981349822642051">Expandir</translation>
<translation id="4336434711095810371">Borrar todos los datos</translation>
<translation id="4402755511846832236">No permitir que los sitios sepan cuando estás usando activamente este dispositivo</translation>
-<translation id="4433925000917964731">Google proporcionó la página básica</translation>
<translation id="4434045419905280838">Ventanas emergentes y redireccionamientos</translation>
<translation id="445467742685312942">Permitir que los sitios reproduzcan contenido protegido</translation>
<translation id="4468959413250150279">Silenciar un sitio específico.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Administrado por tus padres</translation>
<translation id="4670064810192446073">Realidad virtual</translation>
<translation id="4708011789095599544">¿Confirmas que quieres borrar las cookies y otros datos de este sitio web?</translation>
+<translation id="473775607612524610">Actualizar</translation>
<translation id="4751476147751820511">Sensores de luz o movimiento</translation>
<translation id="4836046166855586901">Permitir que los sitios pregunten en qué momento estás usando activamente este dispositivo</translation>
<translation id="4883854917563148705">No puede restablecerse la configuración administrada</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Compartir mediante</translation>
<translation id="5039804452771397117">Permitir</translation>
<translation id="5048398596102334565">Permitir que los sitios accedan a los sensores de movimiento (recomendado)</translation>
+<translation id="5050380848339752099">Este sitio está a punto de compartir información con una app fuera del modo Incógnito.</translation>
<translation id="5063480226653192405">Uso</translation>
<translation id="5100237604440890931">Contraído; haz clic para expandir.</translation>
<translation id="5123685120097942451">Pestaña de incógnito</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Permitir que los sitios ejecuten JavaScript (recomendado)</translation>
<translation id="534295439873310000">Dispositivos NFC</translation>
<translation id="5354152178998424783">Esta acción borrará <ph name="DATASIZE" /> de datos y cookies que almacenaron los sitios.</translation>
-<translation id="5384883051496921101">Este sitio está a punto de compartir información con una app fuera del modo de navegación incógnito.</translation>
+<translation id="536508626067510330">¿Quieres actualizar el ícono en tu pantalla principal?</translation>
<translation id="5391532827096253100">La conexión con este sitio no es segura. Consulta la información del sitio.</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(1 más)}other{(# más)}}</translation>
<translation id="5403592356182871684">Nombres</translation>
<translation id="5489227211564503167">Tiempo transcurrido: <ph name="ELAPSED_TIME" /> de <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Bloquear anuncios de sitios que muestran anuncios intrusivos o engañosos</translation>
+<translation id="549957179819296104">Ãcono nuevo</translation>
<translation id="5502860503640766021">Permitido: <ph name="PERMISSION_1" />; bloqueado: <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Los sitios no podrán preguntarte si quieres recibir notificaciones</translation>
<translation id="5516455585884385570">Abrir la configuración de notificaciones</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Permisos</translation>
<translation id="5860033963881614850">Desactivado</translation>
<translation id="5876056640971328065">Pausar video</translation>
+<translation id="5904826301761575486">¿Quieres actualizar el nombre y el ícono en tu pantalla principal?</translation>
<translation id="5916664084637901428">Activado</translation>
<translation id="5922853908706496913">Compartiendo tu pantalla</translation>
<translation id="5939518447894949180">Restablecer</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Bloquear cookies de terceros</translation>
<translation id="6206551242102657620">La conexión es segura. Consulta la información del sitio.</translation>
<translation id="6216432067784365534">Opciones de <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Cerrar y denunciar un abuso</translation>
<translation id="6262279340360821358">Bloqueados: <ph name="PERMISSION_1" /> y <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Los sitios podrán preguntarte si quieres recibir notificaciones</translation>
<translation id="6295158916970320988">Todos los sitios</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Para permitir que <ph name="APP_NAME" /> acceda a tu ubicación, actívala también en la <ph name="BEGIN_LINK" />Configuración de Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Revocar permiso para el dispositivo</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie en uso}other{# cookies en uso}}</translation>
-<translation id="8463851957836045671">El sitio es rápido</translation>
<translation id="8487700953926739672">Disponible sin conexión</translation>
<translation id="851751545965956758">Impedir que los sitios se conecten a los dispositivos</translation>
<translation id="8525306231823319788">Pantalla completa</translation>
<translation id="857943718398505171">Permitido (recomendado)</translation>
<translation id="8609465669617005112">Subir</translation>
+<translation id="861748745608658996">¿Quieres actualizar el nombre en tu pantalla principal?</translation>
<translation id="8676374126336081632">Borrar entrada</translation>
<translation id="868929229000858085">Busca entre tus contactos</translation>
<translation id="8702612070107455751">Se borrarán los datos sin conexión.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Acercar</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">La tecnología NFC está desactivada en este dispositivo. Actívala en la <ph name="BEGIN_LINK" />Configuración de Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Este sitio se abre y responde rápidamente para la mayoría de las personas</translation>
<translation id="8941729603749328384">www.ejemplo.com</translation>
-<translation id="894871326938397531">¿Deseas salir del modo de navegación incógnito?</translation>
<translation id="8958424370300090006">Bloquea las cookies en un sitio específico.</translation>
<translation id="8959122750345127698">Navegación inaccesible: <ph name="URL" /></translation>
<translation id="8986362086234534611">Borrar</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_es.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_es.xtb
index 3501bc2c7fa..14dd169f83a 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_es.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_es.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="es">
<translation id="1006017844123154345">Abrir versión online</translation>
<translation id="1044891598689252897">Los sitios funcionarán con normalidad</translation>
+<translation id="1100504063505580045">Icono actual</translation>
<translation id="1124090076051167250">Esta acción borrará <ph name="DATASIZE" /> de datos y cookies almacenados por sitios o aplicaciones en tu pantalla de inicio.</translation>
<translation id="1124772482545689468">Usuario</translation>
<translation id="1178581264944972037">Pausar</translation>
@@ -10,7 +11,7 @@
<translation id="1195941046451948919">¿Seguro que quieres restablecer todos los permisos para este sitio web?</translation>
<translation id="1201402288615127009">Siguiente</translation>
<translation id="1242008676835033345">Insertada en <ph name="WEBSITE_URL" /></translation>
-<translation id="1272079795634619415">Interrumpir</translation>
+<translation id="1272079795634619415">Detener</translation>
<translation id="1289742167380433257">Para ahorrar datos, Google ha optimizado las imágenes de esta página.</translation>
<translation id="129382876167171263">Los archivos que guarden los sitios web aparecerán aquí</translation>
<translation id="1317194122196776028">Olvidar este sitio</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Micrófono</translation>
<translation id="3277252321222022663">Permitir que los sitios accedan a los sensores (recomendado)</translation>
<translation id="3295602654194328831">Ocultar información</translation>
+<translation id="3317660236277031814">Una aplicación web que instalaste ha cambiado de icono.</translation>
<translation id="3328801116991980348">Información del sitio</translation>
<translation id="3333961966071413176">Todos los contactos</translation>
<translation id="3386292677130313581">Preguntar antes de permitir que los sitios detecten tu ubicación (recomendado)</translation>
+<translation id="345699454248713913">Una aplicación web que instalaste ha cambiado de nombre.</translation>
<translation id="3538390592868664640">No permitir que los sitios creen un mapa 3D de tu entorno o hagan un seguimiento de la posición de la cámara</translation>
+<translation id="3551268116566418498">¿Salir del modo de incógnito?</translation>
<translation id="3586500876634962664">Uso de cámara y micrófono</translation>
<translation id="358794129225322306">Permitir que un sitio web descargue varios archivos automáticamente.</translation>
<translation id="3594780231884063836">Silenciar vídeo</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Abrir Ajustes de ubicación</translation>
<translation id="4226663524361240545">Es posible que las notificaciones hagan que el dispositivo vibre</translation>
<translation id="4259722352634471385">Se ha bloqueado la navegación: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Una aplicación web que instalaste ha cambiado de nombre e icono</translation>
<translation id="4278390842282768270">Permitido</translation>
<translation id="429312253194641664">Un sitio web está reproduciendo elementos multimedia</translation>
<translation id="42981349822642051">Mostrar</translation>
<translation id="4336434711095810371">Borrar todos los datos</translation>
<translation id="4402755511846832236">Impide que los sitios detecten cuándo usas activamente este dispositivo</translation>
-<translation id="4433925000917964731">Página básica ofrecida por Google</translation>
<translation id="4434045419905280838">Ventanas emergentes y redirecciones</translation>
<translation id="445467742685312942">Permitir que los sitios reproduzcan contenido protegido</translation>
<translation id="4468959413250150279">Silencia el sonido de un sitio específico.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Administrado por uno de tus padres</translation>
<translation id="4670064810192446073">Realidad virtual</translation>
<translation id="4708011789095599544">¿Seguro que quieres borrar las cookies y otros datos de este sitio web?</translation>
+<translation id="473775607612524610">Actualizar</translation>
<translation id="4751476147751820511">Sensores de luz o movimiento</translation>
<translation id="4836046166855586901">Preguntar en caso de que un sitio quiera detectar cuándo usas activamente este dispositivo</translation>
<translation id="4883854917563148705">No se pueden restablecer los ajustes gestionados</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Compartir a través de</translation>
<translation id="5039804452771397117">Permitir</translation>
<translation id="5048398596102334565">Permitir que los sitios accedan a los sensores de movimiento (recomendado)</translation>
+<translation id="5050380848339752099">Este sitio va a compartir información con una aplicación fuera del modo de incógnito.</translation>
<translation id="5063480226653192405">Uso</translation>
<translation id="5100237604440890931">Contraído (hacer clic para ampliar)</translation>
<translation id="5123685120097942451">Pestaña de incógnito</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Permitir que los sitios utilicen JavaScript (recomendado)</translation>
<translation id="534295439873310000">Dispositivos NFC</translation>
<translation id="5354152178998424783">Esta acción borrará <ph name="DATASIZE" /> de datos y cookies almacenados por sitios.</translation>
-<translation id="5384883051496921101">Este sitio web va a compartir información con una aplicación con la que no se utilizará el modo de incógnito.</translation>
+<translation id="536508626067510330">¿Actualizar el icono en tu pantalla de inicio?</translation>
<translation id="5391532827096253100">Tu conexión a este sitio web no es segura. Información del sitio web</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(y 1 más)}other{(y # más)}}</translation>
<translation id="5403592356182871684">Nombres</translation>
<translation id="5489227211564503167">Tiempo transcurrido: <ph name="ELAPSED_TIME" /> de <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Bloquea anuncios invasivos o engañosos en los sitios que los muestran</translation>
+<translation id="549957179819296104">Icono nuevo</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> permitido; <ph name="PERMISSION_2" /> bloqueado</translation>
<translation id="5505264765875738116">Los sitios no pueden preguntarte si quieres que te envíen notificaciones</translation>
<translation id="5516455585884385570">Abrir ajustes de notificaciones</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Permisos</translation>
<translation id="5860033963881614850">Desactivado</translation>
<translation id="5876056640971328065">Pausar vídeo</translation>
+<translation id="5904826301761575486">¿Actualizar el nombre y el icono en tu pantalla de inicio?</translation>
<translation id="5916664084637901428">Activado</translation>
<translation id="5922853908706496913">Compartiendo tu pantalla</translation>
<translation id="5939518447894949180">Restablecer</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Bloquear cookies de terceros</translation>
<translation id="6206551242102657620">La conexión es segura. Información del sitio web</translation>
<translation id="6216432067784365534">Opciones de <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Cerrar y denunciar un abuso</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> y <ph name="PERMISSION_2" /> bloqueados</translation>
<translation id="6270391203985052864">Los sitios pueden preguntarte si quieres que te envíen notificaciones</translation>
<translation id="6295158916970320988">Todos los sitios</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Para que <ph name="APP_NAME" /> tenga acceso a tu ubicación, actívala también en los <ph name="BEGIN_LINK" />ajustes de Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Revocar permiso de dispositivo</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie en uso}other{# cookies en uso}}</translation>
-<translation id="8463851957836045671">El sitio web es rápido</translation>
<translation id="8487700953926739672">Disponible sin conexión</translation>
<translation id="851751545965956758">No permitir que los sitios se conecten a dispositivos</translation>
<translation id="8525306231823319788">Pantalla completa</translation>
<translation id="857943718398505171">Permitido (recomendado)</translation>
<translation id="8609465669617005112">Subir</translation>
+<translation id="861748745608658996">¿Actualizar el nombre en tu pantalla de inicio?</translation>
<translation id="8676374126336081632">Borrar entrada</translation>
<translation id="868929229000858085">Buscar en tus contactos</translation>
<translation id="8702612070107455751">Se borrarán todos los datos offline.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Acercar</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">La tecnología NFC está desactivada en este dispositivo. Actívala en los <ph name="BEGIN_LINK" />ajustes de Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Este sitio web se abre y responde con rapidez en la mayoría de los casos</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">¿Salir del modo de incógnito?</translation>
<translation id="8958424370300090006">Bloquear las cookies de un sitio específico.</translation>
<translation id="8959122750345127698">No se puede realizar la navegación: <ph name="URL" /></translation>
<translation id="8986362086234534611">Dejar de recordar</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_et.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_et.xtb
index 19f1ac23589..dc03025f411 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_et.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_et.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="et">
<translation id="1006017844123154345">Ava veebis</translation>
<translation id="1044891598689252897">Saidid töötavad tavapärasel moel</translation>
+<translation id="1100504063505580045">Praegune ikoon</translation>
<translation id="1124090076051167250">See kustutab <ph name="DATASIZE" /> andmeid ja küpsisefaile, mille saidid või rakendused on teie avakuvale salvestanud.</translation>
<translation id="1124772482545689468">Kasutaja</translation>
<translation id="1178581264944972037">Peata</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Luba saitide jaoks juurdepääs anduritele (soovitatav)</translation>
<translation id="3295602654194328831">Peida teave</translation>
+<translation id="3317660236277031814">Teie installitud veebirakenduse ikoon on muutunud.</translation>
<translation id="3328801116991980348">Saiditeave</translation>
<translation id="3333961966071413176">Kõik kontaktid</translation>
<translation id="3386292677130313581">Küsi enne saitidele minu asukoha avaldamist (soovitatav)</translation>
+<translation id="345699454248713913">Teie installitud veebirakenduse nimi on muutunud.</translation>
<translation id="3538390592868664640">Saitide jaoks blokeeritakse teid ümbritsevast 3D-kaardi loomine või kaamera asendi jälgimine</translation>
+<translation id="3551268116566418498">Kas lahkuda inkognito režiimist?</translation>
<translation id="3586500876634962664">Kaamera ja mikrofoni kasutamine</translation>
<translation id="358794129225322306">Lubab saidil automaatselt mitut faili alla laadida.</translation>
<translation id="3594780231884063836">Video vaigistamine</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Ava asukohaseaded</translation>
<translation id="4226663524361240545">Seade võib märguannete korral vibreerida</translation>
<translation id="4259722352634471385">Navigeerimine on blokeeritud: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Teie installitud veebirakenduse nimi ja ikoon on muutunud.</translation>
<translation id="4278390842282768270">Lubatud</translation>
<translation id="429312253194641664">Sait esitab meediasisu</translation>
<translation id="42981349822642051">Laienda</translation>
<translation id="4336434711095810371">Kustuta kõik andmed</translation>
<translation id="4402755511846832236">Keelake saitidel selle tuvastamine, millal seda seadet aktiivselt kasutate</translation>
-<translation id="4433925000917964731">Lihtsustatud lehte pakub Google</translation>
<translation id="4434045419905280838">Hüpikaknad ja ümbersuunamised</translation>
<translation id="445467742685312942">Saitidel on lubatud esitada kaitstud sisu</translation>
<translation id="4468959413250150279">Konkreetse saidi heli vaigistamine.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Vanema hallatud</translation>
<translation id="4670064810192446073">Virtuaalreaalsus</translation>
<translation id="4708011789095599544">Kas soovite selle veebisaidi puhul kindlasti küpsisefailid ja muud saidi andmed kustutada?</translation>
+<translation id="473775607612524610">Värskenda</translation>
<translation id="4751476147751820511">Liikumis- või valgusandurid</translation>
<translation id="4836046166855586901">Küsi, kui sait soovib teada, millal kasutate aktiivselt seda seadet</translation>
<translation id="4883854917563148705">Hallatud seadeid ei saa lähtestada</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Jagamine:</translation>
<translation id="5039804452771397117">Luba</translation>
<translation id="5048398596102334565">Luba saitide jaoks juurdepääs liikumisanduritele (soovitatav)</translation>
+<translation id="5050380848339752099">See sait jagab teavet väljaspool inkognito režiimi oleva rakendusega.</translation>
<translation id="5063480226653192405">Kasutus</translation>
<translation id="5100237604440890931">Ahendatud – laiendamiseks klõpsake.</translation>
<translation id="5123685120097942451">Inkognito vaheleht</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Luba saitidel käitada JavaScripti (soovitatav)</translation>
<translation id="534295439873310000">NFC-seadmed</translation>
<translation id="5354152178998424783">See kustutab <ph name="DATASIZE" /> andmed ja küpsisefailid, mille saidid on salvestanud.</translation>
-<translation id="5384883051496921101">See sait jagab teavet väljaspool inkognito režiimi oleva rakendusega.</translation>
+<translation id="536508626067510330">Kas värskendada avakuval olevat ikooni?</translation>
<translation id="5391532827096253100">Teie ühendus selle saidiga ei ole turvaline. Saidi teave</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(ja veel 1)}other{(ja veel #)}}</translation>
<translation id="5403592356182871684">Nimed</translation>
<translation id="5489227211564503167">Kulunud aeg: <ph name="ELAPSED_TIME" />/<ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blokeeri reklaamid saitidel, mis kuvavad sekkuvaid või eksitavaid reklaame</translation>
+<translation id="549957179819296104">Uus ikoon</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> on lubatud, <ph name="PERMISSION_2" /> on keelatud</translation>
<translation id="5505264765875738116">Saidid ei saa küsida luba märguannete saatmiseks</translation>
<translation id="5516455585884385570">Ava märguandeseaded</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Load</translation>
<translation id="5860033963881614850">Väljas</translation>
<translation id="5876056640971328065">Video peatamine</translation>
+<translation id="5904826301761575486">Kas värskendada avakuval olevat nime ja ikooni?</translation>
<translation id="5916664084637901428">Sees</translation>
<translation id="5922853908706496913">Ekraanikuva jagamine</translation>
<translation id="5939518447894949180">Lähtesta</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokeeri kolmanda osapoole küpsisefailid</translation>
<translation id="6206551242102657620">Ãœhendus on turvaline. Saidi teave</translation>
<translation id="6216432067784365534">Ãœksuse <ph name="NAME_OF_LIST_ITEM" /> valikud</translation>
+<translation id="6260852843601447737">Sulge ja teavita väärkasutusest</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> ja <ph name="PERMISSION_2" /> on keelatud</translation>
<translation id="6270391203985052864">Saidid saavad küsida luba märguannete saatmiseks</translation>
<translation id="6295158916970320988">Kõik saidid</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Selleks et anda rakendusele <ph name="APP_NAME" /> juurdepääs teie asukohale, lülitage funktsioon Asukoht sisse ka <ph name="BEGIN_LINK" />Androidi seadetes<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Seadme loa tühistamine</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 küpsisefail on kasutuses}other{# küpsisefaili on kasutuses}}</translation>
-<translation id="8463851957836045671">Sait on kiire</translation>
<translation id="8487700953926739672">Võrguühenduseta saadaval</translation>
<translation id="851751545965956758">Blokeeri saitidel seadmetega ühenduse loomine</translation>
<translation id="8525306231823319788">Täisekraan</translation>
<translation id="857943718398505171">Lubatud (soovitatav)</translation>
<translation id="8609465669617005112">Liiguta üles</translation>
+<translation id="861748745608658996">Kas värskendada avakuval olevat nime?</translation>
<translation id="8676374126336081632">Tühjenda sisestus</translation>
<translation id="868929229000858085">Otsige kontaktide hulgast</translation>
<translation id="8702612070107455751">Kõik võrguühenduseta andmed kustutatakse.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Suurendab</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC on selle seadme puhul välja lülitatud. Lülitage see <ph name="BEGIN_LINK" />Androidi seadetes<ph name="END_LINK" /> sisse.</translation>
-<translation id="8929372349074745002">See sait avaneb ja vastab enamikule inimestele kiirelt</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Kas lahkuda inkognito režiimist?</translation>
<translation id="8958424370300090006">Blokeerige konkreetse saidi küpsisefailid.</translation>
<translation id="8959122750345127698">Navigeerimine ei ole saadaval: <ph name="URL" /></translation>
<translation id="8986362086234534611">Unusta</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_eu.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_eu.xtb
index 5f005eff2e3..9f3eb98228a 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_eu.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_eu.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="eu">
<translation id="1006017844123154345">Ireki sarean</translation>
<translation id="1044891598689252897">Webguneek ohiko moduan funtzionatuko dute</translation>
+<translation id="1100504063505580045">Une honetako ikonoa</translation>
<translation id="1124090076051167250">Webguneek edo hasierako pantailako aplikazioek gorde dituzten datu eta cookieen <ph name="DATASIZE" /> garbituko dira.</translation>
<translation id="1124772482545689468">Erabiltzailea</translation>
<translation id="1178581264944972037">Pausatu</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofonoa</translation>
<translation id="3277252321222022663">Eman sentsoreak atzitzeko baimena webguneei (gomendatua)</translation>
<translation id="3295602654194328831">Ezkutatu informazioa</translation>
+<translation id="3317660236277031814">Instalatu duzun sareko aplikazio batek ikonoa aldatu du.</translation>
<translation id="3328801116991980348">Webgunearen informazioa</translation>
<translation id="3333961966071413176">Kontaktu guztiak</translation>
<translation id="3386292677130313581">Webguneei zure kokapena erakusteko baimena eman aurretik, eskatu onespena (gomendatua)</translation>
+<translation id="345699454248713913">Instalatu duzun sareko aplikazio batek izena aldatu du.</translation>
<translation id="3538390592868664640">Ez utzi inongo webguneri inguruaren 3D-ko mapa bat sortzen edo kameraren posizioaren jarraipena egiten</translation>
+<translation id="3551268116566418498">Ezkutuko modutik irten nahi duzu?</translation>
<translation id="3586500876634962664">Kamera- eta mikrofono-erabilera</translation>
<translation id="358794129225322306">Eman hainbat fitxategi automatikoki deskargatzeko baimena webgune bati.</translation>
<translation id="3594780231884063836">Desaktibatu bideoaren audioa</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Ireki kokapen-ezarpenak</translation>
<translation id="4226663524361240545">Gailua dardararaz dezakete jakinarazpenek</translation>
<translation id="4259722352634471385"><ph name="URL" /> orrira joateko aukera blokeatuta dago</translation>
+<translation id="4277239631747669329">Instalatu duzun sareko aplikazio batek izena eta ikonoa aldatu ditu.</translation>
<translation id="4278390842282768270">Baimenduta</translation>
<translation id="429312253194641664">Webgune bat multimedia-edukia erreproduzitzen ari da</translation>
<translation id="42981349822642051">Zabaldu</translation>
<translation id="4336434711095810371">Garbitu datu guztiak</translation>
<translation id="4402755511846832236">Ez utzi jakiten webguneei gailua noiz erabiltzen ari zaren</translation>
-<translation id="4433925000917964731">Google-k eskainitako oinarrizko orria</translation>
<translation id="4434045419905280838">Leiho gainerak. / Birbideratzeak</translation>
<translation id="445467742685312942">Baimendu webguneei eduki babestua erreproduzitzea</translation>
<translation id="4468959413250150279">Desaktibatu webgune jakin baten audioa.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Gurasoek kudeatuta</translation>
<translation id="4670064810192446073">Errealitate birtuala</translation>
<translation id="4708011789095599544">Ziur cookieak eta webgune honetako bestelako datuak garbitu nahi dituzula?</translation>
+<translation id="473775607612524610">Eguneratu</translation>
<translation id="4751476147751820511">Mugimenduaren eta argiaren sentsoreak</translation>
<translation id="4836046166855586901">Eman gailua erabiltzen ari zaren galdetzeko baimena webguneei</translation>
<translation id="4883854917563148705">Kudeatutako ezarpenak ezin dira berrezarri</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Partekatu honen bidez:</translation>
<translation id="5039804452771397117">Baimendu</translation>
<translation id="5048398596102334565">Eman mugimendu-sentsoreak atzitzeko baimena webguneei (gomendatua)</translation>
+<translation id="5050380848339752099">Webgunea informazioa partekatzera doa aplikazio batekin ezkutuko modutik kanpo.</translation>
<translation id="5063480226653192405">Erabilera</translation>
<translation id="5100237604440890931">Tolestuta; egin klik zabaltzeko.</translation>
<translation id="5123685120097942451">Ezkutuko moduko fitxa</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Baimendu webguneei JavaScript erabiltzea (gomendatua)</translation>
<translation id="534295439873310000">NFC darabilten gailuak</translation>
<translation id="5354152178998424783">Webguneek gordetako datu eta cookieen <ph name="DATASIZE" /> garbituko dira.</translation>
-<translation id="5384883051496921101">Webgune hau informazioa partekatzera doa aplikazio batekin ezkutuko modutik kanpo.</translation>
+<translation id="536508626067510330">Hasierako pantailako ikonoa eguneratu nahi duzu?</translation>
<translation id="5391532827096253100">Webgune honetarako konexioa ez da guztiz segurua. Webguneari buruzko informazioa</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(eta beste bat)}other{(eta beste #)}}</translation>
<translation id="5403592356182871684">Izenak</translation>
<translation id="5489227211564503167"><ph name="ELAPSED_TIME" /> igaro dira, eta <ph name="TOTAL_TIME" /> gelditzen</translation>
<translation id="5494752089476963479">Blokeatu iragarki oztopatzaileak edo iruzurrezkoak erakusten dituzten webguneetako iragarkiak</translation>
+<translation id="549957179819296104">Ikono berria</translation>
<translation id="5502860503640766021">Baimena eman zaio honi: <ph name="PERMISSION_1" />; <ph name="PERMISSION_2" /> blokeatu egin da</translation>
<translation id="5505264765875738116">Webguneek ezin dute eskatu jakinarazpenak bidaltzea</translation>
<translation id="5516455585884385570">Ireki jakinarazpen-ezarpenak</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Baimenak</translation>
<translation id="5860033963881614850">Desaktibatuta</translation>
<translation id="5876056640971328065">Pausatu bideoa</translation>
+<translation id="5904826301761575486">Hasierako pantailako izena eta ikonoa eguneratu nahi dituzu?</translation>
<translation id="5916664084637901428">Aktibatuta</translation>
<translation id="5922853908706496913">Pantaila partekatzen</translation>
<translation id="5939518447894949180">Berrezarri</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokeatu hirugarrenen cookieak</translation>
<translation id="6206551242102657620">Konexioa segurua da. Webguneari buruzko informazioa</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> - Aukerak</translation>
+<translation id="6260852843601447737">Itxi eta salatu erabilera okerra</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> eta <ph name="PERMISSION_2" /> blokeatu egin dira</translation>
<translation id="6270391203985052864">Webguneek jakinarazpenak bidaltzea eska dezakete</translation>
<translation id="6295158916970320988">Webgune guztiak</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> aplikazioari kokapena atzitzeko baimena emateko, kokapena atzitzeko baimena aktibatu behar duzu <ph name="BEGIN_LINK" />Android-en ezarpenetan<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Kendu gailua atzitzeko baimena</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Erabiltzen den 1 cookie}other{Erabiltzen diren # cookie}}</translation>
-<translation id="8463851957836045671">Webgunea bizkorra da</translation>
<translation id="8487700953926739672">Konexiorik gabe erabilgarri</translation>
<translation id="851751545965956758">Ez utzi webguneei gailuekin konektatzen</translation>
<translation id="8525306231823319788">Pantaila osoa</translation>
<translation id="857943718398505171">Baimenduta (gomendatua)</translation>
<translation id="8609465669617005112">Eraman gora</translation>
+<translation id="861748745608658996">Hasierako pantailako izena aldatu nahi duzu?</translation>
<translation id="8676374126336081632">Garbitu idatzitakoa</translation>
<translation id="868929229000858085">Bilatu kontaktuak</translation>
<translation id="8702612070107455751">Garbitu egingo dira konexiorik gabe gordetako datu guztiak.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Handitu</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC aukera desaktibatuta dago gailu honetan. Aktiba ezazu <ph name="BEGIN_LINK" />Android-en ezarpenetan<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Webgune hau bizkor irekitzen da eta bizkor erantzuten die gehienei</translation>
<translation id="8941729603749328384">www.adibidea.com</translation>
-<translation id="894871326938397531">Ezkutuko modutik irten?</translation>
<translation id="8958424370300090006">Blokeatu webgune jakin bateko cookieak.</translation>
<translation id="8959122750345127698">Ezin da joan <ph name="URL" /> orrira</translation>
<translation id="8986362086234534611">Ahaztu</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fa.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fa.xtb
index 555eb25f8b8..be80a5cbf44 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fa.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fa.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="fa">
<translation id="1006017844123154345">باز کردن نسخه آنلاین</translation>
<translation id="1044891598689252897">عملکرد سایت‌ها عادی خواهد بود</translation>
+<translation id="1100504063505580045">نماد کنونی</translation>
<translation id="1124090076051167250">با این کار <ph name="DATASIZE" /> از داده‌ها Ùˆ کوکی‌هایی Ú©Ù‡ سایت‌ها Ùˆ برنامه‌ها در صÙحه اصلی ذخیره کرده‌اند پاک می‌شود.</translation>
<translation id="1124772482545689468">کاربر</translation>
<translation id="1178581264944972037">Ù…Ú©Ø«</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">میکروÙÙ†</translation>
<translation id="3277252321222022663">مجاز بودن دسترسی سایت‌ها به حسگرها (توصیه می‌شود)</translation>
<translation id="3295602654194328831">پنهان کردن اطلاعات</translation>
+<translation id="3317660236277031814">نماد یکی از برنامه‌های وبی که نصب کرده‌اید تغییر کرده است.</translation>
<translation id="3328801116991980348">اطلاعات سایت</translation>
<translation id="3333961966071413176">همه مخاطبین</translation>
<translation id="3386292677130313581">قبل از اجازه به سایت‌ها برای اطلاع از مکانتان، ابتدا سؤال شود (توصیه می‌شود)</translation>
+<translation id="345699454248713913">نام یکی از برنامه‌های وبی که نصب کرده‌اید تغییر کرده است.</translation>
<translation id="3538390592868664640">قابلیت سایت‌ها برای ایجاد نقشه سه‌بعدی از محیط یا ردیابی موقعیت دوربین مسدود می‌شود</translation>
+<translation id="3551268116566418498">از «حالت ناشناس» خارج می‌شوید؟</translation>
<translation id="3586500876634962664">استÙاده از دوربین Ùˆ میکروÙون</translation>
<translation id="358794129225322306">به سایت اجازه داده شود چند Ùایل را به‌طور خودکار بارگیری کند.</translation>
<translation id="3594780231884063836">بی‌صدا کردن ویدیو</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">باز کردن «تنظیمات مکان»</translation>
<translation id="4226663524361240545">اعلان‌ها ممکن است دستگاه را بلرزانند</translation>
<translation id="4259722352634471385">پیمایش مسدود شده است: <ph name="URL" /></translation>
+<translation id="4277239631747669329">نام و نماد یکی از برنامه‌های وبی که نصب کرده‌اید تغییر کرده است.</translation>
<translation id="4278390842282768270">مجاز است</translation>
<translation id="429312253194641664">سایتی درحال پخش رسانه است</translation>
<translation id="42981349822642051">بزرگ کردن</translation>
<translation id="4336434711095810371">پاک کردن همه داده‌ها</translation>
<translation id="4402755511846832236">از اینکه سایت‌ها بدانند Ú†Ù‡ زمانی به‌صورت Ùعال از این دستگاه استÙاده می‌کنید جلوگیری می‌شود</translation>
-<translation id="4433925000917964731">â€ØµÙحه ساده‌شده را Google ارائه کرده است</translation>
<translation id="4434045419905280838">پنجره‌های بازشو و هدایت‌ها</translation>
<translation id="445467742685312942">به سایت‌ها اجازه داده شود محتوای محاÙظت‌شده پخش کنند</translation>
<translation id="4468959413250150279">سایتی خاص بی‌صدا شود.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">مدیریت شده توسط والدین شما</translation>
<translation id="4670064810192446073">واقعیت مجازی</translation>
<translation id="4708011789095599544">مطمئن هستید می‌خواهید کوکی‌ها و دیگر داده‌های سایت مربوط به این وب‌سایت را پاک کنید؟</translation>
+<translation id="473775607612524610">به‌روزرسانی</translation>
<translation id="4751476147751820511">حسگرهای نوری یا حرکتی</translation>
<translation id="4836046166855586901">وقتی سایتی می‌خواهد بداند Ú†Ù‡ زمانی به‌صورت Ùعال از این دستگاه استÙاده می‌کنید سؤال می‌شود</translation>
<translation id="4883854917563148705">تنظیمات مدیریت‌شده بازنشانی نشدند</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">اشتراک‌گذاری از طریق</translation>
<translation id="5039804452771397117">اجازه دادن</translation>
<translation id="5048398596102334565">مجاز بودن دسترسی سایت‌ها به حسگرهای حرکتی (توصیه می‌شود)</translation>
+<translation id="5050380848339752099">این سایت می‌خواهد خارج از «حالت ناشناس»، اطلاعاتی را با برنامه‌ای هم‌رسانی کند.</translation>
<translation id="5063480226653192405">کاربر </translation>
<translation id="5100237604440890931">کوچک شده - برای بزرگ کردن کلیک کنید.</translation>
<translation id="5123685120097942451">برگه ناشناس</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">مجاز کردن همه سایت‌ها برای اجرای جاوااسکریپت (توصیه‌ می‌شود)</translation>
<translation id="534295439873310000">â€Ø¯Ø³ØªÚ¯Ø§Ù‡â€ŒÙ‡Ø§ÛŒ NFC</translation>
<translation id="5354152178998424783">با این کار <ph name="DATASIZE" /> از داده‌ها و کوکی‌هایی که سایت ذخیره کرده است پاک خواهد شد.</translation>
-<translation id="5384883051496921101">این سایت می‌خواهد خارج از حالت ناشناس، اطلاعاتی را با برنامه‌ای به اشتراک بگذارد.</translation>
+<translation id="536508626067510330">نماد در صÙحه اصلی به‌روزرسانی شود؟</translation>
<translation id="5391532827096253100">اتصال شما به این سایت امن نیست. اطلاعات سایت</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ ۱ مورد دیگر)}one{(+ # مورد دیگر)}other{(+ # مورد دیگر)}}</translation>
<translation id="5403592356182871684">نام‌ها</translation>
<translation id="5489227211564503167">زمان سپری‌شده: <ph name="ELAPSED_TIME" /> از <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">آگهی سایت‌هایی که آگهی‌های مزاحم یا گمراه‌کننده نشان می‌دهند، مسدود می‌شود</translation>
+<translation id="549957179819296104">نماد جدید</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> مجاز است، <ph name="PERMISSION_2" /> مسدود است</translation>
<translation id="5505264765875738116">سایت‌ها نمی‌توانند برای ارسال اعلان درخواست دهند</translation>
<translation id="5516455585884385570">باز کردن تنظیمات اعلان</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">مجوزها</translation>
<translation id="5860033963881614850">خاموش</translation>
<translation id="5876056640971328065">مکث ویدیو</translation>
+<translation id="5904826301761575486">نام Ùˆ نماد در صÙحه اصلی به‌روزرسانی شود؟</translation>
<translation id="5916664084637901428">روشن</translation>
<translation id="5922853908706496913">درحال هم‌رسانی صÙحه‌نمایش</translation>
<translation id="5939518447894949180">بازنشانی</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">مسدود کردن کوکی‌های شخص ثالث</translation>
<translation id="6206551242102657620">اتصال امن است. اطلاعات سایت</translation>
<translation id="6216432067784365534">گزینه‌های <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">بستن Ùˆ گزارش سوءاستÙاده</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> و <ph name="PERMISSION_2" /> مسدود هستند</translation>
<translation id="6270391203985052864">سایت‌ها می‌توانند برای ارسال اعلان درخواست دهند</translation>
<translation id="6295158916970320988">همه سایت‌ها</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">â€Ø¨Ø±Ø§ÛŒ اینکه به <ph name="APP_NAME" /> اجازه دهید به مکانتان دسترسی پیدا کند، مکان را در <ph name="BEGIN_LINK" />تنظیمات Android<ph name="END_LINK" /> نیز روشن کنید.</translation>
<translation id="8447861592752582886">لغو مجوز دستگاه</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Û± Ú©ÙˆÚ©ÛŒ درحال استÙاده است}one{# Ú©ÙˆÚ©ÛŒ درحال استÙاده است}other{# Ú©ÙˆÚ©ÛŒ درحال استÙاده است}}</translation>
-<translation id="8463851957836045671">سایت سریع است</translation>
<translation id="8487700953926739672">امکان دسترسی به صورت Ø¢Ùلاین</translation>
<translation id="851751545965956758">مسدود کردن سایت‌ها برای اتصال به دستگاه‌ها</translation>
<translation id="8525306231823319788">تمام صÙحه</translation>
<translation id="857943718398505171">مجاز (توصیه می‌شود)</translation>
<translation id="8609465669617005112">انتقال به بالا</translation>
+<translation id="861748745608658996">نام در صÙحه اصلی به‌روزرسانی شود؟</translation>
<translation id="8676374126336081632">پاک کردن ورودی</translation>
<translation id="868929229000858085">جستجوی مخاطبین</translation>
<translation id="8702612070107455751">همه داده‌های Ø¢Ùلاین پاک خواهند شد.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">بزرگ‌نمایی</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">â€NFC برای این دستگاه خاموش است. در <ph name="BEGIN_LINK" />تنظیمات Android<ph name="END_LINK" /> آن را روشن کنید.</translation>
-<translation id="8929372349074745002">این سایت برای اکثر اÙراد سریع باز می‌شود Ùˆ پاسخ می‌دهد</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">از حالت ناشناس خارج می‌شوید؟</translation>
<translation id="8958424370300090006">کوکی‌ها را برای سایت خاصی مسدود کنید.</translation>
<translation id="8959122750345127698">پیمایش غیرقابل دسترسی است: <ph name="URL" /></translation>
<translation id="8986362086234534611">Ùراموش شود</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fi.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fi.xtb
index a03f5148a8d..7ff3c2580dd 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fi.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fi.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="fi">
<translation id="1006017844123154345">Avaa verkkoversio</translation>
<translation id="1044891598689252897">Sivustot toimivat normaalisti</translation>
+<translation id="1100504063505580045">Nykyinen kuvake</translation>
<translation id="1124090076051167250">Tämä tyhjentää <ph name="DATASIZE" /> dataa ja aloitusnäytölläsi olevien sivustojen tai sovellusten tallentamat evästeet.</translation>
<translation id="1124772482545689468">Käyttäjä</translation>
<translation id="1178581264944972037">Tauko</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofoni</translation>
<translation id="3277252321222022663">Anna sivustojen käyttää tunnistimia (suositus)</translation>
<translation id="3295602654194328831">Piilota tiedot</translation>
+<translation id="3317660236277031814">Lataamasi verkkosovelluksen kuvake on muuttunut.</translation>
<translation id="3328801116991980348">Tietoja sivustosta</translation>
<translation id="3333961966071413176">Kaikki yhteystiedot</translation>
<translation id="3386292677130313581">Pyydä lupaa, kun sivustot yrittävät käyttää sijaintiasi (suositus).</translation>
+<translation id="345699454248713913">Lataamasi verkkosovelluksen nimi on muuttunut.</translation>
<translation id="3538390592868664640">Estä sivustoja luomasta 3D-karttaa ympäristöstäsi tai seuraamasta kameran asentoa</translation>
+<translation id="3551268116566418498">Poistutaanko incognito-tilasta?</translation>
<translation id="3586500876634962664">Kameran ja mikrofonin käyttö</translation>
<translation id="358794129225322306">Anna sivuston ladata useita tiedostoja automaattisesti.</translation>
<translation id="3594780231884063836">Mykistä video</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Avaa sijaintiasetukset</translation>
<translation id="4226663524361240545">Laite voi väristä ilmoitusten yhteydessä.</translation>
<translation id="4259722352634471385">Kohde on estetty: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Lataamasi verkkosovelluksen nimi ja kuvake on muuttunut.</translation>
<translation id="4278390842282768270">Sallittu</translation>
<translation id="429312253194641664">Sivusto toistaa mediaa</translation>
<translation id="42981349822642051">Laajenna</translation>
<translation id="4336434711095810371">Poista kaikki data</translation>
<translation id="4402755511846832236">Estä sivustoja tietämästä, kun käytät tätä laitetta aktiivisesti</translation>
-<translation id="4433925000917964731">Googlen tarjoama yksinkertaistettu sivu</translation>
<translation id="4434045419905280838">Ponn.ikkunat ja uudelleenohjaus</translation>
<translation id="445467742685312942">Salli sivustojen toistaa suojattua sisältöä</translation>
<translation id="4468959413250150279">Mykistä tietyn sivuston äänet.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Vanhempasi hallinnoima</translation>
<translation id="4670064810192446073">Virtuaalitodellisuus</translation>
<translation id="4708011789095599544">Haluatko varmasti tyhjentää tämän sivuston evästeet ja muun sivustodatan?</translation>
+<translation id="473775607612524610">Päivitä</translation>
<translation id="4751476147751820511">Liike- tai valotunnistimet</translation>
<translation id="4836046166855586901">Kysy aina, kun sivusto pyytää lupaa nähdä, käytätkö tätä laitetta aktiivisesti</translation>
<translation id="4883854917563148705">Ylläpidettyjä asetuksia ei voi nollata</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Jaa palvelussa:</translation>
<translation id="5039804452771397117">Salli</translation>
<translation id="5048398596102334565">Anna sivustojen käyttää liiketunnistimien lukemia (suositus)</translation>
+<translation id="5050380848339752099">Tämä sivusto aikoo jakaa tietoja sovellukselle incognito-tilan ulkopuolella.</translation>
<translation id="5063480226653192405">Käyttö</translation>
<translation id="5100237604440890931">Tiivistetty – laajenna klikkaamalla.</translation>
<translation id="5123685120097942451">Incognito-välilehti</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Anna kaikkien sivustojen käyttää JavaScriptiä (suositus).</translation>
<translation id="534295439873310000">NFC-laitteet</translation>
<translation id="5354152178998424783">Tämä tyhjentää <ph name="DATASIZE" /> dataa ja sivustojen tallentamat evästeet.</translation>
-<translation id="5384883051496921101">Tämä sivusto aikoo jakaa tietoja sovellukselle incognito-tilan ulkopuolella.</translation>
+<translation id="536508626067510330">Päivitetäänkö kuvake aloitusnäytöllä?</translation>
<translation id="5391532827096253100">Sivustolle muodostamasi yhteys ei ole turvallinen. Sivuston tiedot</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 muu)}other{(+ # muuta)}}</translation>
<translation id="5403592356182871684">Nimet</translation>
<translation id="5489227211564503167">Kulunut aika: <ph name="ELAPSED_TIME" />/<ph name="TOTAL_TIME" /></translation>
<translation id="5494752089476963479">Estä häiritseviä tai harhaanjohtavia mainoksia näyttävien sivustojen mainokset</translation>
+<translation id="549957179819296104">Uusi kuvake</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> sallittu, <ph name="PERMISSION_2" /> estetty</translation>
<translation id="5505264765875738116">Sivustot eivät saa pyytää lupaa ilmoitusten lähettämiseen</translation>
<translation id="5516455585884385570">Avaa ilmoitusasetukset</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Luvat</translation>
<translation id="5860033963881614850">Pois päältä</translation>
<translation id="5876056640971328065">Keskeytä video</translation>
+<translation id="5904826301761575486">Päivitetäänkö nimi ja kuvake aloitusnäytöllä?</translation>
<translation id="5916664084637901428">Päällä</translation>
<translation id="5922853908706496913">Näyttösi jaetaan</translation>
<translation id="5939518447894949180">Tyhjennä</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Estä kolmannen osapuolen evästeet</translation>
<translation id="6206551242102657620">Yhteys on turvallinen. Sivuston tiedot</translation>
<translation id="6216432067784365534">Vaihtoehdot: <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Sulje ja ilmoita väärinkäytöstä</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> ja <ph name="PERMISSION_2" /> estetty</translation>
<translation id="6270391203985052864">Sivustot saavat pyytää lupaa lähettää ilmoituksia</translation>
<translation id="6295158916970320988">Kaikki sivustot</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Ota sijaintitiedot käyttöön myös <ph name="BEGIN_LINK" />Androidin asetuksista<ph name="END_LINK" />, jotta <ph name="APP_NAME" /> saa pääsyn sijaintiisi.</translation>
<translation id="8447861592752582886">Peru laitteen käyttöoikeus</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 eväste käytössä}other{# evästettä käytössä}}</translation>
-<translation id="8463851957836045671">Sivusto on nopea</translation>
<translation id="8487700953926739672">Käytettävissä offline-tilassa</translation>
<translation id="851751545965956758">Estä sivustoja yhdistämästä laitteisiin</translation>
<translation id="8525306231823319788">Koko näyttö</translation>
<translation id="857943718398505171">Sallittu (suositus)</translation>
<translation id="8609465669617005112">Siirrä ylös</translation>
+<translation id="861748745608658996">Päivitetäänkö nimi aloitusnäytöllä?</translation>
<translation id="8676374126336081632">Tyhjennä teksti</translation>
<translation id="868929229000858085">Hae yhteystiedoistasi</translation>
<translation id="8702612070107455751">Kaikki offline-data poistetaan</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Lähennä</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC on pois päältä tällä laitteella. Voit laittaa sen päälle <ph name="BEGIN_LINK" />Androidin asetuksista<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Useimmissa tapauksissa sivusto avautuu ja vastaa nopeasti</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Poistutaanko incognito-tilasta?</translation>
<translation id="8958424370300090006">Estä evästeet tietyltä sivustolta.</translation>
<translation id="8959122750345127698">Kohde ei ole saatavilla: <ph name="URL" /></translation>
<translation id="8986362086234534611">Unohda</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fil.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fil.xtb
index 8580644777e..ebe41bd64d3 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fil.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fil.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="fil">
<translation id="1006017844123154345">Buksan Online</translation>
<translation id="1044891598689252897">Gagana nang normal ang mga site</translation>
+<translation id="1100504063505580045">Kasalukuyang icon</translation>
<translation id="1124090076051167250">Iki-clear nito ang <ph name="DATASIZE" /> ng data at cookies na na-store ng mga site o ng mga app sa iyong Home screen.</translation>
<translation id="1124772482545689468">User</translation>
<translation id="1178581264944972037">I-pause</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikropono</translation>
<translation id="3277252321222022663">Payagan ang mga site na i-access ang mga sensor (inirerekomenda)</translation>
<translation id="3295602654194328831">Itago ang Impormasyon</translation>
+<translation id="3317660236277031814">Binago ng isang web app na na-install mo ang icon nito.</translation>
<translation id="3328801116991980348">Impormasyon ng site</translation>
<translation id="3333961966071413176">Lahat ng contact</translation>
<translation id="3386292677130313581">Magtanong bago payagan ang mga site na malaman ang iyong lokasyon (inirerekomenda)</translation>
+<translation id="345699454248713913">Binago ng isang web app na na-install mo ang pangalan nito.</translation>
<translation id="3538390592868664640">I-block ang mga site sa paggawa ng 3D na mapa ng iyong kapaligiran o pagsubaybay sa posisyon ng camera</translation>
+<translation id="3551268116566418498">Umalis sa Incognito mode?</translation>
<translation id="3586500876634962664">Paggamit ng camera at mikropono</translation>
<translation id="358794129225322306">Payagan ang isang site na awtomatikong mag-download ng maraming file.</translation>
<translation id="3594780231884063836">I-mute ang video</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Buksan ang Mga Setting ng Lokasyon</translation>
<translation id="4226663524361240545">Maaaring mag-vibrate ang device dahil sa mga notification</translation>
<translation id="4259722352634471385">Naka-block ang navigation: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Binago ng isang web app na na-install mo ang pangalan at icon nito.</translation>
<translation id="4278390842282768270">Pinapayagan</translation>
<translation id="429312253194641664">May site na nagpe-play ng media</translation>
<translation id="42981349822642051">Palawakin</translation>
<translation id="4336434711095810371">I-clear ang lahat ng data</translation>
<translation id="4402755511846832236">Pigilan ang mga site na malaman kung kailan mo aktibong ginagamit ang device na ito</translation>
-<translation id="4433925000917964731">Hatid ng Google ang lite na page</translation>
<translation id="4434045419905280838">Mga pop-up at pag-redirect</translation>
<translation id="445467742685312942">Pahintulutan ang mga site na mag-play ng pinoprotektahang content</translation>
<translation id="4468959413250150279">I-mute ang tunog para sa isang partikular na site.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Pinamamahalaan ng iyong magulang</translation>
<translation id="4670064810192446073">Virtual reality</translation>
<translation id="4708011789095599544">Sigurado ka bang gusto mong i-clear ang cookies at iba pang data ng site para sa website na ito?</translation>
+<translation id="473775607612524610">I-update</translation>
<translation id="4751476147751820511">Mga motion o light sensor</translation>
<translation id="4836046166855586901">Magtanong kapag gusto ng site na alamin kung kailan mo aktibong ginagamit ang device na ito</translation>
<translation id="4883854917563148705">Hindi puwedeng i-reset ang mga pinapamahalaang setting</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Ibahagi gamit ang</translation>
<translation id="5039804452771397117">Payagan</translation>
<translation id="5048398596102334565">Payagan ang mga site na i-access ang mga sensor ng paggalaw (inirerekomenda)</translation>
+<translation id="5050380848339752099">Magbabahagi ang site na ito ng impormasyon sa isang app sa labas ng Incognito mode.</translation>
<translation id="5063480226653192405">Paggamit</translation>
<translation id="5100237604440890931">Naka-collapse - i-click upang palawakin</translation>
<translation id="5123685120097942451">Tab na incognito</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Payagan ang mga site na magpatakbo ng JavaScript (inirerekomenda)</translation>
<translation id="534295439873310000">Mga NFC device</translation>
<translation id="5354152178998424783">Iki-clear nito ang <ph name="DATASIZE" /> ng data at cookies na na-store ng mga site.</translation>
-<translation id="5384883051496921101">Magbabahagi ang site na ito ng impormasyon sa isang app sa labas ng incognito mode.</translation>
+<translation id="536508626067510330">I-update ang icon sa iyong homescreen?</translation>
<translation id="5391532827096253100">Hindi secure ang iyong koneksyon sa site na ito. Impormasyon ng site</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 pa)}one{(+ # pa)}other{(+ # pa)}}</translation>
<translation id="5403592356182871684">Mga Pangalan</translation>
<translation id="5489227211564503167"><ph name="ELAPSED_TIME" /> ang lumipas mula sa <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">I-block ang mga ad sa mga site na nagpapakita ng mga nakakasagabal o nakakapanlinlang na ad</translation>
+<translation id="549957179819296104">Bagong icon</translation>
<translation id="5502860503640766021">Pinapayagan ang <ph name="PERMISSION_1" />, naka-block ang <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Hindi puwedeng humiling ang mga site na magpadala ng mga notification</translation>
<translation id="5516455585884385570">Buksan ang mga setting ng notification</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Mga Pahintulot</translation>
<translation id="5860033963881614850">Naka-off</translation>
<translation id="5876056640971328065">I-pause ang video</translation>
+<translation id="5904826301761575486">I-update ang pangalan at icon sa iyong homescreen?</translation>
<translation id="5916664084637901428">Naka-on</translation>
<translation id="5922853908706496913">Ibinabahagi ang iyong screen</translation>
<translation id="5939518447894949180">I-reset</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">I-block ang mga third-party na cookie</translation>
<translation id="6206551242102657620">Secure ang koneksyon. Impormasyon ng site</translation>
<translation id="6216432067784365534">Mga Opsyon sa <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Isara at iulat ang pang-aabuso</translation>
<translation id="6262279340360821358">Naka-block ang <ph name="PERMISSION_1" /> at <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Puwedeng humiling ang mga site na magpadala ng mga notification</translation>
<translation id="6295158916970320988">Lahat ng site</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Para payagan ang <ph name="APP_NAME" /> na i-access ang iyong lokasyon, i-on din ang lokasyon sa <ph name="BEGIN_LINK" />Mga Setting ng Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Bawiin ang pahintulot ng device</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie ang ginagamit}one{# cookie ang ginagamit}other{# na cookie ang ginagamit}}</translation>
-<translation id="8463851957836045671">Mabilis ang site</translation>
<translation id="8487700953926739672">Available sa offline</translation>
<translation id="851751545965956758">I-block ang mga site sa pagkonekta sa mga device</translation>
<translation id="8525306231823319788">Buong screen</translation>
<translation id="857943718398505171">Pinapayagan (inirerekomenda)</translation>
<translation id="8609465669617005112">Lumipat</translation>
+<translation id="861748745608658996">I-update ang pangalan sa iyong homescreen?</translation>
<translation id="8676374126336081632">I-clear ang input</translation>
<translation id="868929229000858085">Maghanap sa iyong mga contact</translation>
<translation id="8702612070107455751">Maki-clear ang anumang offline na data.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Mag-zoom in</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">Naka-off ang NFC para sa device na ito. I-on ito sa <ph name="BEGIN_LINK" />Mga Setting ng Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Mabilis na bumubukas at tumutugon ang site na ito para sa karamihan ng mga tao</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Umalis sa incognito mode?</translation>
<translation id="8958424370300090006">Mag-block ng cookies para sa isang partikular na site.</translation>
<translation id="8959122750345127698">Hindi gumagana ang navigation: <ph name="URL" /></translation>
<translation id="8986362086234534611">Kalimutan</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fr-CA.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fr-CA.xtb
index c22b4e69f96..2063a79d47c 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fr-CA.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fr-CA.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="fr-CA">
<translation id="1006017844123154345">Ouvrir en ligne</translation>
<translation id="1044891598689252897">Les sites fonctionneront normalement</translation>
+<translation id="1100504063505580045">Icône actuelle</translation>
<translation id="1124090076051167250">Cette action effacera <ph name="DATASIZE" /> de données et de témoins qu'ont stockés des sites ou des applications sur votre écran d'accueil.</translation>
<translation id="1124772482545689468">Utilisateur</translation>
<translation id="1178581264944972037">Interrompre</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Microphone</translation>
<translation id="3277252321222022663">Autoriser les sites à accéder aux capteurs (recommandé)</translation>
<translation id="3295602654194328831">Masquer les renseignements</translation>
+<translation id="3317660236277031814">L'icône d'une application Web que vous avez installée a été modifiée.</translation>
<translation id="3328801116991980348">Information sur le site</translation>
<translation id="3333961966071413176">Tous les contacts</translation>
<translation id="3386292677130313581">Demander avant d'autoriser des sites à connaître votre emplacement (recommandé)</translation>
+<translation id="345699454248713913">Le nom d'une application Web que vous avez installée a été modifié.</translation>
<translation id="3538390592868664640">Empêcher les sites de créer une carte 3D de votre environnement et de faire le suivi de la position de l'appareil photo</translation>
+<translation id="3551268116566418498">Désactiver mode navig. privée?</translation>
<translation id="3586500876634962664">Util. de la caméra et du micro</translation>
<translation id="358794129225322306">Permet au site de télécharger plusieurs fichiers automatiquement.</translation>
<translation id="3594780231884063836">Désactiver le son de la vidéo</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Ouvrir les paramètres de localisation</translation>
<translation id="4226663524361240545">Les notifications peuvent faire vibrer l'appareil</translation>
<translation id="4259722352634471385">Navigation bloquée : <ph name="URL" /></translation>
+<translation id="4277239631747669329">Le nom et l'icône d'une application Web que vous avez installée ont été modifiés.</translation>
<translation id="4278390842282768270">Autorisé</translation>
<translation id="429312253194641664">Un site lit du contenu multimédia</translation>
<translation id="42981349822642051">Développer</translation>
<translation id="4336434711095810371">Effacer toutes les données</translation>
<translation id="4402755511846832236">Empêcher les sites de savoir quand vous êtes en train d'utiliser cet appareil</translation>
-<translation id="4433925000917964731">Page en version simplifiée fournie par Google</translation>
<translation id="4434045419905280838">Fenêt. context. et redirections</translation>
<translation id="445467742685312942">Autoriser les sites à lire du contenu protégé</translation>
<translation id="4468959413250150279">Désactivez le son sur un site précis.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Géré par l’un de tes parents</translation>
<translation id="4670064810192446073">Réalité virtuelle</translation>
<translation id="4708011789095599544">Voulez-vous vraiment supprimer les témoins et les autres données de ce site Web?</translation>
+<translation id="473775607612524610">Mise à jour</translation>
<translation id="4751476147751820511">Capteurs de mouvement ou de luminosité</translation>
<translation id="4836046166855586901">Demander une autorisation lorsqu'un site veut savoir si vous êtes en train d'utiliser cet appareil</translation>
<translation id="4883854917563148705">Les paramètres gérés ne peuvent pas être réinitialisés</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Partager par</translation>
<translation id="5039804452771397117">Autoriser</translation>
<translation id="5048398596102334565">Autoriser les sites à accéder à vos capteurs de mouvements (recommandé)</translation>
+<translation id="5050380848339752099">Ce site est sur le point de partager des renseignements avec une application à l'extérieur du mode de navigation privée.</translation>
<translation id="5063480226653192405">Utilisation</translation>
<translation id="5100237604440890931">Réduit : cliquer pour développer</translation>
<translation id="5123685120097942451">Onglet de navigation privée</translation>
@@ -151,14 +157,15 @@
<translation id="5313967007315987356">Ajouter un site</translation>
<translation id="5317780077021120954">Enregistrer</translation>
<translation id="5335288049665977812">Autoriser les sites à exécuter JavaScript (recommandé)</translation>
-<translation id="534295439873310000">Appareils NFC</translation>
+<translation id="534295439873310000">Appareils CCP</translation>
<translation id="5354152178998424783">Cette action effacera <ph name="DATASIZE" /> de données et de témoins qu'ont stockés des sites.</translation>
-<translation id="5384883051496921101">Ce site est sur le point de partager des renseignements avec une application à l'extérieur du mode de navigation privée.</translation>
+<translation id="536508626067510330">Mettre à jour l'icône sur votre écran d'accueil?</translation>
<translation id="5391532827096253100">Votre connexion à ce site n'est pas sécurisée. Renseignements sur le site</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 autre)}one{(+ # autre)}other{(+ # autres)}}</translation>
<translation id="5403592356182871684">Noms</translation>
<translation id="5489227211564503167">Temps écoulé : <ph name="ELAPSED_TIME" /> sur <ph name="TOTAL_TIME" /></translation>
<translation id="5494752089476963479">Bloquer les annonces sur les sites qui diffusent des annonces intrusives ou trompeuses</translation>
+<translation id="549957179819296104">Nouvelle icône</translation>
<translation id="5502860503640766021">Autorisation <ph name="PERMISSION_1" /> autorisée, autorisation <ph name="PERMISSION_2" /> bloquée</translation>
<translation id="5505264765875738116">Les sites ne peuvent pas vous demander l'autorisation d'envoyer des notifications</translation>
<translation id="5516455585884385570">Ouvrir les paramètres de notification</translation>
@@ -169,12 +176,13 @@
<translation id="5677928146339483299">Bloqué</translation>
<translation id="5689516760719285838">Lieu</translation>
<translation id="5690795753582697420">L'appareil photo est désactivé dans les paramètres d'Android</translation>
-<translation id="5710871682236653961">Demander avant d'autoriser les sites à envoyer et à recevoir de l'information lorsque vous touchez des appareils NFC (recommandé)</translation>
+<translation id="5710871682236653961">Demander avant d'autoriser les sites à envoyer et à recevoir de l'information lorsque vous touchez des appareils CCP (recommandé)</translation>
<translation id="5719847187258001597">Cette action entraînera la suppression de l'ensemble des données et des témoins stockés par <ph name="ORIGIN" /> ou son application installée sur votre écran d'accueil.</translation>
<translation id="5771720122942595109">Autorisation <ph name="PERMISSION_1" /> bloquée</translation>
<translation id="5804241973901381774">Autorisations</translation>
<translation id="5860033963881614850">Désactivé</translation>
<translation id="5876056640971328065">Suspendre la vidéo</translation>
+<translation id="5904826301761575486">Mettre à jour le nom et l'icône sur votre écran d'accueil?</translation>
<translation id="5916664084637901428">Activé</translation>
<translation id="5922853908706496913">Partage de votre écran en cours…</translation>
<translation id="5939518447894949180">Recommencer</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Bloquer les témoins de tiers</translation>
<translation id="6206551242102657620">La connexion est sécurisée. Renseignements sur le site</translation>
<translation id="6216432067784365534">Options de <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Fermer et signaler l'abus</translation>
<translation id="6262279340360821358">Autorisations <ph name="PERMISSION_1" /> et <ph name="PERMISSION_2" /> bloquées</translation>
<translation id="6270391203985052864">Les sites peuvent vous demander l'autorisation d'envoyer des notifications</translation>
<translation id="6295158916970320988">Tous les sites</translation>
@@ -214,7 +223,7 @@
<translation id="6766622839693428701">Glissez le doigt vers le bas pour fermer.</translation>
<translation id="6790428901817661496">Jouer</translation>
<translation id="6818926723028410516">Sélectionner des éléments</translation>
-<translation id="6864395892908308021">Cet appareil ne prend pas en charge la technologie NFC</translation>
+<translation id="6864395892908308021">Cet appareil ne prend pas en charge la technologie CCP</translation>
<translation id="6910211073230771657">Supprimé</translation>
<translation id="6912998170423641340">Empêcher les sites de lire du texte et des images du presse-papiers</translation>
<translation id="6945221475159498467">Sélectionner</translation>
@@ -239,7 +248,7 @@
<translation id="7521387064766892559">JavaScript</translation>
<translation id="7554752735887601236">Un site utilise votre microphone</translation>
<translation id="7561196759112975576">Toujours</translation>
-<translation id="7572498721684305250">Empêcher les sites d'envoyer et de recevoir de l'information lorsque vous touchez des appareils NFC</translation>
+<translation id="7572498721684305250">Empêcher les sites d'envoyer et de recevoir de l'information lorsque vous touchez des appareils CCP</translation>
<translation id="757524316907819857">Empêcher les sites de lire du contenu protégé</translation>
<translation id="7589445247086920869">Bloquer pour le moteur de recherche actuel</translation>
<translation id="7649070708921625228">Aide</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Pour autoriser <ph name="APP_NAME" /> à accéder à votre position, activez aussi la localisation dans les <ph name="BEGIN_LINK" />paramètres d'Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Révoquer l'autorisation de l'appareil</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 témoin en cours d'utilisation}one{# témoin en cours d'utilisation}other{# témoins en cours d'utilisation}}</translation>
-<translation id="8463851957836045671">Le site est rapide</translation>
<translation id="8487700953926739672">Offert en ligne</translation>
<translation id="851751545965956758">Empêcher les sites de se connecter à des appareils</translation>
<translation id="8525306231823319788">Plein écran</translation>
<translation id="857943718398505171">Autorisée (recommandé)</translation>
<translation id="8609465669617005112">Déplacer vers le haut</translation>
+<translation id="861748745608658996">Mettre à jour le nom sur votre écran d'accueil?</translation>
<translation id="8676374126336081632">Effacer l'entrée</translation>
<translation id="868929229000858085">Effectuez une recherche dans vos contacts</translation>
<translation id="8702612070107455751">Toutes les données hors ligne seront effacées.</translation>
@@ -301,10 +310,8 @@
<translation id="8847988622838149491">USB</translation>
<translation id="8903921497873541725">Zoom avant</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> sur <ph name="DURATION" /></translation>
-<translation id="8926666909099850184">La NFC est désactivée pour cet appareil. Activez-la dans le menu <ph name="BEGIN_LINK" />Paramètres Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Ce site s'ouvre et répond rapidement pour la majorité des gens</translation>
+<translation id="8926666909099850184">La CCP est désactivée pour cet appareil. Activez-la dans le menu <ph name="BEGIN_LINK" />Paramètres Android<ph name="END_LINK" />.</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Désactiver mode de nav. privée?</translation>
<translation id="8958424370300090006">Bloquer les témoins pour un site en particulier.</translation>
<translation id="8959122750345127698">Navigation inaccessible : <ph name="URL" /></translation>
<translation id="8986362086234534611">Supprimer</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fr.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fr.xtb
index b122f32638b..8ccef9abcf8 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fr.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_fr.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="fr">
<translation id="1006017844123154345">Ouvrir la version en ligne</translation>
<translation id="1044891598689252897">Les sites fonctionneront normalement</translation>
+<translation id="1100504063505580045">Icône actuelle</translation>
<translation id="1124090076051167250">Cette action entraînera la suppression de <ph name="DATASIZE" /> de données et de cookies stockés par des sites ou des applications installées sur votre écran d'accueil.</translation>
<translation id="1124772482545689468">Utilisateur</translation>
<translation id="1178581264944972037">Suspendre</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Micro</translation>
<translation id="3277252321222022663">Autoriser les sites à accéder à vos capteurs (recommandé)</translation>
<translation id="3295602654194328831">Masquer les informations</translation>
+<translation id="3317660236277031814">L'icône d'une application Web que vous avez installée a été modifiée.</translation>
<translation id="3328801116991980348">Informations sur le site</translation>
<translation id="3333961966071413176">Tous les contacts</translation>
<translation id="3386292677130313581">Demander avant d'autoriser des sites à accéder à ma position (recommandé)</translation>
+<translation id="345699454248713913">Le nom d'une application Web que vous avez installée a été modifié.</translation>
<translation id="3538390592868664640">Empêcher les sites de créer un plan 3D de votre environnement ou de suivre la position de la caméra</translation>
+<translation id="3551268116566418498">Quitter la navigation privée ?</translation>
<translation id="3586500876634962664">Utilisation de la caméra et du micro</translation>
<translation id="358794129225322306">Autoriser un site à télécharger automatiquement plusieurs fichiers</translation>
<translation id="3594780231884063836">Couper le son de la vidéo</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Accéder aux paramètres de localisation</translation>
<translation id="4226663524361240545">L'appareil vibrera en cas de notifications.</translation>
<translation id="4259722352634471385">La navigation sur <ph name="URL" /> est bloquée.</translation>
+<translation id="4277239631747669329">Le nom et l'icône d'une application Web que vous avez installée ont été modifiés.</translation>
<translation id="4278390842282768270">Autorisé</translation>
<translation id="429312253194641664">Un site est en train de lire un contenu multimédia</translation>
<translation id="42981349822642051">Développer</translation>
<translation id="4336434711095810371">Effacer toutes les données</translation>
<translation id="4402755511846832236">Empêcher les sites de savoir si vous utilisez activement cet appareil</translation>
-<translation id="4433925000917964731">Page simplifiée fournie par Google</translation>
<translation id="4434045419905280838">Pop-up et redirections</translation>
<translation id="445467742685312942">Autoriser les sites à lire les contenus protégés</translation>
<translation id="4468959413250150279">Coupez le son d'un site spécifique.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Géré par ton papa/ta maman</translation>
<translation id="4670064810192446073">Réalité virtuelle</translation>
<translation id="4708011789095599544">Voulez-vous vraiment supprimer les cookies et autres données de ce site Web ?</translation>
+<translation id="473775607612524610">Mettre à jour</translation>
<translation id="4751476147751820511">Capteurs de mouvement ou de lumière</translation>
<translation id="4836046166855586901">Demander lorsqu'un site souhaite savoir si vous utilisez activement cet appareil</translation>
<translation id="4883854917563148705">Impossible de réinitialiser les paramètres gérés</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Partager via</translation>
<translation id="5039804452771397117">Autoriser</translation>
<translation id="5048398596102334565">Autoriser les sites à accéder à vos capteurs de mouvement (recommandé)</translation>
+<translation id="5050380848339752099">Ce site s'apprête à partager des informations avec une appli en dehors du mode navigation privée.</translation>
<translation id="5063480226653192405">Utilisation</translation>
<translation id="5100237604440890931">Réduit – Cliquer pour développer</translation>
<translation id="5123685120097942451">Onglet de navigation privée</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Autoriser les sites à exécuter JavaScript (recommandé)</translation>
<translation id="534295439873310000">Appareils NFC</translation>
<translation id="5354152178998424783">Cette action entraînera la suppression de <ph name="DATASIZE" /> de données et de cookies stockés par les sites.</translation>
-<translation id="5384883051496921101">Ce site s'apprête à partager des informations avec une application en dehors du mode navigation privée.</translation>
+<translation id="536508626067510330">Modifier l'icône sur votre écran d'accueil ?</translation>
<translation id="5391532827096253100">Votre connexion à ce site n'est pas sécurisée. Informations sur le site</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 autre)}one{(+ # autre)}other{(+ # autres)}}</translation>
<translation id="5403592356182871684">Noms</translation>
<translation id="5489227211564503167">Temps écoulé : <ph name="ELAPSED_TIME" /> sur <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Bloquer les annonces sur les sites qui affichent des annonces intrusives ou trompeuses</translation>
+<translation id="549957179819296104">Nouvelle icône</translation>
<translation id="5502860503640766021">Autorisation accordée : <ph name="PERMISSION_1" />, autorisation refusée : <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Les sites ne peuvent pas vous demander l'autorisation d'envoyer des notifications</translation>
<translation id="5516455585884385570">Ouvrir les paramètres de notification</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Autorisations</translation>
<translation id="5860033963881614850">Désactivé</translation>
<translation id="5876056640971328065">Mettre la vidéo en pause</translation>
+<translation id="5904826301761575486">Modifier le nom et l'icône sur votre écran d'accueil ?</translation>
<translation id="5916664084637901428">Activé</translation>
<translation id="5922853908706496913">Partage de votre écran…</translation>
<translation id="5939518447894949180">Réinitialiser</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Bloquer les cookies tiers</translation>
<translation id="6206551242102657620">La connexion est sécurisée. Informations sur le site</translation>
<translation id="6216432067784365534">Options pour <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Fermer et signaler l'abus</translation>
<translation id="6262279340360821358">Autorisations refusées : <ph name="PERMISSION_1" /> et <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Les sites peuvent vous demander l'autorisation d'envoyer des notifications</translation>
<translation id="6295158916970320988">Tous les sites</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Pour autoriser <ph name="APP_NAME" /> à accéder à votre position, activez également la localisation dans les <ph name="BEGIN_LINK" />paramètres Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Révoquer l'autorisation d'accès à l'appareil</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie est actuellement utilisé}one{# cookie est actuellement utilisé}other{# cookies sont actuellement utilisés}}</translation>
-<translation id="8463851957836045671">Le site est rapide</translation>
<translation id="8487700953926739672">Disponible hors connexion</translation>
<translation id="851751545965956758">Interdire à tous les sites de se connecter à des appareils</translation>
<translation id="8525306231823319788">Plein écran</translation>
<translation id="857943718398505171">Autorisé (recommandé)</translation>
<translation id="8609465669617005112">Monter</translation>
+<translation id="861748745608658996">Modifier le nom sur votre écran d'accueil ?</translation>
<translation id="8676374126336081632">Effacer la saisie</translation>
<translation id="868929229000858085">Rechercher des contacts</translation>
<translation id="8702612070107455751">Toutes les données hors connexion vont être effacées.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Zoom avant</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">La fonctionnalité NFC est désactivée pour cet appareil. Activez-la dans les <ph name="BEGIN_LINK" />paramètres Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Ce site s'ouvre et répond aux interactions rapidement pour la majorité des utilisateurs</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Quitter le mode navigation privée ?</translation>
<translation id="8958424370300090006">Bloquez les cookies pour un site spécifique.</translation>
<translation id="8959122750345127698">Impossible d'accéder à <ph name="URL" />.</translation>
<translation id="8986362086234534611">Retirer</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_gl.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_gl.xtb
index 195d5f5c711..28b0d91be8e 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_gl.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_gl.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="gl">
<translation id="1006017844123154345">Abrir en liña</translation>
<translation id="1044891598689252897">Os sitios funcionarán con normalidade</translation>
+<translation id="1100504063505580045">Icona actual</translation>
<translation id="1124090076051167250">Ao realizar esta acción, borraranse os datos e as cookies (<ph name="DATASIZE" />) que almacenasen os sitios ou as aplicacións da túa pantalla de inicio.</translation>
<translation id="1124772482545689468">Usuario</translation>
<translation id="1178581264944972037">Pausar</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Micrófono</translation>
<translation id="3277252321222022663">Permitir que os sitios accedan aos sensores (recomendado)</translation>
<translation id="3295602654194328831">Ocultar información</translation>
+<translation id="3317660236277031814">Unha aplicación web que instalaches cambiou de icona.</translation>
<translation id="3328801116991980348">Información do sitio</translation>
<translation id="3333961966071413176">Todos os contactos</translation>
<translation id="3386292677130313581">Pregunta antes de permitir que os sitios coñezan a túa localización (recomendado)</translation>
+<translation id="345699454248713913">Unha aplicación web que instalaches cambiou de nome.</translation>
<translation id="3538390592868664640">Impide que os sitios creen un mapa 3D do que te rodea e fagan un seguimento da posición da cámara</translation>
+<translation id="3551268116566418498">Saír do modo de incógnito?</translation>
<translation id="3586500876634962664">Uso da cámara e do micrófono</translation>
<translation id="358794129225322306">Permite que un sitio descargue varios ficheiros automaticamente.</translation>
<translation id="3594780231884063836">Silenciar o vídeo</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Abrir Configuración de localización</translation>
<translation id="4226663524361240545">O dispositivo pode vibrar ao recibir notificacións</translation>
<translation id="4259722352634471385">A navegación está bloqueada: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Unha aplicación web que instalaches cambiou de nome e de icona.</translation>
<translation id="4278390842282768270">Permitida</translation>
<translation id="429312253194641664">Un sitio está reproducindo contido multimedia</translation>
<translation id="42981349822642051">Ampliar</translation>
<translation id="4336434711095810371">Borrar todos os datos</translation>
<translation id="4402755511846832236">Impide que os sitios saiban se estás utilizando este dispositivo de maneira activa</translation>
-<translation id="4433925000917964731">Páxina en modo básico ofrecida por Google.</translation>
<translation id="4434045419905280838">Ventás emerxentes e redireccións</translation>
<translation id="445467742685312942">Permitir que os sitios reproduzan contido protexido</translation>
<translation id="4468959413250150279">Silencia o son dun sitio específico.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Xestionado por teus pais</translation>
<translation id="4670064810192446073">Realidade virtual</translation>
<translation id="4708011789095599544">Seguro que queres borrar as cookies e outros datos deste sitio web?</translation>
+<translation id="473775607612524610">Actualizar</translation>
<translation id="4751476147751820511">Sensores de movemento ou de luz</translation>
<translation id="4836046166855586901">Pregúntache sempre que un sitio quere saber se estás utilizando este dispositivo de maneira activa</translation>
<translation id="4883854917563148705">Non se pode restablecer a configuración xestionada</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Compartir a través de</translation>
<translation id="5039804452771397117">Permitir</translation>
<translation id="5048398596102334565">Permite aos sitios acceder aos teus sensores de movemento (recomendado)</translation>
+<translation id="5050380848339752099">Neste sitio estase a piques de compartir información cunha aplicación fóra do modo de incógnito.</translation>
<translation id="5063480226653192405">Uso</translation>
<translation id="5100237604440890931">Vista contraída (fai clic para ampliala).</translation>
<translation id="5123685120097942451">Pestana do modo de incógnito</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Permite que os sitios executen JavaScript (recomendado)</translation>
<translation id="534295439873310000">Dispositivos con NFC</translation>
<translation id="5354152178998424783">Ao realizar esta acción, borraranse os datos e as cookies (<ph name="DATASIZE" />) que almacenasen os sitios.</translation>
-<translation id="5384883051496921101">Neste sitio estase a piques de compartir información cunha aplicación fóra do modo de incógnito.</translation>
+<translation id="536508626067510330">Queres actualizar a icona que aparece na pantalla de inicio?</translation>
<translation id="5391532827096253100">A túa conexión a este sitio non é segura. Información do sitio</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(e 1 máis)}other{(e # máis)}}</translation>
<translation id="5403592356182871684">Nomes</translation>
<translation id="5489227211564503167">Tempo transcorrido: <ph name="ELAPSED_TIME" /> de <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Bloquear anuncios en sitios que mostran anuncios enganosos ou intrusivos</translation>
+<translation id="549957179819296104">Icona nova</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> (permitido), <ph name="PERMISSION_2" /> (bloqueado)</translation>
<translation id="5505264765875738116">Os sitios non poden pedir permiso para enviar notificacións</translation>
<translation id="5516455585884385570">Abrir a configuración de notificacións</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Permisos</translation>
<translation id="5860033963881614850">Non</translation>
<translation id="5876056640971328065">Pór en pausa o vídeo</translation>
+<translation id="5904826301761575486">Queres actualizar o nome e a icona que aparecen na pantalla de inicio?</translation>
<translation id="5916664084637901428">Si</translation>
<translation id="5922853908706496913">Compartindo pantalla</translation>
<translation id="5939518447894949180">Restablecer</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Bloquear cookies de terceiros</translation>
<translation id="6206551242102657620">A conexión é segura. Información do sitio</translation>
<translation id="6216432067784365534">Opcións de <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Pechar e denunciar uso inadecuado</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> e <ph name="PERMISSION_2" /> (bloqueados)</translation>
<translation id="6270391203985052864">Os sitios poden pedir permiso para enviar notificacións</translation>
<translation id="6295158916970320988">Todos os sitios</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Para permitir que <ph name="APP_NAME" /> acceda á túa localización, actívaa tamén en <ph name="BEGIN_LINK" />Configuración de Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Revoga o permiso do dispositivo</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie en uso}other{# cookies en uso}}</translation>
-<translation id="8463851957836045671">O sitio é rápido</translation>
<translation id="8487700953926739672">Dispoñible sen conexión</translation>
<translation id="851751545965956758">Non permitir que os sitios se conecten aos dispositivos</translation>
<translation id="8525306231823319788">Pantalla completa</translation>
<translation id="857943718398505171">Permitido (recomendado)</translation>
<translation id="8609465669617005112">Mover cara arriba</translation>
+<translation id="861748745608658996">Queres actualizar o nome que aparece na pantalla de inicio?</translation>
<translation id="8676374126336081632">Borrar texto</translation>
<translation id="868929229000858085">Busca nos teus contactos</translation>
<translation id="8702612070107455751">Borraranse todos os datos sen conexión.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Achegar</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">A NFC está desactivada para este dispositivo. Actívaa en <ph name="BEGIN_LINK" />Configuración de Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Este sitio ábrese e responde rápido para a maioría dos usuarios</translation>
<translation id="8941729603749328384">www.exemplo.com</translation>
-<translation id="894871326938397531">Saír do modo de incógnito?</translation>
<translation id="8958424370300090006">Bloquea cookies para un sitio específico.</translation>
<translation id="8959122750345127698">A navegación é inaccesible: <ph name="URL" /></translation>
<translation id="8986362086234534611">Borrar</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_gu.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_gu.xtb
index d65ce9308ea..cae17405604 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_gu.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_gu.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="gu">
<translation id="1006017844123154345">ઑનલાઇન ખોલો</translation>
<translation id="1044891598689252897">સાઇટ સામાનà«àª¯ રીતે કારà«àª¯ કરશે</translation>
+<translation id="1100504063505580045">હાલનà«àª‚ આઇકન</translation>
<translation id="1124090076051167250">આમ કરવાથી તમારી હોમ સà«àª•à«àª°à«€àª¨ પર સાઇટ કે àªàªª દà«àªµàª¾àª°àª¾ સà«àªŸà«‹àª° કરવામાં આવેલો ડેટા અને કૂકીના <ph name="DATASIZE" /> સાફ કરવામાં આવશે.</translation>
<translation id="1124772482545689468">વપરાશકરà«àª¤àª¾</translation>
<translation id="1178581264944972037">થોભો</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">માઇકà«àª°à«‹àª«à«‹àª¨</translation>
<translation id="3277252321222022663">સાઇટને સેનà«àª¸àª°àª¨àª¾ àªàª•à«àª¸à«‡àª¸àª¨à«€ મંજૂરી આપો (સà«àªàª¾àªµ આપેલ)</translation>
<translation id="3295602654194328831">માહિતી છà«àªªàª¾àªµà«‹</translation>
+<translation id="3317660236277031814">તમે ઇનà«àª¸à«àªŸà«‰àª² કરેલી વેબ àªàªªàª¨à«àª‚ આઇકન બદલાઈ ગયà«àª‚ છે.</translation>
<translation id="3328801116991980348">સાઇટ માહિતી</translation>
<translation id="3333961966071413176">બધા સંપરà«àª•à«‹</translation>
<translation id="3386292677130313581">સાઇટà«àª¸àª¨à«‡ તમારા સà«àª¥àª¾àª¨àª¨à«‡ જાણવાની મંજૂરી આપતાં પહેલાં પૂછો (ભલામણ કરેલ)</translation>
+<translation id="345699454248713913">તમે ઇનà«àª¸à«àªŸà«‰àª² કરેલી વેબ àªàªªàª¨à«àª‚ નામ બદલાઈ ગયà«àª‚ છે.</translation>
<translation id="3538390592868664640">કોઈ સાઇટને તમારી આજà«àª¬àª¾àªœà«àª¨à«‹ 3D નકશો બનાવવા અથવા કૅમેરાની સà«àª¥àª¿àª¤àª¿àª¨à«‡ ટà«àª°à«…ક કરી શકવા માટે બà«àª²à«‰àª• કરો</translation>
+<translation id="3551268116566418498">છૂપો મોડ છોડી�</translation>
<translation id="3586500876634962664">કૅમેરા અને માઇકà«àª°à«‹àª«à«‹àª¨àª¨à«‹ ઉપયોગ</translation>
<translation id="358794129225322306">àªàª•àª¥à«€ વધૠફાઇલો ઑટોમૅટિક રીતે ડાઉનલોડ કરવાની મંજૂરી સાઇટને આપો.</translation>
<translation id="3594780231884063836">વીડિયોને મà«àª¯à«‚ટ કરો</translation>
@@ -110,16 +114,16 @@
<translation id="4002066346123236978">શીરà«àª·àª•</translation>
<translation id="4008040567710660924">કોઈ ચોકà«àª•àª¸ સાઇટ માટે કà«àª•à«€àª¨à«‡ મંજૂરી આપો.</translation>
<translation id="4046123991198612571">આગલો ટà«àª°à«…ક</translation>
-<translation id="4165986682804962316">સાઇટ સેટિંગà«àª¸</translation>
+<translation id="4165986682804962316">સાઇટ સેટિંગ</translation>
<translation id="4200726100658658164">સà«àª¥àª¾àª¨ સેટિંગ ખોલો</translation>
<translation id="4226663524361240545">સૂચનાઓ ઉપકરણને વાઇબà«àª°à«‡àªŸ કરી શકે છે</translation>
<translation id="4259722352634471385">નેવિગેશન અવરોધિત છે: <ph name="URL" /></translation>
+<translation id="4277239631747669329">તમે ઇનà«àª¸à«àªŸà«‰àª² કરેલી વેબ àªàªªàª¨à«àª‚ નામ અને આઇકન બદલાઈ ગયાં છે.</translation>
<translation id="4278390842282768270">મંજૂર</translation>
<translation id="429312253194641664">સાઇટ મીડિયા ચલાવી રહી છે</translation>
<translation id="42981349822642051">વિસà«àª¤à«ƒàª¤ કરો</translation>
<translation id="4336434711095810371">બધો ડેટા સાફ કરો</translation>
<translation id="4402755511846832236">તમે સકà«àª°àª¿àª¯ રૂપે આ ડિવાઇસનો ઉપયોગ કà«àª¯àª¾àª°à«‡ કરો છો, તેની જાણ ન થાય ઠમાટે સાઇટ બà«àª²à«‰àª• કરો</translation>
-<translation id="4433925000917964731">Google દà«àªµàª¾àª°àª¾ પૂરà«àª‚ પાડવામાં આવેલà«àª‚ લાઇટ વરà«àªàª¨àª¨à«àª‚ પેજ</translation>
<translation id="4434045419905280838">પૉપ-અપ અને રીડાયરેકà«àªŸ</translation>
<translation id="445467742685312942">સાઇટને સંરકà«àª·àª¿àª¤ કનà«àªŸà«‡àª¨à«àªŸ ચલાવવાની મંજૂરી આપો</translation>
<translation id="4468959413250150279">કોઈ àªàª• ચોકà«àª•àª¸ સાઇટ માટે અવાજ બંધ કરો.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">તમારા માતાપિતા દà«àªµàª¾àª°àª¾ મેનેજ થયેલ</translation>
<translation id="4670064810192446073">વરà«àªšà«àª¯à«àª…લ રિયાલિટી</translation>
<translation id="4708011789095599544">શà«àª‚ તમે ખરેખર આ વેબસાઇટ માટેની કà«àª•à«€ અને અનà«àª¯ સાઇટ ડેટા સાફ કરવા માગો છો?</translation>
+<translation id="473775607612524610">અપડેટ કરો</translation>
<translation id="4751476147751820511">મોશન અથવા લાઇટ સેનà«àª¸àª°</translation>
<translation id="4836046166855586901">તમે સકà«àª°àª¿àª¯ રૂપે આ ડિવાઇસનો ઉપયોગ કà«àª¯àª¾àª°à«‡ કરો છો તેના વિશે જà«àª¯àª¾àª°à«‡ કોઈ સાઇટ જાણવા માગે, તà«àª¯àª¾àª°à«‡ પૂછો</translation>
<translation id="4883854917563148705">મેનેજ કરવામાં આવેલા સેટિંગને રીસેટ કરી શકાતા નથી</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">આનાથી શેર કરો</translation>
<translation id="5039804452771397117">મંજૂરી આપો</translation>
<translation id="5048398596102334565">સાઇટને મોશન સેનà«àª¸àª°àª¨àª¾ àªàª•à«àª¸à«‡àª¸àª¨à«€ મંજૂરી આપો (સà«àªàª¾àªµ આપેલ)</translation>
+<translation id="5050380848339752099">આ સાઇટ છૂપા મોડની બહારની àªàª• àªàªª સાથે માહિતી શેર કરવા જઈ રહી છે.</translation>
<translation id="5063480226653192405">ઉપયોગ</translation>
<translation id="5100237604440890931">સંકà«àªšàª¿àª¤ - વિસà«àª¤à«ƒàª¤ કરવા માટે કà«àª²àª¿àª• કરો.</translation>
<translation id="5123685120097942451">છૂપા મોડમાંની ટૅબ</translation>
@@ -153,17 +159,18 @@
<translation id="5335288049665977812">સાઇટà«àª¸àª¨à«‡ JavaScript ચલાવાની મંજૂરી આપો (ભલામણ કરેલ)</translation>
<translation id="534295439873310000">NFC ડિવાઇસ</translation>
<translation id="5354152178998424783">આમ કરવાથી સાઇટ દà«àªµàª¾àª°àª¾ સà«àªŸà«‹àª° કરવામાં આવેલા <ph name="DATASIZE" /> જેટલો ડેટા અને કà«àª•à«€ સાફ થશે.</translation>
-<translation id="5384883051496921101">આ સાઇટ છà«àªªàª¾ મોડની બહારની àªàª• àªàªªà«àª²àª¿àª•à«‡àª¶àª¨ વડે માહિતી શેર કરવા જઈ રહી છે.</translation>
+<translation id="536508626067510330">તમારી હોમસà«àª•à«àª°à«€àª¨ પરના આઇકનને અપડેટ કરીàª?</translation>
<translation id="5391532827096253100">આ સાઇટ સાથેનà«àª‚ તમારà«àª‚ કનેકà«àª¶àª¨ સà«àª°àª•à«àª·àª¿àª¤ નથી. સાઇટની માહિતી</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ વધૠ1)}one{(+ વધૠ#)}other{(+ વધૠ#)}}</translation>
<translation id="5403592356182871684">નામ</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" />માંથી <ph name="ELAPSED_TIME" />નો સમય વીતી ગયો.</translation>
<translation id="5494752089476963479">ઘૃણાસà«àªªàª¦ અથવા ભà«àª°àª¾àª®àª• જાહેરાતો બતાવતી સાઇટ પરથી જાહેરાતો બà«àª²à«‰àª• કરો</translation>
+<translation id="549957179819296104">નવà«àª‚ આઇકન</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" />ને મંજૂરી આપી, <ph name="PERMISSION_2" />ને બà«àª²à«‰àª• કરà«àª¯à«‹</translation>
<translation id="5505264765875738116">સાઇટ તમને નોટિફિકેશન મોકલવા માટે પૂછી શકશે નહીં</translation>
<translation id="5516455585884385570">નોટિફિકેશનના સેટિંગ ખોલો</translation>
<translation id="5527111080432883924">સાઇટને કà«àª²àª¿àªªàª¬à«‹àª°à«àª¡ પરની ટેકà«àª¸à«àªŸ અને છબીઓને વાંચવાની મંજૂરી આપતાં પહેલાં પૂછો (સà«àªàª¾àªµ આપેલ)</translation>
-<translation id="5556459405103347317">ફરિથી લોડ કરો</translation>
+<translation id="5556459405103347317">ફરીથી લોડ કરો</translation>
<translation id="5596627076506792578">વધૠવિકલà«àªªà«‹</translation>
<translation id="5649053991847567735">ઑટોમૅટિક રીતે ડાઉનલોડ</translation>
<translation id="5677928146339483299">બà«àª²à«‰àª• કરેલ</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">પરવાનગીઓ</translation>
<translation id="5860033963881614850">બંધ</translation>
<translation id="5876056640971328065">વીડિયો થોભાવો</translation>
+<translation id="5904826301761575486">તમારી હોમસà«àª•à«àª°à«€àª¨ પરનà«àª‚ નામ અને આઇકન અપડેટ કરીàª?</translation>
<translation id="5916664084637901428">ચાલà«</translation>
<translation id="5922853908706496913">તમારી સà«àª•à«àª°à«€àª¨ શેર કરીઠછીàª</translation>
<translation id="5939518447894949180">રીસેટ કરો</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">તà«àª°à«€àªœàª¾ પકà«àª·àª¨à«€ કà«àª•à«€àª¨à«‡ બà«àª²à«‰àª• કરો</translation>
<translation id="6206551242102657620">કનેકà«àª¶àª¨ સà«àª°àª•à«àª·àª¿àª¤ છે. સાઇટની માહિતી</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" />ના વિકલà«àªªà«‹</translation>
+<translation id="6260852843601447737">બંધ કરો અને દà«àª°à«àªªàª¯à«‹àª—ની જાણ કરો</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> અને <ph name="PERMISSION_2" />ને બà«àª²à«‰àª• કરà«àª¯àª¾</translation>
<translation id="6270391203985052864">સાઇટ તમને નોટિફિકેશન મોકલવા માટે પૂછી શકે છે</translation>
<translation id="6295158916970320988">બધી સાઇટà«àª¸</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> તમારà«àª‚ સà«àª¥àª¾àª¨ àªàª•à«àª¸à«‡àª¸ કરી શકે તે માટે, <ph name="BEGIN_LINK" />Android સેટિંગ<ph name="END_LINK" />માં પણ સà«àª¥àª¾àª¨ ચાલૠકરો.</translation>
<translation id="8447861592752582886">ઉપકરણની પરવાનગી રદબાતલ કરો</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{વપરાશમાંની 1 કà«àª•à«€}one{વપરાશમાંની # કà«àª•à«€}other{વપરાશમાંની # કà«àª•à«€}}</translation>
-<translation id="8463851957836045671">સાઇટ àªàª¡àªªà«€ છે</translation>
<translation id="8487700953926739672">ઑફલાઇન ઉપલબà«àª§</translation>
<translation id="851751545965956758">સાઇટને ઉપકરણો સાથે કનેકà«àªŸ થવાથી બà«àª²à«‰àª• કરો</translation>
<translation id="8525306231823319788">પૂરà«àª£ સà«àª•à«àª°à«€àª¨</translation>
<translation id="857943718398505171">મંજૂર (ભલામણ કરેલ)</translation>
<translation id="8609465669617005112">ઉપર ખસેડો</translation>
+<translation id="861748745608658996">તમારી હોમસà«àª•à«àª°à«€àª¨ પરનà«àª‚ નામ અપડેટ કરીàª?</translation>
<translation id="8676374126336081632">ઇનપà«àªŸ સાફ કરો</translation>
<translation id="868929229000858085">તમારા સંપરà«àª•à«‹ શોધો</translation>
<translation id="8702612070107455751">બધો ઑફલાઇન ડેટા સાફ કરવામાં આવશે.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">àªà«‚મ વધારો</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">આ ડિવાઇસ માટે NFC સેવા બંધ કરેલી છે. તેને <ph name="BEGIN_LINK" />Android સેટિંગ<ph name="END_LINK" />માં ચાલૠકરો.</translation>
-<translation id="8929372349074745002">આ સાઇટ મોટાભાગના લોકો માટે àªàª¡àªªàª¥à«€ ખૂલે છે અને પà«àª°àª¤àª¿àª¸àª¾àª¦ આપે છે</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">છà«àªªà«‹ મોડ છોડીàª?</translation>
<translation id="8958424370300090006">કોઈ ચોકà«àª•àª¸ સાઇટ માટે કà«àª•à«€àª¨à«‡ બà«àª²à«‰àª• કરો.</translation>
<translation id="8959122750345127698">નેવિગેશન બિનપહોંચ યોગà«àª¯ છે: <ph name="URL" /></translation>
<translation id="8986362086234534611">ભૂલી ગયા</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hi.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hi.xtb
index 964c35c0ca1..cad25342d5d 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hi.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hi.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="hi">
<translation id="1006017844123154345">ऑनलाइन खोलें</translation>
<translation id="1044891598689252897">साइटें सामानà¥à¤¯ रूप से काम करेंगी</translation>
+<translation id="1100504063505580045">मौजूदा आइकॉन</translation>
<translation id="1124090076051167250">इससे वे <ph name="DATASIZE" /> डेटा और कà¥à¤•à¥€ मिट जाà¤à¤‚गे जिनà¥à¤¹à¥‡à¤‚ साइटों या à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ ने आपकी होम सà¥à¤•à¥à¤°à¥€à¤¨ पर सेव किया है.</translation>
<translation id="1124772482545689468">उपयोगकरà¥à¤¤à¤¾</translation>
<translation id="1178581264944972037">रोकें</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">माइकà¥à¤°à¥‹à¤«à¤¼à¥‹à¤¨</translation>
<translation id="3277252321222022663">साइटों को सेंसर à¤à¤•à¥à¤¸à¥‡à¤¸ करने दें (सà¥à¤à¤¾à¤¯à¤¾ गया)</translation>
<translation id="3295602654194328831">जानकारी छिपाà¤à¤‚</translation>
+<translation id="3317660236277031814">आपने जो वेब à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ इंसà¥à¤Ÿà¥‰à¤² किया है उसने अपना आइकॉन बदल दिया है.</translation>
<translation id="3328801116991980348">साइट जानकारी</translation>
<translation id="3333961966071413176">सभी संपरà¥à¤•</translation>
<translation id="3386292677130313581">साइटों को अपनी जगह की जानकारी देने से पहले अनà¥à¤®à¤¤à¤¿ लेना ज़रूरी बनाà¤à¤‚ (सà¥à¤à¤¾à¤¯à¤¾ गया)</translation>
+<translation id="345699454248713913">आपने जो वेब à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ इंसà¥à¤Ÿà¥‰à¤² किया है उसने अपना नाम बदला है.</translation>
<translation id="3538390592868664640">साइटों को अपने आस-पास की जगह का 3D मैप बनाने या कैमरे की सà¥à¤¥à¤¿à¤¤à¤¿ टà¥à¤°à¥ˆà¤• करने से रोकें</translation>
+<translation id="3551268116566418498">गà¥à¤ªà¥à¤¤ मोड से बाहर निकलना है?</translation>
<translation id="3586500876634962664">कैमरा और माइकà¥à¤°à¥‹à¤«à¤¼à¥‹à¤¨ का इसà¥à¤¤à¥‡à¤®à¤¾à¤²</translation>
<translation id="358794129225322306">किसी साइट को अपने आप à¤à¤• से ज़à¥à¤¯à¤¾à¤¦à¤¾ फ़ाइलें लोड करने की मंज़ूरी दें.</translation>
<translation id="3594780231884063836">वीडियो मà¥à¤¯à¥‚ट करें</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">जगह की सेटिंग खोलें</translation>
<translation id="4226663524361240545">नोटिफ़िकेशन से डिवाइस में कंपन हो सकता है</translation>
<translation id="4259722352634471385">मारà¥à¤—दरà¥à¤¶à¤• अवरोधित है: <ph name="URL" /></translation>
+<translation id="4277239631747669329">आपने जो वेब à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ इंसà¥à¤Ÿà¥‰à¤² किया है उसने अपना नाम और आइकॉन बदल दिया है.</translation>
<translation id="4278390842282768270">अनà¥à¤®à¤¤à¤¿ है</translation>
<translation id="429312253194641664">किसी साइट पर मीडिया चल रहा है</translation>
<translation id="42981349822642051">विसà¥à¤¤à¥ƒà¤¤ करें</translation>
<translation id="4336434711095810371">सारा डेटा मिटाà¤à¤‚</translation>
<translation id="4402755511846832236">साइटों को यह जानने से रोकें कि आप इस डिवाइस का इसà¥à¤¤à¥‡à¤®à¤¾à¤² कब करते हैं</translation>
-<translation id="4433925000917964731">लाइट पेज Google ने मà¥à¤¹à¥ˆà¤¯à¤¾ कराया है</translation>
<translation id="4434045419905280838">पॉप-अप और रीडायरेकà¥à¤Ÿ</translation>
<translation id="445467742685312942">साइटों को सभी सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ सामगà¥à¤°à¥€ चलाने दें</translation>
<translation id="4468959413250150279">किसी खास साइट के लिठआवाज़ बंद करें.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">आपके अभिभावक दà¥à¤µà¤¾à¤°à¤¾ पà¥à¤°à¤¬à¤‚धित</translation>
<translation id="4670064810192446073">वरà¥à¤šà¥à¤…ल रिà¤à¤²à¤¿à¤Ÿà¥€</translation>
<translation id="4708011789095599544">कà¥à¤¯à¤¾ आप वाकई इस वेबसाइट के लिà¤, कà¥à¤•à¥€ और साइट का अनà¥à¤¯ डेटा मिटाना चाहते हैं?</translation>
+<translation id="473775607612524610">अपडेट करें</translation>
<translation id="4751476147751820511">गति या लाइट सेंसर</translation>
<translation id="4836046166855586901">साइटों को यह पूछने दें कि आप इस डिवाइस का इसà¥à¤¤à¥‡à¤®à¤¾à¤² कब करते हैं</translation>
<translation id="4883854917563148705">पà¥à¤°à¤¬à¤‚धित सेटिंग रीसेट नहीं की जा सकती हैं</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">इससे शेयर करें</translation>
<translation id="5039804452771397117">अनà¥à¤®à¤¤à¤¿ दें</translation>
<translation id="5048398596102334565">साइटों को मोशन सेंसर à¤à¤•à¥â€à¤¸à¥‡à¤¸ करने दें (सà¥à¤à¤¾à¤¯à¤¾ गया)</translation>
+<translation id="5050380848339752099">यह साइट गà¥à¤ªà¥à¤¤ मोड से बाहर के किसी à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ के साथ जानकारी शेयर करने वाली है.</translation>
<translation id="5063480226653192405">उपयोग</translation>
<translation id="5100237604440890931">छोटा किया गया - पूरा खोलने के लिठकà¥à¤²à¤¿à¤• करें.</translation>
<translation id="5123685120097942451">गà¥à¤ªà¥à¤¤ टैब</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">साइटों को JavaScript चलाने की अनà¥à¤®à¤¤à¤¿ दें (हम इस सेटिंग को चालू रखने का सà¥à¤à¤¾à¤µ देते हैं)</translation>
<translation id="534295439873310000">NFC डिवाइस</translation>
<translation id="5354152178998424783">इससे वे <ph name="DATASIZE" /> डेटा और कà¥à¤•à¥€ मिट जाà¤à¤‚गे जिनà¥à¤¹à¥‡à¤‚ साइटों ने सेव किया है.</translation>
-<translation id="5384883051496921101">यह साइट गà¥à¤ªà¥à¤¤ मोड से बाहर के à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ के साथ जानकारी शेयर करने वाली है.</translation>
+<translation id="536508626067510330">कà¥à¤¯à¤¾ आप अपनी होमसà¥à¤•à¥à¤°à¥€à¤¨ पर आइकॉन अपडेट करना चाहते हैं?</translation>
<translation id="5391532827096253100">इस साइट से आपका कनेकà¥à¤¶à¤¨ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नहीं है. साइट की जानकारी</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 और)}one{(+ # और)}other{(+ # और)}}</translation>
<translation id="5403592356182871684">नाम</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" /> में से <ph name="ELAPSED_TIME" /> का समय बीत चà¥à¤•à¤¾ है.</translation>
<translation id="5494752089476963479">तंग करने वाले या गà¥à¤®à¤°à¤¾à¤¹ करने वाले विजà¥à¤žà¤¾à¤ªà¤¨ दिखाने वाली साइटों पर विजà¥à¤žà¤¾à¤ªà¤¨ बà¥à¤²à¥‰à¤• करें</translation>
+<translation id="549957179819296104">नया आइकॉन</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> इसà¥à¤¤à¥‡à¤®à¤¾à¤² करने की अनà¥à¤®à¤¤à¤¿ दी गई और <ph name="PERMISSION_2" /> को बà¥à¤²à¥‰à¤• किया गया</translation>
<translation id="5505264765875738116">साइटें आपको सूचनाà¤à¤‚ भेजने के लिठनहीं पूछ सकती हैं</translation>
<translation id="5516455585884385570">सूचना सेटिंग खोलें</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">अनà¥à¤®à¤¤à¤¿à¤¯à¤¾à¤‚</translation>
<translation id="5860033963881614850">बंद</translation>
<translation id="5876056640971328065">वीडियो रोकें</translation>
+<translation id="5904826301761575486">कà¥à¤¯à¤¾ आप अपनी होमसà¥à¤•à¥à¤°à¥€à¤¨ पर नाम और आइकॉन अपडेट करना चाहते हैं?</translation>
<translation id="5916664084637901428">चालू है</translation>
<translation id="5922853908706496913">आपकी सà¥à¤•à¥à¤°à¥€à¤¨ शेयर की जा रही है</translation>
<translation id="5939518447894949180">रीसेट करें</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">तीसरे पकà¥à¤· की कà¥à¤•à¥€ बà¥à¤²à¥‰à¤• करें</translation>
<translation id="6206551242102657620">कनेकà¥à¤¶à¤¨ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ है. साइट की जानकारी</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> विकलà¥à¤ª</translation>
+<translation id="6260852843601447737">बंद करके शिकायत करें</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> और <ph name="PERMISSION_2" /> को बà¥à¤²à¥‰à¤• किया गया</translation>
<translation id="6270391203985052864">साइटें आपको सूचनाà¤à¤‚ भेजने के लिठपूछ सकती हैं</translation>
<translation id="6295158916970320988">सभी साइटें</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> को अपनी जगह की जानकारी का à¤à¤•à¥à¤¸à¥‡à¤¸ देने के लिà¤, <ph name="BEGIN_LINK" />Android की सेटिंग<ph name="END_LINK" /> में भी जाकर भी, जगह की जानकारी चालू करें.</translation>
<translation id="8447861592752582886">डिवाइस अनà¥à¤®à¤¤à¤¿ निरसà¥à¤¤ करें</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 कà¥à¤•à¥€ इसà¥à¤¤à¥‡à¤®à¤¾à¤² की जा रही है}one{# कà¥à¤•à¥€ इसà¥à¤¤à¥‡à¤®à¤¾à¤² की जा रही है}other{# कà¥à¤•à¥€ इसà¥à¤¤à¥‡à¤®à¤¾à¤² की जा रही हैं}}</translation>
-<translation id="8463851957836045671">साइट तेज़ी से लोड होती है</translation>
<translation id="8487700953926739672">ऑफ़लाइन उपलबà¥à¤§ है</translation>
<translation id="851751545965956758">साइटों को डिवाइस से कनेकà¥à¤Ÿ होने से रोकें</translation>
<translation id="8525306231823319788">फ़à¥à¤² सà¥â€à¤•à¥à¤°à¥€à¤¨</translation>
<translation id="857943718398505171">अनà¥à¤®à¤¤à¤¿ दी गई (सà¥à¤à¤¾à¤¯à¤¾ गया)</translation>
<translation id="8609465669617005112">ऊपर जाà¤à¤‚</translation>
+<translation id="861748745608658996">कà¥à¤¯à¤¾ आप अपनी होमसà¥à¤•à¥à¤°à¥€à¤¨ पर नाम अपडेट करना चाहते हैं?</translation>
<translation id="8676374126336081632">इनपà¥à¤Ÿ साफ़ करें</translation>
<translation id="868929229000858085">अपने संपरà¥à¤• खोजें</translation>
<translation id="8702612070107455751">ऑफ़लाइन डेटा को मिटा दिया जाà¤à¤—ा.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">ज़ूम इन करें</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">इस डिवाइस पर NFC बंद है. <ph name="BEGIN_LINK" />Android सेटिंग<ph name="END_LINK" /> में इसे चालू करें.</translation>
-<translation id="8929372349074745002">ज़à¥à¤¯à¤¾à¤¦à¤¾à¤¤à¤° लोगों के लिठयह साइट तेज़ी से खà¥à¤²à¤¤à¥€ है और जवाब देती है</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">गà¥à¤ªà¥à¤¤ मोड छोड़ें?</translation>
<translation id="8958424370300090006">किसी खास साइट के लिठकà¥à¤•à¥€ बà¥à¤²à¥‰à¤• करें.</translation>
<translation id="8959122750345127698">मारà¥à¤—दरà¥à¤¶à¤• तक नहीं पहà¥à¤‚चा जा सकता: <ph name="URL" /></translation>
<translation id="8986362086234534611">भूल जाà¤à¤‚</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb
index 34416c692c4..54c564bc05a 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hr.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="hr">
<translation id="1006017844123154345">Otvori online</translation>
<translation id="1044891598689252897">Web-lokacije će normalno raditi</translation>
+<translation id="1100504063505580045">TrenutaÄna ikona</translation>
<translation id="1124090076051167250">Izbrisat će se <ph name="DATASIZE" /> podataka i kolaÄića koje su spremile web-lokacije ili aplikacije na vaÅ¡em poÄetnom zaslonu.</translation>
<translation id="1124772482545689468">Korisnik</translation>
<translation id="1178581264944972037">Pauziraj</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">DopuÅ¡tanje pristupa senzorima za web-lokacije (preporuÄeno)</translation>
<translation id="3295602654194328831">Sakrij informacije</translation>
+<translation id="3317660236277031814">Promijenjena je ikona web-aplikacije koju ste instalirali.</translation>
<translation id="3328801116991980348">Informacije o web-lokaciji</translation>
<translation id="3333961966071413176">Svi kontakti</translation>
<translation id="3386292677130313581">Web-lokacije moraju tražiti dopuÅ¡tenje za pristup lokaciji (preporuÄeno)</translation>
+<translation id="345699454248713913">Promijenjen je naziv web-aplikacije koju ste instalirali.</translation>
<translation id="3538390592868664640">Blokirajte web-lokacije da izrađuju 3D kartu vašeg okruženja ili prate položaj kamere</translation>
+<translation id="3551268116566418498">Napustiti anonimni naÄin?</translation>
<translation id="3586500876634962664">Upotreba kamere i mikrofona</translation>
<translation id="358794129225322306">Dopusti web-lokaciji automatsko preuzimanje više datoteka.</translation>
<translation id="3594780231884063836">IskljuÄi kameru</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Otvori postavke lokacije</translation>
<translation id="4226663524361240545">Obavijesti mogu ukljuÄiti vibriranje ureÄ‘aja</translation>
<translation id="4259722352634471385">Otvaranje je blokirano: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Promijenjeni su naziv i ikona web-aplikacije koju ste instalirali.</translation>
<translation id="4278390842282768270">Dopušteno</translation>
<translation id="429312253194641664">Web-lokacija reproducira medije</translation>
<translation id="42981349822642051">Proširi</translation>
<translation id="4336434711095810371">Izbriši sve podatke</translation>
<translation id="4402755511846832236">Onemogućivanje web-lokacijama da znaju kad aktivno upotrebljavate ovaj uređaj</translation>
-<translation id="4433925000917964731">Jednostavna stranica koju pruža Google</translation>
<translation id="4434045419905280838">SkoÄni prozori i preusmjeravanja</translation>
<translation id="445467742685312942">Web-lokacijama je dopuštena reprodukcija zaštićenog sadržaja</translation>
<translation id="4468959413250150279">IskljuÄivanje zvuka za odreÄ‘enu web-lokaciju.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Upravlja tvoj roditelj</translation>
<translation id="4670064810192446073">Virtualna stvarnost</translation>
<translation id="4708011789095599544">Jeste li sigurni da želite izbrisati kolaÄiće i druge podatke za ovu web-lokaciju?</translation>
+<translation id="473775607612524610">Ažuriraj</translation>
<translation id="4751476147751820511">Senzori pokreta ili osvjetljenja</translation>
<translation id="4836046166855586901">Prikaži upit kad web-lokacija želi znati kad aktivno upotrebljavam ovaj uređaj</translation>
<translation id="4883854917563148705">Upravljane postavke ne mogu se vratiti na zadano</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Dijeli putem</translation>
<translation id="5039804452771397117">Dopusti</translation>
<translation id="5048398596102334565">DopuÅ¡tanje pristupa senzorima kretanja za web-lokacije (preporuÄeno)</translation>
+<translation id="5050380848339752099">Ova će web-lokacija dijeliti podatke s aplikacijom izvan anonimnog naÄina.</translation>
<translation id="5063480226653192405">Upotreba</translation>
<translation id="5100237604440890931">Sažeto – kliknite za proširivanje.</translation>
<translation id="5123685120097942451">Anonimna kartica</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Web-lokacije mogu pokretati JavaScript (preporuÄeno)</translation>
<translation id="534295439873310000">NFC uređaji</translation>
<translation id="5354152178998424783">Izbrisat će se <ph name="DATASIZE" /> podataka i kolaÄića koje su spremile web-lokacije.</translation>
-<translation id="5384883051496921101">Ova će web-lokacija dijeliti podatke s aplikacijom izvan anonimnog naÄina.</translation>
+<translation id="536508626067510330">Želite li ažurirati ikonu na poÄetnom zaslonu?</translation>
<translation id="5391532827096253100">Veza s web-lokacijom nije sigurna. Informacije o web-lokaciji</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ još 1)}one{(+ još #)}few{(+ još #)}other{(+ još #)}}</translation>
<translation id="5403592356182871684">Nazivi</translation>
<translation id="5489227211564503167">Proteklo vrijeme: <ph name="ELAPSED_TIME" /> od <ph name="TOTAL_TIME" /></translation>
<translation id="5494752089476963479">Blokiraj oglase na web-lokacijama koje prikazuju ometajuće ili obmanjujuće oglase</translation>
+<translation id="549957179819296104">Nova ikona</translation>
<translation id="5502860503640766021">Odobreno je dopuštenje <ph name="PERMISSION_1" />, a blokirano <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Web-lokacije ne mogu postavljati pitanja o slanju obavijesti</translation>
<translation id="5516455585884385570">Otvori postavke obavijesti</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Dozvoljeno</translation>
<translation id="5860033963881614850">IskljuÄeno</translation>
<translation id="5876056640971328065">Pauziraj videozapis</translation>
+<translation id="5904826301761575486">Želite li ažurirati naziv i ikonu na poÄetnom zaslonu?</translation>
<translation id="5916664084637901428">UkljuÄi</translation>
<translation id="5922853908706496913">Dijeljenje zaslona</translation>
<translation id="5939518447894949180">Ponovno postavi</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokiraj kolaÄiće trećih strana</translation>
<translation id="6206551242102657620">Veza je sigurna. Informacije o web-lokaciji</translation>
<translation id="6216432067784365534">Opcije stavke <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Zatvori i prijavi zloupotrebu</translation>
<translation id="6262279340360821358">Blokirana su dopuštenja <ph name="PERMISSION_1" /> i <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Web-lokacije mogu postavljati pitanja o slanju obavijesti</translation>
<translation id="6295158916970320988">Sve web-lokacije</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Da bi aplikacija <ph name="APP_NAME" /> mogla pristupiti vaÅ¡oj lokaciji, ukljuÄite lokaciju i u <ph name="BEGIN_LINK" />Androidovim postavkama<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Opozovi odobrenje uređaja</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Koristi se jedan kolaÄić}one{Koristi se # kolaÄić}few{Koriste se # kolaÄića}other{Koristi se # kolaÄića}}</translation>
-<translation id="8463851957836045671">Web-lokacija je brza</translation>
<translation id="8487700953926739672">Dostupno izvanmrežno</translation>
<translation id="851751545965956758">Blokiraj povezivanje web-lokacija s uređajima</translation>
<translation id="8525306231823319788">Cijeli zaslon</translation>
<translation id="857943718398505171">DopuÅ¡teno (preporuÄeno)</translation>
<translation id="8609465669617005112">Premjesti gore</translation>
+<translation id="861748745608658996">Želite li ažurirati naziv na poÄetnom zaslonu?</translation>
<translation id="8676374126336081632">Brisanje unosa</translation>
<translation id="868929229000858085">Pretraživanje kontakata</translation>
<translation id="8702612070107455751">Izbrisat će se svi izvanmrežni podaci.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Povećaj</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC je iskljuÄen za ovaj ureÄ‘aj. UkljuÄite ga u <ph name="BEGIN_LINK" />postavkama Androida<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Za većinu ljudi ova se web-lokacija brzo otvara i reagira</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Želite li napustiti anonimno?</translation>
<translation id="8958424370300090006">Blokiraj kolaÄiće za odreÄ‘enu web-lokaciju.</translation>
<translation id="8959122750345127698">Otvaranje je nedostupno: <ph name="URL" /></translation>
<translation id="8986362086234534611">Zaboravi</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hu.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hu.xtb
index 451260dd8ba..bf499894517 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hu.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hu.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="hu">
<translation id="1006017844123154345">Online megnyitás</translation>
<translation id="1044891598689252897">A webhelyek a megszokott módon fognak működni</translation>
+<translation id="1100504063505580045">Jelenlegi ikon</translation>
<translation id="1124090076051167250">Ezzel törli azt a(z) <ph name="DATASIZE" />-nyi adatot és cookie-t, amelyeket a webhelyek és a kezdőképernyőn lévő alkalmazások tárolnak az eszközön.</translation>
<translation id="1124772482545689468">Felhasználó</translation>
<translation id="1178581264944972037">Szünet</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Az érzékelőkhöz való hozzáférés engedélyezése a webhelyek számára (ajánlott)</translation>
<translation id="3295602654194328831">Információk elrejtése…</translation>
+<translation id="3317660236277031814">Egy Ön által telepített internetes alkalmazás ikonja megváltozott.</translation>
<translation id="3328801116991980348">Webhelyadatok</translation>
<translation id="3333961966071413176">Összes névjegy</translation>
<translation id="3386292677130313581">Kérdezzen rá, mielőtt engedélyezné a webhelyek számára a tartózkodási helyhez való hozzáférést (ajánlott)</translation>
+<translation id="345699454248713913">Egy Ön által telepített internetes alkalmazás neve megváltozott.</translation>
<translation id="3538390592868664640">Az Ön környezetéről készített 3D-s térkép létrehozásának, valamint a kamerapozíció követésének letiltása a webhelyek számára</translation>
+<translation id="3551268116566418498">Kilép az inkognitó módból?</translation>
<translation id="3586500876634962664">Kamera- és mikrofonhasználat</translation>
<translation id="358794129225322306">Engedély webhelynek több fájl automatikus letöltésére.</translation>
<translation id="3594780231884063836">Videó némítása</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Helybeállítások megnyitása</translation>
<translation id="4226663524361240545">Az értesítések miatt rezeghet az eszköz</translation>
<translation id="4259722352634471385">Le van tiltva az ide vezető navigáció: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Egy Ön által telepített internetes alkalmazás neve és ikonja megváltozott.</translation>
<translation id="4278390842282768270">Engedélyezve</translation>
<translation id="429312253194641664">Az egyik webhely médiatartalmat játszik le</translation>
<translation id="42981349822642051">Kibontás</translation>
<translation id="4336434711095810371">Az összes adat törlése</translation>
<translation id="4402755511846832236">A webhelyek nem kaphatnak információt arról, hogy Ön mikor használja aktívan ezt az eszközt.</translation>
-<translation id="4433925000917964731">Egyszerű oldal a Google-tól</translation>
<translation id="4434045419905280838">Előugró ablakok és átirányítások</translation>
<translation id="445467742685312942">Védett tartalmak lejátszásának engedélyezése a webhelyek számára</translation>
<translation id="4468959413250150279">Egy adott webhely hangjának némítása.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">A szülő kezeli</translation>
<translation id="4670064810192446073">Virtuális valóság</translation>
<translation id="4708011789095599544">Biztosan törölni szeretné az ehhez a webhelyhez tartozó cookie-kat és egyéb webhelyadatokat?</translation>
+<translation id="473775607612524610">Frissítés</translation>
<translation id="4751476147751820511">Mozgás- és fényérzékelők</translation>
<translation id="4836046166855586901">Kérdezzen rá, ha valamelyik webhely tudni szeretné, hogy Ön mikor használja aktívan ezt az eszközt.</translation>
<translation id="4883854917563148705">A kezelt beállításokat nem lehet visszaállítani</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Megosztás itt:</translation>
<translation id="5039804452771397117">Engedélyezés</translation>
<translation id="5048398596102334565">A mozgásérzékelőkhöz való hozzáférés engedélyezése a webhelyek számára (ajánlott)</translation>
+<translation id="5050380848339752099">A webhely adatokat kíván megosztani az inkognitó módon kívüli alkalmazással.</translation>
<translation id="5063480226653192405">Használat</translation>
<translation id="5100237604440890931">Összecsukva – kattintson a kibontáshoz.</translation>
<translation id="5123685120097942451">Inkognitó lap</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Engedélyezze a webhelyek számára a JavaScript futtatását (ajánlott)</translation>
<translation id="534295439873310000">NFC-eszközök</translation>
<translation id="5354152178998424783">Ezzel <ph name="DATASIZE" />-nyi, webhelyek által tárolt adatot és cookie-t töröl.</translation>
-<translation id="5384883051496921101">A webhely adatokat kíván megosztani az inkognitó módon kívüli alkalmazással.</translation>
+<translation id="536508626067510330">Frissíti az ikont a kezdőképernyőjén?</translation>
<translation id="5391532827096253100">Kapcsolata a webhellyel nem biztonságos. Webhelyadatok</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 további)}other{(+ # további)}}</translation>
<translation id="5403592356182871684">Nevek</translation>
<translation id="5489227211564503167">Eltelt idő: <ph name="ELAPSED_TIME" />, ennyiből: <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Hirdetések letiltása a tolakodó és félrevezető hirdetéseket megjelenítő webhelyeken</translation>
+<translation id="549957179819296104">Új ikon</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> engedélyezve, <ph name="PERMISSION_2" /> letiltva</translation>
<translation id="5505264765875738116">A webhelyek nem kérdezhetnek rá, hogy küldjenek-e Önnek értesítéseket</translation>
<translation id="5516455585884385570">Értesítési beállítások megnyitása</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Engedélyek</translation>
<translation id="5860033963881614850">Kikapcsolva</translation>
<translation id="5876056640971328065">Videó szüneteltetése</translation>
+<translation id="5904826301761575486">Frissíti a nevet és az ikont a kezdőképernyőjén?</translation>
<translation id="5916664084637901428">Be</translation>
<translation id="5922853908706496913">Képernyő megosztása</translation>
<translation id="5939518447894949180">Visszaállítás</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Harmadik féltől származó cookie-k letiltása</translation>
<translation id="6206551242102657620">A kapcsolat biztonságos. Webhelyadatok</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> – lehetőségek</translation>
+<translation id="6260852843601447737">Bezárás és a visszaélés jelentése</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> és <ph name="PERMISSION_2" /> letiltva</translation>
<translation id="6270391203985052864">A webhelyek rákérdezhetnek, hogy küldjenek-e Önnek értesítéseket</translation>
<translation id="6295158916970320988">Az összes webhely</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Ahhoz, hogy a(z) <ph name="APP_NAME" /> hozzáférhessen a helyadatokhoz, a helyadatokat az <ph name="BEGIN_LINK" />Android-beállítások<ph name="END_LINK" /> között is be kell kapcsolni.</translation>
<translation id="8447861592752582886">Eszközengedély visszavonása</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie van használatban}other{# cookie van használatban}}</translation>
-<translation id="8463851957836045671">A webhely gyors</translation>
<translation id="8487700953926739672">Offline elérhető</translation>
<translation id="851751545965956758">Az eszközökhöz való csatlakozás megtiltása a webhelyeknek</translation>
<translation id="8525306231823319788">Teljes képernyő</translation>
<translation id="857943718398505171">Engedélyezve (ajánlott)</translation>
<translation id="8609465669617005112">Mozgatás felfelé</translation>
+<translation id="861748745608658996">Frissíti a kezdőképernyőn megjelenő nevet?</translation>
<translation id="8676374126336081632">Beírt szöveg törlése</translation>
<translation id="868929229000858085">Keresés a névjegyek között</translation>
<translation id="8702612070107455751">Az offline adatok törlődnek.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Nagyítás</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">Az NFC ki van kapcsolva ezen az eszközön. Kapcsolja be az <ph name="BEGIN_LINK" />Android Beállítások alkalmazásában<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Ez a webhely gyorsan megnyílik és reagál a legtöbb felhasználó számára</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Kilép az inkognitó módból?</translation>
<translation id="8958424370300090006">Adott webhely cookie-jainak letiltása.</translation>
<translation id="8959122750345127698">Nem érhető el az ide vezető navigáció: <ph name="URL" /></translation>
<translation id="8986362086234534611">Elfelejt</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hy.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hy.xtb
index ba8db7b02fd..adbbffc99c8 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hy.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_hy.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="hy">
<translation id="1006017844123154345">Ô²Õ¡ÖÕ¥Õ¬ Õ¡Õ¼ÖÕ¡Õ¶Ö</translation>
<translation id="1044891598689252897">Ô¿Õ¡ÕµÖ„Õ¥Ö€Õ¨ Õ¯Õ¡Õ·Õ­Õ¡Õ¿Õ¥Õ¶ Õ½Õ¸Õ¾Õ¸Ö€Õ¡Õ¯Õ¡Õ¶ Õ¼Õ¥ÕªÕ«Õ´Õ¸Õ¾</translation>
+<translation id="1100504063505580045">Ô¸Õ¶Õ©Õ¡ÖÕ«Õ¯ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¡Õ¯</translation>
<translation id="1124090076051167250">Ô¿Õ»Õ¶Õ»Õ¾Õ¥Õ¶ Õ¢Õ¸Õ¬Õ¸Ö€ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¶ Õ¸Ö‚ Ö„Õ¸Ö‚Ö„Õ«Õ¶Õ¥Ö€Õ¨ (<ph name="DATASIZE" />), Õ¸Ö€Õ¸Õ¶Ö„ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ¯Ö€Õ¡Õ¶Õ«Õ¶ Õ¥Õ¶ ÕºÕ¡Õ°Õ¾Õ¥Õ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ« Ö‡ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ« Õ¯Õ¸Õ²Õ´Õ«ÖÖ‰</translation>
<translation id="1124772482545689468">Õ•Õ£Õ¿Õ¡Õ¿Õ¥Ö€</translation>
<translation id="1178581264944972037">Ô´Õ¡Õ¤Õ¡Ö€</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Ô½Õ¸Õ½Õ¡ÖƒÕ¸Õ²</translation>
<translation id="3277252321222022663">Ô¹Õ¸Ö‚ÕµÕ¬ Õ¿Õ¡Õ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ¿Õ¾Õ«Õ¹Õ¶Õ¥Ö€Õ¨ (Õ­Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ§ Õ¿Ö€Õ¾Õ¸Ö‚Õ´)</translation>
<translation id="3295602654194328831">Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨</translation>
+<translation id="3317660236277031814">ÕÕ¥Ö€ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¡Õ® Õ¾Õ¥Õ¢ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨ ÖƒÕ¸Õ­Õ¥Õ¬ Õ§ Õ«Ö€ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¡Õ¯Õ¨Ö‰</translation>
<translation id="3328801116991980348">ÕÕ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€ Õ¯Õ¡ÕµÖ„Õ« Õ´Õ¡Õ½Õ«Õ¶</translation>
<translation id="3333961966071413176">Ô²Õ¸Õ¬Õ¸Ö€ Õ¯Õ¸Õ¶Õ¿Õ¡Õ¯Õ¿Õ¶Õ¥Ö€Õ¨</translation>
<translation id="3386292677130313581">Õ€Õ¡Ö€ÖÕ¶Õ¥Õ¬Õ Õ¶Õ¡Õ­Ö„Õ¡Õ¶ Õ±Õ¥Ö€ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¤Õ¡Ö€Õ±Õ¶Õ¥Õ¬Õ¨ (Õ­Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ§ Õ¿Ö€Õ¾Õ¸Ö‚Õ´)</translation>
+<translation id="345699454248713913">ÕÕ¥Ö€ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¡Õ® Õ¾Õ¥Õ¢ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨ ÖƒÕ¸Õ­Õ¥Õ¬ Õ§ Õ«Ö€ Õ¡Õ¶Õ¾Õ¡Õ¶Õ¸Ö‚Õ´Õ¨Ö‰</translation>
<translation id="3538390592868664640">Ô±Ö€Õ£Õ¥Õ¬Õ¥Õ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶ Õ½Õ¿Õ¥Õ²Õ®Õ¥Õ¬ Õ·Ö€Õ»Õ¡Õ¯Õ¡ÕµÖ„Õ« Õ¥Õ¼Õ¡Õ¹Õ¡Öƒ Ö„Õ¡Ö€Õ¿Õ¥Õ¦Õ¨ Ö‡ Õ°Õ¥Õ¿Õ¡Õ£Õ®Õ¥Õ¬ Õ¿Õ¥Õ½Õ¡Õ­ÖÕ«Õ¯Õ« Õ¤Õ«Ö€Ö„Õ¨</translation>
+<translation id="3551268116566418498">Ô´Õ¸Ö‚Ö€Õ½ Õ£Õ¡ÕžÕ¬ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ«Ö</translation>
<translation id="3586500876634962664">ÕÕ¥Õ½Õ¡Õ­ÖÕ«Õ¯Õ« Ö‡ Õ­Õ¸Õ½Õ¡ÖƒÕ¸Õ²Õ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´</translation>
<translation id="358794129225322306">Ô¹Õ¸Ö‚ÕµÕ¬ Õ¿Õ¡Õ¬ Õ¯Õ¡ÕµÖ„Õ«Õ¶ Õ¡Õ¾Õ¿Õ¸Õ´Õ¡Õ¿ Õ¶Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ´Õ¥Õ¯Õ«Ö Õ¡Õ¾Õ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¥Ö€Ö‰</translation>
<translation id="3594780231884063836">Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ Õ¿Õ¥Õ½Õ¡Õ¶ÕµÕ¸Ö‚Õ©Õ« Õ±Õ¡ÕµÕ¶Õ¨</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Ô²Õ¡ÖÕ¥Õ¬ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨</translation>
<translation id="4226663524361240545">Ô¾Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ½Õ¡Ö€Ö„Õ¨ Õ¯Õ©Ö€Õ©Õ¼Õ¡</translation>
<translation id="4259722352634471385">Õ†Õ¡Õ¾Õ«Õ£Õ¡ÖÕ«Õ¡Õ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ§Õ <ph name="URL" /></translation>
+<translation id="4277239631747669329">ÕÕ¥Ö€ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¡Õ® Õ¾Õ¥Õ¢ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨ ÖƒÕ¸Õ­Õ¥Õ¬ Õ§ Õ«Ö€ Õ¡Õ¶Õ¾Õ¡Õ¶Õ¸Ö‚Õ´Õ¨ Ö‡ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¡Õ¯Õ¨Ö‰</translation>
<translation id="4278390842282768270">Ô¹Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Ö€Õ¾Õ¡Õ® Õ§</translation>
<translation id="429312253194641664">Ô¿Õ¡ÕµÖ„Õ¸Ö‚Õ´ Õ´Õ¥Õ¤Õ«Õ¡ Ö†Õ¡ÕµÕ¬ Õ§ Õ¶Õ¾Õ¡Õ£Õ¡Ö€Õ¯Õ¾Õ¸Ö‚Õ´</translation>
<translation id="42981349822642051">Ô¸Õ¶Õ¤Õ¡Ö€Õ±Õ¡Õ¯Õ¥Õ¬</translation>
<translation id="4336434711095810371">Õ„Õ¡Ö„Ö€Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨</translation>
<translation id="4402755511846832236">Ô±Ö€Õ£Õ¥Õ¬Õ¥Õ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¶Õ¡Õ¬, Õ¥Ö€Õ¢ Õ¤Õ¸Ö‚Ö„ Õ¡Õ¯Õ¿Õ«Õ¾Õ¸Ö€Õ¥Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„ Õ¡ÕµÕ½ Õ½Õ¡Ö€Ö„Õ¨</translation>
-<translation id="4433925000917964731">Ô·Õ»Õ« Lite Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ¨ Õ¿Ö€Õ¡Õ´Õ¡Õ¤Ö€Õ¾Õ¥Õ¬ Õ§ Google-Õ« Õ¯Õ¸Õ²Õ´Õ«Ö</translation>
<translation id="4434045419905280838">ÔµÕ¬Õ¶Õ¸Õ² ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¶Õ¥Ö€ Ö‡ Õ¾Õ¥Ö€Õ¡Õ°Õ²Õ¸Ö‚Õ´</translation>
<translation id="445467742685312942">Ô¹Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶ Õ¶Õ¾Õ¡Õ£Õ¡Ö€Õ¯Õ¥Õ¬ ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¾Õ¡Õ® Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶</translation>
<translation id="4468959413250150279">Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ Õ±Õ¡ÕµÕ¶Õ¨ Õ¡Õ¼Õ¡Õ¶Õ±Õ«Õ¶ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ¸Ö‚Õ´</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Ô¿Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¾Õ¸Ö‚Õ´ Õ§ Õ±Õ¥Ö€ Õ®Õ¶Õ¸Õ²Õ« Õ¯Õ¸Õ²Õ´Õ«Ö</translation>
<translation id="4670064810192446073">ÕŽÕ«Ö€Õ¿Õ¸Ö‚Õ¡Õ¬ Õ«Ö€Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶</translation>
<translation id="4708011789095599544">Õ„Õ¡Ö„Ö€Õ¥ÕžÕ¬ Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ« Ö„Õ¸Ö‚Ö„Õ«Õ¶Õ¥Ö€Õ¶ Õ¸Ö‚ Õ´ÕµÕ¸Ö‚Õ½ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰</translation>
+<translation id="473775607612524610">Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬</translation>
<translation id="4751476147751820511">Õ‡Õ¡Ö€ÕªÕ´Õ¡Õ¶ Ö‡ Õ¬Õ¸Ö‚Õ½Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¿Õ¾Õ«Õ¹Õ¶Õ¥Ö€</translation>
<translation id="4836046166855586901">Õ€Õ¡Ö€ÖÕ¶Õ¥Õ¬, Õ¥Ö€Õ¢ Õ¸Ö€Ö‡Õ§ Õ¯Õ¡ÕµÖ„ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ§ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡Õ¶Õ¡Õ¬, Õ¥Ö€Õ¢ Õ¤Õ¸Ö‚Ö„ Õ¡Õ¯Õ¿Õ«Õ¾Õ¸Ö€Õ¥Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„ Õ¡ÕµÕ½ Õ½Õ¡Ö€Ö„Õ¨</translation>
<translation id="4883854917563148705">Ô¿Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¾Õ¸Õ² Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ§ Õ¾Õ¥Ö€Õ¡Õ¯Õ¡ÕµÕ¥Õ¬</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Õ€Õ¡Õ´Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ´Õ¡Õ¶ Õ´Õ«Õ»Õ¸ÖÕ¨`</translation>
<translation id="5039804452771397117">Ô¹Õ¸Ö‚ÕµÕ¬ Õ¿Õ¡Õ¬</translation>
<translation id="5048398596102334565">Ô¹Õ¸Ö‚ÕµÕ¬ Õ¿Õ¡Õ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ±Õ¥Ö€ Õ¿Õ¾Õ«Õ¹Õ¶Õ¥Ö€Õ¨ (Õ­Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ§ Õ¿Ö€Õ¾Õ¸Ö‚Õ´)</translation>
+<translation id="5050380848339752099">Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¨ ÕºÕ¡Õ¿Ö€Õ¡Õ½Õ¿Õ¾Õ¸Ö‚Õ´ Õ§ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ´Õ« Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ«, Õ¸Ö€Õ¶ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ«Ö Õ¤Õ¸Ö‚Ö€Õ½ Õ§ Õ£Õ¿Õ¶Õ¾Õ¸Ö‚Õ´Ö‰</translation>
<translation id="5063480226653192405">ÕŽÕ«Õ³Õ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶</translation>
<translation id="5100237604440890931">Ô¿Õ¸Õ®Õ¯Õ¾Õ¡Õ® - Õ¨Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„</translation>
<translation id="5123685120097942451">Ô»Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¶Õ¥Ö€Õ¤Õ«Ö€</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Ô¹Õ¸Ö‚ÕµÕ¬ Õ¿Õ¡Õ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶ Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¥Õ¬ JavaScript-Õ¨ (Õ­Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ§ Õ¿Ö€Õ¾Õ¸Ö‚Õ´)</translation>
<translation id="534295439873310000">NFC Õ½Õ¡Ö€Ö„Õ¥Ö€</translation>
<translation id="5354152178998424783">Ô¿Õ¡ÕµÖ„Õ¥Ö€Õ« ÕºÕ¡Õ°Õ¡Õ® <ph name="DATASIZE" /> Õ®Õ¡Õ¾Õ¡Õ¬Õ¸Õ¾ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¶ Õ¸Ö‚ Ö„Õ¸Ö‚Ö„Õ«Õ¶Õ¥Ö€Õ¨ Õ¯Õ»Õ¶Õ»Õ¾Õ¥Õ¶Ö‰</translation>
-<translation id="5384883051496921101">Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¨ ÕºÕ¡Õ¿Ö€Õ¡Õ½Õ¿Õ¾Õ¸Ö‚Õ´ Õ§ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ´Õ« Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ«, Õ¸Ö€Õ¶ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ«Ö Õ¤Õ¸Ö‚Ö€Õ½ Õ§ Õ£Õ¿Õ¶Õ¾Õ¸Ö‚Õ´Ö‰</translation>
+<translation id="536508626067510330">Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥ÕžÕ¬ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¡Õ¯Õ¨ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ¯Ö€Õ¡Õ¶Õ«Õ¶</translation>
<translation id="5391532827096253100">Ô¿Õ¡ÕµÖ„Õ«Õ¶ Õ¯Õ¡ÕºÕ¡Õ¯ÖÕ¸Ö‚Õ´Õ¨ ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¾Õ¡Õ® Õ¹Õ§: ÕÕ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€ Õ¯Õ¡ÕµÖ„Õ« Õ´Õ¡Õ½Õ«Õ¶:</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(Õ¸Ö‚ Ö‡Õ½ 1)}one{(Õ¸Ö‚ Ö‡Õ½ #)}other{(Õ¸Ö‚ Ö‡Õ½ #)}}</translation>
<translation id="5403592356182871684">Ô±Õ¶Õ¸Ö‚Õ¶Õ¶Õ¥Ö€</translation>
<translation id="5489227211564503167">Ô±Õ¶ÖÕ¡Õ® ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¨Õ <ph name="ELAPSED_TIME" />/<ph name="TOTAL_TIME" />Ö‰</translation>
<translation id="5494752089476963479">Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ£Õ¸Õ¾Õ¡Õ¦Õ¤Õ¨ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ¸Ö‚Õ´, Õ¸Ö€Õ¸Õ¶Ö„ Õ°Õ¸Õ£Õ¶Õ¥ÖÕ¶Õ¸Õ² Õ¯Õ¡Õ´ Õ´Õ¸Õ¬Õ¸Ö€Õ¥ÖÕ¶Õ¸Õ² Õ£Õ¸Õ¾Õ¡Õ¦Õ¤ Õ¥Õ¶ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ´</translation>
+<translation id="549957179819296104">Õ†Õ¸Ö€ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¡Õ¯</translation>
<translation id="5502860503640766021">Ô¹Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Ö€Õ¾Õ¡Õ® Õ§Õ Â«<ph name="PERMISSION_1" />», Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ§Õ Â«<ph name="PERMISSION_2" />»</translation>
<translation id="5505264765875738116">Ô¿Õ¡ÕµÖ„Õ¥Ö€Õ¨ Õ¹Õ¥Õ¶ Õ¯Õ¡Ö€Õ¸Õ² Õ­Õ¶Õ¤Ö€Õ¥Õ¬ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬</translation>
<translation id="5516455585884385570">Ô²Õ¡ÖÕ¥Õ¬ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Ô¹Õ¸Ö‚ÕµÕ¬Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€</translation>
<translation id="5860033963881614850">Ô±Õ¶Õ»Õ¡Õ¿.</translation>
<translation id="5876056640971328065">Ô´Õ¡Õ¤Õ¡Ö€Õ¥ÖÕ¶Õ¥Õ¬</translation>
+<translation id="5904826301761575486">Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥ÕžÕ¬ Õ¡Õ¶Õ¾Õ¡Õ¶Õ¸Ö‚Õ´Õ¶ Õ¸Ö‚ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¡Õ¯Õ¨ Õ±Õ¥Ö€ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ¯Ö€Õ¡Õ¶Õ«Õ¶</translation>
<translation id="5916664084637901428">Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬</translation>
<translation id="5922853908706496913">Ô·Õ¯Ö€Õ¡Õ¶Õ¨ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ¸Ö‚Õ´ Õ§</translation>
<translation id="5939518447894949180">ÕŽÕ¥Ö€Õ¡Õ¯Õ¡ÕµÕ¥Õ¬</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ¥Ö€Ö€Õ¸Ö€Õ¤ Õ¯Õ¸Õ²Õ´Õ« Ö„Õ¸Ö‚Ö„Õ«Õ¶Õ¥Ö€Õ¨</translation>
<translation id="6206551242102657620">Ô¿Õ¡ÕºÕ¡Õ¯ÖÕ¸Ö‚Õ´Õ¨ ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¾Õ¡Õ® Õ¹Õ§: ÕÕ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€ Õ¯Õ¡ÕµÖ„Õ« Õ´Õ¡Õ½Õ«Õ¶:</translation>
<translation id="6216432067784365534">Ô¸Õ¶Õ¿Ö€Õ¡Õ¶Ö„Õ¶Õ¥Ö€Õ <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Õ“Õ¡Õ¯Õ¥Õ¬ Ö‡ Õ°Õ¡Õ²Õ¸Ö€Õ¤Õ¥Õ¬ Õ­Õ¡Õ­Õ¿Õ´Õ¡Õ¶ Õ´Õ¡Õ½Õ«Õ¶</translation>
<translation id="6262279340360821358">Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ¥Õ¶Õ Â«<ph name="PERMISSION_1" />» Ö‡ «<ph name="PERMISSION_2" />»</translation>
<translation id="6270391203985052864">Ô¿Õ¡ÕµÖ„Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ­Õ¶Õ¤Ö€Õ¥Õ¬ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬</translation>
<translation id="6295158916970320988">Ô²Õ¸Õ¬Õ¸Ö€ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ¨</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">ÕˆÖ€ÕºÕ¥Õ½Õ¦Õ« Õ±Õ¥Ö€ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¤Õ¡Õ¼Õ¶Õ¡ <ph name="APP_NAME" />-Õ«Õ¶, Õ´Õ«Õ¡ÖÖ€Õ¥Ö„ Õ¡ÕµÕ¶ <ph name="BEGIN_LINK" />Android-Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´<ph name="END_LINK" />Ö‰</translation>
<translation id="8447861592752582886">Ô±Ö€Õ£Õ¥Õ¬Õ¥Õ¬ Õ½Õ¡Ö€Ö„Õ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´Õ¨</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¸Õ² Ö„Õ¸Ö‚Ö„Õ«}one{# Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¸Õ² Ö„Õ¸Ö‚Ö„Õ«}other{# Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¸Õ² Ö„Õ¸Ö‚Ö„Õ«}}</translation>
-<translation id="8463851957836045671">Ô¿Õ¡ÕµÖ„Õ¨ Õ¢Õ¥Õ¼Õ¶Õ¾Õ¸Ö‚Õ´ Õ§ Õ¡Ö€Õ¡Õ£</translation>
<translation id="8487700953926739672">Õ„Õ¡Õ¿Õ¹Õ¥Õ¬Õ« Õ§ Õ¡Õ¶ÖÕ¡Õ¶Ö Õ¼Õ¥ÕªÕ«Õ´Õ¸Ö‚Õ´</translation>
<translation id="851751545965956758">Ô±Ö€Õ£Õ¥Õ¬Õ¥Õ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶ Õ´Õ«Õ¡Õ¶Õ¡Õ¬ Õ½Õ¡Ö€Ö„Õ¥Ö€Õ«Õ¶</translation>
<translation id="8525306231823319788">Ô¼Õ«Õ¡Õ§Õ¯Ö€Õ¡Õ¶</translation>
<translation id="857943718398505171">Ô¹Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Ö€Õ¾Õ¡Õ® Õ§ (Õ°Õ¡Õ¶Õ±Õ¶Õ¡Ö€Õ¡Ö€Õ¥Õ¬Õ«)</translation>
<translation id="8609465669617005112">ÕÕ¥Õ²Õ¡ÖƒÕ¸Õ­Õ¥Õ¬ Õ¾Õ¥Ö€</translation>
+<translation id="861748745608658996">Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥ÕžÕ¬ Õ¡Õ¶Õ¾Õ¡Õ¶Õ¸Ö‚Õ´Õ¨ Õ±Õ¥Ö€ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ¯Ö€Õ¡Õ¶Õ«Õ¶</translation>
<translation id="8676374126336081632">Õ„Õ¡Ö„Ö€Õ¥Õ¬ Õ¶Õ¥Ö€Õ¡Õ®Õ¸Ö‚Õ´Õ¨</translation>
<translation id="868929229000858085">ÕˆÖ€Õ¸Õ¶Õ¥Ö„ Õ¯Õ¸Õ¶Õ¿Õ¡Õ¯Õ¿Õ¶Õ¥Ö€</translation>
<translation id="8702612070107455751">Ô±Õ¶ÖÕ¡Õ¶Ö Õ¼Õ¥ÕªÕ«Õ´Õ¸Ö‚Õ´ ÕºÕ¡Õ°Õ¾Õ¡Õ® Õ¢Õ¸Õ¬Õ¸Ö€ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¯Õ»Õ¶Õ»Õ¾Õ¥Õ¶Ö‰</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Ô½Õ¸Õ·Õ¸Ö€Õ¡ÖÕ¶Õ¥Õ¬</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">ÕÕ¡Ö€Ö„Õ« NFC-Õ¶ Õ¡Õ¶Õ»Õ¡Õ¿Õ¾Õ¡Õ® Õ§Ö‰ Õ„Õ«Õ¡ÖÖ€Õ¥Ö„ Õ¡ÕµÕ¶ <ph name="BEGIN_LINK" />Android-Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´<ph name="END_LINK" />Ö‰</translation>
-<translation id="8929372349074745002">Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¨ Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ¢Õ¥Õ¼Õ¶Õ¾Õ¸Ö‚Õ´ Ö‡ Õ¡Ö€Õ±Õ¡Õ£Õ¡Õ¶Ö„Õ¸Ö‚Õ´ Õ§ Õ¡Ö€Õ¡Õ£</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Ô´Õ¸Ö‚Ö€Õ½ Õ£Õ¡ÕžÕ¬ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ«Ö</translation>
<translation id="8958424370300090006">Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Ö„Õ¸Ö‚Ö„Õ«Õ¶Õ¥Ö€Õ¨ Õ¯Õ¸Õ¶Õ¯Ö€Õ¥Õ¿ Õ¯Õ¡ÕµÖ„Õ« Õ°Õ¡Õ´Õ¡Ö€:</translation>
<translation id="8959122750345127698">Õ†Õ¡Õ¾Õ«Õ£Õ¡ÖÕ«Õ¡Õ¶ Õ¡Õ¶Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§Õ <ph name="URL" /></translation>
<translation id="8986362086234534611">Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_id.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_id.xtb
index 14a48267f5c..ac88d11709d 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_id.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_id.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="id">
<translation id="1006017844123154345">Buka versi Online</translation>
<translation id="1044891598689252897">Situs akan berfungsi secara normal</translation>
+<translation id="1100504063505580045">Ikon saat ini</translation>
<translation id="1124090076051167250">Ini akan menghapus <ph name="DATASIZE" /> data dan cookie yang disimpan oleh situs atau aplikasi di Layar utama Anda.</translation>
<translation id="1124772482545689468">Pengguna</translation>
<translation id="1178581264944972037">Jeda</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Mengizinkan situs untuk mengakses sensor (disarankan)</translation>
<translation id="3295602654194328831">Sembunyikan Info</translation>
+<translation id="3317660236277031814">Aplikasi web yang Anda instal telah mengubah ikonnya.</translation>
<translation id="3328801116991980348">Informasi situs</translation>
<translation id="3333961966071413176">Semua kontak</translation>
<translation id="3386292677130313581">Minta izin sebelum memungkinkan situs mengetahui lokasi Anda (disarankan)</translation>
+<translation id="345699454248713913">Aplikasi web yang Anda instal telah mengubah namanya.</translation>
<translation id="3538390592868664640">Blokir situs agar tidak membuat peta 3D untuk area di sekeliling Anda atau melacak posisi kamera</translation>
+<translation id="3551268116566418498">Keluar dari mode Samaran?</translation>
<translation id="3586500876634962664">Kamera dan mikrofon aktif</translation>
<translation id="358794129225322306">Izinkan situs untuk otomatis mendownload beberapa file.</translation>
<translation id="3594780231884063836">Bisukan video</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Buka Setelan Lokasi</translation>
<translation id="4226663524361240545">Notifikasi dapat membuat perangkat bergetar</translation>
<translation id="4259722352634471385">Navigasi diblokir: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Aplikasi web yang Anda instal telah mengubah nama dan ikonnya.</translation>
<translation id="4278390842282768270">Diizinkan</translation>
<translation id="429312253194641664">Sebuah situs sedang memutar media</translation>
<translation id="42981349822642051">Luaskan</translation>
<translation id="4336434711095810371">Hapus semua data</translation>
<translation id="4402755511846832236">Blokir situs agar tidak mengetahui saat Anda aktif menggunakan perangkat ini</translation>
-<translation id="4433925000917964731">Halaman ringan yang ditampilkan oleh Google.</translation>
<translation id="4434045419905280838">Pop-up dan pengalihan</translation>
<translation id="445467742685312942">Izinkan situs memutar konten yang dilindungi</translation>
<translation id="4468959413250150279">Mematikan suara untuk situs tertentu.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Dikelola oleh orang tua Anda</translation>
<translation id="4670064810192446073">Virtual reality</translation>
<translation id="4708011789095599544">Yakin ingin menghapus cookie dan data situs lainnya untuk situs ini?</translation>
+<translation id="473775607612524610">Perbarui</translation>
<translation id="4751476147751820511">Sensor gerakan atau cahaya</translation>
<translation id="4836046166855586901">Tanyakan saat situs ingin mengetahui saat Anda aktif menggunakan perangkat ini</translation>
<translation id="4883854917563148705">Setelan yang dikelola tidak dapat direset</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Bagikan dengan</translation>
<translation id="5039804452771397117">Izinkan</translation>
<translation id="5048398596102334565">Mengizinkan situs mengakses sensor gerakan (disarankan)</translation>
+<translation id="5050380848339752099">Situs ini akan membagikan informasi ke aplikasi di luar mode Samaran.</translation>
<translation id="5063480226653192405">Penggunaan</translation>
<translation id="5100237604440890931">Diciutkan - klik untuk memperluas.</translation>
<translation id="5123685120097942451">Tab samaran</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Izinkan situs menjalankan JavaScript (disarankan)</translation>
<translation id="534295439873310000">Perangkat NFC</translation>
<translation id="5354152178998424783">Ini akan menghapus <ph name="DATASIZE" /> data dan cookie yang disimpan oleh situs.</translation>
-<translation id="5384883051496921101">Situs ini akan membagikan informasi dengan aplikasi di luar mode samaran.</translation>
+<translation id="536508626067510330">Perbarui ikon di layar utama Anda?</translation>
<translation id="5391532827096253100">Sambungan ke situs ini tidak aman. Informasi situs</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 lainnya)}other{(+ # lainnya)}}</translation>
<translation id="5403592356182871684">Nama</translation>
<translation id="5489227211564503167">Waktu berlalu <ph name="ELAPSED_TIME" /> dari <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blokir iklan di situs yang menampilkan iklan yang mengganggu atau menyesatkan</translation>
+<translation id="549957179819296104">Ikon baru</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> diizinkan, <ph name="PERMISSION_2" /> diblokir</translation>
<translation id="5505264765875738116">Situs tidak dapat meminta izin mengirimkan notifikasi</translation>
<translation id="5516455585884385570">Buka setelan notifikasi</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Izin</translation>
<translation id="5860033963881614850">Nonaktif</translation>
<translation id="5876056640971328065">Jeda video</translation>
+<translation id="5904826301761575486">Perbarui nama &amp; ikon di layar utama Anda?</translation>
<translation id="5916664084637901428">Aktif</translation>
<translation id="5922853908706496913">Membagikan layar Anda</translation>
<translation id="5939518447894949180">Reset</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokir cookie pihak ketiga</translation>
<translation id="6206551242102657620">Sambungan aman. Informasi situs</translation>
<translation id="6216432067784365534">Opsi <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Tutup dan laporkan penyalahgunaan</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> dan <ph name="PERMISSION_2" /> diblokir</translation>
<translation id="6270391203985052864">Situs dapat meminta izin mengirimkan notifikasi</translation>
<translation id="6295158916970320988">Semua situs</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Untuk mengizinkan <ph name="APP_NAME" /> mengakses lokasi Anda, aktifkan juga lokasi di <ph name="BEGIN_LINK" />Setelan Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Cabut izin perangkat</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie sedang digunakan}other{# cookie sedang digunakan}}</translation>
-<translation id="8463851957836045671">Situs ini cepat</translation>
<translation id="8487700953926739672">Tersedia secara offline</translation>
<translation id="851751545965956758">Blokir situs agar tidak terhubung ke perangkat</translation>
<translation id="8525306231823319788">Layar penuh</translation>
<translation id="857943718398505171">Diizinkan (disarankan)</translation>
<translation id="8609465669617005112">Berpindah ke atas</translation>
+<translation id="861748745608658996">Perbarui nama di layar utama Anda?</translation>
<translation id="8676374126336081632">Hapus masukan</translation>
<translation id="868929229000858085">Telusuri kontak Anda</translation>
<translation id="8702612070107455751">Semua data offline akan dihapus.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Perbesar</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC dinonaktifkan di perangkat ini. Aktifkan di <ph name="BEGIN_LINK" />Setelan Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Situs ini membuka dan merespons dengan cepat bagi sebagian besar orang</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Keluar dari mode samaran?</translation>
<translation id="8958424370300090006">Blokir cookie untuk situs tertentu.</translation>
<translation id="8959122750345127698">Navigasi tidak dapat dijangkau: <ph name="URL" /></translation>
<translation id="8986362086234534611">Lupakan</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_is.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_is.xtb
index 11c88ef5593..6c3fb63cd35 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_is.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_is.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="is">
<translation id="1006017844123154345">Opna á netinu</translation>
<translation id="1044891598689252897">Vefsvæði virka sem skyldi</translation>
+<translation id="1100504063505580045">Núverandi tákn</translation>
<translation id="1124090076051167250">Þetta hreinsar <ph name="DATASIZE" /> af gögnum og fótsporum sem geymd eru af vefsvæðum og forritum á heimaskjánum.</translation>
<translation id="1124772482545689468">Notandi</translation>
<translation id="1178581264944972037">Gera hlé</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Hljóðnemi</translation>
<translation id="3277252321222022663">Leyfa vefsvæðum að fá aðgang að skynjurum (ráðlagt)</translation>
<translation id="3295602654194328831">Fela upplýsingar</translation>
+<translation id="3317660236277031814">Tákn vefforrits sem þú settir upp hefur breyst.</translation>
<translation id="3328801116991980348">Upplýsingar um vefsvæði</translation>
<translation id="3333961966071413176">Allir tengiliðir</translation>
<translation id="3386292677130313581">Spyrja áður en vefsvæðum er veitt heimild til að sjá staðsetningu þína (ráðlagt)</translation>
+<translation id="345699454248713913">Heiti vefforrits sem þú settir upp hefur breyst.</translation>
<translation id="3538390592868664640">Komdu í veg fyrir að vefsvæði búi til þrívíddarkort af umhverfinu eða reki staðsetningu myndavélarinnar</translation>
+<translation id="3551268116566418498">Slökkva á huliðsstillingu?</translation>
<translation id="3586500876634962664">Notkun myndavélar og hljóðnema</translation>
<translation id="358794129225322306">Leyfa vefsvæði að sækja margar skrár sjálfkrafa.</translation>
<translation id="3594780231884063836">Slökkva á mynd</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Opna staðsetningarstillingar</translation>
<translation id="4226663524361240545">Tilkynningar gætu látið tækið titra</translation>
<translation id="4259722352634471385">Lokað er fyrir skoðun: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Heiti og tákni vefforrits sem þú settir upp hefur verið breytt.</translation>
<translation id="4278390842282768270">Leyft</translation>
<translation id="429312253194641664">Vefsvæði er að spila efni</translation>
<translation id="42981349822642051">Stækka</translation>
<translation id="4336434711095810371">Hreinsa öll gögn</translation>
<translation id="4402755511846832236">Lokaðu á að vefsvæði geti séð hvenær þú notar þetta tæki</translation>
-<translation id="4433925000917964731">Léttútgáfa síðu frá Google</translation>
<translation id="4434045419905280838">Sprettigluggar og framsendingar</translation>
<translation id="445467742685312942">Leyfa vefsvæðum að spila varið efni</translation>
<translation id="4468959413250150279">Slökkva á hljóði á tilteknu vefsvæði.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Stjórnað af foreldri þínu</translation>
<translation id="4670064810192446073">Sýndarveruleiki</translation>
<translation id="4708011789095599544">Viltu örugglega hreinsa fótspor og önnur gögn fyrir þetta vefsvæði?</translation>
+<translation id="473775607612524610">Uppfæra</translation>
<translation id="4751476147751820511">Hreyfi- eða birtuskynjarar</translation>
<translation id="4836046166855586901">Spyrja þegar vefsvæði vill vita hvenær þú notar þetta tæki</translation>
<translation id="4883854917563148705">Ekki er hægt að endurstilla stýrðar stillingar</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Deila með</translation>
<translation id="5039804452771397117">Leyfa</translation>
<translation id="5048398596102334565">Leyfa vefsvæðum að fá aðgang að hreyfiskynjurunum (ráðlagt)</translation>
+<translation id="5050380848339752099">Vefsvæðið er við það að deila upplýsingum með forriti fyrir utan huliðsstillingu.</translation>
<translation id="5063480226653192405">Notkun</translation>
<translation id="5100237604440890931">Minnkað – smelltu til að stækka.</translation>
<translation id="5123685120097942451">Huliðsflipi</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Leyfa vefsvæðum að keyra JavaScript (ráðlagt)</translation>
<translation id="534295439873310000">NFC-tæki</translation>
<translation id="5354152178998424783">Þetta hreinsar <ph name="DATASIZE" /> af gögnum og fótsporum sem vefsvæði geyma.</translation>
-<translation id="5384883051496921101">Vefsvæðið er við það að deila upplýsingum með forriti fyrir utan huliðsstillingu.</translation>
+<translation id="536508626067510330">Uppfæra tákn á heimaskjánum?</translation>
<translation id="5391532827096253100">Tenging þín við þetta vefsvæði er ekki örugg. Upplýsingar um vefsvæði</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 í viðbót)}one{(+ # í viðbót)}other{(+ # í viðbót)}}</translation>
<translation id="5403592356182871684">Heiti</translation>
<translation id="5489227211564503167">Liðinn tími: <ph name="ELAPSED_TIME" /> af <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Útiloka auglýsingar á vefsvæðum sem birta ágengar eða villandi auglýsingar</translation>
+<translation id="549957179819296104">Nýtt tákn</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> leyft, lokað er fyrir <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Vefsvæði geta ekki óskað eftir því að senda tilkynningar</translation>
<translation id="5516455585884385570">Opna tilkynningastillingar</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Heimildir</translation>
<translation id="5860033963881614850">Slökkt</translation>
<translation id="5876056640971328065">Gera hlé á spilun</translation>
+<translation id="5904826301761575486">Uppfæra heiti og tákn á heimaskjánum?</translation>
<translation id="5916664084637901428">Kveikt</translation>
<translation id="5922853908706496913">Deiling skjásins þíns</translation>
<translation id="5939518447894949180">Endurstilla</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Loka á fótspor frá þriðja aðila</translation>
<translation id="6206551242102657620">Örugg tenging. Upplýsingar um vefsvæði</translation>
<translation id="6216432067784365534">Valkostir fyrir <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Loka og tilkynna misnotkun</translation>
<translation id="6262279340360821358">Lokað er fyrir <ph name="PERMISSION_1" /> og <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Vefsvæði geta óskað eftir því að senda tilkynningar</translation>
<translation id="6295158916970320988">Öll vefsvæði</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Til að veita <ph name="APP_NAME" /> aðgang að staðsetningu þinni þarftu einnig að kveikja á henni í <ph name="BEGIN_LINK" />stillingum Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Afturkalla tækjaheimild</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 fótspor í notkun}one{# fótspor í notkun}other{# fótspor í notkun}}</translation>
-<translation id="8463851957836045671">Vefsvæðið er hratt</translation>
<translation id="8487700953926739672">à boði án nettengingar</translation>
<translation id="851751545965956758">Ekki leyfa vefsvæðum að tengjast tækjum</translation>
<translation id="8525306231823319788">Allur skjárinn</translation>
<translation id="857943718398505171">Leyft (ráðlagt)</translation>
<translation id="8609465669617005112">Færa upp</translation>
+<translation id="861748745608658996">Uppfæra heiti á heimaskjánum?</translation>
<translation id="8676374126336081632">Hreinsa innslátt</translation>
<translation id="868929229000858085">Leita í tengiliðum</translation>
<translation id="8702612070107455751">Öllum ónettengdum gögnum verður eytt.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Auka aðdrátt</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">Slökkt er á NFC fyrir þetta tæki. Kveiktu á því í <ph name="BEGIN_LINK" />stillingum Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Þetta vefsvæði opnast fljótt og svarar hratt fyrir flesta notendur</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Slökkva á huliðsstillingu?</translation>
<translation id="8958424370300090006">Lokaðu á fótspor fyrir tiltekið vefsvæði.</translation>
<translation id="8959122750345127698">Ekki næst samband: <ph name="URL" /></translation>
<translation id="8986362086234534611">Gleyma</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_it.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_it.xtb
index dce1a26d3e5..119570d8210 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_it.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_it.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="it">
<translation id="1006017844123154345">Apri online</translation>
<translation id="1044891598689252897">I siti funzioneranno normalmente</translation>
+<translation id="1100504063505580045">Icona attuale</translation>
<translation id="1124090076051167250">Verranno cancellati <ph name="DATASIZE" /> di dati e cookie memorizzati da siti e app nella schermata Home.</translation>
<translation id="1124772482545689468">Utente</translation>
<translation id="1178581264944972037">Pausa</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Microfono</translation>
<translation id="3277252321222022663">Consenti ai siti di accedere ai sensori (opzione consigliata)</translation>
<translation id="3295602654194328831">Nascondi informazioni</translation>
+<translation id="3317660236277031814">È cambiata l'icona di un'app web che hai installato.</translation>
<translation id="3328801116991980348">Informazioni sito</translation>
<translation id="3333961966071413176">Tutti i contatti</translation>
<translation id="3386292677130313581">Chiedi conferma prima di consentire ai siti di conoscere la tua posizione (opzione consigliata)</translation>
+<translation id="345699454248713913">È cambiato il nome di un'app web che hai installato.</translation>
<translation id="3538390592868664640">Impedisci ai siti di creare una mappa 3D dell'ambiente circostante o di monitorare la posizione della fotocamera</translation>
+<translation id="3551268116566418498">Uscire da modalità in incognito?</translation>
<translation id="3586500876634962664">Uso di videocamera e microfono</translation>
<translation id="358794129225322306">Consenti a un sito di scaricare automaticamente più file.</translation>
<translation id="3594780231884063836">Disattiva audio video</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Apri Impostazioni di geolocalizzazione</translation>
<translation id="4226663524361240545">Le notifiche possono far vibrare il dispositivo</translation>
<translation id="4259722352634471385">Navigazione bloccata: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Sono cambiati nome e icona di un'app web che hai installato.</translation>
<translation id="4278390842282768270">Consenti</translation>
<translation id="429312253194641664">Un sito sta riproducendo contenuti multimediali</translation>
<translation id="42981349822642051">Espandi</translation>
<translation id="4336434711095810371">Cancella tutti i dati</translation>
<translation id="4402755511846832236">Impedisci ai siti di sapere quando usi attivamente questo dispositivo</translation>
-<translation id="4433925000917964731">Pagina Lite fornita da Google</translation>
<translation id="4434045419905280838">Popup e reindirizzamenti</translation>
<translation id="445467742685312942">Consenti ai siti di riprodurre contenuti protetti</translation>
<translation id="4468959413250150279">Disattiva l'audio per un sito specifico.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Gestito da un genitore</translation>
<translation id="4670064810192446073">Realtà virtuale</translation>
<translation id="4708011789095599544">Vuoi cancellare i cookie e altri dati del sito per questo sito web?</translation>
+<translation id="473775607612524610">Aggiorna</translation>
<translation id="4751476147751820511">Sensori di movimento o della luce</translation>
<translation id="4836046166855586901">Chiedi conferma quando un sito vuole sapere quando usi attivamente questo dispositivo</translation>
<translation id="4883854917563148705">Le impostazioni gestite non possono essere reimpostate</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Condividi tramite</translation>
<translation id="5039804452771397117">Consenti</translation>
<translation id="5048398596102334565">Consenti ai siti di accedere ai sensori di movimento (opzione consigliata)</translation>
+<translation id="5050380848339752099">Questo sito sta per condividere informazioni con un'app esterna alla modalità di navigazione in incognito.</translation>
<translation id="5063480226653192405">Utilizzo</translation>
<translation id="5100237604440890931">Compresso. Fai clic per espandere.</translation>
<translation id="5123685120097942451">Scheda di navigazione in incognito</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Consenti l'esecuzione di JavaScript nei siti (opzione consigliata)</translation>
<translation id="534295439873310000">Dispositivi NFC</translation>
<translation id="5354152178998424783">Verranno cancellati <ph name="DATASIZE" /> di dati e cookie memorizzati dai siti.</translation>
-<translation id="5384883051496921101">Questo sito sta per condividere informazioni con un'app esterna alla modalità di navigazione in incognito.</translation>
+<translation id="536508626067510330">Vuoi aggiornare l'icona nella schermata Home?</translation>
<translation id="5391532827096253100">La tua connessione al sito non è sicura. Informazioni sul sito</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 altro)}other{(+ altri #)}}</translation>
<translation id="5403592356182871684">Nomi</translation>
<translation id="5489227211564503167">Tempo trascorso: <ph name="ELAPSED_TIME" /> di <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blocca gli annunci su siti che mostrano annunci invasivi o fuorvianti</translation>
+<translation id="549957179819296104">Nuova icona</translation>
<translation id="5502860503640766021">Autorizzazione <ph name="PERMISSION_1" /> consentita, autorizzazione <ph name="PERMISSION_2" /> bloccata</translation>
<translation id="5505264765875738116">I siti non possono chiedere di inviare notifiche</translation>
<translation id="5516455585884385570">Apri le impostazioni di notifica</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Autorizzazioni</translation>
<translation id="5860033963881614850">Off</translation>
<translation id="5876056640971328065">Metti in pausa il video</translation>
+<translation id="5904826301761575486">Vuoi aggiornare il nome e l'icona nella schermata Home?</translation>
<translation id="5916664084637901428">On</translation>
<translation id="5922853908706496913">Condivisione dello schermo</translation>
<translation id="5939518447894949180">Reimposta</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blocca cookie di terze parti</translation>
<translation id="6206551242102657620">La connessione è sicura. Informazioni sul sito</translation>
<translation id="6216432067784365534">Opzioni <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Chiudi e segnala illecito</translation>
<translation id="6262279340360821358">Autorizzazioni <ph name="PERMISSION_1" /> e <ph name="PERMISSION_2" /> bloccate</translation>
<translation id="6270391203985052864">I siti possono chiedere di inviare notifiche</translation>
<translation id="6295158916970320988">Tutti i siti</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Per consentire all'app <ph name="APP_NAME" /> di accedere alla tua posizione, devi attivare la posizione anche nelle <ph name="BEGIN_LINK" />Impostazioni Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Revoca autorizzazione dispositivo</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie in uso}other{# cookie in uso}}</translation>
-<translation id="8463851957836045671">Il sito è veloce</translation>
<translation id="8487700953926739672">Disponibile offline</translation>
<translation id="851751545965956758">Impedisci ai siti di connettersi ai dispositivi</translation>
<translation id="8525306231823319788">Schermo intero</translation>
<translation id="857943718398505171">Consentita (opzione consigliata)</translation>
<translation id="8609465669617005112">Sposta su</translation>
+<translation id="861748745608658996">Vuoi aggiornare il nome nella schermata Home?</translation>
<translation id="8676374126336081632">Cancella testo inserito</translation>
<translation id="868929229000858085">Cerca nei contatti</translation>
<translation id="8702612070107455751">I dati offline verranno cancellati.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Aumenta lo zoom</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">Funzionalità NFC non attiva per questo dispositivo. Attivala nelle <ph name="BEGIN_LINK" />Impostazioni Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Questo sito si apre e risponde velocemente per la maggior parte degli utenti</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Uscire da modalità in incognito?</translation>
<translation id="8958424370300090006">Blocca i cookie per un sito specifico.</translation>
<translation id="8959122750345127698">Navigazione inaccessibile: <ph name="URL" /></translation>
<translation id="8986362086234534611">Elimina</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb
index 636a4621bc1..6302fcc25b5 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_iw.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="iw">
<translation id="1006017844123154345">פתיחת גרסה ×ונליין</translation>
<translation id="1044891598689252897">××ª×¨×™× ×™×¤×¢×œ×• כרגיל</translation>
+<translation id="1100504063505580045">הסמל הנוכחי</translation>
<translation id="1124090076051167250">â€×”פעולה ×”×–×ת תמחק <ph name="DATASIZE" /> של × ×ª×•× ×™× ×•×§×•×‘×¦×™ cookie ש××ª×¨×™× ×•×פליקציות שמרו במסך הבית.</translation>
<translation id="1124772482545689468">משתמש</translation>
<translation id="1178581264944972037">השהיה</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">מיקרופון</translation>
<translation id="3277252321222022663">התרת גישה של ××ª×¨×™× ×ל ×”×—×™×™×©× ×™× (מומלץ)</translation>
<translation id="3295602654194328831">הסתרת פרטי×</translation>
+<translation id="3317660236277031814">השתנה הסמל של ×פליקציית ×ינטרנט שהתקנת.</translation>
<translation id="3328801116991980348">פרטי ×תר</translation>
<translation id="3333961966071413176">כל ×נשי הקשר</translation>
<translation id="3386292677130313581">יש לש×ול לפני שמ××¤×©×¨×™× ×œ××ª×¨×™× ×œ×“×¢×ª מה ×”×ž×™×§×•× ×©×œ×š (מומלץ)</translation>
+<translation id="345699454248713913">השתנה ×”×©× ×©×œ ×פליקציית ×ינטרנט שהתקנת.</translation>
<translation id="3538390592868664640">חסימה של יצירת מפה בתלת ממד של הסביבה שלך ×ו של מעקב ×חר ×ž×™×§×•× ×”×ž×¦×œ×ž×” על ידי ×תרי×.</translation>
+<translation id="3551268116566418498">לצ×ת מהמצב ×”×נונימי?</translation>
<translation id="3586500876634962664">שימוש במצלמה ובמיקרופון</translation>
<translation id="358794129225322306">מתן הרש××” ל×תר להוריד ×§×‘×¦×™× ×ž×¨×•×‘×™× ×‘×ופן ×וטומטי.</translation>
<translation id="3594780231884063836">השתקת הסרטון</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">פתיחת הגדרות המיקו×</translation>
<translation id="4226663524361240545">רטט של המכשיר ×פשרי כשמתקבלת הודעה</translation>
<translation id="4259722352634471385">הניווט חסו×: <ph name="URL" /></translation>
+<translation id="4277239631747669329">השתנו ×”×©× ×•×”×¡×ž×œ של ×פליקציית ×ינטרנט שהתקנת.</translation>
<translation id="4278390842282768270">מותר</translation>
<translation id="429312253194641664">×תר ×ž×¡×•×™× ×ž×¤×¢×™×œ מדיה</translation>
<translation id="42981349822642051">הרחבה</translation>
<translation id="4336434711095810371">ניקוי כל הנתוני×</translation>
<translation id="4402755511846832236">××ª×¨×™× ×œ× ×™×•×›×œ×• לדעת מתי המכשיר ×”×–×” משמש ×ותך ב×ופן פעיל</translation>
-<translation id="4433925000917964731">â€×’רסת Lite של הדף נוצרה על ידי Google</translation>
<translation id="4434045419905280838">חלונות ×§×•×¤×¦×™× ×•×”×¤× ×™×•×ª ×וטומטיות</translation>
<translation id="445467742685312942">מתן הרש××” ל××ª×¨×™× ×œ×”×¦×™×’ תוכן מוגן</translation>
<translation id="4468959413250150279">השתקת ×¦×œ×™×œ×™× ×‘×תר ספציפי.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">מנוהל על-ידי ההורה שלך</translation>
<translation id="4670064810192446073">מצי×ות מדומה</translation>
<translation id="4708011789095599544">â€×”×× ×œ×ž×—×•×§ ×ת קובצי ×”-cookie ונתוני ×תר × ×•×¡×¤×™× ×©×œ ×תר ×–×”?</translation>
+<translation id="473775607612524610">עדכון</translation>
<translation id="4751476147751820511">חיישני תנועה ×ו ×ור</translation>
<translation id="4836046166855586901">תוצג ש×לה כש×תר יבקש לדעת מתי המכשיר ×”×–×” משמש ×ותך ב×ופן פעיל</translation>
<translation id="4883854917563148705">×œ× × ×™×ª×Ÿ ל×פס הגדרות מנוהלות</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">שיתוף ב×מצעות</translation>
<translation id="5039804452771397117">זה בסדר</translation>
<translation id="5048398596102334565">התרת גישה של ××ª×¨×™× ×ל חיישני התנועה (מומלץ)</translation>
+<translation id="5050380848339752099">×תר ×–×” עומד לשתף מידע ×¢× ×פליקציה מחוץ למצב ×”×נונימי.</translation>
<translation id="5063480226653192405">שימוש</translation>
<translation id="5100237604440890931">מכווץ – יש ללחוץ כדי להרחיב.</translation>
<translation id="5123685120097942451">כרטיסייה ×נונימית</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">â€×”תרה ל××ª×¨×™× ×œ×”×¨×™×¥ JavaScript (מומלץ)</translation>
<translation id="534295439873310000">â€×ž×›×©×™×¨×™ NFC</translation>
<translation id="5354152178998424783">â€×”פעולה הזו ×ª×’×¨×•× ×œ×ž×—×™×§×ª <ph name="DATASIZE" /> של × ×ª×•× ×™× ×•×§×•×‘×¦×™ cookie שנשמרו על ידי ×תרי×.</translation>
-<translation id="5384883051496921101">×תר ×–×” עומד לשתף מידע ×¢× ×פליקציה מחוץ למצב ×נונימי.</translation>
+<translation id="536508626067510330">לעדכן ×ת הסמל במסך הר×שי?</translation>
<translation id="5391532827096253100">החיבור שלך ל×תר ×”×–×” ×œ× ×ž×ובטח. פרטי ×”×תר</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(ועוד 1)}two{(ועוד #)}many{(ועוד #)}other{(ועוד #)}}</translation>
<translation id="5403592356182871684">שמות</translation>
<translation id="5489227211564503167">צפית ב-<ph name="ELAPSED_TIME" /> מתוך <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">חסימת מודעות ב××ª×¨×™× ×©×ž×•×¦×’×•×ª ×‘×”× ×ž×•×“×¢×•×ª מפריעות ×ו מטעות</translation>
+<translation id="549957179819296104">הסמל החדש</translation>
<translation id="5502860503640766021">פועלת: <ph name="PERMISSION_1" />, חסומה: <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">××ª×¨×™× ×œ× ×™×›×•×œ×™× ×œ×‘×§×© לשלוח התר×ות</translation>
<translation id="5516455585884385570">פתיחה של הגדרות ההתר×ות</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">הרש×ות</translation>
<translation id="5860033963881614850">כבוי</translation>
<translation id="5876056640971328065">השהיית הסרטון</translation>
+<translation id="5904826301761575486">לעדכן ×ת ×”×©× ×•×ת הסמל במסך הר×שי?</translation>
<translation id="5916664084637901428">פועל</translation>
<translation id="5922853908706496913">מתבצע שיתוף מסך</translation>
<translation id="5939518447894949180">×יפוס</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">â€×—סימת קובצי Cookie של צד שלישי</translation>
<translation id="6206551242102657620">החיבור מ×ובטח. פרטי ×”×תר</translation>
<translation id="6216432067784365534">×פשרויות של <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">סגירה ודיווח על התנהלות פוגעת</translation>
<translation id="6262279340360821358">ההרש×ות <ph name="PERMISSION_1" /> ×•×’× <ph name="PERMISSION_2" /> חסומות</translation>
<translation id="6270391203985052864">××ª×¨×™× ×™×›×•×œ×™× ×œ×‘×§×© לשלוח התר×ות</translation>
<translation id="6295158916970320988">כל ×”×תרי×</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">â€×›×“×™ ל×פשר ל-<ph name="APP_NAME" /> לגשת ×ל המיקו×, צריך להפעיל ×ת ×”×ž×™×§×•× ×’× ×‘<ph name="BEGIN_LINK" />הגדרות Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">שלילת הרש×ות מכשיר</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{â€×§×•×‘×¥ cookie ×חד × ×ž×¦× ×‘×©×™×ž×•×©}two{â€# קובצי cookie נמצ××™× ×‘×©×™×ž×•×©}many{â€# קובצי cookie נמצ××™× ×‘×©×™×ž×•×©}other{â€# קובצי cookie נמצ××™× ×‘×©×™×ž×•×©}}</translation>
-<translation id="8463851957836045671">×”×תר ×”×–×” מהיר</translation>
<translation id="8487700953926739672">זמין ×ופליין</translation>
<translation id="851751545965956758">חסימת התחברות של ××ª×¨×™× ×ל התקני×</translation>
<translation id="8525306231823319788">מסך מל×</translation>
<translation id="857943718398505171">מותרת (מומלץ)</translation>
<translation id="8609465669617005112">הזזה למעלה</translation>
+<translation id="861748745608658996">לעדכן ×ת ×”×©× ×‘×ž×¡×š הר×שי?</translation>
<translation id="8676374126336081632">ניקוי קלט</translation>
<translation id="868929229000858085">חיפוש ב×נשי הקשר</translation>
<translation id="8702612070107455751">המערכת תמחק ×ת כל ×”× ×ª×•× ×™× ×©×©×ž×•×¨×™× ×ופליין.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">התקרבות לתצוגה</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">â€×§×™×©×•×¨×™×•×ª ×”-NFC מושבתת במכשיר ×”×–×”. ניתן להפעיל ×ותה דרך <ph name="BEGIN_LINK" />הגדרות Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">רוב ×”×× ×©×™× ×ž×“×•×•×—×™× ×©×”×תר נפתח ומגיב במהירות</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">לצ×ת ממצב ×נונימי?</translation>
<translation id="8958424370300090006">â€×—סימת קובצי Cookie של ×תר מסוי×.</translation>
<translation id="8959122750345127698">הניווט ×œ× ×פשרי: <ph name="URL" /></translation>
<translation id="8986362086234534611">לשכוח</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ja.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ja.xtb
index 32465a7eb1e..469e3df757f 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ja.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ja.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ja">
<translation id="1006017844123154345">オンライン版を開ã</translation>
<translation id="1044891598689252897">サイトã¯é€šå¸¸ã©ãŠã‚Šå‹•ä½œã—ã¾ã™</translation>
+<translation id="1100504063505580045">ç¾åœ¨ã®ã‚¢ã‚¤ã‚³ãƒ³</translation>
<translation id="1124090076051167250">サイトã¾ãŸã¯ãƒ›ãƒ¼ãƒ ç”»é¢ã®ã‚¢ãƒ—リã«ã‚ˆã‚Šä¿å­˜ã•ã‚ŒãŸ <ph name="DATASIZE" /> ã®ãƒ‡ãƒ¼ã‚¿ãŠã‚ˆã³ Cookie ãŒå‰Šé™¤ã•ã‚Œã¾ã™ã€‚</translation>
<translation id="1124772482545689468">ユーザー</translation>
<translation id="1178581264944972037">一時åœæ­¢</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">マイク</translation>
<translation id="3277252321222022663">サイトã«ã‚ˆã‚‹ã‚»ãƒ³ã‚µãƒ¼ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã™ã‚‹ï¼ˆæŽ¨å¥¨ï¼‰</translation>
<translation id="3295602654194328831">情報を表示ã—ãªã„</translation>
+<translation id="3317660236277031814">インストールã—ãŸã‚¦ã‚§ãƒ–アプリã®ã‚¢ã‚¤ã‚³ãƒ³ãŒå¤‰æ›´ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
<translation id="3328801116991980348">サイト情報</translation>
<translation id="3333961966071413176">ã™ã¹ã¦ã®é€£çµ¡å…ˆ</translation>
<translation id="3386292677130313581">サイトã«ç¾åœ¨åœ°ã®èªè­˜ã‚’許å¯ã™ã‚‹å‰ã«ç¢ºèªã™ã‚‹ï¼ˆæŽ¨å¥¨ï¼‰</translation>
+<translation id="345699454248713913">インストールã—ãŸã‚¦ã‚§ãƒ–アプリã®åå‰ãŒå¤‰æ›´ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
<translation id="3538390592868664640">サイトã«ã‚ˆã‚‹å‘¨å›²ã® 3D マップã®ä½œæˆã¾ãŸã¯ã‚«ãƒ¡ãƒ©ä½ç½®ã®è¿½è·¡ã‚’ブロックã—ã¾ã™</translation>
+<translation id="3551268116566418498">シークレット モードを終了ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="3586500876634962664">カメラã¨ãƒžã‚¤ã‚¯ã®ä½¿ç”¨</translation>
<translation id="358794129225322306">複数ファイルã®è‡ªå‹•ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã‚’サイトã«è¨±å¯ã—ã¾ã™ã€‚</translation>
<translation id="3594780231884063836">動画をミュート</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">ä½ç½®æƒ…å ±ã®è¨­å®šã‚’é–‹ã</translation>
<translation id="4226663524361240545">通知をå—ã‘å–ã‚‹ã¨ãƒ‡ãƒã‚¤ã‚¹ãŒæŒ¯å‹•ã—ã¾ã™</translation>
<translation id="4259722352634471385"><ph name="URL" /> ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒãƒ–ロックã•ã‚Œã¾ã—ãŸ</translation>
+<translation id="4277239631747669329">インストールã—ãŸã‚¦ã‚§ãƒ–アプリã®åå‰ã¨ã‚¢ã‚¤ã‚³ãƒ³ãŒå¤‰æ›´ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
<translation id="4278390842282768270">許å¯</translation>
<translation id="429312253194641664">サイトã§ãƒ¡ãƒ‡ã‚£ã‚¢ãŒå†ç”Ÿã•ã‚Œã¦ã„ã¾ã™</translation>
<translation id="42981349822642051">展開</translation>
<translation id="4336434711095810371">データをã™ã¹ã¦æ¶ˆåŽ»</translation>
<translation id="4402755511846832236">サイトã«ã‚ˆã‚‹ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ–状態ã®æ¤œå‡ºã‚’ブロックã™ã‚‹</translation>
-<translation id="4433925000917964731">Google ã‹ã‚‰æä¾›ã•ã‚Œã¦ã„る軽é‡ç‰ˆã®ãƒšãƒ¼ã‚¸</translation>
<translation id="4434045419905280838">ãƒãƒƒãƒ—アップã¨ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆ</translation>
<translation id="445467742685312942">ä¿è­·ã•ã‚ŒãŸã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®å†ç”Ÿã‚’サイトã«è¨±å¯ã™ã‚‹</translation>
<translation id="4468959413250150279">特定ã®ã‚µã‚¤ãƒˆã®éŸ³å£°ã‚’ミュートã—ã¾ã™ã€‚</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">ä¿è­·è€…ã«ã‚ˆã‚Šç®¡ç†ã•ã‚Œã¦ã„ã¾ã™</translation>
<translation id="4670064810192446073">ãƒãƒ¼ãƒãƒ£ãƒ« リアリティ(VR)</translation>
<translation id="4708011789095599544">ã“ã®ã‚¦ã‚§ãƒ–サイト㮠Cookie ã¨ãã®ä»–ã®ã‚µã‚¤ãƒˆãƒ‡ãƒ¼ã‚¿ã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ</translation>
+<translation id="473775607612524610">æ›´æ–°</translation>
<translation id="4751476147751820511">モーション センサーã¾ãŸã¯å…‰ã‚»ãƒ³ã‚µãƒ¼</translation>
<translation id="4836046166855586901">サイトã‹ã‚‰ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ–状態ã®æ¤œå‡ºã‚’求ã‚られãŸã¨ãã«ç¢ºèªã™ã‚‹</translation>
<translation id="4883854917563148705">管ç†è€…ã«ã‚ˆã‚‹è¨­å®šã¯ãƒªã‚»ãƒƒãƒˆã§ãã¾ã›ã‚“</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">共有方法</translation>
<translation id="5039804452771397117">許å¯</translation>
<translation id="5048398596102334565">サイトã«ã‚ˆã‚‹ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ センサーã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã™ã‚‹ï¼ˆæŽ¨å¥¨ï¼‰</translation>
+<translation id="5050380848339752099">ã“ã®ã‚µã‚¤ãƒˆã®æƒ…å ±ãŒã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆ モードã®å¤–部ã®ã‚¢ãƒ—リã«å…±æœ‰ã•ã‚Œã‚ˆã†ã¨ã—ã¦ã„ã¾ã™ã€‚</translation>
<translation id="5063480226653192405">使用状æ³</translation>
<translation id="5100237604440890931">折りãŸãŸã¾ã‚Œã¦ã„ã¾ã™ - クリックã™ã‚‹ã¨å±•é–‹ã—ã¾ã™ã€‚</translation>
<translation id="5123685120097942451">シークレット タブ</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">サイト㫠JavaScript ã®å®Ÿè¡Œã‚’許å¯ã™ã‚‹ï¼ˆæŽ¨å¥¨ï¼‰</translation>
<translation id="534295439873310000">NFC デãƒã‚¤ã‚¹</translation>
<translation id="5354152178998424783">サイトã«ã‚ˆã‚Šä¿å­˜ã•ã‚ŒãŸ <ph name="DATASIZE" /> ã®ãƒ‡ãƒ¼ã‚¿ã¨ Cookie ãŒå‰Šé™¤ã•ã‚Œã¾ã™ã€‚</translation>
-<translation id="5384883051496921101">ã“ã®ã‚µã‚¤ãƒˆã®æƒ…å ±ãŒã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆ モードã®å¤–部ã®ã‚¢ãƒ—リã«å…±æœ‰ã•ã‚Œã‚ˆã†ã¨ã—ã¦ã„ã¾ã™ã€‚</translation>
+<translation id="536508626067510330">ホーム画é¢ã®ã‚¢ã‚¤ã‚³ãƒ³ã‚’æ›´æ–°ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="5391532827096253100">ã“ã®ã‚µã‚¤ãƒˆã¸ã®æŽ¥ç¶šã¯ä¿è­·ã•ã‚Œã¦ã„ã¾ã›ã‚“。サイト情報</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(他 1 件)}other{(他 # 件)}}</translation>
<translation id="5403592356182871684">åå‰</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" /> ã®ã†ã¡ <ph name="ELAPSED_TIME" /> 経éŽã—ã¾ã—ãŸã€‚</translation>
<translation id="5494752089476963479">ç…©ã‚ã—ã„広告や誤解を招ã広告ãŒè¡¨ç¤ºã•ã‚Œã‚‹ã‚µã‚¤ãƒˆã§åºƒå‘Šã‚’ブロックã™ã‚‹</translation>
+<translation id="549957179819296104">アイコンãŒæ–°ã—ããªã‚Šã¾ã—ãŸ</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" />を許å¯ã€<ph name="PERMISSION_2" />をブロック</translation>
<translation id="5505264765875738116">通知をé€ä¿¡ã™ã‚‹ã‹ã©ã†ã‹ã®ç¢ºèªã‚’サイトã«è¨±å¯ã—ãªã„</translation>
<translation id="5516455585884385570">通知設定を開ã</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">権é™</translation>
<translation id="5860033963881614850">オフ</translation>
<translation id="5876056640971328065">動画を一時åœæ­¢</translation>
+<translation id="5904826301761575486">ホーム画é¢ã®åå‰ã¨ã‚¢ã‚¤ã‚³ãƒ³ã‚’æ›´æ–°ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="5916664084637901428">オン</translation>
<translation id="5922853908706496913">ç”»é¢ã‚’共有ã—ã¦ã„ã¾ã™</translation>
<translation id="5939518447894949180">リセット</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">サードパーティ㮠Cookie をブロックã™ã‚‹</translation>
<translation id="6206551242102657620">接続ã¯ä¿è­·ã•ã‚Œã¦ã„ã¾ã™ã€‚サイト情報</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> ã®ã‚ªãƒ—ション</translation>
+<translation id="6260852843601447737">é–‰ã˜ã¦ä¸æ­£è¡Œç‚ºã‚’報告</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" />ã€<ph name="PERMISSION_2" />をブロック</translation>
<translation id="6270391203985052864">通知をé€ä¿¡ã™ã‚‹ã‹ã©ã†ã‹ã®ç¢ºèªã‚’サイトã«è¨±å¯ã™ã‚‹</translation>
<translation id="6295158916970320988">ã™ã¹ã¦ã®ã‚µã‚¤ãƒˆ</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> ã«ç¾åœ¨åœ°ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã™ã‚‹ã«ã¯ã€<ph name="BEGIN_LINK" />Android ã®è¨­å®š<ph name="END_LINK" />ã§ã‚‚ä½ç½®æƒ…報をオンã«ã—ã¦ãã ã•ã„。</translation>
<translation id="8447861592752582886">デãƒã‚¤ã‚¹ã®è¨±å¯ã‚’å–り消ã—ã¾ã™</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 個㮠Cookie ãŒä½¿ç”¨ä¸­ã§ã™}other{# 個㮠Cookie ãŒä½¿ç”¨ä¸­ã§ã™}}</translation>
-<translation id="8463851957836045671">サイトã¯é«˜é€Ÿã§ã™</translation>
<translation id="8487700953926739672">オフラインã§ã®åˆ©ç”¨</translation>
<translation id="851751545965956758">サイトã‹ã‚‰ãƒ‡ãƒã‚¤ã‚¹ã¸ã®æŽ¥ç¶šã‚’ブロックã™ã‚‹</translation>
<translation id="8525306231823319788">全画é¢è¡¨ç¤º</translation>
<translation id="857943718398505171">許å¯ï¼ˆæŽ¨å¥¨ï¼‰</translation>
<translation id="8609465669617005112">上ã«ç§»å‹•</translation>
+<translation id="861748745608658996">ホーム画é¢ã®åå‰ã‚’æ›´æ–°ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="8676374126336081632">入力内容を消去</translation>
<translation id="868929229000858085">連絡先を検索</translation>
<translation id="8702612070107455751">オフライン データも削除ã•ã‚Œã¾ã™ã€‚</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">拡大ã™ã‚‹</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã§ã¯ NFC ãŒã‚ªãƒ•ã«ãªã£ã¦ã„ã¾ã™ã€‚<ph name="BEGIN_LINK" />Android ã®è¨­å®š<ph name="END_LINK" />ã§ã‚ªãƒ³ã«ã—ã¦ãã ã•ã„。</translation>
-<translation id="8929372349074745002">ã“ã®ã‚µã‚¤ãƒˆã¯ã€ã»ã¨ã‚“ã©ã®ç’°å¢ƒã§ã™ã°ã‚„ã表示ã•ã‚Œå¿œç­”ã—ã¦ã„ã¾ã™</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">シークレット モードを終了ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="8958424370300090006">特定ã®ã‚µã‚¤ãƒˆã® Cookie をブロックã—ã¾ã™ã€‚</translation>
<translation id="8959122750345127698"><ph name="URL" /> ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“</translation>
<translation id="8986362086234534611">削除</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ka.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ka.xtb
index e1dcf582d13..1af3548da81 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ka.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ka.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ka">
<translation id="1006017844123154345">áƒáƒœáƒšáƒáƒ˜áƒœ-ვერსიის გáƒáƒ®áƒ¡áƒœáƒ</translation>
<translation id="1044891598689252897">სáƒáƒ˜áƒ¢áƒ”ბი ჩვეულებრივáƒáƒ“ იმუშáƒáƒ•áƒ”ბს</translation>
+<translation id="1100504063505580045">მიმდინáƒáƒ áƒ” ხáƒáƒ¢áƒ£áƒšáƒ</translation>
<translation id="1124090076051167250">áƒáƒ› მáƒáƒ¥áƒ›áƒ”დებით გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ“ებრსáƒáƒ˜áƒ¢áƒ”ბის áƒáƒœ áƒáƒžáƒ”ბის მიერ თქვენს მთáƒáƒ•áƒáƒ  ეკრáƒáƒœáƒ–ე შენáƒáƒ®áƒ£áƒšáƒ˜ მáƒáƒœáƒáƒªáƒ”მებისრდრქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რების <ph name="DATASIZE" />.</translation>
<translation id="1124772482545689468">მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბელი</translation>
<translation id="1178581264944972037">პáƒáƒ£áƒ–áƒ</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">მიკრáƒáƒ¤áƒáƒœáƒ˜</translation>
<translation id="3277252321222022663">სáƒáƒ˜áƒ¢áƒ”ბისთვის სენსáƒáƒ áƒ”ბზე წვდáƒáƒ›áƒ˜áƒ¡ დáƒáƒ¨áƒ•áƒ”ბრ(რეკáƒáƒ›áƒ”ნდებული)</translation>
<translation id="3295602654194328831">ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ დáƒáƒ›áƒáƒšáƒ•áƒ</translation>
+<translation id="3317660236277031814">ვებ-áƒáƒžáƒ›áƒ, რáƒáƒ›áƒ”ლიც დáƒáƒáƒ˜áƒœáƒ¡áƒ¢áƒáƒšáƒ˜áƒ áƒ”თ, შეიცვáƒáƒšáƒ ხáƒáƒ¢áƒ£áƒšáƒ.</translation>
<translation id="3328801116991980348">სáƒáƒ˜áƒ¢áƒ˜áƒ¡ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ</translation>
<translation id="3333961966071413176">ყველრკáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ˜</translation>
<translation id="3386292677130313581">შეკითხვრსáƒáƒ˜áƒ¢áƒ”ბისთვის თქვენი მდებáƒáƒ áƒ”áƒáƒ‘ის დáƒáƒ“გენის დáƒáƒ¨áƒ•áƒ”ბáƒáƒ›áƒ“ე (რეკáƒáƒ›áƒ”ნდებული)</translation>
+<translation id="345699454248713913">ვებ-áƒáƒžáƒ›áƒ, რáƒáƒ›áƒ”ლიც დáƒáƒáƒ˜áƒœáƒ¡áƒ¢áƒáƒšáƒ˜áƒ áƒ”თ, შეიცვáƒáƒšáƒ სáƒáƒ®áƒ”ლი.</translation>
<translation id="3538390592868664640">სáƒáƒ˜áƒ¢áƒ”ბისთვის თქვენი გáƒáƒ áƒ”მáƒáƒ¡ 3-გáƒáƒœáƒ–áƒáƒ›áƒ˜áƒšáƒ”ბიáƒáƒœáƒ˜ რუკის შექმნის áƒáƒœ კáƒáƒ›áƒ”რის პáƒáƒ–იციისთვის თვáƒáƒšáƒ˜áƒ¡ მიდევნების დáƒáƒ‘ლáƒáƒ™áƒ•áƒ</translation>
+<translation id="3551268116566418498">გáƒáƒ•áƒ˜áƒ“ეთ ინკáƒáƒ’ნიტრრეჟიმიდáƒáƒœ?</translation>
<translation id="3586500876634962664">კáƒáƒ›áƒ”რის/მიკრáƒáƒ¤áƒáƒœáƒ˜áƒ¡ გáƒáƒ›áƒáƒ§áƒ”ნებáƒ</translation>
<translation id="358794129225322306">სáƒáƒ˜áƒ¢áƒ˜áƒ¡áƒ—ვის რáƒáƒ›áƒ“ენიმე ფáƒáƒ˜áƒšáƒ˜áƒ¡ áƒáƒ•áƒ¢áƒáƒ›áƒáƒ¢áƒ£áƒ áƒáƒ“ ჩáƒáƒ›áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვის დáƒáƒ¨áƒ•áƒ”ბáƒ.</translation>
<translation id="3594780231884063836">ვიდეáƒáƒ¡ დáƒáƒ“უმებáƒ</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">მდებáƒáƒ áƒ”áƒáƒ‘ის პáƒáƒ áƒáƒ›áƒ”ტრების გáƒáƒ®áƒ¡áƒœáƒ</translation>
<translation id="4226663524361240545">შეტყáƒáƒ‘ინებებმრშეიძლებრმáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის ვიბრáƒáƒªáƒ˜áƒ გáƒáƒ›áƒáƒ˜áƒ¬áƒ•áƒ˜áƒáƒ¡</translation>
<translation id="4259722352634471385">ნáƒáƒ•áƒ˜áƒ’áƒáƒªáƒ˜áƒ დáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜áƒ: <ph name="URL" /></translation>
+<translation id="4277239631747669329">ვებ-áƒáƒžáƒ›áƒ, რáƒáƒ›áƒ”ლიც დáƒáƒáƒ˜áƒœáƒ¡áƒ¢áƒáƒšáƒ˜áƒ áƒ”თ, შეიცვáƒáƒšáƒ სáƒáƒ®áƒ”ლი დრხáƒáƒ¢áƒ£áƒšáƒ.</translation>
<translation id="4278390842282768270">დáƒáƒ¨áƒ•áƒ”ბულიáƒ</translation>
<translation id="429312253194641664">სáƒáƒ˜áƒ¢áƒ–ე გáƒáƒ¨áƒ•áƒ”ბულირმედიáƒ-კáƒáƒœáƒ¢áƒ”ნტი</translation>
<translation id="42981349822642051">გáƒáƒ¨áƒšáƒ</translation>
<translation id="4336434711095810371">ყველრმáƒáƒœáƒáƒªáƒ”მის გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒ</translation>
<translation id="4402755511846832236">სáƒáƒ˜áƒ¢áƒ”ბისთვის áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის áƒáƒ¥áƒ¢áƒ˜áƒ£áƒ áƒáƒ“ გáƒáƒ›áƒáƒ§áƒ”ნების შესáƒáƒ®áƒ”ბ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ მიღების დáƒáƒ‘ლáƒáƒ™áƒ•áƒ</translation>
-<translation id="4433925000917964731">გვერდის Lite ვერსიáƒáƒ¡ უზრუნველყáƒáƒ¤áƒ¡ Google</translation>
<translation id="4434045419905280838">áƒáƒ›áƒáƒ›áƒ®. ფáƒáƒœáƒ¯áƒ áƒ”ბი/გáƒáƒ“áƒáƒ›áƒ˜áƒ¡áƒáƒ›áƒáƒ áƒ—ებáƒ</translation>
<translation id="445467742685312942">სáƒáƒ˜áƒ¢áƒ”ბისთვის დáƒáƒªáƒ£áƒšáƒ˜ კáƒáƒœáƒ¢áƒ”ნტის დáƒáƒ™áƒ•áƒ áƒ˜áƒ¡ დáƒáƒ¨áƒ•áƒ”ბáƒ</translation>
<translation id="4468959413250150279">ხმის დáƒáƒ“უმებრკáƒáƒœáƒ™áƒ áƒ”ტული სáƒáƒ˜áƒ¢áƒ˜áƒ¡áƒ—ვის.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">იმáƒáƒ áƒ—ებრთქვენი მშáƒáƒ‘ლის მიერ</translation>
<translation id="4670064810192446073">ვირტუáƒáƒšáƒ£áƒ áƒ˜ რეáƒáƒšáƒáƒ‘áƒ</translation>
<translation id="4708011789095599544">ნáƒáƒ›áƒ“ვილáƒáƒ“ გსურთ áƒáƒ› ვებსáƒáƒ˜áƒ¢áƒ˜áƒ¡ ქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რებისრდრსხვრმáƒáƒœáƒáƒªáƒ”მების გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒ?</translation>
+<translation id="473775607612524610">გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ</translation>
<translation id="4751476147751820511">მáƒáƒ«áƒ áƒáƒáƒ‘ის áƒáƒœ გáƒáƒœáƒáƒ—ების სენსáƒáƒ áƒ”ბი</translation>
<translation id="4836046166855586901">შეკითხვáƒ, რáƒáƒªáƒ სáƒáƒ˜áƒ¢áƒ”ბს სურთ áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის áƒáƒ¥áƒ¢áƒ˜áƒ£áƒ áƒáƒ“ გáƒáƒ›áƒáƒ§áƒ”ნების შესáƒáƒ®áƒ”ბ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ მიღებáƒ</translation>
<translation id="4883854917563148705">მáƒáƒ áƒ—ული პáƒáƒ áƒáƒ›áƒ”ტრების გáƒáƒ“áƒáƒ§áƒ”ნებრვერ მáƒáƒ®áƒ”რხდებáƒ</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">გáƒáƒ–იáƒáƒ áƒ”ბის პრáƒáƒ’რáƒáƒ›áƒ</translation>
<translation id="5039804452771397117">დáƒáƒ¨áƒ•áƒ”ბáƒ</translation>
<translation id="5048398596102334565">სáƒáƒ˜áƒ¢áƒ”ბისთვის მáƒáƒ«áƒ áƒáƒáƒ‘ის სენსáƒáƒ áƒ”ბზე წვდáƒáƒ›áƒ˜áƒ¡ დáƒáƒ¨áƒ•áƒ”ბრ(რეკáƒáƒ›áƒ”ნდებული)</translation>
+<translation id="5050380848339752099">ეს სáƒáƒ˜áƒ¢áƒ˜ áƒáƒžáƒ˜áƒ áƒ”ბს, ინკáƒáƒ’ნიტრრეჟიმის გáƒáƒ áƒ”თ გáƒáƒ£áƒ–იáƒáƒ áƒáƒ¡ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ áƒáƒžáƒ¡.</translation>
<translation id="5063480226653192405">გáƒáƒ›áƒáƒ§áƒ”ნებáƒ</translation>
<translation id="5100237604440890931">ჩáƒáƒ™áƒ”ცილირ— დáƒáƒáƒ¬áƒ™áƒáƒžáƒ£áƒœáƒ”თ გáƒáƒ¡áƒáƒ¨áƒšáƒ”ლáƒáƒ“.</translation>
<translation id="5123685120097942451">ინკáƒáƒ’ნიტრჩáƒáƒœáƒáƒ áƒ—ი</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">სáƒáƒ˜áƒ¢áƒ”ბისთვის JavaScript-ის გáƒáƒ¨áƒ•áƒ”ბის დáƒáƒ¨áƒ•áƒ”ბრ(რეკáƒáƒ›áƒ”ნდებული)</translation>
<translation id="534295439873310000">NFC მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ები</translation>
<translation id="5354152178998424783">áƒáƒ› მáƒáƒ¥áƒ›áƒ”დებით გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ“ებრსáƒáƒ˜áƒ¢áƒ”ბის მიერ შენáƒáƒ®áƒ£áƒšáƒ˜ მáƒáƒœáƒáƒªáƒ”მებისრდრქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რების <ph name="DATASIZE" />.</translation>
-<translation id="5384883051496921101">ეს სáƒáƒ˜áƒ¢áƒ˜ áƒáƒžáƒ˜áƒ áƒ”ბს ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ გáƒáƒ–იáƒáƒ áƒ”ბáƒáƒ¡ áƒáƒžáƒ—áƒáƒœ ინკáƒáƒ’ნიტრრეჟიმის გáƒáƒ áƒ”თ.</translation>
+<translation id="536508626067510330">გსურთ, გáƒáƒœáƒáƒáƒ®áƒšáƒáƒ— ხáƒáƒ¢áƒ£áƒšáƒ მთáƒáƒ•áƒáƒ  ეკრáƒáƒœáƒ–ე?</translation>
<translation id="5391532827096253100">თქვენი კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜ áƒáƒ› სáƒáƒ˜áƒ¢áƒ—áƒáƒœ áƒáƒ  áƒáƒ áƒ˜áƒ¡ დáƒáƒªáƒ£áƒšáƒ˜. სáƒáƒ˜áƒ¢áƒ˜áƒ¡ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ.</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 სხვáƒ)}other{(+ # სხვáƒ)}}</translation>
<translation id="5403592356182871684">სáƒáƒ®áƒ”ლები</translation>
<translation id="5489227211564503167">გáƒáƒ•áƒ˜áƒ“რ<ph name="ELAPSED_TIME" /> / <ph name="TOTAL_TIME" />-დáƒáƒœ.</translation>
<translation id="5494752089476963479">რეკლáƒáƒ›áƒ˜áƒ¡ დáƒáƒ‘ლáƒáƒ™áƒ•áƒ იმ სáƒáƒ˜áƒ¢áƒ”ბზე, რáƒáƒ›áƒšáƒ”ბიც áƒáƒ©áƒ•áƒ”ნებს მáƒáƒ›áƒáƒ‘ეზრებელ áƒáƒœ შეცდáƒáƒ›áƒáƒ¨áƒ˜ შემყვáƒáƒœ რეკლáƒáƒ›áƒáƒ¡</translation>
+<translation id="549957179819296104">áƒáƒ®áƒáƒšáƒ˜ ხáƒáƒ¢áƒ£áƒšáƒ</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> დáƒáƒ¨áƒ•áƒ”ბულიáƒ, <ph name="PERMISSION_2" /> დáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜áƒ</translation>
<translation id="5505264765875738116">სáƒáƒ˜áƒ¢áƒ”ბი ვერ გთხáƒáƒ•áƒ— შეტყáƒáƒ‘ინებების გáƒáƒ›áƒáƒ’ზáƒáƒ•áƒœáƒáƒ¡</translation>
<translation id="5516455585884385570">შეტყáƒáƒ‘ინების პáƒáƒ áƒáƒ›áƒ”ტრების გáƒáƒ®áƒ¡áƒœáƒ</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">ნებáƒáƒ áƒ—ვები</translation>
<translation id="5860033963881614850">გáƒáƒ›áƒáƒ áƒ—ვáƒ</translation>
<translation id="5876056640971328065">ვიდეáƒáƒ¡ დáƒáƒžáƒáƒ£áƒ–ებáƒ</translation>
+<translation id="5904826301761575486">გáƒáƒœáƒáƒ®áƒšáƒ“ეს მთáƒáƒ•áƒáƒ  ეკრáƒáƒœáƒ–ე გáƒáƒ›áƒáƒ¡áƒáƒ®áƒ£áƒšáƒ˜ სáƒáƒ®áƒ”ლი დრხáƒáƒ¢áƒ£áƒšáƒ?</translation>
<translation id="5916664084637901428">ჩáƒáƒ áƒ—ვáƒ</translation>
<translation id="5922853908706496913">თქვენი ეკრáƒáƒœáƒ˜ ზიáƒáƒ áƒ“ებáƒ</translation>
<translation id="5939518447894949180">გáƒáƒ“áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვáƒ</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">მესáƒáƒ›áƒ” მხáƒáƒ áƒ˜áƒ¡ ქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რების დáƒáƒ‘ლáƒáƒ™áƒ•áƒ</translation>
<translation id="6206551242102657620">კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜ დáƒáƒªáƒ£áƒšáƒ˜áƒ. სáƒáƒ˜áƒ¢áƒ˜áƒ¡ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ.</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> — ვáƒáƒ áƒ˜áƒáƒœáƒ¢áƒ”ბი</translation>
+<translation id="6260852843601447737">დáƒáƒ®áƒ£áƒ áƒ•áƒ დრდáƒáƒ áƒ¦áƒ•áƒ”ვის შესáƒáƒ®áƒ”ბ შეტყáƒáƒ‘ინებáƒ</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> დრ<ph name="PERMISSION_2" /> დáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜áƒ</translation>
<translation id="6270391203985052864">სáƒáƒ˜áƒ¢áƒ”ბს შეუძლიáƒáƒ— შეტყáƒáƒ‘ინებების გáƒáƒ›áƒáƒ’ზáƒáƒ•áƒœáƒ˜áƒ¡ თხáƒáƒ•áƒœáƒ</translation>
<translation id="6295158916970320988">ყველრსáƒáƒ˜áƒ¢áƒ˜</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" />-მრთქვენი მდებáƒáƒ áƒ”áƒáƒ‘ით რáƒáƒ› ისáƒáƒ áƒ’ებლáƒáƒ¡, გáƒáƒáƒáƒ¥áƒ¢áƒ˜áƒ£áƒ áƒ”თ მდებáƒáƒ áƒ”áƒáƒ‘áƒáƒ–ე წვდáƒáƒ›áƒ˜áƒ¡ ნებáƒáƒ áƒ—ვáƒáƒª <ph name="BEGIN_LINK" />Android-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე წვდáƒáƒ›áƒ˜áƒ¡ ნებáƒáƒ áƒ—ვის გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნებრ1 ქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რი}other{გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნებრ# ქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რი}}</translation>
-<translation id="8463851957836045671">სáƒáƒ˜áƒ¢áƒ˜ სწრáƒáƒ¤áƒ˜áƒ</translation>
<translation id="8487700953926739672">áƒáƒ¤áƒšáƒáƒ˜áƒœáƒ¨áƒ˜ ხელმისáƒáƒ¬áƒ•áƒ“áƒáƒ›áƒ˜</translation>
<translation id="851751545965956758">სáƒáƒ˜áƒ¢áƒ”ბისთვის მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ებთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბის áƒáƒ™áƒ áƒ«áƒáƒšáƒ•áƒ</translation>
<translation id="8525306231823319788">მთელ ეკრáƒáƒœáƒ–ე</translation>
<translation id="857943718398505171">დáƒáƒ¨áƒ•áƒ”ბული (რეკáƒáƒ›áƒ”ნდებულიáƒ)</translation>
<translation id="8609465669617005112">გáƒáƒ“áƒáƒáƒ“გილებრზემáƒáƒ—</translation>
+<translation id="861748745608658996">გსურთ თქვენს მთáƒáƒ•áƒáƒ áƒ˜ ეკრáƒáƒœáƒ–ე სáƒáƒ®áƒ”ლის გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ?</translation>
<translation id="8676374126336081632">შეყვáƒáƒœáƒ˜áƒšáƒ˜ ტექსტის გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒ</translation>
<translation id="868929229000858085">თქვენს კáƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ”ბში ძიებáƒ</translation>
<translation id="8702612070107455751">გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ“ებრხáƒáƒ–გáƒáƒ áƒ”შე მáƒáƒœáƒáƒªáƒ”მები.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">მáƒáƒ¡áƒ¨áƒ¢áƒáƒ‘ის გáƒáƒ“იდებáƒ</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC გáƒáƒ›áƒáƒ áƒ—ულირáƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ისთვის. მისი ჩáƒáƒ áƒ—ვრშეგიძლიáƒáƒ— <ph name="BEGIN_LINK" />Android-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბელთრუმეტესáƒáƒ‘ისთვის ეს სáƒáƒ˜áƒ¢áƒ˜ სწრáƒáƒ¤áƒáƒ“ იხსნებრდრრეáƒáƒ’ირებს</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">გსურთ ინკáƒáƒ’ნიტრრეჟიმიდáƒáƒœ გáƒáƒ›áƒáƒ¡áƒ•áƒšáƒ?</translation>
<translation id="8958424370300090006">ქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რების დáƒáƒ‘ლáƒáƒ™áƒ•áƒ კáƒáƒœáƒ™áƒ áƒ”ტული სáƒáƒ˜áƒ¢áƒ˜áƒ¡áƒ—ვის.</translation>
<translation id="8959122750345127698">ნáƒáƒ•áƒ˜áƒ’áƒáƒªáƒ˜áƒ მიუწვდáƒáƒ›áƒ”ლიáƒ: <ph name="URL" /></translation>
<translation id="8986362086234534611">დáƒáƒ•áƒ˜áƒ¬áƒ§áƒ”ბáƒ</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_kk.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_kk.xtb
index 128ec689131..dd46bf7d08f 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_kk.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_kk.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="kk">
<translation id="1006017844123154345">Онлайн режимде ашу</translation>
<translation id="1044891598689252897">Сайттар қалыпты күйде Ð¶Ò±Ð¼Ñ‹Ñ Ñ–Ñтейді.</translation>
+<translation id="1100504063505580045">Қазіргі белгіше</translation>
<translation id="1124090076051167250">Ðегізгі Ñкрандағы Ñайттар мен қолданбаларда Ñақталған <ph name="DATASIZE" /> деректер мен cookie файлдары өшіріледі.</translation>
<translation id="1124772482545689468">Пайдаланушы</translation>
<translation id="1178581264944972037">Кідірту</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Микрофон</translation>
<translation id="3277252321222022663">Сайттардың датчиктерді пайдалануына Ñ€Ò±Ò›Ñат ету (Ò±Ñынылады)</translation>
<translation id="3295602654194328831">Ðқпаратты жаÑыру</translation>
+<translation id="3317660236277031814">Сіз орнатқан веб-қолданбаның белгішеÑÑ– өзгерді.</translation>
<translation id="3328801116991980348">Сайт ақпараты</translation>
<translation id="3333961966071413176">Барлық контакт</translation>
<translation id="3386292677130313581">Сайттар орналаÑқан орныңызды анықтау үшін Ñ€Ò±Ò›Ñат Ñұрайды (Ò±Ñынылады)</translation>
+<translation id="345699454248713913">Сіз орнатқан веб-қолданбаның атауы өзгерді.</translation>
<translation id="3538390592868664640">Сайттарға айналаңыздың 3D картаÑын жаÑауға немеÑе камера орнын бақылауға тыйым Ñалу</translation>
+<translation id="3551268116566418498">Инкогнито режимінен шығаÑыз ба?</translation>
<translation id="3586500876634962664">Камера мен микрофонды пайдалану</translation>
<translation id="358794129225322306">Сайтқа бірнеше файлды автоматты түрде жүктеу Ñ€Ò±Ò›Ñатын беру.</translation>
<translation id="3594780231884063836">Бейненің дыбыÑын өшіру</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">ОрналаÑу параметрлерін ашу</translation>
<translation id="4226663524361240545">Хабарландыру келіп Ñ‚Ò¯Ñкенде, құрылғы дірілдейді</translation>
<translation id="4259722352634471385">ÐÐ°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ Ñ‚Ñ‹Ð¹Ñ‹Ð»Ò“Ð°Ð½: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Сіз орнатқан веб-қолданбаның атауы мен белгішеÑÑ– өзгерді.</translation>
<translation id="4278390842282768270">РұқÑат етілген</translation>
<translation id="429312253194641664">Сайтта мультимедиа ойнатылуда</translation>
<translation id="42981349822642051">Жаю</translation>
<translation id="4336434711095810371">Барлық деректерді өшіру</translation>
<translation id="4402755511846832236">Сайттарды бөгеу арқылы олардың құрылғыны қашан белÑенді пайдаланғаныңыз туралы ақпаратты алуына жол берілмейді.</translation>
-<translation id="4433925000917964731">Google бетті Lite нұÑқаÑында Ò±Ñынды</translation>
<translation id="4434045419905280838">Қалқымалы терезе және бағыттау</translation>
<translation id="445467742685312942">Сайттарға қорғалған мазмұнды ойнатуға Ñ€Ò±Ò›Ñат беру</translation>
<translation id="4468959413250150279">Белгілі бір Ñайтта дыбыÑÑ‚Ñ‹ өшіру.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Ðта-ана баÑқарады</translation>
<translation id="4670064810192446073">Виртуалды шындық</translation>
<translation id="4708011789095599544">ОÑÑ‹ веб-Ñайтқа арналған cookie файлдары мен баÑқа да Ñайт деректері шынымен өшірілÑін бе?</translation>
+<translation id="473775607612524610">Жаңарту</translation>
<translation id="4751476147751820511">ÒšÐ¾Ð·Ò“Ð°Ð»Ñ‹Ñ Ð½Ðµ жарық датчиктері</translation>
<translation id="4836046166855586901">Сайт Ñіз құрылғыңызды қашан белÑенді пайдаланатыныңыз туралы білгіÑÑ– келгенде, Ñ€Ò±Ò›Ñат Ñұралады.</translation>
<translation id="4883854917563148705">БаÑқарылатын параметрлер баÑтапқы күйге қайтарылмайды.</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">БөліÑу</translation>
<translation id="5039804452771397117">РұқÑат беру</translation>
<translation id="5048398596102334565">Сайттардың Ò›Ð¾Ð·Ò“Ð°Ð»Ñ‹Ñ Ð´Ð°Ñ‚Ñ‡Ð¸ÐºÑ‚ÐµÑ€Ñ–Ð½Ðµ кіруіне Ñ€Ò±Ò›Ñат ету (Ò±Ñынылады)</translation>
+<translation id="5050380848339752099">Бұл Ñайт инкогнито режимінен Ñ‚Ñ‹Ñ Ò›Ð¾Ð»Ð´Ð°Ð½Ð±Ð°Ð¼ÐµÐ½ ақпаратты бөліÑкелі тұр.</translation>
<translation id="5063480226653192405">Пайдалану</translation>
<translation id="5100237604440890931">Жиылған – жаю үшін баÑыңыз.</translation>
<translation id="5123685120097942451">Инкогнито қойындыÑÑ‹</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Сайттарға JavaScript тілін Ñ–Ñке қоÑуға Ñ€Ò±Ò›Ñат беру (Ò±Ñынылады)</translation>
<translation id="534295439873310000">NFC функциÑÑÑ‹ бар құрылғылар</translation>
<translation id="5354152178998424783">Сайттарда Ñақталған <ph name="DATASIZE" /> деректер мен cookie файлдары өшіріледі.</translation>
-<translation id="5384883051496921101">Бұл Ñайт инкогнито режимінен Ñ‚Ñ‹Ñ Ò›Ð¾Ð»Ð´Ð°Ð½Ð±Ð°Ð¼ÐµÐ½ ақпаратты бөліÑкелі тұр.</translation>
+<translation id="536508626067510330">Ðегізгі Ñкрандағы белгіше жаңартылÑын ба?</translation>
<translation id="5391532827096253100">Бұл Ñайтпен байланыÑыңыз қорғалмаған. Сайт ақпараты</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(Тағы 1)}other{(Тағы #)}}</translation>
<translation id="5403592356182871684">Ðтаулары</translation>
<translation id="5489227211564503167">Өткен уақыт: <ph name="ELAPSED_TIME" />/<ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Мазалайтын не жалған ақпаратты жарнамалар берілетін Ñайттарда жарнамаларды бөгеу</translation>
+<translation id="549957179819296104">Жаңа белгіше</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> үшін Ñ€Ò±Ò›Ñат етілген, <ph name="PERMISSION_2" /> үшін тыйым Ñалынған.</translation>
<translation id="5505264765875738116">Сайттар хабарландырулар жіберу Ñ€Ò±Ò›Ñатын Ñұрай алмайды</translation>
<translation id="5516455585884385570">Хабарландыру параметрлерін ашу</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">РұқÑаттар</translation>
<translation id="5860033963881614850">Өшірулі</translation>
<translation id="5876056640971328065">Бейнені кідірту</translation>
+<translation id="5904826301761575486">Ðегізгі Ñкрандағы атау мен белгіше жаңартылÑын ба?</translation>
<translation id="5916664084637901428">ҚоÑулы</translation>
<translation id="5922853908706496913">Экранды бөліÑіп жатырÑыз.</translation>
<translation id="5939518447894949180">Қалпына келтіру</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Үшінші тарап cookie файлдарын бөгеу</translation>
<translation id="6206551242102657620">Ð‘Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ò›Ð¾Ñ€Ò“Ð°Ð»Ò“Ð°Ð½. Сайт ақпараты</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> опциÑлары</translation>
+<translation id="6260852843601447737">Жабу және ереже бұзу туралы хабарлау</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> және <ph name="PERMISSION_2" /> үшін тыйым Ñалынған.</translation>
<translation id="6270391203985052864">Сайттар хабарландырулар жіберу Ñ€Ò±Ò›Ñатын Ñұрай алады</translation>
<translation id="6295158916970320988">Барлық Ñайттар</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> браузері геодерегіңізді пайдалануы үшін, <ph name="BEGIN_LINK" />Android параметрлерінде<ph name="END_LINK" /> оны да қоÑыңыз.</translation>
<translation id="8447861592752582886">Құрылғыға кіру Ñ€Ò±Ò›Ñатының күшін жою</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie файлы қолданылып жатыр}other{# cookie файлы қолданылып жатыр}}</translation>
-<translation id="8463851957836045671">Бұл Ñайт жылдам.</translation>
<translation id="8487700953926739672">Желіден Ñ‚Ñ‹Ñ Ñ–Ñтейді</translation>
<translation id="851751545965956758">Сайттардың құрылғыға жалғануына тыйым Ñалу</translation>
<translation id="8525306231823319788">Толық Ñкран</translation>
<translation id="857943718398505171">РұқÑат етілген (ең дұрыÑÑ‹)</translation>
<translation id="8609465669617005112">Жоғары қарай жылжыту</translation>
+<translation id="861748745608658996">Ðегізгі Ñкрандағы атау жаңартылÑын ба?</translation>
<translation id="8676374126336081632">Енгізілгенді өшіру</translation>
<translation id="868929229000858085">Контактілеріңізді іздеңіз</translation>
<translation id="8702612070107455751">Барлық офлайн деректер өшіріледі.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Үлкейту</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">Бұл құрылғыда NFC функциÑÑÑ‹ өшірілген. Оны <ph name="BEGIN_LINK" />Android параметрлерінен<ph name="END_LINK" /> қоÑыңыз.</translation>
-<translation id="8929372349074745002">Сайт көптеген адамдар үшін жылдам ашылып, Ð¶Ò±Ð¼Ñ‹Ñ Ñ–Ñтейді.</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Инкогнито режимінен шығаÑыз ба?</translation>
<translation id="8958424370300090006">Белгілі бір Ñайт үшін cookie файлдарына тыйым Ñалыңыз.</translation>
<translation id="8959122750345127698"><ph name="URL" /> мекенжайына өту мүмкін емеÑ</translation>
<translation id="8986362086234534611">Ұмыту</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb
index 542b8402d00..3c3469d6aaf 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_km.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="km">
<translation id="1006017844123154345">បើកលើអ៊ីនធឺណិáž</translation>
<translation id="1044891598689252897">áž‚áŸáž áž‘ំពáŸážšáž“ឹងដំណើរការធម្មážáž¶</translation>
+<translation id="1100504063505580045">រូបážáŸ†ážŽáž¶áž„​បច្ចុប្បន្ន</translation>
<translation id="1124090076051167250">សកម្មភាពនáŸáŸ‡áž“ឹង​សម្អាážáž‘ិន្ននáŸáž™ áž“áž·áž„ážáž¼áž‚ីទំហំ <ph name="DATASIZE" /> ដែលគáŸáž áž‘ំពáŸážš ឬកម្មវិធី​បានរក្សាទុក​នៅលើ​អáŸáž€áŸ’រង់ដើម​របស់អ្នក។</translation>
<translation id="1124772482545689468">អ្នកប្រើ</translation>
<translation id="1178581264944972037">ផ្អាក</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">ម៉ៃក្រូហ្វូន</translation>
<translation id="3277252321222022663">អនុញ្ញាážâ€‹áž±áŸ’យ​គáŸáž áž‘ំពáŸážšâ€‹áž…ូលប្រើ​ឧបករណáŸâ€‹áž…ាប់សញ្ញា (បាន​ណែនាំ)</translation>
<translation id="3295602654194328831">លាក់ពáŸážáŸŒáž˜áž¶áž“</translation>
+<translation id="3317660236277031814">កម្មវិធីលើ​អ៊ីនធឺណិážâ€‹ážŠáŸ‚លអ្នក​បានដំឡើង​បានផ្លាស់ប្ដូរ​រូបážáŸ†ážŽáž¶áž„​របស់វា។</translation>
<translation id="3328801116991980348">áž–áŸážáŸŒáž˜áž¶áž“áž‚áŸáž áž‘ំពáŸážš</translation>
<translation id="3333961966071413176">ទំនាក់​ទំនង​ទាំងអស់</translation>
<translation id="3386292677130313581">សួរមុនពáŸáž›áž¢áž“ុញ្ញាážáž²áŸ’យគáŸáž áž‘ំពáŸážšážŸáŸ’គាល់ទីážáž¶áŸ†áž„របស់អ្នក (បានណែនាំ)</translation>
+<translation id="345699454248713913">កម្មវិធីលើ​អ៊ីនធឺណិážâ€‹ážŠáŸ‚លអ្នក​បានដំឡើង​បានផ្លាស់ប្ដូរ​ឈ្មោះរបស់វា។</translation>
<translation id="3538390592868664640">ទប់ស្កាážáŸ‹áž‚áŸáž áž‘ំពáŸážšáž˜áž·áž“ឱ្យបង្កើážáž•áŸ‚នទី 3D នៃមជ្ឈដ្ឋានជុំវិញរបស់អ្នក ឬážáž¶áž˜ážŠáž¶áž“ទីážáž¶áŸ†áž„កាមáŸážšáŸ‰áž¶</translation>
+<translation id="3551268116566418498">ចាកចáŸáž‰áž–ី​មុážáž„ារ​ឯកជន​ដែរទáŸ?</translation>
<translation id="3586500876634962664">ការប្រើមីក្រូហ្វូន និងកាមáŸážšáŸ‰áž¶</translation>
<translation id="358794129225322306">អនុញ្ញាážáž±áŸ’យ​គáŸáž áž‘ំពáŸážšáž‘ាញយក​ឯកសារជាច្រើន​ដោយស្វáŸáž™áž”្រវážáŸ’ážáž·áŸ”</translation>
<translation id="3594780231884063836">បិទ​សំឡáŸáž„​វីដáŸáž¢áž¼</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">បើកការកំណážáŸ‹áž‘ីážáž¶áŸ†áž„</translation>
<translation id="4226663524361240545">ការជូនដំណឹងអាចនឹងធ្វើឲ្យឧបករណáŸáž‰áŸážš</translation>
<translation id="4259722352634471385">ការរុករកážáŸ’រូវបានរារាំង៖ <ph name="URL" /></translation>
+<translation id="4277239631747669329">កម្មវិធីលើ​អ៊ីនធឺណិážâ€‹ážŠáŸ‚លអ្នក​បានដំឡើង​បានផ្លាស់ប្ដូរ​រូបážáŸ†ážŽáž¶áž„ និងឈ្មោះ​របស់វា។</translation>
<translation id="4278390842282768270">បានអនុញ្ញាáž</translation>
<translation id="429312253194641664">áž‚áŸáž áž‘ំពáŸážšâ€‹áž€áŸ†áž–ុង​ចាក់មáŸážŒáŸ€</translation>
<translation id="42981349822642051">ពង្រីក</translation>
<translation id="4336434711095810371">សម្អាážâ€‹áž‘ិន្ននáŸáž™â€‹áž‘ាំងអស់</translation>
<translation id="4402755511846832236">ទប់ស្កាážáŸ‹â€‹áž‚áŸáž áž‘ំពáŸážšáž˜áž·áž“ឱ្យដឹង​អំពីពáŸáž›ážœáŸáž›áž¶ážŠáŸ‚លអ្នក​កំពុងប្រើឧបករណáŸáž“áŸáŸ‡â€‹áž™áŸ‰áž¶áž„សកម្ម</translation>
-<translation id="4433925000917964731">ទំពáŸážšážŸáŸ’រាល​ដែល​ផ្ដល់​ដោយ Google</translation>
<translation id="4434045419905280838">ផ្ទាំងផុស​ និង​ការ​បញ្ជូន​បន្áž</translation>
<translation id="445467742685312942">អនុញ្ញាážáž±áŸ’យ​គáŸáž áž‘ំពáŸážšâ€‹áž…ាក់ážáŸ’លឹមសារដែលមាន​ការការពារ</translation>
<translation id="4468959413250150279">បិទសំឡáŸáž„សម្រាប់ទំពáŸážšáž‡áž¶áž€áŸ‹áž›áž¶áž€áŸ‹áŸ”</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">គ្រប់គ្រងដោយឪពុកម្ážáž¶áž™ážšáž”ស់អ្នក</translation>
<translation id="4670064810192446073">VR</translation>
<translation id="4708011789095599544">ážáž¾áž¢áŸ’នក​ពិážáž‡áž¶áž…ង់​សម្អាážážáž¼áž‚ី និងទិន្ននáŸáž™áž‚áŸáž áž‘ំពáŸážšáž•áŸ’សáŸáž„ទៀážážŸáž˜áŸ’រាប់គáŸáž áž‘ំពáŸážšáž“áŸáŸ‡áž˜áŸ‚នឬ?</translation>
+<translation id="473775607612524610">ធ្វើបច្ចុប្បន្នភាព</translation>
<translation id="4751476147751820511">ឧបករណáŸâ€‹áž…ាប់​សញ្ញាពន្លឺ ឬ​ចលនា</translation>
<translation id="4836046166855586901">សួរ​នៅពáŸáž›â€‹áž‚áŸáž áž‘ំពáŸážšâ€‹áž…ង់ដឹងអំពីពáŸáž›ážœáŸáž›áž¶ážŠáŸ‚ល​អ្នកកំពុងប្រើ​ឧបករណáŸáž“áŸáŸ‡áž™áŸ‰áž¶áž„សកម្ម</translation>
<translation id="4883854917563148705">មិនអាច​កំណážáŸ‹â€‹áž€áž¶ážšáž€áŸ†ážŽážáŸ‹â€‹ážŠáŸ‚លស្ážáž·ážáž€áŸ’រោម​ការគ្រប់គ្រង​ឡើងវិញ​បានទáŸ</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">ចែករំលែកážáž¶áž˜ážšáž™áŸˆ</translation>
<translation id="5039804452771397117">អនុញ្ញាáž</translation>
<translation id="5048398596102334565">អនុញ្ញាážáž±áŸ’យ​គáŸáž áž‘ំពáŸážšâ€‹áž…ូលប្រើ​ឧបករណáŸâ€‹áž…ាប់ចលនា (បាន​ណែនាំ)</translation>
+<translation id="5050380848339752099">áž‚áŸáž áž‘ំពáŸážšáž“áŸáŸ‡áž“ឹង​ចែករំលែក​ពáŸážáŸŒáž˜áž¶áž“ជាមួយ​កម្មវិធី​នៅក្រៅ​មុážáž„ារ​ឯកជន​បន្ážáž·áž…ទៀážáž“áŸáŸ‡áŸ”</translation>
<translation id="5063480226653192405">ការប្រើប្រាស់</translation>
<translation id="5100237604440890931">បានបំបែក - ចុចដើម្បីពង្រីក</translation>
<translation id="5123685120097942451">ផ្ទាំង​អនាមិក</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">អនុញ្ញាážáž²áŸ’យគáŸáž áž‘ំពáŸážšážŠáŸ†ážŽáž¾ážšáž€áž¶ážš JavaScript (បានណែនាំ)</translation>
<translation id="534295439873310000">ឧបករណ០NFC</translation>
<translation id="5354152178998424783">សកម្មភាពនáŸáŸ‡â€‹áž“ឹងសម្អាážáž‘ិន្ននáŸáž™ áž“áž·áž„ážáž¼áž‚ីទំហំ <ph name="DATASIZE" /> ដែលគáŸáž áž‘ំពáŸážšáž“ានាបានរក្សាទុក។</translation>
-<translation id="5384883051496921101">ទំពáŸážšáž“áŸáŸ‡â€‹ážáŸ’រៀមនឹង​ចែករំលែក​ពáŸážáŸŒáž˜áž¶áž“​ជាមួយ​កម្មវិធី​ážáž¶áž„ក្រៅ​មុážáž„ារអនាមិក។</translation>
+<translation id="536508626067510330">ប្ដូររូបážáŸ†ážŽáž¶áž„​នៅលើ​អáŸáž€áŸ’រង់ដើម​របស់អ្នក​ដែរទáŸ?</translation>
<translation id="5391532827096253100">ការážáž—្ជាប់​របស់អ្នក​ជាមួយគáŸáž áž‘ំពáŸážšâ€‹áž“áŸáŸ‡áž˜áž·áž“មាន​សុវážáŸ’ážáž·áž—ាពទáŸáŸ” áž–áŸážáŸŒáž˜áž¶áž“​អំពីគáŸáž áž‘ំពáŸážš</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 ទៀáž)}other{(+ # ទៀáž)}}</translation>
<translation id="5403592356182871684">ឈ្មោះ</translation>
<translation id="5489227211564503167">រយៈពáŸáž›â€‹ážŠáŸ‚លកន្លងផុហ<ph name="ELAPSED_TIME" /> នៃ <ph name="TOTAL_TIME" />។</translation>
<translation id="5494752089476963479">ទប់ស្កាážáŸ‹â€‹áž€áž¶ážšáž•áŸ’សាយពាណិជ្ជកម្ម​នៅលើគáŸáž áž‘ំពáŸážšâ€‹ážŠáŸ‚លបង្ហាញ​ការផ្សាយពាណិជ្ជកម្ម​នាំឱ្យយល់ច្រឡំ ឬរំážáž¶áž“</translation>
+<translation id="549957179819296104">រូបážáŸ†ážŽáž¶áž„​ážáŸ’មី</translation>
<translation id="5502860503640766021">បានអនុញ្ញាហ<ph name="PERMISSION_1" />, បានទប់ស្កាážáŸ‹ <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">áž‚áŸáž áž‘ំពáŸážšâ€‹áž˜áž·áž“អាច​ស្នើសុំ​ការអនុញ្ញាážâ€‹ážŠáž¾áž˜áŸ’បី​ផ្ញើ​ការជូន​ដំណឹង​បានទáŸ</translation>
<translation id="5516455585884385570">បើកការកំណážáŸ‹áž€áž¶ážšáž‡áž¼áž“ដំណឹង</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">ការអនុញ្ញាáž</translation>
<translation id="5860033963881614850">បិទ</translation>
<translation id="5876056640971328065">ផ្អាក​វីដáŸáž¢áž¼</translation>
+<translation id="5904826301761575486">ប្ដូរឈ្មោះ និង​រូបážáŸ†ážŽáž¶áž„​នៅលើ​អáŸáž€áŸ’រង់ដើម​របស់អ្នក​ដែរទáŸ?</translation>
<translation id="5916664084637901428">បើក</translation>
<translation id="5922853908706496913">កំពុងចែក​រំលែក​អáŸáž€áŸ’រង់​របស់​អ្នក</translation>
<translation id="5939518447894949180">កំណážáŸ‹áž¡áž¾áž„វិញ</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">រារាំង​ážáž¼áž‚ី​ភាគី​ទីបី</translation>
<translation id="6206551242102657620">ការážáž—្ជាប់​មាន​សុវážáŸ’ážáž·áž—ាព។ áž–áŸážáŸŒáž˜áž¶áž“​អំពីគáŸáž áž‘ំពáŸážš</translation>
<translation id="6216432067784365534">ជម្រើស <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">បិទ ហើយ​រាយការណáŸâ€‹áž¢áŸ†áž–ីការបំពាន</translation>
<translation id="6262279340360821358">បានទប់ស្កាážáŸ‹ <ph name="PERMISSION_1" /> áž“áž·áž„ <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">áž‚áŸáž áž‘ំពáŸážšâ€‹áž¢áž¶áž…​ស្នើសុំ​ការអនុញ្ញាážâ€‹ážŠáž¾áž˜áŸ’បី​ផ្ញើ​ការជូន​ដំណឹង</translation>
<translation id="6295158916970320988">áž‚áŸáž áž‘ំពáŸážšáž‘ាំងអស់</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">ដើម្បីអនុញ្ញាážáž±áŸ’áž™ <ph name="APP_NAME" /> ចូលប្រើទីážáž¶áŸ†áž„​របស់អ្នក អ្នកកáŸážáŸ’រូវបើក​ទីážáž¶áŸ†áž„​នៅក្នុង​<ph name="BEGIN_LINK" />ការកំណážáŸ‹ Android<ph name="END_LINK" /> ផងដែរ។</translation>
<translation id="8447861592752582886">ដកហូážážŸáž·áž‘្ធិអនុញ្ញាážáž§áž”ករណáŸ</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{កំពុងប្រើážáž¼áž‚ី 1}other{កំពុងប្រើážáž¼áž‚ី #}}</translation>
-<translation id="8463851957836045671">áž‚áŸáž áž‘ំពáŸážšâ€‹ážŠáŸ†ážŽáž¾ážšáž€áž¶ážšâ€‹áž›áž¿áž“</translation>
<translation id="8487700953926739672">មាននៅក្រៅបណ្ážáž¶áž‰</translation>
<translation id="851751545965956758">ទប់​ស្កាážáŸ‹â€‹áž‘ំពáŸážšâ€‹áž˜áž·áž“​ឱ្យ​ភ្ជាប់​ជាមួយ​ឧបករណáŸ</translation>
<translation id="8525306231823319788">áž–áŸáž‰áž¢áŸáž€áŸ’រង់</translation>
<translation id="857943718398505171">បានអនុញ្ញាហ(បានណែនាំ)</translation>
<translation id="8609465669617005112">រំកិលទៅលើ</translation>
+<translation id="861748745608658996">ប្ដូរឈ្មោះ​នៅលើ​អáŸáž€áŸ’រង់ដើម​របស់អ្នក​ដែរទáŸ?</translation>
<translation id="8676374126336081632">ជម្រះការបញ្ចូល</translation>
<translation id="868929229000858085">ស្វែងរក​ទំនាក់ទំនង​របស់អ្នក</translation>
<translation id="8702612070107455751">រាល់​​ទិន្ននáŸáž™áž‚áŸáž áž‘ំពáŸážšâ€‹ážŠáŸ‚លបានរក្សាទុកលើឧបករណáŸáž“ឹង​ážáŸ’រូវបាន​សម្អាážáŸ”</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">ពង្រីក</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC ážáŸ’រូវ​បាន​បិទសម្រាប់​ឧបករណáŸâ€‹áž“áŸáŸ‡áŸ” បើក NFC នៅក្នុង<ph name="BEGIN_LINK" />ការកំណážáŸ‹ Android<ph name="END_LINK" />។</translation>
-<translation id="8929372349074745002">áž‚áŸáž áž‘ំពáŸážšáž“áŸáŸ‡â€‹áž”ើក និងឆ្លើយážáž”យ៉ាងរហáŸážŸâ€‹ážŸáž˜áŸ’រាប់​មនុស្សភាគច្រើន</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ចាកចáŸáž‰â€‹áž–ី​មុážáž„ារ​អនាមិក?</translation>
<translation id="8958424370300090006">ទប់ស្កាážáŸ‹â€‹ážáž¼áž‚ីសម្រាប់​គáŸáž áž‘ំពáŸážšâ€‹áž‡áž¶áž€áŸ‹áž›áž¶áž€áŸ‹áŸ”</translation>
<translation id="8959122750345127698">ការុករកមិនអាចភ្ជាប់បានទáŸáŸ– <ph name="URL" /></translation>
<translation id="8986362086234534611">បំភ្លáŸáž…</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_kn.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_kn.xtb
index ed5e88095b4..3271fa87077 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_kn.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_kn.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="kn">
<translation id="1006017844123154345">ಆನà³â€Œà²²à³ˆà²¨à³â€Œà²¨à²²à³à²²à²¿ ತೆರೆಯಿರಿ</translation>
<translation id="1044891598689252897">ಸೈಟà³â€Œà²—ಳೠಸಾಮಾನà³à²¯à²µà²¾à²—ಿ ಕೆಲಸ ಮಾಡà³à²¤à³à²¤à²µà³†</translation>
+<translation id="1100504063505580045">ಪà³à²°à²¸à³à²¤à³à²¤ à²à²•à²¾à²¨à³</translation>
<translation id="1124090076051167250">ನಿಮà³à²® ಹೋಮೠಸà³à²•à³à²°à³€à²¨à³â€Œà²²à³à²²à²¿à²°à³à²µ ಆà³à²¯à²ªà³â€Œà²—ಳೠಅಥವಾ ಸೈಟà³â€Œà²—ಳ ಮೂಲಕ ಸಂಗà³à²°à²¹à²£à³† ಮಾಡಲಾಗಿರà³à²µ <ph name="DATASIZE" /> ಯಷà³à²Ÿà³ ಡೇಟಾ ಹಾಗೂ ಕà³à²•à³€à²—ಳನà³à²¨à³ ಇದೠತೆರವà³à²—ೊಳಿಸà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="1124772482545689468">ಬಳಕೆದಾರ</translation>
<translation id="1178581264944972037">ವಿರಾಮ</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">ಮೈಕà³à²°à³‹à²«à³‹à²¨à³</translation>
<translation id="3277252321222022663">ಸೆನà³à²¸à²°à³â€Œà²—ಳನà³à²¨à³ ಪà³à²°à²µà³‡à²¶à²¿à²¸à²²à³ ಸೈಟà³â€Œà²—ಳಿಗೆ ಅನà³à²®à²¤à²¿ ನೀಡಿ (ಶಿಫಾರಸೠಮಾಡಿರà³à²µà³à²¦à³)</translation>
<translation id="3295602654194328831">ಮಾಹಿತಿಯನà³à²¨à³ ಮರೆಮಾಡಿ</translation>
+<translation id="3317660236277031814">ನೀವೠಇನà³â€Œà²¸à³à²Ÿà²¾à²²à³ ಮಾಡಿದ ವೆಬೠಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³, ತನà³à²¨ à²à²•à²¾à²¨à³ ಅನà³à²¨à³ ಬದಲಾಯಿಸಿದೆ.</translation>
<translation id="3328801116991980348">ಸೈಟೠಮಾಹಿತಿ</translation>
<translation id="3333961966071413176">ಎಲà³à²²à²¾ ಸಂಪರà³à²•à²—ಳà³</translation>
<translation id="3386292677130313581">ನಿಮà³à²® ಸà³à²¥à²³à²µà²¨à³à²¨à³ ತಿಳಿಯಲೠಸೈಟà³â€Œà²—ಳಿಗೆ ಅನà³à²®à²¤à²¿à²¸à³à²µ ಮೊದಲೠಕೇಳಿ (ಶಿಫಾರಸೠಮಾಡಲಾಗಿದೆ)</translation>
+<translation id="345699454248713913">ನೀವೠಇನà³â€Œà²¸à³à²Ÿà²¾à²²à³ ಮಾಡಿದ ವೆಬೠಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³, ತನà³à²¨ ಹೆಸರನà³à²¨à³ ಬದಲಾಯಿಸಿದೆ.</translation>
<translation id="3538390592868664640">ನಿಮà³à²® ಸà³à²¤à³à²¤à²®à³à²¤à³à²¤à²²à²¿à²¨ 3D ನಕà³à²·à³†à²—ಳನà³à²¨à³ ರಚಿಸà³à²µà³à²¦à²°à²¿à²‚ದ ಅಥವಾ ಕà³à²¯à²¾à²®à²°à²¾ ಸà³à²¥à²¿à²¤à²¿à²¯à²¨à³à²¨à³ ಟà³à²°à³à²¯à²¾à²•à³ ಮಾಡà³à²µà³à²¦à²°à²¿à²‚ದ ಸೈಟà³â€Œà²—ಳನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಿ</translation>
+<translation id="3551268116566418498">ಅಜà³à²žà²¾à²¤ ಮೋಡೠತೊರೆಯà³à²µà³à²¦à³‡?</translation>
<translation id="3586500876634962664">ಕà³à²¯à²¾à²®à²°à²¾ ಮತà³à²¤à³ ಮೈಕà³à²°à³‹à²«à³‹à²¨à³ ಬಳಕೆ</translation>
<translation id="358794129225322306">ಬಹೠಫೈಲà³â€Œà²—ಳನà³à²¨à³ ಸà³à²µà²¯à²‚ಚಾಲಿತವಾಗಿ ಡೌನà³â€Œà²²à³‹à²¡à³â€Œ ಮಾಡಲೠಸೈಟà³â€Œ ಒಂದಕà³à²•à³† ಅನà³à²®à²¤à²¿à²¸à³à²µà³à²¦à³.</translation>
<translation id="3594780231884063836">ವೀಡಿಯೊ ಮà³à²¯à³‚ಟೠಮಾಡಿ</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">ಸà³à²¥à²³ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳನà³à²¨à³ ತೆರೆಯಿರಿ</translation>
<translation id="4226663524361240545">ಪà³à²°à²•à²Ÿà²£à³†à²—ಳೠಸಾಧನವನà³à²¨à³ ವೈಬà³à²°à³‡à²Ÿà³ ಮಾಡಬಹà³à²¦à³</translation>
<translation id="4259722352634471385">ನà³à²¯à²¾à²µà²¿à²—ೇಶನà³â€Œ ನಿರà³à²¬à²‚ಧಿಸಲಾಗಿದೆ: <ph name="URL" /></translation>
+<translation id="4277239631747669329">ನೀವೠಇನà³â€Œà²¸à³à²Ÿà²¾à²²à³ ಮಾಡಿದ ವೆಬೠಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³, ತನà³à²¨ ಹೆಸರೠಮತà³à²¤à³ à²à²•à²¾à²¨à³ ಅನà³à²¨à³ ಬದಲಾಯಿಸಿದೆ.</translation>
<translation id="4278390842282768270">ಅನà³à²®à²¤à²¿à²¸à²²à²¾à²—ಿದೆ</translation>
<translation id="429312253194641664">ಒಂದೠಸೈಟà³, ಮಾಧà³à²¯à²®à²µà²¨à³à²¨à³ ಪà³à²²à³‡ ಮಾಡà³à²¤à³à²¤à²¿à²¦à³†</translation>
<translation id="42981349822642051">ವಿಸà³à²¤à²°à²¿à²¸à²¿</translation>
<translation id="4336434711095810371">ಎಲà³à²²à²¾ ಡೇಟಾವನà³à²¨à³ ತೆರವà³à²—ೊಳಿಸಿ</translation>
<translation id="4402755511846832236">ನೀವೠಈ ಸಾಧನವನà³à²¨à³ ಸಕà³à²°à²¿à²¯à²µà²¾à²—ಿ ಬಳಸà³à²¤à³à²¤à²¿à²°à³à²µà²¾à²— ಸೈಟà³â€Œà²—ಳೠನಿಮà³à²® ಉಪಸà³à²¥à²¿à²¤à²¿à²¯ ಕà³à²°à²¿à²¤à³ ತಿಳಿದà³à²•à³Šà²³à³à²³à²¦à²‚ತೆ ನಿರà³à²¬à²‚ಧಿಸಿ</translation>
-<translation id="4433925000917964731">Lite ಪà³à²Ÿà²µà²¨à³à²¨à³ Google ಒದಗಿಸಿದೆ</translation>
<translation id="4434045419905280838">ಪಾಪà³-ಅಪà³â€Œà²—ಳೠಹಾಗೂ ಮರà³à²¨à²¿à²°à³à²¦à³‡à²¶à²¨à²—ಳà³</translation>
<translation id="445467742685312942">ಸಂರಕà³à²·à²¿à²¤ ವಿಷಯವನà³à²¨à³ ಪà³à²²à³‡ ಮಾಡಲೠಸೈಟà³â€Œà²—ಳಿಗೆ ಅನà³à²®à²¤à²¿ ನೀಡಿ</translation>
<translation id="4468959413250150279">ನಿರà³à²¦à²¿à²·à³à²Ÿ ಸೈಟà³â€Œà²¨ ಧà³à²µà²¨à²¿à²¯à²¨à³à²¨à³ ಮà³à²¯à³‚ಟೠಮಾಡಿ</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">ನಿಮà³à²® ಪೋಷಕರೠನಿರà³à²µà²¹à²¿à²¸à³à²¤à³à²¤à²¿à²¦à³à²¦à²¾à²°à³†</translation>
<translation id="4670064810192446073">ವರà³à²šà³à²µà²²à³ ರಿಯಾಲಿಟಿ</translation>
<translation id="4708011789095599544">ಈ ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²¨à²¿à²‚ದ ನೀವೠಕà³à²•à²¿à²—ಳೠಮತà³à²¤à³ ಇತರ ಸೈಟೠಡೇಟಾವನà³à²¨à³ ಖಂಡಿತವಾಗಿಯೂ ತೆಗೆದà³à²¹à²¾à²•à²²à³ ಬಯಸà³à²¤à³à²¤à³€à²°à²¾?</translation>
+<translation id="473775607612524610">ಅಪà³â€Œà²¡à³‡à²Ÿà³â€Œâ€Œ</translation>
<translation id="4751476147751820511">ಚಲನೆ ಅಥವಾ ಬೆಳಕಿನ ಸೆನà³à²¸à²°à³â€Œà²—ಳà³</translation>
<translation id="4836046166855586901">ನೀವೠಈ ಸಾಧನವನà³à²¨à³ ಸಕà³à²°à²¿à²¯à²µà²¾à²—ಿ ಬಳಸà³à²¤à³à²¤à²¿à²°à³à²µà²¾à²— ಸೈಟà³â€Œà²—ಳೠನಿಮà³à²® ಉಪಸà³à²¥à²¿à²¤à²¿à²¯ ಕà³à²°à²¿à²¤à³ ತಿಳಿದà³à²•à³Šà²³à³à²³à²²à³ ಬಯಸಿದಾಗ ಕೇಳಿ</translation>
<translation id="4883854917563148705">ನಿರà³à²µà²¹à²¿à²¸à²²à²¾à²—à³à²µ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳನà³à²¨à³ ಮರà³à²¹à³Šà²‚ದಿಸಲೠಸಾಧà³à²¯à²µà²¿à²²à³à²²</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">ಇದರ ಮೂಲಕ ಹಂಚಿ</translation>
<translation id="5039804452771397117">ಅನà³à²®à²¤à²¿à²¸à²¿</translation>
<translation id="5048398596102334565">ಚಲನಾ ಸೆನà³à²¸à²°à³â€Œà²—ಳನà³à²¨à³ ಪà³à²°à²µà³‡à²¶à²¿à²¸à²²à³ ಸೈಟà³â€Œà²—ಳಿಗೆ ಅನà³à²®à²¤à²¿ ನೀಡಿ (ಶಿಫಾರಸೠಮಾಡಿರà³à²µà³à²¦à³)</translation>
+<translation id="5050380848339752099">ಈ ಸೈಟà³, ಅಜà³à²žà²¾à²¤ ಮೋಡà³â€Œà²—ೆ ಸಂಬಂಧಿಸದ ಆà³à²¯à²ªà³ ಜೊತೆಗೆ ಮಾಹಿತಿಯನà³à²¨à³ ಹಂಚಿಕೊಳà³à²³à²²à²¿à²¦à³†.</translation>
<translation id="5063480226653192405">ಬಳಕೆ</translation>
<translation id="5100237604440890931">ಕà³à²—à³à²—ಿಸಲಾಗಿದೆ - ವಿಸà³à²¤à²°à²¿à²¸à²²à³ ಕà³à²²à²¿à²•à³ ಮಾಡಿ</translation>
<translation id="5123685120097942451">ಅದೃಶà³à²¯ ಟà³à²¯à²¾à²¬à³â€Œ</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">JavaScript ರನೠಮಾಡಲೠಸೈಟà³â€Œà²—ಳಿಗೆ ಅನà³à²®à²¤à²¿à²¸à²¿ (ಶಿಫಾರಸೠಮಾಡಲಾಗಿದೆ)</translation>
<translation id="534295439873310000">NFC ಸಾಧನಗಳà³</translation>
<translation id="5354152178998424783">ಇದೠಸೈಟà³â€Œà²—ಳ ಮೂಲಕ ಸಂಗà³à²°à²¹à²£à³† ಮಾಡಲಾದ <ph name="DATASIZE" /> ಯಷà³à²Ÿà³ ಡೇಟಾ ಮತà³à²¤à³ ಕà³à²•à³€à²—ಳನà³à²¨à³ ತೆರವà³à²—ೊಳಿಸà³à²¤à³à²¤à²¦à³†.</translation>
-<translation id="5384883051496921101">ಈ ಸೈಟà³, ಅಜà³à²žà²¾à²¤ ಮೋಡà³â€Œà²—ೆ ಹೊರತಾಗಿರà³à²µ ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³â€Œà²¨à³Šà²‚ದಿಗೆ ಮಾಹಿತಿಯನà³à²¨à³ ಹಂಚಿಕೊಳà³à²³à²²à²¿à²¦à³†.</translation>
+<translation id="536508626067510330">ನಿಮà³à²® ಹೋಮà³â€Œà²¸à³à²•à³à²°à³€à²¨à³â€Œà²¨à²²à³à²²à²¿ à²à²•à²¾à²¨à³ ಅನà³à²¨à³ ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಬೇಕೆ?</translation>
<translation id="5391532827096253100">ಈ ಸೈಟà³â€Œà²—ೆ ನಿಮà³à²® ಸಂಪರà³à²•à²µà³ ಸà³à²°à²•à³à²·à²¿à²¤à²µà²¾à²—ಿಲà³à²². ಸೈಟೠಮಾಹಿತಿ</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 ಹೆಚà³à²šà³)}one{(+ # ಹೆಚà³à²šà³)}other{(+ # ಹೆಚà³à²šà³)}}</translation>
<translation id="5403592356182871684">ಹೆಸರà³à²—ಳà³</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" /> ನಲà³à²²à²¿ <ph name="ELAPSED_TIME" /> ಸಮಯ ಕಳೆದಿದೆ.</translation>
<translation id="5494752089476963479">ಅನಪೇಕà³à²·à²¿à²¤ ಅಥವಾ ತಪà³à²ªà³à²¦à²¾à²°à²¿à²—ೆಳೆಯà³à²µ ಜಾಹೀರಾತà³à²—ಳನà³à²¨à³ ತೋರಿಸà³à²µ ಸೈಟà³â€Œà²—ಳಲà³à²²à²¿ ಜಾಹೀರಾತà³à²—ಳನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಿ</translation>
+<translation id="549957179819296104">ಹೊಸ à²à²•à²¾à²¨à³</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> ಅನà³à²¨à³ ಅನà³à²®à²¤à²¿à²¸à²²à²¾à²—ಿದೆ <ph name="PERMISSION_2" /> ಅನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಲಾಗಿದೆ</translation>
<translation id="5505264765875738116">ಅಧಿಸೂಚನೆಗಳನà³à²¨à³ ಕಳà³à²¹à²¿à²¸à²¬à²¹à³à²¦à³‡ ಎಂದೠಸೈಟà³â€Œà²—ಳೠಕೇಳಲೠಸಾಧà³à²¯à²µà²¿à²²à³à²²</translation>
<translation id="5516455585884385570">ಅಧಿಸೂಚನೆ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳನà³à²¨à³ ತೆರೆಯಿರಿ</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">ಅನà³à²®à²¤à²¿à²—ಳà³</translation>
<translation id="5860033963881614850">ಆಫà³</translation>
<translation id="5876056640971328065">ವೀಡಿಯೊ ವಿರಾಮಗೊಳಿಸಿ</translation>
+<translation id="5904826301761575486">ನಿಮà³à²® ಹೋಮà³â€Œà²¸à³à²•à³à²°à³€à²¨à³â€Œà²¨à²²à³à²²à²¿à²°à³à²µ ಹೆಸರೠಮತà³à²¤à³ à²à²•à²¾à²¨à³ ಅನà³à²¨à³ ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಬೇಕೆ?</translation>
<translation id="5916664084637901428">ಆನà³â€Œ</translation>
<translation id="5922853908706496913">ನಿಮà³à²® ಸà³à²•à³à²°à³€à²¨à³ ಅನà³à²¨à³ ಹಂಚಿಕೊಳà³à²³à²²à²¾à²—à³à²¤à³à²¤à²¿à²¦à³†</translation>
<translation id="5939518447894949180">ಮರà³à²¹à³Šà²‚ದಿಸà³</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">ಥರà³à²¡à³ ಪಾರà³à²Ÿà²¿ ಕà³à²•à³€à²—ಳನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಿ</translation>
<translation id="6206551242102657620">ಸಂಪರà³à²• ಸà³à²°à²•à³à²·à²¿à²¤à²µà²¾à²—ಿದೆ. ಸೈಟೠಮಾಹಿತಿ</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> ಆಯà³à²•à³†à²—ಳà³</translation>
+<translation id="6260852843601447737">ಮà³à²šà³à²šà²¿ ಮತà³à²¤à³ ನಿಂದನೆ ವರದಿ ಮಾಡಿ</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> ಮತà³à²¤à³ <ph name="PERMISSION_2" /> ಅನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಲಾಗಿದೆ</translation>
<translation id="6270391203985052864">ಅಧಿಸೂಚನೆಗಳನà³à²¨à³ ಕಳà³à²¹à²¿à²¸à²¬à²¹à³à²¦à³‡ ಎಂದೠಸೈಟà³â€Œà²—ಳೠಕೇಳಬಹà³à²¦à³</translation>
<translation id="6295158916970320988">ಎಲà³à²²à²¾ ಸೈಟà³â€Œà²—ಳà³</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> ನಿಮà³à²® ಸà³à²¥à²³à²µà²¨à³à²¨à³ ಪà³à²°à²µà³‡à²¶à²¿à²¸à³à²µà³à²¦à²•à³à²•à³† ಅನà³à²®à²¤à²¿à²¸à²²à³, <ph name="BEGIN_LINK" />Android ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿<ph name="END_LINK" /> ಸà³à²¥à²³à²µà²¨à³à²¨à³ ಸಹ ಆನೠಮಾಡಬೇಕಾಗà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="8447861592752582886">ಸಾಧನ ಅನà³à²®à²¤à²¿à²¯à²¨à³à²¨à³ ಹಿಂತೆಗೆದà³à²•à³Šà²³à³à²³à²¿</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 ಕà³à²•à²¿ ಬಳಕೆಯಲà³à²²à²¿à²¦à³†}one{# ಕà³à²•à³€à²—ಳೠಬಳಕೆಯಲà³à²²à²¿à²µà³†}other{# ಕà³à²•à³€à²—ಳೠಬಳಕೆಯಲà³à²²à²¿à²µà³†}}</translation>
-<translation id="8463851957836045671">ಸೈಟೠವೇಗವಾಗಿದೆ</translation>
<translation id="8487700953926739672">ಆಫà³â€Œà²²à³ˆà²¨à³ ಲಭà³à²¯à²µà²¿à²¦à³†</translation>
<translation id="851751545965956758">ಸಾಧನಗಳಿಗೆ ಸಂಪರà³à²•à²¿à²¸à²¦à²‚ತೆ, ಸೈಟà³â€Œà²—ಳನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಿ</translation>
<translation id="8525306231823319788">ಪೂರà³à²£ ಪರದೆ</translation>
<translation id="857943718398505171">ಅನà³à²®à²¤à²¿à²¸à²²à²¾à²—ಿದೆ (ಶಿಫಾರಸೠಮಾಡಲಾಗಿದೆ)</translation>
<translation id="8609465669617005112">ಮೇಲೆ ಸರಿಸà³</translation>
+<translation id="861748745608658996">ನಿಮà³à²® ಹೋಮà³â€Œà²¸à³à²•à³à²°à³€à²¨à³â€Œà²¨à²²à³à²²à²¿ ಹೆಸರನà³à²¨à³ ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಬೇಕೆ?</translation>
<translation id="8676374126336081632">ಇನà³â€Œà²ªà³à²Ÿà³â€Œâ€Œ ತೆರವà³à²—ೊಳಿಸà³</translation>
<translation id="868929229000858085">ನಿಮà³à²® ಸಂಪರà³à²•à²—ಳನà³à²¨à³ ಹà³à²¡à³à²•à²¿</translation>
<translation id="8702612070107455751">ಯಾವà³à²¦à³‡ ಆಫà³â€Œà²²à³ˆà²¨à³ ಡೇಟಾವನà³à²¨à³ ತೆರವà³à²—ೊಳಿಸಲಾಗà³à²¤à³à²¤à²¦à³†.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">à²à³‚ಮೠಇನà³</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">ಈ ಸಾಧನದಲà³à²²à²¿ NFC ಅನà³à²¨à³ ಆಫೠಮಾಡಲಾಗಿದೆ. ಇದನà³à²¨à³ <ph name="BEGIN_LINK" />Android ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿<ph name="END_LINK" /> ತೆರೆಯಿರಿ.</translation>
-<translation id="8929372349074745002">ಈ ಸೈಟೠಸಾಕಷà³à²Ÿà³ ಜನರಿಗೆ ತà³à²µà²°à²¿à²¤à²µà²¾à²—ಿ ತೆರೆಯà³à²¤à³à²¤à²¦à³† ಮತà³à²¤à³ ಪà³à²°à²¤à²¿à²•à³à²°à²¿à²¯à²¿à²¸à³à²¤à³à²¤à²¦à³†</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ಅದೃಶà³à²¯ ಮೋಡà³â€Œâ€Œ ತೊರೆಯà³à²µà³à²¦à³‡?</translation>
<translation id="8958424370300090006">ನಿರà³à²¦à²¿à²·à³à²Ÿ ಸೈಟà³â€Œ ಒಂದಕà³à²•à³† ಕà³à²•à³€à²—ಳನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಿ.</translation>
<translation id="8959122750345127698">ನà³à²¯à²¾à²µà²¿à²—ೇಶನà³â€Œ ತಲà³à²ªà²²à²¾à²—à³à²µà³à²¦à²¿à²²à³à²²: <ph name="URL" /></translation>
<translation id="8986362086234534611">ಮರೆತà³à²¹à³‹à²—à³</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ko.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ko.xtb
index de3ed27d7bf..4c2fc31cf4f 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ko.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ko.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ko">
<translation id="1006017844123154345">온ë¼ì¸ 열기</translation>
<translation id="1044891598689252897">사ì´íŠ¸ê°€ ì •ìƒì ìœ¼ë¡œ ìž‘ë™í•©ë‹ˆë‹¤.</translation>
+<translation id="1100504063505580045">현재 ì•„ì´ì½˜</translation>
<translation id="1124090076051167250">ì´ë ‡ê²Œ 하면 사ì´íŠ¸ ë˜ëŠ” 홈 í™”ë©´ì˜ ì•±ì—ì„œ 저장한 <ph name="DATASIZE" />ì˜ ë°ì´í„° ë° ì¿ í‚¤ê°€ ì‚­ì œë©ë‹ˆë‹¤.</translation>
<translation id="1124772482545689468">사용ìž</translation>
<translation id="1178581264944972037">ì¼ì‹œì¤‘지</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">마ì´í¬</translation>
<translation id="3277252321222022663">사ì´íŠ¸ì˜ 센서 액세스 허용(권장)</translation>
<translation id="3295602654194328831">정보 숨기기</translation>
+<translation id="3317660236277031814">설치한 웹 ì•±ì˜ ì•„ì´ì½˜ì´ 변경ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
<translation id="3328801116991980348">사ì´íŠ¸ ì •ë³´</translation>
<translation id="3333961966071413176">모든 ì—°ë½ì²˜</translation>
<translation id="3386292677130313581">사ì´íŠ¸ì—ì„œ ë‚´ 위치를 파악하ë„ë¡ í—ˆìš©í•˜ê¸° ì „ì— í™•ì¸(권장)</translation>
+<translation id="345699454248713913">설치한 웹 ì•±ì˜ ì´ë¦„ì´ ë³€ê²½ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
<translation id="3538390592868664640">사ì´íŠ¸ì—ì„œ 주변 í™˜ê²½ì˜ 3D 지ë„를 ìƒì„±í•˜ê±°ë‚˜ ì¹´ë©”ë¼ ìœ„ì¹˜ë¥¼ 추ì í•˜ì§€ 못하ë„ë¡ ì°¨ë‹¨</translation>
+<translation id="3551268116566418498">ì‹œí¬ë¦¿ 모드를 종료하시겠습니까?</translation>
<translation id="3586500876634962664">ì¹´ë©”ë¼ ë° ë§ˆì´í¬ 사용</translation>
<translation id="358794129225322306">사ì´íŠ¸ì—ì„œ 여러 파ì¼ì„ ìžë™ìœ¼ë¡œ 다운로드하ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤.</translation>
<translation id="3594780231884063836">ë™ì˜ìƒ ìŒì†Œê±°</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">위치 설정 열기</translation>
<translation id="4226663524361240545">ì•Œë¦¼ì´ ìžˆìœ¼ë©´ 진ë™ì´ 울릴 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤.</translation>
<translation id="4259722352634471385">íƒìƒ‰ì´ 차단ë¨: <ph name="URL" /></translation>
+<translation id="4277239631747669329">설치한 웹 ì•±ì˜ ì´ë¦„ê³¼ ì•„ì´ì½˜ì´ 변경ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
<translation id="4278390842282768270">허용</translation>
<translation id="429312253194641664">사ì´íŠ¸ì—ì„œ 미디어 ìž¬ìƒ ì¤‘</translation>
<translation id="42981349822642051">펼치기</translation>
<translation id="4336434711095810371">모든 ë°ì´í„° ì‚­ì œ</translation>
<translation id="4402755511846832236">사용ìžê°€ 현재 기기를 사용 중ì¸ì§€ 사ì´íŠ¸ì—ì„œ ì•Œ 수 ì—†ë„ë¡ ì°¨ë‹¨í•©ë‹ˆë‹¤.</translation>
-<translation id="4433925000917964731">Googleì—ì„œ 제공하는 ë¼ì´íŠ¸ 페ì´ì§€</translation>
<translation id="4434045419905280838">íŒì—… ë° ë¦¬ë””ë ‰ì…˜</translation>
<translation id="445467742685312942">사ì´íŠ¸ì—ì„œ ë³´í˜¸ëœ ì½˜í…츠를 재ìƒí•˜ë„ë¡ í—ˆìš©</translation>
<translation id="4468959413250150279">특정 사ì´íŠ¸ë¥¼ ìŒì†Œê±°í•©ë‹ˆë‹¤.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">ë¶€ëª¨ë‹˜ì´ ê´€ë¦¬í•©ë‹ˆë‹¤.</translation>
<translation id="4670064810192446073">ê°€ìƒ í˜„ì‹¤</translation>
<translation id="4708011789095599544">ì´ ì›¹ì‚¬ì´íŠ¸ì˜ 쿠키 ë° ê¸°íƒ€ 사ì´íŠ¸ ë°ì´í„°ë¥¼ 삭제하시겠습니까?</translation>
+<translation id="473775607612524610">ì—…ë°ì´íŠ¸</translation>
<translation id="4751476147751820511">모션 ë˜ëŠ” ì¡°ë„ ì„¼ì„œ</translation>
<translation id="4836046166855586901">사용ìžê°€ 현재 기기를 사용 중ì¸ì§€ 사ì´íŠ¸ì—ì„œ ì•Œê³ ìž í•  ë•Œ 확ì¸</translation>
<translation id="4883854917563148705">관리 ì„¤ì •ì€ ìž¬ì„¤ì •í•  수 없습니다.</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">공유 방법</translation>
<translation id="5039804452771397117">허용</translation>
<translation id="5048398596102334565">사ì´íŠ¸ì˜ 움ì§ìž„ ê°ì§€ 센서 액세스 허용(권장)</translation>
+<translation id="5050380848339752099">ì´ ì‚¬ì´íŠ¸ì—ì„œ ì‹œí¬ë¦¿ 모드 ì™¸ë¶€ì˜ ì•±ì„ ì‚¬ìš©í•˜ì—¬ 정보를 공유하려고 합니다.</translation>
<translation id="5063480226653192405">사용</translation>
<translation id="5100237604440890931">접힘 - 펼치려면 í´ë¦­</translation>
<translation id="5123685120097942451">ì‹œí¬ë¦¿ 탭</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">사ì´íŠ¸ì—ì„œ ìžë°”스í¬ë¦½íŠ¸ë¥¼ 실행하ë„ë¡ í—ˆìš©(권장)</translation>
<translation id="534295439873310000">NFC 기기</translation>
<translation id="5354152178998424783">사ì´íŠ¸ì—ì„œ 저장한 <ph name="DATASIZE" />ì˜ ë°ì´í„°ì™€ 쿠키가 ì‚­ì œë©ë‹ˆë‹¤.</translation>
-<translation id="5384883051496921101">ì´ ì‚¬ì´íŠ¸ì—ì„œ ì‹œí¬ë¦¿ 모드 ì™¸ë¶€ì˜ ì•±ì„ ì‚¬ìš©í•˜ì—¬ 정보를 공유하려고 합니다.</translation>
+<translation id="536508626067510330">홈 화면ì—ì„œ ì•„ì´ì½˜ì„ ì—…ë°ì´íŠ¸í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="5391532827096253100">ì´ ì‚¬ì´íŠ¸ì™€ì˜ ì—°ê²°ì€ ì•ˆì „í•˜ì§€ 않습니다. 사ì´íŠ¸ ì •ë³´</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(외 1개)}other{(외 #개)}}</translation>
<translation id="5403592356182871684">ì´ë¦„</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" /> 중 <ph name="ELAPSED_TIME" /> 경과</translation>
<translation id="5494752089476963479">ë°©í•´ê°€ ë˜ê±°ë‚˜ 사용ìžë¥¼ 현혹하는 광고를 표시하는 사ì´íŠ¸ì˜ ê´‘ê³  차단</translation>
+<translation id="549957179819296104">새로운 ì•„ì´ì½˜</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> 허용ë¨, <ph name="PERMISSION_2" /> 차단ë¨</translation>
<translation id="5505264765875738116">사ì´íŠ¸ì—ì„œ 알림 전송 í—ˆìš©ì„ ìš”ì²­í•  수 ì—†ìŒ</translation>
<translation id="5516455585884385570">알림 설정 열기</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">권한</translation>
<translation id="5860033963881614850">사용 안함</translation>
<translation id="5876056640971328065">ë™ì˜ìƒ ì¼ì‹œì¤‘지</translation>
+<translation id="5904826301761575486">홈 화면ì—ì„œ ì´ë¦„ê³¼ ì•„ì´ì½˜ì„ ì—…ë°ì´íŠ¸í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="5916664084637901428">사용</translation>
<translation id="5922853908706496913">화면 공유</translation>
<translation id="5939518447894949180">초기화</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">타사 쿠키 차단</translation>
<translation id="6206551242102657620">ì´ ì‚¬ì´íŠ¸ì™€ì˜ ì—°ê²°ì€ ì•ˆì „í•©ë‹ˆë‹¤. 사ì´íŠ¸ ì •ë³´</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> 옵션</translation>
+<translation id="6260852843601447737">ë‹«ì€ í›„ 악용사례 ì‹ ê³ </translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> ë° <ph name="PERMISSION_2" /> 차단ë¨</translation>
<translation id="6270391203985052864">사ì´íŠ¸ì—ì„œ 알림 전송 í—ˆìš©ì„ ìš”ì²­í•  수 있ìŒ</translation>
<translation id="6295158916970320988">모든 사ì´íŠ¸</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" />ì—ì„œ 위치 ì •ë³´ì— ì•¡ì„¸ìŠ¤í•˜ë„ë¡ í—ˆìš©í•˜ë ¤ë©´ <ph name="BEGIN_LINK" />Android 설정<ph name="END_LINK" />ì—ì„œë„ ìœ„ì¹˜ë¥¼ 사용 설정하세요.</translation>
<translation id="8447861592752582886">기기 액세스 권한 취소</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{쿠키 1개 사용 중}other{쿠키 #개 사용 중}}</translation>
-<translation id="8463851957836045671">사ì´íŠ¸ ì†ë„ 빠름</translation>
<translation id="8487700953926739672">오프ë¼ì¸ìœ¼ë¡œ 사용 가능</translation>
<translation id="851751545965956758">사ì´íŠ¸ì—ì„œ ê¸°ê¸°ì— ì—°ê²°í•˜ì§€ 못하ë„ë¡ ì°¨ë‹¨</translation>
<translation id="8525306231823319788">전체화면</translation>
<translation id="857943718398505171">허용(권장)</translation>
<translation id="8609465669617005112">위로 ì´ë™</translation>
+<translation id="861748745608658996">홈 화면ì—ì„œ ì´ë¦„ì„ ì—…ë°ì´íŠ¸í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="8676374126336081632">입력내용 지우기</translation>
<translation id="868929229000858085">ì—°ë½ì²˜ 검색</translation>
<translation id="8702612070107455751">모든 오프ë¼ì¸ ë°ì´í„°ê°€ ì‚­ì œë©ë‹ˆë‹¤.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">확대</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">기기ì—ì„œ NFCê°€ 사용 중지ë˜ì–´ 있습니다. <ph name="BEGIN_LINK" />Android 설정<ph name="END_LINK" />ì—ì„œ NFC를 사용 설정하세요.</translation>
-<translation id="8929372349074745002">ì´ ì‚¬ì´íŠ¸ëŠ” ëŒ€ë¶€ë¶„ì˜ ì‚¬ìš©ìžë¥¼ 대ìƒìœ¼ë¡œ 빠르게 열리고 ì‘답합니다.</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ì‹œí¬ë¦¿ 모드를 종료할까요?</translation>
<translation id="8958424370300090006">특정 사ì´íŠ¸ì˜ 쿠키를 차단합니다.</translation>
<translation id="8959122750345127698">íƒìƒ‰í•  수 ì—†ìŒ: <ph name="URL" /></translation>
<translation id="8986362086234534611">저장 안함</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ky.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ky.xtb
index b096b1cb2f4..7198992dc06 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ky.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ky.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ky">
<translation id="1006017844123154345">Онлайнда ачуу</translation>
<translation id="1044891598689252897">Сайттар кадимкидей иштейт</translation>
+<translation id="1100504063505580045">Учурдагы Ñүрөтчө</translation>
<translation id="1124090076051167250">Ушуну менен Ñайттар жана колдонмолор Башкы Ñкраныңызда Ñактаган маалымат менен cookie файлдар ÑÑлеп турган <ph name="DATASIZE" /> орун бошотулат.</translation>
<translation id="1124772482545689468">Колдонуучу</translation>
<translation id="1178581264944972037">Бир азга токтотуу</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Микрофон</translation>
<translation id="3277252321222022663">Сайттарга ÑенÑорлорду колдонууга урукÑат берүү (Ñунушталат)</translation>
<translation id="3295602654194328831">Маалыматты жашыруу</translation>
+<translation id="3317660236277031814">Орноткон веб колдонмоңуз ÑүрөтчөÑүн өзгөрттү.</translation>
<translation id="3328801116991980348">Сайт жөнүндө маалымат</translation>
<translation id="3333961966071413176">Бардык байланыштар</translation>
<translation id="3386292677130313581">Сайттарга жайгашкан жериңиз тууралуу маалымат берүүдөн мурун урукÑат ÑуралÑын (Ñунушталат)</translation>
+<translation id="345699454248713913">Орноткон веб колдонмоңуз аталышын өзгөрттү.</translation>
<translation id="3538390592868664640">Сайттарга айланаңыздын 3D картаÑын түзүүгө же камераңыздын абалына көз Ñалууга бөгөт коюуңуз</translation>
+<translation id="3551268116566418498">Жашыруун режимден чыгаÑызбы?</translation>
<translation id="3586500876634962664">Камера менен микрофонду колдонуу</translation>
<translation id="358794129225322306">Сайтка бир нече файлды автоматтык түрдө жүктөп алууга урукÑат берүү.</translation>
<translation id="3594780231884063836">Видеонун үнүн баÑуу</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Жайгашкан жерди аныктоо жөндөөлөрүн ачуу</translation>
<translation id="4226663524361240545">Билдирмелер кегенде түзмөк дирилдейт</translation>
<translation id="4259722352634471385">Чабыттоо бөгөттөлгөн: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Орноткон веб колдонмоңуз аталышын жана ÑүрөтчөÑүн өзгөрттү.</translation>
<translation id="4278390842282768270">УрукÑат берилген</translation>
<translation id="429312253194641664">Сайтта медиа файл ойнотулууда</translation>
<translation id="42981349822642051">Жайып көрÑÓ©Ñ‚Ò¯Ò¯</translation>
<translation id="4336434711095810371">Бардык маалыматты өчүрүү</translation>
<translation id="4402755511846832236">Түзмөгүңүз активдүү колдонулуп жаткан учур Ñайттардан жашырылÑын</translation>
-<translation id="4433925000917964731">Барактын lite-верÑиÑÑÑ‹ Google аркылуу алынган.</translation>
<translation id="4434045419905280838">Калкыма терезелер жана багыттоолор</translation>
<translation id="445467742685312942">Сайттарга корголгон мазмунду ойнотууга урукÑат берүү</translation>
<translation id="4468959413250150279">Белгилүү бир Ñайттын үнүн өчүрүү.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Ðта-Ñнеңиз башкарат</translation>
<translation id="4670064810192446073">Виртуалдык дүйнө</translation>
<translation id="4708011789095599544">Бул вебÑайттын cookie файлдары жана башка маалыматы чын Ñле тазаланÑынбы?</translation>
+<translation id="473775607612524610">Жаңыртуу</translation>
<translation id="4751476147751820511">Кыймыл же жарык ÑенÑорлору</translation>
<translation id="4836046166855586901">Сайт түзмөктү активдүү колдонуп жаткан учур тууралуу билгиÑи келгенде урукÑат ÑуралÑын</translation>
<translation id="4883854917563148705">Башкарылган жөндөөлөрдү баштапкы абалга келтирүүгө болбойт</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Төмөнкү аркылуу бөлүшүү</translation>
<translation id="5039804452771397117">УрукÑат берүү</translation>
<translation id="5048398596102334565">Сайттарга ÑенÑорлорду колдонууга урукÑат берүү (Ñунушталат)</translation>
+<translation id="5050380848339752099">Бул Ñайт жашыруун режимден Ñырткары колдонмо менен маалыматты бөлүшкөнү жатат.</translation>
<translation id="5063480226653192405">Колдонулушу</translation>
<translation id="5100237604440890931">Жыйналган – жайып көрÑÓ©Ñ‚Ò¯Ò¯ үчүн чыкылдатыңыз.</translation>
<translation id="5123685120097942451">Жашыруун өтмөк</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Сайттарга JavaScript'ти иштетүүгө урукÑат берилÑин (Ñунушталат)</translation>
<translation id="534295439873310000">NFC түзмөктөрү</translation>
<translation id="5354152178998424783">Ушуну менен маалымат жана cookie-файлдары ÑÑлеп турган <ph name="DATASIZE" /> орун бошотулат.</translation>
-<translation id="5384883051496921101">Бул Ñайт жашыруун режиминен Ñырткары колдонмо менен маалыматты бөлүшкөнү турат.</translation>
+<translation id="536508626067510330">Башкы Ñкраныңыздагы Ñүрөтчө жаңыртылÑынбы?</translation>
<translation id="5391532827096253100">Бул Ñайтка туташуу корголгон ÑмеÑ. Сайт тууралуу маалымат</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ дагы 1)}other{(+ дагы #)}}</translation>
<translation id="5403592356182871684">ЫÑымдар</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" /> ичинен <ph name="ELAPSED_TIME" /> өттү.</translation>
<translation id="5494752089476963479">Тажатма же адаштыруучу жарнамаларды көрÑөткөн Ñайттан келген жарнамалар бөгөттөлÑүн</translation>
+<translation id="549957179819296104">Жаңы Ñүрөтчө</translation>
<translation id="5502860503640766021">УрукÑат берилген: <ph name="PERMISSION_1" />. Бөгөттөлгөн: <ph name="PERMISSION_2" />.</translation>
<translation id="5505264765875738116">Сайттар билдирмелерди жөнөтүүнү Ñурана алышпайт</translation>
<translation id="5516455585884385570">Билдирменин жөндөөлөрүн ачуу</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">УрукÑаттар</translation>
<translation id="5860033963881614850">Өчүк</translation>
<translation id="5876056640971328065">Видеону тындыруу</translation>
+<translation id="5904826301761575486">Башкы Ñкраныңыздагы аталышы жана ÑүрөтчөÑÒ¯ жаңыртылÑынбы?</translation>
<translation id="5916664084637901428">Күйүк</translation>
<translation id="5922853908706496913">Экраныңыз бөлүшүлүүдө</translation>
<translation id="5939518447894949180">Кайра коюу</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Үчүнчү жактын кукилери бөгөттөлÑүн</translation>
<translation id="6206551242102657620">Туташуу корголгон. Сайт тууралуу маалымат</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> Параметрлер</translation>
+<translation id="6260852843601447737">Жаап, Ñрежелерди бузуу тууралуу кабар берүү</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> жана <ph name="PERMISSION_2" /> бөгөттөлдү</translation>
<translation id="6270391203985052864">Сайттар билдирмелерди жөнөтүүнү Ñурана алышат</translation>
<translation id="6295158916970320988">Бардык Ñайттар</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> колдонмоÑуна жайгашкан жериңизге кирүүгө урукÑат берүү үчүн, <ph name="BEGIN_LINK" />Android Жөндөөлөрүнөн<ph name="END_LINK" /> жайгашкан жер кызматын күйгүзүңүз.</translation>
<translation id="8447861592752582886">Түзмөккө болгон урукÑатты жоюу</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie файлы колдонулууда}other{# cookie файлы колдонулууда}}</translation>
-<translation id="8463851957836045671">Сайт тез жүктөлөт</translation>
<translation id="8487700953926739672">Оффлайнда жеткиликтүү</translation>
<translation id="851751545965956758">Сайттардын түзмөктөргө туташууÑун бөгөттөө</translation>
<translation id="8525306231823319788">Толук Ñкран</translation>
<translation id="857943718398505171">УрукÑат берилген (Ñунушталат)</translation>
<translation id="8609465669617005112">Өйдө жылуу</translation>
+<translation id="861748745608658996">Ðталышы башкы Ñкраныңызда жаңыртылÑынбы?</translation>
<translation id="8676374126336081632">Киргизилген нерÑени тазалоо</translation>
<translation id="868929229000858085">Байланыштарыңызды издеңиз</translation>
<translation id="8702612070107455751">Оффлайн режиминдеги бардык дайын-даректер өчүрүлөт.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Чоңойтуу</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC бул түзмөктө өчүрүлгөн. <ph name="BEGIN_LINK" />Android жөндөөлөрүнө<ph name="END_LINK" /> өтүп, аны күйгүзүңүз.</translation>
-<translation id="8929372349074745002">Ðдатта бул Ñайт тез ачылат</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Жашыруун режимден чыгаÑызбы?</translation>
<translation id="8958424370300090006">Белгилүү бир Ñайттын cookie файлдарын бөгөттөө.</translation>
<translation id="8959122750345127698">Чабыттоо жеткиликÑиз: <ph name="URL" /></translation>
<translation id="8986362086234534611">Унутуу</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lo.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lo.xtb
index d674ebf6285..a7b684cccf8 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lo.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lo.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="lo">
<translation id="1006017844123154345">ເປີດອອນລາàº</translation>
<translation id="1044891598689252897">ເວັບໄຊຈະເຮັດວຽàºà»„ດ້ປົàºàºàº°àº•àº´</translation>
+<translation id="1100504063505580045">ໄອຄອນປັດຈຸບັນ</translation>
<translation id="1124090076051167250">ນີ້ຈະລຶບລ້າງຂà»à»‰àº¡àº¹àº™ <ph name="DATASIZE" /> à»àº¥àº° ຄຸàºàºàºµà»‰àº—ັງà»àº»àº”ທີ່ເàºàº±àºšà»„ວ້ໂດàºà»€àº§àº±àºšà»„ຊ ຫຼື à»àº­àº±àºšà»ƒàº™à»œà»‰àº²àºˆà»àº«àº¼àº±àºàº‚ອງທ່ານ.</translation>
<translation id="1124772482545689468">ຜູ້​ໃຊ້</translation>
<translation id="1178581264944972037">ຢຸດຊົ່ວຄາວ</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">ໄມໂຄຣໂຟນ</translation>
<translation id="3277252321222022663">ອະນຸàºàº²àº”ໃຫ້ເວັບໄຊເຂົ້າເຖິງເຊັນເຊີ (à»àº™àº°àº™àº³)</translation>
<translation id="3295602654194328831">ເຊື່ອງຂà»à»‰àº¡àº¹àº™</translation>
+<translation id="3317660236277031814">ເວັບà»àº­àº±àºšàº—ີ່ທ່ານຕິດຕັ້ງໄວ້ໄດ້ປ່ຽນໄອຄອນຂອງມັນà»àº¥à»‰àº§.</translation>
<translation id="3328801116991980348">ຂà»à»‰â€‹àº¡àº¹àº™â€‹à»€àº§àº±àºšâ€‹à»„ຊທ໌</translation>
<translation id="3333961966071413176">ລາàºàºŠàº·à»ˆàºœàº¹à»‰àº•àº´àº”ຕà»à»ˆàº—ັງà»àº»àº”</translation>
<translation id="3386292677130313581">ຖາມàºà»ˆàº­àº™àº—ີ່ຈະອະນຸàºàº²àº”ໃຫ້ເວັບໄຊຮູ້ສະຖານທີ່ຂອງທ່ານ (à»àº™àº°àº™àº³)</translation>
+<translation id="345699454248713913">ເວັບà»àº­àº±àºšàº—ີ່ທ່ານຕິດຕັ້ງໄວ້ໄດ້ປ່ຽນຊື່ຂອງມັນà»àº¥à»‰àº§.</translation>
<translation id="3538390592868664640">ບລັອàºà»€àº§àº±àºšà»„ຊບà»à»ˆà»ƒàº«à»‰àºªà»‰àº²àº‡à»àºœàº™àº—ີ່ 3 ມິຕິຂອງສິ່ງທີ່ຢູ່ອ້ອມຂ້າງຕົວທ່ານ ຫຼື ຕິດຕາມຕຳà»à»œà»ˆàº‡àºà»‰àº­àº‡</translation>
+<translation id="3551268116566418498">ອອàºàºˆàº²àºà»‚à»àº”ບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™àºšà»?</translation>
<translation id="3586500876634962664">àºàº²àº™àº™àº³à»ƒàºŠà»‰àºà»‰àº­àº‡ à»àº¥àº° ໄມໂຄຣໂຟນ</translation>
<translation id="358794129225322306">ອະນຸàºàº²àº”ໃຫ້ເວັບໄຊດາວໂຫຼດຫຼາàºà»„ຟລ໌ໂດàºàº­àº±àº”ຕະໂນມັດ.</translation>
<translation id="3594780231884063836">ປິດສຽງວິດີໂອ</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">ເປີດàºàº²àº™àº•àº±à»‰àº‡àº„່າສະຖານທີ່</translation>
<translation id="4226663524361240545">àºàº²àº™à»àºˆà»‰àº‡à»€àº•àº·àº­àº™àº­àº²àº”ຈະເຮັດໃຫ້ອຸປະàºàº­àº™àºªàº±à»ˆàº™</translation>
<translation id="4259722352634471385">àºàº²àº™àº™à»àº²àº—າງຖືàºàºšàº¥àº±àº­àºà»„ວ້: <ph name="URL" /></translation>
+<translation id="4277239631747669329">ເວັບà»àº­àº±àºšàº—ີ່ທ່ານຕິດຕັ້ງໄວ້ໄດ້ປ່ຽນຊື່ à»àº¥àº° ໄອຄອນຂອງມັນà»àº¥à»‰àº§.</translation>
<translation id="4278390842282768270">ອະນຸàºàº²àº”à»àº¥à»‰àº§</translation>
<translation id="429312253194641664">ເວັບໄຊàºàº³àº¥àº±àº‡àº«àº¼àº´à»‰àº™àºªàº·à»ˆàº¢àº¹à»ˆ</translation>
<translation id="42981349822642051">ຂະ​ຫàºàº²àº</translation>
<translation id="4336434711095810371">ລຶບລ້າງຂà»à»‰àº¡àº¹àº™àº—ັງà»àº»àº”</translation>
<translation id="4402755511846832236">ບລັອàºàºšà»à»ˆà»ƒàº«à»‰à»€àº§àº±àºšà»„ຊຮູ້ໃນເວລາທີ່ທ່ານàºàº³àº¥àº±àº‡à»ƒàºŠà»‰àº­àº¸àº›àº°àºàº­àº™àº™àºµà»‰àº¢àº¹à»ˆ</translation>
-<translation id="4433925000917964731">ໜ້າ Lite ທີ່ Google ສະໜອງໃຫ້</translation>
<translation id="4434045419905280838">ປັອບອັບ à»àº¥àº° àºàº²àº™àº›à»ˆàº½àº™à»€àºªàº±à»‰àº™àº—າງ</translation>
<translation id="445467742685312942">ອະນຸàºàº²àº”ໃຫ້ເວັບໄຊຫຼິ້ນເນື້ອຫາທີ່ໄດ້ຮັບàºàº²àº™àº›àº»àºàº›à»‰àº­àº‡</translation>
<translation id="4468959413250150279">ປິດສຽງສຳລັບເວັບໄຊສະເພາະໃດໜຶ່ງ.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">ຈັດ​àºàº²àº™â€‹à»‚ດàºâ€‹àºœàº¹à»‰â€‹àº›àº»àºâ€‹àº„ອງ​ຂອງ​ທ່ານ</translation>
<translation id="4670064810192446073">ເວີຊົວ ຣິອາຣິທີ</translation>
<translation id="4708011789095599544">ທ່ານà»àº™à»ˆà»ƒàºˆàºšà»à»ˆàº§à»ˆàº²àº—່ານຕ້ອງàºàº²àº™àº¥àº¶àºšàº„ຸàºàºàºµà»‰ à»àº¥àº° ຂà»à»‰àº¡àº¹àº™à»€àº§àº±àºšà»„ຊອື່ນສຳລັບເວັບໄຊນີ້?</translation>
+<translation id="473775607612524610">ອັບເດດ</translation>
<translation id="4751476147751820511">ເຊັນເຊີàºàº§àº”ຈັບàºàº²àº™à»€àº„ື່ອນໄຫວ ຫຼື à»àºªàº‡</translation>
<translation id="4836046166855586901">ຖາມເມື່ອເວັບໄຊຕ້ອງàºàº²àº™àº®àº¹à»‰à»€àº¡àº·à»ˆàº­àº—່ານàºàº³àº¥àº±àº‡à»ƒàºŠà»‰àº­àº¸àº›àº°àºàº­àº™àº™àºµà»‰àº¢àº¹à»ˆ</translation>
<translation id="4883854917563148705">ບà»à»ˆàºªàº²àº¡àº²àº”ຣີເຊັດàºàº²àº™àº•àº±à»‰àº‡àº„່າທີ່ມີàºàº²àº™àºˆàº±àº”àºàº²àº™à»„ດ້</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">à»àºŠàº£à»Œàºœà»ˆàº²àº™</translation>
<translation id="5039804452771397117">ອະ​ນຸ​àºàº²àº”​</translation>
<translation id="5048398596102334565">ອະນຸàºàº²àº”ໃຫ້ເວັບໄຊເຂົ້າເຖິງເຊັນເຊີàºàº§àº”ຈັບàºàº²àº™à»€àº„ື່ອນໄຫວ (à»àº™àº°àº™àº³)</translation>
+<translation id="5050380848339752099">ເວັບໄຊນີ້àºàº³àº¥àº±àº‡àºˆàº°à»àºšà»ˆàº‡àº›àº±àº™àº‚à»à»‰àº¡àº¹àº™àºàº±àºšà»àº­àº±àºšàº™àº­àºà»‚à»àº”ບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™.</translation>
<translation id="5063480226653192405">àºàº²àº™àº™à»àº²à»ƒàºŠà»‰</translation>
<translation id="5100237604440890931">ຫàºà»à»‰àº¥àº»àº‡à»àº¥à»‰àº§ - ຄລິàºâ€‹à»€àºžàº·à»ˆàº­â€‹àº‚ະ​ຫàºàº²àº.</translation>
<translation id="5123685120097942451">à»àº–ບທີ່ບà»à»ˆà»€àºœàºµàºàº•àº»àº§àº•àº»àº™</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">ອະນຸàºàº²àº”ໃຫ້ເວັບໄຊເປີດໃຊ້ JavaScript (à»àº™àº°àº™àº³)</translation>
<translation id="534295439873310000">ອຸປະàºàº­àº™ NFC</translation>
<translation id="5354152178998424783">ນີ້ຈະລຶບລ້າງຂà»à»‰àº¡àº¹àº™ <ph name="DATASIZE" /> à»àº¥àº° ຄຸàºàºàºµà»‰àº—ັງà»àº»àº”ທີ່ເàºàº±àºšà»„ວ້ໂດàºà»€àº§àº±àºšà»„ຊ.</translation>
-<translation id="5384883051496921101">ເວັບໄຊນີ້àºàº³àº¥àº±àº‡àºˆàº°à»àºšà»ˆàº‡àº›àº±àº™àº‚à»à»‰àº¡àº¹àº™àºàº±àºšà»àº­àº±àºšàº—ີ່ຢູ່ພາàºàº™àº­àºà»‚à»àº”ບà»à»ˆà»€àºœàºµàºàº•àº»àº§àº•àº»àº™.</translation>
+<translation id="536508626067510330">ອັບເດດໄອຄອນຢູ່ໜ້າຈà»àº«àº¼àº±àºàº‚ອງທ່ານບà»?</translation>
<translation id="5391532827096253100">àºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆàº‚ອງທ່ານàºàº±àºšà»€àº§àº±àºšà»„ຊນີ້ບà»à»ˆàº›àº­àº”ໄພ. ຂà»à»‰àº¡àº¹àº™à»€àº§àº±àºšà»„ຊ</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(ອີຠ1 ລາàºàºàº²àº™)}other{(ອີຠ# ລາàºàºàº²àº™)}}</translation>
<translation id="5403592356182871684">ຊື່</translation>
<translation id="5489227211564503167">ເວລາຜ່ານໄປ <ph name="ELAPSED_TIME" /> ຈາàºàº—ັງà»àº»àº” <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">ບລັອàºà»‚ຄສະນາໃນເວັບໄຊທີ່ສະà»àº”ງໂຄສະນາທີ່ລົບàºàº§àº™ ຫຼື ຫຼອàºàº¥àº§àº‡</translation>
+<translation id="549957179819296104">ໄອຄອນໃà»à»ˆ</translation>
<translation id="5502860503640766021">ອະນຸàºàº²àº” <ph name="PERMISSION_1" /> à»àº¥à»‰àº§, ບລັອຠ<ph name="PERMISSION_2" /> ໄວ້à»àº¥à»‰àº§</translation>
<translation id="5505264765875738116">ເວັບໄຊບà»à»ˆàºªàº²àº¡àº²àº”ຂà»à»ƒàº«à»‰àºªàº»à»ˆàº‡àºàº²àº™à»àºˆà»‰àº‡à»€àº•àº·àº­àº™à»„ດ້</translation>
<translation id="5516455585884385570">ເປີດàºàº²àº™àº•àº±à»‰àº‡àº„່າàºàº²àº™à»àºˆà»‰àº‡à»€àº•àº·àº­àº™</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">àºàº²àº™â€‹àº­àº°â€‹àº™àº¸â€‹àºàº²àº”</translation>
<translation id="5860033963881614850">ປິດ</translation>
<translation id="5876056640971328065">ຢຸດວິດີໂອໄວ້ຊົ່ວຄາວ</translation>
+<translation id="5904826301761575486">ອັບເດດຊື່ à»àº¥àº° ໄອຄອນຢູ່ໜ້າຈà»àº«àº¼àº±àºàº‚ອງທ່ານບà»?</translation>
<translation id="5916664084637901428">ເປີດ</translation>
<translation id="5922853908706496913">àºàº³àº¥àº±àº‡à»àºšà»ˆàº‡àº›àº±àº™à»œà»‰àº²àºˆà»àº‚ອງທ່ານ</translation>
<translation id="5939518447894949180">ຕັ້ງຄ່າຄືນໃà»à»ˆ</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">ບລັອàºàº„ຸàºàºàºµà»‰àºžàº²àºàºªà»ˆàº§àº™àº—ີສາມ</translation>
<translation id="6206551242102657620">àºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆàº›àº­àº”ໄພ. ຂà»à»‰àº¡àº¹àº™à»€àº§àº±àºšà»„ຊ</translation>
<translation id="6216432067784365534">ຕົວເລືອຠ<ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">ປິດ à»àº¥àº° ລາàºàº‡àº²àº™àºàº²àº™àº¥àº°à»€àº¡àºµàº”</translation>
<translation id="6262279340360821358">ບລັອຠ<ph name="PERMISSION_1" /> à»àº¥àº° <ph name="PERMISSION_2" /> ໄວ້à»àº¥à»‰àº§</translation>
<translation id="6270391203985052864">ເວັບໄຊສາມາດຂà»à»ƒàº«à»‰àºªàº»à»ˆàº‡àºàº²àº™à»àºˆà»‰àº‡à»€àº•àº·àº­àº™à»„ດ້</translation>
<translation id="6295158916970320988">ທຸàºâ€‹à»€àº§àº±àºšâ€‹à»„ຊ​ທ໌</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">ເພື່ອອະນຸàºàº²àº”ໃຫ້ <ph name="APP_NAME" /> ເຂົ້າເຖິງສະຖານທີ່ຂອງທ່ານ, àºàº°àº¥àº¸àº™àº²à»€àº›àºµàº”ສະຖານທີ່ໃນ <ph name="BEGIN_LINK" />àºàº²àº™àº•àº±à»‰àº‡àº„່າ Android<ph name="END_LINK" /> ນຳ.</translation>
<translation id="8447861592752582886">ຖອນàºàº²àº™àº­àº°àº™àº¸àºàº²àº”ອຸປະàºàº­àº™</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{ມີàºàº²àº™àº™àº³à»ƒàºŠà»‰àº„ຸàºàºàºµà»‰ 1 ລາàºàºàº²àº™}other{ມີàºàº²àº™àº™àº³à»ƒàºŠà»‰àº„ຸàºàºàºµà»‰ # ລາàºàºàº²àº™}}</translation>
-<translation id="8463851957836045671">ເວັບໄຊໄວດີ</translation>
<translation id="8487700953926739672">ມີອອຟລາàºàº™à»Œàº¢àº¹à»ˆ</translation>
<translation id="851751545965956758">ບລັອàºàºšà»à»ˆà»ƒàº«à»‰à»€àº§àº±àºšà»„ຊເຊື່ອມຕà»à»ˆàºàº±àºšàº­àº¸àº›àº°àºàº­àº™</translation>
<translation id="8525306231823319788">ເຕັມຫນ້າ​ຈà»â€‹</translation>
<translation id="857943718398505171">ອະ​ນຸ​àºàº²àº”​à»àº¥à»‰àº§ (à»àº™àº°â€‹àº™àº³â€‹à»ƒàº«à»‰)</translation>
<translation id="8609465669617005112">àºà»‰àº²àºàº‚ຶ້ນ</translation>
+<translation id="861748745608658996">ອັບເດດຊື່ຢູ່ໜ້າຈà»àº«àº¼àº±àºàº‚ອງທ່ານບà»?</translation>
<translation id="8676374126336081632">ລຶບàºàº²àº™àº›à»‰àº­àº™à»€àº‚ົ້າ</translation>
<translation id="868929229000858085">ຊອàºàº«àº²àº¥àº²àºàºŠàº·à»ˆàºœàº¹à»‰àº•àº´àº”ຕà»à»ˆàº‚ອງທ່ານ</translation>
<translation id="8702612070107455751">ລະບົບຈະລຶບລ້າງຂà»à»‰àº¡àº¹àº™àº­àº­àºšàº¥àº²àºàº•à»ˆàº²àº‡à»†.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">ຊຸມເຂົ້າ</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC ປິດຢູ່ສຳລັບອຸປະàºàº­àº™àº™àºµà»‰. àºàº°àº¥àº¸àº™àº²à»€àº›àºµàº”ມັນໃນ <ph name="BEGIN_LINK" />àºàº²àº™àº•àº±à»‰àº‡àº„່າ Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">ເວັບໄຊນີ້ເປີດ à»àº¥àº° ຕອບສະໜອງຢ່າງວ່ອງໄວສຳລັບຄົນສ່ວນໃຫàºà»ˆ</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ອອàºàºˆàº²àºà»‚à»àº”ທີ່ບà»à»ˆà»€àºœàºµàºàº•àº»àº§àº•àº»àº™àºšà»?</translation>
<translation id="8958424370300090006">ບລັອàºàº„ຸàºàºàºµà»‰àºªàº³àº¥àº±àºšà»€àº§àº±àºšà»„ຊສະເພາະ.</translation>
<translation id="8959122750345127698">àºàº²àº™àº™àº³àº—າງà»àº¡à»ˆàº™àºšà»à»ˆàºªàº²àº¡àº²àº”ເຂົ້າເຖິງໄດ້: <ph name="URL" /></translation>
<translation id="8986362086234534611">ລືມ</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lt.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lt.xtb
index 0411c1b6e7a..e6dee3e3ba0 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lt.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lt.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="lt">
<translation id="1006017844123154345">Atidaryti prisijungus</translation>
<translation id="1044891598689252897">Svetainės veiks įprastai</translation>
+<translation id="1100504063505580045">DabartinÄ— piktograma</translation>
<translation id="1124090076051167250">Tai atlikus bus išvalyta <ph name="DATASIZE" /> svetainių ar programų jūsų pagrindiniame ekrane saugomų duomenų ir slapukų.</translation>
<translation id="1124772482545689468">Naudotojas</translation>
<translation id="1178581264944972037">Pristabdyti</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofonas</translation>
<translation id="3277252321222022663">Leidžiama svetainėms pasiekti jutiklius (rekomenduojama)</translation>
<translation id="3295602654194328831">SlÄ—pti informacijÄ…</translation>
+<translation id="3317660236277031814">Žiniatinklio programa, kurią įdiegėte, pakeitė piktogramą.</translation>
<translation id="3328801116991980348">SvetainÄ—s informacija</translation>
<translation id="3333961966071413176">Visi kontaktai</translation>
<translation id="3386292677130313581">Klausti prieš leidžiant svetainėms žinoti vietą (rekomenduojama)</translation>
+<translation id="345699454248713913">Žiniatinklio programa, kurią įdiegėte, pakeitė pavadinimą.</translation>
<translation id="3538390592868664640">Blokuoti, kad svetainės nekurtų jūsų aplinkos 3D žemėlapio ir nestebėtų kameros padėties</translation>
+<translation id="3551268116566418498">Išjungti inkognito režimą?</translation>
<translation id="3586500876634962664">Kameros ir mikrofono naudojimas</translation>
<translation id="358794129225322306">Leisti svetainei automatiškai atsisiųsti kelis failus.</translation>
<translation id="3594780231884063836">Nutildyti vaizdo įrašą</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Atidaryti vietovÄ—s nustatymus</translation>
<translation id="4226663524361240545">Gavus pranešimą įrenginys gali vibruoti</translation>
<translation id="4259722352634471385">Naršymas užblokuotas: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Žiniatinklio programa, kurią įdiegėte, pakeitė pavadinimą ir piktogramą.</translation>
<translation id="4278390842282768270">Leidžiama</translation>
<translation id="429312253194641664">Svetainėje leidžiama medija</translation>
<translation id="42981349822642051">IÅ¡skleisti</translation>
<translation id="4336434711095810371">IÅ¡valyti visus duomenis</translation>
<translation id="4402755511846832236">Neleisti svetainėms žinoti, kada aktyviai naudojate šį įrenginį</translation>
-<translation id="4433925000917964731">Supaprastintasis puslapis, kurį teikia „Google“</translation>
<translation id="4434045419905280838">IÅ¡Å¡ok. langai ir peradresavimai</translation>
<translation id="445467742685312942">Leisti svetainėms leisti saugomą turinį</translation>
<translation id="4468959413250150279">KonkreÄios svetainÄ—s garso iÅ¡jungimas.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Tvarko vienas iš jūsų tėvų</translation>
<translation id="4670064810192446073">Virtualioji realybÄ—</translation>
<translation id="4708011789095599544">Ar tikrai norite išvalyti šios svetainės slapukus ir kitus svetainės duomenis?</translation>
+<translation id="473775607612524610">Atnaujinti</translation>
<translation id="4751476147751820511">Judesio arba Å¡viesos jutikliai</translation>
<translation id="4836046166855586901">Klausti, kai svetainė nori žinoti, kada aktyviai naudojate šį įrenginį</translation>
<translation id="4883854917563148705">Tvarkomų nustatymų negalima nustatyti iš naujo</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Bendrinti per</translation>
<translation id="5039804452771397117">Leisti</translation>
<translation id="5048398596102334565">Leidžiama svetainėms pasiekti judesio jutiklius (rekomenduojama)</translation>
+<translation id="5050380848339752099">Šioje svetainėje ketinama bendrinti informaciją su programa ne inkognito režimu.</translation>
<translation id="5063480226653192405">Naudojimas</translation>
<translation id="5100237604440890931">Sutraukta – spustelėkite, kad išskleistumėte</translation>
<translation id="5123685120097942451">Inkognito skirtukas</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Leisti svetainėms paleisti „JavaScript“ (rekomenduojama)</translation>
<translation id="534295439873310000">ALR įrenginiai</translation>
<translation id="5354152178998424783">Tai atlikus bus išvalyta <ph name="DATASIZE" /> svetainių saugomų duomenų ir slapukų.</translation>
-<translation id="5384883051496921101">Šioje svetainėje ketinama bendrinti informaciją su programa ne inkognito režimu.</translation>
+<translation id="536508626067510330">Atnaujinti piktogramÄ… pagrindiniame ekrane?</translation>
<translation id="5391532827096253100">Ryšys su šia svetaine nėra saugus. Svetainės informacija</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(ir dar 1)}one{(ir dar #)}few{(ir dar #)}many{(ir dar #)}other{(ir dar #)}}</translation>
<translation id="5403592356182871684">Pavadinimai</translation>
<translation id="5489227211564503167">Praėjęs laikas: <ph name="ELAPSED_TIME" /> iš <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blokuoti skelbimus svetainÄ—se, kuriose rodomi nepageidaujami arba klaidinantys skelbimai</translation>
+<translation id="549957179819296104">Nauja piktograma</translation>
<translation id="5502860503640766021">Leidžiama: <ph name="PERMISSION_1" />, užblokuota: <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Svetainės negali prašyti siųsti pranešimus</translation>
<translation id="5516455585884385570">Atidaryti pranešimų nustatymus</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Leidimai</translation>
<translation id="5860033963881614850">IÅ¡jungta</translation>
<translation id="5876056640971328065">Pristabdyti vaizdo įrašą</translation>
+<translation id="5904826301761575486">Atnaujinti pavadinimÄ… ir piktogramÄ… pagrindiniame ekrane?</translation>
<translation id="5916664084637901428">Įjungta</translation>
<translation id="5922853908706496913">Bendrinamas ekranas</translation>
<translation id="5939518447894949180">Nustatyti iš naujo</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokuoti treÄiosios Å¡alies slapukus</translation>
<translation id="6206551242102657620">Ryšys yra saugus. Svetainės informacija</translation>
<translation id="6216432067784365534">„<ph name="NAME_OF_LIST_ITEM" />“ parinktys</translation>
+<translation id="6260852843601447737">Uždaryti ir pranešti apie piktnaudžiavimą</translation>
<translation id="6262279340360821358">Užblokuota: <ph name="PERMISSION_1" /> ir <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Svetainės gali prašyti siųsti pranešimus</translation>
<translation id="6295158916970320988">Visos svetainÄ—s</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Norėdami leisti „<ph name="APP_NAME" />“ pasiekti jūsų vietovę, taip pat įjunkite ją <ph name="BEGIN_LINK" />„Android“ nustatymuose<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Anuliuoti įrenginio leidimą</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Naudojamas 1 slapukas}one{Naudojamas # slapukas}few{Naudojami # slapukai}many{Naudojama # slapuko}other{Naudojama # slapukų}}</translation>
-<translation id="8463851957836045671">SvetainÄ— veikia sparÄiai</translation>
<translation id="8487700953926739672">Pasiekiama neprisijungus</translation>
<translation id="851751545965956758">Blokuoti svetaines, kad nebūtų galima prisijungti prie įrenginių</translation>
<translation id="8525306231823319788">Viso ekrano režimas</translation>
<translation id="857943718398505171">Leidžiama (rekomenduojama)</translation>
<translation id="8609465669617005112">Perkelti į viršų</translation>
+<translation id="861748745608658996">Atnaujinti pavadinimÄ… pagrindiniame ekrane?</translation>
<translation id="8676374126336081632">Išvalyti įvestą tekstą</translation>
<translation id="868929229000858085">Ieškokite savo kontaktuose</translation>
<translation id="8702612070107455751">Visi neprisijungus pasiekiami duomenys bus išvalyti.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Artinti</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">ALR išjungtas šiame įrenginyje. Įjunkite ALR <ph name="BEGIN_LINK" />„Android“ nustatymuose<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Ši svetainė daugumai žmonių atsidaro ir reaguoja greitai</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Išjungti inkognito režimą?</translation>
<translation id="8958424370300090006">Blokuoti konkreÄios svetainÄ—s slapukus.</translation>
<translation id="8959122750345127698">Naršymas nepasiekiamas: <ph name="URL" /></translation>
<translation id="8986362086234534611">Pamiršti</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lv.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lv.xtb
index dc57b9e7383..aa237e7199a 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lv.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_lv.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="lv">
<translation id="1006017844123154345">Atvērt tiešsaistē</translation>
<translation id="1044891598689252897">Vietnes darbosies normÄli</translation>
+<translation id="1100504063505580045">PaÅ¡reizÄ“jÄ ikona</translation>
<translation id="1124090076051167250">Tiks notÄ«rÄ«ti dati un sÄ«kfaili (<ph name="DATASIZE" />), ko glabÄ vietnes vai lietotnes jÅ«su sÄkuma ekrÄnÄ.</translation>
<translation id="1124772482545689468">LietotÄjs</translation>
<translation id="1178581264944972037">Pauzēt</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofons</translation>
<translation id="3277252321222022663">Atļaut vietnēm piekļūt sensoriem (ieteicams)</translation>
<translation id="3295602654194328831">SlÄ“pt informÄciju</translation>
+<translation id="3317660236277031814">Jūsu instalētai tīmekļa lietotnei tika nomainīta ikona.</translation>
<translation id="3328801116991980348">Vietnes informÄcija</translation>
<translation id="3333961966071413176">Visas kontaktpersonas</translation>
<translation id="3386292677130313581">JautÄt, pirms atļaut vietnÄ“m uzzinÄt jÅ«su atraÅ¡anÄs vietu (ieteicams)</translation>
+<translation id="345699454248713913">Jūsu instalētai tīmekļa lietotnei tika nomainīts nosaukums.</translation>
<translation id="3538390592868664640">Neļaut vietnÄ“m izveidot jÅ«su apkÄrtnes 3D karti vai izsekot kameras pozÄ«ciju</translation>
+<translation id="3551268116566418498">Vai iziet no inkognito režīma?</translation>
<translation id="3586500876634962664">Kameras un mikrofona izmantošana</translation>
<translation id="358794129225322306">Atļaut vietnei automÄtiski lejupielÄdÄ“t vairÄkus failus.</translation>
<translation id="3594780231884063836">Izslēgt video skaņu</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">AtvÄ“rt atraÅ¡anÄs vietu iestatÄ«jumus</translation>
<translation id="4226663524361240545">Saņemot paziņojumu, ierīce var vibrēt.</translation>
<translation id="4259722352634471385">NavigÄcija ir bloÄ·Ä“ta: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Jūsu instalētai tīmekļa lietotnei tika nomainīts nosaukums un ikona.</translation>
<translation id="4278390842282768270">Atļauts</translation>
<translation id="429312253194641664">Vietne atskaņo multivides saturu</translation>
<translation id="42981349822642051">Izvērst</translation>
<translation id="4336434711095810371">Notīrīt visus datus</translation>
<translation id="4402755511846832236">NerÄdÄ«t vietnÄ“m, kad jÅ«s aktÄ«vi lietojat Å¡o ierÄ«ci</translation>
-<translation id="4433925000917964731">VienkÄrÅ¡ota lapa, ko nodroÅ¡ina Google</translation>
<translation id="4434045419905280838">Uznirstošie elem. un novirzīšana</translation>
<translation id="445467742685312942">Ä»aut vietnÄ“m atskaņot aizsargÄtu saturu</translation>
<translation id="4468959413250150279">Izslēgt skaņu noteiktai vietnei</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">PÄrvalda viens no jÅ«su vecÄkiem</translation>
<translation id="4670064810192446073">VirtuÄlÄ realitÄte</translation>
<translation id="4708011789095599544">Vai tieÅ¡Äm vÄ“laties notÄ«rÄ«t Å¡Ä«s vietnes sÄ«kfailus un citus datus?</translation>
+<translation id="473775607612524610">AtjauninÄt</translation>
<translation id="4751476147751820511">Kustību vai gaismas sensori</translation>
<translation id="4836046166855586901">VaicÄt, ja vietne vÄ“las zinÄt, kad jÅ«s aktÄ«vi lietojat Å¡o ierÄ«ci</translation>
<translation id="4883854917563148705">PÄrvaldÄ«tos iestatÄ«jumus nevar atiestatÄ«t</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Kopīgošanas veids:</translation>
<translation id="5039804452771397117">Atļaut</translation>
<translation id="5048398596102334565">Atļaut vietnēm piekļūt kustību sensoriem (ieteicams)</translation>
+<translation id="5050380848339752099">Å Ä« vietne tÅ«lÄ«t kopÄ«gos informÄciju ar lietotni, kas nav inkognito režīmÄ.</translation>
<translation id="5063480226653192405">Lietojums</translation>
<translation id="5100237604440890931">Sakļauts — noklikšķiniet, lai izvērstu.</translation>
<translation id="5123685120097942451">Inkognito cilne</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Atļaut vietnēm izmantot JavaScript (ieteicams)</translation>
<translation id="534295439873310000">NFC ierīces</translation>
<translation id="5354152178998424783">Tiks dzÄ“sti dati un vietnÄ“s uzglabÄtie sÄ«kfaili (<ph name="DATASIZE" />).</translation>
-<translation id="5384883051496921101">Å Ä« vietne kopÄ«gos informÄciju ar lietotni, kas nav inkognito režīmÄ.</translation>
+<translation id="536508626067510330">Vai atjauninÄt ikonu sÄkuma ekrÄnÄ?</translation>
<translation id="5391532827096253100">Savienojums ar Å¡o vietni nav droÅ¡s. Vietnes informÄcija</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(un vēl 1)}zero{(un vēl #)}one{(un vēl #)}other{(un vēl #)}}</translation>
<translation id="5403592356182871684">Nosaukumi</translation>
<translation id="5489227211564503167">PagÄjuÅ¡ais laiks: <ph name="ELAPSED_TIME" /> (no <ph name="TOTAL_TIME" />)</translation>
<translation id="5494752089476963479">BloÄ·Ä“t reklÄmas vietnÄ“s, kurÄs tiek rÄdÄ«tas traucÄ“joÅ¡as vai maldinoÅ¡as reklÄmas</translation>
+<translation id="549957179819296104">JaunÄ ikona</translation>
<translation id="5502860503640766021">Atļauta: <ph name="PERMISSION_1" />, bloķēta: <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Vietnēs nevar lūgt atļauju sūtīt paziņojumus</translation>
<translation id="5516455585884385570">Atvērt paziņojumu iestatījumus</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Atļaujas</translation>
<translation id="5860033963881614850">Izsl.</translation>
<translation id="5876056640971328065">Apturēt video atskaņošanu</translation>
+<translation id="5904826301761575486">Vai atjauninÄt nosaukumu un ikonu sÄkuma ekrÄnÄ?</translation>
<translation id="5916664084637901428">Iesl.</translation>
<translation id="5922853908706496913">Notiek jÅ«su ekrÄna kopÄ«goÅ¡ana</translation>
<translation id="5939518447894949180">Atiestatīt</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Bloķēt trešo pušu sīkfailus</translation>
<translation id="6206551242102657620">Savienojums ir droÅ¡s. Vietnes informÄcija</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" />: iespējas</translation>
+<translation id="6260852843601447737">AizvÄ“rt un ziņot par ļaunprÄtÄ«gu izmantoÅ¡anu</translation>
<translation id="6262279340360821358">BloÄ·Ä“tas: <ph name="PERMISSION_1" /> un <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Vietnēs var lūgt atļauju sūtīt paziņojumus</translation>
<translation id="6295158916970320988">Visas vietnes</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Lai atļautu lietotnei <ph name="APP_NAME" /> piekļūt jÅ«su atraÅ¡anÄs vietas datiem, ieslÄ“dziet atraÅ¡anÄs vietas noteikÅ¡anu arÄ« <ph name="BEGIN_LINK" />Android iestatÄ«jumos<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Atsaukt ierīces atļauju</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Tiek izmantots viens sīkfails}zero{Tiek izmantoti # sīkfaili}one{Tiek izmantots # sīkfails}other{Tiek izmantoti # sīkfaili}}</translation>
-<translation id="8463851957836045671">Ātra vietnes darbība</translation>
<translation id="8487700953926739672">Pieejams bezsaistē</translation>
<translation id="851751545965956758">Neļaut vietnēm izveidot savienojumu ar ierīci</translation>
<translation id="8525306231823319788">PilnekrÄna režīms</translation>
<translation id="857943718398505171">Atļauta (ieteicams)</translation>
<translation id="8609465669617005112">Virziet uz augšu</translation>
+<translation id="861748745608658996">Vai atjauninÄt nosaukumu sÄkuma ekrÄnÄ?</translation>
<translation id="8676374126336081632">Notīrīt ievadi</translation>
<translation id="868929229000858085">Meklējiet kontaktpersonas</translation>
<translation id="8702612070107455751">Visi bezsaistÄ“ saglabÄtie dati tiks notÄ«rÄ«ti.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">TuvinÄt</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">Å ajÄ ierÄ«cÄ“ tehnoloÄ£ija NFC ir izslÄ“gta. IeslÄ“dziet to <ph name="BEGIN_LINK" />Android iestatÄ«jumos<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">LielÄkajai daļai lietotÄju Å¡Ä« vietne atveras un reaģē Ätri.</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Vai iziet no inkognito režīma?</translation>
<translation id="8958424370300090006">Bloķēt sīkfailus konkrētai vietnei.</translation>
<translation id="8959122750345127698">NavigÄcija nav sasniedzama: <ph name="URL" /></translation>
<translation id="8986362086234534611">Aizmirst</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mk.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mk.xtb
index 52b6fb3e5ac..3d08f54ad12 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mk.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mk.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="mk">
<translation id="1006017844123154345">Отвори онлајн</translation>
<translation id="1044891598689252897">Сајтовите ќе работат нормално</translation>
+<translation id="1100504063505580045">Моментална икона</translation>
<translation id="1124090076051167250">Овa ќе ги избрише податоците и колачињата (<ph name="DATASIZE" />) Ñкладирани од Ñајтови или апликации на почетниот екран.</translation>
<translation id="1124772482545689468">КориÑник</translation>
<translation id="1178581264944972037">Пауза</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Микрофон</translation>
<translation id="3277252321222022663">Дозволете Ñајтовите да приÑтапуваат до Ñензорите (препорачано)</translation>
<translation id="3295602654194328831">Сокриј ги информациите</translation>
+<translation id="3317660236277031814">Веб-апликацијата што Ñте ја инÑталирале ја променила Ñвојата икона.</translation>
<translation id="3328801116991980348">Информации за веб-локација</translation>
<translation id="3333961966071413176">Сите контакти</translation>
<translation id="3386292677130313581">Прашај пред да дозволиш Ñајтовите да ја дознаат локацијата (Ñе препорачува)</translation>
+<translation id="345699454248713913">Веб-апликацијата што Ñте ја инÑталирале го променила Ñвоето име.</translation>
<translation id="3538390592868664640">Ðе дозволувај им на Ñајтовите да Ñоздаваат 3D-карта на опкружувањето или да ја Ñледат позицијата на камерата</translation>
+<translation id="3551268116566418498">Да Ñе излезе од „Инкогнито“?</translation>
<translation id="3586500876634962664">КориÑтење камера и микрофон</translation>
<translation id="358794129225322306">Дозволете Ñајтот автоматÑки да презема повеќе датотеки.</translation>
<translation id="3594780231884063836">ИÑклучете звук на видео</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Отворете ги поÑтавките за локација</translation>
<translation id="4226663524361240545">ИзвеÑтувањата може да предизвикаат вибрации на уредот</translation>
<translation id="4259722352634471385">Ðавигацијата е блокирана: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Веб-апликацијата што Ñте ја инÑталирале го променила Ñвоето име и икона.</translation>
<translation id="4278390842282768270">Дозволено</translation>
<translation id="429312253194641664">Сајтот репродуцира аудиовизуелни Ñодржини</translation>
<translation id="42981349822642051">Прошири</translation>
<translation id="4336434711095810371">Избриши ги Ñите податоци</translation>
<translation id="4402755511846832236">Ðе дозволувај Ñајтовите да знаат кога активно го кориÑтам уредов</translation>
-<translation id="4433925000917964731">Lite-Ñтраница овозможена од Google</translation>
<translation id="4434045419905280838">Скокачки прозорци/пренаÑочувања</translation>
<translation id="445467742685312942">Дозволи Ñајтовите да пуштаат заштитени Ñодржини</translation>
<translation id="4468959413250150279">ИÑклучете го звукот за одреден Ñајт.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Управувано од вашиот родител</translation>
<translation id="4670064810192446073">Виртуелна реалноÑÑ‚</translation>
<translation id="4708011789095599544">Дали Ñте Ñигурни дека Ñакате да ги иÑчиÑтите колачињата и другите податоците од Ñајтот за овој веб-Ñајт?</translation>
+<translation id="473775607612524610">Ðжурирај</translation>
<translation id="4751476147751820511">Сензори за движење или Ñветлина</translation>
<translation id="4836046166855586901">Прашувај кога некој Ñајт ќе Ñака да знае дали активно го кориÑтам уредов</translation>
<translation id="4883854917563148705">Управуваните поÑтавки не може да Ñе реÑетираат</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Сподели преку</translation>
<translation id="5039804452771397117">Дозволи</translation>
<translation id="5048398596102334565">Дозволете Ñајтовите да приÑтапуваат до Ñензорите за движење (препорачано)</translation>
+<translation id="5050380848339752099">Сајтов ќе Ñподели информации Ñо апликација надвор од режимот „Инкогнито“.</translation>
<translation id="5063480226653192405">КориÑтење</translation>
<translation id="5100237604440890931">Проширено - кликни да Ñе прошири.</translation>
<translation id="5123685120097942451">Картичка инкогнито</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Дозволи Ñајтовите да извршуваат JavaScript (Ñе препорачува)</translation>
<translation id="534295439873310000">NFC-уреди</translation>
<translation id="5354152178998424783">Ова ќе избрише <ph name="DATASIZE" /> податоци и колачиња Ñкладирани од Ñајтовите.</translation>
-<translation id="5384883051496921101">Сајтов ќе Ñподели информации Ñо една апликација надвор од режимот „Инкогнито“.</translation>
+<translation id="536508626067510330">Да Ñе ажурира иконата на почетниот екран?</translation>
<translation id="5391532827096253100">Ð’Ñ€Ñката Ñо Ñајтов не е безбедна. Информации за Ñајтот</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(и уште 1)}one{(и уште #)}other{(и уште #)}}</translation>
<translation id="5403592356182871684">Имиња</translation>
<translation id="5489227211564503167">Изминато време: <ph name="ELAPSED_TIME" /> од <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Блокирај ги рекламите на Ñајтови што прикажуваат нападни или лажни реклами</translation>
+<translation id="549957179819296104">Ðова икона</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> е одобрена, <ph name="PERMISSION_2" /> е блокирана</translation>
<translation id="5505264765875738116">Сајтовите не можат да прашуваат дали да иÑпраќаат извеÑтувања</translation>
<translation id="5516455585884385570">Отвори ги поÑтавките за извеÑтувања</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Дозволи</translation>
<translation id="5860033963881614850">ИÑклучено</translation>
<translation id="5876056640971328065">Паузирајте го видеото</translation>
+<translation id="5904826301761575486">Да Ñе ажурираат името и иконата на почетниот екран?</translation>
<translation id="5916664084637901428">Вклучено</translation>
<translation id="5922853908706496913">Се Ñподелува екранот</translation>
<translation id="5939518447894949180">РеÑетирај</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Блокирај колачиња од трети лица</translation>
<translation id="6206551242102657620">Ð’Ñ€Ñката е безбедна. Информации за Ñајтот</translation>
<translation id="6216432067784365534">Опции за <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Затворете и пријавете злоупотреба</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> и <ph name="PERMISSION_2" /> Ñе блокирани</translation>
<translation id="6270391203985052864">Сајтовите можат да прашуваат дали да иÑпраќаат извеÑтувања</translation>
<translation id="6295158916970320988">Сите локации</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">За да овозможите <ph name="APP_NAME" /> да приÑтапува до вашата локација, вклучете ја дозволата за локацијата и во <ph name="BEGIN_LINK" />ПоÑтавки за Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Отповикај ја дозволата за приÑтап до уредот</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Се кориÑти 1 колаче}one{Се кориÑти # колаче}other{Се кориÑтат # колачиња}}</translation>
-<translation id="8463851957836045671">Сајтот е брз</translation>
<translation id="8487700953926739672">ДоÑтапно е иÑклучено од линија</translation>
<translation id="851751545965956758">Блокирај ги Ñајтовите од поврзување Ñо уреди</translation>
<translation id="8525306231823319788">Цел екран</translation>
<translation id="857943718398505171">Дозволено (препорачано)</translation>
<translation id="8609465669617005112">ПремеÑти нагоре</translation>
+<translation id="861748745608658996">Да Ñе ажурира името на почетниот екран?</translation>
<translation id="8676374126336081632">ЈаÑно внеÑување</translation>
<translation id="868929229000858085">Пребарајте ги контактите</translation>
<translation id="8702612070107455751">Сите офлајн податоци ќе Ñе избришат.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Зумирај</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC е иÑклучена за уредов. Вклучете ја во <ph name="BEGIN_LINK" />„ПоÑтавки за Android“<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Сајтов Ñе отвора и реагира брзо за повеќето луѓе</translation>
<translation id="8941729603749328384">www.primer.com</translation>
-<translation id="894871326938397531">Да Ñе напушти режимот „Инкогнито“?</translation>
<translation id="8958424370300090006">Блокирајте колачиња за одреден Ñајт.</translation>
<translation id="8959122750345127698">Ðавигацијата е недоÑтапна: <ph name="URL" /></translation>
<translation id="8986362086234534611">Заборави</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ml.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ml.xtb
index bae6a61738d..48d02c9c7bb 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ml.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ml.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ml">
<translation id="1006017844123154345">ഓൺലൈനായി à´¤àµà´±à´•àµà´•àµà´•</translation>
<translation id="1044891598689252897">സൈറàµà´±àµà´•àµ¾ സാധാരണ രീതിയിൽ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´•àµà´•àµà´‚</translation>
+<translation id="1100504063505580045">നിലവിലെ à´à´•àµà´•àµº</translation>
<translation id="1124090076051167250">ഇതൠനിങàµà´™à´³àµà´Ÿàµ† ഹോം à´¸àµà´•àµà´°àµ€à´¨à´¿àµ½ സൈറàµà´±àµà´•à´³àµ‹ ആപàµà´ªàµà´•à´³àµ‹ സംഭരിചàµà´š <ph name="DATASIZE" /> ഡാറàµà´±à´¯àµà´‚ à´•àµà´•àµà´•à´¿à´•à´³àµà´‚ മായàµâ€Œà´•àµà´•àµà´‚.</translation>
<translation id="1124772482545689468">ഉപയോകàµà´¤à´¾à´µàµ</translation>
<translation id="1178581264944972037">à´…à´²àµà´ªà´‚നിരàµâ€à´¤àµà´¤àµ‚</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">മൈകàµà´°àµ‹à´«àµ‹àµº</translation>
<translation id="3277252321222022663">സെൻസറàµà´•àµ¾ ആകàµâ€Œà´¸à´¸àµ ചെയàµà´¯à´¾àµ» സൈറàµà´±àµà´•à´³àµ† à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´• (à´¶àµà´ªà´¾àµ¼à´¶ ചെയàµà´¯àµà´¨àµà´¨à´¤àµ)</translation>
<translation id="3295602654194328831">വിവരങàµà´™àµ¾ മറയàµâ€Œà´•àµà´•àµà´•</translation>
+<translation id="3317660236277031814">നിങàµà´™àµ¾ ഇൻസàµà´±àµà´±à´¾àµ¾ ചെയàµà´¤ വെബàµâ€Œ ആപàµà´ªàµ അതിനàµà´±àµ† à´à´•àµà´•àµº മാറàµà´±à´¿.</translation>
<translation id="3328801116991980348">സൈറàµà´±àµ വിവരങàµà´™à´³àµâ€</translation>
<translation id="3333961966071413176">à´Žà´²àµà´²à´¾ കോൺടാകàµà´±àµà´±àµà´•à´³àµà´‚</translation>
<translation id="3386292677130313581">നിങàµà´™à´³àµà´Ÿàµ† ലൊകàµà´•àµ‡à´·àµ» അറിയാൻ സൈറàµà´±àµà´•à´³àµ† à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ à´®àµà´®àµà´ªàµ ചോദികàµà´•àµà´• (à´¶àµà´ªà´¾àµ¼à´¶à´šàµ†à´¯àµâ€Œà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ)</translation>
+<translation id="345699454248713913">നിങàµà´™àµ¾ ഇൻസàµà´±àµà´±à´¾àµ¾ ചെയàµà´¤ വെബàµâ€Œ ആപàµà´ªàµ അതിനàµà´±àµ† പേരൠമാറàµà´±à´¿.</translation>
<translation id="3538390592868664640">നിങàµà´™à´³àµà´Ÿàµ† à´šàµà´±àµà´±àµà´ªà´¾à´Ÿàµà´•à´³àµà´Ÿàµ† 3D മാപàµà´ªàµ സൃഷàµà´Ÿà´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿àµ½ നിനàµà´¨àµ‹ à´•àµà´¯à´¾à´®à´±à´¯àµà´Ÿàµ† à´¸àµà´¥à´¾à´¨à´‚ à´Ÿàµà´°à´¾à´•àµà´•àµ ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿àµ½ നിനàµà´¨àµ‹ സൈറàµà´±àµà´•à´³àµ† à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµà´¯àµà´•</translation>
+<translation id="3551268116566418498">അദൃശàµà´¯ മോഡൠവിടണോ?</translation>
<translation id="3586500876634962664">à´•àµà´¯à´¾à´®à´±, മൈകàµà´°àµ‹à´«àµ‹àµº ഉപയോഗം</translation>
<translation id="358794129225322306">à´’à´¨àµà´¨à´¿à´²àµ‡à´±àµ† ഫയലàµà´•à´³àµâ€ à´¸àµà´µà´®àµ‡à´§à´¯à´¾ ഡൗണàµâ€â€Œà´²àµ‹à´¡àµ ചെയàµà´¯à´¾à´¨àµâ€ സൈറàµà´±à´¿à´¨àµ† à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´•.</translation>
<translation id="3594780231884063836">വീഡിയോ à´®àµà´¯àµ‚à´Ÿàµà´Ÿàµ ചെയàµà´¯àµà´•</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">ലൊകàµà´•àµ‡à´·àµ» à´•àµà´°à´®àµ€à´•à´°à´£à´‚ à´¤àµà´±à´•àµà´•àµà´•</translation>
<translation id="4226663524361240545">അറിയിപàµà´ªàµà´•àµ¾ ലഭികàµà´•àµà´®àµà´ªàµ‹àµ¾ ഉപകരണം വൈബàµà´°àµ‡à´±àµà´±àµ ചെയàµâ€Œà´¤àµ‡à´•àµà´•à´¾à´‚</translation>
<translation id="4259722352634471385">നാവിഗേഷൻ തടഞàµà´žà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ: <ph name="URL" /></translation>
+<translation id="4277239631747669329">നിങàµà´™àµ¾ ഇൻസàµà´±àµà´±à´¾àµ¾ ചെയàµà´¤ വെബàµâ€Œ ആപàµà´ªàµ അതിനàµà´±àµ† പേരàµà´‚ à´à´•àµà´•à´£àµà´‚ മാറàµà´±à´¿.</translation>
<translation id="4278390842282768270">à´…à´¨àµà´µà´¦à´¨àµ€à´¯à´‚</translation>
<translation id="429312253194641664">സൈറàµà´±àµ, മീഡിയ à´ªàµà´²àµ‡ ചെയàµà´¯àµà´¨àµà´¨àµ</translation>
<translation id="42981349822642051">വികസിപàµà´ªà´¿à´•àµà´•àµà´•</translation>
<translation id="4336434711095810371">à´Žà´²àµà´²à´¾ ഡാറàµà´±à´¯àµà´‚ മായàµà´•àµà´•àµà´•</translation>
<translation id="4402755511846832236">നിങàµà´™àµ¾ à´ˆ ഉപകരണം സജീവമായി ഉപയോഗികàµà´•àµà´¨àµà´¨à´¤àµ അറിയàµà´¨àµà´¨à´¤à´¿àµ½ നിനàµà´¨àµ സൈറàµà´±àµà´•à´³àµ† à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµà´¯àµà´¨àµà´¨àµ</translation>
-<translation id="4433925000917964731">Google നലàµâ€à´•àµà´¨àµà´¨ ലൈറàµà´±àµ പേജàµ</translation>
<translation id="4434045419905280838">പോപàµ-à´…à´ªàµà´ªàµà´•à´³àµà´‚ റീഡയറകàµâ€Œà´±àµà´±àµà´•à´³àµà´‚</translation>
<translation id="445467742685312942">പരിരകàµà´·à´¿à´¤ ഉളàµà´³à´Ÿà´•àµà´•à´‚ à´ªàµà´²àµ‡ ചെയàµà´¯à´¾àµ» സൈറàµà´±àµà´•à´³àµ† à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´•</translation>
<translation id="4468959413250150279">ഒരൠപàµà´°à´¤àµà´¯àµ‡à´• സൈറàµà´±à´¿à´¨à´¾à´¯à´¿ ശബàµâ€Œà´¦à´‚ à´®àµà´¯àµ‚à´Ÿàµà´Ÿàµ ചെയàµà´¯àµà´•.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">നിങàµà´™à´³àµà´Ÿàµ† à´°à´•àµà´·à´¿à´¤à´¾à´µàµ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´¨àµà´¨àµ</translation>
<translation id="4670064810192446073">വെർചàµà´µàµ½ റിയാലിറàµà´±à´¿</translation>
<translation id="4708011789095599544">à´ˆ വെബàµâ€Œà´¸àµˆà´±àµà´±à´¿à´¨àµà´±àµ† à´•àµà´•àµà´•à´¿à´•à´³àµà´‚ മറàµà´±àµ സൈറàµà´±àµ ഡാറàµà´±à´¯àµà´‚ മായàµâ€Œà´•àµà´•à´£à´®àµ†à´¨àµà´¨àµ തീർചàµà´šà´¯à´¾à´£àµ‹?</translation>
+<translation id="473775607612524610">à´…à´ªàµà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´•</translation>
<translation id="4751476147751820511">ചലന à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ വെളിചàµà´š സെൻസറàµà´•àµ¾</translation>
<translation id="4836046166855586901">നിങàµà´™àµ¾ à´ˆ ഉപകരണം സജീവമായി ഉപയോഗികàµà´•àµà´¨àµà´¨à´¤àµ ഒരൠസൈറàµà´±à´¿à´¨àµ അറിയണമെനàµà´¨àµà´³àµà´³à´ªàµà´ªàµ‹àµ¾ ചോദികàµà´•àµà´•</translation>
<translation id="4883854917563148705">മാനേജൠചെയàµà´¯àµà´¨àµà´¨ à´•àµà´°à´®àµ€à´•à´°à´£à´‚ à´ªàµà´¨à´ƒà´¸à´œàµà´œàµ€à´•à´°à´¿à´•àµà´•à´¾à´¨à´¾à´µà´¿à´²àµà´²</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">ഇതàµà´µà´´à´¿ പങàµà´•à´¿à´Ÿàµà´•</translation>
<translation id="5039804452771397117">à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµ‚</translation>
<translation id="5048398596102334565">നിങàµà´™à´³àµà´Ÿàµ† ചലന സെൻസറàµà´•àµ¾ ആകàµâ€Œà´¸à´¸àµ ചെയàµà´¯à´¾àµ» സൈറàµà´±àµà´•à´³àµ† à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´• (à´¶àµà´ªà´¾àµ¼à´¶ ചെയàµà´¯àµà´¨àµà´¨à´¤àµ)</translation>
+<translation id="5050380848339752099">à´ˆ സൈറàµà´±àµ, അദൃശàµà´¯ മോഡിനൠപàµà´±à´¤àµà´¤àµà´³àµà´³ ഒരൠആപàµà´ªàµà´®à´¾à´¯à´¿ വിവരങàµà´™àµ¾ പങàµà´•à´¿à´Ÿà´¾àµ» പോകàµà´¨àµà´¨àµ.</translation>
<translation id="5063480226653192405">ഉപയോഗം</translation>
<translation id="5100237604440890931">à´šàµà´°àµà´•àµà´•à´¿à´¯à´¤àµ - വിപàµà´²àµ€à´•à´°à´¿à´•àµà´•à´¾àµ» à´•àµà´²à´¿à´•àµà´•àµ ചെയàµà´¯àµà´•</translation>
<translation id="5123685120097942451">അദൃശàµà´¯ ടാബàµ</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">JavaScript റൺ ചെയàµà´¯à´¾àµ» സൈറàµà´±àµà´•à´³àµ† à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´• (à´¶àµà´ªà´¾àµ¼à´¶à´šàµ†à´¯àµâ€Œà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ)</translation>
<translation id="534295439873310000">NFC ഉപകരണങàµà´™àµ¾</translation>
<translation id="5354152178998424783">സൈറàµà´±àµà´•àµ¾ സംഭരിചàµà´š <ph name="DATASIZE" /> ഡാറàµà´±à´¯àµà´‚ à´•àµà´•àµà´•à´¿à´•à´³àµà´‚ ഇതൠമായàµâ€Œà´•àµà´•àµà´‚.</translation>
-<translation id="5384883051496921101">അദൃശàµà´¯à´¤à´¾ സംവിധാനതàµà´¤à´¿à´¨àµ à´ªàµà´±à´¤àµà´¤àµà´³àµà´³ ഒരൠആപàµà´ªàµà´®à´¾à´¯à´¿ à´ˆ സൈറàµà´±àµ വിവരങàµà´™àµ¾ പങàµà´•à´¿à´Ÿà´¾àµ» പോകàµà´¨àµà´¨àµ.</translation>
+<translation id="536508626067510330">നിങàµà´™à´³àµà´Ÿàµ† ഹോം à´¸àµâ€Œà´•àµà´°àµ€à´¨à´¿àµ½ à´à´•àµà´•àµº à´…à´ªàµà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯à´£àµ‹?</translation>
<translation id="5391532827096253100">à´ˆ സൈറàµà´±à´¿à´²àµ‡à´•àµà´•àµà´³àµà´³ നിങàµà´™à´³àµà´Ÿàµ† കണകàµà´·àµ» à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´²àµà´². സൈറàµà´±àµ വിവരങàµà´™à´³àµâ€</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ ഒരെണàµà´£à´‚ കൂടി)}other{(+ # à´Žà´£àµà´£à´‚ കൂടി)}}</translation>
<translation id="5403592356182871684">പേരàµà´•àµ¾</translation>
<translation id="5489227211564503167">ആകെ <ph name="TOTAL_TIME" />-ൽ <ph name="ELAPSED_TIME" /> à´•à´´à´¿à´žàµà´žàµ.</translation>
<translation id="5494752089476963479">അനാവശàµà´¯à´®àµ‹ തെറàµà´±à´¿à´¦àµà´§à´°à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨à´¤àµ‹ ആയ പരസàµà´¯à´™àµà´™à´³àµâ€ കാണികàµà´•àµà´¨àµà´¨ സൈറàµà´±àµà´•à´³à´¿à´²àµ† പരസàµà´¯à´™àµà´™àµ¾ à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµà´¯àµà´•</translation>
+<translation id="549957179819296104">à´ªàµà´¤à´¿à´¯ à´à´•àµà´•àµº</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> à´…à´¨àµà´µà´¦à´¿à´šàµà´šàµ, <ph name="PERMISSION_2" /> à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµâ€Œà´¤àµ</translation>
<translation id="5505264765875738116">അറിയിപàµà´ªàµà´•àµ¾ അയയàµà´•àµà´•à´¾àµ» സൈറàµà´±àµà´•àµ¾à´•àµà´•àµ à´…à´¨àµà´µà´¾à´¦à´‚ ചോദികàµà´•à´¾à´¨à´¾à´µà´¿à´²àµà´²</translation>
<translation id="5516455585884385570">അറിയിപàµà´ªàµ à´•àµà´°à´®àµ€à´•à´°à´£à´‚ à´¤àµà´±à´•àµà´•àµà´•</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">à´…à´¨àµà´®à´¤à´¿à´•àµ¾</translation>
<translation id="5860033963881614850">ഓഫാകàµà´•àµà´•</translation>
<translation id="5876056640971328065">വീഡിയോ താൽകàµà´•à´¾à´²à´¿à´•à´®à´¾à´¯à´¿ നിർതàµà´¤àµà´•</translation>
+<translation id="5904826301761575486">നിങàµà´™à´³àµà´Ÿàµ† ഹോം à´¸àµâ€Œà´•àµà´°àµ€à´¨à´¿àµ½ പേരàµà´‚ à´à´•àµà´•à´£àµà´‚ à´…à´ªàµà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯à´£àµ‹?</translation>
<translation id="5916664084637901428">ഓൺ ചെയàµà´¯àµà´•</translation>
<translation id="5922853908706496913">നിങàµà´™à´³àµà´Ÿàµ† à´¸àµâ€Œà´•àµà´°àµ€àµ» പങàµà´•à´¿à´Ÿàµà´¨àµà´¨àµ</translation>
<translation id="5939518447894949180">റീസെറàµà´±àµ ചെയàµà´¯àµà´•</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿ à´•àµà´•àµà´•à´¿à´•à´³àµâ€ à´¬àµà´²àµ‹à´•àµà´•àµà´šàµ†à´¯àµà´¯àµà´•</translation>
<translation id="6206551242102657620">കണകàµà´·àµ» à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´¾à´£àµ. സൈറàµà´±àµ വിവരങàµà´™à´³àµâ€</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> à´“à´ªàµâ€Œà´·à´¨àµà´•àµ¾</translation>
+<translation id="6260852843601447737">à´…à´Ÿà´šàµà´šàµ à´¦àµà´°àµà´ªà´¯àµ‹à´—à´‚ റിപàµà´ªàµ‹à´°àµâ€â€Œà´Ÿàµà´Ÿàµ ചെയàµà´¯àµà´•</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" />,<ph name="PERMISSION_2" /> à´Žà´¨àµà´¨à´¿à´µ à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµâ€Œà´¤àµ</translation>
<translation id="6270391203985052864">അറിയിപàµà´ªàµà´•àµ¾ അയയàµà´•àµà´•à´¾àµ» സൈറàµà´±àµà´•àµ¾à´•àµà´•àµ à´…à´¨àµà´µà´¾à´¦à´‚ ചോദികàµà´•àµ‡à´£àµà´Ÿà´¿ വരàµà´‚</translation>
<translation id="6295158916970320988">à´Žà´²àµà´²à´¾ സൈറàµà´±àµà´•à´³àµà´‚</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">നിങàµà´™à´³àµà´Ÿàµ† ലൊകàµà´•àµ‡à´·àµ» ആകàµâ€Œà´¸à´¸àµ ചെയàµà´¯à´¾àµ» <ph name="APP_NAME" /> ആപàµà´ªà´¿à´¨àµ† à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ, <ph name="BEGIN_LINK" />Android à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿à´²àµà´‚<ph name="END_LINK" /> ലൊകàµà´•àµ‡à´·àµ» ഓണാകàµà´•àµà´•.</translation>
<translation id="8447861592752582886">ഉപകരണ à´…à´¨àµà´®à´¤à´¿ റദàµà´¦à´¾à´•àµà´•àµà´•</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{ഒരൠകàµà´•àµà´•à´¿ ഉപയോഗതàµà´¤à´¿à´²à´¾à´£àµ}other{# à´•àµà´•àµà´•à´¿à´•àµ¾ ഉപയോഗതàµà´¤à´¿à´²à´¾à´£àµ}}</translation>
-<translation id="8463851957836045671">വളരെ വേഗതയàµà´³àµà´³ സൈറàµà´±àµ</translation>
<translation id="8487700953926739672">à´“à´«àµâ€Œà´²àµˆà´¨à´¿à´²àµâ€ ലഭàµà´¯à´®à´¾à´£àµ</translation>
<translation id="851751545965956758">ഉപകരണങàµà´™à´³à´¿à´²àµ‡à´•àµà´•àµ കണകàµâ€Œà´±àµà´±àµ ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿àµ½ നിനàµà´¨àµ സൈറàµà´±àµà´•à´³àµ† à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµà´¯àµà´•</translation>
<translation id="8525306231823319788">പൂരàµâ€à´£àµà´£ à´¸àµà´•àµà´°àµ€à´¨àµâ€</translation>
<translation id="857943718398505171">à´…à´¨àµà´µà´¦à´¿à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ (à´¶àµà´ªà´¾àµ¼à´¶à´šàµ†à´¯àµâ€Œà´¤à´¤àµ)</translation>
<translation id="8609465669617005112">à´®àµà´•à´³à´¿à´²àµ‡à´•àµà´•àµ നീകàµà´•àµà´•</translation>
+<translation id="861748745608658996">നിങàµà´™à´³àµà´Ÿàµ† ഹോം à´¸àµâ€Œà´•àµà´°àµ€à´¨à´¿àµ½ പേരൠഅപàµà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯à´£àµ‹?</translation>
<translation id="8676374126336081632">ഇൻപàµà´Ÿàµà´Ÿàµ മായàµâ€Œà´•àµà´•àµà´•</translation>
<translation id="868929229000858085">നിങàµà´™à´³àµà´Ÿàµ† കോൺടാകàµâ€Œà´±àµà´±àµà´•àµ¾ തിരയàµà´•</translation>
<translation id="8702612070107455751">à´Žà´²àµà´²à´¾ à´“à´«àµâ€à´²àµˆàµ» ഡാറàµà´±à´¯àµà´‚ മായàµâ€Œà´•àµà´•àµà´‚.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">സൂം ഇനàµâ€ ചെയàµà´¯àµà´•</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">à´ˆ ഉപകരണതàµà´¤à´¿à´¨àµà´³àµà´³ NFC ഓഫാണàµ. ഇതൠ<ph name="BEGIN_LINK" />Android à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½<ph name="END_LINK" /> ഓണാകàµà´•àµà´•.</translation>
-<translation id="8929372349074745002">കൂടàµà´¤àµ½ ആളàµà´•àµ¾à´•àµà´•àµà´‚ à´ˆ സൈറàµà´±àµ വേഗതàµà´¤à´¿àµ½ à´¤àµà´±à´•àµà´•àµà´•à´¯àµà´‚ à´ªàµà´°à´¤à´¿à´•à´°à´¿à´•àµà´•àµà´•à´¯àµà´‚ ചെയàµà´¯àµà´¨àµà´¨àµ</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">അദൃശàµà´¯ മോഡൠവിടണോ?</translation>
<translation id="8958424370300090006">ഒരൠപàµà´°à´¤àµà´¯àµ‡à´• സൈറàµà´±à´¿à´¨à´¾à´¯à´¿ à´•àµà´•àµà´•à´¿à´•àµ¾ à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµà´¯àµà´•.</translation>
<translation id="8959122750345127698">നാവിഗേഷൻ ലഭàµà´¯à´®à´²àµà´²: <ph name="URL" /></translation>
<translation id="8986362086234534611">മറനàµà´¨àµ</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mn.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mn.xtb
index 630d743b83a..bba62161611 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mn.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mn.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="mn">
<translation id="1006017844123154345">Онлайнаар нÑÑÑ…</translation>
<translation id="1044891598689252897">Сайтууд Ñ…Ñвийн ажиллана</translation>
+<translation id="1100504063505580045">Одоогийн Ð´Ò¯Ñ€Ñ Ñ‚ÑмдÑг</translation>
<translation id="1124090076051167250">Ð­Ð½Ñ Ð½ÑŒ Ñайт ÑÑвÑл таны ҮндÑÑн нүүрÑн дÑÑрх Ð°Ð¿Ð¿ÑƒÑƒÐ´Ð°Ð°Ñ Ñ…Ð°Ð´Ð³Ð°Ð»Ñан <ph name="DATASIZE" /> өгөгдөл болон күүкиг арилгана.</translation>
<translation id="1124772482545689468">Ð¥ÑÑ€ÑглÑгч</translation>
<translation id="1178581264944972037">Түр зогÑоох</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Микрофон</translation>
<translation id="3277252321222022663">Сайтуудад мÑдрÑгчид хандахыг зөвшөөрөх (Ñанал болгоÑон)</translation>
<translation id="3295602654194328831">ÐœÑдÑÑллийг нуух</translation>
+<translation id="3317660236277031814">Таны ÑуулгаÑан веб апп Ð´Ò¯Ñ€Ñ Ñ‚ÑмдгÑÑ Ó©Ó©Ñ€Ñ‡Ð¸Ð»Ñөн байна.</translation>
<translation id="3328801116991980348">Сайтын мÑдÑÑлÑл</translation>
<translation id="3333961966071413176">Бүх харилцагч</translation>
<translation id="3386292677130313581">Сайтууд байршил мÑдÑÑ… зөвшөөрөл авах (Ñанал болгоÑон)</translation>
+<translation id="345699454248713913">Таны ÑуулгаÑан веб апп нÑÑ€ÑÑ Ó©Ó©Ñ€Ñ‡Ð¸Ð»Ñөн байна.</translation>
<translation id="3538390592868664640">Сайтуудад таны ÑргÑн тойрны 3D газрын зургийг Ò¯Ò¯ÑгÑÑ… ÑÑвÑл камерын хөдөлгөөнийг Ñ…Ñнахыг хориглох</translation>
+<translation id="3551268116566418498">Ðууцлалтай Ð³Ð¾Ñ€Ð¸Ð¼Ð¾Ð¾Ñ Ð³Ð°Ñ€Ð°Ñ… уу?</translation>
<translation id="3586500876634962664">Камер болон микрофоны ашиглалт</translation>
<translation id="358794129225322306">Сайтад олон файлыг автоматаар татахыг зөвшөөрнө үү.</translation>
<translation id="3594780231884063836">Видеоны дууг хаах</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Байршлын тохиргоог нÑÑÑ…</translation>
<translation id="4226663524361240545">ÐœÑдÑгдÑл ирÑÑ…Ñд төхөөрөмж чичрÑнÑ</translation>
<translation id="4259722352634471385">Ðавигацыг хориглоÑон байна: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Таны ÑуулгаÑан веб апп нÑÑ€ болон Ð´Ò¯Ñ€Ñ Ñ‚ÑмдгÑÑ Ó©Ó©Ñ€Ñ‡Ð¸Ð»Ñөн байна.</translation>
<translation id="4278390842282768270">ЗөвшөөрөгдÑөн</translation>
<translation id="429312253194641664">Сайт медиа тоглуулж байна</translation>
<translation id="42981349822642051">Өргөтгөх</translation>
<translation id="4336434711095810371">Бүх өгөгдлийг уÑтгах</translation>
<translation id="4402755511846832236">Сайтуудыг таныг ÑÐ½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶Ð¸Ð¹Ð³ Ñ…ÑзÑÑ Ð¸Ð´ÑвхтÑй ашиглаж буйг мÑдÑхийг нь блоклоно</translation>
-<translation id="4433925000917964731">Google-Ñ Ó©Ð³Ñ‡ буй Ñнгийн хуудаÑ</translation>
<translation id="4434045419905280838">Попап болон дахин чиглүүлÑлт</translation>
<translation id="445467742685312942">Сайтуудад хамгаалагдÑан контент тоглуулахыг зөвшөөрөх</translation>
<translation id="4468959413250150279">Тодорхой Ñайтын дууг хаана уу.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">ЭцÑг, ÑÑ… нь хариуцаж байна</translation>
<translation id="4670064810192446073">Виртуал бодит байдал</translation>
<translation id="4708011789095599544">Та ÑÐ½Ñ Ð²ÐµÐ± Ñайтын күүки болон буÑад Ñайтын өгөгдлийг арилгахдаа итгÑлтÑй байна уу?</translation>
+<translation id="473775607612524610">ШинÑчлÑÑ…</translation>
<translation id="4751476147751820511">Хөдөлгөөн ÑÑвÑл гÑÑ€Ñл мÑдрÑгч</translation>
<translation id="4836046166855586901">Сайтыг таныг ÑÐ½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶Ð¸Ð¹Ð³ Ñ…ÑзÑÑ Ð¸Ð´ÑвхтÑй ашиглаж буйг мÑдÑхийг Ñ…Ò¯ÑÑÑн үед аÑууна</translation>
<translation id="4883854917563148705">Ð¥Ñналттай тохиргоог шинÑчлÑÑ… боломжгүй</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">-аар хуваалцах</translation>
<translation id="5039804452771397117">Зөвшөөрөх</translation>
<translation id="5048398596102334565">Сайтад хөдөлгөөн мÑдрÑгчид хандахыг зөвшөөрөх (Ñанал болгоÑон)</translation>
+<translation id="5050380848339752099">Ð­Ð½Ñ Ñайт Ðууцлалтай Ð³Ð¾Ñ€Ð¸Ð¼Ð¾Ð¾Ñ Ð³Ð°Ð´ÑƒÑƒÑ€ апптай мÑдÑÑлÑл хуваалцах гÑж байна.</translation>
<translation id="5063480226653192405">Ðшиглалт</translation>
<translation id="5100237604440890931">ЗадарÑан, Ñнд дарж өргөтгөнө Ò¯Ò¯.</translation>
<translation id="5123685120097942451">Ðууцлалтай таб</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Сайтад JavaScript-г ажиллуулахыг зөвшөөрөх (Ñанал болгоÑон)</translation>
<translation id="534295439873310000">NFC төхөөрөмжүүд</translation>
<translation id="5354152178998424783">Ð­Ð½Ñ Ð½ÑŒ ÑÐ°Ð¹Ñ‚Ð°Ð°Ñ Ñ…Ð°Ð´Ð³Ð°Ð»Ñан <ph name="DATASIZE" /> өгөгдөл болон күүкиг арилгана.</translation>
-<translation id="5384883051496921101">Ð­Ð½Ñ Ñайт нууцлалын Ð³Ð¾Ñ€Ð¸Ð¼Ð¾Ð¾Ñ Ð³Ð°Ð´ÑƒÑƒÑ€Ñ… апп-тай мÑдÑÑлÑл хуваалцах гÑж байна.</translation>
+<translation id="536508626067510330">Өөрийн үндÑÑн нүүрÑн дÑÑрх Ð´Ò¯Ñ€Ñ Ñ‚Ñмдгийг шинÑчлÑÑ… Ò¯Ò¯?</translation>
<translation id="5391532827096253100">Таны ÑÐ½Ñ Ñайтын холболт аюултай байна. Сайтын мÑдÑÑлÑл</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(буÑад + 1)}other{(буÑад + #)}}</translation>
<translation id="5403592356182871684">ÐÑÑ€</translation>
<translation id="5489227211564503167">ӨнгөрÑөн цаг: <ph name="TOTAL_TIME" />-н <ph name="ELAPSED_TIME" />.</translation>
<translation id="5494752089476963479">ТөвөгтÑй ÑÑвÑл хуурамч зар харуулдаг Ñайтуудын зарыг блоклох</translation>
+<translation id="549957179819296104">Ð¨Ð¸Ð½Ñ Ð´Ò¯Ñ€Ñ Ñ‚ÑмдÑг</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" />-г зөвшөөрÑөн, <ph name="PERMISSION_2" />-г блоклоÑон</translation>
<translation id="5505264765875738116">Сайтууд нь танд мÑдÑгдÑл илгÑÑÑ… зөвшөөрөл аÑуух боломжгүй</translation>
<translation id="5516455585884385570">ÐœÑдÑгдлийн тохиргоог нÑÑÑ…</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Зөвшөөрлүүд</translation>
<translation id="5860033963881614850">ИдÑвхгүй байна</translation>
<translation id="5876056640971328065">Видеог түр зогÑоох</translation>
+<translation id="5904826301761575486">Өөрийн үндÑÑн нүүрÑн дÑÑрх нÑÑ€ болон Ð´Ò¯Ñ€Ñ Ñ‚Ñмдгийг шинÑчлÑÑ… Ò¯Ò¯?</translation>
<translation id="5916664084637901428">ÐÑаах</translation>
<translation id="5922853908706496913">Таны дÑлгÑцийг хуваалцаж байна</translation>
<translation id="5939518447894949180">Дахин ÑÑргÑÑÑ…</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Гуравдагч талын күүкиг блоклох</translation>
<translation id="6206551242102657620">Холболт аюулгүй байна. Сайтын мÑдÑÑлÑл</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> Сонголт</translation>
+<translation id="6260852843601447737">Хаагаад, зохиÑгүй үйлдлийг мÑдÑÑлÑÑ…</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> болон <ph name="PERMISSION_2" />-г блоклоÑон</translation>
<translation id="6270391203985052864">Сайтууд нь танд мÑдÑгдÑл илгÑÑÑ… зөвшөөрөл аÑуух боломжтой</translation>
<translation id="6295158916970320988">Бүх Ñайт</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" />-д таны байршилд хандахыг зөвшөөрөхийн тулд байршлыг мөн <ph name="BEGIN_LINK" />Ðндройдын тохиргоо<ph name="END_LINK" />-нд аÑаана уу.</translation>
<translation id="8447861592752582886">Төхөөрөмжийн зөвшөөрлийг хүчингүй болгох</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 күүки ашиглаж байна}other{# 1 күүки ашиглаж байна}}</translation>
-<translation id="8463851957836045671">Сайт хурдан</translation>
<translation id="8487700953926739672">СүлжÑÑнд холбогдоогүй байна</translation>
<translation id="851751545965956758">Сайтуудыг төхөөрөмжүүдÑд холбогдохыг нь блоклох</translation>
<translation id="8525306231823319788">БүтÑн дÑлгÑц</translation>
<translation id="857943718398505171">ЗөвшөөрөгдÑөн (Ñанал болгоÑон)</translation>
<translation id="8609465669617005112">ДÑÑш зөөх</translation>
+<translation id="861748745608658996">Өөрийн үндÑÑн нүүрÑн дÑÑрх нÑрийг шинÑчлÑÑ… Ò¯Ò¯?</translation>
<translation id="8676374126336081632">Оролтыг цÑвÑрлÑÑ…</translation>
<translation id="868929229000858085">Харилцагчдаа хайх</translation>
<translation id="8702612070107455751">Ðливаа офлайн өгөгдлийг уÑтгах болно.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Томруулж харах</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">Ð­Ð½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶ дÑÑÑ€ NFC унтраалттай байна. Үүнийг <ph name="BEGIN_LINK" />Android-н тохиргоо<ph name="END_LINK" /> Ñ…ÑÑÑгт аÑаана уу.</translation>
-<translation id="8929372349074745002">Ð­Ð½Ñ Ñайт ихÑнх хүнд хурдан нÑÑгдÑж, хариулдаг</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Ðууцлалын Ð³Ð¾Ñ€Ð¸Ð¼Ð¾Ð¾Ñ Ð³Ð°Ñ€Ð°Ñ… уу?</translation>
<translation id="8958424370300090006">Күүкиг тодорхой Ñайтад хориглоно уу.</translation>
<translation id="8959122750345127698">Ðавигацтай холбогдох боломжгүй байна: <ph name="URL" /></translation>
<translation id="8986362086234534611">Мартах</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mr.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mr.xtb
index d2b26a0226f..cda69122c05 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mr.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_mr.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="mr">
<translation id="1006017844123154345">ऑनलाइन उघडा</translation>
<translation id="1044891598689252897">साइट सामानà¥à¤¯à¤ªà¤£à¥‡ काम करतील</translation>
+<translation id="1100504063505580045">सधà¥à¤¯à¤¾à¤šà¤¾ आयकन</translation>
<translation id="1124090076051167250">हे साइट किंवा तà¥à¤®à¤šà¥à¤¯à¤¾ होम सà¥à¤•à¥à¤°à¥€à¤¨à¤µà¤°à¥€à¤² अâ€à¥…पà¥à¤¸à¤¨à¥€ सà¥à¤Ÿà¥‹à¤…र केलेला <ph name="DATASIZE" /> डेटा आणि कà¥à¤•à¥€ साफ करेल.</translation>
<translation id="1124772482545689468">वापरकरà¥à¤¤à¤¾</translation>
<translation id="1178581264944972037">विराम दà¥à¤¯à¤¾</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">मायकà¥à¤°à¥‹à¤«à¥‹à¤¨</translation>
<translation id="3277252321222022663">साइटना सेनà¥à¤¸à¤° ॲकà¥à¤¸à¥‡à¤¸ करणà¥à¤¯à¤¾à¤šà¥€ अनà¥à¤®à¤¤à¥€ दà¥à¤¯à¤¾ (शिफारस केलेले)</translation>
<translation id="3295602654194328831">माहिती लपवा</translation>
+<translation id="3317660236277031814">तà¥à¤®à¥à¤¹à¥€ इंसà¥à¤Ÿà¥‰à¤² केलेलà¥à¤¯à¤¾ वेब अâ€à¥…पने तà¥à¤¯à¤¾à¤šà¤¾ आयकन बदलला आहे.</translation>
<translation id="3328801116991980348">साइट माहिती</translation>
<translation id="3333961966071413176">सरà¥à¤µ संपरà¥à¤•</translation>
<translation id="3386292677130313581">साइटना तà¥à¤®à¤šà¥‡ सà¥à¤¥à¤¾à¤¨ जाणून घेणà¥à¤¯à¤¾à¤šà¥€ अनà¥à¤®à¤¤à¥€ देणà¥à¤¯à¤¾à¤ªà¥‚रà¥à¤µà¥€ विचारा (शिफारस केलेले)</translation>
+<translation id="345699454248713913">तà¥à¤®à¥à¤¹à¥€ इंसà¥à¤Ÿà¥‰à¤² केलेलà¥à¤¯à¤¾ वेब अâ€à¥…पने तà¥à¤¯à¤¾à¤šà¥‡ नाव बदलले आहे.</translation>
<translation id="3538390592868664640">तà¥à¤®à¤šà¥à¤¯à¤¾ आसपासचà¥à¤¯à¤¾ परिसराचा 3D नकाशा तयार करणà¥à¤¯à¤¾à¤ªà¤¾à¤¸à¥‚न किंवा कॅमेरà¥â€à¤¯à¤¾à¤šà¥‡ सà¥à¤¥à¤¾à¤¨ टà¥à¤°à¥…क करणà¥à¤¯à¤¾à¤ªà¤¾à¤¸à¥‚न साइट बà¥à¤²à¥‰à¤• करा</translation>
+<translation id="3551268116566418498">गà¥à¤ªà¥à¤¤ मोडमधून बाहेर पडायचे का?</translation>
<translation id="3586500876634962664">कॅमेरा आणि मायकà¥à¤°à¥‹à¤«à¥‹à¤¨ वापरा</translation>
<translation id="358794129225322306">साइटला à¤à¤•à¤¾à¤¹à¥‚न अधिक फाइल आपोआप डाउनलोड करू दà¥à¤¯à¤¾.</translation>
<translation id="3594780231884063836">वà¥à¤¹à¤¿à¤¡à¤¿à¤“ मà¥â€à¤¯à¥‚ट करा</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">सà¥à¤¥à¤¾à¤¨ सेटिंगà¥à¤œ उघडा</translation>
<translation id="4226663524361240545">सूचनांमà¥à¤³à¥‡ डिवà¥à¤¹à¤¾à¤‡à¤¸à¤šà¥‡ कंपन होऊ शकते</translation>
<translation id="4259722352634471385">नेवà¥à¤¹à¤¿à¤—ेशन अवरोधित केले आहे: <ph name="URL" /></translation>
+<translation id="4277239631747669329">तà¥à¤®à¥à¤¹à¥€ इंसà¥à¤Ÿà¥‰à¤² केलेलà¥à¤¯à¤¾ वेब अâ€à¥…पने तà¥à¤¯à¤¾à¤šà¥‡ नाव आणि आयकन बदलले आहे.</translation>
<translation id="4278390842282768270">अनà¥à¤®à¤¤</translation>
<translation id="429312253194641664">साइट मीडिया पà¥à¤²à¥‡ करत आहे</translation>
<translation id="42981349822642051">विसà¥à¤¤à¥ƒà¤¤ करा</translation>
<translation id="4336434711095810371">सरà¥à¤µ डेटा साफ करा</translation>
<translation id="4402755511846832236">तà¥à¤®à¥à¤¹à¥€ हे डिवà¥à¤¹à¤¾à¤‡à¤¸ ॲकà¥à¤Ÿà¤¿à¤µà¥à¤¹à¤ªà¤£à¥‡ कधी वापरता हे साइटना जाणून घेणà¥à¤¯à¤¾à¤ªà¤¾à¤¸à¥‚न बà¥à¤²à¥‰à¤• करा</translation>
-<translation id="4433925000917964731">Google दà¥à¤µà¤¾à¤°à¥‡ पà¥à¤°à¤µà¤²à¥‡à¤²à¥‡ लाइट पेज</translation>
<translation id="4434045419905280838">पॉप-अप आणि रीडिरेकà¥à¤Ÿ</translation>
<translation id="445467742685312942">साइटना संरकà¥à¤·à¤¿à¤¤Â à¤†à¤¶à¤¯Â à¤ªà¥à¤²à¥‡Â à¤•à¤°à¥‚ दà¥à¤¯à¤¾</translation>
<translation id="4468959413250150279">विशिषà¥à¤Ÿ साइटसाठी धà¥à¤µà¤¨à¥€ मà¥à¤¯à¥‚ट करा.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">आपलà¥à¤¯à¤¾ पालकांदà¥à¤µà¤¾à¤°à¥‡ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करणà¥à¤¯à¤¾à¤¤ आले</translation>
<translation id="4670064810192446073">आभासी वासà¥à¤¤à¤µà¤¿à¤•à¤¤à¤¾</translation>
<translation id="4708011789095599544">तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ या वेबसाइटचà¥à¤¯à¤¾ कà¥à¤•à¥€ आणि इतर साइट डेटा नकà¥à¤•à¥€ साफ करायचा आहे का?</translation>
+<translation id="473775607612524610">अपडेट करा</translation>
<translation id="4751476147751820511">मोशन किंवा पà¥à¤°à¤•à¤¾à¤¶ सेनà¥à¤¸à¤°</translation>
<translation id="4836046166855586901">तà¥à¤®à¥à¤¹à¥€ हे डिवà¥à¤¹à¤¾à¤‡à¤¸ ॲकà¥à¤Ÿà¤¿à¤µà¥à¤¹à¤ªà¤£à¥‡ कधी वापरता हे साइटला जाणून घà¥à¤¯à¤¾à¤¯à¤šà¥‡ असते तेवà¥à¤¹à¤¾ विचारा</translation>
<translation id="4883854917563148705">वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ केलेलà¥à¤¯à¤¾ सेटिंगà¥à¤œ रीसेट करता येत नाहीत</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">यादà¥à¤µà¤¾à¤°à¥‡ शेअर करा</translation>
<translation id="5039804452771397117">परवानगी दà¥à¤¯à¤¾</translation>
<translation id="5048398596102334565">साइटना मोशन सेनà¥à¤¸à¤° ॲकà¥à¤¸à¥‡à¤¸ करणà¥à¤¯à¤¾à¤šà¥€ अनà¥à¤®à¤¤à¥€ दà¥à¤¯à¤¾ (शिफारस केलेले)</translation>
+<translation id="5050380848339752099">ही साइट गà¥à¤ªà¥à¤¤ मोडबाहेरील अâ€à¥…पबरोबर माहिती शेअर करणार आहे.</translation>
<translation id="5063480226653192405">वापर</translation>
<translation id="5100237604440890931">संकà¥à¤šà¤¿à¤¤ केले - विसà¥à¤¤à¥ƒà¤¤ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ कà¥à¤²à¤¿à¤• करा.</translation>
<translation id="5123685120097942451">गà¥à¤ªà¥à¤¤ टॅब</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">साइटना JavaScript रन करणà¥à¤¯à¤¾à¤šà¥€ अनà¥à¤®à¤¤à¥€ दà¥à¤¯à¤¾ (शिफारस केलेले)</translation>
<translation id="534295439873310000">NFC डिवà¥à¤¹à¤¾à¤‡à¤¸</translation>
<translation id="5354152178998424783">हे साइटने सà¥à¤Ÿà¥‹à¤…र केलेला <ph name="DATASIZE" /> डेटा आणि कà¥à¤•à¥€ साफ करेल.</translation>
-<translation id="5384883051496921101">ही साइट गà¥à¤ªà¥à¤¤ मोडचà¥à¤¯à¤¾ बाहेरील à¤à¤–ादà¥à¤¯à¤¾ अâ€à¥…पबरोबर ही माहिती शेअर करणार आहे.</translation>
+<translation id="536508626067510330">तà¥à¤®à¤šà¥à¤¯à¤¾ होमसà¥à¤•à¥à¤°à¥€à¤¨à¤µà¤° आयकन अपडेट करायचा आहे का?</translation>
<translation id="5391532827096253100">या साइटवरील तà¥à¤®à¤šà¥‡ कनेकà¥à¤¶à¤¨ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नाही. साइट माहिती</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ आणखी à¤à¤•)}other{(+ आणखी #)}}</translation>
<translation id="5403592356182871684">नावे</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" /> पैकी <ph name="ELAPSED_TIME" /> गेलेला वेळ.</translation>
<translation id="5494752089476963479">अनाहूत किंवा दिशाभूल करणाऱà¥à¤¯à¤¾ जाहिराती दाखवणाऱà¥à¤¯à¤¾ साइटवरील जाहिराती बà¥à¤²à¥‰à¤• करा</translation>
+<translation id="549957179819296104">नवीन आयकन</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> ची अनà¥à¤®à¤¤à¥€ दिली, <ph name="PERMISSION_2" /> ला बà¥à¤²à¥‰à¤• केले</translation>
<translation id="5505264765875738116">साइट सूचना पाठवणà¥à¤¯à¤¾à¤¸ सांगू शकत नाहीत</translation>
<translation id="5516455585884385570">सूचना सेटिंगà¥à¤œ उघडा</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">परवानगà¥à¤¯à¤¾</translation>
<translation id="5860033963881614850">बंद</translation>
<translation id="5876056640971328065">वà¥à¤¹à¤¿à¤¡à¤¿à¤“ थांबवा</translation>
+<translation id="5904826301761575486">तà¥à¤®à¤šà¥à¤¯à¤¾ होमसà¥à¤•à¥à¤°à¥€à¤¨à¤µà¤° नाव आणि आयकन अपडेट करायचे आहे का?</translation>
<translation id="5916664084637901428">सà¥à¤°à¥‚</translation>
<translation id="5922853908706496913">तà¥à¤®à¤šà¥€ सà¥à¤•à¥à¤°à¥€à¤¨ शेअर करत आहे</translation>
<translation id="5939518447894949180">रीसेट करा</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">तृतीय-पकà¥à¤· कà¥à¤•à¥€à¤œ अवरोधित करा</translation>
<translation id="6206551242102657620">कनेकà¥à¤¶à¤¨ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ आहे. साइट माहिती</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> परà¥à¤¯à¤¾à¤¯</translation>
+<translation id="6260852843601447737">बंद करा आणि गैरवापराची तकà¥à¤°à¤¾à¤° करा</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> आणि <ph name="PERMISSION_2" /> ला बà¥à¤²à¥‰à¤• केले</translation>
<translation id="6270391203985052864">साइट सूचना पाठवणà¥à¤¯à¤¾à¤¸ सांगू शकतात</translation>
<translation id="6295158916970320988">सरà¥à¤µ साइट</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> ला तà¥à¤®à¤šà¥‡ सà¥à¤¥à¤¾à¤¨ अâ€à¥…कà¥à¤¸à¥‡à¤¸ करू देणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€, <ph name="BEGIN_LINK" />Android सेटिंगà¥à¤œ<ph name="END_LINK" /> मधà¥à¤¯à¥‡à¤¦à¥‡à¤–ील सà¥à¤¥à¤¾à¤¨ सà¥à¤°à¥‚ करा.</translation>
<translation id="8447861592752582886">डिवà¥à¤¹à¤¾à¤‡à¤¸ परवानगी रदà¥à¤¦ करा</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{à¤à¤• कà¥à¤•à¥€ वापरात आहे}other{# कà¥à¤•à¥€ वापरात आहेत}}</translation>
-<translation id="8463851957836045671">साइट जलद आहे</translation>
<translation id="8487700953926739672">ऑफलाइन उपलबà¥à¤§</translation>
<translation id="851751545965956758">डिवà¥à¤¹à¤¾à¤‡à¤¸à¥‡à¤¸à¤¶à¥€ कनेकà¥à¤Ÿ करणà¥à¤¯à¤¾à¤ªà¤¾à¤¸à¥‚न साइटना बà¥à¤²à¥‰à¤• करा</translation>
<translation id="8525306231823319788">फà¥à¤² सà¥à¤•à¥à¤°à¥€à¤¨</translation>
<translation id="857943718398505171">अनà¥à¤®à¤¤à¥€ दिली (शिफारस केलेले)</translation>
<translation id="8609465669617005112">वर हलवा</translation>
+<translation id="861748745608658996">तà¥à¤®à¤šà¥à¤¯à¤¾ होमसà¥à¤•à¥à¤°à¥€à¤¨à¤µà¤° नाव अपडेट करायचे आहे का?</translation>
<translation id="8676374126336081632">इनपà¥à¤Ÿ साफ करा</translation>
<translation id="868929229000858085">तà¥à¤®à¤šà¥‡ संपरà¥à¤• शोधा</translation>
<translation id="8702612070107455751">कोणताही ऑफलाइन डेटा साफ केला जाईल.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">à¤à¥‚म इन करा</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤¸à¤¾à¤ à¥€ NFC बंद केले आहे. ते <ph name="BEGIN_LINK" />Android सेटिंगà¥à¤œà¤®à¤§à¥à¤¯à¥‡<ph name="END_LINK" /> सà¥à¤°à¥‚ करा.</translation>
-<translation id="8929372349074745002">बहà¥à¤¤à¥‡à¤• लोकांसाठी ही साइट à¤à¤Ÿà¤ªà¤Ÿà¤ªà¤£à¥‡ उघडते आणि पà¥à¤°à¤¤à¤¿à¤¸à¤¾à¤¦ देते</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">गà¥à¤ªà¥à¤¤ मोड सोडायचा?</translation>
<translation id="8958424370300090006">विशिषà¥à¤Ÿ साइटसाठी कà¥à¤•à¥€Â à¤¬à¥à¤²à¥‰à¤•Â à¤•à¤°à¤¾.</translation>
<translation id="8959122750345127698">नेवà¥à¤¹à¤¿à¤—ेशन आवाकà¥à¤¯à¤¾à¤¬à¤¾à¤¹à¥‡à¤° आहे: <ph name="URL" /></translation>
<translation id="8986362086234534611">विसरा</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ms.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ms.xtb
index 9574c695335..10d9967080d 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ms.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ms.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ms">
<translation id="1006017844123154345">Buka Dalam Talian</translation>
<translation id="1044891598689252897">Tapak akan berfungsi seperti biasa</translation>
+<translation id="1100504063505580045">Ikon semasa</translation>
<translation id="1124090076051167250">Tindakan ini akan mengosongkan <ph name="DATASIZE" /> data dan kuki yang disimpan oleh tapak atau apl pada Skrin utama anda.</translation>
<translation id="1124772482545689468">Pengguna</translation>
<translation id="1178581264944972037">Jeda</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Benarkan tapak mengakses penderia (disyorkan)</translation>
<translation id="3295602654194328831">Sembunyikan Maklumat</translation>
+<translation id="3317660236277031814">Apl web yang anda pasang telah menukar ikon.</translation>
<translation id="3328801116991980348">Maklumat tapak</translation>
<translation id="3333961966071413176">Semua kenalan</translation>
<translation id="3386292677130313581">Tanya sebelum membenarkan tapak mengetahui lokasi anda (disyorkan)</translation>
+<translation id="345699454248713913">Apl web yang anda pasang telah menukar nama.</translation>
<translation id="3538390592868664640">Sekat tapak daripada membuat peta 3D bagi persekitaran anda atau menjejaki kedudukan kamera</translation>
+<translation id="3551268116566418498">Tinggalkan mod Inkognito?</translation>
<translation id="3586500876634962664">Penggunaan kamera dan mikrofon</translation>
<translation id="358794129225322306">Benarkan tapak memuat turun berbilang fail secara automatik.</translation>
<translation id="3594780231884063836">Redam video</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Buka Tetapan Lokasi</translation>
<translation id="4226663524361240545">Pemberitahuan boleh menggetarkan peranti</translation>
<translation id="4259722352634471385">Navigasi disekat: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Apl web yang anda pasang telah menukar nama dan ikon.</translation>
<translation id="4278390842282768270">Dibenarkan</translation>
<translation id="429312253194641664">Tapak sedang memainkan media</translation>
<translation id="42981349822642051">Kembangkan</translation>
<translation id="4336434711095810371">Kosongkan semua data</translation>
<translation id="4402755511846832236">Sekat tapak daripada mengetahui waktu anda menggunakan peranti ini dengan aktif</translation>
-<translation id="4433925000917964731">Halaman Lite disediakan oleh Google</translation>
<translation id="4434045419905280838">Tetingkap timbul dan ubah hala</translation>
<translation id="445467742685312942">Benarkan tapak memainkan kandungan yang dilindungi</translation>
<translation id="4468959413250150279">Redam bunyi untuk tapak tertentu.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Diurus oleh ibu bapa anda</translation>
<translation id="4670064810192446073">Realiti maya</translation>
<translation id="4708011789095599544">Adakah anda pasti anda ingin mengosongkan kuki dan data tapak lain bagi tapak web ini?</translation>
+<translation id="473775607612524610">Kemas kini</translation>
<translation id="4751476147751820511">Penderia gerakan atau cahaya</translation>
<translation id="4836046166855586901">Tanya apabila laman ingin mengetahui waktu anda menggunakan peranti ini dengan aktif</translation>
<translation id="4883854917563148705">Tetapan yang diurus tidak dapat ditetapkan semula</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Kongsi melalui</translation>
<translation id="5039804452771397117">Benarkan</translation>
<translation id="5048398596102334565">Benarkan tapak mengakses penderia gerakan (disyorkan)</translation>
+<translation id="5050380848339752099">Laman ini akan berkongsi maklumat dengan apl di luar mod Inkognito.</translation>
<translation id="5063480226653192405">Penggunaan</translation>
<translation id="5100237604440890931">Diruntuhkan - klik untuk mengembangkan.</translation>
<translation id="5123685120097942451">Tab Inkognito</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Benarkan tapak menjalankan JavaScript (disyorkan)</translation>
<translation id="534295439873310000">Peranti NFC</translation>
<translation id="5354152178998424783">Tindakan ini akan mengosongkan <ph name="DATASIZE" /> data dan kuki yang disimpan oleh tapak.</translation>
-<translation id="5384883051496921101">Tapak ini akan berkongsi maklumat dengan apl di luar daripada mod inkognito.</translation>
+<translation id="536508626067510330">Kemas kini ikon pada skrin utama anda?</translation>
<translation id="5391532827096253100">Sambungan anda ke tapak web ini tidak selamat. Maklumat tapak</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 lagi)}other{(+ # lagi)}}</translation>
<translation id="5403592356182871684">Nama</translation>
<translation id="5489227211564503167"><ph name="ELAPSED_TIME" /> masa berlalu daripada <ph name="TOTAL_TIME" /></translation>
<translation id="5494752089476963479">Sekat iklan di tapak yang menyiarkan iklan yang mengganggu atau mengelirukan</translation>
+<translation id="549957179819296104">Ikon baharu</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> dibenarkan, <ph name="PERMISSION_2" /> disekat</translation>
<translation id="5505264765875738116">Tapak tidak boleh membuat permintaan untuk menghantar pemberitahuan</translation>
<translation id="5516455585884385570">Buka tetapan pemberitahuan</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Kebenaran</translation>
<translation id="5860033963881614850">Dimatikan</translation>
<translation id="5876056640971328065">Jeda video</translation>
+<translation id="5904826301761575486">Kemas kini nama &amp; ikon pada skrin utama anda?</translation>
<translation id="5916664084637901428">Hidupkan</translation>
<translation id="5922853908706496913">Berkongsi skrin anda</translation>
<translation id="5939518447894949180">Tetapkan semula</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Sekat kuki pihak ketiga</translation>
<translation id="6206551242102657620">Sambungan selamat. Maklumat tapak</translation>
<translation id="6216432067784365534">Pilihan <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Tutup dan laporkan penyalahgunaan</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> dan <ph name="PERMISSION_2" /> disekat</translation>
<translation id="6270391203985052864">Tapak boleh membuat permintaan untuk menghantar pemberitahuan</translation>
<translation id="6295158916970320988">Semua tapak</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Untuk membolehkan <ph name="APP_NAME" /> mengakses lokasi anda, hidupkan juga lokasi dalam <ph name="BEGIN_LINK" />Tetapan Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Batalkan kebenaran peranti</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 kuki sedang digunakan}other{# kuki sedang digunakan}}</translation>
-<translation id="8463851957836045671">Tapak laju</translation>
<translation id="8487700953926739672">Tersedia di luar talian</translation>
<translation id="851751545965956758">Sekat tapak daripada menyambung ke peranti</translation>
<translation id="8525306231823319788">Skrin penuh</translation>
<translation id="857943718398505171">Dibenarkan (disyorkan)</translation>
<translation id="8609465669617005112">Alihkan ke atas</translation>
+<translation id="861748745608658996">Kemas kini nama pada skrin utama anda?</translation>
<translation id="8676374126336081632">Kosongkan input</translation>
<translation id="868929229000858085">Cari dalam kenalan anda</translation>
<translation id="8702612070107455751">Sebarang data luar talian akan dipadamkan.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Zum masuk</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC dimatikan untuk peranti ini. Hidupkan dalam <ph name="BEGIN_LINK" />Tetapan Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Tapak ini dibuka dan memberikan respons dengan pantas untuk kebanyakan orang</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Tinggalkan mod inkognito?</translation>
<translation id="8958424370300090006">Sekat kuki untuk tapak tertentu.</translation>
<translation id="8959122750345127698">Tidak dapat mencapai navigasi: <ph name="URL" /></translation>
<translation id="8986362086234534611">Lupa</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_my.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_my.xtb
index 65f03bd20a6..4505815eae6 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_my.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_my.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="my">
<translation id="1006017844123154345">အွန်လိုင်းá€á€½á€„် ဖွင့်ရန်</translation>
<translation id="1044891598689252897">á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸ ပုံမှန်အလုပ်လုပ်ပါမည်</translation>
+<translation id="1100504063505580045">လက်ရှိ သင်္ကေá€</translation>
<translation id="1124090076051167250">áŽá€„်းက သင့် 'ပင်မစာမျက်နှာ' ပေါ်ရှိ á€á€˜á€ºá€†á€­á€¯á€€á€º သို့မဟုá€á€º အက်ပ်များက သိမ်းထားသည့် ဒေá€á€¬á€”ှင့် ကွá€á€ºá€€á€®á€¸ <ph name="DATASIZE" /> ကို ရှင်းထုá€á€ºá€œá€­á€¯á€€á€ºá€•á€«á€™á€Šá€ºá‹</translation>
<translation id="1124772482545689468">အသုံးပြုသူ</translation>
<translation id="1178581264944972037">ဆိုင်းငံ့ထားရန်</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">မိုက်á€á€›á€­á€¯á€–ုန်း</translation>
<translation id="3277252321222022663">အာရုံá€á€¶á€…နစ်များ အသုံးပြုရန် ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ á€á€½á€„့်ပြုသည် (အကြံပြုထားသည်)</translation>
<translation id="3295602654194328831">အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ဖျောက်ထားရန်</translation>
+<translation id="3317660236277031814">သင့်ထည့်သွင်းထားသော á€á€˜á€ºá€¡á€€á€ºá€•á€ºá€€ áŽá€„်းáသင်္ကေá€á€€á€­á€¯ ပြောင်းလိုက်သည်á‹</translation>
<translation id="3328801116991980348">ဆိုက် အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸</translation>
<translation id="3333961966071413176">အဆက်အသွယ်အားလုံး</translation>
<translation id="3386292677130313581">သင့်á€á€Šá€ºá€”ေရာကို ဆိုက်များအား အသိမပေးမီ မေးပါ (အကြံပြုထားသည်)</translation>
+<translation id="345699454248713913">သင့်ထည့်သွင်းထားသော á€á€˜á€ºá€¡á€€á€ºá€•á€ºá€€ áŽá€„်းáအမည်ကို ပြောင်းလိုက်သည်á‹</translation>
<translation id="3538390592868664640">သင့်ပá€á€ºá€á€”်းကျင်á 3D မြေပုံဆွဲá€á€¼á€„်း သို့မဟုá€á€º ကင်မရာအနေအထား á€á€¼á€±á€›á€¬á€á€¶á€á€¼á€„်းá€á€­á€¯á€· မပြုလုပ်ရန် á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ပိá€á€ºá€‘ားသည်</translation>
+<translation id="3551268116566418498">ရုပ်ဖျက်မုဒ်မှ ထွက်လိုသလားá‹</translation>
<translation id="3586500876634962664">ကင်မရာနှင့် မိုက် အသုံးပြုသည်</translation>
<translation id="358794129225322306">á€á€˜á€ºá€†á€­á€¯á€€á€ºá€¡á€¬á€¸ ဖိုင်အမြောက်အမြား အလိုအလျောက်ဒေါင်းလုဒ်လုပ်á€á€¼á€„်းကို á€á€½á€„့်ပြုသည်</translation>
<translation id="3594780231884063836">ဗီဒီယိုကို အသံပိá€á€ºá€›á€”်</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">'á€á€Šá€ºá€”ေရာပြဆက်á€á€„်များ' ကို ဖွင့်ပါ</translation>
<translation id="4226663524361240545">အကြောင်းကြားá€á€»á€€á€ºá€žá€Šá€º စက်ပစ္စည်းကို á€á€¯á€”်á€á€«á€…ေပါမည်</translation>
<translation id="4259722352634471385">သွားလာမှုပြလမ်းညွှန်အား ပိá€á€ºá€‘ားá- <ph name="URL" /></translation>
+<translation id="4277239631747669329">သင့်ထည့်သွင်းထားသော á€á€˜á€ºá€¡á€€á€ºá€•á€ºá€€ áŽá€„်းáအမည်နှင့် သင်္ကေá€á€€á€­á€¯ ပြောင်းလိုက်သည်á‹</translation>
<translation id="4278390842282768270">á€á€½á€„့်ပြုထား</translation>
<translation id="429312253194641664">á€á€˜á€ºá€†á€­á€¯á€€á€ºá€á€…်á€á€¯á€€ မီဒီယာကို ဖွင့်နေသည်</translation>
<translation id="42981349822642051">á€á€­á€¯á€¸á€á€»á€²á€·</translation>
<translation id="4336434711095810371">ဒေá€á€¬á€¡á€¬á€¸á€œá€¯á€¶á€¸ ရှင်းထုá€á€ºá€›á€”်</translation>
<translation id="4402755511846832236">ဤကိရိယာသုံးနေá€á€»á€­á€”်ကို á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€€á€žá€­á€á€¼á€„်းအား ပိá€á€ºá€‘ားရန်</translation>
-<translation id="4433925000917964731">Google á အပေါ့စား စာမျက်နှာ</translation>
<translation id="4434045419905280838">ပေါ့ပ်အပ်နှင့် á€á€…်ဆင့်ညွှန်á€á€»á€€á€º</translation>
<translation id="445467742685312942">ကာကွယ်ထားသော အကြောင်းအရာများ ဖွင့်ရန် á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ï¿½ á€á€½á€„့်ပြုသည်</translation>
<translation id="4468959413250150279">á€á€˜á€ºá€†á€­á€¯á€€á€ºá€á€…်á€á€¯á€¡á€á€½á€€á€º အသံá€á€­á€á€ºá€‘ားသည်á‹</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">သင့်မိဘမှ စီမံသည်</translation>
<translation id="4670064810192446073">ပကá€á€­á€¡á€žá€½á€„်</translation>
<translation id="4708011789095599544">ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€¡á€á€½á€€á€º ကွá€á€ºá€€á€®á€¸á€™á€»á€¬á€¸á€”ှင့် အá€á€¼á€¬á€¸á€á€˜á€ºá€†á€­á€¯á€€á€ºá€’ေá€á€¬á€™á€»á€¬á€¸á€€á€­á€¯ ရှင်းထုá€á€ºá€œá€­á€¯á€žá€Šá€ºá€™á€¾á€¬ သေá€á€»á€¬á€žá€œá€¬á€¸á‹</translation>
+<translation id="473775607612524610">အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€›á€”်</translation>
<translation id="4751476147751820511">လှုပ်ရှားမှု သို့မဟုá€á€º အလင်းအာရုံá€á€¶á€€á€­á€›á€­á€šá€¬á€™á€»á€¬á€¸</translation>
<translation id="4836046166855586901">ဤကိရိယာသုံးနေá€á€»á€­á€”်ကို á€á€˜á€ºá€†á€­á€¯á€€á€ºá€€á€žá€­á€œá€­á€¯á€žá€Šá€·á€ºá€¡á€á€« á€á€½á€„့်á€á€±á€¬á€„်းရန်</translation>
<translation id="4883854917563148705">စီမံထားသော ဆက်á€á€„်များကို ပြင်ဆင်သá€á€ºá€™á€¾á€á€ºá မရပါ</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">မှá€á€…်ဆင့် မျှá€á€±á€›á€”်</translation>
<translation id="5039804452771397117">á€á€½á€„့်ပြုရန်</translation>
<translation id="5048398596102334565">အာရုံá€á€¶á€…နစ်များ အသုံးပြုရန် ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ á€á€½á€„့်ပြုသည် (အကြံပြုထားသည်)</translation>
+<translation id="5050380848339752099">ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€žá€Šá€º အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ရုပ်ဖျက်မုဒ်ပြင်ပရှိ အက်ပ်á€á€…်á€á€¯á€”ှင့် မျှá€á€±á€•á€«á€á€±á€¬á€·á€™á€Šá€ºá‹</translation>
<translation id="5063480226653192405">အသုံးပြုပုံ</translation>
<translation id="5100237604440890931">á€á€»á€¯á€¶á€·á€‘ားá - á€á€»á€²á€·á€›á€”် နှိပ်ပါá‹</translation>
<translation id="5123685120097942451">ရုပ်ဖျက်á€á€˜á€º</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">ဆိုက်များကို JavaScript အားဖွင့်á€á€½á€„့်ပေးပါ (အကြံပြုထားသည်)</translation>
<translation id="534295439873310000">NFC စက်များ</translation>
<translation id="5354152178998424783">áŽá€„်းက ဒေá€á€¬ <ph name="DATASIZE" /> နှင့် á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€€ သိမ်းထားသည့် ကွá€á€ºá€€á€®á€¸á€™á€»á€¬á€¸á€€á€­á€¯ ရှင်းထုá€á€ºá€œá€­á€¯á€€á€ºá€•á€«á€™á€Šá€ºá‹</translation>
-<translation id="5384883051496921101">ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€žá€Šá€º အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ရုပ်ဖျက်မုဒ်ပြင်ပရှိ အက်ပ်á€á€…်á€á€¯á€”ှင့် မျှá€á€±á€•á€«á€á€±á€¬á€·á€™á€Šá€ºá‹</translation>
+<translation id="536508626067510330">သင့်ပင်မစာမျက်နှာရှိ သင်္ကေá€á€€á€­á€¯ အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€™á€œá€¬á€¸á‹</translation>
<translation id="5391532827096253100">ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€žá€­á€¯á€· သင်áá€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€žá€Šá€º လုံá€á€¼á€¯á€¶á€™á€¾á€¯á€™á€›á€¾á€­á€•á€«á‹ á€á€˜á€ºá€†á€­á€¯á€€á€º အá€á€»á€€á€ºá€¡á€œá€€á€º</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ နောက်ထပ် á á€á€¯)}other{(+ နောက်ထပ် # á€á€¯)}}</translation>
<translation id="5403592356182871684">အမည်များ</translation>
<translation id="5489227211564503167">ကုန်လွန်သွားá€á€»á€­á€”် <ph name="TOTAL_TIME" /> အနက် <ph name="ELAPSED_TIME" />á‹</translation>
<translation id="5494752089476963479">စိá€á€ºá€¡á€”ှောင့်အယှက်ဖြစ်စေသော သို့မဟုá€á€º အထင်အမြင်မှားစေနိုင်သော ကြော်ငြာများပြသသည့် á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€á€½á€„် ကြော်ငြာများကို ပိá€á€ºá€žá€Šá€º</translation>
+<translation id="549957179819296104">သင်္ကေဠအသစ်</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> á€á€½á€„့်ပြုထားသည်አ<ph name="PERMISSION_2" /> ပိá€á€ºá€‘ားသည်</translation>
<translation id="5505264765875738116">á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€€ အကြောင်းကြားá€á€»á€€á€ºá€™á€»á€¬á€¸á€•á€­á€¯á€·á€›á€”် á€á€±á€¬á€„်းဆိုáမရပါ</translation>
<translation id="5516455585884385570">အကြောင်းကြားá€á€»á€€á€º ဆက်á€á€„်များကို ဖွင့်ရန်</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">á€á€½á€„့်ပြုá€á€»á€€á€ºá€™á€»á€¬á€¸</translation>
<translation id="5860033963881614850">ပိá€á€ºá€‘ား</translation>
<translation id="5876056640971328065">ဗီဒီယို á€á€á€›á€•á€ºá€›á€”်</translation>
+<translation id="5904826301761575486">သင့်ပင်မစာမျက်နှာá€á€½á€„် အမည်နှင့် သင်္ကေá€á€€á€­á€¯ အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€™á€œá€¬á€¸á‹</translation>
<translation id="5916664084637901428">ဖွင့်ရန်</translation>
<translation id="5922853908706496913">သင့်ဖန်သားပြင်ကို မျှá€á€±á€”ေသည်</translation>
<translation id="5939518447894949180">ပြန်ညှိ</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">ပြင်ပကုမ္ပá€á€®á€€á€½á€á€ºá€€á€®á€¸á€™á€»á€¬á€¸á€€á€­á€¯ ပိá€á€ºá€†á€­á€¯á€·á€™á€Šá€º</translation>
<translation id="6206551242102657620">á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€žá€Šá€º လုံá€á€¼á€¯á€¶á€•á€«á€žá€Šá€ºá‹ á€á€˜á€ºá€†á€­á€¯á€€á€º အá€á€»á€€á€ºá€¡á€œá€€á€º</translation>
<translation id="6216432067784365534">ရွေးစရာ <ph name="NAME_OF_LIST_ITEM" /> á€á€¯</translation>
+<translation id="6260852843601447737">ပိá€á€ºá€•á€¼á€®á€¸ အလွဲသုံးစားပြုá€á€¼á€„်းကို á€á€­á€¯á€„်ကြားရန်</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> နှင့် <ph name="PERMISSION_2" /> ပိá€á€ºá€‘ားသည်</translation>
<translation id="6270391203985052864">á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€€ အကြောင်းကြားá€á€»á€€á€ºá€™á€»á€¬á€¸á€•á€­á€¯á€·á€›á€”် á€á€±á€¬á€„်းဆိုနိုင်သည်</translation>
<translation id="6295158916970320988">ဆိုဒ်များအားလုံး</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> က သင့်á€á€Šá€ºá€”ေရာကို သုံးနိုင်ရန် <ph name="BEGIN_LINK" />Android ဆက်á€á€„်များ<ph name="END_LINK" /> á€á€½á€„်လည်း á€á€Šá€ºá€”ေရာကို ဖွင့်ပါá‹</translation>
<translation id="8447861592752582886">စက်ပစ္စည်းá€á€½á€„့်ပြုá€á€»á€€á€ºá€€á€­á€¯ ရုပ်သိမ်းပါ</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{ကွá€á€ºá€€á€®á€¸á€á€…်á€á€¯á€€á€­á€¯ သုံးနေသည်}other{အသုံးပြုနေသော ကွá€á€ºá€€á€®á€¸ # á€á€¯}}</translation>
-<translation id="8463851957836045671">á€á€˜á€ºá€†á€­á€¯á€€á€ºá€€ မြန်သည်</translation>
<translation id="8487700953926739672">Offline ရနိုင်</translation>
<translation id="851751545965956758">စက်သို့ á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸ á€á€»á€­á€á€ºá€†á€€á€ºá€á€¼á€„်းကို ပိá€á€ºá€‘ားသည်</translation>
<translation id="8525306231823319788">မျက်နှာပြင် အပြည့်</translation>
<translation id="857943718398505171">á€á€½á€„့်ပြုá (အကြံပြုထား)</translation>
<translation id="8609465669617005112">အပေါ်ရွှေ့ပါ</translation>
+<translation id="861748745608658996">သင့်ပင်မစာမျက်နှာá€á€½á€„် အမည်ကို အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€™á€œá€¬á€¸á‹</translation>
<translation id="8676374126336081632">ထည့်သွင်းမှု ရှင်းရန်</translation>
<translation id="868929229000858085">သင်áအဆက်အသွယ်များကို ရှာရန်</translation>
<translation id="8702612070107455751">အော့ဖ်လိုင်းဒေá€á€¬ မှန်သမျှကို ရှင်းထုá€á€ºá€œá€­á€¯á€€á€ºá€•á€«á€™á€Šá€ºá‹</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">á€á€»á€²á€·á€€á€¼á€Šá€·á€ºá€•á€«</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">ဤစက်အá€á€½á€€á€º NFC ကို ပိá€á€ºá€‘ားသည်ዠ<ph name="BEGIN_LINK" />Android ဆက်á€á€„်များ<ph name="END_LINK" /> ထဲá€á€½á€„် áŽá€„်းကို ဖွင့်ပါá‹</translation>
-<translation id="8929372349074745002">ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€žá€Šá€º လူအများစုအá€á€½á€€á€º မြန်ဆန်စွာ ပွင့်ပြီး á€á€¯á€¶á€·á€•á€¼á€”်သည်</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ရုပ်ဖျက်မုဒ်မှ ထွက်လိုပါသလားá‹</translation>
<translation id="8958424370300090006">အá€á€»á€­á€¯á€·á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€¡á€á€½á€€á€º ကွá€á€ºá€€á€®á€¸á€™á€»á€¬á€¸á€€á€­á€¯ ပိá€á€ºá€†á€­á€¯á€·á€žá€Šá€ºá‹</translation>
<translation id="8959122750345127698">သွားလာမှုပြလမ်းညွှန်ဆီသို့ မရောက်နိုင်ပါ- <ph name="URL" /></translation>
<translation id="8986362086234534611">မေ့ပစ်လိုက်ပါ</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ne.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ne.xtb
index 17208eb0832..fb9e0b7abf8 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ne.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ne.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ne">
<translation id="1006017844123154345">अनलाइन खोलà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="1044891598689252897">साइटहरू सामानà¥à¤¯ रूपमा चलà¥à¤¨à¥‡ छनà¥</translation>
+<translation id="1100504063505580045">हालको आइकन</translation>
<translation id="1124090076051167250">यस कारà¥à¤¯à¤²à¥‡ साइट वा à¤à¤ªà¤¹à¤°à¥‚ले तपाईंको होम सà¥à¤•à¥à¤°à¤¿à¤¨à¤®à¤¾ भणà¥à¤¡à¤¾à¤°à¤£ गरेका <ph name="DATASIZE" /> बराबरका डेटा र कà¥à¤•à¥€à¤¹à¤°à¥‚ मेटाउने छ।</translation>
<translation id="1124772482545689468">पà¥à¤°à¤¯à¥‹à¤—करà¥à¤¤à¤¾</translation>
<translation id="1178581264944972037">पज गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">माइकà¥à¤°à¥‹à¤«à¥‹à¤¨</translation>
<translation id="3277252321222022663">साइटहरूलाई सेनà¥à¤¸à¤°à¤¹à¤°à¥‚माथि पहà¥à¤à¤š राखà¥à¤¨à¥‡ अनà¥à¤®à¤¤à¤¿ दिनà¥à¤¹à¥‹à¤¸à¥ (सिफारिस गरिà¤à¤•à¥‹)</translation>
<translation id="3295602654194328831">जानकारी लà¥à¤•à¤¾à¤‰à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="3317660236277031814">तपाईंले इनà¥à¤¸à¥à¤Ÿà¤² गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ कà¥à¤¨à¥ˆ वेब à¤à¤ªà¤²à¥‡ उसको आइकन परिवरà¥à¤¤à¤¨ गरेको छ।</translation>
<translation id="3328801116991980348">साइट जानकारी</translation>
<translation id="3333961966071413176">सबै समà¥à¤ªà¤°à¥à¤•à¤¹à¤°à¥‚</translation>
<translation id="3386292677130313581">साइटहरूलाई तपाईà¤à¤•à¥‹ सà¥à¤¥à¤¾à¤¨ थाहा पाउने अनà¥à¤®à¤¤à¤¿ दिनॠभनà¥à¤¦à¤¾ पहिले तपाईà¤à¤²à¤¾à¤ˆ सोधà¥à¤¨à¥‡ (सिफारिस गरिà¤à¤•à¥‹)</translation>
+<translation id="345699454248713913">तपाईंले इनà¥à¤¸à¥à¤Ÿà¤² गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ कà¥à¤¨à¥ˆ वेब à¤à¤ªà¤²à¥‡ उसको नाम परिवरà¥à¤¤à¤¨ गरेको छ।</translation>
<translation id="3538390592868664640">साइटहरूलाई आफू वरपरको ठाउà¤à¤•à¥‹ 3D नकà¥à¤¸à¤¾ बनाउन वा कà¥à¤¯à¤¾à¤®à¥‡à¤°à¤¾à¤•à¥‹ अवसà¥à¤¥à¤¾ पतà¥à¤¤à¤¾ लगाउन नदिनà¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="3551268116566418498">इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोडबाट बाहिरिने हो?</translation>
<translation id="3586500876634962664">कà¥à¤¯à¤¾à¤®à¥‡à¤°à¤¾ र माइकà¥à¤°à¥‹à¤«à¥‹à¤¨à¤•à¥‹ पà¥à¤°à¤¯à¥‹à¤—</translation>
<translation id="358794129225322306">साइटलाई à¤à¤•à¤­à¤¨à¥à¤¦à¤¾ बढी फाइलहरू सà¥à¤µà¤¤à¤ƒ डाउनलोड गरà¥à¤¨à¥‡ अनà¥à¤®à¤¤à¤¿ दिनà¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
<translation id="3594780231884063836">भिडियो मà¥à¤¯à¥à¤Ÿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">सà¥à¤¥à¤¾à¤¨à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ सेटिङ खोलà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4226663524361240545">सूचनाहरूले गरà¥à¤¦à¤¾ यनà¥à¤¤à¥à¤° कमà¥à¤ªà¤¨ गरà¥à¤¨ सकà¥à¤›</translation>
<translation id="4259722352634471385">नेभिगेशन रोकियो: <ph name="URL" /></translation>
+<translation id="4277239631747669329">तपाईंले इनà¥à¤¸à¥à¤Ÿà¤² गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ कà¥à¤¨à¥ˆ वेब à¤à¤ªà¤²à¥‡ उसको नाम र आइकन परिवरà¥à¤¤à¤¨ गरेको छ।</translation>
<translation id="4278390842282768270">अनà¥à¤®à¤¤à¤¿ पà¥à¤°à¤¾à¤ªà¥à¤¤</translation>
<translation id="429312253194641664">कà¥à¤¨à¥ˆ साइटले मिडियो पà¥à¤²à¥‡ गरिरहेको छ</translation>
<translation id="42981349822642051">विसà¥à¤¤à¥ƒà¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4336434711095810371">सबै डेटा मेटाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4402755511846832236">तपाईं यो डिभाइस चलाउà¤à¤¦à¥ˆ हà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤› कि हà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤¨ भनà¥à¤¨à¥‡ कà¥à¤°à¤¾ साइटहरूलाई थाहा पाउन नदिनà¥à¤¹à¥‹à¤¸à¥</translation>
-<translation id="4433925000917964731">Google ले पà¥à¤°à¤¦à¤¾à¤¨ गरेको मूल पृषà¥à¤ à¤•à¥‹ लाइट संसà¥à¤•à¤°à¤£</translation>
<translation id="4434045419905280838">पपअप तथा रिडिरेकà¥à¤Ÿà¤¹à¤°à¥‚</translation>
<translation id="445467742685312942">साइटहरूलाई संरकà¥à¤·à¤¿à¤¤ सामगà¥à¤°à¥€ पà¥à¤²à¥‡ गरà¥à¤¨à¥‡ अनà¥à¤®à¤¤à¤¿ दिनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4468959413250150279">निशà¥à¤šà¤¿à¤¤ साइटको धà¥à¤µà¤¨à¤¿ मà¥à¤¯à¥à¤Ÿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">तपाईà¤à¤•à¥‹ अविभावक दà¥à¤µà¤¾à¤°à¤¾ पà¥à¤°à¤¬à¤¨à¥à¤§ गरिà¤à¤•à¥‹</translation>
<translation id="4670064810192446073">भरà¥à¤šà¥à¤…ल रियालिटी</translation>
<translation id="4708011789095599544">तपाईं साà¤à¤šà¥à¤šà¤¿à¤•à¥ˆ यो वेबसाइटका कà¥à¤•à¥€ र अनà¥à¤¯ डेटा हटाउन चाहनà¥à¤¹à¥à¤¨à¥à¤›?</translation>
+<translation id="473775607612524610">अपडेट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4751476147751820511">गति वा पà¥à¤°à¤•à¤¾à¤¶à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ सेनà¥à¤¸à¤°à¤¹à¤°à¥‚</translation>
<translation id="4836046166855586901">कà¥à¤¨à¥ˆ साइटले मैले यो डिभाइस चलाइरहेको छॠकि छà¥à¤‡à¤¨à¤ भनà¥à¤¨à¥‡ कà¥à¤°à¤¾à¤•à¥‹ जानकारी मागà¥à¤¦à¤¾ मलाई सोधियोसà¥</translation>
<translation id="4883854917563148705">वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¿à¤¤ सेटिङ रिसेट गरà¥à¤¨ सकिà¤à¤¦à¥ˆà¤¨</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">मारà¥à¤«à¤¤ साà¤à¤¾ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="5039804452771397117">अनà¥à¤®à¤¤à¤¿ दिनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="5048398596102334565">साइटहरूलाई चालसमà¥à¤¬à¤¨à¥à¤§à¥€ सेनà¥à¤¸à¤°à¤¹à¤°à¥‚माथि पहà¥à¤à¤š राखà¥à¤¨à¥‡ अनà¥à¤®à¤¤à¤¿ दिनà¥à¤¹à¥‹à¤¸à¥â€Œ (सिफारिस गरिà¤à¤•à¥‹)</translation>
+<translation id="5050380848339752099">यो साइटले इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोडबाहिरको à¤à¤ªà¤¸à¤à¤— जानकारी सेयर गरà¥à¤¨ लागिरहेको छ।</translation>
<translation id="5063480226653192405">उपयोग</translation>
<translation id="5100237604440890931">संकà¥à¤·à¤¿à¤ªà¥à¤¤ भयो - विसà¥à¤¤à¥ƒà¤¤ गरà¥à¤¨ कà¥à¤²à¤¿à¤• गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="5123685120097942451">इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ टà¥à¤¯à¤¾à¤¬</translation>
@@ -153,16 +159,17 @@
<translation id="5335288049665977812">साइटहरूलाई JavaScript सञà¥à¤šà¤¾à¤²à¤¨ गरà¥à¤¨ अनà¥à¤®à¤¤à¤¿ दिने (सिफारिस गरिà¤à¤•à¥‹)</translation>
<translation id="534295439873310000">NFC यनà¥à¤¤à¥à¤°à¤¹à¤°à¥‚</translation>
<translation id="5354152178998424783">यस कारà¥à¤¯à¤²à¥‡ साइटहरूले भणà¥à¤¡à¤¾à¤°à¤£ गरेका <ph name="DATASIZE" /> डेटा तथा कà¥à¤•à¥€à¤¹à¤°à¥‚ मेटाउने छ।</translation>
-<translation id="5384883051496921101">यो साइटले इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोड बाहिरको अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—सà¤à¤— जानकारी आदान पà¥à¤°à¤¦à¤¾à¤¨ गरà¥à¤¨ लागà¥à¤¦à¥ˆà¤›à¥¤</translation>
+<translation id="536508626067510330">तपाईंको होम सà¥à¤•à¥à¤°à¤¿à¤¨à¤®à¤¾ भà¤à¤•à¥‹ आइकन बदलà¥à¤¨à¥‡ हो?</translation>
<translation id="5391532827096253100">यस साइटमा तपाईंको जडान सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ छैन। साइटसमà¥à¤¬à¤¨à¥à¤§à¥€ जानकारी</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ १ थप)}other{(+ # थप)}}</translation>
<translation id="5403592356182871684">नामहरू</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" /> मधà¥à¤¯à¥‡ <ph name="ELAPSED_TIME" /> समय बितà¥à¤¯à¥‹à¥¤</translation>
<translation id="5494752089476963479">हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ªà¤•à¤¾à¤°à¥€ वा भà¥à¤°à¤¾à¤®à¤• विजà¥à¤žà¤¾à¤ªà¤¨ देखाउने साइटका विजà¥à¤žà¤¾à¤ªà¤¨à¤¹à¤°à¥‚लाई रोक लगाउनà¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="549957179819296104">नयाठआइकन</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> समà¥à¤¬à¤¨à¥à¤§à¥€ अनà¥à¤®à¤¤à¤¿ दिइà¤à¤•à¥‹ छ, <ph name="PERMISSION_2" /> बà¥à¤²à¤• गरिà¤à¤•à¥‹ छ</translation>
<translation id="5505264765875738116">साइटहरूले सूचनाहरू पठाउनका निमà¥à¤¤à¤¿ अनà¥à¤®à¤¤à¤¿ मागà¥à¤¨ सकà¥à¤¦à¥ˆà¤¨à¤¨à¥à¥¤</translation>
<translation id="5516455585884385570">सूचनाका सेटिङहरू खोलà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
-<translation id="5527111080432883924">साइटहरूलाई कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡à¤•à¤¾ पाठ तथा छविहरू पढà¥à¤¨à¥‡ अनà¥à¤®à¤¤à¤¿ दिनà¥à¤­à¤¨à¥à¤¦à¤¾ पहिले सोधà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ (सिफारिस गरिà¤à¤•à¥‹)</translation>
+<translation id="5527111080432883924">साइटहरूलाई कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡à¤•à¤¾ पाठ तथा फोटो पढà¥à¤¨à¥‡ अनà¥à¤®à¤¤à¤¿ दिनà¥à¤­à¤¨à¥à¤¦à¤¾ पहिले सोधà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ (सिफारिस गरिà¤à¤•à¥‹)</translation>
<translation id="5556459405103347317">पà¥à¤¨: लोड गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="5596627076506792578">अनà¥à¤¯ विकलà¥à¤ªà¤¹à¤°à¥‚</translation>
<translation id="5649053991847567735">सà¥à¤µà¤šà¤¾à¤²à¤¿à¤¤ डाउनलोडहरू</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">अनà¥à¤®à¤¤à¤¿à¤¹à¤°à¥‚</translation>
<translation id="5860033963881614850">बनà¥à¤¦</translation>
<translation id="5876056640971328065">भिडियो पज गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="5904826301761575486">तपाईंको होम सà¥à¤•à¥à¤°à¤¿à¤¨à¤®à¤¾ भà¤à¤•à¥‹ नाम र आइकन बदलà¥à¤¨à¥‡ हो?</translation>
<translation id="5916664084637901428">अन</translation>
<translation id="5922853908706496913">तपाईंको सà¥à¤•à¥à¤°à¤¿à¤¨ सेयर गरà¥à¤¦à¥ˆ</translation>
<translation id="5939518447894949180">रिसेट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">तेसà¥à¤°à¥‹ पकà¥à¤·à¥€à¤¯ कà¥à¤•à¥€à¤¹à¤°à¥‚माथि रोक लगाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6206551242102657620">जडान सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ छ। साइटसमà¥à¤¬à¤¨à¥à¤§à¥€ जानकारी</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> विकलà¥à¤ªà¤¹à¤°à¥‚</translation>
+<translation id="6260852843601447737">बनà¥à¤¦ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ र दà¥à¤°à¥à¤ªà¤¯à¥‹à¤—का बारेमा रिपोरà¥à¤Ÿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> र <ph name="PERMISSION_2" /> बà¥à¤²à¤• गरियो</translation>
<translation id="6270391203985052864">साइटहरूले सूचनाहरू पठाउनका निमà¥à¤¤à¤¿ अनà¥à¤®à¤¤à¤¿ मागà¥à¤¨ सकà¥à¤›à¤¨à¥à¥¤</translation>
<translation id="6295158916970320988">सबै साइटहरू</translation>
@@ -216,7 +225,7 @@
<translation id="6818926723028410516">वसà¥à¤¤à¥à¤¹à¤°à¥‚ छनाैट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6864395892908308021">यस यनà¥à¤¤à¥à¤°à¤²à¥‡ NFC पढà¥à¤¨ सकà¥à¤¦à¥ˆà¤¨</translation>
<translation id="6910211073230771657">मेटाइà¤à¤•à¥‹</translation>
-<translation id="6912998170423641340">साइटहरूलाई कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡à¤•à¤¾ पाठ तथा छविहरू पढà¥à¤¨à¤¬à¤¾à¤Ÿ रोक लगाउनà¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="6912998170423641340">साइटहरूलाई कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡à¤•à¤¾ पाठ तथा फोटो पढà¥à¤¨à¤¬à¤¾à¤Ÿ रोक लगाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6945221475159498467">चयन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6963642900430330478">यो पृषà¥à¤  खतरनाक छ। साइटसमà¥à¤¬à¤¨à¥à¤§à¥€ जानकारी</translation>
<translation id="6965382102122355670">ठिक छ</translation>
@@ -229,7 +238,7 @@
<translation id="7128222689758636196">हालको खोज इनà¥à¤œà¤¿à¤¨à¤•à¤¾ लागि अनà¥à¤®à¤¤à¤¿ दिनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7141896414559753902">साइटहरूलाई पपअपहरू देखाउन र रिडिरेकà¥à¤Ÿ गरà¥à¤¨à¤¬à¤¾à¤Ÿ रोकà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ (सिफारिस गरिà¤à¤•à¥‹)</translation>
<translation id="7176368934862295254"><ph name="KILOBYTES" /> के.बि.</translation>
-<translation id="723171743924126238">छविहरू चयन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="723171743924126238">फोटो चयन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7243308994586599757">विकलà¥à¤ªà¤¹à¤°à¥‚ सà¥à¤•à¥à¤°à¤¿à¤¨à¤•à¥‹ तल नजिकै उपलबà¥à¤§ छ</translation>
<translation id="7250468141469952378"><ph name="ITEM_COUNT" /> चयन गरिà¤</translation>
<translation id="7260727271532453612"><ph name="PERMISSION_1" /> र <ph name="PERMISSION_2" /> समà¥à¤¬à¤¨à¥à¤§à¥€ अनà¥à¤®à¤¤à¤¿ दिइà¤à¤•à¥‹ छ</translation>
@@ -249,7 +258,7 @@
<translation id="780301667611848630">भयो, धनà¥à¤¯à¤µà¤¾à¤¦</translation>
<translation id="7804248752222191302">कà¥à¤¨à¥ˆ साइटले तपाईंको कà¥à¤¯à¤¾à¤®à¥‡à¤°à¤¾ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¦à¥ˆ छ</translation>
<translation id="7817023149356982970">तपाईं यो साइटबाट साइन आउट हà¥à¤¨à¥ हà¥à¤¨à¥‡ छ।</translation>
-<translation id="7828557259026017104">कà¥à¤•à¥€à¤¹à¤°à¥‚ भनेका तपाईं जाने वेबसाइटहरूले सिरà¥à¤œà¤¨à¤¾ गरà¥à¤¨à¥‡ फाइल हà¥à¤¨à¥à¥¤ तपाईंका पà¥à¤°à¤¾à¤¥à¤®à¤¿à¤•à¤¤à¤¾à¤¹à¤°à¥‚ याद राखà¥à¤¨ वेबसाइटहरूले ती कà¥à¤•à¥€à¤¹à¤°à¥‚को पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤›à¤¨à¥à¥¤ अनà¥à¤¯ वेबसाइटहरूले तेसà¥à¤°à¥‹ पकà¥à¤·à¥€à¤¯ कà¥à¤•à¥€à¤¹à¤°à¥‚ सिरà¥à¤œà¤¨à¤¾ गरà¥à¤›à¤¨à¥à¥¤ तपाईं जाने वेबपृषà¥à¤ à¤®à¤¾ तपाईंले देखà¥à¤¨à¥‡ विजà¥à¤žà¤¾à¤ªà¤¨ वा छविहरू जसà¥à¤¤à¤¾ केही सामगà¥à¤°à¥€ यी वेबसाइटहरूको सà¥à¤µà¤¾à¤®à¤¿à¤¤à¥à¤µà¤®à¤¾ हà¥à¤¨à¥à¤›à¤¨à¥à¥¤</translation>
+<translation id="7828557259026017104">कà¥à¤•à¥€à¤¹à¤°à¥‚ भनेका तपाईं जाने वेबसाइटहरूले सिरà¥à¤œà¤¨à¤¾ गरà¥à¤¨à¥‡ फाइल हà¥à¤¨à¥à¥¤ तपाईंका पà¥à¤°à¤¾à¤¥à¤®à¤¿à¤•à¤¤à¤¾à¤¹à¤°à¥‚ याद राखà¥à¤¨ वेबसाइटहरूले ती कà¥à¤•à¥€à¤¹à¤°à¥‚को पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤›à¤¨à¥à¥¤ अनà¥à¤¯ वेबसाइटहरूले तेसà¥à¤°à¥‹ पकà¥à¤·à¥€à¤¯ कà¥à¤•à¥€à¤¹à¤°à¥‚ सिरà¥à¤œà¤¨à¤¾ गरà¥à¤›à¤¨à¥à¥¤ तपाईं जाने वेबपृषà¥à¤ à¤®à¤¾ तपाईंले देखà¥à¤¨à¥‡ विजà¥à¤žà¤¾à¤ªà¤¨ वा फोटो जसà¥à¤¤à¤¾ केही सामगà¥à¤°à¥€ यी वेबसाइटहरूको सà¥à¤µà¤¾à¤®à¤¿à¤¤à¥à¤µà¤®à¤¾ हà¥à¤¨à¥à¤›à¤¨à¥à¥¤</translation>
<translation id="7835852323729233924">पà¥à¤²à¥‡ भइरहेको मिडिया</translation>
<translation id="783819812427904514">भिडियो अनमà¥à¤¯à¥à¤Ÿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7846076177841592234">चयन रदà¥à¤¦ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -279,15 +288,15 @@
<translation id="8394832520002899662">साइटमा फरà¥à¤•à¤¨ टà¥à¤¯à¤¾à¤ª गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8425213833346101688">परिवरà¥à¤¤à¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8441146129660941386">पछाडि खोजà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
-<translation id="8444433999583714703"><ph name="APP_NAME" /> लाई आफà¥à¤¨à¥‹ सà¥à¤¥à¤¾à¤¨ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨ दिन <ph name="BEGIN_LINK" />Android का सेटिङ<ph name="END_LINK" />मा गई सà¥à¤¥à¤¾à¤¨à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ सेवा पनि अन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
+<translation id="8444433999583714703"><ph name="APP_NAME" /> लाई आफà¥à¤¨à¥‹ सà¥à¤¥à¤¾à¤¨ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨ दिन <ph name="BEGIN_LINK" />Android का सेटिङ<ph name="END_LINK" />मा गई लोकेसन सरà¥à¤­à¤¿à¤¸ पनि अन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
<translation id="8447861592752582886">यनà¥à¤¤à¥à¤° समà¥à¤¬à¤¨à¥à¤§à¥€ अनà¥à¤®à¤¤à¤¿à¤²à¤¾à¤ˆ उलà¥à¤Ÿà¤¾à¤‰à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{à¤à¤‰à¤Ÿà¤¾ कà¥à¤•à¥€ पà¥à¤°à¤¯à¥‹à¤— भइरहेको छ}other{# वटा कà¥à¤•à¥€ पà¥à¤°à¤¯à¥‹à¤— भइरहेका छनà¥}}</translation>
-<translation id="8463851957836045671">साइट दà¥à¤°à¥‚त छ</translation>
<translation id="8487700953926739672">अफलाईन उपलबà¥à¤§</translation>
<translation id="851751545965956758">साइटहरूलाई यनà¥à¤¤à¥à¤°à¤®à¤¾ जडान गरà¥à¤¨à¤¬à¤¾à¤Ÿ रोक लगाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8525306231823319788">पूरà¥à¤£ सà¥à¤•à¥à¤°à¥€à¤¨</translation>
<translation id="857943718398505171">(सिफारिस गरिà¤à¤•à¥‹) अनà¥à¤®à¤¤à¤¿ दिà¤à¤•à¥‹</translation>
<translation id="8609465669617005112">माथि सारà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="861748745608658996">तपाईंको होम सà¥à¤•à¥à¤°à¤¿à¤¨à¤®à¤¾ भà¤à¤•à¥‹ नाम बदलà¥à¤¨à¥‡ हो?</translation>
<translation id="8676374126336081632">आगत मेटाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="868929229000858085">आफà¥à¤¨à¤¾ समà¥à¤ªà¤°à¥à¤•à¤¹à¤°à¥‚ खोजà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8702612070107455751">सबै अफलाइन डेटा हटाइने छ।</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">जà¥à¤® इन</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">यो डिभाइसमा NFC निषà¥à¤•à¥à¤°à¤¿à¤¯ पारिà¤à¤•à¥‹ छ। <ph name="BEGIN_LINK" />Android का सेटिङ<ph name="END_LINK" /> मा गई यसलाई सकà¥à¤°à¤¿à¤¯ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
-<translation id="8929372349074745002">यो साइट धेरै जसो मानà¥à¤›à¥‡à¤•à¤¾ यनà¥à¤¤à¥à¤°à¤®à¤¾ छिटà¥à¤Ÿà¥ˆ खà¥à¤²à¥à¤›</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोड छोडà¥à¤¨à¥‡ हो?</translation>
<translation id="8958424370300090006">कà¥à¤¨à¥ˆ खास साइटमा कà¥à¤•à¥€à¤¹à¤°à¥‚लाई रोक लगाउनà¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
<translation id="8959122750345127698">नेभिगेशन पहà¥à¤à¤šà¤¯à¥‹à¤—à¥à¤¯ छैन: <ph name="URL" /></translation>
<translation id="8986362086234534611">बिरà¥à¤¸à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_nl.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_nl.xtb
index 1b1b7f88842..fc52ef674ec 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_nl.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_nl.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="nl">
<translation id="1006017844123154345">Online openen</translation>
<translation id="1044891598689252897">Sites werken naar behoren</translation>
+<translation id="1100504063505580045">Huidig icoon</translation>
<translation id="1124090076051167250">Hiermee wis je <ph name="DATASIZE" /> aan gegevens en cookies die zijn opgeslagen door sites of apps op je startscherm.</translation>
<translation id="1124772482545689468">Gebruiker</translation>
<translation id="1178581264944972037">Onderbreken</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Microfoon</translation>
<translation id="3277252321222022663">Sites toegang geven tot sensoren (aanbevolen)</translation>
<translation id="3295602654194328831">Informatie verbergen</translation>
+<translation id="3317660236277031814">Het icoon is gewijzigd voor een web-app die je hebt geïnstalleerd.</translation>
<translation id="3328801116991980348">Site-informatie</translation>
<translation id="3333961966071413176">Alle contacten</translation>
<translation id="3386292677130313581">Vragen of je sites toegang wilt verlenen tot je locatie (aanbevolen)</translation>
+<translation id="345699454248713913">De naam is gewijzigd voor een web-app die je hebt geïnstalleerd.</translation>
<translation id="3538390592868664640">Voorkomen dat sites een 3D-kaart van je omgeving maken of de camerapositie volgen</translation>
+<translation id="3551268116566418498">Incognitomodus verlaten?</translation>
<translation id="3586500876634962664">Camera- en microfoongebruik</translation>
<translation id="358794129225322306">Een site toestaan automatisch meerdere bestanden te downloaden.</translation>
<translation id="3594780231884063836">Geluid van video uitzetten</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Locatie-instellingen openen</translation>
<translation id="4226663524361240545">Het apparaat kan trillen bij meldingen</translation>
<translation id="4259722352634471385">Navigatie is geblokkeerd: <ph name="URL" /></translation>
+<translation id="4277239631747669329">De naam en het icoon zijn gewijzigd voor een web-app die je hebt geïnstalleerd.</translation>
<translation id="4278390842282768270">Toegestaan</translation>
<translation id="429312253194641664">Een site speelt media af</translation>
<translation id="42981349822642051">Uitvouwen</translation>
<translation id="4336434711095810371">Alle gegevens wissen</translation>
<translation id="4402755511846832236">Voorkomen dat sites weten wanneer je dit apparaat actief gebruikt</translation>
-<translation id="4433925000917964731">Lite-pagina geleverd door Google</translation>
<translation id="4434045419905280838">Pop-ups en omleidingen</translation>
<translation id="445467742685312942">Sites toestaan om beschermde content af te spelen</translation>
<translation id="4468959413250150279">Geluid uitzetten voor een specifieke site.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Beheerd door je ouder</translation>
<translation id="4670064810192446073">Virtual reality</translation>
<translation id="4708011789095599544">Weet je zeker dat je de cookies en andere sitegegevens wilt wissen voor deze website?</translation>
+<translation id="473775607612524610">Updaten</translation>
<translation id="4751476147751820511">Bewegings- of lichtsensoren</translation>
<translation id="4836046166855586901">Vragen als een site wil weten wanneer je dit apparaat actief gebruikt</translation>
<translation id="4883854917563148705">Beheerde instellingen kunnen niet worden gereset</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Delen via</translation>
<translation id="5039804452771397117">Toestaan</translation>
<translation id="5048398596102334565">Sites toegang geven tot bewegingssensoren (aanbevolen)</translation>
+<translation id="5050380848339752099">Deze site staat op het punt buiten de incognitomodus informatie met een app te delen.</translation>
<translation id="5063480226653192405">Gebruik</translation>
<translation id="5100237604440890931">Samengevouwen; klik om uit te vouwen.</translation>
<translation id="5123685120097942451">Incognitotabblad</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Sites toestaan JavaScript uit te voeren (aanbevolen)</translation>
<translation id="534295439873310000">NFC-apparaten</translation>
<translation id="5354152178998424783">Hiermee wis je <ph name="DATASIZE" /> aan gegevens en cookies die zijn opgeslagen door sites.</translation>
-<translation id="5384883051496921101">Deze site staat op het punt buiten de incognitomodus informatie met een app te delen.</translation>
+<translation id="536508626067510330">Icoon op het startscherm updaten?</translation>
<translation id="5391532827096253100">Je verbinding met deze site is niet beveiligd. Site-informatie</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(en nog 1)}other{(en nog #)}}</translation>
<translation id="5403592356182871684">Namen</translation>
<translation id="5489227211564503167">De verstreken tijd is <ph name="ELAPSED_TIME" /> van <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Advertenties blokkeren op sites die opdringerige of misleidende advertenties tonen</translation>
+<translation id="549957179819296104">Nieuw icoon</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> toegestaan, <ph name="PERMISSION_2" /> geblokkeerd</translation>
<translation id="5505264765875738116">Sites kunnen niet vragen of ze je meldingen mogen sturen</translation>
<translation id="5516455585884385570">Instellingen voor meldingen openen</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Rechten</translation>
<translation id="5860033963881614850">Uit</translation>
<translation id="5876056640971328065">Video pauzeren</translation>
+<translation id="5904826301761575486">Naam en icoon op het startscherm updaten?</translation>
<translation id="5916664084637901428">Aan</translation>
<translation id="5922853908706496913">Je scherm delen</translation>
<translation id="5939518447894949180">Resetten</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Cookies van derden blokkeren</translation>
<translation id="6206551242102657620">De verbinding is beveiligd. Site-informatie</translation>
<translation id="6216432067784365534">Opties voor <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Sluiten en misbruik melden</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> en <ph name="PERMISSION_2" /> geblokkeerd</translation>
<translation id="6270391203985052864">Sites kunnen vragen of ze je meldingen mogen sturen</translation>
<translation id="6295158916970320988">Alle sites</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Als je <ph name="APP_NAME" /> toegang wilt geven tot je locatie, moet je je locatie ook aanzetten via de <ph name="BEGIN_LINK" />Android-instellingen<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Rechten voor apparaat intrekken</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie in gebruik}other{# cookies in gebruik}}</translation>
-<translation id="8463851957836045671">Site is snel</translation>
<translation id="8487700953926739672">Offline beschikbaar</translation>
<translation id="851751545965956758">Voorkomen dat sites verbinding maken met apparaten</translation>
<translation id="8525306231823319788">Volledig scherm</translation>
<translation id="857943718398505171">Toegestaan (aanbevolen)</translation>
<translation id="8609465669617005112">Omhoog</translation>
+<translation id="861748745608658996">Naam op het startscherm updaten?</translation>
<translation id="8676374126336081632">Invoer wissen</translation>
<translation id="868929229000858085">Zoek in je contacten</translation>
<translation id="8702612070107455751">Alle offline gegevens worden gewist.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Inzoomen</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC staat uit voor dit apparaat. Zet deze functie aan via de <ph name="BEGIN_LINK" />Android-instellingen<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Deze site opent en reageert snel voor de meeste mensen</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Incognitomodus verlaten?</translation>
<translation id="8958424370300090006">Cookies voor een specifieke site blokkeren.</translation>
<translation id="8959122750345127698">Navigatie is onbereikbaar: <ph name="URL" /></translation>
<translation id="8986362086234534611">Vergeten</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_no.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_no.xtb
index 83c21bb67b4..a49b99f237b 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_no.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_no.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="no">
<translation id="1006017844123154345">Åpne på nettet</translation>
<translation id="1044891598689252897">Nettsteder kommer til å fungere som normalt</translation>
+<translation id="1100504063505580045">Nåværende ikon</translation>
<translation id="1124090076051167250">Dette sletter <ph name="DATASIZE" /> med data og informasjonskapsler som er lagret av nettsteder eller apper på startskjermen.</translation>
<translation id="1124772482545689468">Bruker</translation>
<translation id="1178581264944972037">Stans midlertidig</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Gi nettsteder tilgang til sensorer (anbefalt)</translation>
<translation id="3295602654194328831">Skjul informasjonen</translation>
+<translation id="3317660236277031814">Ikonet til et nettprogram du har installert, er endret.</translation>
<translation id="3328801116991980348">Informasjon om nettstedet</translation>
<translation id="3333961966071413176">Alle kontakter</translation>
<translation id="3386292677130313581">Spør før nettsteder får vite posisjonen min (anbefales)</translation>
+<translation id="345699454248713913">Navnet til et nettprogram du har installert, er endret.</translation>
<translation id="3538390592868664640">Blokkér nettsteder fra å lage 3D-kart av omgivelsene dine eller spore kameraposisjonen</translation>
+<translation id="3551268116566418498">Vil du avslutte Inkognitomodus?</translation>
<translation id="3586500876634962664">Kamera- og mikrofonbruk</translation>
<translation id="358794129225322306">Tillat at et nettsted kan laste ned flere filer automatisk.</translation>
<translation id="3594780231884063836">Kutt lyden i videoen</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Ã…pne posisjonsinnstillingene</translation>
<translation id="4226663524361240545">Varsler kan gjøre at enheten vibrerer</translation>
<translation id="4259722352634471385">Nettadressen er blokkert: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Navnet og ikonet til et nettprogram du har installert, er endret.</translation>
<translation id="4278390842282768270">Tillatt</translation>
<translation id="429312253194641664">Et nettsted spiller av medier</translation>
<translation id="42981349822642051">Vis</translation>
<translation id="4336434711095810371">Slett alle data</translation>
<translation id="4402755511846832236">Blokkér nettsteder fra å vite når du bruker denne enheten aktivt</translation>
-<translation id="4433925000917964731">Forenklet versjon av siden levert av Google</translation>
<translation id="4434045419905280838">Forgrunnsvinduer/viderekoblinger</translation>
<translation id="445467742685312942">Tillat at nettsteder kan spille beskyttet innhold</translation>
<translation id="4468959413250150279">Kutt lyden for et bestemt nettsted.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Administreres av foreldrene dine</translation>
<translation id="4670064810192446073">Virtuell virkelighet</translation>
<translation id="4708011789095599544">Er du sikker på at du vil slette informasjonskapsler og andre nettstedsdata for dette nettstedet?</translation>
+<translation id="473775607612524610">Oppdater</translation>
<translation id="4751476147751820511">Bevegelses- eller lyssensorer</translation>
<translation id="4836046166855586901">Spør når nettsteder vil vite når du bruker denne enheten aktivt</translation>
<translation id="4883854917563148705">Administrerte innstillinger kan ikke tilbakestilles</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Del via</translation>
<translation id="5039804452771397117">Tillat</translation>
<translation id="5048398596102334565">Gi nettsteder tilgang til bevegelsessensorer (anbefalt)</translation>
+<translation id="5050380848339752099">Dette nettstedet er i ferd med å dele informasjon med en app utenfor Inkognitomodus.</translation>
<translation id="5063480226653192405">Bruk</translation>
<translation id="5100237604440890931">Minimert – klikk for å utvide</translation>
<translation id="5123685120097942451">Inkognitofane</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Tillat nettsteder å kjøre JavaScript (anbefales)</translation>
<translation id="534295439873310000">NFC-enheter</translation>
<translation id="5354152178998424783">Dette sletter <ph name="DATASIZE" /> med data og informasjonskapsler som er lagret av nettsteder.</translation>
-<translation id="5384883051496921101">Dette nettstedet er i ferd med å dele informasjon med en app utenfor inkognitomodus.</translation>
+<translation id="536508626067510330">Vil du oppdatere ikonet på startskjermen din?</translation>
<translation id="5391532827096253100">Tilkoblingen din til dette nettstedet er ikke sikker. Informasjon om nettstedet</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 til)}other{(+ # til)}}</translation>
<translation id="5403592356182871684">Navn</translation>
<translation id="5489227211564503167">Medgått tid: <ph name="ELAPSED_TIME" /> av <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blokkér annonser på nettsteder som ofte viser forstyrrende eller villedende annonser</translation>
+<translation id="549957179819296104">Nytt ikon</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> er tillatt – <ph name="PERMISSION_2" /> er blokkert</translation>
<translation id="5505264765875738116">Nettsteder kan ikke be om å få sende deg varsler</translation>
<translation id="5516455585884385570">Ã…pne innstillingene for varsler</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Tillatelser</translation>
<translation id="5860033963881614850">Av</translation>
<translation id="5876056640971328065">Sett videoen på pause</translation>
+<translation id="5904826301761575486">Vil du oppdatere navnet og ikonet på startskjermen din?</translation>
<translation id="5916664084637901428">PÃ¥</translation>
<translation id="5922853908706496913">Deler skjermen din</translation>
<translation id="5939518447894949180">Tilbakestill</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokkér informasjonskapsler fra tredjeparter</translation>
<translation id="6206551242102657620">Tilkoblingen er sikker. Informasjon om nettstedet</translation>
<translation id="6216432067784365534">Alternativer for <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Lukk og rapportér misbruk</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> og <ph name="PERMISSION_2" /> er blokkert</translation>
<translation id="6270391203985052864">Nettsteder kan be om å få sende deg varsler</translation>
<translation id="6295158916970320988">Alle nettsteder</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">For å gi <ph name="APP_NAME" /> tilgang til posisjonen din må du også slå på posisjon i <ph name="BEGIN_LINK" />Android-innstillingene<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Opphev tillatelsen til enhetstilgang</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 informasjonskapsel er i bruk}other{# informasjonskapsler er i bruk}}</translation>
-<translation id="8463851957836045671">Nettstedet er raskt</translation>
<translation id="8487700953926739672">Tilgjengelig utenfor nettet</translation>
<translation id="851751545965956758">Blokkér at nettsteder kobler til enheter</translation>
<translation id="8525306231823319788">Full skjerm</translation>
<translation id="857943718398505171">Tillatt (anbefales)</translation>
<translation id="8609465669617005112">Flytt opp</translation>
+<translation id="861748745608658996">Vil du oppdatere navnet på startskjermen din?</translation>
<translation id="8676374126336081632">Slett teksten</translation>
<translation id="868929229000858085">Søk i kontaktene dine</translation>
<translation id="8702612070107455751">Eventuelle frakoblede data blir slettet.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Zoom inn</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC er av for denne enheten. Slå det på i <ph name="BEGIN_LINK" />Android-innstillingene<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Dette nettstedet åpnes og svarer raskt for de fleste</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Vil du avslutte inkognitomodus?</translation>
<translation id="8958424370300090006">Blokkér informasjonskapsler for et spesifikt nettsted.</translation>
<translation id="8959122750345127698">Nettadressen er utilgjengelig: <ph name="URL" /></translation>
<translation id="8986362086234534611">Glem</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_or.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_or.xtb
index b97c3f7a3dc..f517765ec87 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_or.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_or.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="or">
<translation id="1006017844123154345">ଅନà­â€Œà¬²à¬¾à¬‡à¬¨à­â€Œ ଖୋଲନà­à¬¤à­</translation>
<translation id="1044891598689252897">ସାଇଟଗà­à¬¡à¬¼à¬¿à¬• ସାଧାରଣ ଭାବେ କାମ କରିବ</translation>
+<translation id="1100504063505580045">ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨à¬° ଆଇକନà­</translation>
<translation id="1124090076051167250">ଆପଣଙà­à¬• ମୂଳ ସà­à¬•à­à¬°à¬¿à¬¨à¬°à­‡ ସାଇଟୠକିମà­à¬¬à¬¾ ଆପଗà­à¬¡à¬¼à¬¿à¬• ଦà­à­±à¬¾à¬°à¬¾ ଷà­à¬Ÿà­‹à¬°à­ କରାଯାଇଥିବା <ph name="DATASIZE" /> ଡାଟା à¬à¬¬à¬‚ କà­à¬•à­€à¬—à­à¬¡à¬¼à¬¿à¬•à­ à¬à¬¹à¬¾ ଖାଲି କରିଦେବ।</translation>
<translation id="1124772482545689468">ଉପଯୋଗକରà­à¬¤à­à¬¤à¬¾</translation>
<translation id="1178581264944972037">ବିରତି</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">ମାଇକà­à¬°à­‹à¬«à­‹à¬¨à­</translation>
<translation id="3277252321222022663">ସେନà­à¬¸à¬°à­ ଆକà­à¬¸à­‡à¬¸à­ କରିବାକୠସାଇଟà­â€Œà¬—à­à¬¡à¬¼à¬¿à¬•à­ ଅନà­à¬®à¬¤à¬¿ ଦିଅନà­à¬¤à­ (ସà­à¬ªà¬¾à¬°à¬¿à¬¶ କରାଯାଇଛି)</translation>
<translation id="3295602654194328831">ସୂଚନା ଲà­à¬šà¬¾à¬¨à­à¬¤à­</translation>
+<translation id="3317660236277031814">ଆପଣ ଇନଷà­à¬Ÿà¬²à­ କରିଥିବା à¬à¬• ୱେବୠଆପୠà¬à¬¹à¬¾à¬° ଆଇକନୠବଦଳାଇଛି।</translation>
<translation id="3328801116991980348">ସାଇଟà­â€Œ ସୂଚନା</translation>
<translation id="3333961966071413176">ସମସà­à¬¤ ଯୋଗାଯୋଗଗà­à¬¡à¬¼à¬¿à¬•</translation>
<translation id="3386292677130313581">ସାଇଟà­â€à¬—à­à­œà¬¿à¬• ଆପଣଙà­à¬•à¬° ଲୋକେସନà­â€Œ ଜାଣିବା ପୂରà­à¬¬à¬°à­ ପଚାରନà­à¬¤à­ (ସà­à¬ªà¬¾à¬°à¬¿à¬¶à­â€Œ କରାଯାଇଛି)</translation>
+<translation id="345699454248713913">ଆପଣ ଇନଷà­à¬Ÿà¬²à­ କରିଥିବା à¬à¬• ୱେବୠଆପୠà¬à¬¹à¬¾à¬° ନାମ ବଦଳାଇଛି।</translation>
<translation id="3538390592868664640">ଆପଣଙà­à¬• ପରିପାରà­à¬¶à­à­±à¬° à¬à¬• 3D ମà­à­Ÿà¬¾à¬ªà­ ତିଆରି କରିବା à¬à¬¬à¬‚ କà­à­Ÿà¬¾à¬®à­‡à¬°à¬¾ ସà­à¬¥à¬¿à¬¤à¬¿ ଟà­à¬°à¬¾à¬•à­ କରିବାକୠସାଇଟଗà­à¬¡à¬¼à¬¿à¬•à­ ବà­à¬²à¬•à­ କରନà­à¬¤à­</translation>
+<translation id="3551268116566418498">ଇନକଗà­à¬¨à¬¿à¬Ÿà­‹ ମୋଡରୠବାହାରି ଯିବେ କି?</translation>
<translation id="3586500876634962664">କà­à­Ÿà¬¾à¬®à­‡à¬°à¬¾ à¬à¬¬à¬‚ ମାଇକà­à¬°à­‹à¬«à­‹à¬¨à¬° ବà­à­Ÿà¬¬à¬¹à¬¾à¬°</translation>
<translation id="358794129225322306">ସà­à­±à¬šà¬¾à¬³à¬¿à¬¤ ଭାବେ à¬à¬•à¬¾à¬§à¬¿à¬• ଫାଇଲୠଡାଉନà­â€Œà¬²à­‹à¬¡à­ କରିବା ପାଇଠଗୋଟିଠସାଇଟà­â€Œà¬•à­ ଅନà­à¬®à¬¤à¬¿ ଦିଅନà­à¬¤à­à¥¤</translation>
<translation id="3594780231884063836">ଭିଡିଓ ମà­à­Ÿà­à¬Ÿà­ କରନà­à¬¤à­</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">ଲୋକେସନୠସେଟିଂସୠଖୋଲନà­à¬¤à­</translation>
<translation id="4226663524361240545">ବିଜà­à¬žà¬ªà­à¬¤à¬¿ ଡିଭାଇସà­â€à¬•à­ ଭାଇବà­à¬°à­‡à¬Ÿà­ କରିପାରେ</translation>
<translation id="4259722352634471385">ନାଭିଗେସନୠଅବରୋଧ କରାଯାଇଛି: <ph name="URL" /></translation>
+<translation id="4277239631747669329">ଆପଣ ଇନଷà­à¬Ÿà¬²à­ କରିଥିବା à¬à¬• ୱେବୠଆପୠà¬à¬¹à¬¾à¬° ନାମ à¬à¬¬à¬‚ ଆଇକନୠବଦଳାଇଛି।</translation>
<translation id="4278390842282768270">ଅନà­à¬®à­‹à¬¦à¬¿à¬¤</translation>
<translation id="429312253194641664">କୌଣସି ସାଇଟୠମିଡିଆ ଚଲାଉଛି</translation>
<translation id="42981349822642051">ପà­à¬°à¬¸à¬¾à¬°à¬£ କରନà­à¬¤à­</translation>
<translation id="4336434711095810371">ସମସà­à¬¤ ଡାଟା ଖାଲି କରନà­à¬¤à­</translation>
<translation id="4402755511846832236">ଆପଣ କେତେବେଳେ ସକà­à¬°à¬¿à­Ÿ ଭାବେ à¬à¬¹à¬¿ ଡିଭାଇସକୠବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରà­à¬›à¬¨à­à¬¤à¬¿ ତାହା ଜାଣିବାରୠସାଇଟଗà­à¬¡à¬¼à¬¿à¬•à­ ବà­à¬²à¬•à­ କରନà­à¬¤à­</translation>
-<translation id="4433925000917964731">Google ଦà­à­±à¬¾à¬°à¬¾ ପà­à¬°à¬¦à¬¤à­à¬¤ ଲାଇଟୠପୃଷà­à¬ à¬¾</translation>
<translation id="4434045419905280838">ପପà­-ଅପୠà¬à¬¬à¬‚ ରିଡାଇରେକà­â€Œà¬Ÿ</translation>
<translation id="445467742685312942">ସାଇଟà­â€à¬—à­à­œà¬¿à¬•à­ ସà­à¬°à¬•à­à¬·à¬¿à¬¤ ବିଷୟବସà­à¬¤à­ ଚଳାଇବାକୠଅନà­à¬®à¬¤à¬¿ ଦିଅନà­à¬¤à­</translation>
<translation id="4468959413250150279">ଗୋଟିଠନିରà­à¬¦à­à¬¦à¬¿à¬·à­à¬Ÿ ସାଇଟୠପାଇଠସାଉଣà­à¬¡à¬•à­ ମà­à­Ÿà­à¬Ÿà­ କରନà­à¬¤à­à¥¤</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">ଆପଣଙà­à¬•à¬° ଅଭିବାବକଙà­à¬• ଦà­à­±à¬¾à¬°à¬¾ ପରିଚାଳିତ</translation>
<translation id="4670064810192446073">ଭରà­à¬šà­à¬†à¬²à­ ରିଆଲିଟୀ</translation>
<translation id="4708011789095599544">ଆପଣ à¬à¬¹à¬¿ ୱେବସାଇଟର କà­à¬•à­€à¬—à­à­œà¬¿à¬•à­ à¬à¬¬à¬‚ ଅନà­à­Ÿ ସାଇଟà­â€ ଡାଟା ଖାଲି କରିବାକୠଚାହà­à¬à¬¥à¬¿à¬¬à¬¾ ସà­à¬¨à¬¿à¬¶à­à¬šà¬¿à¬¤ କି?</translation>
+<translation id="473775607612524610">ଅପà­â€â€à¬¡à­‡à¬Ÿà­</translation>
<translation id="4751476147751820511">ମୋସନୠକିମà­à¬¬à¬¾ ଲାଇଟୠସେନà­à¬¸à¬°à­</translation>
<translation id="4836046166855586901">ଆପଣ କେତେବେଳେ à¬à¬¹à¬¿ ଡିଭାଇସକୠସକà­à¬°à¬¿à­Ÿ ଭାବରେ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରà­à¬›à¬¨à­à¬¤à¬¿ ତାହା କୌଣସି ସାଇଟୠଜାଣିବାକୠଚାହିà¬à¬²à­‡ ପଚାରନà­à¬¤à­</translation>
<translation id="4883854917563148705">ପରିଚାଳିତ ସେଟିଂଗà­à­œà¬¿à¬•à­ ରିସେଟୠକରାଯାଇପାରିବ ନାହିà¬</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">à¬à¬¹à¬¾ ମାଧà­à­Ÿà¬®à¬°à­‡ ସେୟାରୠକରନà­à¬¤à­</translation>
<translation id="5039804452771397117">ଅନà­à¬®à¬¤à¬¿</translation>
<translation id="5048398596102334565">ମୋସନୠସେନà­â€Œà¬¸à¬°à­ ଆକà­à¬¸à­‡à¬¸à­ କରିବାକୠସାଇଟà­â€Œà¬—à­à¬¡à¬¼à¬¿à¬•à­ ଅନà­à¬®à¬¤à¬¿ ଦିଅନà­à¬¤à­ (ସà­à¬ªà¬¾à¬°à¬¿à¬¶ କରାଯାଇଛି)</translation>
+<translation id="5050380848339752099">ଇନକଗà­à¬¨à¬¿à¬Ÿà­‹ ମୋଡୠବାହାରେ କୌଣସି à¬à¬• ଆପୠସହ à¬à¬¹à¬¿ ସାଇଟୠସୂଚନା ସେୟାରୠକରିବାକୠଯାଉଛି।</translation>
<translation id="5063480226653192405">ବà­à­Ÿà¬¬à¬¹à¬¾à¬°</translation>
<translation id="5100237604440890931">ସଙà­à¬•à­à¬šà¬¿à¬¤ ହୋଇଯାଇଛି - ବିସà­à¬¤à¬¾à¬° କରିବା ପାଇଠକà­à¬²à¬¿à¬•à­ କରନà­à¬¤à­à¥¤</translation>
<translation id="5123685120097942451">ଇନà­â€Œà¬•à¬—à­à¬¨à¬¿à¬Ÿà­‹ ଟାବà­</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">ସାଇଟà­â€Œà¬—à­à¬¡à¬¼à¬¿à¬•à­ JavaScript ଚଲାଇବା ପାଇଠଅନà­à¬®à¬¤à¬¿ ଦିଅନà­à¬¤à­ (ସà­à¬ªà¬¾à¬°à¬¿à¬¶ କରାଯାଇଛି)</translation>
<translation id="534295439873310000">NFC ଡିଭାଇସà­â€Œà¬—à­à­œà¬¿à¬•</translation>
<translation id="5354152178998424783">à¬à¬¹à¬¾ ସାଇଟଗà­à¬¡à¬¼à¬¿à¬• ଦà­à­±à¬¾à¬°à¬¾ ଷà­à¬Ÿà­‹à¬°à­ କରାଯାଇଥିବା <ph name="DATASIZE" /> ଡାଟା à¬à¬¬à¬‚ କà­à¬•à­€à¬—à­à¬¡à¬¼à¬¿à¬•à­ ଖାଲି କରିଦେବ।</translation>
-<translation id="5384883051496921101">à¬à¬¹à¬¿ ସାଇଟୠଇନà­â€Œà¬•à¬—à­à¬¨à¬¿à¬Ÿà­‹ ମୋଡà­â€â€à¬°à­‡ ବାହାରର କୌଣସି ଆପୠସହ ସୂଚନା ସେୟାରୠକରିବାକୠଯାଉଛି।</translation>
+<translation id="536508626067510330">ଆପଣଙà­à¬• ମୂଳସà­à¬•à­à¬°à¬¿à¬¨à¬°à­‡ ଆଇକନୠଅପଡେଟୠକରିବେ?</translation>
<translation id="5391532827096253100">à¬à¬¹à¬¿ ସାଇଟà­â€Œà¬•à­ ଆପଣଙà­à¬•à¬° ସଂଯୋଗ ସà­à¬°à¬•à­à¬·à¬¿à¬¤ ନà­à¬¹à­‡à¬ ସାଇଟୠସୂଚନା</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1ଟି ଅଧିକ)}other{(+ #ଟି ଅଧିକ)}}</translation>
<translation id="5403592356182871684">ନାମଗà­à­œà¬¿à¬•</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" />ର <ph name="ELAPSED_TIME" /> ବିତିଯାଇଥିବା ସମୟ।</translation>
<translation id="5494752089476963479">ଅନଧିକାର ପà­à¬°à¬¬à­‡à¬¶ କରିଥିବା କିମà­à¬¬à¬¾ ବିଭà­à¬°à¬¾à¬¨à­à¬¤à¬¿à¬•à¬° ବିଜà­à¬žà¬¾à¬ªà¬¨ ଦେଖାଉଥିବା ସାଇଟୠବà­à¬²à¬•à­ କରନà­à¬¤à­</translation>
+<translation id="549957179819296104">ନୂଆ ଆଇକନà­</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" />ର ଅନà­à¬®à¬¤à¬¿ ଦିଆଯାଇଛି, <ph name="PERMISSION_2" /> ବà­à¬²à¬•à­ କରାଯାଇଛି</translation>
<translation id="5505264765875738116">ବିଜà­à¬žà¬ªà­à¬¤à¬¿à¬—à­à­œà¬¿à¬•à­ ପଠାଇବାକୠସାଇଟà­â€Œà¬—à­à­œà¬¿à¬• ପଚାରିପାରିବେ ନାହିà¬</translation>
<translation id="5516455585884385570">ବିଜà­à¬žà¬ªà­à¬¤à¬¿ ସେଟିଂସୠଖୋଲନà­à¬¤à­</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">ଅନà­à¬®à¬¤à¬¿à¬—à­à¬¡à¬¼à¬¿à¬•</translation>
<translation id="5860033963881614850">ବନà­à¬¦ ଅଛି</translation>
<translation id="5876056640971328065">ଭିଡିଓ ବିରତ କରନà­à¬¤à­</translation>
+<translation id="5904826301761575486">ଆପଣଙà­à¬• ମୂଳସà­à¬•à­à¬°à¬¿à¬¨à¬°à­‡ ନାମ à¬à¬¬à¬‚ ଆଇକନୠଅପଡେଟୠକରିବେ?</translation>
<translation id="5916664084637901428">ଚାଲà­</translation>
<translation id="5922853908706496913">ଆପଣଙà­à¬• ସà­à¬•à­à¬°à¬¿à¬¨à­ ସେୟାରୠକରାଯାଉଛି</translation>
<translation id="5939518447894949180">ପà­à¬¨à¬ƒà¬¸à­‡à¬Ÿà­</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">ତୃତୀୟ ପକà­à¬· କà­à¬•à­€à¬—à­à­œà¬¿à¬•à­ ବà­à¬²à¬•à­ କରନà­à¬¤à­</translation>
<translation id="6206551242102657620">ସଂଯୋଗ ସà­à¬°à¬•à­à¬·à¬¿à¬¤ ଅଟେ। ସାଇଟୠସୂଚନା</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> ବିକଳà­à¬ª</translation>
+<translation id="6260852843601447737">ବନà­à¬¦ କରି ଅପବà­à­Ÿà¬¬à¬¹à¬¾à¬°à¬° ରିପୋରà­à¬Ÿ କରନà­à¬¤à­</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> à¬à¬¬à¬‚ <ph name="PERMISSION_2" />କୠବà­à¬²à¬•à­ କରାଯାଇଛି</translation>
<translation id="6270391203985052864">ବିଜà­à¬žà¬ªà­à¬¤à¬¿à¬—à­à­œà¬¿à¬•à­ ପଠାଇବାକୠସାଇଟà­â€Œà¬—à­à­œà¬¿à¬• ପଚାରିପାରିବେ</translation>
<translation id="6295158916970320988">ସମସà­à¬¤ ସାଇଟà­â€à¬—à­à­œà¬¿à¬•</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" />କୠଆପଣଙà­à¬• ଲୋକେସନୠଆକà­à¬¸à­‡à¬¸à­ ଦେବା ପାଇà¬, <ph name="BEGIN_LINK" />Android ସେଟିଂସ<ph name="END_LINK" />ରେ ଲୋକେସନୠମଧà­à­Ÿ ଚାଲୠକରନà­à¬¤à­à¥¤</translation>
<translation id="8447861592752582886">ଡିଭାଇସୠଅନà­à¬®à¬¤à¬¿ କାଢ଼ି ଦିଅନà­à¬¤à­</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1ଟି କà­à¬•à­€ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରାଯାଉଛି}other{#ଟି କà­à¬•à­€ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରାଯାଉଛି}}</translation>
-<translation id="8463851957836045671">ସାଇଟୠଶୀଘà­à¬° ଲୋଡୠହà­à¬</translation>
<translation id="8487700953926739672">ଅଫà­â€à¬²à¬¾à¬‡à¬¨à­â€Œà¬°à­‡ ଉପଲବà­à¬§</translation>
<translation id="851751545965956758">ସାଇଟà­â€Œà¬—à­à¬¡à¬¼à¬¿à¬•à­ ଡିଭାଇସà­â€Œà¬—à­à¬¡à¬¼à¬¿à¬• ସହିତ ସଂଯୋଗ ହେବାରୠବà­à¬²à¬•à­ କରନà­à¬¤à­</translation>
<translation id="8525306231823319788">ପୂରà­à¬£à­à¬£ ସà­à¬•à­à¬°à¬¿à¬¨à­â€Œ</translation>
<translation id="857943718398505171">ଅନà­à¬®à­‹à¬¦à¬¿à¬¤ (ସà­à¬ªà¬¾à¬°à¬¿à¬¶ କରାଯାଇଛି)</translation>
<translation id="8609465669617005112">ଉପରକୠଚଳନ କରନà­à¬¤à­</translation>
+<translation id="861748745608658996">ଆପଣଙà­à¬• ମୂଳସà­à¬•à­à¬°à¬¿à¬¨à¬°à­‡ ନାମ ଅପଡେଟୠକରିବେ?</translation>
<translation id="8676374126336081632">ଇନà­â€Œà¬ªà­à¬Ÿà­ ଖାଲି କରନà­à¬¤à­</translation>
<translation id="868929229000858085">ଆପଣଙà­à¬•à¬° ଯୋଗାଯୋଗ ସନà­à¬§à¬¾à¬¨ କରନà­à¬¤à­</translation>
<translation id="8702612070107455751">ଯେ କୌଣସି ଅଫଲାଇନୠଡାଟା ଖାଲି ହୋଇଯିବ।</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">ଜà­à¬®à­ ବà­à¬¾à¬¨à­à¬¤à­</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">à¬à¬¹à¬¿ ଡିଭାଇସୠପାଇଠNFC ବନà­à¬¦ ଅଛି। à¬à¬¹à¬¾à¬•à­ <ph name="BEGIN_LINK" />Android ସେଟିଂସà­â€Œ<ph name="END_LINK" />ରେ ଚାଲୠକରନà­à¬¤à­à¥¤</translation>
-<translation id="8929372349074745002">à¬à¬¹à¬¿ ସାଇଟୠଅଧିକାଂଶ ଲୋକଙà­à¬• ପାଇଠଶୀଘà­à¬° ଖୋଲିଥାଠà¬à¬¬à¬‚ ଶୀଘà­à¬° ବà­à­Ÿà¬¬à¬¹à¬¾à¬° ପାଇଠପà­à¬°à¬¸à­à¬¤à­à¬¤ ଥାà¬</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ଇନà­â€Œà¬•à¬—à­à¬¨à¬¿à¬Ÿà­‹ ମୋଡୠଛାଡ଼ିବେ?</translation>
<translation id="8958424370300090006">à¬à¬• ନିରà­à¬¦à­à¬¦à¬¿à¬·à­à¬Ÿ ସାଇଟୠପାଇଠକà­à¬•à­€à¬—à­à­œà¬¿à¬•à­ ଅବରୋଧ କରନà­à¬¤à­à¥¤</translation>
<translation id="8959122750345127698">ନାଭିଗେସନà­â€Œà¬°à­‡ ପହଞà­à¬šà¬¿ ହେଉନାହିà¬: <ph name="URL" /></translation>
<translation id="8986362086234534611">ଭà­à¬²à¬¿à¬—ଲେ</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pa.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pa.xtb
index 0b3b8ba5195..3c3cf3d3814 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pa.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pa.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="pa">
<translation id="1006017844123154345">ਆਨਲਾਈਨ ਖੋਲà©à¨¹à©‹</translation>
<translation id="1044891598689252897">ਸਾਈਟਾਂ ਸਹੀ ਤਰੀਕੇ ਨਾਲ ਕੰਮ ਕਰਨਗੀਆਂ</translation>
+<translation id="1100504063505580045">ਮੋਜੂਦਾ ਪà©à¨°à¨¤à©€à¨•</translation>
<translation id="1124090076051167250">ਇੰਠਕਰਨ ਨਾਲ ਤà©à¨¹à¨¾à¨¡à©€ ਹੋਮ ਸਕà©à¨°à©€à¨¨ 'ਤੇ ਸਾਈਟਾਂ ਜਾਂ à¨à¨ªà¨¾à¨‚ ਵੱਲੋਂ ਸਟੋਰ ਕੀਤੇ <ph name="DATASIZE" /> ਡਾਟੇ ਅਤੇ ਕà©à¨•à©€à¨œà¨¼ ਨੂੰ ਕਲੀਅਰ ਕਰ ਦਿੱਤਾ ਜਾਵੇਗਾ।</translation>
<translation id="1124772482545689468">ਵਰਤੋਂਕਾਰ</translation>
<translation id="1178581264944972037">ਰੋਕੋ</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">ਮਾਈਕà©à¨°à©‹à¨«à©‹à¨¨</translation>
<translation id="3277252321222022663">ਸਾਈਟਾਂ ਨੂੰ ਸੈਂਸਰਾਂ ਤੱਕ ਪਹà©à©°à¨š ਕਰਨ ਦਿਓ (ਸਿਫ਼ਾਰਸ਼ੀ)</translation>
<translation id="3295602654194328831">ਜਾਣਕਾਰੀ ਲà©à¨•à¨¾à¨“</translation>
+<translation id="3317660236277031814">ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀ ਵੈੱਬ à¨à¨ª ਨੇ ਆਪਣੇ ਪà©à¨°à¨¤à©€à¨• ਨੂੰ ਬਦਲ ਦਿੱਤਾ ਹੈ।</translation>
<translation id="3328801116991980348">ਸਾਈਟ ਜਾਣਕਾਰੀ</translation>
<translation id="3333961966071413176">ਸਭ ਸੰਪਰਕ</translation>
<translation id="3386292677130313581">ਸਾਈਟਾਂ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à¨¾ ਟਿਕਾਣਾ ਜਾਣਨ ਤੋਂ ਪਹਿਲਾਂ ਤà©à¨¹à¨¾à¨¡à©€ ਇਜਾਜ਼ਤ ਲੈਣ ਨੂੰ ਜ਼ਰੂਰੀ ਬਣਾਓ (ਸਿਫ਼ਾਰਸ਼ੀ)</translation>
+<translation id="345699454248713913">ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀ ਵੈੱਬ à¨à¨ª ਨੇ ਆਪਣੇ ਨਾਮ ਨੂੰ ਬਦਲ ਦਿੱਤਾ ਹੈ।</translation>
<translation id="3538390592868664640">ਸਾਈਟਾਂ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ ਆਲੇ-ਦà©à¨†à¨²à©‡ ਦਾ 3D ਨਕਸ਼ਾ ਬਣਾਉਣ ਜਾਂ ਕੈਮਰਾ ਸਥਿਤੀ ਨੂੰ ਟਰੈਕ ਕਰਨ ਤੋਂ ਬਲਾਕ ਕਰੋ</translation>
+<translation id="3551268116566418498">ਕੀ ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਨੂੰ ਛੱਡਣਾ ਹੈ?</translation>
<translation id="3586500876634962664">ਕੈਮਰੇ ਅਤੇ ਮਾਈਕà©à¨°à©‹à©žà©‹à¨¨ ਦੀ ਵਰਤੋਂ</translation>
<translation id="358794129225322306">ਕਿਸੇ ਸਾਈਟ ਨੂੰ ਇੱਕ ਤੋਂ ਜ਼ਿਆਦਾ ਫ਼ਾਈਲਾਂ ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਡਾਊਨਲੋਡ ਕਰਨ ਦਿਓ।</translation>
<translation id="3594780231884063836">ਵੀਡੀਓ ਮਿਊਟ ਕਰੋ</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">ਟਿਕਾਣਾ ਸੈਟਿੰਗਾਂ ਖੋਲà©à¨¹à©‹</translation>
<translation id="4226663524361240545">ਸੂਚਨਾਵਾਂ ਡੀਵਾਈਸ ਨੂੰ ਥਰਥਰਾਹਟ ਕਰ ਸਕਦੀਆਂ ਹਨ</translation>
<translation id="4259722352634471385">ਨੈਵੀਗੇਸ਼ਨ ਬਲੌਕ ਕੀਤੀ ਹੈ: <ph name="URL" /></translation>
+<translation id="4277239631747669329">ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀ ਵੈੱਬ à¨à¨ª ਨੇ ਆਪਣੇ ਨਾਮ ਅਤੇ ਪà©à¨°à¨¤à©€à¨• ਨੂੰ ਬਦਲ ਦਿੱਤਾ ਹੈ।</translation>
<translation id="4278390842282768270">ਆਗਿਆ ਦਿੱਤੀ</translation>
<translation id="429312253194641664">ਕੋਈ ਸਾਈਟ ਮੀਡੀਆ ਫ਼ਾਈਲ ਨੂੰ ਚਲਾ ਰਹੀ ਹੈ</translation>
<translation id="42981349822642051">ਵਿਸਤਾਰ ਕਰੋ</translation>
<translation id="4336434711095810371">ਸਾਰਾ ਡਾਟਾ ਕਲੀਅਰ ਕਰੋ</translation>
<translation id="4402755511846832236">ਸਾਈਟਾਂ ਨੂੰ ਇਹ ਜਾਣਨ ਤੋਂ ਰੋਕਣ ਲਈ ਬਲਾਕ ਕਰੋ ਕਿ ਤà©à¨¸à©€à¨‚ ਕਿਰਿਆਸ਼ੀਲ ਤੌਰ 'ਤੇ ਇਸ ਡੀਵਾਈਸ ਦੀ ਵਰਤੋਂ ਕਦੋਂ ਕਰਦੇ ਹੋ</translation>
-<translation id="4433925000917964731">Google ਵੱਲੋਂ ਮà©à¨¹à©±à¨ˆà¨† ਕਰਵਾਠਗਠਤੇਜ਼ੀ ਨਾਲ ਖà©à©±à¨²à©à¨¹à¨£ ਵਾਲੇ ਪੰਨੇ</translation>
<translation id="4434045419905280838">ਪੌਪ-ਅੱਪ ਅਤੇ ਰੀਡਾਇਰੈਕਟ</translation>
<translation id="445467742685312942">ਸਾਈਟਾਂ ਨੂੰ ਸà©à¨°à©±à¨–ਿਅਤ ਕੀਤੀ ਸਮੱਗਰੀ ਚਲਾਉਣ ਦਿਓ</translation>
<translation id="4468959413250150279">ਕਿਸੇ ਖਾਸ ਸਾਈਟ ਦੀ ਧà©à¨¨à©€ ਨੂੰ ਮਿਊਟ ਕਰੋ।</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">ਤà©à¨¹à¨¾à¨¡à©‡ ਮਾਤਾ ਜਾਂ ਪਿਤਾ ਵੱਲੋਂ ਵਿਵਸਥਿਤ</translation>
<translation id="4670064810192446073">ਆਭਾਸੀ ਵਾਸਤਵਿਕਤਾ</translation>
<translation id="4708011789095599544">ਕੀ ਤà©à¨¸à©€à¨‚ ਪੱਕਾ ਇਸ ਵੈੱਬਸਾਈਟ ਲਈ ਕà©à¨•à©€à¨œà¨¼ ਅਤੇ ਹੋਰ ਸਾਈਟ ਡਾਟੇ ਨੂੰ ਕਲੀਅਰ ਕਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
+<translation id="473775607612524610">ਅੱਪਡੇਟ ਕਰੋ</translation>
<translation id="4751476147751820511">ਗਤੀ ਜਾਂ ਰੋਸ਼ਨੀ ਦੇ ਸੈਂਸਰ</translation>
<translation id="4836046166855586901">ਜਦੋਂ ਕੋਈ ਸਾਈਟ ਜਾਣਨਾ ਚਾਹà©à©°à¨¦à©€ ਹੈ ਕਿ ਤà©à¨¸à©€à¨‚ ਕਿਰਿਆਸ਼ੀਲ ਤੌਰ 'ਤੇ ਇਸ ਡੀਵਾਈਸ ਦੀ ਵਰਤੋਂ ਕਦੋਂ ਕਰਦੇ ਹੋ, ਉਸ ਵੇਲੇ ਪà©à©±à¨›à©‹</translation>
<translation id="4883854917563148705">ਪà©à¨°à¨¬à©°à¨§à¨¿à¨¤ ਕੀਤੀਆਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਰੀਸੈੱਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">ਰਾਹੀਂ ਸ਼ੇਅਰ ਕਰੋ</translation>
<translation id="5039804452771397117">ਆਗਿਆ ਦਿਓ</translation>
<translation id="5048398596102334565">ਸਾਈਟਾਂ ਨੂੰ ਗਤੀਸ਼ੀਲਤਾ ਸੈਂਸਰਾਂ ਤੱਕ ਪਹà©à©°à¨š ਕਰਨ ਦਿਓ (ਸਿਫ਼ਾਰਸ਼ੀ)</translation>
+<translation id="5050380848339752099">ਇਹ ਸਾਈਟ ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਤੋਂ ਬਾਹਰ ਕਿਸੇ à¨à¨ª ਦੇ ਨਾਲ ਜਾਣਕਾਰੀ ਸਾਂà¨à©€ ਕਰਨ ਲੱਗੀ ਹੈ।</translation>
<translation id="5063480226653192405">ਵਰਤੋਂ</translation>
<translation id="5100237604440890931">ਸਮੇਟਿਆ ਗਿਆ - ਵਿਸਤਾਰ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ।</translation>
<translation id="5123685120097942451">ਇਨਕੋਗਨਿਟੋ ਟੈਬ</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">ਸਾਈਟਾਂ ਨੂੰ JavaScript ਚਲਾਉਣ ਦੀ ਆਗਿਆ ਦਿਓ (ਸਿਫ਼ਾਰਸ਼ੀ)</translation>
<translation id="534295439873310000">NFC ਡੀਵਾਈਸਾਂ</translation>
<translation id="5354152178998424783">ਇੰਠਕਰਨ ਨਾਲ ਸਾਈਟਾਂ ਵੱਲੋਂ ਸਟੋਰ ਕੀਤੇ <ph name="DATASIZE" /> ਡਾਟੇ ਅਤੇ ਕà©à¨•à©€à¨œà¨¼ ਨੂੰ ਕਲੀਅਰ ਕਰ ਦਿੱਤਾ ਜਾਵੇਗਾ।</translation>
-<translation id="5384883051496921101">ਇਹ ਸਾਈਟ ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਤੋਂ ਬਾਹਰ ਕਿਸੇ à¨à¨ª ਦੇ ਨਾਲ ਜਾਣਕਾਰੀ ਸਾਂà¨à©€ ਕਰਨ ਲੱਗੀ ਹੈ।</translation>
+<translation id="536508626067510330">ਕੀ ਤà©à¨¸à©€à¨‚ ਆਪਣੀ ਹੋਮ ਸਕà©à¨°à©€à¨¨ 'ਤੇ ਪà©à¨°à¨¤à©€à¨• ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
<translation id="5391532827096253100">ਇਸ ਸਾਈਟ ਲਈ ਤà©à¨¹à¨¾à¨¡à¨¾ ਕਨੈਕਸ਼ਨ ਸà©à¨°à©±à¨–ਿਅਤ ਨਹੀਂ ਹੈ। ਸਾਈਟ ਜਾਣਕਾਰੀ</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 ਹੋਰ)}one{(+ # ਹੋਰ)}other{(+ # ਹੋਰ)}}</translation>
<translation id="5403592356182871684">ਨਾਮ</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" /> ਵਿੱਚੋਂ ਬੀਤਿਆ ਸਮਾਂ <ph name="ELAPSED_TIME" />।</translation>
<translation id="5494752089476963479">ਉਹਨਾਂ ਸਾਈਟਾਂ 'ਤੇ ਵਿਗਿਆਪਨਾਂ ਨੂੰ ਬਲਾਕ ਕਰੋ, ਜੋ ਦਖਲਅੰਦਾਜ਼ੀ ਅਤੇ ਗà©à¨®à¨°à¨¾à¨¹ ਕਰਨ ਵਾਲੇ ਵਿਗਿਆਪਨ ਦਿਖਾਉਂਦੀਆਂ ਹਨ</translation>
+<translation id="549957179819296104">ਨਵਾਂ ਪà©à¨°à¨¤à©€à¨•</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਗਈ, <ph name="PERMISSION_2" /> ਨੂੰ ਬਲਾਕ ਕੀਤਾ ਗਿਆ</translation>
<translation id="5505264765875738116">ਸਾਈਟਾਂ ਸੂਚਨਾਵਾਂ ਭੇਜਣ ਲਈ ਪà©à©±à¨› ਨਹੀਂ ਸਕਦੀਆਂ ਹਨ</translation>
<translation id="5516455585884385570">ਸੂਚਨਾ ਸੈਟਿੰਗਾਂ ਖੋਲà©à¨¹à©‹</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">ਅਨà©à¨®à¨¤à©€à¨†à¨‚</translation>
<translation id="5860033963881614850">ਬੰਦ ਕਰੋ</translation>
<translation id="5876056640971328065">ਵੀਡੀਓ ਰੋਕੋ</translation>
+<translation id="5904826301761575486">ਕੀ ਤà©à¨¸à©€à¨‚ ਆਪਣੀ ਹੋਮ ਸਕà©à¨°à©€à¨¨ 'ਤੇ ਨਾਮ ਅਤੇ ਪà©à¨°à¨¤à©€à¨• ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
<translation id="5916664084637901428">ਚਾਲੂ</translation>
<translation id="5922853908706496913">ਤà©à¨¹à¨¾à¨¡à©€ ਸਕà©à¨°à©€à¨¨ ਸਾਂà¨à©€ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ</translation>
<translation id="5939518447894949180">ਰੀਸੈਟ ਕਰੋ</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">ਤੀਜੀ-ਧਿਰ ਵਾਲੀਆਂ ਕà©à©±à¨•à©€à¨œà¨¼ ਨੂੰ ਬਲੌਕ ਕਰੋ</translation>
<translation id="6206551242102657620">ਕਨੈਕਸ਼ਨ ਸà©à¨°à©±à¨–ਿਅਤ ਹੈ। ਸਾਈਟ ਜਾਣਕਾਰੀ</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> ਵਿਕਲਪ</translation>
+<translation id="6260852843601447737">ਬੰਦ ਕਰੋ ਅਤੇ ਦà©à¨°à¨µà¨¿à¨¹à¨¾à¨° ਲਈ ਰਿਪੋਰਟ ਕਰੋ</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> ਅਤੇ <ph name="PERMISSION_2" /> ਨੂੰ ਬਲਾਕ ਕੀਤਾ ਗਿਆ</translation>
<translation id="6270391203985052864">ਸਾਈਟਾਂ ਸੂਚਨਾਵਾਂ ਭੇਜਣ ਲਈ ਪà©à©±à¨› ਸਕਦੀਆਂ ਹਨ</translation>
<translation id="6295158916970320988">ਸਾਰੀਆਂ ਸਾਈਟਾਂ</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> ਨੂੰ ਆਪਣੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹà©à©°à¨š ਕਰਨ ਦੇਣ ਲਈ, <ph name="BEGIN_LINK" />Android ਸੈਟਿੰਗਾਂ<ph name="END_LINK" /> ਵਿੱਚ ਟਿਕਾਣਾ ਵੀ ਚਾਲੂ ਕਰੋ।</translation>
<translation id="8447861592752582886">ਡੀਵਾਈਸ 'ਤੇ ਪਹà©à©°à¨š ਦੀ ਇਜਾਜ਼ਤ ਰੱਦ ਕਰੋ</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 ਕà©à¨•à©€ ਵਰਤੋਂ ਵਿੱਚ ਹੈ}one{# ਕà©à¨•à©€ ਵਰਤੋਂ ਵਿੱਚ ਹੈ}other{# ਕà©à¨•à©€à©› ਵਰਤੋਂ ਵਿੱਚ ਹਨ}}</translation>
-<translation id="8463851957836045671">ਸਾਈਟ ਤੇਜ਼ ਹੈ</translation>
<translation id="8487700953926739672">ਆਫ਼ਲਾਈਨ ਉਪਲਬਧ</translation>
<translation id="851751545965956758">ਸਾਈਟਾਂ ਨੂੰ ਡੀਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਤੋਂ ਬਲਾਕ ਕਰੋ</translation>
<translation id="8525306231823319788">ਪੂਰੀ ਸਕà©à¨°à©€à¨¨</translation>
<translation id="857943718398505171">ਇਜਾਜ਼ਤ ਹੈ ( ਸਿਫ਼ਾਰਸ਼ ਕੀਤੇ)</translation>
<translation id="8609465669617005112">ਉੱਪਰ ਜਾਓ</translation>
+<translation id="861748745608658996">ਕੀ ਤà©à¨¸à©€à¨‚ ਆਪਣੀ ਹੋਮ ਸਕà©à¨°à©€à¨¨ 'ਤੇ ਨਾਮ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
<translation id="8676374126336081632">ਇਨਪà©à¨Ÿ ਹਟਾਓ</translation>
<translation id="868929229000858085">ਆਪਣੇ ਸੰਪਰਕ ਖੋਜੋ</translation>
<translation id="8702612070107455751">ਕਿਸੇ ਵੀ ਆਫ਼ਲਾਈਨ ਡਾਟੇ ਨੂੰ ਕਲੀਅਰ ਕਰ ਦਿੱਤਾ ਜਾਵੇਗਾ।</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">ਜ਼ੂਮ ਵਧਾਓ</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">ਇਸ ਡੀਵਾਈਸ ਲਈ NFC ਬੰਦ ਹੈ। ਇਸਨੂੰ <ph name="BEGIN_LINK" />Android ਸੈਟਿੰਗਾਂ<ph name="END_LINK" /> ਵਿੱਚ ਚਾਲੂ ਕਰੋ।</translation>
-<translation id="8929372349074745002">ਇਹ ਸਾਈਟ ਜ਼ਿਆਦਾਤਰ ਲੋਕਾਂ ਲਈ ਤੇਜ਼ੀ ਨਾਲ ਖà©à©±à¨²à©à¨¹à¨¦à©€ ਅਤੇ ਜਵਾਬ ਦਿੰਦੀ ਹੈ</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਛੱਡੀ�</translation>
<translation id="8958424370300090006">ਕਿਸੇ ਖਾਸ ਸਾਈਟ ਲਈ ਕà©à¨•à©€à©› ਬਲਾਕ ਕਰੋ।</translation>
<translation id="8959122750345127698">ਨੈਵੀਗੇਸ਼ਨ ਨਾਪਹà©à©°à¨šà¨¯à©‹à¨— ਹੈ: <ph name="URL" /></translation>
<translation id="8986362086234534611">ਭà©à©±à¨²à¨£à¨¾</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pl.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pl.xtb
index 4edef67885c..b9d8d61274e 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pl.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pl.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="pl">
<translation id="1006017844123154345">Otwórz online</translation>
<translation id="1044891598689252897">Strony będą działać normalnie</translation>
+<translation id="1100504063505580045">Aktualna ikona</translation>
<translation id="1124090076051167250">Spowoduje to usunięcie <ph name="DATASIZE" /> danych i plików cookie zapisanych przez stronę lub aplikacje na ekranie głównym.</translation>
<translation id="1124772482545689468">Użytkownik</translation>
<translation id="1178581264944972037">Wstrzymaj</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Zezwalaj stronom na dostęp do czujników (zalecane)</translation>
<translation id="3295602654194328831">Ukryj informacje</translation>
+<translation id="3317660236277031814">Zainstalowana aplikacja internetowa zmieniła ikonę.</translation>
<translation id="3328801116991980348">Informacje o witrynie</translation>
<translation id="3333961966071413176">Wszystkie kontakty</translation>
<translation id="3386292677130313581">Pytaj, zanim udostępnisz stronom swoją lokalizację (zalecane)</translation>
+<translation id="345699454248713913">Zainstalowana aplikacja internetowa zmieniła nazwę.</translation>
<translation id="3538390592868664640">Nie zezwalaj stronom na tworzenie mapy 3D Twojego otoczenia ani na śledzenie pozycji kamery</translation>
+<translation id="3551268116566418498">Wyłączyć tryb incognito?</translation>
<translation id="3586500876634962664">Korzystanie z kamery i mikrofonu</translation>
<translation id="358794129225322306">Zezwól stronie na automatyczne pobieranie wielu plików.</translation>
<translation id="3594780231884063836">Wycisz film</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Otwórz ustawienia lokalizacji</translation>
<translation id="4226663524361240545">Powiadomienia będą sygnalizowane wibracjami</translation>
<translation id="4259722352634471385">Adres zablokowany: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Zainstalowana aplikacja internetowa zmieniła nazwę i ikonę.</translation>
<translation id="4278390842282768270">Dopuszczone</translation>
<translation id="429312253194641664">Strona odtwarza multimedia</translation>
<translation id="42981349822642051">Rozwiń</translation>
<translation id="4336434711095810371">Wyczyść wszystkie dane</translation>
<translation id="4402755511846832236">Nie pozwalaj stronom sprawdzać, czy aktualnie używasz urządzenia</translation>
-<translation id="4433925000917964731">Lżejsza wersja strony dostarczona przez Google</translation>
<translation id="4434045419905280838">Pop-upy i przekierowania</translation>
<translation id="445467742685312942">Zezwalaj stronom na odtwarzanie treści chronionych</translation>
<translation id="4468959413250150279">Wycisz dźwięk na konkretnej stronie.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">ZarzÄ…dzany przez Twojego rodzica</translation>
<translation id="4670064810192446073">Rzeczywistość wirtualna</translation>
<translation id="4708011789095599544">Czy na pewno chcesz wyczyścić pliki cookie i inne dane tej witryny?</translation>
+<translation id="473775607612524610">Aktualizuj</translation>
<translation id="4751476147751820511">Czujniki ruchu lub światła</translation>
<translation id="4836046166855586901">Pytaj, gdy strona chce wiedzieć, kiedy aktywnie korzystasz z urządzenia</translation>
<translation id="4883854917563148705">Ustawień zarządzanych nie można zresetować</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Udostępnij przez</translation>
<translation id="5039804452771397117">Zezwalaj</translation>
<translation id="5048398596102334565">Zezwalaj stronom na dostęp do czujników ruchu (zalecane)</translation>
+<translation id="5050380848339752099">Ta strona zamierza udostępnić informacje aplikacji poza trybem incognito.</translation>
<translation id="5063480226653192405">Wykorzystanie</translation>
<translation id="5100237604440890931">Zwinięty – kliknij, by rozwinąć.</translation>
<translation id="5123685120097942451">Karta incognito</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Zezwalaj na wykonywanie kodu JavaScript w witrynach (zalecane)</translation>
<translation id="534295439873310000">Urządzenia z funkcją NFC</translation>
<translation id="5354152178998424783">Spowoduje to usunięcie <ph name="DATASIZE" /> danych i plików cookie zapisanych przez strony.</translation>
-<translation id="5384883051496921101">Ta strona zamierza udostępnić informacje aplikacji poza trybem incognito.</translation>
+<translation id="536508626067510330">Zaktualizować ikonę na ekranie głównym?</translation>
<translation id="5391532827096253100">Twoje połączenie z tą witryną nie jest bezpieczne. Informacje o witrynie</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(i jeszcze 1)}few{(i jeszcze #)}many{(i jeszcze #)}other{(i jeszcze #)}}</translation>
<translation id="5403592356182871684">Nazwy</translation>
<translation id="5489227211564503167">Upłynęło: <ph name="ELAPSED_TIME" /> z <ph name="TOTAL_TIME" /></translation>
<translation id="5494752089476963479">Blokuj reklamy na stronach, które wyświetlają reklamy uciążliwe lub wprowadzające w błąd</translation>
+<translation id="549957179819296104">Nowa ikona</translation>
<translation id="5502860503640766021">Dozwolone: <ph name="PERMISSION_1" />, zablokowane: <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Strony nie mogą prosić o zgodę na wysyłanie powiadomień</translation>
<translation id="5516455585884385570">Otwórz ustawienia powiadomień</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Uprawnienia</translation>
<translation id="5860033963881614850">Wyłączone</translation>
<translation id="5876056640971328065">Wstrzymaj film</translation>
+<translation id="5904826301761575486">Zaktualizować nazwę i ikonę na ekranie głównym?</translation>
<translation id="5916664084637901428">WÅ‚Ä…czone</translation>
<translation id="5922853908706496913">Udostępnianie ekranu</translation>
<translation id="5939518447894949180">Resetuj</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokuj pliki cookie innych firm</translation>
<translation id="6206551242102657620">Połączenie jest bezpieczne. Informacje o witrynie</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> – opcje</translation>
+<translation id="6260852843601447737">Zamknij i zgłoś nadużycie</translation>
<translation id="6262279340360821358">Zablokowane: <ph name="PERMISSION_1" /> i <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Strony mogą prosić o zgodę na wysyłanie powiadomień</translation>
<translation id="6295158916970320988">Wszystkie witryny</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Aby zezwolić aplikacji <ph name="APP_NAME" /> na dostęp do lokalizacji, musisz ją też włączyć w <ph name="BEGIN_LINK" />ustawieniach Androida<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Cofnij zgodę na dostęp do urządzenia</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 plik cookie w użyciu}few{# pliki cookie w użyciu}many{# plików cookie w użyciu}other{# pliku cookie w użyciu}}</translation>
-<translation id="8463851957836045671">Strona jest szybka</translation>
<translation id="8487700953926739672">Dostępny offline</translation>
<translation id="851751545965956758">Nie zezwalaj stronom na łączenie się z urządzeniami</translation>
<translation id="8525306231823319788">Pełny ekran</translation>
<translation id="857943718398505171">Dozwolone (zalecane)</translation>
<translation id="8609465669617005112">W górę</translation>
+<translation id="861748745608658996">Zaktualizować nazwę na ekranie głównym?</translation>
<translation id="8676374126336081632">Wyczyść wpisany tekst</translation>
<translation id="868929229000858085">Wyszukaj w kontaktach</translation>
<translation id="8702612070107455751">Wszystkie dane offline zostanÄ… wyczyszczone.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Powiększ</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">Funkcja NFC na tym urządzeniu jest wyłączona. Włącz ją w <ph name="BEGIN_LINK" />Ustawieniach Androida<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">U większości użytkowników ta strona szybko się otwiera i umożliwia płynną interakcję</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Zamknąć tryb incognito?</translation>
<translation id="8958424370300090006">Blokuj pliki cookie z określonej strony internetowej.</translation>
<translation id="8959122750345127698">Adres nieosiÄ…galny: <ph name="URL" /></translation>
<translation id="8986362086234534611">Zapomnij</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pt-BR.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pt-BR.xtb
index a73f5953edb..c4253f636dc 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pt-BR.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pt-BR.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="pt-BR">
<translation id="1006017844123154345">Abrir on-line</translation>
<translation id="1044891598689252897">Os sites funcionarão normalmente</translation>
+<translation id="1100504063505580045">Ãcone atual</translation>
<translation id="1124090076051167250">Essa ação apagará <ph name="DATASIZE" /> de dados e cookies armazenados por sites ou apps na sua tela inicial.</translation>
<translation id="1124772482545689468">Usuário</translation>
<translation id="1178581264944972037">Pausar</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Microfone</translation>
<translation id="3277252321222022663">Permitir que sites acessem os sensores (recomendado)</translation>
<translation id="3295602654194328831">Ocultar informações</translation>
+<translation id="3317660236277031814">Um app da Web que você instalou mudou de ícone.</translation>
<translation id="3328801116991980348">Informações do site</translation>
<translation id="3333961966071413176">Todos os contatos</translation>
<translation id="3386292677130313581">Perguntar antes de permitir que sites saibam seu local (recomendado)</translation>
+<translation id="345699454248713913">Um app da Web que você instalou mudou de nome.</translation>
<translation id="3538390592868664640">Impedir sites de criar um mapa 3D do ambiente a sua volta ou acompanhar a posição da câmera</translation>
+<translation id="3551268116566418498">Sair do modo de navegação anônima?</translation>
<translation id="3586500876634962664">Uso de câmera e microfone</translation>
<translation id="358794129225322306">Permite que um site faça o download de vários arquivos automaticamente.</translation>
<translation id="3594780231884063836">Desativar som do vídeo</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Abrir as configurações de localização</translation>
<translation id="4226663524361240545">É possível que as notificações façam o dispositivo vibrar</translation>
<translation id="4259722352634471385">A Navegação GPS está bloqueada: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Um app da Web que você instalou mudou de nome e ícone.</translation>
<translation id="4278390842282768270">Permitido</translation>
<translation id="429312253194641664">Um site está com mídia aberta</translation>
<translation id="42981349822642051">Expandir</translation>
<translation id="4336434711095810371">Limpar todos os dados</translation>
<translation id="4402755511846832236">Impedir que sites saibam quando você está usando este dispositivo</translation>
-<translation id="4433925000917964731">Página Lite exibida pelo Google</translation>
<translation id="4434045419905280838">Pop-ups e redirecionamentos</translation>
<translation id="445467742685312942">Permitir que sites mostrem conteúdo protegido</translation>
<translation id="4468959413250150279">Desativar o som de um site específico.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Gerenciado pelos seus pais</translation>
<translation id="4670064810192446073">Realidade virtual</translation>
<translation id="4708011789095599544">Tem certeza de que quer limpar os cookies e outros dados deste site?</translation>
+<translation id="473775607612524610">Atualizar</translation>
<translation id="4751476147751820511">Sensores de luz ou movimento</translation>
<translation id="4836046166855586901">Perguntar quando um site quiser saber os momentos em que você está usando este dispositivo</translation>
<translation id="4883854917563148705">Não é possível redefinir as configurações gerenciadas</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Compartilhar via</translation>
<translation id="5039804452771397117">Permitir</translation>
<translation id="5048398596102334565">Permitir o acesso de sites aos seus sensores de movimento (recomendado)</translation>
+<translation id="5050380848339752099">Este site compartilhará informações com um app fora do modo de navegação anônima.</translation>
<translation id="5063480226653192405">Uso</translation>
<translation id="5100237604440890931">Visualização recolhida. Clique para expandir</translation>
<translation id="5123685120097942451">Guia anônima</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Permitir que sites executem o JavaScript (recomendado)</translation>
<translation id="534295439873310000">Dispositivos NFC</translation>
<translation id="5354152178998424783">Essa ação apagará <ph name="DATASIZE" /> de dados e cookies armazenados por sites.</translation>
-<translation id="5384883051496921101">Este site está prestes a compartilhar informações com um app fora do modo de navegação anônima.</translation>
+<translation id="536508626067510330">Atualizar o ícone na tela inicial?</translation>
<translation id="5391532827096253100">Sua conexão com este site não é segura. Informações do site</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(mais 1)}one{(mais #)}other{(mais #)}}</translation>
<translation id="5403592356182871684">Nomes</translation>
<translation id="5489227211564503167">Tempo decorrido: <ph name="ELAPSED_TIME" /> de <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Bloquear anúncios em sites com publicidade invasiva ou enganosa</translation>
+<translation id="549957179819296104">Novo ícone</translation>
<translation id="5502860503640766021">Permissão autorizada: <ph name="PERMISSION_1" />. Permissão bloqueada: <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Os sites não podem pedir para enviar notificações</translation>
<translation id="5516455585884385570">Abrir configurações de notificação</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Permissões</translation>
<translation id="5860033963881614850">Desativado</translation>
<translation id="5876056640971328065">Pausar vídeo</translation>
+<translation id="5904826301761575486">Atualizar nome e ícone na tela inicial?</translation>
<translation id="5916664084637901428">Ativado</translation>
<translation id="5922853908706496913">Compartilhando a tela</translation>
<translation id="5939518447894949180">Redefinir</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Bloquear cookies de terceiros</translation>
<translation id="6206551242102657620">A conexão é segura. Informações do site</translation>
<translation id="6216432067784365534">Opções de <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Fechar e denunciar abuso</translation>
<translation id="6262279340360821358">Bloqueadas: <ph name="PERMISSION_1" /> e <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Os sites podem pedir para enviar notificações</translation>
<translation id="6295158916970320988">Todos os sites</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Para permitir que o app <ph name="APP_NAME" /> acesse seu local, ative-o também nas <ph name="BEGIN_LINK" />configurações do Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Revogar permissão do dispositivo</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie em uso}one{# cookie em uso}other{# cookies em uso}}</translation>
-<translation id="8463851957836045671">O site é rápido</translation>
<translation id="8487700953926739672">Disponível off-line</translation>
<translation id="851751545965956758">Impedir que sites se conectem a dispositivos</translation>
<translation id="8525306231823319788">Tela cheia</translation>
<translation id="857943718398505171">Permitido (recomendado)</translation>
<translation id="8609465669617005112">Mover para cima</translation>
+<translation id="861748745608658996">Atualizar o nome na tela inicial?</translation>
<translation id="8676374126336081632">Limpar entrada</translation>
<translation id="868929229000858085">Pesquisar seus contatos</translation>
<translation id="8702612070107455751">Todos os dados off-line serão removidos.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Aumentar zoom</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">A NFC está desativada neste dispositivo. Ative-a nas <ph name="BEGIN_LINK" />configurações do Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Este site abre e responde rapidamente para a maioria das pessoas</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Sair do modo de navegação anônima?</translation>
<translation id="8958424370300090006">Bloqueie cookies de um site específico.</translation>
<translation id="8959122750345127698">A Navegação GPS está inacessível: <ph name="URL" /></translation>
<translation id="8986362086234534611">Esquecer</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pt-PT.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pt-PT.xtb
index 6b5fcbe29e8..7bd38d02f7c 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pt-PT.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_pt-PT.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="pt-PT">
<translation id="1006017844123154345">Abrir online</translation>
<translation id="1044891598689252897">Os sites funcionam normalmente.</translation>
+<translation id="1100504063505580045">Ãcone atual</translation>
<translation id="1124090076051167250">Esta ação limpa <ph name="DATASIZE" /> de dados e cookies armazenados por sites ou apps no seu ecrã principal.</translation>
<translation id="1124772482545689468">Utilizador</translation>
<translation id="1178581264944972037">Pausa</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Microfone</translation>
<translation id="3277252321222022663">Permitir que os sites acedam aos sensores (recomendado)</translation>
<translation id="3295602654194328831">Ocultar informações</translation>
+<translation id="3317660236277031814">Uma app para a Web que instalou mudou o respetivo ícone.</translation>
<translation id="3328801116991980348">Informações do site</translation>
<translation id="3333961966071413176">Todos os contactos</translation>
<translation id="3386292677130313581">Perguntar antes de permitir que os sites conheçam a sua localização (recomendado)</translation>
+<translation id="345699454248713913">Uma app para a Web que instalou mudou o respetivo nome.</translation>
<translation id="3538390592868664640">Impeça que os sites criem um mapa 3D do ambiente à sua volta ou monitorizem a posição da câmara</translation>
+<translation id="3551268116566418498">Quer sair da Navegação anónima?</translation>
<translation id="3586500876634962664">Utilização da câmara e do microfone</translation>
<translation id="358794129225322306">Permitir que um site transfira vários ficheiros automaticamente.</translation>
<translation id="3594780231884063836">Desativar o som do vídeo</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Abrir definições de localização</translation>
<translation id="4226663524361240545">As notificações podem fazer com que o dispositivo vibre</translation>
<translation id="4259722352634471385">A navegação está bloqueada: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Uma app para a Web que instalou mudou o respetivo nome e ícone.</translation>
<translation id="4278390842282768270">Permitido</translation>
<translation id="429312253194641664">Um site está a reproduzir multimédia.</translation>
<translation id="42981349822642051">Expandir</translation>
<translation id="4336434711095810371">Limpar todos os dados</translation>
<translation id="4402755511846832236">Impeça os sites de saberem quando está ativamente a utilizar este dispositivo.</translation>
-<translation id="4433925000917964731">Página em modo lite fornecida pela Google</translation>
<translation id="4434045419905280838">Pop-ups e redirecionamentos</translation>
<translation id="445467742685312942">Permitir que os sites reproduzam conteúdos protegidos</translation>
<translation id="4468959413250150279">Desative o som de um site específico.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Gerido pelos teus pais</translation>
<translation id="4670064810192446073">Realidade virtual</translation>
<translation id="4708011789095599544">Tem a certeza de que pretende limpar os cookies e outros dados deste Website?</translation>
+<translation id="473775607612524610">Atualizar</translation>
<translation id="4751476147751820511">Sensores de movimento ou de luz</translation>
<translation id="4836046166855586901">Perguntar quando um site pretender saber quando está a utilizar ativamente este dispositivo.</translation>
<translation id="4883854917563148705">As definições geridas não podem ser repostas</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Partilhar através de</translation>
<translation id="5039804452771397117">Permitir</translation>
<translation id="5048398596102334565">Permitir que os sites acedam aos sensores de movimentos (recomendado)</translation>
+<translation id="5050380848339752099">Este site está prestes a partilhar informações com uma app fora do Modo de navegação anónima.</translation>
<translation id="5063480226653192405">Utilização</translation>
<translation id="5100237604440890931">Reduzido. Clique para expandir.</translation>
<translation id="5123685120097942451">Separador de navegação anónima</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Permitir que os sites executem JavaScript (recomendado)</translation>
<translation id="534295439873310000">Dispositivos NFC</translation>
<translation id="5354152178998424783">Esta ação eliminará <ph name="DATASIZE" /> de dados e cookies armazenados pelos sites.</translation>
-<translation id="5384883051496921101">Este site está prestes a partilhar informações com uma aplicação fora do modo de navegação anónima.</translation>
+<translation id="536508626067510330">Pretende atualizar o ícone no seu ecrã principal?</translation>
<translation id="5391532827096253100">A sua ligação a este site não é segura. Informações do site</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(mais 1)}other{(mais #)}}</translation>
<translation id="5403592356182871684">Nomes</translation>
<translation id="5489227211564503167">Tempo decorrido: <ph name="ELAPSED_TIME" /> de <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Bloquear anúncios em sites que apresentam anúncios intrusivos ou enganadores</translation>
+<translation id="549957179819296104">Novo ícone</translation>
<translation id="5502860503640766021">Autorização de <ph name="PERMISSION_1" />, bloqueio de <ph name="PERMISSION_2" />.</translation>
<translation id="5505264765875738116">Os sites não podem pedir para enviar notificações.</translation>
<translation id="5516455585884385570">Abrir definições de notificação</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Permissões</translation>
<translation id="5860033963881614850">Desativado</translation>
<translation id="5876056640971328065">Colocar vídeo em pausa</translation>
+<translation id="5904826301761575486">Pretende atualizar o nome e o ícone no seu ecrã principal?</translation>
<translation id="5916664084637901428">Ativado</translation>
<translation id="5922853908706496913">Partilhar o ecrã</translation>
<translation id="5939518447894949180">Repor</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Bloquear cookies de terceiros</translation>
<translation id="6206551242102657620">A ligação é segura. Informações do site</translation>
<translation id="6216432067784365534">Opções de <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Fechar e comunicar abuso</translation>
<translation id="6262279340360821358">Bloqueio de <ph name="PERMISSION_1" /> e <ph name="PERMISSION_2" />.</translation>
<translation id="6270391203985052864">Os sites podem pedir para enviar notificações.</translation>
<translation id="6295158916970320988">Todos os sites</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Para permitir que a app <ph name="APP_NAME" /> aceda à sua localização, ative também a localização nas <ph name="BEGIN_LINK" />Definições do Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Revogar autorização do dispositivo</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie em utilização}other{# cookies em utilização}}</translation>
-<translation id="8463851957836045671">O site é rápido</translation>
<translation id="8487700953926739672">Disponível offline</translation>
<translation id="851751545965956758">Impedir a ligação de sites a dispositivos</translation>
<translation id="8525306231823319788">Ecrã inteiro</translation>
<translation id="857943718398505171">Permitido (recomendado)</translation>
<translation id="8609465669617005112">Mover para cima</translation>
+<translation id="861748745608658996">Pretende atualizar o nome no seu ecrã principal?</translation>
<translation id="8676374126336081632">Limpar texto</translation>
<translation id="868929229000858085">Pesquise os seus contactos</translation>
<translation id="8702612070107455751">Todos os dados offline serão limpos.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Ampliar</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">O NFC está desativado para este dispositivo. Ative-o nas <ph name="BEGIN_LINK" />Definições do Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Este site é aberto e responde rapidamente para a maioria das pessoas.</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Sair da navegação anónima?</translation>
<translation id="8958424370300090006">Bloqueie cookies para um site específico.</translation>
<translation id="8959122750345127698">A navegação está inacessível: <ph name="URL" /></translation>
<translation id="8986362086234534611">Esquecer</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ro.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ro.xtb
index 55859eaf2a9..37f9b5eab02 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ro.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ro.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ro">
<translation id="1006017844123154345">Deschide online</translation>
<translation id="1044891598689252897">Site-urile vor funcționa normal</translation>
+<translation id="1100504063505580045">Pictograma actuală</translation>
<translation id="1124090076051167250">Astfel, se vor șterge <ph name="DATASIZE" /> din datele și cookie-urile stocate de site-uri sau aplicații de pe ecranul de pornire.</translation>
<translation id="1124772482545689468">Utilizator</translation>
<translation id="1178581264944972037">ÃŽntrerupe</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Microfon</translation>
<translation id="3277252321222022663">Permite accesul site-urilor la senzori (recomandat)</translation>
<translation id="3295602654194328831">Ascunde informațiile</translation>
+<translation id="3317660236277031814">Pictograma unei aplicații web pe care ai instalat-o s-a schimbat.</translation>
<translation id="3328801116991980348">Informații despre site</translation>
<translation id="3333961966071413176">Toată agenda</translation>
<translation id="3386292677130313581">Întreabă înainte de a permite site-urilor să afle locația (recomandat)</translation>
+<translation id="345699454248713913">Numele unei aplicații web pe care ai instalat-o s-a schimbat.</translation>
<translation id="3538390592868664640">Împiedică site-urile să creeze o hartă 3D a lucrurilor din jur sau să urmărească poziția camerei video</translation>
+<translation id="3551268116566418498">Ieși din modul incognito?</translation>
<translation id="3586500876634962664">Folosirea camerei și a microfonului</translation>
<translation id="358794129225322306">Permite unui site să descarce automat mai multe fișiere.</translation>
<translation id="3594780231884063836">Dezactivează sunetul videoclipului</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Deschide setările privind locația</translation>
<translation id="4226663524361240545">Notificările pot face dispozitivul să vibreze</translation>
<translation id="4259722352634471385">Navigarea este blocată: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Numele și pictograma unei aplicații web pe care ai instalat-o s-au schimbat.</translation>
<translation id="4278390842282768270">Se permite</translation>
<translation id="429312253194641664">Un site redă fișiere media</translation>
<translation id="42981349822642051">Extinde</translation>
<translation id="4336434711095810371">Șterge toate datele</translation>
<translation id="4402755511846832236">Împiedică site-urile să detecteze când folosești activ dispozitivul</translation>
-<translation id="4433925000917964731">Pagină Lite oferită de Google</translation>
<translation id="4434045419905280838">Ferestre pop-up și redirecționări</translation>
<translation id="445467742685312942">Permite site-urilor să redea conținut protejat</translation>
<translation id="4468959413250150279">Dezactivează sunetul pentru un anumit site.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Gestionat de părintele tău</translation>
<translation id="4670064810192446073">Realitate virtuală</translation>
<translation id="4708011789095599544">Sigur vrei să ștergi cookie-urile și alte date privind site-ul pentru acest site?</translation>
+<translation id="473775607612524610">Actualizează</translation>
<translation id="4751476147751820511">Senzori de mișcare sau de lumină</translation>
<translation id="4836046166855586901">Anunță-mă dacă un site vrea să afle când folosesc activ dispozitivul</translation>
<translation id="4883854917563148705">Setările gestionate nu pot fi resetate</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Trimite prin</translation>
<translation id="5039804452771397117">Permite</translation>
<translation id="5048398596102334565">Permite accesul site-urilor la senzorii de mișcare (recomandat)</translation>
+<translation id="5050380848339752099">Site-ul este pe cale să permită accesul la informații unei aplicații în afara modului incognito.</translation>
<translation id="5063480226653192405">Utilizare</translation>
<translation id="5100237604440890931">Afișare restrânsă – dă clic pentru a extinde.</translation>
<translation id="5123685120097942451">Filă incognito</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Permite site-urilor să ruleze JavaScript (recomandat)</translation>
<translation id="534295439873310000">Dispozitive NFC</translation>
<translation id="5354152178998424783">Astfel, se vor șterge <ph name="DATASIZE" /> din datele și cookie-urile stocate de site-uri.</translation>
-<translation id="5384883051496921101">Site-ul este pe cale să permită accesul la informații unei aplicații în afara modului incognito.</translation>
+<translation id="536508626067510330">Actualizezi pictograma de pe ecranul de pornire?</translation>
<translation id="5391532827096253100">Conexiunea la acest site nu este sigură. Informații despre site</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ încă 1)}few{(+ încă #)}other{(+ încă #)}}</translation>
<translation id="5403592356182871684">Nume</translation>
<translation id="5489227211564503167">Timp scurs: <ph name="ELAPSED_TIME" /> din <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blochează anunțurile pe site-urile care afișează anunțuri deranjante sau înșelătoare</translation>
+<translation id="549957179819296104">Pictogramă nouă</translation>
<translation id="5502860503640766021">S-a blocat <ph name="PERMISSION_1" />, se permite <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Site-urile nu îți pot solicita să îți trimită notificări</translation>
<translation id="5516455585884385570">Deschide setările pentru notificări</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Permisiuni</translation>
<translation id="5860033963881614850">Dezactivat</translation>
<translation id="5876056640971328065">ÃŽntrerupe videoclipul</translation>
+<translation id="5904826301761575486">Actualizezi numele și pictograma de pe ecranul de pornire?</translation>
<translation id="5916664084637901428">Activat</translation>
<translation id="5922853908706496913">Se permite accesul la ecran</translation>
<translation id="5939518447894949180">Resetează</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blochează cookie-urile terță parte</translation>
<translation id="6206551242102657620">Conexiunea este sigură. Informații despre site</translation>
<translation id="6216432067784365534">Opțiuni pentru <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Închide și raportează un abuz</translation>
<translation id="6262279340360821358">Sunt blocate <ph name="PERMISSION_1" /> și <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Site-urile îți pot solicita să îți trimită notificări</translation>
<translation id="6295158916970320988">Toate site-urile</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Pentru a permite aplicației <ph name="APP_NAME" /> să acceseze locația, activează locația și în <ph name="BEGIN_LINK" />Setările Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Revocă permisiunea de accesare a dispozitivului</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Un cookie folosit}few{# cookie-uri folosite}other{# de cookie-uri folosite}}</translation>
-<translation id="8463851957836045671">Site-ul este rapid</translation>
<translation id="8487700953926739672">Disponibil offline</translation>
<translation id="851751545965956758">Blochează conectarea site-urilor la dispozitive</translation>
<translation id="8525306231823319788">Ecran complet</translation>
<translation id="857943718398505171">Acordată (recomandat)</translation>
<translation id="8609465669617005112">Mutați mai sus</translation>
+<translation id="861748745608658996">Actualizezi numele de pe ecranul de pornire?</translation>
<translation id="8676374126336081632">Șterge textul introdus</translation>
<translation id="868929229000858085">Caută în agendă</translation>
<translation id="8702612070107455751">Toate datele offline vor fi șterse.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Mărește</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC este dezactivat pentru acest dispozitiv. Activează-l în <ph name="BEGIN_LINK" />Setări Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Site-ul se deschide și reacționează rapid în majoritatea cazurilor.</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Ieși din modul incognito?</translation>
<translation id="8958424370300090006">Blochează cookie-urile pentru un anumit site.</translation>
<translation id="8959122750345127698">Navigarea nu este accesibilă: <ph name="URL" /></translation>
<translation id="8986362086234534611">Șterge</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ru.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ru.xtb
index 369df06d77e..2b837c3b652 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ru.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ru.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ru">
<translation id="1006017844123154345">Открыть в Интернете</translation>
<translation id="1044891598689252897">Сайты будут работать в нормальном режиме</translation>
+<translation id="1100504063505580045">Текущий значок</translation>
<translation id="1124090076051167250">Будут удалены данные и файлы cookie, Ñохраненные Ñайтами или приложениÑми, добавленными на главный Ñкран. Ð’Ñего: <ph name="DATASIZE" />.</translation>
<translation id="1124772482545689468">Пользователь</translation>
<translation id="1178581264944972037">Пауза</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Микрофон</translation>
<translation id="3277252321222022663">ПредоÑтавить Ñайтам доÑтуп к датчикам (рекомендуетÑÑ)</translation>
<translation id="3295602654194328831">Скрыть информацию</translation>
+<translation id="3317660236277031814">У веб-приложениÑ, которое вы уÑтановили, изменилÑÑ Ð·Ð½Ð°Ñ‡Ð¾Ðº.</translation>
<translation id="3328801116991980348">Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñайте</translation>
<translation id="3333961966071413176">Ð’Ñе контакты</translation>
<translation id="3386292677130313581">Запрашивать разрешение на доÑтуп к данным о меÑтоположении (рекомендуетÑÑ)</translation>
+<translation id="345699454248713913">У веб-приложениÑ, которое вы уÑтановили, изменилоÑÑŒ название.</translation>
<translation id="3538390592868664640">Запретить Ñайтам Ñоздавать 3D-карту меÑта, в котором вы находитеÑÑŒ, и отÑлеживать положение камеры</translation>
+<translation id="3551268116566418498">Выйти из режима инкогнито?</translation>
<translation id="3586500876634962664">ИÑпользование камеры и микрофона</translation>
<translation id="358794129225322306">Разрешить Ñайту автоматичеÑки Ñкачивать неÑколько файлов.</translation>
<translation id="3594780231884063836">Выключить звук Ð´Ð»Ñ Ð²Ð¸Ð´ÐµÐ¾</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Открыть наÑтройки геолокации</translation>
<translation id="4226663524361240545">Ð’Ð¸Ð±Ñ€Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸ получении уведомлений</translation>
<translation id="4259722352634471385">ÐÐ°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð°: <ph name="URL" /></translation>
+<translation id="4277239631747669329">У веб-приложениÑ, которое вы уÑтановили, изменилиÑÑŒ название и значок.</translation>
<translation id="4278390842282768270">Разрешено</translation>
<translation id="429312253194641664">Ðа Ñайте воÑпроизводÑÑ‚ÑÑ Ð¼ÐµÐ´Ð¸Ð°Ñ„Ð°Ð¹Ð»Ñ‹</translation>
<translation id="42981349822642051">Развернуть</translation>
<translation id="4336434711095810371">Удалить вÑе данные</translation>
<translation id="4402755511846832236">Блокировать передачу на Ñайты информации об иÑпользовании уÑтройÑтва</translation>
-<translation id="4433925000917964731">Lite-верÑÐ¸Ñ Ñтраницы получена Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Google</translation>
<translation id="4434045419905280838">Ð’Ñплывающие окна и переадреÑациÑ</translation>
<translation id="445467742685312942">Разрешить Ñайтам воÑпроизводить защищенный контент</translation>
<translation id="4468959413250150279">Отключить звуки на определенном Ñайте</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">УправлÑетÑÑ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ родителÑми</translation>
<translation id="4670064810192446073">Ð’Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ Ñ€ÐµÐ°Ð»ÑŒÐ½Ð¾ÑÑ‚ÑŒ</translation>
<translation id="4708011789095599544">Ð’Ñ‹ дейÑтвительно хотите удалить файлы cookie и другие данные Ð´Ð»Ñ Ñтого Ñайта?</translation>
+<translation id="473775607612524610">Обновить</translation>
<translation id="4751476147751820511">Датчики Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¸ оÑвещенноÑти</translation>
<translation id="4836046166855586901">Спрашивать перед передачей на Ñайт информации об иÑпользовании уÑтройÑтва</translation>
<translation id="4883854917563148705">УправлÑемые наÑтройки ÑброÑить нельзÑ</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">СпоÑоб отправки</translation>
<translation id="5039804452771397117">Разрешить</translation>
<translation id="5048398596102334565">ПредоÑтавить Ñайтам доÑтуп к датчикам Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ (рекомендуетÑÑ)</translation>
+<translation id="5050380848339752099">Этот Ñайт передает информацию Ñтороннему приложению, пока вы находитеÑÑŒ в режиме инкогнито.</translation>
<translation id="5063480226653192405">ИÑпользование</translation>
<translation id="5100237604440890931">Свернуто. Ðажмите, чтобы развернуть.</translation>
<translation id="5123685120097942451">Вкладка инкогнито</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Разрешить Ñайтам иÑпользовать JavaScript (рекомендуетÑÑ)</translation>
<translation id="534295439873310000">УÑтройÑтва Ñ NFC</translation>
<translation id="5354152178998424783">Будут удалены данные и файлы cookie (вÑего <ph name="DATASIZE" />), Ñохраненные Ñайтами.</translation>
-<translation id="5384883051496921101">Этот Ñайт передает информацию Ñтороннему приложению, пока вы в режиме инкогнито.</translation>
+<translation id="536508626067510330">Обновить значок на главном Ñкране?</translation>
<translation id="5391532827096253100">Подключение к Ñайту не защищено. Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñайте</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(и ещё 1)}one{(и ещё #)}few{(и ещё #)}many{(и ещё #)}other{(и ещё #)}}</translation>
<translation id="5403592356182871684">Имена</translation>
<translation id="5489227211564503167">ПроÑмотрено <ph name="ELAPSED_TIME" /> из <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Блокировать объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð½Ð° Ñайтах, которые показывают навÑзчивую или вводÑщую в заблуждение рекламу</translation>
+<translation id="549957179819296104">Ðовый значок</translation>
<translation id="5502860503640766021">Разрешено: <ph name="PERMISSION_1" />. Заблокировано: <ph name="PERMISSION_2" />.</translation>
<translation id="5505264765875738116">Сайты не могут запрашивать Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° отправку уведомлений</translation>
<translation id="5516455585884385570">Перейти в наÑтройки уведомлений</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">РазрешениÑ</translation>
<translation id="5860033963881614850">ВЫКЛ</translation>
<translation id="5876056640971328065">ПриоÑтановить видео</translation>
+<translation id="5904826301761575486">Обновить название и значок на главном Ñкране?</translation>
<translation id="5916664084637901428">ВКЛ</translation>
<translation id="5922853908706496913">ПредоÑтавлен доÑтуп к вашему Ñкрану</translation>
<translation id="5939518447894949180">СброÑить</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Блокировать Ñторонние файлы cookie</translation>
<translation id="6206551242102657620">Подключение защищено. Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñайте</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" />: параметры</translation>
+<translation id="6260852843601447737">Закрыть и Ñообщить о нарушении</translation>
<translation id="6262279340360821358">Заблокировано: <ph name="PERMISSION_1" /> и <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Сайты могут запрашивать Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° отправку уведомлений</translation>
<translation id="6295158916970320988">Ð’Ñе Ñайты</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Чтобы у Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ "<ph name="APP_NAME" />" был доÑтуп к данным о меÑтоположении, включите геолокацию в <ph name="BEGIN_LINK" />наÑтройках Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Отключить доÑтуп к уÑтройÑтву</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{ИÑпользуетÑÑ 1 файл cookie}one{ИÑпользуетÑÑ # файл cookie}few{ИÑпользуютÑÑ # файла cookie}many{ИÑпользуютÑÑ # файлов cookie}other{ИÑпользуетÑÑ # файла cookie}}</translation>
-<translation id="8463851957836045671">Сайт работает быÑтро</translation>
<translation id="8487700953926739672">ДоÑтупно в автономном режиме</translation>
<translation id="851751545965956758">Ðе разрешать Ñайтам подключатьÑÑ Ðº уÑтройÑтвам</translation>
<translation id="8525306231823319788">ПолноÑкранный режим</translation>
<translation id="857943718398505171">Разрешено (рекомендуетÑÑ)</translation>
<translation id="8609465669617005112">ПеремеÑтить вверх</translation>
+<translation id="861748745608658996">Обновить название на главном Ñкране?</translation>
<translation id="8676374126336081632">ОчиÑтить</translation>
<translation id="868929229000858085">ПоиÑк контактов</translation>
<translation id="8702612070107455751">Ð’Ñе офлайн-данные будут удалены.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Увеличить</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ NFC на Ñтом уÑтройÑтве отключена. Включите ее в <ph name="BEGIN_LINK" />наÑтройках Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">У большинÑтва пользователей Ñтот Ñайт быÑтро загружаетÑÑ Ð¸ без задержек отвечает на запроÑÑ‹.</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Выйти из режима инкогнито?</translation>
<translation id="8958424370300090006">Блокировать файлы cookie Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð½Ð¾Ð³Ð¾ Ñайта.</translation>
<translation id="8959122750345127698">Страница не найдена: <ph name="URL" /></translation>
<translation id="8986362086234534611">Удалить</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_si.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_si.xtb
index 60176f7e0e9..83e0623cb89 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_si.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_si.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="si">
<translation id="1006017844123154345">සබà·à¶³à·’à·€ විවෘත කරන්න</translation>
<translation id="1044891598689252897">වෙබ් අඩවි à·ƒà·à¶¸à·à¶±à·Šâ€à¶ºà¶ºà·™à¶±à·Š ක්â€à¶»à·’ය෠කරයි</translation>
+<translation id="1100504063505580045">වත්මන් නිරූපකය</translation>
<translation id="1124090076051167250">මෙය වෙබ් අඩවි හ෠යෙදුම් මඟින් ඔබේ මුල් තිරය මත ගබඩ෠කර ඇති දත්ත සහ කුකී <ph name="DATASIZE" /> ක් ඉවත් කරයි.</translation>
<translation id="1124772482545689468">පරිà·à·“ලක</translation>
<translation id="1178581264944972037">විරà·à¶¸à¶º</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">මයික්â€à¶»à·†à·à¶±à¶º:</translation>
<translation id="3277252321222022663">වෙබ් අඩවිවලට සංවේදක වෙත ප්â€à¶»à·€à·šà· වීමට ඉඩ දෙන්න (නිර්දේà·à·’තයි)</translation>
<translation id="3295602654194328831">තතු සඟවන්න</translation>
+<translation id="3317660236277031814">ඔබ ස්ථà·à¶´à¶±à¶º කළ වෙබ් යෙදුමක් එහි නිරූපකය වෙනස් කර ඇත.</translation>
<translation id="3328801116991980348">අඩවි තොරතුරු</translation>
<translation id="3333961966071413176">සියලු සම්බන්ධතà·</translation>
<translation id="3386292677130313581">අඩවි වලට ඔබගේ ස්ථà·à¶±à¶º දà·à¶± ගà·à¶±à·“මට ඉඩ දීමට පෙර විමසන්න (නිර්දේà·à·’තයි)</translation>
+<translation id="345699454248713913">ඔබ ස්ථà·à¶´à¶±à¶º කළ වෙබ් යෙදුමක් එහි නම වෙනස් කර ඇත.</translation>
<translation id="3538390592868664640">වෙබ් අඩවිය ඔබේ වටපිටà·à·€à·š ත්â€à¶»à·’මà·à¶± සිතියමක් සෑදීමෙන් හ෠කà·à¶¸à¶»à· ස්ථà·à¶±à¶º හඹ෠යෑමෙන් අවහිර කරන්න</translation>
+<translation id="3551268116566418498">අප්â€à¶»à·ƒà·’ද්ධ ප්â€à¶»à¶šà·à¶». ඉවත් වන්නද?</translation>
<translation id="3586500876634962664">කà·à¶¸à¶»à· සහ මයික්â€à¶»à·œà·†à·à¶± භà·à·€à·’තය</translation>
<translation id="358794129225322306">වෙබ් අඩවියකට ගොනු කිහිපයක් ස්වයංක්â€à¶»à·“යව බà·à¶œà·à¶±à·“මට ඉඩ දෙන්න.</translation>
<translation id="3594780231884063836">වීඩියà·à·€ නිහඬ කරන්න</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">ස්ථà·à¶± à·ƒà·à¶šà·ƒà·“ම් විවෘත කරන්න</translation>
<translation id="4226663524361240545">දà·à¶±à·”ම්දීම් උපà·à¶‚ගය කම්පනය කළ à·„à·à¶š</translation>
<translation id="4259722352634471385">සංචà·à¶½à¶±à¶º අවහිර කර ඇත: <ph name="URL" /></translation>
+<translation id="4277239631747669329">ඔබ ස්ථà·à¶´à¶±à¶º කළ වෙබ් යෙදුමක් එහි නම සහ නිරූපකය වෙනස් කර ඇත.</translation>
<translation id="4278390842282768270">ඉඩ දුන්</translation>
<translation id="429312253194641664">වෙබ් අඩවියක් මà·à¶°à·Šâ€à¶º ධà·à·€à¶± කරයි</translation>
<translation id="42981349822642051">දිගහරින්න</translation>
<translation id="4336434711095810371">සියලු දත්ත හිස් කරන්න</translation>
<translation id="4402755511846832236">ඔබ මෙම උපà·à¶‚ගය සක්â€à¶»à·’යව භà·à·€à·’ත කරන විට දà·à¶± ගà·à¶±à·“මෙන් අඩවි අවහිර කරන්න</translation>
-<translation id="4433925000917964731">Google විසින් දෙනු ලබන à·ƒà·à·„à·à¶½à·Šà¶½à·” පිටුව</translation>
<translation id="4434045419905280838">උත්පතන සහ හරව෠යà·à·€à·“ම්</translation>
<translation id="445467742685312942">මෙම වෙබ් අඩවියට ආරක්â€à·‚ිත අන්තර්ගතය ධà·à·€à¶± කිරීමට ඉඩ දෙන්න.</translation>
<translation id="4468959413250150279">නිà·à·Šà¶ à·’ත අඩවියක් සඳහ෠à·à¶¶à·Šà¶¯à¶º නිහඬ කරන්න.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">ඔබේ දෙමව්පියන් පà·à¶½à¶±à¶º කරයි</translation>
<translation id="4670064810192446073">අතත්â€à¶º යථà·à¶»à·Šà¶®à¶º</translation>
<translation id="4708011789095599544">මෙම වෙබ් අඩවිය සඳහ෠කුකි සහ වෙනත් අඩවි දත්ත ඉවත් කිරීමට ඔබට අවà·à·Šâ€à¶º බව ඔබට විà·à·Šà·€à·à·ƒà¶¯?</translation>
+<translation id="473775607612524610">යà·à·€à¶­à·Šà¶šà·à¶½à·“නය</translation>
<translation id="4751476147751820511">චලිත හ෠ආලà·à¶š සංවේදක</translation>
<translation id="4836046166855586901">ඔබ මෙම උපà·à¶‚ගය සක්â€à¶»à·’යව භà·à·€à·’ත කරන අවස්ථà·à·€ අඩවියකට දà·à¶± ගà·à¶±à·“මට අවà·à·Šâ€à¶º විට විමසන්න</translation>
<translation id="4883854917563148705">කළමන෠කෙරෙන à·ƒà·à¶šà·ƒà·“ම් යළි à·ƒà·à¶šà·ƒà·’ය නොහà·à¶š</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">හරහ෠බෙදà·à¶œà¶±à·Šà¶±</translation>
<translation id="5039804452771397117">ඉඩදෙන්න</translation>
<translation id="5048398596102334565">වෙබ් අඩවිවලට චලන සංවේදකවලට ප්â€à¶»à·€à·šà· වීමට ඉඩ දෙන්න (නිර්දේà·à·’තයි)</translation>
+<translation id="5050380848339752099">මෙම අඩවිය අප්â€à¶»à·ƒà·’ද්ධ ප්â€à¶»à¶šà·à¶»à¶ºà·™à¶±à·Š පිටත යෙදුමක් සමග තොරතුරු බෙද෠ගà·à¶±à·“මට සූදà·à¶±à¶¸à·Šà¶º.</translation>
<translation id="5063480226653192405">භà·à·€à·’තය</translation>
<translation id="5100237604440890931">හකුළන ලදි - දිග à·„à·à¶»à·“මට ක්ලික් කරන්න</translation>
<translation id="5123685120097942451">අප්â€à¶»à¶šà¶§ පටිත්ත</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">ජà·à·€à·à·ƒà·Šà¶šà·Šâ€à¶»à·’ප්ට් ධà·à·€à¶±à¶º කිරීමට අඩවි වලට ඉඩ දෙන්න (නිර්දේà·à·’තයි)</translation>
<translation id="534295439873310000">NFC උපà·à¶‚ග</translation>
<translation id="5354152178998424783">මෙය වෙබ් අඩවිවලින් ගමන෠කරනු ලà·à¶¶à·– දත්ත සහ කුකී <ph name="DATASIZE" /> ක් ඉවත් කරයි.</translation>
-<translation id="5384883051496921101">මෙම අඩවිය අප්â€à¶»à·ƒà·’ද්ධ ප්â€à¶»à¶šà·à¶»à·™à¶ºà¶±à·Š පිටත යෙදුමක් සමග තොරතුරු බෙද෠ගà·à¶±à·“මට සූදà·à¶±à¶¸à·Šà¶º.</translation>
+<translation id="536508626067510330">ඔබගේ මුල් තිරයෙහි නිරූපකය යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන්නද?</translation>
<translation id="5391532827096253100">මෙම අඩවිය වෙත ඔබගේ සම්බන්ධතà·à·€à¶º සුරක්ෂිත නොවේ. අඩවි තොරතුරු</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(තවත් + 1ක්)}one{(තවත් + #ක්)}other{(තවත් + #ක්)}}</translation>
<translation id="5403592356182871684">නම්</translation>
<translation id="5489227211564503167">ගත වූ කà·à¶½à¶º <ph name="TOTAL_TIME" /> න් <ph name="ELAPSED_TIME" />.</translation>
<translation id="5494752089476963479">ආක්â€à¶»à¶¸à¶«à·à·“ලී හ෠නොමඟ යවන දà·à¶±à·Šà·€à·“ම් පෙන්වන වෙබ් අඩවි මත දà·à¶±à·Šà·€à·“ම් අවහිර කරන්න</translation>
+<translation id="549957179819296104">නව නිරූපකය</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> ඉඩ දෙන ලදි, <ph name="PERMISSION_2" /> අවහිර කරන ලදි</translation>
<translation id="5505264765875738116">වෙබ් අඩවිවලට දà·à¶±à·”ම්දීම් යà·à·€à·“මට ඉල්ලිය නොහà·à¶š</translation>
<translation id="5516455585884385570">දà·à¶±à·”ම්දීම් à·ƒà·à¶šà·ƒà·“ම් විවෘත කරන්න</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">අවසර</translation>
<translation id="5860033963881614850">අක්â€à¶»à·“ය</translation>
<translation id="5876056640971328065">විඩියà·à·€ විරà·à¶¸ කරන්න</translation>
+<translation id="5904826301761575486">ඔබගේ මුල් තිරයෙහි නම සහ නිරූපකය යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන්නද?</translation>
<translation id="5916664084637901428">ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶šà¶ºà·’</translation>
<translation id="5922853908706496913">ඔබේ තිරය බෙද෠ගà·à¶±à·“ම</translation>
<translation id="5939518447894949180">නà·à·€à¶­ සකසන්න</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">තෙවන-පà·à¶»à·Šà·à·Šà·€ කුකී අවහිර කරන්න</translation>
<translation id="6206551242102657620">සම්බන්ධතà·à·€à¶º සුරක්ෂිතයි. අඩවි තොරතුරු</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> විකල්ප</translation>
+<translation id="6260852843601447737">වසන්න සහ අපයà·à¶¢à¶±à¶º à·€à·à¶»à·Šà¶­à· කරන්න</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> සහ <ph name="PERMISSION_2" /> අවහිර කරන ලදි</translation>
<translation id="6270391203985052864">වෙබ් අඩවිවලට දà·à¶±à·”ම්දීම් යà·à·€à·“මට ඉල්ලිය à·„à·à¶š</translation>
<translation id="6295158916970320988">සියලු අඩවි</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> හට ඔබේ ස්ථà·à¶±à¶ºà¶§ ප්â€à¶»à·€à·šà· වීමට ඉඩ දීමට, <ph name="BEGIN_LINK" />Android à·ƒà·à¶šà·ƒà·“ම්<ph name="END_LINK" /> තුළද ස්ථà·à¶±à¶º ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶š කරන්න.</translation>
<translation id="8447861592752582886">උපà·à¶‚ගයේ අවසර අහà·à·ƒà·’ කරන්න</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{කුකි 1ක් භà·à·€à·’තයේ ඇත}one{කුකි #ක් භà·à·€à·’තයේ ඇත}other{කුකි #ක් භà·à·€à·’තයේ ඇත}}</translation>
-<translation id="8463851957836045671">අඩවිය වේගවත් ය</translation>
<translation id="8487700953926739672">නොබà·à¶³à·’à·€ ලද à·„à·à¶š</translation>
<translation id="851751545965956758">අඩවි උපà·à¶‚ගවලට සම්බන්ධ වීම අවහිර කරන්න</translation>
<translation id="8525306231823319788">සම්පුර්ණ තිරය</translation>
<translation id="857943718398505171">ඉඩ දේ (නිර්දේà·à·’තයි)</translation>
<translation id="8609465669617005112">ඉහළට යන්න</translation>
+<translation id="861748745608658996">ඔබගේ මුල් තිරයෙහි නම යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන්නද?</translation>
<translation id="8676374126336081632">ආදà·à¶±à¶º හිස් කරන්න</translation>
<translation id="868929229000858085">ඔබේ සම්බන්ධත෠සොයන්න</translation>
<translation id="8702612070107455751">නොබà·à¶³à·’ දත්ත කිසිවක් හිස් කෙරේ.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">විà·à·à¶½à¶±à¶º කරන්න</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">මෙම උපà·à¶‚ගය සඳහ෠NFC අක්â€à¶»à·’යයි. <ph name="BEGIN_LINK" />Android à·ƒà·à¶šà·ƒà·“ම්<ph name="END_LINK" /> තුළින් එය සක්â€à¶»à·“ය කරන්න.</translation>
-<translation id="8929372349074745002">මෙම අඩවිය බොහ෠පුද්ගලයින් සඳහ෠ඉක්මනින් විවෘත වන අතර ප්â€à¶»à¶­à·’චà·à¶» දක්වයි</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">අප්â€à¶»à·ƒà·’ද්ධ ප්â€à¶»à¶šà·à¶»à¶º à·„à·à¶» යන්නද?</translation>
<translation id="8958424370300090006">නිà·à·Šà¶ à·’ත අඩවියක් සඳහ෠කුකී අවහිර කරන්න.</translation>
<translation id="8959122750345127698">සංචà·à¶½à¶±à¶º වෙත ළඟ෠විය නොහà·à¶šà·’ය: <ph name="URL" /></translation>
<translation id="8986362086234534611">අමතක</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sk.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sk.xtb
index 5409455bd22..5f0ff2061d1 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sk.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sk.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="sk">
<translation id="1006017844123154345">Otvoriť online</translation>
<translation id="1044891598689252897">Weby budú fungovať normálne</translation>
+<translation id="1100504063505580045">Aktuálna ikona</translation>
<translation id="1124090076051167250">Týmto vymažete <ph name="DATASIZE" /> dát a súbory cookie uložené webmi alebo aplikáciami na ploche.</translation>
<translation id="1124772482545689468">Používateľ</translation>
<translation id="1178581264944972037">Pozastaviť</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofón</translation>
<translation id="3277252321222022663">PovoliÅ¥ webom prístup k senzorom (odporúÄané)</translation>
<translation id="3295602654194328831">Skryť informácie</translation>
+<translation id="3317660236277031814">Zmenila sa ikona webovej aplikácie, ktorú ste nainštalovali.</translation>
<translation id="3328801116991980348">Informácie o stránkach</translation>
<translation id="3333961966071413176">VÅ¡etky kontakty</translation>
<translation id="3386292677130313581">PýtaÅ¥ sa, Äi chcete povoliÅ¥ webu zisÅ¥ovaÅ¥ vaÅ¡u polohu (odporúÄané)</translation>
+<translation id="345699454248713913">Zmenil sa názov webovej aplikácie, ktorú ste nainštalovali.</translation>
<translation id="3538390592868664640">Brániť webom vytvárať priestorovú mapu okolia a sledovať pozíciu kamery</translation>
+<translation id="3551268116566418498">Chcete ukonÄiÅ¥ režim inkognito?</translation>
<translation id="3586500876634962664">Používanie kamery a mikrofónu</translation>
<translation id="358794129225322306">Povoľuje webu automaticky sÅ¥ahovaÅ¥ viacero súborov súÄasne.</translation>
<translation id="3594780231884063836">Vypnúť zvuk videa</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Otvoriť nastavenia polohy</translation>
<translation id="4226663524361240545">Upozornenia môžu pri prijatí na zariadení spustiť vibrovanie</translation>
<translation id="4259722352634471385">Navigácia je zablokovaná: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Zmenil sa názov a ikona webovej aplikácie, ktorú ste nainštalovali.</translation>
<translation id="4278390842282768270">Povolené</translation>
<translation id="429312253194641664">Web prehráva médiá</translation>
<translation id="42981349822642051">Rozbaliť</translation>
<translation id="4336434711095810371">Vymazať všetky dáta</translation>
<translation id="4402755511846832236">NeumožniÅ¥ webom zistiÅ¥, Äi aktívne používate toto zariadenie</translation>
-<translation id="4433925000917964731">Zjednodušenú verziu stránky poskytol Google</translation>
<translation id="4434045419905280838">Vyskakovacie okná a presmerovania</translation>
<translation id="445467742685312942">Povoliť webom prehrávať chránený obsah</translation>
<translation id="4468959413250150279">Vypnúť zvuk na konkrétnom webe.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Spravované vaším rodiÄom</translation>
<translation id="4670064810192446073">Virtuálna realita</translation>
<translation id="4708011789095599544">Naozaj chcete vymazaÅ¥ súbory cookie a ÄalÅ¡ie údaje tohto webu?</translation>
+<translation id="473775607612524610">Aktualizovať</translation>
<translation id="4751476147751820511">Senzory pohybu alebo svetla</translation>
<translation id="4836046166855586901">OpýtaÅ¥ sa, keÄ chce web zistiÅ¥, Äi aktívne používate toto zariadenie</translation>
<translation id="4883854917563148705">Spravované nastavenia sa nedajú resetovať</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Zdieľať</translation>
<translation id="5039804452771397117">Povoliť</translation>
<translation id="5048398596102334565">PovoliÅ¥ webom prístup k senzorom pohybu (odporúÄané)</translation>
+<translation id="5050380848339752099">Tento web chce zdieľať informácie s aplikáciou mimo režimu inkognito.</translation>
<translation id="5063480226653192405">Použitie</translation>
<translation id="5100237604440890931">Zbalená (rozbalíte ju kliknutím)</translation>
<translation id="5123685120097942451">Karta inkognito</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">PovoliÅ¥ webom spúšťaÅ¥ JavaScript (odporúÄa sa)</translation>
<translation id="534295439873310000">Zariadenia NFC</translation>
<translation id="5354152178998424783">Týmto vymažete <ph name="DATASIZE" /> dát a súborov cookie uložených webmi.</translation>
-<translation id="5384883051496921101">Tento web chce zdieľať informácie s aplikáciou mimo režimu inkognito.</translation>
+<translation id="536508626067510330">Chcete aktualizovať ikonu na ploche?</translation>
<translation id="5391532827096253100">Spojenie s týmto webom nie je zabezpeÄené. Informácie o webe</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 ÄalÅ¡ie)}few{(+ # ÄalÅ¡ie)}many{(+ # more)}other{(+ # Äalších)}}</translation>
<translation id="5403592356182871684">Názvy</translation>
<translation id="5489227211564503167">Uplynutý Äas: <ph name="ELAPSED_TIME" /> z <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blokovať reklamy na weboch, ktoré zobrazujú obťažujúce alebo zavádzajúce reklamy</translation>
+<translation id="549957179819296104">Nová ikona</translation>
<translation id="5502860503640766021">Povolené: <ph name="PERMISSION_1" />, blokované: <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Weby nemôžu žiadať o odosielanie upozornení</translation>
<translation id="5516455585884385570">Otvoriť nastavenia upozornení</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Povolenia</translation>
<translation id="5860033963881614850">Vypnuté</translation>
<translation id="5876056640971328065">Pozastaviť video</translation>
+<translation id="5904826301761575486">Chcete aktualizovať názov a ikonu na ploche?</translation>
<translation id="5916664084637901428">Zapnuté</translation>
<translation id="5922853908706496913">Zdieľate obrazovku</translation>
<translation id="5939518447894949180">Resetovať</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokovať súbory cookie tretích strán</translation>
<translation id="6206551242102657620">Spojenie je zabezpeÄené. Informácie o webe</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> – možnosti</translation>
+<translation id="6260852843601447737">Zavrieť a nahlásiť zneužitie</translation>
<translation id="6262279340360821358">Blokované: <ph name="PERMISSION_1" /> a <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Weby môžu žiadať o odosielanie upozornení</translation>
<translation id="6295158916970320988">VÅ¡etky weby</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Ak chcete povoliť aplikácii <ph name="APP_NAME" /> používať vašu polohu, zapnite ju aj v <ph name="BEGIN_LINK" />nastaveniach Androidu<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Odvolať povolenie pre zariadenie</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Používa sa 1 súbor cookie}few{Používajú sa # súbory cookie}many{# cookies in use}other{Používa sa # súborov cookie}}</translation>
-<translation id="8463851957836045671">Web je rýchly</translation>
<translation id="8487700953926739672">K dispozícii offline</translation>
<translation id="851751545965956758">Brániť webom pripájať sa k zariadeniam</translation>
<translation id="8525306231823319788">Celá obrazovka</translation>
<translation id="857943718398505171">Povolené (odporúÄané)</translation>
<translation id="8609465669617005112">Presunúť nahor</translation>
+<translation id="861748745608658996">Chcete aktualizovať názov na ploche?</translation>
<translation id="8676374126336081632">Vymazať vstup</translation>
<translation id="868929229000858085">Prehľadať kontakty</translation>
<translation id="8702612070107455751">Všetky offline dáta budú vymazané.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Priblížiť</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">Technológia NFC je v tomto zariadení vypnutá. Zapnite ju v <ph name="BEGIN_LINK" />Nastaveniach Androidu<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Tento web sa väÄÅ¡ine ľudí otvára rýchlo, aj tak reaguje</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">UkonÄiÅ¥ režim inkognito?</translation>
<translation id="8958424370300090006">Blokovať súbory cookie na konkrétnom webe.</translation>
<translation id="8959122750345127698">Navigácia je nedostupná: <ph name="URL" /></translation>
<translation id="8986362086234534611">Odstrániť</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb
index a69c40409b8..ae514072b25 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sl.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="sl">
<translation id="1006017844123154345">Odpri v spletu</translation>
<translation id="1044891598689252897">Spletna mesta bodo delovala normalno</translation>
+<translation id="1100504063505580045">Trenutna ikona</translation>
<translation id="1124090076051167250">S tem boste izbrisali <ph name="DATASIZE" /> podatkov in piÅ¡kotkov, ki so jih shranila spletna mesta ali aplikacije na zaÄetnem zaslonu.</translation>
<translation id="1124772482545689468">Uporabnik</translation>
<translation id="1178581264944972037">Prekini</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Spletnim mestom dovoli dostop do tipal (priporoÄeno)</translation>
<translation id="3295602654194328831">Skrij informacije</translation>
+<translation id="3317660236277031814">Spletna aplikacija, ki ste jo namestili, je spremenila ikono.</translation>
<translation id="3328801116991980348">Podatki o mestu</translation>
<translation id="3333961966071413176">Vsi stiki</translation>
<translation id="3386292677130313581">Prikaži poziv, preden se spletnim mestom razkrije vaÅ¡a lokacija (priporoÄeno)</translation>
+<translation id="345699454248713913">Spletna aplikacija, ki ste jo namestili, je spremenila ime.</translation>
<translation id="3538390592868664640">PrepreÄevanje, da bi spletna mesta ustvarila 3D-zemljevid vaÅ¡e okolice ali spremljala položaj kamere</translation>
+<translation id="3551268116566418498">Izklop anonimnega naÄina?</translation>
<translation id="3586500876634962664">Uporaba kamere in mikrofona</translation>
<translation id="358794129225322306">Dovoli spletnemu mestu samodejni prenos veÄ datotek.</translation>
<translation id="3594780231884063836">Izklop videa</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Odpri nastavitve lokacije</translation>
<translation id="4226663524361240545">Ob prejemanju obvestil naprava morda vibrira</translation>
<translation id="4259722352634471385">Krmarjenje je blokirano: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Spletna aplikacija, ki ste jo namestili, je spremenila ime in ikono.</translation>
<translation id="4278390842282768270">Dovoljeno</translation>
<translation id="429312253194641664">Spletno mesto predvaja predstavnost</translation>
<translation id="42981349822642051">Razširi</translation>
<translation id="4336434711095810371">Izbriši vse podatke</translation>
<translation id="4402755511846832236">PrepreÄevanje, da bi spletna mesta vedela, kdaj aktivno uporabljate to napravo.</translation>
-<translation id="4433925000917964731">Stran v osnovnem naÄinu, ki jo je prikazal Google</translation>
<translation id="4434045419905280838">Pojavna okna in preusmeritve</translation>
<translation id="445467742685312942">Spletnim mestom dovoli predvajanje zaÅ¡Äitene vsebine</translation>
<translation id="4468959413250150279">Izklop zvoka za doloÄeno spletno mesto.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Upravlja starš</translation>
<translation id="4670064810192446073">Navidezna resniÄnost</translation>
<translation id="4708011789095599544">Ali ste prepriÄani, da želite izbrisati piÅ¡kotke in druge podatke spletnega mesta?</translation>
+<translation id="473775607612524610">Posodobi</translation>
<translation id="4751476147751820511">Tipala za gibanje in svetlobo</translation>
<translation id="4836046166855586901">Vprašaj, ko želi spletno mesto vedeti, kdaj aktivno uporabljate to napravo.</translation>
<translation id="4883854917563148705">Upravljanih nastavitev ni mogoÄe ponastaviti</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Skupna raba prek</translation>
<translation id="5039804452771397117">Dovoli</translation>
<translation id="5048398596102334565">Spletnim mestom dovoli dostop do tipal gibanja (priporoÄeno)</translation>
+<translation id="5050380848339752099">To spletno mesto bo delilo podatke z aplikacijo zunaj anonimnega naÄina.</translation>
<translation id="5063480226653192405">Uporaba</translation>
<translation id="5100237604440890931">Strnjeno – kliknite, Äe želite razÅ¡iriti.</translation>
<translation id="5123685120097942451">Anonimni zavihek</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Spletnim mestom dovoli izvajanje JavaScripta (priporoÄeno)</translation>
<translation id="534295439873310000">Naprave s tehnologijo NFC</translation>
<translation id="5354152178998424783">S tem boste izbrisali <ph name="DATASIZE" /> podatkov in piškotkov, ki so jih shranila spletna mesta.</translation>
-<translation id="5384883051496921101">To spletno mesto bo delilo podatke z aplikacijo zunaj anonimnega naÄina.</translation>
+<translation id="536508626067510330">Želite posodobiti ikono na zaÄetnem zaslonu?</translation>
<translation id="5391532827096253100">Povezava s tem spletnim mestom ni varna. Podatki o spletnem mestu.</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(in Å¡e 1)}one{(in Å¡e #)}two{(in Å¡e #)}few{(in Å¡e #)}other{(in Å¡e #)}}</translation>
<translation id="5403592356182871684">Imena</translation>
<translation id="5489227211564503167">PreteÄeni Äas: <ph name="ELAPSED_TIME" /> od <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blokiranje oglasov na spletnih mestih, ki prikazujejo vsiljive ali zavajajoÄe oglase</translation>
+<translation id="549957179819296104">Nova ikona</translation>
<translation id="5502860503640766021">Dovoljeno: <ph name="PERMISSION_1" />, blokirano: <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Spletna mesta vas ne smejo vprašati, ali želite, da vam pošiljajo obvestila</translation>
<translation id="5516455585884385570">Odpiranje nastavitev obvestil</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Dovoljenja</translation>
<translation id="5860033963881614850">Izklopljeno</translation>
<translation id="5876056640971328065">ZaÄasna zaustavitev videa</translation>
+<translation id="5904826301761575486">Želite posodobiti ime in ikono na zaÄetnem zaslonu?</translation>
<translation id="5916664084637901428">Vklopljeno</translation>
<translation id="5922853908706496913">Deljenje zaslona</translation>
<translation id="5939518447894949180">Ponastavi</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokiraj piškotke drugih spletnih mest</translation>
<translation id="6206551242102657620">Povezava je varna. Podatki o spletnem mestu.</translation>
<translation id="6216432067784365534">Možnosti za <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Zaprite in prijavite zlorabo</translation>
<translation id="6262279340360821358">Blokirano: <ph name="PERMISSION_1" /> in <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Spletna mesta vas lahko vprašajo, ali želite, da vam pošiljajo obvestila</translation>
<translation id="6295158916970320988">Vsa spletna mesta</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">ÄŒe želite aplikaciji <ph name="APP_NAME" /> omogoÄiti dostop do lokacije, lokacijo vklopite tudi v <ph name="BEGIN_LINK" />nastavitvah za Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Umik dovoljenja za dostop do naprave</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 piškotek v uporabi}one{# piškotek v uporabi}two{# piškotka v uporabi}few{# piškotki v uporabi}other{# piškotkov v uporabi}}</translation>
-<translation id="8463851957836045671">Spletno mesto je hitro</translation>
<translation id="8487700953926739672">Na voljo brez povezave</translation>
<translation id="851751545965956758">Spletnim mestom prepreÄi povezovanje z napravami</translation>
<translation id="8525306231823319788">Celozaslonsko</translation>
<translation id="857943718398505171">Dovoljeno (priporoÄeno)</translation>
<translation id="8609465669617005112">Premakni navzgor</translation>
+<translation id="861748745608658996">Želite posodobiti ime na zaÄetnem zaslonu?</translation>
<translation id="8676374126336081632">Izbriši vnos</translation>
<translation id="868929229000858085">Iskanje po stikih</translation>
<translation id="8702612070107455751">Morebitni podatki brez povezave bodo izbrisani.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">PoveÄaj</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">Tehnologija NFC je izklopljena za to napravo. Vklopite jo v <ph name="BEGIN_LINK" />nastavitvah za Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">To spletno mesto se odpre in odzove hitro za veÄino uporabnikov</translation>
<translation id="8941729603749328384">www.primer.si</translation>
-<translation id="894871326938397531">Izklop anonimnega naÄina?</translation>
<translation id="8958424370300090006">Blokiranje piÅ¡kotkov za doloÄeno spletno mesto.</translation>
<translation id="8959122750345127698">Krmarjenje ni dosegljivo: <ph name="URL" /></translation>
<translation id="8986362086234534611">Pozabi</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sq.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sq.xtb
index f858cf56af4..87ab7fc4929 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sq.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sq.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="sq">
<translation id="1006017844123154345">Hap versionin në linjë</translation>
<translation id="1044891598689252897">Sajtet do të punojnë normalisht</translation>
+<translation id="1100504063505580045">Ikona aktuale</translation>
<translation id="1124090076051167250">Kjo do të pastrojë <ph name="DATASIZE" /> të dhëna dhe kuki të ruajtura nga sajtet ose nga aplikacionet në ekranin bazë.</translation>
<translation id="1124772482545689468">Përdoruesi</translation>
<translation id="1178581264944972037">Pauzë</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofoni</translation>
<translation id="3277252321222022663">Lejoju faqeve të të hapin sensorët (rekomandohet)</translation>
<translation id="3295602654194328831">Fshih informacionin</translation>
+<translation id="3317660236277031814">Një aplikacion interneti që ke instaluar ka ndryshuar ikonën.</translation>
<translation id="3328801116991980348">Informacionet rreth sajtit</translation>
<translation id="3333961966071413176">Të gjitha kontaktet</translation>
<translation id="3386292677130313581">Pyet përpara se sajtet të lejohen të dinë vendndodhjen tënde (rekomandohet)</translation>
+<translation id="345699454248713913">Një aplikacion interneti që ke instaluar ka ndryshuar emrin.</translation>
<translation id="3538390592868664640">Blloko krijimin nga sajtet të një harte 3D të ambientit tënd rrethues ose gjurmimin prej tyre të pozicionit të kamerës</translation>
+<translation id="3551268116566418498">Të dilet nga modaliteti "i fshehtë"?</translation>
<translation id="3586500876634962664">Përdorimi i kamerës/mikrofonit</translation>
<translation id="358794129225322306">Lejo një sajt të shkarkojë shumë skedarë automatikisht.</translation>
<translation id="3594780231884063836">Çaktivizo zërin e videos</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Hap "Cilësimet e vendndodhjes"</translation>
<translation id="4226663524361240545">Njoftimet mund të bëjnë që pajisja të dridhet</translation>
<translation id="4259722352634471385">Lundrimi është bllokuar: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Një aplikacion interneti që ke instaluar ka ndryshuar emrin dhe ikonën.</translation>
<translation id="4278390842282768270">Të lejuara</translation>
<translation id="429312253194641664">Një sajt po luan media</translation>
<translation id="42981349822642051">Zgjero</translation>
<translation id="4336434711095810371">Pastro të gjitha të dhënat</translation>
<translation id="4402755511846832236">Blloko sajtet që të mos e dinë kur ti e përdor këtë pajisje në mënyrë aktive</translation>
-<translation id="4433925000917964731">Faqja e lehtë ofrohet nga Google.</translation>
<translation id="4434045419905280838">Dritaret kërcyese dhe ridrejtimet</translation>
<translation id="445467742685312942">Lejo sajtet të luajnë përmbajtje të mbrojtura</translation>
<translation id="4468959413250150279">Hiq zërin për një sajt specifik.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Menaxhohet nga prindi yt</translation>
<translation id="4670064810192446073">Realiteti virtual</translation>
<translation id="4708011789095599544">E konfirmon se dëshiron t'i fshish kukit dhe të dhënat e tjera të sajtit për këtë faqe interneti?</translation>
+<translation id="473775607612524610">Përditësoje</translation>
<translation id="4751476147751820511">Sensorët e lëvizjes ose të dritës</translation>
<translation id="4836046166855586901">Pyet kur një sajt kërkon të dijë kur ti e përdor këtë pajisje në mënyrë aktive</translation>
<translation id="4883854917563148705">Cilësimet e menaxhuara nuk mund të rivendosen</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Ndaje nëpërmjet</translation>
<translation id="5039804452771397117">Lejo</translation>
<translation id="5048398596102334565">Lejoju faqeve të të hapin sensorët e lëvizjes (rekomandohet)</translation>
+<translation id="5050380848339752099">Ky sajt është gati për të ndarë informacione me një aplikacion jashtë modalitetit "të fshehtë".</translation>
<translation id="5063480226653192405">Përdorimi</translation>
<translation id="5100237604440890931">I palosur - kliko për ta zgjeruar</translation>
<translation id="5123685120097942451">Skeda "e fshehtë"</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Lejoji sajtet të ekzekutojnë JavaScript (rekomandohet)</translation>
<translation id="534295439873310000">Pajisjet me NFC</translation>
<translation id="5354152178998424783">Kjo do të pastrojë <ph name="DATASIZE" /> të dhëna dhe kuki të ruajtura nga sajtet.</translation>
-<translation id="5384883051496921101">Ky sajt është gati për të ndarë informacione me një aplikacion jashtë modalitetit "të fshehtë".</translation>
+<translation id="536508626067510330">Të përditësohet ikona në ekranin tënd bazë?</translation>
<translation id="5391532827096253100">Lidhja jote me këtë faqe nuk është e sigurt. Informacioni i faqes</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 tjetër)}other{(+ # të tjerë)}}</translation>
<translation id="5403592356182871684">Emrat</translation>
<translation id="5489227211564503167">Koha e kaluar: <ph name="ELAPSED_TIME" /> nga <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blloko reklamat në sajtet që shfaqin reklama ndërhyrëse ose mashtruese</translation>
+<translation id="549957179819296104">Ikonë e re</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> është lejuar, <ph name="PERMISSION_2" /> është bllokuar</translation>
<translation id="5505264765875738116">Sajtet nuk mund të kërkojnë të dërgojnë njoftime</translation>
<translation id="5516455585884385570">Hap cilësimet e njoftimeve</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Lejet</translation>
<translation id="5860033963881614850">Çaktivizuar</translation>
<translation id="5876056640971328065">Vendose videon në pauzë</translation>
+<translation id="5904826301761575486">Të përditësohet emri dhe ikona në ekranin tënd bazë?</translation>
<translation id="5916664084637901428">Aktiv</translation>
<translation id="5922853908706496913">Po ndan ekranin tënd</translation>
<translation id="5939518447894949180">Rivendos</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blloko kukit e palëve të treta</translation>
<translation id="6206551242102657620">Lidhja është e sigurt. Informacioni i faqes</translation>
<translation id="6216432067784365534">Opsionet për <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Mbyll dhe raporto abuzimin</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> dhe <ph name="PERMISSION_2" /> të bllokuara</translation>
<translation id="6270391203985052864">Sajtet mund të kërkojnë të dërgojnë njoftime</translation>
<translation id="6295158916970320988">Të gjitha sajtet</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Për të lejuar që <ph name="APP_NAME" /> të ketë qasje te vendndodhja jote, aktivizo gjithashtu vendndodhjen në <ph name="BEGIN_LINK" />Cilësimet e Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Revoko lejen e pajisjes</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 kuki në përdorim}other{# kuki në përdorim}}</translation>
-<translation id="8463851957836045671">Sajti është i shpejtë</translation>
<translation id="8487700953926739672">Mundësohet jashtë linje</translation>
<translation id="851751545965956758">Blloko lidhjen e sajteve me pajisjet</translation>
<translation id="8525306231823319788">Ekrani i plotë</translation>
<translation id="857943718398505171">Lejuar (rekomandohet)</translation>
<translation id="8609465669617005112">Lëviz lart</translation>
+<translation id="861748745608658996">Të përditësohet emri në ekranin tënd bazë?</translation>
<translation id="8676374126336081632">Pastro hyrjen</translation>
<translation id="868929229000858085">Kërko te kontaktet e tua</translation>
<translation id="8702612070107455751">Çdo e dhënë jashtë linje do të fshihet.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Zmadho</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">Veçoria NFC është joaktive për këtë pajisje. Aktivizoje te <ph name="BEGIN_LINK" />Cilësimet e Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Ky sajt hapet dhe përgjigjet shpejt për shumicën e personave</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Dëshiron të dalësh nga modaliteti "i fshehtë"?</translation>
<translation id="8958424370300090006">Blloko kukit për një sajt specifik.</translation>
<translation id="8959122750345127698">Lundrimi është i paarritshëm: <ph name="URL" /></translation>
<translation id="8986362086234534611">Harro</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sr-Latn.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sr-Latn.xtb
index d101c63e1b0..e20d317140f 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sr-Latn.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sr-Latn.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="sr-Latn">
<translation id="1006017844123154345">Otvori onlajn</translation>
<translation id="1044891598689252897">Sajtovi cÌe normalno raditi</translation>
+<translation id="1100504063505580045">Aktuelna ikona</translation>
<translation id="1124090076051167250">Ovim briÅ¡ete <ph name="DATASIZE" /> podataka i kolaÄicÌa koje Äuvaju sajtovi ili aplikacije na poÄetnom ekranu.</translation>
<translation id="1124772482545689468">Korisnik</translation>
<translation id="1178581264944972037">Pauziraj</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Dozvoli sajtovima da pristupaju senzorima (preporuÄeno)</translation>
<translation id="3295602654194328831">Sakrij informacije</translation>
+<translation id="3317660236277031814">Veb-aplikacija koju ste instalirali je promenila ikonu.</translation>
<translation id="3328801116991980348">Informacije o sajtu</translation>
<translation id="3333961966071413176">Svi kontakti</translation>
<translation id="3386292677130313581">Pitaj pre nego Å¡to dozvoliÅ¡ sajtovima da znaju lokaciju (preporuÄeno)</translation>
+<translation id="345699454248713913">Veb-aplikacija koju ste instalirali je promenila naziv.</translation>
<translation id="3538390592868664640">SpreÄite sajtove da prave 3D mapu okruženja ili da prate položaj kamere</translation>
+<translation id="3551268116566418498">Izlazite iz rež. bez arhiviranja?</translation>
<translation id="3586500876634962664">KoriÅ¡cÌenje kamere i mikrofona</translation>
<translation id="358794129225322306">Dozvolite sajtu da automatski preuzima više datoteka.</translation>
<translation id="3594780231884063836">IskljuÄite zvuk videa</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Otvorite podešavanja lokacije</translation>
<translation id="4226663524361240545">UreÄ‘aj cÌe vibrirati kada primate obaveÅ¡tenja</translation>
<translation id="4259722352634471385">Navigacija je blokirana: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Veb-aplikacija koju ste instalirali je promenila naziv i ikonu.</translation>
<translation id="4278390842282768270">Dozvoljeno</translation>
<translation id="429312253194641664">Sajt pušta medijski sadržaj</translation>
<translation id="42981349822642051">Proširite</translation>
<translation id="4336434711095810371">Obriši sve podatke</translation>
<translation id="4402755511846832236">Ne dozvolite sajtovima da znaju kada aktivno koristite ovaj uređaj</translation>
-<translation id="4433925000917964731">Pojednostavljenu stranicu pruža Google</translation>
<translation id="4434045419905280838">IskaÄucÌi prozori i preusmeravanja</translation>
<translation id="445467742685312942">Dozvolite sajtovima da puÅ¡taju zaÅ¡ticÌeni sadržaj</translation>
<translation id="4468959413250150279">IskljuÄi zvuk za odreÄ‘eni sajt</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Ovim upravlja tvoj roditelj</translation>
<translation id="4670064810192446073">Virtuelna realnost</translation>
<translation id="4708011789095599544">Želite li stvarno da obriÅ¡ete kolaÄicÌe i druge podatke o sajtu za ovaj veb-sajt?</translation>
+<translation id="473775607612524610">Ažuriraj</translation>
<translation id="4751476147751820511">Senzori za pokret ili svetlo</translation>
<translation id="4836046166855586901">Pitaj kada sajt želi da zna kada aktivno koristim ovaj uređaj</translation>
<translation id="4883854917563148705">Podešavanja kojima se upravlja ne mogu da se resetuju</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Deljenje preko</translation>
<translation id="5039804452771397117">Dozvoli</translation>
<translation id="5048398596102334565">Dozvoli sajtovima da pristupaju senzorima za pokret (preporuÄeno)</translation>
+<translation id="5050380848339752099">Ovaj sajt cÌe deliti informacije sa aplikacijom izvan režima bez arhiviranja.</translation>
<translation id="5063480226653192405">KoriÅ¡cÌenje</translation>
<translation id="5100237604440890931">Skupljeno je – Kliknite da biste proširili.</translation>
<translation id="5123685120097942451">Kartica bez arhiviranja</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Dozvoli sajtovima da pokrecÌu JavaScript (preporuÄeno)</translation>
<translation id="534295439873310000">NFC uređaji</translation>
<translation id="5354152178998424783">Ovim briÅ¡ete <ph name="DATASIZE" /> podataka i kolaÄicÌa koje Äuvaju sajtovi.</translation>
-<translation id="5384883051496921101">Ovaj sajt cÌe deliti informacije sa aplikacijom izvan režima bez arhiviranja.</translation>
+<translation id="536508626067510330">Želite da ažurirate ikonu na poÄetnom ekranu?</translation>
<translation id="5391532827096253100">Veza sa ovim sajtom nije bezbedna. Informacije o sajtu</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(i još 1)}one{(i još #)}few{(i još #)}other{(i još #)}}</translation>
<translation id="5403592356182871684">Imena</translation>
<translation id="5489227211564503167">Proteklo vreme: <ph name="ELAPSED_TIME" /> od <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blokiraj oglase na sajtovima koji prikazuju oglase koji ometaju aktivnosti ili obmanjujucÌe oglase</translation>
+<translation id="549957179819296104">Nova ikona</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" />: dozvoljeno. <ph name="PERMISSION_2" />: blokirano</translation>
<translation id="5505264765875738116">Sajtovi ne mogu da traže da šalju obaveštenja</translation>
<translation id="5516455585884385570">Otvorite podešavanja obaveštenja</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Dozvole</translation>
<translation id="5860033963881614850">IskljuÄeno</translation>
<translation id="5876056640971328065">Pauziraj video</translation>
+<translation id="5904826301761575486">Želite da ažurirate naziv i ikonu na poÄetnom ekranu?</translation>
<translation id="5916664084637901428">UkljuÄeno</translation>
<translation id="5922853908706496913">Deli se ekran</translation>
<translation id="5939518447894949180">Resetuj</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blokiraj kolaÄicÌe trecÌe strane</translation>
<translation id="6206551242102657620">Veza je bezbedna. Informacije o sajtu</translation>
<translation id="6216432067784365534">Opcije stavke <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Zatvori i prijavi zloupotrebu</translation>
<translation id="6262279340360821358">Dozvole <ph name="PERMISSION_1" /> i <ph name="PERMISSION_2" /> su blokirane</translation>
<translation id="6270391203985052864">Sajtovi mogu da traže da šalju obaveštenja</translation>
<translation id="6295158916970320988">Svi sajtovi</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Da biste dozvolili da <ph name="APP_NAME" /> pristupa lokaciji, ukljuÄite lokaciju i u <ph name="BEGIN_LINK" />Android podeÅ¡avanjima<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Opozovi dozvolu za uređaj</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Koristi se 1 kolaÄicÌ}one{Koristi se # kolaÄicÌ}few{Koriste se # kolaÄicÌa}other{Koristi se # kolaÄicÌa}}</translation>
-<translation id="8463851957836045671">Sajt je brz</translation>
<translation id="8487700953926739672">Dostupno van mreže</translation>
<translation id="851751545965956758">OnemogucÌi sajtovima da se povezuju sa ureÄ‘ajima</translation>
<translation id="8525306231823319788">Ceo ekran</translation>
<translation id="857943718398505171">Dozvoljeno (preporuÄeno)</translation>
<translation id="8609465669617005112">Premesti nagore</translation>
+<translation id="861748745608658996">Želite da ažurirate naziv na poÄetnom ekranu?</translation>
<translation id="8676374126336081632">Obriši unos</translation>
<translation id="868929229000858085">Pretražite kontakte</translation>
<translation id="8702612070107455751">Brišu se svi oflajn podaci.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">UvecÌavanje</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC je iskljuÄen za ovaj ureÄ‘aj. UkljuÄite ga u <ph name="BEGIN_LINK" />Android podeÅ¡avanjima<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Ovaj sajt se brzo otvara i brzo reaguje za vecÌinu ljudi</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Izlazite iz režima bez arhiviranja?</translation>
<translation id="8958424370300090006">Blokirajte kolaÄicÌe za odreÄ‘eni sajt.</translation>
<translation id="8959122750345127698">Navigacija je nedostupna: <ph name="URL" /></translation>
<translation id="8986362086234534611">Zaboravi</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sr.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sr.xtb
index d0bb4747952..1e3146b6e2f 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sr.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sr.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="sr">
<translation id="1006017844123154345">Отвори онлајн</translation>
<translation id="1044891598689252897">Сајтови ће нормално радити</translation>
+<translation id="1100504063505580045">Ðктуелна икона</translation>
<translation id="1124090076051167250">Овим бришете <ph name="DATASIZE" /> података и колачића које чувају Ñајтови или апликације на почетном екрану.</translation>
<translation id="1124772482545689468">КориÑник</translation>
<translation id="1178581264944972037">Паузирај</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Микрофон</translation>
<translation id="3277252321222022663">Дозволи Ñајтовима да приÑтупају Ñензорима (препоручено)</translation>
<translation id="3295602654194328831">Сакриј информације</translation>
+<translation id="3317660236277031814">Веб-апликација коју Ñте инÑталирали је променила икону.</translation>
<translation id="3328801116991980348">Информације о Ñајту</translation>
<translation id="3333961966071413176">Сви контакти</translation>
<translation id="3386292677130313581">Питај пре него што дозволиш Ñајтовима да знају локацију (препоручено)</translation>
+<translation id="345699454248713913">Веб-апликација коју Ñте инÑталирали је променила назив.</translation>
<translation id="3538390592868664640">Спречите Ñајтове да праве 3D мапу окружења или да прате положај камере</translation>
+<translation id="3551268116566418498">Излазите из реж. без архивирања?</translation>
<translation id="3586500876634962664">Коришћење камере и микрофона</translation>
<translation id="358794129225322306">Дозволите Ñајту да аутоматÑки преузима више датотека.</translation>
<translation id="3594780231884063836">ИÑкључите звук видеа</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Отворите подешавања локације</translation>
<translation id="4226663524361240545">Уређај ће вибрирати када примате обавештења</translation>
<translation id="4259722352634471385">Ðавигација је блокирана: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Веб-апликација коју Ñте инÑталирали је променила назив и икону.</translation>
<translation id="4278390842282768270">Дозвољено</translation>
<translation id="429312253194641664">Сајт пушта медијÑки Ñадржај</translation>
<translation id="42981349822642051">Проширите</translation>
<translation id="4336434711095810371">Обриши Ñве податке</translation>
<translation id="4402755511846832236">Ðе дозволите Ñајтовима да знају када активно кориÑтите овај уређај</translation>
-<translation id="4433925000917964731">ПоједноÑтављену Ñтраницу пружа Google</translation>
<translation id="4434045419905280838">ИÑкачући прозори и преуÑмеравања</translation>
<translation id="445467742685312942">Дозволите Ñајтовима да пуштају заштићени Ñадржај</translation>
<translation id="4468959413250150279">ИÑкључи звук за одређени Ñајт</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Овим управља твој родитељ</translation>
<translation id="4670064810192446073">Виртуелна реалноÑÑ‚</translation>
<translation id="4708011789095599544">Желите ли Ñтварно да обришете колачиће и друге податке о Ñајту за овај веб-Ñајт?</translation>
+<translation id="473775607612524610">Ðжурирај</translation>
<translation id="4751476147751820511">Сензори за покрет или Ñветло</translation>
<translation id="4836046166855586901">Питај када Ñајт жели да зна када активно кориÑтим овај уређај</translation>
<translation id="4883854917563148705">Подешавања којима Ñе управља не могу да Ñе реÑетују</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Дељење преко</translation>
<translation id="5039804452771397117">Дозволи</translation>
<translation id="5048398596102334565">Дозволи Ñајтовима да приÑтупају Ñензорима за покрет (препоручено)</translation>
+<translation id="5050380848339752099">Овај Ñајт ће делити информације Ñа апликацијом изван режима без архивирања.</translation>
<translation id="5063480226653192405">Коришћење</translation>
<translation id="5100237604440890931">Скупљено је – Кликните да биÑте проширили.</translation>
<translation id="5123685120097942451">Картица без архивирања</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Дозволи Ñајтовима да покрећу JavaScript (препоручено)</translation>
<translation id="534295439873310000">NFC уређаји</translation>
<translation id="5354152178998424783">Овим бришете <ph name="DATASIZE" /> података и колачића које чувају Ñајтови.</translation>
-<translation id="5384883051496921101">Овај Ñајт ће делити информације Ñа апликацијом изван режима без архивирања.</translation>
+<translation id="536508626067510330">Желите да ажурирате икону на почетном екрану?</translation>
<translation id="5391532827096253100">Веза Ñа овим Ñајтом није безбедна. Информације о Ñајту</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(и још 1)}one{(и још #)}few{(и још #)}other{(и још #)}}</translation>
<translation id="5403592356182871684">Имена</translation>
<translation id="5489227211564503167">Протекло време: <ph name="ELAPSED_TIME" /> од <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Блокирај оглаÑе на Ñајтовима који приказују оглаÑе који ометају активноÑти или обмањујуће оглаÑе</translation>
+<translation id="549957179819296104">Ðова икона</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" />: дозвољено. <ph name="PERMISSION_2" />: блокирано</translation>
<translation id="5505264765875738116">Сајтови не могу да траже да шаљу обавештења</translation>
<translation id="5516455585884385570">Отворите подешавања обавештења</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Дозволе</translation>
<translation id="5860033963881614850">ИÑкључено</translation>
<translation id="5876056640971328065">Паузирај видео</translation>
+<translation id="5904826301761575486">Желите да ажурирате назив и икону на почетном екрану?</translation>
<translation id="5916664084637901428">Укључено</translation>
<translation id="5922853908706496913">Дели Ñе екран</translation>
<translation id="5939518447894949180">РеÑетуј</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Блокирај колачиће треће Ñтране</translation>
<translation id="6206551242102657620">Веза је безбедна. Информације о Ñајту</translation>
<translation id="6216432067784365534">Опције Ñтавке <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Затвори и пријави злоупотребу</translation>
<translation id="6262279340360821358">Дозволе <ph name="PERMISSION_1" /> и <ph name="PERMISSION_2" /> Ñу блокиране</translation>
<translation id="6270391203985052864">Сајтови могу да траже да шаљу обавештења</translation>
<translation id="6295158916970320988">Сви Ñајтови</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Да биÑте дозволили да <ph name="APP_NAME" /> приÑтупа локацији, укључите локацију и у <ph name="BEGIN_LINK" />Android подешавањима<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Опозови дозволу за уређај</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{КориÑти Ñе 1 колачић}one{КориÑти Ñе # колачић}few{КориÑте Ñе # колачића}other{КориÑти Ñе # колачића}}</translation>
-<translation id="8463851957836045671">Сајт је брз</translation>
<translation id="8487700953926739672">ДоÑтупно ван мреже</translation>
<translation id="851751545965956758">Онемогући Ñајтовима да Ñе повезују Ñа уређајима</translation>
<translation id="8525306231823319788">Цео екран</translation>
<translation id="857943718398505171">Дозвољено (препоручено)</translation>
<translation id="8609465669617005112">ПремеÑти нагоре</translation>
+<translation id="861748745608658996">Желите да ажурирате назив на почетном екрану?</translation>
<translation id="8676374126336081632">Обриши уноÑ</translation>
<translation id="868929229000858085">Претражите контакте</translation>
<translation id="8702612070107455751">Бришу Ñе Ñви офлајн подаци.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Увећавање</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC је иÑкључен за овај уређај. Укључите га у <ph name="BEGIN_LINK" />Android подешавањима<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Овај Ñајт Ñе брзо отвара и брзо реагује за већину људи</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Излазите из режима без архивирања?</translation>
<translation id="8958424370300090006">Блокирајте колачиће за одређени Ñајт.</translation>
<translation id="8959122750345127698">Ðавигација је недоÑтупна: <ph name="URL" /></translation>
<translation id="8986362086234534611">Заборави</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sv.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sv.xtb
index 77cdeb1f3cb..20b4855fcf7 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sv.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sv.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="sv">
<translation id="1006017844123154345">Öppna onlineversionen</translation>
<translation id="1044891598689252897">Webbplatser fungerar som de ska</translation>
+<translation id="1100504063505580045">Nuvarande ikon</translation>
<translation id="1124090076051167250"><ph name="DATASIZE" /> data och cookies som har sparats av webbplatser eller appar på startskärmen rensas.</translation>
<translation id="1124772482545689468">Användare</translation>
<translation id="1178581264944972037">Paus</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Tillåt att webbplatser får åtkomst till enhetens sensorer (rekommenderas)</translation>
<translation id="3295602654194328831">Dölj info</translation>
+<translation id="3317660236277031814">En webbapp som du har installerat har bytt ikon.</translation>
<translation id="3328801116991980348">Platsinformation</translation>
<translation id="3333961966071413176">Alla kontakter</translation>
<translation id="3386292677130313581">Fråga innan webbplatser tillåts att veta var du befinner dig (rekommenderas)</translation>
+<translation id="345699454248713913">En webbapp som du har installerat har bytt namn.</translation>
<translation id="3538390592868664640">Blockera webbplatser från att skapa en 3D-karta över dina omgivningar eller registrera kamerans position</translation>
+<translation id="3551268116566418498">Vill du avsluta inkognitoläget?</translation>
<translation id="3586500876634962664">Kamera- och mikrofonanvändning</translation>
<translation id="358794129225322306">Tillåt att en webbplats laddar ned flera filer automatiskt.</translation>
<translation id="3594780231884063836">Stäng av ljudet för videon</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Öppna platsinställningarna</translation>
<translation id="4226663524361240545">Aviseringar kan göra att enheten vibrerar</translation>
<translation id="4259722352634471385">Webbadressen har blockerats: <ph name="URL" /></translation>
+<translation id="4277239631747669329">En webbapp som du har installerat har bytt namn och ikon.</translation>
<translation id="4278390842282768270">Tillåts</translation>
<translation id="429312253194641664">Media spelas upp på en webbplats</translation>
<translation id="42981349822642051">Expandera</translation>
<translation id="4336434711095810371">Rensa all data</translation>
<translation id="4402755511846832236">Blockera webbplatser från att veta när du använder enheten aktivt</translation>
-<translation id="4433925000917964731">Lite-sida tillhandahållen av Google</translation>
<translation id="4434045419905280838">Popup-fönster och omdirigeringar</translation>
<translation id="445467742685312942">Tillåt att webbplatser spelar upp skyddat innehåll</translation>
<translation id="4468959413250150279">Stäng av ljudet för en webbplats.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Hanteras av din förälder</translation>
<translation id="4670064810192446073">Virtuell verklighet</translation>
<translation id="4708011789095599544">Vill du rensa cookies och annan webbplatsdata för den här webbplatsen?</translation>
+<translation id="473775607612524610">Uppdatera</translation>
<translation id="4751476147751820511">Rörelse- eller ljussensorer</translation>
<translation id="4836046166855586901">Fråga när en webbplats vill veta om du använder enheten aktivt</translation>
<translation id="4883854917563148705">Hanterade inställningar kan inte återställas</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Dela via</translation>
<translation id="5039804452771397117">Tillåt</translation>
<translation id="5048398596102334565">Tillåt webbplatser att använda enhetens rörelsesensorer (rekommenderas)</translation>
+<translation id="5050380848339752099">Data på den här webbplatsen delas med en app utanför inkognitoläget.</translation>
<translation id="5063480226653192405">Användning</translation>
<translation id="5100237604440890931">Vyn har komprimerats. Expandera den genom att klicka.</translation>
<translation id="5123685120097942451">Inkognitoflik</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Tillåt att JavaScript körs på webbplatser (rekommenderas)</translation>
<translation id="534295439873310000">NFC-enheter</translation>
<translation id="5354152178998424783"><ph name="DATASIZE" /> data och cookies som har sparats av webbplatser rensas.</translation>
-<translation id="5384883051496921101">Data på den här webbplatsen delas med en app utanför inkognitoläget.</translation>
+<translation id="536508626067510330">Vill du uppdatera ikonen på startskärmen?</translation>
<translation id="5391532827096253100">Anslutningen till webbplatsen är inte säker. Webbplatsinformation</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 till)}other{(+ # till)}}</translation>
<translation id="5403592356182871684">Namn</translation>
<translation id="5489227211564503167">Förfluten tid: <ph name="ELAPSED_TIME" /> av <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Blockera annonser på webbplatser där påträngande eller vilseledande annonser visas</translation>
+<translation id="549957179819296104">Ny ikon</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> tillåts, <ph name="PERMISSION_2" /> blockeras</translation>
<translation id="5505264765875738116">Webbplatser får inte be om tillåtelse att skicka aviseringar</translation>
<translation id="5516455585884385570">Öppna aviseringsinställningar</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Behörigheter</translation>
<translation id="5860033963881614850">Av</translation>
<translation id="5876056640971328065">Pausa video</translation>
+<translation id="5904826301761575486">Vill du uppdatera namnet och ikonen på startskärmen?</translation>
<translation id="5916664084637901428">PÃ¥</translation>
<translation id="5922853908706496913">Delar skärmen</translation>
<translation id="5939518447894949180">Återställ</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Blockera cookies från tredje part</translation>
<translation id="6206551242102657620">Anslutningen är säker. Webbplatsinformation</translation>
<translation id="6216432067784365534">Alternativ för <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Stäng och anmäl otillåten användning</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> och <ph name="PERMISSION_2" /> blockeras</translation>
<translation id="6270391203985052864">Webbplatser får be om tillåtelse att skicka aviseringar</translation>
<translation id="6295158916970320988">Alla webbplatser</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Om du vill ge <ph name="APP_NAME" /> åtkomst till din plats måste du även aktivera plats i <ph name="BEGIN_LINK" />Android-inställningarna<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Återkalla enhetsbehörighet</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie används}other{# cookies används}}</translation>
-<translation id="8463851957836045671">Webbplatsen är snabb</translation>
<translation id="8487700953926739672">Tillgänglig offline</translation>
<translation id="851751545965956758">Förhindra att webbplatser ansluter till enheter</translation>
<translation id="8525306231823319788">Helskärm</translation>
<translation id="857943718398505171">Tillåten (rekommenderas)</translation>
<translation id="8609465669617005112">Flytta upp</translation>
+<translation id="861748745608658996">Vill du uppdatera namnet på startskärmen?</translation>
<translation id="8676374126336081632">Radera inmatning</translation>
<translation id="868929229000858085">Sök bland kontakterna</translation>
<translation id="8702612070107455751">All offlinedata raderas.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Zooma in</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC är inte aktiverat på enheten. Aktivera det i <ph name="BEGIN_LINK" />Android-inställningarna<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Den här webbplatsen öppnas och svarar fort för de flesta användare</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Inaktivera inkognitoläget?</translation>
<translation id="8958424370300090006">Blockera cookies för en enskild webbplats.</translation>
<translation id="8959122750345127698">Det går inte att nå webbadressen: <ph name="URL" /></translation>
<translation id="8986362086234534611">Glöm</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sw.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sw.xtb
index 0b20ff9f511..c526dd9ec86 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sw.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_sw.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="sw">
<translation id="1006017844123154345">Fungua Mtandaoni</translation>
<translation id="1044891598689252897">Tovuti zitafanya kazi kama kawaida</translation>
+<translation id="1100504063505580045">Aikoni ya sasa</translation>
<translation id="1124090076051167250">Hatua hii itafuta <ph name="DATASIZE" /> ya data na vidakuzi vilivyohifadhiwa na tovuti au programu kwenye Skrini ya kwanza.</translation>
<translation id="1124772482545689468">Mtumiaji</translation>
<translation id="1178581264944972037">Sitisha</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Maikrofoni</translation>
<translation id="3277252321222022663">Ruhusu tovuti zifikie vitambuzi (inapendekezwa)</translation>
<translation id="3295602654194328831">Ficha Maelezo</translation>
+<translation id="3317660236277031814">Programu ya wavuti uliyosakinisha imebadilisha aikoni yake.</translation>
<translation id="3328801116991980348">Maelezo ya tovuti</translation>
<translation id="3333961966071413176">Anwani zote</translation>
<translation id="3386292677130313581">Uliza kabla ya kuruhusu tovuti zijue mahali ulipo (inapendekezwa)</translation>
+<translation id="345699454248713913">Programu ya wavuti uliyosakinisha imebadilisha jina lake.</translation>
<translation id="3538390592868664640">Zuia tovuti zisibuni ramani ya 3D ya mazingira yako wala kufuatilia mkao wa kamera</translation>
+<translation id="3551268116566418498">Ungependa kufunga hali fiche?</translation>
<translation id="3586500876634962664">Matumizi ya kamera na maikrofoni</translation>
<translation id="358794129225322306">Ruhusu tovuti ipakue faili nyingi kiotomatiki.</translation>
<translation id="3594780231884063836">Zima video</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Fungua Mipangilio ya Mahali</translation>
<translation id="4226663524361240545">Arifa huenda zitatetemesha kifaa</translation>
<translation id="4259722352634471385">Kudurusu kumezuiwa: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Programu ya wavuti uliyosakinisha imebadilisha jina na aikoni yake.</translation>
<translation id="4278390842282768270">Imeruhusiwa</translation>
<translation id="429312253194641664">Tovuti inacheza maudhui</translation>
<translation id="42981349822642051">Panua</translation>
<translation id="4336434711095810371">Futa data yote</translation>
<translation id="4402755511846832236">Zuia tovuti zisijue wakati unatumia kifaa hiki</translation>
-<translation id="4433925000917964731">Ukurasa mwepesi umetolewa na Google</translation>
<translation id="4434045419905280838">Madirisha ibukizi/kuelekeza kwingine</translation>
<translation id="445467742685312942">Ruhusu tovuti icheze maudhui yanayolindwa</translation>
<translation id="4468959413250150279">Zima sauti katika tovuti mahususi.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Inadhibitiwa na wazazi wako</translation>
<translation id="4670064810192446073">Uhalisia pepe</translation>
<translation id="4708011789095599544">Je, una uhakika unataka kufuta vidakuzi na data nyingine ya tovuti hii?</translation>
+<translation id="473775607612524610">Sasisha</translation>
<translation id="4751476147751820511">Vitambuzi vya mwendo au mwangaza</translation>
<translation id="4836046166855586901">Tovuti ikuombe ruhusa inapotaka kujua wakati unatumia kifaa hiki</translation>
<translation id="4883854917563148705">Huwezi kubadilisha mipangilio inayodhibitiwa</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Shiriki kupitia</translation>
<translation id="5039804452771397117">Ruhusu</translation>
<translation id="5048398596102334565">Ruhusu tovuti zifikie vitambuzi vyako vya mwendo (inapendekezwa)</translation>
+<translation id="5050380848339752099">Tovuti hii inaelekea kushiriki maelezo na programu nyingine nje ya Hali fiche.</translation>
<translation id="5063480226653192405">Matumizi</translation>
<translation id="5100237604440890931">Imekunjwa - bofya ili upanue.</translation>
<translation id="5123685120097942451">Kichupo fiche</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Ruhusu tovuti zitumie JavaScript (inapendekezwa)</translation>
<translation id="534295439873310000">Vifaa vya NFC</translation>
<translation id="5354152178998424783">Hatua hii itafuta data na vidakuzi vya ukubwa wa <ph name="DATASIZE" /> vilivyohifadhiwa na tovuti.</translation>
-<translation id="5384883051496921101">Tovuti hii inakaribia kushiriki maelezo na programu nyingine isiyo katika hali fiche.</translation>
+<translation id="536508626067510330">Aikoni kwenye skrini yako ya kwanza ibadilishwe?</translation>
<translation id="5391532827096253100">Muunganisho wako kwenye tovuti hii si salama. Maelezo ya tovuti</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 zaidi)}other{(+ # zaidi)}}</translation>
<translation id="5403592356182871684">Majina</translation>
<translation id="5489227211564503167">Muda uliopita ni <ph name="ELAPSED_TIME" /> kati ya <ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Zuia matangazo kwenye tovuti zinazoonyesha matangazo yanayopotosha au yanayokatiza huduma</translation>
+<translation id="549957179819296104">Aikoni mpya</translation>
<translation id="5502860503640766021">Umeruhusu <ph name="PERMISSION_1" />, umezuia <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Tovuti haziwezi kukuuliza kutuma arifa</translation>
<translation id="5516455585884385570">Fungua mipangilio ya arifa</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Idhini</translation>
<translation id="5860033963881614850">Kimezimwa</translation>
<translation id="5876056640971328065">Sitisha video</translation>
+<translation id="5904826301761575486">Ungependa kubadilisha jina na aikoni kwenye skrini yako ya kwanza?</translation>
<translation id="5916664084637901428">Imewashwa</translation>
<translation id="5922853908706496913">Inashiriki skrini yako</translation>
<translation id="5939518447894949180">Weka upya</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Zuia vidakuzi vya tovuti nyingine</translation>
<translation id="6206551242102657620">Muunganisho ni salama. Maelezo ya tovuti</translation>
<translation id="6216432067784365534">Chaguo za <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Funga na uripoti matumizi mabaya</translation>
<translation id="6262279340360821358">Umezuia <ph name="PERMISSION_1" /> na <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Tovuti zinaweza kukuuliza kutuma arifa</translation>
<translation id="6295158916970320988">Tovuti zote</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Ili uruhusu <ph name="APP_NAME" /> ifikie data ya mahali ulipo, washa pia huduma ya mahali katika <ph name="BEGIN_LINK" />Mipangilio ya Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Batilisha ruhusa ya kifaa</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Kidakuzi kimoja kinatumika}other{Vidakuzi # vinatumika}}</translation>
-<translation id="8463851957836045671">Tovuti inapakia haraka</translation>
<translation id="8487700953926739672">Kinapatikana nje ya mtandao</translation>
<translation id="851751545965956758">Zuia tovuti zisiunganishe kwenye vifaa</translation>
<translation id="8525306231823319788">Skrini nzima</translation>
<translation id="857943718398505171">Imeruhusiwa (inapendekezwa)</translation>
<translation id="8609465669617005112">Songa juu</translation>
+<translation id="861748745608658996">Jina kwenye skrini yako ya kwanza libadilishwe?</translation>
<translation id="8676374126336081632">Futa uingizaji wa maandishi</translation>
<translation id="868929229000858085">Tafuta kwenye anwani zako</translation>
<translation id="8702612070107455751">Data yoyote iliyo nje ya mtandao itafutwa.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Kuza karibu</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">Kipengele cha NFC kimezimwa kwenye kifaa hiki. Kiwashe katika <ph name="BEGIN_LINK" />Mipangilio ya Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Tovuti hii hufunguka na kufanya kazi haraka kwa watu wengi</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Ungependa kuondoka kwenye hali fiche?</translation>
<translation id="8958424370300090006">Zuia vidakuzi katika tovuti maalum.</translation>
<translation id="8959122750345127698">Kudurusu hakufikiki: <ph name="URL" /></translation>
<translation id="8986362086234534611">Sahau</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ta.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ta.xtb
index 8af07250f55..ab0420b739f 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ta.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ta.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ta">
<translation id="1006017844123154345">ஆனà¯à®²à¯ˆà®©à®¿à®²à¯ திற</translation>
<translation id="1044891598689252897">தளஙà¯à®•à®³à¯ இயலà¯à®ªà®¾à®•à®µà¯‡ செயலà¯à®ªà®Ÿà¯à®®à¯</translation>
+<translation id="1100504063505580045">தறà¯à®ªà¯‹à®¤à¯ˆà®¯ à®à®•à®¾à®©à¯</translation>
<translation id="1124090076051167250">இதைச௠செயà¯à®¤à®¾à®²à¯ தளஙà¯à®•à®³à¯‹ à®®à¯à®•à®ªà¯à®ªà¯à®¤à¯ திரையில௠உளà¯à®³ ஆபà¯à®¸à¯‹ சேமிதà¯à®¤à¯à®³à¯à®³ <ph name="DATASIZE" /> தரவà¯à®®à¯ கà¯à®•à¯à®•à¯€à®•à®³à¯à®®à¯ அழிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.</translation>
<translation id="1124772482545689468">பயனரà¯</translation>
<translation id="1178581264944972037">இடைநிறà¯à®¤à¯à®¤à¯</translation>
@@ -12,7 +13,7 @@
<translation id="1242008676835033345"><ph name="WEBSITE_URL" /> இல௠உடà¯à®ªà¯†à®¾à®¤à®¿à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="1272079795634619415">நிறà¯à®¤à¯à®¤à¯</translation>
<translation id="1289742167380433257">உஙà¯à®•à®³à¯ டேடà¯à®Ÿà®¾à®µà¯ˆà®šà¯ சேமிபà¯à®ªà®¤à®±à¯à®•à®¾à®•, இநà¯à®¤à®ªà¯ பகà¯à®•à®¤à¯à®¤à®¿à®©à¯ படஙà¯à®•à®³à¯ Googleளால௠சà¯à®°à¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®©.</translation>
-<translation id="129382876167171263">இணையதளஙà¯à®•à®³à¯ சேமிதà¯à®¤ கோபà¯à®ªà¯à®•à®³à¯ இஙà¯à®•à¯‡ தோனà¯à®±à¯à®®à¯</translation>
+<translation id="129382876167171263">இணையதளஙà¯à®•à®³à¯ சேமிதà¯à®¤ ஃபைலà¯à®•à®³à¯ இஙà¯à®•à¯‡ தோனà¯à®±à¯à®®à¯</translation>
<translation id="1317194122196776028">இநà¯à®¤à®¤à¯ தளதà¯à®¤à¯ˆ அகறà¯à®±à¯</translation>
<translation id="1364532808393826295"><ph name="APP_NAME" /> - <ph name="NOTIFICATION_MESSAGE" /></translation>
<translation id="1369915414381695676"><ph name="SITE_NAME" /> தளம௠சேரà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
@@ -88,12 +89,15 @@
<translation id="3227137524299004712">மைகà¯à®°à¯‡à®¾à®ƒà®ªà¯‡à®¾à®©à¯</translation>
<translation id="3277252321222022663">தளஙà¯à®•à®³à¯ செனà¯à®šà®¾à®°à¯à®•à®³à¯ˆ அணà¯à®• அனà¯à®®à®¤à®¿à®•à¯à®•à¯à®®à¯ (பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯)</translation>
<translation id="3295602654194328831">தகவலை மறை</translation>
+<translation id="3317660236277031814">நீஙà¯à®•à®³à¯ நிறà¯à®µà®¿à®¯ இணைய ஆபà¯à®¸à®¿à®©à¯ à®à®•à®¾à®©à¯ மாறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯.</translation>
<translation id="3328801116991980348">தளம௠கà¯à®±à®¿à®¤à¯à®¤ தகவலà¯</translation>
<translation id="3333961966071413176">எலà¯à®²à®¾à®¤à¯ தொடரà¯à®ªà¯à®•à®³à¯à®®à¯</translation>
<translation id="3386292677130313581">எனத௠இரà¯à®ªà¯à®ªà®¿à®Ÿà®¤à¯à®¤à¯ˆ அறிய தளஙà¯à®•à®³à¯ˆ அனà¯à®®à®¤à®¿à®•à¯à®•à¯à®®à¯ à®®à¯à®©à¯ கேள௠(பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯)</translation>
+<translation id="345699454248713913">நீஙà¯à®•à®³à¯ நிறà¯à®µà®¿à®¯à¯à®³à¯à®³ இணைய ஆபà¯à®¸à®¿à®©à¯ பெயர௠மாறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯.</translation>
<translation id="3538390592868664640">தளஙà¯à®•à®³à¯, எனà¯à®©à¯ˆà®šà¯ சà¯à®±à¯à®±à®¿à®¯à¯à®³à¯à®³ இடஙà¯à®•à®³à®¿à®©à¯ 3D மேபà¯à®ªà¯ˆ உரà¯à®µà®¾à®•à¯à®•à¯à®µà®¤à¯ˆà®¯à¯à®®à¯ கேமரா நிலையை டிராக௠செயà¯à®µà®¤à¯ˆà®¯à¯à®®à¯ தடà¯</translation>
+<translation id="3551268116566418498">மறைநிலையில௠இரà¯à®¨à¯à®¤à¯ வெளியேறவா?</translation>
<translation id="3586500876634962664">கேமரா &amp; மைகà¯à®°à¯‹à®ƒà®ªà¯‹à®©à¯ பயனà¯à®ªà®¾à®Ÿà¯</translation>
-<translation id="358794129225322306">பல கோபà¯à®ªà¯à®•à®³à¯ˆà®¤à¯ தானாகப௠பதிவிறகà¯à®• தளதà¯à®¤à¯ˆ அனà¯à®®à®¤à®¿à®•à¯à®•à¯à®®à¯.</translation>
+<translation id="358794129225322306">பல ஃபைலà¯à®•à®³à¯ˆà®¤à¯ தானாகப௠பதிவிறகà¯à®• தளதà¯à®¤à¯ˆ அனà¯à®®à®¤à®¿à®•à¯à®•à¯à®®à¯.</translation>
<translation id="3594780231884063836">வீடியோவின௠ஒலியை à®®à¯à®Ÿà®•à¯à®•à¯</translation>
<translation id="3596414637720633074">மறைநிலை à®…à®®à¯à®šà®¤à¯à®¤à®¿à®²à¯ மூனà¯à®±à®¾à®®à¯ தரபà¯à®ªà¯ கà¯à®•à¯à®•à¯€à®•à®³à¯ˆà®¤à¯ தடà¯à®•à¯à®•à¯à®®à¯</translation>
<translation id="3600792891314830896">ஒலியை இயகà¯à®•à¯à®®à¯ தளஙà¯à®•à®³à®¿à®²à¯ ஒலியடகà¯à®•à¯</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">இரà¯à®ªà¯à®ªà®¿à®Ÿ அமைபà¯à®ªà¯à®•à®³à¯ˆà®¤à¯ திறகà¯à®•à¯à®®à¯</translation>
<translation id="4226663524361240545">அறிவிபà¯à®ªà¯à®•à®³à¯ வரà¯à®®à¯ போத௠சாதனம௠அதிரà¯à®µà¯à®±à®•à¯à®•à¯‚டà¯à®®à¯</translation>
<translation id="4259722352634471385">செலà¯à®µà®¤à¯ தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯: <ph name="URL" /></translation>
+<translation id="4277239631747669329">நீஙà¯à®•à®³à¯ நிறà¯à®µà®¿à®¯à¯à®³à¯à®³ இணைய ஆபà¯à®¸à®¿à®©à¯ பெயரà¯à®®à¯ à®à®•à®¾à®©à¯à®®à¯ மாறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯.</translation>
<translation id="4278390842282768270">அனà¯à®®à®¤à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="429312253194641664">ஒர௠தளம௠மீடியாவை இயகà¯à®•à¯à®•à®¿à®±à®¤à¯</translation>
<translation id="42981349822642051">விரி</translation>
<translation id="4336434711095810371">அனைதà¯à®¤à¯à®¤à¯ தரவையà¯à®®à¯ அழி</translation>
<translation id="4402755511846832236">இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ நீஙà¯à®•à®³à¯ செயலில௠இரà¯à®ªà¯à®ªà®¤à¯ கà¯à®±à®¿à®¤à¯à®¤à¯à®¤à¯ தளஙà¯à®•à®³à¯ அறிநà¯à®¤à¯à®•à¯Šà®³à¯à®µà®¤à¯ˆà®¤à¯ தடà¯à®•à¯à®•à¯à®®à¯</translation>
-<translation id="4433925000917964731">Google வழஙà¯à®•à¯à®®à¯ Lite பகà¯à®•à®®à¯</translation>
<translation id="4434045419905280838">பாபà¯-அபà¯à®•à®³à¯ &amp; திசைதிரà¯à®ªà¯à®ªà¯à®¤à®²à¯à®•à®³à¯</translation>
<translation id="445467742685312942">பாதà¯à®•à®¾à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ உளà¯à®³à®Ÿà®•à¯à®•à®¤à¯à®¤à¯ˆ இயகà¯à®•à¯à®µà®¤à®±à¯à®•à¯à®¤à¯ தளஙà¯à®•à®³à¯ˆ அனà¯à®®à®¤à®¿à®•à¯à®•à¯à®®à¯</translation>
<translation id="4468959413250150279">கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà¯à®Ÿ தளதà¯à®¤à®¿à®±à¯à®•à¯ ஒலியடகà¯à®•à¯</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">உஙà¯à®•à®³à¯ பெறà¯à®±à¯‹à®°à®¾à®²à¯ நிரà¯à®µà®•à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯</translation>
<translation id="4670064810192446073">விரà¯à®šà¯à®šà¯à®µà®²à¯ ரியாலிடà¯à®Ÿà®¿</translation>
<translation id="4708011789095599544">இநà¯à®¤ இணையதளதà¯à®¤à®¿à®±à¯à®•à®¾à®© கà¯à®•à¯à®•à¯€à®•à®³à¯ˆà®¯à¯à®®à¯ பிற தளதà¯à®¤à®¿à®©à¯ தரவையà¯à®®à¯ அழிகà¯à®• விரà¯à®®à¯à®ªà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à®¾?</translation>
+<translation id="473775607612524610">பà¯à®¤à¯à®ªà¯à®ªà®¿</translation>
<translation id="4751476147751820511">நகரà¯à®µà¯ அலà¯à®²à®¤à¯ ஒளி உணரà¯à®µà®¿à®•à®³à¯</translation>
<translation id="4836046166855586901">இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ நீஙà¯à®•à®³à¯ செயலில௠இரà¯à®ªà¯à®ªà®¤à¯ கà¯à®±à®¿à®¤à¯à®¤à¯ ஒர௠தளம௠அறிநà¯à®¤à¯à®•à¯Šà®³à¯à®³ விரà¯à®®à¯à®ªà¯à®®à¯à®ªà¯‹à®¤à¯ அனà¯à®®à®¤à®¿ கேடà¯à®•à¯à®®à¯</translation>
<translation id="4883854917563148705">நிரà¯à®µà®•à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ அமைபà¯à®ªà¯à®•à®³à¯ˆ மீடà¯à®Ÿà®®à¯ˆà®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">இதனà¯à®µà®´à®¿à®¯à®¾à®• பகிரà¯</translation>
<translation id="5039804452771397117">அனà¯à®®à®¤à®¿</translation>
<translation id="5048398596102334565">மோஷன௠செனà¯à®šà®¾à®°à¯à®•à®³à¯ˆ அணà¯à®• தளஙà¯à®•à®³à¯ˆ அனà¯à®®à®¤à®¿à®•à¯à®•à¯à®®à¯ (பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯)</translation>
+<translation id="5050380848339752099">இநà¯à®¤à®¤à¯ தளம௠மறைநிலைப௠பயனà¯à®®à¯à®±à¯ˆà®¯à®¿à®²à¯ இலà¯à®²à®¾à®¤ ஆபà¯à®¸à¯à®Ÿà®©à¯ தகவலà¯à®•à®³à¯ˆà®ªà¯ பகிரவிரà¯à®•à¯à®•à®¿à®±à®¤à¯.</translation>
<translation id="5063480226653192405">பயனà¯à®ªà®¾à®Ÿà¯</translation>
<translation id="5100237604440890931">சà¯à®°à¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ - விரிவாகà¯à®•, கிளிக௠செயà¯à®¯à®µà¯à®®à¯.</translation>
<translation id="5123685120097942451">மறைநிலைத௠தாவலà¯</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">JavaScript஠இயகà¯à®•à¯à®µà®¤à®±à¯à®•à¯, தளஙà¯à®•à®³à¯ˆ அனà¯à®®à®¤à®¿ (பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯)</translation>
<translation id="534295439873310000">NFC சாதனஙà¯à®•à®³à¯</translation>
<translation id="5354152178998424783">இதைச௠செயà¯à®¤à®¾à®²à¯ தளஙà¯à®•à®³à¯ சேமிதà¯à®¤à¯à®³à¯à®³ <ph name="DATASIZE" /> தரவà¯à®®à¯ கà¯à®•à¯à®•à¯€à®•à®³à¯à®®à¯ அழிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.</translation>
-<translation id="5384883051496921101">இநà¯à®¤à®¤à¯ தளமானத௠மறைநிலைகà¯à®•à¯ வெளியே உளà¯à®³ பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯à®Ÿà®©à¯ தகவலைப௠பகிரவிரà¯à®•à¯à®•à®¿à®±à®¤à¯.</translation>
+<translation id="536508626067510330">à®®à¯à®•à®ªà¯à®ªà¯à®¤à¯ திரையில௠உளà¯à®³ à®à®•à®¾à®©à¯ˆ மாறà¯à®±à®µà®¾?</translation>
<translation id="5391532827096253100">இநà¯à®¤à®¤à¯ தளதà¯à®¤à®¿à®±à¯à®•à®¾à®© இணைபà¯à®ªà¯ பாதà¯à®•à®¾à®ªà¯à®ªà®¾à®©à®¤à®²à¯à®². தளத௠தகவலà¯</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(மேலà¯à®®à¯ 1)}other{(மேலà¯à®®à¯ #)}}</translation>
<translation id="5403592356182871684">பெயரà¯à®•à®³à¯</translation>
<translation id="5489227211564503167">à®®à¯à®Ÿà®¿à®¨à¯à®¤ நேரமà¯: <ph name="ELAPSED_TIME" />/<ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">கà¯à®±à¯à®•à¯à®•à®¿à®Ÿà¯à®®à¯ அலà¯à®²à®¤à¯ தவறாக வழிநடதà¯à®¤à¯à®®à¯ விளமà¯à®ªà®°à®™à¯à®•à®³à¯ˆà®•à¯ காடà¯à®Ÿà¯à®®à¯ தளஙà¯à®•à®³à®¿à®²à¯ விளமà¯à®ªà®°à®™à¯à®•à®³à¯ˆà®¤à¯ தடà¯</translation>
+<translation id="549957179819296104">பà¯à®¤à®¿à®¯ à®à®•à®¾à®©à¯</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" />கà¯à®•à®¾à®© அனà¯à®®à®¤à®¿ வழஙà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯, <ph name="PERMISSION_2" />கà¯à®•à®¾à®© அனà¯à®®à®¤à®¿ தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="5505264765875738116">அறிவிபà¯à®ªà¯à®•à®³à¯ˆ அனà¯à®ªà¯à®ªà¯à®µà®¤à®±à¯à®•à®¾à®© அனà¯à®®à®¤à®¿à®¯à¯ˆà®¤à¯ தளஙà¯à®•à®³à®¾à®²à¯ கோர இயலாதà¯</translation>
<translation id="5516455585884385570">அறிவிபà¯à®ªà¯ அமைபà¯à®ªà¯à®•à®³à¯ˆà®¤à¯ திறகà¯à®•à¯à®®à¯</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">அனà¯à®®à®¤à®¿à®•à®³à¯</translation>
<translation id="5860033963881614850">ஆஃபà¯</translation>
<translation id="5876056640971328065">வீடியோவை இடைநிறà¯à®¤à¯à®¤à¯</translation>
+<translation id="5904826301761575486">à®®à¯à®•à®ªà¯à®ªà¯à®¤à¯ திரையில௠உளà¯à®³ பெயரையà¯à®®à¯ à®à®•à®¾à®©à¯ˆà®¯à¯à®®à¯ மாறà¯à®± வேணà¯à®Ÿà¯à®®à®¾?</translation>
<translation id="5916664084637901428">இயகà¯à®•à¯</translation>
<translation id="5922853908706496913">உஙà¯à®•à®³à¯ திரையைப௠பகிரà¯à®•à®¿à®±à®¤à¯</translation>
<translation id="5939518447894949180">மீடà¯à®Ÿà®®à¯ˆ</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">மூனà¯à®±à®¾à®®à¯ தரபà¯à®ªà¯à®•à¯ கà¯à®•à¯à®•à¯€à®•à®³à¯ˆà®¤à¯ தடà¯</translation>
<translation id="6206551242102657620">பாதà¯à®•à®¾à®ªà¯à®ªà®¾à®© இணைபà¯à®ªà¯. தளத௠தகவலà¯</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> விரà¯à®ªà¯à®ªà®¤à¯à®¤à¯‡à®°à¯à®µà¯à®•à®³à¯</translation>
+<translation id="6260852843601447737">ஆபà¯à®¸à¯ˆ மூடி தவறான பயனà¯à®ªà®¾à®Ÿà¯ கà¯à®±à®¿à®¤à¯à®¤à¯ பà¯à®•à®¾à®°à®³à®¿</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /> ஆகியவறà¯à®±à¯à®•à¯à®•à®¾à®© அனà¯à®®à®¤à®¿à®•à®³à¯ தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®©</translation>
<translation id="6270391203985052864">அறிவிபà¯à®ªà¯à®•à®³à¯ˆ அனà¯à®ªà¯à®ªà¯à®µà®¤à®±à¯à®•à®¾à®© அனà¯à®®à®¤à®¿à®¯à¯ˆà®¤à¯ தளஙà¯à®•à®³à®¾à®²à¯ கோர à®®à¯à®Ÿà®¿à®¯à¯à®®à¯</translation>
<translation id="6295158916970320988">எலà¯à®²à®¾ தளஙà¯à®•à®³à¯à®®à¯</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> ஆபà¯à®¸à¯ உஙà¯à®•à®³à¯ இரà¯à®ªà¯à®ªà®¿à®Ÿà®¤à¯ தகவலை அணà¯à®• அனà¯à®®à®¤à®¿à®ªà¯à®ªà®¤à®±à¯à®•à¯ <ph name="BEGIN_LINK" />Android அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯à®®à¯<ph name="END_LINK" /> இரà¯à®ªà¯à®ªà®¿à®Ÿà®¤à¯à®¤à®¿à®±à¯à®•à®¾à®© அனà¯à®®à®¤à®¿à®¯à¯ˆ இயகà¯à®•à®µà¯à®®à¯.</translation>
<translation id="8447861592752582886">சாதன அனà¯à®®à®¤à®¿à®¯à¯ˆ ரதà¯à®¤à¯à®šà¯†à®¯à¯à®¯à¯à®®à¯</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 கà¯à®•à¯à®•à¯€ உபயோகதà¯à®¤à®¿à®²à¯ உளà¯à®³à®¤à¯}other{# கà¯à®•à¯à®•à¯€à®•à®³à¯ உபயோகதà¯à®¤à®¿à®²à¯ உளà¯à®³à®©}}</translation>
-<translation id="8463851957836045671">தளம௠வேகமாக இரà¯à®•à¯à®•à®¿à®±à®¤à¯</translation>
<translation id="8487700953926739672">ஆஃபà¯à®²à¯ˆà®©à®¿à®²à¯ இரà¯à®•à¯à®•à®¿à®±à®¤à¯</translation>
<translation id="851751545965956758">சாதனஙà¯à®•à®³à¯ˆ இணைபà¯à®ªà®¤à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ தளஙà¯à®•à®³à¯ˆà®¤à¯ தடà¯à®•à¯à®•à¯à®®à¯</translation>
<translation id="8525306231823319788">à®®à¯à®´à¯à®¤à¯à®¤à®¿à®°à¯ˆ</translation>
<translation id="857943718398505171">அனà¯à®®à®¤à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ (பரிநà¯à®¤à¯à®°à¯ˆà®¤à¯à®¤à®¤à¯)</translation>
<translation id="8609465669617005112">மேலே நகரà¯à®¤à¯à®¤à¯</translation>
+<translation id="861748745608658996">à®®à¯à®•à®ªà¯à®ªà¯à®¤à¯ திரையில௠காடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®®à¯ பெயரை மாறà¯à®±à®µà®¾?</translation>
<translation id="8676374126336081632">உளà¯à®³à¯€à®Ÿà¯à®Ÿà¯ˆ அழி</translation>
<translation id="868929229000858085">உஙà¯à®•à®³à¯ தொடரà¯à®ªà¯à®•à®³à®¿à®²à¯ தேடà¯à®•</translation>
<translation id="8702612070107455751">அனைதà¯à®¤à¯ ஆஃபà¯à®²à¯ˆà®©à¯ தரவà¯à®®à¯ அழிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">பெரிதாகà¯à®•à¯</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ NFC ஆஃப௠செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. அதை <ph name="BEGIN_LINK" />Android அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯<ph name="END_LINK" /> ஆன௠செயà¯à®¯à®µà¯à®®à¯.</translation>
-<translation id="8929372349074745002">பெரà¯à®®à¯à®ªà®¾à®²à®¾à®©à®µà®°à¯à®•à®³à¯à®•à¯à®•à¯ இநà¯à®¤à®¤à¯ தளம௠வேகமாகத௠திறகà¯à®•à®¿à®±à®¤à¯ &amp; செயலà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">மறைநிலையிலிரà¯à®¨à¯à®¤à¯ வெளியேறவா?</translation>
<translation id="8958424370300090006">கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà¯à®Ÿ தளதà¯à®¤à®¿à®±à¯à®•à®¾à®© கà¯à®•à¯à®•à¯€à®•à®³à¯ˆà®¤à¯ தடà¯à®•à¯à®•à¯à®®à¯.</translation>
<translation id="8959122750345127698">செலà¯à®² à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ: <ph name="URL" /></translation>
<translation id="8986362086234534611">மற</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb
index b9e4b95eb6c..8fe12a4f61f 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_te.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="te">
<translation id="1006017844123154345">ఆనà±â€Œà°²à±ˆà°¨à±â€Œà°²à±‹ తెరà±à°µà±</translation>
<translation id="1044891598689252897">సైటà±â€Œà°²à± సాధారణ రీతిలో పని చేసà±à°¤à°¾à°¯à°¿</translation>
+<translation id="1100504063505580045">à°ªà±à°°à°¸à±à°¤à±à°¤ à°šà°¿à°¹à±à°¨à°‚</translation>
<translation id="1124090076051167250">ఇది మీ హోమౠసà±à°•à±à°°à±€à°¨à±â€Œà°ªà±ˆ ఉనà±à°¨, సైటà±â€Œà°²à± లేదా యాపà±â€Œà°² à°¦à±à°µà°¾à°°à°¾ à°¸à±à°Ÿà±‹à°°à± చేయబడిన <ph name="DATASIZE" /> డేటా, à°•à±à°•à±à°•à±€à°²à°¨à± à°•à±à°²à°¿à°¯à°°à± చేసà±à°¤à±à°‚ది.</translation>
<translation id="1124772482545689468">వినియోగదారà±</translation>
<translation id="1178581264944972037">పాజౠచేయి</translation>
@@ -12,7 +13,7 @@
<translation id="1242008676835033345"><ph name="WEBSITE_URL" />లో పొందà±à°ªà°°à°šà°¬à°¡à°¿à°‚ది</translation>
<translation id="1272079795634619415">ఆపà±</translation>
<translation id="1289742167380433257">మీ కోసం డేటానౠసేవౠచేయడానికి, à°ˆ పేజీ ఇమేజà±â€Œà°²à± Google à°¦à±à°µà°¾à°°à°¾ ఆపà±à°Ÿà°¿à°®à±ˆà°œà± చేయబడà±à°¡à°¾à°¯à°¿.</translation>
-<translation id="129382876167171263">వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°²à± సేవౠచేసిన ఫైలà±â€Œà°²à± ఇకà±à°•à°¡ కనిపిసà±à°¤à°¾à°¯à°¿</translation>
+<translation id="129382876167171263">వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°²à± సేవౠచేసిన ఫైళà±à°²à± ఇకà±à°•à°¡ కనిపిసà±à°¤à°¾à°¯à°¿</translation>
<translation id="1317194122196776028">à°ˆ సైటà±â€Œà°¨à± విసà±à°®à°°à°¿à°‚à°šà±</translation>
<translation id="1364532808393826295"><ph name="APP_NAME" /> - <ph name="NOTIFICATION_MESSAGE" /></translation>
<translation id="1369915414381695676"><ph name="SITE_NAME" /> సైటౠజోడించబడింది</translation>
@@ -79,7 +80,7 @@
<translation id="2968755619301702150">à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ à°µà±à°¯à±‚యరà±</translation>
<translation id="300526633675317032">ఇది వెబà±â€Œà°¸à±ˆà°Ÿà± నిలà±à°µà°²à±‹à°¨à°¿ మొతà±à°¤à°‚ <ph name="SIZE_IN_KB" />నౠతీసివేసà±à°¤à±à°‚ది.</translation>
<translation id="3008272652534848354">à°…à°¨à±à°®à°¤à±à°²à°¨à± రీసెటౠచేయి</translation>
-<translation id="301521992641321250">à°¸à±à°µà°¯à°‚చాలకంగా à°¬à±à°²à°¾à°•à± చేయబడింది</translation>
+<translation id="301521992641321250">ఆటోమేటికà±â€Œà°—à°¾ à°¬à±à°²à°¾à°•à± చేయబడింది</translation>
<translation id="3114012059975132928">వీడియో à°ªà±à°²à±‡à°¯à°°à±</translation>
<translation id="3115898365077584848">సమాచారానà±à°¨à°¿ చూపà±</translation>
<translation id="3123473560110926937">కొనà±à°¨à°¿ సైటà±â€Œà°²à°²à±‹ à°¬à±à°²à°¾à°•à± చేయబడింది</translation>
@@ -88,12 +89,15 @@
<translation id="3227137524299004712">మైకà±à°°à±‹à°«à±‹à°¨à±</translation>
<translation id="3277252321222022663">సెనà±à°¸à°¾à°°à±â€Œà°²à°¨à± యాకà±à°¸à±†à°¸à± చేయడానికి సైటà±â€Œà°²à°¨à± à°…à°¨à±à°®à°¤à°¿à°¸à±à°¤à±à°‚ది (సిఫారà±à°¸à± చేసà±à°¤à±à°¨à±à°¨à°¾à°®à±)</translation>
<translation id="3295602654194328831">సమాచారానà±à°¨à°¿ దాచà±</translation>
+<translation id="3317660236277031814">మీరౠఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేసిన వెబౠయాపౠదాని à°šà°¿à°¹à±à°¨à°¾à°¨à±à°¨à°¿ మారà±à°šà±à°•à±à°‚ది.</translation>
<translation id="3328801116991980348">సైటౠసమాచారం</translation>
<translation id="3333961966071413176">మొతà±à°¤à°‚ పరిచయాలà±</translation>
<translation id="3386292677130313581">మీ à°¸à±à°¥à°¾à°¨à°¾à°¨à±à°¨à°¿ సైటà±â€Œà°²à± తెలà±à°¸à±à°•à±à°¨à±‡à°²à°¾ వాటిని à°…à°¨à±à°®à°¤à°¿à°‚చే à°®à±à°‚à°¦à±, మిమà±à°®à°²à±à°¨à°¿ à°…à°¡à±à°—à±à°¤à±à°‚ది (సిఫారà±à°¸à± చేయబడింది)</translation>
+<translation id="345699454248713913">మీరౠఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేసిన వెబౠయాపౠదాని పేరà±à°¨à± మారà±à°šà±à°•à±à°‚ది.</translation>
<translation id="3538390592868664640">మీ పరిసరాల 3D à°®à±à°¯à°¾à°ªà±â€Œà°¨à± సృషà±à°Ÿà°¿à°‚à°šà°•à±à°‚à°¡à°¾ లేదా కెమెరా పొజిషనà±â€Œà°¨à± à°Ÿà±à°°à°¾à°•à± చేయకà±à°‚à°¡à°¾ సైటà±â€Œà°²à°¨à± à°¬à±à°²à°¾à°•à± చేయండి</translation>
+<translation id="3551268116566418498">à°…à°œà±à°žà°¾à°¤ మోడà±â€Œà°¨à± నిషà±à°•à±à°°à°®à°¿à°‚చాలా?</translation>
<translation id="3586500876634962664">కెమెరా, మైకà±à°°à±‹à°«à±‹à°¨à±â€Œà°² ఉపయోగం</translation>
-<translation id="358794129225322306">పలౠఫైలà±â€Œà°²à°¨à± ఆటోమేటికà±â€Œà°—à°¾ డౌనà±â€Œà°²à±‹à°¡à± చేయడం కోసం సైటà±â€Œà°¨à°¿ à°…à°¨à±à°®à°¤à°¿à°‚à°šà°‚à°¡à°¿.</translation>
+<translation id="358794129225322306">పలౠఫైళà±à°²à°¨à± ఆటోమేటికà±â€Œà°—à°¾ డౌనà±â€Œà°²à±‹à°¡à± చేయడం కోసం సైటà±â€Œà°¨à°¿ à°…à°¨à±à°®à°¤à°¿à°‚à°šà°‚à°¡à°¿.</translation>
<translation id="3594780231884063836">వీడియోనౠమà±à°¯à±‚టౠచేయండి</translation>
<translation id="3596414637720633074">à°…à°œà±à°žà°¾à°¤à°‚లో థరà±à°¡à±-పారà±à°Ÿà±€ à°•à±à°•à±à°•à±€à°²à°¨à± à°¬à±à°²à°¾à°•à± చేయి</translation>
<translation id="3600792891314830896">à°§à±à°µà°¨à°¿à°¨à°¿ à°ªà±à°²à±‡ చేసే సైటà±â€Œà°²à°¨à± à°®à±à°¯à±‚టౠచేసà±à°¤à±à°‚ది</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">లొకేషనౠసెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°¨à± తెరవండి</translation>
<translation id="4226663524361240545">నోటిఫికేషనà±â€Œà°²à± పరికరానà±à°¨à°¿ వైబà±à°°à±‡à°Ÿà± చేయవచà±à°šà±</translation>
<translation id="4259722352634471385">నావిగేషనౠబà±à°²à°¾à°•à± చేయబడింది: <ph name="URL" /></translation>
+<translation id="4277239631747669329">మీరౠఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేసిన వెబౠయాపౠదాని పేరà±, à°šà°¿à°¹à±à°¨à°¾à°¨à±à°¨à°¿ మారà±à°šà±à°•à±à°‚ది.</translation>
<translation id="4278390842282768270">à°…à°¨à±à°®à°¤à°¿à°‚చబడింది</translation>
<translation id="429312253194641664">à°’à°• సైటà±â€Œà°²à±‹ మీడియా à°ªà±à°²à±‡ చేయబడà±à°¤à±‹à°‚ది</translation>
<translation id="42981349822642051">విసà±à°¤à°°à°¿à°‚à°šà±</translation>
<translation id="4336434711095810371">మొతà±à°¤à°‚ డేటానౠకà±à°²à°¿à°¯à°°à± చేయి</translation>
<translation id="4402755511846832236">మీరౠఈ పరికరానà±à°¨à°¿ యాకà±à°Ÿà°¿à°µà±â€Œà°—à°¾ ఉపయోగిసà±à°¤à±à°¨à±à°¨à°ªà±à°ªà±à°¡à± à°† విషయానà±à°¨à°¿ ఇతర సైటà±â€Œà°²à± తెలà±à°¸à±à°•à±‹à°•à±à°‚à°¡à°¾ à°¬à±à°²à°¾à°•à± చేయండి</translation>
-<translation id="4433925000917964731">Google అందించిన లైటౠపేజీ</translation>
<translation id="4434045419905280838">పాపà±-à°…à°ªà±â€Œà°²à± మరియౠమళà±à°²à°¿à°‚à°ªà±à°²à±</translation>
<translation id="445467742685312942">à°°à°•à±à°·à°¿à°¤ కంటెంటà±â€Œà°¨à± à°ªà±à°²à±‡ చేయడానికి సైటà±â€Œà°²à°¨à± à°…à°¨à±à°®à°¤à°¿à°¸à±à°¤à±à°‚ది</translation>
<translation id="4468959413250150279">నిరà±à°¦à°¿à°·à±à°Ÿ సైటౠకోసం à°§à±à°µà°¨à°¿à°¨à°¿ à°®à±à°¯à±‚టౠచేయండి.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">మీ తలà±à°²à°¿/తండà±à°°à°¿ à°¦à±à°µà°¾à°°à°¾ నిరà±à°µà°¹à°¿à°‚చబడà±à°¤à±‹à°‚ది</translation>
<translation id="4670064810192446073">వరà±à°šà±à°µà°²à± రియాలిటీ</translation>
<translation id="4708011789095599544">మీరౠఖచà±à°šà°¿à°¤à°‚à°—à°¾ à°ˆ వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°•à± సంబంధించిన à°•à±à°•à±à°•à±€à°²à± అలాగే ఇతర సైటౠడేటానౠకà±à°²à°¿à°¯à°°à± చేయాలనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à°¾?</translation>
+<translation id="473775607612524610">à°…à°ªà±â€Œà°¡à±‡à°Ÿà±â€Œ</translation>
<translation id="4751476147751820511">కదలిక లేదా కాంతి సెనà±à°¸à°¾à°°à±â€Œà°²à±</translation>
<translation id="4836046166855586901">మీరౠఈ పరికరానà±à°¨à°¿ యాకà±à°Ÿà°¿à°µà±â€Œà°—à°¾ ఉపయోగిసà±à°¤à±à°¨à±à°¨à°ªà±à°ªà±à°¡à± à°† విషయానà±à°¨à°¿ సైటౠతెలà±à°¸à±à°•à±‹à°µà°¾à°²à°‚టే సైటౠమీ à°…à°¨à±à°®à°¤à°¿à°¨à°¿ అడగాలి</translation>
<translation id="4883854917563148705">నిరà±à°µà°¹à°¿à°¤ సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à± రీసెటౠచేయబడవà±</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">దీని à°¦à±à°µà°¾à°°à°¾ భాగసà±à°µà°¾à°®à±à°¯à°‚ చే.</translation>
<translation id="5039804452771397117">à°…à°¨à±à°®à°¤à°¿à°‚à°šà±</translation>
<translation id="5048398596102334565">మోషనౠసెనà±à°¸à°¾à°°à±â€Œà°²à°¨à± యాకà±à°¸à±†à°¸à± చేయడానికి సైటà±â€Œà°²à°¨à± à°…à°¨à±à°®à°¤à°¿à°‚à°šà°‚à°¡à°¿ (సిఫారà±à°¸à± చేసà±à°¤à±à°¨à±à°¨à°¾à°®à±)</translation>
+<translation id="5050380848339752099">à°ˆ సైటౠఅజà±à°žà°¾à°¤ మోడౠవెలà±à°ªà°² ఉనà±à°¨ à°’à°• యాపà±â€Œà°¤à±‹ సమాచారానà±à°¨à°¿ షేరౠచేయబోతోంది.</translation>
<translation id="5063480226653192405">నిలà±à°µ వినియోగం</translation>
<translation id="5100237604440890931">à°•à±à°¦à°¿à°‚చబడింది - విసà±à°¤à°°à°¿à°‚పజేయడానికి à°•à±à°²à°¿à°•à± చేయండి.</translation>
<translation id="5123685120097942451">à°…à°œà±à°žà°¾à°¤ à°Ÿà±à°¯à°¾à°¬à±</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">సైటà±â€Œà°²à°¨à± జావాసà±à°•à±à°°à°¿à°ªà±à°Ÿà± అమలౠచేయడానికి à°…à°¨à±à°®à°¤à°¿à°¸à±à°¤à±à°‚ది (సిఫారà±à°¸à± చేయబడింది)</translation>
<translation id="534295439873310000">NFC పరికరాలà±</translation>
<translation id="5354152178998424783">ఇది సైటà±â€Œà°² à°¦à±à°µà°¾à°°à°¾ à°¸à±à°Ÿà±‹à°°à± చేయబడిన <ph name="DATASIZE" /> డేటానà±, à°•à±à°•à±à°•à±€à°²à°¨à± à°•à±à°²à°¿à°¯à°°à± చేసà±à°¤à±à°‚ది.</translation>
-<translation id="5384883051496921101">à°ˆ సైటౠఅజà±à°žà°¾à°¤ మోడౠవెలà±à°ªà°² ఉనà±à°¨ à°’à°• యాపà±â€Œà°¤à±‹ సమాచారానà±à°¨à°¿ షేరౠచేయబోతోంది.</translation>
+<translation id="536508626067510330">మీ హోమà±â€Œà°¸à±à°•à±à°°à±€à°¨à±â€Œà°²à±‹ à°šà°¿à°¹à±à°¨à°¾à°¨à±à°¨à°¿ à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేయాలా?</translation>
<translation id="5391532827096253100">à°ˆ సైటà±â€Œà°•à°¿ మీ కనెకà±à°·à°¨à± à°¸à±à°°à°•à±à°·à°¿à°¤à°‚à°—à°¾ లేదà±. సైటౠసమాచారం</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ మరో 1)}other{(+ మరో #)}}</translation>
<translation id="5403592356182871684">పేరà±à°²à±</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" />లో <ph name="ELAPSED_TIME" /> సమయం గడిచిపోయింది.</translation>
<translation id="5494752089476963479">à°…à°¨à±à°šà°¿à°¤à°®à±ˆà°¨ లేదా తపà±à°ªà±à°¦à°¾à°°à°¿ పటà±à°Ÿà°¿à°‚చే à°ªà±à°°à°•à°Ÿà°¨à°²à°¨à± చూపించే సైటà±â€Œà°²à°²à±‹ à°ªà±à°°à°•à°Ÿà°¨à°²à°¨à± à°¬à±à°²à°¾à°•à± చేసà±à°¤à±à°‚ది</translation>
+<translation id="549957179819296104">కొతà±à°¤ à°šà°¿à°¹à±à°¨à°‚</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> à°…à°¨à±à°®à°¤à°¿à°‚చబడింది, <ph name="PERMISSION_2" /> à°¬à±à°²à°¾à°•à± చేయబడింది</translation>
<translation id="5505264765875738116">నోటిఫికేషనà±â€Œà°²à°¨à± పంపడానికి సైటà±â€Œà°²à± à°…à°¡à°—à°µà±</translation>
<translation id="5516455585884385570">నోటిఫికేషనౠసెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°¨à± తెరà±à°µà±</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">à°…à°¨à±à°®à°¤à±à°²à±</translation>
<translation id="5860033963881614850">ఆఫౠఅయà±à°¯à°¿à°‚ది</translation>
<translation id="5876056640971328065">వీడియోనౠపాజౠచేయి</translation>
+<translation id="5904826301761575486">మీ హోమà±â€Œà°¸à±à°•à±à°°à±€à°¨à±â€Œà°²à±‹ పేరà±, à°šà°¿à°¹à±à°¨à°¾à°¨à±à°¨à°¿ à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేయాలా?</translation>
<translation id="5916664084637901428">ఆనౠచేయి</translation>
<translation id="5922853908706496913">మీ à°¸à±à°•à±à°°à±€à°¨à±â€Œà°¨à± షేరౠచేయడం</translation>
<translation id="5939518447894949180">రీసెటౠచేయి</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">థరà±à°¡à± పారà±à°Ÿà±€ à°•à±à°•à±à°•à±€à°²à°¨à± à°¬à±à°²à°¾à°•à± చేయండి</translation>
<translation id="6206551242102657620">కనెకà±à°·à°¨à± à°¸à±à°°à°•à±à°·à°¿à°¤à°‚. సైటౠసమాచారం</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> ఎంపికలà±</translation>
+<translation id="6260852843601447737">మూసివేసి, à°¦à±à°°à±à°µà°¿à°¨à°¿à°¯à±‹à°—ానà±à°¨à°¿ రిపోరà±à°Ÿà± చేయి</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /> à°¬à±à°²à°¾à°•à± చేయబడà±à°¡à°¾à°¯à°¿</translation>
<translation id="6270391203985052864">నోటిఫికేషనà±â€Œà°²à°¨à± పంపడానికి సైటà±â€Œà°²à± à°…à°¡à±à°—గలవà±</translation>
<translation id="6295158916970320988">à°…à°¨à±à°¨à°¿ సైటà±â€Œà°²à±</translation>
@@ -203,7 +212,7 @@
<translation id="6527303717912515753">భాగసà±à°µà°¾à°®à±à°¯à°‚ చేయి</translation>
<translation id="6545864417968258051">à°¬à±à°²à±‚టూతౠసà±à°•à°¾à°¨à°¿à°‚à°—à±</translation>
<translation id="6552800053856095716">{PERMISSIONS_SUMMARY_BLOCKED,plural, =1{<ph name="PERMISSION_1" />, <ph name="PERMISSION_2" />, ఇంకా మరో <ph name="NUM_MORE" /> à°¬à±à°²à°¾à°•à± చేయబడà±à°¡à°¾à°¯à°¿}other{<ph name="PERMISSION_1" />, <ph name="PERMISSION_2" />, ఇంకా మరో <ph name="NUM_MORE" /> à°¬à±à°²à°¾à°•à± చేయబడà±à°¡à°¾à°¯à°¿}}</translation>
-<translation id="6561560012278703671">నిశà±à°¶à°¬à±à°¦ సందేశాలనౠఉపయోగించండి (మీకౠఅంతరాయం కలిగించకà±à°‚à°¡à°¾ నోటిఫికేషనౠపà±à°°à°¾à°‚à°ªà±à°Ÿà±â€Œà°²à°¨à± à°¬à±à°²à°¾à°•à± చేసà±à°¤à±à°‚ది)</translation>
+<translation id="6561560012278703671">నిశà±à°¶à°¬à±à°¦ మెసేజà±â€Œà°²à°¨à± ఉపయోగించండి (మీకౠఅంతరాయం కలిగించకà±à°‚à°¡à°¾ నోటిఫికేషనౠపà±à°°à°¾à°‚à°ªà±à°Ÿà±â€Œà°²à°¨à± à°¬à±à°²à°¾à°•à± చేసà±à°¤à±à°‚ది)</translation>
<translation id="6608650720463149374"><ph name="GIGABYTES" /> GB</translation>
<translation id="6612358246767739896">à°°à°•à±à°·à°¿à°¤ కంటెంటà±</translation>
<translation id="662080504995468778">ఇందà±à°²à±‹à°¨à±‡ ఉంచà±</translation>
@@ -235,7 +244,7 @@
<translation id="7260727271532453612"><ph name="PERMISSION_1" />, <ph name="PERMISSION_2" /> à°…à°¨à±à°®à°¤à°¿à°‚చబడà±à°¡à°¾à°¯à°¿</translation>
<translation id="7302486331832100261">మీరౠసాధారణంగా నోటిఫికేషనà±â€Œà°²à°¨à± à°¬à±à°²à°¾à°•à± చేసà±à°¤à±à°‚టారà±. à°…à°¨à±à°®à°¤à°¿à°‚చడానికి, 'వివరాలà±'నౠనొకà±à°•à°‚à°¡à°¿.</translation>
<translation id="7423098979219808738">à°®à±à°‚à°¦à±à°—à°¾ à°…à°¡à±à°—à±à°¤à±à°‚ది</translation>
-<translation id="7423538860840206698">à°•à±à°²à°¿à°ªà±â€Œà°¬à±‹à°°à±à°¡à±â€Œà°¨à°¿ చదవకà±à°‚à°¡à°¾ à°¬à±à°²à°¾à°•à± చేసారà±</translation>
+<translation id="7423538860840206698">à°•à±à°²à°¿à°ªà±â€Œà°¬à±‹à°°à±à°¡à±â€Œà°¨à°¿ చదవకà±à°‚à°¡à°¾ à°¬à±à°²à°¾à°•à± చేశారà±</translation>
<translation id="7521387064766892559">JavaScript</translation>
<translation id="7554752735887601236">à°’à°• సైటౠమీ మైకà±à°°à±‹à°«à±‹à°¨à±â€Œà°¨à± ఉపయోగిసà±à°¤à±‹à°‚ది</translation>
<translation id="7561196759112975576">à°Žà°²à±à°²à°ªà±à°ªà±à°¡à±‚</translation>
@@ -249,7 +258,7 @@
<translation id="780301667611848630">వదà±à°¦à± , ధనà±à°¯à°µà°¾à°¦à°¾à°²à±</translation>
<translation id="7804248752222191302">à°’à°• సైటౠమీ కెమెరానౠఉపయోగిసà±à°¤à±‹à°‚ది</translation>
<translation id="7817023149356982970">మీరౠఈ సైటౠనà±à°‚à°¡à°¿ సైనౠఅవà±à°Ÿà± చేయబడతారà±.</translation>
-<translation id="7828557259026017104">మీరౠసందరà±à°¶à°¿à°‚చే వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°²à± రూపొందించిన ఫైలà±â€Œà°²à°¨à± à°•à±à°•à±à°•à±€à°²à± అంటారà±. మీ à°ªà±à°°à°¾à°§à°¾à°¨à±à°¯à°¤à°²à°¨à± à°—à±à°°à±à°¤à±à°‚à°šà±à°•à±‹à°µà°¡à°¾à°¨à°¿à°•à°¿ సైటà±â€Œà°²à± వాటిని ఉపయోగిసà±à°¤à°¾à°¯à°¿. ఇతర సైటà±â€Œà°²à± రూపొందించిన à°•à±à°•à±à°•à±€à°²à°¨à± థరà±à°¡à±-పారà±à°Ÿà±€ à°•à±à°•à±à°•à±€à°²à± అంటారà±. మీరౠసందరà±à°¶à°¿à°‚చే వెబౠపేజీలో మీరౠచూసే యాడà±â€Œà°²à± లేదా ఇమేజà±â€Œà°² లాంటి, కొంత కంటెంటà±â€Œà°¨à± à°ˆ సైటà±â€Œà°²à± à°¸à±à°µà°‚తంగా కలిగి ఉంటాయి.</translation>
+<translation id="7828557259026017104">మీరౠసందరà±à°¶à°¿à°‚చే వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°²à± రూపొందించిన ఫైళà±à°²à°¨à± à°•à±à°•à±à°•à±€à°²à± అంటారà±. మీ à°ªà±à°°à°¾à°§à°¾à°¨à±à°¯à°¤à°²à°¨à± à°—à±à°°à±à°¤à±à°‚à°šà±à°•à±‹à°µà°¡à°¾à°¨à°¿à°•à°¿ సైటà±â€Œà°²à± వాటిని ఉపయోగిసà±à°¤à°¾à°¯à°¿. ఇతర సైటà±â€Œà°²à± రూపొందించిన à°•à±à°•à±à°•à±€à°²à°¨à± థరà±à°¡à±-పారà±à°Ÿà±€ à°•à±à°•à±à°•à±€à°²à± అంటారà±. మీరౠసందరà±à°¶à°¿à°‚చే వెబౠపేజీలో మీరౠచూసే యాడà±â€Œà°²à± లేదా ఇమేజà±â€Œà°² లాంటి, కొంత కంటెంటà±â€Œà°¨à± à°ˆ సైటà±â€Œà°²à± à°¸à±à°µà°‚తంగా కలిగి ఉంటాయి.</translation>
<translation id="7835852323729233924">మీడియా à°ªà±à°²à±‡ à°…à°µà±à°¤à±‹à°‚ది</translation>
<translation id="783819812427904514">వీడియోనౠఅనà±â€Œà°®à±à°¯à±‚టౠచేయండి</translation>
<translation id="7846076177841592234">ఎంపికనౠరదà±à°¦à± చేయి</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">మీ లొకేషనà±â€Œà°¨à°¿ యాకà±à°¸à±†à°¸à± చేయడానికి <ph name="APP_NAME" />ని à°…à°¨à±à°®à°¤à°¿à°‚చడానికి, <ph name="BEGIN_LINK" />Android సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²<ph name="END_LINK" />లో కూడా లొకేషనà±â€Œà°¨à°¿ ఆనౠచేయండి.</translation>
<translation id="8447861592752582886">పరికర à°…à°¨à±à°®à°¤à°¿à°¨à°¿ ఉపసంహరిసà±à°¤à±à°‚ది</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 à°•à±à°•à±à°•à±€ ఉపయోగంలో ఉంది}other{# à°•à±à°•à±à°•à±€à°²à± ఉపయోగంలో ఉనà±à°¨à°¾à°¯à°¿}}</translation>
-<translation id="8463851957836045671">సైటౠవేగంగా లోడౠఅవà±à°¤à±à°‚ది</translation>
<translation id="8487700953926739672">ఆఫà±â€Œà°²à±ˆà°¨à±â€Œà°²à±‹ à°…à°‚à°¦à±à°¬à°¾à°Ÿà±</translation>
<translation id="851751545965956758">పరికరాలకౠకనెకà±à°Ÿà± కాకà±à°‚à°¡à°¾ సైటà±â€Œà°²à°¨à± à°¬à±à°²à°¾à°•à± చేసà±à°¤à±à°‚ది</translation>
<translation id="8525306231823319788">పూరà±à°¤à°¿ à°¸à±à°•à±à°°à±€à°¨à±</translation>
<translation id="857943718398505171">à°…à°¨à±à°®à°¤à°¿à°‚చబడింది (సిఫారà±à°¸à± చేయబడింది)</translation>
<translation id="8609465669617005112">పైకి తరలించà±</translation>
+<translation id="861748745608658996">మీ హోమà±â€Œà°¸à±à°•à±à°°à±€à°¨à±â€Œà°²à±‹ పేరà±à°¨à± à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేయాలా?</translation>
<translation id="8676374126336081632">ఇనà±â€Œà°ªà±à°Ÿà±â€Œà°¨à± తీసివేయండి</translation>
<translation id="868929229000858085">మీ పరిచయాలనౠవెతకండి</translation>
<translation id="8702612070107455751">à°à°¦à±ˆà°¨à°¾ ఆఫà±â€Œà°²à±ˆà°¨à± డేటా ఉంటే తీసివేయబడà±à°¤à±à°‚ది.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">దగà±à°—à°°à°¿à°•à°¿ జూమౠచేయి</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">à°ˆ పరికరంలో NFC ఆఫౠచేయబడింది. <ph name="BEGIN_LINK" />Android సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²<ph name="END_LINK" />లో దానà±à°¨à°¿ ఆనౠచేయండి.</translation>
-<translation id="8929372349074745002">చాలా మందికి à°ˆ సైటౠవేగంగా తెరà±à°šà±à°•à±à°‚à°Ÿà±à°‚ది, అలాగే వేగంగా à°¸à±à°ªà°‚దిసà±à°¤à±à°‚ది</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">à°…à°œà±à°žà°¾à°¤ మోడౠనà±à°‚à°¡à°¿ నిషà±à°•à±à°°à°®à°¿à°‚చాలా?</translation>
<translation id="8958424370300090006">à°à°¦à±ˆà°¨à°¾ à°’à°• నిరà±à°¦à°¿à°·à±à°Ÿ సైటà±â€Œà°²à±‹ à°•à±à°•à±à°•à±€à°²à°¨à± à°¬à±à°²à°¾à°•à± చేయండి.</translation>
<translation id="8959122750345127698">దీనికి నావిగేటౠచేయడం సాధà±à°¯à°ªà°¡à°¦à±: <ph name="URL" /></translation>
<translation id="8986362086234534611">మరిచిపోయారా</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_th.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_th.xtb
index f3866f427de..1bc750c2247 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_th.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_th.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="th">
<translation id="1006017844123154345">เปิดà¹à¸šà¸šà¸­à¸­à¸™à¹„ลน์</translation>
<translation id="1044891598689252897">เว็บไซต์จะทำงานตามปà¸à¸•à¸´</translation>
+<translation id="1100504063505580045">ไอคอนปัจจุบัน</translation>
<translation id="1124090076051167250">à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸™à¸µà¹‰à¸ˆà¸°à¸¥à¹‰à¸²à¸‡à¸‚้อมูลà¹à¸¥à¸°à¸„ุà¸à¸à¸µà¹‰à¸—ี่เว็บไซต์ต่างๆ หรือà¹à¸­à¸›à¹ƒà¸™à¸«à¸™à¹‰à¸²à¸ˆà¸­à¸«à¸¥à¸±à¸à¸ˆà¸±à¸”เà¸à¹‡à¸šà¹„ว้รวมทั้งสิ้น <ph name="DATASIZE" /></translation>
<translation id="1124772482545689468">ผู้ใช้</translation>
<translation id="1178581264944972037">หยุดชั่วคราว</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">ไมโครโฟน</translation>
<translation id="3277252321222022663">อนุà¸à¸²à¸•à¹ƒà¸«à¹‰à¹€à¸§à¹‡à¸šà¹„ซต์เข้าถึงเซ็นเซอร์ (à¹à¸™à¸°à¸™à¸³)</translation>
<translation id="3295602654194328831">ซ่อนข้อมูล</translation>
+<translation id="3317660236277031814">เว็บà¹à¸­à¸›à¸—ี่คุณติดตั้งไว้มีà¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹„อคอน</translation>
<translation id="3328801116991980348">ข้อมูลไซต์</translation>
<translation id="3333961966071413176">รายชื่อติดต่อทั้งหมด</translation>
<translation id="3386292677130313581">ถามà¸à¹ˆà¸­à¸™à¸­à¸™à¸¸à¸à¸²à¸•à¹ƒà¸«à¹‰à¹€à¸§à¹‡à¸šà¹„ซต์ทราบตำà¹à¸«à¸™à¹ˆà¸‡à¸‚องคุณ (à¹à¸™à¸°à¸™à¸³)</translation>
+<translation id="345699454248713913">เว็บà¹à¸­à¸›à¸—ี่คุณติดตั้งไว้มีà¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸Šà¸·à¹ˆà¸­</translation>
<translation id="3538390592868664640">บล็อà¸à¹„ม่ให้เว็บไซต์สร้างà¹à¸œà¸™à¸—ี่ 3 มิติของสิ่งที่อยู่รอบตัวคุณหรือติดตามตำà¹à¸«à¸™à¹ˆà¸‡à¸‚องà¸à¸¥à¹‰à¸­à¸‡</translation>
+<translation id="3551268116566418498">ออà¸à¸ˆà¸²à¸à¹‚หมดไม่ระบุตัวตนไหม</translation>
<translation id="3586500876634962664">à¸à¸²à¸£à¹ƒà¸Šà¹‰à¸à¸¥à¹‰à¸­à¸‡à¹à¸¥à¸°à¹„มโครโฟน</translation>
<translation id="358794129225322306">อนุà¸à¸²à¸•à¹ƒà¸«à¹‰à¹€à¸§à¹‡à¸šà¹„ซต์ดาวน์โหลดไฟล์หลายไฟล์โดยอัตโนมัติ</translation>
<translation id="3594780231884063836">ปิดเสียงวิดีโอ</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">เปิดà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าตำà¹à¸«à¸™à¹ˆà¸‡</translation>
<translation id="4226663524361240545">à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•à¸·à¸­à¸™à¸­à¸²à¸ˆà¸—ำให้อุปà¸à¸£à¸“์สั่น</translation>
<translation id="4259722352634471385">มีà¸à¸²à¸£à¸šà¸¥à¹‡à¸­à¸à¸à¸²à¸£à¸™à¸³à¸—าง: <ph name="URL" /></translation>
+<translation id="4277239631747669329">เว็บà¹à¸­à¸›à¸—ี่คุณติดตั้งไว้มีà¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸Šà¸·à¹ˆà¸­à¹à¸¥à¸°à¹„อคอน</translation>
<translation id="4278390842282768270">อนุà¸à¸²à¸•à¹à¸¥à¹‰à¸§</translation>
<translation id="429312253194641664">เว็บไซต์à¸à¸³à¸¥à¸±à¸‡à¹€à¸¥à¹ˆà¸™à¸ªà¸·à¹ˆà¸­</translation>
<translation id="42981349822642051">ขยาย</translation>
<translation id="4336434711095810371">ล้างข้อมูลทั้งหมด</translation>
<translation id="4402755511846832236">บล็อà¸à¹€à¸§à¹‡à¸šà¹„ซต์ไม่ให้ทราบเวลาที่คุณใช้งานอุปà¸à¸£à¸“์นี้อยู่</translation>
-<translation id="4433925000917964731">หน้าเวอร์ชัน Lite ให้บริà¸à¸²à¸£à¹‚ดย Google</translation>
<translation id="4434045419905280838">ป๊อปอัปà¹à¸¥à¸°à¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹€à¸ªà¹‰à¸™à¸—าง</translation>
<translation id="445467742685312942">อนุà¸à¸²à¸•à¹ƒà¸«à¹‰à¹€à¸§à¹‡à¸šà¹„ซต์เล่นเนื้อหาที่ได้รับความคุ้มครอง</translation>
<translation id="4468959413250150279">ปิดเสียงไซต์ที่ต้องà¸à¸²à¸£</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">มีà¸à¸²à¸£à¸ˆà¸±à¸”à¸à¸²à¸£à¹‚ดยผู้ปà¸à¸„รอง</translation>
<translation id="4670064810192446073">Virtual Reality</translation>
<translation id="4708011789095599544">คุณà¹à¸™à¹ˆà¹ƒà¸ˆà¹„หมว่าต้องà¸à¸²à¸£à¸¥à¹‰à¸²à¸‡à¸„ุà¸à¸à¸µà¹‰à¹à¸¥à¸°à¸‚้อมูลเว็บไซต์อื่นๆ สำหรับเว็บไซต์นี้</translation>
+<translation id="473775607612524610">อัปเดต</translation>
<translation id="4751476147751820511">เซ็นเซอร์จับความเคลื่อนไหวหรือเซ็นเซอร์à¹à¸ªà¸‡</translation>
<translation id="4836046166855586901">ถามเมื่อเว็บไซต์ต้องà¸à¸²à¸£à¸—ราบเวลาที่คุณใช้งานอุปà¸à¸£à¸“์นี้อยู่</translation>
<translation id="4883854917563148705">รีเซ็ตà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าที่มีà¸à¸²à¸£à¸ˆà¸±à¸”à¸à¸²à¸£à¹„ม่ได้</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">à¹à¸Šà¸£à¹Œà¸œà¹ˆà¸²à¸™</translation>
<translation id="5039804452771397117">อนุà¸à¸²à¸•</translation>
<translation id="5048398596102334565">อนุà¸à¸²à¸•à¹ƒà¸«à¹‰à¹€à¸§à¹‡à¸šà¹„ซต์เข้าถึงเซ็นเซอร์ตรวจจับความเคลื่อนไหว (à¹à¸™à¸°à¸™à¸³)</translation>
+<translation id="5050380848339752099">เว็บไซต์นี้à¸à¸³à¸¥à¸±à¸‡à¸ˆà¸°à¹à¸Šà¸£à¹Œà¸‚้อมูลà¸à¸±à¸šà¹à¸­à¸›à¸™à¸­à¸à¹‚หมดไม่ระบุตัวตน</translation>
<translation id="5063480226653192405">à¸à¸²à¸£à¹ƒà¸Šà¹‰</translation>
<translation id="5100237604440890931">ยุบ - คลิà¸à¹€à¸žà¸·à¹ˆà¸­à¸‚ยาย</translation>
<translation id="5123685120097942451">à¹à¸—็บที่ไม่ระบุตัวตน</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">อนุà¸à¸²à¸•à¹ƒà¸«à¹‰à¹€à¸§à¹‡à¸šà¹„ซต์เรียà¸à¹ƒà¸Šà¹‰ JavaScript (à¹à¸™à¸°à¸™à¸³)</translation>
<translation id="534295439873310000">อุปà¸à¸£à¸“์ NFC</translation>
<translation id="5354152178998424783">à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸™à¸µà¹‰à¸ˆà¸°à¸¥à¹‰à¸²à¸‡à¸‚้อมูลà¹à¸¥à¸°à¸„ุà¸à¸à¸µà¹‰à¸—ี่เว็บไซต์ต่างๆ จัดเà¸à¹‡à¸šà¹„ว้รวมทั้งสิ้น <ph name="DATASIZE" /></translation>
-<translation id="5384883051496921101">ไซต์นี้à¸à¸³à¸¥à¸±à¸‡à¸ˆà¸°à¹à¸Šà¸£à¹Œà¸‚้อมูลà¸à¸±à¸šà¹à¸­à¸›à¸™à¸­à¸à¹‚หมดไม่ระบุตัวตน</translation>
+<translation id="536508626067510330">อัปเดตไอคอนในหน้าจอหลัà¸à¹„หม</translation>
<translation id="5391532827096253100">à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸à¸±à¸šà¹€à¸§à¹‡à¸šà¹„ซต์นี้ไม่ปลอดภัย ข้อมูลเว็บไซต์</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(อีภ1 รายà¸à¸²à¸£)}other{(อีภ# รายà¸à¸²à¸£)}}</translation>
<translation id="5403592356182871684">ชื่อ</translation>
<translation id="5489227211564503167">เวลาผ่านไป <ph name="ELAPSED_TIME" /> จาภ<ph name="TOTAL_TIME" /></translation>
<translation id="5494752089476963479">บล็อà¸à¹‚ฆษณาในเว็บไซต์ที่à¹à¸ªà¸”งโฆษณาที่à¹à¸—รà¸à¸«à¸£à¸·à¸­à¸—ำให้เข้าใจผิด</translation>
+<translation id="549957179819296104">ไอคอนใหม่</translation>
<translation id="5502860503640766021">อนุà¸à¸²à¸•à¹ƒà¸«à¹‰à¹€à¸‚้าถึง<ph name="PERMISSION_1" /> บล็อà¸<ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">เว็บไซต์ขออนุà¸à¸²à¸•à¹€à¸žà¸·à¹ˆà¸­à¸ªà¹ˆà¸‡à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•à¸·à¸­à¸™à¹„ม่ได้</translation>
<translation id="5516455585884385570">เปิดà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•à¸·à¸­à¸™</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">à¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•</translation>
<translation id="5860033963881614850">ปิด</translation>
<translation id="5876056640971328065">หยุดวิดีโอชั่วคราว</translation>
+<translation id="5904826301761575486">อัปเดตชื่อà¹à¸¥à¸°à¹„อคอนในหน้าจอหลัà¸à¹„หม</translation>
<translation id="5916664084637901428">เปิด</translation>
<translation id="5922853908706496913">à¸à¸³à¸¥à¸±à¸‡à¹à¸Šà¸£à¹Œà¸«à¸™à¹‰à¸²à¸ˆà¸­</translation>
<translation id="5939518447894949180">รีเซ็ต</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">บล็อà¸à¸„ุà¸à¸à¸µà¹‰à¸‚องบุคคลที่สาม</translation>
<translation id="6206551242102657620">à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸›à¸¥à¸­à¸”ภัย ข้อมูลเว็บไซต์</translation>
<translation id="6216432067784365534">ตัวเลือà¸à¸ªà¸³à¸«à¸£à¸±à¸š<ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">ปิดà¹à¸¥à¸°à¸£à¸²à¸¢à¸‡à¸²à¸™à¸à¸²à¸£à¸¥à¸°à¹€à¸¡à¸´à¸”</translation>
<translation id="6262279340360821358">บล็อà¸<ph name="PERMISSION_1" />à¹à¸¥à¸°<ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">เว็บไซต์ขออนุà¸à¸²à¸•à¹€à¸žà¸·à¹ˆà¸­à¸ªà¹ˆà¸‡à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•à¸·à¸­à¸™à¹„ด้</translation>
<translation id="6295158916970320988">เว็บไซต์ทั้งหมด</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">หาà¸à¸•à¹‰à¸­à¸‡à¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•à¹ƒà¸«à¹‰ <ph name="APP_NAME" /> เข้าถึงตำà¹à¸«à¸™à¹ˆà¸‡à¸‚องคุณ ให้เปิดตำà¹à¸«à¸™à¹ˆà¸‡à¹ƒà¸™<ph name="BEGIN_LINK" />à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Android<ph name="END_LINK" /> ด้วย</translation>
<translation id="8447861592752582886">เพิà¸à¸–อนสิทธิ์ของอุปà¸à¸£à¸“์</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{ใช้คุà¸à¸à¸µà¹‰à¸­à¸¢à¸¹à¹ˆ 1 รายà¸à¸²à¸£}other{ใช้คุà¸à¸à¸µà¹‰à¸­à¸¢à¸¹à¹ˆ # รายà¸à¸²à¸£}}</translation>
-<translation id="8463851957836045671">เว็บไซต์โหลดเร็ว</translation>
<translation id="8487700953926739672">ใช้งานà¹à¸šà¸šà¸­à¸­à¸Ÿà¹„ลน์ได้</translation>
<translation id="851751545965956758">บล็อà¸à¹€à¸§à¹‡à¸šà¹„ซต์ไม่ให้เชื่อมต่อà¸à¸±à¸šà¸­à¸¸à¸›à¸à¸£à¸“์</translation>
<translation id="8525306231823319788">เต็มหน้าจอ</translation>
<translation id="857943718398505171">อนุà¸à¸²à¸•à¹à¸¥à¹‰à¸§ (à¹à¸™à¸°à¸™à¸³)</translation>
<translation id="8609465669617005112">เลื่อนขึ้น</translation>
+<translation id="861748745608658996">อัปเดตชื่อในหน้าจอหลัà¸à¹„หม</translation>
<translation id="8676374126336081632">ล้างข้อมูลที่ป้อน</translation>
<translation id="868929229000858085">ค้นหารายชื่อติดต่อ</translation>
<translation id="8702612070107455751">ระบบจะล้างข้อมูลออฟไลน์ทั้งหมด</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">ขยาย</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC ในอุปà¸à¸£à¸“์นี้ปิดอยู่ เปิดได้ใน<ph name="BEGIN_LINK" />à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Android<ph name="END_LINK" /></translation>
-<translation id="8929372349074745002">เว็บไซต์นี้เปิดà¹à¸¥à¸°à¸•à¸­à¸šà¸ªà¸™à¸­à¸‡à¸­à¸¢à¹ˆà¸²à¸‡à¸£à¸§à¸”เร็วสำหรับผู้คนส่วนใหà¸à¹ˆ</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">ออà¸à¸ˆà¸²à¸à¹‚หมดไม่ระบุตัวตนไหม</translation>
<translation id="8958424370300090006">บล็อà¸à¸„ุà¸à¸à¸µà¹‰à¸‚องเว็บไซต์ที่เจาะจง</translation>
<translation id="8959122750345127698">ไม่สามารถเข้าถึงà¸à¸²à¸£à¸™à¸³à¸—างได้: <ph name="URL" /></translation>
<translation id="8986362086234534611">เลิà¸à¸ˆà¸³</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_tr.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_tr.xtb
index ddb19301701..5be00cfbda1 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_tr.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_tr.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="tr">
<translation id="1006017844123154345">İnternet'te aç</translation>
<translation id="1044891598689252897">Siteler normal şekilde çalışır</translation>
+<translation id="1100504063505580045">Mevcut simge</translation>
<translation id="1124090076051167250">Bu işlem, Ana ekranınızdaki siteler veya uygulamalar tarafından depolanan <ph name="DATASIZE" /> boyutunda veriyi ve çerezi temizleyecek.</translation>
<translation id="1124772482545689468">Kullanıcı</translation>
<translation id="1178581264944972037">Duraklat</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Sitelerin sensörlere erişmesine izin ver (önerilen)</translation>
<translation id="3295602654194328831">Bilgileri Gizle</translation>
+<translation id="3317660236277031814">Yüklediğiniz bir web uygulaması, simgesini değiştirdi.</translation>
<translation id="3328801116991980348">Site bilgileri</translation>
<translation id="3333961966071413176">Tüm kişiler</translation>
<translation id="3386292677130313581">Sitelerin, konumunuzu öğrenmesine izin verilmeden önce size sorulsun (önerilir)</translation>
+<translation id="345699454248713913">Yüklediğiniz bir web uygulaması, adını değiştirdi.</translation>
<translation id="3538390592868664640">Sitelerin çevremin 3D haritasını oluşturmasını veya kamera konumunu takip etmesini engelle</translation>
+<translation id="3551268116566418498">Gizli moddan çıkılsın mı?</translation>
<translation id="3586500876634962664">Kamera ve mikrofon kullanımı</translation>
<translation id="358794129225322306">Bir sitenin otomatik olarak birden fazla dosya indirmesine izin verir.</translation>
<translation id="3594780231884063836">Videonun sesini kapat</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Konum Ayarlarını açın</translation>
<translation id="4226663524361240545">Bildirimler cihazı titretebilir</translation>
<translation id="4259722352634471385">Gezinme engellendi: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Yüklediğiniz bir web uygulaması, adını ve simgesini değiştirdi.</translation>
<translation id="4278390842282768270">Ä°zin veriliyor</translation>
<translation id="429312253194641664">Bir site medya oynatıyor</translation>
<translation id="42981349822642051">GeniÅŸlet</translation>
<translation id="4336434711095810371">Tüm verileri temizle</translation>
<translation id="4402755511846832236">Bu cihazı etkin olarak kullandığınızda sitelerin bunu bilmesi engellenir</translation>
-<translation id="4433925000917964731">Google tarafından sağlanan basit sayfa</translation>
<translation id="4434045419905280838">Pop-up'lar ve yönlendirmeler</translation>
<translation id="445467742685312942">Sitelerin korumalı içeriği oynatmasına izin ver</translation>
<translation id="4468959413250150279">Belirli bir site için sesi kapatın.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Ebeveyniniz tarafından yönetiliyor</translation>
<translation id="4670064810192446073">Sanal gerçeklik</translation>
<translation id="4708011789095599544">Bu web sitesi için çerezleri ve diğer site verilerini temizlemek istediğinizden emin misiniz?</translation>
+<translation id="473775607612524610">Güncelle</translation>
<translation id="4751476147751820511">Hareket veya ışık sensörleri</translation>
<translation id="4836046166855586901">Bir site bu cihazı etkin olarak kullandığımı bilmek istediğinde sor</translation>
<translation id="4883854917563148705">Yönetilen ayarlar sıfırlanamaz</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Paylaşım yöntemi:</translation>
<translation id="5039804452771397117">Ä°zin ver</translation>
<translation id="5048398596102334565">Sitelerin hareket sensörlerine erişmesine izin ver (önerilen)</translation>
+<translation id="5050380848339752099">Bu site, Gizli mod dışında bir uygulama ile bilgi paylaşımında bulunmak üzere.</translation>
<translation id="5063480226653192405">Kullanım</translation>
<translation id="5100237604440890931">Daraltıldı - Genişletmek için tıklayın.</translation>
<translation id="5123685120097942451">Gizli sekme</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Sitelerin JavaScript çalıştırmasına izin ver (önerilir)</translation>
<translation id="534295439873310000">NFC cihazları</translation>
<translation id="5354152178998424783">Bu işlem, siteler tarafından depolanan <ph name="DATASIZE" /> boyutunda veriyi ve çerezi temizler.</translation>
-<translation id="5384883051496921101">Bu site, gizli mod dışında bir uygulama ile bilgi paylaşımında bulunmak üzere.</translation>
+<translation id="536508626067510330">Ana ekranınızdaki simge güncellensin mi?</translation>
<translation id="5391532827096253100">Bu siteye bağlantınız güvenli değil. Site bilgileri</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 tane daha)}other{(+ # tane daha)}}</translation>
<translation id="5403592356182871684">Adlar</translation>
<translation id="5489227211564503167">Geçen süre: <ph name="ELAPSED_TIME" />/<ph name="TOTAL_TIME" /></translation>
<translation id="5494752089476963479">Araya giren veya yanıltıcı reklamlar gösteren sitelerde reklamları engelle</translation>
+<translation id="549957179819296104">Yeni simge</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> için izin verildi, <ph name="PERMISSION_2" /> engellendi</translation>
<translation id="5505264765875738116">Siteler bildirim göndermek isteyemez</translation>
<translation id="5516455585884385570">Bildirim ayarlarını aç</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Ä°zinler</translation>
<translation id="5860033963881614850">Kapalı</translation>
<translation id="5876056640971328065">Videoyu duraklat</translation>
+<translation id="5904826301761575486">Ana ekranınızdaki ad ve simge güncellensin mi?</translation>
<translation id="5916664084637901428">Açık</translation>
<translation id="5922853908706496913">Ekranınız paylaşılıyor</translation>
<translation id="5939518447894949180">Sıfırla</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Üçüncü taraf çerezlerini engelle</translation>
<translation id="6206551242102657620">Bağlantı güvenli. Site bilgileri</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> Seçenekleri</translation>
+<translation id="6260852843601447737">Kapatıp kötüye kullanımı bildirin</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> ve <ph name="PERMISSION_2" /> engellendi</translation>
<translation id="6270391203985052864">Siteler bildirim gönderme izni isteyebilir</translation>
<translation id="6295158916970320988">Tüm siteler</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> uygulamasının konumunuza erişebilmesi için <ph name="BEGIN_LINK" />Android Ayarları<ph name="END_LINK" />'nda da konumu açın.</translation>
<translation id="8447861592752582886">Cihaz iznini iptal et</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 çerez kullanımda}other{# çerez kullanımda}}</translation>
-<translation id="8463851957836045671">Site hızlı yükleniyor</translation>
<translation id="8487700953926739672">Çevrimdışı kullanılabilir</translation>
<translation id="851751545965956758">Sitelerin cihazlara bağlanmasını engelle</translation>
<translation id="8525306231823319788">Tam ekran</translation>
<translation id="857943718398505171">İzin verildi (önerilir)</translation>
<translation id="8609465669617005112">Yukarı taşı</translation>
+<translation id="861748745608658996">Ana ekranınızdaki ad güncellensin mi?</translation>
<translation id="8676374126336081632">GiriÅŸi temizle</translation>
<translation id="868929229000858085">Kişilerinizde arama yapın</translation>
<translation id="8702612070107455751">Tüm çevrimdışı veriler temizlenecek.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Yakınlaştır</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC bu cihazda kapalı. Bu özelliği <ph name="BEGIN_LINK" />Android Ayarları<ph name="END_LINK" />'nda açın.</translation>
-<translation id="8929372349074745002">Bu site, çoğu kullanıcı için hızlı açılıp yanıt veriyor</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Gizli moddan çıkılsın mı?</translation>
<translation id="8958424370300090006">Belirli bir site için çerezleri engelleyin.</translation>
<translation id="8959122750345127698">Gezinme işlevine ulaşılamıyor: <ph name="URL" /></translation>
<translation id="8986362086234534611">Unut</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_uk.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_uk.xtb
index f118d3e9653..25293631aca 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_uk.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_uk.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="uk">
<translation id="1006017844123154345">Відкрити в режимі онлайн</translation>
<translation id="1044891598689252897">Сайти працюватимуть у звичному режимі</translation>
+<translation id="1100504063505580045">Поточний значок</translation>
<translation id="1124090076051167250">Буде видалено <ph name="DATASIZE" /> даних Ñ– файлів cookie Ñайтів або додатків на головному екрані.</translation>
<translation id="1124772482545689468">КориÑтувач</translation>
<translation id="1178581264944972037">Пауза</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Мікрофон</translation>
<translation id="3277252321222022663">Ðадати Ñайтам доÑтуп до датчиків (рекомендовано)</translation>
<translation id="3295602654194328831">Сховати інформацію</translation>
+<translation id="3317660236277031814">У веб-додатка, Ñкий ви вÑтановили, змінивÑÑ Ð·Ð½Ð°Ñ‡Ð¾Ðº.</translation>
<translation id="3328801116991980348">Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñайт</translation>
<translation id="3333961966071413176">УÑÑ– контакти</translation>
<translation id="3386292677130313581">Запитувати, перш ніж дозволити Ñайтам визначати ваше міÑÑ†ÐµÐ·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ (рекомендуєтьÑÑ)</translation>
+<translation id="345699454248713913">У веб-додатка, Ñкий ви вÑтановили, змінилаÑÑ Ð½Ð°Ð·Ð²Ð°.</translation>
<translation id="3538390592868664640">Заборонити Ñайтам Ñтворювати 3D-карту вашого Ð¾Ñ‚Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð°Ð±Ð¾ відÑтежувати Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð½Ñ ÐºÐ°Ð¼ÐµÑ€Ð¸</translation>
+<translation id="3551268116566418498">Вимкнути анонімний режим?</translation>
<translation id="3586500876634962664">ВикориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ°Ð¼ÐµÑ€Ð¸ й мікрофона</translation>
<translation id="358794129225322306">Дозволити Ñайту автоматично завантажувати декілька файлів.</translation>
<translation id="3594780231884063836">Вимкнути звук у відео</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Відкрити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупу до моїх геоданих</translation>
<translation id="4226663524361240545">Коли надходитимуть ÑповіщеннÑ, приÑтрій може вібрувати</translation>
<translation id="4259722352634471385">Веб-Ñторінку <ph name="URL" /> заблоковано</translation>
+<translation id="4277239631747669329">У веб-додатка, Ñкий ви вÑтановили, змінилиÑÑ Ð½Ð°Ð·Ð²Ð° й значок.</translation>
<translation id="4278390842282768270">Дозволено</translation>
<translation id="429312253194641664">Сайт відтворює медіа-вміÑÑ‚</translation>
<translation id="42981349822642051">Розгорнути</translation>
<translation id="4336434711095810371">Видалити вÑÑ– дані</translation>
<translation id="4402755511846832236">Блокувати Ñайтам інформацію про те, чи ви активно викориÑтовуєте цей приÑтрій</translation>
-<translation id="4433925000917964731">Спрощену Ñторінку надає Google</translation>
<translation id="4434045419905280838">Спливаючі вікна й переадреÑаціÑ</translation>
<translation id="445467742685312942">Дозволити Ñайтам відтворювати захищений вміÑÑ‚</translation>
<translation id="4468959413250150279">Вимкнути звук Ð´Ð»Ñ Ð¿ÐµÐ²Ð½Ð¾Ð³Ð¾ Ñайту.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">КеруєтьÑÑ Ð¾Ð´Ð½Ð¸Ð¼ із батьків</translation>
<translation id="4670064810192446073">Віртуальна реальніÑÑ‚ÑŒ</translation>
<translation id="4708011789095599544">ОчиÑтити файли cookie й інші дані Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ веб-Ñайту?</translation>
+<translation id="473775607612524610">Оновити</translation>
<translation id="4751476147751820511">Датчики руху та Ñвітла</translation>
<translation id="4836046166855586901">Запитувати, коли Ñайт хоче дізнатиÑÑ, чи ви активно викориÑтовуєте цей приÑтрій</translation>
<translation id="4883854917563148705">ÐалаштуваннÑ, Ñкими керує адмініÑтратор, не можна Ñкинути</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">ÐадіÑлати</translation>
<translation id="5039804452771397117">Дозволити</translation>
<translation id="5048398596102334565">Ðадати Ñайтам доÑтуп до датчиків руху (рекомендовано)</translation>
+<translation id="5050380848339752099">Цей Ñайт збираєтьÑÑ Ð½Ð°Ð´Ñ–Ñлати інформацію зовнішньому додатку, поки ви в режимі анонімного переглÑду.</translation>
<translation id="5063480226653192405">ВикориÑтаннÑ</translation>
<translation id="5100237604440890931">Згорнуто – натиÑніть, щоб розгорнути.</translation>
<translation id="5123685120097942451">Ðнонімна вкладка</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Дозволити Ñайтам запуÑкати JavaScript (рекомендуєтьÑÑ)</translation>
<translation id="534295439873310000">ПриÑтрої NFC</translation>
<translation id="5354152178998424783">Буде видалено <ph name="DATASIZE" /> даних Ñ– файлів cookie Ñайтів.</translation>
-<translation id="5384883051496921101">Цей Ñайт збираєтьÑÑ Ð½Ð°Ð´Ñ–Ñлати інформацію в додаток, у Ñкому вимкнено режим анонімного переглÑду.</translation>
+<translation id="536508626067510330">Оновити значок на головному екрані?</translation>
<translation id="5391532827096253100">Ваше Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· цим Ñайтом незахищене. Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñайт</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ ще 1)}one{(+ ще #)}few{(+ ще #)}many{(+ ще #)}other{(+ ще #)}}</translation>
<translation id="5403592356182871684">Імена</translation>
<translation id="5489227211564503167">Минуло чаÑу: <ph name="ELAPSED_TIME" /> з <ph name="TOTAL_TIME" /></translation>
<translation id="5494752089476963479">Блокувати рекламу на Ñайтах, Ñкі показують нав’Ñзливі чи оманливі оголошеннÑ</translation>
+<translation id="549957179819296104">Ðовий значок</translation>
<translation id="5502860503640766021">Дозволено: "<ph name="PERMISSION_1" />". Заблоковано: "<ph name="PERMISSION_2" />".</translation>
<translation id="5505264765875738116">Сайти не можуть проÑити дозвіл надÑилати ÑповіщеннÑ</translation>
<translation id="5516455585884385570">Відкрити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñповіщень</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Дозволи</translation>
<translation id="5860033963881614850">Вимк.</translation>
<translation id="5876056640971328065">Призупинити відео</translation>
+<translation id="5904826301761575486">Оновити назву й значок на головному екрані?</translation>
<translation id="5916664084637901428">Увімкнено</translation>
<translation id="5922853908706496913">ДоÑтуп до вашого екрана</translation>
<translation id="5939518447894949180">Скинути</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Блокувати Ñторонні файли cookie</translation>
<translation id="6206551242102657620">Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÑ‡Ð½Ðµ. Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñайт</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" />: опції</translation>
+<translation id="6260852843601447737">Закрити й повідомити про порушеннÑ</translation>
<translation id="6262279340360821358">Заблоковано: "<ph name="PERMISSION_1" />" і "<ph name="PERMISSION_2" />"</translation>
<translation id="6270391203985052864">Сайти можуть проÑити дозвіл надÑилати ÑповіщеннÑ</translation>
<translation id="6295158916970320988">УÑÑ– Ñайти</translation>
@@ -205,7 +214,7 @@
<translation id="6552800053856095716">{PERMISSIONS_SUMMARY_BLOCKED,plural, =1{Заблоковано: "<ph name="PERMISSION_1" />", "<ph name="PERMISSION_2" />" і ще <ph name="NUM_MORE" />}one{Заблоковано: "<ph name="PERMISSION_1" />", "<ph name="PERMISSION_2" />" і ще <ph name="NUM_MORE" />}few{Заблоковано: "<ph name="PERMISSION_1" />", "<ph name="PERMISSION_2" />" і ще <ph name="NUM_MORE" />}many{Заблоковано: "<ph name="PERMISSION_1" />", "<ph name="PERMISSION_2" />" і ще <ph name="NUM_MORE" />}other{Заблоковано: "<ph name="PERMISSION_1" />", "<ph name="PERMISSION_2" />" і ще <ph name="NUM_MORE" />}}</translation>
<translation id="6561560012278703671">Показувати лише значок Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ (блокувати ÑповіщеннÑ)</translation>
<translation id="6608650720463149374"><ph name="GIGABYTES" /> ГБ</translation>
-<translation id="6612358246767739896">Захищений вміÑÑ‚</translation>
+<translation id="6612358246767739896">Захищений контент</translation>
<translation id="662080504995468778">ЗалишитиÑÑ</translation>
<translation id="6643016212128521049">ОчиÑтити</translation>
<translation id="6689172468748959065">Фотографії профілів</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Щоб надати додатку <ph name="APP_NAME" /> доÑтуп до геоданих, також увімкніть Ñ—Ñ… у <ph name="BEGIN_LINK" />налаштуваннÑÑ… Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">СкаÑувати доÑтуп до приÑтрою</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{ВикориÑтовуєтьÑÑ 1 файл cookie}one{ВикориÑтовуєтьÑÑ # файл cookie}few{ВикориÑтовуютьÑÑ # файли cookie}many{ВикориÑтовуютьÑÑ # файлів cookie}other{ВикориÑтовуютьÑÑ # файлу cookie}}</translation>
-<translation id="8463851957836045671">Сайт працює швидко</translation>
<translation id="8487700953926739672">ДоÑтуп у режимі офлайн</translation>
<translation id="851751545965956758">Заборонити Ñайтам підключатиÑÑ Ð´Ð¾ приÑтроїв</translation>
<translation id="8525306231823319788">Ðа веÑÑŒ екран</translation>
<translation id="857943718398505171">Дозволено (рекомендуєтьÑÑ)</translation>
<translation id="8609465669617005112">Угору</translation>
+<translation id="861748745608658996">Оновити назву на головному екрані?</translation>
<translation id="8676374126336081632">Видалити введений текÑÑ‚</translation>
<translation id="868929229000858085">Пошук у контактах</translation>
<translation id="8702612070107455751">УÑÑ– дані, збережені офлайн, буде видалено.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Збільшити маÑштаб</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC вимкнено на цьому приÑтрої. Увімкніть цю функцію в <ph name="BEGIN_LINK" />налаштуваннÑÑ… Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Зазвичай цей Ñайт швидко відкриваєтьÑÑ Ð¹ відповідає</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Завершити анонімний переглÑд?</translation>
<translation id="8958424370300090006">Блокувати файли cookie з конкретного Ñайту.</translation>
<translation id="8959122750345127698">Веб-Ñторінка <ph name="URL" /> недоÑтупна</translation>
<translation id="8986362086234534611">Видалити</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ur.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ur.xtb
index cf37eb9c178..f5703db3900 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ur.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_ur.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="ur">
<translation id="1006017844123154345">آن لائن کھولیں</translation>
<translation id="1044891598689252897">سائٹس حسب معمول کام کریں گی</translation>
+<translation id="1100504063505580045">Ù…ÙˆØ¬ÙˆØ¯Û Ø¢Ø¦ÛŒÚ©Ù†</translation>
<translation id="1124090076051167250">اس سے آپ Ú©ÛŒ Ûوم اسکرین پر موجود سائٹس یا ایپس Ú©Û’ ذریعے اسٹور Ú©Ø±Ø¯Û <ph name="DATASIZE" /> ڈیٹا اور کوکیز صا٠ÛÙˆ جائیں گی۔</translation>
<translation id="1124772482545689468">صارÙ</translation>
<translation id="1178581264944972037">موقو٠کریں</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">مائیکروÙون</translation>
<translation id="3277252321222022663">سائٹس Ú©Ùˆ سینسرز تک رسائی حاصل کرنے Ú©ÛŒ اجازت دیں (تجویز کردÛ)</translation>
<translation id="3295602654194328831">معلومات چھپائیں</translation>
+<translation id="3317660236277031814">آپ Ú©ÛŒ انسٹال Ú©Ø±Ø¯Û ÙˆÛŒØ¨ ایپ کا آئیکن تبدیل ÛÙˆ گیا ÛÛ’Û”</translation>
<translation id="3328801116991980348">سائٹ کی معلومات</translation>
<translation id="3333961966071413176">تمام رابطے</translation>
<translation id="3386292677130313581">سائٹس Ú©Ùˆ آپ کا مقام جاننے Ú©ÛŒ اجازت دینے سے Ù¾ÛÙ„Û’ پوچھیں (تجویز کردÛ)</translation>
+<translation id="345699454248713913">آپ Ú©ÛŒ انسٹال Ú©Ø±Ø¯Û ÙˆÛŒØ¨ ایپ کا نام تبدیل ÛÙˆ گیا ÛÛ’Û”</translation>
<translation id="3538390592868664640">â€Ø³Ø§Ø¦Ù¹Ø³ Ú©Ùˆ اپنے اطرا٠کا 3D Ù†Ù‚Ø´Û ØªØ®Ù„ÛŒÙ‚ یا کیمرے Ú©ÛŒ پوزیشن ٹریک کرنے سے مسدود کریں</translation>
+<translation id="3551268116566418498">پوشیدگی وضع ترک کریں؟</translation>
<translation id="3586500876634962664">کیمرا اور مائیکروÙون کا استعمال</translation>
<translation id="358794129225322306">سائٹ Ú©Ùˆ خودکار طور پر متعدد Ùائلیں ڈاؤن لوڈ کرنے Ú©ÛŒ اجازت دیں۔</translation>
<translation id="3594780231884063836">ویڈیو خاموش کریں</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">مقام کی ترتیبات کھولیں</translation>
<translation id="4226663524361240545">اطلاعات Ø¢Ù„Û Ú©Ùˆ وائبریٹ کر سکتی Ûیں</translation>
<translation id="4259722352634471385">نیویگیشن مسدود ÛÛ’: <ph name="URL" /></translation>
+<translation id="4277239631747669329">آپ Ú©ÛŒ انسٹال Ú©Ø±Ø¯Û ÙˆÛŒØ¨ ایپ کا نام اور آئیکن تبدیل ÛÙˆ گیا ÛÛ’Û”</translation>
<translation id="4278390842282768270">اجازت یاÙتÛ</translation>
<translation id="429312253194641664">سائٹ پر میڈیا Ú†Ù„ رÛا ÛÛ’</translation>
<translation id="42981349822642051">پھیلائیں</translation>
<translation id="4336434711095810371">سبھی ڈیٹا صا٠کریں</translation>
<translation id="4402755511846832236">کب آپ Ùعال طور پر اس Ø¢Ù„Û Ú©Ø§ استعمال کر رÛÛ’ Ûیں اس کا Ù¾ØªÛ Ù„Ú¯Ø§Ù†Û’ سے سائٹس Ú©Ùˆ مسدود کریں</translation>
-<translation id="4433925000917964731">â€Google Ú©ÛŒ طر٠سے ÙراÛÙ… Ú©Ø±Ø¯Û Ù„Ø§Ø¦Ù¹ صÙØ­Û</translation>
<translation id="4434045419905280838">پوپ اپس اور ری ڈائریکٹس</translation>
<translation id="445467742685312942">سائٹس Ú©Ùˆ محÙوظ مواد چلانے Ú©ÛŒ اجازت دیں</translation>
<translation id="4468959413250150279">کسی مخصوص سائٹ کیلئے آواز بند کریں۔</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">آپ کے والدین کے زیر انتظام</translation>
<translation id="4670064810192446073">ورچوئل رئیلٹی</translation>
<translation id="4708011789095599544">کیا آپ واقعی اس ویب سائٹ Ú©Û’ لیے کوکیز اور دیگر سائٹ کا ڈیٹا صا٠کرنا چاÛتے Ûیں؟</translation>
+<translation id="473775607612524610">اپ ڈيٹ کریں</translation>
<translation id="4751476147751820511">موشن یا لائٹ سینسرز</translation>
<translation id="4836046166855586901">پوچھیں Ú©Û Ú©Ø¨ کوئی سائٹ ÛŒÛ Ø¬Ø§Ù†Ù†Ø§ چاÛتی ÛÛ’ Ú©Û Ùعال طور پر آپ اس Ø¢Ù„Û Ú©Ø§ استعمال کب کر رÛÛ’ Ûیں</translation>
<translation id="4883854917563148705">نظم Ú©Ø±Ø¯Û ØªØ±ØªÛŒØ¨Ø§Øª Ú©Ùˆ Ø¯ÙˆØ¨Ø§Ø±Û Ø³ÛŒÙ¹ Ù†Ûیں کیا جا سکتا</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">اشتراک کریں بذریعÛ</translation>
<translation id="5039804452771397117">اجازت دیں</translation>
<translation id="5048398596102334565">سائٹس Ú©Ùˆ موشن سینسرز تک رسائی حاصل کرنے Ú©ÛŒ اجازت دیں (تجویز کردÛ)</translation>
+<translation id="5050380848339752099">ÛŒÛ Ø³Ø§Ø¦Ù¹ پوشیدگی وضع سے باÛر ایک ایپ Ú©Û’ ساتھ معلومات کا اشتراک کرنے والی ÛÛ’Û”</translation>
<translation id="5063480226653192405">استعمال</translation>
<translation id="5100237604440890931">سکیڑ دیا گیا - پھیلانے کیلئے کلک کریں۔</translation>
<translation id="5123685120097942451">پوشیدگی ٹیب</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">â€Ø³Ø§Ø¦Ù¹Ø³ Ú©Ùˆ JavaScript چلانے Ú©ÛŒ اجازت دیں (تجویز کردÛ)</translation>
<translation id="534295439873310000">â€NFC آلات</translation>
<translation id="5354152178998424783">اس سے سائٹس Ú©Û’ ذریعے اسٹور Ú©Ø±Ø¯Û <ph name="DATASIZE" /> ڈیٹا اور کوکیز صا٠ÛÙˆ جائیں گی۔</translation>
-<translation id="5384883051496921101">ÛŒÛ Ø³Ø§Ø¦Ù¹ پوشیدگی وضع سے باÛر ایک ایپ Ú©Û’ ساتھ معلومات کا اشتراک کرنے والی ÛÛ’Û”</translation>
+<translation id="536508626067510330">آپ Ú©ÛŒ Ûوم اسکرین پر آئیکن Ú©Ùˆ اپ ڈیٹ کریں؟</translation>
<translation id="5391532827096253100">اس سائٹ Ú©Û’ لیے آپ کا کنکشن محÙوظ Ù†ÛÙŠÚº ÛÛ’Û” سائٹ Ú©ÛŒ معلومات</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{â€(‎+1 مزید)}other{(# + مزید)}}</translation>
<translation id="5403592356182871684">نام</translation>
<translation id="5489227211564503167"><ph name="TOTAL_TIME" /> میں سے <ph name="ELAPSED_TIME" /> وقت گزر گیا۔</translation>
<translation id="5494752089476963479">دخل انداز یا Ú¯Ù…Ø±Ø§Û Ú©Ù† اشتÛارات دکھانے والی سائٹس پر اشتÛارات Ú©Ùˆ مسدود کریں</translation>
+<translation id="549957179819296104">نیا آئیکن</translation>
<translation id="5502860503640766021"><ph name="PERMISSION_1" /> کی اجازت دی گئی، <ph name="PERMISSION_2" /> کو مسدود کر دیا گیا</translation>
<translation id="5505264765875738116">سائٹس اطلاعات بھیجنے Ú©Û’ لیے Ù†Ûیں Ú©ÛÛ Ø³Ú©ØªÛŒ Ûیں</translation>
<translation id="5516455585884385570">اطلاع کی ترتیبات کھولیں</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">اجازتیں</translation>
<translation id="5860033963881614850">Ø¢Ù</translation>
<translation id="5876056640971328065">ویڈیو موقو٠کریں</translation>
+<translation id="5904826301761575486">آپ Ú©ÛŒ Ûوم اسکرین پر نام اور آئیکن اپ ڈیٹ کریں؟</translation>
<translation id="5916664084637901428">آن</translation>
<translation id="5922853908706496913">آپ Ú©ÛŒ اسکرین کا اشتراک کیا جا رÛا ÛÛ’</translation>
<translation id="5939518447894949180">Ø¯ÙˆØ¨Ø§Ø±Û ØªØ±ØªÛŒØ¨ دیں</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Ùریق ثالث کوکیز Ú©Ùˆ مسدود کریں</translation>
<translation id="6206551242102657620">کنیکشن محÙوظ ÛÛ’Û” سائٹ Ú©ÛŒ معلومات</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> اختیارات</translation>
+<translation id="6260852843601447737">بند کریں اور بیجا استعمال کی اطلاع دیں</translation>
<translation id="6262279340360821358"><ph name="PERMISSION_1" /> اور <ph name="PERMISSION_2" /> کو مسدود کیا گیا</translation>
<translation id="6270391203985052864">سائٹس اطلاعات بھیجنے Ú©Û’ لیے Ú©ÛÛ Ø³Ú©ØªÛŒ Ûیں</translation>
<translation id="6295158916970320988">سبھی سائٹس</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">â€<ph name="APP_NAME" /> Ú©Ùˆ اپنے مقام تک رسائی دینے Ú©Û’ لیے، <ph name="BEGIN_LINK" />Android Ú©ÛŒ ترتیبات<ph name="END_LINK" /> میں بھی مقام آن کریں۔</translation>
<translation id="8447861592752582886">Ø¢Ù„Û Ú©ÛŒ اجازت کالعدم کریں</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 زیر استعمال کوکی}other{# زیر استعمال کوکیز}}</translation>
-<translation id="8463851957836045671">سائٹ تیز ÛÛ’</translation>
<translation id="8487700953926739672">آ٠لائن دستیاب ÛÛ’</translation>
<translation id="851751545965956758">سائٹس Ú©Ùˆ آلات سے منسلک Ûونے سے مسدود کریں</translation>
<translation id="8525306231823319788">پوری اسکرین</translation>
<translation id="857943718398505171">اجازت یاÙØªÛ (تجویز کردÛ)</translation>
<translation id="8609465669617005112">اوپر منتقل کریں</translation>
+<translation id="861748745608658996">آپ Ú©ÛŒ Ûوم اسکرین پر نام اپ ڈیٹ کریں؟</translation>
<translation id="8676374126336081632">ان پٹ صا٠کریں</translation>
<translation id="868929229000858085">اپنے رابطوں کو تلاش کریں</translation>
<translation id="8702612070107455751">تمام آ٠لائن ڈیٹا حذ٠ÛÙˆ جائے گا۔</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">زوم ان کریں</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">â€Ø§Ø³ Ø§Ù“Ù„Û Ú©Û’ لیے NFC آ٠ÛÛ’Û” اسے <ph name="BEGIN_LINK" />Android ترتیبات<ph name="END_LINK" /> میں آن کریں۔</translation>
-<translation id="8929372349074745002">ÛŒÛ Ø³Ø§Ø¦Ù¹ Ø²ÛŒØ§Ø¯Û ØªØ± لوگوں Ú©Û’ لئے Ùوری طور پر کھلتی اور جواب دیتی ÛÛ’</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">پوشیدگی وضع ترک کریں؟</translation>
<translation id="8958424370300090006">کسی مخصوص سائٹ کے لیے کوکیز مسدود کریں۔</translation>
<translation id="8959122750345127698">نیویگیشن ناقابل رسائی ÛÛ’: <ph name="URL" /></translation>
<translation id="8986362086234534611">بھول جائیں</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb
index 3d0e3bae125..6842270119b 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_uz.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="uz">
<translation id="1006017844123154345">Onlayn versiyasini ochish</translation>
<translation id="1044891598689252897">Saytlar xatosiz ishlaydi</translation>
+<translation id="1100504063505580045">Joriy belgi</translation>
<translation id="1124090076051167250">Bunda saytlar maʼlumotlari, cookie fayllar va Bosh ekrandagi ilovalar egallagan <ph name="DATASIZE" /> joy tozalanadi.</translation>
<translation id="1124772482545689468">Foydalanuvchi</translation>
<translation id="1178581264944972037">Pauza</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Mikrofon</translation>
<translation id="3277252321222022663">Saytlarga sensorlardan foydalanish uchun ruxsat berish (tavsiya etiladi)</translation>
<translation id="3295602654194328831">Ma’lumotlarni yashirish</translation>
+<translation id="3317660236277031814">Siz oʻrnatgan veb ilovaning belgisi oʻzgardi.</translation>
<translation id="3328801116991980348">Sayt haqida ma’lumot</translation>
<translation id="3333961966071413176">Barcha kontaktlar</translation>
<translation id="3386292677130313581">Joylashuv ma’lumotini ko‘rishiga ruxsat so‘ralsin (tavsiya etiladi)</translation>
+<translation id="345699454248713913">Siz oʻrnatgan veb ilovaning nomi oʻzgardi.</translation>
<translation id="3538390592868664640">Saytlarni atrofingizning 3D xaritasini yaratish yoki kamera joylashuvini aniqlashdan bloklash</translation>
+<translation id="3551268116566418498">Inkognito rejimi tark etilsinmi?</translation>
<translation id="3586500876634962664">Kamera va mikrofonni ishlatish</translation>
<translation id="358794129225322306">Saytga birdaniga bir nechta fayl yuklab olishga ruxsat berish.</translation>
<translation id="3594780231884063836">Video ovozini oʻchirish</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Joylashuv sozlamalarini ochish</translation>
<translation id="4226663524361240545">Bildirishnoma kelganida qurilma tebranishi mumkin</translation>
<translation id="4259722352634471385">Sahifa bloklandi: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Siz oʻrnatgan veb ilovaning nomi va belgisi oʻzgardi.</translation>
<translation id="4278390842282768270">Berilgan ruxsatnomalar</translation>
<translation id="429312253194641664">Saytda media-fayl ijro etilmoqda</translation>
<translation id="42981349822642051">Kengaytirish</translation>
<translation id="4336434711095810371">Barcha maʼlumotlarni tozalash</translation>
<translation id="4402755511846832236">Bu qurilmadan foydalanish axborotlarini saytlar bilishini taqiqlash</translation>
-<translation id="4433925000917964731">Sahifaning Lite versiyasi Google tomonidan taqdim etildi</translation>
<translation id="4434045419905280838">Qalquvchi oyna va yo‘naltirishlar</translation>
<translation id="445467742685312942">Saytlarga himoyalangan kontentni ijro qilish uchun ruxsat berish</translation>
<translation id="4468959413250150279">Muayyan saytdagi ovozni o‘chirish.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Ota-onangiz tomonidan boshqariladi</translation>
<translation id="4670064810192446073">Virtual reallik</translation>
<translation id="4708011789095599544">Bu sayt uchun cookie fayllar va boshqa sayt maʼlumotlari tozalansinmi?</translation>
+<translation id="473775607612524610">Yangilash</translation>
<translation id="4751476147751820511">Harakat va yorug‘lik sensorlari</translation>
<translation id="4836046166855586901">Sayt bu qurilmadan faol foydalanishingiz haqidagi axborotni yuborishdan oldin sizdan ruxsat oladi</translation>
<translation id="4883854917563148705">Boshqariladigan sozlamalarni oʻzgartirish imkonsiz</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Yuborish usuli</translation>
<translation id="5039804452771397117">Ruxsat berish</translation>
<translation id="5048398596102334565">Saytlarga harakat sensorlaridan foydalanish uchun ruxsat berish (tavsiya etiladi)</translation>
+<translation id="5050380848339752099">Bu sayt inkognito oynasidan tashqaridagi ilova bilan axborot ulashmoqchi.</translation>
<translation id="5063480226653192405">Sarfi</translation>
<translation id="5100237604440890931">Yig‘ilgan - Kengaytirish uchun bosing</translation>
<translation id="5123685120097942451">Inkognito varaq</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Saytlarga JavaScript ishga tushirishiga ruxsat berish (tavsiya etiladi)</translation>
<translation id="534295439873310000">NFC qurilmalar</translation>
<translation id="5354152178998424783">Saytlar joylagan <ph name="DATASIZE" /> maʼlumot va cookie fayllar tozalab tashlanadi.</translation>
-<translation id="5384883051496921101">Bu sayt inkognito oynasidan tashqaridagi ilova bilan axborot ulashmoqchi.</translation>
+<translation id="536508626067510330">Bosh ekrandagi belgi yangilansinmi?</translation>
<translation id="5391532827096253100">Bu sayt bilan o‘rnatilgan aloqa himoyalanmagan. Sayt axboroti</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(yana 1 ta)}other{(yana # ta)}}</translation>
<translation id="5403592356182871684">Ismlar</translation>
<translation id="5489227211564503167">Ijro etilgan vaqt: <ph name="ELAPSED_TIME" />/<ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Saytlarda chiquvchi yoqimsiz yoki befoyda reklamalar bloklansin</translation>
+<translation id="549957179819296104">Yangi belgi</translation>
<translation id="5502860503640766021">Ruxsat berildi: <ph name="PERMISSION_1" />, bloklandi:<ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Saytlar bildirishnoma chiqarishga ruxsat soʻray olmaydi</translation>
<translation id="5516455585884385570">Bildirishnoma sozlamalarini ochish</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Ruxsatlar</translation>
<translation id="5860033963881614850">O‘chiq</translation>
<translation id="5876056640971328065">Videoni pauza qilish</translation>
+<translation id="5904826301761575486">Bosh ekrandagi nomi va belgisi yangilansinmi?</translation>
<translation id="5916664084637901428">Yoniq</translation>
<translation id="5922853908706496913">Ekran namoyish qilinmoqda</translation>
<translation id="5939518447894949180">Asliga qaytarish</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Tashqi cookie-fayllarni bloklash.</translation>
<translation id="6206551242102657620">Aloqa himoyalangan. Sayt axboroti</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> parametrlar</translation>
+<translation id="6260852843601447737">Yopish va shikoyat yuborish</translation>
<translation id="6262279340360821358">Bloklandi: <ph name="PERMISSION_1" /> va <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Saytlar bildirishnoma chiqarishga ruxsat soʻray oladi</translation>
<translation id="6295158916970320988">Barcha saytlar</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703"><ph name="APP_NAME" /> joylashuvingizni aniqlay olishi uchun <ph name="BEGIN_LINK" />Android sozlamalari<ph name="END_LINK" /> orqali Joylashuvni aniqlash xizmatini yoqing.</translation>
<translation id="8447861592752582886">Qurilma ruxsatini bekor qilish</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 ta cookie fayl ishlatilmoqda}other{# ta cookie fayl ishlatilmoqda}}</translation>
-<translation id="8463851957836045671">Bu sayt tez</translation>
<translation id="8487700953926739672">Internetsiz foydalanish mumkin</translation>
<translation id="851751545965956758">Saytlarga qurilmalarga ulanishni taqiqlash</translation>
<translation id="8525306231823319788">To‘liq ekran rejimi</translation>
<translation id="857943718398505171">Ruxsat berilgan (tavsiya etiladi)</translation>
<translation id="8609465669617005112">Tepaga o‘tish</translation>
+<translation id="861748745608658996">Bosh ekrandagi nomi yangilansinmi?</translation>
<translation id="8676374126336081632">Tozalash</translation>
<translation id="868929229000858085">Kontaktlarni qidirish</translation>
<translation id="8702612070107455751">Har qanday oflayn axborot tozalab tashlanadi.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Kattalashtirish</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">Telefonda NFC yoqilmagan. Uni <ph name="BEGIN_LINK" />Android sozlamalari<ph name="END_LINK" /> orqali yoqing.</translation>
-<translation id="8929372349074745002">Bu sayt koʻpchilik uchun tezkor ochiladi va javob beradi</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Inkognito rejimi tark etilsinmi?</translation>
<translation id="8958424370300090006">Muayyan saytlar uchun cookie-fayllarni bloklang.</translation>
<translation id="8959122750345127698">Sahifa topilmadi: <ph name="URL" /></translation>
<translation id="8986362086234534611">Olib tashlash</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_vi.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_vi.xtb
index df8e9037763..e492ca660dc 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_vi.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_vi.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="vi">
<translation id="1006017844123154345">Mở trực tuyến</translation>
<translation id="1044891598689252897">Các trang web vẫn hoạt Ä‘á»™ng bình thÆ°á»ng</translation>
+<translation id="1100504063505580045">Biểu tượng hiện tại</translation>
<translation id="1124090076051167250">Thao tác này sẽ xóa <ph name="DATASIZE" /> dữ liệu và cookie lưu trữ trong các trang web hoặc ứng dụng trên Màn hình chính.</translation>
<translation id="1124772482545689468">Người dùng</translation>
<translation id="1178581264944972037">Tạm dừng</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Micrô</translation>
<translation id="3277252321222022663">Cho phép các trang web sử dụng cảm biến của thiết bị (nên dùng)</translation>
<translation id="3295602654194328831">Ẩn thông tin</translation>
+<translation id="3317660236277031814">Một ứng dụng web mà bạn cài đặt đã thay đổi biểu tượng của ứng dụng.</translation>
<translation id="3328801116991980348">Thông tin vỠtrang web</translation>
<translation id="3333961966071413176">Tất cả ngÆ°á»i liên hệ</translation>
<translation id="3386292677130313581">Há»i trÆ°á»›c khi cho phép các trang web biết vị trí của bạn (được Ä‘á» xuất)</translation>
+<translation id="345699454248713913">Một ứng dụng web mà bạn cài đặt đã thay đổi tên của ứng dụng.</translation>
<translation id="3538390592868664640">Chặn không cho trang web tạo bản đồ 3D vỠcác khu vực xung quanh bạn hoặc theo dõi thông tin vị trí của máy ảnh</translation>
+<translation id="3551268116566418498">Thoát khá»i chế Ä‘á»™ Ẩn danh?</translation>
<translation id="3586500876634962664">Äang sá»­ dụng máy ảnh và micrô</translation>
<translation id="358794129225322306">Cho phép má»™t trang web tá»± Ä‘á»™ng tải xuống nhiá»u tệp.</translation>
<translation id="3594780231884063836">Tắt tiếng video</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Mở phần Cài đặt vị trí</translation>
<translation id="4226663524361240545">Thông báo có thể làm rung thiết bị</translation>
<translation id="4259722352634471385">Äiá»u hÆ°á»›ng bị chặn: <ph name="URL" /></translation>
+<translation id="4277239631747669329">Một ứng dụng web mà bạn cài đặt đã thay đổi tên và biểu tượng của ứng dụng.</translation>
<translation id="4278390842282768270">Äược cho phép</translation>
<translation id="429312253194641664">Một trang web đang phát nội dung đa phương tiện</translation>
<translation id="42981349822642051">Mở rộng</translation>
<translation id="4336434711095810371">Xóa tất cả dữ liệu</translation>
<translation id="4402755511846832236">Không cho các trang web biết khi bạn đang dùng thiết bị này</translation>
-<translation id="4433925000917964731">Trang phiên bản rút gá»n do Google cung cấp</translation>
<translation id="4434045419905280838">Cửa sổ bật lên và liên kết chuyển hướng</translation>
<translation id="445467742685312942">Cho phép trang web phát nội dung được bảo vệ</translation>
<translation id="4468959413250150279">Tắt âm thanh trên một trang web cụ thể.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Do cha mẹ của bạn quản lý</translation>
<translation id="4670064810192446073">Thực tế ảo</translation>
<translation id="4708011789095599544">Bạn có chắc chắn muốn xóa cookie và dữ liệu khác của trang web này không?</translation>
+<translation id="473775607612524610">Cập nhật</translation>
<translation id="4751476147751820511">Cảm biến chuyển động hoặc ánh sáng</translation>
<translation id="4836046166855586901">Há»i khi má»™t trang web muốn biết khi bạn Ä‘ang dùng thiết bị này</translation>
<translation id="4883854917563148705">Bạn không thể đặt lại các tùy chá»n cài đặt được quản lý</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Chia sẻ qua</translation>
<translation id="5039804452771397117">Cho phép</translation>
<translation id="5048398596102334565">Cho phép trang web sử dụng cảm biến chuyển động (nên dùng)</translation>
+<translation id="5050380848339752099">Trang web này sắp chia sẻ thông tin với một ứng dụng bên ngoài chế độ Ẩn danh.</translation>
<translation id="5063480226653192405">Mức sử dụng</translation>
<translation id="5100237604440890931">Äã thu gá»n - nhấp để mở rá»™ng.</translation>
<translation id="5123685120097942451">Thẻ ẩn danh</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Cho phép các trang web chạy JavaScript (được đỠxuất)</translation>
<translation id="534295439873310000">Thiết bị dùng công nghệ NFC</translation>
<translation id="5354152178998424783">Thao tác này sẽ xóa <ph name="DATASIZE" /> dữ liệu và cookie do các trang web lưu trữ.</translation>
-<translation id="5384883051496921101">Trang web này sắp chia sẻ thông tin với một ứng dụng bên ngoài chế độ ẩn danh.</translation>
+<translation id="536508626067510330">Cập nhật biểu tượng trên màn hình chính của bạn?</translation>
<translation id="5391532827096253100">Kết nối của bạn tới trang web này không an toàn. Thông tin trang web</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 lá»±a chá»n khác)}other{(+ # lá»±a chá»n khác)}}</translation>
<translation id="5403592356182871684">Tên</translation>
<translation id="5489227211564503167">Thá»i gian đã trôi qua: <ph name="ELAPSED_TIME" />/<ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Chặn quảng cáo trên các trang web hiển thị quảng cáo xâm nhập hoặc quảng cáo gây hiểu nhầm</translation>
+<translation id="549957179819296104">Biểu tượng mới</translation>
<translation id="5502860503640766021">Äã cho phép <ph name="PERMISSION_1" />, đã chặn <ph name="PERMISSION_2" /></translation>
<translation id="5505264765875738116">Các trang web không thể xin phép gửi thông báo</translation>
<translation id="5516455585884385570">Mở mục cài đặt thông báo</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Quyá»n</translation>
<translation id="5860033963881614850">Tắt</translation>
<translation id="5876056640971328065">Tạm dừng video</translation>
+<translation id="5904826301761575486">Cập nhật tên và biểu tượng trên màn hình chính của bạn?</translation>
<translation id="5916664084637901428">Bật</translation>
<translation id="5922853908706496913">Äang chia sẻ màn hình của bạn</translation>
<translation id="5939518447894949180">Äặt lại</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Chặn cookie của bên thứ ba</translation>
<translation id="6206551242102657620">Kết nối an toàn. Thông tin trang web</translation>
<translation id="6216432067784365534">Tùy chá»n <ph name="NAME_OF_LIST_ITEM" /></translation>
+<translation id="6260852843601447737">Äóng ứng dụng và báo vi phạm</translation>
<translation id="6262279340360821358">Äã chặn <ph name="PERMISSION_1" /> và <ph name="PERMISSION_2" /></translation>
<translation id="6270391203985052864">Các trang web có thể xin phép gửi thông báo</translation>
<translation id="6295158916970320988">Tất cả các trang web</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Äể cho phép <ph name="APP_NAME" /> truy cập vào thông tin vị trí của bạn, hãy bật cả dịch vụ vị trí trong phần <ph name="BEGIN_LINK" />Cài đặt Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Thu hồi quyá»n truy cập thiết bị</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 cookie đang được sử dụng}other{# cookie đang được sử dụng}}</translation>
-<translation id="8463851957836045671">Trang web tải nhanh</translation>
<translation id="8487700953926739672">Có thể dùng khi không có mạng</translation>
<translation id="851751545965956758">Chặn các trang web kết nối với thiết bị</translation>
<translation id="8525306231823319788">Toàn màn hình</translation>
<translation id="857943718398505171">Äược phép (được Ä‘á» xuất)</translation>
<translation id="8609465669617005112">Di chuyển lên</translation>
+<translation id="861748745608658996">Cập nhật tên trên màn hình chính của bạn?</translation>
<translation id="8676374126336081632">Xóa văn bản nhập</translation>
<translation id="868929229000858085">Tìm kiếm trong danh bạ</translation>
<translation id="8702612070107455751">Má»i dữ liệu ngoại tuyến sẽ bị xóa.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Phóng to</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">NFC đã tắt đối với thiết bị này. Hãy bật trong phần <ph name="BEGIN_LINK" />Cài đặt Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Trang web này mở và phản hồi nhanh trong hầu hết má»i trÆ°á»ng hợp</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Thoát chế độ ẩn danh?</translation>
<translation id="8958424370300090006">Chặn cookie của một trang web cụ thể.</translation>
<translation id="8959122750345127698">Không thể tiếp cận Ä‘iá»u hÆ°á»›ng: <ph name="URL" /></translation>
<translation id="8986362086234534611">Quên</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-CN.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-CN.xtb
index d22163d2d37..af2b7f994cb 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-CN.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-CN.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="zh-CN">
<translation id="1006017844123154345">在线打开</translation>
<translation id="1044891598689252897">网站将能够正常è¿è¡Œ</translation>
+<translation id="1100504063505580045">当å‰å›¾æ ‡</translation>
<translation id="1124090076051167250">æ­¤æ“作会清除网站或其在主å±å¹•ä¸­å®‰è£…的应用所存储的 <ph name="DATASIZE" /> æ•°æ®å’Œ Cookie。</translation>
<translation id="1124772482545689468">用户</translation>
<translation id="1178581264944972037">æš‚åœ</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">麦克风</translation>
<translation id="3277252321222022663">å…许网站使用传感器(推è)</translation>
<translation id="3295602654194328831">éšè—ä¿¡æ¯</translation>
+<translation id="3317660236277031814">您安装的æŸä¸ª Web 应用更改了图标。</translation>
<translation id="3328801116991980348">网站信æ¯</translation>
<translation id="3333961966071413176">所有è”系人</translation>
<translation id="3386292677130313581">需先询问,得到许å¯åŽæ‰å…许网站获å–您的ä½ç½®ä¿¡æ¯ï¼ˆæŽ¨è)</translation>
+<translation id="345699454248713913">您安装的æŸä¸ª Web 应用更改了å称。</translation>
<translation id="3538390592868664640">ç¦æ­¢ç½‘站为您的周边环境创建 3D 地图或跟踪摄åƒå¤´ä½ç½®</translation>
+<translation id="3551268116566418498">退出无痕模å¼ï¼Ÿ</translation>
<translation id="3586500876634962664">正在使用摄åƒå¤´å’Œéº¦å…‹é£Ž</translation>
<translation id="358794129225322306">å…许网站自动下载多个文件。</translation>
<translation id="3594780231884063836">将视频é™éŸ³</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">打开ä½ç½®ä¿¡æ¯è®¾ç½®</translation>
<translation id="4226663524361240545">收到通知时设备会振动</translation>
<translation id="4259722352634471385">å·²å±è”½ <ph name="URL" /></translation>
+<translation id="4277239631747669329">您安装的æŸä¸ª Web 应用更改了å称和图标。</translation>
<translation id="4278390842282768270">å…许</translation>
<translation id="429312253194641664">æŸä¸ªç½‘站正在播放媒体内容</translation>
<translation id="42981349822642051">展开</translation>
<translation id="4336434711095810371">清除所有数æ®</translation>
<translation id="4402755511846832236">ç¦æ­¢ç½‘站了解您何时在主动使用此设备</translation>
-<translation id="4433925000917964731">ç”± Google æ供的精简版网页</translation>
<translation id="4434045419905280838">弹出å¼çª—å£å’Œé‡å®šå‘</translation>
<translation id="445467742685312942">å…许网站播放å—ä¿æŠ¤å†…容。</translation>
<translation id="4468959413250150279">å°†æŸä¸ªç‰¹å®šç½‘ç«™é™éŸ³ã€‚</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">由您父æ¯ç®¡ç†</translation>
<translation id="4670064810192446073">虚拟实境</translation>
<translation id="4708011789095599544">确定è¦æ¸…除此网站的 Cookie 和其他网站数æ®å—?</translation>
+<translation id="473775607612524610">æ›´æ–°</translation>
<translation id="4751476147751820511">动æ€ä¼ æ„Ÿå™¨æˆ–光传感器</translation>
<translation id="4836046166855586901">在网站想了解您何时在主动使用此设备时询问您</translation>
<translation id="4883854917563148705">无法é‡ç½®æ‰˜ç®¡è®¾ç½®</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">分享方å¼</translation>
<translation id="5039804452771397117">å…许</translation>
<translation id="5048398596102334565">å…许网站使用移动传感器(推è)</translation>
+<translation id="5050380848339752099">该网站å³å°†ä¸ŽæŸä¸ªå¹¶éžå¤„于无痕模å¼ä¸‹çš„应用共享信æ¯ã€‚</translation>
<translation id="5063480226653192405">空间å ç”¨é‡</translation>
<translation id="5100237604440890931">已收起 - 点击此处å³å¯å±•å¼€ã€‚</translation>
<translation id="5123685120097942451">æ— ç—•å¼æ ‡ç­¾é¡µ</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">å…许网站è¿è¡Œ JavaScript(推è)</translation>
<translation id="534295439873310000">NFC 设备</translation>
<translation id="5354152178998424783">æ­¤æ“作会清除网站存储的 <ph name="DATASIZE" /> æ•°æ®å’Œ Cookie。</translation>
-<translation id="5384883051496921101">该网站å³å°†ä¸ŽæŸä¸ªå¹¶éžå¤„于éšèº«æ¨¡å¼ä¸‹çš„应用共享信æ¯ã€‚</translation>
+<translation id="536508626067510330">更新您的主å±å¹•ä¸Šçš„图标?</translation>
<translation id="5391532827096253100">您与此网站之间建立的连接ä¸å®‰å…¨ã€‚网站信æ¯</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(以åŠå¦å¤– 1 个)}other{(以åŠå¦å¤– # 个)}}</translation>
<translation id="5403592356182871684">å称</translation>
<translation id="5489227211564503167">已播时长为 <ph name="ELAPSED_TIME" />,总时长为 <ph name="TOTAL_TIME" />。</translation>
<translation id="5494752089476963479">ç¦æ­¢ä¼šå±•ç¤ºä¾µæ‰°æ€§æˆ–误导性广告的网站显示广告</translation>
+<translation id="549957179819296104">新图标</translation>
<translation id="5502860503640766021">已授予“<ph name="PERMISSION_1" />â€æƒé™ï¼Œå·²ç¦ç”¨â€œ<ph name="PERMISSION_2" />â€æƒé™</translation>
<translation id="5505264765875738116">网站无法询问能å¦å‘您å‘é€é€šçŸ¥</translation>
<translation id="5516455585884385570">打开通知设置</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">æƒé™</translation>
<translation id="5860033963881614850">关闭</translation>
<translation id="5876056640971328065">æš‚åœè§†é¢‘</translation>
+<translation id="5904826301761575486">更新您的主å±å¹•ä¸Šçš„å称和图标?</translation>
<translation id="5916664084637901428">å¯ç”¨</translation>
<translation id="5922853908706496913">正在共享您的å±å¹•</translation>
<translation id="5939518447894949180">é‡ç½®</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">阻止第三方 Cookie</translation>
<translation id="6206551242102657620">连接是安全的。网站信æ¯</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" />选项</translation>
+<translation id="6260852843601447737">关闭此应用并举报它的滥用行为</translation>
<translation id="6262279340360821358">å·²ç¦ç”¨â€œ<ph name="PERMISSION_1" />â€æƒé™å’Œâ€œ<ph name="PERMISSION_2" />â€æƒé™</translation>
<translation id="6270391203985052864">网站å¯ä»¥è¯¢é—®èƒ½å¦å‘您å‘é€é€šçŸ¥</translation>
<translation id="6295158916970320988">所有网站</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">è‹¥è¦å…许 <ph name="APP_NAME" /> 获å–您的ä½ç½®ä¿¡æ¯ï¼Œæ‚¨è¿˜éœ€åœ¨ <ph name="BEGIN_LINK" />Android 设置<ph name="END_LINK" />中开å¯ä½ç½®ä¿¡æ¯æœåŠ¡ã€‚</translation>
<translation id="8447861592752582886">撤消设备æƒé™</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{正在使用 1 个 Cookie}other{正在使用 # 个 Cookie}}</translation>
-<translation id="8463851957836045671">网站加载速度很快</translation>
<translation id="8487700953926739672">å¯ç¦»çº¿ä½¿ç”¨</translation>
<translation id="851751545965956758">ç¦æ­¢ç½‘站连接到设备</translation>
<translation id="8525306231823319788">å…¨å±</translation>
<translation id="857943718398505171">å…许(推è)</translation>
<translation id="8609465669617005112">上移</translation>
+<translation id="861748745608658996">更新您的主å±å¹•ä¸Šçš„å称?</translation>
<translation id="8676374126336081632">清除输入的内容</translation>
<translation id="868929229000858085">æœç´¢è”系人</translation>
<translation id="8702612070107455751">所有离线数æ®éƒ½ä¼šè¢«æ¸…除。</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">放大</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">此设备的 NFC 功能处于关闭状æ€ã€‚请在 <ph name="BEGIN_LINK" />Android 设置<ph name="END_LINK" />中开å¯æ­¤åŠŸèƒ½ã€‚</translation>
-<translation id="8929372349074745002">对于大多数人而言,此网站能快速打开和å“应</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">退出éšèº«æ¨¡å¼ï¼Ÿ</translation>
<translation id="8958424370300090006">阻止特定网站使用 Cookie。</translation>
<translation id="8959122750345127698">无法访问 <ph name="URL" /></translation>
<translation id="8986362086234534611">ä¸ä¿å­˜</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-HK.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-HK.xtb
index 76c47223c8f..40441014fb9 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-HK.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-HK.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="zh-HK">
<translation id="1006017844123154345">在線上開啟</translation>
<translation id="1044891598689252897">網站將正常é‹ä½œ</translation>
+<translation id="1100504063505580045">ç›®å‰åœ–示</translation>
<translation id="1124090076051167250">æ­¤æ“作會清除 <ph name="DATASIZE" /> 主畫é¢ä¸Šå„個網站或應用程å¼å„²å­˜çš„資料和 Cookie。</translation>
<translation id="1124772482545689468">使用者</translation>
<translation id="1178581264944972037">æš«åœ</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">麥克風</translation>
<translation id="3277252321222022663">å…許網站存å–感應器 (建議)</translation>
<translation id="3295602654194328831">éš±è—資料</translation>
+<translation id="3317660236277031814">您已安è£çš„網絡應用程å¼å·²è®Šæ›´åœ–示。</translation>
<translation id="3328801116991980348">網站資料</translation>
<translation id="3333961966071413176">所有è¯çµ¡äºº</translation>
<translation id="3386292677130313581">å…許網站存å–您的ä½ç½®å‰å…ˆè©¢å•æ‚¨ (建議)</translation>
+<translation id="345699454248713913">您已安è£çš„網絡應用程å¼å·²è®Šæ›´å稱。</translation>
<translation id="3538390592868664640">ç¦æ­¢ç¶²ç«™å»ºç«‹æ‚¨èº«è™•ç’°å¢ƒçš„ 3D 地圖或追蹤æ”錄機ä½ç½®</translation>
+<translation id="3551268116566418498">è¦é€€å‡ºç„¡ç—•æ¨¡å¼å—Žï¼Ÿ</translation>
<translation id="3586500876634962664">使用æ”錄機和麥克風</translation>
<translation id="358794129225322306">å…許網站自動下載多個檔案。</translation>
<translation id="3594780231884063836">將影片éœéŸ³</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">é–‹å•Ÿä½ç½®è¨­å®š</translation>
<translation id="4226663524361240545">è£ç½®æœƒåœ¨æ”¶åˆ°é€šçŸ¥æ™‚震動</translation>
<translation id="4259722352634471385">ç€è¦½ç¶²å€è¢«å°éŽ–:<ph name="URL" /></translation>
+<translation id="4277239631747669329">您已安è£çš„網絡應用程å¼å·²è®Šæ›´å稱和圖示。</translation>
<translation id="4278390842282768270">å·²å…許</translation>
<translation id="429312253194641664">網站正在播放媒體</translation>
<translation id="42981349822642051">展開</translation>
<translation id="4336434711095810371">清除所有資料</translation>
<translation id="4402755511846832236">ç¦æ­¢ç¶²ç«™å–å¾—æ­¤è£ç½®çš„使用狀態</translation>
-<translation id="4433925000917964731">此簡易版網é ç”± Google æä¾›</translation>
<translation id="4434045419905280838">彈出å¼è¦–窗和é‡æ–°å°Žå‘</translation>
<translation id="445467742685312942">å…許網站播放å—ä¿è­·çš„內容</translation>
<translation id="4468959413250150279">將特定網站設為éœéŸ³ã€‚</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">由您的家長管ç†</translation>
<translation id="4670064810192446073">虛擬實境</translation>
<translation id="4708011789095599544">確定è¦æ¸…除此網站的 Cookie 和其他網站資料嗎?</translation>
+<translation id="473775607612524610">æ›´æ–°</translation>
<translation id="4751476147751820511">動態或光線感應器</translation>
<translation id="4836046166855586901">在網站è¦æ±‚知é“您是å¦æ­£åœ¨ä½¿ç”¨æ­¤è£ç½®æ™‚è©¢å•æ‚¨</translation>
<translation id="4883854917563148705">無法é‡è¨­å—管ç†çš„設定</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">共用方å¼</translation>
<translation id="5039804452771397117">å…許</translation>
<translation id="5048398596102334565">å…許網站存å–動作感應器 (建議)</translation>
+<translation id="5050380848339752099">此網站å³å°‡é€€å‡ºç„¡ç—•æ¨¡å¼ä¸¦èˆ‡å¤–部應用程å¼åˆ†äº«è³‡æ–™ã€‚</translation>
<translation id="5063480226653192405">用é‡</translation>
<translation id="5100237604440890931">å·²æ”¶åˆ - 點擊å³å¯å±•é–‹ã€‚</translation>
<translation id="5123685120097942451">ç„¡ç—•å¼åˆ†é </translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">å…許網站執行 JavaScript (建議)</translation>
<translation id="534295439873310000">NFC è£ç½®</translation>
<translation id="5354152178998424783">æ­¤æ“作會清除網站儲存的資料和 Cookie (å…± <ph name="DATASIZE" />)。</translation>
-<translation id="5384883051496921101">此網站å³å°‡èˆ‡å¤–部應用程å¼åˆ†äº«è³‡æ–™ï¼Œåˆ†äº«æ™‚會離開無痕模å¼ã€‚</translation>
+<translation id="536508626067510330">è¦æ›´æ–°ä¸»ç•«é¢ä¸Šçš„圖示嗎?</translation>
<translation id="5391532827096253100">呢個網站嘅連線唔安全。網站資料</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(還有 1 個)}other{(還有 # 個)}}</translation>
<translation id="5403592356182871684">å稱</translation>
<translation id="5489227211564503167">播咗嘅時間係 <ph name="ELAPSED_TIME" />,影片總長度係 <ph name="TOTAL_TIME" />。</translation>
<translation id="5494752089476963479">在顯示滋擾或誤導廣告的網站上å°éŽ–廣告</translation>
+<translation id="549957179819296104">新圖示</translation>
<translation id="5502860503640766021">å·²å…許「<ph name="PERMISSION_1" />ã€ï¼Œå·²å°éŽ–「<ph name="PERMISSION_2" />ã€</translation>
<translation id="5505264765875738116">網站將無法è¦æ±‚å‘您傳é€é€šçŸ¥</translation>
<translation id="5516455585884385570">開通知設定</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">權é™</translation>
<translation id="5860033963881614850">關閉</translation>
<translation id="5876056640971328065">æš«åœå½±ç‰‡</translation>
+<translation id="5904826301761575486">è¦æ›´æ–°ä¸»ç•«é¢ä¸Šçš„å稱和圖示嗎?</translation>
<translation id="5916664084637901428">é–‹å•Ÿ</translation>
<translation id="5922853908706496913">正在分享螢幕畫é¢</translation>
<translation id="5939518447894949180">é‡è¨­</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">å°éŽ–第三方 Cookie</translation>
<translation id="6206551242102657620">連線安全。網站資料</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" />é¸é …</translation>
+<translation id="6260852843601447737">關閉並報告濫用情æ³</translation>
<translation id="6262279340360821358">å·²å°éŽ–「<ph name="PERMISSION_1" />ã€å’Œã€Œ<ph name="PERMISSION_2" />ã€</translation>
<translation id="6270391203985052864">網站將å¯ä»¥è¦æ±‚å‘您傳é€é€šçŸ¥</translation>
<translation id="6295158916970320988">所有網站</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">如è¦è®“ <ph name="APP_NAME" /> å­˜å–您的ä½ç½®ï¼Œè«‹ä¸€ä½µåœ¨ <ph name="BEGIN_LINK" />Android 設定<ph name="END_LINK" />中開啟「ä½ç½®è³‡è¨Šã€åŠŸèƒ½ã€‚</translation>
<translation id="8447861592752582886">撤消è£ç½®æ¬Šé™</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{1 個 Cookie 正在使用中}other{# 個 Cookie 正在使用中}}</translation>
-<translation id="8463851957836045671">網站快速</translation>
<translation id="8487700953926739672">å¯é›¢ç·šä½¿ç”¨</translation>
<translation id="851751545965956758">ç¦æ­¢ç¶²ç«™é€£æŽ¥è£ç½®</translation>
<translation id="8525306231823319788">全螢幕</translation>
<translation id="857943718398505171">å…許 (建議)</translation>
<translation id="8609465669617005112">上移</translation>
+<translation id="861748745608658996">è¦æ›´æ–°ä¸»ç•«é¢ä¸Šçš„å稱嗎?</translation>
<translation id="8676374126336081632">清除輸入</translation>
<translation id="868929229000858085">æœå°‹æ‚¨çš„è¯çµ¡äºº</translation>
<translation id="8702612070107455751">所有離線資料將會被清除</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">放大</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">æ­¤è£ç½®çš„ NFC 已關閉,請在「<ph name="BEGIN_LINK" />Android 設定<ph name="END_LINK" />ã€ä¸­é–‹å•Ÿã€‚</translation>
-<translation id="8929372349074745002">å°å¤§éƒ¨åˆ†äººä¾†èªªï¼Œæ­¤ç¶²ç«™èƒ½å¿«é€Ÿé–‹å•Ÿä¸¦ä½œå‡ºå›žæ‡‰</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">è¦é›¢é–‹ç„¡ç—•æ¨¡å¼å—Žï¼Ÿ</translation>
<translation id="8958424370300090006">ç¦æ­¢ç‰¹å®šç¶²ç«™å­˜å– Cookie。</translation>
<translation id="8959122750345127698">無法存å–ç€è¦½ç¶²å€ï¼š<ph name="URL" /></translation>
<translation id="8986362086234534611">清除</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-TW.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-TW.xtb
index d9678f4ce29..d1aa029651e 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-TW.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zh-TW.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="zh-TW">
<translation id="1006017844123154345">在網路上開啟</translation>
<translation id="1044891598689252897">網站將正常é‹ä½œ</translation>
+<translation id="1100504063505580045">ç›®å‰åœ–示</translation>
<translation id="1124090076051167250">這會清除網站或主畫é¢ä¸Šçš„應用程å¼æ‰€å„²å­˜çš„資料和 Cookie (å…± <ph name="DATASIZE" />)。</translation>
<translation id="1124772482545689468">使用者</translation>
<translation id="1178581264944972037">æš«åœ</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">麥克風</translation>
<translation id="3277252321222022663">å…許網站存å–感應器 (建議)</translation>
<translation id="3295602654194328831">éš±è—資訊</translation>
+<translation id="3317660236277031814">你安è£çš„æŸå€‹ç¶²é æ‡‰ç”¨ç¨‹å¼å·²è®Šæ›´åœ–示。</translation>
<translation id="3328801116991980348">網站資訊</translation>
<translation id="3333961966071413176">所有è¯çµ¡äºº</translation>
<translation id="3386292677130313581">å…許網站存å–ä½ çš„ä½ç½®è³‡è¨Šå‰ï¼Œå¿…須先詢å•ä½  (建議)</translation>
+<translation id="345699454248713913">你安è£çš„æŸå€‹ç¶²é æ‡‰ç”¨ç¨‹å¼å·²è®Šæ›´å稱。</translation>
<translation id="3538390592868664640">ç¦æ­¢ç¶²ç«™æ ¹æ“šä½ çš„周é­ç’°å¢ƒå»ºç«‹ 3D 地圖或追蹤æ”影機ä½ç½®</translation>
+<translation id="3551268116566418498">è¦é€€å‡ºç„¡ç—•æ¨¡å¼å—Žï¼Ÿ</translation>
<translation id="3586500876634962664">使用æ”影機和麥克風</translation>
<translation id="358794129225322306">å…許網站自動下載多個檔案。</translation>
<translation id="3594780231884063836">將影片設為éœéŸ³</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">é–‹å•Ÿä½ç½®è³‡è¨Šè¨­å®š</translation>
<translation id="4226663524361240545">收到通知時è£ç½®æœƒéœ‡å‹•</translation>
<translation id="4259722352634471385">ç€è¦½çš„網å€å·²å°éŽ–:<ph name="URL" /></translation>
+<translation id="4277239631747669329">你安è£çš„æŸå€‹ç¶²é æ‡‰ç”¨ç¨‹å¼å·²è®Šæ›´å稱和圖示。</translation>
<translation id="4278390842282768270">å…許</translation>
<translation id="429312253194641664">一個網站正在播放媒體內容</translation>
<translation id="42981349822642051">展開</translation>
<translation id="4336434711095810371">清除所有資料</translation>
<translation id="4402755511846832236">ç¦æ­¢ç¶²ç«™å–得這部è£ç½®çš„使用狀態</translation>
-<translation id="4433925000917964731">ç”± Google æ供的精簡版網é </translation>
<translation id="4434045419905280838">彈出å¼è¦–窗與é‡æ–°å°Žå‘</translation>
<translation id="445467742685312942">å…許網站播放å—ä¿è­·çš„內容</translation>
<translation id="4468959413250150279">將特定網站設為éœéŸ³ã€‚</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">你的家長已åœç”¨é€™é …功能</translation>
<translation id="4670064810192446073">虛擬實境</translation>
<translation id="4708011789095599544">確定è¦æ¸…除這個網站的 Cookie 和其他網站資料嗎?</translation>
+<translation id="473775607612524610">æ›´æ–°</translation>
<translation id="4751476147751820511">動作或光æºæ„Ÿæ‡‰å™¨</translation>
<translation id="4836046166855586901">å…許網站詢å•ä½ ä½¿ç”¨é€™éƒ¨è£ç½®çš„時間</translation>
<translation id="4883854917563148705">無法é‡è¨­å—管ç†çš„設定</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">分享方å¼ï¼š</translation>
<translation id="5039804452771397117">å…許</translation>
<translation id="5048398596102334565">å…許網站存å–動作感應器 (建議)</translation>
+<translation id="5050380848339752099">這個網站å³å°‡é€€å‡ºç„¡ç—•æ¨¡å¼ä¸¦èˆ‡å¤–部應用程å¼åˆ†äº«è³‡è¨Šã€‚</translation>
<translation id="5063480226653192405">用é‡</translation>
<translation id="5100237604440890931">å·²æ”¶åˆ - 按一下å³å¯å±•é–‹ã€‚</translation>
<translation id="5123685120097942451">ç„¡ç—•å¼åˆ†é </translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">å…許網站執行 JavaScript (建議)</translation>
<translation id="534295439873310000">NFC è£ç½®</translation>
<translation id="5354152178998424783">這會清除網站儲存的資料和 Cookie (共 <ph name="DATASIZE" />)。</translation>
-<translation id="5384883051496921101">這個網站å³å°‡èˆ‡å¤–部應用程å¼åˆ†äº«è³‡è¨Šï¼Œåˆ†äº«æ™‚會自動退出無痕模å¼ã€‚</translation>
+<translation id="536508626067510330">è¦æ›´æ–°ä¸»ç•«é¢ä¸Šçš„圖示嗎?</translation>
<translation id="5391532827096253100">你與這個網站的連線ä¸å®‰å…¨ã€‚網站資訊</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(還有 1 個)}other{(還有 # 個)}}</translation>
<translation id="5403592356182871684">å稱</translation>
<translation id="5489227211564503167">經éŽæ™‚間:<ph name="ELAPSED_TIME" />,影片總長:<ph name="TOTAL_TIME" />。</translation>
<translation id="5494752089476963479">å°éŽ–干擾性或誤導性的網站廣告</translation>
+<translation id="549957179819296104">新圖示</translation>
<translation id="5502860503640766021">å·²å…許「<ph name="PERMISSION_1" />ã€ï¼Œå·²å°éŽ–「<ph name="PERMISSION_2" />ã€</translation>
<translation id="5505264765875738116">網站無法è¦æ±‚傳é€é€šçŸ¥çµ¦ä½ </translation>
<translation id="5516455585884385570">開啟通知設定</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">權é™</translation>
<translation id="5860033963881614850">關閉</translation>
<translation id="5876056640971328065">æš«åœå½±ç‰‡</translation>
+<translation id="5904826301761575486">è¦æ›´æ–°ä¸»ç•«é¢ä¸Šçš„å稱和圖示嗎?</translation>
<translation id="5916664084637901428">é–‹å•Ÿ</translation>
<translation id="5922853908706496913">正在分享你的螢幕畫é¢</translation>
<translation id="5939518447894949180">é‡è¨­</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">å°éŽ–第三方 Cookie</translation>
<translation id="6206551242102657620">已建立安全連線。網站資訊</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" />é¸é …</translation>
+<translation id="6260852843601447737">關閉並檢舉濫用情形</translation>
<translation id="6262279340360821358">å·²å°éŽ–「<ph name="PERMISSION_1" />ã€å’Œã€Œ<ph name="PERMISSION_2" />ã€</translation>
<translation id="6270391203985052864">網站å¯ä»¥è¦æ±‚傳é€é€šçŸ¥çµ¦ä½ </translation>
<translation id="6295158916970320988">所有網站</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">如è¦å…許 <ph name="APP_NAME" /> å­˜å–ä½ çš„ä½ç½®ï¼Œè«‹ä¸€ä½µåœ¨ <ph name="BEGIN_LINK" />Android 設定<ph name="END_LINK" />中開啟定ä½åŠŸèƒ½ã€‚</translation>
<translation id="8447861592752582886">撤銷è£ç½®æ¬Šé™</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{ç›®å‰ä½¿ç”¨ 1 個 Cookie}other{ç›®å‰ä½¿ç”¨ # 個 Cookie}}</translation>
-<translation id="8463851957836045671">這個網站的載入速度很快</translation>
<translation id="8487700953926739672">å¯é›¢ç·šä½¿ç”¨</translation>
<translation id="851751545965956758">ç¦æ­¢ç¶²ç«™é€£ç·šè‡³è£ç½®</translation>
<translation id="8525306231823319788">全螢幕</translation>
<translation id="857943718398505171">å·²å…許 (建議)</translation>
<translation id="8609465669617005112">上移</translation>
+<translation id="861748745608658996">è¦æ›´æ–°ä¸»ç•«é¢ä¸Šçš„å稱嗎?</translation>
<translation id="8676374126336081632">清除輸入</translation>
<translation id="868929229000858085">æœå°‹è¯çµ¡äºº</translation>
<translation id="8702612070107455751">所有離線資料都將é­åˆ°æ¸…除。</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">放大</translation>
<translation id="8921772741368021346"><ph name="POSITION" />/<ph name="DURATION" /></translation>
<translation id="8926666909099850184">這部è£ç½®çš„ NFC 功能已關閉。請å‰å¾€ <ph name="BEGIN_LINK" />Android 設定<ph name="END_LINK" />開啟這項功能。</translation>
-<translation id="8929372349074745002">å°å¤§å¤šæ•¸äººè€Œè¨€ï¼Œé€™å€‹ç¶²ç«™çš„開啟和回應速度都很快</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">è¦é€€å‡ºç„¡ç—•æ¨¡å¼å—Žï¼Ÿ</translation>
<translation id="8958424370300090006">å°éŽ–特定網站的 Cookie。</translation>
<translation id="8959122750345127698">ç€è¦½çš„網å€ç„¡æ³•å­˜å–:<ph name="URL" /></translation>
<translation id="8986362086234534611">清除</translation>
diff --git a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb
index 1946d398c3b..8bbec39873c 100644
--- a/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb
+++ b/chromium/components/browser_ui/strings/android/translations/browser_ui_strings_zu.xtb
@@ -3,6 +3,7 @@
<translationbundle lang="zu">
<translation id="1006017844123154345">Vula ku-inthanethi</translation>
<translation id="1044891598689252897">Amasayithi azosebenza ngokuvamile</translation>
+<translation id="1100504063505580045">Isithonjana samanje</translation>
<translation id="1124090076051167250">Lokhu kuzosusa idata engu-<ph name="DATASIZE" /> yamakhukhi agcinwe ngamasayithi noma izinhlelo zokusebenza Kusikrini sakho sasekhaya.</translation>
<translation id="1124772482545689468">Umsebenzisi</translation>
<translation id="1178581264944972037">Misa isikhashana</translation>
@@ -88,10 +89,13 @@
<translation id="3227137524299004712">Imakrofoni</translation>
<translation id="3277252321222022663">Vumela amasayithi ukuthi afinyelele kuzinzwa (kunconyiwe)</translation>
<translation id="3295602654194328831">Fihla ulwazi</translation>
+<translation id="3317660236277031814">I-app yewebhu oyifakile ishintshe isithonjana sayo.</translation>
<translation id="3328801116991980348">Ulwazi lwesayithi</translation>
<translation id="3333961966071413176">Bonke oxhumana nabo</translation>
<translation id="3386292677130313581">Buza ngaphambi kokuvumela amasayithi ukuthi azi indawo yakho (kunconyiwe)</translation>
+<translation id="345699454248713913">I-app yewebhu oyifakile ishintshe igama layo.</translation>
<translation id="3538390592868664640">Vimbela amasayithi ekudaleni imephu ye-3D yendawo ekuzungezile noma ukulandelela indawo yekhamera</translation>
+<translation id="3551268116566418498">Shiya imodi ye-incognito?</translation>
<translation id="3586500876634962664">Ukusetshenziswa kwekhamera nemakrofoni</translation>
<translation id="358794129225322306">Vumela isayithi lilande amafayela amaningi ngokuzenzakalela.</translation>
<translation id="3594780231884063836">Thulisa ividiyo</translation>
@@ -114,12 +118,12 @@
<translation id="4200726100658658164">Vula Izilungiselelo zendawo</translation>
<translation id="4226663524361240545">Izaziso zingadlidliza idivayisi</translation>
<translation id="4259722352634471385">Ukuzulazula kuvinjiwe: <ph name="URL" /></translation>
+<translation id="4277239631747669329">I-app yewebhu oyifakile ishintshe igama nesithonjana sayo.</translation>
<translation id="4278390842282768270">Kuvunyelwe</translation>
<translation id="429312253194641664">Isayithi lidlala imidiya</translation>
<translation id="42981349822642051">Nweba</translation>
<translation id="4336434711095810371">Sula yonke idatha</translation>
<translation id="4402755511846832236">Vimbela amasayithi ukuthi azi lapho usebenzisa le divayisi</translation>
-<translation id="4433925000917964731">Ikhasi elilula linikezwe i-Google</translation>
<translation id="4434045419905280838">Okwesikhashana nokuqondiswa kabusha</translation>
<translation id="445467742685312942">Vumela amasayithi ukudlala okuqukethwe okuvikelekile</translation>
<translation id="4468959413250150279">Thulisa umsindo kusayithi elithile.</translation>
@@ -130,6 +134,7 @@
<translation id="4645575059429386691">Kuphethwe umzali wakho</translation>
<translation id="4670064810192446073">Into engekho ngokoqobo</translation>
<translation id="4708011789095599544">Uyaqiniseka yini ukuthi ufuna ukusula amakhukhi nedatha yelinye isayithi kule webhusayithi?</translation>
+<translation id="473775607612524610">Buyekeza</translation>
<translation id="4751476147751820511">Izinzwa zokunyakaza noma zokukhanya</translation>
<translation id="4836046166855586901">Buza lapho isayithi lifuna ukwazi lapho usebenzisa le divayisi</translation>
<translation id="4883854917563148705">Izilungiselelo eziphethwe azikwazi ukusethwa kabusha</translation>
@@ -140,6 +145,7 @@
<translation id="4996978546172906250">Yabelana nge-</translation>
<translation id="5039804452771397117">Vumela</translation>
<translation id="5048398596102334565">Vumela amasayithi ukuthi afinyelele kuzinzwa zokunyakaza (kunconyiwe)</translation>
+<translation id="5050380848339752099">Le sayithi limayelana nokwabelana ulwazi ne-app ngaphandle kwemodi ye-incognito.</translation>
<translation id="5063480226653192405">Ukusetshenziswa</translation>
<translation id="5100237604440890931">Igoqiwe - chofoza ukuze unwebe.</translation>
<translation id="5123685120097942451">Ithebhu ye-Incognito</translation>
@@ -153,12 +159,13 @@
<translation id="5335288049665977812">Vumela amasayithi ukuthi aqalise i-JavaScript (kunconyiwe)</translation>
<translation id="534295439873310000">Amadivayisi e-NFC</translation>
<translation id="5354152178998424783">Lokhu kuzosula idatha engu-<ph name="DATASIZE" /> namakhukhu alondolozwe amasayithi.</translation>
-<translation id="5384883051496921101">Leli sayithi limayelana nokwabelana ulwazi nohlelo lokusebenza olungaphandle kwemodi ye-incognito.</translation>
+<translation id="536508626067510330">Buyekeza isithonjana esisesikrinini sakho sasekhaya?</translation>
<translation id="5391532827096253100">Uxhumo lwakho kuleli sayithi aliphephile. Ulwazi lwesayithi</translation>
<translation id="5394307150471348411">{DETAIL_COUNT,plural, =1{(+ 1 okuningi)}one{(+ # okuningi)}other{(+ # okuningi)}}</translation>
<translation id="5403592356182871684">Amagama</translation>
<translation id="5489227211564503167">Isikhathi esidlulile singu-<ph name="ELAPSED_TIME" /> kwesingu-<ph name="TOTAL_TIME" />.</translation>
<translation id="5494752089476963479">Vimbela izikhangiso kumasayithi abonisa izikhangiso ezisongelayo noma ezilahlekisayo</translation>
+<translation id="549957179819296104">Isithonjana esisha</translation>
<translation id="5502860503640766021">I-<ph name="PERMISSION_1" /> ivunyelwe, i-<ph name="PERMISSION_2" /> ivinjelwe</translation>
<translation id="5505264765875738116">Amasayithi awakwazi ukuthumela izaziso</translation>
<translation id="5516455585884385570">Vula izilungiselelo zesaziso</translation>
@@ -175,6 +182,7 @@
<translation id="5804241973901381774">Izimvume</translation>
<translation id="5860033963881614850">Valiwe</translation>
<translation id="5876056640971328065">Phumuza ividiyo</translation>
+<translation id="5904826301761575486">Buyekeza igama nesithonjana esikrinini sakho sasekhaya?</translation>
<translation id="5916664084637901428">Vuliwe</translation>
<translation id="5922853908706496913">Yabelana ngesikrini sakho</translation>
<translation id="5939518447894949180">Setha kabusha</translation>
@@ -191,6 +199,7 @@
<translation id="6196640612572343990">Vimba amakhukhi enkampani yangaphandle</translation>
<translation id="6206551242102657620">Uxhumo luphephile. Ulwazi lwesayithi</translation>
<translation id="6216432067784365534"><ph name="NAME_OF_LIST_ITEM" /> Izinketho</translation>
+<translation id="6260852843601447737">Vala bese ubika ukuhlukunyezwa</translation>
<translation id="6262279340360821358">I-<ph name="PERMISSION_1" /> ne-<ph name="PERMISSION_2" /> kuvinjelwe</translation>
<translation id="6270391203985052864">Amasayithi angacela ukuthumela izaziso</translation>
<translation id="6295158916970320988">Wonke amasayithi</translation>
@@ -282,12 +291,12 @@
<translation id="8444433999583714703">Ukuze uvumele i-<ph name="APP_NAME" /> ukuba ifinyelele indawo yakho, vula nendawo <ph name="BEGIN_LINK" />Kumasethingi e-Android<ph name="END_LINK" />.</translation>
<translation id="8447861592752582886">Buyisa imvume yedivayisi</translation>
<translation id="8451050538944905715">{NUM_SELECTED,plural, =1{Ikhukhi e-1 iyasebenza}one{Amakhukhi angu-# asebenzayo}other{Amakhukhi angu-# asebenzayo}}</translation>
-<translation id="8463851957836045671">Isayithi liyashesha</translation>
<translation id="8487700953926739672">Itholakala kokungaxhunyiwe ku-inthanethi</translation>
<translation id="851751545965956758">Vimbela amasayithi kusukela ekuxhumekeni kumadivayisi</translation>
<translation id="8525306231823319788">Isikrini esigcwele</translation>
<translation id="857943718398505171">Kuvunyelwe (kunconyiwe)</translation>
<translation id="8609465669617005112">Hambisa phezulu</translation>
+<translation id="861748745608658996">Buyekeza igama kusikrini sakho sasekhaya?</translation>
<translation id="8676374126336081632">Sula okokufaka</translation>
<translation id="868929229000858085">Sesha oxhumana nabo</translation>
<translation id="8702612070107455751">Noma iyiphi idatha engaxhunyiwe ku-inthanethi izosulwa.</translation>
@@ -302,9 +311,7 @@
<translation id="8903921497873541725">Sondeza</translation>
<translation id="8921772741368021346"><ph name="POSITION" /> / <ph name="DURATION" /></translation>
<translation id="8926666909099850184">I-NFC ivaliwe kule divayisi. Ivule kokuthi <ph name="BEGIN_LINK" />Izilungiselelo ze-Android<ph name="END_LINK" />.</translation>
-<translation id="8929372349074745002">Leli sayithi livuleka futhi lisabele ngokushesha kubantu abaningi</translation>
<translation id="8941729603749328384">www.example.com</translation>
-<translation id="894871326938397531">Shiya imodi ye-incognito?</translation>
<translation id="8958424370300090006">Vimbela amakhukhi kusayithi elithile.</translation>
<translation id="8959122750345127698">Ukuzulazula akufinyeleleki: <ph name="URL" /></translation>
<translation id="8986362086234534611">Khohlwa</translation>
diff --git a/chromium/components/browser_ui/styles/android/BUILD.gn b/chromium/components/browser_ui/styles/android/BUILD.gn
index 8b4d43613c1..70f450a778c 100644
--- a/chromium/components/browser_ui/styles/android/BUILD.gn
+++ b/chromium/components/browser_ui/styles/android/BUILD.gn
@@ -27,6 +27,7 @@ android_resources("java_resources") {
"java/res/color/default_icon_color_secondary_tint_list.xml",
"java/res/color/default_icon_color_tint_list.xml",
"java/res/drawable-hdpi/btn_star_filled.png",
+ "java/res/drawable-hdpi/ic_chrome.png",
"java/res/drawable-hdpi/ic_delete_white_24dp.png",
"java/res/drawable-hdpi/ic_edit_24dp.png",
"java/res/drawable-hdpi/ic_folder_blue_24dp.png",
@@ -52,6 +53,7 @@ android_resources("java_resources") {
"java/res/drawable-ldrtl-xxhdpi/ic_share_white_24dp.png",
"java/res/drawable-ldrtl-xxxhdpi/ic_share_white_24dp.png",
"java/res/drawable-mdpi/btn_star_filled.png",
+ "java/res/drawable-mdpi/ic_chrome.png",
"java/res/drawable-mdpi/ic_delete_white_24dp.png",
"java/res/drawable-mdpi/ic_edit_24dp.png",
"java/res/drawable-mdpi/ic_folder_blue_24dp.png",
@@ -72,6 +74,7 @@ android_resources("java_resources") {
"java/res/drawable-mdpi/top_round_foreground.9.png",
"java/res/drawable-mdpi/top_round_shadow.9.png",
"java/res/drawable-xhdpi/btn_star_filled.png",
+ "java/res/drawable-xhdpi/ic_chrome.png",
"java/res/drawable-xhdpi/ic_delete_white_24dp.png",
"java/res/drawable-xhdpi/ic_edit_24dp.png",
"java/res/drawable-xhdpi/ic_folder_blue_24dp.png",
@@ -92,6 +95,7 @@ android_resources("java_resources") {
"java/res/drawable-xhdpi/top_round_foreground.9.png",
"java/res/drawable-xhdpi/top_round_shadow.9.png",
"java/res/drawable-xxhdpi/btn_star_filled.png",
+ "java/res/drawable-xxhdpi/ic_chrome.png",
"java/res/drawable-xxhdpi/ic_delete_white_24dp.png",
"java/res/drawable-xxhdpi/ic_edit_24dp.png",
"java/res/drawable-xxhdpi/ic_folder_blue_24dp.png",
@@ -112,6 +116,7 @@ android_resources("java_resources") {
"java/res/drawable-xxhdpi/top_round_foreground.9.png",
"java/res/drawable-xxhdpi/top_round_shadow.9.png",
"java/res/drawable-xxxhdpi/btn_star_filled.png",
+ "java/res/drawable-xxxhdpi/ic_chrome.png",
"java/res/drawable-xxxhdpi/ic_delete_white_24dp.png",
"java/res/drawable-xxxhdpi/ic_edit_24dp.png",
"java/res/drawable-xxxhdpi/ic_folder_blue_24dp.png",
diff --git a/chromium/components/browser_ui/webshare/DIR_METADATA b/chromium/components/browser_ui/webshare/DIR_METADATA
index 8875242bb0f..b5243d75f7b 100644
--- a/chromium/components/browser_ui/webshare/DIR_METADATA
+++ b/chromium/components/browser_ui/webshare/DIR_METADATA
@@ -2,4 +2,3 @@ monorail {
component: "Blink>WebShare"
}
-os: ANDROID
diff --git a/chromium/components/browser_ui/widget/android/BUILD.gn b/chromium/components/browser_ui/widget/android/BUILD.gn
index c574de52b17..ec8c8cd8aa4 100644
--- a/chromium/components/browser_ui/widget/android/BUILD.gn
+++ b/chromium/components/browser_ui/widget/android/BUILD.gn
@@ -270,6 +270,7 @@ android_library("javatests") {
"java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionAndAuxButtonTest.java",
"java/src/org/chromium/components/browser_ui/widget/RadioButtonWithDescriptionLayoutTest.java",
"java/src/org/chromium/components/browser_ui/widget/RadioButtonWithEditTextTest.java",
+ "java/src/org/chromium/components/browser_ui/widget/RadioButtonWithIconRenderTest.java",
"java/src/org/chromium/components/browser_ui/widget/RoundedIconGeneratorTest.java",
"java/src/org/chromium/components/browser_ui/widget/WrappingLayoutTest.java",
"java/src/org/chromium/components/browser_ui/widget/highlight/ViewHighlighterTest.java",
@@ -320,6 +321,7 @@ android_resources("java_test_resources") {
"test/java/res/layout/radio_button_with_description_and_aux_button_test.xml",
"test/java/res/layout/radio_button_with_description_layout_test.xml",
"test/java/res/layout/radio_button_with_edit_text_test.xml",
+ "test/java/res/layout/radio_button_with_icon_render_test.xml",
"test/java/res/values/strings.xml",
]
deps = [
diff --git a/chromium/components/browser_ui/widget/android/DIR_METADATA b/chromium/components/browser_ui/widget/android/DIR_METADATA
deleted file mode 100644
index 496d4121fe9..00000000000
--- a/chromium/components/browser_ui/widget/android/DIR_METADATA
+++ /dev/null
@@ -1,7 +0,0 @@
-monorail {
- component: "UI>Browser>Mobile"
-}
-
-team_email: "clank-app-team@google.com"
-
-os: ANDROID
diff --git a/chromium/components/browser_watcher/extended_crash_reporting.cc b/chromium/components/browser_watcher/extended_crash_reporting.cc
index 42eb53557e0..b79ba4f231b 100644
--- a/chromium/components/browser_watcher/extended_crash_reporting.cc
+++ b/chromium/components/browser_watcher/extended_crash_reporting.cc
@@ -11,6 +11,7 @@
#include "base/debug/activity_tracker.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/persistent_memory_allocator.h"
+#include "base/strings/string_piece.h"
#include "base/win/pe_image.h"
#include "build/build_config.h"
#include "components/browser_watcher/activity_data_names.h"
@@ -84,7 +85,7 @@ void RecordChromeModuleInfo(
module.file = "chrome.dll";
module.debug_file =
- base::StringPiece(pdb_filename, pdb_filename_length).as_string();
+ std::string(base::StringPiece(pdb_filename, pdb_filename_length));
global_tracker->RecordModuleInfo(module);
}
diff --git a/chromium/components/browsing_data/content/BUILD.gn b/chromium/components/browsing_data/content/BUILD.gn
index 2d0ff22eea9..74eebd44538 100644
--- a/chromium/components/browsing_data/content/BUILD.gn
+++ b/chromium/components/browsing_data/content/BUILD.gn
@@ -41,6 +41,7 @@ static_library("content") {
"//components/content_settings/core/common",
"//components/no_state_prefetch/browser",
"//components/prefs",
+ "//components/services/storage/public/cpp",
"//components/site_isolation",
"//content/public/browser",
"//net",
@@ -97,6 +98,7 @@ source_set("test_support") {
deps = [
":content",
"//base",
+ "//components/services/storage/public/cpp",
"//content/public/browser",
"//testing/gtest",
"//url",
diff --git a/chromium/components/browsing_data/content/appcache_helper_unittest.cc b/chromium/components/browsing_data/content/appcache_helper_unittest.cc
index 903f63894cf..581c8a18415 100644
--- a/chromium/components/browsing_data/content/appcache_helper_unittest.cc
+++ b/chromium/components/browsing_data/content/appcache_helper_unittest.cc
@@ -37,8 +37,7 @@ class CannedAppCacheHelperTest : public testing::Test {
protected:
scoped_refptr<CannedAppCacheHelper> CreateHelper() {
return base::MakeRefCounted<CannedAppCacheHelper>(
- content::BrowserContext::GetDefaultStoragePartition(&browser_context_)
- ->GetAppCacheService());
+ browser_context_.GetDefaultStoragePartition()->GetAppCacheService());
}
static bool ContainsOrigin(
diff --git a/chromium/components/browsing_data/content/browsing_data_helper.cc b/chromium/components/browsing_data/content/browsing_data_helper.cc
index 8c278f5b26a..dcb4dc623cc 100644
--- a/chromium/components/browsing_data/content/browsing_data_helper.cc
+++ b/chromium/components/browsing_data/content/browsing_data_helper.cc
@@ -81,6 +81,7 @@ void RemovePrerenderCacheData(
void RemoveSiteIsolationData(PrefService* prefs) {
prefs->ClearPref(site_isolation::prefs::kUserTriggeredIsolatedOrigins);
+ prefs->ClearPref(site_isolation::prefs::kWebTriggeredIsolatedOrigins);
// Note that this does not clear these sites from the in-memory map in
// ChildProcessSecurityPolicy, since that is not supported at runtime. That
// list of isolated sites is not directly exposed to users, though, and
@@ -145,6 +146,14 @@ void RemoveSiteSettingsData(const base::Time& delete_begin,
ContentSettingsType::BLUETOOTH_CHOOSER_DATA, delete_begin, delete_end,
HostContentSettingsMap::PatternSourcePredicate());
+ host_content_settings_map->ClearSettingsForOneTypeWithPredicate(
+ ContentSettingsType::FEDERATED_IDENTITY_REQUEST, delete_begin, delete_end,
+ HostContentSettingsMap::PatternSourcePredicate());
+
+ host_content_settings_map->ClearSettingsForOneTypeWithPredicate(
+ ContentSettingsType::FEDERATED_IDENTITY_SHARING, delete_begin, delete_end,
+ HostContentSettingsMap::PatternSourcePredicate());
+
#if !defined(OS_ANDROID)
host_content_settings_map->ClearSettingsForOneTypeWithPredicate(
ContentSettingsType::SERIAL_CHOOSER_DATA, delete_begin, delete_end,
@@ -153,6 +162,10 @@ void RemoveSiteSettingsData(const base::Time& delete_begin,
host_content_settings_map->ClearSettingsForOneTypeWithPredicate(
ContentSettingsType::HID_CHOOSER_DATA, delete_begin, delete_end,
HostContentSettingsMap::PatternSourcePredicate());
+
+ host_content_settings_map->ClearSettingsForOneTypeWithPredicate(
+ ContentSettingsType::FILE_SYSTEM_ACCESS_CHOOSER_DATA, delete_begin,
+ delete_end, HostContentSettingsMap::PatternSourcePredicate());
#endif
}
diff --git a/chromium/components/browsing_data/content/cache_storage_helper.h b/chromium/components/browsing_data/content/cache_storage_helper.h
index e3fd4e0d0d5..7449cc737ae 100644
--- a/chromium/components/browsing_data/content/cache_storage_helper.h
+++ b/chromium/components/browsing_data/content/cache_storage_helper.h
@@ -14,7 +14,6 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
#include "url/origin.h"
namespace content {
diff --git a/chromium/components/browsing_data/content/cache_storage_helper_browsertest.cc b/chromium/components/browsing_data/content/cache_storage_helper_browsertest.cc
index 5915d91de78..e8e901e24f5 100644
--- a/chromium/components/browsing_data/content/cache_storage_helper_browsertest.cc
+++ b/chromium/components/browsing_data/content/cache_storage_helper_browsertest.cc
@@ -27,8 +27,10 @@ using TestCompletionCallback =
class CacheStorageHelperTest : public content::ContentBrowserTest {
public:
content::StoragePartition* storage_partition() const {
- return content::BrowserContext::GetDefaultStoragePartition(
- shell()->web_contents()->GetBrowserContext());
+ return shell()
+ ->web_contents()
+ ->GetBrowserContext()
+ ->GetDefaultStoragePartition();
}
scoped_refptr<CannedCacheStorageHelper> MakeHelper() {
diff --git a/chromium/components/browsing_data/content/cache_storage_helper_unittest.cc b/chromium/components/browsing_data/content/cache_storage_helper_unittest.cc
index c4164f68300..6db861f10d2 100644
--- a/chromium/components/browsing_data/content/cache_storage_helper_unittest.cc
+++ b/chromium/components/browsing_data/content/cache_storage_helper_unittest.cc
@@ -19,8 +19,7 @@ namespace {
class CannedCacheStorageHelperTest : public testing::Test {
public:
content::StoragePartition* storage_partition() {
- return content::BrowserContext::GetDefaultStoragePartition(
- &browser_context_);
+ return browser_context_.GetDefaultStoragePartition();
}
scoped_refptr<CannedCacheStorageHelper> MakeHelper() {
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 bbab52fa5fa..9003810233a 100644
--- a/chromium/components/browsing_data/content/conditional_cache_counting_helper.h
+++ b/chromium/components/browsing_data/content/conditional_cache_counting_helper.h
@@ -2,10 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_BROWSING_DATA_CONTENT_CONTENT_CONDITIONAL_CACHE_COUNTING_HELPER_H_
-#define COMPONENTS_BROWSING_DATA_CONTENT_CONTENT_CONDITIONAL_CACHE_COUNTING_HELPER_H_
-
-#include <memory>
+#ifndef COMPONENTS_BROWSING_DATA_CONTENT_CONDITIONAL_CACHE_COUNTING_HELPER_H_
+#define COMPONENTS_BROWSING_DATA_CONTENT_CONDITIONAL_CACHE_COUNTING_HELPER_H_
#include "base/callback_forward.h"
#include "base/sequenced_task_runner_helpers.h"
@@ -40,4 +38,4 @@ class ConditionalCacheCountingHelper {
} // namespace browsing_data
-#endif // COMPONENTS_BROWSING_DATA_CONTENT_CONTENT_CONDITIONAL_CACHE_COUNTING_HELPER_H_
+#endif // COMPONENTS_BROWSING_DATA_CONTENT_CONDITIONAL_CACHE_COUNTING_HELPER_H_
diff --git a/chromium/components/browsing_data/content/cookie_helper.h b/chromium/components/browsing_data/content/cookie_helper.h
index 99bd6da1335..799e975c9cd 100644
--- a/chromium/components/browsing_data/content/cookie_helper.h
+++ b/chromium/components/browsing_data/content/cookie_helper.h
@@ -8,7 +8,6 @@
#include <stddef.h>
#include <map>
-#include <string>
#include "base/callback.h"
#include "base/callback_forward.h"
diff --git a/chromium/components/browsing_data/content/cookie_helper_unittest.cc b/chromium/components/browsing_data/content/cookie_helper_unittest.cc
index f8453789032..7ff55e8714e 100644
--- a/chromium/components/browsing_data/content/cookie_helper_unittest.cc
+++ b/chromium/components/browsing_data/content/cookie_helper_unittest.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/time/time.h"
@@ -18,6 +17,7 @@
#include "net/cookies/cookie_options.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace browsing_data {
namespace {
@@ -114,7 +114,7 @@ class CookieHelperTest : public testing::Test {
}
void CreateCookiesForTest() {
- base::Optional<base::Time> server_time = base::nullopt;
+ absl::optional<base::Time> server_time = absl::nullopt;
GURL cookie1_source("https://www.google.com");
auto cookie1 = net::CanonicalCookie::Create(cookie1_source, "A=1",
base::Time::Now(), server_time);
@@ -133,7 +133,7 @@ class CookieHelperTest : public testing::Test {
}
void CreateCookiesForDomainCookieTest() {
- base::Optional<base::Time> server_time = base::nullopt;
+ absl::optional<base::Time> server_time = absl::nullopt;
GURL cookie_source("https://www.google.com");
auto cookie1 = net::CanonicalCookie::Create(cookie_source, "A=1",
base::Time::Now(), server_time);
@@ -218,8 +218,7 @@ class CookieHelperTest : public testing::Test {
}
content::StoragePartition* storage_partition() {
- return content::BrowserContext::GetDefaultStoragePartition(
- testing_browser_context_.get());
+ return testing_browser_context_->GetDefaultStoragePartition();
}
protected:
@@ -302,7 +301,7 @@ TEST_F(CookieHelperTest, CannedDeleteCookie) {
const GURL origin1("http://www.google.com");
std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
- origin1, "A=1", base::Time::Now(), base::nullopt /* server_time */));
+ origin1, "A=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie1);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin1,
@@ -310,7 +309,7 @@ TEST_F(CookieHelperTest, CannedDeleteCookie) {
{*cookie1}});
const GURL origin2("http://www.gmail.google.com");
std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
- origin2, "B=1", base::Time::Now(), base::nullopt /* server_time */));
+ origin2, "B=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie2);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin2,
@@ -340,7 +339,7 @@ TEST_F(CookieHelperTest, CannedDomainCookie) {
ASSERT_TRUE(helper->empty());
std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
- origin, "A=1", base::Time::Now(), base::nullopt /* server_time */));
+ origin, "A=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie1);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -348,7 +347,7 @@ TEST_F(CookieHelperTest, CannedDomainCookie) {
{*cookie1}});
std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
origin, "A=1; Domain=.www.google.com", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(cookie2);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -376,7 +375,7 @@ TEST_F(CookieHelperTest, CannedUnique) {
ASSERT_TRUE(helper->empty());
std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
- origin, "A=1", base::Time::Now(), base::nullopt /* server_time */));
+ origin, "A=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie);
helper->AddCookies(
{content::CookieAccessDetails::Type::kChange, origin, origin, {*cookie}});
@@ -405,14 +404,14 @@ TEST_F(CookieHelperTest, CannedReplaceCookie) {
ASSERT_TRUE(helper->empty());
std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
- origin, "A=1", base::Time::Now(), base::nullopt /* server_time */));
+ origin, "A=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie1);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
origin,
{*cookie1}});
std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
- origin, "A=2", base::Time::Now(), base::nullopt /* server_time */));
+ origin, "A=2", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie2);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -420,7 +419,7 @@ TEST_F(CookieHelperTest, CannedReplaceCookie) {
{*cookie2}});
std::unique_ptr<net::CanonicalCookie> cookie3(net::CanonicalCookie::Create(
origin, "A=3; Path=/example/0", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(cookie3);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -428,7 +427,7 @@ TEST_F(CookieHelperTest, CannedReplaceCookie) {
{*cookie3}});
std::unique_ptr<net::CanonicalCookie> cookie4(net::CanonicalCookie::Create(
origin, "A=4; Path=/example/0", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(cookie4);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -436,7 +435,7 @@ TEST_F(CookieHelperTest, CannedReplaceCookie) {
{*cookie4}});
std::unique_ptr<net::CanonicalCookie> cookie5(net::CanonicalCookie::Create(
origin, "A=5; Domain=google.com", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(cookie5);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -444,7 +443,7 @@ TEST_F(CookieHelperTest, CannedReplaceCookie) {
{*cookie5}});
std::unique_ptr<net::CanonicalCookie> cookie6(net::CanonicalCookie::Create(
origin, "A=6; Domain=google.com", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(cookie6);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -452,7 +451,7 @@ TEST_F(CookieHelperTest, CannedReplaceCookie) {
{*cookie6}});
std::unique_ptr<net::CanonicalCookie> cookie7(net::CanonicalCookie::Create(
origin, "A=7; Domain=google.com; Path=/example/1", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(cookie7);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -460,7 +459,7 @@ TEST_F(CookieHelperTest, CannedReplaceCookie) {
{*cookie7}});
std::unique_ptr<net::CanonicalCookie> cookie8(net::CanonicalCookie::Create(
origin, "A=8; Domain=google.com; Path=/example/1", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(cookie8);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -469,7 +468,7 @@ TEST_F(CookieHelperTest, CannedReplaceCookie) {
std::unique_ptr<net::CanonicalCookie> cookie9(net::CanonicalCookie::Create(
origin, "A=9; Domain=www.google.com", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(cookie9);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -477,7 +476,7 @@ TEST_F(CookieHelperTest, CannedReplaceCookie) {
{*cookie9}});
std::unique_ptr<net::CanonicalCookie> cookie10(net::CanonicalCookie::Create(
origin, "A=10; Domain=www.google.com", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(cookie10);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
origin,
@@ -508,7 +507,7 @@ TEST_F(CookieHelperTest, CannedEmpty) {
ASSERT_TRUE(helper->empty());
std::unique_ptr<net::CanonicalCookie> changed_cookie(
net::CanonicalCookie::Create(url_google, "a=1", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(changed_cookie);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
url_google,
@@ -520,7 +519,7 @@ TEST_F(CookieHelperTest, CannedEmpty) {
net::CookieList cookies;
std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
- url_google, "a=1", base::Time::Now(), base::nullopt /* server_time */));
+ url_google, "a=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie);
cookies.push_back(*cookie);
@@ -541,21 +540,21 @@ TEST_F(CookieHelperTest, CannedDifferentFrames) {
ASSERT_TRUE(helper->empty());
std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
- request_url, "a=1", base::Time::Now(), base::nullopt /* server_time */));
+ request_url, "a=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie1);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
frame1_url,
request_url,
{*cookie1}});
std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
- request_url, "b=1", base::Time::Now(), base::nullopt /* server_time */));
+ request_url, "b=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie2);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
frame1_url,
request_url,
{*cookie2}});
std::unique_ptr<net::CanonicalCookie> cookie3(net::CanonicalCookie::Create(
- request_url, "c=1", base::Time::Now(), base::nullopt /* server_time */));
+ request_url, "c=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie3);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
frame1_url,
@@ -588,7 +587,7 @@ TEST_F(CookieHelperTest, CannedGetCookieCount) {
// cookies.
EXPECT_EQ(0U, helper->GetCookieCount());
std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
- frame1_url, "A=1", base::Time::Now(), base::nullopt /* server_time */));
+ frame1_url, "A=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie1);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
frame1_url,
@@ -596,7 +595,7 @@ TEST_F(CookieHelperTest, CannedGetCookieCount) {
{*cookie1}});
EXPECT_EQ(1U, helper->GetCookieCount());
std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
- frame1_url, "B=1", base::Time::Now(), base::nullopt /* server_time */));
+ frame1_url, "B=1", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie2);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
frame1_url,
@@ -610,7 +609,7 @@ TEST_F(CookieHelperTest, CannedGetCookieCount) {
// request to |frame1_url| is updated.
// The cookie-name of |cookie3| must match the cookie-name of |cookie1|.
std::unique_ptr<net::CanonicalCookie> cookie3(net::CanonicalCookie::Create(
- frame1_url, "A=2", base::Time::Now(), base::nullopt /* server_time */));
+ frame1_url, "A=2", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie3);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
frame2_url,
@@ -622,7 +621,7 @@ TEST_F(CookieHelperTest, CannedGetCookieCount) {
// below have a differnt path-value since the request URLs have different
// paths.
std::unique_ptr<net::CanonicalCookie> cookie4(net::CanonicalCookie::Create(
- request1_url, "A=2", base::Time::Now(), base::nullopt /* server_time */));
+ request1_url, "A=2", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie4);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
frame2_url,
@@ -630,7 +629,7 @@ TEST_F(CookieHelperTest, CannedGetCookieCount) {
{*cookie4}});
EXPECT_EQ(3U, helper->GetCookieCount());
std::unique_ptr<net::CanonicalCookie> cookie5(net::CanonicalCookie::Create(
- request2_url, "A=2", base::Time::Now(), base::nullopt /* server_time */));
+ request2_url, "A=2", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie5);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
frame2_url,
@@ -646,7 +645,7 @@ TEST_F(CookieHelperTest, CannedGetCookieCount) {
// Add a domain cookie and check if it increases the cookie count.
std::unique_ptr<net::CanonicalCookie> cookie6(net::CanonicalCookie::Create(
frame1_url, "A=3; Domain=.www.google.com", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(cookie6);
helper->AddCookies({content::CookieAccessDetails::Type::kChange,
frame2_url,
diff --git a/chromium/components/browsing_data/content/database_helper.cc b/chromium/components/browsing_data/content/database_helper.cc
index f828be94a53..248c33a2f69 100644
--- a/chromium/components/browsing_data/content/database_helper.cc
+++ b/chromium/components/browsing_data/content/database_helper.cc
@@ -35,8 +35,9 @@ using storage::DatabaseIdentifier;
namespace browsing_data {
DatabaseHelper::DatabaseHelper(content::BrowserContext* browser_context)
- : tracker_(BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetDatabaseTracker()) {}
+ : tracker_(
+ browser_context->GetDefaultStoragePartition()->GetDatabaseTracker()) {
+}
DatabaseHelper::~DatabaseHelper() {}
diff --git a/chromium/components/browsing_data/content/database_helper.h b/chromium/components/browsing_data/content/database_helper.h
index 12ec3960998..d3f05a0e4a8 100644
--- a/chromium/components/browsing_data/content/database_helper.h
+++ b/chromium/components/browsing_data/content/database_helper.h
@@ -10,12 +10,10 @@
#include <list>
#include <set>
-#include <string>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
#include "storage/browser/database/database_tracker.h"
#include "storage/common/database/database_identifier.h"
#include "url/gurl.h"
diff --git a/chromium/components/browsing_data/content/database_helper_browsertest.cc b/chromium/components/browsing_data/content/database_helper_browsertest.cc
index 905e69a2e4e..17b9f504970 100644
--- a/chromium/components/browsing_data/content/database_helper_browsertest.cc
+++ b/chromium/components/browsing_data/content/database_helper_browsertest.cc
@@ -31,7 +31,6 @@
#include "url/origin.h"
using content::BrowserContext;
-using content::BrowserThread;
namespace browsing_data {
namespace {
@@ -43,19 +42,14 @@ const char kTestIdentifier1[] = "http_www.example.com_0";
const char kTestIdentifierExtension[] =
"chrome-extension_behllobkkfkfnphdnhnkndlbkcpglgmj_0";
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-url::Origin TestOrigin() {
- return url::Origin::Create(GURL("http://www.example.com"));
-}
-
class DatabaseHelperTest : public content::ContentBrowserTest {
public:
virtual void CreateDatabases() {
- storage::DatabaseTracker* db_tracker =
- BrowserContext::GetDefaultStoragePartition(
- shell()->web_contents()->GetBrowserContext())
- ->GetDatabaseTracker();
+ storage::DatabaseTracker* db_tracker = shell()
+ ->web_contents()
+ ->GetBrowserContext()
+ ->GetDefaultStoragePartition()
+ ->GetDatabaseTracker();
base::RunLoop run_loop;
db_tracker->task_runner()->PostTaskAndReply(
FROM_HERE, base::BindLambdaForTesting([&]() {
@@ -87,8 +81,8 @@ class DatabaseHelperTest : public content::ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(DatabaseHelperTest, FetchData) {
CreateDatabases();
- scoped_refptr<DatabaseHelper> database_helper(
- new DatabaseHelper(shell()->web_contents()->GetBrowserContext()));
+ auto database_helper = base::MakeRefCounted<DatabaseHelper>(
+ shell()->web_contents()->GetBrowserContext());
std::list<content::StorageUsageInfo> database_info_list;
base::RunLoop run_loop;
database_helper->StartFetching(base::BindLambdaForTesting(
@@ -97,44 +91,45 @@ IN_PROC_BROWSER_TEST_F(DatabaseHelperTest, FetchData) {
run_loop.Quit();
}));
run_loop.Run();
- ASSERT_EQ(1UL, database_info_list.size());
- EXPECT_EQ(TestOrigin(), database_info_list.begin()->origin);
+ ASSERT_EQ(1u, database_info_list.size());
+ EXPECT_EQ(url::Origin::Create(GURL("http://www.example.com")),
+ database_info_list.begin()->origin);
}
IN_PROC_BROWSER_TEST_F(DatabaseHelperTest, CannedAddDatabase) {
const url::Origin origin1 = url::Origin::Create(GURL("http://host1:1/"));
const url::Origin origin2 = url::Origin::Create(GURL("http://host2:1/"));
- scoped_refptr<CannedDatabaseHelper> helper(
- new CannedDatabaseHelper(shell()->web_contents()->GetBrowserContext()));
- helper->Add(origin1);
- helper->Add(origin1);
- helper->Add(origin2);
+ auto database_helper = base::MakeRefCounted<CannedDatabaseHelper>(
+ shell()->web_contents()->GetBrowserContext());
+ database_helper->Add(origin1);
+ database_helper->Add(origin1);
+ database_helper->Add(origin2);
TestCompletionCallback callback;
- helper->StartFetching(base::BindOnce(&TestCompletionCallback::callback,
- base::Unretained(&callback)));
+ database_helper->StartFetching(base::BindOnce(
+ &TestCompletionCallback::callback, base::Unretained(&callback)));
std::list<content::StorageUsageInfo> result = callback.result();
ASSERT_EQ(2u, result.size());
auto info = result.begin();
EXPECT_EQ(origin1, info->origin);
- info++;
+ ++info;
EXPECT_EQ(origin2, info->origin);
}
IN_PROC_BROWSER_TEST_F(DatabaseHelperTest, CannedUnique) {
const url::Origin origin = url::Origin::Create(GURL("http://host1:1/"));
- scoped_refptr<CannedDatabaseHelper> helper(
- new CannedDatabaseHelper(shell()->web_contents()->GetBrowserContext()));
- helper->Add(origin);
- helper->Add(origin);
+ auto database_helper = base::MakeRefCounted<CannedDatabaseHelper>(
+ shell()->web_contents()->GetBrowserContext());
+ database_helper->Add(origin);
+ database_helper->Add(origin);
TestCompletionCallback callback;
- helper->StartFetching(base::BindOnce(&TestCompletionCallback::callback,
- base::Unretained(&callback)));
+ database_helper->StartFetching(base::BindOnce(
+ &TestCompletionCallback::callback, base::Unretained(&callback)));
std::list<content::StorageUsageInfo> result = callback.result();
diff --git a/chromium/components/browsing_data/content/file_system_helper_unittest.cc b/chromium/components/browsing_data/content/file_system_helper_unittest.cc
index 5e8af0b07c1..cd4b841501d 100644
--- a/chromium/components/browsing_data/content/file_system_helper_unittest.cc
+++ b/chromium/components/browsing_data/content/file_system_helper_unittest.cc
@@ -41,29 +41,6 @@ const int kEmptyFileSystemSize = 0;
using FileSystemInfoList = std::list<FileSystemHelper::FileSystemInfo>;
-// We'll use these three distinct origins for testing, both as strings and as
-// Origins in appropriate contexts.
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-url::Origin Origin1() {
- return url::Origin::Create(GURL("http://host1:1"));
-}
-url::Origin Origin2() {
- return url::Origin::Create(GURL("http://host2:2"));
-}
-url::Origin Origin3() {
- return url::Origin::Create(GURL("http://host3:3"));
-}
-
-// Extensions and Devtools should be ignored.
-url::Origin OriginExt() {
- return url::Origin::Create(
- GURL("chrome-extension://abcdefghijklmnopqrstuvwxyz"));
-}
-url::Origin OriginDevTools() {
- return url::Origin::Create(GURL("devtools://abcdefghijklmnopqrstuvw"));
-}
-
// The FileSystem APIs are all asynchronous; this testing class wraps up the
// boilerplate code necessary to deal with waiting for responses. In a nutshell,
// any async call whose response we want to test ought to create a base::RunLoop
@@ -73,11 +50,9 @@ class FileSystemHelperTest : public testing::Test {
public:
FileSystemHelperTest() {
auto* file_system_context =
- BrowserContext::GetDefaultStoragePartition(&browser_context_)
- ->GetFileSystemContext();
+ browser_context_.GetDefaultStoragePartition()->GetFileSystemContext();
auto* native_io_context =
- BrowserContext::GetDefaultStoragePartition(&browser_context_)
- ->GetNativeIOContext();
+ browser_context_.GetDefaultStoragePartition()->GetNativeIOContext();
helper_ =
FileSystemHelper::Create(file_system_context, {}, native_io_context);
content::RunAllTasksUntilIdle();
@@ -105,7 +80,7 @@ class FileSystemHelperTest : public testing::Test {
storage::FileSystemType type,
storage::OpenFileSystemMode open_mode) {
base::RunLoop run_loop;
- BrowserContext::GetDefaultStoragePartition(&browser_context_)
+ browser_context_.GetDefaultStoragePartition()
->GetFileSystemContext()
->OpenFileSystem(
origin, type, open_mode,
@@ -157,20 +132,23 @@ class FileSystemHelperTest : public testing::Test {
BlockUntilQuit(&run_loop);
}
- // Sets up Origin1() with a temporary file system, Origin2() with a persistent
- // file system, and Origin3() with both.
- virtual void PopulateTestFileSystemData() {
- CreateDirectoryForOriginAndType(Origin1(), kTemporary);
- CreateDirectoryForOriginAndType(Origin2(), kPersistent);
- CreateDirectoryForOriginAndType(Origin3(), kTemporary);
- CreateDirectoryForOriginAndType(Origin3(), kPersistent);
-
- EXPECT_FALSE(FileSystemContainsOriginAndType(Origin1(), kPersistent));
- EXPECT_TRUE(FileSystemContainsOriginAndType(Origin1(), kTemporary));
- EXPECT_TRUE(FileSystemContainsOriginAndType(Origin2(), kPersistent));
- EXPECT_FALSE(FileSystemContainsOriginAndType(Origin2(), kTemporary));
- EXPECT_TRUE(FileSystemContainsOriginAndType(Origin3(), kPersistent));
- EXPECT_TRUE(FileSystemContainsOriginAndType(Origin3(), kTemporary));
+ // Sets up |origin1| with a temporary file system, |origin2| with a persistent
+ // file system, and |origin3| with both.
+ virtual void PopulateTestFileSystemData(const url::Origin& origin1,
+ const url::Origin& origin2,
+ const url::Origin& origin3) {
+ CreateDirectoryForOriginAndType(origin1, kTemporary);
+ EXPECT_FALSE(FileSystemContainsOriginAndType(origin1, kPersistent));
+ EXPECT_TRUE(FileSystemContainsOriginAndType(origin1, kTemporary));
+
+ CreateDirectoryForOriginAndType(origin2, kPersistent);
+ EXPECT_TRUE(FileSystemContainsOriginAndType(origin2, kPersistent));
+ EXPECT_FALSE(FileSystemContainsOriginAndType(origin2, kTemporary));
+
+ CreateDirectoryForOriginAndType(origin3, kTemporary);
+ CreateDirectoryForOriginAndType(origin3, kPersistent);
+ EXPECT_TRUE(FileSystemContainsOriginAndType(origin3, kPersistent));
+ EXPECT_TRUE(FileSystemContainsOriginAndType(origin3, kTemporary));
}
// Calls OpenFileSystem with OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT
@@ -204,29 +182,32 @@ class FileSystemHelperTest : public testing::Test {
// Verifies that the FileSystemHelper correctly finds the test file
// system data, and that each file system returned contains the expected data.
TEST_F(FileSystemHelperTest, FetchData) {
- PopulateTestFileSystemData();
+ const url::Origin origin1 = url::Origin::Create(GURL("http://host1:1"));
+ const url::Origin origin2 = url::Origin::Create(GURL("http://host2:2"));
+ const url::Origin origin3 = url::Origin::Create(GURL("http://host3:3"));
+ PopulateTestFileSystemData(origin1, origin2, origin3);
FetchFileSystems();
- EXPECT_EQ(3UL, file_system_info_list_->size());
+ EXPECT_EQ(3u, file_system_info_list_->size());
// Order is arbitrary, verify all three origins.
bool test_hosts_found[3] = {false, false, false};
for (const auto& info : *file_system_info_list_) {
- if (info.origin == Origin1()) {
+ if (info.origin == origin1) {
EXPECT_FALSE(test_hosts_found[0]);
test_hosts_found[0] = true;
EXPECT_FALSE(base::Contains(info.usage_map, kPersistent));
EXPECT_TRUE(base::Contains(info.usage_map, kTemporary));
EXPECT_EQ(kEmptyFileSystemSize,
info.usage_map.at(storage::kFileSystemTypeTemporary));
- } else if (info.origin == Origin2()) {
+ } else if (info.origin == origin2) {
EXPECT_FALSE(test_hosts_found[1]);
test_hosts_found[1] = true;
EXPECT_TRUE(base::Contains(info.usage_map, kPersistent));
EXPECT_FALSE(base::Contains(info.usage_map, kTemporary));
EXPECT_EQ(kEmptyFileSystemSize, info.usage_map.at(kPersistent));
- } else if (info.origin == Origin3()) {
+ } else if (info.origin == origin3) {
EXPECT_FALSE(test_hosts_found[2]);
test_hosts_found[2] = true;
EXPECT_TRUE(base::Contains(info.usage_map, kPersistent));
@@ -237,24 +218,27 @@ TEST_F(FileSystemHelperTest, FetchData) {
ADD_FAILURE() << info.origin.Serialize() << " isn't an origin we added.";
}
}
- for (size_t i = 0; i < base::size(test_hosts_found); i++) {
- EXPECT_TRUE(test_hosts_found[i]);
+ for (const auto found : test_hosts_found) {
+ EXPECT_TRUE(found);
}
}
// Verifies that the FileSystemHelper correctly deletes file
// systems via DeleteFileSystemOrigin().
TEST_F(FileSystemHelperTest, DeleteData) {
- PopulateTestFileSystemData();
+ const url::Origin origin1 = url::Origin::Create(GURL("http://host1:1"));
+ const url::Origin origin2 = url::Origin::Create(GURL("http://host2:2"));
+ const url::Origin origin3 = url::Origin::Create(GURL("http://host3:3"));
+ PopulateTestFileSystemData(origin1, origin2, origin3);
- helper_->DeleteFileSystemOrigin(Origin1());
- helper_->DeleteFileSystemOrigin(Origin2());
+ helper_->DeleteFileSystemOrigin(origin1);
+ helper_->DeleteFileSystemOrigin(origin2);
FetchFileSystems();
EXPECT_EQ(1UL, file_system_info_list_->size());
- FileSystemHelper::FileSystemInfo info = *(file_system_info_list_->begin());
- EXPECT_EQ(Origin3(), info.origin);
+ FileSystemHelper::FileSystemInfo info = file_system_info_list_->front();
+ EXPECT_EQ(origin3, info.origin);
EXPECT_TRUE(base::Contains(info.usage_map, kPersistent));
EXPECT_TRUE(base::Contains(info.usage_map, kTemporary));
EXPECT_EQ(kEmptyFileSystemSize, info.usage_map[kPersistent]);
@@ -265,7 +249,7 @@ TEST_F(FileSystemHelperTest, DeleteData) {
// whether or not it currently contains file systems.
TEST_F(FileSystemHelperTest, Empty) {
ASSERT_TRUE(canned_helper_->empty());
- canned_helper_->Add(Origin1());
+ canned_helper_->Add(url::Origin::Create(GURL("http://host1:1")));
ASSERT_FALSE(canned_helper_->empty());
canned_helper_->Reset();
ASSERT_TRUE(canned_helper_->empty());
@@ -274,19 +258,21 @@ TEST_F(FileSystemHelperTest, Empty) {
// Verifies that AddFileSystem correctly adds file systems. The canned helper
// does not record usage size.
TEST_F(FileSystemHelperTest, CannedAddFileSystem) {
- canned_helper_->Add(Origin1());
- canned_helper_->Add(Origin2());
+ const url::Origin origin1 = url::Origin::Create(GURL("http://host1:1"));
+ const url::Origin origin2 = url::Origin::Create(GURL("http://host2:2"));
+ canned_helper_->Add(origin1);
+ canned_helper_->Add(origin2);
FetchCannedFileSystems();
EXPECT_EQ(2U, file_system_info_list_->size());
auto info = file_system_info_list_->begin();
- EXPECT_EQ(Origin1(), info->origin);
+ EXPECT_EQ(origin1, info->origin);
EXPECT_FALSE(base::Contains(info->usage_map, kPersistent));
EXPECT_FALSE(base::Contains(info->usage_map, kTemporary));
- info++;
- EXPECT_EQ(Origin2(), info->origin);
+ ++info;
+ EXPECT_EQ(origin2, info->origin);
EXPECT_FALSE(base::Contains(info->usage_map, kPersistent));
EXPECT_FALSE(base::Contains(info->usage_map, kTemporary));
}
@@ -295,9 +281,11 @@ TEST_F(FileSystemHelperTest, CannedAddFileSystem) {
// extension and devtools schemes.
TEST_F(FileSystemHelperTest, IgnoreExtensionsAndDevTools) {
ASSERT_TRUE(canned_helper_->empty());
- canned_helper_->Add(OriginExt());
+ canned_helper_->Add(url::Origin::Create(
+ GURL("chrome-extension://abcdefghijklmnopqrstuvwxyz")));
ASSERT_TRUE(canned_helper_->empty());
- canned_helper_->Add(OriginDevTools());
+ canned_helper_->Add(
+ url::Origin::Create(GURL("devtools://abcdefghijklmnopqrstuvw")));
ASSERT_TRUE(canned_helper_->empty());
}
diff --git a/chromium/components/browsing_data/content/indexed_db_helper.h b/chromium/components/browsing_data/content/indexed_db_helper.h
index 428c6fadde8..86820bb067c 100644
--- a/chromium/components/browsing_data/content/indexed_db_helper.h
+++ b/chromium/components/browsing_data/content/indexed_db_helper.h
@@ -9,7 +9,6 @@
#include <list>
#include <set>
-#include <string>
#include "base/callback.h"
#include "base/macros.h"
diff --git a/chromium/components/browsing_data/content/indexed_db_helper_browsertest.cc b/chromium/components/browsing_data/content/indexed_db_helper_browsertest.cc
index 25dd0ed27e3..809a52520df 100644
--- a/chromium/components/browsing_data/content/indexed_db_helper_browsertest.cc
+++ b/chromium/components/browsing_data/content/indexed_db_helper_browsertest.cc
@@ -27,8 +27,10 @@ using TestCompletionCallback =
class IndexedDBHelperTest : public content::ContentBrowserTest {
public:
content::StoragePartition* StoragePartition() {
- return content::BrowserContext::GetDefaultStoragePartition(
- shell()->web_contents()->GetBrowserContext());
+ return shell()
+ ->web_contents()
+ ->GetBrowserContext()
+ ->GetDefaultStoragePartition();
}
};
diff --git a/chromium/components/browsing_data/content/indexed_db_helper_unittest.cc b/chromium/components/browsing_data/content/indexed_db_helper_unittest.cc
index d15f69e93fb..217fc726222 100644
--- a/chromium/components/browsing_data/content/indexed_db_helper_unittest.cc
+++ b/chromium/components/browsing_data/content/indexed_db_helper_unittest.cc
@@ -21,8 +21,7 @@ namespace {
class CannedIndexedDBHelperTest : public testing::Test {
public:
content::StoragePartition* StoragePartition() {
- return content::BrowserContext::GetDefaultStoragePartition(
- &browser_context_);
+ return browser_context_.GetDefaultStoragePartition();
}
private:
diff --git a/chromium/components/browsing_data/content/local_shared_objects_container.cc b/chromium/components/browsing_data/content/local_shared_objects_container.cc
index f6c6b87117d..6c15343049f 100644
--- a/chromium/components/browsing_data/content/local_shared_objects_container.cc
+++ b/chromium/components/browsing_data/content/local_shared_objects_container.cc
@@ -9,6 +9,7 @@
#include <utility>
#include <vector>
+#include "base/strings/string_piece.h"
#include "components/browsing_data/content/appcache_helper.h"
#include "components/browsing_data/content/cache_storage_helper.h"
#include "components/browsing_data/content/canonical_cookie_hash.h"
@@ -43,31 +44,25 @@ LocalSharedObjectsContainer::LocalSharedObjectsContainer(
const std::vector<storage::FileSystemType>& additional_file_system_types,
browsing_data::CookieHelper::IsDeletionDisabledCallback callback)
: appcaches_(new CannedAppCacheHelper(
- content::BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetAppCacheService())),
- cookies_(new CannedCookieHelper(
- content::BrowserContext::GetDefaultStoragePartition(browser_context),
- std::move(callback))),
+ browser_context->GetDefaultStoragePartition()->GetAppCacheService())),
+ cookies_(
+ new CannedCookieHelper(browser_context->GetDefaultStoragePartition(),
+ std::move(callback))),
databases_(new CannedDatabaseHelper(browser_context)),
file_systems_(new CannedFileSystemHelper(
- content::BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetFileSystemContext(),
+ browser_context->GetDefaultStoragePartition()->GetFileSystemContext(),
additional_file_system_types,
- content::BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetNativeIOContext())),
+ browser_context->GetDefaultStoragePartition()->GetNativeIOContext())),
indexed_dbs_(new CannedIndexedDBHelper(
- content::BrowserContext::GetDefaultStoragePartition(
- browser_context))),
+ browser_context->GetDefaultStoragePartition())),
local_storages_(new CannedLocalStorageHelper(browser_context)),
service_workers_(new CannedServiceWorkerHelper(
- content::BrowserContext::GetDefaultStoragePartition(browser_context)
+ browser_context->GetDefaultStoragePartition()
->GetServiceWorkerContext())),
shared_workers_(new CannedSharedWorkerHelper(
- content::BrowserContext::GetDefaultStoragePartition(
- browser_context))),
+ browser_context->GetDefaultStoragePartition())),
cache_storages_(new CannedCacheStorageHelper(
- content::BrowserContext::GetDefaultStoragePartition(
- browser_context))),
+ browser_context->GetDefaultStoragePartition())),
session_storages_(new CannedLocalStorageHelper(browser_context)) {}
LocalSharedObjectsContainer::~LocalSharedObjectsContainer() = default;
@@ -196,7 +191,7 @@ size_t LocalSharedObjectsContainer::GetDomainCount() const {
hosts.insert(origin.host());
for (const auto& info : shared_workers()->GetSharedWorkerInfo())
- hosts.insert(info.constructor_origin.host());
+ hosts.insert(info.storage_key.origin().host());
for (const auto& origin : cache_storages()->GetOrigins())
hosts.insert(origin.host());
@@ -217,7 +212,7 @@ size_t LocalSharedObjectsContainer::GetDomainCount() const {
if (!domain.empty())
domains.insert(std::move(domain));
else
- domains.insert(host.as_string());
+ domains.insert(std::string(host));
}
return domains.size();
}
diff --git a/chromium/components/browsing_data/content/local_storage_helper.cc b/chromium/components/browsing_data/content/local_storage_helper.cc
index 7cead138519..84775498bdf 100644
--- a/chromium/components/browsing_data/content/local_storage_helper.cc
+++ b/chromium/components/browsing_data/content/local_storage_helper.cc
@@ -50,8 +50,8 @@ void GetUsageInfoCallback(LocalStorageHelper::FetchCallback callback,
} // namespace
LocalStorageHelper::LocalStorageHelper(BrowserContext* context)
- : dom_storage_context_(BrowserContext::GetDefaultStoragePartition(context)
- ->GetDOMStorageContext()) {
+ : dom_storage_context_(
+ context->GetDefaultStoragePartition()->GetDOMStorageContext()) {
DCHECK(dom_storage_context_);
}
diff --git a/chromium/components/browsing_data/content/local_storage_helper.h b/chromium/components/browsing_data/content/local_storage_helper.h
index 50905a4912b..35e296de9e3 100644
--- a/chromium/components/browsing_data/content/local_storage_helper.h
+++ b/chromium/components/browsing_data/content/local_storage_helper.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_BROWSING_DATA_CONTENT_CONTENT_LOCAL_STORAGE_HELPER_H_
-#define COMPONENTS_BROWSING_DATA_CONTENT_CONTENT_LOCAL_STORAGE_HELPER_H_
+#ifndef COMPONENTS_BROWSING_DATA_CONTENT_LOCAL_STORAGE_HELPER_H_
+#define COMPONENTS_BROWSING_DATA_CONTENT_LOCAL_STORAGE_HELPER_H_
#include <stddef.h>
#include <stdint.h>
@@ -13,10 +13,8 @@
#include <set>
#include "base/callback.h"
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
#include "content/public/browser/dom_storage_context.h"
#include "content/public/browser/storage_usage_info.h"
#include "url/origin.h"
@@ -94,4 +92,4 @@ class CannedLocalStorageHelper : public LocalStorageHelper {
} // namespace browsing_data
-#endif // COMPONENTS_BROWSING_DATA_CONTENT_CONTENT_LOCAL_STORAGE_HELPER_H_
+#endif // COMPONENTS_BROWSING_DATA_CONTENT_LOCAL_STORAGE_HELPER_H_
diff --git a/chromium/components/browsing_data/content/local_storage_helper_browsertest.cc b/chromium/components/browsing_data/content/local_storage_helper_browsertest.cc
index e935d1581d3..b4900a1ed4d 100644
--- a/chromium/components/browsing_data/content/local_storage_helper_browsertest.cc
+++ b/chromium/components/browsing_data/content/local_storage_helper_browsertest.cc
@@ -7,28 +7,33 @@
#include <stddef.h>
#include <string>
+#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind.h"
#include "base/test/thread_test_helper.h"
#include "base/threading/thread_restrictions.h"
#include "components/browsing_data/content/browsing_data_helper_browsertest.h"
+#include "components/services/storage/public/mojom/local_storage_control.mojom.h"
+#include "components/services/storage/public/mojom/storage_usage_info.mojom.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/dom_storage_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
+#include "url/origin.h"
using content::BrowserContext;
using content::BrowserThread;
@@ -40,40 +45,44 @@ namespace {
using TestCompletionCallback =
BrowsingDataHelperCallback<content::StorageUsageInfo>;
-constexpr base::FilePath::CharType kTestFile0[] =
- FILE_PATH_LITERAL("http_www.chromium.org_0.localstorage");
+const char kOrigin1[] = "http://www.chromium.org";
+const char kOrigin2[] = "http://www.google.com";
+// This is only here to test that state for non-web-storage schemes is not
+// listed by the helper. Web storage schemes are http, https, file, ftp, ws,
+// and wss.
+const char kOrigin3[] = "chrome://settings";
-const char kOriginOfTestFile0[] = "http://www.chromium.org/";
-
-constexpr base::FilePath::CharType kTestFile1[] =
- FILE_PATH_LITERAL("http_www.google.com_0.localstorage");
-
-constexpr base::FilePath::CharType kTestFileInvalid[] =
- FILE_PATH_LITERAL("http_www.google.com_localstorage_0.foo");
-
-// This is only here to test that extension state is not listed by the helper.
-constexpr base::FilePath::CharType kTestFileExtension[] = FILE_PATH_LITERAL(
- "chrome-extension_behllobkkfkfnphdnhnkndlbkcpglgmj_0.localstorage");
+bool PutTestData(blink::mojom::StorageArea* area) {
+ base::RunLoop run_loop;
+ bool success = false;
+ area->Put({'k', 'e', 'y'}, {'v', 'a', 'l', 'u', 'e'}, absl::nullopt, "source",
+ base::BindLambdaForTesting([&](bool success_in) {
+ run_loop.Quit();
+ success = success_in;
+ }));
+ run_loop.Run();
+ return success;
+}
class LocalStorageHelperTest : public content::ContentBrowserTest {
protected:
- void CreateLocalStorageFilesForTest() {
- base::ScopedAllowBlockingForTesting allow_blocking;
- // Note: This helper depends on details of how the dom_storage library
- // stores data in the host file system.
- base::FilePath storage_path = GetLocalStoragePath();
- base::CreateDirectory(storage_path);
- static constexpr const base::FilePath::CharType* kFilesToCreate[] = {
- kTestFile0, kTestFile1, kTestFileInvalid, kTestFileExtension};
- for (size_t i = 0; i < base::size(kFilesToCreate); ++i) {
- base::FilePath file_path = storage_path.Append(kFilesToCreate[i]);
- base::WriteFile(file_path, nullptr, 0);
- }
+ storage::mojom::LocalStorageControl* GetLocalStorageControl() {
+ return shell()
+ ->web_contents()
+ ->GetBrowserContext()
+ ->GetDefaultStoragePartition()
+ ->GetLocalStorageControl();
}
- base::FilePath GetLocalStoragePath() {
- return shell()->web_contents()->GetBrowserContext()->GetPath().AppendASCII(
- "Local Storage");
+ void CreateLocalStorageDataForTest() {
+ for (const char* origin_str : {kOrigin1, kOrigin2, kOrigin3}) {
+ mojo::Remote<blink::mojom::StorageArea> area;
+ url::Origin origin = url::Origin::Create(GURL(origin_str));
+ ASSERT_FALSE(origin.opaque());
+ GetLocalStorageControl()->BindStorageArea(
+ origin, area.BindNewPipeAndPassReceiver());
+ ASSERT_TRUE(PutTestData(area.get()));
+ }
}
};
@@ -89,22 +98,22 @@ class StopTestOnCallback {
void Callback(
const std::list<content::StorageUsageInfo>& local_storage_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // There's no guarantee on the order, ensure these files are there.
- const char* const kTestHosts[] = {"www.chromium.org", "www.google.com"};
- bool test_hosts_found[base::size(kTestHosts)] = {false, false};
- ASSERT_EQ(base::size(kTestHosts), local_storage_info.size());
- for (size_t i = 0; i < base::size(kTestHosts); ++i) {
- for (const auto& info : local_storage_info) {
- ASSERT_EQ(info.origin.scheme(), "http");
- if (info.origin.host() == kTestHosts[i]) {
- ASSERT_FALSE(test_hosts_found[i]);
- test_hosts_found[i] = true;
- }
+ // There's no guarantee on the order, ensure each of the two http origins
+ // are there exactly once.
+ ASSERT_EQ(2u, local_storage_info.size());
+ bool origin1_found = false, origin2_found = false;
+ for (const auto& info : local_storage_info) {
+ if (info.origin.Serialize() == kOrigin1) {
+ EXPECT_FALSE(origin1_found);
+ origin1_found = true;
+ } else {
+ ASSERT_EQ(info.origin.Serialize(), kOrigin2);
+ EXPECT_FALSE(origin2_found);
+ origin2_found = true;
}
}
- for (size_t i = 0; i < base::size(kTestHosts); ++i) {
- ASSERT_TRUE(test_hosts_found[i]) << kTestHosts[i];
- }
+ EXPECT_TRUE(origin1_found);
+ EXPECT_TRUE(origin2_found);
base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
@@ -115,7 +124,7 @@ class StopTestOnCallback {
IN_PROC_BROWSER_TEST_F(LocalStorageHelperTest, CallbackCompletes) {
scoped_refptr<LocalStorageHelper> local_storage_helper(
new LocalStorageHelper(shell()->web_contents()->GetBrowserContext()));
- CreateLocalStorageFilesForTest();
+ CreateLocalStorageDataForTest();
StopTestOnCallback stop_test_on_callback(local_storage_helper.get());
local_storage_helper->StartFetching(base::BindOnce(
&StopTestOnCallback::Callback, base::Unretained(&stop_test_on_callback)));
@@ -123,27 +132,41 @@ IN_PROC_BROWSER_TEST_F(LocalStorageHelperTest, CallbackCompletes) {
content::RunMessageLoop();
}
-// Disable due to flaky. https://crbug.com/1028676
-IN_PROC_BROWSER_TEST_F(LocalStorageHelperTest, DISABLED_DeleteSingleFile) {
+IN_PROC_BROWSER_TEST_F(LocalStorageHelperTest, DeleteSingleOrigin) {
scoped_refptr<LocalStorageHelper> local_storage_helper(
new LocalStorageHelper(shell()->web_contents()->GetBrowserContext()));
- CreateLocalStorageFilesForTest();
- base::RunLoop run_loop;
- local_storage_helper->DeleteOrigin(
- url::Origin::Create(GURL(kOriginOfTestFile0)), run_loop.QuitClosure());
- run_loop.Run();
-
- // Ensure the file has been deleted.
- base::ScopedAllowBlockingForTesting allow_blocking;
- base::FileEnumerator file_enumerator(GetLocalStoragePath(), false,
- base::FileEnumerator::FILES);
- int num_files = 0;
- for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty();
- file_path = file_enumerator.Next()) {
- ASSERT_FALSE(base::FilePath(kTestFile0) == file_path.BaseName());
- ++num_files;
+ CreateLocalStorageDataForTest();
+ base::RunLoop delete_run_loop;
+ local_storage_helper->DeleteOrigin(url::Origin::Create(GURL(kOrigin1)),
+ delete_run_loop.QuitClosure());
+ delete_run_loop.Run();
+
+ // Ensure the origin has been deleted, but other origins are intact.
+ std::vector<storage::mojom::StorageUsageInfoPtr> usage_infos;
+ base::RunLoop get_usage_run_loop;
+ GetLocalStorageControl()->GetUsage(base::BindLambdaForTesting(
+ [&](std::vector<storage::mojom::StorageUsageInfoPtr> usage_infos_in) {
+ usage_infos.swap(usage_infos_in);
+ get_usage_run_loop.Quit();
+ }));
+ get_usage_run_loop.Run();
+
+ // There's no guarantee on the order, ensure each of the two non-deleted
+ // origins are there exactly once.
+ ASSERT_EQ(2u, usage_infos.size());
+ bool origin2_found = false, origin3_found = false;
+ for (const auto& info : usage_infos) {
+ if (info->origin.Serialize() == kOrigin2) {
+ EXPECT_FALSE(origin2_found);
+ origin2_found = true;
+ } else {
+ ASSERT_EQ(info->origin.Serialize(), kOrigin3);
+ EXPECT_FALSE(origin3_found);
+ origin3_found = true;
+ }
}
- ASSERT_EQ(3, num_files);
+ EXPECT_TRUE(origin2_found);
+ EXPECT_TRUE(origin3_found);
}
IN_PROC_BROWSER_TEST_F(LocalStorageHelperTest, CannedAddLocalStorage) {
diff --git a/chromium/components/browsing_data/content/mock_appcache_helper.cc b/chromium/components/browsing_data/content/mock_appcache_helper.cc
index e36fa7e5c4c..3bba18a937a 100644
--- a/chromium/components/browsing_data/content/mock_appcache_helper.cc
+++ b/chromium/components/browsing_data/content/mock_appcache_helper.cc
@@ -17,8 +17,8 @@ namespace browsing_data {
MockAppCacheHelper::MockAppCacheHelper(content::BrowserContext* browser_context)
: AppCacheHelper(
- content::BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetAppCacheService()) {}
+ browser_context->GetDefaultStoragePartition()->GetAppCacheService()) {
+}
MockAppCacheHelper::~MockAppCacheHelper() {}
diff --git a/chromium/components/browsing_data/content/mock_cache_storage_helper.cc b/chromium/components/browsing_data/content/mock_cache_storage_helper.cc
index d030c05adbd..2c4352ff4bb 100644
--- a/chromium/components/browsing_data/content/mock_cache_storage_helper.cc
+++ b/chromium/components/browsing_data/content/mock_cache_storage_helper.cc
@@ -15,8 +15,7 @@ namespace browsing_data {
MockCacheStorageHelper::MockCacheStorageHelper(
content::BrowserContext* browser_context)
- : CacheStorageHelper(content::BrowserContext::GetDefaultStoragePartition(
- browser_context)) {}
+ : CacheStorageHelper(browser_context->GetDefaultStoragePartition()) {}
MockCacheStorageHelper::~MockCacheStorageHelper() {}
diff --git a/chromium/components/browsing_data/content/mock_cookie_helper.cc b/chromium/components/browsing_data/content/mock_cookie_helper.cc
index 4ca273ed56d..c4cd385b507 100644
--- a/chromium/components/browsing_data/content/mock_cookie_helper.cc
+++ b/chromium/components/browsing_data/content/mock_cookie_helper.cc
@@ -8,18 +8,17 @@
#include "base/callback_helpers.h"
#include "base/containers/contains.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "content/public/browser/browser_context.h"
#include "net/cookies/cookie_options.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace browsing_data {
MockCookieHelper::MockCookieHelper(content::BrowserContext* browser_context)
- : CookieHelper(
- content::BrowserContext::GetDefaultStoragePartition(browser_context),
- base::NullCallback()) {}
+ : CookieHelper(browser_context->GetDefaultStoragePartition(),
+ base::NullCallback()) {}
MockCookieHelper::~MockCookieHelper() {}
@@ -38,7 +37,7 @@ void MockCookieHelper::DeleteCookie(const net::CanonicalCookie& cookie) {
void MockCookieHelper::AddCookieSamples(const GURL& url,
const std::string& cookie_line) {
std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create(
- url, cookie_line, base::Time::Now(), base::nullopt /* server_time */));
+ url, cookie_line, base::Time::Now(), absl::nullopt /* server_time */));
if (cc.get()) {
for (const auto& cookie : cookie_list_) {
diff --git a/chromium/components/browsing_data/content/mock_file_system_helper.cc b/chromium/components/browsing_data/content/mock_file_system_helper.cc
index 6c28ec5bcc9..cb5600ab669 100644
--- a/chromium/components/browsing_data/content/mock_file_system_helper.cc
+++ b/chromium/components/browsing_data/content/mock_file_system_helper.cc
@@ -16,11 +16,10 @@ namespace browsing_data {
MockFileSystemHelper::MockFileSystemHelper(
content::BrowserContext* browser_context)
: FileSystemHelper(
- content::BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetFileSystemContext(),
+ browser_context->GetDefaultStoragePartition()->GetFileSystemContext(),
{},
- content::BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetNativeIOContext()) {}
+ browser_context->GetDefaultStoragePartition()->GetNativeIOContext()) {
+}
MockFileSystemHelper::~MockFileSystemHelper() {}
diff --git a/chromium/components/browsing_data/content/mock_indexed_db_helper.cc b/chromium/components/browsing_data/content/mock_indexed_db_helper.cc
index 68591e24404..2bea3841349 100644
--- a/chromium/components/browsing_data/content/mock_indexed_db_helper.cc
+++ b/chromium/components/browsing_data/content/mock_indexed_db_helper.cc
@@ -16,8 +16,7 @@ namespace browsing_data {
MockIndexedDBHelper::MockIndexedDBHelper(
content::BrowserContext* browser_context)
- : IndexedDBHelper(content::BrowserContext::GetDefaultStoragePartition(
- browser_context)) {}
+ : IndexedDBHelper(browser_context->GetDefaultStoragePartition()) {}
MockIndexedDBHelper::~MockIndexedDBHelper() {}
diff --git a/chromium/components/browsing_data/content/mock_service_worker_helper.cc b/chromium/components/browsing_data/content/mock_service_worker_helper.cc
index 5d017a8ff81..adfc71d040c 100644
--- a/chromium/components/browsing_data/content/mock_service_worker_helper.cc
+++ b/chromium/components/browsing_data/content/mock_service_worker_helper.cc
@@ -17,9 +17,8 @@ namespace browsing_data {
MockServiceWorkerHelper::MockServiceWorkerHelper(
content::BrowserContext* browser_context)
- : ServiceWorkerHelper(
- content::BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetServiceWorkerContext()) {}
+ : ServiceWorkerHelper(browser_context->GetDefaultStoragePartition()
+ ->GetServiceWorkerContext()) {}
MockServiceWorkerHelper::~MockServiceWorkerHelper() {}
diff --git a/chromium/components/browsing_data/content/mock_shared_worker_helper.cc b/chromium/components/browsing_data/content/mock_shared_worker_helper.cc
index ddbb0013209..517b3feb61a 100644
--- a/chromium/components/browsing_data/content/mock_shared_worker_helper.cc
+++ b/chromium/components/browsing_data/content/mock_shared_worker_helper.cc
@@ -6,6 +6,7 @@
#include "base/callback.h"
#include "base/containers/contains.h"
+#include "components/services/storage/public/cpp/storage_key.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,8 +15,7 @@ namespace browsing_data {
MockSharedWorkerHelper::MockSharedWorkerHelper(
content::BrowserContext* browser_context)
- : SharedWorkerHelper(content::BrowserContext::GetDefaultStoragePartition(
- browser_context)) {}
+ : SharedWorkerHelper(browser_context->GetDefaultStoragePartition()) {}
MockSharedWorkerHelper::~MockSharedWorkerHelper() {}
@@ -28,8 +28,8 @@ void MockSharedWorkerHelper::StartFetching(FetchCallback callback) {
void MockSharedWorkerHelper::DeleteSharedWorker(
const GURL& worker,
const std::string& name,
- const url::Origin& constructor_origin) {
- SharedWorkerInfo key(worker, name, constructor_origin);
+ const storage::StorageKey& storage_key) {
+ SharedWorkerInfo key(worker, name, storage_key);
ASSERT_TRUE(base::Contains(workers_, key));
workers_[key] = false;
}
@@ -37,15 +37,15 @@ void MockSharedWorkerHelper::DeleteSharedWorker(
void MockSharedWorkerHelper::AddSharedWorkerSamples() {
GURL worker1("https://sharedworkerhost1:1/app/worker.js");
std::string name1("my worker");
- url::Origin constructor_origin1 = url::Origin::Create(worker1);
+ storage::StorageKey storage_key1(url::Origin::Create(worker1));
GURL worker2("https://sharedworkerhost2:2/worker.js");
std::string name2("another worker");
- url::Origin constructor_origin2 = url::Origin::Create(worker2);
+ storage::StorageKey storage_key2(url::Origin::Create(worker2));
- response_.push_back({worker1, name1, constructor_origin1});
- response_.push_back({worker2, name2, constructor_origin2});
- workers_[{worker1, name1, constructor_origin1}] = true;
- workers_[{worker2, name2, constructor_origin2}] = true;
+ response_.emplace_back(worker1, name1, storage_key1);
+ response_.emplace_back(worker2, name2, storage_key2);
+ workers_[{worker1, name1, storage_key1}] = true;
+ workers_[{worker2, name2, storage_key2}] = true;
}
void MockSharedWorkerHelper::Notify() {
diff --git a/chromium/components/browsing_data/content/mock_shared_worker_helper.h b/chromium/components/browsing_data/content/mock_shared_worker_helper.h
index f6a01e4c847..464f124c80e 100644
--- a/chromium/components/browsing_data/content/mock_shared_worker_helper.h
+++ b/chromium/components/browsing_data/content/mock_shared_worker_helper.h
@@ -14,6 +14,10 @@ namespace content {
class BrowserContext;
}
+namespace storage {
+class StorageKey;
+} // namespace storage
+
namespace browsing_data {
class MockSharedWorkerHelper : public SharedWorkerHelper {
@@ -37,7 +41,7 @@ class MockSharedWorkerHelper : public SharedWorkerHelper {
void StartFetching(FetchCallback callback) override;
void DeleteSharedWorker(const GURL& worker,
const std::string& name,
- const url::Origin& constructor_origin) override;
+ const storage::StorageKey& storage_key) override;
private:
~MockSharedWorkerHelper() override;
diff --git a/chromium/components/browsing_data/content/service_worker_helper_unittest.cc b/chromium/components/browsing_data/content/service_worker_helper_unittest.cc
index 9bb8ccec333..de4877d3026 100644
--- a/chromium/components/browsing_data/content/service_worker_helper_unittest.cc
+++ b/chromium/components/browsing_data/content/service_worker_helper_unittest.cc
@@ -20,8 +20,7 @@ namespace {
class CannedServiceWorkerHelperTest : public testing::Test {
public:
content::ServiceWorkerContext* ServiceWorkerContext() {
- return content::BrowserContext::GetDefaultStoragePartition(
- &browser_context_)
+ return browser_context_.GetDefaultStoragePartition()
->GetServiceWorkerContext();
}
diff --git a/chromium/components/browsing_data/content/shared_worker_helper.cc b/chromium/components/browsing_data/content/shared_worker_helper.cc
index 4c838c498cf..d9c10ae8c0e 100644
--- a/chromium/components/browsing_data/content/shared_worker_helper.cc
+++ b/chromium/components/browsing_data/content/shared_worker_helper.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "components/browsing_data/content/browsing_data_helper.h"
+#include "components/services/storage/public/cpp/storage_key.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/shared_worker_service.h"
@@ -20,8 +21,8 @@ namespace browsing_data {
SharedWorkerHelper::SharedWorkerInfo::SharedWorkerInfo(
const GURL& worker,
const std::string& name,
- const url::Origin& constructor_origin)
- : worker(worker), name(name), constructor_origin(constructor_origin) {}
+ const storage::StorageKey& storage_key)
+ : worker(worker), name(name), storage_key(storage_key) {}
SharedWorkerHelper::SharedWorkerInfo::SharedWorkerInfo(
const SharedWorkerInfo& other) = default;
@@ -30,8 +31,8 @@ SharedWorkerHelper::SharedWorkerInfo::~SharedWorkerInfo() = default;
bool SharedWorkerHelper::SharedWorkerInfo::operator<(
const SharedWorkerInfo& other) const {
- return std::tie(worker, name, constructor_origin) <
- std::tie(other.worker, other.name, other.constructor_origin);
+ return std::tie(worker, name, storage_key) <
+ std::tie(other.worker, other.name, other.storage_key);
}
SharedWorkerHelper::SharedWorkerHelper(
@@ -53,10 +54,10 @@ void SharedWorkerHelper::StartFetching(FetchCallback callback) {
void SharedWorkerHelper::DeleteSharedWorker(
const GURL& worker,
const std::string& name,
- const url::Origin& constructor_origin) {
+ const storage::StorageKey& storage_key) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- storage_partition_->GetSharedWorkerService()->TerminateWorker(
- worker, name, constructor_origin);
+ storage_partition_->GetSharedWorkerService()->TerminateWorker(worker, name,
+ storage_key);
}
CannedSharedWorkerHelper::CannedSharedWorkerHelper(
@@ -68,12 +69,12 @@ CannedSharedWorkerHelper::~CannedSharedWorkerHelper() = default;
void CannedSharedWorkerHelper::AddSharedWorker(
const GURL& worker,
const std::string& name,
- const url::Origin& constructor_origin) {
+ const storage::StorageKey& storage_key) {
if (!HasWebScheme(worker))
return; // Non-websafe state is not considered browsing data.
pending_shared_worker_info_.insert(
- SharedWorkerInfo(worker, name, constructor_origin));
+ SharedWorkerInfo(worker, name, storage_key));
}
void CannedSharedWorkerHelper::Reset() {
@@ -107,13 +108,13 @@ void CannedSharedWorkerHelper::StartFetching(FetchCallback callback) {
void CannedSharedWorkerHelper::DeleteSharedWorker(
const GURL& worker,
const std::string& name,
- const url::Origin& constructor_origin) {
+ const storage::StorageKey& storage_key) {
for (auto it = pending_shared_worker_info_.begin();
it != pending_shared_worker_info_.end();) {
if (it->worker == worker && it->name == name &&
- it->constructor_origin == constructor_origin) {
+ it->storage_key == storage_key) {
SharedWorkerHelper::DeleteSharedWorker(it->worker, it->name,
- it->constructor_origin);
+ it->storage_key);
it = pending_shared_worker_info_.erase(it);
} else {
++it;
diff --git a/chromium/components/browsing_data/content/shared_worker_helper.h b/chromium/components/browsing_data/content/shared_worker_helper.h
index ff00b0f0016..916a186a603 100644
--- a/chromium/components/browsing_data/content/shared_worker_helper.h
+++ b/chromium/components/browsing_data/content/shared_worker_helper.h
@@ -14,6 +14,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "components/services/storage/public/cpp/storage_key.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -33,7 +34,7 @@ class SharedWorkerHelper
struct SharedWorkerInfo {
SharedWorkerInfo(const GURL& worker,
const std::string& name,
- const url::Origin& constructor_origin);
+ const storage::StorageKey& storage_key);
SharedWorkerInfo(const SharedWorkerInfo& other);
~SharedWorkerInfo();
@@ -41,7 +42,7 @@ class SharedWorkerHelper
GURL worker;
std::string name;
- url::Origin constructor_origin;
+ storage::StorageKey storage_key;
};
using FetchCallback =
@@ -57,7 +58,7 @@ class SharedWorkerHelper
// Requests the given Shared Worker to be deleted.
virtual void DeleteSharedWorker(const GURL& worker,
const std::string& name,
- const url::Origin& constructor_origin);
+ const storage::StorageKey& storage_key);
protected:
virtual ~SharedWorkerHelper();
@@ -82,7 +83,7 @@ class CannedSharedWorkerHelper : public SharedWorkerHelper {
// this helper.
void AddSharedWorker(const GURL& worker,
const std::string& name,
- const url::Origin& constructor_origin);
+ const storage::StorageKey& storage_key);
// Clears the list of canned Shared Workers.
void Reset();
@@ -101,7 +102,7 @@ class CannedSharedWorkerHelper : public SharedWorkerHelper {
void StartFetching(FetchCallback callback) override;
void DeleteSharedWorker(const GURL& worker,
const std::string& name,
- const url::Origin& constructor_origin) override;
+ const storage::StorageKey& storage_key) override;
private:
~CannedSharedWorkerHelper() override;
diff --git a/chromium/components/browsing_data/content/shared_worker_helper_unittest.cc b/chromium/components/browsing_data/content/shared_worker_helper_unittest.cc
index edb167d2d17..be67e6bf31d 100644
--- a/chromium/components/browsing_data/content/shared_worker_helper_unittest.cc
+++ b/chromium/components/browsing_data/content/shared_worker_helper_unittest.cc
@@ -27,13 +27,14 @@ class CannedSharedWorkerHelperTest : public testing::Test {
TEST_F(CannedSharedWorkerHelperTest, Empty) {
const GURL worker("https://host1:1/worker.js");
std::string name("test");
- const url::Origin constructor_origin = url::Origin::Create(worker);
+ const storage::StorageKey storage_key =
+ storage::StorageKey(url::Origin::Create(worker));
auto helper = base::MakeRefCounted<CannedSharedWorkerHelper>(
- content::BrowserContext::GetDefaultStoragePartition(browser_context()));
+ browser_context()->GetDefaultStoragePartition());
EXPECT_TRUE(helper->empty());
- helper->AddSharedWorker(worker, name, constructor_origin);
+ helper->AddSharedWorker(worker, name, storage_key);
EXPECT_FALSE(helper->empty());
helper->Reset();
EXPECT_TRUE(helper->empty());
@@ -42,19 +43,19 @@ TEST_F(CannedSharedWorkerHelperTest, Empty) {
TEST_F(CannedSharedWorkerHelperTest, Delete) {
const GURL worker1("http://host1:9000/worker.js");
std::string name1("name");
- const url::Origin constructor_origin1 = url::Origin::Create(worker1);
+ const storage::StorageKey storage_key1(url::Origin::Create(worker1));
const GURL worker2("https://example.com/worker.js");
std::string name2("name");
- const url::Origin constructor_origin2 = url::Origin::Create(worker2);
+ const storage::StorageKey storage_key2(url::Origin::Create(worker2));
auto helper = base::MakeRefCounted<CannedSharedWorkerHelper>(
- content::BrowserContext::GetDefaultStoragePartition(browser_context()));
+ browser_context()->GetDefaultStoragePartition());
EXPECT_TRUE(helper->empty());
- helper->AddSharedWorker(worker1, name1, constructor_origin1);
- helper->AddSharedWorker(worker2, name2, constructor_origin2);
+ helper->AddSharedWorker(worker1, name1, storage_key1);
+ helper->AddSharedWorker(worker2, name2, storage_key2);
EXPECT_EQ(2u, helper->GetSharedWorkerCount());
- helper->DeleteSharedWorker(worker2, name2, constructor_origin2);
+ helper->DeleteSharedWorker(worker2, name2, storage_key2);
EXPECT_EQ(1u, helper->GetSharedWorkerCount());
}
@@ -62,16 +63,16 @@ TEST_F(CannedSharedWorkerHelperTest, IgnoreExtensionsAndDevTools) {
const GURL worker1("chrome-extension://abcdefghijklmnopqrstuvwxyz/worker.js");
const GURL worker2("devtools://abcdefghijklmnopqrstuvwxyz/worker.js");
std::string name("name");
- const url::Origin constructor_origin1 = url::Origin::Create(worker1);
- const url::Origin constructor_origin2 = url::Origin::Create(worker2);
+ const storage::StorageKey storage_key1(url::Origin::Create(worker1));
+ const storage::StorageKey storage_key2(url::Origin::Create(worker2));
auto helper = base::MakeRefCounted<CannedSharedWorkerHelper>(
- content::BrowserContext::GetDefaultStoragePartition(browser_context()));
+ browser_context()->GetDefaultStoragePartition());
EXPECT_TRUE(helper->empty());
- helper->AddSharedWorker(worker1, name, constructor_origin1);
+ helper->AddSharedWorker(worker1, name, storage_key1);
EXPECT_TRUE(helper->empty());
- helper->AddSharedWorker(worker2, name, constructor_origin2);
+ helper->AddSharedWorker(worker2, name, storage_key2);
EXPECT_TRUE(helper->empty());
}
diff --git a/chromium/components/browsing_data/core/counters/bookmark_counter.h b/chromium/components/browsing_data/core/counters/bookmark_counter.h
index cbf75e525e0..5fe25d48c73 100644
--- a/chromium/components/browsing_data/core/counters/bookmark_counter.h
+++ b/chromium/components/browsing_data/core/counters/bookmark_counter.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_BROWSING_DATA_CORE_COUNTERS_BOOKMARK_COUNTER_H_
#define COMPONENTS_BROWSING_DATA_CORE_COUNTERS_BOOKMARK_COUNTER_H_
-#include <memory>
-
#include "components/browsing_data/core/counters/browsing_data_counter.h"
namespace bookmarks {
diff --git a/chromium/components/browsing_data/core/counters/browsing_data_counter.h b/chromium/components/browsing_data/core/counters/browsing_data_counter.h
index e809b00741c..9d8aa95e4a9 100644
--- a/chromium/components/browsing_data/core/counters/browsing_data_counter.h
+++ b/chromium/components/browsing_data/core/counters/browsing_data_counter.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <memory>
-#include <string>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/components/browsing_data/core/history_notice_utils.cc b/chromium/components/browsing_data/core/history_notice_utils.cc
index ef252ed51ca..430e03eac8d 100644
--- a/chromium/components/browsing_data/core/history_notice_utils.cc
+++ b/chromium/components/browsing_data/core/history_notice_utils.cc
@@ -8,7 +8,6 @@
#include "base/callback.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/history/core/browser/web_history_service.h"
#include "components/sync/driver/sync_service.h"
@@ -61,7 +60,7 @@ void ShouldShowNoticeAboutOtherFormsOfBrowsingHistory(
if (!sync_service || !sync_service->IsSyncFeatureActive() ||
!sync_service->GetActiveDataTypes().Has(
syncer::HISTORY_DELETE_DIRECTIVES) ||
- sync_service->GetUserSettings()->IsUsingSecondaryPassphrase() ||
+ sync_service->GetUserSettings()->IsUsingExplicitPassphrase() ||
!history_service) {
std::move(callback).Run(false);
return;
@@ -104,7 +103,7 @@ void ShouldPopupDialogAboutOtherFormsOfBrowsingHistory(
if (!sync_service || !sync_service->IsSyncFeatureActive() ||
!sync_service->GetActiveDataTypes().Has(
syncer::HISTORY_DELETE_DIRECTIVES) ||
- sync_service->GetUserSettings()->IsUsingSecondaryPassphrase() ||
+ sync_service->GetUserSettings()->IsUsingExplicitPassphrase() ||
!history_service) {
std::move(callback).Run(false);
return;
diff --git a/chromium/components/browsing_data/core/history_notice_utils.h b/chromium/components/browsing_data/core/history_notice_utils.h
index ff5174385f4..0bc27ffb582 100644
--- a/chromium/components/browsing_data/core/history_notice_utils.h
+++ b/chromium/components/browsing_data/core/history_notice_utils.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_BROWSING_DATA_CORE_HISTORY_NOTICE_UTILS_H_
#define COMPONENTS_BROWSING_DATA_CORE_HISTORY_NOTICE_UTILS_H_
-#include <string>
-
#include "base/callback_forward.h"
namespace history {
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 7d8d1ce83fe..ea819efd72b 100644
--- a/chromium/components/browsing_data/core/history_notice_utils_unittest.cc
+++ b/chromium/components/browsing_data/core/history_notice_utils_unittest.cc
@@ -74,13 +74,13 @@ TEST_F(HistoryNoticeUtilsTest, SyncingWithWrongParameters) {
// ...the response is false if there's custom passphrase...
sync_service()->SetActiveDataTypes(syncer::ModelTypeSet::All());
- sync_service()->SetIsUsingSecondaryPassphrase(true);
+ sync_service()->SetIsUsingExplicitPassphrase(true);
ExpectShouldPopupDialogAboutOtherFormsOfBrowsingHistoryWithResult(false);
// ...or even if there's no custom passphrase, but we're not syncing history.
syncer::ModelTypeSet only_passwords(syncer::PASSWORDS);
sync_service()->SetActiveDataTypes(only_passwords);
- sync_service()->SetIsUsingSecondaryPassphrase(false);
+ sync_service()->SetIsUsingExplicitPassphrase(false);
ExpectShouldPopupDialogAboutOtherFormsOfBrowsingHistoryWithResult(false);
}
diff --git a/chromium/components/captive_portal/content/captive_portal_service.cc b/chromium/components/captive_portal/content/captive_portal_service.cc
index b899255f9bd..967bbbe142a 100644
--- a/chromium/components/captive_portal/content/captive_portal_service.cc
+++ b/chromium/components/captive_portal/content/captive_portal_service.cc
@@ -130,9 +130,8 @@ CaptivePortalService::CaptivePortalService(
if (loader_factory_for_testing) {
loader_factory = loader_factory_for_testing;
} else {
- shared_url_loader_factory_ =
- content::BrowserContext::GetDefaultStoragePartition(browser_context)
- ->GetURLLoaderFactoryForBrowserProcess();
+ shared_url_loader_factory_ = browser_context->GetDefaultStoragePartition()
+ ->GetURLLoaderFactoryForBrowserProcess();
loader_factory = shared_url_loader_factory_.get();
}
captive_portal_detector_ =
diff --git a/chromium/components/captive_portal/content/captive_portal_tab_reloader.cc b/chromium/components/captive_portal/content/captive_portal_tab_reloader.cc
index 494f508a1be..955d9e6118c 100644
--- a/chromium/components/captive_portal/content/captive_portal_tab_reloader.cc
+++ b/chromium/components/captive_portal/content/captive_portal_tab_reloader.cc
@@ -24,7 +24,7 @@ const int kDefaultSlowSSLTimeSeconds = 30;
// Returns the appropriate CaptivePortalProbeReason if |error| may indicate a
// captive portal, otherwise returns nullopt.
-base::Optional<CaptivePortalProbeReason> SslNetErrorMayImplyCaptivePortal(
+absl::optional<CaptivePortalProbeReason> SslNetErrorMayImplyCaptivePortal(
int error) {
// May be returned when a captive portal silently blocks an SSL request.
if (error == net::ERR_CONNECTION_TIMED_OUT)
@@ -39,7 +39,7 @@ base::Optional<CaptivePortalProbeReason> SslNetErrorMayImplyCaptivePortal(
if (net::IsCertificateError(error))
return CaptivePortalProbeReason::kCertificateError;
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace
@@ -90,7 +90,7 @@ void CaptivePortalTabReloader::OnLoadCommitted(
// If |net_error| is not an error code that could indicate there's a captive
// portal, reset the state.
- base::Optional<CaptivePortalProbeReason> probe_reason =
+ absl::optional<CaptivePortalProbeReason> probe_reason =
SslNetErrorMayImplyCaptivePortal(net_error);
if (!probe_reason.has_value()) {
// TODO(mmenke): If the new URL is the same as the old broken URL, and the
@@ -212,7 +212,7 @@ void CaptivePortalTabReloader::OnSecureDnsNetworkError() {
void CaptivePortalTabReloader::SetState(
State new_state,
- base::Optional<CaptivePortalProbeReason> probe_reason) {
+ absl::optional<CaptivePortalProbeReason> probe_reason) {
// Stop the timer even when old and new states are the same.
if (state_ == STATE_TIMER_RUNNING) {
slow_ssl_load_timer_.Stop();
diff --git a/chromium/components/captive_portal/content/captive_portal_tab_reloader.h b/chromium/components/captive_portal/content/captive_portal_tab_reloader.h
index 103b548799c..0e1e4e5aaaf 100644
--- a/chromium/components/captive_portal/content/captive_portal_tab_reloader.h
+++ b/chromium/components/captive_portal/content/captive_portal_tab_reloader.h
@@ -9,11 +9,11 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/captive_portal/content/captive_portal_service.h"
#include "net/dns/public/resolve_error_info.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class WebContents;
@@ -138,7 +138,7 @@ class CaptivePortalTabReloader {
// |probe_trigger| should be specified.
void SetState(
State new_state,
- base::Optional<CaptivePortalProbeReason> probe_reason = base::nullopt);
+ absl::optional<CaptivePortalProbeReason> probe_reason = absl::nullopt);
// Called by a timer when an SSL main frame provisional load is taking a
// while to commit.
diff --git a/chromium/components/captive_portal/core/captive_portal_testing_utils.h b/chromium/components/captive_portal/core/captive_portal_testing_utils.h
index b5cc2d1673d..22619a1a3e1 100644
--- a/chromium/components/captive_portal/core/captive_portal_testing_utils.h
+++ b/chromium/components/captive_portal/core/captive_portal_testing_utils.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_CAPTIVE_PORTAL_CORE_CAPTIVE_PORTAL_TESTING_UTILS_H_
#define COMPONENTS_CAPTIVE_PORTAL_CORE_CAPTIVE_PORTAL_TESTING_UTILS_H_
-#include <string>
-
#include "base/macros.h"
#include "components/captive_portal/core/captive_portal_detector.h"
#include "services/network/test/test_url_loader_factory.h"
diff --git a/chromium/components/cast/api_bindings/scoped_api_binding.cc b/chromium/components/cast/api_bindings/scoped_api_binding.cc
index 30843b3af92..004002117df 100644
--- a/chromium/components/cast/api_bindings/scoped_api_binding.cc
+++ b/chromium/components/cast/api_bindings/scoped_api_binding.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/strings/string_piece.h"
#include "components/cast/api_bindings/manager.h"
namespace cast_api_bindings {
@@ -58,7 +59,7 @@ bool ScopedApiBinding::SendMessage(base::StringPiece data_utf8) {
return false;
}
- if (!message_port_->PostMessage(data_utf8.as_string())) {
+ if (!message_port_->PostMessage(data_utf8)) {
return false;
}
diff --git a/chromium/components/cast/api_bindings/scoped_api_binding.h b/chromium/components/cast/api_bindings/scoped_api_binding.h
index bb5f3cdbb75..2c3c451c13b 100644
--- a/chromium/components/cast/api_bindings/scoped_api_binding.h
+++ b/chromium/components/cast/api_bindings/scoped_api_binding.h
@@ -7,12 +7,11 @@
#include <memory>
-#include "base/callback_forward.h"
#include "base/check.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "components/cast/cast_component_export.h"
#include "components/cast/message_port/message_port.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cast_api_bindings {
diff --git a/chromium/components/cast/common/BUILD.gn b/chromium/components/cast/common/BUILD.gn
new file mode 100644
index 00000000000..4eef367a8ea
--- /dev/null
+++ b/chromium/components/cast/common/BUILD.gn
@@ -0,0 +1,10 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("constants") {
+ sources = [
+ "constants.cc",
+ "constants.h",
+ ]
+}
diff --git a/chromium/components/cast/common/constants.cc b/chromium/components/cast/common/constants.cc
new file mode 100644
index 00000000000..c662d658021
--- /dev/null
+++ b/chromium/components/cast/common/constants.cc
@@ -0,0 +1,11 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast/common/constants.h"
+
+namespace chromecast {
+
+const char kFrozenCrKeyValue[] = "1.56.500000";
+
+} // namespace chromecast
diff --git a/chromium/components/cast/common/constants.h b/chromium/components/cast/common/constants.h
new file mode 100644
index 00000000000..affcdc265a9
--- /dev/null
+++ b/chromium/components/cast/common/constants.h
@@ -0,0 +1,15 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_COMMON_CONSTANTS_H_
+#define COMPONENTS_CAST_COMMON_CONSTANTS_H_
+
+namespace chromecast {
+
+// See internal b/187823385 for details.
+extern const char kFrozenCrKeyValue[];
+
+} // namespace chromecast
+
+#endif // COMPONENTS_CAST_COMMON_CONSTANTS_H_
diff --git a/chromium/components/cast/message_port/message_port_fuchsia.cc b/chromium/components/cast/message_port/message_port_fuchsia.cc
index e8ce09d021e..0f044f67250 100644
--- a/chromium/components/cast/message_port/message_port_fuchsia.cc
+++ b/chromium/components/cast/message_port/message_port_fuchsia.cc
@@ -7,6 +7,7 @@
#include "base/fuchsia/fuchsia_logging.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
+#include "base/strings/string_piece.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
@@ -242,8 +243,7 @@ fuchsia::web::WebMessage MessagePortFuchsia::CreateWebMessage(
base::StringPiece message,
std::vector<std::unique_ptr<MessagePort>> ports) {
fuchsia::web::WebMessage message_fidl;
- message_fidl.set_data(cr_fuchsia::MemBufferFromString(message.as_string(),
- message.as_string()));
+ message_fidl.set_data(cr_fuchsia::MemBufferFromString(message, message));
if (!ports.empty()) {
PortType expected_port_type = FromMessagePort(ports[0].get())->port_type_;
std::vector<fuchsia::web::IncomingTransferable> incoming_transferables;
@@ -290,7 +290,7 @@ MessagePortFuchsia::MessagePortFuchsia(PortType port_type)
: receiver_(nullptr), port_type_(port_type) {}
MessagePortFuchsia::~MessagePortFuchsia() = default;
-base::Optional<fuchsia::web::FrameError>
+absl::optional<fuchsia::web::FrameError>
MessagePortFuchsia::ExtractAndHandleMessageFromFidl(
fuchsia::web::WebMessage message) {
DCHECK(receiver_);
@@ -322,7 +322,7 @@ MessagePortFuchsia::ExtractAndHandleMessageFromFidl(
return fuchsia::web::FrameError::INTERNAL_ERROR;
}
- return base::nullopt;
+ return absl::nullopt;
}
void MessagePortFuchsia::OnZxError(zx_status_t status) {
diff --git a/chromium/components/cast/message_port/message_port_fuchsia.h b/chromium/components/cast/message_port/message_port_fuchsia.h
index d547dee1714..ec3c315dab8 100644
--- a/chromium/components/cast/message_port/message_port_fuchsia.h
+++ b/chromium/components/cast/message_port/message_port_fuchsia.h
@@ -11,9 +11,9 @@
#include <lib/fidl/cpp/interface_request.h>
#include "base/containers/circular_deque.h"
-#include "base/optional.h"
#include "components/cast/message_port/message_port.h"
#include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cast_api_bindings {
@@ -67,7 +67,7 @@ class MessagePortFuchsia : public cast_api_bindings::MessagePort {
// or handling the message fails.
// Note that handling the message may result in |this| being deleted before
// the call returns.
- base::Optional<fuchsia::web::FrameError> ExtractAndHandleMessageFromFidl(
+ absl::optional<fuchsia::web::FrameError> ExtractAndHandleMessageFromFidl(
fuchsia::web::WebMessage message);
void OnZxError(zx_status_t status);
diff --git a/chromium/components/cast/message_port/test_message_port_receiver.cc b/chromium/components/cast/message_port/test_message_port_receiver.cc
index 6dcacfd0075..7b6f68dfc07 100644
--- a/chromium/components/cast/message_port/test_message_port_receiver.cc
+++ b/chromium/components/cast/message_port/test_message_port_receiver.cc
@@ -5,6 +5,7 @@
#include "components/cast/message_port/test_message_port_receiver.h"
#include "base/run_loop.h"
+#include "base/strings/string_piece.h"
namespace cast_api_bindings {
@@ -33,7 +34,7 @@ void TestMessagePortReceiver::RunUntilDisconnected() {
bool TestMessagePortReceiver::OnMessage(
base::StringPiece message,
std::vector<std::unique_ptr<MessagePort>> ports) {
- buffer_.push_back(std::make_pair(message.as_string(), std::move(ports)));
+ buffer_.push_back(std::make_pair(std::string(message), std::move(ports)));
if (message_count_target_ == buffer_.size()) {
DCHECK(on_receive_satisfied_);
std::move(on_receive_satisfied_).Run();
diff --git a/chromium/components/cast/named_message_port_connector/named_message_port_connector.cc b/chromium/components/cast/named_message_port_connector/named_message_port_connector.cc
index 31138dc85cb..9828dc89d18 100644
--- a/chromium/components/cast/named_message_port_connector/named_message_port_connector.cc
+++ b/chromium/components/cast/named_message_port_connector/named_message_port_connector.cc
@@ -46,7 +46,6 @@ void NamedMessagePortConnector::GetConnectMessage(
std::string* message,
std::unique_ptr<MessagePort>* port) {
constexpr char kControlPortConnectMessage[] = "cast.master.connect";
- std::unique_ptr<MessagePort> control_port_for_web_engine;
MessagePort::CreatePair(&control_port_, port);
*message = kControlPortConnectMessage;
control_port_->SetReceiver(this);
diff --git a/chromium/components/cast_certificate/cast_cert_reader.cc b/chromium/components/cast_certificate/cast_cert_reader.cc
index 30696784ffd..5c94f52cb4a 100644
--- a/chromium/components/cast_certificate/cast_cert_reader.cc
+++ b/chromium/components/cast_certificate/cast_cert_reader.cc
@@ -42,12 +42,18 @@ std::vector<std::string> ReadCertificateChainFromFile(
return {};
}
+ return ReadCertificateChainFromString(file_data.data());
+}
+
+std::vector<std::string> ReadCertificateChainFromString(const char* str) {
std::vector<std::string> certs;
- net::PEMTokenizer pem_tokenizer(file_data, {"CERTIFICATE"});
+ net::PEMTokenizer pem_tokenizer(str, {"CERTIFICATE"});
while (pem_tokenizer.GetNext())
certs.push_back(pem_tokenizer.data());
- CHECK(!certs.empty());
+ if (certs.empty()) {
+ LOG(WARNING) << "Certificate chain is empty.";
+ }
return certs;
}
diff --git a/chromium/components/cast_certificate/cast_cert_reader.h b/chromium/components/cast_certificate/cast_cert_reader.h
index bb84520cd4e..0cc73d7a996 100644
--- a/chromium/components/cast_certificate/cast_cert_reader.h
+++ b/chromium/components/cast_certificate/cast_cert_reader.h
@@ -23,6 +23,10 @@ bool PopulateStoreWithCertsFromPath(net::TrustStoreInMemory* store,
std::vector<std::string> ReadCertificateChainFromFile(
const base::FilePath& path);
+// Reads a PEM certificate list loaded into a C-string |str| into a
+// vector of their DER data.
+std::vector<std::string> ReadCertificateChainFromString(const char* str);
+
} // namespace cast_certificate
#endif // COMPONENTS_CAST_CERTIFICATE_CAST_CERT_READER_H_
diff --git a/chromium/components/cast_certificate/cast_cert_validator.cc b/chromium/components/cast_certificate/cast_cert_validator.cc
index 17491d1ff58..3b6a673b7b9 100644
--- a/chromium/components/cast_certificate/cast_cert_validator.cc
+++ b/chromium/components/cast_certificate/cast_cert_validator.cc
@@ -14,6 +14,7 @@
#include "base/containers/contains.h"
#include "base/logging.h"
#include "base/no_destructor.h"
+#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
@@ -165,7 +166,7 @@ class CertVerificationContextImpl : public CertVerificationContext {
// Save a copy of the passed in public key (DER) and common name (text).
CertVerificationContextImpl(const net::der::Input& spki,
const base::StringPiece& common_name)
- : spki_(spki.AsString()), common_name_(common_name.as_string()) {}
+ : spki_(spki.AsString()), common_name_(common_name) {}
bool VerifySignatureOverData(
const base::StringPiece& signature,
diff --git a/chromium/components/cast_channel/BUILD.gn b/chromium/components/cast_channel/BUILD.gn
index 9f3a14c5e53..77d28064172 100644
--- a/chromium/components/cast_channel/BUILD.gn
+++ b/chromium/components/cast_channel/BUILD.gn
@@ -4,6 +4,7 @@
import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
+import("//third_party/openscreen/src/build/config/data_headers_template.gni")
import("//third_party/protobuf/proto_library.gni")
static_library("cast_channel") {
@@ -116,13 +117,24 @@ source_set("unit_tests") {
]
}
+# TODO(issuetracker.google.com/185815206): fuzzing should move to Open Screen.
if (use_fuzzing_engine) {
+ data_headers("cast_auth_util_fuzzer_certs") {
+ namespace = "cast"
+ sources =
+ [ "../test/data/cast_certificate/certificates/chromecast_gen1.pem" ]
+ }
+
fuzzable_proto_library("cast_channel_fuzzer_inputs") {
sources = [ "proto/fuzzer_inputs.proto" ]
import_dirs = [
"//third_party/openscreen/src/cast/common/certificate/proto",
"//third_party/openscreen/src/cast/common/channel/proto",
]
+ link_deps = [
+ "//third_party/openscreen/src/cast/common/certificate/proto:certificate_proto",
+ "//third_party/openscreen/src/cast/common/channel/proto:channel_proto",
+ ]
proto_out_dir = "components/cast_channel/fuzz_proto"
}
@@ -152,6 +164,7 @@ if (use_fuzzing_engine) {
fuzzer_test("cast_auth_util_fuzzer") {
sources = [ "cast_auth_util_fuzzer.cc" ]
deps = [
+ ":cast_auth_util_fuzzer_certs",
":cast_channel",
":cast_channel_fuzzer_inputs",
"//components/cast_certificate",
diff --git a/chromium/components/cast_channel/DEPS b/chromium/components/cast_channel/DEPS
index e55deb98d32..a0b9c3ed36a 100644
--- a/chromium/components/cast_channel/DEPS
+++ b/chromium/components/cast_channel/DEPS
@@ -22,7 +22,8 @@ specific_include_rules = {
# For google::protobuf::LogSilencer
"+third_party/protobuf",
],
- ".*_unittest.cc": [
+ ".*_(unittest|fuzzer).cc": [
"+third_party/openscreen/src/cast/common/channel/testing",
+ "+components/test/data/cast_certificate",
],
}
diff --git a/chromium/components/cast_channel/cast_auth_util.cc b/chromium/components/cast_channel/cast_auth_util.cc
index ceb368c1efc..33f665e078c 100644
--- a/chromium/components/cast_channel/cast_auth_util.cc
+++ b/chromium/components/cast_channel/cast_auth_util.cc
@@ -13,7 +13,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "components/cast_certificate/cast_cert_validator.h"
#include "components/cast_certificate/cast_crl.h"
#include "components/cast_channel/cast_channel_enum.h"
diff --git a/chromium/components/cast_channel/cast_auth_util_fuzzer.cc b/chromium/components/cast_channel/cast_auth_util_fuzzer.cc
index 46cb664f188..4480211d189 100644
--- a/chromium/components/cast_channel/cast_auth_util_fuzzer.cc
+++ b/chromium/components/cast_channel/cast_auth_util_fuzzer.cc
@@ -14,6 +14,8 @@
#include "components/cast_certificate/cast_cert_test_helpers.h"
#include "components/cast_channel/cast_auth_util.h"
#include "components/cast_channel/fuzz_proto/fuzzer_inputs.pb.h"
+// Generated by the "cast_auth_util_fuzzer_certs" data_headers target.
+#include "components/test/data/cast_certificate/certificates/chromecast_gen1_data.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "net/test/test_certificate_data.h"
@@ -31,9 +33,8 @@ const char kCertData[] = {
base::NoDestructor<std::vector<std::string>> certs;
static bool InitializeOnce() {
- *certs = cast_certificate::ReadCertificateChainFromFile(
- cast_certificate::testing::GetCastCertificatesSubDirectory().AppendASCII(
- "chromecast_gen1.pem"));
+ *certs = cast_certificate::ReadCertificateChainFromString(
+ openscreen::cast::kChromecastGen1);
CHECK(certs->size() >= 1)
<< "We should always have at least one certificate.";
return true;
diff --git a/chromium/components/cast_channel/cast_message_handler.cc b/chromium/components/cast_channel/cast_message_handler.cc
index 6049faefdc8..06bb25332d9 100644
--- a/chromium/components/cast_channel/cast_message_handler.cc
+++ b/chromium/components/cast_channel/cast_message_handler.cc
@@ -207,7 +207,7 @@ void CastMessageHandler::LaunchSession(
const std::string& app_id,
base::TimeDelta launch_timeout,
const std::vector<std::string>& supported_app_types,
- const base::Optional<base::Value>& app_params,
+ const absl::optional<base::Value>& app_params,
LaunchSessionCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CastSocket* socket = socket_service_->GetSocket(channel_id);
@@ -240,7 +240,7 @@ void CastMessageHandler::LaunchSession(
void CastMessageHandler::StopSession(
int channel_id,
const std::string& session_id,
- const base::Optional<std::string>& client_id,
+ const absl::optional<std::string>& client_id,
ResultCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CastSocket* socket = socket_service_->GetSocket(channel_id);
@@ -286,7 +286,7 @@ Result CastMessageHandler::SendAppMessage(int channel_id,
return SendCastMessage(channel_id, message);
}
-base::Optional<int> CastMessageHandler::SendMediaRequest(
+absl::optional<int> CastMessageHandler::SendMediaRequest(
int channel_id,
const base::Value& body,
const std::string& source_id,
@@ -296,7 +296,7 @@ base::Optional<int> CastMessageHandler::SendMediaRequest(
CastSocket* socket = socket_service_->GetSocket(channel_id);
if (!socket) {
DVLOG(2) << __func__ << ": socket not found: " << channel_id;
- return base::nullopt;
+ return absl::nullopt;
}
int request_id = NextRequestId();
@@ -407,7 +407,7 @@ void CastMessageHandler::HandleCastInternalMessage(
return;
}
- base::Optional<int> request_id = GetRequestIdFromResponse(payload);
+ absl::optional<int> request_id = GetRequestIdFromResponse(payload);
if (request_id) {
auto requests_it = pending_requests_.find(channel_id);
if (requests_it != pending_requests_.end())
diff --git a/chromium/components/cast_channel/cast_message_handler.h b/chromium/components/cast_channel/cast_message_handler.h
index 1485d2d581a..0d2848afd79 100644
--- a/chromium/components/cast_channel/cast_message_handler.h
+++ b/chromium/components/cast_channel/cast_message_handler.h
@@ -11,7 +11,6 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/tick_clock.h"
#include "base/timer/timer.h"
@@ -20,6 +19,7 @@
#include "components/cast_channel/cast_message_util.h"
#include "components/cast_channel/cast_socket.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cast_channel {
@@ -186,7 +186,7 @@ class CastMessageHandler : public CastSocket::Observer {
const std::string& app_id,
base::TimeDelta launch_timeout,
const std::vector<std::string>& supported_app_types,
- const base::Optional<base::Value>& app_params,
+ const absl::optional<base::Value>& app_params,
LaunchSessionCallback callback);
// Stops the session given by |session_id| on the device given by
@@ -194,7 +194,7 @@ class CastMessageHandler : public CastSocket::Observer {
// request.
virtual void StopSession(int channel_id,
const std::string& session_id,
- const base::Optional<std::string>& client_id,
+ const absl::optional<std::string>& client_id,
ResultCallback callback);
// Sends |message| to the device given by |channel_id|. The caller may use
@@ -218,7 +218,7 @@ class CastMessageHandler : public CastSocket::Observer {
// Sends a media command |body|. Returns the ID of the request that is sent to
// the receiver. It is invalid to call this with a message body that is not a
- // media command. Returns |base::nullopt| if |channel_id| is invalid.
+ // media command. Returns |absl::nullopt| if |channel_id| is invalid.
//
// Note: This API is designed to return a request ID instead of taking a
// callback. This is because a MEDIA_STATUS message from the receiver can be
@@ -227,7 +227,7 @@ class CastMessageHandler : public CastSocket::Observer {
// all clients and (2) make sure the client that sent the media command
// receives the message only once *and* in the form of a response (by setting
// the sequenceNumber on the message).
- virtual base::Optional<int> SendMediaRequest(
+ virtual absl::optional<int> SendMediaRequest(
int channel_id,
const base::Value& body,
const std::string& source_id,
diff --git a/chromium/components/cast_channel/cast_message_handler_unittest.cc b/chromium/components/cast_channel/cast_message_handler_unittest.cc
index ef7aa00cc1a..c2456c4a950 100644
--- a/chromium/components/cast_channel/cast_message_handler_unittest.cc
+++ b/chromium/components/cast_channel/cast_message_handler_unittest.cc
@@ -139,22 +139,22 @@ class CastMessageHandlerTest : public testing::Test {
void ExpectEnsureConnection() {
EXPECT_CALL(*transport_,
- SendMessage(HasMessageType(CastMessageType::kConnect), _));
+ SendMessage_(HasMessageType(CastMessageType::kConnect), _));
}
void ExpectEnsureConnectionThen(CastMessageType next_type,
int request_count = 1) {
InSequence dummy;
ExpectEnsureConnection();
- EXPECT_CALL(*transport_, SendMessage(HasMessageType(next_type), _))
+ EXPECT_CALL(*transport_, SendMessage_(HasMessageType(next_type), _))
.Times(request_count)
.WillRepeatedly(SaveArg<0>(&last_request_));
}
void CreatePendingRequests() {
- EXPECT_CALL(*transport_, SendMessage(_, _)).Times(AnyNumber());
+ EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(AnyNumber());
handler_.LaunchSession(channel_id_, kAppId1, base::TimeDelta::Max(),
- {"WEB"}, /* appParams */ base::nullopt,
+ {"WEB"}, /* appParams */ absl::nullopt,
launch_session_callback_.Get());
for (int i = 0; i < 2; i++) {
handler_.RequestAppAvailability(&cast_socket_, kAppId1,
@@ -177,14 +177,14 @@ class CastMessageHandlerTest : public testing::Test {
InSequence dummy;
// We should first send a CONNECT request to ensure a connection.
EXPECT_CALL(*transport_,
- SendMessage(HasMessageType(CastMessageType::kConnect), _))
+ SendMessage_(HasMessageType(CastMessageType::kConnect), _))
.WillOnce(WithArg<0>([&](const CastMessage& message) {
std::unique_ptr<base::Value> dict =
GetDictionaryFromCastMessage(message);
EXPECT_EQ(connection_type, dict->FindIntKey("connType").value());
}));
// Then we send the actual message.
- EXPECT_CALL(*transport_, SendMessage(_, _));
+ EXPECT_CALL(*transport_, SendMessage_(_, _));
}
EXPECT_EQ(Result::kOk, handler_.SendAppMessage(channel_id_, message));
}
@@ -313,7 +313,7 @@ TEST_F(CastMessageHandlerTest, RequestAppAvailability) {
}
TEST_F(CastMessageHandlerTest, RequestAppAvailabilityTimesOut) {
- EXPECT_CALL(*transport_, SendMessage(_, _)).Times(2);
+ EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(2);
handler_.RequestAppAvailability(
&cast_socket_, "ABCDEFAB",
base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
@@ -324,13 +324,13 @@ TEST_F(CastMessageHandlerTest, RequestAppAvailabilityTimesOut) {
}
TEST_F(CastMessageHandlerTest, AppAvailabilitySentOnlyOnceWhilePending) {
- EXPECT_CALL(*transport_, SendMessage(_, _)).Times(2);
+ EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(2);
handler_.RequestAppAvailability(
&cast_socket_, "ABCDEFAB",
base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
base::Unretained(this)));
- EXPECT_CALL(*transport_, SendMessage(_, _)).Times(0);
+ EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(0);
handler_.RequestAppAvailability(
&cast_socket_, "ABCDEFAB",
base::BindOnce(&CastMessageHandlerTest::OnAppAvailability,
@@ -344,7 +344,7 @@ TEST_F(CastMessageHandlerTest, EnsureConnection) {
VirtualConnectionType::kStrong);
// No-op because connection is already created the first time.
- EXPECT_CALL(*transport_, SendMessage(_, _)).Times(0);
+ EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(0);
handler_.EnsureConnection(channel_id_, kSourceId, kDestinationId,
VirtualConnectionType::kStrong);
}
@@ -356,7 +356,7 @@ TEST_F(CastMessageHandlerTest, CloseConnection) {
EXPECT_CALL(
*transport_,
- SendMessage(HasMessageType(CastMessageType::kCloseConnection), _));
+ SendMessage_(HasMessageType(CastMessageType::kCloseConnection), _));
handler_.CloseConnection(channel_id_, kSourceId, kDestinationId);
// Re-open virtual connection should cause CONNECT message to be sent.
@@ -384,7 +384,7 @@ TEST_F(CastMessageHandlerTest, CloseConnectionFromReceiver) {
task_environment_.RunUntilIdle();
// Re-open virtual connection should cause message to be sent.
- EXPECT_CALL(*transport_, SendMessage(_, _));
+ EXPECT_CALL(*transport_, SendMessage_(_, _));
handler_.EnsureConnection(channel_id_, kSourceId, kDestinationId,
VirtualConnectionType::kStrong);
}
@@ -392,7 +392,7 @@ TEST_F(CastMessageHandlerTest, CloseConnectionFromReceiver) {
TEST_F(CastMessageHandlerTest, LaunchSession) {
ExpectEnsureConnectionThen(CastMessageType::kLaunch);
- const base::Optional<base::Value> json = base::JSONReader::Read(kAppParams);
+ const absl::optional<base::Value> json = base::JSONReader::Read(kAppParams);
handler_.LaunchSession(
channel_id_, kAppId1, base::TimeDelta::FromSeconds(30), {"WEB"}, json,
@@ -437,7 +437,7 @@ TEST_F(CastMessageHandlerTest, LaunchSessionTimedOut) {
handler_.LaunchSession(
channel_id_, kAppId1, base::TimeDelta::FromSeconds(30), {"WEB"},
- /* appParams */ base::nullopt,
+ /* appParams */ absl::nullopt,
base::BindOnce(&CastMessageHandlerTest::ExpectSessionLaunchResult,
base::Unretained(this),
LaunchSessionResponse::Result::kTimedOut));
@@ -452,7 +452,7 @@ TEST_F(CastMessageHandlerTest, LaunchSessionMessageExceedsSizeLimit) {
json.SetKey("key", base::Value(invalid_URL));
handler_.LaunchSession(
channel_id_, kAppId1, base::TimeDelta::FromSeconds(30), {"WEB"},
- base::make_optional<base::Value>(std::move(json)),
+ absl::make_optional<base::Value>(std::move(json)),
base::BindOnce(&CastMessageHandlerTest::ExpectSessionLaunchResult,
base::Unretained(this),
LaunchSessionResponse::Result::kError));
@@ -468,7 +468,7 @@ TEST_F(CastMessageHandlerTest, SendAppMessage) {
InSequence dummy;
ExpectEnsureConnection();
EXPECT_CALL(*transport_,
- SendMessage(HasPayloadUtf8(message.payload_utf8()), _));
+ SendMessage_(HasPayloadUtf8(message.payload_utf8()), _));
}
EXPECT_EQ(Result::kOk, handler_.SendAppMessage(channel_id_, message));
@@ -503,7 +503,7 @@ TEST_F(CastMessageHandlerTest, SendMediaRequest) {
{
InSequence dummy;
ExpectEnsureConnection();
- EXPECT_CALL(*transport_, SendMessage(_, _))
+ EXPECT_CALL(*transport_, SendMessage_(_, _))
.WillOnce(WithArg<0>([&](const auto& message) {
std::string expected_body = R"({
"requestId": 1,
@@ -525,7 +525,7 @@ TEST_F(CastMessageHandlerTest, SendMediaRequest) {
std::string message_str = R"({
"type": "PLAY",
})";
- base::Optional<int> request_id = handler_.SendMediaRequest(
+ absl::optional<int> request_id = handler_.SendMediaRequest(
channel_id_, ParseJson(message_str), "theSourceId", kDestinationId);
EXPECT_EQ(1, request_id);
}
@@ -538,7 +538,7 @@ TEST_F(CastMessageHandlerTest, SendBroadcastMessage) {
InSequence dummy;
ExpectEnsureConnection();
EXPECT_CALL(*transport_,
- SendMessage(HasPayloadUtf8(message.payload_utf8()), _));
+ SendMessage_(HasPayloadUtf8(message.payload_utf8()), _));
}
EXPECT_EQ(Result::kOk,
@@ -561,7 +561,7 @@ TEST_F(CastMessageHandlerTest, SendVolumeCommand) {
{
InSequence dummy;
ExpectEnsureConnection();
- EXPECT_CALL(*transport_, SendMessage(_, _))
+ EXPECT_CALL(*transport_, SendMessage_(_, _))
.WillOnce(WithArg<0>([&](const auto& message) {
std::string expected_body = R"({
"requestId": 1,
@@ -597,7 +597,7 @@ TEST_F(CastMessageHandlerTest, PendingRequestsDestructor) {
EXPECT_CALL(launch_session_callback_, Run(_))
.WillOnce([&](LaunchSessionResponse response) {
EXPECT_EQ(LaunchSessionResponse::kError, response.result);
- EXPECT_EQ(base::nullopt, response.receiver_status);
+ EXPECT_EQ(absl::nullopt, response.receiver_status);
});
EXPECT_CALL(get_app_availability_callback_,
Run(kAppId1, GetAppAvailabilityResult::kUnknown))
@@ -644,7 +644,7 @@ TEST_F(CastMessageHandlerTest, HandlePendingRequest) {
// Check that set volume requests time out correctly.
TEST_F(CastMessageHandlerTest, SetVolumeTimedOut) {
- EXPECT_CALL(*transport_, SendMessage(_, _)).Times(AnyNumber());
+ EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(AnyNumber());
std::string message_str = R"({
"sessionId": "theSessionId",
@@ -670,14 +670,14 @@ TEST_F(CastMessageHandlerTest, SendMultipleLaunchRequests) {
.WillOnce(WithArg<0>([](LaunchSessionResponse response) {
EXPECT_EQ(LaunchSessionResponse::Result::kError, response.result);
}));
- EXPECT_CALL(*transport_, SendMessage(_, _)).Times(AnyNumber());
+ EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(AnyNumber());
handler_.LaunchSession(channel_id_, kAppId1, base::TimeDelta::Max(), {"WEB"},
- /* appParams */ base::nullopt,
+ /* appParams */ absl::nullopt,
expect_success_callback.Get());
// When there already is a launch request queued, we expect subsequent
// requests to fail.
handler_.LaunchSession(channel_id_, kAppId1, base::TimeDelta::Max(), {"WEB"},
- /* appParams */ base::nullopt,
+ /* appParams */ absl::nullopt,
expect_failure_callback.Get());
// This resolves the first launch request.
HandlePendingLaunchSessionRequest(next_request_id++);
@@ -688,9 +688,9 @@ TEST_F(CastMessageHandlerTest, SendMultipleStopRequests) {
base::MockCallback<ResultCallback> expect_success_callback;
base::MockCallback<ResultCallback> expect_failure_callback;
- EXPECT_CALL(*transport_, SendMessage(_, _)).Times(AnyNumber());
+ EXPECT_CALL(*transport_, SendMessage_(_, _)).Times(AnyNumber());
handler_.LaunchSession(channel_id_, kAppId1, base::TimeDelta::Max(), {"WEB"},
- /* appParams */ base::nullopt,
+ /* appParams */ absl::nullopt,
launch_session_callback_.Get());
HandlePendingLaunchSessionRequest(next_request_id++);
diff --git a/chromium/components/cast_channel/cast_message_util.cc b/chromium/components/cast_channel/cast_message_util.cc
index d70a0704ba5..0e57d23a8ff 100644
--- a/chromium/components/cast_channel/cast_message_util.cc
+++ b/chromium/components/cast_channel/cast_message_util.cc
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -181,7 +182,7 @@ int GetVirtualConnectPlatformValue() {
// messages are passed using a CastInternalMessage object.
base::StringPiece GetRemappedMediaRequestType(
base::StringPiece v2_message_type) {
- base::Optional<V2MessageType> type =
+ absl::optional<V2MessageType> type =
StringToEnum<V2MessageType>(v2_message_type);
DCHECK(type && IsMediaRequestMessageType(*type));
switch (*type) {
@@ -475,7 +476,7 @@ CastMessage CreateLaunchRequest(
const std::string& app_id,
const std::string& locale,
const std::vector<std::string>& supported_app_types,
- const base::Optional<base::Value>& app_params) {
+ const absl::optional<base::Value>& app_params) {
Value dict(Value::Type::DICTIONARY);
dict.SetKey("type",
Value(EnumToString<CastMessageType, CastMessageType::kLaunch>()));
@@ -548,8 +549,7 @@ CastMessage CreateSetVolumeRequest(const base::Value& body,
const std::string& source_id) {
DCHECK(body.FindKeyOfType("type", Value::Type::STRING) &&
body.FindKeyOfType("type", Value::Type::STRING)->GetString() ==
- (EnumToString<V2MessageType, V2MessageType::kSetVolume>())
- .as_string());
+ (EnumToString<V2MessageType, V2MessageType::kSetVolume>()));
Value dict = body.Clone();
dict.RemoveKey("sessionId");
dict.SetKey("requestId", Value(request_id));
@@ -586,13 +586,13 @@ const char* ToString(GetAppAvailabilityResult result) {
return EnumToString(result).value_or("").data();
}
-base::Optional<int> GetRequestIdFromResponse(const Value& payload) {
+absl::optional<int> GetRequestIdFromResponse(const Value& payload) {
DCHECK(payload.is_dict());
const Value* request_id_value =
payload.FindKeyOfType("requestId", Value::Type::INTEGER);
if (!request_id_value)
- return base::nullopt;
+ return absl::nullopt;
return request_id_value->GetInt();
}
diff --git a/chromium/components/cast_channel/cast_message_util.h b/chromium/components/cast_channel/cast_message_util.h
index e777c6bc4e2..00b4c66c7b1 100644
--- a/chromium/components/cast_channel/cast_message_util.h
+++ b/chromium/components/cast_channel/cast_message_util.h
@@ -257,7 +257,7 @@ CastMessage CreateLaunchRequest(
const std::string& app_id,
const std::string& locale,
const std::vector<std::string>& supported_app_types,
- const base::Optional<base::Value>& app_params);
+ const absl::optional<base::Value>& app_params);
CastMessage CreateStopRequest(const std::string& source_id,
int request_id,
@@ -292,7 +292,7 @@ enum class GetAppAvailabilityResult {
const char* ToString(GetAppAvailabilityResult result);
// Extracts request ID from |payload| corresponding to a Cast message response.
-base::Optional<int> GetRequestIdFromResponse(const base::Value& payload);
+absl::optional<int> GetRequestIdFromResponse(const base::Value& payload);
// Returns the GetAppAvailabilityResult corresponding to |app_id| in |payload|.
// Returns kUnknown if result is not found.
@@ -313,7 +313,7 @@ struct LaunchSessionResponse {
Result result = Result::kUnknown;
// Populated if |result| is |kOk|.
- base::Optional<base::Value> receiver_status;
+ absl::optional<base::Value> receiver_status;
// Populated if |result| is |kError|.
std::string error_msg;
};
diff --git a/chromium/components/cast_channel/cast_message_util_fuzzer.cc b/chromium/components/cast_channel/cast_message_util_fuzzer.cc
index 6827cd0b2c3..a004f6812df 100644
--- a/chromium/components/cast_channel/cast_message_util_fuzzer.cc
+++ b/chromium/components/cast_channel/cast_message_util_fuzzer.cc
@@ -55,7 +55,7 @@ DEFINE_PROTO_FUZZER(const CastMessageUtilInputs& input_union) {
}
case CastMessageUtilInputs::kCreateLaunchRequestInput: {
const auto& input = input_union.create_launch_request_input();
- base::Optional<base::Value> app_params;
+ absl::optional<base::Value> app_params;
if (input.has_app_params())
app_params = MakeValue(input.app_params());
CreateLaunchRequest(input.source_id(), input.request_id(), input.app_id(),
diff --git a/chromium/components/cast_channel/cast_socket.cc b/chromium/components/cast_channel/cast_socket.cc
index 01edef199ca..4e9781ed054 100644
--- a/chromium/components/cast_channel/cast_socket.cc
+++ b/chromium/components/cast_channel/cast_socket.cc
@@ -19,7 +19,6 @@
#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/sys_byteorder.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -62,8 +61,8 @@ bool IsTerminalState(ConnectionState state) {
void OnConnected(
network::mojom::NetworkContext::CreateTCPConnectedSocketCallback callback,
int result,
- const base::Optional<net::IPEndPoint>& local_addr,
- const base::Optional<net::IPEndPoint>& peer_addr,
+ const absl::optional<net::IPEndPoint>& local_addr,
+ const absl::optional<net::IPEndPoint>& peer_addr,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -79,7 +78,7 @@ void ConnectOnUIThread(
mojo::PendingReceiver<network::mojom::TCPConnectedSocket> receiver,
network::mojom::NetworkContext::CreateTCPConnectedSocketCallback callback) {
network_context_getter.Run()->CreateTCPConnectedSocket(
- base::nullopt /* local_addr */, remote_address_list,
+ absl::nullopt /* local_addr */, remote_address_list,
nullptr /* tcp_connected_socket_options */,
net::MutableNetworkTrafficAnnotationTag(
CastSocketImpl::GetNetworkTrafficAnnotationTag()),
@@ -550,8 +549,8 @@ int CastSocketImpl::DoAuthChallengeReplyComplete(int result) {
void CastSocketImpl::OnConnect(
int result,
- const base::Optional<net::IPEndPoint>& local_addr,
- const base::Optional<net::IPEndPoint>& peer_addr,
+ const absl::optional<net::IPEndPoint>& local_addr,
+ const absl::optional<net::IPEndPoint>& peer_addr,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream) {
DoConnectLoop(result);
@@ -561,7 +560,7 @@ void CastSocketImpl::OnUpgradeToTLS(
int result,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream,
- const base::Optional<net::SSLInfo>& ssl_info) {
+ const absl::optional<net::SSLInfo>& ssl_info) {
if (result == net::OK) {
mojo_data_pump_ = std::make_unique<MojoDataPump>(std::move(receive_stream),
std::move(send_stream));
diff --git a/chromium/components/cast_channel/cast_socket.h b/chromium/components/cast_channel/cast_socket.h
index ad420f942f9..bdf05e2095a 100644
--- a/chromium/components/cast_channel/cast_socket.h
+++ b/chromium/components/cast_channel/cast_socket.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <queue>
-#include <string>
#include "base/cancelable_callback.h"
#include "base/gtest_prod_util.h"
@@ -311,14 +310,14 @@ class CastSocketImpl : public CastSocket {
// Callback from network::mojom::NetworkContext::CreateTCPConnectedSocket.
void OnConnect(int result,
- const base::Optional<net::IPEndPoint>& local_addr,
- const base::Optional<net::IPEndPoint>& peer_addr,
+ const absl::optional<net::IPEndPoint>& local_addr,
+ const absl::optional<net::IPEndPoint>& peer_addr,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream);
void OnUpgradeToTLS(int result,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream,
- const base::Optional<net::SSLInfo>& ssl_info);
+ const absl::optional<net::SSLInfo>& ssl_info);
/////////////////////////////////////////////////////////////////////////////
// Resets the cancellable callback used for async invocations of
diff --git a/chromium/components/cast_channel/cast_socket_service.h b/chromium/components/cast_channel/cast_socket_service.h
index 776f05da2cb..f241d956b98 100644
--- a/chromium/components/cast_channel/cast_socket_service.h
+++ b/chromium/components/cast_channel/cast_socket_service.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_CAST_CHANNEL_CAST_CHANNEL_SERVICE_H_
-#define COMPONENTS_CAST_CHANNEL_CAST_CHANNEL_SERVICE_H_
+#ifndef COMPONENTS_CAST_CHANNEL_CAST_SOCKET_SERVICE_H_
+#define COMPONENTS_CAST_CHANNEL_CAST_SOCKET_SERVICE_H_
#include <map>
#include <memory>
@@ -129,4 +129,4 @@ class CastSocketServiceImpl : public CastSocketService {
} // namespace cast_channel
-#endif // COMPONENTS_CAST_CHANNEL_CAST_CHANNEL_SERVICE_H_
+#endif // COMPONENTS_CAST_CHANNEL_CAST_SOCKET_SERVICE_H_
diff --git a/chromium/components/cast_channel/cast_socket_service_unittest.cc b/chromium/components/cast_channel/cast_socket_service_unittest.cc
index b5177308452..1e6458f48ed 100644
--- a/chromium/components/cast_channel/cast_socket_service_unittest.cc
+++ b/chromium/components/cast_channel/cast_socket_service_unittest.cc
@@ -5,6 +5,7 @@
#include "components/cast_channel/cast_socket_service.h"
#include "base/memory/ptr_util.h"
+#include "base/test/gmock_callback_support.h"
#include "base/test/mock_callback.h"
#include "base/test/test_simple_task_runner.h"
#include "components/cast_channel/cast_test_util.h"
@@ -84,11 +85,8 @@ TEST_F(CastSocketServiceTest, TestOpenChannel) {
mock_socket->SetIPEndpoint(ip_endpoint);
cast_socket_service_->SetSocketForTest(base::WrapUnique(mock_socket));
- EXPECT_CALL(*mock_socket, ConnectInternal(_))
- .WillOnce(WithArgs<0>(
- Invoke([&](const MockCastSocket::MockOnOpenCallback& callback) {
- callback.Run(mock_socket);
- })));
+ EXPECT_CALL(*mock_socket, Connect_(_))
+ .WillOnce(base::test::RunOnceCallback<0>(mock_socket));
EXPECT_CALL(mock_on_open_callback_, Run(mock_socket));
EXPECT_CALL(*mock_socket, AddObserver(_));
diff --git a/chromium/components/cast_channel/cast_socket_unittest.cc b/chromium/components/cast_channel/cast_socket_unittest.cc
index 7159bd2a82c..d4bb2347772 100644
--- a/chromium/components/cast_channel/cast_socket_unittest.cc
+++ b/chromium/components/cast_channel/cast_socket_unittest.cc
@@ -441,7 +441,7 @@ class MockCastSocketTest : public CastSocketTestBase {
socket_->SetupMockTransport();
CastMessage challenge_proto = CreateAuthChallenge();
EXPECT_CALL(*socket_->GetMockTransport(),
- SendMessage(EqualsProto(challenge_proto), _))
+ SendMessage_(EqualsProto(challenge_proto), _))
.WillOnce(PostCompletionCallbackTask<1>(net::OK));
EXPECT_CALL(*socket_->GetMockTransport(), Start());
EXPECT_CALL(handler_, OnConnectComplete(socket_.get()));
@@ -658,7 +658,7 @@ TEST_F(MockCastSocketTest, TestConnectAuthMessageCorrupted) {
CastMessage challenge_proto = CreateAuthChallenge();
EXPECT_CALL(*socket_->GetMockTransport(),
- SendMessage(EqualsProto(challenge_proto), _))
+ SendMessage_(EqualsProto(challenge_proto), _))
.WillOnce(PostCompletionCallbackTask<1>(net::OK));
EXPECT_CALL(*socket_->GetMockTransport(), Start());
EXPECT_CALL(handler_, OnConnectComplete(socket_.get()));
@@ -826,7 +826,7 @@ TEST_F(MockCastSocketTest, TestConnectChallengeSendError) {
client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK);
client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, net::OK);
EXPECT_CALL(*socket_->GetMockTransport(),
- SendMessage(EqualsProto(CreateAuthChallenge()), _))
+ SendMessage_(EqualsProto(CreateAuthChallenge()), _))
.WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET));
EXPECT_CALL(handler_, OnConnectComplete(socket_.get()));
@@ -846,7 +846,7 @@ TEST_F(MockCastSocketTest, TestConnectDestroyedAfterChallengeSent) {
client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK);
client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, net::OK);
EXPECT_CALL(*socket_->GetMockTransport(),
- SendMessage(EqualsProto(CreateAuthChallenge()), _))
+ SendMessage_(EqualsProto(CreateAuthChallenge()), _))
.WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET));
socket_->Connect(base::BindOnce(&CompleteHandler::OnConnectComplete,
base::Unretained(&handler_)));
@@ -863,7 +863,7 @@ TEST_F(MockCastSocketTest, TestConnectChallengeReplyReceiveError) {
client_socket_factory()->SetupTcpConnect(net::SYNCHRONOUS, net::OK);
client_socket_factory()->SetupSslConnect(net::SYNCHRONOUS, net::OK);
EXPECT_CALL(*socket_->GetMockTransport(),
- SendMessage(EqualsProto(CreateAuthChallenge()), _))
+ SendMessage_(EqualsProto(CreateAuthChallenge()), _))
.WillOnce(PostCompletionCallbackTask<1>(net::OK));
client_socket_factory()->AddReadResult(net::SYNCHRONOUS, net::ERR_FAILED);
EXPECT_CALL(*observer_, OnError(_, ChannelError::CAST_SOCKET_ERROR));
@@ -891,7 +891,7 @@ TEST_F(MockCastSocketTest, TestConnectChallengeVerificationFails) {
EXPECT_CALL(*observer_, OnError(_, ChannelError::AUTHENTICATION_ERROR));
CastMessage challenge_proto = CreateAuthChallenge();
EXPECT_CALL(*socket_->GetMockTransport(),
- SendMessage(EqualsProto(challenge_proto), _))
+ SendMessage_(EqualsProto(challenge_proto), _))
.WillOnce(PostCompletionCallbackTask<1>(net::OK));
EXPECT_CALL(handler_, OnConnectComplete(socket_.get()));
EXPECT_CALL(*socket_->GetMockTransport(), Start());
diff --git a/chromium/components/cast_channel/cast_test_util.h b/chromium/components/cast_channel/cast_test_util.h
index 01b22c62c7a..40eac4dde93 100644
--- a/chromium/components/cast_channel/cast_test_util.h
+++ b/chromium/components/cast_channel/cast_test_util.h
@@ -39,12 +39,12 @@ class MockCastTransport : public CastTransport {
net::CompletionOnceCallback callback) override {
// GMock does not handle move-only types, we need to rely on a mock method
// that takes a repeating callback, which will work well with GMock actions.
- SendMessage(message, base::AdaptCallbackForRepeating(std::move(callback)));
+ SendMessage_(message, callback);
}
- MOCK_METHOD2(SendMessage,
+ MOCK_METHOD2(SendMessage_,
void(const CastMessage& message,
- const net::CompletionRepeatingCallback& callback));
+ net::CompletionOnceCallback& callback));
MOCK_METHOD0(Start, void(void));
@@ -89,15 +89,12 @@ class MockCastSocketService : public CastSocketServiceImpl {
void OpenSocket(NetworkContextGetter network_context_getter,
const CastSocketOpenParams& open_params,
CastSocket::OnOpenCallback open_cb) override {
- // Unit test should not call |open_cb| more than once. Just use
- // base::AdaptCallbackForRepeating to pass |open_cb| to a mock method.
- OpenSocketInternal(open_params.ip_endpoint,
- base::AdaptCallbackForRepeating(std::move(open_cb)));
+ OpenSocket_(open_params.ip_endpoint, open_cb);
}
- MOCK_METHOD2(OpenSocketInternal,
+ MOCK_METHOD2(OpenSocket_,
void(const net::IPEndPoint& ip_endpoint,
- const base::RepeatingCallback<void(CastSocket*)>& open_cb));
+ CastSocket::OnOpenCallback& open_cb));
MOCK_CONST_METHOD1(GetSocket, CastSocket*(int channel_id));
};
@@ -109,19 +106,17 @@ class MockCastSocket : public CastSocket {
~MockCastSocket() override;
void Connect(CastSocket::OnOpenCallback callback) override {
- // Unit test should not call |open_cb| more than once. Just use
- // base::AdaptCallbackForRepeating to pass |open_cb| to a mock method.
- ConnectInternal(base::AdaptCallbackForRepeating(std::move(callback)));
+ Connect_(callback);
}
void Close(net::CompletionOnceCallback callback) override {
// GMock does not handle move-only types, we need to rely on a mock method
// that takes a repeating callback, which will work well with GMock actions.
- Close(base::AdaptCallbackForRepeating(std::move(callback)));
+ Close_(callback);
}
- MOCK_METHOD1(ConnectInternal, void(const MockOnOpenCallback& callback));
- MOCK_METHOD1(Close, void(const net::CompletionRepeatingCallback& callback));
+ MOCK_METHOD1(Connect_, void(CastSocket::OnOpenCallback& callback));
+ MOCK_METHOD1(Close_, void(net::CompletionOnceCallback& callback));
MOCK_CONST_METHOD0(ready_state, ReadyState());
MOCK_METHOD1(AddObserver, void(Observer* observer));
MOCK_METHOD1(RemoveObserver, void(Observer* observer));
@@ -187,19 +182,19 @@ class MockCastMessageHandler : public CastMessageHandler {
const std::string&,
base::TimeDelta,
const std::vector<std::string>&,
- const base::Optional<base::Value>&,
+ const absl::optional<base::Value>&,
LaunchSessionCallback callback));
MOCK_METHOD4(StopSession,
void(int channel_id,
const std::string& session_id,
- const base::Optional<std::string>& client_id,
+ const absl::optional<std::string>& client_id,
ResultCallback callback));
MOCK_METHOD2(SendAppMessage,
Result(int channel_id, const CastMessage& message));
MOCK_METHOD2(SendCastMessage,
Result(int channel_id, const CastMessage& message));
MOCK_METHOD4(SendMediaRequest,
- base::Optional<int>(int channel_id,
+ absl::optional<int>(int channel_id,
const base::Value& body,
const std::string& source_id,
const std::string& destination_id));
@@ -231,7 +226,7 @@ ACTION_TEMPLATE(PostCompletionCallbackTask,
HAS_1_TEMPLATE_PARAMS(int, cb_idx),
AND_1_VALUE_PARAMS(rv)) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(testing::get<cb_idx>(args), rv));
+ FROM_HERE, base::BindOnce(std::move(testing::get<cb_idx>(args)), rv));
}
} // namespace cast_channel
diff --git a/chromium/components/cast_channel/cast_transport.cc b/chromium/components/cast_channel/cast_transport.cc
index 373c197db41..340318f6bca 100644
--- a/chromium/components/cast_channel/cast_transport.cc
+++ b/chromium/components/cast_channel/cast_transport.cc
@@ -16,7 +16,6 @@
#include "base/location.h"
#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/cast_channel/cast_framer.h"
#include "components/cast_channel/cast_message_util.h"
diff --git a/chromium/components/cast_channel/cast_transport_unittest.cc b/chromium/components/cast_channel/cast_transport_unittest.cc
index 43ad1c2d8b4..a3d0ce50798 100644
--- a/chromium/components/cast_channel/cast_transport_unittest.cc
+++ b/chromium/components/cast_channel/cast_transport_unittest.cc
@@ -121,7 +121,7 @@ ACTION_TEMPLATE(FillBufferFromString,
ACTION_TEMPLATE(EnqueueCallback,
HAS_1_TEMPLATE_PARAMS(int, cb_idx),
AND_1_VALUE_PARAMS(completion_queue)) {
- completion_queue->Push(testing::get<cb_idx>(args));
+ completion_queue->Push(std::move(testing::get<cb_idx>(args)));
}
} // namespace
@@ -131,24 +131,24 @@ class MockSocket : public cast_channel::CastTransportImpl::Channel {
void Read(net::IOBuffer* buffer,
int bytes,
net::CompletionOnceCallback callback) override {
- Read(buffer, bytes, base::AdaptCallbackForRepeating(std::move(callback)));
+ Read_(buffer, bytes, callback);
}
void Write(net::IOBuffer* buffer,
int bytes,
net::CompletionOnceCallback callback) override {
- Write(buffer, bytes, base::AdaptCallbackForRepeating(std::move(callback)));
+ Write_(buffer, bytes, callback);
}
- MOCK_METHOD3(Read,
+ MOCK_METHOD3(Read_,
void(net::IOBuffer* buf,
int buf_len,
- const net::CompletionRepeatingCallback& callback));
+ net::CompletionOnceCallback& callback));
- MOCK_METHOD3(Write,
+ MOCK_METHOD3(Write_,
void(net::IOBuffer* buf,
int buf_len,
- const net::CompletionRepeatingCallback& callback));
+ net::CompletionOnceCallback& callback));
};
class CastTransportTest : public testing::Test {
@@ -186,7 +186,7 @@ TEST_F(CastTransportTest, TestFullWriteAsync) {
std::string serialized_message;
EXPECT_TRUE(MessageFramer::Serialize(message, &serialized_message));
- EXPECT_CALL(mock_socket_, Write(NotNull(), serialized_message.size(), _))
+ EXPECT_CALL(mock_socket_, Write_(NotNull(), serialized_message.size(), _))
.WillOnce(DoAll(ReadBufferToString<0, 1>(&output),
EnqueueCallback<2>(&socket_cbs)));
EXPECT_CALL(write_handler, Complete(net::OK));
@@ -211,13 +211,13 @@ TEST_F(CastTransportTest, TestPartialWritesAsync) {
// Only one byte is written.
EXPECT_CALL(mock_socket_,
- Write(NotNull(), static_cast<int>(serialized_message.size()), _))
+ Write_(NotNull(), static_cast<int>(serialized_message.size()), _))
.WillOnce(DoAll(ReadBufferToString<0, 1>(&output),
EnqueueCallback<2>(&socket_cbs)));
// Remainder of bytes are written.
EXPECT_CALL(
mock_socket_,
- Write(NotNull(), static_cast<int>(serialized_message.size() - 1), _))
+ Write_(NotNull(), static_cast<int>(serialized_message.size() - 1), _))
.WillOnce(DoAll(ReadBufferToString<0, 1>(&output),
EnqueueCallback<2>(&socket_cbs)));
@@ -240,7 +240,7 @@ TEST_F(CastTransportTest, TestWriteFailureAsync) {
CompletionQueue socket_cbs;
CompleteHandler write_handler;
CastMessage message = CreateCastMessage();
- EXPECT_CALL(mock_socket_, Write(NotNull(), _, _))
+ EXPECT_CALL(mock_socket_, Write_(NotNull(), _, _))
.WillOnce(EnqueueCallback<2>(&socket_cbs));
EXPECT_CALL(write_handler, Complete(net::ERR_FAILED));
EXPECT_CALL(*delegate_, OnError(ChannelError::CAST_SOCKET_ERROR));
@@ -269,16 +269,16 @@ TEST_F(CastTransportTest, TestFullReadAsync) {
// Read bytes [0, 3].
EXPECT_CALL(mock_socket_,
- Read(NotNull(), MessageFramer::MessageHeader::header_size(), _))
+ Read_(NotNull(), MessageFramer::MessageHeader::header_size(), _))
.WillOnce(DoAll(FillBufferFromString<0>(serialized_message),
EnqueueCallback<2>(&socket_cbs)));
// Read bytes [4, n].
EXPECT_CALL(mock_socket_,
- Read(NotNull(),
- serialized_message.size() -
- MessageFramer::MessageHeader::header_size(),
- _))
+ Read_(NotNull(),
+ serialized_message.size() -
+ MessageFramer::MessageHeader::header_size(),
+ _))
.WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr(
MessageFramer::MessageHeader::header_size(),
serialized_message.size() -
@@ -288,7 +288,7 @@ TEST_F(CastTransportTest, TestFullReadAsync) {
EXPECT_CALL(*delegate_, OnMessage(EqualsProto(message)));
EXPECT_CALL(mock_socket_,
- Read(NotNull(), MessageFramer::MessageHeader::header_size(), _));
+ Read_(NotNull(), MessageFramer::MessageHeader::header_size(), _));
transport_->Start();
RunPendingTasks();
socket_cbs.Pop(MessageFramer::MessageHeader::header_size());
@@ -309,16 +309,16 @@ TEST_F(CastTransportTest, TestPartialReadAsync) {
// Read bytes [0, 3].
EXPECT_CALL(mock_socket_,
- Read(NotNull(), MessageFramer::MessageHeader::header_size(), _))
+ Read_(NotNull(), MessageFramer::MessageHeader::header_size(), _))
.WillOnce(DoAll(FillBufferFromString<0>(serialized_message),
EnqueueCallback<2>(&socket_cbs)))
.RetiresOnSaturation();
// Read bytes [4, n-1].
EXPECT_CALL(mock_socket_,
- Read(NotNull(),
- serialized_message.size() -
- MessageFramer::MessageHeader::header_size(),
- _))
+ Read_(NotNull(),
+ serialized_message.size() -
+ MessageFramer::MessageHeader::header_size(),
+ _))
.WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr(
MessageFramer::MessageHeader::header_size(),
serialized_message.size() -
@@ -326,7 +326,7 @@ TEST_F(CastTransportTest, TestPartialReadAsync) {
EnqueueCallback<2>(&socket_cbs)))
.RetiresOnSaturation();
// Read final byte.
- EXPECT_CALL(mock_socket_, Read(NotNull(), 1, _))
+ EXPECT_CALL(mock_socket_, Read_(NotNull(), 1, _))
.WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr(
serialized_message.size() - 1, 1)),
EnqueueCallback<2>(&socket_cbs)))
@@ -337,7 +337,7 @@ TEST_F(CastTransportTest, TestPartialReadAsync) {
socket_cbs.Pop(serialized_message.size() -
MessageFramer::MessageHeader::header_size() - 1);
EXPECT_CALL(mock_socket_,
- Read(NotNull(), MessageFramer::MessageHeader::header_size(), _));
+ Read_(NotNull(), MessageFramer::MessageHeader::header_size(), _));
socket_cbs.Pop(1);
}
@@ -352,7 +352,7 @@ TEST_F(CastTransportTest, TestReadErrorInHeaderAsync) {
// Read bytes [0, 3].
EXPECT_CALL(mock_socket_,
- Read(NotNull(), MessageFramer::MessageHeader::header_size(), _))
+ Read_(NotNull(), MessageFramer::MessageHeader::header_size(), _))
.WillOnce(DoAll(FillBufferFromString<0>(serialized_message),
EnqueueCallback<2>(&socket_cbs)))
.RetiresOnSaturation();
@@ -378,16 +378,16 @@ TEST_F(CastTransportTest, TestReadErrorInBodyAsync) {
// Read bytes [0, 3].
EXPECT_CALL(mock_socket_,
- Read(NotNull(), MessageFramer::MessageHeader::header_size(), _))
+ Read_(NotNull(), MessageFramer::MessageHeader::header_size(), _))
.WillOnce(DoAll(FillBufferFromString<0>(serialized_message),
EnqueueCallback<2>(&socket_cbs)))
.RetiresOnSaturation();
// Read bytes [4, n-1].
EXPECT_CALL(mock_socket_,
- Read(NotNull(),
- serialized_message.size() -
- MessageFramer::MessageHeader::header_size(),
- _))
+ Read_(NotNull(),
+ serialized_message.size() -
+ MessageFramer::MessageHeader::header_size(),
+ _))
.WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr(
MessageFramer::MessageHeader::header_size(),
serialized_message.size() -
@@ -422,16 +422,16 @@ TEST_F(CastTransportTest, TestReadCorruptedMessageAsync) {
EXPECT_CALL(*delegate_, Start());
// Read bytes [0, 3].
EXPECT_CALL(mock_socket_,
- Read(NotNull(), MessageFramer::MessageHeader::header_size(), _))
+ Read_(NotNull(), MessageFramer::MessageHeader::header_size(), _))
.WillOnce(DoAll(FillBufferFromString<0>(serialized_message),
EnqueueCallback<2>(&socket_cbs)))
.RetiresOnSaturation();
// Read bytes [4, n].
EXPECT_CALL(mock_socket_,
- Read(NotNull(),
- serialized_message.size() -
- MessageFramer::MessageHeader::header_size(),
- _))
+ Read_(NotNull(),
+ serialized_message.size() -
+ MessageFramer::MessageHeader::header_size(),
+ _))
.WillOnce(DoAll(FillBufferFromString<0>(serialized_message.substr(
MessageFramer::MessageHeader::header_size(),
serialized_message.size() -
diff --git a/chromium/components/cast_channel/enum_table.cc b/chromium/components/cast_channel/enum_table.cc
index d40033c3002..6162a1c72be 100644
--- a/chromium/components/cast_channel/enum_table.cc
+++ b/chromium/components/cast_channel/enum_table.cc
@@ -30,7 +30,7 @@ const GenericEnumTableEntry* GenericEnumTableEntry::FindByString(
}
// static
-base::Optional<base::StringPiece> GenericEnumTableEntry::FindByValue(
+absl::optional<base::StringPiece> GenericEnumTableEntry::FindByValue(
const GenericEnumTableEntry data[],
std::size_t size,
int value) {
@@ -38,7 +38,7 @@ base::Optional<base::StringPiece> GenericEnumTableEntry::FindByValue(
if (data[i].value == value && data[i].has_str())
return data[i].str();
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace cast_util
diff --git a/chromium/components/cast_channel/enum_table.h b/chromium/components/cast_channel/enum_table.h
index e3130c7b326..cca3a6650a6 100644
--- a/chromium/components/cast_channel/enum_table.h
+++ b/chromium/components/cast_channel/enum_table.h
@@ -11,9 +11,9 @@
#include "base/check_op.h"
#include "base/macros.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
// TODO(jrw): Move this file to a more appropriate directory.
//
@@ -192,7 +192,7 @@ class
const GenericEnumTableEntry data[],
std::size_t size,
base::StringPiece str);
- static base::Optional<base::StringPiece>
+ static absl::optional<base::StringPiece>
FindByValue(const GenericEnumTableEntry data[], std::size_t size, int value);
constexpr base::StringPiece str() const {
@@ -302,7 +302,7 @@ class EnumTable {
// Gets the string associated with the given enum value. When the argument
// is a constant, prefer the zero-argument form below.
- inline base::Optional<base::StringPiece> GetString(E value) const {
+ inline absl::optional<base::StringPiece> GetString(E value) const {
if (is_sorted_) {
const std::size_t index = static_cast<std::size_t>(value);
if (ANALYZER_ASSUME_TRUE(index < data_.size())) {
@@ -310,7 +310,7 @@ class EnumTable {
if (ANALYZER_ASSUME_TRUE(entry.has_str()))
return entry.str();
}
- return base::nullopt;
+ return absl::nullopt;
}
return GenericEnumTableEntry::FindByValue(
reinterpret_cast<const GenericEnumTableEntry*>(data_.begin()),
@@ -340,11 +340,11 @@ class EnumTable {
// GetString(), this method is not defined as a constexpr, because it should
// never be called with a literal string; it's simpler to just refer to the
// enum value directly.
- base::Optional<E> GetEnum(base::StringPiece str) const {
+ absl::optional<E> GetEnum(base::StringPiece str) const {
auto* entry = GenericEnumTableEntry::FindByString(
reinterpret_cast<const GenericEnumTableEntry*>(data_.begin()),
data_.size(), str);
- return entry ? static_cast<E>(entry->value) : base::Optional<E>();
+ return entry ? static_cast<E>(entry->value) : absl::optional<E>();
}
// The default instance of this class. There should normally only be one
@@ -383,7 +383,7 @@ class EnumTable {
#ifndef NDEBUG
// Finds and returns the first i for which data[i].value != i;
- constexpr static base::Optional<std::size_t> FindNonConsecutiveEntry(
+ constexpr static absl::optional<std::size_t> FindNonConsecutiveEntry(
std::initializer_list<Entry> data) {
int32_t counter = 0;
for (const auto& entry : data) {
@@ -402,7 +402,7 @@ class EnumTable {
// Converts an enum value to a string using the default table
// (EnumTable<E>::instance) for the given enum type.
template <typename E>
-inline base::Optional<base::StringPiece> EnumToString(E value) {
+inline absl::optional<base::StringPiece> EnumToString(E value) {
return EnumTable<E>::GetInstance().GetString(value);
}
@@ -426,7 +426,7 @@ inline base::StringPiece EnumToString() {
// Converts a string to an enum value using the default table
// (EnumTable<E>::instance) for the given enum type.
template <typename E>
-inline base::Optional<E> StringToEnum(base::StringPiece str) {
+inline absl::optional<E> StringToEnum(base::StringPiece str) {
return EnumTable<E>::GetInstance().GetEnum(str);
}
diff --git a/chromium/components/cast_channel/enum_table_unittest.cc b/chromium/components/cast_channel/enum_table_unittest.cc
index 5ba3fc88a2f..250c7191aec 100644
--- a/chromium/components/cast_channel/enum_table_unittest.cc
+++ b/chromium/components/cast_channel/enum_table_unittest.cc
@@ -5,9 +5,9 @@
#include "components/cast_channel/enum_table.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace cast_util {
namespace {
@@ -61,12 +61,12 @@ TEST(EnumTableTest, TestGetStringUnsorted) {
TEST(EnumTableTest, TestGetMissingString) {
EXPECT_EQ("ZERO", kSortedMissing.GetString(MyEnum::kZero));
- EXPECT_EQ(base::nullopt, kSortedMissing.GetString(MyEnum::kOne));
+ EXPECT_EQ(absl::nullopt, kSortedMissing.GetString(MyEnum::kOne));
EXPECT_EQ("TWO", kSortedMissing.GetString(MyEnum::kTwo));
}
TEST(EnumTableTest, TestGetMissingStringUnsorted) {
- EXPECT_EQ(base::nullopt, kUnsortedMissing.GetString(MyEnum::kZero));
+ EXPECT_EQ(absl::nullopt, kUnsortedMissing.GetString(MyEnum::kZero));
EXPECT_EQ("ONE", kUnsortedMissing.GetString(MyEnum::kOne));
EXPECT_EQ("TWO", kUnsortedMissing.GetString(MyEnum::kTwo));
}
@@ -94,16 +94,16 @@ TEST(EnumTableTest, TestGetEnum) {
EXPECT_EQ(MyEnum::kZero, kSorted.GetEnum("ZERO"));
EXPECT_EQ(MyEnum::kOne, kSorted.GetEnum("ONE"));
EXPECT_EQ(MyEnum::kTwo, kSorted.GetEnum("TWO"));
- EXPECT_EQ(base::nullopt, kSorted.GetEnum("THREE"));
- EXPECT_EQ(base::nullopt, kSorted.GetEnum(""));
+ EXPECT_EQ(absl::nullopt, kSorted.GetEnum("THREE"));
+ EXPECT_EQ(absl::nullopt, kSorted.GetEnum(""));
}
TEST(EnumTableTest, TestStringToEnumGlobal) {
EXPECT_EQ(MyEnum::kZero, StringToEnum<MyEnum>("ZERO_DEFAULT"));
EXPECT_EQ(MyEnum::kOne, StringToEnum<MyEnum>("ONE_DEFAULT"));
EXPECT_EQ(MyEnum::kTwo, StringToEnum<MyEnum>("TWO_DEFAULT"));
- EXPECT_EQ(base::nullopt, StringToEnum<MyEnum>("THREE"));
- EXPECT_EQ(base::nullopt, StringToEnum<MyEnum>(""));
+ EXPECT_EQ(absl::nullopt, StringToEnum<MyEnum>("THREE"));
+ EXPECT_EQ(absl::nullopt, StringToEnum<MyEnum>(""));
}
// See note in enum_table.h for details of why these tests have to be compiled
diff --git a/chromium/components/cast_channel/keep_alive_delegate_unittest.cc b/chromium/components/cast_channel/keep_alive_delegate_unittest.cc
index f71a77ed807..11df52429ed 100644
--- a/chromium/components/cast_channel/keep_alive_delegate_unittest.cc
+++ b/chromium/components/cast_channel/keep_alive_delegate_unittest.cc
@@ -119,7 +119,7 @@ TEST_F(KeepAliveDelegateTest, TestErrorHandledBeforeStarting) {
TEST_F(KeepAliveDelegateTest, TestPing) {
EXPECT_CALL(*socket_.mock_transport(),
- SendMessage(EqualsProto(CreateKeepAlivePingMessage()), _))
+ SendMessage_(EqualsProto(CreateKeepAlivePingMessage()), _))
.WillOnce(PostCompletionCallbackTask<1>(net::OK));
EXPECT_CALL(*inner_delegate_, Start());
EXPECT_CALL(*ping_timer_, ResetTriggered()).Times(2);
@@ -137,7 +137,7 @@ TEST_F(KeepAliveDelegateTest, TestPing) {
TEST_F(KeepAliveDelegateTest, TestPingFailed) {
EXPECT_CALL(*socket_.mock_transport(),
- SendMessage(EqualsProto(CreateKeepAlivePingMessage()), _))
+ SendMessage_(EqualsProto(CreateKeepAlivePingMessage()), _))
.WillOnce(PostCompletionCallbackTask<1>(net::ERR_CONNECTION_RESET));
EXPECT_CALL(*inner_delegate_, Start());
EXPECT_CALL(*inner_delegate_, OnError(ChannelError::CAST_SOCKET_ERROR));
@@ -157,7 +157,7 @@ TEST_F(KeepAliveDelegateTest, TestPingFailed) {
TEST_F(KeepAliveDelegateTest, TestPingAndLivenessTimeout) {
EXPECT_CALL(*socket_.mock_transport(),
- SendMessage(EqualsProto(CreateKeepAlivePingMessage()), _))
+ SendMessage_(EqualsProto(CreateKeepAlivePingMessage()), _))
.WillOnce(PostCompletionCallbackTask<1>(net::OK));
EXPECT_CALL(*inner_delegate_, OnError(ChannelError::PING_TIMEOUT));
EXPECT_CALL(*inner_delegate_, Start());
@@ -248,7 +248,7 @@ TEST_F(KeepAliveDelegateTest, TestLivenessTimerResetAfterSendingMessage) {
keep_alive_->Start();
EXPECT_CALL(*socket_.mock_transport(),
- SendMessage(EqualsProto(CreateKeepAlivePingMessage()), _))
+ SendMessage_(EqualsProto(CreateKeepAlivePingMessage()), _))
.WillOnce(PostCompletionCallbackTask<1>(net::OK));
// Forward 1s, at time 1, fire ping timer.
mock_time_task_runner->FastForwardBy(
diff --git a/chromium/components/cast_channel/libcast_socket_service.h b/chromium/components/cast_channel/libcast_socket_service.h
index a9d6c26bcbe..c0d2005c288 100644
--- a/chromium/components/cast_channel/libcast_socket_service.h
+++ b/chromium/components/cast_channel/libcast_socket_service.h
@@ -15,7 +15,6 @@
#include "components/cast_channel/cast_socket.h"
#include "components/cast_channel/cast_socket_service.h"
#include "components/openscreen_platform/task_runner.h"
-#include "services/network/public/mojom/network_context.mojom.h"
#include "third_party/openscreen/src/cast/common/public/cast_socket.h"
#include "third_party/openscreen/src/cast/sender/public/sender_socket_factory.h"
#include "third_party/openscreen/src/platform/api/tls_connection_factory.h"
diff --git a/chromium/components/cast_channel/logger.h b/chromium/components/cast_channel/logger.h
index f4d91e8bda5..a4b9c8e848c 100644
--- a/chromium/components/cast_channel/logger.h
+++ b/chromium/components/cast_channel/logger.h
@@ -9,7 +9,6 @@
#include <map>
#include <memory>
-#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/components/cast_streaming/BUILD.gn b/chromium/components/cast_streaming/BUILD.gn
new file mode 100644
index 00000000000..dd23c30858b
--- /dev/null
+++ b/chromium/components/cast_streaming/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("unit_tests") {
+ testonly = true
+ deps = [
+ "//components/cast_streaming/browser:unit_tests",
+ "//components/cast_streaming/renderer:unit_tests",
+ ]
+}
diff --git a/chromium/components/cast_streaming/DEPS b/chromium/components/cast_streaming/DEPS
new file mode 100644
index 00000000000..cce7e7985ea
--- /dev/null
+++ b/chromium/components/cast_streaming/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "+content/public/common",
+ "-components/cast_streaming",
+ "+net",
+ "+services/network/public",
+]
diff --git a/chromium/components/cast_streaming/DIR_METADATA b/chromium/components/cast_streaming/DIR_METADATA
new file mode 100644
index 00000000000..6ea7faa66c9
--- /dev/null
+++ b/chromium/components/cast_streaming/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Internals>Cast>Providers"
+}
diff --git a/chromium/components/cast_streaming/OWNERS b/chromium/components/cast_streaming/OWNERS
new file mode 100644
index 00000000000..456541a3141
--- /dev/null
+++ b/chromium/components/cast_streaming/OWNERS
@@ -0,0 +1,3 @@
+jophba@chromium.org
+fdegans@chromium.org
+rwkeane@google.com
diff --git a/chromium/components/cast_streaming/README.md b/chromium/components/cast_streaming/README.md
new file mode 100644
index 00000000000..ca91ed0d835
--- /dev/null
+++ b/chromium/components/cast_streaming/README.md
@@ -0,0 +1,10 @@
+# Introduction
+
+This directory defines a wrapper around the LibCast implementation of Cast
+Streaming (found in //third_party/openscreen/src) to allow for integration with
+the Chromium Renderer pipeline.
+
+Currently, this code is used in production //fuchsia code, with further uses in
+progress.
+
+TODO(crbug.com/1208196): Expand upon this file.
diff --git a/chromium/components/cast_streaming/browser/BUILD.gn b/chromium/components/cast_streaming/browser/BUILD.gn
new file mode 100644
index 00000000000..80cc843654c
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/BUILD.gn
@@ -0,0 +1,154 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//testing/test.gni")
+
+# TODO(crbug.com/1207718): Remove cast_message_port_impl code from this
+# component and replace with a more general interface.
+# TODO(crbug.com/1208195): Move code to correct place with respect to the
+# /public folder to only expose publicly needed headers.
+source_set("core") {
+ deps = [
+ "//base",
+ "//media",
+ ]
+ public_deps = [
+ "//components/cast/message_port",
+ "//third_party/openscreen/src/cast/common:public",
+ "//third_party/openscreen/src/cast/streaming:common",
+ ]
+ visibility = [ ":*" ]
+ sources = [
+ "cast_message_port_impl.cc",
+ "cast_message_port_impl.h",
+ "config_conversions.cc",
+ "config_conversions.h",
+ "message_serialization.cc",
+ "message_serialization.h",
+ ]
+}
+
+source_set("receiver_session") {
+ deps = [
+ ":core",
+ "//base",
+ "//components/openscreen_platform",
+ "//media",
+ "//media/mojo/common",
+ "//media/mojo/mojom",
+ "//mojo/public/cpp/system",
+ "//third_party/openscreen/src/cast/common:public",
+ "//third_party/openscreen/src/cast/streaming:receiver",
+ "//third_party/openscreen/src/util",
+ ]
+ public_deps = [ "//components/cast/message_port" ]
+ visibility = [ ":*" ]
+ public = [ "public/cast_streaming_session.h" ]
+ sources = [
+ "cast_streaming_session.cc",
+ "stream_consumer.cc",
+ "stream_consumer.h",
+ ]
+}
+
+source_set("network_context") {
+ public = [ "public/network_context_getter.h" ]
+ deps = [
+ "//base",
+ "//components/openscreen_platform:openscreen_platform_network_service",
+ ]
+ visibility = [ ":*" ]
+ sources = [ "network_context_getter.cc" ]
+}
+
+# TODO(crbug.com/1208194): Also move cast_streaming_session_client here from
+# //fuchsia.
+source_set("browser") {
+ public_deps = [
+ ":network_context",
+ ":receiver_session",
+ ]
+}
+
+# TODO(crbug.com/1207715): Move to /tests directory.
+source_set("test_sender") {
+ testonly = true
+ deps = [
+ ":core",
+ "//media/mojo/common",
+ "//media/mojo/mojom",
+ "//mojo/public/cpp/system",
+ "//third_party/openscreen/src/platform:api",
+ "//third_party/openscreen/src/util",
+ ]
+ public_deps = [
+ "//base",
+ "//components/openscreen_platform",
+ "//media",
+ "//third_party/openscreen/src/cast/common:public",
+ "//third_party/openscreen/src/cast/streaming:sender",
+ ]
+ sources = [
+ "test/cast_message_port_sender_impl.cc",
+ "test/cast_message_port_sender_impl.h",
+ "test/cast_streaming_test_sender.cc",
+ "test/cast_streaming_test_sender.h",
+ ]
+}
+
+# TODO(crbug.com/1207715): Move to /tests directory.
+source_set("test_receiver") {
+ testonly = true
+ deps = [
+ ":receiver_session",
+ "//base",
+ "//components/openscreen_platform",
+ "//media",
+ "//media/mojo/common",
+ "//mojo/public/cpp/system",
+ "//third_party/openscreen/src/cast/common:public",
+ "//third_party/openscreen/src/cast/streaming:receiver",
+ "//third_party/openscreen/src/platform:api",
+ "//third_party/openscreen/src/util",
+ ]
+ visibility = [ ":*" ]
+ sources = [
+ "test/cast_streaming_test_receiver.cc",
+ "test/cast_streaming_test_receiver.h",
+ ]
+}
+
+# TODO(crbug.com/1207715): Move to /tests directory.
+test("e2e_tests") {
+ deps = [
+ ":core",
+ ":receiver_session",
+ ":test_receiver",
+ ":test_sender",
+ "//base/test:test_support",
+ "//components/openscreen_platform:openscreen_platform_net",
+ "//media",
+ "//mojo/core/embedder",
+ "//testing/gtest",
+ "//third_party/openscreen/src/platform:api",
+ ]
+ sources = [
+ "cast_streaming_session_unittest.cc",
+ "test/run_all_unittests.cc",
+ ]
+}
+
+# TODO(crbug.com/1207721): Add more unit tests for code in this directory.
+source_set("unit_tests") {
+ testonly = true
+ deps = [
+ ":browser",
+ ":core",
+ "//base",
+ "//base/test:test_support",
+ "//components/cast/message_port:test_message_port_receiver",
+ "//testing/gtest",
+ ]
+ sources = [ "cast_message_port_impl_unittest.cc" ]
+}
diff --git a/chromium/components/cast_streaming/browser/DEPS b/chromium/components/cast_streaming/browser/DEPS
new file mode 100644
index 00000000000..e76d5654b62
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/DEPS
@@ -0,0 +1,11 @@
+include_rules = [
+ "+components/cast/message_port",
+ "+components/cast_streaming/mojo",
+ "+components/openscreen_platform",
+ "+media/base",
+ "+media/mojo",
+ "+mojo/core",
+ "+mojo/public",
+ "+net/base",
+ "+third_party/openscreen/src",
+]
diff --git a/chromium/components/cast_streaming/browser/cast_message_port_impl.cc b/chromium/components/cast_streaming/browser/cast_message_port_impl.cc
new file mode 100644
index 00000000000..c9cbd3b7986
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/cast_message_port_impl.cc
@@ -0,0 +1,169 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// TODO(crbug.com/1207718): Delete this file.
+
+#include "components/cast_streaming/browser/cast_message_port_impl.h"
+
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/values.h"
+#include "components/cast_streaming/browser/message_serialization.h"
+#include "third_party/openscreen/src/platform/base/error.h"
+
+namespace cast_streaming {
+
+CastMessagePortImpl::CastMessagePortImpl(
+ std::unique_ptr<cast_api_bindings::MessagePort> message_port,
+ base::OnceClosure on_close)
+ : message_port_(std::move(message_port)), on_close_(std::move(on_close)) {
+ DVLOG(1) << __func__;
+ message_port_->SetReceiver(this);
+
+ // Initialize the connection with the Cast Streaming Sender.
+ PostMessage(kValueSystemSenderId, kSystemNamespace, kInitialConnectMessage);
+}
+
+CastMessagePortImpl::~CastMessagePortImpl() = default;
+
+void CastMessagePortImpl::MaybeClose() {
+ if (message_port_) {
+ message_port_.reset();
+ }
+ if (client_) {
+ client_->OnError(
+ openscreen::Error(openscreen::Error::Code::kCastV2CastSocketError));
+ }
+ if (on_close_) {
+ // |this| might be deleted as part of |on_close_| being run. Do not add any
+ // code after running the closure.
+ std::move(on_close_).Run();
+ }
+}
+
+void CastMessagePortImpl::SetClient(
+ openscreen::cast::MessagePort::Client* client,
+ std::string client_sender_id) {
+ DVLOG(2) << __func__;
+ DCHECK_NE(!client_, !client);
+ client_ = client;
+ if (!client_)
+ MaybeClose();
+}
+
+void CastMessagePortImpl::ResetClient() {
+ client_ = nullptr;
+ MaybeClose();
+}
+
+void CastMessagePortImpl::SendInjectResponse(const std::string& sender_id,
+ const std::string& message) {
+ absl::optional<base::Value> value = base::JSONReader::Read(message);
+ if (!value) {
+ LOG(ERROR) << "Malformed message from sender " << sender_id
+ << ": not a json payload:" << message;
+ return;
+ }
+
+ if (!value->is_dict()) {
+ LOG(ERROR) << "Malformed message from sender " << sender_id
+ << ": non-dictionary json payload: " << message;
+ return;
+ }
+
+ const std::string* type = value->FindStringKey(kKeyType);
+ if (!type) {
+ LOG(ERROR) << "Malformed message from sender " << sender_id
+ << ": no message type: " << message;
+ return;
+ }
+ if (*type != kValueWrapped) {
+ LOG(ERROR) << "Malformed message from sender " << sender_id
+ << ": unknown message type: " << *type;
+ return;
+ }
+
+ absl::optional<int> request_id = value->FindIntKey(kKeyRequestId);
+ if (!request_id) {
+ LOG(ERROR) << "Malformed message from sender " << sender_id
+ << ": no request id: " << message;
+ return;
+ }
+
+ // Build the response message.
+ base::Value response_value(base::Value::Type::DICTIONARY);
+ response_value.SetKey(kKeyType, base::Value(kValueError));
+ response_value.SetKey(kKeyRequestId, base::Value(request_id.value()));
+ response_value.SetKey(kKeyData, base::Value(kValueInjectNotSupportedError));
+ response_value.SetKey(kKeyCode, base::Value(kValueWrappedError));
+
+ std::string json_message;
+ CHECK(base::JSONWriter::Write(response_value, &json_message));
+ PostMessage(sender_id, kInjectNamespace, json_message);
+}
+
+void CastMessagePortImpl::PostMessage(const std::string& sender_id,
+ const std::string& message_namespace,
+ const std::string& message) {
+ DVLOG(3) << __func__;
+ if (!message_port_)
+ return;
+
+ DVLOG(3) << "Received Open Screen message. SenderId: " << sender_id
+ << ". Namespace: " << message_namespace << ". Message: " << message;
+ message_port_->PostMessage(
+ SerializeCastMessage(sender_id, message_namespace, message));
+}
+
+bool CastMessagePortImpl::OnMessage(
+ base::StringPiece message,
+ std::vector<std::unique_ptr<cast_api_bindings::MessagePort>> ports) {
+ DVLOG(3) << __func__;
+
+ // If |client_| was cleared, |message_port_| should have been reset.
+ DCHECK(client_);
+
+ if (!ports.empty()) {
+ // We should never receive any ports for Cast Streaming.
+ LOG(ERROR) << "Received ports on Cast Streaming MessagePort.";
+ return false;
+ }
+
+ std::string sender_id;
+ std::string message_namespace;
+ std::string str_message;
+ if (!DeserializeCastMessage(message, &sender_id, &message_namespace,
+ &str_message)) {
+ LOG(ERROR) << "Received bad message.";
+ client_->OnError(
+ openscreen::Error(openscreen::Error::Code::kCastV2InvalidMessage));
+ return true;
+ }
+ DVLOG(3) << "Received Cast message. SenderId: " << sender_id
+ << ". Namespace: " << message_namespace
+ << ". Message: " << str_message;
+
+ // TODO(b/156118960): Have Open Screen handle message namespaces.
+ if (message_namespace == kMirroringNamespace ||
+ message_namespace == kRemotingNamespace) {
+ client_->OnMessage(sender_id, message_namespace, str_message);
+ } else if (message_namespace == kInjectNamespace) {
+ SendInjectResponse(sender_id, str_message);
+ } else if (message_namespace != kSystemNamespace) {
+ // System messages are ignored, log messages from unknown namespaces.
+ DVLOG(2) << "Unknown message from " << sender_id
+ << ", namespace=" << message_namespace
+ << ", message=" << str_message;
+ }
+
+ return true;
+}
+
+void CastMessagePortImpl::OnPipeError() {
+ DVLOG(3) << __func__;
+ MaybeClose();
+}
+
+} // namespace cast_streaming
diff --git a/chromium/components/cast_streaming/browser/cast_message_port_impl.h b/chromium/components/cast_streaming/browser/cast_message_port_impl.h
new file mode 100644
index 00000000000..40a0105989e
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/cast_message_port_impl.h
@@ -0,0 +1,59 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// TODO(crbug.com/1207718): Delete this file.
+
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_CAST_MESSAGE_PORT_IMPL_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_CAST_MESSAGE_PORT_IMPL_H_
+
+#include "base/callback.h"
+#include "components/cast/message_port/message_port.h"
+#include "third_party/openscreen/src/cast/common/public/message_port.h"
+
+namespace cast_streaming {
+
+// Wrapper for a cast MessagePort that provides an Open Screen MessagePort
+// implementation.
+class CastMessagePortImpl : public openscreen::cast::MessagePort,
+ public cast_api_bindings::MessagePort::Receiver {
+ public:
+ CastMessagePortImpl(
+ std::unique_ptr<cast_api_bindings::MessagePort> message_port,
+ base::OnceClosure on_close);
+ ~CastMessagePortImpl() final;
+
+ CastMessagePortImpl(const CastMessagePortImpl&) = delete;
+ CastMessagePortImpl& operator=(const CastMessagePortImpl&) = delete;
+
+ // openscreen::cast::MessagePort implementation.
+ void SetClient(Client* client, std::string client_sender_id) final;
+ void ResetClient() final;
+ void PostMessage(const std::string& sender_id,
+ const std::string& message_namespace,
+ const std::string& message) final;
+
+ private:
+ // Resets |message_port_| if it is open and signals an error to |client_| if
+ // |client_| is set.
+ void MaybeClose();
+
+ // Returns a "not supported" error message to the sender for messages from
+ // the inject namespace.
+ void SendInjectResponse(const std::string& sender_id,
+ const std::string& message);
+
+ // cast_api_bindings::MessagePort::Receiver implementation.
+ bool OnMessage(
+ base::StringPiece message,
+ std::vector<std::unique_ptr<cast_api_bindings::MessagePort>> ports) final;
+ void OnPipeError() final;
+
+ Client* client_ = nullptr;
+ std::unique_ptr<cast_api_bindings::MessagePort> message_port_;
+ base::OnceClosure on_close_;
+};
+
+} // namespace cast_streaming
+
+#endif // COMPONENTS_CAST_STREAMING_BROWSER_CAST_MESSAGE_PORT_IMPL_H_
diff --git a/chromium/components/cast_streaming/browser/cast_message_port_impl_unittest.cc b/chromium/components/cast_streaming/browser/cast_message_port_impl_unittest.cc
new file mode 100644
index 00000000000..a5d1308e3d0
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/cast_message_port_impl_unittest.cc
@@ -0,0 +1,211 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/browser/cast_message_port_impl.h"
+
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "components/cast/message_port/test_message_port_receiver.h"
+#include "components/cast_streaming/browser/message_serialization.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cast_streaming {
+
+namespace {
+const char kSenderId[] = "senderId";
+} // namespace
+
+class CastMessagePortImplTest : public testing::Test,
+ public openscreen::cast::MessagePort::Client {
+ public:
+ CastMessagePortImplTest() = default;
+ ~CastMessagePortImplTest() override = default;
+
+ CastMessagePortImplTest(const CastMessagePortImplTest&) = delete;
+ CastMessagePortImplTest& operator=(const CastMessagePortImplTest&) = delete;
+
+ void SetUp() override {
+ std::unique_ptr<cast_api_bindings::MessagePort> receiver;
+ cast_api_bindings::MessagePort::CreatePair(&sender_message_port_,
+ &receiver);
+
+ sender_message_port_->SetReceiver(&sender_message_port_receiver_);
+ receiver_message_port_ = std::make_unique<CastMessagePortImpl>(
+ std::move(receiver),
+ base::BindOnce(&CastMessagePortImplTest::OnCastChannelClosed,
+ base::Unretained(this)));
+ receiver_message_port_->SetClient(this, kSenderId);
+ }
+
+ protected:
+ struct CastMessage {
+ std::string sender_id;
+ std::string message_namespace;
+ std::string message;
+ };
+
+ void RunUntilMessageCountIsAtLeast(size_t message_count) {
+ while (receiver_messages_.size() < message_count) {
+ base::RunLoop run_loop;
+ receiver_message_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+ }
+
+ void RunUntilError() {
+ base::RunLoop run_loop;
+ error_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+
+ void RunUntilCastChannelClosed() {
+ base::RunLoop run_loop;
+ cast_channel_closed_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+
+ void OnCastChannelClosed() {
+ if (cast_channel_closed_closure_) {
+ std::move(cast_channel_closed_closure_).Run();
+ } else {
+ ADD_FAILURE() << "Cast Streaming Session MessagePort disconnected";
+ }
+ }
+
+ // openscreen::cast::MessagePort::Client implementation.
+ void OnMessage(const std::string& source_sender_id,
+ const std::string& message_namespace,
+ const std::string& message) override {
+ receiver_messages_.push_back(
+ {source_sender_id, message_namespace, message});
+ if (receiver_message_closure_) {
+ std::move(receiver_message_closure_).Run();
+ }
+ }
+ void OnError(openscreen::Error error) override {
+ latest_error_ = error;
+ if (error_closure_) {
+ std::move(error_closure_).Run();
+ }
+ }
+
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
+
+ openscreen::Error latest_error_ = openscreen::Error::None();
+ std::vector<CastMessage> receiver_messages_;
+ base::OnceClosure receiver_message_closure_;
+ base::OnceClosure error_closure_;
+ base::OnceClosure cast_channel_closed_closure_;
+
+ std::unique_ptr<CastMessagePortImpl> receiver_message_port_;
+ std::unique_ptr<cast_api_bindings::MessagePort> sender_message_port_;
+ cast_api_bindings::TestMessagePortReceiver sender_message_port_receiver_;
+};
+
+// Tests basic connection between the sender and receiver message port is
+// working.
+TEST_F(CastMessagePortImplTest, BasicConnection) {
+ std::string sender_id;
+ std::string message_namespace;
+ std::string message;
+ const std::string test_message = "testMessage";
+
+ // Check the initial connect message is properly sent.
+ sender_message_port_receiver_.RunUntilMessageCountEqual(1u);
+ ASSERT_EQ(sender_message_port_receiver_.buffer().size(), 1u);
+ ASSERT_TRUE(
+ DeserializeCastMessage(sender_message_port_receiver_.buffer().at(0).first,
+ &sender_id, &message_namespace, &message));
+ EXPECT_EQ(sender_id, kValueSystemSenderId);
+ EXPECT_EQ(message_namespace, kSystemNamespace);
+ EXPECT_EQ(message, kInitialConnectMessage);
+
+ // Check the the connection from the sender to the receiver is working.
+ sender_message_port_->PostMessage(
+ SerializeCastMessage(kSenderId, kMirroringNamespace, test_message));
+ RunUntilMessageCountIsAtLeast(1u);
+ ASSERT_EQ(receiver_messages_.size(), 1u);
+ EXPECT_EQ(receiver_messages_.at(0).sender_id, kSenderId);
+ EXPECT_EQ(receiver_messages_.at(0).message_namespace, kMirroringNamespace);
+ EXPECT_EQ(receiver_messages_.at(0).message, test_message);
+
+ // Check the connection from the receiver to the sender is working.
+ receiver_message_port_->PostMessage(kSenderId, kMirroringNamespace,
+ test_message);
+ sender_message_port_receiver_.RunUntilMessageCountEqual(2u);
+ ASSERT_EQ(sender_message_port_receiver_.buffer().size(), 2u);
+ ASSERT_TRUE(
+ DeserializeCastMessage(sender_message_port_receiver_.buffer().at(1).first,
+ &sender_id, &message_namespace, &message));
+ EXPECT_EQ(sender_id, kSenderId);
+ EXPECT_EQ(message_namespace, kMirroringNamespace);
+ EXPECT_EQ(message, test_message);
+}
+
+// Tests the "not supported" message is properly received for the inject
+// message.
+TEST_F(CastMessagePortImplTest, InjectMessage) {
+ const int kRequestId = 42;
+ base::Value inject_value(base::Value::Type::DICTIONARY);
+ inject_value.SetKey(kKeyType, base::Value(kValueWrapped));
+ inject_value.SetKey(kKeyRequestId, base::Value(kRequestId));
+ std::string inject_message;
+ ASSERT_TRUE(base::JSONWriter::Write(inject_value, &inject_message));
+
+ sender_message_port_->PostMessage(
+ SerializeCastMessage(kSenderId, kInjectNamespace, inject_message));
+ sender_message_port_receiver_.RunUntilMessageCountEqual(2u);
+ ASSERT_EQ(sender_message_port_receiver_.buffer().size(), 2u);
+
+ std::string sender_id;
+ std::string message_namespace;
+ std::string message;
+ ASSERT_TRUE(
+ DeserializeCastMessage(sender_message_port_receiver_.buffer().at(1).first,
+ &sender_id, &message_namespace, &message));
+ EXPECT_EQ(sender_id, kSenderId);
+ EXPECT_EQ(message_namespace, kInjectNamespace);
+
+ absl::optional<base::Value> return_value = base::JSONReader::Read(message);
+ ASSERT_TRUE(return_value);
+ ASSERT_TRUE(return_value->is_dict());
+
+ const std::string* type_value = return_value->FindStringKey(kKeyType);
+ ASSERT_TRUE(type_value);
+ EXPECT_EQ(*type_value, kValueError);
+
+ absl::optional<int> request_id_value =
+ return_value->FindIntKey(kKeyRequestId);
+ ASSERT_TRUE(request_id_value);
+ EXPECT_EQ(request_id_value.value(), kRequestId);
+
+ const std::string* data_value = return_value->FindStringKey(kKeyData);
+ ASSERT_TRUE(data_value);
+ EXPECT_EQ(*data_value, kValueInjectNotSupportedError);
+
+ const std::string* code_value = return_value->FindStringKey(kKeyCode);
+ ASSERT_TRUE(code_value);
+ EXPECT_EQ(*code_value, kValueWrappedError);
+}
+
+// Tests sending a bad message properly reports an error to Open Screen without
+// crashing.
+TEST_F(CastMessagePortImplTest, BadMessage) {
+ const std::string kBadMessage = "42";
+ sender_message_port_->PostMessage(kBadMessage);
+ RunUntilError();
+ EXPECT_EQ(latest_error_,
+ openscreen::Error(openscreen::Error::Code::kCastV2InvalidMessage));
+}
+
+// Tests closing the sender-end of the Cast Channel properly runs the closure.
+TEST_F(CastMessagePortImplTest, CastChannelClosed) {
+ sender_message_port_.reset();
+ RunUntilCastChannelClosed();
+}
+
+} // namespace cast_streaming
diff --git a/chromium/components/cast_streaming/browser/cast_streaming_session.cc b/chromium/components/cast_streaming/browser/cast_streaming_session.cc
new file mode 100644
index 00000000000..676cfd839a6
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/cast_streaming_session.cc
@@ -0,0 +1,313 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/browser/public/cast_streaming_session.h"
+
+#include "base/bind.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "components/cast_streaming/browser/cast_message_port_impl.h"
+#include "components/cast_streaming/browser/config_conversions.h"
+#include "components/cast_streaming/browser/stream_consumer.h"
+#include "components/openscreen_platform/network_util.h"
+#include "components/openscreen_platform/task_runner.h"
+#include "media/base/timestamp_constants.h"
+#include "media/mojo/common/mojo_decoder_buffer_converter.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "third_party/openscreen/src/cast/streaming/receiver.h"
+#include "third_party/openscreen/src/cast/streaming/receiver_session.h"
+
+namespace {
+
+// Timeout to stop the Session when no data is received.
+constexpr base::TimeDelta kNoDataTimeout = base::TimeDelta::FromSeconds(15);
+
+bool CreateDataPipeForStreamType(media::DemuxerStream::Type type,
+ mojo::ScopedDataPipeProducerHandle* producer,
+ mojo::ScopedDataPipeConsumerHandle* consumer) {
+ const MojoCreateDataPipeOptions data_pipe_options{
+ sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE,
+ 1u /* element_num_bytes */,
+ media::GetDefaultDecoderBufferConverterCapacity(type)};
+ MojoResult result =
+ mojo::CreateDataPipe(&data_pipe_options, *producer, *consumer);
+ return result == MOJO_RESULT_OK;
+}
+
+// Timeout to end the Session when no offer message is sent.
+constexpr base::TimeDelta kInitTimeout = base::TimeDelta::FromSeconds(5);
+
+} // namespace
+
+namespace cast_streaming {
+
+// Owns the Open Screen ReceiverSession. The Cast Streaming Session is tied to
+// the lifespan of this object.
+class CastStreamingSession::Internal
+ : public openscreen::cast::ReceiverSession::Client {
+ public:
+ Internal(CastStreamingSession::Client* client,
+ std::unique_ptr<cast_api_bindings::MessagePort> message_port,
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : task_runner_(task_runner),
+ environment_(&openscreen::Clock::now, &task_runner_),
+ cast_message_port_impl_(
+ std::move(message_port),
+ base::BindOnce(&CastStreamingSession::Internal::OnCastChannelClosed,
+ base::Unretained(this))),
+ client_(client) {
+ DCHECK(task_runner);
+ DCHECK(client_);
+
+ // TODO(crbug.com/1087520): Add streaming session Constraints and
+ // DisplayDescription.
+ receiver_session_ = std::make_unique<openscreen::cast::ReceiverSession>(
+ this, &environment_, &cast_message_port_impl_,
+ openscreen::cast::ReceiverSession::Preferences(
+ {openscreen::cast::VideoCodec::kH264,
+ openscreen::cast::VideoCodec::kVp8},
+ {openscreen::cast::AudioCodec::kAac,
+ openscreen::cast::AudioCodec::kOpus}));
+
+ init_timeout_timer_.Start(
+ FROM_HERE, kInitTimeout,
+ base::BindOnce(&CastStreamingSession::Internal::OnInitializationTimeout,
+ base::Unretained(this)));
+ }
+
+ ~Internal() final = default;
+
+ Internal(const Internal&) = delete;
+ Internal& operator=(const Internal&) = delete;
+
+ private:
+ void OnInitializationTimeout() {
+ DVLOG(1) << __func__;
+ DCHECK(!is_initialized_);
+ client_->OnSessionEnded();
+ is_initialized_ = true;
+ }
+
+ // Initializes the audio consumer with |audio_capture_config|. Returns an
+ // empty Optional on failure.
+ absl::optional<AudioStreamInfo> InitializeAudioConsumer(
+ openscreen::cast::Receiver* audio_receiver,
+ const openscreen::cast::AudioCaptureConfig& audio_capture_config) {
+ DCHECK(audio_receiver);
+
+ // Create the audio data pipe.
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ if (!CreateDataPipeForStreamType(media::DemuxerStream::Type::AUDIO,
+ &data_pipe_producer,
+ &data_pipe_consumer)) {
+ return absl::nullopt;
+ }
+
+ // We can use unretained pointers here because StreamConsumer is owned by
+ // this object and |client_| is guaranteed to outlive this object.
+ audio_consumer_ = std::make_unique<StreamConsumer>(
+ audio_receiver, media::kNoTimestamp, std::move(data_pipe_producer),
+ base::BindRepeating(
+ &CastStreamingSession::Client::OnAudioBufferReceived,
+ base::Unretained(client_)),
+ base::BindRepeating(&base::OneShotTimer::Reset,
+ base::Unretained(&data_timeout_timer_)));
+
+ return AudioStreamInfo{
+ AudioCaptureConfigToAudioDecoderConfig(audio_capture_config),
+ std::move(data_pipe_consumer)};
+ }
+
+ // Initializes the video consumer with |video_capture_config|. Returns an
+ // empty Optional on failure.
+ absl::optional<VideoStreamInfo> InitializeVideoConsumer(
+ openscreen::cast::Receiver* video_receiver,
+ const openscreen::cast::VideoCaptureConfig& video_capture_config) {
+ DCHECK(video_receiver);
+
+ // Creare the video data pipe.
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ if (!CreateDataPipeForStreamType(media::DemuxerStream::Type::VIDEO,
+ &data_pipe_producer,
+ &data_pipe_consumer)) {
+ return absl::nullopt;
+ }
+
+ // We can use unretained pointers here because StreamConsumer is owned by
+ // this object and |client_| is guaranteed to outlive this object.
+ // |data_timeout_timer_| is also owned by this object and will outlive both
+ // StreamConsumers.
+ // The frame duration is set to 10 minutes to work around cases where
+ // senders do not send data for a long period of time. We end up with
+ // overlapping video frames but this is fine since the media pipeline mostly
+ // considers the playout time when deciding which frame to present or play
+ video_consumer_ = std::make_unique<StreamConsumer>(
+ video_receiver, base::TimeDelta::FromMinutes(10),
+ std::move(data_pipe_producer),
+ base::BindRepeating(
+ &CastStreamingSession::Client::OnVideoBufferReceived,
+ base::Unretained(client_)),
+ base::BindRepeating(&base::OneShotTimer::Reset,
+ base::Unretained(&data_timeout_timer_)));
+
+ return VideoStreamInfo{
+ VideoCaptureConfigToVideoDecoderConfig(video_capture_config),
+ std::move(data_pipe_consumer)};
+ }
+
+ // openscreen::cast::ReceiverSession::Client implementation.
+ void OnNegotiated(
+ const openscreen::cast::ReceiverSession* session,
+ openscreen::cast::ReceiverSession::ConfiguredReceivers receivers) final {
+ DVLOG(1) << __func__;
+ DCHECK_EQ(session, receiver_session_.get());
+ init_timeout_timer_.Stop();
+
+ bool is_new_offer = is_initialized_;
+ if (is_new_offer) {
+ // This is a second offer message, reinitialize the streams.
+ bool existing_session_has_audio = audio_consumer_ != nullptr;
+ bool existing_session_has_video = video_consumer_ != nullptr;
+ audio_consumer_.reset();
+ video_consumer_.reset();
+
+ bool new_offer_has_audio = receivers.audio_receiver != nullptr;
+ bool new_offer_has_video = receivers.video_receiver != nullptr;
+
+ if (new_offer_has_audio != existing_session_has_audio ||
+ new_offer_has_video != existing_session_has_video) {
+ // Different audio/video configuration than in the first offer message.
+ // Return early here.
+ client_->OnSessionEnded();
+ return;
+ }
+ }
+
+ // Set |is_initialized_| now so we can return early on failure.
+ is_initialized_ = true;
+
+ absl::optional<AudioStreamInfo> audio_stream_info;
+ if (receivers.audio_receiver) {
+ audio_stream_info = InitializeAudioConsumer(receivers.audio_receiver,
+ receivers.audio_config);
+ if (audio_stream_info) {
+ DVLOG(1) << "Initialized audio stream. "
+ << audio_stream_info->decoder_config.AsHumanReadableString();
+ } else {
+ client_->OnSessionEnded();
+ return;
+ }
+ }
+
+ absl::optional<VideoStreamInfo> video_stream_info;
+ if (receivers.video_receiver) {
+ video_stream_info = InitializeVideoConsumer(receivers.video_receiver,
+ receivers.video_config);
+ if (video_stream_info) {
+ DVLOG(1) << "Initialized video stream. "
+ << video_stream_info->decoder_config.AsHumanReadableString();
+ } else {
+ audio_consumer_.reset();
+ audio_stream_info.reset();
+ client_->OnSessionEnded();
+ return;
+ }
+ }
+
+ // This is necessary in case the offer message had no audio and no video
+ // stream.
+ if (!audio_stream_info && !video_stream_info) {
+ client_->OnSessionEnded();
+ return;
+ }
+
+ if (is_new_offer) {
+ client_->OnSessionReinitialization(std::move(audio_stream_info),
+ std::move(video_stream_info));
+ } else {
+ client_->OnSessionInitialization(std::move(audio_stream_info),
+ std::move(video_stream_info));
+ data_timeout_timer_.Start(
+ FROM_HERE, kNoDataTimeout,
+ base::BindOnce(&CastStreamingSession::Internal::OnDataTimeout,
+ base::Unretained(this)));
+ }
+ }
+
+ void OnReceiversDestroying(const openscreen::cast::ReceiverSession* session,
+ ReceiversDestroyingReason reason) final {
+ // This can be called when |receiver_session_| is being destroyed, so we
+ // do not sanity-check |session| here.
+ DVLOG(1) << __func__;
+
+ switch (reason) {
+ case ReceiversDestroyingReason::kEndOfSession:
+ audio_consumer_.reset();
+ video_consumer_.reset();
+ client_->OnSessionEnded();
+ break;
+ case ReceiversDestroyingReason::kRenegotiated:
+ break;
+ }
+ }
+
+ void OnError(const openscreen::cast::ReceiverSession* session,
+ openscreen::Error error) final {
+ DCHECK_EQ(session, receiver_session_.get());
+ LOG(ERROR) << error;
+ if (!is_initialized_) {
+ client_->OnSessionEnded();
+ is_initialized_ = true;
+ }
+ }
+
+ void OnDataTimeout() {
+ DVLOG(1) << __func__;
+ receiver_session_.reset();
+ }
+
+ void OnCastChannelClosed() {
+ DVLOG(1) << __func__;
+ receiver_session_.reset();
+ }
+
+ openscreen_platform::TaskRunner task_runner_;
+ openscreen::cast::Environment environment_;
+ CastMessagePortImpl cast_message_port_impl_;
+ std::unique_ptr<openscreen::cast::ReceiverSession> receiver_session_;
+ base::OneShotTimer init_timeout_timer_;
+
+ // Timer to trigger connection closure if no data is received for 15 seconds.
+ base::OneShotTimer data_timeout_timer_;
+
+ bool is_initialized_ = false;
+ CastStreamingSession::Client* const client_;
+ std::unique_ptr<StreamConsumer> audio_consumer_;
+ std::unique_ptr<StreamConsumer> video_consumer_;
+};
+
+CastStreamingSession::Client::~Client() = default;
+CastStreamingSession::CastStreamingSession() = default;
+CastStreamingSession::~CastStreamingSession() = default;
+
+void CastStreamingSession::Start(
+ Client* client,
+ std::unique_ptr<cast_api_bindings::MessagePort> message_port,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ DVLOG(1) << __func__;
+ DCHECK(client);
+ DCHECK(!internal_);
+ internal_ =
+ std::make_unique<Internal>(client, std::move(message_port), task_runner);
+}
+
+void CastStreamingSession::Stop() {
+ DVLOG(1) << __func__;
+ DCHECK(internal_);
+ internal_.reset();
+}
+
+} // namespace cast_streaming
diff --git a/chromium/components/cast_streaming/browser/cast_streaming_session_unittest.cc b/chromium/components/cast_streaming/browser/cast_streaming_session_unittest.cc
new file mode 100644
index 00000000000..bb5c266ea1d
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/cast_streaming_session_unittest.cc
@@ -0,0 +1,141 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/browser/public/cast_streaming_session.h"
+
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/cast_streaming/browser/test/cast_streaming_test_receiver.h"
+#include "components/cast_streaming/browser/test/cast_streaming_test_sender.h"
+#include "media/base/media_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cast_streaming {
+
+namespace {
+
+media::AudioDecoderConfig GetDefaultAudioConfig() {
+ return media::AudioDecoderConfig(
+ media::AudioCodec::kCodecOpus, media::SampleFormat::kSampleFormatF32,
+ media::ChannelLayout::CHANNEL_LAYOUT_STEREO,
+ 48000 /* samples_per_second */, media::EmptyExtraData(),
+ media::EncryptionScheme::kUnencrypted);
+}
+
+media::VideoDecoderConfig GetDefaultVideoConfig() {
+ const gfx::Size kVideoSize = {1920, 1080};
+ const gfx::Rect kVideoRect(kVideoSize);
+
+ return media::VideoDecoderConfig(
+ media::VideoCodec::kCodecVP8, media::VideoCodecProfile::VP8PROFILE_MIN,
+ media::VideoDecoderConfig::AlphaMode::kIsOpaque, media::VideoColorSpace(),
+ media::VideoTransformation(), kVideoSize, kVideoRect, kVideoSize,
+ media::EmptyExtraData(), media::EncryptionScheme::kUnencrypted);
+}
+
+// Compare |decoder_buffer| to |data_buffer| metadata and data. Returns true if
+// these are equivalent.
+void VerifyAreEquals(const scoped_refptr<media::DecoderBuffer>& decoder_buffer,
+ const scoped_refptr<media::DataBuffer>& data_buffer) {
+ if (decoder_buffer->end_of_stream() || data_buffer->end_of_stream()) {
+ EXPECT_EQ(decoder_buffer->end_of_stream(), data_buffer->end_of_stream());
+ return;
+ }
+
+ ASSERT_EQ(decoder_buffer->timestamp(), data_buffer->timestamp());
+
+ // Signed to unsigned conversion.
+ size_t data_buffer_size = data_buffer->data_size();
+ ASSERT_EQ(decoder_buffer->data_size(), data_buffer_size);
+
+ ASSERT_EQ(
+ memcmp(decoder_buffer->data(), data_buffer->data(), data_buffer_size), 0);
+}
+
+} // namespace
+
+class CastStreamingSessionTest : public testing::Test {
+ public:
+ CastStreamingSessionTest() = default;
+ ~CastStreamingSessionTest() override = default;
+
+ CastStreamingSessionTest(const CastStreamingSessionTest&) = delete;
+ CastStreamingSessionTest& operator=(const CastStreamingSessionTest&) = delete;
+
+ protected:
+ void StartSession() {
+ std::unique_ptr<cast_api_bindings::MessagePort> sender_message_port;
+ std::unique_ptr<cast_api_bindings::MessagePort> receiver_message_port;
+ cast_api_bindings::MessagePort::CreatePair(&sender_message_port,
+ &receiver_message_port);
+
+ receiver_.Start(std::move(receiver_message_port));
+ EXPECT_TRUE(sender_.Start(
+ std::move(sender_message_port), net::IPAddress::IPv6Localhost(),
+ GetDefaultAudioConfig(), GetDefaultVideoConfig()));
+ sender_.RunUntilStarted();
+ receiver_.RunUntilStarted();
+ }
+
+ void StopReceiverSession() {
+ receiver_.Stop();
+ receiver_.RunUntilStopped();
+ sender_.RunUntilStopped();
+ }
+
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::IO};
+
+ CastStreamingTestSender sender_;
+ CastStreamingTestReceiver receiver_;
+};
+
+// Basic sanity check for the test fixture.
+TEST_F(CastStreamingSessionTest, DoNothing) {}
+
+// Tests session lifespan is correct.
+TEST_F(CastStreamingSessionTest, StartAndStopSession) {
+ StartSession();
+
+ // Sender-initiated closure.
+ sender_.Stop();
+ sender_.RunUntilStopped();
+ receiver_.RunUntilStopped();
+
+ // Start a new session.
+ StartSession();
+
+ // Renderer-initiated closure.
+ StopReceiverSession();
+}
+
+// Tests buffers sent from the sender are properly received by the receiver.
+TEST_F(CastStreamingSessionTest, SendAndReceiveBuffers) {
+ StartSession();
+
+ const uint8_t kAudioData[] = {42};
+ scoped_refptr<media::DataBuffer> audio_buffer =
+ media::DataBuffer::CopyFrom(kAudioData, sizeof(kAudioData));
+ audio_buffer->set_timestamp(base::TimeDelta::FromSeconds(0));
+
+ const uint8_t kVideoData[] = {42, 84};
+ scoped_refptr<media::DataBuffer> video_buffer =
+ media::DataBuffer::CopyFrom(kVideoData, sizeof(kVideoData));
+ video_buffer->set_timestamp(base::TimeDelta::FromSeconds(0));
+
+ sender_.SendAudioBuffer(audio_buffer);
+ sender_.SendVideoBuffer(video_buffer, true);
+
+ ASSERT_TRUE(receiver_.RunUntilAudioFramesCountIsAtLeast(1u));
+ VerifyAreEquals(receiver_.audio_buffers()[0], audio_buffer);
+
+ ASSERT_TRUE(receiver_.RunUntilVideoFramesCountIsAtLeast(1u));
+ VerifyAreEquals(receiver_.video_buffers()[0], video_buffer);
+ EXPECT_TRUE(receiver_.video_buffers()[0]->is_key_frame());
+
+ StopReceiverSession();
+}
+
+} // namespace cast_streaming
diff --git a/chromium/components/cast_streaming/browser/config_conversions.cc b/chromium/components/cast_streaming/browser/config_conversions.cc
new file mode 100644
index 00000000000..e41d2f02a7f
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/config_conversions.cc
@@ -0,0 +1,112 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/browser/config_conversions.h"
+
+#include "base/notreached.h"
+#include "media/base/media_util.h"
+
+namespace cast_streaming {
+
+openscreen::cast::AudioCaptureConfig AudioDecoderConfigToAudioCaptureConfig(
+ const media::AudioDecoderConfig& audio_config) {
+ openscreen::cast::AudioCaptureConfig audio_capture_config;
+
+ switch (audio_config.codec()) {
+ case media::AudioCodec::kCodecAAC:
+ audio_capture_config.codec = openscreen::cast::AudioCodec::kAac;
+ break;
+ case media::AudioCodec::kCodecOpus:
+ audio_capture_config.codec = openscreen::cast::AudioCodec::kOpus;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ audio_capture_config.channels =
+ media::ChannelLayoutToChannelCount(audio_config.channel_layout());
+ audio_capture_config.sample_rate = audio_config.samples_per_second();
+
+ return audio_capture_config;
+}
+
+openscreen::cast::VideoCaptureConfig VideoDecoderConfigToVideoCaptureConfig(
+ const media::VideoDecoderConfig& video_config) {
+ openscreen::cast::VideoCaptureConfig video_capture_config;
+
+ switch (video_config.codec()) {
+ case media::VideoCodec::kCodecH264:
+ video_capture_config.codec = openscreen::cast::VideoCodec::kH264;
+ break;
+ case media::VideoCodec::kCodecVP8:
+ video_capture_config.codec = openscreen::cast::VideoCodec::kVp8;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ video_capture_config.resolutions.push_back(
+ {video_config.visible_rect().width(),
+ video_config.visible_rect().height()});
+ return video_capture_config;
+}
+
+media::AudioDecoderConfig AudioCaptureConfigToAudioDecoderConfig(
+ const openscreen::cast::AudioCaptureConfig& audio_capture_config) {
+ // Gather data for the audio decoder config.
+ media::AudioCodec media_audio_codec = media::AudioCodec::kUnknownAudioCodec;
+ switch (audio_capture_config.codec) {
+ case openscreen::cast::AudioCodec::kAac:
+ media_audio_codec = media::AudioCodec::kCodecAAC;
+ break;
+ case openscreen::cast::AudioCodec::kOpus:
+ media_audio_codec = media::AudioCodec::kCodecOpus;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ return media::AudioDecoderConfig(
+ media_audio_codec, media::SampleFormat::kSampleFormatF32,
+ media::GuessChannelLayout(audio_capture_config.channels),
+ audio_capture_config.sample_rate /* samples_per_second */,
+ media::EmptyExtraData(), media::EncryptionScheme::kUnencrypted);
+}
+
+media::VideoDecoderConfig VideoCaptureConfigToVideoDecoderConfig(
+ const openscreen::cast::VideoCaptureConfig& video_capture_config) {
+ // Gather data for the video decoder config.
+ uint32_t video_width = video_capture_config.resolutions[0].width;
+ uint32_t video_height = video_capture_config.resolutions[0].height;
+ gfx::Size video_size(video_width, video_height);
+ gfx::Rect video_rect(video_width, video_height);
+
+ media::VideoCodec media_video_codec = media::VideoCodec::kUnknownVideoCodec;
+ media::VideoCodecProfile video_codec_profile =
+ media::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
+ switch (video_capture_config.codec) {
+ case openscreen::cast::VideoCodec::kH264:
+ media_video_codec = media::VideoCodec::kCodecH264;
+ video_codec_profile = media::VideoCodecProfile::H264PROFILE_BASELINE;
+ break;
+ case openscreen::cast::VideoCodec::kVp8:
+ media_video_codec = media::VideoCodec::kCodecVP8;
+ video_codec_profile = media::VideoCodecProfile::VP8PROFILE_MIN;
+ break;
+ case openscreen::cast::VideoCodec::kHevc:
+ case openscreen::cast::VideoCodec::kVp9:
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ return media::VideoDecoderConfig(
+ media_video_codec, video_codec_profile,
+ media::VideoDecoderConfig::AlphaMode::kIsOpaque, media::VideoColorSpace(),
+ media::VideoTransformation(), video_size, video_rect, video_size,
+ media::EmptyExtraData(), media::EncryptionScheme::kUnencrypted);
+}
+
+} // namespace cast_streaming
diff --git a/chromium/components/cast_streaming/browser/config_conversions.h b/chromium/components/cast_streaming/browser/config_conversions.h
new file mode 100644
index 00000000000..ce3044a5e39
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/config_conversions.h
@@ -0,0 +1,30 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_CONFIG_CONVERSIONS_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_CONFIG_CONVERSIONS_H_
+
+#include "media/base/audio_decoder_config.h"
+#include "media/base/video_decoder_config.h"
+#include "third_party/openscreen/src/cast/streaming/capture_configs.h"
+
+namespace cast_streaming {
+
+// Utility functions to convert between media and Open Screen types.
+
+openscreen::cast::AudioCaptureConfig AudioDecoderConfigToAudioCaptureConfig(
+ const media::AudioDecoderConfig& audio_config);
+
+openscreen::cast::VideoCaptureConfig VideoDecoderConfigToVideoCaptureConfig(
+ const media::VideoDecoderConfig& video_config);
+
+media::AudioDecoderConfig AudioCaptureConfigToAudioDecoderConfig(
+ const openscreen::cast::AudioCaptureConfig& audio_capture_config);
+
+media::VideoDecoderConfig VideoCaptureConfigToVideoDecoderConfig(
+ const openscreen::cast::VideoCaptureConfig& video_capture_config);
+
+} // namespace cast_streaming
+
+#endif // COMPONENTS_CAST_STREAMING_BROWSER_CONFIG_CONVERSIONS_H_
diff --git a/chromium/components/cast_streaming/browser/message_serialization.cc b/chromium/components/cast_streaming/browser/message_serialization.cc
new file mode 100644
index 00000000000..f7b5550dcb8
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/message_serialization.cc
@@ -0,0 +1,90 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/browser/message_serialization.h"
+
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/values.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace cast_streaming {
+
+const char kMirroringNamespace[] = "urn:x-cast:com.google.cast.webrtc";
+const char kRemotingNamespace[] = "urn:x-cast:com.google.cast.remoting";
+const char kSystemNamespace[] = "urn:x-cast:com.google.cast.system";
+const char kInjectNamespace[] = "urn:x-cast:com.google.cast.inject";
+
+const char kKeySenderId[] = "senderId";
+const char kKeyNamespace[] = "namespace";
+const char kKeyData[] = "data";
+const char kKeyType[] = "type";
+const char kKeyRequestId[] = "requestId";
+const char kKeyCode[] = "code";
+
+const char kValueSystemSenderId[] = "SystemSender";
+const char kValueWrapped[] = "WRAPPED";
+const char kValueError[] = "ERROR";
+const char kValueWrappedError[] = "WRAPPED_ERROR";
+const char kValueInjectNotSupportedError[] =
+ R"({"code":"NOT_SUPPORTED","type":"ERROR"})";
+
+const char kInitialConnectMessage[] = R"(
+ {
+ "type": "ready",
+ "activeNamespaces": [
+ "urn:x-cast:com.google.cast.webrtc",
+ "urn:x-cast:com.google.cast.remoting",
+ "urn:x-cast:com.google.cast.inject"
+ ],
+ "version": "2.0.0",
+ "messagesVersion": "1.0"
+ }
+ )";
+
+bool DeserializeCastMessage(base::StringPiece buffer,
+ std::string* sender_id,
+ std::string* message_namespace,
+ std::string* message) {
+ absl::optional<base::Value> converted_value = base::JSONReader::Read(buffer);
+ if (!converted_value)
+ return false;
+
+ if (!converted_value->is_dict())
+ return false;
+
+ const std::string* sender_id_value =
+ converted_value->FindStringPath(kKeySenderId);
+ if (!sender_id_value)
+ return false;
+ *sender_id = *sender_id_value;
+
+ const std::string* message_namespace_value =
+ converted_value->FindStringPath(kKeyNamespace);
+ if (!message_namespace_value)
+ return false;
+ *message_namespace = *message_namespace_value;
+
+ const std::string* message_value = converted_value->FindStringPath(kKeyData);
+ if (!message_value)
+ return false;
+ *message = *message_value;
+
+ return true;
+}
+
+std::string SerializeCastMessage(const std::string& sender_id,
+ const std::string& message_namespace,
+ const std::string& message) {
+ base::Value value(base::Value::Type::DICTIONARY);
+ value.SetStringKey(kKeyNamespace, message_namespace);
+ value.SetStringKey(kKeySenderId, sender_id);
+ value.SetStringKey(kKeyData, message);
+
+ std::string json_message;
+ CHECK(base::JSONWriter::Write(value, &json_message));
+ return json_message;
+}
+
+} // namespace cast_streaming
diff --git a/chromium/components/cast_streaming/browser/message_serialization.h b/chromium/components/cast_streaming/browser/message_serialization.h
new file mode 100644
index 00000000000..6b5dc6e95ac
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/message_serialization.h
@@ -0,0 +1,51 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_MESSAGE_SERIALIZATION_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_MESSAGE_SERIALIZATION_H_
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+
+namespace cast_streaming {
+
+// TODO(b/156118960): Remove all these when Cast messages are handled by Open
+// Screen.
+extern const char kMirroringNamespace[];
+extern const char kRemotingNamespace[];
+extern const char kSystemNamespace[];
+extern const char kInjectNamespace[];
+
+extern const char kKeySenderId[];
+extern const char kKeyNamespace[];
+extern const char kKeyData[];
+extern const char kKeyType[];
+extern const char kKeyRequestId[];
+extern const char kKeyCode[];
+
+extern const char kValueSystemSenderId[];
+extern const char kValueWrapped[];
+extern const char kValueError[];
+extern const char kValueWrappedError[];
+extern const char kValueInjectNotSupportedError[];
+
+extern const char kInitialConnectMessage[];
+
+// Parses |buffer| data into |sender_id|, |message_namespace| and |message|.
+// Returns true on success.
+bool DeserializeCastMessage(base::StringPiece buffer,
+ std::string* sender_id,
+ std::string* message_namespace,
+ std::string* message);
+
+// Creates a message string out of the |sender_id|, |message_namespace| and
+// |message|.
+std::string SerializeCastMessage(const std::string& sender_id,
+ const std::string& message_namespace,
+ const std::string& message);
+
+} // namespace cast_streaming
+
+#endif // COMPONENTS_CAST_STREAMING_BROWSER_MESSAGE_SERIALIZATION_H_
diff --git a/chromium/components/cast_streaming/browser/network_context_getter.cc b/chromium/components/cast_streaming/browser/network_context_getter.cc
new file mode 100644
index 00000000000..1c68f073c15
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/network_context_getter.cc
@@ -0,0 +1,15 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/browser/public/network_context_getter.h"
+
+#include "components/openscreen_platform/network_context.h"
+
+namespace cast_streaming {
+
+void SetNetworkContextGetter(NetworkContextGetter getter) {
+ openscreen_platform::SetNetworkContextGetter(std::move(getter));
+}
+
+} // namespace cast_streaming
diff --git a/chromium/components/cast_streaming/browser/public/cast_streaming_session.h b/chromium/components/cast_streaming/browser/public/cast_streaming_session.h
new file mode 100644
index 00000000000..0efe080e289
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/public/cast_streaming_session.h
@@ -0,0 +1,95 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_CAST_STREAMING_SESSION_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_CAST_STREAMING_SESSION_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/sequenced_task_runner.h"
+#include "components/cast/message_port/message_port.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/video_decoder_config.h"
+#include "media/mojo/mojom/media_types.mojom.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace cast_streaming {
+
+// Entry point for the Cast Streaming Receiver implementation. Used to start a
+// Cast Streaming Session for a provided FIDL MessagePort request.
+class CastStreamingSession {
+ public:
+ template <class T>
+ struct StreamInfo {
+ T decoder_config;
+ mojo::ScopedDataPipeConsumerHandle data_pipe;
+ };
+ using AudioStreamInfo = StreamInfo<media::AudioDecoderConfig>;
+ using VideoStreamInfo = StreamInfo<media::VideoDecoderConfig>;
+
+ class Client {
+ public:
+ // Called when the Cast Streaming Session has been successfully initialized.
+ // It is guaranteed that at least one of |audio_stream_info| or
+ // |video_stream_info| will be set.
+ virtual void OnSessionInitialization(
+ absl::optional<AudioStreamInfo> audio_stream_info,
+ absl::optional<VideoStreamInfo> video_stream_info) = 0;
+
+ // Called on every new audio buffer after OnSessionInitialization(). The
+ // frame data must be accessed via the |data_pipe| property in StreamInfo.
+ virtual void OnAudioBufferReceived(
+ media::mojom::DecoderBufferPtr buffer) = 0;
+
+ // Called on every new video buffer after OnSessionInitialization(). The
+ // frame data must be accessed via the |data_pipe| property in StreamInfo.
+ virtual void OnVideoBufferReceived(
+ media::mojom::DecoderBufferPtr buffer) = 0;
+
+ // Called on receiver session reinitialization. It is guaranteed that at
+ // least one of |audio_stream_info| or |video_stream_info| will be set.
+ virtual void OnSessionReinitialization(
+ absl::optional<AudioStreamInfo> audio_stream_info,
+ absl::optional<VideoStreamInfo> video_stream_info) = 0;
+
+ // Called when the Cast Streaming Session has ended.
+ virtual void OnSessionEnded() = 0;
+
+ protected:
+ virtual ~Client();
+ };
+
+ CastStreamingSession();
+ ~CastStreamingSession();
+
+ CastStreamingSession(const CastStreamingSession&) = delete;
+ CastStreamingSession& operator=(const CastStreamingSession&) = delete;
+
+ // Starts the Cast Streaming Session. This can only be called once during the
+ // lifespan of this object. |client| must not be null and must outlive this
+ // object.
+ // * On success, OnSessionInitialization() will be called and
+ // OnAudioFrameReceived() and/or OnVideoFrameReceived() will be called on
+ // every subsequent Frame.
+ // * On failure, OnSessionEnded() will be called.
+ // * When a new offer is sent by the Cast Streaming Sender,
+ // OnSessionReinitialization() will be called.
+ void Start(Client* client,
+ std::unique_ptr<cast_api_bindings::MessagePort> message_port,
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
+
+ // Stops the Cast Streaming Session. This can only be called once during the
+ // lifespan of this object and only after a call to Start().
+ void Stop();
+
+ private:
+ class Internal;
+ std::unique_ptr<Internal> internal_;
+};
+
+} // namespace cast_streaming
+
+#endif // COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_CAST_STREAMING_SESSION_H_
diff --git a/chromium/components/cast_streaming/browser/public/network_context_getter.h b/chromium/components/cast_streaming/browser/public/network_context_getter.h
new file mode 100644
index 00000000000..ce8c9a718bc
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/public/network_context_getter.h
@@ -0,0 +1,30 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_NETWORK_CONTEXT_GETTER_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_NETWORK_CONTEXT_GETTER_H_
+
+#include "base/callback.h"
+
+namespace network {
+namespace mojom {
+class NetworkContext;
+} // namespace mojom
+} // namespace network
+
+namespace cast_streaming {
+
+using NetworkContextGetter =
+ base::RepeatingCallback<network::mojom::NetworkContext*()>;
+
+// Sets the NetworkContextGetter for embedders that use the Network Service.
+// This must be called before any call to CastStreamingSession::Start() and must
+// only be called once. If the NetworkContext crashes, any existing Cast
+// Streaming Session will eventually terminate and call
+// CastStreamingSession::OnSessionEnded().
+void SetNetworkContextGetter(NetworkContextGetter getter);
+
+} // namespace cast_streaming
+
+#endif // COMPONENTS_CAST_STREAMING_BROWSER_PUBLIC_NETWORK_CONTEXT_GETTER_H_
diff --git a/chromium/components/cast_streaming/browser/stream_consumer.cc b/chromium/components/cast_streaming/browser/stream_consumer.cc
new file mode 100644
index 00000000000..891ffae0d3c
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/stream_consumer.cc
@@ -0,0 +1,174 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/browser/stream_consumer.h"
+
+#include "base/logging.h"
+#include "media/base/media_util.h"
+
+namespace cast_streaming {
+
+StreamConsumer::StreamConsumer(openscreen::cast::Receiver* receiver,
+ base::TimeDelta frame_duration,
+ mojo::ScopedDataPipeProducerHandle data_pipe,
+ FrameReceivedCB frame_received_cb,
+ base::RepeatingClosure on_new_frame)
+ : receiver_(receiver),
+ data_pipe_(std::move(data_pipe)),
+ frame_received_cb_(std::move(frame_received_cb)),
+ pipe_watcher_(FROM_HERE,
+ mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+ base::SequencedTaskRunnerHandle::Get()),
+ frame_duration_(frame_duration),
+ on_new_frame_(std::move(on_new_frame)) {
+ DCHECK(receiver_);
+ receiver_->SetConsumer(this);
+ MojoResult result =
+ pipe_watcher_.Watch(data_pipe_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
+ base::BindRepeating(&StreamConsumer::OnPipeWritable,
+ base::Unretained(this)));
+ if (result != MOJO_RESULT_OK) {
+ CloseDataPipeOnError();
+ return;
+ }
+}
+
+StreamConsumer::~StreamConsumer() {
+ receiver_->SetConsumer(nullptr);
+}
+
+void StreamConsumer::CloseDataPipeOnError() {
+ DLOG(WARNING) << "[ssrc:" << receiver_->ssrc() << "] Data pipe closed.";
+ receiver_->SetConsumer(nullptr);
+ pipe_watcher_.Cancel();
+ data_pipe_.reset();
+}
+
+void StreamConsumer::OnPipeWritable(MojoResult result) {
+ DCHECK(data_pipe_);
+
+ if (result != MOJO_RESULT_OK) {
+ CloseDataPipeOnError();
+ return;
+ }
+
+ uint32_t bytes_written = pending_buffer_remaining_bytes_;
+ result = data_pipe_->WriteData(pending_buffer_ + pending_buffer_offset_,
+ &bytes_written, MOJO_WRITE_DATA_FLAG_NONE);
+ if (result != MOJO_RESULT_OK) {
+ CloseDataPipeOnError();
+ return;
+ }
+
+ pending_buffer_offset_ += bytes_written;
+ pending_buffer_remaining_bytes_ -= bytes_written;
+ if (pending_buffer_remaining_bytes_ != 0) {
+ pipe_watcher_.ArmOrNotify();
+ return;
+ }
+
+ // Advance to the next frame if a new one is ready.
+ int next_frame_buffer_size = receiver_->AdvanceToNextFrame();
+ if (next_frame_buffer_size != openscreen::cast::Receiver::kNoFramesReady)
+ OnFramesReady(next_frame_buffer_size);
+}
+
+void StreamConsumer::OnFramesReady(int next_frame_buffer_size) {
+ DCHECK(data_pipe_);
+ on_new_frame_.Run();
+
+ if (pending_buffer_remaining_bytes_ != 0) {
+ // There already is a pending frame. Ignore this one for now.
+ return;
+ }
+
+ void* buffer = nullptr;
+ uint32_t buffer_size = next_frame_buffer_size;
+ uint32_t mojo_buffer_size = next_frame_buffer_size;
+
+ if (buffer_size > kMaxFrameSize) {
+ LOG(ERROR) << "[ssrc:" << receiver_->ssrc() << "] "
+ << "Frame size too big: " << buffer_size;
+ CloseDataPipeOnError();
+ return;
+ }
+
+ MojoResult result = data_pipe_->BeginWriteData(
+ &buffer, &mojo_buffer_size, MOJO_BEGIN_WRITE_DATA_FLAG_NONE);
+
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ pipe_watcher_.ArmOrNotify();
+ return;
+ }
+
+ if (result != MOJO_RESULT_OK) {
+ CloseDataPipeOnError();
+ return;
+ }
+
+ openscreen::cast::EncodedFrame encoded_frame;
+ size_t bytes_written = 0;
+
+ if (mojo_buffer_size < buffer_size) {
+ DVLOG(2) << "[ssrc:" << receiver_->ssrc() << "] "
+ << "Mojo data pipe full";
+
+ // The |data_pipe_| buffer cannot take the full frame, write to
+ // |pending_buffer_| instead.
+ encoded_frame = receiver_->ConsumeNextFrame(
+ absl::Span<uint8_t>(pending_buffer_, buffer_size));
+
+ // Write as much as we can to the |data_pipe_| buffer.
+ memcpy(buffer, pending_buffer_, mojo_buffer_size);
+ pending_buffer_offset_ = mojo_buffer_size;
+ pending_buffer_remaining_bytes_ = buffer_size - mojo_buffer_size;
+ bytes_written = mojo_buffer_size;
+ } else {
+ // Write directly to the |data_pipe_| buffer.
+ encoded_frame = receiver_->ConsumeNextFrame(
+ absl::Span<uint8_t>(static_cast<uint8_t*>(buffer), buffer_size));
+ bytes_written = buffer_size;
+ }
+
+ result = data_pipe_->EndWriteData(bytes_written);
+ if (result != MOJO_RESULT_OK) {
+ CloseDataPipeOnError();
+ return;
+ }
+
+ const bool is_key_frame =
+ encoded_frame.dependency ==
+ openscreen::cast::EncodedFrame::Dependency::KEY_FRAME;
+
+ base::TimeDelta playout_time = base::TimeDelta::FromMicroseconds(
+ encoded_frame.rtp_timestamp
+ .ToTimeSinceOrigin<std::chrono::microseconds>(
+ receiver_->rtp_timebase())
+ .count());
+
+ // Some senders do not send an initial playout time of 0. To work around this,
+ // a playout offset is added here.
+ if (playout_offset_ == base::TimeDelta::Max()) {
+ playout_offset_ = playout_time;
+ }
+ playout_time -= playout_offset_;
+
+ DVLOG(3) << "[ssrc:" << receiver_->ssrc() << "] "
+ << "Received new frame. Timestamp: " << playout_time
+ << ", is_key_frame: " << is_key_frame;
+
+ frame_received_cb_.Run(media::mojom::DecoderBuffer::New(
+ playout_time /* timestamp */, frame_duration_,
+ false /* is_end_of_stream */, buffer_size, is_key_frame,
+ media::EmptyExtraData(), media::mojom::DecryptConfigPtr(),
+ base::TimeDelta() /* front_discard */,
+ base::TimeDelta() /* back_discard */
+ ));
+
+ if (pending_buffer_remaining_bytes_ != 0) {
+ pipe_watcher_.ArmOrNotify();
+ }
+}
+
+} // namespace cast_streaming
diff --git a/chromium/components/cast_streaming/browser/stream_consumer.h b/chromium/components/cast_streaming/browser/stream_consumer.h
new file mode 100644
index 00000000000..d3a56563981
--- /dev/null
+++ b/chromium/components/cast_streaming/browser/stream_consumer.h
@@ -0,0 +1,87 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_STREAMING_BROWSER_STREAM_CONSUMER_H_
+#define COMPONENTS_CAST_STREAMING_BROWSER_STREAM_CONSUMER_H_
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "media/mojo/mojom/media_types.mojom.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "third_party/openscreen/src/cast/streaming/receiver.h"
+#include "third_party/openscreen/src/cast/streaming/receiver_session.h"
+
+namespace cast_streaming {
+
+// Attaches to an Open Screen Receiver to receive buffers of encoded data and
+// invokes |frame_received_cb_| with each buffer.
+//
+// Internally, this class writes buffers of encoded data directly to
+// |data_pipe_| rather than using a helper class like MojoDecoderBufferWriter.
+// This allows us to use |data_pipe_| as an end-to-end buffer to cap memory
+// usage. Receiving new buffers is delayed until the pipe has free memory again.
+// The Open Screen library takes care of discarding buffers that are too old and
+// requesting new key frames as needed.
+class StreamConsumer : public openscreen::cast::Receiver::Consumer {
+ public:
+ using FrameReceivedCB =
+ base::RepeatingCallback<void(media::mojom::DecoderBufferPtr)>;
+
+ // |receiver| sends frames to this object. It must outlive this object.
+ // |frame_received_cb| is called on every new frame, after a new frame has
+ // been written to |data_pipe|. On error, |data_pipe| will be closed.
+ // On every new frame, |on_new_frame| will be called.
+ StreamConsumer(openscreen::cast::Receiver* receiver,
+ base::TimeDelta frame_duration,
+ mojo::ScopedDataPipeProducerHandle data_pipe,
+ FrameReceivedCB frame_received_cb,
+ base::RepeatingClosure on_new_frame);
+ ~StreamConsumer() final;
+
+ StreamConsumer(const StreamConsumer&) = delete;
+ StreamConsumer& operator=(const StreamConsumer&) = delete;
+
+ private:
+ // Maximum frame size that OnFramesReady() can accept.
+ static constexpr uint32_t kMaxFrameSize = 512 * 1024;
+
+ // Closes |data_pipe_| and resets the Consumer in |receiver_|. No frames will
+ // be received after this call.
+ void CloseDataPipeOnError();
+
+ // Callback when |data_pipe_| can be written to again after it was full.
+ void OnPipeWritable(MojoResult result);
+
+ // openscreen::cast::Receiver::Consumer implementation.
+ void OnFramesReady(int next_frame_buffer_size) final;
+
+ openscreen::cast::Receiver* const receiver_;
+ mojo::ScopedDataPipeProducerHandle data_pipe_;
+ const FrameReceivedCB frame_received_cb_;
+
+ // Provides notifications about |data_pipe_| readiness.
+ mojo::SimpleWatcher pipe_watcher_;
+
+ // Buffer used when |data_pipe_| is too full to accept the next frame size.
+ uint8_t pending_buffer_[kMaxFrameSize];
+
+ // Current offset for data |pending_buffer_| to be written to |data_pipe_|.
+ size_t pending_buffer_offset_ = 0;
+
+ // Remaining bytes to write from |pending_buffer_| to |data_pipe_|.
+ size_t pending_buffer_remaining_bytes_ = 0;
+
+ // Offset for frames playout time. This is initialized by the first frame.
+ base::TimeDelta playout_offset_ = base::TimeDelta::Max();
+
+ const base::TimeDelta frame_duration_;
+
+ // Closure called on every new frame.
+ base::RepeatingClosure on_new_frame_;
+};
+
+} // namespace cast_streaming
+
+#endif // COMPONENTS_CAST_STREAMING_BROWSER_STREAM_CONSUMER_H_
diff --git a/chromium/components/cast_streaming/mojo/BUILD.gn b/chromium/components/cast_streaming/mojo/BUILD.gn
new file mode 100644
index 00000000000..ada234e70cc
--- /dev/null
+++ b/chromium/components/cast_streaming/mojo/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+ sources = [ "cast_streaming_session.mojom" ]
+ public_deps = [
+ "//media/mojo/mojom",
+ "//mojo/public/mojom/base",
+ ]
+}
diff --git a/chromium/components/cast_streaming/mojo/OWNERS b/chromium/components/cast_streaming/mojo/OWNERS
new file mode 100644
index 00000000000..08850f42120
--- /dev/null
+++ b/chromium/components/cast_streaming/mojo/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/components/cast_streaming/mojo/cast_streaming_session.mojom b/chromium/components/cast_streaming/mojo/cast_streaming_session.mojom
new file mode 100644
index 00000000000..d94b83c6450
--- /dev/null
+++ b/chromium/components/cast_streaming/mojo/cast_streaming_session.mojom
@@ -0,0 +1,71 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module mojom;
+
+import "media/mojo/mojom/media_types.mojom";
+
+// Renderer-implemented interface that is used to receive metadata for buffers.
+interface CastStreamingBufferReceiver {
+ // Provide metadata for a buffer to the Cast Streaming Receiver in the
+ // renderer process. The buffer data itself is on the associated |data_pipe|,
+ // from AudioStreamInfo or VideoStreamInfo.
+ // This is called for every new buffer pushed in the associated |data_pipe|.
+ ProvideBuffer(media.mojom.DecoderBuffer buffer);
+
+ // Signals the audio decoder configuration has changed. After this call,
+ // CastStreamingBufferReceiver.ProvideBuffer() will be called on every new
+ // frame. The buffer data itself is on |data_pipe|.
+ OnNewAudioConfig(media.mojom.AudioDecoderConfig decoder_config,
+ handle<data_pipe_consumer> data_pipe);
+
+ // Signals the video configuration has changed. After this call,
+ // CastStreamingBufferReceiver.ProvideBuffer() will be called on every new
+ // frame. The buffer data itself is on |data_pipe|.
+ OnNewVideoConfig(media.mojom.VideoDecoderConfig decoder_config,
+ handle<data_pipe_consumer> data_pipe);
+};
+
+// Information about a Cast Streaming audio stream.
+struct AudioStreamInfo {
+ // Audio decoder configuration.
+ media.mojom.AudioDecoderConfig decoder_config;
+
+ // Audio buffer metadata receiver.
+ pending_receiver<CastStreamingBufferReceiver> buffer_receiver;
+
+ // Mojo data pipe over which audio buffer data is sent.
+ handle<data_pipe_consumer> data_pipe;
+};
+
+// Information about a Cast Streaming video stream.
+struct VideoStreamInfo {
+ // Video decoder configuration.
+ media.mojom.VideoDecoderConfig decoder_config;
+
+ // Video buffer metadata receiver.
+ pending_receiver<CastStreamingBufferReceiver> buffer_receiver;
+
+ // Mojo data pipe over which video buffer data is sent.
+ handle<data_pipe_consumer> data_pipe;
+};
+
+// Implemented by the renderer, used to start the Cast Streaming Session.
+// Closure of the Mojo channel will trigger the end of the Cast Streaming
+// Session.
+interface CastStreamingReceiver {
+ // Used for synchronization between the browser and the renderer. The browser
+ // should invoke this after binding the interface, and wait for the reply
+ // callback to know when the renderer is ready to receive and render frames.
+ EnableReceiver() => ();
+
+ // Called when the streams have been successfully initialized. At least one of
+ // |audio_stream_info| or |video_stream_info| must be set. This will only be
+ // called once per the lifetime of CastStreamingReceiver. After this call,
+ // CastStreamingBufferReceiver.ProvideBuffer() will be called on every new
+ // frame.
+ OnStreamsInitialized(
+ AudioStreamInfo? audio_stream_info,
+ VideoStreamInfo? video_stream_info);
+};
diff --git a/chromium/components/cast_streaming/renderer/BUILD.gn b/chromium/components/cast_streaming/renderer/BUILD.gn
new file mode 100644
index 00000000000..2dc75ed385c
--- /dev/null
+++ b/chromium/components/cast_streaming/renderer/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//testing/test.gni")
+
+# TODO(crbug.com/1208195): Move code to correct place with respect to the
+# /public folder to only expose publicly needed headers.
+source_set("renderer") {
+ deps = [
+ "//base",
+ "//components/cast_streaming/mojo:mojom",
+ "//media",
+ "//media/mojo/common",
+ "//mojo/public/cpp/bindings",
+ ]
+ sources = [
+ "cast_streaming_demuxer.cc",
+ "cast_streaming_demuxer.h",
+ "cast_streaming_receiver.cc",
+ "cast_streaming_receiver.h",
+ ]
+}
+
+# NOTE: This source set is intentionally empty. It is used to force the building
+# of the code defined in this directory, as it is production code which must
+# be validated as part of the CQ.
+# TODO(crbug.com/1207721): Add unit tests for code in this directory.
+source_set("unit_tests") {
+ testonly = true
+ deps = [ ":renderer" ]
+ sources = []
+}
diff --git a/chromium/components/cast_streaming/renderer/DEPS b/chromium/components/cast_streaming/renderer/DEPS
new file mode 100644
index 00000000000..89d164177a5
--- /dev/null
+++ b/chromium/components/cast_streaming/renderer/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+ "+components/cast_streaming/mojo",
+ "+media/base",
+ "+media/mojo",
+ "+mojo/public",
+]
diff --git a/chromium/components/cast_streaming/renderer/cast_streaming_demuxer.cc b/chromium/components/cast_streaming/renderer/cast_streaming_demuxer.cc
new file mode 100644
index 00000000000..e098b328cca
--- /dev/null
+++ b/chromium/components/cast_streaming/renderer/cast_streaming_demuxer.cc
@@ -0,0 +1,420 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/renderer/cast_streaming_demuxer.h"
+
+#include "base/bind.h"
+#include "base/sequence_checker.h"
+#include "base/single_thread_task_runner.h"
+#include "components/cast_streaming/renderer/cast_streaming_receiver.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/decoder_buffer.h"
+#include "media/base/timestamp_constants.h"
+#include "media/base/video_decoder_config.h"
+#include "media/mojo/common/mojo_decoder_buffer_converter.h"
+
+namespace cast_streaming {
+namespace {
+
+// media::DemuxerStream shared audio/video implementation for Cast Streaming.
+// Receives buffer metadata over a Mojo service and reads the buffers over a
+// Mojo data pipe from the browser process.
+class CastStreamingDemuxerStream : public media::DemuxerStream,
+ public mojom::CastStreamingBufferReceiver {
+ public:
+ CastStreamingDemuxerStream(
+ mojo::PendingReceiver<mojom::CastStreamingBufferReceiver>
+ pending_receiver,
+ mojo::ScopedDataPipeConsumerHandle consumer)
+ : receiver_(this, std::move(pending_receiver)),
+ decoder_buffer_reader_(std::make_unique<media::MojoDecoderBufferReader>(
+ std::move(consumer))) {
+ DVLOG(1) << __func__;
+
+ // Mojo service disconnection means the Cast Streaming Session ended and no
+ // further buffer will be received. kAborted will be returned to the media
+ // pipeline for every subsequent DemuxerStream::Read() attempt.
+ receiver_.set_disconnect_handler(base::BindOnce(
+ &CastStreamingDemuxerStream::OnMojoDisconnect, base::Unretained(this)));
+ }
+ ~CastStreamingDemuxerStream() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ }
+
+ // mojom::CastStreamingBufferReceiver implementation.
+ void ProvideBuffer(media::mojom::DecoderBufferPtr buffer) final {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ pending_buffer_metadata_.push_back(std::move(buffer));
+ GetNextBuffer();
+ }
+
+ void AbortPendingRead() {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (pending_read_cb_)
+ std::move(pending_read_cb_).Run(Status::kAborted, nullptr);
+ }
+
+ protected:
+ void ChangeDataPipe(mojo::ScopedDataPipeConsumerHandle data_pipe) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ pending_config_change_ = true;
+
+ // Reset the buffer reader and the current buffer. Data from the old pipe is
+ // no longer valid.
+ current_buffer_.reset();
+ decoder_buffer_reader_ =
+ std::make_unique<media::MojoDecoderBufferReader>(std::move(data_pipe));
+ CompletePendingConfigChange();
+ }
+
+ void CompletePendingConfigChange() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(pending_config_change_);
+
+ if (!pending_read_cb_)
+ return;
+
+ std::move(pending_read_cb_).Run(Status::kConfigChanged, nullptr);
+ pending_config_change_ = false;
+ }
+
+ // True when this stream is undergoing a decoder configuration change.
+ bool pending_config_change_ = false;
+
+ private:
+ void CompletePendingRead() {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (pending_config_change_ || !pending_read_cb_ || !current_buffer_)
+ return;
+
+ if (current_buffer_->end_of_stream()) {
+ std::move(pending_read_cb_).Run(Status::kError, nullptr);
+ return;
+ }
+
+ std::move(pending_read_cb_).Run(Status::kOk, std::move(current_buffer_));
+ GetNextBuffer();
+ }
+
+ void GetNextBuffer() {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (current_buffer_ || pending_buffer_metadata_.empty())
+ return;
+
+ media::mojom::DecoderBufferPtr buffer =
+ std::move(pending_buffer_metadata_.front());
+ pending_buffer_metadata_.pop_front();
+ decoder_buffer_reader_->ReadDecoderBuffer(
+ std::move(buffer),
+ base::BindOnce(&CastStreamingDemuxerStream::OnBufferRead,
+ base::Unretained(this)));
+ }
+
+ void OnBufferRead(scoped_refptr<media::DecoderBuffer> buffer) {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ // The pending buffer reads are cancelled when we reset the data pipe on a
+ // configuration change. Just ignore them and return early here.
+ if (!buffer)
+ return;
+
+ // Stop processing the pending buffer. OnMojoDisconnect() will trigger
+ // sending kAborted on subsequent Read() calls. This can happen if this
+ // object was in the process of reading a buffer off the data pipe when the
+ // Mojo connection ended.
+ if (!receiver_.is_bound())
+ return;
+
+ DCHECK(!current_buffer_);
+ current_buffer_ = buffer;
+ CompletePendingRead();
+ }
+
+ void OnMojoDisconnect() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ receiver_.reset();
+ pending_buffer_metadata_.clear();
+ current_buffer_ = media::DecoderBuffer::CreateEOSBuffer();
+ CompletePendingRead();
+ }
+
+ // DemuxerStream implementation.
+ void Read(ReadCB read_cb) final {
+ DVLOG(3) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(pending_read_cb_.is_null());
+
+ pending_read_cb_ = std::move(read_cb);
+ if (pending_config_change_)
+ CompletePendingConfigChange();
+ else
+ CompletePendingRead();
+ }
+ Liveness liveness() const final { return Liveness::LIVENESS_LIVE; }
+ bool SupportsConfigChanges() final { return true; }
+
+ mojo::Receiver<CastStreamingBufferReceiver> receiver_;
+ std::unique_ptr<media::MojoDecoderBufferReader> decoder_buffer_reader_;
+
+ ReadCB pending_read_cb_;
+ base::circular_deque<media::mojom::DecoderBufferPtr> pending_buffer_metadata_;
+ scoped_refptr<media::DecoderBuffer> current_buffer_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+};
+
+} // namespace
+
+class CastStreamingAudioDemuxerStream : public CastStreamingDemuxerStream {
+ public:
+ explicit CastStreamingAudioDemuxerStream(
+ mojom::AudioStreamInfoPtr audio_stream_info)
+ : CastStreamingDemuxerStream(
+ std::move(audio_stream_info->buffer_receiver),
+ std::move(audio_stream_info->data_pipe)),
+ config_(audio_stream_info->decoder_config) {
+ DVLOG(1) << __func__
+ << ": config info: " << config_.AsHumanReadableString();
+ }
+ ~CastStreamingAudioDemuxerStream() final = default;
+
+ private:
+ // CastStreamingBufferReceiver implementation.
+ void OnNewAudioConfig(const media::AudioDecoderConfig& decoder_config,
+ mojo::ScopedDataPipeConsumerHandle data_pipe) final {
+ config_ = decoder_config;
+ DVLOG(1) << __func__
+ << ": config info: " << config_.AsHumanReadableString();
+ ChangeDataPipe(std::move(data_pipe));
+ }
+
+ void OnNewVideoConfig(const media::VideoDecoderConfig& decoder_config,
+ mojo::ScopedDataPipeConsumerHandle data_pipe) final {
+ NOTREACHED();
+ }
+
+ // DemuxerStream implementation.
+ media::AudioDecoderConfig audio_decoder_config() final { return config_; }
+ media::VideoDecoderConfig video_decoder_config() final {
+ NOTREACHED();
+ return media::VideoDecoderConfig();
+ }
+ Type type() const final { return Type::AUDIO; }
+
+ media::AudioDecoderConfig config_;
+};
+
+class CastStreamingVideoDemuxerStream : public CastStreamingDemuxerStream {
+ public:
+ explicit CastStreamingVideoDemuxerStream(
+ mojom::VideoStreamInfoPtr video_stream_info)
+ : CastStreamingDemuxerStream(
+ std::move(video_stream_info->buffer_receiver),
+ std::move(video_stream_info->data_pipe)),
+ config_(video_stream_info->decoder_config) {
+ DVLOG(1) << __func__
+ << ": config info: " << config_.AsHumanReadableString();
+ }
+ ~CastStreamingVideoDemuxerStream() final = default;
+
+ private:
+ // CastStreamingBufferReceiver implementation.
+ void OnNewAudioConfig(const media::AudioDecoderConfig& decoder_config,
+ mojo::ScopedDataPipeConsumerHandle data_pipe) final {
+ NOTREACHED();
+ }
+
+ void OnNewVideoConfig(const media::VideoDecoderConfig& decoder_config,
+ mojo::ScopedDataPipeConsumerHandle data_pipe) final {
+ config_ = decoder_config;
+ DVLOG(1) << __func__
+ << ": config info: " << config_.AsHumanReadableString();
+ ChangeDataPipe(std::move(data_pipe));
+ }
+
+ // DemuxerStream implementation.
+ media::AudioDecoderConfig audio_decoder_config() final {
+ NOTREACHED();
+ return media::AudioDecoderConfig();
+ }
+ media::VideoDecoderConfig video_decoder_config() final { return config_; }
+ Type type() const final { return Type::VIDEO; }
+
+ media::VideoDecoderConfig config_;
+};
+
+CastStreamingDemuxer::CastStreamingDemuxer(
+ CastStreamingReceiver* receiver,
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner)
+ : media_task_runner_(media_task_runner),
+ original_task_runner_(base::SequencedTaskRunnerHandle::Get()),
+ receiver_(receiver) {
+ DVLOG(1) << __func__;
+ DCHECK(receiver_);
+}
+
+CastStreamingDemuxer::~CastStreamingDemuxer() {
+ DVLOG(1) << __func__;
+
+ if (was_initialization_successful_) {
+ original_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&CastStreamingReceiver::OnDemuxerDestroyed,
+ base::Unretained(receiver_)));
+ }
+}
+
+void CastStreamingDemuxer::OnStreamsInitialized(
+ mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info) {
+ DVLOG(1) << __func__;
+ DCHECK(!media_task_runner_->BelongsToCurrentThread());
+
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CastStreamingDemuxer::OnStreamsInitializedOnMediaThread,
+ base::Unretained(this), std::move(audio_stream_info),
+ std::move(video_stream_info)));
+}
+
+void CastStreamingDemuxer::OnStreamsInitializedOnMediaThread(
+ mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info) {
+ DVLOG(1) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK(initialized_cb_);
+
+ if (!audio_stream_info && !video_stream_info) {
+ std::move(initialized_cb_)
+ .Run(media::PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
+ return;
+ }
+
+ if (audio_stream_info) {
+ audio_stream_ = std::make_unique<CastStreamingAudioDemuxerStream>(
+ std::move(audio_stream_info));
+ }
+ if (video_stream_info) {
+ video_stream_ = std::make_unique<CastStreamingVideoDemuxerStream>(
+ std::move(video_stream_info));
+ }
+ was_initialization_successful_ = true;
+
+ std::move(initialized_cb_).Run(media::PipelineStatus::PIPELINE_OK);
+}
+
+std::vector<media::DemuxerStream*> CastStreamingDemuxer::GetAllStreams() {
+ DVLOG(1) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ std::vector<media::DemuxerStream*> streams;
+ if (video_stream_)
+ streams.push_back(video_stream_.get());
+ if (audio_stream_)
+ streams.push_back(audio_stream_.get());
+ return streams;
+}
+
+std::string CastStreamingDemuxer::GetDisplayName() const {
+ return "CastStreamingDemuxer";
+}
+
+void CastStreamingDemuxer::Initialize(media::DemuxerHost* host,
+ media::PipelineStatusCallback status_cb) {
+ DVLOG(1) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ host_ = host;
+
+ // Live streams have infinite duration.
+ host_->SetDuration(media::kInfiniteDuration);
+ initialized_cb_ = std::move(status_cb);
+
+ original_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CastStreamingReceiver::SetDemuxer,
+ base::Unretained(receiver_), base::Unretained(this)));
+}
+
+void CastStreamingDemuxer::AbortPendingReads() {
+ DVLOG(2) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ if (audio_stream_)
+ audio_stream_->AbortPendingRead();
+ if (video_stream_)
+ video_stream_->AbortPendingRead();
+}
+
+// Not supported.
+void CastStreamingDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {}
+
+// Not supported.
+void CastStreamingDemuxer::CancelPendingSeek(base::TimeDelta seek_time) {}
+
+// Not supported.
+void CastStreamingDemuxer::Seek(base::TimeDelta time,
+ media::PipelineStatusCallback status_cb) {
+ std::move(status_cb).Run(media::PipelineStatus::PIPELINE_OK);
+}
+
+void CastStreamingDemuxer::Stop() {
+ DVLOG(1) << __func__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ if (audio_stream_)
+ audio_stream_.reset();
+ if (video_stream_)
+ video_stream_.reset();
+}
+
+base::TimeDelta CastStreamingDemuxer::GetStartTime() const {
+ return base::TimeDelta();
+}
+
+// Not supported.
+base::Time CastStreamingDemuxer::GetTimelineOffset() const {
+ return base::Time();
+}
+
+// Not supported.
+int64_t CastStreamingDemuxer::GetMemoryUsage() const {
+ return 0;
+}
+
+absl::optional<media::container_names::MediaContainerName>
+CastStreamingDemuxer::GetContainerForMetrics() const {
+ // Cast Streaming frames have no container.
+ return absl::nullopt;
+}
+
+// Not supported.
+void CastStreamingDemuxer::OnEnabledAudioTracksChanged(
+ const std::vector<media::MediaTrack::Id>& track_ids,
+ base::TimeDelta curr_time,
+ TrackChangeCB change_completed_cb) {
+ DLOG(WARNING) << "Track changes are not supported.";
+ std::vector<media::DemuxerStream*> streams;
+ std::move(change_completed_cb).Run(media::DemuxerStream::AUDIO, streams);
+}
+
+// Not supported.
+void CastStreamingDemuxer::OnSelectedVideoTrackChanged(
+ const std::vector<media::MediaTrack::Id>& track_ids,
+ base::TimeDelta curr_time,
+ TrackChangeCB change_completed_cb) {
+ DLOG(WARNING) << "Track changes are not supported.";
+ std::vector<media::DemuxerStream*> streams;
+ std::move(change_completed_cb).Run(media::DemuxerStream::VIDEO, streams);
+}
+
+} // namespace cast_streaming
diff --git a/chromium/components/cast_streaming/renderer/cast_streaming_demuxer.h b/chromium/components/cast_streaming/renderer/cast_streaming_demuxer.h
new file mode 100644
index 00000000000..93b68aee20e
--- /dev/null
+++ b/chromium/components/cast_streaming/renderer/cast_streaming_demuxer.h
@@ -0,0 +1,88 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_STREAMING_RENDERER_CAST_STREAMING_DEMUXER_H_
+#define COMPONENTS_CAST_STREAMING_RENDERER_CAST_STREAMING_DEMUXER_H_
+
+#include "components/cast_streaming/mojo/cast_streaming_session.mojom.h"
+#include "media/base/demuxer.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace cast_streaming {
+
+class CastStreamingReceiver;
+class CastStreamingAudioDemuxerStream;
+class CastStreamingVideoDemuxerStream;
+
+// media::Demuxer implementation for a Cast Streaming Receiver.
+// This object is instantiated on the main thread, whose task runner is stored
+// as |original_task_runner_|. OnStreamsInitialized() is the only method called
+// on the main thread. Every other method is called on the media thread, whose
+// task runner is |media_task_runner_|.
+// |original_task_runner_| is used to post method calls to |receiver_|, which is
+// guaranteed to outlive this object.
+// TODO(crbug.com/1082821): Simplify the CastStreamingDemuxer initialization
+// sequence when the CastStreamingReceiver Component has been implemented.
+class CastStreamingDemuxer : public media::Demuxer {
+ public:
+ CastStreamingDemuxer(
+ CastStreamingReceiver* receiver,
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner);
+ ~CastStreamingDemuxer() final;
+
+ CastStreamingDemuxer(const CastStreamingDemuxer&) = delete;
+ CastStreamingDemuxer& operator=(const CastStreamingDemuxer&) = delete;
+
+ void OnStreamsInitialized(mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info);
+
+ private:
+ void OnStreamsInitializedOnMediaThread(
+ mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info);
+
+ // media::Demuxer implementation.
+ std::vector<media::DemuxerStream*> GetAllStreams() final;
+ std::string GetDisplayName() const final;
+ void Initialize(media::DemuxerHost* host,
+ media::PipelineStatusCallback status_cb) final;
+ void AbortPendingReads() final;
+ void StartWaitingForSeek(base::TimeDelta seek_time) final;
+ void CancelPendingSeek(base::TimeDelta seek_time) final;
+ void Seek(base::TimeDelta time,
+ media::PipelineStatusCallback status_cb) final;
+ void Stop() final;
+ base::TimeDelta GetStartTime() const final;
+ base::Time GetTimelineOffset() const final;
+ int64_t GetMemoryUsage() const final;
+ absl::optional<media::container_names::MediaContainerName>
+ GetContainerForMetrics() const final;
+ void OnEnabledAudioTracksChanged(
+ const std::vector<media::MediaTrack::Id>& track_ids,
+ base::TimeDelta curr_time,
+ TrackChangeCB change_completed_cb) final;
+ void OnSelectedVideoTrackChanged(
+ const std::vector<media::MediaTrack::Id>& track_ids,
+ base::TimeDelta curr_time,
+ TrackChangeCB change_completed_cb) final;
+
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+ scoped_refptr<base::SequencedTaskRunner> original_task_runner_;
+ media::DemuxerHost* host_ = nullptr;
+ std::unique_ptr<CastStreamingAudioDemuxerStream> audio_stream_;
+ std::unique_ptr<CastStreamingVideoDemuxerStream> video_stream_;
+
+ // Set to true if the Demuxer was successfully initialized.
+ bool was_initialization_successful_ = false;
+ media::PipelineStatusCallback initialized_cb_;
+ CastStreamingReceiver* const receiver_;
+};
+
+} // namespace cast_streaming
+
+#endif // COMPONENTS_CAST_STREAMING_RENDERER_CAST_STREAMING_DEMUXER_H_
diff --git a/chromium/components/cast_streaming/renderer/cast_streaming_receiver.cc b/chromium/components/cast_streaming/renderer/cast_streaming_receiver.cc
new file mode 100644
index 00000000000..b49992bb0c1
--- /dev/null
+++ b/chromium/components/cast_streaming/renderer/cast_streaming_receiver.cc
@@ -0,0 +1,131 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/cast_streaming/renderer/cast_streaming_receiver.h"
+
+#include "components/cast_streaming/renderer/cast_streaming_demuxer.h"
+
+namespace cast_streaming {
+
+CastStreamingReceiver::CastStreamingReceiver(
+ base::OnceCallback<
+ void(CastStreamingReceiver::InterfaceRegistryBinderCallback)>
+ interface_binder_factory) {
+ DVLOG(1) << __func__;
+ DCHECK(interface_binder_factory);
+
+ // It is fine to use an unretained pointer to |this| here as the
+ // AssociatedInterfaceRegistry, owned by |render_frame| will be torn-down at
+ // the same time as |this|.
+ std::move(interface_binder_factory)
+ .Run(base::BindRepeating(&CastStreamingReceiver::BindToReceiver,
+ base::Unretained(this)));
+}
+
+CastStreamingReceiver::~CastStreamingReceiver() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void CastStreamingReceiver::SetDemuxer(CastStreamingDemuxer* demuxer) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(demuxer);
+
+ if (demuxer_) {
+ // We do not support more than one active CastStreamingDemuxer in the same
+ // RenderFrame. Return early here.
+ demuxer->OnStreamsInitialized(mojom::AudioStreamInfoPtr(),
+ mojom::VideoStreamInfoPtr());
+ return;
+ }
+
+ DCHECK(!is_demuxer_initialized_);
+
+ if (IsBound()) {
+ demuxer_ = demuxer;
+ MaybeCallEnableReceiverCallback();
+ } else {
+ // The Cast Streaming Sender disconnected after |demuxer| was instantiated
+ // but before |demuxer| was initialized on the media thread.
+ demuxer->OnStreamsInitialized(mojom::AudioStreamInfoPtr(),
+ mojom::VideoStreamInfoPtr());
+ }
+}
+
+void CastStreamingReceiver::OnDemuxerDestroyed() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(demuxer_);
+
+ demuxer_ = nullptr;
+ is_demuxer_initialized_ = false;
+ cast_streaming_receiver_receiver_.reset();
+}
+
+void CastStreamingReceiver::BindToReceiver(
+ mojo::PendingAssociatedReceiver<mojom::CastStreamingReceiver> receiver) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!cast_streaming_receiver_receiver_.is_bound());
+
+ cast_streaming_receiver_receiver_.Bind(std::move(receiver));
+
+ // Mojo service disconnection means the Cast Streaming Session ended or the
+ // Cast Streaming Sender disconnected.
+ cast_streaming_receiver_receiver_.set_disconnect_handler(base::BindOnce(
+ &CastStreamingReceiver::OnReceiverDisconnected, base::Unretained(this)));
+}
+
+bool CastStreamingReceiver::IsBound() const {
+ DVLOG(2) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ return cast_streaming_receiver_receiver_.is_bound();
+}
+
+void CastStreamingReceiver::MaybeCallEnableReceiverCallback() {
+ DVLOG(2) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (enable_receiver_callback_ && demuxer_)
+ std::move(enable_receiver_callback_).Run();
+}
+
+void CastStreamingReceiver::OnReceiverDisconnected() {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ cast_streaming_receiver_receiver_.reset();
+ enable_receiver_callback_.Reset();
+
+ if (demuxer_ && !is_demuxer_initialized_) {
+ OnStreamsInitialized(mojom::AudioStreamInfoPtr(),
+ mojom::VideoStreamInfoPtr());
+ }
+}
+
+void CastStreamingReceiver::EnableReceiver(EnableReceiverCallback callback) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!enable_receiver_callback_);
+ DCHECK(callback);
+
+ enable_receiver_callback_ = std::move(callback);
+ MaybeCallEnableReceiverCallback();
+}
+
+void CastStreamingReceiver::OnStreamsInitialized(
+ mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info) {
+ DVLOG(1) << __func__;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!is_demuxer_initialized_);
+ DCHECK(demuxer_);
+
+ is_demuxer_initialized_ = true;
+ demuxer_->OnStreamsInitialized(std::move(audio_stream_info),
+ std::move(video_stream_info));
+}
+
+} // namespace cast_streaming
diff --git a/chromium/components/cast_streaming/renderer/cast_streaming_receiver.h b/chromium/components/cast_streaming/renderer/cast_streaming_receiver.h
new file mode 100644
index 00000000000..57ba88ce88b
--- /dev/null
+++ b/chromium/components/cast_streaming/renderer/cast_streaming_receiver.h
@@ -0,0 +1,70 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CAST_STREAMING_RENDERER_CAST_STREAMING_RECEIVER_H_
+#define COMPONENTS_CAST_STREAMING_RENDERER_CAST_STREAMING_RECEIVER_H_
+
+#include "base/callback.h"
+#include "base/sequence_checker.h"
+#include "components/cast_streaming/mojo/cast_streaming_session.mojom.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+
+namespace cast_streaming {
+
+class CastStreamingDemuxer;
+
+// Handles the Cast Streaming Session lifetime in the renderer process.
+// Owned by WebEngineRenderFrameObserver, this object will be destroyed on
+// RenderFrame destruction. This is guaranteed to outlive the
+// CastStreamingDemuxer that uses it as the RenderFrame destruction will have
+// triggered the destruction of the media pipeline and the CastStreamingDemuxer
+// before the call to content::RenderFrameObserver::OnDestruct(), which triggers
+// this object destruction.
+class CastStreamingReceiver : public mojom::CastStreamingReceiver {
+ public:
+ using PendingCastStreamingReceiver =
+ mojo::PendingAssociatedReceiver<mojom::CastStreamingReceiver>;
+ using InterfaceRegistryBinderCallback = base::RepeatingCallback<void(
+ CastStreamingReceiver::PendingCastStreamingReceiver)>;
+
+ explicit CastStreamingReceiver(
+ base::OnceCallback<void(InterfaceRegistryBinderCallback)>
+ interface_binder_factory);
+ ~CastStreamingReceiver() final;
+
+ CastStreamingReceiver(const CastStreamingReceiver&) = delete;
+ CastStreamingReceiver& operator=(const CastStreamingReceiver&) = delete;
+
+ void SetDemuxer(CastStreamingDemuxer* demuxer);
+ void OnDemuxerDestroyed();
+
+ // Returns true if a Mojo connection is active.
+ bool IsBound() const;
+
+ private:
+ void BindToReceiver(PendingCastStreamingReceiver receiver);
+
+ void MaybeCallEnableReceiverCallback();
+
+ void OnReceiverDisconnected();
+
+ // mojom::CastStreamingReceiver implementation.
+ void EnableReceiver(EnableReceiverCallback callback) final;
+ void OnStreamsInitialized(mojom::AudioStreamInfoPtr audio_stream_info,
+ mojom::VideoStreamInfoPtr video_stream_info) final;
+
+ mojo::AssociatedReceiver<mojom::CastStreamingReceiver>
+ cast_streaming_receiver_receiver_{this};
+
+ EnableReceiverCallback enable_receiver_callback_;
+ CastStreamingDemuxer* demuxer_ = nullptr;
+ bool is_demuxer_initialized_ = false;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+};
+
+} // namespace cast_streaming
+
+#endif // COMPONENTS_CAST_STREAMING_RENDERER_CAST_STREAMING_RECEIVER_H_
diff --git a/chromium/components/cbor/diagnostic_writer_unittest.cc b/chromium/components/cbor/diagnostic_writer_unittest.cc
index a45fbd0f5bd..a561275b484 100644
--- a/chromium/components/cbor/diagnostic_writer_unittest.cc
+++ b/chromium/components/cbor/diagnostic_writer_unittest.cc
@@ -64,7 +64,7 @@ TEST(CBORDiagnosticWriterTest, InvalidUTF8) {
static const uint8_t kInvalidUTF8[] = {0x62, 0xe2, 0x80};
cbor::Reader::Config config;
config.allow_invalid_utf8 = true;
- base::Optional<cbor::Value> maybe_value =
+ absl::optional<cbor::Value> maybe_value =
cbor::Reader::Read(kInvalidUTF8, config);
ASSERT_TRUE(maybe_value);
diff --git a/chromium/components/cbor/reader.cc b/chromium/components/cbor/reader.cc
index 9c748d44869..d1fd6f20191 100644
--- a/chromium/components/cbor/reader.cc
+++ b/chromium/components/cbor/reader.cc
@@ -71,7 +71,7 @@ Reader::Reader(base::span<const uint8_t> data)
Reader::~Reader() {}
// static
-base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
+absl::optional<Value> Reader::Read(base::span<uint8_t const> data,
DecoderError* error_code_out,
int max_nesting_level) {
Config config;
@@ -82,7 +82,7 @@ base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
}
// static
-base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
+absl::optional<Value> Reader::Read(base::span<uint8_t const> data,
size_t* num_bytes_consumed,
DecoderError* error_code_out,
int max_nesting_level) {
@@ -97,10 +97,10 @@ base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
}
// static
-base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
+absl::optional<Value> Reader::Read(base::span<uint8_t const> data,
const Config& config) {
Reader reader(data);
- base::Optional<Value> value =
+ absl::optional<Value> value =
reader.DecodeCompleteDataItem(config, config.max_nesting_level);
auto error = reader.GetErrorCode();
@@ -122,16 +122,16 @@ base::Optional<Value> Reader::Read(base::span<uint8_t const> data,
return value;
}
-base::Optional<Value> Reader::DecodeCompleteDataItem(const Config& config,
+absl::optional<Value> Reader::DecodeCompleteDataItem(const Config& config,
int max_nesting_level) {
if (max_nesting_level < 0 || max_nesting_level > kCBORMaxDepth) {
error_code_ = DecoderError::TOO_MUCH_NESTING;
- return base::nullopt;
+ return absl::nullopt;
}
- base::Optional<DataItemHeader> header = DecodeDataItemHeader();
+ absl::optional<DataItemHeader> header = DecodeDataItemHeader();
if (!header.has_value()) {
- return base::nullopt;
+ return absl::nullopt;
}
switch (header->type) {
@@ -156,29 +156,29 @@ base::Optional<Value> Reader::DecodeCompleteDataItem(const Config& config,
}
error_code_ = DecoderError::UNSUPPORTED_MAJOR_TYPE;
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<Reader::DataItemHeader> Reader::DecodeDataItemHeader() {
- const base::Optional<uint8_t> initial_byte = ReadByte();
+absl::optional<Reader::DataItemHeader> Reader::DecodeDataItemHeader() {
+ const absl::optional<uint8_t> initial_byte = ReadByte();
if (!initial_byte) {
- return base::nullopt;
+ return absl::nullopt;
}
const auto major_type = GetMajorType(initial_byte.value());
const uint8_t additional_info = GetAdditionalInfo(initial_byte.value());
- base::Optional<uint64_t> value = ReadVariadicLengthInteger(additional_info);
- return value ? base::make_optional(
+ absl::optional<uint64_t> value = ReadVariadicLengthInteger(additional_info);
+ return value ? absl::make_optional(
DataItemHeader{major_type, additional_info, value.value()})
- : base::nullopt;
+ : absl::nullopt;
}
-base::Optional<uint64_t> Reader::ReadVariadicLengthInteger(
+absl::optional<uint64_t> Reader::ReadVariadicLengthInteger(
uint8_t additional_info) {
uint8_t additional_bytes = 0;
if (additional_info < 24) {
- return base::make_optional(additional_info);
+ return absl::make_optional(additional_info);
} else if (additional_info == 24) {
additional_bytes = 1;
} else if (additional_info == 25) {
@@ -189,13 +189,13 @@ base::Optional<uint64_t> Reader::ReadVariadicLengthInteger(
additional_bytes = 8;
} else {
error_code_ = DecoderError::UNKNOWN_ADDITIONAL_INFO;
- return base::nullopt;
+ return absl::nullopt;
}
- const base::Optional<base::span<const uint8_t>> bytes =
+ const absl::optional<base::span<const uint8_t>> bytes =
ReadBytes(additional_bytes);
if (!bytes) {
- return base::nullopt;
+ return absl::nullopt;
}
uint64_t int_data = 0;
@@ -205,36 +205,36 @@ base::Optional<uint64_t> Reader::ReadVariadicLengthInteger(
}
return IsEncodingMinimal(additional_bytes, int_data)
- ? base::make_optional(int_data)
- : base::nullopt;
+ ? absl::make_optional(int_data)
+ : absl::nullopt;
}
-base::Optional<Value> Reader::DecodeValueToNegative(uint64_t value) {
+absl::optional<Value> Reader::DecodeValueToNegative(uint64_t value) {
auto negative_value = -base::CheckedNumeric<int64_t>(value) - 1;
if (!negative_value.IsValid()) {
error_code_ = DecoderError::OUT_OF_RANGE_INTEGER_VALUE;
- return base::nullopt;
+ return absl::nullopt;
}
return Value(negative_value.ValueOrDie());
}
-base::Optional<Value> Reader::DecodeValueToUnsigned(uint64_t value) {
+absl::optional<Value> Reader::DecodeValueToUnsigned(uint64_t value) {
auto unsigned_value = base::CheckedNumeric<int64_t>(value);
if (!unsigned_value.IsValid()) {
error_code_ = DecoderError::OUT_OF_RANGE_INTEGER_VALUE;
- return base::nullopt;
+ return absl::nullopt;
}
return Value(unsigned_value.ValueOrDie());
}
-base::Optional<Value> Reader::DecodeToSimpleValue(
+absl::optional<Value> Reader::DecodeToSimpleValue(
const DataItemHeader& header) {
// ReadVariadicLengthInteger provides this bound.
CHECK_LE(header.additional_info, 27);
// Floating point numbers are not supported.
if (header.additional_info > 24) {
error_code_ = DecoderError::UNSUPPORTED_FLOATING_POINT_VALUE;
- return base::nullopt;
+ return absl::nullopt;
}
// Since |header.additional_info| <= 24, ReadVariadicLengthInteger also
@@ -253,16 +253,16 @@ base::Optional<Value> Reader::DecodeToSimpleValue(
}
error_code_ = DecoderError::UNSUPPORTED_SIMPLE_VALUE;
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<Value> Reader::ReadStringContent(
+absl::optional<Value> Reader::ReadStringContent(
const Reader::DataItemHeader& header,
const Config& config) {
uint64_t num_bytes = header.value;
- const base::Optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
+ const absl::optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
if (!bytes) {
- return base::nullopt;
+ return absl::nullopt;
}
std::string cbor_string(bytes->begin(), bytes->end());
@@ -275,22 +275,22 @@ base::Optional<Value> Reader::ReadStringContent(
}
error_code_ = DecoderError::INVALID_UTF8;
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<Value> Reader::ReadByteStringContent(
+absl::optional<Value> Reader::ReadByteStringContent(
const Reader::DataItemHeader& header) {
uint64_t num_bytes = header.value;
- const base::Optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
+ const absl::optional<base::span<const uint8_t>> bytes = ReadBytes(num_bytes);
if (!bytes) {
- return base::nullopt;
+ return absl::nullopt;
}
std::vector<uint8_t> cbor_byte_string(bytes->begin(), bytes->end());
return Value(std::move(cbor_byte_string));
}
-base::Optional<Value> Reader::ReadArrayContent(
+absl::optional<Value> Reader::ReadArrayContent(
const Reader::DataItemHeader& header,
const Config& config,
int max_nesting_level) {
@@ -298,17 +298,17 @@ base::Optional<Value> Reader::ReadArrayContent(
Value::ArrayValue cbor_array;
for (uint64_t i = 0; i < length; ++i) {
- base::Optional<Value> cbor_element =
+ absl::optional<Value> cbor_element =
DecodeCompleteDataItem(config, max_nesting_level - 1);
if (!cbor_element.has_value()) {
- return base::nullopt;
+ return absl::nullopt;
}
cbor_array.push_back(std::move(cbor_element.value()));
}
return Value(std::move(cbor_array));
}
-base::Optional<Value> Reader::ReadMapContent(
+absl::optional<Value> Reader::ReadMapContent(
const Reader::DataItemHeader& header,
const Config& config,
int max_nesting_level) {
@@ -316,12 +316,12 @@ base::Optional<Value> Reader::ReadMapContent(
Value::MapValue cbor_map;
for (uint64_t i = 0; i < length; ++i) {
- base::Optional<Value> key =
+ absl::optional<Value> key =
DecodeCompleteDataItem(config, max_nesting_level - 1);
- base::Optional<Value> value =
+ absl::optional<Value> value =
DecodeCompleteDataItem(config, max_nesting_level - 1);
if (!key.has_value() || !value.has_value()) {
- return base::nullopt;
+ return absl::nullopt;
}
switch (key.value().type()) {
@@ -332,13 +332,13 @@ base::Optional<Value> Reader::ReadMapContent(
break;
case Value::Type::INVALID_UTF8:
error_code_ = DecoderError::INVALID_UTF8;
- return base::nullopt;
+ return absl::nullopt;
default:
error_code_ = DecoderError::INCORRECT_MAP_KEY_TYPE;
- return base::nullopt;
+ return absl::nullopt;
}
if (!IsKeyInOrder(key.value(), &cbor_map)) {
- return base::nullopt;
+ return absl::nullopt;
}
cbor_map.insert_or_assign(std::move(key.value()), std::move(value.value()));
@@ -346,16 +346,16 @@ base::Optional<Value> Reader::ReadMapContent(
return Value(std::move(cbor_map));
}
-base::Optional<uint8_t> Reader::ReadByte() {
- const base::Optional<base::span<const uint8_t>> bytes = ReadBytes(1);
- return bytes ? base::make_optional(bytes.value()[0]) : base::nullopt;
+absl::optional<uint8_t> Reader::ReadByte() {
+ const absl::optional<base::span<const uint8_t>> bytes = ReadBytes(1);
+ return bytes ? absl::make_optional(bytes.value()[0]) : absl::nullopt;
}
-base::Optional<base::span<const uint8_t>> Reader::ReadBytes(
+absl::optional<base::span<const uint8_t>> Reader::ReadBytes(
uint64_t num_bytes) {
if (base::strict_cast<uint64_t>(rest_.size()) < num_bytes) {
error_code_ = DecoderError::INCOMPLETE_CBOR_DATA;
- return base::nullopt;
+ return absl::nullopt;
}
const base::span<const uint8_t> ret = rest_.first(num_bytes);
rest_ = rest_.subspan(num_bytes);
diff --git a/chromium/components/cbor/reader.h b/chromium/components/cbor/reader.h
index 4ff907653c8..058cd88099b 100644
--- a/chromium/components/cbor/reader.h
+++ b/chromium/components/cbor/reader.h
@@ -7,13 +7,10 @@
#include <stddef.h>
-#include <string>
-#include <vector>
-
#include "base/containers/span.h"
-#include "base/optional.h"
#include "components/cbor/cbor_export.h"
#include "components/cbor/values.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
// Concise Binary Object Representation (CBOR) decoder as defined by
// https://tools.ietf.org/html/rfc7049. This decoder only accepts canonical CBOR
@@ -125,18 +122,18 @@ class CBOR_EXPORT Reader {
//
// Returns an empty Optional if not all the data was consumed, and sets
// |error_code_out| to EXTRANEOUS_DATA in this case.
- static base::Optional<Value> Read(base::span<const uint8_t> input_data,
+ static absl::optional<Value> Read(base::span<const uint8_t> input_data,
DecoderError* error_code_out = nullptr,
int max_nesting_level = kCBORMaxDepth);
// A version of |Read|, above, that takes a |Config| structure to allow
// additional controls.
- static base::Optional<Value> Read(base::span<const uint8_t> input_data,
+ static absl::optional<Value> Read(base::span<const uint8_t> input_data,
const Config& config);
// A version of |Read| that takes some fields of |Config| as parameters to
// avoid having to construct a |Config| object explicitly.
- static base::Optional<Value> Read(base::span<const uint8_t> input_data,
+ static absl::optional<Value> Read(base::span<const uint8_t> input_data,
size_t* num_bytes_consumed,
DecoderError* error_code_out = nullptr,
int max_nesting_level = kCBORMaxDepth);
@@ -162,24 +159,24 @@ class CBOR_EXPORT Reader {
uint64_t value;
};
- base::Optional<DataItemHeader> DecodeDataItemHeader();
- base::Optional<Value> DecodeCompleteDataItem(const Config& config,
+ absl::optional<DataItemHeader> DecodeDataItemHeader();
+ absl::optional<Value> DecodeCompleteDataItem(const Config& config,
int max_nesting_level);
- base::Optional<Value> DecodeValueToNegative(uint64_t value);
- base::Optional<Value> DecodeValueToUnsigned(uint64_t value);
- base::Optional<Value> DecodeToSimpleValue(const DataItemHeader& header);
- base::Optional<uint64_t> ReadVariadicLengthInteger(uint8_t additional_info);
- base::Optional<Value> ReadByteStringContent(const DataItemHeader& header);
- base::Optional<Value> ReadStringContent(const DataItemHeader& header,
+ absl::optional<Value> DecodeValueToNegative(uint64_t value);
+ absl::optional<Value> DecodeValueToUnsigned(uint64_t value);
+ absl::optional<Value> DecodeToSimpleValue(const DataItemHeader& header);
+ absl::optional<uint64_t> ReadVariadicLengthInteger(uint8_t additional_info);
+ absl::optional<Value> ReadByteStringContent(const DataItemHeader& header);
+ absl::optional<Value> ReadStringContent(const DataItemHeader& header,
const Config& config);
- base::Optional<Value> ReadArrayContent(const DataItemHeader& header,
+ absl::optional<Value> ReadArrayContent(const DataItemHeader& header,
const Config& config,
int max_nesting_level);
- base::Optional<Value> ReadMapContent(const DataItemHeader& header,
+ absl::optional<Value> ReadMapContent(const DataItemHeader& header,
const Config& config,
int max_nesting_level);
- base::Optional<uint8_t> ReadByte();
- base::Optional<base::span<const uint8_t>> ReadBytes(uint64_t num_bytes);
+ absl::optional<uint8_t> ReadByte();
+ absl::optional<base::span<const uint8_t>> ReadBytes(uint64_t num_bytes);
bool IsKeyInOrder(const Value& new_key, Value::MapValue* map);
bool IsEncodingMinimal(uint8_t additional_bytes, uint64_t uint_data);
diff --git a/chromium/components/cbor/reader_fuzzer.cc b/chromium/components/cbor/reader_fuzzer.cc
index 3a1e0458ad9..439154c830c 100644
--- a/chromium/components/cbor/reader_fuzzer.cc
+++ b/chromium/components/cbor/reader_fuzzer.cc
@@ -12,10 +12,10 @@ namespace cbor {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::vector<uint8_t> input(data, data + size);
- base::Optional<Value> cbor = Reader::Read(input);
+ absl::optional<Value> cbor = Reader::Read(input);
if (cbor.has_value()) {
- base::Optional<std::vector<uint8_t>> serialized_cbor =
+ absl::optional<std::vector<uint8_t>> serialized_cbor =
Writer::Write(cbor.value());
CHECK(serialized_cbor.has_value());
if (serialized_cbor.has_value()) {
diff --git a/chromium/components/cbor/reader_unittest.cc b/chromium/components/cbor/reader_unittest.cc
index cfee33d71f7..9e81a07f56b 100644
--- a/chromium/components/cbor/reader_unittest.cc
+++ b/chromium/components/cbor/reader_unittest.cc
@@ -52,7 +52,7 @@ TEST(CBORReaderTest, TestReadUint) {
for (const UintTestCase& test_case : kUintTestCases) {
SCOPED_TRACE(testing::Message() << "testing uint: " << test_case.value);
- base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+ absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), Value::Type::UNSIGNED);
EXPECT_EQ(cbor.value().GetInteger(), test_case.value);
@@ -117,7 +117,7 @@ TEST(CBORReaderTest, TestUintEncodedWithNonMinimumByteLength) {
SCOPED_TRACE(testing::Message()
<< "testing element at index : " << test_case_index++);
- base::Optional<Value> cbor = Reader::Read(non_minimal_uint, &error_code);
+ absl::optional<Value> cbor = Reader::Read(non_minimal_uint, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::NON_MINIMAL_CBOR_ENCODING);
}
@@ -144,7 +144,7 @@ TEST(CBORReaderTest, TestReadNegativeInt) {
SCOPED_TRACE(testing::Message()
<< "testing negative int : " << test_case.negative_int);
- base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+ absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), Value::Type::NEGATIVE);
EXPECT_EQ(cbor.value().GetInteger(), test_case.negative_int);
@@ -184,7 +184,7 @@ TEST(CBORReaderTest, TestReadBytes) {
SCOPED_TRACE(testing::Message()
<< "testing string test case at : " << element_index++);
- base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+ absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), Value::Type::BYTE_STRING);
EXPECT_EQ(cbor.value().GetBytestring(), test_case.value);
@@ -226,7 +226,7 @@ TEST(CBORReaderTest, TestReadString) {
SCOPED_TRACE(testing::Message()
<< "testing string value : " << test_case.value);
- base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+ absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), Value::Type::STRING);
EXPECT_EQ(cbor.value().GetString(), test_case.value);
@@ -271,7 +271,7 @@ TEST(CBORReaderTest, TestReadStringWithNUL) {
SCOPED_TRACE(testing::Message()
<< "testing string with nul bytes :" << test_case.value);
- base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+ absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), Value::Type::STRING);
EXPECT_EQ(cbor.value().GetString(), test_case.value);
@@ -301,7 +301,7 @@ TEST(CBORReaderTest, TestReadStringWithInvalidByteSequenceAfterNUL) {
static const std::vector<uint8_t> string_with_invalid_continuation_byte = {
0x63, 0x00, 0x00, 0xA6};
Reader::DecoderError error_code;
- base::Optional<Value> cbor =
+ absl::optional<Value> cbor =
Reader::Read(string_with_invalid_continuation_byte, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::INVALID_UTF8);
@@ -317,7 +317,7 @@ TEST(CBORReaderTest, TestReadArray) {
// clang-format on
};
- base::Optional<Value> cbor = Reader::Read(kArrayTestCaseCbor);
+ absl::optional<Value> cbor = Reader::Read(kArrayTestCaseCbor);
ASSERT_TRUE(cbor.has_value());
const Value cbor_array = std::move(cbor.value());
ASSERT_EQ(cbor_array.type(), Value::Type::ARRAY);
@@ -366,7 +366,7 @@ TEST(CBORReaderTest, TestReadMapWithMapValue) {
// clang-format on
};
- base::Optional<Value> cbor = Reader::Read(kMapTestCaseCbor);
+ absl::optional<Value> cbor = Reader::Read(kMapTestCaseCbor);
ASSERT_TRUE(cbor.has_value());
const Value cbor_val = std::move(cbor.value());
ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -428,7 +428,7 @@ TEST(CBORReaderTest, TestReadMapWithIntegerKeys) {
// clang-format on
};
- base::Optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
+ absl::optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
ASSERT_TRUE(cbor.has_value());
const Value cbor_val = std::move(cbor.value());
ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -487,7 +487,7 @@ TEST(CBORReaderTest, TestReadMapWithNegativeIntegersKeys) {
// clang-format on
};
- base::Optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
+ absl::optional<Value> cbor = Reader::Read(kMapWithIntegerKeyCbor);
ASSERT_TRUE(cbor.has_value());
const Value cbor_val = std::move(cbor.value());
ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -541,7 +541,7 @@ TEST(CBORReaderTest, TestReadMapWithArray) {
// clang-format on
};
- base::Optional<Value> cbor = Reader::Read(kMapArrayTestCaseCbor);
+ absl::optional<Value> cbor = Reader::Read(kMapArrayTestCaseCbor);
ASSERT_TRUE(cbor.has_value());
const Value cbor_val = std::move(cbor.value());
ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -594,7 +594,7 @@ TEST(CBORReaderTest, TestReadMapWithTextStringKeys) {
};
Reader::DecoderError error_code;
- base::Optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
+ absl::optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor->type(), Value::Type::MAP);
ASSERT_EQ(cbor->GetMap().size(), 2u);
@@ -637,7 +637,7 @@ TEST(CBORReaderTest, TestReadMapWithByteStringKeys) {
};
Reader::DecoderError error_code;
- base::Optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
+ absl::optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor->type(), Value::Type::MAP);
ASSERT_EQ(cbor->GetMap().size(), 2u);
@@ -710,7 +710,7 @@ TEST(CBORReaderTest, TestReadMapWithMixedKeys) {
};
Reader::DecoderError error_code;
- base::Optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
+ absl::optional<Value> cbor = Reader::Read(kMapTestCase, &error_code);
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor->type(), Value::Type::MAP);
ASSERT_EQ(cbor->GetMap().size(), 6u);
@@ -763,7 +763,7 @@ TEST(CBORReaderTest, TestReadNestedMap) {
// clang-format on
};
- base::Optional<Value> cbor = Reader::Read(kNestedMapTestCase);
+ absl::optional<Value> cbor = Reader::Read(kNestedMapTestCase);
ASSERT_TRUE(cbor.has_value());
const Value cbor_val = std::move(cbor.value());
ASSERT_EQ(cbor_val.type(), Value::Type::MAP);
@@ -800,11 +800,11 @@ TEST(CBORReaderTest, TestIntegerRange) {
static const std::vector<uint8_t> kMinNegativeInt = {
0x3b, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- base::Optional<Value> max_positive_int = Reader::Read(kMaxPositiveInt);
+ absl::optional<Value> max_positive_int = Reader::Read(kMaxPositiveInt);
ASSERT_TRUE(max_positive_int.has_value());
EXPECT_EQ(max_positive_int.value().GetInteger(), INT64_MAX);
- base::Optional<Value> min_negative_int = Reader::Read(kMinNegativeInt);
+ absl::optional<Value> min_negative_int = Reader::Read(kMinNegativeInt);
ASSERT_TRUE(min_negative_int.has_value());
EXPECT_EQ(min_negative_int.value().GetInteger(), INT64_MIN);
}
@@ -817,12 +817,12 @@ TEST(CBORReaderTest, TestIntegerOutOfRangeError) {
0x3b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Reader::DecoderError error_code;
- base::Optional<Value> positive_int_out_of_range_cbor =
+ absl::optional<Value> positive_int_out_of_range_cbor =
Reader::Read(kOutOfRangePositiveInt, &error_code);
EXPECT_FALSE(positive_int_out_of_range_cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_RANGE_INTEGER_VALUE);
- base::Optional<Value> negative_int_out_of_range_cbor =
+ absl::optional<Value> negative_int_out_of_range_cbor =
Reader::Read(kOutOfRangeNegativeInt, &error_code);
EXPECT_FALSE(negative_int_out_of_range_cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_RANGE_INTEGER_VALUE);
@@ -844,7 +844,7 @@ TEST(CBORReaderTest, TestReadSimpleValue) {
SCOPED_TRACE(testing::Message()
<< "testing simple value at index : " << test_element_index++);
- base::Optional<Value> cbor = Reader::Read(test_case.cbor_data);
+ absl::optional<Value> cbor = Reader::Read(test_case.cbor_data);
ASSERT_TRUE(cbor.has_value());
ASSERT_EQ(cbor.value().type(), Value::Type::SIMPLE_VALUE);
EXPECT_EQ(cbor.value().GetSimpleValue(), test_case.value);
@@ -880,7 +880,7 @@ TEST(CBORReaderTest, TestReadUnsupportedFloatingPointNumbers) {
<< "testing unsupported floating point : "
<< testing::PrintToString(unsupported_floating_point));
Reader::DecoderError error_code;
- base::Optional<Value> cbor =
+ absl::optional<Value> cbor =
Reader::Read(unsupported_floating_point, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code,
@@ -925,7 +925,7 @@ TEST(CBORReaderTest, TestIncompleteCBORDataError) {
<< test_element_index++);
Reader::DecoderError error_code;
- base::Optional<Value> cbor = Reader::Read(incomplete_data, &error_code);
+ absl::optional<Value> cbor = Reader::Read(incomplete_data, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::INCOMPLETE_CBOR_DATA);
}
@@ -947,7 +947,7 @@ TEST(CBORReaderTest, TestUnsupportedMapKeyFormatError) {
};
Reader::DecoderError error_code;
- base::Optional<Value> cbor = Reader::Read(kMapWithUintKey, &error_code);
+ absl::optional<Value> cbor = Reader::Read(kMapWithUintKey, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::INCORRECT_MAP_KEY_TYPE);
}
@@ -979,7 +979,7 @@ TEST(CBORReaderTest, TestUnknownAdditionalInfoError) {
<< "testing data at index : " << test_element_index++);
Reader::DecoderError error_code;
- base::Optional<Value> cbor = Reader::Read(incorrect_cbor, &error_code);
+ absl::optional<Value> cbor = Reader::Read(incorrect_cbor, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::UNKNOWN_ADDITIONAL_INFO);
}
@@ -1004,7 +1004,7 @@ TEST(CBORReaderTest, TestTooMuchNestingError) {
SCOPED_TRACE(testing::Message()
<< "testing zero nested data : " << test_element_index++);
Reader::DecoderError error_code;
- base::Optional<Value> cbor = Reader::Read(zero_depth_data, &error_code, 0);
+ absl::optional<Value> cbor = Reader::Read(zero_depth_data, &error_code, 0);
EXPECT_TRUE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
}
@@ -1026,12 +1026,12 @@ TEST(CBORReaderTest, TestTooMuchNestingError) {
};
Reader::DecoderError error_code;
- base::Optional<Value> cbor_single_layer_max =
+ absl::optional<Value> cbor_single_layer_max =
Reader::Read(kNestedCBORData, &error_code, 1);
EXPECT_FALSE(cbor_single_layer_max.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::TOO_MUCH_NESTING);
- base::Optional<Value> cbor_double_layer_max =
+ absl::optional<Value> cbor_double_layer_max =
Reader::Read(kNestedCBORData, &error_code, 2);
EXPECT_TRUE(cbor_double_layer_max.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
@@ -1087,7 +1087,7 @@ TEST(CBORReaderTest, TestOutOfOrderKeyError) {
scope_message << "testing unsorted map : " << test_element_index++;
SCOPED_TRACE(scope_message);
- base::Optional<Value> cbor =
+ absl::optional<Value> cbor =
Reader::Read(unsorted_map, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_ORDER_KEY);
@@ -1120,7 +1120,7 @@ TEST(CBORReaderTest, TestDuplicateKeyError) {
Reader::DecoderError error_code;
- base::Optional<Value> cbor = Reader::Read(kMapWithDuplicateKey, &error_code);
+ absl::optional<Value> cbor = Reader::Read(kMapWithDuplicateKey, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::OUT_OF_ORDER_KEY);
}
@@ -1143,7 +1143,7 @@ TEST(CBORReaderTest, TestIncorrectStringEncodingError) {
SCOPED_TRACE(testing::Message() << "testing cbor data utf8 encoding : "
<< test_element_index++);
- base::Optional<Value> correctly_encoded_cbor =
+ absl::optional<Value> correctly_encoded_cbor =
Reader::Read(cbor_byte, &error_code);
EXPECT_TRUE(correctly_encoded_cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::CBOR_NO_ERROR);
@@ -1151,7 +1151,7 @@ TEST(CBORReaderTest, TestIncorrectStringEncodingError) {
// Incorrect UTF8 encoding referenced by section 3.5.3 of the stress test.
std::vector<uint8_t> impossible_utf_byte{0x64, 0xfe, 0xfe, 0xff, 0xff};
- base::Optional<Value> incorrectly_encoded_cbor =
+ absl::optional<Value> incorrectly_encoded_cbor =
Reader::Read(impossible_utf_byte, &error_code);
EXPECT_FALSE(incorrectly_encoded_cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::INVALID_UTF8);
@@ -1177,7 +1177,7 @@ TEST(CBORReaderTest, TestExtraneousCBORDataError) {
<< "testing cbor extraneous data : " << test_element_index++);
Reader::DecoderError error_code;
- base::Optional<Value> cbor =
+ absl::optional<Value> cbor =
Reader::Read(extraneous_cbor_data, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::EXTRANEOUS_DATA);
@@ -1212,7 +1212,7 @@ TEST(CBORReaderTest, TestUnsupportedSimpleValue) {
<< ::testing::PrintToString(unsupported_simple_val));
Reader::DecoderError error_code;
- base::Optional<Value> cbor =
+ absl::optional<Value> cbor =
Reader::Read(unsupported_simple_val, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::UNSUPPORTED_SIMPLE_VALUE);
@@ -1228,7 +1228,7 @@ TEST(CBORReaderTest, TestSuperLongContentDontCrash) {
};
for (const auto& test_case : kTestCases) {
Reader::DecoderError error_code;
- base::Optional<Value> cbor = Reader::Read(test_case, &error_code);
+ absl::optional<Value> cbor = Reader::Read(test_case, &error_code);
EXPECT_FALSE(cbor.has_value());
EXPECT_EQ(error_code, Reader::DecoderError::INCOMPLETE_CBOR_DATA);
}
@@ -1252,7 +1252,7 @@ TEST(CBORReaderTest, AllowInvalidUTF8) {
Reader::Config config;
config.error_code_out = &error;
- base::Optional<Value> cbor = Reader::Read(kInvalidUTF8, config);
+ absl::optional<Value> cbor = Reader::Read(kInvalidUTF8, config);
EXPECT_FALSE(cbor);
EXPECT_EQ(Reader::DecoderError::INVALID_UTF8, error);
diff --git a/chromium/components/cbor/values.cc b/chromium/components/cbor/values.cc
index 7329b584ffc..be88f500598 100644
--- a/chromium/components/cbor/values.cc
+++ b/chromium/components/cbor/values.cc
@@ -10,6 +10,7 @@
#include "base/check_op.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "components/cbor/constants.h"
@@ -113,7 +114,7 @@ Value::Value(base::StringPiece in_string, Type type) : type_(type) {
switch (type_) {
case Type::STRING:
new (&string_value_) std::string();
- string_value_ = in_string.as_string();
+ string_value_ = std::string(in_string);
DCHECK(base::IsStringUTF8(string_value_));
break;
case Type::BYTE_STRING:
diff --git a/chromium/components/cbor/writer.cc b/chromium/components/cbor/writer.cc
index 24650c75915..0e27a0f0be5 100644
--- a/chromium/components/cbor/writer.cc
+++ b/chromium/components/cbor/writer.cc
@@ -17,19 +17,19 @@ namespace cbor {
Writer::~Writer() {}
// static
-base::Optional<std::vector<uint8_t>> Writer::Write(const Value& node,
+absl::optional<std::vector<uint8_t>> Writer::Write(const Value& node,
const Config& config) {
std::vector<uint8_t> cbor;
Writer writer(&cbor);
if (!writer.EncodeCBOR(node, config.max_nesting_level,
config.allow_invalid_utf8_for_testing)) {
- return base::nullopt;
+ return absl::nullopt;
}
return cbor;
}
// static
-base::Optional<std::vector<uint8_t>> Writer::Write(const Value& node,
+absl::optional<std::vector<uint8_t>> Writer::Write(const Value& node,
size_t max_nesting_level) {
Config config;
config.max_nesting_level = base::checked_cast<int>(max_nesting_level);
diff --git a/chromium/components/cbor/writer.h b/chromium/components/cbor/writer.h
index a4f64ee1424..c4596b88aef 100644
--- a/chromium/components/cbor/writer.h
+++ b/chromium/components/cbor/writer.h
@@ -10,9 +10,9 @@
#include <vector>
-#include "base/optional.h"
#include "components/cbor/cbor_export.h"
#include "components/cbor/values.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
// A basic Concise Binary Object Representation (CBOR) encoder as defined by
// https://tools.ietf.org/html/rfc7049. This is a generic encoder that supplies
@@ -77,12 +77,12 @@ class CBOR_EXPORT Writer {
// Returns the CBOR byte string representation of |node|, unless its nesting
// depth is greater than |max_nesting_level|, in which case an empty optional
// value is returned.
- static base::Optional<std::vector<uint8_t>> Write(
+ static absl::optional<std::vector<uint8_t>> Write(
const Value& node,
size_t max_nesting_level = kDefaultMaxNestingDepth);
// A version of |Write| above that takes a Config.
- static base::Optional<std::vector<uint8_t>> Write(const Value& node,
+ static absl::optional<std::vector<uint8_t>> Write(const Value& node,
const Config& config);
private:
diff --git a/chromium/components/cdm/browser/cdm_message_filter_android.cc b/chromium/components/cdm/browser/cdm_message_filter_android.cc
index c7c260afd01..63eb9bd6b87 100644
--- a/chromium/components/cdm/browser/cdm_message_filter_android.cc
+++ b/chromium/components/cdm/browser/cdm_message_filter_android.cc
@@ -17,6 +17,7 @@
#include "components/cdm/common/cdm_messages_android.h"
#include "content/public/browser/android/android_overlay_provider.h"
#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
#include "media/base/android/media_codec_util.h"
#include "media/base/android/media_drm_bridge.h"
#include "media/base/audio_codecs.h"
diff --git a/chromium/components/cdm/browser/media_drm_storage_impl.cc b/chromium/components/cdm/browser/media_drm_storage_impl.cc
index 4b9967b72ca..1cf9f6618c5 100644
--- a/chromium/components/cdm/browser/media_drm_storage_impl.cc
+++ b/chromium/components/cdm/browser/media_drm_storage_impl.cc
@@ -13,7 +13,6 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
-#include "base/optional.h"
#include "base/strings/string_util.h"
#include "base/util/values/values_util.h"
#include "build/build_config.h"
@@ -24,6 +23,7 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_handle.h"
#include "media/base/media_drm_key_type.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
#include "url/url_constants.h"
@@ -166,7 +166,7 @@ class OriginData {
if (!origin_id_value)
return nullptr;
- base::Optional<base::UnguessableToken> origin_id =
+ absl::optional<base::UnguessableToken> origin_id =
util::ValueToUnguessableToken(*origin_id_value);
if (!origin_id)
return nullptr;
@@ -613,7 +613,7 @@ std::set<GURL> MediaDrmStorageImpl::GetAllOrigins(
return std::set<GURL>();
std::set<GURL> origin_set;
- for (const auto& key_value : *storage_dict) {
+ for (const auto& key_value : storage_dict->DictItems()) {
GURL origin(key_value.first);
if (origin.is_valid())
origin_set.insert(origin);
@@ -747,7 +747,7 @@ MediaDrmStorageImpl::~MediaDrmStorageImpl() {
DVLOG(1) << __func__;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (init_cb_)
- std::move(init_cb_).Run(false, base::nullopt);
+ std::move(init_cb_).Run(false, absl::nullopt);
}
void MediaDrmStorageImpl::Initialize(InitializeCallback callback) {
@@ -792,7 +792,7 @@ void MediaDrmStorageImpl::OnOriginIdObtained(
}
void MediaDrmStorageImpl::OnEmptyOriginIdAllowed(bool allowed) {
- std::move(init_cb_).Run(allowed, base::nullopt);
+ std::move(init_cb_).Run(allowed, absl::nullopt);
}
void MediaDrmStorageImpl::OnProvisioned(OnProvisionedCallback callback) {
diff --git a/chromium/components/cdm/browser/media_drm_storage_impl.h b/chromium/components/cdm/browser/media_drm_storage_impl.h
index 45686fe4210..772f9793b67 100644
--- a/chromium/components/cdm/browser/media_drm_storage_impl.h
+++ b/chromium/components/cdm/browser/media_drm_storage_impl.h
@@ -11,7 +11,6 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
@@ -21,6 +20,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "media/mojo/mojom/media_drm_storage.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -47,7 +47,7 @@ class MediaDrmStorageImpl final
public:
// When using per-origin provisioning, this is the ID for the origin.
// If not specified, the device specific origin ID is to be used.
- using MediaDrmOriginId = base::Optional<base::UnguessableToken>;
+ using MediaDrmOriginId = absl::optional<base::UnguessableToken>;
// |success| is true if an origin ID was obtained and |origin_id| is
// specified, false otherwise.
diff --git a/chromium/components/cdm/browser/media_drm_storage_impl_unittest.cc b/chromium/components/cdm/browser/media_drm_storage_impl_unittest.cc
index a88e56f6c9a..df61f8f9fe3 100644
--- a/chromium/components/cdm/browser/media_drm_storage_impl_unittest.cc
+++ b/chromium/components/cdm/browser/media_drm_storage_impl_unittest.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/unguessable_token.h"
@@ -18,6 +17,7 @@
#include "media/mojo/services/mojo_media_drm_storage.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -45,7 +45,7 @@ void CreateOriginId(MediaDrmStorageImpl::OriginIdObtainedCB callback) {
void CreateEmptyOriginId(MediaDrmStorageImpl::OriginIdObtainedCB callback) {
// |callback| has to fail in order to check if empty origin ID allowed.
- std::move(callback).Run(false, base::nullopt);
+ std::move(callback).Run(false, absl::nullopt);
}
void CreateOriginIdAsync(MediaDrmStorageImpl::OriginIdObtainedCB callback) {
@@ -70,7 +70,7 @@ class MediaDrmStorageImplTest : public content::RenderViewHostTestHarness {
void SetUp() override {
RenderViewHostTestHarness::SetUp();
- pref_service_.reset(new TestingPrefServiceSimple());
+ pref_service_ = std::make_unique<TestingPrefServiceSimple>();
PrefRegistrySimple* registry = pref_service_->registry();
MediaDrmStorageImpl::RegisterProfilePrefs(registry);
diff --git a/chromium/components/cdm/common/cdm_manifest.cc b/chromium/components/cdm/common/cdm_manifest.cc
index b8e801d2685..de31fce5500 100644
--- a/chromium/components/cdm/common/cdm_manifest.cc
+++ b/chromium/components/cdm/common/cdm_manifest.cc
@@ -23,6 +23,8 @@
#include "media/base/content_decryption_module.h"
#include "media/base/decrypt_config.h"
#include "media/base/video_codecs.h"
+#include "media/cdm/cdm_capability.h"
+#include "media/cdm/supported_audio_codecs.h"
#include "media/cdm/supported_cdm_versions.h"
#include "media/media_buildflags.h"
@@ -118,11 +120,87 @@ bool CheckForCompatibleVersion(const base::Value& manifest,
return false;
}
+// Returns true and updates |encryption_schemes| if the appropriate manifest
+// entry is valid. Returns false and does not modify |encryption_schemes| if the
+// manifest entry is incorrectly formatted. It is assumed that all CDMs support
+// 'cenc', so if the manifest entry is missing, the result will indicate support
+// for 'cenc' only. Incorrect types in the manifest entry will log the error and
+// fail. Unrecognized values will be reported but otherwise ignored.
+bool GetEncryptionSchemes(
+ const base::Value& manifest,
+ base::flat_set<media::EncryptionScheme>* encryption_schemes) {
+ DCHECK(manifest.is_dict());
+ DCHECK(encryption_schemes);
+
+ const base::Value* value =
+ manifest.FindKey(kCdmSupportedEncryptionSchemesName);
+ if (!value) {
+ // No manifest entry found, so assume only 'cenc' supported for backwards
+ // compatibility.
+ encryption_schemes->insert(media::EncryptionScheme::kCenc);
+ return true;
+ }
+
+ if (!value->is_list()) {
+ DLOG(ERROR) << "CDM manifest entry " << kCdmSupportedEncryptionSchemesName
+ << " is not a list.";
+ return false;
+ }
+
+ base::flat_set<media::EncryptionScheme> result;
+ for (const auto& item : value->GetList()) {
+ if (!item.is_string()) {
+ DLOG(ERROR) << "Unrecognized item type in CDM manifest entry "
+ << kCdmSupportedEncryptionSchemesName;
+ return false;
+ }
+
+ const std::string& scheme = item.GetString();
+ if (scheme == kCdmSupportedEncryptionSchemeCenc) {
+ result.insert(media::EncryptionScheme::kCenc);
+ } else if (scheme == kCdmSupportedEncryptionSchemeCbcs) {
+ result.insert(media::EncryptionScheme::kCbcs);
+ } else {
+ DLOG(WARNING) << "Unrecognized encryption scheme '" << scheme
+ << "' in CDM manifest entry "
+ << kCdmSupportedEncryptionSchemesName;
+ }
+ }
+
+ // As the manifest entry exists, it must specify at least one valid value.
+ if (result.empty())
+ return false;
+
+ encryption_schemes->swap(result);
+ return true;
+}
+
+// Returns true and updates |audio_codecs| with the full set of audio
+// codecs that support decryption.
+bool GetAudioCodecs(const base::Value& manifest,
+ std::vector<media::AudioCodec>* audio_codecs) {
+ DCHECK(manifest.is_dict());
+ DCHECK(audio_codecs);
+
+ // Note that desktop CDMs only support decryption of audio content,
+ // no decoding. Manifest does not contain any audio codecs, so return
+ // the standard set of audio codecs supported only if there is at least
+ // one encryption scheme specified.
+ base::flat_set<media::EncryptionScheme> encryption_schemes;
+ if (!GetEncryptionSchemes(manifest, &encryption_schemes)) {
+ return false;
+ }
+
+ DCHECK(!encryption_schemes.empty());
+ *audio_codecs = media::GetCdmSupportedAudioCodecs();
+ return true;
+}
+
// Returns true and updates |video_codecs| if the appropriate manifest entry is
// valid. Returns false and does not modify |video_codecs| if the manifest entry
// is incorrectly formatted.
-bool GetCodecs(const base::Value& manifest,
- std::vector<media::VideoCodec>* video_codecs) {
+bool GetVideoCodecs(const base::Value& manifest,
+ std::vector<media::VideoCodec>* video_codecs) {
DCHECK(manifest.is_dict());
DCHECK(video_codecs);
@@ -191,61 +269,6 @@ bool GetSessionTypes(const base::Value& manifest,
return true;
}
-// Returns true and updates |encryption_schemes| if the appropriate manifest
-// entry is valid. Returns false and does not modify |encryption_schemes| if the
-// manifest entry is incorrectly formatted. It is assumed that all CDMs support
-// 'cenc', so if the manifest entry is missing, the result will indicate support
-// for 'cenc' only. Incorrect types in the manifest entry will log the error and
-// fail. Unrecognized values will be reported but otherwise ignored.
-bool GetEncryptionSchemes(
- const base::Value& manifest,
- base::flat_set<media::EncryptionScheme>* encryption_schemes) {
- DCHECK(manifest.is_dict());
- DCHECK(encryption_schemes);
-
- const base::Value* value =
- manifest.FindKey(kCdmSupportedEncryptionSchemesName);
- if (!value) {
- // No manifest entry found, so assume only 'cenc' supported for backwards
- // compatibility.
- encryption_schemes->insert(media::EncryptionScheme::kCenc);
- return true;
- }
-
- if (!value->is_list()) {
- DLOG(ERROR) << "CDM manifest entry " << kCdmSupportedEncryptionSchemesName
- << " is not a list.";
- return false;
- }
-
- base::flat_set<media::EncryptionScheme> result;
- for (const auto& item : value->GetList()) {
- if (!item.is_string()) {
- DLOG(ERROR) << "Unrecognized item type in CDM manifest entry "
- << kCdmSupportedEncryptionSchemesName;
- return false;
- }
-
- const std::string& scheme = item.GetString();
- if (scheme == kCdmSupportedEncryptionSchemeCenc) {
- result.insert(media::EncryptionScheme::kCenc);
- } else if (scheme == kCdmSupportedEncryptionSchemeCbcs) {
- result.insert(media::EncryptionScheme::kCbcs);
- } else {
- DLOG(WARNING) << "Unrecognized encryption scheme '" << scheme
- << "' in CDM manifest entry "
- << kCdmSupportedEncryptionSchemesName;
- }
- }
-
- // As the manifest entry exists, it must specify at least one valid value.
- if (result.empty())
- return false;
-
- encryption_schemes->swap(result);
- return true;
-}
-
bool GetVersion(const base::Value& manifest, base::Version* version) {
DCHECK(manifest.is_dict());
auto* version_string = manifest.FindStringKey(kCdmVersion);
@@ -278,17 +301,18 @@ bool IsCdmManifestCompatibleWithChrome(const base::Value& manifest) {
}
bool ParseCdmManifest(const base::Value& manifest,
- content::CdmCapability* capability) {
+ media::CdmCapability* capability) {
DCHECK(manifest.is_dict());
- return GetCodecs(manifest, &capability->video_codecs) &&
+ return GetAudioCodecs(manifest, &capability->audio_codecs) &&
+ GetVideoCodecs(manifest, &capability->video_codecs) &&
GetEncryptionSchemes(manifest, &capability->encryption_schemes) &&
GetSessionTypes(manifest, &capability->session_types);
}
bool ParseCdmManifestFromPath(const base::FilePath& manifest_path,
base::Version* version,
- content::CdmCapability* capability) {
+ media::CdmCapability* capability) {
JSONFileValueDeserializer deserializer(manifest_path);
int error_code;
std::string error_message;
diff --git a/chromium/components/cdm/common/cdm_manifest.h b/chromium/components/cdm/common/cdm_manifest.h
index 8e63c04c87a..4e1b2c71f28 100644
--- a/chromium/components/cdm/common/cdm_manifest.h
+++ b/chromium/components/cdm/common/cdm_manifest.h
@@ -11,7 +11,7 @@ class Value;
class Version;
} // namespace base
-namespace content {
+namespace media {
struct CdmCapability;
}
@@ -26,7 +26,7 @@ bool IsCdmManifestCompatibleWithChrome(const base::Value& manifest);
// Returns true on success, false if there are errors in the manifest.
// If this method returns false, |capability| may or may not be updated.
bool ParseCdmManifest(const base::Value& manifest,
- content::CdmCapability* capability);
+ media::CdmCapability* capability);
// Reads the file |manifest_path| which is assumed to be a CDM manifest and
// extracts the necessary information from it to update |version| and
@@ -37,6 +37,6 @@ bool ParseCdmManifest(const base::Value& manifest,
// |version| and |capability| may or may not be updated.
bool ParseCdmManifestFromPath(const base::FilePath& manifest_path,
base::Version* version,
- content::CdmCapability* capability);
+ media::CdmCapability* capability);
-#endif // CHROME_COMMON_MEDIA_CDM_MANIFEST_H_
+#endif // COMPONENTS_CDM_COMMON_CDM_MANIFEST_H_
diff --git a/chromium/components/cdm/common/cdm_manifest_unittest.cc b/chromium/components/cdm/common/cdm_manifest_unittest.cc
index 461513c0cf3..0584a8a672e 100644
--- a/chromium/components/cdm/common/cdm_manifest_unittest.cc
+++ b/chromium/components/cdm/common/cdm_manifest_unittest.cc
@@ -20,10 +20,11 @@
#include "base/version.h"
#include "content/public/common/cdm_info.h"
#include "media/cdm/api/content_decryption_module.h"
+#include "media/cdm/cdm_capability.h"
#include "media/cdm/supported_cdm_versions.h"
#include "testing/gtest/include/gtest/gtest.h"
-using content::CdmCapability;
+using media::CdmCapability;
namespace {
@@ -95,8 +96,9 @@ base::Value DefaultManifest() {
return dict;
}
-void CheckCodecs(const std::vector<media::VideoCodec>& actual,
- const std::vector<media::VideoCodec>& expected) {
+template <class Codec>
+void CheckCodecs(const std::vector<Codec>& actual,
+ const std::vector<Codec>& expected) {
EXPECT_EQ(expected.size(), actual.size());
for (const auto& codec : expected) {
EXPECT_TRUE(base::Contains(actual, codec));
@@ -184,6 +186,13 @@ TEST(CdmManifestTest, ValidManifest) {
CheckCodecs(capability.video_codecs,
{media::VideoCodec::kCodecVP8, media::VideoCodec::kCodecVP9,
media::VideoCodec::kCodecAV1});
+ CheckCodecs(capability.audio_codecs, {
+ media::AudioCodec::kCodecOpus, media::AudioCodec::kCodecVorbis,
+ media::AudioCodec::kCodecFLAC,
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+ media::AudioCodec::kCodecAAC,
+#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
+ });
CheckEncryptionSchemes(
capability.encryption_schemes,
{media::EncryptionScheme::kCenc, media::EncryptionScheme::kCbcs});
@@ -197,6 +206,13 @@ TEST(CdmManifestTest, EmptyManifest) {
CdmCapability capability;
EXPECT_TRUE(ParseCdmManifest(manifest, &capability));
CheckCodecs(capability.video_codecs, {});
+ CheckCodecs(capability.audio_codecs, {
+ media::AudioCodec::kCodecOpus, media::AudioCodec::kCodecVorbis,
+ media::AudioCodec::kCodecFLAC,
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+ media::AudioCodec::kCodecAAC,
+#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
+ });
CheckEncryptionSchemes(capability.encryption_schemes,
{media::EncryptionScheme::kCenc});
CheckSessionTypes(capability.session_types,
diff --git a/chromium/components/cdm/common/cdm_messages_android.h b/chromium/components/cdm/common/cdm_messages_android.h
index 27f4b5082f6..80c848b3d7d 100644
--- a/chromium/components/cdm/common/cdm_messages_android.h
+++ b/chromium/components/cdm/common/cdm_messages_android.h
@@ -9,6 +9,7 @@
#include <vector>
#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
#include "media/base/eme_constants.h"
#define IPC_MESSAGE_START EncryptedMediaMsgStart
diff --git a/chromium/components/cdm/renderer/android_key_systems.cc b/chromium/components/cdm/renderer/android_key_systems.cc
index 18e3fdca3d6..a6d72f35b70 100644
--- a/chromium/components/cdm/renderer/android_key_systems.cc
+++ b/chromium/components/cdm/renderer/android_key_systems.cc
@@ -73,7 +73,13 @@ class AndroidPlatformKeySystemProperties : public KeySystemProperties {
EmeConfigRule GetRobustnessConfigRule(
media::EmeMediaType media_type,
- const std::string& requested_robustness) const override {
+ const std::string& requested_robustness,
+ const bool* /*hw_secure_requirement*/) const override {
+ // `hw_secure_requirement` is ignored here because it's a temporary solution
+ // until a larger refactoring of the key system logic is done. It also does
+ // not need to account for it here because if it does introduce an
+ // incompatibility at this point, it will still be caught by the rule logic
+ // in KeySystemConfigSelector: crbug.com/1204284
return requested_robustness.empty() ? EmeConfigRule::SUPPORTED
: EmeConfigRule::NOT_SUPPORTED;
}
diff --git a/chromium/components/cdm/renderer/external_clear_key_key_system_properties.cc b/chromium/components/cdm/renderer/external_clear_key_key_system_properties.cc
index f0ff61f11f6..231036f3b29 100644
--- a/chromium/components/cdm/renderer/external_clear_key_key_system_properties.cc
+++ b/chromium/components/cdm/renderer/external_clear_key_key_system_properties.cc
@@ -53,7 +53,8 @@ media::SupportedCodecs ExternalClearKeyProperties::GetSupportedCodecs() const {
media::EmeConfigRule ExternalClearKeyProperties::GetRobustnessConfigRule(
media::EmeMediaType media_type,
- const std::string& requested_robustness) const {
+ const std::string& requested_robustness,
+ const bool* /*hw_secure_requirement*/) const {
return requested_robustness.empty() ? media::EmeConfigRule::SUPPORTED
: media::EmeConfigRule::NOT_SUPPORTED;
}
diff --git a/chromium/components/cdm/renderer/external_clear_key_key_system_properties.h b/chromium/components/cdm/renderer/external_clear_key_key_system_properties.h
index 328400f8687..81f8dab797e 100644
--- a/chromium/components/cdm/renderer/external_clear_key_key_system_properties.h
+++ b/chromium/components/cdm/renderer/external_clear_key_key_system_properties.h
@@ -27,7 +27,8 @@ class ExternalClearKeyProperties : public media::KeySystemProperties {
media::SupportedCodecs GetSupportedCodecs() const override;
media::EmeConfigRule GetRobustnessConfigRule(
media::EmeMediaType media_type,
- const std::string& requested_robustness) const override;
+ const std::string& requested_robustness,
+ const bool* hw_secure_requirement) const override;
media::EmeSessionTypeSupport GetPersistentLicenseSessionSupport()
const override;
media::EmeFeatureSupport GetPersistentStateSupport() const override;
diff --git a/chromium/components/cdm/renderer/widevine_key_system_properties.cc b/chromium/components/cdm/renderer/widevine_key_system_properties.cc
index 98ec5fa7dfa..bf3da04dc37 100644
--- a/chromium/components/cdm/renderer/widevine_key_system_properties.cc
+++ b/chromium/components/cdm/renderer/widevine_key_system_properties.cc
@@ -4,7 +4,9 @@
#include "components/cdm/renderer/widevine_key_system_properties.h"
+#include "base/compiler_specific.h"
#include "base/feature_list.h"
+#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "media/base/media_switches.h"
#include "media/media_buildflags.h"
@@ -110,7 +112,8 @@ SupportedCodecs WidevineKeySystemProperties::GetSupportedHwSecureCodecs()
EmeConfigRule WidevineKeySystemProperties::GetRobustnessConfigRule(
EmeMediaType media_type,
- const std::string& requested_robustness) const {
+ const std::string& requested_robustness,
+ const bool* hw_secure_requirement) const {
Robustness robustness = ConvertRobustness(requested_robustness);
if (robustness == Robustness::INVALID)
return EmeConfigRule::NOT_SUPPORTED;
@@ -136,10 +139,12 @@ EmeConfigRule WidevineKeySystemProperties::GetRobustnessConfigRule(
return EmeConfigRule::NOT_SUPPORTED;
}
+ bool hw_secure_codecs_required =
+ hw_secure_requirement && *hw_secure_requirement;
#if BUILDFLAG(IS_CHROMEOS_ASH)
// Hardware security requires HWDRM or remote attestation, both of these
// require an identifier.
- if (robustness >= Robustness::HW_SECURE_CRYPTO)
+ if (robustness >= Robustness::HW_SECURE_CRYPTO || hw_secure_codecs_required)
#if BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA)
return EmeConfigRule::IDENTIFIER_AND_HW_SECURE_CODECS_REQUIRED;
#else
@@ -157,18 +162,22 @@ EmeConfigRule WidevineKeySystemProperties::GetRobustnessConfigRule(
}
#elif defined(OS_ANDROID)
// On Android, require hardware secure codecs for SW_SECURE_DECODE and above.
- if (robustness >= Robustness::SW_SECURE_DECODE) {
+ if (robustness >= Robustness::SW_SECURE_DECODE || hw_secure_codecs_required)
return EmeConfigRule::HW_SECURE_CODECS_REQUIRED;
- }
+#elif defined(OS_WIN)
+ // On Windows, hardware security uses MediaFoundation-based CDM which requires
+ // identifier and persistent state.
+ if (robustness >= Robustness::HW_SECURE_CRYPTO || hw_secure_codecs_required)
+ return EmeConfigRule::IDENTIFIER_PERSISTENCE_AND_HW_SECURE_CODECS_REQUIRED;
#else
- // On Linux/Mac/Win, require hardware secure codecs for HW_SECURE_CRYPTO and
+ // On other platforms, require hardware secure codecs for HW_SECURE_CRYPTO and
// above.
- if (robustness >= Robustness::HW_SECURE_CRYPTO) {
+ if (robustness >= Robustness::HW_SECURE_CRYPTO)
return EmeConfigRule::HW_SECURE_CODECS_REQUIRED;
- }
+
+ ALLOW_UNUSED_LOCAL(hw_secure_codecs_required);
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
- // TODO(crbug.com/848532): Handle HW_SECURE* levels for Windows.
return EmeConfigRule::SUPPORTED;
}
diff --git a/chromium/components/cdm/renderer/widevine_key_system_properties.h b/chromium/components/cdm/renderer/widevine_key_system_properties.h
index f6e53c09480..6eed985b1f4 100644
--- a/chromium/components/cdm/renderer/widevine_key_system_properties.h
+++ b/chromium/components/cdm/renderer/widevine_key_system_properties.h
@@ -49,7 +49,8 @@ class WidevineKeySystemProperties : public media::KeySystemProperties {
media::SupportedCodecs GetSupportedHwSecureCodecs() const override;
media::EmeConfigRule GetRobustnessConfigRule(
media::EmeMediaType media_type,
- const std::string& requested_robustness) const override;
+ const std::string& requested_robustness,
+ const bool* hw_secure_requirement) const override;
media::EmeSessionTypeSupport GetPersistentLicenseSessionSupport()
const override;
media::EmeFeatureSupport GetPersistentStateSupport() const override;
diff --git a/chromium/components/certificate_transparency/data/log_list.json b/chromium/components/certificate_transparency/data/log_list.json
index fc99e839edc..b154b677753 100644
--- a/chromium/components/certificate_transparency/data/log_list.json
+++ b/chromium/components/certificate_transparency/data/log_list.json
@@ -7,22 +7,6 @@
],
"logs": [
{
- "description": "Google 'Argon2020' log",
- "log_id": "sh4FzIuizYogTodm+Su5iiUgZ2va+nDnsklTLe+LkF4=",
- "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6Tx2p1yKY4015NyIYvdrk36es0uAc1zA4PQ+TGRY+3ZjUTIYY9Wyu+3q/147JG4vNVKLtDWarZwVqGkg6lAYzA==",
- "url": "https://ct.googleapis.com/logs/argon2020/",
- "mmd": 86400,
- "state": {
- "usable": {
- "timestamp": "2018-06-15T02:30:13Z"
- }
- },
- "temporal_interval": {
- "start_inclusive": "2020-01-01T00:00:00Z",
- "end_exclusive": "2021-01-01T00:00:00Z"
- }
- },
- {
"description": "Google 'Argon2021' log",
"log_id": "9lyUL9F3MCIUVBgIMJRWjuNNExkzv98MLyALzE7xZOM=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETeBmZOrzZKo4xYktx9gI2chEce3cw/tbr5xkoQlmhB18aKfsxD+MnILgGNl0FOm0eYGilFVi85wLRIOhK8lxKw==",
@@ -71,22 +55,6 @@
}
},
{
- "description": "Google 'Xenon2020' log",
- "log_id": "B7dcG+V9aP/xsMYdIxXHuuZXfFeUt2ruvGE6GmnTohw=",
- "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZU75VqjyzSTgFZKAnWg1QeYfFFIRZTMK7q3kWWZsmHhQdrBYnHRZ3OA4kUeUx0JN+xX+dSgt1ruqUhhl7jOvmw==",
- "url": "https://ct.googleapis.com/logs/xenon2020/",
- "mmd": 86400,
- "state": {
- "usable": {
- "timestamp": "2019-06-17T21:23:01Z"
- }
- },
- "temporal_interval": {
- "start_inclusive": "2020-01-01T00:00:00Z",
- "end_exclusive": "2021-01-01T00:00:00Z"
- }
- },
- {
"description": "Google 'Xenon2021' log",
"log_id": "fT7y+I//iFVoJMLAyp5SiXkrxQ54CX8uapdomX4i8Nc=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAER+1MInu8Q39BwDZ5Rp9TwXhwm3ktvgJzpk/r7dDgGk7ZacMm3ljfcoIvP1E72T8jvyLT1bvdapylajZcTH6W5g==",
@@ -212,22 +180,6 @@
],
"logs": [
{
- "description": "Cloudflare 'Nimbus2020' Log",
- "log_id": "Xqdz+d9WwOe1Nkh90EngMnqRmgyEoRIShBh1loFxRVg=",
- "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01EAhx4o0zPQrXTcYjgCt4MVFsT0Pwjzb1RwrM0lhWDlxAYPP6/gyMCXNkOn/7KFsjL7rwk78tHMpY8rXn8AYg==",
- "url": "https://ct.cloudflare.com/logs/nimbus2020/",
- "mmd": 86400,
- "state": {
- "usable": {
- "timestamp": "2018-06-15T02:30:13Z"
- }
- },
- "temporal_interval": {
- "start_inclusive": "2020-01-01T00:00:00Z",
- "end_exclusive": "2021-01-01T00:00:00Z"
- }
- },
- {
"description": "Cloudflare 'Nimbus2021' Log",
"log_id": "RJRlLrDuzq/EQAfYqP4owNrmgr7YyzG1P9MzlrW2gag=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExpon7ipsqehIeU1bmpog9TFo4Pk8+9oN8OYHl1Q2JGVXnkVFnuuvPgSo2Ep+6vLffNLcmEbxOucz03sFiematg==",
@@ -308,22 +260,6 @@
}
},
{
- "description": "DigiCert Yeti2020 Log",
- "log_id": "8JWkWfIA0YJAEC0vk4iOrUv+HUfjmeHQNKawqKqOsnM=",
- "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEURAG+Zo0ac3n37ifZKUhBFEV6jfcCzGIRz3tsq8Ca9BP/5XUHy6ZiqsPaAEbVM0uI3Tm9U24RVBHR9JxDElPmg==",
- "url": "https://yeti2020.ct.digicert.com/log/",
- "mmd": 86400,
- "state": {
- "usable": {
- "timestamp": "2018-08-24T00:53:07Z"
- }
- },
- "temporal_interval": {
- "start_inclusive": "2020-01-01T00:00:00Z",
- "end_exclusive": "2021-01-01T00:00:00Z"
- }
- },
- {
"description": "DigiCert Yeti2021 Log",
"log_id": "XNxDkv7mq0VEsV6a1FbmEDf71fpH3KFzlLJe5vbHDso=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6J4EbcpIAl1+AkSRsbhoY5oRTj3VoFfaf1DlQkfi7Rbe/HcjfVtrwN8jaC+tQDGjF+dqvKhWJAQ6Q6ev6q9Mew==",
@@ -372,22 +308,6 @@
}
},
{
- "description": "DigiCert Nessie2020 Log",
- "log_id": "xlKg7EjOs/yrFwmSxDqHQTMJ6ABlomJSQBujNioXxWU=",
- "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4hHIyMVIrR9oShgbQMYEk8WX1lmkfFKB448Gn93KbsZnnwljDHY6MQqEnWfKGgMOq0gh3QK48c5ZB3UKSIFZ4g==",
- "url": "https://nessie2020.ct.digicert.com/log/",
- "mmd": 86400,
- "state": {
- "usable": {
- "timestamp": "2019-05-09T22:11:02Z"
- }
- },
- "temporal_interval": {
- "start_inclusive": "2020-01-01T00:00:00Z",
- "end_exclusive": "2021-01-01T00:00:00Z"
- }
- },
- {
"description": "DigiCert Nessie2021 Log",
"log_id": "7sCV7o1yZA+S48O5G8cSo2lqCXtLahoUOOZHssvtxfk=",
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9o7AiwrbGBIX6Lnc47I6OfLMdZnRzKoP5u072nBi6vpIOEooktTi1gNwlRPzGC2ySGfuc1xLDeaA/wSFGgpYFg==",
@@ -632,22 +552,6 @@
],
"logs": [
{
- "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": {
- "usable": {
- "timestamp": "2020-01-27T18:18:26Z"
- }
- },
- "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==",
@@ -704,19 +608,19 @@
],
"logs": [
{
- "description": "Trust Asia Log2020",
- "log_id": "pZWUO1NwvukG4AUNH7W7xqQOZfJlroUsdjY/rbIzNu0=",
- "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbsWC7ukn2WYOMxTAcqL8gMRZEQTZF9+Ho1MB9WLhHIaCHpHsJSx0DjJdVILW9mtM5xZtWywMWMQ9/R3OBgQEXQ==",
- "url": "https://ct.trustasia.com/log2020/",
+ "description": "Trust Asia CT2021",
+ "log_id": "qNxS9j1rJCXlMeN89ORKcU8UKiCAOw0E0uLuBmR5SiM=",
+ "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESdAfC+h1SZNsSARs188n/dCiNYjGSgkT7avLYe1mmXJzzHhsmxmAorHtOzhDkFgaCSCrUPrXdunK946eyIeSmA==",
+ "url": "https://ct2021.trustasia.com/log2021/",
"mmd": 86400,
"state": {
- "retired": {
- "timestamp": "2020-12-01T00:00:00Z"
+ "qualified": {
+ "timestamp": "2021-05-11T07:00:00Z"
}
},
"temporal_interval": {
- "start_inclusive": "2020-01-01T00:00:00Z",
- "end_exclusive": "2021-01-01T00:00:00Z"
+ "start_inclusive": "2021-01-01T00:00:00Z",
+ "end_exclusive": "2022-01-01T00:00:00Z"
}
},
{
diff --git a/chromium/components/chrome_cleaner/DIR_METADATA b/chromium/components/chrome_cleaner/DIR_METADATA
index efa11fb9132..c5f6b73590f 100644
--- a/chromium/components/chrome_cleaner/DIR_METADATA
+++ b/chromium/components/chrome_cleaner/DIR_METADATA
@@ -1,5 +1,5 @@
monorail {
- component: "UI>Browser>Preferences>Protector"
+ component: "Services>Safebrowsing>ChromeCleanup"
}
team_email: "security-dev@chromium.org"
diff --git a/chromium/components/chrome_cleaner/public/proto/DIR_METADATA b/chromium/components/chrome_cleaner/public/proto/DIR_METADATA
deleted file mode 100644
index efa11fb9132..00000000000
--- a/chromium/components/chrome_cleaner/public/proto/DIR_METADATA
+++ /dev/null
@@ -1,5 +0,0 @@
-monorail {
- component: "UI>Browser>Preferences>Protector"
-}
-
-team_email: "security-dev@chromium.org"
diff --git a/chromium/components/chromeos_camera/dmabuf_utils.cc b/chromium/components/chromeos_camera/dmabuf_utils.cc
index 3c63e9f7577..0fa4d72c805 100644
--- a/chromium/components/chromeos_camera/dmabuf_utils.cc
+++ b/chromium/components/chromeos_camera/dmabuf_utils.cc
@@ -49,7 +49,7 @@ scoped_refptr<media::VideoFrame> ConstructVideoFrame(
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 =
+ const absl::optional<media::VideoFrameLayout> layout =
media::VideoFrameLayout::CreateWithPlanes(pixel_format, coded_size,
std::move(planes));
if (!layout) {
diff --git a/chromium/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc b/chromium/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc
index e425ff6ff5b..bee4fef3b20 100644
--- a/chromium/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc
+++ b/chromium/components/chromeos_camera/jpeg_encode_accelerator_unittest.cc
@@ -662,7 +662,7 @@ void JpegClient::StartEncodeDmaBuf(int32_t bitstream_buffer_id) {
auto input_buffer = gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
test_image->visible_size, gfx::BufferFormat::YUV_420_BIPLANAR,
gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE,
- gpu::kNullSurfaceHandle);
+ gpu::kNullSurfaceHandle, nullptr);
ASSERT_EQ(input_buffer->Map(), true);
uint8_t* plane_buf[2] = {static_cast<uint8_t*>(input_buffer->memory(0)),
@@ -682,7 +682,8 @@ void JpegClient::StartEncodeDmaBuf(int32_t bitstream_buffer_id) {
auto output_buffer = gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
gfx::Size(kJpegMaxSize, 1), gfx::BufferFormat::R_8,
- gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE, gpu::kNullSurfaceHandle);
+ gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE, gpu::kNullSurfaceHandle,
+ nullptr);
ASSERT_EQ(output_buffer->Map(), true);
hw_out_frame_ = GetVideoFrameFromGpuMemoryBuffer(
output_buffer.get(), test_image->visible_size, media::PIXEL_FORMAT_MJPEG);
diff --git a/chromium/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc b/chromium/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
index 1cf76a39d06..a8c569dd9fd 100644
--- a/chromium/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
+++ b/chromium/components/chromeos_camera/mjpeg_decode_accelerator_unittest.cc
@@ -8,6 +8,7 @@
#include <unistd.h>
#include <memory>
+#include <numeric>
#include <string>
#include <utility>
#include <vector>
@@ -17,13 +18,13 @@
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
+#include "base/json/json_writer.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"
@@ -33,6 +34,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "components/chromeos_camera/gpu_mjpeg_decode_accelerator_factory.h"
#include "components/chromeos_camera/mjpeg_decode_accelerator.h"
@@ -47,6 +49,7 @@
#include "media/parsers/jpeg_parser.h"
#include "mojo/core/embedder/embedder.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/libyuv/include/libyuv.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/codec/jpeg_codec.h"
@@ -162,15 +165,19 @@ class MjpegDecodeAcceleratorTestEnvironment : public ::testing::Environment {
MjpegDecodeAcceleratorTestEnvironment(
const base::FilePath::CharType* jpeg_filenames,
const base::FilePath::CharType* test_data_path,
+ const base::FilePath::CharType* perf_output_path,
int perf_decode_times)
: perf_decode_times_(perf_decode_times ? perf_decode_times
: kDefaultPerfDecodeTimes),
user_jpeg_filenames_(jpeg_filenames ? jpeg_filenames
: kDefaultJpegFilename),
- test_data_path_(test_data_path) {}
+ test_data_path_(test_data_path),
+ perf_output_path_(perf_output_path) {}
void SetUp() override;
+ void TearDown() override;
+
// Resolve the specified file path. The file path can be either an absolute
// path, relative to the current directory, or relative to the test data path.
// This is either a custom test data path provided by --test_data_path, or the
@@ -213,6 +220,8 @@ class MjpegDecodeAcceleratorTestEnvironment : public ::testing::Environment {
// CreateDmaBufVideoFrame().
std::vector<media::VideoPixelFormat> GetSupportedDmaBufFormats();
+ void AddMetric(const std::string& name, const base::TimeDelta& time);
+
// Used for InputSizeChange test case. The image size should be smaller than
// |kDefaultJpegFilename|.
std::unique_ptr<ParsedJpegImage> image_data_1280x720_black_;
@@ -235,6 +244,8 @@ class MjpegDecodeAcceleratorTestEnvironment : public ::testing::Environment {
private:
const base::FilePath::CharType* user_jpeg_filenames_;
const base::FilePath::CharType* test_data_path_;
+ const base::FilePath::CharType* perf_output_path_;
+ base::Value metrics_;
std::unique_ptr<media::LocalGpuMemoryBufferManager>
gpu_memory_buffer_manager_;
@@ -267,6 +278,18 @@ void MjpegDecodeAcceleratorTestEnvironment::SetUp() {
gpu_memory_buffer_manager_ =
std::make_unique<media::LocalGpuMemoryBufferManager>();
+
+ metrics_ = base::Value(base::Value::Type::DICTIONARY);
+}
+
+void MjpegDecodeAcceleratorTestEnvironment::TearDown() {
+ // Write recorded metrics to file in JSON format.
+ if (perf_output_path_ != nullptr) {
+ std::string json;
+ ASSERT_TRUE(base::JSONWriter::WriteWithOptions(
+ metrics_, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json));
+ ASSERT_TRUE(base::WriteFile(base::FilePath(perf_output_path_), json));
+ }
}
scoped_refptr<media::VideoFrame>
@@ -311,7 +334,7 @@ MjpegDecodeAcceleratorTestEnvironment::CreateDmaBufVideoFrame(
DCHECK(gpu_memory_buffer_manager_);
// Create a GpuMemoryBuffer and get a NativePixmapHandle from it.
- const base::Optional<gfx::BufferFormat> gfx_format =
+ const absl::optional<gfx::BufferFormat> gfx_format =
media::VideoPixelFormatToGfxBufferFormat(format);
if (!gfx_format) {
LOG(ERROR) << "Unsupported pixel format: " << format;
@@ -319,7 +342,8 @@ MjpegDecodeAcceleratorTestEnvironment::CreateDmaBufVideoFrame(
}
std::unique_ptr<gfx::GpuMemoryBuffer> gmb =
gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
- coded_size, *gfx_format, kBufferUsage, gpu::kNullSurfaceHandle);
+ coded_size, *gfx_format, kBufferUsage, gpu::kNullSurfaceHandle,
+ nullptr);
if (!gmb) {
LOG(ERROR) << "Failed to create GpuMemoryBuffer";
return nullptr;
@@ -358,7 +382,7 @@ MjpegDecodeAcceleratorTestEnvironment::CreateDmaBufVideoFrame(
base::checked_cast<size_t>(plane.size));
dmabuf_fds.push_back(std::move(plane.fd));
}
- const base::Optional<media::VideoFrameLayout> layout =
+ const absl::optional<media::VideoFrameLayout> layout =
media::VideoFrameLayout::CreateWithPlanes(format, coded_size,
std::move(planes));
if (!layout) {
@@ -413,7 +437,7 @@ base::ScopedFD MjpegDecodeAcceleratorTestEnvironment::CreateDmaBufFd(
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);
+ kBufferUsage, gpu::kNullSurfaceHandle, nullptr);
if (!gmb) {
LOG(ERROR) << "Failed to create GpuMemoryBuffer";
return base::ScopedFD();
@@ -453,7 +477,7 @@ MjpegDecodeAcceleratorTestEnvironment::GetSupportedDmaBufFormats() {
};
std::vector<media::VideoPixelFormat> supported_formats;
for (const media::VideoPixelFormat format : kPreferredFormats) {
- const base::Optional<gfx::BufferFormat> gfx_format =
+ const absl::optional<gfx::BufferFormat> gfx_format =
media::VideoPixelFormatToGfxBufferFormat(format);
if (gfx_format && gpu_memory_buffer_manager_->IsFormatAndUsageSupported(
*gfx_format, kBufferUsage))
@@ -462,6 +486,12 @@ MjpegDecodeAcceleratorTestEnvironment::GetSupportedDmaBufFormats() {
return supported_formats;
}
+void MjpegDecodeAcceleratorTestEnvironment::AddMetric(
+ const std::string& name,
+ const base::TimeDelta& time) {
+ metrics_.SetDoubleKey(name, time.InMillisecondsF());
+}
+
enum ClientState {
CS_CREATED,
CS_INITIALIZED,
@@ -469,19 +499,26 @@ enum ClientState {
CS_ERROR,
};
+struct PerfMetrics {
+ size_t num_frames_decoded;
+ base::TimeDelta total_decode_time;
+ base::TimeDelta total_decode_map_time;
+};
+
class JpegClient : public MjpegDecodeAccelerator::Client {
public:
// JpegClient takes ownership of |note|.
JpegClient(
- const std::vector<ParsedJpegImage*>& test_image_files,
+ const std::vector<const ParsedJpegImage*>& test_image_files,
std::unique_ptr<media::test::ClientStateNotification<ClientState>> note,
bool use_dmabuf,
- bool is_skip);
+ bool skip_result_checking);
~JpegClient() override;
void CreateJpegDecoder();
void StartDecode(int32_t task_id, bool do_prepare_memory);
void PrepareMemory(int32_t task_id);
bool GetSoftwareDecodeResult(int32_t task_id);
+ PerfMetrics GetPerfMetrics() const;
// MjpegDecodeAccelerator::Client implementation.
void VideoFrameReady(int32_t task_id) override;
@@ -509,7 +546,7 @@ class JpegClient : public MjpegDecodeAccelerator::Client {
double GetMeanAbsoluteDifference();
// JpegClient doesn't own |test_image_files_|.
- const std::vector<ParsedJpegImage*>& test_image_files_;
+ const std::vector<const ParsedJpegImage*>& test_image_files_;
ClientState state_;
@@ -520,7 +557,7 @@ class JpegClient : public MjpegDecodeAccelerator::Client {
bool use_dmabuf_;
// Skip JDA decode result. Used for testing performance.
- bool is_skip_;
+ bool skip_result_checking_;
// Input shared memory and mapping.
base::UnsafeSharedMemoryRegion in_shm_;
@@ -540,19 +577,25 @@ class JpegClient : public MjpegDecodeAccelerator::Client {
// |hw_out_frame_| can be accessed.
std::unique_ptr<MjpegDecodeAccelerator> decoder_;
+ // Timers for individual decoding calls indexed by |task_id|.
+ std::map<int32_t, base::ElapsedTimer> timers_;
+ // Recorded performance metrics.
+ std::vector<base::TimeDelta> decode_times_;
+ std::vector<base::TimeDelta> decode_map_times_;
+
DISALLOW_COPY_AND_ASSIGN(JpegClient);
};
JpegClient::JpegClient(
- const std::vector<ParsedJpegImage*>& test_image_files,
+ const std::vector<const ParsedJpegImage*>& test_image_files,
std::unique_ptr<media::test::ClientStateNotification<ClientState>> note,
bool use_dmabuf,
- bool is_skip)
+ bool skip_result_checking)
: test_image_files_(test_image_files),
state_(CS_CREATED),
note_(std::move(note)),
use_dmabuf_(use_dmabuf),
- is_skip_(is_skip) {}
+ skip_result_checking_(skip_result_checking) {}
JpegClient::~JpegClient() {}
@@ -588,27 +631,39 @@ void JpegClient::CreateJpegDecoder() {
}
void JpegClient::VideoFrameReady(int32_t task_id) {
- if (is_skip_) {
- SetState(CS_DECODE_PASS);
- return;
+ const auto timer_iter = timers_.find(task_id);
+ ASSERT_TRUE(timer_iter != timers_.end());
+ base::ElapsedTimer& timer = timer_iter->second;
+ decode_times_.push_back(timer.Elapsed());
+
+ scoped_refptr<media::VideoFrame> mapped_dmabuf_frame;
+ if (use_dmabuf_) {
+ // Map and convert the output frame to I420.
+ mapped_dmabuf_frame = g_env->MapToVideoFrame(
+ hw_out_gmb_.get(), hw_out_dmabuf_frame_->layout(),
+ hw_out_dmabuf_frame_->visible_rect());
+ ASSERT_TRUE(mapped_dmabuf_frame);
+ decode_map_times_.push_back(timer.Elapsed());
}
- if (!GetSoftwareDecodeResult(task_id)) {
- SetState(CS_ERROR);
+ timers_.erase(timer_iter);
+
+ if (skip_result_checking_) {
+ SetState(CS_DECODE_PASS);
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(),
+ hw_out_frame_ = media::test::ConvertVideoFrame(mapped_dmabuf_frame.get(),
media::PIXEL_FORMAT_I420);
ASSERT_TRUE(hw_out_frame_);
}
+ if (!GetSoftwareDecodeResult(task_id)) {
+ SetState(CS_ERROR);
+ return;
+ }
+
if (g_save_to_file) {
SaveToFile(task_id, hw_out_frame_, "_hw");
SaveToFile(task_id, sw_out_frame_, "_sw");
@@ -631,7 +686,7 @@ void JpegClient::NotifyError(int32_t task_id,
}
void JpegClient::PrepareMemory(int32_t task_id) {
- ParsedJpegImage* image_file = test_image_files_[task_id];
+ const ParsedJpegImage* image_file = test_image_files_[task_id];
if (use_dmabuf_) {
in_dmabuf_fd_ = g_env->CreateDmaBufFd(image_file->data_str.data(),
@@ -680,7 +735,7 @@ 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_[task_id];
+ const 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.
@@ -757,11 +812,12 @@ double JpegClient::GetMeanAbsoluteDifference() {
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];
+ const ParsedJpegImage* image_file = test_image_files_[task_id];
if (do_prepare_memory)
PrepareMemory(task_id);
+ timers_[task_id] = base::ElapsedTimer();
if (use_dmabuf_) {
base::ScopedFD duped_in_dmabuf_fd(HANDLE_EINTR(dup(in_dmabuf_fd_.get())));
ASSERT_TRUE(duped_in_dmabuf_fd.is_valid());
@@ -782,7 +838,7 @@ void JpegClient::StartDecode(int32_t task_id, bool do_prepare_memory) {
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];
+ const 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(),
@@ -803,6 +859,17 @@ bool JpegClient::GetSoftwareDecodeResult(int32_t task_id) {
return true;
}
+PerfMetrics JpegClient::GetPerfMetrics() const {
+ return PerfMetrics{
+ .num_frames_decoded = decode_times_.size(),
+ .total_decode_time = std::accumulate(
+ decode_times_.begin(), decode_times_.end(), base::TimeDelta()),
+ .total_decode_map_time =
+ std::accumulate(decode_map_times_.begin(), decode_map_times_.end(),
+ base::TimeDelta()),
+ };
+}
+
// This class holds a |client| that will be deleted on |task_runner|. This is
// necessary because |client->decoder_| expects to be destroyed on the thread on
// which it was created.
@@ -827,20 +894,20 @@ class MjpegDecodeAcceleratorTest : public ::testing::TestWithParam<bool> {
protected:
MjpegDecodeAcceleratorTest() = default;
- void TestDecode(const std::vector<ParsedJpegImage*>& images,
+ void TestDecode(const std::vector<const ParsedJpegImage*>& images,
const std::vector<ClientState>& expected_status,
size_t num_concurrent_decoders = 1);
void PerfDecodeByJDA(int decode_times,
- const std::vector<ParsedJpegImage*>& images);
+ const std::vector<const ParsedJpegImage*>& images);
void PerfDecodeBySW(int decode_times,
- const std::vector<ParsedJpegImage*>& images);
+ const std::vector<const ParsedJpegImage*>& images);
protected:
DISALLOW_COPY_AND_ASSIGN(MjpegDecodeAcceleratorTest);
};
void MjpegDecodeAcceleratorTest::TestDecode(
- const std::vector<ParsedJpegImage*>& images,
+ const std::vector<const ParsedJpegImage*>& images,
const std::vector<ClientState>& expected_status,
size_t num_concurrent_decoders) {
LOG_ASSERT(images.size() >= expected_status.size());
@@ -853,7 +920,7 @@ void MjpegDecodeAcceleratorTest::TestDecode(
auto client = std::make_unique<JpegClient>(
images,
std::make_unique<media::test::ClientStateNotification<ClientState>>(),
- GetParam() /* use_dmabuf */, false /* is_skip */);
+ GetParam() /* use_dmabuf */, false /* skip_result_checking */);
scoped_clients.emplace_back(
new ScopedJpegClient(decoder_thread.task_runner(), std::move(client)));
@@ -882,15 +949,16 @@ void MjpegDecodeAcceleratorTest::TestDecode(
void MjpegDecodeAcceleratorTest::PerfDecodeByJDA(
int decode_times,
- const std::vector<ParsedJpegImage*>& images) {
+ const std::vector<const ParsedJpegImage*>& images) {
LOG_ASSERT(images.size() == 1);
base::Thread decoder_thread("DecoderThread");
ASSERT_TRUE(decoder_thread.Start());
+ const bool use_dmabuf = GetParam();
auto client = std::make_unique<JpegClient>(
images,
std::make_unique<media::test::ClientStateNotification<ClientState>>(),
- GetParam() /* use_dmabuf */, true /* is_skip */);
+ use_dmabuf, true /* skip_result_checking */);
auto scoped_client = std::make_unique<ScopedJpegClient>(
decoder_thread.task_runner(), std::move(client));
@@ -901,7 +969,6 @@ void MjpegDecodeAcceleratorTest::PerfDecodeByJDA(
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,
@@ -909,23 +976,38 @@ void MjpegDecodeAcceleratorTest::PerfDecodeByJDA(
task_id, false /* do_prepare_memory */));
ASSERT_EQ(scoped_client->client()->note()->Wait(), CS_DECODE_PASS);
}
- const base::TimeDelta elapsed_time = timer.Elapsed();
- LOG(INFO) << elapsed_time << " for " << decode_times
- << " iterations (avg: " << elapsed_time / decode_times << ") -- "
- << images[0]->visible_size.ToString() << ", ("
- << images[0]->visible_size.GetArea() << " pixels) "
+
+ const PerfMetrics metrics = scoped_client->client()->GetPerfMetrics();
+ const base::TimeDelta avg_decode_time =
+ metrics.total_decode_time / metrics.num_frames_decoded;
+ LOG(INFO) << "Decode: " << metrics.total_decode_time << " for "
+ << metrics.num_frames_decoded
+ << " iterations (avg: " << avg_decode_time << ")";
+ g_env->AddMetric(
+ use_dmabuf ? "hw_jpeg_decode_latency" : "hw_shm_jpeg_decode_latency",
+ avg_decode_time);
+ if (use_dmabuf) {
+ const base::TimeDelta avg_decode_map_time =
+ metrics.total_decode_map_time / metrics.num_frames_decoded;
+ LOG(INFO) << "Decode + map: " << metrics.total_decode_map_time << " for "
+ << metrics.num_frames_decoded
+ << " iterations (avg: " << avg_decode_map_time << ")";
+ g_env->AddMetric("hw_jpeg_decode_map_latency", avg_decode_map_time);
+ }
+ LOG(INFO) << "-- " << images[0]->visible_size.ToString() << " ("
+ << images[0]->visible_size.GetArea() << " pixels), "
<< images[0]->filename();
}
void MjpegDecodeAcceleratorTest::PerfDecodeBySW(
int decode_times,
- const std::vector<ParsedJpegImage*>& images) {
+ const std::vector<const ParsedJpegImage*>& images) {
LOG_ASSERT(images.size() == 1);
std::unique_ptr<JpegClient> client = std::make_unique<JpegClient>(
images,
std::make_unique<media::test::ClientStateNotification<ClientState>>(),
- false /* use_dmabuf */, true /* is_skip */);
+ false /* use_dmabuf */, true /* skip_result_checking */);
const int32_t task_id = 0;
client->PrepareMemory(task_id);
@@ -933,11 +1015,13 @@ void MjpegDecodeAcceleratorTest::PerfDecodeBySW(
for (int index = 0; index < decode_times; index++)
client->GetSoftwareDecodeResult(task_id);
const base::TimeDelta elapsed_time = timer.Elapsed();
- LOG(INFO) << elapsed_time << " for " << decode_times
- << " iterations (avg: " << elapsed_time / decode_times << ") -- "
- << images[0]->visible_size.ToString() << ", ("
+ const base::TimeDelta avg_decode_time = elapsed_time / decode_times;
+ LOG(INFO) << "Decode: " << elapsed_time << " for " << decode_times
+ << " iterations (avg: " << avg_decode_time << ")";
+ LOG(INFO) << "-- " << images[0]->visible_size.ToString() << ", ("
<< images[0]->visible_size.GetArea() << " pixels) "
<< images[0]->filename();
+ g_env->AddMetric("sw_jpeg_decode_latency", avg_decode_time);
}
// Returns a media::VideoFrame that contains YUV data using 4:2:0 subsampling.
@@ -974,7 +1058,8 @@ scoped_refptr<media::VideoFrame> GetTestDecodedData() {
}
TEST(JpegClientTest, GetMeanAbsoluteDifference) {
- JpegClient client(std::vector<ParsedJpegImage*>(), nullptr, false, false);
+ JpegClient client(std::vector<const ParsedJpegImage*>(), nullptr, false,
+ false);
client.hw_out_frame_ = GetTestDecodedData();
client.sw_out_frame_ = GetTestDecodedData();
@@ -1009,7 +1094,7 @@ TEST(JpegClientTest, GetMeanAbsoluteDifference) {
}
TEST_P(MjpegDecodeAcceleratorTest, SimpleDecode) {
- std::vector<ParsedJpegImage*> images;
+ std::vector<const ParsedJpegImage*> images;
for (auto& image : g_env->image_data_user_)
images.push_back(image.get());
const std::vector<ClientState> expected_status(images.size(), CS_DECODE_PASS);
@@ -1017,7 +1102,7 @@ TEST_P(MjpegDecodeAcceleratorTest, SimpleDecode) {
}
TEST_P(MjpegDecodeAcceleratorTest, MultipleDecoders) {
- std::vector<ParsedJpegImage*> images;
+ std::vector<const ParsedJpegImage*> images;
for (auto& image : g_env->image_data_user_)
images.push_back(image.get());
const std::vector<ClientState> expected_status(images.size(), CS_DECODE_PASS);
@@ -1027,7 +1112,7 @@ TEST_P(MjpegDecodeAcceleratorTest, MultipleDecoders) {
TEST_P(MjpegDecodeAcceleratorTest, InputSizeChange) {
// The size of |image_data_1280x720_black_| is smaller than
// |image_data_1280x720_default_|.
- const std::vector<ParsedJpegImage*> images = {
+ const std::vector<const ParsedJpegImage*> images = {
g_env->image_data_1280x720_black_.get(),
g_env->image_data_1280x720_default_.get(),
g_env->image_data_1280x720_black_.get()};
@@ -1036,7 +1121,7 @@ TEST_P(MjpegDecodeAcceleratorTest, InputSizeChange) {
}
TEST_P(MjpegDecodeAcceleratorTest, ResolutionChange) {
- const std::vector<ParsedJpegImage*> images = {
+ const std::vector<const ParsedJpegImage*> images = {
g_env->image_data_640x368_black_.get(),
g_env->image_data_1280x720_default_.get(),
g_env->image_data_640x368_black_.get()};
@@ -1045,7 +1130,7 @@ TEST_P(MjpegDecodeAcceleratorTest, ResolutionChange) {
}
TEST_P(MjpegDecodeAcceleratorTest, CodedSizeAlignment) {
- const std::vector<ParsedJpegImage*> images = {
+ const std::vector<const ParsedJpegImage*> images = {
g_env->image_data_640x360_black_.get()};
const std::vector<ClientState> expected_status = {CS_DECODE_PASS};
TestDecode(images, expected_status);
@@ -1053,7 +1138,7 @@ TEST_P(MjpegDecodeAcceleratorTest, CodedSizeAlignment) {
// Tests whether different JPEG sampling formats will be decoded correctly.
TEST_P(MjpegDecodeAcceleratorTest, SamplingFormatChange) {
- const std::vector<ParsedJpegImage*> images = {
+ const std::vector<const ParsedJpegImage*> images = {
g_env->image_data_640x368_black_.get(),
g_env->image_data_640x368_422_black_.get()};
const std::vector<ClientState> expected_status(images.size(), CS_DECODE_PASS);
@@ -1061,14 +1146,14 @@ TEST_P(MjpegDecodeAcceleratorTest, SamplingFormatChange) {
}
TEST_P(MjpegDecodeAcceleratorTest, FailureJpeg) {
- const std::vector<ParsedJpegImage*> images = {
+ const std::vector<const ParsedJpegImage*> images = {
g_env->image_data_invalid_.get()};
const std::vector<ClientState> expected_status = {CS_ERROR};
TestDecode(images, expected_status);
}
TEST_P(MjpegDecodeAcceleratorTest, KeepDecodeAfterFailure) {
- const std::vector<ParsedJpegImage*> images = {
+ const std::vector<const ParsedJpegImage*> images = {
g_env->image_data_invalid_.get(),
g_env->image_data_1280x720_default_.get()};
const std::vector<ClientState> expected_status = {CS_ERROR, CS_DECODE_PASS};
@@ -1077,7 +1162,7 @@ TEST_P(MjpegDecodeAcceleratorTest, KeepDecodeAfterFailure) {
TEST_P(MjpegDecodeAcceleratorTest, Abort) {
constexpr size_t kNumOfJpegToDecode = 5;
- const std::vector<ParsedJpegImage*> images(
+ const std::vector<const ParsedJpegImage*> images(
kNumOfJpegToDecode, g_env->image_data_1280x720_default_.get());
// Verify only one decode success to ensure both decoders have started the
// decoding. Then destroy the first decoder when it is still decoding. The
@@ -1089,7 +1174,7 @@ TEST_P(MjpegDecodeAcceleratorTest, Abort) {
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 = {
+ const std::vector<const ParsedJpegImage*> images = {
g_env->image_data_user_[0].get()};
PerfDecodeByJDA(g_env->perf_decode_times_, images);
}
@@ -1097,7 +1182,7 @@ TEST_P(MjpegDecodeAcceleratorTest, PerfJDA) {
TEST_F(MjpegDecodeAcceleratorTest, PerfSW) {
// Only the first image will be used for perf testing.
ASSERT_GE(g_env->image_data_user_.size(), 1u);
- const std::vector<ParsedJpegImage*> images = {
+ const std::vector<const ParsedJpegImage*> images = {
g_env->image_data_user_[0].get()};
PerfDecodeBySW(g_env->perf_decode_times_, images);
}
@@ -1131,6 +1216,7 @@ int main(int argc, char** argv) {
const base::FilePath::CharType* jpeg_filenames = nullptr;
const base::FilePath::CharType* test_data_path = nullptr;
+ const base::FilePath::CharType* perf_output_path = nullptr;
int perf_decode_times = 0;
base::CommandLine::SwitchMap switches = cmd_line->GetSwitches();
for (base::CommandLine::SwitchMap::const_iterator it = switches.begin();
@@ -1144,6 +1230,10 @@ int main(int argc, char** argv) {
test_data_path = it->second.c_str();
continue;
}
+ if (it->first == "perf_output_path") {
+ perf_output_path = it->second.c_str();
+ continue;
+ }
if (it->first == "perf_decode_times") {
perf_decode_times = std::stoi(it->second);
continue;
@@ -1167,7 +1257,8 @@ int main(int argc, char** argv) {
reinterpret_cast<chromeos_camera::MjpegDecodeAcceleratorTestEnvironment*>(
testing::AddGlobalTestEnvironment(
new chromeos_camera::MjpegDecodeAcceleratorTestEnvironment(
- jpeg_filenames, test_data_path, perf_decode_times)));
+ jpeg_filenames, test_data_path, perf_output_path,
+ perf_decode_times)));
return RUN_ALL_TESTS();
}
diff --git a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.h b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.h
index a774f7d8870..0dfb85ee71f 100644
--- a/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.h
+++ b/chromium/components/chromeos_camera/mojo_mjpeg_decode_accelerator.h
@@ -7,8 +7,6 @@
#include <stdint.h>
-#include <memory>
-
#include "base/macros.h"
#include "components/chromeos_camera/common/mjpeg_decode_accelerator.mojom.h"
#include "components/chromeos_camera/mjpeg_decode_accelerator.h"
diff --git a/chromium/components/client_hints/README.md b/chromium/components/client_hints/README.md
index a75d8db0d14..202a31df157 100644
--- a/chromium/components/client_hints/README.md
+++ b/chromium/components/client_hints/README.md
@@ -83,7 +83,7 @@ The canonical enum for client hint tokens is [network::mojom::WebClientHintsType
**NOTE:** It’s very important that the order of these arrays remain in sync.
-There should also be a new feature policy created, which should go in [/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5](/third_party/blink/renderer/core/feature_policy/feature_policy_features.json5), and the header should be added to the cors `safe_names` list in [/services/network/public/cpp/cors/cors.cc](/services/network/public/cpp/cors/cors.cc)
+There should also be a new feature policy created, which should go in [/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5](/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5), and the header should be added to the cors `safe_names` list in [/services/network/public/cpp/cors/cors.cc](/services/network/public/cpp/cors/cors.cc)
TODO(crbug.com/1176808): There should be UseCounters measuring usage, but there are not currently.
diff --git a/chromium/components/client_hints/browser/client_hints.h b/chromium/components/client_hints/browser/client_hints.h
index 6700146d5e4..57d192daa6c 100644
--- a/chromium/components/client_hints/browser/client_hints.h
+++ b/chromium/components/client_hints/browser/client_hints.h
@@ -6,13 +6,12 @@
#define COMPONENTS_CLIENT_HINTS_BROWSER_CLIENT_HINTS_H_
#include <memory>
-#include <string>
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/client_hints_controller_delegate.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
class GURL;
diff --git a/chromium/components/client_update_protocol/ecdsa_unittest.cc b/chromium/components/client_update_protocol/ecdsa_unittest.cc
index 71c7441c213..c45974f667e 100644
--- a/chromium/components/client_update_protocol/ecdsa_unittest.cc
+++ b/chromium/components/client_update_protocol/ecdsa_unittest.cc
@@ -12,7 +12,6 @@
#include "base/base64.h"
#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
#include "crypto/random.h"
#include "crypto/secure_util.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/cloud_devices/common/cloud_device_description.cc b/chromium/components/cloud_devices/common/cloud_device_description.cc
index dfa77cae632..f37889b2b2b 100644
--- a/chromium/components/cloud_devices/common/cloud_device_description.cc
+++ b/chromium/components/cloud_devices/common/cloud_device_description.cc
@@ -21,7 +21,7 @@ CloudDeviceDescription::CloudDeviceDescription()
CloudDeviceDescription::~CloudDeviceDescription() = default;
bool CloudDeviceDescription::InitFromString(const std::string& json) {
- base::Optional<base::Value> value = base::JSONReader::Read(json);
+ absl::optional<base::Value> value = base::JSONReader::Read(json);
if (!value)
return false;
diff --git a/chromium/components/cloud_devices/common/cloud_device_description_consts.h b/chromium/components/cloud_devices/common/cloud_device_description_consts.h
index 77443c9619b..ed01dbff458 100644
--- a/chromium/components/cloud_devices/common/cloud_device_description_consts.h
+++ b/chromium/components/cloud_devices/common/cloud_device_description_consts.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_CLOUD_DEVICESCLOUD_DEVICE_DESCRIPTION_CONSTS_H_
-#define COMPONENTS_CLOUD_DEVICESCLOUD_DEVICE_DESCRIPTION_CONSTS_H_
+#ifndef COMPONENTS_CLOUD_DEVICES_COMMON_CLOUD_DEVICE_DESCRIPTION_CONSTS_H_
+#define COMPONENTS_CLOUD_DEVICES_COMMON_CLOUD_DEVICE_DESCRIPTION_CONSTS_H_
// Constants for common parts of JSON representation of CDD/CJT.
@@ -22,4 +22,4 @@ extern const char kKeyOption[];
} // namespace cloud_devices
-#endif // COMPONENTS_CLOUD_DEVICESCLOUD_DEVICE_DESCRIPTION_CONSTS_H_
+#endif // COMPONENTS_CLOUD_DEVICES_COMMON_CLOUD_DEVICE_DESCRIPTION_CONSTS_H_
diff --git a/chromium/components/cloud_devices/common/cloud_devices_urls.cc b/chromium/components/cloud_devices/common/cloud_devices_urls.cc
index 1409d6fc2b8..b97e7cc3d0c 100644
--- a/chromium/components/cloud_devices/common/cloud_devices_urls.cc
+++ b/chromium/components/cloud_devices/common/cloud_devices_urls.cc
@@ -6,7 +6,6 @@
#include "base/command_line.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "components/cloud_devices/common/cloud_devices_switches.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/url_util.h"
diff --git a/chromium/components/cloud_devices/common/description_items.h b/chromium/components/cloud_devices/common/description_items.h
index 08f119e2db5..a11251127e2 100644
--- a/chromium/components/cloud_devices/common/description_items.h
+++ b/chromium/components/cloud_devices/common/description_items.h
@@ -114,8 +114,8 @@ class SelectionCapability {
}
const Option& GetDefault() const {
- CHECK_GE(default_idx_, 0);
- return options_[default_idx_];
+ CHECK(!options_.empty());
+ return options_[std::max(default_idx_, 0)];
}
void AddOption(const Option& option) { AddDefaultOption(option, false); }
diff --git a/chromium/components/cloud_devices/common/description_items_inl.h b/chromium/components/cloud_devices/common/description_items_inl.h
index ede9d240982..834cc657343 100644
--- a/chromium/components/cloud_devices/common/description_items_inl.h
+++ b/chromium/components/cloud_devices/common/description_items_inl.h
@@ -100,12 +100,13 @@ bool SelectionCapability<Option, Traits>::operator==(
template <class Option, class Traits>
bool SelectionCapability<Option, Traits>::IsValid() const {
if (empty())
- return false; // This type of capabilities can't be empty
+ return false; // This type of capabilities can't be empty.
for (size_t i = 0; i < options_.size(); ++i) {
if (!Traits::IsValid(options_[i]))
return false;
}
- return default_idx_ >= 0 && default_idx_ < base::checked_cast<int>(size());
+ // This type of capability does not need a default value.
+ return default_idx_ >= -1 && default_idx_ < base::checked_cast<int>(size());
}
template <class Option, class Traits>
diff --git a/chromium/components/cloud_devices/common/printer_description.cc b/chromium/components/cloud_devices/common/printer_description.cc
index 6977e80e100..a589d8d217a 100644
--- a/chromium/components/cloud_devices/common/printer_description.cc
+++ b/chromium/components/cloud_devices/common/printer_description.cc
@@ -63,9 +63,9 @@ extern constexpr char kOptionRangeCapability[] = "range_cap";
extern constexpr char kOptionSelectCapability[] = "select_cap";
extern constexpr char kOptionTypedValueCapability[] = "typed_value_cap";
extern constexpr char kOptionVendorCapability[] = "vendor_capability";
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
extern constexpr char kOptionPin[] = "pin";
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif // defined(OS_CHROMEOS)
constexpr char kMarginBottom[] = "bottom_microns";
constexpr char kMarginLeft[] = "left_microns";
@@ -92,9 +92,9 @@ constexpr char kMinValue[] = "min";
constexpr char kMaxValue[] = "max";
constexpr char kDefaultValue[] = "default";
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
constexpr char kPinSupported[] = "supported";
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif // defined(OS_CHROMEOS)
constexpr char kTypeRangeVendorCapabilityFloat[] = "FLOAT";
constexpr char kTypeRangeVendorCapabilityInteger[] = "INTEGER";
@@ -1214,7 +1214,7 @@ class CopiesTicketItemTraits : public NoValueValidation,
public ItemsTraits<kOptionCopies> {
public:
static bool Load(const base::Value& dict, int32_t* option) {
- base::Optional<int> copies = dict.FindIntKey(kOptionCopies);
+ absl::optional<int> copies = dict.FindIntKey(kOptionCopies);
if (!copies)
return false;
@@ -1231,11 +1231,11 @@ class CopiesCapabilityTraits : public NoValueValidation,
public ItemsTraits<kOptionCopies> {
public:
static bool Load(const base::Value& dict, Copies* option) {
- base::Optional<int> default_copies = dict.FindIntKey(kDefaultValue);
+ absl::optional<int> default_copies = dict.FindIntKey(kDefaultValue);
if (!default_copies)
return false;
- base::Optional<int> max_copies = dict.FindIntKey(kMaxValue);
+ absl::optional<int> max_copies = dict.FindIntKey(kMaxValue);
if (!max_copies)
return false;
@@ -1257,10 +1257,10 @@ class MarginsTraits : public NoValueValidation,
const std::string* type = dict.FindStringKey(kKeyType);
if (!type || !TypeFromString(kMarginsNames, *type, &option->type))
return false;
- base::Optional<int> top_um = dict.FindIntKey(kMarginTop);
- base::Optional<int> right_um = dict.FindIntKey(kMarginRight);
- base::Optional<int> bottom_um = dict.FindIntKey(kMarginBottom);
- base::Optional<int> left_um = dict.FindIntKey(kMarginLeft);
+ absl::optional<int> top_um = dict.FindIntKey(kMarginTop);
+ absl::optional<int> right_um = dict.FindIntKey(kMarginRight);
+ absl::optional<int> bottom_um = dict.FindIntKey(kMarginBottom);
+ absl::optional<int> left_um = dict.FindIntKey(kMarginLeft);
if (!top_um || !right_um || !bottom_um || !left_um)
return false;
option->top_um = top_um.value();
@@ -1285,8 +1285,8 @@ class DpiTraits : public ItemsTraits<kOptionDpi> {
static bool IsValid(const Dpi& option) { return option.IsValid(); }
static bool Load(const base::Value& dict, Dpi* option) {
- base::Optional<int> horizontal = dict.FindIntKey(kDpiHorizontal);
- base::Optional<int> vertical = dict.FindIntKey(kDpiVertical);
+ absl::optional<int> horizontal = dict.FindIntKey(kDpiHorizontal);
+ absl::optional<int> vertical = dict.FindIntKey(kDpiVertical);
if (!horizontal || !vertical)
return false;
option->horizontal = horizontal.value();
@@ -1361,13 +1361,13 @@ class MediaTraits : public ItemsTraits<kOptionMediaSize> {
const std::string* type = dict.FindStringKey(kKeyName);
if (type && !TypeFromString(kMediaDefinitions, *type, &option->type))
return false;
- base::Optional<int> width_um = dict.FindIntKey(kMediaWidth);
+ absl::optional<int> width_um = dict.FindIntKey(kMediaWidth);
if (width_um)
option->width_um = width_um.value();
- base::Optional<int> height_um = dict.FindIntKey(kMediaHeight);
+ absl::optional<int> height_um = dict.FindIntKey(kMediaHeight);
if (height_um)
option->height_um = height_um.value();
- base::Optional<bool> is_continuous_feed =
+ absl::optional<bool> is_continuous_feed =
dict.FindBoolKey(kMediaIsContinuous);
if (is_continuous_feed)
option->is_continuous_feed = is_continuous_feed.value();
@@ -1408,7 +1408,7 @@ class CollateTraits : public NoValueValidation,
static const bool kDefault = true;
static bool Load(const base::Value& dict, bool* option) {
- base::Optional<bool> collate = dict.FindBoolKey(kOptionCollate);
+ absl::optional<bool> collate = dict.FindBoolKey(kOptionCollate);
if (!collate)
return false;
*option = collate.value();
@@ -1426,7 +1426,7 @@ class ReverseTraits : public NoValueValidation,
static const bool kDefault = false;
static bool Load(const base::Value& dict, bool* option) {
- base::Optional<bool> reverse = dict.FindBoolKey(kOptionReverse);
+ absl::optional<bool> reverse = dict.FindBoolKey(kOptionReverse);
if (!reverse)
return false;
*option = reverse.value();
@@ -1438,11 +1438,11 @@ class ReverseTraits : public NoValueValidation,
}
};
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
class PinTraits : public NoValueValidation, public ItemsTraits<kOptionPin> {
public:
static bool Load(const base::Value& dict, bool* option) {
- base::Optional<bool> supported = dict.FindBoolKey(kPinSupported);
+ absl::optional<bool> supported = dict.FindBoolKey(kPinSupported);
if (!supported)
return false;
*option = supported.value();
@@ -1453,7 +1453,7 @@ class PinTraits : public NoValueValidation, public ItemsTraits<kOptionPin> {
dict->SetKey(kPinSupported, base::Value(option));
}
};
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif // defined(OS_CHROMEOS)
} // namespace printer
@@ -1478,9 +1478,9 @@ template class ValueCapability<printer::Copies,
template class EmptyCapability<printer::PageRangeTraits>;
template class BooleanCapability<printer::CollateTraits>;
template class BooleanCapability<printer::ReverseTraits>;
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
template class ValueCapability<bool, printer::PinTraits>;
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif // defined(OS_CHROMEOS)
template class TicketItem<printer::PwgRasterConfig,
printer::PwgRasterConfigTraits>;
diff --git a/chromium/components/cloud_devices/common/printer_description.h b/chromium/components/cloud_devices/common/printer_description.h
index 0c392c7019f..33da6fda698 100644
--- a/chromium/components/cloud_devices/common/printer_description.h
+++ b/chromium/components/cloud_devices/common/printer_description.h
@@ -525,11 +525,11 @@ typedef ValueCapability<Copies, class CopiesCapabilityTraits> CopiesCapability;
typedef EmptyCapability<class PageRangeTraits> PageRangeCapability;
typedef BooleanCapability<class CollateTraits> CollateCapability;
typedef BooleanCapability<class ReverseTraits> ReverseCapability;
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
// This capability is not a part of standard CDD description. It's used for
// providing PIN printing opportunity in Chrome OS native printing.
typedef ValueCapability<bool, class PinTraits> PinCapability;
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif // defined(OS_CHROMEOS)
typedef TicketItem<PwgRasterConfig, PwgRasterConfigTraits>
PwgRasterConfigTicketItem;
diff --git a/chromium/components/cloud_devices/common/printer_description_unittest.cc b/chromium/components/cloud_devices/common/printer_description_unittest.cc
index e76c01bd862..217f8cdbd2e 100644
--- a/chromium/components/cloud_devices/common/printer_description_unittest.cc
+++ b/chromium/components/cloud_devices/common/printer_description_unittest.cc
@@ -41,7 +41,6 @@ const char kCdd[] = R"(
},
"color": {
"option": [ {
- "is_default": true,
"type": "STANDARD_COLOR"
}, {
"type": "STANDARD_MONOCHROME"
@@ -165,20 +164,6 @@ const char kBadVersionCdd[] = R"(
}
})";
-const char kNoDefaultCdd[] = R"(
- {
- "version": "1.0",
- "printer": {
- "color": {
- "option": [ {
- "type": "STANDARD_COLOR"
- }, {
- "type": "STANDARD_MONOCHROME"
- } ]
- }
- }
- })";
-
const char kMultyDefaultCdd[] = R"(
{
"version": "1.0",
@@ -351,8 +336,11 @@ const char kMissingDisplayNameSelectVendorCapabilityJson[] = R"(
const char kNoDefaultSelectVendorCapabilityJson[] = R"(
{
"option": [ {
- "value": "value",
- "display_name": "name"
+ "value": "value_1",
+ "display_name": "name_1"
+ }, {
+ "value": "value_2",
+ "display_name": "name_2"
} ]
})";
@@ -519,7 +507,7 @@ const char kSeveralInnerCapabilitiesVendorCapabilityCdd[] = R"(
}
})";
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
const char kPinOnlyCdd[] = R"(
{
"version": "1.0",
@@ -529,7 +517,7 @@ const char kPinOnlyCdd[] = R"(
}
}
})";
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif // defined(OS_CHROMEOS)
const char kCjt[] = R"(
{
@@ -671,9 +659,6 @@ TEST(PrinterDescriptionTest, CddInvalid) {
EXPECT_FALSE(description.InitFromString(kBadVersionCdd));
- EXPECT_TRUE(description.InitFromString(kNoDefaultCdd));
- EXPECT_FALSE(color.LoadFrom(description));
-
EXPECT_TRUE(description.InitFromString(kMultyDefaultCdd));
EXPECT_FALSE(color.LoadFrom(description));
}
@@ -704,7 +689,7 @@ TEST(PrinterDescriptionTest, CddSetAll) {
custom_raster.rotate_all_pages = false;
pwg_raster_config.set_value(custom_raster);
- color.AddDefaultOption(Color(ColorType::STANDARD_COLOR), true);
+ color.AddOption(Color(ColorType::STANDARD_COLOR));
color.AddOption(Color(ColorType::STANDARD_MONOCHROME));
Color custom(ColorType::CUSTOM_MONOCHROME);
custom.vendor_id = "123";
@@ -905,7 +890,7 @@ TEST(PrinterDescriptionTest, CddSetDocumentTypeSupported) {
TEST(PrinterDescriptionTest, CddGetRangeVendorCapability) {
for (const auto& capacity : kTestRangeCapabilities) {
- base::Optional<base::Value> value =
+ absl::optional<base::Value> value =
base::JSONReader::Read(capacity.json_name);
ASSERT_TRUE(value);
base::Value description = std::move(*value);
@@ -920,7 +905,7 @@ TEST(PrinterDescriptionTest, CddGetRangeVendorCapability) {
kInvalidBoundariesRangeVendorCapabilityJson,
kInvalidDefaultValueRangeVendorCapabilityJson};
for (const char* invalid_json_name : kInvalidJsonNames) {
- base::Optional<base::Value> value =
+ absl::optional<base::Value> value =
base::JSONReader::Read(invalid_json_name);
ASSERT_TRUE(value);
base::Value description = std::move(*value);
@@ -944,7 +929,7 @@ TEST(PrinterDescriptionTest, CddSetRangeVendorCapability) {
TEST(PrinterDescriptionTest, CddGetSelectVendorCapability) {
{
- base::Optional<base::Value> value =
+ absl::optional<base::Value> value =
base::JSONReader::Read(kSelectVendorCapabilityJson);
ASSERT_TRUE(value);
base::Value description = std::move(*value);
@@ -958,15 +943,28 @@ TEST(PrinterDescriptionTest, CddGetSelectVendorCapability) {
EXPECT_EQ(SelectVendorCapabilityOption("value_2", "name_2"),
select_capability.GetDefault());
}
-
+ {
+ absl::optional<base::Value> value =
+ base::JSONReader::Read(kNoDefaultSelectVendorCapabilityJson);
+ ASSERT_TRUE(value);
+ base::Value description = std::move(*value);
+ SelectVendorCapability select_capability;
+ EXPECT_TRUE(select_capability.LoadFrom(description));
+ EXPECT_EQ(2u, select_capability.size());
+ EXPECT_TRUE(select_capability.Contains(
+ SelectVendorCapabilityOption("value_1", "name_1")));
+ EXPECT_TRUE(select_capability.Contains(
+ SelectVendorCapabilityOption("value_2", "name_2")));
+ EXPECT_EQ(SelectVendorCapabilityOption("value_1", "name_1"),
+ select_capability.GetDefault());
+ }
const char* const kInvalidJsonNames[] = {
kNotListSelectVendorCapabilityJson,
kMissingValueSelectVendorCapabilityJson,
kMissingDisplayNameSelectVendorCapabilityJson,
- kNoDefaultSelectVendorCapabilityJson,
kSeveralDefaultsSelectVendorCapabilityJson};
for (const char* invalid_json_name : kInvalidJsonNames) {
- base::Optional<base::Value> value =
+ absl::optional<base::Value> value =
base::JSONReader::Read(invalid_json_name);
ASSERT_TRUE(value);
base::Value description = std::move(*value);
@@ -976,24 +974,41 @@ TEST(PrinterDescriptionTest, CddGetSelectVendorCapability) {
}
TEST(PrinterDescriptionTest, CddSetSelectVendorCapability) {
- SelectVendorCapability select_capability;
- select_capability.AddOption(
- SelectVendorCapabilityOption("value_1", "name_1"));
- select_capability.AddDefaultOption(
- SelectVendorCapabilityOption("value_2", "name_2"), true);
- base::Value select_capability_value(base::Value::Type::DICTIONARY);
- select_capability.SaveTo(&select_capability_value);
- std::string select_capability_str;
- EXPECT_TRUE(base::JSONWriter::WriteWithOptions(
- select_capability_value, base::JSONWriter::OPTIONS_PRETTY_PRINT,
- &select_capability_str));
- EXPECT_EQ(NormalizeJson(kSelectVendorCapabilityJson),
- NormalizeJson(select_capability_str));
+ {
+ SelectVendorCapability select_capability;
+ select_capability.AddOption(
+ SelectVendorCapabilityOption("value_1", "name_1"));
+ select_capability.AddDefaultOption(
+ SelectVendorCapabilityOption("value_2", "name_2"), true);
+ base::Value select_capability_value(base::Value::Type::DICTIONARY);
+ select_capability.SaveTo(&select_capability_value);
+ std::string select_capability_str;
+ EXPECT_TRUE(base::JSONWriter::WriteWithOptions(
+ select_capability_value, base::JSONWriter::OPTIONS_PRETTY_PRINT,
+ &select_capability_str));
+ EXPECT_EQ(NormalizeJson(kSelectVendorCapabilityJson),
+ NormalizeJson(select_capability_str));
+ }
+ {
+ SelectVendorCapability select_capability;
+ select_capability.AddOption(
+ SelectVendorCapabilityOption("value_1", "name_1"));
+ select_capability.AddOption(
+ SelectVendorCapabilityOption("value_2", "name_2"));
+ base::Value select_capability_value(base::Value::Type::DICTIONARY);
+ select_capability.SaveTo(&select_capability_value);
+ std::string select_capability_str;
+ EXPECT_TRUE(base::JSONWriter::WriteWithOptions(
+ select_capability_value, base::JSONWriter::OPTIONS_PRETTY_PRINT,
+ &select_capability_str));
+ EXPECT_EQ(NormalizeJson(kNoDefaultSelectVendorCapabilityJson),
+ NormalizeJson(select_capability_str));
+ }
}
TEST(PrinterDescriptionTest, CddGetTypedValueVendorCapability) {
for (const auto& capacity : kTestTypedValueCapabilities) {
- base::Optional<base::Value> value =
+ absl::optional<base::Value> value =
base::JSONReader::Read(capacity.json_name);
ASSERT_TRUE(value);
base::Value description = std::move(*value);
@@ -1008,7 +1023,7 @@ TEST(PrinterDescriptionTest, CddGetTypedValueVendorCapability) {
kInvalidFloatTypedValueVendorCapabilityJson,
kInvalidIntegerTypedValueVendorCapabilityJson};
for (const char* invalid_json_name : kInvalidJsonNames) {
- base::Optional<base::Value> value =
+ absl::optional<base::Value> value =
base::JSONReader::Read(invalid_json_name);
ASSERT_TRUE(value);
base::Value description = std::move(*value);
@@ -1088,7 +1103,7 @@ TEST(PrinterDescriptionTest, CddSetVendorCapability) {
NormalizeJson(description.ToString()));
}
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
TEST(PrinterDescriptionTest, CddGetPin) {
{
CloudDeviceDescription description;
@@ -1114,7 +1129,7 @@ TEST(PrinterDescriptionTest, CddSetPin) {
pin_capability.SaveTo(&description);
EXPECT_EQ(NormalizeJson(kPinOnlyCdd), NormalizeJson(description.ToString()));
}
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif // defined(OS_CHROMEOS)
TEST(PrinterDescriptionTest, CddGetAll) {
CloudDeviceDescription description;
diff --git a/chromium/components/component_updater/android/loader_policies/trust_token_key_commitments_component_loader_policy.cc b/chromium/components/component_updater/android/loader_policies/trust_token_key_commitments_component_loader_policy.cc
index cd55c8d544f..cde932a5a13 100644
--- a/chromium/components/component_updater/android/loader_policies/trust_token_key_commitments_component_loader_policy.cc
+++ b/chromium/components/component_updater/android/loader_policies/trust_token_key_commitments_component_loader_policy.cc
@@ -18,24 +18,24 @@
#include "base/containers/flat_map.h"
#include "base/files/file_util.h"
#include "base/logging.h"
-#include "base/optional.h"
#include "base/values.h"
#include "base/version.h"
#include "components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace {
// Attempts to load key commitments as raw JSON from their storage file,
// returning the loaded commitments on success and nullopt on failure.
// TODO(crbug.com/1180964) move reading string from fd to base/file_util.h
-base::Optional<std::string> LoadKeyCommitmentsFromDisk(int fd) {
+absl::optional<std::string> LoadKeyCommitmentsFromDisk(int fd) {
base::ScopedFILE file_stream(fdopen(fd, "r"));
if (!file_stream.get()) {
- return base::nullopt;
+ return absl::nullopt;
}
std::string commitments;
if (!base::ReadStreamToString(file_stream.get(), &commitments))
- return base::nullopt;
+ return absl::nullopt;
return commitments;
}
diff --git a/chromium/components/component_updater/component_installer.cc b/chromium/components/component_updater/component_installer.cc
index bc82389f170..6ff113890b3 100644
--- a/chromium/components/component_updater/component_installer.cc
+++ b/chromium/components/component_updater/component_installer.cc
@@ -18,6 +18,7 @@
#include "base/path_service.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
@@ -103,18 +104,19 @@ void ComponentInstaller::OnUpdateError(int error) {
LOG(ERROR) << "Component update error: " << error;
}
-Result ComponentInstaller::InstallHelper(
- const base::FilePath& unpack_path,
- std::unique_ptr<base::DictionaryValue>* manifest,
- base::Version* version,
- base::FilePath* install_path) {
- auto local_manifest = update_client::ReadManifest(unpack_path);
- if (!local_manifest)
+Result ComponentInstaller::InstallHelper(const base::FilePath& unpack_path,
+ base::Value* manifest,
+ base::Version* version,
+ base::FilePath* install_path) {
+ base::Value local_manifest = update_client::ReadManifest(unpack_path);
+ if (!local_manifest.is_dict())
return Result(InstallError::BAD_MANIFEST);
- std::string version_ascii;
- local_manifest->GetStringASCII("version", &version_ascii);
- const base::Version manifest_version(version_ascii);
+ const std::string* version_ascii = local_manifest.FindStringKey("version");
+ if (!version_ascii || !base::IsStringASCII(*version_ascii))
+ return Result(InstallError::INVALID_VERSION);
+
+ const base::Version manifest_version(*version_ascii);
VLOG(1) << "Install: version=" << manifest_version.GetString()
<< " current version=" << current_version_.GetString();
@@ -158,14 +160,17 @@ Result ComponentInstaller::InstallHelper(
DCHECK(!base::PathExists(unpack_path));
DCHECK(base::PathExists(local_install_path));
- const Result result =
- installer_policy_->OnCustomInstall(*local_manifest, local_install_path);
+ const base::DictionaryValue& local_manifest_dict =
+ base::Value::AsDictionaryValue(local_manifest);
+ const Result result = installer_policy_->OnCustomInstall(local_manifest_dict,
+ local_install_path);
if (result.error)
return result;
- if (!installer_policy_->VerifyInstallation(*local_manifest,
- local_install_path))
+ if (!installer_policy_->VerifyInstallation(local_manifest_dict,
+ local_install_path)) {
return Result(InstallError::INSTALL_VERIFICATION_FAILED);
+ }
*manifest = std::move(local_manifest);
*version = manifest_version;
@@ -180,7 +185,7 @@ void ComponentInstaller::Install(
std::unique_ptr<InstallParams> /*install_params*/,
ProgressCallback /*progress_callback*/,
Callback callback) {
- std::unique_ptr<base::DictionaryValue> manifest;
+ base::Value manifest;
base::Version version;
base::FilePath install_path;
const Result result =
@@ -196,8 +201,10 @@ void ComponentInstaller::Install(
current_install_dir_ = install_path;
main_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&ComponentInstaller::ComponentReady, this,
- std::move(manifest)));
+ FROM_HERE,
+ base::BindOnce(&ComponentInstaller::ComponentReady, this,
+ base::DictionaryValue::From(
+ base::Value::ToUniquePtrValue(std::move(manifest)))));
main_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), result));
}
@@ -227,20 +234,22 @@ bool ComponentInstaller::FindPreinstallation(
return false;
}
- std::unique_ptr<base::DictionaryValue> manifest =
- update_client::ReadManifest(path);
- if (!manifest) {
+ base::Value manifest = update_client::ReadManifest(path);
+ if (!manifest.is_dict()) {
DVLOG(1) << "Manifest does not exist: " << path.MaybeAsASCII();
return false;
}
- if (!installer_policy_->VerifyInstallation(*manifest, path)) {
+ std::unique_ptr<base::DictionaryValue> manifest_dict =
+ base::DictionaryValue::From(
+ base::Value::ToUniquePtrValue(std::move(manifest)));
+ if (!installer_policy_->VerifyInstallation(*manifest_dict, path)) {
DVLOG(1) << "Installation verification failed: " << path.MaybeAsASCII();
return false;
}
std::string version_lexical;
- if (!manifest->GetStringASCII("version", &version_lexical)) {
+ if (!manifest_dict->GetStringASCII("version", &version_lexical)) {
DVLOG(1) << "Failed to get component version from the manifest.";
return false;
}
@@ -257,7 +266,7 @@ bool ComponentInstaller::FindPreinstallation(
registration_info->install_dir = path;
registration_info->version = version;
- registration_info->manifest = std::move(manifest);
+ registration_info->manifest = std::move(manifest_dict);
return true;
}
@@ -334,7 +343,8 @@ void ComponentInstaller::StartRegistration(
}
std::unique_ptr<base::DictionaryValue> manifest =
- update_client::ReadManifest(path);
+ base::DictionaryValue::From(
+ base::Value::ToUniquePtrValue(update_client::ReadManifest(path)));
if (!manifest || !installer_policy_->VerifyInstallation(*manifest, path)) {
PLOG(ERROR) << "Failed to read manifest or verify installation for "
<< installer_policy_->GetName() << " (" << path.MaybeAsASCII()
diff --git a/chromium/components/component_updater/component_installer.h b/chromium/components/component_updater/component_installer.h
index bedc9e02130..89a7633106f 100644
--- a/chromium/components/component_updater/component_installer.h
+++ b/chromium/components/component_updater/component_installer.h
@@ -166,7 +166,7 @@ class ComponentInstaller final : public update_client::CrxInstaller {
scoped_refptr<RegistrationInfo> registration_info);
update_client::CrxInstaller::Result InstallHelper(
const base::FilePath& unpack_path,
- std::unique_ptr<base::DictionaryValue>* manifest,
+ base::Value* manifest,
base::Version* version,
base::FilePath* install_path);
void StartRegistration(scoped_refptr<RegistrationInfo> registration_info);
diff --git a/chromium/components/component_updater/component_updater_paths.cc b/chromium/components/component_updater/component_updater_paths.cc
index 31574f899b8..a25d7245494 100644
--- a/chromium/components/component_updater/component_updater_paths.cc
+++ b/chromium/components/component_updater/component_updater_paths.cc
@@ -4,6 +4,7 @@
#include "components/component_updater/component_updater_paths.h"
+#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/path_service.h"
diff --git a/chromium/components/component_updater/component_updater_paths.h b/chromium/components/component_updater/component_updater_paths.h
index d9383d2e9c3..1c266d2238e 100644
--- a/chromium/components/component_updater/component_updater_paths.h
+++ b/chromium/components/component_updater/component_updater_paths.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_PATHS_H_
#define COMPONENTS_COMPONENT_UPDATER_COMPONENT_UPDATER_PATHS_H_
-#include "base/files/file_path.h"
-
namespace component_updater {
enum {
diff --git a/chromium/components/component_updater/component_updater_service.cc b/chromium/components/component_updater/component_updater_service.cc
index 94e48b56e36..58b4ba8bded 100644
--- a/chromium/components/component_updater/component_updater_service.cc
+++ b/chromium/components/component_updater/component_updater_service.cc
@@ -210,7 +210,7 @@ OnDemandUpdater& CrxUpdateService::GetOnDemandUpdater() {
return *this;
}
-base::Optional<CrxComponent> CrxUpdateService::GetComponent(
+absl::optional<CrxComponent> CrxUpdateService::GetComponent(
const std::string& id) const {
DCHECK(thread_checker_.CalledOnValidThread());
return component_updater::GetComponent(components_, id);
@@ -374,7 +374,7 @@ bool CrxUpdateService::GetComponentDetails(const std::string& id,
return false;
}
-std::vector<base::Optional<CrxComponent>> CrxUpdateService::GetCrxComponents(
+std::vector<absl::optional<CrxComponent>> CrxUpdateService::GetCrxComponents(
const std::vector<std::string>& ids) {
DCHECK(thread_checker_.CalledOnValidThread());
return component_updater::GetCrxComponents(components_, ids);
diff --git a/chromium/components/component_updater/component_updater_service_internal.h b/chromium/components/component_updater/component_updater_service_internal.h
index e27044e3842..65f0174a599 100644
--- a/chromium/components/component_updater/component_updater_service_internal.h
+++ b/chromium/components/component_updater/component_updater_service_internal.h
@@ -13,9 +13,9 @@
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "components/component_updater/update_scheduler.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class TimeTicks;
@@ -77,11 +77,11 @@ class CrxUpdateService : public ComponentUpdateService,
bool DoUnregisterComponent(const CrxComponent& component);
- base::Optional<CrxComponent> GetComponent(const std::string& id) const;
+ absl::optional<CrxComponent> GetComponent(const std::string& id) const;
const CrxUpdateItem* GetComponentState(const std::string& id) const;
- std::vector<base::Optional<CrxComponent>> GetCrxComponents(
+ std::vector<absl::optional<CrxComponent>> GetCrxComponents(
const std::vector<std::string>& ids);
void OnUpdateComplete(Callback callback,
const base::TimeTicks& start_time,
diff --git a/chromium/components/component_updater/component_updater_utils.cc b/chromium/components/component_updater/component_updater_utils.cc
index 2def469b88a..d314a2659e6 100644
--- a/chromium/components/component_updater/component_updater_utils.cc
+++ b/chromium/components/component_updater/component_updater_utils.cc
@@ -8,25 +8,25 @@
#include <vector>
#include "base/containers/flat_map.h"
-#include "base/optional.h"
#include "components/update_client/update_client.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace component_updater {
-base::Optional<update_client::CrxComponent> GetComponent(
+absl::optional<update_client::CrxComponent> GetComponent(
const base::flat_map<std::string, update_client::CrxComponent>& components,
const std::string& id) {
const auto it = components.find(id);
if (it != components.end())
return it->second;
- return base::nullopt;
+ return absl::nullopt;
}
-std::vector<base::Optional<update_client::CrxComponent>> GetCrxComponents(
+std::vector<absl::optional<update_client::CrxComponent>> GetCrxComponents(
const base::flat_map<std::string, update_client::CrxComponent>&
registered_components,
const std::vector<std::string>& ids) {
- std::vector<base::Optional<update_client::CrxComponent>> components;
+ std::vector<absl::optional<update_client::CrxComponent>> components;
for (const auto& id : ids)
components.push_back(GetComponent(registered_components, id));
return components;
diff --git a/chromium/components/component_updater/component_updater_utils.h b/chromium/components/component_updater/component_updater_utils.h
index d65639e9455..6819d75c3cf 100644
--- a/chromium/components/component_updater/component_updater_utils.h
+++ b/chromium/components/component_updater/component_updater_utils.h
@@ -9,7 +9,7 @@
#include <vector>
#include "base/containers/flat_map.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace update_client {
struct CrxComponent;
@@ -17,11 +17,11 @@ struct CrxComponent;
namespace component_updater {
-base::Optional<update_client::CrxComponent> GetComponent(
+absl::optional<update_client::CrxComponent> GetComponent(
const base::flat_map<std::string, update_client::CrxComponent>& components,
const std::string& id);
-std::vector<base::Optional<update_client::CrxComponent>> GetCrxComponents(
+std::vector<absl::optional<update_client::CrxComponent>> GetCrxComponents(
const base::flat_map<std::string, update_client::CrxComponent>&
registered_components,
const std::vector<std::string>& ids);
diff --git a/chromium/components/component_updater/installer_policies/on_device_head_suggest_component_installer.h b/chromium/components/component_updater/installer_policies/on_device_head_suggest_component_installer.h
index c433dfbbc1b..5319a9e33e5 100644
--- a/chromium/components/component_updater/installer_policies/on_device_head_suggest_component_installer.h
+++ b/chromium/components/component_updater/installer_policies/on_device_head_suggest_component_installer.h
@@ -56,4 +56,4 @@ void RegisterOnDeviceHeadSuggestComponent(ComponentUpdateService* cus,
} // namespace component_updater
-#endif // CHROME_BROWSER_COMPONENT_UPDATER_ON_DEVICE_HEAD_SUGGEST_COMPONENT_INSTALLER_H_
+#endif // COMPONENTS_COMPONENT_UPDATER_INSTALLER_POLICIES_ON_DEVICE_HEAD_SUGGEST_COMPONENT_INSTALLER_H_
diff --git a/chromium/components/component_updater/installer_policies/optimization_hints_component_installer.cc b/chromium/components/component_updater/installer_policies/optimization_hints_component_installer.cc
index a5472111dad..85bed691126 100644
--- a/chromium/components/component_updater/installer_policies/optimization_hints_component_installer.cc
+++ b/chromium/components/component_updater/installer_policies/optimization_hints_component_installer.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
+#include "base/logging.h"
#include "base/path_service.h"
#include "base/task/post_task.h"
#include "base/version.h"
diff --git a/chromium/components/component_updater/installer_policies/optimization_hints_component_installer_unittest.cc b/chromium/components/component_updater/installer_policies/optimization_hints_component_installer_unittest.cc
index 6538af932ce..eb3e3ce877a 100644
--- a/chromium/components/component_updater/installer_policies/optimization_hints_component_installer_unittest.cc
+++ b/chromium/components/component_updater/installer_policies/optimization_hints_component_installer_unittest.cc
@@ -155,7 +155,7 @@ TEST_F(OptimizationHintsComponentInstallerTest, LoadFileWithData) {
ASSERT_NO_FATAL_FAILURE(CreateTestOptimizationHints(expected_hints));
ASSERT_NO_FATAL_FAILURE(LoadOptimizationHints(ruleset_format_version()));
- base::Optional<optimization_guide::HintsComponentInfo> component_info =
+ absl::optional<optimization_guide::HintsComponentInfo> component_info =
optimization_guide::OptimizationHintsComponentUpdateListener::
GetInstance()
->hints_component_info();
diff --git a/chromium/components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.cc b/chromium/components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.cc
index 87295372536..b2127f5215b 100644
--- a/chromium/components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.cc
+++ b/chromium/components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.cc
@@ -40,17 +40,17 @@ const char kTrustTokenKeyCommitmentsManifestName[] =
// Attempts to load key commitments as raw JSON from their storage file,
// returning the loaded commitments on success and nullopt on failure.
-base::Optional<std::string> LoadKeyCommitmentsFromDisk(
+absl::optional<std::string> LoadKeyCommitmentsFromDisk(
const base::FilePath& path) {
if (path.empty())
- return base::nullopt;
+ return absl::nullopt;
VLOG(1) << "Reading trust token key commitments from file: " << path.value();
std::string ret;
if (!base::ReadFileToString(path, &ret)) {
VLOG(1) << "Failed reading from " << path.value();
- return base::nullopt;
+ return absl::nullopt;
}
return ret;
@@ -158,7 +158,7 @@ void TrustTokenKeyCommitmentsComponentInstallerPolicy::GetPublicKeyHash(
// static
void TrustTokenKeyCommitmentsComponentInstallerPolicy::
LoadTrustTokensFromString(
- base::OnceCallback<base::Optional<std::string>()> load_keys_from_disk,
+ base::OnceCallback<absl::optional<std::string>()> load_keys_from_disk,
base::OnceCallback<void(const std::string&)> on_commitments_ready) {
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
@@ -167,7 +167,7 @@ void TrustTokenKeyCommitmentsComponentInstallerPolicy::
// Only bother sending commitments to the network service if we loaded
// them successfully.
[](base::OnceCallback<void(const std::string&)> on_commitments_ready,
- base::Optional<std::string> loaded_commitments) {
+ absl::optional<std::string> loaded_commitments) {
if (loaded_commitments.has_value()) {
std::move(on_commitments_ready).Run(loaded_commitments.value());
}
diff --git a/chromium/components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.h b/chromium/components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.h
index c6e31982c62..5024860569a 100644
--- a/chromium/components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.h
+++ b/chromium/components/component_updater/installer_policies/trust_token_key_commitments_component_installer_policy.h
@@ -14,9 +14,9 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/values.h"
#include "components/component_updater/component_installer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class FilePath;
@@ -58,7 +58,7 @@ class TrustTokenKeyCommitmentsComponentInstallerPolicy
// return them as an optional string. `on_commitments_ready` loads trust
// tokens in network service.
static void LoadTrustTokensFromString(
- base::OnceCallback<base::Optional<std::string>()> load_keys_from_disk,
+ base::OnceCallback<absl::optional<std::string>()> load_keys_from_disk,
base::OnceCallback<void(const std::string&)> on_commitments_ready);
protected:
diff --git a/chromium/components/components_strings.grd b/chromium/components/components_strings.grd
index 2e74372afb4..346579eb414 100644
--- a/chromium/components/components_strings.grd
+++ b/chromium/components/components_strings.grd
@@ -291,13 +291,16 @@
<part file="bookmark_component_strings.grdp" />
<part file="blocked_content_strings.grdp" />
<part file="browsing_data_strings.grdp" />
+ <part file="live_caption_strings.grdp" />
<part file="components_settings_strings.grdp" />
+ <part file="content_creation_strings.grdp" />
<part file="crash_strings.grdp" />
<part file="dialog_strings.grdp" />
<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="fullscreen_control_strings.grdp" />
<part file="heavy_ad_intervention_strings.grdp" />
<part file="history_strings.grdp" />
<part file="javascript_dialogs_strings.grdp" />
@@ -315,6 +318,7 @@
<part file="policy_strings.grdp" />
<part file="print_media_strings.grdp" />
<part file="printing_component_strings.grdp" />
+ <part file="privacy_sandbox_strings.grdp" />
<part file="reset_password_strings.grdp" />
<part file="safe_browsing_strings.grdp" />
<part file="security_interstitials_strings.grdp" />
@@ -388,10 +392,10 @@
Update
</message>
<if expr="is_android">
- <message name="IDS_SHOW_CONTENT" desc="Generic label to show content for a feature. [CHAR-LIMIT=20]" formatter_data="android_java">
+ <message name="IDS_SHOW_CONTENT" desc="Generic label to show content for a feature. [CHAR_LIMIT=20]" formatter_data="android_java">
Show
</message>
- <message name="IDS_HIDE_CONTENT" desc="Generic label to hide content for a feature. [CHAR-LIMIT=20]" formatter_data="android_java">
+ <message name="IDS_HIDE_CONTENT" desc="Generic label to hide content for a feature. [CHAR_LIMIT=20]" formatter_data="android_java">
Hide
</message>
</if>
@@ -451,7 +455,7 @@
Recently Closed
</message>
</if>
- <message name="IDS_CHOOSE" desc="Label for a button to choose something, like a shipping address for a payment request. [CHAR-LIMIT=20]" formatter_data="android_java">
+ <message name="IDS_CHOOSE" desc="Label for a button to choose something, like a shipping address for a payment request. [CHAR_LIMIT=20]" formatter_data="android_java">
Choose
</message>
diff --git a/chromium/components/consent_auditor/OWNERS b/chromium/components/consent_auditor/OWNERS
index 0e2c166181b..745d3ad1b91 100644
--- a/chromium/components/consent_auditor/OWNERS
+++ b/chromium/components/consent_auditor/OWNERS
@@ -1,4 +1,3 @@
dullweber@chromium.org
markusheintz@chromium.org
msramek@chromium.org
-vitaliii@chromium.org
diff --git a/chromium/components/consent_auditor/consent_auditor_impl_unittest.cc b/chromium/components/consent_auditor/consent_auditor_impl_unittest.cc
index 566b920a518..b7e303a6c33 100644
--- a/chromium/components/consent_auditor/consent_auditor_impl_unittest.cc
+++ b/chromium/components/consent_auditor/consent_auditor_impl_unittest.cc
@@ -197,7 +197,7 @@ TEST_F(ConsentAuditorImplTest, LocalConsentPrefRepresentation) {
EXPECT_EQ(kCurrentAppLocale, locale);
// They are two separate records; the latter did not overwrite the former.
- EXPECT_EQ(2u, consents->size());
+ EXPECT_EQ(2u, consents->DictSize());
EXPECT_TRUE(
consents->FindKeyOfType("feature1", base::Value::Type::DICTIONARY));
@@ -224,7 +224,7 @@ TEST_F(ConsentAuditorImplTest, LocalConsentPrefRepresentation) {
EXPECT_EQ(kFeature2NewAppLocale, locale);
// We still have two records.
- EXPECT_EQ(2u, consents->size());
+ EXPECT_EQ(2u, consents->DictSize());
}
TEST_F(ConsentAuditorImplTest, RecordGaiaConsentAsUserConsent) {
diff --git a/chromium/components/consent_auditor/consent_sync_bridge_impl.cc b/chromium/components/consent_auditor/consent_sync_bridge_impl.cc
index 67652540d66..ca51b34a8fa 100644
--- a/chromium/components/consent_auditor/consent_sync_bridge_impl.cc
+++ b/chromium/components/consent_auditor/consent_sync_bridge_impl.cc
@@ -84,7 +84,7 @@ ConsentSyncBridgeImpl::CreateMetadataChangeList() {
return WriteBatch::CreateMetadataChangeList();
}
-base::Optional<ModelError> ConsentSyncBridgeImpl::MergeSyncData(
+absl::optional<ModelError> ConsentSyncBridgeImpl::MergeSyncData(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_data) {
DCHECK(entity_data.empty());
@@ -95,7 +95,7 @@ base::Optional<ModelError> ConsentSyncBridgeImpl::MergeSyncData(
std::move(entity_data));
}
-base::Optional<ModelError> ConsentSyncBridgeImpl::ApplySyncChanges(
+absl::optional<ModelError> ConsentSyncBridgeImpl::ApplySyncChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_changes) {
std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
@@ -165,7 +165,7 @@ void ConsentSyncBridgeImpl::ReadAllDataAndResubmit() {
}
void ConsentSyncBridgeImpl::OnReadAllDataToResubmit(
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<RecordList> data_records) {
if (change_processor()->TrackedAccountId().empty()) {
// Meanwhile the sync has been disabled. We will try next time.
@@ -249,7 +249,7 @@ void ConsentSyncBridgeImpl::ProcessQueuedEvents() {
}
void ConsentSyncBridgeImpl::OnStoreCreated(
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<ModelTypeStore> store) {
if (error) {
change_processor()->ReportError(*error);
@@ -263,7 +263,7 @@ void ConsentSyncBridgeImpl::OnStoreCreated(
}
void ConsentSyncBridgeImpl::OnReadAllMetadata(
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<MetadataBatch> metadata_batch) {
if (error) {
change_processor()->ReportError(*error);
@@ -280,7 +280,7 @@ void ConsentSyncBridgeImpl::OnReadAllMetadata(
}
}
-void ConsentSyncBridgeImpl::OnCommit(const base::Optional<ModelError>& error) {
+void ConsentSyncBridgeImpl::OnCommit(const absl::optional<ModelError>& error) {
if (error) {
change_processor()->ReportError(*error);
}
@@ -288,7 +288,7 @@ void ConsentSyncBridgeImpl::OnCommit(const base::Optional<ModelError>& error) {
void ConsentSyncBridgeImpl::OnReadData(
DataCallback callback,
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<RecordList> data_records,
std::unique_ptr<IdList> missing_id_list) {
OnReadAllData(std::move(callback), error, std::move(data_records));
@@ -296,7 +296,7 @@ void ConsentSyncBridgeImpl::OnReadData(
void ConsentSyncBridgeImpl::OnReadAllData(
DataCallback callback,
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<RecordList> data_records) {
if (error) {
change_processor()->ReportError(*error);
diff --git a/chromium/components/consent_auditor/consent_sync_bridge_impl.h b/chromium/components/consent_auditor/consent_sync_bridge_impl.h
index aa959b5657d..8e1f62ccfb3 100644
--- a/chromium/components/consent_auditor/consent_sync_bridge_impl.h
+++ b/chromium/components/consent_auditor/consent_sync_bridge_impl.h
@@ -13,11 +13,11 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/consent_auditor/consent_sync_bridge.h"
#include "components/sync/model/model_type_change_processor.h"
#include "components/sync/model/model_type_store.h"
#include "components/sync/model/model_type_sync_bridge.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace consent_auditor {
@@ -32,10 +32,10 @@ class ConsentSyncBridgeImpl : public ConsentSyncBridge,
// ModelTypeSyncBridge implementation.
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
@@ -61,19 +61,19 @@ class ConsentSyncBridgeImpl : public ConsentSyncBridge,
// Record events in the deferred queue and clear the queue.
void ProcessQueuedEvents();
- void OnStoreCreated(const base::Optional<syncer::ModelError>& error,
+ void OnStoreCreated(const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore> store);
- void OnReadAllMetadata(const base::Optional<syncer::ModelError>& error,
+ void OnReadAllMetadata(const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch);
- void OnCommit(const base::Optional<syncer::ModelError>& error);
+ void OnCommit(const absl::optional<syncer::ModelError>& error);
void OnReadData(
DataCallback callback,
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records,
std::unique_ptr<syncer::ModelTypeStore::IdList> missing_id_list);
void OnReadAllData(
DataCallback callback,
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records);
// Resubmit all the consents persisted in the store to sync consents, which
@@ -81,7 +81,7 @@ class ConsentSyncBridgeImpl : public ConsentSyncBridge,
// processor already knows about (i.e. with metadata), but it is allowed.
void ReadAllDataAndResubmit();
void OnReadAllDataToResubmit(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records);
// Persistent storage for in flight consents. Should remain quite small, as we
diff --git a/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views.cc b/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
index f90ef6a3b39..47992aa6cdc 100644
--- a/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
+++ b/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/auto_reset.h"
#include "components/constrained_window/constrained_window_views.h"
#include "components/web_modal/web_contents_modal_dialog_host.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
@@ -36,15 +37,15 @@ NativeWebContentsModalDialogManagerViews::
NativeWebContentsModalDialogManagerViews(
gfx::NativeWindow dialog,
SingleWebContentsDialogManagerDelegate* native_delegate)
- : native_delegate_(native_delegate),
- dialog_(dialog),
- host_(nullptr),
- host_destroying_(false) {
+ : native_delegate_(native_delegate), dialog_(dialog) {
ManageDialog();
}
NativeWebContentsModalDialogManagerViews::
~NativeWebContentsModalDialogManagerViews() {
+ // Temporary, for debugging https://crbug.com/1207814.
+ CHECK(!within_show_);
+
if (host_)
host_->RemoveObserver(this);
@@ -93,15 +94,18 @@ void NativeWebContentsModalDialogManagerViews::Show() {
#if defined(USE_AURA)
std::unique_ptr<wm::SuspendChildWindowVisibilityAnimations> suspend;
if (shown_widgets_.find(widget) != shown_widgets_.end()) {
- suspend.reset(new wm::SuspendChildWindowVisibilityAnimations(
- widget->GetNativeWindow()->parent()));
+ suspend = std::make_unique<wm::SuspendChildWindowVisibilityAnimations>(
+ widget->GetNativeWindow()->parent());
}
#endif
- // |host_| may be null during tab drag on Views/Win32.
- //
- // TODO(https://crbug.com/1119431): This null check may be out of date.
- if (host_)
- constrained_window::UpdateWebContentsModalDialogPosition(widget, host_);
+
+ // `host_` should not be null. If you can reproduce this, please comment on
+ // https://crbug.com/1207814.
+ CHECK(host_);
+ // Temporary, for debugging https://crbug.com/1207814.
+ base::AutoReset<bool> within_show(&within_show_, true);
+
+ constrained_window::UpdateWebContentsModalDialogPosition(widget, host_);
widget->Show();
if (host_->ShouldActivateDialog())
Focus();
@@ -124,9 +128,8 @@ void NativeWebContentsModalDialogManagerViews::Show() {
void NativeWebContentsModalDialogManagerViews::Hide() {
views::Widget* widget = GetWidget(dialog());
#if defined(USE_AURA)
- std::unique_ptr<wm::SuspendChildWindowVisibilityAnimations> suspend;
- suspend.reset(new wm::SuspendChildWindowVisibilityAnimations(
- widget->GetNativeWindow()->parent()));
+ auto suspend = std::make_unique<wm::SuspendChildWindowVisibilityAnimations>(
+ widget->GetNativeWindow()->parent());
#endif
widget->Hide();
}
@@ -183,7 +186,7 @@ void NativeWebContentsModalDialogManagerViews::HostChanged(
host_ = new_host;
- // |host_| may be null during WebContents destruction or Win32 tab dragging.
+ // |host_| may be null during WebContents destruction.
if (host_) {
host_->AddObserver(this);
diff --git a/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views.h b/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views.h
index 109d6d1adab..03eaacdcf29 100644
--- a/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views.h
+++ b/chromium/components/constrained_window/native_web_contents_modal_dialog_manager_views.h
@@ -73,8 +73,9 @@ class NativeWebContentsModalDialogManagerViews
web_modal::SingleWebContentsDialogManagerDelegate* native_delegate_;
gfx::NativeWindow dialog_;
- web_modal::WebContentsModalDialogHost* host_;
- bool host_destroying_;
+ web_modal::WebContentsModalDialogHost* host_ = nullptr;
+ bool within_show_ = false;
+ bool host_destroying_ = false;
std::set<views::Widget*> observed_widgets_;
std::set<views::Widget*> shown_widgets_;
diff --git a/chromium/components/content_capture/browser/content_capture_receiver.cc b/chromium/components/content_capture/browser/content_capture_receiver.cc
index a23d799da8e..b16da6a6467 100644
--- a/chromium/components/content_capture/browser/content_capture_receiver.cc
+++ b/chromium/components/content_capture/browser/content_capture_receiver.cc
@@ -199,7 +199,7 @@ const ContentCaptureFrame& ContentCaptureReceiver::GetContentCaptureFrame() {
frame_content_capture_data_.id = id_;
frame_content_capture_data_.url = url;
- const base::Optional<gfx::Size>& size = rfh_->GetFrameSize();
+ const absl::optional<gfx::Size>& size = rfh_->GetFrameSize();
if (size.has_value())
frame_content_capture_data_.bounds = gfx::Rect(size.value());
diff --git a/chromium/components/content_capture/browser/content_capture_receiver_test.cc b/chromium/components/content_capture/browser/content_capture_receiver_test.cc
index 4f6aafec5e3..48c9f2cdc70 100644
--- a/chromium/components/content_capture/browser/content_capture_receiver_test.cc
+++ b/chromium/components/content_capture/browser/content_capture_receiver_test.cc
@@ -24,10 +24,11 @@
namespace content_capture {
namespace {
-static constexpr char kMainFrameUrl[] = "http://foo.com/main.html";
-static constexpr char kMainFrameUrl2[] = "http://foo.com/2.html";
-static constexpr char kChildFrameUrl[] = "http://foo.org/child.html";
-static constexpr char kMainFrameSameDocument[] = "http://foo.com/main.html#1";
+static constexpr char16_t kMainFrameUrl[] = u"http://foo.com/main.html";
+static constexpr char16_t kMainFrameUrl2[] = u"http://foo.com/2.html";
+static constexpr char16_t kChildFrameUrl[] = u"http://foo.org/child.html";
+static constexpr char16_t kMainFrameSameDocument[] =
+ u"http://foo.com/main.html#1";
// Fake ContentCaptureSender to call ContentCaptureReceiver mojom interface.
class FakeContentCaptureSender {
@@ -185,10 +186,10 @@ class ContentCaptureReceiverTest : public content::RenderViewHostTestHarness,
child.value = u"Hello";
child.bounds = gfx::Rect(5, 5, 5, 5);
// No need to set id in sender.
- test_data_.value = base::ASCIIToUTF16(kMainFrameUrl);
+ test_data_.value = kMainFrameUrl;
test_data_.bounds = gfx::Rect(10, 10);
test_data_.children.push_back(child);
- test_data2_.value = base::ASCIIToUTF16(kChildFrameUrl);
+ test_data2_.value = kChildFrameUrl;
test_data2_.bounds = gfx::Rect(10, 10);
test_data2_.children.push_back(child);
@@ -197,7 +198,7 @@ class ContentCaptureReceiverTest : public content::RenderViewHostTestHarness,
child_change.id = 2;
child_change.value = u"Hello World";
child_change.bounds = gfx::Rect(5, 5, 5, 5);
- test_data_change_.value = base::ASCIIToUTF16(kMainFrameUrl);
+ test_data_change_.value = kMainFrameUrl;
test_data_change_.bounds = gfx::Rect(10, 10);
test_data_change_.children.push_back(child_change);
@@ -207,7 +208,7 @@ class ContentCaptureReceiverTest : public content::RenderViewHostTestHarness,
child2.id = 3;
child2.value = u"World";
child2.bounds = gfx::Rect(5, 10, 5, 5);
- test_data_update_.value = base::ASCIIToUTF16(kMainFrameUrl);
+ test_data_update_.value = kMainFrameUrl;
test_data_update_.bounds = gfx::Rect(10, 10);
test_data_update_.children.push_back(child2);
}
@@ -655,7 +656,7 @@ TEST_P(ContentCaptureReceiverTest, MAYBE_ChildFrameCaptureContentFirst) {
if (content::CanSameSiteMainFrameNavigationsChangeRenderFrameHosts())
data = GetExpectedTestData(/* main_frame =*/true);
- data.url = base::ASCIIToUTF16(kMainFrameUrl2);
+ data.url = kMainFrameUrl2;
// Currently, there is no way to fake frame size, set it to 0.
data.bounds = gfx::Rect();
expected.clear();
diff --git a/chromium/components/content_capture/renderer/content_capture_sender.h b/chromium/components/content_capture/renderer/content_capture_sender.h
index 4e1d2e23cf3..5f5ddc3bd0e 100644
--- a/chromium/components/content_capture/renderer/content_capture_sender.h
+++ b/chromium/components/content_capture/renderer/content_capture_sender.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_CONTENT_CAPTURE_RENDERER_CONTENT_CAPTURE_SENDER_H_
#define COMPONENTS_CONTENT_CAPTURE_RENDERER_CONTENT_CAPTURE_SENDER_H_
-#include <vector>
-
#include "components/content_capture/common/content_capture.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
diff --git a/chromium/components/content_creation/DIR_METADATA b/chromium/components/content_creation/DIR_METADATA
new file mode 100644
index 00000000000..41d1f6aaec4
--- /dev/null
+++ b/chromium/components/content_creation/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+ component: "UI>Browser>Creation"
+}
+
+team_email: "chrome-creation@google.com"
diff --git a/chromium/components/content_creation/OWNERS b/chromium/components/content_creation/OWNERS
new file mode 100644
index 00000000000..ab3ce6f1263
--- /dev/null
+++ b/chromium/components/content_creation/OWNERS
@@ -0,0 +1,2 @@
+seblalancette@chromium.org
+sebsg@chromium.org \ No newline at end of file
diff --git a/chromium/components/content_creation/README.md b/chromium/components/content_creation/README.md
new file mode 100644
index 00000000000..e3892c78069
--- /dev/null
+++ b/chromium/components/content_creation/README.md
@@ -0,0 +1,4 @@
+# Content Creation Component
+
+This directory contains cross-platform business logic code for content creation
+features. \ No newline at end of file
diff --git a/chromium/components/content_creation/notes/DEPS b/chromium/components/content_creation/notes/DEPS
new file mode 100644
index 00000000000..354c1babc0b
--- /dev/null
+++ b/chromium/components/content_creation/notes/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+ "+components/keyed_service/core",
+ "+components/strings/grit",
+ "+ui/base",
+]
diff --git a/chromium/components/content_creation/notes/android/BUILD.gn b/chromium/components/content_creation/notes/android/BUILD.gn
new file mode 100644
index 00000000000..56caaff52fc
--- /dev/null
+++ b/chromium/components/content_creation/notes/android/BUILD.gn
@@ -0,0 +1,53 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/config.gni")
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+ sources = [
+ "java/src/org/chromium/components/content_creation/notes/NoteService.java",
+ "java/src/org/chromium/components/content_creation/notes/bridges/NoteServiceBridge.java",
+ "java/src/org/chromium/components/content_creation/notes/bridges/NoteTemplateConversionBridge.java",
+ "java/src/org/chromium/components/content_creation/notes/models/Background.java",
+ "java/src/org/chromium/components/content_creation/notes/models/FooterStyle.java",
+ "java/src/org/chromium/components/content_creation/notes/models/LinearGradientBackground.java",
+ "java/src/org/chromium/components/content_creation/notes/models/LinearGradientDirection.java",
+ "java/src/org/chromium/components/content_creation/notes/models/NoteTemplate.java",
+ "java/src/org/chromium/components/content_creation/notes/models/SolidBackground.java",
+ "java/src/org/chromium/components/content_creation/notes/models/TextAlignment.java",
+ "java/src/org/chromium/components/content_creation/notes/models/TextStyle.java",
+ ]
+
+ deps = [
+ "//base:base_java",
+ "//third_party/androidx:androidx_annotation_annotation_java",
+ ]
+
+ resources_package = "org.chromium.components.content_creation.notes"
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+}
+
+generate_jni("jni_headers") {
+ sources = [
+ "java/src/org/chromium/components/content_creation/notes/bridges/NoteServiceBridge.java",
+ "java/src/org/chromium/components/content_creation/notes/bridges/NoteTemplateConversionBridge.java",
+ ]
+}
+
+source_set("android") {
+ sources = [
+ "note_service_bridge.cc",
+ "note_service_bridge.h",
+ "note_template_conversion_bridge.cc",
+ "note_template_conversion_bridge.h",
+ ]
+
+ deps = [
+ ":jni_headers",
+ "//base",
+ "//components/content_creation/notes/core",
+ "//components/content_creation/notes/core/templates",
+ ]
+}
diff --git a/chromium/components/content_creation/notes/android/note_service_bridge.cc b/chromium/components/content_creation/notes/android/note_service_bridge.cc
new file mode 100644
index 00000000000..b742e4721e7
--- /dev/null
+++ b/chromium/components/content_creation/notes/android/note_service_bridge.cc
@@ -0,0 +1,66 @@
+// Copyright 2021 The Chromium Authors. 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/content_creation/notes/android/note_service_bridge.h"
+
+#include "base/android/callback_android.h"
+#include "base/android/jni_array.h"
+#include "base/bind.h"
+#include "components/content_creation/notes/android/jni_headers/NoteServiceBridge_jni.h"
+#include "components/content_creation/notes/android/note_template_conversion_bridge.h"
+#include "components/content_creation/notes/core/templates/note_template.h"
+
+using base::android::AttachCurrentThread;
+
+namespace content_creation {
+namespace {
+const char kNoteServiceBridgeKey[] = "note_service_bridge";
+
+void RunGetTemplatesCallback(const JavaRef<jobject>& j_callback,
+ std::vector<NoteTemplate> templates) {
+ JNIEnv* env = AttachCurrentThread();
+ RunObjectCallbackAndroid(
+ j_callback,
+ NoteTemplateConversionBridge::CreateJavaNoteTemplates(env, templates));
+}
+
+} // namespace
+
+// static
+ScopedJavaLocalRef<jobject> NoteServiceBridge::GetBridgeForNoteService(
+ NoteService* note_service) {
+ DCHECK(note_service);
+ if (!note_service->GetUserData(kNoteServiceBridgeKey)) {
+ note_service->SetUserData(
+ kNoteServiceBridgeKey,
+ std::make_unique<NoteServiceBridge>(note_service));
+ }
+
+ NoteServiceBridge* bridge = static_cast<NoteServiceBridge*>(
+ note_service->GetUserData(kNoteServiceBridgeKey));
+ return ScopedJavaLocalRef<jobject>(bridge->java_obj_);
+}
+
+NoteServiceBridge::NoteServiceBridge(NoteService* note_service)
+ : note_service_(note_service) {
+ DCHECK(note_service_);
+ JNIEnv* env = AttachCurrentThread();
+ java_obj_.Reset(
+ env, Java_NoteServiceBridge_create(env, reinterpret_cast<int64_t>(this))
+ .obj());
+}
+
+NoteServiceBridge::~NoteServiceBridge() {
+ JNIEnv* env = AttachCurrentThread();
+ Java_NoteServiceBridge_clearNativePtr(env, java_obj_);
+}
+
+void NoteServiceBridge::GetTemplates(JNIEnv* env,
+ const JavaParamRef<jobject>& jcaller,
+ const JavaParamRef<jobject>& jcallback) {
+ note_service_->GetTemplates(base::BindOnce(
+ &RunGetTemplatesCallback, ScopedJavaGlobalRef<jobject>(jcallback)));
+}
+
+} // namespace content_creation
diff --git a/chromium/components/content_creation/notes/android/note_service_bridge.h b/chromium/components/content_creation/notes/android/note_service_bridge.h
new file mode 100644
index 00000000000..ff2c1c9498e
--- /dev/null
+++ b/chromium/components/content_creation/notes/android/note_service_bridge.h
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CONTENT_CREATION_NOTES_ANDROID_NOTE_SERVICE_BRIDGE_H_
+#define COMPONENTS_CONTENT_CREATION_NOTES_ANDROID_NOTE_SERVICE_BRIDGE_H_
+
+#include "base/android/jni_android.h"
+#include "base/supports_user_data.h"
+#include "components/content_creation/notes/core/note_service.h"
+
+using base::android::JavaParamRef;
+using base::android::JavaRef;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace content_creation {
+
+class NoteServiceBridge : public base::SupportsUserData::Data {
+ public:
+ static ScopedJavaLocalRef<jobject> GetBridgeForNoteService(
+ NoteService* note_service);
+
+ explicit NoteServiceBridge(NoteService* note_service);
+ ~NoteServiceBridge() override;
+
+ // Not copyable or movable.
+ NoteServiceBridge(const NoteServiceBridge&) = delete;
+ NoteServiceBridge& operator=(const NoteServiceBridge&) = delete;
+
+ void GetTemplates(JNIEnv* env,
+ const JavaParamRef<jobject>& jcaller,
+ const JavaParamRef<jobject>& jcallback);
+
+ private:
+ ScopedJavaGlobalRef<jobject> java_obj_;
+
+ // Not owned.
+ NoteService* note_service_;
+};
+
+} // namespace content_creation
+
+#endif // COMPONENTS_CONTENT_CREATION_NOTES_ANDROID_NOTE_SERVICE_BRIDGE_H_
diff --git a/chromium/components/content_creation/notes/android/note_template_conversion_bridge.cc b/chromium/components/content_creation/notes/android/note_template_conversion_bridge.cc
new file mode 100644
index 00000000000..1d1be9f1236
--- /dev/null
+++ b/chromium/components/content_creation/notes/android/note_template_conversion_bridge.cc
@@ -0,0 +1,80 @@
+// Copyright 2021 The Chromium Authors. 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/content_creation/notes/android/note_template_conversion_bridge.h"
+
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "components/content_creation/notes/android/jni_headers/NoteTemplateConversionBridge_jni.h"
+#include "components/content_creation/notes/core/templates/template_types.h"
+
+namespace content_creation {
+
+using base::android::ConvertUTF8ToJavaString;
+using base::android::ScopedJavaLocalRef;
+
+namespace {
+
+ScopedJavaLocalRef<jobject> CreateJavaBackground(JNIEnv* env,
+ const Background& background) {
+ if (background.is_linear_gradient()) {
+ const std::vector<int> int_colors(background.colors()->begin(),
+ background.colors()->end());
+ ScopedJavaLocalRef<jintArray> int_array =
+ base::android::ToJavaIntArray(env, int_colors);
+
+ return Java_NoteTemplateConversionBridge_createLinearGradientBackground(
+ env, int_array, static_cast<uint16_t>(background.direction()));
+ }
+ return Java_NoteTemplateConversionBridge_createBackground(env,
+ background.color());
+}
+
+ScopedJavaLocalRef<jobject> CreateJavaTextStyle(JNIEnv* env,
+ const TextStyle& text_style) {
+ return Java_NoteTemplateConversionBridge_createTextStyle(
+ env, ConvertUTF8ToJavaString(env, text_style.font_name()),
+ text_style.font_color(), text_style.weight(), text_style.all_caps(),
+ static_cast<uint16_t>(text_style.alignment()));
+}
+
+ScopedJavaLocalRef<jobject> CreateJavaFooterStyle(
+ JNIEnv* env,
+ const FooterStyle& footer_style) {
+ return Java_NoteTemplateConversionBridge_createFooterStyle(
+ env, footer_style.text_color(), footer_style.logo_color());
+}
+
+ScopedJavaLocalRef<jobject> CreateJavaTemplateAndMaybeAddToList(
+ JNIEnv* env,
+ ScopedJavaLocalRef<jobject> jlist,
+ const NoteTemplate& note_template) {
+ auto jbackground = CreateJavaBackground(env, note_template.main_background());
+ auto jtext_style = CreateJavaTextStyle(env, note_template.text_style());
+ auto jfooter_style = CreateJavaFooterStyle(env, note_template.footer_style());
+
+ return Java_NoteTemplateConversionBridge_createTemplateAndMaybeAddToList(
+ env, jlist, static_cast<uint32_t>(note_template.id()),
+ ConvertUTF8ToJavaString(env, note_template.localized_name()), jbackground,
+ jtext_style, jfooter_style);
+}
+
+} // namespace
+
+// static
+ScopedJavaLocalRef<jobject>
+NoteTemplateConversionBridge::CreateJavaNoteTemplates(
+ JNIEnv* env,
+ const std::vector<NoteTemplate>& note_templates) {
+ ScopedJavaLocalRef<jobject> jlist =
+ Java_NoteTemplateConversionBridge_createTemplateList(env);
+
+ for (const auto& note_template : note_templates) {
+ CreateJavaTemplateAndMaybeAddToList(env, jlist, note_template);
+ }
+
+ return jlist;
+}
+
+} // namespace content_creation
diff --git a/chromium/components/content_creation/notes/android/note_template_conversion_bridge.h b/chromium/components/content_creation/notes/android/note_template_conversion_bridge.h
new file mode 100644
index 00000000000..5463943c746
--- /dev/null
+++ b/chromium/components/content_creation/notes/android/note_template_conversion_bridge.h
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CONTENT_CREATION_NOTES_ANDROID_NOTE_TEMPLATE_CONVERSION_BRIDGE_H_
+#define COMPONENTS_CONTENT_CREATION_NOTES_ANDROID_NOTE_TEMPLATE_CONVERSION_BRIDGE_H_
+
+#include "base/android/jni_android.h"
+#include "components/content_creation/notes/core/templates/note_template.h"
+
+using base::android::ScopedJavaLocalRef;
+
+namespace content_creation {
+
+class NoteTemplateConversionBridge {
+ public:
+ static ScopedJavaLocalRef<jobject> CreateJavaNoteTemplates(
+ JNIEnv* env,
+ const std::vector<NoteTemplate>& templates);
+};
+
+} // namespace content_creation
+
+#endif // COMPONENTS_CONTENT_CREATION_NOTES_ANDROID_NOTE_TEMPLATE_CONVERSION_BRIDGE_H_
diff --git a/chromium/components/content_creation/notes/core/BUILD.gn b/chromium/components/content_creation/notes/core/BUILD.gn
new file mode 100644
index 00000000000..4eca27746e8
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("core") {
+ sources = [
+ "note_service.cc",
+ "note_service.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/content_creation/notes/core/templates",
+ "//components/keyed_service/core",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+
+ sources = [
+ "note_service_unittest.cc",
+ "templates/template_store_unittest.cc",
+ ]
+
+ deps = [
+ ":core",
+ "//base",
+ "//base/test:test_support",
+ "//components/content_creation/notes/core/templates",
+ "//components/content_creation/notes/core/test:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/content_creation/notes/core/note_service.cc b/chromium/components/content_creation/notes/core/note_service.cc
new file mode 100644
index 00000000000..c95dc35800e
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/note_service.cc
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/content_creation/notes/core/note_service.h"
+
+#include "base/callback.h"
+
+namespace content_creation {
+
+NoteService::NoteService(std::unique_ptr<TemplateStore> template_store)
+ : template_store_(std::move(template_store)) {}
+
+NoteService::~NoteService() = default;
+
+void NoteService::GetTemplates(GetTemplatesCallback callback) {
+ template_store_->GetTemplates(std::move(callback));
+}
+
+} // namespace content_creation \ No newline at end of file
diff --git a/chromium/components/content_creation/notes/core/note_service.h b/chromium/components/content_creation/notes/core/note_service.h
new file mode 100644
index 00000000000..6fb6aaf9e98
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/note_service.h
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CONTENT_CREATION_NOTES_CORE_NOTE_SERVICE_H_
+#define COMPONENTS_CONTENT_CREATION_NOTES_CORE_NOTE_SERVICE_H_
+
+#include <memory>
+
+#include "base/supports_user_data.h"
+#include "components/content_creation/notes/core/templates/template_store.h"
+#include "components/keyed_service/core/keyed_service.h"
+
+namespace content_creation {
+
+// Keyed service to be used by user-facing surfaces to retrieve templating
+// information for generating stylized notes.
+class NoteService : public KeyedService, public base::SupportsUserData {
+ public:
+ explicit NoteService(std::unique_ptr<TemplateStore> template_store);
+ ~NoteService() override;
+
+ // Not copyable or movable.
+ NoteService(const NoteService&) = delete;
+ NoteService& operator=(const NoteService&) = delete;
+
+ // Gets the set of templates to be used for generating stylized notes. Will
+ // invoke |callback| with the results.
+ void GetTemplates(GetTemplatesCallback callback);
+
+ private:
+ std::unique_ptr<TemplateStore> template_store_;
+};
+
+} // namespace content_creation
+
+#endif // COMPONENTS_CONTENT_CREATION_NOTES_CORE_NOTE_SERVICE_H_ \ No newline at end of file
diff --git a/chromium/components/content_creation/notes/core/note_service_unittest.cc b/chromium/components/content_creation/notes/core/note_service_unittest.cc
new file mode 100644
index 00000000000..faaf189b8ed
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/note_service_unittest.cc
@@ -0,0 +1,47 @@
+// Copyright 2021 The Chromium Authors. 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/content_creation/notes/core/note_service.h"
+
+#include <vector>
+
+#include "base/run_loop.h"
+#include "base/test/bind.h"
+#include "base/test/task_environment.h"
+#include "components/content_creation/notes/core/templates/note_template.h"
+#include "components/content_creation/notes/core/test/mocks.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace content_creation {
+
+class NoteServiceTest : public testing::Test {
+ void SetUp() override {
+ auto mock_template_store = std::make_unique<test::MockTemplateStore>();
+ mock_template_store_ = mock_template_store.get();
+
+ note_service_ =
+ std::make_unique<NoteService>(std::move(mock_template_store));
+ }
+
+ protected:
+ // Have to use TaskEnvironment since the TemplateStore posts tasks to the
+ // thread pool.
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+
+ std::unique_ptr<NoteService> note_service_;
+ test::MockTemplateStore* mock_template_store_;
+};
+
+TEST_F(NoteServiceTest, GetTemplatesSuccess_Empty) {
+ EXPECT_CALL(*mock_template_store_, GetTemplates(_)).Times(1);
+
+ note_service_->GetTemplates(base::BindLambdaForTesting(
+ [](std::vector<NoteTemplate> templates) { /* No-op */ }));
+}
+
+} // namespace content_creation
diff --git a/chromium/components/content_creation/notes/core/templates/BUILD.gn b/chromium/components/content_creation/notes/core/templates/BUILD.gn
new file mode 100644
index 00000000000..ceaa65ade80
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/templates/BUILD.gn
@@ -0,0 +1,22 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("templates") {
+ sources = [
+ "note_template.cc",
+ "note_template.h",
+ "template_constants.cc",
+ "template_constants.h",
+ "template_store.cc",
+ "template_store.h",
+ "template_types.cc",
+ "template_types.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/strings:components_strings",
+ "//ui/base",
+ ]
+}
diff --git a/chromium/components/content_creation/notes/core/templates/note_template.cc b/chromium/components/content_creation/notes/core/templates/note_template.cc
new file mode 100644
index 00000000000..e880dbb08b5
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/templates/note_template.cc
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/content_creation/notes/core/templates/note_template.h"
+
+namespace content_creation {
+
+NoteTemplate::NoteTemplate(NoteTemplateIds id,
+ const std::string& localized_name,
+ const Background& main_background,
+ const TextStyle& text_style,
+ const FooterStyle& footer_style)
+ : id_(id),
+ localized_name_(localized_name),
+ main_background_(main_background),
+ text_style_(text_style),
+ footer_style_(footer_style) {}
+
+NoteTemplate::NoteTemplate(const NoteTemplate& other)
+ : id_(other.id()),
+ localized_name_(other.localized_name()),
+ main_background_(other.main_background()),
+ text_style_(other.text_style()),
+ footer_style_(other.footer_style()) {}
+
+} // namespace content_creation
diff --git a/chromium/components/content_creation/notes/core/templates/note_template.h b/chromium/components/content_creation/notes/core/templates/note_template.h
new file mode 100644
index 00000000000..3e79e49a2ef
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/templates/note_template.h
@@ -0,0 +1,50 @@
+// Copyright 2021 The Chromium Authors. 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_CONTENT_CREATION_NOTES_CORE_TEMPLATES_NOTE_TEMPLATE_H_
+#define COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_NOTE_TEMPLATE_H_
+
+#include <string>
+#include <vector>
+
+#include "components/content_creation/notes/core/templates/template_types.h"
+
+namespace content_creation {
+
+// Contains the information required to be able to render a note.
+class NoteTemplate {
+ public:
+ explicit NoteTemplate(NoteTemplateIds id,
+ const std::string& localized_name,
+ const Background& background,
+ const TextStyle& text_style,
+ const FooterStyle& footer_style);
+
+ NoteTemplate(const NoteTemplate& other);
+
+ NoteTemplateIds id() const { return id_; }
+ const std::string localized_name() const { return localized_name_; }
+ const Background main_background() const { return main_background_; }
+ const TextStyle text_style() const { return text_style_; }
+ const FooterStyle footer_style() const { return footer_style_; }
+
+ private:
+ // The template's identifier.
+ NoteTemplateIds id_;
+
+ // Name of the template to be shown to the users.
+ std::string localized_name_;
+
+ // Styling of the main background.
+ Background main_background_;
+
+ // Styling of the main text.
+ TextStyle text_style_;
+
+ // Styling of the footer part.
+ FooterStyle footer_style_;
+};
+
+} // namespace content_creation
+
+#endif // COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_NOTE_TEMPLATE_H_
diff --git a/chromium/components/content_creation/notes/core/templates/template_constants.cc b/chromium/components/content_creation/notes/core/templates/template_constants.cc
new file mode 100644
index 00000000000..66fdae1081a
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/templates/template_constants.cc
@@ -0,0 +1,139 @@
+// Copyright 2021 The Chromium Authors. 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/content_creation/notes/core/templates/template_constants.h"
+
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace content_creation {
+namespace {
+
+const uint16_t k400Weight = 400;
+const uint16_t k700Weight = 700;
+
+const char kBebasNeueFontName[] = "Bebas Neue";
+const char kMansalvaFontName[] = "Mansalva";
+const char kRobotoCondensedFontName[] = "Roboto Condensed";
+const char kSourceSerifProFontName[] = "Source Serif Pro";
+
+const ARGBColor kGreen50Color = 0xFFE6F4EA;
+const ARGBColor kGreen900Color = 0xFF0D652D;
+const ARGBColor kGrey200Color = 0xFFE8EAED;
+const ARGBColor kGrey900Color = 0xFF202124;
+const ARGBColor kYellow400Color = 0xFFFCC934;
+
+const ARGBColor kWhiteColor = 0xFFFFFFFF;
+const ARGBColor kBlackColor = 0xFF000000;
+
+// White color with 0.7 opacity.
+const ARGBColor kSlightlyTransparentWhiteColor = 0xB3FFFFFF;
+
+// White color with 0.2 opacity.
+const ARGBColor kTransparentWhiteColor = 0x33FFFFFF;
+
+// Black color with 0.5 opacity.
+const ARGBColor kSlightlyTransparentBlackColor = 0x80000000;
+
+// Black color with 0.1 opacity.
+const ARGBColor kTransparentBlackColor = 0x1A000000;
+
+FooterStyle CreateLightBackgroundFooterStyle() {
+ return FooterStyle(
+ /*text_color=*/kSlightlyTransparentBlackColor,
+ /*logo_color=*/kTransparentBlackColor);
+}
+
+FooterStyle CreateDarkBackgroundFooterStyle() {
+ return FooterStyle(
+ /*text_color=*/kSlightlyTransparentWhiteColor,
+ /*logo_color=*/kTransparentWhiteColor);
+}
+
+} // namespace
+
+NoteTemplate GetClassicTemplate() {
+ return NoteTemplate(
+ /*id=*/NoteTemplateIds::kClassic,
+ l10n_util::GetStringUTF8(IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_CLASSIC),
+ Background(/*color=*/kGrey900Color),
+ TextStyle(kSourceSerifProFontName,
+ /*font_color=*/kWhiteColor, k700Weight,
+ /*all_caps=*/false, TextAlignment::kStart),
+ /*footer_style=*/CreateDarkBackgroundFooterStyle());
+}
+
+NoteTemplate GetFreshTemplate() {
+ return NoteTemplate(
+ /*id=*/NoteTemplateIds::kFresh,
+ l10n_util::GetStringUTF8(IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRESH),
+ Background(/*color=*/kGreen50Color),
+ TextStyle(kSourceSerifProFontName,
+ /*font_color=*/kGreen900Color, k400Weight,
+ /*all_caps=*/false, TextAlignment::kStart),
+ /*footer_style=*/CreateLightBackgroundFooterStyle());
+}
+
+NoteTemplate GetPowerfulTemplate() {
+ return NoteTemplate(
+ /*id=*/NoteTemplateIds::kPowerful,
+ l10n_util::GetStringUTF8(
+ IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_POWERFUL),
+ Background(/*color=*/kYellow400Color),
+ TextStyle(kRobotoCondensedFontName,
+ /*font_color=*/kBlackColor, k400Weight,
+ /*all_caps=*/true, TextAlignment::kStart),
+ /*footer_style=*/CreateLightBackgroundFooterStyle());
+}
+
+NoteTemplate GetImpactfulTemplate() {
+ // TODO(crbug.com/1194168): Add text background color.
+ return NoteTemplate(
+ /*id=*/NoteTemplateIds::kImpactful,
+ l10n_util::GetStringUTF8(
+ IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_IMPACTFUL),
+ Background(/*color=*/kGrey200Color),
+ TextStyle(kBebasNeueFontName,
+ /*font_color=*/kBlackColor, k400Weight,
+ /*all_caps=*/true, TextAlignment::kCenter),
+ /*footer_style=*/CreateLightBackgroundFooterStyle());
+}
+
+NoteTemplate GetMonochromeTemplate() {
+ return NoteTemplate(
+ /*id=*/NoteTemplateIds::kMonochrome,
+ l10n_util::GetStringUTF8(
+ IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_MONOCHROME),
+ Background(/*color=*/kBlackColor),
+ TextStyle(kBebasNeueFontName,
+ /*font_color=*/kWhiteColor, k400Weight,
+ /*all_caps=*/true, TextAlignment::kCenter),
+ /*footer_style=*/CreateDarkBackgroundFooterStyle());
+}
+
+NoteTemplate GetBoldTemplate() {
+ // TODO(crbug.com/1194168): Add text background color.
+ return NoteTemplate(
+ /*id=*/NoteTemplateIds::kBold,
+ l10n_util::GetStringUTF8(IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_BOLD),
+ Background(/*color=*/kWhiteColor),
+ TextStyle(kBebasNeueFontName,
+ /*font_color=*/kBlackColor, k400Weight,
+ /*all_caps=*/true, TextAlignment::kCenter),
+ /*footer_style=*/CreateLightBackgroundFooterStyle());
+}
+
+NoteTemplate GetDreamyTemplate() {
+ return NoteTemplate(
+ /*id=*/NoteTemplateIds::kDreamy,
+ l10n_util::GetStringUTF8(IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_DREAMY),
+ Background(/*colors=*/{0xFFDB80B8, 0xFFF39FD3, 0xFFA89CED},
+ LinearGradientDirection::kTopToBottom),
+ TextStyle(kMansalvaFontName,
+ /*font_color=*/kWhiteColor, k400Weight,
+ /*all_caps=*/false, TextAlignment::kStart),
+ /*footer_style=*/CreateLightBackgroundFooterStyle());
+}
+
+} // namespace content_creation
diff --git a/chromium/components/content_creation/notes/core/templates/template_constants.h b/chromium/components/content_creation/notes/core/templates/template_constants.h
new file mode 100644
index 00000000000..9d82bdad709
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/templates/template_constants.h
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_TEMPLATE_CONSTANTS_H_
+#define COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_TEMPLATE_CONSTANTS_H_
+
+#include "components/content_creation/notes/core/templates/note_template.h"
+
+namespace content_creation {
+
+// TODO(crbug.com/1194168): Add missing templates: Friendly, Lovely, and Groovy.
+
+// Returns a NoteTemplate with the Classic style.
+NoteTemplate GetClassicTemplate();
+
+// Returns a NoteTemplate with the Fresh style.
+NoteTemplate GetFreshTemplate();
+
+// Returns a NoteTemplate with the Powerful style.
+NoteTemplate GetPowerfulTemplate();
+
+// Returns a NoteTemplate with the Impactful style.
+NoteTemplate GetImpactfulTemplate();
+
+// Returns a NoteTemplate with the Monochrome style.
+NoteTemplate GetMonochromeTemplate();
+
+// Returns a NoteTemplate with the Bold style.
+NoteTemplate GetBoldTemplate();
+
+// Returns a NoteTemplate with the Dreamy style.
+NoteTemplate GetDreamyTemplate();
+
+} // namespace content_creation
+
+#endif // COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_TEMPLATE_CONSTANTS_H_
diff --git a/chromium/components/content_creation/notes/core/templates/template_store.cc b/chromium/components/content_creation/notes/core/templates/template_store.cc
new file mode 100644
index 00000000000..2f00676f59b
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/templates/template_store.cc
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/content_creation/notes/core/templates/template_store.h"
+
+#include "base/bind.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/task_runner_util.h"
+#include "components/content_creation/notes/core/templates/template_constants.h"
+
+namespace content_creation {
+
+TemplateStore::TemplateStore()
+ : task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_BLOCKING})) {}
+
+TemplateStore::~TemplateStore() = default;
+
+void TemplateStore::GetTemplates(GetTemplatesCallback callback) {
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(), FROM_HERE,
+ base::BindOnce(&TemplateStore::BuildTemplates, base::Unretained(this)),
+ base::BindOnce(&TemplateStore::OnTemplatesReceived,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+std::vector<NoteTemplate> TemplateStore::BuildTemplates() {
+ return {GetClassicTemplate(), GetFreshTemplate(),
+ GetPowerfulTemplate(), GetImpactfulTemplate(),
+ GetMonochromeTemplate(), GetBoldTemplate(),
+ GetDreamyTemplate()};
+}
+
+void TemplateStore::OnTemplatesReceived(
+ GetTemplatesCallback callback,
+ std::vector<NoteTemplate> note_templates) {
+ std::move(callback).Run(note_templates);
+}
+
+} // namespace content_creation
diff --git a/chromium/components/content_creation/notes/core/templates/template_store.h b/chromium/components/content_creation/notes/core/templates/template_store.h
new file mode 100644
index 00000000000..898831af04f
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/templates/template_store.h
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_TEMPLATE_STORE_H_
+#define COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_TEMPLATE_STORE_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "base/supports_user_data.h"
+#include "components/content_creation/notes/core/templates/note_template.h"
+
+namespace content_creation {
+
+using GetTemplatesCallback =
+ base::OnceCallback<void(std::vector<NoteTemplate>)>;
+
+// Instance in charge of generating the ordered list of note templates to be
+// offered to the user.
+class TemplateStore {
+ public:
+ explicit TemplateStore();
+ virtual ~TemplateStore();
+
+ // Not copyable or movable.
+ TemplateStore(const TemplateStore&) = delete;
+ TemplateStore& operator=(const TemplateStore&) = delete;
+
+ // Gets the set of templates to be used for generating stylized notes. Will
+ // invoke |callback| with the results.
+ virtual void GetTemplates(GetTemplatesCallback callback);
+
+ protected:
+ // Function which generates the ordered list of templates to be offered to
+ // the user.
+ std::vector<NoteTemplate> BuildTemplates();
+
+ // This function is invoked when the store has successfully built the list
+ // of |note_templates|, and will send them to the user via |callback|.
+ void OnTemplatesReceived(GetTemplatesCallback callback,
+ std::vector<NoteTemplate> note_templates);
+
+ // Task runner delegating tasks to the ThreadPool.
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ base::WeakPtrFactory<TemplateStore> weak_ptr_factory_{this};
+};
+
+} // namespace content_creation
+
+#endif // COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_TEMPLATE_STORE_H_ \ No newline at end of file
diff --git a/chromium/components/content_creation/notes/core/templates/template_store_unittest.cc b/chromium/components/content_creation/notes/core/templates/template_store_unittest.cc
new file mode 100644
index 00000000000..4bbde029cf8
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/templates/template_store_unittest.cc
@@ -0,0 +1,62 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/content_creation/notes/core/templates/template_store.h"
+
+#include <unordered_set>
+#include <vector>
+
+#include "base/run_loop.h"
+#include "base/test/bind.h"
+#include "base/test/task_environment.h"
+#include "components/content_creation/notes/core/templates/note_template.h"
+#include "components/content_creation/notes/core/templates/template_types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content_creation {
+
+class TemplateStoreTest : public testing::Test {
+ void SetUp() override { template_store_ = std::make_unique<TemplateStore>(); }
+
+ protected:
+ void ValidateTemplates(const std::vector<NoteTemplate>& note_templates) {
+ std::unordered_set<NoteTemplateIds> ids_set;
+ for (const NoteTemplate& note_template : note_templates) {
+ EXPECT_LT(NoteTemplateIds::kUnknown, note_template.id());
+ EXPECT_GE(NoteTemplateIds::kMaxValue, note_template.id());
+ EXPECT_FALSE(note_template.localized_name().empty());
+ EXPECT_FALSE(note_template.text_style().font_name().empty());
+
+ // There should be no duplicated IDs.
+ EXPECT_TRUE(ids_set.find(note_template.id()) == ids_set.end());
+ ids_set.insert(note_template.id());
+ }
+ }
+
+ // Have to use TaskEnvironment since the TemplateStore posts tasks to the
+ // thread pool.
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+
+ std::unique_ptr<TemplateStore> template_store_;
+};
+
+// Tests that the store does return templates, and also validates the templates'
+// information.
+TEST_F(TemplateStoreTest, GetTemplatesSuccess) {
+ base::RunLoop run_loop;
+
+ template_store_->GetTemplates(base::BindLambdaForTesting(
+ [&run_loop, this](std::vector<NoteTemplate> templates) {
+ EXPECT_EQ(7U, templates.size());
+
+ ValidateTemplates(templates);
+
+ run_loop.Quit();
+ }));
+
+ run_loop.Run();
+}
+
+} // namespace content_creation
diff --git a/chromium/components/content_creation/notes/core/templates/template_types.cc b/chromium/components/content_creation/notes/core/templates/template_types.cc
new file mode 100644
index 00000000000..8336d4dbd8f
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/templates/template_types.cc
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/content_creation/notes/core/templates/template_types.h"
+
+#include "base/check.h"
+
+namespace content_creation {
+
+Background::Background(ARGBColor color)
+ : color_(color),
+ colors_(),
+ direction_(LinearGradientDirection::kInvalid),
+ is_linear_gradient_(false) {}
+
+Background::Background(const std::vector<ARGBColor>& colors,
+ LinearGradientDirection direction)
+ : color_(0U),
+ colors_(colors),
+ direction_(direction),
+ is_linear_gradient_(true) {
+ // Can't have a linear gradient with only one (or no) color.
+ DCHECK(colors_.size() > 1);
+}
+
+Background::Background(const Background& other) {
+ if (other.is_linear_gradient()) {
+ is_linear_gradient_ = true;
+ colors_ = *other.colors();
+ direction_ = other.direction();
+ } else {
+ is_linear_gradient_ = false;
+ color_ = other.color();
+ }
+}
+
+Background::~Background() = default;
+
+TextStyle::TextStyle(const std::string& font_name,
+ ARGBColor font_color,
+ uint16_t weight,
+ bool all_caps,
+ TextAlignment alignment)
+ : font_name_(font_name),
+ font_color_(font_color),
+ weight_(weight),
+ all_caps_(all_caps),
+ alignment_(alignment) {}
+
+FooterStyle::FooterStyle(ARGBColor text_color, ARGBColor logo_color)
+ : text_color_(text_color), logo_color_(logo_color) {}
+
+} // namespace content_creation
diff --git a/chromium/components/content_creation/notes/core/templates/template_types.h b/chromium/components/content_creation/notes/core/templates/template_types.h
new file mode 100644
index 00000000000..4b5f2fd01bc
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/templates/template_types.h
@@ -0,0 +1,113 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_TEMPLATE_TYPES_H_
+#define COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_TEMPLATE_TYPES_H_
+
+#include <string>
+#include <vector>
+
+namespace content_creation {
+
+using ARGBColor = uint32_t;
+
+// Represents all currently known templates.
+enum class NoteTemplateIds {
+ kUnknown = 0,
+ kClassic = 1,
+ kFriendly = 2,
+ kFresh = 3,
+ kPowerful = 4,
+ kImpactful = 5,
+ kLovely = 6,
+ kGroovy = 7,
+ kMonochrome = 8,
+ kBold = 9,
+ kDreamy = 10,
+
+ kMaxValue = kDreamy
+};
+
+// Represents the different supported linear gradient directions. Keep this enum
+// in sync with its Java counterpart of the same name.
+enum class LinearGradientDirection {
+ kInvalid = 0,
+ kTopToBottom = 1,
+ kTopRightToBottomLeft = 2,
+ kRightToLeft = 3,
+ kBottomRightToTopLeft = 4,
+};
+
+// Represents a colored background.
+class Background {
+ public:
+ // Creates a solid colored background.
+ explicit Background(ARGBColor color);
+
+ // Creates a linear gradient background.
+ explicit Background(const std::vector<ARGBColor>& colors,
+ LinearGradientDirection direction);
+
+ Background(const Background& other);
+
+ ~Background();
+
+ ARGBColor color() const { return color_; }
+
+ const std::vector<ARGBColor>* colors() const { return &colors_; }
+ LinearGradientDirection direction() const { return direction_; }
+
+ bool is_linear_gradient() const { return is_linear_gradient_; }
+
+ private:
+ ARGBColor color_;
+
+ std::vector<ARGBColor> colors_;
+ LinearGradientDirection direction_;
+
+ bool is_linear_gradient_;
+};
+
+// Represents the different supported text alignment. Keep this enum in sync with its Java
+// counterpart of the same name.
+enum class TextAlignment { kInvalid = 0, kStart = 1, kCenter = 2, kEnd = 3 };
+
+// Parameters dictating how to display text.
+class TextStyle {
+ public:
+ explicit TextStyle(const std::string& font_name,
+ ARGBColor font_color,
+ uint16_t weight,
+ bool all_caps,
+ TextAlignment alignment);
+
+ const std::string font_name() const { return font_name_; }
+ ARGBColor font_color() const { return font_color_; }
+ uint16_t weight() const { return weight_; }
+ bool all_caps() const { return all_caps_; }
+ TextAlignment alignment() const { return alignment_; }
+
+ private:
+ std::string font_name_;
+ ARGBColor font_color_;
+ uint16_t weight_;
+ bool all_caps_;
+ TextAlignment alignment_;
+};
+
+// Parameters to control the appearance of the elements in a note's footer.
+class FooterStyle {
+ public:
+ explicit FooterStyle(ARGBColor text_color, ARGBColor logo_color);
+
+ ARGBColor text_color() const { return text_color_; }
+ ARGBColor logo_color() const { return logo_color_; }
+
+ private:
+ ARGBColor text_color_;
+ ARGBColor logo_color_;
+};
+
+} // namespace content_creation
+
+#endif // COMPONENTS_CONTENT_CREATION_NOTES_CORE_TEMPLATES_TEMPLATE_TYPES_H_
diff --git a/chromium/components/content_creation/notes/core/test/BUILD.gn b/chromium/components/content_creation/notes/core/test/BUILD.gn
new file mode 100644
index 00000000000..d990ddcb56e
--- /dev/null
+++ b/chromium/components/content_creation/notes/core/test/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("test_support") {
+ testonly = true
+ sources = [
+ "mocks.cc",
+ "mocks.h",
+ ]
+ deps = [
+ "//base",
+ "//components/content_creation/notes/core/templates",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/content_creation_strings.grdp b/chromium/components/content_creation_strings.grdp
new file mode 100644
index 00000000000..7c97e48b447
--- /dev/null
+++ b/chromium/components/content_creation_strings.grdp
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+
+<if expr="is_android">
+ <!-- Note Template Names, currently only used on Android. -->
+ <message name="IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_CLASSIC" desc="Name for a styled template which creates a nice looking note from text. The name is loosely connected with the font and color of the template. [CHAR_LIMIT=25]">
+ Classic
+ </message>
+ <message name="IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRIENDLY" desc="Name for a styled template which creates a nice looking note from text. The name is loosely connected with the font and color of the template. [CHAR_LIMIT=25]">
+ Friendly
+ </message>
+ <message name="IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRESH" desc="Name for a styled template which creates a nice looking note from text. The name is loosely connected with the font and color of the template. [CHAR_LIMIT=25]">
+ Fresh
+ </message>
+ <message name="IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_POWERFUL" desc="Name for a styled template which creates a nice looking note from text. The name is loosely connected with the font and color of the template. [CHAR_LIMIT=25]">
+ Powerful
+ </message>
+ <message name="IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_IMPACTFUL" desc="Name for a styled template which creates a nice looking note from text. The name is loosely connected with the font and color of the template. [CHAR_LIMIT=25]">
+ Impactful
+ </message>
+ <message name="IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_LOVELY" desc="Name for a styled template which creates a nice looking note from text. The name is loosely connected with the font and color of the template. [CHAR_LIMIT=25]">
+ Lovely
+ </message>
+ <message name="IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_GROOVY" desc="Name for a styled template which creates a nice looking note from text. The name is loosely connected with the font and color of the template. [CHAR_LIMIT=25]">
+ Groovy
+ </message>
+ <message name="IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_MONOCHROME" desc="Name for a styled template which creates a nice looking note from text. The name is loosely connected with the font and color of the template. [CHAR_LIMIT=25]">
+ Monochrome
+ </message>
+ <message name="IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_BOLD" desc="Name for a styled template which creates a nice looking note from text. The name is loosely connected with the font and color of the template. [CHAR_LIMIT=25]">
+ Bold
+ </message>
+ <message name="IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_DREAMY" desc="Name for a styled template which creates a nice looking note from text. The name is loosely connected with the font and color of the template. [CHAR_LIMIT=25]">
+ Dreamy
+ </message>
+</if>
+
+</grit-part>
diff --git a/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_BOLD.png.sha1 b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_BOLD.png.sha1
new file mode 100644
index 00000000000..3bce3c472f7
--- /dev/null
+++ b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_BOLD.png.sha1
@@ -0,0 +1 @@
+fe59f2de1e18f6fe91cb1f01c5c8937f9ec1fa27 \ No newline at end of file
diff --git a/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_CLASSIC.png.sha1 b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_CLASSIC.png.sha1
new file mode 100644
index 00000000000..fe404254acd
--- /dev/null
+++ b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_CLASSIC.png.sha1
@@ -0,0 +1 @@
+af50f1404d15631c99e56eed776219be2cc8cbb2 \ No newline at end of file
diff --git a/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_DREAMY.png.sha1 b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_DREAMY.png.sha1
new file mode 100644
index 00000000000..b4daf51000f
--- /dev/null
+++ b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_DREAMY.png.sha1
@@ -0,0 +1 @@
+f6f8ef6e099496dc9e32bf86663fe2b7b8aa5db3 \ No newline at end of file
diff --git a/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRESH.png.sha1 b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRESH.png.sha1
new file mode 100644
index 00000000000..c812ef2fcaf
--- /dev/null
+++ b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRESH.png.sha1
@@ -0,0 +1 @@
+433f4d040b9688535c32ffc08210345aaf9b51e6 \ No newline at end of file
diff --git a/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRIENDLY.png.sha1 b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRIENDLY.png.sha1
new file mode 100644
index 00000000000..fbe1b84322e
--- /dev/null
+++ b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_FRIENDLY.png.sha1
@@ -0,0 +1 @@
+00c65bdebb3c76db095bd1fea74b16aef9f3cca9 \ No newline at end of file
diff --git a/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_GROOVY.png.sha1 b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_GROOVY.png.sha1
new file mode 100644
index 00000000000..a4026b77f82
--- /dev/null
+++ b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_GROOVY.png.sha1
@@ -0,0 +1 @@
+06201317a487f27b40f04de4a15577e6240d6b54 \ No newline at end of file
diff --git a/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_IMPACTFUL.png.sha1 b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_IMPACTFUL.png.sha1
new file mode 100644
index 00000000000..e5d44027d72
--- /dev/null
+++ b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_IMPACTFUL.png.sha1
@@ -0,0 +1 @@
+b4dd462e915eef684826514e6aebdd8c7c353655 \ No newline at end of file
diff --git a/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_LOVELY.png.sha1 b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_LOVELY.png.sha1
new file mode 100644
index 00000000000..3e60819f98e
--- /dev/null
+++ b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_LOVELY.png.sha1
@@ -0,0 +1 @@
+52c280faaef8fb439342573f5ee8a13652f52fab \ No newline at end of file
diff --git a/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_MONOCHROME.png.sha1 b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_MONOCHROME.png.sha1
new file mode 100644
index 00000000000..094812a6112
--- /dev/null
+++ b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_MONOCHROME.png.sha1
@@ -0,0 +1 @@
+b7f1a4e5640f98b4cc232c8e4f1ce7afa057f61f \ No newline at end of file
diff --git a/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_POWERFUL.png.sha1 b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_POWERFUL.png.sha1
new file mode 100644
index 00000000000..84e1eba4794
--- /dev/null
+++ b/chromium/components/content_creation_strings_grdp/IDS_CONTENT_CREATION_NOTE_TEMPLATE_NAME_POWERFUL.png.sha1
@@ -0,0 +1 @@
+8619cdbfc0d0adb077032ecffb9842d8392c3312 \ No newline at end of file
diff --git a/chromium/components/content_settings/android/cookie_controls_bridge.h b/chromium/components/content_settings/android/cookie_controls_bridge.h
index 67fee8c97e1..62e0a3a2153 100644
--- a/chromium/components/content_settings/android/cookie_controls_bridge.h
+++ b/chromium/components/content_settings/android/cookie_controls_bridge.h
@@ -6,11 +6,11 @@
#define COMPONENTS_CONTENT_SETTINGS_ANDROID_COOKIE_CONTROLS_BRIDGE_H_
#include "base/android/jni_weak_ref.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "components/content_settings/browser/ui/cookie_controls_controller.h"
#include "components/content_settings/browser/ui/cookie_controls_view.h"
#include "components/content_settings/core/common/cookie_controls_status.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content_settings {
@@ -49,8 +49,8 @@ class CookieControlsBridge : public CookieControlsView {
CookieControlsStatus status_ = CookieControlsStatus::kUninitialized;
CookieControlsEnforcement enforcement_ =
CookieControlsEnforcement::kNoEnforcement;
- base::Optional<int> blocked_cookies_;
- base::Optional<int> allowed_cookies_;
+ absl::optional<int> blocked_cookies_;
+ absl::optional<int> allowed_cookies_;
std::unique_ptr<CookieControlsController> controller_;
base::ScopedObservation<CookieControlsController, CookieControlsView>
observation_{this};
diff --git a/chromium/components/content_settings/browser/BUILD.gn b/chromium/components/content_settings/browser/BUILD.gn
index 8f8045a483b..4a1cc00f444 100644
--- a/chromium/components/content_settings/browser/BUILD.gn
+++ b/chromium/components/content_settings/browser/BUILD.gn
@@ -46,6 +46,7 @@ source_set("unit_tests") {
"//base",
"//components/content_settings/core/browser",
"//components/security_state/core",
+ "//components/services/storage/public/cpp",
"//components/sync_preferences:test_support",
"//content/test:test_support",
"//net",
diff --git a/chromium/components/content_settings/browser/DEPS b/chromium/components/content_settings/browser/DEPS
index cb87cc1c81c..464bc8ad67a 100644
--- a/chromium/components/content_settings/browser/DEPS
+++ b/chromium/components/content_settings/browser/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+components/browsing_data/content",
"+components/page_load_metrics/browser",
"+components/security_state/core",
+ "+components/services/storage/public/cpp",
"+components/sync_preferences",
"+components/url_formatter",
"+content/public/browser",
diff --git a/chromium/components/content_settings/browser/page_specific_content_settings.cc b/chromium/components/content_settings/browser/page_specific_content_settings.cc
index 42e88358c35..0a206ad47b3 100644
--- a/chromium/components/content_settings/browser/page_specific_content_settings.cc
+++ b/chromium/components/content_settings/browser/page_specific_content_settings.cc
@@ -10,7 +10,6 @@
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/memory/ptr_util.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -39,6 +38,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/content_constants.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "url/origin.h"
@@ -118,10 +118,9 @@ PageSpecificContentSettings::WebContentsHandler::WebContentsHandler(
map_(delegate_->GetSettingsMap()) {
DCHECK(!PageSpecificContentSettings::GetForCurrentDocument(
web_contents->GetMainFrame()));
- content::SetRenderDocumentHostUserData(
- web_contents->GetMainFrame(), PageSpecificContentSettings::UserDataKey(),
- base::WrapUnique(
- new PageSpecificContentSettings(*this, delegate_.get())));
+ content::RenderDocumentHostUserData<PageSpecificContentSettings>::
+ CreateForCurrentDocument(web_contents->GetMainFrame(), *this,
+ delegate_.get());
}
PageSpecificContentSettings::WebContentsHandler::~WebContentsHandler() {
@@ -146,16 +145,13 @@ void PageSpecificContentSettings::WebContentsHandler::
void PageSpecificContentSettings::WebContentsHandler::OnCookiesAccessed(
content::NavigationHandle* navigation,
const content::CookieAccessDetails& details) {
- auto it = inflight_navigation_settings_.find(navigation);
- if (it != inflight_navigation_settings_.end()) {
- it->second.cookie_accesses.push_back(details);
+ if (WillNavigationCreateNewPageSpecificContentSettingsOnCommit(navigation)) {
+ auto* inflight_navigation_settings =
+ content::NavigationHandleUserData<InflightNavigationContentSettings>::
+ GetOrCreateForNavigationHandle(*navigation);
+ inflight_navigation_settings->cookie_accesses.push_back(details);
return;
}
- // TODO(carlscab): We should be able to
- // DHECK(!WillNavigationCreateNewPageSpecificContentSettingsOnCommit) here,
- // but there is still code that starts a navigation before attaching the tab
- // helpers in DevConsole related code. So we miss the DidStartNavigation event
- // for those navigations. (https://crbug.com/1095576)
OnCookiesAccessed(web_contents()->GetMainFrame(), details);
}
@@ -174,17 +170,14 @@ void PageSpecificContentSettings::WebContentsHandler::OnServiceWorkerAccessed(
content::AllowServiceWorkerResult allowed) {
DCHECK(scope.is_valid());
- auto it = inflight_navigation_settings_.find(navigation);
- if (it != inflight_navigation_settings_.end()) {
- it->second.service_worker_accesses.emplace_back(
+ if (WillNavigationCreateNewPageSpecificContentSettingsOnCommit(navigation)) {
+ auto* inflight_navigation_settings =
+ content::NavigationHandleUserData<InflightNavigationContentSettings>::
+ GetOrCreateForNavigationHandle(*navigation);
+ inflight_navigation_settings->service_worker_accesses.emplace_back(
std::make_pair(scope, allowed));
return;
}
- // TODO(carlscab): We should be able to
- // DHECK(!WillNavigationCreateNewPageSpecificContentSettingsOnCommit) here,
- // but there is still code that starts a navigation before attaching the tab
- // helpers in DevConsole related code. So we miss the DidStartNavigation event
- // for those navigations.
OnServiceWorkerAccessed(web_contents()->GetMainFrame(), scope, allowed);
}
@@ -198,17 +191,6 @@ void PageSpecificContentSettings::WebContentsHandler::OnServiceWorkerAccessed(
tscs->OnServiceWorkerAccessed(scope, allowed);
}
-void PageSpecificContentSettings::WebContentsHandler::DidStartNavigation(
- content::NavigationHandle* navigation_handle) {
- if (!WillNavigationCreateNewPageSpecificContentSettingsOnCommit(
- navigation_handle)) {
- return;
- }
-
- inflight_navigation_settings_.insert(
- std::make_pair(navigation_handle, InflightNavigationContentSettings()));
-}
-
void PageSpecificContentSettings::WebContentsHandler::ReadyToCommitNavigation(
content::NavigationHandle* navigation_handle) {
if (!WillNavigationCreateNewPageSpecificContentSettingsOnCommit(
@@ -219,39 +201,29 @@ void PageSpecificContentSettings::WebContentsHandler::ReadyToCommitNavigation(
// There may be content settings that were updated for the navigated URL.
// These would not have been sent before if we're navigating cross-origin.
// Ensure up to date rules are sent before navigation commits.
- MaybeSendRendererContentSettingsRules(
- navigation_handle->GetWebContents()->GetMainFrame(), map_,
- delegate_.get());
+ MaybeSendRendererContentSettingsRules(navigation_handle->GetRenderFrameHost(),
+ map_, delegate_.get());
}
void PageSpecificContentSettings::WebContentsHandler::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
if (!WillNavigationCreateNewPageSpecificContentSettingsOnCommit(
- navigation_handle)) {
+ navigation_handle) ||
+ !navigation_handle->HasCommitted()) {
return;
}
- if (!navigation_handle->HasCommitted()) {
- inflight_navigation_settings_.erase(navigation_handle);
- return;
- }
+ content::RenderDocumentHostUserData<PageSpecificContentSettings>::
+ CreateForCurrentDocument(navigation_handle->GetRenderFrameHost(), *this,
+ delegate_.get());
+ InflightNavigationContentSettings* inflight_settings =
+ content::NavigationHandleUserData<InflightNavigationContentSettings>::
+ GetForNavigationHandle(*navigation_handle);
- auto tscs =
- base::WrapUnique(new PageSpecificContentSettings(*this, delegate_.get()));
-
- // TODO(carlscab): This sort of internal. Maybe add a
- // RenderDocumentHostUserData::Create(RenderFrameHost* rfh, Params...)
- content::SetRenderDocumentHostUserData(
- navigation_handle->GetRenderFrameHost(),
- PageSpecificContentSettings::UserDataKey(), std::move(tscs));
-
- auto it = inflight_navigation_settings_.find(navigation_handle);
- if (it != inflight_navigation_settings_.end()) {
+ if (inflight_settings) {
TransferNavigationContentSettingsToCommittedDocument(
- it->second, navigation_handle->GetRenderFrameHost());
- inflight_navigation_settings_.erase(it);
+ *inflight_settings, navigation_handle->GetRenderFrameHost());
}
-
delegate_->UpdateLocationBar();
}
@@ -280,29 +252,19 @@ void PageSpecificContentSettings::WebContentsHandler::
observer.OnSiteDataAccessed();
}
-PageSpecificContentSettings::WebContentsHandler::
- InflightNavigationContentSettings::InflightNavigationContentSettings() =
- default;
-PageSpecificContentSettings::WebContentsHandler::
- InflightNavigationContentSettings::InflightNavigationContentSettings(
- const InflightNavigationContentSettings&) = default;
-PageSpecificContentSettings::WebContentsHandler::
- InflightNavigationContentSettings::InflightNavigationContentSettings(
- InflightNavigationContentSettings&&) = default;
+PageSpecificContentSettings::InflightNavigationContentSettings::
+ InflightNavigationContentSettings(content::NavigationHandle&) {}
-PageSpecificContentSettings::WebContentsHandler::
- InflightNavigationContentSettings::~InflightNavigationContentSettings() =
- default;
+PageSpecificContentSettings::InflightNavigationContentSettings::
+ ~InflightNavigationContentSettings() = default;
-PageSpecificContentSettings::WebContentsHandler::
- InflightNavigationContentSettings&
- PageSpecificContentSettings::WebContentsHandler::
- InflightNavigationContentSettings::operator=(
- InflightNavigationContentSettings&&) = default;
+NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(
+ PageSpecificContentSettings::InflightNavigationContentSettings)
WEB_CONTENTS_USER_DATA_KEY_IMPL(PageSpecificContentSettings::WebContentsHandler)
PageSpecificContentSettings::PageSpecificContentSettings(
+ content::RenderFrameHost*,
PageSpecificContentSettings::WebContentsHandler& handler,
Delegate* delegate)
: handler_(handler),
@@ -426,13 +388,13 @@ void PageSpecificContentSettings::SharedWorkerAccessed(
int render_frame_id,
const GURL& worker_url,
const std::string& name,
- const url::Origin& constructor_origin,
+ const storage::StorageKey& storage_key,
bool blocked_by_policy) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PageSpecificContentSettings* settings =
GetForFrame(render_process_id, render_frame_id);
if (settings)
- settings->OnSharedWorkerAccessed(worker_url, name, constructor_origin,
+ settings->OnSharedWorkerAccessed(worker_url, name, storage_key,
blocked_by_policy);
}
@@ -650,16 +612,16 @@ void PageSpecificContentSettings::OnServiceWorkerAccessed(
void PageSpecificContentSettings::OnSharedWorkerAccessed(
const GURL& worker_url,
const std::string& name,
- const url::Origin& constructor_origin,
+ const storage::StorageKey& storage_key,
bool blocked_by_policy) {
DCHECK(worker_url.is_valid());
if (blocked_by_policy) {
blocked_local_shared_objects_.shared_workers()->AddSharedWorker(
- worker_url, name, constructor_origin);
+ worker_url, name, storage_key);
OnContentBlocked(ContentSettingsType::COOKIES);
} else {
allowed_local_shared_objects_.shared_workers()->AddSharedWorker(
- worker_url, name, constructor_origin);
+ worker_url, name, storage_key);
OnContentAllowed(ContentSettingsType::COOKIES);
}
}
@@ -696,7 +658,7 @@ void PageSpecificContentSettings::OnFileSystemAccessed(const GURL& url,
handler_.NotifySiteDataObservers();
}
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
void PageSpecificContentSettings::OnProtectedMediaIdentifierPermissionSet(
const GURL& requesting_origin,
bool allowed) {
diff --git a/chromium/components/content_settings/browser/page_specific_content_settings.h b/chromium/components/content_settings/browser/page_specific_content_settings.h
index 4e58ce721a4..06b13636868 100644
--- a/chromium/components/content_settings/browser/page_specific_content_settings.h
+++ b/chromium/components/content_settings/browser/page_specific_content_settings.h
@@ -26,6 +26,7 @@
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "content/public/browser/allow_service_worker_result.h"
+#include "content/public/browser/navigation_handle_user_data.h"
#include "content/public/browser/render_document_host_user_data.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents_observer.h"
@@ -35,6 +36,10 @@ namespace content {
class NavigationHandle;
}
+namespace storage {
+class StorageKey;
+} // namespace storage
+
namespace url {
class Origin;
} // namespace url
@@ -248,7 +253,7 @@ class PageSpecificContentSettings
int render_frame_id,
const GURL& worker_url,
const std::string& name,
- const url::Origin& constructor_origin,
+ const storage::StorageKey& storage_key,
bool blocked_by_policy);
static content::WebContentsObserver* GetWebContentsObserverForTest(
@@ -351,10 +356,10 @@ class PageSpecificContentSettings
void OnCacheStorageAccessed(const GURL& url, bool blocked_by_policy);
void OnSharedWorkerAccessed(const GURL& worker_url,
const std::string& name,
- const url::Origin& constructor_origin,
+ const storage::StorageKey& storage_key,
bool blocked_by_policy);
void OnWebDatabaseAccessed(const GURL& url, bool blocked_by_policy);
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
void OnProtectedMediaIdentifierPermissionSet(const GURL& requesting_frame,
bool allowed);
#endif
@@ -386,6 +391,31 @@ class PageSpecificContentSettings
private:
friend class content::RenderDocumentHostUserData<PageSpecificContentSettings>;
+ // Keeps track of cookie and service worker access during a navigation.
+ // These types of access can happen for the current page or for a new
+ // navigation (think cookies sent in the HTTP request or service worker
+ // being run to serve a fetch request). A navigation might fail to
+ // commit in which case we have to handle it as if it had never
+ // occurred. So we cache all cookies and service worker accesses that
+ // happen during a navigation and only apply the changes if the
+ // navigation commits.
+ class InflightNavigationContentSettings
+ : public content::NavigationHandleUserData<
+ InflightNavigationContentSettings> {
+ public:
+ ~InflightNavigationContentSettings() override;
+ std::vector<content::CookieAccessDetails> cookie_accesses;
+ std::vector<std::pair<GURL, content::AllowServiceWorkerResult>>
+ service_worker_accesses;
+
+ private:
+ explicit InflightNavigationContentSettings(
+ content::NavigationHandle& navigation_handle);
+ friend class content::NavigationHandleUserData<
+ InflightNavigationContentSettings>;
+ NAVIGATION_HANDLE_USER_DATA_KEY_DECL();
+ };
+
// This class attaches to WebContents to listen to events and route them to
// appropriate PageSpecificContentSettings, store navigation related events
// until the navigation finishes and then transferring the
@@ -412,30 +442,6 @@ class PageSpecificContentSettings
private:
friend class content::WebContentsUserData<WebContentsHandler>;
- // Keeps track of cookie and service worker access during a navigation.
- // These types of access can happen for the current page or for a new
- // navigation (think cookies sent in the HTTP request or service worker
- // being run to serve a fetch request). A navigation might fail to
- // commit in which case we have to handle it as if it had never
- // occurred. So we cache all cookies and service worker accesses that
- // happen during a navigation and only apply the changes if the
- // navigation commits.
- struct InflightNavigationContentSettings {
- InflightNavigationContentSettings();
- InflightNavigationContentSettings(
- const InflightNavigationContentSettings&);
- InflightNavigationContentSettings(InflightNavigationContentSettings&&);
-
- ~InflightNavigationContentSettings();
-
- InflightNavigationContentSettings& operator=(
- InflightNavigationContentSettings&&);
-
- std::vector<content::CookieAccessDetails> cookie_accesses;
- std::vector<std::pair<GURL, content::AllowServiceWorkerResult>>
- service_worker_accesses;
- };
-
// Applies all stored events for the given navigation to the current main
// document.
void TransferNavigationContentSettingsToCommittedDocument(
@@ -443,8 +449,6 @@ class PageSpecificContentSettings
content::RenderFrameHost* rfh);
// content::WebContentsObserver overrides.
- void DidStartNavigation(
- content::NavigationHandle* navigation_handle) override;
void ReadyToCommitNavigation(
content::NavigationHandle* navigation_handle) override;
void DidFinishNavigation(
@@ -479,16 +483,11 @@ class PageSpecificContentSettings
// All currently registered |SiteDataObserver|s.
base::ObserverList<SiteDataObserver>::Unchecked observer_list_;
- // Keeps track of currently inflight navigations. Updates for those are
- // kept aside until the navigation commits.
- std::unordered_map<content::NavigationHandle*,
- InflightNavigationContentSettings>
- inflight_navigation_settings_;
-
WEB_CONTENTS_USER_DATA_KEY_DECL();
};
explicit PageSpecificContentSettings(
+ content::RenderFrameHost* rfh,
PageSpecificContentSettings::WebContentsHandler& handler,
Delegate* delegate);
diff --git a/chromium/components/content_settings/browser/page_specific_content_settings_unittest.cc b/chromium/components/content_settings/browser/page_specific_content_settings_unittest.cc
index e36561cd1ba..d5ea6c0bf39 100644
--- a/chromium/components/content_settings/browser/page_specific_content_settings_unittest.cc
+++ b/chromium/components/content_settings/browser/page_specific_content_settings_unittest.cc
@@ -7,13 +7,13 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/content_settings/browser/test_page_specific_content_settings_delegate.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/security_state/core/security_state.h"
+#include "components/services/storage/public/cpp/storage_key.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/mock_navigation_handle.h"
@@ -23,6 +23,7 @@
#include "net/cookies/cookie_options.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content_settings {
namespace {
@@ -99,7 +100,7 @@ TEST_F(PageSpecificContentSettingsTest, BlockedContent) {
// popup.
GURL origin("http://google.com");
std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
- origin, "A=B", base::Time::Now(), base::nullopt /* server_time */));
+ origin, "A=B", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie1);
GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
{content::CookieAccessDetails::Type::kChange,
@@ -146,7 +147,7 @@ TEST_F(PageSpecificContentSettingsTest, BlockedContent) {
// Block a cookie.
std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
- origin, "C=D", base::Time::Now(), base::nullopt /* server_time */));
+ origin, "C=D", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie2);
GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
{content::CookieAccessDetails::Type::kChange,
@@ -233,7 +234,7 @@ TEST_F(PageSpecificContentSettingsTest, AllowedContent) {
// Record a cookie.
GURL origin("http://google.com");
std::unique_ptr<net::CanonicalCookie> cookie1(net::CanonicalCookie::Create(
- origin, "A=B", base::Time::Now(), base::nullopt /* server_time */));
+ origin, "A=B", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie1);
GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
{content::CookieAccessDetails::Type::kChange,
@@ -247,7 +248,7 @@ TEST_F(PageSpecificContentSettingsTest, AllowedContent) {
// Record a blocked cookie.
std::unique_ptr<net::CanonicalCookie> cookie2(net::CanonicalCookie::Create(
- origin, "C=D", base::Time::Now(), base::nullopt /* server_time */));
+ origin, "C=D", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie2);
GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
{content::CookieAccessDetails::Type::kChange,
@@ -288,7 +289,7 @@ TEST_F(PageSpecificContentSettingsTest, SiteDataObserver) {
bool blocked_by_policy = false;
GURL origin("http://google.com");
std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
- origin, "A=B", base::Time::Now(), base::nullopt /* server_time */));
+ origin, "A=B", base::Time::Now(), absl::nullopt /* server_time */));
ASSERT_TRUE(cookie);
GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
{content::CookieAccessDetails::Type::kChange,
@@ -301,7 +302,7 @@ TEST_F(PageSpecificContentSettingsTest, SiteDataObserver) {
std::unique_ptr<net::CanonicalCookie> other_cookie(
net::CanonicalCookie::Create(GURL("http://google.com"),
"CookieName=CookieValue", base::Time::Now(),
- base::nullopt /* server_time */));
+ absl::nullopt /* server_time */));
ASSERT_TRUE(other_cookie);
cookie_list.push_back(*other_cookie);
@@ -326,7 +327,7 @@ TEST_F(PageSpecificContentSettingsTest, LocalSharedObjectsContainer) {
bool blocked_by_policy = false;
auto cookie = net::CanonicalCookie::Create(GURL("http://google.com"), "k=v",
base::Time::Now(),
- base::nullopt /* server_time */);
+ absl::nullopt /* server_time */);
GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
{content::CookieAccessDetails::Type::kRead,
GURL("http://google.com"),
@@ -343,7 +344,8 @@ TEST_F(PageSpecificContentSettingsTest, LocalSharedObjectsContainer) {
blocked_by_policy);
content_settings->OnSharedWorkerAccessed(
GURL("http://youtube.com/worker.js"), "worker",
- url::Origin::Create(GURL("https://youtube.com")), blocked_by_policy);
+ storage::StorageKey(url::Origin::Create(GURL("https://youtube.com"))),
+ blocked_by_policy);
const auto& objects = content_settings->allowed_local_shared_objects();
EXPECT_EQ(6u, objects.GetObjectCount());
@@ -363,16 +365,16 @@ TEST_F(PageSpecificContentSettingsTest, LocalSharedObjectsContainerCookie) {
bool blocked_by_policy = false;
auto cookie1 = net::CanonicalCookie::Create(GURL("http://google.com"), "k1=v",
base::Time::Now(),
- base::nullopt /* server_time */);
+ absl::nullopt /* server_time */);
auto cookie2 = net::CanonicalCookie::Create(
GURL("http://www.google.com"), "k2=v; Domain=google.com",
- base::Time::Now(), base::nullopt /* server_time */);
+ base::Time::Now(), absl::nullopt /* server_time */);
auto cookie3 = net::CanonicalCookie::Create(
GURL("http://www.google.com"), "k3=v; Domain=.google.com",
- base::Time::Now(), base::nullopt /* server_time */);
+ base::Time::Now(), absl::nullopt /* server_time */);
auto cookie4 = net::CanonicalCookie::Create(
GURL("http://www.google.com"), "k4=v; Domain=.www.google.com",
- base::Time::Now(), base::nullopt /* server_time */);
+ base::Time::Now(), absl::nullopt /* server_time */);
GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
{content::CookieAccessDetails::Type::kRead,
GURL("http://www.google.com"),
@@ -382,7 +384,7 @@ TEST_F(PageSpecificContentSettingsTest, LocalSharedObjectsContainerCookie) {
auto cookie5 = net::CanonicalCookie::Create(GURL("https://www.google.com"),
"k5=v", base::Time::Now(),
- base::nullopt /* server_time */);
+ absl::nullopt /* server_time */);
GetHandle()->OnCookiesAccessed(web_contents()->GetMainFrame(),
{content::CookieAccessDetails::Type::kRead,
GURL("https://www.google.com"),
diff --git a/chromium/components/content_settings/common/DIR_METADATA b/chromium/components/content_settings/common/DIR_METADATA
deleted file mode 100644
index 9578a5d9492..00000000000
--- a/chromium/components/content_settings/common/DIR_METADATA
+++ /dev/null
@@ -1,4 +0,0 @@
-monorail {
- component: "Internals>Permissions>Model"
-}
-team_email: "permissions-dev@chromium.org"
diff --git a/chromium/components/content_settings/core/browser/content_settings_default_provider.cc b/chromium/components/content_settings/core/browser/content_settings_default_provider.cc
index 4b4c23346ec..cbfaabb1c41 100644
--- a/chromium/components/content_settings/core/browser/content_settings_default_provider.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_default_provider.cc
@@ -13,6 +13,7 @@
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
#include "components/content_settings/core/browser/content_settings_info.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
#include "components/content_settings/core/browser/content_settings_rule.h"
@@ -47,14 +48,16 @@ const char kObsoletePluginsDataDefaultPref[] =
#endif // !defined(OS_ANDROID)
#endif // !defined(OS_IOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
+// This setting was moved and should be migrated on profile startup.
+const char kDeprecatedEnableDRM[] = "settings.privacy.drm_enabled";
+#endif // BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
+
ContentSetting GetDefaultValue(const WebsiteSettingsInfo* info) {
const base::Value* initial_default = info->initial_default_value();
if (!initial_default)
return CONTENT_SETTING_DEFAULT;
- int result = 0;
- bool success = initial_default->GetAsInteger(&result);
- DCHECK(success);
- return static_cast<ContentSetting>(result);
+ return static_cast<ContentSetting>(initial_default->GetInt());
}
ContentSetting GetDefaultValue(ContentSettingsType type) {
@@ -123,6 +126,10 @@ void DefaultProvider::RegisterProfilePrefs(
registry->RegisterIntegerPref(kObsoletePluginsDefaultPref, 0);
#endif // !defined(OS_ANDROID)
#endif // !defined(OS_IOS)
+
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
+ registry->RegisterBooleanPref(kDeprecatedEnableDRM, true);
+#endif // BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
}
DefaultProvider::DefaultProvider(PrefService* prefs, bool off_the_record)
@@ -312,7 +319,7 @@ void DefaultProvider::ChangeSetting(ContentSettingsType content_type,
DCHECK(!info || !value ||
info->IsDefaultSettingValid(ValueToContentSetting(value)));
default_settings_[content_type] =
- value ? base::WrapUnique(value->DeepCopy())
+ value ? base::Value::ToUniquePtrValue(value->Clone())
: ContentSettingToValue(GetDefaultValue(content_type));
}
@@ -323,10 +330,7 @@ void DefaultProvider::WriteToPref(ContentSettingsType content_type,
return;
}
- int int_value = GetDefaultValue(content_type);
- bool is_integer = value->GetAsInteger(&int_value);
- DCHECK(is_integer);
- prefs_->SetInteger(GetPrefName(content_type), int_value);
+ prefs_->SetInteger(GetPrefName(content_type), value->GetInt());
}
void DefaultProvider::OnPreferenceChanged(const std::string& name) {
@@ -388,6 +392,22 @@ void DefaultProvider::DiscardOrMigrateObsoletePreferences() {
prefs_->ClearPref(kObsoletePluginsDataDefaultPref);
#endif // !defined(OS_ANDROID)
#endif // !defined(OS_IOS)
+
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
+ // TODO(crbug.com/1191642): Remove this migration logic in M100.
+ WebsiteSettingsRegistry* website_settings =
+ WebsiteSettingsRegistry::GetInstance();
+ const base::Value* deprecated_enable_drm_value =
+ prefs_->GetUserPrefValue(kDeprecatedEnableDRM);
+ if (deprecated_enable_drm_value) {
+ prefs_->SetInteger(
+ website_settings->Get(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER)
+ ->default_value_pref_name(),
+ deprecated_enable_drm_value->GetBool() ? CONTENT_SETTING_ALLOW
+ : CONTENT_SETTING_BLOCK);
+ }
+ prefs_->ClearPref(kDeprecatedEnableDRM);
+#endif // BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
}
} // namespace content_settings
diff --git a/chromium/components/content_settings/core/browser/content_settings_details.h b/chromium/components/content_settings/core/browser/content_settings_details.h
index fd36c0a7248..2d5cb58c88c 100644
--- a/chromium/components/content_settings/core/browser/content_settings_details.h
+++ b/chromium/components/content_settings/core/browser/content_settings_details.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_DETAILS_H_
#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_DETAILS_H_
-#include <string>
-
#include "base/macros.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
diff --git a/chromium/components/content_settings/core/browser/content_settings_info.cc b/chromium/components/content_settings/core/browser/content_settings_info.cc
index 1edd0f79385..836ae72a5ae 100644
--- a/chromium/components/content_settings/core/browser/content_settings_info.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_info.cc
@@ -42,14 +42,6 @@ bool ContentSettingsInfo::IsSettingValid(ContentSetting setting) const {
// IsDefaultSettingValid.
bool ContentSettingsInfo::IsDefaultSettingValid(ContentSetting setting) const {
ContentSettingsType type = website_settings_info_->type();
-#if BUILDFLAG(IS_CHROMEOS_ASH)
- // Don't support ALLOW for protected media default setting until migration.
- if (type == ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER &&
- setting == CONTENT_SETTING_ALLOW) {
- return false;
- }
-#endif
-
// Don't support ALLOW for the default media settings.
if ((type == ContentSettingsType::MEDIASTREAM_CAMERA ||
type == ContentSettingsType::MEDIASTREAM_MIC) &&
diff --git a/chromium/components/content_settings/core/browser/content_settings_observable_provider.h b/chromium/components/content_settings/core/browser/content_settings_observable_provider.h
index 29c44138993..1e2498ae2cf 100644
--- a/chromium/components/content_settings/core/browser/content_settings_observable_provider.h
+++ b/chromium/components/content_settings/core/browser/content_settings_observable_provider.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_OBSERVABLE_PROVIDER_H_
#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_OBSERVABLE_PROVIDER_H_
-#include <string>
-
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "components/content_settings/core/browser/content_settings_observer.h"
diff --git a/chromium/components/content_settings/core/browser/content_settings_observer.h b/chromium/components/content_settings/core/browser/content_settings_observer.h
index 569c3b3fe09..65354a417b4 100644
--- a/chromium/components/content_settings/core/browser/content_settings_observer.h
+++ b/chromium/components/content_settings/core/browser/content_settings_observer.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_OBSERVER_H_
#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_OBSERVER_H_
-#include <string>
-
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/content_settings_types.h"
diff --git a/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h b/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h
index 515f849db57..0aa7660f641 100644
--- a/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h
+++ b/chromium/components/content_settings/core/browser/content_settings_origin_identifier_value_map.h
@@ -9,7 +9,6 @@
#include <map>
#include <memory>
-#include <string>
#include "base/macros.h"
#include "base/time/time.h"
diff --git a/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc b/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc
index 7d8f647e848..9113d200c50 100644
--- a/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_policy_provider.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/containers/contains.h"
#include "base/json/json_reader.h"
+#include "base/logging.h"
#include "base/values.h"
#include "components/content_settings/core/browser/content_settings_info.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
@@ -342,7 +343,7 @@ void PolicyProvider::GetAutoSelectCertificateSettingsFromPreferences(
continue;
}
- base::Optional<base::Value> pattern_filter = base::JSONReader::Read(
+ absl::optional<base::Value> pattern_filter = base::JSONReader::Read(
pattern_filter_str.GetString(), base::JSON_ALLOW_TRAILING_COMMAS);
if (!pattern_filter || !pattern_filter->is_dict()) {
VLOG(1) << "Ignoring invalid certificate auto select setting. Reason:"
diff --git a/chromium/components/content_settings/core/browser/content_settings_pref.cc b/chromium/components/content_settings/core/browser/content_settings_pref.cc
index dcfb882f82c..f9189c9d34f 100644
--- a/chromium/components/content_settings/core/browser/content_settings_pref.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_pref.cc
@@ -14,6 +14,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
+#include "base/values.h"
#include "components/content_settings/core/browser/content_settings_info.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
#include "components/content_settings/core/browser/content_settings_rule.h"
@@ -39,12 +40,11 @@ bool IsValueAllowedForType(const base::Value* value, ContentSettingsType type) {
const content_settings::ContentSettingsInfo* info =
content_settings::ContentSettingsRegistry::GetInstance()->Get(type);
if (info) {
- int setting;
- if (!value->GetAsInteger(&setting))
+ if (!value->is_int())
return false;
- if (setting == CONTENT_SETTING_DEFAULT)
+ if (value->GetInt() == CONTENT_SETTING_DEFAULT)
return false;
- return info->IsSettingValid(IntToContentSetting(setting));
+ return info->IsSettingValid(IntToContentSetting(value->GetInt()));
}
// TODO(raymes): We should permit different types of base::Value for
@@ -411,8 +411,8 @@ void ContentSettingsPref::UpdatePref(
settings_dictionary->RemoveWithoutPathExpansion(kSessionModelPath,
nullptr);
} else {
- settings_dictionary->SetWithoutPathExpansion(kSettingPath,
- value->CreateDeepCopy());
+ settings_dictionary->SetWithoutPathExpansion(
+ kSettingPath, base::Value::ToUniquePtrValue(value->Clone()));
settings_dictionary->SetKey(
kLastModifiedPath,
base::Value(base::NumberToString(
diff --git a/chromium/components/content_settings/core/browser/content_settings_provider.h b/chromium/components/content_settings/core/browser/content_settings_provider.h
index a87df227c03..744c6f1d7ad 100644
--- a/chromium/components/content_settings/core/browser/content_settings_provider.h
+++ b/chromium/components/content_settings/core/browser/content_settings_provider.h
@@ -8,7 +8,6 @@
#define COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_CONTENT_SETTINGS_PROVIDER_H_
#include <memory>
-#include <string>
#include "base/values.h"
#include "components/content_settings/core/browser/content_settings_rule.h"
diff --git a/chromium/components/content_settings/core/browser/content_settings_provider_unittest.cc b/chromium/components/content_settings/core/browser/content_settings_provider_unittest.cc
index 8a682fb7baa..87ec9511472 100644
--- a/chromium/components/content_settings/core/browser/content_settings_provider_unittest.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_provider_unittest.cc
@@ -28,9 +28,8 @@ TEST(ContentSettingsProviderTest, Mock) {
ContentSettingsType::NOTIFICATIONS, false));
std::unique_ptr<base::Value> value_ptr(TestUtils::GetContentSettingValue(
&mock_provider, url, url, ContentSettingsType::NOTIFICATIONS, false));
- int int_value = -1;
- value_ptr->GetAsInteger(&int_value);
- EXPECT_EQ(CONTENT_SETTING_BLOCK, IntToContentSetting(int_value));
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ IntToContentSetting(value_ptr->GetIfInt().value_or(-1)));
EXPECT_EQ(
CONTENT_SETTING_DEFAULT,
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 71297982d3d..6abf923af42 100644
--- a/chromium/components/content_settings/core/browser/content_settings_registry.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_registry.cc
@@ -77,19 +77,6 @@ std::set<ContentSetting> ValidSettings(ContentSetting setting1,
return std::set<ContentSetting>(settings, settings + base::size(settings));
}
-ContentSetting GetInitialDefaultContentSettingForProtectedMediaIdentifier() {
-// On Android, the default value is ALLOW or ASK depending on whether per-origin
-// provisioning is used (https://crbug.com/854737 and https://crbug.com/904883).
-// On ChromeOS the default value is always ASK.
-#if defined(OS_ANDROID)
- return media::MediaDrmBridge::IsPerOriginProvisioningSupported()
- ? CONTENT_SETTING_ALLOW
- : CONTENT_SETTING_ASK;
-#else
- return CONTENT_SETTING_ASK;
-#endif // defined(OS_ANDROID)
-}
-
} // namespace
// static
@@ -272,16 +259,32 @@ void ContentSettingsRegistry::Init() {
ContentSettingsInfo::PERSISTENT,
ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY);
+ // On Android, the default value is ALLOW or ASK depending on whether
+ // per-origin provisioning is used (https://crbug.com/854737 and
+ // https://crbug.com/904883).
+ // On ChromeOS and Windows the default value is always ALLOW.
const auto protected_media_identifier_setting =
- GetInitialDefaultContentSettingForProtectedMediaIdentifier();
+#if defined(OS_ANDROID)
+ media::MediaDrmBridge::IsPerOriginProvisioningSupported()
+ ? CONTENT_SETTING_ALLOW
+ : CONTENT_SETTING_ASK;
+#else
+ CONTENT_SETTING_ALLOW;
+#endif // defined(OS_ANDROID)
+
Register(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
"protected-media-identifier", protected_media_identifier_setting,
WebsiteSettingsInfo::UNSYNCABLE, AllowlistedSchemes(),
+#if defined(OS_ANDROID)
ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK,
CONTENT_SETTING_ASK),
+#else // defined(OS_ANDROID)
+ ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK),
+#endif // else
WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
WebsiteSettingsRegistry::PLATFORM_ANDROID |
- WebsiteSettingsRegistry::PLATFORM_CHROMEOS,
+ WebsiteSettingsRegistry::PLATFORM_CHROMEOS |
+ WebsiteSettingsRegistry::PLATFORM_WINDOWS,
protected_media_identifier_setting == CONTENT_SETTING_ALLOW
? ContentSettingsInfo::INHERIT_IN_INCOGNITO
: ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE,
diff --git a/chromium/components/content_settings/core/browser/content_settings_registry_unittest.cc b/chromium/components/content_settings/core/browser/content_settings_registry_unittest.cc
index e72f9dac05e..b6d6b5052df 100644
--- a/chromium/components/content_settings/core/browser/content_settings_registry_unittest.cc
+++ b/chromium/components/content_settings/core/browser/content_settings_registry_unittest.cc
@@ -51,8 +51,8 @@ TEST_F(ContentSettingsRegistryTest, GetPlatformDependent) {
EXPECT_FALSE(registry()->Get(ContentSettingsType::IMAGES));
#endif
-// Protected media identifier only get registered on android and chromeos.
-#if defined(ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+// Protected media identifier only registered on Android, Chrome OS and Windows.
+#if defined(ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
EXPECT_TRUE(registry()->Get(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER));
#else
EXPECT_FALSE(
@@ -85,10 +85,9 @@ TEST_F(ContentSettingsRegistryTest, Properties) {
website_settings_info->pref_name());
EXPECT_EQ("profile.default_content_setting_values.cookies",
website_settings_info->default_value_pref_name());
- int setting;
- ASSERT_TRUE(
- website_settings_info->initial_default_value()->GetAsInteger(&setting));
- EXPECT_EQ(CONTENT_SETTING_ALLOW, setting);
+ ASSERT_TRUE(website_settings_info->initial_default_value()->is_int());
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ website_settings_info->initial_default_value()->GetInt());
#if defined(OS_ANDROID) || defined(OS_IOS)
EXPECT_EQ(PrefRegistry::NO_REGISTRATION_FLAGS,
website_settings_info->GetPrefRegistrationFlags());
@@ -169,7 +168,7 @@ TEST_F(ContentSettingsRegistryTest, IsDefaultSettingValid) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
info = registry()->Get(ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER);
- EXPECT_FALSE(info->IsDefaultSettingValid(CONTENT_SETTING_ALLOW));
+ EXPECT_TRUE(info->IsDefaultSettingValid(CONTENT_SETTING_ALLOW));
#endif
#if !defined(OS_IOS) && !defined(OS_ANDROID)
diff --git a/chromium/components/content_settings/core/browser/host_content_settings_map.cc b/chromium/components/content_settings/core/browser/host_content_settings_map.cc
index 6aa89287d22..c1c3f72f019 100644
--- a/chromium/components/content_settings/core/browser/host_content_settings_map.cc
+++ b/chromium/components/content_settings/core/browser/host_content_settings_map.cc
@@ -393,7 +393,7 @@ ContentSetting HostContentSettingsMap::GetUserModifiableContentSetting(
void HostContentSettingsMap::GetSettingsForOneType(
ContentSettingsType content_type,
ContentSettingsForOneType* settings,
- base::Optional<content_settings::SessionModel> session_model) const {
+ absl::optional<content_settings::SessionModel> session_model) const {
DCHECK(settings);
UsedContentSettingsProviders();
@@ -768,7 +768,7 @@ void HostContentSettingsMap::AddSettingsForOneType(
ContentSettingsType content_type,
ContentSettingsForOneType* settings,
bool incognito,
- base::Optional<content_settings::SessionModel> session_model) const {
+ absl::optional<content_settings::SessionModel> session_model) const {
std::unique_ptr<content_settings::RuleIterator> rule_iterator(
provider->GetRuleIterator(content_type, incognito));
if (!rule_iterator)
@@ -905,7 +905,7 @@ std::unique_ptr<base::Value> HostContentSettingsMap::GetWebsiteSettingInternal(
info->primary_pattern = ContentSettingsPattern();
info->secondary_pattern = ContentSettingsPattern();
}
- return std::unique_ptr<base::Value>();
+ return nullptr;
}
// static
@@ -964,11 +964,11 @@ HostContentSettingsMap::GetContentSettingValueAndPatterns(
*secondary_pattern = rule.secondary_pattern;
if (session_model)
*session_model = rule.session_model;
- return rule.value.CreateDeepCopy();
+ return base::Value::ToUniquePtrValue(rule.value.Clone());
}
}
}
- return std::unique_ptr<base::Value>();
+ return nullptr;
}
void HostContentSettingsMap::
diff --git a/chromium/components/content_settings/core/browser/host_content_settings_map.h b/chromium/components/content_settings/core/browser/host_content_settings_map.h
index b6c425ac577..913348c7601 100644
--- a/chromium/components/content_settings/core/browser/host_content_settings_map.h
+++ b/chromium/components/content_settings/core/browser/host_content_settings_map.h
@@ -155,8 +155,8 @@ class HostContentSettingsMap : public content_settings::Observer,
// This may be called on any thread.
void GetSettingsForOneType(ContentSettingsType content_type,
ContentSettingsForOneType* settings,
- base::Optional<content_settings::SessionModel>
- session_model = base::nullopt) const;
+ absl::optional<content_settings::SessionModel>
+ session_model = absl::nullopt) const;
// Sets the default setting for a particular content type. This method must
// not be invoked on an incognito map.
@@ -363,7 +363,7 @@ class HostContentSettingsMap : public content_settings::Observer,
ContentSettingsType content_type,
ContentSettingsForOneType* settings,
bool incognito,
- base::Optional<content_settings::SessionModel> session_model) const;
+ absl::optional<content_settings::SessionModel> session_model) const;
// Call UsedContentSettingsProviders() whenever you access
// content_settings_providers_ (apart from initialization and
diff --git a/chromium/components/content_settings/core/browser/insecure_private_network_policy_handler.cc b/chromium/components/content_settings/core/browser/insecure_private_network_policy_handler.cc
index 13ff2f6e196..f86d8ec6daa 100644
--- a/chromium/components/content_settings/core/browser/insecure_private_network_policy_handler.cc
+++ b/chromium/components/content_settings/core/browser/insecure_private_network_policy_handler.cc
@@ -32,10 +32,10 @@ void InsecurePrivateNetworkPolicyHandler::ApplyPolicySettings(
const policy::PolicyMap& policies,
PrefValueMap* prefs) {
const base::Value* value = policies.GetValue(policy_name());
- bool is_allowed = false;
- if (value && value->GetAsBoolean(&is_allowed)) {
- prefs->SetValue(prefs::kManagedDefaultInsecurePrivateNetworkSetting,
- base::Value(ConvertBooleanToContentSetting(is_allowed)));
+ if (value && value->is_bool()) {
+ prefs->SetValue(
+ prefs::kManagedDefaultInsecurePrivateNetworkSetting,
+ base::Value(ConvertBooleanToContentSetting(value->GetBool())));
}
}
diff --git a/chromium/components/content_settings/core/browser/website_settings_registry.cc b/chromium/components/content_settings/core/browser/website_settings_registry.cc
index e2900ed03ee..5389b9aa339 100644
--- a/chromium/components/content_settings/core/browser/website_settings_registry.cc
+++ b/chromium/components/content_settings/core/browser/website_settings_registry.cc
@@ -221,11 +221,26 @@ void WebsiteSettingsRegistry::Init() {
WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE,
DESKTOP | PLATFORM_ANDROID,
WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
+ Register(ContentSettingsType::FILE_SYSTEM_ACCESS_CHOOSER_DATA,
+ "file-system-access-chooser-data", nullptr,
+ WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
+ WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, DESKTOP,
+ WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
Register(ContentSettingsType::FILE_SYSTEM_LAST_PICKED_DIRECTORY,
"file-system-last-picked-directory", nullptr,
WebsiteSettingsInfo::UNSYNCABLE, WebsiteSettingsInfo::NOT_LOSSY,
WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, DESKTOP,
WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
+ Register(ContentSettingsType::FEDERATED_IDENTITY_SHARING, "webid-share",
+ nullptr, WebsiteSettingsInfo::UNSYNCABLE,
+ WebsiteSettingsInfo::NOT_LOSSY,
+ WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, ALL_PLATFORMS,
+ WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
+ Register(ContentSettingsType::FEDERATED_IDENTITY_REQUEST, "webid-request",
+ nullptr, WebsiteSettingsInfo::UNSYNCABLE,
+ WebsiteSettingsInfo::NOT_LOSSY,
+ WebsiteSettingsInfo::SINGLE_ORIGIN_ONLY_SCOPE, ALL_PLATFORMS,
+ WebsiteSettingsInfo::DONT_INHERIT_IN_INCOGNITO);
}
} // namespace content_settings
diff --git a/chromium/components/content_settings/core/browser/website_settings_registry_unittest.cc b/chromium/components/content_settings/core/browser/website_settings_registry_unittest.cc
index 040fb6077f1..a1a8202bddf 100644
--- a/chromium/components/content_settings/core/browser/website_settings_registry_unittest.cc
+++ b/chromium/components/content_settings/core/browser/website_settings_registry_unittest.cc
@@ -98,9 +98,8 @@ TEST_F(WebsiteSettingsRegistryTest, Properties) {
EXPECT_EQ("profile.content_settings.exceptions.test", info->pref_name());
EXPECT_EQ("profile.default_content_setting_values.test",
info->default_value_pref_name());
- int setting;
- ASSERT_TRUE(info->initial_default_value()->GetAsInteger(&setting));
- EXPECT_EQ(999, setting);
+ ASSERT_TRUE(info->initial_default_value()->is_int());
+ EXPECT_EQ(999, info->initial_default_value()->GetInt());
#if defined(OS_ANDROID) || defined(OS_IOS)
EXPECT_EQ(PrefRegistry::LOSSY_PREF, info->GetPrefRegistrationFlags());
#else
diff --git a/chromium/components/content_settings/core/common/content_settings.cc b/chromium/components/content_settings/core/common/content_settings.cc
index 5906e845297..edf31ba76eb 100644
--- a/chromium/components/content_settings/core/common/content_settings.cc
+++ b/chromium/components/content_settings/core/common/content_settings.cc
@@ -94,6 +94,9 @@ constexpr HistogramValue kHistogramValue[] = {
{ContentSettingsType::FILE_SYSTEM_LAST_PICKED_DIRECTORY, 73},
{ContentSettingsType::DISPLAY_CAPTURE, 74},
{ContentSettingsType::FILE_HANDLING, 75},
+ {ContentSettingsType::FILE_SYSTEM_ACCESS_CHOOSER_DATA, 76},
+ {ContentSettingsType::FEDERATED_IDENTITY_SHARING, 77},
+ {ContentSettingsType::FEDERATED_IDENTITY_REQUEST, 78},
};
} // namespace
diff --git a/chromium/components/content_settings/core/common/content_settings_pattern.cc b/chromium/components/content_settings/core/common/content_settings_pattern.cc
index 1f0afcae547..c592cc4b156 100644
--- a/chromium/components/content_settings/core/common/content_settings_pattern.cc
+++ b/chromium/components/content_settings/core/common/content_settings_pattern.cc
@@ -13,7 +13,6 @@
#include "base/check_op.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
@@ -21,6 +20,7 @@
#include "base/strings/string_util.h"
#include "components/content_settings/core/common/content_settings_pattern_parser.h"
#include "net/base/url_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/url_constants.h"
@@ -74,23 +74,23 @@ bool IsSubDomainOrEqual(base::StringPiece sub_domain,
// Splits a |domain| name on the last dot. The returned tuple will consist of:
// (1) A prefix of the |domain| name such that the right-most domain label and
-// its separating dot is removed; or base::nullopt if |domain| consisted
+// its separating dot is removed; or absl::nullopt if |domain| consisted
// only of a single domain label.
// (2) The right-most domain label, which is defined as the empty string if
// |domain| is empty or ends in a dot.
-std::tuple<base::Optional<base::StringPiece>, base::StringPiece>
+std::tuple<absl::optional<base::StringPiece>, base::StringPiece>
SplitDomainOnLastDot(const base::StringPiece domain) {
size_t index_of_last_dot = domain.rfind('.');
if (index_of_last_dot == base::StringPiece::npos)
- return std::make_tuple(base::nullopt, domain);
+ return std::make_tuple(absl::nullopt, domain);
return std::make_tuple(domain.substr(0, index_of_last_dot),
domain.substr(index_of_last_dot + 1));
}
// Compares two domain names.
int CompareDomainNames(base::StringPiece domain_a, base::StringPiece domain_b) {
- base::Optional<base::StringPiece> rest_of_a(domain_a);
- base::Optional<base::StringPiece> rest_of_b(domain_b);
+ absl::optional<base::StringPiece> rest_of_a(domain_a);
+ absl::optional<base::StringPiece> rest_of_b(domain_b);
while (rest_of_a && rest_of_b) {
base::StringPiece rightmost_label_a;
@@ -412,7 +412,7 @@ ContentSettingsPattern ContentSettingsPattern::FromURL(
}
if (local_url->port_piece().empty()) {
if (local_url->SchemeIs(url::kHttpsScheme))
- builder.WithPort(GetDefaultPort(url::kHttpsScheme).as_string());
+ builder.WithPort(std::string(GetDefaultPort(url::kHttpsScheme)));
else
builder.WithPortWildcard();
} else {
@@ -435,7 +435,7 @@ ContentSettingsPattern ContentSettingsPattern::FromURLNoWildcard(
} else {
builder.WithScheme(local_url->scheme())->WithHost(local_url->host());
if (local_url->port_piece().empty()) {
- builder.WithPort(GetDefaultPort(local_url->scheme_piece()).as_string());
+ builder.WithPort(std::string(GetDefaultPort(local_url->scheme_piece())));
} else {
builder.WithPort(local_url->port());
}
diff --git a/chromium/components/content_settings/core/common/content_settings_pattern_parser.cc b/chromium/components/content_settings/core/common/content_settings_pattern_parser.cc
index 7064c2b4c96..fa27361009d 100644
--- a/chromium/components/content_settings/core/common/content_settings_pattern_parser.cc
+++ b/chromium/components/content_settings/core/common/content_settings_pattern_parser.cc
@@ -111,7 +111,7 @@ void PatternParser::Parse(base::StringPiece pattern_spec,
if (scheme_piece == kSchemeWildcard) {
builder->WithSchemeWildcard();
} else {
- builder->WithScheme(scheme_piece.as_string());
+ builder->WithScheme(std::string(scheme_piece));
}
} else {
builder->WithSchemeWildcard();
@@ -142,14 +142,14 @@ void PatternParser::Parse(base::StringPiece pattern_spec,
host_piece.remove_prefix(kDomainWildcardLength);
builder->WithDomainWildcard();
- builder->WithHost(host_piece.as_string());
+ builder->WithHost(std::string(host_piece));
} else {
// If the host contains a wildcard symbol then it is invalid.
if (host_piece.find(kHostWildcard) != std::string::npos) {
builder->Invalid();
return;
}
- builder->WithHost(host_piece.as_string());
+ builder->WithHost(std::string(host_piece));
}
}
@@ -171,7 +171,7 @@ void PatternParser::Parse(base::StringPiece pattern_spec,
}
}
// TODO(markusheintz): Check port range.
- builder->WithPort(port_piece.as_string());
+ builder->WithPort(std::string(port_piece));
}
} else {
if (!ContentSettingsPattern::IsNonWildcardDomainNonPortScheme(
@@ -184,7 +184,7 @@ void PatternParser::Parse(base::StringPiece pattern_spec,
if (path_piece.substr(1) == kPathWildcard)
builder->WithPathWildcard();
else
- builder->WithPath(path_piece.as_string());
+ builder->WithPath(std::string(path_piece));
}
}
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 86739218b10..47d6effe7e3 100644
--- a/chromium/components/content_settings/core/common/content_settings_types.h
+++ b/chromium/components/content_settings/core/common/content_settings_types.h
@@ -158,7 +158,7 @@ enum class ContentSettingsType : int32_t {
// 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
- // File System API.
+ // File System Access API.
FILE_SYSTEM_WRITE_GUARD,
// Content settings for installed web apps that browsing history may be
@@ -194,7 +194,7 @@ enum class ContentSettingsType : int32_t {
AR,
// Content setting which stores whether to allow site to open and read files
- // and directories selected through the File System API.
+ // and directories selected through the File System Access API.
FILE_SYSTEM_READ_GUARD,
// Access to first party storage in a third-party context. Exceptions are
@@ -243,6 +243,24 @@ enum class ContentSettingsType : int32_t {
// access files through drag & drop or clipboard paste operations.
FILE_HANDLING,
+ // Website setting to store permissions metadata granted to paths on the local
+ // file system via the File System Access API. |FILE_SYSTEM_WRITE_GUARD| is
+ // the corresponding "guard" setting.
+ FILE_SYSTEM_ACCESS_CHOOSER_DATA,
+
+ // Stores a grant for the browser to intermediate or allow without
+ // restriction sharing of identity information by an identity provider to
+ // specified relying parties. The setting is associated with the identity
+ // provider's origin.
+ // This is managed by WebID.
+ FEDERATED_IDENTITY_SHARING,
+
+ // Stores a grant that allows a relying party to send a request for identity
+ // information to specified identity providers, potentially through any
+ // anti-tracking measures that would otherwise prevent it. This setting is
+ // associated with the relying party's origin.
+ FEDERATED_IDENTITY_REQUEST,
+
NUM_TYPES,
};
diff --git a/chromium/components/content_settings/core/common/content_settings_utils.cc b/chromium/components/content_settings/core/common/content_settings_utils.cc
index 415d73983de..45a3ee0d957 100644
--- a/chromium/components/content_settings/core/common/content_settings_utils.cc
+++ b/chromium/components/content_settings/core/common/content_settings_utils.cc
@@ -21,10 +21,9 @@ bool ParseContentSettingValue(const base::Value* value,
*setting = CONTENT_SETTING_DEFAULT;
return true;
}
- int int_value = -1;
- if (!value->GetAsInteger(&int_value))
+ if (!value->is_int())
return false;
- *setting = IntToContentSetting(int_value);
+ *setting = IntToContentSetting(value->GetInt());
return *setting != CONTENT_SETTING_DEFAULT;
}
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 eaab010af84..d93ee1ae6e7 100644
--- a/chromium/components/content_settings/core/common/cookie_settings_base.cc
+++ b/chromium/components/content_settings/core/common/cookie_settings_base.cc
@@ -82,7 +82,7 @@ bool CookieSettingsBase::IsCookieAccessAllowed(
bool CookieSettingsBase::IsCookieAccessAllowed(
const GURL& url,
const GURL& site_for_cookies,
- const base::Optional<url::Origin>& top_frame_origin) const {
+ const absl::optional<url::Origin>& top_frame_origin) const {
ContentSetting setting = GetCookieSettingInternal(
url, top_frame_origin ? top_frame_origin->GetURL() : site_for_cookies,
IsThirdPartyRequest(url, site_for_cookies), nullptr);
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 509fbf0fa3a..de17a2bc197 100644
--- a/chromium/components/content_settings/core/common/cookie_settings_base.h
+++ b/chromium/components/content_settings/core/common/cookie_settings_base.h
@@ -7,9 +7,9 @@
#include <string>
-#include "base/optional.h"
#include "components/content_settings/core/common/content_settings.h"
#include "net/cookies/cookie_constants.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace url {
class Origin;
@@ -97,7 +97,7 @@ class CookieSettingsBase {
bool IsCookieAccessAllowed(
const GURL& url,
const GURL& site_for_cookies,
- const base::Optional<url::Origin>& top_frame_origin) const;
+ const absl::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|
diff --git a/chromium/components/content_settings/renderer/content_settings_agent_impl.cc b/chromium/components/content_settings/renderer/content_settings_agent_impl.cc
index b6b38ab9a25..3ef8da910ce 100644
--- a/chromium/components/content_settings/renderer/content_settings_agent_impl.cc
+++ b/chromium/components/content_settings/renderer/content_settings_agent_impl.cc
@@ -77,18 +77,18 @@ bool ContentSettingsAgentImpl::Delegate::IsSchemeAllowlisted(
return false;
}
-base::Optional<bool>
+absl::optional<bool>
ContentSettingsAgentImpl::Delegate::AllowReadFromClipboard() {
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<bool>
+absl::optional<bool>
ContentSettingsAgentImpl::Delegate::AllowWriteToClipboard() {
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<bool> ContentSettingsAgentImpl::Delegate::AllowMutationEvents() {
- return base::nullopt;
+absl::optional<bool> ContentSettingsAgentImpl::Delegate::AllowMutationEvents() {
+ return absl::nullopt;
}
void ContentSettingsAgentImpl::Delegate::PassiveInsecureContentFound(
@@ -312,6 +312,7 @@ bool ContentSettingsAgentImpl::AllowStorageAccessSync(
if (permissions != cached_storage_permissions_.end())
return permissions->second;
+ SCOPED_UMA_HISTOGRAM_TIMER("ContentSettings.AllowStorageAccessSync");
bool result = false;
GetContentSettingsManager().AllowStorageAccess(
routing_id(), ConvertToMojoStorageType(storage_type),
diff --git a/chromium/components/content_settings/renderer/content_settings_agent_impl.h b/chromium/components/content_settings/renderer/content_settings_agent_impl.h
index f5f55e59b07..7abd12a94f5 100644
--- a/chromium/components/content_settings/renderer/content_settings_agent_impl.h
+++ b/chromium/components/content_settings/renderer/content_settings_agent_impl.h
@@ -12,7 +12,6 @@
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h"
-#include "base/time/time.h"
#include "components/content_settings/common/content_settings_agent.mojom.h"
#include "components/content_settings/common/content_settings_manager.mojom.h"
#include "components/content_settings/core/common/content_settings.h"
@@ -52,10 +51,10 @@ class ContentSettingsAgentImpl
// Allows the delegate to override logic for various
// blink::WebContentSettingsClient methods. If an optional value is
- // returned, return base::nullopt to use the default logic.
- virtual base::Optional<bool> AllowReadFromClipboard();
- virtual base::Optional<bool> AllowWriteToClipboard();
- virtual base::Optional<bool> AllowMutationEvents();
+ // returned, return absl::nullopt to use the default logic.
+ virtual absl::optional<bool> AllowReadFromClipboard();
+ virtual absl::optional<bool> AllowWriteToClipboard();
+ virtual absl::optional<bool> AllowMutationEvents();
virtual void PassiveInsecureContentFound(const blink::WebURL& resource_url);
};
diff --git a/chromium/components/contextual_search/core/browser/ctr_aggregator.h b/chromium/components/contextual_search/core/browser/ctr_aggregator.h
index cfc22458ea6..96baddfacdc 100644
--- a/chromium/components/contextual_search/core/browser/ctr_aggregator.h
+++ b/chromium/components/contextual_search/core/browser/ctr_aggregator.h
@@ -12,8 +12,6 @@
#ifndef COMPONENTS_CONTEXTUAL_SEARCH_CORE_BROWSER_CTR_AGGREGATOR_H_
#define COMPONENTS_CONTEXTUAL_SEARCH_CORE_BROWSER_CTR_AGGREGATOR_H_
-#include <string>
-
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "components/contextual_search/core/browser/weekly_activity_storage.h"
diff --git a/chromium/components/contextual_search/core/browser/weekly_activity_storage.h b/chromium/components/contextual_search/core/browser/weekly_activity_storage.h
index 3850b254e13..35abb7baf63 100644
--- a/chromium/components/contextual_search/core/browser/weekly_activity_storage.h
+++ b/chromium/components/contextual_search/core/browser/weekly_activity_storage.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_CONTEXTUAL_SEARCH_CORE_BROWSER_WEEKLY_ACTIVITY_STORAGE_H_
#define COMPONENTS_CONTEXTUAL_SEARCH_CORE_BROWSER_WEEKLY_ACTIVITY_STORAGE_H_
-#include <string>
-#include <unordered_map>
-
#include "base/macros.h"
namespace contextual_search {
diff --git a/chromium/components/continuous_search/OWNERS b/chromium/components/continuous_search/OWNERS
index 83d31b806a5..fb7061e1d6f 100644
--- a/chromium/components/continuous_search/OWNERS
+++ b/chromium/components/continuous_search/OWNERS
@@ -1,3 +1,3 @@
ckitagawa@chromium.org
fredmello@chromium.org
-mahmoudi@chromium.org
+yashard@chromium.org
diff --git a/chromium/components/continuous_search/browser/search_result_extractor_client_status.h b/chromium/components/continuous_search/browser/search_result_extractor_client_status.h
index df0a29a7fc1..3a5e27c0a6b 100644
--- a/chromium/components/continuous_search/browser/search_result_extractor_client_status.h
+++ b/chromium/components/continuous_search/browser/search_result_extractor_client_status.h
@@ -19,6 +19,7 @@ enum SearchResultExtractorClientStatus {
kNativeNotInitialized,
kAlreadyCapturing,
kWebContentsHasNonSrpUrl,
+ kNotEnoughResults,
kMaxValue,
};
diff --git a/chromium/components/continuous_search/common/title_validator.cc b/chromium/components/continuous_search/common/title_validator.cc
index 177af6eac4a..8cd5dee683f 100644
--- a/chromium/components/continuous_search/common/title_validator.cc
+++ b/chromium/components/continuous_search/common/title_validator.cc
@@ -24,8 +24,8 @@ bool IsUnicodeWhitespaceOrControl(wchar_t c) {
c != 0x000B;
}
-template <typename CharT>
-std::basic_string<CharT> ValidateTitleT(base::BasicStringPiece<CharT> input) {
+template <typename T, typename CharT = typename T::value_type>
+std::basic_string<CharT> ValidateTitleT(T input) {
auto begin_it = std::find_if(input.begin(), input.end(),
base::not_fn(IsUnicodeWhitespaceOrControl));
auto end_it = std::find_if(input.rbegin(), input.rend(),
diff --git a/chromium/components/continuous_search/renderer/search_result_extractor_impl.cc b/chromium/components/continuous_search/renderer/search_result_extractor_impl.cc
index b53c9d43183..9909eb99e37 100644
--- a/chromium/components/continuous_search/renderer/search_result_extractor_impl.cc
+++ b/chromium/components/continuous_search/renderer/search_result_extractor_impl.cc
@@ -178,6 +178,9 @@ void SearchResultExtractorImpl::OnDestruct() {
void SearchResultExtractorImpl::BindSearchResultExtractor(
mojo::PendingAssociatedReceiver<mojom::SearchResultExtractor> receiver) {
+ // Requests can occur multiple times on the same frame. If the browser has
+ // released its endpoint and creates a new one this needs to be reset.
+ receiver_.reset();
receiver_.Bind(std::move(receiver));
}
diff --git a/chromium/components/crash/android/DIR_METADATA b/chromium/components/crash/android/DIR_METADATA
index 7c7d44182a8..7a2580a646c 100644
--- a/chromium/components/crash/android/DIR_METADATA
+++ b/chromium/components/crash/android/DIR_METADATA
@@ -1,4 +1 @@
-monorail {
- component: "Internals>CrashReporting"
-}
os: ANDROID
diff --git a/chromium/components/crash/content/browser/crash_metrics_reporter_android.cc b/chromium/components/crash/content/browser/crash_metrics_reporter_android.cc
index c388c0bd386..a7f4ad09cb6 100644
--- a/chromium/components/crash/content/browser/crash_metrics_reporter_android.cc
+++ b/chromium/components/crash/content/browser/crash_metrics_reporter_android.cc
@@ -7,11 +7,11 @@
#include "base/check.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
-#include "base/optional.h"
#include "base/rand_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
#include "components/crash/content/browser/process_exit_reason_from_system_android.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace crash_reporter {
namespace {
diff --git a/chromium/components/crash/content/browser/error_reporting/DIR_METADATA b/chromium/components/crash/content/browser/error_reporting/DIR_METADATA
deleted file mode 100644
index 030c855a3b0..00000000000
--- a/chromium/components/crash/content/browser/error_reporting/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Internals>CrashReporting"
-}
diff --git a/chromium/components/crash/content/browser/error_reporting/javascript_error_report.h b/chromium/components/crash/content/browser/error_reporting/javascript_error_report.h
index a5ee3db1ffb..a2d68e53714 100644
--- a/chromium/components/crash/content/browser/error_reporting/javascript_error_report.h
+++ b/chromium/components/crash/content/browser/error_reporting/javascript_error_report.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/component_export.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
enum class WindowType {
// No browser found, thus no window exists.
@@ -59,21 +59,21 @@ struct COMPONENT_EXPORT(JS_ERROR_REPORTING) JavaScriptErrorReport {
std::string version;
// Line number where the error occurred. Not sent if not present.
- base::Optional<int> line_number;
+ absl::optional<int> line_number;
// Column number where the error occurred. Not sent if not present.
- base::Optional<int> column_number;
+ absl::optional<int> column_number;
// String containing the stack trace for the error. Not sent if not present.
- base::Optional<std::string> stack_trace;
+ absl::optional<std::string> stack_trace;
// String containing the application locale. Not sent if not present.
- base::Optional<std::string> app_locale;
+ absl::optional<std::string> app_locale;
// URL of the page the user was on when the error occurred. Must include the
// protocol (e.g. http://www.example.com) but not query, fragment, or other
// privacy-sensitive details we don't want to send.
- base::Optional<std::string> page_url;
+ absl::optional<std::string> page_url;
// Uptime of the renderer process in milliseconds. 0 if the callee
// |web_contents| is null (shouldn't really happen as this is caled from a JS
@@ -82,7 +82,7 @@ struct COMPONENT_EXPORT(JS_ERROR_REPORTING) JavaScriptErrorReport {
int renderer_process_uptime_ms = 0;
// The window type of the JS context that reported this error.
- base::Optional<WindowType> window_type;
+ absl::optional<WindowType> window_type;
// If true (the default), send this report to the production server. If false,
// send to the staging server. This should be set to false for errors from
diff --git a/chromium/components/crash/content/browser/error_reporting/mock_crash_endpoint.h b/chromium/components/crash/content/browser/error_reporting/mock_crash_endpoint.h
index 9e3f7682559..e7d3c2a9b9c 100644
--- a/chromium/components/crash/content/browser/error_reporting/mock_crash_endpoint.h
+++ b/chromium/components/crash/content/browser/error_reporting/mock_crash_endpoint.h
@@ -11,8 +11,8 @@
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
#include "net/http/http_status_code.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace net {
@@ -41,7 +41,7 @@ class MockCrashEndpoint {
Report WaitForReport();
// Returns the last report received, if any.
- const base::Optional<Report>& last_report() const { return last_report_; }
+ const absl::optional<Report>& last_report() const { return last_report_; }
// Clears last report so that WaitForReport will wait for another report.
// Does not clear report_count() or all_reports().
@@ -74,7 +74,7 @@ class MockCrashEndpoint {
net::test_server::EmbeddedTestServer* test_server_;
std::unique_ptr<Client> client_;
- base::Optional<Report> last_report_;
+ absl::optional<Report> last_report_;
std::vector<Report> all_reports_;
int report_count_ = 0;
bool consented_ = true;
diff --git a/chromium/components/crash/core/DIR_METADATA b/chromium/components/crash/core/DIR_METADATA
deleted file mode 100644
index 030c855a3b0..00000000000
--- a/chromium/components/crash/core/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Internals>CrashReporting"
-}
diff --git a/chromium/components/crash/core/app/crashpad_mac.mm b/chromium/components/crash/core/app/crashpad_mac.mm
index 2be2fd857bc..e3fc1fb2bca 100644
--- a/chromium/components/crash/core/app/crashpad_mac.mm
+++ b/chromium/components/crash/core/app/crashpad_mac.mm
@@ -18,7 +18,6 @@
#include "base/mac/foundation_util.h"
#include "base/strings/string_number_conversions.h"
#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/core/app/crash_reporter_client.h"
diff --git a/chromium/components/crash/core/browser/resources/crashes.js b/chromium/components/crash/core/browser/resources/crashes.js
index 0d21ef1b4fa..2ee88479245 100644
--- a/chromium/components/crash/core/browser/resources/crashes.js
+++ b/chromium/components/crash/core/browser/resources/crashes.js
@@ -10,7 +10,7 @@ import 'chrome://resources/js/action_link.js';
import './strings.m.js';
import {addWebUIListener} from 'chrome://resources/js/cr.m.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {$} from 'chrome://resources/js/util.m.js';
+import {$, appendParam} from 'chrome://resources/js/util.m.js';
/* Id for tracking automatic refresh of crash list. */
let refreshCrashListId = undefined;
@@ -178,7 +178,7 @@ function fileBug(crashId, os, version) {
// TODO(scottmg): Use add_labels to add 'User-Submitted' rather than
// duplicating the template's labels (the first two) once
// https://bugs.chromium.org/p/monorail/issues/detail?id=1488 is done.
- labels: 'Restrict-View-EditIssue,Stability-Crash,User-Submitted',
+ labels: 'Restrict-View-EditIssue,Stability-Crash,User-Submitted,Pri-3,Type-Bug',
};
let href = 'https://bugs.chromium.org/p/chromium/issues/entry';
for (const param in params) {
diff --git a/chromium/components/crash/core/common/crash_key_breakpad.cc b/chromium/components/crash/core/common/crash_key_breakpad.cc
index 986530b20c2..bb37248d363 100644
--- a/chromium/components/crash/core/common/crash_key_breakpad.cc
+++ b/chromium/components/crash/core/common/crash_key_breakpad.cc
@@ -62,7 +62,7 @@ void CrashKeyStringImpl::Set(base::StringPiece value) {
// If there is only one slot for the value, then handle it directly.
if (index_array_count_ == 1) {
- std::string value_string = value.as_string();
+ std::string value_string(value);
if (is_set()) {
storage->SetValueAtIndex(index_array_[0], value_string.c_str());
} else {
diff --git a/chromium/components/crash/core/common/crash_key_breakpad_ios.mm b/chromium/components/crash/core/common/crash_key_breakpad_ios.mm
index 8149c70ff42..cec8f36d9fa 100644
--- a/chromium/components/crash/core/common/crash_key_breakpad_ios.mm
+++ b/chromium/components/crash/core/common/crash_key_breakpad_ios.mm
@@ -48,7 +48,7 @@ void CrashKeyStringImpl::Set(base::StringPiece value) {
return;
NSString* key = base::SysUTF8ToNSString(name_);
- NSString* value_ns = base::SysUTF8ToNSString(value.as_string());
+ NSString* value_ns = base::SysUTF8ToNSString(value);
[[BreakpadController sharedInstance] addUploadParameter:value_ns forKey:key];
[[PreviousSessionInfo sharedInstance] setReportParameterValue:value_ns
diff --git a/chromium/components/cronet/android/BUILD.gn b/chromium/components/cronet/android/BUILD.gn
index 3dad6db6b27..d31f03874e2 100644
--- a/chromium/components/cronet/android/BUILD.gn
+++ b/chromium/components/cronet/android/BUILD.gn
@@ -674,6 +674,7 @@ _jar_excluded_patterns = [
"*/process_launcher/*.class",
"*/SysUtils*.class",
"org/chromium/base/FeatureList*.class",
+ "org/chromium/base/jank_tracker/*.class",
"org/chromium/base/memory/MemoryPressureMonitor*.class",
]
@@ -837,7 +838,7 @@ if (!is_component_build) {
"//base:i18n",
"//base/test:test_support",
"//components/cronet:cronet_version_header",
- "//components/cronet/test:test_support",
+ "//components/cronet/testing:test_support",
"//components/prefs",
"//net",
"//net:simple_quic_tools",
@@ -958,7 +959,15 @@ if (!is_component_build) {
"//net/android:net_java",
"//net/android:net_java_test_support",
"//url:url_java",
+ "//third_party/google-truth:google_truth_java",
"//third_party/junit",
+ "//third_party/mockito:mockito_java",
+
+ # Transitive Mockito dependencies
+ "//third_party/byte_buddy:byte_buddy_agent_java",
+ "//third_party/byte_buddy:byte_buddy_android_java",
+ "//third_party/byte_buddy:dx_25_0_2_java",
+ "//third_party/byte_buddy:byte_buddy_java",
]
android_library("cronet_javatests") {
@@ -996,6 +1005,7 @@ if (!is_component_build) {
"test/javatests/src/org/chromium/net/urlconnection/CronetFixedModeOutputStreamTest.java",
"test/javatests/src/org/chromium/net/urlconnection/CronetHttpURLConnectionTest.java",
"test/javatests/src/org/chromium/net/urlconnection/CronetHttpURLStreamHandlerTest.java",
+ "test/javatests/src/org/chromium/net/urlconnection/CronetInputStreamTest.java",
"test/javatests/src/org/chromium/net/urlconnection/CronetURLStreamHandlerFactoryTest.java",
"test/javatests/src/org/chromium/net/urlconnection/MessageLoopTest.java",
"test/javatests/src/org/chromium/net/urlconnection/QuicUploadTest.java",
@@ -1014,7 +1024,7 @@ if (!is_component_build) {
"//third_party/hamcrest:hamcrest_core_java",
]
deps += cronet_javatests_deps_to_package
- data = [ "//components/cronet/test/data/" ]
+ data = [ "//components/cronet/testing/test_server/data/" ]
}
instrumentation_test_apk("cronet_test_instrumentation_apk") {
@@ -1212,7 +1222,7 @@ if (!is_component_build) {
sources = [ "../run_all_unittests.cc" ]
- data = [ "//components/cronet/test/data/" ]
+ data = [ "//components/cronet/testing/test_server/data/" ]
if (is_android) {
shard_timeout = 180
@@ -1238,7 +1248,7 @@ if (!is_component_build) {
defines = [ "CRONET_TESTS_IMPLEMENTATION" ]
- data = [ "//components/cronet/test/data/" ]
+ data = [ "//components/cronet/testing/test_server/data/" ]
if (is_android) {
shard_timeout = 180
@@ -1424,7 +1434,7 @@ if (!is_component_build) {
copy("cronet_package_copy_test_assets") {
testonly = true
- sources = [ "//components/cronet/test/data" ]
+ sources = [ "//components/cronet/testing/test_server/data" ]
outputs = [ "$_test_package_dir/assets/test" ]
}
diff --git a/chromium/components/cronet/ios/test/BUILD.gn b/chromium/components/cronet/ios/test/BUILD.gn
index a25b6570e08..ea564f394c9 100644
--- a/chromium/components/cronet/ios/test/BUILD.gn
+++ b/chromium/components/cronet/ios/test/BUILD.gn
@@ -32,7 +32,7 @@ test("cronet_test") {
"//components/cronet:cronet_buildflags",
"//components/cronet/ios:cronet_framework+link",
"//components/cronet/native/test:cronet_native_tests",
- "//components/cronet/test:test_support",
+ "//components/cronet/testing:test_support",
"//components/grpc_support:bidirectional_stream_test",
"//net",
"//net:simple_quic_tools",
diff --git a/chromium/components/cronet/native/test/BUILD.gn b/chromium/components/cronet/native/test/BUILD.gn
index 336876d99c6..75b3b599469 100644
--- a/chromium/components/cronet/native/test/BUILD.gn
+++ b/chromium/components/cronet/native/test/BUILD.gn
@@ -34,7 +34,7 @@ source_set("cronet_native_tests") {
"//base/allocator:buildflags",
"//base/test:test_support",
"//components/cronet/native:cronet_native_headers",
- "//components/cronet/test:test_support",
+ "//components/cronet/testing:test_support",
"//components/grpc_support:bidirectional_stream_test",
"//components/grpc_support/test:get_stream_engine_header",
"//net:test_support",
diff --git a/chromium/components/cronet/test/BUILD.gn b/chromium/components/cronet/test/BUILD.gn
deleted file mode 100644
index 9ed0fc20190..00000000000
--- a/chromium/components/cronet/test/BUILD.gn
+++ /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.
-
-import("//testing/test.gni")
-
-# This section can be updated from globbing rules using:
-# find data -type f | sort | sed 's/\(.*\)/"\1",/g'
-bundle_data("test_support_bundle_data") {
- visibility = [ ":test_support" ]
- testonly = true
- sources = [
- "data/cacheable.txt",
- "data/cacheable.txt.mock-http-headers",
- "data/content_length_mismatch.html",
- "data/content_length_mismatch.html.mock-http-headers",
- "data/gzipped.html",
- "data/gzipped.html.mock-http-headers",
- "data/multiredirect.html",
- "data/multiredirect.html.mock-http-headers",
- "data/notfound.html",
- "data/notfound.html.mock-http-headers",
- "data/quic_data/simple.txt",
- "data/redirect.html",
- "data/redirect.html.mock-http-headers",
- "data/redirect_invalid_scheme.html",
- "data/redirect_invalid_scheme.html.mock-http-headers",
- "data/secureproxychecksuccess.txt",
- "data/secureproxychecksuccess.txt.mock-http-headers",
- "data/set_cookie.html",
- "data/set_cookie.html.mock-http-headers",
- "data/success.txt",
- "data/success.txt.mock-http-headers",
- ]
- outputs = [ "{{bundle_resources_dir}}/" +
- "{{source_root_relative_dir}}/{{source_file_part}}" ]
-}
-
-# Test support for Cronet common implementation.
-source_set("test_support") {
- testonly = true
-
- deps = [ "//net:test_support" ]
-
- data = [ "data/" ]
-
- sources = [
- "test_server.cc",
- "test_server.h",
- ]
-
- if (is_ios) {
- deps += [ ":test_support_bundle_data" ]
- }
-}
diff --git a/chromium/components/cronet/testing/BUILD.gn b/chromium/components/cronet/testing/BUILD.gn
new file mode 100644
index 00000000000..68c96d2d86c
--- /dev/null
+++ b/chromium/components/cronet/testing/BUILD.gn
@@ -0,0 +1,55 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//testing/test.gni")
+
+# This section can be updated from globbing rules using:
+# find data -type f | sort | sed 's/\(.*\)/"\1",/g'
+bundle_data("test_support_bundle_data") {
+ visibility = [ ":test_support" ]
+ testonly = true
+ sources = [
+ "test_server/data/cacheable.txt",
+ "test_server/data/cacheable.txt.mock-http-headers",
+ "test_server/data/content_length_mismatch.html",
+ "test_server/data/content_length_mismatch.html.mock-http-headers",
+ "test_server/data/gzipped.html",
+ "test_server/data/gzipped.html.mock-http-headers",
+ "test_server/data/multiredirect.html",
+ "test_server/data/multiredirect.html.mock-http-headers",
+ "test_server/data/notfound.html",
+ "test_server/data/notfound.html.mock-http-headers",
+ "test_server/data/quic_data/simple.txt",
+ "test_server/data/redirect.html",
+ "test_server/data/redirect.html.mock-http-headers",
+ "test_server/data/redirect_invalid_scheme.html",
+ "test_server/data/redirect_invalid_scheme.html.mock-http-headers",
+ "test_server/data/secureproxychecksuccess.txt",
+ "test_server/data/secureproxychecksuccess.txt.mock-http-headers",
+ "test_server/data/set_cookie.html",
+ "test_server/data/set_cookie.html.mock-http-headers",
+ "test_server/data/success.txt",
+ "test_server/data/success.txt.mock-http-headers",
+ ]
+ outputs = [ "{{bundle_resources_dir}}/" +
+ "{{source_root_relative_dir}}/{{source_file_part}}" ]
+}
+
+# Test support for Cronet common implementation.
+source_set("test_support") {
+ testonly = true
+
+ deps = [ "//net:test_support" ]
+
+ data = [ "test_server/data/" ]
+
+ sources = [
+ "test_server/test_server.cc",
+ "test_server/test_server.h",
+ ]
+
+ if (is_ios) {
+ deps += [ ":test_support_bundle_data" ]
+ }
+}
diff --git a/chromium/components/crx_file/crx_verifier.cc b/chromium/components/crx_file/crx_verifier.cc
index df9bcc6e494..0d7f97a6d89 100644
--- a/chromium/components/crx_file/crx_verifier.cc
+++ b/chromium/components/crx_file/crx_verifier.cc
@@ -156,7 +156,7 @@ VerifierResult VerifyCrx3(
std::vector<uint8_t> publisher_key(std::begin(kPublisherKeyHash),
std::end(kPublisherKeyHash));
- base::Optional<std::vector<uint8_t>> publisher_test_key;
+ absl::optional<std::vector<uint8_t>> publisher_test_key;
if (accept_publisher_test_key) {
publisher_test_key.emplace(std::begin(kPublisherTestKeyHash),
std::end(kPublisherTestKeyHash));
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 be4df7eb843..1885bf6faf6 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
@@ -130,7 +130,7 @@ void MoveAndClearDictionaryPrefs(PrefService* pref_service,
base::DictionaryValue* pref_dict_src = pref_update_src.Get();
pref_dict_dst->Clear();
pref_dict_dst->Swap(pref_dict_src);
- DCHECK(pref_dict_src->empty());
+ DCHECK(pref_dict_src->DictEmpty());
}
void MaybeInitWeeklyAggregateDataUsePrefs(const base::Time& now,
@@ -173,9 +173,9 @@ void RecordDictionaryToHistogram(const std::string& histogram_name,
const base::DictionaryValue* dictionary) {
base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
histogram_name, base::HistogramBase::kUmaTargetedHistogramFlag);
- for (const auto& entry : *dictionary) {
+ for (const auto& entry : dictionary->DictItems()) {
int key;
- int value = entry.second->GetInt();
+ int value = entry.second.GetInt();
if (value > 0 && base::StringToInt(entry.first, &key)) {
histogram->AddCount(key, value);
}
@@ -626,10 +626,9 @@ void DataReductionProxyCompressionStats::DelayedWritePrefs() {
}
void DataReductionProxyCompressionStats::TransferList(
- const base::ListValue& from_list,
- base::ListValue* to_list) {
- to_list->Clear();
- from_list.CreateDeepCopy()->Swap(to_list);
+ const base::Value& from_list,
+ base::Value* to_list) {
+ *to_list = from_list.Clone();
}
void DataReductionProxyCompressionStats::RecordRequestSizePrefs(
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h
index 708c9db9e9c..524d92fc048 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h
@@ -208,8 +208,7 @@ class DataReductionProxyCompressionStats {
// Copies the values at each index of |from_list| to the same index in
// |to_list|.
- void TransferList(const base::ListValue& from_list,
- base::ListValue* to_list);
+ void TransferList(const base::Value& from_list, base::Value* to_list);
// Records content length updates to prefs.
void RecordRequestSizePrefs(int64_t compressed_size,
diff --git a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h
index 59fcaa7e7a3..3db755b2ec3 100644
--- a/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h
+++ b/chromium/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h
@@ -11,10 +11,10 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/supports_user_data.h"
#include "net/base/network_change_notifier.h"
#include "net/nqe/effective_connection_type.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace data_reduction_proxy {
@@ -76,7 +76,7 @@ class DataReductionProxyData : public base::SupportsUserData::Data {
// An identifier that is guaranteed to be unique to each page load during a
// data saver session. Only present on main frame requests.
- const base::Optional<uint64_t>& page_id() const { return page_id_; }
+ const absl::optional<uint64_t>& page_id() const { return page_id_; }
void set_page_id(uint64_t page_id) { page_id_ = page_id; }
// Whether the blacklist prevented a preview.
@@ -119,7 +119,7 @@ class DataReductionProxyData : public base::SupportsUserData::Data {
// An identifier that is guaranteed to be unique to each page load during a
// data saver session. Only present on main frame requests.
- base::Optional<uint64_t> page_id_;
+ absl::optional<uint64_t> page_id_;
DISALLOW_ASSIGN(DataReductionProxyData);
};
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 3d62fac2b4c..108afbe6d00 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
@@ -8,11 +8,11 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/optional.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/safe_sprintf.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
@@ -24,6 +24,7 @@
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/proxy_server.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if defined(USE_GOOGLE_API_KEYS_FOR_AUTH_KEY)
#include "google_apis/google_api_keys.h"
@@ -124,7 +125,7 @@ void DataReductionProxyRequestOptions::AddPageIDRequestHeader(
void DataReductionProxyRequestOptions::AddRequestHeader(
net::HttpRequestHeaders* request_headers,
- base::Optional<uint64_t> page_id) {
+ absl::optional<uint64_t> page_id) {
DCHECK(thread_checker_.CalledOnValidThread());
AddRequestHeader(request_headers, page_id, header_value_);
}
@@ -132,7 +133,7 @@ void DataReductionProxyRequestOptions::AddRequestHeader(
// static
void DataReductionProxyRequestOptions::AddRequestHeader(
net::HttpRequestHeaders* request_headers,
- base::Optional<uint64_t> page_id,
+ absl::optional<uint64_t> page_id,
const std::string& session_header_value) {
DCHECK(!page_id || page_id.value() > 0u);
std::string header_value;
@@ -231,32 +232,32 @@ void DataReductionProxyRequestOptions::RegenerateRequestHeaderValue() {
}
// static
-base::Optional<std::string>
+absl::optional<std::string>
DataReductionProxyRequestOptions::GetSessionKeyFromRequestHeaders(
const net::HttpRequestHeaders& request_headers) {
base::StringPairs kv_pairs;
if (!ParseChromeProxyHeader(request_headers, &kv_pairs))
- return base::nullopt;
+ return absl::nullopt;
for (const auto& kv_pair : kv_pairs) {
// Delete leading and trailing white space characters from the key before
// comparing.
if (base::TrimWhitespaceASCII(kv_pair.first, base::TRIM_ALL) ==
kSecureSessionHeaderOption) {
- return base::TrimWhitespaceASCII(kv_pair.second, base::TRIM_ALL)
- .as_string();
+ return std::string(
+ base::TrimWhitespaceASCII(kv_pair.second, base::TRIM_ALL));
}
}
- return base::nullopt;
+ return absl::nullopt;
}
// static
-base::Optional<uint64_t>
+absl::optional<uint64_t>
DataReductionProxyRequestOptions::GetPageIdFromRequestHeaders(
const net::HttpRequestHeaders& request_headers) {
base::StringPairs kv_pairs;
if (!ParseChromeProxyHeader(request_headers, &kv_pairs))
- return base::nullopt;
+ return absl::nullopt;
for (const auto& kv_pair : kv_pairs) {
// Delete leading and trailing white space characters from the key before
@@ -265,22 +266,20 @@ DataReductionProxyRequestOptions::GetPageIdFromRequestHeaders(
kPageIdOption) {
uint64_t page_id;
if (base::StringToUint64(
- base::TrimWhitespaceASCII(kv_pair.second, base::TRIM_ALL)
- .as_string(),
+ base::TrimWhitespaceASCII(kv_pair.second, base::TRIM_ALL),
&page_id)) {
return page_id;
}
// Also attempt parsing the page_id as a hex string.
if (base::HexStringToUInt64(
- base::TrimWhitespaceASCII(kv_pair.second, base::TRIM_ALL)
- .as_string(),
+ base::TrimWhitespaceASCII(kv_pair.second, base::TRIM_ALL),
&page_id)) {
return page_id;
}
}
}
- return base::nullopt;
+ return absl::nullopt;
}
uint64_t DataReductionProxyRequestOptions::GeneratePageId() {
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 84df3b4bca2..0745726e847 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
@@ -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_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_AUTH_REQUEST_HANDLER_H_
-#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_AUTH_REQUEST_HANDLER_H_
+#ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_REQUEST_OPTIONS_H_
+#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_REQUEST_OPTIONS_H_
#include <stddef.h>
#include <stdint.h>
@@ -14,11 +14,11 @@
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "net/http/http_request_headers.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace net {
class HttpRequestHeaders;
@@ -60,9 +60,9 @@ class DataReductionProxyRequestOptions {
// proxy authentication credentials. |page_id| should only be non-empty for
// main frame requests.
void AddRequestHeader(net::HttpRequestHeaders* request_headers,
- base::Optional<uint64_t> page_id);
+ absl::optional<uint64_t> page_id);
static void AddRequestHeader(net::HttpRequestHeaders* request_headers,
- base::Optional<uint64_t> page_id,
+ absl::optional<uint64_t> page_id,
const std::string& session_header_value);
// Adds |page_id| to the 'Chrome-Proxy' header, merging with existing value if
@@ -94,11 +94,11 @@ class DataReductionProxyRequestOptions {
void Invalidate();
// Parses |request_headers| and returns the value of the session key.
- static base::Optional<std::string> GetSessionKeyFromRequestHeaders(
+ static absl::optional<std::string> GetSessionKeyFromRequestHeaders(
const net::HttpRequestHeaders& request_headers);
// Parses |request_headers| and returns the value of the page id.
- static base::Optional<uint64_t> GetPageIdFromRequestHeaders(
+ static absl::optional<uint64_t> GetPageIdFromRequestHeaders(
const net::HttpRequestHeaders& request_headers);
// Creates and returns a new unique page ID (unique per session).
@@ -158,4 +158,4 @@ class DataReductionProxyRequestOptions {
};
} // namespace data_reduction_proxy
-#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_AUTH_REQUEST_HANDLER_H_
+#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_REQUEST_OPTIONS_H_
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 fcb3061e477..278f8734352 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
@@ -54,7 +54,7 @@ const char kClientStr[] = "android";
#elif defined(OS_IOS)
const Client kClient = Client::CHROME_IOS;
const char kClientStr[] = "ios";
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
const Client kClient = Client::CHROME_MAC;
const char kClientStr[] = "mac";
#elif BUILDFLAG(IS_CHROMEOS_ASH)
@@ -386,7 +386,7 @@ TEST_F(DataReductionProxyRequestOptionsTest, GetSessionKeyFromRequestHeaders) {
test.chrome_proxy_header_value);
request_headers.SetHeader("some_random_header_after", "some_random_key");
- base::Optional<std::string> session_key =
+ absl::optional<std::string> session_key =
request_options()->GetSessionKeyFromRequestHeaders(request_headers);
EXPECT_EQ(test.expect_result, session_key.has_value());
if (test.expect_result) {
@@ -428,7 +428,7 @@ TEST_F(DataReductionProxyRequestOptionsTest, GetPageIdFromRequestHeaders) {
test.chrome_proxy_header_value);
request_headers.SetHeader("some_random_header_after", "some_random_key");
- base::Optional<uint64_t> page_id =
+ absl::optional<uint64_t> page_id =
request_options()->GetPageIdFromRequestHeaders(request_headers);
EXPECT_EQ(test.expect_result, page_id.has_value());
if (test.expect_result) {
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 bb9447fbf63..9d0e0a343ce 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
@@ -35,14 +35,14 @@ namespace data_reduction_proxy {
namespace {
-base::Optional<base::Value> GetSaveDataSavingsPercentEstimateFromFieldTrial() {
+absl::optional<base::Value> GetSaveDataSavingsPercentEstimateFromFieldTrial() {
if (!base::FeatureList::IsEnabled(features::kReportSaveDataSavings))
- return base::nullopt;
+ return absl::nullopt;
const auto origin_savings_estimate_json =
base::GetFieldTrialParamValueByFeature(features::kReportSaveDataSavings,
"origin_savings_estimate");
if (origin_savings_estimate_json.empty())
- return base::nullopt;
+ return absl::nullopt;
auto origin_savings_estimates =
base::JSONReader::Read(origin_savings_estimate_json);
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 81d5adadc40..5ac8c19d30e 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
@@ -174,8 +174,7 @@ class DataReductionProxyService
const std::string channel_;
// Dictionary of save-data savings estimates by origin.
- const base::Optional<base::Value> save_data_savings_estimate_dict_;
-
+ const absl::optional<base::Value> save_data_savings_estimate_dict_;
SEQUENCE_CHECKER(sequence_checker_);
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 f505cd32902..ab60b2701ad 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
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <memory>
-#include <string>
#include <vector>
#include "base/callback.h"
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 e793d1c1ec5..ccc6c2b19e0 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
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers_test_utils.h"
@@ -129,7 +130,7 @@ void DataReductionProxySettingsTestBase::CheckDataReductionProxySyntheticTrial(
bool DataReductionProxySettingsTestBase::OnSyntheticFieldTrialRegistration(
base::StringPiece trial_name,
base::StringPiece group_name) {
- synthetic_field_trials_[trial_name.as_string()] = group_name.as_string();
+ synthetic_field_trials_[std::string(trial_name)] = std::string(group_name);
return true;
}
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 4d965c26058..8801f424d16 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
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
+#include "base/strings/string_piece.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h"
@@ -114,7 +115,7 @@ TestDataStore::~TestDataStore() {}
DataStore::Status TestDataStore::Get(base::StringPiece key,
std::string* value) {
- auto value_iter = map_.find(key.as_string());
+ auto value_iter = map_.find(std::string(key));
if (value_iter == map_.end())
return NOT_FOUND;
@@ -131,7 +132,7 @@ DataStore::Status TestDataStore::Put(
}
DataStore::Status TestDataStore::Delete(base::StringPiece key) {
- map_.erase(key.as_string());
+ map_.erase(std::string(key));
return OK;
}
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 a0a46b6c0fa..c6bf0811692 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
@@ -18,7 +18,6 @@
#include "base/strings/string_piece.h"
#include "base/time/clock.h"
#include "base/time/tick_clock.h"
-#include "base/time/time.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"
diff --git a/chromium/components/data_reduction_proxy/core/browser/db_data_owner.h b/chromium/components/data_reduction_proxy/core/browser/db_data_owner.h
index 9a63addf9bc..bef1a1595db 100644
--- a/chromium/components/data_reduction_proxy/core/browser/db_data_owner.h
+++ b/chromium/components/data_reduction_proxy/core/browser/db_data_owner.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_DATA_REDUCTION_PROXY_CORE_BROWSER_DB_SERVICE_H_
-#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DB_SERVICE_H_
+#ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DB_DATA_OWNER_H_
+#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DB_DATA_OWNER_H_
#include <memory>
#include <vector>
@@ -64,4 +64,4 @@ class DBDataOwner {
};
} // namespace data_reduction_proxy
-#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DB_SERVICE_H_
+#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DB_DATA_OWNER_H_
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
index f3e6d583361..cc6cb47d179 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
@@ -5,12 +5,8 @@
#ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_HEADERS_H_
#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_HEADERS_H_
-#include <string>
-#include <vector>
-
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "base/time/time.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
@@ -26,7 +22,6 @@ namespace data_reduction_proxy {
// Gets the header used for data reduction proxy requests and responses.
const char* chrome_proxy_header();
-
// Returns the Original-Full-Content-Length(OFCL) value in the Chrome-Proxy
// header. Returns -1 in case of of error or if OFCL does not exist. |headers|
// must be non-null.
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
index 6500d015c36..31a33d5af05 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -10,8 +10,7 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
-#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace data_reduction_proxy {
diff --git a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
index 1491c21849a..468dca549d9 100644
--- a/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
+++ b/chromium/components/data_reduction_proxy/core/common/data_reduction_proxy_params_unittest.cc
@@ -15,7 +15,6 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_param_associator.h"
#include "base/metrics/field_trial_params.h"
-#include "base/optional.h"
#include "base/test/scoped_feature_list.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
@@ -23,6 +22,7 @@
#include "net/http/http_status_code.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if defined(OS_ANDROID)
#include "base/system/sys_info.h"
diff --git a/chromium/components/data_use_measurement/core/data_use.h b/chromium/components/data_use_measurement/core/data_use.h
index d9b41e2bb7e..8d4812a9317 100644
--- a/chromium/components/data_use_measurement/core/data_use.h
+++ b/chromium/components/data_use_measurement/core/data_use.h
@@ -11,7 +11,6 @@
#include "base/macros.h"
#include "base/supports_user_data.h"
-#include "base/time/time.h"
#include "url/gurl.h"
namespace data_use_measurement {
diff --git a/chromium/components/data_use_measurement/core/data_use_measurement.h b/chromium/components/data_use_measurement/core/data_use_measurement.h
index 6b5d3e84193..cac4f56c31d 100644
--- a/chromium/components/data_use_measurement/core/data_use_measurement.h
+++ b/chromium/components/data_use_measurement/core/data_use_measurement.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_DATA_USE_MEASUREMENT_CONTENT_DATA_USE_MEASUREMENT_H_
-#define COMPONENTS_DATA_USE_MEASUREMENT_CONTENT_DATA_USE_MEASUREMENT_H_
+#ifndef COMPONENTS_DATA_USE_MEASUREMENT_CORE_DATA_USE_MEASUREMENT_H_
+#define COMPONENTS_DATA_USE_MEASUREMENT_CORE_DATA_USE_MEASUREMENT_H_
#include <stdint.h>
@@ -15,7 +15,6 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
-#include "base/time/time.h"
#include "build/build_config.h"
#include "components/data_use_measurement/core/data_use_tracker_prefs.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
@@ -198,4 +197,4 @@ class DataUseMeasurement
} // namespace data_use_measurement
-#endif // COMPONENTS_DATA_USE_MEASUREMENT_CONTENT_DATA_USE_MEASUREMENT_H_
+#endif // COMPONENTS_DATA_USE_MEASUREMENT_CORE_DATA_USE_MEASUREMENT_H_
diff --git a/chromium/components/data_use_measurement/core/data_use_pref_names.h b/chromium/components/data_use_measurement/core/data_use_pref_names.h
index 5135a402e03..cdc5f1e77a5 100644
--- a/chromium/components/data_use_measurement/core/data_use_pref_names.h
+++ b/chromium/components/data_use_measurement/core/data_use_pref_names.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_DATA_USE_MEASUREMENT_CORE_DATA_USE_PREF_NAMES_H_
#define COMPONENTS_DATA_USE_MEASUREMENT_CORE_DATA_USE_PREF_NAMES_H_
-#include <memory>
-
#include "base/macros.h"
namespace data_use_measurement {
diff --git a/chromium/components/data_use_measurement/core/data_use_tracker_prefs.cc b/chromium/components/data_use_measurement/core/data_use_tracker_prefs.cc
index e29bedb08ad..13ef991a72a 100644
--- a/chromium/components/data_use_measurement/core/data_use_tracker_prefs.cc
+++ b/chromium/components/data_use_measurement/core/data_use_tracker_prefs.cc
@@ -17,6 +17,8 @@
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/time/clock.h"
+#include "base/time/time.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "components/data_use_measurement/core/data_use_pref_names.h"
#include "components/prefs/pref_registry_simple.h"
@@ -78,7 +80,8 @@ void DataUseTrackerPrefs::RemoveExpiredEntriesForPref(
base::Time key_date;
if (base::Time::FromUTCString(it.first.c_str(), &key_date) &&
key_date > last_date) {
- user_pref_new_dict.Set(it.first, it.second.CreateDeepCopy());
+ user_pref_new_dict.Set(it.first,
+ base::Value::ToUniquePtrValue(it.second.Clone()));
}
}
pref_service_->Set(pref_name, user_pref_new_dict);
diff --git a/chromium/components/data_use_measurement/core/data_use_tracker_prefs_unittest.cc b/chromium/components/data_use_measurement/core/data_use_tracker_prefs_unittest.cc
index 1e0c7e3aae1..f01213f584a 100644
--- a/chromium/components/data_use_measurement/core/data_use_tracker_prefs_unittest.cc
+++ b/chromium/components/data_use_measurement/core/data_use_tracker_prefs_unittest.cc
@@ -58,43 +58,43 @@ TEST(DataUseTrackerPrefsTest, PrefsOnMeteredConnection) {
DataUseTrackerPrefsTest tracker_prefs_test_1(&clock, &test_prefs);
tracker_prefs_test_1.data_use_tracker_prefs()->ReportNetworkServiceDataUse(
true, true, true, 10);
- EXPECT_EQ(1u,
- test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->size());
+ EXPECT_EQ(
+ 1u, test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->DictSize());
tracker_prefs_test_1.data_use_tracker_prefs()->ReportNetworkServiceDataUse(
true, true, true, 10);
- EXPECT_EQ(1u,
- test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->size());
+ EXPECT_EQ(
+ 1u, test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->DictSize());
// Verify other prefs are not set.
EXPECT_TRUE(
- test_prefs.GetDictionary(prefs::kDataUsedUserBackground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedUserBackground)->DictEmpty());
EXPECT_TRUE(
- test_prefs.GetDictionary(prefs::kDataUsedServicesForeground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedServicesForeground)->DictEmpty());
EXPECT_TRUE(
- test_prefs.GetDictionary(prefs::kDataUsedServicesBackground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedServicesBackground)->DictEmpty());
// Move clock forward 10 days. New data use reported must go in a separate
// entry in the dictionary pref.
clock.Advance(base::TimeDelta::FromDays(10));
DataUseTrackerPrefsTest tracker_prefs_test_2(&clock, &test_prefs);
- EXPECT_EQ(1u,
- test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->size());
+ EXPECT_EQ(
+ 1u, test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->DictSize());
tracker_prefs_test_2.data_use_tracker_prefs()->ReportNetworkServiceDataUse(
true, true, true, 10);
- EXPECT_EQ(2u,
- test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->size());
+ EXPECT_EQ(
+ 2u, test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->DictSize());
// Move clock forward 55 days. This should clean up the first entry since they
// are now 65 days older (i.e., more than 60 days old). New data use reported
// must go in a separate entry in the dictionary pref.
clock.Advance(base::TimeDelta::FromDays(55));
DataUseTrackerPrefsTest tracker_prefs_test_3(&clock, &test_prefs);
- EXPECT_EQ(1u,
- test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->size());
+ EXPECT_EQ(
+ 1u, test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->DictSize());
tracker_prefs_test_2.data_use_tracker_prefs()->ReportNetworkServiceDataUse(
true, true, true, 10);
- EXPECT_EQ(2u,
- test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->size());
+ EXPECT_EQ(
+ 2u, test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->DictSize());
}
// Verifies that the prefs are not updated on unmetered connections.
@@ -113,13 +113,13 @@ TEST(DataUseTrackerPrefsTest, PrefsOnUnmeteredConnection) {
// Verify prefs are not set.
EXPECT_TRUE(
- test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->DictEmpty());
EXPECT_TRUE(
- test_prefs.GetDictionary(prefs::kDataUsedUserBackground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedUserBackground)->DictEmpty());
EXPECT_TRUE(
- test_prefs.GetDictionary(prefs::kDataUsedServicesForeground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedServicesForeground)->DictEmpty());
EXPECT_TRUE(
- test_prefs.GetDictionary(prefs::kDataUsedServicesBackground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedServicesBackground)->DictEmpty());
}
TEST(DataUseTrackerPrefsTest, TestBasicUserForeground) {
@@ -152,21 +152,21 @@ TEST(DataUseTrackerPrefsTest, TestBasicUserForeground) {
true, test.foreground, test.user_initiated, 10);
// Verify that the expected pref has an entry.
EXPECT_FALSE(
- test_prefs.GetDictionary(test.pref_expected_as_non_empty)->empty());
+ test_prefs.GetDictionary(test.pref_expected_as_non_empty)->DictEmpty());
// Verify other prefs are not set.
EXPECT_TRUE(
test.pref_expected_as_non_empty == prefs::kDataUsedUserForeground ||
- test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedUserForeground)->DictEmpty());
EXPECT_TRUE(
test.pref_expected_as_non_empty == prefs::kDataUsedUserBackground ||
- test_prefs.GetDictionary(prefs::kDataUsedUserBackground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedUserBackground)->DictEmpty());
EXPECT_TRUE(
test.pref_expected_as_non_empty == prefs::kDataUsedServicesForeground ||
- test_prefs.GetDictionary(prefs::kDataUsedServicesForeground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedServicesForeground)->DictEmpty());
EXPECT_TRUE(
test.pref_expected_as_non_empty == prefs::kDataUsedServicesBackground ||
- test_prefs.GetDictionary(prefs::kDataUsedServicesBackground)->empty());
+ test_prefs.GetDictionary(prefs::kDataUsedServicesBackground)->DictEmpty());
}
}
diff --git a/chromium/components/data_use_measurement/core/data_use_user_data.h b/chromium/components/data_use_measurement/core/data_use_user_data.h
index f7f35e06ab7..e7eaaefb8f9 100644
--- a/chromium/components/data_use_measurement/core/data_use_user_data.h
+++ b/chromium/components/data_use_measurement/core/data_use_user_data.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_DATA_USE_MEASUREMENT_CORE_DATA_USE_USER_DATA_H_
#define COMPONENTS_DATA_USE_MEASUREMENT_CORE_DATA_USE_USER_DATA_H_
-#include <memory>
-#include <string>
-
#include "base/macros.h"
#include "base/supports_user_data.h"
diff --git a/chromium/components/desks_storage/OWNERS b/chromium/components/desks_storage/OWNERS
new file mode 100644
index 00000000000..7d6a9c2a6b8
--- /dev/null
+++ b/chromium/components/desks_storage/OWNERS
@@ -0,0 +1,5 @@
+afakhry@chromium.org
+avynn@google.com
+richui@google.com
+xdai@chromium.org
+yzd@google.com \ No newline at end of file
diff --git a/chromium/components/desks_storage/README.md b/chromium/components/desks_storage/README.md
new file mode 100644
index 00000000000..2af15469396
--- /dev/null
+++ b/chromium/components/desks_storage/README.md
@@ -0,0 +1,3 @@
+The desks storage component contains code necessary for saving user's
+desk as desk templates to Chrome Sync and loading desk templates from
+Chrome Sync and enterprise policy.
diff --git a/chromium/components/device_event_log/device_event_log.h b/chromium/components/device_event_log/device_event_log.h
index bc5e62694eb..10b3bc95bec 100644
--- a/chromium/components/device_event_log/device_event_log.h
+++ b/chromium/components/device_event_log/device_event_log.h
@@ -278,4 +278,4 @@ class DEVICE_EVENT_LOG_EXPORT ScopedDeviceLogIfSlow {
} // namespace device_event_log
-#endif // DEVICE_EVENT_LOG_DEVICE_EVENT_LOG_H_
+#endif // COMPONENTS_DEVICE_EVENT_LOG_DEVICE_EVENT_LOG_H_
diff --git a/chromium/components/device_event_log/device_event_log_impl.cc b/chromium/components/device_event_log/device_event_log_impl.cc
index cb915f66873..f2ad3af561c 100644
--- a/chromium/components/device_event_log/device_event_log_impl.cc
+++ b/chromium/components/device_event_log/device_event_log_impl.cc
@@ -26,19 +26,19 @@ namespace device_event_log {
namespace {
-const char* kLogLevelName[] = {"Error", "User", "Event", "Debug"};
-
-const char* kLogTypeNetworkDesc = "Network";
-const char* kLogTypePowerDesc = "Power";
-const char* kLogTypeLoginDesc = "Login";
-const char* kLogTypeBluetoothDesc = "Bluetooth";
-const char* kLogTypeUsbDesc = "USB";
-const char* kLogTypeHidDesc = "HID";
-const char* kLogTypeMemoryDesc = "Memory";
-const char* kLogTypePrinterDesc = "Printer";
-const char* kLogTypeFidoDesc = "FIDO";
-const char* kLogTypeSerialDesc = "Serial";
-const char* kLogTypeCameraDesc = "Camera";
+const char* const kLogLevelName[] = {"Error", "User", "Event", "Debug"};
+
+const char kLogTypeNetworkDesc[] = "Network";
+const char kLogTypePowerDesc[] = "Power";
+const char kLogTypeLoginDesc[] = "Login";
+const char kLogTypeBluetoothDesc[] = "Bluetooth";
+const char kLogTypeUsbDesc[] = "USB";
+const char kLogTypeHidDesc[] = "HID";
+const char kLogTypeMemoryDesc[] = "Memory";
+const char kLogTypePrinterDesc[] = "Printer";
+const char kLogTypeFidoDesc[] = "FIDO";
+const char kLogTypeSerialDesc[] = "Serial";
+const char kLogTypeCameraDesc[] = "Camera";
enum class ShowTime {
kNone,
@@ -77,7 +77,7 @@ std::string GetLogTypeString(LogType type) {
return "Unknown";
}
-LogType GetLogTypeFromString(const std::string& desc) {
+LogType GetLogTypeFromString(base::StringPiece desc) {
std::string desc_lc = base::ToLowerASCII(desc);
for (int i = 0; i < LOG_TYPE_UNKNOWN; ++i) {
auto type = static_cast<LogType>(i);
@@ -248,24 +248,24 @@ void GetFormat(const std::string& format_string,
*show_level = false;
*format_json = false;
while (tokens.GetNext()) {
- std::string tok(tokens.token());
- if (tok == "time")
+ base::StringPiece tok = tokens.token_piece();
+ if (tok == "time") {
*show_time = ShowTime::kTimeWithMs;
- if (tok == "unixtime") {
+ } else if (tok == "unixtime") {
#if defined(OS_POSIX)
*show_time = ShowTime::kUnix;
#else
*show_time = ShowTime::kTimeWithMs;
#endif
- }
- if (tok == "file")
+ } else if (tok == "file") {
*show_file = true;
- if (tok == "type")
+ } else if (tok == "type") {
*show_type = true;
- if (tok == "level")
+ } else if (tok == "level") {
*show_level = true;
- if (tok == "json")
+ } else if (tok == "json") {
*format_json = true;
+ }
}
}
@@ -274,8 +274,8 @@ void GetLogTypes(const std::string& types,
std::set<LogType>* exclude_types) {
base::StringTokenizer tokens(types, ",");
while (tokens.GetNext()) {
- std::string tok(tokens.token());
- if (tok.substr(0, 4) == "non-") {
+ base::StringPiece tok = tokens.token_piece();
+ if (base::StartsWith(tok, "non-")) {
LogType type = GetLogTypeFromString(tok.substr(4));
if (type != LOG_TYPE_UNKNOWN)
exclude_types->insert(type);
@@ -399,7 +399,7 @@ std::string DeviceEventLogImpl::GetAsString(StringOrder order,
GetLogTypes(types, &include_types, &exclude_types);
std::string result;
- base::ListValue log_entries;
+ base::Value log_entries(base::Value::Type::LIST);
if (order == OLDEST_FIRST) {
size_t offset = 0;
if (max_events > 0 && max_events < entries_.size()) {
@@ -428,7 +428,7 @@ std::string DeviceEventLogImpl::GetAsString(StringOrder order,
if (entry.log_level > max_level)
continue;
if (format_json) {
- log_entries.AppendString(LogEntryAsJSON(entry));
+ log_entries.Append(LogEntryAsJSON(entry));
} else {
result += LogEntryToString(entry, show_time, show_file, show_type,
show_level);
@@ -444,7 +444,7 @@ std::string DeviceEventLogImpl::GetAsString(StringOrder order,
if (entry.log_level > max_level)
continue;
if (format_json) {
- log_entries.AppendString(LogEntryAsJSON(entry));
+ log_entries.Append(LogEntryAsJSON(entry));
} else {
result += LogEntryToString(entry, show_time, show_file, show_type,
show_level);
diff --git a/chromium/components/digital_asset_links/digital_asset_links_handler.cc b/chromium/components/digital_asset_links/digital_asset_links_handler.cc
index 0bc633ff9f3..72a7e391107 100644
--- a/chromium/components/digital_asset_links/digital_asset_links_handler.cc
+++ b/chromium/components/digital_asset_links/digital_asset_links_handler.cc
@@ -129,7 +129,7 @@ DigitalAssetLinksHandler::~DigitalAssetLinksHandler() = default;
void DigitalAssetLinksHandler::OnURLLoadComplete(
std::string relationship,
- base::Optional<std::string> fingerprint,
+ absl::optional<std::string> fingerprint,
std::map<std::string, std::set<std::string>> target_values,
std::unique_ptr<std::string> response_body) {
int response_code = -1;
@@ -166,7 +166,7 @@ void DigitalAssetLinksHandler::OnURLLoadComplete(
void DigitalAssetLinksHandler::OnJSONParseResult(
std::string relationship,
- base::Optional<std::string> fingerprint,
+ absl::optional<std::string> fingerprint,
std::map<std::string, std::set<std::string>> target_values,
data_decoder::DataDecoder::ValueOrError result) {
if (!result.value) {
@@ -245,14 +245,14 @@ bool DigitalAssetLinksHandler::CheckDigitalAssetLinkRelationshipForWebApk(
const std::string& manifest_url,
RelationshipCheckResultCallback callback) {
return CheckDigitalAssetLinkRelationship(
- web_domain, "delegate_permission/common.query_webapk", base::nullopt,
+ web_domain, "delegate_permission/common.query_webapk", absl::nullopt,
{{"namespace", {"web"}}, {"site", {manifest_url}}}, std::move(callback));
}
bool DigitalAssetLinksHandler::CheckDigitalAssetLinkRelationship(
const std::string& web_domain,
const std::string& relationship,
- const base::Optional<std::string>& fingerprint,
+ const absl::optional<std::string>& fingerprint,
const std::map<std::string, std::set<std::string>>& target_values,
RelationshipCheckResultCallback callback) {
// TODO(peconn): Propagate the use of url::Origin backwards to clients.
diff --git a/chromium/components/digital_asset_links/digital_asset_links_handler.h b/chromium/components/digital_asset_links/digital_asset_links_handler.h
index d612ccdf37c..8d2177a5843 100644
--- a/chromium/components/digital_asset_links/digital_asset_links_handler.h
+++ b/chromium/components/digital_asset_links/digital_asset_links_handler.h
@@ -11,11 +11,10 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
-#include "base/values.h"
#include "content/public/browser/web_contents_observer.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace network {
class SharedURLLoaderFactory;
@@ -88,7 +87,7 @@ class DigitalAssetLinksHandler : public content::WebContentsObserver {
bool CheckDigitalAssetLinkRelationship(
const std::string& web_domain,
const std::string& relationship,
- const base::Optional<std::string>& fingerprint,
+ const absl::optional<std::string>& fingerprint,
const std::map<std::string, std::set<std::string>>& target_values,
RelationshipCheckResultCallback callback);
@@ -100,14 +99,14 @@ class DigitalAssetLinksHandler : public content::WebContentsObserver {
private:
void OnURLLoadComplete(
std::string relationship,
- base::Optional<std::string> fingerprint,
+ absl::optional<std::string> fingerprint,
std::map<std::string, std::set<std::string>> target_values,
std::unique_ptr<std::string> response_body);
// Callback for the DataDecoder.
void OnJSONParseResult(
std::string relationship,
- base::Optional<std::string> fingerprint,
+ absl::optional<std::string> fingerprint,
std::map<std::string, std::set<std::string>> target_values,
data_decoder::DataDecoder::ValueOrError result);
diff --git a/chromium/components/discardable_memory/client/client_discardable_shared_memory_manager.cc b/chromium/components/discardable_memory/client/client_discardable_shared_memory_manager.cc
index b222ccd4e7d..e1d9286de4f 100644
--- a/chromium/components/discardable_memory/client/client_discardable_shared_memory_manager.cc
+++ b/chromium/components/discardable_memory/client/client_discardable_shared_memory_manager.cc
@@ -14,12 +14,11 @@
#include "base/macros.h"
#include "base/memory/discardable_memory.h"
#include "base/memory/discardable_shared_memory.h"
+#include "base/memory/page_size.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/memory.h"
-#include "base/process/process_metrics.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/system/sys_info.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -322,6 +321,9 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
// at least one span from the free lists.
MemoryUsageChanged(heap_->GetSize(), heap_->GetFreelistSize());
+ // Memory in this span is no longer held in the freelist, so we don't want
+ // to count it towards the total of dirty freelist memory.
+ heap_->dirty_freed_memory_page_count_ -= free_span->MarkAsClean();
auto discardable_memory =
std::make_unique<DiscardableMemoryImpl>(this, std::move(free_span));
allocated_memory_.insert(discardable_memory.get());
@@ -374,7 +376,7 @@ ClientDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
reinterpret_cast<size_t>(leftover->shared_memory()->memory()),
leftover->length() * base::GetPageSize());
leftover->set_is_locked(false);
- heap_->MergeIntoFreeLists(std::move(leftover));
+ heap_->MergeIntoFreeListsClean(std::move(leftover));
}
if (pages >= allocation_pages) {
@@ -406,6 +408,11 @@ bool ClientDiscardableSharedMemoryManager::OnMemoryDump(
base::UmaHistogramCounts1M("Memory.Discardable.Size.Foreground",
total_size - freelist_size);
}
+
+ base::UmaHistogramCounts1M(
+ "Memory.Discardable.FreelistSize.Dirty",
+ heap_->dirty_freed_memory_page_count_ * base::GetPageSize() / 1024);
+
return heap_->OnMemoryDump(args, pmd);
}
diff --git a/chromium/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc b/chromium/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc
index 1d425615c99..cf0fea4d33f 100644
--- a/chromium/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc
+++ b/chromium/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc
@@ -5,7 +5,7 @@
#include "components/discardable_memory/client/client_discardable_shared_memory_manager.h"
#include "base/memory/discardable_memory.h"
#include "base/memory/discardable_shared_memory.h"
-#include "base/process/process_metrics.h"
+#include "base/memory/page_size.h"
#include "base/synchronization/lock.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
@@ -65,6 +65,11 @@ class TestClientDiscardableSharedMemoryManager
return heap_->GetFreelistSize();
}
+ size_t GetDirtyFreedMemoryPageCount() const {
+ base::AutoLock lock(lock_);
+ return heap_->dirty_freed_memory_page_count_;
+ }
+
bool IsPurgeScheduled() const {
base::AutoLock lock(lock_);
return is_purge_scheduled_;
@@ -458,5 +463,79 @@ TEST_F(ClientDiscardableSharedMemoryManagerTest,
EXPECT_FALSE(client->IsPurgeScheduled());
}
+TEST_F(ClientDiscardableSharedMemoryManagerTest, MarkDirtyFreelistPages) {
+ auto client =
+ base::MakeRefCounted<TestClientDiscardableSharedMemoryManager>();
+
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+
+ auto mem1 = client->AllocateLockedDiscardableMemory(base::GetPageSize() / 2u);
+
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+
+ auto mem2 =
+ client->AllocateLockedDiscardableMemory(base::GetPageSize() * 1.2);
+
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+
+ // Allocate 5 MiB. This is to test large allocations, which are special-cased
+ // when allocating.
+ auto mem3 = client->AllocateLockedDiscardableMemory(5 * 1024 * 1024);
+
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+
+ mem1 = nullptr;
+
+ ASSERT_EQ(1u, client->GetDirtyFreedMemoryPageCount());
+
+ mem2 = nullptr;
+
+ // Allocations on done in multiples of the page size, so we have 3 pages
+ // dirtied, even though we only actually touched 1.7 pages (since the 0.5 page
+ // allocation used 1 page, and the 1.2 page allocation used 2).
+ ASSERT_EQ(3u, client->GetDirtyFreedMemoryPageCount());
+
+ mem3 = nullptr;
+
+ ASSERT_EQ(1283u, client->GetDirtyFreedMemoryPageCount());
+
+ client->ReleaseFreeMemory();
+
+ // All pages should be freed now, so there are no dirty pages in the freelist.
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+}
+
+TEST_F(ClientDiscardableSharedMemoryManagerTest,
+ MarkDirtyFreelistPagesReleaseFreeListPages) {
+ base::test::ScopedFeatureList fl;
+ fl.InitAndEnableFeature(discardable_memory::kReleaseDiscardableFreeListPages);
+ auto client =
+ base::MakeRefCounted<TestClientDiscardableSharedMemoryManager>();
+
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+
+ auto mem1 = client->AllocateLockedDiscardableMemory(base::GetPageSize() / 2u);
+
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+
+ auto mem2 =
+ client->AllocateLockedDiscardableMemory(base::GetPageSize() * 1.2);
+
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+
+ mem1 = nullptr;
+
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+
+ mem2 = nullptr;
+
+ // Freelist memory is released immediately, so there's no dirty memory.
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+
+ client->ReleaseFreeMemory();
+
+ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount());
+}
+
} // namespace
} // namespace discardable_memory
diff --git a/chromium/components/discardable_memory/common/discardable_shared_memory_heap.cc b/chromium/components/discardable_memory/common/discardable_shared_memory_heap.cc
index b0751f27fc1..c6deffd3804 100644
--- a/chromium/components/discardable_memory/common/discardable_shared_memory_heap.cc
+++ b/chromium/components/discardable_memory/common/discardable_shared_memory_heap.cc
@@ -14,6 +14,7 @@
#include "base/format_macros.h"
#include "base/memory/aligned_memory.h"
#include "base/memory/discardable_shared_memory.h"
+#include "base/memory/page_size.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
@@ -36,31 +37,70 @@ bool IsInFreeList(DiscardableSharedMemoryHeap::Span* span) {
DiscardableSharedMemoryHeap::Span::Span(
base::DiscardableSharedMemory* shared_memory,
size_t start,
- size_t length)
- : shared_memory_(shared_memory),
+ size_t length,
+ DiscardableSharedMemoryHeap::ScopedMemorySegment* memory_segment)
+ : memory_segment_(memory_segment),
+ shared_memory_(shared_memory),
start_(start),
length_(length),
is_locked_(false) {}
-DiscardableSharedMemoryHeap::Span::~Span() {}
-
DiscardableSharedMemoryHeap::ScopedMemorySegment::ScopedMemorySegment(
DiscardableSharedMemoryHeap* heap,
std::unique_ptr<base::DiscardableSharedMemory> shared_memory,
size_t size,
int32_t id,
base::OnceClosure deleted_callback)
- : heap_(heap),
+ : dirty_pages_(std::vector<bool>(size / base::GetPageSize())),
+ heap_(heap),
shared_memory_(std::move(shared_memory)),
size_(size),
id_(id),
deleted_callback_(std::move(deleted_callback)) {}
+size_t DiscardableSharedMemoryHeap::Span::MarkAsClean() {
+ return memory_segment_->MarkPages(start_, length_, false);
+}
+
+size_t DiscardableSharedMemoryHeap::Span::MarkAsDirty() {
+ return memory_segment_->MarkPages(start_, length_, true);
+}
+
+DiscardableSharedMemoryHeap::ScopedMemorySegment*
+DiscardableSharedMemoryHeap::Span::GetScopedMemorySegmentForTesting() const {
+ return memory_segment_;
+}
+
DiscardableSharedMemoryHeap::ScopedMemorySegment::~ScopedMemorySegment() {
+ heap_->dirty_freed_memory_page_count_ -= MarkPages(
+ reinterpret_cast<size_t>(shared_memory_->memory()) / base::GetPageSize(),
+ dirty_pages_.size(), false);
heap_->ReleaseMemory(shared_memory_.get(), size_);
std::move(deleted_callback_).Run();
}
+size_t DiscardableSharedMemoryHeap::ScopedMemorySegment::MarkPages(
+ size_t start,
+ size_t length,
+ bool value) {
+ if (!shared_memory_)
+ return 0;
+
+ const size_t offset =
+ start -
+ reinterpret_cast<size_t>(shared_memory_->memory()) / base::GetPageSize();
+
+ size_t tmp = 0;
+ for (size_t i = offset; i < offset + length; i++) {
+ if (dirty_pages_[i] != value) {
+ dirty_pages_[i] = value;
+ tmp++;
+ }
+ }
+
+ return tmp;
+}
+
bool DiscardableSharedMemoryHeap::ScopedMemorySegment::IsUsed() const {
return heap_->IsMemoryUsed(shared_memory_.get(), size_);
}
@@ -74,6 +114,11 @@ bool DiscardableSharedMemoryHeap::ScopedMemorySegment::ContainsSpan(
return shared_memory_.get() == span->shared_memory();
}
+size_t DiscardableSharedMemoryHeap::ScopedMemorySegment::CountMarkedPages()
+ const {
+ return std::count(dirty_pages_.begin(), dirty_pages_.end(), true);
+}
+
base::trace_event::MemoryAllocatorDump*
DiscardableSharedMemoryHeap::ScopedMemorySegment::CreateMemoryAllocatorDump(
Span* span,
@@ -124,10 +169,13 @@ DiscardableSharedMemoryHeap::Grow(
DCHECK(base::IsAligned(shared_memory->memory(), block_size_));
DCHECK(base::IsAligned(size, block_size_));
- std::unique_ptr<Span> span(
- new Span(shared_memory.get(),
- reinterpret_cast<size_t>(shared_memory->memory()) / block_size_,
- size / block_size_));
+ auto* raw_shared_memory = shared_memory.get();
+ auto scoped_memory_segment = std::make_unique<ScopedMemorySegment>(
+ this, std::move(shared_memory), size, id, std::move(deleted_callback));
+ std::unique_ptr<Span> span(new Span(
+ raw_shared_memory,
+ reinterpret_cast<size_t>(raw_shared_memory->memory()) / block_size_,
+ size / block_size_, scoped_memory_segment.get()));
DCHECK(spans_.find(span->start_) == spans_.end());
DCHECK(spans_.find(span->start_ + span->length_ - 1) == spans_.end());
RegisterSpan(span.get());
@@ -135,18 +183,22 @@ DiscardableSharedMemoryHeap::Grow(
num_blocks_ += span->length_;
// Start tracking if segment is resident by adding it to |memory_segments_|.
- memory_segments_.push_back(std::make_unique<ScopedMemorySegment>(
- this, std::move(shared_memory), size, id, std::move(deleted_callback)));
+ memory_segments_.push_back(std::move(scoped_memory_segment));
return span;
}
void DiscardableSharedMemoryHeap::MergeIntoFreeLists(
std::unique_ptr<Span> span) {
- DCHECK(span->shared_memory_);
+ if (!base::FeatureList::IsEnabled(kReleaseDiscardableFreeListPages)) {
+ dirty_freed_memory_page_count_ += span->MarkAsDirty();
+ }
+ MergeIntoFreeListsClean(std::move(span));
+}
- // First add length of |span| to |num_free_blocks_|.
- num_free_blocks_ += span->length_;
+void DiscardableSharedMemoryHeap::MergeIntoFreeListsClean(
+ std::unique_ptr<Span> span) {
+ DCHECK(span->shared_memory_);
if (base::FeatureList::IsEnabled(kReleaseDiscardableFreeListPages)) {
SCOPED_UMA_HISTOGRAM_SHORT_TIMER("Memory.Discardable.FreeListReleaseTime");
@@ -167,6 +219,9 @@ void DiscardableSharedMemoryHeap::MergeIntoFreeLists(
offset, span->length_ * base::GetPageSize());
}
+ // First add length of |span| to |num_free_blocks_|.
+ num_free_blocks_ += span->length_;
+
// Merge with previous span if possible.
auto prev_it = spans_.find(span->start_ - 1);
if (prev_it != spans_.end() && IsInFreeList(prev_it->second)) {
@@ -200,8 +255,9 @@ DiscardableSharedMemoryHeap::Split(Span* span, size_t blocks) {
DCHECK(blocks);
DCHECK_LT(blocks, span->length_);
- std::unique_ptr<Span> leftover(new Span(
- span->shared_memory_, span->start_ + blocks, span->length_ - blocks));
+ std::unique_ptr<Span> leftover(
+ new Span(span->shared_memory_, span->start_ + blocks,
+ span->length_ - blocks, span->memory_segment_));
DCHECK(leftover->length_ == 1 ||
spans_.find(leftover->start_) == spans_.end());
RegisterSpan(leftover.get());
@@ -275,7 +331,7 @@ size_t DiscardableSharedMemoryHeap::GetFreelistSize() const {
return num_free_blocks_ * block_size_;
}
-base::Optional<size_t> DiscardableSharedMemoryHeap::GetResidentSize() const {
+absl::optional<size_t> DiscardableSharedMemoryHeap::GetResidentSize() const {
size_t resident_size = 0;
// Each member of |free_spans_| is a LinkedList of Spans. We need to iterate
// over each of these.
@@ -287,11 +343,11 @@ base::Optional<size_t> DiscardableSharedMemoryHeap::GetResidentSize() const {
// |shared_memory|) has Span::start_ initialized to a value equivalent
// to reinterpret_cast<shared_memory->memory()) / block_size_.
void* mem = reinterpret_cast<void*>(free_span->start() * block_size_);
- base::Optional<size_t> resident_in_span =
+ absl::optional<size_t> resident_in_span =
base::trace_event::ProcessMemoryDump::CountResidentBytes(
mem, free_span->length() * base::GetPageSize());
if (!resident_in_span)
- return base::nullopt;
+ return absl::nullopt;
resident_size += resident_in_span.value();
}
}
@@ -310,6 +366,9 @@ bool DiscardableSharedMemoryHeap::OnMemoryDump(
total_dump->AddScalar("freelist_size",
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
freelist_size);
+ total_dump->AddScalar("freelist_size_dirty",
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ dirty_freed_memory_page_count_ * base::GetPageSize());
if (args.level_of_detail ==
base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
// These metrics (size and virtual size) are also reported by each
@@ -363,8 +422,9 @@ DiscardableSharedMemoryHeap::Carve(Span* span, size_t blocks) {
const size_t extra = serving->length_ - blocks;
if (extra) {
- std::unique_ptr<Span> leftover(
- new Span(serving->shared_memory_, serving->start_ + blocks, extra));
+ std::unique_ptr<Span> leftover(new Span(serving->shared_memory_,
+ serving->start_ + blocks, extra,
+ serving->memory_segment_));
leftover->set_is_locked(false);
DCHECK(extra == 1 || spans_.find(leftover->start_) == spans_.end());
RegisterSpan(leftover.get());
diff --git a/chromium/components/discardable_memory/common/discardable_shared_memory_heap.h b/chromium/components/discardable_memory/common/discardable_shared_memory_heap.h
index d4de3fe822c..23f80bc9699 100644
--- a/chromium/components/discardable_memory/common/discardable_shared_memory_heap.h
+++ b/chromium/components/discardable_memory/common/discardable_shared_memory_heap.h
@@ -14,6 +14,7 @@
#include "base/callback.h"
#include "base/containers/linked_list.h"
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/trace_event/process_memory_dump.h"
#include "components/discardable_memory/common/discardable_memory_export.h"
@@ -24,26 +25,43 @@ class DiscardableSharedMemory;
namespace discardable_memory {
+DISCARDABLE_MEMORY_EXPORT extern const base::Feature
+ kReleaseDiscardableFreeListPages;
+
// Implements a heap of discardable shared memory. An array of free lists
// is used to keep track of free blocks.
class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryHeap {
+ private:
+ class ScopedMemorySegment;
+
public:
class DISCARDABLE_MEMORY_EXPORT Span : public base::LinkNode<Span> {
public:
- ~Span();
+ ~Span() = default;
base::DiscardableSharedMemory* shared_memory() { return shared_memory_; }
size_t start() const { return start_; }
size_t length() const { return length_; }
void set_is_locked(bool is_locked) { is_locked_ = is_locked; }
+ // Marks all bytes in this Span as dirty, returns the number of pages
+ // marked as dirty this way.
+ size_t MarkAsDirty();
+ // Marks all bytes in this Span as non-dirty, returning the number of
+ // pages marked as non-dirty this way.
+ size_t MarkAsClean();
+
+ ScopedMemorySegment* GetScopedMemorySegmentForTesting() const;
+
private:
friend class DiscardableSharedMemoryHeap;
Span(base::DiscardableSharedMemory* shared_memory,
size_t start,
- size_t length);
+ size_t length,
+ DiscardableSharedMemoryHeap::ScopedMemorySegment* memory_segment);
+ DiscardableSharedMemoryHeap::ScopedMemorySegment* const memory_segment_;
base::DiscardableSharedMemory* shared_memory_;
size_t start_;
size_t length_;
@@ -69,6 +87,11 @@ class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryHeap {
// neighboring free spans when possible.
void MergeIntoFreeLists(std::unique_ptr<Span> span);
+ // Same as |MergeIntoFreeLists|, but doesn't mark the memory in the span as
+ // dirtied (this is used for keeping track of how much memory is dirtied in
+ // the freelist at any given time.
+ void MergeIntoFreeListsClean(std::unique_ptr<Span> span);
+
// Split an allocated span into two spans, one of length |blocks| followed
// by another span of length "span->length - blocks" blocks. Modifies |span|
// to point to the first span of length |blocks|. Return second span.
@@ -104,8 +127,10 @@ class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryHeap {
const char* name,
base::trace_event::ProcessMemoryDump* pmd) const;
+ size_t dirty_freed_memory_page_count_ = 0;
+
private:
- class ScopedMemorySegment {
+ class DISCARDABLE_MEMORY_EXPORT ScopedMemorySegment {
public:
ScopedMemorySegment(
DiscardableSharedMemoryHeap* heap,
@@ -120,6 +145,8 @@ class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryHeap {
bool ContainsSpan(Span* span) const;
+ size_t CountMarkedPages() const;
+
base::trace_event::MemoryAllocatorDump* CreateMemoryAllocatorDump(
Span* span,
size_t block_size,
@@ -129,7 +156,10 @@ class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryHeap {
// Used for dumping memory statistics from the segment to chrome://tracing.
void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd) const;
+ size_t MarkPages(size_t start, size_t length, bool value);
+
private:
+ std::vector<bool> dirty_pages_;
DiscardableSharedMemoryHeap* const heap_;
std::unique_ptr<base::DiscardableSharedMemory> shared_memory_;
const size_t size_;
@@ -150,7 +180,7 @@ class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryHeap {
void ReleaseMemory(const base::DiscardableSharedMemory* shared_memory,
size_t size);
- base::Optional<size_t> GetResidentSize() const;
+ absl::optional<size_t> GetResidentSize() const;
// Dumps memory statistics about a memory segment for chrome://tracing.
void OnMemoryDump(const base::DiscardableSharedMemory* shared_memory,
diff --git a/chromium/components/discardable_memory/common/discardable_shared_memory_heap_perftest.cc b/chromium/components/discardable_memory/common/discardable_shared_memory_heap_perftest.cc
index e2100e442a7..915c0a53fa0 100644
--- a/chromium/components/discardable_memory/common/discardable_shared_memory_heap_perftest.cc
+++ b/chromium/components/discardable_memory/common/discardable_shared_memory_heap_perftest.cc
@@ -14,7 +14,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/memory/discardable_shared_memory.h"
-#include "base/process/process_metrics.h"
+#include "base/memory/page_size.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_result_reporter.h"
diff --git a/chromium/components/discardable_memory/common/discardable_shared_memory_heap_unittest.cc b/chromium/components/discardable_memory/common/discardable_shared_memory_heap_unittest.cc
index f4ff0ecbb17..31ac6cf7715 100644
--- a/chromium/components/discardable_memory/common/discardable_shared_memory_heap_unittest.cc
+++ b/chromium/components/discardable_memory/common/discardable_shared_memory_heap_unittest.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/memory/discardable_shared_memory.h"
-#include "base/process/process_metrics.h"
+#include "base/memory/page_size.h"
#include "base/strings/stringprintf.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -361,11 +361,14 @@ TEST(DiscardableSharedMemoryHeapTest, OnMemoryDumpTest) {
"discardable/child_0x%" PRIXPTR, reinterpret_cast<uintptr_t>(&heap)));
ASSERT_NE(nullptr, dump);
- base::trace_event::MemoryAllocatorDump::Entry freelist("freelist_size",
- "bytes", 0);
+ base::trace_event::MemoryAllocatorDump::Entry freelist_size("freelist_size",
+ "bytes", 0);
+ base::trace_event::MemoryAllocatorDump::Entry freelist_size_dirty(
+ "freelist_size_dirty", "bytes", 0);
base::trace_event::MemoryAllocatorDump::Entry virtual_size("virtual_size",
"bytes", 0);
- EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist))));
+ EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist_size))));
+ EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist_size_dirty))));
EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(virtual_size))));
}
@@ -382,11 +385,14 @@ TEST(DiscardableSharedMemoryHeapTest, OnMemoryDumpTest) {
"discardable/child_0x%" PRIXPTR, reinterpret_cast<uintptr_t>(&heap)));
ASSERT_NE(nullptr, dump);
- base::trace_event::MemoryAllocatorDump::Entry freelist("freelist_size",
- "bytes", 0);
+ base::trace_event::MemoryAllocatorDump::Entry freelist_size("freelist_size",
+ "bytes", 0);
+ base::trace_event::MemoryAllocatorDump::Entry freelist_size_dirty(
+ "freelist_size_dirty", "bytes", 0);
base::trace_event::MemoryAllocatorDump::Entry virtual_size(
"virtual_size", "bytes", block_size);
- EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist))));
+ EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist_size))));
+ EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist_size_dirty))));
EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(virtual_size))));
}
@@ -441,5 +447,52 @@ TEST(DiscardableSharedMemoryHeapTest, DetailedDumpsDontContainRedundantData) {
heap.MergeIntoFreeLists(std::move(span));
}
+TEST(DiscardableSharedMemoryHeapTest, MarkSpans) {
+ DiscardableSharedMemoryHeap heap;
+
+ const size_t block_size = base::GetPageSize();
+
+ auto memory = std::make_unique<base::DiscardableSharedMemory>();
+ ASSERT_TRUE(memory->CreateAndMap(block_size));
+ auto span = heap.Grow(std::move(memory), block_size, 1, base::DoNothing());
+
+ auto* memory_segment = span->GetScopedMemorySegmentForTesting();
+
+ ASSERT_EQ(0u, memory_segment->CountMarkedPages());
+ ASSERT_EQ(0u, heap.dirty_freed_memory_page_count_);
+
+ heap.MergeIntoFreeLists(std::move(span));
+
+ ASSERT_EQ(1u, memory_segment->CountMarkedPages());
+ ASSERT_EQ(1u, heap.dirty_freed_memory_page_count_);
+
+ memory = std::make_unique<base::DiscardableSharedMemory>();
+ ASSERT_TRUE(memory->CreateAndMap(2 * block_size));
+ span = heap.Grow(std::move(memory), 2 * block_size, 1, base::DoNothing());
+
+ ASSERT_EQ(1u, heap.dirty_freed_memory_page_count_);
+
+ memory_segment = span->GetScopedMemorySegmentForTesting();
+
+ ASSERT_EQ(0u, memory_segment->CountMarkedPages());
+
+ ASSERT_EQ(1u, heap.dirty_freed_memory_page_count_);
+ ASSERT_EQ(1 * block_size, heap.GetFreelistSize());
+
+ heap.ReleaseFreeMemory();
+
+ ASSERT_EQ(0 * block_size, heap.GetFreelistSize());
+ ASSERT_EQ(0u, heap.dirty_freed_memory_page_count_);
+
+ heap.MergeIntoFreeLists(std::move(span));
+
+ ASSERT_EQ(2u, memory_segment->CountMarkedPages());
+ ASSERT_EQ(2u, heap.dirty_freed_memory_page_count_);
+
+ heap.ReleaseFreeMemory();
+
+ ASSERT_EQ(0u, heap.dirty_freed_memory_page_count_);
+}
+
} // namespace
} // namespace discardable_memory
diff --git a/chromium/components/dom_distiller/content/browser/distillability_driver.cc b/chromium/components/dom_distiller/content/browser/distillability_driver.cc
index a1dc3824ef1..0c7439595ce 100644
--- a/chromium/components/dom_distiller/content/browser/distillability_driver.cc
+++ b/chromium/components/dom_distiller/content/browser/distillability_driver.cc
@@ -47,7 +47,7 @@ class DistillabilityServiceImpl : public mojom::DistillabilityService {
};
DistillabilityDriver::DistillabilityDriver(content::WebContents* web_contents)
- : latest_result_(base::nullopt), web_contents_(web_contents) {
+ : latest_result_(absl::nullopt), web_contents_(web_contents) {
if (!web_contents)
return;
}
diff --git a/chromium/components/dom_distiller/content/browser/distillability_driver.h b/chromium/components/dom_distiller/content/browser/distillability_driver.h
index b6f76477b1f..2ac579e5f6a 100644
--- a/chromium/components/dom_distiller/content/browser/distillability_driver.h
+++ b/chromium/components/dom_distiller/content/browser/distillability_driver.h
@@ -2,19 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLIBILITY_DRIVER_H_
-#define COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLIBILITY_DRIVER_H_
-
-#include <string>
+#ifndef COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLABILITY_DRIVER_H_
+#define COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLABILITY_DRIVER_H_
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "components/dom_distiller/content/browser/distillable_page_utils.h"
#include "components/dom_distiller/content/browser/uma_helper.h"
#include "components/dom_distiller/content/common/mojom/distillability_service.mojom.h"
#include "content/public/browser/web_contents_user_data.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace dom_distiller {
@@ -29,7 +27,7 @@ class DistillabilityDriver
base::ObserverList<DistillabilityObserver>* GetObserverList() {
return &observers_;
}
- base::Optional<DistillabilityResult> GetLatestResult() const {
+ absl::optional<DistillabilityResult> GetLatestResult() const {
return latest_result_;
}
@@ -58,7 +56,7 @@ class DistillabilityDriver
//
// TODO(https://crbug.com/952042): Set this to nullopt when navigating to a
// new page, accounting for same-document navigation.
- base::Optional<DistillabilityResult> latest_result_;
+ absl::optional<DistillabilityResult> latest_result_;
// For UMA metrics on durations spent in distilled or distillable pages.
// Because each DistillabilityDriver is associated with just one WebContents,
@@ -77,4 +75,4 @@ class DistillabilityDriver
} // namespace dom_distiller
-#endif // COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLIBILITY_DRIVER_H_
+#endif // COMPONENTS_DOM_DISTILLER_CONTENT_BROWSER_DISTILLABILITY_DRIVER_H_
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 da0ab8ff2e7..1ef9c4b2425 100644
--- a/chromium/components/dom_distiller/content/browser/distillable_page_utils.cc
+++ b/chromium/components/dom_distiller/content/browser/distillable_page_utils.cc
@@ -97,7 +97,7 @@ void RemoveObserver(content::WebContents* web_contents,
}
}
-base::Optional<DistillabilityResult> GetLatestResult(
+absl::optional<DistillabilityResult> GetLatestResult(
content::WebContents* web_contents) {
CHECK(web_contents);
DistillabilityDriver::CreateForWebContents(web_contents);
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 08d21d6f432..331616fae5a 100644
--- a/chromium/components/dom_distiller/content/browser/distillable_page_utils.h
+++ b/chromium/components/dom_distiller/content/browser/distillable_page_utils.h
@@ -9,7 +9,7 @@
#include "base/callback.h"
#include "base/observer_list_types.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class WebContents;
@@ -54,7 +54,7 @@ void AddObserver(content::WebContents* web_contents,
void RemoveObserver(content::WebContents* web_contents,
DistillabilityObserver* observer);
-base::Optional<DistillabilityResult> GetLatestResult(
+absl::optional<DistillabilityResult> GetLatestResult(
content::WebContents* web_contents);
} // namespace dom_distiller
diff --git a/chromium/components/dom_distiller/content/browser/test_distillability_observer.h b/chromium/components/dom_distiller/content/browser/test_distillability_observer.h
index 3c3035ccb91..a8a12dd60b7 100644
--- a/chromium/components/dom_distiller/content/browser/test_distillability_observer.h
+++ b/chromium/components/dom_distiller/content/browser/test_distillability_observer.h
@@ -34,7 +34,7 @@ class TestDistillabilityObserver : public DistillabilityObserver {
content::WebContents* web_contents_;
std::unique_ptr<base::RunLoop> run_loop_;
- base::Optional<DistillabilityResult> result_to_wait_for_;
+ absl::optional<DistillabilityResult> result_to_wait_for_;
std::vector<DistillabilityResult> results_;
};
diff --git a/chromium/components/dom_distiller/content/renderer/distillability_agent.cc b/chromium/components/dom_distiller/content/renderer/distillability_agent.cc
index 478c658fb25..3f75c879410 100644
--- a/chromium/components/dom_distiller/content/renderer/distillability_agent.cc
+++ b/chromium/components/dom_distiller/content/renderer/distillability_agent.cc
@@ -107,7 +107,7 @@ void DumpDistillability(content::RenderFrame* render_frame,
std::unique_ptr<base::ListValue> derived_features(new base::ListValue());
for (double value : derived) {
- derived_features->AppendDouble(value);
+ derived_features->Append(value);
}
dict.Set("derived_features", std::move(derived_features));
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 3aa4a4143a7..30eb44aa544 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
@@ -25,7 +25,7 @@ DistillerJsRenderFrameObserver::~DistillerJsRenderFrameObserver() {}
void DistillerJsRenderFrameObserver::DidStartNavigation(
const GURL& url,
- base::Optional<blink::WebNavigationType> navigation_type) {
+ absl::optional<blink::WebNavigationType> navigation_type) {
is_distiller_page_ = url_utils::IsDistilledPage(url);
}
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 faaa9bc91df..07bdaa7d009 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
@@ -6,7 +6,6 @@
#define COMPONENTS_DOM_DISTILLER_CONTENT_RENDERER_DISTILLER_JS_RENDER_FRAME_OBSERVER_H_
#include "base/memory/weak_ptr.h"
-#include "components/dom_distiller/content/common/mojom/distiller_javascript_service.mojom.h"
#include "components/dom_distiller/content/renderer/distiller_native_javascript.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_frame_observer.h"
@@ -27,12 +26,11 @@ class DistillerJsRenderFrameObserver : public content::RenderFrameObserver {
// RenderFrameObserver implementation.
void DidStartNavigation(
const GURL& url,
- base::Optional<blink::WebNavigationType> navigation_type) override;
+ absl::optional<blink::WebNavigationType> navigation_type) override;
void DidCreateScriptContext(v8::Local<v8::Context> context,
int32_t world_id) override;
private:
-
// RenderFrameObserver implementation.
void OnDestruct() override;
diff --git a/chromium/components/dom_distiller/core/distilled_content_store.h b/chromium/components/dom_distiller/core/distilled_content_store.h
index f0296854088..054718883d4 100644
--- a/chromium/components/dom_distiller/core/distilled_content_store.h
+++ b/chromium/components/dom_distiller/core/distilled_content_store.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_DOM_DISTILLER_CORE_DOM_DISTILLER_CONTENT_STORE_H_
-#define COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_CONTENT_STORE_H_
+#ifndef COMPONENTS_DOM_DISTILLER_CORE_DISTILLED_CONTENT_STORE_H_
+#define COMPONENTS_DOM_DISTILLER_CORE_DISTILLED_CONTENT_STORE_H_
#include <memory>
#include <string>
@@ -87,4 +87,4 @@ class InMemoryContentStore : public DistilledContentStore {
} // namespace dom_distiller
-#endif // COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_CONTENT_CACHE_H_
+#endif // COMPONENTS_DOM_DISTILLER_CORE_DISTILLED_CONTENT_STORE_H_
diff --git a/chromium/components/dom_distiller/core/dom_distiller_service.cc b/chromium/components/dom_distiller/core/dom_distiller_service.cc
index 32bbbf2058c..d959b0ea723 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_service.cc
+++ b/chromium/components/dom_distiller/core/dom_distiller_service.cc
@@ -62,7 +62,7 @@ std::unique_ptr<ViewerHandle> DomDistillerService::ViewUrl(
std::unique_ptr<DistillerPage> distiller_page,
const GURL& url) {
if (!url.is_valid()) {
- return std::unique_ptr<ViewerHandle>();
+ return nullptr;
}
TaskTracker* task_tracker = nullptr;
diff --git a/chromium/components/dom_distiller/core/dom_distiller_service.h b/chromium/components/dom_distiller/core/dom_distiller_service.h
index 97d76749924..121bf8d7c12 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_service.h
+++ b/chromium/components/dom_distiller/core/dom_distiller_service.h
@@ -6,7 +6,6 @@
#define COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_SERVICE_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/callback.h"
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 6a91cde52ba..46ed0c90967 100644
--- a/chromium/components/dom_distiller/core/dom_distiller_service_android.h
+++ b/chromium/components/dom_distiller/core/dom_distiller_service_android.h
@@ -37,4 +37,4 @@ class DomDistillerServiceAndroid {
} // namespace android
} // namespace dom_distiller
-#endif // COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_SERVICE_ANDROID_H
+#endif // COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_SERVICE_ANDROID_H_
diff --git a/chromium/components/dom_distiller/core/viewer.cc b/chromium/components/dom_distiller/core/viewer.cc
index dffef376602..c6ccd76af19 100644
--- a/chromium/components/dom_distiller/core/viewer.cc
+++ b/chromium/components/dom_distiller/core/viewer.cc
@@ -317,7 +317,7 @@ std::unique_ptr<ViewerHandle> CreateViewRequest(
if (has_valid_entry_id && has_valid_url) {
// It is invalid to specify a query param for both |kEntryIdKey| and
// |kUrlKey|.
- return std::unique_ptr<ViewerHandle>();
+ return nullptr;
}
if (has_valid_entry_id) {
@@ -331,7 +331,7 @@ std::unique_ptr<ViewerHandle> CreateViewRequest(
}
// It is invalid to not specify a query param for |kEntryIdKey| or |kUrlKey|.
- return std::unique_ptr<ViewerHandle>();
+ return nullptr;
}
const std::string GetDistilledPageThemeJs(mojom::Theme theme) {
diff --git a/chromium/components/dom_distiller/core/viewer_unittest.cc b/chromium/components/dom_distiller/core/viewer_unittest.cc
index 3e63395487a..c28e09a8aaa 100644
--- a/chromium/components/dom_distiller/core/viewer_unittest.cc
+++ b/chromium/components/dom_distiller/core/viewer_unittest.cc
@@ -54,11 +54,11 @@ class TestDomDistillerService : public DomDistillerServiceInterface {
}
std::unique_ptr<DistillerPage> CreateDefaultDistillerPage(
const gfx::Size& render_view_size) override {
- return std::unique_ptr<DistillerPage>();
+ return nullptr;
}
std::unique_ptr<DistillerPage> CreateDefaultDistillerPageWithHandle(
std::unique_ptr<SourcePageHandle> handle) override {
- return std::unique_ptr<DistillerPage>();
+ return nullptr;
}
DistilledPagePrefs* GetDistilledPagePrefs() override;
DistillerUIHandle* GetDistillerUIHandle() override;
diff --git a/chromium/components/dom_distiller/ios/distiller_page_ios.mm b/chromium/components/dom_distiller/ios/distiller_page_ios.mm
index a1c4aefaf8a..0a2cc17dc08 100644
--- a/chromium/components/dom_distiller/ios/distiller_page_ios.mm
+++ b/chromium/components/dom_distiller/ios/distiller_page_ios.mm
@@ -240,8 +240,7 @@ void DistillerPageIOS::DidStartLoading(web::WebState* web_state) {
void DistillerPageIOS::DidStopLoading(web::WebState* web_state) {
DCHECK_EQ(web_state_.get(), web_state);
- if (web_state->IsShowingWebInterstitial() ||
- media_blocker_->main_frame_navigation_blocked()) {
+ if (media_blocker_->main_frame_navigation_blocked()) {
// If there is an interstitial, stop the distillation.
// The interstitial is not displayed to the user who cannot choose to
// continue.
diff --git a/chromium/components/dom_distiller/standalone/content_extractor_browsertest.cc b/chromium/components/dom_distiller/standalone/content_extractor_browsertest.cc
index b3380e95a04..1d67dd21a02 100644
--- a/chromium/components/dom_distiller/standalone/content_extractor_browsertest.cc
+++ b/chromium/components/dom_distiller/standalone/content_extractor_browsertest.cc
@@ -136,7 +136,7 @@ std::unique_ptr<DomDistillerService> CreateDomDistillerService(
std::make_unique<DistillerPageWebContentsFactory>(context);
auto distiller_url_fetcher_factory =
std::make_unique<DistillerURLFetcherFactory>(
- content::BrowserContext::GetDefaultStoragePartition(context)
+ context->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess());
dom_distiller::proto::DomDistillerOptions options;
diff --git a/chromium/components/domain_reliability/config.cc b/chromium/components/domain_reliability/config.cc
index 6266afc0e57..e9ebee7ce56 100644
--- a/chromium/components/domain_reliability/config.cc
+++ b/chromium/components/domain_reliability/config.cc
@@ -7,7 +7,7 @@
#include <utility>
#include "base/json/json_reader.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/url_constants.h"
namespace {
@@ -44,7 +44,7 @@ DomainReliabilityConfig::~DomainReliabilityConfig() {}
// static
std::unique_ptr<const DomainReliabilityConfig>
DomainReliabilityConfig::FromJSON(const base::StringPiece& json) {
- base::Optional<base::Value> value = base::JSONReader::Read(json);
+ absl::optional<base::Value> value = base::JSONReader::Read(json);
if (!value)
return nullptr;
diff --git a/chromium/components/domain_reliability/config.h b/chromium/components/domain_reliability/config.h
index 4776575171d..3efa6dc2712 100644
--- a/chromium/components/domain_reliability/config.h
+++ b/chromium/components/domain_reliability/config.h
@@ -12,7 +12,6 @@
#include "base/json/json_value_converter.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
-#include "base/values.h"
#include "components/domain_reliability/domain_reliability_export.h"
#include "url/gurl.h"
diff --git a/chromium/components/domain_reliability/dispatcher.h b/chromium/components/domain_reliability/dispatcher.h
index 6bc7218f56d..e3e95809886 100644
--- a/chromium/components/domain_reliability/dispatcher.h
+++ b/chromium/components/domain_reliability/dispatcher.h
@@ -67,4 +67,4 @@ class DOMAIN_RELIABILITY_EXPORT DomainReliabilityDispatcher {
} // namespace domain_reliability
-#endif
+#endif // COMPONENTS_DOMAIN_RELIABILITY_DISPATCHER_H_
diff --git a/chromium/components/domain_reliability/google_configs.cc b/chromium/components/domain_reliability/google_configs.cc
index 7de679f8840..7d54b0ab62a 100644
--- a/chromium/components/domain_reliability/google_configs.cc
+++ b/chromium/components/domain_reliability/google_configs.cc
@@ -575,8 +575,8 @@ std::unique_ptr<const DomainReliabilityConfig> MaybeGetGoogleConfig(
base::StartsWith(hostname, "www.", base::CompareCase::SENSITIVE);
std::string hostname_parent = net::GetSuperdomain(hostname);
- std::unique_ptr<const DomainReliabilityConfig> config = nullptr;
- std::unique_ptr<const DomainReliabilityConfig> superdomain_config = nullptr;
+ std::unique_ptr<const DomainReliabilityConfig> config;
+ std::unique_ptr<const DomainReliabilityConfig> superdomain_config;
for (const auto& params : kGoogleConfigs) {
if (params.hostname == hostname) {
diff --git a/chromium/components/domain_reliability/monitor.h b/chromium/components/domain_reliability/monitor.h
index a606a84fd65..972274c15a9 100644
--- a/chromium/components/domain_reliability/monitor.h
+++ b/chromium/components/domain_reliability/monitor.h
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
#include "components/domain_reliability/beacon.h"
#include "components/domain_reliability/clear_mode.h"
#include "components/domain_reliability/config.h"
diff --git a/chromium/components/download/content/internal/context_menu_download.cc b/chromium/components/download/content/internal/context_menu_download.cc
index 8540e33d8d2..2e8ebf02c8d 100644
--- a/chromium/components/download/content/internal/context_menu_download.cc
+++ b/chromium/components/download/content/internal/context_menu_download.cc
@@ -22,8 +22,8 @@ void CreateContextMenuDownload(content::WebContents* web_contents,
const GURL& url = is_link ? params.link_url : params.src_url;
const GURL& referring_url =
params.frame_url.is_empty() ? params.page_url : params.frame_url;
- content::DownloadManager* dlm = content::BrowserContext::GetDownloadManager(
- web_contents->GetBrowserContext());
+ content::DownloadManager* dlm =
+ web_contents->GetBrowserContext()->GetDownloadManager();
std::unique_ptr<download::DownloadUrlParameters> dl_params(
content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
web_contents, url,
diff --git a/chromium/components/download/content/internal/download_driver_impl.cc b/chromium/components/download/content/internal/download_driver_impl.cc
index eb5d6fc2d0f..7344ca16ae5 100644
--- a/chromium/components/download/content/internal/download_driver_impl.cc
+++ b/chromium/components/download/content/internal/download_driver_impl.cc
@@ -233,13 +233,13 @@ void DownloadDriverImpl::Resume(const std::string& guid) {
item->Resume(true);
}
-base::Optional<DriverEntry> DownloadDriverImpl::Find(const std::string& guid) {
+absl::optional<DriverEntry> DownloadDriverImpl::Find(const std::string& guid) {
if (!download_manager_coordinator_)
- return base::nullopt;
+ return absl::nullopt;
DownloadItem* item = download_manager_coordinator_->GetDownloadByGuid(guid);
if (item)
return CreateDriverEntry(item);
- return base::nullopt;
+ return absl::nullopt;
}
std::set<std::string> DownloadDriverImpl::GetActiveDownloads() {
diff --git a/chromium/components/download/content/internal/download_driver_impl.h b/chromium/components/download/content/internal/download_driver_impl.h
index 97e9a0c5f86..6f97194d0a0 100644
--- a/chromium/components/download/content/internal/download_driver_impl.h
+++ b/chromium/components/download/content/internal/download_driver_impl.h
@@ -49,7 +49,7 @@ class DownloadDriverImpl : public DownloadDriver,
void Remove(const std::string& guid, bool remove_file) override;
void Pause(const std::string& guid) override;
void Resume(const std::string& guid) override;
- base::Optional<DriverEntry> Find(const std::string& guid) override;
+ absl::optional<DriverEntry> Find(const std::string& guid) override;
std::set<std::string> GetActiveDownloads() override;
size_t EstimateMemoryUsage() const override;
diff --git a/chromium/components/download/content/internal/download_driver_impl_unittest.cc b/chromium/components/download/content/internal/download_driver_impl_unittest.cc
index c32912245db..7535bdc06da 100644
--- a/chromium/components/download/content/internal/download_driver_impl_unittest.cc
+++ b/chromium/components/download/content/internal/download_driver_impl_unittest.cc
@@ -13,7 +13,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "components/download/content/public/all_download_item_notifier.h"
#include "components/download/internal/background_service/test/mock_download_driver_client.h"
-#include "components/download/public/common//mock_simple_download_manager.h"
+#include "components/download/public/common/mock_simple_download_manager.h"
#include "content/public/test/fake_download_item.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
diff --git a/chromium/components/download/database/download_db.h b/chromium/components/download/database/download_db.h
index 6b11d98ea59..90b8040fd8c 100644
--- a/chromium/components/download/database/download_db.h
+++ b/chromium/components/download/database/download_db.h
@@ -10,8 +10,8 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/optional.h"
#include "components/download/database/download_namespace.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
diff --git a/chromium/components/download/database/download_db_conversions.cc b/chromium/components/download/database/download_db_conversions.cc
index 2e6291671e0..b6019e033ae 100644
--- a/chromium/components/download/database/download_db_conversions.cc
+++ b/chromium/components/download/database/download_db_conversions.cc
@@ -310,7 +310,7 @@ download_pb::DownloadSchedule DownloadDBConversions::DownloadScheduleToProto(
DownloadSchedule DownloadDBConversions::DownloadScheduleFromProto(
const download_pb::DownloadSchedule& proto,
bool only_on_wifi) {
- base::Optional<base::Time> start_time;
+ absl::optional<base::Time> start_time;
if (proto.has_start_time())
start_time = FromMillisecondsToTime(proto.start_time());
return DownloadSchedule(only_on_wifi, std::move(start_time));
diff --git a/chromium/components/download/database/download_db_conversions_unittest.cc b/chromium/components/download/database/download_db_conversions_unittest.cc
index a2b80872d1d..226f5d8534b 100644
--- a/chromium/components/download/database/download_db_conversions_unittest.cc
+++ b/chromium/components/download/database/download_db_conversions_unittest.cc
@@ -4,12 +4,12 @@
#include "components/download/database/download_db_conversions.h"
-#include "base/optional.h"
#include "base/test/scoped_feature_list.h"
#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_schedule.h"
#include "components/download/public/common/download_url_parameters.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
@@ -50,8 +50,8 @@ InProgressInfo CreateInProgressInfo() {
std::make_pair<std::string, std::string>("123", "456"));
info.request_headers.emplace_back(
std::make_pair<std::string, std::string>("ABC", "def"));
- info.download_schedule = base::make_optional<DownloadSchedule>(
- false /*only_on_wifi*/, base::nullopt);
+ info.download_schedule = absl::make_optional<DownloadSchedule>(
+ false /*only_on_wifi*/, absl::nullopt);
return info;
}
@@ -183,7 +183,7 @@ TEST_F(DownloadDBConversionsTest, DownloadDBEntry) {
TEST_F(DownloadDBConversionsTest, DownloadSchedule) {
const bool kOnlyOnWifi = true;
- DownloadSchedule download_schedule(kOnlyOnWifi, base::nullopt /*start_time*/);
+ DownloadSchedule download_schedule(kOnlyOnWifi, absl::nullopt /*start_time*/);
// InProgressInfo.metered is used to set DownloadSchedule.only_on_wifi.
auto persisted_download_schedule = DownloadScheduleFromProto(
DownloadScheduleToProto(download_schedule), !kOnlyOnWifi);
diff --git a/chromium/components/download/database/download_db_entry.h b/chromium/components/download/database/download_db_entry.h
index 84f6130e9dd..ab6777119c0 100644
--- a/chromium/components/download/database/download_db_entry.h
+++ b/chromium/components/download/database/download_db_entry.h
@@ -7,9 +7,9 @@
#include <string>
-#include "base/optional.h"
#include "components/download/database/download_info.h"
#include "components/download/database/download_namespace.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
@@ -27,7 +27,7 @@ struct DownloadDBEntry {
std::string GetGuid() const;
// Information about a regular download.
- base::Optional<DownloadInfo> download_info;
+ absl::optional<DownloadInfo> download_info;
};
} // namespace download
diff --git a/chromium/components/download/database/download_db_impl.h b/chromium/components/download/database/download_db_impl.h
index 2a85c7cb564..ba3ba584022 100644
--- a/chromium/components/download/database/download_db_impl.h
+++ b/chromium/components/download/database/download_db_impl.h
@@ -90,4 +90,4 @@ class DownloadDBImpl : public DownloadDB {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_DATABASE_IN_PROGRESS_DOWNLOAD_DB_IMPL_H_
+#endif // COMPONENTS_DOWNLOAD_DATABASE_DOWNLOAD_DB_IMPL_H_
diff --git a/chromium/components/download/database/download_info.h b/chromium/components/download/database/download_info.h
index 483115fb72e..05b9312babd 100644
--- a/chromium/components/download/database/download_info.h
+++ b/chromium/components/download/database/download_info.h
@@ -7,9 +7,9 @@
#include <string>
-#include "base/optional.h"
#include "components/download/database/in_progress/in_progress_info.h"
#include "components/download/database/in_progress/ukm_info.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
@@ -30,10 +30,10 @@ struct DownloadInfo {
int id = -1;
// UKM information for reporting.
- base::Optional<UkmInfo> ukm_info;
+ absl::optional<UkmInfo> ukm_info;
// In progress information for active download.
- base::Optional<InProgressInfo> in_progress_info;
+ absl::optional<InProgressInfo> in_progress_info;
};
} // namespace download
diff --git a/chromium/components/download/database/in_progress/in_progress_info.h b/chromium/components/download/database/in_progress/in_progress_info.h
index 2b67686c04c..fda2de6f312 100644
--- a/chromium/components/download/database/in_progress/in_progress_info.h
+++ b/chromium/components/download/database/in_progress/in_progress_info.h
@@ -8,11 +8,11 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_schedule.h"
#include "components/download/public/common/download_url_parameters.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace download {
@@ -125,7 +125,7 @@ struct InProgressInfo {
bool metered = false;
// When to start the download. Used by download later feature.
- base::Optional<DownloadSchedule> download_schedule;
+ absl::optional<DownloadSchedule> download_schedule;
};
} // namespace download
diff --git a/chromium/components/download/internal/background_service/controller.h b/chromium/components/download/internal/background_service/controller.h
index 5136c1deadb..6993624fc6a 100644
--- a/chromium/components/download/internal/background_service/controller.h
+++ b/chromium/components/download/internal/background_service/controller.h
@@ -78,7 +78,7 @@ class Controller {
// Starts a download with |params|. See DownloadParams::StartCallback and
// DownloadParams::StartResponse for information on how a caller can determine
// whether or not the download was successfully accepted and queued.
- virtual void StartDownload(const DownloadParams& params) = 0;
+ virtual void StartDownload(DownloadParams params) = 0;
// Pauses a download request associated with |guid| if one exists.
virtual void PauseDownload(const std::string& guid) = 0;
diff --git a/chromium/components/download/internal/background_service/controller_impl.cc b/chromium/components/download/internal/background_service/controller_impl.cc
index b620c89d8ee..9216d7547e4 100644
--- a/chromium/components/download/internal/background_service/controller_impl.cc
+++ b/chromium/components/download/internal/background_service/controller_impl.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/optional.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_allocator_dump.h"
@@ -31,6 +30,7 @@
#include "components/download/public/background_service/navigation_monitor.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/resource_request_body.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
namespace {
@@ -163,7 +163,7 @@ Controller::State ControllerImpl::GetState() {
return controller_state_;
}
-void ControllerImpl::StartDownload(const DownloadParams& params) {
+void ControllerImpl::StartDownload(DownloadParams params) {
DCHECK(controller_state_ == State::READY ||
controller_state_ == State::UNAVAILABLE);
@@ -173,7 +173,7 @@ void ControllerImpl::StartDownload(const DownloadParams& params) {
if (controller_state_ != State::READY) {
HandleStartDownloadResponse(params.client, params.guid,
DownloadParams::StartResult::INTERNAL_ERROR,
- params.callback);
+ std::move(params.callback));
return;
}
@@ -183,7 +183,7 @@ void ControllerImpl::StartDownload(const DownloadParams& params) {
model_->Get(params.guid) != nullptr) {
HandleStartDownloadResponse(params.client, params.guid,
DownloadParams::StartResult::UNEXPECTED_GUID,
- params.callback);
+ std::move(params.callback));
return;
}
@@ -191,7 +191,7 @@ void ControllerImpl::StartDownload(const DownloadParams& params) {
if (!client) {
HandleStartDownloadResponse(params.client, params.guid,
DownloadParams::StartResult::UNEXPECTED_CLIENT,
- params.callback);
+ std::move(params.callback));
return;
}
@@ -200,11 +200,11 @@ void ControllerImpl::StartDownload(const DownloadParams& params) {
if (client_count >= config_->max_scheduled_downloads) {
HandleStartDownloadResponse(params.client, params.guid,
DownloadParams::StartResult::BACKOFF,
- params.callback);
+ std::move(params.callback));
return;
}
- start_callbacks_[params.guid] = params.callback;
+ start_callbacks_[params.guid] = std::move(params.callback);
Entry entry(params);
entry.target_file_path = download_file_dir_.AppendASCII(params.guid);
model_->Add(entry);
@@ -619,15 +619,15 @@ LogSource::EntryDetailsList ControllerImpl::GetServiceDownloads() {
return list;
}
-base::Optional<LogSource::EntryDetails> ControllerImpl::GetServiceDownload(
+absl::optional<LogSource::EntryDetails> ControllerImpl::GetServiceDownload(
const std::string& guid) {
if (controller_state_ != State::READY)
- return base::nullopt;
+ return absl::nullopt;
auto* entry = model_->Get(guid);
auto driver_entry = driver_->Find(guid);
- return base::Optional<LogSource::EntryDetails>(
+ return absl::optional<LogSource::EntryDetails>(
std::make_pair(entry, driver_entry));
}
@@ -767,7 +767,7 @@ void ControllerImpl::CleanupUnknownFiles() {
auto entries = model_->PeekEntries();
std::vector<DriverEntry> driver_entries;
for (auto* entry : entries) {
- base::Optional<DriverEntry> driver_entry = driver_->Find(entry->guid);
+ absl::optional<DriverEntry> driver_entry = driver_->Find(entry->guid);
if (driver_entry.has_value())
driver_entries.push_back(driver_entry.value());
}
@@ -784,7 +784,7 @@ void ControllerImpl::ResolveInitialRequestStates() {
// Pull the initial Entry::State and DriverEntry::State.
Entry::State state = entry->state;
auto driver_entry = driver_->Find(entry->guid);
- base::Optional<DriverEntry::State> driver_state;
+ absl::optional<DriverEntry::State> driver_state;
if (driver_entry.has_value()) {
DCHECK_NE(DriverEntry::State::UNKNOWN, driver_entry->state);
driver_state = driver_entry->state;
@@ -927,7 +927,7 @@ void ControllerImpl::UpdateDriverState(Entry* entry) {
return;
}
- base::Optional<DriverEntry> driver_entry = driver_->Find(entry->guid);
+ absl::optional<DriverEntry> driver_entry = driver_->Find(entry->guid);
// Check if the DriverEntry is in a finished state already. If so we need to
// clean up our Entry and finish the download.
@@ -1105,9 +1105,9 @@ void ControllerImpl::HandleStartDownloadResponse(
DownloadClient client,
const std::string& guid,
DownloadParams::StartResult result) {
- auto callback = start_callbacks_[guid];
+ DownloadParams::StartCallback callback = std::move(start_callbacks_[guid]);
start_callbacks_.erase(guid);
- HandleStartDownloadResponse(client, guid, result, callback);
+ HandleStartDownloadResponse(client, guid, result, std::move(callback));
}
void ControllerImpl::HandleStartDownloadResponse(
@@ -1323,7 +1323,7 @@ bool ControllerImpl::ShouldBlockDownloadOnNavigation(Entry* entry) {
bool pausable_priority =
entry->scheduling_params.priority <= SchedulingParams::Priority::NORMAL;
- base::Optional<DriverEntry> driver_entry = driver_->Find(entry->guid);
+ absl::optional<DriverEntry> driver_entry = driver_->Find(entry->guid);
bool new_download = !driver_entry.has_value();
bool resumable_download =
driver_entry.has_value() && driver_entry->can_resume;
diff --git a/chromium/components/download/internal/background_service/controller_impl.h b/chromium/components/download/internal/background_service/controller_impl.h
index 6cd417eeb17..f05438f32c1 100644
--- a/chromium/components/download/internal/background_service/controller_impl.h
+++ b/chromium/components/download/internal/background_service/controller_impl.h
@@ -14,7 +14,6 @@
#include "base/cancelable_callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/trace_event/memory_dump_provider.h"
#include "components/download/internal/background_service/controller.h"
#include "components/download/internal/background_service/download_blockage_status.h"
@@ -29,6 +28,7 @@
#include "components/download/public/background_service/download_params.h"
#include "components/download/public/background_service/navigation_monitor.h"
#include "components/download/public/task/task_scheduler.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
@@ -72,7 +72,7 @@ class ControllerImpl : public Controller,
// Controller implementation.
void Initialize(base::OnceClosure callback) override;
State GetState() override;
- void StartDownload(const DownloadParams& params) override;
+ void StartDownload(DownloadParams params) override;
void PauseDownload(const std::string& guid) override;
void ResumeDownload(const std::string& guid) override;
void CancelDownload(const std::string& guid) override;
@@ -113,7 +113,7 @@ class ControllerImpl : public Controller,
Controller::State GetControllerState() override;
const StartupStatus& GetStartupStatus() override;
LogSource::EntryDetailsList GetServiceDownloads() override;
- base::Optional<EntryDetails> GetServiceDownload(
+ absl::optional<EntryDetails> GetServiceDownload(
const std::string& guid) override;
// MemoryDumpProvider implementation.
diff --git a/chromium/components/download/internal/background_service/controller_impl_unittest.cc b/chromium/components/download/internal/background_service/controller_impl_unittest.cc
index bd02cfc8faf..0358cef4d48 100644
--- a/chromium/components/download/internal/background_service/controller_impl_unittest.cc
+++ b/chromium/components/download/internal/background_service/controller_impl_unittest.cc
@@ -267,7 +267,9 @@ class DownloadServiceControllerImplTest : public testing::Test {
MockTaskScheduler* task_scheduler_;
MockFileMonitor* file_monitor_;
- DownloadParams::StartCallback start_callback_;
+ // A repeatable DownloadParams::StartCallback.
+ base::RepeatingCallback<void(const std::string&, DownloadParams::StartResult)>
+ start_callback_;
bool init_callback_called_;
private:
@@ -537,7 +539,7 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadAccepted) {
EXPECT_CALL(*this,
StartCallback(params.guid, DownloadParams::StartResult::ACCEPTED))
.Times(1);
- controller_->StartDownload(params);
+ controller_->StartDownload(std::move(params));
// TODO(dtrainor): Compare the full DownloadParams with the full Entry.
store_->TriggerUpdate(true);
@@ -569,12 +571,13 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithBackoff) {
// Trigger the download.
DownloadParams params = MakeDownloadParams();
+ auto guid = params.guid;
EXPECT_CALL(*this,
StartCallback(params.guid, DownloadParams::StartResult::BACKOFF))
.Times(1);
- controller_->StartDownload(params);
+ controller_->StartDownload(std::move(params));
- EXPECT_FALSE(GuidInEntryList(store_->updated_entries(), params.guid));
+ EXPECT_FALSE(GuidInEntryList(store_->updated_entries(), guid));
task_runner_->RunUntilIdle();
}
@@ -600,7 +603,7 @@ TEST_F(DownloadServiceControllerImplTest,
*this,
StartCallback(params.guid, DownloadParams::StartResult::UNEXPECTED_GUID))
.Times(1);
- controller_->StartDownload(params);
+ controller_->StartDownload(std::move(params));
task_runner_->RunUntilIdle();
}
@@ -616,20 +619,23 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithDuplicateCall) {
driver_->MakeReady();
task_runner_->RunUntilIdle();
- // Trigger the download twice.
- DownloadParams params = MakeDownloadParams();
+ // Trigger two download with the same guids.
+ DownloadParams params1 = MakeDownloadParams();
+ DownloadParams params2 = MakeDownloadParams();
+ auto guid = params1.guid;
+ params1.guid = params2.guid = guid;
EXPECT_CALL(
*this,
- StartCallback(params.guid, DownloadParams::StartResult::UNEXPECTED_GUID))
+ StartCallback(params1.guid, DownloadParams::StartResult::UNEXPECTED_GUID))
.Times(1);
- EXPECT_CALL(*this,
- StartCallback(params.guid, DownloadParams::StartResult::ACCEPTED))
+ EXPECT_CALL(
+ *this, StartCallback(params1.guid, DownloadParams::StartResult::ACCEPTED))
.Times(1);
- controller_->StartDownload(params);
- controller_->StartDownload(params);
+ controller_->StartDownload(std::move(params1));
+ controller_->StartDownload(std::move(params2));
store_->TriggerUpdate(true);
- EXPECT_TRUE(GuidInEntryList(store_->updated_entries(), params.guid));
+ EXPECT_TRUE(GuidInEntryList(store_->updated_entries(), guid));
task_runner_->RunUntilIdle();
}
@@ -651,7 +657,7 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithBadClient) {
StartCallback(params.guid,
DownloadParams::StartResult::UNEXPECTED_CLIENT))
.Times(1);
- controller_->StartDownload(params);
+ controller_->StartDownload(std::move(params));
task_runner_->RunUntilIdle();
}
@@ -668,13 +674,14 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithClientCancel) {
// Trigger the download.
DownloadParams params = MakeDownloadParams();
+ auto guid = params.guid;
EXPECT_CALL(
*this,
StartCallback(params.guid, DownloadParams::StartResult::CLIENT_CANCELLED))
.Times(1);
- controller_->StartDownload(params);
+ controller_->StartDownload(std::move(params));
- controller_->CancelDownload(params.guid);
+ controller_->CancelDownload(guid);
store_->TriggerUpdate(true);
task_runner_->RunUntilIdle();
@@ -695,7 +702,7 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithInternalError) {
EXPECT_CALL(*this, StartCallback(params.guid,
DownloadParams::StartResult::INTERNAL_ERROR))
.Times(1);
- controller_->StartDownload(params);
+ controller_->StartDownload(std::move(params));
store_->TriggerUpdate(false);
@@ -1271,8 +1278,8 @@ TEST_F(DownloadServiceControllerImplTest,
auto verify_entry =
[this](const std::string& guid,
- base::Optional<Entry::State> expected_state,
- base::Optional<DriverEntry::State> expected_driver_state,
+ absl::optional<Entry::State> expected_state,
+ absl::optional<DriverEntry::State> expected_driver_state,
bool has_upload_data) {
auto* entry = model_->Get(guid);
auto driver_entry = driver_->Find(guid);
@@ -1315,11 +1322,11 @@ TEST_F(DownloadServiceControllerImplTest,
task_runner_->RunUntilIdle();
// No driver entry yet as entries are waiting for client response.
- verify_entry(entry1.guid, Entry::State::ACTIVE, base::nullopt, false);
- verify_entry(entry2.guid, Entry::State::ACTIVE, base::nullopt, false);
- verify_entry(entry3.guid, Entry::State::ACTIVE, base::nullopt, false);
- verify_entry(entry4.guid, Entry::State::ACTIVE, base::nullopt, false);
- verify_entry(entry5.guid, Entry::State::ACTIVE, base::nullopt, false);
+ verify_entry(entry1.guid, Entry::State::ACTIVE, absl::nullopt, false);
+ verify_entry(entry2.guid, Entry::State::ACTIVE, absl::nullopt, false);
+ verify_entry(entry3.guid, Entry::State::ACTIVE, absl::nullopt, false);
+ verify_entry(entry4.guid, Entry::State::ACTIVE, absl::nullopt, false);
+ verify_entry(entry5.guid, Entry::State::ACTIVE, absl::nullopt, false);
// At 20 seconds.
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(20));
@@ -1340,7 +1347,7 @@ TEST_F(DownloadServiceControllerImplTest,
// Call PauseDownload before client response for entry5.
controller_->PauseDownload(entry5.guid);
task_runner_->RunUntilIdle();
- verify_entry(entry5.guid, Entry::State::PAUSED, base::nullopt, false);
+ verify_entry(entry5.guid, Entry::State::PAUSED, absl::nullopt, false);
// Test CancelDownload before client response for entry2.
EXPECT_CALL(*client3_, OnDownloadFailed(entry2.guid, _,
@@ -1348,14 +1355,14 @@ TEST_F(DownloadServiceControllerImplTest,
.Times(1);
controller_->CancelDownload(entry2.guid);
task_runner_->RunUntilIdle();
- verify_entry(entry2.guid, base::nullopt, base::nullopt, false);
+ verify_entry(entry2.guid, absl::nullopt, absl::nullopt, false);
// At 25 seconds.
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(5));
// Entry2, entry5 receive client response.
- verify_entry(entry2.guid, base::nullopt, base::nullopt, false);
- verify_entry(entry5.guid, Entry::State::PAUSED, base::nullopt, true);
+ verify_entry(entry2.guid, absl::nullopt, absl::nullopt, false);
+ verify_entry(entry5.guid, Entry::State::PAUSED, absl::nullopt, true);
// Entry3 timeouts before client response.
EXPECT_CALL(
@@ -1365,7 +1372,7 @@ TEST_F(DownloadServiceControllerImplTest,
// At 40 seconds.
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(15));
- verify_entry(entry3.guid, base::nullopt, base::nullopt, false);
+ verify_entry(entry3.guid, absl::nullopt, absl::nullopt, false);
// Test network failure for entry4. First check the entry is in progress.
verify_entry(entry4.guid, Entry::State::ACTIVE,
@@ -1377,14 +1384,14 @@ TEST_F(DownloadServiceControllerImplTest,
BuildDriverEntry(entry4, DriverEntry::State::INTERRUPTED);
driver_->NotifyDownloadFailed(dentry4, FailureType::NOT_RECOVERABLE);
task_runner_->RunUntilIdle();
- verify_entry(entry4.guid, base::nullopt, base::nullopt, false);
+ verify_entry(entry4.guid, absl::nullopt, absl::nullopt, false);
// Entry5 is still paused, call ResumeDownload. It should make another fresh
// request for data.
- verify_entry(entry5.guid, Entry::State::PAUSED, base::nullopt, true);
+ verify_entry(entry5.guid, Entry::State::PAUSED, absl::nullopt, true);
controller_->ResumeDownload(entry5.guid);
task_runner_->RunUntilIdle();
- verify_entry(entry5.guid, Entry::State::ACTIVE, base::nullopt, true);
+ verify_entry(entry5.guid, Entry::State::ACTIVE, absl::nullopt, true);
// At 65 seconds. Entry5 receives data for the second time and continues.
task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(25));
@@ -1498,11 +1505,11 @@ TEST_F(DownloadServiceControllerImplTest, StartupRecovery) {
EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entries[2].guid)->state);
EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entries[3].guid)->state);
EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entries[4].guid)->state);
- EXPECT_EQ(base::nullopt, driver_->Find(entries[0].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[1].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[2].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[3].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[4].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[0].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[1].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[2].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[3].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[4].guid));
// Entry::State::AVAILABLE.
EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entries[5].guid)->state);
@@ -1510,11 +1517,11 @@ TEST_F(DownloadServiceControllerImplTest, StartupRecovery) {
EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[7].guid)->state);
EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entries[8].guid)->state);
EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entries[9].guid)->state);
- EXPECT_NE(base::nullopt, driver_->Find(entries[5].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[6].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[7].guid));
- EXPECT_NE(base::nullopt, driver_->Find(entries[8].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[9].guid));
+ EXPECT_NE(absl::nullopt, driver_->Find(entries[5].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[6].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[7].guid));
+ EXPECT_NE(absl::nullopt, driver_->Find(entries[8].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[9].guid));
// Entry::State::ACTIVE.
EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entries[10].guid)->state);
@@ -1522,11 +1529,11 @@ TEST_F(DownloadServiceControllerImplTest, StartupRecovery) {
EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[12].guid)->state);
EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entries[13].guid)->state);
EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entries[14].guid)->state);
- EXPECT_NE(base::nullopt, driver_->Find(entries[10].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[11].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[12].guid));
- EXPECT_NE(base::nullopt, driver_->Find(entries[13].guid));
- EXPECT_NE(base::nullopt, driver_->Find(entries[14].guid));
+ EXPECT_NE(absl::nullopt, driver_->Find(entries[10].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[11].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[12].guid));
+ EXPECT_NE(absl::nullopt, driver_->Find(entries[13].guid));
+ EXPECT_NE(absl::nullopt, driver_->Find(entries[14].guid));
// Entry::State::PAUSED.
EXPECT_EQ(Entry::State::PAUSED, model_->Get(entries[15].guid)->state);
@@ -1534,11 +1541,11 @@ TEST_F(DownloadServiceControllerImplTest, StartupRecovery) {
EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[17].guid)->state);
EXPECT_EQ(Entry::State::PAUSED, model_->Get(entries[18].guid)->state);
EXPECT_EQ(Entry::State::PAUSED, model_->Get(entries[19].guid)->state);
- EXPECT_NE(base::nullopt, driver_->Find(entries[15].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[16].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[17].guid));
- EXPECT_NE(base::nullopt, driver_->Find(entries[18].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[19].guid));
+ EXPECT_NE(absl::nullopt, driver_->Find(entries[15].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[16].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[17].guid));
+ EXPECT_NE(absl::nullopt, driver_->Find(entries[18].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[19].guid));
// prog, comp, canc, int, __
// Entry::State::COMPLETE.
@@ -1547,11 +1554,11 @@ TEST_F(DownloadServiceControllerImplTest, StartupRecovery) {
EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[22].guid)->state);
EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[23].guid)->state);
EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entries[24].guid)->state);
- EXPECT_EQ(base::nullopt, driver_->Find(entries[20].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[21].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[22].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[23].guid));
- EXPECT_EQ(base::nullopt, driver_->Find(entries[24].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[20].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[21].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[22].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[23].guid));
+ EXPECT_EQ(absl::nullopt, driver_->Find(entries[24].guid));
}
TEST_F(DownloadServiceControllerImplTest, StartupRecoveryForUploadEntries) {
@@ -1562,7 +1569,7 @@ TEST_F(DownloadServiceControllerImplTest, StartupRecoveryForUploadEntries) {
auto add_entry = [&entries, &driver_entries](
Entry::State state,
- base::Optional<DriverEntry::State> driver_state) {
+ absl::optional<DriverEntry::State> driver_state) {
Entry entry = test::BuildBasicEntry(state);
entry.has_upload_data = true;
if (state == Entry::State::COMPLETE)
@@ -1577,19 +1584,19 @@ TEST_F(DownloadServiceControllerImplTest, StartupRecoveryForUploadEntries) {
add_entry(Entry::State::ACTIVE, DriverEntry::State::COMPLETE);
add_entry(Entry::State::ACTIVE, DriverEntry::State::CANCELLED);
add_entry(Entry::State::ACTIVE, DriverEntry::State::INTERRUPTED);
- add_entry(Entry::State::ACTIVE, base::nullopt);
+ add_entry(Entry::State::ACTIVE, absl::nullopt);
add_entry(Entry::State::PAUSED, DriverEntry::State::IN_PROGRESS);
add_entry(Entry::State::PAUSED, DriverEntry::State::COMPLETE);
add_entry(Entry::State::PAUSED, DriverEntry::State::CANCELLED);
add_entry(Entry::State::PAUSED, DriverEntry::State::INTERRUPTED);
- add_entry(Entry::State::PAUSED, base::nullopt);
+ add_entry(Entry::State::PAUSED, absl::nullopt);
add_entry(Entry::State::COMPLETE, DriverEntry::State::IN_PROGRESS);
add_entry(Entry::State::COMPLETE, DriverEntry::State::COMPLETE);
add_entry(Entry::State::COMPLETE, DriverEntry::State::CANCELLED);
add_entry(Entry::State::COMPLETE, DriverEntry::State::INTERRUPTED);
- add_entry(Entry::State::COMPLETE, base::nullopt);
+ add_entry(Entry::State::COMPLETE, absl::nullopt);
// Set up the Controller.
device_status_listener_->SetDeviceStatus(
@@ -1606,7 +1613,7 @@ TEST_F(DownloadServiceControllerImplTest, StartupRecoveryForUploadEntries) {
task_runner_->RunUntilIdle();
auto verify_entry = [this](const std::string& guid, Entry::State state,
- base::Optional<DriverEntry::State> driver_state) {
+ absl::optional<DriverEntry::State> driver_state) {
EXPECT_EQ(state, model_->Get(guid)->state);
auto driver_entry = driver_->Find(guid);
EXPECT_EQ(driver_state.has_value(), driver_entry.has_value());
@@ -1618,26 +1625,26 @@ TEST_F(DownloadServiceControllerImplTest, StartupRecoveryForUploadEntries) {
// download should be moved to complete state for ACTIVE/PAUSED entries.
// Entry::State::ACTIVE.
- verify_entry(entries[0].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[1].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[2].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[3].guid, Entry::State::COMPLETE, base::nullopt);
+ verify_entry(entries[0].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[1].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[2].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[3].guid, Entry::State::COMPLETE, absl::nullopt);
verify_entry(entries[4].guid, Entry::State::ACTIVE,
DriverEntry::State::IN_PROGRESS);
// Entry::State::PAUSED.
- verify_entry(entries[5].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[6].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[7].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[8].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[9].guid, Entry::State::PAUSED, base::nullopt);
+ verify_entry(entries[5].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[6].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[7].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[8].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[9].guid, Entry::State::PAUSED, absl::nullopt);
// Entry::State::COMPLETE.
- verify_entry(entries[10].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[11].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[12].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[13].guid, Entry::State::COMPLETE, base::nullopt);
- verify_entry(entries[14].guid, Entry::State::COMPLETE, base::nullopt);
+ verify_entry(entries[10].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[11].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[12].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[13].guid, Entry::State::COMPLETE, absl::nullopt);
+ verify_entry(entries[14].guid, Entry::State::COMPLETE, absl::nullopt);
}
// Download driver will remove the download if failed to persist the response
@@ -2021,7 +2028,7 @@ TEST_F(DownloadServiceControllerImplTest, DownloadTaskQueuesAfterFinish) {
// Simulate a download success event, which will trigger the controller to
// start a new download.
- base::Optional<DriverEntry> dentry1 = driver_->Find(entry1.guid);
+ absl::optional<DriverEntry> dentry1 = driver_->Find(entry1.guid);
EXPECT_TRUE(dentry1.has_value());
driver_->NotifyDownloadSucceeded(dentry1.value());
task_runner_->RunUntilIdle();
@@ -2035,7 +2042,7 @@ TEST_F(DownloadServiceControllerImplTest, DownloadTaskQueuesAfterFinish) {
// Simulate a download success event, which will trigger the controller to
// end it's task and schedule the task once (because the task is currently
// running).
- base::Optional<DriverEntry> dentry2 = driver_->Find(entry2.guid);
+ absl::optional<DriverEntry> dentry2 = driver_->Find(entry2.guid);
EXPECT_TRUE(dentry2.has_value());
driver_->NotifyDownloadSucceeded(dentry2.value());
task_runner_->RunUntilIdle();
diff --git a/chromium/components/download/internal/background_service/download_blockage_status.h b/chromium/components/download/internal/background_service/download_blockage_status.h
index e6ef9eaefab..16161c5be00 100644
--- a/chromium/components/download/internal/background_service/download_blockage_status.h
+++ b/chromium/components/download/internal/background_service/download_blockage_status.h
@@ -6,7 +6,7 @@
#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_DOWNLOAD_BLOCKAGE_STATUS_H_
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
diff --git a/chromium/components/download/internal/background_service/download_driver.h b/chromium/components/download/internal/background_service/download_driver.h
index 3cd9484c22e..3a2dcf74009 100644
--- a/chromium/components/download/internal/background_service/download_driver.h
+++ b/chromium/components/download/internal/background_service/download_driver.h
@@ -8,10 +8,10 @@
#include <set>
#include <string>
-#include "base/optional.h"
#include "components/download/internal/background_service/driver_entry.h"
#include "components/download/internal/background_service/memory_tracker.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class FilePath;
@@ -109,7 +109,7 @@ class DownloadDriver : public MemoryTracker {
virtual void Resume(const std::string& guid) = 0;
// Finds a download record from low level download library.
- virtual base::Optional<DriverEntry> Find(const std::string& guid) = 0;
+ virtual absl::optional<DriverEntry> Find(const std::string& guid) = 0;
// Called to query the current set of active downloads. This doesn't
// necessarily mean downloads started by the service.
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 22c38ee32ca..b039255db60 100644
--- a/chromium/components/download/internal/background_service/download_service_impl.cc
+++ b/chromium/components/download/internal/background_service/download_service_impl.cc
@@ -76,15 +76,15 @@ DownloadService::ServiceStatus DownloadServiceImpl::GetStatus() {
}
}
-void DownloadServiceImpl::StartDownload(const DownloadParams& download_params) {
+void DownloadServiceImpl::StartDownload(DownloadParams download_params) {
stats::LogServiceApiAction(download_params.client,
stats::ServiceApiAction::START_DOWNLOAD);
if (startup_completed_) {
- controller_->StartDownload(download_params);
+ controller_->StartDownload(std::move(download_params));
} else {
- pending_actions_.push_back(
- base::BindOnce(&Controller::StartDownload,
- base::Unretained(controller_.get()), download_params));
+ pending_actions_.push_back(base::BindOnce(
+ &Controller::StartDownload, base::Unretained(controller_.get()),
+ std::move(download_params)));
}
}
diff --git a/chromium/components/download/internal/background_service/download_service_impl.h b/chromium/components/download/internal/background_service/download_service_impl.h
index e604ab2d432..bfbaf53ca30 100644
--- a/chromium/components/download/internal/background_service/download_service_impl.h
+++ b/chromium/components/download/internal/background_service/download_service_impl.h
@@ -38,7 +38,7 @@ class DownloadServiceImpl : public DownloadService {
TaskFinishedCallback callback) override;
bool OnStopScheduledTask(DownloadTaskType task_type) override;
ServiceStatus GetStatus() override;
- void StartDownload(const DownloadParams& download_params) override;
+ void StartDownload(DownloadParams download_params) override;
void PauseDownload(const std::string& guid) override;
void ResumeDownload(const std::string& guid) override;
void CancelDownload(const std::string& guid) override;
diff --git a/chromium/components/download/internal/background_service/download_service_impl_unittest.cc b/chromium/components/download/internal/background_service/download_service_impl_unittest.cc
index 9792b067a85..f976d795184 100644
--- a/chromium/components/download/internal/background_service/download_service_impl_unittest.cc
+++ b/chromium/components/download/internal/background_service/download_service_impl_unittest.cc
@@ -67,13 +67,14 @@ TEST_F(DownloadServiceImplTest, TestGetStatus) {
TEST_F(DownloadServiceImplTest, TestApiPassThrough) {
DownloadParams params = test::BuildBasicDownloadParams();
+ auto guid = params.guid;
SchedulingParams scheduling_params;
scheduling_params.priority = SchedulingParams::Priority::UI;
EXPECT_CALL(*controller_, GetOwnerOfDownload(_))
.WillRepeatedly(Return(DownloadClient::TEST));
- EXPECT_CALL(*controller_, StartDownload(_)).Times(0);
+ EXPECT_CALL(*controller_, StartDownload_(_)).Times(0);
EXPECT_CALL(*controller_, PauseDownload(params.guid)).Times(0);
EXPECT_CALL(*controller_, ResumeDownload(params.guid)).Times(0);
EXPECT_CALL(*controller_, CancelDownload(params.guid)).Times(0);
@@ -82,7 +83,7 @@ TEST_F(DownloadServiceImplTest, TestApiPassThrough) {
{
base::HistogramTester histogram_tester;
- service_->StartDownload(params);
+ service_->StartDownload(std::move(params));
histogram_tester.ExpectBucketCount(
"Download.Service.Request.ClientAction",
@@ -99,38 +100,28 @@ TEST_F(DownloadServiceImplTest, TestApiPassThrough) {
histogram_tester.ExpectTotalCount(
"Download.Service.Request.ClientAction.__Test__", 1);
}
- service_->PauseDownload(params.guid);
- service_->ResumeDownload(params.guid);
- service_->CancelDownload(params.guid);
- service_->ChangeDownloadCriteria(params.guid, scheduling_params);
+ service_->PauseDownload(guid);
+ service_->ResumeDownload(guid);
+ service_->CancelDownload(guid);
+ service_->ChangeDownloadCriteria(guid, scheduling_params);
task_runner_->RunUntilIdle();
testing::Sequence seq1;
- EXPECT_CALL(*controller_, StartDownload(_)).Times(1).InSequence(seq1);
- EXPECT_CALL(*controller_, PauseDownload(params.guid))
- .Times(1)
- .InSequence(seq1);
- EXPECT_CALL(*controller_, ResumeDownload(params.guid))
- .Times(1)
- .InSequence(seq1);
- EXPECT_CALL(*controller_, CancelDownload(params.guid))
- .Times(1)
- .InSequence(seq1);
- EXPECT_CALL(*controller_, ChangeDownloadCriteria(params.guid, _))
+ EXPECT_CALL(*controller_, StartDownload_(_)).Times(1).InSequence(seq1);
+ EXPECT_CALL(*controller_, PauseDownload(guid)).Times(1).InSequence(seq1);
+ EXPECT_CALL(*controller_, ResumeDownload(guid)).Times(1).InSequence(seq1);
+ EXPECT_CALL(*controller_, CancelDownload(guid)).Times(1).InSequence(seq1);
+ EXPECT_CALL(*controller_, ChangeDownloadCriteria(guid, _))
.Times(1)
.InSequence(seq1);
controller_->TriggerInitCompleted();
task_runner_->RunUntilIdle();
- EXPECT_CALL(*controller_, PauseDownload(params.guid))
- .Times(1)
- .InSequence(seq1);
- EXPECT_CALL(*controller_, ResumeDownload(params.guid))
- .Times(1)
- .InSequence(seq1);
- service_->PauseDownload(params.guid);
- service_->ResumeDownload(params.guid);
+ EXPECT_CALL(*controller_, PauseDownload(guid)).Times(1).InSequence(seq1);
+ EXPECT_CALL(*controller_, ResumeDownload(guid)).Times(1).InSequence(seq1);
+ service_->PauseDownload(guid);
+ service_->ResumeDownload(guid);
task_runner_->RunUntilIdle();
}
diff --git a/chromium/components/download/internal/background_service/download_store_unittest.cc b/chromium/components/download/internal/background_service/download_store_unittest.cc
index 0e39297d535..c9f124752c6 100644
--- a/chromium/components/download/internal/background_service/download_store_unittest.cc
+++ b/chromium/components/download/internal/background_service/download_store_unittest.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/guid.h"
-#include "base/optional.h"
#include "components/download/internal/background_service/entry.h"
#include "components/download/internal/background_service/proto/entry.pb.h"
#include "components/download/internal/background_service/proto_conversions.h"
@@ -18,6 +17,7 @@
#include "components/leveldb_proto/testing/fake_db.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using testing::_;
@@ -65,7 +65,7 @@ class DownloadStoreTest : public testing::Test {
std::map<std::string, protodb::Entry> db_entries_;
leveldb_proto::test::FakeDB<protodb::Entry>* db_;
std::unique_ptr<DownloadStore> store_;
- base::Optional<bool> hard_recover_result_;
+ absl::optional<bool> hard_recover_result_;
DISALLOW_COPY_AND_ASSIGN(DownloadStoreTest);
};
diff --git a/chromium/components/download/internal/background_service/driver_entry.h b/chromium/components/download/internal/background_service/driver_entry.h
index cf3f973939b..84f42957cc3 100644
--- a/chromium/components/download/internal/background_service/driver_entry.h
+++ b/chromium/components/download/internal/background_service/driver_entry.h
@@ -10,8 +10,8 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace net {
@@ -70,7 +70,7 @@ struct DriverEntry {
// The blob data handle that contains download data.
// Will be available after the download is completed in incognito mode.
- base::Optional<storage::BlobDataHandle> blob_handle;
+ absl::optional<storage::BlobDataHandle> blob_handle;
// Time the download was marked as complete, base::Time() if the download is
// not yet complete.
diff --git a/chromium/components/download/internal/background_service/entry.h b/chromium/components/download/internal/background_service/entry.h
index 409b110ddd9..3b37f0b3588 100644
--- a/chromium/components/download/internal/background_service/entry.h
+++ b/chromium/components/download/internal/background_service/entry.h
@@ -7,6 +7,7 @@
#include <vector>
+#include "base/files/file_path.h"
#include "base/time/time.h"
#include "components/download/public/background_service/client.h"
#include "components/download/public/background_service/clients.h"
diff --git a/chromium/components/download/internal/background_service/entry_utils.h b/chromium/components/download/internal/background_service/entry_utils.h
index a519d759e24..b251a5b12fd 100644
--- a/chromium/components/download/internal/background_service/entry_utils.h
+++ b/chromium/components/download/internal/background_service/entry_utils.h
@@ -7,7 +7,6 @@
#include <map>
#include <set>
-#include <string>
#include <vector>
#include "components/download/internal/background_service/model.h"
diff --git a/chromium/components/download/internal/background_service/file_monitor.h b/chromium/components/download/internal/background_service/file_monitor.h
index 11fd4dd6a8a..050cb3bd1c1 100644
--- a/chromium/components/download/internal/background_service/file_monitor.h
+++ b/chromium/components/download/internal/background_service/file_monitor.h
@@ -7,7 +7,6 @@
#include <memory>
#include <set>
-#include <string>
#include <vector>
#include "components/download/internal/background_service/model.h"
diff --git a/chromium/components/download/internal/background_service/file_monitor_impl.h b/chromium/components/download/internal/background_service/file_monitor_impl.h
index 34ee78051a2..3df902b2261 100644
--- a/chromium/components/download/internal/background_service/file_monitor_impl.h
+++ b/chromium/components/download/internal/background_service/file_monitor_impl.h
@@ -9,7 +9,6 @@
#include <memory>
#include <set>
-#include <string>
#include <vector>
#include "base/files/file_path.h"
diff --git a/chromium/components/download/internal/background_service/file_monitor_unittest.cc b/chromium/components/download/internal/background_service/file_monitor_unittest.cc
index 4f7e2a7017c..2206ccce4b4 100644
--- a/chromium/components/download/internal/background_service/file_monitor_unittest.cc
+++ b/chromium/components/download/internal/background_service/file_monitor_unittest.cc
@@ -9,7 +9,6 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
-#include "base/optional.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/download/internal/background_service/driver_entry.h"
@@ -18,6 +17,7 @@
#include "components/download/internal/background_service/test/entry_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using testing::_;
@@ -55,7 +55,7 @@ class FileMonitorTest : public testing::Test {
bool completion_callback_called_;
std::unique_ptr<FileMonitor> monitor_;
- base::Optional<bool> hard_recovery_result_;
+ absl::optional<bool> hard_recovery_result_;
private:
DISALLOW_COPY_AND_ASSIGN(FileMonitorTest);
diff --git a/chromium/components/download/internal/background_service/in_memory_download.cc b/chromium/components/download/internal/background_service/in_memory_download.cc
index f5e369ff666..dd7445df8e6 100644
--- a/chromium/components/download/internal/background_service/in_memory_download.cc
+++ b/chromium/components/download/internal/background_service/in_memory_download.cc
@@ -8,6 +8,7 @@
#include <string>
#include "base/bind.h"
+#include "base/strings/string_piece.h"
#include "components/download/internal/background_service/blob_task_proxy.h"
#include "net/base/load_flags.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
@@ -110,8 +111,8 @@ size_t InMemoryDownloadImpl::EstimateMemoryUsage() const {
void InMemoryDownloadImpl::OnDataReceived(base::StringPiece string_piece,
base::OnceClosure resume) {
- size_t size = string_piece.as_string().size();
- data_.append(string_piece.as_string().data(), size);
+ size_t size = string_piece.size();
+ data_.append(std::string(string_piece).data(), size);
bytes_downloaded_ += size;
if (paused_) {
diff --git a/chromium/components/download/internal/background_service/in_memory_download_driver.cc b/chromium/components/download/internal/background_service/in_memory_download_driver.cc
index 69fed665443..082abf4df11 100644
--- a/chromium/components/download/internal/background_service/in_memory_download_driver.cc
+++ b/chromium/components/download/internal/background_service/in_memory_download_driver.cc
@@ -46,7 +46,7 @@ DriverEntry CreateDriverEntry(const InMemoryDownload& download) {
if (download.state() == InMemoryDownload::State::COMPLETE) {
auto blob_handle = download.ResultAsBlob();
if (blob_handle)
- entry.blob_handle = base::Optional<storage::BlobDataHandle>(*blob_handle);
+ entry.blob_handle = absl::optional<storage::BlobDataHandle>(*blob_handle);
}
return entry;
}
@@ -128,9 +128,9 @@ void InMemoryDownloadDriver::Resume(const std::string& guid) {
it->second->Resume();
}
-base::Optional<DriverEntry> InMemoryDownloadDriver::Find(
+absl::optional<DriverEntry> InMemoryDownloadDriver::Find(
const std::string& guid) {
- base::Optional<DriverEntry> entry;
+ absl::optional<DriverEntry> entry;
auto it = downloads_.find(guid);
if (it != downloads_.end())
entry = CreateDriverEntry(*it->second);
diff --git a/chromium/components/download/internal/background_service/in_memory_download_driver.h b/chromium/components/download/internal/background_service/in_memory_download_driver.h
index 4d2bbcabb4f..b08db473015 100644
--- a/chromium/components/download/internal/background_service/in_memory_download_driver.h
+++ b/chromium/components/download/internal/background_service/in_memory_download_driver.h
@@ -67,7 +67,7 @@ class InMemoryDownloadDriver : public DownloadDriver,
void Remove(const std::string& guid, bool remove_file) override;
void Pause(const std::string& guid) override;
void Resume(const std::string& guid) override;
- base::Optional<DriverEntry> Find(const std::string& guid) override;
+ absl::optional<DriverEntry> Find(const std::string& guid) override;
std::set<std::string> GetActiveDownloads() override;
size_t EstimateMemoryUsage() const override;
diff --git a/chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc b/chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc
index 432884237bc..8a5d35593b4 100644
--- a/chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc
+++ b/chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc
@@ -155,7 +155,7 @@ TEST_F(InMemoryDownloadDriverTest, DownloadSuccessAndRemove) {
// After starting a download, we should be able to find a record in the
// driver.
- base::Optional<DriverEntry> entry = driver()->Find(guid);
+ absl::optional<DriverEntry> entry = driver()->Find(guid);
EXPECT_TRUE(entry.has_value());
EXPECT_EQ(guid, entry->guid);
EXPECT_EQ(DriverEntry::State::IN_PROGRESS, entry->state);
@@ -207,7 +207,7 @@ TEST_F(InMemoryDownloadDriverTest, DownloadFailure) {
// Trigger download complete.
factory()->last_created_download()->SimulateDownloadComplete(
false /* success*/);
- base::Optional<DriverEntry> entry = driver()->Find(guid);
+ absl::optional<DriverEntry> entry = driver()->Find(guid);
EXPECT_TRUE(entry.has_value());
EXPECT_EQ(guid, entry->guid);
EXPECT_EQ(DriverEntry::State::INTERRUPTED, entry->state);
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 6dd468430ef..5d6bb457fdf 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
@@ -92,7 +92,7 @@ class InMemoryDownloadTest : public testing::Test {
void SetUp() override {
io_thread_ = std::make_unique<base::Thread>("Network and Blob IO thread");
base::Thread::Options options(base::MessagePumpType::IO, 0);
- io_thread_->StartWithOptions(options);
+ io_thread_->StartWithOptions(std::move(options));
base::RunLoop loop;
io_thread_->task_runner()->PostTask(
diff --git a/chromium/components/download/internal/background_service/log_source.h b/chromium/components/download/internal/background_service/log_source.h
index 930cb9f28f7..41b5ebd5eb0 100644
--- a/chromium/components/download/internal/background_service/log_source.h
+++ b/chromium/components/download/internal/background_service/log_source.h
@@ -8,8 +8,8 @@
#include <utility>
#include <vector>
-#include "base/optional.h"
#include "components/download/internal/background_service/controller.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
@@ -21,7 +21,7 @@ struct StartupStatus;
// instance of LogSource to push relevant log information to observers.
class LogSource {
public:
- using EntryDetails = std::pair<const Entry*, base::Optional<DriverEntry>>;
+ using EntryDetails = std::pair<const Entry*, absl::optional<DriverEntry>>;
using EntryDetailsList = std::vector<EntryDetails>;
virtual ~LogSource() = default;
@@ -36,7 +36,7 @@ class LogSource {
virtual EntryDetailsList GetServiceDownloads() = 0;
// Returns the (Driver)Entry object representing the donwnload at |guid|.
- virtual base::Optional<EntryDetails> GetServiceDownload(
+ virtual absl::optional<EntryDetails> GetServiceDownload(
const std::string& guid) = 0;
};
diff --git a/chromium/components/download/internal/background_service/logger_impl.cc b/chromium/components/download/internal/background_service/logger_impl.cc
index 0864d80aefb..6553cec8383 100644
--- a/chromium/components/download/internal/background_service/logger_impl.cc
+++ b/chromium/components/download/internal/background_service/logger_impl.cc
@@ -32,7 +32,7 @@ std::string ControllerStateToString(Controller::State state) {
}
}
-std::string OptBoolToString(base::Optional<bool> value) {
+std::string OptBoolToString(absl::optional<bool> value) {
if (value.has_value())
return value.value() ? "OK" : "BAD";
@@ -155,8 +155,8 @@ std::unique_ptr<base::DictionaryValue> DriverEntryToValue(
std::unique_ptr<base::DictionaryValue> EntryToValue(
const Entry& entry,
- const base::Optional<DriverEntry>& driver,
- const base::Optional<CompletionType>& completion_type) {
+ const absl::optional<DriverEntry>& driver,
+ const absl::optional<CompletionType>& completion_type) {
std::unique_ptr<base::DictionaryValue> serialized_entry =
std::make_unique<base::DictionaryValue>();
serialized_entry->SetString("client", ClientToString(entry.client));
@@ -236,7 +236,7 @@ base::Value LoggerImpl::GetServiceDownloads() {
auto entries = log_source_->GetServiceDownloads();
for (auto& entry : entries) {
serialized_entries.Append(
- EntryToValue(*entry.first, entry.second, base::nullopt));
+ EntryToValue(*entry.first, entry.second, absl::nullopt));
}
return std::move(serialized_entries);
@@ -270,7 +270,7 @@ void LoggerImpl::OnServiceDownloadChanged(const std::string& guid) {
return;
auto entry = EntryToValue(*(entry_details->first), entry_details->second,
- base::nullopt);
+ absl::nullopt);
for (auto& observer : observers_)
observer.OnServiceDownloadChanged(*entry);
@@ -283,7 +283,7 @@ void LoggerImpl::OnServiceDownloadFailed(CompletionType completion_type,
if (observers_.empty())
return;
- auto serialized_entry = EntryToValue(entry, base::nullopt, completion_type);
+ auto serialized_entry = EntryToValue(entry, absl::nullopt, completion_type);
for (auto& observer : observers_)
observer.OnServiceDownloadFailed(*serialized_entry);
}
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 9381396f953..62d3db18b94 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
@@ -7,7 +7,7 @@
#include <memory>
#include "base/run_loop.h"
-#include "base/test/power_monitor_test_base.h"
+#include "base/test/power_monitor_test.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/download/internal/background_service/scheduler/battery_status_listener_impl.h"
@@ -85,10 +85,6 @@ class DeviceStatusListenerTest : public testing::Test {
DeviceStatusListenerTest() {}
void SetUp() override {
- auto power_source = std::make_unique<base::PowerMonitorTestSource>();
- power_source_ = power_source.get();
- base::PowerMonitor::Initialize(std::move(power_source));
-
auto battery_listener = std::make_unique<TestBatteryStatusListener>();
test_battery_listener_ = battery_listener.get();
@@ -102,7 +98,6 @@ class DeviceStatusListenerTest : public testing::Test {
void TearDown() override {
listener_.reset();
- base::PowerMonitor::ShutdownForTesting();
}
protected:
@@ -135,7 +130,7 @@ class DeviceStatusListenerTest : public testing::Test {
// Simulates a battery change call.
void SimulateBatteryChange(bool on_battery_power) {
- power_source_->GeneratePowerStateEvent(on_battery_power);
+ power_source_.GeneratePowerStateEvent(on_battery_power);
}
void ChangeBatteryPercentage(int percentage) {
@@ -148,7 +143,7 @@ class DeviceStatusListenerTest : public testing::Test {
// Needed for network change notifier and power monitor.
base::test::SingleThreadTaskEnvironment task_environment_;
- base::PowerMonitorTestSource* power_source_;
+ base::test::ScopedPowerMonitorTestSource power_source_;
TestBatteryStatusListener* test_battery_listener_;
};
diff --git a/chromium/components/download/internal/background_service/startup_status.h b/chromium/components/download/internal/background_service/startup_status.h
index f9814535280..fda6b2459fc 100644
--- a/chromium/components/download/internal/background_service/startup_status.h
+++ b/chromium/components/download/internal/background_service/startup_status.h
@@ -6,7 +6,7 @@
#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STARTUP_STATUS_H_
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
@@ -16,9 +16,9 @@ struct StartupStatus {
StartupStatus();
~StartupStatus();
- base::Optional<bool> driver_ok;
- base::Optional<bool> model_ok;
- base::Optional<bool> file_monitor_ok;
+ absl::optional<bool> driver_ok;
+ absl::optional<bool> model_ok;
+ absl::optional<bool> file_monitor_ok;
// Resets all startup state tracking.
void Reset();
diff --git a/chromium/components/download/internal/background_service/stats.h b/chromium/components/download/internal/background_service/stats.h
index 7bbeda897e6..24f1b0a2bc6 100644
--- a/chromium/components/download/internal/background_service/stats.h
+++ b/chromium/components/download/internal/background_service/stats.h
@@ -6,7 +6,6 @@
#define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_STATS_H_
#include "base/files/file.h"
-#include "base/optional.h"
#include "components/download/internal/background_service/controller.h"
#include "components/download/internal/background_service/download_blockage_status.h"
#include "components/download/internal/background_service/driver_entry.h"
@@ -14,6 +13,7 @@
#include "components/download/public/background_service/clients.h"
#include "components/download/public/background_service/download_params.h"
#include "components/download/public/task/download_task_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
diff --git a/chromium/components/download/internal/common/download_create_info.cc b/chromium/components/download/internal/common/download_create_info.cc
index bba0342d593..677d4cf2aa9 100644
--- a/chromium/components/download/internal/common/download_create_info.cc
+++ b/chromium/components/download/internal/common/download_create_info.cc
@@ -8,7 +8,6 @@
#include <string>
#include "base/format_macros.h"
-#include "base/strings/stringprintf.h"
#include "net/http/http_response_headers.h"
namespace download {
diff --git a/chromium/components/download/internal/common/download_db_cache.cc b/chromium/components/download/internal/common/download_db_cache.cc
index 9ff1755ad45..eeb30cf1235 100644
--- a/chromium/components/download/internal/common/download_db_cache.cc
+++ b/chromium/components/download/internal/common/download_db_cache.cc
@@ -27,19 +27,19 @@ enum class ShouldUpdateDownloadDBResult {
};
ShouldUpdateDownloadDBResult ShouldUpdateDownloadDB(
- base::Optional<DownloadDBEntry> previous,
+ absl::optional<DownloadDBEntry> previous,
const DownloadDBEntry& current) {
if (!previous)
return ShouldUpdateDownloadDBResult::UPDATE_IMMEDIATELY;
- base::Optional<InProgressInfo> previous_info;
+ absl::optional<InProgressInfo> previous_info;
if (previous->download_info)
previous_info = previous->download_info->in_progress_info;
base::FilePath previous_path =
previous_info ? previous_info->current_path : base::FilePath();
bool previous_paused = previous_info ? previous_info->paused : false;
- base::Optional<InProgressInfo> current_info;
+ absl::optional<InProgressInfo> current_info;
if (current.download_info)
current_info = current.download_info->in_progress_info;
@@ -76,7 +76,7 @@ void CleanUpInProgressEntry(DownloadDBEntry* entry) {
if (!entry->download_info)
return;
- base::Optional<InProgressInfo>& in_progress_info =
+ absl::optional<InProgressInfo>& in_progress_info =
entry->download_info->in_progress_info;
if (!in_progress_info)
return;
@@ -98,7 +98,7 @@ void OnDownloadDBUpdated(bool success) {
}
// Check if a DownloadDBEntry represents an in progress download.
-bool IsInProgressEntry(base::Optional<DownloadDBEntry> entry) {
+bool IsInProgressEntry(absl::optional<DownloadDBEntry> entry) {
if (!entry || !entry->download_info ||
!entry->download_info->in_progress_info)
return false;
@@ -123,12 +123,12 @@ void DownloadDBCache::Initialize(InitializeCallback callback) {
weak_factory_.GetWeakPtr(), std::move(callback)));
}
-base::Optional<DownloadDBEntry> DownloadDBCache::RetrieveEntry(
+absl::optional<DownloadDBEntry> DownloadDBCache::RetrieveEntry(
const std::string& guid) {
auto iter = cached_entries_.find(guid);
if (iter != cached_entries_.end())
return iter->second;
- return base::nullopt;
+ return absl::nullopt;
}
void DownloadDBCache::AddOrReplaceEntry(const DownloadDBEntry& entry) {
@@ -167,7 +167,7 @@ void DownloadDBCache::UpdateDownloadDB() {
std::vector<DownloadDBEntry> entries;
for (const auto& guid : updated_guids_) {
- base::Optional<DownloadDBEntry> entry = RetrieveEntry(guid);
+ absl::optional<DownloadDBEntry> entry = RetrieveEntry(guid);
DCHECK(entry);
entries.emplace_back(entry.value());
// If the entry is no longer in-progress, remove it from the cache as it may
diff --git a/chromium/components/download/internal/common/download_db_cache.h b/chromium/components/download/internal/common/download_db_cache.h
index bd61630fcc4..639559aabfd 100644
--- a/chromium/components/download/internal/common/download_db_cache.h
+++ b/chromium/components/download/internal/common/download_db_cache.h
@@ -12,10 +12,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/timer/timer.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_item.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
@@ -34,7 +34,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadDBCache
std::unique_ptr<std::vector<DownloadDBEntry>>)>;
void Initialize(InitializeCallback callback);
- base::Optional<DownloadDBEntry> RetrieveEntry(const std::string& guid);
+ absl::optional<DownloadDBEntry> RetrieveEntry(const std::string& guid);
void AddOrReplaceEntry(const DownloadDBEntry& entry);
// Remove an entry from the DownloadDB.
diff --git a/chromium/components/download/internal/common/download_file_impl.cc b/chromium/components/download/internal/common/download_file_impl.cc
index b34b5b579ff..7d9ae871a61 100644
--- a/chromium/components/download/internal/common/download_file_impl.cc
+++ b/chromium/components/download/internal/common/download_file_impl.cc
@@ -11,12 +11,12 @@
#include "base/bind.h"
#include "base/files/file_util.h"
-#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/download/internal/common/parallel_download_utils.h"
diff --git a/chromium/components/download/internal/common/download_file_unittest.cc b/chromium/components/download/internal/common/download_file_unittest.cc
index 9e51afeabe9..070ac4da552 100644
--- a/chromium/components/download/internal/common/download_file_unittest.cc
+++ b/chromium/components/download/internal/common/download_file_unittest.cc
@@ -239,7 +239,8 @@ class DownloadFileTest : public testing::Test {
int data_len = strlen(kTestData1);
while (len > 0) {
int bytes_to_write = len > data_len ? data_len : len;
- base::AppendToFile(save_info->file_path, kTestData1, bytes_to_write);
+ base::AppendToFile(save_info->file_path,
+ base::StringPiece(kTestData1, bytes_to_write));
len -= bytes_to_write;
}
}
diff --git a/chromium/components/download/internal/common/download_item_impl.cc b/chromium/components/download/internal/common/download_item_impl.cc
index f557ef87951..2d56947d149 100644
--- a/chromium/components/download/internal/common/download_item_impl.cc
+++ b/chromium/components/download/internal/common/download_item_impl.cc
@@ -34,7 +34,6 @@
#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
@@ -42,6 +41,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task_runner_util.h"
#include "base/trace_event/memory_usage_estimator.h"
+#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/download/internal/common/download_job_impl.h"
#include "components/download/internal/common/parallel_download_utils.h"
@@ -61,6 +61,7 @@
#include "net/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/referrer_policy.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if defined(OS_ANDROID)
#include "components/download/internal/common/android/download_collection_bridge.h"
@@ -152,6 +153,8 @@ std::string GetDownloadDangerNames(DownloadDangerType type) {
return "POTENTIALLY_UNWANTED";
case DOWNLOAD_DANGER_TYPE_ALLOWLISTED_BY_POLICY:
return "ALLOWLISTED_BY_POLICY";
+ case DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE:
+ return "DANGEROUS_ACCOUNT_COMPROMISE";
default:
NOTREACHED();
return "UNKNOWN_DANGER_TYPE";
@@ -228,7 +231,7 @@ DownloadItemImpl::RequestInfo::RequestInfo(
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
- const base::Optional<url::Origin>& request_initiator,
+ const absl::optional<url::Origin>& request_initiator,
const std::string& suggested_filename,
const base::FilePath& forced_file_path,
ui::PageTransition transition_type,
@@ -295,7 +298,7 @@ DownloadItemImpl::DownloadItemImpl(
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_refererr_url,
- const base::Optional<url::Origin>& request_initiator,
+ const absl::optional<url::Origin>& request_initiator,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
@@ -315,7 +318,7 @@ DownloadItemImpl::DownloadItemImpl(
base::Time last_access_time,
bool transient,
const std::vector<DownloadItem::ReceivedSlice>& received_slices,
- base::Optional<DownloadSchedule> download_schedule,
+ absl::optional<DownloadSchedule> download_schedule,
std::unique_ptr<DownloadEntry> download_entry)
: request_info_(url_chain,
referrer_url,
@@ -644,14 +647,14 @@ void DownloadItemImpl::UpdateResumptionInfo(bool user_resume) {
}
auto_resume_count_ = user_resume ? 0 : ++auto_resume_count_;
- download_schedule_ = base::nullopt;
+ download_schedule_ = absl::nullopt;
RecordDownloadLaterEvent(DownloadLaterEvent::kScheduleRemoved);
}
void DownloadItemImpl::Cancel(bool user_cancel) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DVLOG(20) << __func__ << "() download = " << DebugString(true);
- download_schedule_ = base::nullopt;
+ download_schedule_ = absl::nullopt;
InterruptAndDiscardPartialState(
user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
: DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN);
@@ -862,7 +865,7 @@ const GURL& DownloadItemImpl::GetTabReferrerUrl() const {
return request_info_.tab_referrer_url;
}
-const base::Optional<url::Origin>& DownloadItemImpl::GetRequestInitiator()
+const absl::optional<url::Origin>& DownloadItemImpl::GetRequestInitiator()
const {
return request_info_.request_initiator;
}
@@ -999,7 +1002,8 @@ bool DownloadItemImpl::IsDangerous() const {
danger_type_ == DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE ||
danger_type_ == DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING ||
danger_type_ == DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK ||
- danger_type_ == DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING;
+ danger_type_ == DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING ||
+ danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE;
}
bool DownloadItemImpl::IsMixedContent() const {
@@ -1124,7 +1128,7 @@ DownloadItem::DownloadCreationType DownloadItemImpl::GetDownloadCreationType()
return download_type_;
}
-const base::Optional<DownloadSchedule>& DownloadItemImpl::GetDownloadSchedule()
+const absl::optional<DownloadSchedule>& DownloadItemImpl::GetDownloadSchedule()
const {
return download_schedule_;
}
@@ -1163,7 +1167,7 @@ void DownloadItemImpl::OnAsyncScanningCompleted(
}
void DownloadItemImpl::OnDownloadScheduleChanged(
- base::Optional<DownloadSchedule> schedule) {
+ absl::optional<DownloadSchedule> schedule) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!base::FeatureList::IsEnabled(features::kDownloadLater) ||
state_ != INTERRUPTED_INTERNAL) {
@@ -1581,7 +1585,12 @@ void DownloadItemImpl::Start(
destination_info_.hash.clear();
deferred_interrupt_reason_ = new_create_info.result;
TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
- DetermineDownloadTarget();
+ // We're posting the call to DetermineDownloadTarget() instead of calling it
+ // directly to ensure that OnDownloadTargetDetermined() is not called
+ // synchronously. See crbug.com/1209856 for more details.
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&DownloadItemImpl::DetermineDownloadTarget,
+ weak_ptr_factory_.GetWeakPtr()));
return;
}
@@ -1629,7 +1638,7 @@ void DownloadItemImpl::Start(
job_->Start(download_file_.get(),
base::BindRepeating(&DownloadItemImpl::OnDownloadFileInitialized,
- weak_ptr_factory_.GetWeakPtr()),
+ weak_ptr_factory_.GetWeakPtr()),
GetReceivedSlices());
}
@@ -1665,7 +1674,7 @@ void DownloadItemImpl::DetermineDownloadTarget() {
download_source_);
delegate_->DetermineDownloadTarget(
this, base::BindOnce(&DownloadItemImpl::OnDownloadTargetDetermined,
- weak_ptr_factory_.GetWeakPtr()));
+ weak_ptr_factory_.GetWeakPtr()));
}
// Called by delegate_ when the download target path has been determined.
@@ -1675,7 +1684,7 @@ void DownloadItemImpl::OnDownloadTargetDetermined(
DownloadDangerType danger_type,
MixedContentStatus mixed_content_status,
const base::FilePath& intermediate_path,
- base::Optional<DownloadSchedule> download_schedule,
+ absl::optional<DownloadSchedule> download_schedule,
DownloadInterruptReason interrupt_reason) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (state_ == CANCELLED_INTERNAL)
@@ -1755,7 +1764,7 @@ void DownloadItemImpl::OnDownloadTargetDetermined(
DCHECK(!IsSavePackageDownload());
DownloadFile::RenameCompletionCallback callback =
base::BindOnce(&DownloadItemImpl::OnDownloadRenamedToIntermediateName,
- weak_ptr_factory_.GetWeakPtr());
+ weak_ptr_factory_.GetWeakPtr());
#if defined(OS_ANDROID)
if ((download_type_ == TYPE_ACTIVE_DOWNLOAD && !transient_ &&
DownloadCollectionBridge::ShouldPublishDownload(GetTargetFilePath())) ||
@@ -1845,7 +1854,7 @@ void DownloadItemImpl::OnTargetResolved() {
return;
}
- download_schedule_ = base::nullopt;
+ download_schedule_ = absl::nullopt;
TransitionTo(IN_PROGRESS_INTERNAL);
// TODO(asanka): Calling UpdateObservers() prior to MaybeCompleteDownload() is
@@ -1889,7 +1898,7 @@ bool DownloadItemImpl::ShouldDownloadLater() const {
}
void DownloadItemImpl::SwapDownloadSchedule(
- base::Optional<DownloadSchedule> download_schedule) {
+ absl::optional<DownloadSchedule> download_schedule) {
if (!base::FeatureList::IsEnabled(features::kDownloadLater))
return;
download_schedule_ = std::move(download_schedule);
@@ -2223,7 +2232,7 @@ void DownloadItemImpl::InterruptWithPartialState(
base::TimeDelta time_since_start = base::Time::Now() - GetStartTime();
int resulting_file_size = GetReceivedBytes();
- base::Optional<int> change_in_file_size;
+ absl::optional<int> change_in_file_size;
if (total_bytes_ >= 0) {
change_in_file_size = total_bytes_ - resulting_file_size;
}
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 b432a41ee88..92c931b6448 100644
--- a/chromium/components/download/internal/common/download_item_impl_delegate.cc
+++ b/chromium/components/download/internal/common/download_item_impl_delegate.cc
@@ -38,7 +38,7 @@ void DownloadItemImplDelegate::DetermineDownloadTarget(
target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, target_path,
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
}
bool DownloadItemImplDelegate::ShouldCompleteDownload(
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 30f609d2537..a36a7adf763 100644
--- a/chromium/components/download/internal/common/download_item_impl_unittest.cc
+++ b/chromium/components/download/internal/common/download_item_impl_unittest.cc
@@ -287,7 +287,7 @@ class DownloadItemTest : public testing::Test {
download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, reason, false, false,
false, base::Time::Now(), true,
std::vector<download::DownloadItem::ReceivedSlice>(),
- base::nullopt /*download_schedule*/, nullptr /* download_entry */);
+ absl::nullopt /*download_schedule*/, nullptr /* download_entry */);
return item;
}
@@ -337,7 +337,7 @@ class DownloadItemTest : public testing::Test {
DownloadItemImplDelegate::DownloadTargetCallback callback;
MockDownloadFile* file = CallDownloadItemStart(item, &callback);
DoRenameAndRunTargetCallback(item, file, std::move(callback), danger_type,
- base::nullopt);
+ absl::nullopt);
return file;
}
@@ -346,7 +346,7 @@ class DownloadItemTest : public testing::Test {
MockDownloadFile* download_file,
DownloadItemImplDelegate::DownloadTargetCallback callback,
DownloadDangerType danger_type,
- base::Optional<DownloadSchedule> download_schedule) {
+ absl::optional<DownloadSchedule> download_schedule) {
base::FilePath target_path(kDummyTargetPath);
base::FilePath intermediate_path(kDummyIntermediatePath);
auto task_runner = base::ThreadTaskRunnerHandle::Get();
@@ -616,7 +616,7 @@ TEST_F(DownloadItemTest, NotificationAfterOnDownloadTargetDetermined) {
target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
EXPECT_FALSE(observer.CheckAndResetDownloadUpdated());
task_environment_.RunUntilIdle();
EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
@@ -915,7 +915,7 @@ TEST_F(DownloadItemTest, AutomaticResumption_AttemptLimit) {
target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
// Use a continuable interrupt.
@@ -1009,7 +1009,7 @@ TEST_F(DownloadItemTest, FailedResumptionDoesntUpdateOriginState) {
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN,
base::FilePath(kDummyIntermediatePath),
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
ASSERT_TRUE(item->GetResponseHeaders());
@@ -1218,7 +1218,7 @@ TEST_F(DownloadItemTest, DisplayName) {
target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
EXPECT_EQ(FILE_PATH_LITERAL("foo.bar"),
item->GetFileNameToReportUser().value());
@@ -1272,7 +1272,7 @@ TEST_F(DownloadItemTest, InitDownloadFileFails) {
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN,
base::FilePath(kDummyIntermediatePath),
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
@@ -1315,7 +1315,7 @@ TEST_F(DownloadItemTest, StartFailedDownload) {
.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, target_path,
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
// Interrupt reason carried in create info should be recorded.
@@ -1352,7 +1352,7 @@ TEST_F(DownloadItemTest, CallbackAfterRename) {
final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
// All the callbacks should have happened by now.
::testing::Mock::VerifyAndClearExpectations(download_file);
@@ -1408,7 +1408,7 @@ TEST_F(DownloadItemTest, CallbackAfterInterruptedRename) {
final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
// All the callbacks should have happened by now.
::testing::Mock::VerifyAndClearExpectations(download_file);
@@ -1478,7 +1478,7 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Restart) {
final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
// All the callbacks should have happened by now.
::testing::Mock::VerifyAndClearExpectations(download_file);
@@ -1530,7 +1530,7 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Continue) {
final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
// All the callbacks should have happened by now.
::testing::Mock::VerifyAndClearExpectations(download_file);
@@ -1577,7 +1577,7 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Failed) {
final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, intermediate_path,
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
// All the callbacks should have happened by now.
::testing::Mock::VerifyAndClearExpectations(download_file);
@@ -1620,7 +1620,7 @@ TEST_F(DownloadItemTest, DownloadTargetDetermined_Cancel) {
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN,
base::FilePath(FILE_PATH_LITERAL("bar")),
- base::nullopt /*download_schedule*/,
+ absl::nullopt /*download_schedule*/,
DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
EXPECT_EQ(DownloadItem::CANCELLED, item->GetState());
}
@@ -1635,7 +1635,7 @@ TEST_F(DownloadItemTest, DownloadTargetDetermined_CancelWithEmptyName) {
base::FilePath(), DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, base::FilePath(),
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
EXPECT_EQ(DownloadItem::CANCELLED, item->GetState());
}
@@ -1650,7 +1650,7 @@ TEST_F(DownloadItemTest, DownloadTargetDetermined_Conflict) {
DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN,
- target_path, base::nullopt /*download_schedule*/,
+ target_path, absl::nullopt /*download_schedule*/,
DOWNLOAD_INTERRUPT_REASON_FILE_SAME_AS_SOURCE);
EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_SAME_AS_SOURCE,
@@ -2511,7 +2511,7 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, DownloadCancelledByUser) {
.Run(base::FilePath(), DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN, base::FilePath(),
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
EXPECT_EQ(DownloadItem::CANCELLED, item_->GetState());
EXPECT_TRUE(canceled());
task_environment_.RunUntilIdle();
@@ -2566,7 +2566,7 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameFails) {
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN,
base::FilePath(kDummyIntermediatePath),
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
ASSERT_FALSE(intermediate_rename_callback.is_null());
@@ -2635,7 +2635,7 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameSucceeds) {
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
DownloadItem::MixedContentStatus::UNKNOWN,
base::FilePath(kDummyIntermediatePath),
- base::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
+ absl::nullopt /*download_schedule*/, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
ASSERT_FALSE(intermediate_rename_callback.is_null());
@@ -2671,7 +2671,7 @@ TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameSucceeds) {
struct DownloadLaterTestParam {
// Input to build DownloadSchedule and config network type.
bool only_on_wifi;
- base::Optional<base::Time> start_time;
+ absl::optional<base::Time> start_time;
bool is_active_network_metered;
// Output and expectation.
@@ -2683,10 +2683,10 @@ std::vector<DownloadLaterTestParam> DownloadLaterTestParams() {
std::vector<DownloadLaterTestParam> params;
// Required wifi, and currently on wifi, the download won't stop.
params.push_back(
- {true, base::nullopt, false, DownloadItem::IN_PROGRESS, false});
+ {true, absl::nullopt, false, DownloadItem::IN_PROGRESS, false});
// Don't require wifi, and currently not on wifi, the download won't stop.
params.push_back(
- {false, base::nullopt, true, DownloadItem::IN_PROGRESS, true});
+ {false, absl::nullopt, true, DownloadItem::IN_PROGRESS, true});
// Download later, will be interrupted.
auto future_time = base::Time::Now() + base::TimeDelta::FromDays(10);
params.push_back({false, future_time, true, DownloadItem::INTERRUPTED, true});
@@ -2724,8 +2724,8 @@ TEST_P(DownloadLaterTest, TestDownloadScheduleAfterTargetDetermined) {
EXPECT_CALL(*download_file, Detach());
}
- base::Optional<DownloadSchedule> download_schedule =
- base::make_optional<DownloadSchedule>(param.only_on_wifi,
+ absl::optional<DownloadSchedule> download_schedule =
+ absl::make_optional<DownloadSchedule>(param.only_on_wifi,
param.start_time);
DoRenameAndRunTargetCallback(item, download_file, std::move(callback),
@@ -2767,8 +2767,8 @@ TEST_P(DownloadLaterTest, TestOnDownloadScheduleChanged) {
.Times(will_resume);
// Change the download schedule.
- base::Optional<DownloadSchedule> download_schedule =
- base::make_optional<DownloadSchedule>(param.only_on_wifi,
+ absl::optional<DownloadSchedule> download_schedule =
+ absl::make_optional<DownloadSchedule>(param.only_on_wifi,
param.start_time);
item->OnDownloadScheduleChanged(std::move(download_schedule));
@@ -2789,7 +2789,7 @@ TEST_F(DownloadItemTest, CancelWithDownloadSchedule) {
auto item = CreateDownloadItem(DownloadItem::DownloadState::INTERRUPTED,
DOWNLOAD_INTERRUPT_REASON_CRASH);
- auto download_schedule = base::make_optional<DownloadSchedule>(
+ auto download_schedule = absl::make_optional<DownloadSchedule>(
false, base::Time::Now() + base::TimeDelta::FromDays(10));
item->OnDownloadScheduleChanged(std::move(download_schedule));
diff --git a/chromium/components/download/internal/common/download_item_rename_handler.cc b/chromium/components/download/internal/common/download_item_rename_handler.cc
index 53b32772598..fc2c31e67ce 100644
--- a/chromium/components/download/internal/common/download_item_rename_handler.cc
+++ b/chromium/components/download/internal/common/download_item_rename_handler.cc
@@ -4,6 +4,7 @@
#include "components/download/public/common/download_item_rename_handler.h"
+#include "base/files/file_path.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item.h"
diff --git a/chromium/components/download/internal/common/download_ukm_helper.cc b/chromium/components/download/internal/common/download_ukm_helper.cc
index 97efecff42a..86e3f61f51e 100644
--- a/chromium/components/download/internal/common/download_ukm_helper.cc
+++ b/chromium/components/download/internal/common/download_ukm_helper.cc
@@ -41,7 +41,7 @@ void DownloadUkmHelper::RecordDownloadStarted(int download_id,
void DownloadUkmHelper::RecordDownloadInterrupted(
int download_id,
- base::Optional<int> change_in_file_size,
+ absl::optional<int> change_in_file_size,
DownloadInterruptReason reason,
int resulting_file_size,
const base::TimeDelta& time_since_start,
diff --git a/chromium/components/download/internal/common/download_utils.cc b/chromium/components/download/internal/common/download_utils.cc
index 6ad1043959e..46f111b676f 100644
--- a/chromium/components/download/internal/common/download_utils.cc
+++ b/chromium/components/download/internal/common/download_utils.cc
@@ -448,13 +448,13 @@ DownloadDBEntry CreateDownloadDBEntryFromItem(const DownloadItemImpl& item) {
}
std::unique_ptr<DownloadEntry> CreateDownloadEntryFromDownloadDBEntry(
- base::Optional<DownloadDBEntry> entry) {
+ absl::optional<DownloadDBEntry> entry) {
if (!entry || !entry->download_info)
return nullptr;
- base::Optional<InProgressInfo> in_progress_info =
+ absl::optional<InProgressInfo> in_progress_info =
entry->download_info->in_progress_info;
- base::Optional<UkmInfo> ukm_info = entry->download_info->ukm_info;
+ absl::optional<UkmInfo> ukm_info = entry->download_info->ukm_info;
if (!ukm_info || !in_progress_info)
return nullptr;
diff --git a/chromium/components/download/internal/common/download_worker.h b/chromium/components/download/internal/common/download_worker.h
index 8c2339862ba..b1443d13ebe 100644
--- a/chromium/components/download/internal/common/download_worker.h
+++ b/chromium/components/download/internal/common/download_worker.h
@@ -84,4 +84,4 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_WORKER_H_
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_COMMON_DOWNLOAD_WORKER_H_
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 c8a3830f214..654649ad350 100644
--- a/chromium/components/download/internal/common/in_progress_download_manager.cc
+++ b/chromium/components/download/internal/common/in_progress_download_manager.cc
@@ -5,7 +5,6 @@
#include "components/download/public/common/in_progress_download_manager.h"
#include "base/bind.h"
-#include "base/optional.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -28,6 +27,7 @@
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
@@ -50,7 +50,7 @@ std::unique_ptr<DownloadItemImpl> CreateDownloadItemImpl(
if (entry.download_info->id < 0)
return nullptr;
- base::Optional<InProgressInfo> in_progress_info =
+ absl::optional<InProgressInfo> in_progress_info =
entry.download_info->in_progress_info;
if (!in_progress_info)
return nullptr;
@@ -59,7 +59,7 @@ std::unique_ptr<DownloadItemImpl> CreateDownloadItemImpl(
in_progress_info->current_path, in_progress_info->target_path,
in_progress_info->url_chain, in_progress_info->referrer_url,
in_progress_info->site_url, in_progress_info->tab_url,
- in_progress_info->tab_referrer_url, base::nullopt,
+ in_progress_info->tab_referrer_url, absl::nullopt,
in_progress_info->mime_type, in_progress_info->original_mime_type,
in_progress_info->start_time, in_progress_info->end_time,
in_progress_info->etag, in_progress_info->last_modified,
@@ -158,7 +158,7 @@ void OnPathReserved(DownloadItemImplDelegate::DownloadTargetCallback callback,
const InProgressDownloadManager::IntermediatePathCallback&
intermediate_path_cb,
const base::FilePath& forced_file_path,
- base::Optional<DownloadSchedule> download_schedule,
+ absl::optional<DownloadSchedule> download_schedule,
PathValidationResult result,
const base::FilePath& target_path) {
base::FilePath intermediate_path;
diff --git a/chromium/components/download/internal/common/resource_downloader.cc b/chromium/components/download/internal/common/resource_downloader.cc
index 20ebc607e12..fe8a1a6d638 100644
--- a/chromium/components/download/internal/common/resource_downloader.cc
+++ b/chromium/components/download/internal/common/resource_downloader.cc
@@ -252,7 +252,7 @@ void ResourceDownloader::OnReceiveRedirect() {
std::vector<std::string>() /* removed_headers */,
net::HttpRequestHeaders() /* modified_headers */,
net::HttpRequestHeaders() /* modified_cors_exempt_headers */,
- base::nullopt);
+ absl::nullopt);
}
void ResourceDownloader::OnResponseCompleted() {
diff --git a/chromium/components/download/internal/common/resource_downloader.h b/chromium/components/download/internal/common/resource_downloader.h
index d3c52f7945b..dfe78b80c40 100644
--- a/chromium/components/download/internal/common/resource_downloader.h
+++ b/chromium/components/download/internal/common/resource_downloader.h
@@ -149,7 +149,7 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
GURL tab_referrer_url_;
// URLLoader status when intercepting the navigation request.
- base::Optional<network::URLLoaderCompletionStatus> url_loader_status_;
+ absl::optional<network::URLLoaderCompletionStatus> url_loader_status_;
// TaskRunner to post callbacks to the |delegate_|
scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
diff --git a/chromium/components/download/public/background_service/basic_task_scheduler.h b/chromium/components/download/public/background_service/basic_task_scheduler.h
index aa4fef38521..c9194792667 100644
--- a/chromium/components/download/public/background_service/basic_task_scheduler.h
+++ b/chromium/components/download/public/background_service/basic_task_scheduler.h
@@ -51,4 +51,4 @@ class BasicTaskScheduler : public download::TaskScheduler {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_PUBLIC_TASK_TASK_SCHEDULER_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_BASIC_TASK_SCHEDULER_H_
diff --git a/chromium/components/download/public/background_service/client.h b/chromium/components/download/public/background_service/client.h
index 1374d0d83eb..f7cbf5cd217 100644
--- a/chromium/components/download/public/background_service/client.h
+++ b/chromium/components/download/public/background_service/client.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/files/file_path.h"
#include "net/http/http_response_headers.h"
#include "url/gurl.h"
diff --git a/chromium/components/download/public/background_service/download_metadata.h b/chromium/components/download/public/background_service/download_metadata.h
index cddd230e933..a2d4b47db63 100644
--- a/chromium/components/download/public/background_service/download_metadata.h
+++ b/chromium/components/download/public/background_service/download_metadata.h
@@ -9,9 +9,9 @@
#include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "net/http/http_response_headers.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace download {
@@ -24,7 +24,7 @@ struct CompletionInfo {
// The blob data handle that contains download data.
// Will be available after the download is completed in incognito mode.
- base::Optional<storage::BlobDataHandle> blob_handle;
+ absl::optional<storage::BlobDataHandle> blob_handle;
// Download file size in bytes.
uint64_t bytes_downloaded = 0u;
@@ -70,7 +70,7 @@ struct DownloadMetaData {
// Info about successfully completed download, or null for in-progress
// download. Failed download will not be persisted and exposed as meta data.
- base::Optional<CompletionInfo> completion_info;
+ absl::optional<CompletionInfo> completion_info;
DownloadMetaData();
~DownloadMetaData();
diff --git a/chromium/components/download/public/background_service/download_params.cc b/chromium/components/download/public/background_service/download_params.cc
index 00a3ccbd9c8..b7c1e4093a6 100644
--- a/chromium/components/download/public/background_service/download_params.cc
+++ b/chromium/components/download/public/background_service/download_params.cc
@@ -26,9 +26,9 @@ RequestParams::RequestParams()
RequestParams::RequestParams(const RequestParams& other) = default;
DownloadParams::DownloadParams() : client(DownloadClient::INVALID) {}
-
-DownloadParams::DownloadParams(const DownloadParams& other) = default;
-
DownloadParams::~DownloadParams() = default;
+DownloadParams::DownloadParams(DownloadParams&& other) = default;
+DownloadParams& DownloadParams::operator=(DownloadParams&& other) = default;
+
} // namespace download
diff --git a/chromium/components/download/public/background_service/download_params.h b/chromium/components/download/public/background_service/download_params.h
index b16c150d8a5..bc9d1e504aa 100644
--- a/chromium/components/download/public/background_service/download_params.h
+++ b/chromium/components/download/public/background_service/download_params.h
@@ -143,12 +143,14 @@ struct DownloadParams {
};
using StartCallback =
- base::RepeatingCallback<void(const std::string&, StartResult)>;
+ base::OnceCallback<void(const std::string&, StartResult)>;
DownloadParams();
- DownloadParams(const DownloadParams& other);
~DownloadParams();
+ DownloadParams(DownloadParams&& other);
+ DownloadParams& operator=(DownloadParams&& other);
+
// The feature that is requesting this download.
DownloadClient client;
diff --git a/chromium/components/download/public/background_service/download_service.h b/chromium/components/download/public/background_service/download_service.h
index f8b1a729977..9feab88b499 100644
--- a/chromium/components/download/public/background_service/download_service.h
+++ b/chromium/components/download/public/background_service/download_service.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
@@ -77,7 +76,7 @@ class DownloadService : public KeyedService {
// Sends the download to the service. A callback to
// |DownloadParams::callback| will be triggered once the download has been
// persisted and saved in the service.
- virtual void StartDownload(const DownloadParams& download_params) = 0;
+ virtual void StartDownload(DownloadParams download_params) = 0;
// Allows any feature to pause or resume downloads at will. Paused downloads
// will not start or stop based on scheduling criteria. They will be
diff --git a/chromium/components/download/public/background_service/logger.h b/chromium/components/download/public/background_service/logger.h
index cc9aa3036b8..3156b357362 100644
--- a/chromium/components/download/public/background_service/logger.h
+++ b/chromium/components/download/public/background_service/logger.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_LOGGER_H_
#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_LOGGER_H_
-#include <memory>
-
#include "base/macros.h"
namespace base {
diff --git a/chromium/components/download/public/common/auto_resumption_handler.cc b/chromium/components/download/public/common/auto_resumption_handler.cc
index dbab3fd117a..003e9590d4a 100644
--- a/chromium/components/download/public/common/auto_resumption_handler.cc
+++ b/chromium/components/download/public/common/auto_resumption_handler.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/files/file_path.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
diff --git a/chromium/components/download/public/common/auto_resumption_handler_unittest.cc b/chromium/components/download/public/common/auto_resumption_handler_unittest.cc
index d7fa404ee55..b5e6a5b656d 100644
--- a/chromium/components/download/public/common/auto_resumption_handler_unittest.cc
+++ b/chromium/components/download/public/common/auto_resumption_handler_unittest.cc
@@ -10,7 +10,6 @@
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/guid.h"
-#include "base/optional.h"
#include "base/test/simple_test_clock.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -21,6 +20,7 @@
#include "services/network/test/test_network_connection_tracker.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using TaskParams = download::TaskManager::TaskParams;
using network::mojom::ConnectionType;
@@ -108,7 +108,7 @@ class AutoResumptionHandlerTest : public testing::Test {
: download::DOWNLOAD_INTERRUPT_REASON_NONE;
ON_CALL(*download, GetLastReason()).WillByDefault(Return(last_reason));
ON_CALL(*download, GetDownloadSchedule())
- .WillByDefault(ReturnRefOfCopy(base::Optional<DownloadSchedule>()));
+ .WillByDefault(ReturnRefOfCopy(absl::optional<DownloadSchedule>()));
// Make sure the item won't be expired and ignored.
ON_CALL(*download, GetStartTime())
@@ -122,7 +122,7 @@ class AutoResumptionHandlerTest : public testing::Test {
void SetDownloadSchedule(MockDownloadItem* download,
DownloadSchedule download_schedule) {
- base::Optional<DownloadSchedule> copy = download_schedule;
+ absl::optional<DownloadSchedule> copy = download_schedule;
ON_CALL(*download, GetDownloadSchedule())
.WillByDefault(ReturnRefOfCopy(copy));
}
@@ -299,7 +299,7 @@ TEST_F(AutoResumptionHandlerTest, ExpiredDownloadNotAutoResumed) {
auto item1 = std::make_unique<NiceMock<MockDownloadItem>>();
SetDownloadState(item1.get(), DownloadItem::INTERRUPTED, false, false);
SetDownloadSchedule(item1.get(),
- DownloadSchedule(true /*only_on_wifi*/, base::nullopt));
+ DownloadSchedule(true /*only_on_wifi*/, absl::nullopt));
ON_CALL(*item1.get(), GetStartTime())
.WillByDefault(Return(expired_start_time));
@@ -367,7 +367,7 @@ TEST_F(AutoResumptionHandlerTest, DownloadLaterMeteredAutoResumed) {
SetDownloadState(item.get(), DownloadItem::INTERRUPTED, false,
true /*allow_metered*/);
SetDownloadSchedule(item.get(),
- DownloadSchedule(true /*only_on_wifi*/, base::nullopt));
+ DownloadSchedule(true /*only_on_wifi*/, absl::nullopt));
auto_resumption_handler_->OnDownloadStarted(item.get());
task_runner_->FastForwardUntilNoTasksRemain();
diff --git a/chromium/components/download/public/common/base_file.h b/chromium/components/download/public/common/base_file.h
index 058d640e941..96905e88d97 100644
--- a/chromium/components/download/public/common/base_file.h
+++ b/chromium/components/download/public/common/base_file.h
@@ -19,7 +19,6 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -30,6 +29,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/net_errors.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace download {
diff --git a/chromium/components/download/public/common/download_content.h b/chromium/components/download/public/common/download_content.h
index c88ffb0e690..e6d33a10959 100644
--- a/chromium/components/download/public/common/download_content.h
+++ b/chromium/components/download/public/common/download_content.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_DOWNLOAD_DOWNLOAD_CONTENT_H_
-#define COMPONENTS_DOWNLOAD_DOWNLOAD_CONTENT_H_
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_CONTENT_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_CONTENT_H_
// The type of download based on mimetype.
// This is used by UMA and UKM metrics.
@@ -35,4 +35,4 @@ enum class DownloadContent {
} // namespace download
-#endif // COMPONENTS_DOWNLOAD_DOWNLOAD_CONTENT_H_
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_CONTENT_H_
diff --git a/chromium/components/download/public/common/download_create_info.h b/chromium/components/download/public/common/download_create_info.h
index b8c6e21b1b7..37dc268c0ec 100644
--- a/chromium/components/download/public/common/download_create_info.h
+++ b/chromium/components/download/public/common/download_create_info.h
@@ -10,11 +10,8 @@
#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"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_interrupt_reasons.h"
@@ -25,6 +22,7 @@
#include "net/http/http_response_info.h"
#include "net/url_request/referrer_policy.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -78,7 +76,7 @@ struct COMPONENTS_DOWNLOAD_EXPORT DownloadCreateInfo {
GURL tab_referrer_url;
// The origin of the requester that originally initiated the download.
- base::Optional<url::Origin> request_initiator;
+ absl::optional<url::Origin> request_initiator;
// The time when the download started.
base::Time start_time;
@@ -99,7 +97,7 @@ struct COMPONENTS_DOWNLOAD_EXPORT DownloadCreateInfo {
// short-lived and is not shown in the UI.
bool transient;
- base::Optional<ui::PageTransition> transition_type;
+ absl::optional<ui::PageTransition> transition_type;
// The HTTP response headers. This contains a nullptr when the response has
// not yet been received. Only for consuming headers.
diff --git a/chromium/components/download/public/common/download_danger_type.h b/chromium/components/download/public/common/download_danger_type.h
index 237e87467f8..348e9bf1158 100644
--- a/chromium/components/download/public/common/download_danger_type.h
+++ b/chromium/components/download/public/common/download_danger_type.h
@@ -81,6 +81,10 @@ enum DownloadDangerType {
// policy for details.
DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE = 18,
+ // SafeBrowsing download service has classified this file as being associated
+ // with account compromise through stealing cookies.
+ DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE = 19,
+
// Memory space for histograms is determined by the max.
// ALWAYS ADD NEW VALUES BEFORE THIS ONE.
DOWNLOAD_DANGER_TYPE_MAX
diff --git a/chromium/components/download/public/common/download_features.cc b/chromium/components/download/public/common/download_features.cc
index 5734eee5904..409d18d81a0 100644
--- a/chromium/components/download/public/common/download_features.cc
+++ b/chromium/components/download/public/common/download_features.cc
@@ -68,7 +68,7 @@ const base::Feature kDeleteExpiredDownloads{"DeleteExpiredDownloads",
base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kDeleteOverwrittenDownloads{
- "DeleteOverwrittenDownloads", base::FEATURE_DISABLED_BY_DEFAULT};
+ "DeleteOverwrittenDownloads", base::FEATURE_ENABLED_BY_DEFAULT};
} // namespace features
diff --git a/chromium/components/download/public/common/download_item.h b/chromium/components/download/public/common/download_item.h
index b561de01fba..f2f3a4337bf 100644
--- a/chromium/components/download/public/common/download_item.h
+++ b/chromium/components/download/public/common/download_item.h
@@ -24,15 +24,14 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/supports_user_data.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_schedule.h"
#include "components/download/public/common/download_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/page_transition_types.h"
#include "url/origin.h"
@@ -306,7 +305,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItem : public base::SupportsUserData {
virtual const GURL& GetTabReferrerUrl() const = 0;
// Origin of the original originator of this download, before redirects, etc.
- virtual const base::Optional<url::Origin>& GetRequestInitiator() const = 0;
+ virtual const absl::optional<url::Origin>& GetRequestInitiator() const = 0;
// For downloads initiated via <a download>, this is the suggested download
// filename from the download attribute.
@@ -520,7 +519,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItem : public base::SupportsUserData {
virtual DownloadCreationType GetDownloadCreationType() const = 0;
// Gets the download schedule to start the time at particular time.
- virtual const base::Optional<DownloadSchedule>& GetDownloadSchedule()
+ virtual const absl::optional<DownloadSchedule>& GetDownloadSchedule()
const = 0;
// External state transitions/setters ----------------------------------------
@@ -543,7 +542,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItem : public base::SupportsUserData {
// Called when the user changes the download schedule options.
virtual void OnDownloadScheduleChanged(
- base::Optional<DownloadSchedule> schedule) = 0;
+ absl::optional<DownloadSchedule> schedule) = 0;
// Mark the download to be auto-opened when completed.
virtual void SetOpenWhenComplete(bool open) = 0;
diff --git a/chromium/components/download/public/common/download_item_factory.h b/chromium/components/download/public/common/download_item_factory.h
index f89fb11f0fc..bd00f9e6660 100644
--- a/chromium/components/download/public/common/download_item_factory.h
+++ b/chromium/components/download/public/common/download_item_factory.h
@@ -15,10 +15,10 @@
#include <string>
#include <vector>
-#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
class GURL;
@@ -48,7 +48,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemFactory {
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_refererr_url,
- const base::Optional<url::Origin>& initiator_origin,
+ const absl::optional<url::Origin>& initiator_origin,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
diff --git a/chromium/components/download/public/common/download_item_impl.h b/chromium/components/download/public/common/download_item_impl.h
index 2868b25bd9c..0c56a25f4cd 100644
--- a/chromium/components/download/public/common/download_item_impl.h
+++ b/chromium/components/download/public/common/download_item_impl.h
@@ -16,7 +16,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_checker_impl.h"
#include "base/time/time.h"
@@ -31,6 +30,7 @@
#include "components/download/public/common/url_loader_factory_provider.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -54,7 +54,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
- const base::Optional<url::Origin>& request_initiator,
+ const absl::optional<url::Origin>& request_initiator,
const std::string& suggested_filename,
const base::FilePath& forced_file_path,
ui::PageTransition transition_type,
@@ -82,7 +82,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
GURL tab_referrer_url;
// The origin of the requester that originally initiated the download.
- base::Optional<url::Origin> request_initiator;
+ absl::optional<url::Origin> request_initiator;
// Filename suggestion from DownloadSaveInfo. It could, among others, be the
// suggested filename in 'download' attribute of an anchor. Details:
@@ -176,7 +176,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
- const base::Optional<url::Origin>& request_initiator,
+ const absl::optional<url::Origin>& request_initiator,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
@@ -196,7 +196,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
base::Time last_access_time,
bool transient,
const std::vector<DownloadItem::ReceivedSlice>& received_slices,
- base::Optional<DownloadSchedule> download_schedule,
+ absl::optional<DownloadSchedule> download_schedule,
std::unique_ptr<DownloadEntry> download_entry);
// Constructing for a regular download.
@@ -250,7 +250,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
const GURL& GetSiteUrl() const override;
const GURL& GetTabUrl() const override;
const GURL& GetTabReferrerUrl() const override;
- const base::Optional<url::Origin>& GetRequestInitiator() const override;
+ const absl::optional<url::Origin>& GetRequestInitiator() const override;
std::string GetSuggestedFilename() const override;
const scoped_refptr<const net::HttpResponseHeaders>& GetResponseHeaders()
const override;
@@ -300,12 +300,12 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
bool IsTransient() const override;
bool IsParallelDownload() const override;
DownloadCreationType GetDownloadCreationType() const override;
- const base::Optional<DownloadSchedule>& GetDownloadSchedule() const override;
+ const absl::optional<DownloadSchedule>& GetDownloadSchedule() const override;
void OnContentCheckCompleted(DownloadDangerType danger_type,
DownloadInterruptReason reason) override;
void OnAsyncScanningCompleted(DownloadDangerType danger_type) override;
void OnDownloadScheduleChanged(
- base::Optional<DownloadSchedule> schedule) override;
+ absl::optional<DownloadSchedule> schedule) override;
void SetOpenWhenComplete(bool open) override;
void SetOpened(bool opened) override;
void SetLastAccessTime(base::Time last_access_time) override;
@@ -567,7 +567,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
DownloadDangerType danger_type,
MixedContentStatus mixed_content_status,
const base::FilePath& intermediate_path,
- base::Optional<DownloadSchedule> download_schedule,
+ absl::optional<DownloadSchedule> download_schedule,
DownloadInterruptReason interrupt_reason);
void OnDownloadRenamedToIntermediateName(DownloadInterruptReason reason,
@@ -583,9 +583,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
// condition and user scheduled start time defined in |download_schedule_|.
bool ShouldDownloadLater() const;
- // Swap the |download_schedule_| with new data, may pass in base::nullopt to
+ // Swap the |download_schedule_| with new data, may pass in absl::nullopt to
// remove the schedule.
- void SwapDownloadSchedule(base::Optional<DownloadSchedule> download_schedule);
+ void SwapDownloadSchedule(absl::optional<DownloadSchedule> download_schedule);
// If all pre-requisites have been met, complete download processing, i.e. do
// internal cleanup, file rename, and potentially auto-open. (Dangerous
@@ -861,7 +861,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
MixedContentStatus mixed_content_status_ = MixedContentStatus::UNKNOWN;
// Defines when to start the download. Used by download later feature.
- base::Optional<DownloadSchedule> download_schedule_;
+ absl::optional<DownloadSchedule> download_schedule_;
// A handler for renaming and helping with display the item.
std::unique_ptr<DownloadItemRenameHandler> rename_handler_;
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 538dfac4b83..bbbc5d12797 100644
--- a/chromium/components/download/public/common/download_item_impl_delegate.h
+++ b/chromium/components/download/public/common/download_item_impl_delegate.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/macros.h"
-#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_item_rename_handler.h"
@@ -22,6 +21,7 @@
#include "components/services/quarantine/public/mojom/quarantine.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
class DownloadItemImpl;
@@ -49,7 +49,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImplDelegate {
DownloadDangerType danger_type,
DownloadItem::MixedContentStatus mixed_content_status,
const base::FilePath& intermediate_path,
- base::Optional<DownloadSchedule> download_schedule,
+ absl::optional<DownloadSchedule> download_schedule,
DownloadInterruptReason interrupt_reason)>;
// Request determination of the download target from the delegate.
virtual void DetermineDownloadTarget(DownloadItemImpl* download,
diff --git a/chromium/components/download/public/common/download_job.h b/chromium/components/download/public/common/download_job.h
index 42d56093eb8..f5cc391ffc3 100644
--- a/chromium/components/download/public/common/download_job.h
+++ b/chromium/components/download/public/common/download_job.h
@@ -7,7 +7,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
#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"
diff --git a/chromium/components/download/public/common/download_response_handler.h b/chromium/components/download/public/common/download_response_handler.h
index e7081025df2..bb2eb51b460 100644
--- a/chromium/components/download/public/common/download_response_handler.h
+++ b/chromium/components/download/public/common/download_response_handler.h
@@ -8,7 +8,6 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_source.h"
@@ -19,6 +18,7 @@
#include "net/cert/cert_status_flags.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
namespace download {
@@ -99,7 +99,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler
DownloadSource download_source_;
net::CertStatus cert_status_;
bool has_strong_validators_;
- base::Optional<url::Origin> request_initiator_;
+ absl::optional<url::Origin> request_initiator_;
bool is_partial_request_;
bool completed_;
diff --git a/chromium/components/download/public/common/download_schedule.cc b/chromium/components/download/public/common/download_schedule.cc
index eb53fe70024..25c6fd9bd2d 100644
--- a/chromium/components/download/public/common/download_schedule.cc
+++ b/chromium/components/download/public/common/download_schedule.cc
@@ -9,7 +9,7 @@
namespace download {
DownloadSchedule::DownloadSchedule(bool only_on_wifi,
- base::Optional<base::Time> start_time)
+ absl::optional<base::Time> start_time)
: only_on_wifi_(only_on_wifi), start_time_(start_time) {}
DownloadSchedule::DownloadSchedule(const DownloadSchedule&) = default;
diff --git a/chromium/components/download/public/common/download_schedule.h b/chromium/components/download/public/common/download_schedule.h
index 205fbe7a4f8..9055faa9a1c 100644
--- a/chromium/components/download/public/common/download_schedule.h
+++ b/chromium/components/download/public/common/download_schedule.h
@@ -5,9 +5,9 @@
#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_SCHEDULE_H_
#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_SCHEDULE_H_
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/download/public/common/download_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
@@ -15,7 +15,7 @@ namespace download {
// feature.
class COMPONENTS_DOWNLOAD_EXPORT DownloadSchedule {
public:
- DownloadSchedule(bool only_on_wifi, base::Optional<base::Time> start_time);
+ DownloadSchedule(bool only_on_wifi, absl::optional<base::Time> start_time);
DownloadSchedule(const DownloadSchedule&);
~DownloadSchedule();
@@ -23,14 +23,14 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadSchedule {
bool only_on_wifi() const { return only_on_wifi_; }
- const base::Optional<base::Time>& start_time() const { return start_time_; }
+ const absl::optional<base::Time>& start_time() const { return start_time_; }
private:
// Whether to download only on WIFI. If true, |start_time_| will be ignored.
bool only_on_wifi_;
// Time to start the download. Will be ignored if |only_on_wifi_| is true.
- base::Optional<base::Time> start_time_;
+ absl::optional<base::Time> start_time_;
};
} // namespace download
diff --git a/chromium/components/download/public/common/download_schedule_unittest.cc b/chromium/components/download/public/common/download_schedule_unittest.cc
index 4de42429ccb..5c97ca1c10b 100644
--- a/chromium/components/download/public/common/download_schedule_unittest.cc
+++ b/chromium/components/download/public/common/download_schedule_unittest.cc
@@ -4,22 +4,22 @@
#include "components/download/public/common/download_schedule.h"
-#include "base/optional.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace download {
namespace {
TEST(DownloadScheduleTest, CtorAndCopy) {
- DownloadSchedule download_schedule(false, base::nullopt);
+ DownloadSchedule download_schedule(false, absl::nullopt);
EXPECT_FALSE(download_schedule.only_on_wifi());
- EXPECT_EQ(download_schedule.start_time(), base::nullopt);
+ EXPECT_EQ(download_schedule.start_time(), absl::nullopt);
- download_schedule = DownloadSchedule(true, base::nullopt);
+ download_schedule = DownloadSchedule(true, absl::nullopt);
EXPECT_TRUE(download_schedule.only_on_wifi());
- EXPECT_EQ(download_schedule.start_time(), base::nullopt);
+ EXPECT_EQ(download_schedule.start_time(), absl::nullopt);
- auto time = base::make_optional(
+ auto time = absl::make_optional(
base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromDays(1)));
download_schedule = DownloadSchedule(false, time);
EXPECT_FALSE(download_schedule.only_on_wifi());
diff --git a/chromium/components/download/public/common/download_ukm_helper.h b/chromium/components/download/public/common/download_ukm_helper.h
index 7df8e84bac0..362f402de6b 100644
--- a/chromium/components/download/public/common/download_ukm_helper.h
+++ b/chromium/components/download/public/common/download_ukm_helper.h
@@ -36,7 +36,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUkmHelper {
// Record when the download is interrupted.
static void RecordDownloadInterrupted(int download_id,
- base::Optional<int> change_in_file_size,
+ absl::optional<int> change_in_file_size,
DownloadInterruptReason reason,
int resulting_file_size,
const base::TimeDelta& time_since_start,
diff --git a/chromium/components/download/public/common/download_url_parameters.h b/chromium/components/download/public/common/download_url_parameters.h
index 0be34e0e33f..903a532bc01 100644
--- a/chromium/components/download/public/common/download_url_parameters.h
+++ b/chromium/components/download/public/common/download_url_parameters.h
@@ -14,7 +14,6 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_save_info.h"
#include "components/download/public/common/download_source.h"
@@ -24,6 +23,7 @@
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/mojom/fetch_api.mojom-shared.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -111,7 +111,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
// The origin of the context which initiated the request. See
// net::URLRequest::initiator().
- void set_initiator(const base::Optional<url::Origin>& initiator) {
+ void set_initiator(const absl::optional<url::Origin>& initiator) {
initiator_ = initiator;
}
@@ -272,7 +272,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
const GURL& referrer() const { return referrer_; }
net::ReferrerPolicy referrer_policy() const { return referrer_policy_; }
const std::string& referrer_encoding() const { return referrer_encoding_; }
- const base::Optional<url::Origin>& initiator() const { return initiator_; }
+ const absl::optional<url::Origin>& initiator() const { return initiator_; }
const std::string& request_origin() const { return request_origin_; }
BlobStorageContextGetter get_blob_storage_context_getter() {
return std::move(blob_storage_context_getter_);
@@ -305,7 +305,7 @@ 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_; }
- const base::Optional<net::IsolationInfo>& isolation_info() const {
+ const absl::optional<net::IsolationInfo>& isolation_info() const {
return isolation_info_;
}
@@ -337,7 +337,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
bool prefer_cache_;
GURL referrer_;
net::ReferrerPolicy referrer_policy_;
- base::Optional<url::Origin> initiator_;
+ absl::optional<url::Origin> initiator_;
std::string referrer_encoding_;
int render_process_host_id_;
int render_frame_host_routing_id_;
@@ -353,7 +353,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
DownloadSource download_source_;
UploadProgressCallback upload_callback_;
bool require_safety_checks_;
- base::Optional<net::IsolationInfo> isolation_info_;
+ absl::optional<net::IsolationInfo> isolation_info_;
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 97373c2454e..66177cb7bb3 100644
--- a/chromium/components/download/public/common/download_utils.h
+++ b/chromium/components/download/public/common/download_utils.h
@@ -78,7 +78,7 @@ CreateDownloadDBEntryFromItem(const DownloadItemImpl& item);
// Helper function to convert DownloadDBEntry to DownloadEntry.
// TODO(qinmin): remove this function after DownloadEntry is deprecated.
COMPONENTS_DOWNLOAD_EXPORT std::unique_ptr<DownloadEntry>
-CreateDownloadEntryFromDownloadDBEntry(base::Optional<DownloadDBEntry> entry);
+CreateDownloadEntryFromDownloadDBEntry(absl::optional<DownloadDBEntry> entry);
COMPONENTS_DOWNLOAD_EXPORT uint64_t GetUniqueDownloadId();
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 f222e9abaf0..b9b1248387d 100644
--- a/chromium/components/download/public/common/in_progress_download_manager.h
+++ b/chromium/components/download/public/common/in_progress_download_manager.h
@@ -13,7 +13,6 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.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"
@@ -25,6 +24,7 @@
#include "mojo/public/cpp/system/data_pipe.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace network {
diff --git a/chromium/components/download/public/common/mock_download_item.h b/chromium/components/download/public/common/mock_download_item.h
index 2ca3726cbeb..13234b09f6a 100644
--- a/chromium/components/download/public/common/mock_download_item.h
+++ b/chromium/components/download/public/common/mock_download_item.h
@@ -11,14 +11,15 @@
#include <vector>
#include "base/callback.h"
+#include "base/files/file_path.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_source.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -70,7 +71,7 @@ class MockDownloadItem : public DownloadItem {
MOCK_CONST_METHOD0(GetSiteUrl, const GURL&());
MOCK_CONST_METHOD0(GetTabUrl, const GURL&());
MOCK_CONST_METHOD0(GetTabReferrerUrl, const GURL&());
- MOCK_CONST_METHOD0(GetRequestInitiator, const base::Optional<url::Origin>&());
+ MOCK_CONST_METHOD0(GetRequestInitiator, const absl::optional<url::Origin>&());
MOCK_CONST_METHOD0(GetSuggestedFilename, std::string());
MOCK_CONST_METHOD0(GetContentDisposition, std::string());
MOCK_CONST_METHOD0(GetResponseHeaders,
@@ -126,7 +127,7 @@ class MockDownloadItem : public DownloadItem {
MOCK_CONST_METHOD0(IsParallelDownload, bool());
MOCK_CONST_METHOD0(GetDownloadCreationType, DownloadCreationType());
MOCK_CONST_METHOD0(GetDownloadSchedule,
- const base::Optional<DownloadSchedule>&());
+ const absl::optional<DownloadSchedule>&());
MOCK_METHOD2(OnContentCheckCompleted,
void(DownloadDangerType, DownloadInterruptReason));
MOCK_METHOD1(SetOpenWhenComplete, void(bool));
@@ -140,7 +141,7 @@ class MockDownloadItem : public DownloadItem {
MOCK_METHOD1(OnAsyncScanningCompleted, void(DownloadDangerType));
MOCK_METHOD(void,
OnDownloadScheduleChanged,
- (base::Optional<DownloadSchedule>),
+ (absl::optional<DownloadSchedule>),
(override));
private:
diff --git a/chromium/components/download/public/common/mock_download_item_impl.cc b/chromium/components/download/public/common/mock_download_item_impl.cc
index d9cbdea889c..d5d14724e53 100644
--- a/chromium/components/download/public/common/mock_download_item_impl.cc
+++ b/chromium/components/download/public/common/mock_download_item_impl.cc
@@ -37,7 +37,7 @@ MockDownloadItemImpl::MockDownloadItemImpl(DownloadItemImplDelegate* delegate)
base::Time(),
true,
DownloadItem::ReceivedSlices(),
- base::nullopt /*download_schedule*/,
+ absl::nullopt /*download_schedule*/,
nullptr /* download_entry */) {}
MockDownloadItemImpl::~MockDownloadItemImpl() = default;
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 e2ea66f139f..c2f72312b2c 100644
--- a/chromium/components/download/public/common/mock_download_item_impl.h
+++ b/chromium/components/download/public/common/mock_download_item_impl.h
@@ -10,12 +10,12 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#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_schedule.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
namespace download {
@@ -34,7 +34,7 @@ class MockDownloadItemImpl : public DownloadItemImpl {
DownloadDangerType,
MixedContentStatus,
const base::FilePath&,
- base::Optional<DownloadSchedule>,
+ absl::optional<DownloadSchedule>,
DownloadInterruptReason));
MOCK_METHOD1(AddObserver, void(DownloadItem::Observer*));
MOCK_METHOD1(RemoveObserver, void(DownloadItem::Observer*));
@@ -84,7 +84,7 @@ class MockDownloadItemImpl : public DownloadItemImpl {
MOCK_CONST_METHOD0(GetReferrerUrl, const GURL&());
MOCK_CONST_METHOD0(GetTabUrl, const GURL&());
MOCK_CONST_METHOD0(GetTabReferrerUrl, const GURL&());
- MOCK_CONST_METHOD0(GetRequestInitiator, const base::Optional<url::Origin>&());
+ MOCK_CONST_METHOD0(GetRequestInitiator, const absl::optional<url::Origin>&());
MOCK_CONST_METHOD0(GetSuggestedFilename, std::string());
MOCK_CONST_METHOD0(GetContentDisposition, std::string());
MOCK_CONST_METHOD0(GetMimeType, std::string());
diff --git a/chromium/components/embedder_support/BUILD.gn b/chromium/components/embedder_support/BUILD.gn
index c78282a4e4c..bbb2746c319 100644
--- a/chromium/components/embedder_support/BUILD.gn
+++ b/chromium/components/embedder_support/BUILD.gn
@@ -23,7 +23,8 @@ static_library("browser_util") {
deps = [
":embedder_support",
"//build:branding_buildflags",
- "//components/content_settings/core/browser:browser",
+ "//components/content_settings/browser",
+ "//components/content_settings/core/browser",
"//components/version_info",
"//content/public/browser",
]
diff --git a/chromium/components/embedder_support/DEPS b/chromium/components/embedder_support/DEPS
index ef2c078eaa2..18c8d9cc482 100644
--- a/chromium/components/embedder_support/DEPS
+++ b/chromium/components/embedder_support/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/content_settings/browser",
"+components/content_settings/core/browser",
"+components/content_settings/core/common",
"+components/version_info",
diff --git a/chromium/components/embedder_support/README b/chromium/components/embedder_support/README
new file mode 100644
index 00000000000..86e161d86bb
--- /dev/null
+++ b/chromium/components/embedder_support/README
@@ -0,0 +1,5 @@
+The embedder_support component is for small shims and minimal glue layer on top
+of the Content API that do not clearly justify a component of their own. Before
+adding additional features to this component, consider whether the feature
+justifies a new component instead (e.g. more than 5 files would be a good
+indicator that a new component could be used instead)
diff --git a/chromium/components/embedder_support/android/contextmenu/context_menu_builder.cc b/chromium/components/embedder_support/android/contextmenu/context_menu_builder.cc
index ae7cb0c5fed..40d7926562d 100644
--- a/chromium/components/embedder_support/android/contextmenu/context_menu_builder.cc
+++ b/chromium/components/embedder_support/android/contextmenu/context_menu_builder.cc
@@ -38,7 +38,7 @@ base::android::ScopedJavaGlobalRef<jobject> BuildJavaContextMenuParams(
ConvertUTF16ToJavaString(env, title_text),
url::GURLAndroid::FromNativeGURL(env, sanitizedReferrer),
static_cast<int>(params.referrer_policy), can_save, params.x,
- params.y, params.source_type));
+ params.y, params.source_type, params.opened_from_highlight));
}
content::ContextMenuParams* ContextMenuParamsFromJavaObject(
diff --git a/chromium/components/embedder_support/android/delegate/color_chooser_android.h b/chromium/components/embedder_support/android/delegate/color_chooser_android.h
index 71ae29e46a4..05da5e36e6a 100644
--- a/chromium/components/embedder_support/android/delegate/color_chooser_android.h
+++ b/chromium/components/embedder_support/android/delegate/color_chooser_android.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_EMBEDDER_SUPPORT_ANDROID_DELEGATE_COLOR_CHOOSER_ANDROID_H_
#define COMPONENTS_EMBEDDER_SUPPORT_ANDROID_DELEGATE_COLOR_CHOOSER_ANDROID_H_
-#include <string>
#include <vector>
#include "base/android/jni_android.h"
diff --git a/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.cc b/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.cc
index e878f49dd6c..821efb221cd 100644
--- a/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.cc
+++ b/chromium/components/embedder_support/android/delegate/web_contents_delegate_android.cc
@@ -405,7 +405,11 @@ bool WebContentsDelegateAndroid::ShouldAnimateBrowserControlsHeightChanges() {
bool WebContentsDelegateAndroid::DoBrowserControlsShrinkRendererSize(
content::WebContents* contents) {
- return contents->GetNativeView()->ControlsResizeView();
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
+ if (obj.is_null())
+ return false;
+ return Java_WebContentsDelegateAndroid_controlsResizeView(env, obj);
}
blink::mojom::DisplayMode WebContentsDelegateAndroid::GetDisplayMode(
diff --git a/chromium/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java b/chromium/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
index 37188b78e75..8337f9da676 100644
--- a/chromium/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
+++ b/chromium/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
@@ -141,22 +141,6 @@ public class UrlUtilitiesUnitTest {
@Test
@SmallTest
- public void testIsValidForIntentFallbackUrl() {
- Assert.assertTrue(UrlUtilities.isValidForIntentFallbackNavigation(
- "https://user:pass@awesome.com:9000/bad-scheme:#fake:"));
- Assert.assertTrue(
- UrlUtilities.isValidForIntentFallbackNavigation("http://awesome.example.com/"));
- Assert.assertFalse(UrlUtilities.isValidForIntentFallbackNavigation("inline:skates.co.uk"));
- Assert.assertFalse(UrlUtilities.isValidForIntentFallbackNavigation("javascript:alert(1)"));
- Assert.assertFalse(
- UrlUtilities.isValidForIntentFallbackNavigation("file://hostname/path/to/file"));
- Assert.assertFalse(UrlUtilities.isValidForIntentFallbackNavigation("data:data"));
- Assert.assertFalse(UrlUtilities.isValidForIntentFallbackNavigation("about:awesome"));
- Assert.assertFalse(UrlUtilities.isValidForIntentFallbackNavigation(""));
- }
-
- @Test
- @SmallTest
public void testIsUrlWithinScope() {
String scope = "http://www.example.com/sub";
Assert.assertTrue(UrlUtilities.isUrlWithinScope(scope, scope));
@@ -253,4 +237,17 @@ public class UrlUtilitiesUnitTest {
Assert.assertEquals("foo+bar", UrlUtilities.escapeQueryParamValue("foo bar", true));
Assert.assertEquals("foo%2B%2B", UrlUtilities.escapeQueryParamValue("foo++", true));
}
+
+ // Note that this just tests the plumbing of the Java code to the native
+ // net::GetValueForKeyInQuery function, which is tested much more thoroughly there.
+ @Test
+ @SmallTest
+ public void testGetValueForKeyInQuery() {
+ GURL url = new GURL("https://www.example.com/?q1=foo&q2=bar&q11=#q2=notbar&q3=baz");
+ Assert.assertEquals("foo", UrlUtilities.getValueForKeyInQuery(url, "q1"));
+ Assert.assertEquals("bar", UrlUtilities.getValueForKeyInQuery(url, "q2"));
+ Assert.assertEquals("", UrlUtilities.getValueForKeyInQuery(url, "q11"));
+ Assert.assertNull(UrlUtilities.getValueForKeyInQuery(url, "1"));
+ Assert.assertNull(UrlUtilities.getValueForKeyInQuery(url, "q3"));
+ }
}
diff --git a/chromium/components/embedder_support/android/util/android_stream_reader_url_loader.cc b/chromium/components/embedder_support/android/util/android_stream_reader_url_loader.cc
index 8330d611c27..475dc030cfb 100644
--- a/chromium/components/embedder_support/android/util/android_stream_reader_url_loader.cc
+++ b/chromium/components/embedder_support/android/util/android_stream_reader_url_loader.cc
@@ -105,7 +105,7 @@ AndroidStreamReaderURLLoader::AndroidStreamReaderURLLoader(
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
std::unique_ptr<ResponseDelegate> response_delegate,
- base::Optional<SecurityOptions> security_options)
+ absl::optional<SecurityOptions> security_options)
: resource_request_(resource_request),
response_head_(network::mojom::URLResponseHead::New()),
reject_cors_request_(false),
@@ -142,7 +142,7 @@ void AndroidStreamReaderURLLoader::FollowRedirect(
const std::vector<std::string>& removed_headers,
const net::HttpRequestHeaders& modified_headers,
const net::HttpRequestHeaders& modified_cors_exempt_headers,
- const base::Optional<GURL>& new_url) {}
+ const absl::optional<GURL>& new_url) {}
void AndroidStreamReaderURLLoader::SetPriority(net::RequestPriority priority,
int intra_priority_value) {}
void AndroidStreamReaderURLLoader::PauseReadingBodyFromNet() {}
diff --git a/chromium/components/embedder_support/android/util/android_stream_reader_url_loader.h b/chromium/components/embedder_support/android/util/android_stream_reader_url_loader.h
index ef02b4708af..b76f1e129f2 100644
--- a/chromium/components/embedder_support/android/util/android_stream_reader_url_loader.h
+++ b/chromium/components/embedder_support/android/util/android_stream_reader_url_loader.h
@@ -9,7 +9,6 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -18,6 +17,7 @@
#include "services/network/public/cpp/net_adapters.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace embedder_support {
class InputStream;
@@ -88,7 +88,7 @@ class AndroidStreamReaderURLLoader : public network::mojom::URLLoader {
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
std::unique_ptr<ResponseDelegate> response_delegate,
- base::Optional<SecurityOptions> security_options);
+ absl::optional<SecurityOptions> security_options);
~AndroidStreamReaderURLLoader() override;
void Start();
@@ -98,7 +98,7 @@ class AndroidStreamReaderURLLoader : public network::mojom::URLLoader {
const std::vector<std::string>& removed_headers,
const net::HttpRequestHeaders& modified_headers,
const net::HttpRequestHeaders& modified_cors_exempt_headers,
- const base::Optional<GURL>& new_url) override;
+ const absl::optional<GURL>& new_url) override;
void SetPriority(net::RequestPriority priority,
int intra_priority_value) override;
void PauseReadingBodyFromNet() override;
diff --git a/chromium/components/embedder_support/android/util/android_stream_reader_url_loader_unittest.cc b/chromium/components/embedder_support/android/util/android_stream_reader_url_loader_unittest.cc
index 637bd8bc4e4..39e7ce58c36 100644
--- a/chromium/components/embedder_support/android/util/android_stream_reader_url_loader_unittest.cc
+++ b/chromium/components/embedder_support/android/util/android_stream_reader_url_loader_unittest.cc
@@ -174,7 +174,7 @@ class AndroidStreamReaderURLLoaderTest : public ::testing::Test {
request, client->CreateRemote(),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
std::make_unique<TestResponseDelegate>(std::move(input_stream)),
- base::nullopt);
+ absl::nullopt);
}
// helper method for creating loaders given a stream and MIME type
@@ -188,7 +188,7 @@ class AndroidStreamReaderURLLoaderTest : public ::testing::Test {
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
std::make_unique<TestResponseDelegate>(std::move(input_stream),
custom_mime_type),
- base::nullopt);
+ absl::nullopt);
}
// helper method for creating loaders given a stream and response header
@@ -206,7 +206,7 @@ class AndroidStreamReaderURLLoaderTest : public ::testing::Test {
std::make_unique<TestResponseDelegate>(
std::move(input_stream), custom_status, custom_header_name,
custom_header_value),
- base::nullopt);
+ absl::nullopt);
}
// Extracts the body data that is present in the consumer pipe
diff --git a/chromium/components/embedder_support/android/util/url_utilities.cc b/chromium/components/embedder_support/android/util/url_utilities.cc
index 3415b78565b..8f2ac074897 100644
--- a/chromium/components/embedder_support/android/util/url_utilities.cc
+++ b/chromium/components/embedder_support/android/util/url_utilities.cc
@@ -11,6 +11,7 @@
#include "components/google/core/common/google_util.h"
#include "net/base/escape.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/base/url_util.h"
#include "url/android/gurl_android.h"
#include "url/gurl.h"
@@ -23,32 +24,10 @@ namespace embedder_support {
namespace {
-static const char* const g_supported_schemes[] = {
- "about", "data", "file", "http", "https", "inline", "javascript", nullptr};
-
-static const char* const g_downloadable_schemes[] = {
- "data", "blob", "file", "filesystem", "http", "https", nullptr};
-
-static const char* const g_fallback_valid_schemes[] = {"http", "https",
- nullptr};
-
GURL JNI_UrlUtilities_ConvertJavaStringToGURL(JNIEnv* env, jstring url) {
return url ? GURL(ConvertJavaStringToUTF8(env, url)) : GURL();
}
-bool CheckSchemeBelongsToList(JNIEnv* env,
- const GURL& gurl,
- const char* const* scheme_list) {
- if (gurl.is_valid()) {
- for (size_t i = 0; scheme_list[i]; i++) {
- if (gurl.scheme() == scheme_list[i]) {
- return true;
- }
- }
- }
- return false;
-}
-
net::registry_controlled_domains::PrivateRegistryFilter GetRegistryFilter(
jboolean include_private) {
return include_private
@@ -189,27 +168,6 @@ static jboolean JNI_UrlUtilities_UrlsFragmentsDiffer(
return gurl.ref() != gurl2.ref();
}
-static jboolean JNI_UrlUtilities_IsAcceptedScheme(
- JNIEnv* env,
- const JavaParamRef<jstring>& url) {
- GURL gurl = JNI_UrlUtilities_ConvertJavaStringToGURL(env, url);
- return CheckSchemeBelongsToList(env, gurl, g_supported_schemes);
-}
-
-static jboolean JNI_UrlUtilities_IsValidForIntentFallbackNavigation(
- JNIEnv* env,
- const JavaParamRef<jstring>& url) {
- GURL gurl = JNI_UrlUtilities_ConvertJavaStringToGURL(env, url);
- return CheckSchemeBelongsToList(env, gurl, g_fallback_valid_schemes);
-}
-
-static jboolean JNI_UrlUtilities_IsDownloadable(
- JNIEnv* env,
- const JavaParamRef<jobject>& url) {
- return CheckSchemeBelongsToList(
- env, *url::GURLAndroid::ToNativeGURL(env, url), g_downloadable_schemes);
-}
-
static ScopedJavaLocalRef<jstring> JNI_UrlUtilities_EscapeQueryParamValue(
JNIEnv* env,
const JavaParamRef<jstring>& url,
@@ -219,4 +177,29 @@ static ScopedJavaLocalRef<jstring> JNI_UrlUtilities_EscapeQueryParamValue(
base::android::ConvertJavaStringToUTF8(url), use_plus));
}
+static ScopedJavaLocalRef<jstring> JNI_UrlUtilities_GetValueForKeyInQuery(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& j_url,
+ const JavaParamRef<jstring>& j_key) {
+ DCHECK(j_url);
+ DCHECK(j_key);
+ const std::string& key = ConvertJavaStringToUTF8(env, j_key);
+ std::string out;
+ if (!net::GetValueForKeyInQuery(*url::GURLAndroid::ToNativeGURL(env, j_url),
+ key, &out)) {
+ return ScopedJavaLocalRef<jstring>();
+ }
+ return base::android::ConvertUTF8ToJavaString(env, out);
+}
+
+ScopedJavaLocalRef<jobject> JNI_UrlUtilities_ClearPort(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& j_url) {
+ std::unique_ptr<GURL> gurl = url::GURLAndroid::ToNativeGURL(env, j_url);
+ GURL::Replacements remove_port;
+ remove_port.ClearPort();
+ return url::GURLAndroid::FromNativeGURL(env,
+ gurl->ReplaceComponents(remove_port));
+}
+
} // namespace embedder_support
diff --git a/chromium/components/embedder_support/content_settings_utils.cc b/chromium/components/embedder_support/content_settings_utils.cc
index 6d713ca6c24..356f3bb9c15 100644
--- a/chromium/components/embedder_support/content_settings_utils.cc
+++ b/chromium/components/embedder_support/content_settings_utils.cc
@@ -4,6 +4,7 @@
#include "components/embedder_support/content_settings_utils.h"
+#include "components/content_settings/browser/page_specific_content_settings.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_utils.h"
@@ -14,7 +15,7 @@ namespace embedder_support {
bool AllowAppCache(const GURL& manifest_url,
const GURL& site_for_cookies,
- const base::Optional<url::Origin>& top_frame_origin,
+ const absl::optional<url::Origin>& top_frame_origin,
const content_settings::CookieSettings* cookie_settings) {
return cookie_settings->IsCookieAccessAllowed(manifest_url, site_for_cookies,
top_frame_origin);
@@ -23,7 +24,7 @@ bool AllowAppCache(const GURL& manifest_url,
content::AllowServiceWorkerResult AllowServiceWorker(
const GURL& scope,
const GURL& site_for_cookies,
- const base::Optional<url::Origin>& top_frame_origin,
+ const absl::optional<url::Origin>& top_frame_origin,
const content_settings::CookieSettings* cookie_settings,
const HostContentSettingsMap* settings_map) {
GURL first_party_url = top_frame_origin ? top_frame_origin->GetURL() : GURL();
@@ -45,31 +46,60 @@ content::AllowServiceWorkerResult AllowServiceWorker(
bool AllowSharedWorker(
const GURL& worker_url,
const GURL& site_for_cookies,
- const base::Optional<url::Origin>& top_frame_origin,
+ const absl::optional<url::Origin>& top_frame_origin,
+ const std::string& name,
+ const storage::StorageKey& storage_key,
+ int render_process_id,
+ int render_frame_id,
const content_settings::CookieSettings* cookie_settings) {
- return cookie_settings->IsCookieAccessAllowed(worker_url, site_for_cookies,
- top_frame_origin);
+ bool allow = cookie_settings->IsCookieAccessAllowed(
+ worker_url, site_for_cookies, top_frame_origin);
+
+ content_settings::PageSpecificContentSettings::SharedWorkerAccessed(
+ render_process_id, render_frame_id, worker_url, name, storage_key,
+ !allow);
+ return allow;
}
bool AllowWorkerFileSystem(
const GURL& url,
+ const std::vector<content::GlobalFrameRoutingId>& render_frames,
const content_settings::CookieSettings* cookie_settings) {
- return cookie_settings->IsCookieAccessAllowed(url, url,
- url::Origin::Create(url));
+ bool allow = cookie_settings->IsCookieAccessAllowed(url, url,
+ url::Origin::Create(url));
+ for (const auto& it : render_frames) {
+ content_settings::PageSpecificContentSettings::FileSystemAccessed(
+ it.child_id, it.frame_routing_id, url, !allow);
+ }
+ return allow;
}
bool AllowWorkerIndexedDB(
const GURL& url,
+ const std::vector<content::GlobalFrameRoutingId>& render_frames,
const content_settings::CookieSettings* cookie_settings) {
- return cookie_settings->IsCookieAccessAllowed(url, url,
- url::Origin::Create(url));
+ bool allow = cookie_settings->IsCookieAccessAllowed(url, url,
+ url::Origin::Create(url));
+
+ for (const auto& it : render_frames) {
+ content_settings::PageSpecificContentSettings::IndexedDBAccessed(
+ it.child_id, it.frame_routing_id, url, !allow);
+ }
+ return allow;
}
bool AllowWorkerCacheStorage(
const GURL& url,
+ const std::vector<content::GlobalFrameRoutingId>& render_frames,
const content_settings::CookieSettings* cookie_settings) {
- return cookie_settings->IsCookieAccessAllowed(url, url,
- url::Origin::Create(url));
+ bool allow = cookie_settings->IsCookieAccessAllowed(url, url,
+ url::Origin::Create(url));
+
+ for (const auto& it : render_frames) {
+ content_settings::PageSpecificContentSettings::CacheStorageAccessed(
+ it.child_id, it.frame_routing_id, url, !allow);
+ }
+ return allow;
}
bool AllowWorkerWebLocks(
diff --git a/chromium/components/embedder_support/content_settings_utils.h b/chromium/components/embedder_support/content_settings_utils.h
index 8a681ff005e..2436b91f9c6 100644
--- a/chromium/components/embedder_support/content_settings_utils.h
+++ b/chromium/components/embedder_support/content_settings_utils.h
@@ -5,8 +5,9 @@
#ifndef COMPONENTS_EMBEDDER_SUPPORT_CONTENT_SETTINGS_UTILS_H_
#define COMPONENTS_EMBEDDER_SUPPORT_CONTENT_SETTINGS_UTILS_H_
-#include "base/optional.h"
#include "content/public/browser/allow_service_worker_result.h"
+#include "content/public/browser/global_routing_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
class GURL;
@@ -16,41 +17,56 @@ namespace content_settings {
class CookieSettings;
}
+namespace storage {
+class StorageKey;
+}
+
namespace embedder_support {
// See ContentBrowserClient::AllowAppCache.
bool AllowAppCache(const GURL& manifest_url,
const GURL& site_for_cookies,
- const base::Optional<url::Origin>& top_frame_origin,
+ const absl::optional<url::Origin>& top_frame_origin,
const content_settings::CookieSettings* cookie_settings);
// See ContentBrowserClient::AllowServiceWorker.
content::AllowServiceWorkerResult AllowServiceWorker(
const GURL& scope,
const GURL& site_for_cookies,
- const base::Optional<url::Origin>& top_frame_origin,
+ const absl::optional<url::Origin>& top_frame_origin,
const content_settings::CookieSettings* cookie_settings,
const HostContentSettingsMap* settings_map);
-// See ContentBrowserClient::AllowSharedWorker.
+// See ContentBrowserClient::AllowSharedWorker. This also notifies content
+// settings of shared worker access.
bool AllowSharedWorker(const GURL& worker_url,
const GURL& site_for_cookies,
- const base::Optional<url::Origin>& top_frame_origin,
+ const absl::optional<url::Origin>& top_frame_origin,
+ const std::string& name,
+ const storage::StorageKey& storage_key,
+ int render_process_id,
+ int render_frame_id,
const content_settings::CookieSettings* cookie_settings);
-// See ContentBrowserClient::AllowWorkerFileSystem.
+// See ContentBrowserClient::AllowWorkerFileSystem. This also notifies content
+// settings of file system access.
bool AllowWorkerFileSystem(
const GURL& url,
+ const std::vector<content::GlobalFrameRoutingId>& render_frames,
const content_settings::CookieSettings* cookie_settings);
-// See ContentBrowserClient::AllowWorkerIndexedDB.
+// See ContentBrowserClient::AllowWorkerIndexedDB. This also notifies content
+// settings of Indexed DB access.
bool AllowWorkerIndexedDB(
const GURL& url,
+ const std::vector<content::GlobalFrameRoutingId>& render_frames,
const content_settings::CookieSettings* cookie_settings);
-// See ContentBrowserClient::AllowWorkerCacheStorage.
+// See ContentBrowserClient::AllowWorkerCacheStorage. This also notifies content
+// settings of cache storage access.
bool AllowWorkerCacheStorage(
const GURL& url,
+ const std::vector<content::GlobalFrameRoutingId>& render_frames,
const content_settings::CookieSettings* cookie_settings);
// See ContentBrowserClient::AllowWorkerWebLocks.
diff --git a/chromium/components/embedder_support/origin_trials/component_updater_utils.cc b/chromium/components/embedder_support/origin_trials/component_updater_utils.cc
index 5ef281e3d88..93d699205ee 100644
--- a/chromium/components/embedder_support/origin_trials/component_updater_utils.cc
+++ b/chromium/components/embedder_support/origin_trials/component_updater_utils.cc
@@ -41,7 +41,7 @@ void ReadOriginTrialsConfigAndPopulateLocalState(
const bool manifest_has_disabled_features = manifest->GetList(
kManifestDisabledFeaturesPath, &override_disabled_feature_list);
if (manifest_has_disabled_features &&
- !override_disabled_feature_list->empty()) {
+ !override_disabled_feature_list->GetList().empty()) {
ListPrefUpdate update(local_state, prefs::kOriginTrialDisabledFeatures);
update->Swap(override_disabled_feature_list);
} else {
@@ -50,7 +50,8 @@ void ReadOriginTrialsConfigAndPopulateLocalState(
base::ListValue* disabled_tokens_list = nullptr;
const bool manifest_has_disabled_tokens = manifest->GetList(
kManifestDisabledTokenSignaturesPath, &disabled_tokens_list);
- if (manifest_has_disabled_tokens && !disabled_tokens_list->empty()) {
+ if (manifest_has_disabled_tokens &&
+ !disabled_tokens_list->GetList().empty()) {
ListPrefUpdate update(local_state, prefs::kOriginTrialDisabledTokens);
update->Swap(disabled_tokens_list);
} else {
diff --git a/chromium/components/embedder_support/origin_trials/component_updater_utils_unittest.cc b/chromium/components/embedder_support/origin_trials/component_updater_utils_unittest.cc
index e18e6a8680b..702899aeb02 100644
--- a/chromium/components/embedder_support/origin_trials/component_updater_utils_unittest.cc
+++ b/chromium/components/embedder_support/origin_trials/component_updater_utils_unittest.cc
@@ -78,7 +78,9 @@ class OriginTrialsComponentInstallerTest : public PlatformTest {
void AddDisabledFeaturesToPrefs(const std::vector<std::string>& features) {
base::ListValue disabled_feature_list;
- disabled_feature_list.AppendStrings(features);
+ for (const std::string& feature : features) {
+ disabled_feature_list.Append(feature);
+ }
ListPrefUpdate update(
local_state(), embedder_support::prefs::kOriginTrialDisabledFeatures);
update->Swap(&disabled_feature_list);
@@ -110,7 +112,9 @@ class OriginTrialsComponentInstallerTest : public PlatformTest {
void AddDisabledTokensToPrefs(const std::vector<std::string>& tokens) {
base::ListValue disabled_token_list;
- disabled_token_list.AppendStrings(tokens);
+ for (const std::string& token : tokens) {
+ disabled_token_list.Append(token);
+ }
ListPrefUpdate update(local_state(),
embedder_support::prefs::kOriginTrialDisabledTokens);
update->Swap(&disabled_token_list);
@@ -232,7 +236,9 @@ TEST_F(OriginTrialsComponentInstallerTest,
auto manifest = std::make_unique<base::DictionaryValue>();
auto disabled_feature_list = std::make_unique<base::ListValue>();
- disabled_feature_list->AppendStrings(kNewDisabledFeatures);
+ for (const std::string& feature : kNewDisabledFeatures) {
+ disabled_feature_list->Append(feature);
+ }
manifest->Set(kManifestDisabledFeaturesPath,
std::move(disabled_feature_list));
@@ -311,7 +317,9 @@ TEST_F(OriginTrialsComponentInstallerTest,
auto manifest = std::make_unique<base::DictionaryValue>();
auto disabled_token_list = std::make_unique<base::ListValue>();
- disabled_token_list->AppendStrings(kNewDisabledTokens);
+ for (const std::string& token : kNewDisabledTokens) {
+ disabled_token_list->Append(token);
+ }
manifest->Set(kManifestDisabledTokenSignaturesPath,
std::move(disabled_token_list));
diff --git a/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.cc b/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.cc
index 4cdb5c3a1ae..b31d092458e 100644
--- a/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.cc
+++ b/chromium/components/embedder_support/origin_trials/origin_trial_policy_impl.cc
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/stl_util.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "components/embedder_support/origin_trials/features.h"
#include "components/embedder_support/switches.h"
@@ -66,12 +67,12 @@ std::vector<base::StringPiece> OriginTrialPolicyImpl::GetPublicKeys() const {
}
bool OriginTrialPolicyImpl::IsFeatureDisabled(base::StringPiece feature) const {
- return disabled_features_.count(feature.as_string()) > 0;
+ return disabled_features_.count(std::string(feature)) > 0;
}
bool OriginTrialPolicyImpl::IsTokenDisabled(
base::StringPiece token_signature) const {
- return disabled_tokens_.count(token_signature.as_string()) > 0;
+ return disabled_tokens_.count(std::string(token_signature)) > 0;
}
// Exclude users in Field trial control group from the corresponding origin
diff --git a/chromium/components/embedder_support/user_agent_utils.cc b/chromium/components/embedder_support/user_agent_utils.cc
index 569518f209a..1f8de242c42 100644
--- a/chromium/components/embedder_support/user_agent_utils.cc
+++ b/chromium/components/embedder_support/user_agent_utils.cc
@@ -5,6 +5,7 @@
#include "components/embedder_support/user_agent_utils.h"
#include "base/command_line.h"
+#include "base/no_destructor.h"
#include "base/strings/strcat.h"
#include "build/branding_buildflags.h"
#include "components/embedder_support/switches.h"
@@ -54,9 +55,9 @@ std::string GetUserAgent() {
// version checking.
blink::UserAgentBrandList GenerateBrandVersionList(
int seed,
- base::Optional<std::string> brand,
+ absl::optional<std::string> brand,
std::string major_version,
- base::Optional<std::string> maybe_greasey_brand) {
+ absl::optional<std::string> maybe_greasey_brand) {
DCHECK_GE(seed, 0);
const int npermutations = 6; // 3!
int permutation = seed % npermutations;
@@ -105,15 +106,15 @@ const blink::UserAgentBrandList& GetBrandVersionList() {
int major_version_number;
std::string major_version = version_info::GetMajorVersionNumber();
base::StringToInt(major_version, &major_version_number);
- base::Optional<std::string> brand;
+ absl::optional<std::string> brand;
#if !BUILDFLAG(CHROMIUM_BRANDING)
brand = version_info::GetProductName();
#endif
- base::Optional<std::string> maybe_param_override =
+ absl::optional<std::string> maybe_param_override =
base::GetFieldTrialParamValueByFeature(features::kGreaseUACH,
"brand_override");
if (maybe_param_override->empty())
- maybe_param_override = base::nullopt;
+ maybe_param_override = absl::nullopt;
return GenerateBrandVersionList(major_version_number, brand,
major_version, maybe_param_override);
diff --git a/chromium/components/embedder_support/user_agent_utils.h b/chromium/components/embedder_support/user_agent_utils.h
index 52e1148e213..81a5edd2307 100644
--- a/chromium/components/embedder_support/user_agent_utils.h
+++ b/chromium/components/embedder_support/user_agent_utils.h
@@ -30,9 +30,9 @@ blink::UserAgentMetadata GetUserAgentMetadata();
blink::UserAgentBrandList GenerateBrandVersionList(
int seed,
- base::Optional<std::string> brand,
+ absl::optional<std::string> brand,
std::string major_version,
- base::Optional<std::string> maybe_greasey_brand);
+ absl::optional<std::string> maybe_greasey_brand);
#if defined(OS_ANDROID)
// This sets a user agent string to simulate a desktop user agent on mobile.
diff --git a/chromium/components/embedder_support/user_agent_utils_unittest.cc b/chromium/components/embedder_support/user_agent_utils_unittest.cc
index c515a429f6b..281f9f717b4 100644
--- a/chromium/components/embedder_support/user_agent_utils_unittest.cc
+++ b/chromium/components/embedder_support/user_agent_utils_unittest.cc
@@ -302,26 +302,26 @@ TEST(UserAgentUtilsTest, GenerateBrandVersionList) {
blink::UserAgentMetadata metadata;
metadata.brand_version_list =
- GenerateBrandVersionList(84, base::nullopt, "84", base::nullopt);
+ GenerateBrandVersionList(84, absl::nullopt, "84", absl::nullopt);
std::string brand_list = metadata.SerializeBrandVersionList();
EXPECT_EQ(R"(" Not A;Brand";v="99", "Chromium";v="84")", brand_list);
metadata.brand_version_list =
- GenerateBrandVersionList(85, base::nullopt, "85", base::nullopt);
+ GenerateBrandVersionList(85, absl::nullopt, "85", absl::nullopt);
std::string brand_list_diff = metadata.SerializeBrandVersionList();
// Make sure the lists are different for different seeds
EXPECT_EQ(R"("Chromium";v="85", " Not;A Brand";v="99")", brand_list_diff);
EXPECT_NE(brand_list, brand_list_diff);
metadata.brand_version_list =
- GenerateBrandVersionList(84, "Totally A Brand", "84", base::nullopt);
+ GenerateBrandVersionList(84, "Totally A Brand", "84", absl::nullopt);
std::string brand_list_w_brand = metadata.SerializeBrandVersionList();
EXPECT_EQ(
R"(" Not A;Brand";v="99", "Chromium";v="84", "Totally A Brand";v="84")",
brand_list_w_brand);
metadata.brand_version_list =
- GenerateBrandVersionList(84, base::nullopt, "84", "Clean GREASE");
+ GenerateBrandVersionList(84, absl::nullopt, "84", "Clean GREASE");
std::string brand_list_grease_override = metadata.SerializeBrandVersionList();
EXPECT_EQ(R"("Clean GREASE";v="99", "Chromium";v="84")",
brand_list_grease_override);
@@ -329,7 +329,7 @@ TEST(UserAgentUtilsTest, GenerateBrandVersionList) {
// Should DCHECK on negative numbers
EXPECT_DCHECK_DEATH(
- GenerateBrandVersionList(-1, base::nullopt, "99", base::nullopt));
+ GenerateBrandVersionList(-1, absl::nullopt, "99", absl::nullopt));
}
} // namespace embedder_support
diff --git a/chromium/components/encrypted_messages/OWNERS b/chromium/components/encrypted_messages/OWNERS
index 589776dbc06..fb3da75c7bb 100644
--- a/chromium/components/encrypted_messages/OWNERS
+++ b/chromium/components/encrypted_messages/OWNERS
@@ -1,3 +1,2 @@
estark@chromium.org
-felt@chromium.org
rsleevi@chromium.org
diff --git a/chromium/components/enterprise/BUILD.gn b/chromium/components/enterprise/BUILD.gn
index 35a6655b58c..6488945e242 100644
--- a/chromium/components/enterprise/BUILD.gn
+++ b/chromium/components/enterprise/BUILD.gn
@@ -19,6 +19,7 @@ static_library("enterprise") {
deps = [
"//base",
"//build:chromeos_buildflags",
+ "//components/policy/core/browser",
"//components/policy/core/common",
"//components/prefs",
"//services/network/public/cpp",
@@ -32,6 +33,8 @@ static_library("enterprise") {
"browser/reporting/policy_info.h",
"browser/reporting/profile_report_generator.cc",
"browser/reporting/profile_report_generator.h",
+ "browser/reporting/real_time_report_generator.cc",
+ "browser/reporting/real_time_report_generator.h",
"browser/reporting/real_time_uploader.cc",
"browser/reporting/real_time_uploader.h",
"browser/reporting/report_generator.cc",
@@ -49,7 +52,6 @@ static_library("enterprise") {
deps += [
"//base/util/timer",
- "//components/policy/core/browser",
"//components/policy/proto",
"//components/reporting/client:report_queue_provider",
"//components/strings",
@@ -58,7 +60,7 @@ static_library("enterprise") {
]
}
- if (!is_android && !is_chromeos_ash) {
+ if (!is_chromeos_ash) {
sources += [
"browser/controller/chrome_browser_cloud_management_controller.cc",
"browser/controller/chrome_browser_cloud_management_controller.h",
@@ -100,6 +102,7 @@ source_set("unit_tests") {
deps += [
"//build:chromeos_buildflags",
+ "//components/enterprise/common/proto:extensions_workflow_events_proto",
"//components/policy/core/common:test_support",
"//components/reporting/client:test_support",
]
diff --git a/chromium/components/enterprise/DEPS b/chromium/components/enterprise/DEPS
index c7c2cb1a0b5..fb27fb38fab 100644
--- a/chromium/components/enterprise/DEPS
+++ b/chromium/components/enterprise/DEPS
@@ -7,4 +7,5 @@ include_rules = [
"+components/version_info",
"+net",
"+services/network/public",
+ "+third_party/protobuf"
]
diff --git a/chromium/components/enterprise/browser/controller/browser_dm_token_storage.h b/chromium/components/enterprise/browser/controller/browser_dm_token_storage.h
index 4491cd0c477..a78a555ffec 100644
--- a/chromium/components/enterprise/browser/controller/browser_dm_token_storage.h
+++ b/chromium/components/enterprise/browser/controller/browser_dm_token_storage.h
@@ -13,13 +13,13 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/no_destructor.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/sequence_checker.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece_forward.h"
#include "base/system/sys_info.h"
#include "components/policy/core/common/cloud/dm_token.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class TaskRunner;
diff --git a/chromium/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc b/chromium/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc
index 179e0886e18..770726b1b25 100644
--- a/chromium/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc
+++ b/chromium/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.cc
@@ -19,8 +19,6 @@
#include "components/enterprise/browser/controller/browser_dm_token_storage.h"
#include "components/enterprise/browser/controller/chrome_browser_cloud_management_helper.h"
#include "components/enterprise/browser/enterprise_switches.h"
-#include "components/enterprise/browser/reporting/report_generator.h"
-#include "components/enterprise/browser/reporting/report_scheduler.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/cloud/chrome_browser_cloud_management_metrics.h"
#include "components/policy/core/common/cloud/cloud_external_data_manager.h"
@@ -34,6 +32,11 @@
#include "components/policy/policy_constants.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#if !defined(OS_ANDROID)
+#include "components/enterprise/browser/reporting/report_generator.h"
+#include "components/enterprise/browser/reporting/report_scheduler.h"
+#endif
+
namespace policy {
namespace {
@@ -163,6 +166,7 @@ void ChromeBrowserCloudManagementController::Init(
delegate_->InitializeOAuthTokenFactory(url_loader_factory, local_state);
}
+#if !defined(OS_ANDROID)
// Post the task of CreateReportScheduler to run on best effort after launch
// is completed.
delegate_->GetBestEffortTaskRunner()->PostTask(
@@ -170,6 +174,7 @@ void ChromeBrowserCloudManagementController::Init(
base::BindOnce(
&ChromeBrowserCloudManagementController::CreateReportScheduler,
weak_factory_.GetWeakPtr()));
+#endif
MachineLevelUserCloudPolicyManager* policy_manager =
delegate_->GetMachineLevelUserCloudPolicyManager();
@@ -272,10 +277,12 @@ void ChromeBrowserCloudManagementController::InvalidatePolicies() {
policy_fetcher_->Disconnect();
}
+#if !defined(OS_ANDROID)
// This causes the scheduler to stop refreshing itself since the DM token is
// no longer valid.
if (report_scheduler_)
report_scheduler_->OnDMTokenUpdated();
+#endif
}
void ChromeBrowserCloudManagementController::InvalidateDMTokenCallback(
@@ -318,8 +325,10 @@ void ChromeBrowserCloudManagementController::OnServiceAccountSet(
void ChromeBrowserCloudManagementController::ShutDown() {
delegate_->ShutDown();
+#if !defined(OS_ANDROID)
if (report_scheduler_)
report_scheduler_.reset();
+#endif
}
void ChromeBrowserCloudManagementController::NotifyPolicyRegisterFinished(
@@ -335,11 +344,13 @@ void ChromeBrowserCloudManagementController::NotifyBrowserUnenrolled(
observer.OnBrowserUnenrolled(succeeded);
}
+#if !defined(OS_ANDROID)
void ChromeBrowserCloudManagementController::NotifyCloudReportingLaunched() {
for (auto& observer : observers_) {
observer.OnCloudReportingLaunched();
}
}
+#endif
bool ChromeBrowserCloudManagementController::GetEnrollmentTokenAndClientId(
std::string* enrollment_token,
@@ -398,13 +409,16 @@ void ChromeBrowserCloudManagementController::
VLOG(1) << "Fetch policy after enrollment.";
policy_fetcher_->SetupRegistrationAndFetchPolicy(
BrowserDMTokenStorage::Get()->RetrieveDMToken(), client_id);
+#if !defined(OS_ANDROID)
if (report_scheduler_) {
report_scheduler_->OnDMTokenUpdated();
}
+#endif
NotifyPolicyRegisterFinished(true);
}
+#if !defined(OS_ANDROID)
void ChromeBrowserCloudManagementController::CreateReportScheduler() {
cloud_policy_client_ = std::make_unique<policy::CloudPolicyClient>(
delegate_->GetDeviceManagementService(),
@@ -416,6 +430,7 @@ void ChromeBrowserCloudManagementController::CreateReportScheduler() {
NotifyCloudReportingLaunched();
}
+#endif
void ChromeBrowserCloudManagementController::SetGaiaURLLoaderFactory(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
diff --git a/chromium/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h b/chromium/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h
index 68effcc7c27..819ed6188f8 100644
--- a/chromium/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h
+++ b/chromium/components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h
@@ -14,9 +14,13 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
-#include "components/enterprise/browser/reporting/reporting_delegate_factory.h"
+#include "build/build_config.h"
#include "components/policy/core/common/cloud/cloud_policy_client.h"
+#if !defined(OS_ANDROID)
+#include "components/enterprise/browser/reporting/reporting_delegate_factory.h"
+#endif
+
class PrefService;
namespace network {
@@ -24,9 +28,11 @@ class NetworkConnectionTracker;
class SharedURLLoaderFactory;
} // namespace network
+#if !defined(OS_ANDROID)
namespace enterprise_reporting {
class ReportScheduler;
}
+#endif
namespace policy {
class ChromeBrowserCloudManagementRegistrar;
@@ -120,11 +126,13 @@ class ChromeBrowserCloudManagementController
virtual scoped_refptr<network::SharedURLLoaderFactory>
GetSharedURLLoaderFactory() = 0;
+#if !defined(OS_ANDROID)
// Creates and returns a ReportScheduler for enterprise reporting. Delegates
// must pass the platform-specific factory that should be used to
// instantiate the delegates for the reporting objects.
virtual std::unique_ptr<enterprise_reporting::ReportScheduler>
CreateReportScheduler(CloudPolicyClient* client) = 0;
+#endif
// Returns a BestEffort Task Runner, bound to the UI thread like the rest of
// this class, that is meant to be used to schedule asynchronous tasks
@@ -149,8 +157,10 @@ class ChromeBrowserCloudManagementController
// Called when the browser has been unenrolled.
virtual void OnBrowserUnenrolled(bool succeeded) {}
+#if !defined(OS_ANDROID)
// Called when the cloud reporting is launched.
virtual void OnCloudReportingLaunched() {}
+#endif
};
// Directory name under the user-data-dir where the policy data is stored.
@@ -200,7 +210,9 @@ class ChromeBrowserCloudManagementController
protected:
void NotifyPolicyRegisterFinished(bool succeeded);
void NotifyBrowserUnenrolled(bool succeeded);
+#if !defined(OS_ANDROID)
void NotifyCloudReportingLaunched();
+#endif
private:
bool GetEnrollmentTokenAndClientId(std::string* enrollment_token,
@@ -212,7 +224,9 @@ class ChromeBrowserCloudManagementController
void InvalidatePolicies();
void InvalidateDMTokenCallback(bool success);
+#if !defined(OS_ANDROID)
void CreateReportScheduler();
+#endif
base::ObserverList<Observer, true>::Unchecked observers_;
@@ -225,7 +239,9 @@ class ChromeBrowserCloudManagementController
// Time at which the enrollment process was started. Used to log UMA metric.
base::Time enrollment_start_time_;
+#if !defined(OS_ANDROID)
std::unique_ptr<enterprise_reporting::ReportScheduler> report_scheduler_;
+#endif
std::unique_ptr<policy::CloudPolicyClient> cloud_policy_client_;
diff --git a/chromium/components/enterprise/browser/enterprise_switches.cc b/chromium/components/enterprise/browser/enterprise_switches.cc
index d7787a18647..b35a3b15238 100644
--- a/chromium/components/enterprise/browser/enterprise_switches.cc
+++ b/chromium/components/enterprise/browser/enterprise_switches.cc
@@ -9,7 +9,7 @@
namespace switches {
-#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
// Enables the Chrome Browser Cloud Management integration on Chromium builds.
// CBCM is always enabled in branded builds.
const char kEnableChromeBrowserCloudManagement[] =
diff --git a/chromium/components/enterprise/browser/enterprise_switches.h b/chromium/components/enterprise/browser/enterprise_switches.h
index 902e1f24188..0a9d8139195 100644
--- a/chromium/components/enterprise/browser/enterprise_switches.h
+++ b/chromium/components/enterprise/browser/enterprise_switches.h
@@ -13,7 +13,7 @@
namespace switches {
-#if !BUILDFLAG(IS_CHROMEOS_ASH) && !defined(OS_ANDROID)
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
extern const char kEnableChromeBrowserCloudManagement[];
#endif
diff --git a/chromium/components/enterprise/browser/reporting/common_pref_names.cc b/chromium/components/enterprise/browser/reporting/common_pref_names.cc
index 8b15ce92f89..cc93b96be0b 100644
--- a/chromium/components/enterprise/browser/reporting/common_pref_names.cc
+++ b/chromium/components/enterprise/browser/reporting/common_pref_names.cc
@@ -17,4 +17,8 @@ const char kCloudReportingEnabled[] =
const char kLastUploadTimestamp[] =
"enterprise_reporting.last_upload_timestamp";
+// The timestamp of the last enterprise report upload is succeeded.
+const char kLastUploadSucceededTimestamp[] =
+ "enterprise_reporting.last_upload_succeeded_timestamp";
+
} // namespace enterprise_reporting
diff --git a/chromium/components/enterprise/browser/reporting/common_pref_names.h b/chromium/components/enterprise/browser/reporting/common_pref_names.h
index c5d5e66ac74..39b968ad96f 100644
--- a/chromium/components/enterprise/browser/reporting/common_pref_names.h
+++ b/chromium/components/enterprise/browser/reporting/common_pref_names.h
@@ -15,6 +15,8 @@ extern const char kCloudReportingEnabled[];
extern const char kLastUploadTimestamp[];
+extern const char kLastUploadSucceededTimestamp[];
+
} // namespace enterprise_reporting
#endif // COMPONENTS_ENTERPRISE_BROWSER_REPORTING_COMMON_PREF_NAMES_H_
diff --git a/chromium/components/enterprise/browser/reporting/policy_info.cc b/chromium/components/enterprise/browser/reporting/policy_info.cc
index 57278146563..773e8b1fe8a 100644
--- a/chromium/components/enterprise/browser/reporting/policy_info.cc
+++ b/chromium/components/enterprise/browser/reporting/policy_info.cc
@@ -62,6 +62,8 @@ em::Policy_PolicySource GetSource(const base::Value& policy) {
return em::Policy_PolicySource_SOURCE_PRIORITY_CLOUD;
case policy::POLICY_SOURCE_MERGED:
return em::Policy_PolicySource_SOURCE_MERGED;
+ case policy::POLICY_SOURCE_CLOUD_FROM_ASH:
+ return em::Policy_PolicySource_SOURCE_CLOUD_FROM_ASH;
case policy::POLICY_SOURCE_COUNT:
NOTREACHED();
return em::Policy_PolicySource_SOURCE_UNKNOWN;
diff --git a/chromium/components/enterprise/browser/reporting/profile_report_generator.h b/chromium/components/enterprise/browser/reporting/profile_report_generator.h
index a16a03c8a25..fe86556ba8c 100644
--- a/chromium/components/enterprise/browser/reporting/profile_report_generator.h
+++ b/chromium/components/enterprise/browser/reporting/profile_report_generator.h
@@ -89,8 +89,7 @@ class ProfileReportGenerator {
bool extensions_enabled_ = true;
bool policies_enabled_ = true;
- std::unique_ptr<enterprise_management::ChromeUserProfileInfo> report_ =
- nullptr;
+ std::unique_ptr<enterprise_management::ChromeUserProfileInfo> report_;
};
} // namespace enterprise_reporting
diff --git a/chromium/components/enterprise/browser/reporting/real_time_report_generator.cc b/chromium/components/enterprise/browser/reporting/real_time_report_generator.cc
new file mode 100644
index 00000000000..5c23721fefb
--- /dev/null
+++ b/chromium/components/enterprise/browser/reporting/real_time_report_generator.cc
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/enterprise/browser/reporting/real_time_report_generator.h"
+#include "components/enterprise/browser/reporting/reporting_delegate_factory.h"
+
+namespace enterprise_reporting {
+
+RealTimeReportGenerator::Delegate::Delegate() = default;
+RealTimeReportGenerator::Delegate::~Delegate() = default;
+
+RealTimeReportGenerator::RealTimeReportGenerator(
+ ReportingDelegateFactory* delegate_factory)
+ : delegate_(delegate_factory->GetRealTimeReportGeneratorDelegate()) {}
+RealTimeReportGenerator::~RealTimeReportGenerator() = default;
+
+std::vector<std::unique_ptr<google::protobuf::MessageLite>>
+RealTimeReportGenerator::Generate(ReportType type) {
+ if (!delegate_)
+ return std::vector<std::unique_ptr<google::protobuf::MessageLite>>();
+ return delegate_->Generate(type);
+}
+
+} // namespace enterprise_reporting
diff --git a/chromium/components/enterprise/browser/reporting/real_time_report_generator.h b/chromium/components/enterprise/browser/reporting/real_time_report_generator.h
new file mode 100644
index 00000000000..b825ddd849e
--- /dev/null
+++ b/chromium/components/enterprise/browser/reporting/real_time_report_generator.h
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ENTERPRISE_BROWSER_REPORTING_REAL_TIME_REPORT_GENERATOR_H_
+#define COMPONENTS_ENTERPRISE_BROWSER_REPORTING_REAL_TIME_REPORT_GENERATOR_H_
+
+#include <memory>
+#include <vector>
+
+#include "third_party/protobuf/src/google/protobuf/message_lite.h"
+
+namespace enterprise_reporting {
+
+class ReportingDelegateFactory;
+
+// Generator of reports that is uploaded with the ERP (Encrypted Reporting
+// Pipeline). The reports generated here should be relatively small and can be
+// uploaded much more frequently than the CBCM status report.
+class RealTimeReportGenerator {
+ public:
+ enum ReportType { kExtensionRequest = 0 };
+
+ // Delegate class that is used to collect information and generate reports
+ // outside the //components. For example, RealTimeReportGeneratorDesktop
+ // actual_report chrome/browser/enterprise/reporting.
+ class Delegate {
+ public:
+ Delegate();
+ Delegate(const Delegate&) = delete;
+ Delegate& operator=(const Delegate&) = delete;
+ virtual ~Delegate();
+
+ virtual std::vector<std::unique_ptr<google::protobuf::MessageLite>>
+ Generate(ReportType type) = 0;
+ };
+
+ explicit RealTimeReportGenerator(ReportingDelegateFactory* delegate_factory);
+ RealTimeReportGenerator(const RealTimeReportGenerator&) = delete;
+ RealTimeReportGenerator& operator=(const RealTimeReportGenerator&) = delete;
+ virtual ~RealTimeReportGenerator();
+
+ // Generates and returns reports for |type|. Multiple reports can be generated
+ // together in case of previous events are not generated successfully.
+ virtual std::vector<std::unique_ptr<google::protobuf::MessageLite>> Generate(
+ ReportType type);
+
+ private:
+ std::unique_ptr<Delegate> delegate_;
+};
+
+} // namespace enterprise_reporting
+
+#endif // COMPONENTS_ENTERPRISE_BROWSER_REPORTING_REAL_TIME_REPORT_GENERATOR_H_
diff --git a/chromium/components/enterprise/browser/reporting/real_time_uploader.cc b/chromium/components/enterprise/browser/reporting/real_time_uploader.cc
index b749a6f9f78..d542be78880 100644
--- a/chromium/components/enterprise/browser/reporting/real_time_uploader.cc
+++ b/chromium/components/enterprise/browser/reporting/real_time_uploader.cc
@@ -4,33 +4,39 @@
#include "components/enterprise/browser/reporting/real_time_uploader.h"
+#include <queue>
+
#include "base/bind_post_task.h"
+#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
#include "components/enterprise/browser/controller/browser_dm_token_storage.h"
#include "components/prefs/pref_service.h"
namespace enterprise_reporting {
-RealTimeUploader::RealTimeUploader() = default;
-RealTimeUploader::~RealTimeUploader() = default;
-
-bool RealTimeUploader::IsEnabled() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return !!report_queue_;
-}
-
// static
std::unique_ptr<RealTimeUploader> RealTimeUploader::Create(
const std::string& dm_token,
- reporting::Destination destination) {
- auto uploader = std::make_unique<RealTimeUploader>();
+ reporting::Destination destination,
+ reporting::Priority priority) {
+ auto uploader = base::WrapUnique(new RealTimeUploader(priority));
uploader->CreateReportQueue(dm_token, destination);
return uploader;
}
+RealTimeUploader::RealTimeUploader(reporting::Priority priority)
+ : report_priority_(priority) {}
+RealTimeUploader::~RealTimeUploader() = default;
+
+bool RealTimeUploader::IsEnabled() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return !!report_queue_;
+}
+
void RealTimeUploader::CreateReportQueue(const std::string& dm_token,
reporting::Destination destination) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto config = reporting::ReportQueueConfiguration::Create(
dm_token, destination,
@@ -42,27 +48,49 @@ void RealTimeUploader::CreateReportQueue(const std::string& dm_token,
return;
}
- auto report_queue_creation_callback = base::BindOnce(
- &RealTimeUploader::OnReportQueueCreated, weak_factory_.GetWeakPtr());
-
- CreateReportQueueRequest(
- std::move(config),
+ auto report_queue_creation_callback =
base::BindPostTask(base::ThreadTaskRunnerHandle::Get(),
- std::move(report_queue_creation_callback)));
+ base::BindOnce(&RealTimeUploader::OnReportQueueCreated,
+ weak_factory_.GetWeakPtr()));
+
+ CreateReportQueueRequest(std::move(config),
+ std::move(report_queue_creation_callback));
+}
+
+void RealTimeUploader::Upload(
+ std::unique_ptr<google::protobuf::MessageLite> report,
+ EnqueueCallback callback) {
+ DCHECK_NE(report_priority_, reporting::Priority::UNDEFINED_PRIORITY);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // The |upload_closure| will be only called by the RealTimeUploader directly.
+ auto upload_closure =
+ base::BindOnce(&RealTimeUploader::UploadClosure, base::Unretained(this),
+ std::move(report), std::move(callback));
+ if (!report_queue_) {
+ pending_reports_.push(std::move(upload_closure));
+ return;
+ }
+
+ std::move(upload_closure).Run();
}
void RealTimeUploader::CreateReportQueueRequest(
reporting::StatusOr<std::unique_ptr<reporting::ReportQueueConfiguration>>
config,
reporting::ReportQueueProvider::CreateReportQueueCallback callback) {
+#if !defined(OS_IOS)
reporting::ReportQueueProvider::CreateQueue(std::move(config.ValueOrDie()),
std::move(callback));
+#else
+ NOTREACHED();
+#endif // !defined(OS_IOS)
}
void RealTimeUploader::OnReportQueueCreated(
reporting::ReportQueueProvider::CreateReportQueueResponse
create_report_queue_response) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
if (!create_report_queue_response.ok()) {
// TODO(crbug.com/1192292): Retry on unavailable error, and collect metrics
// on failure rate.
@@ -71,5 +99,30 @@ void RealTimeUploader::OnReportQueueCreated(
return;
}
report_queue_ = std::move(create_report_queue_response.ValueOrDie());
+
+ while (!pending_reports_.empty()) {
+ std::move(pending_reports_.front()).Run();
+ pending_reports_.pop();
+ }
+}
+
+void RealTimeUploader::UploadClosure(
+ std::unique_ptr<google::protobuf::MessageLite> report,
+ EnqueueCallback callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(report_queue_);
+ report_queue_->Enqueue(
+ report.get(), report_priority_,
+ base::BindPostTask(
+ base::ThreadTaskRunnerHandle::Get(),
+ base::BindOnce(&RealTimeUploader::OnReportEnqueued,
+ weak_factory_.GetWeakPtr(), std::move(callback))));
}
+
+void RealTimeUploader::OnReportEnqueued(EnqueueCallback callback,
+ reporting::Status status) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ std::move(callback).Run(status.ok());
+}
+
} // namespace enterprise_reporting
diff --git a/chromium/components/enterprise/browser/reporting/real_time_uploader.h b/chromium/components/enterprise/browser/reporting/real_time_uploader.h
index acb7225d81a..2ee58302d1b 100644
--- a/chromium/components/enterprise/browser/reporting/real_time_uploader.h
+++ b/chromium/components/enterprise/browser/reporting/real_time_uploader.h
@@ -6,29 +6,44 @@
#define COMPONENTS_ENTERPRISE_BROWSER_REPORTING_REAL_TIME_UPLOADER_H_
#include "base/memory/weak_ptr.h"
-#include "base/sequence_checker.h"
+#include "base/threading/thread_checker.h"
#include "components/reporting/client/report_queue_provider.h"
namespace enterprise_reporting {
+// A helper class to upload real time reports with ERP. It needs to be created
+// and used on the main thread.
class RealTimeUploader {
public:
- RealTimeUploader();
+ using EnqueueCallback = base::OnceCallback<void(bool)>;
+
+ static std::unique_ptr<RealTimeUploader> Create(
+ const std::string& dm_token,
+ reporting::Destination destination,
+ reporting::Priority priority);
+
RealTimeUploader(const RealTimeUploader&) = delete;
RealTimeUploader& operator=(const RealTimeUploader&) = delete;
virtual ~RealTimeUploader();
- // Returns true if report queue is ready.
- bool IsEnabled();
- static std::unique_ptr<RealTimeUploader> Create(
- const std::string& dm_token,
- reporting::Destination destination);
+ // Returns true if report queue is ready.
+ bool IsEnabled() const;
// Creates the reporting::ReportQueue.
void CreateReportQueue(const std::string& dm_token,
reporting::Destination destination);
+ // Uploads the |report|. This API must be called after CreateReportQueue().
+ // However, the caller doesn't have to wait for async queue creation. The
+ // reports that are added before queue is ready will be cached and sent out
+ // afterwards.
+ // The |callback| will be called once the report is in the queue. There is no
+ // callback for report uploading.
+ virtual void Upload(std::unique_ptr<google::protobuf::MessageLite> report,
+ EnqueueCallback callback);
+
protected:
+ explicit RealTimeUploader(reporting::Priority priority);
// virtual function for unit test to fake
// reporting::ReportQueueProvider::CreateQueue() call before API providing a
// fake implementation.
@@ -42,9 +57,17 @@ class RealTimeUploader {
reporting::ReportQueueProvider::CreateReportQueueResponse
create_report_queue_response);
+ void UploadClosure(std::unique_ptr<google::protobuf::MessageLite> report,
+ EnqueueCallback callback);
+ void OnReportEnqueued(EnqueueCallback callback, reporting::Status status);
+
std::unique_ptr<reporting::ReportQueue> report_queue_;
- SEQUENCE_CHECKER(sequence_checker_);
+ const reporting::Priority report_priority_;
+
+ std::queue<base::OnceClosure> pending_reports_;
+
+ THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<RealTimeUploader> weak_factory_{this};
};
diff --git a/chromium/components/enterprise/browser/reporting/real_time_uploader_unittest.cc b/chromium/components/enterprise/browser/reporting/real_time_uploader_unittest.cc
index 2c108d1d572..8997bd36519 100644
--- a/chromium/components/enterprise/browser/reporting/real_time_uploader_unittest.cc
+++ b/chromium/components/enterprise/browser/reporting/real_time_uploader_unittest.cc
@@ -7,17 +7,29 @@
#include <memory>
#include "base/task/thread_pool.h"
+#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
+#include "components/enterprise/common/proto/extensions_workflow_events.pb.h"
#include "components/reporting/client/mock_report_queue.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::WithArg;
+
namespace enterprise_reporting {
namespace {
constexpr char kDMToken[] = "dm-token";
+constexpr reporting::Priority kPriority = reporting::Priority::FAST_BATCH;
class FakeRealTimeUploader : public RealTimeUploader {
public:
- FakeRealTimeUploader() = default;
+ explicit FakeRealTimeUploader(reporting::Priority priority)
+ : RealTimeUploader(priority),
+ mock_report_queue_(std::make_unique<reporting::MockReportQueue>()),
+ mock_report_queue_ptr_(mock_report_queue_.get()) {}
~FakeRealTimeUploader() override = default;
// RealTimeUploader
@@ -26,22 +38,29 @@ class FakeRealTimeUploader : public RealTimeUploader {
config,
reporting::ReportQueueProvider::CreateReportQueueCallback callback)
override {
- if (!callback)
- return;
+ DCHECK(callback);
reporting::ReportQueueProvider::CreateReportQueueResponse response;
- if (code_ == reporting::error::OK)
- response = std::make_unique<reporting::MockReportQueue>();
- else
+ if (code_ == reporting::error::OK) {
+ response = std::move(mock_report_queue_);
+ } else {
response = reporting::Status(code_, "");
+ }
base::ThreadPool::PostTask(
FROM_HERE, base::BindOnce(std::move(callback), std::move(response)));
}
+ reporting::MockReportQueue* mock_report_queue() {
+ DCHECK(mock_report_queue_ptr_);
+ return mock_report_queue_ptr_;
+ }
+
void SetError(reporting::error::Code code) { code_ = code; }
private:
reporting::error::Code code_ = reporting::error::OK;
+ std::unique_ptr<reporting::MockReportQueue> mock_report_queue_;
+ reporting::MockReportQueue* mock_report_queue_ptr_;
};
} // namespace
@@ -50,17 +69,23 @@ class RealTimeUploaderTest : public ::testing::Test {
RealTimeUploaderTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
- void CreateUploader() {
- uploader_ = std::make_unique<FakeRealTimeUploader>();
+ std::unique_ptr<ExtensionsWorkflowEvent> CreateReportAndGetSerializedString(
+ const std::string& id,
+ std::string* serialized_string) {
+ auto report = std::make_unique<ExtensionsWorkflowEvent>();
+ report->set_id(id);
+ report->SerializeToString(serialized_string);
+ return report;
}
protected:
- std::unique_ptr<FakeRealTimeUploader> uploader_;
base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<FakeRealTimeUploader> uploader_;
+ base::MockCallback<RealTimeUploader::EnqueueCallback> mock_enqueue_callback_;
};
TEST_F(RealTimeUploaderTest, CreateReportQueue) {
- CreateUploader();
+ uploader_ = std::make_unique<FakeRealTimeUploader>(kPriority);
uploader_->CreateReportQueue(kDMToken,
reporting::Destination::EXTENSIONS_WORKFLOW);
@@ -71,7 +96,7 @@ TEST_F(RealTimeUploaderTest, CreateReportQueue) {
}
TEST_F(RealTimeUploaderTest, CreateReportQueueAndFailed) {
- CreateUploader();
+ uploader_ = std::make_unique<FakeRealTimeUploader>(kPriority);
uploader_->SetError(reporting::error::UNKNOWN);
uploader_->CreateReportQueue(kDMToken,
reporting::Destination::EXTENSIONS_WORKFLOW);
@@ -82,14 +107,86 @@ TEST_F(RealTimeUploaderTest, CreateReportQueueAndFailed) {
}
TEST_F(RealTimeUploaderTest, CreateReportQueueAndCancel) {
- CreateUploader();
+ uploader_ = std::make_unique<FakeRealTimeUploader>(kPriority);
uploader_->CreateReportQueue(kDMToken,
reporting::Destination::EXTENSIONS_WORKFLOW);
-
// uploader is deleted before the report queue is created.
uploader_.reset();
task_environment_.RunUntilIdle();
}
+TEST_F(RealTimeUploaderTest, UploadReport) {
+ uploader_ = std::make_unique<FakeRealTimeUploader>(kPriority);
+ uploader_->CreateReportQueue(kDMToken,
+ reporting::Destination::EXTENSIONS_WORKFLOW);
+ task_environment_.RunUntilIdle();
+
+ std::string expected_report_1;
+ auto report_1 =
+ CreateReportAndGetSerializedString("id-1", &expected_report_1);
+ std::string expected_report_2;
+ auto report_2 =
+ CreateReportAndGetSerializedString("id-2", &expected_report_2);
+ {
+ InSequence sequence;
+
+ EXPECT_CALL(*uploader_->mock_report_queue(),
+ AddRecord(base::StringPiece(expected_report_1), kPriority, _))
+ .Times(1)
+ .WillOnce(WithArg<2>(
+ Invoke([](reporting::ReportQueue::EnqueueCallback callback) {
+ base::ThreadPool::PostTask(
+ base::BindOnce(std::move(callback),
+ reporting::Status(reporting::error::OK, "")));
+ })));
+
+ EXPECT_CALL(*uploader_->mock_report_queue(),
+ AddRecord(base::StringPiece(expected_report_2), kPriority, _))
+ .Times(1)
+ .WillOnce(WithArg<2>(
+ Invoke([](reporting::ReportQueue::EnqueueCallback callback) {
+ base::ThreadPool::PostTask(base::BindOnce(
+ std::move(callback),
+ reporting::Status(reporting::error::UNKNOWN, "")));
+ })));
+ }
+
+ EXPECT_CALL(mock_enqueue_callback_, Run(true)).Times(1);
+ EXPECT_CALL(mock_enqueue_callback_, Run(false)).Times(1);
+
+ uploader_->Upload(std::move(report_1), mock_enqueue_callback_.Get());
+ uploader_->Upload(std::move(report_2), mock_enqueue_callback_.Get());
+
+ task_environment_.RunUntilIdle();
+}
+
+TEST_F(RealTimeUploaderTest, UploadReportBeforeQueueIsReady) {
+ uploader_ = std::make_unique<FakeRealTimeUploader>(kPriority);
+
+ uploader_->CreateReportQueue(kDMToken,
+ reporting::Destination::EXTENSIONS_WORKFLOW);
+
+ // Does not call RunUntilIdle so that the queue is not created.
+ std::string expected_report;
+ auto report = CreateReportAndGetSerializedString("id", &expected_report);
+
+ EXPECT_CALL(*uploader_->mock_report_queue(),
+
+ AddRecord(base::StringPiece(expected_report), kPriority, _))
+ .Times(1)
+ .WillOnce(WithArg<2>(
+ Invoke([](reporting::ReportQueue::EnqueueCallback callback) {
+ base::ThreadPool::PostTask(
+ base::BindOnce(std::move(callback),
+ reporting::Status(reporting::error::OK, "")));
+ })));
+
+ EXPECT_CALL(mock_enqueue_callback_, Run(true)).Times(1);
+ EXPECT_CALL(mock_enqueue_callback_, Run(false)).Times(0);
+ uploader_->Upload(std::move(report), mock_enqueue_callback_.Get());
+
+ task_environment_.RunUntilIdle();
+}
+
} // namespace enterprise_reporting
diff --git a/chromium/components/enterprise/browser/reporting/report_request_queue_generator.h b/chromium/components/enterprise/browser/reporting/report_request_queue_generator.h
index 99e2f9c75de..4dcb92af59c 100644
--- a/chromium/components/enterprise/browser/reporting/report_request_queue_generator.h
+++ b/chromium/components/enterprise/browser/reporting/report_request_queue_generator.h
@@ -8,7 +8,6 @@
#include <memory>
#include <queue>
-#include "base/callback_forward.h"
#include "base/macros.h"
#include "build/build_config.h"
#include "components/enterprise/browser/reporting/profile_report_generator.h"
diff --git a/chromium/components/enterprise/browser/reporting/report_scheduler.cc b/chromium/components/enterprise/browser/reporting/report_scheduler.cc
index 214b27e4079..226d4d661a0 100644
--- a/chromium/components/enterprise/browser/reporting/report_scheduler.cc
+++ b/chromium/components/enterprise/browser/reporting/report_scheduler.cc
@@ -16,6 +16,7 @@
#include "build/chromeos_buildflags.h"
#include "components/enterprise/browser/controller/browser_dm_token_storage.h"
#include "components/enterprise/browser/reporting/common_pref_names.h"
+#include "components/enterprise/browser/reporting/real_time_uploader.h"
#include "components/enterprise/browser/reporting/reporting_delegate_factory.h"
#include "components/policy/core/common/cloud/cloud_policy_client.h"
#include "components/policy/core/common/cloud/device_management_service.h"
@@ -39,6 +40,7 @@ bool IsBrowserVersionUploaded(ReportScheduler::ReportTrigger trigger) {
return true;
case ReportScheduler::kTriggerNone:
case ReportScheduler::kTriggerExtensionRequest:
+ case ReportScheduler::kTriggerExtensionRequestRealTime:
return false;
}
}
@@ -47,6 +49,7 @@ bool IsExtensionRequestUploaded(ReportScheduler::ReportTrigger trigger) {
switch (trigger) {
case ReportScheduler::kTriggerTimer:
case ReportScheduler::kTriggerExtensionRequest:
+ case ReportScheduler::kTriggerExtensionRequestRealTime:
return true;
case ReportScheduler::kTriggerNone:
case ReportScheduler::kTriggerUpdate:
@@ -55,6 +58,13 @@ bool IsExtensionRequestUploaded(ReportScheduler::ReportTrigger trigger) {
}
}
+void OnExtensionRequestEnqueued(bool success) {
+ // So far, there is nothing handle the enqueue failure as the CBCM status
+ // report will cover all failed requests. However, we may need a retry logic
+ // here if Extension workflow is decoupled from the status report.
+ LOG(ERROR) << "Extension request failed to be added to the pipeline.";
+}
+
} // namespace
ReportScheduler::Delegate::Delegate() = default;
@@ -69,18 +79,22 @@ void ReportScheduler::Delegate::SetReportTriggerCallback(
ReportScheduler::ReportScheduler(
policy::CloudPolicyClient* client,
std::unique_ptr<ReportGenerator> report_generator,
+ std::unique_ptr<RealTimeReportGenerator> real_time_report_generator,
ReportingDelegateFactory* delegate_factory)
: ReportScheduler(std::move(client),
std::move(report_generator),
+ std::move(real_time_report_generator),
delegate_factory->GetReportSchedulerDelegate()) {}
ReportScheduler::ReportScheduler(
policy::CloudPolicyClient* client,
std::unique_ptr<ReportGenerator> report_generator,
+ std::unique_ptr<RealTimeReportGenerator> real_time_report_generator,
std::unique_ptr<ReportScheduler::Delegate> delegate)
: delegate_(std::move(delegate)),
cloud_policy_client_(std::move(client)),
- report_generator_(std::move(report_generator)) {
+ report_generator_(std::move(report_generator)),
+ real_time_report_generator_(std::move(real_time_report_generator)) {
delegate_->SetReportTriggerCallback(
base::BindRepeating(&ReportScheduler::GenerateAndUploadReport,
weak_ptr_factory_.GetWeakPtr()));
@@ -102,6 +116,11 @@ void ReportScheduler::SetReportUploaderForTesting(
report_uploader_ = std::move(uploader);
}
+void ReportScheduler::SetExtensionRequestUploaderForTesting(
+ std::unique_ptr<RealTimeUploader> uploader) {
+ extension_request_uploader_ = std::move(uploader);
+}
+
void ReportScheduler::OnDMTokenUpdated() {
OnReportEnabledPrefChanged();
}
@@ -146,6 +165,7 @@ void ReportScheduler::Stop() {
request_timer_.Stop();
delegate_->StopWatchingUpdates();
delegate_->StopWatchingExtensionRequest();
+ extension_request_uploader_.reset();
}
bool ReportScheduler::SetupBrowserPolicyClientRegistration() {
@@ -183,6 +203,12 @@ void ReportScheduler::Start(base::Time last_upload_time) {
}
void ReportScheduler::GenerateAndUploadReport(ReportTrigger trigger) {
+ // Real time report is generated and uploaded separately.
+ if (trigger == kTriggerExtensionRequestRealTime) {
+ UploadExtensionRequests();
+ return;
+ }
+
if (active_trigger_ != kTriggerNone) {
// A report is already being generated. Remember this trigger to be handled
// once the current report completes.
@@ -194,6 +220,7 @@ void ReportScheduler::GenerateAndUploadReport(ReportTrigger trigger) {
ReportType report_type = kFull;
switch (trigger) {
case kTriggerNone:
+ case kTriggerExtensionRequestRealTime:
NOTREACHED();
FALLTHROUGH;
case kTriggerTimer:
@@ -254,6 +281,9 @@ void ReportScheduler::OnReportUploaded(ReportUploader::ReportStatus status) {
if (IsExtensionRequestUploaded(active_trigger_))
delegate_->OnExtensionRequestUploaded();
+
+ delegate_->GetLocalState()->SetTime(kLastUploadSucceededTimestamp,
+ base::Time::Now());
FALLTHROUGH;
case ReportUploader::kTransientError:
// Stop retrying and schedule the next report to avoid stale report.
@@ -300,6 +330,27 @@ void ReportScheduler::RunPendingTriggers() {
GenerateAndUploadReport(trigger);
}
+void ReportScheduler::UploadExtensionRequests() {
+ RecordUploadTrigger(kTriggerExtensionRequestRealTime);
+ DCHECK(real_time_report_generator_);
+ VLOG(1) << "Create extension request and add it to the pipeline.";
+ if (!extension_request_uploader_) {
+ extension_request_uploader_ =
+ RealTimeUploader::Create(cloud_policy_client_->dm_token(),
+ reporting::Destination::EXTENSIONS_WORKFLOW,
+ reporting::Priority::FAST_BATCH);
+ }
+ auto reports = real_time_report_generator_->Generate(
+ RealTimeReportGenerator::kExtensionRequest);
+
+ for (auto& report : reports) {
+ extension_request_uploader_->Upload(
+ std::move(report), base::BindOnce(&OnExtensionRequestEnqueued));
+ }
+
+ delegate_->OnExtensionRequestUploaded();
+}
+
// static
void ReportScheduler::RecordUploadTrigger(ReportTrigger trigger) {
// These values are persisted to logs. Entries should not be renumbered and
@@ -310,7 +361,8 @@ void ReportScheduler::RecordUploadTrigger(ReportTrigger trigger) {
kUpdate = 2,
kNewVersion = 3,
kExtensionRequest = 4,
- kMaxValue = kExtensionRequest
+ kExtensionRequestRealTime = 5,
+ kMaxValue = kExtensionRequestRealTime
} sample = Sample::kNone;
switch (trigger) {
case kTriggerNone:
@@ -327,6 +379,9 @@ void ReportScheduler::RecordUploadTrigger(ReportTrigger trigger) {
case kTriggerExtensionRequest:
sample = Sample::kExtensionRequest;
break;
+ case kTriggerExtensionRequestRealTime:
+ sample = Sample::kExtensionRequestRealTime;
+ break;
}
base::UmaHistogramEnumeration("Enterprise.CloudReportingUploadTrigger",
sample);
diff --git a/chromium/components/enterprise/browser/reporting/report_scheduler.h b/chromium/components/enterprise/browser/reporting/report_scheduler.h
index 5052f12ed1f..1c43baad66f 100644
--- a/chromium/components/enterprise/browser/reporting/report_scheduler.h
+++ b/chromium/components/enterprise/browser/reporting/report_scheduler.h
@@ -14,6 +14,7 @@
#include "base/observer_list_types.h"
#include "base/time/time.h"
#include "base/util/timer/wall_clock_timer.h"
+#include "components/enterprise/browser/reporting/real_time_report_generator.h"
#include "components/enterprise/browser/reporting/report_generator.h"
#include "components/enterprise/browser/reporting/report_uploader.h"
#include "components/prefs/pref_change_registrar.h"
@@ -25,6 +26,7 @@ class CloudPolicyClient;
namespace enterprise_reporting {
class ReportingDelegateFactory;
+class RealTimeUploader;
// Schedules report generation and upload every 24 hours (and upon browser
// update for desktop Chrome) while cloud reporting is enabled via
@@ -41,6 +43,8 @@ class ReportScheduler {
kTriggerUpdate = 1U << 1, // An update was detected.
kTriggerNewVersion = 1U << 2, // A new version is running.
kTriggerExtensionRequest = 1U << 3, // Pending extension requests updated.
+ // Pending extension requests updated, with encrypted realtime pipeline.
+ kTriggerExtensionRequestRealTime = 1U << 4,
};
using ReportTriggerCallback = base::RepeatingCallback<void(ReportTrigger)>;
@@ -73,13 +77,17 @@ class ReportScheduler {
ReportTriggerCallback trigger_report_callback_;
};
- ReportScheduler(policy::CloudPolicyClient* client,
- std::unique_ptr<ReportGenerator> report_generator,
- ReportingDelegateFactory* delegate_factory);
+ ReportScheduler(
+ policy::CloudPolicyClient* client,
+ std::unique_ptr<ReportGenerator> report_generator,
+ std::unique_ptr<RealTimeReportGenerator> real_time_report_generator,
+ ReportingDelegateFactory* delegate_factory);
- ReportScheduler(policy::CloudPolicyClient* client,
- std::unique_ptr<ReportGenerator> report_generator,
- std::unique_ptr<ReportScheduler::Delegate> delegate);
+ ReportScheduler(
+ policy::CloudPolicyClient* client,
+ std::unique_ptr<ReportGenerator> report_generator,
+ std::unique_ptr<RealTimeReportGenerator> real_time_report_generator,
+ std::unique_ptr<ReportScheduler::Delegate> delegate);
~ReportScheduler();
@@ -92,6 +100,8 @@ class ReportScheduler {
bool IsNextReportScheduledForTesting() const;
void SetReportUploaderForTesting(std::unique_ptr<ReportUploader> uploader);
+ void SetExtensionRequestUploaderForTesting(
+ std::unique_ptr<RealTimeUploader> uploader);
void OnDMTokenUpdated();
@@ -128,6 +138,9 @@ class ReportScheduler {
// of another report.
void RunPendingTriggers();
+ // Creates and uploads extension requests with real time reporting pipeline.
+ void UploadExtensionRequests();
+
// Records that |trigger| was responsible for an upload attempt.
static void RecordUploadTrigger(ReportTrigger trigger);
@@ -144,6 +157,10 @@ class ReportScheduler {
std::unique_ptr<ReportGenerator> report_generator_;
+ std::unique_ptr<RealTimeReportGenerator> real_time_report_generator_;
+
+ std::unique_ptr<RealTimeUploader> extension_request_uploader_;
+
// The trigger responsible for initiating active report generation.
ReportTrigger active_trigger_ = kTriggerNone;
diff --git a/chromium/components/enterprise/browser/reporting/reporting_delegate_factory.h b/chromium/components/enterprise/browser/reporting/reporting_delegate_factory.h
index f4f64d8666b..9cdbaff7586 100644
--- a/chromium/components/enterprise/browser/reporting/reporting_delegate_factory.h
+++ b/chromium/components/enterprise/browser/reporting/reporting_delegate_factory.h
@@ -9,6 +9,7 @@
#include "components/enterprise/browser/reporting/browser_report_generator.h"
#include "components/enterprise/browser/reporting/profile_report_generator.h"
+#include "components/enterprise/browser/reporting/real_time_report_generator.h"
#include "components/enterprise/browser/reporting/report_generator.h"
#include "components/enterprise/browser/reporting/report_scheduler.h"
@@ -33,6 +34,9 @@ class ReportingDelegateFactory {
virtual std::unique_ptr<ReportScheduler::Delegate>
GetReportSchedulerDelegate() = 0;
+
+ virtual std::unique_ptr<RealTimeReportGenerator::Delegate>
+ GetRealTimeReportGeneratorDelegate() = 0;
};
} // namespace enterprise_reporting
diff --git a/chromium/components/enterprise/common/proto/BUILD.gn b/chromium/components/enterprise/common/proto/BUILD.gn
index 565e441e73e..99c2bb6a73b 100644
--- a/chromium/components/enterprise/common/proto/BUILD.gn
+++ b/chromium/components/enterprise/common/proto/BUILD.gn
@@ -15,3 +15,8 @@ proto_library("extensions_workflow_events_proto") {
proto_in_dir = "//"
sources = [ "extensions_workflow_events.proto" ]
}
+
+proto_library("device_trust_report_event_proto") {
+ proto_in_dir = "//"
+ sources = [ "device_trust_report_event.proto" ]
+}
diff --git a/chromium/components/enterprise/common/proto/device_trust_report_event.proto b/chromium/components/enterprise/common/proto/device_trust_report_event.proto
new file mode 100644
index 00000000000..855fc8b6c8c
--- /dev/null
+++ b/chromium/components/enterprise/common/proto/device_trust_report_event.proto
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved. Use
+// of this source code is governed by a BSD-style license that can
+// be found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package enterprise_connectors;
+
+// Event containing signals from the Device that can be used to
+// inform decisions about whether the machine is in a trustable state.
+//
+// May be sent periodically or triggered by a signal affecting change.
+//
+// The most common consumer of this information is an authentication
+// or authorization system.
+//
+// Next ID: 1.
+message DeviceTrustReportEvent {
+ // The registration field is used during the initial event and
+ // establishes the credentials used to verify future reports. It
+ // can only be sent once and subsequent attempst to register will fail.
+ //
+ // Because this field is used rarely, it is given a tag number
+ // outside the 1-byte tag range (tags 1-15).
+ message Credential {
+ // The format of the credential field.
+ enum CredentialFormat {
+ INVALID = 0;
+ EC_NID_X9_62_PRIME256V1_PUBLIC_DER = 1;
+ }
+ optional CredentialFormat format = 1; // Required.
+
+ // The credential used by the server to attest future reports.
+ optional bytes credential = 2; // Required.
+ }
+ optional Credential attestation_credential = 16;
+}
diff --git a/chromium/components/enterprise/common/proto/extensions_workflow_events.proto b/chromium/components/enterprise/common/proto/extensions_workflow_events.proto
index 4ce823d0f73..aeb4e83677c 100644
--- a/chromium/components/enterprise/common/proto/extensions_workflow_events.proto
+++ b/chromium/components/enterprise/common/proto/extensions_workflow_events.proto
@@ -6,7 +6,7 @@ syntax = "proto2";
option optimize_for = LITE_RUNTIME;
-package reporting;
+package enterprise_reporting;
// ExtensionsWorkflowEvent contains an extension request and is sent whenever a
// user requests an extension or cancels one.
diff --git a/chromium/components/error_page/common/alt_game_images.h b/chromium/components/error_page/common/alt_game_images.h
index d6677f2c307..e96cf3a2301 100644
--- a/chromium/components/error_page/common/alt_game_images.h
+++ b/chromium/components/error_page/common/alt_game_images.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
namespace error_page {
diff --git a/chromium/components/error_page/common/localized_error.cc b/chromium/components/error_page/common/localized_error.cc
index 99c0d0f29da..c92890edc32 100644
--- a/chromium/components/error_page/common/localized_error.cc
+++ b/chromium/components/error_page/common/localized_error.cc
@@ -624,7 +624,7 @@ void GetSuggestionsSummaryList(int error_code,
return;
if (IsOnlySuggestion(suggestions, SUGGEST_CONTACT_ADMINISTRATOR)) {
- DCHECK(suggestions_summary_list->empty());
+ DCHECK(suggestions_summary_list->GetList().empty());
DCHECK(!(suggestions & ~SUGGEST_CONTACT_ADMINISTRATOR));
AddSingleEntryDictionaryToList(suggestions_summary_list, "summary",
IDS_ERRORPAGES_SUGGESTION_CONTACT_ADMIN_SUMMARY_STANDALONE, false);
@@ -636,7 +636,7 @@ void GetSuggestionsSummaryList(int error_code,
}
if (IsOnlySuggestion(suggestions, SUGGEST_COMPLETE_SETUP)) {
- DCHECK(suggestions_summary_list->empty());
+ DCHECK(suggestions_summary_list->GetList().empty());
DCHECK(!(suggestions & ~SUGGEST_COMPLETE_SETUP));
AddSingleEntryDictionaryToList(suggestions_summary_list, "summary",
IDS_ERRORPAGES_SUGGESTION_DIAGNOSE_CONNECTION_SUMMARY, false);
@@ -647,7 +647,7 @@ void GetSuggestionsSummaryList(int error_code,
DCHECK(!IsSuggested(suggestions, SUGGEST_COMPLETE_SETUP));
if (IsOnlySuggestion(suggestions,SUGGEST_REPOST_RELOAD)) {
- DCHECK(suggestions_summary_list->empty());
+ DCHECK(suggestions_summary_list->GetList().empty());
DCHECK(!(suggestions & ~SUGGEST_REPOST_RELOAD));
// If the page was created by a post, it can't be reloaded in the same
// way, so just add a suggestion instead.
@@ -660,7 +660,7 @@ void GetSuggestionsSummaryList(int error_code,
DCHECK(!IsSuggested(suggestions, SUGGEST_REPOST_RELOAD));
if (IsOnlySuggestion(suggestions, SUGGEST_NAVIGATE_TO_ORIGIN)) {
- DCHECK(suggestions_summary_list->empty());
+ DCHECK(suggestions_summary_list->GetList().empty());
DCHECK(!(suggestions & ~SUGGEST_NAVIGATE_TO_ORIGIN));
url::Origin failed_origin = url::Origin::Create(failed_url);
if (failed_origin.opaque())
@@ -677,7 +677,7 @@ void GetSuggestionsSummaryList(int error_code,
DCHECK(!IsSuggested(suggestions, SUGGEST_NAVIGATE_TO_ORIGIN));
if (IsOnlySuggestion(suggestions, SUGGEST_LEARNMORE)) {
- DCHECK(suggestions_summary_list->empty());
+ DCHECK(suggestions_summary_list->GetList().empty());
AddLinkedSuggestionToList(error_code, locale, suggestions_summary_list,
true);
return;
@@ -688,7 +688,7 @@ void GetSuggestionsSummaryList(int error_code,
}
if (suggestions & SUGGEST_DISABLE_EXTENSION) {
- DCHECK(suggestions_summary_list->empty());
+ DCHECK(suggestions_summary_list->GetList().empty());
AddSingleEntryDictionaryToList(suggestions_summary_list, "summary",
IDS_ERRORPAGES_SUGGESTION_DISABLE_EXTENSION_SUMMARY, false);
return;
@@ -928,6 +928,9 @@ LocalizedError::PageState LocalizedError::GetPageState(
result.strings.SetString(
"dinoGameA11yStartGame",
l10n_util::GetStringUTF16(IDS_ERRORPAGE_DINO_GAME_START));
+ result.strings.SetString(
+ "dinoGameA11ySpeedToggle",
+ l10n_util::GetStringUTF16(IDS_ERRORPAGE_DINO_SLOW_SPEED_TOGGLE));
if (EnableAltGameMode()) {
result.strings.SetBoolean("enableAltGameMode", true);
diff --git a/chromium/components/error_page/content/browser/net_error_auto_reloader.h b/chromium/components/error_page/content/browser/net_error_auto_reloader.h
index 2b82abf0fcf..cea28834560 100644
--- a/chromium/components/error_page/content/browser/net_error_auto_reloader.h
+++ b/chromium/components/error_page/content/browser/net_error_auto_reloader.h
@@ -11,7 +11,6 @@
#include <set>
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/public/browser/web_contents_observer.h"
@@ -19,6 +18,7 @@
#include "net/base/net_errors.h"
#include "services/network/public/cpp/network_connection_tracker.h"
#include "services/network/public/mojom/network_change_manager.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace content {
@@ -72,7 +72,7 @@ class NetErrorAutoReloader
// Returns the timer used internally to schedule the next auto-reload task,
// or null if no auto-reload task is currently scheduled.
- base::Optional<base::OneShotTimer>& next_reload_timer_for_testing() {
+ absl::optional<base::OneShotTimer>& next_reload_timer_for_testing() {
return next_reload_timer_;
}
@@ -103,8 +103,8 @@ class NetErrorAutoReloader
network::NetworkConnectionTracker* connection_tracker_;
bool is_online_ = true;
std::set<content::NavigationHandle*> pending_navigations_;
- base::Optional<base::OneShotTimer> next_reload_timer_;
- base::Optional<ErrorPageInfo> current_reloadable_error_page_info_;
+ absl::optional<base::OneShotTimer> next_reload_timer_;
+ absl::optional<ErrorPageInfo> current_reloadable_error_page_info_;
size_t num_reloads_for_current_error_ = 0;
bool is_auto_reload_in_progress_ = false;
base::WeakPtrFactory<NetErrorAutoReloader> weak_ptr_factory_{this};
diff --git a/chromium/components/error_page/content/browser/net_error_auto_reloader_browsertest.cc b/chromium/components/error_page/content/browser/net_error_auto_reloader_browsertest.cc
index 91d2f26cceb..4006adc0d7c 100644
--- a/chromium/components/error_page/content/browser/net_error_auto_reloader_browsertest.cc
+++ b/chromium/components/error_page/content/browser/net_error_auto_reloader_browsertest.cc
@@ -7,7 +7,6 @@
#include <memory>
#include <utility>
-#include "base/optional.h"
#include "base/test/bind.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/web_contents.h"
@@ -22,6 +21,7 @@
#include "content/shell/browser/shell_content_browser_client.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace error_page {
@@ -187,11 +187,11 @@ class NetErrorAutoReloaderBrowserTest : public content::ContentBrowserTest {
// Returns the time-delay of the currently scheduled auto-reload task, if one
// is scheduled. If no auto-reload is scheduled, this returns null.
- base::Optional<base::TimeDelta> GetCurrentAutoReloadDelay() {
- const base::Optional<base::OneShotTimer>& timer =
+ absl::optional<base::TimeDelta> GetCurrentAutoReloadDelay() {
+ const absl::optional<base::OneShotTimer>& timer =
GetAutoReloader()->next_reload_timer_for_testing();
if (!timer)
- return base::nullopt;
+ return absl::nullopt;
return timer->GetCurrentDelay();
}
@@ -200,7 +200,7 @@ class NetErrorAutoReloaderBrowserTest : public content::ContentBrowserTest {
// logic without waiting a long time or painfully messing around with mock
// time in browser tests.
void ForceScheduledAutoReloadNow() {
- base::Optional<base::OneShotTimer>& timer =
+ absl::optional<base::OneShotTimer>& timer =
GetAutoReloader()->next_reload_timer_for_testing();
if (timer && timer->IsRunning())
timer->FireNow();
@@ -240,7 +240,7 @@ class NetErrorAutoReloaderBrowserTest : public content::ContentBrowserTest {
// A successful navigation results in no auto-reload being scheduled.
IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest, NoError) {
EXPECT_TRUE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
// A normal error page triggers a scheduled reload.
@@ -268,7 +268,7 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest, ErrorRecovery) {
EXPECT_TRUE(navigation.was_successful());
// No new auto-reload scheduled.
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
// An auto-reload that fails in the same way as the original navigation will
@@ -362,7 +362,7 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest, StopCancelsAutoReload) {
/*extra_headers=*/std::string());
EXPECT_TRUE(navigation.WaitForRequestStart());
shell()->web_contents()->Stop();
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
// Various specific types of network-layer errors do not trigger auto-reload.
@@ -372,42 +372,42 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
NetErrorUrlInterceptor interceptor(GetTestUrl(),
net::ERR_UNKNOWN_URL_SCHEME);
EXPECT_FALSE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
{
NetErrorUrlInterceptor interceptor(GetTestUrl(),
net::ERR_BAD_SSL_CLIENT_AUTH_CERT);
EXPECT_FALSE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
{
NetErrorUrlInterceptor interceptor(GetTestUrl(), net::ERR_CERT_INVALID);
EXPECT_FALSE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
{
NetErrorUrlInterceptor interceptor(GetTestUrl(),
net::ERR_SSL_PROTOCOL_ERROR);
EXPECT_FALSE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
{
NetErrorUrlInterceptor interceptor(GetTestUrl(),
net::ERR_BLOCKED_BY_CLIENT);
EXPECT_FALSE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
{
NetErrorUrlInterceptor interceptor(GetTestUrl(),
net::ERR_BLOCKED_BY_ADMINISTRATOR);
EXPECT_FALSE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
{
NetErrorUrlInterceptor interceptor(GetTestUrl(),
net::ERR_INVALID_AUTH_CREDENTIALS);
EXPECT_FALSE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
}
@@ -418,14 +418,14 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
const GURL kTestDataUrl{"data://whatever"};
NetErrorUrlInterceptor interceptor(kTestDataUrl, net::ERR_ACCESS_DENIED);
EXPECT_FALSE(NavigateMainFrame(kTestDataUrl));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
{
const GURL kTestFileUrl{"file://whatever"};
NetErrorUrlInterceptor interceptor(kTestFileUrl, net::ERR_ACCESS_DENIED);
EXPECT_FALSE(NavigateMainFrame(kTestFileUrl));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
}
@@ -447,7 +447,7 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
GetTestUrl(), content::Referrer(), ui::PAGE_TRANSITION_TYPED,
/*extra_headers=*/std::string());
deferrer.WaitForNextNavigationToBeDeferred();
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
// Now cancel the deferred navigation and observe that auto-reload for the
// error page is rescheduled.
@@ -463,7 +463,7 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
// This would normally schedule an auto-reload, but we're offline.
NetErrorUrlInterceptor interceptor(GetTestUrl(), net::ERR_CONNECTION_RESET);
EXPECT_FALSE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
// If the browser comes online while sitting at an error page that supports
@@ -475,7 +475,7 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
// This would normally schedule an auto-reload, but we're offline.
NetErrorUrlInterceptor interceptor(GetTestUrl(), net::ERR_CONNECTION_RESET);
EXPECT_FALSE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
SimulateNetworkGoingOnline();
EXPECT_EQ(GetDelayForReloadCount(0), GetCurrentAutoReloadDelay());
@@ -486,13 +486,13 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
NoAutoReloadOnNonErrorPageWhenBrowserComesOnline) {
EXPECT_TRUE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
SimulateNetworkGoingOffline();
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
SimulateNetworkGoingOnline();
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
// Auto-reload is not scheduled when the WebContents are hidden.
@@ -504,7 +504,7 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
// Hiding the contents cancels the scheduled auto-reload.
shell()->web_contents()->WasHidden();
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
// If the WebContents becomes visible while sitting at an error page that
@@ -517,7 +517,7 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
// Hiding the contents cancels the scheduled auto-reload.
shell()->web_contents()->WasHidden();
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
// Becoming visible again reschedules auto-reload.
shell()->web_contents()->WasShown();
@@ -529,13 +529,13 @@ IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
IN_PROC_BROWSER_TEST_F(NetErrorAutoReloaderBrowserTest,
NoAutoReloadOnNonErrorPageWhenContentsBecomeVisible) {
EXPECT_TRUE(NavigateMainFrame(GetTestUrl()));
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
shell()->web_contents()->WasHidden();
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
shell()->web_contents()->WasShown();
- EXPECT_EQ(base::nullopt, GetCurrentAutoReloadDelay());
+ EXPECT_EQ(absl::nullopt, GetCurrentAutoReloadDelay());
}
} // namespace
diff --git a/chromium/components/error_page_strings.grdp b/chromium/components/error_page_strings.grdp
index 4c09565a2f9..2d96432ce72 100644
--- a/chromium/components/error_page_strings.grdp
+++ b/chromium/components/error_page_strings.grdp
@@ -397,4 +397,7 @@
<message name="IDS_ERRORPAGE_DINO_JUMP" desc="Message to be spoken by a screen reader while the dino game is running to tell the user to jump because an obstacle is near.">
Jump!
</message>
+ <message name="IDS_ERRORPAGE_DINO_SLOW_SPEED_TOGGLE" desc="Label for a toggle which allows a user to select a slower speed for the dino game.">
+ Start slower
+ </message>
</grit-part>
diff --git a/chromium/components/error_page_strings_grdp/IDS_ERRORPAGE_DINO_SLOW_SPEED_TOGGLE.png.sha1 b/chromium/components/error_page_strings_grdp/IDS_ERRORPAGE_DINO_SLOW_SPEED_TOGGLE.png.sha1
new file mode 100644
index 00000000000..af61812240a
--- /dev/null
+++ b/chromium/components/error_page_strings_grdp/IDS_ERRORPAGE_DINO_SLOW_SPEED_TOGGLE.png.sha1
@@ -0,0 +1 @@
+1fd277f722ecd0a83b5f711d8b52c8cf6fdbbe21 \ No newline at end of file
diff --git a/chromium/components/exo/BUILD.gn b/chromium/components/exo/BUILD.gn
index 9d0858a910b..c6235bfb012 100644
--- a/chromium/components/exo/BUILD.gn
+++ b/chromium/components/exo/BUILD.gn
@@ -133,6 +133,9 @@ static_library("exo") {
"//chromeos/crosapi/cpp",
"//chromeos/ui/base",
"//chromeos/ui/frame",
+ "//components/full_restore",
+ "//components/fullscreen_control",
+ "//components/strings",
"//ui/base",
"//ui/events/ozone/layout",
]
@@ -170,8 +173,6 @@ static_library("exo") {
"toast_surface.cc",
"toast_surface.h",
"toast_surface_manager.h",
- "ui_lock_bubble.cc",
- "ui_lock_bubble.h",
"ui_lock_controller.cc",
"ui_lock_controller.h",
"wm_helper_chromeos.cc",
@@ -306,6 +307,7 @@ source_set("unit_tests") {
"seat_unittest.cc",
"shared_memory_unittest.cc",
"shell_surface_unittest.cc",
+ "shell_surface_util_unittest.cc",
"sub_surface_unittest.cc",
"surface_unittest.cc",
"text_input_unittest.cc",
@@ -326,10 +328,12 @@ source_set("unit_tests") {
"//build:chromeos_buildflags",
"//chromeos/ui/base",
"//chromeos/ui/frame",
+ "//components/fullscreen_control",
"//ui/base:test_support",
"//ui/base/cursor/mojom:cursor_type",
"//ui/base/dragdrop:types",
"//ui/base/dragdrop/mojom",
+ "//ui/gfx:test_support",
"//ui/gfx/geometry",
]
}
diff --git a/chromium/components/exo/DEPS b/chromium/components/exo/DEPS
index b46bea3ae5a..43bccd772b1 100644
--- a/chromium/components/exo/DEPS
+++ b/chromium/components/exo/DEPS
@@ -4,6 +4,9 @@ include_rules = [
"+chromeos/crosapi/cpp/crosapi_constants.h",
"+chromeos/ui/base",
"+chromeos/ui/frame",
+ "+components/fullscreen_control",
+ "+components/full_restore",
+ "+components/strings",
"+components/viz/common",
"+components/viz/host",
"+device/gamepad",
diff --git a/chromium/components/exo/OWNERS b/chromium/components/exo/OWNERS
index 19eabafd78f..af708f9e1e9 100644
--- a/chromium/components/exo/OWNERS
+++ b/chromium/components/exo/OWNERS
@@ -1,10 +1,8 @@
oshima@chromium.org
-# For Input (keyboard, mouse, touch)
+# For Input (keyboard, mouse, touch, data_device)
mukai@chromium.org
-
-# For graphics (surface/buffer change)
-malaykeshav@chromium.org
+yhanada@chromium.org
# Not working on chromium anymore, but kept just in case we need his review.
dcastagna@chromium.org
diff --git a/chromium/components/exo/buffer.cc b/chromium/components/exo/buffer.cc
index 3378df0b285..8a5fdcf48e0 100644
--- a/chromium/components/exo/buffer.cc
+++ b/chromium/components/exo/buffer.cc
@@ -24,7 +24,6 @@
#include "components/viz/common/resources/resource_format.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/resources/resource_id.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/raster_interface.h"
diff --git a/chromium/components/exo/buffer_unittest.cc b/chromium/components/exo/buffer_unittest.cc
index 97c5bef4a84..d9ac18dc613 100644
--- a/chromium/components/exo/buffer_unittest.cc
+++ b/chromium/components/exo/buffer_unittest.cc
@@ -14,12 +14,12 @@
#include "components/exo/test/exo_test_base.h"
#include "components/exo/test/exo_test_helper.h"
#include "components/viz/common/gpu/context_provider.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "gpu/command_buffer/client/raster_interface.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/env.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/test/in_process_context_provider.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/gpu_memory_buffer.h"
namespace exo {
@@ -68,12 +68,11 @@ TEST_F(BufferTest, ReleaseCallback) {
ASSERT_TRUE(rv);
// Release buffer.
- viz::ReturnedResource returned_resource;
- returned_resource.id = resource.id;
- returned_resource.sync_token = resource.mailbox_holder.sync_token;
- returned_resource.lost = false;
- std::vector<viz::ReturnedResource> resources = {returned_resource};
- frame_sink_holder->ReclaimResources(resources);
+ std::vector<viz::ReturnedResource> resources;
+ resources.emplace_back(resource.id, resource.mailbox_holder.sync_token,
+ /*release_fence=*/gfx::GpuFenceHandle(),
+ /*count=*/0, /*lost=*/false);
+ frame_sink_holder->ReclaimResources(std::move(resources));
base::RunLoop().RunUntilIdle();
ASSERT_EQ(release_call_count, 0);
@@ -110,13 +109,11 @@ TEST_F(BufferTest, IsLost) {
}
// Release buffer.
- bool is_lost = true;
- viz::ReturnedResource returned_resource;
- returned_resource.id = resource.id;
- returned_resource.sync_token = gpu::SyncToken();
- returned_resource.lost = is_lost;
- std::vector<viz::ReturnedResource> resources = {returned_resource};
- frame_sink_holder->ReclaimResources(resources);
+ std::vector<viz::ReturnedResource> resources;
+ resources.emplace_back(resource.id, gpu::SyncToken(),
+ /*release_fence=*/gfx::GpuFenceHandle(),
+ /*count=*/0, /*lost=*/true);
+ frame_sink_holder->ReclaimResources(std::move(resources));
base::RunLoop().RunUntilIdle();
// Producing a new texture transferable resource for the contents of the
@@ -127,12 +124,11 @@ TEST_F(BufferTest, IsLost) {
ASSERT_TRUE(rv);
buffer->OnDetach();
- viz::ReturnedResource returned_resource2;
- returned_resource2.id = new_resource.id;
- returned_resource2.sync_token = gpu::SyncToken();
- returned_resource2.lost = false;
- std::vector<viz::ReturnedResource> resources2 = {returned_resource2};
- frame_sink_holder->ReclaimResources(resources2);
+ std::vector<viz::ReturnedResource> resources2;
+ resources2.emplace_back(new_resource.id, gpu::SyncToken(),
+ /*release_fence=*/gfx::GpuFenceHandle(),
+ /*count=*/0, /*lost=*/false);
+ frame_sink_holder->ReclaimResources(std::move(resources2));
base::RunLoop().RunUntilIdle();
}
@@ -258,13 +254,11 @@ TEST_F(BufferTest, SurfaceTreeHostLastFrame) {
// Try to release buffer in last frame. This can happen during a resize
// when frame sink id changes.
- viz::ReturnedResource returned_resource;
- returned_resource.id = resource.id;
- returned_resource.sync_token = resource.mailbox_holder.sync_token;
- returned_resource.lost = false;
-
- std::vector<viz::ReturnedResource> resources = {returned_resource};
- frame_sink_holder->ReclaimResources(resources);
+ std::vector<viz::ReturnedResource> resources;
+ resources.emplace_back(resource.id, resource.mailbox_holder.sync_token,
+ /*release_fence=*/gfx::GpuFenceHandle(),
+ /*count=*/0, /*lost=*/false);
+ frame_sink_holder->ReclaimResources(std::move(resources));
}
base::RunLoop().RunUntilIdle();
diff --git a/chromium/components/exo/client_controlled_shell_surface.cc b/chromium/components/exo/client_controlled_shell_surface.cc
index 2efee6195ef..a511ea49e43 100644
--- a/chromium/components/exo/client_controlled_shell_surface.cc
+++ b/chromium/components/exo/client_controlled_shell_surface.cc
@@ -16,6 +16,7 @@
#include "ash/public/cpp/window_backdrop.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/root_window_controller.h"
+#include "ash/screen_util.h"
#include "ash/shell.h"
#include "ash/wm/client_controlled_state.h"
#include "ash/wm/collision_detection/collision_detection_utils.h"
@@ -61,10 +62,12 @@
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/core/window_util.h"
+DEFINE_UI_CLASS_PROPERTY_TYPE(exo::ClientControlledShellSurface*)
+
namespace exo {
namespace {
-
+using ::ash::screen_util::GetIdealBoundsForMaximizedOrFullscreenOrPinnedState;
using ::chromeos::WindowStateType;
// Client controlled specific accelerators.
@@ -473,7 +476,7 @@ void ClientControlledShellSurface::SetShadowBounds(const gfx::Rect& bounds) {
TRACE_EVENT1("exo", "ClientControlledShellSurface::SetShadowBounds", "bounds",
bounds.ToString());
auto shadow_bounds =
- bounds.IsEmpty() ? base::nullopt : base::make_optional(bounds);
+ bounds.IsEmpty() ? absl::nullopt : absl::make_optional(bounds);
if (shadow_bounds_ != shadow_bounds) {
shadow_bounds_ = shadow_bounds;
shadow_bounds_changed_ = true;
@@ -634,6 +637,16 @@ void ClientControlledShellSurface::SetClientAccessibilityId(
}
}
+void ClientControlledShellSurface::RebindRootSurface(
+ Surface* root_surface,
+ bool can_minimize,
+ int container,
+ bool default_scale_cancellation) {
+ current_pin_ = chromeos::WindowPinType::kNone;
+ use_default_scale_cancellation_ = default_scale_cancellation;
+ ShellSurfaceBase::RebindRootSurface(root_surface, can_minimize, container);
+}
+
void ClientControlledShellSurface::DidReceiveCompositorFrameAck() {
orientation_ = pending_orientation_;
// Unlock the compositor after the frame is received by viz so that
@@ -682,7 +695,7 @@ void ClientControlledShellSurface::OnBoundsChangeEvent(
if (server_reparent_window_ &&
window_state->GetDisplay().id() != display_id) {
ScopedSetBoundsLocally scoped_set_bounds(this);
- int container_id = window_state->window()->parent()->id();
+ int container_id = window_state->window()->parent()->GetId();
aura::Window* new_parent =
ash::Shell::GetRootWindowControllerWithDisplayId(display_id)
->GetContainer(container_id);
@@ -963,8 +976,11 @@ void ClientControlledShellSurface::SetWidgetBounds(const gfx::Rect& bounds) {
// Calculate a minimum window visibility required bounds.
gfx::Rect adjusted_bounds = bounds;
if (!is_display_move_pending) {
+ const gfx::Rect& restriction = GetWindowState()->IsFullscreen()
+ ? target_display.bounds()
+ : target_display.work_area();
ash::ClientControlledState::AdjustBoundsForMinimumWindowVisibility(
- target_display.work_area(), &adjusted_bounds);
+ restriction, &adjusted_bounds);
// Collision detection to the bounds set by Android should be applied only
// to initial bounds. Do not adjust new bounds as it can be obsolete or in
// transit during animation, which results in incorrect resting postiion.
@@ -1024,7 +1040,8 @@ void ClientControlledShellSurface::SetWidgetBounds(const gfx::Rect& bounds) {
gfx::Rect ClientControlledShellSurface::GetShadowBounds() const {
gfx::Rect shadow_bounds = ShellSurfaceBase::GetShadowBounds();
const ash::NonClientFrameViewAsh* frame_view = GetFrameView();
- if (frame_view->GetVisible()) {
+ if (frame_view->GetFrameEnabled() && !shadow_bounds_->IsEmpty() &&
+ !geometry_.IsEmpty()) {
// The client controlled geometry is only for the client
// area. When the chrome side frame is enabled, the shadow height
// has to include the height of the frame, and the total height is
@@ -1080,10 +1097,10 @@ float ClientControlledShellSurface::GetScale() const {
return scale_;
}
-base::Optional<gfx::Rect> ClientControlledShellSurface::GetWidgetBounds()
+absl::optional<gfx::Rect> ClientControlledShellSurface::GetWidgetBounds()
const {
const ash::NonClientFrameViewAsh* frame_view = GetFrameView();
- if (frame_view->GetVisible()) {
+ if (frame_view->GetFrameEnabled()) {
gfx::Rect visible_bounds = ShellSurfaceBase::GetVisibleBounds();
if (widget_->IsMaximized() && frame_type_ == SurfaceFrameType::NORMAL) {
// When the widget is maximized in clamshell mode, client sends
@@ -1256,15 +1273,15 @@ void ClientControlledShellSurface::OnContentSizeChanged(Surface* surface) {
void ClientControlledShellSurface::UpdateFrame() {
if (!widget_)
return;
- gfx::Rect work_area =
- display::Screen::GetScreen()
- ->GetDisplayNearestWindow(widget_->GetNativeWindow())
- .work_area();
-
ash::WindowState* window_state = GetWindowState();
- bool enable_wide_frame = GetFrameView()->GetVisible() &&
- window_state->IsMaximizedOrFullscreenOrPinned() &&
- work_area.width() != geometry().width();
+ bool enable_wide_frame = false;
+ if (GetFrameView()->GetFrameEnabled() &&
+ window_state->IsMaximizedOrFullscreenOrPinned()) {
+ gfx::Rect ideal_bounds =
+ GetIdealBoundsForMaximizedOrFullscreenOrPinnedState(
+ widget_->GetNativeWindow());
+ enable_wide_frame = ideal_bounds.width() != geometry().width();
+ }
bool update_frame = state_changed_;
state_changed_ = false;
if (enable_wide_frame) {
diff --git a/chromium/components/exo/client_controlled_shell_surface.h b/chromium/components/exo/client_controlled_shell_surface.h
index 03794afbca4..4da8da0fcd0 100644
--- a/chromium/components/exo/client_controlled_shell_surface.h
+++ b/chromium/components/exo/client_controlled_shell_surface.h
@@ -184,6 +184,12 @@ class ClientControlledShellSurface : public ShellSurfaceBase,
// |accessibility_id| is negative value, it will unset the ID.
void SetClientAccessibilityId(int32_t accessibility_id);
+ // Rebind a surface as the root surface of the shell surface.
+ void RebindRootSurface(Surface* root_surface,
+ bool can_minimize,
+ int container,
+ bool default_scale_cancellation);
+
// Overridden from SurfaceTreeHost:
void DidReceiveCompositorFrameAck() override;
@@ -246,6 +252,8 @@ class ClientControlledShellSurface : public ShellSurfaceBase,
float GetScale() const override;
private:
+ FRIEND_TEST_ALL_PREFIXES(ClientControlledShellSurfaceTest,
+ OverlayShadowBounds);
class ScopedSetBoundsLocally;
class ScopedLockedToRoot;
@@ -253,7 +261,7 @@ class ClientControlledShellSurface : public ShellSurfaceBase,
void SetWidgetBounds(const gfx::Rect& bounds) override;
gfx::Rect GetShadowBounds() const override;
void InitializeWindowState(ash::WindowState* window_state) override;
- base::Optional<gfx::Rect> GetWidgetBounds() const override;
+ absl::optional<gfx::Rect> GetWidgetBounds() const override;
gfx::Point GetSurfaceOrigin() const override;
bool OnPreWidgetCommit() override;
void OnPostWidgetCommit() override;
@@ -368,7 +376,7 @@ class ClientControlledShellSurface : public ShellSurfaceBase,
std::unique_ptr<ClientControlledAcceleratorTarget> accelerator_target_;
// Accessibility ID provided by client.
- base::Optional<int32_t> client_accessibility_id_;
+ absl::optional<int32_t> client_accessibility_id_;
bool pending_resize_lock_ = false;
diff --git a/chromium/components/exo/client_controlled_shell_surface_unittest.cc b/chromium/components/exo/client_controlled_shell_surface_unittest.cc
index dc4756c4a80..8542f1a3820 100644
--- a/chromium/components/exo/client_controlled_shell_surface_unittest.cc
+++ b/chromium/components/exo/client_controlled_shell_surface_unittest.cc
@@ -9,9 +9,12 @@
#include "ash/frame/non_client_frame_view_ash.h"
#include "ash/frame/wide_frame_view.h"
#include "ash/public/cpp/ash_features.h"
+#include "ash/public/cpp/shelf_types.h"
#include "ash/public/cpp/test/shell_test_api.h"
+#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/system/unified/unified_system_tray.h"
+#include "ash/test/test_widget_builder.h"
#include "ash/wm/drag_window_resizer.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/pip/pip_positioner.h"
@@ -52,6 +55,7 @@
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_targeter.h"
#include "ui/aura/window_tree_host.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/compositor_extra/shadow.h"
@@ -517,7 +521,7 @@ TEST_F(ClientControlledShellSurfaceTest, Frame) {
// Normal state.
widget->LayoutRootViewIfNecessary();
- EXPECT_TRUE(frame_view->GetVisible());
+ EXPECT_TRUE(frame_view->GetFrameEnabled());
EXPECT_EQ(normal_window_bounds, widget->GetWindowBoundsInScreen());
EXPECT_EQ(client_bounds,
frame_view->GetClientBoundsForWindowBounds(normal_window_bounds));
@@ -528,7 +532,7 @@ TEST_F(ClientControlledShellSurfaceTest, Frame) {
surface->Commit();
widget->LayoutRootViewIfNecessary();
- EXPECT_TRUE(frame_view->GetVisible());
+ EXPECT_TRUE(frame_view->GetFrameEnabled());
EXPECT_EQ(fullscreen_bounds, widget->GetWindowBoundsInScreen());
EXPECT_EQ(
gfx::Size(800, 568),
@@ -541,7 +545,7 @@ TEST_F(ClientControlledShellSurfaceTest, Frame) {
surface->Commit();
widget->LayoutRootViewIfNecessary();
- EXPECT_TRUE(frame_view->GetVisible());
+ EXPECT_TRUE(frame_view->GetFrameEnabled());
EXPECT_EQ(gfx::Rect(0, 200, 800, 400), widget->GetWindowBoundsInScreen());
display_manager->UpdateWorkAreaOfDisplay(display_id, gfx::Insets(0, 0, 0, 0));
@@ -552,7 +556,7 @@ TEST_F(ClientControlledShellSurfaceTest, Frame) {
surface->Commit();
widget->LayoutRootViewIfNecessary();
- EXPECT_TRUE(frame_view->GetVisible());
+ EXPECT_TRUE(frame_view->GetFrameEnabled());
EXPECT_EQ(fullscreen_bounds, widget->GetWindowBoundsInScreen());
EXPECT_EQ(fullscreen_bounds,
frame_view->GetClientBoundsForWindowBounds(fullscreen_bounds));
@@ -562,7 +566,7 @@ TEST_F(ClientControlledShellSurfaceTest, Frame) {
surface->Commit();
widget->LayoutRootViewIfNecessary();
- EXPECT_TRUE(frame_view->GetVisible());
+ EXPECT_TRUE(frame_view->GetFrameEnabled());
EXPECT_EQ(fullscreen_bounds, widget->GetWindowBoundsInScreen());
EXPECT_EQ(fullscreen_bounds,
frame_view->GetClientBoundsForWindowBounds(fullscreen_bounds));
@@ -587,7 +591,7 @@ TEST_F(ClientControlledShellSurfaceTest, Frame) {
surface->Commit();
widget->LayoutRootViewIfNecessary();
- EXPECT_TRUE(frame_view->GetVisible());
+ EXPECT_TRUE(frame_view->GetFrameEnabled());
EXPECT_EQ(normal_window_bounds, widget->GetWindowBoundsInScreen());
EXPECT_EQ(client_bounds,
frame_view->GetClientBoundsForWindowBounds(normal_window_bounds));
@@ -599,7 +603,7 @@ TEST_F(ClientControlledShellSurfaceTest, Frame) {
surface->Commit();
widget->LayoutRootViewIfNecessary();
- EXPECT_FALSE(frame_view->GetVisible());
+ EXPECT_FALSE(frame_view->GetFrameEnabled());
EXPECT_EQ(client_bounds, widget->GetWindowBoundsInScreen());
EXPECT_EQ(client_bounds,
frame_view->GetClientBoundsForWindowBounds(client_bounds));
@@ -611,14 +615,14 @@ TEST_F(ClientControlledShellSurfaceTest, Frame) {
surface->Commit();
widget->LayoutRootViewIfNecessary();
- EXPECT_TRUE(frame_view->GetVisible());
+ EXPECT_TRUE(frame_view->GetFrameEnabled());
EXPECT_TRUE(frame_view->GetHeaderView()->in_immersive_mode());
surface->SetFrame(SurfaceFrameType::NONE);
surface->Commit();
widget->LayoutRootViewIfNecessary();
- EXPECT_FALSE(frame_view->GetVisible());
+ EXPECT_FALSE(frame_view->GetFrameEnabled());
EXPECT_FALSE(frame_view->GetHeaderView()->in_immersive_mode());
}
@@ -1016,7 +1020,7 @@ TEST_F(ClientControlledShellSurfaceTest,
EXPECT_FALSE(shell_surface->GetWidget()->widget_delegate()->CanResize());
}
-// The shell surface in SystemModal container should not become target
+// The shell surface in SystemModal container should be a target
// at the edge.
TEST_F(ClientControlledShellSurfaceTest, ShellSurfaceInSystemModalHitTest) {
std::unique_ptr<Surface> surface(new Surface);
@@ -1042,7 +1046,7 @@ TEST_F(ClientControlledShellSurfaceTest, ShellSurfaceInSystemModalHitTest) {
aura::WindowTargeter targeter;
aura::Window* found =
static_cast<aura::Window*>(targeter.FindTargetForEvent(root, &event));
- EXPECT_FALSE(window->Contains(found));
+ EXPECT_TRUE(window->Contains(found));
}
// Test the snap functionalities in splitscreen in tablet mode.
@@ -1635,22 +1639,74 @@ TEST_F(ClientControlledShellSurfaceTest, WideFrame) {
new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(gfx::Size(64, 64))));
surface->Attach(desktop_buffer.get());
surface->SetInputRegion(gfx::Rect(0, 0, 64, 64));
- shell_surface->SetGeometry(gfx::Rect(0, 0, 64, 64));
+ shell_surface->SetGeometry(gfx::Rect(100, 0, 64, 64));
shell_surface->SetMaximized();
surface->SetFrame(SurfaceFrameType::NORMAL);
surface->Commit();
+ aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
+ ash::Shelf* shelf = ash::Shelf::ForWindow(window);
+ shelf->SetAlignment(ash::ShelfAlignment::kLeft);
+
+ const gfx::Rect work_area =
+ display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
+ const gfx::Rect display_bounds =
+ display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
+ ASSERT_TRUE(work_area.x() != display_bounds.x());
+
auto* wide_frame = shell_surface->wide_frame_for_test();
ASSERT_TRUE(wide_frame);
EXPECT_FALSE(wide_frame->header_view()->in_immersive_mode());
+ EXPECT_EQ(work_area.x(), wide_frame->GetBoundsInScreen().x());
+ EXPECT_EQ(work_area.width(), wide_frame->GetBoundsInScreen().width());
- // Check targeter is still CustomWindowTargeter.
- aura::Window* window = shell_surface->GetWidget()->GetNativeWindow();
+ auto another_window = ash::TestWidgetBuilder().BuildOwnsNativeWidget();
+ another_window->SetFullscreen(true);
+
+ // Make sure that the wide frame stays in maximzied size even if there is
+ // active fullscreen window.
+ EXPECT_EQ(work_area.x(), wide_frame->GetBoundsInScreen().x());
+ EXPECT_EQ(work_area.width(), wide_frame->GetBoundsInScreen().width());
+
+ shell_surface->Activate();
+
+ EXPECT_EQ(work_area.x(), wide_frame->GetBoundsInScreen().x());
+ EXPECT_EQ(work_area.width(), wide_frame->GetBoundsInScreen().width());
+
+ // If the shelf is set to auto hide by a user, use the display bounds.
+ ash::Shelf::ForWindow(window)->SetAutoHideBehavior(
+ ash::ShelfAutoHideBehavior::kAlways);
+ EXPECT_EQ(display_bounds.x(), wide_frame->GetBoundsInScreen().x());
+ EXPECT_EQ(display_bounds.width(), wide_frame->GetBoundsInScreen().width());
+
+ ash::Shelf::ForWindow(window)->SetAutoHideBehavior(
+ ash::ShelfAutoHideBehavior::kNever);
+ EXPECT_EQ(work_area.x(), wide_frame->GetBoundsInScreen().x());
+ EXPECT_EQ(work_area.width(), wide_frame->GetBoundsInScreen().width());
+
+ shell_surface->SetFullscreen(true);
+ surface->Commit();
+ EXPECT_EQ(display_bounds.x(), wide_frame->GetBoundsInScreen().x());
+ EXPECT_EQ(display_bounds.width(), wide_frame->GetBoundsInScreen().width());
+ EXPECT_EQ(display_bounds,
+ display::Screen::GetScreen()->GetPrimaryDisplay().work_area());
+
+ // Activating maximized window should not affect the fullscreen shell
+ // surface's wide frame.
+ another_window->Activate();
+ another_window->SetFullscreen(false);
+ EXPECT_EQ(work_area,
+ display::Screen::GetScreen()->GetPrimaryDisplay().work_area());
+ EXPECT_EQ(display_bounds.x(), wide_frame->GetBoundsInScreen().x());
+ EXPECT_EQ(display_bounds.width(), wide_frame->GetBoundsInScreen().width());
+
+ another_window->Close();
+ // Check targeter is still CustomWindowTargeter.
ASSERT_TRUE(window->parent());
auto* custom_targeter = window->targeter();
- gfx::Point mouse_location(1, 50);
+ gfx::Point mouse_location(101, 50);
auto* root = window->GetRootWindow();
aura::WindowTargeter targeter;
@@ -2015,7 +2071,7 @@ TEST_F(ClientControlledShellSurfaceTest, SnappedInTabletMode) {
// Snapped window can also use auto hide.
surface->SetFrame(SurfaceFrameType::AUTOHIDE);
surface->Commit();
- EXPECT_TRUE(frame_view->GetVisible());
+ EXPECT_TRUE(frame_view->GetFrameEnabled());
EXPECT_TRUE(frame_view->GetHeaderView()->in_immersive_mode());
}
@@ -2703,4 +2759,36 @@ TEST_F(ClientControlledShellSurfaceTest,
}
}
+TEST_F(ClientControlledShellSurfaceTest, OverlayShadowBounds) {
+ gfx::Size buffer_size(1, 1);
+ std::unique_ptr<Buffer> buffer(
+ new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+ std::unique_ptr<Surface> surface(new Surface);
+ auto shell_surface =
+ exo_test_helper()->CreateClientControlledShellSurface(surface.get());
+ surface->Attach(buffer.get());
+ surface->Commit();
+
+ display::Display primary_display =
+ display::Screen::GetScreen()->GetPrimaryDisplay();
+ gfx::Rect initial_bounds(150, 10, 200, 200);
+ shell_surface->SetBounds(primary_display.id(), initial_bounds);
+ shell_surface->OnSetFrame(SurfaceFrameType::NORMAL);
+ surface->Commit();
+
+ EXPECT_FALSE(shell_surface->HasOverlay());
+
+ ShellSurfaceBase::OverlayParams params(std::make_unique<views::View>());
+ params.overlaps_frame = false;
+ shell_surface->AddOverlay(std::move(params));
+ EXPECT_TRUE(shell_surface->HasOverlay());
+
+ {
+ gfx::Size overlay_size =
+ shell_surface->GetWidget()->GetWindowBoundsInScreen().size();
+ gfx::Size shadow_size = shell_surface->GetShadowBounds().size();
+ EXPECT_EQ(shadow_size, overlay_size);
+ }
+}
+
} // namespace exo
diff --git a/chromium/components/exo/data_device.cc b/chromium/components/exo/data_device.cc
index 29e77c28839..eafc1583d69 100644
--- a/chromium/components/exo/data_device.cc
+++ b/chromium/components/exo/data_device.cc
@@ -4,6 +4,7 @@
#include "components/exo/data_device.h"
+#include "base/callback_helpers.h"
#include "base/run_loop.h"
#include "components/exo/data_device_delegate.h"
#include "components/exo/data_exchange_delegate.h"
@@ -165,6 +166,13 @@ DragOperation DataDevice::OnPerformDrop(const ui::DropTargetEvent& event) {
return DndActionToDragOperation(dnd_action);
}
+WMHelper::DropCallback DataDevice::GetDropCallback(
+ const ui::DropTargetEvent& event) {
+ // TODO(crbug.com/1197501): Return async drop callback.
+ NOTIMPLEMENTED();
+ return base::NullCallback();
+}
+
void DataDevice::OnClipboardDataChanged() {
if (!focused_surface_)
return;
diff --git a/chromium/components/exo/data_device.h b/chromium/components/exo/data_device.h
index 0f5191671dd..b8496ebc741 100644
--- a/chromium/components/exo/data_device.h
+++ b/chromium/components/exo/data_device.h
@@ -63,6 +63,8 @@ class DataDevice : public WMHelper::DragDropObserver,
void OnDragExited() override;
ui::mojom::DragOperation OnPerformDrop(
const ui::DropTargetEvent& event) override;
+ WMHelper::DropCallback GetDropCallback(
+ const ui::DropTargetEvent& event) override;
// Overridden from ui::ClipboardObserver:
void OnClipboardDataChanged() override;
diff --git a/chromium/components/exo/data_device_delegate.h b/chromium/components/exo/data_device_delegate.h
index 6120ff1f783..65053f80321 100644
--- a/chromium/components/exo/data_device_delegate.h
+++ b/chromium/components/exo/data_device_delegate.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_EXO_DATA_DEVICE_DELEGATE_H_
#define COMPONENTS_EXO_DATA_DEVICE_DELEGATE_H_
-#include <string>
-#include <vector>
-
#include "base/containers/flat_set.h"
#include "components/exo/data_offer.h"
diff --git a/chromium/components/exo/data_device_unittest.cc b/chromium/components/exo/data_device_unittest.cc
index f2fa00c84fa..75dfbf5079a 100644
--- a/chromium/components/exo/data_device_unittest.cc
+++ b/chromium/components/exo/data_device_unittest.cc
@@ -80,7 +80,7 @@ class TestDataDeviceDelegate : public DataDeviceDelegate {
}
DataOffer* OnDataOffer() override {
events_.push_back(DataEvent::kOffer);
- data_offer_.reset(new DataOffer(new TestDataOfferDelegate));
+ data_offer_ = std::make_unique<DataOffer>(new TestDataOfferDelegate);
return data_offer_.get();
}
void OnEnter(Surface* surface,
diff --git a/chromium/components/exo/data_exchange_delegate.h b/chromium/components/exo/data_exchange_delegate.h
index d7ef0de5f04..4bbd623d3b8 100644
--- a/chromium/components/exo/data_exchange_delegate.h
+++ b/chromium/components/exo/data_exchange_delegate.h
@@ -21,7 +21,7 @@ class RefCountedMemory;
} // namespace base
namespace ui {
-class Clipboard;
+class DataTransferEndpoint;
struct FileInfo;
enum class EndpointType;
} // namespace ui
@@ -75,11 +75,11 @@ class DataExchangeDelegate {
ui::EndpointType source,
const std::vector<uint8_t>& data) const = 0;
- // Reads clipboard custom data pickle for fs/sources with newline-separated
- // filesystem URLs to send to |target| endpoint.
- virtual std::vector<ui::FileInfo> ParseClipboardFilenamesPickle(
- const ui::EndpointType target,
- const ui::Clipboard& data) const = 0;
+ // Reads pickle for FilesApp fs/sources with newline-separated filesystem
+ // URLs. Validates that |source| is FilesApp.
+ virtual std::vector<ui::FileInfo> ParseFileSystemSources(
+ const ui::DataTransferEndpoint* source,
+ const base::Pickle& pickle) const = 0;
};
} // namespace exo
diff --git a/chromium/components/exo/data_offer.cc b/chromium/components/exo/data_offer.cc
index efbf44e3310..91d1f7a7e7b 100644
--- a/chromium/components/exo/data_offer.cc
+++ b/chromium/components/exo/data_offer.cc
@@ -50,9 +50,7 @@ constexpr char kUTF16[] = "utf16";
void WriteFileDescriptorOnWorkerThread(
base::ScopedFD fd,
scoped_refptr<base::RefCountedMemory> memory) {
- if (!base::WriteFileDescriptor(fd.get(),
- reinterpret_cast<const char*>(memory->front()),
- memory->size()))
+ if (!base::WriteFileDescriptor(fd.get(), *memory))
DLOG(ERROR) << "Failed to write drop data";
}
@@ -240,20 +238,28 @@ void DataOffer::SetDropData(DataExchangeDelegate* data_exchange_delegate,
data_exchange_delegate->GetDataTransferEndpointType(target);
const std::string uri_list_mime_type =
data_exchange_delegate->GetMimeTypeForUriList(endpoint_type);
- if (data.HasFile()) {
- std::vector<ui::FileInfo> files;
- if (data.GetFilenames(&files)) {
- data_callbacks_.emplace(
- uri_list_mime_type,
- base::BindOnce(&DataExchangeDelegate::SendFileInfo,
- base::Unretained(data_exchange_delegate),
- endpoint_type, std::move(files)));
- delegate_->OnOffer(uri_list_mime_type);
- return;
- }
+ // We accept the filenames pickle from FilesApp, or
+ // OSExchangeData::GetFilenames().
+ std::vector<ui::FileInfo> filenames;
+ base::Pickle pickle;
+ if (data.GetPickledData(ui::ClipboardFormatType::GetWebCustomDataType(),
+ &pickle)) {
+ filenames = data_exchange_delegate->ParseFileSystemSources(data.GetSource(),
+ pickle);
+ }
+ if (filenames.empty() && data.HasFile()) {
+ data.GetFilenames(&filenames);
+ }
+ if (!filenames.empty()) {
+ data_callbacks_.emplace(
+ uri_list_mime_type,
+ base::BindOnce(&DataExchangeDelegate::SendFileInfo,
+ base::Unretained(data_exchange_delegate), endpoint_type,
+ std::move(filenames)));
+ delegate_->OnOffer(uri_list_mime_type);
+ return;
}
- base::Pickle pickle;
if (data.GetPickledData(GetClipboardFormatType(), &pickle) &&
data_exchange_delegate->HasUrlsInPickle(pickle)) {
data_callbacks_.emplace(
@@ -365,9 +371,15 @@ void DataOffer::SetClipboardData(DataExchangeDelegate* data_exchange_delegate,
}
// We accept the filenames pickle from FilesApp, or text/uri-list from apps.
- std::vector<ui::FileInfo> filenames =
- data_exchange_delegate->ParseClipboardFilenamesPickle(endpoint_type,
- data);
+ std::vector<ui::FileInfo> filenames;
+ std::string buf;
+ data.ReadData(ui::ClipboardFormatType::GetWebCustomDataType(), &data_dst,
+ &buf);
+ if (!buf.empty()) {
+ base::Pickle pickle(buf.data(), static_cast<int>(buf.size()));
+ filenames = data_exchange_delegate->ParseFileSystemSources(
+ data.GetSource(ui::ClipboardBuffer::kCopyPaste), pickle);
+ }
if (filenames.empty() &&
data.IsFormatAvailable(ui::ClipboardFormatType::GetFilenamesType(),
ui::ClipboardBuffer::kCopyPaste, &data_dst)) {
diff --git a/chromium/components/exo/data_offer_observer.h b/chromium/components/exo/data_offer_observer.h
index d05b0352146..492b5ce2b68 100644
--- a/chromium/components/exo/data_offer_observer.h
+++ b/chromium/components/exo/data_offer_observer.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_EXO_DATA_OFFER_OBSERVER_H_
#define COMPONENTS_EXO_DATA_OFFER_OBSERVER_H_
-#include <string>
-
namespace exo {
class DataOffer;
diff --git a/chromium/components/exo/data_source.cc b/chromium/components/exo/data_source.cc
index 794acf03fc4..6832f42b8ff 100644
--- a/chromium/components/exo/data_source.cc
+++ b/chromium/components/exo/data_source.cc
@@ -11,8 +11,8 @@
#include "base/files/file_util.h"
#include "base/i18n/character_encoding.h"
#include "base/i18n/icu_string_conversions.h"
-#include "base/optional.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
@@ -20,6 +20,7 @@
#include "components/exo/data_source_observer.h"
#include "components/exo/mime_utils.h"
#include "net/base/mime_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "third_party/icu/source/common/unicode/ucnv.h"
#include "ui/base/clipboard/clipboard_constants.h"
@@ -32,6 +33,7 @@ constexpr char kTextPlain[] = "text/plain";
constexpr char kTextRTF[] = "text/rtf";
constexpr char kTextHTML[] = "text/html";
constexpr char kTextUriList[] = "text/uri-list";
+constexpr char kApplicationOctetStream[] = "application/octet-stream";
constexpr char kUtfPrefix[] = "UTF";
constexpr char kEncoding16[] = "16";
@@ -47,7 +49,7 @@ constexpr char kImageBitmap[] = "image/bmp";
constexpr char kImagePNG[] = "image/png";
constexpr char kImageAPNG[] = "image/apng";
-base::Optional<std::vector<uint8_t>> ReadDataOnWorkerThread(base::ScopedFD fd) {
+absl::optional<std::vector<uint8_t>> ReadDataOnWorkerThread(base::ScopedFD fd) {
constexpr size_t kChunkSize = 1024;
std::vector<uint8_t> bytes;
while (true) {
@@ -61,7 +63,7 @@ base::Optional<std::vector<uint8_t>> ReadDataOnWorkerThread(base::ScopedFD fd) {
return bytes;
if (bytes_read < 0) {
PLOG(ERROR) << "Failed to read selection data from clipboard";
- return base::nullopt;
+ return absl::nullopt;
}
}
}
@@ -134,6 +136,20 @@ std::u16string CodepageToUTF16(const std::vector<uint8_t>& data,
return output;
}
+// Returns name parameter in application/octet-stream;name=<...>, or empty
+// string if parsing fails.
+std::string GetApplicationOctetStreamName(const std::string& mime_type) {
+ base::StringPairs params;
+ if (net::MatchesMimeType(std::string(kApplicationOctetStream), mime_type) &&
+ net::ParseMimeType(mime_type, nullptr, &params)) {
+ for (const auto& kv : params) {
+ if (kv.first == "name")
+ return kv.second;
+ }
+ }
+ return std::string();
+}
+
} // namespace
ScopedDataSource::ScopedDataSource(DataSource* data_source,
@@ -172,7 +188,7 @@ void DataSource::SetActions(const base::flat_set<DndAction>& dnd_actions) {
dnd_actions_ = dnd_actions;
}
-void DataSource::Target(const base::Optional<std::string>& mime_type) {
+void DataSource::Target(const absl::optional<std::string>& mime_type) {
delegate_->OnTarget(mime_type);
}
@@ -228,7 +244,7 @@ void DataSource::ReadData(const std::string& mime_type,
void DataSource::OnDataRead(ReadDataCallback callback,
const std::string& mime_type,
base::OnceClosure failure_callback,
- const base::Optional<std::vector<uint8_t>>& data) {
+ const absl::optional<std::vector<uint8_t>>& data) {
if (!data) {
std::move(failure_callback).Run();
return;
@@ -242,8 +258,14 @@ void DataSource::GetDataForPreferredMimeTypes(
ReadTextDataCallback html_reader,
ReadDataCallback image_reader,
ReadDataCallback filenames_reader,
+ ReadFileContentsDataCallback file_contents_reader,
base::RepeatingClosure failure_callback) {
- std::string text_mime, rtf_mime, html_mime, image_mime, filenames_mime;
+ std::string text_mime;
+ std::string rtf_mime;
+ std::string html_mime;
+ std::string image_mime;
+ std::string filenames_mime;
+ std::string file_contents_mime;
int text_rank = std::numeric_limits<int>::max();
int html_rank = std::numeric_limits<int>::max();
@@ -293,6 +315,8 @@ void DataSource::GetDataForPreferredMimeTypes(
continue;
filenames_mime = mime_type;
+ } else if (!GetApplicationOctetStreamName(mime_type).empty()) {
+ file_contents_mime = mime_type;
}
}
@@ -309,6 +333,11 @@ void DataSource::GetDataForPreferredMimeTypes(
failure_callback);
ReadData(image_mime, std::move(image_reader), failure_callback);
ReadData(filenames_mime, std::move(filenames_reader), failure_callback);
+ ReadData(file_contents_mime,
+ base::BindOnce(&DataSource::OnFileContentsRead,
+ read_data_weak_ptr_factory_.GetWeakPtr(),
+ std::move(file_contents_reader)),
+ failure_callback);
}
void DataSource::OnTextRead(ReadTextDataCallback callback,
@@ -318,6 +347,13 @@ void DataSource::OnTextRead(ReadTextDataCallback callback,
std::move(callback).Run(mime_type, std::move(output));
}
+void DataSource::OnFileContentsRead(ReadFileContentsDataCallback callback,
+ const std::string& mime_type,
+ const std::vector<uint8_t>& data) {
+ const base::FilePath filename(GetApplicationOctetStreamName(mime_type));
+ std::move(callback).Run(mime_type, filename, data);
+}
+
bool DataSource::CanBeDataSourceForCopy(Surface* surface) const {
return delegate_->CanAcceptDataEventsForSurface(surface);
}
diff --git a/chromium/components/exo/data_source.h b/chromium/components/exo/data_source.h
index 53d00ae85ab..a2f3bde107d 100644
--- a/chromium/components/exo/data_source.h
+++ b/chromium/components/exo/data_source.h
@@ -22,6 +22,11 @@ enum class DndAction;
// Object representing transferred data offered by a client.
class DataSource {
public:
+ // The maximum number of different data types that will be read by
+ // GetDataForPreferredMimeTypes (plain text, RTF, HTML, image, text/uri-list,
+ // application/octet-stream).
+ static constexpr int kMaxDataTypes = 6;
+
explicit DataSource(DataSourceDelegate* delegate);
~DataSource();
@@ -43,7 +48,7 @@ class DataSource {
// 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);
+ void Target(const absl::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
@@ -71,12 +76,18 @@ class DataSource {
base::OnceCallback<void(const std::string&, const std::vector<uint8_t>&)>;
using ReadTextDataCallback =
base::OnceCallback<void(const std::string&, std::u16string)>;
- void GetDataForPreferredMimeTypes(ReadTextDataCallback text_reader,
- ReadDataCallback rtf_reader,
- ReadTextDataCallback html_reader,
- ReadDataCallback image_reader,
- ReadDataCallback filenames_reader,
- base::RepeatingClosure failure_callback);
+ using ReadFileContentsDataCallback =
+ base::OnceCallback<void(const std::string&,
+ const base::FilePath&,
+ const std::vector<uint8_t>&)>;
+ void GetDataForPreferredMimeTypes(
+ ReadTextDataCallback text_reader,
+ ReadDataCallback rtf_reader,
+ ReadTextDataCallback html_reader,
+ ReadDataCallback image_reader,
+ ReadDataCallback filenames_reader,
+ ReadFileContentsDataCallback file_contents_reader,
+ base::RepeatingClosure failure_callback);
void ReadDataForTesting(const std::string& mime_type,
ReadDataCallback callback);
@@ -94,12 +105,16 @@ class DataSource {
void OnDataRead(ReadDataCallback callback,
const std::string& mime_type,
base::OnceClosure failure_callback,
- const base::Optional<std::vector<uint8_t>>& data);
+ const absl::optional<std::vector<uint8_t>>& data);
void OnTextRead(ReadTextDataCallback callback,
const std::string& mime_type,
const std::vector<uint8_t>& data);
+ void OnFileContentsRead(ReadFileContentsDataCallback callback,
+ const std::string& mime_type,
+ const std::vector<uint8_t>& data);
+
DataSourceDelegate* const delegate_;
base::ObserverList<DataSourceObserver>::Unchecked observers_;
diff --git a/chromium/components/exo/data_source_delegate.h b/chromium/components/exo/data_source_delegate.h
index fceafe734e0..4140af3e3a7 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 base::Optional<std::string>& mime_type) = 0;
+ virtual void OnTarget(const absl::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_observer.h b/chromium/components/exo/data_source_observer.h
index 43fc3296908..dc4cef5ff61 100644
--- a/chromium/components/exo/data_source_observer.h
+++ b/chromium/components/exo/data_source_observer.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_EXO_DATA_SOURCE_OBSERVER_H_
#define COMPONENTS_EXO_DATA_SOURCE_OBSERVER_H_
-#include <string>
-
namespace exo {
class DataSource;
diff --git a/chromium/components/exo/data_source_unittest.cc b/chromium/components/exo/data_source_unittest.cc
index 93c20a39822..0039d46f72b 100644
--- a/chromium/components/exo/data_source_unittest.cc
+++ b/chromium/components/exo/data_source_unittest.cc
@@ -4,6 +4,8 @@
#include "components/exo/data_source.h"
+#include <atomic>
+
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
@@ -32,10 +34,9 @@ class TestDataSourceDelegate : public DataSourceDelegate {
// Overridden from DataSourceDelegate:
void OnDataSourceDestroying(DataSource* source) override {}
- void OnTarget(const base::Optional<std::string>& mime_type) override {}
+ void OnTarget(const absl::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)));
+ ASSERT_TRUE(base::WriteFileDescriptor(fd.get(), kTestData));
}
void OnCancelled() override {}
void OnDndDropPerformed() override {}
@@ -51,7 +52,7 @@ void CheckMimeType(const std::string& expected,
const std::string& mime_type,
const std::vector<uint8_t>& data) {
EXPECT_FALSE(expected.empty());
- EXPECT_EQ(mime_type, expected);
+ EXPECT_EQ(expected, mime_type);
std::move(counter).Run();
}
@@ -60,11 +61,29 @@ void CheckTextMimeType(const std::string& expected,
const std::string& mime_type,
std::u16string data) {
EXPECT_FALSE(expected.empty());
- EXPECT_EQ(mime_type, expected);
+ EXPECT_EQ(expected, mime_type);
std::move(counter).Run();
}
-void IncrementCounter(base::RepeatingClosure counter) {
+struct FileContents {
+ std::string mime_type;
+ std::string parsed_filename;
+};
+
+void CheckFileContentsMimeType(const FileContents& file_contents,
+ base::OnceClosure counter,
+ const std::string& mime_type,
+ const base::FilePath& filename,
+ const std::vector<uint8_t>& data) {
+ EXPECT_FALSE(file_contents.mime_type.empty());
+ EXPECT_EQ(file_contents.mime_type, mime_type);
+ EXPECT_EQ(file_contents.parsed_filename, filename.value());
+ std::move(counter).Run();
+}
+
+void IncrementFailureCounter(std::atomic_int* failure_count,
+ base::RepeatingClosure counter) {
+ ++(*failure_count);
std::move(counter).Run();
}
@@ -73,18 +92,30 @@ void CheckMimeTypesReceived(DataSource* data_source,
const std::string& rtf_mime,
const std::string& html_mime,
const std::string& image_mime,
- const std::string& filenames_mime) {
+ const std::string& filenames_mime,
+ const FileContents& file_contents) {
base::RunLoop run_loop;
base::RepeatingClosure counter =
- base::BarrierClosure(4, run_loop.QuitClosure());
+ base::BarrierClosure(DataSource::kMaxDataTypes, run_loop.QuitClosure());
+ std::atomic_int failure_count;
+ failure_count.store(0);
data_source->GetDataForPreferredMimeTypes(
base::BindOnce(&CheckTextMimeType, text_mime, counter),
base::BindOnce(&CheckMimeType, rtf_mime, counter),
base::BindOnce(&CheckTextMimeType, html_mime, counter),
base::BindOnce(&CheckMimeType, image_mime, counter),
base::BindOnce(&CheckMimeType, filenames_mime, counter),
- base::BindRepeating(&IncrementCounter, counter));
+ base::BindOnce(&CheckFileContentsMimeType, file_contents, counter),
+ base::BindRepeating(&IncrementFailureCounter, &failure_count, counter));
run_loop.Run();
+
+ int expected_failure_count = 0;
+ for (const auto& mime_type : {text_mime, rtf_mime, html_mime, image_mime,
+ filenames_mime, file_contents.mime_type}) {
+ if (mime_type.empty())
+ ++expected_failure_count;
+ }
+ EXPECT_EQ(expected_failure_count, failure_count.load());
}
TEST_F(DataSourceTest, ReadData) {
@@ -172,13 +203,8 @@ TEST_F(DataSourceTest, PreferredMimeTypeUTF16) {
data_source.Offer("text/html;charset=UTF-16");
data_source.Offer("text/html;charset=utf-8");
- CheckMimeTypesReceived(
- &data_source,
- "text/plain;charset=utf-16",
- "",
- "text/html;charset=UTF-16",
- "",
- "");
+ CheckMimeTypesReceived(&data_source, "text/plain;charset=utf-16", "",
+ "text/html;charset=UTF-16", "", "", {});
}
TEST_F(DataSourceTest, PreferredMimeTypeUTF16LE) {
@@ -189,13 +215,8 @@ TEST_F(DataSourceTest, PreferredMimeTypeUTF16LE) {
data_source.Offer("text/html;charset=utf16le");
data_source.Offer("text/html;charset=utf-8");
- CheckMimeTypesReceived(
- &data_source,
- "text/plain;charset=utf-16le",
- "",
- "text/html;charset=utf16le",
- "",
- "");
+ CheckMimeTypesReceived(&data_source, "text/plain;charset=utf-16le", "",
+ "text/html;charset=utf16le", "", "", {});
}
TEST_F(DataSourceTest, PreferredMimeTypeUTF16BE) {
@@ -206,13 +227,8 @@ TEST_F(DataSourceTest, PreferredMimeTypeUTF16BE) {
data_source.Offer("text/html;charset=UTF16be");
data_source.Offer("text/html;charset=utf-8");
- CheckMimeTypesReceived(
- &data_source,
- "text/plain;charset=utf-16be",
- "",
- "text/html;charset=UTF16be",
- "",
- "");
+ CheckMimeTypesReceived(&data_source, "text/plain;charset=utf-16be", "",
+ "text/html;charset=UTF16be", "", "", {});
}
TEST_F(DataSourceTest, PreferredMimeTypeUTFToOther) {
@@ -223,13 +239,8 @@ TEST_F(DataSourceTest, PreferredMimeTypeUTFToOther) {
data_source.Offer("text/html;charset=utf-8");
data_source.Offer("text/html;charset=iso-8859-1");
- CheckMimeTypesReceived(
- &data_source,
- "text/plain;charset=utf-8",
- "",
- "text/html;charset=utf-8",
- "",
- "");
+ CheckMimeTypesReceived(&data_source, "text/plain;charset=utf-8", "",
+ "text/html;charset=utf-8", "", "", {});
}
TEST_F(DataSourceTest, RecogniseUTF8Legaccy) {
@@ -238,13 +249,7 @@ TEST_F(DataSourceTest, RecogniseUTF8Legaccy) {
data_source.Offer("UTF8_STRING");
data_source.Offer("text/plain;charset=iso-8859-1");
- CheckMimeTypesReceived(
- &data_source,
- "UTF8_STRING",
- "",
- "",
- "",
- "");
+ CheckMimeTypesReceived(&data_source, "UTF8_STRING", "", "", "", "", {});
}
TEST_F(DataSourceTest, PreferredMimeTypeOtherToAscii) {
@@ -255,13 +260,8 @@ TEST_F(DataSourceTest, PreferredMimeTypeOtherToAscii) {
data_source.Offer("text/html;charset=iso-8859-1");
data_source.Offer("text/html;charset=ascii");
- CheckMimeTypesReceived(
- &data_source,
- "text/plain;charset=iso-8859-1",
- "",
- "text/html;charset=iso-8859-1",
- "",
- "");
+ CheckMimeTypesReceived(&data_source, "text/plain;charset=iso-8859-1", "",
+ "text/html;charset=iso-8859-1", "", "", {});
}
TEST_F(DataSourceTest, PreferredMimeTypeOtherToUnspecified) {
@@ -272,13 +272,8 @@ TEST_F(DataSourceTest, PreferredMimeTypeOtherToUnspecified) {
data_source.Offer("text/html;charset=iso-8859-1");
data_source.Offer("text/html");
- CheckMimeTypesReceived(
- &data_source,
- "text/plain;charset=iso-8859-1",
- "",
- "text/html;charset=iso-8859-1",
- "",
- "");
+ CheckMimeTypesReceived(&data_source, "text/plain;charset=iso-8859-1", "",
+ "text/html;charset=iso-8859-1", "", "", {});
}
TEST_F(DataSourceTest, PreferredMimeTypeRTF) {
@@ -286,13 +281,7 @@ TEST_F(DataSourceTest, PreferredMimeTypeRTF) {
DataSource data_source(&delegate);
data_source.Offer("text/rtf");
- CheckMimeTypesReceived(
- &data_source,
- "",
- "text/rtf",
- "",
- "",
- "");
+ CheckMimeTypesReceived(&data_source, "", "text/rtf", "", "", "", {});
}
TEST_F(DataSourceTest, PreferredMimeTypeBitmapToPNG) {
@@ -301,13 +290,7 @@ TEST_F(DataSourceTest, PreferredMimeTypeBitmapToPNG) {
data_source.Offer("image/bmp");
data_source.Offer("image/png");
- CheckMimeTypesReceived(
- &data_source,
- "",
- "",
- "",
- "image/bmp",
- "");
+ CheckMimeTypesReceived(&data_source, "", "", "", "image/bmp", "", {});
}
TEST_F(DataSourceTest, PreferredMimeTypePNGToJPEG) {
@@ -317,13 +300,7 @@ TEST_F(DataSourceTest, PreferredMimeTypePNGToJPEG) {
data_source.Offer("image/jpeg");
data_source.Offer("image/jpg");
- CheckMimeTypesReceived(
- &data_source,
- "",
- "",
- "",
- "image/png",
- "");
+ CheckMimeTypesReceived(&data_source, "", "", "", "image/png", "", {});
}
TEST_F(DataSourceTest, PreferredMimeTypeTextUriList) {
@@ -331,13 +308,35 @@ TEST_F(DataSourceTest, PreferredMimeTypeTextUriList) {
DataSource data_source(&delegate);
data_source.Offer("text/uri-list");
+ CheckMimeTypesReceived(&data_source, "", "", "", "", "text/uri-list", {});
+}
+
+TEST_F(DataSourceTest, PreferredMimeTypeOctetStream) {
+ TestDataSourceDelegate delegate;
+ DataSource data_source(&delegate);
+ data_source.Offer("application/octet-stream;name=test.jpg");
+
+ CheckMimeTypesReceived(
+ &data_source, "", "", "", "", "",
+ {"application/octet-stream;name=test.jpg", "test.jpg"});
+}
+
+TEST_F(DataSourceTest, OctetStreamWithoutName) {
+ TestDataSourceDelegate delegate;
+ DataSource data_source(&delegate);
+ data_source.Offer("application/octet-stream");
+
+ CheckMimeTypesReceived(&data_source, "", "", "", "", "", {});
+}
+
+TEST_F(DataSourceTest, OctetStreamWithQuotedName) {
+ TestDataSourceDelegate delegate;
+ DataSource data_source(&delegate);
+ data_source.Offer("application/octet-stream;name=\"t\\\\est\\\".jpg\"");
+
CheckMimeTypesReceived(
- &data_source,
- "",
- "",
- "",
- "",
- "text/uri-list");
+ &data_source, "", "", "", "", "",
+ {"application/octet-stream;name=\"t\\\\est\\\".jpg\"", "t\\est\".jpg"});
}
} // namespace
diff --git a/chromium/components/exo/display.cc b/chromium/components/exo/display.cc
index 222da6fcac1..102145076d4 100644
--- a/chromium/components/exo/display.cc
+++ b/chromium/components/exo/display.cc
@@ -19,6 +19,7 @@
#include "components/exo/notification_surface.h"
#include "components/exo/notification_surface_manager.h"
#include "components/exo/shared_memory.h"
+#include "components/exo/shell_surface_util.h"
#include "components/exo/sub_surface.h"
#include "components/exo/surface.h"
#include "ui/gfx/linux/client_native_pixmap_factory_dmabuf.h"
@@ -167,10 +168,11 @@ std::unique_ptr<XdgShellSurface> Display::CreateXdgShellSurface(
}
std::unique_ptr<ClientControlledShellSurface>
-Display::CreateClientControlledShellSurface(Surface* surface,
- int container,
- double default_device_scale_factor,
- bool default_scale_cancellation) {
+Display::CreateOrGetClientControlledShellSurface(
+ Surface* surface,
+ int container,
+ double default_device_scale_factor,
+ bool default_scale_cancellation) {
TRACE_EVENT2("exo", "Display::CreateRemoteShellSurface", "surface",
surface->AsTracedValue(), "container", container);
@@ -182,9 +184,28 @@ Display::CreateClientControlledShellSurface(Surface* surface,
// Remote shell surfaces in system modal container cannot be minimized.
bool can_minimize = container != ash::kShellWindowId_SystemModalContainer;
- std::unique_ptr<ClientControlledShellSurface> shell_surface(
- std::make_unique<ClientControlledShellSurface>(
- surface, can_minimize, container, default_scale_cancellation));
+ std::unique_ptr<ClientControlledShellSurface> shell_surface;
+
+ int window_session_id = surface->GetWindowSessionId();
+ if (window_session_id > 0) {
+ // Root surface has window session id, try get shell surface from external
+ // source first.
+ ui::PropertyHandler handler;
+ WMHelper::AppPropertyResolver::Params params;
+ params.window_session_id = window_session_id;
+ WMHelper::GetInstance()->PopulateAppProperties(params, handler);
+ shell_surface =
+ base::WrapUnique(GetShellClientControlledShellSurface(&handler));
+ }
+
+ if (shell_surface) {
+ shell_surface->RebindRootSurface(surface, can_minimize, container,
+ default_scale_cancellation);
+ } else {
+ shell_surface = std::make_unique<ClientControlledShellSurface>(
+ surface, can_minimize, container, default_scale_cancellation);
+ }
+
if (default_scale_cancellation) {
shell_surface->SetScale(default_device_scale_factor);
shell_surface->CommitPendingScale();
diff --git a/chromium/components/exo/display.h b/chromium/components/exo/display.h
index e494af12a0b..fd1a76c1887 100644
--- a/chromium/components/exo/display.h
+++ b/chromium/components/exo/display.h
@@ -93,12 +93,14 @@ class Display {
// Creates a xdg shell surface for an existing surface.
std::unique_ptr<XdgShellSurface> CreateXdgShellSurface(Surface* surface);
- // Creates a remote shell surface for an existing surface using |container|.
+ // Returns a remote shell surface for an existing surface using |container|.
+ // If the existing surface has window session id associated, the remote shell
+ // will be get from PropertyResolver. Or it will create a new remote shell.
std::unique_ptr<ClientControlledShellSurface>
- CreateClientControlledShellSurface(Surface* surface,
- int container,
- double default_device_scale_factor,
- bool default_scale_cancellation);
+ CreateOrGetClientControlledShellSurface(Surface* surface,
+ int container,
+ double default_device_scale_factor,
+ bool default_scale_cancellation);
// Creates a notification surface for a surface and notification id.
std::unique_ptr<NotificationSurface> CreateNotificationSurface(
diff --git a/chromium/components/exo/display_unittest.cc b/chromium/components/exo/display_unittest.cc
index ee10fd08f1d..28e1a948bec 100644
--- a/chromium/components/exo/display_unittest.cc
+++ b/chromium/components/exo/display_unittest.cc
@@ -15,6 +15,7 @@
#include "components/exo/notification_surface_manager.h"
#include "components/exo/shared_memory.h"
#include "components/exo/shell_surface.h"
+#include "components/exo/shell_surface_util.h"
#include "components/exo/sub_surface.h"
#include "components/exo/surface.h"
#include "components/exo/test/exo_test_base.h"
@@ -31,7 +32,56 @@
namespace exo {
namespace {
-using DisplayTest = test::ExoTestBase;
+class DisplayTest : public test::ExoTestBase {
+ public:
+ DisplayTest()
+ : test::ExoTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+ DisplayTest(const DisplayTest&) = delete;
+ DisplayTest& operator=(const DisplayTest&) = delete;
+ ~DisplayTest() override = default;
+
+ protected:
+ // A property resolver for provide external shell surface source.
+ class TestPropertyResolver : public exo::WMHelper::AppPropertyResolver {
+ public:
+ TestPropertyResolver() = default;
+ ~TestPropertyResolver() override = default;
+ void PopulateProperties(
+ const Params& params,
+ ui::PropertyHandler& out_properties_container) override {
+ if (params.window_session_id <= 0)
+ return;
+ auto it = shell_surface_map_.find(params.window_session_id);
+ if (it != shell_surface_map_.end()) {
+ SetShellClientControlledShellSurface(&out_properties_container,
+ it->second.release());
+ shell_surface_map_.erase(it);
+ }
+ }
+ void PutClientControlledShellSurface(
+ int window_session_id,
+ std::unique_ptr<exo::ClientControlledShellSurface> shell_surface) {
+ shell_surface_map_.emplace(window_session_id, std::move(shell_surface));
+ }
+
+ private:
+ std::map<int, std::unique_ptr<exo::ClientControlledShellSurface>>
+ shell_surface_map_;
+ };
+
+ TestPropertyResolver* property_resolver() { return resolver_; }
+
+ // test::ExoTestBase:
+ void SetUp() override {
+ test::ExoTestBase::SetUp();
+ auto resolver = std::make_unique<TestPropertyResolver>();
+ resolver_ = resolver.get();
+ WMHelper::GetInstance()->RegisterAppPropertyResolver(std::move(resolver));
+ }
+
+ private:
+ TestPropertyResolver* resolver_;
+};
TEST_F(DisplayTest, CreateSurface) {
std::unique_ptr<Display> display(new Display);
@@ -126,7 +176,7 @@ TEST_F(DisplayTest, CreateClientControlledShellSurface) {
// Create a remote shell surface for surface1.
std::unique_ptr<ClientControlledShellSurface> shell_surface1 =
- display->CreateClientControlledShellSurface(
+ display->CreateOrGetClientControlledShellSurface(
surface1.get(), ash::kShellWindowId_SystemModalContainer,
/*default_scale_factor=*/2.0,
/*default_scale_cancellation=*/true);
@@ -135,13 +185,40 @@ TEST_F(DisplayTest, CreateClientControlledShellSurface) {
// Create a remote shell surface for surface2.
std::unique_ptr<ShellSurfaceBase> shell_surface2 =
- display->CreateClientControlledShellSurface(
+ display->CreateOrGetClientControlledShellSurface(
surface2.get(), ash::desks_util::GetActiveDeskContainerId(),
/*default_scale_factor=*/1.0,
/*default_scale_cancellation=*/true);
EXPECT_TRUE(shell_surface2);
}
+TEST_F(DisplayTest, GetClientControlledShellSurface) {
+ std::unique_ptr<Display> display(new Display);
+
+ // Create a external surface, bind with a window id.
+ ClientControlledShellSurface* external_shell_surface =
+ new ClientControlledShellSurface(
+ new Surface,
+ /*can_minimize=*/true, ash::desks_util::GetActiveDeskContainerId(),
+ /*default_scale_cancellation=*/true);
+ property_resolver()->PutClientControlledShellSurface(
+ /*window_session_id=*/10001, base::WrapUnique(external_shell_surface));
+
+ // Create surface with specific window id.
+ std::unique_ptr<Surface> surface_with_id = display->CreateSurface();
+ ASSERT_TRUE(surface_with_id);
+ surface_with_id->SetWindowSessionId(10001);
+
+ // Get a remote shell surface by external source.
+ std::unique_ptr<ClientControlledShellSurface> shell_surface =
+ display->CreateOrGetClientControlledShellSurface(
+ surface_with_id.get(), ash::desks_util::GetActiveDeskContainerId(),
+ /*default_scale_factor=*/2.0,
+ /*default_scale_cancellation=*/true);
+ ASSERT_TRUE(external_shell_surface);
+ EXPECT_EQ(shell_surface.get(), external_shell_surface);
+}
+
TEST_F(DisplayTest, CreateSubSurface) {
std::unique_ptr<Display> display(new Display);
@@ -242,7 +319,7 @@ TEST_F(DisplayTest, PinnedAlwaysOnTopWindow) {
ASSERT_TRUE(surface);
std::unique_ptr<ClientControlledShellSurface> shell_surface =
- display.CreateClientControlledShellSurface(
+ display.CreateOrGetClientControlledShellSurface(
surface.get(), ash::desks_util::GetActiveDeskContainerId(),
/*default_scale_factor=*/2.0,
/*default_scale_cancellation=*/true);
diff --git a/chromium/components/exo/drag_drop_operation.cc b/chromium/components/exo/drag_drop_operation.cc
index c862d62c0c4..d0291e67f93 100644
--- a/chromium/components/exo/drag_drop_operation.cc
+++ b/chromium/components/exo/drag_drop_operation.cc
@@ -21,7 +21,9 @@
#include "ui/base/clipboard/file_info.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/point.h"
@@ -37,9 +39,10 @@
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
namespace exo {
-
namespace {
+using ::ui::mojom::DragOperation;
+
uint32_t DndActionsToDragOperations(const base::flat_set<DndAction>& actions) {
uint32_t dnd_operations = 0;
for (const DndAction action : actions) {
@@ -72,13 +75,13 @@ DndAction DragOperationsToPreferredDndAction(int op) {
}
#endif
-DndAction DragOperationToDndAction(int op) {
+DndAction DragOperationToDndAction(DragOperation op) {
switch (op) {
- case ui::DragDropTypes::DragOperation::DRAG_NONE:
+ case DragOperation::kNone:
return DndAction::kNone;
- case ui::DragDropTypes::DragOperation::DRAG_MOVE:
+ case DragOperation::kMove:
return DndAction::kMove;
- case ui::DragDropTypes::DragOperation::DRAG_COPY:
+ case DragOperation::kCopy:
return DndAction::kCopy;
default:
NOTREACHED();
@@ -205,9 +208,9 @@ DragDropOperation::DragDropOperation(
base::BindOnce(&DragDropOperation::ScheduleStartDragDropOperation,
weak_ptr_factory_.GetWeakPtr());
- // When the icon is present, make the count kMaxClipboardDataTypes + 1 so we
- // can wait for the icon to be captured as well.
- counter_ = base::BarrierClosure(kMaxClipboardDataTypes + (icon ? 1 : 0),
+ // When the icon is present, make the count kMaxDataTypes + 1 so we can wait
+ // for the icon to be captured as well.
+ counter_ = base::BarrierClosure(DataSource::kMaxDataTypes + (icon ? 1 : 0),
std::move(start_op_callback));
source->GetDataForPreferredMimeTypes(
@@ -220,6 +223,8 @@ DragDropOperation::DragDropOperation(
base::BindOnce(&DragDropOperation::OnFilenamesRead,
weak_ptr_factory_.GetWeakPtr(), data_exchange_delegate,
origin->window()),
+ base::BindOnce(&DragDropOperation::OnFileContentsRead,
+ weak_ptr_factory_.GetWeakPtr()),
counter_);
}
@@ -274,6 +279,16 @@ void DragDropOperation::OnFilenamesRead(
counter_.Run();
}
+void DragDropOperation::OnFileContentsRead(const std::string& mime_type,
+ const base::FilePath& filename,
+ const std::vector<uint8_t>& data) {
+ DCHECK(os_exchange_data_);
+ os_exchange_data_->SetFileContents(filename,
+ std::string(data.begin(), data.end()));
+ mime_type_ = mime_type;
+ counter_.Run();
+}
+
void DragDropOperation::OnDragIconCaptured(const SkBitmap& icon_bitmap) {
DCHECK(icon_);
@@ -318,7 +333,7 @@ void DragDropOperation::StartDragDropOperation() {
// This triggers a nested run loop that terminates when the drag and drop
// operation is completed.
- int op = drag_drop_controller_->StartDragAndDrop(
+ DragOperation op = drag_drop_controller_->StartDragAndDrop(
std::move(os_exchange_data_), origin_->get()->window()->GetRootWindow(),
origin_->get()->window(), drag_start_point, dnd_operations,
event_source_);
@@ -327,7 +342,7 @@ void DragDropOperation::StartDragDropOperation() {
if (!weak_ptr)
return;
- if (op) {
+ if (op != DragOperation::kNone) {
// Success
// TODO(crbug.com/994065) This is currently not the actual mime type used by
@@ -368,7 +383,7 @@ void DragDropOperation::OnDragActionsChanged(int actions) {
if (dnd_action != DndAction::kNone)
source_->get()->Target(mime_type_);
else
- source_->get()->Target(base::nullopt);
+ source_->get()->Target(absl::nullopt);
source_->get()->Action(dnd_action);
}
diff --git a/chromium/components/exo/drag_drop_operation.h b/chromium/components/exo/drag_drop_operation.h
index c6788257504..ffcf85f8c60 100644
--- a/chromium/components/exo/drag_drop_operation.h
+++ b/chromium/components/exo/drag_drop_operation.h
@@ -105,6 +105,9 @@ class DragDropOperation : public DataSourceObserver,
aura::Window* source,
const std::string& mime_type,
const std::vector<uint8_t>& data);
+ void OnFileContentsRead(const std::string& mime_type,
+ const base::FilePath& filename,
+ const std::vector<uint8_t>& data);
void ScheduleStartDragDropOperation();
diff --git a/chromium/components/exo/drag_drop_operation_unittest.cc b/chromium/components/exo/drag_drop_operation_unittest.cc
index 3c7ebd247b3..65b95eb3857 100644
--- a/chromium/components/exo/drag_drop_operation_unittest.cc
+++ b/chromium/components/exo/drag_drop_operation_unittest.cc
@@ -34,10 +34,10 @@ class TestDataSourceDelegate : public DataSourceDelegate {
// DataSourceDelegate:
void OnDataSourceDestroying(DataSource* source) override {}
- void OnTarget(const base::Optional<std::string>& mime_type) override {}
+ void OnTarget(const absl::optional<std::string>& mime_type) override {}
void OnSend(const std::string& mime_type, base::ScopedFD fd) override {
- base::WriteFileDescriptor(fd.get(), kText, sizeof(kText));
+ base::WriteFileDescriptor(fd.get(), kText);
}
void OnCancelled() override {}
diff --git a/chromium/components/exo/extended_drag_source.cc b/chromium/components/exo/extended_drag_source.cc
index 69a50fb41b0..105cf0f4a30 100644
--- a/chromium/components/exo/extended_drag_source.cc
+++ b/chromium/components/exo/extended_drag_source.cc
@@ -13,9 +13,9 @@
#include "base/check_op.h"
#include "base/logging.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "components/exo/data_source.h"
#include "components/exo/surface.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window_observer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
@@ -33,6 +33,8 @@
namespace exo {
+using ::ui::mojom::DragOperation;
+
// static
ExtendedDragSource* ExtendedDragSource::instance_ = nullptr;
@@ -177,11 +179,11 @@ void ExtendedDragSource::OnToplevelWindowDragStarted(
StartDrag(dragged_window_holder_->toplevel_window(), start_location);
}
-int ExtendedDragSource::OnToplevelWindowDragDropped() {
+DragOperation ExtendedDragSource::OnToplevelWindowDragDropped() {
DVLOG(1) << "OnDragDropped()";
Cleanup();
- return delegate_->ShouldAllowDropAnywhere() ? ui::DragDropTypes::DRAG_MOVE
- : ui::DragDropTypes::DRAG_NONE;
+ return delegate_->ShouldAllowDropAnywhere() ? DragOperation::kMove
+ : DragOperation::kNone;
}
void ExtendedDragSource::OnToplevelWindowDragCancelled() {
@@ -295,11 +297,11 @@ aura::Window* ExtendedDragSource::GetDraggedWindowForTesting() {
: nullptr;
}
-base::Optional<gfx::Vector2d> ExtendedDragSource::GetDragOffsetForTesting()
+absl::optional<gfx::Vector2d> ExtendedDragSource::GetDragOffsetForTesting()
const {
return dragged_window_holder_
- ? base::Optional<gfx::Vector2d>(dragged_window_holder_->offset())
- : base::nullopt;
+ ? absl::optional<gfx::Vector2d>(dragged_window_holder_->offset())
+ : absl::nullopt;
}
} // namespace exo
diff --git a/chromium/components/exo/extended_drag_source.h b/chromium/components/exo/extended_drag_source.h
index 3aed93f9ee7..ead29b44899 100644
--- a/chromium/components/exo/extended_drag_source.h
+++ b/chromium/components/exo/extended_drag_source.h
@@ -11,8 +11,8 @@
#include "ash/drag_drop/toplevel_window_drag_delegate.h"
#include "ash/wm/toplevel_window_event_handler.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "components/exo/data_source_observer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/scoped_window_event_targeting_blocker.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
#include "ui/gfx/geometry/point.h"
@@ -76,7 +76,7 @@ class ExtendedDragSource : public DataSourceObserver,
// ash::ToplevelWindowDragDelegate:
void OnToplevelWindowDragStarted(const gfx::PointF& start_location,
ui::mojom::DragEventSource source) override;
- int OnToplevelWindowDragDropped() override;
+ ui::mojom::DragOperation OnToplevelWindowDragDropped() override;
void OnToplevelWindowDragCancelled() override;
void OnToplevelWindowDragEvent(ui::LocatedEvent* event) override;
@@ -84,7 +84,7 @@ class ExtendedDragSource : public DataSourceObserver,
void OnDataSourceDestroying(DataSource* source) override;
aura::Window* GetDraggedWindowForTesting();
- base::Optional<gfx::Vector2d> GetDragOffsetForTesting() const;
+ absl::optional<gfx::Vector2d> GetDragOffsetForTesting() const;
private:
class DraggedWindowHolder;
diff --git a/chromium/components/exo/extended_drag_source_unittest.cc b/chromium/components/exo/extended_drag_source_unittest.cc
index f40b2ea5516..89eef95852e 100644
--- a/chromium/components/exo/extended_drag_source_unittest.cc
+++ b/chromium/components/exo/extended_drag_source_unittest.cc
@@ -45,7 +45,7 @@ class TestDataSourceDelegate : public DataSourceDelegate {
// Overridden from DataSourceDelegate:
void OnDataSourceDestroying(DataSource* device) override { delete this; }
- void OnTarget(const base::Optional<std::string>& mime_type) override {}
+ void OnTarget(const absl::optional<std::string>& mime_type) override {}
void OnSend(const std::string& mime_type, base::ScopedFD fd) override {}
void OnCancelled() override { cancelled_ = true; }
void OnDndDropPerformed() override {}
diff --git a/chromium/components/exo/fullscreen_shell_surface.cc b/chromium/components/exo/fullscreen_shell_surface.cc
index 94262cc23f1..8a11409184c 100644
--- a/chromium/components/exo/fullscreen_shell_surface.cc
+++ b/chromium/components/exo/fullscreen_shell_surface.cc
@@ -13,10 +13,10 @@
#include "ui/aura/window_observer.h"
#include "ui/aura/window_occlusion_tracker.h"
#include "ui/aura/window_targeter.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/compositor/compositor.h"
#include "ui/views/accessibility/view_accessibility.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/window_util.h"
@@ -267,7 +267,7 @@ void FullscreenShellSurface::CreateFullscreenShellSurfaceWidget(
params.shadow_type = views::Widget::InitParams::ShadowType::kNone;
params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
params.show_state = show_state;
- params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
+ params.activatable = views::Widget::InitParams::Activatable::kYes;
params.parent = WMHelper::GetInstance()->GetRootWindowForNewWindows();
params.bounds = gfx::Rect(params.parent->bounds().size());
diff --git a/chromium/components/exo/fullscreen_shell_surface.h b/chromium/components/exo/fullscreen_shell_surface.h
index 5d655f15c0c..8613f34a6ae 100644
--- a/chromium/components/exo/fullscreen_shell_surface.h
+++ b/chromium/components/exo/fullscreen_shell_surface.h
@@ -91,8 +91,8 @@ class FullscreenShellSurface : public SurfaceTreeHost,
views::Widget* widget_ = nullptr;
aura::Window* parent_ = nullptr;
- base::Optional<std::string> application_id_;
- base::Optional<std::string> startup_id_;
+ absl::optional<std::string> application_id_;
+ absl::optional<std::string> startup_id_;
base::RepeatingClosure close_callback_;
base::OnceClosure surface_destroyed_callback_;
FullscreenShellView* contents_view_ = nullptr;
@@ -102,4 +102,4 @@ class FullscreenShellSurface : public SurfaceTreeHost,
} // namespace exo
-#endif // COMPONENTS_EXO_FULLSCREEN_SHELL_SURFACE_H
+#endif // COMPONENTS_EXO_FULLSCREEN_SHELL_SURFACE_H_
diff --git a/chromium/components/exo/fullscreen_shell_surface_unittest.cc b/chromium/components/exo/fullscreen_shell_surface_unittest.cc
index eaac185d2b2..b5104d42246 100644
--- a/chromium/components/exo/fullscreen_shell_surface_unittest.cc
+++ b/chromium/components/exo/fullscreen_shell_surface_unittest.cc
@@ -35,7 +35,7 @@ std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer(
->context_factory()
->GetGpuMemoryBufferManager()
->CreateGpuMemoryBuffer(size, format, gfx::BufferUsage::GPU_READ,
- gpu::kNullSurfaceHandle);
+ gpu::kNullSurfaceHandle, nullptr);
}
void DestroyFullscreenShellSurface(
diff --git a/chromium/components/exo/gaming_seat_unittest.cc b/chromium/components/exo/gaming_seat_unittest.cc
index 58224267bfd..0f3bbb9ccf9 100644
--- a/chromium/components/exo/gaming_seat_unittest.cc
+++ b/chromium/components/exo/gaming_seat_unittest.cc
@@ -4,6 +4,7 @@
#include "components/exo/gaming_seat.h"
+#include <memory>
#include <vector>
#include "ash/shell.h"
@@ -60,7 +61,7 @@ class GamingSeatTest : public test::ExoTestBase {
public:
GamingSeatTest() {}
void InitializeGamingSeat(MockGamingSeatDelegate* delegate) {
- gaming_seat_.reset(new GamingSeat(delegate));
+ gaming_seat_ = std::make_unique<GamingSeat>(delegate);
}
void DestroyGamingSeat(MockGamingSeatDelegate* delegate) {
diff --git a/chromium/components/exo/keyboard.cc b/chromium/components/exo/keyboard.cc
index 2461922af7e..5a08bd8f1c0 100644
--- a/chromium/components/exo/keyboard.cc
+++ b/chromium/components/exo/keyboard.cc
@@ -13,6 +13,7 @@
#include "base/bind.h"
#include "base/containers/contains.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
#include "components/exo/input_trace.h"
#include "components/exo/keyboard_delegate.h"
#include "components/exo/keyboard_device_configuration_delegate.h"
@@ -168,6 +169,7 @@ Keyboard::Keyboard(std::unique_ptr<KeyboardDelegate> delegate, Seat* seat)
}
Keyboard::~Keyboard() {
+ RemoveEventHandler();
for (KeyboardObserver& observer : observer_list_)
observer.OnKeyboardDestroying(this);
if (focus_)
@@ -176,7 +178,6 @@ Keyboard::~Keyboard() {
ash::Shell::Get()->ime_controller()->RemoveObserver(this);
ash::KeyboardController::Get()->RemoveObserver(this);
seat_->RemoveObserver(this);
- RemoveEventHandler();
}
bool Keyboard::HasDeviceConfigurationDelegate() const {
@@ -229,7 +230,7 @@ void Keyboard::AckKeyboardKey(uint32_t serial, bool handled) {
// ui::EventHandler overrides:
void Keyboard::OnKeyEvent(ui::KeyEvent* event) {
- if (!focus_)
+ if (!focus_ || seat_->was_shutdown())
return;
DCHECK(GetShellRootSurface(static_cast<aura::Window*>(event->target())) ||
diff --git a/chromium/components/exo/keyboard_device_configuration_delegate.h b/chromium/components/exo/keyboard_device_configuration_delegate.h
index aa80e4c8697..3befb912e75 100644
--- a/chromium/components/exo/keyboard_device_configuration_delegate.h
+++ b/chromium/components/exo/keyboard_device_configuration_delegate.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_EXO_KEYBOARD_DEVICE_CONFIGURATION_H_
-#define COMPONENTS_EXO_KEYBOARD_DEVICE_CONFIGURATION_H_
+#ifndef COMPONENTS_EXO_KEYBOARD_DEVICE_CONFIGURATION_DELEGATE_H_
+#define COMPONENTS_EXO_KEYBOARD_DEVICE_CONFIGURATION_DELEGATE_H_
namespace exo {
@@ -19,4 +19,4 @@ class KeyboardDeviceConfigurationDelegate {
} // namespace exo
-#endif // COMPONENTS_EXO_KEYBOARD_DEVICE_CONFIGURATION_H_
+#endif // COMPONENTS_EXO_KEYBOARD_DEVICE_CONFIGURATION_DELEGATE_H_
diff --git a/chromium/components/exo/layer_tree_frame_sink_holder.cc b/chromium/components/exo/layer_tree_frame_sink_holder.cc
index 2923119222f..4aef196254d 100644
--- a/chromium/components/exo/layer_tree_frame_sink_holder.cc
+++ b/chromium/components/exo/layer_tree_frame_sink_holder.cc
@@ -99,26 +99,26 @@ void LayerTreeFrameSinkHolder::SubmitCompositorFrame(
void LayerTreeFrameSinkHolder::DidNotProduceFrame(
const viz::BeginFrameAck& ack) {
DCHECK(!is_lost_);
- frame_sink_->DidNotProduceFrame(ack);
+ frame_sink_->DidNotProduceFrame(ack, cc::FrameSkippedReason::kNoDamage);
}
////////////////////////////////////////////////////////////////////////////////
// cc::LayerTreeFrameSinkClient overrides:
-base::Optional<viz::HitTestRegionList>
+absl::optional<viz::HitTestRegionList>
LayerTreeFrameSinkHolder::BuildHitTestData() {
return {};
}
void LayerTreeFrameSinkHolder::ReclaimResources(
- const std::vector<viz::ReturnedResource>& resources) {
+ std::vector<viz::ReturnedResource> resources) {
for (auto& resource : resources) {
// Skip resources that are also in last frame. This can happen if
// the frame sink id changed.
if (base::Contains(last_frame_resources_, resource.id)) {
continue;
}
- resource_manager_.ReclaimResource(resource);
+ resource_manager_.ReclaimResource(std::move(resource));
}
if (lifetime_manager_ && resource_manager_.HasNoCallbacks())
diff --git a/chromium/components/exo/layer_tree_frame_sink_holder.h b/chromium/components/exo/layer_tree_frame_sink_holder.h
index 523b4833e2b..cf9f6d0dc9a 100644
--- a/chromium/components/exo/layer_tree_frame_sink_holder.h
+++ b/chromium/components/exo/layer_tree_frame_sink_holder.h
@@ -52,9 +52,8 @@ class LayerTreeFrameSinkHolder : public cc::LayerTreeFrameSinkClient,
// Overridden from cc::LayerTreeFrameSinkClient:
void SetBeginFrameSource(viz::BeginFrameSource* source) override {}
- base::Optional<viz::HitTestRegionList> BuildHitTestData() override;
- void ReclaimResources(
- const std::vector<viz::ReturnedResource>& resources) override;
+ absl::optional<viz::HitTestRegionList> BuildHitTestData() override;
+ void ReclaimResources(std::vector<viz::ReturnedResource> resources) override;
void SetTreeActivationCallback(base::RepeatingClosure callback) override {}
void DidReceiveCompositorFrameAck() override;
void DidPresentCompositorFrame(
diff --git a/chromium/components/exo/notification.cc b/chromium/components/exo/notification.cc
index 7453130abe2..eea3c862b53 100644
--- a/chromium/components/exo/notification.cc
+++ b/chromium/components/exo/notification.cc
@@ -21,7 +21,7 @@ class NotificationDelegate : public message_center::NotificationDelegate {
public:
NotificationDelegate(
const base::RepeatingCallback<void(bool)>& close_callback,
- const base::RepeatingCallback<void(const base::Optional<int>&)>&
+ const base::RepeatingCallback<void(const absl::optional<int>&)>&
click_callback)
: close_callback_(close_callback), click_callback_(click_callback) {}
@@ -32,8 +32,8 @@ class NotificationDelegate : public message_center::NotificationDelegate {
close_callback_.Run(by_user);
}
- void Click(const base::Optional<int>& button_index,
- const base::Optional<std::u16string>& reply) override {
+ void Click(const absl::optional<int>& button_index,
+ const absl::optional<std::u16string>& reply) override {
if (!click_callback_)
return;
click_callback_.Run(button_index);
@@ -44,7 +44,7 @@ class NotificationDelegate : public message_center::NotificationDelegate {
~NotificationDelegate() override = default;
const base::RepeatingCallback<void(bool)> close_callback_;
- const base::RepeatingCallback<void(const base::Optional<int>&)>
+ const base::RepeatingCallback<void(const absl::optional<int>&)>
click_callback_;
DISALLOW_COPY_AND_ASSIGN(NotificationDelegate);
@@ -60,7 +60,7 @@ Notification::Notification(
const std::string& notifier_id,
const std::vector<std::string>& buttons,
const base::RepeatingCallback<void(bool)>& close_callback,
- const base::RepeatingCallback<void(const base::Optional<int>&)>&
+ const base::RepeatingCallback<void(const absl::optional<int>&)>&
click_callback)
: notification_id_(notification_id) {
// Currently, exo::Notification is used only for Crostini notifications.
diff --git a/chromium/components/exo/notification.h b/chromium/components/exo/notification.h
index bcf8d3593d8..bd1b3d6efea 100644
--- a/chromium/components/exo/notification.h
+++ b/chromium/components/exo/notification.h
@@ -9,7 +9,7 @@
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace exo {
@@ -23,7 +23,7 @@ class Notification {
const std::string& notifier_id,
const std::vector<std::string>& buttons,
const base::RepeatingCallback<void(bool)>& close_callback,
- const base::RepeatingCallback<void(const base::Optional<int>&)>&
+ const base::RepeatingCallback<void(const absl::optional<int>&)>&
click_callback);
// Closes this notification.
diff --git a/chromium/components/exo/notification_surface.cc b/chromium/components/exo/notification_surface.cc
index a6f496e8a89..c9ef57b8b9c 100644
--- a/chromium/components/exo/notification_surface.cc
+++ b/chromium/components/exo/notification_surface.cc
@@ -10,6 +10,7 @@
#include "components/viz/host/host_frame_sink_manager.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
+#include "ui/compositor/layer.h"
#include "ui/gfx/geometry/rect.h"
namespace exo {
@@ -40,7 +41,7 @@ const gfx::Size& NotificationSurface::GetContentSize() const {
}
void NotificationSurface::SetApplicationId(const char* application_id) {
- SetShellApplicationId(host_window(), base::make_optional(application_id));
+ SetShellApplicationId(host_window(), absl::make_optional(application_id));
}
void NotificationSurface::OnSurfaceCommit() {
diff --git a/chromium/components/exo/notification_unittest.cc b/chromium/components/exo/notification_unittest.cc
index aaca5bf6aca..f16224723b6 100644
--- a/chromium/components/exo/notification_unittest.cc
+++ b/chromium/components/exo/notification_unittest.cc
@@ -22,8 +22,8 @@ void Close(int* close_call_count, bool by_user) {
}
void Click(int* click_call_count,
- base::Optional<int>* passed_button_index,
- const base::Optional<int>& button_index) {
+ absl::optional<int>* passed_button_index,
+ const absl::optional<int>& button_index) {
(*click_call_count)++;
*passed_button_index = button_index;
}
@@ -87,7 +87,7 @@ TEST_F(NotificationTest, ClickCallback) {
// For the click callback.
int click_call_count = 0;
- base::Optional<int> passed_button_index;
+ absl::optional<int> passed_button_index;
Notification notification(
title, message, display_source, notification_id, notifier_id, buttons,
@@ -105,7 +105,7 @@ TEST_F(NotificationTest, ClickCallback) {
// Expected to be called once without button index
EXPECT_EQ(click_call_count, 1);
- EXPECT_EQ(passed_button_index, base::nullopt);
+ EXPECT_EQ(passed_button_index, absl::nullopt);
// Clicks on button.
message_center->ClickOnNotificationButton(notification_id, 0);
diff --git a/chromium/components/exo/pointer.cc b/chromium/components/exo/pointer.cc
index 56c55e9765f..a497acf54d4 100644
--- a/chromium/components/exo/pointer.cc
+++ b/chromium/components/exo/pointer.cc
@@ -8,8 +8,8 @@
#include "base/bind.h"
#include "base/feature_list.h"
-#include "base/optional.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
#include "build/chromeos_buildflags.h"
#include "components/exo/input_trace.h"
#include "components/exo/pointer_constraint_delegate.h"
@@ -23,6 +23,7 @@
#include "components/exo/wm_helper.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/env.h"
@@ -33,6 +34,7 @@
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/layout.h"
#include "ui/base/resource/scale_factor.h"
+#include "ui/compositor/layer.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
@@ -127,6 +129,8 @@ Pointer::Pointer(PointerDelegate* delegate, Seat* seat)
}
Pointer::~Pointer() {
+ WMHelper* helper = WMHelper::GetInstance();
+ helper->RemovePreTargetHandler(this);
delegate_->OnPointerDestroying(this);
if (focus_surface_)
focus_surface_->RemoveSurfaceObserver(this);
@@ -142,8 +146,6 @@ Pointer::~Pointer() {
}
if (stylus_delegate_)
stylus_delegate_->OnPointerDestroying(this);
- WMHelper* helper = WMHelper::GetInstance();
- helper->RemovePreTargetHandler(this);
// TODO(sky): CursorClient does not exist in mash
// yet. https://crbug.com/631103.
aura::client::CursorClient* cursor_client = helper->GetCursorClient();
@@ -369,6 +371,9 @@ void Pointer::OnSurfaceDestroying(Surface* surface) {
// ui::EventHandler overrides:
void Pointer::OnMouseEvent(ui::MouseEvent* event) {
+ if (seat_->was_shutdown())
+ return;
+
// Nothing to report to a client nor have to update the pointer when capture
// changes.
if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
@@ -420,7 +425,7 @@ void Pointer::OnMouseEvent(ui::MouseEvent* event) {
//
// TODO(b/161755250): the ifdef is only necessary because of the feature
// flag. This code should work fine on non-cros.
- base::Optional<gfx::Vector2dF> ordinal_motion = base::nullopt;
+ absl::optional<gfx::Vector2dF> ordinal_motion = absl::nullopt;
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (event->flags() & ui::EF_UNADJUSTED_MOUSE &&
base::FeatureList::IsEnabled(chromeos::features::kExoOrdinalMotion)) {
@@ -766,16 +771,14 @@ void Pointer::UpdateCursor() {
ui::ScaleAndRotateCursorBitmapAndHotpoint(scale, display.panel_rotation(),
&bitmap, &hotspot);
- ui::PlatformCursor platform_cursor;
// TODO(reveman): Add interface for creating cursors from GpuMemoryBuffers
// and use that here instead of the current bitmap API.
// https://crbug.com/686600
- platform_cursor = ui::CursorFactory::GetInstance()->CreateImageCursor(
- cursor_.type(), bitmap, hotspot);
- cursor_.SetPlatformCursor(platform_cursor);
+ cursor_.SetPlatformCursor(
+ ui::CursorFactory::GetInstance()->CreateImageCursor(cursor_.type(),
+ bitmap, hotspot));
cursor_.set_custom_bitmap(bitmap);
cursor_.set_custom_hotspot(hotspot);
- ui::CursorFactory::GetInstance()->UnrefImageCursor(platform_cursor);
}
// If there is a focused surface, update its widget as the views framework
@@ -827,7 +830,7 @@ void Pointer::MoveCursorToCenterOfActiveDisplay() {
bool Pointer::HandleRelativePointerMotion(
base::TimeTicks time_stamp,
gfx::PointF location_in_root,
- const base::Optional<gfx::Vector2dF>& ordinal_motion) {
+ const absl::optional<gfx::Vector2dF>& ordinal_motion) {
if (!relative_pointer_delegate_)
return false;
diff --git a/chromium/components/exo/pointer.h b/chromium/components/exo/pointer.h
index b1bcbd7f18b..ab1deb61dd7 100644
--- a/chromium/components/exo/pointer.h
+++ b/chromium/components/exo/pointer.h
@@ -9,11 +9,11 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/unguessable_token.h"
#include "components/exo/surface_observer.h"
#include "components/exo/surface_tree_host.h"
#include "components/exo/wm_helper.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/client/cursor_client_observer.h"
#include "ui/aura/client/focus_change_observer.h"
@@ -160,7 +160,7 @@ class Pointer : public SurfaceTreeHost,
bool HandleRelativePointerMotion(
base::TimeTicks time_stamp,
gfx::PointF location_in_target,
- const base::Optional<gfx::Vector2dF>& ordinal_motion);
+ const absl::optional<gfx::Vector2dF>& ordinal_motion);
// The delegate instance that all events are dispatched to.
PointerDelegate* const delegate_;
@@ -186,11 +186,11 @@ class Pointer : public SurfaceTreeHost,
gfx::PointF location_;
// The location of the pointer when pointer capture is first enabled.
- base::Optional<gfx::Point> location_when_pointer_capture_enabled_;
+ absl::optional<gfx::Point> location_when_pointer_capture_enabled_;
// If this is not nullptr, a synthetic move was sent and this points to the
// location of a generated move that was sent which should not be forwarded.
- base::Optional<gfx::Point> location_synthetic_move_;
+ absl::optional<gfx::Point> location_synthetic_move_;
// The window with pointer capture. Pointer capture is enabled if and only if
// this is not null.
diff --git a/chromium/components/exo/pointer_unittest.cc b/chromium/components/exo/pointer_unittest.cc
index 1820754f367..b6f97e9d5f4 100644
--- a/chromium/components/exo/pointer_unittest.cc
+++ b/chromium/components/exo/pointer_unittest.cc
@@ -106,7 +106,7 @@ class TestDataSourceDelegate : public DataSourceDelegate {
// Overridden from DataSourceDelegate:
void OnDataSourceDestroying(DataSource* device) override {}
- void OnTarget(const base::Optional<std::string>& mime_type) override {}
+ void OnTarget(const absl::optional<std::string>& mime_type) override {}
void OnSend(const std::string& mime_type, base::ScopedFD fd) override {}
void OnCancelled() override {}
void OnDndDropPerformed() override {}
diff --git a/chromium/components/exo/seat.cc b/chromium/components/exo/seat.cc
index 89bd7255f3e..363f0705718 100644
--- a/chromium/components/exo/seat.cc
+++ b/chromium/components/exo/seat.cc
@@ -5,11 +5,6 @@
#include "components/exo/seat.h"
#include <memory>
-#include "ui/gfx/geometry/point_f.h"
-
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "ash/shell.h"
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/wm/window_util.h"
#include "base/auto_reset.h"
@@ -18,6 +13,7 @@
#include "base/callback_helpers.h"
#include "base/feature_list.h"
#include "base/memory/weak_ptr.h"
+#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "build/chromeos_buildflags.h"
@@ -39,31 +35,15 @@
#include "ui/base/ui_base_features.h"
#include "ui/events/event_utils.h"
#include "ui/events/platform/platform_event_source.h"
+#include "ui/gfx/geometry/point_f.h"
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/shell.h"
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
namespace exo {
namespace {
-Surface* GetEffectiveFocus(aura::Window* window) {
- if (!window)
- return nullptr;
- Surface* const surface = Surface::AsSurface(window);
- if (surface)
- return surface;
- ShellSurfaceBase* shell_surface_base = nullptr;
- for (auto* current = window; current && !shell_surface_base;
- current = current->parent()) {
- shell_surface_base = GetShellSurfaceBaseForWindow(current);
- }
- // Make sure the |window| is the toplevel or a host window, but not
- // another window added to the toplevel.
- if (shell_surface_base &&
- (shell_surface_base->GetWidget()->GetNativeWindow() == window ||
- shell_surface_base->host_window()->Contains(window))) {
- return shell_surface_base->root_surface();
- }
- return nullptr;
-}
-
} // namespace
Seat::Seat(std::unique_ptr<DataExchangeDelegate> delegate)
@@ -96,10 +76,15 @@ Seat::~Seat() {
Shutdown();
}
+void Seat::SetFocusChangedCallback(FocusChangedCallback callback) {
+ focus_changed_callback_ = std::move(callback);
+ OnWindowFocused(WMHelper::GetInstance()->GetActiveWindow(), nullptr);
+}
+
void Seat::Shutdown() {
- if (shutdown_)
+ if (was_shutdown_)
return;
- shutdown_ = true;
+ was_shutdown_ = true;
DCHECK(!selection_source_) << "DataSource must be released before Seat";
#if BUILDFLAG(IS_CHROMEOS_ASH)
ash::Shell::Get()->ime_controller()->RemoveObserver(this);
@@ -120,7 +105,8 @@ void Seat::RemoveObserver(SeatObserver* observer) {
}
Surface* Seat::GetFocusedSurface() {
- return GetEffectiveFocus(WMHelper::GetInstance()->GetFocusedWindow());
+ return GetTargetSurfaceForKeyboardFocus(
+ WMHelper::GetInstance()->GetFocusedWindow());
}
void Seat::StartDrag(DataSource* source,
@@ -164,7 +150,7 @@ void Seat::SetSelection(DataSource* source) {
base::MakeRefCounted<RefCountedScopedClipboardWriter>(endpoint_type);
base::RepeatingClosure data_read_callback = base::BarrierClosure(
- kMaxClipboardDataTypes,
+ DataSource::kMaxDataTypes,
base::BindOnce(&Seat::OnAllReadsFinished, weak_ptr_factory_.GetWeakPtr(),
writer));
@@ -179,7 +165,7 @@ void Seat::SetSelection(DataSource* source) {
data_read_callback),
base::BindOnce(&Seat::OnFilenamesRead, weak_ptr_factory_.GetWeakPtr(),
endpoint_type, writer, data_read_callback),
- data_read_callback);
+ DataSource::ReadFileContentsDataCallback(), data_read_callback);
}
class Seat::RefCountedScopedClipboardWriter
@@ -289,12 +275,20 @@ void Seat::OnAllReadsFinished(
void Seat::OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) {
- Surface* const surface = GetEffectiveFocus(gained_focus);
+ Surface* const gaining_focus_surface =
+ GetTargetSurfaceForKeyboardFocus(gained_focus);
+ Surface* const lost_focus_surface =
+ GetTargetSurfaceForKeyboardFocus(lost_focus);
+
+ if (!focus_changed_callback_.is_null()) {
+ focus_changed_callback_.Run(gaining_focus_surface, lost_focus_surface,
+ !!gained_focus);
+ }
for (auto& observer : observers_) {
- observer.OnSurfaceFocusing(surface);
+ observer.OnSurfaceFocusing(gaining_focus_surface);
}
for (auto& observer : observers_) {
- observer.OnSurfaceFocused(surface);
+ observer.OnSurfaceFocused(gaining_focus_surface);
}
}
diff --git a/chromium/components/exo/seat.h b/chromium/components/exo/seat.h
index 086425e8c9c..8cf17c97520 100644
--- a/chromium/components/exo/seat.h
+++ b/chromium/components/exo/seat.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_EXO_SEAT_H_
#define COMPONENTS_EXO_SEAT_H_
+#include "base/callback.h"
#include "base/check.h"
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
@@ -39,10 +40,6 @@ class SeatObserver;
class Surface;
class XkbTracker;
-// The maximum number of different data types that we will write to the
-// clipboard (plain text, RTF, HTML, image, text/uri-list)
-constexpr int kMaxClipboardDataTypes = 5;
-
// 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,
@@ -60,6 +57,11 @@ class Seat : public aura::client::FocusChangeObserver,
Seat& operator=(const Seat&) = delete;
~Seat() override;
+ using FocusChangedCallback =
+ base::RepeatingCallback<void(Surface*, Surface*, bool)>;
+
+ void SetFocusChangedCallback(FocusChangedCallback callback);
+
void Shutdown();
void AddObserver(SeatObserver* observer);
@@ -137,6 +139,8 @@ class Seat : public aura::client::FocusChangeObserver,
return drag_drop_operation_;
}
+ bool was_shutdown() const { return was_shutdown_; }
+
private:
class RefCountedScopedClipboardWriter;
@@ -190,7 +194,9 @@ class Seat : public aura::client::FocusChangeObserver,
gfx::PointF last_pointer_location_;
- bool shutdown_ = false;
+ FocusChangedCallback focus_changed_callback_;
+
+ bool was_shutdown_ = false;
#if BUILDFLAG(IS_CHROMEOS_ASH)
std::unique_ptr<UILockController> ui_lock_controller_;
diff --git a/chromium/components/exo/seat_unittest.cc b/chromium/components/exo/seat_unittest.cc
index 150c6fd39bc..2942c6ac394 100644
--- a/chromium/components/exo/seat_unittest.cc
+++ b/chromium/components/exo/seat_unittest.cc
@@ -56,16 +56,13 @@ class TestDataSourceDelegate : public DataSourceDelegate {
// Overridden from DataSourceDelegate:
void OnDataSourceDestroying(DataSource* device) override {}
- void OnTarget(const base::Optional<std::string>& mime_type) override {}
+ void OnTarget(const absl::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";
- ASSERT_TRUE(base::WriteFileDescriptor(fd.get(), test_data.data(),
- test_data.size()));
+ const char kTestData[] = "TestData";
+ ASSERT_TRUE(base::WriteFileDescriptor(fd.get(), kTestData));
} else {
- ASSERT_TRUE(base::WriteFileDescriptor(
- fd.get(), reinterpret_cast<const char*>(data_->data()),
- data_->size()));
+ ASSERT_TRUE(base::WriteFileDescriptor(fd.get(), *data_));
}
}
void OnCancelled() override { cancelled_ = true; }
@@ -82,7 +79,7 @@ class TestDataSourceDelegate : public DataSourceDelegate {
private:
bool cancelled_ = false;
- base::Optional<std::vector<uint8_t>> data_;
+ absl::optional<std::vector<uint8_t>> data_;
DISALLOW_COPY_AND_ASSIGN(TestDataSourceDelegate);
};
diff --git a/chromium/components/exo/shell_surface.cc b/chromium/components/exo/shell_surface.cc
index 5923cd6f55f..b153636fdc6 100644
--- a/chromium/components/exo/shell_surface.cc
+++ b/chromium/components/exo/shell_surface.cc
@@ -14,6 +14,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
#include "chromeos/ui/base/window_state_type.h"
#include "components/exo/shell_surface_util.h"
#include "ui/aura/client/aura_constants.h"
@@ -23,6 +24,7 @@
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ui_base_types.h"
+#include "ui/compositor/layer.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/core/transient_window_manager.h"
@@ -286,10 +288,10 @@ void ShellSurface::InitializeWindowState(ash::WindowState* window_state) {
MaybeMakeTransient();
}
-base::Optional<gfx::Rect> ShellSurface::GetWidgetBounds() const {
+absl::optional<gfx::Rect> ShellSurface::GetWidgetBounds() const {
// Defer if configure requests are pending.
if (!pending_configs_.empty() || scoped_configure_)
- return base::nullopt;
+ return absl::nullopt;
gfx::Rect visible_bounds = GetVisibleBounds();
gfx::Rect new_widget_bounds =
diff --git a/chromium/components/exo/shell_surface.h b/chromium/components/exo/shell_surface.h
index 45ee33b89eb..5ecbb09d2c7 100644
--- a/chromium/components/exo/shell_surface.h
+++ b/chromium/components/exo/shell_surface.h
@@ -95,7 +95,7 @@ class ShellSurface : public ShellSurfaceBase, public ash::WindowStateObserver {
// Overridden from ShellSurfaceBase:
void InitializeWindowState(ash::WindowState* window_state) override;
- base::Optional<gfx::Rect> GetWidgetBounds() const override;
+ absl::optional<gfx::Rect> GetWidgetBounds() const override;
gfx::Point GetSurfaceOrigin() const override;
// Overridden from aura::WindowObserver:
diff --git a/chromium/components/exo/shell_surface_base.cc b/chromium/components/exo/shell_surface_base.cc
index b123d175c82..7c9e0d2d49e 100644
--- a/chromium/components/exo/shell_surface_base.cc
+++ b/chromium/components/exo/shell_surface_base.cc
@@ -20,18 +20,22 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
+#include "build/chromeos_buildflags.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "chromeos/crosapi/cpp/crosapi_constants.h"
-#include "chromeos/ui/base//window_properties.h"
#include "chromeos/ui/base/window_pin_type.h"
+#include "chromeos/ui/base/window_properties.h"
#include "chromeos/ui/base/window_state_type.h"
#include "chromeos/ui/frame/caption_buttons/snap_controller.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/surface.h"
#include "components/exo/wm_helper.h"
+#include "components/full_restore/full_restore_info.h"
+#include "components/full_restore/full_restore_utils.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
@@ -48,6 +52,7 @@
#include "ui/base/class_property.h"
#include "ui/base/ui_base_features.h"
#include "ui/compositor/compositor.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor_extra/shadow.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
@@ -111,8 +116,7 @@ class CustomFrameView : public ash::NonClientFrameViewAsh {
ShellSurfaceBase* shell_surface,
bool enabled)
: NonClientFrameViewAsh(widget), shell_surface_(shell_surface) {
- SetEnabled(enabled);
- SetVisible(enabled);
+ SetFrameEnabled(enabled);
if (!enabled)
NonClientFrameViewAsh::SetShouldPaintHeader(false);
}
@@ -121,7 +125,7 @@ class CustomFrameView : public ash::NonClientFrameViewAsh {
// Overridden from ash::NonClientFrameViewAsh:
void SetShouldPaintHeader(bool paint) override {
- if (GetVisible()) {
+ if (GetFrameEnabled()) {
NonClientFrameViewAsh::SetShouldPaintHeader(paint);
return;
}
@@ -129,46 +133,46 @@ class CustomFrameView : public ash::NonClientFrameViewAsh {
// Overridden from views::NonClientFrameView:
gfx::Rect GetBoundsForClientView() const override {
- if (GetVisible())
+ if (GetFrameEnabled())
return ash::NonClientFrameViewAsh::GetBoundsForClientView();
return bounds();
}
gfx::Rect GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const override {
- if (GetVisible()) {
+ if (GetFrameEnabled()) {
return ash::NonClientFrameViewAsh::GetWindowBoundsForClientBounds(
client_bounds);
}
return client_bounds;
}
int NonClientHitTest(const gfx::Point& point) override {
- if (GetVisible() || shell_surface_->server_side_resize())
+ if (GetFrameEnabled() || shell_surface_->server_side_resize())
return ash::NonClientFrameViewAsh::NonClientHitTest(point);
return GetWidget()->client_view()->NonClientHitTest(point);
}
void GetWindowMask(const gfx::Size& size, SkPath* window_mask) override {
- if (GetVisible())
+ if (GetFrameEnabled())
return ash::NonClientFrameViewAsh::GetWindowMask(size, window_mask);
}
void ResetWindowControls() override {
- if (GetVisible())
+ if (GetFrameEnabled())
return ash::NonClientFrameViewAsh::ResetWindowControls();
}
void UpdateWindowIcon() override {
- if (GetVisible())
+ if (GetFrameEnabled())
return ash::NonClientFrameViewAsh::ResetWindowControls();
}
void UpdateWindowTitle() override {
- if (GetVisible())
+ if (GetFrameEnabled())
return ash::NonClientFrameViewAsh::UpdateWindowTitle();
}
void SizeConstraintsChanged() override {
- if (GetVisible())
+ if (GetFrameEnabled())
return ash::NonClientFrameViewAsh::SizeConstraintsChanged();
}
gfx::Size GetMinimumSize() const override {
gfx::Size minimum_size = shell_surface_->GetMinimumSize();
- if (GetVisible()) {
+ if (GetFrameEnabled()) {
return ash::NonClientFrameViewAsh::GetWindowBoundsForClientBounds(
gfx::Rect(minimum_size))
.size();
@@ -177,7 +181,7 @@ class CustomFrameView : public ash::NonClientFrameViewAsh {
}
gfx::Size GetMaximumSize() const override {
gfx::Size maximum_size = shell_surface_->GetMaximumSize();
- if (GetVisible() && !maximum_size.IsEmpty()) {
+ if (GetFrameEnabled() && !maximum_size.IsEmpty()) {
return ash::NonClientFrameViewAsh::GetWindowBoundsForClientBounds(
gfx::Rect(maximum_size))
.size();
@@ -288,14 +292,13 @@ class CustomWindowStateDelegate : public ash::WindowStateDelegate {
DISALLOW_COPY_AND_ASSIGN(CustomWindowStateDelegate);
};
-void CloseAllTransientChildren(aura::Window* window) {
- // Deleting a window may delete other transient children, so
- // delete them by popping from the list.
- for (;;) {
- auto list = wm::GetTransientChildren(window);
- if (list.empty())
- return;
- wm::RemoveTransientChild(window, *list.begin());
+void CloseAllShellSurfaceTransientChildren(aura::Window* window) {
+ // Deleting a window may delete other transient children. Remove other shell
+ // surface bases first so they don't get deleted.
+ auto list = wm::GetTransientChildren(window);
+ for (size_t i = 0; i < list.size(); ++i) {
+ if (GetShellSurfaceBaseForWindow(list[i]))
+ wm::RemoveTransientChild(window, list[i]);
}
}
@@ -351,8 +354,9 @@ ShellSurfaceBase::~ShellSurfaceBase() {
if (widget_) {
widget_->GetNativeWindow()->RemoveObserver(this);
widget_->RemoveObserver(this);
- // Remove transient children so they are not automatically destroyed.
- CloseAllTransientChildren(widget_->GetNativeWindow());
+ // Remove transient children which are shell surfaces so they are not
+ // automatically destroyed.
+ CloseAllShellSurfaceTransientChildren(widget_->GetNativeWindow());
if (widget_->IsVisible())
widget_->Hide();
widget_->CloseNow();
@@ -491,6 +495,16 @@ void ShellSurfaceBase::UnsetSnap() {
CommitSnap(widget_->GetNativeWindow(), chromeos::SnapDirection::kNone);
}
+void ShellSurfaceBase::SetCanGoBack() {
+ if (widget_)
+ widget_->GetNativeWindow()->SetProperty(ash::kMinimizeOnBackKey, false);
+}
+
+void ShellSurfaceBase::UnsetCanGoBack() {
+ if (widget_)
+ widget_->GetNativeWindow()->SetProperty(ash::kMinimizeOnBackKey, true);
+}
+
void ShellSurfaceBase::SetChildAxTreeId(ui::AXTreeID child_ax_tree_id) {
GetViewAccessibility().OverrideChildTreeID(child_ax_tree_id);
this->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, false);
@@ -571,10 +585,30 @@ void ShellSurfaceBase::DisableMovement() {
}
void ShellSurfaceBase::UpdateCanResize() {
+ if (overlay_widget_ && overlay_can_resize_.has_value()) {
+ SetCanResize(*overlay_can_resize_);
+ return;
+ }
SetCanResize(!movement_disabled_ &&
(minimum_size_.IsEmpty() || minimum_size_ != maximum_size_));
}
+void ShellSurfaceBase::RebindRootSurface(Surface* root_surface,
+ bool can_minimize,
+ int container) {
+ can_minimize_ = can_minimize;
+ container_ = container;
+ this->root_surface()->RemoveSurfaceObserver(this);
+ root_surface->AddSurfaceObserver(this);
+ SetRootSurface(root_surface);
+ host_window()->Show();
+
+ SetCanMinimize(can_minimize_);
+ SetCanMaximize(ash::desks_util::IsDeskContainerId(container_));
+ SetCanResize(true);
+ SetShowTitle(false);
+}
+
std::unique_ptr<base::trace_event::TracedValue>
ShellSurfaceBase::AsTracedValue() const {
std::unique_ptr<base::trace_event::TracedValue> value(
@@ -599,6 +633,8 @@ ShellSurfaceBase::AsTracedValue() const {
void ShellSurfaceBase::AddOverlay(OverlayParams&& overlay_params) {
DCHECK(widget_);
DCHECK(!overlay_widget_);
+ overlay_overlaps_frame_ = overlay_params.overlaps_frame;
+ overlay_can_resize_ = std::move(overlay_params.can_resize);
views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
params.parent = widget_->GetNativeWindow();
@@ -607,7 +643,7 @@ void ShellSurfaceBase::AddOverlay(OverlayParams&& overlay_params) {
params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
if (overlay_params.focusable)
- params.activatable = views::Widget::InitParams::ACTIVATABLE_YES;
+ params.activatable = views::Widget::InitParams::Activatable::kYes;
params.delegate = new views::WidgetDelegate();
params.delegate->SetContentsView(std::move(overlay_params.contents_view));
@@ -633,6 +669,7 @@ void ShellSurfaceBase::AddOverlay(OverlayParams&& overlay_params) {
}
UpdateWidgetBounds();
+ UpdateCanResize();
}
void ShellSurfaceBase::RemoveOverlay() {
@@ -642,6 +679,7 @@ void ShellSurfaceBase::RemoveOverlay() {
GetWidget()->GetNativeWindow()->SetProperty(
aura::client::kSkipImeProcessing, true);
}
+ UpdateCanResize();
}
////////////////////////////////////////////////////////////////////////////////
@@ -710,11 +748,10 @@ void ShellSurfaceBase::OnSetFrame(SurfaceFrameType frame_type) {
CustomFrameView* frame_view =
static_cast<CustomFrameView*>(widget_->non_client_view()->frame_view());
- if (frame_view->GetEnabled() == frame_enabled())
+ if (frame_view->GetFrameEnabled() == frame_enabled())
return;
- frame_view->SetEnabled(frame_enabled());
- frame_view->SetVisible(frame_enabled());
+ frame_view->SetFrameEnabled(frame_enabled());
frame_view->SetShouldPaintHeader(frame_enabled());
widget_->GetRootView()->Layout();
// TODO(oshima): We probably should wait applying these if the
@@ -769,8 +806,9 @@ void ShellSurfaceBase::OnSurfaceDestroying(Surface* surface) {
// Hide widget before surface is destroyed. This allows hide animations to
// run using the current surface contents.
if (widget_) {
- // Remove transient children so they are not automatically hidden.
- CloseAllTransientChildren(widget_->GetNativeWindow());
+ // Remove transient children which are shell surfaces so they are not
+ // automatically hidden.
+ CloseAllShellSurfaceTransientChildren(widget_->GetNativeWindow());
widget_->Hide();
}
@@ -1015,11 +1053,16 @@ void ShellSurfaceBase::CreateShellSurfaceWidget(
params.show_state = show_state;
// Make shell surface a transient child if |parent_| has been set and
// container_ isn't specified.
- if (ash::desks_util::IsDeskContainerId(container_) && parent_) {
- params.parent = parent_;
+ aura::Window* root_window =
+ WMHelper::GetInstance()->GetRootWindowForNewWindows();
+ if (ash::desks_util::IsDeskContainerId(container_)) {
+ DCHECK_EQ(ash::desks_util::GetActiveDeskContainerId(), container_);
+ if (parent_)
+ params.parent = parent_;
+ else
+ params.context = root_window;
} else {
- params.parent = ash::Shell::GetContainer(
- WMHelper::GetInstance()->GetRootWindowForNewWindows(), container_);
+ params.parent = ash::Shell::GetContainer(root_window, container_);
}
params.bounds = gfx::Rect(origin_, gfx::Size());
@@ -1045,8 +1088,15 @@ void ShellSurfaceBase::CreateShellSurfaceWidget(
// Transient child needs to have an application id to be activatable.
if (parent_)
activatable &= application_id_.has_value();
- params.activatable = activatable ? views::Widget::InitParams::ACTIVATABLE_YES
- : views::Widget::InitParams::ACTIVATABLE_NO;
+ params.activatable = activatable
+ ? views::Widget::InitParams::Activatable::kYes
+ : views::Widget::InitParams::Activatable::kNo;
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ full_restore::ModifyWidgetParams(params.init_properties_container.GetProperty(
+ full_restore::kRestoreWindowIdKey),
+ &params);
+#endif
OverrideInitParams(&params);
@@ -1111,9 +1161,19 @@ bool ShellSurfaceBase::IsResizing() const {
void ShellSurfaceBase::UpdateWidgetBounds() {
DCHECK(widget_);
- base::Optional<gfx::Rect> bounds = GetWidgetBounds();
- if (bounds && overlay_widget_)
- overlay_widget_->SetBounds(gfx::Rect(bounds->size()));
+ absl::optional<gfx::Rect> bounds = GetWidgetBounds();
+ if (bounds && overlay_widget_) {
+ gfx::Rect content_bounds(bounds->size());
+ int height = 0;
+ if (!overlay_overlaps_frame_ && frame_enabled()) {
+ auto* frame_view = static_cast<const ash::NonClientFrameViewAsh*>(
+ widget_->non_client_view()->frame_view());
+ height = frame_view->NonClientTopBorderHeight();
+ }
+ content_bounds.set_height(content_bounds.height() - height);
+ content_bounds.set_y(height);
+ overlay_widget_->SetBounds(content_bounds);
+ }
aura::Window* window = widget_->GetNativeWindow();
ash::WindowState* window_state = ash::WindowState::Get(window);
diff --git a/chromium/components/exo/shell_surface_base.h b/chromium/components/exo/shell_surface_base.h
index d4b2cf4db3f..08e678e2f3c 100644
--- a/chromium/components/exo/shell_surface_base.h
+++ b/chromium/components/exo/shell_surface_base.h
@@ -12,9 +12,9 @@
#include "ash/display/window_tree_host_manager.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/exo/surface_observer.h"
#include "components/exo/surface_tree_host.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_tree_id.h"
#include "ui/aura/client/capture_client_observer.h"
#include "ui/aura/window_observer.h"
@@ -135,6 +135,11 @@ class ShellSurfaceBase : public SurfaceTreeHost,
// Update the resizability for the surface.
virtual void UpdateCanResize();
+ // Rebind a surface as the root surface of the shell surface.
+ void RebindRootSurface(Surface* root_surface,
+ bool can_minimize,
+ int container);
+
// Returns a trace value representing the state of the surface.
std::unique_ptr<base::trace_event::TracedValue> AsTracedValue() const;
@@ -145,6 +150,10 @@ class ShellSurfaceBase : public SurfaceTreeHost,
~OverlayParams();
bool translucent = false;
+ bool overlaps_frame = true;
+ absl::optional<bool> can_resize;
+ // TODO(oshima): It's unlikely for overlay not to request focus.
+ // Remove this.
bool focusable = true;
std::unique_ptr<views::View> contents_view;
};
@@ -175,6 +184,8 @@ class ShellSurfaceBase : public SurfaceTreeHost,
void UnsetSnap() override;
void OnActivationRequested() override;
void OnSetServerStartResize() override;
+ void SetCanGoBack() override;
+ void UnsetCanGoBack() override;
// SurfaceObserver:
void OnSurfaceDestroying(Surface* surface) override;
@@ -233,6 +244,10 @@ class ShellSurfaceBase : public SurfaceTreeHost,
bool server_side_resize() const { return server_side_resize_; }
+ const views::Widget* overlay_widget_for_testing() const {
+ return overlay_widget_.get();
+ }
+
protected:
// Creates the |widget_| for |surface_|. |show_state| is the initial state
// of the widget (e.g. maximized).
@@ -300,7 +315,7 @@ class ShellSurfaceBase : public SurfaceTreeHost,
gfx::Rect pending_geometry_;
int64_t display_id_ = display::kInvalidDisplayId;
int64_t pending_display_id_ = display::kInvalidDisplayId;
- base::Optional<gfx::Rect> shadow_bounds_;
+ absl::optional<gfx::Rect> shadow_bounds_;
bool shadow_bounds_changed_ = false;
SurfaceFrameType frame_type_ = SurfaceFrameType::NONE;
bool is_popup_ = false;
@@ -320,7 +335,7 @@ class ShellSurfaceBase : public SurfaceTreeHost,
// Return the bounds of the widget/origin of surface taking visible
// bounds and current resize direction into account.
- virtual base::Optional<gfx::Rect> GetWidgetBounds() const = 0;
+ virtual absl::optional<gfx::Rect> GetWidgetBounds() const = 0;
virtual gfx::Point GetSurfaceOrigin() const = 0;
// Commit is deferred if this returns false.
@@ -337,8 +352,8 @@ class ShellSurfaceBase : public SurfaceTreeHost,
SkColor active_frame_color_ = SK_ColorBLACK;
SkColor inactive_frame_color_ = SK_ColorBLACK;
bool pending_show_widget_ = false;
- base::Optional<std::string> application_id_;
- base::Optional<std::string> startup_id_;
+ absl::optional<std::string> application_id_;
+ absl::optional<std::string> startup_id_;
bool immersive_implied_by_fullscreen_ = true;
base::RepeatingClosure close_callback_;
base::RepeatingClosure pre_close_callback_;
@@ -351,8 +366,11 @@ class ShellSurfaceBase : public SurfaceTreeHost,
gfx::Size pending_maximum_size_;
gfx::SizeF pending_aspect_ratio_;
- bool skip_ime_processing_ = false;
+ // Overlay members.
std::unique_ptr<views::Widget> overlay_widget_;
+ bool skip_ime_processing_ = false;
+ bool overlay_overlaps_frame_ = true;
+ absl::optional<bool> overlay_can_resize_;
DISALLOW_COPY_AND_ASSIGN(ShellSurfaceBase);
};
diff --git a/chromium/components/exo/shell_surface_unittest.cc b/chromium/components/exo/shell_surface_unittest.cc
index 8ad30045f5a..718ebe639bd 100644
--- a/chromium/components/exo/shell_surface_unittest.cc
+++ b/chromium/components/exo/shell_surface_unittest.cc
@@ -18,7 +18,6 @@
#include "ash/wm/workspace_controller_test_api.h"
#include "base/bind.h"
#include "base/callback.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "components/exo/buffer.h"
@@ -49,9 +48,6 @@
#include "ui/wm/core/shadow_types.h"
#include "ui/wm/core/window_util.h"
-#include "ash/wm/resize_shadow.h"
-#include "ash/wm/resize_shadow_controller.h"
-
namespace exo {
using ShellSurfaceTest = test::ExoTestBase;
@@ -486,7 +482,7 @@ TEST_F(ShellSurfaceTest, EmulateOverrideRedirect) {
// manager.
EXPECT_TRUE(ash::WindowState::Get(child_window)->allow_set_bounds_direct());
EXPECT_EQ(ash::kShellWindowId_ShelfBubbleContainer,
- child_window->parent()->id());
+ child_window->parent()->GetId());
// NONE/SHADOW frame type should work on override redirect.
child_surface->SetFrame(SurfaceFrameType::SHADOW);
@@ -982,7 +978,7 @@ TEST_F(ShellSurfaceTest, Popup) {
// Verify that created shell surface is popup and has capture.
EXPECT_EQ(aura::client::WINDOW_TYPE_POPUP,
- popup_shell_surface->GetWidget()->GetNativeWindow()->type());
+ popup_shell_surface->GetWidget()->GetNativeWindow()->GetType());
EXPECT_EQ(WMHelper::GetInstance()->GetCaptureClient()->GetCaptureWindow(),
popup_shell_surface->GetWidget()->GetNativeWindow());
@@ -1006,7 +1002,7 @@ TEST_F(ShellSurfaceTest, Popup) {
// The capture should be on sub_popup_shell_surface.
EXPECT_EQ(WMHelper::GetInstance()->GetCaptureClient()->GetCaptureWindow(),
target);
- EXPECT_EQ(aura::client::WINDOW_TYPE_POPUP, target->type());
+ EXPECT_EQ(aura::client::WINDOW_TYPE_POPUP, target->GetType());
{
// Mouse is on the top most popup.
@@ -1080,7 +1076,7 @@ TEST_F(ShellSurfaceTest, PopupWithInputRegion) {
// Verify that created shell surface is popup and has capture.
EXPECT_EQ(aura::client::WINDOW_TYPE_POPUP,
- popup_shell_surface->GetWidget()->GetNativeWindow()->type());
+ popup_shell_surface->GetWidget()->GetNativeWindow()->GetType());
EXPECT_EQ(WMHelper::GetInstance()->GetCaptureClient()->GetCaptureWindow(),
popup_shell_surface->GetWidget()->GetNativeWindow());
@@ -1455,6 +1451,11 @@ TEST_F(ShellSurfaceTest, Overlay) {
EXPECT_NE(shell_surface->GetWidget()->GetFocusManager()->GetFocusedView(),
textfield_ptr);
+ EXPECT_TRUE(shell_surface->GetWidget()->widget_delegate()->CanResize());
+ EXPECT_EQ(gfx::Size(100, 100), shell_surface->overlay_widget_for_testing()
+ ->GetWindowBoundsInScreen()
+ .size());
+
ui::test::EventGenerator* generator = GetEventGenerator();
generator->PressKey(ui::VKEY_X, 0);
generator->ReleaseKey(ui::VKEY_X, 0);
@@ -1500,4 +1501,61 @@ TEST_F(ShellSurfaceTest, Overlay) {
EXPECT_TRUE(textfield_ptr->GetSelectedText().empty());
}
+TEST_F(ShellSurfaceTest, OverlayOverlapsFrame) {
+ auto shell_surface =
+ test::ShellSurfaceBuilder({100, 100}).BuildShellSurface();
+ shell_surface->GetWidget()->GetNativeWindow()->SetProperty(
+ aura::client::kSkipImeProcessing, true);
+ shell_surface->OnSetFrame(SurfaceFrameType::NORMAL);
+
+ EXPECT_FALSE(shell_surface->HasOverlay());
+
+ ShellSurfaceBase::OverlayParams params(std::make_unique<views::View>());
+ params.overlaps_frame = false;
+ shell_surface->AddOverlay(std::move(params));
+ EXPECT_TRUE(shell_surface->HasOverlay());
+
+ {
+ gfx::Size overlay_size =
+ shell_surface->GetWidget()->GetWindowBoundsInScreen().size();
+ overlay_size.set_height(overlay_size.height() - views::kCaptionButtonWidth);
+ EXPECT_EQ(overlay_size, shell_surface->overlay_widget_for_testing()
+ ->GetWindowBoundsInScreen()
+ .size());
+ }
+
+ shell_surface->OnSetFrame(SurfaceFrameType::NONE);
+ {
+ gfx::Size overlay_size =
+ shell_surface->GetWidget()->GetWindowBoundsInScreen().size();
+ EXPECT_EQ(overlay_size, shell_surface->overlay_widget_for_testing()
+ ->GetWindowBoundsInScreen()
+ .size());
+ }
+}
+
+TEST_F(ShellSurfaceTest, OverlayCanResize) {
+ auto shell_surface =
+ test::ShellSurfaceBuilder({100, 100}).BuildShellSurface();
+ shell_surface->GetWidget()->GetNativeWindow()->SetProperty(
+ aura::client::kSkipImeProcessing, true);
+ shell_surface->OnSetFrame(SurfaceFrameType::NORMAL);
+
+ EXPECT_FALSE(shell_surface->HasOverlay());
+ {
+ ShellSurfaceBase::OverlayParams params(std::make_unique<views::View>());
+ params.can_resize = false;
+ shell_surface->AddOverlay(std::move(params));
+ }
+ EXPECT_FALSE(shell_surface->GetWidget()->widget_delegate()->CanResize());
+
+ shell_surface->RemoveOverlay();
+ {
+ ShellSurfaceBase::OverlayParams params(std::make_unique<views::View>());
+ params.can_resize = true;
+ shell_surface->AddOverlay(std::move(params));
+ }
+ EXPECT_TRUE(shell_surface->GetWidget()->widget_delegate()->CanResize());
+}
+
} // namespace exo
diff --git a/chromium/components/exo/shell_surface_util.cc b/chromium/components/exo/shell_surface_util.cc
index c3e4ccaf539..9e04e9e81d5 100644
--- a/chromium/components/exo/shell_surface_util.cc
+++ b/chromium/components/exo/shell_surface_util.cc
@@ -24,6 +24,7 @@
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chromeos/ui/base/window_properties.h"
+#include "components/exo/client_controlled_shell_surface.h"
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
namespace exo {
@@ -43,6 +44,13 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kStartupIdKey, nullptr)
// Accessibility Id set by the client.
DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kClientAccessibilityIdKey, -1)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+// A property key containing the client controlled shell surface.
+DEFINE_UI_CLASS_PROPERTY_KEY(ClientControlledShellSurface*,
+ kClientControlledShellSurface,
+ nullptr)
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+
// Returns true if the component for a located event should be taken care of
// by the window system.
bool ShouldHTComponentBlocked(int component) {
@@ -74,7 +82,7 @@ aura::WindowTargeter* FindTargeter(ui::EventTarget* target) {
} // namespace
void SetShellApplicationId(ui::PropertyHandler* property_handler,
- const base::Optional<std::string>& id) {
+ const absl::optional<std::string>& id) {
TRACE_EVENT1("exo", "SetApplicationId", "application_id", id ? *id : "null");
if (id)
@@ -88,7 +96,7 @@ const std::string* GetShellApplicationId(const aura::Window* property_handler) {
}
void SetShellStartupId(ui::PropertyHandler* property_handler,
- const base::Optional<std::string>& id) {
+ const absl::optional<std::string>& id) {
TRACE_EVENT1("exo", "SetStartupId", "startup_id", id ? *id : "null");
if (id)
@@ -97,7 +105,7 @@ void SetShellStartupId(ui::PropertyHandler* property_handler,
property_handler->ClearProperty(kStartupIdKey);
}
-const std::string* GetShellStartupId(aura::Window* window) {
+const std::string* GetShellStartupId(const aura::Window* window) {
return window->GetProperty(kStartupIdKey);
}
@@ -112,7 +120,7 @@ void SetShellUseImmersiveForFullscreen(aura::Window* window, bool value) {
}
void SetShellClientAccessibilityId(aura::Window* window,
- const base::Optional<int32_t>& id) {
+ const absl::optional<int32_t>& id) {
TRACE_EVENT1("exo", "SetClientAccessibilityId", "id",
id ? base::NumberToString(*id) : "null");
@@ -122,15 +130,34 @@ void SetShellClientAccessibilityId(aura::Window* window,
window->ClearProperty(kClientAccessibilityIdKey);
}
-const base::Optional<int32_t> GetShellClientAccessibilityId(
+const absl::optional<int32_t> GetShellClientAccessibilityId(
aura::Window* window) {
auto id = window->GetProperty(kClientAccessibilityIdKey);
if (id < 0)
- return base::nullopt;
+ return absl::nullopt;
else
return id;
}
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+
+void SetShellClientControlledShellSurface(
+ ui::PropertyHandler* property_handler,
+ const absl::optional<ClientControlledShellSurface*>& shell_surface) {
+ if (shell_surface)
+ property_handler->SetProperty(kClientControlledShellSurface,
+ shell_surface.value());
+ else
+ property_handler->ClearProperty(kClientControlledShellSurface);
+}
+
+ClientControlledShellSurface* GetShellClientControlledShellSurface(
+ ui::PropertyHandler* property_handler) {
+ return property_handler->GetProperty(kClientControlledShellSurface);
+}
+
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+
void SetShellRootSurface(ui::PropertyHandler* property_handler,
Surface* surface) {
property_handler->SetProperty(kRootSurfaceKey, surface);
@@ -147,7 +174,14 @@ ShellSurfaceBase* GetShellSurfaceBaseForWindow(aura::Window* window) {
views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
if (!widget)
return nullptr;
- return static_cast<ShellSurfaceBase*>(widget->widget_delegate());
+ ShellSurfaceBase* shell_surface_base =
+ static_cast<ShellSurfaceBase*>(widget->widget_delegate());
+ // We can obtain widget from native window, but not |shell_surface_base|.
+ // This means we are in the process of destroying this surface so we should
+ // return nullptr.
+ if (!shell_surface_base || !shell_surface_base->GetWidget())
+ return nullptr;
+ return shell_surface_base;
}
Surface* GetTargetSurfaceForLocatedEvent(
@@ -192,7 +226,6 @@ Surface* GetTargetSurfaceForLocatedEvent(
aura::Window* focused =
static_cast<aura::Window*>(targeter->FindTargetForEvent(window, event));
-
if (focused) {
Surface* surface = Surface::AsSurface(focused);
if (focused != window)
@@ -224,6 +257,28 @@ Surface* GetTargetSurfaceForLocatedEvent(
}
}
+Surface* GetTargetSurfaceForKeyboardFocus(aura::Window* window) {
+ if (!window)
+ return nullptr;
+ // The keyboard focus should be set to the root surface.
+ ShellSurfaceBase* shell_surface_base = nullptr;
+ for (auto* current = window; current && !shell_surface_base;
+ current = current->parent()) {
+ shell_surface_base = GetShellSurfaceBaseForWindow(current);
+ }
+ // Make sure the |window| is the toplevel or a host window, but not
+ // another window added to the toplevel.
+ if (shell_surface_base && !shell_surface_base->HasOverlay() &&
+ (shell_surface_base->GetWidget()->GetNativeWindow() == window ||
+ shell_surface_base->host_window()->Contains(window))) {
+ return shell_surface_base->root_surface();
+ }
+
+ // Fallback to the window's surface if any. This is used for
+ // notifications.
+ return Surface::AsSurface(window);
+}
+
void GrantPermissionToActivate(aura::Window* window, base::TimeDelta timeout) {
// Activation is the only permission, so just set the property. The window
// owns the Permission object.
diff --git a/chromium/components/exo/shell_surface_util.h b/chromium/components/exo/shell_surface_util.h
index 7f491eefffd..1ca5d25d7ed 100644
--- a/chromium/components/exo/shell_surface_util.h
+++ b/chromium/components/exo/shell_surface_util.h
@@ -8,7 +8,8 @@
#include <memory>
#include <string>
-#include "base/optional.h"
+#include "build/chromeos_buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ui {
class PropertyHandler;
@@ -29,33 +30,43 @@ class KeyEvent;
namespace exo {
+class ClientControlledShellSurface;
class Surface;
class ShellSurfaceBase;
// Sets the application ID to the property_handler. The application ID
// identifies the general class of applications to which the window belongs.
void SetShellApplicationId(ui::PropertyHandler* property_handler,
- const base::Optional<std::string>& id);
+ const absl::optional<std::string>& id);
const std::string* GetShellApplicationId(const aura::Window* window);
// Sets the startup ID to the property handler. The startup ID identifies the
// application using startup notification protocol.
void SetShellStartupId(ui::PropertyHandler* property_handler,
- const base::Optional<std::string>& id);
-const std::string* GetShellStartupId(aura::Window* window);
+ const absl::optional<std::string>& id);
+const std::string* GetShellStartupId(const aura::Window* window);
-// Hides/shows the shelf when fullscreen. If true, shelf is inaccessible
-// (plain fullscreen). If false, shelf auto-hides and can be shown with a
-// mouse gesture (immersive fullscreen).
+// Shows/hides the shelf when fullscreen. If true, titlebar/shelf will show when
+// the mouse moves to the top/bottom of the screen. If false (plain fullscreen),
+// the titlebar and shelf are always hidden.
void SetShellUseImmersiveForFullscreen(aura::Window* window, bool value);
// Sets the client accessibility ID for the window. The accessibility ID
// identifies the accessibility tree provided by client.
void SetShellClientAccessibilityId(aura::Window* window,
- const base::Optional<int32_t>& id);
-const base::Optional<int32_t> GetShellClientAccessibilityId(
+ const absl::optional<int32_t>& id);
+const absl::optional<int32_t> GetShellClientAccessibilityId(
aura::Window* window);
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+// Sets the ClientControlledShellSurface to the property handler.
+void SetShellClientControlledShellSurface(
+ ui::PropertyHandler* property_handler,
+ const absl::optional<ClientControlledShellSurface*>& shell_surface);
+ClientControlledShellSurface* GetShellClientControlledShellSurface(
+ ui::PropertyHandler* property_handler);
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+
// Sets the root surface to the property handler.
void SetShellRootSurface(ui::PropertyHandler* property_handler,
Surface* surface);
@@ -74,6 +85,12 @@ ShellSurfaceBase* GetShellSurfaceBaseForWindow(aura::Window* window);
// requested grab.
Surface* GetTargetSurfaceForLocatedEvent(const ui::LocatedEvent* event);
+// Returns the focused surface for given 'focused_window'. If a surface is
+// attached to the window, this will return that surface. If the window is
+// either the shell surface's window, or host window, it will return the root
+// surface, otherwise returns nullptr.
+Surface* GetTargetSurfaceForKeyboardFocus(aura::Window* focused_window);
+
// Allows the |window| to activate itself for the duration of |timeout|. Revokes
// any existing permission.
void GrantPermissionToActivate(aura::Window* window, base::TimeDelta timeout);
diff --git a/chromium/components/exo/shell_surface_util_unittest.cc b/chromium/components/exo/shell_surface_util_unittest.cc
new file mode 100644
index 00000000000..83295543691
--- /dev/null
+++ b/chromium/components/exo/shell_surface_util_unittest.cc
@@ -0,0 +1,107 @@
+// Copyright 2021 The Chromium Authors. 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/shell_surface_util.h"
+
+#include "components/exo/buffer.h"
+#include "components/exo/display.h"
+#include "components/exo/shell_surface.h"
+#include "components/exo/shell_surface_util.h"
+#include "components/exo/test/exo_test_base.h"
+#include "components/exo/test/shell_surface_builder.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event.h"
+
+namespace exo {
+namespace {
+
+using ShellSurfaceUtilTest = test::ExoTestBase;
+
+void SetPositionAtOrigin(ui::LocatedEvent* event, aura::Window* target) {
+ ui::Event::DispatcherApi test_api(event);
+ test_api.set_target(target);
+ gfx::Point point;
+ aura::Window::ConvertPointToTarget(target, target->GetRootWindow(), &point);
+ event->set_location(point);
+}
+
+TEST_F(ShellSurfaceUtilTest, TargetForLocatedEvent) {
+ auto shell_surface = test::ShellSurfaceBuilder({20, 20})
+ .SetOrigin({10, 10})
+ .BuildShellSurface();
+ auto* root_surface = shell_surface->root_surface();
+ auto* child_surface = test::ShellSurfaceBuilder::AddChildSurface(
+ root_surface, {10, 10, 10, 10});
+ child_surface->Commit();
+ root_surface->Commit();
+
+ ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(0, 0),
+ gfx::Point(0, 0), ui::EventTimeForNow(), 0, 0);
+ aura::Window* root_window = root_surface->window()->GetRootWindow();
+ ui::Event::DispatcherApi(&mouse_event).set_target(root_window);
+ EXPECT_EQ(nullptr, GetTargetSurfaceForLocatedEvent(&mouse_event));
+
+ SetPositionAtOrigin(&mouse_event, root_surface->window());
+ EXPECT_EQ(root_surface, GetTargetSurfaceForLocatedEvent(&mouse_event));
+ SetPositionAtOrigin(&mouse_event, child_surface->window());
+ EXPECT_EQ(child_surface, GetTargetSurfaceForLocatedEvent(&mouse_event));
+
+ // Capture
+ auto* shell_surface_window = shell_surface->GetWidget()->GetNativeWindow();
+ shell_surface_window->SetCapture();
+ ui::Event::DispatcherApi(&mouse_event).set_target(shell_surface_window);
+ mouse_event.set_location({-1, -1});
+ EXPECT_EQ(root_surface, GetTargetSurfaceForLocatedEvent(&mouse_event));
+ mouse_event.set_location({1, 1});
+ EXPECT_EQ(root_surface, GetTargetSurfaceForLocatedEvent(&mouse_event));
+ mouse_event.set_location({11, 11});
+ EXPECT_EQ(child_surface, GetTargetSurfaceForLocatedEvent(&mouse_event));
+ shell_surface.reset();
+}
+
+TEST_F(ShellSurfaceUtilTest, TargetForKeyboardFocus) {
+ auto shell_surface = test::ShellSurfaceBuilder({20, 20})
+ .SetOrigin({10, 10})
+ .BuildShellSurface();
+ auto* root_surface = shell_surface->root_surface();
+ auto* child_surface = test::ShellSurfaceBuilder::AddChildSurface(
+ root_surface, {10, 10, 10, 10});
+
+ EXPECT_EQ(root_surface,
+ GetTargetSurfaceForKeyboardFocus(child_surface->window()));
+ EXPECT_EQ(root_surface,
+ GetTargetSurfaceForKeyboardFocus(root_surface->window()));
+ EXPECT_EQ(root_surface,
+ GetTargetSurfaceForKeyboardFocus(shell_surface->host_window()));
+ EXPECT_EQ(root_surface, GetTargetSurfaceForKeyboardFocus(
+ shell_surface->GetWidget()->GetNativeWindow()));
+}
+
+TEST_F(ShellSurfaceUtilTest, ClientControlledTargetForKeyboardFocus) {
+ Display display;
+
+ gfx::Size buffer_size(256, 256);
+ std::unique_ptr<Buffer> buffer(
+ new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
+
+ std::unique_ptr<Surface> surface(new Surface);
+ surface->Attach(buffer.get());
+ surface->Commit();
+
+ auto shell_surface(
+ exo_test_helper()->CreateClientControlledShellSurface(surface.get()));
+ shell_surface->set_delegate(
+ std::make_unique<test::ClientControlledShellSurfaceDelegate>(
+ shell_surface.get(), true));
+ shell_surface->SetMinimized();
+ surface->Commit();
+
+ shell_surface->GetWidget()->Hide();
+ shell_surface->OnSurfaceCommit();
+
+ shell_surface->GetWidget()->GetNativeWindow()->Focus();
+}
+
+} // namespace
+} // namespace exo
diff --git a/chromium/components/exo/sub_surface.h b/chromium/components/exo/sub_surface.h
index 5b8a8718bbe..45416f40aaa 100644
--- a/chromium/components/exo/sub_surface.h
+++ b/chromium/components/exo/sub_surface.h
@@ -68,6 +68,8 @@ class SubSurface : public SurfaceDelegate, public SurfaceObserver {
void SetSnappedToLeft() override {}
void SetSnappedToRight() override {}
void UnsetSnap() override {}
+ void SetCanGoBack() override {}
+ void UnsetCanGoBack() override {}
// Overridden from SurfaceObserver:
void OnSurfaceDestroying(Surface* surface) override;
diff --git a/chromium/components/exo/surface.cc b/chromium/components/exo/surface.cc
index 471d727412b..34fd2515769 100644
--- a/chromium/components/exo/surface.cc
+++ b/chromium/components/exo/surface.cc
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
+#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#include "build/build_config.h"
@@ -29,7 +30,6 @@
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/resources/resource_id.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/aura/client/aura_constants.h"
@@ -122,7 +122,7 @@ bool IsDeskContainer(aura::Window* container) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
return ash::desks_util::IsDeskContainer(container);
#else
- return container->id() == ash::kShellWindowId_DefaultContainerDeprecated;
+ return container->GetId() == ash::kShellWindowId_DefaultContainerDeprecated;
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
}
@@ -167,7 +167,7 @@ class CustomWindowDelegate : public aura::WindowDelegate {
void OnWindowDestroyed(aura::Window* window) override { delete this; }
void OnWindowTargetVisibilityChanged(bool visible) override {}
void OnWindowOcclusionChanged(
- aura::Window::OcclusionState occlusion_state) override {
+ aura::Window::OcclusionState GetOcclusionState) override {
surface_->OnWindowOcclusionChanged();
}
bool HasHitTestMask() const override { return true; }
@@ -346,7 +346,7 @@ void Surface::SetInputRegion(const cc::Region& region) {
void Surface::ResetInputRegion() {
TRACE_EVENT0("exo", "Surface::ResetInputRegion");
- pending_state_.basic_state.input_region = base::nullopt;
+ pending_state_.basic_state.input_region = absl::nullopt;
}
void Surface::SetInputOutset(int outset) {
@@ -382,6 +382,10 @@ void Surface::AddSubSurface(Surface* sub_surface) {
sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point()));
sub_surfaces_changed_ = true;
+ // Propagate the kSkipImeProcessing property to the new child.
+ if (window_->GetProperty(aura::client::kSkipImeProcessing))
+ sub_surface->window()->SetProperty(aura::client::kSkipImeProcessing, true);
+
// The shell might have not be added to the root yet.
if (window_->GetRootWindow()) {
auto display =
@@ -596,6 +600,16 @@ void Surface::UnsetSnap() {
delegate_->UnsetSnap();
}
+void Surface::SetCanGoBack() {
+ if (delegate_)
+ delegate_->SetCanGoBack();
+}
+
+void Surface::UnsetCanGoBack() {
+ if (delegate_)
+ delegate_->UnsetCanGoBack();
+}
+
void Surface::SetColorSpace(gfx::ColorSpace color_space) {
TRACE_EVENT1("exo", "Surface::SetColorSpace", "color_space",
color_space.ToString());
@@ -1214,13 +1228,12 @@ void Surface::AppendContentsToFrame(const gfx::Point& origin,
viz::SharedQuadState* quad_state =
render_pass->CreateAndAppendSharedQuadState();
- quad_state->SetAll(quad_to_target_transform, quad_rect /*quad_layer_rect=*/,
- quad_rect /*visible_quad_layer_rect=*/,
- gfx::MaskFilterInfo() /*mask_filter_info=*/,
- gfx::Rect() /*clip_rect=*/, false /*is_clipped=*/,
- are_contents_opaque, state_.basic_state.alpha /*opacity=*/,
- SkBlendMode::kSrcOver /*blend_mode=*/,
- 0 /*sorting_context_id=*/);
+ quad_state->SetAll(
+ quad_to_target_transform, quad_rect /*quad_layer_rect=*/,
+ quad_rect /*visible_quad_layer_rect=*/,
+ gfx::MaskFilterInfo() /*mask_filter_info=*/, absl::nullopt /*clip_rect=*/,
+ are_contents_opaque, state_.basic_state.alpha /*opacity=*/,
+ SkBlendMode::kSrcOver /*blend_mode=*/, 0 /*sorting_context_id=*/);
quad_state->no_damage = damage_rect.IsEmpty();
if (current_resource_.id) {
@@ -1258,7 +1271,6 @@ void Surface::AppendContentsToFrame(const gfx::Point& origin,
if (latest_embedded_surface_id_.is_valid() &&
!embedded_surface_size_.IsEmpty()) {
if (!state_.basic_state.crop.IsEmpty()) {
- quad_state->is_clipped = true;
quad_state->clip_rect = output_rect;
}
viz::SurfaceDrawQuad* surface_quad =
diff --git a/chromium/components/exo/surface.h b/chromium/components/exo/surface.h
index eee206535f3..93161022e2c 100644
--- a/chromium/components/exo/surface.h
+++ b/chromium/components/exo/surface.h
@@ -41,6 +41,7 @@ class TracedValue;
namespace gfx {
class ColorSpace;
class GpuFence;
+struct PresentationFeedback;
}
namespace viz {
@@ -184,9 +185,9 @@ class Surface final : public ui::PropertyHandler {
// Request that surface should have a specific application ID string.
void SetApplicationId(const char* application_id);
- // Whether to hide the shelf when fullscreen. If true, shelf is inaccessible
- // (plain fullscreen). If false, shelf auto-hides and can be shown with a
- // mouse gesture (immersive fullscreen).
+ // Whether to show/hide the shelf when fullscreen. If true, the titlebar/shelf
+ // will show when the mouse moves to the top/bottom of the screen. If false
+ // (plain fullscreen), the titlebar and shelf are always hidden.
void SetUseImmersiveForFullscreen(bool value);
// Called to show the snap preview to the right or left, or to hide it.
@@ -199,6 +200,10 @@ class Surface final : public ui::PropertyHandler {
void SetSnappedToLeft();
void UnsetSnap();
+ // Whether the current client window can go back, as per its navigation list.
+ void SetCanGoBack();
+ void UnsetCanGoBack();
+
// This sets the color space for the buffer for this surface.
void SetColorSpace(gfx::ColorSpace color_space);
@@ -342,7 +347,7 @@ class Surface final : public ui::PropertyHandler {
bool operator!=(const State& other) const { return !(*this == other); }
cc::Region opaque_region;
- base::Optional<cc::Region> input_region;
+ absl::optional<cc::Region> input_region;
int input_outset = 0;
float buffer_scale = 1.0f;
Transform buffer_transform = Transform::NORMAL;
diff --git a/chromium/components/exo/surface_delegate.h b/chromium/components/exo/surface_delegate.h
index bfabc2bdf2c..61bc97a0dbd 100644
--- a/chromium/components/exo/surface_delegate.h
+++ b/chromium/components/exo/surface_delegate.h
@@ -44,9 +44,9 @@ class SurfaceDelegate {
// Called when surface was requested to set a specific application ID label.
virtual void OnSetApplicationId(const char* application_id) = 0;
- // Whether to hide the shelf when fullscreen. If true, shelf is inaccessible
- // (plain fullscreen). If false, shelf auto-hides and can be shown with a
- // mouse gesture (immersive fullscreen).
+ // Whether to show/hide the shelf when fullscreen. If true, the titlebar/shelf
+ // will show when the mouse moves to the top/bottom of the screen. If false
+ // (plain fullscreen), the titlebar and shelf are always hidden.
virtual void SetUseImmersiveForFullscreen(bool value) = 0;
// Called when the surface's application wants it to be activated.
@@ -68,6 +68,10 @@ class SurfaceDelegate {
virtual void SetSnappedToRight() = 0;
virtual void UnsetSnap() = 0;
+ // Whether the current client window can go back, as per its navigation list.
+ virtual void SetCanGoBack() = 0;
+ virtual void UnsetCanGoBack() = 0;
+
protected:
virtual ~SurfaceDelegate() {}
};
diff --git a/chromium/components/exo/surface_tree_host.cc b/chromium/components/exo/surface_tree_host.cc
index d12527519ae..5d217a8d42b 100644
--- a/chromium/components/exo/surface_tree_host.cc
+++ b/chromium/components/exo/surface_tree_host.cc
@@ -31,6 +31,7 @@
#include "ui/aura/window_targeter.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/dip_util.h"
@@ -299,9 +300,9 @@ void SurfaceTreeHost::SubmitEmptyCompositorFrame() {
render_pass->CreateAndAppendSharedQuadState();
quad_state->SetAll(
gfx::Transform(), /*quad_layer_rect=*/quad_rect,
- /*visible_quad_layer_rect=*/quad_rect,
- /*mask_filter_info=*/gfx::MaskFilterInfo(), /*clip_rect=*/gfx::Rect(),
- /*is_clipped=*/false, /*are_contents_opaque=*/true, /*opacity=*/1.f,
+ /*visible_layer_rect=*/quad_rect,
+ /*mask_filter_info=*/gfx::MaskFilterInfo(), /*clip_rect=*/absl::nullopt,
+ /*are_contents_opaque=*/true, /*opacity=*/1.f,
/*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
viz::SolidColorDrawQuad* solid_quad =
diff --git a/chromium/components/exo/surface_tree_host.h b/chromium/components/exo/surface_tree_host.h
index d067eb7fd6f..e4856eaa1e2 100644
--- a/chromium/components/exo/surface_tree_host.h
+++ b/chromium/components/exo/surface_tree_host.h
@@ -101,6 +101,8 @@ class SurfaceTreeHost : public SurfaceDelegate,
void SetSnappedToLeft() override {}
void SetSnappedToRight() override {}
void UnsetSnap() override {}
+ void SetCanGoBack() override {}
+ void UnsetCanGoBack() override {}
// display::DisplayObserver:
void OnDisplayMetricsChanged(const display::Display& display,
diff --git a/chromium/components/exo/surface_unittest.cc b/chromium/components/exo/surface_unittest.cc
index 5d89e0cf0bf..dc34ffbb584 100644
--- a/chromium/components/exo/surface_unittest.cc
+++ b/chromium/components/exo/surface_unittest.cc
@@ -20,6 +20,7 @@
#include "components/viz/test/fake_external_begin_frame_source.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/khronos/GLES2/gl2.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/layer_tree_owner.h"
#include "ui/display/display.h"
#include "ui/display/display_switches.h"
@@ -1306,7 +1307,7 @@ TEST_P(SurfaceTest, UpdatesOcclusionOnDestroyingSubsurface) {
sub_surface.reset();
EXPECT_EQ(1, observer.num_occlusion_changes());
EXPECT_EQ(aura::Window::OcclusionState::HIDDEN,
- child_surface->window()->occlusion_state());
+ child_surface->window()->GetOcclusionState());
}
} // namespace
diff --git a/chromium/components/exo/text_input.cc b/chromium/components/exo/text_input.cc
index 8e337549f60..b91a34bb80d 100644
--- a/chromium/components/exo/text_input.cc
+++ b/chromium/components/exo/text_input.cc
@@ -73,6 +73,12 @@ void TextInput::Resync() {
input_method_->OnCaretBoundsChanged(this);
}
+void TextInput::Reset() {
+ composition_ = ui::CompositionText();
+ if (input_method_)
+ input_method_->CancelComposition(this);
+}
+
void TextInput::SetSurroundingText(const std::u16string& text,
uint32_t cursor_pos,
uint32_t anchor) {
@@ -122,6 +128,7 @@ uint32_t TextInput::ConfirmCompositionText(bool keep_selection) {
const uint32_t composition_text_length =
static_cast<uint32_t>(composition_.text.length());
delegate_->Commit(composition_.text);
+ composition_ = ui::CompositionText();
return composition_text_length;
}
@@ -180,6 +187,11 @@ gfx::Rect TextInput::GetCaretBounds() const {
return caret_bounds_ + window_->GetBoundsInScreen().OffsetFromOrigin();
}
+gfx::Rect TextInput::GetSelectionBoundingBox() const {
+ NOTIMPLEMENTED();
+ return gfx::Rect();
+}
+
bool TextInput::GetCompositionCharacterBounds(uint32_t index,
gfx::Rect* rect) const {
return false;
@@ -365,6 +377,26 @@ bool TextInput::SetAutocorrectRange(const gfx::Range& range) {
return false;
}
+absl::optional<ui::GrammarFragment> TextInput::GetGrammarFragment(
+ const gfx::Range& range) {
+ // TODO(https://crbug.com/1201454): Implement this method.
+ NOTIMPLEMENTED_LOG_ONCE();
+ return absl::nullopt;
+}
+
+bool TextInput::ClearGrammarFragments(const gfx::Range& range) {
+ // TODO(https://crbug.com/1201454): Implement this method.
+ NOTIMPLEMENTED_LOG_ONCE();
+ return false;
+}
+
+bool TextInput::AddGrammarFragments(
+ const std::vector<ui::GrammarFragment>& fragments) {
+ // TODO(https://crbug.com/1201454): Implement this method.
+ NOTIMPLEMENTED_LOG_ONCE();
+ return false;
+}
+
void TextInput::OnKeyboardVisibilityChanged(bool is_visible) {
delegate_->OnVirtualKeyboardVisibilityChanged(is_visible);
}
diff --git a/chromium/components/exo/text_input.h b/chromium/components/exo/text_input.h
index bdb6c223a02..70b8fbd4c25 100644
--- a/chromium/components/exo/text_input.h
+++ b/chromium/components/exo/text_input.h
@@ -9,7 +9,7 @@
#include "ash/public/cpp/keyboard/keyboard_controller_observer.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_flags.h"
#include "ui/base/ime/text_input_mode.h"
@@ -87,6 +87,9 @@ class TextInput : public ui::TextInputClient,
// during the text input session.
void Resync();
+ // Resets the current input method state.
+ void Reset();
+
// Sets the surrounding text in the app.
void SetSurroundingText(const std::u16string& text,
uint32_t cursor_pos,
@@ -116,6 +119,7 @@ class TextInput : public ui::TextInputClient,
int GetTextInputFlags() const override;
bool CanComposeInline() const override;
gfx::Rect GetCaretBounds() const override;
+ gfx::Rect GetSelectionBoundingBox() const override;
bool GetCompositionCharacterBounds(uint32_t index,
gfx::Rect* rect) const override;
bool HasCompositionText() const override;
@@ -142,6 +146,11 @@ class TextInput : public ui::TextInputClient,
gfx::Range GetAutocorrectRange() const override;
gfx::Rect GetAutocorrectCharacterBounds() const override;
bool SetAutocorrectRange(const gfx::Range& range) override;
+ absl::optional<ui::GrammarFragment> GetGrammarFragment(
+ const gfx::Range& range) override;
+ bool ClearGrammarFragments(const gfx::Range& range) override;
+ bool AddGrammarFragments(
+ const std::vector<ui::GrammarFragment>& fragments) override;
// ash::KeyboardControllerObserver:
void OnKeyboardVisibilityChanged(bool is_visible) override;
@@ -163,7 +172,7 @@ class TextInput : public ui::TextInputClient,
bool should_do_learning_ = true;
ui::CompositionText composition_;
std::u16string surrounding_text_;
- base::Optional<gfx::Range> cursor_pos_;
+ absl::optional<gfx::Range> cursor_pos_;
base::i18n::TextDirection direction_ = base::i18n::UNKNOWN_DIRECTION;
DISALLOW_COPY_AND_ASSIGN(TextInput);
@@ -171,4 +180,4 @@ class TextInput : public ui::TextInputClient,
} // namespace exo
-#endif // COMPONENTS_EXO_KEYBOARD_H_
+#endif // COMPONENTS_EXO_TEXT_INPUT_H_
diff --git a/chromium/components/exo/text_input_unittest.cc b/chromium/components/exo/text_input_unittest.cc
index bab11a6c1e8..7979da2c2a0 100644
--- a/chromium/components/exo/text_input_unittest.cc
+++ b/chromium/components/exo/text_input_unittest.cc
@@ -120,9 +120,9 @@ class TextInputTest : public test::ExoTestBase {
return surface_->window()->GetHost()->GetInputMethod();
}
- void SetCompositionText(const std::string& utf8) {
+ void SetCompositionText(const std::u16string& utf16) {
ui::CompositionText t;
- t.text = base::UTF8ToUTF16(utf8);
+ t.text = utf16;
t.selection = gfx::Range(1u);
t.ime_text_spans.push_back(
ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, t.text.size(),
@@ -239,7 +239,7 @@ TEST_F(TextInputTest, CaretBounds) {
}
TEST_F(TextInputTest, CompositionText) {
- SetCompositionText("composition");
+ SetCompositionText(u"composition");
ui::CompositionText empty;
EXPECT_CALL(*delegate(), SetCompositionText(empty)).Times(1);
@@ -247,19 +247,30 @@ TEST_F(TextInputTest, CompositionText) {
}
TEST_F(TextInputTest, CompositionTextEmpty) {
- SetCompositionText("");
+ SetCompositionText(u"");
EXPECT_CALL(*delegate(), SetCompositionText(_)).Times(0);
text_input()->ClearCompositionText();
}
TEST_F(TextInputTest, CommitCompositionText) {
- SetCompositionText("composition");
+ SetCompositionText(u"composition");
- EXPECT_CALL(*delegate(), Commit(base::UTF8ToUTF16("composition"))).Times(1);
+ EXPECT_CALL(*delegate(), Commit(std::u16string(u"composition"))).Times(1);
const uint32_t composition_text_length =
- text_input()->ConfirmCompositionText(/** keep_selection */ false);
+ text_input()->ConfirmCompositionText(/*keep_selection=*/false);
EXPECT_EQ(composition_text_length, static_cast<uint32_t>(11));
+ testing::Mock::VerifyAndClearExpectations(delegate());
+
+ // Second call should be the empty commit string.
+ EXPECT_EQ(0u, text_input()->ConfirmCompositionText(/*keep_selection=*/false));
+}
+
+TEST_F(TextInputTest, ResetCompositionText) {
+ SetCompositionText(u"composition");
+
+ text_input()->Reset();
+ EXPECT_EQ(0u, text_input()->ConfirmCompositionText(/*keep_selection=*/false));
}
TEST_F(TextInputTest, Commit) {
@@ -308,7 +319,7 @@ TEST_F(TextInputTest, SurroundingText) {
std::u16string got_text;
EXPECT_FALSE(text_input()->GetTextFromRange(gfx::Range(0, 1), &got_text));
- std::u16string text = base::UTF8ToUTF16("surrounding\xE3\x80\x80text");
+ std::u16string text = u"surrounding\u3000text";
text_input()->SetSurroundingText(text, 11, 12);
EXPECT_TRUE(text_input()->GetTextRange(&range));
@@ -326,7 +337,7 @@ TEST_F(TextInputTest, SurroundingText) {
text_input()->ExtendSelectionAndDelete(0, 0);
size_t composition_size = std::string("composition").size();
- SetCompositionText("composition");
+ SetCompositionText(u"composition");
EXPECT_TRUE(text_input()->GetCompositionTextRange(&range));
EXPECT_EQ(gfx::Range(11, 11 + composition_size).ToString(), range.ToString());
EXPECT_TRUE(text_input()->GetTextRange(&range));
@@ -340,24 +351,24 @@ TEST_F(TextInputTest, GetTextRange) {
std::u16string text = u"surrounding text";
text_input()->SetSurroundingText(text, 11, 12);
- SetCompositionText("composition");
+ SetCompositionText(u"composition");
const struct {
gfx::Range range;
- std::string expected;
+ std::u16string expected;
} kTestCases[] = {
- {gfx::Range(0, 3), "sur"},
- {gfx::Range(10, 13), "gco"},
- {gfx::Range(10, 23), "gcompositiont"},
- {gfx::Range(12, 15), "omp"},
- {gfx::Range(12, 23), "ompositiont"},
- {gfx::Range(22, 25), "tex"},
+ {gfx::Range(0, 3), u"sur"},
+ {gfx::Range(10, 13), u"gco"},
+ {gfx::Range(10, 23), u"gcompositiont"},
+ {gfx::Range(12, 15), u"omp"},
+ {gfx::Range(12, 23), u"ompositiont"},
+ {gfx::Range(22, 25), u"tex"},
};
for (auto& c : kTestCases) {
std::u16string result;
EXPECT_TRUE(text_input()->GetTextFromRange(c.range, &result))
<< c.range.ToString();
- EXPECT_EQ(base::UTF8ToUTF16(c.expected), result) << c.range.ToString();
+ EXPECT_EQ(c.expected, result) << c.range.ToString();
}
}
diff --git a/chromium/components/exo/touch.cc b/chromium/components/exo/touch.cc
index e5174f40fe4..6ad15885bf5 100644
--- a/chromium/components/exo/touch.cc
+++ b/chromium/components/exo/touch.cc
@@ -4,6 +4,7 @@
#include "components/exo/touch.h"
+#include "base/trace_event/trace_event.h"
#include "components/exo/input_trace.h"
#include "components/exo/seat.h"
#include "components/exo/shell_surface_util.h"
@@ -12,6 +13,7 @@
#include "components/exo/touch_stylus_delegate.h"
#include "components/exo/wm_helper.h"
#include "ui/aura/window.h"
+#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/wm/core/capture_controller.h"
#include "ui/wm/core/window_util.h"
@@ -41,11 +43,11 @@ Touch::Touch(TouchDelegate* delegate, Seat* seat)
}
Touch::~Touch() {
+ WMHelper::GetInstance()->RemovePreTargetHandler(this);
delegate_->OnTouchDestroying(this);
if (HasStylusDelegate())
stylus_delegate_->OnTouchDestroying(this);
CancelAllTouches();
- WMHelper::GetInstance()->RemovePreTargetHandler(this);
}
void Touch::SetStylusDelegate(TouchStylusDelegate* delegate) {
@@ -60,6 +62,9 @@ bool Touch::HasStylusDelegate() const {
// ui::EventHandler overrides:
void Touch::OnTouchEvent(ui::TouchEvent* event) {
+ if (seat_->was_shutdown())
+ return;
+
seat_->SetLastPointerLocation(event->root_location_f());
bool send_details = false;
diff --git a/chromium/components/exo/touch_unittest.cc b/chromium/components/exo/touch_unittest.cc
index 6c0f779b034..721591aefdd 100644
--- a/chromium/components/exo/touch_unittest.cc
+++ b/chromium/components/exo/touch_unittest.cc
@@ -64,7 +64,7 @@ class TestDataSourceDelegate : public DataSourceDelegate {
// Overridden from DataSourceDelegate:
void OnDataSourceDestroying(DataSource* device) override {}
- void OnTarget(const base::Optional<std::string>& mime_type) override {}
+ void OnTarget(const absl::optional<std::string>& mime_type) override {}
void OnSend(const std::string& mime_type, base::ScopedFD fd) override {}
void OnCancelled() override {}
void OnDndDropPerformed() override {}
diff --git a/chromium/components/exo/ui_lock_bubble.cc b/chromium/components/exo/ui_lock_bubble.cc
deleted file mode 100644
index e34da64dbcc..00000000000
--- a/chromium/components/exo/ui_lock_bubble.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/exo/ui_lock_bubble.h"
-
-#include <memory>
-
-#include "ash/strings/grit/ash_strings.h"
-#include "ash/wm/desks/desks_util.h"
-#include "components/exo/surface.h"
-#include "components/exo/wm_helper.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/canvas.h"
-#include "ui/views/border.h"
-#include "ui/views/bubble/bubble_dialog_delegate_view.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/layout/layout_provider.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
-#include "ui/views/style/typography.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
-
-namespace exo {
-namespace {
-
-constexpr int kPaddingTop = 100;
-
-} // namespace
-
-UILockBubbleView::~UILockBubbleView() = default;
-
-UILockBubbleView::UILockBubbleView(views::View* anchor_view)
- : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_CENTER) {
- set_margins(views::LayoutProvider::Get()->GetInsetsMetric(
- views::InsetsMetric::INSETS_DIALOG));
- SetCanActivate(false);
- SetButtons(ui::DIALOG_BUTTON_NONE);
- set_color(SK_ColorBLACK);
-
- SetLayoutManager(std::make_unique<views::FillLayout>());
-
- views::Label* text_label = AddChildView(
- std::make_unique<views::Label>(std::u16string(l10n_util::GetStringUTF16(
- IDS_EXO_UI_LOCK_NOTIFICATION_BUBBLE_MESSAGE))));
- text_label->SetEnabledColor(SK_ColorWHITE);
- text_label->SetBackgroundColor(SK_ColorBLACK);
- text_label->SetAutoColorReadabilityEnabled(true);
- text_label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
- set_anchor_view_insets(gfx::Insets(kPaddingTop, 0, 0, 0));
-}
-
-// TODO(crbug.com/1178861): Refactor this functionality to be provided by Ash
-// directly
-views::Widget* UILockBubbleView::DisplayBubble(views::View* bubble_anchor) {
- views::Widget* bubble_view_widget =
- views::BubbleDialogDelegateView::CreateBubble(
- new UILockBubbleView(bubble_anchor));
- bubble_view_widget->SetOpacity(0.5);
- bubble_view_widget->SetZOrderLevel(ui::ZOrderLevel::kSecuritySurface);
- bubble_view_widget->Show();
- return bubble_view_widget;
-}
-
-BEGIN_METADATA(UILockBubbleView, views::BubbleDialogDelegateView)
-END_METADATA
-
-} // namespace exo
diff --git a/chromium/components/exo/ui_lock_bubble.h b/chromium/components/exo/ui_lock_bubble.h
deleted file mode 100644
index cf593893a63..00000000000
--- a/chromium/components/exo/ui_lock_bubble.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_EXO_UI_LOCK_BUBBLE_H_
-#define COMPONENTS_EXO_UI_LOCK_BUBBLE_H_
-
-#include "base/macros.h"
-#include "ui/views/bubble/bubble_dialog_delegate_view.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
-
-namespace exo {
-
-// This view displays a Bubble within the always on top container instructing a
-// user on how to exit non-immersive fullscreen or 'gaming mode'.
-// TODO(b/161952658): Use ShellSurfaceBase::AddOverlay() rather than
-// BubbleDialogDelegateView.
-class UILockBubbleView : public views::BubbleDialogDelegateView {
- public:
- METADATA_HEADER(UILockBubbleView);
- ~UILockBubbleView() override;
- UILockBubbleView(const UILockBubbleView&) = delete;
- UILockBubbleView& operator=(const UILockBubbleView&) = delete;
-
- static views::Widget* DisplayBubble(views::View* anchor_view);
-
- private:
- UILockBubbleView(views::View* anchor_view);
-};
-
-} // namespace exo
-
-#endif // COMPONENTS_EXO_UI_LOCK_BUBBLE_H_
diff --git a/chromium/components/exo/ui_lock_controller.cc b/chromium/components/exo/ui_lock_controller.cc
index f0e794860df..9cca61e61ef 100644
--- a/chromium/components/exo/ui_lock_controller.cc
+++ b/chromium/components/exo/ui_lock_controller.cc
@@ -8,8 +8,8 @@
#include "ash/public/cpp/app_types.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_state_observer.h"
+#include "base/bind.h"
#include "base/feature_list.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -17,83 +17,187 @@
#include "components/exo/seat.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/surface.h"
-#include "components/exo/ui_lock_bubble.h"
#include "components/exo/wm_helper.h"
+#include "components/fullscreen_control/fullscreen_control_popup.h"
+#include "components/fullscreen_control/subtle_notification_view.h"
+#include "components/strings/grit/components_strings.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
+#include "ui/base/l10n/l10n_util.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/strings/grit/ui_strings.h"
#include "ui/views/widget/widget.h"
namespace {
-constexpr auto kEscHoldMessageDuration = base::TimeDelta::FromSeconds(4);
+// The Esc hold notification shows a message to press and hold Esc to exit
+// fullscreen. It will hide after a 4s timeout but shows again each time the
+// window goes to fullscreen.
+//
+// The exit popup is a circle with an 'X' close icon which exits fullscreen when
+// the user clicks it.
+// * It is not shown on windows such as borealis with property
+// kEscHoldExitFullscreenToMinimized.
+// * It is displayed when the mouse moves to the top 3px of the screen.
+// * It will hide after a 3s timeout, or the user moves below 150px.
+// * After hiding, there is a cooldown where it will not display again until the
+// mouse moves below 150px.
+
+// Duration to show the 'Press and hold Esc' notification.
+constexpr auto kEscNotificationDuration = base::TimeDelta::FromSeconds(4);
+// Position of Esc notification from top of screen.
+const int kEscNotificationTopPx = 45;
+// Duration to show the exit 'X' popup.
+constexpr auto kExitPopupDuration = base::TimeDelta::FromSeconds(3);
+// Display the exit popup if mouse is above this height.
+constexpr float kExitPopupDisplayHeight = 3.f;
+// Hide the exit popup if mouse is below this height.
+constexpr float kExitPopupHideHeight = 150.f;
+
+// Create and position Esc notification.
+views::Widget* CreateEscNotification(aura::Window* parent) {
+ auto content_view = std::make_unique<SubtleNotificationView>();
+ std::u16string accelerator = l10n_util::GetStringUTF16(IDS_APP_ESC_KEY);
+ content_view->UpdateContent(l10n_util::GetStringFUTF16(
+ IDS_FULLSCREEN_HOLD_ESC_TO_EXIT_FULLSCREEN, accelerator));
+ gfx::Size size = content_view->GetPreferredSize();
+ views::Widget* popup = SubtleNotificationView::CreatePopupWidget(
+ parent, std::move(content_view));
+ popup->SetZOrderLevel(ui::ZOrderLevel::kSecuritySurface);
+ gfx::Rect bounds = parent->GetBoundsInScreen();
+ int y = bounds.y() + kEscNotificationTopPx;
+ bounds.ClampToCenteredSize(size);
+ bounds.set_y(y);
+ popup->SetBounds(bounds);
+ return popup;
+}
+
+// Exits fullscreen to either default or minimized.
+void ExitFullscreen(aura::Window* window) {
+ ash::WindowState* window_state = ash::WindowState::Get(window);
+ if (window->GetProperty(chromeos::kEscHoldExitFullscreenToMinimized))
+ window_state->Minimize();
+ else
+ window_state->Restore();
+}
-// Shows 'Press and hold ESC to exit fullscreen' message.
-class EscHoldNotifier : public ash::WindowStateObserver {
+// Shows 'Press and hold ESC to exit fullscreen' message, and exit popup.
+class EscHoldNotifier : public ui::EventHandler,
+ public ash::WindowStateObserver {
public:
- explicit EscHoldNotifier(aura::Window* window) {
+ explicit EscHoldNotifier(aura::Window* window) : window_(window) {
ash::WindowState* window_state = ash::WindowState::Get(window);
window_state_observation_.Observe(window_state);
if (window_state->IsFullscreen())
- ShowBubble(window);
+ OnFullscreen();
}
EscHoldNotifier(const EscHoldNotifier&) = delete;
EscHoldNotifier& operator=(const EscHoldNotifier&) = delete;
- ~EscHoldNotifier() override { CloseBubble(); }
+ ~EscHoldNotifier() override { CloseAll(); }
+
+ views::Widget* esc_notification() { return esc_notification_; }
- views::Widget* bubble() { return bubble_; }
+ FullscreenControlPopup* exit_popup() { return exit_popup_.get(); }
private:
- // Overridden from ash::WindowStateObserver:
- void OnPreWindowStateTypeChange(ash::WindowState* window_state,
- chromeos::WindowStateType old_type) override {
+ // Overridden from ui::EventHandler:
+ void OnMouseEvent(ui::MouseEvent* event) override {
+ gfx::PointF point = event->location_f();
+ aura::Window::ConvertPointToTarget(
+ static_cast<aura::Window*>(event->target()), window_, &point);
+ if (!esc_notification_ && !exit_popup_cooldown_ &&
+ window_ == exo::WMHelper::GetInstance()->GetActiveWindow() &&
+ point.y() <= kExitPopupDisplayHeight) {
+ // Show exit popup if mouse is above 3px, unless esc notification is
+ // visible, or during cooldown (popup shown and mouse still at top).
+ if (!exit_popup_) {
+ exit_popup_ = std::make_unique<FullscreenControlPopup>(
+ window_, base::BindRepeating(&ExitFullscreen, window_),
+ base::DoNothing());
+ }
+ views::Widget* widget =
+ views::Widget::GetTopLevelWidgetForNativeView(window_);
+ exit_popup_->Show(widget->GetClientAreaBoundsInScreen());
+ exit_popup_timer_.Start(FROM_HERE, kExitPopupDuration,
+ base::BindOnce(&EscHoldNotifier::HideExitPopup,
+ base::Unretained(this),
+ /*animate=*/true));
+ exit_popup_cooldown_ = true;
+ } else if (point.y() > kExitPopupHideHeight) {
+ // Hide exit popup if mouse is below 150px, reset cooloff.
+ HideExitPopup(/*animate=*/true);
+ exit_popup_cooldown_ = false;
+ }
}
+
+ // Overridden from ash::WindowStateObserver:
void OnPostWindowStateTypeChange(
ash::WindowState* window_state,
chromeos::WindowStateType old_type) override {
+ DCHECK_EQ(window_, window_state->window());
if (window_state->IsFullscreen()) {
- ShowBubble(window_state->window());
+ OnFullscreen();
} else {
- CloseBubble();
+ CloseAll();
}
}
- void ShowBubble(aura::Window* window) {
- // Only show message once per window.
- if (has_been_shown_)
- return;
+ void OnFullscreen() {
+ // Register ui::EventHandler to watch if mouse goes to top of screen.
+ if (!is_handling_events_ &&
+ !window_->GetProperty(chromeos::kEscHoldExitFullscreenToMinimized)) {
+ window_->AddPreTargetHandler(this);
+ is_handling_events_ = true;
+ }
- views::Widget* widget =
- views::Widget::GetTopLevelWidgetForNativeView(window);
- if (!widget)
+ // Only show Esc notification when window is active.
+ if (window_ != exo::WMHelper::GetInstance()->GetActiveWindow())
return;
- bubble_ = exo::UILockBubbleView::DisplayBubble(widget->GetContentsView());
- // Close bubble after 4s.
- close_timer_.Start(
- FROM_HERE, kEscHoldMessageDuration,
- base::BindOnce(&EscHoldNotifier::CloseBubble, base::Unretained(this),
- /*closed_by_timer=*/true));
+ if (!esc_notification_)
+ esc_notification_ = CreateEscNotification(window_);
+ esc_notification_->Show();
+
+ // Close Esc notification after 4s.
+ esc_notification_timer_.Start(
+ FROM_HERE, kEscNotificationDuration,
+ base::BindOnce(&EscHoldNotifier::CloseEscNotification,
+ base::Unretained(this)));
}
- void CloseBubble(bool closed_by_timer = false) {
- if (bubble_) {
- bubble_->CloseWithReason(views::Widget::ClosedReason::kUnspecified);
- bubble_ = nullptr;
- // Message is only shown once as long as it shows for the full 4s.
- if (closed_by_timer) {
- has_been_shown_ = true;
- window_state_observation_.Reset();
- }
+ void CloseAll() {
+ if (is_handling_events_) {
+ window_->RemovePreTargetHandler(this);
+ is_handling_events_ = false;
}
+ CloseEscNotification();
+ HideExitPopup();
}
- views::Widget* bubble_ = nullptr;
- bool has_been_shown_ = false;
- base::OneShotTimer close_timer_;
+ void CloseEscNotification() {
+ if (!esc_notification_)
+ return;
+ esc_notification_->CloseWithReason(
+ views::Widget::ClosedReason::kUnspecified);
+ esc_notification_ = nullptr;
+ }
+
+ void HideExitPopup(bool animate = false) {
+ if (exit_popup_)
+ exit_popup_->Hide(animate);
+ }
+
+ aura::Window* window_;
+ views::Widget* esc_notification_ = nullptr;
+ std::unique_ptr<FullscreenControlPopup> exit_popup_;
+ bool is_handling_events_ = false;
+ bool exit_popup_cooldown_ = false;
+ base::OneShotTimer esc_notification_timer_;
+ base::OneShotTimer exit_popup_timer_;
base::ScopedObservation<ash::WindowState, ash::WindowStateObserver>
window_state_observation_{this};
};
@@ -125,12 +229,13 @@ UILockController::~UILockController() {
}
void UILockController::OnKeyEvent(ui::KeyEvent* event) {
- // If the event target is not an exo::Surface, let another handler process the
- // event.
- if (!GetShellRootSurface(static_cast<aura::Window*>(event->target())) &&
- !Surface::AsSurface(static_cast<aura::Window*>(event->target()))) {
+ // TODO(oshima): Rather than handling key event here, add a hook in
+ // keyboard.cc to intercept key event and handle this.
+
+ // If no surface is focused, let another handler process the event.
+ aura::Window* window = static_cast<aura::Window*>(event->target());
+ if (!GetTargetSurfaceForKeyboardFocus(window))
return;
- }
if (event->code() == ui::DomCode::ESCAPE &&
(event->flags() & kExcludedFlags) == 0) {
@@ -163,8 +268,14 @@ void UILockController::OnSurfaceFocused(Surface* gained_focus) {
window->SetProperty(kEscHoldNotifierKey, new EscHoldNotifier(window));
}
-bool UILockController::IsBubbleVisibleForTesting(aura::Window* window) {
- return window->GetProperty(kEscHoldNotifierKey)->bubble();
+views::Widget* UILockController::GetEscNotificationForTesting(
+ aura::Window* window) {
+ return window->GetProperty(kEscHoldNotifierKey)->esc_notification();
+}
+
+FullscreenControlPopup* UILockController::GetExitPopupForTesting(
+ aura::Window* window) {
+ return window->GetProperty(kEscHoldNotifierKey)->exit_popup();
}
namespace {
@@ -212,18 +323,7 @@ void UILockController::OnEscapeHeld() {
focused_surface_to_unlock_ = nullptr;
- auto* widget =
- views::Widget::GetTopLevelWidgetForNativeView(surface->window());
- auto* window_state =
- ash::WindowState::Get(widget ? widget->GetNativeWindow() : nullptr);
- if (window_state) {
- if (window_state->window()->GetProperty(
- chromeos::kEscHoldExitFullscreenToMinimized)) {
- window_state->Minimize();
- } else {
- window_state->Restore();
- }
- }
+ ExitFullscreen(surface->window()->GetToplevelWindow());
}
void UILockController::StopTimer() {
diff --git a/chromium/components/exo/ui_lock_controller.h b/chromium/components/exo/ui_lock_controller.h
index 32426ba602b..046227bc055 100644
--- a/chromium/components/exo/ui_lock_controller.h
+++ b/chromium/components/exo/ui_lock_controller.h
@@ -10,6 +10,8 @@
#include "components/exo/seat_observer.h"
#include "ui/events/event_handler.h"
+class FullscreenControlPopup;
+
namespace exo {
class Seat;
@@ -38,7 +40,8 @@ class UILockController : public ui::EventHandler, public SeatObserver {
void OnSurfaceFocusing(Surface* gaining_focus) override {}
void OnSurfaceFocused(Surface* gained_focus) override;
- bool IsBubbleVisibleForTesting(aura::Window* window);
+ views::Widget* GetEscNotificationForTesting(aura::Window* window);
+ FullscreenControlPopup* GetExitPopupForTesting(aura::Window* window);
private:
void OnEscapeKey(bool pressed);
diff --git a/chromium/components/exo/ui_lock_controller_unittest.cc b/chromium/components/exo/ui_lock_controller_unittest.cc
index 2ff813fdd63..83349a0c41e 100644
--- a/chromium/components/exo/ui_lock_controller_unittest.cc
+++ b/chromium/components/exo/ui_lock_controller_unittest.cc
@@ -16,10 +16,11 @@
#include "components/exo/surface.h"
#include "components/exo/test/exo_test_base.h"
#include "components/exo/test/exo_test_helper.h"
-#include "components/exo/ui_lock_bubble.h"
#include "components/exo/wm_helper.h"
+#include "components/fullscreen_control/fullscreen_control_popup.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/class_property.h"
+#include "ui/gfx/animation/animation_test_api.h"
#include "ui/wm/core/window_util.h"
namespace exo {
@@ -27,6 +28,7 @@ namespace exo {
namespace {
constexpr char kNoEscHoldAppId[] = "no-esc-hold";
+constexpr char kEscToMinimizeAppId[] = "esc-to-minimize";
struct SurfaceTriplet {
std::unique_ptr<Surface> surface;
@@ -77,6 +79,9 @@ class UILockControllerTest : public test::ExoTestBase {
ui::PropertyHandler& out_properties_container) override {
out_properties_container.SetProperty(chromeos::kEscHoldToExitFullscreen,
params.app_id != kNoEscHoldAppId);
+ out_properties_container.SetProperty(
+ chromeos::kEscHoldExitFullscreenToMinimized,
+ params.app_id == kEscToMinimizeAppId);
}
};
@@ -95,10 +100,10 @@ class UILockControllerTest : public test::ExoTestBase {
test::ExoTestBase::TearDown();
}
- SurfaceTriplet BuildSurface(int w, int h) {
+ SurfaceTriplet BuildSurface(gfx::Point origin, int w, int h) {
auto surface = std::make_unique<Surface>();
auto shell_surface = std::make_unique<ShellSurface>(
- surface.get(), gfx::Point{0, 0},
+ surface.get(), origin,
/*can_minimize=*/true, ash::desks_util::GetActiveDeskContainerId());
auto buffer = std::make_unique<Buffer>(
exo_test_helper()->CreateGpuMemoryBuffer({w, h}));
@@ -107,6 +112,27 @@ class UILockControllerTest : public test::ExoTestBase {
return {std::move(surface), std::move(shell_surface), std::move(buffer)};
}
+ SurfaceTriplet BuildSurface(int w, int h) {
+ return BuildSurface(gfx::Point(0, 0), w, h);
+ }
+
+ views::Widget* GetEscNotification(SurfaceTriplet* surface) {
+ return seat_->GetUILockControllerForTesting()->GetEscNotificationForTesting(
+ surface->GetTopLevelWindow());
+ }
+
+ bool IsExitPopupVisible(aura::Window* window) {
+ FullscreenControlPopup* popup =
+ seat_->GetUILockControllerForTesting()->GetExitPopupForTesting(window);
+ if (popup && popup->IsAnimating()) {
+ gfx::AnimationTestApi animation_api(popup->GetAnimationForTesting());
+ base::TimeTicks now = base::TimeTicks::Now();
+ animation_api.SetStartTime(now);
+ animation_api.Step(now + base::TimeDelta::FromMilliseconds(500));
+ }
+ return popup && popup->IsVisible();
+ }
+
std::unique_ptr<Seat> seat_;
base::test::ScopedFeatureList scoped_feature_list_;
};
@@ -143,8 +169,8 @@ TEST_F(UILockControllerTest, HoldingCtrlEscapeDoesNotExitFullscreen) {
TEST_F(UILockControllerTest,
HoldingEscapeOnlyExitsFullscreenIfWindowPropertySet) {
- // Do not set chromeos::kEscHoldToExitFullscreen on TopLevelWindow.
SurfaceTriplet test_surface = BuildSurface(1024, 768);
+ // Do not set chromeos::kEscHoldToExitFullscreen on TopLevelWindow.
test_surface.shell_surface->SetApplicationId(kNoEscHoldAppId);
test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
test_surface.shell_surface->SetFullscreen(true);
@@ -238,11 +264,11 @@ TEST_F(UILockControllerTest, ShortHoldEscapeDoesNotExitFullscreen) {
TEST_F(UILockControllerTest, HoldingEscapeMinimizesIfPropertySet) {
SurfaceTriplet test_surface = BuildSurface(1024, 768);
+ // Set chromeos::kEscHoldExitFullscreenToMinimized on TopLevelWindow.
+ test_surface.shell_surface->SetApplicationId(kEscToMinimizeAppId);
test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
test_surface.shell_surface->SetFullscreen(true);
test_surface.surface->Commit();
- test_surface.GetTopLevelWindow()->SetProperty(
- chromeos::kEscHoldExitFullscreenToMinimized, true);
auto* window_state = test_surface.GetTopLevelWindowState();
EXPECT_TRUE(window_state->IsFullscreen());
@@ -257,11 +283,11 @@ TEST_F(UILockControllerTest, HoldingEscapeMinimizesIfPropertySet) {
TEST_F(UILockControllerTest, HoldingEscapeDoesNotMinimizeIfWindowed) {
SurfaceTriplet test_surface = BuildSurface(1024, 768);
+ // Set chromeos::kEscHoldExitFullscreenToMinimized on TopLevelWindow.
+ test_surface.shell_surface->SetApplicationId(kEscToMinimizeAppId);
test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
test_surface.surface->Commit();
auto* window_state = test_surface.GetTopLevelWindowState();
- test_surface.GetTopLevelWindow()->SetProperty(
- chromeos::kEscHoldExitFullscreenToMinimized, true);
GetEventGenerator()->PressKey(ui::VKEY_ESCAPE, ui::EF_NONE);
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(2));
@@ -269,103 +295,186 @@ TEST_F(UILockControllerTest, HoldingEscapeDoesNotMinimizeIfWindowed) {
EXPECT_FALSE(window_state->IsMinimized());
}
-TEST_F(UILockControllerTest, FullScreenShowsBubble) {
+TEST_F(UILockControllerTest, FullScreenShowsEscNotification) {
SurfaceTriplet test_surface = BuildSurface(1024, 768);
test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
test_surface.shell_surface->SetFullscreen(true);
test_surface.surface->Commit();
EXPECT_TRUE(test_surface.GetTopLevelWindowState()->IsFullscreen());
- EXPECT_TRUE(seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
- test_surface.GetTopLevelWindow()));
+ EXPECT_TRUE(GetEscNotification(&test_surface));
}
-TEST_F(UILockControllerTest, BubbleClosesAfterDuration) {
+TEST_F(UILockControllerTest, EscNotificationClosesAfterDuration) {
SurfaceTriplet test_surface = BuildSurface(1024, 768);
test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
test_surface.shell_surface->SetFullscreen(true);
test_surface.surface->Commit();
- EXPECT_TRUE(seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
- test_surface.GetTopLevelWindow()));
+ EXPECT_TRUE(GetEscNotification(&test_surface));
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(5));
- EXPECT_FALSE(
- seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
- test_surface.GetTopLevelWindow()));
+ EXPECT_FALSE(GetEscNotification(&test_surface));
}
-TEST_F(UILockControllerTest, HoldingEscapeHidesBubble) {
+TEST_F(UILockControllerTest, HoldingEscapeHidesNotification) {
SurfaceTriplet test_surface = BuildSurface(1024, 768);
test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
test_surface.shell_surface->SetFullscreen(true);
test_surface.surface->Commit();
EXPECT_TRUE(test_surface.GetTopLevelWindowState()->IsFullscreen());
- EXPECT_TRUE(seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
- test_surface.GetTopLevelWindow()));
+ EXPECT_TRUE(GetEscNotification(&test_surface));
GetEventGenerator()->PressKey(ui::VKEY_ESCAPE, ui::EF_NONE);
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(3));
EXPECT_FALSE(test_surface.GetTopLevelWindowState()->IsFullscreen());
- EXPECT_FALSE(
- seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
- test_surface.GetTopLevelWindow()));
+ EXPECT_FALSE(GetEscNotification(&test_surface));
}
-TEST_F(UILockControllerTest, LosingFullscreenHidesBubble) {
+TEST_F(UILockControllerTest, LosingFullscreenHidesNotification) {
SurfaceTriplet test_surface = BuildSurface(1024, 768);
test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
test_surface.shell_surface->SetFullscreen(true);
test_surface.surface->Commit();
EXPECT_TRUE(test_surface.GetTopLevelWindowState()->IsFullscreen());
- EXPECT_TRUE(seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
- test_surface.GetTopLevelWindow()));
+ EXPECT_TRUE(GetEscNotification(&test_surface));
- // Have surface loose fullscreen, bubble should now be hidden.
+ // Have surface loose fullscreen, notification should now be hidden.
test_surface.shell_surface->Minimize();
test_surface.shell_surface->SetFullscreen(false);
test_surface.surface->Commit();
EXPECT_FALSE(test_surface.GetTopLevelWindowState()->IsFullscreen());
EXPECT_FALSE(
- seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
+ seat_->GetUILockControllerForTesting()->GetEscNotificationForTesting(
test_surface.GetTopLevelWindow()));
}
-TEST_F(UILockControllerTest, BubbleIsReshown) {
+TEST_F(UILockControllerTest, EscNotificationIsReshown) {
SurfaceTriplet test_surface = BuildSurface(1024, 768);
test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
test_surface.shell_surface->SetFullscreen(true);
test_surface.surface->Commit();
- EXPECT_TRUE(seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
- test_surface.GetTopLevelWindow()));
+ EXPECT_TRUE(GetEscNotification(&test_surface));
// Stop fullscreen.
test_surface.shell_surface->SetFullscreen(false);
EXPECT_FALSE(
- seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
+ seat_->GetUILockControllerForTesting()->GetEscNotificationForTesting(
test_surface.GetTopLevelWindow()));
- // Fullscreen should show bubble since it did not stay visible for duration.
+ // Fullscreen should show notification since it did not stay visible for
+ // duration.
test_surface.shell_surface->SetFullscreen(true);
- EXPECT_TRUE(seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
- test_surface.GetTopLevelWindow()));
+ EXPECT_TRUE(GetEscNotification(&test_surface));
- // After duration, bubble should be removed.
+ // After duration, notification should be removed.
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(5));
- EXPECT_FALSE(
- seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
- test_surface.GetTopLevelWindow()));
+ EXPECT_FALSE(GetEscNotification(&test_surface));
- // Bubble is not shown after fullscreen toggle.
+ // Notification is shown after fullscreen toggle.
test_surface.shell_surface->SetFullscreen(false);
test_surface.shell_surface->SetFullscreen(true);
- EXPECT_FALSE(
- seat_->GetUILockControllerForTesting()->IsBubbleVisibleForTesting(
- test_surface.GetTopLevelWindow()));
+ EXPECT_TRUE(GetEscNotification(&test_surface));
+}
+
+TEST_F(UILockControllerTest, EscNotificationShowsOnSecondaryDisplay) {
+ // Create surface on secondary display.
+ UpdateDisplay("800x800,600x600");
+ SurfaceTriplet test_surface = BuildSurface(gfx::Point(900, 100), 200, 200);
+ test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
+ test_surface.shell_surface->SetFullscreen(true);
+ test_surface.surface->Commit();
+
+ // Esc notification should be in secondary display.
+ views::Widget* esc_notification = GetEscNotification(&test_surface);
+ EXPECT_TRUE(GetSecondaryDisplay().bounds().Contains(
+ esc_notification->GetWindowBoundsInScreen()));
+}
+
+TEST_F(UILockControllerTest, ExitPopup) {
+ SurfaceTriplet test_surface = BuildSurface(1024, 768);
+ test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
+ test_surface.shell_surface->SetFullscreen(true);
+ test_surface.surface->Commit();
+ auto* window_state = test_surface.GetTopLevelWindowState();
+ EXPECT_TRUE(window_state->IsFullscreen());
+ aura::Window* window = test_surface.GetTopLevelWindow();
+ EXPECT_FALSE(IsExitPopupVisible(window));
+ EXPECT_TRUE(GetEscNotification(&test_surface));
+
+ // Move mouse above y=3 should not show exit popup while notification is
+ // visible.
+ GetEventGenerator()->MoveMouseTo(0, 2);
+ EXPECT_FALSE(IsExitPopupVisible(window));
+
+ // Wait for notification to close, now exit popup should show.
+ task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(5));
+ EXPECT_FALSE(GetEscNotification(&test_surface));
+ GetEventGenerator()->MoveMouseTo(1, 2);
+ EXPECT_TRUE(IsExitPopupVisible(window));
+
+ // Move mouse below y=150 should hide exit popup.
+ GetEventGenerator()->MoveMouseTo(0, 160);
+ EXPECT_FALSE(IsExitPopupVisible(window));
+
+ // Move mouse back above y=3 should show exit popup.
+ GetEventGenerator()->MoveMouseTo(0, 2);
+ EXPECT_TRUE(IsExitPopupVisible(window));
+
+ // Popup should hide after 3s.
+ task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(5));
+ EXPECT_FALSE(IsExitPopupVisible(window));
+
+ // Moving mouse to y=100, then above y=3 should still have popup hidden.
+ GetEventGenerator()->MoveMouseTo(0, 100);
+ GetEventGenerator()->MoveMouseTo(0, 2);
+ EXPECT_FALSE(IsExitPopupVisible(window));
+
+ // Moving mouse below y=150, then above y=3 should show exit popup.
+ GetEventGenerator()->MoveMouseTo(0, 160);
+ GetEventGenerator()->MoveMouseTo(0, 2);
+ EXPECT_TRUE(IsExitPopupVisible(window));
+
+ // Clicking exit popup should exit fullscreen.
+ FullscreenControlPopup* popup =
+ seat_->GetUILockControllerForTesting()->GetExitPopupForTesting(window);
+ GetEventGenerator()->MoveMouseTo(
+ popup->GetPopupWidget()->GetWindowBoundsInScreen().CenterPoint());
+ GetEventGenerator()->ClickLeftButton();
+ EXPECT_FALSE(window_state->IsFullscreen());
+ EXPECT_FALSE(IsExitPopupVisible(window));
+}
+
+TEST_F(UILockControllerTest, ExitPopupNotShownIfPropertySet) {
+ SurfaceTriplet test_surface = BuildSurface(1024, 768);
+ // Set chromeos::kEscHoldExitFullscreenToMinimized on TopLevelWindow.
+ test_surface.shell_surface->SetApplicationId(kEscToMinimizeAppId);
+ test_surface.shell_surface->SetUseImmersiveForFullscreen(false);
+ test_surface.shell_surface->SetFullscreen(true);
+ test_surface.surface->Commit();
+ EXPECT_FALSE(IsExitPopupVisible(test_surface.GetTopLevelWindow()));
+
+ // Move mouse above y=3 should not show exit popup.
+ GetEventGenerator()->MoveMouseTo(0, 2);
+ EXPECT_FALSE(IsExitPopupVisible(test_surface.GetTopLevelWindow()));
+}
+
+TEST_F(UILockControllerTest, OnlyShowWhenActive) {
+ SurfaceTriplet test_surface1 = BuildSurface(1024, 768);
+ test_surface1.surface->Commit();
+ SurfaceTriplet test_surface2 = BuildSurface(gfx::Point(100, 100), 200, 200);
+ test_surface2.surface->Commit();
+
+ // Surface2 is active when we make Surface1 fullscreen.
+ // Esc notification, and exit popup should not be shown.
+ test_surface1.shell_surface->SetFullscreen(true);
+ EXPECT_FALSE(GetEscNotification(&test_surface1));
+ GetEventGenerator()->MoveMouseTo(0, 2);
+ EXPECT_FALSE(IsExitPopupVisible(test_surface1.GetTopLevelWindow()));
}
} // namespace
diff --git a/chromium/components/exo/wayland/clients/client_base.cc b/chromium/components/exo/wayland/clients/client_base.cc
index 9c042062049..88f9aa964ba 100644
--- a/chromium/components/exo/wayland/clients/client_base.cc
+++ b/chromium/components/exo/wayland/clients/client_base.cc
@@ -522,8 +522,8 @@ bool ClientBase::Init(const InitParams& params) {
gl::init::CreateGLContext(nullptr, // share_group
gl_surface_.get(), gl::GLContextAttribs());
- make_current_.reset(
- new ui::ScopedMakeCurrent(gl_context_.get(), gl_surface_.get()));
+ make_current_ = std::make_unique<ui::ScopedMakeCurrent>(gl_context_.get(),
+ gl_surface_.get());
if (gl::GLSurfaceEGL::HasEGLExtension("EGL_EXT_image_flush_external") ||
gl::GLSurfaceEGL::HasEGLExtension("EGL_ARM_implicit_external_sync")) {
@@ -1029,10 +1029,10 @@ std::unique_ptr<ClientBase::Buffer> ClientBase::CreateDrmBuffer(
eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
nullptr /* no client buffer */, khr_image_attrs);
- buffer->egl_image.reset(new ScopedEglImage(image));
+ buffer->egl_image = std::make_unique<ScopedEglImage>(image);
GLuint texture = 0;
glGenTextures(1, &texture);
- buffer->texture.reset(new ScopedTexture(texture));
+ buffer->texture = std::make_unique<ScopedTexture>(texture);
glBindTexture(GL_TEXTURE_2D, buffer->texture->get());
glEGLImageTargetTexture2DOES(
GL_TEXTURE_2D, static_cast<GLeglImageOES>(buffer->egl_image->get()));
diff --git a/chromium/components/exo/wayland/clients/client_helper.h b/chromium/components/exo/wayland/clients/client_helper.h
index cf27083002e..8b483baf52c 100644
--- a/chromium/components/exo/wayland/clients/client_helper.h
+++ b/chromium/components/exo/wayland/clients/client_helper.h
@@ -35,8 +35,6 @@
#include <xdg-shell-client-protocol.h>
#include <xdg-shell-unstable-v6-client-protocol.h>
-#include <memory>
-
#include "base/scoped_generic.h"
#if defined(USE_GBM)
diff --git a/chromium/components/exo/wayland/clients/explicit_synchronization.cc b/chromium/components/exo/wayland/clients/explicit_synchronization.cc
index 8bb2d880c4a..a44e7d08ccc 100644
--- a/chromium/components/exo/wayland/clients/explicit_synchronization.cc
+++ b/chromium/components/exo/wayland/clients/explicit_synchronization.cc
@@ -6,6 +6,8 @@
#include <linux-explicit-synchronization-unstable-v1-client-protocol.h>
+#include <memory>
+
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/files/scoped_file.h"
@@ -89,8 +91,8 @@ void ExplicitSynchronizationClient::Run() {
// Create an EGLSyncKHR object to signal when rendering is done.
gr_context_->flushAndSubmit();
- buffer->egl_sync.reset(new ScopedEglSync(
- eglCreateSyncKHR(eglGetCurrentDisplay(), egl_sync_type_, nullptr)));
+ buffer->egl_sync = std::make_unique<ScopedEglSync>(
+ eglCreateSyncKHR(eglGetCurrentDisplay(), egl_sync_type_, nullptr));
DCHECK(buffer->egl_sync->is_valid());
glFlush();
diff --git a/chromium/components/exo/wayland/clients/fullscreen_shell.cc b/chromium/components/exo/wayland/clients/fullscreen_shell.cc
index 9c0cb6bfec4..e32ebe7bdfd 100644
--- a/chromium/components/exo/wayland/clients/fullscreen_shell.cc
+++ b/chromium/components/exo/wayland/clients/fullscreen_shell.cc
@@ -7,7 +7,6 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkSurface.h"
diff --git a/chromium/components/exo/wayland/clients/rects.cc b/chromium/components/exo/wayland/clients/rects.cc
index e08aea4b670..e74a5a7740f 100644
--- a/chromium/components/exo/wayland/clients/rects.cc
+++ b/chromium/components/exo/wayland/clients/rects.cc
@@ -13,6 +13,7 @@
#include <cmath>
#include <iostream>
+#include <memory>
#include <string>
#include <vector>
@@ -24,7 +25,6 @@
#include "base/scoped_generic.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_executor.h"
#include "base/time/time.h"
#include "components/exo/wayland/clients/client_base.h"
@@ -442,8 +442,8 @@ int RectsClient::Run(const ClientBase::InitParams& params,
#if defined(USE_GBM)
if (egl_sync_type_) {
- buffer->egl_sync.reset(new ScopedEglSync(eglCreateSyncKHR(
- eglGetCurrentDisplay(), egl_sync_type_, nullptr)));
+ buffer->egl_sync = std::make_unique<ScopedEglSync>(eglCreateSyncKHR(
+ eglGetCurrentDisplay(), egl_sync_type_, nullptr));
DCHECK(buffer->egl_sync->is_valid());
}
#endif
diff --git a/chromium/components/exo/wayland/compatibility_test/template_client_event_receiver_version_tests.cc.tmpl b/chromium/components/exo/wayland/compatibility_test/template_client_event_receiver_version_tests.cc.tmpl
index 2f1f95bed33..3ba1123fe47 100644
--- a/chromium/components/exo/wayland/compatibility_test/template_client_event_receiver_version_tests.cc.tmpl
+++ b/chromium/components/exo/wayland/compatibility_test/template_client_event_receiver_version_tests.cc.tmpl
@@ -329,11 +329,11 @@ void {{ base_fixture_name }}::ValidateEventsImpl(uint32_t target_interface_versi
"{{ target_interface.name }}::{{ event.name }}";
constexpr uint32_t event_since_version =
{{ event.since or 1 }}u;
- base::Optional<uint32_t> received_at_version =
+ absl::optional<uint32_t> received_at_version =
recorder.MaybeGetReceivedAtVersion(event_name);
if (target_interface_version == event_since_version) {
- EXPECT_THAT(received_at_version, ::testing::Not(::testing::Eq(base::nullopt)))
+ EXPECT_THAT(received_at_version, ::testing::Not(::testing::Eq(absl::nullopt)))
<< "Failed to receive " << event_name << " at interface version "
<< target_interface_version
<< " as the event is defined as since version "
@@ -346,7 +346,7 @@ void {{ base_fixture_name }}::ValidateEventsImpl(uint32_t target_interface_versi
if (target_interface_version >= event_since_version) {
ASSERT_THAT(received_at_version, ::testing::AnyOf(
- ::testing::Eq(base::nullopt),
+ ::testing::Eq(absl::nullopt),
::testing::Optional(::testing::Eq(target_interface_version))))
<< "Unexpected version mismatch. Test expected to create a\n"
<< " {{ target_interface.name }}"
@@ -358,7 +358,7 @@ void {{ base_fixture_name }}::ValidateEventsImpl(uint32_t target_interface_versi
}
if (target_interface_version < event_since_version) {
- EXPECT_THAT(received_at_version, ::testing::Eq(base::nullopt))
+ EXPECT_THAT(received_at_version, ::testing::Eq(absl::nullopt))
<< "Unexpectedly received "
<< event_name
<< " at interface version "
diff --git a/chromium/components/exo/wayland/compatibility_test/wayland_client_event_recorder.h b/chromium/components/exo/wayland/compatibility_test/wayland_client_event_recorder.h
index 5dc15c2c10e..a5d48b0c0b5 100644
--- a/chromium/components/exo/wayland/compatibility_test/wayland_client_event_recorder.h
+++ b/chromium/components/exo/wayland/compatibility_test/wayland_client_event_recorder.h
@@ -9,7 +9,7 @@
#include <string>
#include <unordered_map>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace exo {
namespace wayland {
@@ -24,10 +24,10 @@ struct EventRecorder {
data.emplace(event_name, version);
}
- base::Optional<uint32_t> MaybeGetReceivedAtVersion(
+ absl::optional<uint32_t> MaybeGetReceivedAtVersion(
const char* event_name) const noexcept {
auto it = data.find(event_name);
- return it != data.end() ? base::make_optional(it->second) : base::nullopt;
+ return it != data.end() ? absl::make_optional(it->second) : absl::nullopt;
}
std::unordered_map<std::string, uint32_t> data;
diff --git a/chromium/components/exo/wayland/compatibility_test/wayland_client_registry.cc b/chromium/components/exo/wayland/compatibility_test/wayland_client_registry.cc
index 9434cb92c9d..067e7a05511 100644
--- a/chromium/components/exo/wayland/compatibility_test/wayland_client_registry.cc
+++ b/chromium/components/exo/wayland/compatibility_test/wayland_client_registry.cc
@@ -26,7 +26,7 @@ WaylandClientRegistry::WaylandClientRegistry(wl_display* display)
WaylandClientRegistry::~WaylandClientRegistry() = default;
-base::Optional<WaylandClientRegistry::Entry> WaylandClientRegistry::GetEntry(
+absl::optional<WaylandClientRegistry::Entry> WaylandClientRegistry::GetEntry(
const char* interface_name) const noexcept {
DCHECK(registry_);
if (!registry_)
diff --git a/chromium/components/exo/wayland/compatibility_test/wayland_client_registry.h b/chromium/components/exo/wayland/compatibility_test/wayland_client_registry.h
index bae0206a0ee..ef083dc84b8 100644
--- a/chromium/components/exo/wayland/compatibility_test/wayland_client_registry.h
+++ b/chromium/components/exo/wayland/compatibility_test/wayland_client_registry.h
@@ -13,8 +13,8 @@
#include <wayland-client-protocol.h>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/exo/wayland/compatibility_test/generated-wayland-client-helpers.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace exo {
namespace wayland {
@@ -48,7 +48,7 @@ class WaylandClientRegistry {
uint32_t server_version;
};
- base::Optional<Entry> GetEntry(const char* interface_name) const noexcept;
+ absl::optional<Entry> GetEntry(const char* interface_name) const noexcept;
bool Has(const char* interface_name, uint32_t client_version) const noexcept;
void* Bind(const char* interface_name,
const struct wl_interface* protocol_interface,
diff --git a/chromium/components/exo/wayland/fuzzer/wayland_templater.gni b/chromium/components/exo/wayland/fuzzer/wayland_templater.gni
index 9a4c9dead60..27ffbb1b036 100644
--- a/chromium/components/exo/wayland/fuzzer/wayland_templater.gni
+++ b/chromium/components/exo/wayland/fuzzer/wayland_templater.gni
@@ -24,6 +24,9 @@
#
# If needed, the user can set 'script_override=foo.py' to use a different
# templating script to the default (wayland_templater.py).
+
+import("//build/config/python.gni")
+
template("wayland_templater") {
assert(defined(invoker.sources), "Need sources for wayland_templater")
assert(defined(invoker.protocols), "Need protocols for wayland_templater")
@@ -50,7 +53,8 @@ template("wayland_templater") {
build_path_to_outputs = rebase_path(template_outputs, root_build_dir)
build_path_to_protocols = rebase_path(invoker.protocols, root_build_dir)
- action(target_name) {
+ # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
+ python2_action(target_name) {
script = "//third_party/blink/renderer/build/scripts/run_with_pythonpath.py"
sources = [
script,
diff --git a/chromium/components/exo/wayland/protocol/aura-shell.xml b/chromium/components/exo/wayland/protocol/aura-shell.xml
index bbc81a33086..2b27be8fe4e 100644
--- a/chromium/components/exo/wayland/protocol/aura-shell.xml
+++ b/chromium/components/exo/wayland/protocol/aura-shell.xml
@@ -24,7 +24,7 @@
DEALINGS IN THE SOFTWARE.
</copyright>
- <interface name="zaura_shell" version="18">
+ <interface name="zaura_shell" version="19">
<description summary="aura_shell">
The global interface exposing aura shell capabilities is used to
instantiate an interface extension for a wl_surface object.
@@ -95,7 +95,7 @@
</event>
</interface>
- <interface name="zaura_surface" version="18">
+ <interface name="zaura_surface" version="19">
<description summary="aura shell interface to a wl_surface">
An additional interface to a wl_surface object, which allows the
client to access aura shell specific functionality for surface.
@@ -334,6 +334,23 @@
</description>
<arg name="id" type="int" summary="window session id"/>
</request>
+
+ <!-- Version 19 additions -->
+ <request name="set_can_go_back" since="19">
+ <description summary="Set the minimize-on-back-gesture behavior.">
+ Sets that the surface can go back as per its navigation list.
+ This allows the server to react to by minimizing the window upon a
+ system wide back gesture.
+ </description>
+ </request>
+
+ <request name="unset_can_go_back" since="19">
+ <description summary="Unset the minimize-on-back-gesture behavior.">
+ Unsets that the surface can go back as per its navigation list.
+ See above.
+ </description>
+ </request>
+
</interface>
<interface name="zaura_output" version="6">
diff --git a/chromium/components/exo/wayland/serial_tracker.cc b/chromium/components/exo/wayland/serial_tracker.cc
index 6430391ab1a..e10cde70749 100644
--- a/chromium/components/exo/wayland/serial_tracker.cc
+++ b/chromium/components/exo/wayland/serial_tracker.cc
@@ -40,13 +40,13 @@ uint32_t SerialTracker::GetNextSerial(EventType type) {
pointer_down_serial_ = serial;
break;
case EventType::POINTER_BUTTON_UP:
- pointer_down_serial_ = base::nullopt;
+ pointer_down_serial_ = absl::nullopt;
break;
case EventType::TOUCH_DOWN:
touch_down_serial_ = serial;
break;
case EventType::TOUCH_UP:
- touch_down_serial_ = base::nullopt;
+ touch_down_serial_ = absl::nullopt;
break;
default:
break;
@@ -55,34 +55,34 @@ uint32_t SerialTracker::GetNextSerial(EventType type) {
return serial;
}
-base::Optional<SerialTracker::EventType> SerialTracker::GetEventType(
+absl::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;
+ return absl::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 absl::nullopt;
}
return events_[serial % kMaxEventsTracked];
}
-base::Optional<uint32_t> SerialTracker::GetPointerDownSerial() {
+absl::optional<uint32_t> SerialTracker::GetPointerDownSerial() {
return pointer_down_serial_;
}
-base::Optional<uint32_t> SerialTracker::GetTouchDownSerial() {
+absl::optional<uint32_t> SerialTracker::GetTouchDownSerial() {
return touch_down_serial_;
}
void SerialTracker::ResetTouchDownSerial() {
- touch_down_serial_ = base::nullopt;
+ touch_down_serial_ = absl::nullopt;
}
uint32_t SerialTracker::MaybeNextKeySerial() {
@@ -92,7 +92,7 @@ uint32_t SerialTracker::MaybeNextKeySerial() {
}
void SerialTracker::ResetKeySerial() {
- key_serial_ = base::nullopt;
+ key_serial_ = absl::nullopt;
}
} // namespace wayland
diff --git a/chromium/components/exo/wayland/serial_tracker.h b/chromium/components/exo/wayland/serial_tracker.h
index 7de91b244ba..79d5eac3263 100644
--- a/chromium/components/exo/wayland/serial_tracker.h
+++ b/chromium/components/exo/wayland/serial_tracker.h
@@ -9,7 +9,7 @@
#include <vector>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
struct wl_display;
@@ -42,8 +42,8 @@ class SerialTracker {
// 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();
+ absl::optional<uint32_t> GetPointerDownSerial();
+ absl::optional<uint32_t> GetTouchDownSerial();
// Needed because wl_touch::cancel doesn't send a serial number, so we can't
// test for it in GetNextSerial.
@@ -59,7 +59,7 @@ class SerialTracker {
// 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;
+ absl::optional<EventType> GetEventType(uint32_t serial) const;
private:
struct wl_display* display_;
@@ -74,9 +74,9 @@ class SerialTracker {
uint32_t min_event_ = 1;
uint32_t max_event_ = 1;
- base::Optional<uint32_t> pointer_down_serial_;
- base::Optional<uint32_t> touch_down_serial_;
- base::Optional<uint32_t> key_serial_;
+ absl::optional<uint32_t> pointer_down_serial_;
+ absl::optional<uint32_t> touch_down_serial_;
+ absl::optional<uint32_t> key_serial_;
};
} // namespace wayland
diff --git a/chromium/components/exo/wayland/server.cc b/chromium/components/exo/wayland/server.cc
index 9c178fa269a..34a80e88529 100644
--- a/chromium/components/exo/wayland/server.cc
+++ b/chromium/components/exo/wayland/server.cc
@@ -41,6 +41,7 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/strings/stringprintf.h"
#include "build/chromeos_buildflags.h"
#include "components/exo/display.h"
#include "components/exo/wayland/serial_tracker.h"
@@ -199,9 +200,15 @@ Server::Server(Display* display) : display_(display) {
bind_keyboard_configuration);
wl_global_create(wl_display_.get(), &zcr_notification_shell_v1_interface, 1,
display_, bind_notification_shell);
+
+ remote_shell_data_ = std::make_unique<WaylandRemoteShellData>(
+ display_,
+ WaylandRemoteShellData::OutputResourceProvider(base::BindRepeating(
+ &Server::GetOutputResource, base::Unretained(this))));
wl_global_create(wl_display_.get(), &zcr_remote_shell_v1_interface,
- zcr_remote_shell_v1_interface.version, display_,
- bind_remote_shell);
+ zcr_remote_shell_v1_interface.version,
+ remote_shell_data_.get(), bind_remote_shell);
+
wl_global_create(wl_display_.get(), &zcr_stylus_tools_v1_interface, 1,
display_, bind_stylus_tools);
wl_global_create(wl_display_.get(),
diff --git a/chromium/components/exo/wayland/server.h b/chromium/components/exo/wayland/server.h
index 62baedd7a3a..5bec03ad5a9 100644
--- a/chromium/components/exo/wayland/server.h
+++ b/chromium/components/exo/wayland/server.h
@@ -32,6 +32,7 @@ struct WaylandSeat;
struct WaylandTextInputManager;
struct WaylandXdgShell;
struct WaylandZxdgShell;
+struct WaylandRemoteShellData;
// This class is a thin wrapper around a Wayland display server. All Wayland
// requests are dispatched into the given Exosphere display.
@@ -82,6 +83,7 @@ class Server : public display::DisplayObserver {
std::unique_ptr<WaylandTextInputManager> zwp_text_manager_data_;
std::unique_ptr<WaylandZxdgShell> zxdg_shell_data_;
std::unique_ptr<WaylandXdgShell> xdg_shell_data_;
+ std::unique_ptr<WaylandRemoteShellData> remote_shell_data_;
#endif
DISALLOW_COPY_AND_ASSIGN(Server);
diff --git a/chromium/components/exo/wayland/wayland_display_observer.cc b/chromium/components/exo/wayland/wayland_display_observer.cc
index e15cb235030..7655505db2a 100644
--- a/chromium/components/exo/wayland/wayland_display_observer.cc
+++ b/chromium/components/exo/wayland/wayland_display_observer.cc
@@ -55,6 +55,11 @@ void WaylandDisplayHandler::AddObserver(WaylandDisplayObserver* observer) {
}
}
+int64_t WaylandDisplayHandler::id() const {
+ DCHECK(output_);
+ return output_->id();
+}
+
void WaylandDisplayHandler::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t changed_metrics) {
diff --git a/chromium/components/exo/wayland/wayland_display_observer.h b/chromium/components/exo/wayland/wayland_display_observer.h
index 7ec87fb8a75..bf7ecbcb218 100644
--- a/chromium/components/exo/wayland/wayland_display_observer.h
+++ b/chromium/components/exo/wayland/wayland_display_observer.h
@@ -41,6 +41,7 @@ class WaylandDisplayHandler : public display::DisplayObserver,
wl_resource* output_resource);
~WaylandDisplayHandler() override;
void AddObserver(WaylandDisplayObserver* observer);
+ int64_t id() const;
// Overridden from display::DisplayObserver:
void OnDisplayMetricsChanged(const display::Display& display,
diff --git a/chromium/components/exo/wayland/wayland_keyboard_delegate.cc b/chromium/components/exo/wayland/wayland_keyboard_delegate.cc
index 61d1f6e8181..b74f727f8d9 100644
--- a/chromium/components/exo/wayland/wayland_keyboard_delegate.cc
+++ b/chromium/components/exo/wayland/wayland_keyboard_delegate.cc
@@ -10,6 +10,7 @@
#include <wayland-server-protocol-core.h>
#include "base/containers/flat_map.h"
+#include "base/memory/unsafe_shared_memory_region.h"
#include "components/exo/wayland/serial_tracker.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
diff --git a/chromium/components/exo/wayland/wl_data_device_manager.cc b/chromium/components/exo/wayland/wl_data_device_manager.cc
index f344de18c9a..f59154bdec8 100644
--- a/chromium/components/exo/wayland/wl_data_device_manager.cc
+++ b/chromium/components/exo/wayland/wl_data_device_manager.cc
@@ -91,7 +91,7 @@ class WaylandDataSourceDelegate : public DataSourceDelegate {
return surface &&
wl_resource_get_client(GetSurfaceResource(surface)) == client_;
}
- void OnTarget(const base::Optional<std::string>& mime_type) override {
+ void OnTarget(const absl::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_));
@@ -302,9 +302,9 @@ class WaylandDataDeviceDelegate : public DataDeviceDelegate {
Surface* origin,
Surface* icon,
uint32_t serial) {
- base::Optional<wayland::SerialTracker::EventType> event_type =
+ absl::optional<wayland::SerialTracker::EventType> event_type =
serial_tracker_->GetEventType(serial);
- if (event_type == base::nullopt) {
+ if (event_type == absl::nullopt) {
LOG(ERROR) << "The serial passed to StartDrag does not exist.";
return;
}
@@ -327,9 +327,9 @@ class WaylandDataDeviceDelegate : public DataDeviceDelegate {
void SetSelection(DataDevice* data_device,
DataSource* source,
uint32_t serial) {
- base::Optional<wayland::SerialTracker::EventType> event_type =
+ absl::optional<wayland::SerialTracker::EventType> event_type =
serial_tracker_->GetEventType(serial);
- if (event_type == base::nullopt) {
+ if (event_type == absl::nullopt) {
LOG(ERROR) << "The serial passed to SetSelection does not exist.";
return;
}
diff --git a/chromium/components/exo/wayland/zaura_shell.cc b/chromium/components/exo/wayland/zaura_shell.cc
index f9ad35ea7b5..98f08f2ae01 100644
--- a/chromium/components/exo/wayland/zaura_shell.cc
+++ b/chromium/components/exo/wayland/zaura_shell.cc
@@ -24,6 +24,7 @@
#include "components/exo/wm_helper.h"
#include "ui/aura/env.h"
#include "ui/aura/window_occlusion_tracker.h"
+#include "ui/compositor/layer.h"
#include "ui/display/display_observer.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/display_util.h"
@@ -189,6 +190,14 @@ void aura_surface_set_window_session_id(wl_client* client,
GetUserDataAs<AuraSurface>(resource)->SetWindowSessionId(id);
}
+void aura_surface_set_can_go_back(wl_client* client, wl_resource* resource) {
+ GetUserDataAs<AuraSurface>(resource)->SetCanGoBack();
+}
+
+void aura_surface_unset_can_go_back(wl_client* client, wl_resource* resource) {
+ GetUserDataAs<AuraSurface>(resource)->UnsetCanGoBack();
+}
+
const struct zaura_surface_interface aura_surface_implementation = {
aura_surface_set_frame,
aura_surface_set_parent,
@@ -207,7 +216,9 @@ const struct zaura_surface_interface aura_surface_implementation = {
aura_surface_set_snap_left,
aura_surface_set_snap_right,
aura_surface_unset_snap,
- aura_surface_set_window_session_id};
+ aura_surface_set_window_session_id,
+ aura_surface_set_can_go_back,
+ aura_surface_unset_can_go_back};
} // namespace
@@ -330,6 +341,14 @@ void AuraSurface::SetWindowSessionId(int32_t window_session_id) {
surface_->SetWindowSessionId(window_session_id);
}
+void AuraSurface::SetCanGoBack() {
+ surface_->SetCanGoBack();
+}
+
+void AuraSurface::UnsetCanGoBack() {
+ surface_->UnsetCanGoBack();
+}
+
// Overridden from SurfaceObserver:
void AuraSurface::OnSurfaceDestroying(Surface* surface) {
surface->RemoveSurfaceObserver(this);
@@ -340,11 +359,14 @@ void AuraSurface::OnWindowOcclusionChanged(Surface* surface) {
if (!surface_ || !surface_->IsTrackingOcclusion())
return;
auto* window = surface_->window();
- ComputeAndSendOcclusionFraction(window->occlusion_state(),
+ ComputeAndSendOcclusionFraction(window->GetOcclusionState(),
window->occluded_region_in_root());
}
void AuraSurface::OnFrameLockingChanged(Surface* surface, bool lock) {
+ if (wl_resource_get_version(resource_) <
+ ZAURA_SURFACE_LOCK_FRAME_NORMAL_SINCE_VERSION)
+ return;
if (lock)
zaura_surface_send_lock_frame_normal(resource_);
else
diff --git a/chromium/components/exo/wayland/zaura_shell.h b/chromium/components/exo/wayland/zaura_shell.h
index 5028f277452..abdb05486d6 100644
--- a/chromium/components/exo/wayland/zaura_shell.h
+++ b/chromium/components/exo/wayland/zaura_shell.h
@@ -17,7 +17,7 @@ struct wl_resource;
namespace exo {
namespace wayland {
-constexpr uint32_t kZAuraShellVersion = 18;
+constexpr uint32_t kZAuraShellVersion = 19;
// Adds bindings to the Aura Shell. Normally this implies Ash on ChromeOS
// builds. On non-ChromeOS builds the protocol provides access to Aura windowing
@@ -49,6 +49,8 @@ class AuraSurface : public SurfaceObserver,
void SetSnapRight();
void UnsetSnap();
void SetWindowSessionId(int32_t window_session_id);
+ void SetCanGoBack();
+ void UnsetCanGoBack();
// Overridden from SurfaceObserver:
void OnSurfaceDestroying(Surface* surface) override;
diff --git a/chromium/components/exo/wayland/zaura_shell_unittest.cc b/chromium/components/exo/wayland/zaura_shell_unittest.cc
index 22ff1a5f643..c2df8ade6ed 100644
--- a/chromium/components/exo/wayland/zaura_shell_unittest.cc
+++ b/chromium/components/exo/wayland/zaura_shell_unittest.cc
@@ -18,6 +18,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/window_occlusion_tracker.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
@@ -88,6 +89,8 @@ class MockSurfaceDelegate : public SurfaceDelegate {
MOCK_METHOD(void, SetSnappedToRight, (), (override));
MOCK_METHOD(void, SetSnappedToLeft, (), (override));
MOCK_METHOD(void, UnsetSnap, (), (override));
+ MOCK_METHOD(void, SetCanGoBack, (), (override));
+ MOCK_METHOD(void, UnsetCanGoBack, (), (override));
};
} // namespace
@@ -106,10 +109,10 @@ class ZAuraSurfaceTest : public test::ExoTestBase,
std::unique_ptr<Buffer> buffer(
new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)));
- surface_.reset(new Surface);
+ surface_ = std::make_unique<Surface>();
surface_->Attach(buffer.get());
- aura_surface_.reset(new TestAuraSurface(surface_.get()));
+ aura_surface_ = std::make_unique<TestAuraSurface>(surface_.get());
gfx::Transform transform;
transform.Scale(1.5f, 1.5f);
diff --git a/chromium/components/exo/wayland/zcr_notification_shell.cc b/chromium/components/exo/wayland/zcr_notification_shell.cc
index 5b7eb80fa9f..f5006631a64 100644
--- a/chromium/components/exo/wayland/zcr_notification_shell.cc
+++ b/chromium/components/exo/wayland/zcr_notification_shell.cc
@@ -12,11 +12,12 @@
#include "base/atomic_sequence_num.h"
#include "base/bind.h"
-#include "base/optional.h"
+#include "base/strings/stringprintf.h"
#include "components/exo/notification.h"
#include "components/exo/notification_surface.h"
#include "components/exo/notification_surface_manager.h"
#include "components/exo/wayland/server_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace exo {
namespace wayland {
@@ -61,7 +62,7 @@ class WaylandNotificationShellNotification {
wl_client_flush(wl_resource_get_client(resource_));
}
- void OnClick(const base::Optional<int>& button_index) {
+ void OnClick(const absl::optional<int>& button_index) {
int32_t index = button_index ? *button_index : -1;
zcr_notification_shell_notification_v1_send_clicked(resource_, index);
wl_client_flush(wl_resource_get_client(resource_));
diff --git a/chromium/components/exo/wayland/zcr_remote_shell.cc b/chromium/components/exo/wayland/zcr_remote_shell.cc
index 97db3a294e2..809097a8dce 100644
--- a/chromium/components/exo/wayland/zcr_remote_shell.cc
+++ b/chromium/components/exo/wayland/zcr_remote_shell.cc
@@ -56,21 +56,6 @@ constexpr char kForceRemoteShellScale[] = "force-remote-shell-scale";
} // namespace switches
-Surface* FindRootSurface(aura::Window* window) {
- if (!window)
- return nullptr;
- Surface* root = GetShellRootSurface(window);
- if (root)
- return root;
- root = Surface::AsSurface(window);
- for (aura::Window* parent = window->parent();
- root && parent && Surface::AsSurface(parent);
- parent = parent->parent()) {
- root = Surface::AsSurface(parent);
- }
- return root;
-}
-
using chromeos::WindowStateType;
// We don't send configure immediately after tablet mode switch
@@ -677,6 +662,20 @@ void remote_surface_unset_resize_lock(wl_client* client,
GetUserDataAs<ClientControlledShellSurface>(resource)->SetResizeLock(false);
}
+void remote_surface_set_bounds_in_output(wl_client* client,
+ wl_resource* resource,
+ wl_resource* output_resource,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height) {
+ WaylandDisplayHandler* display_handler =
+ GetUserDataAs<WaylandDisplayHandler>(output_resource);
+ // Bounds are set in pixels, and should not be scaled.
+ GetUserDataAs<ClientControlledShellSurface>(resource)->SetBounds(
+ display_handler->id(), gfx::Rect(x, y, width, height));
+}
+
const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
remote_surface_destroy,
remote_surface_set_app_id,
@@ -728,7 +727,9 @@ const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
remote_surface_unset_pip_original_window,
remote_surface_set_system_gesture_exclusion,
remote_surface_set_resize_lock,
- remote_surface_unset_resize_lock};
+ remote_surface_unset_resize_lock,
+ remote_surface_set_bounds_in_output,
+};
////////////////////////////////////////////////////////////////////////////////
// notification_surface_interface:
@@ -767,9 +768,25 @@ void input_method_surface_set_bounds(wl_client* client,
gfx::Rect(x, y, width, height));
}
+void input_method_surface_set_bounds_in_output(wl_client* client,
+ wl_resource* resource,
+ wl_resource* output_resource,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height) {
+ WaylandDisplayHandler* display_handler =
+ GetUserDataAs<WaylandDisplayHandler>(output_resource);
+ GetUserDataAs<InputMethodSurface>(resource)->SetBounds(
+ display_handler->id(), gfx::Rect(x, y, width, height));
+}
+
const struct zcr_input_method_surface_v1_interface
- input_method_surface_implementation = {input_method_surface_destroy,
- input_method_surface_set_bounds};
+ input_method_surface_implementation = {
+ input_method_surface_destroy,
+ input_method_surface_set_bounds,
+ input_method_surface_set_bounds_in_output,
+};
////////////////////////////////////////////////////////////////////////////////
// toast_surface_interface:
@@ -797,10 +814,24 @@ void toast_surface_set_size(wl_client* client,
gfx::Size(width, height));
}
+void toast_surface_set_bounds_in_output(wl_client* client,
+ wl_resource* resource,
+ wl_resource* output_resource,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height) {
+ WaylandDisplayHandler* display_handler =
+ GetUserDataAs<WaylandDisplayHandler>(output_resource);
+ GetUserDataAs<ToastSurface>(resource)->SetBounds(
+ display_handler->id(), gfx::Rect(x, y, width, height));
+}
+
const struct zcr_toast_surface_v1_interface toast_surface_implementation = {
toast_surface_destroy,
toast_surface_set_position,
toast_surface_set_size,
+ toast_surface_set_bounds_in_output,
};
////////////////////////////////////////////////////////////////////////////////
@@ -900,14 +931,17 @@ class WaylandRemoteOutput : public WaylandDisplayObserver {
// Implements remote shell interface and monitors workspace state needed
// for the remote shell interface.
class WaylandRemoteShell : public ash::TabletModeObserver,
- public aura::client::FocusChangeObserver,
public display::DisplayObserver {
public:
- WaylandRemoteShell(Display* display, wl_resource* remote_shell_resource)
- : display_(display), remote_shell_resource_(remote_shell_resource) {
+ using OutputResourceProvider = base::RepeatingCallback<wl_resource*(int64_t)>;
+ WaylandRemoteShell(Display* display,
+ wl_resource* remote_shell_resource,
+ OutputResourceProvider output_provider)
+ : display_(display),
+ remote_shell_resource_(remote_shell_resource),
+ output_provider_(output_provider) {
WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
helper->AddTabletModeObserver(this);
- helper->AddFocusObserver(this);
display::Screen::GetScreen()->AddObserver(this);
helper->AddFrameThrottlingObserver();
@@ -928,12 +962,13 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
}
SendDisplayMetrics();
- SendActivated(helper->GetActiveWindow(), nullptr);
+ display->seat()->SetFocusChangedCallback(
+ base::BindRepeating(&WaylandRemoteShell::FocusedSurfaceChanged,
+ weak_ptr_factory_.GetWeakPtr()));
}
~WaylandRemoteShell() override {
WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
helper->RemoveTabletModeObserver(this);
- helper->RemoveFocusObserver(this);
display::Screen::GetScreen()->RemoveObserver(this);
helper->RemoveFrameThrottlingObserver();
}
@@ -942,7 +977,7 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
Surface* surface,
int container,
double default_device_scale_factor) {
- return display_->CreateClientControlledShellSurface(
+ return display_->CreateOrGetClientControlledShellSurface(
surface, container, default_device_scale_factor,
use_default_scale_cancellation_);
}
@@ -1026,12 +1061,6 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
}
void OnTabletModeEnded() override {}
- // Overridden from wm::ActivationChangeObserver:
- void OnWindowFocused(aura::Window* gained_active,
- aura::Window* lost_active) override {
- SendActivated(gained_active, lost_active);
- }
-
private:
class WaylandRemoteSurfaceDelegate
: public ClientControlledShellSurface::Delegate {
@@ -1205,9 +1234,9 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
wl_client_flush(client);
}
- void SendActivated(aura::Window* gained_active, aura::Window* lost_active) {
- Surface* gained_active_surface = FindRootSurface(gained_active);
- Surface* lost_active_surface = FindRootSurface(lost_active);
+ void FocusedSurfaceChanged(Surface* gained_active_surface,
+ Surface* lost_active_surface,
+ bool has_focused_client) {
if (gained_active_surface == lost_active_surface)
return;
@@ -1238,7 +1267,7 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
uint32_t focus_state;
if (gained_active_surface_resource) {
focus_state = ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED;
- } else if (gained_active) {
+ } else if (has_focused_client) {
focus_state =
ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED;
} else {
@@ -1320,6 +1349,18 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
static_cast<uint32_t>(display_id), bounds_in_display.x(),
bounds_in_display.y(), bounds_in_display.width(),
bounds_in_display.height(), reason);
+ if (wl_resource_get_version(resource) >=
+ ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGED_IN_OUTPUT_SINCE_VERSION) {
+ wl_resource* output = output_provider_.Run(display_id);
+ if (output == nullptr) {
+ LOG(WARNING) << "Failed to get wayland_output resource for display_id: "
+ << display_id;
+ return;
+ }
+ zcr_remote_surface_v1_send_bounds_changed_in_output(
+ resource, output, bounds_in_display.x(), bounds_in_display.y(),
+ bounds_in_display.width(), bounds_in_display.height(), reason);
+ }
}
void OnRemoteSurfaceStateChanged(wl_resource* resource,
@@ -1408,6 +1449,9 @@ class WaylandRemoteShell : public ash::TabletModeObserver,
// The remote shell resource associated with observer.
wl_resource* const remote_shell_resource_;
+ // Callback to get the wl_output resource for a given display_id.
+ OutputResourceProvider const output_provider_;
+
// When true, the compositor should use the default_device_scale_factor to
// undo the scaling on the client buffers. When false, the compositor should
// use the device_scale_factor for the display for this scaling cancellation.
@@ -1608,6 +1652,12 @@ const struct zcr_remote_shell_v1_interface remote_shell_implementation = {
} // namespace
+WaylandRemoteShellData::WaylandRemoteShellData(
+ Display* display,
+ OutputResourceProvider output_provider)
+ : display(display), output_provider(output_provider) {}
+WaylandRemoteShellData::~WaylandRemoteShellData() {}
+
void bind_remote_shell(wl_client* client,
void* data,
uint32_t version,
@@ -1616,9 +1666,12 @@ void bind_remote_shell(wl_client* client,
client, &zcr_remote_shell_v1_interface,
std::min<uint32_t>(version, zcr_remote_shell_v1_interface.version), id);
- SetImplementation(resource, &remote_shell_implementation,
- std::make_unique<WaylandRemoteShell>(
- static_cast<Display*>(data), resource));
+ auto* remote_shell_data = static_cast<WaylandRemoteShellData*>(data);
+ SetImplementation(
+ resource, &remote_shell_implementation,
+ std::make_unique<WaylandRemoteShell>(
+ remote_shell_data->display, resource,
+ base::BindRepeating(remote_shell_data->output_provider, client)));
}
gfx::Insets GetWorkAreaInsetsInPixel(const display::Display& display,
diff --git a/chromium/components/exo/wayland/zcr_remote_shell.h b/chromium/components/exo/wayland/zcr_remote_shell.h
index dc8e3ed7efd..9ab8fc859d3 100644
--- a/chromium/components/exo/wayland/zcr_remote_shell.h
+++ b/chromium/components/exo/wayland/zcr_remote_shell.h
@@ -7,7 +7,10 @@
#include <stdint.h>
+#include "base/callback.h"
+
struct wl_client;
+struct wl_resource;
namespace gfx {
class Rect;
@@ -20,8 +23,28 @@ class Display;
}
namespace exo {
+
+class Display;
+
namespace wayland {
+struct WaylandRemoteShellData {
+ using OutputResourceProvider =
+ base::RepeatingCallback<wl_resource*(wl_client*, int64_t)>;
+
+ explicit WaylandRemoteShellData(Display* display,
+ OutputResourceProvider output_provider);
+ ~WaylandRemoteShellData();
+
+ // Owned by WaylandServerController, which always outlives this.
+ Display* const display;
+
+ OutputResourceProvider const output_provider;
+
+ WaylandRemoteShellData(const WaylandRemoteShellData&) = delete;
+ WaylandRemoteShellData& operator=(const WaylandRemoteShellData&) = delete;
+};
+
void bind_remote_shell(wl_client* client,
void* data,
uint32_t version,
diff --git a/chromium/components/exo/wayland/zwp_text_input_manager.cc b/chromium/components/exo/wayland/zwp_text_input_manager.cc
index 1356a8a7b1e..4c5a9424f9e 100644
--- a/chromium/components/exo/wayland/zwp_text_input_manager.cc
+++ b/chromium/components/exo/wayland/zwp_text_input_manager.cc
@@ -76,6 +76,7 @@ class WaylandTextInputDelegate : public TextInput::Delegate {
break;
case ui::ImeTextSpan::Type::kMisspellingSuggestion:
case ui::ImeTextSpan::Type::kAutocorrect:
+ case ui::ImeTextSpan::Type::kGrammarSuggestion:
style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_INCORRECT;
break;
}
@@ -222,7 +223,7 @@ void text_input_hide_input_panel(wl_client* client, wl_resource* resource) {
}
void text_input_reset(wl_client* client, wl_resource* resource) {
- GetUserDataAs<TextInput>(resource)->Resync();
+ GetUserDataAs<TextInput>(resource)->Reset();
}
void text_input_set_surrounding_text(wl_client* client,
diff --git a/chromium/components/exo/wm_helper.h b/chromium/components/exo/wm_helper.h
index 5dfdfd6c2fc..5c0950b65f2 100644
--- a/chromium/components/exo/wm_helper.h
+++ b/chromium/components/exo/wm_helper.h
@@ -11,7 +11,6 @@
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/time/time.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h"
@@ -50,6 +49,8 @@ class VSyncTimingManager;
// Helper interface for accessing WindowManager related features.
class WMHelper : public aura::client::DragDropDelegate {
public:
+ using DropCallback = aura::client::DragDropDelegate::DropCallback;
+
class DragDropObserver {
public:
virtual void OnDragEntered(const ui::DropTargetEvent& event) = 0;
@@ -58,6 +59,7 @@ class WMHelper : public aura::client::DragDropDelegate {
virtual void OnDragExited() = 0;
virtual ui::mojom::DragOperation OnPerformDrop(
const ui::DropTargetEvent& event) = 0;
+ virtual DropCallback GetDropCallback(const ui::DropTargetEvent& event) = 0;
protected:
virtual ~DragDropObserver() {}
@@ -160,6 +162,7 @@ class WMHelper : public aura::client::DragDropDelegate {
ui::mojom::DragOperation OnPerformDrop(
const ui::DropTargetEvent& event,
std::unique_ptr<ui::OSExchangeData> data) override = 0;
+ DropCallback GetDropCallback(const ui::DropTargetEvent& event) override = 0;
// Registers an AppPropertyResolver. Multiple resolver can be registered and
// all resolvers are called in the registration order by the method below.
diff --git a/chromium/components/exo/wm_helper_chromeos.cc b/chromium/components/exo/wm_helper_chromeos.cc
index 3afb5413d59..05db30590bd 100644
--- a/chromium/components/exo/wm_helper_chromeos.cc
+++ b/chromium/components/exo/wm_helper_chromeos.cc
@@ -3,18 +3,20 @@
// found in the LICENSE file.
#include "components/exo/wm_helper_chromeos.h"
-#include "components/exo/wm_helper.h"
#include "ash/frame_throttler/frame_throttling_controller.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
+#include "base/callback_helpers.h"
#include "base/memory/singleton.h"
+#include "components/exo/wm_helper.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/client/focus_client.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
+#include "ui/compositor/layer.h"
#include "ui/display/manager/display_configurator.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/types/display_snapshot.h"
@@ -153,6 +155,13 @@ ui::mojom::DragOperation WMHelperChromeOS::OnPerformDrop(
return operation;
}
+WMHelper::DropCallback WMHelperChromeOS::GetDropCallback(
+ const ui::DropTargetEvent& event) {
+ // TODO(crbug.com/1197501): Return drop callback
+ NOTIMPLEMENTED();
+ return base::NullCallback();
+}
+
void WMHelperChromeOS::AddVSyncParameterObserver(
mojo::PendingRemote<viz::mojom::VSyncParameterObserver> observer) {
GetPrimaryRoot()->layer()->GetCompositor()->AddVSyncParameterObserver(
diff --git a/chromium/components/exo/wm_helper_chromeos.h b/chromium/components/exo/wm_helper_chromeos.h
index 547d53d24d1..f0cf8286799 100644
--- a/chromium/components/exo/wm_helper_chromeos.h
+++ b/chromium/components/exo/wm_helper_chromeos.h
@@ -113,6 +113,8 @@ class WMHelperChromeOS : public WMHelper, public VSyncTimingManager::Delegate {
ui::mojom::DragOperation OnPerformDrop(
const ui::DropTargetEvent& event,
std::unique_ptr<ui::OSExchangeData> data) override;
+ WMHelper::DropCallback GetDropCallback(
+ const ui::DropTargetEvent& event) override;
// Overridden from VSyncTimingManager::Delegate:
void AddVSyncParameterObserver(
diff --git a/chromium/components/exo/wm_helper_chromeos_unittest.cc b/chromium/components/exo/wm_helper_chromeos_unittest.cc
index 4a7b68a112d..a9a98585701 100644
--- a/chromium/components/exo/wm_helper_chromeos_unittest.cc
+++ b/chromium/components/exo/wm_helper_chromeos_unittest.cc
@@ -8,6 +8,8 @@
#include "ash/frame_throttler/frame_throttling_controller.h"
#include "ash/shell.h"
+#include "base/callback_helpers.h"
+#include "base/notreached.h"
#include "components/exo/mock_vsync_timing_observer.h"
#include "components/exo/test/exo_test_base.h"
#include "components/exo/wm_helper.h"
@@ -39,6 +41,11 @@ class MockDragDropObserver : public WMHelper::DragDropObserver {
DragOperation OnPerformDrop(const ui::DropTargetEvent& event) override {
return drop_result_;
}
+ WMHelper::DropCallback GetDropCallback(
+ const ui::DropTargetEvent& event) override {
+ NOTIMPLEMENTED();
+ return base::NullCallback();
+ }
private:
DragOperation drop_result_;
diff --git a/chromium/components/exo/xdg_shell_surface.h b/chromium/components/exo/xdg_shell_surface.h
index 9319bc8cf45..12ba7a68c78 100644
--- a/chromium/components/exo/xdg_shell_surface.h
+++ b/chromium/components/exo/xdg_shell_surface.h
@@ -6,16 +6,14 @@
#define COMPONENTS_EXO_XDG_SHELL_SURFACE_H_
#include <cstdint>
-#include <memory>
-#include <string>
#include "ash/display/window_tree_host_manager.h"
#include "ash/wm/window_state_observer.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/exo/shell_surface.h"
#include "components/exo/surface_observer.h"
#include "components/exo/surface_tree_host.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/window_observer.h"
#include "ui/base/hit_test.h"
diff --git a/chromium/components/exo/xkb_tracker.h b/chromium/components/exo/xkb_tracker.h
index 74d4a0933a1..8dd39f34518 100644
--- a/chromium/components/exo/xkb_tracker.h
+++ b/chromium/components/exo/xkb_tracker.h
@@ -14,7 +14,7 @@
#include <xkbcommon/xkbcommon.h>
#include "base/memory/free_deleter.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/scoped_xkb.h" // nogncheck
#endif
diff --git a/chromium/components/external_intents/android/BUILD.gn b/chromium/components/external_intents/android/BUILD.gn
index 86d85e2c9d0..e3ab9740539 100644
--- a/chromium/components/external_intents/android/BUILD.gn
+++ b/chromium/components/external_intents/android/BUILD.gn
@@ -7,7 +7,7 @@ import("//build/config/android/rules.gni")
android_library("java") {
sources = [
"java/src/org/chromium/components/external_intents/AuthenticatorNavigationInterceptor.java",
- "java/src/org/chromium/components/external_intents/ExternalIntentsFeatureList.java",
+ "java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java",
"java/src/org/chromium/components/external_intents/ExternalIntentsSwitches.java",
"java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java",
"java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java",
@@ -23,6 +23,7 @@ android_library("java") {
"//base:base_java",
"//components/embedder_support/android:util_java",
"//components/navigation_interception/android:navigation_interception_java",
+ "//components/url_formatter/android:url_formatter_java",
"//components/webapk/android/libs/client:java",
"//content/public/android:content_java",
"//services/network/public/mojom:url_loader_base_java",
@@ -45,15 +46,15 @@ android_resources("java_resources") {
generate_jni("jni_headers") {
sources = [
- "java/src/org/chromium/components/external_intents/ExternalIntentsFeatureList.java",
+ "java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java",
"java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java",
]
}
static_library("android") {
sources = [
- "external_intents_feature_list.cc",
- "external_intents_feature_list.h",
+ "external_intents_features.cc",
+ "external_intents_features.h",
"intercept_navigation_delegate_impl.cc",
]
@@ -80,11 +81,14 @@ android_library("javatests") {
"//content/public/test/android:content_java_test_support",
"//third_party/android_sdk:android_test_mock_java",
"//third_party/android_support_test_runner:runner_java",
+ "//third_party/androidx:androidx_appcompat_appcompat_java",
"//third_party/androidx:androidx_browser_browser_java",
"//third_party/androidx:androidx_core_core_java",
"//third_party/androidx:androidx_test_runner_java",
"//third_party/junit",
+ "//third_party/mockito:mockito_java",
"//ui/android:ui_java",
+ "//ui/android:ui_java_test_support",
"//url:gurl_java",
"//url:gurl_junit_test_support",
"//url:origin_java",
diff --git a/chromium/components/external_intents/android/external_intents_feature_list.cc b/chromium/components/external_intents/android/external_intents_features.cc
index 91a4c0e7edc..dca311ee082 100644
--- a/chromium/components/external_intents/android/external_intents_feature_list.cc
+++ b/chromium/components/external_intents/android/external_intents_features.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/external_intents/android/external_intents_feature_list.h"
+#include "components/external_intents/android/external_intents_features.h"
#include <jni.h>
#include <stddef.h>
@@ -10,28 +10,17 @@
#include "base/android/jni_string.h"
#include "base/notreached.h"
-#include "components/external_intents/android/jni_headers/ExternalIntentsFeatureList_jni.h"
+#include "components/external_intents/android/jni_headers/ExternalIntentsFeatures_jni.h"
namespace external_intents {
namespace {
-// Array of features exposed through the Java ExternalIntentsFeatureList API.
+// Array of features exposed through the Java ExternalIntentsFeatures API.
const base::Feature* kFeaturesExposedToJava[] = {
&kIntentBlockExternalFormRedirectsNoGesture,
};
-const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
- for (const auto* feature : kFeaturesExposedToJava) {
- if (feature->name == feature_name)
- return feature;
- }
- NOTREACHED()
- << "Queried feature cannot be found in ExternalIntentsFeatureList: "
- << feature_name;
- return nullptr;
-}
-
} // namespace
// Alphabetical:
@@ -39,12 +28,8 @@ const base::Feature kIntentBlockExternalFormRedirectsNoGesture{
"IntentBlockExternalFormRedirectsNoGesture",
base::FEATURE_DISABLED_BY_DEFAULT};
-static jboolean JNI_ExternalIntentsFeatureList_IsEnabled(
- JNIEnv* env,
- const base::android::JavaParamRef<jstring>& jfeature_name) {
- const base::Feature* feature = FindFeatureExposedToJava(
- base::android::ConvertJavaStringToUTF8(env, jfeature_name));
- return base::FeatureList::IsEnabled(*feature);
+static jlong JNI_ExternalIntentsFeatures_GetFeature(JNIEnv* env, jint ordinal) {
+ return reinterpret_cast<jlong>(kFeaturesExposedToJava[ordinal]);
}
} // namespace external_intents
diff --git a/chromium/components/external_intents/android/external_intents_feature_list.h b/chromium/components/external_intents/android/external_intents_features.h
index 02388aafb0b..e6c0d54b303 100644
--- a/chromium/components/external_intents/android/external_intents_feature_list.h
+++ b/chromium/components/external_intents/android/external_intents_features.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_EXTERNAL_INTENTS_ANDROID_EXTERNAL_INTENTS_FEATURE_LIST_H_
-#define COMPONENTS_EXTERNAL_INTENTS_ANDROID_EXTERNAL_INTENTS_FEATURE_LIST_H_
+#ifndef COMPONENTS_EXTERNAL_INTENTS_ANDROID_EXTERNAL_INTENTS_FEATURES_H_
+#define COMPONENTS_EXTERNAL_INTENTS_ANDROID_EXTERNAL_INTENTS_FEATURES_H_
#include "base/feature_list.h"
@@ -14,4 +14,4 @@ extern const base::Feature kIntentBlockExternalFormRedirectsNoGesture;
} // namespace external_intents
-#endif // COMPONENTS_EXTERNAL_INTENTS_ANDROID_EXTERNAL_INTENTS_FEATURE_LIST_H_
+#endif // COMPONENTS_EXTERNAL_INTENTS_ANDROID_EXTERNAL_INTENTS_FEATURES_H_
diff --git a/chromium/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/chromium/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
index cdbd84a6fdd..41bc53777ff 100644
--- a/chromium/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
+++ b/chromium/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
@@ -5,8 +5,12 @@
package org.chromium.components.external_intents;
import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.Instrumentation.ActivityMonitor;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
@@ -20,18 +24,26 @@ import android.provider.Browser;
import android.support.test.InstrumentationRegistry;
import android.test.mock.MockPackageManager;
+import androidx.appcompat.app.AlertDialog;
import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
import org.chromium.base.ContextUtils;
import org.chromium.base.Function;
import org.chromium.base.IntentUtils;
+import org.chromium.base.ThreadUtils;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Batch;
import org.chromium.components.external_intents.ExternalNavigationDelegate.IntentToAutofillAllowingAppResult;
@@ -43,6 +55,7 @@ import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
import org.chromium.ui.base.PageTransition;
import org.chromium.ui.base.WindowAndroid;
+import org.chromium.ui.test.util.DummyUiActivity;
import org.chromium.url.GURL;
import org.chromium.url.Origin;
@@ -75,6 +88,11 @@ public class ExternalNavigationHandlerTest {
private static final boolean HANDLES_INSTANT_APP_LAUNCHING_INTERNALLY = true;
private static final boolean INTENT_STARTED_TASK = true;
+ private static final String INTENT_APP_PACKAGE_NAME = "com.imdb.mobile";
+ private static final String YOUTUBE_URL = "http://youtube.com/";
+ private static final String YOUTUBE_MOBILE_URL = "http://m.youtube.com";
+ private static final String YOUTUBE_PACKAGE_NAME = "youtube";
+
private static final String SEARCH_RESULT_URL_FOR_TOM_HANKS =
"https://www.google.com/search?q=tom+hanks";
private static final String IMDB_WEBPAGE_FOR_TOM_HANKS = "http://m.imdb.com/name/nm0000158";
@@ -114,11 +132,9 @@ public class ExternalNavigationHandlerTest {
+ "package=org.chromium.chrome;"
+ "action=android.intent.action.VIEW;"
+ "scheme=http;"
+ + "S." + ExternalNavigationHandler.EXTRA_BROWSER_FALLBACK_URL + "="
+ + Uri.encode(YOUTUBE_URL) + ";end"
+ "end;";
- private static final String INTENT_APP_PACKAGE_NAME = "com.imdb.mobile";
- private static final String YOUTUBE_URL = "http://youtube.com";
- private static final String YOUTUBE_MOBILE_URL = "http://m.youtube.com";
- private static final String YOUTUBE_PACKAGE_NAME = "youtube";
private static final String PLUS_STREAM_URL = "https://plus.google.com/stream";
private static final String CALENDAR_URL = "http://www.google.com/calendar";
@@ -156,6 +172,12 @@ public class ExternalNavigationHandlerTest {
private static final String IS_INSTANT_APP_EXTRA = "IS_INSTANT_APP";
+ @Rule
+ public MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
+
+ @Mock
+ AlertDialog mAlertDialog;
+
private Context mContext;
private final TestExternalNavigationDelegate mDelegate;
private ExternalNavigationHandlerForTesting mUrlHandler;
@@ -180,6 +202,11 @@ public class ExternalNavigationHandlerTest {
@After
public void tearDown() {
ContextUtils.initApplicationContextForTests(mApplicationContextToRestore);
+ // Any tests showing the dialog should have closed the dialog, even if assertions in the
+ // test failed.
+ if (mUrlHandler.mShownIncognitoAlertDialog != null) {
+ Assert.assertFalse(mUrlHandler.mShownIncognitoAlertDialog.isShowing());
+ }
}
@Test
@@ -522,41 +549,30 @@ public class ExternalNavigationHandlerTest {
public void testYouTubePairingCode() {
mDelegate.add(new IntentActivity(YOUTUBE_MOBILE_URL, YOUTUBE_PACKAGE_NAME));
+ String mobileUrl = "http://m.youtube.com/watch?v=1234&pairingCode=5678";
int transitionTypeIncomingIntent = PageTransition.LINK | PageTransition.FROM_API;
- final String[] goodUrls = {"http://m.youtube.com/watch?v=1234&pairingCode=5678",
- "youtube.com?pairingCode=xyz", "youtube.com/tv?pairingCode=xyz",
- "youtube.com/watch?v=1234&version=3&autohide=1&pairingCode=xyz",
- "youtube.com/watch?v=1234&pairingCode=xyz&version=3&autohide=1"};
- final String[] badUrls = {"youtube.com.foo.com/tv?pairingCode=xyz",
- "youtube.com.foo.com?pairingCode=xyz",
- "youtube.com/watch?v=tEsT&version=3&autohide=1&pairingCode=",
- "youtube.com&pairingCode=xyz",
- "youtube.com/watch?v=tEsT?version=3&pairingCode=&autohide=1"};
+ final String[] goodUrls = {mobileUrl, "http://youtube.com?pairingCode=xyz",
+ "http://youtube.com/tv?pairingCode=xyz",
+ "http://youtube.com/watch?v=1234&version=3&autohide=1&pairingCode=xyz",
+ "http://youtube.com/watch?v=1234&pairingCode=xyz&version=3&autohide=1"};
+ final String[] badUrls = {"http://youtube.com.foo.com/tv?pairingCode=xyz",
+ "http://youtube.com.foo.com?pairingCode=xyz", "http://youtube.com&pairingCode=xyz",
+ "http://youtube.com/watch?v=1234#pairingCode=xyz"};
// Make sure we don't override when faced with valid pairing code URLs.
for (String url : goodUrls) {
- // http://crbug/386600 - it makes no sense to switch activities for pairing code URLs.
- checkUrl(url).withIsRedirect(true).expecting(
- OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE);
-
- checkUrl(url)
- .withPageTransition(transitionTypeIncomingIntent)
- .withIsRedirect(true)
- .expecting(OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE);
+ Assert.assertTrue(mUrlHandler.isYoutubePairingCode(new GURL(url)));
}
-
- // The pairing code URL regex shouldn't cause NO_OVERRIDE on invalid URLs.
for (String url : badUrls) {
- checkUrl(url).withIsRedirect(true).expecting(
- OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT,
- START_OTHER_ACTIVITY);
-
- checkUrl(url)
- .withPageTransition(transitionTypeIncomingIntent)
- .withIsRedirect(true)
- .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT,
- START_OTHER_ACTIVITY);
+ Assert.assertFalse(mUrlHandler.isYoutubePairingCode(new GURL(url)));
}
+ // http://crbug/386600 - it makes no sense to switch activities for pairing code URLs.
+ checkUrl(mobileUrl).withIsRedirect(true).expecting(
+ OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE);
+ checkUrl(mobileUrl)
+ .withPageTransition(transitionTypeIncomingIntent)
+ .withIsRedirect(true)
+ .expecting(OverrideUrlLoadingResultType.NO_OVERRIDE, IGNORE);
}
@Test
@@ -742,11 +758,13 @@ public class ExternalNavigationHandlerTest {
@Test
@SmallTest
public void testCCTIntentUriDoesNotFireCCTAndLoadInChrome_InIncognito() throws Exception {
+ mUrlHandler.mResolveInfoContainsSelf = true;
mDelegate.setCanLoadUrlInTab(false);
checkUrl(INTENT_URL_FOR_CHROME_CUSTOM_TABS)
.withIsIncognito(true)
- .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT, IGNORE);
- Assert.assertTrue(mDelegate.handleIncognitoIntentTargetingSelfCalled);
+ .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+ Assert.assertNull(mDelegate.startActivityIntent);
+ Assert.assertEquals("http://example.com/", mUrlHandler.mNewUrlAfterClobbering);
}
@Test
@@ -756,17 +774,26 @@ public class ExternalNavigationHandlerTest {
.withIsIncognito(false)
.expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT,
START_OTHER_ACTIVITY);
- Assert.assertFalse(mDelegate.handleIncognitoIntentTargetingSelfCalled);
+ Assert.assertNotNull(mDelegate.startActivityIntent);
}
@Test
@SmallTest
public void testChromeIntentUriDoesNotFireAndLoadsInChrome_InIncognito() throws Exception {
+ mUrlHandler.mResolveInfoContainsSelf = true;
mDelegate.setCanLoadUrlInTab(false);
checkUrl(INTENT_URL_FOR_CHROME)
.withIsIncognito(true)
- .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT, IGNORE);
- Assert.assertTrue(mDelegate.handleIncognitoIntentTargetingSelfCalled);
+ .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+ Assert.assertNull(mDelegate.startActivityIntent);
+ Assert.assertEquals("http://example.com/", mUrlHandler.mNewUrlAfterClobbering);
+
+ mUrlHandler.mResolveInfoContainsSelf = false;
+ checkUrl(INTENT_URL_FOR_CHROME)
+ .withIsIncognito(true)
+ .expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB, IGNORE);
+ Assert.assertNull(mDelegate.startActivityIntent);
+ Assert.assertEquals(YOUTUBE_URL, mUrlHandler.mNewUrlAfterClobbering);
}
@Test
@@ -867,14 +894,14 @@ public class ExternalNavigationHandlerTest {
public void testFallbackUrl_IntentResolutionSucceedsInIncognito() {
// IMDB app is installed.
mDelegate.add(new IntentActivity("imdb:", INTENT_APP_PACKAGE_NAME));
+ mUrlHandler.mCanShowIncognitoDialog = true;
// Expect that the user is prompted to leave incognito mode.
checkUrl(INTENT_URL_WITH_FALLBACK_URL)
.withIsIncognito(true)
.withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
.expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
- OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH,
- START_INCOGNITO | START_OTHER_ACTIVITY);
+ OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO);
Assert.assertNull(mUrlHandler.mNewUrlAfterClobbering);
Assert.assertNull(mUrlHandler.mReferrerUrlForClobbering);
@@ -959,6 +986,114 @@ public class ExternalNavigationHandlerTest {
}
@Test
+ @MediumTest
+ public void testFallbackUrl_FallbackToMarketApp_Incognito() {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_VIEW);
+ filter.addCategory(Intent.CATEGORY_BROWSABLE);
+ filter.addDataScheme("market");
+ ActivityMonitor monitor = InstrumentationRegistry.getInstrumentation().addMonitor(
+ filter, new Instrumentation.ActivityResult(Activity.RESULT_OK, null), true);
+ Intent dummyIntent = new Intent(mApplicationContextToRestore, DummyUiActivity.class);
+ dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Activity activity =
+ InstrumentationRegistry.getInstrumentation().startActivitySync(dummyIntent);
+ mDelegate.setContext(activity);
+ mDelegate.setCanLoadUrlInTab(true);
+ try {
+ mDelegate.setCanResolveActivityForExternalSchemes(false);
+ String playUrl = "https://play.google.com/store/apps/details?id=com.imdb.mobile"
+ + "&referrer=mypage";
+
+ String intent = "intent:///name/nm0000158#Intent;scheme=imdb;package=com.imdb.mobile;"
+ + "S." + ExternalNavigationHandler.EXTRA_BROWSER_FALLBACK_URL + "="
+ + Uri.encode(playUrl, null) + ";end;";
+
+ mUrlHandler.mCanShowIncognitoDialog = true;
+ ThreadUtils.runOnUiThreadBlocking(() -> {
+ checkUrl(intent).withIsIncognito(true).withHasUserGesture(true).expecting(
+ OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
+ OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO);
+ Assert.assertNull(mDelegate.startActivityIntent);
+ Assert.assertNull(mUrlHandler.mNewUrlAfterClobbering);
+ mUrlHandler.mShownIncognitoAlertDialog.cancel();
+ });
+ // Cancel callback is posted, so continue after posting to the task queue.
+ ThreadUtils.runOnUiThreadBlocking(() -> {
+ Assert.assertEquals(playUrl, mUrlHandler.mNewUrlAfterClobbering);
+ mUrlHandler.mNewUrlAfterClobbering = null;
+
+ checkUrl(intent).withIsIncognito(true).withHasUserGesture(true).expecting(
+ OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
+ OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO);
+ Assert.assertNull(mDelegate.startActivityIntent);
+ mUrlHandler.mShownIncognitoAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
+ .performClick();
+ });
+ // Click callback is posted, so continue after posting to the task queue.
+ ThreadUtils.runOnUiThreadBlocking(() -> {
+ Assert.assertNull(mUrlHandler.mNewUrlAfterClobbering);
+ Assert.assertEquals(1, monitor.getHits());
+ Assert.assertEquals("market://details?id=com.imdb.mobile&referrer=mypage",
+ mDelegate.startActivityIntent.getDataString());
+ });
+ } finally {
+ if (mUrlHandler.mShownIncognitoAlertDialog != null) {
+ mUrlHandler.mShownIncognitoAlertDialog.cancel();
+ }
+ activity.finish();
+ InstrumentationRegistry.getInstrumentation().removeMonitor(monitor);
+ }
+ }
+
+ @Test
+ @MediumTest
+ public void testFallbackUrl_ChromeCanHandle_Incognito() {
+ mDelegate.add(new IntentActivity("https", "package"));
+ Intent dummyIntent = new Intent(mApplicationContextToRestore, DummyUiActivity.class);
+ dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Activity activity =
+ InstrumentationRegistry.getInstrumentation().startActivitySync(dummyIntent);
+ mDelegate.setContext(activity);
+ mDelegate.setCanLoadUrlInTab(true);
+ try {
+ String intent = "intent://example.com#Intent;scheme=https;"
+ + "S.browser_fallback_url=http%3A%2F%2Fgoogle.com;end";
+
+ mUrlHandler.mResolveInfoContainsSelf = true;
+ mUrlHandler.mCanShowIncognitoDialog = true;
+ ThreadUtils.runOnUiThreadBlocking(() -> {
+ checkUrl(intent).withIsIncognito(true).withHasUserGesture(true).expecting(
+ OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
+ OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO);
+ Assert.assertNull(mDelegate.startActivityIntent);
+ Assert.assertNull(mUrlHandler.mNewUrlAfterClobbering);
+ mUrlHandler.mShownIncognitoAlertDialog.cancel();
+ });
+ // Cancel callback is posted, so continue after posting to the task queue.
+ ThreadUtils.runOnUiThreadBlocking(() -> {
+ Assert.assertEquals("https://example.com/", mUrlHandler.mNewUrlAfterClobbering);
+ mUrlHandler.mNewUrlAfterClobbering = null;
+ mUrlHandler.mResolveInfoContainsSelf = false;
+
+ checkUrl(intent).withIsIncognito(true).withHasUserGesture(true).expecting(
+ OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
+ OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO);
+ Assert.assertNull(mDelegate.startActivityIntent);
+ mUrlHandler.mShownIncognitoAlertDialog.cancel();
+ });
+ // Click callback is posted, so continue after posting to the task queue.
+ ThreadUtils.runOnUiThreadBlocking(() -> {
+ Assert.assertEquals("http://google.com/", mUrlHandler.mNewUrlAfterClobbering);
+ });
+ } finally {
+ if (mUrlHandler.mShownIncognitoAlertDialog != null) {
+ mUrlHandler.mShownIncognitoAlertDialog.cancel();
+ }
+ activity.finish();
+ }
+ }
+
+ @Test
@SmallTest
public void testFallbackUrl_SubframeFallbackToMarketApp() {
mDelegate.setCanResolveActivityForExternalSchemes(false);
@@ -1095,14 +1230,14 @@ public class ExternalNavigationHandlerTest {
public void testFallbackUrl_IgnoreJavascriptFallbackUrl() {
// IMDB app isn't installed.
mDelegate.setCanResolveActivityForExternalSchemes(false);
+ mUrlHandler.mCanShowIncognitoDialog = true;
// Will be redirected to market since package is given.
checkUrl(INTENT_URL_WITH_JAVASCRIPT_FALLBACK_URL)
.withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
.withIsIncognito(true)
.expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
- OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH,
- START_INCOGNITO | START_OTHER_ACTIVITY);
+ OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO);
Intent invokedIntent = mUrlHandler.mStartActivityInIncognitoIntent;
Assert.assertTrue(invokedIntent.getData().toString().startsWith("market://"));
@@ -1246,7 +1381,7 @@ public class ExternalNavigationHandlerTest {
mUrlHandler = new ExternalNavigationHandlerForTesting(mDelegate);
ExternalNavigationParams params =
- new ExternalNavigationParams.Builder(YOUTUBE_MOBILE_URL, false)
+ new ExternalNavigationParams.Builder(new GURL(YOUTUBE_MOBILE_URL), false)
.setOpenInNewTab(true)
.build();
OverrideUrlLoadingResult result = mUrlHandler.shouldOverrideUrlLoading(params);
@@ -1346,7 +1481,7 @@ public class ExternalNavigationHandlerTest {
@Test
@SmallTest
public void testUsafeIntentFlagsFiltered() {
- checkUrl("intent://#Intent;package=com.test.package;launchFlags=0x7FFFFFFF;end;")
+ checkUrl("intent:#Intent;package=com.test.package;launchFlags=0x7FFFFFFF;end;")
.expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT,
START_OTHER_ACTIVITY);
Assert.assertEquals(ExternalNavigationHandler.ALLOWED_INTENT_FLAGS,
@@ -1363,7 +1498,7 @@ public class ExternalNavigationHandlerTest {
@Test
@SmallTest
public void testIntentWithNoSchemeLaunched() {
- checkUrl("intent://#Intent;package=com.test.package;end;")
+ checkUrl("intent:#Intent;package=com.test.package;end;")
.expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT,
START_OTHER_ACTIVITY);
}
@@ -1382,6 +1517,8 @@ public class ExternalNavigationHandlerTest {
checkUrl("intent://#Intent;package=com.test.package;scheme=w3irD;end;")
.expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT,
START_OTHER_ACTIVITY);
+ // Schemes on Android are case-sensitive, so ensure the scheme is passed through as-is.
+ Assert.assertEquals("w3irD", mDelegate.startActivityIntent.getScheme());
}
@Test
@@ -1408,8 +1545,8 @@ public class ExternalNavigationHandlerTest {
public void testReferrerExtra() {
mDelegate.add(new IntentActivity(YOUTUBE_URL, YOUTUBE_PACKAGE_NAME));
- String referrer = "http://www.google.com";
- checkUrl("http://youtube.com:90/foo/bar")
+ String referrer = "http://www.google.com/";
+ checkUrl(YOUTUBE_URL + ":90/foo/bar")
.withReferrer(referrer)
.withPageTransition(PageTransition.FORM_SUBMIT)
.withIsRedirect(true)
@@ -1631,11 +1768,11 @@ public class ExternalNavigationHandlerTest {
@Test
@SmallTest
public void testMarketIntent_ShowDialogIncognitoMarketInstalled() {
+ mUrlHandler.mCanShowIncognitoDialog = true;
checkUrl("market://1234")
.withIsIncognito(true)
.expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
- OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH,
- START_INCOGNITO | START_OTHER_ACTIVITY);
+ OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO);
Assert.assertTrue(mUrlHandler.mStartIncognitoIntentCalled);
}
@@ -1672,13 +1809,13 @@ public class ExternalNavigationHandlerTest {
// IMDB app is installed.
mDelegate.add(new IntentActivity("imdb:", INTENT_APP_PACKAGE_NAME));
+ mUrlHandler.mCanShowIncognitoDialog = true;
checkUrl(INTENT_URL_WITH_FALLBACK_URL)
.withReferrer(SEARCH_RESULT_URL_FOR_TOM_HANKS)
.withHasUserGesture(true)
.withIsIncognito(true)
.expecting(OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION,
- OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH,
- START_INCOGNITO | START_OTHER_ACTIVITY);
+ OverrideUrlLoadingAsyncActionType.UI_GATING_INTENT_LAUNCH, START_INCOGNITO);
Assert.assertTrue(mDelegate.maybeSetRequestMetadataCalled);
Assert.assertTrue(mUrlHandler.mStartIncognitoIntentCalled);
}
@@ -1800,15 +1937,16 @@ public class ExternalNavigationHandlerTest {
@SmallTest
public void testIsDownload_noSystemDownloadManager() {
Assert.assertTrue("pdf should be a download, no viewer in Android Chrome",
- mUrlHandler.isPdfDownload("http://somesampeleurldne.com/file.pdf"));
+ mUrlHandler.isPdfDownload(new GURL("http://somesampeleurldne.com/file.pdf")));
Assert.assertFalse("URL is not a file, but web page",
- mUrlHandler.isPdfDownload("http://somesampleurldne.com/index.html"));
+ mUrlHandler.isPdfDownload(new GURL("http://somesampleurldne.com/index.html")));
Assert.assertFalse("URL is not a file url",
- mUrlHandler.isPdfDownload("http://somesampeleurldne.com/not.a.real.extension"));
+ mUrlHandler.isPdfDownload(
+ new GURL("http://somesampeleurldne.com/not.a.real.extension")));
Assert.assertFalse("URL is an image, can be viewed in Chrome",
- mUrlHandler.isPdfDownload("http://somesampleurldne.com/image.jpg"));
+ mUrlHandler.isPdfDownload(new GURL("http://somesampleurldne.com/image.jpg")));
Assert.assertFalse("URL is a text file can be viewed in Chrome",
- mUrlHandler.isPdfDownload("http://somesampleurldne.com/copy.txt"));
+ mUrlHandler.isPdfDownload(new GURL("http://somesampleurldne.com/copy.txt")));
}
@Test
@@ -2021,7 +2159,7 @@ public class ExternalNavigationHandlerTest {
}
}
- private static class ExternalNavigationHandlerForTesting extends ExternalNavigationHandler {
+ private class ExternalNavigationHandlerForTesting extends ExternalNavigationHandler {
public String defaultSmsPackageName;
public GURL mLastCommittedUrl;
public boolean mIsSerpReferrer;
@@ -2032,6 +2170,9 @@ public class ExternalNavigationHandlerTest {
public boolean mStartFileIntentCalled;
public Intent mStartActivityInIncognitoIntent;
public boolean mStartIncognitoIntentCalled;
+ public boolean mCanShowIncognitoDialog;
+ public AlertDialog mShownIncognitoAlertDialog;
+ public boolean mResolveInfoContainsSelf;
public ExternalNavigationHandlerForTesting(ExternalNavigationDelegate delegate) {
super(delegate);
@@ -2049,11 +2190,19 @@ public class ExternalNavigationHandlerTest {
}
@Override
- protected boolean startIncognitoIntentInternal(Intent intent, String referrerUrl,
- String fallbackUrl, boolean needsToCloseTab, boolean proxy) {
+ protected boolean canLaunchIncognitoIntent(Intent intent, Context context) {
mStartActivityInIncognitoIntent = intent;
mStartIncognitoIntentCalled = true;
- return true;
+ return mCanShowIncognitoDialog;
+ }
+
+ @Override
+ protected AlertDialog showLeavingIncognitoAlert(Context context,
+ ExternalNavigationParams params, Intent intent, GURL fallbackUrl, boolean proxy) {
+ if (context == null) return mAlertDialog;
+ mShownIncognitoAlertDialog =
+ super.showLeavingIncognitoAlert(context, params, intent, fallbackUrl, proxy);
+ return mShownIncognitoAlertDialog;
}
@Override
@@ -2077,54 +2226,68 @@ public class ExternalNavigationHandlerTest {
}
@Override
- protected boolean shouldRequestFileAccess(String url) {
+ protected boolean shouldRequestFileAccess(GURL url) {
return mShouldRequestFileAccess;
}
@Override
- protected void startFileIntent(Intent intent, String referrerUrl, boolean needsToCloseTab) {
+ protected void startFileIntent(ExternalNavigationParams params) {
mStartFileIntentCalled = true;
}
@Override
- protected OverrideUrlLoadingResult clobberCurrentTab(String url, String referrerUrl) {
- mNewUrlAfterClobbering = url;
- mReferrerUrlForClobbering = referrerUrl;
+ protected OverrideUrlLoadingResult clobberCurrentTab(GURL url, GURL referrerUrl) {
+ mNewUrlAfterClobbering = url.getSpec();
+ mReferrerUrlForClobbering = referrerUrl.getSpec();
return OverrideUrlLoadingResult.forClobberingTab();
}
+
+ @Override
+ public boolean isYoutubePairingCode(GURL url) {
+ return super.isYoutubePairingCode(url);
+ }
+
+ @Override
+ protected boolean resolveInfoContainsSelf(List<ResolveInfo> resolveInfos) {
+ return mResolveInfoContainsSelf;
+ }
};
private static class TestExternalNavigationDelegate implements ExternalNavigationDelegate {
public List<ResolveInfo> queryIntentActivities(Intent intent) {
List<ResolveInfo> list = new ArrayList<>();
String dataString = intent.getDataString();
- if (dataString == null) return list;
- if (dataString.startsWith("http://") || dataString.startsWith("https://")) {
- list.add(newResolveInfo("chrome"));
- }
- for (IntentActivity intentActivity : mIntentActivities) {
- if (dataString.startsWith(intentActivity.urlPrefix())) {
- list.add(newSpecializedResolveInfo(
- intentActivity.packageName(), intentActivity));
+ if (intent.getScheme() != null) {
+ if (dataString.startsWith("http://") || dataString.startsWith("https://")) {
+ list.add(newResolveInfo("chrome"));
}
- }
- if (!list.isEmpty()) return list;
+ for (IntentActivity intentActivity : mIntentActivities) {
+ if (dataString.startsWith(intentActivity.urlPrefix())) {
+ list.add(newSpecializedResolveInfo(
+ intentActivity.packageName(), intentActivity));
+ }
+ }
+ if (!list.isEmpty()) return list;
- String schemeString = intent.getData().getScheme();
- boolean isMarketScheme = schemeString != null && schemeString.startsWith("market");
- if (mCanResolveActivityForMarket && isMarketScheme) {
- list.add(newResolveInfo("market"));
- return list;
- }
- if (mCanResolveActivityForExternalSchemes && !isMarketScheme) {
- list.add(newResolveInfo(intent.getData().getScheme()));
+ String schemeString = intent.getScheme();
+ boolean isMarketScheme = schemeString != null && schemeString.startsWith("market");
+ if (mCanResolveActivityForMarket && isMarketScheme) {
+ list.add(newResolveInfo("market"));
+ return list;
+ }
+ if (mCanResolveActivityForExternalSchemes && !isMarketScheme) {
+ list.add(newResolveInfo(intent.getData().getScheme()));
+ }
+ } else if (mCanResolveActivityForExternalSchemes) {
+ // Scheme-less intents (eg. Action-based intents like opening Settings).
+ list.add(newResolveInfo("package"));
}
return list;
}
@Override
public Context getContext() {
- return null;
+ return mContext;
}
@Override
@@ -2142,7 +2305,7 @@ public class ExternalNavigationHandlerTest {
}
@Override
- public boolean shouldDisableExternalIntentRequestsForUrl(String url) {
+ public boolean shouldDisableExternalIntentRequestsForUrl(GURL url) {
return mShouldDisableExternalIntentRequests;
}
@@ -2170,24 +2333,8 @@ public class ExternalNavigationHandlerTest {
}
@Override
- public OverrideUrlLoadingResult handleIncognitoIntentTargetingSelf(
- Intent intent, String referrerUrl, String fallbackUrl) {
- handleIncognitoIntentTargetingSelfCalled = true;
- if (mCanLoadUrlInTab) return OverrideUrlLoadingResult.forClobberingTab();
- return OverrideUrlLoadingResult.forExternalIntent();
- }
-
- @Override
- public boolean supportsCreatingNewTabs() {
- return false;
- }
-
- @Override
- public void loadUrlInNewTab(final String url, final boolean launchIncognito) {}
-
- @Override
public boolean canLoadUrlInCurrentTab() {
- return false;
+ return mCanLoadUrlInTab;
}
@Override
@@ -2205,10 +2352,10 @@ public class ExternalNavigationHandlerTest {
public void maybeSetWindowId(Intent intent) {}
@Override
- public void maybeSetPendingReferrer(Intent intent, String referrerUrl) {
+ public void maybeSetPendingReferrer(Intent intent, GURL referrerUrl) {
// This is used in a test to check that ExternalNavigationHandler correctly passes
// this data to the delegate when the referrer URL is non-null.
- intent.putExtra(Intent.EXTRA_REFERRER, Uri.parse(referrerUrl));
+ intent.putExtra(Intent.EXTRA_REFERRER, Uri.parse(referrerUrl.getSpec()));
}
@Override
@@ -2235,8 +2382,8 @@ public class ExternalNavigationHandlerTest {
}
@Override
- public boolean maybeLaunchInstantApp(String url, String referrerUrl,
- boolean isIncomingRedirect, boolean isSerpReferrer) {
+ public boolean maybeLaunchInstantApp(
+ GURL url, GURL referrerUrl, boolean isIncomingRedirect, boolean isSerpReferrer) {
return mCanHandleWithInstantApp;
}
@@ -2284,17 +2431,20 @@ public class ExternalNavigationHandlerTest {
@Override
public boolean handleWithAutofillAssistant(ExternalNavigationParams params,
- Intent targetIntent, String browserFallbackUrl, boolean isGoogleReferrer) {
+ Intent targetIntent, GURL browserFallbackUrl, boolean isGoogleReferrer) {
return mHandleWithAutofillAssistant;
}
public void reset() {
startActivityIntent = null;
startIncognitoIntentCalled = false;
- handleIncognitoIntentTargetingSelfCalled = false;
mCalledWithProxy = false;
}
+ public void setContext(Context context) {
+ mContext = context;
+ }
+
public void add(IntentActivity handler) {
mIntentActivities.add(handler);
}
@@ -2354,7 +2504,6 @@ public class ExternalNavigationHandlerTest {
public Intent startActivityIntent;
public boolean startIncognitoIntentCalled;
- public boolean handleIncognitoIntentTargetingSelfCalled;
public boolean maybeSetRequestMetadataCalled;
private String mReferrerWebappPackageName;
@@ -2372,6 +2521,7 @@ public class ExternalNavigationHandlerTest {
private boolean mIsIntentToAutofillAssistant;
private @IntentToAutofillAllowingAppResult int mAutofillAssistantAllowAppOverrideResult;
private boolean mCanLoadUrlInTab;
+ private Context mContext;
}
private void checkIntentSanity(Intent intent, String name) {
@@ -2485,7 +2635,8 @@ public class ExternalNavigationHandlerTest {
ExternalNavigationParams params =
new ExternalNavigationParams
- .Builder(mUrl, mIsIncognito, mReferrerUrl, mPageTransition, mIsRedirect)
+ .Builder(new GURL(mUrl), mIsIncognito, new GURL(mReferrerUrl),
+ mPageTransition, mIsRedirect)
.setApplicationMustBeInForeground(mChromeAppInForegroundRequired)
.setRedirectHandler(mRedirectHandler)
.setIsBackgroundTabNavigation(mIsBackgroundTabNavigation)
@@ -2502,9 +2653,7 @@ public class ExternalNavigationHandlerTest {
// Incognito intent launching gets caught by the test URL handler, whereas non-incgonito
// intent launching gets caught by the test delegate.
- Intent startActivityIntent = expectStartIncognito
- ? mUrlHandler.mStartActivityInIncognitoIntent
- : mDelegate.startActivityIntent;
+ Intent startActivityIntent = mDelegate.startActivityIntent;
if (startActivityIntent != null) {
startActivityCalled = true;
diff --git a/chromium/components/favicon/android/large_icon_bridge.h b/chromium/components/favicon/android/large_icon_bridge.h
index 21422f4e8e7..190d2583772 100644
--- a/chromium/components/favicon/android/large_icon_bridge.h
+++ b/chromium/components/favicon/android/large_icon_bridge.h
@@ -7,8 +7,6 @@
#include <jni.h>
-#include <memory>
-
#include "base/android/scoped_java_ref.h"
#include "base/task/cancelable_task_tracker.h"
diff --git a/chromium/components/favicon/content/content_favicon_driver.cc b/chromium/components/favicon/content/content_favicon_driver.cc
index 67336386920..aafe1680ab6 100644
--- a/chromium/components/favicon/content/content_favicon_driver.cc
+++ b/chromium/components/favicon/content/content_favicon_driver.cc
@@ -47,14 +47,28 @@ GURL ContentFaviconDriver::GetActiveURL() {
return entry ? entry->GetURL() : GURL();
}
+GURL ContentFaviconDriver::GetManifestURL(content::RenderFrameHost* rfh) {
+ DocumentManifestData* document_data =
+ DocumentManifestData::GetOrCreateForCurrentDocument(rfh);
+ return document_data->has_manifest_url ? rfh->ManifestURL() : GURL();
+}
+
ContentFaviconDriver::ContentFaviconDriver(content::WebContents* web_contents,
CoreFaviconService* favicon_service)
: content::WebContentsObserver(web_contents),
- FaviconDriverImpl(favicon_service),
- document_on_load_completed_(false) {}
+ FaviconDriverImpl(favicon_service) {}
ContentFaviconDriver::~ContentFaviconDriver() = default;
+ContentFaviconDriver::DocumentManifestData::DocumentManifestData(
+ content::RenderFrameHost* render_frame_host) {}
+ContentFaviconDriver::DocumentManifestData::~DocumentManifestData() = default;
+
+ContentFaviconDriver::NavigationManifestData::NavigationManifestData(
+ content::NavigationHandle& navigation_handle) {}
+ContentFaviconDriver::NavigationManifestData::~NavigationManifestData() =
+ default;
+
void ContentFaviconDriver::OnDidDownloadManifest(
ManifestDownloadCallback callback,
const GURL& manifest_url,
@@ -143,63 +157,58 @@ void ContentFaviconDriver::DidUpdateFaviconURL(
// occur when loading an initially blank page.
content::NavigationEntry* entry =
web_contents()->GetController().GetLastCommittedEntry();
+
if (!entry)
return;
- // We update |favicon_urls_| even if the list is believed to be partial
- // (checked below), because callers of our getter favicon_urls() expect so.
- std::vector<blink::mojom::FaviconURL> favicon_urls;
- for (const auto& candidate : candidates)
- favicon_urls.push_back(*candidate);
- favicon_urls_ = favicon_urls;
-
- if (!document_on_load_completed_)
+ if (!rfh->IsDocumentOnLoadCompletedInMainFrame())
return;
- OnUpdateCandidates(entry->GetURL(),
- FaviconURLsFromContentFaviconURLs(favicon_urls_.value_or(
- std::vector<blink::mojom::FaviconURL>())),
- manifest_url_);
+ OnUpdateCandidates(rfh->GetLastCommittedURL(),
+ FaviconURLsFromContentFaviconURLs(candidates),
+ GetManifestURL(rfh));
}
void ContentFaviconDriver::DidUpdateWebManifestURL(
content::RenderFrameHost* rfh,
- const base::Optional<GURL>& manifest_url) {
+ const absl::optional<GURL>& manifest_url) {
// Ignore the update if there is no last committed navigation entry. This can
// occur when loading an initially blank page.
content::NavigationEntry* entry =
web_contents()->GetController().GetLastCommittedEntry();
- if (!entry || !document_on_load_completed_)
+ if (!entry || !rfh->IsDocumentOnLoadCompletedInMainFrame())
return;
- manifest_url_ = manifest_url.value_or(GURL());
+ DocumentManifestData* document_data =
+ DocumentManifestData::GetOrCreateForCurrentDocument(rfh);
+ document_data->has_manifest_url = true;
// On regular page loads, DidUpdateManifestURL() is guaranteed to be called
// before DidUpdateFaviconURL(). However, a page can update the favicons via
// javascript.
- if (favicon_urls_.has_value()) {
- OnUpdateCandidates(entry->GetURL(),
- FaviconURLsFromContentFaviconURLs(*favicon_urls_),
- manifest_url_);
+ if (!rfh->FaviconURLs().empty()) {
+ OnUpdateCandidates(rfh->GetLastCommittedURL(),
+ FaviconURLsFromContentFaviconURLs(rfh->FaviconURLs()),
+ GetManifestURL(rfh));
}
}
void ContentFaviconDriver::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
- if (!navigation_handle->IsInMainFrame())
+ if (!navigation_handle->IsInPrimaryMainFrame())
return;
- favicon_urls_.reset();
-
- if (!navigation_handle->IsSameDocument()) {
- document_on_load_completed_ = false;
- manifest_url_ = GURL();
- }
-
content::ReloadType reload_type = navigation_handle->GetReloadType();
if (reload_type == content::ReloadType::NONE || IsOffTheRecord())
return;
+ if (!navigation_handle->IsSameDocument()) {
+ NavigationManifestData* navigation_data =
+ NavigationManifestData::GetOrCreateForNavigationHandle(
+ *navigation_handle);
+ navigation_data->has_manifest_url = false;
+ }
+
bypass_cache_page_url_ = navigation_handle->GetURL();
SetFaviconOutOfDateForPage(
navigation_handle->GetURL(),
@@ -208,12 +217,20 @@ void ContentFaviconDriver::DidStartNavigation(
void ContentFaviconDriver::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
- if (!navigation_handle->IsInMainFrame() ||
- !navigation_handle->HasCommitted() ||
- navigation_handle->IsErrorPage()) {
+ if (!navigation_handle->IsInPrimaryMainFrame() ||
+ !navigation_handle->HasCommitted() || navigation_handle->IsErrorPage()) {
return;
}
+ // Transfer in-flight navigation data to the document user data.
+ NavigationManifestData* navigation_data =
+ NavigationManifestData::GetOrCreateForNavigationHandle(
+ *navigation_handle);
+ DocumentManifestData* document_data =
+ DocumentManifestData::GetOrCreateForCurrentDocument(
+ navigation_handle->GetRenderFrameHost());
+ document_data->has_manifest_url = navigation_data->has_manifest_url;
+
// Wait till the user navigates to a new URL to start checking the cache
// again. The cache may be ignored for non-reload navigations (e.g.
// history.replace() in-page navigation). This is allowed to increase the
@@ -229,11 +246,10 @@ void ContentFaviconDriver::DidFinishNavigation(
FetchFavicon(url, navigation_handle->IsSameDocument());
}
-void ContentFaviconDriver::DocumentOnLoadCompletedInMainFrame(
- content::RenderFrameHost* render_frame_host) {
- document_on_load_completed_ = true;
-}
-
+NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(
+ ContentFaviconDriver::NavigationManifestData)
+RENDER_DOCUMENT_HOST_USER_DATA_KEY_IMPL(
+ ContentFaviconDriver::DocumentManifestData)
WEB_CONTENTS_USER_DATA_KEY_IMPL(ContentFaviconDriver)
} // namespace favicon
diff --git a/chromium/components/favicon/content/content_favicon_driver.h b/chromium/components/favicon/content/content_favicon_driver.h
index 68903eef52b..6ba904decb0 100644
--- a/chromium/components/favicon/content/content_favicon_driver.h
+++ b/chromium/components/favicon/content/content_favicon_driver.h
@@ -8,11 +8,13 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/favicon/core/favicon_driver_impl.h"
+#include "content/public/browser/navigation_handle_user_data.h"
#include "content/public/browser/reload_type.h"
+#include "content/public/browser/render_document_host_user_data.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h"
#include "url/gurl.h"
@@ -30,17 +32,13 @@ class ContentFaviconDriver
public:
~ContentFaviconDriver() override;
- // Returns the current tab's favicon URLs. If this is empty,
- // DidUpdateFaviconURL has not yet been called for the current navigation.
- std::vector<blink::mojom::FaviconURL> favicon_urls() const {
- return favicon_urls_.value_or(std::vector<blink::mojom::FaviconURL>());
- }
-
// FaviconDriver implementation.
gfx::Image GetFavicon() const override;
bool FaviconIsValid() const override;
GURL GetActiveURL() override;
+ GURL GetManifestURL(content::RenderFrameHost* rfh);
+
protected:
ContentFaviconDriver(content::WebContents* web_contents,
CoreFaviconService* favicon_service);
@@ -48,6 +46,25 @@ class ContentFaviconDriver
private:
friend class content::WebContentsUserData<ContentFaviconDriver>;
+ // TODO(crbug.com/1205018): these two classes are current used to ensure that
+ // we disregard manifest URL updates that arrive prior to onload firing.
+ struct DocumentManifestData
+ : public content::RenderDocumentHostUserData<DocumentManifestData> {
+ explicit DocumentManifestData(content::RenderFrameHost* rfh);
+ ~DocumentManifestData() override;
+ RENDER_DOCUMENT_HOST_USER_DATA_KEY_DECL();
+ bool has_manifest_url = false;
+ };
+
+ struct NavigationManifestData
+ : public content::NavigationHandleUserData<NavigationManifestData> {
+ explicit NavigationManifestData(
+ content::NavigationHandle& navigation_handle);
+ ~NavigationManifestData() override;
+ NAVIGATION_HANDLE_USER_DATA_KEY_DECL();
+ bool has_manifest_url = false;
+ };
+
// Callback when a manifest is downloaded.
void OnDidDownloadManifest(ManifestDownloadCallback callback,
const GURL& manifest_url,
@@ -75,20 +92,13 @@ class ContentFaviconDriver
const std::vector<blink::mojom::FaviconURLPtr>& candidates) override;
void DidUpdateWebManifestURL(
content::RenderFrameHost* rfh,
- const base::Optional<GURL>& manifest_url) override;
+ const absl::optional<GURL>& manifest_url) override;
void DidStartNavigation(
content::NavigationHandle* navigation_handle) override;
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
- void DocumentOnLoadCompletedInMainFrame(
- content::RenderFrameHost* render_frame_host) override;
- bool document_on_load_completed_;
GURL bypass_cache_page_url_;
- // nullopt until the actual list is reported via DidUpdateFaviconURL().
- base::Optional<std::vector<blink::mojom::FaviconURL>> favicon_urls_;
- // Web Manifest URL or empty URL if none.
- GURL manifest_url_;
WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/chromium/components/favicon/content/content_favicon_driver_unittest.cc b/chromium/components/favicon/content/content_favicon_driver_unittest.cc
index a7ae1b51611..ae8cc6b6ef1 100644
--- a/chromium/components/favicon/content/content_favicon_driver_unittest.cc
+++ b/chromium/components/favicon/content/content_favicon_driver_unittest.cc
@@ -28,9 +28,9 @@
namespace favicon {
namespace {
+using testing::_;
using testing::Return;
using testing::SizeIs;
-using testing::_;
void TestFetchFaviconForPage(
content::WebContents* web_contents,
@@ -50,6 +50,7 @@ class ContentFaviconDriverTest : public content::RenderViewHostTestHarness {
const std::vector<SkBitmap> kEmptyIcons;
const GURL kPageURL = GURL("http://www.google.com/");
const GURL kIconURL = GURL("http://www.google.com/favicon.ico");
+ const GURL kFakeManifestURL = GURL("http://www.google.com/manifest.json");
ContentFaviconDriverTest() {
ON_CALL(favicon_service_, UpdateFaviconMappingsAndFetch(_, _, _, _, _, _))
@@ -103,6 +104,48 @@ TEST_F(ContentFaviconDriverTest, ShouldCauseImageDownload) {
kIconURL, 200, kEmptyIcons, kEmptyIconSizes));
}
+// Ensures that we do not consider a manifest URL if it arrives before the
+// onload handler has fired.
+// TODO(crbug.com/1205018): This may not necessarily the desired behavior, but
+// this test will prevent unintentional behavioral changes until the issue is
+// resolved.
+TEST_F(ContentFaviconDriverTest, IgnoreManifestURLBeforeOnLoad) {
+ ContentFaviconDriver* favicon_driver =
+ ContentFaviconDriver::FromWebContents(web_contents());
+ auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
+ kPageURL, web_contents());
+ navigation->SetKeepLoading(true);
+ navigation->Commit();
+ absl::optional<GURL> manifest_url = kFakeManifestURL;
+ auto* rfh_tester =
+ content::RenderFrameHostTester::For(web_contents()->GetMainFrame());
+ rfh_tester->SimulateManifestURLUpdate(manifest_url);
+ static_cast<content::WebContentsObserver*>(favicon_driver)
+ ->DidUpdateWebManifestURL(web_contents()->GetMainFrame(), manifest_url);
+ EXPECT_EQ(GURL(),
+ favicon_driver->GetManifestURL(web_contents()->GetMainFrame()));
+}
+
+// Ensures that we use a manifest URL if it arrives after the onload handler
+// has fired. See crbug.com/1205018 for details.
+TEST_F(ContentFaviconDriverTest, UseManifestURLAFterOnLoad) {
+ ContentFaviconDriver* favicon_driver =
+ ContentFaviconDriver::FromWebContents(web_contents());
+ auto navigation = content::NavigationSimulator::CreateBrowserInitiated(
+ kPageURL, web_contents());
+ navigation->SetKeepLoading(true);
+ navigation->Commit();
+ navigation->StopLoading();
+ absl::optional<GURL> manifest_url = kFakeManifestURL;
+ auto* rfh_tester =
+ content::RenderFrameHostTester::For(web_contents()->GetMainFrame());
+ rfh_tester->SimulateManifestURLUpdate(manifest_url);
+ static_cast<content::WebContentsObserver*>(favicon_driver)
+ ->DidUpdateWebManifestURL(web_contents()->GetMainFrame(), manifest_url);
+ EXPECT_EQ(kFakeManifestURL,
+ favicon_driver->GetManifestURL(web_contents()->GetMainFrame()));
+}
+
// Test that no download is initiated when DocumentOnLoadCompletedInMainFrame()
// is not triggered (e.g. user stopped an ongoing page load).
TEST_F(ContentFaviconDriverTest, ShouldNotCauseImageDownload) {
@@ -120,9 +163,6 @@ TEST_F(ContentFaviconDriverTest, ShouldNotCauseImageDownload) {
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(web_contents_tester()->HasPendingDownloadImage(kIconURL));
-
- // Nevertheless, we expect the list exposed via favicon_urls().
- EXPECT_THAT(favicon_driver->favicon_urls(), SizeIs(1));
}
// Test that Favicon is not requested repeatedly during the same session if
@@ -155,25 +195,6 @@ TEST_F(ContentFaviconDriverTest, ShouldDownloadSecondIfFirstUnavailable) {
EXPECT_TRUE(web_contents_tester()->HasPendingDownloadImage(kOtherIconURL));
}
-// Test that ContentFaviconDriver ignores updated favicon URLs if there is no
-// last committed entry. This occurs when script is injected in about:blank.
-// See crbug.com/520759 for more details
-TEST_F(ContentFaviconDriverTest, FaviconUpdateNoLastCommittedEntry) {
- ASSERT_EQ(nullptr, web_contents()->GetController().GetLastCommittedEntry());
-
- std::vector<blink::mojom::FaviconURLPtr> favicon_urls;
- favicon_urls.push_back(blink::mojom::FaviconURL::New(
- GURL("http://www.google.ca/favicon.ico"),
- blink::mojom::FaviconIconType::kFavicon, kEmptyIconSizes));
- favicon::ContentFaviconDriver* driver =
- favicon::ContentFaviconDriver::FromWebContents(web_contents());
- static_cast<content::WebContentsObserver*>(driver)->DidUpdateFaviconURL(
- web_contents()->GetMainFrame(), favicon_urls);
-
- // Test that ContentFaviconDriver ignored the favicon url update.
- EXPECT_TRUE(driver->favicon_urls().empty());
-}
-
using ContentFaviconDriverTestNoFaviconService =
content::RenderViewHostTestHarness;
diff --git a/chromium/components/favicon/content/favicon_url_util.cc b/chromium/components/favicon/content/favicon_url_util.cc
index edd71f12134..b27692cc507 100644
--- a/chromium/components/favicon/content/favicon_url_util.cc
+++ b/chromium/components/favicon/content/favicon_url_util.cc
@@ -32,14 +32,14 @@ favicon_base::IconType IconTypeFromContentIconType(
} // namespace
FaviconURL FaviconURLFromContentFaviconURL(
- const blink::mojom::FaviconURL& favicon_url) {
- return FaviconURL(favicon_url.icon_url,
- IconTypeFromContentIconType(favicon_url.icon_type),
- favicon_url.icon_sizes);
+ const blink::mojom::FaviconURLPtr& favicon_url) {
+ return FaviconURL(favicon_url->icon_url,
+ IconTypeFromContentIconType(favicon_url->icon_type),
+ favicon_url->icon_sizes);
}
std::vector<FaviconURL> FaviconURLsFromContentFaviconURLs(
- const std::vector<blink::mojom::FaviconURL>& favicon_urls) {
+ const std::vector<blink::mojom::FaviconURLPtr>& favicon_urls) {
std::vector<FaviconURL> result;
result.reserve(favicon_urls.size());
std::transform(favicon_urls.begin(), favicon_urls.end(),
diff --git a/chromium/components/favicon/content/favicon_url_util.h b/chromium/components/favicon/content/favicon_url_util.h
index af3abc828a7..fbbef8ff598 100644
--- a/chromium/components/favicon/content/favicon_url_util.h
+++ b/chromium/components/favicon/content/favicon_url_util.h
@@ -14,11 +14,11 @@ struct FaviconURL;
// Creates a favicon::FaviconURL from a blink::mojom::FaviconURL.
FaviconURL FaviconURLFromContentFaviconURL(
- const blink::mojom::FaviconURL& favicon_url);
+ const blink::mojom::FaviconURLPtr& favicon_url);
-// Creates favicon::FaviconURLs from content::FaviconURLs.
+// Creates favicon::FaviconURLs from blink::mojom::FaviconURLPtrs.
std::vector<FaviconURL> FaviconURLsFromContentFaviconURLs(
- const std::vector<blink::mojom::FaviconURL>& favicon_urls);
+ const std::vector<blink::mojom::FaviconURLPtr>& favicon_urls);
} // namespace favicon
diff --git a/chromium/components/favicon/core/favicon_backend.cc b/chromium/components/favicon/core/favicon_backend.cc
index 0aad24c6d93..22c7636007c 100644
--- a/chromium/components/favicon/core/favicon_backend.cc
+++ b/chromium/components/favicon/core/favicon_backend.cc
@@ -626,7 +626,7 @@ FaviconBackend::GetFaviconsFromDB(const GURL& page_url,
// host of |page_url| for fuzzy matching. Query the database for a page_url
// that is known to exist and matches the host of |page_url|. Do this only
// if we have a HTTP/HTTPS url.
- base::Optional<GURL> fallback_page_url =
+ absl::optional<GURL> fallback_page_url =
db_->FindFirstPageURLForHost(page_url, icon_types);
if (fallback_page_url) {
diff --git a/chromium/components/favicon/core/favicon_database.cc b/chromium/components/favicon/core/favicon_database.cc
index cb04cc97ad3..dedb4f29601 100644
--- a/chromium/components/favicon/core/favicon_database.cc
+++ b/chromium/components/favicon/core/favicon_database.cc
@@ -786,11 +786,11 @@ bool FaviconDatabase::GetIconMappingsForPageURL(
return result;
}
-base::Optional<GURL> FaviconDatabase::FindFirstPageURLForHost(
+absl::optional<GURL> FaviconDatabase::FindFirstPageURLForHost(
const GURL& url,
const favicon_base::IconTypeSet& required_icon_types) {
if (url.host().empty())
- return base::nullopt;
+ return absl::nullopt;
sql::Statement statement(
db_.GetCachedStatement(SQL_FROM_HERE,
@@ -810,9 +810,9 @@ base::Optional<GURL> FaviconDatabase::FindFirstPageURLForHost(
FaviconDatabase::FromPersistedIconType(statement.ColumnInt(1));
if (required_icon_types.count(icon_type) != 0)
- return base::make_optional(GURL(statement.ColumnString(0)));
+ return absl::make_optional(GURL(statement.ColumnString(0)));
}
- return base::nullopt;
+ return absl::nullopt;
}
IconMappingID FaviconDatabase::AddIconMapping(const GURL& page_url,
diff --git a/chromium/components/favicon/core/favicon_database.h b/chromium/components/favicon/core/favicon_database.h
index 99d6967f4bf..1d2692b8f91 100644
--- a/chromium/components/favicon/core/favicon_database.h
+++ b/chromium/components/favicon/core/favicon_database.h
@@ -9,12 +9,12 @@
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "components/favicon/core/favicon_types.h"
#include "sql/database.h"
#include "sql/init_status.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class FilePath;
@@ -203,7 +203,7 @@ class FaviconDatabase {
// |url| = http://www.google.com would match
// |page_url| = https://www.google.com/search. The returned optional will be
// empty if no such |page_url| exists.
- base::Optional<GURL> FindFirstPageURLForHost(
+ absl::optional<GURL> FindFirstPageURLForHost(
const GURL& url,
const favicon_base::IconTypeSet& required_icon_types);
diff --git a/chromium/components/favicon/core/favicon_database_unittest.cc b/chromium/components/favicon/core/favicon_database_unittest.cc
index 60627cde178..6c1fd255fa3 100644
--- a/chromium/components/favicon/core/favicon_database_unittest.cc
+++ b/chromium/components/favicon/core/favicon_database_unittest.cc
@@ -12,7 +12,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted_memory.h"
#include "base/path_service.h"
-#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/favicon/core/favicon_database.h"
@@ -218,7 +217,7 @@ class FaviconDatabaseTest : public testing::Test {
std::unique_ptr<FaviconDatabase> LoadFromGolden(const char* golden_path) {
if (!history::CreateDatabaseFromSQL(file_name_, golden_path)) {
ADD_FAILURE() << "Failed loading " << golden_path;
- return std::unique_ptr<FaviconDatabase>();
+ return nullptr;
}
std::unique_ptr<FaviconDatabase> db = std::make_unique<FaviconDatabase>();
@@ -892,7 +891,7 @@ TEST_F(FaviconDatabaseTest, FindFirstPageURLForHost) {
{favicon_base::IconType::kFavicon}));
// Expect a match when we search for a TouchIcon.
- base::Optional<GURL> result = db.FindFirstPageURLForHost(
+ absl::optional<GURL> result = db.FindFirstPageURLForHost(
kPageUrlHttps,
{favicon_base::IconType::kFavicon, favicon_base::IconType::kTouchIcon});
diff --git a/chromium/components/favicon/core/favicon_driver.h b/chromium/components/favicon/core/favicon_driver.h
index d69ebe458c8..ca63a217317 100644
--- a/chromium/components/favicon/core/favicon_driver.h
+++ b/chromium/components/favicon/core/favicon_driver.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_FAVICON_CORE_FAVICON_DRIVER_H_
#define COMPONENTS_FAVICON_CORE_FAVICON_DRIVER_H_
-#include <string>
-
#include "base/macros.h"
#include "base/observer_list.h"
#include "components/favicon/core/favicon_driver_observer.h"
diff --git a/chromium/components/favicon/core/favicon_handler.cc b/chromium/components/favicon/core/favicon_handler.cc
index 0d3919e703d..ddfc129b658 100644
--- a/chromium/components/favicon/core/favicon_handler.cc
+++ b/chromium/components/favicon/core/favicon_handler.cc
@@ -86,7 +86,7 @@ bool HasExpiredOrIncompleteResult(
bool HasValidResult(
const std::vector<favicon_base::FaviconRawBitmapResult>& bitmap_results) {
return std::find_if(bitmap_results.begin(), bitmap_results.end(), IsValid) !=
- bitmap_results.end();
+ bitmap_results.end();
}
std::vector<int> GetDesiredPixelSizes(
@@ -171,8 +171,7 @@ FaviconHandler::FaviconHandler(
DCHECK(delegate_);
}
-FaviconHandler::~FaviconHandler() {
-}
+FaviconHandler::~FaviconHandler() = default;
// static
favicon_base::IconTypeSet FaviconHandler::GetIconTypesFromHandlerType(
@@ -297,8 +296,7 @@ void FaviconHandler::NotifyFaviconUpdated(
DCHECK(!favicon_bitmap_results.empty());
gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs(
- favicon_bitmap_results,
- favicon_base::GetFaviconScales(),
+ favicon_bitmap_results, favicon_base::GetFaviconScales(),
preferred_icon_size());
// The history service sends back results for a single icon URL and icon
// type, so it does not matter which result we get |icon_url| and |icon_type|
@@ -532,10 +530,8 @@ void FaviconHandler::OnDidDownloadFavicon(
image_skia =
gfx::ImageSkia::CreateFrom1xBitmap(bitmaps[best_indices.front()]);
} else {
- image_skia = CreateFaviconImageSkia(bitmaps,
- original_bitmap_sizes,
- preferred_icon_size(),
- &score);
+ image_skia = CreateFaviconImageSkia(bitmaps, original_bitmap_sizes,
+ preferred_icon_size(), &score);
}
if (!image_skia.isNull() && score > best_favicon_.candidate.score) {
@@ -675,8 +671,9 @@ void FaviconHandler::GetFaviconAndUpdateMappingsUnlessIncognito(
}
}
-void FaviconHandler::OnFaviconData(const std::vector<
- favicon_base::FaviconRawBitmapResult>& favicon_bitmap_results) {
+void FaviconHandler::OnFaviconData(
+ const std::vector<favicon_base::FaviconRawBitmapResult>&
+ favicon_bitmap_results) {
bool has_valid_result = HasValidResult(favicon_bitmap_results);
// For off-the-record profiles pretend that favicons from FaviconService are
// expired so websites don't know if a site was previously visited in regular
@@ -703,7 +700,7 @@ void FaviconHandler::OnFaviconData(const std::vector<
void FaviconHandler::ScheduleImageDownload(const GURL& image_url,
favicon_base::IconType icon_type) {
DCHECK(image_url.is_valid());
- // Note that CancelableCallback starts cancelled.
+ // Note that CancelableOnceCallback starts cancelled.
DCHECK(image_download_request_.IsCancelled())
<< "More than one ongoing download";
if (service_ && service_->WasUnableToDownloadFavicon(image_url)) {
diff --git a/chromium/components/favicon/core/favicon_handler.h b/chromium/components/favicon/core/favicon_handler.h
index 574d88ac91a..631d3bf584b 100644
--- a/chromium/components/favicon/core/favicon_handler.h
+++ b/chromium/components/favicon/core/favicon_handler.h
@@ -14,11 +14,11 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/task/cancelable_task_tracker.h"
#include "components/favicon/core/favicon_driver_observer.h"
#include "components/favicon/core/favicon_url.h"
#include "components/favicon_base/favicon_callback.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/image/image.h"
#include "url/gurl.h"
@@ -263,7 +263,6 @@ class FaviconHandler {
// - A mapping is known to exist (reflected by |notification_icon_type_|).
// - All download attempts returned 404s OR no relevant candidate was
// provided (as per |icon_types_|).
- // - The corresponding feature is enabled (currently behind variations).
void MaybeDeleteFaviconMappings();
// Notifies |driver_| that FaviconHandler found an icon which matches the
@@ -355,7 +354,7 @@ class FaviconHandler {
// The prioritized favicon candidates from the page back from the renderer.
// Populated by OnGotFinalIconURLCandidates().
- base::Optional<std::vector<FaviconCandidate>> final_candidates_;
+ absl::optional<std::vector<FaviconCandidate>> final_candidates_;
// The icon URL and the icon type of the favicon in the most recent
// FaviconDriver::OnFaviconAvailable() notification.
diff --git a/chromium/components/favicon/core/favicon_url.h b/chromium/components/favicon/core/favicon_url.h
index 04f000a5762..b3b0a025bca 100644
--- a/chromium/components/favicon/core/favicon_url.h
+++ b/chromium/components/favicon/core/favicon_url.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_FAVICON_CORE_FAVICON_URL_
-#define COMPONENTS_FAVICON_CORE_FAVICON_URL_
+#ifndef COMPONENTS_FAVICON_CORE_FAVICON_URL_H_
+#define COMPONENTS_FAVICON_CORE_FAVICON_URL_H_
#include <vector>
@@ -34,4 +34,4 @@ struct FaviconURL {
} // namespace favicon
-#endif // COMPONENTS_FAVICON_CORE_FAVICON_URL_
+#endif // COMPONENTS_FAVICON_CORE_FAVICON_URL_H_
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 0f7b57b08f3..05940d08deb 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
@@ -131,16 +131,15 @@ void HistoryUiFaviconRequestHandlerImpl::OnBitmapLocalDataAvailable(
}
if (can_send_history_data_getter_.Run()) {
- // base::AdaptCallbackForRepeating() is necessary here because
+ // base::SplitOnceCallback() is necessary here because
// |response_callback| is needed to build both the empty response and local
// lookup callbacks. This is safe because only one of the two is called.
- base::RepeatingCallback<void(const favicon_base::FaviconRawBitmapResult&)>
- repeating_response_callback =
- base::AdaptCallbackForRepeating(std::move(response_callback));
+ auto split_response_callback =
+ base::SplitOnceCallback(std::move(response_callback));
RequestFromGoogleServer(
page_url,
/*empty_response_callback=*/
- base::BindOnce(repeating_response_callback,
+ base::BindOnce(std::move(split_response_callback.first),
favicon_base::FaviconRawBitmapResult()),
/*local_lookup_callback=*/
base::BindOnce(
@@ -149,7 +148,8 @@ void HistoryUiFaviconRequestHandlerImpl::OnBitmapLocalDataAvailable(
// doesn't execute the callback if |this| is deleted.
base::Unretained(favicon_service_), page_url,
GetIconTypesForLocalQuery(), desired_size_in_pixel, kFallbackToHost,
- repeating_response_callback, &cancelable_task_tracker_),
+ std::move(split_response_callback.second),
+ &cancelable_task_tracker_),
origin_for_uma, request_start_time_for_uma);
return;
}
@@ -179,16 +179,15 @@ void HistoryUiFaviconRequestHandlerImpl::OnImageLocalDataAvailable(
}
if (can_send_history_data_getter_.Run()) {
- // base::AdaptCallbackForRepeating() is necessary here because
+ // base::SplitOnceCallback() is necessary here because
// |response_callback| is needed to build both the empty response and local
// lookup callbacks. This is safe because only one of the two is called.
- base::RepeatingCallback<void(const favicon_base::FaviconImageResult&)>
- repeating_response_callback =
- base::AdaptCallbackForRepeating(std::move(response_callback));
+ auto split_response_callback =
+ base::SplitOnceCallback(std::move(response_callback));
RequestFromGoogleServer(
page_url,
/*empty_response_callback=*/
- base::BindOnce(repeating_response_callback,
+ base::BindOnce(std::move(split_response_callback.first),
favicon_base::FaviconImageResult()),
/*local_lookup_callback=*/
base::BindOnce(
@@ -196,7 +195,8 @@ void HistoryUiFaviconRequestHandlerImpl::OnImageLocalDataAvailable(
// base::Unretained() is safe here as RequestFromGoogleServer()
// doesn't execture the callback if |this| is deleted.
base::Unretained(favicon_service_), page_url,
- repeating_response_callback, &cancelable_task_tracker_),
+ std::move(split_response_callback.second),
+ &cancelable_task_tracker_),
origin_for_uma, request_start_time_for_uma);
return;
}
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 9affc4d2264..69101e5680f 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
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_FAVICON_CORE_HISTORY_UI_FAVICON_REQUEST_HANDLER_IMPL_H_
#define COMPONENTS_FAVICON_CORE_HISTORY_UI_FAVICON_REQUEST_HANDLER_IMPL_H_
-#include <map>
-#include <memory>
-
#include "base/memory/weak_ptr.h"
#include "base/task/cancelable_task_tracker.h"
#include "components/favicon/core/history_ui_favicon_request_handler.h"
diff --git a/chromium/components/favicon/core/large_icon_service.h b/chromium/components/favicon/core/large_icon_service.h
index b5e6cf343b7..a813d41466f 100644
--- a/chromium/components/favicon/core/large_icon_service.h
+++ b/chromium/components/favicon/core/large_icon_service.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_FAVICON_CORE_LARGE_ICON_SERVICE_H_
#define COMPONENTS_FAVICON_CORE_LARGE_ICON_SERVICE_H_
-#include <memory>
-
#include "base/macros.h"
#include "base/task/cancelable_task_tracker.h"
#include "components/favicon_base/favicon_callback.h"
diff --git a/chromium/components/feature_engagement/README.md b/chromium/components/feature_engagement/README.md
index a22c25f2ba3..2fa27aa8c48 100644
--- a/chromium/components/feature_engagement/README.md
+++ b/chromium/components/feature_engagement/README.md
@@ -350,10 +350,27 @@ Format:
"x_???": "..."
}
```
+Alternate format:
+
+```
+{
+ "IPH_MyFunFeature_availability": "{Comparator}",
+ "IPH_MyFunFeature_session_rate": "{Comparator}",
+ "IPH_MyFunFeature_session_rate_impact": "{SessionRateImpact}",
+ "IPH_MyFunFeature_event_used": "{EventConfig}",
+ "IPH_MyFunFeature_event_trigger": "{EventConfig}",
+ "IPH_MyFunFeature_event_???": "{EventConfig}",
+ "IPH_MyFunFeature_tracking_only": "{Boolean}"
+ "IPH_MyFunFeature_x_???": "..."
+ }
+```
The `FeatureConfig` fields `availability`, `session_rate`, `event_used` and
`event_trigger` are required, and there can be an arbitrary amount of other
-`event_???` entries.
+`event_???` entries. The fields can optionally have a feature name prefix
+(e.g. `IPH_MyFunFeature_`) as well, which is sometimes required to
+disambiguate between param names between different IPHs if they are combined
+into the same finch study.
* `availability` __REQUIRED__
* For how long must an in-product help experiment have been available to
diff --git a/chromium/components/feature_engagement/internal/availability_model.h b/chromium/components/feature_engagement/internal/availability_model.h
index 27aea7e653a..fdf4f03d1b7 100644
--- a/chromium/components/feature_engagement/internal/availability_model.h
+++ b/chromium/components/feature_engagement/internal/availability_model.h
@@ -9,7 +9,7 @@
#include "base/callback_forward.h"
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
struct Feature;
@@ -39,7 +39,7 @@ class AvailabilityModel {
// Returns the day number since epoch (1970-01-01) in the local timezone for
// when the particular |feature| was made available.
// See TimeProvider::GetCurrentDay().
- virtual base::Optional<uint32_t> GetAvailability(
+ virtual absl::optional<uint32_t> GetAvailability(
const base::Feature& feature) const = 0;
protected:
diff --git a/chromium/components/feature_engagement/internal/availability_model_impl.cc b/chromium/components/feature_engagement/internal/availability_model_impl.cc
index 4b332cd40bd..b316e20fa8b 100644
--- a/chromium/components/feature_engagement/internal/availability_model_impl.cc
+++ b/chromium/components/feature_engagement/internal/availability_model_impl.cc
@@ -33,11 +33,11 @@ bool AvailabilityModelImpl::IsReady() const {
return ready_;
}
-base::Optional<uint32_t> AvailabilityModelImpl::GetAvailability(
+absl::optional<uint32_t> AvailabilityModelImpl::GetAvailability(
const base::Feature& feature) const {
auto search = feature_availabilities_.find(feature.name);
if (search == feature_availabilities_.end())
- return base::nullopt;
+ return absl::nullopt;
return search->second;
}
diff --git a/chromium/components/feature_engagement/internal/availability_model_impl.h b/chromium/components/feature_engagement/internal/availability_model_impl.h
index bdee2f5542b..23721d77615 100644
--- a/chromium/components/feature_engagement/internal/availability_model_impl.h
+++ b/chromium/components/feature_engagement/internal/availability_model_impl.h
@@ -37,7 +37,7 @@ class AvailabilityModelImpl : public AvailabilityModel {
void Initialize(OnInitializedCallback callback,
uint32_t current_day) override;
bool IsReady() const override;
- base::Optional<uint32_t> GetAvailability(
+ absl::optional<uint32_t> GetAvailability(
const base::Feature& feature) const override;
private:
diff --git a/chromium/components/feature_engagement/internal/availability_model_impl_unittest.cc b/chromium/components/feature_engagement/internal/availability_model_impl_unittest.cc
index 40bcad5241a..6610a3cf07d 100644
--- a/chromium/components/feature_engagement/internal/availability_model_impl_unittest.cc
+++ b/chromium/components/feature_engagement/internal/availability_model_impl_unittest.cc
@@ -11,9 +11,9 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/feature_engagement/internal/persistent_availability_store.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feature_engagement {
@@ -63,8 +63,8 @@ class AvailabilityModelImplTest : public testing::Test {
std::unique_ptr<AvailabilityModelImpl> availability_model_;
AvailabilityModel::OnInitializedCallback initialized_callback_;
- base::Optional<bool> success_;
- base::Optional<uint32_t> current_day_;
+ absl::optional<bool> success_;
+ absl::optional<uint32_t> current_day_;
private:
DISALLOW_COPY_AND_ASSIGN(AvailabilityModelImplTest);
@@ -105,7 +105,7 @@ TEST_F(AvailabilityModelImplTest, SuccessfullyLoadThreeFeatures) {
EXPECT_EQ(100u, availability_model_->GetAvailability(kTestFeatureFoo));
EXPECT_EQ(200u, availability_model_->GetAvailability(kTestFeatureBar));
EXPECT_EQ(300u, availability_model_->GetAvailability(kTestFeatureNop));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
availability_model_->GetAvailability(kTestFeatureQux));
}
@@ -120,13 +120,13 @@ TEST_F(AvailabilityModelImplTest, FailToLoadThreeFeatures) {
EXPECT_FALSE(availability_model_->IsReady());
// Load failed, so all results should be ignored.
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
availability_model_->GetAvailability(kTestFeatureFoo));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
availability_model_->GetAvailability(kTestFeatureBar));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
availability_model_->GetAvailability(kTestFeatureNop));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
availability_model_->GetAvailability(kTestFeatureQux));
}
diff --git a/chromium/components/feature_engagement/internal/chrome_variations_configuration.cc b/chromium/components/feature_engagement/internal/chrome_variations_configuration.cc
index 139f72e65ae..ae2f6190169 100644
--- a/chromium/components/feature_engagement/internal/chrome_variations_configuration.cc
+++ b/chromium/components/feature_engagement/internal/chrome_variations_configuration.cc
@@ -150,7 +150,7 @@ bool ParseEventConfig(const base::StringPiece& definition,
}
has_name = true;
- event_config->name = value.as_string();
+ event_config->name = std::string(value);
} else if (base::LowerCaseEqualsASCII(key, kEventConfigDataComparatorKey)) {
if (has_comparator) {
*event_config = EventConfig();
@@ -202,7 +202,7 @@ bool ParseEventConfig(const base::StringPiece& definition,
bool IsKnownFeature(const base::StringPiece& feature_name,
const FeatureVector& features) {
for (const auto* feature : features) {
- if (feature->name == feature_name.as_string())
+ if (feature->name == feature_name)
return true;
}
return false;
@@ -254,7 +254,7 @@ bool ParseSessionRateImpact(const base::StringPiece& definition,
FAILURE_SESSION_RATE_IMPACT_UNKNOWN_FEATURE);
continue;
}
- affected_features.push_back(feature_name.as_string());
+ affected_features.push_back(std::string(feature_name));
}
if (affected_features.empty())
@@ -338,10 +338,18 @@ void ChromeVariationsConfiguration::ParseFeatureConfig(
uint32_t parse_errors = 0;
for (const auto& it : params) {
- const std::string& key = it.first;
+ std::string param_name = it.first;
+ std::string param_value = params[param_name];
+ std::string key = param_name;
+ // The param name might have a prefix containing the feature name with
+ // a trailing underscore, e.g. IPH_FooFeature_session_rate. Strip out
+ // the feature prefix for further comparison.
+ if (base::StartsWith(key, feature->name, base::CompareCase::SENSITIVE))
+ key = param_name.substr(strlen(feature->name) + 1);
+
if (key == kEventConfigUsedKey) {
EventConfig event_config;
- if (!ParseEventConfig(params[key], &event_config)) {
+ if (!ParseEventConfig(param_value, &event_config)) {
++parse_errors;
stats::RecordConfigParsingEvent(
stats::ConfigParsingEvent::FAILURE_USED_EVENT_PARSE);
@@ -350,7 +358,7 @@ void ChromeVariationsConfiguration::ParseFeatureConfig(
config.used = event_config;
} else if (key == kEventConfigTriggerKey) {
EventConfig event_config;
- if (!ParseEventConfig(params[key], &event_config)) {
+ if (!ParseEventConfig(param_value, &event_config)) {
stats::RecordConfigParsingEvent(
stats::ConfigParsingEvent::FAILURE_TRIGGER_EVENT_PARSE);
++parse_errors;
@@ -359,7 +367,7 @@ void ChromeVariationsConfiguration::ParseFeatureConfig(
config.trigger = event_config;
} else if (key == kSessionRateKey) {
Comparator comparator;
- if (!ParseComparator(params[key], &comparator)) {
+ if (!ParseComparator(param_value, &comparator)) {
stats::RecordConfigParsingEvent(
stats::ConfigParsingEvent::FAILURE_SESSION_RATE_PARSE);
++parse_errors;
@@ -368,7 +376,7 @@ void ChromeVariationsConfiguration::ParseFeatureConfig(
config.session_rate = comparator;
} else if (key == kSessionRateImpactKey) {
SessionRateImpact impact;
- if (!ParseSessionRateImpact(params[key], &impact, feature,
+ if (!ParseSessionRateImpact(param_value, &impact, feature,
all_features)) {
stats::RecordConfigParsingEvent(
stats::ConfigParsingEvent::FAILURE_SESSION_RATE_IMPACT_PARSE);
@@ -378,7 +386,7 @@ void ChromeVariationsConfiguration::ParseFeatureConfig(
config.session_rate_impact = impact;
} else if (key == kTrackingOnlyKey) {
bool tracking_only;
- if (!ParseTrackingOnly(params[key], &tracking_only)) {
+ if (!ParseTrackingOnly(param_value, &tracking_only)) {
stats::RecordConfigParsingEvent(
stats::ConfigParsingEvent::FAILURE_TRACKING_ONLY_PARSE);
++parse_errors;
@@ -387,7 +395,7 @@ void ChromeVariationsConfiguration::ParseFeatureConfig(
config.tracking_only = tracking_only;
} else if (key == kAvailabilityKey) {
Comparator comparator;
- if (!ParseComparator(params[key], &comparator)) {
+ if (!ParseComparator(param_value, &comparator)) {
stats::RecordConfigParsingEvent(
stats::ConfigParsingEvent::FAILURE_AVAILABILITY_PARSE);
++parse_errors;
@@ -397,7 +405,7 @@ void ChromeVariationsConfiguration::ParseFeatureConfig(
} else if (base::StartsWith(key, kEventConfigKeyPrefix,
base::CompareCase::INSENSITIVE_ASCII)) {
EventConfig event_config;
- if (!ParseEventConfig(params[key], &event_config)) {
+ if (!ParseEventConfig(param_value, &event_config)) {
stats::RecordConfigParsingEvent(
stats::ConfigParsingEvent::FAILURE_OTHER_EVENT_PARSE);
++parse_errors;
@@ -408,10 +416,10 @@ void ChromeVariationsConfiguration::ParseFeatureConfig(
base::CompareCase::INSENSITIVE_ASCII)) {
// Intentionally ignoring parameter using registered ignored prefix.
DVLOG(2) << "Ignoring unknown key when parsing config for feature "
- << feature->name << ": " << key;
+ << feature->name << ": " << param_name;
} else {
DVLOG(1) << "Unknown key found when parsing config for feature "
- << feature->name << ": " << key;
+ << feature->name << ": " << param_name;
stats::RecordConfigParsingEvent(
stats::ConfigParsingEvent::FAILURE_UNKNOWN_KEY);
}
diff --git a/chromium/components/feature_engagement/internal/chrome_variations_configuration_unittest.cc b/chromium/components/feature_engagement/internal/chrome_variations_configuration_unittest.cc
index 828c5483707..94f8ea022f6 100644
--- a/chromium/components/feature_engagement/internal/chrome_variations_configuration_unittest.cc
+++ b/chromium/components/feature_engagement/internal/chrome_variations_configuration_unittest.cc
@@ -179,6 +179,93 @@ TEST_F(ChromeVariationsConfigurationTest, ParseSingleFeature) {
EXPECT_EQ(expected_foo, foo);
}
+TEST_F(ChromeVariationsConfigurationTest, ParsePrefixedParamNames) {
+ std::map<std::string, std::string> foo_params;
+ // Prefixed param names.
+ foo_params["test_foo_session_rate"] = "!=6";
+ foo_params["test_foo_availability"] = ">=1";
+ foo_params["test_foo_event_used"] =
+ "name:page_download_started;comparator:any;window:0;storage:360";
+ foo_params["test_foo_event_trigger"] =
+ "name:opened_chrome_home;comparator:any;window:0;storage:360";
+ foo_params["test_foo_event_1"] =
+ "name:user_has_seen_dino;comparator:>=1;window:120;storage:180";
+ foo_params["event_2"] =
+ "name:user_opened_app_menu;comparator:<=0;window:120;storage:180";
+ foo_params["event_3"] =
+ "name:user_opened_downloads_home;comparator:any;window:0;storage:360";
+
+ SetFeatureParams(kChromeTestFeatureFoo, foo_params);
+
+ base::HistogramTester histogram_tester;
+ std::vector<const base::Feature*> features = {&kChromeTestFeatureFoo};
+ configuration_.ParseFeatureConfigs(features);
+
+ FeatureConfig foo = configuration_.GetFeatureConfig(kChromeTestFeatureFoo);
+ EXPECT_TRUE(foo.valid);
+ histogram_tester.ExpectBucketCount(
+ kConfigParseEventName,
+ static_cast<int>(stats::ConfigParsingEvent::SUCCESS), 1);
+ histogram_tester.ExpectTotalCount(kConfigParseEventName, 1);
+
+ FeatureConfig expected_foo;
+ expected_foo.valid = true;
+ expected_foo.used =
+ EventConfig("page_download_started", Comparator(ANY, 0), 0, 360);
+ expected_foo.trigger =
+ EventConfig("opened_chrome_home", Comparator(ANY, 0), 0, 360);
+ expected_foo.event_configs.insert(EventConfig(
+ "user_has_seen_dino", Comparator(GREATER_THAN_OR_EQUAL, 1), 120, 180));
+ expected_foo.event_configs.insert(EventConfig(
+ "user_opened_app_menu", Comparator(LESS_THAN_OR_EQUAL, 0), 120, 180));
+ expected_foo.event_configs.insert(
+ EventConfig("user_opened_downloads_home", Comparator(ANY, 0), 0, 360));
+ expected_foo.session_rate = Comparator(NOT_EQUAL, 6);
+ expected_foo.availability = Comparator(GREATER_THAN_OR_EQUAL, 1);
+ EXPECT_EQ(expected_foo, foo);
+}
+
+TEST_F(ChromeVariationsConfigurationTest,
+ MultipleFeaturesWithPrefixedAndUnprefixedParams) {
+ std::map<std::string, std::string> foo_params;
+ foo_params["test_foo_session_rate"] = "!=6";
+ foo_params["test_foo_availability"] = ">=1";
+ SetFeatureParams(kChromeTestFeatureFoo, foo_params);
+
+ std::map<std::string, std::string> bar_params;
+ bar_params["test_bar_session_rate"] = "!=7";
+ bar_params["test_bar_availability"] = ">=2";
+ SetFeatureParams(kChromeTestFeatureBar, bar_params);
+
+ std::map<std::string, std::string> qux_params;
+ qux_params["session_rate"] = "!=3";
+ qux_params["availability"] = ">=5";
+ SetFeatureParams(kChromeTestFeatureQux, qux_params);
+
+ std::vector<const base::Feature*> features = {
+ &kChromeTestFeatureFoo, &kChromeTestFeatureBar, &kChromeTestFeatureQux};
+ configuration_.ParseFeatureConfigs(features);
+
+ FeatureConfig foo = configuration_.GetFeatureConfig(kChromeTestFeatureFoo);
+ FeatureConfig bar = configuration_.GetFeatureConfig(kChromeTestFeatureBar);
+ FeatureConfig qux = configuration_.GetFeatureConfig(kChromeTestFeatureQux);
+
+ FeatureConfig expected_foo;
+ expected_foo.session_rate = Comparator(NOT_EQUAL, 6);
+ expected_foo.availability = Comparator(GREATER_THAN_OR_EQUAL, 1);
+ EXPECT_EQ(expected_foo, foo);
+
+ FeatureConfig expected_bar;
+ expected_bar.session_rate = Comparator(NOT_EQUAL, 7);
+ expected_bar.availability = Comparator(GREATER_THAN_OR_EQUAL, 2);
+ EXPECT_EQ(expected_bar, bar);
+
+ FeatureConfig expected_qux;
+ expected_qux.session_rate = Comparator(NOT_EQUAL, 3);
+ expected_qux.availability = Comparator(GREATER_THAN_OR_EQUAL, 5);
+ EXPECT_EQ(expected_qux, qux);
+}
+
TEST_F(ChromeVariationsConfigurationTest, MissingUsedIsInvalid) {
std::map<std::string, std::string> foo_params;
foo_params["event_trigger"] = "name:et;comparator:any;window:0;storage:360";
diff --git a/chromium/components/feature_engagement/internal/event_store.h b/chromium/components/feature_engagement/internal/event_store.h
index ce07a3cfc7a..e77a5e5fac1 100644
--- a/chromium/components/feature_engagement/internal/event_store.h
+++ b/chromium/components/feature_engagement/internal/event_store.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_FEATURE_ENGAGEMENT_INTERNAL_STORE_H_
-#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_STORE_H_
+#ifndef COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_STORE_H_
+#define COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_STORE_H_
#include <string>
@@ -46,4 +46,4 @@ class EventStore {
} // namespace feature_engagement
-#endif // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_STORE_H_
+#endif // COMPONENTS_FEATURE_ENGAGEMENT_INTERNAL_EVENT_STORE_H_
diff --git a/chromium/components/feature_engagement/internal/feature_config_condition_validator.cc b/chromium/components/feature_engagement/internal/feature_config_condition_validator.cc
index 8afff82f1f6..8cd8d93caac 100644
--- a/chromium/components/feature_engagement/internal/feature_config_condition_validator.cc
+++ b/chromium/components/feature_engagement/internal/feature_config_condition_validator.cc
@@ -114,7 +114,7 @@ bool FeatureConfigConditionValidator::AvailabilityMeetsConditions(
if (comparator.type == ANY)
return true;
- base::Optional<uint32_t> availability_day =
+ absl::optional<uint32_t> availability_day =
availability_model.GetAvailability(feature);
if (!availability_day.has_value())
return false;
diff --git a/chromium/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc b/chromium/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc
index e33822dc72a..85e41a8247c 100644
--- a/chromium/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc
+++ b/chromium/components/feature_engagement/internal/feature_config_condition_validator_unittest.cc
@@ -123,24 +123,24 @@ class TestAvailabilityModel : public AvailabilityModel {
void SetIsReady(bool ready) { ready_ = ready; }
- base::Optional<uint32_t> GetAvailability(
+ absl::optional<uint32_t> GetAvailability(
const base::Feature& feature) const override {
auto search = availabilities_.find(feature.name);
if (search == availabilities_.end())
- return base::nullopt;
+ return absl::nullopt;
return search->second;
}
void SetAvailability(const base::Feature* feature,
- base::Optional<uint32_t> availability) {
+ absl::optional<uint32_t> availability) {
availabilities_[feature->name] = availability;
}
private:
bool ready_;
- std::map<std::string, base::Optional<uint32_t>> availabilities_;
+ std::map<std::string, absl::optional<uint32_t>> availabilities_;
DISALLOW_COPY_AND_ASSIGN(TestAvailabilityModel);
};
diff --git a/chromium/components/feature_engagement/internal/init_aware_event_model_unittest.cc b/chromium/components/feature_engagement/internal/init_aware_event_model_unittest.cc
index 9d07636c8f2..1ffe69baa20 100644
--- a/chromium/components/feature_engagement/internal/init_aware_event_model_unittest.cc
+++ b/chromium/components/feature_engagement/internal/init_aware_event_model_unittest.cc
@@ -8,11 +8,11 @@
#include "base/bind.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/feature_engagement/internal/proto/feature_event.pb.h"
#include "components/feature_engagement/internal/test/event_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using testing::_;
using testing::Return;
@@ -63,7 +63,7 @@ class InitAwareEventModelTest : public testing::Test {
MockEventModel* mocked_model_;
// Load callback tracking.
- base::Optional<bool> load_success_;
+ absl::optional<bool> load_success_;
EventModel::OnModelInitializationFinished load_callback_;
private:
diff --git a/chromium/components/feature_engagement/internal/never_availability_model.cc b/chromium/components/feature_engagement/internal/never_availability_model.cc
index 03eb01da3ac..cac8ce1a607 100644
--- a/chromium/components/feature_engagement/internal/never_availability_model.cc
+++ b/chromium/components/feature_engagement/internal/never_availability_model.cc
@@ -8,10 +8,10 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feature_engagement {
@@ -31,9 +31,9 @@ bool NeverAvailabilityModel::IsReady() const {
return ready_;
}
-base::Optional<uint32_t> NeverAvailabilityModel::GetAvailability(
+absl::optional<uint32_t> NeverAvailabilityModel::GetAvailability(
const base::Feature& feature) const {
- return base::nullopt;
+ return absl::nullopt;
}
void NeverAvailabilityModel::ForwardedOnInitializedCallback(
diff --git a/chromium/components/feature_engagement/internal/never_availability_model.h b/chromium/components/feature_engagement/internal/never_availability_model.h
index 9d30f1a83ad..27fef7fe235 100644
--- a/chromium/components/feature_engagement/internal/never_availability_model.h
+++ b/chromium/components/feature_engagement/internal/never_availability_model.h
@@ -23,7 +23,7 @@ class NeverAvailabilityModel : public AvailabilityModel {
void Initialize(AvailabilityModel::OnInitializedCallback callback,
uint32_t current_day) override;
bool IsReady() const override;
- base::Optional<uint32_t> GetAvailability(
+ absl::optional<uint32_t> GetAvailability(
const base::Feature& feature) const override;
private:
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 e2941404fc6..294625dd63e 100644
--- a/chromium/components/feature_engagement/internal/never_availability_model_unittest.cc
+++ b/chromium/components/feature_engagement/internal/never_availability_model_unittest.cc
@@ -6,10 +6,10 @@
#include "base/bind.h"
#include "base/feature_list.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feature_engagement {
@@ -28,7 +28,7 @@ class NeverAvailabilityModelTest : public ::testing::Test {
protected:
NeverAvailabilityModel availability_model_;
- base::Optional<bool> success_;
+ absl::optional<bool> success_;
private:
base::test::SingleThreadTaskEnvironment task_environment_;
@@ -39,9 +39,9 @@ class NeverAvailabilityModelTest : public ::testing::Test {
} // namespace
TEST_F(NeverAvailabilityModelTest, ShouldNeverHaveData) {
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
availability_model_.GetAvailability(kAvailabilityTestFeatureFoo));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
availability_model_.GetAvailability(kAvailabilityTestFeatureBar));
availability_model_.Initialize(
@@ -50,9 +50,9 @@ TEST_F(NeverAvailabilityModelTest, ShouldNeverHaveData) {
14u);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
availability_model_.GetAvailability(kAvailabilityTestFeatureFoo));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
availability_model_.GetAvailability(kAvailabilityTestFeatureBar));
}
diff --git a/chromium/components/feature_engagement/internal/persistent_availability_store_unittest.cc b/chromium/components/feature_engagement/internal/persistent_availability_store_unittest.cc
index cf771b2b24d..d2c32972430 100644
--- a/chromium/components/feature_engagement/internal/persistent_availability_store_unittest.cc
+++ b/chromium/components/feature_engagement/internal/persistent_availability_store_unittest.cc
@@ -15,13 +15,13 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/test/scoped_feature_list.h"
#include "components/feature_engagement/internal/proto/availability.pb.h"
#include "components/feature_engagement/public/feature_list.h"
#include "components/leveldb_proto/public/proto_database.h"
#include "components/leveldb_proto/testing/fake_db.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feature_engagement {
@@ -75,7 +75,7 @@ class PersistentAvailabilityStoreTest : public testing::Test {
PersistentAvailabilityStore::OnLoadedCallback load_callback_;
// Callback results.
- base::Optional<bool> load_successful_;
+ absl::optional<bool> load_successful_;
std::unique_ptr<std::map<std::string, uint32_t>> load_results_;
// |db_availabilities_| is used during creation of the FakeDB in CreateDB(),
diff --git a/chromium/components/feature_engagement/internal/persistent_event_store_unittest.cc b/chromium/components/feature_engagement/internal/persistent_event_store_unittest.cc
index 54b922ac59b..0e2387eec5f 100644
--- a/chromium/components/feature_engagement/internal/persistent_event_store_unittest.cc
+++ b/chromium/components/feature_engagement/internal/persistent_event_store_unittest.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/files/file_path.h"
-#include "base/optional.h"
#include "base/test/metrics/histogram_tester.h"
#include "components/feature_engagement/internal/proto/feature_event.pb.h"
#include "components/feature_engagement/internal/stats.h"
@@ -17,6 +16,7 @@
#include "components/leveldb_proto/public/proto_database.h"
#include "components/leveldb_proto/testing/fake_db.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feature_engagement {
@@ -62,7 +62,7 @@ class PersistentEventStoreTest : public ::testing::Test {
}
// Callback results.
- base::Optional<bool> load_successful_;
+ absl::optional<bool> load_successful_;
std::unique_ptr<std::vector<Event>> load_results_;
EventStore::OnLoadedCallback load_callback_;
diff --git a/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc b/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc
index 44c097b89c9..bf92e5a0f2e 100644
--- a/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc
+++ b/chromium/components/feature_engagement/internal/tracker_impl_unittest.cc
@@ -151,9 +151,9 @@ class TestTrackerAvailabilityModel : public AvailabilityModel {
void SetIsReady(bool ready) { ready_ = ready; }
- base::Optional<uint32_t> GetAvailability(
+ absl::optional<uint32_t> GetAvailability(
const base::Feature& feature) const override {
- return base::nullopt;
+ return absl::nullopt;
}
private:
diff --git a/chromium/components/feature_engagement/public/BUILD.gn b/chromium/components/feature_engagement/public/BUILD.gn
index 02a3f8b929d..f458072d849 100644
--- a/chromium/components/feature_engagement/public/BUILD.gn
+++ b/chromium/components/feature_engagement/public/BUILD.gn
@@ -25,6 +25,7 @@ source_set("public") {
deps = [
"//base",
+ "//components/feed:feature_list",
"//components/flags_ui",
"//components/keyed_service/core",
]
diff --git a/chromium/components/feature_engagement/public/configuration.cc b/chromium/components/feature_engagement/public/configuration.cc
index 8bfaec44b2b..bde709171a7 100644
--- a/chromium/components/feature_engagement/public/configuration.cc
+++ b/chromium/components/feature_engagement/public/configuration.cc
@@ -7,7 +7,7 @@
#include <string>
#include "base/notreached.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feature_engagement {
namespace {
diff --git a/chromium/components/feature_engagement/public/configuration.h b/chromium/components/feature_engagement/public/configuration.h
index 08c959926ee..244ee94f8d1 100644
--- a/chromium/components/feature_engagement/public/configuration.h
+++ b/chromium/components/feature_engagement/public/configuration.h
@@ -12,7 +12,7 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
struct Feature;
@@ -102,7 +102,7 @@ struct SessionRateImpact {
// In the case of the Type |EXPLICIT|, this is the list of affected
// base::Feature names.
- base::Optional<std::vector<std::string>> affected_features;
+ absl::optional<std::vector<std::string>> affected_features;
};
bool operator==(const SessionRateImpact& lhs, const SessionRateImpact& rhs);
diff --git a/chromium/components/feature_engagement/public/event_constants.cc b/chromium/components/feature_engagement/public/event_constants.cc
index d1f26b4f615..b354db6a6a2 100644
--- a/chromium/components/feature_engagement/public/event_constants.cc
+++ b/chromium/components/feature_engagement/public/event_constants.cc
@@ -39,6 +39,10 @@ const char kWebUITabStripClosed[] = "webui_tab_strip_closed";
const char kWebUITabStripOpened[] = "webui_tab_strip_opened";
const char kDesktopPwaInstalled[] = "desktop_pwa_installed";
+
+const char kUpdatedConnectionSecurityIndicatorDisplayed[] =
+ "updated_connection_security_indicator_displayed";
+
#endif // defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) ||
// defined(OS_CHROMEOS)
diff --git a/chromium/components/feature_engagement/public/event_constants.h b/chromium/components/feature_engagement/public/event_constants.h
index 2fd6821f3c0..a81e8b7da7a 100644
--- a/chromium/components/feature_engagement/public/event_constants.h
+++ b/chromium/components/feature_engagement/public/event_constants.h
@@ -66,6 +66,9 @@ extern const char kWebUITabStripOpened[];
// The PWA was installed by the user.
extern const char kDesktopPwaInstalled[];
+// Omnibox displayed the updated connection security indicator.
+extern const char kUpdatedConnectionSecurityIndicatorDisplayed[];
+
#endif // defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) ||
// defined(OS_CHROMEOS)
diff --git a/chromium/components/feature_engagement/public/feature_configurations.cc b/chromium/components/feature_engagement/public/feature_configurations.cc
index 62c33be1a9b..452e753ad3a 100644
--- a/chromium/components/feature_engagement/public/feature_configurations.cc
+++ b/chromium/components/feature_engagement/public/feature_configurations.cc
@@ -10,12 +10,12 @@
namespace feature_engagement {
-base::Optional<FeatureConfig> GetClientSideFeatureConfig(
+absl::optional<FeatureConfig> GetClientSideFeatureConfig(
const base::Feature* feature) {
#if defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) || \
defined(OS_CHROMEOS)
if (kIPHPasswordsAccountStorageFeature.name == feature->name) {
- base::Optional<FeatureConfig> config = FeatureConfig();
+ absl::optional<FeatureConfig> config = FeatureConfig();
config->valid = true;
config->availability = Comparator(ANY, 0);
config->session_rate = Comparator(ANY, 0);
@@ -30,7 +30,7 @@ base::Optional<FeatureConfig> GetClientSideFeatureConfig(
}
if (kIPHProfileSwitchFeature.name == feature->name) {
- base::Optional<FeatureConfig> config = FeatureConfig();
+ absl::optional<FeatureConfig> config = FeatureConfig();
config->valid = true;
config->availability = Comparator(ANY, 0);
config->session_rate = Comparator(ANY, 0);
@@ -49,7 +49,7 @@ base::Optional<FeatureConfig> GetClientSideFeatureConfig(
constexpr int k10YearsInDays = 365 * 10;
if (kIPHDataSaverDetailFeature.name == feature->name) {
- base::Optional<FeatureConfig> config = FeatureConfig();
+ absl::optional<FeatureConfig> config = FeatureConfig();
config->valid = true;
config->availability = Comparator(ANY, 0);
config->session_rate = Comparator(EQUAL, 0);
@@ -63,7 +63,7 @@ base::Optional<FeatureConfig> GetClientSideFeatureConfig(
return config;
}
if (kIPHDataSaverPreviewFeature.name == feature->name) {
- base::Optional<FeatureConfig> config = FeatureConfig();
+ absl::optional<FeatureConfig> config = FeatureConfig();
config->valid = true;
config->availability = Comparator(ANY, 0);
config->session_rate = Comparator(EQUAL, 0);
@@ -74,7 +74,7 @@ base::Optional<FeatureConfig> GetClientSideFeatureConfig(
return config;
}
if (kIPHPreviewsOmniboxUIFeature.name == feature->name) {
- base::Optional<FeatureConfig> config = FeatureConfig();
+ absl::optional<FeatureConfig> config = FeatureConfig();
config->valid = true;
config->availability = Comparator(ANY, 0);
config->session_rate = Comparator(EQUAL, 0);
@@ -87,7 +87,7 @@ base::Optional<FeatureConfig> GetClientSideFeatureConfig(
return config;
}
if (kIPHDownloadHomeFeature.name == feature->name) {
- base::Optional<FeatureConfig> config = FeatureConfig();
+ absl::optional<FeatureConfig> config = FeatureConfig();
config->valid = true;
config->availability = Comparator(GREATER_THAN_OR_EQUAL, 14);
config->session_rate = Comparator(EQUAL, 0);
@@ -102,7 +102,7 @@ base::Optional<FeatureConfig> GetClientSideFeatureConfig(
if (kIPHDownloadIndicatorFeature.name == feature->name) {
// A config that allows the DownloadIndicator IPH to be shown up to 2 times,
// but only if download home hasn't been opened in the last 90 days.
- base::Optional<FeatureConfig> config = FeatureConfig();
+ absl::optional<FeatureConfig> config = FeatureConfig();
config->valid = true;
config->availability = Comparator(ANY, 0);
config->session_rate = Comparator(ANY, 0);
@@ -116,7 +116,7 @@ base::Optional<FeatureConfig> GetClientSideFeatureConfig(
// A config that allows the ExploreSites IPH to be shown:
// * Once per day
// * Up to 3 times but only if unused in the last 90 days.
- base::Optional<FeatureConfig> config = FeatureConfig();
+ absl::optional<FeatureConfig> config = FeatureConfig();
config->valid = true;
config->availability = Comparator(ANY, 0);
config->session_rate = Comparator(EQUAL, 0);
@@ -128,12 +128,45 @@ base::Optional<FeatureConfig> GetClientSideFeatureConfig(
Comparator(LESS_THAN, 1), 1, 360));
return config;
}
+ if (kIPHAddToHomescreenMessageFeature.name == feature->name) {
+ // A config that allows the Add to homescreen message IPH to be shown:
+ // * Once per 15 days
+ // * Up to 2 times but only if unused in the last 15 days.
+ absl::optional<FeatureConfig> config = FeatureConfig();
+ config->valid = true;
+ config->availability = Comparator(ANY, 0);
+ config->session_rate = Comparator(EQUAL, 0);
+ config->trigger = EventConfig("add_to_homescreen_message_iph_trigger",
+ Comparator(LESS_THAN, 2), 90, 90);
+ config->used = EventConfig("add_to_homescreen_dialog_shown",
+ Comparator(EQUAL, 0), 90, 90);
+ config->event_configs.insert(EventConfig(
+ "add_to_homescreen_message_iph_trigger", Comparator(EQUAL, 0), 15, 90));
+ return config;
+ }
+ if (kIPHAddToHomescreenTextBubbleFeature.name == feature->name) {
+ // A config that allows the Add to homescreen text bubble IPH to be shown:
+ // * Once per 15 days
+ // * Up to 2 times but only if unused in the last 15 days.
+ absl::optional<FeatureConfig> config = FeatureConfig();
+ config->valid = true;
+ config->availability = Comparator(ANY, 0);
+ config->session_rate = Comparator(EQUAL, 0);
+ config->trigger = EventConfig("add_to_homescreen_text_bubble_iph_trigger",
+ Comparator(LESS_THAN, 2), 90, 90);
+ config->used = EventConfig("add_to_homescreen_dialog_shown",
+ Comparator(EQUAL, 0), 90, 90);
+ config->event_configs.insert(
+ EventConfig("add_to_homescreen_text_bubble_iph_trigger",
+ Comparator(EQUAL, 0), 15, 90));
+ return config;
+ }
if (kIPHFeedHeaderMenuFeature.name == feature->name) {
// A config that allows the feed header menu IPH to be shown only once when
// the user starts using a version of the feed that uploads click and view
// actions.
- base::Optional<FeatureConfig> config = FeatureConfig();
+ absl::optional<FeatureConfig> config = FeatureConfig();
config->valid = true;
config->availability = Comparator(ANY, 0);
@@ -161,7 +194,7 @@ base::Optional<FeatureConfig> GetClientSideFeatureConfig(
if (kIPHDummyFeature.name == feature->name) {
// Only used for tests. Various magic tricks are used below to ensure this
// config is invalid and unusable.
- base::Optional<FeatureConfig> config = FeatureConfig();
+ absl::optional<FeatureConfig> config = FeatureConfig();
config->valid = false;
config->availability = Comparator(LESS_THAN, 0);
config->session_rate = Comparator(LESS_THAN, 0);
@@ -172,7 +205,7 @@ base::Optional<FeatureConfig> GetClientSideFeatureConfig(
return config;
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace feature_engagement
diff --git a/chromium/components/feature_engagement/public/feature_configurations.h b/chromium/components/feature_engagement/public/feature_configurations.h
index 717ffad199e..fe119a55216 100644
--- a/chromium/components/feature_engagement/public/feature_configurations.h
+++ b/chromium/components/feature_engagement/public/feature_configurations.h
@@ -5,7 +5,7 @@
#ifndef COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_FEATURE_CONFIGURATIONS_H_
#define COMPONENTS_FEATURE_ENGAGEMENT_PUBLIC_FEATURE_CONFIGURATIONS_H_
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
struct Feature;
@@ -17,7 +17,7 @@ struct FeatureConfig;
// Returns client-side specified FeatureConfig if it exists, else an empty
// optional. For this FeatureConfig to be usable, the feature also needs to
// be enabled by default.
-base::Optional<FeatureConfig> GetClientSideFeatureConfig(
+absl::optional<FeatureConfig> GetClientSideFeatureConfig(
const base::Feature* feature);
} // namespace feature_engagement
diff --git a/chromium/components/feature_engagement/public/feature_constants.cc b/chromium/components/feature_engagement/public/feature_constants.cc
index 97d9dd149d3..f694d963967 100644
--- a/chromium/components/feature_engagement/public/feature_constants.cc
+++ b/chromium/components/feature_engagement/public/feature_constants.cc
@@ -23,7 +23,7 @@ const base::Feature kIPHGlobalMediaControlsFeature{
const base::Feature kIPHLiveCaptionFeature{"IPH_LiveCaption",
base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kIPHPasswordsAccountStorageFeature{
- "IPH_PasswordsAccountStorage", base::FEATURE_DISABLED_BY_DEFAULT};
+ "IPH_PasswordsAccountStorage", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kIPHReadingListDiscoveryFeature{
"IPH_ReadingListDiscovery", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHReadingListEntryPointFeature{
@@ -38,10 +38,24 @@ const base::Feature kIPHDesktopPwaInstallFeature{
"IPH_DesktopPwaInstall", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHProfileSwitchFeature{"IPH_ProfileSwitch",
base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kIPHUpdatedConnectionSecurityIndicatorsFeature{
+ "IPH_UpdatedConnectionSecurityIndicators",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
#endif // defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) ||
// defined(OS_CHROMEOS)
#if defined(OS_ANDROID)
+const base::Feature kIPHAdaptiveButtonInTopToolbarCustomizationNewTabFeature{
+ "IPH_AdaptiveButtonInTopToolbarCustomization_NewTab",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kIPHAdaptiveButtonInTopToolbarCustomizationShareFeature{
+ "IPH_AdaptiveButtonInTopToolbarCustomization_Share",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature
+ kIPHAdaptiveButtonInTopToolbarCustomizationVoiceSearchFeature{
+ "IPH_AdaptiveButtonInTopToolbarCustomization_VoiceSearch",
+ base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHAddToHomescreenMessageFeature{
"IPH_AddToHomescreenMessage", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kIPHAddToHomescreenTextBubbleFeature{
@@ -154,9 +168,15 @@ const base::Feature kIPHChromeReengagementNotification2Feature{
const base::Feature kIPHChromeReengagementNotification3Feature{
"IPH_ChromeReengagementNotification3", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHPwaInstallAvailableFeature{
- "IPH_PwaInstallAvailable", base::FEATURE_DISABLED_BY_DEFAULT};
+ "IPH_PwaInstallAvailableFeature", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kIPHShareScreenshotFeature{
"IPH_ShareScreenshot", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kIPHWebFeedFollowFeature{"IPH_WebFeedFollow",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kIPHWebFeedPostFollowDialogFeature{
+ "IPH_WebFeedPostFollowDialog", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kIPHSharedHighlightingBuilder{
+ "IPH_SharedHighlightingBuilder", base::FEATURE_DISABLED_BY_DEFAULT};
#endif // defined(OS_ANDROID)
#if defined(OS_IOS)
diff --git a/chromium/components/feature_engagement/public/feature_constants.h b/chromium/components/feature_engagement/public/feature_constants.h
index d4ad174e39c..bb59c2ad7be 100644
--- a/chromium/components/feature_engagement/public/feature_constants.h
+++ b/chromium/components/feature_engagement/public/feature_constants.h
@@ -30,6 +30,7 @@ extern const base::Feature kIPHWebUITabStripFeature;
extern const base::Feature kIPHDesktopSnoozeFeature;
extern const base::Feature kIPHDesktopPwaInstallFeature;
extern const base::Feature kIPHProfileSwitchFeature;
+extern const base::Feature kIPHUpdatedConnectionSecurityIndicatorsFeature;
#endif // defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) ||
// defined(OS_CHROMEOS)
@@ -37,6 +38,12 @@ extern const base::Feature kIPHProfileSwitchFeature;
// should also be declared in:
// org.chromium.components.feature_engagement.FeatureConstants.
#if defined(OS_ANDROID)
+extern const base::Feature
+ kIPHAdaptiveButtonInTopToolbarCustomizationNewTabFeature;
+extern const base::Feature
+ kIPHAdaptiveButtonInTopToolbarCustomizationShareFeature;
+extern const base::Feature
+ kIPHAdaptiveButtonInTopToolbarCustomizationVoiceSearchFeature;
extern const base::Feature kIPHAddToHomescreenMessageFeature;
extern const base::Feature kIPHAddToHomescreenTextBubbleFeature;
extern const base::Feature kIPHDataSaverDetailFeature;
@@ -96,6 +103,9 @@ extern const base::Feature kIPHChromeReengagementNotification2Feature;
extern const base::Feature kIPHChromeReengagementNotification3Feature;
extern const base::Feature kIPHPwaInstallAvailableFeature;
extern const base::Feature kIPHShareScreenshotFeature;
+extern const base::Feature kIPHWebFeedFollowFeature;
+extern const base::Feature kIPHWebFeedPostFollowDialogFeature;
+extern const base::Feature kIPHSharedHighlightingBuilder;
#endif // defined(OS_ANDROID)
#if defined(OS_IOS)
diff --git a/chromium/components/feature_engagement/public/feature_list.cc b/chromium/components/feature_engagement/public/feature_list.cc
index 4f3547f4e61..a9532bc25fa 100644
--- a/chromium/components/feature_engagement/public/feature_list.cc
+++ b/chromium/components/feature_engagement/public/feature_list.cc
@@ -16,6 +16,9 @@ namespace {
const base::Feature* const kAllFeatures[] = {
&kIPHDummyFeature, // Ensures non-empty array for all platforms.
#if defined(OS_ANDROID)
+ &kIPHAdaptiveButtonInTopToolbarCustomizationNewTabFeature,
+ &kIPHAdaptiveButtonInTopToolbarCustomizationShareFeature,
+ &kIPHAdaptiveButtonInTopToolbarCustomizationVoiceSearchFeature,
&kIPHAddToHomescreenMessageFeature,
&kIPHAddToHomescreenTextBubbleFeature,
&kIPHDataSaverDetailFeature,
@@ -73,6 +76,9 @@ const base::Feature* const kAllFeatures[] = {
&kIPHExploreSitesTileFeature,
&kIPHFeedHeaderMenuFeature,
&kIPHShareScreenshotFeature,
+ &kIPHWebFeedFollowFeature,
+ &kIPHWebFeedPostFollowDialogFeature,
+ &kIPHSharedHighlightingBuilder,
#endif // defined(OS_ANDROID)
#if defined(OS_IOS)
&kIPHBottomToolbarTipFeature,
@@ -96,6 +102,7 @@ const base::Feature* const kAllFeatures[] = {
&kIPHWebUITabStripFeature,
&kIPHDesktopPwaInstallFeature,
&kIPHProfileSwitchFeature,
+ &kIPHUpdatedConnectionSecurityIndicatorsFeature,
#endif // defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) ||
// defined(OS_CHROMEOS)
};
diff --git a/chromium/components/feature_engagement/public/feature_list.h b/chromium/components/feature_engagement/public/feature_list.h
index dbb1794cfbf..19fc5d2ce43 100644
--- a/chromium/components/feature_engagement/public/feature_list.h
+++ b/chromium/components/feature_engagement/public/feature_list.h
@@ -46,6 +46,13 @@ namespace {
// Defines a flags_ui::FeatureEntry::FeatureParam for each feature.
DEFINE_VARIATION_PARAM(kIPHDummyFeature, "IPH_Dummy");
#if defined(OS_ANDROID)
+DEFINE_VARIATION_PARAM(kIPHAdaptiveButtonInTopToolbarCustomizationNewTabFeature,
+ "IPH_AdaptiveButtonInTopToolbarCustomization_NewTab");
+DEFINE_VARIATION_PARAM(kIPHAdaptiveButtonInTopToolbarCustomizationShareFeature,
+ "IPH_AdaptiveButtonInTopToolbarCustomization_Share");
+DEFINE_VARIATION_PARAM(
+ kIPHAdaptiveButtonInTopToolbarCustomizationVoiceSearchFeature,
+ "IPH_AdaptiveButtonInTopToolbarCustomization_VoiceSearch");
DEFINE_VARIATION_PARAM(kIPHAddToHomescreenMessageFeature,
"IPH_AddToHomescreenMessage");
DEFINE_VARIATION_PARAM(kIPHAddToHomescreenTextBubbleFeature,
@@ -141,6 +148,11 @@ DEFINE_VARIATION_PARAM(kIPHVideoTutorialNTPSummaryFeature,
DEFINE_VARIATION_PARAM(kIPHExploreSitesTileFeature, "IPH_ExploreSitesTile");
DEFINE_VARIATION_PARAM(kIPHFeedHeaderMenuFeature, "IPH_FeedHeaderMenu");
DEFINE_VARIATION_PARAM(kIPHShareScreenshotFeature, "IPH_ShareScreenshot");
+DEFINE_VARIATION_PARAM(kIPHWebFeedFollowFeature, "IPH_WebFeedFollow");
+DEFINE_VARIATION_PARAM(kIPHWebFeedPostFollowDialogFeature,
+ "IPH_WebFeedPostFollowDialog");
+DEFINE_VARIATION_PARAM(kIPHSharedHighlightingBuilder,
+ "IPH_SharedHighlightingBuilder");
#endif // defined(OS_ANDROID)
#if defined(OS_IOS)
DEFINE_VARIATION_PARAM(kIPHBottomToolbarTipFeature, "IPH_BottomToolbarTip");
@@ -172,6 +184,8 @@ DEFINE_VARIATION_PARAM(kIPHReopenTabFeature, "IPH_ReopenTab");
DEFINE_VARIATION_PARAM(kIPHWebUITabStripFeature, "IPH_WebUITabStrip");
DEFINE_VARIATION_PARAM(kIPHDesktopPwaInstallFeature, "IPH_DesktopPwaInstall");
DEFINE_VARIATION_PARAM(kIPHProfileSwitchFeature, "IPH_ProfileSwitch");
+DEFINE_VARIATION_PARAM(kIPHUpdatedConnectionSecurityIndicatorsFeature,
+ "IPH_UpdatedConnectionSecurityIndicators");
#endif // defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) ||
// defined(OS_CHROMEOS)
@@ -183,6 +197,12 @@ DEFINE_VARIATION_PARAM(kIPHProfileSwitchFeature, "IPH_ProfileSwitch");
constexpr flags_ui::FeatureEntry::FeatureVariation
kIPHDemoModeChoiceVariations[] = {
#if defined(OS_ANDROID)
+ VARIATION_ENTRY(
+ kIPHAdaptiveButtonInTopToolbarCustomizationNewTabFeature),
+ VARIATION_ENTRY(
+ kIPHAdaptiveButtonInTopToolbarCustomizationShareFeature),
+ VARIATION_ENTRY(
+ kIPHAdaptiveButtonInTopToolbarCustomizationVoiceSearchFeature),
VARIATION_ENTRY(kIPHAddToHomescreenMessageFeature),
VARIATION_ENTRY(kIPHAddToHomescreenTextBubbleFeature),
VARIATION_ENTRY(kIPHDataSaverDetailFeature),
@@ -240,6 +260,9 @@ constexpr flags_ui::FeatureEntry::FeatureVariation
VARIATION_ENTRY(kIPHExploreSitesTileFeature),
VARIATION_ENTRY(kIPHFeedHeaderMenuFeature),
VARIATION_ENTRY(kIPHShareScreenshotFeature),
+ VARIATION_ENTRY(kIPHWebFeedFollowFeature),
+ VARIATION_ENTRY(kIPHWebFeedPostFollowDialogFeature),
+ VARIATION_ENTRY(kIPHSharedHighlightingBuilder),
#elif defined(OS_IOS)
VARIATION_ENTRY(kIPHBottomToolbarTipFeature),
VARIATION_ENTRY(kIPHLongPressToolbarTipFeature),
@@ -248,7 +271,7 @@ constexpr flags_ui::FeatureEntry::FeatureVariation
VARIATION_ENTRY(kIPHBadgedReadingListFeature),
VARIATION_ENTRY(kIPHBadgedTranslateManualTriggerFeature),
VARIATION_ENTRY(kIPHDiscoverFeedHeaderFeature),
-#elif defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) || \
+#elif defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) || \
defined(OS_CHROMEOS)
VARIATION_ENTRY(kIPHDesktopTabGroupsNewGroupFeature),
VARIATION_ENTRY(kIPHFocusModeFeature),
@@ -261,7 +284,8 @@ constexpr flags_ui::FeatureEntry::FeatureVariation
VARIATION_ENTRY(kIPHWebUITabStripFeature),
VARIATION_ENTRY(kIPHDesktopPwaInstallFeature),
VARIATION_ENTRY(kIPHProfileSwitchFeature),
-#endif // defined(OS_WIN) || defined(OS_APPLE) || defined(OS_LINUX) ||
+ VARIATION_ENTRY(kIPHUpdatedConnectionSecurityIndicatorsFeature),
+#endif // defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) ||
// defined(OS_CHROMEOS)
};
diff --git a/chromium/components/federated_learning/features/features.cc b/chromium/components/federated_learning/features/features.cc
index 16d550c7b5d..9647df0c469 100644
--- a/chromium/components/federated_learning/features/features.cc
+++ b/chromium/components/federated_learning/features/features.cc
@@ -8,6 +8,12 @@
namespace federated_learning {
+// If enabled, the check for whether the IP address is publicly routable will be
+// bypassed when determining the eligibility for a page to be included in floc
+// computation. This is useful for developers to test FLoC in local environment.
+const base::Feature kFlocBypassIPIsPubliclyRoutableCheck{
+ "FlocBypassIPIsPubliclyRoutableCheck", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables or disables the FlocIdComputed event logging, which happens when a
// floc id is first computed for a browsing session or is refreshed due to a
// long period of time has passed since the last computation.
diff --git a/chromium/components/federated_learning/features/features.h b/chromium/components/federated_learning/features/features.h
index 9b1d00a01ab..2de1234c788 100644
--- a/chromium/components/federated_learning/features/features.h
+++ b/chromium/components/federated_learning/features/features.h
@@ -6,9 +6,11 @@
#define COMPONENTS_FEDERATED_LEARNING_FEATURES_FEATURES_H_
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
namespace federated_learning {
+extern const base::Feature kFlocBypassIPIsPubliclyRoutableCheck;
extern const base::Feature kFlocIdComputedEventLogging;
extern const base::Feature
kFlocPagesWithAdResourcesDefaultIncludedInFlocComputation;
@@ -20,4 +22,4 @@ extern const base::FeatureParam<int> kFlocIdFinchConfigVersion;
} // namespace federated_learning
-#endif // COMPONENTS_FEDERATED_LEARNING_FEATURES_FEATURES_H_ \ No newline at end of file
+#endif // COMPONENTS_FEDERATED_LEARNING_FEATURES_FEATURES_H_
diff --git a/chromium/components/federated_learning/floc_id.cc b/chromium/components/federated_learning/floc_id.cc
index 06eeef0ba50..bf6e43cec0e 100644
--- a/chromium/components/federated_learning/floc_id.cc
+++ b/chromium/components/federated_learning/floc_id.cc
@@ -108,9 +108,15 @@ void FlocId::InvalidateIdAndSaveToPrefs(PrefService* prefs) {
prefs->ClearPref(kFlocIdValuePrefKey);
}
+void FlocId::ResetComputeTimeAndSaveToPrefs(base::Time compute_time,
+ PrefService* prefs) {
+ compute_time_ = compute_time;
+ prefs->SetTime(kFlocIdComputeTimePrefKey, compute_time_);
+}
+
// static
FlocId FlocId::ReadFromPrefs(PrefService* prefs) {
- base::Optional<uint64_t> id;
+ absl::optional<uint64_t> id;
if (prefs->HasPrefPath(kFlocIdValuePrefKey))
id = prefs->GetUint64(kFlocIdValuePrefKey);
@@ -121,7 +127,7 @@ FlocId FlocId::ReadFromPrefs(PrefService* prefs) {
prefs->GetTime(kFlocIdComputeTimePrefKey));
}
-FlocId::FlocId(base::Optional<uint64_t> id,
+FlocId::FlocId(absl::optional<uint64_t> id,
base::Time history_begin_time,
base::Time history_end_time,
uint32_t finch_config_version,
diff --git a/chromium/components/federated_learning/floc_id.h b/chromium/components/federated_learning/floc_id.h
index e0451d67903..f119fed6b8a 100644
--- a/chromium/components/federated_learning/floc_id.h
+++ b/chromium/components/federated_learning/floc_id.h
@@ -5,10 +5,10 @@
#ifndef COMPONENTS_FEDERATED_LEARNING_FLOC_ID_H_
#define COMPONENTS_FEDERATED_LEARNING_FLOC_ID_H_
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/version.h"
#include "components/prefs/prefs_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/federated_learning/floc.mojom-forward.h"
#include <stdint.h>
@@ -84,19 +84,25 @@ class FlocId {
// other unaffected field.
void InvalidateIdAndSaveToPrefs(PrefService* prefs);
+ // Resets |compute_time_| to provided |compute_time| and saves it to prefs.
+ // This should at least be called if the floc compute timer is reset, to
+ // ensure that the compute cycle continues at the expected frequency.
+ void ResetComputeTimeAndSaveToPrefs(base::Time compute_time,
+ PrefService* prefs);
+
private:
friend class FlocIdTester;
// Create a floc with stated params. This will only be used to create a floc
// read from prefs.
- explicit FlocId(base::Optional<uint64_t> id,
+ explicit FlocId(absl::optional<uint64_t> id,
base::Time history_begin_time,
base::Time history_end_time,
uint32_t finch_config_version,
uint32_t sorting_lsh_version,
base::Time compute_time);
- base::Optional<uint64_t> id_;
+ absl::optional<uint64_t> id_;
// The time range of the actual history used to compute the floc. This should
// always be within the time range of each history query.
diff --git a/chromium/components/federated_learning/floc_id_unittest.cc b/chromium/components/federated_learning/floc_id_unittest.cc
index 4c01b51e41c..84bee39eaec 100644
--- a/chromium/components/federated_learning/floc_id_unittest.cc
+++ b/chromium/components/federated_learning/floc_id_unittest.cc
@@ -205,4 +205,17 @@ TEST_F(FlocIdUnitTest, InvalidateIdAndSaveToPrefs) {
EXPECT_EQ(base::Time::Now(), prefs.GetTime(kFlocIdComputeTimePrefKey));
}
+TEST_F(FlocIdUnitTest, ResetComputeTimeAndSaveToPrefs) {
+ TestingPrefServiceSimple prefs;
+ FlocId::RegisterPrefs(prefs.registry());
+
+ FlocId floc_id =
+ FlocId(123, base::Time::FromTimeT(1), base::Time::FromTimeT(2), 3);
+ floc_id.SaveToPrefs(&prefs);
+ EXPECT_EQ(base::Time::Now(), prefs.GetTime(kFlocIdComputeTimePrefKey));
+
+ floc_id.ResetComputeTimeAndSaveToPrefs(base::Time::FromTimeT(4), &prefs);
+ EXPECT_EQ(base::Time::FromTimeT(4), prefs.GetTime(kFlocIdComputeTimePrefKey));
+}
+
} // namespace federated_learning
diff --git a/chromium/components/federated_learning/floc_sorting_lsh_clusters_service.cc b/chromium/components/federated_learning/floc_sorting_lsh_clusters_service.cc
index 01da1c1839b..9325bacccd2 100644
--- a/chromium/components/federated_learning/floc_sorting_lsh_clusters_service.cc
+++ b/chromium/components/federated_learning/floc_sorting_lsh_clusters_service.cc
@@ -37,13 +37,13 @@ class CopyingFileInputStream : public google::protobuf::io::CopyingInputStream {
base::File file_;
};
-base::Optional<uint64_t> ApplySortingLshOnBackgroundThread(
+absl::optional<uint64_t> ApplySortingLshOnBackgroundThread(
uint64_t sim_hash,
const base::FilePath& file_path) {
base::File sorting_lsh_clusters_file(
file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!sorting_lsh_clusters_file.IsValid())
- return base::nullopt;
+ return absl::nullopt;
CopyingFileInputStream copying_stream(std::move(sorting_lsh_clusters_file));
google::protobuf::io::CopyingInputStreamAdaptor zero_copy_stream_adaptor(
@@ -89,25 +89,25 @@ base::Optional<uint64_t> ApplySortingLshOnBackgroundThread(
for (uint64_t index = 0; input_stream.ReadVarint32(&next_combined); ++index) {
// Sanitizing error: the entry used more than |kSortingLshMaxBits| bits.
if ((next_combined >> kSortingLshMaxBits) > 0)
- return base::nullopt;
+ return absl::nullopt;
bool is_blocked = next_combined & kSortingLshBlockedMask;
uint32_t next = next_combined & kSortingLshSizeMask;
// Sanitizing error
if (next > kMaxNumberOfBitsInFloc)
- return base::nullopt;
+ return absl::nullopt;
cumulative_sum += (1ULL << next);
// Sanitizing error
if (cumulative_sum > kExpectedFinalCumulativeSum)
- return base::nullopt;
+ return absl::nullopt;
// Found the sim-hash upper bound. Use the index as the new floc.
if (cumulative_sum > sim_hash) {
if (is_blocked)
- return base::nullopt;
+ return absl::nullopt;
return index;
}
@@ -115,7 +115,7 @@ base::Optional<uint64_t> ApplySortingLshOnBackgroundThread(
// Sanitizing error: we didn't find a sim-hash upper bound, but we expect to
// always find it after finish iterating through the list.
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace
@@ -173,7 +173,7 @@ void FlocSortingLshClustersService::SetBackgroundTaskRunnerForTesting(
void FlocSortingLshClustersService::DidApplySortingLsh(
ApplySortingLshCallback callback,
base::Version version,
- base::Optional<uint64_t> final_hash) {
+ absl::optional<uint64_t> final_hash) {
std::move(callback).Run(std::move(final_hash), std::move(version));
}
diff --git a/chromium/components/federated_learning/floc_sorting_lsh_clusters_service.h b/chromium/components/federated_learning/floc_sorting_lsh_clusters_service.h
index 43d6f625b50..443b77c2c32 100644
--- a/chromium/components/federated_learning/floc_sorting_lsh_clusters_service.h
+++ b/chromium/components/federated_learning/floc_sorting_lsh_clusters_service.h
@@ -12,9 +12,9 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/version.h"
#include "components/federated_learning/floc_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class FilePath;
@@ -30,7 +30,7 @@ namespace federated_learning {
class FlocSortingLshClustersService {
public:
using ApplySortingLshCallback =
- base::OnceCallback<void(base::Optional<uint64_t>, base::Version)>;
+ base::OnceCallback<void(absl::optional<uint64_t>, base::Version)>;
class Observer {
public:
@@ -66,7 +66,7 @@ class FlocSortingLshClustersService {
void DidApplySortingLsh(ApplySortingLshCallback callback,
base::Version version,
- base::Optional<uint64_t> final_hash);
+ absl::optional<uint64_t> final_hash);
// Runner for tasks that do not influence user experience.
scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
diff --git a/chromium/components/federated_learning/floc_sorting_lsh_clusters_service_unittest.cc b/chromium/components/federated_learning/floc_sorting_lsh_clusters_service_unittest.cc
index bf89c1c91a5..9e9de368649 100644
--- a/chromium/components/federated_learning/floc_sorting_lsh_clusters_service_unittest.cc
+++ b/chromium/components/federated_learning/floc_sorting_lsh_clusters_service_unittest.cc
@@ -46,7 +46,7 @@ class CopyingFileOutputStream
};
struct ApplySortingLshResult {
- base::Optional<uint64_t> final_hash;
+ absl::optional<uint64_t> final_hash;
base::Version version;
};
@@ -115,9 +115,9 @@ class FlocSortingLshClustersServiceTest : public ::testing::Test {
FlocSortingLshClustersService* service() { return service_.get(); }
- base::Optional<base::FilePath> sorting_lsh_clusters_file_path() {
+ absl::optional<base::FilePath> sorting_lsh_clusters_file_path() {
if (!service()->first_file_ready_seen_)
- return base::nullopt;
+ return absl::nullopt;
return service()->sorting_lsh_clusters_file_path_;
}
@@ -127,7 +127,7 @@ class FlocSortingLshClustersServiceTest : public ::testing::Test {
base::RunLoop run_loop;
auto cb = base::BindLambdaForTesting(
- [&](base::Optional<uint64_t> final_hash, base::Version version) {
+ [&](absl::optional<uint64_t> final_hash, base::Version version) {
result.final_hash = final_hash;
result.version = version;
run_loop.Quit();
@@ -157,9 +157,9 @@ TEST_F(FlocSortingLshClustersServiceTest, NoFilePath) {
TEST_F(FlocSortingLshClustersServiceTest, EmptyList) {
InitializeSortingLshClustersFile({}, base::Version("2.3.4"));
- EXPECT_EQ(base::nullopt, ApplySortingLsh(0).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(1).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(0).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(1).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
}
TEST_F(FlocSortingLshClustersServiceTest, List_0) {
@@ -167,24 +167,24 @@ TEST_F(FlocSortingLshClustersServiceTest, List_0) {
EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
EXPECT_EQ(base::Version("2.3.4"), ApplySortingLsh(0).version);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(1).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(1).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
}
TEST_F(FlocSortingLshClustersServiceTest, List_0_Blocked) {
InitializeSortingLshClustersFile({{0, true}}, base::Version("2.3.4"));
- EXPECT_EQ(base::nullopt, ApplySortingLsh(0).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(1).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(0).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(1).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
}
TEST_F(FlocSortingLshClustersServiceTest, List_UnexpectedNumber) {
InitializeSortingLshClustersFile({{1 << 8, false}}, base::Version("2.3.4"));
- EXPECT_EQ(base::nullopt, ApplySortingLsh(0).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(1).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(0).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(1).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
}
TEST_F(FlocSortingLshClustersServiceTest, List_1) {
@@ -192,8 +192,8 @@ TEST_F(FlocSortingLshClustersServiceTest, List_1) {
EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
EXPECT_EQ(0u, ApplySortingLsh(1).final_hash.value());
- EXPECT_EQ(base::nullopt, ApplySortingLsh(2).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(2).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
}
TEST_F(FlocSortingLshClustersServiceTest, List_0_0) {
@@ -202,8 +202,8 @@ TEST_F(FlocSortingLshClustersServiceTest, List_0_0) {
EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
EXPECT_EQ(1u, ApplySortingLsh(1).final_hash.value());
- EXPECT_EQ(base::nullopt, ApplySortingLsh(2).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(2).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
}
TEST_F(FlocSortingLshClustersServiceTest, List_0_1) {
@@ -213,8 +213,8 @@ TEST_F(FlocSortingLshClustersServiceTest, List_0_1) {
EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
EXPECT_EQ(1u, ApplySortingLsh(1).final_hash.value());
EXPECT_EQ(1u, ApplySortingLsh(2).final_hash.value());
- EXPECT_EQ(base::nullopt, ApplySortingLsh(3).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(3).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
}
TEST_F(FlocSortingLshClustersServiceTest, List_1_0) {
@@ -224,8 +224,8 @@ TEST_F(FlocSortingLshClustersServiceTest, List_1_0) {
EXPECT_EQ(0u, ApplySortingLsh(0).final_hash.value());
EXPECT_EQ(0u, ApplySortingLsh(1).final_hash.value());
EXPECT_EQ(1u, ApplySortingLsh(2).final_hash.value());
- EXPECT_EQ(base::nullopt, ApplySortingLsh(3).final_hash);
- EXPECT_EQ(base::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(3).final_hash);
+ EXPECT_EQ(absl::nullopt, ApplySortingLsh(kMaxSimHash).final_hash);
}
TEST_F(FlocSortingLshClustersServiceTest, List_SingleCluster) {
@@ -259,9 +259,9 @@ TEST_F(FlocSortingLshClustersServiceTest,
base::RunLoop run_loop;
auto cb = base::BindLambdaForTesting(
- [&](base::Optional<uint64_t> final_hash, base::Version version) {
+ [&](absl::optional<uint64_t> final_hash, base::Version version) {
// Since the file has been deleted, expect an invalid final_hash.
- EXPECT_EQ(base::nullopt, final_hash);
+ EXPECT_EQ(absl::nullopt, final_hash);
EXPECT_EQ(base::Version("2.3.4"), version);
run_loop.Quit();
});
diff --git a/chromium/components/feed/DEPS b/chromium/components/feed/DEPS
index 2bac831fea2..73fd9bb39b2 100644
--- a/chromium/components/feed/DEPS
+++ b/chromium/components/feed/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+components/image_fetcher",
+ "+components/url_matcher",
"+components/history/core/browser",
"+components/keyed_service/core",
"+components/leveldb_proto",
diff --git a/chromium/components/feed/content/renderer/BUILD.gn b/chromium/components/feed/content/renderer/BUILD.gn
new file mode 100644
index 00000000000..7d6c587f931
--- /dev/null
+++ b/chromium/components/feed/content/renderer/BUILD.gn
@@ -0,0 +1,11 @@
+static_library("feed_renderer") {
+ sources = [
+ "rss_link_reader.cc",
+ "rss_link_reader.h",
+ ]
+ deps = [
+ "//components/feed/mojom:mojo_bindings",
+ "//content/public/renderer",
+ "//third_party/blink/public:blink_headers",
+ ]
+}
diff --git a/chromium/components/feed/content/renderer/DEPS b/chromium/components/feed/content/renderer/DEPS
new file mode 100644
index 00000000000..dd7005314a0
--- /dev/null
+++ b/chromium/components/feed/content/renderer/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+ "+content/public",
+ "+third_party/blink/public/platform",
+ "+third_party/blink/public/web",
+ "+mojo/public",
+ "+services/service_manager/public",
+]
diff --git a/chromium/components/feed/content/renderer/rss_link_reader.cc b/chromium/components/feed/content/renderer/rss_link_reader.cc
new file mode 100644
index 00000000000..86d7402098d
--- /dev/null
+++ b/chromium/components/feed/content/renderer/rss_link_reader.cc
@@ -0,0 +1,81 @@
+// Copyright 2021 The Chromium Authors. 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/feed/content/renderer/rss_link_reader.h"
+
+#include "components/feed/mojom/rss_link_reader.mojom.h"
+#include "content/public/renderer/render_frame.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/web/web_document.h"
+#include "third_party/blink/public/web/web_element.h"
+#include "third_party/blink/public/web/web_element_collection.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+
+namespace feed {
+namespace {
+
+// Maximum number of RSS URLs to read.
+constexpr int kMaxRssUrls = 50;
+
+// Returns the RSS URL embedded in `link_element`, or any empty GURL if no RSS
+// url is contained.
+GURL GetRssUrlFromLinkElement(const blink::WebDocument& document,
+ const blink::WebElement& link_element) {
+ GURL result;
+ if (link_element.HasAttribute("type") && link_element.HasAttribute("href")) {
+ blink::WebString type = link_element.GetAttribute("type");
+ if (type.Equals("application/rss+xml") ||
+ type.Equals("application/rss+atom") ||
+ type.Equals("application/atom+xml")) {
+ blink::WebURL url =
+ document.CompleteURL(link_element.GetAttribute("href"));
+ if (url.IsValid())
+ result = url;
+ }
+ }
+ return result;
+}
+
+} // namespace
+
+RssLinkReader::RssLinkReader(content::RenderFrame* render_frame,
+ service_manager::BinderRegistry* registry)
+ : content::RenderFrameObserver(render_frame) {
+ // Being a RenderFrameObserver, this object is scoped to the RenderFrame.
+ // Unretained is safe here because `registry` is also scoped to the
+ // RenderFrame.
+ registry->AddInterface(base::BindRepeating(&RssLinkReader::BindReceiver,
+ base::Unretained(this)));
+}
+
+RssLinkReader::~RssLinkReader() = default;
+
+void RssLinkReader::GetRssLinks(GetRssLinksCallback callback) {
+ std::vector<GURL> rss_urls;
+ blink::WebDocument document = render_frame()->GetWebFrame()->GetDocument();
+ const blink::WebElement head = document.Head();
+ blink::WebElementCollection link_iter = head.GetElementsByHTMLTagName("link");
+ for (blink::WebElement element = link_iter.FirstItem();
+ !element.IsNull() && rss_urls.size() < kMaxRssUrls;
+ element = link_iter.NextItem()) {
+ GURL url = GetRssUrlFromLinkElement(document, element);
+ if (url.is_valid())
+ rss_urls.push_back(url);
+ }
+ std::move(callback).Run(
+ mojom::RssLinks::New(document.Url(), std::move(rss_urls)));
+}
+
+void RssLinkReader::OnDestruct() {
+ delete this;
+}
+
+void RssLinkReader::BindReceiver(
+ mojo::PendingReceiver<mojom::RssLinkReader> receiver) {
+ receiver_.reset();
+ receiver_.Bind(std::move(receiver));
+}
+
+} // namespace feed
diff --git a/chromium/components/feed/content/renderer/rss_link_reader.h b/chromium/components/feed/content/renderer/rss_link_reader.h
new file mode 100644
index 00000000000..cd89997fe9f
--- /dev/null
+++ b/chromium/components/feed/content/renderer/rss_link_reader.h
@@ -0,0 +1,40 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FEED_CONTENT_RENDERER_RSS_LINK_READER_H_
+#define COMPONENTS_FEED_CONTENT_RENDERER_RSS_LINK_READER_H_
+
+#include "components/feed/mojom/rss_link_reader.mojom.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+
+namespace content {
+class RenderFrame;
+}
+namespace feed {
+
+// Implements mojom::RssLinkReader, see rss_link_reader.mojom.
+class RssLinkReader : public content::RenderFrameObserver,
+ public mojom::RssLinkReader {
+ public:
+ explicit RssLinkReader(content::RenderFrame* render_frame,
+ service_manager::BinderRegistry* registry);
+ ~RssLinkReader() override;
+
+ // mojom::RssLinkReader
+ void GetRssLinks(GetRssLinksCallback callback) override;
+
+ // content::RenderFrameObserver
+ void OnDestruct() override;
+
+ private:
+ void BindReceiver(mojo::PendingReceiver<mojom::RssLinkReader> receiver);
+
+ mojo::Receiver<mojom::RssLinkReader> receiver_{this};
+};
+
+} // namespace feed
+
+#endif // COMPONENTS_FEED_CONTENT_RENDERER_RSS_LINK_READER_H_
diff --git a/chromium/components/feed/core/common/pref_names.cc b/chromium/components/feed/core/common/pref_names.cc
index 7ca3d2ecec9..085e32b26e2 100644
--- a/chromium/components/feed/core/common/pref_names.cc
+++ b/chromium/components/feed/core/common/pref_names.cc
@@ -40,12 +40,17 @@ const char kClientInstanceId[] = "feedv2.client_instance_id";
// This pref applies to all discover APIs despite the string.
const char kDiscoverAPIEndpointOverride[] = "feedv2.actions_endpoint_override";
const char kExperiments[] = "feedv2.experiments";
-const char kEnableWebFeedUI[] = "webfeed_ui.enable";
+const char kEnableWebFeedFollowIntroDebug[] =
+ "webfeed_follow_intro_debug.enable";
+const char kReliabilityLoggingIdSalt[] = "feedv2.reliability_logging_id_salt";
+const char kIsWebFeedSubscriber[] = "webfeed.is_subscriber";
+const char kHasStoredData[] = "feedv2.has_stored_data";
} // namespace prefs
// Deprecated prefs:
namespace {
+// Deprecated 02/2021
const char kLastRefreshWasSignedIn[] = "feed.last_refresh_was_signed_in";
const char kBackgroundRefreshPeriod[] = "feed.background_refresh_period";
const char kThrottlerRequestCount[] = "feed.refresh_throttler.count";
@@ -54,18 +59,19 @@ const char kUserClassifierAverageSuggestionsViwedPerHour[] =
"feed.user_classifier.average_suggestions_veiwed_per_hour";
const char kUserClassifierAverageSuggestionsUsedPerHour[] =
"feed.user_classifier.average_suggestions_used_per_hour";
-
const char kUserClassifierLastTimeToViewSuggestions[] =
"feed.user_classifier.last_time_to_view_suggestions";
const char kUserClassifierLastTimeToUseSuggestions[] =
"feed.user_classifier.last_time_to_use_suggestions";
+// Deprecated 05/2021 (can be removed along with 02/2021)
+const char kEnableWebFeedUI[] = "webfeed_ui.enable";
+
void RegisterObsoletePrefsFeb_2021(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(kLastRefreshWasSignedIn, false);
registry->RegisterTimeDeltaPref(kBackgroundRefreshPeriod, base::TimeDelta());
registry->RegisterIntegerPref(kThrottlerRequestCount, 0);
registry->RegisterIntegerPref(kThrottlerRequestsDay, 0);
-
registry->RegisterDoublePref(kUserClassifierAverageSuggestionsViwedPerHour,
0.0);
registry->RegisterDoublePref(kUserClassifierAverageSuggestionsUsedPerHour,
@@ -74,6 +80,7 @@ void RegisterObsoletePrefsFeb_2021(PrefRegistrySimple* registry) {
base::Time());
registry->RegisterTimePref(kUserClassifierLastTimeToUseSuggestions,
base::Time());
+ registry->RegisterBooleanPref(kEnableWebFeedUI, false);
}
} // namespace
@@ -97,7 +104,11 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(feed::prefs::kNoticeCardViewsCount, 0);
registry->RegisterIntegerPref(feed::prefs::kNoticeCardClicksCount, 0);
registry->RegisterDictionaryPref(feed::prefs::kExperiments);
- registry->RegisterBooleanPref(feed::prefs::kEnableWebFeedUI, false);
+ registry->RegisterBooleanPref(feed::prefs::kEnableWebFeedFollowIntroDebug,
+ false);
+ registry->RegisterUint64Pref(feed::prefs::kReliabilityLoggingIdSalt, 0);
+ registry->RegisterBooleanPref(feed::prefs::kIsWebFeedSubscriber, false);
+ registry->RegisterBooleanPref(feed::prefs::kHasStoredData, false);
#if defined(OS_IOS)
registry->RegisterBooleanPref(feed::prefs::kLastFetchHadLoggingEnabled,
@@ -112,11 +123,11 @@ void MigrateObsoleteProfilePrefsFeb_2021(PrefService* prefs) {
prefs->ClearPref(kBackgroundRefreshPeriod);
prefs->ClearPref(kThrottlerRequestCount);
prefs->ClearPref(kThrottlerRequestsDay);
-
prefs->ClearPref(kUserClassifierAverageSuggestionsViwedPerHour);
prefs->ClearPref(kUserClassifierAverageSuggestionsUsedPerHour);
prefs->ClearPref(kUserClassifierLastTimeToViewSuggestions);
prefs->ClearPref(kUserClassifierLastTimeToUseSuggestions);
+ prefs->ClearPref(kEnableWebFeedUI);
}
} // namespace feed
diff --git a/chromium/components/feed/core/common/pref_names.h b/chromium/components/feed/core/common/pref_names.h
index 4c92c7bbe36..2f835fb517f 100644
--- a/chromium/components/feed/core/common/pref_names.h
+++ b/chromium/components/feed/core/common/pref_names.h
@@ -67,8 +67,16 @@ extern const char kClientInstanceId[];
extern const char kDiscoverAPIEndpointOverride[];
// The pref name for storing the server experiments the client is in.
extern const char kExperiments[];
-// If set to false, the WebFeed UI is disabled.
-extern const char kEnableWebFeedUI[];
+// If set to true, the WebFeed follow intro bypasses some gates and only checks
+// for recommended and scroll status.
+extern const char kEnableWebFeedFollowIntroDebug[];
+// Random bytes used in generating reliability logging ID.
+extern const char kReliabilityLoggingIdSalt[];
+// Whether the user has subscribed to a web feed.
+extern const char kIsWebFeedSubscriber[];
+// Whether the Feed may have data stored, which should be deleted if the Feed
+// is ever turned off.
+extern const char kHasStoredData[];
} // namespace prefs
diff --git a/chromium/components/feed/core/proto/BUILD.gn b/chromium/components/feed/core/proto/BUILD.gn
index f8be80e1c5b..d14b9442e00 100644
--- a/chromium/components/feed/core/proto/BUILD.gn
+++ b/chromium/components/feed/core/proto/BUILD.gn
@@ -22,7 +22,6 @@ proto_library("proto_v2") {
"v2/wire/chrome_feed_response_metadata.proto",
"v2/wire/chrome_fulfillment_info.proto",
"v2/wire/client_info.proto",
- "v2/wire/color.proto",
"v2/wire/consistency_token.proto",
"v2/wire/content_id.proto",
"v2/wire/data_operation.proto",
@@ -51,8 +50,8 @@ proto_library("proto_v2") {
"v2/wire/upload_actions_response.proto",
"v2/wire/version.proto",
"v2/wire/web_feed_matcher.proto",
+ "v2/wire/web_feed_token.proto",
"v2/wire/web_feeds.proto",
- "v2/wire/wrappers.proto",
"v2/wire/xsurface_container.proto",
"v2/wire/xsurface_content.proto",
"v2/xsurface.proto",
diff --git a/chromium/components/feed/core/proto/v2/store.proto b/chromium/components/feed/core/proto/v2/store.proto
index 22b60e5be2e..2e47531db8f 100644
--- a/chromium/components/feed/core/proto/v2/store.proto
+++ b/chromium/components/feed/core/proto/v2/store.proto
@@ -60,6 +60,8 @@ message StreamData {
bool privacy_notice_fulfilled = 9;
// Stream ID. Should match the id value stored in the record's key.
string stream_id = 10;
+ // List of unique IDs representing content contained in the stream.
+ repeated int64 content_ids = 11;
reserved 3, 5;
}
@@ -75,10 +77,16 @@ message Metadata {
// Metadata about a specific stream.
message StreamMetadata {
string stream_id = 1;
- // If this stream has been viewed before, this timestamp matches the
- // 'StreamData.last_added_time_millis' value of that stream. This is used to
- // determine whether the user has already seen a stored stream's data.
- int64 view_time_millis = 2;
+ // Whether the stream data is known to be stale. This can happen in the
+ // WebFeed stream if the subscription list changes.
+ bool is_known_stale = 3;
+ // If this stream has been viewed before, this is the list of content in the
+ // stream
+ // (`StreamData.content_ids`). This is used to determine whether the user
+ // has already seen a stored stream's data.
+ repeated int64 view_content_ids = 4;
+
+ reserved 2;
}
// Token used to read or write to the same storage.
diff --git a/chromium/components/feed/core/proto/v2/ui.proto b/chromium/components/feed/core/proto/v2/ui.proto
index b3e24a7fb81..138e55d58a8 100644
--- a/chromium/components/feed/core/proto/v2/ui.proto
+++ b/chromium/components/feed/core/proto/v2/ui.proto
@@ -44,6 +44,7 @@ message Slice {
LoadingSpinnerSlice loading_spinner_slice = 4;
}
string slice_id = 2;
+ SliceMetadata slice_metadata = 5;
}
// This slice is sent when no feed data can be loaded.
@@ -74,3 +75,8 @@ message SharedState {
string id = 1;
bytes xsurface_shared_state = 2;
}
+
+message SliceMetadata {
+ string uri = 1;
+ string title = 2;
+}
diff --git a/chromium/components/feed/core/proto/v2/wire/capability.proto b/chromium/components/feed/core/proto/v2/wire/capability.proto
index 953e7b6c882..854fd053308 100644
--- a/chromium/components/feed/core/proto/v2/wire/capability.proto
+++ b/chromium/components/feed/core/proto/v2/wire/capability.proto
@@ -14,8 +14,10 @@ enum Capability {
INFINITE_FEED = 5;
DISMISS_COMMAND = 9;
UNDO_FOR_DISMISS_COMMAND = 10;
+ WEB_FEEDS = 11;
SPORTS_IN_GAME_UPDATE = 35;
PERSIST_GAME_CONTENT = 46;
+ OPEN_VIDEO_COMMAND = 16;
UI_THEME_V2 = 17;
INLINE_VIDEO_AUTOPLAY = 18;
CARD_MENU = 19;
diff --git a/chromium/components/feed/core/proto/v2/wire/color.proto b/chromium/components/feed/core/proto/v2/wire/color.proto
deleted file mode 100644
index 0433b3862d6..00000000000
--- a/chromium/components/feed/core/proto/v2/wire/color.proto
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto3";
-
-package feedwire;
-
-import "components/feed/core/proto/v2/wire/wrappers.proto";
-
-option optimize_for = LITE_RUNTIME;
-
-message Color {
- float red = 1;
- float green = 2;
- float blue = 3;
- FloatValue alpha = 4;
-}
diff --git a/chromium/components/feed/core/proto/v2/wire/feed_query.proto b/chromium/components/feed/core/proto/v2/wire/feed_query.proto
index 6dcced289a5..2c80a8e9dd4 100644
--- a/chromium/components/feed/core/proto/v2/wire/feed_query.proto
+++ b/chromium/components/feed/core/proto/v2/wire/feed_query.proto
@@ -19,8 +19,13 @@ message FeedQuery {
MANUAL_REFRESH = 1;
SCHEDULED_REFRESH = 2;
NEXT_PAGE_SCROLL = 3;
+ PREFETCHED_WEB_FEED = 8;
+ INTERACTIVE_WEB_FEED = 9;
+ }
+ oneof token {
+ Token next_page_token = 3;
+ Token web_feed_token = 4;
}
- oneof token { Token next_page_token = 3; }
optional RequestReason reason = 1;
optional FeedEntryPointData feed_entry_point_data = 9;
optional ChromeFulfillmentInfo chrome_fulfillment_info = 341477699;
diff --git a/chromium/components/feed/core/proto/v2/wire/token.proto b/chromium/components/feed/core/proto/v2/wire/token.proto
index 37ac17c0b56..c5123e77f2f 100644
--- a/chromium/components/feed/core/proto/v2/wire/token.proto
+++ b/chromium/components/feed/core/proto/v2/wire/token.proto
@@ -8,11 +8,13 @@ package feedwire;
import "components/feed/core/proto/v2/wire/content_id.proto";
import "components/feed/core/proto/v2/wire/next_page_token.proto";
+import "components/feed/core/proto/v2/wire/web_feed_token.proto";
option optimize_for = LITE_RUNTIME;
message Token {
optional ContentId parent_id = 2;
+ optional WebFeedToken web_feed_token = 1001;
optional NextPageToken next_page_token = 1002;
optional bytes in_place_update_token = 1003;
optional bytes story_token = 1004;
diff --git a/chromium/components/feed/core/proto/v2/wire/wrappers.proto b/chromium/components/feed/core/proto/v2/wire/web_feed_token.proto
index a9d8df77d3d..b17f95b5447 100644
--- a/chromium/components/feed/core/proto/v2/wire/wrappers.proto
+++ b/chromium/components/feed/core/proto/v2/wire/web_feed_token.proto
@@ -1,13 +1,13 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-syntax = "proto3";
+syntax = "proto2";
package feedwire;
option optimize_for = LITE_RUNTIME;
-message FloatValue {
- float value = 1;
+message WebFeedToken {
+ optional bytes web_feed_token = 1;
}
diff --git a/chromium/components/feed/core/v2/BUILD.gn b/chromium/components/feed/core/v2/BUILD.gn
index b305ba18d92..1d36927402d 100644
--- a/chromium/components/feed/core/v2/BUILD.gn
+++ b/chromium/components/feed/core/v2/BUILD.gn
@@ -25,10 +25,10 @@ source_set("feed_core_v2") {
"image_fetcher.h",
"metrics_reporter.cc",
"metrics_reporter.h",
- "offline_page_spy.cc",
- "offline_page_spy.h",
"persistent_key_value_store_impl.cc",
"persistent_key_value_store_impl.h",
+ "prefs.cc",
+ "prefs.h",
"proto_util.cc",
"proto_util.h",
"protocol_translator.cc",
@@ -37,13 +37,19 @@ source_set("feed_core_v2") {
"public/feed_api.h",
"public/feed_service.cc",
"public/feed_service.h",
+ "public/feed_stream_surface.cc",
+ "public/feed_stream_surface.h",
"public/persistent_key_value_store.cc",
"public/persistent_key_value_store.h",
"public/refresh_task_scheduler.h",
"public/types.cc",
+ "public/unread_content_observer.cc",
+ "public/unread_content_observer.h",
"public/web_feed_subscriptions.h",
"request_throttler.cc",
"request_throttler.h",
+ "scheduling.cc",
+ "scheduling.h",
"stream/unread_content_notifier.cc",
"stream/unread_content_notifier.h",
"stream/upload_criteria.cc",
@@ -58,8 +64,6 @@ source_set("feed_core_v2") {
"surface_updater.h",
"tasks/clear_all_task.cc",
"tasks/clear_all_task.h",
- "tasks/get_prefetch_suggestions_task.cc",
- "tasks/get_prefetch_suggestions_task.h",
"tasks/load_more_task.cc",
"tasks/load_more_task.h",
"tasks/load_stream_from_store_task.cc",
@@ -95,11 +99,10 @@ source_set("feed_core_v2") {
"//components/feed/core/shared_prefs:feed_shared_prefs",
"//components/history/core/browser",
"//components/leveldb_proto:leveldb_proto",
- "//components/offline_pages/core:core",
- "//components/offline_pages/core/prefetch",
"//components/offline_pages/task:task",
"//components/prefs",
"//components/signin/public/identity_manager",
+ "//components/url_matcher:url_matcher",
"//components/variations",
"//components/variations/net",
"//components/version_info:channel",
@@ -128,11 +131,9 @@ source_set("feed_core_base") {
"enums.h",
"notice_card_tracker.cc",
"notice_card_tracker.h",
- "prefs.cc",
- "prefs.h",
+ "public/stream_type.cc",
+ "public/stream_type.h",
"public/types.h",
- "scheduling.cc",
- "scheduling.h",
"types.cc",
"types.h",
]
@@ -154,12 +155,23 @@ source_set("common") {
deps = []
}
+source_set("test_helpers") {
+ testonly = true
+ sources = [
+ "test/callback_receiver.cc",
+ "test/callback_receiver.h",
+ ]
+ deps = [
+ "//base",
+ "//base/test:test_support",
+ ]
+}
+
source_set("core_unit_tests") {
testonly = true
sources = [
"algorithm_unittest.cc",
"api_test/feed_api_notice_card_unittest.cc",
- "api_test/feed_api_offline_pages_unittest.cc",
"api_test/feed_api_stream_unittest.cc",
"api_test/feed_api_subscriptions_unittest.cc",
"api_test/feed_api_test.cc",
@@ -175,9 +187,8 @@ source_set("core_unit_tests") {
"public/feed_service_unittest.cc",
"public/types_unittest.cc",
"request_throttler_unittest.cc",
+ "scheduling_unittest.cc",
"stream_model_unittest.cc",
- "test/callback_receiver.cc",
- "test/callback_receiver.h",
"test/callback_receiver_unittest.cc",
"test/proto_printer.cc",
"test/proto_printer.h",
@@ -188,6 +199,7 @@ source_set("core_unit_tests") {
"web_feed_subscriptions/web_feed_index_unittest.cc",
]
+ public_deps = [ ":test_helpers" ]
deps = [
":common",
":feed_core_base_unit_tests",
@@ -201,10 +213,7 @@ source_set("core_unit_tests") {
"//components/feed/core/shared_prefs:feed_shared_prefs",
"//components/history/core/browser",
"//components/leveldb_proto:test_support",
- "//components/offline_pages/core:core",
"//components/offline_pages/core:test_support",
- "//components/offline_pages/core/prefetch",
- "//components/offline_pages/core/prefetch:test_support",
"//components/prefs:test_support",
"//components/signin/public/identity_manager",
"//components/signin/public/identity_manager:test_support",
@@ -218,13 +227,23 @@ source_set("core_unit_tests") {
]
}
+source_set("feed_core_stubs") {
+ testonly = true
+ sources = [
+ "public/test/stub_feed_api.cc",
+ "public/test/stub_feed_api.h",
+ "public/test/stub_web_feed_subscriptions.cc",
+ "public/test/stub_web_feed_subscriptions.h",
+ ]
+ deps = [ ":feed_core_v2" ]
+}
+
# Tests for :feed_core_base that can be compiled in iOS.
# This source set is added as a dep of :core_unit_tests.
source_set("feed_core_base_unit_tests") {
testonly = true
sources = [
"notice_card_tracker_unittest.cc",
- "scheduling_unittest.cc",
"types_unittest.cc",
]
deps = [
diff --git a/chromium/components/feed/core/v2/api_test/feed_api_notice_card_unittest.cc b/chromium/components/feed/core/v2/api_test/feed_api_notice_card_unittest.cc
index e4465e57d7e..7b020b20f94 100644
--- a/chromium/components/feed/core/v2/api_test/feed_api_notice_card_unittest.cc
+++ b/chromium/components/feed/core/v2/api_test/feed_api_notice_card_unittest.cc
@@ -47,7 +47,7 @@ TEST_F(FeedApiTest, LoadStreamSendsNoticeCardAcknowledgement) {
slice_id);
stream_->ReportSliceViewed(surface.GetSurfaceId(), surface.GetStreamType(),
slice_id);
- stream_->ReportOpenAction(surface.GetStreamType(), slice_id);
+ stream_->ReportOpenAction(GURL(), surface.GetStreamType(), slice_id);
response_translator_.InjectResponse(MakeTypicalInitialModelState());
stream_->UnloadModel(surface.GetStreamType());
diff --git a/chromium/components/feed/core/v2/api_test/feed_api_offline_pages_unittest.cc b/chromium/components/feed/core/v2/api_test/feed_api_offline_pages_unittest.cc
deleted file mode 100644
index 9521ab3b811..00000000000
--- a/chromium/components/feed/core/v2/api_test/feed_api_offline_pages_unittest.cc
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/callback_helpers.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/metrics/user_action_tester.h"
-#include "components/feed/core/v2/api_test/feed_api_test.h"
-#include "components/feed/core/v2/config.h"
-#include "components/feed/core/v2/feed_stream.h"
-#include "components/feed/core/v2/test/callback_receiver.h"
-#include "components/offline_pages/core/client_namespace_constants.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace feed {
-namespace test {
-namespace {
-
-TEST_F(FeedApiTest, ProvidesPrefetchSuggestionsWhenModelLoaded) {
- // Setup by triggering a model load.
- response_translator_.InjectResponse(MakeTypicalInitialModelState());
- TestForYouSurface surface(stream_.get());
- WaitForIdleTaskQueue();
-
- // Because we loaded from the network,
- // PrefetchService::NewSuggestionsAvailable() should have been called.
- EXPECT_EQ(1, prefetch_service_.NewSuggestionsAvailableCallCount());
-
- CallbackReceiver<std::vector<offline_pages::PrefetchSuggestion>> callback;
- prefetch_service_.suggestions_provider()->GetCurrentArticleSuggestions(
- callback.Bind());
- WaitForIdleTaskQueue();
-
- ASSERT_TRUE(callback.GetResult());
- const std::vector<offline_pages::PrefetchSuggestion>& suggestions =
- callback.GetResult().value();
-
- ASSERT_EQ(2UL, suggestions.size());
- EXPECT_EQ("http://content0/", suggestions[0].article_url);
- EXPECT_EQ("title0", suggestions[0].article_title);
- EXPECT_EQ("publisher0", suggestions[0].article_attribution);
- EXPECT_EQ("snippet0", suggestions[0].article_snippet);
- EXPECT_EQ("http://image0/", suggestions[0].thumbnail_url);
- EXPECT_EQ("http://favicon0/", suggestions[0].favicon_url);
-
- EXPECT_EQ("http://content1/", suggestions[1].article_url);
-}
-
-TEST_F(FeedApiTest, ProvidesPrefetchSuggestionsWhenModelNotLoaded) {
- store_->OverwriteStream(kForYouStream, MakeTypicalInitialModelState(),
- base::DoNothing());
-
- CallbackReceiver<std::vector<offline_pages::PrefetchSuggestion>> callback;
- prefetch_service_.suggestions_provider()->GetCurrentArticleSuggestions(
- callback.Bind());
- WaitForIdleTaskQueue();
-
- ASSERT_FALSE(stream_->GetModel(kForYouStream));
- ASSERT_TRUE(callback.GetResult());
- const std::vector<offline_pages::PrefetchSuggestion>& suggestions =
- callback.GetResult().value();
-
- ASSERT_EQ(2UL, suggestions.size());
- EXPECT_EQ("http://content0/", suggestions[0].article_url);
- EXPECT_EQ("http://content1/", suggestions[1].article_url);
- EXPECT_EQ(0, prefetch_service_.NewSuggestionsAvailableCallCount());
-}
-
-TEST_F(FeedApiTest, ScrubsUrlsInProvidedPrefetchSuggestions) {
- {
- auto initial_state = MakeTypicalInitialModelState();
- initial_state->content[0].mutable_prefetch_metadata(0)->set_uri(
- "?notavalidurl?");
- initial_state->content[0].mutable_prefetch_metadata(0)->set_image_url(
- "?asdf?");
- initial_state->content[0].mutable_prefetch_metadata(0)->set_favicon_url(
- "?hi?");
- initial_state->content[0].mutable_prefetch_metadata(0)->clear_uri();
- store_->OverwriteStream(kForYouStream, std::move(initial_state),
- base::DoNothing());
- }
-
- CallbackReceiver<std::vector<offline_pages::PrefetchSuggestion>> callback;
- prefetch_service_.suggestions_provider()->GetCurrentArticleSuggestions(
- callback.Bind());
- WaitForIdleTaskQueue();
-
- ASSERT_TRUE(callback.GetResult());
- const std::vector<offline_pages::PrefetchSuggestion>& suggestions =
- callback.GetResult().value();
-
- ASSERT_EQ(2UL, suggestions.size());
- EXPECT_EQ("", suggestions[0].article_url.possibly_invalid_spec());
- EXPECT_EQ("", suggestions[0].thumbnail_url.possibly_invalid_spec());
- EXPECT_EQ("", suggestions[0].favicon_url.possibly_invalid_spec());
-}
-
-TEST_F(FeedApiTest, OfflineBadgesArePopulatedInitially) {
- // Add two offline pages. We exclude tab-bound pages, so only the first is
- // used.
- offline_page_model_.AddTestPage(GURL("http://content0/"));
- offline_page_model_.AddTestPage(GURL("http://content1/"));
- offline_page_model_.items()[1].client_id.name_space =
- offline_pages::kLastNNamespace;
- response_translator_.InjectResponse(MakeTypicalInitialModelState());
- TestForYouSurface surface(stream_.get());
- WaitForIdleTaskQueue();
-
- EXPECT_EQ((std::map<std::string, std::string>(
- {{"app/badge0", SerializedOfflineBadgeContent()}})),
- surface.GetDataStoreEntries());
-}
-
-TEST_F(FeedApiTest, OfflineBadgesArePopulatedOnNewOfflineItemAdded) {
- response_translator_.InjectResponse(MakeTypicalInitialModelState());
- TestForYouSurface surface(stream_.get());
- WaitForIdleTaskQueue();
-
- ASSERT_EQ((std::map<std::string, std::string>({})),
- surface.GetDataStoreEntries());
-
- // Add an offline page.
- offline_page_model_.AddTestPage(GURL("http://content1/"));
- offline_page_model_.CallObserverOfflinePageAdded(
- offline_page_model_.items()[0]);
- task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
-
- EXPECT_EQ((std::map<std::string, std::string>(
- {{"app/badge1", SerializedOfflineBadgeContent()}})),
- surface.GetDataStoreEntries());
-}
-
-TEST_F(FeedApiTest, OfflineBadgesAreRemovedWhenOfflineItemRemoved) {
- offline_page_model_.AddTestPage(GURL("http://content0/"));
- response_translator_.InjectResponse(MakeTypicalInitialModelState());
- TestForYouSurface surface(stream_.get());
- WaitForIdleTaskQueue();
-
- ASSERT_EQ((std::map<std::string, std::string>(
- {{"app/badge0", SerializedOfflineBadgeContent()}})),
- surface.GetDataStoreEntries());
-
- // Remove the offline page.
- offline_page_model_.CallObserverOfflinePageDeleted(
- offline_page_model_.items()[0]);
- task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
-
- EXPECT_EQ((std::map<std::string, std::string>()),
- surface.GetDataStoreEntries());
-}
-
-TEST_F(FeedApiTest, OfflineBadgesAreProvidedToNewSurfaces) {
- offline_page_model_.AddTestPage(GURL("http://content0/"));
- response_translator_.InjectResponse(MakeTypicalInitialModelState());
- TestForYouSurface surface(stream_.get());
- WaitForIdleTaskQueue();
-
- TestForYouSurface surface2(stream_.get());
- WaitForIdleTaskQueue();
-
- EXPECT_EQ((std::map<std::string, std::string>(
- {{"app/badge0", SerializedOfflineBadgeContent()}})),
- surface2.GetDataStoreEntries());
-}
-
-TEST_F(FeedApiTest, OfflineBadgesAreRemovedWhenModelIsUnloaded) {
- offline_page_model_.AddTestPage(GURL("http://content0/"));
- response_translator_.InjectResponse(MakeTypicalInitialModelState());
- TestForYouSurface surface(stream_.get());
- WaitForIdleTaskQueue();
-
- stream_->UnloadModel(surface.GetStreamType());
-
- // Offline badge no longer present.
- EXPECT_EQ((std::map<std::string, std::string>()),
- surface.GetDataStoreEntries());
-}
-
-TEST_F(FeedApiTest, MultipleOfflineBadgesWithSameUrl) {
- {
- std::unique_ptr<StreamModelUpdateRequest> state =
- MakeTypicalInitialModelState();
- const feedwire::PrefetchMetadata& prefetch_metadata1 =
- state->content[0].prefetch_metadata(0);
- feedwire::PrefetchMetadata& prefetch_metadata2 =
- *state->content[0].add_prefetch_metadata();
- prefetch_metadata2 = prefetch_metadata1;
- prefetch_metadata2.set_badge_id("app/badge0b");
- response_translator_.InjectResponse(std::move(state));
- }
- offline_page_model_.AddTestPage(GURL("http://content0/"));
-
- TestForYouSurface surface(stream_.get());
- WaitForIdleTaskQueue();
-
- EXPECT_EQ((std::map<std::string, std::string>(
- {{"app/badge0", SerializedOfflineBadgeContent()},
- {"app/badge0b", SerializedOfflineBadgeContent()}})),
- surface.GetDataStoreEntries());
-}
-
-} // namespace
-} // namespace test
-} // namespace feed
diff --git a/chromium/components/feed/core/v2/api_test/feed_api_stream_unittest.cc b/chromium/components/feed/core/v2/api_test/feed_api_stream_unittest.cc
index 1598f1f60b6..9619d857f9c 100644
--- a/chromium/components/feed/core/v2/api_test/feed_api_stream_unittest.cc
+++ b/chromium/components/feed/core/v2/api_test/feed_api_stream_unittest.cc
@@ -3,14 +3,26 @@
// found in the LICENSE file.
#include "base/callback_helpers.h"
+#include "base/feature_list.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "components/feed/core/common/pref_names.h"
+#include "components/feed/core/shared_prefs/pref_names.h"
#include "components/feed/core/v2/api_test/feed_api_test.h"
#include "components/feed/core/v2/config.h"
+#include "components/feed/core/v2/feed_network.h"
#include "components/feed/core/v2/feed_stream.h"
#include "components/feed/core/v2/feedstore_util.h"
#include "components/feed/core/v2/public/feed_api.h"
+#include "components/feed/core/v2/public/feed_service.h"
+#include "components/feed/core/v2/public/stream_type.h"
+#include "components/feed/core/v2/scheduling.h"
#include "components/feed/core/v2/test/callback_receiver.h"
+#include "components/feed/core/v2/test/stream_builder.h"
+#include "components/feed/feed_feature_list.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -51,26 +63,26 @@ TEST_F(FeedApiTest, BackgroundRefreshForYouSuccess) {
TestForYouSurface surface(stream_.get());
WaitForIdleTaskQueue();
EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates());
- // Verify that prefetch service was informed.
- EXPECT_EQ(1, prefetch_service_.NewSuggestionsAvailableCallCount());
}
-TEST_F(FeedApiTest, BackgroundRefreshWebFeedSuccess) {
- // Trigger a background refresh.
- response_translator_.InjectResponse(MakeTypicalInitialModelState());
- stream_->ExecuteRefreshTask(RefreshTaskId::kRefreshWebFeed);
- WaitForIdleTaskQueue();
+TEST_F(FeedApiTest, WebFeedDoesNotBackgroundRefresh) {
+ {
+ RefreshResponseData injected_response;
+ injected_response.model_update_request = MakeTypicalInitialModelState();
+ RequestSchedule schedule;
+ schedule.anchor_time = kTestTimeEpoch;
+ schedule.refresh_offsets = {base::TimeDelta::FromSeconds(12),
+ base::TimeDelta::FromSeconds(48)};
+
+ injected_response.request_schedule = schedule;
+ response_translator_.InjectResponse(std::move(injected_response));
+ }
- // Verify the refresh happened and that we can load a stream without the
- // network.
- ASSERT_TRUE(
- refresh_scheduler_.completed_tasks.count(RefreshTaskId::kRefreshWebFeed));
- EXPECT_TRUE(response_translator_.InjectedResponseConsumed());
TestWebFeedSurface surface(stream_.get());
WaitForIdleTaskQueue();
- EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates());
- // Verify that prefetch service is NOT informed.
- EXPECT_EQ(0, prefetch_service_.NewSuggestionsAvailableCallCount());
+
+ // The request schedule should be ignored.
+ EXPECT_TRUE(refresh_scheduler_.scheduled_run_times.empty());
}
TEST_F(FeedApiTest, BackgroundRefreshPrefetchesImages) {
@@ -281,6 +293,7 @@ TEST_P(FeedStreamTestForAllStreamTypes, LoadFromNetwork) {
TestSurface surface(stream_.get());
WaitForIdleTaskQueue();
ASSERT_TRUE(network_.query_request_sent);
+ EXPECT_EQ(0, network_.GetApiRequestCount<QueryInteractiveFeedDiscoverApi>());
EXPECT_EQ(
"token",
network_.query_request_sent->feed_request().consistency_token().token());
@@ -296,6 +309,49 @@ TEST_P(FeedStreamTestForAllStreamTypes, LoadFromNetwork) {
ModelStateFor(GetStreamType(), store_.get()));
}
+// Test that we use QueryInteractiveFeedDiscoverApi and QueryNextPageDiscoverApi
+// when kDiscoFeedEndpoint is enabled.
+TEST_F(FeedApiTest, LoadFromNetworkDiscoFeedEnabled) {
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeature(kDiscoFeedEndpoint);
+
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ response_translator_.InjectResponse(MakeTypicalNextPageState());
+ TestForYouSurface surface(stream_.get());
+ WaitForIdleTaskQueue();
+ EXPECT_EQ(1, network_.GetApiRequestCount<QueryInteractiveFeedDiscoverApi>());
+
+ stream_->LoadMore(surface, base::DoNothing());
+ WaitForIdleTaskQueue();
+
+ EXPECT_EQ(1, network_.GetApiRequestCount<QueryNextPageDiscoverApi>());
+ EXPECT_EQ("loading -> 2 slices -> 2 slices +spinner -> 4 slices",
+ surface.DescribeUpdates());
+}
+
+// Perform a background refresh when DiscoFeedEndpoint is enabled. A
+// QueryBackgroundFeedDiscoverApi request should be made.
+TEST_F(FeedApiTest, BackgroundRefreshDiscoFeedEnabled) {
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeature(kDiscoFeedEndpoint);
+
+ // Trigger a background refresh.
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ stream_->ExecuteRefreshTask(RefreshTaskId::kRefreshForYouFeed);
+ WaitForIdleTaskQueue();
+
+ // Verify the refresh happened and that we can load a stream without the
+ // network.
+ ASSERT_TRUE(refresh_scheduler_.completed_tasks.count(
+ RefreshTaskId::kRefreshForYouFeed));
+ EXPECT_EQ(1, network_.GetApiRequestCount<QueryBackgroundFeedDiscoverApi>());
+ EXPECT_EQ(LoadStreamStatus::kLoadedFromNetwork,
+ metrics_reporter_->background_refresh_status);
+ TestForYouSurface surface(stream_.get());
+ WaitForIdleTaskQueue();
+ EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates());
+}
+
TEST_F(FeedApiTest, ForceRefreshForDebugging) {
// First do a normal load via network that will fail.
is_offline_ = true;
@@ -312,7 +368,7 @@ TEST_F(FeedApiTest, ForceRefreshForDebugging) {
surface.DescribeUpdates());
}
-TEST_P(FeedStreamTestForAllStreamTypes, RefreshScheduleFlow) {
+TEST_F(FeedApiTest, RefreshScheduleFlow) {
// Inject a typical network response, with a server-defined request schedule.
{
RequestSchedule schedule;
@@ -327,36 +383,41 @@ TEST_P(FeedStreamTestForAllStreamTypes, RefreshScheduleFlow) {
// Load the stream, and then destroy the surface to allow background
// refresh.
- TestSurface surface(stream_.get());
+ TestForYouSurface surface(stream_.get());
WaitForIdleTaskQueue();
UnloadModel(surface.GetStreamType());
}
// Verify the first refresh was scheduled.
EXPECT_EQ(base::TimeDelta::FromSeconds(12),
- refresh_scheduler_.scheduled_run_times[GetRefreshTaskId()]);
+ refresh_scheduler_
+ .scheduled_run_times[RefreshTaskId::kRefreshForYouFeed]);
// Simulate executing the background task.
refresh_scheduler_.Clear();
task_environment_.AdvanceClock(base::TimeDelta::FromSeconds(12));
- stream_->ExecuteRefreshTask(GetRefreshTaskId());
+ stream_->ExecuteRefreshTask(RefreshTaskId::kRefreshForYouFeed);
WaitForIdleTaskQueue();
// Verify |RefreshTaskComplete()| was called and next refresh was scheduled.
- EXPECT_TRUE(refresh_scheduler_.completed_tasks.count(GetRefreshTaskId()));
+ EXPECT_TRUE(refresh_scheduler_.completed_tasks.count(
+ RefreshTaskId::kRefreshForYouFeed));
EXPECT_EQ(base::TimeDelta::FromSeconds(48 - 12),
- refresh_scheduler_.scheduled_run_times[GetRefreshTaskId()]);
+ refresh_scheduler_
+ .scheduled_run_times[RefreshTaskId::kRefreshForYouFeed]);
// Simulate executing the background task again.
refresh_scheduler_.Clear();
task_environment_.AdvanceClock(base::TimeDelta::FromSeconds(48 - 12));
- stream_->ExecuteRefreshTask(GetRefreshTaskId());
+ stream_->ExecuteRefreshTask(RefreshTaskId::kRefreshForYouFeed);
WaitForIdleTaskQueue();
// Verify |RefreshTaskComplete()| was called and next refresh was scheduled.
- EXPECT_TRUE(refresh_scheduler_.completed_tasks.count(GetRefreshTaskId()));
+ EXPECT_TRUE(refresh_scheduler_.completed_tasks.count(
+ RefreshTaskId::kRefreshForYouFeed));
EXPECT_EQ(GetFeedConfig().default_background_refresh_interval,
- refresh_scheduler_.scheduled_run_times[GetRefreshTaskId()]);
+ refresh_scheduler_
+ .scheduled_run_times[RefreshTaskId::kRefreshForYouFeed]);
}
TEST_F(FeedApiTest, ForceRefreshIfMissedScheduledRefresh) {
@@ -405,9 +466,10 @@ TEST_P(FeedStreamTestForAllStreamTypes, LoadFromNetworkBecauseStoreIsStale) {
store_->OverwriteStream(
GetStreamType(),
MakeTypicalInitialModelState(
- /*first_cluster_id=*/0, kTestTimeEpoch -
- GetFeedConfig().stale_content_threshold -
- base::TimeDelta::FromMinutes(1)),
+ /*first_cluster_id=*/0,
+ kTestTimeEpoch -
+ GetFeedConfig().GetStalenessThreshold(GetStreamType()) -
+ base::TimeDelta::FromMinutes(1)),
base::DoNothing());
// Store is stale, so we should fallback to a network request.
@@ -505,7 +567,6 @@ TEST_F(FeedApiTest, LoadFromNetworkFailsDueToProtoTranslation) {
EXPECT_EQ(LoadStreamStatus::kProtoTranslationFailed,
metrics_reporter_->load_stream_status);
- EXPECT_EQ(0, prefetch_service_.NewSuggestionsAvailableCallCount());
}
TEST_F(FeedApiTest, DoNotLoadFromNetworkWhenOffline) {
is_offline_ = true;
@@ -579,7 +640,7 @@ TEST_F(FeedApiTest, ForceSignedOutRequestAfterHistoryIsDeleted) {
// Validate that the network request was sent as signed out.
ASSERT_EQ(1, network_.send_query_call_count);
- EXPECT_TRUE(network_.forced_signed_out_request);
+ EXPECT_EQ("", network_.last_gaia);
EXPECT_TRUE(network_.query_request_sent->feed_request()
.client_info()
.chrome_client_info()
@@ -604,7 +665,7 @@ TEST_F(FeedApiTest, ForceSignedOutRequestAfterHistoryIsDeleted) {
// Validate that the network request was sent as signed out and
// contained the session id.
ASSERT_EQ(2, network_.send_query_call_count);
- EXPECT_TRUE(network_.forced_signed_out_request);
+ EXPECT_EQ("", network_.last_gaia);
EXPECT_EQ(kSessionId, stream_->GetMetadata().session_id().token());
EXPECT_EQ(network_.query_request_sent->feed_request()
.client_info()
@@ -625,7 +686,7 @@ TEST_F(FeedApiTest, ForceSignedOutRequestAfterHistoryIsDeleted) {
// Validate that a signed-in request was sent.
ASSERT_EQ(3, network_.send_query_call_count);
- EXPECT_FALSE(network_.forced_signed_out_request);
+ EXPECT_NE("", network_.last_gaia);
// The model should now be in the signed-in state.
EXPECT_TRUE(stream_->GetModel(kForYouStream)->signed_in());
@@ -640,7 +701,7 @@ TEST_F(FeedApiTest, WebFeedUsesSignedInRequestAfterHistoryIsDeleted) {
WaitForIdleTaskQueue();
ASSERT_EQ(1, network_.send_query_call_count);
- EXPECT_FALSE(network_.forced_signed_out_request);
+ EXPECT_NE("", network_.last_gaia);
}
TEST_F(FeedApiTest, AllowSignedInRequestAfterHistoryIsDeletedAfterDelay) {
@@ -652,7 +713,7 @@ TEST_F(FeedApiTest, AllowSignedInRequestAfterHistoryIsDeletedAfterDelay) {
WaitForIdleTaskQueue();
EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates());
- EXPECT_FALSE(network_.forced_signed_out_request);
+ EXPECT_NE("", network_.last_gaia);
EXPECT_TRUE(stream_->GetMetadata().session_id().token().empty());
}
@@ -789,7 +850,7 @@ TEST_F(FeedApiTest, ReportOpenInNewTabAction) {
base::UserActionTester user_actions;
stream_->ReportOpenInNewTabAction(
- surface.GetStreamType(),
+ GURL(), surface.GetStreamType(),
surface.initial_state->updated_slices(1).slice().slice_id());
EXPECT_EQ(1, user_actions.GetActionCount(
@@ -804,9 +865,52 @@ TEST_F(FeedApiTest, HasUnreadContentAfterLoadFromNetwork) {
WaitForIdleTaskQueue();
+ EXPECT_EQ(std::vector<bool>({false, true}), observer.calls);
+}
+
+TEST_F(FeedApiTest, HasUnreadContentInitially) {
+ // Prime the feed with new content.
+ {
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ TestForYouSurface surface(stream_.get());
+ WaitForIdleTaskQueue();
+ }
+
+ // Reload FeedStream. Add an observer before initialization completes.
+ // After initialization, the observer will be informed about unread content.
+ CreateStream(/*wait_for_initialization*/ false);
+ TestUnreadContentObserver observer;
+ stream_->AddUnreadContentObserver(kForYouStream, &observer);
+ WaitForIdleTaskQueue();
+
EXPECT_EQ(std::vector<bool>({true}), observer.calls);
}
+TEST_F(FeedApiTest, NetworkFetchWithNoNewContentDoesNotProvideUnreadContent) {
+ TestUnreadContentObserver observer;
+ stream_->AddUnreadContentObserver(kForYouStream, &observer);
+ // Load content from the network, and view it.
+ {
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ TestForYouSurface surface(stream_.get());
+ WaitForIdleTaskQueue();
+
+ stream_->ReportSliceViewed(
+ surface.GetSurfaceId(), surface.GetStreamType(),
+ surface.initial_state->updated_slices(1).slice().slice_id());
+ }
+ // Wait until the feed content is stale.
+
+ task_environment_.FastForwardBy(base::TimeDelta::FromHours(100));
+
+ // Load content from the network again. This time there is no new content.
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ TestForYouSurface surface(stream_.get());
+ WaitForIdleTaskQueue();
+
+ EXPECT_EQ(std::vector<bool>({false, true, false}), observer.calls);
+}
+
TEST_F(FeedApiTest, RemovedUnreadContentObserverDoesNotReceiveCalls) {
response_translator_.InjectResponse(MakeTypicalInitialModelState());
TestUnreadContentObserver observer;
@@ -816,7 +920,7 @@ TEST_F(FeedApiTest, RemovedUnreadContentObserverDoesNotReceiveCalls) {
WaitForIdleTaskQueue();
- EXPECT_EQ(std::vector<bool>(), observer.calls);
+ EXPECT_EQ(std::vector<bool>({false}), observer.calls);
}
TEST_F(FeedApiTest, DeletedUnreadContentObserverDoesNotCrash) {
@@ -833,10 +937,9 @@ TEST_F(FeedApiTest, DeletedUnreadContentObserverDoesNotCrash) {
TEST_F(FeedApiTest, HasUnreadContentAfterLoadFromStore) {
store_->OverwriteStream(kForYouStream, MakeTypicalInitialModelState(),
base::DoNothing());
-
+ TestForYouSurface surface(stream_.get());
TestUnreadContentObserver observer;
stream_->AddUnreadContentObserver(kForYouStream, &observer);
- TestForYouSurface surface(stream_.get());
WaitForIdleTaskQueue();
@@ -845,10 +948,9 @@ TEST_F(FeedApiTest, HasUnreadContentAfterLoadFromStore) {
TEST_F(FeedApiTest, ReportSliceViewedUpdatesObservers) {
response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ TestForYouSurface surface(stream_.get());
TestUnreadContentObserver observer;
stream_->AddUnreadContentObserver(kForYouStream, &observer);
- TestForYouSurface surface(stream_.get());
-
WaitForIdleTaskQueue();
stream_->ReportSliceViewed(
@@ -882,7 +984,7 @@ TEST_P(FeedStreamTestForAllStreamTypes, LoadMoreAppendsContent) {
// Ensure metrics reporter was informed at the start of the operation.
EXPECT_EQ(surface.GetSurfaceId(), metrics_reporter_->load_more_surface_id);
WaitForIdleTaskQueue();
- ASSERT_EQ(base::Optional<bool>(true), callback.GetResult());
+ ASSERT_EQ(absl::optional<bool>(true), callback.GetResult());
EXPECT_EQ("2 slices +spinner -> 4 slices", surface.DescribeUpdates());
// Load page 3.
@@ -890,13 +992,8 @@ TEST_P(FeedStreamTestForAllStreamTypes, LoadMoreAppendsContent) {
stream_->LoadMore(surface, callback.Bind());
WaitForIdleTaskQueue();
- ASSERT_EQ(base::Optional<bool>(true), callback.GetResult());
+ ASSERT_EQ(absl::optional<bool>(true), callback.GetResult());
EXPECT_EQ("4 slices +spinner -> 6 slices", surface.DescribeUpdates());
- if (GetStreamType().IsForYou()) {
- EXPECT_EQ(3, prefetch_service_.NewSuggestionsAvailableCallCount());
- } else {
- EXPECT_EQ(0, prefetch_service_.NewSuggestionsAvailableCallCount());
- }
}
TEST_P(FeedStreamTestForAllStreamTypes, LoadMorePersistsData) {
@@ -911,7 +1008,7 @@ TEST_P(FeedStreamTestForAllStreamTypes, LoadMorePersistsData) {
stream_->LoadMore(surface, callback.Bind());
WaitForIdleTaskQueue();
- ASSERT_EQ(base::Optional<bool>(true), callback.GetResult());
+ ASSERT_EQ(absl::optional<bool>(true), callback.GetResult());
// Verify stored state is equivalent to in-memory model.
EXPECT_STRINGS_EQUAL(
@@ -932,7 +1029,7 @@ TEST_F(FeedApiTest, LoadMorePersistAndLoadMore) {
CallbackReceiver<bool> callback;
stream_->LoadMore(surface, callback.Bind());
WaitForIdleTaskQueue();
- ASSERT_EQ(base::Optional<bool>(true), callback.GetResult());
+ ASSERT_EQ(absl::optional<bool>(true), callback.GetResult());
surface.Detach();
UnloadModel(kForYouStream);
@@ -946,7 +1043,7 @@ TEST_F(FeedApiTest, LoadMorePersistAndLoadMore) {
stream_->LoadMore(surface, callback.Bind());
WaitForIdleTaskQueue();
- ASSERT_EQ(base::Optional<bool>(true), callback.GetResult());
+ ASSERT_EQ(absl::optional<bool>(true), callback.GetResult());
ASSERT_EQ("4 slices +spinner -> 6 slices", surface.DescribeUpdates());
// Verify stored state is equivalent to in-memory model.
EXPECT_STRINGS_EQUAL(
@@ -1013,10 +1110,10 @@ TEST_F(FeedApiTest, LoadMoreAbortsIfNoNextPageToken) {
WaitForIdleTaskQueue();
// LoadMore fails, and does not make an additional request.
- EXPECT_EQ(base::Optional<bool>(false), callback.GetResult());
+ EXPECT_EQ(absl::optional<bool>(false), callback.GetResult());
ASSERT_EQ(1, network_.send_query_call_count);
EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates());
- EXPECT_EQ(base::nullopt, metrics_reporter_->load_more_surface_id)
+ EXPECT_EQ(absl::nullopt, metrics_reporter_->load_more_surface_id)
<< "metrics reporter was informed about a load more operation which "
"didn't begin";
}
@@ -1033,7 +1130,7 @@ TEST_F(FeedApiTest, LoadMoreFail) {
stream_->LoadMore(surface, callback.Bind());
WaitForIdleTaskQueue();
- EXPECT_EQ(base::Optional<bool>(false), callback.GetResult());
+ EXPECT_EQ(absl::optional<bool>(false), callback.GetResult());
EXPECT_EQ("2 slices +spinner -> 2 slices", surface.DescribeUpdates());
}
@@ -1049,7 +1146,7 @@ TEST_F(FeedApiTest, LoadMoreWithClearAllInResponse) {
stream_->LoadMore(surface, callback.Bind());
WaitForIdleTaskQueue();
- ASSERT_EQ(base::Optional<bool>(true), callback.GetResult());
+ ASSERT_EQ(absl::optional<bool>(true), callback.GetResult());
// Verify stored state is equivalent to in-memory model.
EXPECT_STRINGS_EQUAL(
@@ -1078,7 +1175,7 @@ TEST_F(FeedApiTest, LoadMoreBeforeLoad) {
TestForYouSurface surface;
stream_->LoadMore(surface, callback.Bind());
- EXPECT_EQ(base::Optional<bool>(false), callback.GetResult());
+ EXPECT_EQ(absl::optional<bool>(false), callback.GetResult());
}
TEST_F(FeedApiTest, ReadNetworkResponse) {
@@ -1109,7 +1206,20 @@ TEST_F(FeedApiTest, ReadNetworkResponse) {
// The stream's user attributes are set, so activity logging is enabled.
EXPECT_TRUE(stream_->IsActivityLoggingEnabled(kForYouStream));
- EXPECT_EQ(1, prefetch_service_.NewSuggestionsAvailableCallCount());
+ // This network response has content.
+ EXPECT_TRUE(stream_->HasUnreadContent(kForYouStream));
+}
+
+TEST_F(FeedApiTest, ReadNetworkResponseWithNoContent) {
+ base::HistogramTester histograms;
+ network_.InjectRealFeedQueryResponseWithNoContent();
+ TestForYouSurface surface(stream_.get());
+ WaitForIdleTaskQueue();
+
+ ASSERT_EQ("loading -> loading -> no-cards", surface.DescribeUpdates());
+
+ // This network response has no content.
+ EXPECT_FALSE(stream_->HasUnreadContent(kForYouStream));
}
TEST_F(FeedApiTest, ClearAllAfterLoadResultsInRefresh) {
@@ -2009,6 +2119,149 @@ TEST_F(FeedApiTest, StreamDataOverwritesOldStream) {
EXPECT_EQ("new-frame-data", stored_data->content[0].frame());
}
+TEST_F(FeedApiTest, ReliabilityLoggingId_GetAndReset) {
+ // If nothing changes between two calls to GetReliabilityLoggingId(), it
+ // should return the same ID.
+ uint64_t first_id =
+ FeedService::GetReliabilityLoggingId(/*metrics_id=*/"", &profile_prefs_);
+ EXPECT_EQ(first_id, FeedService::GetReliabilityLoggingId(/*metrics_id=*/"",
+ &profile_prefs_));
+
+ profile_prefs_.ClearPref(prefs::kReliabilityLoggingIdSalt);
+ EXPECT_NE(first_id, FeedService::GetReliabilityLoggingId(/*metrics_id=*/"",
+ &profile_prefs_));
+}
+
+TEST_F(FeedApiTest, ReliabilityLoggingId_ChangeOnMetricsIdChange) {
+ const char kSomeMetricsId[] = "metrics-id-1";
+ uint64_t first_id =
+ FeedService::GetReliabilityLoggingId(kSomeMetricsId, &profile_prefs_);
+ EXPECT_NE(first_id, FeedService::GetReliabilityLoggingId("metrics-id-2",
+ &profile_prefs_));
+
+ // If we use the original metrics ID, we should get the original ID unless
+ // the salt is cleared.
+ EXPECT_EQ(first_id, FeedService::GetReliabilityLoggingId(kSomeMetricsId,
+ &profile_prefs_));
+ profile_prefs_.ClearPref(prefs::kReliabilityLoggingIdSalt);
+ EXPECT_NE(first_id, FeedService::GetReliabilityLoggingId(kSomeMetricsId,
+ &profile_prefs_));
+}
+
+TEST_F(FeedApiTest, HasUnreadContentIsFalseAfterSliceView) {
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ TestForYouSurface surface(stream_.get());
+ WaitForIdleTaskQueue();
+ EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates());
+ ASSERT_TRUE(stream_->HasUnreadContent(kForYouStream));
+ stream_->ReportSliceViewed(
+ surface.GetSurfaceId(), surface.GetStreamType(),
+ surface.initial_state->updated_slices(1).slice().slice_id());
+
+ EXPECT_FALSE(stream_->HasUnreadContent(kForYouStream));
+}
+
+TEST_F(FeedApiTest,
+ LoadingForYouStreamTriggersWebFeedRefreshIfNoUnreadContent) {
+ Config config = GetFeedConfig();
+ config.refresh_web_feed_after_for_you_feed_loads = true;
+ SetFeedConfigForTesting(config);
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeature(kWebFeed);
+
+ // Both streams should be fetched.
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ TestForYouSurface surface(stream_.get());
+ WaitForIdleTaskQueue();
+ ASSERT_EQ(2, network_.send_query_call_count);
+ EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates());
+ EXPECT_EQ(LoadStreamStatus::kLoadedFromNetwork,
+ metrics_reporter_->load_stream_status);
+
+ // Attach a Web Feed surface, and verify content is loaded from the store.
+ TestWebFeedSurface web_feed_surface(stream_.get());
+ WaitForIdleTaskQueue();
+
+ EXPECT_EQ("loading -> 2 slices", web_feed_surface.DescribeUpdates());
+ EXPECT_EQ(LoadStreamStatus::kLoadedFromStore,
+ metrics_reporter_->load_stream_status);
+}
+
+TEST_F(
+ FeedApiTest,
+ LoadForYouStreamDoesNotTriggerWebFeedRefreshContentIfIsAlreadyAvailable) {
+ Config config = GetFeedConfig();
+ config.refresh_web_feed_after_for_you_feed_loads = true;
+ SetFeedConfigForTesting(config);
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeature(kWebFeed);
+
+ // Both streams should be fetched because there is no unread web-feed content.
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ TestForYouSurface surface(stream_.get());
+ WaitForIdleTaskQueue();
+ ASSERT_EQ(2, network_.send_query_call_count);
+
+ // Detach and re-attach the surface. The for-you feed should be loaded again,
+ // but this time the web-feed is not refreshed.
+ surface.Detach();
+ UnloadModel(surface.GetStreamType());
+ surface.Attach(stream_.get());
+ WaitForIdleTaskQueue();
+ // Neither stream type should be refreshed.
+ ASSERT_EQ(2, network_.send_query_call_count);
+}
+
+TEST_F(FeedApiTest, WasUrlRecentlyNavigatedFromFeed) {
+ const GURL url1("https://someurl1");
+ const GURL url2("https://someurl2");
+ EXPECT_FALSE(stream_->WasUrlRecentlyNavigatedFromFeed(url1));
+ EXPECT_FALSE(stream_->WasUrlRecentlyNavigatedFromFeed(url2));
+
+ stream_->ReportOpenAction(url1, kForYouStream, "slice");
+ stream_->ReportOpenInNewTabAction(url2, kForYouStream, "slice");
+
+ EXPECT_TRUE(stream_->WasUrlRecentlyNavigatedFromFeed(url1));
+ EXPECT_TRUE(stream_->WasUrlRecentlyNavigatedFromFeed(url2));
+}
+
+// After 10 URLs are navigated, they are forgotten in FIFO order.
+TEST_F(FeedApiTest, WasUrlRecentlyNavigatedFromFeedMaxHistory) {
+ std::vector<GURL> urls;
+ for (int i = 0; i < 11; ++i)
+ urls.emplace_back("https://someurl" + base::NumberToString(i));
+
+ for (const GURL& url : urls)
+ stream_->ReportOpenAction(url, kForYouStream, "slice");
+
+ EXPECT_FALSE(stream_->WasUrlRecentlyNavigatedFromFeed(urls[0]));
+ for (size_t i = 1; i < urls.size(); ++i) {
+ EXPECT_TRUE(stream_->WasUrlRecentlyNavigatedFromFeed(urls[i]));
+ }
+}
+
+TEST_F(FeedApiTest, ClearAllOnStartupIfFeedIsDisabled) {
+ CallbackReceiver<> on_clear_all;
+ on_clear_all_ = on_clear_all.BindRepeating();
+
+ // Fetch a feed, so that there's stored data.
+ response_translator_.InjectResponse(MakeTypicalInitialModelState());
+ TestForYouSurface surface(stream_.get());
+ WaitForIdleTaskQueue();
+
+ // Turn off the feed, and re-create FeedStream. It should perform a ClearAll.
+ profile_prefs_.SetBoolean(feed::prefs::kEnableSnippets, false);
+ CreateStream();
+ EXPECT_TRUE(on_clear_all.called());
+
+ // Re-create the feed, and verify ClearAll isn't called again.
+ on_clear_all.Clear();
+ CreateStream();
+ EXPECT_FALSE(on_clear_all.called());
+}
+
// Keep instantiations at the bottom.
INSTANTIATE_TEST_SUITE_P(FeedApiTest,
FeedStreamTestForAllStreamTypes,
diff --git a/chromium/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc b/chromium/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc
index 6ab23be9197..9f5e545a42c 100644
--- a/chromium/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc
+++ b/chromium/components/feed/core/v2/api_test/feed_api_subscriptions_unittest.cc
@@ -6,8 +6,12 @@
#include "components/feed/core/v2/api_test/feed_api_test.h"
#include "components/feed/core/v2/config.h"
+#include "components/feed/core/v2/feed_network.h"
#include "components/feed/core/v2/feed_stream.h"
+#include "components/feed/core/v2/feedstore_util.h"
+#include "components/feed/core/v2/public/feed_api.h"
#include "components/feed/core/v2/public/types.h"
+#include "components/feed/core/v2/public/web_feed_subscriptions.h"
#include "components/feed/core/v2/test/callback_receiver.h"
#include "components/feed/feed_feature_list.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -176,6 +180,7 @@ TEST_F(FeedApiSubscriptionsTest, FollowWebFeedSuccess) {
"WebFeedMetadata{ id=id_cats title=Title cats "
"publisher_url=https://cats.com/ status=kSubscribed }",
PrintToString(callback.RunAndGetResult().web_feed_metadata));
+ EXPECT_TRUE(feedstore::IsKnownStale(stream_->GetMetadata(), kWebFeedStream));
}
TEST_F(FeedApiSubscriptionsTest, FollowRecommendedWebFeedById) {
@@ -277,6 +282,7 @@ TEST_F(FeedApiSubscriptionsTest, CantFollowWebFeedWhileOffline) {
TEST_F(FeedApiSubscriptionsTest, FollowWebFeedNetworkError) {
network_.InjectFollowResponse(MakeFailedResponse());
CallbackReceiver<WebFeedSubscriptions::FollowWebFeedResult> callback;
+ EXPECT_FALSE(feedstore::IsKnownStale(stream_->GetMetadata(), kWebFeedStream));
subscriptions().FollowWebFeed(MakeWebFeedPageInformation("http://cats.com"),
callback.Bind());
@@ -284,6 +290,7 @@ TEST_F(FeedApiSubscriptionsTest, FollowWebFeedNetworkError) {
EXPECT_EQ(WebFeedSubscriptionRequestStatus::kFailedUnknownError,
callback.RunAndGetResult().request_status);
EXPECT_EQ("{}", PrintToString(CheckAllSubscriptions()));
+ EXPECT_FALSE(feedstore::IsKnownStale(stream_->GetMetadata(), kWebFeedStream));
}
// Follow and then unfollow a web feed successfully.
@@ -293,7 +300,8 @@ TEST_F(FeedApiSubscriptionsTest, UnfollowAFollowedWebFeed) {
subscriptions().FollowWebFeed(MakeWebFeedPageInformation("http://cats.com"),
follow_callback.Bind());
follow_callback.RunUntilCalled();
-
+ // Un-mark stream as stale, to verify unsubscribe also marks stream as stale.
+ stream_->SetStreamStale(kWebFeedStream, false);
CallbackReceiver<WebFeedSubscriptions::UnfollowWebFeedResult>
unfollow_callback;
network_.InjectResponse(SuccessfulUnfollowResponse());
@@ -306,6 +314,7 @@ TEST_F(FeedApiSubscriptionsTest, UnfollowAFollowedWebFeed) {
EXPECT_EQ(WebFeedSubscriptionRequestStatus::kSuccess,
unfollow_callback.GetResult()->request_status);
EXPECT_EQ("{}", PrintToString(CheckAllSubscriptions()));
+ EXPECT_TRUE(feedstore::IsKnownStale(stream_->GetMetadata(), kWebFeedStream));
}
TEST_F(FeedApiSubscriptionsTest, UnfollowAFollowedWebFeedTwiceAtOnce) {
@@ -347,6 +356,8 @@ TEST_F(FeedApiSubscriptionsTest, UnfollowNetworkFailure) {
CallbackReceiver<WebFeedSubscriptions::UnfollowWebFeedResult>
unfollow_callback;
network_.InjectUnfollowResponse(MakeFailedResponse());
+ // Un-mark stream as stale, to verify unsubscribe also marks stream as stale.
+ stream_->SetStreamStale(kWebFeedStream, false);
subscriptions().UnfollowWebFeed(
follow_callback.GetResult()->web_feed_metadata.web_feed_id,
unfollow_callback.Bind());
@@ -359,6 +370,7 @@ TEST_F(FeedApiSubscriptionsTest, UnfollowNetworkFailure) {
"{ WebFeedMetadata{ id=id_cats title=Title cats "
"publisher_url=https://cats.com/ status=kSubscribed } }",
PrintToString(CheckAllSubscriptions()));
+ EXPECT_FALSE(feedstore::IsKnownStale(stream_->GetMetadata(), kWebFeedStream));
}
TEST_F(FeedApiSubscriptionsTest, UnfollowWhileOffline) {
@@ -624,6 +636,20 @@ TEST_F(FeedApiSubscriptionsTest,
ASSERT_EQ(0, network_.GetListRecommendedWebFeedsRequestCount());
}
+TEST_F(
+ FeedApiSubscriptionsTest,
+ RecommendedAndFollowedWebFeedsAreNotFetchedAfterStartupWhenFeedIsDisabled) {
+ profile_prefs_.SetBoolean(feed::prefs::kEnableSnippets, false);
+ SetUpWithDefaultConfig();
+
+ // Wait until the delayed task would normally run, verify no request is made.
+ task_environment_.FastForwardBy(GetFeedConfig().fetch_web_feed_info_delay +
+ base::TimeDelta::FromSeconds(1));
+ WaitForIdleTaskQueue();
+ EXPECT_EQ(0, network_.GetListRecommendedWebFeedsRequestCount());
+ EXPECT_EQ(0, network_.GetListFollowedWebFeedsRequestCount());
+}
+
TEST_F(FeedApiSubscriptionsTest, RecommendedWebFeedsAreFetchedAfterStartup) {
SetUpWithDefaultConfig();
InjectRecommendedWebFeedsResponse({MakeWireWebFeed("cats")});
@@ -705,7 +731,7 @@ TEST_F(FeedApiSubscriptionsTest,
}
TEST_F(FeedApiSubscriptionsTest,
- RecommendedWebFeedsAreNotFetchedAfterStartupWhenDataIsFresh) {
+ RecommendedWebFeedsAreFetchedAfterStartupOnlyWhenStale) {
// 1. First, fetch recommended web feeds at startup, same as
// RecommendedWebFeedsAreFetchedAfterStartup.
{
@@ -785,6 +811,7 @@ TEST_F(FeedApiSubscriptionsTest, SubscribedWebFeedsAreFetchedAfterStartup) {
"{ WebFeedMetadata{ id=id_cats title=Title cats "
"publisher_url=https://cats.com/ status=kSubscribed } }",
PrintToString(CheckAllSubscriptions()));
+ EXPECT_TRUE(subscriptions().IsWebFeedSubscriber());
}
TEST_F(FeedApiSubscriptionsTest, SubscribedWebFeedsAreClearedOnSignOut) {
@@ -810,7 +837,8 @@ TEST_F(FeedApiSubscriptionsTest, SubscribedWebFeedsAreClearedOnSignOut) {
stream_->OnSignedOut();
WaitForIdleTaskQueue();
ASSERT_EQ(1, network_.GetListFollowedWebFeedsRequestCount());
- EXPECT_EQ("{}", PrintToString(CheckRecommendedFeeds()));
+ EXPECT_EQ("{}", PrintToString(CheckAllSubscriptions()));
+ EXPECT_FALSE(subscriptions().IsWebFeedSubscriber());
}
TEST_F(FeedApiSubscriptionsTest,
@@ -846,8 +874,8 @@ TEST_F(FeedApiSubscriptionsTest,
TEST_F(FeedApiSubscriptionsTest,
SubscribedWebFeedsAreFetchedAfterStartupOnlyWhenStale) {
- // 1. First, fetch recommended web feeds at startup, same as
- // RecommendedWebFeedsAreFetchedAfterStartup.
+ // 1. First, fetch subscribed web feeds at startup, same as
+ // SubscribedWebFeedsAreFetchedAfterStartup.
{
SetUpWithDefaultConfig();
InjectListWebFeedsResponse({MakeWireWebFeed("cats")});
@@ -858,7 +886,7 @@ TEST_F(FeedApiSubscriptionsTest,
ASSERT_EQ(1, network_.GetListFollowedWebFeedsRequestCount());
}
- // 2. Recreate FeedStream, and verify recommended web feeds are not fetched
+ // 2. Recreate FeedStream, and verify subscribed web feeds are not fetched
// again.
{
CreateStream();
@@ -869,17 +897,16 @@ TEST_F(FeedApiSubscriptionsTest,
ASSERT_EQ(1, network_.GetListFollowedWebFeedsRequestCount());
}
- // 3. Wait until the data is stale, and then verify the recommended web feeds
+ // 3. Wait until the data is stale, and then verify the subscribed web feeds
// are fetched again.
{
task_environment_.FastForwardBy(
- GetFeedConfig().recommended_feeds_staleness_threshold);
+ GetFeedConfig().subscribed_feeds_staleness_threshold);
InjectListWebFeedsResponse({MakeWireWebFeed("catsv2")});
CreateStream();
- task_environment_.FastForwardBy(
- GetFeedConfig().subscribed_feeds_staleness_threshold +
- base::TimeDelta::FromSeconds(1));
+ task_environment_.FastForwardBy(GetFeedConfig().fetch_web_feed_info_delay +
+ base::TimeDelta::FromSeconds(1));
WaitForIdleTaskQueue();
ASSERT_EQ(2, network_.GetListFollowedWebFeedsRequestCount());
EXPECT_EQ(
@@ -889,6 +916,52 @@ TEST_F(FeedApiSubscriptionsTest,
}
}
+TEST_F(FeedApiSubscriptionsTest, RefreshSubscriptionsSuccess) {
+ CallbackReceiver<WebFeedSubscriptions::RefreshResult> result;
+ InjectListWebFeedsResponse({MakeWireWebFeed("cats")});
+ subscriptions().RefreshSubscriptions(result.Bind());
+
+ WaitForIdleTaskQueue();
+
+ EXPECT_TRUE(result.RunAndGetResult().success);
+
+ EXPECT_EQ(
+ "{ WebFeedMetadata{ id=id_cats title=Title cats "
+ "publisher_url=https://cats.com/ status=kSubscribed } }",
+ PrintToString(CheckAllSubscriptions()));
+}
+
+TEST_F(FeedApiSubscriptionsTest, RefreshSubscriptionsFail) {
+ CallbackReceiver<WebFeedSubscriptions::RefreshResult> result;
+
+ network_.InjectApiRawResponse<ListWebFeedsDiscoverApi>(MakeFailedResponse());
+ subscriptions().RefreshSubscriptions(result.Bind());
+
+ WaitForIdleTaskQueue();
+
+ EXPECT_FALSE(result.RunAndGetResult().success);
+}
+
+// Two calls to RefreshSubscriptions at the same time, so only one refresh
+// occurs.
+TEST_F(FeedApiSubscriptionsTest, RefreshSubscriptionsDuringRefresh) {
+ CallbackReceiver<WebFeedSubscriptions::RefreshResult> result1;
+ CallbackReceiver<WebFeedSubscriptions::RefreshResult> result2;
+ InjectListWebFeedsResponse({MakeWireWebFeed("cats")});
+ subscriptions().RefreshSubscriptions(result1.Bind());
+ subscriptions().RefreshSubscriptions(result2.Bind());
+
+ WaitForIdleTaskQueue();
+
+ EXPECT_TRUE(result1.RunAndGetResult().success);
+ EXPECT_TRUE(result2.RunAndGetResult().success);
+
+ EXPECT_EQ(
+ "{ WebFeedMetadata{ id=id_cats title=Title cats "
+ "publisher_url=https://cats.com/ status=kSubscribed } }",
+ PrintToString(CheckAllSubscriptions()));
+}
+
} // namespace
} // namespace test
} // namespace feed
diff --git a/chromium/components/feed/core/v2/api_test/feed_api_test.cc b/chromium/components/feed/core/v2/api_test/feed_api_test.cc
index c942299cbb9..debe207c698 100644
--- a/chromium/components/feed/core/v2/api_test/feed_api_test.cc
+++ b/chromium/components/feed/core/v2/api_test/feed_api_test.cc
@@ -4,6 +4,8 @@
#include "components/feed/core/v2/api_test/feed_api_test.h"
#include "components/feed/core/proto/v2/wire/web_feeds.pb.h"
+#include "components/feed/core/v2/enums.h"
+#include "components/feed/core/v2/feed_network.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "base/callback.h"
@@ -34,7 +36,6 @@
#include "components/feed/core/v2/test/test_util.h"
#include "components/feed/feed_feature_list.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
-#include "components/offline_pages/core/client_namespace_constants.h"
namespace feed {
namespace test {
@@ -59,7 +60,7 @@ std::unique_ptr<StreamModelUpdateRequest> StoredModelData(
result = std::move(task_result);
};
LoadStreamFromStoreTask load_task(
- LoadStreamFromStoreTask::LoadType::kFullLoad, stream_type, store,
+ LoadStreamFromStoreTask::LoadType::kFullLoad, nullptr, stream_type, store,
/*missed_last_refresh=*/false, base::BindLambdaForTesting(complete));
// We want to load the data no matter how stale.
load_task.IgnoreStalenessForTesting();
@@ -175,15 +176,15 @@ void TestSurfaceBase::StreamUpdate(const feedui::StreamUpdate& stream_update) {
}
void TestSurfaceBase::ReplaceDataStoreEntry(base::StringPiece key,
base::StringPiece data) {
- data_store_entries_[key.as_string()] = data.as_string();
+ data_store_entries_[std::string(key)] = std::string(data);
}
void TestSurfaceBase::RemoveDataStoreEntry(base::StringPiece key) {
- data_store_entries_.erase(key.as_string());
+ data_store_entries_.erase(std::string(key));
}
void TestSurfaceBase::Clear() {
- initial_state = base::nullopt;
- update = base::nullopt;
+ initial_state = absl::nullopt;
+ update = absl::nullopt;
described_updates_.clear();
}
@@ -262,10 +263,9 @@ TestFeedNetwork::~TestFeedNetwork() = default;
void TestFeedNetwork::SendQueryRequest(
NetworkRequestType request_type,
const feedwire::Request& request,
- bool force_signed_out_request,
const std::string& gaia,
base::OnceCallback<void(QueryRequestResult)> callback) {
- forced_signed_out_request = force_signed_out_request;
+ last_gaia = gaia;
++send_query_call_count;
// Emulate a successful response.
// The response body is currently an empty message, because most of the
@@ -298,61 +298,111 @@ void DebugLogApiResponse(std::string request_bytes,
}
}
-void DebugLogResponse(base::StringPiece api_path,
+void DebugLogResponse(NetworkRequestType request_type,
+ base::StringPiece api_path,
base::StringPiece method,
std::string request_bytes,
const FeedNetwork::RawResponse& raw_response) {
VLOG(1) << "TestFeedNetwork responding to request " << method << " "
<< api_path;
- if (api_path == UploadActionsDiscoverApi::RequestPath()) {
+ if (request_type == UploadActionsDiscoverApi::kRequestType) {
DebugLogApiResponse<UploadActionsDiscoverApi>(request_bytes, raw_response);
- } else if (api_path == ListRecommendedWebFeedDiscoverApi::RequestPath()) {
+ } else if (request_type == ListRecommendedWebFeedDiscoverApi::kRequestType) {
DebugLogApiResponse<ListRecommendedWebFeedDiscoverApi>(request_bytes,
raw_response);
- } else if (api_path == ListWebFeedsDiscoverApi::RequestPath()) {
+ } else if (request_type == ListWebFeedsDiscoverApi::kRequestType) {
DebugLogApiResponse<ListWebFeedsDiscoverApi>(request_bytes, raw_response);
}
}
void TestFeedNetwork::SendDiscoverApiRequest(
+ NetworkRequestType request_type,
base::StringPiece api_path,
base::StringPiece method,
std::string request_bytes,
const std::string& gaia,
base::OnceCallback<void(RawResponse)> callback) {
- api_requests_sent_[api_path.as_string()] = request_bytes;
- ++api_request_count_[api_path.as_string()];
+ last_gaia = gaia;
+ api_requests_sent_[request_type] = request_bytes;
+ ++api_request_count_[request_type];
std::vector<RawResponse>& injected_responses =
- injected_api_responses_[api_path.as_string()];
+ injected_api_responses_[request_type];
+
+ bool is_feed_query_request =
+ request_type == NetworkRequestType::kFeedQuery ||
+ request_type == WebFeedListContentsDiscoverApi::kRequestType ||
+ request_type == QueryInteractiveFeedDiscoverApi::kRequestType ||
+ request_type == QueryBackgroundFeedDiscoverApi::kRequestType ||
+ request_type == QueryNextPageDiscoverApi::kRequestType;
+
+ if (is_feed_query_request) {
+ feedwire::Request request_proto;
+ request_proto.ParseFromString(request_bytes);
+ query_request_sent = request_proto;
+ send_query_call_count++;
+ }
// If there is no injected response, create a default response.
if (injected_responses.empty()) {
- if (api_path == UploadActionsDiscoverApi::RequestPath()) {
- feedwire::UploadActionsRequest request;
- ASSERT_TRUE(request.ParseFromString(request_bytes));
- feedwire::UploadActionsResponse response_message;
- response_message.mutable_consistency_token()->set_token(
- consistency_token);
- InjectApiResponse<UploadActionsDiscoverApi>(response_message);
- }
- if (api_path == ListRecommendedWebFeedDiscoverApi::RequestPath()) {
- feedwire::webfeed::ListRecommendedWebFeedsRequest request;
- ASSERT_TRUE(request.ParseFromString(request_bytes));
- feedwire::webfeed::ListRecommendedWebFeedsResponse response_message;
- InjectResponse(response_message);
- }
- if (api_path == ListWebFeedsDiscoverApi::RequestPath()) {
- feedwire::webfeed::ListWebFeedsRequest request;
- ASSERT_TRUE(request.ParseFromString(request_bytes));
- feedwire::webfeed::ListWebFeedsResponse response_message;
- InjectResponse(response_message);
+ switch (request_type) {
+ case UploadActionsDiscoverApi::kRequestType: {
+ feedwire::UploadActionsRequest request;
+ ASSERT_TRUE(request.ParseFromString(request_bytes));
+ feedwire::UploadActionsResponse response_message;
+ response_message.mutable_consistency_token()->set_token(
+ consistency_token);
+ InjectApiResponse<UploadActionsDiscoverApi>(response_message);
+ break;
+ }
+ case ListRecommendedWebFeedDiscoverApi::kRequestType: {
+ feedwire::webfeed::ListRecommendedWebFeedsRequest request;
+ ASSERT_TRUE(request.ParseFromString(request_bytes));
+ feedwire::webfeed::ListRecommendedWebFeedsResponse response_message;
+ InjectResponse(response_message);
+ break;
+ }
+ case ListWebFeedsDiscoverApi::kRequestType: {
+ feedwire::webfeed::ListWebFeedsRequest request;
+ ASSERT_TRUE(request.ParseFromString(request_bytes));
+ feedwire::webfeed::ListWebFeedsResponse response_message;
+ InjectResponse(response_message);
+ break;
+ }
+
+ // For FeedQuery requests, emulate a successful response.
+ // The response body is currently an empty message, because most of the
+ // time we want to inject a translated response for ease of
+ // test-writing.
+
+ case WebFeedListContentsDiscoverApi::kRequestType: {
+ feedwire::Response response;
+ InjectApiResponse<WebFeedListContentsDiscoverApi>(response);
+ break;
+ }
+ case QueryInteractiveFeedDiscoverApi::kRequestType: {
+ feedwire::Response response;
+ InjectApiResponse<QueryInteractiveFeedDiscoverApi>(response);
+ break;
+ }
+ case QueryBackgroundFeedDiscoverApi::kRequestType: {
+ feedwire::Response response;
+ InjectApiResponse<QueryBackgroundFeedDiscoverApi>(response);
+ break;
+ }
+ case QueryNextPageDiscoverApi::kRequestType: {
+ feedwire::Response response;
+ InjectApiResponse<QueryNextPageDiscoverApi>(response);
+ break;
+ }
+ default:
+ break;
}
}
if (!injected_responses.empty()) {
RawResponse response = injected_responses[0];
injected_responses.erase(injected_responses.begin());
- DebugLogResponse(api_path, method, request_bytes, response);
+ DebugLogResponse(request_type, api_path, method, request_bytes, response);
Reply(base::BindOnce(std::move(callback), std::move(response)));
return;
}
@@ -378,11 +428,29 @@ void TestFeedNetwork::InjectRealFeedQueryResponse() {
injected_response_ = response;
}
+void TestFeedNetwork::InjectRealFeedQueryResponseWithNoContent() {
+ base::FilePath response_file_path;
+ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &response_file_path));
+ response_file_path = response_file_path.AppendASCII(
+ "components/test/data/feed/response.binarypb");
+ std::string response_data;
+ CHECK(base::ReadFileToString(response_file_path, &response_data));
+
+ feedwire::Response response;
+ CHECK(response.ParseFromString(response_data));
+ // Keep only the first two operations, the CLEAR_ALL and root, but no content.
+ auto* data_operations =
+ response.mutable_feed_response()->mutable_data_operation();
+ data_operations->erase(data_operations->begin() + 2, data_operations->end());
+
+ injected_response_ = response;
+}
+
void TestFeedNetwork::InjectEmptyActionRequestResult() {
InjectApiRawResponse<UploadActionsDiscoverApi>({});
}
-base::Optional<feedwire::UploadActionsRequest>
+absl::optional<feedwire::UploadActionsRequest>
TestFeedNetwork::GetActionRequestSent() {
return GetApiRequestSent<UploadActionsDiscoverApi>();
}
@@ -454,7 +522,7 @@ RefreshResponseData TestWireResponseTranslator::TranslateWireResponse(
}
void TestWireResponseTranslator::InjectResponse(
std::unique_ptr<StreamModelUpdateRequest> response,
- base::Optional<std::string> session_id) {
+ absl::optional<std::string> session_id) {
DCHECK(!response->stream_data.signed_in() || !session_id);
RefreshResponseData data;
data.model_update_request = std::move(response);
@@ -531,66 +599,6 @@ void TestMetricsReporter::OnUploadActions(UploadActionsStatus status) {
MetricsReporter::OnUploadActions(status);
}
-TestPrefetchService::TestPrefetchService() = default;
-TestPrefetchService::~TestPrefetchService() = default;
-void TestPrefetchService::SetSuggestionProvider(
- offline_pages::SuggestionsProvider* suggestions_provider) {
- suggestions_provider_ = suggestions_provider;
-}
-void TestPrefetchService::NewSuggestionsAvailable() {
- ++new_suggestions_available_call_count_;
-}
-
-offline_pages::SuggestionsProvider*
-TestPrefetchService::suggestions_provider() {
- return suggestions_provider_;
-}
-int TestPrefetchService::NewSuggestionsAvailableCallCount() const {
- return new_suggestions_available_call_count_;
-}
-TestOfflinePageModel::TestOfflinePageModel() = default;
-TestOfflinePageModel::~TestOfflinePageModel() = default;
-void TestOfflinePageModel::AddObserver(Observer* observer) {
- CHECK(observers_.insert(observer).second);
-}
-void TestOfflinePageModel::RemoveObserver(Observer* observer) {
- CHECK_EQ(1UL, observers_.erase(observer));
-}
-void TestOfflinePageModel::GetPagesWithCriteria(
- const offline_pages::PageCriteria& criteria,
- offline_pages::MultipleOfflinePageItemCallback callback) {
- std::vector<offline_pages::OfflinePageItem> result;
- for (const offline_pages::OfflinePageItem& item : items_) {
- if (MeetsCriteria(criteria, item)) {
- result.push_back(item);
- }
- }
- base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), result));
-}
-
-void TestOfflinePageModel::AddTestPage(const GURL& url) {
- offline_pages::OfflinePageItem item;
- item.url = url;
- item.client_id =
- offline_pages::ClientId(offline_pages::kSuggestedArticlesNamespace, "");
- items_.push_back(item);
-}
-
-void TestOfflinePageModel::CallObserverOfflinePageAdded(
- const offline_pages::OfflinePageItem& item) {
- for (Observer* observer : observers_) {
- observer->OfflinePageAdded(this, item);
- }
-}
-
-void TestOfflinePageModel::CallObserverOfflinePageDeleted(
- const offline_pages::OfflinePageItem& item) {
- for (Observer* observer : observers_) {
- observer->OfflinePageDeleted(item);
- }
-}
-
FeedApiTest::FeedApiTest() = default;
FeedApiTest::~FeedApiTest() = default;
void FeedApiTest::SetUp() {
@@ -602,6 +610,12 @@ void FeedApiTest::SetUp() {
// Disable fetching of recommended web feeds at startup to
// avoid a delayed task in tests that don't need it.
config.fetch_web_feed_info_delay = base::TimeDelta();
+ // `use_feed_query_requests_for_web_feeds` is a temporary option for
+ // debugging, setting it to false tests the preferred endpoint.
+ config.use_feed_query_requests_for_web_feeds = false;
+ // Disable refreshing the Web Feed stream after the for-you stream is loaded,
+ // to simplify tests unrelated to this feature.
+ config.refresh_web_feed_after_for_you_feed_loads = false;
SetFeedConfigForTesting(config);
feed::prefs::RegisterFeedSharedProfilePrefs(profile_prefs_.registry());
@@ -652,23 +666,30 @@ DisplayMetrics FeedApiTest::GetDisplayMetrics() {
std::string FeedApiTest::GetLanguageTag() {
return "en-US";
}
+bool FeedApiTest::IsAutoplayEnabled() {
+ return false;
+}
+void FeedApiTest::ClearAll() {
+ if (on_clear_all_)
+ on_clear_all_.Run();
+}
void FeedApiTest::PrefetchImage(const GURL& url) {
prefetched_images_.push_back(url);
prefetch_image_call_count_++;
}
-void FeedApiTest::CreateStream() {
+void FeedApiTest::CreateStream(bool wait_for_initialization) {
ChromeInfo chrome_info;
chrome_info.channel = version_info::Channel::STABLE;
chrome_info.version = base::Version({99, 1, 9911, 2});
stream_ = std::make_unique<FeedStream>(
&refresh_scheduler_, metrics_reporter_.get(), this, &profile_prefs_,
&network_, image_fetcher_.get(), store_.get(),
- persistent_key_value_store_.get(), &prefetch_service_,
- &offline_page_model_, chrome_info);
-
- WaitForIdleTaskQueue(); // Wait for any initialization.
+ persistent_key_value_store_.get(), chrome_info);
stream_->SetWireResponseTranslatorForTesting(&response_translator_);
+
+ if (wait_for_initialization)
+ WaitForIdleTaskQueue(); // Wait for any initialization.
}
bool FeedApiTest::IsTaskQueueIdle() const {
diff --git a/chromium/components/feed/core/v2/api_test/feed_api_test.h b/chromium/components/feed/core/v2/api_test/feed_api_test.h
index d0bf52ad6e7..3b34d864eaf 100644
--- a/chromium/components/feed/core/v2/api_test/feed_api_test.h
+++ b/chromium/components/feed/core/v2/api_test/feed_api_test.h
@@ -11,7 +11,6 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/optional.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "components/feed/core/common/pref_names.h"
@@ -26,16 +25,16 @@
#include "components/feed/core/v2/image_fetcher.h"
#include "components/feed/core/v2/metrics_reporter.h"
#include "components/feed/core/v2/prefs.h"
+#include "components/feed/core/v2/public/feed_stream_surface.h"
#include "components/feed/core/v2/stream_model.h"
#include "components/feed/core/v2/test/proto_printer.h"
#include "components/feed/core/v2/test/stream_builder.h"
#include "components/feed/core/v2/test/test_util.h"
#include "components/feed/core/v2/wire_response_translator.h"
-#include "components/offline_pages/core/prefetch/stub_prefetch_service.h"
-#include "components/offline_pages/core/stub_offline_page_model.h"
#include "components/prefs/testing_pref_service.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feed {
namespace test {
@@ -97,9 +96,9 @@ class TestSurfaceBase : public FeedStreamSurface {
// The initial state of the stream, if it was received. This is nullopt if
// only the loading spinner was seen.
- base::Optional<feedui::StreamUpdate> initial_state;
+ absl::optional<feedui::StreamUpdate> initial_state;
// The last stream update received.
- base::Optional<feedui::StreamUpdate> update;
+ absl::optional<feedui::StreamUpdate> update;
private:
std::string CurrentState();
@@ -134,7 +133,7 @@ class TestImageFetcher : public ImageFetcher {
ImageFetchId::Generator id_generator_;
};
-class TestUnreadContentObserver : public FeedApi::UnreadContentObserver {
+class TestUnreadContentObserver : public UnreadContentObserver {
public:
TestUnreadContentObserver();
~TestUnreadContentObserver() override;
@@ -151,11 +150,11 @@ class TestFeedNetwork : public FeedNetwork {
void SendQueryRequest(
NetworkRequestType request_type,
const feedwire::Request& request,
- bool force_signed_out_request,
const std::string& gaia,
base::OnceCallback<void(QueryRequestResult)> callback) override;
void SendDiscoverApiRequest(
+ NetworkRequestType request_type,
base::StringPiece api_path,
base::StringPiece method,
std::string request_bytes,
@@ -165,12 +164,13 @@ class TestFeedNetwork : public FeedNetwork {
void CancelRequests() override;
void InjectRealFeedQueryResponse();
+ void InjectRealFeedQueryResponseWithNoContent();
template <typename API>
void InjectApiRawResponse(RawResponse result) {
- injected_api_responses_[API::RequestPath().as_string()].push_back(result);
+ NetworkRequestType request_type = API::kRequestType;
+ injected_api_responses_[request_type].push_back(result);
}
-
template <typename API>
void InjectApiResponse(const typename API::Response& response_message) {
RawResponse response;
@@ -204,15 +204,16 @@ class TestFeedNetwork : public FeedNetwork {
void InjectEmptyActionRequestResult();
template <typename API>
- base::Optional<typename API::Request> GetApiRequestSent() {
- base::Optional<typename API::Request> result;
- auto iter = api_requests_sent_.find(API::RequestPath().as_string());
+ absl::optional<typename API::Request> GetApiRequestSent() {
+ absl::optional<typename API::Request> result;
+ NetworkRequestType request_type = API::kRequestType;
+ auto iter = api_requests_sent_.find(request_type);
if (iter != api_requests_sent_.end()) {
typename API::Request message;
if (!iter->second.empty()) {
if (!message.ParseFromString(iter->second)) {
LOG(ERROR) << "Failed to parse API request.";
- return base::nullopt;
+ return absl::nullopt;
}
}
result = message;
@@ -220,11 +221,12 @@ class TestFeedNetwork : public FeedNetwork {
return result;
}
- base::Optional<feedwire::UploadActionsRequest> GetActionRequestSent();
+ absl::optional<feedwire::UploadActionsRequest> GetActionRequestSent();
template <typename API>
int GetApiRequestCount() const {
- auto iter = api_request_count_.find(API::RequestPath().as_string());
+ NetworkRequestType request_type = API::kRequestType;
+ auto iter = api_request_count_.find(request_type);
return iter == api_request_count_.end() ? 0 : iter->second;
}
int GetActionRequestCount() const;
@@ -249,8 +251,10 @@ class TestFeedNetwork : public FeedNetwork {
void SendResponsesOnCommand(bool on);
void SendResponse();
- base::Optional<feedwire::Request> query_request_sent;
+ absl::optional<feedwire::Request> query_request_sent;
+ // Number of FeedQuery requests sent (including Web Feed ListContents).
int send_query_call_count = 0;
+ std::string last_gaia;
std::string consistency_token;
bool forced_signed_out_request = false;
@@ -260,10 +264,11 @@ class TestFeedNetwork : public FeedNetwork {
bool send_responses_on_command_ = false;
std::vector<base::OnceClosure> reply_closures_;
base::RepeatingClosure on_reply_added_;
- std::map<std::string, std::vector<RawResponse>> injected_api_responses_;
- std::map<std::string, std::string> api_requests_sent_;
- std::map<std::string, int> api_request_count_;
- base::Optional<feedwire::Response> injected_response_;
+ std::map<NetworkRequestType, std::vector<RawResponse>>
+ injected_api_responses_;
+ std::map<NetworkRequestType, std::string> api_requests_sent_;
+ std::map<NetworkRequestType, int> api_request_count_;
+ absl::optional<feedwire::Response> injected_response_;
};
// Forwards to |FeedStream::WireResponseTranslator| unless a response is
@@ -278,7 +283,7 @@ class TestWireResponseTranslator : public WireResponseTranslator {
bool was_signed_in_request,
base::Time current_time) const override;
void InjectResponse(std::unique_ptr<StreamModelUpdateRequest> response,
- base::Optional<std::string> session_id = base::nullopt);
+ absl::optional<std::string> session_id = absl::nullopt);
void InjectResponse(RefreshResponseData response_data);
bool InjectedResponseConsumed() const;
@@ -326,56 +331,14 @@ class TestMetricsReporter : public MetricsReporter {
// Test access.
- base::Optional<int> slice_viewed_index;
- base::Optional<LoadStreamStatus> load_stream_status;
- base::Optional<LoadStreamStatus> load_stream_from_store_status;
- base::Optional<SurfaceId> load_more_surface_id;
- base::Optional<LoadStreamStatus> load_more_status;
- base::Optional<LoadStreamStatus> background_refresh_status;
- base::Optional<base::TimeDelta> time_since_last_clear;
- base::Optional<UploadActionsStatus> upload_action_status;
-};
-
-class TestPrefetchService : public offline_pages::StubPrefetchService {
- public:
- TestPrefetchService();
- ~TestPrefetchService() override;
- // offline_pages::StubPrefetchService.
- void SetSuggestionProvider(
- offline_pages::SuggestionsProvider* suggestions_provider) override;
- void NewSuggestionsAvailable() override;
-
- // Test functionality.
- offline_pages::SuggestionsProvider* suggestions_provider();
- int NewSuggestionsAvailableCallCount() const;
-
- private:
- offline_pages::SuggestionsProvider* suggestions_provider_ = nullptr;
- int new_suggestions_available_call_count_ = 0;
-};
-
-class TestOfflinePageModel : public offline_pages::StubOfflinePageModel {
- public:
- TestOfflinePageModel();
- ~TestOfflinePageModel() override;
- // offline_pages::OfflinePageModel
- void AddObserver(Observer* observer) override;
- void RemoveObserver(Observer* observer) override;
- void GetPagesWithCriteria(
- const offline_pages::PageCriteria& criteria,
- offline_pages::MultipleOfflinePageItemCallback callback) override;
-
- // Test functions.
-
- void AddTestPage(const GURL& url);
- std::vector<offline_pages::OfflinePageItem>& items() { return items_; }
- void CallObserverOfflinePageAdded(const offline_pages::OfflinePageItem& item);
- void CallObserverOfflinePageDeleted(
- const offline_pages::OfflinePageItem& item);
-
- private:
- std::vector<offline_pages::OfflinePageItem> items_;
- std::set<Observer*> observers_;
+ absl::optional<int> slice_viewed_index;
+ absl::optional<LoadStreamStatus> load_stream_status;
+ absl::optional<LoadStreamStatus> load_stream_from_store_status;
+ absl::optional<SurfaceId> load_more_surface_id;
+ absl::optional<LoadStreamStatus> load_more_status;
+ absl::optional<LoadStreamStatus> background_refresh_status;
+ absl::optional<base::TimeDelta> time_since_last_clear;
+ absl::optional<UploadActionsStatus> upload_action_status;
};
class FeedApiTest : public testing::Test, public FeedStream::Delegate {
@@ -393,7 +356,8 @@ class FeedApiTest : public testing::Test, public FeedStream::Delegate {
bool IsOffline() override;
DisplayMetrics GetDisplayMetrics() override;
std::string GetLanguageTag() override;
- void ClearAll() override {}
+ bool IsAutoplayEnabled() override;
+ void ClearAll() override;
std::string GetSyncSignedInGaia() override;
void PrefetchImage(const GURL& url) override;
void RegisterExperiments(const Experiments& experiments) override {}
@@ -401,7 +365,7 @@ class FeedApiTest : public testing::Test, public FeedStream::Delegate {
// For tests.
// Replace stream_.
- void CreateStream();
+ void CreateStream(bool wait_for_initialization = true);
bool IsTaskQueueIdle() const;
void WaitForIdleTaskQueue();
void UnloadModel(const StreamType& stream_type);
@@ -436,8 +400,6 @@ class FeedApiTest : public testing::Test, public FeedStream::Delegate {
task_environment_.GetMainThreadTaskRunner()));
FakeRefreshTaskScheduler refresh_scheduler_;
- TestPrefetchService prefetch_service_;
- TestOfflinePageModel offline_page_model_;
std::unique_ptr<FeedStream> stream_;
bool is_eula_accepted_ = true;
bool is_offline_ = false;
@@ -445,6 +407,7 @@ class FeedApiTest : public testing::Test, public FeedStream::Delegate {
base::test::ScopedFeatureList scoped_feature_list_;
int prefetch_image_call_count_ = 0;
std::vector<GURL> prefetched_images_;
+ base::RepeatingClosure on_clear_all_;
};
class FeedStreamTestForAllStreamTypes
diff --git a/chromium/components/feed/core/v2/common_enums.h b/chromium/components/feed/core/v2/common_enums.h
index 3c021c73237..9fa23ffbd35 100644
--- a/chromium/components/feed/core/v2/common_enums.h
+++ b/chromium/components/feed/core/v2/common_enums.h
@@ -88,8 +88,10 @@ enum class FeedUserActionType {
kClosedNativePulldownMenu = 27,
// User tapped feed header menu item 'Manage reactions'.
kTappedManageReactions = 28,
+ // User tapped on share.
+ kShare = 29,
// Highest enumerator. Recommended by Histogram metrics best practices.
- kMaxValue = kTappedManageReactions,
+ kMaxValue = kShare,
};
} // namespace feed
diff --git a/chromium/components/feed/core/v2/config.cc b/chromium/components/feed/core/v2/config.cc
index 67d81a18de3..f678aea2c8e 100644
--- a/chromium/components/feed/core/v2/config.cc
+++ b/chromium/components/feed/core/v2/config.cc
@@ -9,6 +9,7 @@
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "components/feed/core/proto/v2/wire/capability.pb.h"
+#include "components/feed/core/v2/public/stream_type.h"
#include "components/feed/feed_feature_list.h"
namespace feed {
@@ -126,6 +127,21 @@ void OverrideWithFinch(Config* config) {
kWebFeed, "webfeed_accelerator_recent_visit_history_days",
config->webfeed_accelerator_recent_visit_history_days);
+ config->recommended_feeds_staleness_threshold =
+ base::TimeDelta::FromDays(base::GetFieldTrialParamByFeatureAsInt(
+ kWebFeed, "recommended_feeds_staleness_threshold_days",
+ config->recommended_feeds_staleness_threshold.InDays()));
+
+ config->subscribed_feeds_staleness_threshold =
+ base::TimeDelta::FromDays(base::GetFieldTrialParamByFeatureAsInt(
+ kWebFeed, "subscribed_feeds_staleness_threshold_days",
+ config->subscribed_feeds_staleness_threshold.InDays()));
+
+ config->web_feed_stale_content_threshold =
+ base::TimeDelta::FromSecondsD(base::GetFieldTrialParamByFeatureAsDouble(
+ kWebFeed, "web_feed_stale_content_threshold_seconds",
+ config->web_feed_stale_content_threshold.InSecondsF()));
+
// Erase any capabilities with "enable_CAPABILITY = false" set.
base::EraseIf(config->experimental_capabilities, CapabilityDisabled);
}
@@ -153,4 +169,10 @@ Config::Config() = default;
Config::Config(const Config& other) = default;
Config::~Config() = default;
+base::TimeDelta Config::GetStalenessThreshold(
+ const StreamType& stream_type) const {
+ return stream_type.IsForYou() ? stale_content_threshold
+ : web_feed_stale_content_threshold;
+}
+
} // namespace feed
diff --git a/chromium/components/feed/core/v2/config.h b/chromium/components/feed/core/v2/config.h
index 44943c32eff..61e3b00fda5 100644
--- a/chromium/components/feed/core/v2/config.h
+++ b/chromium/components/feed/core/v2/config.h
@@ -10,6 +10,7 @@
#include "components/feed/core/proto/v2/wire/capability.pb.h"
namespace feed {
+class StreamType;
// The Feed configuration. Default values appear below. Always use
// |GetFeedConfig()| to get the current configuration.
@@ -61,13 +62,17 @@ struct Config {
// Configuration for Web Feeds.
+ // How long before Web Feed content is considered stale.
+ base::TimeDelta web_feed_stale_content_threshold =
+ base::TimeDelta::FromHours(1);
// TimeDelta after startup to fetch recommended and subscribed Web Feeds if
// they are stale. If zero, no fetching is done.
base::TimeDelta fetch_web_feed_info_delay = base::TimeDelta::FromSeconds(40);
// How long before cached recommended feed data on the device is considered
// stale and refetched.
+ // TODO(crbug/1152592): Revert to 7 days.
base::TimeDelta recommended_feeds_staleness_threshold =
- base::TimeDelta::FromDays(7);
+ base::TimeDelta::FromDays(1);
// How long before cached subscribed feed data on the device is considered
// stale and refetched.
base::TimeDelta subscribed_feeds_staleness_threshold =
@@ -75,6 +80,9 @@ struct Config {
// Number of days of history to query when determining whether to show the
// follow accelerator.
int webfeed_accelerator_recent_visit_history_days = 14;
+ // After loading the for-you feed, should the web-feed be refreshed as well?
+ // This is true except for testing.
+ bool refresh_web_feed_after_for_you_feed_loads = true;
// Configuration for `PersistentKeyValueStore`.
@@ -83,6 +91,10 @@ struct Config {
// Eviction task is performed after this many bytes are written.
int persistent_kv_store_cleanup_interval_in_written_bytes = 1000000;
+ // Until we get the new list contents API working, keep using FeedQuery.
+ // TODO(crbug/1152592): turn this off when possible.
+ bool use_feed_query_requests_for_web_feeds = true;
+
// Set of optional capabilities included in requests. See
// CreateFeedQueryRequest() for required capabilities.
base::flat_set<feedwire::Capability> experimental_capabilities = {
@@ -99,6 +111,8 @@ struct Config {
Config();
Config(const Config& other);
~Config();
+
+ base::TimeDelta GetStalenessThreshold(const StreamType& stream_type) const;
};
// Gets the current configuration.
diff --git a/chromium/components/feed/core/v2/enums.cc b/chromium/components/feed/core/v2/enums.cc
index 06d389aa1ad..f6b191e6d73 100644
--- a/chromium/components/feed/core/v2/enums.cc
+++ b/chromium/components/feed/core/v2/enums.cc
@@ -65,6 +65,8 @@ std::ostream& operator<<(std::ostream& out, LoadStreamStatus value) {
return out << "kDataInStoreIsForAnotherUser";
case LoadStreamStatus::kAbortWithPendingClearAll:
return out << "kAbortWithPendingClearAll";
+ case LoadStreamStatus::kAlreadyHaveUnreadContent:
+ return out << "kAlreadyHaveUnreadContent";
}
#else
return out << (static_cast<int>(value));
diff --git a/chromium/components/feed/core/v2/enums.h b/chromium/components/feed/core/v2/enums.h
index 8da815c9fd3..6420afaae44 100644
--- a/chromium/components/feed/core/v2/enums.h
+++ b/chromium/components/feed/core/v2/enums.h
@@ -18,6 +18,10 @@ enum class NetworkRequestType : int {
kUnfollowWebFeed = 4,
kFollowWebFeed = 5,
kListRecommendedWebFeeds = 6,
+ kWebFeedListContents = 7,
+ kQueryInteractiveFeed = 8,
+ kQueryBackgroundFeed = 9,
+ kQueryNextPage = 10,
};
// This must be kept in sync with FeedLoadStreamStatus in enums.xml.
@@ -59,7 +63,8 @@ enum class LoadStreamStatus {
kDataInStoreIsExpired = 22,
kDataInStoreIsForAnotherUser = 23,
kAbortWithPendingClearAll = 24,
- kMaxValue = kAbortWithPendingClearAll,
+ kAlreadyHaveUnreadContent = 25,
+ kMaxValue = kAlreadyHaveUnreadContent,
};
std::ostream& operator<<(std::ostream& out, LoadStreamStatus value);
diff --git a/chromium/components/feed/core/v2/feed_network.h b/chromium/components/feed/core/v2/feed_network.h
index abe869a87c1..33657097331 100644
--- a/chromium/components/feed/core/v2/feed_network.h
+++ b/chromium/components/feed/core/v2/feed_network.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/callback.h"
+#include "components/feed/core/proto/v2/wire/feed_query.pb.h"
#include "components/feed/core/proto/v2/wire/request.pb.h"
#include "components/feed/core/proto/v2/wire/response.pb.h"
#include "components/feed/core/proto/v2/wire/upload_actions_request.pb.h"
@@ -26,52 +27,99 @@ namespace feed {
// DiscoverApi types. Defines information about each discover API. For use with
// `FeedNetwork::SendApiRequest()`.
+struct QueryInteractiveFeedDiscoverApi {
+ using Request = feedwire::Request;
+ using Response = feedwire::Response;
+ static constexpr NetworkRequestType kRequestType =
+ NetworkRequestType::kQueryInteractiveFeed;
+ static base::StringPiece Method() { return "POST"; }
+ static base::StringPiece RequestPath(const Request&) {
+ return "v1:queryInteractiveFeed";
+ }
+};
+
+struct QueryBackgroundFeedDiscoverApi {
+ using Request = feedwire::Request;
+ using Response = feedwire::Response;
+ static constexpr NetworkRequestType kRequestType =
+ NetworkRequestType::kQueryBackgroundFeed;
+ static base::StringPiece Method() { return "POST"; }
+ static base::StringPiece RequestPath(const Request&) {
+ return "v1:queryBackgroundFeed";
+ }
+};
+
+struct QueryNextPageDiscoverApi {
+ using Request = feedwire::Request;
+ using Response = feedwire::Response;
+ static constexpr NetworkRequestType kRequestType =
+ NetworkRequestType::kQueryNextPage;
+ static base::StringPiece Method() { return "POST"; }
+ static base::StringPiece RequestPath(const Request&) {
+ return "v1:queryNextPage";
+ }
+};
+
struct UploadActionsDiscoverApi {
using Request = feedwire::UploadActionsRequest;
using Response = feedwire::UploadActionsResponse;
- static const NetworkRequestType kRequestType =
+ static constexpr NetworkRequestType kRequestType =
NetworkRequestType::kUploadActions;
static base::StringPiece Method() { return "POST"; }
- static base::StringPiece RequestPath() { return "v1/actions:upload"; }
+ static base::StringPiece RequestPath(const Request&) {
+ return "v1/actions:upload";
+ }
};
struct ListWebFeedsDiscoverApi {
using Request = feedwire::webfeed::ListWebFeedsRequest;
using Response = feedwire::webfeed::ListWebFeedsResponse;
- static const NetworkRequestType kRequestType =
+ static constexpr NetworkRequestType kRequestType =
NetworkRequestType::kListWebFeeds;
static base::StringPiece Method() { return "GET"; }
- // TODO(harringtond): Path TDB.
- static base::StringPiece RequestPath() { return "v1/webFeeds"; }
+ static base::StringPiece RequestPath(const Request&) { return "v1/webFeeds"; }
};
struct ListRecommendedWebFeedDiscoverApi {
using Request = feedwire::webfeed::ListRecommendedWebFeedsRequest;
using Response = feedwire::webfeed::ListRecommendedWebFeedsResponse;
- static const NetworkRequestType kRequestType =
+ static constexpr NetworkRequestType kRequestType =
NetworkRequestType::kListRecommendedWebFeeds;
static base::StringPiece Method() { return "GET"; }
- static base::StringPiece RequestPath() { return "v1/recommendedWebFeeds"; }
+ static base::StringPiece RequestPath(const Request&) {
+ return "v1/recommendedWebFeeds";
+ }
};
struct FollowWebFeedDiscoverApi {
using Request = feedwire::webfeed::FollowWebFeedRequest;
using Response = feedwire::webfeed::FollowWebFeedResponse;
- static const NetworkRequestType kRequestType =
+ static constexpr NetworkRequestType kRequestType =
NetworkRequestType::kFollowWebFeed;
static base::StringPiece Method() { return "POST"; }
- // TODO(harringtond): Path TDB.
- static base::StringPiece RequestPath() { return "v1:followWebFeed"; }
+ static base::StringPiece RequestPath(const Request&) {
+ return "v1:followWebFeed";
+ }
};
struct UnfollowWebFeedDiscoverApi {
using Request = feedwire::webfeed::UnfollowWebFeedRequest;
using Response = feedwire::webfeed::UnfollowWebFeedResponse;
- static const NetworkRequestType kRequestType =
+ static constexpr NetworkRequestType kRequestType =
NetworkRequestType::kUnfollowWebFeed;
static base::StringPiece Method() { return "POST"; }
- // TODO(harringtond): Path TDB.
- static base::StringPiece RequestPath() { return "v1:unfollowWebFeed"; }
+ static base::StringPiece RequestPath(const Request&) {
+ return "v1:unfollowWebFeed";
+ }
+};
+
+struct WebFeedListContentsDiscoverApi {
+ using Request = feedwire::Request;
+ using Response = feedwire::Response;
+ static constexpr NetworkRequestType kRequestType =
+ NetworkRequestType::kWebFeedListContents;
+ static base::StringPiece Method() { return "POST"; }
+ static base::StringPiece RequestPath(const Request&) { return "v1/contents"; }
};
class FeedNetwork {
@@ -115,7 +163,6 @@ class FeedNetwork {
virtual void SendQueryRequest(
NetworkRequestType request_type,
const feedwire::Request& request,
- bool force_signed_out_request,
const std::string& gaia,
base::OnceCallback<void(QueryRequestResult)> callback) = 0;
@@ -129,7 +176,8 @@ class FeedNetwork {
std::string binary_proto;
request.SerializeToString(&binary_proto);
SendDiscoverApiRequest(
- API::RequestPath(), API::Method(), std::move(binary_proto), gaia,
+ API::kRequestType, API::RequestPath(request), API::Method(),
+ std::move(binary_proto), gaia,
base::BindOnce(&ParseAndForwardApiResponse<API>, std::move(callback)));
}
@@ -141,6 +189,7 @@ class FeedNetwork {
static void ParseAndForwardApiResponseBegin(NetworkRequestType request_type,
const RawResponse& raw_response);
virtual void SendDiscoverApiRequest(
+ NetworkRequestType request_type,
base::StringPiece api_path,
base::StringPiece method,
std::string request_bytes,
diff --git a/chromium/components/feed/core/v2/feed_network_impl.cc b/chromium/components/feed/core/v2/feed_network_impl.cc
index 8cc12632648..4e163f3ce7a 100644
--- a/chromium/components/feed/core/v2/feed_network_impl.cc
+++ b/chromium/components/feed/core/v2/feed_network_impl.cc
@@ -59,6 +59,7 @@ GURL GetFeedQueryURL(feedwire::FeedQuery::RequestReason reason) {
// Add URLs for Bling when it is supported.
switch (reason) {
case feedwire::FeedQuery::SCHEDULED_REFRESH:
+ case feedwire::FeedQuery::PREFETCHED_WEB_FEED:
return GURL(
"https://www.google.com/httpservice/noretry/TrellisClankService/"
"FeedQuery");
@@ -67,6 +68,7 @@ GURL GetFeedQueryURL(feedwire::FeedQuery::RequestReason reason) {
"https://www.google.com/httpservice/retry/TrellisClankService/"
"NextPageQuery");
case feedwire::FeedQuery::MANUAL_REFRESH:
+ case feedwire::FeedQuery::INTERACTIVE_WEB_FEED:
return GURL(
"https://www.google.com/httpservice/retry/TrellisClankService/"
"FeedQuery");
@@ -153,7 +155,7 @@ class FeedNetworkImpl::NetworkFetch {
NetworkFetch(const GURL& url,
base::StringPiece request_method,
std::string request_body,
- bool force_signed_out_request,
+ FeedNetworkImpl::Delegate* delegate,
signin::IdentityManager* identity_manager,
network::SharedURLLoaderFactory* loader_factory,
const std::string& api_key,
@@ -162,7 +164,7 @@ class FeedNetworkImpl::NetworkFetch {
: url_(url),
request_method_(request_method),
request_body_(std::move(request_body)),
- force_signed_out_request_(force_signed_out_request),
+ delegate_(delegate),
identity_manager_(identity_manager),
loader_factory_(loader_factory),
api_key_(api_key),
@@ -176,8 +178,7 @@ class FeedNetworkImpl::NetworkFetch {
void Start(base::OnceCallback<void(RawResponse)> done_callback) {
done_callback_ = std::move(done_callback);
- if (force_signed_out_request_ ||
- !identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync)) {
+ if (gaia_.empty()) {
StartLoader();
return;
}
@@ -199,6 +200,7 @@ class FeedNetworkImpl::NetworkFetch {
void AccessTokenFetchFinished(base::TimeTicks token_start_ticks,
GoogleServiceAuthError error,
signin::AccessTokenInfo access_token_info) {
+ DCHECK(!gaia_.empty());
UMA_HISTOGRAM_ENUMERATION(
"ContentSuggestions.Feed.Network.TokenFetchStatus", error.state(),
GoogleServiceAuthError::NUM_STATES);
@@ -209,19 +211,17 @@ class FeedNetworkImpl::NetworkFetch {
access_token_ = access_token_info.token;
- // Verify the correct user is logged in before issuing the request.
- if (identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync)) {
- if (identity_manager_->GetPrimaryAccountInfo(signin::ConsentLevel::kSync)
- .gaia == gaia_) {
- StartLoader();
- return;
- }
+ // Abort if the signed-in user doesn't match.
+ if (delegate_->GetSyncSignedInGaia() != gaia_) {
+ NetworkResponseInfo response_info;
+ RawResponse raw_response;
+ response_info.status_code = net::ERR_INVALID_ARGUMENT;
+ raw_response.response_info = std::move(response_info);
+ std::move(done_callback_).Run(std::move(raw_response));
+ return;
}
- NetworkResponseInfo response_info;
- RawResponse raw_response;
- response_info.status_code = net::ERR_INVALID_ARGUMENT;
- raw_response.response_info = std::move(response_info);
- std::move(done_callback_).Run(std::move(raw_response));
+
+ StartLoader();
}
void StartLoader() {
@@ -398,12 +398,11 @@ class FeedNetworkImpl::NetworkFetch {
std::move(done_callback_).Run(std::move(raw_response));
}
- private:
GURL url_;
const std::string request_method_;
std::string access_token_;
const std::string request_body_;
- bool force_signed_out_request_;
+ FeedNetworkImpl::Delegate* delegate_;
signin::IdentityManager* const identity_manager_;
std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher> token_fetcher_;
std::unique_ptr<network::SimpleURLLoader> simple_loader_;
@@ -439,7 +438,6 @@ FeedNetworkImpl::~FeedNetworkImpl() = default;
void FeedNetworkImpl::SendQueryRequest(
NetworkRequestType request_type,
const feedwire::Request& request,
- bool force_signed_out_request,
const std::string& gaia,
base::OnceCallback<void(QueryRequestResult)> callback) {
std::string binary_proto;
@@ -486,7 +484,7 @@ void FeedNetworkImpl::SendQueryRequest(
AddMothershipPayloadQueryParams(base64proto, delegate_->GetLanguageTag(),
url);
- Send(url, "GET", /*request_body=*/{}, force_signed_out_request,
+ Send(url, "GET", /*request_body=*/{},
/*allow_bless_auth=*/host_overridden, gaia,
base::BindOnce(&ParseAndForwardQueryResponse, request_type,
std::move(callback)));
@@ -499,12 +497,11 @@ void FeedNetworkImpl::CancelRequests() {
void FeedNetworkImpl::Send(const GURL& url,
base::StringPiece request_method,
std::string request_body,
- bool force_signed_out_request,
bool allow_bless_auth,
const std::string& gaia,
base::OnceCallback<void(RawResponse)> callback) {
auto fetch = std::make_unique<NetworkFetch>(
- url, request_method, std::move(request_body), force_signed_out_request,
+ url, request_method, std::move(request_body), delegate_,
identity_manager_, loader_factory_.get(), api_key_, gaia,
allow_bless_auth);
NetworkFetch* fetch_unowned = fetch.get();
@@ -518,6 +515,7 @@ void FeedNetworkImpl::Send(const GURL& url,
}
void FeedNetworkImpl::SendDiscoverApiRequest(
+ NetworkRequestType request_type,
base::StringPiece request_path,
base::StringPiece method,
std::string request_body,
@@ -535,7 +533,6 @@ void FeedNetworkImpl::SendDiscoverApiRequest(
}
Send(url, method, std::move(request_body),
- /*force_signed_out_request=*/false,
/*allow_bless_auth=*/false, gaia, std::move(callback));
}
diff --git a/chromium/components/feed/core/v2/feed_network_impl.h b/chromium/components/feed/core/v2/feed_network_impl.h
index 7d077c7e6c3..c2f463475c7 100644
--- a/chromium/components/feed/core/v2/feed_network_impl.h
+++ b/chromium/components/feed/core/v2/feed_network_impl.h
@@ -12,6 +12,7 @@
#include "base/containers/unique_ptr_adapters.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/string_piece.h"
+#include "components/feed/core/v2/enums.h"
#include "components/feed/core/v2/feed_network.h"
#include "components/version_info/channel.h"
#include "url/gurl.h"
@@ -35,6 +36,9 @@ class FeedNetworkImpl : public FeedNetwork {
// Returns a string which represents the top locale and region of the
// device.
virtual std::string GetLanguageTag() = 0;
+ // Returns the GAIA string for the signed in user if they are sync-enabled,
+ // or the empty string otherwise.
+ virtual std::string GetSyncSignedInGaia() = 0;
};
FeedNetworkImpl(Delegate* delegate,
@@ -51,11 +55,11 @@ class FeedNetworkImpl : public FeedNetwork {
void SendQueryRequest(
NetworkRequestType request_type,
const feedwire::Request& request,
- bool force_signed_out_request,
const std::string& gaia,
base::OnceCallback<void(QueryRequestResult)> callback) override;
void SendDiscoverApiRequest(
+ NetworkRequestType request_type,
base::StringPiece api_path,
base::StringPiece method,
std::string request_bytes,
@@ -74,7 +78,6 @@ class FeedNetworkImpl : public FeedNetwork {
void Send(const GURL& url,
base::StringPiece request_method,
std::string request_body,
- bool force_signed_out_request,
bool allow_bless_auth,
const std::string& gaia,
base::OnceCallback<void(FeedNetworkImpl::RawResponse)> callback);
diff --git a/chromium/components/feed/core/v2/feed_network_impl_unittest.cc b/chromium/components/feed/core/v2/feed_network_impl_unittest.cc
index e873f8fd26b..6b507ed8054 100644
--- a/chromium/components/feed/core/v2/feed_network_impl_unittest.cc
+++ b/chromium/components/feed/core/v2/feed_network_impl_unittest.cc
@@ -73,7 +73,17 @@ feedwire::UploadActionsResponse GetTestActionResponse() {
class TestDelegate : public FeedNetworkImpl::Delegate {
public:
+ explicit TestDelegate(signin::IdentityTestEnvironment* identity_test_env)
+ : identity_test_env_(identity_test_env) {}
+
std::string GetLanguageTag() override { return "en"; }
+ std::string GetSyncSignedInGaia() override {
+ return identity_test_env_->identity_manager()
+ ->GetPrimaryAccountInfo(signin::ConsentLevel::kSync)
+ .gaia;
+ }
+
+ signin::IdentityTestEnvironment* identity_test_env_;
};
class FeedNetworkTest : public testing::Test {
@@ -103,11 +113,7 @@ class FeedNetworkTest : public testing::Test {
return &identity_test_env_;
}
- std::string gaia() {
- return identity_test_env_.identity_manager()
- ->GetPrimaryAccountInfo(signin::ConsentLevel::kSync)
- .gaia;
- }
+ std::string gaia() { return delegate_.GetSyncSignedInGaia(); }
network::TestURLLoaderFactory* test_factory() { return &test_factory_; }
@@ -203,8 +209,8 @@ class FeedNetworkTest : public testing::Test {
scoped_refptr<net::HttpResponseHeaders> response_headers_;
private:
- TestDelegate delegate_;
signin::IdentityTestEnvironment identity_test_env_;
+ TestDelegate delegate_{&identity_test_env_};
std::unique_ptr<FeedNetwork> feed_network_;
network::TestURLLoaderFactory test_factory_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
@@ -215,7 +221,7 @@ class FeedNetworkTest : public testing::Test {
TEST_F(FeedNetworkTest, SendQueryRequestEmpty) {
CallbackReceiver<QueryRequestResult> receiver;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- feedwire::Request(), false, gaia(),
+ feedwire::Request(), gaia(),
receiver.Bind());
ASSERT_TRUE(receiver.GetResult());
@@ -227,7 +233,7 @@ TEST_F(FeedNetworkTest, SendQueryRequestEmpty) {
TEST_F(FeedNetworkTest, SendQueryRequestSendsValidRequest) {
CallbackReceiver<QueryRequestResult> receiver;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
network::ResourceRequest resource_request =
RespondToQueryRequest("", net::HTTP_OK);
@@ -248,9 +254,9 @@ TEST_F(FeedNetworkTest, SendQueryRequestSendsValidRequest) {
TEST_F(FeedNetworkTest, SendQueryRequestForceSignedOut) {
CallbackReceiver<QueryRequestResult> receiver;
- feed_network()->SendQueryRequest(
- NetworkRequestType::kFeedQuery, GetTestFeedRequest(),
- /*force_signed_out_request=*/true, gaia(), receiver.Bind());
+ feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
+ GetTestFeedRequest(), /*gaia=*/"",
+ receiver.Bind());
network::ResourceRequest resource_request =
RespondToQueryRequest("", net::HTTP_OK);
@@ -264,7 +270,7 @@ TEST_F(FeedNetworkTest, SendQueryRequestForceSignedOut) {
TEST_F(FeedNetworkTest, SendQueryRequestInvalidResponse) {
CallbackReceiver<QueryRequestResult> receiver;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
RespondToQueryRequest("invalid", net::HTTP_OK);
@@ -277,7 +283,7 @@ TEST_F(FeedNetworkTest, SendQueryRequestInvalidResponse) {
TEST_F(FeedNetworkTest, SendQueryRequestReceivesResponse) {
CallbackReceiver<QueryRequestResult> receiver;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
RespondToQueryRequest(GetTestFeedResponse(), net::HTTP_OK);
@@ -296,7 +302,7 @@ TEST_F(FeedNetworkTest, SendQueryRequestReceivesResponse) {
TEST_F(FeedNetworkTest, SendQueryRequestIgnoresBodyForNon200Response) {
CallbackReceiver<QueryRequestResult> receiver;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
RespondToQueryRequest(GetTestFeedResponse(), net::HTTP_FORBIDDEN);
@@ -312,8 +318,8 @@ TEST_F(FeedNetworkTest, SendQueryRequestIgnoresBodyForNon200Response) {
TEST_F(FeedNetworkTest, SendQueryRequestFailsForWrongUser) {
CallbackReceiver<QueryRequestResult> receiver;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false,
- "some_other_gaia", receiver.Bind());
+ GetTestFeedRequest(), "some_other_gaia",
+ receiver.Bind());
task_environment_.RunUntilIdle();
network::TestURLLoaderFactory::PendingRequest* pending_request =
test_factory()->GetPendingRequest(0);
@@ -331,7 +337,7 @@ TEST_F(FeedNetworkTest, SendQueryRequestFailsForWrongUser) {
TEST_F(FeedNetworkTest, CancelRequest) {
CallbackReceiver<QueryRequestResult> receiver;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
feed_network()->CancelRequests();
task_environment_.FastForwardUntilNoTasksRemain();
@@ -343,7 +349,7 @@ TEST_F(FeedNetworkTest, RequestTimeout) {
base::HistogramTester histogram_tester;
CallbackReceiver<QueryRequestResult> receiver;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
task_environment_.FastForwardBy(TimeDelta::FromSeconds(30));
@@ -358,13 +364,13 @@ TEST_F(FeedNetworkTest, RequestTimeout) {
TEST_F(FeedNetworkTest, ParallelRequests) {
CallbackReceiver<QueryRequestResult> receiver1, receiver2;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver1.Bind());
// Make another request with a different URL so Respond() won't affect both
// requests.
feed_network()->SendQueryRequest(
NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(feedwire::FeedQuery::NEXT_PAGE_SCROLL), false, gaia(),
+ GetTestFeedRequest(feedwire::FeedQuery::NEXT_PAGE_SCROLL), gaia(),
receiver2.Bind());
// Respond to both requests, avoiding FastForwardUntilNoTasksRemain until
@@ -388,7 +394,7 @@ TEST_F(FeedNetworkTest, ShouldReportResponseStatusCode) {
CallbackReceiver<QueryRequestResult> receiver;
base::HistogramTester histogram_tester;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
RespondToQueryRequest(GetTestFeedResponse(), net::HTTP_FORBIDDEN);
@@ -404,7 +410,7 @@ TEST_F(FeedNetworkTest, ShouldIncludeAPIKeyForAuthError) {
base::HistogramTester histogram_tester;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
identity_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
GoogleServiceAuthError(
@@ -431,7 +437,7 @@ TEST_F(FeedNetworkTest, ShouldIncludeAPIKeyForNoSignedInUser) {
identity_env()->ClearPrimaryAccount();
CallbackReceiver<QueryRequestResult> receiver;
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
network::ResourceRequest resource_request =
@@ -448,7 +454,7 @@ TEST_F(FeedNetworkTest, TestDurationHistogram) {
const TimeDelta kDuration = TimeDelta::FromMilliseconds(12345);
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
task_environment_.FastForwardBy(kDuration);
RespondToQueryRequest(GetTestFeedResponse(), net::HTTP_OK);
@@ -465,7 +471,7 @@ TEST_F(FeedNetworkTest, TestHostOverrideWithAuthHeader) {
profile_prefs().SetString(feed::prefs::kHostOverrideHost,
"http://www.newhost.com/");
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
ASSERT_EQ("www.newhost.com", GetPendingRequestURL().host());
@@ -486,7 +492,7 @@ TEST_F(FeedNetworkTest, TestHostOverrideWithPath) {
profile_prefs().SetString(feed::prefs::kHostOverrideHost,
"http://www.newhost.com/testpath");
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
ASSERT_EQ("www.newhost.com", GetPendingRequestURL().host());
@@ -499,7 +505,7 @@ TEST_F(FeedNetworkTest, TestHostOverrideWithPathTrailingSlash) {
profile_prefs().SetString(feed::prefs::kHostOverrideHost,
"http://www.newhost.com/testpath/");
feed_network()->SendQueryRequest(NetworkRequestType::kFeedQuery,
- GetTestFeedRequest(), false, gaia(),
+ GetTestFeedRequest(), gaia(),
receiver.Bind());
ASSERT_EQ("www.newhost.com", GetPendingRequestURL().host());
diff --git a/chromium/components/feed/core/v2/feed_store.cc b/chromium/components/feed/core/v2/feed_store.cc
index 4c0bd9fcf4a..96445ba68b5 100644
--- a/chromium/components/feed/core/v2/feed_store.cc
+++ b/chromium/components/feed/core/v2/feed_store.cc
@@ -18,8 +18,10 @@
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
+#include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/v2/feedstore_util.h"
#include "components/feed/core/v2/protocol_translator.h"
+#include "components/feed/core/v2/public/stream_type.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
namespace feed {
@@ -95,7 +97,7 @@ bool IsAnyStreamRecordKey(const std::string& key) {
class StreamKeyMatcher {
public:
explicit StreamKeyMatcher(const StreamType& stream_type) {
- stream_id_ = feedstore::StreamId(stream_type).as_string();
+ stream_id_ = std::string(feedstore::StreamId(stream_type));
stream_id_plus_slash_ = stream_id_ + '/';
}
@@ -235,19 +237,19 @@ MakeUpdatesForStreamModelUpdateRequest(
base::StringPiece stream_id = feedstore::StreamId(stream_type);
auto updates = std::make_unique<
std::vector<std::pair<std::string, feedstore::Record>>>();
- update_request->stream_data.set_stream_id(stream_id.as_string());
+ update_request->stream_data.set_stream_id(std::string(stream_id));
updates->push_back(MakeKeyAndRecord(std::move(update_request->stream_data)));
for (feedstore::Content& content : update_request->content) {
- content.set_stream_id(stream_id.as_string());
+ content.set_stream_id(std::string(stream_id));
updates->push_back(MakeKeyAndRecord(std::move(content)));
}
for (feedstore::StreamSharedState& shared_state :
update_request->shared_states) {
- shared_state.set_stream_id(stream_id.as_string());
+ shared_state.set_stream_id(std::string(stream_id));
updates->push_back(MakeKeyAndRecord(std::move(shared_state)));
}
feedstore::StreamStructureSet stream_structure_set;
- stream_structure_set.set_stream_id(stream_id.as_string());
+ stream_structure_set.set_stream_id(std::string(stream_id));
stream_structure_set.set_sequence_number(structure_set_sequence_number);
for (feedstore::StreamStructure& structure :
update_request->stream_structures) {
@@ -278,6 +280,12 @@ FeedStore::LoadStreamResult::LoadStreamResult(LoadStreamResult&&) = default;
FeedStore::LoadStreamResult& FeedStore::LoadStreamResult::operator=(
LoadStreamResult&&) = default;
+FeedStore::StartupData::StartupData() = default;
+FeedStore::StartupData::StartupData(StartupData&&) = default;
+FeedStore::StartupData::~StartupData() = default;
+FeedStore::StartupData& FeedStore::StartupData::operator=(StartupData&&) =
+ default;
+
FeedStore::FeedStore(
std::unique_ptr<leveldb_proto::ProtoDatabase<feedstore::Record>> database)
: database_status_(leveldb_proto::Enums::InitStatus::kNotInitialized),
@@ -490,12 +498,12 @@ void FeedStore::WriteOperations(
*structure_set.add_structures() = std::move(*operation.mutable_structure());
if (operation.has_content()) {
feedstore::Record record;
- operation.mutable_content()->set_stream_id(stream_id.as_string());
+ operation.mutable_content()->set_stream_id(std::string(stream_id));
record.set_allocated_content(operation.release_content());
records.push_back(std::move(record));
}
}
- structure_set.set_stream_id(feedstore::StreamId(stream_type).as_string());
+ structure_set.set_stream_id(std::string(feedstore::StreamId(stream_type)));
structure_set.set_sequence_number(sequence_number);
records.push_back(std::move(structures_record));
@@ -676,6 +684,35 @@ void FeedStore::OnReadWebFeedStartupDataFinished(
std::move(callback).Run(std::move(result));
}
+void FeedStore::ReadStartupData(
+ base::OnceCallback<void(StartupData)> callback) {
+ ReadMany({StreamDataKey(kWebFeedStream), StreamDataKey(kForYouStream),
+ kMetadataKey},
+ base::BindOnce(&FeedStore::OnReadStartupDataFinished, GetWeakPtr(),
+ std::move(callback)));
+}
+
+void FeedStore::OnReadStartupDataFinished(
+ base::OnceCallback<void(StartupData)> callback,
+ bool read_ok,
+ std::unique_ptr<std::vector<feedstore::Record>> records) {
+ StartupData result;
+ if (records) {
+ for (feedstore::Record& r : *records) {
+ if (r.has_stream_data()) {
+ result.stream_data.push_back(std::move(r.stream_data()));
+ } else if (r.has_metadata()) {
+ result.metadata = base::WrapUnique(r.release_metadata());
+ } else {
+ DLOG(ERROR) << "OnReadStartupDataFinished: Got record with no "
+ "useful data. data_case="
+ << static_cast<int>(r.data_case());
+ }
+ }
+ }
+ std::move(callback).Run(std::move(result));
+}
+
void FeedStore::WriteRecommendedFeeds(
feedstore::RecommendedWebFeedIndex index,
std::vector<feedstore::WebFeedInfo> web_feed_info,
diff --git a/chromium/components/feed/core/v2/feed_store.h b/chromium/components/feed/core/v2/feed_store.h
index fb69822ea4e..f88aea006dc 100644
--- a/chromium/components/feed/core/v2/feed_store.h
+++ b/chromium/components/feed/core/v2/feed_store.h
@@ -42,6 +42,15 @@ class FeedStore {
// These are sorted by increasing ID.
std::vector<feedstore::StoredAction> pending_actions;
};
+ struct StartupData {
+ StartupData();
+ StartupData(StartupData&&);
+ ~StartupData();
+ StartupData& operator=(StartupData&&);
+
+ std::unique_ptr<feedstore::Metadata> metadata;
+ std::vector<feedstore::StreamData> stream_data;
+ };
struct WebFeedStartupData {
feedstore::SubscribedWebFeeds subscribed_web_feeds;
feedstore::RecommendedWebFeedIndex recommended_feed_index;
@@ -117,6 +126,7 @@ class FeedStore {
base::OnceCallback<void(feedstore::Metadata)> callback);
void ReadWebFeedStartupData(
base::OnceCallback<void(WebFeedStartupData)> callback);
+ void ReadStartupData(base::OnceCallback<void(StartupData)> callback);
void WriteRecommendedFeeds(feedstore::RecommendedWebFeedIndex index,
std::vector<feedstore::WebFeedInfo> web_feed_info,
base::OnceClosure callback);
@@ -184,6 +194,10 @@ class FeedStore {
base::OnceCallback<void(WebFeedStartupData)> callback,
bool read_ok,
std::unique_ptr<std::vector<feedstore::Record>> records);
+ void OnReadStartupDataFinished(
+ base::OnceCallback<void(StartupData)> callback,
+ bool read_ok,
+ std::unique_ptr<std::vector<feedstore::Record>> records);
void ReadRecommendedWebFeedInfoFinished(
base::OnceCallback<void(std::unique_ptr<feedstore::WebFeedInfo>)>
callback,
diff --git a/chromium/components/feed/core/v2/feed_store_unittest.cc b/chromium/components/feed/core/v2/feed_store_unittest.cc
index 0a6c833a194..4aa9ac648cc 100644
--- a/chromium/components/feed/core/v2/feed_store_unittest.cc
+++ b/chromium/components/feed/core/v2/feed_store_unittest.cc
@@ -142,6 +142,7 @@ TEST_F(FeedStoreTest, OverwriteStream) {
content_domain: "render_data"
}
stream_id: "i"
+ content_ids: 1
}
}
[T/i/0] {
@@ -263,6 +264,7 @@ TEST_F(FeedStoreTest, OverwriteStreamWebFeed) {
content_domain: "render_data"
}
stream_id: "w"
+ content_ids: 1
}
}
[T/w/0] {
@@ -502,9 +504,9 @@ TEST_F(FeedStoreTest, ReadNonexistentContentAndSharedStates) {
{MakeSharedStateContentId(0)}, cr.Bind());
fake_db_->LoadCallback(true);
- ASSERT_NE(cr.GetResult<0>(), base::nullopt);
+ ASSERT_NE(cr.GetResult<0>(), absl::nullopt);
EXPECT_EQ(cr.GetResult<0>()->size(), 0ul);
- ASSERT_NE(cr.GetResult<1>(), base::nullopt);
+ ASSERT_NE(cr.GetResult<1>(), absl::nullopt);
EXPECT_EQ(cr.GetResult<1>()->size(), 0ul);
}
@@ -536,9 +538,9 @@ TEST_F(FeedStoreTest, ReadContentAndSharedStates) {
store_->ReadContent(kForYouStream, content_ids, shared_state_ids, cr.Bind());
fake_db_->LoadCallback(true);
- ASSERT_NE(cr.GetResult<0>(), base::nullopt);
+ ASSERT_NE(cr.GetResult<0>(), absl::nullopt);
std::vector<feedstore::Content> content = *cr.GetResult<0>();
- ASSERT_NE(cr.GetResult<1>(), base::nullopt);
+ ASSERT_NE(cr.GetResult<1>(), absl::nullopt);
std::vector<feedstore::StreamSharedState> shared_states = *cr.GetResult<1>();
ASSERT_EQ(content.size(), 2ul);
@@ -556,9 +558,9 @@ TEST_F(FeedStoreTest, ReadContentAndSharedStates) {
store_->ReadContent(kForYouStream, content_ids, shared_state_ids, cr.Bind());
fake_db_->LoadCallback(false);
- ASSERT_NE(cr.GetResult<0>(), base::nullopt);
+ ASSERT_NE(cr.GetResult<0>(), absl::nullopt);
EXPECT_EQ(cr.GetResult<0>()->size(), 0ul);
- ASSERT_NE(cr.GetResult<1>(), base::nullopt);
+ ASSERT_NE(cr.GetResult<1>(), absl::nullopt);
EXPECT_EQ(cr.GetResult<1>()->size(), 0ul);
}
@@ -571,7 +573,7 @@ TEST_F(FeedStoreTest, ReadActions) {
CallbackReceiver<std::vector<feedstore::StoredAction>> receiver;
store_->ReadActions(receiver.Bind());
fake_db_->LoadCallback(true);
- ASSERT_NE(base::nullopt, receiver.GetResult());
+ ASSERT_NE(absl::nullopt, receiver.GetResult());
std::vector<feedstore::StoredAction> result =
std::move(*receiver.GetResult());
@@ -582,7 +584,7 @@ TEST_F(FeedStoreTest, ReadActions) {
receiver.Clear();
store_->ReadActions(receiver.Bind());
fake_db_->LoadCallback(false);
- ASSERT_NE(base::nullopt, receiver.GetResult());
+ ASSERT_NE(absl::nullopt, receiver.GetResult());
result = std::move(*receiver.GetResult());
EXPECT_EQ(0ul, result.size());
}
@@ -603,7 +605,7 @@ TEST_F(FeedStoreTest, WriteActions) {
receiver.GetResult().reset();
store_->WriteActions({action}, receiver.Bind());
fake_db_->UpdateCallback(false);
- EXPECT_NE(receiver.GetResult(), base::nullopt);
+ EXPECT_NE(receiver.GetResult(), absl::nullopt);
EXPECT_EQ(receiver.GetResult().value(), false);
}
@@ -624,7 +626,7 @@ TEST_F(FeedStoreTest, RemoveActions) {
receiver.GetResult().reset();
store_->RemoveActions(ids, receiver.Bind());
fake_db_->UpdateCallback(false);
- EXPECT_NE(receiver.GetResult(), base::nullopt);
+ EXPECT_NE(receiver.GetResult(), absl::nullopt);
EXPECT_EQ(receiver.GetResult().value(), false);
}
diff --git a/chromium/components/feed/core/v2/feed_stream.cc b/chromium/components/feed/core/v2/feed_stream.cc
index 2d850310816..23b728c6c19 100644
--- a/chromium/components/feed/core/v2/feed_stream.cc
+++ b/chromium/components/feed/core/v2/feed_stream.cc
@@ -28,18 +28,19 @@
#include "components/feed/core/v2/feedstore_util.h"
#include "components/feed/core/v2/image_fetcher.h"
#include "components/feed/core/v2/metrics_reporter.h"
-#include "components/feed/core/v2/offline_page_spy.h"
#include "components/feed/core/v2/prefs.h"
#include "components/feed/core/v2/protocol_translator.h"
#include "components/feed/core/v2/public/feed_api.h"
+#include "components/feed/core/v2/public/feed_stream_surface.h"
#include "components/feed/core/v2/public/refresh_task_scheduler.h"
+#include "components/feed/core/v2/public/stream_type.h"
#include "components/feed/core/v2/public/types.h"
+#include "components/feed/core/v2/public/unread_content_observer.h"
#include "components/feed/core/v2/scheduling.h"
#include "components/feed/core/v2/stream/unread_content_notifier.h"
#include "components/feed/core/v2/stream_model.h"
#include "components/feed/core/v2/surface_updater.h"
#include "components/feed/core/v2/tasks/clear_all_task.h"
-#include "components/feed/core/v2/tasks/get_prefetch_suggestions_task.h"
#include "components/feed/core/v2/tasks/load_stream_task.h"
#include "components/feed/core/v2/tasks/prefetch_images_task.h"
#include "components/feed/core/v2/tasks/upload_actions_task.h"
@@ -47,12 +48,12 @@
#include "components/feed/core/v2/web_feed_subscription_coordinator.h"
#include "components/feed/core/v2/web_feed_subscriptions/web_feed_index.h"
#include "components/feed/feed_feature_list.h"
-#include "components/offline_pages/core/prefetch/prefetch_service.h"
#include "components/offline_pages/task/closure_task.h"
#include "components/prefs/pref_service.h"
namespace feed {
namespace {
+constexpr size_t kMaxRecentFeedNavigations = 10;
void UpdateDebugStreamData(
const UploadActionsTask::Result& upload_actions_result,
@@ -87,28 +88,6 @@ void PopulateDebugStreamData(
} // namespace
-// offline_pages::SuggestionsProvider.
-class FeedStream::OfflineSuggestionsProvider
- : public offline_pages::SuggestionsProvider {
- public:
- explicit OfflineSuggestionsProvider(FeedStream* stream) : stream_(stream) {}
- virtual ~OfflineSuggestionsProvider() = default;
- OfflineSuggestionsProvider(const OfflineSuggestionsProvider&) = delete;
- OfflineSuggestionsProvider& operator=(const OfflineSuggestionsProvider&) =
- delete;
- void GetCurrentArticleSuggestions(
- SuggestionCallback suggestions_callback) override {
- stream_->GetPrefetchSuggestions(std::move(suggestions_callback));
- }
-
- // These signals aren't used for v2.
- void ReportArticleListViewed() override {}
- void ReportArticleViewed(GURL article_url) override {}
-
- private:
- FeedStream* stream_;
-};
-
FeedStream::Stream::Stream() = default;
FeedStream::Stream::~Stream() = default;
@@ -120,11 +99,8 @@ FeedStream::FeedStream(RefreshTaskScheduler* refresh_task_scheduler,
ImageFetcher* image_fetcher,
FeedStore* feed_store,
PersistentKeyValueStoreImpl* persistent_key_value_store,
- offline_pages::PrefetchService* prefetch_service,
- offline_pages::OfflinePageModel* offline_page_model,
const ChromeInfo& chrome_info)
- : prefetch_service_(prefetch_service),
- refresh_task_scheduler_(refresh_task_scheduler),
+ : refresh_task_scheduler_(refresh_task_scheduler),
metrics_reporter_(metrics_reporter),
delegate_(delegate),
profile_prefs_(profile_prefs),
@@ -140,24 +116,23 @@ FeedStream::FeedStream(RefreshTaskScheduler* refresh_task_scheduler,
static WireResponseTranslator default_translator;
wire_response_translator_ = &default_translator;
+ base::RepeatingClosure preference_change_callback =
+ base::BindRepeating(&FeedStream::EnabledPreferencesChanged, GetWeakPtr());
+ enable_snippets_.Init(prefs::kEnableSnippets, profile_prefs,
+ preference_change_callback);
+ articles_list_visible_.Init(prefs::kArticlesListVisible, profile_prefs,
+ preference_change_callback);
+ has_stored_data_.Init(feed::prefs::kHasStoredData, profile_prefs);
+
web_feed_subscription_coordinator_ =
- std::make_unique<WebFeedSubscriptionCoordinator>(this);
- Stream& stream = GetStream(kForYouStream);
- offline_page_spy_ = std::make_unique<OfflinePageSpy>(
- stream.surface_updater.get(), offline_page_model);
-
- if (prefetch_service_) {
- offline_suggestions_provider_ =
- std::make_unique<OfflineSuggestionsProvider>(this);
- prefetch_service_->SetSuggestionProvider(
- offline_suggestions_provider_.get());
- }
+ std::make_unique<WebFeedSubscriptionCoordinator>(profile_prefs, this);
// Inserting this task first ensures that |store_| is initialized before
// it is used.
task_queue_.AddTask(std::make_unique<WaitForStoreInitializeTask>(
store_, this,
base::BindOnce(&FeedStream::InitializeComplete, base::Unretained(this))));
+ EnabledPreferencesChanged();
}
FeedStream::~FeedStream() = default;
@@ -208,18 +183,41 @@ void FeedStream::TriggerStreamLoad(const StreamType& stream_type) {
stream.model_loading_in_progress = true;
stream.surface_updater->LoadStreamStarted();
+ LoadStreamTask::Options options;
+ options.stream_type = stream_type;
task_queue_.AddTask(std::make_unique<LoadStreamTask>(
- LoadStreamTask::LoadType::kInitialLoad, stream_type, this,
+ options, this,
base::BindOnce(&FeedStream::InitialStreamLoadComplete,
base::Unretained(this))));
}
void FeedStream::InitializeComplete(WaitForStoreInitializeTask::Result result) {
- metadata_ = std::move(result.metadata);
+ metadata_ = *std::move(result.startup_data.metadata);
+ for (const feedstore::StreamData& stream_data :
+ result.startup_data.stream_data) {
+ StreamType stream_type =
+ feedstore::StreamTypeFromId(stream_data.stream_id());
+ if (stream_type.IsValid()) {
+ GetStream(stream_type).content_ids =
+ feedstore::GetContentIds(stream_data);
+ }
+ }
metadata_populated_ = true;
// TODO(crbug/1152592): Test that the index is populated once there's an API
// to access the data.
web_feed_subscription_coordinator_->Populate(result.web_feed_startup_data);
+
+ for (const feedstore::StreamData& stream_data :
+ result.startup_data.stream_data) {
+ StreamType stream_type =
+ feedstore::StreamTypeFromId(stream_data.stream_id());
+ if (stream_type.IsValid())
+ MaybeNotifyHasUnreadContent(stream_type);
+ }
+
+ if (!IsEnabledAndVisible() && has_stored_data_.GetValue()) {
+ ClearAll();
+ }
}
void FeedStream::InitialStreamLoadComplete(LoadStreamTask::Result result) {
@@ -244,6 +242,24 @@ void FeedStream::InitialStreamLoadComplete(LoadStreamTask::Result result) {
result.final_status);
LoadTaskComplete(result);
+
+ // When done loading the for-you feed, try to refresh the web-feed if there's
+ // no unread content.
+ if (base::FeatureList::IsEnabled(kWebFeed) &&
+ GetFeedConfig().refresh_web_feed_after_for_you_feed_loads) {
+ if (result.stream_type.IsForYou()) {
+ if (!HasUnreadContent(kWebFeedStream)) {
+ LoadStreamTask::Options options;
+ options.load_type = LoadStreamTask::LoadType::kBackgroundRefresh;
+ options.stream_type = kWebFeedStream;
+ options.abort_if_unread_content = true;
+ task_queue_.AddTask(std::make_unique<LoadStreamTask>(
+ options, this,
+ base::BindOnce(&FeedStream::BackgroundRefreshComplete,
+ base::Unretained(this))));
+ }
+ }
+ }
}
void FeedStream::OnEnterBackground() {
@@ -272,11 +288,30 @@ void FeedStream::UpdateIsActivityLoggingEnabled(const StreamType& stream_type) {
std::string FeedStream::GetSessionId() const {
return metadata_.session_id().token();
}
+
+const feedstore::Metadata& FeedStream::GetMetadata() const {
+ DCHECK(metadata_populated_)
+ << "Metadata is not yet populated. This function should only be called "
+ "after the WaitForStoreInitialize task is complete.";
+ return metadata_;
+}
+
void FeedStream::SetMetadata(feedstore::Metadata metadata) {
metadata_ = std::move(metadata);
store_->WriteMetadata(metadata_, base::DoNothing());
}
-bool FeedStream::SetMetadata(base::Optional<feedstore::Metadata> metadata) {
+
+void FeedStream::SetStreamStale(const StreamType& stream_type, bool is_stale) {
+ feedstore::Metadata metadata = GetMetadata();
+ feedstore::Metadata::StreamMetadata& stream_metadata =
+ feedstore::MetadataForStream(metadata, stream_type);
+ if (stream_metadata.is_known_stale() != is_stale) {
+ stream_metadata.set_is_known_stale(is_stale);
+ SetMetadata(metadata);
+ }
+}
+
+bool FeedStream::SetMetadata(absl::optional<feedstore::Metadata> metadata) {
if (metadata) {
SetMetadata(std::move(*metadata));
return true;
@@ -372,7 +407,7 @@ void FeedStream::UnloadModelIfNoSurfacesAttachedTask(
}
bool FeedStream::IsArticlesListVisible() {
- return profile_prefs_->GetBoolean(prefs::kArticlesListVisible);
+ return articles_list_visible_.GetValue();
}
std::string FeedStream::GetClientInstanceId() const {
@@ -380,7 +415,17 @@ std::string FeedStream::GetClientInstanceId() const {
}
bool FeedStream::IsFeedEnabledByEnterprisePolicy() {
- return profile_prefs_->GetBoolean(prefs::kEnableSnippets);
+ return enable_snippets_.GetValue();
+}
+
+bool FeedStream::IsEnabledAndVisible() {
+ return IsArticlesListVisible() && IsFeedEnabledByEnterprisePolicy();
+}
+
+void FeedStream::EnabledPreferencesChanged() {
+ // Assume there might be stored data if the Feed is ever enabled.
+ if (IsEnabledAndVisible())
+ has_stored_data_.SetValue(true);
}
void FeedStream::LoadMore(const FeedStreamSurface& surface,
@@ -428,8 +473,6 @@ void FeedStream::LoadMoreComplete(LoadMoreTask::Result result) {
for (auto& callback : moved_callbacks) {
std::move(callback).Run(success);
}
-
- MaybeReportNewSuggestionsAvailable(result);
}
void FeedStream::ExecuteOperations(
@@ -513,11 +556,10 @@ void FeedStream::UploadActionsComplete(UploadActionsTask::Result result) {
PopulateDebugStreamData(result, *profile_prefs_);
}
-void FeedStream::GetPrefetchSuggestions(
- base::OnceCallback<void(std::vector<offline_pages::PrefetchSuggestion>)>
- suggestions_callback) {
- task_queue_.AddTask(std::make_unique<GetPrefetchSuggestionsTask>(
- this, std::move(suggestions_callback)));
+bool FeedStream::WasUrlRecentlyNavigatedFromFeed(const GURL& url) {
+ return std::find(recent_feed_navigations_.begin(),
+ recent_feed_navigations_.end(),
+ url) != recent_feed_navigations_.end();
}
DebugStreamData FeedStream::GetDebugStreamData() {
@@ -719,6 +761,7 @@ RequestMetadata FeedStream::GetRequestMetadata(const StreamType& stream_type,
result.language_tag = delegate_->GetLanguageTag();
result.notice_card_acknowledged =
notice_card_tracker_.HasAcknowledgedNoticeCard();
+ result.autoplay_enabled = delegate_->IsAutoplayEnabled();
if (is_for_next_page) {
// If we are continuing an existing feed, use whatever session continuity
@@ -811,8 +854,12 @@ void FeedStream::ExecuteRefreshTask(RefreshTaskId task_id) {
return;
}
+ LoadStreamTask::Options options;
+ options.stream_type = stream_type;
+ options.load_type = LoadStreamTask::LoadType::kBackgroundRefresh;
+ options.refresh_even_when_not_stale = true;
task_queue_.AddTask(std::make_unique<LoadStreamTask>(
- LoadStreamTask::LoadType::kBackgroundRefresh, stream_type, this,
+ options, this,
base::BindOnce(&FeedStream::BackgroundRefreshComplete,
base::Unretained(this))));
}
@@ -844,31 +891,23 @@ void FeedStream::LoadTaskComplete(const LoadStreamTask::Result& result) {
if (result.fetched_content_has_notice_card.has_value())
feed::prefs::SetLastFetchHadNoticeCard(
*profile_prefs_, *result.fetched_content_has_notice_card);
- if (!result.last_added_time.is_null())
- GetStream(result.stream_type).last_updated_time = result.last_added_time;
+ if (!result.content_ids.IsEmpty())
+ GetStream(result.stream_type).content_ids = result.content_ids;
if (result.loaded_new_content_from_network) {
+ SetStreamStale(result.stream_type, false);
if (result.stream_type.IsForYou())
UpdateExperiments(result.experiments);
}
MaybeNotifyHasUnreadContent(result.stream_type);
- MaybeReportNewSuggestionsAvailable(result);
-}
-
-void FeedStream::MaybeReportNewSuggestionsAvailable(
- const LoadStreamTask::Result& result) {
- if (result.loaded_new_content_from_network && prefetch_service_ &&
- result.stream_type.IsForYou()) {
- prefetch_service_->NewSuggestionsAvailable();
- }
}
-void FeedStream::MaybeReportNewSuggestionsAvailable(
- const LoadMoreTask::Result& result) {
- if (result.loaded_new_content_from_network && prefetch_service_ &&
- result.stream_type.IsForYou()) {
- prefetch_service_->NewSuggestionsAvailable();
- }
+bool FeedStream::HasUnreadContent(const StreamType& stream_type) {
+ Stream& stream = GetStream(stream_type);
+ if (stream.content_ids.IsEmpty())
+ return false;
+ return !feedstore::GetViewContentIds(metadata_, stream_type)
+ .ContainsAllOf(stream.content_ids);
}
void FeedStream::ClearAll() {
@@ -879,6 +918,7 @@ void FeedStream::ClearAll() {
void FeedStream::FinishClearAll() {
// Clear any experiments stored.
+ has_stored_data_.SetValue(false);
feed::prefs::SetExperiments({}, *profile_prefs_);
feed::prefs::ClearClientInstanceId(*profile_prefs_);
upload_criteria_.Clear();
@@ -930,11 +970,8 @@ void FeedStream::LoadModel(const StreamType& stream_type,
stream.model = std::move(model);
stream.model->SetStreamType(stream_type);
stream.model->SetStoreObserver(this);
- stream.last_updated_time = stream.model->GetLastAddedTime();
+ stream.content_ids = stream.model->GetContentIds();
stream.surface_updater->SetModel(stream.model.get());
- if (stream.type.IsForYou()) {
- offline_page_spy_->SetModel(stream.model.get());
- }
ScheduleModelUnloadIfNoSurfacesAttached(stream_type);
MaybeNotifyHasUnreadContent(stream_type);
}
@@ -967,9 +1004,6 @@ void FeedStream::UnloadModel(const StreamType& stream_type) {
Stream* stream = FindStream(stream_type);
if (!stream || !stream->model)
return;
- if (stream_type.IsForYou()) {
- offline_page_spy_->SetModel(nullptr);
- }
stream->surface_updater->SetModel(nullptr);
stream->model.reset();
}
@@ -980,8 +1014,13 @@ void FeedStream::UnloadModels() {
}
}
-void FeedStream::ReportOpenAction(const StreamType& stream_type,
+void FeedStream::ReportOpenAction(const GURL& url,
+ const StreamType& stream_type,
const std::string& slice_id) {
+ recent_feed_navigations_.insert(recent_feed_navigations_.begin(), url);
+ recent_feed_navigations_.resize(
+ std::min(kMaxRecentFeedNavigations, recent_feed_navigations_.size()));
+
Stream& stream = GetStream(stream_type);
int index = stream.surface_updater->GetSliceIndexFromSliceId(slice_id);
@@ -997,8 +1036,13 @@ void FeedStream::ReportOpenAction(const StreamType& stream_type,
void FeedStream::ReportOpenVisitComplete(base::TimeDelta visit_time) {
metrics_reporter_->OpenVisitComplete(visit_time);
}
-void FeedStream::ReportOpenInNewTabAction(const StreamType& stream_type,
+void FeedStream::ReportOpenInNewTabAction(const GURL& url,
+ const StreamType& stream_type,
const std::string& slice_id) {
+ recent_feed_navigations_.insert(recent_feed_navigations_.begin(), url);
+ recent_feed_navigations_.resize(
+ std::min(kMaxRecentFeedNavigations, recent_feed_navigations_.size()));
+
Stream& stream = GetStream(stream_type);
int index = stream.surface_updater->GetSliceIndexFromSliceId(slice_id);
if (index < 0)
@@ -1010,6 +1054,7 @@ void FeedStream::ReportOpenInNewTabAction(const StreamType& stream_type,
notice_card_tracker_.OnOpenAction(index);
}
}
+
void FeedStream::ReportSliceViewed(SurfaceId surface_id,
const StreamType& stream_type,
const std::string& slice_id) {
@@ -1019,8 +1064,8 @@ void FeedStream::ReportSliceViewed(SurfaceId surface_id,
return;
if (stream.model) {
- if (SetMetadata(SetStreamViewTime(metadata_, stream_type,
- stream.model->GetLastAddedTime()))) {
+ if (SetMetadata(SetStreamViewContentIds(metadata_, stream_type,
+ stream.model->GetContentIds()))) {
MaybeNotifyHasUnreadContent(stream_type);
}
metrics_reporter_->ContentSliceViewed(stream_type, index);
@@ -1044,20 +1089,16 @@ bool FeedStream::CanLogViews() const {
}
// Notifies observers if 'HasUnreadContent' has changed for `stream_type`.
-// Stream content has been seen if StreamData::last_added_time_millis ==
-// Metadata::StreamMetadata::view_time_millis. This should be called: when the
-// model is loaded, when a refresh is attempted, and when content is viewed.
+// Stream content has been seen if StreamData::content_hash ==
+// Metadata::StreamMetadata::view_content_hash. This should be called:
+// when initial metadata is loaded, when the model is loaded, when a refresh is
+// attempted, and when content is viewed.
void FeedStream::MaybeNotifyHasUnreadContent(const StreamType& stream_type) {
Stream& stream = GetStream(stream_type);
- // Don't notify if we don't know the update time.
- if (stream.last_updated_time.is_null())
+ if (!metadata_populated_ || stream.model_loading_in_progress)
return;
- const bool has_new_content =
- feedstore::GetStreamViewTime(metadata_, stream_type) !=
- stream.last_updated_time &&
- !stream.last_updated_time.is_null();
-
+ const bool has_new_content = HasUnreadContent(stream_type);
for (auto& o : stream.unread_content_notifiers) {
o.NotifyIfValueChanged(has_new_content);
}
diff --git a/chromium/components/feed/core/v2/feed_stream.h b/chromium/components/feed/core/v2/feed_stream.h
index 6ea5c4ddafa..09860ff615b 100644
--- a/chromium/components/feed/core/v2/feed_stream.h
+++ b/chromium/components/feed/core/v2/feed_stream.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/containers/circular_deque.h"
#include "base/memory/scoped_refptr.h"
#include "base/observer_list.h"
#include "base/sequenced_task_runner.h"
@@ -31,16 +32,11 @@
#include "components/feed/core/v2/web_feed_subscription_coordinator.h"
#include "components/feed/core/v2/web_feed_subscriptions/web_feed_index.h"
#include "components/feed/core/v2/wire_response_translator.h"
-#include "components/offline_pages/core/prefetch/suggestions_provider.h"
#include "components/offline_pages/task/task_queue.h"
+#include "components/prefs/pref_member.h"
class PrefService;
-namespace offline_pages {
-class OfflinePageModel;
-class PrefetchService;
-} // namespace offline_pages
-
namespace feed {
namespace feed_stream {
class UnreadContentNotifier;
@@ -50,7 +46,6 @@ class FeedStore;
class WebFeedSubscriptionCoordinator;
class ImageFetcher;
class MetricsReporter;
-class OfflinePageSpy;
class RefreshTaskScheduler;
class PersistentKeyValueStoreImpl;
class StreamModel;
@@ -71,6 +66,7 @@ class FeedStream : public FeedApi,
virtual bool IsOffline() = 0;
virtual DisplayMetrics GetDisplayMetrics() = 0;
virtual std::string GetLanguageTag() = 0;
+ virtual bool IsAutoplayEnabled() = 0;
virtual void ClearAll() = 0;
virtual std::string GetSyncSignedInGaia() = 0;
virtual void PrefetchImage(const GURL& url) = 0;
@@ -85,8 +81,6 @@ class FeedStream : public FeedApi,
ImageFetcher* image_fetcher,
FeedStore* feed_store,
PersistentKeyValueStoreImpl* persistent_key_value_store,
- offline_pages::PrefetchService* prefetch_service,
- offline_pages::OfflinePageModel* offline_page_model,
const ChromeInfo& chrome_info);
~FeedStream() override;
@@ -129,6 +123,7 @@ class FeedStream : public FeedApi,
EphemeralChangeId id) override;
void ProcessThereAndBackAgain(base::StringPiece data) override;
void ProcessViewAction(base::StringPiece data) override;
+ bool WasUrlRecentlyNavigatedFromFeed(const GURL& url) override;
DebugStreamData GetDebugStreamData() override;
void ForceRefreshForDebugging() override;
std::string DumpStateForDebugging() override;
@@ -140,10 +135,12 @@ class FeedStream : public FeedApi,
const std::string& slice_id) override;
void ReportFeedViewed(SurfaceId surface_id) override;
void ReportPageLoaded() override;
- void ReportOpenAction(const StreamType& stream_type,
+ void ReportOpenAction(const GURL& url,
+ const StreamType& stream_type,
const std::string& slice_id) override;
void ReportOpenVisitComplete(base::TimeDelta visit_time) override;
- void ReportOpenInNewTabAction(const StreamType& stream_type,
+ void ReportOpenInNewTabAction(const GURL& url,
+ const StreamType& stream_type,
const std::string& slice_id) override;
void ReportStreamScrolled(const StreamType& stream_type,
int distance_dp) override;
@@ -190,9 +187,10 @@ class FeedStream : public FeedApi,
FeedNetwork* GetNetwork() { return feed_network_; }
FeedStore* GetStore() { return store_; }
RequestThrottler* GetRequestThrottler() { return &request_throttler_; }
- const feedstore::Metadata& GetMetadata() const { return metadata_; }
+ const feedstore::Metadata& GetMetadata() const;
void SetMetadata(feedstore::Metadata metadata);
- bool SetMetadata(base::Optional<feedstore::Metadata> metadata);
+ bool SetMetadata(absl::optional<feedstore::Metadata> metadata);
+ void SetStreamStale(const StreamType& stream_type, bool is_stale);
MetricsReporter& GetMetricsReporter() const { return *metrics_reporter_; }
@@ -248,6 +246,8 @@ class FeedStream : public FeedApi,
RequestMetadata GetRequestMetadata(const StreamType& stream_type,
bool is_for_next_page) const;
+ bool HasUnreadContent(const StreamType& stream_type);
+
bool IsOffline() const { return delegate_->IsOffline(); }
offline_pages::TaskQueue& GetTaskQueue() { return task_queue_; }
@@ -272,12 +272,13 @@ class FeedStream : public FeedApi,
bool ClearAllInProgress() const { return clear_all_in_progress_; }
+ bool IsEnabledAndVisible();
+
base::WeakPtr<FeedStream> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
private:
- class OfflineSuggestionsProvider;
using UnreadContentNotifier = feed_stream::UnreadContentNotifier;
struct Stream {
@@ -295,9 +296,7 @@ class FeedStream : public FeedApi,
// |UnloadModel()|.
std::unique_ptr<StreamModel> model;
int unload_on_detach_sequence_number = 0;
- // When new content was last added to this stream. Populated when we attempt
- // to load the model or background refresh.
- base::Time last_updated_time;
+ ContentIdSet content_ids;
std::vector<UnreadContentNotifier> unread_content_notifiers;
std::vector<base::OnceCallback<void(bool)>> load_more_complete_callbacks;
bool is_activity_logging_enabled = false;
@@ -313,10 +312,6 @@ class FeedStream : public FeedApi,
// Re-evaluate whether or not activity logging should currently be enabled.
void UpdateIsActivityLoggingEnabled(const StreamType& stream_type);
- void GetPrefetchSuggestions(
- base::OnceCallback<void(std::vector<offline_pages::PrefetchSuggestion>)>
- suggestions_callback);
-
// A single function task to delete stored feed data and force a refresh.
// To only be called from within a |Task|.
void ForceRefreshForDebuggingTask();
@@ -331,8 +326,6 @@ class FeedStream : public FeedApi,
void BackgroundRefreshComplete(LoadStreamTask::Result result);
void LoadTaskComplete(const LoadStreamTask::Result& result);
void UploadActionsComplete(UploadActionsTask::Result result);
- void MaybeReportNewSuggestionsAvailable(const LoadStreamTask::Result& result);
- void MaybeReportNewSuggestionsAvailable(const LoadMoreTask::Result& result);
void ClearAll();
@@ -343,6 +336,7 @@ class FeedStream : public FeedApi,
bool CanLogViews() const;
void MaybeNotifyHasUnreadContent(const StreamType& stream_type);
+ void EnabledPreferencesChanged();
Stream& GetStream(const StreamType& type);
Stream* FindStream(const StreamType& type);
@@ -351,7 +345,6 @@ class FeedStream : public FeedApi,
// Unowned.
- offline_pages::PrefetchService* prefetch_service_;
RefreshTaskScheduler* refresh_task_scheduler_;
MetricsReporter* metrics_reporter_;
Delegate* delegate_;
@@ -368,8 +361,6 @@ class FeedStream : public FeedApi,
std::map<StreamType, Stream> streams_;
- std::unique_ptr<OfflineSuggestionsProvider> offline_suggestions_provider_;
- std::unique_ptr<OfflinePageSpy> offline_page_spy_;
std::unique_ptr<WebFeedSubscriptionCoordinator>
web_feed_subscription_coordinator_;
@@ -377,6 +368,10 @@ class FeedStream : public FeedApi,
RequestThrottler request_throttler_;
base::TimeTicks signed_out_for_you_refreshes_until_;
+ BooleanPrefMember has_stored_data_;
+ BooleanPrefMember enable_snippets_;
+ BooleanPrefMember articles_list_visible_;
+
// State loaded at startup:
feedstore::Metadata metadata_;
bool metadata_populated_ = false;
@@ -395,6 +390,8 @@ class FeedStream : public FeedApi,
bool clear_all_in_progress_ = false;
+ std::vector<GURL> recent_feed_navigations_;
+
base::WeakPtrFactory<FeedStream> weak_ptr_factory_{this};
};
diff --git a/chromium/components/feed/core/v2/feedstore_util.cc b/chromium/components/feed/core/v2/feedstore_util.cc
index d08f33e6df3..67a43657f46 100644
--- a/chromium/components/feed/core/v2/feedstore_util.cc
+++ b/chromium/components/feed/core/v2/feedstore_util.cc
@@ -4,8 +4,10 @@
#include "components/feed/core/v2/feedstore_util.h"
+#include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/v2/config.h"
#include "components/feed/core/v2/feed_store.h"
+#include "components/feed/core/v2/public/stream_type.h"
namespace feedstore {
using feed::LocalActionId;
@@ -18,6 +20,14 @@ base::StringPiece StreamId(const StreamType& stream_type) {
return kFollowStreamId;
}
+feed::StreamType StreamTypeFromId(base::StringPiece id) {
+ if (id == kForYouStreamId)
+ return feed::kForYouStream;
+ if (id == kFollowStreamId)
+ return feed::kWebFeedStream;
+ return {};
+}
+
int64_t ToTimestampMillis(base::Time t) {
return (t - base::Time::UnixEpoch()).InMilliseconds();
}
@@ -49,9 +59,9 @@ void SetSessionId(Metadata& metadata,
expiry_time.ToDeltaSinceWindowsEpoch().InMilliseconds());
}
-base::Optional<Metadata> MaybeUpdateSessionId(
+absl::optional<Metadata> MaybeUpdateSessionId(
const Metadata& metadata,
- base::Optional<std::string> token) {
+ absl::optional<std::string> token) {
if (token && metadata.session_id().token() != *token) {
base::Time expiry_time =
token->empty()
@@ -61,7 +71,7 @@ base::Optional<Metadata> MaybeUpdateSessionId(
SetSessionId(new_metadata, *token, expiry_time);
return new_metadata;
}
- return base::nullopt;
+ return absl::nullopt;
}
LocalActionId GetNextActionId(Metadata& metadata) {
@@ -91,25 +101,25 @@ Metadata::StreamMetadata& MetadataForStream(Metadata& metadata,
if (existing)
return *const_cast<Metadata::StreamMetadata*>(existing);
Metadata::StreamMetadata* sm = metadata.add_stream_metadata();
- sm->set_stream_id(StreamId(stream_type).as_string());
+ sm->set_stream_id(std::string(StreamId(stream_type)));
return *sm;
}
-void SetStreamViewTime(Metadata& metadata,
- const StreamType& stream_type,
- base::Time stream_last_added_time) {
- Metadata::StreamMetadata& sm = MetadataForStream(metadata, stream_type);
- sm.set_view_time_millis(ToTimestampMillis(stream_last_added_time));
+void SetStreamViewContentIds(Metadata& metadata,
+ const StreamType& stream_type,
+ const feed::ContentIdSet& content_ids) {
+ Metadata::StreamMetadata& stream_metadata =
+ MetadataForStream(metadata, stream_type);
+ stream_metadata.clear_view_content_ids();
+ stream_metadata.mutable_view_content_ids()->Add(content_ids.values().begin(),
+ content_ids.values().end());
}
-base::Time GetStreamViewTime(const Metadata& metadata,
- const StreamType& stream_type) {
- base::Time result;
+bool IsKnownStale(const Metadata& metadata,
+ const feed::StreamType& stream_type) {
const Metadata::StreamMetadata* sm =
FindMetadataForStream(metadata, stream_type);
- if (sm)
- result = FromTimestampMillis(sm->view_time_millis());
- return result;
+ return sm ? sm->is_known_stale() : false;
}
feedstore::Metadata MakeMetadata(const std::string& gaia) {
@@ -119,15 +129,31 @@ feedstore::Metadata MakeMetadata(const std::string& gaia) {
return md;
}
-base::Optional<Metadata> SetStreamViewTime(const Metadata& metadata,
- const StreamType& stream_type,
- base::Time stream_last_added_time) {
- base::Optional<Metadata> result;
- if (GetStreamViewTime(metadata, stream_type) != stream_last_added_time) {
+absl::optional<Metadata> SetStreamViewContentIds(
+ const Metadata& metadata,
+ const feed::StreamType& stream_type,
+ const feed::ContentIdSet& content_ids) {
+ absl::optional<Metadata> result;
+ if (!(GetViewContentIds(metadata, stream_type) == content_ids)) {
result = metadata;
- SetStreamViewTime(*result, stream_type, stream_last_added_time);
+ SetStreamViewContentIds(*result, stream_type, content_ids);
}
return result;
}
+feed::ContentIdSet GetContentIds(const StreamData& stream_data) {
+ return feed::ContentIdSet{
+ {stream_data.content_ids().begin(), stream_data.content_ids().end()}};
+}
+feed::ContentIdSet GetViewContentIds(const Metadata& metadata,
+ const feed::StreamType& stream_type) {
+ const Metadata::StreamMetadata* stream_metadata =
+ FindMetadataForStream(metadata, stream_type);
+ if (stream_metadata) {
+ return feed::ContentIdSet({stream_metadata->view_content_ids().begin(),
+ stream_metadata->view_content_ids().end()});
+ }
+ return {};
+}
+
} // namespace feedstore
diff --git a/chromium/components/feed/core/v2/feedstore_util.h b/chromium/components/feed/core/v2/feedstore_util.h
index d7bdfd2f788..d802be325ac 100644
--- a/chromium/components/feed/core/v2/feedstore_util.h
+++ b/chromium/components/feed/core/v2/feedstore_util.h
@@ -6,11 +6,12 @@
#define COMPONENTS_FEED_CORE_V2_FEEDSTORE_UTIL_H_
#include <string>
-#include "base/optional.h"
+#include "base/strings/string_piece_forward.h"
#include "base/time/time.h"
#include "components/feed/core/proto/v2/store.pb.h"
-#include "components/feed/core/v2/public/feed_api.h"
+#include "components/feed/core/v2/public/stream_type.h"
#include "components/feed/core/v2/types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feedstore {
class Metadata;
@@ -19,6 +20,7 @@ constexpr base::StringPiece kForYouStreamId{"i"};
constexpr base::StringPiece kFollowStreamId{"w"};
base::StringPiece StreamId(const feed::StreamType& stream_type);
+feed::StreamType StreamTypeFromId(base::StringPiece id);
///////////////////////////////////////////////////
// Functions that operate on feedstore proto types.
@@ -31,6 +33,8 @@ base::Time GetLastAddedTime(const feedstore::StreamData& data);
base::Time GetSessionIdExpiryTime(const feedstore::Metadata& metadata);
base::Time GetStreamViewTime(const Metadata& metadata,
const feed::StreamType& stream_type);
+bool IsKnownStale(const Metadata& metadata,
+ const feed::StreamType& stream_type);
feedstore::Metadata MakeMetadata(const std::string& gaia);
// Mutations of Metadata. Metadata will need stored again after being changed,
@@ -38,15 +42,23 @@ feedstore::Metadata MakeMetadata(const std::string& gaia);
void SetSessionId(feedstore::Metadata& metadata,
std::string token,
base::Time expiry_time);
-base::Optional<Metadata> MaybeUpdateSessionId(
+absl::optional<Metadata> MaybeUpdateSessionId(
const feedstore::Metadata& metadata,
- base::Optional<std::string> token);
+ absl::optional<std::string> token);
feed::LocalActionId GetNextActionId(feedstore::Metadata& metadata);
-const feedstore::Metadata::StreamMetadata* FindMetadataForStream(
+const Metadata::StreamMetadata* FindMetadataForStream(
+ const Metadata& metadata,
const feed::StreamType& stream_type);
-base::Optional<Metadata> SetStreamViewTime(const Metadata& metadata,
- const feed::StreamType& stream_type,
- base::Time stream_last_added_time);
+Metadata::StreamMetadata& MetadataForStream(
+ Metadata& metadata,
+ const feed::StreamType& stream_type);
+absl::optional<Metadata> SetStreamViewContentIds(
+ const Metadata& metadata,
+ const feed::StreamType& stream_type,
+ const feed::ContentIdSet& content_ids);
+feed::ContentIdSet GetContentIds(const StreamData& stream_data);
+feed::ContentIdSet GetViewContentIds(const Metadata& metadata,
+ const feed::StreamType& stream_type);
} // namespace feedstore
diff --git a/chromium/components/feed/core/v2/feedstore_util_unittest.cc b/chromium/components/feed/core/v2/feedstore_util_unittest.cc
index 2dbe7f3ddb0..24c8917e25c 100644
--- a/chromium/components/feed/core/v2/feedstore_util_unittest.cc
+++ b/chromium/components/feed/core/v2/feedstore_util_unittest.cc
@@ -40,21 +40,21 @@ TEST(feedstore_util_test, MaybeUpdateSessionId) {
SetSessionId(metadata, Token1(), kExpiryTime1);
// Updating the token with nullopt is a NOP.
- EXPECT_FALSE(MaybeUpdateSessionId(metadata, base::nullopt));
+ EXPECT_FALSE(MaybeUpdateSessionId(metadata, absl::nullopt));
// Updating the token with the same value is a NOP.
EXPECT_FALSE(MaybeUpdateSessionId(metadata, Token1()));
// Updating the token with a different value resets the token and assigns a
// new expiry time.
- base::Optional<Metadata> metadata2 = MaybeUpdateSessionId(metadata, Token2());
+ absl::optional<Metadata> metadata2 = MaybeUpdateSessionId(metadata, Token2());
ASSERT_TRUE(metadata2);
EXPECT_EQ(Token2(), metadata2->session_id().token());
EXPECT_TIME_EQ(base::Time::Now() + feed::GetFeedConfig().session_id_max_age,
GetSessionIdExpiryTime(*metadata2));
// Updating the token with the empty string clears its value.
- base::Optional<Metadata> metadata3 = MaybeUpdateSessionId(*metadata2, "");
+ absl::optional<Metadata> metadata3 = MaybeUpdateSessionId(*metadata2, "");
EXPECT_TRUE(metadata3->session_id().token().empty());
EXPECT_TRUE(GetSessionIdExpiryTime(*metadata3).is_null());
}
diff --git a/chromium/components/feed/core/v2/image_fetcher.cc b/chromium/components/feed/core/v2/image_fetcher.cc
index 49c4bc60dfe..852e9071b85 100644
--- a/chromium/components/feed/core/v2/image_fetcher.cc
+++ b/chromium/components/feed/core/v2/image_fetcher.cc
@@ -67,7 +67,7 @@ ImageFetchId ImageFetcher::Fetch(const GURL& url, ImageCallback callback) {
void ImageFetcher::OnFetchComplete(ImageFetchId id,
std::unique_ptr<std::string> response_data) {
- base::Optional<PendingRequest> request = RemovePending(id);
+ absl::optional<PendingRequest> request = RemovePending(id);
if (!request)
return;
@@ -87,7 +87,7 @@ void ImageFetcher::OnFetchComplete(ImageFetchId id,
}
void ImageFetcher::Cancel(ImageFetchId id) {
- base::Optional<PendingRequest> request = RemovePending(id);
+ absl::optional<PendingRequest> request = RemovePending(id);
if (!request)
return;
@@ -97,13 +97,13 @@ void ImageFetcher::Cancel(ImageFetchId id) {
.Run({/*response_bytes=*/std::string(), net::Error::ERR_ABORTED});
}
-base::Optional<ImageFetcher::PendingRequest> ImageFetcher::RemovePending(
+absl::optional<ImageFetcher::PendingRequest> ImageFetcher::RemovePending(
ImageFetchId id) {
auto iterator = pending_requests_.find(id);
if (iterator == pending_requests_.end())
- return base::nullopt;
+ return absl::nullopt;
- auto request = base::make_optional(std::move(iterator->second));
+ auto request = absl::make_optional(std::move(iterator->second));
pending_requests_.erase(iterator);
return request;
}
diff --git a/chromium/components/feed/core/v2/image_fetcher.h b/chromium/components/feed/core/v2/image_fetcher.h
index 0d33332117e..136588fbc71 100644
--- a/chromium/components/feed/core/v2/image_fetcher.h
+++ b/chromium/components/feed/core/v2/image_fetcher.h
@@ -9,8 +9,8 @@
#include "base/containers/flat_map.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/feed/core/v2/public/types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace network {
@@ -51,7 +51,7 @@ class ImageFetcher {
void OnFetchComplete(ImageFetchId id,
std::unique_ptr<std::string> response_data);
- base::Optional<PendingRequest> RemovePending(ImageFetchId id);
+ absl::optional<PendingRequest> RemovePending(ImageFetchId id);
ImageFetchId::Generator id_generator_;
base::flat_map<ImageFetchId, PendingRequest> pending_requests_;
diff --git a/chromium/components/feed/core/v2/metrics_reporter.cc b/chromium/components/feed/core/v2/metrics_reporter.cc
index df2ea474af8..04da533f912 100644
--- a/chromium/components/feed/core/v2/metrics_reporter.cc
+++ b/chromium/components/feed/core/v2/metrics_reporter.cc
@@ -81,6 +81,7 @@ std::string LoadLatencyStepName(LoadLatencyTimes::StepKind kind) {
void ReportLoadLatencies(std::unique_ptr<LoadLatencyTimes> latencies) {
for (const LoadLatencyTimes::Step& step : latencies->steps()) {
+ // TODO(crbug/1152592): Add a WebFeed-specific histogram for this.
base::UmaHistogramCustomTimes(
"ContentSuggestions.Feed.LoadStepLatency." +
LoadLatencyStepName(step.kind),
@@ -118,7 +119,7 @@ void MetricsReporter::TrackTimeSpentInFeed(bool interacted_or_scrolled) {
persistent_data_.accumulated_time_spent_in_feed +=
std::min(kTimeSpentInFeedInteractionTimeout,
base::TimeTicks::Now() - *time_in_feed_start_);
- time_in_feed_start_ = base::nullopt;
+ time_in_feed_start_ = absl::nullopt;
}
if (interacted_or_scrolled) {
@@ -334,7 +335,13 @@ void MetricsReporter::OtherUserAction(const StreamType& stream_type,
"ContentSuggestions.Feed.CardAction.ManageReactions"));
RecordInteraction(stream_type);
break;
+ case FeedUserActionType::kShare:
+ base::RecordAction(
+ base::UserMetricsAction("ContentSuggestions.Feed.CardAction.Share"));
+ RecordInteraction(stream_type);
+ break;
case FeedUserActionType::kEphemeralChange:
+ FALLTHROUGH;
case FeedUserActionType::kEphemeralChangeRejected:
case FeedUserActionType::kTappedTurnOn:
case FeedUserActionType::kTappedTurnOff:
@@ -491,6 +498,26 @@ void MetricsReporter::NetworkRequestComplete(NetworkRequestType type,
"ListRecommendedWebFeeds",
http_status_code);
return;
+ case NetworkRequestType::kWebFeedListContents:
+ base::UmaHistogramSparse(
+ "ContentSuggestions.Feed.Network.ResponseStatus.WebFeedListContents",
+ http_status_code);
+ return;
+ case NetworkRequestType::kQueryInteractiveFeed:
+ base::UmaHistogramSparse(
+ "ContentSuggestions.Feed.Network.ResponseStatus.QueryInteractiveFeed",
+ http_status_code);
+ return;
+ case NetworkRequestType::kQueryBackgroundFeed:
+ base::UmaHistogramSparse(
+ "ContentSuggestions.Feed.Network.ResponseStatus.QueryBackgroundFeed",
+ http_status_code);
+ return;
+ case NetworkRequestType::kQueryNextPage:
+ base::UmaHistogramSparse(
+ "ContentSuggestions.Feed.Network.ResponseStatus.QueryNextPage",
+ http_status_code);
+ return;
}
}
diff --git a/chromium/components/feed/core/v2/metrics_reporter.h b/chromium/components/feed/core/v2/metrics_reporter.h
index 704fc2cd854..b14839cb2d7 100644
--- a/chromium/components/feed/core/v2/metrics_reporter.h
+++ b/chromium/components/feed/core/v2/metrics_reporter.h
@@ -9,13 +9,13 @@
#include <map>
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/feed/core/v2/common_enums.h"
#include "components/feed/core/v2/enums.h"
-#include "components/feed/core/v2/public/feed_api.h"
+#include "components/feed/core/v2/public/stream_type.h"
#include "components/feed/core/v2/public/web_feed_subscriptions.h"
#include "components/feed/core/v2/types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
namespace feed {
@@ -145,10 +145,10 @@ class MetricsReporter {
// tapped is stored here. Upon timeout, another open attempt, or
// |ChromeStopping()|, the open is considered failed. Otherwise, if the
// loading the page succeeds, the open is considered successful.
- base::Optional<base::TimeTicks> pending_open_;
+ absl::optional<base::TimeTicks> pending_open_;
// For tracking time spent in the Feed.
- base::Optional<base::TimeTicks> time_in_feed_start_;
+ absl::optional<base::TimeTicks> time_in_feed_start_;
// For TimeSpentOnFeed.
base::TimeDelta tracked_visit_time_in_feed_;
// Non-null only directly after a stream load.
diff --git a/chromium/components/feed/core/v2/notice_card_tracker.cc b/chromium/components/feed/core/v2/notice_card_tracker.cc
index 823b3a14c0c..79c2e7f1acc 100644
--- a/chromium/components/feed/core/v2/notice_card_tracker.cc
+++ b/chromium/components/feed/core/v2/notice_card_tracker.cc
@@ -4,7 +4,7 @@
#include "components/feed/core/v2/notice_card_tracker.h"
-#include "components/feed/core/v2/prefs.h"
+#include "components/feed/core/common/pref_names.h"
#include "components/feed/feed_feature_list.h"
#include "components/prefs/pref_service.h"
@@ -23,6 +23,48 @@ int GetNoticeCardIndex() {
} // namespace
+namespace prefs {
+
+void IncrementNoticeCardViewsCount(PrefService& pref_service) {
+ int count = pref_service.GetInteger(feed::prefs::kNoticeCardViewsCount);
+ pref_service.SetInteger(feed::prefs::kNoticeCardViewsCount, count + 1);
+}
+
+int GetNoticeCardViewsCount(const PrefService& pref_service) {
+ return pref_service.GetInteger(feed::prefs::kNoticeCardViewsCount);
+}
+
+void IncrementNoticeCardClicksCount(PrefService& pref_service) {
+ int count = pref_service.GetInteger(feed::prefs::kNoticeCardClicksCount);
+ pref_service.SetInteger(feed::prefs::kNoticeCardClicksCount, count + 1);
+}
+
+int GetNoticeCardClicksCount(const PrefService& pref_service) {
+ return pref_service.GetInteger(feed::prefs::kNoticeCardClicksCount);
+}
+
+void SetLastFetchHadNoticeCard(PrefService& pref_service, bool value) {
+ pref_service.SetBoolean(feed::prefs::kLastFetchHadNoticeCard, value);
+}
+
+bool GetLastFetchHadNoticeCard(const PrefService& pref_service) {
+ return pref_service.GetBoolean(feed::prefs::kLastFetchHadNoticeCard);
+}
+
+void SetHasReachedClickAndViewActionsUploadConditions(PrefService& pref_service,
+ bool value) {
+ pref_service.SetBoolean(
+ feed::prefs::kHasReachedClickAndViewActionsUploadConditions, value);
+}
+
+bool GetHasReachedClickAndViewActionsUploadConditions(
+ const PrefService& pref_service) {
+ return pref_service.GetBoolean(
+ feed::prefs::kHasReachedClickAndViewActionsUploadConditions);
+}
+
+} // namespace prefs
+
NoticeCardTracker::NoticeCardTracker(PrefService* profile_prefs)
: profile_prefs_(profile_prefs) {
DCHECK(profile_prefs_);
diff --git a/chromium/components/feed/core/v2/notice_card_tracker.h b/chromium/components/feed/core/v2/notice_card_tracker.h
index ab604c15f2b..afe5f0b1470 100644
--- a/chromium/components/feed/core/v2/notice_card_tracker.h
+++ b/chromium/components/feed/core/v2/notice_card_tracker.h
@@ -17,6 +17,23 @@ constexpr char kNoticeCardViewsCountThresholdParamName[] =
constexpr char kNoticeCardClicksCountThresholdParamName[] =
"notice-card-clicks-count-threshold";
+namespace prefs {
+
+// Increment the stored notice card views count by 1.
+void IncrementNoticeCardViewsCount(PrefService& pref_service);
+// Increment the stored notice card clicks count by 1.
+void IncrementNoticeCardClicksCount(PrefService& pref_service);
+int GetNoticeCardClicksCount(const PrefService& pref_service);
+int GetNoticeCardViewsCount(const PrefService& pref_service);
+void SetLastFetchHadNoticeCard(PrefService& pref_service, bool value);
+bool GetLastFetchHadNoticeCard(const PrefService& pref_service);
+void SetHasReachedClickAndViewActionsUploadConditions(PrefService& pref_service,
+ bool value);
+bool GetHasReachedClickAndViewActionsUploadConditions(
+ const PrefService& pref_service);
+
+} // namespace prefs
+
// Tracker for the notice card related actions that also provide signals based
// on those.
class NoticeCardTracker {
diff --git a/chromium/components/feed/core/v2/notice_card_tracker_unittest.cc b/chromium/components/feed/core/v2/notice_card_tracker_unittest.cc
index 60efb9d10aa..822a1b8864c 100644
--- a/chromium/components/feed/core/v2/notice_card_tracker_unittest.cc
+++ b/chromium/components/feed/core/v2/notice_card_tracker_unittest.cc
@@ -6,7 +6,6 @@
#include "base/test/scoped_feature_list.h"
#include "components/feed/core/common/pref_names.h"
-#include "components/feed/core/v2/prefs.h"
#include "components/feed/feed_feature_list.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
@@ -148,4 +147,4 @@ TEST_F(NoticeCardTrackerTest,
}
} // namespace
-} // namespace feed \ No newline at end of file
+} // namespace feed
diff --git a/chromium/components/feed/core/v2/offline_page_spy.cc b/chromium/components/feed/core/v2/offline_page_spy.cc
deleted file mode 100644
index 391bb13f650..00000000000
--- a/chromium/components/feed/core/v2/offline_page_spy.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/feed/core/v2/offline_page_spy.h"
-
-#include <algorithm>
-#include <tuple>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/containers/flat_set.h"
-#include "components/feed/core/v2/algorithm.h"
-#include "components/feed/core/v2/surface_updater.h"
-
-namespace feed {
-
-namespace {
-
-std::vector<OfflinePageSpy::BadgeInfo> GetBadgesInStream(
- StreamModel* stream_model) {
- std::vector<OfflinePageSpy::BadgeInfo> badges;
- for (ContentRevision content_rev : stream_model->GetContentList()) {
- const feedstore::Content* content = stream_model->FindContent(content_rev);
- if (!content)
- continue;
- for (const feedwire::PrefetchMetadata& prefetch_metadata :
- content->prefetch_metadata()) {
- const std::string& badge_id = prefetch_metadata.badge_id();
- if (badge_id.empty())
- continue;
- GURL url(prefetch_metadata.uri());
- if (url.is_empty() || !url.is_valid())
- continue;
-
- badges.emplace_back(url, badge_id);
- }
- }
- return badges;
-}
-
-base::flat_set<GURL> OfflineItemsToUrlSet(
- const std::vector<offline_pages::OfflinePageItem>& items) {
- std::vector<GURL> url_list;
- for (const auto& item : items) {
- url_list.push_back(item.GetOriginalUrl());
- }
- return url_list;
-}
-
-} // namespace
-
-OfflinePageSpy::BadgeInfo::BadgeInfo() = default;
-OfflinePageSpy::BadgeInfo::BadgeInfo(const GURL& url,
- const std::string& badge_id)
- : url(url), badge_id(badge_id) {}
-
-bool OfflinePageSpy::BadgeInfo::operator<(const BadgeInfo& rhs) const {
- return std::tie(url, badge_id) < std::tie(rhs.url, rhs.badge_id);
-}
-
-OfflinePageSpy::OfflinePageSpy(
- SurfaceUpdater* surface_updater,
- offline_pages::OfflinePageModel* offline_page_model)
- : surface_updater_(surface_updater),
- offline_page_model_(offline_page_model) {
- offline_page_model_->AddObserver(this);
-}
-
-OfflinePageSpy::~OfflinePageSpy() {
- offline_page_model_->RemoveObserver(this);
-}
-
-void OfflinePageSpy::SetModel(StreamModel* stream_model) {
- if (stream_model_) {
- stream_model_->RemoveObserver(this);
- stream_model_ = nullptr;
- }
- if (stream_model) {
- stream_model_ = stream_model;
- stream_model_->AddObserver(this);
- UpdateWatchedPages();
- } else {
- for (const BadgeInfo& badge : badges_) {
- if (badge.available_offline) {
- surface_updater_->SetOfflinePageAvailability(badge.badge_id, false);
- }
- }
- badges_.clear();
- }
-}
-
-void OfflinePageSpy::SetAvailability(const base::flat_set<GURL>& urls,
- bool available) {
- for (BadgeInfo& badge : badges_) {
- if (badge.available_offline != available && urls.contains(badge.url)) {
- badge.available_offline = available;
- surface_updater_->SetOfflinePageAvailability(badge.badge_id, available);
- }
- }
-}
-
-void OfflinePageSpy::GetPagesDone(
- const std::vector<offline_pages::OfflinePageItem>& items) {
- SetAvailability(OfflineItemsToUrlSet(items), true);
-}
-
-void OfflinePageSpy::OfflinePageAdded(
- offline_pages::OfflinePageModel* model,
- const offline_pages::OfflinePageItem& added_page) {
- SetAvailability({added_page.GetOriginalUrl()}, true);
-}
-
-void OfflinePageSpy::OfflinePageDeleted(
- const offline_pages::OfflinePageItem& deleted_page) {
- SetAvailability({deleted_page.GetOriginalUrl()}, false);
-}
-
-void OfflinePageSpy::OnUiUpdate(const StreamModel::UiUpdate& update) {
- DCHECK(stream_model_);
- if (update.content_list_changed)
- UpdateWatchedPages();
-}
-
-void OfflinePageSpy::UpdateWatchedPages() {
- std::vector<BadgeInfo> badges = GetBadgesInStream(stream_model_);
-
- // Both lists need to be sorted. |badges_| should already be sorted.
- std::sort(badges.begin(), badges.end());
- DCHECK(std::is_sorted(badges_.begin(), badges_.end()));
-
- // Compare new and old lists. We need to inform SurfaceUpdater of removed
- // badges, and collect new URLs.
- std::vector<GURL> new_urls;
- auto differ = [&](BadgeInfo* new_badge, BadgeInfo* old_badge) {
- if (!old_badge) { // Added a page.
- new_urls.push_back(new_badge->url);
- return;
- }
- if (!new_badge) { // Removed a page.
- surface_updater_->SetOfflinePageAvailability(old_badge->badge_id, false);
- return;
- }
- // Page remains, update |badges|.
- new_badge->available_offline = old_badge->available_offline;
- };
-
- DiffSortedRange(badges.begin(), badges.end(), badges_.begin(), badges_.end(),
- differ);
-
- badges_ = std::move(badges);
- RequestOfflinePageStatus(std::move(new_urls));
-}
-
-void OfflinePageSpy::RequestOfflinePageStatus(std::vector<GURL> new_urls) {
- if (new_urls.empty())
- return;
-
- offline_pages::PageCriteria criteria;
- criteria.exclude_tab_bound_pages = true;
- criteria.additional_criteria = base::BindRepeating(
- [](const base::flat_set<GURL>& url_set,
- const offline_pages::OfflinePageItem& item) {
- return url_set.count(item.GetOriginalUrl()) > 0;
- },
- std::move(new_urls));
-
- offline_page_model_->GetPagesWithCriteria(
- criteria, base::BindOnce(&OfflinePageSpy::GetPagesDone, GetWeakPtr()));
-}
-
-} // namespace feed
diff --git a/chromium/components/feed/core/v2/offline_page_spy.h b/chromium/components/feed/core/v2/offline_page_spy.h
deleted file mode 100644
index ae5539bc387..00000000000
--- a/chromium/components/feed/core/v2/offline_page_spy.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_FEED_CORE_V2_OFFLINE_PAGE_SPY_H_
-#define COMPONENTS_FEED_CORE_V2_OFFLINE_PAGE_SPY_H_
-
-#include <string>
-#include <vector>
-
-#include "base/containers/flat_set.h"
-#include "base/memory/weak_ptr.h"
-#include "components/feed/core/v2/stream_model.h"
-#include "components/offline_pages/core/offline_page_model.h"
-#include "url/gurl.h"
-
-namespace feed {
-class SurfaceUpdater;
-
-// Watches for availability of offline pages for pages linked on the Feed.
-// Offline page availability is sent to
-// |SurfaceUpdater::SetOfflinePageAvailability()|.
-class OfflinePageSpy : public offline_pages::OfflinePageModel::Observer,
- public feed::StreamModel::Observer {
- public:
- struct BadgeInfo {
- BadgeInfo();
- BadgeInfo(const GURL& url, const std::string& badge_id);
- // For sorting by (url, badge_id).
- bool operator<(const BadgeInfo& rhs) const;
- GURL url;
- std::string badge_id;
- // Initially, this is false until we receive information that indicates
- // otherwise.
- bool available_offline = false;
- };
-
- OfflinePageSpy(SurfaceUpdater* surface_updater,
- offline_pages::OfflinePageModel* offline_page_model);
- ~OfflinePageSpy() override;
- OfflinePageSpy(const OfflinePageSpy&) = delete;
- OfflinePageSpy& operator=(const OfflinePageSpy&) = delete;
-
- void SetModel(StreamModel* stream_model);
-
- private:
- // offline_pages::OfflinePageModel::Observer
- void OfflinePageAdded(
- offline_pages::OfflinePageModel* model,
- const offline_pages::OfflinePageItem& added_page) override;
- void OfflinePageDeleted(
- const offline_pages::OfflinePageItem& deleted_page) override;
- void OfflinePageModelLoaded(offline_pages::OfflinePageModel* model) override {
- }
-
- // StreamModel::Observer
- void OnUiUpdate(const StreamModel::UiUpdate& update) override;
-
- void SetAvailability(const base::flat_set<GURL>& urls, bool available);
- void GetPagesDone(const std::vector<offline_pages::OfflinePageItem>& items);
- void UpdateWatchedPages();
- void RequestOfflinePageStatus(std::vector<GURL> new_urls);
-
- base::WeakPtr<OfflinePageSpy> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
-
- SurfaceUpdater* surface_updater_; // unowned
- offline_pages::OfflinePageModel* offline_page_model_; // unowned
- // Null when the model is not loaded.
- StreamModel* stream_model_ = nullptr; // unowned
-
- // A list of offline badges for all content in the stream.
- std::vector<BadgeInfo> badges_;
-
- base::WeakPtrFactory<OfflinePageSpy> weak_ptr_factory_{this};
-};
-
-} // namespace feed
-
-#endif // COMPONENTS_FEED_CORE_V2_OFFLINE_PAGE_SPY_H_
diff --git a/chromium/components/feed/core/v2/persistent_key_value_store_impl.h b/chromium/components/feed/core/v2/persistent_key_value_store_impl.h
index 520b7607951..270948d056b 100644
--- a/chromium/components/feed/core/v2/persistent_key_value_store_impl.h
+++ b/chromium/components/feed/core/v2/persistent_key_value_store_impl.h
@@ -11,11 +11,11 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/feed/core/v2/public/persistent_key_value_store.h"
#include "components/leveldb_proto/public/proto_database.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
#include "components/offline_pages/task/task_queue.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feedkvstore {
class Entry;
diff --git a/chromium/components/feed/core/v2/prefs.cc b/chromium/components/feed/core/v2/prefs.cc
index 340c8b98c95..3942923830d 100644
--- a/chromium/components/feed/core/v2/prefs.cc
+++ b/chromium/components/feed/core/v2/prefs.cc
@@ -102,44 +102,6 @@ void ClearClientInstanceId(PrefService& pref_service) {
pref_service.ClearPref(feed::prefs::kClientInstanceId);
}
-void SetLastFetchHadNoticeCard(PrefService& pref_service, bool value) {
- pref_service.SetBoolean(feed::prefs::kLastFetchHadNoticeCard, value);
-}
-
-bool GetLastFetchHadNoticeCard(const PrefService& pref_service) {
- return pref_service.GetBoolean(feed::prefs::kLastFetchHadNoticeCard);
-}
-
-void SetHasReachedClickAndViewActionsUploadConditions(PrefService& pref_service,
- bool value) {
- pref_service.SetBoolean(
- feed::prefs::kHasReachedClickAndViewActionsUploadConditions, value);
-}
-
-bool GetHasReachedClickAndViewActionsUploadConditions(
- const PrefService& pref_service) {
- return pref_service.GetBoolean(
- feed::prefs::kHasReachedClickAndViewActionsUploadConditions);
-}
-
-void IncrementNoticeCardViewsCount(PrefService& pref_service) {
- int count = pref_service.GetInteger(feed::prefs::kNoticeCardViewsCount);
- pref_service.SetInteger(feed::prefs::kNoticeCardViewsCount, count + 1);
-}
-
-int GetNoticeCardViewsCount(const PrefService& pref_service) {
- return pref_service.GetInteger(feed::prefs::kNoticeCardViewsCount);
-}
-
-void IncrementNoticeCardClicksCount(PrefService& pref_service) {
- int count = pref_service.GetInteger(feed::prefs::kNoticeCardClicksCount);
- pref_service.SetInteger(feed::prefs::kNoticeCardClicksCount, count + 1);
-}
-
-int GetNoticeCardClicksCount(const PrefService& pref_service) {
- return pref_service.GetInteger(feed::prefs::kNoticeCardClicksCount);
-}
-
void SetExperiments(const Experiments& experiments, PrefService& pref_service) {
base::Value value(base::Value::Type::DICTIONARY);
for (const auto& exp : experiments) {
diff --git a/chromium/components/feed/core/v2/prefs.h b/chromium/components/feed/core/v2/prefs.h
index 30b09e52d0d..04637160b05 100644
--- a/chromium/components/feed/core/v2/prefs.h
+++ b/chromium/components/feed/core/v2/prefs.h
@@ -46,24 +46,6 @@ void SetPersistentMetricsData(const PersistentMetricsData& data,
std::string GetClientInstanceId(PrefService& pref_service);
void ClearClientInstanceId(PrefService& pref_service);
-void SetLastFetchHadNoticeCard(PrefService& pref_service, bool value);
-bool GetLastFetchHadNoticeCard(const PrefService& pref_service);
-
-void SetHasReachedClickAndViewActionsUploadConditions(PrefService& pref_service,
- bool value);
-bool GetHasReachedClickAndViewActionsUploadConditions(
- const PrefService& pref_service);
-
-// Increment the stored notice card views count by 1.
-void IncrementNoticeCardViewsCount(PrefService& pref_service);
-
-int GetNoticeCardViewsCount(const PrefService& pref_service);
-
-// Increment the stored notice card clicks count by 1.
-void IncrementNoticeCardClicksCount(PrefService& pref_service);
-
-int GetNoticeCardClicksCount(const PrefService& pref_service);
-
void SetExperiments(const Experiments& experiments, PrefService& pref_service);
Experiments GetExperiments(PrefService& pref_service);
diff --git a/chromium/components/feed/core/v2/proto_util.cc b/chromium/components/feed/core/v2/proto_util.cc
index 2e352c97bc9..09c5becc589 100644
--- a/chromium/components/feed/core/v2/proto_util.cc
+++ b/chromium/components/feed/core/v2/proto_util.cc
@@ -7,6 +7,7 @@
#include <tuple>
#include <vector>
+#include "base/feature_list.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/system/sys_info.h"
@@ -18,6 +19,7 @@
#include "components/feed/core/proto/v2/wire/request.pb.h"
#include "components/feed/core/v2/config.h"
#include "components/feed/core/v2/feed_stream.h"
+#include "components/feed/core/v2/public/feed_api.h"
#include "components/feed/feed_feature_list.h"
#if defined(OS_ANDROID)
@@ -110,6 +112,7 @@ feedwire::Version GetAppVersionMessage(const ChromeInfo& chrome_info) {
}
feedwire::Request CreateFeedQueryRequest(
+ const StreamType& stream_type,
feedwire::FeedQuery::RequestReason request_reason,
const RequestMetadata& request_metadata,
const std::string& consistency_token,
@@ -127,14 +130,19 @@ feedwire::Request CreateFeedQueryRequest(
if (base::FeatureList::IsEnabled(kFeedShare)) {
feed_request.add_client_capability(feedwire::Capability::SHARE);
}
+ if (stream_type.IsWebFeed()) {
+ feed_request.add_client_capability(feedwire::Capability::WEB_FEEDS);
+ }
for (auto capability : GetFeedConfig().experimental_capabilities)
feed_request.add_client_capability(capability);
if (base::FeatureList::IsEnabled(kInterestFeedV2Hearts)) {
feed_request.add_client_capability(feedwire::Capability::HEART);
}
- if (base::FeatureList::IsEnabled(kInterestFeedV2Autoplay)) {
+ if (request_metadata.autoplay_enabled) {
feed_request.add_client_capability(
feedwire::Capability::INLINE_VIDEO_AUTOPLAY);
+ feed_request.add_client_capability(
+ feedwire::Capability::OPEN_VIDEO_COMMAND);
}
*feed_request.mutable_client_info() = CreateClientInfo(request_metadata);
@@ -244,11 +252,22 @@ feedwire::ClientInfo CreateClientInfo(const RequestMetadata& request_metadata) {
}
feedwire::Request CreateFeedQueryRefreshRequest(
+ const StreamType& stream_type,
feedwire::FeedQuery::RequestReason request_reason,
const RequestMetadata& request_metadata,
const std::string& consistency_token) {
- feedwire::Request request = CreateFeedQueryRequest(
- request_reason, request_metadata, consistency_token, std::string());
+ feedwire::Request request =
+ CreateFeedQueryRequest(stream_type, request_reason, request_metadata,
+ consistency_token, std::string());
+ if (stream_type.IsWebFeed()) {
+ // A special token that requests content for followed Web Feeds.
+ constexpr char kChromeFollowToken[] = "\"\004\022\002\b5*\tFollowing";
+ request.mutable_feed_request()
+ ->mutable_feed_query()
+ ->mutable_web_feed_token()
+ ->mutable_web_feed_token()
+ ->set_web_feed_token(kChromeFollowToken);
+ }
SetNoticeCardAcknowledged(&request, request_metadata);
return request;
}
@@ -257,9 +276,9 @@ feedwire::Request CreateFeedQueryLoadMoreRequest(
const RequestMetadata& request_metadata,
const std::string& consistency_token,
const std::string& next_page_token) {
- return CreateFeedQueryRequest(feedwire::FeedQuery::NEXT_PAGE_SCROLL,
- request_metadata, consistency_token,
- next_page_token);
+ return CreateFeedQueryRequest(
+ kForYouStream, feedwire::FeedQuery::NEXT_PAGE_SCROLL, request_metadata,
+ consistency_token, next_page_token);
}
} // namespace feed
diff --git a/chromium/components/feed/core/v2/proto_util.h b/chromium/components/feed/core/v2/proto_util.h
index 8314df731ce..c4b0bea73b6 100644
--- a/chromium/components/feed/core/v2/proto_util.h
+++ b/chromium/components/feed/core/v2/proto_util.h
@@ -7,10 +7,10 @@
#include <string>
-#include "base/time/time.h"
#include "components/feed/core/proto/v2/wire/client_info.pb.h"
#include "components/feed/core/proto/v2/wire/content_id.pb.h"
#include "components/feed/core/proto/v2/wire/feed_query.pb.h"
+#include "components/feed/core/v2/public/feed_api.h"
#include "components/feed/core/v2/types.h"
namespace feedwire {
@@ -50,6 +50,7 @@ class ContentCompareFunctor {
feedwire::ClientInfo CreateClientInfo(const RequestMetadata& request_metadata);
feedwire::Request CreateFeedQueryRefreshRequest(
+ const StreamType& stream_type,
feedwire::FeedQuery::RequestReason request_reason,
const RequestMetadata& request_metadata,
const std::string& consistency_token);
diff --git a/chromium/components/feed/core/v2/proto_util_unittest.cc b/chromium/components/feed/core/v2/proto_util_unittest.cc
index e545c67b2a1..b9ec31cbec3 100644
--- a/chromium/components/feed/core/v2/proto_util_unittest.cc
+++ b/chromium/components/feed/core/v2/proto_util_unittest.cc
@@ -10,6 +10,7 @@
#include "components/feed/core/proto/v2/wire/feed_request.pb.h"
#include "components/feed/core/proto/v2/wire/request.pb.h"
#include "components/feed/core/v2/config.h"
+#include "components/feed/core/v2/public/feed_api.h"
#include "components/feed/core/v2/test/proto_printer.h"
#include "components/feed/core/v2/types.h"
#include "components/feed/feed_feature_list.h"
@@ -49,7 +50,8 @@ TEST(ProtoUtilTest, CreateClientInfo) {
TEST(ProtoUtilTest, DefaultCapabilities) {
feedwire::FeedRequest request =
- CreateFeedQueryRefreshRequest(feedwire::FeedQuery::MANUAL_REFRESH,
+ CreateFeedQueryRefreshRequest(kForYouStream,
+ feedwire::FeedQuery::MANUAL_REFRESH,
/*request_metadata=*/{},
/*consistency_token=*/std::string())
.feed_request();
@@ -73,7 +75,8 @@ TEST(ProtoUtilTest, HeartsEnabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatures({kInterestFeedV2Hearts}, {});
feedwire::FeedRequest request =
- CreateFeedQueryRefreshRequest(feedwire::FeedQuery::MANUAL_REFRESH,
+ CreateFeedQueryRefreshRequest(kForYouStream,
+ feedwire::FeedQuery::MANUAL_REFRESH,
/*request_metadata=*/{},
/*consistency_token=*/std::string())
.feed_request();
@@ -86,7 +89,8 @@ TEST(ProtoUtilTest, ShareEnabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatures({kFeedShare}, {});
feedwire::FeedRequest request =
- CreateFeedQueryRefreshRequest(feedwire::FeedQuery::MANUAL_REFRESH,
+ CreateFeedQueryRefreshRequest(kForYouStream,
+ feedwire::FeedQuery::MANUAL_REFRESH,
/*request_metadata=*/{},
/*consistency_token=*/std::string())
.feed_request();
@@ -105,7 +109,8 @@ TEST(ProtoUtilTest, DisableCapabilitiesWithFinch) {
OverrideConfigWithFinchForTesting();
feedwire::FeedRequest request =
- CreateFeedQueryRefreshRequest(feedwire::FeedQuery::MANUAL_REFRESH,
+ CreateFeedQueryRefreshRequest(kForYouStream,
+ feedwire::FeedQuery::MANUAL_REFRESH,
/*request_metadata=*/{},
/*consistency_token=*/std::string())
.feed_request();
@@ -128,7 +133,7 @@ TEST(ProtoUtilTest, NoticeCardAcknowledged) {
RequestMetadata request_metadata;
request_metadata.notice_card_acknowledged = true;
feedwire::Request request = CreateFeedQueryRefreshRequest(
- feedwire::FeedQuery::MANUAL_REFRESH, request_metadata,
+ kForYouStream, feedwire::FeedQuery::MANUAL_REFRESH, request_metadata,
/*consistency_token=*/std::string());
EXPECT_TRUE(request.feed_request()
@@ -141,7 +146,7 @@ TEST(ProtoUtilTest, NoticeCardNotAcknowledged) {
RequestMetadata request_metadata;
request_metadata.notice_card_acknowledged = false;
feedwire::Request request = CreateFeedQueryRefreshRequest(
- feedwire::FeedQuery::MANUAL_REFRESH, request_metadata,
+ kForYouStream, feedwire::FeedQuery::MANUAL_REFRESH, request_metadata,
/*consistency_token=*/std::string());
EXPECT_FALSE(request.feed_request()
@@ -150,5 +155,21 @@ TEST(ProtoUtilTest, NoticeCardNotAcknowledged) {
.notice_card_acknowledged());
}
+TEST(ProtoUtilTest, AutoplayEnabled) {
+ RequestMetadata request_metadata;
+ request_metadata.autoplay_enabled = true;
+
+ feedwire::FeedRequest request =
+ CreateFeedQueryRefreshRequest(
+ kForYouStream, feedwire::FeedQuery::MANUAL_REFRESH, request_metadata,
+ /*consistency_token=*/std::string())
+ .feed_request();
+
+ ASSERT_THAT(request.client_capability(),
+ testing::Contains(feedwire::Capability::INLINE_VIDEO_AUTOPLAY));
+ ASSERT_THAT(request.client_capability(),
+ testing::Contains(feedwire::Capability::OPEN_VIDEO_COMMAND));
+}
+
} // namespace
} // namespace feed
diff --git a/chromium/components/feed/core/v2/protocol_translator.cc b/chromium/components/feed/core/v2/protocol_translator.cc
index 59b2ccf58da..ee4219f04d6 100644
--- a/chromium/components/feed/core/v2/protocol_translator.cc
+++ b/chromium/components/feed/core/v2/protocol_translator.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/logging.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/feed/core/proto/v2/packing.pb.h"
#include "components/feed/core/proto/v2/wire/chrome_feed_response_metadata.pb.h"
@@ -22,6 +21,7 @@
#include "components/feed/core/v2/feedstore_util.h"
#include "components/feed/core/v2/metrics_reporter.h"
#include "components/feed/core/v2/proto_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feed {
@@ -64,7 +64,7 @@ base::TimeDelta TranslateDuration(const feedwire::Duration& v) {
base::TimeDelta::FromNanoseconds(v.nanos());
}
-base::Optional<RequestSchedule> TranslateRequestSchedule(
+absl::optional<RequestSchedule> TranslateRequestSchedule(
base::Time now,
const feedwire::RequestSchedule& v) {
RequestSchedule schedule;
@@ -80,14 +80,14 @@ base::Optional<RequestSchedule> TranslateRequestSchedule(
// Fields that should be present at most once in the response.
struct ConvertedGlobalData {
- base::Optional<RequestSchedule> request_schedule;
+ absl::optional<RequestSchedule> request_schedule;
};
struct ConvertedDataOperation {
feedstore::StreamStructure stream_structure;
- base::Optional<feedstore::Content> content;
- base::Optional<feedstore::StreamSharedState> shared_state;
- base::Optional<std::string> next_page_token;
+ absl::optional<feedstore::Content> content;
+ absl::optional<feedstore::StreamSharedState> shared_state;
+ absl::optional<std::string> next_page_token;
};
bool TranslateFeature(feedwire::Feature* feature,
@@ -118,11 +118,11 @@ bool TranslateFeature(feedwire::Feature* feature,
return true;
}
-base::Optional<feedstore::StreamSharedState> TranslateSharedState(
+absl::optional<feedstore::StreamSharedState> TranslateSharedState(
feedwire::ContentId content_id,
feedwire::RenderData& wire_shared_state) {
if (wire_shared_state.render_data_type() != feedwire::RenderData::XSURFACE) {
- return base::nullopt;
+ return absl::nullopt;
}
feedstore::StreamSharedState shared_state;
@@ -178,7 +178,7 @@ bool TranslatePayload(base::Time now,
return true;
}
-base::Optional<ConvertedDataOperation> TranslateDataOperationInternal(
+absl::optional<ConvertedDataOperation> TranslateDataOperationInternal(
base::Time now,
feedwire::DataOperation operation,
ConvertedGlobalData* global_data) {
@@ -194,18 +194,18 @@ base::Optional<ConvertedDataOperation> TranslateDataOperationInternal(
case feedstore::StreamStructure::UPDATE_OR_APPEND:
if (!operation.has_metadata() || !operation.metadata().has_content_id())
- return base::nullopt;
+ return absl::nullopt;
result.stream_structure.set_allocated_content_id(
operation.mutable_metadata()->release_content_id());
if (!TranslatePayload(now, std::move(operation), global_data, result))
- return base::nullopt;
+ return absl::nullopt;
break;
case feedstore::StreamStructure::REMOVE:
if (!operation.has_metadata() || !operation.metadata().has_content_id())
- return base::nullopt;
+ return absl::nullopt;
result.stream_structure.set_allocated_content_id(
operation.mutable_metadata()->release_content_id());
@@ -213,7 +213,7 @@ base::Optional<ConvertedDataOperation> TranslateDataOperationInternal(
case feedstore::StreamStructure::UNKNOWN: // Fall through
default:
- return base::nullopt;
+ return absl::nullopt;
}
return result;
@@ -234,7 +234,7 @@ RefreshResponseData::RefreshResponseData(RefreshResponseData&&) = default;
RefreshResponseData& RefreshResponseData::operator=(RefreshResponseData&&) =
default;
-base::Optional<feedstore::DataOperation> TranslateDataOperation(
+absl::optional<feedstore::DataOperation> TranslateDataOperation(
base::Time now,
feedwire::DataOperation wire_operation) {
feedstore::DataOperation store_operation;
@@ -242,15 +242,15 @@ base::Optional<feedstore::DataOperation> TranslateDataOperation(
// actions embedded in the server protobuf. Some data in data operations
// aren't supported by this function, which is why we're passing in
// global_data=nullptr.
- base::Optional<ConvertedDataOperation> converted =
+ absl::optional<ConvertedDataOperation> converted =
TranslateDataOperationInternal(now, std::move(wire_operation), nullptr);
if (!converted)
- return base::nullopt;
+ return absl::nullopt;
// We only support translating StreamSharedStates when they will be attached
// to StreamModelUpdateRequests.
if (converted->shared_state)
- return base::nullopt;
+ return absl::nullopt;
*store_operation.mutable_structure() = std::move(converted->stream_structure);
if (converted->content)
@@ -276,7 +276,7 @@ RefreshResponseData TranslateWireResponse(
if (!wire_data_operation.has_operation())
continue;
- base::Optional<ConvertedDataOperation> operation =
+ absl::optional<ConvertedDataOperation> operation =
TranslateDataOperationInternal(
current_time, std::move(wire_data_operation), &global_data);
if (!operation)
@@ -309,20 +309,23 @@ RefreshResponseData TranslateWireResponse(
result->stream_data.set_logging_enabled(response_metadata.logging_enabled());
result->stream_data.set_privacy_notice_fulfilled(
response_metadata.privacy_notice_fulfilled());
+ for (const feedstore::Content& content : result->content) {
+ result->stream_data.add_content_ids(content.content_id().id());
+ }
- base::Optional<std::string> session_id = base::nullopt;
+ absl::optional<std::string> session_id = absl::nullopt;
if (was_signed_in_request) {
// Signed-in requests don't use session_id tokens; set an empty value to
// ensure that there are no old session_id tokens left hanging around.
session_id = std::string();
} else if (response_metadata.has_session_id()) {
// Signed-out requests can set a new session token; otherwise, we leave
- // the default base::nullopt value to keep whatever token is already in
+ // the default absl::nullopt value to keep whatever token is already in
// play.
session_id = response_metadata.session_id();
}
- base::Optional<Experiments> experiments = base::nullopt;
+ absl::optional<Experiments> experiments = absl::nullopt;
if (response_metadata.experiments_size() > 0) {
Experiments e;
for (feedwire::Experiment exp : response_metadata.experiments()) {
@@ -349,7 +352,7 @@ std::vector<feedstore::DataOperation> TranslateDismissData(
feedpacking::DismissData data) {
std::vector<feedstore::DataOperation> result;
for (auto& operation : data.data_operations()) {
- base::Optional<feedstore::DataOperation> translated_operation =
+ absl::optional<feedstore::DataOperation> translated_operation =
TranslateDataOperation(current_time, operation);
if (translated_operation) {
result.push_back(std::move(translated_operation.value()));
diff --git a/chromium/components/feed/core/v2/protocol_translator.h b/chromium/components/feed/core/v2/protocol_translator.h
index 43e12bf8592..3bac55f2ac1 100644
--- a/chromium/components/feed/core/v2/protocol_translator.h
+++ b/chromium/components/feed/core/v2/protocol_translator.h
@@ -8,15 +8,14 @@
#include <memory>
#include <vector>
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/feed/core/proto/v2/packing.pb.h"
#include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/proto/v2/wire/data_operation.pb.h"
#include "components/feed/core/proto/v2/wire/response.pb.h"
-#include "components/feed/core/v2/public/feed_api.h"
#include "components/feed/core/v2/scheduling.h"
#include "components/feed/core/v2/types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feed {
@@ -65,16 +64,16 @@ struct RefreshResponseData {
std::unique_ptr<StreamModelUpdateRequest> model_update_request;
// Server-defined request schedule, if provided.
- base::Optional<RequestSchedule> request_schedule;
+ absl::optional<RequestSchedule> request_schedule;
// Server-defined session id token, if provided.
- base::Optional<std::string> session_id;
+ absl::optional<std::string> session_id;
// List of experiments from the server, if provided.
- base::Optional<Experiments> experiments;
+ absl::optional<Experiments> experiments;
};
-base::Optional<feedstore::DataOperation> TranslateDataOperation(
+absl::optional<feedstore::DataOperation> TranslateDataOperation(
base::Time current_time,
feedwire::DataOperation wire_operation);
diff --git a/chromium/components/feed/core/v2/protocol_translator_unittest.cc b/chromium/components/feed/core/v2/protocol_translator_unittest.cc
index 56188f71b11..e3e34fc2aa9 100644
--- a/chromium/components/feed/core/v2/protocol_translator_unittest.cc
+++ b/chromium/components/feed/core/v2/protocol_translator_unittest.cc
@@ -95,7 +95,7 @@ RefreshResponseData TranslateWireResponse(feedwire::Response response,
RefreshResponseData TranslateWireResponse(feedwire::Response response) {
return TranslateWireResponse(response, true);
}
-base::Optional<feedstore::DataOperation> TranslateDataOperation(
+absl::optional<feedstore::DataOperation> TranslateDataOperation(
feedwire::DataOperation operation) {
return ::feed::TranslateDataOperation(base::Time(), std::move(operation));
}
@@ -202,7 +202,7 @@ TEST(ProtocolTranslatorTest, MissingResponseVersion) {
TEST(ProtocolTranslatorTest, TranslateContent) {
feedwire::DataOperation wire_operation =
MakeDataOperationWithContent(feedwire::DataOperation::UPDATE_OR_APPEND);
- base::Optional<feedstore::DataOperation> translated =
+ absl::optional<feedstore::DataOperation> translated =
TranslateDataOperation(wire_operation);
EXPECT_TRUE(translated);
EXPECT_EQ("content", translated->content().frame());
@@ -308,6 +308,16 @@ stream_data: {
shared_state_ids {
content_domain: "render_data"
}
+ content_ids: 3328940074512586021
+ content_ids: 8191455549164721606
+ content_ids: -8109602013173974591
+ content_ids: -8979410608587540000
+ content_ids: -8421826555441408245
+ content_ids: -3490122365494686813
+ content_ids: 2741853109953412745
+ content_ids: 586433679892097787
+ content_ids: 790985792726953756
+ content_ids: 7324025093440047528
}
content: {
content_id {
diff --git a/chromium/components/feed/core/v2/public/feed_api.cc b/chromium/components/feed/core/v2/public/feed_api.cc
index 3ff23a9c0e2..3381f276305 100644
--- a/chromium/components/feed/core/v2/public/feed_api.cc
+++ b/chromium/components/feed/core/v2/public/feed_api.cc
@@ -6,55 +6,7 @@
namespace feed {
-std::string StreamType::ToString() const {
- switch (type_) {
- case Type::kUnspecified:
- return "Unspecified";
- case Type::kForYou:
- return "ForYou";
- case Type::kWebFeed:
- return "WebFeed";
- }
-}
-
-// static
-StreamType StreamType::ForTaskId(RefreshTaskId task_id) {
- switch (task_id) {
- case RefreshTaskId::kRefreshForYouFeed:
- return kForYouStream;
- case RefreshTaskId::kRefreshWebFeed:
- return kWebFeedStream;
- }
-}
-
-bool StreamType::GetRefreshTaskId(RefreshTaskId& out_id) const {
- switch (type_) {
- case Type::kUnspecified:
- return false;
- case Type::kForYou:
- out_id = RefreshTaskId::kRefreshForYouFeed;
- return true;
- case Type::kWebFeed:
- out_id = RefreshTaskId::kRefreshWebFeed;
- return true;
- }
-}
FeedApi::FeedApi() = default;
FeedApi::~FeedApi() = default;
-FeedApi::UnreadContentObserver::UnreadContentObserver() = default;
-FeedApi::UnreadContentObserver::~UnreadContentObserver() = default;
-
-FeedStreamSurface::FeedStreamSurface(StreamType stream_type)
- : stream_type_(stream_type) {
- static SurfaceId::Generator id_generator;
- surface_id_ = id_generator.GenerateNextId();
-}
-
-FeedStreamSurface::~FeedStreamSurface() = default;
-
-SurfaceId FeedStreamSurface::GetSurfaceId() const {
- return surface_id_;
-}
-
} // namespace feed
diff --git a/chromium/components/feed/core/v2/public/feed_api.h b/chromium/components/feed/core/v2/public/feed_api.h
index fff76171615..981df1c7c0f 100644
--- a/chromium/components/feed/core/v2/public/feed_api.h
+++ b/chromium/components/feed/core/v2/public/feed_api.h
@@ -14,7 +14,9 @@
#include "base/time/time.h"
#include "components/feed/core/v2/common_enums.h"
#include "components/feed/core/v2/public/refresh_task_scheduler.h"
+#include "components/feed/core/v2/public/stream_type.h"
#include "components/feed/core/v2/public/types.h"
+#include "components/feed/core/v2/public/unread_content_observer.h"
#include "components/feed/core/v2/public/web_feed_subscriptions.h"
#include "url/gurl.h"
@@ -26,77 +28,9 @@ class DataOperation;
} // namespace feedstore
namespace feed {
-class WebFeedSubscriptions;
+class FeedStreamSurface;
class PersistentKeyValueStore;
-
-// Selects the stream type.
-// Note: currently there are two options, but this leaves room for more
-// parameters.
-class StreamType {
- public:
- enum class Type {
- // An unspecified stream type. Used only to represent an uninitialized
- // stream type value.
- kUnspecified,
- // The For-You feed stream.
- kForYou,
- // The Web Feed stream.
- kWebFeed,
- };
- constexpr StreamType() = default;
- constexpr explicit StreamType(Type t) : type_(t) {}
- bool operator<(const StreamType& rhs) const { return type_ < rhs.type_; }
- bool operator==(const StreamType& rhs) const { return type_ == rhs.type_; }
- bool IsForYou() const { return type_ == Type::kForYou; }
- bool IsWebFeed() const { return type_ == Type::kWebFeed; }
-
- // Returns a human-readable value, for debugging/DCHECK prints.
- std::string ToString() const;
-
- // Mapping functions between RefreshTaskId and StreamType.
- // Returns false if there should be no background refreshes associated with
- // this stream.
- bool GetRefreshTaskId(RefreshTaskId& out_id) const;
- static StreamType ForTaskId(RefreshTaskId task_id);
-
- private:
- Type type_ = Type::kUnspecified;
-};
-
-// Consumes stream data for a single `StreamType` and displays it to the user.
-class FeedStreamSurface : public base::CheckedObserver {
- public:
- explicit FeedStreamSurface(StreamType type);
- ~FeedStreamSurface() override;
-
- // Returns a unique ID for the surface. The ID will not be reused until
- // after the Chrome process is closed.
- SurfaceId GetSurfaceId() const;
-
- // Returns the `StreamType` this `FeedStreamSurface` requests.
- StreamType GetStreamType() const { return stream_type_; }
-
- // Called after registering the observer to provide the full stream state.
- // Also called whenever the stream changes.
- virtual void StreamUpdate(const feedui::StreamUpdate&) = 0;
-
- // Access to the xsurface data store.
- virtual void ReplaceDataStoreEntry(base::StringPiece key,
- base::StringPiece data) = 0;
- virtual void RemoveDataStoreEntry(base::StringPiece key) = 0;
-
- private:
- StreamType stream_type_;
- SurfaceId surface_id_;
-};
-
-inline std::ostream& operator<<(std::ostream& os,
- const StreamType& stream_type) {
- return os << stream_type.ToString();
-}
-
-constexpr StreamType kForYouStream(StreamType::Type::kForYou);
-constexpr StreamType kWebFeedStream(StreamType::Type::kWebFeed);
+class WebFeedSubscriptions;
// This is the public access point for interacting with the Feed contents.
// FeedApi serves multiple streams of data, one for each StreamType.
@@ -107,26 +41,6 @@ class FeedApi {
FeedApi(const FeedApi&) = delete;
FeedApi& operator=(const FeedApi&) = delete;
- // Observes whether there is unread content for a specific stream type.
- // In some cases, this information will not be known until after stream
- // data is loaded from the database. This observer will not be notified until
- // the information is available.
- class UnreadContentObserver {
- public:
- UnreadContentObserver();
- virtual ~UnreadContentObserver();
- virtual void HasUnreadContentChanged(bool has_unread_content) = 0;
- UnreadContentObserver(const UnreadContentObserver&) = delete;
- UnreadContentObserver& operator=(const UnreadContentObserver&) = delete;
-
- base::WeakPtr<UnreadContentObserver> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
-
- private:
- base::WeakPtrFactory<UnreadContentObserver> weak_ptr_factory_{this};
- };
-
virtual WebFeedSubscriptions& subscriptions() = 0;
// Attach/detach a surface. Surfaces should be attached when content is
@@ -211,8 +125,12 @@ class FeedApi {
//|feedwire::FeedAction| message.
virtual void ProcessViewAction(base::StringPiece data) = 0;
- // User interaction reporting. These should have no side-effects other than
- // reporting metrics.
+ // Returns whether `url` is a suggested Feed URLs, recently
+ // navigated to by the user.
+ virtual bool WasUrlRecentlyNavigatedFromFeed(const GURL& url) = 0;
+
+ // User interaction reporting. Unless otherwise documented, these have no
+ // side-effects other than reporting metrics.
// A slice was viewed (2/3rds of it is in the viewport). Should be called
// once for each viewed slice in the stream.
@@ -225,14 +143,18 @@ class FeedApi {
// A web page was loaded in response to opening a link from the Feed.
virtual void ReportPageLoaded() = 0;
// The user triggered the default open action, usually by tapping the card.
- virtual void ReportOpenAction(const StreamType& stream_type,
+ // Remembers the URL for later calls to `WasUrlRecentlyNavigatedFromFeed()`.
+ virtual void ReportOpenAction(const GURL& url,
+ const StreamType& stream_type,
const std::string& slice_id) = 0;
// The user triggered an open action, visited a web page, and then navigated
// away or backgrouded the tab. |visit_time| is a measure of how long the
// visited page was foregrounded.
virtual void ReportOpenVisitComplete(base::TimeDelta visit_time) = 0;
// The user triggered the 'open in new tab' action.
- virtual void ReportOpenInNewTabAction(const StreamType& stream_type,
+ // Remembers the URL for later calls to `WasUrlRecentlyNavigatedFromFeed()`.
+ virtual void ReportOpenInNewTabAction(const GURL& url,
+ const StreamType& stream_type,
const std::string& slice_id) = 0;
// The user scrolled the feed by |distance_dp| and then stopped.
virtual void ReportStreamScrolled(const StreamType& stream_type,
diff --git a/chromium/components/feed/core/v2/public/feed_service.cc b/chromium/components/feed/core/v2/public/feed_service.cc
index c120ff2bb16..19855883cfb 100644
--- a/chromium/components/feed/core/v2/public/feed_service.cc
+++ b/chromium/components/feed/core/v2/public/feed_service.cc
@@ -7,8 +7,13 @@
#include <utility>
#include "base/command_line.h"
+#include "base/hash/hash.h"
+#include "base/memory/ptr_util.h"
+#include "base/rand_util.h"
#include "base/scoped_observation.h"
+#include "base/strings/strcat.h"
#include "build/build_config.h"
+#include "components/feed/core/common/pref_names.h"
#include "components/feed/core/shared_prefs/pref_names.h"
#include "components/feed/core/v2/feed_network_impl.h"
#include "components/feed/core/v2/feed_store.h"
@@ -87,8 +92,10 @@ class FeedService::HistoryObserverImpl
class FeedService::NetworkDelegateImpl : public FeedNetworkImpl::Delegate {
public:
- explicit NetworkDelegateImpl(FeedService::Delegate* service_delegate)
- : service_delegate_(service_delegate) {}
+ NetworkDelegateImpl(FeedService::Delegate* service_delegate,
+ signin::IdentityManager* identity_manager)
+ : service_delegate_(service_delegate),
+ identity_manager_(identity_manager) {}
NetworkDelegateImpl(const NetworkDelegateImpl&) = delete;
NetworkDelegateImpl& operator=(const NetworkDelegateImpl&) = delete;
@@ -97,8 +104,14 @@ class FeedService::NetworkDelegateImpl : public FeedNetworkImpl::Delegate {
return service_delegate_->GetLanguageTag();
}
+ std::string GetSyncSignedInGaia() override {
+ return identity_manager_->GetPrimaryAccountInfo(signin::ConsentLevel::kSync)
+ .gaia;
+ }
+
private:
FeedService::Delegate* service_delegate_;
+ signin::IdentityManager* identity_manager_;
};
class FeedService::StreamDelegateImpl : public FeedStream::Delegate {
@@ -121,7 +134,7 @@ class FeedService::StreamDelegateImpl : public FeedStream::Delegate {
bool IsEulaAccepted() override {
return eula_notifier_.IsEulaAccepted() ||
base::CommandLine::ForCurrentProcess()->HasSwitch(
- "feedv2-accept-eula");
+ "feed-screenshot-mode");
}
bool IsOffline() override { return net::NetworkChangeNotifier::IsOffline(); }
DisplayMetrics GetDisplayMetrics() override {
@@ -130,6 +143,9 @@ class FeedService::StreamDelegateImpl : public FeedStream::Delegate {
std::string GetLanguageTag() override {
return service_delegate_->GetLanguageTag();
}
+ bool IsAutoplayEnabled() override {
+ return service_delegate_->IsAutoplayEnabled();
+ }
void ClearAll() override { service_delegate_->ClearAll(); }
void PrefetchImage(const GURL& url) override {
service_delegate_->PrefetchImage(url);
@@ -194,8 +210,6 @@ FeedService::FeedService(
key_value_store_database,
signin::IdentityManager* identity_manager,
history::HistoryService* history_service,
- offline_pages::PrefetchService* prefetch_service,
- offline_pages::OfflinePageModel* offline_page_model,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
scoped_refptr<base::SequencedTaskRunner> background_task_runner,
const std::string& api_key,
@@ -204,7 +218,8 @@ FeedService::FeedService(
refresh_task_scheduler_(std::move(refresh_task_scheduler)) {
stream_delegate_ = std::make_unique<StreamDelegateImpl>(
local_state, delegate_.get(), identity_manager);
- network_delegate_ = std::make_unique<NetworkDelegateImpl>(delegate_.get());
+ network_delegate_ =
+ std::make_unique<NetworkDelegateImpl>(delegate_.get(), identity_manager);
metrics_reporter_ = std::make_unique<MetricsReporter>(profile_prefs);
feed_network_ = std::make_unique<FeedNetworkImpl>(
network_delegate_.get(), identity_manager, api_key, url_loader_factory,
@@ -218,7 +233,8 @@ FeedService::FeedService(
refresh_task_scheduler_.get(), metrics_reporter_.get(),
stream_delegate_.get(), profile_prefs, feed_network_.get(),
image_fetcher_.get(), store_.get(), persistent_key_value_store_.get(),
- prefetch_service, offline_page_model, chrome_info);
+ chrome_info);
+ api_ = stream_.get();
history_observer_ = std::make_unique<HistoryObserverImpl>(
history_service, static_cast<FeedStream*>(stream_.get()),
@@ -238,10 +254,19 @@ FeedService::FeedService(
#endif
}
+FeedService::FeedService() = default;
+
+// static
+std::unique_ptr<FeedService> FeedService::CreateForTesting(FeedApi* api) {
+ auto result = base::WrapUnique(new FeedService());
+ result->api_ = api;
+ return result;
+}
+
FeedService::~FeedService() = default;
FeedApi* FeedService::GetStream() {
- return stream_.get();
+ return api_;
}
void FeedService::ClearCachedData() {
@@ -253,6 +278,24 @@ bool FeedService::IsEnabled(const PrefService& pref_service) {
return pref_service.GetBoolean(feed::prefs::kEnableSnippets);
}
+// static
+uint64_t FeedService::GetReliabilityLoggingId(const std::string& metrics_id,
+ PrefService* prefs) {
+ // The reliability logging ID is generated from the UMA client ID so that it
+ // changes whenever the UMA client ID changes. We hash the UMA client ID with
+ // a random salt so that the UMA client ID can't be guessed from the
+ // reliability logging ID. The salt never leaves the client.
+ uint64_t salt;
+ if (!prefs->HasPrefPath(prefs::kReliabilityLoggingIdSalt)) {
+ salt = base::RandUint64();
+ prefs->SetUint64(prefs::kReliabilityLoggingIdSalt, salt);
+ } else {
+ salt = prefs->GetUint64(prefs::kReliabilityLoggingIdSalt);
+ }
+ return base::FastHash(base::StrCat(
+ {metrics_id, std::string(reinterpret_cast<char*>(&salt), sizeof(salt))}));
+}
+
#if defined(OS_ANDROID)
void FeedService::OnApplicationStateChange(
base::android::ApplicationState state) {
diff --git a/chromium/components/feed/core/v2/public/feed_service.h b/chromium/components/feed/core/v2/public/feed_service.h
index ff5e7ed5353..e0c79a38e74 100644
--- a/chromium/components/feed/core/v2/public/feed_service.h
+++ b/chromium/components/feed/core/v2/public/feed_service.h
@@ -8,7 +8,6 @@
#include <memory>
#include <string>
-#include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "components/feed/core/v2/public/feed_api.h"
@@ -37,10 +36,6 @@ class Entry;
namespace network {
class SharedURLLoaderFactory;
} // namespace network
-namespace offline_pages {
-class OfflinePageModel;
-class PrefetchService;
-} // namespace offline_pages
namespace signin {
class IdentityManager;
} // namespace signin
@@ -69,6 +64,8 @@ class FeedService : public KeyedService {
virtual std::string GetLanguageTag() = 0;
// Returns display metrics for the device.
virtual DisplayMetrics GetDisplayMetrics() = 0;
+ // Returns true if autoplay is enabled.
+ virtual bool IsAutoplayEnabled() = 0;
// Clear all stored data.
virtual void ClearAll() = 0;
// Fetch the image and store it in the disk cache.
@@ -92,12 +89,11 @@ class FeedService : public KeyedService {
key_value_store_database,
signin::IdentityManager* identity_manager,
history::HistoryService* history_service,
- offline_pages::PrefetchService* prefetch_service,
- offline_pages::OfflinePageModel* offline_page_model,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
scoped_refptr<base::SequencedTaskRunner> background_task_runner,
const std::string& api_key,
const ChromeInfo& chrome_info);
+ static std::unique_ptr<FeedService> CreateForTesting(FeedApi* api);
~FeedService() override;
FeedService(const FeedService&) = delete;
FeedService& operator=(const FeedService&) = delete;
@@ -113,11 +109,20 @@ class FeedService : public KeyedService {
// Whether Feedv2 is enabled. If false, the FeedService should not be created.
static bool IsEnabled(const PrefService& pref_service);
+ // Returns the client ID for reliability logging.
+ static uint64_t GetReliabilityLoggingId(const std::string& metrics_id,
+ PrefService* pref_service);
+
+ // Whether autoplay is enabled.
+ static bool IsAutoplayEnabled(const PrefService& pref_service);
+
private:
class StreamDelegateImpl;
class NetworkDelegateImpl;
class HistoryObserverImpl;
class IdentityManagerObserverImpl;
+
+ FeedService();
#if defined(OS_ANDROID)
void OnApplicationStateChange(base::android::ApplicationState state);
#endif
@@ -141,6 +146,7 @@ class FeedService : public KeyedService {
application_status_listener_;
#endif
std::unique_ptr<FeedStream> stream_;
+ FeedApi* api_; // Points to `stream_`, overridden for testing.
};
} // namespace feed
diff --git a/chromium/components/feed/core/v2/public/feed_stream_surface.cc b/chromium/components/feed/core/v2/public/feed_stream_surface.cc
new file mode 100644
index 00000000000..1d88c8a5b89
--- /dev/null
+++ b/chromium/components/feed/core/v2/public/feed_stream_surface.cc
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/feed/core/v2/public/feed_stream_surface.h"
+
+namespace feed {
+
+FeedStreamSurface::FeedStreamSurface(StreamType stream_type)
+ : stream_type_(stream_type) {
+ static SurfaceId::Generator id_generator;
+ surface_id_ = id_generator.GenerateNextId();
+}
+
+FeedStreamSurface::~FeedStreamSurface() = default;
+
+SurfaceId FeedStreamSurface::GetSurfaceId() const {
+ return surface_id_;
+}
+
+} // namespace feed
diff --git a/chromium/components/feed/core/v2/public/feed_stream_surface.h b/chromium/components/feed/core/v2/public/feed_stream_surface.h
new file mode 100644
index 00000000000..1b04c568b3a
--- /dev/null
+++ b/chromium/components/feed/core/v2/public/feed_stream_surface.h
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FEED_CORE_V2_PUBLIC_FEED_STREAM_SURFACE_H_
+#define COMPONENTS_FEED_CORE_V2_PUBLIC_FEED_STREAM_SURFACE_H_
+
+#include "base/observer_list_types.h"
+#include "components/feed/core/v2/public/stream_type.h"
+#include "components/feed/core/v2/public/types.h"
+
+namespace feedui {
+class StreamUpdate;
+}
+
+namespace feed {
+
+// Consumes stream data for a single `StreamType` and displays it to the user.
+class FeedStreamSurface : public base::CheckedObserver {
+ public:
+ explicit FeedStreamSurface(StreamType type);
+ ~FeedStreamSurface() override;
+
+ // Returns a unique ID for the surface. The ID will not be reused until
+ // after the Chrome process is closed.
+ SurfaceId GetSurfaceId() const;
+
+ // Returns the `StreamType` this `FeedStreamSurface` requests.
+ StreamType GetStreamType() const { return stream_type_; }
+
+ // Called after registering the observer to provide the full stream state.
+ // Also called whenever the stream changes.
+ virtual void StreamUpdate(const feedui::StreamUpdate&) = 0;
+
+ // Access to the xsurface data store.
+ virtual void ReplaceDataStoreEntry(base::StringPiece key,
+ base::StringPiece data) = 0;
+ virtual void RemoveDataStoreEntry(base::StringPiece key) = 0;
+
+ private:
+ StreamType stream_type_;
+ SurfaceId surface_id_;
+};
+
+} // namespace feed
+#endif // COMPONENTS_FEED_CORE_V2_PUBLIC_FEED_STREAM_SURFACE_H_
diff --git a/chromium/components/feed/core/v2/public/persistent_key_value_store.h b/chromium/components/feed/core/v2/public/persistent_key_value_store.h
index 070d21e8782..35a4d2653e1 100644
--- a/chromium/components/feed/core/v2/public/persistent_key_value_store.h
+++ b/chromium/components/feed/core/v2/public/persistent_key_value_store.h
@@ -9,7 +9,7 @@
#include <string>
#include "base/callback.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feed {
@@ -28,7 +28,7 @@ class PersistentKeyValueStore {
// database error, or a missing key/value pair.
bool success = false;
// For `Get()` operations, the value of the key if it exists.
- base::Optional<std::string> get_result;
+ absl::optional<std::string> get_result;
};
using ResultCallback = base::OnceCallback<void(Result)>;
diff --git a/chromium/components/feed/core/v2/public/stream_type.cc b/chromium/components/feed/core/v2/public/stream_type.cc
new file mode 100644
index 00000000000..077d5e7f418
--- /dev/null
+++ b/chromium/components/feed/core/v2/public/stream_type.cc
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/feed/core/v2/public/stream_type.h"
+
+namespace feed {
+
+std::string StreamType::ToString() const {
+ switch (type_) {
+ case Type::kUnspecified:
+ return "Unspecified";
+ case Type::kForYou:
+ return "ForYou";
+ case Type::kWebFeed:
+ return "WebFeed";
+ }
+}
+
+// static
+StreamType StreamType::ForTaskId(RefreshTaskId task_id) {
+ switch (task_id) {
+ case RefreshTaskId::kRefreshForYouFeed:
+ return kForYouStream;
+ case RefreshTaskId::kRefreshWebFeed:
+ return kWebFeedStream;
+ }
+}
+
+bool StreamType::GetRefreshTaskId(RefreshTaskId& out_id) const {
+ switch (type_) {
+ case Type::kUnspecified:
+ return false;
+ case Type::kForYou:
+ out_id = RefreshTaskId::kRefreshForYouFeed;
+ return true;
+ case Type::kWebFeed:
+ return false;
+ }
+}
+
+} // namespace feed
diff --git a/chromium/components/feed/core/v2/public/stream_type.h b/chromium/components/feed/core/v2/public/stream_type.h
new file mode 100644
index 00000000000..f846a1e18cf
--- /dev/null
+++ b/chromium/components/feed/core/v2/public/stream_type.h
@@ -0,0 +1,59 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FEED_CORE_V2_PUBLIC_STREAM_TYPE_H_
+#define COMPONENTS_FEED_CORE_V2_PUBLIC_STREAM_TYPE_H_
+
+#include <string>
+
+#include "components/feed/core/v2/public/types.h"
+
+namespace feed {
+
+// Selects the stream type.
+// Note: currently there are two options, but this leaves room for more
+// parameters.
+class StreamType {
+ public:
+ enum class Type {
+ // An unspecified stream type. Used only to represent an uninitialized
+ // stream type value.
+ kUnspecified,
+ // The For-You feed stream.
+ kForYou,
+ // The Web Feed stream.
+ kWebFeed,
+ };
+ constexpr StreamType() = default;
+ constexpr explicit StreamType(Type t) : type_(t) {}
+ bool operator<(const StreamType& rhs) const { return type_ < rhs.type_; }
+ bool operator==(const StreamType& rhs) const { return type_ == rhs.type_; }
+ bool IsForYou() const { return type_ == Type::kForYou; }
+ bool IsWebFeed() const { return type_ == Type::kWebFeed; }
+ bool IsValid() const { return type_ != Type::kUnspecified; }
+
+ // Returns a human-readable value, for debugging/DCHECK prints.
+ std::string ToString() const;
+
+ // Mapping functions between RefreshTaskId and StreamType.
+ // Returns false if there should be no background refreshes associated with
+ // this stream.
+ bool GetRefreshTaskId(RefreshTaskId& out_id) const;
+ static StreamType ForTaskId(RefreshTaskId task_id);
+
+ private:
+ Type type_ = Type::kUnspecified;
+};
+
+constexpr StreamType kForYouStream(StreamType::Type::kForYou);
+constexpr StreamType kWebFeedStream(StreamType::Type::kWebFeed);
+
+inline std::ostream& operator<<(std::ostream& os,
+ const StreamType& stream_type) {
+ return os << stream_type.ToString();
+}
+
+} // namespace feed
+
+#endif // COMPONENTS_FEED_CORE_V2_PUBLIC_STREAM_TYPE_H_
diff --git a/chromium/components/feed/core/v2/public/types.cc b/chromium/components/feed/core/v2/public/types.cc
index fd7ec1758df..d71fa010cea 100644
--- a/chromium/components/feed/core/v2/public/types.cc
+++ b/chromium/components/feed/core/v2/public/types.cc
@@ -13,15 +13,51 @@ WebFeedMetadata::WebFeedMetadata(WebFeedMetadata&&) = default;
WebFeedMetadata& WebFeedMetadata::operator=(const WebFeedMetadata&) = default;
WebFeedMetadata& WebFeedMetadata::operator=(WebFeedMetadata&&) = default;
+WebFeedPageInformation::WebFeedPageInformation() = default;
+WebFeedPageInformation::~WebFeedPageInformation() = default;
+WebFeedPageInformation::WebFeedPageInformation(const WebFeedPageInformation&) =
+ default;
+WebFeedPageInformation::WebFeedPageInformation(WebFeedPageInformation&&) =
+ default;
+WebFeedPageInformation& WebFeedPageInformation::operator=(
+ const WebFeedPageInformation&) = default;
+WebFeedPageInformation& WebFeedPageInformation::operator=(
+ WebFeedPageInformation&&) = default;
void WebFeedPageInformation::SetUrl(const GURL& url) {
url::Replacements<char> clear_ref;
clear_ref.ClearRef();
url_ = url.ReplaceComponents(clear_ref);
}
+void WebFeedPageInformation::SetRssUrls(const std::vector<GURL>& rss_urls) {
+ rss_urls_ = rss_urls;
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const WebFeedPageInformation& value) {
+ os << "{ " << value.url() << " ";
+ os << "RSS:\n";
+ for (const GURL& url : value.GetRssUrls()) {
+ os << url << '\n';
+ }
+ os << "}";
+ return os;
+}
+
// operator<< functions below are for test purposes, and shouldn't be called
// from production code to avoid a binary size impact.
+std::ostream& operator<<(std::ostream& os, const NetworkResponseInfo& o) {
+ return os << "NetworkResponseInfo{"
+ << " status_code=" << o.status_code
+ << " fetch_duration=" << o.fetch_duration
+ << " fetch_time=" << o.fetch_time
+ << " bless_nonce=" << o.bless_nonce
+ << " base_request_url=" << o.base_request_url
+ << " response_body_bytes=" << o.response_body_bytes
+ << " was_signed_in=" << o.was_signed_in << "}";
+}
+
std::ostream& operator<<(std::ostream& out, WebFeedSubscriptionStatus value) {
switch (value) {
case WebFeedSubscriptionStatus::kUnknown:
diff --git a/chromium/components/feed/core/v2/public/types.h b/chromium/components/feed/core/v2/public/types.h
index d26f30820b5..92220b0c7ac 100644
--- a/chromium/components/feed/core/v2/public/types.h
+++ b/chromium/components/feed/core/v2/public/types.h
@@ -9,18 +9,20 @@
#include <map>
#include <string>
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "base/util/type_safety/id_type.h"
#include "base/version.h"
#include "components/version_info/channel.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace feed {
enum class RefreshTaskId {
kRefreshForYouFeed,
+ // TODO(1152592): Refresh is not currently used for the Web Feed. Remove this
+ // code if we don't need it.
kRefreshWebFeed,
};
@@ -62,6 +64,8 @@ struct NetworkResponseInfo {
bool was_signed_in = false;
};
+std::ostream& operator<<(std::ostream& os, const NetworkResponseInfo& o);
+
struct NetworkResponse {
// HTTP response body.
std::string response_bytes;
@@ -82,30 +86,42 @@ struct DebugStreamData {
DebugStreamData(const DebugStreamData&);
DebugStreamData& operator=(const DebugStreamData&);
- base::Optional<NetworkResponseInfo> fetch_info;
- base::Optional<NetworkResponseInfo> upload_info;
+ absl::optional<NetworkResponseInfo> fetch_info;
+ absl::optional<NetworkResponseInfo> upload_info;
std::string load_stream_status;
};
std::string SerializeDebugStreamData(const DebugStreamData& data);
-base::Optional<DebugStreamData> DeserializeDebugStreamData(
+absl::optional<DebugStreamData> DeserializeDebugStreamData(
base::StringPiece base64_encoded);
// Information about a web page which may be used to determine an associated web
// feed.
class WebFeedPageInformation {
public:
- WebFeedPageInformation() = default;
+ WebFeedPageInformation();
+ ~WebFeedPageInformation();
+ WebFeedPageInformation(const WebFeedPageInformation&);
+ WebFeedPageInformation(WebFeedPageInformation&&);
+ WebFeedPageInformation& operator=(const WebFeedPageInformation&);
+ WebFeedPageInformation& operator=(WebFeedPageInformation&&);
+
// The URL for the page. `url().has_ref()` is always false.
- GURL url() const { return url_; }
+ const GURL& url() const { return url_; }
+ // The list of RSS urls embedded in the page with the <link> tag.
+ const std::vector<GURL>& GetRssUrls() const { return rss_urls_; }
// Set the URL for the page. Trims off the URL ref.
void SetUrl(const GURL& url);
+ void SetRssUrls(const std::vector<GURL>& rss_urls);
+
private:
GURL url_;
+ std::vector<GURL> rss_urls_;
// TODO(crbug/1152592): There will be additional optional information.
};
+std::ostream& operator<<(std::ostream& os, const WebFeedPageInformation& value);
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.feed.webfeed
enum class WebFeedSubscriptionStatus {
diff --git a/chromium/components/feed/core/v2/public/types_unittest.cc b/chromium/components/feed/core/v2/public/types_unittest.cc
index 26f7d3e5081..96b2a355094 100644
--- a/chromium/components/feed/core/v2/public/types_unittest.cc
+++ b/chromium/components/feed/core/v2/public/types_unittest.cc
@@ -37,7 +37,7 @@ DebugStreamData MakeDebugStreamData() {
TEST(DebugStreamData, CanSerialize) {
const DebugStreamData test_data = MakeDebugStreamData();
const auto serialized = SerializeDebugStreamData(test_data);
- base::Optional<DebugStreamData> result =
+ absl::optional<DebugStreamData> result =
DeserializeDebugStreamData(serialized);
ASSERT_TRUE(result);
@@ -68,10 +68,10 @@ TEST(DebugStreamData, CanSerialize) {
TEST(DebugStreamData, CanSerializeWithoutFetchInfo) {
DebugStreamData input = MakeDebugStreamData();
- input.fetch_info = base::nullopt;
+ input.fetch_info = absl::nullopt;
const auto serialized = SerializeDebugStreamData(input);
- base::Optional<DebugStreamData> result =
+ absl::optional<DebugStreamData> result =
DeserializeDebugStreamData(serialized);
ASSERT_TRUE(result);
@@ -80,10 +80,10 @@ TEST(DebugStreamData, CanSerializeWithoutFetchInfo) {
TEST(DebugStreamData, CanSerializeWithoutUploadInfo) {
DebugStreamData input = MakeDebugStreamData();
- input.upload_info = base::nullopt;
+ input.upload_info = absl::nullopt;
const auto serialized = SerializeDebugStreamData(input);
- base::Optional<DebugStreamData> result =
+ absl::optional<DebugStreamData> result =
DeserializeDebugStreamData(serialized);
ASSERT_TRUE(result);
@@ -91,7 +91,7 @@ TEST(DebugStreamData, CanSerializeWithoutUploadInfo) {
}
TEST(DebugStreamData, FailsDeserializationGracefully) {
- ASSERT_EQ(base::nullopt, DeserializeDebugStreamData({}));
+ ASSERT_EQ(absl::nullopt, DeserializeDebugStreamData({}));
}
TEST(WebFeedPageInformation, SetUrlStripsFragment) {
diff --git a/chromium/components/feed/core/v2/public/unread_content_observer.cc b/chromium/components/feed/core/v2/public/unread_content_observer.cc
new file mode 100644
index 00000000000..81da26c47a9
--- /dev/null
+++ b/chromium/components/feed/core/v2/public/unread_content_observer.cc
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/feed/core/v2/public/unread_content_observer.h"
+
+namespace feed {
+
+UnreadContentObserver::UnreadContentObserver() = default;
+UnreadContentObserver::~UnreadContentObserver() = default;
+
+} // namespace feed
diff --git a/chromium/components/feed/core/v2/public/unread_content_observer.h b/chromium/components/feed/core/v2/public/unread_content_observer.h
new file mode 100644
index 00000000000..dc85256bf18
--- /dev/null
+++ b/chromium/components/feed/core/v2/public/unread_content_observer.h
@@ -0,0 +1,34 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_FEED_CORE_V2_PUBLIC_UNREAD_CONTENT_OBSERVER_H_
+#define COMPONENTS_FEED_CORE_V2_PUBLIC_UNREAD_CONTENT_OBSERVER_H_
+
+#include "base/memory/weak_ptr.h"
+
+namespace feed {
+
+// Observes whether there is unread content for a specific stream type.
+// In some cases, this information will not be known until after stream
+// data is loaded from the database. This observer will not be notified until
+// the information is available.
+class UnreadContentObserver {
+ public:
+ UnreadContentObserver();
+ virtual ~UnreadContentObserver();
+ virtual void HasUnreadContentChanged(bool has_unread_content) = 0;
+ UnreadContentObserver(const UnreadContentObserver&) = delete;
+ UnreadContentObserver& operator=(const UnreadContentObserver&) = delete;
+
+ base::WeakPtr<UnreadContentObserver> GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
+ private:
+ base::WeakPtrFactory<UnreadContentObserver> weak_ptr_factory_{this};
+};
+
+} // namespace feed
+
+#endif // COMPONENTS_FEED_CORE_V2_PUBLIC_UNREAD_CONTENT_OBSERVER_H_
diff --git a/chromium/components/feed/core/v2/public/web_feed_subscriptions.h b/chromium/components/feed/core/v2/public/web_feed_subscriptions.h
index c87dbb6acb3..31de4fa8fcf 100644
--- a/chromium/components/feed/core/v2/public/web_feed_subscriptions.h
+++ b/chromium/components/feed/core/v2/public/web_feed_subscriptions.h
@@ -61,6 +61,21 @@ class WebFeedSubscriptions {
// Returns all current subscriptions.
virtual void GetAllSubscriptions(
base::OnceCallback<void(std::vector<WebFeedMetadata>)> callback) = 0;
+
+ // Result of `RefreshSubscriptions()`.
+ struct RefreshResult {
+ // Whether or not the refresh succeeded. Failures may happen due to network
+ // errors.
+ bool success = false;
+ };
+ // Refresh list of subscribed web feeds from the server.
+ virtual void RefreshSubscriptions(
+ base::OnceCallback<void(RefreshResult)> callback) = 0;
+
+ // Whether the user has subscribed to at least one web feed.
+ // Because this function returns synchronously, it may return the wrong value.
+ // TODO(crbug.com/1152592): Update this and its callers to use an async call.
+ virtual bool IsWebFeedSubscriber() = 0;
};
} // namespace feed
diff --git a/chromium/components/feed/core/v2/request_throttler.cc b/chromium/components/feed/core/v2/request_throttler.cc
index c0dc3ac97a0..682becee351 100644
--- a/chromium/components/feed/core/v2/request_throttler.cc
+++ b/chromium/components/feed/core/v2/request_throttler.cc
@@ -19,10 +19,14 @@ int GetMaxRequestsPerDay(NetworkRequestType request_type) {
const Config& config = GetFeedConfig();
switch (request_type) {
case NetworkRequestType::kFeedQuery:
+ case NetworkRequestType::kWebFeedListContents:
+ case NetworkRequestType::kQueryInteractiveFeed:
+ case NetworkRequestType::kQueryBackgroundFeed:
return config.max_feed_query_requests_per_day;
case NetworkRequestType::kUploadActions:
return config.max_action_upload_requests_per_day;
case NetworkRequestType::kNextPage:
+ case NetworkRequestType::kQueryNextPage:
return config.max_next_page_requests_per_day;
case NetworkRequestType::kListWebFeeds:
return config.max_list_web_feeds_requests_per_day;
diff --git a/chromium/components/feed/core/v2/scheduling.cc b/chromium/components/feed/core/v2/scheduling.cc
index 9b8671a996d..1dcc6e00d7b 100644
--- a/chromium/components/feed/core/v2/scheduling.cc
+++ b/chromium/components/feed/core/v2/scheduling.cc
@@ -8,6 +8,7 @@
#include "base/util/values/values_util.h"
#include "base/values.h"
#include "components/feed/core/v2/config.h"
+#include "components/feed/core/v2/feedstore_util.h"
namespace feed {
namespace {
@@ -25,7 +26,7 @@ bool ValueToVector(const base::Value& value,
if (!value.is_list())
return false;
for (const base::Value& entry : value.GetList()) {
- base::Optional<base::TimeDelta> delta = util::ValueToTimeDelta(entry);
+ absl::optional<base::TimeDelta> delta = util::ValueToTimeDelta(entry);
if (!delta)
return false;
result->push_back(*delta);
@@ -52,7 +53,7 @@ RequestSchedule RequestScheduleFromValue(const base::Value& value) {
if (!value.is_dict())
return {};
RequestSchedule result;
- base::Optional<base::Time> anchor =
+ absl::optional<base::Time> anchor =
util::ValueToTime(value.FindKey("anchor"));
const base::Value* offsets =
value.FindKeyOfType("offsets", base::Value::Type::LIST);
@@ -86,8 +87,17 @@ base::Time NextScheduledRequestTime(base::Time now, RequestSchedule* schedule) {
return now + GetFeedConfig().default_background_refresh_interval;
}
-bool ShouldWaitForNewContent(bool has_content, base::TimeDelta content_age) {
- return !has_content || content_age > GetFeedConfig().stale_content_threshold;
+bool ShouldWaitForNewContent(const feedstore::Metadata& metadata,
+ const StreamType& stream_type,
+ bool has_content,
+ base::TimeDelta content_age) {
+ if (!has_content)
+ return true;
+ const feedstore::Metadata::StreamMetadata* stream_metadata =
+ feedstore::FindMetadataForStream(metadata, stream_type);
+ if (stream_metadata && stream_metadata->is_known_stale())
+ return true;
+ return content_age > GetFeedConfig().GetStalenessThreshold(stream_type);
}
} // namespace feed
diff --git a/chromium/components/feed/core/v2/scheduling.h b/chromium/components/feed/core/v2/scheduling.h
index 693809600a4..b3c9f66095d 100644
--- a/chromium/components/feed/core/v2/scheduling.h
+++ b/chromium/components/feed/core/v2/scheduling.h
@@ -9,10 +9,14 @@
#include "base/time/time.h"
#include "components/feed/core/v2/enums.h"
+#include "components/feed/core/v2/public/stream_type.h"
namespace base {
class Value;
}
+namespace feedstore {
+class Metadata;
+}
namespace feed {
constexpr base::TimeDelta kSuppressRefreshDuration =
base::TimeDelta::FromMinutes(30);
@@ -39,7 +43,10 @@ RequestSchedule RequestScheduleFromValue(const base::Value&);
base::Time NextScheduledRequestTime(base::Time now, RequestSchedule* schedule);
// Returns whether we should wait for new content before showing stream content.
-bool ShouldWaitForNewContent(bool has_content, base::TimeDelta content_age);
+bool ShouldWaitForNewContent(const feedstore::Metadata& metadata,
+ const StreamType& stream_type,
+ bool has_content,
+ base::TimeDelta content_age);
} // namespace feed
#endif // COMPONENTS_FEED_CORE_V2_SCHEDULING_H_
diff --git a/chromium/components/feed/core/v2/stream/unread_content_notifier.h b/chromium/components/feed/core/v2/stream/unread_content_notifier.h
index 8168d032d4c..fb98d51258c 100644
--- a/chromium/components/feed/core/v2/stream/unread_content_notifier.h
+++ b/chromium/components/feed/core/v2/stream/unread_content_notifier.h
@@ -5,7 +5,7 @@
#ifndef COMPONENTS_FEED_CORE_V2_STREAM_UNREAD_CONTENT_NOTIFIER_H_
#define COMPONENTS_FEED_CORE_V2_STREAM_UNREAD_CONTENT_NOTIFIER_H_
-#include "components/feed/core/v2/public/feed_api.h"
+#include "components/feed/core/v2/public/unread_content_observer.h"
namespace feed {
namespace feed_stream {
@@ -13,7 +13,6 @@ namespace feed_stream {
// Wraps and notifies a `UnreadContentObserver`.
class UnreadContentNotifier {
public:
- using UnreadContentObserver = FeedApi::UnreadContentObserver;
explicit UnreadContentNotifier(base::WeakPtr<UnreadContentObserver> observer);
~UnreadContentNotifier();
UnreadContentNotifier(UnreadContentNotifier&&);
diff --git a/chromium/components/feed/core/v2/stream/upload_criteria.cc b/chromium/components/feed/core/v2/stream/upload_criteria.cc
index 529b4f97b78..4daf2baade9 100644
--- a/chromium/components/feed/core/v2/stream/upload_criteria.cc
+++ b/chromium/components/feed/core/v2/stream/upload_criteria.cc
@@ -5,6 +5,7 @@
#include "components/feed/core/v2/stream/upload_criteria.h"
#include "base/feature_list.h"
+#include "components/feed/core/v2/notice_card_tracker.h"
#include "components/feed/core/v2/prefs.h"
#include "components/feed/feed_feature_list.h"
#include "components/prefs/pref_service.h"
diff --git a/chromium/components/feed/core/v2/stream_model.cc b/chromium/components/feed/core/v2/stream_model.cc
index 4722656d320..3ee039ee569 100644
--- a/chromium/components/feed/core/v2/stream_model.cc
+++ b/chromium/components/feed/core/v2/stream_model.cc
@@ -272,6 +272,9 @@ const std::string& StreamModel::GetNextPageToken() const {
base::Time StreamModel::GetLastAddedTime() const {
return feedstore::GetLastAddedTime(stream_data_);
}
+ContentIdSet StreamModel::GetContentIds() const {
+ return feedstore::GetContentIds(stream_data_);
+}
std::string StreamModel::DumpStateForTesting() {
std::stringstream ss;
diff --git a/chromium/components/feed/core/v2/stream_model.h b/chromium/components/feed/core/v2/stream_model.h
index f72d859e13a..ddc07d6c937 100644
--- a/chromium/components/feed/core/v2/stream_model.h
+++ b/chromium/components/feed/core/v2/stream_model.h
@@ -16,9 +16,10 @@
#include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/proto/v2/wire/content_id.pb.h"
#include "components/feed/core/v2/proto_util.h"
-#include "components/feed/core/v2/public/feed_api.h"
+#include "components/feed/core/v2/public/stream_type.h"
#include "components/feed/core/v2/stream_model/ephemeral_change.h"
#include "components/feed/core/v2/stream_model/feature_tree.h"
+#include "components/feed/core/v2/types.h"
namespace feedwire {
class DataOperation;
@@ -134,6 +135,9 @@ class StreamModel {
// Time the client received this stream data. 'NextPage' requests do not
// change this time.
base::Time GetLastAddedTime() const;
+ // Returns a set of content IDs contained. This remains constant even
+ // after data operations or next-page requests.
+ ContentIdSet GetContentIds() const;
// Outputs a string representing the model state for debugging or testing.
std::string DumpStateForTesting();
diff --git a/chromium/components/feed/core/v2/stream_model_unittest.cc b/chromium/components/feed/core/v2/stream_model_unittest.cc
index fa5765f8de5..50d49c75958 100644
--- a/chromium/components/feed/core/v2/stream_model_unittest.cc
+++ b/chromium/components/feed/core/v2/stream_model_unittest.cc
@@ -9,13 +9,13 @@
#include <utility>
#include <vector>
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/proto/v2/wire/content_id.pb.h"
#include "components/feed/core/v2/protocol_translator.h"
#include "components/feed/core/v2/test/stream_builder.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feed {
namespace {
@@ -41,15 +41,15 @@ class TestObserver : public StreamModel::Observer {
// StreamModel::Observer.
void OnUiUpdate(const UiUpdate& update) override { update_ = update; }
- const base::Optional<UiUpdate>& GetUiUpdate() const { return update_; }
+ const absl::optional<UiUpdate>& GetUiUpdate() const { return update_; }
bool ContentListChanged() const {
return update_ && update_->content_list_changed;
}
- void Clear() { update_ = base::nullopt; }
+ void Clear() { update_ = absl::nullopt; }
private:
- base::Optional<UiUpdate> update_;
+ absl::optional<UiUpdate> update_;
};
class TestStoreObserver : public StreamModel::StoreObserver {
@@ -63,12 +63,12 @@ class TestStoreObserver : public StreamModel::StoreObserver {
update_ = std::move(records);
}
- const base::Optional<StoreUpdate>& GetUpdate() const { return update_; }
+ const absl::optional<StoreUpdate>& GetUpdate() const { return update_; }
- void Clear() { update_ = base::nullopt; }
+ void Clear() { update_ = absl::nullopt; }
private:
- base::Optional<StoreUpdate> update_;
+ absl::optional<StoreUpdate> update_;
};
TEST(StreamModelTest, ConstructEmptyModel) {
diff --git a/chromium/components/feed/core/v2/surface_updater.cc b/chromium/components/feed/core/v2/surface_updater.cc
index 949a07fd925..bbd85b998ed 100644
--- a/chromium/components/feed/core/v2/surface_updater.cc
+++ b/chromium/components/feed/core/v2/surface_updater.cc
@@ -10,8 +10,10 @@
#include "base/check.h"
#include "base/strings/string_number_conversions.h"
#include "components/feed/core/proto/v2/xsurface.pb.h"
+#include "components/feed/core/v2/enums.h"
#include "components/feed/core/v2/feed_stream.h"
#include "components/feed/core/v2/metrics_reporter.h"
+#include "components/feed/core/v2/public/feed_stream_surface.h"
namespace feed {
namespace {
@@ -53,6 +55,11 @@ void AddSliceUpdate(const StreamModel& model,
const feedstore::Content* content = model.FindContent(content_revision);
DCHECK(content);
slice->mutable_xsurface_slice()->set_xsurface_frame(content->frame());
+ if (content->prefetch_metadata_size() > 0) {
+ auto metadata = content->prefetch_metadata(0);
+ slice->mutable_slice_metadata()->set_uri(metadata.uri());
+ slice->mutable_slice_metadata()->set_title(metadata.title());
+ }
} else {
stream_update->add_updated_slices()->set_slice_id(
ToString(content_revision));
@@ -159,6 +166,7 @@ feedui::ZeroStateSlice::Type GetZeroStateType(LoadStreamStatus status) {
case LoadStreamStatus::kDataInStoreIsExpired:
case LoadStreamStatus::kDataInStoreIsForAnotherUser:
case LoadStreamStatus::kAbortWithPendingClearAll:
+ case LoadStreamStatus::kAlreadyHaveUnreadContent:
break;
}
return feedui::ZeroStateSlice::NO_CARDS_AVAILABLE;
diff --git a/chromium/components/feed/core/v2/surface_updater.h b/chromium/components/feed/core/v2/surface_updater.h
index 7f0b359cef1..cc4e5dc6ccd 100644
--- a/chromium/components/feed/core/v2/surface_updater.h
+++ b/chromium/components/feed/core/v2/surface_updater.h
@@ -13,13 +13,13 @@
#include "base/observer_list.h"
#include "components/feed/core/proto/v2/ui.pb.h"
#include "components/feed/core/v2/enums.h"
-#include "components/feed/core/v2/public/feed_api.h"
#include "components/feed/core/v2/stream_model.h"
namespace feedui {
class StreamUpdate;
} // namespace feedui
namespace feed {
+class FeedStreamSurface;
class MetricsReporter;
// Keeps the UI up to date by calling |FeedStreamSurface::StreamUpdate()|.
diff --git a/chromium/components/feed/core/v2/tasks/get_prefetch_suggestions_task.cc b/chromium/components/feed/core/v2/tasks/get_prefetch_suggestions_task.cc
deleted file mode 100644
index 00ba9efa851..00000000000
--- a/chromium/components/feed/core/v2/tasks/get_prefetch_suggestions_task.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/feed/core/v2/tasks/get_prefetch_suggestions_task.h"
-
-#include <utility>
-
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/logging.h"
-#include "components/feed/core/proto/v2/wire/stream_structure.pb.h"
-#include "components/feed/core/v2/feed_store.h"
-#include "components/feed/core/v2/feed_stream.h"
-#include "components/feed/core/v2/stream_model.h"
-#include "components/feed/core/v2/tasks/load_stream_from_store_task.h"
-
-namespace feed {
-namespace {
-
-// Converts a URL string into a GURL. If the string is not a valid URL, returns
-// an empty GURL. Since GURL::spec() asserts on invalid URLs, this is necessary
-// to scrub the incoming data from the wire.
-GURL SpecToGURL(const std::string& url_string) {
- GURL url(url_string);
- if (!url.is_valid())
- url = GURL();
- return url;
-}
-
-offline_pages::PrefetchSuggestion ConvertToSuggestion(
- const feedwire::PrefetchMetadata& metadata) {
- offline_pages::PrefetchSuggestion result;
- result.article_url = SpecToGURL(metadata.uri());
- result.article_title = metadata.title();
- result.article_attribution = metadata.publisher();
- result.article_snippet = metadata.snippet();
- result.thumbnail_url = SpecToGURL(metadata.image_url());
- result.favicon_url = SpecToGURL(metadata.favicon_url());
- return result;
-}
-
-} // namespace
-
-GetPrefetchSuggestionsTask::GetPrefetchSuggestionsTask(
- FeedStream* stream,
- base::OnceCallback<void(std::vector<offline_pages::PrefetchSuggestion>)>
- result_callback)
- : stream_(stream), result_callback_(std::move(result_callback)) {}
-
-GetPrefetchSuggestionsTask::~GetPrefetchSuggestionsTask() = default;
-
-void GetPrefetchSuggestionsTask::Run() {
- if (stream_->ClearAllInProgress()) {
- // Abort and return an empty list.
- std::move(result_callback_).Run({});
- TaskComplete();
- return;
- }
-
- if (stream_->GetModel(kForYouStream)) {
- PullSuggestionsFromModel(*stream_->GetModel(kForYouStream));
- return;
- }
-
- load_from_store_task_ = std::make_unique<LoadStreamFromStoreTask>(
- LoadStreamFromStoreTask::LoadType::kFullLoad, kForYouStream,
- stream_->GetStore(),
- /*missed_last_refresh=*/false,
- base::BindOnce(&GetPrefetchSuggestionsTask::LoadStreamComplete,
- base::Unretained(this)));
-
- load_from_store_task_->Execute(base::DoNothing());
-}
-
-void GetPrefetchSuggestionsTask::LoadStreamComplete(
- LoadStreamFromStoreTask::Result result) {
- if (!result.update_request) {
- // Give up and return an empty list.
- std::move(result_callback_).Run({});
- TaskComplete();
- return;
- }
-
- // It is a bit dangerous to retain the model loaded here. The normal
- // LoadStreamTask flow has various considerations for metrics and signalling
- // surfaces to update. For this reason, we're not going to retain the loaded
- // model for use outside of this task.
- StreamModel model;
- model.Update(std::move(result.update_request));
- PullSuggestionsFromModel(model);
-}
-
-void GetPrefetchSuggestionsTask::PullSuggestionsFromModel(
- const StreamModel& model) {
- std::vector<offline_pages::PrefetchSuggestion> suggestions;
- for (ContentRevision rev : model.GetContentList()) {
- const feedstore::Content* content = model.FindContent(rev);
- if (!content)
- continue;
- for (const feedwire::PrefetchMetadata& metadata :
- content->prefetch_metadata()) {
- suggestions.push_back(ConvertToSuggestion(metadata));
- }
- }
-
- std::move(result_callback_).Run(std::move(suggestions));
- TaskComplete();
-}
-
-} // namespace feed
diff --git a/chromium/components/feed/core/v2/tasks/get_prefetch_suggestions_task.h b/chromium/components/feed/core/v2/tasks/get_prefetch_suggestions_task.h
deleted file mode 100644
index 1e4d3b65521..00000000000
--- a/chromium/components/feed/core/v2/tasks/get_prefetch_suggestions_task.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_FEED_CORE_V2_TASKS_GET_PREFETCH_SUGGESTIONS_TASK_H_
-#define COMPONENTS_FEED_CORE_V2_TASKS_GET_PREFETCH_SUGGESTIONS_TASK_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/memory/weak_ptr.h"
-#include "components/feed/core/v2/tasks/load_stream_from_store_task.h"
-#include "components/offline_pages/task/task.h"
-
-namespace offline_pages {
-struct PrefetchSuggestion;
-}
-
-namespace feed {
-class FeedStream;
-class StreamModel;
-
-// Get the list of prefetch suggestions.
-class GetPrefetchSuggestionsTask : public offline_pages::Task {
- public:
- explicit GetPrefetchSuggestionsTask(
- FeedStream* stream,
- base::OnceCallback<void(std::vector<offline_pages::PrefetchSuggestion>)>
- result_callback);
- ~GetPrefetchSuggestionsTask() override;
- GetPrefetchSuggestionsTask(const GetPrefetchSuggestionsTask&) = delete;
- GetPrefetchSuggestionsTask& operator=(const GetPrefetchSuggestionsTask&) =
- delete;
-
- private:
- base::WeakPtr<GetPrefetchSuggestionsTask> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
-
- // offline_pages::Task.
- void Run() override;
-
- void LoadStreamComplete(LoadStreamFromStoreTask::Result result);
-
- void PullSuggestionsFromModel(const StreamModel& model);
-
- FeedStream* stream_;
- base::OnceCallback<void(std::vector<offline_pages::PrefetchSuggestion>)>
- result_callback_;
-
- std::unique_ptr<LoadStreamFromStoreTask> load_from_store_task_;
-
- base::WeakPtrFactory<GetPrefetchSuggestionsTask> weak_ptr_factory_{this};
-};
-} // namespace feed
-
-#endif // COMPONENTS_FEED_CORE_V2_TASKS_GET_PREFETCH_SUGGESTIONS_TASK_H_
diff --git a/chromium/components/feed/core/v2/tasks/load_more_task.cc b/chromium/components/feed/core/v2/tasks/load_more_task.cc
index 64c1c77ba9f..0ac466c63ec 100644
--- a/chromium/components/feed/core/v2/tasks/load_more_task.cc
+++ b/chromium/components/feed/core/v2/tasks/load_more_task.cc
@@ -9,6 +9,7 @@
#include "base/callback_helpers.h"
#include "base/check.h"
+#include "base/feature_list.h"
#include "base/time/time.h"
#include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/proto/v2/wire/client_info.pb.h"
@@ -22,6 +23,7 @@
#include "components/feed/core/v2/stream_model.h"
#include "components/feed/core/v2/tasks/upload_actions_task.h"
#include "components/feed/core/v2/wire_response_translator.h"
+#include "components/feed/feed_feature_list.h"
namespace feed {
@@ -78,33 +80,55 @@ void LoadMoreTask::UploadActionsComplete(UploadActionsTask::Result result) {
// content determines the sign-in state of the subsequent load more requests.
// This avoids a possible situation where there would be a mix of signed-in
// and signed-out content, which we don't want.
- bool force_signed_out_request = !model->signed_in();
+ std::string gaia =
+ model->signed_in() ? stream_->GetSyncSignedInGaia() : std::string();
// Send network request.
fetch_start_time_ = base::TimeTicks::Now();
- // TODO(crbug/1152592): Send a different network request type for WebFeeds.
- stream_->GetNetwork()->SendQueryRequest(
- NetworkRequestType::kNextPage,
- CreateFeedQueryLoadMoreRequest(
- stream_->GetRequestMetadata(stream_type_, /*is_for_next_page=*/true),
- stream_->GetMetadata().consistency_token(),
- stream_->GetModel(stream_type_)->GetNextPageToken()),
- force_signed_out_request, stream_->GetSyncSignedInGaia(),
- base::BindOnce(&LoadMoreTask::QueryRequestComplete, GetWeakPtr()));
+
+ feedwire::Request request = CreateFeedQueryLoadMoreRequest(
+ stream_->GetRequestMetadata(stream_type_,
+ /*is_for_next_page=*/true),
+ stream_->GetMetadata().consistency_token(),
+ stream_->GetModel(stream_type_)->GetNextPageToken());
+
+ // TODO(crbug/1152592): Send a different network request type for
+ // WebFeeds.
+ if (base::FeatureList::IsEnabled(kDiscoFeedEndpoint)) {
+ stream_->GetNetwork()->SendApiRequest<QueryNextPageDiscoverApi>(
+ request, gaia,
+ base::BindOnce(&LoadMoreTask::QueryApiRequestComplete, GetWeakPtr()));
+ } else {
+ stream_->GetNetwork()->SendQueryRequest(
+ NetworkRequestType::kNextPage, request, gaia,
+ base::BindOnce(&LoadMoreTask::QueryRequestComplete, GetWeakPtr()));
+ }
+}
+
+void LoadMoreTask::QueryApiRequestComplete(
+ FeedNetwork::ApiResult<feedwire::Response> result) {
+ ProcessNetworkResponse(std::move(result.response_body),
+ std::move(result.response_info));
}
void LoadMoreTask::QueryRequestComplete(
FeedNetwork::QueryRequestResult result) {
+ ProcessNetworkResponse(std::move(result.response_body),
+ std::move(result.response_info));
+}
+
+void LoadMoreTask::ProcessNetworkResponse(
+ std::unique_ptr<feedwire::Response> response_body,
+ NetworkResponseInfo response_info) {
StreamModel* model = stream_->GetModel(stream_type_);
DCHECK(model) << "Model was unloaded outside of a Task";
- if (!result.response_body)
+ if (!response_body)
return Done(LoadStreamStatus::kNoResponseBody);
RefreshResponseData translated_response =
stream_->GetWireResponseTranslator()->TranslateWireResponse(
- *result.response_body,
- StreamModelUpdateRequest::Source::kNetworkLoadMore,
- result.response_info.was_signed_in, base::Time::Now());
+ *response_body, StreamModelUpdateRequest::Source::kNetworkLoadMore,
+ response_info.was_signed_in, base::Time::Now());
if (!translated_response.model_update_request)
return Done(LoadStreamStatus::kProtoTranslationFailed);
@@ -112,7 +136,7 @@ void LoadMoreTask::QueryRequestComplete(
result_.loaded_new_content_from_network =
!translated_response.model_update_request->stream_structures.empty();
- base::Optional<feedstore::Metadata> updated_metadata =
+ absl::optional<feedstore::Metadata> updated_metadata =
feedstore::MaybeUpdateSessionId(stream_->GetMetadata(),
translated_response.session_id);
if (updated_metadata) {
diff --git a/chromium/components/feed/core/v2/tasks/load_more_task.h b/chromium/components/feed/core/v2/tasks/load_more_task.h
index ce490315ff2..619bfb78208 100644
--- a/chromium/components/feed/core/v2/tasks/load_more_task.h
+++ b/chromium/components/feed/core/v2/tasks/load_more_task.h
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "components/feed/core/proto/v2/store.pb.h"
+#include "components/feed/core/proto/v2/wire/response.pb.h"
#include "components/feed/core/v2/enums.h"
#include "components/feed/core/v2/feed_network.h"
#include "components/feed/core/v2/scheduling.h"
@@ -38,7 +39,7 @@ class LoadMoreTask : public offline_pages::Task {
// Final status of loading the stream.
LoadStreamStatus final_status = LoadStreamStatus::kNoStatus;
bool loaded_new_content_from_network = false;
- base::Optional<RequestSchedule> request_schedule;
+ absl::optional<RequestSchedule> request_schedule;
std::unique_ptr<StreamModelUpdateRequest> model_update_request;
};
@@ -56,7 +57,11 @@ class LoadMoreTask : public offline_pages::Task {
}
void UploadActionsComplete(UploadActionsTask::Result result);
+ void QueryApiRequestComplete(
+ FeedNetwork::ApiResult<feedwire::Response> result);
void QueryRequestComplete(FeedNetwork::QueryRequestResult result);
+ void ProcessNetworkResponse(std::unique_ptr<feedwire::Response> response_body,
+ NetworkResponseInfo response_info);
void Done(LoadStreamStatus status);
StreamType stream_type_;
diff --git a/chromium/components/feed/core/v2/tasks/load_stream_from_store_task.cc b/chromium/components/feed/core/v2/tasks/load_stream_from_store_task.cc
index b5c9a458300..0d4a96304c3 100644
--- a/chromium/components/feed/core/v2/tasks/load_stream_from_store_task.cc
+++ b/chromium/components/feed/core/v2/tasks/load_stream_from_store_task.cc
@@ -29,11 +29,13 @@ LoadStreamFromStoreTask::Result& LoadStreamFromStoreTask::Result::operator=(
LoadStreamFromStoreTask::LoadStreamFromStoreTask(
LoadType load_type,
+ FeedStream* feed_stream,
const StreamType& stream_type,
FeedStore* store,
bool missed_last_refresh,
base::OnceCallback<void(Result)> callback)
: load_type_(load_type),
+ feed_stream_(feed_stream),
stream_type_(stream_type),
store_(store),
missed_last_refresh_(missed_last_refresh),
@@ -56,31 +58,35 @@ void LoadStreamFromStoreTask::LoadStreamDone(
}
pending_actions_ = std::move(result.pending_actions);
- if (load_type_ == LoadType::kPendingActionsOnly) {
- Complete(LoadStreamStatus::kLoadedFromStore);
- return;
- }
-
if (result.stream_structures.empty()) {
Complete(LoadStreamStatus::kNoStreamDataInStore);
return;
}
+ content_ids_ = feedstore::GetContentIds(result.stream_data);
if (!ignore_staleness_) {
- last_added_time_ = feedstore::GetLastAddedTime(result.stream_data);
- content_age_ = base::Time::Now() - last_added_time_;
+ content_age_ =
+ base::Time::Now() - feedstore::GetLastAddedTime(result.stream_data);
+
if (content_age_ > GetFeedConfig().content_expiration_threshold) {
Complete(LoadStreamStatus::kDataInStoreIsExpired);
return;
}
if (content_age_ < base::TimeDelta()) {
stale_reason_ = LoadStreamStatus::kDataInStoreIsStaleTimestampInFuture;
- } else if (ShouldWaitForNewContent(true, content_age_)) {
+ } else if (ShouldWaitForNewContent(feed_stream_->GetMetadata(),
+ result.stream_type, true,
+ content_age_)) {
stale_reason_ = LoadStreamStatus::kDataInStoreIsStale;
} else if (missed_last_refresh_) {
stale_reason_ = LoadStreamStatus::kDataInStoreStaleMissedLastRefresh;
}
}
+ if (load_type_ == LoadType::kLoadNoContent) {
+ Complete(LoadStreamStatus::kLoadedFromStore);
+ return;
+ }
+
std::vector<ContentId> referenced_content_ids;
for (const feedstore::StreamStructureSet& structure_set :
result.stream_structures) {
@@ -147,7 +153,7 @@ void LoadStreamFromStoreTask::Complete(LoadStreamStatus status) {
task_result.status = status;
}
task_result.content_age = content_age_;
- task_result.last_added_time = last_added_time_;
+ task_result.content_ids = content_ids_;
std::move(result_callback_).Run(std::move(task_result));
TaskComplete();
}
diff --git a/chromium/components/feed/core/v2/tasks/load_stream_from_store_task.h b/chromium/components/feed/core/v2/tasks/load_stream_from_store_task.h
index 96e35e0e79c..2385e5ebff9 100644
--- a/chromium/components/feed/core/v2/tasks/load_stream_from_store_task.h
+++ b/chromium/components/feed/core/v2/tasks/load_stream_from_store_task.h
@@ -6,16 +6,17 @@
#define COMPONENTS_FEED_CORE_V2_TASKS_LOAD_STREAM_FROM_STORE_TASK_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "components/feed/core/v2/enums.h"
#include "components/feed/core/v2/feed_store.h"
+#include "components/feed/core/v2/types.h"
#include "components/offline_pages/task/task.h"
namespace feed {
+class FeedStream;
struct StreamModelUpdateRequest;
// Attempts to load stream data from persistent storage.
@@ -29,25 +30,28 @@ class LoadStreamFromStoreTask : public offline_pages::Task {
LoadStreamStatus status = LoadStreamStatus::kNoStatus;
// Only provided if using |LoadType::kFullLoad| AND successful.
std::unique_ptr<StreamModelUpdateRequest> update_request;
- // This data is provided when |LoadType::kPendingActionsOnly|, or
- // when loading fails.
- std::string consistency_token;
+
+ // The fields below are provided for all `LoadType`s.
+
// Pending actions to be uploaded if the stream is to be loaded from the
// network.
std::vector<feedstore::StoredAction> pending_actions;
// How long since the loaded content was fetched from the server.
// May be zero if content is not loaded.
base::TimeDelta content_age;
- // Last time the stream was fetched from the network.
- base::Time last_added_time;
+ ContentIdSet content_ids;
};
+ // Determines what kind of data is loaded. See `Result` for what is loaded.
enum class LoadType {
+ // Load the full stream content.
kFullLoad = 0,
- kPendingActionsOnly = 1,
+ // Skips loading stream content.
+ kLoadNoContent = 1,
};
LoadStreamFromStoreTask(LoadType load_type,
+ FeedStream* feed_stream,
const StreamType& stream_type,
FeedStore* store,
bool missed_last_refresh,
@@ -72,6 +76,7 @@ class LoadStreamFromStoreTask : public offline_pages::Task {
LoadStreamStatus stale_reason_ = LoadStreamStatus::kNoStatus;
LoadType load_type_;
+ FeedStream* feed_stream_;
StreamType stream_type_;
FeedStore* store_; // Unowned.
bool ignore_staleness_ = false;
@@ -82,7 +87,7 @@ class LoadStreamFromStoreTask : public offline_pages::Task {
std::unique_ptr<StreamModelUpdateRequest> update_request_;
std::vector<feedstore::StoredAction> pending_actions_;
base::TimeDelta content_age_;
- base::Time last_added_time_;
+ ContentIdSet content_ids_;
base::WeakPtrFactory<LoadStreamFromStoreTask> weak_ptr_factory_{this};
};
diff --git a/chromium/components/feed/core/v2/tasks/load_stream_task.cc b/chromium/components/feed/core/v2/tasks/load_stream_task.cc
index 6ea7b37415e..87b51ad3a60 100644
--- a/chromium/components/feed/core/v2/tasks/load_stream_task.cc
+++ b/chromium/components/feed/core/v2/tasks/load_stream_task.cc
@@ -9,32 +9,42 @@
#include "base/callback_helpers.h"
#include "base/check.h"
+#include "base/feature_list.h"
#include "base/time/time.h"
#include "components/feed/core/proto/v2/wire/capability.pb.h"
#include "components/feed/core/proto/v2/wire/client_info.pb.h"
+#include "components/feed/core/proto/v2/wire/feed_query.pb.h"
#include "components/feed/core/proto/v2/wire/feed_request.pb.h"
#include "components/feed/core/proto/v2/wire/request.pb.h"
+#include "components/feed/core/v2/config.h"
#include "components/feed/core/v2/feed_network.h"
#include "components/feed/core/v2/feed_stream.h"
#include "components/feed/core/v2/feedstore_util.h"
#include "components/feed/core/v2/metrics_reporter.h"
#include "components/feed/core/v2/proto_util.h"
#include "components/feed/core/v2/protocol_translator.h"
-#include "components/feed/core/v2/public/feed_api.h"
#include "components/feed/core/v2/stream_model.h"
#include "components/feed/core/v2/tasks/upload_actions_task.h"
+#include "components/feed/feed_feature_list.h"
namespace feed {
namespace {
using LoadType = LoadStreamTask::LoadType;
using Result = LoadStreamTask::Result;
-feedwire::FeedQuery::RequestReason GetRequestReason(LoadType load_type) {
+feedwire::FeedQuery::RequestReason GetRequestReason(
+ const StreamType& stream_type,
+ LoadType load_type) {
switch (load_type) {
case LoadType::kInitialLoad:
- return feedwire::FeedQuery::MANUAL_REFRESH;
+ return stream_type.IsForYou() ? feedwire::FeedQuery::MANUAL_REFRESH
+ : feedwire::FeedQuery::INTERACTIVE_WEB_FEED;
case LoadType::kBackgroundRefresh:
- return feedwire::FeedQuery::SCHEDULED_REFRESH;
+ return stream_type.IsForYou()
+ ? feedwire::FeedQuery::SCHEDULED_REFRESH
+ // TODO(b/185848601): Switch back to PREFETCHED_WEB_FEED when
+ // the server supports it.
+ : feedwire::FeedQuery::INTERACTIVE_WEB_FEED;
}
}
@@ -47,14 +57,13 @@ Result::~Result() = default;
Result::Result(Result&&) = default;
Result& Result::operator=(Result&&) = default;
-LoadStreamTask::LoadStreamTask(LoadType load_type,
- const StreamType& stream_type,
+LoadStreamTask::LoadStreamTask(const Options& options,
FeedStream* stream,
base::OnceCallback<void(Result)> done_callback)
- : load_type_(load_type),
- stream_type_(stream_type),
+ : options_(options),
stream_(stream),
done_callback_(std::move(done_callback)) {
+ DCHECK(options.stream_type.IsValid()) << "A stream type must be chosen";
latencies_ = std::make_unique<LoadLatencyTimes>();
}
@@ -73,21 +82,27 @@ void LoadStreamTask::Run() {
// First, ensure we still should load the model.
LoadStreamStatus should_not_attempt_reason =
- stream_->ShouldAttemptLoad(stream_type_,
+ stream_->ShouldAttemptLoad(options_.stream_type,
/*model_loading=*/true);
if (should_not_attempt_reason != LoadStreamStatus::kNoStatus) {
return Done(should_not_attempt_reason);
}
- // Use |kConsistencyTokenOnly| to short-circuit loading from store if we don't
+ if (options_.abort_if_unread_content &&
+ stream_->HasUnreadContent(options_.stream_type)) {
+ Done(LoadStreamStatus::kAlreadyHaveUnreadContent);
+ return;
+ }
+
+ // Use |kLoadNoContent| to short-circuit loading from store if we don't
// need the full stream state.
auto load_from_store_type =
- (load_type_ == LoadType::kInitialLoad)
+ (options_.load_type == LoadType::kInitialLoad)
? LoadStreamFromStoreTask::LoadType::kFullLoad
- : LoadStreamFromStoreTask::LoadType::kPendingActionsOnly;
+ : LoadStreamFromStoreTask::LoadType::kLoadNoContent;
load_from_store_task_ = std::make_unique<LoadStreamFromStoreTask>(
- load_from_store_type, stream_type_, stream_->GetStore(),
- stream_->MissedLastRefresh(stream_type_),
+ load_from_store_type, stream_, options_.stream_type, stream_->GetStore(),
+ stream_->MissedLastRefresh(options_.stream_type),
base::BindOnce(&LoadStreamTask::LoadFromStoreComplete, GetWeakPtr()));
load_from_store_task_->Execute(base::DoNothing());
}
@@ -97,31 +112,30 @@ void LoadStreamTask::LoadFromStoreComplete(
load_from_store_status_ = result.status;
latencies_->StepComplete(LoadLatencyTimes::kLoadFromStore);
stored_content_age_ = result.content_age;
- last_added_time_ = result.last_added_time;
+ content_ids_ = result.content_ids;
- // Phase 2.
- // - If loading from store works, update the model.
- // - Otherwise, try to load from the network.
+ // Phase 2. Process the result of `LoadStreamFromStoreTask`.
- if (load_type_ == LoadType::kInitialLoad &&
+ if (!options_.refresh_even_when_not_stale &&
result.status == LoadStreamStatus::kLoadedFromStore) {
update_request_ = std::move(result.update_request);
Done(LoadStreamStatus::kLoadedFromStore);
return;
}
- // If data in store is stale, we'll continue with a network request, but keep
- // the stale model data in case we fail to load a fresh feed.
- if (load_type_ == LoadType::kInitialLoad &&
+ const bool store_is_stale =
(result.status == LoadStreamStatus::kDataInStoreStaleMissedLastRefresh ||
result.status == LoadStreamStatus::kDataInStoreIsStale ||
- result.status ==
- LoadStreamStatus::kDataInStoreIsStaleTimestampInFuture)) {
+ result.status == LoadStreamStatus::kDataInStoreIsStaleTimestampInFuture);
+
+ // If data in store is stale, we'll continue with a network request, but keep
+ // the stale model data in case we fail to load a fresh feed.
+ if (options_.load_type == LoadType::kInitialLoad && store_is_stale) {
stale_store_state_ = std::move(result.update_request);
}
LoadStreamStatus final_status =
- stream_->ShouldMakeFeedQueryRequest(stream_type_);
+ stream_->ShouldMakeFeedQueryRequest(options_.stream_type);
if (final_status != LoadStreamStatus::kNoStatus) {
Done(final_status);
return;
@@ -136,34 +150,78 @@ void LoadStreamTask::LoadFromStoreComplete(
void LoadStreamTask::UploadActionsComplete(UploadActionsTask::Result result) {
bool force_signed_out_request =
- stream_->ShouldForceSignedOutFeedQueryRequest(stream_type_);
+ stream_->ShouldForceSignedOutFeedQueryRequest(options_.stream_type);
upload_actions_result_ =
std::make_unique<UploadActionsTask::Result>(std::move(result));
latencies_->StepComplete(LoadLatencyTimes::kUploadActions);
- // TODO(crbug/1152592): Send a different network request type for WebFeeds.
- stream_->GetNetwork()->SendQueryRequest(
- NetworkRequestType::kFeedQuery,
- CreateFeedQueryRefreshRequest(
- GetRequestReason(load_type_),
- stream_->GetRequestMetadata(stream_type_, /*is_for_next_page=*/false),
- stream_->GetMetadata().consistency_token()),
- force_signed_out_request, stream_->GetSyncSignedInGaia(),
- base::BindOnce(&LoadStreamTask::QueryRequestComplete, GetWeakPtr()));
+
+ feedwire::Request request = CreateFeedQueryRefreshRequest(
+ options_.stream_type,
+ GetRequestReason(options_.stream_type, options_.load_type),
+ stream_->GetRequestMetadata(options_.stream_type,
+ /*is_for_next_page=*/false),
+ stream_->GetMetadata().consistency_token());
+
+ const std::string gaia =
+ force_signed_out_request ? std::string() : stream_->GetSyncSignedInGaia();
+
+ if (options_.stream_type.IsForYou() ||
+ GetFeedConfig().use_feed_query_requests_for_web_feeds) {
+ if (base::FeatureList::IsEnabled(kDiscoFeedEndpoint)) {
+ switch (options_.load_type) {
+ case LoadType::kInitialLoad:
+ stream_->GetNetwork()
+ ->SendApiRequest<QueryInteractiveFeedDiscoverApi>(
+ request, gaia,
+ base::BindOnce(&LoadStreamTask::QueryApiRequestComplete,
+ GetWeakPtr()));
+ break;
+ case LoadType::kBackgroundRefresh:
+ stream_->GetNetwork()->SendApiRequest<QueryBackgroundFeedDiscoverApi>(
+ request, gaia,
+ base::BindOnce(&LoadStreamTask::QueryApiRequestComplete,
+ GetWeakPtr()));
+ break;
+ }
+ } else {
+ stream_->GetNetwork()->SendQueryRequest(
+ NetworkRequestType::kFeedQuery, request, gaia,
+ base::BindOnce(&LoadStreamTask::QueryRequestComplete, GetWeakPtr()));
+ }
+ } else {
+ DCHECK(options_.stream_type.IsWebFeed());
+ stream_->GetNetwork()->SendApiRequest<WebFeedListContentsDiscoverApi>(
+ std::move(request), gaia,
+ base::BindOnce(&LoadStreamTask::QueryApiRequestComplete, GetWeakPtr()));
+ }
}
void LoadStreamTask::QueryRequestComplete(
FeedNetwork::QueryRequestResult result) {
+ ProcessNetworkResponse(std::move(result.response_body),
+ std::move(result.response_info));
+}
+
+void LoadStreamTask::QueryApiRequestComplete(
+ FeedNetwork::ApiResult<feedwire::Response> result) {
+ ProcessNetworkResponse(std::move(result.response_body),
+ std::move(result.response_info));
+}
+
+void LoadStreamTask::ProcessNetworkResponse(
+ std::unique_ptr<feedwire::Response> response_body,
+ NetworkResponseInfo response_info) {
latencies_->StepComplete(LoadLatencyTimes::kQueryRequest);
- DCHECK(!stream_->GetModel(stream_type_));
+ DCHECK(!stream_->GetModel(options_.stream_type));
- network_response_info_ = result.response_info;
+ network_response_info_ = response_info;
- if (result.response_info.status_code != 200)
+ if (response_info.status_code != 200)
return Done(LoadStreamStatus::kNetworkFetchFailed);
- if (!result.response_body) {
- if (result.response_info.response_body_bytes > 0)
+ if (!response_body) {
+ if (response_info.response_body_bytes > 0)
return Done(LoadStreamStatus::kCannotParseNetworkResponseBody);
else
return Done(LoadStreamStatus::kNoResponseBody);
@@ -171,18 +229,17 @@ void LoadStreamTask::QueryRequestComplete(
RefreshResponseData response_data =
stream_->GetWireResponseTranslator()->TranslateWireResponse(
- *result.response_body,
- StreamModelUpdateRequest::Source::kNetworkUpdate,
- result.response_info.was_signed_in, base::Time::Now());
+ *response_body, StreamModelUpdateRequest::Source::kNetworkUpdate,
+ response_info.was_signed_in, base::Time::Now());
if (!response_data.model_update_request)
return Done(LoadStreamStatus::kProtoTranslationFailed);
loaded_new_content_from_network_ = true;
- last_added_time_ = feedstore::GetLastAddedTime(
- response_data.model_update_request->stream_data);
+ content_ids_ =
+ feedstore::GetContentIds(response_data.model_update_request->stream_data);
stream_->GetStore()->OverwriteStream(
- stream_type_,
+ options_.stream_type,
std::make_unique<StreamModelUpdateRequest>(
*response_data.model_update_request),
base::DoNothing());
@@ -193,7 +250,7 @@ void LoadStreamTask::QueryRequestComplete(
MetricsReporter::NoticeCardFulfilled(*fetched_content_has_notice_card_);
- base::Optional<feedstore::Metadata> updated_metadata =
+ absl::optional<feedstore::Metadata> updated_metadata =
feedstore::MaybeUpdateSessionId(stream_->GetMetadata(),
response_data.session_id);
if (updated_metadata) {
@@ -202,7 +259,7 @@ void LoadStreamTask::QueryRequestComplete(
if (response_data.experiments)
experiments_ = *response_data.experiments;
- if (load_type_ != LoadType::kBackgroundRefresh) {
+ if (options_.load_type != LoadType::kBackgroundRefresh) {
update_request_ = std::move(response_data.model_update_request);
}
@@ -219,12 +276,12 @@ void LoadStreamTask::Done(LoadStreamStatus status) {
status = LoadStreamStatus::kLoadedStaleDataFromStoreDueToNetworkFailure;
}
Result result;
- result.stream_type = stream_type_;
+ result.stream_type = options_.stream_type;
result.load_from_store_status = load_from_store_status_;
result.stored_content_age = stored_content_age_;
- result.last_added_time = last_added_time_;
+ result.content_ids = content_ids_;
result.final_status = status;
- result.load_type = load_type_;
+ result.load_type = options_.load_type;
result.update_request = std::move(update_request_);
result.request_schedule = std::move(request_schedule_);
result.network_response_info = network_response_info_;
@@ -237,4 +294,18 @@ void LoadStreamTask::Done(LoadStreamStatus status) {
TaskComplete();
}
+std::ostream& operator<<(std::ostream& os,
+ const LoadStreamTask::Result& result) {
+ os << "LoadStreamTask::Result{" << result.stream_type
+ << " final_status=" << result.final_status
+ << " load_from_store_status=" << result.load_from_store_status
+ << " stored_content_age=" << result.stored_content_age
+ << " load_type=" << static_cast<int>(result.load_type)
+ << " request_schedule?=" << result.request_schedule.has_value();
+ if (result.network_response_info)
+ os << " network_response_info=" << *result.network_response_info;
+ return os << " loaded_new_content_from_network="
+ << result.loaded_new_content_from_network << "}";
+}
+
} // namespace feed
diff --git a/chromium/components/feed/core/v2/tasks/load_stream_task.h b/chromium/components/feed/core/v2/tasks/load_stream_task.h
index 5e6c0854b6b..fbe6237a900 100644
--- a/chromium/components/feed/core/v2/tasks/load_stream_task.h
+++ b/chromium/components/feed/core/v2/tasks/load_stream_task.h
@@ -9,15 +9,17 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
+#include "components/feed/core/proto/v2/wire/response.pb.h"
#include "components/feed/core/v2/enums.h"
#include "components/feed/core/v2/feed_network.h"
+#include "components/feed/core/v2/public/stream_type.h"
#include "components/feed/core/v2/public/types.h"
#include "components/feed/core/v2/scheduling.h"
#include "components/feed/core/v2/tasks/load_stream_from_store_task.h"
#include "components/feed/core/v2/tasks/upload_actions_task.h"
#include "components/offline_pages/task/task.h"
#include "components/version_info/channel.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feed {
class FeedStream;
@@ -37,6 +39,15 @@ class LoadStreamTask : public offline_pages::Task {
kBackgroundRefresh,
};
+ struct Options {
+ // The stream type to load.
+ StreamType stream_type;
+ LoadType load_type = LoadType::kInitialLoad;
+ // Abort the background refresh if there's already unread content.
+ bool abort_if_unread_content = false;
+ bool refresh_even_when_not_stale = false;
+ };
+
struct Result {
Result();
Result(const StreamType& stream_type, LoadStreamStatus status);
@@ -51,18 +62,17 @@ class LoadStreamTask : public offline_pages::Task {
LoadStreamStatus load_from_store_status = LoadStreamStatus::kNoStatus;
// Age of content loaded from local storage. Zero if none was loaded.
base::TimeDelta stored_content_age;
- // Last time the stream was fetched from the network. This may be either
- // a previous fetch time, or the one triggered by `LoadStreamTask`.
- base::Time last_added_time;
+ // Set of content IDs present in the feed.
+ ContentIdSet content_ids;
LoadType load_type;
std::unique_ptr<StreamModelUpdateRequest> update_request;
- base::Optional<RequestSchedule> request_schedule;
+ absl::optional<RequestSchedule> request_schedule;
// Information about the network request, if one was made.
- base::Optional<NetworkResponseInfo> network_response_info;
+ absl::optional<NetworkResponseInfo> network_response_info;
bool loaded_new_content_from_network = false;
std::unique_ptr<LoadLatencyTimes> latencies;
- base::Optional<bool> fetched_content_has_notice_card;
+ absl::optional<bool> fetched_content_has_notice_card;
// Result of the upload actions task.
std::unique_ptr<UploadActionsTask::Result> upload_actions_result;
@@ -71,8 +81,7 @@ class LoadStreamTask : public offline_pages::Task {
Experiments experiments;
};
- LoadStreamTask(LoadType load_type,
- const StreamType& stream_type,
+ LoadStreamTask(const Options& options,
FeedStream* stream,
base::OnceCallback<void(Result)> done_callback);
~LoadStreamTask() override;
@@ -87,24 +96,27 @@ class LoadStreamTask : public offline_pages::Task {
void LoadFromStoreComplete(LoadStreamFromStoreTask::Result result);
void UploadActionsComplete(UploadActionsTask::Result result);
+ void QueryApiRequestComplete(
+ FeedNetwork::ApiResult<feedwire::Response> result);
void QueryRequestComplete(FeedNetwork::QueryRequestResult result);
+ void ProcessNetworkResponse(std::unique_ptr<feedwire::Response> response,
+ NetworkResponseInfo response_info);
void Done(LoadStreamStatus status);
- LoadType load_type_;
- StreamType stream_type_;
+ Options options_;
FeedStream* stream_; // Unowned.
std::unique_ptr<LoadStreamFromStoreTask> load_from_store_task_;
std::unique_ptr<StreamModelUpdateRequest> stale_store_state_;
// Information to be stuffed in |Result|.
LoadStreamStatus load_from_store_status_ = LoadStreamStatus::kNoStatus;
- base::Optional<NetworkResponseInfo> network_response_info_;
+ absl::optional<NetworkResponseInfo> network_response_info_;
bool loaded_new_content_from_network_ = false;
base::TimeDelta stored_content_age_;
- base::Time last_added_time_;
+ ContentIdSet content_ids_;
Experiments experiments_;
std::unique_ptr<StreamModelUpdateRequest> update_request_;
- base::Optional<RequestSchedule> request_schedule_;
+ absl::optional<RequestSchedule> request_schedule_;
std::unique_ptr<LoadLatencyTimes> latencies_;
base::TimeTicks task_creation_time_;
@@ -112,9 +124,11 @@ class LoadStreamTask : public offline_pages::Task {
base::OnceCallback<void(Result)> done_callback_;
std::unique_ptr<UploadActionsTask> upload_actions_task_;
std::unique_ptr<UploadActionsTask::Result> upload_actions_result_;
- base::Optional<bool> fetched_content_has_notice_card_;
+ absl::optional<bool> fetched_content_has_notice_card_;
base::WeakPtrFactory<LoadStreamTask> weak_ptr_factory_{this};
};
+
+std::ostream& operator<<(std::ostream& os, const LoadStreamTask::Result&);
} // namespace feed
#endif // COMPONENTS_FEED_CORE_V2_TASKS_LOAD_STREAM_TASK_H_
diff --git a/chromium/components/feed/core/v2/tasks/prefetch_images_task.cc b/chromium/components/feed/core/v2/tasks/prefetch_images_task.cc
index fe0433287f5..15113483115 100644
--- a/chromium/components/feed/core/v2/tasks/prefetch_images_task.cc
+++ b/chromium/components/feed/core/v2/tasks/prefetch_images_task.cc
@@ -51,7 +51,7 @@ void PrefetchImagesTask::Run() {
}
load_from_store_task_ = std::make_unique<LoadStreamFromStoreTask>(
- LoadStreamFromStoreTask::LoadType::kFullLoad, kForYouStream,
+ LoadStreamFromStoreTask::LoadType::kFullLoad, stream_, kForYouStream,
stream_->GetStore(),
/*missed_last_refresh=*/false,
base::BindOnce(&PrefetchImagesTask::LoadStreamComplete,
diff --git a/chromium/components/feed/core/v2/tasks/upload_actions_task.h b/chromium/components/feed/core/v2/tasks/upload_actions_task.h
index e7aa5a76d9b..05443ce7c3d 100644
--- a/chromium/components/feed/core/v2/tasks/upload_actions_task.h
+++ b/chromium/components/feed/core/v2/tasks/upload_actions_task.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/proto/v2/wire/feed_action.pb.h"
#include "components/feed/core/proto/v2/wire/upload_actions_request.pb.h"
@@ -19,6 +18,7 @@
#include "components/feed/core/v2/feed_store.h"
#include "components/feed/core/v2/types.h"
#include "components/offline_pages/task/task.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feed {
class FeedStream;
@@ -51,7 +51,7 @@ class UploadActionsTask : public offline_pages::Task {
// staleness.
size_t stale_count;
// Information about the last network request, if one was attempted.
- base::Optional<NetworkResponseInfo> last_network_response_info;
+ absl::optional<NetworkResponseInfo> last_network_response_info;
};
// Store an action. Use |upload_now|=true to kick off an upload of all pending
@@ -100,7 +100,7 @@ class UploadActionsTask : public offline_pages::Task {
bool upload_now_ = false;
bool read_pending_actions_ = false;
// Pending action to be stored.
- base::Optional<feedwire::FeedAction> wire_action_;
+ absl::optional<feedwire::FeedAction> wire_action_;
// Pending actions to be uploaded, set either by the constructor or by
// OnReadPendingActionsFinished(). Not set if we're just storing an action.
@@ -115,7 +115,7 @@ class UploadActionsTask : public offline_pages::Task {
size_t upload_attempt_count_ = 0;
// Number of stale actions.
size_t stale_count_ = 0;
- base::Optional<NetworkResponseInfo> last_network_response_info_;
+ absl::optional<NetworkResponseInfo> last_network_response_info_;
std::string gaia_;
diff --git a/chromium/components/feed/core/v2/tasks/wait_for_store_initialize_task.cc b/chromium/components/feed/core/v2/tasks/wait_for_store_initialize_task.cc
index 37b7639c43a..c687924f8b4 100644
--- a/chromium/components/feed/core/v2/tasks/wait_for_store_initialize_task.cc
+++ b/chromium/components/feed/core/v2/tasks/wait_for_store_initialize_task.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "components/feed/core/v2/tasks/wait_for_store_initialize_task.h"
+#include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/v2/feed_store.h"
#include "components/feed/core/v2/feed_stream.h"
@@ -22,47 +23,54 @@ void WaitForStoreInitializeTask::Run() {
}
void WaitForStoreInitializeTask::OnStoreInitialized() {
- store_->ReadMetadata(base::BindOnce(
- &WaitForStoreInitializeTask::OnMetadataLoaded, base::Unretained(this)));
+ store_->ReadStartupData(
+ base::BindOnce(&WaitForStoreInitializeTask::ReadStartupDataDone,
+ base::Unretained(this)));
store_->ReadWebFeedStartupData(
base::BindOnce(&WaitForStoreInitializeTask::WebFeedStartupDataDone,
base::Unretained(this)));
}
-void WaitForStoreInitializeTask::OnMetadataLoaded(
- std::unique_ptr<feedstore::Metadata> metadata) {
- if (metadata && metadata->gaia() != stream_->GetSyncSignedInGaia()) {
+void WaitForStoreInitializeTask::ReadStartupDataDone(
+ FeedStore::StartupData startup_data) {
+ if (startup_data.metadata &&
+ startup_data.metadata->gaia() != stream_->GetSyncSignedInGaia()) {
store_->ClearAll(base::BindOnce(&WaitForStoreInitializeTask::ClearAllDone,
base::Unretained(this)));
return;
}
- MaybeUpgradeStreamSchema(std::move(metadata));
+ result_.startup_data = std::move(startup_data);
+ MaybeUpgradeStreamSchema();
}
void WaitForStoreInitializeTask::ClearAllDone(bool clear_ok) {
DLOG_IF(ERROR, !clear_ok) << "FeedStore::ClearAll failed";
// ClearAll just wiped metadata, so send nullptr.
- MaybeUpgradeStreamSchema(nullptr);
+ MaybeUpgradeStreamSchema();
}
-void WaitForStoreInitializeTask::MaybeUpgradeStreamSchema(
- std::unique_ptr<feedstore::Metadata> metadata) {
- if (!metadata || metadata->stream_schema_version() != 1) {
- if (!metadata) {
- metadata = std::make_unique<feedstore::Metadata>();
- metadata->set_gaia(stream_->GetSyncSignedInGaia());
+void WaitForStoreInitializeTask::MaybeUpgradeStreamSchema() {
+ feedstore::Metadata metadata;
+ if (result_.startup_data.metadata)
+ metadata = *result_.startup_data.metadata;
+
+ if (metadata.stream_schema_version() != 1) {
+ result_.startup_data.stream_data.clear();
+ if (metadata.gaia().empty()) {
+ metadata.set_gaia(stream_->GetSyncSignedInGaia());
}
store_->UpgradeFromStreamSchemaV0(
- std::move(*metadata),
- base::BindOnce(&WaitForStoreInitializeTask::MetadataDone,
+ std::move(metadata),
+ base::BindOnce(&WaitForStoreInitializeTask::UpgradeDone,
base::Unretained(this)));
return;
}
- MetadataDone(std::move(*metadata));
+ Done();
}
-void WaitForStoreInitializeTask::MetadataDone(feedstore::Metadata metadata) {
- result_.metadata = std::move(metadata);
+void WaitForStoreInitializeTask::UpgradeDone(feedstore::Metadata metadata) {
+ result_.startup_data.metadata =
+ std::make_unique<feedstore::Metadata>(std::move(metadata));
Done();
}
diff --git a/chromium/components/feed/core/v2/tasks/wait_for_store_initialize_task.h b/chromium/components/feed/core/v2/tasks/wait_for_store_initialize_task.h
index 4be97ec3edb..73c06440127 100644
--- a/chromium/components/feed/core/v2/tasks/wait_for_store_initialize_task.h
+++ b/chromium/components/feed/core/v2/tasks/wait_for_store_initialize_task.h
@@ -18,7 +18,7 @@ class FeedStream;
class WaitForStoreInitializeTask : public offline_pages::Task {
public:
struct Result {
- feedstore::Metadata metadata;
+ FeedStore::StartupData startup_data;
FeedStore::WebFeedStartupData web_feed_startup_data;
};
@@ -38,8 +38,9 @@ class WaitForStoreInitializeTask : public offline_pages::Task {
void OnMetadataLoaded(std::unique_ptr<feedstore::Metadata> metadata);
void ClearAllDone(bool clear_ok);
- void MaybeUpgradeStreamSchema(std::unique_ptr<feedstore::Metadata> metadata);
- void MetadataDone(feedstore::Metadata metadata);
+ void MaybeUpgradeStreamSchema();
+ void UpgradeDone(feedstore::Metadata metadata);
+ void ReadStartupDataDone(FeedStore::StartupData startup_data);
void WebFeedStartupDataDone(FeedStore::WebFeedStartupData data);
void Done();
diff --git a/chromium/components/feed/core/v2/types.cc b/chromium/components/feed/core/v2/types.cc
index 23e54bfd4f5..639100ed2b0 100644
--- a/chromium/components/feed/core/v2/types.cc
+++ b/chromium/components/feed/core/v2/types.cc
@@ -50,7 +50,7 @@ bool UnpickleNetworkResponseInfo(base::PickleIterator& iterator,
}
void PickleOptionalNetworkResponseInfo(
- const base::Optional<NetworkResponseInfo>& value,
+ const absl::optional<NetworkResponseInfo>& value,
base::Pickle& pickle) {
if (value.has_value()) {
pickle.WriteBool(true);
@@ -62,7 +62,7 @@ void PickleOptionalNetworkResponseInfo(
bool UnpickleOptionalNetworkResponseInfo(
base::PickleIterator& iterator,
- base::Optional<NetworkResponseInfo>& value) {
+ absl::optional<NetworkResponseInfo>& value) {
bool has_network_response_info = false;
if (!iterator.ReadBool(&has_network_response_info))
return false;
@@ -134,15 +134,15 @@ std::string SerializeDebugStreamData(const DebugStreamData& data) {
base::span<const uint8_t>(pickle_data_ptr, pickle.size()));
}
-base::Optional<DebugStreamData> DeserializeDebugStreamData(
+absl::optional<DebugStreamData> DeserializeDebugStreamData(
base::StringPiece base64_encoded) {
std::string binary_data;
if (!base::Base64Decode(base64_encoded, &binary_data))
- return base::nullopt;
+ return absl::nullopt;
base::Pickle pickle(binary_data.data(), binary_data.size());
DebugStreamData result;
if (!UnpickleDebugStreamData(base::PickleIterator(pickle), result))
- return base::nullopt;
+ return absl::nullopt;
return result;
}
@@ -163,12 +163,12 @@ PersistentMetricsData PersistentMetricsDataFromValue(const base::Value& value) {
PersistentMetricsData result;
if (!value.is_dict())
return result;
- base::Optional<base::Time> day_start =
+ absl::optional<base::Time> day_start =
util::ValueToTime(value.FindKey("day_start"));
if (!day_start)
return result;
result.current_day_start = *day_start;
- base::Optional<base::TimeDelta> time_spent_in_feed =
+ absl::optional<base::TimeDelta> time_spent_in_feed =
util::ValueToTimeDelta(value.FindKey("time_spent_in_feed"));
if (time_spent_in_feed) {
result.accumulated_time_spent_in_feed = *time_spent_in_feed;
@@ -185,4 +185,26 @@ void LoadLatencyTimes::StepComplete(StepKind kind) {
last_time_ = now;
}
+ContentIdSet::ContentIdSet() = default;
+ContentIdSet::~ContentIdSet() = default;
+ContentIdSet::ContentIdSet(base::flat_set<int64_t> content_ids)
+ : content_ids_(std::move(content_ids)) {}
+ContentIdSet::ContentIdSet(const ContentIdSet&) = default;
+ContentIdSet::ContentIdSet(ContentIdSet&&) = default;
+ContentIdSet& ContentIdSet::operator=(const ContentIdSet&) = default;
+ContentIdSet& ContentIdSet::operator=(ContentIdSet&&) = default;
+bool ContentIdSet::ContainsAllOf(const ContentIdSet& items) const {
+ for (int64_t id : items.content_ids_) {
+ if (!content_ids_.contains(id))
+ return false;
+ }
+ return true;
+}
+bool ContentIdSet::IsEmpty() const {
+ return content_ids_.empty();
+}
+bool ContentIdSet::operator==(const ContentIdSet& rhs) const {
+ return content_ids_ == rhs.content_ids_;
+}
+
} // namespace feed
diff --git a/chromium/components/feed/core/v2/types.h b/chromium/components/feed/core/v2/types.h
index 61ab5d94a38..303eb243962 100644
--- a/chromium/components/feed/core/v2/types.h
+++ b/chromium/components/feed/core/v2/types.h
@@ -5,8 +5,10 @@
#ifndef COMPONENTS_FEED_CORE_V2_TYPES_H_
#define COMPONENTS_FEED_CORE_V2_TYPES_H_
+#include <cstdint>
#include <string>
+#include "base/containers/flat_set.h"
#include "base/time/time.h"
#include "base/util/type_safety/id_type.h"
#include "base/values.h"
@@ -45,6 +47,7 @@ struct RequestMetadata {
std::string session_id;
DisplayMetrics display_metrics;
bool notice_card_acknowledged = false;
+ bool autoplay_enabled = false;
};
// Data internal to MetricsReporter which is persisted to Prefs.
@@ -68,7 +71,7 @@ class LoadLatencyTimes {
// Time spent querying for and uploading stored actions. Recorded even if
// no actions are uploaded.
kUploadActions,
- // Time spent making the FeedQuery request.
+ // Time spent making the FeedQuery (or WebFeed List Contents) request.
kQueryRequest,
// A view was reported in the stream, indicating the stream was shown.
kStreamViewed,
@@ -92,6 +95,31 @@ class LoadLatencyTimes {
std::vector<Step> steps_;
};
+// Tracks a set of `feedstore::Content` content IDs, for tracking whether unread
+// content is received from the server.
+class ContentIdSet {
+ public:
+ ContentIdSet();
+ ~ContentIdSet();
+ explicit ContentIdSet(base::flat_set<int64_t> ids);
+ ContentIdSet(const ContentIdSet&);
+ ContentIdSet(ContentIdSet&&);
+ ContentIdSet& operator=(const ContentIdSet&);
+ ContentIdSet& operator=(ContentIdSet&&);
+
+ // Returns whether this set contains all items.
+ bool ContainsAllOf(const ContentIdSet& items) const;
+ bool IsEmpty() const;
+ const base::flat_set<int64_t>& values() const { return content_ids_; }
+
+ bool operator==(const ContentIdSet& rhs) const;
+
+ private:
+ // Note, we only store the `id` field of ContentId, with the assumption that
+ // `id` is unique enough given these are only `feedstore::Content` ids.
+ base::flat_set<int64_t> content_ids_;
+};
+
} // namespace feed
#endif // COMPONENTS_FEED_CORE_V2_TYPES_H_
diff --git a/chromium/components/feed/core/v2/types_unittest.cc b/chromium/components/feed/core/v2/types_unittest.cc
index 1e48d3da836..633ae59be09 100644
--- a/chromium/components/feed/core/v2/types_unittest.cc
+++ b/chromium/components/feed/core/v2/types_unittest.cc
@@ -51,4 +51,14 @@ TEST(Types, ToContentRevision) {
EXPECT_EQ(ContentRevision(), ToContentRevision("c/"));
}
+TEST(Types, ContentIdSet) {
+ ContentIdSet v123(std::vector<int64_t>{1, 2, 3});
+ ContentIdSet v1234(std::vector<int64_t>{1, 2, 3, 4});
+
+ EXPECT_TRUE(v1234.ContainsAllOf(v123));
+ EXPECT_FALSE(v123.ContainsAllOf(v1234));
+ EXPECT_FALSE(v123.IsEmpty());
+ EXPECT_TRUE(ContentIdSet().IsEmpty());
+}
+
} // namespace feed
diff --git a/chromium/components/feed/core/v2/web_feed_subscription_coordinator.cc b/chromium/components/feed/core/v2/web_feed_subscription_coordinator.cc
index b314570abb3..e43733066a8 100644
--- a/chromium/components/feed/core/v2/web_feed_subscription_coordinator.cc
+++ b/chromium/components/feed/core/v2/web_feed_subscription_coordinator.cc
@@ -7,19 +7,22 @@
#include <memory>
#include "base/feature_list.h"
-#include "base/optional.h"
#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
+#include "components/feed/core/common/pref_names.h"
#include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/v2/config.h"
#include "components/feed/core/v2/feed_stream.h"
#include "components/feed/core/v2/feedstore_util.h"
#include "components/feed/core/v2/metrics_reporter.h"
+#include "components/feed/core/v2/public/feed_api.h"
#include "components/feed/core/v2/public/types.h"
#include "components/feed/core/v2/web_feed_subscriptions/subscribe_to_web_feed_task.h"
#include "components/feed/feed_feature_list.h"
#include "components/offline_pages/task/closure_task.h"
+#include "components/prefs/pref_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace feed {
namespace {
@@ -68,10 +71,10 @@ struct InFlightChange {
// Either subscribing or unsubscribing.
bool subscribing = false;
// Set only when subscribing from a web page.
- base::Optional<WebFeedPageInformation> page_information;
+ absl::optional<WebFeedPageInformation> page_information;
// We may or may not know about this web feed when subscribing; always known
// when unsubscribing.
- base::Optional<feedstore::WebFeedInfo> web_feed_info;
+ absl::optional<feedstore::WebFeedInfo> web_feed_info;
};
// An in-memory model of the subscribed web feeds. This should be loaded before
@@ -191,8 +194,9 @@ class WebFeedSubscriptionModel {
} // namespace internal
WebFeedSubscriptionCoordinator::WebFeedSubscriptionCoordinator(
+ PrefService* profile_prefs,
FeedStream* feed_stream)
- : feed_stream_(feed_stream) {
+ : feed_stream_(feed_stream), profile_prefs_(profile_prefs) {
base::TimeDelta delay = GetFeedConfig().fetch_web_feed_info_delay;
if (IsSignedInAndWebFeedsEnabled() && !delay.is_zero()) {
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
@@ -211,7 +215,8 @@ WebFeedSubscriptionCoordinator::WebFeedSubscriptionCoordinator(
}
bool WebFeedSubscriptionCoordinator::IsSignedInAndWebFeedsEnabled() const {
- return base::FeatureList::IsEnabled(kWebFeed) && feed_stream_->IsSignedIn();
+ return feed_stream_->IsEnabledAndVisible() &&
+ base::FeatureList::IsEnabled(kWebFeed) && feed_stream_->IsSignedIn();
}
WebFeedSubscriptionCoordinator::~WebFeedSubscriptionCoordinator() = default;
@@ -220,11 +225,15 @@ void WebFeedSubscriptionCoordinator::Populate(
const FeedStore::WebFeedStartupData& startup_data) {
index_.Populate(startup_data.recommended_feed_index);
index_.Populate(startup_data.subscribed_web_feeds);
+ populated_ = true;
+
+ UpdateIsSubscriberPref();
}
void WebFeedSubscriptionCoordinator::ClearAllFinished() {
- index_.Populate(feedstore::RecommendedWebFeedIndex{});
+ index_.Clear();
model_.reset();
+ UpdateIsSubscriberPref();
FetchRecommendedWebFeedsIfStale();
FetchSubscribedWebFeedsIfStale();
}
@@ -233,7 +242,7 @@ void WebFeedSubscriptionCoordinator::FollowWebFeed(
const WebFeedPageInformation& page_info,
base::OnceCallback<void(FollowWebFeedResult)> callback) {
EnqueueInFlightChange(/*subscribing=*/true, page_info,
- /*info=*/base::nullopt);
+ /*info=*/absl::nullopt);
WithModel(
base::BindOnce(&WebFeedSubscriptionCoordinator::FollowWebFeedFromUrlStart,
base::Unretained(this), page_info, std::move(callback)));
@@ -243,7 +252,7 @@ void WebFeedSubscriptionCoordinator::FollowWebFeedFromUrlStart(
const WebFeedPageInformation& page_info,
base::OnceCallback<void(FollowWebFeedResult)> callback) {
DCHECK(model_);
- WebFeedIndex::Entry entry = index_.FindWebFeedForUrl(page_info.url());
+ WebFeedIndex::Entry entry = index_.FindWebFeed(page_info);
SubscribeToWebFeedTask::Request request;
request.page_info = page_info;
@@ -259,7 +268,7 @@ void WebFeedSubscriptionCoordinator::FollowWebFeed(
feedstore::WebFeedInfo info;
info.set_web_feed_id(web_feed_id);
EnqueueInFlightChange(/*subscribing=*/true,
- /*page_information=*/base::nullopt, info);
+ /*page_information=*/absl::nullopt, info);
WithModel(
base::BindOnce(&WebFeedSubscriptionCoordinator::FollowWebFeedFromIdStart,
base::Unretained(this), web_feed_id, std::move(callback)));
@@ -286,6 +295,7 @@ void WebFeedSubscriptionCoordinator::FollowWebFeedComplete(
DequeueInflightChange();
if (result.request_status == WebFeedSubscriptionRequestStatus::kSuccess) {
model_->OnSubscribed(result.web_feed_info);
+ feed_stream_->SetStreamStale(kWebFeedStream, true);
}
SubscriptionInfo info =
model_->GetSubscriptionInfo(result.followed_web_feed_id);
@@ -313,10 +323,10 @@ void WebFeedSubscriptionCoordinator::UnfollowWebFeedStart(
SubscriptionInfo info = model_->GetSubscriptionInfo(web_feed_id);
EnqueueInFlightChange(/*subscribing=*/false,
- /*page_information=*/base::nullopt,
+ /*page_information=*/absl::nullopt,
info.status != WebFeedSubscriptionStatus::kUnknown
- ? base::make_optional(info.web_feed_info)
- : base::nullopt);
+ ? absl::make_optional(info.web_feed_info)
+ : absl::nullopt);
feed_stream_->GetTaskQueue().AddTask(
std::make_unique<UnsubscribeFromWebFeedTask>(
@@ -331,6 +341,7 @@ void WebFeedSubscriptionCoordinator::UnfollowWebFeedComplete(
UnsubscribeFromWebFeedTask::Result result) {
if (!result.unsubscribed_feed_name.empty()) {
model_->OnUnsubscribed(result.unsubscribed_feed_name);
+ feed_stream_->SetStreamStale(kWebFeedStream, true);
}
DequeueInflightChange();
UnfollowWebFeedResult callback_result;
@@ -344,7 +355,7 @@ void WebFeedSubscriptionCoordinator::FindWebFeedInfoForPage(
base::OnceCallback<void(WebFeedMetadata)> callback) {
if (!model_ && !loading_model_) {
// No model loaded, try to answer the request without it.
- WebFeedIndex::Entry entry = index_.FindWebFeedForUrl(page_info.url());
+ WebFeedIndex::Entry entry = index_.FindWebFeed(page_info);
if (!entry.followed()) {
LookupWebFeedDataAndRespond(
entry.web_feed_id, /*maybe_page_info=*/nullptr, std::move(callback));
@@ -419,7 +430,7 @@ void WebFeedSubscriptionCoordinator::LookupWebFeedDataAndRespond(
if (!id.empty()) {
entry = index_.FindWebFeed(id);
} else if (maybe_page_info) {
- entry = index_.FindWebFeedForUrl(maybe_page_info->url());
+ entry = index_.FindWebFeed(*maybe_page_info);
if (entry)
id = entry.web_feed_id;
}
@@ -520,8 +531,8 @@ void WebFeedSubscriptionCoordinator::ModelDataLoaded(
void WebFeedSubscriptionCoordinator::EnqueueInFlightChange(
bool subscribing,
- base::Optional<WebFeedPageInformation> page_information,
- base::Optional<feedstore::WebFeedInfo> info) {
+ absl::optional<WebFeedPageInformation> page_information,
+ absl::optional<feedstore::WebFeedInfo> info) {
in_flight_changes_.push_back(
{subscribing, std::move(page_information), std::move(info)});
}
@@ -572,11 +583,19 @@ void WebFeedSubscriptionCoordinator::GetAllSubscriptionsStart(
std::move(callback).Run(std::move(result));
}
+void WebFeedSubscriptionCoordinator::RefreshSubscriptions(
+ base::OnceCallback<void(RefreshResult)> callback) {
+ on_refresh_subscriptions_.push_back(std::move(callback));
+
+ WithModel(base::BindOnce(
+ &WebFeedSubscriptionCoordinator::FetchSubscribedWebFeedsStart,
+ base::Unretained(this)));
+}
+
SubscriptionInfo WebFeedSubscriptionCoordinator::FindSubscriptionInfo(
const WebFeedPageInformation& page_info) {
DCHECK(model_);
- return model_->GetSubscriptionInfo(
- index_.FindWebFeedForUrl(page_info.url()).web_feed_id);
+ return model_->GetSubscriptionInfo(index_.FindWebFeed(page_info).web_feed_id);
}
SubscriptionInfo WebFeedSubscriptionCoordinator::FindSubscriptionInfoById(
const std::string& web_feed_id) {
@@ -600,7 +619,7 @@ void WebFeedSubscriptionCoordinator::FetchRecommendedWebFeedsIfStale() {
void WebFeedSubscriptionCoordinator::FetchRecommendedWebFeedsStart() {
DCHECK(model_);
- if (fetching_recommended_web_feeds_)
+ if (fetching_recommended_web_feeds_ || !IsSignedInAndWebFeedsEnabled())
return;
fetching_recommended_web_feeds_ = true;
feed_stream_->GetTaskQueue().AddTask(
@@ -639,6 +658,10 @@ void WebFeedSubscriptionCoordinator::FetchSubscribedWebFeedsStart() {
DCHECK(model_);
if (fetching_subscribed_web_feeds_)
return;
+ if (!IsSignedInAndWebFeedsEnabled()) {
+ CallRefreshCompleteCallbacks({});
+ return;
+ }
fetching_subscribed_web_feeds_ = true;
feed_stream_->GetTaskQueue().AddTask(
std::make_unique<FetchSubscribedWebFeedsTask>(
@@ -656,6 +679,37 @@ void WebFeedSubscriptionCoordinator::FetchSubscribedWebFeedsComplete(
result.status, result.subscribed_web_feeds.size());
if (result.status == WebFeedRefreshStatus::kSuccess)
model_->UpdateSubscribedFeeds(std::move(result.subscribed_web_feeds));
+
+ UpdateIsSubscriberPref();
+ CallRefreshCompleteCallbacks(
+ RefreshResult{result.status == WebFeedRefreshStatus::kSuccess});
+}
+
+void WebFeedSubscriptionCoordinator::CallRefreshCompleteCallbacks(
+ RefreshResult result) {
+ std::vector<base::OnceCallback<void(RefreshResult)>> callbacks;
+ on_refresh_subscriptions_.swap(callbacks);
+ for (auto& callback : callbacks) {
+ std::move(callback).Run(result);
+ }
+}
+
+// Ideally, this function would be async so that we can determine with more
+// certainty that the user is a web feed subscriber. Until the UI can be
+// updated, we need to return an answer right away, so we cache a boolean in
+// prefs.
+bool WebFeedSubscriptionCoordinator::IsWebFeedSubscriber() {
+ if (populated_) {
+ return IsSignedInAndWebFeedsEnabled() && index_.HasSubscriptions();
+ } else {
+ return profile_prefs_->GetBoolean(feed::prefs::kIsWebFeedSubscriber);
+ }
+}
+
+void WebFeedSubscriptionCoordinator::UpdateIsSubscriberPref() {
+ profile_prefs_->SetBoolean(
+ feed::prefs::kIsWebFeedSubscriber,
+ IsSignedInAndWebFeedsEnabled() && index_.HasSubscriptions());
}
} // namespace feed
diff --git a/chromium/components/feed/core/v2/web_feed_subscription_coordinator.h b/chromium/components/feed/core/v2/web_feed_subscription_coordinator.h
index 9381335d8e7..d11dabb0323 100644
--- a/chromium/components/feed/core/v2/web_feed_subscription_coordinator.h
+++ b/chromium/components/feed/core/v2/web_feed_subscription_coordinator.h
@@ -10,7 +10,6 @@
#include "base/callback_forward.h"
#include "components/feed/core/proto/v2/store.pb.h"
-#include "components/feed/core/v2/public/feed_api.h"
#include "components/feed/core/v2/public/web_feed_subscriptions.h"
#include "components/feed/core/v2/web_feed_subscriptions/fetch_recommended_web_feeds_task.h"
#include "components/feed/core/v2/web_feed_subscriptions/fetch_subscribed_web_feeds_task.h"
@@ -18,6 +17,7 @@
#include "components/feed/core/v2/web_feed_subscriptions/unsubscribe_from_web_feed_task.h"
#include "components/feed/core/v2/web_feed_subscriptions/web_feed_index.h"
+class PrefService;
namespace feed {
namespace internal {
class WebFeedSubscriptionModel;
@@ -29,7 +29,8 @@ class FeedStream;
// Coordinates the state of subscription to web feeds.
class WebFeedSubscriptionCoordinator : public WebFeedSubscriptions {
public:
- explicit WebFeedSubscriptionCoordinator(FeedStream* feed_stream);
+ explicit WebFeedSubscriptionCoordinator(PrefService* profile_prefs,
+ FeedStream* feed_stream);
virtual ~WebFeedSubscriptionCoordinator();
WebFeedSubscriptionCoordinator(const WebFeedSubscriptionCoordinator&) =
delete;
@@ -60,6 +61,9 @@ class WebFeedSubscriptionCoordinator : public WebFeedSubscriptions {
base::OnceCallback<void(WebFeedMetadata)> callback) override;
void GetAllSubscriptions(
base::OnceCallback<void(std::vector<WebFeedMetadata>)> callback) override;
+ void RefreshSubscriptions(
+ base::OnceCallback<void(RefreshResult)> callback) override;
+ bool IsWebFeedSubscriber() override;
// Types / functions exposed for task implementations.
@@ -135,8 +139,8 @@ class WebFeedSubscriptionCoordinator : public WebFeedSubscriptions {
void EnqueueInFlightChange(
bool subscribing,
- base::Optional<WebFeedPageInformation> page_information,
- base::Optional<feedstore::WebFeedInfo> info);
+ absl::optional<WebFeedPageInformation> page_information,
+ absl::optional<feedstore::WebFeedInfo> info);
const InFlightChange* FindInflightChange(
const std::string& web_feed_id,
const WebFeedPageInformation* maybe_page_info);
@@ -151,9 +155,15 @@ class WebFeedSubscriptionCoordinator : public WebFeedSubscriptions {
void FetchSubscribedWebFeedsStart();
void FetchSubscribedWebFeedsComplete(
FetchSubscribedWebFeedsTask::Result result);
+ void CallRefreshCompleteCallbacks(RefreshResult);
+ void UpdateIsSubscriberPref();
FeedStream* feed_stream_; // Always non-null, it owns this.
+ PrefService* profile_prefs_;
+
WebFeedIndex index_;
+ // Whether `Populate()` has been called.
+ bool populated_ = false;
// A model of subscriptions. In memory only while needed.
// TODO(harringtond): Unload the model eventually.
std::unique_ptr<WebFeedSubscriptionModel> model_;
@@ -167,6 +177,8 @@ class WebFeedSubscriptionCoordinator : public WebFeedSubscriptions {
// Chrome process goes down.
std::vector<feedstore::WebFeedInfo> recent_unsubscribed_;
std::vector<base::OnceClosure> when_model_loads_;
+ std::vector<base::OnceCallback<void(RefreshResult)>>
+ on_refresh_subscriptions_;
bool fetching_recommended_web_feeds_ = false;
bool fetching_subscribed_web_feeds_ = false;
diff --git a/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index.cc b/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index.cc
index b9d4baf2ad0..464e0d4f159 100644
--- a/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index.cc
+++ b/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index.cc
@@ -4,49 +4,376 @@
#include "components/feed/core/v2/web_feed_subscriptions/web_feed_index.h"
+#include <memory>
#include <ostream>
+#include <vector>
+#include "base/containers/flat_map.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
#include "components/feed/core/proto/v2/store.pb.h"
#include "components/feed/core/proto/v2/wire/web_feed_matcher.pb.h"
#include "components/feed/core/v2/feedstore_util.h"
+#include "components/url_matcher/string_pattern.h"
+#include "components/url_matcher/url_matcher.h"
#include "url/gurl.h"
-
namespace feed {
-
namespace {
using Entry = WebFeedIndex::Entry;
-void AddEntries(std::vector<Entry>& entries,
- std::vector<std::pair<std::string, int>>& domain_list,
- const ::google::protobuf::RepeatedPtrField<
- feedwire::webfeed::WebFeedMatcher>& matchers,
- bool is_recommended,
- const std::string& web_feed_id) {
- int index = static_cast<int>(entries.size());
- entries.push_back({web_feed_id, is_recommended});
- for (const feedwire::webfeed::WebFeedMatcher& matcher : matchers) {
- // TODO(crbug/1152592): This code is wrong! We need to match ALL criteria
- // provided. Also, we need to support the initial set of criteria types.
- if (!web_feed_id.empty()) {
- for (const auto& criteria : matcher.criteria()) {
- if (criteria.criteria_type() == feedwire::webfeed::WebFeedMatcher::
- Criteria::PAGE_URL_HOST_SUFFIX &&
- !criteria.text().empty()) {
- domain_list.emplace_back(criteria.text(), index);
- }
+
+// Given a host and a list of host suffixes, efficiently finds which host
+// suffixes match.
+class HostSuffixMatcher {
+ public:
+ // A host suffix to search for.
+ struct Entry {
+ bool operator<(const Entry& rhs) const {
+ return host_suffix < rhs.host_suffix;
+ }
+ bool operator<(base::StringPiece other_host_suffix) const {
+ return host_suffix < other_host_suffix;
+ }
+ std::string host_suffix;
+ int condition_id;
+ };
+
+ explicit HostSuffixMatcher(std::vector<Entry> entries) {
+ entries_ = std::move(entries);
+ std::sort(entries_.begin(), entries_.end());
+ }
+
+ // Find all host suffixes that match `host_string`, and add the match IDs to
+ // `match_set`.
+ void FindMatches(const std::string& host_string, std::set<int>& match_set) {
+ base::StringPiece host(host_string);
+ if (host.empty())
+ return;
+ // Ignore a trailing dot for a FQDN.
+ if (host[host.size() - 1] == '.')
+ host = host.substr(0, host.size() - 1);
+
+ // Given a `host_string` of 'sub.foo.com', search for 'sub.foo.com',
+ // 'foo.com', and then finally 'com'.
+ FindExactMatches(host, match_set);
+ for (size_t i = 0; i < host.size(); ++i) {
+ if (host[i] == '.')
+ FindExactMatches(host.substr(i + 1), match_set);
+ }
+ }
+
+ private:
+ void FindExactMatches(base::StringPiece prefix, std::set<int>& match_set) {
+ auto iter = std::lower_bound(entries_.begin(), entries_.end(), prefix);
+ while (iter != entries_.end() && iter->host_suffix == prefix) {
+ match_set.insert(iter->condition_id);
+ ++iter;
+ }
+ }
+
+ std::vector<Entry> entries_;
+};
+
+constexpr int kFirstConditionId = 1;
+
+// References a set of conditions that all must be true to identify a Web Feed.
+// Conditions in this context are represented by unique integer IDs. Each
+// MultiConditionSet represents a set of sequential contion IDs, and an entry
+// index which points to the Web Feed with these associated match conditions.
+// See its use in EntrySet::Search() for context.
+struct MultiConditionSet {
+ // The number of conditions that must be true. Because MultiConditionSet is
+ // always stored as a vector<MultiConditionSet>, this alone uniquely
+ // identifies the condition IDs that must be met, given the following
+ // assumptions:
+ // 1. The first MultiConditionSet starts with kFirstConditionId.
+ // 2. Each MultiConditionSet claims sequential condition IDs.
+ //
+ // For example, given the list of MultiConditionSets with the condition
+ // counts [2,3,1], the condition sets correspond to the condition IDs: [{1,2},
+ // {3,4,5}, {6}].
+ int condition_count = 0;
+ // The index of the Web Feed entry which is identified by these conditions.
+ int entry_index;
+};
+
+} // namespace
+
+namespace web_feed_index_internal {
+class EntrySetBuilder;
+
+// A set of WebFeedIndex::Entry objects.
+class EntrySet {
+ public:
+ EntrySet() = default;
+ // Returns the Web Feed entry for the Web Feed that matches `page_url` and
+ // `rss_urls`. Returns an invalid Entry if none is found.
+ Entry Search(const GURL& page_url, const std::vector<GURL>& rss_urls) {
+ // Search each 'vertical slice' independently: page URL, page host suffix,
+ // page suffix, and RSS URL. Collect set of matching IDs.
+
+ std::set<int> matching_ids = page_url_matcher_.MatchURL(page_url);
+ for (const GURL& rss_url : rss_urls) {
+ auto ids = rss_url_matcher_.MatchURL(rss_url);
+ matching_ids.insert(ids.begin(), ids.end());
+ }
+ page_host_matcher_.Match(page_url.host(), &matching_ids);
+ host_suffix_matcher_.FindMatches(page_url.host(), matching_ids);
+ page_path_matcher_.Match(page_url.path(), &matching_ids);
+
+ // Iterate through `condition_sets_` to find any which has all conditions
+ // met. Because condition IDs used in condition_sets_ and matching_ids
+ // are both sorted, this can be done in a single O(N) pass.
+ // Note: If we make the assumption that `matching_ids` is very small, we can
+ // do better by binary searching for each of `matching_ids`. But a linear
+ // scan is easier and likely pretty fast since condition_sets_ is dense and
+ // flat.
+
+ int mcs_first_condition_id = kFirstConditionId;
+ int matches_for_mcs = 0;
+ auto match_iter = matching_ids.begin();
+ for (size_t i = 0;
+ i < condition_sets_.size() && match_iter != matching_ids.end();) {
+ MultiConditionSet& mcs = condition_sets_[i];
+ if (*match_iter < mcs_first_condition_id) {
+ ++match_iter;
+ matches_for_mcs = 0;
+ continue;
+ }
+ if (mcs_first_condition_id + mcs.condition_count <= *match_iter) {
+ matches_for_mcs = 0;
+ mcs_first_condition_id += mcs.condition_count;
+ ++i;
+ continue;
+ }
+ ++matches_for_mcs;
+ ++match_iter;
+ if (mcs.condition_count == matches_for_mcs) {
+ return entries_[mcs.entry_index];
}
}
+ return {};
+ }
+
+ const std::vector<Entry>& entries() const { return entries_; }
+
+ private:
+ friend class EntrySetBuilder;
+
+ // Web Feeds in this set.
+ std::vector<Entry> entries_;
+
+ // Members that just hold on to memory used in matchers.
+ url_matcher::URLMatcherConditionFactory condition_factory_;
+ std::vector<url_matcher::StringPattern> host_match_patterns_;
+ std::vector<url_matcher::StringPattern> path_match_patterns_;
+
+ // List of `MultiConditionSet`. Each one knows how to aggregate match IDs
+ // reported from matchers below into a WebFeed match.
+ std::vector<MultiConditionSet> condition_sets_;
+
+ // Each of the following matcher have the capability to match different
+ // things, and report integer IDs for each match.
+ url_matcher::URLMatcher page_url_matcher_;
+ url_matcher::RegexSetMatcher page_host_matcher_;
+ url_matcher::RegexSetMatcher page_path_matcher_;
+ HostSuffixMatcher host_suffix_matcher_{{}};
+ url_matcher::URLMatcher rss_url_matcher_;
+};
+
+class EntrySetBuilder {
+ public:
+ void AddSubscribed(const feedstore::WebFeedInfo& web_feed_info) {
+ int index = static_cast<int>(entry_set_->entries_.size());
+ entry_set_->entries_.push_back(
+ {web_feed_info.web_feed_id(), /*is_recommended=*/false});
+ for (const auto& matcher : web_feed_info.matchers()) {
+ CreateMatcherConditions(matcher, index);
+ }
+ }
+
+ void AddRecommended(const feedstore::RecommendedWebFeedIndex::Entry& entry) {
+ int index = static_cast<int>(entry_set_->entries_.size());
+ entry_set_->entries_.push_back(
+ {entry.web_feed_id(), /*is_recommended=*/true});
+ for (const auto& matcher : entry.matchers()) {
+ CreateMatcherConditions(matcher, index);
+ }
}
-}
+
+ std::unique_ptr<EntrySet> Build() && {
+ DCHECK(entry_set_) << "Build can only be called once";
+ entry_set_->page_url_matcher_.AddConditionSets(page_conditions_);
+ entry_set_->rss_url_matcher_.AddConditionSets(rss_conditions_);
+ entry_set_->page_host_matcher_.AddPatterns(
+ MakeVectorOfPointers(entry_set_->host_match_patterns_));
+ entry_set_->page_path_matcher_.AddPatterns(
+ MakeVectorOfPointers(entry_set_->path_match_patterns_));
+
+ entry_set_->host_suffix_matcher_ =
+ HostSuffixMatcher(std::move(host_suffix_entries_));
+ return std::move(entry_set_);
+ }
+
+ private:
+ bool CreateMatcherConditions(
+ const feedwire::webfeed::WebFeedMatcher& web_feed_matcher,
+ int web_feed_entry_index) {
+ // Interpret all of the criteria first. If there are any errors, or unknown
+ // criteria types, abort adding the conditions by returning early.
+ if (web_feed_matcher.criteria_size() == 0)
+ return false;
+ for (const auto& criteria : web_feed_matcher.criteria()) {
+ const std::string* text = nullptr;
+ const std::string* regex = nullptr;
+ switch (criteria.match_case()) {
+ case feedwire::webfeed::WebFeedMatcher::Criteria::MatchCase::kRegex:
+ regex = &criteria.regex();
+ if (regex->empty())
+ return false;
+ break;
+ case feedwire::webfeed::WebFeedMatcher::Criteria::MatchCase::kText:
+ text = &criteria.text();
+ if (text->empty())
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ switch (criteria.criteria_type()) {
+ case feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_HOST_SUFFIX:
+ if (!text)
+ return false;
+ break;
+ case feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_HOST_MATCH:
+ case feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_PATH_MATCH:
+ case feedwire::webfeed::WebFeedMatcher::Criteria::RSS_URL_MATCH:
+ if (text || regex)
+ break;
+ return false;
+ default:
+ return false;
+ }
+ }
+
+ // All criteria were understood, so create a `MultiConditionSet`
+ // representing them.
+ std::set<url_matcher::URLMatcherCondition> page_matcher_conditions;
+ MultiConditionSet mcs;
+ mcs.entry_index = web_feed_entry_index;
+
+ for (const auto& criteria : web_feed_matcher.criteria()) {
+ const std::string* text = nullptr;
+ const std::string* regex = nullptr;
+ switch (criteria.match_case()) {
+ case feedwire::webfeed::WebFeedMatcher::Criteria::MatchCase::kRegex:
+ regex = &criteria.regex();
+ break;
+ case feedwire::webfeed::WebFeedMatcher::Criteria::MatchCase::kText:
+ text = &criteria.text();
+ break;
+ default:
+ return false;
+ }
+
+ switch (criteria.criteria_type()) {
+ case feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_HOST_MATCH:
+ if (text) {
+ page_matcher_conditions.insert(
+ entry_set_->condition_factory_.CreateHostEqualsCondition(
+ *text));
+ break;
+ }
+ DCHECK(regex);
+ entry_set_->host_match_patterns_.emplace_back(
+ std::move(*regex), next_condition_set_id++);
+ ++mcs.condition_count;
+ break;
+ case feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_HOST_SUFFIX:
+ DCHECK(text);
+ host_suffix_entries_.push_back({*text, next_condition_set_id++});
+ ++mcs.condition_count;
+ break;
+ case feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_PATH_MATCH:
+ if (text) {
+ page_matcher_conditions.insert(
+ entry_set_->condition_factory_.CreatePathEqualsCondition(
+ *text));
+ break;
+ }
+ DCHECK(regex);
+ entry_set_->path_match_patterns_.emplace_back(
+ *regex, next_condition_set_id++);
+ ++mcs.condition_count;
+ break;
+ case feedwire::webfeed::WebFeedMatcher::Criteria::RSS_URL_MATCH: {
+ url_matcher::URLMatcherCondition condition;
+ if (text) {
+ condition =
+ entry_set_->condition_factory_.CreateURLEqualsCondition(*text);
+ } else {
+ DCHECK(regex);
+ condition =
+ entry_set_->condition_factory_.CreateURLMatchesCondition(
+ *regex);
+ }
+ rss_conditions_.push_back(
+ base::MakeRefCounted<url_matcher::URLMatcherConditionSet>(
+ next_condition_set_id++,
+ std::set<url_matcher::URLMatcherCondition>(
+ {std::move(condition)})));
+ ++mcs.condition_count;
+ } break;
+ default:
+ DCHECK(false);
+ break;
+ }
+ }
+
+ if (!page_matcher_conditions.empty()) {
+ page_conditions_.push_back(
+ base::MakeRefCounted<url_matcher::URLMatcherConditionSet>(
+ next_condition_set_id++, page_matcher_conditions));
+ ++mcs.condition_count;
+ }
+ DCHECK_GE(mcs.condition_count, 0);
+ entry_set_->condition_sets_.push_back(mcs);
+ return true;
+ }
+
+ static std::vector<const url_matcher::StringPattern*> MakeVectorOfPointers(
+ const std::vector<url_matcher::StringPattern>& patterns) {
+ std::vector<const url_matcher::StringPattern*> result(patterns.size());
+ for (size_t i = 0; i < patterns.size(); ++i) {
+ result[i] = &patterns[i];
+ }
+ return result;
+ }
+
+ // The `EntrySet` being built.
+ std::unique_ptr<EntrySet> entry_set_ = std::make_unique<EntrySet>();
+
+ // Temporary state for building `entry_set_`.
+ int next_condition_set_id = kFirstConditionId;
+ std::vector<scoped_refptr<url_matcher::URLMatcherConditionSet>>
+ page_conditions_;
+ std::vector<scoped_refptr<url_matcher::URLMatcherConditionSet>>
+ rss_conditions_;
+ std::vector<HostSuffixMatcher::Entry> host_suffix_entries_;
+};
+
+} // namespace web_feed_index_internal
+
+namespace {
+
+using EntrySetBuilder = web_feed_index_internal::EntrySetBuilder;
} // namespace
-WebFeedIndex::EntrySet::EntrySet() = default;
-WebFeedIndex::EntrySet::~EntrySet() = default;
-WebFeedIndex::EntrySet::EntrySet(const EntrySet&) = default;
-WebFeedIndex::EntrySet& WebFeedIndex::EntrySet::operator=(const EntrySet&) =
- default;
-WebFeedIndex::WebFeedIndex() = default;
+WebFeedIndex::WebFeedIndex() {
+ Clear();
+}
+
WebFeedIndex::~WebFeedIndex() = default;
void WebFeedIndex::Populate(
@@ -56,17 +383,15 @@ void WebFeedIndex::Populate(
update_time_millis <= 0
? base::Time()
: feedstore::FromTimestampMillis(update_time_millis);
- recommended_ = {};
- std::vector<std::pair<std::string, int>> domain_list;
+
+ EntrySetBuilder builder;
for (const feedstore::RecommendedWebFeedIndex::Entry& entry :
recommended_feed_index.entries()) {
- AddEntries(recommended_.entries, domain_list, entry.matchers(),
- /*is_recommended=*/true, entry.web_feed_id());
+ builder.AddRecommended(entry);
}
- recommended_.domains =
- base::flat_map<std::string, int>(std::move(domain_list));
+ recommended_ = std::move(builder).Build();
}
void WebFeedIndex::Populate(
@@ -76,79 +401,61 @@ void WebFeedIndex::Populate(
update_time_millis <= 0
? base::Time()
: feedstore::FromTimestampMillis(update_time_millis);
- subscribed_ = {};
- std::vector<std::pair<std::string, int>> domain_list;
+
+ EntrySetBuilder builder;
+
// TODO(crbug/1152592): Record UMA for subscribed and recommended lists.
// Note that flat_map will keep only the first entry with a given key.
for (const auto& info : subscribed_feeds.feeds()) {
- AddEntries(subscribed_.entries, domain_list, info.matchers(),
- /*is_recommended=*/false, info.web_feed_id());
+ builder.AddSubscribed(info);
}
-
- subscribed_.domains =
- base::flat_map<std::string, int>(std::move(domain_list));
+ subscribed_ = std::move(builder).Build();
}
-// For host a.b.c.d.com ->
-// Lookup, in this order: a.b.c.d.com, b.c.d.com, c.d.com, d.com, com.
-WebFeedIndex::Entry WebFeedIndex::FindWebFeedForUrl(const GURL& url) {
- std::string host_string = url.host();
- base::StringPiece host(host_string);
- if (host.empty())
- return empty_entry_;
- // Ignore a trailing dot for a FQDN.
- if (host[host.size() - 1] == '.')
- host = host.substr(0, host.size() - 1);
-
- const Entry* result = &FindWebFeedForDomain(host);
- for (size_t i = 0; i < host.size() && result->web_feed_id.empty(); ++i) {
- if (host[i] == '.')
- result = &FindWebFeedForDomain(host.substr(i + 1));
- }
- return *result;
+void WebFeedIndex::Clear() {
+ recommended_ = std::make_unique<EntrySet>();
+ subscribed_ = std::make_unique<EntrySet>();
+ recommended_feeds_update_time_ = base::Time();
+ subscribed_feeds_update_time_ = base::Time();
}
WebFeedIndex::Entry WebFeedIndex::FindWebFeed(const std::string& web_feed_id) {
- for (const Entry& e : subscribed_.entries) {
+ for (const Entry& e : subscribed_->entries()) {
if (e.web_feed_id == web_feed_id)
return e;
}
- for (const Entry& e : recommended_.entries) {
+ for (const Entry& e : recommended_->entries()) {
if (e.web_feed_id == web_feed_id)
return e;
}
return {};
}
-const WebFeedIndex::Entry& WebFeedIndex::FindWebFeedForDomain(
- base::StringPiece domain) {
- const Entry& result = FindWebFeedForDomain(subscribed_, domain);
- if (!result.web_feed_id.empty())
- return result;
- return FindWebFeedForDomain(recommended_, domain);
-}
-
-const WebFeedIndex::Entry& WebFeedIndex::FindWebFeedForDomain(
- const EntrySet& entry_set,
- base::StringPiece domain) {
- auto iter = entry_set.domains.find(domain);
- return (iter != entry_set.domains.end()) ? entry_set.entries[iter->second]
- : empty_entry_;
+Entry WebFeedIndex::FindWebFeed(const WebFeedPageInformation& page_info) {
+ Entry result = subscribed_->Search(page_info.url(), page_info.GetRssUrls());
+ if (!result) {
+ result = recommended_->Search(page_info.url(), page_info.GetRssUrls());
+ }
+ return result;
}
bool WebFeedIndex::IsRecommended(const std::string& web_feed_id) const {
if (web_feed_id.empty())
return false;
- for (const Entry& e : recommended_.entries) {
+ for (const Entry& e : recommended_->entries()) {
if (e.web_feed_id == web_feed_id)
return true;
}
return false;
}
+bool WebFeedIndex::HasSubscriptions() const {
+ return !subscribed_->entries().empty();
+}
+
std::vector<WebFeedIndex::Entry> WebFeedIndex::GetRecommendedEntriesForTesting()
const {
- return recommended_.entries;
+ return recommended_->entries();
}
std::ostream& operator<<(std::ostream& os, const WebFeedIndex::Entry& entry) {
diff --git a/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index.h b/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index.h
index f58df805b3e..d78433712ac 100644
--- a/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index.h
+++ b/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index.h
@@ -13,12 +13,15 @@
#include "components/feed/core/v2/enums.h"
#include "components/feed/core/v2/feed_store.h"
#include "components/feed/core/v2/proto_util.h"
+#include "components/url_matcher/url_matcher.h"
-class GURL;
namespace feedstore {
class UriMatcher;
}
namespace feed {
+namespace web_feed_index_internal {
+class EntrySet;
+} // namespace web_feed_index_internal
// Tracks followed web feeds, and recommended web feeds.
class WebFeedIndex {
@@ -43,10 +46,11 @@ class WebFeedIndex {
// Populate the recommended feed index.
void Populate(const feedstore::RecommendedWebFeedIndex& recommended_feeds);
- // Returns the `Entry` for `url`. If more than one web feed matches,
- // this returns only one. Subscribed feeds, and more specific URL matches are
- // returned preferentially.
- Entry FindWebFeedForUrl(const GURL& url);
+ void Clear();
+
+ // Returns the Web Feed `Entry` which matches `page_info`. If there's more
+ // than one match, preferentially returns subscribed Web Feed entries.
+ Entry FindWebFeed(const WebFeedPageInformation& page_info);
Entry FindWebFeed(const std::string& id);
bool IsRecommended(const std::string& web_feed_id) const;
@@ -57,32 +61,22 @@ class WebFeedIndex {
base::Time GetSubscribedFeedsUpdateTime() const {
return subscribed_feeds_update_time_;
}
+ bool HasSubscriptions() const;
std::vector<Entry> GetRecommendedEntriesForTesting() const;
private:
- // TODO(crbug/1152592): This code is temporary, we will need to have
- // additional matching criteria. Plan to use url_matcher.h instead.
- struct EntrySet {
- EntrySet();
- ~EntrySet();
- EntrySet(const EntrySet&);
- EntrySet& operator=(const EntrySet&);
- // Maps from domain -> entries_ index.
- base::flat_map<std::string, int> domains;
- std::vector<Entry> entries;
- };
+ using EntrySet = web_feed_index_internal::EntrySet;
+
void AddMatcher(const std::string& web_feed_id,
const feedstore::UriMatcher& matcher);
- const Entry& FindWebFeedForDomain(base::StringPiece domain);
- const Entry& FindWebFeedForDomain(const EntrySet& entry_set,
- base::StringPiece domain);
base::Time recommended_feeds_update_time_;
base::Time subscribed_feeds_update_time_;
- EntrySet subscribed_;
- EntrySet recommended_;
Entry empty_entry_;
+
+ std::unique_ptr<EntrySet> recommended_;
+ std::unique_ptr<EntrySet> subscribed_;
};
// For tests.
diff --git a/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index_unittest.cc b/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index_unittest.cc
index 333f32c6d2f..9c1ed3bc251 100644
--- a/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index_unittest.cc
+++ b/chromium/components/feed/core/v2/web_feed_subscriptions/web_feed_index_unittest.cc
@@ -9,22 +9,47 @@
namespace feed {
namespace {
+using Criteria = feedwire::webfeed::WebFeedMatcher::Criteria;
+
+WebFeedPageInformation MakePageInfo(const GURL& url,
+ std::vector<GURL> rss_urls = {}) {
+ WebFeedPageInformation page_info;
+ page_info.SetUrl(url);
+ page_info.SetRssUrls(rss_urls);
+ return page_info;
+}
+
+feedwire::webfeed::WebFeedMatcher::Criteria TextCriteria(
+ feedwire::webfeed::WebFeedMatcher::Criteria::CriteriaType criteria_type,
+ const std::string& text) {
+ feedwire::webfeed::WebFeedMatcher::Criteria criteria;
+ criteria.set_criteria_type(criteria_type);
+ criteria.set_text(text);
+ return criteria;
+}
+
+feedwire::webfeed::WebFeedMatcher::Criteria RegexCriteria(
+ feedwire::webfeed::WebFeedMatcher::Criteria::CriteriaType criteria_type,
+ const std::string& regex) {
+ feedwire::webfeed::WebFeedMatcher::Criteria criteria;
+ criteria.set_criteria_type(criteria_type);
+ criteria.set_regex(regex);
+ return criteria;
+}
feedwire::webfeed::WebFeedMatcher MakeDomainMatcher(const std::string& domain) {
feedwire::webfeed::WebFeedMatcher result;
- feedwire::webfeed::WebFeedMatcher::Criteria* criteria = result.add_criteria();
- criteria->set_criteria_type(
- feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_HOST_SUFFIX);
- criteria->set_text(domain);
+ *result.add_criteria() = TextCriteria(Criteria::PAGE_URL_HOST_SUFFIX, domain);
return result;
}
TEST(WebFeedIndex, FindWebFeedForUrlBeforePopulate) {
WebFeedIndex index;
- EXPECT_EQ("", index.FindWebFeedForUrl(GURL("http://foo")).web_feed_id);
+ EXPECT_EQ("",
+ index.FindWebFeed(MakePageInfo(GURL("http://foo"))).web_feed_id);
}
-TEST(WebFeedIndex, FindWebFeedForUrlResolvesDomainsCorrectly) {
+TEST(WebFeedIndex, FindWebFeedResolvesDomainsCorrectly) {
WebFeedIndex index;
FeedStore::WebFeedStartupData startup_data;
{
@@ -35,29 +60,42 @@ TEST(WebFeedIndex, FindWebFeedForUrlResolvesDomainsCorrectly) {
index.Populate(startup_data.subscribed_web_feeds);
// Matching URLs.
- EXPECT_EQ("id", index.FindWebFeedForUrl(GURL("https://foo.com")).web_feed_id);
- EXPECT_EQ("id", index.FindWebFeedForUrl(GURL("http://foo.com")).web_feed_id);
- EXPECT_EQ("id",
- index.FindWebFeedForUrl(GURL("http://foo.com:1234")).web_feed_id);
- EXPECT_EQ("id",
- index.FindWebFeedForUrl(GURL("https://foo.com/bar")).web_feed_id);
- EXPECT_EQ("id", index.FindWebFeedForUrl(GURL("https://foo.com")).web_feed_id);
- EXPECT_EQ("id",
- index.FindWebFeedForUrl(GURL("https://baz.foo.com")).web_feed_id);
- EXPECT_EQ("id",
- index.FindWebFeedForUrl(GURL("https://baz.foo.com.")).web_feed_id);
EXPECT_EQ(
"id",
- index.FindWebFeedForUrl(GURL("https://a.b.c.d.e.foo.com")).web_feed_id);
+ index.FindWebFeed(MakePageInfo(GURL("https://foo.com"))).web_feed_id);
+ EXPECT_EQ(
+ "id",
+ index.FindWebFeed(MakePageInfo(GURL("http://foo.com"))).web_feed_id);
+ EXPECT_EQ(
+ "id",
+ index.FindWebFeed(MakePageInfo(GURL("http://foo.com:1234"))).web_feed_id);
+ EXPECT_EQ(
+ "id",
+ index.FindWebFeed(MakePageInfo(GURL("https://foo.com/bar"))).web_feed_id);
+ EXPECT_EQ(
+ "id",
+ index.FindWebFeed(MakePageInfo(GURL("https://foo.com"))).web_feed_id);
+ EXPECT_EQ(
+ "id",
+ index.FindWebFeed(MakePageInfo(GURL("https://baz.foo.com"))).web_feed_id);
+ EXPECT_EQ("id", index.FindWebFeed(MakePageInfo(GURL("https://baz.foo.com.")))
+ .web_feed_id);
+ EXPECT_EQ("id",
+ index.FindWebFeed(MakePageInfo(GURL("https://a.b.c.d.e.foo.com")))
+ .web_feed_id);
// Non-matching URLs.
- EXPECT_EQ("",
- index.FindWebFeedForUrl(GURL("https://foo.com.br")).web_feed_id);
- EXPECT_EQ("",
- index.FindWebFeedForUrl(GURL("https://xyz.foo.com.z")).web_feed_id);
+ EXPECT_EQ(
+ "",
+ index.FindWebFeed(MakePageInfo(GURL("https://foo.com.br"))).web_feed_id);
+ EXPECT_EQ(
+ "",
+ index.FindWebFeed(MakePageInfo(GURL("https://xfoo.com"))).web_feed_id);
+ EXPECT_EQ("", index.FindWebFeed(MakePageInfo(GURL("https://xyz.foo.com.z")))
+ .web_feed_id);
EXPECT_EQ("", index
- .FindWebFeedForUrl(
- GURL("https://1000:1000:1000:0000:0000:0000:0000:0000"))
+ .FindWebFeed(MakePageInfo(GURL(
+ "https://1000:1000:1000:0000:0000:0000:0000:0000")))
.web_feed_id);
}
@@ -72,9 +110,11 @@ TEST(WebFeedIndex, PopulateOverwritesContent) {
feed->set_web_feed_id("aid");
index.Populate(startup_data.subscribed_web_feeds);
- EXPECT_EQ("aid",
- index.FindWebFeedForUrl(GURL("https://boo.com")).web_feed_id);
- EXPECT_EQ("", index.FindWebFeedForUrl(GURL("https://foo.com")).web_feed_id);
+ EXPECT_EQ(
+ "aid",
+ index.FindWebFeed(MakePageInfo(GURL("https://boo.com"))).web_feed_id);
+ EXPECT_EQ(
+ "", index.FindWebFeed(MakePageInfo(GURL("https://foo.com"))).web_feed_id);
}
TEST(WebFeedIndex, FindWebFeedForUrlFindsRecommendedUrl) {
@@ -85,53 +125,257 @@ TEST(WebFeedIndex, FindWebFeedForUrlFindsRecommendedUrl) {
*feed->add_matchers() = MakeDomainMatcher("foo.com");
index.Populate(startup_data.recommended_feed_index);
- EXPECT_EQ("id", index.FindWebFeedForUrl(GURL("https://foo.com")).web_feed_id);
+ EXPECT_EQ(
+ "id",
+ index.FindWebFeed(MakePageInfo(GURL("https://foo.com"))).web_feed_id);
}
-TEST(WebFeedIndex, FindWebFeedForUrlFindMoreSpecificFirst) {
+TEST(WebFeedIndex, FindWebFeedWithPageInfoFindsSubscribedFeedsPreferentially) {
WebFeedIndex index;
FeedStore::WebFeedStartupData startup_data;
{
- auto* feed = startup_data.recommended_feed_index.add_entries();
- feed->set_web_feed_id("foo");
+ auto* feed = startup_data.subscribed_web_feeds.add_feeds();
+ feed->set_web_feed_id("sub-id");
*feed->add_matchers() = MakeDomainMatcher("foo.com");
}
{
auto* feed = startup_data.recommended_feed_index.add_entries();
- feed->set_web_feed_id("barfoo");
- *feed->add_matchers() = MakeDomainMatcher("bar.foo.com");
+ feed->set_web_feed_id("recommended-id");
+ *feed->add_matchers() = MakeDomainMatcher("foo.com");
}
-
index.Populate(startup_data.recommended_feed_index);
+ index.Populate(startup_data.subscribed_web_feeds);
- EXPECT_EQ("barfoo",
- index.FindWebFeedForUrl(GURL("https://bar.foo.com")).web_feed_id);
- EXPECT_EQ("barfoo",
- index.FindWebFeedForUrl(GURL("https://a.bar.foo.com")).web_feed_id);
- EXPECT_EQ("foo",
- index.FindWebFeedForUrl(GURL("https://foo.com")).web_feed_id);
- EXPECT_EQ("foo",
- index.FindWebFeedForUrl(GURL("https://baz.foo.com")).web_feed_id);
+ EXPECT_EQ(
+ "sub-id",
+ index.FindWebFeed(MakePageInfo(GURL("https://foo.com"))).web_feed_id);
}
-TEST(WebFeedIndex, FindWebFeedForUrlFindsSubscribedFeedsPreferentially) {
+TEST(WebFeedIndex, FindWebFeedCriteriaPageUrlHostMatch) {
WebFeedIndex index;
FeedStore::WebFeedStartupData startup_data;
{
auto* feed = startup_data.subscribed_web_feeds.add_feeds();
- feed->set_web_feed_id("sub-id");
- *feed->add_matchers() = MakeDomainMatcher("foo.com");
+ feed->set_web_feed_id("id");
+ *feed->add_matchers()->add_criteria() =
+ RegexCriteria(Criteria::PAGE_URL_HOST_MATCH, "^[fb]oobar.com");
+ *feed->add_matchers()->add_criteria() =
+ TextCriteria(Criteria::PAGE_URL_HOST_MATCH, "baz.com");
}
+ index.Populate(startup_data.subscribed_web_feeds);
+
+ EXPECT_EQ("id",
+ index.FindWebFeed(MakePageInfo(GURL("https://foobar.com/path")))
+ .web_feed_id);
+ EXPECT_EQ("id",
+ index.FindWebFeed(MakePageInfo(GURL("https://boobar.com/path")))
+ .web_feed_id);
+ EXPECT_EQ("id", index.FindWebFeed(MakePageInfo(GURL("https://baz.com/path")))
+ .web_feed_id);
+
+ EXPECT_EQ("",
+ index.FindWebFeed(MakePageInfo(GURL("https://sub.foobar.com/path")))
+ .web_feed_id);
+ EXPECT_EQ("",
+ index.FindWebFeed(MakePageInfo(GURL("https://sub.baz.com/path")))
+ .web_feed_id);
+}
+
+TEST(WebFeedIndex, FindWebFeedCriteriaPathMatch) {
+ WebFeedIndex index;
+ FeedStore::WebFeedStartupData startup_data;
{
- auto* feed = startup_data.recommended_feed_index.add_entries();
- feed->set_web_feed_id("recommended-id");
- *feed->add_matchers() = MakeDomainMatcher("foo.com");
+ auto* feed = startup_data.subscribed_web_feeds.add_feeds();
+ feed->set_web_feed_id("id");
+ *feed->add_matchers()->add_criteria() =
+ RegexCriteria(Criteria::PAGE_URL_PATH_MATCH, "[fb]oobar");
+ *feed->add_matchers()->add_criteria() =
+ TextCriteria(Criteria::PAGE_URL_PATH_MATCH, "/baz");
}
- index.Populate(startup_data.recommended_feed_index);
index.Populate(startup_data.subscribed_web_feeds);
- EXPECT_EQ("sub-id",
- index.FindWebFeedForUrl(GURL("https://foo.com")).web_feed_id);
+ EXPECT_EQ(
+ "id",
+ index.FindWebFeed(MakePageInfo(GURL("https://test.com/fun-foobar-fun")))
+ .web_feed_id);
+ EXPECT_EQ("id",
+ index.FindWebFeed(MakePageInfo(GURL("https://test.com/boobar")))
+ .web_feed_id);
+ EXPECT_EQ("id", index.FindWebFeed(MakePageInfo(GURL("https://test.com/baz")))
+ .web_feed_id);
+
+ EXPECT_EQ("", index.FindWebFeed(MakePageInfo(GURL("https://test.com/path")))
+ .web_feed_id);
+
+ EXPECT_EQ(
+ "",
+ index.FindWebFeed(MakePageInfo(GURL("https://test.com"))).web_feed_id);
+
+ EXPECT_EQ("", index.FindWebFeed(MakePageInfo(GURL("https://foobar.com/path")))
+ .web_feed_id);
+
+ EXPECT_EQ("", index.FindWebFeed(MakePageInfo(GURL("https://test.com/baz-")))
+ .web_feed_id);
+}
+
+TEST(WebFeedIndex, FindWebFeedCriteriaRssUrlMatch) {
+ // Visited page URL doesn't matter for this test, because we're using RSS URL
+ // match criteria.
+ const GURL PAGE_URL = GURL("https://somepage");
+ WebFeedIndex index;
+ FeedStore::WebFeedStartupData startup_data;
+ {
+ auto* feed = startup_data.subscribed_web_feeds.add_feeds();
+ feed->set_web_feed_id("id");
+ *feed->add_matchers()->add_criteria() =
+ RegexCriteria(Criteria::RSS_URL_MATCH, "[fb]oobar");
+ *feed->add_matchers()->add_criteria() =
+ TextCriteria(Criteria::RSS_URL_MATCH, "https://plaintext/rss.xml");
+ }
+ index.Populate(startup_data.subscribed_web_feeds);
+
+ EXPECT_EQ("id",
+ index
+ .FindWebFeed(MakePageInfo(
+ PAGE_URL, {GURL("https://test.com/fun-foobar-fun.xml")}))
+ .web_feed_id);
+ EXPECT_EQ("id", index
+ .FindWebFeed(MakePageInfo(
+ PAGE_URL, {GURL("https://test.com/boobar.xml")}))
+ .web_feed_id);
+ EXPECT_EQ("id", index
+ .FindWebFeed(MakePageInfo(
+ PAGE_URL, {GURL("https://plaintext/rss.xml")}))
+ .web_feed_id);
+ EXPECT_EQ("id", index
+ .FindWebFeed(MakePageInfo(
+ PAGE_URL, {GURL("https://notmatch"),
+ GURL("https://plaintext/rss.xml")}))
+ .web_feed_id);
+
+ EXPECT_EQ(
+ "",
+ index.FindWebFeed(MakePageInfo(PAGE_URL, {GURL("https://test.com/path")}))
+ .web_feed_id);
+ EXPECT_EQ(
+ "", index.FindWebFeed(MakePageInfo(PAGE_URL, {GURL("https://test.com")}))
+ .web_feed_id);
+ EXPECT_EQ("", index
+ .FindWebFeed(MakePageInfo(
+ PAGE_URL, {GURL("https://plaintext/rss.xml2")}))
+ .web_feed_id);
+}
+
+TEST(WebFeedIndex, MultipleConditionsRequiredForMatch) {
+ WebFeedIndex index;
+ FeedStore::WebFeedStartupData startup_data;
+ {
+ auto* feed = startup_data.subscribed_web_feeds.add_feeds();
+ feed->set_web_feed_id("id");
+ feedwire::webfeed::WebFeedMatcher* matcher = feed->add_matchers();
+ {
+ feedwire::webfeed::WebFeedMatcher::Criteria* criteria =
+ matcher->add_criteria();
+ criteria->set_criteria_type(
+ feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_HOST_SUFFIX);
+ criteria->set_text("foo.com");
+ }
+ {
+ feedwire::webfeed::WebFeedMatcher::Criteria* criteria =
+ matcher->add_criteria();
+ criteria->set_criteria_type(
+ feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_PATH_MATCH);
+ criteria->set_text("/fun");
+ }
+ }
+ {
+ auto* feed = startup_data.subscribed_web_feeds.add_feeds();
+ feed->set_web_feed_id("id2");
+ feedwire::webfeed::WebFeedMatcher* matcher = feed->add_matchers();
+ {
+ feedwire::webfeed::WebFeedMatcher::Criteria* criteria =
+ matcher->add_criteria();
+ criteria->set_criteria_type(
+ feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_HOST_SUFFIX);
+ criteria->set_text("bar.com");
+ }
+ {
+ feedwire::webfeed::WebFeedMatcher::Criteria* criteria =
+ matcher->add_criteria();
+ criteria->set_criteria_type(
+ feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_PATH_MATCH);
+ criteria->set_text("/woo");
+ }
+ }
+ {
+ auto* feed = startup_data.subscribed_web_feeds.add_feeds();
+ feed->set_web_feed_id("id3");
+ feedwire::webfeed::WebFeedMatcher* matcher = feed->add_matchers();
+ {
+ feedwire::webfeed::WebFeedMatcher::Criteria* criteria =
+ matcher->add_criteria();
+ criteria->set_criteria_type(
+ feedwire::webfeed::WebFeedMatcher::Criteria::PAGE_URL_HOST_SUFFIX);
+ criteria->set_text("feed.com");
+ }
+ {
+ feedwire::webfeed::WebFeedMatcher::Criteria* criteria =
+ matcher->add_criteria();
+ criteria->set_criteria_type(
+ feedwire::webfeed::WebFeedMatcher::Criteria::RSS_URL_MATCH);
+ criteria->set_text("https://rss1.com/rss.xml");
+ }
+ {
+ feedwire::webfeed::WebFeedMatcher::Criteria* criteria =
+ matcher->add_criteria();
+ criteria->set_criteria_type(
+ feedwire::webfeed::WebFeedMatcher::Criteria::RSS_URL_MATCH);
+ criteria->set_text("https://rss2.com/rss.xml");
+ }
+ }
+ index.Populate(startup_data.subscribed_web_feeds);
+
+ EXPECT_EQ(
+ "id",
+ index.FindWebFeed(MakePageInfo(GURL("https://foo.com/fun"))).web_feed_id);
+ EXPECT_EQ(
+ "id",
+ index.FindWebFeed(MakePageInfo(GURL("http://sub.foo.com/fun?query")))
+ .web_feed_id);
+ EXPECT_EQ(
+ "id2",
+ index.FindWebFeed(MakePageInfo(GURL("https://bar.com/woo"))).web_feed_id);
+ EXPECT_EQ(
+ "id2",
+ index.FindWebFeed(MakePageInfo(GURL("http://sub.bar.com/woo?query")))
+ .web_feed_id);
+ EXPECT_EQ("id3",
+ index
+ .FindWebFeed(MakePageInfo(GURL("http://feed.com/"),
+ {GURL("https://rss2.com/rss.xml"),
+ GURL("https://rss1.com/rss.xml")}))
+ .web_feed_id);
+
+ EXPECT_EQ("", index.FindWebFeed(MakePageInfo(GURL("https://fooo.com/fun")))
+ .web_feed_id);
+ EXPECT_EQ("", index.FindWebFeed(MakePageInfo(GURL("https://foo.com/fuun")))
+ .web_feed_id);
+ EXPECT_EQ(
+ "",
+ index.FindWebFeed(MakePageInfo(GURL("https://bar.com/fun"))).web_feed_id);
+ EXPECT_EQ(
+ "",
+ index.FindWebFeed(MakePageInfo(GURL("https://foo.com/woo"))).web_feed_id);
+ EXPECT_EQ("",
+ index
+ .FindWebFeed(MakePageInfo(GURL("http://feed.com/"),
+ {GURL("https://rss1.com/rss.xml")}))
+ .web_feed_id);
+ EXPECT_EQ("",
+ index
+ .FindWebFeed(MakePageInfo(GURL("http://feed.com/"),
+ {GURL("https://rss2.com/rss.xml")}))
+ .web_feed_id);
}
} // namespace
diff --git a/chromium/components/feed/feed_feature_list.cc b/chromium/components/feed/feed_feature_list.cc
index 6a0ec02664c..29c096a0859 100644
--- a/chromium/components/feed/feed_feature_list.cc
+++ b/chromium/components/feed/feed_feature_list.cc
@@ -55,6 +55,8 @@ const base::Feature kInterestFeedSpinnerAlwaysAnimate{
const base::Feature kFeedShare{"FeedShare", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kWebFeed{"WebFeed", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kDiscoFeedEndpoint{"DiscoFeedEndpoint",
+ base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kXsurfaceMetricsReporting{
"XsurfaceMetricsReporting", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromium/components/feed/feed_feature_list.h b/chromium/components/feed/feed_feature_list.h
index 229c30e3604..67b4525fffc 100644
--- a/chromium/components/feed/feed_feature_list.h
+++ b/chromium/components/feed/feed_feature_list.h
@@ -46,6 +46,9 @@ extern const base::Feature kFeedShare;
// Feature that allows users to keep up with and consume web content.
extern const base::Feature kWebFeed;
+// Use the new DiscoFeed endpoint.
+extern const base::Feature kDiscoFeedEndpoint;
+
// Feature that enables xsurface to provide the metrics reporting state to an
// xsurface feed.
extern const base::Feature kXsurfaceMetricsReporting;
diff --git a/chromium/components/feed/mojom/BUILD.gn b/chromium/components/feed/mojom/BUILD.gn
new file mode 100644
index 00000000000..9587fa15cb5
--- /dev/null
+++ b/chromium/components/feed/mojom/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojo_bindings") {
+ disable_variants = true
+
+ sources = [ "rss_link_reader.mojom" ]
+
+ deps = []
+
+ public_deps = [
+ "//mojo/public/mojom/base",
+ "//url/mojom:url_mojom_gurl",
+ ]
+}
diff --git a/chromium/components/feed/mojom/rss_link_reader.mojom b/chromium/components/feed/mojom/rss_link_reader.mojom
new file mode 100644
index 00000000000..f902ddc4c8d
--- /dev/null
+++ b/chromium/components/feed/mojom/rss_link_reader.mojom
@@ -0,0 +1,19 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+module feed.mojom;
+
+import "url/mojom/url.mojom";
+
+struct RssLinks {
+ // URL of the page.
+ url.mojom.Url page_url;
+ // List of RSS URLs within the page's <head>.
+ array<url.mojom.Url> links;
+};
+
+// One instance per main frame on the renderer.
+interface RssLinkReader {
+ // Scans the document for RSS links, and returns them.
+ GetRssLinks() => (RssLinks rss_links);
+};
diff --git a/chromium/components/feedback/BUILD.gn b/chromium/components/feedback/BUILD.gn
index f108f6e054c..7dd3bcb211e 100644
--- a/chromium/components/feedback/BUILD.gn
+++ b/chromium/components/feedback/BUILD.gn
@@ -28,8 +28,9 @@ static_library("feedback") {
"tracing_manager.h",
]
+ public_deps = [ "//base" ]
+
deps = [
- "//base",
"//build:chromeos_buildflags",
"//components/feedback/proto",
"//components/keyed_service/core",
diff --git a/chromium/components/feedback/content/content_tracing_manager.cc b/chromium/components/feedback/content/content_tracing_manager.cc
index fb40e22b789..fbbe9b09fa9 100644
--- a/chromium/components/feedback/content/content_tracing_manager.cc
+++ b/chromium/components/feedback/content/content_tracing_manager.cc
@@ -10,6 +10,7 @@
#include "base/memory/ref_counted_memory.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_config.h"
#include "components/feedback/feedback_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/tracing_controller.h"
diff --git a/chromium/components/feedback/content/content_tracing_manager.h b/chromium/components/feedback/content/content_tracing_manager.h
index 31d9f1ace30..19c1d0f9ff3 100644
--- a/chromium/components/feedback/content/content_tracing_manager.h
+++ b/chromium/components/feedback/content/content_tracing_manager.h
@@ -13,7 +13,6 @@
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
-#include "base/values.h"
// This class is used to manage performance metrics that can be attached to
// feedback reports. This class is a Singleton that is owned by the preference
diff --git a/chromium/components/feedback/content/feedback_uploader_factory.cc b/chromium/components/feedback/content/feedback_uploader_factory.cc
index 916b7c911a4..131e70df210 100644
--- a/chromium/components/feedback/content/feedback_uploader_factory.cc
+++ b/chromium/components/feedback/content/feedback_uploader_factory.cc
@@ -19,7 +19,7 @@ namespace {
// be expensive, this is delayed so that it does not happen during startup.
scoped_refptr<network::SharedURLLoaderFactory>
CreateURLLoaderFactoryForBrowserContext(content::BrowserContext* context) {
- return content::BrowserContext::GetDefaultStoragePartition(context)
+ return context->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess();
}
diff --git a/chromium/components/feedback/redaction_tool.cc b/chromium/components/feedback/redaction_tool.cc
index e34262f8e5e..deaad295bad 100644
--- a/chromium/components/feedback/redaction_tool.cc
+++ b/chromium/components/feedback/redaction_tool.cc
@@ -484,9 +484,9 @@ std::string RedactionTool::RedactMACAddresses(const std::string& input) {
while (FindAndConsumeAndGetSkipped(&text, *mac_re, &skipped, &oui, &nic)) {
// 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());
+ std::string oui_string = base::ToLowerASCII(std::string(oui));
base::ReplaceChars(oui_string, kMacSeparatorChars, ":", &oui_string);
- std::string nic_string = base::ToLowerASCII(nic.as_string());
+ std::string nic_string = base::ToLowerASCII(std::string(nic));
base::ReplaceChars(nic_string, kMacSeparatorChars, ":", &nic_string);
std::string mac = oui_string + ":" + nic_string;
std::string replacement_mac = mac_addresses_[mac];
@@ -541,9 +541,9 @@ std::string RedactionTool::RedactHashes(const std::string& input) {
// Look up the hash value address in the map of replacements.
std::string hash_prefix_string =
- base::ToLowerASCII(hash_prefix.as_string());
+ base::ToLowerASCII(std::string(hash_prefix));
std::string hash =
- hash_prefix_string + base::ToLowerASCII(hash_suffix.as_string());
+ hash_prefix_string + base::ToLowerASCII(std::string(hash_suffix));
std::string replacement_hash = hashes_[hash];
if (replacement_hash.empty()) {
// If not found, build up a replacement value.
@@ -644,7 +644,7 @@ std::string RedactionTool::RedactCustomPatternWithContext(
re2::StringPiece pre_match, pre_matched_id, matched_id, post_matched_id;
while (FindAndConsumeAndGetSkipped(&text, *re, &skipped, &pre_matched_id,
&matched_id, &post_matched_id)) {
- std::string matched_id_as_string = matched_id.as_string();
+ std::string matched_id_as_string(matched_id);
std::string replacement_id;
if (identifier_space->count(matched_id_as_string) == 0) {
// The weird NumberToString trick is because Windows does not like
@@ -732,7 +732,7 @@ std::string RedactionTool::RedactCustomPatternWithoutContext(
matched_id.AppendToString(&result);
continue;
}
- std::string matched_id_as_string = matched_id.as_string();
+ std::string matched_id_as_string(matched_id);
std::string replacement_id;
if (identifier_space->count(matched_id_as_string) == 0) {
replacement_id = MaybeScrubIPAddress(matched_id_as_string);
diff --git a/chromium/components/feedback/redaction_tool.h b/chromium/components/feedback/redaction_tool.h
index f08d8c62717..7159caa66e4 100644
--- a/chromium/components/feedback/redaction_tool.h
+++ b/chromium/components/feedback/redaction_tool.h
@@ -10,7 +10,6 @@
#include <string>
#include <vector>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
@@ -35,6 +34,12 @@ struct CustomPatternWithAlias {
// using custom patterns.
class RedactionTool {
public:
+ // Disallow copy or move
+ RedactionTool(const RedactionTool&) = delete;
+ RedactionTool& operator=(const RedactionTool&) = delete;
+ RedactionTool(RedactionTool&&) = delete;
+ RedactionTool& operator=(RedactionTool&&) = delete;
+
// |first_party_extension_ids| is a null terminated array of all the 1st
// party extension IDs whose URLs won't be redacted. It is OK to pass null for
// that value if it's OK to redact those URLs or they won't be present.
@@ -96,8 +101,6 @@ class RedactionTool {
std::map<std::string, std::unique_ptr<re2::RE2>> regexp_cache_;
SEQUENCE_CHECKER(sequence_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(RedactionTool);
};
// A container for a RedactionTool that is thread-safely ref-countable.
diff --git a/chromium/components/find_in_page/android/DIR_METADATA b/chromium/components/find_in_page/android/DIR_METADATA
deleted file mode 100644
index 831a23a2b5c..00000000000
--- a/chromium/components/find_in_page/android/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "UI>Browser>FindInPage"
-}
diff --git a/chromium/components/flags_ui/flags_state.cc b/chromium/components/flags_ui/flags_state.cc
index 2cfa74e9fb1..4a1e03257df 100644
--- a/chromium/components/flags_ui/flags_state.cc
+++ b/chromium/components/flags_ui/flags_state.cc
@@ -190,10 +190,8 @@ std::set<std::string> TokenizeOriginList(const std::string& value) {
base::StringTokenizer tokenizer(input, delimiters);
std::set<std::string> origin_strings;
while (tokenizer.GetNext()) {
- const std::string token = tokenizer.token();
- if (token.empty()) {
- continue;
- }
+ base::StringPiece token = tokenizer.token_piece();
+ DCHECK(!token.empty());
const GURL url(token);
if (!url.is_valid() ||
(!url.SchemeIsHTTPOrHTTPS() && !url.SchemeIsWSOrWSS())) {
@@ -458,7 +456,7 @@ void FlagsState::RemoveFlagsSwitches(
// For any featrue name in |features| that is not in |switch_added_values| -
// i.e. it wasn't added by about_flags code, add it to |remaining_features|.
for (const auto& feature : features) {
- if (!base::Contains(switch_added_values, feature.as_string()))
+ if (!base::Contains(switch_added_values, std::string(feature)))
remaining_features.push_back(feature);
}
diff --git a/chromium/components/flags_ui/flags_ui_constants.cc b/chromium/components/flags_ui/flags_ui_constants.cc
index cc8fa4b6b58..8e51c44c7d0 100644
--- a/chromium/components/flags_ui/flags_ui_constants.cc
+++ b/chromium/components/flags_ui/flags_ui_constants.cc
@@ -21,7 +21,6 @@ const char kRestartBrowser[] = "restartBrowser";
const char kFlagsRestartButton[] = "flagsRestartButton";
const char kFlagsRestartNotice[] = "flagsRestartNotice";
const char kNeedsRestart[] = "needsRestart";
-const char kReturnExperimentalFeatures[] = "returnExperimentalFeatures";
const char kShowBetaChannelPromotion[] = "showBetaChannelPromotion";
const char kShowDevChannelPromotion[] = "showDevChannelPromotion";
const char kShowOwnerWarning[] = "showOwnerWarning";
diff --git a/chromium/components/flags_ui/flags_ui_constants.h b/chromium/components/flags_ui/flags_ui_constants.h
index 93917d6d31b..76e2397c81e 100644
--- a/chromium/components/flags_ui/flags_ui_constants.h
+++ b/chromium/components/flags_ui/flags_ui_constants.h
@@ -25,7 +25,6 @@ extern const char kRestartBrowser[];
extern const char kFlagsRestartButton[];
extern const char kFlagsRestartNotice[];
extern const char kNeedsRestart[];
-extern const char kReturnExperimentalFeatures[];
extern const char kShowBetaChannelPromotion[];
extern const char kShowDevChannelPromotion[];
extern const char kShowOwnerWarning[];
diff --git a/chromium/components/flags_ui/flags_ui_metrics.h b/chromium/components/flags_ui/flags_ui_metrics.h
index 792a32f0295..613b92709af 100644
--- a/chromium/components/flags_ui/flags_ui_metrics.h
+++ b/chromium/components/flags_ui/flags_ui_metrics.h
@@ -32,4 +32,4 @@ extern const base::HistogramBase::Sample kBadSwitchFormatHistogramId;
} // namespace flags_ui
-#endif // COMPONENTS_FLAGS_UI_FLAGS_UI_WITCHES_H_
+#endif // COMPONENTS_FLAGS_UI_FLAGS_UI_METRICS_H_
diff --git a/chromium/components/flags_ui/pref_service_flags_storage.cc b/chromium/components/flags_ui/pref_service_flags_storage.cc
index f73fb1c6d62..007ed343050 100644
--- a/chromium/components/flags_ui/pref_service_flags_storage.cc
+++ b/chromium/components/flags_ui/pref_service_flags_storage.cc
@@ -25,10 +25,9 @@ std::set<std::string> PrefServiceFlagsStorage::GetFlags() const {
const base::ListValue* enabled_experiments =
prefs_->GetList(prefs::kAboutFlagsEntries);
std::set<std::string> flags;
- for (auto it = enabled_experiments->begin(); it != enabled_experiments->end();
- ++it) {
+ for (const auto& entry : enabled_experiments->GetList()) {
std::string experiment_name;
- if (!it->GetAsString(&experiment_name)) {
+ if (!entry.GetAsString(&experiment_name)) {
LOG(WARNING) << "Invalid entry in " << prefs::kAboutFlagsEntries;
continue;
}
diff --git a/chromium/components/flags_ui/resources/BUILD.gn b/chromium/components/flags_ui/resources/BUILD.gn
index 1c9a6f40dce..6b0dc4dd5bd 100644
--- a/chromium/components/flags_ui/resources/BUILD.gn
+++ b/chromium/components/flags_ui/resources/BUILD.gn
@@ -5,15 +5,14 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- uses_legacy_modules = true
deps = [ ":flags" ]
}
js_library("flags") {
deps = [
"//third_party/jstemplate:jstemplate",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:util",
- "//ui/webui/resources/js/cr/ui:focus_outline_manager",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:util.m",
+ "//ui/webui/resources/js/cr/ui:focus_outline_manager.m",
]
}
diff --git a/chromium/components/flags_ui/resources/flags.css b/chromium/components/flags_ui/resources/flags.css
index 4177223058a..28140954206 100644
--- a/chromium/components/flags_ui/resources/flags.css
+++ b/chromium/components/flags_ui/resources/flags.css
@@ -172,7 +172,7 @@ button {
}
#search {
- background: var(--input-background) url(../../../ui/webui/resources/images/icon_search.svg) no-repeat 8px 50%;
+ background: var(--input-background) url(chrome://resources/images/icon_search.svg) no-repeat 8px 50%;
border: 1px solid transparent;
border-radius: 3px;
box-sizing: border-box;
@@ -188,7 +188,7 @@ button {
@media (prefers-color-scheme: dark) {
#search {
- background-image: url(../../../ui/webui/resources/images/dark/icon_search.svg);
+ background-image: url(chrome://resources/images/dark/icon_search.svg);
}
#search::placeholder {
@@ -202,7 +202,7 @@ button {
}
.clear-search {
- -webkit-mask-image: url(../../../ui/webui/resources/images/icon_cancel.svg);
+ -webkit-mask-image: url(chrome://resources/images/icon_cancel.svg);
-webkit-mask-size: 20px;
background: var(--secondary-color);
border: 0;
diff --git a/chromium/components/flags_ui/resources/flags.html b/chromium/components/flags_ui/resources/flags.html
index c45a0b30b3d..61501ec8e36 100644
--- a/chromium/components/flags_ui/resources/flags.html
+++ b/chromium/components/flags_ui/resources/flags.html
@@ -14,16 +14,8 @@
<if expr="is_ios">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1, maximum-scale=1">
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
- <!-- TODO(crbug.com/487000): Remove this once injected by web. -->
- <script src="chrome://resources/js/ios/web_ui.js"></script>
</if>
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://resources/js/cr/ui/focus_outline_manager.js"></script>
-<script src="chrome://resources/js/assert.js"></script>
-<script src="chrome://resources/js/util.js"></script>
-<script src="chrome://resources/js/load_time_data.js"></script>
-<script src="strings.js"></script>
</head>
<body>
<div id="header">
@@ -228,7 +220,6 @@
</div>
</div>
</div>
-<script src="flags.js"></script>
-<script src="chrome://resources/js/jstemplate_compiled.js"></script>
+<script type="module" src="flags.js"></script>
</body>
</html>
diff --git a/chromium/components/flags_ui/resources/flags.js b/chromium/components/flags_ui/resources/flags.js
index 7030f4a1ca4..b3062814d3b 100644
--- a/chromium/components/flags_ui/resources/flags.js
+++ b/chromium/components/flags_ui/resources/flags.js
@@ -2,6 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// <if expr="is_ios">
+import 'chrome://resources/js/ios/web_ui.js';
+// </if>
+
+import 'chrome://resources/js/jstemplate_compiled.js';
+import './strings.m.js';
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {isIOS, sendWithPromise} from 'chrome://resources/js/cr.m.js';
+import {FocusOutlineManager} from 'chrome://resources/js/cr/ui/focus_outline_manager.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {$} from 'chrome://resources/js/util.m.js';
+
let lastChanged = null;
let lastFocused = null;
const restartButton = $('experiment-restart-button');
@@ -9,8 +22,9 @@ const restartButton = $('experiment-restart-button');
/** @type {?function():void} */
let experimentalFeaturesResolver = null;
+// Exported on |window| since this is needed by tests.
/** @type {!Promise} */
-const experimentalFeaturesReady = new Promise(resolve => {
+window.experimentalFeaturesReadyForTest = new Promise(resolve => {
experimentalFeaturesResolver = resolve;
});
@@ -84,7 +98,7 @@ function renderTemplate(experimentalFeaturesData) {
};
}
- assert(restartButton || cr.isIOS);
+ assert(restartButton || isIOS);
if (restartButton) {
restartButton.onclick = restartBrowser;
}
@@ -171,7 +185,8 @@ function highlightReferencedFlag() {
* |returnExperimentalFeatures()| will be called with reply.
*/
function requestExperimentalFeaturesData() {
- chrome.send('requestExperimentalFeatures');
+ sendWithPromise('requestExperimentalFeatures')
+ .then(returnExperimentalFeatures);
}
/** Restart browser and restore tabs. */
@@ -659,7 +674,7 @@ document.addEventListener('DOMContentLoaded', function() {
// Get and display the data upon loading.
requestExperimentalFeaturesData();
setupRestartButton();
- cr.ui.FocusOutlineManager.forDocument(document);
+ FocusOutlineManager.forDocument(document);
});
// Update the highlighted flag when the hash changes.
diff --git a/chromium/components/full_restore/app_launch_info.h b/chromium/components/full_restore/app_launch_info.h
index c86cda8ffe6..bf93ea5e206 100644
--- a/chromium/components/full_restore/app_launch_info.h
+++ b/chromium/components/full_restore/app_launch_info.h
@@ -9,8 +9,8 @@
#include "base/component_export.h"
#include "base/files/file_path.h"
-#include "base/optional.h"
#include "components/services/app_service/public/mojom/types.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h"
@@ -53,15 +53,15 @@ struct COMPONENT_EXPORT(FULL_RESTORE) AppLaunchInfo {
~AppLaunchInfo();
std::string app_id;
- base::Optional<int32_t> window_id;
- base::Optional<int32_t> event_flag;
- base::Optional<int32_t> container;
- base::Optional<int32_t> disposition;
- base::Optional<int32_t> arc_session_id;
- base::Optional<int64_t> display_id;
- base::Optional<GURL> url;
- base::Optional<std::vector<base::FilePath>> file_paths;
- base::Optional<apps::mojom::IntentPtr> intent;
+ absl::optional<int32_t> window_id;
+ absl::optional<int32_t> event_flag;
+ absl::optional<int32_t> container;
+ absl::optional<int32_t> disposition;
+ absl::optional<int32_t> arc_session_id;
+ absl::optional<int64_t> display_id;
+ absl::optional<GURL> url;
+ absl::optional<std::vector<base::FilePath>> file_paths;
+ absl::optional<apps::mojom::IntentPtr> intent;
};
} // namespace full_restore
diff --git a/chromium/components/full_restore/app_restore_data.cc b/chromium/components/full_restore/app_restore_data.cc
index 12e83c4d075..10e41824155 100644
--- a/chromium/components/full_restore/app_restore_data.cc
+++ b/chromium/components/full_restore/app_restore_data.cc
@@ -31,6 +31,18 @@ constexpr char kVisibleOnAllWorkspacesKey[] = "all_desk";
constexpr char kRestoreBoundsKey[] = "restore_bounds";
constexpr char kCurrentBoundsKey[] = "current_bounds";
constexpr char kWindowStateTypeKey[] = "window_state_type";
+constexpr char kMinimumSizeKey[] = "min_size";
+constexpr char kMaximumSizeKey[] = "max_size";
+constexpr char kPrimaryColorKey[] = "primary_color";
+constexpr char kStatusBarColorKey[] = "status_bar_color";
+
+// Converts |size| to base::Value, e.g. { 100, 300 }.
+base::Value ConvertSizeToValue(const gfx::Size& size) {
+ base::Value size_list(base::Value::Type::LIST);
+ size_list.Append(base::Value(size.width()));
+ size_list.Append(base::Value(size.height()));
+ return size_list;
+}
// Converts |rect| to base::Value, e.g. { 0, 100, 200, 300 }.
base::Value ConvertRectToValue(const gfx::Rect& rect) {
@@ -42,25 +54,42 @@ base::Value ConvertRectToValue(const gfx::Rect& rect) {
return rect_list;
}
+// Converts |uint32_t| to base::Value in string, e.g 123 to "123".
+base::Value ConvertUintToValue(uint32_t number) {
+ return base::Value(base::NumberToString(number));
+}
+
// Gets bool value from base::DictionaryValue, e.g. { "key": true } returns
// true.
-base::Optional<bool> GetBoolValueFromDict(const base::DictionaryValue& dict,
+absl::optional<bool> GetBoolValueFromDict(const base::DictionaryValue& dict,
const std::string& key_name) {
- return dict.HasKey(key_name) ? dict.FindBoolKey(key_name) : base::nullopt;
+ return dict.HasKey(key_name) ? dict.FindBoolKey(key_name) : absl::nullopt;
}
// Gets int value from base::DictionaryValue, e.g. { "key": 100 } returns 100.
-base::Optional<int32_t> GetIntValueFromDict(const base::DictionaryValue& dict,
+absl::optional<int32_t> GetIntValueFromDict(const base::DictionaryValue& dict,
const std::string& key_name) {
- return dict.HasKey(key_name) ? dict.FindIntKey(key_name) : base::nullopt;
+ return dict.HasKey(key_name) ? dict.FindIntKey(key_name) : absl::nullopt;
+}
+
+// Gets uint32_t value from base::DictionaryValue, e.g. { "key": "123" } returns
+// 123.
+absl::optional<uint32_t> GetUIntValueFromDict(const base::DictionaryValue& dict,
+ const std::string& key_name) {
+ uint32_t result = 0;
+ if (!dict.HasKey(key_name) ||
+ !base::StringToUint(dict.FindStringKey(key_name)->c_str(), &result)) {
+ return absl::nullopt;
+ }
+ return result;
}
// Gets display id from base::DictionaryValue, e.g. { "display_id": "22000000" }
// returns 22000000.
-base::Optional<int64_t> GetDisplayIdFromDict(
+absl::optional<int64_t> GetDisplayIdFromDict(
const base::DictionaryValue& dict) {
if (!dict.HasKey(kDisplayIdKey))
- return base::nullopt;
+ return absl::nullopt;
const std::string* display_id_str = dict.FindStringKey(kDisplayIdKey);
int64_t display_id_value;
@@ -69,21 +98,21 @@ base::Optional<int64_t> GetDisplayIdFromDict(
return display_id_value;
}
- return base::nullopt;
+ return absl::nullopt;
}
// Gets std::vector<base::FilePath> from base::DictionaryValue, e.g.
// {"file_paths": { "aa.cc", "bb.h", ... }} returns
// std::vector<base::FilePath>{"aa.cc", "bb.h", ...}.
-base::Optional<std::vector<base::FilePath>> GetFilePathsFromDict(
+absl::optional<std::vector<base::FilePath>> GetFilePathsFromDict(
const base::DictionaryValue& dict) {
if (!dict.HasKey(kFilePathsKey))
- return base::nullopt;
+ return absl::nullopt;
const base::Value* file_paths_value = dict.FindListKey(kFilePathsKey);
if (!file_paths_value || !file_paths_value->is_list() ||
file_paths_value->GetList().empty())
- return base::nullopt;
+ return absl::nullopt;
std::vector<base::FilePath> file_paths;
for (const auto& item : file_paths_value->GetList()) {
@@ -95,36 +124,56 @@ base::Optional<std::vector<base::FilePath>> GetFilePathsFromDict(
return file_paths;
}
+// Gets gfx::Size from base::Value, e.g. { 100, 300 } returns
+// gfx::Size(100, 300).
+absl::optional<gfx::Size> GetSizeFromDict(const base::DictionaryValue& dict,
+ const std::string& key_name) {
+ if (!dict.HasKey(key_name))
+ return absl::nullopt;
+
+ const base::Value* size_value = dict.FindListKey(key_name);
+ if (!size_value || !size_value->is_list() ||
+ size_value->GetList().size() != 2) {
+ return absl::nullopt;
+ }
+
+ std::vector<int> size;
+ for (const auto& item : size_value->GetList())
+ size.push_back(item.GetInt());
+
+ return gfx::Size(size[0], size[1]);
+}
+
// Gets gfx::Rect from base::Value, e.g. { 0, 100, 200, 300 } returns
// gfx::Rect(0, 100, 200, 300).
-base::Optional<gfx::Rect> GetBoundsRectFromDict(
+absl::optional<gfx::Rect> GetBoundsRectFromDict(
const base::DictionaryValue& dict,
const std::string& key_name) {
if (!dict.HasKey(key_name))
- return base::nullopt;
+ return absl::nullopt;
const base::Value* rect_value = dict.FindListKey(key_name);
if (!rect_value || !rect_value->is_list() || rect_value->GetList().empty())
- return base::nullopt;
+ return absl::nullopt;
std::vector<int> rect;
for (const auto& item : rect_value->GetList())
rect.push_back(item.GetInt());
if (rect.size() != 4)
- return base::nullopt;
+ return absl::nullopt;
return gfx::Rect(rect[0], rect[1], rect[2], rect[3]);
}
// Gets WindowStateType from base::DictionaryValue, e.g. { "window_state_type":
// 2 } returns WindowStateType::kMinimized.
-base::Optional<chromeos::WindowStateType> GetWindowStateTypeFromDict(
+absl::optional<chromeos::WindowStateType> GetWindowStateTypeFromDict(
const base::DictionaryValue& dict) {
return dict.HasKey(kWindowStateTypeKey)
- ? base::make_optional(static_cast<chromeos::WindowStateType>(
+ ? absl::make_optional(static_cast<chromeos::WindowStateType>(
dict.FindIntKey(kWindowStateTypeKey).value()))
- : base::nullopt;
+ : absl::nullopt;
}
} // namespace
@@ -152,6 +201,10 @@ AppRestoreData::AppRestoreData(base::Value&& value) {
restore_bounds = GetBoundsRectFromDict(*data_dict, kRestoreBoundsKey);
current_bounds = GetBoundsRectFromDict(*data_dict, kCurrentBoundsKey);
window_state_type = GetWindowStateTypeFromDict(*data_dict);
+ maximum_size = GetSizeFromDict(*data_dict, kMaximumSizeKey);
+ minimum_size = GetSizeFromDict(*data_dict, kMinimumSizeKey);
+ primary_color = GetUIntValueFromDict(*data_dict, kPrimaryColorKey);
+ status_bar_color = GetUIntValueFromDict(*data_dict, kStatusBarColorKey);
if (data_dict->HasKey(kIntentKey)) {
intent = apps_util::ConvertValueToIntent(
@@ -216,6 +269,18 @@ std::unique_ptr<AppRestoreData> AppRestoreData::Clone() const {
if (window_state_type.has_value())
data->window_state_type = window_state_type.value();
+ if (maximum_size.has_value())
+ data->maximum_size = maximum_size.value();
+
+ if (minimum_size.has_value())
+ data->minimum_size = minimum_size.value();
+
+ if (primary_color.has_value())
+ data->primary_color = primary_color.value();
+
+ if (status_bar_color.has_value())
+ data->status_bar_color = status_bar_color.value();
+
return data;
}
@@ -277,6 +342,26 @@ base::Value AppRestoreData::ConvertToValue() const {
static_cast<int>(window_state_type.value()));
}
+ if (maximum_size.has_value()) {
+ launch_info_dict.SetKey(kMaximumSizeKey,
+ ConvertSizeToValue(maximum_size.value()));
+ }
+
+ if (minimum_size.has_value()) {
+ launch_info_dict.SetKey(kMinimumSizeKey,
+ ConvertSizeToValue(minimum_size.value()));
+ }
+
+ if (primary_color.has_value()) {
+ launch_info_dict.SetKey(kPrimaryColorKey,
+ ConvertUintToValue(primary_color.value()));
+ }
+
+ if (status_bar_color.has_value()) {
+ launch_info_dict.SetKey(kStatusBarColorKey,
+ ConvertUintToValue(status_bar_color.value()));
+ }
+
return launch_info_dict;
}
@@ -301,6 +386,17 @@ void AppRestoreData::ModifyWindowInfo(const WindowInfo& window_info) {
if (window_info.display_id.has_value())
display_id = window_info.display_id.value();
+
+ if (window_info.arc_extra_info.has_value()) {
+ minimum_size = window_info.arc_extra_info->minimum_size;
+ maximum_size = window_info.arc_extra_info->maximum_size;
+ }
+}
+
+void AppRestoreData::ModifyThemeColor(uint32_t window_primary_color,
+ uint32_t window_status_bar_color) {
+ primary_color = window_primary_color;
+ status_bar_color = window_status_bar_color;
}
void AppRestoreData::ClearWindowInfo() {
@@ -310,6 +406,10 @@ void AppRestoreData::ClearWindowInfo() {
restore_bounds.reset();
current_bounds.reset();
window_state_type.reset();
+ minimum_size.reset();
+ maximum_size.reset();
+ primary_color.reset();
+ status_bar_color.reset();
}
std::unique_ptr<WindowInfo> AppRestoreData::GetWindowInfo() const {
@@ -333,6 +433,12 @@ std::unique_ptr<WindowInfo> AppRestoreData::GetWindowInfo() const {
if (window_state_type.has_value())
window_info->window_state_type = window_state_type.value();
+ if (maximum_size.has_value() || minimum_size.has_value()) {
+ window_info->arc_extra_info = WindowInfo::ArcExtraInfo();
+ window_info->arc_extra_info->maximum_size = maximum_size;
+ window_info->arc_extra_info->minimum_size = minimum_size;
+ }
+
// Display id is set as the app launch parameter, so we don't need to return
// the display id to restore the display id.
return window_info;
diff --git a/chromium/components/full_restore/app_restore_data.h b/chromium/components/full_restore/app_restore_data.h
index 696b0d5d2ec..7ad70753dfb 100644
--- a/chromium/components/full_restore/app_restore_data.h
+++ b/chromium/components/full_restore/app_restore_data.h
@@ -9,9 +9,9 @@
#include <vector>
#include "base/component_export.h"
-#include "base/optional.h"
#include "chromeos/ui/base/window_state_type.h"
#include "components/services/app_service/public/mojom/types.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
@@ -60,6 +60,10 @@ struct COMPONENT_EXPORT(FULL_RESTORE) AppRestoreData {
// Modifies the window's information based on |window_info|.
void ModifyWindowInfo(const WindowInfo& window_info);
+ // Modifies the window's theme colors.
+ void ModifyThemeColor(uint32_t window_primary_color,
+ uint32_t window_status_bar_color);
+
// Clears the window's information.
void ClearWindowInfo();
@@ -70,21 +74,27 @@ struct COMPONENT_EXPORT(FULL_RESTORE) AppRestoreData {
apps::mojom::WindowInfoPtr GetAppWindowInfo() const;
// App launch parameters.
- base::Optional<int32_t> event_flag;
- base::Optional<int32_t> container;
- base::Optional<int32_t> disposition;
- base::Optional<int64_t> display_id;
- base::Optional<GURL> url;
- base::Optional<apps::mojom::IntentPtr> intent;
- base::Optional<std::vector<base::FilePath>> file_paths;
+ absl::optional<int32_t> event_flag;
+ absl::optional<int32_t> container;
+ absl::optional<int32_t> disposition;
+ absl::optional<int64_t> display_id;
+ absl::optional<GURL> url;
+ absl::optional<apps::mojom::IntentPtr> intent;
+ absl::optional<std::vector<base::FilePath>> file_paths;
// Window's information.
- base::Optional<int32_t> activation_index;
- base::Optional<int32_t> desk_id;
- base::Optional<bool> visible_on_all_workspaces;
- base::Optional<gfx::Rect> restore_bounds;
- base::Optional<gfx::Rect> current_bounds;
- base::Optional<chromeos::WindowStateType> window_state_type;
+ absl::optional<int32_t> activation_index;
+ absl::optional<int32_t> desk_id;
+ absl::optional<bool> visible_on_all_workspaces;
+ absl::optional<gfx::Rect> restore_bounds;
+ absl::optional<gfx::Rect> current_bounds;
+ absl::optional<chromeos::WindowStateType> window_state_type;
+
+ // Extra ARC window's information.
+ absl::optional<gfx::Size> minimum_size;
+ absl::optional<gfx::Size> maximum_size;
+ absl::optional<uint32_t> primary_color;
+ absl::optional<uint32_t> status_bar_color;
};
} // namespace full_restore
diff --git a/chromium/components/full_restore/arc_read_handler.cc b/chromium/components/full_restore/arc_read_handler.cc
index bdf7cb8cb4e..fbf4831b3b3 100644
--- a/chromium/components/full_restore/arc_read_handler.cc
+++ b/chromium/components/full_restore/arc_read_handler.cc
@@ -64,8 +64,8 @@ void ArcReadHandler::OnTaskCreated(const std::string& app_id,
if (window_it != arc_window_candidates_.end()) {
(*window_it)
->SetProperty(full_restore::kRestoreWindowIdKey, restore_window_id);
- (*window_it)->SetProperty(full_restore::kParentToHiddenContainerKey, false);
- FullRestoreInfo::GetInstance()->OnWindowInitialized(*window_it);
+ FullRestoreInfo::GetInstance()->OnARCTaskReadyForUnparentedWindow(
+ *window_it);
arc_window_candidates_.erase(*window_it);
}
}
@@ -94,8 +94,25 @@ std::unique_ptr<WindowInfo> ArcReadHandler::GetWindowInfo(
if (it == window_id_to_app_id_.end())
return nullptr;
- return FullRestoreReadHandler::GetInstance()->GetWindowInfo(
+ auto window_info = FullRestoreReadHandler::GetInstance()->GetWindowInfo(
profile_path_, it->second, restore_window_id);
+
+ // For ARC windows, Android can restore window bounds, so remove the window
+ // bounds from the window info.
+ window_info->current_bounds.reset();
+
+ // For ARC windows, Android can restore window minimized or maximized status,
+ // so remove the WindowStateType from the window info for the minimized and
+ // maximized state.
+ if (window_info->window_state_type.has_value() &&
+ (chromeos::IsMinimizedWindowStateType(
+ window_info->window_state_type.value()) ||
+ window_info->window_state_type.value() ==
+ chromeos::WindowStateType::kMaximized)) {
+ window_info->window_state_type.reset();
+ }
+
+ return window_info;
}
int32_t ArcReadHandler::GetArcRestoreWindowId(int32_t task_id) {
diff --git a/chromium/components/full_restore/arc_save_handler.cc b/chromium/components/full_restore/arc_save_handler.cc
index a776b41a511..51f28af333f 100644
--- a/chromium/components/full_restore/arc_save_handler.cc
+++ b/chromium/components/full_restore/arc_save_handler.cc
@@ -19,7 +19,7 @@ namespace {
// Repeat timer interval between each checking that whether a task is created
// for each app launching.
constexpr base::TimeDelta kCheckCycleInterval =
- base::TimeDelta::FromSeconds(30);
+ base::TimeDelta::FromSeconds(600);
} // namespace
@@ -119,6 +119,17 @@ void ArcSaveHandler::OnTaskDestroyed(int32_t task_id) {
task_id_to_app_id_.erase(task_id);
}
+void ArcSaveHandler::OnTaskThemeColorUpdated(int32_t task_id,
+ uint32_t primary_color,
+ uint32_t status_bar_color) {
+ auto it = task_id_to_app_id_.find(task_id);
+ if (it == task_id_to_app_id_.end())
+ return;
+
+ FullRestoreSaveHandler::GetInstance()->ModifyThemeColor(
+ profile_path_, it->second, task_id, primary_color, status_bar_color);
+}
+
int32_t ArcSaveHandler::GetArcSessionId() {
if (session_id_ >= kArcSessionIdOffsetForRestoredLaunching) {
LOG(WARNING) << "ARC session id is too large: " << session_id_;
diff --git a/chromium/components/full_restore/arc_save_handler.h b/chromium/components/full_restore/arc_save_handler.h
index bfb928ba261..f340dc610ce 100644
--- a/chromium/components/full_restore/arc_save_handler.h
+++ b/chromium/components/full_restore/arc_save_handler.h
@@ -58,6 +58,11 @@ class COMPONENT_EXPORT(FULL_RESTORE) ArcSaveHandler {
// Invoked when the task is destroyed for an ARC app.
void OnTaskDestroyed(int32_t task_id);
+ // Invoked when the task theme color is updated for an ARC app.
+ void OnTaskThemeColorUpdated(int32_t task_id,
+ uint32_t primary_color,
+ uint32_t status_bar_color);
+
// Generates the ARC session id (0 - 1,000,000,000) for ARC apps.
int32_t GetArcSessionId();
diff --git a/chromium/components/full_restore/full_restore_info.cc b/chromium/components/full_restore/full_restore_info.cc
index 7f4d1423b89..54ab3c040dc 100644
--- a/chromium/components/full_restore/full_restore_info.cc
+++ b/chromium/components/full_restore/full_restore_info.cc
@@ -4,11 +4,13 @@
#include "components/full_restore/full_restore_info.h"
+#include "base/containers/contains.h"
#include "base/no_destructor.h"
#include "components/account_id/account_id.h"
namespace full_restore {
+// static
FullRestoreInfo* FullRestoreInfo::GetInstance() {
static base::NoDestructor<FullRestoreInfo> full_restore_info;
return full_restore_info.get();
@@ -27,7 +29,7 @@ void FullRestoreInfo::RemoveObserver(Observer* observer) {
}
bool FullRestoreInfo::ShouldRestore(const AccountId& account_id) {
- return restore_flags_.find(account_id) != restore_flags_.end();
+ return base::Contains(restore_flags_, account_id);
}
void FullRestoreInfo::SetRestoreFlag(const AccountId& account_id,
@@ -44,6 +46,24 @@ void FullRestoreInfo::SetRestoreFlag(const AccountId& account_id,
observer.OnRestoreFlagChanged(account_id, should_restore);
}
+bool FullRestoreInfo::CanPerformRestore(const AccountId& account_id) {
+ return base::Contains(restore_prefs_, account_id);
+}
+
+void FullRestoreInfo::SetRestorePref(const AccountId& account_id,
+ bool could_restore) {
+ if (could_restore == CanPerformRestore(account_id))
+ return;
+
+ if (could_restore)
+ restore_prefs_.insert(account_id);
+ else
+ restore_prefs_.erase(account_id);
+
+ for (auto& observer : observers_)
+ observer.OnRestorePrefChanged(account_id, could_restore);
+}
+
void FullRestoreInfo::OnAppLaunched(aura::Window* window) {
for (auto& observer : observers_)
observer.OnAppLaunched(window);
@@ -59,4 +79,9 @@ void FullRestoreInfo::OnWidgetInitialized(views::Widget* widget) {
observer.OnWidgetInitialized(widget);
}
+void FullRestoreInfo::OnARCTaskReadyForUnparentedWindow(aura::Window* window) {
+ for (auto& observer : observers_)
+ observer.OnARCTaskReadyForUnparentedWindow(window);
+}
+
} // namespace full_restore
diff --git a/chromium/components/full_restore/full_restore_info.h b/chromium/components/full_restore/full_restore_info.h
index f9bda6da2ad..f791bc83c78 100644
--- a/chromium/components/full_restore/full_restore_info.h
+++ b/chromium/components/full_restore/full_restore_info.h
@@ -26,11 +26,9 @@ namespace full_restore {
// FullRestoreInfo is responsible for providing the information for
// FullRestoreInfo::Observer, including:
// 1. Whether we should restore apps and browser windows for |account_id|.
-// 2. Notifies when |window| is ready to be restored, after we have the app
+// 2. Notifies when the restore pref is changed for |account_id|.
+// 3. Notifies when |window| is ready to be restored, after we have the app
// launch information, e.g. a task id for an ARC app
-//
-// TODO(crbug.com/1146900): Get the app launch information, and notify
-// observers.
class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreInfo {
public:
class Observer : public base::CheckedObserver {
@@ -39,6 +37,12 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreInfo {
virtual void OnRestoreFlagChanged(const AccountId& account_id,
bool should_restore) {}
+ // Notifies when the restore pref is changed. If the restore pref is 'Do not
+ // restore', `could_restore` is false. Otherwise, `could_restore` is true,
+ // for the pref 'Always' and 'Ask every time'.
+ virtual void OnRestorePrefChanged(const AccountId& account_id,
+ bool could_restore) {}
+
// Notifies when |window| is ready to save the window info.
//
// When |window| is created, we might not have the app launch info yet. For
@@ -60,6 +64,11 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreInfo {
// ARC task also may not be created yet at this point.
virtual void OnWidgetInitialized(views::Widget* widget) {}
+ // Called once a window which was created without an associated task is now
+ // associated with a ARC task. Will not be called for non-ARC windows, or
+ // ARC windows created with an associated task.
+ virtual void OnARCTaskReadyForUnparentedWindow(aura::Window* window) {}
+
protected:
~Observer() override = default;
};
@@ -83,6 +92,16 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreInfo {
// and the user's choice from the notification for |account_id|.
void SetRestoreFlag(const AccountId& account_id, bool should_restore);
+ // Returns true if the restore pref is 'Always' or 'Ask every time', as we
+ // could restore apps and pages based on the user's choice from the
+ // notification for `account_id`. Otherwise, returns false, when the restore
+ // pref is 'Do not restore'.
+ bool CanPerformRestore(const AccountId& account_id);
+
+ // Sets whether we could restore apps and pages, based on the restore pref
+ // setting for `account_id`.
+ void SetRestorePref(const AccountId& account_id, bool could_restore);
+
// Notifies observers to observe |window| and restore or save the window info
// for |window|.
void OnAppLaunched(aura::Window* window);
@@ -93,6 +112,10 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreInfo {
// Notifies observers that |widget| has been initialized.
void OnWidgetInitialized(views::Widget* widget);
+ // Notifies observers that `window`, which previously had no associated task,
+ // now has one.
+ void OnARCTaskReadyForUnparentedWindow(aura::Window* window);
+
private:
base::ObserverList<Observer> observers_;
@@ -100,6 +123,12 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreInfo {
// added, that means we should restore apps and pages for the account id.
// Otherwise, we should not restore for the account id.
std::set<AccountId> restore_flags_;
+
+ // Records the restore pref. If the account id is not added, that means the
+ // restore pref is 'Do not restore' for the account id. Otherwise, the restore
+ // pref is 'Always' or 'Ask every time', and we could restore for the account
+ // id.
+ std::set<AccountId> restore_prefs_;
};
} // namespace full_restore
diff --git a/chromium/components/full_restore/full_restore_info_unittest.cc b/chromium/components/full_restore/full_restore_info_unittest.cc
index 84c059732b8..bb2322e1b5f 100644
--- a/chromium/components/full_restore/full_restore_info_unittest.cc
+++ b/chromium/components/full_restore/full_restore_info_unittest.cc
@@ -21,21 +21,42 @@ class FakeFullRestoreInfoObserver : public FullRestoreInfo::Observer {
else
restore_flags_.erase(account_id);
- invoked_count_[account_id]++;
+ restore_flag_changed_count_[account_id]++;
}
- bool ShouldRestore(const AccountId& account_id) {
+ void OnRestorePrefChanged(const AccountId& account_id,
+ bool could_restore) override {
+ if (could_restore)
+ restore_prefs_.insert(account_id);
+ else
+ restore_prefs_.erase(account_id);
+
+ restore_pref_changed_count_[account_id]++;
+ }
+
+ bool ShouldRestore(const AccountId& account_id) const {
return restore_flags_.find(account_id) != restore_flags_.end();
}
- int InvokedCount(const AccountId& account_id) {
- auto it = invoked_count_.find(account_id);
- return it != invoked_count_.end() ? it->second : 0;
+ int RestoreFlagChangedCount(const AccountId& account_id) const {
+ auto it = restore_flag_changed_count_.find(account_id);
+ return it != restore_flag_changed_count_.end() ? it->second : 0;
+ }
+
+ bool CanPerformRestore(const AccountId& account_id) const {
+ return restore_prefs_.find(account_id) != restore_prefs_.end();
+ }
+
+ int RestorePrefChangedCount(const AccountId& account_id) const {
+ auto it = restore_pref_changed_count_.find(account_id);
+ return it != restore_pref_changed_count_.end() ? it->second : 0;
}
private:
std::set<AccountId> restore_flags_;
- std::map<AccountId, int> invoked_count_;
+ std::set<AccountId> restore_prefs_;
+ std::map<AccountId, int> restore_flag_changed_count_;
+ std::map<AccountId, int> restore_pref_changed_count_;
};
using FullRestoreInfoTest = testing::Test;
@@ -50,23 +71,56 @@ TEST_F(FullRestoreInfoTest, RestoreFlag) {
FakeFullRestoreInfoObserver observer;
FullRestoreInfo::GetInstance()->AddObserver(&observer);
- // Not change the restore flag
+ // Not change the restore flag.
FullRestoreInfo::GetInstance()->SetRestoreFlag(account_id1, true);
FullRestoreInfo::GetInstance()->SetRestoreFlag(account_id2, false);
- EXPECT_EQ(0, observer.InvokedCount(account_id1));
- EXPECT_EQ(0, observer.InvokedCount(account_id2));
+ EXPECT_EQ(0, observer.RestoreFlagChangedCount(account_id1));
+ EXPECT_EQ(0, observer.RestoreFlagChangedCount(account_id2));
EXPECT_TRUE(FullRestoreInfo::GetInstance()->ShouldRestore(account_id1));
EXPECT_FALSE(FullRestoreInfo::GetInstance()->ShouldRestore(account_id2));
- // Change the restore flag
+ // Change the restore flag.
FullRestoreInfo::GetInstance()->SetRestoreFlag(account_id1, false);
FullRestoreInfo::GetInstance()->SetRestoreFlag(account_id2, true);
- EXPECT_EQ(1, observer.InvokedCount(account_id1));
- EXPECT_EQ(1, observer.InvokedCount(account_id2));
+ EXPECT_EQ(1, observer.RestoreFlagChangedCount(account_id1));
+ EXPECT_EQ(1, observer.RestoreFlagChangedCount(account_id2));
EXPECT_FALSE(observer.ShouldRestore(account_id1));
EXPECT_TRUE(observer.ShouldRestore(account_id2));
EXPECT_FALSE(FullRestoreInfo::GetInstance()->ShouldRestore(account_id1));
EXPECT_TRUE(FullRestoreInfo::GetInstance()->ShouldRestore(account_id2));
+
+ FullRestoreInfo::GetInstance()->RemoveObserver(&observer);
+}
+
+// Test the OnRestorePrefChanged callback when the restore pref is reset.
+TEST_F(FullRestoreInfoTest, RestorePref) {
+ AccountId account_id1 = AccountId::FromUserEmail("aaa@gmail.com");
+ AccountId account_id2 = AccountId::FromUserEmail("bbb@gmail.com");
+
+ FullRestoreInfo::GetInstance()->SetRestorePref(account_id1, true);
+
+ FakeFullRestoreInfoObserver observer;
+ FullRestoreInfo::GetInstance()->AddObserver(&observer);
+
+ // Not change the restore flag.
+ FullRestoreInfo::GetInstance()->SetRestorePref(account_id1, true);
+ FullRestoreInfo::GetInstance()->SetRestorePref(account_id2, false);
+ EXPECT_EQ(0, observer.RestorePrefChangedCount(account_id1));
+ EXPECT_EQ(0, observer.RestorePrefChangedCount(account_id2));
+ EXPECT_TRUE(FullRestoreInfo::GetInstance()->CanPerformRestore(account_id1));
+ EXPECT_FALSE(FullRestoreInfo::GetInstance()->CanPerformRestore(account_id2));
+
+ // Change the restore flag.
+ FullRestoreInfo::GetInstance()->SetRestorePref(account_id1, false);
+ FullRestoreInfo::GetInstance()->SetRestorePref(account_id2, true);
+ EXPECT_EQ(1, observer.RestorePrefChangedCount(account_id1));
+ EXPECT_EQ(1, observer.RestorePrefChangedCount(account_id2));
+ EXPECT_FALSE(observer.CanPerformRestore(account_id1));
+ EXPECT_TRUE(observer.CanPerformRestore(account_id2));
+ EXPECT_FALSE(FullRestoreInfo::GetInstance()->CanPerformRestore(account_id1));
+ EXPECT_TRUE(FullRestoreInfo::GetInstance()->CanPerformRestore(account_id2));
+
+ FullRestoreInfo::GetInstance()->RemoveObserver(&observer);
}
} // namespace full_restore
diff --git a/chromium/components/full_restore/full_restore_read_and_save_unittest.cc b/chromium/components/full_restore/full_restore_read_and_save_unittest.cc
index f53808c6acd..7ec381783f4 100644
--- a/chromium/components/full_restore/full_restore_read_and_save_unittest.cc
+++ b/chromium/components/full_restore/full_restore_read_and_save_unittest.cc
@@ -116,11 +116,11 @@ class FullRestoreSaveHandlerTestApi {
if (it == session_id_to_app_launch_info.end())
return;
- // If there is no task created for the session id in 30 seconds, the session
- // id record is removed. So set the record time as 31 seconds ago, so that
- // CheckTasksForAppLaunching can remove the session id record to simulate
- // the task is not created for the session id.
- it->second.second = it->second.second - base::TimeDelta::FromSeconds(31);
+ // If there is no task created for the session id in 600 seconds, the
+ // session id record is removed. So set the record time as 601 seconds ago,
+ // so that CheckTasksForAppLaunching can remove the session id record to
+ // simulate the task is not created for the session id.
+ it->second.second = it->second.second - base::TimeDelta::FromSeconds(601);
}
base::RepeatingTimer* GetArcCheckTimer() {
diff --git a/chromium/components/full_restore/full_restore_read_handler.cc b/chromium/components/full_restore/full_restore_read_handler.cc
index 84e8dae443d..67dcfb2a374 100644
--- a/chromium/components/full_restore/full_restore_read_handler.cc
+++ b/chromium/components/full_restore/full_restore_read_handler.cc
@@ -156,17 +156,6 @@ bool FullRestoreReadHandler::HasWindowInfo(int32_t restore_window_id) {
}
std::unique_ptr<WindowInfo> FullRestoreReadHandler::GetWindowInfo(
- const base::FilePath& profile_path,
- const std::string& app_id,
- int32_t restore_window_id) {
- auto it = profile_path_to_restore_data_.find(profile_path);
- if (it == profile_path_to_restore_data_.end())
- return nullptr;
-
- return it->second->GetWindowInfo(app_id, restore_window_id);
-}
-
-std::unique_ptr<WindowInfo> FullRestoreReadHandler::GetWindowInfo(
aura::Window* window) {
if (!window)
return nullptr;
@@ -200,7 +189,7 @@ int32_t FullRestoreReadHandler::GetArcRestoreWindowId(int32_t task_id) {
return arc_read_handler_->GetArcRestoreWindowId(task_id);
}
-bool FullRestoreReadHandler::ModifyWidgetParams(
+void FullRestoreReadHandler::ModifyWidgetParams(
int32_t restore_window_id,
views::Widget::InitParams* out_params) {
DCHECK(out_params);
@@ -217,7 +206,7 @@ bool FullRestoreReadHandler::ModifyWidgetParams(
window_info = GetWindowInfo(restore_window_id);
}
if (!window_info)
- return false;
+ return;
if (window_info->activation_index) {
const int32_t index = *window_info->activation_index;
@@ -229,7 +218,8 @@ bool FullRestoreReadHandler::ModifyWidgetParams(
// are shown are activated by default. Force the widget to not be
// activatable; the activation will be restored in ash once the window is
// launched.
- out_params->activatable = views::Widget::InitParams::ACTIVATABLE_NO;
+ out_params->init_properties_container.SetProperty(
+ kLaunchedFromFullRestoreKey, true);
}
if (window_info->desk_id)
out_params->workspace = base::NumberToString(*window_info->desk_id);
@@ -254,8 +244,6 @@ bool FullRestoreReadHandler::ModifyWidgetParams(
base::BindOnce(&FullRestoreReadHandler::OnWidgetInitialized,
weak_factory_.GetWeakPtr(), delegate));
}
-
- return true;
}
int32_t FullRestoreReadHandler::GetArcSessionId() {
@@ -270,6 +258,17 @@ void FullRestoreReadHandler::SetArcSessionIdForWindowId(int32_t arc_session_id,
}
std::unique_ptr<WindowInfo> FullRestoreReadHandler::GetWindowInfo(
+ const base::FilePath& profile_path,
+ const std::string& app_id,
+ int32_t restore_window_id) {
+ auto it = profile_path_to_restore_data_.find(profile_path);
+ if (it == profile_path_to_restore_data_.end())
+ return nullptr;
+
+ return it->second->GetWindowInfo(app_id, restore_window_id);
+}
+
+std::unique_ptr<WindowInfo> FullRestoreReadHandler::GetWindowInfo(
int32_t restore_window_id) {
if (!SessionID::IsValidValue(restore_window_id))
return nullptr;
diff --git a/chromium/components/full_restore/full_restore_read_handler.h b/chromium/components/full_restore/full_restore_read_handler.h
index 8c327221bb6..2a52932941f 100644
--- a/chromium/components/full_restore/full_restore_read_handler.h
+++ b/chromium/components/full_restore/full_restore_read_handler.h
@@ -94,12 +94,6 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreReadHandler
// for Arc app windows.
bool HasWindowInfo(int32_t restore_window_id);
- // Gets the window information from |profile_path| for |app_id| and
- // |restore_window_id|.
- std::unique_ptr<WindowInfo> GetWindowInfo(const base::FilePath& profile_path,
- const std::string& app_id,
- int32_t restore_window_id);
-
// Gets the window information for |window|.
std::unique_ptr<WindowInfo> GetWindowInfo(aura::Window* window);
@@ -114,8 +108,8 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreReadHandler
int32_t GetArcRestoreWindowId(int32_t task_id);
// Modifies `out_params` based on the window info associated with
- // `restore_window_id`. Returns true if `out_params` was modified.
- bool ModifyWidgetParams(int32_t restore_window_id,
+ // `restore_window_id`.
+ void ModifyWidgetParams(int32_t restore_window_id,
views::Widget::InitParams* out_params);
// Generates the ARC session id (1,000,000,001 - INT_MAX) for restored ARC
@@ -127,9 +121,16 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreReadHandler
void SetArcSessionIdForWindowId(int32_t arc_session_id, int32_t window_id);
private:
+ friend class ArcReadHandler;
friend class ::chromeos::full_restore::AppLaunchHandlerBrowserTest;
friend class FullRestoreReadHandlerTestApi;
+ // Gets the window information from |profile_path| for |app_id| and
+ // |restore_window_id|.
+ std::unique_ptr<WindowInfo> GetWindowInfo(const base::FilePath& profile_path,
+ const std::string& app_id,
+ int32_t restore_window_id);
+
// Gets the window information for |restore_window_id| for browser windows and
// Chrome app windows only. This interface can't be used for ARC app windows.
std::unique_ptr<WindowInfo> GetWindowInfo(int32_t restore_window_id);
diff --git a/chromium/components/full_restore/full_restore_save_handler.cc b/chromium/components/full_restore/full_restore_save_handler.cc
index 62f014f7d79..b5690d31836 100644
--- a/chromium/components/full_restore/full_restore_save_handler.cc
+++ b/chromium/components/full_restore/full_restore_save_handler.cc
@@ -203,6 +203,16 @@ void FullRestoreSaveHandler::OnTaskDestroyed(int32_t task_id) {
arc_save_handler_->OnTaskDestroyed(task_id);
}
+void FullRestoreSaveHandler::OnTaskThemeColorUpdated(
+ int32_t task_id,
+ uint32_t primary_color,
+ uint32_t status_bar_color) {
+ if (arc_save_handler_) {
+ arc_save_handler_->OnTaskThemeColorUpdated(task_id, primary_color,
+ status_bar_color);
+ }
+}
+
void FullRestoreSaveHandler::Flush(const base::FilePath& profile_path) {
if (save_running_.find(profile_path) != save_running_.end())
return;
@@ -262,6 +272,24 @@ void FullRestoreSaveHandler::ModifyWindowInfo(
MaybeStartSaveTimer();
}
+void FullRestoreSaveHandler::ModifyThemeColor(
+ const base::FilePath& profile_path,
+ const std::string& app_id,
+ int32_t window_id,
+ uint32_t primary_color,
+ uint32_t status_bar_color) {
+ auto it = profile_path_to_restore_data_.find(profile_path);
+ if (it == profile_path_to_restore_data_.end())
+ return;
+
+ profile_path_to_restore_data_[profile_path].ModifyThemeColor(
+ app_id, window_id, primary_color, status_bar_color);
+
+ pending_save_profile_paths_.insert(profile_path);
+
+ MaybeStartSaveTimer();
+}
+
void FullRestoreSaveHandler::RemoveApp(const base::FilePath& profile_path,
const std::string& app_id) {
auto it = profile_path_to_restore_data_.find(profile_path);
diff --git a/chromium/components/full_restore/full_restore_save_handler.h b/chromium/components/full_restore/full_restore_save_handler.h
index 92a236f86b1..503ab44cf8a 100644
--- a/chromium/components/full_restore/full_restore_save_handler.h
+++ b/chromium/components/full_restore/full_restore_save_handler.h
@@ -79,6 +79,11 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreSaveHandler
// Invoked when the task is destroyed for an ARC app.
void OnTaskDestroyed(int32_t task_id);
+ // Invoked when the task theme color is updated for an ARC app.
+ void OnTaskThemeColorUpdated(int32_t task_id,
+ uint32_t primary_color,
+ uint32_t status_bar_color);
+
// Flushes the full restore file in |profile_path| with the current restore
// data.
void Flush(const base::FilePath& profile_path);
@@ -95,6 +100,14 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreSaveHandler
int32_t window_id,
const WindowInfo& window_info);
+ // Saves |primary_color| and |status_bar_color| to |profile_path| for |app_id|
+ // and |window_id|.
+ void ModifyThemeColor(const base::FilePath& profile_path,
+ const std::string& app_id,
+ int32_t window_id,
+ uint32_t primary_color,
+ uint32_t status_bar_color);
+
// Removes app launching and app windows for an app with the given |app_id|
// from |file_path_to_restore_data_| for |profile_path| .
void RemoveApp(const base::FilePath& profile_path, const std::string& app_id);
diff --git a/chromium/components/full_restore/full_restore_utils.cc b/chromium/components/full_restore/full_restore_utils.cc
index 04a2b2d36a8..d776e2c9a25 100644
--- a/chromium/components/full_restore/full_restore_utils.cc
+++ b/chromium/components/full_restore/full_restore_utils.cc
@@ -22,6 +22,7 @@ DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kRestoreWindowIdKey, 0)
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kAppIdKey, nullptr)
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(int32_t, kActivationIndexKey, nullptr)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kParentToHiddenContainerKey, false)
+DEFINE_UI_CLASS_PROPERTY_KEY(bool, kLaunchedFromFullRestoreKey, false)
void SaveAppLaunchInfo(const base::FilePath& profile_path,
std::unique_ptr<AppLaunchInfo> app_launch_info) {
@@ -64,6 +65,10 @@ bool ShouldRestore(const AccountId& account_id) {
return FullRestoreInfo::GetInstance()->ShouldRestore(account_id);
}
+bool CanPerformRestore(const AccountId& account_id) {
+ return FullRestoreInfo::GetInstance()->CanPerformRestore(account_id);
+}
+
void SetActiveProfilePath(const base::FilePath& profile_path) {
if (!ash::features::IsFullRestoreEnabled())
return;
@@ -80,13 +85,13 @@ bool HasWindowInfo(int32_t restore_window_id) {
restore_window_id);
}
-bool ModifyWidgetParams(int32_t restore_window_id,
+void ModifyWidgetParams(int32_t restore_window_id,
views::Widget::InitParams* out_params) {
if (!ash::features::IsFullRestoreEnabled())
- return false;
+ return;
- return FullRestoreReadHandler::GetInstance()->ModifyWidgetParams(
- restore_window_id, out_params);
+ FullRestoreReadHandler::GetInstance()->ModifyWidgetParams(restore_window_id,
+ out_params);
}
void OnTaskCreated(const std::string& app_id,
@@ -103,4 +108,11 @@ void OnTaskDestroyed(int32_t task_id) {
FullRestoreSaveHandler::GetInstance()->OnTaskDestroyed(task_id);
}
+void OnTaskThemeColorUpdated(int32_t task_id,
+ uint32_t primary_color,
+ uint32_t status_bar_color) {
+ FullRestoreSaveHandler::GetInstance()->OnTaskThemeColorUpdated(
+ task_id, primary_color, status_bar_color);
+}
+
} // namespace full_restore
diff --git a/chromium/components/full_restore/full_restore_utils.h b/chromium/components/full_restore/full_restore_utils.h
index f79c330a143..747a46b2cc9 100644
--- a/chromium/components/full_restore/full_restore_utils.h
+++ b/chromium/components/full_restore/full_restore_utils.h
@@ -58,10 +58,10 @@ extern const ui::ClassProperty<std::string*>* const kAppIdKey;
// if a window is restored by the full restore process. Only a window, restored
// from the full restore file and read by FullRestoreReadHandler during the
// system startup phase, could have a kActivationIndexKey. This is cleared after
-// the window been stacked accordingly, or has been activated. A larger index
-// indicates a more recently used window. If this key is null, then the window
-// was not launched from full restore, or it is longer treated like a full
-// restore launched window (i.e. user clicked on it).
+// the window been activated. A smaller index indicates a more recently used
+// window. If this key is null, then the window was not launched from full
+// restore, or it is longer treated like a full restore launched window (i.e.
+// user clicked on it).
COMPONENT_EXPORT(FULL_RESTORE)
extern const ui::ClassProperty<int32_t*>* const kActivationIndexKey;
@@ -70,6 +70,11 @@ extern const ui::ClassProperty<int32_t*>* const kActivationIndexKey;
COMPONENT_EXPORT(FULL_RESTORE)
extern const ui::ClassProperty<bool>* const kParentToHiddenContainerKey;
+// A property key indicating whether a window was launched from full restore.
+// These windows will not be activatable until they are shown.
+COMPONENT_EXPORT(FULL_RESTORE)
+extern const ui::ClassProperty<bool>* const kLaunchedFromFullRestoreKey;
+
// Saves the app launch parameters to the full restore file.
COMPONENT_EXPORT(FULL_RESTORE)
void SaveAppLaunchInfo(const base::FilePath& profile_path,
@@ -96,6 +101,13 @@ int32_t GetArcRestoreWindowId(int32_t task_id);
// and the user's choice from the notification. Otherwise, returns false.
COMPONENT_EXPORT(FULL_RESTORE) bool ShouldRestore(const AccountId& account_id);
+// Returns true if the restore pref is 'Always' or 'Ask every time', as we
+// could restore apps and pages based on the user's choice from the
+// notification for |account_id|. Otherwise, returns false, when the restore
+// pref is 'Do not restore'.
+COMPONENT_EXPORT(FULL_RESTORE)
+bool CanPerformRestore(const AccountId& account_id);
+
// Sets the current active profile path.
COMPONENT_EXPORT(FULL_RESTORE)
void SetActiveProfilePath(const base::FilePath& profile_path);
@@ -107,9 +119,9 @@ COMPONENT_EXPORT(FULL_RESTORE)
bool HasWindowInfo(int32_t restore_window_id);
// Modifies `out_params` based on the window info associated with
-// `restore_window_id`. Returns true if `out_params` was modified.
+// `restore_window_id`.
COMPONENT_EXPORT(FULL_RESTORE)
-bool ModifyWidgetParams(int32_t restore_window_id,
+void ModifyWidgetParams(int32_t restore_window_id,
views::Widget::InitParams* out_params);
// Invoked when the task is created for an ARC app.
@@ -122,6 +134,12 @@ void OnTaskCreated(const std::string& app_id,
COMPONENT_EXPORT(FULL_RESTORE)
void OnTaskDestroyed(int32_t task_id);
+// Invoked when the task theme colors are updated for an ARC app.
+COMPONENT_EXPORT(FULL_RESTORE)
+void OnTaskThemeColorUpdated(int32_t task_id,
+ uint32_t primary_color,
+ uint32_t status_bar_color);
+
} // namespace full_restore
#endif // COMPONENTS_FULL_RESTORE_FULL_RESTORE_UTILS_H_
diff --git a/chromium/components/full_restore/restore_data.cc b/chromium/components/full_restore/restore_data.cc
index 00e4da6446a..e134b4b4cd7 100644
--- a/chromium/components/full_restore/restore_data.cc
+++ b/chromium/components/full_restore/restore_data.cc
@@ -106,6 +106,15 @@ void RestoreData::ModifyWindowInfo(const std::string& app_id,
app_restore_data->ModifyWindowInfo(window_info);
}
+void RestoreData::ModifyThemeColor(const std::string& app_id,
+ int32_t window_id,
+ uint32_t primary_color,
+ uint32_t status_bar_color) {
+ auto* app_restore_data = GetAppRestoreData(app_id, window_id);
+ if (app_restore_data)
+ app_restore_data->ModifyThemeColor(primary_color, status_bar_color);
+}
+
void RestoreData::SetNextRestoreWindowIdForChromeApp(
const std::string& app_id) {
auto it = app_id_to_launch_list_.find(app_id);
diff --git a/chromium/components/full_restore/restore_data.h b/chromium/components/full_restore/restore_data.h
index 0127598b9ca..184c2cec737 100644
--- a/chromium/components/full_restore/restore_data.h
+++ b/chromium/components/full_restore/restore_data.h
@@ -92,6 +92,13 @@ class COMPONENT_EXPORT(FULL_RESTORE) RestoreData {
int32_t window_id,
const WindowInfo& window_info);
+ // Modifies the window's theme colors for the window with |window_id| of the
+ // app with |app_id|,
+ void ModifyThemeColor(const std::string& app_id,
+ int32_t window_id,
+ uint32_t primary_color,
+ uint32_t status_bar_color);
+
// Modifies |chrome_app_id_to_current_window_id_| to set the next restore
// window id for the given |app_id|.
//
diff --git a/chromium/components/full_restore/restore_data_unittest.cc b/chromium/components/full_restore/restore_data_unittest.cc
index b8de27f2dd8..f551b7c7126 100644
--- a/chromium/components/full_restore/restore_data_unittest.cc
+++ b/chromium/components/full_restore/restore_data_unittest.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/containers/contains.h"
+#include "base/values.h"
#include "chromeos/ui/base/window_state_type.h"
#include "components/full_restore/app_launch_info.h"
#include "components/full_restore/app_restore_data.h"
@@ -69,6 +70,16 @@ constexpr chromeos::WindowStateType kWindowStateType2 =
constexpr chromeos::WindowStateType kWindowStateType3 =
chromeos::WindowStateType::kFullscreen;
+constexpr gfx::Size kMaxSize1(600, 800);
+constexpr gfx::Size kMinSize1(100, 50);
+constexpr gfx::Size kMinSize2(88, 128);
+
+constexpr uint32_t kPrimaryColor1(0xFFFFFFFF);
+constexpr uint32_t kPrimaryColor2(0xFF000000);
+
+constexpr uint32_t kStatusBarColor1(0xFF00FF00);
+constexpr uint32_t kStatusBarColor2(0xFF000000);
+
} // namespace
// Unit tests for restore data.
@@ -129,6 +140,9 @@ class RestoreDataTest : public testing::Test {
window_info1.current_bounds = kCurrentBounds1;
window_info1.window_state_type = kWindowStateType1;
window_info1.display_id = kDisplayId2;
+ window_info1.arc_extra_info = WindowInfo::ArcExtraInfo();
+ window_info1.arc_extra_info->maximum_size = kMaxSize1;
+ window_info1.arc_extra_info->minimum_size = kMinSize1;
WindowInfo window_info2;
window_info2.activation_index = kActivationIndex2;
@@ -137,6 +151,8 @@ class RestoreDataTest : public testing::Test {
window_info2.current_bounds = kCurrentBounds2;
window_info2.window_state_type = kWindowStateType2;
window_info2.display_id = kDisplayId1;
+ window_info2.arc_extra_info = WindowInfo::ArcExtraInfo();
+ window_info2.arc_extra_info->minimum_size = kMinSize2;
WindowInfo window_info3;
window_info3.activation_index = kActivationIndex3;
@@ -152,6 +168,13 @@ class RestoreDataTest : public testing::Test {
restore_data().ModifyWindowInfo(kAppId2, kWindowId3, window_info3);
}
+ void ModifyThemeColors() {
+ restore_data().ModifyThemeColor(kAppId1, kWindowId1, kPrimaryColor1,
+ kStatusBarColor1);
+ restore_data().ModifyThemeColor(kAppId1, kWindowId2, kPrimaryColor2,
+ kStatusBarColor2);
+ }
+
void VerifyAppRestoreData(const std::unique_ptr<AppRestoreData>& data,
apps::mojom::LaunchContainer container,
WindowOpenDisposition disposition,
@@ -163,7 +186,11 @@ class RestoreDataTest : public testing::Test {
bool visible_on_all_workspaces,
const gfx::Rect& restore_bounds,
const gfx::Rect& current_bounds,
- chromeos::WindowStateType window_state_type) {
+ chromeos::WindowStateType window_state_type,
+ absl::optional<gfx::Size> max_size,
+ absl::optional<gfx::Size> min_size,
+ uint32_t primary_color,
+ uint32_t status_bar_color) {
EXPECT_TRUE(data->container.has_value());
EXPECT_EQ(static_cast<int>(container), data->container.value());
@@ -206,6 +233,34 @@ class RestoreDataTest : public testing::Test {
EXPECT_TRUE(data->window_state_type.has_value());
EXPECT_EQ(window_state_type, data->window_state_type.value());
+
+ if (max_size.has_value()) {
+ EXPECT_TRUE(data->maximum_size.has_value());
+ EXPECT_EQ(max_size.value(), data->maximum_size.value());
+ } else {
+ EXPECT_FALSE(data->maximum_size.has_value());
+ }
+
+ if (min_size.has_value()) {
+ EXPECT_TRUE(data->minimum_size.has_value());
+ EXPECT_EQ(min_size.value(), data->minimum_size.value());
+ } else {
+ EXPECT_FALSE(data->minimum_size.has_value());
+ }
+
+ if (primary_color) {
+ EXPECT_TRUE(data->primary_color.has_value());
+ EXPECT_EQ(primary_color, data->primary_color.value());
+ } else {
+ EXPECT_FALSE(data->primary_color.has_value());
+ }
+
+ if (status_bar_color) {
+ EXPECT_TRUE(data->status_bar_color.has_value());
+ EXPECT_EQ(status_bar_color, data->status_bar_color.value());
+ } else {
+ EXPECT_FALSE(data->status_bar_color.has_value());
+ }
}
void VerifyRestoreData(const RestoreData& restore_data) {
@@ -228,7 +283,8 @@ class RestoreDataTest : public testing::Test {
base::FilePath(kFilePath2)},
CreateIntent(kIntentActionSend, kMimeType, kShareText1),
kActivationIndex1, kDeskId1, kVisibleOnAllWorkspaces1, kRestoreBounds1,
- kCurrentBounds1, kWindowStateType1);
+ kCurrentBounds1, kWindowStateType1, kMaxSize1, kMinSize1,
+ kPrimaryColor1, kStatusBarColor1);
const auto app_restore_data_it2 = launch_list_it1->second.find(kWindowId2);
EXPECT_TRUE(app_restore_data_it2 != launch_list_it1->second.end());
@@ -239,7 +295,8 @@ class RestoreDataTest : public testing::Test {
std::vector<base::FilePath>{base::FilePath(kFilePath2)},
CreateIntent(kIntentActionView, kMimeType, kShareText2),
kActivationIndex2, kDeskId2, kVisibleOnAllWorkspaces2, kRestoreBounds2,
- kCurrentBounds2, kWindowStateType2);
+ kCurrentBounds2, kWindowStateType2, absl::nullopt, kMinSize2,
+ kPrimaryColor2, kStatusBarColor2);
// Verify for |kAppId2|.
const auto launch_list_it2 =
@@ -255,7 +312,7 @@ class RestoreDataTest : public testing::Test {
std::vector<base::FilePath>{base::FilePath(kFilePath1)},
CreateIntent(kIntentActionView, kMimeType, kShareText1),
kActivationIndex3, kDeskId3, kVisibleOnAllWorkspaces3, kRestoreBounds3,
- kCurrentBounds3, kWindowStateType3);
+ kCurrentBounds3, kWindowStateType3, absl::nullopt, absl::nullopt, 0, 0);
}
RestoreData& restore_data() { return restore_data_; }
@@ -281,12 +338,14 @@ TEST_F(RestoreDataTest, AddNullAppLaunchInfo) {
TEST_F(RestoreDataTest, AddAppLaunchInfos) {
AddAppLaunchInfos();
ModifyWindowInfos();
+ ModifyThemeColors();
VerifyRestoreData(restore_data());
}
TEST_F(RestoreDataTest, RemoveAppRestoreData) {
AddAppLaunchInfos();
ModifyWindowInfos();
+ ModifyThemeColors();
VerifyRestoreData(restore_data());
EXPECT_TRUE(restore_data().HasAppRestoreData(kAppId1, kWindowId1));
@@ -345,6 +404,7 @@ TEST_F(RestoreDataTest, RemoveAppRestoreData) {
TEST_F(RestoreDataTest, RemoveWindowInfo) {
AddAppLaunchInfos();
ModifyWindowInfos();
+ ModifyThemeColors();
VerifyRestoreData(restore_data());
// Remove kAppId1.
@@ -358,11 +418,13 @@ TEST_F(RestoreDataTest, RemoveWindowInfo) {
EXPECT_FALSE(window_info->restore_bounds.has_value());
EXPECT_FALSE(window_info->current_bounds.has_value());
EXPECT_FALSE(window_info->window_state_type.has_value());
+ EXPECT_FALSE(window_info->arc_extra_info.has_value());
}
TEST_F(RestoreDataTest, RemoveApp) {
AddAppLaunchInfos();
ModifyWindowInfos();
+ ModifyThemeColors();
VerifyRestoreData(restore_data());
// Remove kAppId1.
@@ -386,6 +448,7 @@ TEST_F(RestoreDataTest, RemoveApp) {
TEST_F(RestoreDataTest, Convert) {
AddAppLaunchInfos();
ModifyWindowInfos();
+ ModifyThemeColors();
std::unique_ptr<base::Value> value =
std::make_unique<base::Value>(restore_data().ConvertToValue());
std::unique_ptr<RestoreData> restore_data =
@@ -455,7 +518,7 @@ TEST_F(RestoreDataTest, GetAppWindowInfo) {
auto app_window_info = data_it->second->GetAppWindowInfo();
EXPECT_TRUE(app_window_info);
- EXPECT_EQ(-1, app_window_info->state);
+ EXPECT_EQ(0, app_window_info->state);
EXPECT_EQ(kDisplayId2, app_window_info->display_id);
EXPECT_FALSE(app_window_info->bounds);
diff --git a/chromium/components/full_restore/window_info.cc b/chromium/components/full_restore/window_info.cc
index cc567c13060..75aef52a304 100644
--- a/chromium/components/full_restore/window_info.cc
+++ b/chromium/components/full_restore/window_info.cc
@@ -10,30 +10,37 @@ namespace full_restore {
namespace {
-std::string ToPrefixedString(base::Optional<int32_t> val,
+std::string ToPrefixedString(absl::optional<int32_t> val,
const std::string& prefix) {
return prefix + base::StringPrintf(": %d \n", val ? *val : -1);
}
-std::string ToPrefixedString(base::Optional<bool> val,
+std::string ToPrefixedString(absl::optional<bool> val,
const std::string& prefix) {
return prefix + base::StringPrintf(": %d \n", val ? *val : 0);
}
-std::string ToPrefixedString(base::Optional<gfx::Rect> val,
+std::string ToPrefixedString(absl::optional<gfx::Rect> val,
const std::string& prefix) {
return prefix + ": " + (val ? *val : gfx::Rect()).ToString() + " \n";
}
-std::string ToPrefixedString(base::Optional<chromeos::WindowStateType> val,
+std::string ToPrefixedString(absl::optional<chromeos::WindowStateType> val,
const std::string& prefix) {
- base::Optional<int> new_val =
- val ? base::make_optional(static_cast<int>(*val)) : base::nullopt;
+ absl::optional<int> new_val =
+ val ? absl::make_optional(static_cast<int>(*val)) : absl::nullopt;
return ToPrefixedString(new_val, prefix);
}
} // namespace
+WindowInfo::ArcExtraInfo::ArcExtraInfo() = default;
+WindowInfo::ArcExtraInfo::ArcExtraInfo(const WindowInfo::ArcExtraInfo&) =
+ default;
+WindowInfo::ArcExtraInfo& WindowInfo::ArcExtraInfo::operator=(
+ const WindowInfo::ArcExtraInfo&) = default;
+WindowInfo::ArcExtraInfo::~ArcExtraInfo() = default;
+
WindowInfo::WindowInfo() = default;
WindowInfo::~WindowInfo() = default;
diff --git a/chromium/components/full_restore/window_info.h b/chromium/components/full_restore/window_info.h
index eb877f2e32d..539dac386aa 100644
--- a/chromium/components/full_restore/window_info.h
+++ b/chromium/components/full_restore/window_info.h
@@ -5,8 +5,8 @@
#ifndef COMPONENTS_FULL_RESTORE_WINDOW_INFO_H_
#define COMPONENTS_FULL_RESTORE_WINDOW_INFO_H_
-#include "base/optional.h"
#include "chromeos/ui/base/window_state_type.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/aura/window.h"
#include "ui/gfx/geometry/rect.h"
@@ -16,6 +16,17 @@ namespace full_restore {
// window information.
struct COMPONENT_EXPORT(FULL_RESTORE) WindowInfo {
public:
+ // This struct is the ARC specific window info.
+ struct ArcExtraInfo {
+ ArcExtraInfo();
+ ArcExtraInfo(const WindowInfo::ArcExtraInfo&);
+ ArcExtraInfo& operator=(const WindowInfo::ArcExtraInfo&);
+ ~ArcExtraInfo();
+
+ absl::optional<gfx::Size> maximum_size;
+ absl::optional<gfx::Size> minimum_size;
+ };
+
WindowInfo();
WindowInfo(const WindowInfo&) = delete;
WindowInfo& operator=(const WindowInfo&) = delete;
@@ -25,13 +36,13 @@ struct COMPONENT_EXPORT(FULL_RESTORE) WindowInfo {
// Index in MruWindowTracker to restore window stack. A lower index
// indicates a more recently used window.
- base::Optional<int32_t> activation_index;
+ absl::optional<int32_t> activation_index;
// Virtual desk id.
- base::Optional<int32_t> desk_id;
+ absl::optional<int32_t> desk_id;
// Whether the |window| is visible on all workspaces.
- base::Optional<bool> visible_on_all_workspaces;
+ absl::optional<bool> visible_on_all_workspaces;
// The restored bounds in screen coordinates. Empty if the window is not
// snapped/maximized/minimized.
@@ -40,17 +51,20 @@ struct COMPONENT_EXPORT(FULL_RESTORE) WindowInfo {
// |current_bounds| will be stored as restore bounds and the maximized or
// snapped bounds will be determined by the system. Update the comment below
// if this is removed.
- base::Optional<gfx::Rect> restore_bounds;
+ absl::optional<gfx::Rect> restore_bounds;
// Current bounds in screen in coordinates. If the window has restore bounds,
// then this contains the restore bounds.
- base::Optional<gfx::Rect> current_bounds;
+ absl::optional<gfx::Rect> current_bounds;
// Window state, minimized, maximized, inactive, etc.
- base::Optional<chromeos::WindowStateType> window_state_type;
+ absl::optional<chromeos::WindowStateType> window_state_type;
// Display id to launch an app.
- base::Optional<int64_t> display_id;
+ absl::optional<int64_t> display_id;
+
+ // Extra window info of ARC app window.
+ absl::optional<ArcExtraInfo> arc_extra_info;
std::string ToString() const;
};
diff --git a/chromium/components/fullscreen_control/BUILD.gn b/chromium/components/fullscreen_control/BUILD.gn
new file mode 100644
index 00000000000..b3cd5bd3579
--- /dev/null
+++ b/chromium/components/fullscreen_control/BUILD.gn
@@ -0,0 +1,46 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("fullscreen_control") {
+ sources = [
+ "fullscreen_control_popup.cc",
+ "fullscreen_control_popup.h",
+ "fullscreen_control_view.cc",
+ "fullscreen_control_view.h",
+ "subtle_notification_view.cc",
+ "subtle_notification_view.h",
+ ]
+ deps = [
+ "//base",
+ "//cc/paint",
+ "//components/strings",
+ "//components/vector_icons",
+ "//skia",
+ "//ui/accessibility:ax_base",
+ "//ui/base",
+ "//ui/compositor",
+ "//ui/gfx:native_widget_types",
+ "//ui/gfx/animation",
+ "//ui/gfx/geometry",
+ "//ui/views",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "fullscreen_control_popup_unittest.cc",
+ "fullscreen_control_view_unittest.cc",
+ ]
+
+ deps = [
+ ":fullscreen_control",
+ "//base",
+ "//base/test:test_support",
+ "//testing/gtest",
+ "//ui/gfx:test_support",
+ "//ui/views",
+ "//ui/views:test_support",
+ ]
+}
diff --git a/chromium/components/fullscreen_control/DEPS b/chromium/components/fullscreen_control/DEPS
new file mode 100644
index 00000000000..4ff2dc3c498
--- /dev/null
+++ b/chromium/components/fullscreen_control/DEPS
@@ -0,0 +1,8 @@
+include_rules = [
+ "+cc/paint",
+ "+components/vector_icons",
+ "+components/strings",
+ "+testing/gtest",
+ "+third_party/skia",
+ "+ui"
+]
diff --git a/chromium/components/fullscreen_control/DIR_METADATA b/chromium/components/fullscreen_control/DIR_METADATA
new file mode 100644
index 00000000000..9719bd8c21f
--- /dev/null
+++ b/chromium/components/fullscreen_control/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "UI>Browser"
+}
diff --git a/chromium/components/fullscreen_control/OWNERS b/chromium/components/fullscreen_control/OWNERS
new file mode 100644
index 00000000000..2950655f0ff
--- /dev/null
+++ b/chromium/components/fullscreen_control/OWNERS
@@ -0,0 +1,2 @@
+file://chrome/browser/ui/views/fullscreen_control/OWNERS
+file://chrome/browser/ui/views/OWNERS
diff --git a/chromium/components/fullscreen_control/README.md b/chromium/components/fullscreen_control/README.md
new file mode 100644
index 00000000000..471484f086e
--- /dev/null
+++ b/chromium/components/fullscreen_control/README.md
@@ -0,0 +1,7 @@
+# Fullscreen Control #
+
+Fullscreen control provides UI components used during fullscreen:
+* 'Press and hold [ESC] to exit' message shown at the start.
+* Exit circle with 'X' shown when the mouse moves to the top of the screen.
+
+The components are used by chrome browser, and by Chrome OS exo.
diff --git a/chromium/components/fullscreen_control/fullscreen_control_popup.cc b/chromium/components/fullscreen_control/fullscreen_control_popup.cc
new file mode 100644
index 00000000000..c2c22f52907
--- /dev/null
+++ b/chromium/components/fullscreen_control/fullscreen_control_popup.cc
@@ -0,0 +1,149 @@
+// 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/fullscreen_control/fullscreen_control_popup.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "components/fullscreen_control/fullscreen_control_view.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/views/widget/widget.h"
+
+namespace {
+
+// Offsets with respect to the top y coordinate of the parent widget.
+constexpr int kFinalOffset = 45;
+
+constexpr float kInitialOpacity = 0.1f;
+constexpr float kFinalOpacity = 1.f;
+
+// Creates a Widget containing an FullscreenControlView.
+std::unique_ptr<views::Widget> CreatePopupWidget(
+ gfx::NativeView parent_view,
+ std::unique_ptr<FullscreenControlView> view) {
+ // Initialize the popup.
+ std::unique_ptr<views::Widget> popup = std::make_unique<views::Widget>();
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
+ params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.parent = parent_view;
+ popup->Init(std::move(params));
+ popup->SetContentsView(std::move(view));
+
+ return popup;
+}
+
+} // namespace
+
+FullscreenControlPopup::FullscreenControlPopup(
+ gfx::NativeView parent_view,
+ const base::RepeatingClosure& on_button_pressed,
+ const base::RepeatingClosure& on_visibility_changed)
+ : FullscreenControlPopup(
+ CreatePopupWidget(
+ parent_view,
+ std::make_unique<FullscreenControlView>(on_button_pressed)),
+ on_visibility_changed) {}
+
+FullscreenControlPopup::~FullscreenControlPopup() {}
+
+// static
+int FullscreenControlPopup::GetButtonBottomOffset() {
+ return kFinalOffset + FullscreenControlView::kCircleButtonDiameter;
+}
+
+void FullscreenControlPopup::Show(const gfx::Rect& parent_bounds_in_screen) {
+ if (IsVisible())
+ return;
+
+ parent_bounds_in_screen_ = parent_bounds_in_screen;
+
+ animation_->SetSlideDuration(base::TimeDelta::FromMilliseconds(300));
+ animation_->Show();
+
+ // The default animation progress is 0. Call it once here then show the popup
+ // to prevent potential flickering.
+ AnimationProgressed(animation_.get());
+ popup_->Show();
+}
+
+void FullscreenControlPopup::Hide(bool animated) {
+ if (!IsVisible())
+ return;
+
+ if (animated) {
+ animation_->SetSlideDuration(base::TimeDelta::FromMilliseconds(150));
+ animation_->Hide();
+ return;
+ }
+
+ animation_->Reset(0);
+ AnimationEnded(animation_.get());
+}
+
+views::Widget* FullscreenControlPopup::GetPopupWidget() {
+ return popup_.get();
+}
+
+gfx::SlideAnimation* FullscreenControlPopup::GetAnimationForTesting() {
+ return animation_.get();
+}
+
+bool FullscreenControlPopup::IsAnimating() const {
+ return animation_->is_animating();
+}
+
+bool FullscreenControlPopup::IsVisible() const {
+ return popup_->IsVisible();
+}
+
+FullscreenControlPopup::FullscreenControlPopup(
+ std::unique_ptr<views::Widget> popup,
+ const base::RepeatingClosure& on_visibility_changed)
+ : AnimationDelegateViews(popup->GetRootView()),
+ control_view_(
+ static_cast<FullscreenControlView*>(popup->GetContentsView())),
+ popup_(std::move(popup)),
+ animation_(std::make_unique<gfx::SlideAnimation>(this)),
+ on_visibility_changed_(on_visibility_changed) {
+ DCHECK(on_visibility_changed_);
+ animation_->Reset(0);
+}
+
+void FullscreenControlPopup::AnimationProgressed(
+ const gfx::Animation* animation) {
+ float opacity = static_cast<float>(
+ animation_->CurrentValueBetween(kInitialOpacity, kFinalOpacity));
+ popup_->SetOpacity(opacity);
+
+ int initial_offset = -control_view_->GetPreferredSize().height();
+ popup_->SetBounds(CalculateBounds(
+ animation_->CurrentValueBetween(initial_offset, kFinalOffset)));
+}
+
+void FullscreenControlPopup::AnimationEnded(const gfx::Animation* animation) {
+ if (animation_->GetCurrentValue() == 0.0) {
+ // It's the end of the reversed animation. Just hide the popup in this case.
+ parent_bounds_in_screen_ = gfx::Rect();
+ popup_->Hide();
+ } else {
+ AnimationProgressed(animation);
+ }
+ OnVisibilityChanged();
+}
+
+gfx::Rect FullscreenControlPopup::CalculateBounds(int y_offset) const {
+ if (parent_bounds_in_screen_.IsEmpty())
+ return gfx::Rect();
+
+ gfx::Point origin(parent_bounds_in_screen_.CenterPoint().x() -
+ control_view_->GetPreferredSize().width() / 2,
+ parent_bounds_in_screen_.y() + y_offset);
+ return {origin, control_view_->GetPreferredSize()};
+}
+
+void FullscreenControlPopup::OnVisibilityChanged() {
+ on_visibility_changed_.Run();
+}
diff --git a/chromium/components/fullscreen_control/fullscreen_control_popup.h b/chromium/components/fullscreen_control/fullscreen_control_popup.h
new file mode 100644
index 00000000000..1ce95d1ebd8
--- /dev/null
+++ b/chromium/components/fullscreen_control/fullscreen_control_popup.h
@@ -0,0 +1,82 @@
+// 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_FULLSCREEN_CONTROL_FULLSCREEN_CONTROL_POPUP_H_
+#define COMPONENTS_FULLSCREEN_CONTROL_FULLSCREEN_CONTROL_POPUP_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "ui/gfx/animation/animation_delegate.h"
+#include "ui/gfx/animation/slide_animation.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/views/animation/animation_delegate_views.h"
+
+namespace views {
+class Widget;
+} // namespace views
+
+class FullscreenControlView;
+
+// FullscreenControlPopup is a helper class that holds a FullscreenControlView
+// and allows showing and hiding the view with a drop down animation.
+class FullscreenControlPopup : public views::AnimationDelegateViews {
+ public:
+ FullscreenControlPopup(gfx::NativeView parent_view,
+ const base::RepeatingClosure& on_button_pressed,
+ const base::RepeatingClosure& on_visibility_changed);
+ ~FullscreenControlPopup() override;
+
+ // Returns the final bottom of the button as a y offset to its parent view.
+ static int GetButtonBottomOffset();
+
+ // Shows the indicator with an animation that drops it off the top of
+ // |parent_view|.
+ // |parent_bounds_in_screen| holds the bounds of |parent_view| in the screen
+ // coordinate system.
+ void Show(const gfx::Rect& parent_bounds_in_screen);
+
+ // Hides the indicator. If |animated| is true, the indicator will be hidden by
+ // the reversed animation of Show(), i.e. the indicator flies to the top of
+ // |parent_widget|.
+ void Hide(bool animated);
+
+ views::Widget* GetPopupWidget();
+ gfx::SlideAnimation* GetAnimationForTesting();
+
+ bool IsAnimating() const;
+
+ // Returns true if the popup is visible on the screen, i.e. Show() has been
+ // called and Hide() has never been called since then.
+ bool IsVisible() const;
+
+ FullscreenControlView* control_view() { return control_view_; }
+
+ private:
+ FullscreenControlPopup(std::unique_ptr<views::Widget> popup,
+ const base::RepeatingClosure& on_visibility_changed);
+
+ // views::AnimationDelegateViews:
+ void AnimationProgressed(const gfx::Animation* animation) override;
+ void AnimationEnded(const gfx::Animation* animation) override;
+
+ gfx::Rect CalculateBounds(int y_offset) const;
+
+ void OnVisibilityChanged();
+
+ FullscreenControlView* const control_view_;
+ const std::unique_ptr<views::Widget> popup_;
+ const std::unique_ptr<gfx::SlideAnimation> animation_;
+
+ // The bounds is empty when the popup is not showing.
+ gfx::Rect parent_bounds_in_screen_;
+
+ const base::RepeatingClosure on_visibility_changed_;
+
+ DISALLOW_COPY_AND_ASSIGN(FullscreenControlPopup);
+};
+
+#endif // COMPONENTS_FULLSCREEN_CONTROL_FULLSCREEN_CONTROL_POPUP_H_
diff --git a/chromium/components/fullscreen_control/fullscreen_control_popup_unittest.cc b/chromium/components/fullscreen_control/fullscreen_control_popup_unittest.cc
new file mode 100644
index 00000000000..53ec2f67023
--- /dev/null
+++ b/chromium/components/fullscreen_control/fullscreen_control_popup_unittest.cc
@@ -0,0 +1,122 @@
+// 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 "ui/views/widget/widget.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/run_loop.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "components/fullscreen_control/fullscreen_control_popup.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/animation/animation_test_api.h"
+#include "ui/views/test/widget_test.h"
+
+class FullscreenControlPopupTest : public views::test::WidgetTest {
+ public:
+ FullscreenControlPopupTest() {}
+ ~FullscreenControlPopupTest() override {}
+
+ // views::test::WidgetTest:
+ void SetUp() override {
+ views::test::WidgetTest::SetUp();
+ parent_widget_ = CreateTopLevelNativeWidget();
+ parent_widget_->SetBounds(gfx::Rect(100, 100, 640, 480));
+ parent_widget_->Show();
+ popup_ = std::make_unique<FullscreenControlPopup>(
+ parent_widget_->GetNativeView(), base::DoNothing(), base::DoNothing());
+ animation_api_ = std::make_unique<gfx::AnimationTestApi>(
+ popup_->GetAnimationForTesting());
+ }
+
+ void TearDown() override {
+ parent_widget_->CloseNow();
+ views::test::WidgetTest::TearDown();
+ }
+
+ protected:
+ void RunAnimationFor(base::TimeDelta duration) {
+ base::TimeTicks now = base::TimeTicks::Now();
+ animation_api_->SetStartTime(now);
+ animation_api_->Step(now + duration);
+ }
+
+ void CompleteAnimation() {
+ RunAnimationFor(base::TimeDelta::FromMilliseconds(5000));
+ }
+
+ gfx::Rect GetParentBounds() const {
+ return parent_widget_->GetClientAreaBoundsInScreen();
+ }
+
+ gfx::Rect GetPopupBounds() const {
+ return popup_->GetPopupWidget()->GetClientAreaBoundsInScreen();
+ }
+
+ std::unique_ptr<FullscreenControlPopup> popup_;
+
+ private:
+ std::unique_ptr<gfx::AnimationTestApi> animation_api_;
+ views::Widget* parent_widget_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(FullscreenControlPopupTest);
+};
+
+TEST_F(FullscreenControlPopupTest, ShowPopupAnimated) {
+ EXPECT_FALSE(popup_->IsAnimating());
+ EXPECT_FALSE(popup_->IsVisible());
+
+ popup_->Show(GetParentBounds());
+ EXPECT_TRUE(popup_->IsAnimating());
+ EXPECT_TRUE(popup_->IsVisible());
+
+ // The popup should be above the parent bounds when the animation is just
+ // started.
+ EXPECT_GT(GetParentBounds().y(), GetPopupBounds().y());
+
+ CompleteAnimation();
+
+ EXPECT_FALSE(popup_->IsAnimating());
+ EXPECT_TRUE(popup_->IsVisible());
+ int final_bottom =
+ FullscreenControlPopup::GetButtonBottomOffset() + GetParentBounds().y();
+ EXPECT_EQ(final_bottom, GetPopupBounds().bottom());
+}
+
+TEST_F(FullscreenControlPopupTest, HidePopupWhileStillShowing) {
+ popup_->Show(GetParentBounds());
+
+ RunAnimationFor(base::TimeDelta::FromMilliseconds(50));
+
+ EXPECT_TRUE(popup_->IsAnimating());
+ EXPECT_TRUE(popup_->IsVisible());
+
+ // The popup is partially shown.
+ EXPECT_LT(GetParentBounds().y(), GetPopupBounds().bottom());
+
+ popup_->Hide(true);
+ EXPECT_TRUE(popup_->IsAnimating());
+ EXPECT_TRUE(popup_->IsVisible());
+ EXPECT_LT(GetParentBounds().y(), GetPopupBounds().bottom());
+
+ CompleteAnimation();
+
+ EXPECT_FALSE(popup_->IsAnimating());
+ EXPECT_FALSE(popup_->IsVisible());
+ EXPECT_GT(GetParentBounds().y(), GetPopupBounds().y());
+}
+
+TEST_F(FullscreenControlPopupTest, HidePopupWithoutAnimation) {
+ popup_->Show(GetParentBounds());
+
+ CompleteAnimation();
+
+ popup_->Hide(false);
+ EXPECT_FALSE(popup_->IsAnimating());
+ EXPECT_FALSE(popup_->IsVisible());
+}
diff --git a/chromium/components/fullscreen_control/fullscreen_control_view.cc b/chromium/components/fullscreen_control/fullscreen_control_view.cc
new file mode 100644
index 00000000000..45efcd0369a
--- /dev/null
+++ b/chromium/components/fullscreen_control/fullscreen_control_view.cc
@@ -0,0 +1,82 @@
+// 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/fullscreen_control/fullscreen_control_view.h"
+
+#include <memory>
+
+#include "base/callback.h"
+#include "cc/paint/paint_flags.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/vector_icons/vector_icons.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/background.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/vector_icons.h"
+
+namespace {
+
+// Partially-transparent background color.
+const SkColor kButtonBackgroundColor = SkColorSetARGB(0xcc, 0x28, 0x2c, 0x32);
+
+constexpr int kCloseIconSize = 24;
+
+class CloseFullscreenButton : public views::Button {
+ public:
+ METADATA_HEADER(CloseFullscreenButton);
+ explicit CloseFullscreenButton(PressedCallback callback)
+ : views::Button(std::move(callback)) {
+ std::unique_ptr<views::ImageView> close_image_view =
+ std::make_unique<views::ImageView>();
+ close_image_view->SetImage(gfx::CreateVectorIcon(
+ views::kIcCloseIcon, kCloseIconSize, SK_ColorWHITE));
+ // Not focusable by default, only for accessibility.
+ SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
+ SetAccessibleName(l10n_util::GetStringUTF16(IDS_EXIT_FULLSCREEN_MODE));
+ AddChildView(close_image_view.release());
+ SetLayoutManager(std::make_unique<views::FillLayout>());
+ }
+ CloseFullscreenButton(const CloseFullscreenButton&) = delete;
+ CloseFullscreenButton& operator=(const CloseFullscreenButton&) = delete;
+
+ private:
+ void PaintButtonContents(gfx::Canvas* canvas) override {
+ // TODO(robliao): If we decide to move forward with this, use themes.
+ cc::PaintFlags flags;
+ flags.setAntiAlias(true);
+ flags.setColor(kButtonBackgroundColor);
+ flags.setStyle(cc::PaintFlags::kFill_Style);
+ float radius = FullscreenControlView::kCircleButtonDiameter / 2.0f;
+ canvas->DrawCircle(gfx::PointF(radius, radius), radius, flags);
+ }
+};
+
+BEGIN_METADATA(CloseFullscreenButton, views::Button)
+END_METADATA
+
+} // namespace
+
+FullscreenControlView::FullscreenControlView(
+ views::Button::PressedCallback callback) {
+ exit_fullscreen_button_ = AddChildView(
+ std::make_unique<CloseFullscreenButton>(std::move(callback)));
+ SetLayoutManager(std::make_unique<views::FillLayout>());
+ exit_fullscreen_button_->SetPreferredSize(
+ gfx::Size(kCircleButtonDiameter, kCircleButtonDiameter));
+}
+
+FullscreenControlView::~FullscreenControlView() = default;
+
+BEGIN_METADATA(FullscreenControlView, views::View)
+END_METADATA
diff --git a/chromium/components/fullscreen_control/fullscreen_control_view.h b/chromium/components/fullscreen_control/fullscreen_control_view.h
new file mode 100644
index 00000000000..21cf9a5bf6f
--- /dev/null
+++ b/chromium/components/fullscreen_control/fullscreen_control_view.h
@@ -0,0 +1,35 @@
+// 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_FULLSCREEN_CONTROL_FULLSCREEN_CONTROL_VIEW_H_
+#define COMPONENTS_FULLSCREEN_CONTROL_FULLSCREEN_CONTROL_VIEW_H_
+
+#include "base/callback.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/view.h"
+
+// FullscreenControlView shows a FAB (floating action button from the material
+// design spec) with close icon (i.e. a partially-transparent black circular
+// button with a "X" icon in the middle).
+// |callback| will be called when the user taps the button.
+class FullscreenControlView : public views::View {
+ public:
+ METADATA_HEADER(FullscreenControlView);
+ explicit FullscreenControlView(views::Button::PressedCallback callback);
+ FullscreenControlView(const FullscreenControlView&) = delete;
+ FullscreenControlView& operator=(const FullscreenControlView&) = delete;
+ ~FullscreenControlView() override;
+
+ static constexpr int kCircleButtonDiameter = 48;
+
+ views::Button* exit_fullscreen_button_for_testing() {
+ return exit_fullscreen_button_;
+ }
+
+ private:
+ views::Button* exit_fullscreen_button_;
+};
+
+#endif // COMPONENTS_FULLSCREEN_CONTROL_FULLSCREEN_CONTROL_VIEW_H_
diff --git a/chromium/components/fullscreen_control/fullscreen_control_view_unittest.cc b/chromium/components/fullscreen_control/fullscreen_control_view_unittest.cc
new file mode 100644
index 00000000000..aaf99c6b4bd
--- /dev/null
+++ b/chromium/components/fullscreen_control/fullscreen_control_view_unittest.cc
@@ -0,0 +1,16 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/fullscreen_control/fullscreen_control_view.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/view.h"
+
+TEST(FullscreenControlView, CheckExitButtonFocusBehavior) {
+ FullscreenControlView control_view{views::Button::PressedCallback()};
+ EXPECT_EQ(
+ views::View::FocusBehavior::ACCESSIBLE_ONLY,
+ control_view.exit_fullscreen_button_for_testing()->GetFocusBehavior());
+}
diff --git a/chromium/components/fullscreen_control/subtle_notification_view.cc b/chromium/components/fullscreen_control/subtle_notification_view.cc
new file mode 100644
index 00000000000..4643b35ffa6
--- /dev/null
+++ b/chromium/components/fullscreen_control/subtle_notification_view.cc
@@ -0,0 +1,212 @@
+// 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/fullscreen_control/subtle_notification_view.h"
+
+#include <memory>
+
+#include "base/strings/string_split.h"
+#include "base/strings/utf_string_conversions.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/font_list.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/views/bubble/bubble_border.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/style/typography.h"
+#include "ui/views/widget/widget.h"
+
+namespace {
+
+// Space between the site info label.
+const int kMiddlePaddingPx = 30;
+
+const int kOuterPaddingHorizPx = 40;
+const int kOuterPaddingVertPx = 8;
+
+// Partially-transparent background color.
+const SkColor kSubtleNotificationBackgroundColor =
+ SkColorSetARGB(0xcc, 0x28, 0x2c, 0x32);
+
+// Spacing around the key name.
+const int kKeyNameMarginHorizPx = 7;
+const int kKeyNameBorderPx = 1;
+const int kKeyNameCornerRadius = 2;
+const int kKeyNamePaddingPx = 5;
+
+// The context used to obtain typography for the instruction text. It's not
+// really a dialog, but a dialog title is a good fit.
+constexpr int kInstructionTextContext = views::style::CONTEXT_DIALOG_TITLE;
+
+// Delimiter indicating there should be a segment displayed as a keyboard key.
+constexpr char16_t kKeyNameDelimiter[] = u"|";
+
+} // namespace
+
+// Class containing the instruction text. Contains fancy styling on the keyboard
+// key (not just a simple label).
+class SubtleNotificationView::InstructionView : public views::View {
+ public:
+ METADATA_HEADER(InstructionView);
+ // Creates an InstructionView with specific text. |text| may contain one or
+ // more segments delimited by a pair of pipes ('|'); each of these segments
+ // will be displayed as a keyboard key. e.g., "Press |Alt|+|Q| to exit" will
+ // have "Alt" and "Q" rendered as keys.
+ explicit InstructionView(const std::u16string& text);
+ InstructionView(const InstructionView&) = delete;
+ InstructionView& operator=(const InstructionView&) = delete;
+
+ std::u16string GetText() const;
+ void SetText(const std::u16string& text);
+
+ private:
+ // Adds a label to the end of the notification text. If |format_as_key|,
+ // surrounds the label in a rounded-rect border to indicate that it is a
+ // keyboard key.
+ void AddTextSegment(const std::u16string& text, bool format_as_key);
+
+ std::u16string text_;
+};
+
+SubtleNotificationView::InstructionView::InstructionView(
+ const std::u16string& text) {
+ // The |between_child_spacing| is the horizontal margin of the key name.
+ SetLayoutManager(std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
+ kKeyNameMarginHorizPx));
+
+ SetText(text);
+}
+
+std::u16string SubtleNotificationView::InstructionView::GetText() const {
+ return text_;
+}
+
+void SubtleNotificationView::InstructionView::SetText(
+ const std::u16string& text) {
+ // Avoid replacing the contents with the same text.
+ if (text == text_)
+ return;
+
+ RemoveAllChildViews(true);
+
+ // Parse |text|, looking for pipe-delimited segment.
+ std::vector<std::u16string> segments = base::SplitString(
+ text, kKeyNameDelimiter, base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ // SplitString() returns empty strings for zero-length segments, so given an
+ // even number of pipes, there should always be an odd number of segments.
+ // The exception is if |text| is entirely empty, in which case the returned
+ // list is also empty (rather than containing a single empty string).
+ DCHECK(segments.empty() || segments.size() % 2 == 1);
+
+ // Add text segment, alternating between non-key (no border) and key (border)
+ // formatting.
+ bool format_as_key = false;
+ for (const auto& segment : segments) {
+ AddTextSegment(segment, format_as_key);
+ format_as_key = !format_as_key;
+ }
+
+ text_ = text;
+}
+
+void SubtleNotificationView::InstructionView::AddTextSegment(
+ const std::u16string& text,
+ bool format_as_key) {
+ constexpr SkColor kForegroundColor = SK_ColorWHITE;
+
+ views::Label* label = new views::Label(text, kInstructionTextContext);
+ label->SetEnabledColor(kForegroundColor);
+ label->SetBackgroundColor(kSubtleNotificationBackgroundColor);
+
+ if (!format_as_key) {
+ AddChildView(label);
+ return;
+ }
+
+ views::View* key = new views::View;
+ auto key_name_layout = std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kHorizontal,
+ gfx::Insets(0, kKeyNamePaddingPx), 0);
+ key_name_layout->set_minimum_cross_axis_size(
+ label->GetPreferredSize().height() + kKeyNamePaddingPx * 2);
+ key->SetLayoutManager(std::move(key_name_layout));
+ key->AddChildView(label);
+ // The key name has a border around it.
+ std::unique_ptr<views::Border> border(views::CreateRoundedRectBorder(
+ kKeyNameBorderPx, kKeyNameCornerRadius, kForegroundColor));
+ key->SetBorder(std::move(border));
+ AddChildView(key);
+}
+
+BEGIN_METADATA(SubtleNotificationView, InstructionView, views::View)
+ADD_PROPERTY_METADATA(std::u16string, Text)
+END_METADATA
+
+SubtleNotificationView::SubtleNotificationView() : instruction_view_(nullptr) {
+ std::unique_ptr<views::BubbleBorder> bubble_border(new views::BubbleBorder(
+ views::BubbleBorder::NONE, views::BubbleBorder::NO_SHADOW,
+ kSubtleNotificationBackgroundColor));
+ SetBackground(std::make_unique<views::BubbleBackground>(bubble_border.get()));
+ SetBorder(std::move(bubble_border));
+
+ instruction_view_ = new InstructionView(std::u16string());
+
+ int outer_padding_horiz = kOuterPaddingHorizPx;
+ int outer_padding_vert = kOuterPaddingVertPx;
+ AddChildView(instruction_view_);
+
+ SetLayoutManager(std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kHorizontal,
+ gfx::Insets(outer_padding_vert, outer_padding_horiz), kMiddlePaddingPx));
+}
+
+SubtleNotificationView::~SubtleNotificationView() {}
+
+void SubtleNotificationView::UpdateContent(
+ const std::u16string& instruction_text) {
+ instruction_view_->SetText(instruction_text);
+ instruction_view_->SetVisible(!instruction_text.empty());
+ Layout();
+}
+
+// static
+views::Widget* SubtleNotificationView::CreatePopupWidget(
+ gfx::NativeView parent_view,
+ std::unique_ptr<SubtleNotificationView> view) {
+ // Initialize the popup.
+ views::Widget* popup = new views::Widget;
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
+ params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.parent = parent_view;
+ params.accept_events = false;
+ popup->Init(std::move(params));
+ popup->SetContentsView(std::move(view));
+ // We set layout manager to nullptr to prevent the widget from sizing its
+ // contents to the same size as itself. This prevents the widget contents from
+ // shrinking while we animate the height of the popup to give the impression
+ // that it is sliding off the top of the screen.
+ // TODO(mgiuca): This probably isn't necessary now that there is no slide
+ // animation. Remove it.
+ popup->GetRootView()->SetLayoutManager(nullptr);
+
+ return popup;
+}
+
+void SubtleNotificationView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+ node_data->role = ax::mojom::Role::kAlert;
+ std::u16string accessible_name;
+ base::RemoveChars(instruction_view_->GetText(), kKeyNameDelimiter,
+ &accessible_name);
+ node_data->SetName(accessible_name);
+}
+
+BEGIN_METADATA(SubtleNotificationView, views::View)
+END_METADATA
diff --git a/chromium/components/fullscreen_control/subtle_notification_view.h b/chromium/components/fullscreen_control/subtle_notification_view.h
new file mode 100644
index 00000000000..4bfb7fad0e5
--- /dev/null
+++ b/chromium/components/fullscreen_control/subtle_notification_view.h
@@ -0,0 +1,51 @@
+// 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_FULLSCREEN_CONTROL_SUBTLE_NOTIFICATION_VIEW_H_
+#define COMPONENTS_FULLSCREEN_CONTROL_SUBTLE_NOTIFICATION_VIEW_H_
+
+#include <memory>
+#include <string>
+
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/views/view.h"
+
+namespace views {
+class Widget;
+}
+
+// A transient, transparent notification bubble that appears at the top of the
+// browser window to give the user a short instruction (e.g., "Press Esc to exit
+// full screen"). Unlike a full notification, a subtle notification
+// auto-dismisses after a short period of time. It also has special
+// functionality for displaying keyboard shortcuts (rendering the keys inside a
+// rounded rectangle).
+class SubtleNotificationView : public views::View {
+ public:
+ METADATA_HEADER(SubtleNotificationView);
+ SubtleNotificationView();
+ SubtleNotificationView(const SubtleNotificationView&) = delete;
+ SubtleNotificationView& operator=(const SubtleNotificationView&) = delete;
+ ~SubtleNotificationView() override;
+
+ // Display the |instruction_text| to the user. If |instruction_text| is
+ // empty hide the view.
+ void UpdateContent(const std::u16string& instruction_text);
+
+ // Creates a Widget containing a SubtleNotificationView.
+ static views::Widget* CreatePopupWidget(
+ gfx::NativeView parent_view,
+ std::unique_ptr<SubtleNotificationView> view);
+ // views::View
+ void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+
+ private:
+ class InstructionView;
+
+ // Text displayed in the bubble, with optional keyboard keys.
+ InstructionView* instruction_view_;
+};
+
+#endif // COMPONENTS_FULLSCREEN_CONTROL_SUBTLE_NOTIFICATION_VIEW_H_
diff --git a/chromium/components/fullscreen_control_strings.grdp b/chromium/components/fullscreen_control_strings.grdp
new file mode 100644
index 00000000000..e1b298598d2
--- /dev/null
+++ b/chromium/components/fullscreen_control_strings.grdp
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <message name="IDS_EXIT_FULLSCREEN_MODE" desc="Clickable message displayed on entering full screen mode. Clicking on the link exits full screen mode.">
+ Exit full screen
+ </message>
+ <message name="IDS_FULLSCREEN_HOLD_ESC_TO_EXIT_FULLSCREEN" desc="Text displayed in the bubble to tell users how to return from fullscreen mode (where the web page occupies the entire screen) to normal mode. Please surround the name of the key (e.g. 'Esc') in pipe characters so it can be rendered as a key.">
+ Press and hold |<ph name="ACCELERATOR">$1<ex>Esc</ex></ph>| to exit full screen
+ </message>
+</grit-part>
diff --git a/chromium/components/fullscreen_control_strings_grdp/DIR_METADATA b/chromium/components/fullscreen_control_strings_grdp/DIR_METADATA
new file mode 100644
index 00000000000..9719bd8c21f
--- /dev/null
+++ b/chromium/components/fullscreen_control_strings_grdp/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "UI>Browser"
+}
diff --git a/chromium/components/fullscreen_control_strings_grdp/IDS_EXIT_FULLSCREEN_MODE.png.sha1 b/chromium/components/fullscreen_control_strings_grdp/IDS_EXIT_FULLSCREEN_MODE.png.sha1
new file mode 100644
index 00000000000..10f2f68fd9a
--- /dev/null
+++ b/chromium/components/fullscreen_control_strings_grdp/IDS_EXIT_FULLSCREEN_MODE.png.sha1
@@ -0,0 +1 @@
+77262c576584a767eb718ce4e342d8c8b59d3d78 \ No newline at end of file
diff --git a/chromium/components/fullscreen_control_strings_grdp/IDS_FULLSCREEN_HOLD_ESC_TO_EXIT_FULLSCREEN.png.sha1 b/chromium/components/fullscreen_control_strings_grdp/IDS_FULLSCREEN_HOLD_ESC_TO_EXIT_FULLSCREEN.png.sha1
new file mode 100644
index 00000000000..eabb423a156
--- /dev/null
+++ b/chromium/components/fullscreen_control_strings_grdp/IDS_FULLSCREEN_HOLD_ESC_TO_EXIT_FULLSCREEN.png.sha1
@@ -0,0 +1 @@
+40ceb982a00e927fce67fef094db9190f55affdf \ No newline at end of file
diff --git a/chromium/components/fullscreen_control_strings_grdp/OWNERS b/chromium/components/fullscreen_control_strings_grdp/OWNERS
new file mode 100644
index 00000000000..37b4d8b8812
--- /dev/null
+++ b/chromium/components/fullscreen_control_strings_grdp/OWNERS
@@ -0,0 +1 @@
+file://components/fullscreen_control/OWNERS
diff --git a/chromium/components/fullscreen_control_strings_grdp/README.md b/chromium/components/fullscreen_control_strings_grdp/README.md
new file mode 100644
index 00000000000..119d8b9bff7
--- /dev/null
+++ b/chromium/components/fullscreen_control_strings_grdp/README.md
@@ -0,0 +1,5 @@
+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/gcm_driver/BUILD.gn b/chromium/components/gcm_driver/BUILD.gn
index 21d0cc80e3d..1cbe23d6e7b 100644
--- a/chromium/components/gcm_driver/BUILD.gn
+++ b/chromium/components/gcm_driver/BUILD.gn
@@ -77,10 +77,6 @@ static_library("gcm_driver") {
"//components/gcm_driver/instance_id",
]
- if (is_chromeos_ash) {
- deps += [ "//components/timers" ]
- }
-
if (use_gcm_from_platform) {
assert(is_android)
sources += [
diff --git a/chromium/components/google/core/common/google_util.cc b/chromium/components/google/core/common/google_util.cc
index c6bfc4cec94..f0df49dd17a 100644
--- a/chromium/components/google/core/common/google_util.cc
+++ b/chromium/components/google/core/common/google_util.cc
@@ -16,6 +16,7 @@
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -145,7 +146,7 @@ bool HasGoogleSearchQueryParam(base::StringPiece str) {
url::Component query(0, static_cast<int>(str.length())), key, value;
while (url::ExtractQueryKeyValue(str.data(), &query, &key, &value)) {
base::StringPiece key_str = str.substr(key.begin, key.len);
- if (key_str == "q" || key_str == "as_q")
+ if (key_str == "q" || key_str == "as_q" || key_str == "imgurl")
return true;
}
return false;
@@ -181,7 +182,7 @@ std::string GetGoogleCountryCode(const GURL& google_homepage_url) {
// so use Spain instead.
if (country_code == "cat")
return "es";
- return country_code.as_string();
+ return std::string(country_code);
}
GURL GetGoogleSearchURL(const GURL& google_homepage_url) {
@@ -257,7 +258,7 @@ bool IsGoogleSearchUrl(const GURL& url) {
// Make sure the path is a known search path.
base::StringPiece path(url.path_piece());
bool is_home_page_base = IsPathHomePageBase(path);
- if (!is_home_page_base && (path != "/search"))
+ if (!is_home_page_base && path != "/search" && path != "/imgres")
return false;
// Check for query parameter in URL parameter and hash fragment, depending on
diff --git a/chromium/components/guest_os/guest_os_engagement_metrics.cc b/chromium/components/guest_os/guest_os_engagement_metrics.cc
index 350b34d52ae..9732ea547bb 100644
--- a/chromium/components/guest_os/guest_os_engagement_metrics.cc
+++ b/chromium/components/guest_os/guest_os_engagement_metrics.cc
@@ -39,19 +39,41 @@ GuestOsEngagementMetrics::GuestOsEngagementMetrics(
WindowMatcher window_matcher,
const std::string& pref_prefix,
const std::string& uma_name)
+ : GuestOsEngagementMetrics(pref_service,
+ window_matcher,
+ pref_prefix,
+ uma_name,
+ base::DefaultClock::GetInstance(),
+ base::DefaultTickClock::GetInstance()) {}
+
+// Private, for testing use only
+GuestOsEngagementMetrics::GuestOsEngagementMetrics(
+ PrefService* pref_service,
+ WindowMatcher window_matcher,
+ const std::string& pref_prefix,
+ const std::string& uma_name,
+ const base::Clock* clock,
+ const base::TickClock* tick_clock)
: 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()),
+ clock_(clock),
+ tick_clock_(tick_clock),
last_update_ticks_(tick_clock_->NowTicks()) {
- // If WMHelper doesn't exist, do nothing. This occurs in tests.
+ // WMHelper, SessionManager and PowerManagerClient may not exist in tests.
if (exo::WMHelper::HasInstance())
exo::WMHelper::GetInstance()->AddActivationObserver(this);
- session_manager::SessionManager::Get()->AddObserver(this);
- chromeos::PowerManagerClient::Get()->AddObserver(this);
+ if (session_manager::SessionManager::Get()) {
+ session_active_ =
+ (session_manager::SessionManager::Get()->session_state() ==
+ session_manager::SessionState::ACTIVE);
+ session_manager::SessionManager::Get()->AddObserver(this);
+ }
+
+ if (chromeos::PowerManagerClient::Get())
+ chromeos::PowerManagerClient::Get()->AddObserver(this);
DCHECK(pref_service_);
RestoreEngagementTimeFromPrefs();
@@ -69,8 +91,12 @@ GuestOsEngagementMetrics::~GuestOsEngagementMetrics() {
UpdateEngagementTime();
SaveEngagementTimeToPrefs();
- chromeos::PowerManagerClient::Get()->RemoveObserver(this);
- session_manager::SessionManager::Get()->RemoveObserver(this);
+ // Observers for WMHelper, SessionManager and PowerManagerClient may not
+ // have been added in tests.
+ if (chromeos::PowerManagerClient::Get())
+ chromeos::PowerManagerClient::Get()->RemoveObserver(this);
+ if (session_manager::SessionManager::Get())
+ session_manager::SessionManager::Get()->RemoveObserver(this);
// If WMHelper is already destroyed, do nothing.
// TODO(crbug.com/748380): Fix shutdown order.
@@ -85,14 +111,6 @@ void GuestOsEngagementMetrics::SetBackgroundActive(bool background_active) {
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,
@@ -224,4 +242,18 @@ bool GuestOsEngagementMetrics::ShouldRecordEngagementTimeToUma() const {
return day_id_ != GetDayId(clock_);
}
+std::unique_ptr<GuestOsEngagementMetrics>
+GuestOsEngagementMetrics::GetEngagementMetricsForTesting(
+ PrefService* pref_service,
+ WindowMatcher window_matcher,
+ const std::string& pref_prefix,
+ const std::string& uma_name,
+ const base::Clock* clock,
+ const base::TickClock* tick_clock) {
+ GuestOsEngagementMetrics* metrics = new GuestOsEngagementMetrics(
+ pref_service, window_matcher, pref_prefix, uma_name, clock, tick_clock);
+ // WrapUnique is needed because the constructor is private.
+ return base::WrapUnique(metrics);
+}
+
} // 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
index 0b74315953a..fd06e8c9317 100644
--- a/chromium/components/guest_os/guest_os_engagement_metrics.h
+++ b/chromium/components/guest_os/guest_os_engagement_metrics.h
@@ -56,8 +56,6 @@ class GuestOsEngagementMetrics : public wm::ActivationChangeObserver,
// 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,
@@ -70,7 +68,23 @@ class GuestOsEngagementMetrics : public wm::ActivationChangeObserver,
void ScreenIdleStateChanged(
const power_manager::ScreenIdleState& proto) override;
+ static std::unique_ptr<GuestOsEngagementMetrics>
+ GetEngagementMetricsForTesting(PrefService* pref_service,
+ WindowMatcher window_matcher,
+ const std::string& pref_prefix,
+ const std::string& uma_name,
+ const base::Clock* clock,
+ const base::TickClock* tick_clock);
+
private:
+ // Private, for testing use only
+ GuestOsEngagementMetrics(PrefService* pref_service,
+ WindowMatcher window_matcher,
+ const std::string& pref_prefix,
+ const std::string& uma_name,
+ const base::Clock* clock,
+ const base::TickClock* tick_clock);
+
// Restores accumulated engagement time in previous sessions from profile
// preferences.
void RestoreEngagementTimeFromPrefs();
diff --git a/chromium/components/guest_os/guest_os_engagement_metrics_unittest.cc b/chromium/components/guest_os/guest_os_engagement_metrics_unittest.cc
index cb44d320ec5..a982da38023 100644
--- a/chromium/components/guest_os/guest_os_engagement_metrics_unittest.cc
+++ b/chromium/components/guest_os/guest_os_engagement_metrics_unittest.cc
@@ -46,16 +46,11 @@ class GuestOsEngagementMetricsTest : public testing::Test {
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_);
+ CreateEngagementMetrics();
SetSessionState(session_manager::SessionState::ACTIVE);
}
@@ -111,6 +106,17 @@ class GuestOsEngagementMetricsTest : public testing::Test {
base::TimeDelta::FromSeconds(seconds), 1);
}
+ void DestroyEngagementMetrics() { engagement_metrics_.reset(); }
+
+ void CreateEngagementMetrics() {
+ engagement_metrics_ =
+ GuestOsEngagementMetrics::GetEngagementMetricsForTesting(
+ pref_service_.get(),
+ base::BindRepeating(&GuestOsEngagementMetricsTest::MatchWindow,
+ base::Unretained(this)),
+ kPrefPrefix, kUmaName, &test_clock_, &test_tick_clock_);
+ }
+
private:
bool MatchWindow(const aura::Window* window) {
return window == matched_window_.get();
@@ -216,5 +222,27 @@ TEST_F(GuestOsEngagementMetricsTest,
ExpectTime(kHistogramActiveTotal, 16);
}
+TEST_F(GuestOsEngagementMetricsTest, RecordEngagementTimeIfDestroyed) {
+ AdvanceSeconds(1); // Total
+ engagement_metrics()->SetBackgroundActive(true);
+ FocusMatchedWindow();
+ AdvanceSeconds(1); // Total + foreground + active
+
+ DestroyEngagementMetrics();
+
+ AdvanceSeconds(1); // Nothing
+
+ CreateEngagementMetrics();
+ engagement_metrics()->SetBackgroundActive(true);
+ FocusNonMatchedWindow();
+ AdvanceSeconds(1); // Total + background + active
+
+ TriggerRecordEngagementTimeToUma();
+ ExpectTime(kHistogramTotal, 3);
+ ExpectTime(kHistogramForeground, 1);
+ ExpectTime(kHistogramBackground, 1);
+ ExpectTime(kHistogramActiveTotal, 2);
+}
+
} // namespace
} // namespace guest_os
diff --git a/chromium/components/guest_view/browser/guest_view_base.cc b/chromium/components/guest_view/browser/guest_view_base.cc
index 94951a8f48a..6716d5efd28 100644
--- a/chromium/components/guest_view/browser/guest_view_base.cc
+++ b/chromium/components/guest_view/browser/guest_view_base.cc
@@ -43,15 +43,15 @@ base::LazyInstance<WebContentsGuestViewMap>::Leaky g_webcontents_guestview_map =
} // namespace
-SetSizeParams::SetSizeParams() {
-}
-SetSizeParams::~SetSizeParams() {
-}
+SetSizeParams::SetSizeParams() = default;
+SetSizeParams::~SetSizeParams() = default;
+// TODO(832879): It would be better to have proper ownership semantics than
+// manually destroying guests and their WebContents.
+//
// This observer ensures that the GuestViewBase destroys itself when its
// embedder goes away. It also tracks when the embedder's fullscreen is
-// toggled or when its page scale factor changes so the guest can change
-// itself accordingly.
+// toggled so the guest can change itself accordingly.
class GuestViewBase::OwnerContentsObserver : public WebContentsObserver {
public:
OwnerContentsObserver(GuestViewBase* guest,
@@ -61,7 +61,7 @@ class GuestViewBase::OwnerContentsObserver : public WebContentsObserver {
destroyed_(false),
guest_(guest) {}
- ~OwnerContentsObserver() override {}
+ ~OwnerContentsObserver() override = default;
// WebContentsObserver implementation.
void WebContentsDestroyed() override {
@@ -71,6 +71,8 @@ class GuestViewBase::OwnerContentsObserver : public WebContentsObserver {
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override {
+ // TODO(1206312, 1205920): It is incorrect to assume that a navigation will
+ // destroy the embedder.
// If the embedder navigates to a different page then destroy the guest.
if (!navigation_handle->IsInMainFrame() ||
!navigation_handle->HasCommitted() ||
@@ -149,7 +151,7 @@ class GuestViewBase::OpenerLifetimeObserver : public WebContentsObserver {
: WebContentsObserver(guest->GetOpener()->web_contents()),
guest_(guest) {}
- ~OpenerLifetimeObserver() override {}
+ ~OpenerLifetimeObserver() override = default;
// WebContentsObserver implementation.
void WebContentsDestroyed() override {
diff --git a/chromium/components/guest_view/browser/guest_view_base.h b/chromium/components/guest_view/browser/guest_view_base.h
index b879bf14e7f..9a6c512c778 100644
--- a/chromium/components/guest_view/browser/guest_view_base.h
+++ b/chromium/components/guest_view/browser/guest_view_base.h
@@ -449,8 +449,8 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
std::unique_ptr<base::DictionaryValue> attach_params_;
// This observer ensures that this guest self-destructs if the embedder goes
- // away. It also tracks when the embedder's fullscreen is toggled or when its
- // page scale factor changes so the guest can change itself accordingly.
+ // away. It also tracks when the embedder's fullscreen is toggled so the guest
+ // can change itself accordingly.
std::unique_ptr<OwnerContentsObserver> owner_contents_observer_;
// This observer ensures that if the guest is unattached and its opener goes
diff --git a/chromium/components/guest_view/browser/guest_view_manager.cc b/chromium/components/guest_view/browser/guest_view_manager.cc
index 8c49510cfc1..77ba8a045ab 100644
--- a/chromium/components/guest_view/browser/guest_view_manager.cc
+++ b/chromium/components/guest_view/browser/guest_view_manager.cc
@@ -237,6 +237,19 @@ SiteInstance* GuestViewManager::GetGuestSiteInstance(
return nullptr;
}
+void GuestViewManager::ForEachUnattachedGuest(
+ content::WebContents* owner_web_contents,
+ base::RepeatingCallback<void(content::WebContents*)> callback) {
+ for (const auto& guest : guest_web_contents_by_instance_id_) {
+ auto* guest_view = GuestViewBase::FromWebContents(guest.second);
+
+ if (guest_view->owner_web_contents() == owner_web_contents &&
+ !guest_view->attached()) {
+ callback.Run(guest_view->web_contents());
+ }
+ }
+}
+
bool GuestViewManager::ForEachGuest(WebContents* owner_web_contents,
const GuestCallback& callback) {
for (const auto& guest : guest_web_contents_by_instance_id_) {
@@ -520,8 +533,7 @@ bool GuestViewManager::CanEmbedderAccessInstanceID(
GuestViewManager::ElementInstanceKey::ElementInstanceKey()
: embedder_process_id(content::ChildProcessHost::kInvalidUniqueID),
- element_instance_id(content::ChildProcessHost::kInvalidUniqueID) {
-}
+ element_instance_id(kInstanceIDNone) {}
GuestViewManager::ElementInstanceKey::ElementInstanceKey(
int embedder_process_id,
diff --git a/chromium/components/guest_view/browser/guest_view_manager.h b/chromium/components/guest_view/browser/guest_view_manager.h
index 6375b655843..1947870ae34 100644
--- a/chromium/components/guest_view/browser/guest_view_manager.h
+++ b/chromium/components/guest_view/browser/guest_view_manager.h
@@ -125,6 +125,9 @@ class GuestViewManager : public content::BrowserPluginGuestManager,
int element_instance_id);
// BrowserPluginGuestManager implementation.
+ void ForEachUnattachedGuest(
+ content::WebContents* owner_web_contents,
+ base::RepeatingCallback<void(content::WebContents*)> callback) override;
bool ForEachGuest(content::WebContents* owner_web_contents,
const GuestCallback& callback) override;
content::WebContents* GetFullPageGuest(
diff --git a/chromium/components/guest_view/common/DIR_METADATA b/chromium/components/guest_view/common/DIR_METADATA
deleted file mode 100644
index 22d44120c3e..00000000000
--- a/chromium/components/guest_view/common/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Platform>Apps>BrowserTag"
-}
diff --git a/chromium/components/guest_view/common/guest_view_messages.h b/chromium/components/guest_view/common/guest_view_messages.h
index be5ada164e4..82a0d4ea1d3 100644
--- a/chromium/components/guest_view/common/guest_view_messages.h
+++ b/chromium/components/guest_view/common/guest_view_messages.h
@@ -9,6 +9,7 @@
#include "base/values.h"
#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
#define IPC_MESSAGE_START GuestViewMsgStart
diff --git a/chromium/components/guest_view/renderer/guest_view_container.h b/chromium/components/guest_view/renderer/guest_view_container.h
index 73943377d5a..d934bb80181 100644
--- a/chromium/components/guest_view/renderer/guest_view_container.h
+++ b/chromium/components/guest_view/renderer/guest_view_container.h
@@ -9,6 +9,7 @@
#include "base/containers/circular_deque.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "ipc/ipc_message.h"
#include "v8/include/v8.h"
diff --git a/chromium/components/guest_view/renderer/guest_view_container_dispatcher.cc b/chromium/components/guest_view/renderer/guest_view_container_dispatcher.cc
index 23a5b51958a..a21c58226d7 100644
--- a/chromium/components/guest_view/renderer/guest_view_container_dispatcher.cc
+++ b/chromium/components/guest_view/renderer/guest_view_container_dispatcher.cc
@@ -7,6 +7,7 @@
#include "components/guest_view/common/guest_view_constants.h"
#include "components/guest_view/renderer/guest_view_container.h"
#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
namespace guest_view {
diff --git a/chromium/components/guest_view/renderer/guest_view_request.h b/chromium/components/guest_view/renderer/guest_view_request.h
index cf8824b9876..4b151d338af 100644
--- a/chromium/components/guest_view/renderer/guest_view_request.h
+++ b/chromium/components/guest_view/renderer/guest_view_request.h
@@ -57,4 +57,4 @@ class GuestViewRequest {
} // namespace guest_view
-#endif // COMPONENTS_GUEST_VIEW_RENDERER_GUEST_VIEW_CONTAINER_H_
+#endif // COMPONENTS_GUEST_VIEW_RENDERER_GUEST_VIEW_REQUEST_H_
diff --git a/chromium/components/guest_view/renderer/iframe_guest_view_request.h b/chromium/components/guest_view/renderer/iframe_guest_view_request.h
index fa97ad17fef..1700d289cfe 100644
--- a/chromium/components/guest_view/renderer/iframe_guest_view_request.h
+++ b/chromium/components/guest_view/renderer/iframe_guest_view_request.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/macros.h"
+#include "base/values.h"
#include "components/guest_view/renderer/guest_view_request.h"
#include "ipc/ipc_message.h"
#include "v8/include/v8.h"
diff --git a/chromium/components/gwp_asan/client/guarded_page_allocator.cc b/chromium/components/gwp_asan/client/guarded_page_allocator.cc
index fc28cd50b2f..f1838cacb86 100644
--- a/chromium/components/gwp_asan/client/guarded_page_allocator.cc
+++ b/chromium/components/gwp_asan/client/guarded_page_allocator.cc
@@ -11,8 +11,8 @@
#include "base/bits.h"
#include "base/debug/stack_trace.h"
#include "base/logging.h"
+#include "base/memory/page_size.h"
#include "base/no_destructor.h"
-#include "base/process/process_metrics.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
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 870eacf46bd..2ae1f7f9d00 100644
--- a/chromium/components/gwp_asan/client/guarded_page_allocator_unittest.cc
+++ b/chromium/components/gwp_asan/client/guarded_page_allocator_unittest.cc
@@ -11,7 +11,7 @@
#include <vector>
#include "base/bits.h"
-#include "base/process/process_metrics.h"
+#include "base/memory/page_size.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "base/threading/simple_thread.h"
diff --git a/chromium/components/gwp_asan/client/gwp_asan.cc b/chromium/components/gwp_asan/client/gwp_asan.cc
index a838cac6ef1..6fdaab81b1f 100644
--- a/chromium/components/gwp_asan/client/gwp_asan.cc
+++ b/chromium/components/gwp_asan/client/gwp_asan.cc
@@ -16,12 +16,11 @@
#include "base/macros.h"
#include "base/metrics/field_trial_params.h"
#include "base/numerics/safe_math.h"
-#include "base/optional.h"
#include "base/partition_alloc_buildflags.h"
#include "base/rand_util.h"
-#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "components/gwp_asan/client/guarded_page_allocator.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if BUILDFLAG(USE_ALLOCATOR_SHIM)
#include "components/gwp_asan/client/sampling_malloc_shims.h"
@@ -135,11 +134,11 @@ size_t AllocationSamplingFrequency(const base::Feature& feature) {
} // namespace
// Exported for testing.
-GWP_ASAN_EXPORT base::Optional<AllocatorSettings> GetAllocatorSettings(
+GWP_ASAN_EXPORT absl::optional<AllocatorSettings> GetAllocatorSettings(
const base::Feature& feature,
bool boost_sampling) {
if (!base::FeatureList::IsEnabled(feature))
- return base::nullopt;
+ return absl::nullopt;
static_assert(AllocatorState::kMaxSlots <= std::numeric_limits<int>::max(),
"kMaxSlots out of range");
@@ -153,7 +152,7 @@ GWP_ASAN_EXPORT base::Optional<AllocatorSettings> GetAllocatorSettings(
kDefaultTotalPages);
if (total_pages < 1 || total_pages > kMaxSlots) {
DLOG(ERROR) << "GWP-ASan TotalPages is out-of-range: " << total_pages;
- return base::nullopt;
+ return absl::nullopt;
}
int max_metadata = GetFieldTrialParamByFeatureAsInt(feature, "MaxMetadata",
@@ -161,7 +160,7 @@ GWP_ASAN_EXPORT base::Optional<AllocatorSettings> GetAllocatorSettings(
if (max_metadata < 1 || max_metadata > std::min(total_pages, kMaxMetadata)) {
DLOG(ERROR) << "GWP-ASan MaxMetadata is out-of-range: " << max_metadata
<< " with TotalPages = " << total_pages;
- return base::nullopt;
+ return absl::nullopt;
}
int max_allocations = GetFieldTrialParamByFeatureAsInt(
@@ -169,15 +168,15 @@ GWP_ASAN_EXPORT base::Optional<AllocatorSettings> GetAllocatorSettings(
if (max_allocations < 1 || max_allocations > max_metadata) {
DLOG(ERROR) << "GWP-ASan MaxAllocations is out-of-range: "
<< max_allocations << " with MaxMetadata = " << max_metadata;
- return base::nullopt;
+ return absl::nullopt;
}
size_t alloc_sampling_freq = AllocationSamplingFrequency(feature);
if (!alloc_sampling_freq)
- return base::nullopt;
+ return absl::nullopt;
if (!SampleProcess(feature, boost_sampling))
- return base::nullopt;
+ return absl::nullopt;
return AllocatorSettings{max_allocations, max_metadata, total_pages,
alloc_sampling_freq};
diff --git a/chromium/components/gwp_asan/client/gwp_asan_unittest.cc b/chromium/components/gwp_asan/client/gwp_asan_unittest.cc
index 9a92aef664b..22410002983 100644
--- a/chromium/components/gwp_asan/client/gwp_asan_unittest.cc
+++ b/chromium/components/gwp_asan/client/gwp_asan_unittest.cc
@@ -10,17 +10,17 @@
#include <utility>
#include "base/metrics/field_trial_params.h"
-#include "base/optional.h"
#include "base/test/gtest_util.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace gwp_asan {
namespace internal {
-base::Optional<AllocatorSettings> GetAllocatorSettings(
+absl::optional<AllocatorSettings> GetAllocatorSettings(
const base::Feature& feature,
bool boost_sampling);
diff --git a/chromium/components/gwp_asan/client/sampling_malloc_shims_unittest.cc b/chromium/components/gwp_asan/client/sampling_malloc_shims_unittest.cc
index d64c2feacdb..8eeb3ec96e4 100644
--- a/chromium/components/gwp_asan/client/sampling_malloc_shims_unittest.cc
+++ b/chromium/components/gwp_asan/client/sampling_malloc_shims_unittest.cc
@@ -11,7 +11,7 @@
#include "base/allocator/allocator_shim.h"
#include "base/callback_helpers.h"
-#include "base/process/process_metrics.h"
+#include "base/memory/page_size.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/gtest_util.h"
#include "base/test/multiprocess_test.h"
diff --git a/chromium/components/gwp_asan/client/sampling_partitionalloc_shims_unittest.cc b/chromium/components/gwp_asan/client/sampling_partitionalloc_shims_unittest.cc
index 5d3de48f926..2451a1c7a93 100644
--- a/chromium/components/gwp_asan/client/sampling_partitionalloc_shims_unittest.cc
+++ b/chromium/components/gwp_asan/client/sampling_partitionalloc_shims_unittest.cc
@@ -14,8 +14,8 @@
#include "base/allocator/partition_allocator/partition_root.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
+#include "base/memory/page_size.h"
#include "base/partition_alloc_buildflags.h"
-#include "base/process/process_metrics.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/gtest_util.h"
#include "base/test/multiprocess_test.h"
diff --git a/chromium/components/gwp_asan/common/allocator_state.cc b/chromium/components/gwp_asan/common/allocator_state.cc
index 5d8130420ac..29e744d15f3 100644
--- a/chromium/components/gwp_asan/common/allocator_state.cc
+++ b/chromium/components/gwp_asan/common/allocator_state.cc
@@ -8,7 +8,7 @@
#include "base/bits.h"
#include "base/logging.h"
-#include "base/process/process_metrics.h"
+#include "base/memory/page_size.h"
#include "base/strings/stringprintf.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
diff --git a/chromium/components/gwp_asan/common/allocator_state_unittest.cc b/chromium/components/gwp_asan/common/allocator_state_unittest.cc
index 9f602c66bd7..990e43bc57c 100644
--- a/chromium/components/gwp_asan/common/allocator_state_unittest.cc
+++ b/chromium/components/gwp_asan/common/allocator_state_unittest.cc
@@ -6,7 +6,7 @@
#include <limits>
-#include "base/process/process_metrics.h"
+#include "base/memory/page_size.h"
#include "base/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
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 dc160204bf2..67a58a51efd 100644
--- a/chromium/components/gwp_asan/crash_handler/crash_handler_unittest.cc
+++ b/chromium/components/gwp_asan/crash_handler/crash_handler_unittest.cc
@@ -13,9 +13,9 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/memory/page_size.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"
#include "base/test/multiprocess_test.h"
diff --git a/chromium/components/heap_profiling/in_process/heap_profiler_controller.cc b/chromium/components/heap_profiling/in_process/heap_profiler_controller.cc
index a90461f4dc1..ff2524792f1 100644
--- a/chromium/components/heap_profiling/in_process/heap_profiler_controller.cc
+++ b/chromium/components/heap_profiling/in_process/heap_profiler_controller.cc
@@ -75,6 +75,34 @@ void HeapProfilerController::Start() {
ScheduleNextSnapshot(stopped_, base::TimeDelta::FromMinutes(interval));
}
+bool HeapProfilerController::SampleComparator::operator()(
+ const Sample& lhs,
+ const Sample& rhs) const {
+ // We consider two samples to be equal if and only if their stacks are equal.
+ // Note that equal stack implies equal allocator. It's technically possible
+ // for two equal stacks to have different thread names, but it's an edge
+ // condition and marking them as equal will not significantly change analysis.
+ return lhs.stack < rhs.stack;
+}
+
+// Merges samples that have identical stack traces, excluding total and size.
+HeapProfilerController::SampleMap HeapProfilerController::MergeSamples(
+ const std::vector<Sample>& samples) {
+ SampleMap results;
+ for (const Sample& sample : samples) {
+ size_t count = std::max<size_t>(
+ static_cast<size_t>(
+ std::llround(static_cast<double>(sample.total) / sample.size)),
+ 1);
+ // Either update the existing entry or construct a new entry [with default
+ // initializer 0].
+ SampleValue& value = results[sample];
+ value.total += sample.total;
+ value.count += count;
+ }
+ return results;
+}
+
// static
void HeapProfilerController::ScheduleNextSnapshot(
scoped_refptr<StoppedFlag> stopped,
@@ -116,7 +144,12 @@ void HeapProfilerController::RetrieveAndSendSnapshot() {
metrics::CallStackProfileParams::PERIODIC_HEAP_COLLECTION);
metrics::CallStackProfileBuilder profile_builder(params);
- for (const base::SamplingHeapProfiler::Sample& sample : samples) {
+ SampleMap merged_samples = MergeSamples(samples);
+
+ for (auto& pair : merged_samples) {
+ const Sample& sample = pair.first;
+ const SampleValue& value = pair.second;
+
std::vector<base::Frame> frames;
frames.reserve(sample.stack.size());
for (const void* frame : sample.stack) {
@@ -125,14 +158,10 @@ void HeapProfilerController::RetrieveAndSendSnapshot() {
module_cache.GetModuleForAddress(address);
frames.emplace_back(address, module);
}
- size_t count = std::max<size_t>(
- static_cast<size_t>(
- std::llround(static_cast<double>(sample.total) / sample.size)),
- 1);
// Heap "samples" represent allocation stacks aggregated over time so do not
// have a meaningful timestamp.
profile_builder.OnSampleCompleted(std::move(frames), base::TimeTicks(),
- sample.total, count);
+ value.total, value.count);
}
profile_builder.OnProfileCompleted(base::TimeDelta(), base::TimeDelta());
diff --git a/chromium/components/heap_profiling/in_process/heap_profiler_controller.h b/chromium/components/heap_profiling/in_process/heap_profiler_controller.h
index a3c96ee7adc..139f54e40b8 100644
--- a/chromium/components/heap_profiling/in_process/heap_profiler_controller.h
+++ b/chromium/components/heap_profiling/in_process/heap_profiler_controller.h
@@ -5,8 +5,12 @@
#ifndef COMPONENTS_HEAP_PROFILING_IN_PROCESS_HEAP_PROFILER_CONTROLLER_H_
#define COMPONENTS_HEAP_PROFILING_IN_PROCESS_HEAP_PROFILER_CONTROLLER_H_
+#include <map>
+#include <vector>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/sampling_heap_profiler/sampling_heap_profiler.h"
#include "base/synchronization/atomic_flag.h"
// HeapProfilerController controls collection of sampled heap allocation
@@ -19,6 +23,29 @@ class HeapProfilerController {
// Starts periodic heap snapshot collection.
void Start();
+ // Public for testing.
+ using Sample = base::SamplingHeapProfiler::Sample;
+ struct SampleComparator {
+ bool operator()(const Sample& lhs, const Sample& rhs) const;
+ };
+ struct SampleValue {
+ // Sum of all allocations attributed to this Sample's stack trace.
+ size_t total = 0;
+ // Count of all allocations attributed to this Sample's stack trace.
+ size_t count = 0;
+ };
+
+ // The value of the map tracks total size and count of all Samples associated
+ // with the key's stack trace.
+ // We use a std::map here since most comparisons will early out in one of the
+ // first entries in the vector. For reference: the first entry is likely the
+ // address of the code calling malloc(). Using a hash-based container would
+ // typically entail hashing the entire contents of the stack trace.
+ using SampleMap = std::map<Sample, SampleValue, SampleComparator>;
+
+ // Merges samples that have identical stack traces, excluding total and size.
+ static SampleMap MergeSamples(const std::vector<Sample>& samples);
+
private:
using StoppedFlag = base::RefCountedData<base::AtomicFlag>;
diff --git a/chromium/components/heap_profiling/in_process/heap_profiler_controller_unittest.cc b/chromium/components/heap_profiling/in_process/heap_profiler_controller_unittest.cc
index eb4c10d2bbc..f32a4d76407 100644
--- a/chromium/components/heap_profiling/in_process/heap_profiler_controller_unittest.cc
+++ b/chromium/components/heap_profiling/in_process/heap_profiler_controller_unittest.cc
@@ -89,3 +89,27 @@ TEST_F(HeapProfilerControllerTest, ProfileCollectionsScheduler) {
EXPECT_LE(kSnapshotsToCollect, profile_count);
}
#endif
+
+TEST_F(HeapProfilerControllerTest, MergeSamples) {
+ using Sample = base::SamplingHeapProfiler::Sample;
+ Sample sample1(/*size=*/5, /*total=*/100, /*ordinal=*/1);
+ sample1.stack = {reinterpret_cast<void*>(0x1), reinterpret_cast<void*>(0x2)};
+ Sample sample2(/*size=*/6, /*total=*/102, /*ordinal=*/2);
+ sample2.stack = {reinterpret_cast<void*>(0x1), reinterpret_cast<void*>(0x3)};
+ Sample sample3(/*size=*/7, /*total=*/105, /*ordinal=*/3);
+ sample3.stack = {reinterpret_cast<void*>(0x1), reinterpret_cast<void*>(0x2)};
+
+ std::vector<Sample> samples = {sample1, sample2, sample3};
+
+ HeapProfilerController::SampleMap map =
+ HeapProfilerController::MergeSamples(samples);
+ ASSERT_EQ(map.size(), 2u);
+ auto it = map.find(sample1);
+ ASSERT_TRUE(it != map.end());
+ EXPECT_EQ(it->second.count, 35u); // 100 / 5 + 105 / 7 = 35
+ EXPECT_EQ(it->second.total, 205u);
+ it = map.find(sample2);
+ ASSERT_TRUE(it != map.end());
+ EXPECT_EQ(it->second.count, 17u); // 102 / 6 = 17
+ EXPECT_EQ(it->second.total, 102u);
+}
diff --git a/chromium/components/heap_profiling/multi_process/client_connection_manager.cc b/chromium/components/heap_profiling/multi_process/client_connection_manager.cc
index daf60c5efdd..9cff0ef869b 100644
--- a/chromium/components/heap_profiling/multi_process/client_connection_manager.cc
+++ b/chromium/components/heap_profiling/multi_process/client_connection_manager.cc
@@ -76,6 +76,19 @@ bool ShouldProfileNonRendererProcessType(Mode mode, int process_type) {
return false;
}
+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(std::move(client), pid, process_type);
+}
+
void StartProfilingNonRendererChildOnProcessThread(
base::WeakPtr<Controller> controller,
const content::ChildProcessData& data) {
@@ -83,9 +96,6 @@ void StartProfilingNonRendererChildOnProcessThread(
? content::BrowserThread::UI
: content::BrowserThread::IO);
- if (!controller)
- return;
-
content::BrowserChildProcessHost* host =
content::BrowserChildProcessHost::FromID(data.id);
if (!host)
@@ -99,21 +109,16 @@ void StartProfilingNonRendererChildOnProcessThread(
// Tell the child process to start profiling.
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,
- mojo::PendingRemote<mojom::ProfilingClient> client,
- base::ProcessId pid,
- mojom::ProcessType process_type) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
- if (!controller)
- return;
- controller->StartProfilingClient(std::move(client), pid, process_type);
+ auto start_task =
+ base::BindOnce(&StartProfilingClientOnIOThread, std::move(controller),
+ std::move(client), data.GetProcess().Pid(), process_type);
+ if (base::FeatureList::IsEnabled(features::kProcessHostOnUI)) {
+ content::GetIOThreadTaskRunner({})->PostTask(FROM_HERE,
+ std::move(start_task));
+ } else {
+ std::move(start_task).Run();
+ }
}
void StartProfilingBrowserProcessOnIOThread(
@@ -136,12 +141,11 @@ void StartProfilingPidOnProcessThread(base::WeakPtr<Controller> controller,
? content::BrowserThread::UI
: content::BrowserThread::IO);
- if (!controller)
- return;
-
// Check if the request is for the current process.
if (pid == base::GetCurrentProcId()) {
- StartProfilingBrowserProcessOnIOThread(std::move(controller));
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&StartProfilingBrowserProcessOnIOThread,
+ std::move(controller)));
return;
}
@@ -167,9 +171,6 @@ void StartProfilingNonRenderersIfNecessaryOnProcessThread(
? content::BrowserThread::UI
: content::BrowserThread::IO);
- if (!controller)
- return;
-
for (content::BrowserChildProcessHostIterator browser_child_iter;
!browser_child_iter.Done(); ++browser_child_iter) {
const content::ChildProcessData& data = browser_child_iter.GetData();
@@ -209,9 +210,7 @@ Mode ClientConnectionManager::GetMode() {
}
void ClientConnectionManager::StartProfilingProcess(base::ProcessId pid) {
- DCHECK_CURRENTLY_ON(base::FeatureList::IsEnabled(features::kProcessHostOnUI)
- ? content::BrowserThread::UI
- : content::BrowserThread::IO);
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
mode_ = Mode::kManual;
diff --git a/chromium/components/heap_profiling/multi_process/supervisor.cc b/chromium/components/heap_profiling/multi_process/supervisor.cc
index 71015b3a306..68414503d51 100644
--- a/chromium/components/heap_profiling/multi_process/supervisor.cc
+++ b/chromium/components/heap_profiling/multi_process/supervisor.cc
@@ -166,18 +166,15 @@ void Supervisor::RequestTraceWithHeapDump(TraceFinishedCallback callback,
base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED,
base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND,
base::trace_event::MemoryDumpDeterminism::NONE,
- base::AdaptCallbackForRepeating(
- std::move(finished_dump_callback)));
+ std::move(finished_dump_callback));
},
std::move(finished_dump_callback));
// The only reason this should return false is if tracing is already enabled,
// which we've already checked.
- // Use AdaptCallbackForRepeating since the argument passed to StartTracing()
- // is intended to be a OnceCallback, but the code has not yet been migrated.
bool result = content::TracingController::GetInstance()->StartTracing(
GetBackgroundTracingConfig(anonymize),
- base::AdaptCallbackForRepeating(std::move(trigger_memory_dump_callback)));
+ std::move(trigger_memory_dump_callback));
DCHECK(result);
}
diff --git a/chromium/components/heavy_ad_intervention/heavy_ad_service.h b/chromium/components/heavy_ad_intervention/heavy_ad_service.h
index 1c1c9409c22..7a795d19776 100644
--- a/chromium/components/heavy_ad_intervention/heavy_ad_service.h
+++ b/chromium/components/heavy_ad_intervention/heavy_ad_service.h
@@ -6,7 +6,6 @@
#define COMPONENTS_HEAVY_AD_INTERVENTION_HEAVY_AD_SERVICE_H_
#include <memory>
-#include <string>
#include "base/callback.h"
#include "base/macros.h"
diff --git a/chromium/components/history/content/browser/download_conversions.cc b/chromium/components/history/content/browser/download_conversions.cc
index 62f3e90063d..256fecfb1ab 100644
--- a/chromium/components/history/content/browser/download_conversions.cc
+++ b/chromium/components/history/content/browser/download_conversions.cc
@@ -91,6 +91,8 @@ download::DownloadDangerType ToContentDownloadDangerType(
return download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING;
case DownloadDangerType::BLOCKED_UNSUPPORTED_FILETYPE:
return download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE;
+ case DownloadDangerType::DANGEROUS_ACCOUNT_COMRPOMISE:
+ return download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE;
case DownloadDangerType::INVALID:
NOTREACHED();
return download::DOWNLOAD_DANGER_TYPE_MAX;
@@ -140,7 +142,8 @@ DownloadDangerType ToHistoryDownloadDangerType(
return DownloadDangerType::PROMPT_FOR_SCANNING;
case download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE:
return DownloadDangerType::BLOCKED_UNSUPPORTED_FILETYPE;
-
+ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE:
+ return DownloadDangerType::DANGEROUS_ACCOUNT_COMRPOMISE;
default:
NOTREACHED();
return DownloadDangerType::INVALID;
diff --git a/chromium/components/history/content/browser/download_conversions.h b/chromium/components/history/content/browser/download_conversions.h
index 1482efab9a6..274d4d817c8 100644
--- a/chromium/components/history/content/browser/download_conversions.h
+++ b/chromium/components/history/content/browser/download_conversions.h
@@ -7,8 +7,6 @@
#include <stdint.h>
-#include <string>
-
#include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item.h"
diff --git a/chromium/components/history/content/browser/history_database_helper.h b/chromium/components/history/content/browser/history_database_helper.h
index 4a975142715..12f89f1b9a6 100644
--- a/chromium/components/history/content/browser/history_database_helper.h
+++ b/chromium/components/history/content/browser/history_database_helper.h
@@ -13,7 +13,7 @@ namespace history {
struct HistoryDatabaseParams;
-// Returns a HistoryDatabaseParams for |history_dir|.
+// Returns a HistoryDatabaseParams for `history_dir`.
HistoryDatabaseParams HistoryDatabaseParamsForPath(
const base::FilePath& history_dir);
diff --git a/chromium/components/history/core/browser/BUILD.gn b/chromium/components/history/core/browser/BUILD.gn
index a9ab815c940..ed2342484ed 100644
--- a/chromium/components/history/core/browser/BUILD.gn
+++ b/chromium/components/history/core/browser/BUILD.gn
@@ -178,6 +178,7 @@ bundle_data("unit_tests_bundle_data") {
"//components/test/data/history/history.41.sql",
"//components/test/data/history/history.42.sql",
"//components/test/data/history/history.43.sql",
+ "//components/test/data/history/history.44.sql",
"//components/test/data/history/thumbnail_wild/Favicons.corrupt_meta.disable",
"//components/test/data/history/thumbnail_wild/Favicons.v2.init.sql",
"//components/test/data/history/thumbnail_wild/Favicons.v3.init.sql",
diff --git a/chromium/components/history/core/browser/android/android_cache_database.h b/chromium/components/history/core/browser/android/android_cache_database.h
index 273e8e17a99..c2c087c811c 100644
--- a/chromium/components/history/core/browser/android/android_cache_database.h
+++ b/chromium/components/history/core/browser/android/android_cache_database.h
@@ -38,27 +38,27 @@ class AndroidCacheDatabase {
// Clears all rows in the bookmark_cache table; returns true on success.
bool ClearAllBookmarkCache();
- // Marks the given |url_ids| as bookmarked; Returns true on success.
+ // Marks the given `url_ids` as bookmarked; Returns true on success.
bool MarkURLsAsBookmarked(const std::vector<URLID>& url_id);
- // Set the given |url_id|'s favicon column to |favicon_id|. Returns true on
+ // Set the given `url_id`'s favicon column to `favicon_id`. Returns true on
// success.
bool SetFaviconID(URLID url_id, favicon_base::FaviconID favicon_id);
// The search_terms table -------------------------------------------------
//
- // Add a row in the search_term table with the given |term| and
- // |last_visit_time|. Return the new row's id on success, otherwise 0 is
+ // Add a row in the search_term table with the given `term` and
+ // `last_visit_time`. Return the new row's id on success, otherwise 0 is
// returned.
SearchTermID AddSearchTerm(const std::u16string& term,
const base::Time& last_visit_time);
- // Updates the |id|'s row with the given |row|; returns true on success.
+ // Updates the `id`'s row with the given `row`; returns true on success.
bool UpdateSearchTerm(SearchTermID id, const SearchTermRow& row);
- // Get SearchTermRow of the given |term|; return the row id on success.
+ // Get SearchTermRow of the given `term`; return the row id on success.
// otherwise 0 is returned.
- // The found row is return in |row| if it is not NULL.
+ // The found row is return in `row` if it is not NULL.
SearchTermID GetSearchTerm(const std::u16string& term, SearchTermRow* row);
// Delete the search terms which don't exist in keyword_search_terms table.
diff --git a/chromium/components/history/core/browser/android/android_history_types.h b/chromium/components/history/core/browser/android/android_history_types.h
index 81cd383a28d..ab37d9efb5f 100644
--- a/chromium/components/history/core/browser/android/android_history_types.h
+++ b/chromium/components/history/core/browser/android/android_history_types.h
@@ -137,7 +137,7 @@ class HistoryAndBookmarkRow {
}
URLID url_id() const { return url_id_; }
- // Returns true if the given |id| has been set explicitly.
+ // Returns true if the given `id` has been set explicitly.
bool is_value_set_explicitly(ColumnID id) const {
return values_set_.find(id) != values_set_.end();
}
@@ -214,7 +214,7 @@ class SearchRow {
keyword_id_ = keyword_id;
}
- // Returns true if the given |id| has been set explicitly.
+ // Returns true if the given `id` has been set explicitly.
bool is_value_set_explicitly(ColumnID id) const {
return values_set_.find(id) != values_set_.end();
}
diff --git a/chromium/components/history/core/browser/android/android_urls_database.h b/chromium/components/history/core/browser/android/android_urls_database.h
index 37b714e7b05..9b465e5d82e 100644
--- a/chromium/components/history/core/browser/android/android_urls_database.h
+++ b/chromium/components/history/core/browser/android/android_urls_database.h
@@ -34,24 +34,24 @@ class AndroidURLsDatabase {
// table was created or already exists.
bool CreateAndroidURLsTable();
- // Adds a new mapping between |raw_url| and |url_id|, returns the id if it
+ // Adds a new mapping between `raw_url` and `url_id`, returns the id if it
// succeeds, otherwise 0 is returned.
AndroidURLID AddAndroidURLRow(const std::string& raw_url, URLID url_id);
- // Looks up the given |url_id| in android_urls table. Returns true if success,
- // and fill in the |row| if it not NULL, returns false if the |url_id| is not
+ // Looks up the given `url_id` in android_urls table. Returns true if success,
+ // and fill in the `row` if it not NULL, returns false if the `url_id` is not
// found.
bool GetAndroidURLRow(URLID url_id, AndroidURLRow* row);
- // Deletes the rows whose url_id is in |url_ids|. Returns true if all
- // |url_ids| were found and deleted, otherwise false is returned.
+ // Deletes the rows whose url_id is in `url_ids`. Returns true if all
+ // `url_ids` were found and deleted, otherwise false is returned.
bool DeleteAndroidURLRows(const std::vector<URLID>& url_ids);
// Deletes all the rows whose url_id doesn't exist in urls table. Returns true
// on success.
bool DeleteUnusedAndroidURLs();
- // Updates the row of |id| with the given |raw_url| and |url_id|. Returns true
+ // Updates the row of `id` with the given `raw_url` and `url_id`. Returns true
// on success.
bool UpdateAndroidURLRow(AndroidURLID id,
const std::string& raw_url,
diff --git a/chromium/components/history/core/browser/android/sql_handler.h b/chromium/components/history/core/browser/android/sql_handler.h
index 02c28d2b724..a257abbbb48 100644
--- a/chromium/components/history/core/browser/android/sql_handler.h
+++ b/chromium/components/history/core/browser/android/sql_handler.h
@@ -38,30 +38,30 @@ typedef std::vector<TableIDRow> TableIDRows;
// need be inserted or updated.
class SQLHandler {
public:
- // |columns| is the implementation's columns.
- // |column_count| is the number of column in |columns|.
+ // `columns` is the implementation's columns.
+ // `column_count` is the number of column in `columns`.
SQLHandler(const HistoryAndBookmarkRow::ColumnID columns[], int column_count);
virtual ~SQLHandler();
- // Updates the rows whose URLID or URL is in the given |ids_set| with new
- // value stored in |row|. Return true if the update succeeds.
+ // Updates the rows whose URLID or URL is in the given `ids_set` with new
+ // value stored in `row`. Return true if the update succeeds.
virtual bool Update(const HistoryAndBookmarkRow& row,
const TableIDRows& ids_set) = 0;
- // Inserts the given |row|, return true on success; The id of insertted row
- // should be set in |row|, so other implemnetations could use it to complete
+ // Inserts the given `row`, return true on success; The id of insertted row
+ // should be set in `row`, so other implemnetations could use it to complete
// the insert.
virtual bool Insert(HistoryAndBookmarkRow* row) = 0;
- // Deletes the rows whose id is in |ids_set|, returns false if any deletion
+ // Deletes the rows whose id is in `ids_set`, returns false if any deletion
// failed, otherwise return true even all/some of rows are not found.
virtual bool Delete(const TableIDRows& ids_set) = 0;
- // Return true if |row| has a value explicitly set for at least one of the
- // columns in |row| that are known to this class.
+ // Return true if `row` has a value explicitly set for at least one of the
+ // columns in `row` that are known to this class.
bool HasColumnIn(const HistoryAndBookmarkRow& row);
- // Returns true if |id| is one of the columns known to this class.
+ // Returns true if `id` is one of the columns known to this class.
bool HasColumn(HistoryAndBookmarkRow::ColumnID id);
private:
diff --git a/chromium/components/history/core/browser/android/visit_sql_handler.cc b/chromium/components/history/core/browser/android/visit_sql_handler.cc
index 14e7db90c49..7451eb8230d 100644
--- a/chromium/components/history/core/browser/android/visit_sql_handler.cc
+++ b/chromium/components/history/core/browser/android/visit_sql_handler.cc
@@ -32,7 +32,7 @@ VisitSQLHandler::VisitSQLHandler(URLDatabase* url_db, VisitDatabase* visit_db)
VisitSQLHandler::~VisitSQLHandler() {
}
-// The created time is updated according the given |row|.
+// The created time is updated according the given `row`.
// We simulate updating created time by
// a. Remove all visits.
// b. Insert a new visit which has visit time same as created time.
diff --git a/chromium/components/history/core/browser/android/visit_sql_handler.h b/chromium/components/history/core/browser/android/visit_sql_handler.h
index 39f1e545f73..c23335d49bc 100644
--- a/chromium/components/history/core/browser/android/visit_sql_handler.h
+++ b/chromium/components/history/core/browser/android/visit_sql_handler.h
@@ -30,16 +30,16 @@ class VisitSQLHandler : public SQLHandler {
bool Delete(const TableIDRows& ids_set) override;
private:
- // Add a row in visit table with the given |url_id| and |visit_time|.
+ // Add a row in visit table with the given `url_id` and `visit_time`.
bool AddVisit(URLID url_id, const base::Time& visit_time);
- // Add the given |visit_count| rows for |url_id|. The visit time of each row
- // has minium difference and ends with the |last_visit_time|.
+ // Add the given `visit_count` rows for `url_id`. The visit time of each row
+ // has minium difference and ends with the `last_visit_time`.
bool AddVisitRows(URLID url_id,
int visit_count,
const base::Time& last_visit_time);
- // Delete the visits of the given |url_id|.
+ // Delete the visits of the given `url_id`.
bool DeleteVisitsForURL(URLID url_id);
URLDatabase* url_db_;
diff --git a/chromium/components/history/core/browser/browsing_history_driver.h b/chromium/components/history/core/browser/browsing_history_driver.h
index c41f240a711..00f651523ae 100644
--- a/chromium/components/history/core/browser/browsing_history_driver.h
+++ b/chromium/components/history/core/browser/browsing_history_driver.h
@@ -64,7 +64,7 @@ class BrowsingHistoryDriver {
// Whether the Clear Browsing Data UI should show a notice about the existence
// of other forms of browsing history stored in user's account. The response
- // is returned in a |callback|.
+ // is returned in a `callback`.
virtual void ShouldShowNoticeAboutOtherFormsOfBrowsingHistory(
const syncer::SyncService* sync_service,
WebHistoryService* history_service,
diff --git a/chromium/components/history/core/browser/browsing_history_service.cc b/chromium/components/history/core/browser/browsing_history_service.cc
index 336fc22bb79..0f89304b287 100644
--- a/chromium/components/history/core/browser/browsing_history_service.cc
+++ b/chromium/components/history/core/browser/browsing_history_service.cc
@@ -184,10 +184,10 @@ BrowsingHistoryService::BrowsingHistoryService(
if (web_history) {
web_history_service_observation_.Observe(web_history);
} else if (sync_service_) {
- // If |web_history| is not available, it means that history sync is
- // disabled. If |sync_service_| is not null, it means that syncing is
+ // If `web_history` is not available, it means that history sync is
+ // disabled. If `sync_service_` is not null, it means that syncing is
// possible, and that history sync/web history may become enabled later, so
- // attach start observing. If |sync_service_| is null then we cannot start
+ // attach start observing. If `sync_service_` is null then we cannot start
// observing. This is okay because sync will never start for us, for example
// it may be disabled by flag or we're part of an incognito/guest mode
// window.
@@ -216,7 +216,7 @@ void BrowsingHistoryService::WebHistoryTimeout(
scoped_refptr<QueryHistoryState> state) {
state->remote_status = TIMED_OUT;
- // Don't reset |web_history_request_| so we can still record histogram.
+ // Don't reset `web_history_request_` so we can still record histogram.
// TODO(dubroy): Communicate the failure to the front end.
if (!query_task_tracker_.HasTrackedTasks())
ReturnResultsToDriver(std::move(state));
@@ -463,7 +463,7 @@ void BrowsingHistoryService::MergeDuplicateResults(
// Maps a URL to the most recent entry on a particular day.
std::map<GURL, HistoryEntry*> current_day_entries;
- // Keeps track of the day that |current_day_entries| is holding entries for
+ // Keeps track of the day that `current_day_entries` is holding entries for
// in order to handle removing per-day duplicates.
base::Time current_day_midnight;
@@ -517,7 +517,7 @@ void BrowsingHistoryService::MergeDuplicateResults(
} else if (CanRetry(state->remote_status)) {
// TODO(skym): It is unclear if this is the best behavior. The UI is going
// to behave incorrectly if out of order results are received. So to
- // guarantee that doesn't happen, use |oldest_local| for continuation
+ // guarantee that doesn't happen, use `oldest_local` for continuation
// calls. This will result in missing history entries for the failed calls.
// crbug.com/685866 is related to this problem.
state->remote_end_time_for_continuation = oldest_local;
diff --git a/chromium/components/history/core/browser/browsing_history_service.h b/chromium/components/history/core/browser/browsing_history_service.h
index 30fa2bd75be..bf0905d7d51 100644
--- a/chromium/components/history/core/browser/browsing_history_service.h
+++ b/chromium/components/history/core/browser/browsing_history_service.h
@@ -85,7 +85,7 @@ class BrowsingHistoryService : public HistoryServiceObserver,
std::u16string title; // Title of the entry. May be empty.
// The time of the entry. Usually this will be the time of the most recent
- // visit to |url| on a particular day as defined in the local timezone.
+ // visit to `url` on a particular day as defined in the local timezone.
base::Time time;
// The sync ID of the client on which the most recent visit occurred.
@@ -144,7 +144,7 @@ class BrowsingHistoryService : public HistoryServiceObserver,
void QueryHistory(const std::u16string& search_text,
const QueryOptions& options);
- // Removes |items| from history.
+ // Removes `items` from history.
void RemoveVisits(const std::vector<HistoryEntry>& items);
// SyncServiceObserver implementation.
@@ -164,12 +164,12 @@ class BrowsingHistoryService : public HistoryServiceObserver,
// Used to hold and track query state between asynchronous calls.
struct QueryHistoryState;
- // Moves results from |state| into |results|, merging both remote and local
+ // Moves results from `state` into `results`, merging both remote and local
// results together and maintaining reverse chronological order. Any results
// with the same URL will be merged together for each day. Often holds back
- // some results in |state| from one of the two sources to ensure that they're
+ // some results in `state` from one of the two sources to ensure that they're
// always returned to the driver in correct order. This function also updates
- // the end times in |state| for both sources that the next query should be
+ // the end times in `state` for both sources that the next query should be
// made against.
static void MergeDuplicateResults(QueryHistoryState* state,
std::vector<HistoryEntry>* results);
@@ -186,7 +186,7 @@ class BrowsingHistoryService : public HistoryServiceObserver,
// BrowsingHistoryDriver.
void ReturnResultsToDriver(scoped_refptr<QueryHistoryState> state);
- // Callback from |web_history_timer_| when a response from web history has
+ // Callback from `web_history_timer_` when a response from web history has
// not been received in time.
void WebHistoryTimeout(scoped_refptr<QueryHistoryState> state);
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 9247eeda8a5..7a5e097bb5b 100644
--- a/chromium/components/history/core/browser/browsing_history_service_unittest.cc
+++ b/chromium/components/history/core/browser/browsing_history_service_unittest.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "base/callback_forward.h"
#include "base/callback_helpers.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
@@ -382,9 +381,9 @@ TEST_F(BrowsingHistoryServiceTest, QueryHistoryLocalTimeRanges) {
QueryOptions options;
options.begin_time = OffsetToTime(2);
options.end_time = OffsetToTime(4);
- // Having a |reached_beginning| value of false here seems
- // counterintuitive. Seems to be for paging by |begin_time| instead of
- // |count|. If the local history implementation changes, feel free to update
+ // Having a `reached_beginning` value of false here seems
+ // counterintuitive. Seems to be for paging by `begin_time` instead of
+ // `count`. If the local history implementation changes, feel free to update
// this value, all this test cares about is that BrowsingHistoryService passes
// the values through correctly.
VerifyQueryResult(/*reached_beginning*/ false,
@@ -655,7 +654,7 @@ TEST_F(BrowsingHistoryServiceTest, WebHistoryTimeout) {
// WebHistoryService will DCHECK if we destroy it before the observer in
// BrowsingHistoryService is removed, so reset our first
- // BrowsingHistoryService before |timeout| goes out of scope.
+ // BrowsingHistoryService before `timeout` goes out of scope.
driver()->SetWebHistory(nullptr);
ResetService(driver(), nullptr, nullptr);
}
@@ -717,7 +716,7 @@ TEST_F(BrowsingHistoryServiceTest, IncorrectlyOrderedRemoteResults) {
// WebHistoryService will DCHECK if we destroy it before the observer in
// BrowsingHistoryService is removed, so reset our first
- // BrowsingHistoryService before |reversed| goes out of scope.
+ // BrowsingHistoryService before `reversed` goes out of scope.
driver()->SetWebHistory(nullptr);
ResetService(driver(), nullptr, nullptr);
}
diff --git a/chromium/components/history/core/browser/download_constants.h b/chromium/components/history/core/browser/download_constants.h
index 2bda18abf15..bb82bcdcd61 100644
--- a/chromium/components/history/core/browser/download_constants.h
+++ b/chromium/components/history/core/browser/download_constants.h
@@ -45,6 +45,7 @@ enum class DownloadDangerType {
DEEP_SCANNED_OPENED_DANGEROUS = 16,
PROMPT_FOR_SCANNING = 17,
BLOCKED_UNSUPPORTED_FILETYPE = 18,
+ DANGEROUS_ACCOUNT_COMRPOMISE = 19,
};
// DownloadId represents the id of a DownloadRow into the DownloadDatabase.
@@ -52,6 +53,6 @@ enum class DownloadDangerType {
// kInvalidDownloadId.
extern const DownloadId kInvalidDownloadId;
-} // namespace
+} // namespace history
#endif // COMPONENTS_HISTORY_CORE_BROWSER_DOWNLOAD_CONSTANTS_H_
diff --git a/chromium/components/history/core/browser/download_database.cc b/chromium/components/history/core/browser/download_database.cc
index 4eff6f81bb5..d034b2af0e3 100644
--- a/chromium/components/history/core/browser/download_database.cc
+++ b/chromium/components/history/core/browser/download_database.cc
@@ -394,11 +394,11 @@ uint32_t DownloadDatabase::GetNextDownloadId() {
// return 0 = kInvalidDownloadId, so GetNextDownloadId() will set
// *id = kInvalidDownloadId + 1.
//
- // If there is at least one record but all of the |id|s are
+ // If there is at least one record but all of the `id`s are
// <= kInvalidDownloadId, then max(id) will return <= kInvalidDownloadId,
// so GetNextDownloadId() should return kInvalidDownloadId + 1.
//
- // Note that any records with |id <= kInvalidDownloadId| will be dropped in
+ // Note that any records with `id <= kInvalidDownloadId` will be dropped in
// QueryDownloads().
//
// SQLITE doesn't have unsigned integers.
@@ -437,7 +437,7 @@ void DownloadDatabase::QueryDownloads(std::vector<DownloadRow>* results) {
int column = 0;
// SQLITE does not have unsigned integers, so explicitly handle negative
- // |id|s instead of casting them to very large uint32s, which would break
+ // `id`s instead of casting them to very large uint32s, which would break
// the max(id) logic in GetNextDownloadId().
int64_t signed_id = statement_main.ColumnInt64(column++);
bool valid = ConvertIntToDownloadId(signed_id, &(info->id));
@@ -791,8 +791,8 @@ size_t DownloadDatabase::CountDownloads() {
bool DownloadDatabase::CreateOrUpdateDownloadSlice(
const DownloadSliceInfo& info) {
// If the slice has no data, there is no need to insert it into the db. Note
- // that for each slice, |received_bytes| can only go up. So if a slice is
- // already in the db, its |received_bytes| should always be larger than 0.
+ // that for each slice, `received_bytes` can only go up. So if a slice is
+ // already in the db, its `received_bytes` should always be larger than 0.
if (info.received_bytes == 0)
return true;
sql::Statement statement_replace(GetDB().GetCachedStatement(
diff --git a/chromium/components/history/core/browser/download_database.h b/chromium/components/history/core/browser/download_database.h
index e64e666c16f..a7d428c2b49 100644
--- a/chromium/components/history/core/browser/download_database.h
+++ b/chromium/components/history/core/browser/download_database.h
@@ -40,7 +40,7 @@ class DownloadDatabase {
void QueryDownloads(std::vector<DownloadRow>* results);
// Update the state of one download. Returns true if successful.
- // Does not update |url|, |start_time|; uses |id| only
+ // Does not update `url`, `start_time`; uses `id` only
// to select the row in the database table to update.
bool UpdateDownload(const DownloadRow& data);
@@ -48,7 +48,7 @@ class DownloadDatabase {
// creation succeeded, false otherwise.
bool CreateDownload(const DownloadRow& info);
- // Remove |id| from the database.
+ // Remove `id` from the database.
void RemoveDownload(DownloadId id);
size_t CountDownloads();
@@ -61,7 +61,7 @@ class DownloadDatabase {
bool MigrateMimeType();
// Returns true if able to successfully rewrite the invalid values for the
- // |state| field from 3 to 4. Returns false if there was an error fixing the
+ // `state` field from 3 to 4. Returns false if there was an error fixing the
// database. See http://crbug.com/140687
bool MigrateDownloadsState();
@@ -116,14 +116,14 @@ class DownloadDatabase {
// Fixes state of the download entries. Sometimes entries with IN_PROGRESS
// state are not updated during browser shutdown (particularly when crashing).
// On the next start such entries are considered interrupted with
- // interrupt reason |DOWNLOAD_INTERRUPT_REASON_CRASH|. This function
+ // interrupt reason `DOWNLOAD_INTERRUPT_REASON_CRASH`. This function
// fixes such entries.
void EnsureInProgressEntriesCleanedUp();
// Ensures a column exists in downloads table.
bool EnsureColumnExists(const std::string& name, const std::string& type);
- // Ensures a column exists in |table|.
+ // Ensures a column exists in `table`.
bool EnsureColumnExistsInTable(const std::string& table,
const std::string& name,
const std::string& type);
@@ -138,7 +138,7 @@ class DownloadDatabase {
void RemoveDownloadSlices(DownloadId id);
// Helper method to query the download slices for all the records in
- // |download_row_map|.
+ // `download_row_map`.
using DownloadRowMap = std::map<DownloadId, DownloadRow*>;
void QueryDownloadSlices(DownloadRowMap* download_row_map);
diff --git a/chromium/components/history/core/browser/download_row.h b/chromium/components/history/core/browser/download_row.h
index bef280393db..cf812e597a5 100644
--- a/chromium/components/history/core/browser/download_row.h
+++ b/chromium/components/history/core/browser/download_row.h
@@ -101,7 +101,7 @@ struct DownloadRow {
std::string hash;
// The id of the download in the database. Is not changed by UpdateDownload().
- // Note: This field should be considered deprecated in favor of |guid| below.
+ // Note: This field should be considered deprecated in favor of `guid` below.
// See http://crbug.com/593020.
DownloadId id = kInvalidDownloadId;
diff --git a/chromium/components/history/core/browser/download_slice_info.h b/chromium/components/history/core/browser/download_slice_info.h
index 296f48568c3..27f9d6fa14d 100644
--- a/chromium/components/history/core/browser/download_slice_info.h
+++ b/chromium/components/history/core/browser/download_slice_info.h
@@ -6,7 +6,6 @@
#define COMPONENTS_HISTORY_CORE_BROWSER_DOWNLOAD_SLICE_INFO_H_
#include <stdint.h>
-#include <string>
#include "components/history/core/browser/download_types.h"
diff --git a/chromium/components/history/core/browser/download_types.cc b/chromium/components/history/core/browser/download_types.cc
index a95682a5b32..b6b413f7b63 100644
--- a/chromium/components/history/core/browser/download_types.cc
+++ b/chromium/components/history/core/browser/download_types.cc
@@ -74,6 +74,7 @@ DownloadDangerType IntToDownloadDangerType(int danger_type) {
case DownloadDangerType::DEEP_SCANNED_OPENED_DANGEROUS:
case DownloadDangerType::PROMPT_FOR_SCANNING:
case DownloadDangerType::BLOCKED_UNSUPPORTED_FILETYPE:
+ case DownloadDangerType::DANGEROUS_ACCOUNT_COMRPOMISE:
return static_cast<DownloadDangerType>(danger_type);
case DownloadDangerType::INVALID:
@@ -134,6 +135,9 @@ std::ostream& operator<<(std::ostream& stream, DownloadDangerType danger_type) {
case DownloadDangerType::BLOCKED_UNSUPPORTED_FILETYPE:
return stream
<< "history::DownloadDangerType::BLOCKED_UNSUPPORTED_FILETYPE";
+ case DownloadDangerType::DANGEROUS_ACCOUNT_COMRPOMISE:
+ return stream
+ << "history::DownloadDangerType::DANGEROUS_ACCOUNT_COMRPOMISE";
}
NOTREACHED();
return stream;
diff --git a/chromium/components/history/core/browser/expire_history_backend.cc b/chromium/components/history/core/browser/expire_history_backend.cc
index 26b17af58d1..0c7332c51b9 100644
--- a/chromium/components/history/core/browser/expire_history_backend.cc
+++ b/chromium/components/history/core/browser/expire_history_backend.cc
@@ -68,9 +68,9 @@ class AllVisitsReader : public ExpiringVisitsReader {
// Reads only AUTO_SUBFRAME visits, within a computed range. The range is
// computed as follows:
-// * |begin_time| is read from the meta table. This value is updated whenever
+// * `begin_time` is read from the meta table. This value is updated whenever
// there are no more additional visits to expire by this reader.
-// * |end_time| is advanced forward by a constant (kEarlyExpirationAdvanceDay),
+// * `end_time` is advanced forward by a constant (kEarlyExpirationAdvanceDay),
// but not past the current time.
class AutoSubframeVisitsReader : public ExpiringVisitsReader {
public:
@@ -82,7 +82,7 @@ class AutoSubframeVisitsReader : public ExpiringVisitsReader {
DCHECK(visits) << "visit vector has to exist in order to populate it";
base::Time begin_time = db->GetEarlyExpirationThreshold();
- // Advance |end_time| to expire early.
+ // Advance `end_time` to expire early.
base::Time early_end_time = end_time +
base::TimeDelta::FromDays(kEarlyExpirationAdvanceDays);
@@ -155,12 +155,9 @@ const int kOnDemandFaviconIsOldAfterDays = 30;
// ExpireHistoryBackend::DeleteEffects ----------------------------------------
-ExpireHistoryBackend::DeleteEffects::DeleteEffects() {
-}
-
-ExpireHistoryBackend::DeleteEffects::~DeleteEffects() {
-}
+ExpireHistoryBackend::DeleteEffects::DeleteEffects() = default;
+ExpireHistoryBackend::DeleteEffects::~DeleteEffects() = default;
// ExpireHistoryBackend -------------------------------------------------------
@@ -176,8 +173,7 @@ ExpireHistoryBackend::ExpireHistoryBackend(
DCHECK(notifier_);
}
-ExpireHistoryBackend::~ExpireHistoryBackend() {
-}
+ExpireHistoryBackend::~ExpireHistoryBackend() = default;
void ExpireHistoryBackend::SetDatabases(HistoryDatabase* main_db,
favicon::FaviconDatabase* favicon_db) {
@@ -195,14 +191,13 @@ void ExpireHistoryBackend::DeleteURLs(const std::vector<GURL>& urls,
return;
DeleteEffects effects;
- for (auto url = urls.begin(); url != urls.end(); ++url) {
- const bool is_pinned =
- backend_client_ && backend_client_->IsPinnedURL(*url);
+ for (const auto& url : urls) {
+ const bool is_pinned = backend_client_ && backend_client_->IsPinnedURL(url);
URLRow url_row;
- if (!main_db_->GetRowForURL(*url, &url_row) && !is_pinned) {
+ if (!main_db_->GetRowForURL(url, &url_row) && !is_pinned) {
// If the URL isn't in the database and not pinned, we should still
// check to see if any favicons need to be deleted.
- DeleteIcons(*url, &effects);
+ DeleteIcons(url, &effects);
continue;
}
@@ -213,7 +208,7 @@ void ExpireHistoryBackend::DeleteURLs(const std::vector<GURL>& urls,
main_db_->GetVisitsForURL(url_row.id(), &visits_to_delete);
size_t total_visits = visits_to_delete.size();
if (!end_time.is_null() && !end_time.is_max()) {
- // Remove all items that should not be deleted from |visits_to_delete|.
+ // Remove all items that should not be deleted from `visits_to_delete`.
base::EraseIf(visits_to_delete,
[=](auto& v) { return v.visit_time > end_time; });
}
@@ -232,7 +227,7 @@ void ExpireHistoryBackend::DeleteURLs(const std::vector<GURL>& urls,
DeleteFaviconsIfPossible(&effects);
BroadcastNotifications(&effects, DELETION_USER_INITIATED,
- DeletionTimeRange::Invalid(), base::nullopt);
+ DeletionTimeRange::Invalid(), absl::nullopt);
}
void ExpireHistoryBackend::ExpireHistoryBetween(
@@ -248,13 +243,13 @@ void ExpireHistoryBackend::ExpireHistoryBetween(
main_db_->GetAllVisitsInRange(begin_time, end_time, 0, &visits);
if (!restrict_urls.empty()) {
std::set<URLID> url_ids;
- for (auto url = restrict_urls.begin(); url != restrict_urls.end(); ++url)
- url_ids.insert(main_db_->GetRowForURL(*url, nullptr));
+ for (const auto& restrict_url : restrict_urls)
+ url_ids.insert(main_db_->GetRowForURL(restrict_url, nullptr));
VisitVector all_visits;
all_visits.swap(visits);
- for (auto visit = all_visits.begin(); visit != all_visits.end(); ++visit) {
- if (url_ids.find(visit->url_id) != url_ids.end())
- visits.push_back(*visit);
+ for (const auto& visit : all_visits) {
+ if (url_ids.find(visit.url_id) != url_ids.end())
+ visits.push_back(visit);
}
}
DeletionTimeRange time_range(begin_time, end_time);
@@ -265,7 +260,7 @@ void ExpireHistoryBackend::ExpireHistoryBetween(
void ExpireHistoryBackend::ExpireHistoryForTimes(
const std::vector<base::Time>& times) {
- // |times| must be in reverse chronological order and have no
+ // `times` must be in reverse chronological order and have no
// duplicates, i.e. each member must be earlier than the one before
// it.
DCHECK(
@@ -310,7 +305,7 @@ void ExpireHistoryBackend::ExpireVisitsInternal(
DeleteFaviconsIfPossible(&effects);
BroadcastNotifications(
&effects, type, time_range,
- restrict_urls.empty() ? base::Optional<std::set<GURL>>() : restrict_urls);
+ restrict_urls.empty() ? absl::optional<std::set<GURL>>() : restrict_urls);
// Pick up any bits possibly left over.
ParanoidExpireHistory();
@@ -370,14 +365,14 @@ void ExpireHistoryBackend::ClearOldOnDemandFaviconsIfPossible(
}
BroadcastNotifications(&effects, DELETION_EXPIRED,
- DeletionTimeRange::Invalid(), base::nullopt);
+ DeletionTimeRange::Invalid(), absl::nullopt);
}
void ExpireHistoryBackend::InitWorkQueue() {
DCHECK(work_queue_.empty()) << "queue has to be empty prior to init";
- for (size_t i = 0; i < readers_.size(); i++)
- work_queue_.push(readers_[i]);
+ for (const auto* reader : readers_)
+ work_queue_.push(reader);
}
const ExpiringVisitsReader* ExpireHistoryBackend::GetAllVisitsReader() {
@@ -432,7 +427,7 @@ void ExpireHistoryBackend::BroadcastNotifications(
DeleteEffects* effects,
DeletionType type,
const DeletionTimeRange& time_range,
- base::Optional<std::set<GURL>> restrict_urls) {
+ absl::optional<std::set<GURL>> restrict_urls) {
if (!effects->modified_urls.empty()) {
notifier_->NotifyURLsModified(effects->modified_urls,
type == DELETION_EXPIRED
@@ -467,19 +462,19 @@ VisitVector ExpireHistoryBackend::GetVisitsAndRedirectParents(
void ExpireHistoryBackend::DeleteVisitRelatedInfo(const VisitVector& visits,
DeleteEffects* effects) {
- for (size_t i = 0; i < visits.size(); i++) {
+ for (const auto& visit : visits) {
// Delete the visit itself.
- main_db_->DeleteVisit(visits[i]);
+ main_db_->DeleteVisit(visit);
// Add the URL row to the affected URL list.
- if (!effects->affected_urls.count(visits[i].url_id)) {
+ if (!effects->affected_urls.count(visit.url_id)) {
URLRow row;
- if (main_db_->GetURLRow(visits[i].url_id, &row))
- effects->affected_urls[visits[i].url_id] = row;
+ if (main_db_->GetURLRow(visit.url_id, &row))
+ effects->affected_urls[visit.url_id] = row;
}
- // Delete content annotations associated with visit.
- main_db_->DeleteContentAnnotationsForVisit(visits[i].visit_id);
+ // Delete content & context annotations associated with visit.
+ main_db_->DeleteAnnotationsForVisit(visit.visit_id);
}
}
@@ -502,9 +497,8 @@ void ExpireHistoryBackend::DeleteIcons(const GURL& gurl,
std::vector<favicon::IconMapping> icon_mappings;
if (favicon_db_ &&
favicon_db_->GetIconMappingsForPageURL(gurl, &icon_mappings)) {
- for (auto m = icon_mappings.begin(); m != icon_mappings.end(); ++m) {
- effects->affected_favicons.insert(m->icon_id);
- }
+ for (const auto& icon_mapping : icon_mappings)
+ effects->affected_favicons.insert(icon_mapping.icon_id);
// Delete the mapping entries for the url.
favicon_db_->DeleteIconMappings(gurl);
}
@@ -525,14 +519,14 @@ void ExpireHistoryBackend::ExpireURLsForVisits(const VisitVector& visits,
// First find all unique URLs and the number of visits we're deleting for
// each one.
std::map<URLID, ChangedURL> changed_urls;
- for (size_t i = 0; i < visits.size(); i++) {
- ChangedURL& cur = changed_urls[visits[i].url_id];
+ for (const auto& visit : visits) {
+ ChangedURL& cur = changed_urls[visit.url_id];
// NOTE: This code must stay in sync with HistoryBackend::AddPageVisit().
- if (!ui::PageTransitionCoreTypeIs(visits[i].transition,
+ if (!ui::PageTransitionCoreTypeIs(visit.transition,
ui::PAGE_TRANSITION_RELOAD)) {
cur.visit_count++;
}
- if (visits[i].incremented_omnibox_typed_score)
+ if (visit.incremented_omnibox_typed_score)
cur.typed_count++;
}
@@ -653,7 +647,7 @@ bool ExpireHistoryBackend::ExpireSomeOldHistory(
DeleteFaviconsIfPossible(&deleted_effects);
BroadcastNotifications(&deleted_effects, DELETION_EXPIRED,
- DeletionTimeRange::Invalid(), base::nullopt);
+ DeletionTimeRange::Invalid(), absl::nullopt);
return more_to_expire;
}
diff --git a/chromium/components/history/core/browser/expire_history_backend.h b/chromium/components/history/core/browser/expire_history_backend.h
index e9118f42979..6c8dc8e27a4 100644
--- a/chromium/components/history/core/browser/expire_history_backend.h
+++ b/chromium/components/history/core/browser/expire_history_backend.h
@@ -37,7 +37,7 @@ class HistoryDatabase;
class ExpiringVisitsReader {
public:
virtual ~ExpiringVisitsReader() {}
- // Populates |visits| from |db|, using provided |end_time| and |max_visits|
+ // Populates `visits` from `db`, using provided `end_time` and `max_visits`
// cap.
virtual bool Read(base::Time end_time, HistoryDatabase* db,
VisitVector* visits, int max_visits) const = 0;
@@ -74,10 +74,10 @@ class ExpireHistoryBackend {
// will continue until the object is deleted.
void StartExpiringOldStuff(base::TimeDelta expiration_threshold);
- // Deletes everything associated with a URL until |end_time|.
+ // Deletes everything associated with a URL until `end_time`.
void DeleteURL(const GURL& url, base::Time end_time);
- // Deletes everything associated with each URL in the list until |end_time|.
+ // Deletes everything associated with each URL in the list until `end_time`.
void DeleteURLs(const std::vector<GURL>& url, base::Time end_time);
// Removes all visits to restrict_urls (or all URLs if empty) in the given
@@ -88,7 +88,7 @@ class ExpireHistoryBackend {
bool user_initiated);
// Removes all visits to all URLs with the given times, updating the
- // URLs accordingly. |times| must be in reverse chronological order
+ // URLs accordingly. `times` must be in reverse chronological order
// and not contain any duplicates.
void ExpireHistoryForTimes(const std::vector<base::Time>& times);
@@ -152,7 +152,7 @@ class ExpireHistoryBackend {
std::set<GURL> deleted_favicons;
};
- // Returns a vector with all visits that eventually redirect to |visits|.
+ // Returns a vector with all visits that eventually redirect to `visits`.
VisitVector GetVisitsAndRedirectParents(const VisitVector& visits);
// Deletes the visit-related stuff for all the visits in the given list, and
@@ -180,7 +180,7 @@ class ExpireHistoryBackend {
bool is_pinned,
DeleteEffects* effects);
- // Deletes all favicons associated with |gurl|.
+ // Deletes all favicons associated with `gurl`.
void DeleteIcons(const GURL& gurl, DeleteEffects* effects);
// Deletes all the URLs in the given vector and handles their dependencies.
@@ -197,7 +197,7 @@ class ExpireHistoryBackend {
//
// The visits in the given vector should have already been deleted from the
// database, and the list of affected URLs already be filled into
- // |depenencies->affected_urls|.
+ // `depenencies->affected_urls`.
//
// Starred URLs will not be deleted. The information in the dependencies that
// DeleteOneURL fills in will be updated, and this function will also delete
@@ -218,9 +218,9 @@ class ExpireHistoryBackend {
const std::set<GURL>& restrict_urls,
DeletionType type);
- // Deletes the favicons listed in |effects->affected_favicons| if they are
+ // Deletes the favicons listed in `effects->affected_favicons` if they are
// unused. Fails silently (we don't care about favicons so much, so don't want
- // to stop everything if it fails). Fills |expired_favicons| with the set of
+ // to stop everything if it fails). Fills `expired_favicons` with the set of
// favicon urls that no longer have associated visits and were therefore
// expired.
void DeleteFaviconsIfPossible(DeleteEffects* effects);
@@ -229,7 +229,7 @@ class ExpireHistoryBackend {
void BroadcastNotifications(DeleteEffects* effects,
DeletionType type,
const DeletionTimeRange& time_range,
- base::Optional<std::set<GURL>> restrict_urls);
+ absl::optional<std::set<GURL>> restrict_urls);
// Schedules a call to DoExpireIteration.
void ScheduleExpire();
@@ -239,8 +239,8 @@ class ExpireHistoryBackend {
// future.
void DoExpireIteration();
- // Tries to expire the oldest |max_visits| visits from history that are older
- // than |time_threshold|. The return value indicates if we think there might
+ // Tries to expire the oldest `max_visits` visits from history that are older
+ // than `time_threshold`. The return value indicates if we think there might
// be more history to expire with the current time threshold (it does not
// indicate success or failure).
bool ExpireSomeOldHistory(base::Time end_time,
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 da481c41ba0..8b302a94e55 100644
--- a/chromium/components/history/core/browser/expire_history_backend_unittest.cc
+++ b/chromium/components/history/core/browser/expire_history_backend_unittest.cc
@@ -62,7 +62,7 @@ base::Time PretendNow() {
return out_time;
}
-// Returns whether |url| can be added to history.
+// Returns whether `url` can be added to history.
bool MockCanAddURLToHistory(const GURL& url) {
return url.is_valid();
}
@@ -99,7 +99,7 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
// EXPECTs that each URL-specific history thing (basically, everything but
// favicons) is gone, the reason being either that it was automatically
- // |expired|, or manually deleted.
+ // `expired`, or manually deleted.
void EnsureURLInfoGone(const URLRow& row, bool expired);
const DeletionInfo* GetLastDeletionInfo() {
@@ -109,7 +109,7 @@ class ExpireHistoryTest : public testing::Test, public HistoryBackendNotifier {
}
// Returns whether HistoryBackendNotifier::NotifyURLsModified was
- // called for |url|.
+ // called for `url`.
bool ModifiedNotificationSentDueToExpiry(const GURL& url);
bool ModifiedNotificationSentDueToUserAction(const GURL& url);
@@ -287,36 +287,6 @@ void ExpireHistoryTest::AddExampleData(URLID url_ids[3],
main_db_->AddVisit(&visit_row4, SOURCE_BROWSED);
}
-void ExpireHistoryTest::AddExampleSourceData(const GURL& url, URLID* id) {
- if (!main_db_)
- return;
-
- base::Time last_visit_time = PretendNow();
- // Add one URL.
- URLRow url_row1(url);
- url_row1.set_last_visit(last_visit_time);
- url_row1.set_visit_count(4);
- URLID url_id = main_db_->AddURL(url_row1);
- *id = url_id;
-
- // Four times for each visit.
- VisitRow visit_row1(url_id, last_visit_time - base::TimeDelta::FromDays(4), 0,
- ui::PAGE_TRANSITION_TYPED, 0, true, false);
- main_db_->AddVisit(&visit_row1, SOURCE_SYNCED);
-
- VisitRow visit_row2(url_id, last_visit_time - base::TimeDelta::FromDays(3), 0,
- ui::PAGE_TRANSITION_TYPED, 0, true, false);
- main_db_->AddVisit(&visit_row2, SOURCE_BROWSED);
-
- VisitRow visit_row3(url_id, last_visit_time - base::TimeDelta::FromDays(2), 0,
- ui::PAGE_TRANSITION_TYPED, 0, true, false);
- main_db_->AddVisit(&visit_row3, SOURCE_EXTENSION);
-
- VisitRow visit_row4(url_id, last_visit_time, 0, ui::PAGE_TRANSITION_TYPED, 0,
- true, false);
- main_db_->AddVisit(&visit_row4, SOURCE_FIREFOX_IMPORTED);
-}
-
bool ExpireHistoryTest::HasFavicon(favicon_base::FaviconID favicon_id) {
if (!thumb_db_ || favicon_id == 0)
return false;
@@ -335,8 +305,8 @@ favicon_base::FaviconID ExpireHistoryTest::GetFavicon(
}
void ExpireHistoryTest::EnsureURLInfoGone(const URLRow& row, bool expired) {
- // The passed in |row| must originate from |main_db_| so that its ID will be
- // set to what had been in effect in |main_db_| before the deletion.
+ // The passed in `row` must originate from `main_db_` so that its ID will be
+ // set to what had been in effect in `main_db_` before the deletion.
ASSERT_NE(0, row.id());
// Verify the URL no longer exists.
@@ -541,6 +511,34 @@ TEST_F(ExpireHistoryTest, DeleteURLWithoutFavicon) {
EXPECT_TRUE(HasFavicon(favicon_id));
}
+// Deletes a URL with context annotations attached to the visits. Verifies the
+// context annotations are also deleted.
+TEST_F(ExpireHistoryTest, DeleteURLAndContextAnnotations) {
+ URLID url_ids[3];
+ base::Time visit_times[4];
+ AddExampleData(url_ids, visit_times);
+
+ // Add some stub context annotations for the last URL row.
+ URLRow last_row;
+ ASSERT_TRUE(main_db_->GetURLRow(url_ids[2], &last_row));
+ VisitVector visits;
+ main_db_->GetVisitsForURL(url_ids[2], &visits);
+ ASSERT_EQ(1U, visits.size());
+ main_db_->AddContextAnnotationsForVisit(visits[0].visit_id, {});
+
+ // Verify that the context annotation is there for that visit.
+ auto annotated_visits = main_db_->GetAllContextAnnotationsForTesting();
+ ASSERT_EQ(1U, annotated_visits.size());
+ EXPECT_EQ(visits[0].visit_id, annotated_visits[0].visit_id);
+
+ // Delete the URL and its dependencies.
+ expirer_.DeleteURL(last_row.url(), base::Time::Max());
+
+ // All the normal data + the favicon should be gone.
+ EnsureURLInfoGone(last_row, false);
+ EXPECT_TRUE(main_db_->GetAllContextAnnotationsForTesting().empty());
+}
+
// DeleteURL should delete the history of starred urls, but the URL should
// remain starred and its favicon should remain too.
TEST_F(ExpireHistoryTest, DeleteStarredVisitedURL) {
diff --git a/chromium/components/history/core/browser/history_backend.cc b/chromium/components/history/core/browser/history_backend.cc
index afcb5debb3f..1a6bb7ad482 100644
--- a/chromium/components/history/core/browser/history_backend.cc
+++ b/chromium/components/history/core/browser/history_backend.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <functional>
+#include <iterator>
#include <limits>
#include <map>
#include <memory>
@@ -20,16 +21,17 @@
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
+#include "base/logging.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
+#include "base/notreached.h"
#include "base/rand_util.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
-#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/favicon/core/favicon_backend.h"
@@ -52,7 +54,6 @@
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "sql/error_delegate_util.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/codec/png_codec.h"
#include "url/gurl.h"
#include "url/url_constants.h"
@@ -199,7 +200,7 @@ QueuedHistoryDBTask::QueuedHistoryDBTask(
}
QueuedHistoryDBTask::~QueuedHistoryDBTask() {
- // Ensure that |task_| is destroyed on its origin thread.
+ // Ensure that `task_` is destroyed on its origin thread.
origin_loop_->PostTask(FROM_HERE,
base::BindOnce(&base::DeletePointer<HistoryDBTask>,
base::Unretained(task_.release())));
@@ -257,7 +258,6 @@ HistoryBackend::HistoryBackend(
scheduled_kill_db_(false),
expirer_(this, backend_client.get(), task_runner),
recent_redirects_(kMaxRedirectCount),
- segment_queried_(false),
backend_client_(std::move(backend_client)),
task_runner_(task_runner) {
DCHECK(delegate_);
@@ -487,7 +487,7 @@ void HistoryBackend::SetFlocAllowed(ContextID context_id,
void HistoryBackend::AddContentModelAnnotationsForVisit(
VisitID visit_id,
const VisitContentModelAnnotations& model_annotations) {
- TRACE_EVENT0("browser", "HistoryBackend::AddContentAnnotationsForVisit");
+ TRACE_EVENT0("browser", "HistoryBackend::AddContentModelAnnotationsForVisit");
if (!db_)
return;
@@ -645,12 +645,12 @@ void HistoryBackend::AddPage(const HistoryAddPageArgs& request) {
ui::PageTransition redirect_info = ui::PAGE_TRANSITION_CHAIN_START;
RedirectList redirects = request.redirects;
- // In the presence of client redirects, |request.redirects| can be a partial
+ // In the presence of client redirects, `request.redirects` can be a partial
// chain because previous calls to this function may have reported a
// redirect chain already. This is fine for the visits database where we'll
- // just append data but insufficient for |recent_redirects_|
+ // just append data but insufficient for `recent_redirects_`
// (backpropagation of favicons and titles), where we'd like the full
- // (extended) redirect chain. We use |extended_redirect_chain| to represent
+ // (extended) redirect chain. We use `extended_redirect_chain` to represent
// this.
RedirectList extended_redirect_chain;
@@ -946,7 +946,7 @@ std::pair<URLID, VisitID> HistoryBackend::AddPageVisit(
VisitSource visit_source,
bool should_increment_typed_count,
bool floc_allowed,
- base::Optional<std::u16string> title) {
+ absl::optional<std::u16string> title) {
// See if this URL is already in the DB.
URLRow url_info(url);
URLID url_id = db_->GetRowForURL(url, &url_info);
@@ -1101,9 +1101,9 @@ void HistoryBackend::SetPageTitle(const GURL& url,
}
URLRows changed_urls;
- for (size_t i = 0; i < redirects->size(); i++) {
+ for (const auto& redirect : *redirects) {
URLRow row;
- URLID row_id = db_->GetRowForURL(redirects->at(i), &row);
+ URLID row_id = db_->GetRowForURL(redirect, &row);
if (row_id && row.title() != title) {
row.set_title(title);
db_->UpdateURLRow(row_id, row);
@@ -1203,10 +1203,10 @@ bool HistoryBackend::AddVisits(const GURL& url,
const std::vector<VisitInfo>& visits,
VisitSource visit_source) {
if (db_) {
- for (auto visit = visits.begin(); visit != visits.end(); ++visit) {
- if (!AddPageVisit(url, visit->first, 0, visit->second,
- !ui::PageTransitionIsMainFrame(visit->second),
- visit_source, IsTypedIncrement(visit->second),
+ for (const auto& visit : visits) {
+ if (!AddPageVisit(url, visit.first, 0, visit.second,
+ !ui::PageTransitionIsMainFrame(visit.second),
+ visit_source, IsTypedIncrement(visit.second),
/*floc_allowed=*/false)
.first) {
return false;
@@ -1408,15 +1408,52 @@ void HistoryBackend::DeleteMatchingURLsForKeyword(KeywordID keyword_id,
std::vector<KeywordSearchTermRow> rows;
if (db_->GetKeywordSearchTermRows(term, &rows)) {
std::vector<GURL> items_to_delete;
- URLRow row;
- for (auto it = rows.begin(); it != rows.end(); ++it) {
- if ((it->keyword_id == keyword_id) && db_->GetURLRow(it->url_id, &row))
- items_to_delete.push_back(row.url());
+ URLRow url_row;
+ for (const auto& row : rows) {
+ if (row.keyword_id == keyword_id && db_->GetURLRow(row.url_id, &url_row))
+ items_to_delete.push_back(url_row.url());
}
DeleteURLs(items_to_delete);
}
}
+// Clusters --------------------------------------------------------------------
+
+void HistoryBackend::AddContextAnnotationsForVisit(
+ VisitID visit_id,
+ const VisitContextAnnotations& visit_context_annotations) {
+ TRACE_EVENT0("browser", "HistoryBackend::AddContextAnnotationsForVisit");
+ DCHECK(visit_id);
+ VisitRow visit_row;
+ if (!db_ || !db_->GetRowForVisit(visit_id, &visit_row))
+ return;
+ db_->AddContextAnnotationsForVisit(visit_id, visit_context_annotations);
+ ScheduleCommit();
+}
+
+std::vector<AnnotatedVisit> HistoryBackend::GetAnnotatedVisits(
+ int max_results) {
+ TRACE_EVENT0("browser", "HistoryBackend::GetAnnotatedVisits");
+ if (!db_)
+ return {};
+ std::vector<AnnotatedVisit> annotated_visits;
+ for (const auto& row : db_->GetAnnotatedVisits(max_results)) {
+ URLRow url_row;
+ VisitRow visit_row;
+ if (db_->GetRowForVisit(row.visit_id, &visit_row) &&
+ db_->GetURLRow(visit_row.url_id, &url_row)) {
+ annotated_visits.push_back(
+ {url_row, visit_row, row.context_annotations, {}});
+ } else {
+ // Ignore corrupt data but do not crash, as user DBs can be in bad states.
+ DVLOG(0) << "HistoryBackend: AnnotatedVisit found with missing associated"
+ "URL or visit. visit_id = "
+ << row.visit_id;
+ }
+ }
+ return annotated_visits;
+}
+
// Observers -------------------------------------------------------------------
void HistoryBackend::AddObserver(HistoryBackendObserver* observer) {
@@ -1478,9 +1515,8 @@ void HistoryBackend::RemoveDownloads(const std::set<uint32_t>& ids) {
size_t downloads_count_before = db_->CountDownloads();
// HistoryBackend uses a long-running Transaction that is committed
// periodically, so this loop doesn't actually hit the disk too hard.
- for (auto it = ids.begin(); it != ids.end(); ++it) {
- db_->RemoveDownload(*it);
- }
+ for (uint32_t id : ids)
+ db_->RemoveDownload(id);
ScheduleCommit();
size_t downloads_count_after = db_->CountDownloads();
@@ -1520,9 +1556,7 @@ void HistoryBackend::QueryHistoryBasic(const QueryOptions& options,
// Now add them and the URL rows to the results.
std::vector<URLResult> matching_results;
URLResult url_result;
- for (size_t i = 0; i < visits.size(); i++) {
- const VisitRow visit = visits[i];
-
+ for (const auto& visit : visits) {
// Add a result row for this visit, get the URL info from the DB.
if (!db_->GetURLRow(visit.url_id, &url_result)) {
DVLOG(0) << "Failed to get id " << visit.url_id << " from history.urls.";
@@ -1566,17 +1600,15 @@ void HistoryBackend::QueryHistoryText(const std::u16string& text_query,
std::vector<URLResult> matching_visits;
VisitVector visits; // Declare outside loop to prevent re-construction.
- for (size_t i = 0; i < text_matches.size(); i++) {
- const URLRow& text_match = text_matches[i];
+ for (const auto& text_match : text_matches) {
// Get all visits for given URL match.
db_->GetVisibleVisitsForURL(text_match.id(), options, &visits);
- for (size_t j = 0; j < visits.size(); j++) {
+ for (const auto& visit : visits) {
URLResult url_result(text_match);
- url_result.set_visit_time(visits[j].visit_time);
+ url_result.set_visit_time(visit.visit_time);
VisitContentAnnotations content_annotations;
- db_->GetContentAnnotationsForVisit(visits[j].visit_id,
- &content_annotations);
+ db_->GetContentAnnotationsForVisit(visit.visit_id, &content_annotations);
url_result.set_content_annotations(content_annotations);
matching_visits.push_back(url_result);
@@ -1682,9 +1714,9 @@ void HistoryBackend::GetRedirectsFromSpecificVisit(VisitID cur_visit,
void HistoryBackend::GetRedirectsToSpecificVisit(VisitID cur_visit,
RedirectList* redirects) {
- // Follow redirects going to cur_visit. These are added to |redirects| in
+ // Follow redirects going to cur_visit. These are added to `redirects` in
// the order they are found. If a redirect chain looks like A -> B -> C and
- // |cur_visit| = C, redirects will be {B, A} in that order.
+ // `cur_visit` = C, redirects will be {B, A} in that order.
if (!db_)
return;
@@ -1895,47 +1927,46 @@ void HistoryBackend::SetImportedFavicons(
std::set<GURL> favicons_changed;
favicon::FaviconDatabase* favicon_db = favicon_backend_->db();
- for (size_t i = 0; i < favicon_usage.size(); i++) {
+ for (const auto& favicon_usage_data : favicon_usage) {
favicon_base::FaviconID favicon_id = favicon_db->GetFaviconIDForFaviconURL(
- favicon_usage[i].favicon_url, favicon_base::IconType::kFavicon);
+ favicon_usage_data.favicon_url, favicon_base::IconType::kFavicon);
if (!favicon_id) {
// This favicon doesn't exist yet, so we create it using the given data.
// TODO(pkotwicz): Pass in real pixel size.
favicon_id = favicon_db->AddFavicon(
- favicon_usage[i].favicon_url, favicon_base::IconType::kFavicon,
- new base::RefCountedBytes(favicon_usage[i].png_data),
+ favicon_usage_data.favicon_url, favicon_base::IconType::kFavicon,
+ new base::RefCountedBytes(favicon_usage_data.png_data),
FaviconBitmapType::ON_VISIT, now, gfx::Size());
}
// Save the mapping from all the URLs to the favicon.
- for (auto url = favicon_usage[i].urls.begin();
- url != favicon_usage[i].urls.end(); ++url) {
+ for (const auto& url : favicon_usage_data.urls) {
URLRow url_row;
- if (!db_->GetRowForURL(*url, &url_row)) {
+ if (!db_->GetRowForURL(url, &url_row)) {
// If the URL is present as a bookmark, add the url in history to
// save the favicon mapping. This will match with what history db does
// for regular bookmarked URLs with favicons - when history db is
// cleaned, we keep an entry in the db with 0 visits as long as that
// url is bookmarked. The same is applicable to the saved credential's
// URLs.
- if (backend_client_ && backend_client_->IsPinnedURL(*url)) {
- URLRow url_info(*url);
+ if (backend_client_ && backend_client_->IsPinnedURL(url)) {
+ URLRow url_info(url);
url_info.set_visit_count(0);
url_info.set_typed_count(0);
url_info.set_last_visit(base::Time());
url_info.set_hidden(false);
db_->AddURL(url_info);
- favicon_db->AddIconMapping(*url, favicon_id);
- favicons_changed.insert(*url);
+ favicon_db->AddIconMapping(url, favicon_id);
+ favicons_changed.insert(url);
}
} else {
if (!favicon_db->GetIconMappingsForPageURL(
- *url, {favicon_base::IconType::kFavicon},
+ url, {favicon_base::IconType::kFavicon},
/*mapping_data=*/nullptr)) {
// URL is present in history, update the favicon *only* if it is not
// set already.
- favicon_db->AddIconMapping(*url, favicon_id);
- favicons_changed.insert(*url);
+ favicon_db->AddIconMapping(url, favicon_id);
+ favicons_changed.insert(url);
}
}
}
@@ -1955,7 +1986,7 @@ RedirectList HistoryBackend::GetCachedRecentRedirects(const GURL& page_url) {
DCHECK_EQ(iter->second.back(), page_url);
return iter->second;
}
- // No known redirects, construct mock redirect chain containing |page_url|.
+ // No known redirects, construct mock redirect chain containing `page_url`.
return RedirectList{page_url};
}
@@ -2003,7 +2034,7 @@ void HistoryBackend::Commit() {
void HistoryBackend::ScheduleCommit() {
// Non-cancelled means there's an already scheduled commit. Note that
- // CancelableClosure starts cancelled with the default constructor.
+ // CancelableOnceClosure starts cancelled with the default constructor.
if (!scheduled_commit_.IsCancelled())
return;
@@ -2133,20 +2164,20 @@ void HistoryBackend::ExpireHistoryForTimes(const std::set<base::Time>& times,
QueryResults results;
QueryHistoryBasic(options, &results);
- // 1st pass: find URLs that are visited at one of |times|.
+ // 1st pass: find URLs that are visited at one of `times`.
std::set<GURL> urls;
- for (size_t i = 0; i < results.size(); ++i) {
- if (times.count(results[i].visit_time()) > 0)
- urls.insert(results[i].url());
+ for (const auto& result : results) {
+ if (times.count(result.visit_time()) > 0)
+ urls.insert(result.url());
}
if (urls.empty())
return;
// 2nd pass: collect all visit times of those URLs.
std::vector<base::Time> times_to_expire;
- for (size_t i = 0; i < results.size(); ++i) {
- if (urls.count(results[i].url()))
- times_to_expire.push_back(results[i].visit_time());
+ for (const auto& result : results) {
+ if (urls.count(result.url()))
+ times_to_expire.push_back(result.visit_time());
}
// Put the times in reverse chronological order and remove
@@ -2163,7 +2194,7 @@ void HistoryBackend::ExpireHistoryForTimes(const std::set<base::Time>& times,
Commit();
DCHECK_GE(times_to_expire.back(), first_recorded_time_);
- // Update |first_recorded_time_| if we expired it.
+ // Update `first_recorded_time_` if we expired it.
if (times_to_expire.back() == first_recorded_time_)
db_->GetStartDate(&first_recorded_time_);
}
@@ -2173,16 +2204,16 @@ void HistoryBackend::ExpireHistory(
if (db_) {
bool update_first_recorded_time = false;
- for (auto it = expire_list.begin(); it != expire_list.end(); ++it) {
- expirer_.ExpireHistoryBetween(it->urls, it->begin_time, it->end_time,
- true);
+ for (const auto& expire : expire_list) {
+ expirer_.ExpireHistoryBetween(expire.urls, expire.begin_time,
+ expire.end_time, true);
- if (it->begin_time < first_recorded_time_)
+ if (expire.begin_time < first_recorded_time_)
update_first_recorded_time = true;
}
Commit();
- // Update |first_recorded_time_| if any deletion might have affected it.
+ // Update `first_recorded_time_` if any deletion might have affected it.
if (update_first_recorded_time)
db_->GetStartDate(&first_recorded_time_);
}
@@ -2201,16 +2232,16 @@ void HistoryBackend::URLsNoLongerBookmarked(const std::set<GURL>& urls) {
if (!db_)
return;
- for (auto i = urls.begin(); i != urls.end(); ++i) {
+ for (const auto& url : urls) {
VisitVector visits;
URLRow url_row;
- if (db_->GetRowForURL(*i, &url_row))
+ if (db_->GetRowForURL(url, &url_row))
db_->GetVisitsForURL(url_row.id(), &visits);
// We need to call DeleteURL() even if the DB didn't contain this URL, so
// that we can delete all associated icons in the case of deleting an
// unvisited bookmarked URL.
if (visits.empty())
- expirer_.DeleteURL(*i, base::Time::Max());
+ expirer_.DeleteURL(url, base::Time::Max());
}
}
@@ -2220,7 +2251,7 @@ void HistoryBackend::DatabaseErrorCallback(int error, sql::Statement* stmt) {
db_diagnostics_ = db_->GetDiagnosticInfo(error, stmt);
- // Don't just do the close/delete here, as we are being called by |db| and
+ // Don't just do the close/delete here, as we are being called by `db` and
// that seems dangerous.
// TODO(https://crbug.com/854258): It is also dangerous to kill the database
// by a posted task: tasks that run before KillHistoryDatabase still can try
@@ -2255,7 +2286,7 @@ void HistoryBackend::KillHistoryDatabase() {
// databases which will be closed.
expirer_.SetDatabases(nullptr, nullptr);
- // Reopen a new transaction for |db_| for the sake of CloseAllDatabases().
+ // Reopen a new transaction for `db_` for the sake of CloseAllDatabases().
db_->BeginTransaction();
CloseAllDatabases();
}
@@ -2413,9 +2444,8 @@ bool HistoryBackend::ClearAllMainHistory(const URLRows& kept_urls) {
return false;
// Insert the URLs into the temporary table.
- for (auto i = kept_urls.begin(); i != kept_urls.end(); ++i) {
- db_->AddTemporaryURL(*i);
- }
+ for (const auto& url : kept_urls)
+ db_->AddTemporaryURL(url);
// Replace the original URL table with the temporary one.
if (!db_->CommitTemporaryURLTable())
diff --git a/chromium/components/history/core/browser/history_backend.h b/chromium/components/history/core/browser/history_backend.h
index f11436eb1bc..bbf6b21b217 100644
--- a/chromium/components/history/core/browser/history_backend.h
+++ b/chromium/components/history/core/browser/history_backend.h
@@ -24,7 +24,6 @@
#include "base/macros.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/supports_user_data.h"
#include "base/task/cancelable_task_tracker.h"
@@ -38,6 +37,7 @@
#include "components/history/core/browser/keyword_id.h"
#include "components/history/core/browser/visit_tracker.h"
#include "sql/init_status.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class SkBitmap;
@@ -59,6 +59,7 @@ class HistoryBackendClient;
class HistoryBackendDBBaseTest;
class HistoryBackendObserver;
class HistoryBackend;
+class TestHistoryBackend;
class HistoryBackendTest;
class HistoryDatabase;
struct HistoryDatabaseParams;
@@ -68,12 +69,12 @@ class HistoryBackendHelper;
class TypedURLSyncBridge;
class URLDatabase;
-// Returns a formatted version of |url| with the HTTP/HTTPS scheme, port,
+// Returns a formatted version of `url` with the HTTP/HTTPS scheme, port,
// username/password, and any trivial subdomains (e.g., "www.", "m.") removed.
std::u16string FormatUrlForRedirectComparison(const GURL& url);
-// Advances (if |day| >= 0) or backtracks (if |day| < 0) from |time| by
-// abs(|day|) calendar days in local timezone and returns the midnight of the
+// Advances (if `day` >= 0) or backtracks (if `day` < 0) from `time` by
+// abs(`day`) calendar days in local timezone and returns the midnight of the
// resulting day.
base::Time MidnightNDaysLater(base::Time time, int days);
@@ -120,10 +121,10 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// a history service object.
class Delegate {
public:
- virtual ~Delegate() {}
+ virtual ~Delegate() = default;
// Called when the database cannot be read correctly for some reason.
- // |diagnostics| contains information about the underlying database
+ // `diagnostics` contains information about the underlying database
// which can help in identifying the cause of the profile error.
virtual void NotifyProfileError(sql::InitStatus init_status,
const std::string& diagnostics) = 0;
@@ -142,7 +143,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// http://www.google.com) and the given icon URL (e.g.
// http://www.google.com/favicon.ico) have changed. HistoryService notifies
// any registered callbacks. It is valid to call NotifyFaviconsChanged()
- // with non-empty |page_urls| and an empty |icon_url| and vice versa.
+ // with non-empty `page_urls` and an empty `icon_url` and vice versa.
virtual void NotifyFaviconsChanged(const std::set<GURL>& page_urls,
const GURL& icon_url) = 0;
@@ -190,11 +191,11 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// constructed on any thread, but all other functions including Init() must
// be called on the history thread.
//
- // |history_dir| is the directory where the history files will be placed.
+ // `history_dir` is the directory where the history files will be placed.
// See the definition of BroadcastNotificationsCallback above. This function
// takes ownership of the callback pointer.
//
- // |history_client| is used to determine bookmarked URLs when deleting and
+ // `history_client` is used to determine bookmarked URLs when deleting and
// may be null.
//
// This constructor is fast and does no I/O, so can be called at any time.
@@ -206,7 +207,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// fails, all other functions will fail as well. (Since this runs on another
// thread, we don't bother returning failure.)
//
- // |force_fail| can be set during unittests to unconditionally fail to init.
+ // `force_fail` can be set during unittests to unconditionally fail to init.
void Init(bool force_fail,
const HistoryDatabaseParams& history_database_params);
@@ -226,7 +227,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// Clears all on-demand favicons.
void ClearAllOnDemandFavicons();
- // Gets the counts and last last time of URLs that belong to |origins| in the
+ // Gets the counts and last last time of URLs that belong to `origins` in the
// history database. Origins that are not in the history database will be in
// the map with a count and time of 0.
// Returns an empty map if db_ is not initialized.
@@ -235,7 +236,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// Navigation ----------------------------------------------------------------
- // |request.time| must be unique with high probability.
+ // `request.time` must be unique with high probability.
void AddPage(const HistoryAddPageArgs& request);
virtual void SetPageTitle(const GURL& url, const std::u16string& title);
void AddPageNoVisitForBookmark(const GURL& url, const std::u16string& title);
@@ -250,8 +251,8 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// Querying ------------------------------------------------------------------
- // Run the |callback| on the History thread.
- // |callback| should handle the null database case.
+ // Run the `callback` on the History thread.
+ // `callback` should handle the null database case.
void ScheduleAutocomplete(
base::OnceCallback<void(HistoryBackend*, URLDatabase*)> callback);
@@ -267,22 +268,22 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
RedirectList QueryRedirectsFrom(const GURL& url);
// Similar to above function except computes a chain of redirects to the
- // given URL. Stores the most recent list of redirects ending at |url| in the
+ // given URL. Stores the most recent list of redirects ending at `url` in the
// given RedirectList. For example, if we have the redirect list A -> B -> C,
// then calling this function with url=C would fill redirects with {B, A}.
RedirectList QueryRedirectsTo(const GURL& url);
VisibleVisitCountToHostResult GetVisibleVisitCountToHost(const GURL& url);
- // Request the |result_count| most visited URLs and the chain of
- // redirects leading to each of these URLs. |days_back| is the
+ // Request the `result_count` most visited URLs and the chain of
+ // redirects leading to each of these URLs. `days_back` is the
// number of days of history to use. Used by TopSites.
MostVisitedURLList QueryMostVisitedURLs(int result_count, int days_back);
// Statistics ----------------------------------------------------------------
// Gets the number of URLs as seen in chrome://history within the time range
- // [|begin_time|, |end_time|). Each URL is counted only once per day. For
+ // [`begin_time`, `end_time`). Each URL is counted only once per day. For
// determination of the date, timestamps are converted to dates using local
// time.
HistoryCountResult GetHistoryCount(const base::Time& begin_time,
@@ -296,21 +297,21 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// top-level domain (eTLD) + 1, e.g. "foo.com", "bar.co.uk") visited within
// the 1-day, 7-day or 28-day span that ends at a midnight in local timezone.
//
- // For each of the most recent |number_of_days_to_report| midnights before
- // |report_time|(inclusive), this function computes a subset of
+ // For each of the most recent `number_of_days_to_report` midnights before
+ // `report_time`(inclusive), this function computes a subset of
// {1-day, 7-day, 28-day} metrics whose spanning periods all end on that
// midnight. This subset of metrics to compute is specified by a bitmask
- // |metric_type_bitmask|, which takes a bitwise combination of
+ // `metric_type_bitmask`, which takes a bitwise combination of
// kEnableLast1DayMetric, kEnableLast7DayMetric and kEnableLast28DayMetric.
//
// All computed metrics are stored in DomainDiversityResults, which represents
// a collection of DomainMetricSet's. Each DomainMetricSet contains up to 3
// metrics ending at one unique midnight in the time range of
- // |number_of_days_to_report| days before |report_time|. The collection of
+ // `number_of_days_to_report` days before `report_time`. The collection of
// DomainMetricSet is sorted reverse chronologically by the ending midnight.
//
- // For example, when |report_time| = 2019/11/01 00:01am, |number_of_days| = 3,
- // |metric_type_bitmask| = kEnableLast28DayMetric | kEnableLast1DayMetric,
+ // For example, when `report_time` = 2019/11/01 00:01am, `number_of_days` = 3,
+ // `metric_type_bitmask` = kEnableLast28DayMetric | kEnableLast1DayMetric,
// DomainDiversityResults will hold 3 DomainMetricSets, each containing 2
// metrics measuring domain visit counts spanning the following date ranges
// (all dates are inclusive):
@@ -321,20 +322,20 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
DomainMetricBitmaskType metric_type_bitmask);
// Gets the last time any webpage on the given host was visited within the
- // time range [|begin_time|, |end_time|). If the given host has not been
+ // time range [`begin_time`, `end_time`). If the given host has not been
// visited in the given time range, the result will have a null base::Time,
// but still report success.
HistoryLastVisitResult GetLastVisitToHost(const GURL& host,
base::Time begin_time,
base::Time end_time);
- // Gets the last time |url| was visited before |end_time|. If the given URL
+ // Gets the last time `url` was visited before `end_time`. If the given URL
// has not been visited in the past, the result will have a null base::Time,
// but still report success.
HistoryLastVisitResult GetLastVisitToURL(const GURL& url,
base::Time end_time);
- // Gets counts for total visits and days visited for pages matching |host|'s
+ // Gets counts for total visits and days visited for pages matching `host`'s
// scheme, port, and host. Counts only user-visible visits.
DailyVisitsResult GetDailyVisitsToHost(const GURL& host,
base::Time begin_time,
@@ -377,7 +378,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
scoped_refptr<base::RefCountedMemory> bitmap_data,
const gfx::Size& pixel_size);
- // |page_urls| must not be empty.
+ // `page_urls` must not be empty.
void SetFavicons(const base::flat_set<GURL>& page_urls,
favicon_base::IconType icon_type,
const GURL& icon_url,
@@ -426,6 +427,14 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
void DeleteMatchingURLsForKeyword(KeywordID keyword_id,
const std::u16string& term);
+ // Clusters ------------------------------------------------------------------
+
+ void AddContextAnnotationsForVisit(
+ VisitID visit_id,
+ const VisitContextAnnotations& visit_context_annotations);
+
+ std::vector<AnnotatedVisit> GetAnnotatedVisits(int max_results);
+
// Observers -----------------------------------------------------------------
void AddObserver(HistoryBackendObserver* observer);
@@ -442,12 +451,12 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
virtual bool GetVisitsForURL(URLID id, VisitVector* visits);
- // Fetches up to |max_visits| most recent visits for the passed URL.
+ // Fetches up to `max_visits` most recent visits for the passed URL.
virtual bool GetMostRecentVisitsForURL(URLID id,
int max_visits,
VisitVector* visits);
- // For each element in |urls|, updates the pre-existing URLRow in the database
+ // For each element in `urls`, updates the pre-existing URLRow in the database
// with the same ID; or ignores the element if no such row exists. Returns the
// number of records successfully updated.
virtual size_t UpdateURLs(const URLRows& urls);
@@ -469,7 +478,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
bool GetURLByID(URLID url_id, URLRow* url_row);
// Returns the sync controller delegate for syncing typed urls. The returned
- // delegate is owned by |this| object.
+ // delegate is owned by `this` object.
base::WeakPtr<syncer::ModelTypeControllerDelegate>
GetTypedURLSyncControllerDelegate();
@@ -489,9 +498,9 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
base::Time end_time,
bool user_initiated);
- // Finds the URLs visited at |times| and expires all their visits within
- // [|begin_time|, |end_time|). All times in |times| should be in
- // [|begin_time|, |end_time|). This is used when expiration request is from
+ // Finds the URLs visited at `times` and expires all their visits within
+ // [`begin_time`, `end_time`). All times in `times` should be in
+ // [`begin_time`, `end_time`). This is used when expiration request is from
// server side, i.e. web history deletes, where only visit times (possibly
// incomplete) are transmitted to protect user's privacy.
void ExpireHistoryForTimes(const std::set<base::Time>& times,
@@ -499,7 +508,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
base::Time end_time);
// Calls ExpireHistoryBetween() once for each element in the vector.
- // The fields of |ExpireHistoryArgs| map directly to the arguments of
+ // The fields of `ExpireHistoryArgs` map directly to the arguments of
// of ExpireHistoryBetween().
void ExpireHistory(const std::vector<ExpireHistoryArgs>& expire_list);
@@ -568,94 +577,10 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
private:
friend class base::RefCountedThreadSafe<HistoryBackend>;
+ friend class TestHistoryBackend;
friend class HistoryBackendTest;
friend class HistoryBackendDBBaseTest; // So the unit tests can poke our
// innards.
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, DeleteAll);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, DeleteAllURLPreviouslyDeleted);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, DeleteAllThenAddData);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddPagesWithDetails);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, UpdateURLs);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, ImportedFaviconsTest);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, URLsNoLongerBookmarked);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, StripUsernamePasswordTest);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddPageVisitSource);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddPageVisitBackForward);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddPageVisitRedirectBackForward);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddPageVisitNotLastVisit);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- AddPageVisitFiresNotificationWithCorrectDetails);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddPageArgsSource);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, AddVisitsSource);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, GetMostRecentVisits);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, RemoveVisitsSource);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, RemoveVisitsTransitions);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MigrationVisitSource);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- SetFaviconMappingsForPageAndRedirects);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- SetFaviconMappingsForPageAndRedirectsWithFragment);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- RecentRedirectsForClientRedirects);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- SetFaviconMappingsForPageDuplicates);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetFaviconsDeleteBitmaps);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetFaviconsReplaceBitmapData);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- SetFaviconsSameFaviconURLForTwoPages);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetFaviconsWithTwoPageURLs);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetOnDemandFaviconsForEmptyDB);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetOnDemandFaviconsForPageInDB);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetOnDemandFaviconsForIconInDB);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- UpdateFaviconMappingsAndFetchNoChange);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MergeFaviconPageURLNotInDB);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MergeFaviconPageURLInDB);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MergeFaviconMaxFaviconsPerPage);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- MergeFaviconIconURLMappedToDifferentPageURL);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- MergeFaviconMaxFaviconBitmapsPerIconURL);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- MergeIdenticalFaviconDoesNotChangeLastUpdatedTime);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- FaviconChangedNotificationNewFavicon);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- FaviconChangedNotificationBitmapDataChanged);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- FaviconChangedNotificationIconMappingChanged);
- FRIEND_TEST_ALL_PREFIXES(
- HistoryBackendTest,
- FaviconChangedNotificationIconMappingAndBitmapDataChanged);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- FaviconChangedNotificationsMergeCopy);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, NoFaviconChangedNotifications);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- UpdateFaviconMappingsAndFetchMultipleIconTypes);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, CloneFaviconMappingsForPages);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, GetFaviconsFromDBEmpty);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- GetFaviconsFromDBNoFaviconBitmaps);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- GetFaviconsFromDBSelectClosestMatch);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, GetFaviconsFromDBIconType);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, GetFaviconsFromDBExpired);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, GetFaviconsFromDBFallbackToHost);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest,
- UpdateFaviconMappingsAndFetchNoDB);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, QueryFilteredURLs);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, TopHosts);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, TopHosts_ElidePortAndScheme);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, TopHosts_ElideWWW);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, TopHosts_OnlyLast30Days);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, TopHosts_MaxNumHosts);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, TopHosts_IgnoreUnusualURLs);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, GetCountsAndLastVisitForOrigins);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, UpdateVisitDuration);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, ExpireHistoryForTimes);
- FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, DeleteFTSIndexDatabases);
- FRIEND_TEST_ALL_PREFIXES(ProfileSyncServiceTypedUrlTest,
- ProcessUserChangeRemove);
// Returns the name of the Favicons database.
base::FilePath GetFaviconsFileName() const;
@@ -690,22 +615,22 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
VisitSource visit_source,
bool should_increment_typed_count,
bool floc_allowed,
- base::Optional<std::u16string> title = base::nullopt);
+ absl::optional<std::u16string> title = absl::nullopt);
- // Returns a redirect chain in |redirects| for the VisitID
- // |cur_visit|. |cur_visit| is assumed to be valid. Assumes that
+ // Returns a redirect chain in `redirects` for the VisitID
+ // `cur_visit`. `cur_visit` is assumed to be valid. Assumes that
// this HistoryBackend object has been Init()ed successfully.
void GetRedirectsFromSpecificVisit(VisitID cur_visit,
RedirectList* redirects);
// Similar to the above function except returns a redirect list ending
- // at |cur_visit|.
+ // at `cur_visit`.
void GetRedirectsToSpecificVisit(VisitID cur_visit, RedirectList* redirects);
// Updates the visit_duration information in visits table.
void UpdateVisitDuration(VisitID visit_id, const base::Time end_ts);
- // Returns whether |url| is on an untyped intranet host.
+ // Returns whether `url` is on an untyped intranet host.
bool IsUntypedIntranetHost(const GURL& url);
// Querying ------------------------------------------------------------------
@@ -755,19 +680,19 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// Favicons ------------------------------------------------------------------
- // Returns all the page URLs in the redirect chain for |page_url|. If there
- // are no known redirects for |page_url|, returns a vector with |page_url|.
+ // Returns all the page URLs in the redirect chain for `page_url`. If there
+ // are no known redirects for `page_url`, returns a vector with `page_url`.
RedirectList GetCachedRecentRedirects(const GURL& page_url);
- // Send notification that the favicon has changed for |page_url| and all its
+ // Send notification that the favicon has changed for `page_url` and all its
// redirects. This should be called if the mapping between the page URL
// (e.g. http://www.google.com) and the icon URL (e.g.
// http://www.google.com/favicon.ico) has changed.
void SendFaviconChangedNotificationForPageAndRedirects(const GURL& page_url);
- // Send notification that the bitmap data for the favicon at |icon_url| has
+ // Send notification that the bitmap data for the favicon at `icon_url` has
// changed. Sending this notification is important because the favicon at
- // |icon_url| may be mapped to hundreds of page URLs.
+ // `icon_url` may be mapped to hundreds of page URLs.
void SendFaviconChangedNotificationForIconURL(const GURL& icon_url);
// Generic stuff -------------------------------------------------------------
@@ -867,10 +792,6 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>,
// Tracks page transition types.
VisitTracker tracker_;
- // A boolean variable to track whether we have already purged obsolete segment
- // data.
- bool segment_queried_;
-
// List of QueuedHistoryDBTasks to run;
std::list<std::unique_ptr<QueuedHistoryDBTask>> queued_history_db_tasks_;
diff --git a/chromium/components/history/core/browser/history_backend_client.h b/chromium/components/history/core/browser/history_backend_client.h
index 7f8bcda037f..753915751ab 100644
--- a/chromium/components/history/core/browser/history_backend_client.h
+++ b/chromium/components/history/core/browser/history_backend_client.h
@@ -30,7 +30,7 @@ class HistoryBackendClient {
// Returns the set of pinned URLs with their titles.
virtual std::vector<URLAndTitle> GetPinnedURLs() = 0;
- // Returns whether |url| should be considered web-safe (see
+ // Returns whether `url` should be considered web-safe (see
// content::ChildProcessSecurityPolicy).
virtual bool IsWebSafe(const GURL& url) = 0;
diff --git a/chromium/components/history/core/browser/history_backend_db_unittest.cc b/chromium/components/history/core/browser/history_backend_db_unittest.cc
index 222eb2682b1..ef14c66b313 100644
--- a/chromium/components/history/core/browser/history_backend_db_unittest.cc
+++ b/chromium/components/history/core/browser/history_backend_db_unittest.cc
@@ -1894,6 +1894,66 @@ TEST_F(HistoryBackendDBTest, MigrateFlocAllowedToAnnotationsTable) {
}
}
+TEST_F(HistoryBackendDBTest, MigrateReplaceClusterVisitsTable) {
+ ASSERT_NO_FATAL_FAILURE(CreateDBVersion(44));
+
+ sql::Database db;
+ ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename)));
+
+ const char kInsertVisitStatement[] =
+ "INSERT INTO visits "
+ "(id, url, visit_time) VALUES (?, ?, ?)";
+
+ const char kInsertAnnotationsStatement[] =
+ "INSERT INTO cluster_visits "
+ "(cluster_visit_id, url_id, visit_id, "
+ "cluster_visit_context_signal_bitmask, duration_since_last_visit, "
+ "page_end_reason) "
+ "VALUES (?, ?, ?, ?, ?, ?)";
+
+ // Add a row to `visits` table.
+ {
+ sql::Statement s(db.GetUniqueStatement(kInsertVisitStatement));
+ s.BindInt64(0, 1);
+ s.BindInt64(1, 1);
+ s.BindTime(2, base::Time::Now());
+ ASSERT_TRUE(s.Run());
+ }
+
+ // Add a row to the `cluster_visits` table.
+ {
+ sql::Statement s(db.GetUniqueStatement(kInsertAnnotationsStatement));
+ s.BindInt64(0, 1);
+ s.BindInt64(1, 1);
+ s.BindInt64(2, 1);
+ s.BindInt64(3, 0);
+ s.BindInt64(4, 0);
+ s.BindInt(5, 0);
+ ASSERT_TRUE(s.Run());
+ }
+
+ // Re-open the db, triggering migration.
+ CreateBackendAndDatabase();
+
+ // The version should have been updated.
+ ASSERT_GE(HistoryDatabase::GetCurrentVersion(), 45);
+
+ // Confirm the old `cluster_visits` table no longer exists.
+ ASSERT_FALSE(db.DoesTableExist("cluster_visits"));
+
+ // Confirm the new `context_annotations` exists.
+ ASSERT_TRUE(db.DoesTableExist("context_annotations"));
+
+ // Check `context_annotations` is empty.
+ {
+ sql::Statement s(
+ db.GetUniqueStatement("SELECT COUNT(*) FROM content_annotations"));
+ EXPECT_TRUE(s.Step());
+ EXPECT_EQ(s.ColumnInt64(0), 0u);
+ EXPECT_FALSE(s.Step());
+ }
+}
+
// Tests that the migration code correctly replaces the lower_term column in the
// keyword search terms table which normalized_term which contains the
// normalized search term during migration to version 42.
diff --git a/chromium/components/history/core/browser/history_backend_notifier.h b/chromium/components/history/core/browser/history_backend_notifier.h
index d63a68e06a7..077d37c2c9c 100644
--- a/chromium/components/history/core/browser/history_backend_notifier.h
+++ b/chromium/components/history/core/browser/history_backend_notifier.h
@@ -24,25 +24,25 @@ class HistoryBackendNotifier {
// Sends notification that the favicons for the given page URLs (e.g.
// http://www.google.com) and the given icon URL (e.g.
// http://www.google.com/favicon.ico) have changed. It is valid to call
- // NotifyFaviconsChanged() with non-empty |page_urls| and an empty |icon_url|
+ // NotifyFaviconsChanged() with non-empty `page_urls` and an empty `icon_url`
// and vice versa.
virtual void NotifyFaviconsChanged(const std::set<GURL>& page_urls,
const GURL& icon_url) = 0;
- // Sends notification that |transition| to |row| occurred at |visit_time|
- // following |redirects| (empty if there is no redirects).
+ // Sends notification that `transition` to `row` occurred at `visit_time`
+ // following `redirects` (empty if there is no redirects).
virtual void NotifyURLVisited(ui::PageTransition transition,
const URLRow& row,
const RedirectList& redirects,
base::Time visit_time) = 0;
- // Sends notification that |changed_urls| have been changed or added.
+ // Sends notification that `changed_urls` have been changed or added.
virtual void NotifyURLsModified(const URLRows& changed_urls,
UrlsModifiedReason reason) = 0;
// Sends notification that some or the totality of the URLs have been
// deleted.
- // |deletion_info| describes the urls that have been removed from history.
+ // `deletion_info` describes the urls that have been removed from history.
virtual void NotifyURLsDeleted(DeletionInfo deletion_info) = 0;
};
diff --git a/chromium/components/history/core/browser/history_backend_observer.h b/chromium/components/history/core/browser/history_backend_observer.h
index f0e905ada81..ead1241b60f 100644
--- a/chromium/components/history/core/browser/history_backend_observer.h
+++ b/chromium/components/history/core/browser/history_backend_observer.h
@@ -19,11 +19,11 @@ class HistoryBackendObserver {
// Called when user visits an URL.
//
- // The |row| ID will be set to the value that is currently in effect in the
- // main history database. |redirects| is the list of redirects leading up to
+ // The `row` ID will be set to the value that is currently in effect in the
+ // main history database. `redirects` is the list of redirects leading up to
// the URL. If we have a redirect chain A -> B -> C and user is visiting C,
- // then |redirects[0]=B| and |redirects[1]=A|. If there are no redirects,
- // |redirects| is an empty vector.
+ // then `redirects[0]=B` and `redirects[1]=A`. If there are no redirects,
+ // `redirects` is an empty vector.
virtual void OnURLVisited(HistoryBackend* history_backend,
ui::PageTransition transition,
const URLRow& row,
@@ -32,9 +32,9 @@ class HistoryBackendObserver {
// Called when a URL has been added or modified.
//
- // |changed_urls| lists the information for each of the URLs affected. The
+ // `changed_urls` lists the information for each of the URLs affected. The
// rows will have the IDs that are currently in effect in the main history
- // database. |is_from_expiration| is true if the modification is caused by
+ // database. `is_from_expiration` is true if the modification is caused by
// automatic history expiration (the visit count got reduced by expiring some
// of the visits); it is false if the modification is caused by user action.
virtual void OnURLsModified(HistoryBackend* history_backend,
@@ -43,12 +43,12 @@ class HistoryBackendObserver {
// Called when one or more of URLs are deleted.
//
- // |all_history| is set to true, if all the URLs are deleted.
- // When set to true, |deleted_rows| and |favicon_urls| are
+ // `all_history` is set to true, if all the URLs are deleted.
+ // When set to true, `deleted_rows` and `favicon_urls` are
// undefined.
- // |expired| is set to true, if the URL deletion is due to expiration.
- // |deleted_rows| list of the deleted URLs.
- // |favicon_urls| list of favicon URLs that correspond to the deleted URLs.
+ // `expired` is set to true, if the URL deletion is due to expiration.
+ // `deleted_rows` list of the deleted URLs.
+ // `favicon_urls` list of favicon URLs that correspond to the deleted URLs.
virtual void OnURLsDeleted(HistoryBackend* history_backend,
bool all_history,
bool expired,
diff --git a/chromium/components/history/core/browser/history_backend_unittest.cc b/chromium/components/history/core/browser/history_backend_unittest.cc
index 388ea7c3cba..cc847b716bf 100644
--- a/chromium/components/history/core/browser/history_backend_unittest.cc
+++ b/chromium/components/history/core/browser/history_backend_unittest.cc
@@ -27,6 +27,7 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/gtest_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -59,6 +60,8 @@
// history unit test. Because of the elaborate callbacks involved, this is no
// harder than calling it directly for many things.
+namespace history {
+
namespace {
using base::HistogramBase;
@@ -77,15 +80,13 @@ const gfx::Size kSmallSize = gfx::Size(kSmallEdgeSize, kSmallEdgeSize);
const gfx::Size kLargeSize = gfx::Size(kLargeEdgeSize, kLargeEdgeSize);
using SimulateNotificationCallback =
- base::RepeatingCallback<void(const history::URLRow*,
- const history::URLRow*,
- const history::URLRow*)>;
-
-void SimulateNotificationURLVisited(history::HistoryServiceObserver* observer,
- const history::URLRow* row1,
- const history::URLRow* row2,
- const history::URLRow* row3) {
- history::URLRows rows;
+ base::RepeatingCallback<void(const URLRow*, const URLRow*, const URLRow*)>;
+
+void SimulateNotificationURLVisited(HistoryServiceObserver* observer,
+ const URLRow* row1,
+ const URLRow* row2,
+ const URLRow* row3) {
+ URLRows rows;
rows.push_back(*row1);
if (row2)
rows.push_back(*row2);
@@ -93,18 +94,18 @@ void SimulateNotificationURLVisited(history::HistoryServiceObserver* observer,
rows.push_back(*row3);
base::Time visit_time;
- history::RedirectList redirects;
- for (const history::URLRow& row : rows) {
+ RedirectList redirects;
+ for (const URLRow& row : rows) {
observer->OnURLVisited(nullptr, ui::PAGE_TRANSITION_LINK, row, redirects,
visit_time);
}
}
-void SimulateNotificationURLsModified(history::HistoryServiceObserver* observer,
- const history::URLRow* row1,
- const history::URLRow* row2,
- const history::URLRow* row3) {
- history::URLRows rows;
+void SimulateNotificationURLsModified(HistoryServiceObserver* observer,
+ const URLRow* row1,
+ const URLRow* row2,
+ const URLRow* row3) {
+ URLRows rows;
rows.push_back(*row1);
if (row2)
rows.push_back(*row2);
@@ -116,8 +117,6 @@ void SimulateNotificationURLsModified(history::HistoryServiceObserver* observer,
} // namespace
-namespace history {
-
class HistoryBackendTestBase;
// This must be a separate object since HistoryBackend manages its lifetime.
@@ -153,6 +152,24 @@ class HistoryBackendTestDelegate : public HistoryBackend::Delegate {
HistoryBackendTestBase* test_;
};
+// Exposes some of `HistoryBackend`'s private methods.
+class TestHistoryBackend : public HistoryBackend {
+ public:
+ using HistoryBackend::AddPageVisit;
+ using HistoryBackend::DeleteAllHistory;
+ using HistoryBackend::DeleteFTSIndexDatabases;
+ using HistoryBackend::HistoryBackend;
+ using HistoryBackend::UpdateVisitDuration;
+
+ using HistoryBackend::db_;
+ using HistoryBackend::expirer_;
+ using HistoryBackend::favicon_backend_;
+ using HistoryBackend::recent_redirects_;
+
+ private:
+ ~TestHistoryBackend() override = default;
+};
+
class HistoryBackendTestBase : public testing::Test {
public:
typedef std::vector<std::pair<ui::PageTransition, URLRow>> URLVisitedList;
@@ -244,8 +261,8 @@ class HistoryBackendTestBase : public testing::Test {
}
base::test::TaskEnvironment task_environment_;
- history::HistoryClientFakeBookmarks history_client_;
- scoped_refptr<HistoryBackend> backend_; // Will be NULL on init failure.
+ HistoryClientFakeBookmarks history_client_;
+ scoped_refptr<TestHistoryBackend> backend_; // Will be NULL on init failure.
std::unique_ptr<InMemoryHistoryBackend> mem_backend_;
bool loaded_ = false;
@@ -257,7 +274,7 @@ class HistoryBackendTestBase : public testing::Test {
if (!base::CreateNewTempDirectory(FILE_PATH_LITERAL("BackendTest"),
&test_dir_))
return;
- backend_ = base::MakeRefCounted<HistoryBackend>(
+ backend_ = base::MakeRefCounted<TestHistoryBackend>(
std::make_unique<HistoryBackendTestDelegate>(this),
history_client_.CreateBackendClient(),
base::ThreadTaskRunnerHandle::Get());
@@ -352,24 +369,24 @@ class HistoryBackendTest : public HistoryBackendTestBase {
int nav_entry_id,
ui::PageTransition transition,
base::Time time) {
- history::RedirectList redirects;
+ RedirectList redirects;
for (int i = 0; sequence[i] != nullptr; ++i)
redirects.push_back(GURL(sequence[i]));
ContextID context_id = reinterpret_cast<ContextID>(1);
- history::HistoryAddPageArgs request(
- redirects.back(), time, context_id, nav_entry_id, GURL(), redirects,
- transition, false, history::SOURCE_BROWSED, true, true, false);
+ HistoryAddPageArgs request(redirects.back(), time, context_id, nav_entry_id,
+ GURL(), redirects, transition, false,
+ SOURCE_BROWSED, true, true, false);
backend_->AddPage(request);
}
// Adds CLIENT_REDIRECT page transition.
- // |url1| is the source URL and |url2| is the destination.
- // |did_replace| is true if the transition is non-user initiated and the
- // navigation entry for |url2| has replaced that for |url1|. The possibly
- // updated transition code of the visit records for |url1| and |url2| is
- // returned by filling in |*transition1| and |*transition2|, respectively,
- // unless null. |time| is a time of the redirect.
+ // `url1` is the source URL and `url2` is the destination.
+ // `did_replace` is true if the transition is non-user initiated and the
+ // navigation entry for `url2` has replaced that for `url1`. The possibly
+ // updated transition code of the visit records for `url1` and `url2` is
+ // returned by filling in `*transition1` and `*transition2`, respectively,
+ // unless null. `time` is a time of the redirect.
void AddClientRedirect(const GURL& url1,
const GURL& url2,
bool did_replace,
@@ -377,15 +394,14 @@ class HistoryBackendTest : public HistoryBackendTestBase {
int* transition1,
int* transition2) {
ContextID dummy_context_id = reinterpret_cast<ContextID>(0x87654321);
- history::RedirectList redirects;
+ RedirectList redirects;
if (url1.is_valid())
redirects.push_back(url1);
if (url2.is_valid())
redirects.push_back(url2);
HistoryAddPageArgs request(url2, time, dummy_context_id, 0, url1, redirects,
ui::PAGE_TRANSITION_CLIENT_REDIRECT, false,
- history::SOURCE_BROWSED, did_replace, true,
- false);
+ SOURCE_BROWSED, did_replace, true, false);
backend_->AddPage(request);
if (transition1)
@@ -396,12 +412,12 @@ class HistoryBackendTest : public HistoryBackendTestBase {
}
// Adds SERVER_REDIRECT page transition.
- // |url1| is the source URL and |url2| is the destination.
- // |did_replace| is true if the transition is non-user initiated and the
- // navigation entry for |url2| has replaced that for |url1|. The possibly
- // updated transition code of the visit records for |url1| and |url2| is
- // returned by filling in |*transition1| and |*transition2|, respectively,
- // unless null. |time| is a time of the redirect.
+ // `url1` is the source URL and `url2` is the destination.
+ // `did_replace` is true if the transition is non-user initiated and the
+ // navigation entry for `url2` has replaced that for `url1`. The possibly
+ // updated transition code of the visit records for `url1` and `url2` is
+ // returned by filling in `*transition1` and `*transition2`, respectively,
+ // unless null. `time` is a time of the redirect.
void AddServerRedirect(const GURL& url1,
const GURL& url2,
bool did_replace,
@@ -410,15 +426,15 @@ class HistoryBackendTest : public HistoryBackendTestBase {
int& transition1,
int& transition2) {
ContextID dummy_context_id = reinterpret_cast<ContextID>(0x87654321);
- history::RedirectList redirects;
+ RedirectList redirects;
redirects.push_back(url1);
redirects.push_back(url2);
ui::PageTransition redirect_transition = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_FORM_SUBMIT | ui::PAGE_TRANSITION_SERVER_REDIRECT);
- HistoryAddPageArgs request(
- url2, time, dummy_context_id, 0, url1, redirects, redirect_transition,
- false, history::SOURCE_BROWSED, did_replace, true, false,
- base::Optional<std::u16string>(page2_title));
+ HistoryAddPageArgs request(url2, time, dummy_context_id, 0, url1, redirects,
+ redirect_transition, false, SOURCE_BROWSED,
+ did_replace, true, false,
+ absl::optional<std::u16string>(page2_title));
backend_->AddPage(request);
transition1 = GetTransition(url1);
@@ -443,7 +459,7 @@ class HistoryBackendTest : public HistoryBackendTestBase {
return sizes_small_and_large;
}
- // Returns the number of icon mappings of |icon_type| to |page_url|.
+ // Returns the number of icon mappings of `icon_type` to `page_url`.
size_t NumIconMappingsForPageURL(const GURL& page_url, IconType icon_type) {
std::vector<IconMapping> icon_mappings;
favicon_db()->GetIconMappingsForPageURL(page_url, {icon_type},
@@ -451,14 +467,14 @@ class HistoryBackendTest : public HistoryBackendTestBase {
return icon_mappings.size();
}
- // Returns the icon mappings for |page_url|.
+ // Returns the icon mappings for `page_url`.
std::vector<IconMapping> GetIconMappingsForPageURL(const GURL& page_url) {
std::vector<IconMapping> icon_mappings;
favicon_db()->GetIconMappingsForPageURL(page_url, &icon_mappings);
return icon_mappings;
}
- // Returns the favicon bitmaps for |icon_id| sorted by pixel size in
+ // Returns the favicon bitmaps for `icon_id` sorted by pixel size in
// ascending order. Returns true if there is at least one favicon bitmap.
bool GetSortedFaviconBitmaps(favicon_base::FaviconID icon_id,
std::vector<FaviconBitmap>* favicon_bitmaps) {
@@ -472,7 +488,7 @@ class HistoryBackendTest : public HistoryBackendTestBase {
}
// Returns true if there is exactly one favicon bitmap associated to
- // |favicon_id|. If true, returns favicon bitmap in output parameter.
+ // `favicon_id`. If true, returns favicon bitmap in output parameter.
bool GetOnlyFaviconBitmap(const favicon_base::FaviconID icon_id,
FaviconBitmap* favicon_bitmap) {
std::vector<FaviconBitmap> favicon_bitmaps;
@@ -484,7 +500,7 @@ class HistoryBackendTest : public HistoryBackendTestBase {
return true;
}
- // Creates an |edge_size|x|edge_size| bitmap of |color|.
+ // Creates an `edge_size`x`edge_size` bitmap of `color`.
SkBitmap CreateBitmap(SkColor color, int edge_size) {
SkBitmap bitmap;
bitmap.allocN32Pixels(edge_size, edge_size);
@@ -492,7 +508,7 @@ class HistoryBackendTest : public HistoryBackendTestBase {
return bitmap;
}
- // Returns true if |bitmap_data| is equal to |expected_data|.
+ // Returns true if `bitmap_data` is equal to `expected_data`.
bool BitmapDataEqual(char expected_data,
scoped_refptr<base::RefCountedMemory> bitmap_data) {
return bitmap_data.get() &&
@@ -567,13 +583,13 @@ class InMemoryHistoryBackendTest : public HistoryBackendTestBase {
const SimulateNotificationCallback& callback);
static const KeywordID kTestKeywordId;
- static const char kTestSearchTerm1[];
- static const char kTestSearchTerm2[];
+ static const char16_t kTestSearchTerm1[];
+ static const char16_t kTestSearchTerm2[];
};
const KeywordID InMemoryHistoryBackendTest::kTestKeywordId = 42;
-const char InMemoryHistoryBackendTest::kTestSearchTerm1[] = "banana";
-const char InMemoryHistoryBackendTest::kTestSearchTerm2[] = "orange";
+const char16_t InMemoryHistoryBackendTest::kTestSearchTerm1[] = u"banana";
+const char16_t InMemoryHistoryBackendTest::kTestSearchTerm2[] = u"orange";
// http://crbug.com/114287
#if defined(OS_WIN)
@@ -634,7 +650,7 @@ TEST_F(HistoryBackendTest, DeleteAll) {
URLRows rows;
rows.push_back(row2); // Reversed order for the same reason as favicons.
rows.push_back(row1);
- backend_->AddPagesWithDetails(rows, history::SOURCE_BROWSED);
+ backend_->AddPagesWithDetails(rows, SOURCE_BROWSED);
URLID row1_id = backend_->db_->GetRowForURL(row1.url(), nullptr);
URLID row2_id = backend_->db_->GetRowForURL(row2.url(), nullptr);
@@ -734,15 +750,14 @@ TEST_F(HistoryBackendTest, DeleteAllURLPreviouslyDeleted) {
GURL kPageURL("http://www.google.com");
GURL kFaviconURL("http://www.google.com/favicon.ico");
- // Setup: Add visit for |kPageURL|.
+ // Setup: Add visit for `kPageURL`.
URLRow row(kPageURL);
row.set_visit_count(2);
row.set_typed_count(1);
row.set_last_visit(base::Time::Now());
- backend_->AddPagesWithDetails(std::vector<URLRow>(1u, row),
- history::SOURCE_BROWSED);
+ backend_->AddPagesWithDetails(std::vector<URLRow>(1u, row), SOURCE_BROWSED);
- // Setup: Add favicon for |kPageURL|.
+ // Setup: Add favicon for `kPageURL`.
std::vector<unsigned char> data;
data.push_back('a');
favicon_base::FaviconID favicon = favicon_db()->AddFavicon(
@@ -764,7 +779,7 @@ TEST_F(HistoryBackendTest, DeleteAllURLPreviouslyDeleted) {
kPageURL, {IconType::kFavicon}, &icon_mappings));
ASSERT_EQ(1u, icon_mappings.size());
- // Delete information for |kPageURL|, then clear all browsing data.
+ // Delete information for `kPageURL`, then clear all browsing data.
backend_->DeleteURL(kPageURL);
backend_->DeleteAllHistory();
@@ -787,9 +802,9 @@ TEST_F(HistoryBackendTest, DeleteAllThenAddData) {
base::Time visit_time = base::Time::Now();
GURL url("http://www.google.com/");
HistoryAddPageArgs request(url, visit_time, nullptr, 0, GURL(),
- history::RedirectList(),
+ RedirectList(),
ui::PAGE_TRANSITION_KEYWORD_GENERATED, false,
- history::SOURCE_BROWSED, false, true, false);
+ SOURCE_BROWSED, false, true, false);
backend_->AddPage(request);
// Check that a row was added.
@@ -855,7 +870,7 @@ TEST_F(HistoryBackendTest, URLsNoLongerBookmarked) {
URLRows rows;
rows.push_back(row2); // Reversed order for the same reason as favicons.
rows.push_back(row1);
- backend_->AddPagesWithDetails(rows, history::SOURCE_BROWSED);
+ backend_->AddPagesWithDetails(rows, SOURCE_BROWSED);
URLID row1_id = backend_->db_->GetRowForURL(row1.url(), nullptr);
URLID row2_id = backend_->db_->GetRowForURL(row2.url(), nullptr);
@@ -920,9 +935,9 @@ TEST_F(HistoryBackendTest, KeywordGenerated) {
base::Time visit_time = base::Time::Now() - base::TimeDelta::FromDays(1);
HistoryAddPageArgs request(url, visit_time, nullptr, 0, GURL(),
- history::RedirectList(),
+ RedirectList(),
ui::PAGE_TRANSITION_KEYWORD_GENERATED, false,
- history::SOURCE_BROWSED, false, true, false);
+ SOURCE_BROWSED, false, true, false);
backend_->AddPage(request);
// A row should have been added for the url.
@@ -952,9 +967,9 @@ TEST_F(HistoryBackendTest, KeywordGenerated) {
// Going back to the same entry should not increment the typed count.
ui::PageTransition back_transition = ui::PageTransitionFromInt(
ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FORWARD_BACK);
- HistoryAddPageArgs back_request(
- url, visit_time, nullptr, 0, GURL(), history::RedirectList(),
- back_transition, false, history::SOURCE_BROWSED, false, true, false);
+ HistoryAddPageArgs back_request(url, visit_time, nullptr, 0, GURL(),
+ RedirectList(), back_transition, false,
+ SOURCE_BROWSED, false, true, false);
backend_->AddPage(back_request);
url_id = backend_->db()->GetRowForURL(url, &row);
ASSERT_NE(0, url_id);
@@ -1010,9 +1025,9 @@ TEST_F(HistoryBackendTest, FormSubmitRedirect) {
// User goes to form page.
GURL url_a("http://www.google.com/a");
HistoryAddPageArgs request(url_a, base::Time::Now(), nullptr, 0, GURL(),
- history::RedirectList(), ui::PAGE_TRANSITION_TYPED,
- false, history::SOURCE_BROWSED, false, true, false,
- base::Optional<std::u16string>(page1_title));
+ RedirectList(), ui::PAGE_TRANSITION_TYPED, false,
+ SOURCE_BROWSED, false, true, false,
+ absl::optional<std::u16string>(page1_title));
backend_->AddPage(request);
// Check that URL was added.
@@ -1064,9 +1079,9 @@ TEST_F(HistoryBackendTest, AddPagesWithDetails) {
rows.push_back(row2);
rows.push_back(row3);
rows.push_back(row4);
- backend_->AddPagesWithDetails(rows, history::SOURCE_BROWSED);
+ backend_->AddPagesWithDetails(rows, SOURCE_BROWSED);
- // Verify that recent URLs have ended up in the main |db_|, while the already
+ // Verify that recent URLs have ended up in the main `db_`, while the already
// expired URL has been ignored.
URLRow stored_row1, stored_row2, stored_row3, stored_row4;
EXPECT_NE(0, backend_->db_->GetRowForURL(row1.url(), &stored_row1));
@@ -1084,17 +1099,17 @@ TEST_F(HistoryBackendTest, AddPagesWithDetails) {
EXPECT_EQ(3u, changed_urls.size());
auto it_row1 = std::find_if(changed_urls.begin(), changed_urls.end(),
- history::URLRow::URLRowHasURL(row1.url()));
+ URLRow::URLRowHasURL(row1.url()));
ASSERT_NE(changed_urls.end(), it_row1);
EXPECT_EQ(stored_row1.id(), it_row1->id());
auto it_row2 = std::find_if(changed_urls.begin(), changed_urls.end(),
- history::URLRow::URLRowHasURL(row2.url()));
+ URLRow::URLRowHasURL(row2.url()));
ASSERT_NE(changed_urls.end(), it_row2);
EXPECT_EQ(stored_row2.id(), it_row2->id());
auto it_row3 = std::find_if(changed_urls.begin(), changed_urls.end(),
- history::URLRow::URLRowHasURL(row3.url()));
+ URLRow::URLRowHasURL(row3.url()));
ASSERT_NE(changed_urls.end(), it_row3);
EXPECT_EQ(stored_row3.id(), it_row3->id());
}
@@ -1152,13 +1167,13 @@ TEST_F(HistoryBackendTest, UpdateURLs) {
EXPECT_EQ(2u, changed_urls.size());
auto it_row1 = std::find_if(changed_urls.begin(), changed_urls.end(),
- history::URLRow::URLRowHasURL(row1.url()));
+ URLRow::URLRowHasURL(row1.url()));
ASSERT_NE(changed_urls.end(), it_row1);
EXPECT_EQ(altered_row1.id(), it_row1->id());
EXPECT_EQ(altered_row1.visit_count(), it_row1->visit_count());
auto it_row3 = std::find_if(changed_urls.begin(), changed_urls.end(),
- history::URLRow::URLRowHasURL(row3.url()));
+ URLRow::URLRowHasURL(row3.url()));
ASSERT_NE(changed_urls.end(), it_row3);
EXPECT_EQ(altered_row3.id(), it_row3->id());
EXPECT_EQ(altered_row3.visit_count(), it_row3->visit_count());
@@ -1167,7 +1182,7 @@ TEST_F(HistoryBackendTest, UpdateURLs) {
// This verifies that a notification is fired. In-depth testing of logic should
// be done in HistoryTest.SetTitle.
TEST_F(HistoryBackendTest, SetPageTitleFiresNotificationWithCorrectDetails) {
- const char kTestUrlTitle[] = "Google Search";
+ const char16_t kTestUrlTitle[] = u"Google Search";
ASSERT_TRUE(backend_.get());
@@ -1182,10 +1197,10 @@ TEST_F(HistoryBackendTest, SetPageTitleFiresNotificationWithCorrectDetails) {
URLRows rows;
rows.push_back(row1);
rows.push_back(row2);
- backend_->AddPagesWithDetails(rows, history::SOURCE_BROWSED);
+ backend_->AddPagesWithDetails(rows, SOURCE_BROWSED);
ClearBroadcastedNotifications();
- backend_->SetPageTitle(row2.url(), base::UTF8ToUTF16(kTestUrlTitle));
+ backend_->SetPageTitle(row2.url(), kTestUrlTitle);
// Ensure that a notification was fired, and further verify that the IDs in
// the notification are set to those that are in effect in the main database.
@@ -1196,7 +1211,7 @@ TEST_F(HistoryBackendTest, SetPageTitleFiresNotificationWithCorrectDetails) {
const URLRows& changed_urls = urls_modified_notifications()[0];
ASSERT_EQ(1u, changed_urls.size());
- EXPECT_EQ(base::UTF8ToUTF16(kTestUrlTitle), changed_urls[0].title());
+ EXPECT_EQ(kTestUrlTitle, changed_urls[0].title());
EXPECT_EQ(stored_row2.id(), changed_urls[0].id());
}
@@ -1223,7 +1238,7 @@ TEST_F(HistoryBackendTest, ImportedFaviconsTest) {
URLRows rows;
rows.push_back(row1);
rows.push_back(row2);
- backend_->AddPagesWithDetails(rows, history::SOURCE_BROWSED);
+ backend_->AddPagesWithDetails(rows, SOURCE_BROWSED);
URLRow url_row1, url_row2;
EXPECT_NE(0, backend_->db_->GetRowForURL(row1.url(), &url_row1));
EXPECT_NE(0, backend_->db_->GetRowForURL(row2.url(), &url_row2));
@@ -1288,7 +1303,7 @@ TEST_F(HistoryBackendTest, StripUsernamePasswordTest) {
// Visit the url with username, password.
backend_->AddPageVisit(url, base::Time::Now(), 0, ui::PAGE_TRANSITION_TYPED,
- false, history::SOURCE_BROWSED, true, false);
+ false, SOURCE_BROWSED, true, false);
// Fetch the row information about stripped url from history db.
VisitVector visits;
@@ -1309,7 +1324,7 @@ TEST_F(HistoryBackendTest, AddPageVisitBackForward) {
// Visit the url after typing it.
backend_->AddPageVisit(url, base::Time::Now(), 0, ui::PAGE_TRANSITION_TYPED,
- false, history::SOURCE_BROWSED, true, false);
+ false, SOURCE_BROWSED, true, false);
// Ensure both the typed count and visit count are 1.
VisitVector visits;
@@ -1324,7 +1339,7 @@ TEST_F(HistoryBackendTest, AddPageVisitBackForward) {
url, base::Time::Now(), 0,
ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
ui::PAGE_TRANSITION_FORWARD_BACK),
- false, history::SOURCE_BROWSED, false, false);
+ false, SOURCE_BROWSED, false, false);
// Ensure the typed count is still 1 but the visit count is 2.
id = backend_->db()->GetRowForURL(url, &row);
@@ -1344,12 +1359,12 @@ TEST_F(HistoryBackendTest, AddPageVisitRedirectBackForward) {
// Visit a typed URL with a redirect.
backend_->AddPageVisit(url1, base::Time::Now(), 0, ui::PAGE_TRANSITION_TYPED,
- false, history::SOURCE_BROWSED, true, false);
+ false, SOURCE_BROWSED, true, false);
backend_->AddPageVisit(
url2, base::Time::Now(), 0,
ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
ui::PAGE_TRANSITION_CLIENT_REDIRECT),
- false, history::SOURCE_BROWSED, false, false);
+ false, SOURCE_BROWSED, false, false);
// Ensure the redirected URL does not count as typed.
VisitVector visits;
@@ -1365,7 +1380,7 @@ TEST_F(HistoryBackendTest, AddPageVisitRedirectBackForward) {
ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
ui::PAGE_TRANSITION_FORWARD_BACK |
ui::PAGE_TRANSITION_CLIENT_REDIRECT),
- false, history::SOURCE_BROWSED, false, false);
+ false, SOURCE_BROWSED, false, false);
// Ensure the typed count is still 1 but the visit count is 2.
id = backend_->db()->GetRowForURL(url2, &row);
@@ -1382,15 +1397,15 @@ TEST_F(HistoryBackendTest, AddPageVisitSource) {
// Clear all history.
backend_->DeleteAllHistory();
- // Assume visiting the url from an externsion.
+ // Assume visiting the url from an extension.
backend_->AddPageVisit(url, base::Time::Now(), 0, ui::PAGE_TRANSITION_TYPED,
- false, history::SOURCE_EXTENSION, true, false);
+ false, SOURCE_EXTENSION, true, false);
// Assume the url is imported from Firefox.
backend_->AddPageVisit(url, base::Time::Now(), 0, ui::PAGE_TRANSITION_TYPED,
- false, history::SOURCE_FIREFOX_IMPORTED, true, false);
+ false, SOURCE_FIREFOX_IMPORTED, true, false);
// Assume this url is also synced.
backend_->AddPageVisit(url, base::Time::Now(), 0, ui::PAGE_TRANSITION_TYPED,
- false, history::SOURCE_SYNCED, true, false);
+ false, SOURCE_SYNCED, true, false);
// Fetch the row information about the url from history db.
VisitVector visits;
@@ -1405,13 +1420,13 @@ TEST_F(HistoryBackendTest, AddPageVisitSource) {
int sources = 0;
for (int i = 0; i < 3; i++) {
switch (visit_sources[visits[i].visit_id]) {
- case history::SOURCE_EXTENSION:
+ case SOURCE_EXTENSION:
sources |= 0x1;
break;
- case history::SOURCE_FIREFOX_IMPORTED:
+ case SOURCE_FIREFOX_IMPORTED:
sources |= 0x2;
break;
- case history::SOURCE_SYNCED:
+ case SOURCE_SYNCED:
sources |= 0x4;
break;
default:
@@ -1436,12 +1451,12 @@ TEST_F(HistoryBackendTest, AddPageVisitNotLastVisit) {
// Visit the url with recent time.
backend_->AddPageVisit(url, recent_time, 0, ui::PAGE_TRANSITION_TYPED, false,
- history::SOURCE_BROWSED, true, false);
+ SOURCE_BROWSED, true, false);
// Add to the url a visit with older time (could be syncing from another
// client, etc.).
backend_->AddPageVisit(url, older_time, 0, ui::PAGE_TRANSITION_TYPED, false,
- history::SOURCE_SYNCED, true, false);
+ SOURCE_SYNCED, true, false);
// Fetch the row information about url from history db.
VisitVector visits;
@@ -1467,11 +1482,11 @@ TEST_F(HistoryBackendTest, AddPageVisitFiresNotificationWithCorrectDetails) {
// Visit two distinct URLs, the second one twice.
backend_->AddPageVisit(url1, base::Time::Now(), 0, ui::PAGE_TRANSITION_LINK,
- false, history::SOURCE_BROWSED, false, false);
+ false, SOURCE_BROWSED, false, false);
for (int i = 0; i < 2; ++i) {
backend_->AddPageVisit(url2, base::Time::Now(), 0,
- ui::PAGE_TRANSITION_TYPED, false,
- history::SOURCE_BROWSED, true, false);
+ ui::PAGE_TRANSITION_TYPED, false, SOURCE_BROWSED,
+ true, false);
}
URLRow stored_row1, stored_row2;
@@ -1504,21 +1519,19 @@ TEST_F(HistoryBackendTest, AddPageArgsSource) {
// Assume this page is browsed by user.
HistoryAddPageArgs request1(url, base::Time::Now(), nullptr, 0, GURL(),
- history::RedirectList(),
+ RedirectList(),
ui::PAGE_TRANSITION_KEYWORD_GENERATED, false,
- history::SOURCE_BROWSED, false, true, false);
+ SOURCE_BROWSED, false, true, false);
backend_->AddPage(request1);
// Assume this page is synced.
HistoryAddPageArgs request2(url, base::Time::Now(), nullptr, 0, GURL(),
- history::RedirectList(), ui::PAGE_TRANSITION_LINK,
- false, history::SOURCE_SYNCED, false, true,
- false);
+ RedirectList(), ui::PAGE_TRANSITION_LINK, false,
+ SOURCE_SYNCED, false, true, false);
backend_->AddPage(request2);
// Assume this page is browsed again.
HistoryAddPageArgs request3(url, base::Time::Now(), nullptr, 0, GURL(),
- history::RedirectList(),
- ui::PAGE_TRANSITION_TYPED, false,
- history::SOURCE_BROWSED, false, true, false);
+ RedirectList(), ui::PAGE_TRANSITION_TYPED, false,
+ SOURCE_BROWSED, false, true, false);
backend_->AddPage(request3);
// Three visits should be added with proper sources.
@@ -1530,7 +1543,7 @@ TEST_F(HistoryBackendTest, AddPageArgsSource) {
VisitSourceMap visit_sources;
ASSERT_TRUE(backend_->GetVisitsSource(visits, &visit_sources));
ASSERT_EQ(1U, visit_sources.size());
- EXPECT_EQ(history::SOURCE_SYNCED, visit_sources.begin()->second);
+ EXPECT_EQ(SOURCE_SYNCED, visit_sources.begin()->second);
}
TEST_F(HistoryBackendTest, AddContentModelAnnotations_NoEntryInVisitTable) {
@@ -1541,9 +1554,8 @@ TEST_F(HistoryBackendTest, AddContentModelAnnotations_NoEntryInVisitTable) {
int nav_entry_id = 1;
HistoryAddPageArgs request(url, base::Time::Now(), context_id, nav_entry_id,
- GURL(), history::RedirectList(),
- ui::PAGE_TRANSITION_TYPED, false,
- history::SOURCE_BROWSED, false, true, false);
+ GURL(), RedirectList(), ui::PAGE_TRANSITION_TYPED,
+ false, SOURCE_BROWSED, false, true, false);
backend_->AddPage(request);
VisitVector visits;
@@ -1576,9 +1588,8 @@ TEST_F(HistoryBackendTest, SetFlocAllowed) {
int nav_entry_id = 1;
HistoryAddPageArgs request(url, base::Time::Now(), context_id, nav_entry_id,
- GURL(), history::RedirectList(),
- ui::PAGE_TRANSITION_TYPED, false,
- history::SOURCE_BROWSED, false, true, false);
+ GURL(), RedirectList(), ui::PAGE_TRANSITION_TYPED,
+ false, SOURCE_BROWSED, false, true, false);
backend_->AddPage(request);
VisitVector visits;
@@ -1626,9 +1637,8 @@ TEST_F(HistoryBackendTest, AddContentModelAnnotations) {
int nav_entry_id = 1;
HistoryAddPageArgs request(url, base::Time::Now(), context_id, nav_entry_id,
- GURL(), history::RedirectList(),
- ui::PAGE_TRANSITION_TYPED, false,
- history::SOURCE_BROWSED, false, true, false);
+ GURL(), RedirectList(), ui::PAGE_TRANSITION_TYPED,
+ false, SOURCE_BROWSED, false, true, false);
backend_->AddPage(request);
VisitVector visits;
@@ -1691,9 +1701,8 @@ TEST_F(HistoryBackendTest, MixedContentAnnotationsRequestTypes) {
int nav_entry_id = 1;
HistoryAddPageArgs request(url, base::Time::Now(), context_id, nav_entry_id,
- GURL(), history::RedirectList(),
- ui::PAGE_TRANSITION_TYPED, false,
- history::SOURCE_BROWSED, false, true, false);
+ GURL(), RedirectList(), ui::PAGE_TRANSITION_TYPED,
+ false, SOURCE_BROWSED, false, true, false);
backend_->AddPage(request);
VisitVector visits;
@@ -1750,27 +1759,23 @@ TEST_F(HistoryBackendTest, AddVisitsSource) {
GURL url1("http://www.cnn.com");
std::vector<VisitInfo> visits1, visits2;
- visits1.push_back(VisitInfo(
- base::Time::Now() - base::TimeDelta::FromDays(5),
- ui::PAGE_TRANSITION_LINK));
- visits1.push_back(VisitInfo(
- base::Time::Now() - base::TimeDelta::FromDays(1),
- ui::PAGE_TRANSITION_LINK));
- visits1.push_back(VisitInfo(
- base::Time::Now(), ui::PAGE_TRANSITION_LINK));
+ visits1.emplace_back(base::Time::Now() - base::TimeDelta::FromDays(5),
+ ui::PAGE_TRANSITION_LINK);
+ visits1.emplace_back(base::Time::Now() - base::TimeDelta::FromDays(1),
+ ui::PAGE_TRANSITION_LINK);
+ visits1.emplace_back(base::Time::Now(), ui::PAGE_TRANSITION_LINK);
GURL url2("http://www.example.com");
- visits2.push_back(VisitInfo(
- base::Time::Now() - base::TimeDelta::FromDays(10),
- ui::PAGE_TRANSITION_LINK));
- visits2.push_back(VisitInfo(base::Time::Now(), ui::PAGE_TRANSITION_LINK));
+ visits2.emplace_back(base::Time::Now() - base::TimeDelta::FromDays(10),
+ ui::PAGE_TRANSITION_LINK);
+ visits2.emplace_back(base::Time::Now(), ui::PAGE_TRANSITION_LINK);
// Clear all history.
backend_->DeleteAllHistory();
// Add the visits.
- backend_->AddVisits(url1, visits1, history::SOURCE_IE_IMPORTED);
- backend_->AddVisits(url2, visits2, history::SOURCE_SYNCED);
+ backend_->AddVisits(url1, visits1, SOURCE_IE_IMPORTED);
+ backend_->AddVisits(url2, visits2, SOURCE_SYNCED);
// Verify the visits were added with their sources.
VisitVector visits;
@@ -1782,14 +1787,14 @@ TEST_F(HistoryBackendTest, AddVisitsSource) {
ASSERT_TRUE(backend_->GetVisitsSource(visits, &visit_sources));
ASSERT_EQ(3U, visit_sources.size());
for (int i = 0; i < 3; i++)
- EXPECT_EQ(history::SOURCE_IE_IMPORTED, visit_sources[visits[i].visit_id]);
+ EXPECT_EQ(SOURCE_IE_IMPORTED, visit_sources[visits[i].visit_id]);
id = backend_->db()->GetRowForURL(url2, &row);
ASSERT_TRUE(backend_->db()->GetVisitsForURL(id, &visits));
ASSERT_EQ(2U, visits.size());
ASSERT_TRUE(backend_->GetVisitsSource(visits, &visit_sources));
ASSERT_EQ(2U, visit_sources.size());
for (int i = 0; i < 2; i++)
- EXPECT_EQ(history::SOURCE_SYNCED, visit_sources[visits[i].visit_id]);
+ EXPECT_EQ(SOURCE_SYNCED, visit_sources[visits[i].visit_id]);
}
TEST_F(HistoryBackendTest, GetMostRecentVisits) {
@@ -1797,20 +1802,17 @@ TEST_F(HistoryBackendTest, GetMostRecentVisits) {
GURL url1("http://www.cnn.com");
std::vector<VisitInfo> visits1;
- visits1.push_back(VisitInfo(
- base::Time::Now() - base::TimeDelta::FromDays(5),
- ui::PAGE_TRANSITION_LINK));
- visits1.push_back(VisitInfo(
- base::Time::Now() - base::TimeDelta::FromDays(1),
- ui::PAGE_TRANSITION_LINK));
- visits1.push_back(VisitInfo(
- base::Time::Now(), ui::PAGE_TRANSITION_LINK));
+ visits1.emplace_back(base::Time::Now() - base::TimeDelta::FromDays(5),
+ ui::PAGE_TRANSITION_LINK);
+ visits1.emplace_back(base::Time::Now() - base::TimeDelta::FromDays(1),
+ ui::PAGE_TRANSITION_LINK);
+ visits1.emplace_back(base::Time::Now(), ui::PAGE_TRANSITION_LINK);
// Clear all history.
backend_->DeleteAllHistory();
// Add the visits.
- backend_->AddVisits(url1, visits1, history::SOURCE_IE_IMPORTED);
+ backend_->AddVisits(url1, visits1, SOURCE_IE_IMPORTED);
// Verify the visits were added with their sources.
VisitVector visits;
@@ -1843,7 +1845,7 @@ TEST_F(HistoryBackendTest, RemoveVisitsTransitions) {
visits_to_add.push_back(link_visit);
// Add the visits.
- backend_->AddVisits(url1, visits_to_add, history::SOURCE_SYNCED);
+ backend_->AddVisits(url1, visits_to_add, SOURCE_SYNCED);
// Verify that the various counts are what we expect.
VisitVector visits;
@@ -1881,24 +1883,21 @@ TEST_F(HistoryBackendTest, RemoveVisitsSource) {
GURL url1("http://www.cnn.com");
std::vector<VisitInfo> visits1, visits2;
- visits1.push_back(VisitInfo(
- base::Time::Now() - base::TimeDelta::FromDays(5),
- ui::PAGE_TRANSITION_LINK));
- visits1.push_back(VisitInfo(base::Time::Now(),
- ui::PAGE_TRANSITION_LINK));
+ visits1.emplace_back(base::Time::Now() - base::TimeDelta::FromDays(5),
+ ui::PAGE_TRANSITION_LINK);
+ visits1.emplace_back(base::Time::Now(), ui::PAGE_TRANSITION_LINK);
GURL url2("http://www.example.com");
- visits2.push_back(VisitInfo(
- base::Time::Now() - base::TimeDelta::FromDays(10),
- ui::PAGE_TRANSITION_LINK));
- visits2.push_back(VisitInfo(base::Time::Now(), ui::PAGE_TRANSITION_LINK));
+ visits2.emplace_back(base::Time::Now() - base::TimeDelta::FromDays(10),
+ ui::PAGE_TRANSITION_LINK);
+ visits2.emplace_back(base::Time::Now(), ui::PAGE_TRANSITION_LINK);
// Clear all history.
backend_->DeleteAllHistory();
// Add the visits.
- backend_->AddVisits(url1, visits1, history::SOURCE_IE_IMPORTED);
- backend_->AddVisits(url2, visits2, history::SOURCE_SYNCED);
+ backend_->AddVisits(url1, visits1, SOURCE_IE_IMPORTED);
+ backend_->AddVisits(url2, visits2, SOURCE_SYNCED);
// Verify the visits of url1 were added.
VisitVector visits;
@@ -1919,7 +1918,7 @@ TEST_F(HistoryBackendTest, RemoveVisitsSource) {
ASSERT_TRUE(backend_->GetVisitsSource(visits, &visit_sources));
ASSERT_EQ(2U, visit_sources.size());
for (int i = 0; i < 2; i++)
- EXPECT_EQ(history::SOURCE_SYNCED, visit_sources[visits[i].visit_id]);
+ EXPECT_EQ(SOURCE_SYNCED, visit_sources[visits[i].visit_id]);
}
// Test for migration of adding visit_source table.
@@ -1940,7 +1939,7 @@ TEST_F(HistoryBackendTest, MigrationVisitSource) {
base::FilePath new_history_file = new_history_path.Append(kHistoryFilename);
ASSERT_TRUE(base::CopyFile(old_history_path, new_history_file));
- backend_ = base::MakeRefCounted<HistoryBackend>(
+ backend_ = base::MakeRefCounted<TestHistoryBackend>(
std::make_unique<HistoryBackendTestDelegate>(this),
history_client_.CreateBackendClient(),
base::ThreadTaskRunnerHandle::Get());
@@ -1967,7 +1966,7 @@ TEST_F(HistoryBackendTest, MigrationVisitSource) {
EXPECT_FALSE(s.Step());
}
-// Test that |recent_redirects_| stores the full redirect chain in case of
+// Test that `recent_redirects_` stores the full redirect chain in case of
// client redirects. In this case, a server-side redirect is followed by a
// client-side one.
TEST_F(HistoryBackendTest, RecentRedirectsForClientRedirects) {
@@ -1980,8 +1979,7 @@ TEST_F(HistoryBackendTest, RecentRedirectsForClientRedirects) {
HistoryAddPageArgs request(
client_redirect_url, base::Time::Now(), nullptr, 0, GURL(),
/*redirects=*/{server_redirect_url, client_redirect_url},
- ui::PAGE_TRANSITION_TYPED, false, history::SOURCE_BROWSED, false, true,
- false);
+ ui::PAGE_TRANSITION_TYPED, false, SOURCE_BROWSED, false, true, false);
backend_->AddPage(request);
// Client redirect to page C (non-user initiated).
@@ -2102,8 +2100,8 @@ TEST_F(HistoryBackendTest, FaviconChangedNotificationIconMappingChanged) {
backend_->SetFavicons({page_url1}, IconType::kFavicon, icon_url1, bitmaps);
backend_->SetFavicons({page_url2}, IconType::kFavicon, icon_url2, bitmaps);
- // Map |page_url3| to |icon_url1| so that the test does not delete the
- // favicon at |icon_url1|.
+ // Map `page_url3` to `icon_url1` so that the test does not delete the
+ // favicon at `icon_url1`.
std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results =
backend_->UpdateFaviconMappingsAndFetch({page_url3}, icon_url1,
IconType::kFavicon,
@@ -2205,8 +2203,8 @@ TEST_F(HistoryBackendTest,
backend_->SetFavicons({page_url1}, IconType::kFavicon, icon_url1, bitmaps);
backend_->SetFavicons({page_url2}, IconType::kFavicon, icon_url2, bitmaps);
- // Map |page_url3| to |icon_url1| so that the test does not delete the
- // favicon at |icon_url1|.
+ // Map `page_url3` to `icon_url1` so that the test does not delete the
+ // favicon at `icon_url1`.
std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results =
backend_->UpdateFaviconMappingsAndFetch({page_url3}, icon_url1,
IconType::kFavicon,
@@ -2263,17 +2261,17 @@ TEST_F(HistoryBackendTest, FaviconChangedNotificationsMergeCopy) {
new base::RefCountedBytes(png_bytes2), kLargeSize);
ClearBroadcastedNotifications();
- // Calling MergeFavicon() with |page_url2|, |icon_url1|, |png_bytes1| and
- // |kSmallSize| should cause the large favicon bitmap from |icon_url2| to
- // be copied to |icon_url1|.
+ // Calling MergeFavicon() with `page_url2`, `icon_url1`, `png_bytes1` and
+ // `kSmallSize` should cause the large favicon bitmap from `icon_url2` to
+ // be copied to `icon_url1`.
backend_->MergeFavicon(page_url2, icon_url1, IconType::kFavicon,
new base::RefCountedBytes(png_bytes1), kSmallSize);
ASSERT_EQ(1u, favicon_changed_notifications_page_urls().size());
EXPECT_EQ(page_url2, favicon_changed_notifications_page_urls()[0]);
- // A favicon bitmap was copied to the favicon at |icon_url1|. A notification
- // that the favicon at |icon_url1| has changed should be sent.
+ // A favicon bitmap was copied to the favicon at `icon_url1`. A notification
+ // that the favicon at `icon_url1` has changed should be sent.
ASSERT_EQ(1u, favicon_changed_notifications_icon_urls().size());
EXPECT_EQ(icon_url1, favicon_changed_notifications_icon_urls()[0]);
}
@@ -2326,7 +2324,7 @@ TEST_F(HistoryBackendTest, CloneFaviconMappingsForPages) {
// Setup
{
- // A mapping exists for |landing_page_url1|.
+ // A mapping exists for `landing_page_url1`.
std::vector<favicon_base::FaviconRawBitmapData> favicon_bitmap_data;
backend_->SetFavicons({landing_page_url1}, IconType::kFavicon, icon_url,
{CreateBitmap(SK_ColorBLUE, kSmallEdgeSize)});
@@ -2375,23 +2373,23 @@ TEST_F(HistoryBackendTest, GetCountsAndLastVisitForOrigins) {
base::Time last_week = now - base::TimeDelta::FromDays(7);
backend_->AddPageVisit(GURL("http://cnn.com/intl"), yesterday, 0,
- ui::PAGE_TRANSITION_LINK, false,
- history::SOURCE_BROWSED, false, false);
+ ui::PAGE_TRANSITION_LINK, false, SOURCE_BROWSED, false,
+ false);
backend_->AddPageVisit(GURL("http://cnn.com/us"), last_week, 0,
- ui::PAGE_TRANSITION_LINK, false,
- history::SOURCE_BROWSED, false, false);
+ ui::PAGE_TRANSITION_LINK, false, SOURCE_BROWSED, false,
+ false);
backend_->AddPageVisit(GURL("http://cnn.com/ny"), now, 0,
- ui::PAGE_TRANSITION_LINK, false,
- history::SOURCE_BROWSED, false, false);
+ ui::PAGE_TRANSITION_LINK, false, SOURCE_BROWSED, false,
+ false);
backend_->AddPageVisit(GURL("https://cnn.com/intl"), yesterday, 0,
- ui::PAGE_TRANSITION_LINK, false,
- history::SOURCE_BROWSED, false, false);
+ ui::PAGE_TRANSITION_LINK, false, SOURCE_BROWSED, false,
+ false);
backend_->AddPageVisit(GURL("http://cnn.com:8080/path"), yesterday, 0,
- ui::PAGE_TRANSITION_LINK, false,
- history::SOURCE_BROWSED, false, false);
+ ui::PAGE_TRANSITION_LINK, false, SOURCE_BROWSED, false,
+ false);
backend_->AddPageVisit(GURL("http://dogtopia.com/pups?q=poods"), now, 0,
- ui::PAGE_TRANSITION_LINK, false,
- history::SOURCE_BROWSED, false, false);
+ ui::PAGE_TRANSITION_LINK, false, SOURCE_BROWSED, false,
+ false);
std::set<GURL> origins;
origins.insert(GURL("http://cnn.com/"));
@@ -2404,8 +2402,8 @@ TEST_F(HistoryBackendTest, GetCountsAndLastVisitForOrigins) {
origins.insert(GURL("https://cnn.com/"));
origins.insert(GURL("http://notpresent.com/"));
backend_->AddPageVisit(GURL("http://cnn.com/"), tomorrow, 0,
- ui::PAGE_TRANSITION_LINK, false,
- history::SOURCE_BROWSED, false, false);
+ ui::PAGE_TRANSITION_LINK, false, SOURCE_BROWSED, false,
+ false);
EXPECT_THAT(
backend_->GetCountsAndLastVisitForOrigins(origins),
@@ -2428,19 +2426,18 @@ TEST_F(HistoryBackendTest, UpdateVisitDuration) {
std::vector<VisitInfo> visit_info1, visit_info2;
base::Time start_ts = base::Time::Now() - base::TimeDelta::FromDays(5);
base::Time end_ts = start_ts + base::TimeDelta::FromDays(2);
- visit_info1.push_back(VisitInfo(start_ts, ui::PAGE_TRANSITION_LINK));
+ visit_info1.emplace_back(start_ts, ui::PAGE_TRANSITION_LINK);
GURL url2("http://www.example.com");
- visit_info2.push_back(
- VisitInfo(base::Time::Now() - base::TimeDelta::FromDays(10),
- ui::PAGE_TRANSITION_LINK));
+ visit_info2.emplace_back(base::Time::Now() - base::TimeDelta::FromDays(10),
+ ui::PAGE_TRANSITION_LINK);
// Clear all history.
backend_->DeleteAllHistory();
// Add the visits.
- backend_->AddVisits(url1, visit_info1, history::SOURCE_BROWSED);
- backend_->AddVisits(url2, visit_info2, history::SOURCE_BROWSED);
+ backend_->AddVisits(url1, visit_info1, SOURCE_BROWSED);
+ backend_->AddVisits(url2, visit_info2, SOURCE_BROWSED);
// Verify the entries for both visits were added in visit_details.
VisitVector visits1, visits2;
@@ -2487,7 +2484,7 @@ TEST_F(HistoryBackendTest, MigrationVisitDuration) {
base::FilePath new_history_file = new_history_path.Append(kHistoryFilename);
ASSERT_TRUE(base::CopyFile(old_history, new_history_file));
- backend_ = base::MakeRefCounted<HistoryBackend>(
+ backend_ = base::MakeRefCounted<TestHistoryBackend>(
std::make_unique<HistoryBackendTestDelegate>(this),
history_client_.CreateBackendClient(),
base::ThreadTaskRunnerHandle::Get());
@@ -2540,24 +2537,22 @@ TEST_F(HistoryBackendTest, ExpireHistoryForTimes) {
HistoryAddPageArgs args[10];
for (size_t i = 0; i < base::size(args); ++i) {
- args[i].url = GURL("http://example" +
- std::string((i % 2 == 0 ? ".com" : ".net")));
+ args[i].url =
+ GURL("http://example" + std::string((i % 2 == 0 ? ".com" : ".net")));
args[i].time = base::Time::FromInternalValue(i);
backend_->AddPage(args[i]);
}
EXPECT_EQ(base::Time(), backend_->GetFirstRecordedTimeForTest());
URLRow row;
- for (size_t i = 0; i < base::size(args); ++i) {
- EXPECT_TRUE(backend_->GetURL(args[i].url, &row));
- }
+ for (auto& arg : args)
+ EXPECT_TRUE(backend_->GetURL(arg.url, &row));
std::set<base::Time> times;
times.insert(args[5].time);
// Invalid time (outside range), should have no effect.
times.insert(base::Time::FromInternalValue(10));
- backend_->ExpireHistoryForTimes(times,
- base::Time::FromInternalValue(2),
+ backend_->ExpireHistoryForTimes(times, base::Time::FromInternalValue(2),
base::Time::FromInternalValue(8));
EXPECT_EQ(base::Time::FromInternalValue(0),
@@ -2882,7 +2877,7 @@ TEST_F(HistoryBackendTest, ClientRedirectScoring) {
// Initial typed page visit, with no server redirects.
HistoryAddPageArgs request(typed_url, base::Time::Now(), nullptr, 0, GURL(),
{}, ui::PAGE_TRANSITION_TYPED, false,
- history::SOURCE_BROWSED, false, true, false);
+ SOURCE_BROWSED, false, true, false);
backend_->AddPage(request);
// Client redirect to HTTPS (non-user initiated).
@@ -2900,8 +2895,8 @@ TEST_F(HistoryBackendTest, ClientRedirectScoring) {
// between them is the type of the notification sent out.
void InMemoryHistoryBackendTest::TestAddingAndChangingURLRows(
const SimulateNotificationCallback& callback) {
- const char kTestTypedURLAlternativeTitle[] = "Google Search Again";
- const char kTestNonTypedURLAlternativeTitle[] = "Google News Again";
+ const char16_t kTestTypedURLAlternativeTitle[] = u"Google Search Again";
+ const char16_t kTestNonTypedURLAlternativeTitle[] = u"Google News Again";
// Notify the in-memory database that a typed and non-typed URLRow (which were
// never before seen by the cache) have been modified.
@@ -2918,15 +2913,14 @@ void InMemoryHistoryBackendTest::TestAddingAndChangingURLRows(
EXPECT_EQ(row1.id(), cached_row1.id());
// Try changing attributes (other than typed_count) for existing URLRows.
- row1.set_title(base::UTF8ToUTF16(kTestTypedURLAlternativeTitle));
- row2.set_title(base::UTF8ToUTF16(kTestNonTypedURLAlternativeTitle));
+ row1.set_title(kTestTypedURLAlternativeTitle);
+ row2.set_title(kTestNonTypedURLAlternativeTitle);
callback.Run(&row1, &row2, nullptr);
// URLRows that are cached by the in-memory database should be updated.
EXPECT_NE(0, mem_backend_->db()->GetRowForURL(row1.url(), &cached_row1));
EXPECT_EQ(0, mem_backend_->db()->GetRowForURL(row2.url(), &cached_row2));
- EXPECT_EQ(base::UTF8ToUTF16(kTestTypedURLAlternativeTitle),
- cached_row1.title());
+ EXPECT_EQ(kTestTypedURLAlternativeTitle, cached_row1.title());
// Now decrease the typed count for the typed URLRow, and increase it for the
// previously non-typed URLRow.
@@ -2939,8 +2933,7 @@ void InMemoryHistoryBackendTest::TestAddingAndChangingURLRows(
EXPECT_EQ(0, mem_backend_->db()->GetRowForURL(row1.url(), &cached_row1));
EXPECT_NE(0, mem_backend_->db()->GetRowForURL(row2.url(), &cached_row2));
EXPECT_EQ(row2.id(), cached_row2.id());
- EXPECT_EQ(base::UTF8ToUTF16(kTestNonTypedURLAlternativeTitle),
- cached_row2.title());
+ EXPECT_EQ(kTestNonTypedURLAlternativeTitle, cached_row2.title());
}
TEST_F(InMemoryHistoryBackendTest, OnURLsModified) {
@@ -2981,7 +2974,7 @@ TEST_F(InMemoryHistoryBackendTest, OnURLsDeletedEnMasse) {
SimulateNotificationURLsModified(mem_backend_.get(), &row1, &row2, &row3);
// Now notify the in-memory database that all history has been deleted.
- mem_backend_->OnURLsDeleted(nullptr, history::DeletionInfo::ForAllHistory());
+ mem_backend_->OnURLsDeleted(nullptr, DeletionInfo::ForAllHistory());
// Expect that everything goes away.
EXPECT_EQ(0, mem_backend_->db()->GetRowForURL(row1.url(), nullptr));
@@ -2999,7 +2992,7 @@ void InMemoryHistoryBackendTest::PopulateTestURLsAndSearchTerms(
URLRows rows;
rows.push_back(*row1);
rows.push_back(*row2);
- backend_->AddPagesWithDetails(rows, history::SOURCE_BROWSED);
+ backend_->AddPagesWithDetails(rows, SOURCE_BROWSED);
backend_->db()->GetRowForURL(row1->url(), row1); // Get effective IDs from
backend_->db()->GetRowForURL(row2->url(), row2); // the database.
@@ -3013,8 +3006,8 @@ void InMemoryHistoryBackendTest::PopulateTestURLsAndSearchTerms(
TEST_F(InMemoryHistoryBackendTest, SetKeywordSearchTerms) {
URLRow row1(CreateTestTypedURL());
URLRow row2(CreateTestNonTypedURL());
- std::u16string term1(base::UTF8ToUTF16(kTestSearchTerm1));
- std::u16string term2(base::UTF8ToUTF16(kTestSearchTerm2));
+ std::u16string term1(kTestSearchTerm1);
+ std::u16string term2(kTestSearchTerm2);
PopulateTestURLsAndSearchTerms(&row1, &row2, term1, term2);
// Both URLs now have associated search terms, so the in-memory database
@@ -3036,8 +3029,8 @@ TEST_F(InMemoryHistoryBackendTest, SetKeywordSearchTerms) {
TEST_F(InMemoryHistoryBackendTest, DeleteKeywordSearchTerms) {
URLRow row1(CreateTestTypedURL());
URLRow row2(CreateTestNonTypedURL());
- std::u16string term1(base::UTF8ToUTF16(kTestSearchTerm1));
- std::u16string term2(base::UTF8ToUTF16(kTestSearchTerm2));
+ std::u16string term1(kTestSearchTerm1);
+ std::u16string term2(kTestSearchTerm2);
PopulateTestURLsAndSearchTerms(&row1, &row2, term1, term2);
// Delete both search terms. This should be reflected in the in-memory DB.
@@ -3061,8 +3054,8 @@ TEST_F(InMemoryHistoryBackendTest, DeleteKeywordSearchTerms) {
TEST_F(InMemoryHistoryBackendTest, DeleteAllSearchTermsForKeyword) {
URLRow row1(CreateTestTypedURL());
URLRow row2(CreateTestNonTypedURL());
- std::u16string term1(base::UTF8ToUTF16(kTestSearchTerm1));
- std::u16string term2(base::UTF8ToUTF16(kTestSearchTerm2));
+ std::u16string term1(kTestSearchTerm1);
+ std::u16string term2(kTestSearchTerm2);
PopulateTestURLsAndSearchTerms(&row1, &row2, term1, term2);
// Delete all corresponding search terms from the in-memory database.
@@ -3086,8 +3079,8 @@ TEST_F(InMemoryHistoryBackendTest, DeleteAllSearchTermsForKeyword) {
TEST_F(InMemoryHistoryBackendTest, OnURLsDeletedWithSearchTerms) {
URLRow row1(CreateTestTypedURL());
URLRow row2(CreateTestNonTypedURL());
- std::u16string term1(base::UTF8ToUTF16(kTestSearchTerm1));
- std::u16string term2(base::UTF8ToUTF16(kTestSearchTerm2));
+ std::u16string term1(kTestSearchTerm1);
+ std::u16string term2(kTestSearchTerm2);
PopulateTestURLsAndSearchTerms(&row1, &row2, term1, term2);
// Notify the in-memory database that the second typed URL has been deleted.
@@ -3162,4 +3155,92 @@ TEST(FormatUrlForRedirectComparisonTest, TestUrlFormatting) {
EXPECT_EQ(u"www.baz.com/", FormatUrlForRedirectComparison(url3));
}
+TEST_F(HistoryBackendTest, AnnotatedVisits) {
+ auto last_visit_time = base::Time::Now();
+ auto add_url_and_visit = [&](std::string url) {
+ // Each it should have a unique `visit_time` to avoid deduping visits to the
+ // same URL. The exact times don't matter, but we use increasing values to
+ // making the test cases easy to reason about.
+ last_visit_time += base::TimeDelta::FromMilliseconds(1);
+ return backend_->AddPageVisit(GURL(url), last_visit_time, 0,
+ ui::PageTransition::PAGE_TRANSITION_FIRST,
+ false, SOURCE_BROWSED, false, false);
+ };
+ auto delete_url = [&](URLID id) { backend_->db_->DeleteURLRow(id); };
+ auto delete_visit = [&](VisitID id) {
+ VisitRow row;
+ backend_->db_->GetRowForVisit(id, &row);
+ backend_->db_->DeleteVisit(row);
+ };
+
+ // Happy path; annotated visits with associated URL & visits.
+ ASSERT_EQ(add_url_and_visit("http://1.com/"),
+ (std::pair<URLID, VisitID>{1, 1}));
+ ASSERT_EQ(add_url_and_visit("http://2.com/"),
+ (std::pair<URLID, VisitID>{2, 2}));
+ ASSERT_EQ(add_url_and_visit("http://1.com/"),
+ (std::pair<URLID, VisitID>{1, 3}));
+ backend_->AddContextAnnotationsForVisit(1, {true});
+ backend_->AddContextAnnotationsForVisit(3, {false});
+ backend_->AddContextAnnotationsForVisit(2, {true});
+ EXPECT_EQ(backend_->db_->GetAnnotatedVisits(10).size(), 3u);
+
+ // Annotated visits should have a visit IDs.
+ EXPECT_DCHECK_DEATH(backend_->AddContextAnnotationsForVisit(0, {true}));
+ EXPECT_EQ(backend_->db_->GetAnnotatedVisits(10).size(), 3u);
+
+ // Annotated visits without an associated visit should not be added.
+ backend_->AddContextAnnotationsForVisit(4, {true});
+ EXPECT_EQ(add_url_and_visit("http://3.com/"),
+ (std::pair<URLID, VisitID>{3, 4}));
+ EXPECT_EQ(backend_->db_->GetAnnotatedVisits(10).size(), 3u);
+
+ // Annotated visits associated with a removed visit should not be added.
+ EXPECT_EQ(add_url_and_visit("http://4.com/"),
+ (std::pair<URLID, VisitID>{4, 5}));
+ delete_visit(5);
+ backend_->AddContextAnnotationsForVisit(5, {true});
+ EXPECT_EQ(backend_->db_->GetAnnotatedVisits(10).size(), 3u);
+
+ // Verify only the correct annotated visits are retrieved ordered recent
+ // visits first.
+ auto annotated_visits = backend_->GetAnnotatedVisits(10);
+ ASSERT_EQ(annotated_visits.size(), 3u);
+ EXPECT_EQ(annotated_visits[0].url_row.id(), 1);
+ EXPECT_EQ(annotated_visits[0].url_row.url(), "http://1.com/");
+ EXPECT_EQ(annotated_visits[0].visit_row.visit_id, 3);
+ EXPECT_EQ(annotated_visits[0].visit_row.url_id, 1);
+ EXPECT_EQ(annotated_visits[0].context_annotations.omnibox_url_copied, false);
+ EXPECT_EQ(annotated_visits[1].url_row.id(), 2);
+ EXPECT_EQ(annotated_visits[1].url_row.url(), "http://2.com/");
+ EXPECT_EQ(annotated_visits[1].visit_row.visit_id, 2);
+ EXPECT_EQ(annotated_visits[1].visit_row.url_id, 2);
+ EXPECT_EQ(annotated_visits[1].context_annotations.omnibox_url_copied, true);
+ EXPECT_EQ(annotated_visits[2].url_row.id(), 1);
+ EXPECT_EQ(annotated_visits[2].url_row.url(), "http://1.com/");
+ EXPECT_EQ(annotated_visits[2].visit_row.visit_id, 1);
+ EXPECT_EQ(annotated_visits[2].visit_row.url_id, 1);
+ EXPECT_EQ(annotated_visits[2].context_annotations.omnibox_url_copied, true);
+
+ // Annotated visits should be removed if their associated URL or visit is
+ // removed.
+ delete_url(2);
+ delete_visit(3);
+ // `db_->GetAnnotatedVisits()` should only return annotated visits with
+ // associated visits, but doesn't check for associated URLs.
+ EXPECT_EQ(backend_->db_->GetAnnotatedVisits(10).size(), 2u);
+ // `backend_->GetAnnotatedVisits()` should check for both associated URL and
+ // visit.
+ annotated_visits = backend_->GetAnnotatedVisits(10);
+ ASSERT_EQ(annotated_visits.size(), 1u);
+ EXPECT_EQ(annotated_visits[0].url_row.id(), 1);
+ EXPECT_EQ(annotated_visits[0].url_row.url(), "http://1.com/");
+ EXPECT_EQ(annotated_visits[0].visit_row.visit_id, 1);
+ EXPECT_EQ(annotated_visits[0].visit_row.url_id, 1);
+ EXPECT_EQ(annotated_visits[0].context_annotations.omnibox_url_copied, true);
+ // `backend_->GetAnnotatedVisits()` should not delete visits without
+ // associated URLs and visits. Let ExpireHistoryBackend do that.
+ EXPECT_EQ(backend_->db_->GetAnnotatedVisits(10).size(), 2u);
+}
+
} // namespace history
diff --git a/chromium/components/history/core/browser/history_database.cc b/chromium/components/history/core/browser/history_database.cc
index d68da4eb88a..be495e98b01 100644
--- a/chromium/components/history/core/browser/history_database.cc
+++ b/chromium/components/history/core/browser/history_database.cc
@@ -12,8 +12,8 @@
#include <utility>
#include <vector>
-#include "base/command_line.h"
#include "base/files/file_util.h"
+#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
@@ -21,7 +21,6 @@
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "components/history/core/browser/url_utils.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
@@ -38,7 +37,7 @@ namespace {
// Current version number. We write databases at the "current" version number,
// but any previous version that can read the "compatible" one can make do with
// our database without *too* many bad effects.
-const int kCurrentVersionNumber = 44;
+const int kCurrentVersionNumber = 45;
const int kCompatibleVersionNumber = 16;
const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold";
@@ -102,7 +101,7 @@ sql::InitStatus HistoryDatabase::Init(const base::FilePath& history_name) {
if (!db_.Open(history_name))
return LogInitFailure(InitStep::OPEN);
- // Wrap the rest of init in a tranaction. This will prevent the database from
+ // Wrap the rest of init in a transaction. This will prevent the database from
// getting corrupted if we crash in the middle of initialization or migration.
sql::Transaction committer(&db_);
if (!committer.Begin())
@@ -116,16 +115,13 @@ sql::InitStatus HistoryDatabase::Init(const base::FilePath& history_name) {
// Prime the cache.
db_.Preload();
- // Create the tables and indices.
- // NOTE: If you add something here, also add it to
- // RecreateAllButStarAndURLTables.
+ // Create the tables and indices. If you add something here, also add it to
+ // `RecreateAllTablesButURL()`.
if (!meta_table_.Init(&db_, GetCurrentVersion(), kCompatibleVersionNumber))
return LogInitFailure(InitStep::META_TABLE_INIT);
if (!CreateURLTable(false) || !InitVisitTable() ||
!InitKeywordSearchTermsTable() || !InitDownloadTable() ||
- !InitSegmentTables() || !InitSyncTable())
- return LogInitFailure(InitStep::CREATE_TABLES);
- if (!InitVisitAnnotationsTables())
+ !InitSegmentTables() || !InitSyncTable() || !InitVisitAnnotationsTables())
return LogInitFailure(InitStep::CREATE_TABLES);
CreateMainURLIndex();
@@ -645,6 +641,12 @@ sql::InitStatus HistoryDatabase::EnsureCurrentVersion() {
meta_table_.SetVersionNumber(cur_version);
}
+ if (cur_version == 44) {
+ MigrateReplaceClusterVisitsTable();
+ cur_version++;
+ meta_table_.SetVersionNumber(cur_version);
+ }
+
// ========================= ^^ new migration code goes here ^^
// ADDING NEW MIGRATION CODE
// =========================
diff --git a/chromium/components/history/core/browser/history_database.h b/chromium/components/history/core/browser/history_database.h
index 1d80042b6ec..868f56046d5 100644
--- a/chromium/components/history/core/browser/history_database.h
+++ b/chromium/components/history/core/browser/history_database.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_DATABASE_H_
#define COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_DATABASE_H_
-#include <stddef.h>
-
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -93,7 +91,7 @@ class HistoryDatabase : public DownloadDatabase,
int CountUniqueHostsVisitedLastMonth();
// Counts the number of unique domains (eLTD+1) visited within
- // [|begin_time|, |end_time|).
+ // [`begin_time`, `end_time`).
int CountUniqueDomainsVisited(base::Time begin_time, base::Time end_time);
// Call to set the mode on the database to exclusive. The default locking mode
@@ -172,7 +170,7 @@ class HistoryDatabase : public DownloadDatabase,
private:
#if defined(OS_ANDROID)
- // AndroidProviderBackend uses the |db_|.
+ // AndroidProviderBackend uses the `db_`.
friend class AndroidProviderBackend;
FRIEND_TEST_ALL_PREFIXES(AndroidURLsMigrationTest, MigrateToVersion22);
#endif
@@ -189,7 +187,7 @@ class HistoryDatabase : public DownloadDatabase,
// Makes sure the version is up to date, updating if necessary. If the
// database is too old to migrate, the user will be notified. Returns
- // sql::INIT_OK iff the DB is up to date and ready for use.
+ // sql::INIT_OK iff the DB is up to date and ready for use.
//
// This assumes it is called from the init function inside a transaction. It
// may commit the transaction and start a new one if migration requires it.
diff --git a/chromium/components/history/core/browser/history_querying_unittest.cc b/chromium/components/history/core/browser/history_querying_unittest.cc
index 8c75bf5c5c7..25f0063eb86 100644
--- a/chromium/components/history/core/browser/history_querying_unittest.cc
+++ b/chromium/components/history/core/browser/history_querying_unittest.cc
@@ -128,7 +128,7 @@ class HistoryQueryTest : public testing::Test {
options.end_time = results.back().visit_time();
}
- // Add a couple of entries with duplicate timestamps. Use |query_text| as
+ // Add a couple of entries with duplicate timestamps. Use `query_text` as
// the title of both entries so that they match a text query.
TestEntry duplicates[] = {
{ "http://www.google.com/x", query_text.c_str(), 1, },
@@ -266,7 +266,7 @@ TEST_F(HistoryQueryTest, ReachedBeginning) {
QueryHistory("some", options, &results);
EXPECT_FALSE(results.reached_beginning());
- // Try |begin_time| just later than the oldest visit.
+ // Try `begin_time` just later than the oldest visit.
options.begin_time =
test_entries[0].time + base::TimeDelta::FromMicroseconds(1);
QueryHistory(std::string(), options, &results);
@@ -274,14 +274,14 @@ TEST_F(HistoryQueryTest, ReachedBeginning) {
QueryHistory("some", options, &results);
EXPECT_FALSE(results.reached_beginning());
- // Try |begin_time| equal to the oldest visit.
+ // Try `begin_time` equal to the oldest visit.
options.begin_time = test_entries[0].time;
QueryHistory(std::string(), options, &results);
EXPECT_TRUE(results.reached_beginning());
QueryHistory("some", options, &results);
EXPECT_TRUE(results.reached_beginning());
- // Try |begin_time| just earlier than the oldest visit.
+ // Try `begin_time` just earlier than the oldest visit.
options.begin_time =
test_entries[0].time - base::TimeDelta::FromMicroseconds(1);
QueryHistory(std::string(), options, &results);
@@ -289,14 +289,14 @@ TEST_F(HistoryQueryTest, ReachedBeginning) {
QueryHistory("some", options, &results);
EXPECT_TRUE(results.reached_beginning());
- // Test with |max_count| specified.
+ // Test with `max_count` specified.
options.max_count = 1;
QueryHistory(std::string(), options, &results);
EXPECT_FALSE(results.reached_beginning());
QueryHistory("some", options, &results);
EXPECT_FALSE(results.reached_beginning());
- // Test with |max_count| greater than the number of results,
+ // Test with `max_count` greater than the number of results,
// and exactly equal to the number of results.
options.max_count = 100;
QueryHistory(std::string(), options, &results);
diff --git a/chromium/components/history/core/browser/history_service.cc b/chromium/components/history/core/browser/history_service.cc
index 6f113f1f32f..c3f16455a7d 100644
--- a/chromium/components/history/core/browser/history_service.cc
+++ b/chromium/components/history/core/browser/history_service.cc
@@ -17,13 +17,14 @@
#include "components/history/core/browser/history_service.h"
+#include <functional>
+
#include "base/callback.h"
-#include "base/callback_forward.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
-#include "base/feature_list.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_macros.h"
#include "base/sequence_checker.h"
@@ -49,7 +50,6 @@
#include "components/history/core/browser/visit_database.h"
#include "components/history/core/browser/visit_delegate.h"
#include "components/history/core/browser/web_history_service.h"
-#include "components/history/core/common/thumbnail_score.h"
#include "components/sync/model/proxy_model_type_controller_delegate.h"
#include "components/sync/model/sync_error_factory.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -265,6 +265,30 @@ void HistoryService::URLsNoLongerBookmarked(const std::set<GURL>& urls) {
history_backend_, urls));
}
+void HistoryService::AddContextAnnotationsForVisit(
+ VisitID visit_id,
+ const VisitContextAnnotations& visit_context_annotations) {
+ DCHECK(backend_task_runner_) << "History service being called after cleanup";
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ ScheduleTask(
+ PRIORITY_NORMAL,
+ base::BindOnce(&HistoryBackend::AddContextAnnotationsForVisit,
+ history_backend_, visit_id, visit_context_annotations));
+}
+
+base::CancelableTaskTracker::TaskId HistoryService::GetAnnotatedVisits(
+ int max_results,
+ GetAnnotatedVisitsCallback callback,
+ base::CancelableTaskTracker* tracker) const {
+ DCHECK(backend_task_runner_) << "History service being called after cleanup";
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return tracker->PostTaskAndReplyWithResult(
+ backend_task_runner_.get(), FROM_HERE,
+ base::BindOnce(&HistoryBackend::GetAnnotatedVisits, history_backend_,
+ max_results),
+ std::move(callback));
+}
+
void HistoryService::AddObserver(HistoryServiceObserver* observer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
observers_.AddObserver(observer);
@@ -985,7 +1009,7 @@ void HistoryService::Cleanup() {
std::move(history_backend_)));
}
- // Clear |backend_task_runner_| to make sure it's not used after Cleanup().
+ // Clear `backend_task_runner_` to make sure it's not used after Cleanup().
backend_task_runner_ = nullptr;
}
@@ -995,7 +1019,7 @@ bool HistoryService::Init(
TRACE_EVENT0("browser,startup", "HistoryService::Init");
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Unit tests can inject |backend_task_runner_| before this is called.
+ // Unit tests can inject `backend_task_runner_` before this is called.
if (!backend_task_runner_) {
backend_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::WithBaseSyncPrimitives(),
@@ -1166,7 +1190,7 @@ void HistoryService::DeleteLocalAndRemoteHistoryBetween(
// Attempt online deletion from the history server, but ignore the result.
// Deletion directives ensure that the results will eventually be deleted.
//
- // TODO(davidben): |callback| should not run until this operation completes
+ // TODO(davidben): `callback` should not run until this operation completes
// too.
net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
net::DefinePartialNetworkTrafficAnnotation(
diff --git a/chromium/components/history/core/browser/history_service.h b/chromium/components/history/core/browser/history_service.h
index c5588a35470..d3d8e518a4d 100644
--- a/chromium/components/history/core/browser/history_service.h
+++ b/chromium/components/history/core/browser/history_service.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_SERVICE_H_
#define COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_SERVICE_H_
-#include <stddef.h>
#include <stdint.h>
#include <memory>
@@ -20,13 +19,11 @@
#include "base/check.h"
#include "base/containers/flat_set.h"
#include "base/feature_list.h"
-#include "base/files/file_path.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "base/task/cancelable_task_tracker.h"
@@ -85,8 +82,8 @@ class WebHistoryService;
class HistoryService : public KeyedService {
public:
// Must call Init after construction. The empty constructor provided only for
- // unit tests. When using the full constructor, |history_client| may only be
- // null during testing, while |visit_delegate| may be null if the embedder use
+ // unit tests. When using the full constructor, `history_client` may only be
+ // null during testing, while `visit_delegate` may be null if the embedder use
// another way to track visited links.
HistoryService();
HistoryService(std::unique_ptr<HistoryClient> history_client,
@@ -142,7 +139,7 @@ class HistoryService : public KeyedService {
using GetCountsAndLastVisitForOriginsCallback =
base::OnceCallback<void(OriginCountAndLastVisitMap)>;
- // Gets the counts and most recent visit date of URLs that belong to |origins|
+ // Gets the counts and most recent visit date of URLs that belong to `origins`
// in the history database.
void GetCountsAndLastVisitForOriginsForTesting(
const std::set<GURL>& origins,
@@ -162,7 +159,7 @@ class HistoryService : public KeyedService {
// should be the unique ID of the current navigation entry in the given
// process.
//
- // |floc_allowed| indicates whether this URL visit can be included in FLoC
+ // `floc_allowed` indicates whether this URL visit can be included in FLoC
// computation. See VisitRow::floc_allowed for details.
// TODO(yaoxia): Remove the floc_allowed param from this API as well as from
// HistoryAddPageArgs. This bit will never be set at this point.
@@ -239,7 +236,7 @@ class HistoryService : public KeyedService {
// Queries the basic information about the URL in the history database. If
// the caller is interested in the visits (each time the URL is visited),
- // set |want_visits| to true. If these are not needed, the function will be
+ // set `want_visits` to true. If these are not needed, the function will be
// faster by setting this to false.
base::CancelableTaskTracker::TaskId QueryURL(
const GURL& url,
@@ -290,7 +287,7 @@ class HistoryService : public KeyedService {
base::CancelableTaskTracker* tracker);
// Requests the number of user-visible visits (i.e. no redirects or subframes)
- // to all urls on the same scheme/host/port as |url|. This is only valid for
+ // to all urls on the same scheme/host/port as `url`. This is only valid for
// HTTP and HTTPS URLs.
using GetVisibleVisitCountToHostCallback =
base::OnceCallback<void(VisibleVisitCountToHostResult)>;
@@ -300,8 +297,8 @@ class HistoryService : public KeyedService {
GetVisibleVisitCountToHostCallback callback,
base::CancelableTaskTracker* tracker);
- // Request the |result_count| most visited URLs and the chain of
- // redirects leading to each of these URLs. |days_back| is the
+ // Request the `result_count` most visited URLs and the chain of
+ // redirects leading to each of these URLs. `days_back` is the
// number of days of history to use. Used by TopSites.
using QueryMostVisitedURLsCallback =
base::OnceCallback<void(MostVisitedURLList)>;
@@ -315,7 +312,7 @@ class HistoryService : public KeyedService {
// Statistics ----------------------------------------------------------------
// Gets the number of URLs as seen in chrome://history within the time range
- // [|begin_time|, |end_time|). Each URL is counted only once per day. For
+ // [`begin_time`, `end_time`). Each URL is counted only once per day. For
// determination of the date, timestamps are converted to dates using local
// time.
using GetHistoryCountCallback = base::OnceCallback<void(HistoryCountResult)>;
@@ -330,10 +327,10 @@ class HistoryService : public KeyedService {
void CountUniqueHostsVisitedLastMonth(GetHistoryCountCallback callback,
base::CancelableTaskTracker* tracker);
- // For each of the continuous |number_of_days_to_report| midnights
- // immediately preceding |report_time| (inclusive), report (a subset of) the
+ // For each of the continuous `number_of_days_to_report` midnights
+ // immediately preceding `report_time` (inclusive), report (a subset of) the
// last 1-day, 7-day and 28-day domain visit counts ending at that midnight.
- // The subset of metric types to report is specified by |metric_type_bitmask|.
+ // The subset of metric types to report is specified by `metric_type_bitmask`.
void GetDomainDiversity(base::Time report_time,
int number_of_days_to_report,
DomainMetricBitmaskType metric_type_bitmask,
@@ -343,7 +340,7 @@ class HistoryService : public KeyedService {
using GetLastVisitCallback = base::OnceCallback<void(HistoryLastVisitResult)>;
// Gets the last time any webpage on the given host was visited within the
- // time range [|begin_time|, |end_time|). If the given host has not been
+ // time range [`begin_time`, `end_time`). If the given host has not been
// visited in the given time range, the callback will be called with a null
// base::Time.
base::CancelableTaskTracker::TaskId GetLastVisitToHost(
@@ -353,7 +350,7 @@ class HistoryService : public KeyedService {
GetLastVisitCallback callback,
base::CancelableTaskTracker* tracker);
- // Gets the last time |url| was visited before |end_time|. If the given URL
+ // Gets the last time `url` was visited before `end_time`. If the given URL
// has not been visited in the past, the callback will be called with a null
// base::Time.
base::CancelableTaskTracker::TaskId GetLastVisitToURL(
@@ -385,10 +382,10 @@ class HistoryService : public KeyedService {
// Removes all visits in the selected time range (including the
// start time), updating the URLs accordingly. This deletes any
// associated data. This function also deletes the associated
- // favicons, if they are no longer referenced. |callback| runs when
+ // favicons, if they are no longer referenced. `callback` runs when
// the expiration is complete. You may use null Time values to do an
// unbounded delete in either direction.
- // If |restrict_urls| is not empty, only visits to the URLs in this set are
+ // If `restrict_urls` is not empty, only visits to the URLs in this set are
// removed.
void ExpireHistoryBetween(const std::set<GURL>& restrict_urls,
base::Time begin_time,
@@ -399,7 +396,7 @@ class HistoryService : public KeyedService {
// Removes all visits to specified URLs in specific time ranges.
// This is the equivalent ExpireHistoryBetween() once for each element in the
- // vector. The fields of |ExpireHistoryArgs| map directly to the arguments of
+ // vector. The fields of `ExpireHistoryArgs` map directly to the arguments of
// of ExpireHistoryBetween().
void ExpireHistory(const std::vector<ExpireHistoryArgs>& expire_list,
base::OnceClosure callback,
@@ -412,7 +409,7 @@ class HistoryService : public KeyedService {
base::CancelableTaskTracker* tracker);
// Mark all favicons as out of date that have been modified at or after
- // |begin| and before |end|. Calls |callback| when done.
+ // `begin` and before `end`. Calls `callback` when done.
void SetFaviconsOutOfDateBetween(base::Time begin,
base::Time end,
base::OnceClosure callback,
@@ -431,7 +428,7 @@ class HistoryService : public KeyedService {
// visits and handles deletion of synced visits if appropriate.
void DeleteLocalAndRemoteUrl(WebHistoryService* web_history, const GURL& url);
- // Processes the given |delete_directive| and sends it to the
+ // Processes the given `delete_directive` and sends it to the
// SyncChangeProcessor (if it exists).
void ProcessLocalDeleteDirective(
const sync_pb::HistoryDeleteDirectiveSpecifics& delete_directive);
@@ -487,11 +484,11 @@ class HistoryService : public KeyedService {
// Deletes all search terms for the specified keyword.
void DeleteAllSearchTermsForKeyword(KeywordID keyword_id);
- // Deletes any search term corresponding to |url|.
+ // Deletes any search term corresponding to `url`.
void DeleteKeywordSearchTermForURL(const GURL& url);
- // Deletes all URL and search term entries matching the given |term| and
- // |keyword_id|.
+ // Deletes all URL and search term entries matching the given `term` and
+ // `keyword_id`.
void DeleteMatchingURLsForKeyword(KeywordID keyword_id,
const std::u16string& term);
@@ -500,6 +497,21 @@ class HistoryService : public KeyedService {
// Notification that a URL is no longer bookmarked.
void URLsNoLongerBookmarked(const std::set<GURL>& urls);
+ // Clusters ------------------------------------------------------------------
+
+ // Add a `AnnotatedVisitRow`.
+ void AddContextAnnotationsForVisit(
+ VisitID visit_id,
+ const VisitContextAnnotations& visit_context_annotations);
+
+ // Get all `AnnotatedVisitRow`s and map them to `AnnotatedVisit`s.
+ using GetAnnotatedVisitsCallback =
+ base::OnceCallback<void(std::vector<AnnotatedVisit>)>;
+ base::CancelableTaskTracker::TaskId GetAnnotatedVisits(
+ int max_results,
+ GetAnnotatedVisitsCallback callback,
+ base::CancelableTaskTracker* tracker) const;
+
// Observers -----------------------------------------------------------------
// Adds/Removes an Observer.
@@ -509,7 +521,7 @@ class HistoryService : public KeyedService {
// Generic Stuff -------------------------------------------------------------
// Schedules a HistoryDBTask for running on the history backend. See
- // HistoryDBTask for details on what this does. Takes ownership of |task|.
+ // HistoryDBTask for details on what this does. Takes ownership of `task`.
virtual base::CancelableTaskTracker::TaskId ScheduleDBTask(
const base::Location& from_here,
std::unique_ptr<HistoryDBTask> task,
@@ -532,7 +544,7 @@ class HistoryService : public KeyedService {
// Testing -------------------------------------------------------------------
- // Runs |flushed| after the backend has processed all other pre-existing
+ // Runs `flushed` after the backend has processed all other pre-existing
// tasks.
void FlushForTest(base::OnceClosure flushed);
@@ -555,8 +567,8 @@ class HistoryService : public KeyedService {
// instead.
//
// Note that this routine (and AddPageWithDetails()) always adds a single
- // visit using the |last_visit| timestamp, and a PageTransition type of LINK,
- // if |visit_source| != SYNCED.
+ // visit using the `last_visit` timestamp, and a PageTransition type of LINK,
+ // if `visit_source` != SYNCED.
void AddPageWithDetails(const GURL& url,
const std::u16string& title,
int visit_count,
@@ -579,7 +591,7 @@ class HistoryService : public KeyedService {
std::unique_ptr<syncer::ModelTypeControllerDelegate>
GetTypedURLSyncControllerDelegate();
- // Override |backend_task_runner_| for testing; needs to be called before
+ // Override `backend_task_runner_` for testing; needs to be called before
// Init.
void set_backend_task_runner_for_testing(
scoped_refptr<base::SequencedTaskRunner> task_runner) {
@@ -627,7 +639,7 @@ class HistoryService : public KeyedService {
// still in memory (pending requests may be holding a reference to us).
void Cleanup();
- // Low-level Init(). Same as the public version, but adds a |no_db| parameter
+ // Low-level Init(). Same as the public version, but adds a `no_db` parameter
// that is only set by unittests which causes the backend to not init its DB.
bool Init(bool no_db, const HistoryDatabaseParams& history_database_params);
@@ -644,23 +656,23 @@ class HistoryService : public KeyedService {
// Observers ----------------------------------------------------------------
// Notify all HistoryServiceObservers registered that user is visiting a URL.
- // The |row| ID will be set to the value that is currently in effect in the
- // main history database. |redirects| is the list of redirects leading up to
+ // The `row` ID will be set to the value that is currently in effect in the
+ // main history database. `redirects` is the list of redirects leading up to
// the URL. If we have a redirect chain A -> B -> C and user is visiting C,
- // then |redirects[0]=B| and |redirects[1]=A|. If there are no redirects,
- // |redirects| is an empty vector.
+ // then `redirects[0]=B` and `redirects[1]=A`. If there are no redirects,
+ // `redirects` is an empty vector.
void NotifyURLVisited(ui::PageTransition transition,
const URLRow& row,
const RedirectList& redirects,
base::Time visit_time);
// Notify all HistoryServiceObservers registered that URLs have been added or
- // modified. |changed_urls| contains the list of affects URLs.
+ // modified. `changed_urls` contains the list of affects URLs.
void NotifyURLsModified(const URLRows& changed_urls,
UrlsModifiedReason reason);
// Notify all HistoryServiceObservers registered that URLs have been deleted.
- // |deletion_info| describes the urls that have been removed from history.
+ // `deletion_info` describes the urls that have been removed from history.
void NotifyURLsDeleted(const DeletionInfo& deletion_info);
// Notify all HistoryServiceObservers registered that the
@@ -672,14 +684,14 @@ class HistoryService : public KeyedService {
void NotifyHistoryServiceBeingDeleted();
// Notify all HistoryServiceObservers registered that a keyword search term
- // has been updated. |row| contains the URL information for search |term|.
- // |keyword_id| associated with a URL and search term.
+ // has been updated. `row` contains the URL information for search `term`.
+ // `keyword_id` associated with a URL and search term.
void NotifyKeywordSearchTermUpdated(const URLRow& row,
KeywordID keyword_id,
const std::u16string& term);
// Notify all HistoryServiceObservers registered that keyword search term is
- // deleted. |url_id| is the id of the url row.
+ // deleted. `url_id` is the id of the url row.
void NotifyKeywordSearchTermDeleted(URLID url_id);
// Favicon -------------------------------------------------------------------
@@ -689,11 +701,11 @@ class HistoryService : public KeyedService {
// FaviconService.
// Used by FaviconService to get the favicon bitmaps from the history backend
- // whose edge sizes most closely match |desired_sizes| for |icon_type|. If
- // |desired_sizes| has a '0' entry, the largest favicon bitmap for
- // |icon_type| is returned. The returned FaviconBitmapResults will have at
- // most one result for each entry in |desired_sizes|. If a favicon bitmap is
- // determined to be the best candidate for multiple |desired_sizes| there will
+ // whose edge sizes most closely match `desired_sizes` for `icon_type`. If
+ // `desired_sizes` has a '0' entry, the largest favicon bitmap for
+ // `icon_type` is returned. The returned FaviconBitmapResults will have at
+ // most one result for each entry in `desired_sizes`. If a favicon bitmap is
+ // determined to be the best candidate for multiple `desired_sizes` there will
// be fewer results.
base::CancelableTaskTracker::TaskId GetFavicon(
const GURL& icon_url,
@@ -702,18 +714,18 @@ class HistoryService : public KeyedService {
favicon_base::FaviconResultsCallback callback,
base::CancelableTaskTracker* tracker);
- // Used by the FaviconService to get favicons mapped to |page_url| for
- // |icon_types| whose edge sizes most closely match |desired_sizes|. If
- // |desired_sizes| has a '0' entry, the largest favicon bitmap for
- // |icon_types| is returned. The returned FaviconBitmapResults will have at
- // most one result for each entry in |desired_sizes|. If a favicon bitmap is
- // determined to be the best candidate for multiple |desired_sizes| there
- // will be fewer results. If |fallback_to_host| is true, the host of
- // |page_url| will be used to search the favicon database if an exact match
+ // Used by the FaviconService to get favicons mapped to `page_url` for
+ // `icon_types` whose edge sizes most closely match `desired_sizes`. If
+ // `desired_sizes` has a '0' entry, the largest favicon bitmap for
+ // `icon_types` is returned. The returned FaviconBitmapResults will have at
+ // most one result for each entry in `desired_sizes`. If a favicon bitmap is
+ // determined to be the best candidate for multiple `desired_sizes` there
+ // will be fewer results. If `fallback_to_host` is true, the host of
+ // `page_url` will be used to search the favicon database if an exact match
// cannot be found. Generally, code showing an icon for a full/previously
- // visited URL should set |fallback_to_host|=false. Otherwise, if only a host
+ // visited URL should set `fallback_to_host`=false. Otherwise, if only a host
// is available, and any icon matching the host is permissible, use
- // |fallback_to_host|=true.
+ // `fallback_to_host`=true.
base::CancelableTaskTracker::TaskId GetFaviconsForURL(
const GURL& page_url,
const favicon_base::IconTypeSet& icon_types,
@@ -723,14 +735,14 @@ class HistoryService : public KeyedService {
base::CancelableTaskTracker* tracker);
// Used by FaviconService to find the first favicon bitmap whose width and
- // height are greater than that of |minimum_size_in_pixels|. This searches
- // for icons by IconType. Each element of |icon_types| is a bitmask of
+ // height are greater than that of `minimum_size_in_pixels`. This searches
+ // for icons by IconType. Each element of `icon_types` is a bitmask of
// IconTypes indicating the types to search for.
- // If the largest icon of |icon_types[0]| is not larger than
- // |minimum_size_in_pixel|, the next icon types of
- // |icon_types| will be searched and so on.
- // If no icon is larger than |minimum_size_in_pixel|, the largest one of all
- // icon types in |icon_types| is returned.
+ // If the largest icon of `icon_types[0]` is not larger than
+ // `minimum_size_in_pixel`, the next icon types of
+ // `icon_types` will be searched and so on.
+ // If no icon is larger than `minimum_size_in_pixel`, the largest one of all
+ // icon types in `icon_types` is returned.
// This feature is especially useful when some types of icon is preferred as
// long as its size is larger than a specific value.
base::CancelableTaskTracker::TaskId GetLargestFaviconForURL(
@@ -741,20 +753,20 @@ class HistoryService : public KeyedService {
base::CancelableTaskTracker* tracker);
// Used by the FaviconService to get the favicon bitmap which most closely
- // matches |desired_size| from the favicon with |favicon_id| from the history
- // backend. If |desired_size| is 0, the largest favicon bitmap for
- // |favicon_id| is returned.
+ // matches `desired_size` from the favicon with `favicon_id` from the history
+ // backend. If `desired_size` is 0, the largest favicon bitmap for
+ // `favicon_id` is returned.
base::CancelableTaskTracker::TaskId GetFaviconForID(
favicon_base::FaviconID favicon_id,
int desired_size,
favicon_base::FaviconResultsCallback callback,
base::CancelableTaskTracker* tracker);
- // Maps |page_urls| to the favicon at |icon_url| if there is an entry in the
- // database for |icon_url| and |icon_type|. This occurs when there is a
- // mapping from a different page URL to |icon_url|. The favicon bitmaps whose
- // edge sizes most closely match |desired_sizes| from the favicons which were
- // just mapped to |page_urls| are returned. If |desired_sizes| has a '0'
+ // Maps `page_urls` to the favicon at `icon_url` if there is an entry in the
+ // database for `icon_url` and `icon_type`. This occurs when there is a
+ // mapping from a different page URL to `icon_url`. The favicon bitmaps whose
+ // edge sizes most closely match `desired_sizes` from the favicons which were
+ // just mapped to `page_urls` are returned. If `desired_sizes` has a '0'
// entry, the largest favicon bitmap is returned.
base::CancelableTaskTracker::TaskId UpdateFaviconMappingsAndFetch(
const base::flat_set<GURL>& page_urls,
@@ -764,28 +776,28 @@ class HistoryService : public KeyedService {
favicon_base::FaviconResultsCallback callback,
base::CancelableTaskTracker* tracker);
- // Deletes favicon mappings for each URL in |page_urls| and their redirects.
+ // Deletes favicon mappings for each URL in `page_urls` and their redirects.
void DeleteFaviconMappings(const base::flat_set<GURL>& page_urls,
favicon_base::IconType icon_type);
- // Used by FaviconService to set a favicon for |page_url| and |icon_url| with
- // |pixel_size|.
+ // Used by FaviconService to set a favicon for `page_url` and `icon_url` with
+ // `pixel_size`.
// Example:
- // |page_url|: www.google.com
- // 2 favicons in history for |page_url|:
+ // `page_url`: www.google.com
+ // 2 favicons in history for `page_url`:
// www.google.com/a.ico 16x16
// www.google.com/b.ico 32x32
- // MergeFavicon(|page_url|, www.google.com/a.ico, ..., ..., 16x16)
+ // MergeFavicon(`page_url`, www.google.com/a.ico, ..., ..., 16x16)
//
// Merging occurs in the following manner:
- // 1) |page_url| is set to map to only to |icon_url|. In order to not lose
- // data, favicon bitmaps mapped to |page_url| but not to |icon_url| are
- // copied to the favicon at |icon_url|.
- // For the example above, |page_url| will only be mapped to a.ico.
+ // 1) `page_url` is set to map to only to `icon_url`. In order to not lose
+ // data, favicon bitmaps mapped to `page_url` but not to `icon_url` are
+ // copied to the favicon at `icon_url`.
+ // For the example above, `page_url` will only be mapped to a.ico.
// The 32x32 favicon bitmap at b.ico is copied to a.ico
- // 2) |bitmap_data| is added to the favicon at |icon_url|, overwriting any
- // favicon bitmaps of |pixel_size|.
- // For the example above, |bitmap_data| overwrites the 16x16 favicon
+ // 2) `bitmap_data` is added to the favicon at `icon_url`, overwriting any
+ // favicon bitmaps of `pixel_size`.
+ // For the example above, `bitmap_data` overwrites the 16x16 favicon
// bitmap for a.ico.
// TODO(pkotwicz): Remove once no longer required by sync.
void MergeFavicon(const GURL& page_url,
@@ -795,39 +807,39 @@ class HistoryService : public KeyedService {
const gfx::Size& pixel_size);
// Used by the FaviconService to replace the favicon bitmaps mapped to all
- // URLs in |page_urls| for |icon_type|.
- // Use MergeFavicon() if |bitmaps| is incomplete, and favicon bitmaps in the
+ // URLs in `page_urls` for `icon_type`.
+ // Use MergeFavicon() if `bitmaps` is incomplete, and favicon bitmaps in the
// database should be preserved if possible. For instance, favicon bitmaps
// from sync are 1x only. MergeFavicon() is used to avoid deleting the 2x
- // favicon bitmap if it is present in the history backend. |page_urls| must
+ // favicon bitmap if it is present in the history backend. `page_urls` must
// not be empty.
void SetFavicons(const base::flat_set<GURL>& page_urls,
favicon_base::IconType icon_type,
const GURL& icon_url,
const std::vector<SkBitmap>& bitmaps);
- // Causes each page in |page_urls_to_write| to be associated to the same
- // icon as the page |page_url_to_read| for icon types matching |icon_types|.
- // No-op if |page_url_to_read| has no mappings for |icon_types|.
+ // Causes each page in `page_urls_to_write` to be associated to the same
+ // icon as the page `page_url_to_read` for icon types matching `icon_types`.
+ // No-op if `page_url_to_read` has no mappings for `icon_types`.
void CloneFaviconMappingsForPages(
const GURL& page_url_to_read,
const favicon_base::IconTypeSet& icon_types,
const base::flat_set<GURL>& page_urls_to_write);
// Figures out whether an on-demand favicon can be written for provided
- // |page_url| and returns the result via |callback|. The result is false if
- // there is an existing cached favicon for |icon_type| or if there is a
- // non-expired icon of *any* type for |page_url|.
+ // `page_url` and returns the result via `callback`. The result is false if
+ // there is an existing cached favicon for `icon_type` or if there is a
+ // non-expired icon of *any* type for `page_url`.
void CanSetOnDemandFavicons(const GURL& page_url,
favicon_base::IconType icon_type,
base::OnceCallback<void(bool)> callback);
// Same as SetFavicons with three differences:
// 1) It will be a no-op if CanSetOnDemandFavicons() returns false.
- // 2) If |icon_url| is known to the database, |bitmaps| will be ignored (i.e.
- // the icon won't be overwritten) but the mappings from |page_url| to
- // |icon_url| will be stored (conditioned to point 1 above).
- // 3) If |icon_url| is stored, it will be marked as "on-demand".
+ // 2) If `icon_url` is known to the database, `bitmaps` will be ignored (i.e.
+ // the icon won't be overwritten) but the mappings from `page_url` to
+ // `icon_url` will be stored (conditioned to point 1 above).
+ // 3) If `icon_url` is stored, it will be marked as "on-demand".
//
// On-demand favicons are those that are fetched without visiting their page.
// For this reason, their life-time cannot be bound to the life-time of the
@@ -849,7 +861,7 @@ class HistoryService : public KeyedService {
// of date.
void SetFaviconsOutOfDateForPage(const GURL& page_url);
- // Mark that the on-demand favicon at |icon_url| was requested now. This
+ // Mark that the on-demand favicon at `icon_url` was requested now. This
// postpones the automatic eviction of the favicon from the database. Not all
// calls end up in a write into the DB:
// - it is no-op if the bitmaps are not stored using SetOnDemandFavicons();
@@ -879,7 +891,7 @@ class HistoryService : public KeyedService {
// Called when the favicons for the given page URLs (e.g.
// http://www.google.com) and the given icon URL (e.g.
// http://www.google.com/favicon.ico) have changed. It is valid to call
- // NotifyFaviconsChanged() with non-empty |page_urls| and an empty |icon_url|
+ // NotifyFaviconsChanged() with non-empty `page_urls` and an empty `icon_url`
// and vice versa.
void NotifyFaviconsChanged(const std::set<GURL>& page_urls,
const GURL& icon_url);
@@ -891,7 +903,7 @@ class HistoryService : public KeyedService {
scoped_refptr<base::SequencedTaskRunner> backend_task_runner_;
// This class has most of the implementation. You MUST communicate with this
- // class ONLY through |backend_task_runner_|.
+ // class ONLY through `backend_task_runner_`.
//
// This pointer will be null once Cleanup() has been called, meaning no
// more tasks should be scheduled.
diff --git a/chromium/components/history/core/browser/history_service_observer.h b/chromium/components/history/core/browser/history_service_observer.h
index 45d79550572..6f5cd13c6cc 100644
--- a/chromium/components/history/core/browser/history_service_observer.h
+++ b/chromium/components/history/core/browser/history_service_observer.h
@@ -20,11 +20,11 @@ class HistoryServiceObserver {
// Called when user visits an URL.
//
- // The |row| ID will be set to the value that is currently in effect in the
- // main history database. |redirects| is the list of redirects leading up to
+ // The `row` ID will be set to the value that is currently in effect in the
+ // main history database. `redirects` is the list of redirects leading up to
// the URL. If we have a redirect chain A -> B -> C and user is visiting C,
- // then |redirects[0]=B| and |redirects[1]=A|. If there are no redirects,
- // |redirects| is an empty vector.
+ // then `redirects[0]=B` and `redirects[1]=A`. If there are no redirects,
+ // `redirects` is an empty vector.
virtual void OnURLVisited(HistoryService* history_service,
ui::PageTransition transition,
const URLRow& row,
@@ -33,7 +33,7 @@ class HistoryServiceObserver {
// Called when a URL has been added or modified.
//
- // |changed_urls| lists the information for each of the URLs affected. The
+ // `changed_urls` lists the information for each of the URLs affected. The
// rows will have the IDs that are currently in effect in the main history
// database.
virtual void OnURLsModified(HistoryService* history_service,
@@ -47,27 +47,27 @@ class HistoryServiceObserver {
// Called when one or more URLs are deleted.
//
- // |deletion_info| describes the urls that have been removed from history.
+ // `deletion_info` describes the urls that have been removed from history.
virtual void OnURLsDeleted(HistoryService* history_service,
const DeletionInfo& deletion_info) {}
- // Is called to notify when |history_service| has finished loading.
+ // Is called to notify when `history_service` has finished loading.
virtual void OnHistoryServiceLoaded(HistoryService* history_service) {}
- // Is called to notify when |history_service| is being deleted.
+ // Is called to notify when `history_service` is being deleted.
virtual void HistoryServiceBeingDeleted(HistoryService* history_service) {}
// Sent when a keyword search term is updated.
//
- // |row| contains the URL information for search |term|.
- // |keyword_id| associated with a URL and search term.
+ // `row` contains the URL information for search `term`.
+ // `keyword_id` associated with a URL and search term.
virtual void OnKeywordSearchTermUpdated(HistoryService* history_service,
const URLRow& row,
KeywordID keyword_id,
const std::u16string& term) {}
// Sent when a keyword search term is deleted.
- // |url_id| is the id of the url row.
+ // `url_id` is the id of the url row.
virtual void OnKeywordSearchTermDeleted(HistoryService* history_service,
URLID url_id) {}
diff --git a/chromium/components/history/core/browser/history_service_unittest.cc b/chromium/components/history/core/browser/history_service_unittest.cc
index a08e2b38021..9564acb7337 100644
--- a/chromium/components/history/core/browser/history_service_unittest.cc
+++ b/chromium/components/history/core/browser/history_service_unittest.cc
@@ -25,6 +25,7 @@
#include <array>
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -33,25 +34,15 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "components/history/core/browser/history_backend.h"
#include "components/history/core/browser/history_database_params.h"
#include "components/history/core/browser/history_db_task.h"
#include "components/history/core/test/database_test_utils.h"
#include "components/history/core/test/test_history_database.h"
-#include "components/sync/model/sync_change.h"
-#include "components/sync/model/sync_change_processor.h"
-#include "components/sync/model/sync_error.h"
-#include "components/sync/model/sync_error_factory.h"
-#include "components/sync/protocol/history_delete_directive_specifics.pb.h"
-#include "components/sync/protocol/sync.pb.h"
-#include "components/sync/test/model/fake_sync_change_processor.h"
-#include "components/sync/test/model/sync_change_processor_wrapper_for_test.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace history {
@@ -59,7 +50,7 @@ namespace history {
class HistoryServiceTest : public testing::Test {
public:
HistoryServiceTest() = default;
- ~HistoryServiceTest() override {}
+ ~HistoryServiceTest() override = default;
protected:
friend class BackendDelegate;
@@ -104,7 +95,7 @@ class HistoryServiceTest : public testing::Test {
// Fills the query_url_result_ structures with the information about the given
// URL and whether the operation succeeded or not.
- bool QueryURL(history::HistoryService* history, const GURL& url) {
+ bool QueryURL(const GURL& url) {
base::RunLoop run_loop;
history_service_->QueryURL(
url, true,
@@ -119,7 +110,7 @@ class HistoryServiceTest : public testing::Test {
// Fills in saved_redirects_ with the redirect information for the given URL,
// returning true on success. False means the URL was not found.
- void QueryRedirectsFrom(history::HistoryService* history, const GURL& url) {
+ void QueryRedirectsFrom(const GURL& url) {
base::RunLoop run_loop;
history_service_->QueryRedirectsFrom(
url,
@@ -201,7 +192,7 @@ TEST_F(HistoryServiceTest, AddPage) {
history::RedirectList(),
ui::PAGE_TRANSITION_MANUAL_SUBFRAME,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url));
+ EXPECT_TRUE(QueryURL(test_url));
EXPECT_EQ(1, query_url_result_.row.visit_count());
EXPECT_EQ(0, query_url_result_.row.typed_count());
EXPECT_TRUE(
@@ -211,7 +202,7 @@ TEST_F(HistoryServiceTest, AddPage) {
history_service_->AddPage(test_url, base::Time::Now(), nullptr, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url));
+ EXPECT_TRUE(QueryURL(test_url));
EXPECT_EQ(2, query_url_result_.row.visit_count()); // Added twice.
EXPECT_EQ(0, query_url_result_.row.typed_count()); // Never typed.
EXPECT_FALSE(
@@ -232,7 +223,7 @@ TEST_F(HistoryServiceTest, AddRedirect) {
// The first page should be added once with a link visit type (because we set
// LINK when we added the original URL, and a referrer of nowhere (0).
- EXPECT_TRUE(QueryURL(history_service_.get(), first_redirects[0]));
+ EXPECT_TRUE(QueryURL(first_redirects[0]));
EXPECT_EQ(1, query_url_result_.row.visit_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
int64_t first_visit = query_url_result_.visits[0].visit_id;
@@ -244,7 +235,7 @@ TEST_F(HistoryServiceTest, AddRedirect) {
// The second page should be a server redirect type with a referrer of the
// first page.
- EXPECT_TRUE(QueryURL(history_service_.get(), first_redirects[1]));
+ EXPECT_TRUE(QueryURL(first_redirects[1]));
EXPECT_EQ(1, query_url_result_.row.visit_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
int64_t second_visit = query_url_result_.visits[0].visit_id;
@@ -256,7 +247,7 @@ TEST_F(HistoryServiceTest, AddRedirect) {
// Check that the redirect finding function successfully reports it.
saved_redirects_.clear();
- QueryRedirectsFrom(history_service_.get(), first_redirects[0]);
+ QueryRedirectsFrom(first_redirects[0]);
ASSERT_EQ(1U, saved_redirects_.size());
EXPECT_EQ(first_redirects[1], saved_redirects_[0]);
@@ -275,11 +266,11 @@ TEST_F(HistoryServiceTest, AddRedirect) {
// The last page (source of the client redirect) should NOT have an
// additional visit added, because it was a client redirect (normally it
// would). We should only have 1 left over from the first sequence.
- EXPECT_TRUE(QueryURL(history_service_.get(), second_redirects[0]));
+ EXPECT_TRUE(QueryURL(second_redirects[0]));
EXPECT_EQ(1, query_url_result_.row.visit_count());
// The final page should be set as a client redirect from the previous visit.
- EXPECT_TRUE(QueryURL(history_service_.get(), second_redirects[1]));
+ EXPECT_TRUE(QueryURL(second_redirects[1]));
EXPECT_EQ(1, query_url_result_.row.visit_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs(
@@ -298,7 +289,7 @@ TEST_F(HistoryServiceTest, MakeIntranetURLsTyped) {
history_service_->AddPage(test_url, base::Time::Now(), nullptr, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url));
+ EXPECT_TRUE(QueryURL(test_url));
EXPECT_EQ(1, query_url_result_.row.visit_count());
EXPECT_EQ(1, query_url_result_.row.typed_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
@@ -313,7 +304,7 @@ TEST_F(HistoryServiceTest, MakeIntranetURLsTyped) {
history_service_->AddPage(test_url2, base::Time::Now(), nullptr, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url2));
+ EXPECT_TRUE(QueryURL(test_url2));
EXPECT_EQ(1, query_url_result_.row.visit_count());
EXPECT_EQ(0, query_url_result_.row.typed_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
@@ -325,7 +316,7 @@ TEST_F(HistoryServiceTest, MakeIntranetURLsTyped) {
history_service_->AddPage(test_url3, base::Time::Now(), nullptr, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url3));
+ EXPECT_TRUE(QueryURL(test_url3));
EXPECT_EQ(1, query_url_result_.row.visit_count());
EXPECT_EQ(0, query_url_result_.row.typed_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
@@ -337,7 +328,7 @@ TEST_F(HistoryServiceTest, MakeIntranetURLsTyped) {
history_service_->AddPage(test_url4, base::Time::Now(), nullptr, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url4));
+ EXPECT_TRUE(QueryURL(test_url4));
EXPECT_EQ(1, query_url_result_.row.visit_count());
EXPECT_EQ(0, query_url_result_.row.typed_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
@@ -349,7 +340,7 @@ TEST_F(HistoryServiceTest, MakeIntranetURLsTyped) {
history_service_->AddPage(
test_url5, base::Time::Now(), nullptr, 0, GURL(), history::RedirectList(),
ui::PAGE_TRANSITION_AUTO_BOOKMARK, history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url5));
+ EXPECT_TRUE(QueryURL(test_url5));
EXPECT_EQ(1, query_url_result_.row.visit_count());
EXPECT_EQ(0, query_url_result_.row.typed_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
@@ -361,7 +352,7 @@ TEST_F(HistoryServiceTest, MakeIntranetURLsTyped) {
history_service_->AddPage(test_url, base::Time::Now(), nullptr, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url));
+ EXPECT_TRUE(QueryURL(test_url));
EXPECT_EQ(2, query_url_result_.row.visit_count());
EXPECT_EQ(1, query_url_result_.row.typed_count());
ASSERT_EQ(2U, query_url_result_.visits.size());
@@ -375,7 +366,7 @@ TEST_F(HistoryServiceTest, MakeIntranetURLsTyped) {
history_service_->AddPage(redirects1.back(), base::Time::Now(), nullptr, 0,
GURL(), redirects1, ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), redirects1.front()));
+ EXPECT_TRUE(QueryURL(redirects1.front()));
EXPECT_EQ(1, query_url_result_.row.visit_count());
EXPECT_EQ(1, query_url_result_.row.typed_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
@@ -389,7 +380,7 @@ TEST_F(HistoryServiceTest, MakeIntranetURLsTyped) {
history_service_->AddPage(redirects2.back(), base::Time::Now(), nullptr, 0,
GURL(), redirects2, ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), redirects2.back()));
+ EXPECT_TRUE(QueryURL(redirects2.back()));
EXPECT_EQ(1, query_url_result_.row.visit_count());
EXPECT_EQ(0, query_url_result_.row.typed_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
@@ -403,7 +394,7 @@ TEST_F(HistoryServiceTest, MakeIntranetURLsTyped) {
history_service_->AddPage(redirects3.back(), base::Time::Now(), nullptr, 0,
GURL(), redirects3, ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), redirects3[1]));
+ EXPECT_TRUE(QueryURL(redirects3[1]));
EXPECT_EQ(1, query_url_result_.row.visit_count());
EXPECT_EQ(0, query_url_result_.row.typed_count());
ASSERT_EQ(1U, query_url_result_.visits.size());
@@ -421,7 +412,7 @@ TEST_F(HistoryServiceTest, Typed) {
history_service_->AddPage(test_url, base::Time::Now(), context_id, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_TYPED,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url));
+ EXPECT_TRUE(QueryURL(test_url));
// We should have the same typed & visit count.
EXPECT_EQ(1, query_url_result_.row.visit_count());
@@ -431,7 +422,7 @@ TEST_F(HistoryServiceTest, Typed) {
history_service_->AddPage(test_url, base::Time::Now(), context_id, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_LINK,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url));
+ EXPECT_TRUE(QueryURL(test_url));
// The second time should not have updated the typed count.
EXPECT_EQ(2, query_url_result_.row.visit_count());
@@ -442,7 +433,7 @@ TEST_F(HistoryServiceTest, Typed) {
history::RedirectList(),
ui::PAGE_TRANSITION_GENERATED,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url));
+ EXPECT_TRUE(QueryURL(test_url));
// This should have worked like a link click.
EXPECT_EQ(3, query_url_result_.row.visit_count());
@@ -452,7 +443,7 @@ TEST_F(HistoryServiceTest, Typed) {
history_service_->AddPage(test_url, base::Time::Now(), context_id, 0, GURL(),
history::RedirectList(), ui::PAGE_TRANSITION_RELOAD,
history::SOURCE_BROWSED, false, false);
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url));
+ EXPECT_TRUE(QueryURL(test_url));
// This should not have incremented any visit counts.
EXPECT_EQ(3, query_url_result_.row.visit_count());
@@ -472,7 +463,7 @@ TEST_F(HistoryServiceTest, SetTitle) {
history_service_->SetPageTitle(existing_url, existing_title);
// Make sure the title got set.
- EXPECT_TRUE(QueryURL(history_service_.get(), existing_url));
+ EXPECT_TRUE(QueryURL(existing_url));
EXPECT_EQ(existing_title, query_url_result_.row.title());
// set a title on a nonexistent page
@@ -481,7 +472,7 @@ TEST_F(HistoryServiceTest, SetTitle) {
history_service_->SetPageTitle(nonexistent_url, nonexistent_title);
// Make sure nothing got written.
- EXPECT_FALSE(QueryURL(history_service_.get(), nonexistent_url));
+ EXPECT_FALSE(QueryURL(nonexistent_url));
EXPECT_EQ(std::u16string(), query_url_result_.row.title());
// TODO(brettw) this should also test redirects, which get the title of the
@@ -591,7 +582,7 @@ class HistoryDBTaskImpl : public HistoryDBTask {
bool* done_invoked_;
private:
- ~HistoryDBTaskImpl() override {}
+ ~HistoryDBTaskImpl() override = default;
DISALLOW_COPY_AND_ASSIGN(HistoryDBTaskImpl);
};
@@ -716,7 +707,7 @@ DomainDiversityResults GetDomainDiversityHelper(
// Test one domain visit metric. A negative value indicates that an invalid
// metric is expected.
-void TestDomainMetric(const base::Optional<DomainMetricCountType>& metric,
+void TestDomainMetric(const absl::optional<DomainMetricCountType>& metric,
int expected) {
if (expected >= 0) {
ASSERT_TRUE(metric.has_value());
@@ -764,14 +755,13 @@ TEST_F(HistoryServiceTest, CountMonthlyVisitedHosts) {
}
TEST_F(HistoryServiceTest, GetDomainDiversityShortBasetimeRange) {
- base::HistogramTester histogram_tester;
HistoryService* history = history_service_.get();
ASSERT_TRUE(history);
base::Time query_time = base::Time::Now();
- // Make sure |query_time| is at least some time past the midnight so that
- // some domain visits can be inserted between |query_time| and midnight
+ // Make sure `query_time` is at least some time past the midnight so that
+ // some domain visits can be inserted between `query_time` and midnight
// for testing.
query_time =
std::max(query_time.LocalMidnight() + base::TimeDelta::FromMinutes(10),
@@ -801,7 +791,7 @@ TEST_F(HistoryServiceTest, GetDomainDiversityShortBasetimeRange) {
GetTimeInThePast(query_time, 1, 8));
AddPageAtTime(history, "http://ak/", GetTimeInThePast(query_time, 1, 14));
- // Should return empty result if |begin_time| == |end_time|.
+ // Should return empty result if `begin_time` == `end_time`.
DomainDiversityResults res = GetDomainDiversityHelper(
history, query_time, query_time,
history::kEnableLast1DayMetric | history::kEnableLast7DayMetric |
@@ -825,7 +815,6 @@ TEST_F(HistoryServiceTest, GetDomainDiversityShortBasetimeRange) {
}
TEST_F(HistoryServiceTest, GetDomainDiversityLongBasetimeRange) {
- base::HistogramTester histogram_tester;
HistoryService* history = history_service_.get();
ASSERT_TRUE(history);
@@ -871,7 +860,6 @@ TEST_F(HistoryServiceTest, GetDomainDiversityLongBasetimeRange) {
}
TEST_F(HistoryServiceTest, GetDomainDiversityBitmaskTest) {
- base::HistogramTester histogram_tester;
HistoryService* history = history_service_.get();
ASSERT_TRUE(history);
diff --git a/chromium/components/history/core/browser/history_types.cc b/chromium/components/history/core/browser/history_types.cc
index 3afef40d319..1e77d1167c9 100644
--- a/chromium/components/history/core/browser/history_types.cc
+++ b/chromium/components/history/core/browser/history_types.cc
@@ -15,7 +15,7 @@ namespace history {
// VisitRow --------------------------------------------------------------------
-VisitRow::VisitRow() {}
+VisitRow::VisitRow() = default;
VisitRow::VisitRow(URLID arg_url_id,
base::Time arg_visit_time,
@@ -31,14 +31,13 @@ VisitRow::VisitRow(URLID arg_url_id,
segment_id(arg_segment_id),
incremented_omnibox_typed_score(arg_incremented_omnibox_typed_score) {}
-VisitRow::~VisitRow() {
-}
+VisitRow::~VisitRow() = default;
// QueryResults ----------------------------------------------------------------
-QueryResults::QueryResults() {}
+QueryResults::QueryResults() = default;
-QueryResults::~QueryResults() {}
+QueryResults::~QueryResults() = default;
QueryResults::QueryResults(QueryResults&& other) noexcept {
Swap(&other);
@@ -102,7 +101,7 @@ void QueryResults::DeleteRange(size_t begin, size_t end) {
// exclusive, while ours is inclusive, hence the +1).
results_.erase(results_.begin() + begin, results_.begin() + end + 1);
- // Delete the indicies referencing the deleted entries.
+ // Delete the indices referencing the deleted entries.
for (const auto& url : urls_modified) {
auto found = url_to_results_.find(url);
if (found == url_to_results_.end()) {
@@ -114,7 +113,7 @@ void QueryResults::DeleteRange(size_t begin, size_t end) {
for (int match = 0; match < static_cast<int>(found->second->size());
match++) {
if (found->second[match] >= begin && found->second[match] <= end) {
- // Remove this referece from the list.
+ // Remove this reference from the list.
found->second->erase(found->second->begin() + match);
match--;
}
@@ -145,18 +144,18 @@ void QueryResults::AddURLUsageAtIndex(const GURL& url, size_t index) {
}
void QueryResults::AdjustResultMap(size_t begin, size_t end, ptrdiff_t delta) {
- for (auto i = url_to_results_.begin(); i != url_to_results_.end(); ++i) {
- for (size_t match = 0; match < i->second->size(); match++) {
- size_t match_index = i->second[match];
+ for (auto& url_to_result : url_to_results_) {
+ for (size_t match = 0; match < url_to_result.second->size(); match++) {
+ size_t match_index = url_to_result.second[match];
if (match_index >= begin && match_index <= end)
- i->second[match] += delta;
+ url_to_result.second[match] += delta;
}
}
}
// QueryOptions ----------------------------------------------------------------
-QueryOptions::QueryOptions() {}
+QueryOptions::QueryOptions() = default;
void QueryOptions::SetRecentDayRange(int days_ago) {
end_time = base::Time::Now();
@@ -192,7 +191,7 @@ QueryURLResult& QueryURLResult::operator=(QueryURLResult&&) noexcept = default;
// MostVisitedURL --------------------------------------------------------------
-MostVisitedURL::MostVisitedURL() {}
+MostVisitedURL::MostVisitedURL() = default;
MostVisitedURL::MostVisitedURL(const GURL& url, const std::u16string& title)
: url(url), title(title) {}
@@ -207,7 +206,7 @@ MostVisitedURL& MostVisitedURL::operator=(const MostVisitedURL&) = default;
// FilteredURL -----------------------------------------------------------------
-FilteredURL::FilteredURL() {}
+FilteredURL::FilteredURL() = default;
FilteredURL::FilteredURL(const PageUsageData& page_data)
: url(page_data.GetURL()),
@@ -217,7 +216,7 @@ FilteredURL::FilteredURL(const PageUsageData& page_data)
FilteredURL::FilteredURL(FilteredURL&& other) noexcept = default;
-FilteredURL::~FilteredURL() {}
+FilteredURL::~FilteredURL() = default;
// FilteredURL::ExtendedInfo ---------------------------------------------------
@@ -225,11 +224,11 @@ FilteredURL::ExtendedInfo::ExtendedInfo() = default;
// TopSitesDelta --------------------------------------------------------------
-TopSitesDelta::TopSitesDelta() {}
+TopSitesDelta::TopSitesDelta() = default;
TopSitesDelta::TopSitesDelta(const TopSitesDelta& other) = default;
-TopSitesDelta::~TopSitesDelta() {}
+TopSitesDelta::~TopSitesDelta() = default;
// HistoryAddPageArgs ---------------------------------------------------------
@@ -246,7 +245,7 @@ HistoryAddPageArgs::HistoryAddPageArgs()
false,
true,
false,
- base::nullopt) {}
+ absl::nullopt) {}
HistoryAddPageArgs::HistoryAddPageArgs(const GURL& url,
base::Time time,
@@ -260,7 +259,7 @@ HistoryAddPageArgs::HistoryAddPageArgs(const GURL& url,
bool did_replace_entry,
bool consider_for_ntp_most_visited,
bool floc_allowed,
- base::Optional<std::u16string> title)
+ absl::optional<std::u16string> title)
: url(url),
time(time),
context_id(context_id),
@@ -277,24 +276,22 @@ HistoryAddPageArgs::HistoryAddPageArgs(const GURL& url,
HistoryAddPageArgs::HistoryAddPageArgs(const HistoryAddPageArgs& other) =
default;
-HistoryAddPageArgs::~HistoryAddPageArgs() {}
+HistoryAddPageArgs::~HistoryAddPageArgs() = default;
// DomainMetricSet ------------------------------------------------------------
-DomainMetricSet::DomainMetricSet() {}
+DomainMetricSet::DomainMetricSet() = default;
DomainMetricSet::DomainMetricSet(const DomainMetricSet&) = default;
-DomainMetricSet::~DomainMetricSet() {}
+DomainMetricSet::~DomainMetricSet() = default;
DomainMetricSet& DomainMetricSet::operator=(const DomainMetricSet&) = default;
// ExpireHistoryArgs ----------------------------------------------------------
-ExpireHistoryArgs::ExpireHistoryArgs() {
-}
+ExpireHistoryArgs::ExpireHistoryArgs() = default;
ExpireHistoryArgs::ExpireHistoryArgs(const ExpireHistoryArgs& other) = default;
-ExpireHistoryArgs::~ExpireHistoryArgs() {
-}
+ExpireHistoryArgs::~ExpireHistoryArgs() = default;
void ExpireHistoryArgs::SetTimeRangeForOneDay(base::Time time) {
begin_time = time.LocalMidnight();
@@ -328,7 +325,7 @@ bool DeletionTimeRange::IsAllTime() const {
// static
DeletionInfo DeletionInfo::ForAllHistory() {
return DeletionInfo(DeletionTimeRange::AllTime(), false, {}, {},
- base::nullopt);
+ absl::nullopt);
}
// static
@@ -336,14 +333,14 @@ DeletionInfo DeletionInfo::ForUrls(URLRows deleted_rows,
std::set<GURL> favicon_urls) {
return DeletionInfo(DeletionTimeRange::Invalid(), false,
std::move(deleted_rows), std::move(favicon_urls),
- base::nullopt);
+ absl::nullopt);
}
DeletionInfo::DeletionInfo(const DeletionTimeRange& time_range,
bool is_from_expiration,
URLRows deleted_rows,
std::set<GURL> favicon_urls,
- base::Optional<std::set<GURL>> restrict_urls)
+ absl::optional<std::set<GURL>> restrict_urls)
: time_range_(time_range),
is_from_expiration_(is_from_expiration),
deleted_rows_(std::move(deleted_rows)),
@@ -362,4 +359,22 @@ DeletionInfo::DeletionInfo(DeletionInfo&& other) noexcept = default;
DeletionInfo& DeletionInfo::operator=(DeletionInfo&& rhs) noexcept = default;
+// Clusters --------------------------------------------------------------------
+
+AnnotatedVisit::AnnotatedVisit() = default;
+AnnotatedVisit::AnnotatedVisit(URLRow url_row,
+ VisitRow visit_row,
+ VisitContextAnnotations context_annotations,
+ VisitContentAnnotations content_annotations)
+ : url_row(url_row),
+ visit_row(visit_row),
+ context_annotations(context_annotations),
+ content_annotations(content_annotations) {}
+AnnotatedVisit::AnnotatedVisit(const AnnotatedVisit&) = default;
+AnnotatedVisit::~AnnotatedVisit() = default;
+
+Cluster::Cluster() = default;
+Cluster::Cluster(const Cluster&) = default;
+Cluster::~Cluster() = default;
+
} // namespace history
diff --git a/chromium/components/history/core/browser/history_types.h b/chromium/components/history/core/browser/history_types.h
index a09b3a9364b..395d15352fc 100644
--- a/chromium/components/history/core/browser/history_types.h
+++ b/chromium/components/history/core/browser/history_types.h
@@ -17,13 +17,12 @@
#include "base/callback.h"
#include "base/containers/stack_container.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/favicon_base/favicon_types.h"
#include "components/history/core/browser/history_context.h"
#include "components/history/core/browser/url_row.h"
-#include "components/history/core/common/thumbnail_score.h"
#include "components/query_parser/query_parser.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
@@ -162,12 +161,12 @@ class QueryResults {
}
// Returns a pointer to the beginning of an array of all matching indices
- // for entries with the given URL. The array will be |*num_matches| long.
- // |num_matches| can be NULL if the caller is not interested in the number of
+ // for entries with the given URL. The array will be `*num_matches` long.
+ // `num_matches` can be NULL if the caller is not interested in the number of
// results (commonly it will only be interested in the first one and can test
// the pointer for NULL).
//
- // When there is no match, it will return NULL and |*num_matches| will be 0.
+ // When there is no match, it will return NULL and `*num_matches` will be 0.
const size_t* MatchesForURL(const GURL& url, size_t* num_matches) const;
// Swaps the current result with another. This allows ownership to be
@@ -191,11 +190,11 @@ class QueryResults {
// memory when possible.
typedef std::map<GURL, base::StackVector<size_t, 4>> URLToResultIndices;
- // Inserts an entry into the |url_to_results_| map saying that the given URL
+ // Inserts an entry into the `url_to_results_` map saying that the given URL
// is at the given index in the results_.
void AddURLUsageAtIndex(const GURL& url, size_t index);
- // Adds |delta| to each index in url_to_results_ in the range [begin,end]
+ // Adds `delta` to each index in url_to_results_ in the range [begin,end]
// (this is inclusive). This is used when inserting or deleting.
void AdjustResultMap(size_t begin, size_t end, ptrdiff_t delta);
@@ -228,7 +227,7 @@ struct QueryOptions {
base::Time begin_time;
base::Time end_time;
- // Sets the query time to the last |days_ago| days to the present time.
+ // Sets the query time to the last `days_ago` days to the present time.
void SetRecentDayRange(int days_ago);
// The maximum number of results to return. The results will be sorted with
@@ -277,7 +276,7 @@ struct QueryURLResult {
~QueryURLResult();
// Indicates whether the call to HistoryBackend::QueryURL was successful
- // or not. If false, then both |row| and |visits| fields are undefined.
+ // or not. If false, then both `row` and `visits` fields are undefined.
bool success = false;
URLRow row;
VisitVector visits;
@@ -289,7 +288,7 @@ struct QueryURLResult {
// HistoryBackend::GetVisibleVisitCountToHost.
struct VisibleVisitCountToHostResult {
// Indicates whether the call to HistoryBackend::GetVisibleVisitCountToHost
- // was successful or not. If false, then both |count| and |first_visit| are
+ // was successful or not. If false, then both `count` and `first_visit` are
// undefined.
bool success = false;
int count = 0;
@@ -318,7 +317,7 @@ struct MostVisitedURL {
// FilteredURL -----------------------------------------------------------------
-// Holds the per-URL information of the filterd url query.
+// Holds the per-URL information of the filtered url query.
struct FilteredURL {
struct ExtendedInfo {
ExtendedInfo();
@@ -353,7 +352,7 @@ struct HistoryAddPageArgs {
// GURL(), base::Time(), nullptr, 0, GURL(),
// RedirectList(), ui::PAGE_TRANSITION_LINK,
// false, SOURCE_BROWSED, false, true,
- // base::nullopt)
+ // absl::nullopt)
HistoryAddPageArgs();
HistoryAddPageArgs(const GURL& url,
base::Time time,
@@ -367,7 +366,7 @@ struct HistoryAddPageArgs {
bool did_replace_entry,
bool consider_for_ntp_most_visited,
bool floc_allowed,
- base::Optional<std::u16string> title = base::nullopt);
+ absl::optional<std::u16string> title = absl::nullopt);
HistoryAddPageArgs(const HistoryAddPageArgs& other);
~HistoryAddPageArgs();
@@ -389,7 +388,7 @@ struct HistoryAddPageArgs {
// Indicates whether this URL visit can be included in FLoC computation. See
// VisitRow::floc_allowed for details.
bool floc_allowed;
- base::Optional<std::u16string> title;
+ absl::optional<std::u16string> title;
};
// TopSites -------------------------------------------------------------------
@@ -424,7 +423,7 @@ typedef std::map<GURL, std::pair<int, base::Time>> OriginCountAndLastVisitMap;
// HistoryBackend::GetHistoryCount or
// HistoryBackend::CountUniqueHostsVisitedLastMonth.
struct HistoryCountResult {
- // Indicates whether the call was successful or not. If false, then |count|
+ // Indicates whether the call was successful or not. If false, then `count`
// is undefined.
bool success = false;
int count = 0;
@@ -448,9 +447,9 @@ struct DomainMetricSet {
DomainMetricSet& operator=(const DomainMetricSet&);
- base::Optional<DomainMetricCountType> one_day_metric;
- base::Optional<DomainMetricCountType> seven_day_metric;
- base::Optional<DomainMetricCountType> twenty_eight_day_metric;
+ absl::optional<DomainMetricCountType> one_day_metric;
+ absl::optional<DomainMetricCountType> seven_day_metric;
+ absl::optional<DomainMetricCountType> twenty_eight_day_metric;
// The end time of the spanning periods. All 3 metrics should have the same
// end time.
@@ -482,9 +481,9 @@ enum DomainMetricType : DomainMetricBitmaskType {
struct HistoryLastVisitResult {
// Indicates whether the call was successful or not. This can happen if there
// are internal database errors or the query was called with invalid
- // arguments. |success| will be true and |last_visit| will be null if
- // the host was never visited before. |last_visit| will always be null if
- // |success| is false.
+ // arguments. `success` will be true and `last_visit` will be null if
+ // the host was never visited before. `last_visit` will always be null if
+ // `success` is false.
bool success = false;
base::Time last_visit;
};
@@ -507,8 +506,8 @@ struct ExpireHistoryArgs {
ExpireHistoryArgs(const ExpireHistoryArgs& other);
~ExpireHistoryArgs();
- // Sets |begin_time| and |end_time| to the beginning and end of the day (in
- // local time) on which |time| occurs.
+ // Sets `begin_time` and `end_time` to the beginning and end of the day (in
+ // local time) on which `time` occurs.
void SetTimeRangeForOneDay(base::Time time);
std::set<GURL> urls;
@@ -516,7 +515,7 @@ struct ExpireHistoryArgs {
base::Time end_time;
};
-// Represents the time range of a history deletion. If |IsValid()| is false,
+// Represents the time range of a history deletion. If `IsValid()` is false,
// the time range doesn't apply to this deletion e.g. because only a list of
// urls was deleted.
class DeletionTimeRange {
@@ -556,11 +555,11 @@ class DeletionTimeRange {
};
// Describes the urls that have been removed due to a history deletion.
-// If |IsAllHistory()| returns true, all urls haven been deleted.
-// In this case, |deleted_rows()| and |favicon_urls()| are undefined.
-// Otherwise |deleted_rows()| contains the urls where all visits have been
+// If `IsAllHistory()` returns true, all urls haven been deleted.
+// In this case, `deleted_rows()` and `favicon_urls()` are undefined.
+// Otherwise `deleted_rows()` contains the urls where all visits have been
// removed from history.
-// If |expired()| returns true, this deletion is due to a regularly performed
+// If `expired()` returns true, this deletion is due to a regularly performed
// history expiration. Otherwise it is an explicit deletion due to a user
// action.
class DeletionInfo {
@@ -575,23 +574,23 @@ class DeletionInfo {
bool is_from_expiration,
URLRows deleted_rows,
std::set<GURL> favicon_urls,
- base::Optional<std::set<GURL>> restrict_urls);
+ absl::optional<std::set<GURL>> restrict_urls);
~DeletionInfo();
// Move-only because of potentially large containers.
DeletionInfo(DeletionInfo&& other) noexcept;
DeletionInfo& operator=(DeletionInfo&& rhs) noexcept;
- // If IsAllHistory() returns true, all URLs are deleted and |deleted_rows()|
- // and |favicon_urls()| are undefined.
+ // If IsAllHistory() returns true, all URLs are deleted and `deleted_rows()`
+ // and `favicon_urls()` are undefined.
bool IsAllHistory() const { return time_range_.IsAllTime(); }
- // If time_range.IsValid() is true, |restrict_urls| (or all URLs if empty)
+ // If time_range.IsValid() is true, `restrict_urls` (or all URLs if empty)
// between time_range.begin() and time_range.end() have been removed.
const DeletionTimeRange& time_range() const { return time_range_; }
- // Restricts deletions within |time_range()|.
- const base::Optional<std::set<GURL>>& restrict_urls() const {
+ // Restricts deletions within `time_range()`.
+ const absl::optional<std::set<GURL>>& restrict_urls() const {
return restrict_urls_;
}
@@ -599,11 +598,11 @@ class DeletionInfo {
bool is_from_expiration() const { return is_from_expiration_; }
// Returns the list of the deleted URLs.
- // Undefined if |IsAllHistory()| returns true.
+ // Undefined if `IsAllHistory()` returns true.
const URLRows& deleted_rows() const { return deleted_rows_; }
// Returns the list of favicon URLs that correspond to the deleted URLs.
- // Undefined if |IsAllHistory()| returns true.
+ // Undefined if `IsAllHistory()` returns true.
const std::set<GURL>& favicon_urls() const { return favicon_urls_; }
// Returns a map from origins with deleted urls to a count of remaining URLs
@@ -625,7 +624,7 @@ class DeletionInfo {
bool is_from_expiration_;
URLRows deleted_rows_;
std::set<GURL> favicon_urls_;
- base::Optional<std::set<GURL>> restrict_urls_;
+ absl::optional<std::set<GURL>> restrict_urls_;
OriginCountAndLastVisitMap deleted_urls_origin_map_;
DISALLOW_COPY_AND_ASSIGN(DeletionInfo);
@@ -663,6 +662,99 @@ enum class UrlsModifiedReason {
kAndroidDb,
};
+// Clusters --------------------------------------------------------------------
+
+// Context annotations about a page visit collected during the page lifetime.
+// This struct encapsulates data that's shared between UKM and the on-device
+// storage for `HistoryCluster` metadata, recorded to both when the page
+// lifetime ends. This is to ensure that History actually has the visit row
+// already written.
+struct VisitContextAnnotations {
+ // True if the user has cut or copied the omnibox URL to the clipboard for
+ // this page load.
+ bool omnibox_url_copied = false;
+
+ // True if the page was in a tab group when the navigation was committed.
+ bool is_existing_part_of_tab_group = false;
+
+ // True if the page was NOT part of a tab group when the navigation
+ // committed, and IS part of a tab group at the end of the page lifetime.
+ bool is_placed_in_tab_group = false;
+
+ // True if this page was a bookmark when the navigation was committed.
+ bool is_existing_bookmark = false;
+
+ // True if the page was NOT a bookmark when the navigation was committed and
+ // was MADE a bookmark during the page's lifetime. In other words:
+ // If `is_existing_bookmark` is true, that implies `is_new_bookmark` is false.
+ bool is_new_bookmark = false;
+
+ // True if the page has been explicitly added (by the user) to the list of
+ // custom links displayed in the NTP. Links added to the NTP by History
+ // TopSites don't count for this. Always false on Android, because Android
+ // does not have NTP custom links.
+ bool is_ntp_custom_link = false;
+
+ // The duration since the last visit to this URL in seconds, if the user has
+ // visited the URL before. Recorded as -1 (second) if the user has not
+ // visited the URL before, or if the History service is unavailable or slow to
+ // respond. Any duration that exceeds 30 days will be recorded as 30 days, so
+ // in practice, if this duration indicates 30 days, it can be anything from 30
+ // to the maximum duration that local history is stored.
+ base::TimeDelta duration_since_last_visit = base::TimeDelta::FromSeconds(-1);
+
+ // ---------------------------------------------------------------------------
+ // The below metrics are all already recorded by UKM for non-memories reasons.
+ // We are duplicating them below to persist on-device and send to an offline
+ // model.
+
+ // An opaque integer representing page_load_metrics::PageEndReason.
+ // Do not use this directly, as it's a raw integer for serialization, and not
+ // a typesafe page_load_metrics::PageEndReason.
+ int page_end_reason = 0;
+};
+
+// A `VisitRow` along with its corresponding `URLRow`,
+// `VisitContextAnnotations`, and `VisitContentAnnotations`.
+struct AnnotatedVisit {
+ AnnotatedVisit();
+ AnnotatedVisit(URLRow url_row,
+ VisitRow visit_row,
+ VisitContextAnnotations context_annotations,
+ VisitContentAnnotations content_annotations);
+ AnnotatedVisit(const AnnotatedVisit&);
+ ~AnnotatedVisit();
+
+ URLRow url_row;
+ VisitRow visit_row;
+ VisitContextAnnotations context_annotations;
+ VisitContentAnnotations content_annotations;
+};
+
+// The DB representation of `AnnotatedVisit`.
+struct AnnotatedVisitRow {
+ AnnotatedVisitRow() = default;
+ AnnotatedVisitRow(const VisitID visit_id,
+ const VisitContextAnnotations& context_annotations,
+ const VisitContentAnnotations& content_annotations)
+ : visit_id(visit_id),
+ context_annotations(context_annotations),
+ content_annotations(content_annotations) {}
+
+ VisitID visit_id;
+ VisitContextAnnotations context_annotations;
+ VisitContentAnnotations content_annotations;
+};
+
+struct Cluster {
+ Cluster();
+ Cluster(const Cluster&);
+ ~Cluster();
+
+ std::vector<std::u16string> keywords;
+ std::vector<AnnotatedVisit> annotated_visits;
+};
+
} // namespace history
#endif // COMPONENTS_HISTORY_CORE_BROWSER_HISTORY_TYPES_H_
diff --git a/chromium/components/history/core/browser/in_memory_database.cc b/chromium/components/history/core/browser/in_memory_database.cc
index 71556d26cd2..dd9f6a9ad74 100644
--- a/chromium/components/history/core/browser/in_memory_database.cc
+++ b/chromium/components/history/core/browser/in_memory_database.cc
@@ -97,7 +97,6 @@ bool InMemoryDatabase::InitFromDisk(const base::FilePath& history_name) {
db_.GetLastChangeCount());
// 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, "
"u.visit_count, u.typed_count, u.last_visit_time, u.hidden "
"FROM history.urls u JOIN history.keyword_search_terms kst "
@@ -109,7 +108,6 @@ bool InMemoryDatabase::InitFromDisk(const base::FilePath& history_name) {
db_.GetLastChangeCount());
// Copy search terms to memory.
- begin_load = base::TimeTicks::Now();
if (!db_.Execute(
"INSERT INTO keyword_search_terms SELECT * FROM "
"history.keyword_search_terms")) {
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 7e203eb38a2..c6ae62cb1a4 100644
--- a/chromium/components/history/core/browser/in_memory_history_backend.h
+++ b/chromium/components/history/core/browser/in_memory_history_backend.h
@@ -7,7 +7,7 @@
// low-latency operations, such as in-line autocomplete.
//
// The in-memory cache provides the following guarantees:
-// (1.) It will always contain URLRows that either have a |typed_count| > 0; or
+// (1.) It will always contain URLRows that either have a `typed_count` > 0; or
// that have a corresponding search term, in which case information about
// the search term is also stored.
// (2.) It will be an actual subset, i.e., it will contain verbatim data, and
@@ -47,7 +47,7 @@ class InMemoryHistoryBackend : public HistoryServiceObserver {
~InMemoryHistoryBackend() override;
// Initializes the backend from the history database pointed to by the
- // full path in |history_filename|.
+ // full path in `history_filename`.
bool Init(const base::FilePath& history_filename);
// Does initialization work when this object is attached to the history
diff --git a/chromium/components/history/core/browser/keyword_search_term.h b/chromium/components/history/core/browser/keyword_search_term.h
index 295dfeb66ef..a8c88f4e9d2 100644
--- a/chromium/components/history/core/browser/keyword_search_term.h
+++ b/chromium/components/history/core/browser/keyword_search_term.h
@@ -27,8 +27,8 @@ struct NormalizedKeywordSearchTermVisit {
// recency_in_seconds + recency_decay_unit_in_seconds
// This score combines frequency and recency of the visit favoring ones that
// are more frequent and more recent (see go/local-zps-frecency-ranking).
- // |recency_decay_unit_sec| is the number of seconds until the recency
- // component of the score decays to half. |frequency_exponent| is factor by
+ // `recency_decay_unit_sec` is the number of seconds until the recency
+ // component of the score decays to half. `frequency_exponent` is factor by
// which the frequency of the visit is exponentiated.
double GetFrecency(base::Time now,
int recency_decay_unit_sec,
diff --git a/chromium/components/history/core/browser/sync/delete_directive_handler.cc b/chromium/components/history/core/browser/sync/delete_directive_handler.cc
index 8248ca34dd2..b491250cd81 100644
--- a/chromium/components/history/core/browser/sync/delete_directive_handler.cc
+++ b/chromium/components/history/core/browser/sync/delete_directive_handler.cc
@@ -13,6 +13,7 @@
#include <vector>
#include "base/json/json_writer.h"
+#include "base/logging.h"
#include "base/rand_util.h"
#include "base/time/time.h"
#include "base/values.h"
@@ -69,7 +70,7 @@ int64_t TimeToUnixUsec(base::Time time) {
return (time - base::Time::UnixEpoch()).InMicroseconds();
}
-// Converts global IDs in |global_id_directive| to times.
+// Converts global IDs in `global_id_directive` to times.
void GetTimesFromGlobalIds(
const sync_pb::GlobalIdDirective& global_id_directive,
std::set<base::Time>* times) {
@@ -157,8 +158,8 @@ class DeleteDirectiveHandler::DeleteDirectiveTask : public HistoryDBTask {
const syncer::SyncDataList& global_id_directives);
// Process a list of time range directives, all history entries within the
- // time ranges are deleted. |time_range_directives| should be sorted by
- // |start_time_usec| and |end_time_usec| already.
+ // time ranges are deleted. `time_range_directives` should be sorted by
+ // `start_time_usec` and `end_time_usec` already.
void ProcessTimeRangeDeleteDirectives(
HistoryBackend* history_backend,
const syncer::SyncDataList& time_range_directives);
@@ -378,7 +379,7 @@ bool DeleteDirectiveHandler::CreateDeleteDirectives(
global_id_directive->set_end_time_usec(end_time_usecs);
}
}
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
ProcessLocalDeleteDirective(delete_directive);
return !error.has_value();
}
@@ -392,12 +393,12 @@ bool DeleteDirectiveHandler::CreateUrlDeleteDirective(const GURL& url) {
url_directive->set_url(url.spec());
url_directive->set_end_time_usec(TimeToUnixUsec(base::Time::Now()));
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
ProcessLocalDeleteDirective(delete_directive);
return !error.has_value();
}
-base::Optional<syncer::ModelError>
+absl::optional<syncer::ModelError>
DeleteDirectiveHandler::ProcessLocalDeleteDirective(
const sync_pb::HistoryDeleteDirectiveSpecifics& delete_directive) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -433,7 +434,7 @@ void DeleteDirectiveHandler::WaitUntilReadyToSync(base::OnceClosure done) {
}
}
-base::Optional<syncer::ModelError>
+absl::optional<syncer::ModelError>
DeleteDirectiveHandler::MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
@@ -452,7 +453,7 @@ DeleteDirectiveHandler::MergeDataAndStartSyncing(
&internal_tracker_);
}
- return base::nullopt;
+ return absl::nullopt;
}
void DeleteDirectiveHandler::StopSyncing(syncer::ModelType type) {
@@ -461,7 +462,7 @@ void DeleteDirectiveHandler::StopSyncing(syncer::ModelType type) {
sync_processor_.reset();
}
-base::Optional<syncer::ModelError> DeleteDirectiveHandler::ProcessSyncChanges(
+absl::optional<syncer::ModelError> DeleteDirectiveHandler::ProcessSyncChanges(
const base::Location& from_here,
const syncer::SyncChangeList& change_list) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -496,7 +497,7 @@ base::Optional<syncer::ModelError> DeleteDirectiveHandler::ProcessSyncChanges(
&internal_tracker_);
}
- return base::nullopt;
+ return absl::nullopt;
}
void DeleteDirectiveHandler::FinishProcessing(
diff --git a/chromium/components/history/core/browser/sync/delete_directive_handler.h b/chromium/components/history/core/browser/sync/delete_directive_handler.h
index cdf2b1fcbf8..6316ba955e5 100644
--- a/chromium/components/history/core/browser/sync/delete_directive_handler.h
+++ b/chromium/components/history/core/browser/sync/delete_directive_handler.h
@@ -48,32 +48,32 @@ class DeleteDirectiveHandler : public syncer::SyncableService {
void OnBackendLoaded();
// Create delete directives for the deletion of visits identified by
- // |global_ids| (which may be empty), in the time range specified by
- // |begin_time| and |end_time|.
+ // `global_ids` (which may be empty), in the time range specified by
+ // `begin_time` and `end_time`.
bool CreateDeleteDirectives(const std::set<int64_t>& global_ids,
base::Time begin_time,
base::Time end_time);
bool CreateUrlDeleteDirective(const GURL& url);
- // Sends the given |delete_directive| to SyncChangeProcessor (if it exists).
+ // Sends the given `delete_directive` to SyncChangeProcessor (if it exists).
// Returns any error resulting from sending the delete directive to sync.
- // NOTE: the given |delete_directive| is not processed to remove local
+ // NOTE: the given `delete_directive` is not processed to remove local
// history entries that match. Caller still needs to call other
// interfaces, e.g. HistoryService::ExpireHistoryBetween(), to delete
// local history entries.
- base::Optional<syncer::ModelError> ProcessLocalDeleteDirective(
+ absl::optional<syncer::ModelError> ProcessLocalDeleteDirective(
const sync_pb::HistoryDeleteDirectiveSpecifics& delete_directive);
// syncer::SyncableService implementation.
void WaitUntilReadyToSync(base::OnceClosure done) override;
- base::Optional<syncer::ModelError> MergeDataAndStartSyncing(
+ absl::optional<syncer::ModelError> MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
std::unique_ptr<syncer::SyncErrorFactory> error_handler) override;
void StopSyncing(syncer::ModelType type) override;
- base::Optional<syncer::ModelError> ProcessSyncChanges(
+ absl::optional<syncer::ModelError> ProcessSyncChanges(
const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
@@ -85,7 +85,7 @@ class DeleteDirectiveHandler : public syncer::SyncableService {
enum PostProcessingAction { KEEP_AFTER_PROCESSING, DROP_AFTER_PROCESSING };
// Callback when history backend finishes deleting visits according to
- // |delete_directives|.
+ // `delete_directives`.
void FinishProcessing(PostProcessingAction post_processing_action,
const syncer::SyncDataList& delete_directives);
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 9d51f82e32b..68e0f9114cb 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
@@ -19,6 +19,7 @@
#include "components/history/core/browser/history_types.h"
#include "components/history/core/browser/in_memory_history_backend.h"
#include "components/history/core/test/test_history_database.h"
+#include "components/sync/base/client_tag_hash.h"
#include "components/sync/model/sync_error_factory.h"
#include "components/sync/test/model/fake_sync_change_processor.h"
#include "components/sync/test/model/sync_change_processor_wrapper_for_test.h"
@@ -121,6 +122,11 @@ class HistoryDeleteDirectiveHandlerTest : public testing::Test {
DeleteDirectiveHandler* handler() { return delete_directive_handler_.get(); }
+ // DeleteDirectiveHandler doesn't actually read the client tag, so a fake
+ // constant is used in tests.
+ const syncer::ClientTagHash kFakeClientTagHash =
+ syncer::ClientTagHash::FromHashed("unused");
+
private:
base::test::TaskEnvironment task_environment_;
base::ScopedTempDir test_dir_;
@@ -178,7 +184,7 @@ TEST_F(HistoryDeleteDirectiveHandlerTest,
std::unique_ptr<syncer::SyncErrorFactory>())
.has_value());
- base::Optional<syncer::ModelError> err =
+ absl::optional<syncer::ModelError> err =
handler()->ProcessLocalDeleteDirective(delete_directive);
EXPECT_FALSE(err.has_value());
EXPECT_EQ(1u, change_processor.changes().size());
@@ -215,7 +221,8 @@ TEST_F(HistoryDeleteDirectiveHandlerTest, ProcessGlobalIdDeleteDirective) {
.ToInternalValue());
global_id_directive->set_start_time_usec(3);
global_id_directive->set_end_time_usec(10);
- directives.push_back(syncer::SyncData::CreateRemoteData(entity_specs));
+ directives.push_back(
+ syncer::SyncData::CreateRemoteData(entity_specs, kFakeClientTagHash));
// 2nd directive.
global_id_directive->Clear();
@@ -224,7 +231,8 @@ TEST_F(HistoryDeleteDirectiveHandlerTest, ProcessGlobalIdDeleteDirective) {
.ToInternalValue());
global_id_directive->set_start_time_usec(13);
global_id_directive->set_end_time_usec(19);
- directives.push_back(syncer::SyncData::CreateRemoteData(entity_specs));
+ directives.push_back(
+ syncer::SyncData::CreateRemoteData(entity_specs, kFakeClientTagHash));
syncer::FakeSyncChangeProcessor change_processor;
EXPECT_FALSE(handler()
@@ -283,13 +291,15 @@ TEST_F(HistoryDeleteDirectiveHandlerTest, ProcessTimeRangeDeleteDirective) {
->mutable_time_range_directive();
time_range_directive->set_start_time_usec(2);
time_range_directive->set_end_time_usec(5);
- directives.push_back(syncer::SyncData::CreateRemoteData(entity_specs));
+ directives.push_back(
+ syncer::SyncData::CreateRemoteData(entity_specs, kFakeClientTagHash));
// 2nd directive.
time_range_directive->Clear();
time_range_directive->set_start_time_usec(8);
time_range_directive->set_end_time_usec(10);
- directives.push_back(syncer::SyncData::CreateRemoteData(entity_specs));
+ directives.push_back(
+ syncer::SyncData::CreateRemoteData(entity_specs, kFakeClientTagHash));
syncer::FakeSyncChangeProcessor change_processor;
EXPECT_FALSE(handler()
@@ -348,13 +358,15 @@ TEST_F(HistoryDeleteDirectiveHandlerTest, ProcessUrlDeleteDirective) {
entity_specs1.mutable_history_delete_directive()->mutable_url_directive();
url_directive->set_url(test_url1.spec());
url_directive->set_end_time_usec(8);
- directives.push_back(syncer::SyncData::CreateRemoteData(entity_specs1));
+ directives.push_back(
+ syncer::SyncData::CreateRemoteData(entity_specs1, kFakeClientTagHash));
sync_pb::EntitySpecifics entity_specs2;
url_directive =
entity_specs2.mutable_history_delete_directive()->mutable_url_directive();
url_directive->set_url(test_url2.spec());
url_directive->set_end_time_usec(8);
- directives.push_back(syncer::SyncData::CreateRemoteData(entity_specs2));
+ directives.push_back(
+ syncer::SyncData::CreateRemoteData(entity_specs2, kFakeClientTagHash));
syncer::FakeSyncChangeProcessor change_processor;
EXPECT_FALSE(handler()
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 16801b465c4..fe78e6c2f28 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
@@ -25,7 +25,7 @@ class HistoryDeleteDirectivesModelTypeController
: public syncer::SyncableServiceBasedModelTypeController,
public syncer::SyncServiceObserver {
public:
- // |sync_service| and |history_service| must not be null and must outlive this
+ // `sync_service` and `history_service` must not be null and must outlive this
// object.
HistoryDeleteDirectivesModelTypeController(
const base::RepeatingClosure& dump_stack,
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 eb09078de81..dd3f8979478 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
@@ -8,6 +8,7 @@
#include "base/auto_reset.h"
#include "base/big_endian.h"
+#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "components/sync/model/mutable_data_batch.h"
@@ -98,7 +99,7 @@ TypedURLSyncBridge::CreateMetadataChangeList() {
sync_metadata_database_, syncer::TYPED_URLS);
}
-base::Optional<ModelError> TypedURLSyncBridge::MergeSyncData(
+absl::optional<ModelError> TypedURLSyncBridge::MergeSyncData(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_data) {
DCHECK(sequence_checker_.CalledOnValidSequence());
@@ -123,7 +124,7 @@ base::Optional<ModelError> TypedURLSyncBridge::MergeSyncData(
// Iterate through entity_data and check for all the urls that
// sync already knows about. MergeURLWithSync() will remove urls that
- // are the same as the synced ones from |new_db_urls|.
+ // are the same as the synced ones from `new_db_urls`.
for (const std::unique_ptr<EntityChange>& entity_change : entity_data) {
DCHECK(entity_change->data().specifics.has_typed_url());
const TypedUrlSpecifics& specifics =
@@ -147,7 +148,7 @@ base::Optional<ModelError> TypedURLSyncBridge::MergeSyncData(
&updated_synced_urls);
}
- base::Optional<ModelError> error =
+ absl::optional<ModelError> error =
WriteToHistoryBackend(&new_synced_urls, &updated_synced_urls, nullptr,
&new_synced_visits, nullptr);
if (error)
@@ -180,7 +181,7 @@ base::Optional<ModelError> TypedURLSyncBridge::MergeSyncData(
->TakeError();
}
-base::Optional<ModelError> TypedURLSyncBridge::ApplySyncChanges(
+absl::optional<ModelError> TypedURLSyncBridge::ApplySyncChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_changes) {
DCHECK(sequence_checker_.CalledOnValidSequence());
@@ -198,7 +199,7 @@ base::Optional<ModelError> TypedURLSyncBridge::ApplySyncChanges(
entity_change->storage_key());
if (!history_backend_->GetURLByID(url_id, &url_row)) {
// Ignoring the case that there is no matching URLRow with URLID
- // |url_id|.
+ // `url_id`.
continue;
}
@@ -224,7 +225,7 @@ base::Optional<ModelError> TypedURLSyncBridge::ApplySyncChanges(
&updated_synced_urls, &new_synced_urls);
}
- base::Optional<ModelError> error = WriteToHistoryBackend(
+ absl::optional<ModelError> error = WriteToHistoryBackend(
&new_synced_urls, &updated_synced_urls, &pending_deleted_urls,
&new_synced_visits, &deleted_visits);
if (error)
@@ -262,7 +263,7 @@ void TypedURLSyncBridge::GetData(StorageKeyList storage_keys,
URLID url_id = TypedURLSyncMetadataDatabase::StorageKeyToURLID(key);
if (!history_backend_->GetURLByID(url_id, &url_row)) {
- // Ignoring the case which no matching URLRow with URLID |url_id|.
+ // Ignoring the case which no matching URLRow with URLID `url_id`.
DLOG(ERROR) << "Could not find URL for id: " << url_id;
continue;
}
@@ -775,7 +776,7 @@ void TypedURLSyncBridge::MergeURLWithSync(
bool is_existing_url =
history_backend_->GetURL(untyped_url.url(), &untyped_url);
if (is_existing_url) {
- // Add a new entry to |local_typed_urls|, and set the iterator to it.
+ // Add a new entry to `local_typed_urls`, and set the iterator to it.
VisitVector untyped_visits;
if (!FixupURLAndGetVisits(&untyped_url, &untyped_visits)) {
return;
@@ -785,7 +786,7 @@ void TypedURLSyncBridge::MergeURLWithSync(
// Store row info that will be used to update sync's visits.
(*local_typed_urls)[untyped_url.url()] = untyped_url;
- // Set iterator |it| to point to this entry.
+ // Set iterator `it` to point to this entry.
it = local_typed_urls->find(untyped_url.url());
DCHECK(it != local_typed_urls->end());
// Continue with merge below.
@@ -821,7 +822,7 @@ void TypedURLSyncBridge::MergeURLWithSync(
// Empty URLs should be filtered out by ShouldIgnoreUrl() previously.
DCHECK(!it->second.url().spec().empty());
- // Initialize fields in |new_url| to the same values as the fields in
+ // Initialize fields in `new_url` to the same values as the fields in
// the existing URLRow in the history DB. This is needed because we
// overwrite the existing value in WriteToHistoryBackend(), but some of
// the values in that structure are not synced (like typed_count).
@@ -926,7 +927,7 @@ void TypedURLSyncBridge::UpdateSyncFromLocal(
// If the URL has no typed visits any more we should get rid of it. It is
// possible that this URL never had typed visits and thus it has no sync
// entity and no sync metadata. We do not need to check for this case
- // as all the code below is no-op if there is no sync metadata for |row|.
+ // as all the code below is no-op if there is no sync metadata for `row`.
if (is_from_expiration) {
// Only remove its metadata as we do not sync up deletions for expired
// entities (see the comment in OnURLsDeleted()).
@@ -942,13 +943,13 @@ void TypedURLSyncBridge::UpdateSyncFromLocal(
void TypedURLSyncBridge::ExpireMetadataForURL(const URLRow& row) {
std::string storage_key = GetStorageKeyFromURLRow(row);
// The following functions need to tolerate if there exists no metadata
- // for |storage_key| as we might call this function multiple times for a given
+ // for `storage_key` as we might call this function multiple times for a given
// url.
sync_metadata_database_->ClearSyncMetadata(syncer::TYPED_URLS, storage_key);
change_processor()->UntrackEntityForStorageKey(storage_key);
}
-base::Optional<ModelError> TypedURLSyncBridge::WriteToHistoryBackend(
+absl::optional<ModelError> TypedURLSyncBridge::WriteToHistoryBackend(
const URLRows* new_urls,
const URLRows* updated_urls,
const std::vector<GURL>* deleted_urls,
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 af10e38296b..9b31f1e5bcf 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
@@ -26,7 +26,7 @@ namespace history {
class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
public HistoryBackendObserver {
public:
- // |sync_metadata_store| is owned by |history_backend|, and must outlive
+ // `sync_metadata_store` is owned by `history_backend`, and must outlive
// TypedURLSyncBridge.
TypedURLSyncBridge(
HistoryBackend* history_backend,
@@ -37,10 +37,10 @@ class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
// syncer::ModelTypeSyncBridge implementation.
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
@@ -88,7 +88,7 @@ class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
typedef std::map<GURL, URLRow> TypedURLMap;
// This is a helper map used to associate visit vectors from the history db
- // to the typed urls in the above map |TypedURLMap|.
+ // to the typed urls in the above map `TypedURLMap`.
typedef std::map<GURL, VisitVector> URLVisitVectorMap;
// Bitfield returned from MergeUrls to specify the result of a merge.
@@ -98,14 +98,14 @@ class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
static const MergeResult DIFF_LOCAL_ROW_CHANGED = 1 << 1;
static const MergeResult DIFF_LOCAL_VISITS_ADDED = 1 << 2;
- // Merges the URL information in |typed_url| with the URL information from the
- // history database in |url| and |visits|, and returns a bitmask with the
+ // Merges the URL information in `typed_url` with the URL information from the
+ // history database in `url` and `visits`, and returns a bitmask with the
// results of the merge:
- // DIFF_UPDATE_NODE - changes have been made to |new_url| and |visits| which
+ // DIFF_UPDATE_NODE - changes have been made to `new_url` and `visits` which
// should be persisted to the sync node.
- // DIFF_LOCAL_ROW_CHANGED - The history data in |new_url| should be persisted
+ // DIFF_LOCAL_ROW_CHANGED - The history data in `new_url` should be persisted
// to the history DB.
- // DIFF_LOCAL_VISITS_ADDED - |new_visits| contains a list of visits that
+ // DIFF_LOCAL_VISITS_ADDED - `new_visits` contains a list of visits that
// should be written to the history DB for this URL. Deletions are not
// written to the DB - each client is left to age out visits on their own.
static MergeResult MergeUrls(const sync_pb::TypedUrlSpecifics& typed_url,
@@ -115,16 +115,16 @@ class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
std::vector<VisitInfo>* new_visits);
// Diffs the set of visits between the history DB and the sync DB, using the
- // sync DB as the canonical copy. Result is the set of |new_visits| and
- // |removed_visits| that can be applied to the history DB to make it match
- // the sync DB version. |removed_visits| can be null if the caller does not
+ // sync DB as the canonical copy. Result is the set of `new_visits` and
+ // `removed_visits` that can be applied to the history DB to make it match
+ // the sync DB version. `removed_visits` can be null if the caller does not
// care about which visits to remove.
static void DiffVisits(const VisitVector& history_visits,
const sync_pb::TypedUrlSpecifics& sync_specifics,
std::vector<VisitInfo>* new_visits,
VisitVector* removed_visits);
- // Fills |new_url| with formatted data from |typed_url|.
+ // Fills `new_url` with formatted data from `typed_url`.
static void UpdateURLRowFromTypedUrlSpecifics(
const sync_pb::TypedUrlSpecifics& typed_url,
URLRow* new_url);
@@ -133,7 +133,7 @@ class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
// pass it to the processor so that it can start tracking changes.
void LoadMetadata();
- // Compares |server_typed_url| from the server against local history to decide
+ // Compares `server_typed_url` from the server against local history to decide
// how to merge any existing data, and updates appropriate data containers to
// write to server and backend.
void MergeURLWithSync(const sync_pb::TypedUrlSpecifics& server_typed_url,
@@ -146,9 +146,9 @@ class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
// Given a typed URL in the sync DB, looks for an existing entry in the
// local history DB and generates a list of visits to add to the
// history DB to bring it up to date (avoiding duplicates).
- // Updates the passed |visits_to_add| and |visits_to_remove| vectors with the
+ // Updates the passed `visits_to_add` and `visits_to_remove` vectors with the
// visits to add to/remove from the history DB, and adds a new entry to either
- // |updated_urls| or |new_urls| depending on whether the URL already existed
+ // `updated_urls` or `new_urls` depending on whether the URL already existed
// in the history DB.
void UpdateFromSync(const sync_pb::TypedUrlSpecifics& typed_url,
TypedURLVisitVector* visits_to_add,
@@ -157,20 +157,20 @@ class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
URLRows* new_urls);
// Utility routine that (a) updates an existing sync node or (b) creates a
- // new one for the passed |typed_url| if one does not already exist or (c)
- // removes metadata for |row| if |is_from_expiration| is true and the |row|
+ // new one for the passed `typed_url` if one does not already exist or (c)
+ // removes metadata for `row` if `is_from_expiration` is true and the `row`
// has no more typed visits.
void UpdateSyncFromLocal(URLRow row,
bool is_from_expiration,
syncer::MetadataChangeList* metadata_change_list);
- // Deletes metadata for an expired URL |row| but does not send up the deletion
+ // Deletes metadata for an expired URL `row` but does not send up the deletion
// to the server (each client expires them independently). It is an no-op when
// called on an url with already expired metadata.
void ExpireMetadataForURL(const URLRow& row);
// Writes new typed url data from sync server to history backend.
- base::Optional<syncer::ModelError> WriteToHistoryBackend(
+ absl::optional<syncer::ModelError> WriteToHistoryBackend(
const URLRows* new_urls,
const URLRows* updated_urls,
const std::vector<GURL>* deleted_urls,
@@ -201,21 +201,21 @@ class TypedURLSyncBridge : public syncer::ModelTypeSyncBridge,
// function compensates for the fact that the history DB has rather poor data
// integrity (duplicate visits, visit timestamps that don't match the
// last_visit timestamp, huge data sets that exhaust memory when fetched,
- // expired visits that are not deleted by |ExpireHistoryBackend|, etc) by
- // modifying the passed |url| object and |visits| vector. The order of
- // |visits| will be from the oldest to the newest order.
+ // expired visits that are not deleted by `ExpireHistoryBackend`, etc) by
+ // modifying the passed `url` object and `visits` vector. The order of
+ // `visits` will be from the oldest to the newest order.
// Returns false in two cases.
// 1. we could not fetch the visits for the passed URL, DB error.
// 2. No visits for the passed url, or all the visits are expired.
bool FixupURLAndGetVisits(URLRow* url, VisitVector* visits);
- // Create an EntityData by URL |row| and its visits |visits|.
+ // Create an EntityData by URL `row` and its visits `visits`.
std::unique_ptr<syncer::EntityData> CreateEntityData(
const URLRow& row,
const VisitVector& visits);
// Get all the typed urls and visits from the history db, after filtering
- // them, put them into |url_to_visit| and |url_to_urlrow|.
+ // them, put them into `url_to_visit` and `url_to_urlrow`.
// Return false if cannot get urls from HistoryBackend.
bool GetValidURLsAndVisits(URLVisitVectorMap* url_to_visit,
TypedURLMap* url_to_urlrow);
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 babb09f8c4b..352867630c2 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
@@ -142,8 +142,8 @@ void AddOldestVisit(ui::PageTransition transition,
url->set_visit_count(visits->size());
}
-// Create a new row object and the typed visit çorresponding with the time at
-// |last_visit| in the |visits| vector.
+// Create a new row object and the typed visit corresponding with the time at
+// `last_visit` in the `visits` vector.
URLRow MakeTypedUrlRow(const std::string& url,
const std::string& title,
int typed_count,
@@ -161,11 +161,11 @@ URLRow MakeTypedUrlRow(const std::string& url,
history_url.set_last_visit(last_visit_time);
if (typed_count > 0) {
- // Add a typed visit for time |last_visit_time|.
+ // Add a typed visit for time `last_visit_time`.
visits->push_back(VisitRow(history_url.id(), last_visit_time, 0,
ui::PAGE_TRANSITION_TYPED, 0, true, false));
} else {
- // Add a non-typed visit for time |last_visit_time|.
+ // Add a non-typed visit for time `last_visit_time`.
visits->push_back(VisitRow(history_url.id(), last_visit_time, 0,
ui::PAGE_TRANSITION_RELOAD, 0, false, false));
}
@@ -197,7 +197,7 @@ URLRow MakeTypedUrlRowWithTwoVisits(const std::string& url,
visits->push_back(VisitRow(history_url.id(), typed_visit_time, 0,
ui::PAGE_TRANSITION_TYPED, 0, true, false));
- // Add a non-typed visit for time |last_visit|.
+ // Add a non-typed visit for time `last_visit`.
visits->push_back(VisitRow(history_url.id(), reload_visit_time, 0,
ui::PAGE_TRANSITION_RELOAD, 0, false, false));
return history_url;
@@ -266,9 +266,9 @@ class TestHistoryBackendDelegate : public HistoryBackend::Delegate {
DISALLOW_COPY_AND_ASSIGN(TestHistoryBackendDelegate);
};
-class TestHistoryBackend : public HistoryBackend {
+class TestHistoryBackendForSync : public HistoryBackend {
public:
- TestHistoryBackend()
+ TestHistoryBackendForSync()
: HistoryBackend(std::make_unique<TestHistoryBackendDelegate>(),
nullptr,
base::ThreadTaskRunnerHandle::Get()) {}
@@ -297,7 +297,7 @@ class TestHistoryBackend : public HistoryBackend {
}
private:
- ~TestHistoryBackend() override {}
+ ~TestHistoryBackendForSync() override {}
};
} // namespace
@@ -305,7 +305,7 @@ class TestHistoryBackend : public HistoryBackend {
class TypedURLSyncBridgeTest : public testing::Test {
public:
void SetUp() override {
- fake_history_backend_ = new TestHistoryBackend();
+ fake_history_backend_ = new TestHistoryBackendForSync();
ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
fake_history_backend_->Init(
false, TestHistoryDatabaseParamsForPath(test_dir_.GetPath()));
@@ -323,7 +323,7 @@ class TypedURLSyncBridgeTest : public testing::Test {
fake_history_backend_->Closing();
}
- // Starts sync for |typed_url_sync_bridge_| with |initial_data| as the
+ // Starts sync for `typed_url_sync_bridge_` with `initial_data` as the
// initial sync data.
void StartSyncing(const std::vector<TypedUrlSpecifics>& specifics) {
ON_CALL(mock_processor_, IsTrackingMetadata()).WillByDefault(Return(true));
@@ -415,7 +415,7 @@ class TypedURLSyncBridgeTest : public testing::Test {
void RemoveObserver() { bridge()->history_backend_observation_.Reset(); }
- // Fills |specifics| with the sync data for |url| and |visits|.
+ // Fills `specifics` with the sync data for `url` and `visits`.
static bool WriteToTypedUrlSpecifics(const URLRow& url,
const VisitVector& visits,
TypedUrlSpecifics* specifics) {
@@ -517,7 +517,7 @@ class TypedURLSyncBridgeTest : public testing::Test {
protected:
base::test::SingleThreadTaskEnvironment task_environment_;
base::ScopedTempDir test_dir_;
- scoped_refptr<TestHistoryBackend> fake_history_backend_;
+ scoped_refptr<TestHistoryBackendForSync> fake_history_backend_;
TypedURLSyncBridge* typed_url_sync_bridge_ = nullptr;
NiceMock<MockModelTypeChangeProcessor> mock_processor_;
};
@@ -1150,7 +1150,7 @@ TEST_F(TypedURLSyncBridgeTest, MaxVisitLocalTypedUrl) {
URLRow url_row = url_rows.front();
VisitVector visits;
- // Add |kMaxTypedUrlVisits| + 10 visits to the url. The 10 oldest
+ // Add `kMaxTypedUrlVisits` + 10 visits to the url. The 10 oldest
// non-typed visits are expected to be skipped.
int i = 1;
for (; i <= kMaxTypedUrlVisits - 20; ++i)
diff --git a/chromium/components/history/core/browser/sync/typed_url_sync_metadata_database.cc b/chromium/components/history/core/browser/sync/typed_url_sync_metadata_database.cc
index 1f76bce86b5..241e3d0e316 100644
--- a/chromium/components/history/core/browser/sync/typed_url_sync_metadata_database.cc
+++ b/chromium/components/history/core/browser/sync/typed_url_sync_metadata_database.cc
@@ -131,15 +131,15 @@ bool TypedURLSyncMetadataDatabase::
"SELECT storage_key FROM typed_url_sync_metadata ORDER BY storage_key"));
while (sorted_metadata_rowids.Step()) {
URLID metadata_rowid = sorted_metadata_rowids.ColumnInt64(0);
- // Both collections are sorted, we check whether |metadata_rowid| is valid
+ // Both collections are sorted, we check whether `metadata_rowid` is valid
// by iterating both at the same time.
- // First, skip all valid IDs that are omitted in |sorted_metadata_rowids|.
+ // First, skip all valid IDs that are omitted in `sorted_metadata_rowids`.
while (valid_rowids_iter != sorted_valid_rowids.end() &&
*valid_rowids_iter < metadata_rowid) {
valid_rowids_iter++;
}
- // Now, is |metadata_rowid| invalid?
+ // Now, is `metadata_rowid` invalid?
if (valid_rowids_iter == sorted_valid_rowids.end() ||
*valid_rowids_iter != metadata_rowid) {
invalid_metadata_rowids.push_back(metadata_rowid);
diff --git a/chromium/components/history/core/browser/sync/typed_url_sync_metadata_database.h b/chromium/components/history/core/browser/sync/typed_url_sync_metadata_database.h
index e49c9c5359c..b3d10bdc556 100644
--- a/chromium/components/history/core/browser/sync/typed_url_sync_metadata_database.h
+++ b/chromium/components/history/core/browser/sync/typed_url_sync_metadata_database.h
@@ -32,7 +32,7 @@ class TypedURLSyncMetadataDatabase : public syncer::SyncMetadataStore {
TypedURLSyncMetadataDatabase();
~TypedURLSyncMetadataDatabase() override;
- // Read all the stored metadata for typed URL and fill |metadata_batch|
+ // Read all the stored metadata for typed URL and fill `metadata_batch`
// with it.
bool GetAllSyncMetadata(syncer::MetadataBatch* metadata_batch);
@@ -63,7 +63,7 @@ class TypedURLSyncMetadataDatabase : public syncer::SyncMetadataStore {
bool InitSyncTable();
// Cleans up orphaned metadata for typed URLs, i.e. deletes all metadata
- // entries for rowids not present in |sorted_valid_rowids| (which must be
+ // entries for rowids not present in `sorted_valid_rowids` (which must be
// sorted in ascending order). Returns true if the clean up finishes without
// any DB error.
bool CleanTypedURLOrphanedMetadataForMigrationToVersion40(
@@ -71,10 +71,10 @@ class TypedURLSyncMetadataDatabase : public syncer::SyncMetadataStore {
private:
// Read all sync_pb::EntityMetadata for typed URL and fill
- // |metadata_records| with it.
+ // `metadata_records` with it.
bool GetAllSyncEntityMetadata(syncer::MetadataBatch* metadata_batch);
- // Read sync_pb::ModelTypeState for typed URL and fill |state| with it.
+ // Read sync_pb::ModelTypeState for typed URL and fill `state` with it.
bool GetModelTypeState(sync_pb::ModelTypeState* state);
DISALLOW_COPY_AND_ASSIGN(TypedURLSyncMetadataDatabase);
diff --git a/chromium/components/history/core/browser/top_sites.h b/chromium/components/history/core/browser/top_sites.h
index 481728b1770..58661166a46 100644
--- a/chromium/components/history/core/browser/top_sites.h
+++ b/chromium/components/history/core/browser/top_sites.h
@@ -86,7 +86,7 @@ class TopSites : public RefcountedKeyedService {
// Returns the set of prepopulated pages.
virtual PrepopulatedPageList GetPrepopulatedPages() = 0;
- // Called when user has navigated to |url|.
+ // Called when user has navigated to `url`.
virtual void OnNavigationCommitted(const GURL& url) = 0;
// Add Observer to the list.
diff --git a/chromium/components/history/core/browser/top_sites_database.cc b/chromium/components/history/core/browser/top_sites_database.cc
index 3da74a93d16..cc2d038df24 100644
--- a/chromium/components/history/core/browser/top_sites_database.cc
+++ b/chromium/components/history/core/browser/top_sites_database.cc
@@ -160,7 +160,7 @@ void FixTopSitesTable(sql::Database* db, int version) {
sql::Statement update_statement(db->GetUniqueStatement(
base::StringPrintf(kAdjustRankSql, kTableName).c_str()));
- // Update any rows where |next_rank| doesn't match |url_rank|.
+ // Update any rows where `next_rank` doesn't match `url_rank`.
int next_rank = 0;
bool adjusted = false;
while (select_statement.Step()) {
@@ -246,7 +246,7 @@ void DatabaseErrorCallback(sql::Database* db,
// Prevent reentrant calls.
db->reset_error_callback();
- // After this call, the |db| handle is poisoned so that future calls will
+ // After this call, the `db` handle is poisoned so that future calls will
// return errors until the handle is re-opened.
RecoverAndFixup(db, db_path);
diff --git a/chromium/components/history/core/browser/top_sites_database.h b/chromium/components/history/core/browser/top_sites_database.h
index f97d43ac587..6078cd1bd1a 100644
--- a/chromium/components/history/core/browser/top_sites_database.h
+++ b/chromium/components/history/core/browser/top_sites_database.h
@@ -6,7 +6,6 @@
#define COMPONENTS_HISTORY_CORE_BROWSER_TOP_SITES_DATABASE_H_
#include <map>
-#include <string>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -33,7 +32,7 @@ class TopSitesDatabase {
// Returns true on success. If false, no other functions should be called.
bool Init(const base::FilePath& db_name);
- // Updates the database according to the changes recorded in |delta|.
+ // Updates the database according to the changes recorded in `delta`.
void ApplyDelta(const TopSitesDelta& delta);
// Returns a list of all URLs currently in the table.
@@ -61,7 +60,7 @@ class TopSitesDatabase {
// was successful.
bool UpgradeToVersion4();
- // Sets a top site for the URL. |new_rank| is the position of the URL in the
+ // Sets a top site for the URL. `new_rank` is the position of the URL in the
// list of top sites, zero-based.
// If the URL is not in the table, adds it. If it is, updates its rank and
// shifts the ranks of other URLs if necessary. Should be called within an
@@ -75,7 +74,7 @@ class TopSitesDatabase {
// Returns true if the database query succeeds.
bool UpdateSite(const MostVisitedURL& url);
- // Returns |url|'s current rank or kRankOfNonExistingURL if not present.
+ // Returns `url`'s current rank or kRankOfNonExistingURL if not present.
int GetURLRank(const MostVisitedURL& url);
// Sets the rank for a given URL. The URL must be in the database. Should be
diff --git a/chromium/components/history/core/browser/top_sites_impl.cc b/chromium/components/history/core/browser/top_sites_impl.cc
index 8d27ae605d1..9db45ba9335 100644
--- a/chromium/components/history/core/browser/top_sites_impl.cc
+++ b/chromium/components/history/core/browser/top_sites_impl.cc
@@ -46,7 +46,7 @@ void RunOrPostGetMostVisitedURLsCallback(
task_runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback), urls));
}
-// Checks if the titles stored in |old_list| and |new_list| have changes.
+// Checks if the titles stored in `old_list` and `new_list` have changes.
bool DoTitlesDiffer(const MostVisitedURLList& old_list,
const MostVisitedURLList& new_list) {
// If the two lists have different sizes, the most visited titles are
@@ -145,7 +145,7 @@ void TopSitesImpl::SyncWithHistory() {
bool TopSitesImpl::HasBlockedUrls() const {
const base::DictionaryValue* blocked_urls =
pref_service_->GetDictionary(kBlockedUrlsPrefsKey);
- return blocked_urls && !blocked_urls->empty();
+ return blocked_urls && !blocked_urls->DictEmpty();
}
void TopSitesImpl::AddBlockedUrl(const GURL& url) {
@@ -155,7 +155,8 @@ void TopSitesImpl::AddBlockedUrl(const GURL& url) {
{
DictionaryPrefUpdate update(pref_service_, kBlockedUrlsPrefsKey);
base::DictionaryValue* blocked_urls = update.Get();
- blocked_urls->SetWithoutPathExpansion(GetURLHash(url), std::move(dummy));
+ blocked_urls->SetKey(GetURLHash(url),
+ base::Value::FromUniquePtrValue(std::move(dummy)));
}
ResetThreadSafeCache();
@@ -371,7 +372,7 @@ int TopSitesImpl::num_results_to_request_from_history() const {
const base::DictionaryValue* blocked_urls =
pref_service_->GetDictionary(kBlockedUrlsPrefsKey);
- return kTopSitesNumber + (blocked_urls ? blocked_urls->size() : 0);
+ return kTopSitesNumber + (blocked_urls ? blocked_urls->DictSize() : 0);
}
void TopSitesImpl::MoveStateToLoaded() {
@@ -419,7 +420,7 @@ void TopSitesImpl::ScheduleUpdateTimer() {
void TopSitesImpl::OnGotMostVisitedURLs(MostVisitedURLList sites) {
DCHECK(thread_checker_.CalledOnValidThread());
- // Set |top_sites_| directly so that SetTopSites() diffs correctly.
+ // Set `top_sites_` directly so that SetTopSites() diffs correctly.
top_sites_ = sites;
SetTopSites(std::move(sites), CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_URLS);
diff --git a/chromium/components/history/core/browser/top_sites_impl.h b/chromium/components/history/core/browser/top_sites_impl.h
index 168912b2d3d..62171bf52ec 100644
--- a/chromium/components/history/core/browser/top_sites_impl.h
+++ b/chromium/components/history/core/browser/top_sites_impl.h
@@ -18,7 +18,6 @@
#include "base/synchronization/lock.h"
#include "base/task/cancelable_task_tracker.h"
#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"
@@ -111,11 +110,11 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// Generates the diff of things that happened between "old" and "new."
//
// The URLs that are in "new" but not "old" will be have their index from
- // "new" placed in |added_urls|. The URLs that are in "old" but not "new" will
- // have their index from "old" placed in |deleted_urls|.
+ // "new" placed in `added_urls`. The URLs that are in "old" but not "new" will
+ // have their index from "old" placed in `deleted_urls`.
//
// URLs that appear in both lists but have different indices will have their
- // index from "new" placed in |moved_urls|.
+ // index from "new" placed in `moved_urls`.
static void DiffMostVisited(const MostVisitedURLList& old_list,
const MostVisitedURLList& new_list,
TopSitesDelta* delta);
@@ -123,15 +122,15 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
// Adds prepopulated pages to TopSites. Returns true if any pages were added.
bool AddPrepopulatedPages(MostVisitedURLList* urls) const;
- // Takes |urls|, produces it's copy in |out| after removing blocked urls.
+ // Takes `urls`, produces it's copy in `out` after removing blocked urls.
// Also ensures we respect the maximum number TopSites URLs.
MostVisitedURLList ApplyBlockedUrls(const MostVisitedURLList& urls);
// Returns an MD5 hash of the URL. Hashing is required for blocking urls.
static std::string GetURLHash(const GURL& url);
- // Updates URLs in |cache_| and the db (in the background). The URLs in
- // |new_top_sites| replace those in |cache_|. All mutations to cache_ *must*
+ // Updates URLs in `cache_` and the db (in the background). The URLs in
+ // `new_top_sites` replace those in `cache_`. All mutations to cache_ *must*
// go through this. Should be called from the UI thread.
void SetTopSites(MostVisitedURLList new_top_sites,
const CallLocation location);
@@ -167,15 +166,15 @@ class TopSitesImpl : public TopSites, public HistoryServiceObserver {
scoped_refptr<TopSitesBackend> backend_;
- // Lock used to access |thread_safe_cache_|.
+ // Lock used to access `thread_safe_cache_`.
mutable base::Lock lock_;
// The top sites data.
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 blocked urls
- // applied (|top_sites_| does not).
+ // you hold `lock_`). The data in `thread_safe_cache_` has blocked urls
+ // applied (`top_sites_` does not).
MostVisitedURLList thread_safe_cache_ GUARDED_BY(lock_);
// Task tracker for history and backend requests.
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 6fb350ae8eb..fe86326bc84 100644
--- a/chromium/components/history/core/browser/top_sites_impl_unittest.cc
+++ b/chromium/components/history/core/browser/top_sites_impl_unittest.cc
@@ -47,7 +47,7 @@ const char kApplicationScheme[] = "application";
const char kPrepopulatedPageURL[] =
"http://www.google.com/int/chrome/welcome.html";
-// Returns whether |url| can be added to history.
+// Returns whether `url` can be added to history.
bool MockCanAddURLToHistory(const GURL& url) {
return url.is_valid() && !url.SchemeIs(kApplicationScheme);
}
@@ -59,7 +59,7 @@ class TopSitesQuerier {
public:
TopSitesQuerier() : number_of_callbacks_(0), waiting_(false) {}
- // Queries top sites. If |wait| is true a nested run loop is run until the
+ // Queries top sites. If `wait` is true a nested run loop is run until the
// callback is notified.
void QueryTopSites(TopSitesImpl* top_sites, bool wait) {
int start_number_of_callbacks = number_of_callbacks_;
@@ -149,7 +149,7 @@ class TopSitesImplTest : public HistoryUnitTestBase {
}
// Returns true if the TopSitesQuerier contains the prepopulate data starting
- // at |start_index|.
+ // at `start_index`.
void ContainsPrepopulatePages(const TopSitesQuerier& querier,
size_t start_index) {
PrepopulatedPageList prepopulate_pages = GetPrepopulatedPages();
@@ -308,7 +308,7 @@ TEST_F(TopSitesImplTest, DoTitlesDiffer) {
SetTopSites(list_1);
EXPECT_FALSE(observer.is_notified());
- // Change |url_2|'s title to |title_1| in list_2. The two lists are different
+ // Change `url_2`'s title to `title_1` in list_2. The two lists are different
// in titles now. TopSites should notify its observers.
list_2.pop_back();
list_2.emplace_back(url_2, title_1);
diff --git a/chromium/components/history/core/browser/url_database.cc b/chromium/components/history/core/browser/url_database.cc
index 63b02c050bd..98d056b29e0 100644
--- a/chromium/components/history/core/browser/url_database.cc
+++ b/chromium/components/history/core/browser/url_database.cc
@@ -10,7 +10,6 @@
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
@@ -29,11 +28,9 @@ URLDatabase::URLEnumeratorBase::URLEnumeratorBase()
: initialized_(false) {
}
-URLDatabase::URLEnumeratorBase::~URLEnumeratorBase() {
-}
+URLDatabase::URLEnumeratorBase::~URLEnumeratorBase() = default;
-URLDatabase::URLEnumerator::URLEnumerator() {
-}
+URLDatabase::URLEnumerator::URLEnumerator() = default;
bool URLDatabase::URLEnumerator::GetNextURL(URLRow* r) {
if (statement_.Step()) {
@@ -47,8 +44,7 @@ URLDatabase::URLDatabase()
: has_keyword_search_terms_(false) {
}
-URLDatabase::~URLDatabase() {
-}
+URLDatabase::~URLDatabase() = default;
// Convenience to fill a URLRow. Must be in sync with the fields in
// kURLRowFields.
@@ -159,7 +155,7 @@ bool URLDatabase::UpdateURLRow(URLID url_id, const URLRow& info) {
URLID URLDatabase::AddURLInternal(const URLRow& info, bool is_temporary) {
// This function is used to insert into two different tables, so we have to
- // do some shuffling. Unfortinately, we can't use the macro
+ // do some shuffling. Unfortunately, we can't use the macro
// HISTORY_URL_ROW_FIELDS because that specifies the table name which is
// invalid in the insert syntax.
#define ADDURL_COMMON_SUFFIX \
@@ -211,7 +207,7 @@ bool URLDatabase::URLTableContainsAutoincrement() {
std::string urls_schema = statement.ColumnString(0);
// We check if the whole schema contains "AUTOINCREMENT", since
// "AUTOINCREMENT" only can be used for "INTEGER PRIMARY KEY", so we assume no
- // other columns could cantain "AUTOINCREMENT".
+ // other columns could contain "AUTOINCREMENT".
return urls_schema.find("AUTOINCREMENT") != std::string::npos;
}
@@ -363,13 +359,13 @@ bool URLDatabase::IsTypedHost(const std::string& host, std::string* scheme) {
url::kFtpScheme
};
URLRows dummy;
- for (size_t i = 0; i < base::size(schemes); ++i) {
- std::string scheme_and_host(schemes[i]);
+ for (const char* known_scheme : schemes) {
+ std::string scheme_and_host(known_scheme);
scheme_and_host += url::kStandardSchemeSeparator + host;
if (AutocompleteForPrefix(scheme_and_host + '/', 1, true, &dummy) ||
AutocompleteForPrefix(scheme_and_host + ':', 1, true, &dummy)) {
if (scheme != nullptr)
- *scheme = schemes[i];
+ *scheme = known_scheme;
return true;
}
}
@@ -382,7 +378,7 @@ bool URLDatabase::FindShortestURLFromBase(const std::string& base,
int min_typed,
bool allow_base,
URLRow* info) {
- // Select URLs that start with |base| and are prefixes of |url|. All parts
+ // Select URLs that start with `base` and are prefixes of `url`. All parts
// of this query except the substr() call can be done using the index. We
// could do this query with a couple of LIKE or GLOB statements as well, but
// those wouldn't use the index, and would run into problems with "wildcard"
@@ -736,7 +732,7 @@ bool URLDatabase::CreateURLTable(bool is_temporary) {
sql.append(name);
sql.append(
"("
- // The id uses AUTOINCREMENT is for sync propose. Sync uses this |id| as
+ // The id uses AUTOINCREMENT is for sync propose. Sync uses this `id` as
// an unique key to identify the URLs. If here did not use AUTOINCREMENT,
// and Sync was not working somehow, a ROWID could be deleted and re-used
// during this period. Once Sync come back, Sync would use ROWIDs and
@@ -760,7 +756,7 @@ bool URLDatabase::CreateURLTable(bool is_temporary) {
"typed_count INTEGER DEFAULT 0 NOT NULL,"
"last_visit_time INTEGER NOT NULL,"
"hidden INTEGER DEFAULT 0 NOT NULL)");
- // IMPORTANT: If you change the colums, also update in_memory_database.cc
+ // IMPORTANT: If you change the columns, also update in_memory_database.cc
// where the values are copied (InitFromDisk).
return GetDB().Execute(sql.c_str());
diff --git a/chromium/components/history/core/browser/url_database.h b/chromium/components/history/core/browser/url_database.h
index 2f4d8160158..34f6a4f17eb 100644
--- a/chromium/components/history/core/browser/url_database.h
+++ b/chromium/components/history/core/browser/url_database.h
@@ -72,7 +72,7 @@ class URLDatabase {
bool UpdateURLRow(URLID url_id, const URLRow& info);
// Adds a line to the URL database with the given information and returns the
- // newly generated ID for the row (the |id| in |info| is ignored). A row with
+ // newly generated ID for the row (the `id` in `info` is ignored). A row with
// the given URL must not exist. Returns 0 on error.
//
// This does NOT add a row to the full text search database. Use
@@ -82,8 +82,8 @@ class URLDatabase {
}
// Either adds a new row to the URL table with the given information (with the
- // the |id| as specified in |info|), or updates the pre-existing row with this
- // |id| if there is one already. This is also known as an "upsert" or "merge"
+ // the `id` as specified in `info`), or updates the pre-existing row with this
+ // `id` if there is one already. This is also known as an "upsert" or "merge"
// operation. Returns true on success.
bool InsertOrUpdateURLRowByID(const URLRow& info);
@@ -95,7 +95,7 @@ class URLDatabase {
// URL mass-deleting ---------------------------------------------------------
// Begins the mass-deleting operation by creating a temporary URL table.
- // The caller than adds the URLs it wants to preseve to the temporary table,
+ // The caller than adds the URLs it wants to preserve to the temporary table,
// and then deletes everything else by calling CommitTemporaryURLTable().
// Returns true on success.
bool CreateTemporaryURLTable();
@@ -154,7 +154,7 @@ class URLDatabase {
// Fills the given array with URLs matching the given prefix. They will be
// sorted by typed count, then by visit count, then by visit date (most recent
- // first) up to the given maximum number. If |typed_only| is true, only urls
+ // first) up to the given maximum number. If `typed_only` is true, only urls
// that have been typed once are returned. For caller convenience, returns
// whether any results were found.
bool AutocompleteForPrefix(const std::string& prefix,
@@ -163,16 +163,16 @@ class URLDatabase {
URLRows* results);
// Returns true if the database holds some past typed navigation to a URL on
- // the provided hostname. If the return value is true and |scheme| is not
- // nullptr, |scheme| holds the scheme of one of the corresponding entries in
+ // the provided hostname. If the return value is true and `scheme` is not
+ // nullptr, `scheme` holds the scheme of one of the corresponding entries in
// the database.
bool IsTypedHost(const std::string& host, std::string* scheme);
- // Tries to find the shortest URL beginning with |base| that strictly
- // prefixes |url|, and has minimum visit_ and typed_counts as specified.
- // If found, fills in |info| and returns true; otherwise returns false,
- // leaving |info| unchanged.
- // We allow matches of exactly |base| iff |allow_base| is true.
+ // Tries to find the shortest URL beginning with `base` that strictly
+ // prefixes `url`, and has minimum visit_ and typed_counts as specified.
+ // If found, fills in `info` and returns true; otherwise returns false,
+ // leaving `info` unchanged.
+ // We allow matches of exactly `base` iff `allow_base` is true.
bool FindShortestURLFromBase(const std::string& base,
const std::string& url,
int min_visits,
@@ -183,11 +183,11 @@ class URLDatabase {
// History search ------------------------------------------------------------
// Performs a brute force search over the database to find any URLs or titles
- // which match the |query| string, using the default text matching algorithm.
- // Returns any matches in |results|.
+ // which match the `query` string, using the default text matching algorithm.
+ // Returns any matches in `results`.
bool GetTextMatches(const std::u16string& query, URLRows* results);
- // Same as GetTextMatches, using |algorithm| as the text matching
+ // Same as GetTextMatches, using `algorithm` as the text matching
// algorithm.
bool GetTextMatchesWithAlgorithm(const std::u16string& query,
query_parser::MatchingAlgorithm algorithm,
@@ -201,7 +201,7 @@ class URLDatabase {
const std::u16string& term);
// Looks up a keyword search term given a url id. Returns all the search terms
- // in |rows|. Returns true on success.
+ // in `rows`. Returns true on success.
bool GetKeywordSearchTermRow(URLID url_id, KeywordSearchTermRow* row);
// Looks up all keyword search terms given a term, Fills the rows with data.
@@ -221,22 +221,22 @@ class URLDatabase {
int max_count,
std::vector<KeywordSearchTermVisit>* matches);
- // Returns the most recent (i.e., no older than |age_threshold|) normalized
+ // Returns the most recent (i.e., no older than `age_threshold`) normalized
// search terms (i.e., search terms in lower case with whitespaces collapsed)
// for the specified keyword.
std::vector<NormalizedKeywordSearchTermVisit>
GetMostRecentNormalizedKeywordSearchTerms(KeywordID keyword_id,
base::Time age_threshold);
- // Deletes all searches matching |term|.
+ // Deletes all searches matching `term`.
bool DeleteKeywordSearchTerm(const std::u16string& term);
- // Deletes any search corresponding to |normalized_term|.
+ // Deletes any search corresponding to `normalized_term`.
bool DeleteKeywordSearchTermForNormalizedTerm(
KeywordID keyword_id,
const std::u16string& normalized_term);
- // Deletes any search corresponding to |url_id|.
+ // Deletes any search corresponding to `url_id`.
bool DeleteKeywordSearchTermForURL(URLID url_id);
// This is a cover for VisitDatabase::GetVisitsForURL(). It's here to avoid
@@ -268,7 +268,7 @@ class URLDatabase {
// index, which is faster than the reverse.
//
// is_temporary is false when generating the "regular" URLs table. The expirer
- // sets this to true to generate the temporary table, which will have a
+ // sets this to true to generate the temporary table, which will have a
// different name but the same schema.
bool CreateURLTable(bool is_temporary);
@@ -289,7 +289,7 @@ class URLDatabase {
// Inserts the given URL row into the URLs table, using the regular table
// if is_temporary is false, or the temporary URL table if is temporary is
- // true. The current |id| of |info| will be ignored in both cases and a new ID
+ // true. The current `id` of `info` will be ignored in both cases and a new ID
// will be generated, which will also constitute the return value, except in
// case of an error, when the return value is 0. The temporary table may only
// be used in between CreateTemporaryURLTable() and CommitTemporaryURLTable().
@@ -303,7 +303,7 @@ class URLDatabase {
// kHistoryURLRowFields.
static void FillURLRow(const sql::Statement& s, URLRow* i);
- // Returns the database for the functions in this interface. The decendent of
+ // Returns the database for the functions in this interface. The descendant of
// this class implements these functions to return its objects.
virtual sql::Database& GetDB() = 0;
@@ -350,11 +350,11 @@ extern const base::TimeDelta kAutocompleteDuplicateVisitIntervalThreshold;
// Returns the date threshold for considering an history item as significant.
base::Time AutocompleteAgeThreshold();
-// Return true if |row| qualifies as an autocomplete candidate. If |threshold|
+// Return true if `row` qualifies as an autocomplete candidate. If `threshold`
// is_null() then this function determines a new time threshold each time it is
// called. Since getting system time can be costly (such as for cases where
// this function will be called in a loop over many history items), you can
-// provide a non-null |threshold| by simply initializing |threshold| with
+// provide a non-null `threshold` by simply initializing `threshold` with
// AutocompleteAgeThreshold() (or any other desired time in the past).
bool RowQualifiesAsSignificant(const URLRow& row, const base::Time& threshold);
diff --git a/chromium/components/history/core/browser/url_database_unittest.cc b/chromium/components/history/core/browser/url_database_unittest.cc
index 8f0172f4bdd..d1db494d3e2 100644
--- a/chromium/components/history/core/browser/url_database_unittest.cc
+++ b/chromium/components/history/core/browser/url_database_unittest.cc
@@ -6,7 +6,6 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/history/core/browser/keyword_search_term.h"
#include "sql/database.h"
@@ -36,8 +35,7 @@ bool IsURLRowEqual(const URLRow& a,
class URLDatabaseTest : public testing::Test,
public URLDatabase {
public:
- URLDatabaseTest() {
- }
+ URLDatabaseTest() = default;
void CreateVersion33URLTable() {
EXPECT_TRUE(GetDB().Execute("DROP TABLE urls"));
@@ -345,7 +343,7 @@ TEST_F(URLDatabaseTest, GetAndDeleteKeywordSearchTermByTerm) {
ASSERT_TRUE(SetKeywordSearchTermsForURL(url_id3, keyword_id, keyword2));
- // We should get 2 rows for |keyword|.
+ // We should get 2 rows for `keyword`.
std::vector<KeywordSearchTermRow> rows;
ASSERT_TRUE(GetKeywordSearchTermRows(keyword, &rows));
ASSERT_EQ(2u, rows.size());
@@ -360,7 +358,7 @@ TEST_F(URLDatabaseTest, GetAndDeleteKeywordSearchTermByTerm) {
EXPECT_EQ(url_id2, rows[0].url_id);
}
- // We should get 1 row for |keyword2|.
+ // We should get 1 row for `keyword2`.
rows.clear();
ASSERT_TRUE(GetKeywordSearchTermRows(keyword2, &rows));
ASSERT_EQ(1u, rows.size());
@@ -435,7 +433,7 @@ TEST_F(URLDatabaseTest, MigrationURLTableForAddingAUTOINCREMENT) {
// Upgrade urls table.
RecreateURLTableWithAllContents();
- // Verify all data keeped.
+ // Verify all data kept.
EXPECT_TRUE(GetRowForURL(url1, &info1));
EXPECT_TRUE(IsURLRowEqual(url_info1, info1));
EXPECT_FALSE(GetRowForURL(url2, &info2));
diff --git a/chromium/components/history/core/browser/url_utils.cc b/chromium/components/history/core/browser/url_utils.cc
index 307c89419bd..d38f49efe11 100644
--- a/chromium/components/history/core/browser/url_utils.cc
+++ b/chromium/components/history/core/browser/url_utils.cc
@@ -41,7 +41,7 @@ bool CanonicalURLStringCompare(const std::string& s1, const std::string& s2) {
++ch2;
}
int pri_diff = GetURLCharPriority(*ch1) - GetURLCharPriority(*ch2);
- // We want false to be returned if |pri_diff| > 0.
+ // We want false to be returned if `pri_diff` > 0.
return (pri_diff != 0) ? pri_diff < 0 : *ch1 < *ch2;
}
@@ -55,18 +55,18 @@ bool IsPathPrefix(const std::string& p1, const std::string& p2) {
return false;
std::pair<std::string::const_iterator, std::string::const_iterator>
first_diff = std::mismatch(p1.begin(), p1.end(), p2.begin());
- // Necessary condition: |p1| is a string prefix of |p2|.
+ // Necessary condition: `p1` is a string prefix of `p2`.
if (first_diff.first != p1.end())
- return false; // E.g.: (|p1| = "/test", |p2| = "/exam") => false.
+ return false; // E.g.: (`p1` = "/test", `p2` = "/exam") => false.
- // |p1| is string prefix.
+ // `p1` is string prefix.
if (first_diff.second == p2.end()) // Is exact match?
return true; // E.g.: ("/test", "/test") => true.
- // |p1| is strict string prefix, check full match of last path component.
+ // `p1` is strict string prefix, check full match of last path component.
if (!p1.empty() && *p1.rbegin() == '/') // Ends in '/'?
return true; // E.g.: ("/test/", "/test/stuff") => true.
- // Finally, |p1| does not end in "/": check first extra character in |p2|.
+ // Finally, `p1` does not end in "/": check first extra character in `p2`.
// E.g.: ("/test", "/test/stuff") => true; ("/test", "/testing") => false.
return *(first_diff.second) == '/';
}
diff --git a/chromium/components/history/core/browser/url_utils.h b/chromium/components/history/core/browser/url_utils.h
index ba4f4aa5cf0..4721b65c294 100644
--- a/chromium/components/history/core/browser/url_utils.h
+++ b/chromium/components/history/core/browser/url_utils.h
@@ -15,30 +15,30 @@ namespace history {
// that represent valid URLs, so that if the pre-path (scheme, host, and port)
// parts are equal, then the path parts are compared by treating path components
// (delimited by "/") as separate tokens that form units of comparison.
-// For example, let us compare |s1| and |s2|, with
-// |s1| = "http://www.google.com:80/base/test/ab/cd?query/stuff"
-// |s2| = "http://www.google.com:80/base/test-case/yz#ref/stuff"
+// For example, let us compare `s1` and `s2`, with
+// `s1` = "http://www.google.com:80/base/test/ab/cd?query/stuff"
+// `s2` = "http://www.google.com:80/base/test-case/yz#ref/stuff"
// The pre-path parts "http://www.google.com:80/" match. We treat the paths as
-// |s1| => ["base", "test", "ab", "cd"]
-// |s2| => ["base", "test-case", "yz"]
+// `s1` => ["base", "test", "ab", "cd"]
+// `s2` => ["base", "test-case", "yz"]
// Components 1 "base" are identical. Components 2 yield "test" < "test-case",
-// so we consider |s1| < |s2|, and return true. Note that naive string
-// comparison would yield the opposite (|s1| > |s2|), since '/' > '-' in ASCII.
+// so we consider `s1` < `s2`, and return true. Note that naive string
+// comparison would yield the opposite (`s1` > `s2`), since '/' > '-' in ASCII.
// Note that path can be terminated by "?query" or "#ref". The post-path parts
// are compared in an arbitrary (but consistent) way.
bool CanonicalURLStringCompare(const std::string& s1, const std::string& s2);
-// Returns whether |url1| and |url2| have the same scheme, host, and port.
+// Returns whether `url1` and `url2` have the same scheme, host, and port.
bool HaveSameSchemeHostAndPort(const GURL&url1, const GURL& url2);
-// Treats |path1| and |path2| as lists of path components (e.g., ["a", "bb"]
-// for "/a/bb"). Returns whether |path1|'s list is a prefix of |path2|'s list.
+// Treats `path1` and `path2` as lists of path components (e.g., ["a", "bb"]
+// for "/a/bb"). Returns whether `path1`'s list is a prefix of `path2`'s list.
// This is used to define "URL prefix". Note that "test" does not count as a
// prefix of "testing", even though "test" is a (string) prefix of "testing".
bool IsPathPrefix(const std::string& p1, const std::string& p2);
-// Converts |url| from HTTP to HTTPS, and vice versa, then returns the result.
-// If |url| is neither HTTP nor HTTPS, returns an empty URL.
+// Converts `url` from HTTP to HTTPS, and vice versa, then returns the result.
+// If `url` is neither HTTP nor HTTPS, returns an empty URL.
GURL ToggleHTTPAndHTTPS(const GURL& url);
// Returns the host of the given URL, canonicalized as it would be for
diff --git a/chromium/components/history/core/browser/visit_annotations_database.cc b/chromium/components/history/core/browser/visit_annotations_database.cc
index 2ff13cd51d8..fd95915614a 100644
--- a/chromium/components/history/core/browser/visit_annotations_database.cc
+++ b/chromium/components/history/core/browser/visit_annotations_database.cc
@@ -4,18 +4,29 @@
#include "components/history/core/browser/visit_annotations_database.h"
+#include <string>
+
+#include "base/logging.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "components/history/core/browser/url_row.h"
#include "sql/statement.h"
-#include "sql/transaction.h"
+#include "sql/statement_id.h"
namespace history {
namespace {
-// Converts the serialized categories into a vector of (category_id, weight)
+#define HISTORY_CONTENT_ANNOTATIONS_ROW_FIELDS \
+ " visit_id, floc_protected_score, categories, page_topics_model_version, " \
+ "annotation_flags "
+#define HISTORY_CONTEXT_ANNOTATIONS_ROW_FIELDS \
+ " visit_id, context_annotation_flags, duration_since_last_visit, " \
+ "page_end_reason "
+
+// Converts the serialized categories into a vector of (`id`, `weight`)
// pairs.
std::vector<VisitContentModelAnnotations::Category>
GetCategoriesFromStringColumn(const std::string& column_value) {
@@ -51,6 +62,102 @@ std::string ConvertCategoriesToStringColumn(
return base::JoinString(serialized_categories, ",");
}
+// An enum of bitmasks to help represent the boolean flags of
+// `VisitContextAnnotations` in the database. This avoids having to update
+// the schema every time we add/remove/change a bool context annotation. As
+// these are persisted to the database, entries should not be renumbered and
+// numeric values should never be reused.
+enum class ContextAnnotationFlags : uint64_t {
+ // True if the user has cut or copied the omnibox URL to the clipboard for
+ // this page load.
+ kOmniboxUrlCopied = 1 << 0,
+
+ // True if the page was in a tab group when the navigation was committed.
+ kIsExistingPartOfTabGroup = 1 << 1,
+
+ // True if the page was NOT part of a tab group when the navigation
+ // committed, and IS part of a tab group at the end of the page lifetime.
+ kIsPlacedInTabGroup = 1 << 2,
+
+ // True if this page was a bookmark when the navigation was committed.
+ kIsExistingBookmark = 1 << 3,
+
+ // True if the page was NOT a bookmark when the navigation was committed and
+ // was MADE a bookmark during the page's lifetime. In other words:
+ // If `is_existing_bookmark` is true, that implies `is_new_bookmark` is false.
+ kIsNewBookmark = 1 << 4,
+
+ // True if the page has been explicitly added (by the user) to the list of
+ // custom links displayed in the NTP. Links added to the NTP by History
+ // TopSites don't count for this. Always false on Android, because Android
+ // does not have NTP custom links.
+ kIsNtpCustomLink = 1 << 5,
+};
+
+int64_t ContextAnnotationsToFlags(VisitContextAnnotations context_annotations) {
+ return (context_annotations.omnibox_url_copied &
+ static_cast<uint64_t>(ContextAnnotationFlags::kOmniboxUrlCopied)) |
+ (context_annotations.is_existing_part_of_tab_group &
+ static_cast<uint64_t>(
+ ContextAnnotationFlags::kIsExistingPartOfTabGroup)) |
+ (context_annotations.is_placed_in_tab_group &
+ static_cast<uint64_t>(ContextAnnotationFlags::kIsPlacedInTabGroup)) |
+ (context_annotations.is_existing_bookmark &
+ static_cast<uint64_t>(ContextAnnotationFlags::kIsExistingBookmark)) |
+ (context_annotations.is_new_bookmark &
+ static_cast<uint64_t>(ContextAnnotationFlags::kIsNewBookmark)) |
+ (context_annotations.is_ntp_custom_link &
+ static_cast<uint64_t>(ContextAnnotationFlags::kIsNtpCustomLink));
+}
+
+VisitContextAnnotations ConstructContextAnnotationsWithFlags(
+ int64_t flags,
+ base::TimeDelta duration_since_last_visit,
+ int page_end_reason) {
+ VisitContextAnnotations context_annotations;
+ context_annotations.omnibox_url_copied =
+ flags & static_cast<uint64_t>(ContextAnnotationFlags::kOmniboxUrlCopied);
+ context_annotations.is_existing_part_of_tab_group =
+ flags &
+ static_cast<uint64_t>(ContextAnnotationFlags::kIsExistingPartOfTabGroup);
+ context_annotations.is_placed_in_tab_group =
+ flags &
+ static_cast<uint64_t>(ContextAnnotationFlags::kIsPlacedInTabGroup);
+ context_annotations.is_existing_bookmark =
+ flags &
+ static_cast<uint64_t>(ContextAnnotationFlags::kIsExistingBookmark);
+ context_annotations.is_new_bookmark =
+ flags & static_cast<uint64_t>(ContextAnnotationFlags::kIsNewBookmark);
+ context_annotations.is_ntp_custom_link =
+ flags & static_cast<uint64_t>(ContextAnnotationFlags::kIsNtpCustomLink);
+ context_annotations.duration_since_last_visit = duration_since_last_visit;
+ context_annotations.page_end_reason = page_end_reason;
+ return context_annotations;
+}
+
+// Convenience to construct a `AnnotatedVisitRow`. Assumes the visit values are
+// bound starting at index 0.
+AnnotatedVisitRow StatementToAnnotatedVisitRow(
+ const sql::Statement& statement) {
+ return {statement.ColumnInt64(0),
+ ConstructContextAnnotationsWithFlags(
+ statement.ColumnInt64(1),
+ base::TimeDelta::FromMicroseconds(statement.ColumnInt64(2)),
+ statement.ColumnInt(3)),
+ {}};
+}
+
+// Like `StatementToAnnotatedVisitRow()` but for multiple rows.
+std::vector<AnnotatedVisitRow> StatementToAnnotatedVisitRowVector(
+ sql::Statement& statement) {
+ if (!statement.is_valid())
+ return {};
+ std::vector<AnnotatedVisitRow> rows;
+ while (statement.Step())
+ rows.push_back(StatementToAnnotatedVisitRow(statement));
+ return rows;
+}
+
} // namespace
VisitAnnotationsDatabase::VisitAnnotationsDatabase() = default;
@@ -68,23 +175,35 @@ bool VisitAnnotationsDatabase::InitVisitAnnotationsTables() {
return false;
}
}
+
+ if (!GetDB().DoesTableExist("context_annotations")) {
+ // See `AnnotatedVisitRow` and `VisitContextAnnotations` for details about
+ // these fields.
+ if (!GetDB().Execute("CREATE TABLE context_annotations("
+ "visit_id INTEGER PRIMARY KEY,"
+ "context_annotation_flags INTEGER DEFAULT 0 NOT NULL,"
+ "duration_since_last_visit INTEGER,"
+ "page_end_reason INTEGER)")) {
+ return false;
+ }
+ }
+
return true;
}
bool VisitAnnotationsDatabase::DropVisitAnnotationsTables() {
// Dropping the tables will implicitly delete the indices.
- return GetDB().Execute("DROP TABLE content_annotations");
+ return GetDB().Execute("DROP TABLE content_annotations") &&
+ GetDB().Execute("DROP TABLE context_annotations");
}
-bool VisitAnnotationsDatabase::AddContentAnnotationsForVisit(
+void VisitAnnotationsDatabase::AddContentAnnotationsForVisit(
VisitID visit_id,
const VisitContentAnnotations& visit_content_annotations) {
sql::Statement statement(GetDB().GetCachedStatement(
SQL_FROM_HERE,
- "INSERT INTO content_annotations "
- "(visit_id, floc_protected_score, categories, page_topics_model_version, "
- "annotation_flags) "
- "VALUES (?,?,?,?,?)"));
+ "INSERT INTO content_annotations (" HISTORY_CONTENT_ANNOTATIONS_ROW_FIELDS
+ ") VALUES (?, ?, ?, ?, ?)"));
statement.BindInt64(0, visit_id);
statement.BindDouble(
1, static_cast<double>(
@@ -97,16 +216,32 @@ bool VisitAnnotationsDatabase::AddContentAnnotationsForVisit(
statement.BindInt64(4, visit_content_annotations.annotation_flags);
if (!statement.Run()) {
+ DVLOG(0) << "Failed to execute 'content_annotations' insert statement: "
+ << "visit_id = " << visit_id;
+ }
+}
+
+void VisitAnnotationsDatabase::AddContextAnnotationsForVisit(
+ VisitID visit_id,
+ const VisitContextAnnotations& visit_context_annotations) {
+ sql::Statement statement(GetDB().GetCachedStatement(
+ SQL_FROM_HERE,
+ "INSERT INTO context_annotations (" HISTORY_CONTEXT_ANNOTATIONS_ROW_FIELDS
+ ") VALUES (?, ?, ?, ?)"));
+ statement.BindInt64(0, visit_id);
+ statement.BindInt64(1, ContextAnnotationsToFlags(visit_context_annotations));
+ statement.BindInt64(
+ 2, visit_context_annotations.duration_since_last_visit.InMicroseconds());
+ statement.BindInt(3, visit_context_annotations.page_end_reason);
+
+ if (!statement.Run()) {
DVLOG(0)
- << "Failed to execute visit content annotations insert statement: "
+ << "Failed to execute visit 'context_annotations' insert statement: "
<< "visit_id = " << visit_id;
- return false;
}
-
- return true;
}
-bool VisitAnnotationsDatabase::UpdateContentAnnotationsForVisit(
+void VisitAnnotationsDatabase::UpdateContentAnnotationsForVisit(
VisitID visit_id,
const VisitContentAnnotations& visit_content_annotations) {
sql::Statement statement(
@@ -127,7 +262,11 @@ bool VisitAnnotationsDatabase::UpdateContentAnnotationsForVisit(
statement.BindInt64(3, visit_content_annotations.annotation_flags);
statement.BindInt64(4, visit_id);
- return statement.Run();
+ if (!statement.Run()) {
+ DVLOG(0)
+ << "Failed to execute visit 'content_annotations' update statement: "
+ << "visit_id = " << visit_id;
+ }
}
bool VisitAnnotationsDatabase::GetContentAnnotationsForVisit(
@@ -136,10 +275,8 @@ bool VisitAnnotationsDatabase::GetContentAnnotationsForVisit(
DCHECK(out_content_annotations);
sql::Statement statement(GetDB().GetCachedStatement(
- SQL_FROM_HERE,
- "SELECT visit_id, floc_protected_score, "
- "categories,page_topics_model_version,annotation_flags "
- "FROM content_annotations WHERE visit_id=?"));
+ SQL_FROM_HERE, "SELECT" HISTORY_CONTENT_ANNOTATIONS_ROW_FIELDS
+ "FROM content_annotations WHERE visit_id=?"));
statement.BindInt64(0, visit_id);
if (!statement.Step())
@@ -161,13 +298,44 @@ bool VisitAnnotationsDatabase::GetContentAnnotationsForVisit(
return true;
}
-bool VisitAnnotationsDatabase::DeleteContentAnnotationsForVisit(
- VisitID visit_id) {
- sql::Statement delete_content(GetDB().GetCachedStatement(
+std::vector<AnnotatedVisitRow> VisitAnnotationsDatabase::GetAnnotatedVisits(
+ int max_results) {
+ // TODO(manukh): Currently, this only sets the `context_annotations`. It
+ // should also set the `content_annotations`.
+ sql::Statement statement(GetDB().GetCachedStatement(
+ SQL_FROM_HERE, "SELECT" HISTORY_CONTEXT_ANNOTATIONS_ROW_FIELDS
+ "FROM context_annotations "
+ "JOIN visits ON visit_id = visits.id "
+ "ORDER BY visits.visit_time DESC "
+ "LIMIT ?"));
+ statement.BindInt64(0, max_results);
+ return StatementToAnnotatedVisitRowVector(statement);
+}
+
+std::vector<AnnotatedVisitRow>
+VisitAnnotationsDatabase::GetAllContextAnnotationsForTesting() {
+ sql::Statement statement(GetDB().GetCachedStatement(
+ SQL_FROM_HERE, "SELECT" HISTORY_CONTEXT_ANNOTATIONS_ROW_FIELDS
+ "FROM context_annotations"));
+ return StatementToAnnotatedVisitRowVector(statement);
+}
+
+void VisitAnnotationsDatabase::DeleteAnnotationsForVisit(VisitID visit_id) {
+ sql::Statement delete_content_statement(GetDB().GetCachedStatement(
SQL_FROM_HERE, "DELETE FROM content_annotations WHERE visit_id = ?"));
- delete_content.BindInt64(0, visit_id);
+ delete_content_statement.BindInt64(0, visit_id);
+ if (!delete_content_statement.Run()) {
+ DVLOG(0) << "Failed to execute 'content_annotations' delete statement: "
+ << "visit_id = " << visit_id;
+ }
- return delete_content.Run();
+ sql::Statement delete_context_statement(GetDB().GetCachedStatement(
+ SQL_FROM_HERE, "DELETE FROM context_annotations WHERE visit_id = ?"));
+ delete_context_statement.BindInt64(0, visit_id);
+ if (!delete_context_statement.Run()) {
+ DVLOG(0) << "Failed to execute 'context_annotations' delete statement: "
+ << "visit_id = " << visit_id;
+ }
}
bool VisitAnnotationsDatabase::MigrateFlocAllowedToAnnotationsTable() {
@@ -178,7 +346,7 @@ bool VisitAnnotationsDatabase::MigrateFlocAllowedToAnnotationsTable() {
// Not all version 43 history has the content_annotations table. So at this
// point the content_annotations table may already have been initialized with
- // the latest verssion with a annotation_flags column.
+ // the latest version with a annotation_flags column.
if (!GetDB().DoesColumnExist("content_annotations", "annotation_flags")) {
// Add a annotation_flags column to the content_annotations table.
if (!GetDB().Execute("ALTER TABLE content_annotations ADD COLUMN "
@@ -212,4 +380,11 @@ bool VisitAnnotationsDatabase::MigrateFlocAllowedToAnnotationsTable() {
return true;
}
+bool VisitAnnotationsDatabase::MigrateReplaceClusterVisitsTable() {
+ // We don't need to actually copy values from the previous table; it was only
+ // rolled out behind a flag.
+ return !GetDB().DoesTableExist("cluster_visits") ||
+ GetDB().Execute("DROP TABLE cluster_visits");
+}
+
} // namespace history
diff --git a/chromium/components/history/core/browser/visit_annotations_database.h b/chromium/components/history/core/browser/visit_annotations_database.h
index 88f71b8dcbd..a32c6494d09 100644
--- a/chromium/components/history/core/browser/visit_annotations_database.h
+++ b/chromium/components/history/core/browser/visit_annotations_database.h
@@ -5,11 +5,8 @@
#ifndef COMPONENTS_HISTORY_CORE_BROWSER_VISIT_ANNOTATIONS_DATABASE_H_
#define COMPONENTS_HISTORY_CORE_BROWSER_VISIT_ANNOTATIONS_DATABASE_H_
-#include <memory>
-#include <string>
+#include <vector>
-#include "base/callback_forward.h"
-#include "base/macros.h"
#include "components/history/core/browser/history_types.h"
namespace sql {
@@ -18,45 +15,55 @@ class Database;
namespace history {
-// Holds annotations made for a user's visits.
+struct VisitContentAnnotations;
+
+// A database that stores visit content & context annotations. A
+// `VisitAnnotationsDatabase` must also be a `VisitDatabase`, as this joins with
+// the `visits` table. The `content_annotations` and `context_annotations` use
+// `visit_id` as their primary key; each row in the `visits` table will be
+// associated with 0 or 1 rows in each annotation table.
class VisitAnnotationsDatabase {
public:
- // Must call InitAnnotationsTables before using any other part of this class.
+ // Must call `InitAnnotationsTables()` before using any other part of this
+ // class.
VisitAnnotationsDatabase();
VisitAnnotationsDatabase(const VisitAnnotationsDatabase&) = delete;
VisitAnnotationsDatabase& operator=(const VisitAnnotationsDatabase&) = delete;
virtual ~VisitAnnotationsDatabase();
- // Adds a line to the content annotations database with the given information,
- // returning true on success, false on failure. The given content annotations
- // are updated with the new row on success.
- bool AddContentAnnotationsForVisit(
+ // Adds a line to the content annotations table with the given information.
+ void AddContentAnnotationsForVisit(
VisitID visit_id,
const VisitContentAnnotations& visit_content_annotations);
+ // Adds a line to the context annotation table with the given information..
+ void AddContextAnnotationsForVisit(
+ VisitID visit_id,
+ const VisitContextAnnotations& visit_context_annotations);
+
// Updates an existing row. The new information is set on the row, using the
// VisitID as the key. The content annotations for the visit must exist.
- // Returns true on success.
- bool UpdateContentAnnotationsForVisit(
+ void UpdateContentAnnotationsForVisit(
VisitID visit_id,
const VisitContentAnnotations& visit_content_annotations);
- // Query for a VisitContentAnnotations given a visit id and returns it if
+ // Query for a VisitContentAnnotations given a `VisitID` and returns it if
// present. If it's present, `out_content_annotations` will be filled with the
// expected data; otherwise, `out_content_annotations` won't be changed.
bool GetContentAnnotationsForVisit(
VisitID visit_id,
VisitContentAnnotations* out_content_annotations);
- // Deletes content annotations currently using the provided visit for
- // representation. This will also delete any associated annotations usage
- // data. If no content annotations exist for the visit id, this is a no-op.
- bool DeleteContentAnnotationsForVisit(VisitID visit_id);
- // Called by the derived classes to migrate the older visits table's
- // floc_allowed (for historical reasons named "publicly_routable" in the
- // schema) column to the content_annotations table, from a BOOLEAN filed to
- // a bit masking INTEGER filed.
- bool MigrateFlocAllowedToAnnotationsTable();
+ // Get the `max_results` most recent `AnnotatedVisitRow`s.
+ std::vector<AnnotatedVisitRow> GetAnnotatedVisits(int max_results);
+
+ // Gets all the context annotation rows for testing.
+ std::vector<AnnotatedVisitRow> GetAllContextAnnotationsForTesting();
+
+ // Deletes the content & context annotations associated with `visit_id`. This
+ // will also delete any associated annotations usage data. If no annotations
+ // exist for the `VisitId`, this is a no-op.
+ void DeleteAnnotationsForVisit(VisitID visit_id);
protected:
// Returns the database for the functions in this interface.
@@ -68,6 +75,18 @@ class VisitAnnotationsDatabase {
// Deletes all the annotations tables, returning true on success.
bool DropVisitAnnotationsTables();
+
+ // Called by the derived classes to migrate the older visits table's
+ // floc_allowed (for historical reasons named "publicly_routable" in the
+ // schema) column to the content_annotations table, from a BOOLEAN filed to
+ // a bit masking INTEGER filed.
+ bool MigrateFlocAllowedToAnnotationsTable();
+
+ // Replaces `cluster_visits` with `context_annotations`. Besides the name
+ // change, the new table drops 2 columns: cluster_visit_id (obsolete) and
+ // url_id (redundant); and renames 1 column:
+ // cluster_visit_context_signal_bitmask to context_annotation_flags.
+ bool MigrateReplaceClusterVisitsTable();
};
} // namespace history
diff --git a/chromium/components/history/core/browser/visit_annotations_database_unittest.cc b/chromium/components/history/core/browser/visit_annotations_database_unittest.cc
index 1b5c25c8425..faa5ba8789d 100644
--- a/chromium/components/history/core/browser/visit_annotations_database_unittest.cc
+++ b/chromium/components/history/core/browser/visit_annotations_database_unittest.cc
@@ -4,7 +4,10 @@
#include "components/history/core/browser/visit_annotations_database.h"
-#include "base/files/scoped_temp_dir.h"
+#include "base/time/time.h"
+#include "components/history/core/browser/history_types.h"
+#include "components/history/core/browser/url_row.h"
+#include "components/history/core/browser/visit_database.h"
#include "sql/database.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -15,32 +18,44 @@ namespace {
using ::testing::ElementsAre;
+// Returns a Time that's `seconds` seconds after Windows epoch.
+base::Time IntToTime(int seconds) {
+ return base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromSeconds(seconds));
+}
+
} // namespace
class VisitAnnotationsDatabaseTest : public testing::Test,
- public VisitAnnotationsDatabase {
+ public VisitAnnotationsDatabase,
+ public VisitDatabase {
public:
VisitAnnotationsDatabaseTest() = default;
~VisitAnnotationsDatabaseTest() override = default;
+ protected:
+ // Convenience wrapper for `VisitDatabase::AddVisit()`.
+ void AddVisitWithDetails(URLID url_id, base::Time visit_time) {
+ VisitRow visit_row;
+ visit_row.url_id = url_id;
+ visit_row.visit_time = visit_time;
+ AddVisit(&visit_row, VisitSource::SOURCE_BROWSED);
+ }
+
private:
// Test setup.
void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- base::FilePath db_file =
- temp_dir_.GetPath().AppendASCII("VisitAnnotationsTest.db");
-
- ASSERT_TRUE(db_.Open(db_file));
+ ASSERT_TRUE(db_.OpenInMemory());
// Initialize the tables for this test.
- InitVisitAnnotationsTables();
+ EXPECT_TRUE(InitVisitTable());
+ EXPECT_TRUE(InitVisitAnnotationsTables());
}
void TearDown() override { db_.Close(); }
// VisitAnnotationsDatabase:
sql::Database& GetDB() override { return db_; }
- base::ScopedTempDir temp_dir_;
sql::Database db_;
};
@@ -53,7 +68,7 @@ TEST_F(VisitAnnotationsDatabaseTest, AddContentAnnotationsForVisit) {
VisitContentAnnotationFlag::kFlocEligibleRelaxed;
VisitContentAnnotations content_annotations{annotation_flags,
model_annotations};
- EXPECT_TRUE(AddContentAnnotationsForVisit(visit_id, content_annotations));
+ AddContentAnnotationsForVisit(visit_id, content_annotations);
// Query for it.
VisitContentAnnotations got_content_annotations;
@@ -73,6 +88,43 @@ TEST_F(VisitAnnotationsDatabaseTest, AddContentAnnotationsForVisit) {
123, got_content_annotations.model_annotations.page_topics_model_version);
}
+TEST_F(VisitAnnotationsDatabaseTest, AddGetAndDeleteContextAnnotations) {
+ AddVisitWithDetails(1, IntToTime(20));
+ AddVisitWithDetails(1, IntToTime(30));
+ AddVisitWithDetails(2, IntToTime(10));
+
+ // Verify `AddContextAnnotationsForVisit()` and `GetAnnotatedVisits()`.
+ AddContextAnnotationsForVisit(1, {true}); // Ordered 2nd
+ AddContextAnnotationsForVisit(2, {false}); // Ordered 1st
+ AddContextAnnotationsForVisit(3, {false}); // Ordered 3rd
+
+ std::vector<AnnotatedVisitRow> rows = GetAnnotatedVisits(10);
+ ASSERT_EQ(rows.size(), 3u);
+ EXPECT_EQ(rows[0].visit_id, 2);
+ EXPECT_FALSE(rows[0].context_annotations.omnibox_url_copied);
+ EXPECT_EQ(rows[1].visit_id, 1);
+ EXPECT_TRUE(rows[1].context_annotations.omnibox_url_copied);
+ EXPECT_EQ(rows[2].visit_id, 3);
+ EXPECT_FALSE(rows[2].context_annotations.omnibox_url_copied);
+
+ // Verify `max_results` param of `GetAnnotatedVisits()`.
+ rows = GetAnnotatedVisits(2);
+ ASSERT_EQ(rows.size(), 2u);
+ EXPECT_EQ(rows[0].visit_id, 2);
+ EXPECT_FALSE(rows[0].context_annotations.omnibox_url_copied);
+ EXPECT_EQ(rows[1].visit_id, 1);
+ EXPECT_TRUE(rows[1].context_annotations.omnibox_url_copied);
+
+ // Verify `DeleteAnnotationsForVisit()`.
+ DeleteAnnotationsForVisit(1);
+ DeleteAnnotationsForVisit(3);
+
+ rows = GetAnnotatedVisits(10);
+ ASSERT_EQ(rows.size(), 1u);
+ EXPECT_EQ(rows[0].visit_id, 2);
+ EXPECT_FALSE(rows[0].context_annotations.omnibox_url_copied);
+}
+
TEST_F(VisitAnnotationsDatabaseTest, UpdateContentAnnotationsForVisit) {
// Add content annotations for 1 visit.
VisitID visit_id = 1;
@@ -81,12 +133,12 @@ TEST_F(VisitAnnotationsDatabaseTest, UpdateContentAnnotationsForVisit) {
VisitContentAnnotationFlags annotation_flags =
VisitContentAnnotationFlag::kFlocEligibleRelaxed;
VisitContentAnnotations original{annotation_flags, model_annotations};
- EXPECT_TRUE(AddContentAnnotationsForVisit(visit_id, original));
+ AddContentAnnotationsForVisit(visit_id, original);
// Mutate that row.
VisitContentAnnotations modification(original);
modification.model_annotations.floc_protected_score = 0.3f;
- EXPECT_TRUE(UpdateContentAnnotationsForVisit(visit_id, modification));
+ UpdateContentAnnotationsForVisit(visit_id, modification);
// Check that the mutated version was written.
VisitContentAnnotations final;
@@ -103,7 +155,7 @@ TEST_F(VisitAnnotationsDatabaseTest, UpdateContentAnnotationsForVisit) {
EXPECT_EQ(123, final.model_annotations.page_topics_model_version);
}
-TEST_F(VisitAnnotationsDatabaseTest, DeleteContentAnnotationsForVisit) {
+TEST_F(VisitAnnotationsDatabaseTest, DeleteAnnotationsForVisit) {
// Add content annotations for 1 visit.
VisitID visit_id = 1;
VisitContentModelAnnotations model_annotations = {
@@ -112,7 +164,7 @@ TEST_F(VisitAnnotationsDatabaseTest, DeleteContentAnnotationsForVisit) {
VisitContentAnnotationFlag::kNone;
VisitContentAnnotations content_annotations{annotation_flags,
model_annotations};
- EXPECT_TRUE(AddContentAnnotationsForVisit(visit_id, content_annotations));
+ AddContentAnnotationsForVisit(visit_id, content_annotations);
VisitContentAnnotations got_content_annotations;
// First make sure the annotations are there.
@@ -120,7 +172,7 @@ TEST_F(VisitAnnotationsDatabaseTest, DeleteContentAnnotationsForVisit) {
GetContentAnnotationsForVisit(visit_id, &got_content_annotations));
// Delete annotations and make sure we cannot query for it.
- EXPECT_TRUE(DeleteContentAnnotationsForVisit(visit_id));
+ DeleteAnnotationsForVisit(visit_id);
EXPECT_FALSE(
GetContentAnnotationsForVisit(visit_id, &got_content_annotations));
}
diff --git a/chromium/components/history/core/browser/visit_database.cc b/chromium/components/history/core/browser/visit_database.cc
index 1be502c55f5..e7c04dc0e47 100644
--- a/chromium/components/history/core/browser/visit_database.cc
+++ b/chromium/components/history/core/browser/visit_database.cc
@@ -73,9 +73,9 @@ bool TransitionIsVisible(int32_t transition) {
} // namespace
-VisitDatabase::VisitDatabase() {}
+VisitDatabase::VisitDatabase() = default;
-VisitDatabase::~VisitDatabase() {}
+VisitDatabase::~VisitDatabase() = default;
bool VisitDatabase::InitVisitTable() {
if (!GetDB().DoesTableExist("visits")) {
@@ -172,7 +172,7 @@ bool VisitDatabase::FillVisitVectorWithOptions(sql::Statement& statement,
VisitVector* visits) {
std::set<URLID> found_urls;
- // Keeps track of the day that |found_urls| is holding the URLs for, in order
+ // Keeps track of the day that `found_urls` is holding the URLs for, in order
// to handle removing per-day duplicates.
base::Time found_urls_midnight;
@@ -345,12 +345,12 @@ bool VisitDatabase::GetVisitsForTimes(const std::vector<base::Time>& times,
VisitVector* visits) {
visits->clear();
- for (auto it = times.begin(); it != times.end(); ++it) {
+ for (const auto& time : times) {
sql::Statement statement(GetDB().GetCachedStatement(
SQL_FROM_HERE, "SELECT" HISTORY_VISIT_ROW_FIELDS "FROM visits "
"WHERE visit_time == ?"));
- statement.BindInt64(0, it->ToInternalValue());
+ statement.BindInt64(0, time.ToInternalValue());
if (!FillVisitVector(statement, visits))
return false;
diff --git a/chromium/components/history/core/browser/visit_database.h b/chromium/components/history/core/browser/visit_database.h
index d5240fe4943..42485f48e9a 100644
--- a/chromium/components/history/core/browser/visit_database.h
+++ b/chromium/components/history/core/browser/visit_database.h
@@ -62,7 +62,7 @@ class VisitDatabase {
// and match the set of options passed, sorted in ascending order of date.
//
// Returns true if there are more results available, i.e. if the number of
- // results was restricted by |options.max_count|.
+ // results was restricted by `options.max_count`.
bool GetVisibleVisitsForURL(URLID url_id,
const QueryOptions& options,
VisitVector* visits);
@@ -70,8 +70,8 @@ class VisitDatabase {
// Fills the vector with all visits with times in the given list.
//
// The results will be in no particular order. Also, no duplicate
- // detection is performed, so if |times| has duplicate times,
- // |visits| may have duplicate visits.
+ // detection is performed, so if `times` has duplicate times,
+ // `visits` may have duplicate visits.
bool GetVisitsForTimes(const std::vector<base::Time>& times,
VisitVector* visits);
@@ -79,7 +79,7 @@ class VisitDatabase {
// time can be is_null(), in which case the times in that direction are
// unbounded.
//
- // If |max_results| is non-zero, up to that many results will be returned. If
+ // If `max_results` is non-zero, up to that many results will be returned. If
// there are more results than that, the oldest ones will be returned. (This
// is used for history expiration.)
//
@@ -93,7 +93,7 @@ class VisitDatabase {
// to the given vector. Either time can be is_null(), in which case the times
// in that direction are unbounded.
//
- // If |max_results| is non-zero, up to that many results will be returned. If
+ // If `max_results` is non-zero, up to that many results will be returned. If
// there are more results than that, the oldest ones will be returned. (This
// is used for history expiration.)
//
@@ -114,15 +114,15 @@ class VisitDatabase {
// begin time is inclusive, the end time is exclusive. Either time can be
// is_null(), in which case the times in that direction are unbounded.
//
- // Up to |max_count| visits will be returned. If there are more visits than
- // that, the most recent |max_count| will be returned. If 0, all visits in the
+ // Up to `max_count` visits will be returned. If there are more visits than
+ // that, the most recent `max_count` will be returned. If 0, all visits in the
// range will be computed.
//
// Only one visit for each URL will be returned, and it will be the most
// recent one in the time range.
//
// Returns true if there are more results available, i.e. if the number of
- // results was restricted by |options.max_count|.
+ // results was restricted by `options.max_count`.
bool GetVisibleVisitsInRange(const QueryOptions& options,
VisitVector* visits);
@@ -133,16 +133,16 @@ class VisitDatabase {
// the found visit. When no visit is found, the row will be unchanged.
VisitID GetMostRecentVisitForURL(URLID url_id, VisitRow* visit_row);
- // Returns the |max_results| most recent visit sessions for |url_id|.
+ // Returns the `max_results` most recent visit sessions for `url_id`.
//
// Returns false if there's a failure preparing the statement. True
- // otherwise. (No results are indicated with an empty |visits|
+ // otherwise. (No results are indicated with an empty `visits`
// vector.)
bool GetMostRecentVisitsForURL(URLID url_id,
int max_results,
VisitVector* visits);
- // Finds a redirect coming from the given |from_visit|. If a redirect is
+ // Finds a redirect coming from the given `from_visit`. If a redirect is
// found, it fills the visit ID and URL into the out variables and returns
// true. If there is no redirect from the given visit, returns false.
//
@@ -157,13 +157,13 @@ class VisitDatabase {
GURL* to_url);
// Similar to the above function except finds a redirect going to a given
- // |to_visit|.
+ // `to_visit`.
bool GetRedirectToVisit(VisitID to_visit,
VisitID* from_visit,
GURL* from_url);
// Gets the number of user-visible visits to all URLs on the same
- // scheme/host/port as |url|, as well as the time of the earliest visit.
+ // scheme/host/port as `url`, as well as the time of the earliest visit.
// "User-visible" is defined as in GetVisibleVisitsInRange() above, i.e.
// excluding redirects and subframes.
// This function is only valid for HTTP and HTTPS URLs; all other schemes
@@ -173,7 +173,7 @@ class VisitDatabase {
base::Time* first_visit);
// Gets the number of URLs as seen in chrome://history within the time
- // range [|begin_time|, |end_time|). "User-visible" is defined as in
+ // range [`begin_time`, `end_time`). "User-visible" is defined as in
// GetVisibleVisitsInRange() above, i.e. excluding redirects and subframes.
// Each URL is counted only once per day. For determination of the date,
// timestamps are converted to dates using local time. Returns false if
@@ -183,8 +183,8 @@ class VisitDatabase {
int* count);
// Gets the last time any webpage on the given host was visited within the
- // time range [|begin_time|, |end_time|). If the given host has not been
- // visited in the given time range, this will return true and |last_visit|
+ // time range [`begin_time`, `end_time`). If the given host has not been
+ // visited in the given time range, this will return true and `last_visit`
// will be set to base::Time(). False will be returned if the host is not a
// valid HTTP or HTTPS url or for other database errors.
bool GetLastVisitToHost(const GURL& host,
@@ -192,15 +192,15 @@ class VisitDatabase {
base::Time end_time,
base::Time* last_visit);
- // Gets the last time |url| was visited before |end_time|. If the given |url|
- // has no past visits, this will return true and |last_visit| will be set to
- // base::Time(). False will be returned if |url| is not a valid HTTP or HTTPS
+ // Gets the last time `url` was visited before `end_time`. If the given `url`
+ // has no past visits, this will return true and `last_visit` will be set to
+ // base::Time(). False will be returned if `url` is not a valid HTTP or HTTPS
// url or for other database errors.
bool GetLastVisitToURL(const GURL& url,
base::Time end_time,
base::Time* last_visit);
- // Gets counts for total visits and days visited for pages matching |host|'s
+ // Gets counts for total visits and days visited for pages matching `host`'s
// scheme, port, and host. Counts only user-visible visits.
DailyVisitsResult GetDailyVisitsToHost(const GURL& host,
base::Time begin_time,
@@ -236,7 +236,7 @@ class VisitDatabase {
static bool FillVisitVector(sql::Statement& statement, VisitVector* visits);
// Convenience to fill a VisitVector while respecting the set of options.
- // |statement| should order the query decending by visit_time to ensure
+ // `statement` should order the query descending by visit_time to ensure
// correct duplicate management behavior. Assumes that statement.step()
// hasn't happened yet.
static bool FillVisitVectorWithOptions(sql::Statement& statement,
diff --git a/chromium/components/history/core/browser/visit_database_unittest.cc b/chromium/components/history/core/browser/visit_database_unittest.cc
index fe1bc14f8e3..4fb0925c658 100644
--- a/chromium/components/history/core/browser/visit_database_unittest.cc
+++ b/chromium/components/history/core/browser/visit_database_unittest.cc
@@ -554,19 +554,19 @@ TEST_F(VisitDatabaseTest, GetHistoryCount) {
EXPECT_TRUE(GetHistoryCount(Time(), Time::Max(), &result));
EXPECT_EQ(5, result);
- // Narrowing the range to exclude |first_day_1| will still return 5,
- // because |first_day_1| is not unique.
+ // Narrowing the range to exclude `first_day_1` will still return 5,
+ // because `first_day_1` is not unique.
EXPECT_TRUE(
GetHistoryCount(two_days_ago + TimeDelta::FromHours(2), today, &result));
EXPECT_EQ(5, result);
- // Narrowing the range to exclude |second_day_4| will return 4,
- // because |second_day_4| is unique.
+ // Narrowing the range to exclude `second_day_4` will return 4,
+ // because `second_day_4` is unique.
EXPECT_TRUE(GetHistoryCount(two_days_ago, yesterday + TimeDelta::FromHours(3),
&result));
EXPECT_EQ(4, result);
- // Narrowing the range to exclude both |first_day_1| and |second_day_4| will
+ // Narrowing the range to exclude both `first_day_1` and `second_day_4` will
// still return 4.
EXPECT_TRUE(GetHistoryCount(two_days_ago + TimeDelta::FromHours(2),
yesterday + TimeDelta::FromHours(3), &result));
@@ -582,7 +582,7 @@ TEST_F(VisitDatabaseTest, GetHistoryCount) {
// TimeDelta::FromDays(1) to move one day, as this simply removes 24 hours and
// thus does not work correctly with DST shifts. Instead, we'll go back
// 1 second (i.e. somewhere in the middle of the previous day), and use
- // |LocalMidnight()| to round down to the beginning of the day in the local
+ // `LocalMidnight()` to round down to the beginning of the day in the local
// time, taking timezones and DST into account. This is necessary to achieve
// the same equivalence class on days as the DATE(..., 'localtime') function
// in SQL.
@@ -824,7 +824,7 @@ TEST_F(VisitDatabaseTest, GetLastVisitToURL) {
base::Time::FromTimeT(1000), &last_visit));
EXPECT_EQ(last_visit, base::Time::FromTimeT(200));
}
- // Test getting the older visit using an |end_time| of 150.
+ // Test getting the older visit using an `end_time` of 150.
{
base::Time last_visit;
EXPECT_TRUE(GetLastVisitToURL(GURL("https://foo.com/bar/baz"),
diff --git a/chromium/components/history/core/browser/visitsegment_database.cc b/chromium/components/history/core/browser/visitsegment_database.cc
index e1b6b6011fa..9dc5fc29d70 100644
--- a/chromium/components/history/core/browser/visitsegment_database.cc
+++ b/chromium/components/history/core/browser/visitsegment_database.cc
@@ -329,7 +329,7 @@ bool VisitSegmentDatabase::MigrateVisitSegmentNames() {
SegmentID to_segment_id = GetSegmentNamed(new_name);
if (to_segment_id) {
- // |new_name| is already in use, so merge.
+ // `new_name` is already in use, so merge.
success = success && MergeSegments(/*from_segment_id=*/id, to_segment_id);
} else {
// Trivial rename of the segment.
@@ -355,8 +355,8 @@ bool VisitSegmentDatabase::MergeSegments(SegmentID from_segment_id,
return false;
// For each time slot where there are visits for the absorbed segment
- // (|from_segment_id|), add them to the absorbing/staying segment
- // (|to_segment_id|).
+ // (`from_segment_id`), add them to the absorbing/staying segment
+ // (`to_segment_id`).
sql::Statement select(
GetDB().GetCachedStatement(SQL_FROM_HERE,
"SELECT time_slot, visit_count FROM "
diff --git a/chromium/components/history/core/browser/visitsegment_database.h b/chromium/components/history/core/browser/visitsegment_database.h
index 629f1e19909..a3b5aef368d 100644
--- a/chromium/components/history/core/browser/visitsegment_database.h
+++ b/chromium/components/history/core/browser/visitsegment_database.h
@@ -35,9 +35,9 @@ class VisitSegmentDatabase {
// is no segment with that name.
SegmentID GetSegmentNamed(const std::string& segment_name);
- // Update the segment identified by |out_segment_id| with the provided URL ID.
+ // Update the segment identified by `out_segment_id` with the provided URL ID.
// The URL identifies the page that will now represent the segment. If url_id
- // is non zero, it is assumed to be the row id of |url|.
+ // is non zero, it is assumed to be the row id of `url`.
bool UpdateSegmentRepresentationURL(SegmentID segment_id,
URLID url_id);
@@ -50,9 +50,9 @@ class VisitSegmentDatabase {
bool IncreaseSegmentVisitCount(SegmentID segment_id, base::Time ts,
int amount);
- // Computes the segment usage since |from_time|. If |url_filter| is non-null,
+ // Computes the segment usage since `from_time`. If `url_filter` is non-null,
// then only URLs for which it returns true will be included.
- // Returns the highest-scored segments up to |max_result_count|.
+ // Returns the highest-scored segments up to `max_result_count`.
std::vector<std::unique_ptr<PageUsageData>> QuerySegmentUsage(
base::Time from_time,
int max_result_count,
@@ -79,16 +79,16 @@ class VisitSegmentDatabase {
// Runs ComputeSegmentName() to recompute 'name'. If multiple segments have
// the same name, they are merged by:
- // 1. Choosing one arbitrary |segment_id| and updating all references.
- // 2. Merging duplicate |segment_usage| entries (add up visit counts).
+ // 1. Choosing one arbitrary `segment_id` and updating all references.
+ // 2. Merging duplicate `segment_usage` entries (add up visit counts).
// 3. Deleting old data for the absorbed segment.
bool MigrateVisitSegmentNames();
private:
- // Updates the |name| column for a single segment. Returns true on success.
+ // Updates the `name` column for a single segment. Returns true on success.
bool RenameSegment(SegmentID segment_id, const std::string& new_name);
// Merges two segments such that data is aggregated, all former references to
- // |from_segment_id| are updated to |to_segment_id| and |from_segment_id| is
+ // `from_segment_id` are updated to `to_segment_id` and `from_segment_id` is
// deleted. Returns true on success.
bool MergeSegments(SegmentID from_segment_id, SegmentID to_segment_id);
diff --git a/chromium/components/history/core/browser/web_history_service.cc b/chromium/components/history/core/browser/web_history_service.cc
index 5f64ac3610c..6a5059cda18 100644
--- a/chromium/components/history/core/browser/web_history_service.cc
+++ b/chromium/components/history/core/browser/web_history_service.cc
@@ -13,7 +13,6 @@
#include "base/json/json_writer.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
@@ -34,6 +33,7 @@
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace history {
@@ -111,7 +111,7 @@ class RequestImpl : public WebHistoryService::Request {
UMA_HISTOGRAM_BOOLEAN("WebHistory.OAuthTokenCompletion", false);
std::move(callback_).Run(this, false);
- // It is valid for the callback to delete |this|, so do not access any
+ // It is valid for the callback to delete `this`, so do not access any
// members below here.
return;
}
@@ -210,7 +210,7 @@ class RequestImpl : public WebHistoryService::Request {
}
is_pending_ = false;
std::move(callback_).Run(this, true);
- // It is valid for the callback to delete |this|, so do not access any
+ // It is valid for the callback to delete `this`, so do not access any
// members below here.
}
@@ -235,7 +235,7 @@ class RequestImpl : public WebHistoryService::Request {
GURL url_;
// POST data to be sent with the request (may be empty).
- base::Optional<std::string> post_data_;
+ absl::optional<std::string> post_data_;
// MIME type of the post requests. Defaults to text/plain.
std::string post_data_mime_type_;
@@ -283,7 +283,7 @@ std::string ServerTimeString(base::Time time) {
}
// Returns a URL for querying the history server for a query specified by
-// |options|. |version_info|, if not empty, should be a token that was received
+// `options`. `version_info`, if not empty, should be a token that was received
// from the server in response to a write operation. It is used to help ensure
// read consistency after a write.
GURL GetQueryUrl(const std::u16string& text_query,
@@ -292,9 +292,9 @@ GURL GetQueryUrl(const std::u16string& text_query,
GURL url = GURL(kHistoryQueryHistoryUrl);
url = net::AppendQueryParameter(url, "titles", "1");
- // Take |begin_time|, |end_time|, and |max_count| from the original query
+ // Take `begin_time`, `end_time`, and `max_count` from the original query
// options, and convert them to the equivalent URL parameters. Note that
- // QueryOptions uses exclusive |end_time| while the history.google.com API
+ // QueryOptions uses exclusive `end_time` while the history.google.com API
// uses it inclusively, so we subtract 1us during conversion.
base::Time end_time =
@@ -325,7 +325,7 @@ GURL GetQueryUrl(const std::u16string& text_query,
// Creates a DictionaryValue to hold the parameters for a deletion.
// Ownership is passed to the caller.
-// |url| may be empty, indicating a time-range deletion.
+// `url` may be empty, indicating a time-range deletion.
std::unique_ptr<base::DictionaryValue> CreateDeletion(
const std::string& min_time,
const std::string& max_time,
@@ -616,7 +616,7 @@ void WebHistoryService::AudioHistoryCompletionCallback(
}
// If there is no response_value, then for our purposes, the request has
- // failed, despite receiving a true |success| value. This can happen if
+ // failed, despite receiving a true `success` value. This can happen if
// the user is offline.
std::move(callback).Run(success && response_value, enabled_value);
}
diff --git a/chromium/components/history/core/browser/web_history_service.h b/chromium/components/history/core/browser/web_history_service.h
index 55a2ee3a681..f10d26efc1c 100644
--- a/chromium/components/history/core/browser/web_history_service.h
+++ b/chromium/components/history/core/browser/web_history_service.h
@@ -104,9 +104,9 @@ class WebHistoryService : public KeyedService {
void AddObserver(WebHistoryServiceObserver* observer);
void RemoveObserver(WebHistoryServiceObserver* observer);
- // Searches synced history for visits matching |text_query|. The timeframe to
- // search, along with other options, is specified in |options|. If
- // |text_query| is empty, all visits in the timeframe will be returned.
+ // Searches synced history for visits matching `text_query`. The timeframe to
+ // search, along with other options, is specified in `options`. If
+ // `text_query` is empty, all visits in the timeframe will be returned.
// This method is the equivalent of HistoryService::QueryHistory.
// The caller takes ownership of the returned Request. If it is destroyed, the
// request is cancelled.
@@ -139,7 +139,7 @@ class WebHistoryService : public KeyedService {
const net::PartialNetworkTrafficAnnotationTag&
partial_traffic_annotation);
- // Sets the state of audio history recording to |new_enabled_value|.
+ // Sets the state of audio history recording to `new_enabled_value`.
virtual void SetAudioHistoryEnabled(
bool new_enabled_value,
AudioWebHistoryCallback callback,
@@ -171,44 +171,44 @@ class WebHistoryService : public KeyedService {
partial_traffic_annotation);
// Extracts a JSON-encoded HTTP response into a DictionaryValue.
- // If |request|'s HTTP response code indicates failure, or if the response
+ // If `request`'s HTTP response code indicates failure, or if the response
// body is not JSON, a null pointer is returned.
static std::unique_ptr<base::DictionaryValue> ReadResponse(Request* request);
- // Called by |request| when a web history query has completed. Unpacks the
- // response and calls |callback|, which is the original callback that was
+ // Called by `request` when a web history query has completed. Unpacks the
+ // response and calls `callback`, which is the original callback that was
// passed to QueryHistory().
static void QueryHistoryCompletionCallback(
WebHistoryService::QueryWebHistoryCallback callback,
WebHistoryService::Request* request,
bool success);
- // Called by |request| when a request to delete history from the server has
- // completed. Unpacks the response and calls |callback|, which is the original
+ // Called by `request` when a request to delete history from the server has
+ // completed. Unpacks the response and calls `callback`, which is the original
// callback that was passed to ExpireHistory().
void ExpireHistoryCompletionCallback(
WebHistoryService::ExpireWebHistoryCallback callback,
WebHistoryService::Request* request,
bool success);
- // Called by |request| when a request to get or set audio history from the
- // server has completed. Unpacks the response and calls |callback|, which is
+ // Called by `request` when a request to get or set audio history from the
+ // server has completed. Unpacks the response and calls `callback`, which is
// the original callback that was passed to AudioHistory().
void AudioHistoryCompletionCallback(
WebHistoryService::AudioWebHistoryCallback callback,
WebHistoryService::Request* request,
bool success);
- // Called by |request| when a web and app activity query has completed.
- // Unpacks the response and calls |callback|, which is the original callback
+ // Called by `request` when a web and app activity query has completed.
+ // Unpacks the response and calls `callback`, which is the original callback
// that was passed to QueryWebAndAppActivity().
void QueryWebAndAppActivityCompletionCallback(
WebHistoryService::QueryWebAndAppActivityCallback callback,
WebHistoryService::Request* request,
bool success);
- // Called by |request| when a query for other forms of browsing history has
- // completed. Unpacks the response and calls |callback|, which is the original
+ // Called by `request` when a query for other forms of browsing history has
+ // completed. Unpacks the response and calls `callback`, which is the original
// callback that was passed to QueryOtherFormsOfBrowsingHistory().
void QueryOtherFormsOfBrowsingHistoryCompletionCallback(
WebHistoryService::QueryWebAndAppActivityCallback callback,
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 d7cae239441..1e1caae69ba 100644
--- a/chromium/components/history/core/browser/web_history_service_unittest.cc
+++ b/chromium/components/history/core/browser/web_history_service_unittest.cc
@@ -179,7 +179,7 @@ std::unique_ptr<base::DictionaryValue> TestingWebHistoryService::ReadResponse(
void TestingWebHistoryService::SetAudioHistoryCallback(
bool success, bool new_enabled_value) {
EXPECT_TRUE(success);
- // |new_enabled_value| should be equal to whatever the audio history value
+ // `new_enabled_value` should be equal to whatever the audio history value
// was just set to.
EXPECT_EQ(expected_audio_history_value_, new_enabled_value);
}
diff --git a/chromium/components/history/core/common/thumbnail_score.h b/chromium/components/history/core/common/thumbnail_score.h
index 7ab7750e772..ba62d429c98 100644
--- a/chromium/components/history/core/common/thumbnail_score.h
+++ b/chromium/components/history/core/common/thumbnail_score.h
@@ -48,7 +48,7 @@ struct ThumbnailScore {
// Whether the thumbnail was taken with height greater than
// width or width greater than height and the aspect ratio less than
- // kTooWideAspectRatio. In cases where we don't have |good_clipping|,
+ // kTooWideAspectRatio. In cases where we don't have `good_clipping`,
// the thumbnails are either clipped from the horizontal center of the
// window, or are otherwise weirdly stretched.
bool good_clipping;
@@ -57,7 +57,7 @@ struct ThumbnailScore {
// displaying the top of the page. Most pages are more recognizable
// by their headers then by a set of random text half way down the
// page; i.e. most MediaWiki sites would be indistinguishable by
- // thumbnails with |at_top| set to false.
+ // thumbnails with `at_top` set to false.
bool at_top;
// Whether this thumbnail was taken after load was completed.
@@ -95,7 +95,7 @@ struct ThumbnailScore {
static const double kThumbnailDegradePerHour;
// If a thumbnail is taken with the aspect ratio greater than or equal to
- // this value, |good_clipping| is to false.
+ // this value, `good_clipping` is to false.
static const double kTooWideAspectRatio;
// Checks whether we should consider updating a new thumbnail based on
diff --git a/chromium/components/history/ios/OWNERS b/chromium/components/history/ios/OWNERS
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/components/history/ios/OWNERS
+++ /dev/null
diff --git a/chromium/components/history/ios/browser/history_database_helper.h b/chromium/components/history/ios/browser/history_database_helper.h
index 3093efe3ddd..1f5df5e9f9a 100644
--- a/chromium/components/history/ios/browser/history_database_helper.h
+++ b/chromium/components/history/ios/browser/history_database_helper.h
@@ -13,7 +13,7 @@ namespace history {
struct HistoryDatabaseParams;
-// Returns a HistoryDatabaseParams for |history_dir|.
+// Returns a HistoryDatabaseParams for `history_dir`.
HistoryDatabaseParams HistoryDatabaseParamsForPath(
const base::FilePath& history_dir);
diff --git a/chromium/components/history/metrics/domain_diversity_reporter.cc b/chromium/components/history/metrics/domain_diversity_reporter.cc
index 244c69d3cda..b5c7dd4e9a8 100644
--- a/chromium/components/history/metrics/domain_diversity_reporter.cc
+++ b/chromium/components/history/metrics/domain_diversity_reporter.cc
@@ -84,7 +84,7 @@ void DomainDiversityReporter::ComputeDomainMetrics() {
int number_of_days_to_report = 7;
// If the last report time is too far back in the past, simply use the
- // highest possible value for |number_of_days_to_report| and skip its
+ // highest possible value for `number_of_days_to_report` and skip its
// computation. This avoids calling LocalMidnight() on some very old
// timestamp that may cause unexpected behaviors on certain
// platforms/timezones (see https://crbug.com/1048145).
@@ -98,9 +98,9 @@ void DomainDiversityReporter::ComputeDomainMetrics() {
time_current_report_triggered.LocalMidnight() -
time_last_report_triggered.LocalMidnight();
- // Due to daylight saving time, |report_time_range| may not be a multiple
+ // Due to daylight saving time, `report_time_range` may not be a multiple
// of 24 hours. A small time offset is therefore added to
- // |report_time_range| so that the resulting time range is guaranteed to
+ // `report_time_range` so that the resulting time range is guaranteed to
// be at least the correct number of days times 24. The number of days to
// report is capped at 7 days.
number_of_days_to_report = std::min(
@@ -134,7 +134,7 @@ void DomainDiversityReporter::ReportDomainMetrics(
history::DomainDiversityResults result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // An empty DomainDiversityResults indicates that |db_| is null in
+ // An empty DomainDiversityResults indicates that `db_` is null in
// HistoryBackend.
if (result.empty())
return;
diff --git a/chromium/components/history/metrics/domain_diversity_reporter.h b/chromium/components/history/metrics/domain_diversity_reporter.h
index 2a866b981b6..134e45692a4 100644
--- a/chromium/components/history/metrics/domain_diversity_reporter.h
+++ b/chromium/components/history/metrics/domain_diversity_reporter.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_HISTORY_METRICS_DOMAIN_DIVERSITY_REPORTER_H_
#define COMPONENTS_HISTORY_METRICS_DOMAIN_DIVERSITY_REPORTER_H_
-#include <vector>
-
#include "base/scoped_observation.h"
#include "base/sequence_checker.h"
#include "base/time/clock.h"
@@ -29,7 +27,7 @@ class DomainDiversityReporter : public KeyedService,
base::Clock* clock);
~DomainDiversityReporter() override;
- // Registers Profile preferences in |registry|.
+ // Registers Profile preferences in `registry`.
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
// Invokes ComputeDomainMetrics() if history backend is already loaded.
@@ -71,4 +69,4 @@ class DomainDiversityReporter : public KeyedService,
DISALLOW_COPY_AND_ASSIGN(DomainDiversityReporter);
};
-#endif // COMPONENTS_HISTORY_MERICS_DOMAIN_DIVERSITY_REPORTER_H_
+#endif // COMPONENTS_HISTORY_METRICS_DOMAIN_DIVERSITY_REPORTER_H_
diff --git a/chromium/components/history/metrics/domain_diversity_reporter_unittest.cc b/chromium/components/history/metrics/domain_diversity_reporter_unittest.cc
index 299c99bd17a..bd0dd1a6610 100644
--- a/chromium/components/history/metrics/domain_diversity_reporter_unittest.cc
+++ b/chromium/components/history/metrics/domain_diversity_reporter_unittest.cc
@@ -103,10 +103,10 @@ class DomainDiversityReporterTest : public testing::Test {
TestClock& test_clock() { return test_clock_; }
protected:
- // A |task_environment_| configured to MOCK_TIME so tests can
+ // A `task_environment_` configured to MOCK_TIME so tests can
// FastForwardAndWait() when waiting for a specific timeout (delayed task)
- // to fire. DomainDiversityReporter internally uses a |test_clock_| instead of
- // |task_environment_|'s clock because it needs to test very specific times
+ // to fire. DomainDiversityReporter internally uses a `test_clock_` instead of
+ // `task_environment_`'s clock because it needs to test very specific times
// rather than just advance in deltas from Now().
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
diff --git a/chromium/components/history_clusters/core/BUILD.gn b/chromium/components/history_clusters/core/BUILD.gn
index 01382cc2e17..ef5a1aa5063 100644
--- a/chromium/components/history_clusters/core/BUILD.gn
+++ b/chromium/components/history_clusters/core/BUILD.gn
@@ -6,20 +6,21 @@ import("//mojo/public/tools/bindings/mojom.gni")
static_library("core") {
sources = [
+ "history_clusters_service.cc",
+ "history_clusters_service.h",
"memories_features.cc",
"memories_features.h",
"memories_remote_model_helper.cc",
"memories_remote_model_helper.h",
- "memories_service.cc",
- "memories_service.h",
"visit_data.h",
]
deps = [
":mojo_bindings",
"//base",
"//components/history/core/browser",
+ "//components/history_clusters/core/proto",
"//components/keyed_service/core",
- "//services/data_decoder/public/cpp",
+ "//components/query_parser",
"//services/network/public/cpp",
"//url",
]
@@ -36,13 +37,14 @@ mojom("mojo_bindings") {
source_set("unit_tests") {
testonly = true
- sources = [ "memories_service_unittest.cc" ]
+ sources = [ "history_clusters_service_unittest.cc" ]
deps = [
":core",
":test_support",
"//base/test:test_support",
"//components/history/core/browser",
- "//services/data_decoder/public/cpp:test_support",
+ "//components/history/core/test",
+ "//components/history_clusters/core/proto",
"//services/network:test_support",
"//testing/gtest",
]
@@ -50,6 +52,9 @@ source_set("unit_tests") {
source_set("test_support") {
testonly = true
- sources = [ "memories_service_test_api.h" ]
- deps = [ ":core" ]
+ sources = [ "history_clusters_service_test_api.h" ]
+ deps = [
+ ":core",
+ "//components/history/core/browser",
+ ]
}
diff --git a/chromium/components/history_clusters/core/DEPS b/chromium/components/history_clusters/core/DEPS
index 654cc9f4af3..81c75d6faea 100644
--- a/chromium/components/history_clusters/core/DEPS
+++ b/chromium/components/history_clusters/core/DEPS
@@ -1,7 +1,7 @@
include_rules = [
"+components/history/core",
"+components/keyed_service/core",
- "+services/data_decoder/public/cpp",
+ "+components/query_parser",
"+services/network/public/cpp",
"+services/network/test",
]
diff --git a/chromium/components/history_clusters/core/history_clusters_service.cc b/chromium/components/history_clusters/core/history_clusters_service.cc
new file mode 100644
index 00000000000..d9f197ae81a
--- /dev/null
+++ b/chromium/components/history_clusters/core/history_clusters_service.cc
@@ -0,0 +1,233 @@
+// Copyright 2021 The Chromium Authors. 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_clusters/core/history_clusters_service.h"
+
+#include <numeric>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/feature_list.h"
+#include "base/i18n/case_conversion.h"
+#include "base/ranges/algorithm.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/history_clusters/core/memories_features.h"
+#include "components/query_parser/query_parser.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace history_clusters {
+
+namespace {
+
+// Filter `clusters` matching `query`. There are additional filters (e.g.
+// `recency_threshold`) used when requesting `QueryMemories()`, but this
+// function is only responsible for matching `query`.
+std::vector<history::Cluster> FilterClustersMatchingQuery(
+ std::string query,
+ std::vector<history::Cluster> clusters) {
+ if (query.empty())
+ return clusters;
+
+ // Extract query nodes from the query string.
+ query_parser::QueryNodeVector query_nodes;
+ query_parser::QueryParser::ParseQueryNodes(
+ base::UTF8ToUTF16(query),
+ query_parser::MatchingAlgorithm::ALWAYS_PREFIX_SEARCH, &query_nodes);
+
+ std::vector<history::Cluster> matching_clusters;
+ base::ranges::copy_if(clusters, std::back_inserter(matching_clusters),
+ [&](const auto& cluster) {
+ query_parser::QueryWordVector find_in_words;
+ for (auto& keyword : cluster.keywords) {
+ // Each `keyword` may itself have multiple terms
+ // that we need to extract and append to
+ // `find_in_words`.
+ query_parser::QueryParser::ExtractQueryWords(
+ base::i18n::ToLower(keyword), &find_in_words);
+ }
+
+ return query_parser::QueryParser::DoesQueryMatch(
+ find_in_words, query_nodes);
+ });
+ return matching_clusters;
+}
+
+// TODO(manukh): Move mojom translation to `MemoriesHandler` once we've created
+// a mirror cpp struct the `MemoryService` can return instead. There's no need
+// to do this yet, since the `MemoriesHandler` is the only consumer of
+// `HistoryClustersService`, but once the omnibox comes into play, we'll need a
+// common non-mojom response.
+// TODO(crbug.com/1179069): fill out the remaining Memories mojom fields.
+// Translate a `AnnotatedVisit` to `mojom::VisitPtr`.
+history_clusters::mojom::VisitPtr VisitToMojom(
+ const history::AnnotatedVisit& visit) {
+ auto visit_mojom = history_clusters::mojom::Visit::New();
+ visit_mojom->id = visit.visit_row.visit_id;
+ visit_mojom->url = visit.url_row.url();
+ visit_mojom->time = visit.visit_row.visit_time;
+ visit_mojom->page_title = base::UTF16ToUTF8(visit.url_row.title());
+ return visit_mojom;
+}
+
+// Translate a vector of `Cluster`s to a vector of `mojom::MemoryPtr`s.
+std::vector<history_clusters::mojom::MemoryPtr> ClustersToMojom(
+ const std::vector<history::Cluster>& clusters) {
+ std::vector<history_clusters::mojom::MemoryPtr> clusters_mojom;
+ for (const auto& cluster : clusters) {
+ auto cluster_mojom = history_clusters::mojom::Memory::New();
+ cluster_mojom->id = base::UnguessableToken::Create();
+ for (const auto& keyword : cluster.keywords)
+ cluster_mojom->keywords.push_back(keyword);
+ for (const auto& visit : cluster.annotated_visits)
+ cluster_mojom->top_visits.push_back(VisitToMojom(visit));
+ clusters_mojom.emplace_back(std::move(cluster_mojom));
+ }
+ return clusters_mojom;
+}
+
+// Form a `QueryMemoriesResponse` containing `clusters` and continuation query
+// params meant to be used in a follow-up request. `query_params` are the params
+// used to get `clusters` from `QueryMemories()`.
+// TODO(mahmadi): At the moment, the recency threshold of `query_params` is
+// ignored and continuation query params is set to nullptr. The service does
+// not support paging.
+HistoryClustersService::QueryMemoriesResponse FormQueryMemoriesResponse(
+ mojom::QueryParamsPtr query_params,
+ std::vector<history::Cluster> clusters) {
+ return {nullptr, ClustersToMojom(clusters)};
+}
+
+} // namespace
+
+HistoryClustersService::QueryMemoriesResponse::QueryMemoriesResponse(
+ mojom::QueryParamsPtr query_params,
+ std::vector<mojom::MemoryPtr> clusters)
+ : query_params(std::move(query_params)), clusters(std::move(clusters)) {}
+
+HistoryClustersService::QueryMemoriesResponse::QueryMemoriesResponse(
+ QueryMemoriesResponse&& other) = default;
+
+HistoryClustersService::QueryMemoriesResponse::~QueryMemoriesResponse() =
+ default;
+
+HistoryClustersService::HistoryClustersService(
+ history::HistoryService* history_service,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ : history_service_(history_service) {
+ remote_model_helper_ = std::make_unique<MemoriesRemoteModelHelper>(
+ url_loader_factory,
+ base::BindRepeating(&HistoryClustersService::NotifyDebugMessage,
+ weak_ptr_factory_.GetWeakPtr()));
+ remote_model_helper_weak_factory_ =
+ std::make_unique<base::WeakPtrFactory<MemoriesRemoteModelHelper>>(
+ remote_model_helper_.get());
+}
+
+HistoryClustersService::~HistoryClustersService() = default;
+
+void HistoryClustersService::Shutdown() {}
+
+void HistoryClustersService::AddObserver(Observer* obs) {
+ observers_.AddObserver(obs);
+}
+
+void HistoryClustersService::RemoveObserver(Observer* obs) {
+ observers_.RemoveObserver(obs);
+}
+
+void HistoryClustersService::NotifyDebugMessage(
+ const std::string& message) const {
+ for (Observer& obs : observers_) {
+ obs.OnMemoriesDebugMessage(message);
+ }
+}
+
+IncompleteVisitContextAnnotations&
+HistoryClustersService::GetIncompleteVisitContextAnnotations(int64_t nav_id) {
+ DCHECK(HasIncompleteVisitContextAnnotations(nav_id));
+ return GetOrCreateIncompleteVisitContextAnnotations(nav_id);
+}
+
+IncompleteVisitContextAnnotations&
+HistoryClustersService::GetOrCreateIncompleteVisitContextAnnotations(
+ int64_t nav_id) {
+ return incomplete_visit_context_annotations_[nav_id];
+}
+
+bool HistoryClustersService::HasIncompleteVisitContextAnnotations(
+ int64_t nav_id) {
+ return incomplete_visit_context_annotations_.count(nav_id);
+}
+
+void HistoryClustersService::CompleteVisitContextAnnotationsIfReady(
+ int64_t nav_id) {
+ auto& visit_context_annotations =
+ GetIncompleteVisitContextAnnotations(nav_id);
+ DCHECK((visit_context_annotations.status.history_rows &&
+ visit_context_annotations.status.navigation_ended) ||
+ !visit_context_annotations.status.navigation_end_signals);
+ DCHECK(visit_context_annotations.status.expect_ukm_page_end_signals ||
+ !visit_context_annotations.status.ukm_page_end_signals);
+ if (visit_context_annotations.status.history_rows &&
+ visit_context_annotations.status.navigation_end_signals &&
+ (visit_context_annotations.status.ukm_page_end_signals ||
+ !visit_context_annotations.status.expect_ukm_page_end_signals)) {
+ if (base::FeatureList::IsEnabled(kMemories)) {
+ if (kPersistContextAnnotationsInHistoryDb.Get())
+ history_service_->AddContextAnnotationsForVisit(
+ visit_context_annotations.visit_row.visit_id,
+ visit_context_annotations.context_annotations);
+ else
+ visits_.push_back({visit_context_annotations.url_row,
+ visit_context_annotations.visit_row,
+ visit_context_annotations.context_annotations,
+ {}});
+ }
+ incomplete_visit_context_annotations_.erase(nav_id);
+ }
+}
+
+void HistoryClustersService::QueryMemories(
+ mojom::QueryParamsPtr query_params,
+ base::OnceCallback<void(QueryMemoriesResponse)> callback,
+ base::CancelableTaskTracker* task_tracker) {
+ // `QueryMemories` has 4 steps:
+ // 1. Get visits either asynchronously from the history db or synchronously
+ // from `visits_`.
+ // 2. Ask `remote_model_helper_` to convert the visits to memories.
+ // 3. Filter memories matching `query_params` and create.
+ // 4. Run `callback` with the continuation query params and matched memories.
+
+ // Copy `query_params->query` because `query_params` is about to be moved.
+ auto query_string = query_params->query;
+ auto on_visits_callback =
+ base::BindOnce(&MemoriesRemoteModelHelper::GetMemories,
+ remote_model_helper_weak_factory_->GetWeakPtr(),
+ base::BindOnce(&FilterClustersMatchingQuery, query_string)
+ .Then(base::BindOnce(&FormQueryMemoriesResponse,
+ std::move(query_params)))
+ .Then(std::move(callback)));
+
+ if (kPersistContextAnnotationsInHistoryDb.Get()) {
+ history_service_->GetAnnotatedVisits(
+ kMaxVisitsToCluster.Get(),
+ base::BindOnce(
+ // This echo callback is necessary to copy the `AnnotatedVisit`
+ // refs.
+ [](std::vector<history::AnnotatedVisit> visits) { return visits; })
+ .Then(std::move(on_visits_callback)),
+ task_tracker);
+ } else
+ std::move(on_visits_callback).Run(visits_);
+}
+
+void HistoryClustersService::RemoveVisits(
+ const std::vector<history::ExpireHistoryArgs>& expire_list,
+ base::OnceClosure closure,
+ base::CancelableTaskTracker* task_tracker) {
+ std::move(closure).Run();
+ // TODO(crbug.com/1203789): Remove the visits from relevant history tables.
+}
+
+} // namespace history_clusters
diff --git a/chromium/components/history_clusters/core/history_clusters_service.h b/chromium/components/history_clusters/core/history_clusters_service.h
new file mode 100644
index 00000000000..141fba7a36a
--- /dev/null
+++ b/chromium/components/history_clusters/core/history_clusters_service.h
@@ -0,0 +1,132 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_HISTORY_CLUSTERS_CORE_HISTORY_CLUSTERS_SERVICE_H_
+#define COMPONENTS_HISTORY_CLUSTERS_CORE_HISTORY_CLUSTERS_SERVICE_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/task/cancelable_task_tracker.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/history/core/browser/history_types.h"
+#include "components/history_clusters/core/memories.mojom.h"
+#include "components/history_clusters/core/memories_remote_model_helper.h"
+#include "components/history_clusters/core/visit_data.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace history_clusters {
+
+// This Service is the API for UIs to fetch Chrome Memories.
+class HistoryClustersService : public KeyedService {
+ public:
+ class Observer : public base::CheckedObserver {
+ public:
+ virtual void OnMemoriesDebugMessage(const std::string& message) = 0;
+ };
+
+ struct QueryMemoriesResponse {
+ QueryMemoriesResponse(mojom::QueryParamsPtr query_params,
+ std::vector<mojom::MemoryPtr> clusters);
+ QueryMemoriesResponse(QueryMemoriesResponse&& other);
+ ~QueryMemoriesResponse();
+ mojom::QueryParamsPtr query_params;
+ std::vector<mojom::MemoryPtr> clusters;
+ };
+
+ explicit HistoryClustersService(
+ history::HistoryService* history_service,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+ HistoryClustersService(const HistoryClustersService&) = delete;
+ HistoryClustersService& operator=(const HistoryClustersService&) = delete;
+ ~HistoryClustersService() override;
+
+ // KeyedService:
+ void Shutdown() override;
+
+ // Used to add and remove observers.
+ void AddObserver(Observer* obs);
+ void RemoveObserver(Observer* obs);
+
+ // Notifies the observers of a debug message being available.
+ void NotifyDebugMessage(const std::string& message) const;
+
+ // TODO(manukh) `HistoryClustersService` should be responsible for
+ // constructing the
+ // `AnnotatedVisit`s rather than exposing these methods which are used by
+ // `HistoryClustersTabHelper` to construct the visits.
+ // Gets an `IncompleteVisitContextAnnotations` after DCHECKing it exists; this
+ // saves the call sites the effort.
+ IncompleteVisitContextAnnotations& GetIncompleteVisitContextAnnotations(
+ int64_t nav_id);
+ // Gets or creates an `IncompleteVisitContextAnnotations`.
+ IncompleteVisitContextAnnotations&
+ GetOrCreateIncompleteVisitContextAnnotations(int64_t nav_id);
+ // Returns whether an `IncompleteVisitContextAnnotations` exists.
+ // TODO(manukh): Merge `HasIncompleteVisitContextAnnotations()` and
+ // `GetIncompleteVisitContextAnnotations()`.
+ bool HasIncompleteVisitContextAnnotations(int64_t nav_id);
+ // Completes the `IncompleteVisitContextAnnotations` if the expected metrics
+ // have been recorded. References retrieved prior will no longer be valid.
+ void CompleteVisitContextAnnotationsIfReady(int64_t nav_id);
+
+ // Returns the freshest Memories created from the user visit history, in
+ // reverse chronological order, based on the parameters in `query_params`
+ // along with continuation query params meant to be used in the follow-up
+ // request to load older Memories.
+ // Note: At the moment, this method asks `remote_model_helper_` to construct
+ // Memories from `visits_`.
+ void QueryMemories(mojom::QueryParamsPtr query_params,
+ base::OnceCallback<void(QueryMemoriesResponse)> callback,
+ base::CancelableTaskTracker* task_tracker);
+ // Removes all visits to the specified URLs in the specified time ranges in
+ // `expire_list`. Calls `closure` when done.
+ void RemoveVisits(const std::vector<history::ExpireHistoryArgs>& expire_list,
+ base::OnceClosure closure,
+ base::CancelableTaskTracker* task_tracker);
+
+ private:
+ friend class HistoryClustersServiceTestApi;
+
+ // If the Memories flag is enabled, this contains all the visits in-memory
+ // during the Profile lifetime. If the `kPersistContextAnnotationsInHistoryDb`
+ // param is true, this will be empty.
+ // TODO(tommycli): Hide this better behind a new debug flag.
+ std::vector<history::AnnotatedVisit> visits_;
+
+ // `VisitContextAnnotations`s are constructed stepwise; they're initially
+ // placed in `incomplete_visit_context_annotations_` and moved either to
+ // `visits_` or the history database once completed.
+ std::map<int64_t, IncompleteVisitContextAnnotations>
+ incomplete_visit_context_annotations_;
+
+ history::HistoryService* history_service_;
+
+ // Helper service to handle communicating with the remote model. This will be
+ // used for debugging only; the launch ready feature will use a local model
+ // instead.
+ std::unique_ptr<MemoriesRemoteModelHelper> remote_model_helper_;
+
+ // A list of observers for this service.
+ base::ObserverList<Observer> observers_;
+
+ // Used to asyncly call into `remote_model_helper_` after async history
+ // request.
+ std::unique_ptr<base::WeakPtrFactory<MemoriesRemoteModelHelper>>
+ remote_model_helper_weak_factory_;
+ // Weak pointers issued from this factory never get invalidated before the
+ // service is destroyed.
+ base::WeakPtrFactory<HistoryClustersService> weak_ptr_factory_{this};
+};
+
+} // namespace history_clusters
+
+#endif // COMPONENTS_HISTORY_CLUSTERS_CORE_HISTORY_CLUSTERS_SERVICE_H_
diff --git a/chromium/components/history_clusters/core/history_clusters_service_test_api.h b/chromium/components/history_clusters/core/history_clusters_service_test_api.h
new file mode 100644
index 00000000000..8f19acd332c
--- /dev/null
+++ b/chromium/components/history_clusters/core/history_clusters_service_test_api.h
@@ -0,0 +1,30 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_HISTORY_CLUSTERS_CORE_HISTORY_CLUSTERS_SERVICE_TEST_API_H_
+#define COMPONENTS_HISTORY_CLUSTERS_CORE_HISTORY_CLUSTERS_SERVICE_TEST_API_H_
+
+#include <vector>
+
+#include "components/history/core/browser/history_types.h"
+#include "components/history_clusters/core/history_clusters_service.h"
+
+namespace history_clusters {
+
+class HistoryClustersServiceTestApi {
+ public:
+ explicit HistoryClustersServiceTestApi(
+ HistoryClustersService* history_clusters_service)
+ : history_clusters_service_(history_clusters_service) {}
+
+ std::vector<history::AnnotatedVisit> GetVisits() const {
+ return history_clusters_service_->visits_;
+ }
+
+ HistoryClustersService* history_clusters_service_;
+};
+
+} // namespace history_clusters
+
+#endif // COMPONENTS_HISTORY_CLUSTERS_CORE_HISTORY_CLUSTERS_SERVICE_TEST_API_H_
diff --git a/chromium/components/history_clusters/core/history_clusters_service_unittest.cc b/chromium/components/history_clusters/core/history_clusters_service_unittest.cc
new file mode 100644
index 00000000000..7e8cce1de9b
--- /dev/null
+++ b/chromium/components/history_clusters/core/history_clusters_service_unittest.cc
@@ -0,0 +1,754 @@
+// Copyright 2021 The Chromium Authors. 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_clusters/core/history_clusters_service.h"
+
+#include <memory>
+#include <string>
+
+#include "base/base64.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/task/cancelable_task_tracker.h"
+#include "base/test/bind.h"
+#include "base/test/gtest_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "components/history/core/browser/history_types.h"
+#include "components/history/core/browser/url_row.h"
+#include "components/history/core/test/history_service_test_util.h"
+#include "components/history_clusters/core/history_clusters_service_test_api.h"
+#include "components/history_clusters/core/memories_features.h"
+#include "components/history_clusters/core/memories_remote_model_helper.h"
+#include "components/history_clusters/core/proto/clusters.pb.h"
+#include "components/history_clusters/core/visit_data.h"
+#include "services/network/public/cpp/data_element.h"
+#include "services/network/public/cpp/resource_request_body.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace history_clusters {
+
+namespace {
+
+// Returns a Time that's `milliseconds` milliseconds after Windows epoch.
+base::Time IntToTime(int milliseconds) {
+ return base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromMilliseconds(milliseconds));
+}
+
+class HistoryClustersServiceTest : public testing::Test {
+ public:
+ HistoryClustersServiceTest()
+ : task_environment_(
+ base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME),
+ shared_url_loader_factory_(
+ base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+ &test_url_loader_factory_)),
+ run_loop_quit_(run_loop_.QuitClosure()) {
+ CHECK(history_dir_.CreateUniqueTempDir());
+ history_service_ =
+ history::CreateHistoryService(history_dir_.GetPath(), true);
+ history_clusters_service_ = std::make_unique<HistoryClustersService>(
+ history_service_.get(), shared_url_loader_factory_);
+ history_clusters_service_test_api_ =
+ std::make_unique<HistoryClustersServiceTestApi>(
+ history_clusters_service_.get());
+ }
+
+ HistoryClustersServiceTest(const HistoryClustersServiceTest&) = delete;
+ HistoryClustersServiceTest& operator=(const HistoryClustersServiceTest&) =
+ delete;
+
+ void EnableMemoriesWithEndpoint(
+ const std::string& endpoint_url = kFakeEndpoint,
+ const std::string& endpoint_experiment = "") {
+ scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
+ scoped_feature_list_->InitWithFeaturesAndParameters(
+ {
+ {
+ kMemories,
+ {},
+ },
+ {
+ kRemoteModelForDebugging,
+ {
+ {"MemoriesRemoteModelEndpoint", endpoint_url},
+ {"MemoriesRemoteModelEndpointExperimentName",
+ endpoint_experiment},
+ },
+ },
+ },
+ {});
+ }
+
+ void AddVisit(int time, const GURL& url) {
+ history::AnnotatedVisit visit;
+ visit.url_row.set_url(url);
+ visit.visit_row.visit_time = IntToTime(time);
+ AddVisit(visit);
+ }
+
+ void AddVisit(history::URLID url_id,
+ const GURL& url,
+ const std::u16string title,
+ history::VisitID visit_id,
+ base::Time visit_time,
+ int page_end_reason) {
+ history::AnnotatedVisit visit;
+ visit.url_row.set_id(url_id);
+ visit.url_row.set_url(url);
+ visit.url_row.set_title(title);
+ visit.visit_row.visit_id = visit_id;
+ visit.visit_row.visit_time = visit_time;
+ visit.context_annotations.page_end_reason = page_end_reason;
+ AddVisit(visit);
+ }
+
+ void AddVisit(const history::AnnotatedVisit& visit) {
+ history_service_->AddPageWithDetails(
+ visit.url_row.url(), visit.url_row.title(), visit.url_row.visit_count(),
+ visit.url_row.typed_count(), visit.visit_row.visit_time,
+ visit.url_row.hidden(), history::VisitSource::SOURCE_BROWSED);
+
+ auto& incomplete_visit_context_annotations =
+ history_clusters_service_->GetOrCreateIncompleteVisitContextAnnotations(
+ next_navigation_id_);
+ incomplete_visit_context_annotations.visit_row = visit.visit_row;
+ incomplete_visit_context_annotations.url_row = visit.url_row;
+ incomplete_visit_context_annotations.context_annotations =
+ visit.context_annotations;
+ incomplete_visit_context_annotations.status.history_rows = true;
+ incomplete_visit_context_annotations.status.navigation_ended = true;
+ incomplete_visit_context_annotations.status.navigation_end_signals = true;
+ history_clusters_service_->CompleteVisitContextAnnotationsIfReady(
+ next_navigation_id_);
+ next_navigation_id_++;
+ }
+
+ // Helper to get the most recent remote request body.
+ std::string GetPendingRequestBody() {
+ const scoped_refptr<network::ResourceRequestBody>& request_body =
+ test_url_loader_factory_.GetPendingRequest(0)->request.request_body;
+ const network::DataElement& element = (*request_body->elements())[0];
+ return std::string(element.As<network::DataElementBytes>().AsStringPiece());
+ }
+
+ // Verifies that that a particular hardcoded request is in a pending request
+ // within the URL loader.
+ void VerifyHardcodedTestDataInUrlLoaderRequest(
+ const std::string& expected_experiment_name = "") {
+ EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ proto::GetClustersRequest request;
+ request.set_experiment_name(expected_experiment_name);
+ auto* visit = request.add_visits();
+ visit->set_visit_id(2);
+ visit->set_navigation_time_ms(2);
+ visit->set_origin("https://google.com/");
+ visit->set_page_end_reason(3);
+ visit->set_url("https://google.com/");
+ visit = request.add_visits();
+ visit->set_visit_id(4);
+ visit->set_navigation_time_ms(4);
+ visit->set_origin("https://github.com/");
+ visit->set_page_end_reason(5);
+ visit->set_url("https://github.com/");
+
+ std::string encoded;
+ base::Base64Encode(request.SerializeAsString(), &encoded);
+ std::string expected_request_body =
+ base::StringPrintf("{\"data\":\"%s\"}", encoded.c_str());
+
+ EXPECT_EQ(GetPendingRequestBody(), expected_request_body);
+ }
+
+ // Fakes a particular partly hardcoded response from the URL loader.
+ void InjectHardcodedTestDataToUrlLoaderResponse(
+ std::vector<std::vector<int>> clustered_visit_ids) {
+ proto::GetClustersResponse response;
+ for (auto visit_ids : clustered_visit_ids) {
+ auto* cluster = response.add_clusters();
+ for (auto visit_id : visit_ids)
+ cluster->add_visit_ids(visit_id);
+ }
+ if (!clustered_visit_ids.empty()) {
+ response.mutable_clusters(0)->mutable_keywords()->Add("apples");
+ // We had a bug where we couldn't match against uppercase keywords,
+ // so we therefore want to test against an uppercase keyword.
+ response.mutable_clusters(0)->mutable_keywords()->Add("Red Oranges");
+ }
+ test_url_loader_factory_.AddResponse(kFakeEndpoint,
+ response.SerializeAsString());
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ }
+
+ base::test::TaskEnvironment task_environment_;
+
+ // Used to construct a `HistoryClustersService`.
+ base::ScopedTempDir history_dir_;
+ std::unique_ptr<history::HistoryService> history_service_;
+
+ static constexpr char kFakeEndpoint[] = "https://endpoint.com/";
+ std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
+
+ network::TestURLLoaderFactory test_url_loader_factory_;
+ scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
+ std::unique_ptr<HistoryClustersService> history_clusters_service_;
+ std::unique_ptr<HistoryClustersServiceTestApi>
+ history_clusters_service_test_api_;
+
+ base::CancelableTaskTracker task_tracker_;
+
+ // Used to verify the async callback is invoked.
+ base::RunLoop run_loop_;
+ base::RepeatingClosure run_loop_quit_;
+
+ // Tracks the next available navigation ID to be associated with visits.
+ int64_t next_navigation_id_ = 0;
+};
+
+// Useless, but required by the C++14 standard. Please deliver us, C++17.
+constexpr char HistoryClustersServiceTest::kFakeEndpoint[];
+
+TEST_F(HistoryClustersServiceTest, QueryMemoriesVariousQueries) {
+ std::string experiment_name = "someExperiment";
+ EnableMemoriesWithEndpoint(kFakeEndpoint, experiment_name);
+
+ AddVisit(0, GURL{"https://google.com"}, u"Google title", 2, IntToTime(2), 3);
+ AddVisit(0, GURL{"https://github.com"}, u"Github title", 4, IntToTime(4), 5);
+
+ struct TestData {
+ std::string query;
+ const bool expect_first_cluster;
+ const bool expect_second_cluster;
+ } test_data[] = {
+ // Empty query should get both.
+ {"", true, true},
+ // Non matching query should get none.
+ {"non_matching_query", false, false},
+ // Query matching one cluster.
+ {"oran", true, false},
+ // This verifies the memory doesn't flicker away as the user is typing
+ // out: "red oran" one key at a time. Also tests out multi-term queries.
+ {"red", true, false},
+ {"red ", true, false},
+ {"red o", true, false},
+ {"red or", true, false},
+ {"red ora", true, false},
+ {"red oran", true, false},
+ };
+
+ for (size_t i = 0; i < base::size(test_data); ++i) {
+ SCOPED_TRACE(base::StringPrintf("Testing case i=%d, query=%s", int(i),
+ test_data[i].query.c_str()));
+
+ base::RunLoop run_loop;
+ auto run_loop_quit = run_loop.QuitClosure();
+
+ test_url_loader_factory_.ClearResponses();
+ ASSERT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ auto query_params = mojom::QueryParams::New();
+ query_params->query = test_data[i].query;
+ history_clusters_service_->QueryMemories(
+ std::move(query_params),
+ // This "expect" block is not run until after the fake response is sent
+ // further down in this method.
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ // Verify that the continuation query params is nullptr.
+ ASSERT_FALSE(!!response.query_params);
+
+ size_t expected_size = int(test_data[i].expect_first_cluster) +
+ int(test_data[i].expect_second_cluster);
+ ASSERT_EQ(response.clusters.size(), expected_size);
+
+ if (test_data[i].expect_first_cluster) {
+ const auto& cluster = response.clusters[0];
+ EXPECT_FALSE(cluster->id.is_empty());
+ ASSERT_EQ(cluster->top_visits.size(), 2u);
+ EXPECT_EQ(cluster->top_visits[0]->id, 2);
+ EXPECT_EQ(cluster->top_visits[0]->url, "https://google.com/");
+ EXPECT_EQ(cluster->top_visits[0]->time, IntToTime(2));
+ EXPECT_EQ(cluster->top_visits[0]->page_title, "Google title");
+ EXPECT_EQ(cluster->top_visits[1]->id, 4);
+ EXPECT_EQ(cluster->top_visits[1]->url, "https://github.com/");
+ EXPECT_EQ(cluster->top_visits[1]->time, IntToTime(4));
+ EXPECT_EQ(cluster->top_visits[1]->page_title, "Github title");
+ ASSERT_EQ(cluster->keywords.size(), 2u);
+ EXPECT_EQ(cluster->keywords[0], u"apples");
+ EXPECT_EQ(cluster->keywords[1], u"Red Oranges");
+ }
+
+ if (test_data[i].expect_second_cluster) {
+ const auto& cluster = test_data[i].expect_first_cluster
+ ? response.clusters[1]
+ : response.clusters[0];
+ EXPECT_FALSE(cluster->id.is_empty());
+ ASSERT_EQ(cluster->top_visits.size(), 1u);
+ EXPECT_EQ(cluster->top_visits[0]->id, 4);
+ EXPECT_EQ(cluster->top_visits[0]->url, "https://github.com/");
+ EXPECT_EQ(cluster->top_visits[0]->time, IntToTime(4));
+ EXPECT_EQ(cluster->top_visits[0]->page_title, "Github title");
+ EXPECT_TRUE(cluster->keywords.empty());
+ }
+
+ run_loop_quit.Run();
+ }),
+ &task_tracker_);
+
+ VerifyHardcodedTestDataInUrlLoaderRequest(experiment_name);
+ InjectHardcodedTestDataToUrlLoaderResponse({{2, 4}, {4}});
+
+ // Verify the callback is invoked.
+ run_loop.Run();
+ }
+}
+
+TEST_F(HistoryClustersServiceTest, QueryMemoriesWithEmptyVisits) {
+ EnableMemoriesWithEndpoint();
+
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ history_clusters_service_->QueryMemories(
+ mojom::QueryParams::New(),
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ // Verify that the continuation query params is nullptr.
+ ASSERT_FALSE(!!response.query_params);
+ // Verify the parsed response.
+ EXPECT_TRUE(response.clusters.empty());
+ run_loop_quit_.Run();
+ }),
+ &task_tracker_);
+
+ // Verify no request is made.
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ // Verify the callback is invoked.
+ run_loop_.Run();
+}
+
+TEST_F(HistoryClustersServiceTest, QueryMemoriesWithEmptyEndpoint) {
+ EnableMemoriesWithEndpoint("");
+
+ AddVisit(1, GURL{"google.com"});
+ AddVisit(2, GURL{"github.com"});
+
+ EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
+ history_clusters_service_->QueryMemories(
+ mojom::QueryParams::New(),
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ // Verify that the continuation query params is nullptr.
+ ASSERT_FALSE(!!response.query_params);
+ // Verify the empty response.
+ EXPECT_TRUE(response.clusters.empty());
+ run_loop_quit_.Run();
+ }),
+ &task_tracker_);
+
+ // Verify no request is made.
+ EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
+
+ // Verify the callback is invoked.
+ run_loop_.Run();
+}
+
+TEST_F(HistoryClustersServiceTest, QueryMemoriesWithEmptyResponse) {
+ EnableMemoriesWithEndpoint();
+
+ AddVisit(1, GURL{"google.com"});
+ AddVisit(2, GURL{"github.com"});
+
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ history_clusters_service_->QueryMemories(
+ mojom::QueryParams::New(),
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ // Verify that the continuation query params is nullptr.
+ ASSERT_FALSE(!!response.query_params);
+ // Verify the parsed response.
+ EXPECT_TRUE(response.clusters.empty());
+ run_loop_quit_.Run();
+ }),
+ &task_tracker_);
+
+ // Verify a request is made.
+ EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ // Fake an empty but valid response from the endpoint.
+ test_url_loader_factory_.AddResponse(
+ kFakeEndpoint, proto::GetClustersResponse().SerializeAsString());
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ // Verify the callback is invoked.
+ run_loop_.Run();
+}
+
+TEST_F(HistoryClustersServiceTest, QueryMemoriesWithInvalidJsonResponse) {
+ EnableMemoriesWithEndpoint();
+
+ AddVisit(1, GURL{"google.com"});
+ AddVisit(2, GURL{"github.com"});
+
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ history_clusters_service_->QueryMemories(
+ mojom::QueryParams::New(),
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ // Verify that the continuation query params is nullptr.
+ ASSERT_FALSE(!!response.query_params);
+ // Verify the parsed response.
+ EXPECT_TRUE(response.clusters.empty());
+ run_loop_quit_.Run();
+ }),
+ &task_tracker_);
+
+ // Verify a request is made.
+ EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ // Fake a junk response from the endpoint.
+ test_url_loader_factory_.AddResponse(kFakeEndpoint,
+ "{waka404woko.weke) !*(&,");
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ // Verify the callback is invoked.
+ run_loop_.Run();
+}
+
+TEST_F(HistoryClustersServiceTest, QueryMemoriesWithEmptyJsonResponse) {
+ EnableMemoriesWithEndpoint();
+
+ AddVisit(1, GURL{"google.com"});
+ AddVisit(2, GURL{"github.com"});
+
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ history_clusters_service_->QueryMemories(
+ mojom::QueryParams::New(),
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ // Verify that the continuation query params is nullptr.
+ ASSERT_FALSE(!!response.query_params);
+ // Verify the parsed response.
+ EXPECT_TRUE(response.clusters.empty());
+ run_loop_quit_.Run();
+ }),
+ &task_tracker_);
+
+ // Verify a request is made.
+ EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ // Fake an empty but valid response from the endpoint.
+ test_url_loader_factory_.AddResponse(
+ kFakeEndpoint, proto::GetClustersResponse().SerializeAsString());
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ // Verify the callback is invoked.
+ run_loop_.Run();
+}
+
+TEST_F(HistoryClustersServiceTest, QueryMemoriesWithPendingRequest) {
+ EnableMemoriesWithEndpoint();
+
+ AddVisit(1, GURL{"google.com"});
+ AddVisit(2, GURL{"github.com"});
+
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ history_clusters_service_->QueryMemories(
+ mojom::QueryParams::New(),
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ // Verify that the continuation query params is nullptr.
+ ASSERT_FALSE(!!response.query_params);
+ // Verify the parsed response.
+ EXPECT_EQ(response.clusters.size(), 2u);
+ }),
+ &task_tracker_);
+
+ // Verify there's a single request to the endpoint.
+ EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
+
+ EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ history_clusters_service_->QueryMemories(
+ mojom::QueryParams::New(),
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ // Verify that the continuation query params is nullptr.
+ ASSERT_FALSE(!!response.query_params);
+ // Verify the parsed response.
+ EXPECT_EQ(response.clusters.size(), 2u);
+ run_loop_quit_.Run();
+ }),
+ &task_tracker_);
+
+ // Verify there are two requests to the endpoint.
+ EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ EXPECT_EQ(test_url_loader_factory_.NumPending(), 2);
+
+ // Fake a response from the endpoint with two clusters.
+ proto::GetClustersResponse response;
+ response.add_clusters();
+ response.add_clusters();
+ test_url_loader_factory_.AddResponse(kFakeEndpoint,
+ response.SerializeAsString());
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ // Verify both callbacks are invoked.
+ run_loop_.Run();
+}
+
+TEST_F(HistoryClustersServiceTest, QueryMemoriesWithHistoryDb) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters(
+ {
+ {
+ kMemories,
+ {{"MemoriesPersistContextAnnotationsInHistoryDb", "true"}},
+ },
+ {
+ kRemoteModelForDebugging,
+ {{"MemoriesRemoteModelEndpoint", kFakeEndpoint}},
+ },
+ },
+ {});
+
+ // Must not be too old otherwise the history layer will ignore the visit.
+ const auto visit_time = base::Time::Now() - base::TimeDelta::FromDays(1);
+ AddVisit(1, GURL{"https://google.com"}, u"Google title", 1, visit_time, 3);
+ AddVisit(2, GURL{"https://github.com"}, u"Github title", 2, visit_time, 5);
+
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ history_clusters_service_->QueryMemories(
+ mojom::QueryParams::New(),
+ // This "expect" block is not run until after the fake response is sent
+ // further down in this method.
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ // Verify the parsed response.
+ ASSERT_EQ(response.clusters.size(), 2u);
+ EXPECT_FALSE(response.clusters[0]->id.is_empty());
+ ASSERT_EQ(response.clusters[0]->top_visits.size(), 2u);
+ EXPECT_EQ(response.clusters[0]->top_visits[0]->id, 1);
+ EXPECT_EQ(response.clusters[0]->top_visits[0]->url,
+ "https://google.com/");
+ EXPECT_EQ(response.clusters[0]->top_visits[0]->time, visit_time);
+ EXPECT_EQ(response.clusters[0]->top_visits[0]->page_title,
+ "Google title");
+ EXPECT_EQ(response.clusters[0]->top_visits[1]->id, 2);
+ EXPECT_EQ(response.clusters[0]->top_visits[1]->url,
+ "https://github.com/");
+ EXPECT_EQ(response.clusters[0]->top_visits[1]->time, visit_time);
+ EXPECT_EQ(response.clusters[0]->top_visits[1]->page_title,
+ "Github title");
+ ASSERT_EQ(response.clusters[1]->top_visits.size(), 1u);
+ EXPECT_FALSE(response.clusters[1]->id.is_empty());
+ EXPECT_EQ(response.clusters[1]->top_visits[0]->id, 2);
+ EXPECT_EQ(response.clusters[1]->top_visits[0]->url,
+ "https://github.com/");
+ EXPECT_EQ(response.clusters[1]->top_visits[0]->time, visit_time);
+ EXPECT_EQ(response.clusters[1]->top_visits[0]->page_title,
+ "Github title");
+ run_loop_quit_.Run();
+ }),
+ &task_tracker_);
+
+ history::BlockUntilHistoryProcessesPendingRequests(history_service_.get());
+
+ // Verify there's a single request to the endpoint.
+ EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
+
+ // Fake a response from the endpoint with two clusters.
+ InjectHardcodedTestDataToUrlLoaderResponse({{1, 2}, {2}});
+
+ // Verify the callback is invoked.
+ run_loop_.Run();
+}
+
+TEST_F(HistoryClustersServiceTest,
+ QueryMemoriesWithHistoryDbWithPendingRequest) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters(
+ {
+ {
+ kMemories,
+ {{"MemoriesPersistContextAnnotationsInHistoryDb", "true"}},
+ },
+ {
+ kRemoteModelForDebugging,
+ {{"MemoriesRemoteModelEndpoint", kFakeEndpoint}},
+ },
+ },
+ {});
+
+ // Must not be too old otherwise the history layer will ignore the visit.
+ const auto visit_time = base::Time::Now() - base::TimeDelta::FromDays(1);
+ AddVisit(1, GURL{"https://google.com"}, u"Google title", 1, visit_time, 3);
+ AddVisit(2, GURL{"https://github.com"}, u"Github title", 2, visit_time, 5);
+
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ history_clusters_service_->QueryMemories(
+ mojom::QueryParams::New(),
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ ADD_FAILURE() << "This should not be reached.";
+ }),
+ &task_tracker_);
+
+ // Verify there are no requests to the endpoint just yet.
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+
+ // Cancel pending queries, if any.
+ task_tracker_.TryCancelAll();
+
+ EXPECT_FALSE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ history_clusters_service_->QueryMemories(
+ mojom::QueryParams::New(),
+ base::BindLambdaForTesting(
+ [&](HistoryClustersService::QueryMemoriesResponse response) {
+ // Verify the parsed response.
+ EXPECT_EQ(response.clusters.size(), 2u);
+ run_loop_quit_.Run();
+ }),
+ &task_tracker_);
+
+ history::BlockUntilHistoryProcessesPendingRequests(history_service_.get());
+
+ // Verify there's a single request to the endpoint.
+ EXPECT_TRUE(test_url_loader_factory_.IsPending(kFakeEndpoint));
+ EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
+
+ // Fake a response from the endpoint with two clusters.
+ InjectHardcodedTestDataToUrlLoaderResponse({{1, 2}, {2}});
+
+ // Verify the last callback is invoked.
+ run_loop_.Run();
+}
+
+TEST_F(HistoryClustersServiceTest, CompleteVisitContextAnnotationsIfReady) {
+ auto test = [&](RecordingStatus status, bool expected_complete) {
+ auto& incomplete_visit_context_annotations =
+ history_clusters_service_->GetOrCreateIncompleteVisitContextAnnotations(
+ 0);
+ incomplete_visit_context_annotations.status = status;
+ history_clusters_service_->CompleteVisitContextAnnotationsIfReady(0);
+ EXPECT_NE(
+ history_clusters_service_->HasIncompleteVisitContextAnnotations(0),
+ expected_complete);
+ };
+
+ // Complete cases:
+ {
+ SCOPED_TRACE("Complete without UKM");
+ test({true, true, true}, true);
+ }
+ {
+ SCOPED_TRACE("Complete with UKM");
+ test({true, true, true, true, true}, true);
+ }
+
+ // Incomplete without UKM cases:
+ {
+ SCOPED_TRACE("Incomplete, missing history rows");
+ test({false, true}, false);
+ }
+ {
+ SCOPED_TRACE("Incomplete, navigation hasn't ended");
+ test({true}, false);
+ }
+ {
+ SCOPED_TRACE("Incomplete, navigation end metrics haven't been recorded");
+ test({true, true}, false);
+ }
+
+ // Incomplete with UKM cases:
+ {
+ SCOPED_TRACE("Incomplete, missing history rows");
+ test({false, true, false, true, true}, false);
+ }
+ {
+ SCOPED_TRACE("Incomplete, navigation hasn't ended");
+ test({true, false, false, true, true}, false);
+ }
+ {
+ SCOPED_TRACE("Incomplete, navigation end metrics haven't been recorded");
+ test({true, true, false, true, true}, false);
+ }
+ {
+ SCOPED_TRACE("Incomplete, UKM page end missing");
+ test({true, true, true, true, false}, false);
+ }
+
+ auto test_dcheck = [&](RecordingStatus status) {
+ auto& incomplete_visit_context_annotations =
+ history_clusters_service_->GetOrCreateIncompleteVisitContextAnnotations(
+ 0);
+ incomplete_visit_context_annotations.status = status;
+ EXPECT_DCHECK_DEATH(
+ history_clusters_service_->CompleteVisitContextAnnotationsIfReady(0));
+ EXPECT_TRUE(
+ history_clusters_service_->HasIncompleteVisitContextAnnotations(0));
+ };
+
+ // Impossible cases:
+ {
+ SCOPED_TRACE(
+ "Impossible, navigation end signals recorded before navigation ended");
+ test_dcheck({true, false, true});
+ }
+ {
+ SCOPED_TRACE(
+ "Impossible, navigation end signals recorded before history rows");
+ test_dcheck({false, true, true});
+ }
+ {
+ SCOPED_TRACE("Impossible, unexpected UKM page end recorded");
+ test_dcheck({false, false, false, false, true});
+ }
+}
+
+TEST_F(HistoryClustersServiceTest,
+ CompleteVisitContextAnnotationsIfReadyWhenFeatureDisabled) {
+ {
+ // When the feature is disabled, the `IncompleteVisitContextAnnotations`
+ // should be removed but not added to visits.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndDisableFeature(kMemories);
+ auto& incomplete_visit_context_annotations =
+ history_clusters_service_->GetOrCreateIncompleteVisitContextAnnotations(
+ 0);
+ incomplete_visit_context_annotations.status = {true, true, true};
+ history_clusters_service_->CompleteVisitContextAnnotationsIfReady(0);
+ EXPECT_FALSE(
+ history_clusters_service_->HasIncompleteVisitContextAnnotations(0));
+ EXPECT_TRUE(history_clusters_service_test_api_->GetVisits().empty());
+ }
+
+ {
+ // When the feature is enabled, the `IncompleteVisitContextAnnotations`
+ // should be removed and added to visits.
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(kMemories);
+ auto& incomplete_visit_context_annotations =
+ history_clusters_service_->GetOrCreateIncompleteVisitContextAnnotations(
+ 0);
+ incomplete_visit_context_annotations.status = {true, true, true};
+ history_clusters_service_->CompleteVisitContextAnnotationsIfReady(0);
+ EXPECT_FALSE(
+ history_clusters_service_->HasIncompleteVisitContextAnnotations(0));
+ EXPECT_EQ(history_clusters_service_test_api_->GetVisits().size(), 1u);
+ }
+}
+
+} // namespace
+
+} // namespace history_clusters
diff --git a/chromium/components/history_clusters/core/memories.mojom b/chromium/components/history_clusters/core/memories.mojom
index 9b45e29c761..4f177585a1d 100644
--- a/chromium/components/history_clusters/core/memories.mojom
+++ b/chromium/components/history_clusters/core/memories.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.
-module memories.mojom;
+module history_clusters.mojom;
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/time.mojom";
@@ -13,7 +13,7 @@ import "url/mojom/url.mojom";
// Represents a search query related to a Memory.
struct SearchQuery {
// Text of the search query.
- mojo_base.mojom.String16 query;
+ string query;
// URL of the search query page.
url.mojom.Url url;
};
@@ -23,7 +23,7 @@ struct WebPage {
// URL of the webpage; Identifies the webpage.
url.mojom.Url url;
// Title of the webpage.
- mojo_base.mojom.String16 title;
+ string title;
// Optional externally hosted thumbnail representing the webpage.
url.mojom.Url? thumbnail_url;
};
@@ -33,27 +33,33 @@ struct TabGroup {
// Tab group identifier. See //components/tab_groups/tab_group_id.h
mojo_base.mojom.Token id;
// Title of the tab group.
- mojo_base.mojom.String16 title;
+ string title;
// Pages in this tab group.
array<WebPage> pages;
};
-// Represents a visit to a webpage.
+// Represents the most recent visit to a URL in a Memory. Those visits in a
+// Memory for which there is a more recent visit to the same URL are omitted.
+// However, the time of the least recent visit as well as the number of those
+// visits are preserved for use in the UI as well as deletion.
struct Visit {
// Visit identifier. See //components/history/core/browser/history_types.h
int64 id;
// Visited URL.
url.mojom.Url url;
// Title of the visited webpage.
- mojo_base.mojom.String16 page_title;
+ string page_title;
// Optional externally hosted thumbnail representing the visited webpage.
url.mojom.Url? thumbnail_url;
// Time of the visit.
mojo_base.mojom.Time time;
+ // Time of the least recent visit in the Memory to the same URL. Equals `time`
+ // if there is only one visit in the Memory to the URL.
+ mojo_base.mojom.Time first_visit_time;
// Localized string of approximate time of visit, e.g., "2 days ago".
- mojo_base.mojom.String16 relative_date;
+ string relative_date;
// Time of day of visit, e.g., "3:07 PM".
- mojo_base.mojom.String16 time_of_day;
+ string time_of_day;
// Number of duplicate visits (i.e., visits to the same URL) in the Memory.
int32 num_duplicate_visits;
// Related visits (e.g., visits to the same domain name) in the Memory;
@@ -70,17 +76,42 @@ struct Visit {
struct Memory {
// Memory identifier.
mojo_base.mojom.UnguessableToken id;
+
+ // Top constituent visits; starting with the most recent.
+ array<Visit> top_visits;
+
+ // The content "topics", or keywords, that the memory contains/is related to.
+ // These strings should never be exposed to the user directly in case they are
+ // offensively wrong, but may be queried over with search terms to find
+ // memories.
+ array<mojo_base.mojom.String16> keywords;
+
// Search queries related to the constituent visits.
array<SearchQuery> related_searches;
// Tab groups containing one or more of the visited URLs in the Memory.
array<TabGroup> related_tab_groups;
// Bookmarked visited pages in the Memory.
array<WebPage> bookmarks;
- // Top constituent visits; starting with the most recent.
- array<Visit> top_visits;
// Time of the most recent visit in the Memory. Used for extracting Memories.
mojo_base.mojom.Time last_visit_time;
// A calculated engagement score based on engagement scores of constituent
// visits. Used to rank Memories.
double engagement_score;
};
+
+// Parameters used to query the service for Memories in reverse chronological
+// order.
+struct QueryParams {
+ // The query string the Memories are matched against. The default value of
+ // empty string means to return every Memory that matches the other criteria.
+ string query;
+
+ // The optional time threshold (exclusive) for how recent the Memories can be.
+ // If specified, Memories before `recency_threshold` and if missing, Memories
+ // until the present time that match the other criteria are returned.
+ mojo_base.mojom.Time? recency_threshold;
+
+ // The maximum number of Memories to return. The default value of 0 means to
+ // return every Memory that matches the other criteria.
+ uint32 max_count;
+};
diff --git a/chromium/components/history_clusters/core/memories_features.cc b/chromium/components/history_clusters/core/memories_features.cc
index 630164834df..8824f1a3ad7 100644
--- a/chromium/components/history_clusters/core/memories_features.cc
+++ b/chromium/components/history_clusters/core/memories_features.cc
@@ -6,18 +6,39 @@
#include "base/metrics/field_trial_params.h"
-namespace memories {
+namespace history_clusters {
+
+namespace {
+
+const base::FeatureParam<std::string> kRemoteModelEndpoint{
+ &kRemoteModelForDebugging, "MemoriesRemoteModelEndpoint", ""};
+
+} // namespace
GURL RemoteModelEndpoint() {
- return GURL(base::GetFieldTrialParamValueByFeature(
- kMemories, kRemoteModelEndpointParam));
+ return GURL(kRemoteModelEndpoint.Get());
}
-// Enables the Chrome Memories history clustering feature.
+const base::FeatureParam<std::string> kRemoteModelEndpointExperimentName{
+ &kRemoteModelForDebugging, "MemoriesRemoteModelEndpointExperimentName", ""};
+
+const base::FeatureParam<bool> kPersistContextAnnotationsInHistoryDb{
+ &kMemories, "MemoriesPersistContextAnnotationsInHistoryDb", false};
+
+const base::FeatureParam<int> kMaxVisitsToCluster{
+ &kMemories, "MemoriesMaxVisitsToCluster", 10};
+
+const base::FeatureParam<int> kMaxDaysToCluster{&kMemories,
+ "MemoriesMaxDaysToCluster", 9};
+
+const base::FeatureParam<bool> kPersistClustersInHistoryDb{
+ &kMemories, "MemoriesPersistClustersInHistoryDb", false};
+
const base::Feature kMemories{"Memories", base::FEATURE_DISABLED_BY_DEFAULT};
-const char kRemoteModelEndpointParam[] = "MemoriesRemoteModelEndpoint";
-// Enables debug info; e.g. shows visit metadata on chrome://history entries.
const base::Feature kDebug{"MemoriesDebug", base::FEATURE_DISABLED_BY_DEFAULT};
-} // namespace memories
+const base::Feature kRemoteModelForDebugging{"MemoriesRemoteModelForDebugging",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+} // namespace history_clusters
diff --git a/chromium/components/history_clusters/core/memories_features.h b/chromium/components/history_clusters/core/memories_features.h
index 8df63a7d7ba..9b82e781a6f 100644
--- a/chromium/components/history_clusters/core/memories_features.h
+++ b/chromium/components/history_clusters/core/memories_features.h
@@ -6,19 +6,59 @@
#define COMPONENTS_HISTORY_CLUSTERS_CORE_MEMORIES_FEATURES_H_
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
#include "url/gurl.h"
-namespace memories {
+namespace history_clusters {
+// Params & helpers functions
+
+// Returns the remote model debug endpoint used to cluster visits into memories.
+// Returns an empty GURL() when the remote model debug endpoint is disabled.
GURL RemoteModelEndpoint();
+// Returns the experiment name to pass through to the remote model debug
+// endpoint to control how the visits get clustered. Returns an empty string if
+// this client should just use be returned the default clustering or if the
+// remote model debug endpoint is disabled.
+extern const base::FeatureParam<std::string> kRemoteModelEndpointExperimentName;
+
+// If enabled, completed visits context annotations are persisted to the history
+// DB and read back when clustering. If disabled, completed visit context
+// annotations are kept in-memory and used these in-memory visits are used when
+// clustering.
+extern const base::FeatureParam<bool> kPersistContextAnnotationsInHistoryDb;
+
+// The max number of visits to use for each clustering iteration. When using the
+// remote model, this limits the number of visits sent. Only applies when using
+// persisted visit context annotations; i.e.
+// `kPersistContextAnnotationsInHistoryDb` is true.
+extern const base::FeatureParam<int> kMaxVisitsToCluster;
+
+// The recency threshold controlling which visits will be clustered. This isn't
+// the only factor; i.e. visits older than `MaxDaysToCluster()` may still be
+// clustered. Only applies when using persisted visit context annotations; i.e.
+// `kPersistContextAnnotationsInHistoryDb` is true.
+extern const base::FeatureParam<int> kMaxDaysToCluster;
+
+// If enabled, updating clusters will persist the results to the history DB and
+// accessing clusters will retrieve them from the history DB. If disabled,
+// updating clusters is a no-op and accessing clusters will generate and return
+// new clusters without persisting them.
+extern const base::FeatureParam<bool> kPersistClustersInHistoryDb;
+
+// Features
+
+// Enables the Chrome Memories history clustering feature.
extern const base::Feature kMemories;
-// The remote model endpoint used to cluster visits into memories.
-extern const char kRemoteModelEndpointParam[];
-// Enables debug features; e.g. displaying typed_count on chrome://history.
+// Enables debug info; e.g. shows visit metadata on chrome://history entries.
extern const base::Feature kDebug;
-} // namespace memories
+// Enables using a remote model endpoint for Memories clustering for debugging
+// purposes. This should not be ever enabled in production.
+extern const base::Feature kRemoteModelForDebugging;
+
+} // namespace history_clusters
#endif // COMPONENTS_HISTORY_CLUSTERS_CORE_MEMORIES_FEATURES_H_
diff --git a/chromium/components/history_clusters/core/memories_remote_model_helper.cc b/chromium/components/history_clusters/core/memories_remote_model_helper.cc
index 6be5ae3ac23..9232a9b16d7 100644
--- a/chromium/components/history_clusters/core/memories_remote_model_helper.cc
+++ b/chromium/components/history_clusters/core/memories_remote_model_helper.cc
@@ -6,177 +6,188 @@
#include <utility>
+#include "base/base64.h"
#include "base/bind.h"
#include "base/json/json_writer.h"
#include "base/ranges/algorithm.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "components/history_clusters/core/memories_features.h"
-#include "services/data_decoder/public/cpp/data_decoder.h"
+#include "components/history_clusters/core/proto/clusters.pb.h"
+
+namespace history_clusters {
namespace {
const size_t kMaxExpectedResponseSize = 1024 * 1024;
-// Helpers to translate from |MemoriesVisit|s to |base::Value|; and from
-// |base::Value| to |mojom::MemoryPtr|s.
-
-base::Value VisitToValue(const memories::MemoriesVisit& visit) {
- base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetKey("visitId",
- base::Value(static_cast<double>(visit.visit_row.visit_id)));
- dict.SetKey("url", base::Value(visit.url_row.url().spec()));
- dict.SetKey("origin", base::Value(visit.url_row.url().GetOrigin().spec()));
- dict.SetKey("foregroundTimeSecs", base::Value(0));
- dict.SetKey("navigationTimeMs",
- base::Value(static_cast<double>(
- visit.visit_row.visit_time.ToDeltaSinceWindowsEpoch()
- .InMilliseconds())));
- dict.SetKey("siteEngagementScore", base::Value(0));
- dict.SetKey("pageEndReason",
- base::Value(visit.context_signals.page_end_reason));
- dict.SetKey("pageTransition",
- base::Value(static_cast<int>(visit.visit_row.transition)));
- dict.SetKey("isFromGoogleSearch", base::Value(false));
- // TODO(manukh) fill out:
- // |foregroundTimeSecs|
- // |siteEngagementScore|
- // |isFromGoogleSearch|
- return dict;
-}
+// Also writes one line of debug information per visit to `debug_string`, if
+// the parameter is non-nullptr.
+proto::GetClustersRequest CreateRequestProto(
+ const std::vector<history::AnnotatedVisit>& visits,
+ absl::optional<DebugLoggerCallback> debug_logger) {
+ proto::GetClustersRequest request;
+ request.set_experiment_name(kRemoteModelEndpointExperimentName.Get());
+
+ base::ListValue debug_visits_list;
+ for (auto& visit : visits) {
+ proto::Visit* request_visit = request.add_visits();
+ request_visit->set_visit_id(visit.visit_row.visit_id);
+ request_visit->set_url(visit.url_row.url().spec());
+ request_visit->set_origin(visit.url_row.url().GetOrigin().spec());
+ request_visit->set_navigation_time_ms(
+ visit.visit_row.visit_time.ToDeltaSinceWindowsEpoch().InMilliseconds());
+ request_visit->set_page_end_reason(
+ visit.context_annotations.page_end_reason);
+ request_visit->set_page_transition(
+ static_cast<int>(visit.visit_row.transition));
+
+ if (debug_logger) {
+ base::DictionaryValue debug_visit;
+ debug_visit.SetStringKey("visitId",
+ base::NumberToString(request_visit->visit_id()));
+ debug_visit.SetStringKey("url", request_visit->url());
+ debug_visit.SetStringKey(
+ "navigationTimeMs",
+ base::NumberToString(request_visit->navigation_time_ms()));
+ debug_visit.SetStringKey(
+ "pageEndReason",
+ base::NumberToString(request_visit->page_end_reason()));
+ debug_visit.SetStringKey(
+ "pageTransition",
+ base::NumberToString(request_visit->page_transition()));
+ debug_visits_list.Append(std::move(debug_visit));
+ }
+ }
-base::Value VisitsToValue(const std::vector<memories::MemoriesVisit>& visits) {
- base::Value visits_list(base::Value::Type::LIST);
- for (const auto& visit : visits)
- visits_list.Append(VisitToValue(visit));
+ if (debug_logger) {
+ debug_logger->Run("MemoriesRemoteModelHelper CreateRequestProto:");
- base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetKey("visits", std::move(visits_list));
- return dict;
-}
+ base::DictionaryValue debug_value;
+ debug_value.SetStringKey("experiment_name", request.experiment_name());
+ debug_value.SetKey("visits", std::move(debug_visits_list));
-// A helper method to get the values of the |base::ListValue| at |value[key]|.
-template <typename T>
-std::vector<T> FindListKeyAndCast(
- const base::Value& value,
- std::string key,
- base::RepeatingCallback<T(const base::Value&)> cast_callback) {
- const base::Value* list_ptr = value.FindListKey(key);
- if (!list_ptr)
- return {};
-
- base::Value::ConstListView list = list_ptr->GetList();
- std::vector<T> casted(list.size());
-
- base::ranges::transform(list, casted.begin(), [&](const base::Value& value) {
- return cast_callback.Run(value);
- });
- return casted;
+ std::string debug_string;
+ if (base::JSONWriter::WriteWithOptions(
+ debug_value, base::JSONWriter::OPTIONS_PRETTY_PRINT,
+ &debug_string)) {
+ debug_logger->Run(debug_string);
+ }
+ }
+ return request;
}
-memories::mojom::VisitPtr ValueToVisit(
- const std::vector<memories::MemoriesVisit>& visits,
- const base::Value& visit_id_value) {
- auto visit = memories::mojom::Visit::New();
- visit->id = visit_id_value.GetIfInt().value_or(-1);
-
- const auto memory_visit_it = base::ranges::find(
- visits, visit->id,
- [](const auto& visit) { return visit.visit_row.visit_id; });
- if (memory_visit_it != visits.end()) {
- visit->url = memory_visit_it->url_row.url();
- visit->time = memory_visit_it->visit_row.visit_time;
- visit->page_title = memory_visit_it->url_row.title();
+std::vector<history::Cluster> ParseResponseProto(
+ const std::vector<history::AnnotatedVisit>& visits,
+ const proto::GetClustersResponse& response_proto,
+ absl::optional<DebugLoggerCallback> debug_logger) {
+ std::vector<history::Cluster> clusters;
+ for (const proto::Cluster& cluster_proto : response_proto.clusters()) {
+ history::Cluster cluster;
+ for (const std::string& keyword : cluster_proto.keywords())
+ cluster.keywords.push_back(base::UTF8ToUTF16(keyword));
+ for (int64_t visit_id : cluster_proto.visit_ids()) {
+ const auto visits_it = base::ranges::find(
+ visits, visit_id,
+ [](const auto& visit) { return visit.visit_row.visit_id; });
+ if (visits_it != visits.end())
+ cluster.annotated_visits.push_back(*visits_it);
+ }
+ clusters.push_back(cluster);
}
- // TODO(manukh) fill out:
- // |thumbnail_url|
- // |relative_date|
- // |time_of_day|
- // |num_duplicate_visits|
- // |related_visits|
- // |engagement_score|
- return visit;
-}
-
-memories::mojom::MemoryPtr ValueToMemory(
- const std::vector<memories::MemoriesVisit>& visits,
- const base::Value& value) {
- auto memory = memories::mojom::Memory::New();
- memory->id = base::UnguessableToken::Create();
- memory->top_visits = FindListKeyAndCast<memories::mojom::VisitPtr>(
- value, "visitIds", base::BindRepeating(&ValueToVisit, visits));
- // TODO(manukh) fill out:
- // |id|
- // |related_searches|
- // |related_tab_groups|
- // |bookmarks|
- // |last_visit_time|
- // |engagement_score|
- return memory;
-}
+ if (debug_logger) {
+ // TODO(manukh): `ListValue` is deprecated; replace with `std::vector`.
+ base::ListValue debug_clusters_list;
+ for (const proto::Cluster& cluster : response_proto.clusters()) {
+ base::DictionaryValue debug_cluster;
+
+ base::ListValue debug_keywords;
+ for (const std::string& keyword : cluster.keywords()) {
+ debug_keywords.Append(keyword);
+ }
+ debug_cluster.SetKey("keywords", std::move(debug_keywords));
+
+ base::ListValue debug_visit_ids;
+ for (int64_t visit_id : cluster.visit_ids()) {
+ debug_visit_ids.Append(base::NumberToString(visit_id));
+ }
+ debug_cluster.SetKey("visit_ids", std::move(debug_visit_ids));
+
+ debug_clusters_list.Append(std::move(debug_cluster));
+ }
+
+ debug_logger->Run("MemoriesRemoteModelHelper ParseResponseProto Clusters:");
+
+ std::string debug_string;
+ if (base::JSONWriter::WriteWithOptions(
+ debug_clusters_list, base::JSONWriter::OPTIONS_PRETTY_PRINT,
+ &debug_string)) {
+ debug_logger->Run(debug_string);
+ }
+ }
-memories::Memories ValueToMemories(
- const std::vector<memories::MemoriesVisit>& visits,
- const base::Value& value) {
- return FindListKeyAndCast<memories::mojom::MemoryPtr>(
- value, "memories", base::BindRepeating(&ValueToMemory, visits));
+ return clusters;
}
} // namespace
-namespace memories {
-
MemoriesRemoteModelHelper::MemoriesRemoteModelHelper(
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
- : url_loader_(nullptr), url_loader_factory_(url_loader_factory) {}
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ absl::optional<DebugLoggerCallback> debug_logger)
+ : url_loader_factory_(url_loader_factory), debug_logger_(debug_logger) {}
MemoriesRemoteModelHelper::~MemoriesRemoteModelHelper() = default;
void MemoriesRemoteModelHelper::GetMemories(
- const std::vector<MemoriesVisit>& visits,
- MemoriesCallback callback) {
- const GURL endpoint(memories::RemoteModelEndpoint());
- if (!endpoint.is_valid())
- NOTREACHED();
- StopPendingRequests();
+ MemoriesCallback callback,
+ const std::vector<history::AnnotatedVisit>& visits) {
+ const GURL endpoint(RemoteModelEndpoint());
+ if (!endpoint.is_valid() || visits.empty()) {
+ std::move(callback).Run({});
+ return;
+ }
+
+ // It's weird but the endpoint only accepts JSON, so wrap our serialized proto
+ // like this: {"data":"<base64-encoded-proto-serialization>"}
+ proto::GetClustersRequest request_proto =
+ CreateRequestProto(visits, debug_logger_);
+ const std::string serialized_request_proto =
+ request_proto.SerializeAsString();
+ std::string request_proto_base64;
+ base::Base64Encode(serialized_request_proto, &request_proto_base64);
+
+ base::DictionaryValue container_value;
+ container_value.SetStringPath("data", request_proto_base64);
std::string request_body;
- base::JSONWriter::Write(VisitsToValue(visits), &request_body);
- auto request = CreateRequest(endpoint);
- url_loader_ = CreateLoader(CreateRequest(endpoint), request_body);
+ base::JSONWriter::Write(container_value, &request_body);
- url_loader_->DownloadToString(
+ auto url_loader = CreateLoader(CreateRequest(endpoint), request_body);
+ network::SimpleURLLoader* unowned_url_loader = url_loader.get();
+ unowned_url_loader->DownloadToString(
url_loader_factory_.get(),
base::BindOnce(
- [](const std::vector<MemoriesVisit>& visits,
- MemoriesCallback callback, std::unique_ptr<std::string> response) {
+ [](std::unique_ptr<network::SimpleURLLoader> url_loader,
+ absl::optional<DebugLoggerCallback> debug_logger,
+ const std::vector<history::AnnotatedVisit>& visits,
+ std::unique_ptr<std::string> response) {
if (!response) {
- std::move(callback).Run({});
- return;
+ if (debug_logger) {
+ debug_logger->Run("MemoriesRemoteModelHelper response nullptr");
+ }
+ return std::vector<history::Cluster>{};
}
- data_decoder::DataDecoder::ParseJsonIsolated(
- *response,
- base::BindOnce(
- [](const std::vector<MemoriesVisit>& visits,
- data_decoder::DataDecoder::ValueOrError value_or_error)
- -> Memories {
- return value_or_error.value
- ? ValueToMemories(visits,
- value_or_error.value.value())
- : Memories{};
- },
- visits)
- .Then(std::move(callback)));
+ proto::GetClustersResponse response_proto;
+ response_proto.ParseFromString(*response);
+ return ParseResponseProto(visits, response_proto, debug_logger);
},
- visits, std::move(callback)),
+ std::move(url_loader), debug_logger_, visits)
+ .Then(std::move(callback)),
kMaxExpectedResponseSize);
}
-void MemoriesRemoteModelHelper::StopPendingRequests() {
- // TODO(manukh): Ensure the callback for the pending request is invoked.
- url_loader_.reset();
-}
-
// static
std::unique_ptr<network::ResourceRequest>
MemoriesRemoteModelHelper::CreateRequest(const GURL& endpoint) {
@@ -230,4 +241,4 @@ MemoriesRemoteModelHelper::CreateLoader(
return loader;
}
-} // namespace memories
+} // namespace history_clusters
diff --git a/chromium/components/history_clusters/core/memories_remote_model_helper.h b/chromium/components/history_clusters/core/memories_remote_model_helper.h
index f04d9a7b69e..b330e9f330c 100644
--- a/chromium/components/history_clusters/core/memories_remote_model_helper.h
+++ b/chromium/components/history_clusters/core/memories_remote_model_helper.h
@@ -11,49 +11,52 @@
#include "base/callback.h"
#include "base/memory/scoped_refptr.h"
-#include "components/history_clusters/core/memories.mojom.h"
-#include "components/history_clusters/core/visit_data.h"
+#include "components/history/core/browser/history_types.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 "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
-namespace memories {
+namespace history_clusters {
-using Memories = std::vector<mojom::MemoryPtr>;
-using MemoriesCallback = base::OnceCallback<void(Memories)>;
+using DebugLoggerCallback = base::RepeatingCallback<void(const std::string&)>;
// A helper class to communicate with the remote model. Forms requests from
-// |MemoriesVisit|s and parses the response into |mojom::MemoryPtr|s.
+// `history::AnnotatedVisit`s and parses the response into
+// `history::Cluster`s.
class MemoriesRemoteModelHelper {
public:
- explicit MemoriesRemoteModelHelper(
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+ // Pass in a defined `debug_logger` to enable debug logging from this class.
+ MemoriesRemoteModelHelper(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ absl::optional<DebugLoggerCallback> debug_logger);
~MemoriesRemoteModelHelper();
- // POSTs |visits| to |endpoint_| and invokes |callback| with the retrieved
- // |MemoryPtr|s.
- void GetMemories(const std::vector<MemoriesVisit>& visits,
- MemoriesCallback callback);
+ // POSTs `visits` to the remote endpoint and invokes `callback` with the
+ // retrieved `Cluster`s.
+ using MemoriesCallback =
+ base::OnceCallback<void(std::vector<history::Cluster>)>;
+ void GetMemories(MemoriesCallback callback,
+ const std::vector<history::AnnotatedVisit>& visits);
private:
- // Stops pending requests. Invoking |GetMemories| multiple times will stop
- // incomplete previous requests.
- void StopPendingRequests();
-
- // Helpers for making requests used by |GetMemories()|.
+ // Helpers for making requests used by `GetMemories()`.
static std::unique_ptr<network::ResourceRequest> CreateRequest(
const GURL& endpoint);
static std::unique_ptr<network::SimpleURLLoader> CreateLoader(
std::unique_ptr<network::ResourceRequest> request,
const std::string& request_body);
- // The most recent request.
- std::unique_ptr<network::SimpleURLLoader> url_loader_;
// Used to make requests.
const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+
+ // This should be set to absl::nullopt if debug logging is disabled.
+ // This is absl::optional, so we can skip the expense of constructing the log
+ // messages if the logger is disabled.
+ absl::optional<DebugLoggerCallback> debug_logger_;
};
-} // namespace memories
+} // namespace history_clusters
#endif // COMPONENTS_HISTORY_CLUSTERS_CORE_MEMORIES_REMOTE_MODEL_HELPER_H_
diff --git a/chromium/components/history_clusters/core/memories_service.cc b/chromium/components/history_clusters/core/memories_service.cc
deleted file mode 100644
index 6ae6b00d0e9..00000000000
--- a/chromium/components/history_clusters/core/memories_service.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/history_clusters/core/memories_service.h"
-
-#include <utility>
-
-#include "base/feature_list.h"
-#include "components/history_clusters/core/memories_features.h"
-
-namespace memories {
-
-MemoriesService::MemoriesService(
- history::HistoryService* history_service,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
- : remote_model_helper_(
- std::make_unique<MemoriesRemoteModelHelper>(url_loader_factory)) {}
-
-MemoriesService::~MemoriesService() = default;
-
-void MemoriesService::Shutdown() {}
-
-MemoriesVisit& MemoriesService::GetIncompleteVisit(int64_t nav_id) {
- DCHECK(HasIncompleteVisit(nav_id));
- return GetOrCreateIncompleteVisit(nav_id);
-}
-
-MemoriesVisit& MemoriesService::GetOrCreateIncompleteVisit(int64_t nav_id) {
- return incomplete_visits_[nav_id];
-}
-
-bool MemoriesService::HasIncompleteVisit(int64_t nav_id) {
- return incomplete_visits_.count(nav_id);
-}
-
-void MemoriesService::CompleteVisitIfReady(int64_t nav_id) {
- auto& visit = GetIncompleteVisit(nav_id);
- DCHECK((visit.status.history_rows && visit.status.navigation_ended) ||
- !visit.status.navigation_end_signals);
- DCHECK(visit.status.expect_ukm_page_end_signals ||
- !visit.status.ukm_page_end_signals);
- if (visit.status.history_rows && visit.status.navigation_end_signals &&
- (visit.status.ukm_page_end_signals ||
- !visit.status.expect_ukm_page_end_signals)) {
- if (base::FeatureList::IsEnabled(memories::kMemories))
- visits_.push_back(visit);
- incomplete_visits_.erase(nav_id);
- // TODO(tommycli/manukh): Persist |visits_| to History, and take out of
- // in-memory.
- }
-}
-
-void MemoriesService::GetMemories(MemoriesCallback callback) {
- if (visits_.empty())
- std::move(callback).Run({});
- else
- remote_model_helper_->GetMemories(visits_, std::move(callback));
-}
-
-} // namespace memories
diff --git a/chromium/components/history_clusters/core/memories_service.h b/chromium/components/history_clusters/core/memories_service.h
deleted file mode 100644
index 49cf983da57..00000000000
--- a/chromium/components/history_clusters/core/memories_service.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_HISTORY_CLUSTERS_CORE_MEMORIES_SERVICE_H_
-#define COMPONENTS_HISTORY_CLUSTERS_CORE_MEMORIES_SERVICE_H_
-
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/history_clusters/core/memories_remote_model_helper.h"
-#include "components/history_clusters/core/visit_data.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
-
-namespace memories {
-
-// This Service is the API for UIs to fetch Chrome Memories.
-class MemoriesService : public KeyedService {
- public:
- explicit MemoriesService(
- history::HistoryService* history_service,
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
- ~MemoriesService() override;
-
- // KeyedService:
- void Shutdown() override;
-
- // TODO(manukh) |MemoriesService| should be responsible for constructing the
- // MemoriesVisit rather than exposing these methods which are used by
- // |HistoryClustersTabHelper| to construct the visits.
- // Gets an incomplete visit after DCHECKing it exists; this saves the call
- // sites the effort.
- MemoriesVisit& GetIncompleteVisit(int64_t nav_id);
- // Gets or creates an incomplete visit.
- MemoriesVisit& GetOrCreateIncompleteVisit(int64_t nav_id);
- // Returns whether an incomplete visit exists.
- // TODO(manukh): Merge |HasIncompleteVisit()| and |GetIncompleteVisit()|.
- bool HasIncompleteVisit(int64_t nav_id);
- // Completes the visit if the expected metrics have been recorded. Incomplete
- // visit references retrieved prior will no longer be valid.
- void CompleteVisitIfReady(int64_t nav_id);
-
- // Asks |remote_model_helper_| to construct memories from |visits_|.
- void GetMemories(MemoriesCallback callback);
-
- private:
- friend class MemoriesServiceTestApi;
-
- // If the Memories flag is enabled, this contains all the visits in-memory
- // during the Profile lifetime.
- // TODO(tommycli): Hide this better behind a new debug flag.
- std::vector<MemoriesVisit> visits_;
- // A visit is constructed stepwise. Visits are initially placed in
- // |incomplete_visits_| and moved to |visits_| once completed.
- std::map<int64_t, MemoriesVisit> incomplete_visits_;
-
- // Helper service to handle communicating with the remote model. This will be
- // used for debugging only; the launch ready feature will use a local model
- // instead.
- std::unique_ptr<MemoriesRemoteModelHelper> remote_model_helper_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoriesService);
-};
-
-} // namespace memories
-
-#endif // COMPONENTS_HISTORY_CLUSTERS_CORE_MEMORIES_SERVICE_H_
diff --git a/chromium/components/history_clusters/core/memories_service_test_api.h b/chromium/components/history_clusters/core/memories_service_test_api.h
deleted file mode 100644
index 813c73476df..00000000000
--- a/chromium/components/history_clusters/core/memories_service_test_api.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_HISTORY_CLUSTERS_CORE_MEMORIES_SERVICE_TEST_API_H_
-#define COMPONENTS_HISTORY_CLUSTERS_CORE_MEMORIES_SERVICE_TEST_API_H_
-
-#include <vector>
-
-#include "components/history_clusters/core/memories_service.h"
-#include "components/history_clusters/core/visit_data.h"
-
-namespace memories {
-
-class MemoriesServiceTestApi {
- public:
- explicit MemoriesServiceTestApi(MemoriesService* memories_service)
- : memories_service_(memories_service) {}
-
- std::vector<MemoriesVisit> GetVisits() const {
- return memories_service_->visits_;
- }
-
- MemoriesService* memories_service_;
-};
-
-} // namespace memories
-
-#endif // COMPONENTS_HISTORY_CLUSTERS_CORE_MEMORIES_SERVICE_TEST_API_H_
diff --git a/chromium/components/history_clusters/core/memories_service_unittest.cc b/chromium/components/history_clusters/core/memories_service_unittest.cc
deleted file mode 100644
index 57774913304..00000000000
--- a/chromium/components/history_clusters/core/memories_service_unittest.cc
+++ /dev/null
@@ -1,474 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/history_clusters/core/memories_service.h"
-
-#include <memory>
-#include <string>
-
-#include "base/callback_forward.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/run_loop.h"
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-#include "base/test/bind.h"
-#include "base/test/gtest_util.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
-#include "base/time/time.h"
-#include "components/history/core/browser/history_types.h"
-#include "components/history/core/browser/url_row.h"
-#include "components/history_clusters/core/memories_features.h"
-#include "components/history_clusters/core/memories_service_test_api.h"
-#include "components/history_clusters/core/visit_data.h"
-#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
-#include "services/network/public/cpp/data_element.h"
-#include "services/network/public/cpp/resource_request_body.h"
-#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/network/test/test_url_loader_factory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace {
-
-std::string StripWhitespace(std::string str) {
- base::EraseIf(str, base::IsAsciiWhitespace<char>);
- return str;
-}
-
-// Returns a Time that's |milliseconds| milliseconds after Windows epoch.
-base::Time IntToTime(int milliseconds) {
- return base::Time::FromDeltaSinceWindowsEpoch(
- base::TimeDelta::FromMilliseconds(milliseconds));
-}
-
-class MemoriesServiceTest : public testing::Test {
- public:
- MemoriesServiceTest()
- : shared_url_loader_factory_(
- base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
- &test_url_loader_factory_)),
- memories_service_(std::make_unique<memories::MemoriesService>(
- nullptr,
- shared_url_loader_factory_)),
- memories_service_test_api_(
- std::make_unique<memories::MemoriesServiceTestApi>(
- memories_service_.get())),
- task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
- run_loop_quit_(run_loop_.QuitClosure()) {}
-
- MemoriesServiceTest(const MemoriesServiceTest&) = delete;
- MemoriesServiceTest& operator=(const MemoriesServiceTest&) = delete;
-
- void AddVisit(int time, const GURL& url) {
- auto& visit =
- memories_service_->GetOrCreateIncompleteVisit(next_navigation_id_);
- visit.visit_row.visit_time = IntToTime(time);
- visit.url_row.set_url(url);
- AddVisit(visit);
- }
-
- void AddVisit(const memories::MemoriesVisit& visit) {
- auto& visit_copy =
- memories_service_->GetOrCreateIncompleteVisit(next_navigation_id_);
- visit_copy = visit;
- visit_copy.status.history_rows = true;
- visit_copy.status.navigation_ended = true;
- visit_copy.status.navigation_end_signals = true;
- memories_service_->CompleteVisitIfReady(next_navigation_id_);
- next_navigation_id_++;
- }
-
- // Helper to get the most recent remote request body.
- std::string GetPendingRequestBody() {
- const scoped_refptr<network::ResourceRequestBody>& request_body =
- test_url_loader_factory_.GetPendingRequest(0)->request.request_body;
- const network::DataElement& element = (*request_body->elements())[0];
- return std::string(element.As<network::DataElementBytes>().AsStringPiece());
- }
-
- network::TestURLLoaderFactory test_url_loader_factory_;
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
- std::unique_ptr<memories::MemoriesService> memories_service_;
- std::unique_ptr<memories::MemoriesServiceTestApi> memories_service_test_api_;
-
- // Used to allow decoding in tests without spinning up an isolated process.
- base::test::TaskEnvironment task_environment_;
- data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
-
- // Used to verify the async callback is invoked.
- base::RunLoop run_loop_;
- base::RepeatingClosure run_loop_quit_;
-
- // Tracks the next available navigation ID to be associated with visits.
- int64_t next_navigation_id_ = 0;
-};
-
-TEST_F(MemoriesServiceTest, GetMemories) {
- const char endpoint[] = "https://endpoint.com/";
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- memories::kMemories, {{memories::kRemoteModelEndpointParam, endpoint}});
-
- auto AddVisitWithDetails = [&](int time, const GURL& url,
- const std::u16string title, int visit_id,
- int page_end_reason) {
- memories::MemoriesVisit visit;
- visit.visit_row.visit_time = IntToTime(time);
- visit.url_row.set_url(url);
- visit.url_row.set_title(title);
- visit.visit_row.visit_id = visit_id;
- visit.context_signals.page_end_reason = page_end_reason;
- AddVisit(visit);
- };
-
- AddVisitWithDetails(2, GURL{"https://google.com"}, u"Google title", 2, 3);
- AddVisitWithDetails(4, GURL{"https://github.com"}, u"Github title", 4, 5);
-
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
- memories_service_->GetMemories(
- base::BindLambdaForTesting([&](memories::Memories memories) {
- // Verify the parsed response.
- ASSERT_EQ(memories.size(), 2u);
- EXPECT_FALSE(memories[0]->id.is_empty());
- ASSERT_EQ(memories[0]->top_visits.size(), 2u);
- EXPECT_EQ(memories[0]->top_visits[0]->id, 2);
- EXPECT_EQ(memories[0]->top_visits[0]->url, "https://google.com/");
- EXPECT_EQ(memories[0]->top_visits[0]->time, IntToTime(2));
- EXPECT_EQ(base::UTF16ToUTF8(memories[0]->top_visits[0]->page_title),
- "Google title");
- EXPECT_EQ(memories[0]->top_visits[1]->id, 4);
- EXPECT_EQ(memories[0]->top_visits[1]->url, "https://github.com/");
- EXPECT_EQ(memories[0]->top_visits[1]->time, IntToTime(4));
- EXPECT_EQ(base::UTF16ToUTF8(memories[0]->top_visits[1]->page_title),
- "Github title");
- ASSERT_EQ(memories[1]->top_visits.size(), 1u);
- EXPECT_FALSE(memories[1]->id.is_empty());
- EXPECT_EQ(memories[1]->top_visits[0]->id, 4);
- EXPECT_EQ(memories[1]->top_visits[0]->url, "https://github.com/");
- EXPECT_EQ(memories[1]->top_visits[0]->time, IntToTime(4));
- EXPECT_EQ(base::UTF16ToUTF8(memories[1]->top_visits[0]->page_title),
- "Github title");
- run_loop_quit_.Run();
- }));
-
- // Verify the serialized request.
- EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
- EXPECT_EQ(GetPendingRequestBody(), StripWhitespace(R"(
- {
- "visits": [
- {
- "foregroundTimeSecs": 0,
- "isFromGoogleSearch": false,
- "navigationTimeMs": 2.0,
- "origin": "https://google.com/",
- "pageEndReason": 3,
- "pageTransition": 0,
- "siteEngagementScore": 0,
- "url": "https://google.com/",
- "visitId": 2.0
- },
- {
- "foregroundTimeSecs": 0,
- "isFromGoogleSearch": false,
- "navigationTimeMs": 4.0,
- "origin": "https://github.com/",
- "pageEndReason": 5,
- "pageTransition": 0,
- "siteEngagementScore": 0,
- "url": "https://github.com/",
- "visitId": 4.0
- }
- ]
- })"));
-
- // Fake a response from the endpoint.
- test_url_loader_factory_.AddResponse(endpoint, R"(
- {
- "memories": [
- {
- "description": "description",
- "topics": [
- "topic 1",
- "topic 2"
- ],
- "visitIds": [
- 2,
- 4
- ]
- },
- {
- "description": "description 2",
- "topics": [
- "topic 3",
- "topic 4"
- ],
- "visitIds": [
- 4
- ]
- }
- ]
- })");
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-
- // Verify the callback is invoked.
- run_loop_.Run();
-}
-
-TEST_F(MemoriesServiceTest, GetMemoriesWithEmptyVisits) {
- const char endpoint[] = "https://endpoint.com/";
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- memories::kMemories, {{memories::kRemoteModelEndpointParam, endpoint}});
-
- memories_service_->GetMemories(
- base::BindLambdaForTesting([&](memories::Memories memories) {
- // Verify the parsed response.
- EXPECT_TRUE(memories.empty());
- run_loop_quit_.Run();
- }));
-
- // Verify no request is made.
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-
- // Verify the callback is invoked.
- run_loop_.Run();
-}
-
-TEST_F(MemoriesServiceTest, GetMemoriesWithEmptyEndpoint) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- memories::kMemories, {{memories::kRemoteModelEndpointParam, ""}});
-
- AddVisit(0, GURL{"google.com"});
- AddVisit(1, GURL{"github.com"});
-
- EXPECT_DCHECK_DEATH(memories_service_->GetMemories(base::BindLambdaForTesting(
- [&](memories::Memories memories) { NOTREACHED(); })));
-
- // Verify no request is made.
- EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
-}
-
-TEST_F(MemoriesServiceTest, GetMemoriesWithEmptyResponse) {
- const char endpoint[] = "https://endpoint.com/";
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- memories::kMemories, {{memories::kRemoteModelEndpointParam, endpoint}});
-
- AddVisit(0, GURL{"google.com"});
- AddVisit(1, GURL{"github.com"});
-
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
- memories_service_->GetMemories(
- base::BindLambdaForTesting([&](memories::Memories memories) {
- // Verify the parsed response.
- EXPECT_TRUE(memories.empty());
- run_loop_quit_.Run();
- }));
-
- // Verify a request is made.
- EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
-
- // Fake a response from the endpoint.
- test_url_loader_factory_.AddResponse(endpoint, "");
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-
- // Verify the callback is invoked.
- run_loop_.Run();
-}
-
-TEST_F(MemoriesServiceTest, GetMemoriesWithInvalidJsonResponse) {
- const char endpoint[] = "https://endpoint.com/";
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- memories::kMemories, {{memories::kRemoteModelEndpointParam, endpoint}});
-
- AddVisit(0, GURL{"google.com"});
- AddVisit(1, GURL{"github.com"});
-
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
- memories_service_->GetMemories(
- base::BindLambdaForTesting([&](memories::Memories memories) {
- // Verify the parsed response.
- EXPECT_TRUE(memories.empty());
- run_loop_quit_.Run();
- }));
-
- // Verify a request is made.
- EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
-
- // Fake a response from the endpoint.
- test_url_loader_factory_.AddResponse(endpoint, "{waka404woko.weke) !*(&,");
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-
- // Verify the callback is invoked.
- run_loop_.Run();
-}
-
-TEST_F(MemoriesServiceTest, GetMemoriesWithEmptyJsonResponse) {
- const char endpoint[] = "https://endpoint.com/";
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- memories::kMemories, {{memories::kRemoteModelEndpointParam, endpoint}});
-
- AddVisit(0, GURL{"google.com"});
- AddVisit(1, GURL{"github.com"});
-
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
- memories_service_->GetMemories(
- base::BindLambdaForTesting([&](memories::Memories memories) {
- // Verify the parsed response.
- EXPECT_TRUE(memories.empty());
- run_loop_quit_.Run();
- }));
-
- // Verify a request is made.
- EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
-
- // Fake a response from the endpoint.
- test_url_loader_factory_.AddResponse(endpoint, "{}");
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-
- // Verify the callback is invoked.
- run_loop_.Run();
-}
-
-TEST_F(MemoriesServiceTest, GetMemoriesWithPendingRequest) {
- const char endpoint[] = "https://endpoint.com/";
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeatureWithParameters(
- memories::kMemories, {{memories::kRemoteModelEndpointParam, endpoint}});
-
- AddVisit(0, GURL{"google.com"});
- AddVisit(1, GURL{"github.com"});
-
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
- memories_service_->GetMemories(
- base::BindLambdaForTesting([&](memories::Memories memories) {
- // Verify not reached.
- EXPECT_TRUE(false);
- }));
-
- EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
- memories_service_->GetMemories(
- base::BindLambdaForTesting([&](memories::Memories memories) {
- // Verify the parsed response.
- EXPECT_EQ(memories.size(), 2u);
- run_loop_quit_.Run();
- }));
-
- // Verify there's a single request to the endpoint.
- EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
- EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
-
- // Fake a response from the endpoint.
- test_url_loader_factory_.AddResponse(endpoint, R"({"memories": [{}, {}]})");
- EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
-
- // Verify the callback is invoked.
- run_loop_.Run();
-}
-
-TEST_F(MemoriesServiceTest, CompleteVisitIfReady) {
- auto test = [&](memories::RecordingStatus status, bool expected_complete) {
- auto& visit = memories_service_->GetOrCreateIncompleteVisit(0);
- visit.status = status;
- memories_service_->CompleteVisitIfReady(0);
- EXPECT_NE(memories_service_->HasIncompleteVisit(0), expected_complete);
- };
-
- // Complete cases:
- {
- SCOPED_TRACE("Complete without UKM");
- test({true, true, true}, true);
- }
- {
- SCOPED_TRACE("Complete with UKM");
- test({true, true, true, true, true}, true);
- }
-
- // Incomplete without UKM cases:
- {
- SCOPED_TRACE("Incomplete, missing history rows");
- test({false, true}, false);
- }
- {
- SCOPED_TRACE("Incomplete, navigation hasn't ended");
- test({true}, false);
- }
- {
- SCOPED_TRACE("Incomplete, navigation end metrics haven't been recorded");
- test({true, true}, false);
- }
-
- // Incomplete with UKM cases:
- {
- SCOPED_TRACE("Incomplete, missing history rows");
- test({false, true, false, true, true}, false);
- }
- {
- SCOPED_TRACE("Incomplete, navigation hasn't ended");
- test({true, false, false, true, true}, false);
- }
- {
- SCOPED_TRACE("Incomplete, navigation end metrics haven't been recorded");
- test({true, true, false, true, true}, false);
- }
- {
- SCOPED_TRACE("Incomplete, UKM page end missing");
- test({true, true, true, true, false}, false);
- }
-
- auto test_dcheck = [&](memories::RecordingStatus status) {
- auto& visit = memories_service_->GetOrCreateIncompleteVisit(0);
- visit.status = status;
- EXPECT_DCHECK_DEATH(memories_service_->CompleteVisitIfReady(0));
- EXPECT_TRUE(memories_service_->HasIncompleteVisit(0));
- };
-
- // Impossible cases:
- {
- SCOPED_TRACE(
- "Impossible, navigation end signals recorded before navigation ended");
- test_dcheck({true, false, true});
- }
- {
- SCOPED_TRACE(
- "Impossible, navigation end signals recorded before history rows");
- test_dcheck({false, true, true});
- }
- {
- SCOPED_TRACE("Impossible, unexpected UKM page end recorded");
- test_dcheck({false, false, false, false, true});
- }
-}
-
-TEST_F(MemoriesServiceTest, CompleteVisitIfReadyWhenFeatureDisabled) {
- {
- // When the feature is disabled, the incomplete visit should be removed but
- // not added to visits.
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(memories::kMemories);
- auto& visit = memories_service_->GetOrCreateIncompleteVisit(0);
- visit.status = {true, true, true};
- memories_service_->CompleteVisitIfReady(0);
- EXPECT_FALSE(memories_service_->HasIncompleteVisit(0));
- EXPECT_TRUE(memories_service_test_api_->GetVisits().empty());
- }
-
- {
- // When the feature is enabled, the incomplete visit should be removed and
- // added to visits.
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(memories::kMemories);
- auto& visit = memories_service_->GetOrCreateIncompleteVisit(0);
- visit.status = {true, true, true};
- memories_service_->CompleteVisitIfReady(0);
- EXPECT_FALSE(memories_service_->HasIncompleteVisit(0));
- EXPECT_EQ(memories_service_test_api_->GetVisits().size(), 1u);
- }
-}
-
-} // namespace
diff --git a/chromium/components/history_clusters/core/proto/BUILD.gn b/chromium/components/history_clusters/core/proto/BUILD.gn
new file mode 100644
index 00000000000..20e7e6e4afa
--- /dev/null
+++ b/chromium/components/history_clusters/core/proto/BUILD.gn
@@ -0,0 +1,9 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/protobuf/proto_library.gni")
+
+proto_library("proto") {
+ sources = [ "clusters.proto" ]
+}
diff --git a/chromium/components/history_clusters/core/proto/clusters.proto b/chromium/components/history_clusters/core/proto/clusters.proto
new file mode 100644
index 00000000000..54e2093b9b4
--- /dev/null
+++ b/chromium/components/history_clusters/core/proto/clusters.proto
@@ -0,0 +1,52 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+syntax = "proto3";
+
+option optimize_for = LITE_RUNTIME;
+
+package history_clusters.proto;
+
+// Below this line sourced from Google3 for debug (non-production) usage only.
+
+message GetClustersRequest {
+ // Represents a set of visits.
+ repeated Visit visits = 1;
+ // The experiment name that controls the clustering behavior served for
+ // this request.
+ string experiment_name = 2;
+}
+
+message GetClustersResponse {
+ // Represents a set of clusters calculated from the request.
+ repeated Cluster clusters = 1;
+}
+
+message Visit {
+ // The ID associated with this visit.
+ int64 visit_id = 1;
+ // The URL for the visit.
+ string url = 2;
+ // The origin for the visit.
+ string origin = 3;
+ // The amount of time the page load was in the foreground in seconds.
+ int64 foreground_time_secs = 4;
+ // Relative time of navigation for this page load.
+ int64 navigation_time_ms = 5;
+ // Site engagement score rounded to nearest ten.
+ int64 site_engagement_score = 6;
+ // The page end reason.
+ int64 page_end_reason = 7;
+ // Page transition.
+ int64 page_transition = 8;
+ // Whether the page load originated from Google Search.
+ bool is_from_google_search = 9;
+}
+
+message Cluster {
+ // The keywords that the cluster contains/is related to.
+ repeated string keywords = 1;
+ // The ids of each visit that is attached to this cluster where
+ // visit_id corresponds to the visit in the history table.
+ repeated int64 visit_ids = 2;
+}
diff --git a/chromium/components/history_clusters/core/visit_data.h b/chromium/components/history_clusters/core/visit_data.h
index 2e91b5379e9..fa3d28b7a2e 100644
--- a/chromium/components/history_clusters/core/visit_data.h
+++ b/chromium/components/history_clusters/core/visit_data.h
@@ -6,85 +6,39 @@
#define COMPONENTS_HISTORY_CLUSTERS_CORE_VISIT_DATA_H_
#include "components/history/core/browser/history_types.h"
-#include "components/history/core/browser/url_row.h"
-namespace memories {
-
-// Context signals about a page visit collected during the page lifetime.
-// This struct encapsulates data that's shared between UKM and the on-device
-// storage for Memories metadata, recorded to both when the page lifetime ends.
-// This is to ensure that History actually has the visit row already written.
-struct VisitContextSignals {
- // True if the user has cut or copied the omnibox URL to the clipboard for
- // this page load.
- bool omnibox_url_copied = false;
-
- // True if the page was in a tab group when the navigation was committed.
- bool is_existing_part_of_tab_group = false;
-
- // True if the page was NOT part of a tab group when the navigation
- // committed, and IS part of a tab group at the end of the page lifetime.
- bool is_placed_in_tab_group = false;
-
- // True if this page was a bookmark when the navigation was committed.
- bool is_existing_bookmark = false;
-
- // True if the page was NOT a bookmark when the navigation was committed and
- // was MADE a bookmark during the page's lifetime. In other words:
- // If |is_existing_bookmark| is true, that implies |is_new_bookmark| is false.
- bool is_new_bookmark = false;
-
- // True if the page has been explicitly added (by the user) to the list of
- // custom links displayed in the NTP. Links added to the NTP by History
- // TopSites don't count for this. Always false on Android, because Android
- // does not have NTP custom links.
- bool is_ntp_custom_link = false;
-
- // The duration since the last visit to this URL in seconds, if the user has
- // visited the URL before. Recorded as -1 if the user has not visited the URL
- // before, or if the History service is unavailable or slow to respond. Any
- // duration that exceeds 30 days will be recorded as 30 days, so in practice,
- // if this duration indicates 30 days, it can be anything from 30 to the
- // maximum duration that local history is stored.
- int64_t duration_since_last_visit_seconds = -1;
-
- // ---------------------------------------------------------------------------
- // The below metrics are all already recorded by UKM for non-memories reasons.
- // We are duplicating them below to persist on-device and send to an offline
- // model.
-
- // An opaque integer representing page_load_metrics::PageEndReason.
- // Do not use this directly, as it's a raw integer for serialization, and not
- // a typesafe page_load_metrics::PageEndReason.
- int page_end_reason = 0;
-};
+namespace history_clusters {
// Tracks which fields have been or are pending recording. This helps 1) avoid
// re-recording fields and 2) determine whether a visit is compete (i.e. has all
// expected fields recorded).
struct RecordingStatus {
- // Whether |url_row| and |visit_row| have been set.
+ // Whether `url_row` and `visit_row` have been set.
bool history_rows = false;
// Whether a navigation has ended; i.e. another navigation has began in the
// same tab or the navigation's tab has been closed.
bool navigation_ended = false;
- // Whether the |context_signals| associated with navigation end have been set.
- // Should only be true if both |history_rows| and |navigation_ended| are true.
+ // Whether the `context_annotations` associated with navigation end have been
+ // set. Should only be true if both `history_rows` and `navigation_ended` are
+ // true.
bool navigation_end_signals = false;
- // Whether the UKM |page_end_reason| |context_signal| is expected to be set.
+ // Whether the UKM `page_end_reason` `context_annotations` is expected to be
+ // set.
bool expect_ukm_page_end_signals = false;
- // Whether the UKM |page_end_reason| |context_signal| has been set. Should
- // only be true if |expect_ukm_page_end_signals| is true.
+ // Whether the UKM `page_end_reason` `context_annotations` has been set.
+ // Should only be true if `expect_ukm_page_end_signals` is true.
bool ukm_page_end_signals = false;
};
-struct MemoriesVisit {
+// A partially built VisitContextAnnotations with its state of completeness and
+// associated `URLRow` and `VisitRow` which are necessary to build it.
+struct IncompleteVisitContextAnnotations {
+ RecordingStatus status;
history::URLRow url_row;
history::VisitRow visit_row;
- VisitContextSignals context_signals;
- RecordingStatus status;
+ history::VisitContextAnnotations context_annotations;
};
-} // namespace memories
+} // namespace history_clusters
#endif // COMPONENTS_HISTORY_CLUSTERS_CORE_VISIT_DATA_H_
diff --git a/chromium/components/image_fetcher/core/cache/image_cache.cc b/chromium/components/image_fetcher/core/cache/image_cache.cc
index 7737d6dcd51..2bbee9d835f 100644
--- a/chromium/components/image_fetcher/core/cache/image_cache.cc
+++ b/chromium/components/image_fetcher/core/cache/image_cache.cc
@@ -182,7 +182,7 @@ void ImageCache::OnImageMetadataLoadedForLoadImage(
const std::string& key,
ImageDataCallback callback,
base::TimeTicks start_time,
- base::Optional<CachedImageMetadataProto> metadata) {
+ absl::optional<CachedImageMetadataProto> metadata) {
// Record time spent to load metadata.
ImageFetcherMetricsReporter::ReportLoadImageMetadata(start_time);
diff --git a/chromium/components/image_fetcher/core/cache/image_cache.h b/chromium/components/image_fetcher/core/cache/image_cache.h
index ec19ca89c12..0a7a6b869ef 100644
--- a/chromium/components/image_fetcher/core/cache/image_cache.h
+++ b/chromium/components/image_fetcher/core/cache/image_cache.h
@@ -11,9 +11,9 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/image_fetcher/core/cache/image_store_types.h"
#include "components/image_fetcher/core/cache/proto/cached_image_metadata.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefRegistrySimple;
class PrefService;
@@ -87,7 +87,7 @@ class ImageCache : public base::RefCounted<ImageCache> {
const std::string& key,
ImageDataCallback callback,
base::TimeTicks start_time,
- base::Optional<CachedImageMetadataProto> metadata);
+ absl::optional<CachedImageMetadataProto> metadata);
// Deletes the data for |url|.
void DeleteImageImpl(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 8291b03bc92..a403b8a7a2f 100644
--- a/chromium/components/image_fetcher/core/cache/image_cache_unittest.cc
+++ b/chromium/components/image_fetcher/core/cache/image_cache_unittest.cc
@@ -78,7 +78,7 @@ class CachedImageFetcherImageCacheTest : public testing::Test {
InitializeImageCache();
image_cache()->SaveImage(kImageUrl, kImageData, needs_transcoding,
- base::nullopt /* expiration_interval */);
+ absl::nullopt /* expiration_interval */);
RunUntilIdle();
ASSERT_TRUE(IsMetadataPresent(kImageUrlHashed));
@@ -154,7 +154,7 @@ class CachedImageFetcherImageCacheTest : public testing::Test {
void InjectMetadata(std::string key, int data_size, bool needs_transcoding) {
metadata_store_->SaveImageMetadata(key, data_size, needs_transcoding,
- base::nullopt /* expiration_interval */);
+ absl::nullopt /* expiration_interval */);
}
void InjectData(std::string key, std::string data, bool needs_transcoding) {
@@ -202,7 +202,7 @@ TEST_F(CachedImageFetcherImageCacheTest, SanityTest) {
image_cache()->SaveImage(kImageUrl, kImageData,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
RunUntilIdle();
LoadImage(kImageUrl, kImageData);
@@ -224,7 +224,7 @@ TEST_F(CachedImageFetcherImageCacheTest, SaveCallsInitialization) {
ASSERT_FALSE(IsCacheInitialized());
image_cache()->SaveImage(kImageUrl, kImageData,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
db()->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
RunUntilIdle();
@@ -237,7 +237,7 @@ TEST_F(CachedImageFetcherImageCacheTest, Save) {
image_cache()->SaveImage(kImageUrl, kImageData,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
LoadImage(kImageUrl, kImageData);
}
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 7e805043627..6fadd258ade 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
@@ -68,7 +68,7 @@ class CachedImageFetcherImageMetadataStoreLevelDBTest : public testing::Test {
metadata_store()->SaveImageMetadata(
kImageKey, kImageDataLength,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
ASSERT_TRUE(IsDataPresent(kImageKey));
if (!initialize) {
@@ -110,7 +110,7 @@ class CachedImageFetcherImageMetadataStoreLevelDBTest : public testing::Test {
base::Time creation_time,
base::Time last_used_time,
bool needs_transcoding,
- ExpirationInterval expiration_interval = base::nullopt) {
+ ExpirationInterval expiration_interval = absl::nullopt) {
if (!IsDataPresent(key)) {
ASSERT_TRUE(false);
}
@@ -142,7 +142,7 @@ class CachedImageFetcherImageMetadataStoreLevelDBTest : public testing::Test {
MOCK_METHOD1(OnKeysReturned, void(std::vector<std::string>));
MOCK_METHOD1(OnStoreOperationComplete, void(bool));
MOCK_METHOD1(OnImageMetadataLoaded,
- void(base::Optional<CachedImageMetadataProto>));
+ void(absl::optional<CachedImageMetadataProto>));
private:
std::unique_ptr<base::SimpleTestClock> clock_;
@@ -170,7 +170,7 @@ TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, SaveBeforeInit) {
// Start an image load before the database is initialized.
metadata_store()->SaveImageMetadata(kImageKey, kImageDataLength,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
InitializeDatabase();
EXPECT_TRUE(metadata_store()->IsInitialized());
@@ -184,7 +184,7 @@ TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, Save) {
metadata_store()->SaveImageMetadata(kImageKey, kImageDataLength,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
AssertDataPresent(kImageKey, kImageDataLength, clock()->Now(), clock()->Now(),
/* needs_transcoding */ false);
@@ -210,7 +210,7 @@ TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, Delete) {
InitializeDatabase();
metadata_store()->SaveImageMetadata(kImageKey, kImageDataLength,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
ASSERT_TRUE(IsDataPresent(kImageKey));
// Delete the data.
@@ -226,7 +226,7 @@ TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, DeleteDifferentKey) {
InitializeDatabase();
metadata_store()->SaveImageMetadata(kImageKey, kImageDataLength,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
ASSERT_TRUE(IsDataPresent(kImageKey));
// Delete the data.
@@ -303,7 +303,7 @@ TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, GetAllKeys) {
PrepareDatabase(true);
metadata_store()->SaveImageMetadata(kOtherImageKey, kImageDataLength,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
// A GC call before the db is initialized should be ignore.
EXPECT_CALL(
@@ -319,7 +319,7 @@ TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, GetAllKeysLoadFailed) {
PrepareDatabase(true);
metadata_store()->SaveImageMetadata(kOtherImageKey, kImageDataLength,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
// A GC call before the db is initialized should be ignore.
EXPECT_CALL(*this, OnKeysReturned(std::vector<std::string>({})));
@@ -425,7 +425,7 @@ TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest,
clock()->SetNow(clock()->Now() + base::TimeDelta::FromHours(1));
metadata_store()->SaveImageMetadata(kOtherImageKey, kImageDataLength,
/* needs_transcoding */ false,
- /* expiration_interval*/ base::nullopt);
+ /* expiration_interval*/ absl::nullopt);
clock()->SetNow(clock()->Now() - base::TimeDelta::FromHours(1));
ASSERT_TRUE(IsDataPresent(kOtherImageKey));
@@ -498,7 +498,7 @@ TEST_F(CachedImageFetcherImageMetadataStoreLevelDBTest, LoadImageMetadata) {
PrepareDatabase(true);
metadata_store()->SaveImageMetadata(kOtherImageKey, kImageDataLength,
/* needs_transcoding */ true,
- /* expiration_interval*/ base::nullopt);
+ /* expiration_interval*/ absl::nullopt);
EXPECT_CALL(*this, OnImageMetadataLoaded(_));
metadata_store()->LoadImageMetadata(
diff --git a/chromium/components/image_fetcher/core/cache/image_store_types.h b/chromium/components/image_fetcher/core/cache/image_store_types.h
index d99dd14a042..ef19c40fc1c 100644
--- a/chromium/components/image_fetcher/core/cache/image_store_types.h
+++ b/chromium/components/image_fetcher/core/cache/image_store_types.h
@@ -9,8 +9,8 @@
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
#include "components/image_fetcher/core/cache/proto/cached_image_metadata.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace image_fetcher {
@@ -40,13 +40,13 @@ using ImageStoreOperationCallback = base::OnceCallback<void(bool)>;
// CachedImageMetadataProto will be returned if image metadata is loaded
// successfully.
using ImageMetadataCallback =
- base::OnceCallback<void(base::Optional<CachedImageMetadataProto>)>;
+ base::OnceCallback<void(absl::optional<CachedImageMetadataProto>)>;
// Returns a vector of keys.
using KeysCallback = base::OnceCallback<void(std::vector<std::string>)>;
// The expiration interval for CacheStrategy::HOLD_UNTIL_EXPIRED.
-using ExpirationInterval = base::Optional<base::TimeDelta>;
+using ExpirationInterval = absl::optional<base::TimeDelta>;
} // namespace image_fetcher
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 6c523744ef8..d84c9dfd488 100644
--- a/chromium/components/image_fetcher/core/cached_image_fetcher_unittest.cc
+++ b/chromium/components/image_fetcher/core/cached_image_fetcher_unittest.cc
@@ -97,7 +97,7 @@ class CachedImageFetcherTest : public testing::Test {
// Use an initial request to start the cache up.
image_cache_->SaveImage(ImageUrl().spec(), kImageData,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
RunUntilIdle();
db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
image_cache_->DeleteImage(ImageUrl().spec());
@@ -171,7 +171,7 @@ TEST_F(CachedImageFetcherTest, FetchImageFromCache) {
// Save the image in the database.
image_cache()->SaveImage(ImageUrl().spec(), kImageData,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
RunUntilIdle();
base::MockCallback<ImageDataFetcherCallback> data_callback;
@@ -196,7 +196,7 @@ TEST_F(CachedImageFetcherTest, FetchImageFromCacheNeedsTranscoding) {
// Save the image in the database.
image_cache()->SaveImage(ImageUrl().spec(), kImageData,
/* needs_transcoding */ true,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
RunUntilIdle();
base::MockCallback<ImageDataFetcherCallback> data_callback;
@@ -223,7 +223,7 @@ TEST_F(CachedImageFetcherTest, FetchImageFromCacheReadOnly) {
// Save the image in the database.
image_cache()->SaveImage(ImageUrl().spec(), kImageData,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
test_url_loader_factory()->AddResponse(ImageUrl().spec(), kImageData);
RunUntilIdle();
{
@@ -376,7 +376,7 @@ TEST_F(CachedImageFetcherTest, FetchImageWithSkipDiskCache) {
// Save the image in the database.
image_cache()->SaveImage(ImageUrl().spec(), kImageDataOther,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
RunUntilIdle();
test_url_loader_factory()->AddResponse(ImageUrl().spec(), kImageData);
diff --git a/chromium/components/image_fetcher/core/image_data_fetcher.cc b/chromium/components/image_fetcher/core/image_data_fetcher.cc
index 89179e46945..f9629371bf3 100644
--- a/chromium/components/image_fetcher/core/image_data_fetcher.cc
+++ b/chromium/components/image_fetcher/core/image_data_fetcher.cc
@@ -57,7 +57,7 @@ ImageDataFetcher::~ImageDataFetcher() {
}
void ImageDataFetcher::SetImageDownloadLimit(
- base::Optional<int64_t> max_download_bytes) {
+ absl::optional<int64_t> max_download_bytes) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
max_download_bytes_ = max_download_bytes;
}
diff --git a/chromium/components/image_fetcher/core/image_data_fetcher.h b/chromium/components/image_fetcher/core/image_data_fetcher.h
index ef6740951be..3d8d134ef7a 100644
--- a/chromium/components/image_fetcher/core/image_data_fetcher.h
+++ b/chromium/components/image_fetcher/core/image_data_fetcher.h
@@ -12,13 +12,13 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "components/image_fetcher/core/image_fetcher.h"
#include "components/image_fetcher/core/image_fetcher_types.h"
#include "components/image_fetcher/core/request_metadata.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/referrer_policy.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace network {
@@ -39,7 +39,7 @@ class ImageDataFetcher {
// Sets an upper limit for image downloads.
// Already running downloads are not affected.
- void SetImageDownloadLimit(base::Optional<int64_t> max_download_bytes);
+ void SetImageDownloadLimit(absl::optional<int64_t> max_download_bytes);
// Fetches the raw image bytes from the given |image_url| and calls the given
// |callback|. The callback is run even if fetching the URL fails. In case
@@ -99,7 +99,7 @@ class ImageDataFetcher {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// Upper limit for the number of bytes to download per image.
- base::Optional<int64_t> max_download_bytes_;
+ absl::optional<int64_t> max_download_bytes_;
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/components/image_fetcher/core/image_fetcher.h b/chromium/components/image_fetcher/core/image_fetcher.h
index 0d59dc8584c..3c073ac5a33 100644
--- a/chromium/components/image_fetcher/core/image_fetcher.h
+++ b/chromium/components/image_fetcher/core/image_fetcher.h
@@ -10,10 +10,10 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/image_fetcher/core/image_fetcher_types.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
#include "url/gurl.h"
@@ -56,11 +56,11 @@ class ImageFetcherParams {
return network_traffic_annotation_tag_;
}
- void set_max_download_size(base::Optional<int64_t> max_download_bytes) {
+ void set_max_download_size(absl::optional<int64_t> max_download_bytes) {
max_download_bytes_ = max_download_bytes;
}
- base::Optional<int64_t> max_download_size() const {
+ absl::optional<int64_t> max_download_size() const {
return max_download_bytes_;
}
@@ -89,7 +89,7 @@ class ImageFetcherParams {
skip_disk_cache_read_ = skip_disk_cache_read;
}
- const base::Optional<base::TimeDelta>& expiration_interval() const {
+ const absl::optional<base::TimeDelta>& expiration_interval() const {
return expiration_interval_;
}
@@ -109,11 +109,11 @@ class ImageFetcherParams {
const net::NetworkTrafficAnnotationTag network_traffic_annotation_tag_;
- base::Optional<int64_t> max_download_bytes_;
+ absl::optional<int64_t> max_download_bytes_;
// Only used in rare cases to keep the cache file on disk for certain period
// of time. Image files will stay in cache at least for |expiration_interval_|
// after last use.
- base::Optional<base::TimeDelta> expiration_interval_;
+ absl::optional<base::TimeDelta> expiration_interval_;
gfx::Size desired_frame_size_;
std::string uma_client_name_;
// When true, the image fetcher will skip transcoding whenever possible. Only
diff --git a/chromium/components/image_fetcher/core/reduced_mode_image_fetcher.h b/chromium/components/image_fetcher/core/reduced_mode_image_fetcher.h
index ceeb25b4285..4524caff9d9 100644
--- a/chromium/components/image_fetcher/core/reduced_mode_image_fetcher.h
+++ b/chromium/components/image_fetcher/core/reduced_mode_image_fetcher.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_IMAGE_FETCHER_CORE_REDUCED_MODE_IMAGE_FETCHER_H_
#define COMPONENTS_IMAGE_FETCHER_CORE_REDUCED_MODE_IMAGE_FETCHER_H_
-#include <string>
-
#include "base/sequence_checker.h"
#include "components/image_fetcher/core/image_fetcher.h"
#include "url/gurl.h"
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 6c44b285664..40de5837691 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
@@ -91,7 +91,7 @@ class ReducedModeImageFetcherTest : public testing::Test {
// Use an initial request to start the cache up.
image_cache_->SaveImage(ImageUrl().spec(), kImageData,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
RunUntilIdle();
db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
image_cache_->DeleteImage(ImageUrl().spec());
@@ -167,7 +167,7 @@ TEST_F(ReducedModeImageFetcherTest, FetchNeedsTranscodingImageFromCache) {
// Save the image that needs transcoding in the database.
image_cache()->SaveImage(ImageUrl().spec(), kImageData,
/* needs_transcoding */ true,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
VerifyCacheHit();
}
@@ -175,7 +175,7 @@ TEST_F(ReducedModeImageFetcherTest, FetchImageFromCache) {
// Save the image that doesn't need transcoding in the database.
image_cache()->SaveImage(ImageUrl().spec(), kImageData,
/* needs_transcoding */ false,
- /* expiration_interval */ base::nullopt);
+ /* expiration_interval */ absl::nullopt);
VerifyCacheHit();
}
diff --git a/chromium/components/image_fetcher/ios/ios_image_decoder_impl.h b/chromium/components/image_fetcher/ios/ios_image_decoder_impl.h
index da7398ce40f..3e442909dc5 100644
--- a/chromium/components/image_fetcher/ios/ios_image_decoder_impl.h
+++ b/chromium/components/image_fetcher/ios/ios_image_decoder_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_IMAGE_FETCHER_IOS_IMAGE_DECODER_IMPL_H_
-#define COMPONENTS_IMAGE_FETCHER_IOS_IMAGE_DECODER_IMPL_H_
+#ifndef COMPONENTS_IMAGE_FETCHER_IOS_IOS_IMAGE_DECODER_IMPL_H_
+#define COMPONENTS_IMAGE_FETCHER_IOS_IOS_IMAGE_DECODER_IMPL_H_
#include <memory>
@@ -16,4 +16,4 @@ std::unique_ptr<ImageDecoder> CreateIOSImageDecoder();
} // namespace image_fetcher
-#endif // COMPONENTS_IMAGE_FETCHER_IOS_IMAGE_DECODER_IMPL_H_
+#endif // COMPONENTS_IMAGE_FETCHER_IOS_IOS_IMAGE_DECODER_IMPL_H_
diff --git a/chromium/components/infobars/android/infobar_android.h b/chromium/components/infobars/android/infobar_android.h
index cf08fe9aeb9..38881e8c4b4 100644
--- a/chromium/components/infobars/android/infobar_android.h
+++ b/chromium/components/infobars/android/infobar_android.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_INFOBARS_ANDROID_INFOBAR_ANDROID_H_
#define COMPONENTS_INFOBARS_ANDROID_INFOBAR_ANDROID_H_
-#include <string>
-
#include "base/android/scoped_java_ref.h"
#include "base/callback.h"
#include "base/macros.h"
diff --git a/chromium/components/infobars/content/content_infobar_manager.cc b/chromium/components/infobars/content/content_infobar_manager.cc
index d93801b6c63..d8b13e2ef31 100644
--- a/chromium/components/infobars/content/content_infobar_manager.cc
+++ b/chromium/components/infobars/content/content_infobar_manager.cc
@@ -5,7 +5,6 @@
#include "components/infobars/content/content_infobar_manager.h"
#include "base/command_line.h"
-#include "components/infobars/core/confirm_infobar_delegate.h"
#include "components/infobars/core/infobar.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
@@ -62,12 +61,6 @@ int ContentInfoBarManager::GetActiveEntryID() {
return active_entry ? active_entry->GetUniqueID() : 0;
}
-std::unique_ptr<InfoBar> ContentInfoBarManager::CreateConfirmInfoBar(
- std::unique_ptr<ConfirmInfoBarDelegate> delegate) {
- NOTREACHED();
- return nullptr;
-}
-
void ContentInfoBarManager::RenderProcessGone(base::TerminationStatus status) {
RemoveAllInfoBars(true);
}
@@ -94,8 +87,16 @@ void ContentInfoBarManager::NavigationEntryCommitted(
}
void ContentInfoBarManager::WebContentsDestroyed() {
- // Subclasses may override this method to destroy this object, so don't do
- // anything here.
+ // The WebContents is going away; be aggressively paranoid and delete
+ // |this| lest other parts of the system attempt to add infobars or use
+ // this object otherwise during the destruction.
+ // TODO(blundell): This operation seems unnecessary as detailed in the
+ // conversation on
+ // https://chromium-review.googlesource.com/c/chromium/src/+/2859170/7 .
+ // Look at removing it.
+ web_contents()->RemoveUserData(UserDataKey());
+ // That was the equivalent of "delete this". This object is now destroyed;
+ // returning from this function is the only safe thing to do.
}
void ContentInfoBarManager::OpenURL(const GURL& url,
@@ -109,7 +110,8 @@ void ContentInfoBarManager::OpenURL(const GURL& url,
? WindowOpenDisposition::NEW_FOREGROUND_TAB
: disposition,
ui::PAGE_TRANSITION_LINK, false));
+}
-} // namespace infobars
+WEB_CONTENTS_USER_DATA_KEY_IMPL(ContentInfoBarManager)
} // namespace infobars
diff --git a/chromium/components/infobars/content/content_infobar_manager.h b/chromium/components/infobars/content/content_infobar_manager.h
index f9c123445ed..fedd7f412d9 100644
--- a/chromium/components/infobars/content/content_infobar_manager.h
+++ b/chromium/components/infobars/content/content_infobar_manager.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_INFOBARS_CONTENT_CONTENT_INFOBAR_MANAGER_H_
#define COMPONENTS_INFOBARS_CONTENT_CONTENT_INFOBAR_MANAGER_H_
-#include <memory>
-#include <vector>
-
#include "base/macros.h"
#include "build/build_config.h"
#include "components/infobars/core/infobar_manager.h"
@@ -27,15 +24,10 @@ class InfoBar;
// Associates a WebContents to an InfoBarManager.
// It manages the infobar notifications and responds to navigation events.
-// By default the creation of confirm infobars is not supported. If embedders
-// wish to add such support, they should create a custom subclass of
-// ContentInfoBarManager that overrides CreateConfirmInfoBar().
-// This class is not itself a WebContentsUserData in order to support such
-// subclassing; it is expected that embedders will either have an instance of
-// this class as a member of their "Tab" objects or create a custom subclass
-// that is a WCUD.
-class ContentInfoBarManager : public InfoBarManager,
- public content::WebContentsObserver {
+class ContentInfoBarManager
+ : public InfoBarManager,
+ public content::WebContentsObserver,
+ public content::WebContentsUserData<ContentInfoBarManager> {
public:
explicit ContentInfoBarManager(content::WebContents* web_contents);
~ContentInfoBarManager() override;
@@ -58,14 +50,13 @@ class ContentInfoBarManager : public InfoBarManager,
void set_ignore_next_reload() { ignore_next_reload_ = true; }
// InfoBarManager:
- // NOTE: By default this method is NOTREACHED() and returns nullptr.
- // TODO(sdefresne): Change clients to invoke this on InfoBarManager
- // and turn the method override private.
- std::unique_ptr<InfoBar> CreateConfirmInfoBar(
- std::unique_ptr<ConfirmInfoBarDelegate> delegate) override;
void OpenURL(const GURL& url, WindowOpenDisposition disposition) override;
private:
+ friend class content::WebContentsUserData<ContentInfoBarManager>;
+
+ WEB_CONTENTS_USER_DATA_KEY_DECL();
+
// InfoBarManager:
int GetActiveEntryID() override;
diff --git a/chromium/components/infobars/core/BUILD.gn b/chromium/components/infobars/core/BUILD.gn
index a19199fbd74..8882f9c15e4 100644
--- a/chromium/components/infobars/core/BUILD.gn
+++ b/chromium/components/infobars/core/BUILD.gn
@@ -25,10 +25,12 @@ static_library("core") {
"simple_alert_infobar_delegate.h",
]
- public_deps = [ "//skia" ]
+ public_deps = [
+ "//base",
+ "//skia",
+ ]
deps = [
- "//base",
"//ui/base",
"//ui/gfx",
"//ui/gfx/animation",
diff --git a/chromium/components/infobars/core/infobar_container.h b/chromium/components/infobars/core/infobar_container.h
index 004e773db8e..d7602d28e03 100644
--- a/chromium/components/infobars/core/infobar_container.h
+++ b/chromium/components/infobars/core/infobar_container.h
@@ -11,7 +11,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/time/time.h"
#include "components/infobars/core/infobar_manager.h"
#include "third_party/skia/include/core/SkColor.h"
diff --git a/chromium/components/infobars/core/infobar_manager.h b/chromium/components/infobars/core/infobar_manager.h
index 4b9bf110f2a..eb53254b6bf 100644
--- a/chromium/components/infobars/core/infobar_manager.h
+++ b/chromium/components/infobars/core/infobar_manager.h
@@ -14,7 +14,6 @@
#include "base/observer_list.h"
#include "components/infobars/core/infobar_delegate.h"
-class ConfirmInfoBarDelegate;
class GURL;
class TestInfoBar;
@@ -101,10 +100,6 @@ class InfoBarManager {
// Returns the active entry ID.
virtual int GetActiveEntryID() = 0;
- // Returns a confirm infobar that owns |delegate|.
- virtual std::unique_ptr<infobars::InfoBar> CreateConfirmInfoBar(
- std::unique_ptr<ConfirmInfoBarDelegate> delegate) = 0;
-
// Opens a URL according to the specified |disposition|.
virtual void OpenURL(const GURL& url, WindowOpenDisposition disposition) = 0;
diff --git a/chromium/components/infobars/core/simple_alert_infobar_delegate.cc b/chromium/components/infobars/core/simple_alert_infobar_delegate.cc
index ed5cb461774..62447bb5835 100644
--- a/chromium/components/infobars/core/simple_alert_infobar_delegate.cc
+++ b/chromium/components/infobars/core/simple_alert_infobar_delegate.cc
@@ -6,24 +6,8 @@
#include <memory>
-#include "components/infobars/core/infobar.h"
-#include "components/infobars/core/infobar_manager.h"
#include "third_party/skia/include/core/SkBitmap.h"
-// static
-void SimpleAlertInfoBarDelegate::Create(
- infobars::InfoBarManager* infobar_manager,
- infobars::InfoBarDelegate::InfoBarIdentifier infobar_identifier,
- const gfx::VectorIcon* vector_icon,
- const std::u16string& message,
- bool auto_expire,
- bool should_animate) {
- infobar_manager->AddInfoBar(infobar_manager->CreateConfirmInfoBar(
- std::unique_ptr<ConfirmInfoBarDelegate>(new SimpleAlertInfoBarDelegate(
- infobar_identifier, vector_icon, message, auto_expire,
- should_animate))));
-}
-
SimpleAlertInfoBarDelegate::SimpleAlertInfoBarDelegate(
infobars::InfoBarDelegate::InfoBarIdentifier infobar_identifier,
const gfx::VectorIcon* vector_icon,
diff --git a/chromium/components/infobars/core/simple_alert_infobar_delegate.h b/chromium/components/infobars/core/simple_alert_infobar_delegate.h
index f95853c8cee..173543c757a 100644
--- a/chromium/components/infobars/core/simple_alert_infobar_delegate.h
+++ b/chromium/components/infobars/core/simple_alert_infobar_delegate.h
@@ -15,24 +15,8 @@ namespace gfx {
struct VectorIcon;
}
-namespace infobars {
-class InfoBarManager;
-}
-
class SimpleAlertInfoBarDelegate : public ConfirmInfoBarDelegate {
public:
- // Creates a simple alert infobar and delegate and adds the infobar to
- // |infobar_manager|. If |vector_icon| is not null, it will be shown.
- // |infobar_identifier| names what class triggered the infobar for metrics.
- static void Create(
- infobars::InfoBarManager* infobar_manager,
- infobars::InfoBarDelegate::InfoBarIdentifier infobar_identifier,
- const gfx::VectorIcon* vector_icon,
- const std::u16string& message,
- bool auto_expire = true,
- bool should_animate = true);
-
- private:
SimpleAlertInfoBarDelegate(
infobars::InfoBarDelegate::InfoBarIdentifier infobar_identifier,
const gfx::VectorIcon* vector_icon,
@@ -41,6 +25,7 @@ class SimpleAlertInfoBarDelegate : public ConfirmInfoBarDelegate {
bool should_animate);
~SimpleAlertInfoBarDelegate() override;
+ private:
// ConfirmInfoBarDelegate:
infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
const gfx::VectorIcon& GetVectorIcon() const override;
diff --git a/chromium/components/installedapp/android/installed_app_verifier.cc b/chromium/components/installedapp/android/installed_app_verifier.cc
index 61e466f3770..d1d13d01ca2 100644
--- a/chromium/components/installedapp/android/installed_app_verifier.cc
+++ b/chromium/components/installedapp/android/installed_app_verifier.cc
@@ -45,7 +45,7 @@ void JNI_InstalledAppProviderImpl_CheckDigitalAssetLinksRelationshipForWebApk(
auto handler =
std::make_unique<digital_asset_links::DigitalAssetLinksHandler>(
- content::BrowserContext::GetDefaultStoragePartition(browser_context)
+ browser_context->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess());
auto* handler_ptr = handler.get();
diff --git a/chromium/components/javascript_dialogs/android/javascript_dialogs_android_strings.grd b/chromium/components/javascript_dialogs/android/javascript_dialogs_android_strings.grd
index 6068d52e8b1..f62b2f861fe 100644
--- a/chromium/components/javascript_dialogs/android/javascript_dialogs_android_strings.grd
+++ b/chromium/components/javascript_dialogs/android/javascript_dialogs_android_strings.grd
@@ -170,7 +170,7 @@
<release seq="1">
<messages fallback_to_english="true">
<!-- These are copied from javascript_dialogs_strings.grdp. It would be better to share, but javascript_dialogs_strings.grdp are part of the monolithic components_strings_grd target, and depending on that pulls in lots of unnecessary strings, causing UnusedResource errors. -->
- <message name="IDS_LEAVE" desc="Dialog button to leave the current page and navigate to a new page. [CHAR-LIMIT=20]">
+ <message name="IDS_LEAVE" desc="Dialog button to leave the current page and navigate to a new page. [CHAR_LIMIT=20]">
Leave
</message>
<message name="IDS_SUPPRESS_JS_MODAL_DIALOGS" desc="Checkbox allowing users to forgo additional prompts from a web page.">
diff --git a/chromium/components/javascript_dialogs/tab_modal_dialog_manager.cc b/chromium/components/javascript_dialogs/tab_modal_dialog_manager.cc
index 6890e2a7f65..d47ce32f95e 100644
--- a/chromium/components/javascript_dialogs/tab_modal_dialog_manager.cc
+++ b/chromium/components/javascript_dialogs/tab_modal_dialog_manager.cc
@@ -353,6 +353,9 @@ void TabModalDialogManager::OnVisibilityChanged(
void TabModalDialogManager::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
+ if (!navigation_handle->IsInPrimaryMainFrame())
+ return;
+
// Close the dialog if the user started a new navigation. This allows reloads
// and history navigations to proceed.
CloseDialog(DismissalCause::kTabNavigated, false, std::u16string());
diff --git a/chromium/components/javascript_dialogs/tab_modal_dialog_manager.h b/chromium/components/javascript_dialogs/tab_modal_dialog_manager.h
index 549dc5725a2..870cb7ff97b 100644
--- a/chromium/components/javascript_dialogs/tab_modal_dialog_manager.h
+++ b/chromium/components/javascript_dialogs/tab_modal_dialog_manager.h
@@ -10,13 +10,13 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/javascript_dialogs/tab_modal_dialog_manager_delegate.h"
#include "components/javascript_dialogs/tab_modal_dialog_view.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace javascript_dialogs {
diff --git a/chromium/components/javascript_dialogs/views/OWNERS b/chromium/components/javascript_dialogs/views/OWNERS
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/components/javascript_dialogs/views/OWNERS
+++ /dev/null
diff --git a/chromium/components/javascript_dialogs/views/layer_dimmer_unittest.cc b/chromium/components/javascript_dialogs/views/layer_dimmer_unittest.cc
index de9e22bdf4e..6531c6a9079 100644
--- a/chromium/components/javascript_dialogs/views/layer_dimmer_unittest.cc
+++ b/chromium/components/javascript_dialogs/views/layer_dimmer_unittest.cc
@@ -10,6 +10,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/window_types.h"
#include "ui/aura/window.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/layer_type.h"
#include "ui/gfx/geometry/rect.h"
diff --git a/chromium/components/js_injection/browser/js_communication_host.h b/chromium/components/js_injection/browser/js_communication_host.h
index 12758410900..5f15854623f 100644
--- a/chromium/components/js_injection/browser/js_communication_host.h
+++ b/chromium/components/js_injection/browser/js_communication_host.h
@@ -9,9 +9,9 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "components/js_injection/common/interfaces.mojom.h"
#include "content/public/browser/web_contents_observer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class RenderFrameHost;
@@ -44,8 +44,8 @@ class JsCommunicationHost : public content::WebContentsObserver {
AddScriptResult& operator=(const AddScriptResult&);
~AddScriptResult();
- base::Optional<std::string> error_message;
- base::Optional<int> script_id;
+ absl::optional<std::string> error_message;
+ absl::optional<int> script_id;
};
// Native side AddDocumentStartJavaScript, returns an error message if the
diff --git a/chromium/components/js_injection/browser/js_to_browser_messaging.cc b/chromium/components/js_injection/browser/js_to_browser_messaging.cc
index a1e677189f6..c7778d2be58 100644
--- a/chromium/components/js_injection/browser/js_to_browser_messaging.cc
+++ b/chromium/components/js_injection/browser/js_to_browser_messaging.cc
@@ -51,7 +51,8 @@ class JsToBrowserMessaging::ReplyProxyImpl : public WebMessageReplyProxy {
java_to_js_messaging_->OnPostMessage(message->message);
}
bool IsInBackForwardCache() override {
- return render_frame_host_->IsInBackForwardCache();
+ return render_frame_host_->GetLifecycleState() ==
+ content::RenderFrameHost::LifecycleState::kInBackForwardCache;
}
private:
diff --git a/chromium/components/js_injection/browser/web_message_reply_proxy.h b/chromium/components/js_injection/browser/web_message_reply_proxy.h
index 9a09c02e62c..2eb52975efe 100644
--- a/chromium/components/js_injection/browser/web_message_reply_proxy.h
+++ b/chromium/components/js_injection/browser/web_message_reply_proxy.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_JS_INJECTION_BROWSER_WEB_MESSAGE_REPLY_PROXY_H_
#define COMPONENTS_JS_INJECTION_BROWSER_WEB_MESSAGE_REPLY_PROXY_H_
-#include <string>
-
-
namespace js_injection {
struct WebMessage;
diff --git a/chromium/components/js_injection/common/origin_matcher_mojom_traits.cc b/chromium/components/js_injection/common/origin_matcher_mojom_traits.cc
index 3bb7bd838a0..34cf33dc4b5 100644
--- a/chromium/components/js_injection/common/origin_matcher_mojom_traits.cc
+++ b/chromium/components/js_injection/common/origin_matcher_mojom_traits.cc
@@ -5,7 +5,6 @@
#include "components/js_injection/common/origin_matcher_mojom_traits.h"
#include "base/strings/pattern.h"
-#include "base/strings/stringprintf.h"
#include "components/js_injection/common/origin_matcher_internal.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
diff --git a/chromium/components/js_injection/common/origin_matcher_mojom_traits.h b/chromium/components/js_injection/common/origin_matcher_mojom_traits.h
index 873d2cb94e2..b4c0255399e 100644
--- a/chromium/components/js_injection/common/origin_matcher_mojom_traits.h
+++ b/chromium/components/js_injection/common/origin_matcher_mojom_traits.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_JS_INJECTION_COMMON_ORIGIN_MATCHER_MOJOM_TRAITS_H_
#define COMPONENTS_JS_INJECTION_COMMON_ORIGIN_MATCHER_MOJOM_TRAITS_H_
-#include <string>
#include <vector>
#include "components/js_injection/common/origin_matcher.h"
diff --git a/chromium/components/js_injection/renderer/js_binding.cc b/chromium/components/js_injection/renderer/js_binding.cc
index bcac5ccdc7a..31ce81b502a 100644
--- a/chromium/components/js_injection/renderer/js_binding.cc
+++ b/chromium/components/js_injection/renderer/js_binding.cc
@@ -150,7 +150,7 @@ void JsBinding::PostMessage(gin::Arguments* args) {
}
for (auto& obj : objs) {
- base::Optional<blink::MessagePortChannel> port =
+ absl::optional<blink::MessagePortChannel> port =
blink::WebMessagePortConverter::DisentangleAndExtractMessagePortChannel(
args->isolate(), obj);
// If the port is null we should throw an exception.
diff --git a/chromium/components/keep_alive_registry/keep_alive_types.cc b/chromium/components/keep_alive_registry/keep_alive_types.cc
index d9ee3e9166d..21388288450 100644
--- a/chromium/components/keep_alive_registry/keep_alive_types.cc
+++ b/chromium/components/keep_alive_registry/keep_alive_types.cc
@@ -66,6 +66,12 @@ std::ostream& operator<<(std::ostream& out, const KeepAliveOrigin& origin) {
return out << "CREDENTIAL_PROVIDER_SIGNIN_DIALOG";
case KeepAliveOrigin::NATIVE_MESSAGING_HOST_ERROR_REPORT:
return out << "NATIVE_MESSAGING_HOST_ERROR_REPORT";
+ case KeepAliveOrigin::WEB_APP_INTENT_PICKER:
+ return out << "WEB_APP_INTENT_PICKER";
+ case KeepAliveOrigin::WEB_APP_PROTOCOL_HANDLER_LAUNCH:
+ return out << "WEB_APP_PROTOCOL_HANDLER_LAUNCH";
+ case KeepAliveOrigin::SESSION_DATA_DELETER:
+ return out << "SESSION_DATA_DELETER";
}
NOTREACHED();
diff --git a/chromium/components/keep_alive_registry/keep_alive_types.h b/chromium/components/keep_alive_registry/keep_alive_types.h
index fbceab5d91a..ab3fb234492 100644
--- a/chromium/components/keep_alive_registry/keep_alive_types.h
+++ b/chromium/components/keep_alive_registry/keep_alive_types.h
@@ -61,9 +61,14 @@ enum class KeepAliveOrigin {
PROFILE_LOADER,
USER_MANAGER_VIEW,
CREDENTIAL_PROVIDER_SIGNIN_DIALOG,
+ WEB_APP_INTENT_PICKER,
+ WEB_APP_PROTOCOL_HANDLER_LAUNCH,
// c/b/web_applications
APP_START_URL_MIGRATION,
+
+ // c/b/sessions
+ SESSION_DATA_DELETER,
};
// Restart: Allow Chrome to restart when all the registered KeepAlives allow
diff --git a/chromium/components/keyed_service/content/browser_context_dependency_manager.h b/chromium/components/keyed_service/content/browser_context_dependency_manager.h
index 4628cc68ad5..e521103701f 100644
--- a/chromium/components/keyed_service/content/browser_context_dependency_manager.h
+++ b/chromium/components/keyed_service/content/browser_context_dependency_manager.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_KEYED_SERVICE_CONTENT_BROWSER_CONTEXT_DEPENDENCY_MANAGER_H_
#define COMPONENTS_KEYED_SERVICE_CONTENT_BROWSER_CONTEXT_DEPENDENCY_MANAGER_H_
-#include <memory>
-
#include "base/callback_forward.h"
#include "base/callback_list.h"
#include "base/compiler_specific.h"
diff --git a/chromium/components/keyed_service/core/BUILD.gn b/chromium/components/keyed_service/core/BUILD.gn
index 443a617d575..d9424463e19 100644
--- a/chromium/components/keyed_service/core/BUILD.gn
+++ b/chromium/components/keyed_service/core/BUILD.gn
@@ -38,8 +38,9 @@ component("core") {
defines = [ "KEYED_SERVICE_IMPLEMENTATION" ]
+ public_deps = [ "//base" ]
+
deps = [
- "//base",
"//components/pref_registry",
"//components/prefs",
"//services/tracing/public/cpp:cpp",
diff --git a/chromium/components/keyed_service/core/keyed_service.h b/chromium/components/keyed_service/core/keyed_service.h
index 2bd32cf2167..df300b37e24 100644
--- a/chromium/components/keyed_service/core/keyed_service.h
+++ b/chromium/components/keyed_service/core/keyed_service.h
@@ -30,6 +30,8 @@ class KEYED_SERVICE_EXPORT KeyedService {
virtual ~KeyedService();
// The first pass is to call Shutdown on a KeyedService.
+ // Shutdown will be called automatically for you. Don't directly invoke this
+ // unless you have a specific reason and understand the implications.
virtual void Shutdown();
private:
diff --git a/chromium/components/keyed_service/core/keyed_service_base_factory.h b/chromium/components/keyed_service/core/keyed_service_base_factory.h
index dd57940566b..7f5d7df18be 100644
--- a/chromium/components/keyed_service/core/keyed_service_base_factory.h
+++ b/chromium/components/keyed_service/core/keyed_service_base_factory.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_KEYED_SERVICE_CORE_KEYED_SERVICE_BASE_FACTORY_H_
#define COMPONENTS_KEYED_SERVICE_CORE_KEYED_SERVICE_BASE_FACTORY_H_
-#include <set>
-
#include "base/sequence_checker.h"
#include "components/keyed_service/core/dependency_node.h"
#include "components/keyed_service/core/keyed_service_export.h"
diff --git a/chromium/components/keyed_service/core/keyed_service_shutdown_notifier.cc b/chromium/components/keyed_service/core/keyed_service_shutdown_notifier.cc
index 6f06f25c2b6..d451c42b987 100644
--- a/chromium/components/keyed_service/core/keyed_service_shutdown_notifier.cc
+++ b/chromium/components/keyed_service/core/keyed_service_shutdown_notifier.cc
@@ -5,14 +5,12 @@
#include "components/keyed_service/core/keyed_service_export.h"
#include "components/keyed_service/core/keyed_service_shutdown_notifier.h"
-KeyedServiceShutdownNotifier::KeyedServiceShutdownNotifier() {
-}
-KeyedServiceShutdownNotifier::~KeyedServiceShutdownNotifier() {
-}
+KeyedServiceShutdownNotifier::KeyedServiceShutdownNotifier() = default;
+KeyedServiceShutdownNotifier::~KeyedServiceShutdownNotifier() = default;
base::CallbackListSubscription KeyedServiceShutdownNotifier::Subscribe(
- const base::RepeatingClosure& callback) {
- return closure_list_.Add(callback);
+ base::OnceClosure callback) {
+ return closure_list_.Add(std::move(callback));
}
void KeyedServiceShutdownNotifier::Shutdown() {
diff --git a/chromium/components/keyed_service/core/keyed_service_shutdown_notifier.h b/chromium/components/keyed_service/core/keyed_service_shutdown_notifier.h
index 2348443d22f..47603d172ac 100644
--- a/chromium/components/keyed_service/core/keyed_service_shutdown_notifier.h
+++ b/chromium/components/keyed_service/core/keyed_service_shutdown_notifier.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_KEYED_SERVICE_CORE_KEYED_SERVICE_SHUTDOWN_NOTIFIER_H_
#define COMPONENTS_KEYED_SERVICE_CORE_KEYED_SERVICE_SHUTDOWN_NOTIFIER_H_
-#include <memory>
-
#include "base/callback_list.h"
#include "base/macros.h"
#include "components/keyed_service/core/keyed_service.h"
@@ -26,14 +24,13 @@ class KEYED_SERVICE_EXPORT KeyedServiceShutdownNotifier : public KeyedService {
// Subscribe for a notification when the keyed services this object depends on
// (as defined by its factory) are shut down. The subscription can be
// destroyed to unsubscribe.
- base::CallbackListSubscription Subscribe(
- const base::RepeatingClosure& callback);
+ base::CallbackListSubscription Subscribe(base::OnceClosure callback);
private:
// KeyedService implementation:
void Shutdown() override;
- base::RepeatingClosureList closure_list_;
+ base::OnceClosureList closure_list_;
DISALLOW_COPY_AND_ASSIGN(KeyedServiceShutdownNotifier);
};
diff --git a/chromium/components/keyed_service/ios/BUILD.gn b/chromium/components/keyed_service/ios/BUILD.gn
index 2e5638d8d89..4987575a900 100644
--- a/chromium/components/keyed_service/ios/BUILD.gn
+++ b/chromium/components/keyed_service/ios/BUILD.gn
@@ -12,8 +12,9 @@ source_set("ios") {
"refcounted_browser_state_keyed_service_factory.h",
]
+ public_deps = [ "//base" ]
+
deps = [
- "//base",
"//base/third_party/dynamic_annotations",
"//components/keyed_service/core",
"//ios/web",
diff --git a/chromium/components/keyed_service/ios/browser_state_dependency_manager.h b/chromium/components/keyed_service/ios/browser_state_dependency_manager.h
index 2ad8cf87b54..92528bb81b9 100644
--- a/chromium/components/keyed_service/ios/browser_state_dependency_manager.h
+++ b/chromium/components/keyed_service/ios/browser_state_dependency_manager.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_KEYED_SERVICE_IOS_BROWSER_STATE_DEPENDENCY_MANAGER_H_
#define COMPONENTS_KEYED_SERVICE_IOS_BROWSER_STATE_DEPENDENCY_MANAGER_H_
-#include "base/callback_forward.h"
#include "base/callback_list.h"
#include "base/macros.h"
#include "components/keyed_service/core/dependency_manager.h"
diff --git a/chromium/components/language/android/BUILD.gn b/chromium/components/language/android/BUILD.gn
index 50f6042e38f..703069a3b9f 100644
--- a/chromium/components/language/android/BUILD.gn
+++ b/chromium/components/language/android/BUILD.gn
@@ -30,6 +30,27 @@ android_library("language_bridge_java") {
"java/src/org/chromium/components/language/GeoLanguageProviderBridge.java",
]
- deps = [ "//base:base_java" ]
+ deps = [
+ "//base:base_java",
+ "//third_party/androidx:androidx_annotation_annotation_java",
+ ]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
+
+android_library("language_bridge_javatests") {
+ testonly = true
+
+ sources = [ "java/src/org/chromium/components/language/AndroidLanguageMetricsBridgeTest.java" ]
+ deps = [
+ ":language_bridge_java",
+ "//base:base_java",
+ "//base:base_java_test_support",
+ "//chrome/browser/flags:java",
+ "//chrome/test/android:chrome_java_test_support",
+ "//content/public/test/android:content_java_test_support",
+ "//third_party/android_support_test_runner:rules_java",
+ "//third_party/androidx:androidx_annotation_annotation_java",
+ "//third_party/androidx:androidx_test_runner_java",
+ "//third_party/junit",
+ ]
+}
diff --git a/chromium/components/language/android/DEPS b/chromium/components/language/android/DEPS
index 771bfcf2ecd..e1d0dc50d76 100644
--- a/chromium/components/language/android/DEPS
+++ b/chromium/components/language/android/DEPS
@@ -1,3 +1,10 @@
include_rules = [
"+components/language/content",
]
+
+specific_include_rules = {
+ ".*Test\.java": [
+ "+chrome/test/android",
+ "+content/public/test/android",
+ ]
+}
diff --git a/chromium/components/language/android/android_language_metrics_bridge.cc b/chromium/components/language/android/android_language_metrics_bridge.cc
index f3b6610e2d1..e2805097f5d 100644
--- a/chromium/components/language/android/android_language_metrics_bridge.cc
+++ b/chromium/components/language/android/android_language_metrics_bridge.cc
@@ -24,3 +24,13 @@ JNI_AndroidLanguageMetricsBridge_ReportExplicitLanguageAskStateChanged(
: kTranslateExplicitLanguageAskLanguageRemoved,
base::HashMetricName(base::android::ConvertJavaStringToUTF8(language)));
}
+
+// Records the HashMetric of |value| in the sparse histogram |histogramName|.
+static void JNI_AndroidLanguageMetricsBridge_ReportHashMetricName(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& histogramName,
+ const base::android::JavaParamRef<jstring>& value) {
+ base::UmaHistogramSparse(
+ base::android::ConvertJavaStringToUTF8(histogramName),
+ base::HashMetricName(base::android::ConvertJavaStringToUTF8(value)));
+}
diff --git a/chromium/components/language/content/browser/geo_language_provider.cc b/chromium/components/language/content/browser/geo_language_provider.cc
index aba9e9f14f4..8324a8a5fcf 100644
--- a/chromium/components/language/content/browser/geo_language_provider.cc
+++ b/chromium/components/language/content/browser/geo_language_provider.cc
@@ -75,7 +75,7 @@ void GeoLanguageProvider::StartUp(PrefService* const prefs) {
const base::ListValue* const cached_languages_list =
prefs_->GetList(kCachedGeoLanguagesPref);
- for (const auto& language_value : *cached_languages_list) {
+ for (const auto& language_value : cached_languages_list->GetList()) {
languages_.push_back(language_value.GetString());
}
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 fb9193ef6b2..01e5c51e6b6 100644
--- a/chromium/components/language/content/browser/geo_language_provider_unittest.cc
+++ b/chromium/components/language/content/browser/geo_language_provider_unittest.cc
@@ -76,7 +76,7 @@ class GeoLanguageProviderTest : public testing::Test {
std::vector<std::string> languages;
const base::ListValue* const cached_languages_list =
local_state_.GetList(GeoLanguageProvider::kCachedGeoLanguagesPref);
- for (const auto& language_value : *cached_languages_list) {
+ for (const auto& language_value : cached_languages_list->GetList()) {
languages.push_back(language_value.GetString());
}
return languages;
diff --git a/chromium/components/language/content/browser/ulp_language_code_locator/BUILD.gn b/chromium/components/language/content/browser/ulp_language_code_locator/BUILD.gn
index 9b711fdb663..b80435d4e73 100644
--- a/chromium/components/language/content/browser/ulp_language_code_locator/BUILD.gn
+++ b/chromium/components/language/content/browser/ulp_language_code_locator/BUILD.gn
@@ -6,8 +6,7 @@ import("//build/config/compiler/compiler.gni")
import("//build/config/python.gni")
import("//testing/test.gni")
-# TODO(crbug.com/1112471): Get this to run correctly under Python3.
-python2_action("ulp_serialized_to_static_c") {
+action("ulp_serialized_to_static_c") {
script = "ulp_serialized_to_static_c.py"
inputs = [
"geolanguage-data_rank0.bin",
diff --git a/chromium/components/language/content/browser/ulp_language_code_locator/ulp_serialized_to_static_c.py b/chromium/components/language/content/browser/ulp_language_code_locator/ulp_serialized_to_static_c.py
index c3bf08cdbbe..009ec4a7403 100644
--- a/chromium/components/language/content/browser/ulp_language_code_locator/ulp_serialized_to_static_c.py
+++ b/chromium/components/language/content/browser/ulp_language_code_locator/ulp_serialized_to_static_c.py
@@ -27,7 +27,7 @@ def ReadSerializedData(input_path):
linebreak = data.index(b'\n')
# First line is comma-separated list of languages.
- language_codes = data[:linebreak].strip().split(b',')
+ language_codes = data[:linebreak].strip().decode(encoding="utf-8").split(',')
# Rest of the file is the serialized tree.
tree_bytes = data[linebreak+1:]
diff --git a/chromium/components/language/core/browser/heuristic_language_model.cc b/chromium/components/language/core/browser/heuristic_language_model.cc
index 98b4fe95197..66c2731d546 100644
--- a/chromium/components/language/core/browser/heuristic_language_model.cc
+++ b/chromium/components/language/core/browser/heuristic_language_model.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/feature_list.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "components/prefs/pref_service.h"
@@ -41,7 +42,7 @@ bool HasBaseAndRegion(const std::string& lang, std::string* const base) {
const std::vector<base::StringPiece> tokens = base::SplitStringPiece(
lang, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- *base = tokens.size() > 0 ? tokens[0].as_string() : "";
+ *base = tokens.size() > 0 ? std::string(tokens[0]) : "";
return tokens.size() > 1 && !tokens[1].empty();
}
@@ -191,7 +192,7 @@ std::vector<std::string> GetUlpLanguages(
return langs;
// It is assumed that languages appear in descending order of probability.
- for (const auto& entry : *preference) {
+ for (const auto& entry : preference->GetList()) {
const base::DictionaryValue* item = nullptr;
std::string language;
double probability = 0.0;
diff --git a/chromium/components/language/core/browser/language_prefs.cc b/chromium/components/language/core/browser/language_prefs.cc
index 0e744bad147..49e30e1fa3e 100644
--- a/chromium/components/language/core/browser/language_prefs.cc
+++ b/chromium/components/language/core/browser/language_prefs.cc
@@ -160,7 +160,7 @@ void LanguagePrefs::GetDeduplicatedUserLanguages(
// Add policy languages.
for (const auto& language :
- *prefs_->GetList(language::prefs::kForcedLanguages)) {
+ prefs_->GetList(language::prefs::kForcedLanguages)->GetList()) {
if (forced_languages_set_.find(language.GetString()) ==
forced_languages_set_.end()) {
deduplicated_languages.emplace_back(language.GetString());
diff --git a/chromium/components/language/core/browser/url_language_histogram.cc b/chromium/components/language/core/browser/url_language_histogram.cc
index a0b092ba45d..6a0d1551e9c 100644
--- a/chromium/components/language/core/browser/url_language_histogram.cc
+++ b/chromium/components/language/core/browser/url_language_histogram.cc
@@ -26,11 +26,10 @@ const float kDiscountFactor = 0.75f;
// Gets the sum of the counter for all languages in the histogram.
int GetCountersSum(const base::DictionaryValue& dict) {
int sum = 0;
- int counter_value = 0;
for (base::DictionaryValue::Iterator itr(dict); !itr.IsAtEnd();
itr.Advance()) {
- if (itr.value().GetAsInteger(&counter_value))
- sum += counter_value;
+ if (itr.value().is_int())
+ sum += itr.value().GetInt();
}
return sum;
}
@@ -39,18 +38,17 @@ int GetCountersSum(const base::DictionaryValue& dict) {
void DiscountAndCleanCounters(base::DictionaryValue* dict) {
std::set<std::string> remove_keys;
- int counter_value = 0;
for (base::DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd();
itr.Advance()) {
// Remove languages with invalid or small values.
- if (!itr.value().GetAsInteger(&counter_value) ||
- counter_value < (kCutoffRatio * kMaxCountersSum)) {
+ if (!itr.value().is_int() ||
+ itr.value().GetInt() < (kCutoffRatio * kMaxCountersSum)) {
remove_keys.insert(itr.key());
continue;
}
// Discount the value.
- dict->SetInteger(itr.key(), counter_value * kDiscountFactor);
+ dict->SetInteger(itr.key(), itr.value().GetInt() * kDiscountFactor);
}
for (const std::string& lang_to_remove : remove_keys)
@@ -67,13 +65,12 @@ std::vector<UrlLanguageHistogram::LanguageInfo> GetAllLanguages(
return std::vector<UrlLanguageHistogram::LanguageInfo>();
std::vector<UrlLanguageHistogram::LanguageInfo> top_languages;
- int counter_value = 0;
for (base::DictionaryValue::Iterator itr(dict); !itr.IsAtEnd();
itr.Advance()) {
- if (!itr.value().GetAsInteger(&counter_value))
+ if (!itr.value().is_int())
continue;
top_languages.emplace_back(
- itr.key(), static_cast<float>(counter_value) / counters_sum);
+ itr.key(), static_cast<float>(itr.value().GetInt()) / counters_sum);
}
return top_languages;
}
diff --git a/chromium/components/language/ios/browser/ios_language_detection_tab_helper.h b/chromium/components/language/ios/browser/ios_language_detection_tab_helper.h
index d9c82e21c73..b62bdf2f586 100644
--- a/chromium/components/language/ios/browser/ios_language_detection_tab_helper.h
+++ b/chromium/components/language/ios/browser/ios_language_detection_tab_helper.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_LANUGUAGE_IOS_BROWSER_IOS_LANGUAGE_DETECTION_TAB_HELPER_H_
-#define COMPONENTS_LANUGUAGE_IOS_BROWSER_IOS_LANGUAGE_DETECTION_TAB_HELPER_H_
+#ifndef COMPONENTS_LANGUAGE_IOS_BROWSER_IOS_LANGUAGE_DETECTION_TAB_HELPER_H_
+#define COMPONENTS_LANGUAGE_IOS_BROWSER_IOS_LANGUAGE_DETECTION_TAB_HELPER_H_
#include "base/callback.h"
#include "base/macros.h"
@@ -66,4 +66,4 @@ class IOSLanguageDetectionTabHelper
} // namespace language
-#endif // COMPONENTS_LANUGUAGE_IOS_BROWSER_IOS_LANGUAGE_DETECTION_TAB_HELPER_H_
+#endif // COMPONENTS_LANGUAGE_IOS_BROWSER_IOS_LANGUAGE_DETECTION_TAB_HELPER_H_
diff --git a/chromium/components/lens/lens_features.cc b/chromium/components/lens/lens_features.cc
index 2b98254c038..ccbe505ff8b 100644
--- a/chromium/components/lens/lens_features.cc
+++ b/chromium/components/lens/lens_features.cc
@@ -3,7 +3,9 @@
// found in the LICENSE file.
#include "components/lens/lens_features.h"
+
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
namespace lens {
namespace features {
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 a4711650e83..529b1fe23d3 100644
--- a/chromium/components/leveldb_proto/internal/leveldb_proto_feature_list.h
+++ b/chromium/components/leveldb_proto/internal/leveldb_proto_feature_list.h
@@ -15,4 +15,4 @@ extern const COMPONENT_EXPORT(LEVELDB_PROTO) base::Feature
} // namespace leveldb_proto
-#endif // COMPONENTS_LEVELDB_PROTO_FEATURE_LIST_H_ \ No newline at end of file
+#endif // COMPONENTS_LEVELDB_PROTO_INTERNAL_LEVELDB_PROTO_FEATURE_LIST_H_
diff --git a/chromium/components/leveldb_proto/internal/proto/shared_db_metadata.proto b/chromium/components/leveldb_proto/internal/proto/shared_db_metadata.proto
index 28d9950982b..07903f654d4 100644
--- a/chromium/components/leveldb_proto/internal/proto/shared_db_metadata.proto
+++ b/chromium/components/leveldb_proto/internal/proto/shared_db_metadata.proto
@@ -47,4 +47,8 @@ message SharedDBMetadataProto {
};
optional MigrationStatus migration_status = 3;
+
+ // Number of times the shared db failed to open. After a number of failures we
+ // try to delete the database and and create a new one.
+ optional uint32 failure_count = 4;
}
diff --git a/chromium/components/leveldb_proto/internal/proto_database_selector.h b/chromium/components/leveldb_proto/internal/proto_database_selector.h
index a15954f2f00..4778b538bac 100644
--- a/chromium/components/leveldb_proto/internal/proto_database_selector.h
+++ b/chromium/components/leveldb_proto/internal/proto_database_selector.h
@@ -62,7 +62,9 @@ class COMPONENT_EXPORT(LEVELDB_PROTO) ProtoDatabaseSelector
kFailureNoSharedDBProviderUniqueFailed = 26,
kSuccessNoSharedDBProviderUniqueSucceeded = 27,
kFailureUniqueDbMissingClearSharedFailed = 28,
- kMaxValue = kFailureUniqueDbMissingClearSharedFailed,
+ kDeletedSharedDbOnRepeatedFailures = 29,
+ kDeletionOfSharedDbFailed = 30,
+ kMaxValue = kDeletionOfSharedDbFailed,
};
static void RecordInitState(ProtoDatabaseInitState state);
diff --git a/chromium/components/leveldb_proto/internal/shared_proto_database.cc b/chromium/components/leveldb_proto/internal/shared_proto_database.cc
index 263105fe6e7..416fe74678e 100644
--- a/chromium/components/leveldb_proto/internal/shared_proto_database.cc
+++ b/chromium/components/leveldb_proto/internal/shared_proto_database.cc
@@ -25,8 +25,16 @@ namespace {
const base::FilePath::CharType kMetadataDatabasePath[] =
FILE_PATH_LITERAL("metadata");
+
+// Number of attempts within a session to open the metadata database. The most
+// common errors observed from metrics are IO errors and retries would help
+// reduce this. After retries the shared db initialization will fail.
const int kMaxInitMetaDatabaseAttempts = 3;
+// The number of consecutive failures when opening shared db after which the db
+// is destroyed and created again.
+const int kMaxSharedDbFailuresBeforeDestroy = 5;
+
const char kGlobalMetadataKey[] = "__global";
const char kSharedProtoDatabaseUmaName[] = "SharedDb";
@@ -287,23 +295,9 @@ void SharedProtoDatabase::ProcessInitRequests(Enums::InitStatus status) {
}
}
-// We allow some number of attempts to be made to initialize the metadata
-// database because it's crucial for the operation of the shared database. In
-// the event that the metadata DB is corrupt, at least one retry will be made
-// so that we create the DB from scratch again.
-// |corruption| lets us know whether the retries are because of corruption.
void SharedProtoDatabase::InitMetadataDatabase(int attempt, bool corruption) {
DCHECK_CALLED_ON_VALID_SEQUENCE(on_task_runner_);
- if (attempt >= kMaxInitMetaDatabaseAttempts) {
- // TODO(crbug/1003951): |attempt| is always 0, need to save it and do the
- // retry, or delete it.
- init_state_ = InitState::kFailure;
- init_status_ = Enums::InitStatus::kError;
- ProcessInitRequests(init_status_);
- return;
- }
-
// TODO: figure out destroy on corruption param
metadata_db_wrapper_->Init(
base::BindOnce(&SharedProtoDatabase::OnMetadataInitComplete, this,
@@ -319,6 +313,15 @@ void SharedProtoDatabase::OnMetadataInitComplete(
bool success = status == Enums::kOK;
if (!success) {
+ // We allow some number of attempts to be made to initialize the metadata
+ // database because it's crucial for the operation of the shared database.
+ // In the event that the metadata DB is corrupt, at least one retry will be
+ // made so that we create the DB from scratch again.
+ if (attempt < kMaxInitMetaDatabaseAttempts) {
+ InitMetadataDatabase(attempt + 1, corruption);
+ return;
+ }
+
init_state_ = InitState::kFailure;
init_status_ = Enums::InitStatus::kError;
ProcessInitRequests(init_status_);
@@ -342,6 +345,14 @@ void SharedProtoDatabase::OnGetGlobalMetadata(
if (success && proto) {
// It existed so let's update our internal |corruption_count_|
metadata_ = std::move(proto);
+
+ if (metadata_->failure_count() >= kMaxSharedDbFailuresBeforeDestroy) {
+ ProtoLevelDBWrapper::Destroy(
+ db_dir_, /*client_id=*/std::string(), task_runner_,
+ base::BindOnce(&SharedProtoDatabase::OnDestroySharedDatabase, this));
+ return;
+ }
+
InitDatabase();
return;
}
@@ -351,12 +362,12 @@ void SharedProtoDatabase::OnGetGlobalMetadata(
metadata_ = std::make_unique<SharedDBMetadataProto>();
metadata_->set_corruptions(corruption ? 1U : 0U);
metadata_->clear_migration_status();
+ metadata_->set_failure_count(0);
CommitUpdatedGlobalMetadata(
- base::BindOnce(&SharedProtoDatabase::OnFinishCorruptionCountWrite, this));
+ base::BindOnce(&SharedProtoDatabase::OnWriteMetadataAtInit, this));
}
-void SharedProtoDatabase::OnFinishCorruptionCountWrite(
- bool success) {
+void SharedProtoDatabase::OnWriteMetadataAtInit(bool success) {
DCHECK_CALLED_ON_VALID_SEQUENCE(on_task_runner_);
// TODO(thildebr): Should we retry a few times if we fail this? It feels like
// if we fail to write this single value something serious happened with the
@@ -371,6 +382,29 @@ void SharedProtoDatabase::OnFinishCorruptionCountWrite(
InitDatabase();
}
+void SharedProtoDatabase::OnDestroySharedDatabase(bool success) {
+ if (success) {
+ // Destroy database should just delete files in a directory. It fails less
+ // often than opening database. If this fails, do not update the failure
+ // count and retry destroy in next session and just try to open the database
+ // normally.
+ metadata_->set_failure_count(0);
+
+ // Try to commit the changes to metadata, but do nothing in case of failure.
+ CommitUpdatedGlobalMetadata(base::BindOnce([](bool success) {}));
+ }
+ if (success) {
+ ProtoDatabaseSelector::RecordInitState(
+ ProtoDatabaseSelector::ProtoDatabaseInitState::
+ kDeletedSharedDbOnRepeatedFailures);
+ } else {
+ ProtoDatabaseSelector::RecordInitState(
+ ProtoDatabaseSelector::ProtoDatabaseInitState::
+ kDeletionOfSharedDbFailed);
+ }
+ InitDatabase();
+}
+
void SharedProtoDatabase::InitDatabase() {
DCHECK_CALLED_ON_VALID_SEQUENCE(on_task_runner_);
auto options = CreateSimpleOptions();
@@ -399,6 +433,7 @@ void SharedProtoDatabase::OnDatabaseInit(bool create_if_missing,
// Again, it seems like a failure to update here will indicate something
// serious has gone wrong with the metadata database.
metadata_->set_corruptions(metadata_->corruptions() + 1);
+ metadata_->set_failure_count(metadata_->failure_count() + 1);
CommitUpdatedGlobalMetadata(base::BindOnce(
&SharedProtoDatabase::OnUpdateCorruptionCountAtInit, this));
@@ -446,6 +481,13 @@ void SharedProtoDatabase::OnDatabaseInit(bool create_if_missing,
task_runner_->PostDelayedTask(FROM_HERE, delete_obsolete_task_.callback(),
delete_obsolete_delay_);
}
+ if (init_state_ == InitState::kSuccess) {
+ metadata_->set_failure_count(0);
+ } else {
+ metadata_->set_failure_count(metadata_->failure_count() + 1);
+ }
+ // Try to commit the changes to metadata, but do nothing in case of failure.
+ CommitUpdatedGlobalMetadata(base::BindOnce([](bool success) {}));
}
void SharedProtoDatabase::Shutdown() {
diff --git a/chromium/components/leveldb_proto/internal/shared_proto_database.h b/chromium/components/leveldb_proto/internal/shared_proto_database.h
index 1d9c4237ae7..67b6adc41a9 100644
--- a/chromium/components/leveldb_proto/internal/shared_proto_database.h
+++ b/chromium/components/leveldb_proto/internal/shared_proto_database.h
@@ -132,7 +132,8 @@ class COMPONENT_EXPORT(LEVELDB_PROTO) SharedProtoDatabase
void OnGetGlobalMetadata(bool corruption,
bool success,
std::unique_ptr<SharedDBMetadataProto> proto);
- void OnFinishCorruptionCountWrite(bool success);
+ void OnWriteMetadataAtInit(bool success);
+ void OnDestroySharedDatabase(bool success);
void InitDatabase();
void OnDatabaseInit(bool create_if_missing, Enums::InitStatus status);
void CheckCorruptionAndRunInitCallback(
diff --git a/chromium/components/leveldb_proto/public/proto_database.h b/chromium/components/leveldb_proto/public/proto_database.h
index 5f377e41416..6b022980bf5 100644
--- a/chromium/components/leveldb_proto/public/proto_database.h
+++ b/chromium/components/leveldb_proto/public/proto_database.h
@@ -9,7 +9,6 @@
#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"
#include "third_party/leveldatabase/env_chromium.h"
diff --git a/chromium/components/leveldb_proto/public/proto_database_provider.cc b/chromium/components/leveldb_proto/public/proto_database_provider.cc
index 20a05522385..9a5caaa9bd6 100644
--- a/chromium/components/leveldb_proto/public/proto_database_provider.cc
+++ b/chromium/components/leveldb_proto/public/proto_database_provider.cc
@@ -54,6 +54,7 @@ void ProtoDatabaseProvider::GetSharedDBInstance(
void ProtoDatabaseProvider::SetSharedDBDeleteObsoleteDelayForTesting(
base::TimeDelta delay) {
+ base::AutoLock lock(get_db_lock_);
if (db_)
db_->set_delete_obsolete_delay_for_testing(delay); // IN-TEST
}
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 bd625c1695f..0f779a5d224 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
@@ -93,6 +93,14 @@ std::string SharedProtoDatabaseClientList::ProtoDbTypeToString(
return "CommerceSubscriptionDatabase";
case ProtoDbType::MERCHANT_TRUST_SIGNAL_DATABASE:
return "MerchantTrustSignalEventDatabase";
+ case ProtoDbType::SHARE_HISTORY_DATABASE:
+ return "ShareHistoryDatabase";
+ case ProtoDbType::SEGMENT_INFO_DATABASE:
+ return "SegmentInfoDatabase";
+ case ProtoDbType::SIGNAL_DATABASE:
+ return "SignalDatabase";
+ case ProtoDbType::SIGNAL_STORAGE_CONFIG_DATABASE:
+ return "SignalStorageConfigDatabase";
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 442adb6b11b..3e229afbd1b 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
@@ -58,6 +58,10 @@ enum class ProtoDbType {
CART_DATABASE = 32,
COMMERCE_SUBSCRIPTION_DATABASE = 33,
MERCHANT_TRUST_SIGNAL_DATABASE = 34,
+ SHARE_HISTORY_DATABASE = 35,
+ SEGMENT_INFO_DATABASE = 37,
+ SIGNAL_DATABASE = 38,
+ SIGNAL_STORAGE_CONFIG_DATABASE = 39,
LAST,
};
diff --git a/chromium/components/link_header_util/link_header_util.cc b/chromium/components/link_header_util/link_header_util.cc
index 0fdb95ea0fc..ea5d2877e1d 100644
--- a/chromium/components/link_header_util/link_header_util.cc
+++ b/chromium/components/link_header_util/link_header_util.cc
@@ -154,7 +154,7 @@ bool ParseLinkHeaderValue(
std::string::const_iterator begin,
std::string::const_iterator end,
std::string* url,
- std::unordered_map<std::string, base::Optional<std::string>>* params) {
+ std::unordered_map<std::string, absl::optional<std::string>>* params) {
// Can't parse an empty string.
if (begin == end)
return false;
@@ -183,7 +183,7 @@ bool ParseLinkHeaderValue(
std::string name = base::ToLowerASCII(params_iterator.name_piece());
if (!params_iterator.value_is_quoted() &&
params_iterator.value_piece().empty())
- params->insert(std::make_pair(name, base::nullopt));
+ params->insert(std::make_pair(name, absl::nullopt));
else
params->insert(std::make_pair(name, params_iterator.value()));
}
diff --git a/chromium/components/link_header_util/link_header_util.h b/chromium/components/link_header_util/link_header_util.h
index 2eba9a69dd8..35a0d3d0314 100644
--- a/chromium/components/link_header_util/link_header_util.h
+++ b/chromium/components/link_header_util/link_header_util.h
@@ -10,7 +10,7 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace link_header_util {
@@ -35,7 +35,7 @@ bool ParseLinkHeaderValue(
std::string::const_iterator begin,
std::string::const_iterator end,
std::string* url,
- std::unordered_map<std::string, base::Optional<std::string>>* params);
+ std::unordered_map<std::string, absl::optional<std::string>>* params);
} // namespace link_header_util
diff --git a/chromium/components/link_header_util/link_header_util_fuzzer.cc b/chromium/components/link_header_util/link_header_util_fuzzer.cc
index 42f2b7f6495..de959f76a8f 100644
--- a/chromium/components/link_header_util/link_header_util_fuzzer.cc
+++ b/chromium/components/link_header_util/link_header_util_fuzzer.cc
@@ -7,8 +7,8 @@
#include <string>
#include <unordered_map>
-#include "base/optional.h"
#include "components/link_header_util/link_header_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace link_header_util {
@@ -19,7 +19,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
for (const auto& pair : result) {
assert(pair.first < pair.second);
std::string url;
- std::unordered_map<std::string, base::Optional<std::string>> params;
+ std::unordered_map<std::string, absl::optional<std::string>> params;
(void)ParseLinkHeaderValue(pair.first, pair.second, &url, &params);
}
diff --git a/chromium/components/link_header_util/link_header_util_unittest.cc b/chromium/components/link_header_util/link_header_util_unittest.cc
index bbc53fbe542..6674aa7e4b2 100644
--- a/chromium/components/link_header_util/link_header_util_unittest.cc
+++ b/chromium/components/link_header_util/link_header_util_unittest.cc
@@ -22,7 +22,7 @@ void SplitLinkHeaderForTesting(const std::string& header,
bool ParseLinkHeaderValueForTesting(
std::string value,
std::string* url,
- std::unordered_map<std::string, base::Optional<std::string>>* params) {
+ std::unordered_map<std::string, absl::optional<std::string>>* params) {
return ParseLinkHeaderValue(value.begin(), value.end(), url, params);
}
@@ -98,7 +98,7 @@ TEST_P(SimpleParseTest, Simple) {
const SimpleParseTestData test = GetParam();
std::string url;
- std::unordered_map<std::string, base::Optional<std::string>> params;
+ std::unordered_map<std::string, absl::optional<std::string>> params;
EXPECT_EQ(test.valid,
ParseLinkHeaderValueForTesting(test.link, &url, &params));
if (test.valid) {
diff --git a/chromium/components/live_caption/BUILD.gn b/chromium/components/live_caption/BUILD.gn
new file mode 100644
index 00000000000..0cfc6b44131
--- /dev/null
+++ b/chromium/components/live_caption/BUILD.gn
@@ -0,0 +1,49 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (!is_android) {
+ static_library("live_caption") {
+ sources = [
+ "views/caption_bubble.cc",
+ "views/caption_bubble.h",
+ "views/caption_bubble_model.cc",
+ "views/caption_bubble_model.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/strings",
+ "//components/vector_icons",
+ "//third_party/re2",
+ "//ui/accessibility",
+ "//ui/base",
+ "//ui/gfx",
+ "//ui/native_theme",
+ "//ui/strings:ui_strings_grit",
+ "//ui/views",
+ ]
+ }
+} # !is_android
+
+source_set("constants") {
+ sources = [
+ "pref_names.cc",
+ "pref_names.h",
+ ]
+}
+
+source_set("utils") {
+ sources = [
+ "caption_util.cc",
+ "caption_util.h",
+ ]
+
+ deps = [
+ ":constants",
+ "//base",
+ "//components/prefs",
+ "//ui/base",
+ "//ui/native_theme",
+ ]
+}
diff --git a/chromium/components/live_caption/DEPS b/chromium/components/live_caption/DEPS
new file mode 100644
index 00000000000..c658d2910ff
--- /dev/null
+++ b/chromium/components/live_caption/DEPS
@@ -0,0 +1,14 @@
+include_rules = [
+ "+base",
+ "+build/build_config",
+ "+components/prefs",
+ "+components/strings",
+ "+components/vector_icons",
+ "+third_party/re2",
+ "+ui/accessibility",
+ "+ui/base",
+ "+ui/gfx",
+ "+ui/native_theme",
+ "+ui/strings",
+ "+ui/views",
+]
diff --git a/chromium/components/live_caption/DIR_METADATA b/chromium/components/live_caption/DIR_METADATA
new file mode 100644
index 00000000000..032b6e41a97
--- /dev/null
+++ b/chromium/components/live_caption/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Internals>Media>LiveCaption"
+}
diff --git a/chromium/components/live_caption/OWNERS b/chromium/components/live_caption/OWNERS
new file mode 100644
index 00000000000..a903813952e
--- /dev/null
+++ b/chromium/components/live_caption/OWNERS
@@ -0,0 +1,2 @@
+abigailbklein@google.com
+ellyjones@chromium.org
diff --git a/chromium/components/live_caption/caption_util.cc b/chromium/components/live_caption/caption_util.cc
new file mode 100644
index 00000000000..5bf84959c73
--- /dev/null
+++ b/chromium/components/live_caption/caption_util.cc
@@ -0,0 +1,117 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/live_caption/caption_util.h"
+
+#include <stddef.h>
+
+#include "base/command_line.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "components/live_caption/pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/native_theme/native_theme.h"
+
+namespace {
+
+// Returns whether the style is default or not. If the user has changed any of
+// the captions settings from the default value, that is an interesting metric
+// to observe.
+bool IsDefaultStyle(absl::optional<ui::CaptionStyle> style) {
+ return (style.has_value() && style->text_size.empty() &&
+ style->font_family.empty() && style->text_color.empty() &&
+ style->background_color.empty() && style->text_shadow.empty());
+}
+
+// Adds !important to all captions styles. They should always override any
+// styles added by the video author or by a user stylesheet. This is because in
+// Chrome, there is an option to turn off captions styles, so any time the
+// captions are on, the styles should take priority.
+std::string AddCSSImportant(std::string css_string) {
+ return css_string.empty() ? "" : css_string + " !important";
+}
+
+// Constructs the CaptionStyle struct from the caption-related preferences.
+absl::optional<ui::CaptionStyle> GetCaptionStyleFromPrefs(PrefService* prefs) {
+ if (!prefs) {
+ return absl::nullopt;
+ }
+
+ ui::CaptionStyle style;
+
+ style.text_size =
+ AddCSSImportant(prefs->GetString(prefs::kAccessibilityCaptionsTextSize));
+ style.font_family =
+ AddCSSImportant(prefs->GetString(prefs::kAccessibilityCaptionsTextFont));
+ if (!prefs->GetString(prefs::kAccessibilityCaptionsTextColor).empty()) {
+ std::string text_color = base::StringPrintf(
+ "rgba(%s,%s)",
+ prefs->GetString(prefs::kAccessibilityCaptionsTextColor).c_str(),
+ base::NumberToString(
+ prefs->GetInteger(prefs::kAccessibilityCaptionsTextOpacity) / 100.0)
+ .c_str());
+ style.text_color = AddCSSImportant(text_color);
+ }
+
+ if (!prefs->GetString(prefs::kAccessibilityCaptionsBackgroundColor).empty()) {
+ std::string background_color = base::StringPrintf(
+ "rgba(%s,%s)",
+ prefs->GetString(prefs::kAccessibilityCaptionsBackgroundColor).c_str(),
+ base::NumberToString(
+ prefs->GetInteger(prefs::kAccessibilityCaptionsBackgroundOpacity) /
+ 100.0)
+ .c_str());
+ style.background_color = AddCSSImportant(background_color);
+ }
+
+ style.text_shadow = AddCSSImportant(
+ prefs->GetString(prefs::kAccessibilityCaptionsTextShadow));
+
+ return style;
+}
+
+} // namespace
+
+namespace captions {
+
+absl::optional<ui::CaptionStyle> GetCaptionStyleFromUserSettings(
+ PrefService* prefs,
+ bool record_metrics) {
+ // Apply native CaptionStyle parameters.
+ absl::optional<ui::CaptionStyle> style;
+
+ // Apply native CaptionStyle parameters.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ ::switches::kForceCaptionStyle)) {
+ style = ui::CaptionStyle::FromSpec(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kForceCaptionStyle));
+ }
+
+ // Apply system caption style.
+ if (!style) {
+ ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForWeb();
+ style = native_theme->GetSystemCaptionStyle();
+ if (record_metrics && style.has_value()) {
+ base::UmaHistogramBoolean(
+ "Accessibility.CaptionSettingsLoadedFromSystemSettings",
+ !IsDefaultStyle(style));
+ }
+ }
+
+ // Apply caption style from preferences if system caption style is undefined.
+ if (!style) {
+ style = GetCaptionStyleFromPrefs(prefs);
+ if (record_metrics && style.has_value()) {
+ base::UmaHistogramBoolean("Accessibility.CaptionSettingsLoadedFromPrefs",
+ !IsDefaultStyle(style));
+ }
+ }
+
+ return style;
+}
+
+} // namespace captions
diff --git a/chromium/components/live_caption/caption_util.h b/chromium/components/live_caption/caption_util.h
new file mode 100644
index 00000000000..2534e011fc3
--- /dev/null
+++ b/chromium/components/live_caption/caption_util.h
@@ -0,0 +1,21 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_LIVE_CAPTION_CAPTION_UTIL_H_
+#define COMPONENTS_LIVE_CAPTION_CAPTION_UTIL_H_
+
+#include "components/prefs/pref_service.h"
+#include "ui/native_theme/caption_style.h"
+
+class PrefService;
+
+namespace captions {
+
+absl::optional<ui::CaptionStyle> GetCaptionStyleFromUserSettings(
+ PrefService* prefs,
+ bool record_metrics);
+
+} // namespace captions
+
+#endif // COMPONENTS_LIVE_CAPTION_CAPTION_UTIL_H_
diff --git a/chromium/components/live_caption/pref_names.cc b/chromium/components/live_caption/pref_names.cc
new file mode 100644
index 00000000000..b596aad3e5f
--- /dev/null
+++ b/chromium/components/live_caption/pref_names.cc
@@ -0,0 +1,47 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/live_caption/pref_names.h"
+
+namespace prefs {
+
+#if !defined(ANDROID)
+// Whether the Live Caption feature is enabled.
+const char kLiveCaptionEnabled[] =
+ "accessibility.captions.live_caption_enabled";
+
+// The language to use with the Live Caption feature.
+const char kLiveCaptionLanguageCode[] =
+ "accessibility.captions.live_caption_language";
+#endif // !defined(ANDROID)
+
+// String indicating the size of the captions text as a percentage.
+const char kAccessibilityCaptionsTextSize[] =
+ "accessibility.captions.text_size";
+
+// String indicating the font of the captions text.
+const char kAccessibilityCaptionsTextFont[] =
+ "accessibility.captions.text_font";
+
+// Comma-separated string indicating the RGB values of the captions text color.
+const char kAccessibilityCaptionsTextColor[] =
+ "accessibility.captions.text_color";
+
+// Integer indicating the opacity of the captions text from 0 - 100.
+const char kAccessibilityCaptionsTextOpacity[] =
+ "accessibility.captions.text_opacity";
+
+// Comma-separated string indicating the RGB values of the background color.
+const char kAccessibilityCaptionsBackgroundColor[] =
+ "accessibility.captions.background_color";
+
+// CSS string indicating the shadow of the captions text.
+const char kAccessibilityCaptionsTextShadow[] =
+ "accessibility.captions.text_shadow";
+
+// Integer indicating the opacity of the captions text background from 0 - 100.
+const char kAccessibilityCaptionsBackgroundOpacity[] =
+ "accessibility.captions.background_opacity";
+
+} // namespace prefs
diff --git a/chromium/components/live_caption/pref_names.h b/chromium/components/live_caption/pref_names.h
new file mode 100644
index 00000000000..3f93d11ad4b
--- /dev/null
+++ b/chromium/components/live_caption/pref_names.h
@@ -0,0 +1,30 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_LIVE_CAPTION_PREF_NAMES_H_
+#define COMPONENTS_LIVE_CAPTION_PREF_NAMES_H_
+
+namespace prefs {
+
+// Live Caption is not available on Android, so exclude these unneeded
+// kLiveCaption* prefs.
+#if !defined(ANDROID)
+extern const char kLiveCaptionEnabled[];
+extern const char kLiveCaptionLanguageCode[];
+#endif // !defined(ANDROID)
+
+// These kAccessibilityCaptions* caption style prefs are used on Android
+// (though their primary use is for Live Caption, which is why they are housed
+// within this live_caption component instead of somewhere more generic).
+extern const char kAccessibilityCaptionsTextSize[];
+extern const char kAccessibilityCaptionsTextFont[];
+extern const char kAccessibilityCaptionsTextColor[];
+extern const char kAccessibilityCaptionsTextOpacity[];
+extern const char kAccessibilityCaptionsBackgroundColor[];
+extern const char kAccessibilityCaptionsTextShadow[];
+extern const char kAccessibilityCaptionsBackgroundOpacity[];
+
+} // namespace prefs
+
+#endif // COMPONENTS_LIVE_CAPTION_PREF_NAMES_H_
diff --git a/chromium/components/live_caption/views/caption_bubble.cc b/chromium/components/live_caption/views/caption_bubble.cc
new file mode 100644
index 00000000000..f3b6b3bd891
--- /dev/null
+++ b/chromium/components/live_caption/views/caption_bubble.cc
@@ -0,0 +1,905 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/live_caption/views/caption_bubble.h"
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/time/default_tick_clock.h"
+#include "base/timer/timer.h"
+#include "build/build_config.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/vector_icons/vector_icons.h"
+#include "third_party/re2/src/re2/re2.h"
+#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/buildflags.h"
+#include "ui/base/hit_test.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/vector2d.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/strings/grit/ui_strings.h"
+#include "ui/views/accessibility/view_accessibility.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/image_button_factory.h"
+#include "ui/views/controls/highlight_path_generator.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.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/layout/layout_types.h"
+#include "ui/views/view_class_properties.h"
+#include "ui/views/widget/widget.h"
+
+// The CaptionBubbleLabel needs to be focusable in order for NVDA to enable
+// document navigation. It is suspected that other screen readers on Windows and
+// Linux will need this behavior, too. VoiceOver and ChromeVox do not need the
+// label to be focusable.
+#if BUILDFLAG_INTERNAL_HAS_NATIVE_ACCESSIBILITY() && !defined(OS_MAC)
+#define NEED_FOCUS_FOR_ACCESSIBILITY
+#endif
+
+#if defined(NEED_FOCUS_FOR_ACCESSIBILITY)
+#include "ui/accessibility/platform/ax_platform_node.h"
+#endif
+
+namespace {
+
+// Formatting constants
+static constexpr int kLineHeightDip = 24;
+static constexpr int kNumLinesCollapsed = 2;
+static constexpr int kNumLinesExpanded = 8;
+static constexpr int kCornerRadiusDip = 4;
+static constexpr int kSidePaddingDip = 18;
+static constexpr int kButtonDip = 16;
+static constexpr int kButtonCircleHighlightPaddingDip = 2;
+static constexpr int kMaxWidthDip = 536;
+// Margin of the bubble with respect to the context window.
+static constexpr int kMinAnchorMarginDip = 20;
+static constexpr uint16_t kCaptionBubbleAlpha = 230; // 90% opacity
+static constexpr char kPrimaryFont[] = "Roboto";
+static constexpr char kSecondaryFont[] = "Arial";
+static constexpr char kTertiaryFont[] = "sans-serif";
+static constexpr int kFontSizePx = 16;
+static constexpr double kDefaultRatioInParentX = 0.5;
+static constexpr double kDefaultRatioInParentY = 1;
+static constexpr int kErrorImageSizeDip = 20;
+static constexpr int kErrorMessageBetweenChildSpacingDip = 16;
+static constexpr int kNoActivityIntervalSeconds = 5;
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused. These should be the same as
+// LiveCaptionSessionEvent in enums.xml.
+enum class SessionEvent {
+ // We began showing captions for an audio stream.
+ kStreamStarted = 0,
+ // The audio stream ended and the caption bubble closes.
+ kStreamEnded = 1,
+ // The close button was clicked, so we stopped listening to an audio stream.
+ kCloseButtonClicked = 2,
+ kMaxValue = kCloseButtonClicked,
+};
+
+void LogSessionEvent(SessionEvent event) {
+ base::UmaHistogramEnumeration("Accessibility.LiveCaption.Session", event);
+}
+
+std::unique_ptr<views::ImageButton> BuildImageButton(
+ views::Button::PressedCallback callback,
+ const int tooltip_text_id) {
+ auto button = views::CreateVectorImageButton(std::move(callback));
+ button->SetTooltipText(l10n_util::GetStringUTF16(tooltip_text_id));
+ button->SizeToPreferredSize();
+ views::InstallCircleHighlightPathGenerator(
+ button.get(), gfx::Insets(kButtonCircleHighlightPaddingDip));
+ return button;
+}
+
+// ui::CaptionStyle styles are CSS strings that can sometimes have !important.
+// This method removes " !important" if it exists at the end of a CSS string.
+std::string MaybeRemoveCSSImportant(std::string css_string) {
+ RE2::Replace(&css_string, "\\s+!important", "");
+ return css_string;
+}
+
+// Parses a CSS color string that is in the form rgba and has a non-zero alpha
+// value into an SkColor and sets it to be the value of the passed-in SkColor
+// address. Returns whether or not the operation was a success.
+//
+// `css_string` is the CSS color string passed in. It is in the form
+// rgba(#,#,#,#). r, g, and b are integers between 0 and 255, inclusive.
+// a is a double between 0.0 and 1.0. There may be whitespace in between the
+// commas.
+// `sk_color` is the address of an SKColor. If the operation is a success, the
+// function will set sk_color's value to be the parsed SkColor. If the
+// operation is not a success, sk_color's value will not change.
+//
+// As of spring 2021, all OS's use rgba to define the caption style colors.
+// However, the ui::CaptionStyle spec also allows for the use of any valid CSS
+// color spec. This function will need to be revisited should ui::CaptionStyle
+// colors use non-rgba to define their colors.
+bool ParseNonTransparentRGBACSSColorString(std::string css_string,
+ SkColor* sk_color) {
+ std::string rgba = MaybeRemoveCSSImportant(css_string);
+ if (rgba.empty())
+ return false;
+ uint16_t r, g, b;
+ double a;
+ bool match = RE2::FullMatch(
+ rgba, "rgba\\((\\d+),\\s*(\\d+),\\s*(\\d+),\\s*(\\d+\\.?\\d*)\\)", &r, &g,
+ &b, &a);
+ // If the opacity is set to 0 (fully transparent), we ignore the user's
+ // preferred style and use our default color.
+ if (!match || a == 0)
+ return false;
+ uint16_t a_int = uint16_t{a * 255};
+#if defined(OS_MAC)
+ // On Mac, any opacity lower than 90% leaves rendering artifacts which make
+ // it appear like there is a layer of faint text beneath the actual text.
+ // TODO(crbug.com/1199419): Fix the rendering issue and then remove this
+ // workaround.
+ a_int = std::max(kCaptionBubbleAlpha, a_int);
+#endif
+ *sk_color = SkColorSetARGB(a_int, r, g, b);
+ return match;
+}
+
+} // namespace
+
+namespace captions {
+// CaptionBubble implementation of BubbleFrameView. This class takes care
+// of making the caption draggable.
+class CaptionBubbleFrameView : public views::BubbleFrameView {
+ public:
+ METADATA_HEADER(CaptionBubbleFrameView);
+ explicit CaptionBubbleFrameView(std::vector<views::View*> buttons)
+ : views::BubbleFrameView(gfx::Insets(), gfx::Insets()),
+ buttons_(buttons) {
+ auto border = std::make_unique<views::BubbleBorder>(
+ views::BubbleBorder::FLOAT, views::BubbleBorder::DIALOG_SHADOW,
+ gfx::kPlaceholderColor);
+ border->SetCornerRadius(kCornerRadiusDip);
+ views::BubbleFrameView::SetBubbleBorder(std::move(border));
+ }
+
+ ~CaptionBubbleFrameView() override = default;
+ CaptionBubbleFrameView(const CaptionBubbleFrameView&) = delete;
+ CaptionBubbleFrameView& operator=(const CaptionBubbleFrameView&) = delete;
+
+ // TODO(crbug.com/1055150): This does not work on Linux because the bubble is
+ // not a top-level view, so it doesn't receive events. See crbug.com/1074054
+ // for more about why it doesn't work.
+ int NonClientHitTest(const gfx::Point& point) override {
+ // Outside of the window bounds, do nothing.
+ if (!bounds().Contains(point))
+ return HTNOWHERE;
+
+ // |point| is in coordinates relative to CaptionBubbleFrameView, i.e.
+ // (0,0) is the upper left corner of this view. Convert it to screen
+ // coordinates to see whether one of the buttons contains this point.
+ // If it is, return HTCLIENT, so that the click is sent through to be
+ // handled by CaptionBubble::BubblePressed().
+ gfx::Point point_in_screen =
+ GetBoundsInScreen().origin() + gfx::Vector2d(point.x(), point.y());
+ for (views::View* button : buttons_) {
+ if (button->GetBoundsInScreen().Contains(point_in_screen))
+ return HTCLIENT;
+ }
+
+ // Ensure it's within the BubbleFrameView. This takes into account the
+ // rounded corners and drop shadow of the BubbleBorder.
+ int hit = views::BubbleFrameView::NonClientHitTest(point);
+
+ // After BubbleFrameView::NonClientHitTest processes the bubble-specific
+ // hits such as the rounded corners, it checks hits to the bubble's client
+ // view. Any hits to ClientFrameView::NonClientHitTest return HTCLIENT or
+ // HTNOWHERE. Override these to return HTCAPTION in order to make the
+ // entire widget draggable.
+ return (hit == HTCLIENT || hit == HTNOWHERE) ? HTCAPTION : hit;
+ }
+
+ private:
+ std::vector<views::View*> buttons_;
+};
+
+BEGIN_METADATA(CaptionBubbleFrameView, views::BubbleFrameView)
+END_METADATA
+
+class CaptionBubbleLabelAXModeObserver;
+
+// CaptionBubble implementation of Label. This class takes care of setting up
+// the accessible virtual views of the label in order to support braille
+// accessibility. The CaptionBubbleLabel is a readonly document with a paragraph
+// inside. Inside the paragraph are staticText nodes, one for each visual line
+// in the rendered text of the label. These staticText nodes are shown on a
+// braille display so that a braille user can read the caption text line by
+// line.
+class CaptionBubbleLabel : public views::Label {
+ public:
+ METADATA_HEADER(CaptionBubbleLabel);
+#if defined(NEED_FOCUS_FOR_ACCESSIBILITY)
+ CaptionBubbleLabel() {
+ ax_mode_observer_ =
+ std::make_unique<CaptionBubbleLabelAXModeObserver>(this);
+ SetFocusBehaviorForAccessibility();
+ }
+#else
+ CaptionBubbleLabel() = default;
+#endif
+ ~CaptionBubbleLabel() override = default;
+ CaptionBubbleLabel(const CaptionBubbleLabel&) = delete;
+ CaptionBubbleLabel& operator=(const CaptionBubbleLabel&) = delete;
+
+ void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
+ // Views are not supposed to be documents (see
+ // `ViewAccessibility::IsValidRoleForViews` for more information) but we
+ // make an exception here. The CaptionBubbleLabel is designed to be
+ // interacted with by a braille display in virtual buffer mode. In order to
+ // activate the virtual buffer in NVDA, we set the CaptionBubbleLabel to be
+ // a readonly document.
+ node_data->role = ax::mojom::Role::kDocument;
+ node_data->SetRestriction(ax::mojom::Restriction::kReadOnly);
+#if defined(NEED_FOCUS_FOR_ACCESSIBILITY)
+ // Focusable nodes generally must have a name, but the purpose of focusing
+ // this document is to let the user read the static text nodes inside.
+ node_data->SetNameFrom(ax::mojom::NameFrom::kAttributeExplicitlyEmpty);
+#endif
+ }
+
+ void SetText(const std::u16string& text) override {
+ views::Label::SetText(text);
+
+ auto& ax_lines = GetViewAccessibility().virtual_children();
+ if (text.empty() && !ax_lines.empty()) {
+ GetViewAccessibility().RemoveAllVirtualChildViews();
+ NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, true);
+ return;
+ }
+
+ const size_t num_lines = GetRequiredLines();
+ size_t start = 0;
+ for (size_t i = 0; i < num_lines - 1; ++i) {
+ size_t end = GetTextIndexOfLine(i + 1);
+ std::u16string substring = text.substr(start, end - start);
+ UpdateAXLine(substring, i, gfx::Range(start, end));
+ start = end;
+ }
+ std::u16string substring = text.substr(start, text.size() - start);
+ if (!substring.empty()) {
+ UpdateAXLine(substring, num_lines - 1, gfx::Range(start, text.size()));
+ }
+
+ // Remove all ax_lines that don't have a corresponding line.
+ size_t num_ax_lines = ax_lines.size();
+ for (size_t i = num_lines; i < num_ax_lines; ++i) {
+ GetViewAccessibility().RemoveVirtualChildView(ax_lines.back().get());
+ NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, true);
+ }
+ }
+
+#if defined(NEED_FOCUS_FOR_ACCESSIBILITY)
+ // The CaptionBubbleLabel needs to be focusable in order for NVDA to enable
+ // document navigation. Making the CaptionBubbleLabel focusable means it gets
+ // a tabstop, so it should only be focusable for screen reader users.
+ void SetFocusBehaviorForAccessibility() {
+ if (ui::AXPlatformNode::GetAccessibilityMode().has_mode(
+ ui::AXMode::kScreenReader)) {
+ SetFocusBehavior(FocusBehavior::ALWAYS);
+ } else {
+ SetFocusBehavior(FocusBehavior::NEVER);
+ }
+ }
+#endif
+
+ private:
+ void UpdateAXLine(const std::u16string& line_text,
+ const size_t line_index,
+ const gfx::Range& text_range) {
+ auto& ax_lines = GetViewAccessibility().virtual_children();
+
+ // Add a new virtual child for a new line of text.
+ DCHECK(line_index <= ax_lines.size());
+ if (line_index == ax_lines.size()) {
+ auto ax_line = std::make_unique<views::AXVirtualView>();
+ ax_line->GetCustomData().role = ax::mojom::Role::kStaticText;
+ GetViewAccessibility().AddVirtualChildView(std::move(ax_line));
+ NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, true);
+ }
+
+ // Set the virtual child's name as line text.
+ ui::AXNodeData& ax_node_data = ax_lines[line_index]->GetCustomData();
+ if (base::UTF8ToUTF16(ax_node_data.GetStringAttribute(
+ ax::mojom::StringAttribute::kName)) != line_text) {
+ ax_node_data.SetName(line_text);
+ std::vector<gfx::Rect> bounds = GetSubstringBounds(text_range);
+ ax_node_data.relative_bounds.bounds = gfx::RectF(bounds[0]);
+ ax_lines[line_index]->NotifyAccessibilityEvent(
+ ax::mojom::Event::kTextChanged);
+ }
+ }
+
+#if defined(NEED_FOCUS_FOR_ACCESSIBILITY)
+ std::unique_ptr<CaptionBubbleLabelAXModeObserver> ax_mode_observer_;
+#endif
+};
+
+BEGIN_METADATA(CaptionBubbleLabel, views::Label)
+END_METADATA
+
+#if defined(NEED_FOCUS_FOR_ACCESSIBILITY)
+// A helper class to the CaptionBubbleLabel which observes AXMode changes and
+// updates the CaptionBubbleLabel focus behavior in response.
+// TODO(crbug.com/1191091): Implement a ui::AXModeObserver::OnAXModeRemoved
+// method which observes the removal of AXModes. Without that, the caption
+// bubble label will remain focusable once accessibility is enabled, even if
+// accessibility is later disabled.
+class CaptionBubbleLabelAXModeObserver : public ui::AXModeObserver {
+ public:
+ explicit CaptionBubbleLabelAXModeObserver(CaptionBubbleLabel* owner)
+ : owner_(owner) {
+ ui::AXPlatformNode::AddAXModeObserver(this);
+ }
+
+ ~CaptionBubbleLabelAXModeObserver() override {
+ ui::AXPlatformNode::RemoveAXModeObserver(this);
+ }
+
+ CaptionBubbleLabelAXModeObserver(const CaptionBubbleLabelAXModeObserver&) =
+ delete;
+ CaptionBubbleLabelAXModeObserver& operator=(
+ const CaptionBubbleLabelAXModeObserver&) = delete;
+
+ void OnAXModeAdded(ui::AXMode mode) override {
+ owner_->SetFocusBehaviorForAccessibility();
+ }
+
+ private:
+ CaptionBubbleLabel* owner_;
+};
+#endif
+
+CaptionBubble::CaptionBubble(base::OnceClosure destroyed_callback,
+ bool hide_on_inactivity)
+ : destroyed_callback_(std::move(destroyed_callback)),
+ hide_on_inactivity_(hide_on_inactivity),
+ tick_clock_(base::DefaultTickClock::GetInstance()) {
+ // Bubbles that use transparent colors should not paint their ClientViews to a
+ // layer as doing so could result in visual artifacts.
+ SetPaintClientToLayer(false);
+ SetButtons(ui::DIALOG_BUTTON_NONE);
+ // While not shown, the title is still used to identify the window in the
+ // window switcher.
+ SetShowTitle(false);
+ SetTitle(IDS_LIVE_CAPTION_BUBBLE_TITLE);
+ set_has_parent(false);
+
+ // No need to set up timer if the bubble is not hidden on inactivity.
+ if (!hide_on_inactivity_)
+ return;
+
+ inactivity_timer_ = std::make_unique<base::RetainingOneShotTimer>(
+ FROM_HERE, base::TimeDelta::FromSeconds(kNoActivityIntervalSeconds),
+ base::BindRepeating(&CaptionBubble::OnInactivityTimeout,
+ base::Unretained(this)),
+ tick_clock_);
+ inactivity_timer_->Stop();
+}
+
+CaptionBubble::~CaptionBubble() {
+ if (model_)
+ model_->RemoveObserver();
+}
+
+gfx::Rect CaptionBubble::GetBubbleBounds() {
+ // Bubble bounds are what the computed bubble bounds would be, taking into
+ // account the current bubble size.
+ gfx::Rect bubble_bounds = views::BubbleDialogDelegateView::GetBubbleBounds();
+ // Widget bounds are where the bubble currently is in space.
+ gfx::Rect widget_bounds = GetWidget()->GetWindowBoundsInScreen();
+ // Use the widget x and y to keep the bubble oriented at its current location,
+ // and use the bubble width and height to set the correct bubble size.
+ return gfx::Rect(widget_bounds.x(), widget_bounds.y(), bubble_bounds.width(),
+ bubble_bounds.height());
+}
+
+void CaptionBubble::Init() {
+ SetLayoutManager(std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kVertical))
+ ->set_cross_axis_alignment(
+ views::BoxLayout::CrossAxisAlignment::kStretch);
+ UseCompactMargins();
+ set_close_on_deactivate(false);
+ SetCanActivate(true);
+
+ views::View* header_container = new views::View();
+ header_container
+ ->SetLayoutManager(std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kHorizontal))
+ ->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kEnd);
+
+ views::View* content_container = new views::View();
+ content_container->SetLayoutManager(std::make_unique<views::FlexLayout>())
+ ->SetOrientation(views::LayoutOrientation::kVertical)
+ .SetMainAxisAlignment(views::LayoutAlignment::kEnd)
+ .SetCrossAxisAlignment(views::LayoutAlignment::kStretch)
+ .SetInteriorMargin(gfx::Insets(0, kSidePaddingDip))
+ .SetDefault(
+ views::kFlexBehaviorKey,
+ views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred,
+ views::MaximumFlexSizeRule::kPreferred,
+ /*adjust_height_for_width*/ true));
+
+ auto label = std::make_unique<CaptionBubbleLabel>();
+ label->SetMultiLine(true);
+ label->SetBackgroundColor(SK_ColorTRANSPARENT);
+ label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
+ label->SetVerticalAlignment(gfx::VerticalAlignment::ALIGN_TOP);
+ label->SetTooltipText(std::u16string());
+ // Render text truncates the end of text that is greater than 10000 chars.
+ // While it is unlikely that the text will exceed 10000 chars, it is not
+ // impossible, if the speech service sends a very long transcription_result.
+ // In order to guarantee that the caption bubble displays the last lines, and
+ // in order to ensure that caption_bubble_->GetTextIndexOfLine() is correct,
+ // set the truncate_length to 0 to ensure that it never truncates.
+ label->SetTruncateLength(0);
+
+ auto title = std::make_unique<views::Label>();
+ title->SetBackgroundColor(SK_ColorTRANSPARENT);
+ title->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
+ title->SetText(l10n_util::GetStringUTF16(IDS_LIVE_CAPTION_BUBBLE_TITLE));
+ title->GetViewAccessibility().OverrideIsIgnored(true);
+
+ auto error_text = std::make_unique<views::Label>();
+ error_text->SetBackgroundColor(SK_ColorTRANSPARENT);
+ error_text->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
+ error_text->SetText(l10n_util::GetStringUTF16(IDS_LIVE_CAPTION_BUBBLE_ERROR));
+
+ auto error_icon = std::make_unique<views::ImageView>();
+
+ auto error_message = std::make_unique<views::View>();
+ error_message
+ ->SetLayoutManager(std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
+ kErrorMessageBetweenChildSpacingDip))
+ ->set_cross_axis_alignment(views::BoxLayout::CrossAxisAlignment::kCenter);
+ error_message->SetVisible(false);
+
+ views::Button::PressedCallback expand_or_collapse_callback =
+ base::BindRepeating(&CaptionBubble::ExpandOrCollapseButtonPressed,
+ base::Unretained(this));
+ auto expand_button = BuildImageButton(expand_or_collapse_callback,
+ IDS_LIVE_CAPTION_BUBBLE_EXPAND);
+ expand_button->SetVisible(!is_expanded_);
+
+ auto collapse_button = BuildImageButton(
+ std::move(expand_or_collapse_callback), IDS_LIVE_CAPTION_BUBBLE_COLLAPSE);
+ collapse_button->SetVisible(is_expanded_);
+
+ auto back_to_tab_button = BuildImageButton(
+ base::BindRepeating(&CaptionBubble::BackToTabButtonPressed,
+ base::Unretained(this)),
+ IDS_LIVE_CAPTION_BUBBLE_BACK_TO_TAB);
+ back_to_tab_button->SetVisible(false);
+
+ auto close_button =
+ BuildImageButton(base::BindRepeating(&CaptionBubble::CloseButtonPressed,
+ base::Unretained(this)),
+ IDS_LIVE_CAPTION_BUBBLE_CLOSE);
+
+ back_to_tab_button_ =
+ header_container->AddChildView(std::move(back_to_tab_button));
+ close_button_ = header_container->AddChildView(std::move(close_button));
+
+ title_ = content_container->AddChildView(std::move(title));
+ label_ = content_container->AddChildView(std::move(label));
+
+ error_icon_ = error_message->AddChildView(std::move(error_icon));
+ error_text_ = error_message->AddChildView(std::move(error_text));
+ error_message_ = content_container->AddChildView(std::move(error_message));
+
+ expand_button_ = content_container->AddChildView(std::move(expand_button));
+ collapse_button_ =
+ content_container->AddChildView(std::move(collapse_button));
+
+ AddChildView(std::move(header_container));
+ AddChildView(std::move(content_container));
+
+ SetCaptionBubbleStyle();
+ UpdateContentSize();
+}
+
+void CaptionBubble::OnBeforeBubbleWidgetInit(views::Widget::InitParams* params,
+ views::Widget* widget) const {
+ params->type = views::Widget::InitParams::TYPE_WINDOW;
+ params->z_order = ui::ZOrderLevel::kFloatingWindow;
+ params->visible_on_all_workspaces = true;
+ params->name = "LiveCaptionWindow";
+}
+
+bool CaptionBubble::ShouldShowCloseButton() const {
+ // We draw our own close button so that we can capture the button presses and
+ // so we can customize its appearance.
+ return false;
+}
+
+std::unique_ptr<views::NonClientFrameView>
+CaptionBubble::CreateNonClientFrameView(views::Widget* widget) {
+ std::vector<views::View*> buttons = {back_to_tab_button_, close_button_,
+ expand_button_, collapse_button_};
+ auto frame = std::make_unique<CaptionBubbleFrameView>(buttons);
+ frame_ = frame.get();
+ return frame;
+}
+
+void CaptionBubble::OnWidgetBoundsChanged(views::Widget* widget,
+ const gfx::Rect& new_bounds) {
+ DCHECK_EQ(widget, GetWidget());
+ if (!hide_on_inactivity_)
+ return;
+
+ // If the widget is visible and unfocused, probably due to a mouse drag, reset
+ // the inactivity timer.
+ if (GetWidget()->IsVisible() && !HasFocus())
+ inactivity_timer_->Reset();
+}
+
+void CaptionBubble::OnWidgetActivationChanged(views::Widget* widget,
+ bool active) {
+ DCHECK_EQ(widget, GetWidget());
+ if (!hide_on_inactivity_)
+ return;
+
+ if (active) {
+ inactivity_timer_->Stop();
+ } else {
+ inactivity_timer_->Reset();
+ }
+}
+
+void CaptionBubble::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+ node_data->role = ax::mojom::Role::kDialog;
+ node_data->SetName(title_->GetText());
+}
+
+std::u16string CaptionBubble::GetAccessibleWindowTitle() const {
+ return title_->GetText();
+}
+
+void CaptionBubble::BackToTabButtonPressed() {
+ DCHECK(model_);
+ model_->ActivateContext();
+}
+
+void CaptionBubble::CloseButtonPressed() {
+ LogSessionEvent(SessionEvent::kCloseButtonClicked);
+ if (model_)
+ model_->Close();
+}
+
+void CaptionBubble::ExpandOrCollapseButtonPressed() {
+ is_expanded_ = !is_expanded_;
+ base::UmaHistogramBoolean("Accessibility.LiveCaption.ExpandBubble",
+ is_expanded_);
+ views::Button *old_button = collapse_button_, *new_button = expand_button_;
+ if (is_expanded_)
+ std::swap(old_button, new_button);
+ bool button_had_focus = old_button->HasFocus();
+ OnIsExpandedChanged();
+ // TODO(crbug.com/1055150): Ensure that the button keeps focus on mac.
+ if (button_had_focus)
+ new_button->RequestFocus();
+
+ if (hide_on_inactivity_)
+ inactivity_timer_->Reset();
+}
+
+void CaptionBubble::SetModel(CaptionBubbleModel* model) {
+ if (model_)
+ model_->RemoveObserver();
+ model_ = model;
+ if (model_) {
+ model_->SetObserver(this);
+ back_to_tab_button_->SetVisible(model_->IsContextActivatable());
+ } else {
+ UpdateBubbleVisibility();
+ }
+}
+
+void CaptionBubble::OnTextChanged() {
+ DCHECK(model_);
+ std::string text = model_->GetFullText();
+ label_->SetText(base::UTF8ToUTF16(text));
+ UpdateBubbleAndTitleVisibility();
+
+ if (hide_on_inactivity_ && GetWidget()->IsVisible())
+ inactivity_timer_->Reset();
+}
+
+void CaptionBubble::OnErrorChanged() {
+ DCHECK(model_);
+ bool has_error = model_->HasError();
+ label_->SetVisible(!has_error);
+ error_message_->SetVisible(has_error);
+ expand_button_->SetVisible(!has_error && !is_expanded_);
+ collapse_button_->SetVisible(!has_error && is_expanded_);
+
+ // The error is only 1 line, so redraw the bubble.
+ Redraw();
+}
+
+void CaptionBubble::OnIsExpandedChanged() {
+ expand_button_->SetVisible(!is_expanded_);
+ collapse_button_->SetVisible(is_expanded_);
+
+ // The change of expanded state may cause the title to change visibility, and
+ // it surely causes the content height to change, so redraw the bubble.
+ Redraw();
+}
+
+void CaptionBubble::UpdateBubbleAndTitleVisibility() {
+ // Show the title if there is room for it and no error.
+ title_->SetVisible(model_ && !model_->HasError() &&
+ GetNumLinesInLabel() <
+ static_cast<size_t>(GetNumLinesVisible()));
+ UpdateBubbleVisibility();
+}
+
+void CaptionBubble::UpdateBubbleVisibility() {
+ DCHECK(GetWidget());
+ // If there is no model set, do not show the bubble.
+ if (!model_) {
+ Hide();
+ return;
+ }
+
+ // Hide the widget if the model is closed or the bubble has no activity.
+ // Activity is defined as transcription received from the speech service or
+ // user interacting with the bubble through focus, pressing buttons, or
+ // dragging.
+ if (model_->IsClosed() || !HasActivity()) {
+ Hide();
+ return;
+ }
+
+ // Show the widget if it has text or an error to display.
+ if (!model_->GetFullText().empty() || model_->HasError()) {
+ ShowInactive();
+ return;
+ }
+
+ // No text and no error. Hide it.
+ Hide();
+}
+
+void CaptionBubble::UpdateCaptionStyle(
+ absl::optional<ui::CaptionStyle> caption_style) {
+ caption_style_ = caption_style;
+ SetCaptionBubbleStyle();
+ Redraw();
+}
+
+size_t CaptionBubble::GetTextIndexOfLineInLabel(size_t line) const {
+ return label_->GetTextIndexOfLine(line);
+}
+
+size_t CaptionBubble::GetNumLinesInLabel() const {
+ return label_->GetRequiredLines();
+}
+
+int CaptionBubble::GetNumLinesVisible() {
+ return is_expanded_ ? kNumLinesExpanded : kNumLinesCollapsed;
+}
+
+void CaptionBubble::SetCaptionBubbleStyle() {
+ SetTextSizeAndFontFamily();
+ SetTextColor();
+ SetBackgroundColor();
+}
+
+double CaptionBubble::GetTextScaleFactor() {
+ double textScaleFactor = 1;
+ if (caption_style_) {
+ std::string text_size = MaybeRemoveCSSImportant(caption_style_->text_size);
+ if (!text_size.empty()) {
+ // ui::CaptionStyle states that text_size is percentage as a CSS string.
+ bool match =
+ RE2::FullMatch(text_size, "(\\d+\\.?\\d*)%", &textScaleFactor);
+ textScaleFactor = match ? textScaleFactor / 100 : 1;
+ }
+ }
+ return textScaleFactor;
+}
+
+void CaptionBubble::SetTextSizeAndFontFamily() {
+ double textScaleFactor = GetTextScaleFactor();
+
+ std::vector<std::string> font_names;
+ if (caption_style_) {
+ std::string font_family =
+ MaybeRemoveCSSImportant(caption_style_->font_family);
+ if (!font_family.empty())
+ font_names.push_back(font_family);
+ }
+ font_names.push_back(kPrimaryFont);
+ font_names.push_back(kSecondaryFont);
+ font_names.push_back(kTertiaryFont);
+
+ const gfx::FontList font_list =
+ gfx::FontList(font_names, gfx::Font::FontStyle::NORMAL,
+ kFontSizePx * textScaleFactor, gfx::Font::Weight::NORMAL);
+ label_->SetFontList(font_list);
+ title_->SetFontList(font_list.DeriveWithStyle(gfx::Font::FontStyle::ITALIC));
+ error_text_->SetFontList(font_list);
+
+ label_->SetLineHeight(kLineHeightDip * textScaleFactor);
+ label_->SetMaximumWidth(kMaxWidthDip * textScaleFactor - kSidePaddingDip * 2);
+ title_->SetLineHeight(kLineHeightDip * textScaleFactor);
+ error_text_->SetLineHeight(kLineHeightDip * textScaleFactor);
+ error_icon_->SetImageSize(gfx::Size(kErrorImageSizeDip * textScaleFactor,
+ kErrorImageSizeDip * textScaleFactor));
+}
+
+void CaptionBubble::SetTextColor() {
+ SkColor text_color = SK_ColorWHITE; // The default text color is white.
+ if (caption_style_)
+ ParseNonTransparentRGBACSSColorString(caption_style_->text_color,
+ &text_color);
+ label_->SetEnabledColor(text_color);
+ title_->SetEnabledColor(text_color);
+ error_text_->SetEnabledColor(text_color);
+
+ error_icon_->SetImage(
+ gfx::CreateVectorIcon(vector_icons::kErrorOutlineIcon, text_color));
+ views::SetImageFromVectorIcon(back_to_tab_button_, vector_icons::kLaunchIcon,
+ kButtonDip, text_color);
+ views::SetImageFromVectorIcon(close_button_, vector_icons::kCloseRoundedIcon,
+ kButtonDip, text_color);
+ views::SetImageFromVectorIcon(expand_button_, vector_icons::kCaretDownIcon,
+ kButtonDip, text_color);
+ views::SetImageFromVectorIcon(collapse_button_, vector_icons::kCaretUpIcon,
+ kButtonDip, text_color);
+
+ back_to_tab_button_->ink_drop()->SetBaseColor(text_color);
+ close_button_->ink_drop()->SetBaseColor(text_color);
+ expand_button_->ink_drop()->SetBaseColor(text_color);
+ collapse_button_->ink_drop()->SetBaseColor(text_color);
+}
+
+void CaptionBubble::SetBackgroundColor() {
+ // The default background color is Google Grey 900 with 90% opacity.
+ SkColor background_color =
+ SkColorSetA(gfx::kGoogleGrey900, kCaptionBubbleAlpha);
+ if (caption_style_ && !ParseNonTransparentRGBACSSColorString(
+ caption_style_->window_color, &background_color)) {
+ ParseNonTransparentRGBACSSColorString(caption_style_->background_color,
+ &background_color);
+ }
+ set_color(background_color);
+ OnThemeChanged(); // Need to call `OnThemeChanged` after calling `set_color`.
+}
+
+void CaptionBubble::UpdateContentSize() {
+ double text_scale_factor = GetTextScaleFactor();
+ int width = kMaxWidthDip * text_scale_factor;
+ int content_height =
+ (model_ && model_->HasError())
+ ? kLineHeightDip * text_scale_factor
+ : kLineHeightDip * GetNumLinesVisible() * text_scale_factor;
+ // The title takes up 1 line.
+ int label_height = title_->GetVisible()
+ ? content_height - kLineHeightDip * text_scale_factor
+ : content_height;
+ label_->SetPreferredSize(gfx::Size(width - kSidePaddingDip, label_height));
+ // The header height is the same as the close button height. The footer height
+ // is the same as the expand button height.
+ SetPreferredSize(gfx::Size(
+ width, content_height + close_button_->GetPreferredSize().height() +
+ expand_button_->GetPreferredSize().height()));
+}
+
+void CaptionBubble::Redraw() {
+ UpdateBubbleAndTitleVisibility();
+ UpdateContentSize();
+ SizeToContents();
+}
+
+void CaptionBubble::ShowInactive() {
+ DCHECK(model_);
+ if (GetWidget()->IsVisible())
+ return;
+
+ GetWidget()->ShowInactive();
+ GetViewAccessibility().AnnounceText(l10n_util::GetStringUTF16(
+ IDS_LIVE_CAPTION_BUBBLE_APPEAR_SCREENREADER_ANNOUNCEMENT));
+ LogSessionEvent(SessionEvent::kStreamStarted);
+
+ // If the caption bubble has already been shown, do not reposition it.
+ if (has_been_shown_)
+ return;
+ has_been_shown_ = true;
+
+ // The first time that the caption bubble is shown, place it at the bottom
+ // center of the context widget for the currently set model. We do the
+ // placement at this time to ensure that the caption bubble is positioned
+ // where the user will spot it. If there are multiple browser windows open,
+ // and the user plays media on the second window, the caption bubble will show
+ // up in the bottom center of the second window, which is where the user is
+ // already looking. It also ensures that the caption bubble will appear in the
+ // right workspace if a user has Chrome windows open on multiple workspaces.
+ if (!model_->GetContextBoundsInScreen().has_value())
+ return;
+ gfx::Rect context_rect = model_->GetContextBoundsInScreen().value();
+
+ context_rect.Inset(gfx::Insets(kMinAnchorMarginDip));
+ gfx::Rect bubble_bounds = GetBubbleBounds();
+
+ // The placement is based on the ratio between the center of the widget and
+ // the center of the context_rect.
+ int target_x = context_rect.x() +
+ context_rect.width() * kDefaultRatioInParentX -
+ bubble_bounds.width() / 2.0;
+ int target_y = context_rect.y() +
+ context_rect.height() * kDefaultRatioInParentY -
+ bubble_bounds.height() / 2.0;
+ gfx::Rect target_bounds = gfx::Rect(target_x, target_y, bubble_bounds.width(),
+ bubble_bounds.height());
+ if (!context_rect.Contains(target_bounds)) {
+ target_bounds.AdjustToFit(context_rect);
+ }
+
+ GetWidget()->SetBounds(target_bounds);
+}
+
+void CaptionBubble::Hide() {
+ if (!GetWidget()->IsVisible())
+ return;
+ GetWidget()->Hide();
+ LogSessionEvent(SessionEvent::kStreamEnded);
+}
+
+void CaptionBubble::OnInactivityTimeout() {
+ Hide();
+
+ // Clear the partial and final text in the caption bubble model and the label.
+ // Does not affect the speech service. The speech service will emit a final
+ // result after ~10-15 seconds of no audio which the caption bubble will
+ // receive but will not display. If the speech service is in the middle of a
+ // recognition phrase, and the caption bubble regains activity (such as if the
+ // audio stream restarts), the speech service will emit partial results that
+ // contain text cleared by the UI.
+ if (model_)
+ model_->ClearText();
+}
+
+bool CaptionBubble::HasActivity() {
+ return model_ &&
+ ((inactivity_timer_ && inactivity_timer_->IsRunning()) || HasFocus() ||
+ !model_->GetFullText().empty() || model_->HasError());
+}
+
+views::Label* CaptionBubble::GetLabelForTesting() {
+ return static_cast<views::Label*>(label_);
+}
+
+base::RetainingOneShotTimer* CaptionBubble::GetInactivityTimerForTesting() {
+ return inactivity_timer_.get();
+}
+
+BEGIN_METADATA(CaptionBubble, views::BubbleDialogDelegateView)
+END_METADATA
+
+} // namespace captions
diff --git a/chromium/components/live_caption/views/caption_bubble.h b/chromium/components/live_caption/views/caption_bubble.h
new file mode 100644
index 00000000000..468691b662c
--- /dev/null
+++ b/chromium/components/live_caption/views/caption_bubble.h
@@ -0,0 +1,187 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_LIVE_CAPTION_VIEWS_CAPTION_BUBBLE_H_
+#define COMPONENTS_LIVE_CAPTION_VIEWS_CAPTION_BUBBLE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback_helpers.h"
+#include "components/live_caption/views/caption_bubble_model.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/native_theme/caption_style.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/metadata/view_factory.h"
+
+namespace base {
+class RetainingOneShotTimer;
+class TickClock;
+}
+
+namespace views {
+class ImageButton;
+class ImageView;
+class Label;
+} // namespace views
+
+namespace ui {
+struct AXNodeData;
+}
+
+namespace captions {
+class CaptionBubbleFrameView;
+class CaptionBubbleLabel;
+
+///////////////////////////////////////////////////////////////////////////////
+// Caption Bubble
+//
+// A caption bubble that floats above all other windows and shows
+// automatically- generated text captions for audio and media streams. The
+// captions bubble's widget is a top-level window that has top z order and is
+// visible on all workspaces. It is draggable in and out of the tab.
+//
+class CaptionBubble : public views::BubbleDialogDelegateView {
+ public:
+ METADATA_HEADER(CaptionBubble);
+ CaptionBubble(base::OnceClosure destroyed_callback, bool hide_on_inactivity);
+ CaptionBubble(const CaptionBubble&) = delete;
+ CaptionBubble& operator=(const CaptionBubble&) = delete;
+ ~CaptionBubble() override;
+
+ // Sets the caption bubble model currently being used for this caption bubble.
+ // There exists one CaptionBubble per profile, but one CaptionBubbleModel per
+ // media stream. A new CaptionBubbleModel is set when transcriptions from a
+ // different media stream are received. A CaptionBubbleModel is owned by the
+ // CaptionBubbleControllerViews. It is created when transcriptions from a new
+ // media stream are received and exists until the audio stream ends for that
+ // stream.
+ void SetModel(CaptionBubbleModel* model);
+
+ // Changes the caption style of the caption bubble.
+ void UpdateCaptionStyle(absl::optional<ui::CaptionStyle> caption_style);
+
+ // Returns whether the bubble has activity. Activity is defined as
+ // transcription received from the speech service or user interacting with the
+ // bubble through focus, pressing buttons, or dragging.
+ bool HasActivity();
+
+ views::Label* GetLabelForTesting();
+ base::RetainingOneShotTimer* GetInactivityTimerForTesting();
+ void set_tick_clock_for_testing(const base::TickClock* tick_clock) {
+ tick_clock_ = tick_clock;
+ }
+
+ protected:
+ // views::BubbleDialogDelegateView:
+ void Init() override;
+ void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params,
+ views::Widget* widget) const override;
+ bool ShouldShowCloseButton() const override;
+ std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
+ views::Widget* widget) override;
+ gfx::Rect GetBubbleBounds() override;
+ void OnWidgetBoundsChanged(views::Widget* widget,
+ const gfx::Rect& new_bounds) override;
+ void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
+ void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+ std::u16string GetAccessibleWindowTitle() const override;
+
+ private:
+ friend class CaptionBubbleControllerViewsTest;
+ friend class CaptionBubbleModel;
+
+ void BackToTabButtonPressed();
+ void CloseButtonPressed();
+ void ExpandOrCollapseButtonPressed();
+
+ // Called by CaptionBubbleModel to notify this object that the model's text
+ // has changed. Sets the text of the caption bubble to the model's text.
+ void OnTextChanged();
+
+ // Called by CaptionBubbleModel to notify this object that the model's error
+ // state has changed. Makes the caption bubble display an error message if
+ // the model has an error, otherwise displays the latest text.
+ void OnErrorChanged();
+
+ // Called when the caption bubble expanded state has changed. Changes the
+ // number of lines displayed.
+ void OnIsExpandedChanged();
+
+ // The caption bubble manages its own visibility based on whether there's
+ // space for it to be shown, and if it has an error or text to display.
+ void UpdateBubbleVisibility();
+ void UpdateBubbleAndTitleVisibility();
+
+ // For the provided line index, gets the corresponding rendered line in the
+ // label and returns the text position of the first character of that line.
+ // Returns the same value regardless of whether the label is visible or not.
+ // TODO(crbug.com/1055150): This feature is launching for English first.
+ // Make sure this is correct for all languages.
+ size_t GetTextIndexOfLineInLabel(size_t line) const;
+
+ // Returns the number of lines in the caption bubble label that are rendered.
+ size_t GetNumLinesInLabel() const;
+ int GetNumLinesVisible();
+ void UpdateContentSize();
+ void Redraw();
+ void ShowInactive();
+ void Hide();
+
+ // The following methods set the caption bubble style based on the user's
+ // preferences, which are stored in `caption_style_`.
+ void SetCaptionBubbleStyle();
+ double GetTextScaleFactor();
+ void SetTextSizeAndFontFamily();
+ void SetTextColor();
+ void SetBackgroundColor();
+
+ // After 5 seconds of inactivity, hide the caption bubble. Activity is defined
+ // as transcription received from the speech service or user interacting with
+ // the bubble through focus, pressing buttons, or dragging.
+ void OnInactivityTimeout();
+
+ // Unowned. Owned by views hierarchy.
+ CaptionBubbleLabel* label_;
+ views::Label* title_;
+ views::Label* error_text_;
+ views::ImageView* error_icon_;
+ views::View* error_message_;
+ views::ImageButton* back_to_tab_button_;
+ views::ImageButton* close_button_;
+ views::ImageButton* expand_button_;
+ views::ImageButton* collapse_button_;
+ CaptionBubbleFrameView* frame_;
+
+ absl::optional<ui::CaptionStyle> caption_style_;
+ CaptionBubbleModel* model_ = nullptr;
+
+ base::ScopedClosureRunner destroyed_callback_;
+
+ // Whether the caption bubble is expanded to show more lines of text.
+ bool is_expanded_ = false;
+
+ bool has_been_shown_ = false;
+
+ // Whether we should hide the caption bubble on inactivity.
+ bool const hide_on_inactivity_;
+
+ // A timer which causes the bubble to hide if there is no activity after a
+ // specified interval.
+ std::unique_ptr<base::RetainingOneShotTimer> inactivity_timer_;
+ const base::TickClock* tick_clock_;
+};
+
+BEGIN_VIEW_BUILDER(/* no export */,
+ CaptionBubble,
+ views::BubbleDialogDelegateView)
+END_VIEW_BUILDER
+
+} // namespace captions
+
+DEFINE_VIEW_BUILDER(/* no export */, captions::CaptionBubble)
+
+#endif // COMPONENTS_LIVE_CAPTION_VIEWS_CAPTION_BUBBLE_H_
diff --git a/chromium/components/live_caption/views/caption_bubble_model.cc b/chromium/components/live_caption/views/caption_bubble_model.cc
new file mode 100644
index 00000000000..680d8058bdb
--- /dev/null
+++ b/chromium/components/live_caption/views/caption_bubble_model.cc
@@ -0,0 +1,117 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/live_caption/views/caption_bubble_model.h"
+
+#include "components/live_caption/views/caption_bubble.h"
+
+namespace {
+// The caption bubble contains 2 lines of text in its normal size and 8 lines
+// in its expanded size, so the maximum number of lines before truncating is 9.
+constexpr int kMaxLines = 9;
+} // namespace
+
+namespace captions {
+
+CaptionBubbleModel::CaptionBubbleModel(
+ const absl::optional<gfx::Rect>& context_bounds_in_screen,
+ base::RepeatingClosure activate_context_callback)
+ : context_bounds_in_screen_(context_bounds_in_screen),
+ activate_context_callback_(activate_context_callback) {}
+
+CaptionBubbleModel::~CaptionBubbleModel() {
+ if (observer_)
+ observer_->SetModel(nullptr);
+}
+
+void CaptionBubbleModel::SetObserver(CaptionBubble* observer) {
+ if (observer_)
+ return;
+ observer_ = observer;
+ if (observer_) {
+ observer_->OnTextChanged();
+ observer_->OnErrorChanged();
+ }
+}
+
+void CaptionBubbleModel::RemoveObserver() {
+ observer_ = nullptr;
+}
+
+void CaptionBubbleModel::OnTextChanged() {
+ if (observer_)
+ observer_->OnTextChanged();
+}
+
+void CaptionBubbleModel::SetPartialText(const std::string& partial_text) {
+ partial_text_ = partial_text;
+ OnTextChanged();
+ if (has_error_) {
+ has_error_ = false;
+ if (observer_)
+ observer_->OnErrorChanged();
+ }
+}
+
+void CaptionBubbleModel::Close() {
+ is_closed_ = true;
+ ClearText();
+}
+
+void CaptionBubbleModel::Open() {
+ is_closed_ = false;
+ OnTextChanged();
+}
+
+void CaptionBubbleModel::OnError() {
+ has_error_ = true;
+ if (observer_)
+ observer_->OnErrorChanged();
+}
+
+void CaptionBubbleModel::ClearText() {
+ partial_text_.clear();
+ final_text_.clear();
+ OnTextChanged();
+}
+
+void CaptionBubbleModel::CommitPartialText() {
+ final_text_ += partial_text_;
+
+ // If the first character of partial text isn't a space, add a space before
+ // appending it to final text. There is no need to alert the observer because
+ // the text itself has not changed, just its representation, and there is no
+ // need to render a trailing space.
+ // TODO(crbug.com/1055150): This feature is launching for English first.
+ // Make sure spacing is correct for all languages.
+ if (partial_text_.size() > 0 &&
+ partial_text_.compare(partial_text_.size() - 1, 1, " ") != 0) {
+ final_text_ += " ";
+ }
+ partial_text_.clear();
+
+ if (!observer_)
+ return;
+
+ // Truncate the final text to kMaxLines lines long. This time, alert the
+ // observer that the text has changed.
+ const size_t num_lines = observer_->GetNumLinesInLabel();
+ if (num_lines > kMaxLines) {
+ const size_t truncate_index =
+ observer_->GetTextIndexOfLineInLabel(num_lines - kMaxLines);
+ final_text_.erase(0, truncate_index);
+ OnTextChanged();
+ }
+}
+
+bool CaptionBubbleModel::IsContextActivatable() {
+ return activate_context_callback_ != base::NullCallback();
+}
+
+void CaptionBubbleModel::ActivateContext() {
+ DCHECK(IsContextActivatable());
+ activate_context_callback_.Run();
+}
+
+} // namespace captions
diff --git a/chromium/components/live_caption/views/caption_bubble_model.h b/chromium/components/live_caption/views/caption_bubble_model.h
new file mode 100644
index 00000000000..1c920077e89
--- /dev/null
+++ b/chromium/components/live_caption/views/caption_bubble_model.h
@@ -0,0 +1,113 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_LIVE_CAPTION_VIEWS_CAPTION_BUBBLE_MODEL_H_
+#define COMPONENTS_LIVE_CAPTION_VIEWS_CAPTION_BUBBLE_MODEL_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace captions {
+
+class CaptionBubble;
+
+///////////////////////////////////////////////////////////////////////////////
+// Caption Bubble Model
+//
+// A representation of the data a caption bubble needs for a particular media
+// stream. The caption bubble controller sets the value of the text. The
+// caption bubble observes the model, and when the values change, the observer
+// is alerted.
+//
+// There exists one CaptionBubble and one CaptionBubbleControllerViews per
+// profile, but one CaptionBubbleModel per media stream. The CaptionBubbleModel
+// is owned by the CaptionBubbleControllerViews. It is created when
+// transcriptions from a new media stream are received and exists until the
+// audio stream ends for that stream.
+//
+// Partial text is a speech result that is subject to change. Incoming partial
+// texts overlap with the previous partial text.
+// Final text is the final transcription from the speech service that no
+// longer changes. Incoming partial texts do not overlap with final text.
+// When a final result is received from the speech service, the partial text is
+// appended to the end of the final text. The caption bubble displays the full
+// final + partial text.
+//
+class CaptionBubbleModel {
+ public:
+ CaptionBubbleModel(const absl::optional<gfx::Rect>& context_bounds_in_screen,
+ base::RepeatingClosure activate_context_callback);
+ ~CaptionBubbleModel();
+ CaptionBubbleModel(const CaptionBubbleModel&) = delete;
+ CaptionBubbleModel& operator=(const CaptionBubbleModel&) = delete;
+
+ void SetObserver(CaptionBubble* observer);
+ void RemoveObserver();
+
+ // Set the partial text and alert the observer.
+ void SetPartialText(const std::string& partial_text);
+
+ // Commits the partial text as final text.
+ void CommitPartialText();
+
+ // Set that the bubble has an error and alert the observer.
+ void OnError();
+
+ // Mark the bubble as closed, clear the partial and final text, and alert the
+ // observer.
+ void Close();
+
+ // Marks the bubble as open.
+ void Open();
+
+ // Clears the partial and final text and alerts the observer.
+ void ClearText();
+
+ // Calls the activate context callback.
+ void ActivateContext();
+
+ // Returns whether there is an activate context callback available.
+ bool IsContextActivatable();
+
+ bool IsClosed() const { return is_closed_; }
+ bool HasError() const { return has_error_; }
+ std::string GetFullText() const { return final_text_ + partial_text_; }
+ const absl::optional<gfx::Rect>& GetContextBoundsInScreen() const {
+ return context_bounds_in_screen_;
+ }
+
+ private:
+ // Alert the observer that a change has occurred to the model text.
+ void OnTextChanged();
+
+ std::string final_text_;
+ std::string partial_text_;
+
+ // Whether the bubble has been closed by the user.
+ bool is_closed_ = false;
+
+ // Whether an error should be displayed one the bubble.
+ bool has_error_ = false;
+
+ // The bounds of the context widget. On Chrome browser, this is the bounds in
+ // screen of the top level widget of the browser window. When Live Caption is
+ // implemented in ash, this will be bounds of the top level widget of the ash
+ // window.
+ const absl::optional<gfx::Rect> context_bounds_in_screen_;
+
+ // A callback which activates the context for this CaptionBubbleModel. In
+ // Live Caption on browser, this activates the browser window and tab of the
+ // web contents to which this CaptionBubbleModel belongs.
+ const base::RepeatingClosure activate_context_callback_;
+
+ // The CaptionBubble observing changes to this model.
+ CaptionBubble* observer_ = nullptr;
+};
+
+} // namespace captions
+
+#endif // COMPONENTS_LIVE_CAPTION_VIEWS_CAPTION_BUBBLE_MODEL_H_
diff --git a/chromium/components/live_caption_strings.grdp b/chromium/components/live_caption_strings.grdp
new file mode 100644
index 00000000000..f9a2e41411e
--- /dev/null
+++ b/chromium/components/live_caption_strings.grdp
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <!-- Live caption. -->
+ <message name="IDS_LIVE_CAPTION_BUBBLE_TITLE" desc="Title of the Live Caption bubble">
+ Live Caption
+ </message>
+ <message name="IDS_LIVE_CAPTION_BUBBLE_CLOSE" desc="Tooltip for the Live Caption close button">
+ Turn off Live Caption for now
+ </message>
+ <message name="IDS_LIVE_CAPTION_BUBBLE_EXPAND" desc="Tooltip for the Live Caption expand button">
+ Show more lines
+ </message>
+ <message name="IDS_LIVE_CAPTION_BUBBLE_COLLAPSE" desc="Tooltip for the Live Caption collapse button">
+ Show fewer lines
+ </message>
+ <message name="IDS_LIVE_CAPTION_BUBBLE_BACK_TO_TAB" desc="Tooltip for the Live Caption back-to-tab button. Clicking the button brings a user's focus back to the tab which is streaming the audio or video.">
+ Back to tab
+ </message>
+ <message name="IDS_LIVE_CAPTION_BUBBLE_ERROR" desc="Error message for the Live Caption bubble when Live Captions are unavailable.">
+ Live Caption is not available right now
+ </message>
+ <message name="IDS_LIVE_CAPTION_BUBBLE_APPEAR_SCREENREADER_ANNOUNCEMENT" desc="Announcement to screen readers on ChromeOS when the Live Caption bubble appears to inform users of how to focus the bubble.">
+ Live Caption visible, use window switcher to focus
+ </message>
+</grit-part>
diff --git a/chromium/components/live_caption_strings_grdp/DIR_METADATA b/chromium/components/live_caption_strings_grdp/DIR_METADATA
new file mode 100644
index 00000000000..032b6e41a97
--- /dev/null
+++ b/chromium/components/live_caption_strings_grdp/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Internals>Media>LiveCaption"
+}
diff --git a/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_APPEAR_SCREENREADER_ANNOUNCEMENT.png.sha1 b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_APPEAR_SCREENREADER_ANNOUNCEMENT.png.sha1
new file mode 100644
index 00000000000..1c84b613514
--- /dev/null
+++ b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_APPEAR_SCREENREADER_ANNOUNCEMENT.png.sha1
@@ -0,0 +1 @@
+8e07dd0fc6181d75c48d503cf6e52977f2f05747 \ No newline at end of file
diff --git a/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_BACK_TO_TAB.png.sha1 b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_BACK_TO_TAB.png.sha1
new file mode 100644
index 00000000000..a5e4dc02948
--- /dev/null
+++ b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_BACK_TO_TAB.png.sha1
@@ -0,0 +1 @@
+93b94add9a63a63c7ba6bf0dc4f12fc1cf67493c \ No newline at end of file
diff --git a/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_CLOSE.png.sha1 b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_CLOSE.png.sha1
new file mode 100644
index 00000000000..47c683cf21b
--- /dev/null
+++ b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_CLOSE.png.sha1
@@ -0,0 +1 @@
+b268a27f9e1ebfd1680adbdf444f89ffefd7012e \ No newline at end of file
diff --git a/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_COLLAPSE.png.sha1 b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_COLLAPSE.png.sha1
new file mode 100644
index 00000000000..49cd9e2e0ec
--- /dev/null
+++ b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_COLLAPSE.png.sha1
@@ -0,0 +1 @@
+b3499faf1b0acf057a63549e44acdbb58e2e5c6c \ No newline at end of file
diff --git a/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_ERROR.png.sha1 b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_ERROR.png.sha1
new file mode 100644
index 00000000000..0ed93e3bb04
--- /dev/null
+++ b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_ERROR.png.sha1
@@ -0,0 +1 @@
+2ca55db3d7bd3bdd497a9bef2545b28424d98b86 \ No newline at end of file
diff --git a/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_EXPAND.png.sha1 b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_EXPAND.png.sha1
new file mode 100644
index 00000000000..88efdf1599b
--- /dev/null
+++ b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_EXPAND.png.sha1
@@ -0,0 +1 @@
+840b5967d1609a82282fca7e4240361ca3e10030 \ No newline at end of file
diff --git a/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_TITLE.png.sha1 b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_TITLE.png.sha1
new file mode 100644
index 00000000000..cb4e21dd342
--- /dev/null
+++ b/chromium/components/live_caption_strings_grdp/IDS_LIVE_CAPTION_BUBBLE_TITLE.png.sha1
@@ -0,0 +1 @@
+1feaf983c48f99f60c7b6b29339b553ecaf5f424 \ No newline at end of file
diff --git a/chromium/components/live_caption_strings_grdp/OWNERS b/chromium/components/live_caption_strings_grdp/OWNERS
new file mode 100644
index 00000000000..1a11b9978fd
--- /dev/null
+++ b/chromium/components/live_caption_strings_grdp/OWNERS
@@ -0,0 +1 @@
+file://components/live_caption/OWNERS
diff --git a/chromium/components/live_caption_strings_grdp/README.md b/chromium/components/live_caption_strings_grdp/README.md
new file mode 100644
index 00000000000..119d8b9bff7
--- /dev/null
+++ b/chromium/components/live_caption_strings_grdp/README.md
@@ -0,0 +1,5 @@
+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/location/android/location_settings_dialog_context.h b/chromium/components/location/android/location_settings_dialog_context.h
index 3b4ae42addd..564be66e357 100644
--- a/chromium/components/location/android/location_settings_dialog_context.h
+++ b/chromium/components/location/android/location_settings_dialog_context.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_LOCATION_LOCATION_SETTINGS_DIALOG_CONTEXT_H_
-#define COMPONENTS_LOCATION_LOCATION_SETTINGS_DIALOG_CONTEXT_H_
+#ifndef COMPONENTS_LOCATION_ANDROID_LOCATION_SETTINGS_DIALOG_CONTEXT_H_
+#define COMPONENTS_LOCATION_ANDROID_LOCATION_SETTINGS_DIALOG_CONTEXT_H_
// An enum to describe the context in which a system location setting prompt
// is triggered to allow the prompt UI to be customized to the given context.
@@ -15,4 +15,4 @@ enum LocationSettingsDialogContext {
SEARCH = 2,
};
-#endif // COMPONENTS_LOCATION_LOCATION_SETTINGS_DIALOG_CONTEXT_H_
+#endif // COMPONENTS_LOCATION_ANDROID_LOCATION_SETTINGS_DIALOG_CONTEXT_H_
diff --git a/chromium/components/location/android/location_settings_dialog_outcome.h b/chromium/components/location/android/location_settings_dialog_outcome.h
index b5924c2a065..a0ae32103bc 100644
--- a/chromium/components/location/android/location_settings_dialog_outcome.h
+++ b/chromium/components/location/android/location_settings_dialog_outcome.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_LOCATION_LOCATION_SETTINGS_DIALOG_OUTCOME_H_
-#define COMPONENTS_LOCATION_LOCATION_SETTINGS_DIALOG_OUTCOME_H_
+#ifndef COMPONENTS_LOCATION_ANDROID_LOCATION_SETTINGS_DIALOG_OUTCOME_H_
+#define COMPONENTS_LOCATION_ANDROID_LOCATION_SETTINGS_DIALOG_OUTCOME_H_
// An enum to describe the outcome of a system location setting prompt.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.location
@@ -27,4 +27,4 @@ enum LocationSettingsDialogOutcome {
NO_PROMPT = 3,
};
-#endif // COMPONENTS_LOCATION_LOCATION_SETTINGS_DIALOG_OUTCOME_H_
+#endif // COMPONENTS_LOCATION_ANDROID_LOCATION_SETTINGS_DIALOG_OUTCOME_H_
diff --git a/chromium/components/location/android/location_settings_impl.h b/chromium/components/location/android/location_settings_impl.h
index c967566c114..bc85b03e1cd 100644
--- a/chromium/components/location/android/location_settings_impl.h
+++ b/chromium/components/location/android/location_settings_impl.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_LOCATION_ANDROID_LOCATION_SETTINGS_IMPL_H_
#define COMPONENTS_LOCATION_ANDROID_LOCATION_SETTINGS_IMPL_H_
-#include <memory>
-
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
diff --git a/chromium/components/login/base_screen_handler_utils.cc b/chromium/components/login/base_screen_handler_utils.cc
index d21bcbeba44..da5d94c1325 100644
--- a/chromium/components/login/base_screen_handler_utils.cc
+++ b/chromium/components/login/base_screen_handler_utils.cc
@@ -30,7 +30,11 @@ bool ParseValue(const base::Value* value, bool* out_value) {
}
bool ParseValue(const base::Value* value, int* out_value) {
- return value->GetAsInteger(out_value);
+ if (out_value && value->is_int()) {
+ *out_value = value->GetInt();
+ return true;
+ }
+ return value->is_int();
}
bool ParseValue(const base::Value* value, double* out_value) {
diff --git a/chromium/components/login/base_screen_handler_utils.h b/chromium/components/login/base_screen_handler_utils.h
index 6f4d0195691..4f38955a036 100644
--- a/chromium/components/login/base_screen_handler_utils.h
+++ b/chromium/components/login/base_screen_handler_utils.h
@@ -7,7 +7,6 @@
#include <stddef.h>
-#include <cstddef>
#include <string>
#include <utility>
diff --git a/chromium/components/login/secure_module_util_chromeos.h b/chromium/components/login/secure_module_util_chromeos.h
index 424e2bb412f..f1487b09d33 100644
--- a/chromium/components/login/secure_module_util_chromeos.h
+++ b/chromium/components/login/secure_module_util_chromeos.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_LOGIN_SECURE_MODULE_UTIL_H_
-#define COMPONENTS_LOGIN_SECURE_MODULE_UTIL_H_
+#ifndef COMPONENTS_LOGIN_SECURE_MODULE_UTIL_CHROMEOS_H_
+#define COMPONENTS_LOGIN_SECURE_MODULE_UTIL_CHROMEOS_H_
#include "base/callback.h"
#include "components/login/login_export.h"
@@ -26,4 +26,4 @@ void LOGIN_EXPORT GetSecureModuleUsed(GetSecureModuleUsedCallback callback);
} // namespace login
-#endif // COMPONENTS_LOGIN_SECURE_MODULE_UTIL_H_
+#endif // COMPONENTS_LOGIN_SECURE_MODULE_UTIL_CHROMEOS_H_
diff --git a/chromium/components/lookalikes/core/BUILD.gn b/chromium/components/lookalikes/core/BUILD.gn
index fccb48046c8..c46ad6f7e1d 100644
--- a/chromium/components/lookalikes/core/BUILD.gn
+++ b/chromium/components/lookalikes/core/BUILD.gn
@@ -14,6 +14,8 @@ static_library("core") {
"//base",
"//components/pref_registry",
"//components/prefs:prefs",
+ "//components/reputation/core:core",
+ "//components/reputation/core:proto",
"//components/security_interstitials/core",
"//components/security_state/core:features",
"//components/strings",
@@ -36,6 +38,7 @@ source_set("unit_tests") {
deps = [
":core",
":features",
+ "//components/reputation/core",
"//net:test_support",
"//testing/gtest",
]
diff --git a/chromium/components/lookalikes/core/DEPS b/chromium/components/lookalikes/core/DEPS
index a3c048b885f..33c4e659341 100644
--- a/chromium/components/lookalikes/core/DEPS
+++ b/chromium/components/lookalikes/core/DEPS
@@ -3,4 +3,6 @@ include_rules = [
# should not be introduced.
"-content",
"-ios/web",
+ # components/reputation contains the lookalike (safety tips) component.
+ "+components/reputation/core",
]
diff --git a/chromium/components/lookalikes/core/features.cc b/chromium/components/lookalikes/core/features.cc
index 3eb15692239..3d1fb0c01c4 100644
--- a/chromium/components/lookalikes/core/features.cc
+++ b/chromium/components/lookalikes/core/features.cc
@@ -9,7 +9,7 @@ namespace features {
// Note: this flag is ignored on iOS. See lookalike_url_util.cc.
const base::Feature kDetectTargetEmbeddingLookalikes{
- "TargetEmbeddingLookalikes", base::FEATURE_DISABLED_BY_DEFAULT};
+ "TargetEmbeddingLookalikes", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kLookalikeInterstitialForPunycode{
"LookalikeInterstitialForPunycode", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chromium/components/lookalikes/core/lookalike_url_util.cc b/chromium/components/lookalikes/core/lookalike_url_util.cc
index 7677aa9660f..a3e5695061d 100644
--- a/chromium/components/lookalikes/core/lookalike_url_util.cc
+++ b/chromium/components/lookalikes/core/lookalike_url_util.cc
@@ -27,6 +27,7 @@
#include "base/values.h"
#include "build/build_config.h"
#include "components/lookalikes/core/features.h"
+#include "components/reputation/core/safety_tips_config.h"
#include "components/security_interstitials/core/pref_names.h"
#include "components/security_state/core/features.h"
#include "components/url_formatter/spoof_checks/common_words/common_words_util.h"
@@ -212,13 +213,12 @@ bool ASubdomainIsAllowlisted(
const base::span<const base::StringPiece>& domain_labels,
const LookalikeTargetAllowlistChecker& in_target_allowlist) {
DCHECK(domain_labels.size() >= 2);
- std::string potential_hostname =
- domain_labels[domain_labels.size() - 1].as_string();
+ std::string potential_hostname(domain_labels[domain_labels.size() - 1]);
// Attach each token from the end to the embedded target to check if that
// subdomain has been allowlisted.
for (int i = domain_labels.size() - 2; i >= 0; i--) {
potential_hostname =
- domain_labels[i].as_string() + "." + potential_hostname;
+ std::string(domain_labels[i]) + "." + potential_hostname;
if (in_target_allowlist.Run(potential_hostname)) {
return true;
}
@@ -286,7 +286,8 @@ bool DoesETLDPlus1MatchTopDomainOrEngagedSite(
// Returns whether the e2LD of the provided domain is a common word (e.g.
// weather.com, ask.com). Target embeddings of these domains are often false
// positives (e.g. "super-best-fancy-hotels.com" isn't spoofing "hotels.com").
-bool UsesCommonWord(const DomainInfo& domain) {
+bool UsesCommonWord(const reputation::SafetyTipsConfig* config_proto,
+ const DomainInfo& domain) {
// kDomainsPermittedInEndEmbeddings are based on domains with common words,
// but they should not be excluded here (and instead are checked later).
for (auto* permitted_ending : kDomainsPermittedInEndEmbeddings) {
@@ -301,7 +302,13 @@ bool UsesCommonWord(const DomainInfo& domain) {
return true;
}
- // Also check the local lists.
+ // Search for words in the component-provided word list.
+ if (reputation::IsCommonWordInConfigProto(config_proto,
+ domain.domain_without_registry)) {
+ return true;
+ }
+
+ // Search for words in the local word lists.
for (auto* common_word : kLocalAdditionalCommonWords) {
if (domain.domain_without_registry == common_word) {
return true;
@@ -323,14 +330,13 @@ bool UsesCommonWord(const DomainInfo& domain) {
bool IsEmbeddingItself(const base::span<const base::StringPiece>& domain_labels,
const std::string& embedding_domain) {
DCHECK(domain_labels.size() >= 2);
- std::string potential_hostname =
- domain_labels[domain_labels.size() - 1].as_string();
+ std::string potential_hostname(domain_labels[domain_labels.size() - 1]);
// Attach each token from the end to the embedded target to check if that
// subdomain is the embedding domain. (e.g. using the earlier example, check
// each ["com", "example.com", "foo.example.com"] against "example.com".
for (int i = domain_labels.size() - 2; i >= 0; i--) {
potential_hostname =
- domain_labels[i].as_string() + "." + potential_hostname;
+ std::string(domain_labels[i]) + "." + potential_hostname;
if (embedding_domain == potential_hostname) {
return true;
}
@@ -371,8 +377,9 @@ bool IsAllowedToBeEmbedded(
const DomainInfo& embedded_target,
const base::span<const base::StringPiece>& subdomain_span,
const LookalikeTargetAllowlistChecker& in_target_allowlist,
- const std::string& embedding_domain) {
- return UsesCommonWord(embedded_target) ||
+ const std::string& embedding_domain,
+ const reputation::SafetyTipsConfig* config_proto) {
+ return UsesCommonWord(config_proto, embedded_target) ||
ASubdomainIsAllowlisted(subdomain_span, in_target_allowlist) ||
IsEmbeddingItself(subdomain_span, embedding_domain) ||
IsCrossTLDMatch(embedded_target, embedding_domain) ||
@@ -616,6 +623,7 @@ bool GetMatchingDomain(
const DomainInfo& navigated_domain,
const std::vector<DomainInfo>& engaged_sites,
const LookalikeTargetAllowlistChecker& in_target_allowlist,
+ const reputation::SafetyTipsConfig* config_proto,
std::string* matched_domain,
LookalikeUrlMatchType* match_type) {
DCHECK(!navigated_domain.domain_and_registry.empty());
@@ -676,7 +684,7 @@ bool GetMatchingDomain(
TargetEmbeddingType embedding_type =
GetTargetEmbeddingType(navigated_domain.hostname, engaged_sites,
- in_target_allowlist, matched_domain);
+ in_target_allowlist, config_proto, matched_domain);
if (embedding_type == TargetEmbeddingType::kSafetyTip) {
*match_type = LookalikeUrlMatchType::kTargetEmbeddingForSafetyTips;
return true;
@@ -725,6 +733,37 @@ TargetEmbeddingType GetTargetEmbeddingType(
const std::string& hostname,
const std::vector<DomainInfo>& engaged_sites,
const LookalikeTargetAllowlistChecker& in_target_allowlist,
+ const reputation::SafetyTipsConfig* config_proto,
+ std::string* safe_hostname) {
+ // Because of how target embeddings are detected (i.e. by sweeping the URL
+ // from back to front), we're guaranteed to find tail-embedding before other
+ // target embedding. Tail embedding triggers a safety tip, but interstitials
+ // are more important than safety tips, so if we find a safety tippable
+ // embedding with SearchForEmbeddings, go search again not permitting safety
+ // tips to see if we can also find an interstitiallable embedding.
+ auto result = SearchForEmbeddings(
+ hostname, engaged_sites, in_target_allowlist, config_proto,
+ /*safety_tips_allowed=*/true, safe_hostname);
+ if (result == TargetEmbeddingType::kSafetyTip) {
+ std::string no_st_safe_hostname;
+ auto no_st_result = SearchForEmbeddings(
+ hostname, engaged_sites, in_target_allowlist, config_proto,
+ /*safety_tips_allowed=*/false, &no_st_safe_hostname);
+ if (no_st_result == TargetEmbeddingType::kNone) {
+ return result;
+ }
+ *safe_hostname = no_st_safe_hostname;
+ return no_st_result;
+ }
+ return result;
+}
+
+TargetEmbeddingType SearchForEmbeddings(
+ const std::string& hostname,
+ const std::vector<DomainInfo>& engaged_sites,
+ const LookalikeTargetAllowlistChecker& in_target_allowlist,
+ const reputation::SafetyTipsConfig* config_proto,
+ bool safety_tips_allowed,
std::string* safe_hostname) {
const std::string embedding_domain = GetETLDPlusOne(hostname);
const std::vector<base::StringPiece> hostname_tokens =
@@ -764,7 +803,8 @@ TargetEmbeddingType GetTargetEmbeddingType(
if (no_separator_dominfo.domain_without_registry.length() >
kMinE2LDLengthForTargetEmbedding &&
!IsAllowedToBeEmbedded(no_separator_dominfo, no_separator_tokens,
- in_target_allowlist, embedding_domain)) {
+ in_target_allowlist, embedding_domain,
+ config_proto)) {
*safe_hostname = embedded_target;
return TargetEmbeddingType::kInterstitial;
}
@@ -793,9 +833,17 @@ TargetEmbeddingType GetTargetEmbeddingType(
for (auto& engaged_site : engaged_sites) {
if (engaged_site.hostname == embedded_dominfo.hostname &&
!IsAllowedToBeEmbedded(embedded_dominfo, span, in_target_allowlist,
- embedding_domain)) {
+ embedding_domain, config_proto)) {
*safe_hostname = engaged_site.hostname;
- return TargetEmbeddingType::kInterstitial;
+ // Tail-embedding (e.g. evil-google.com, where the embedding happens
+ // at the very end of the hostname) is a safety tip, but only when
+ // safety tips are allowed. If it's tail embedding but we can't create
+ // a safety tip, keep looking. Non-tail-embeddings are interstitials.
+ if (end != static_cast<int>(hostname_tokens.size())) {
+ return TargetEmbeddingType::kInterstitial;
+ } else if (safety_tips_allowed) {
+ return TargetEmbeddingType::kSafetyTip;
+ } // else keep searching.
}
}
}
@@ -805,8 +853,17 @@ TargetEmbeddingType GetTargetEmbeddingType(
if (DoesETLDPlus1MatchTopDomainOrEngagedSite(
etld_check_dominfo, engaged_sites, safe_hostname) &&
!IsAllowedToBeEmbedded(etld_check_dominfo, etld_check_span,
- in_target_allowlist, embedding_domain)) {
- return TargetEmbeddingType::kInterstitial;
+ in_target_allowlist, embedding_domain,
+ config_proto)) {
+ // Tail-embedding (e.g. evil-google.com, where the embedding happens at
+ // the very end of the hostname) is a safety tip, but only when safety
+ // tips are allowed. If it's tail embedding but we can't create a safety
+ // tip, keep looking. Non-tail-embeddings are interstitials.
+ if (end != static_cast<int>(hostname_tokens.size())) {
+ return TargetEmbeddingType::kInterstitial;
+ } else if (safety_tips_allowed) {
+ return TargetEmbeddingType::kSafetyTip;
+ } // else keep searching.
}
}
return TargetEmbeddingType::kNone;
@@ -879,7 +936,7 @@ bool IsAllowedByEnterprisePolicy(const PrefService* pref_service,
const GURL& url) {
const auto* list =
pref_service->GetList(prefs::kLookalikeWarningAllowlistDomains);
- for (const auto& domain_val : *list) {
+ for (const auto& domain_val : list->GetList()) {
auto domain = domain_val.GetString();
if (url.DomainIs(domain)) {
return true;
diff --git a/chromium/components/lookalikes/core/lookalike_url_util.h b/chromium/components/lookalikes/core/lookalike_url_util.h
index 72124acb0ca..e5a8ba87dfa 100644
--- a/chromium/components/lookalikes/core/lookalike_url_util.h
+++ b/chromium/components/lookalikes/core/lookalike_url_util.h
@@ -9,9 +9,9 @@
#include <vector>
#include "base/callback.h"
-#include "base/time/time.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
+#include "components/reputation/core/safety_tips.pb.h"
#include "components/url_formatter/url_formatter.h"
#include "url/gurl.h"
@@ -163,31 +163,33 @@ bool GetMatchingDomain(
const DomainInfo& navigated_domain,
const std::vector<DomainInfo>& engaged_sites,
const LookalikeTargetAllowlistChecker& in_target_allowlist,
+ const reputation::SafetyTipsConfig* config_proto,
std::string* matched_domain,
LookalikeUrlMatchType* match_type);
void RecordUMAFromMatchType(LookalikeUrlMatchType match_type);
// Checks to see if a URL is a target embedding lookalike. This function sets
-// |safe_hostname| to the url of the embedded target domain.
-// At the moment we consider the following cases as Target Embedding:
-// example-google.com-site.com, example.google.com-site.com,
-// example-google-info-site.com, example.google.com.site.com,
-// example-googlé.com-site.com where the embedded target is google.com. We
-// detect embeddings of top 500 domains and engaged domains. However, to reduce
-// false positives, we do not protect domains that are shorter than 7 characters
-// long (e.g. com.ru).
-// This function checks possible targets against |in_target_allowlist| to skip
-// permitted embeddings.
-// If no target embedding is found, the return value will be set to |kNonw|.
-// When the target is embedded with another TLD instead of its actual TLD, it
-// should trigger a Safety Tip when the embedded TLD is a ccTLD. In this
-// situation, return value will be |kSafetyTip|. All the other triggers will
-// result in a |kInterstitial| return value.
+// |safe_hostname| to the url of the embedded target domain. See the unit tests
+// for what qualifies as target embedding.
TargetEmbeddingType GetTargetEmbeddingType(
const std::string& hostname,
const std::vector<DomainInfo>& engaged_sites,
const LookalikeTargetAllowlistChecker& in_target_allowlist,
+ const reputation::SafetyTipsConfig* config_proto,
+ std::string* safe_hostname);
+
+// Same as GetTargetEmbeddingType, but explicitly state whether or not a safety
+// tip is permitted via |safety_tips_allowed|. Safety tips are presently only
+// used for tail embedding (e.g. "evil-google.com"). This function may return
+// kSafetyTip preferentially to kInterstitial -- call with !safety_tips_allowed
+// if you're interested in determining if there's *also* an interstitial.
+TargetEmbeddingType SearchForEmbeddings(
+ const std::string& hostname,
+ const std::vector<DomainInfo>& engaged_sites,
+ const LookalikeTargetAllowlistChecker& in_target_allowlist,
+ const reputation::SafetyTipsConfig* config_proto,
+ bool safety_tips_allowed,
std::string* safe_hostname);
// Returns true if a navigation to an IDN should be blocked.
diff --git a/chromium/components/lookalikes/core/lookalike_url_util_unittest.cc b/chromium/components/lookalikes/core/lookalike_url_util_unittest.cc
index 4062ea99861..e7b52ca0a5f 100644
--- a/chromium/components/lookalikes/core/lookalike_url_util_unittest.cc
+++ b/chromium/components/lookalikes/core/lookalike_url_util_unittest.cc
@@ -7,8 +7,22 @@
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "components/lookalikes/core/features.h"
+#include "components/reputation/core/safety_tip_test_utils.h"
+#include "components/reputation/core/safety_tips_config.h"
#include "testing/gtest/include/gtest/gtest.h"
+std::string TargetEmbeddingTypeToString(TargetEmbeddingType type) {
+ switch (type) {
+ case TargetEmbeddingType::kNone:
+ return "kNone";
+ case TargetEmbeddingType::kInterstitial:
+ return "kInterstitial";
+ case TargetEmbeddingType::kSafetyTip:
+ return "kSafetyTip";
+ }
+ NOTREACHED();
+}
+
TEST(LookalikeUrlUtilTest, IsEditDistanceAtMostOne) {
const struct TestCase {
const wchar_t* domain;
@@ -139,7 +153,7 @@ struct TargetEmbeddingHeuristicTestCase {
const TargetEmbeddingType expected_type;
};
-TEST(LookalikeUrlUtilTest, TargetEmbeddingTest) {
+TEST(LookalikeUrlUtilTest, TargetEmbedding) {
const std::vector<DomainInfo> kEngagedSites = {
GetDomainInfo(GURL("https://highengagement.com")),
GetDomainInfo(GURL("https://highengagement.inthesubdomain.com")),
@@ -278,12 +292,15 @@ TEST(LookalikeUrlUtilTest, TargetEmbeddingTest) {
{"google.com.google.com", "", TargetEmbeddingType::kNone},
{"www.google.com.google.com", "", TargetEmbeddingType::kNone},
- // Detect embeddings at the end of the domain, too.
- {"www-google.com", "google.com", TargetEmbeddingType::kInterstitial},
+ // Detect embeddings at the end of the domain, too, but as a Safety Tip.
+ {"www-google.com", "google.com", TargetEmbeddingType::kSafetyTip},
{"www-highengagement.com", "highengagement.com",
- TargetEmbeddingType::kInterstitial},
+ TargetEmbeddingType::kSafetyTip},
{"subdomain-highengagement.com", "subdomain.highengagement.com",
- TargetEmbeddingType::kInterstitial},
+ TargetEmbeddingType::kSafetyTip},
+ // If the match duplicates the TLD, it's not quite tail-embedding.
+ {"google-com.com", "google.com", TargetEmbeddingType::kInterstitial},
+ // If there are multiple options, it should choose the more severe one.
{"google-com.google-com.com", "google.com",
TargetEmbeddingType::kInterstitial},
{"subdomain.google-com.google-com.com", "google.com",
@@ -300,14 +317,17 @@ TEST(LookalikeUrlUtilTest, TargetEmbeddingTest) {
// works for domains on the list, but not for others.
{"office.com-foo.com", "office.com", TargetEmbeddingType::kInterstitial},
{"example-office.com", "", TargetEmbeddingType::kNone},
- {"example-google.com", "google.com", TargetEmbeddingType::kInterstitial},
+ {"example-google.com", "google.com", TargetEmbeddingType::kSafetyTip},
};
+ reputation::InitializeBlankLookalikeAllowlistForTesting();
+ auto* config_proto = reputation::GetSafetyTipsRemoteConfigProto();
+
for (auto& test_case : kTestCases) {
std::string safe_hostname;
TargetEmbeddingType embedding_type = GetTargetEmbeddingType(
test_case.hostname, kEngagedSites,
- base::BindRepeating(&IsGoogleScholar), &safe_hostname);
+ base::BindRepeating(&IsGoogleScholar), config_proto, &safe_hostname);
if (test_case.expected_type != TargetEmbeddingType::kNone) {
EXPECT_EQ(safe_hostname, test_case.expected_safe_host)
<< test_case.hostname << " should trigger on "
@@ -315,19 +335,43 @@ TEST(LookalikeUrlUtilTest, TargetEmbeddingTest) {
<< (safe_hostname.empty() ? "it didn't trigger at all."
: "triggered on " + safe_hostname);
EXPECT_EQ(embedding_type, test_case.expected_type)
- << test_case.hostname << " should trigger on "
+ << test_case.hostname << " should trigger "
+ << TargetEmbeddingTypeToString(test_case.expected_type) << " against "
<< test_case.expected_safe_host << " but it returned "
- << (embedding_type == TargetEmbeddingType::kNone
- ? "kNone."
- : "something unexpected");
+ << TargetEmbeddingTypeToString(embedding_type);
} else {
EXPECT_EQ(embedding_type, TargetEmbeddingType::kNone)
- << test_case.hostname << " unexpectedly triggered on "
+ << test_case.hostname << " unexpectedly triggered "
+ << TargetEmbeddingTypeToString(embedding_type) << " against "
<< safe_hostname;
}
}
}
+TEST(LookalikeUrlUtilTest, TargetEmbeddingIgnoresComponentWordlist) {
+ const std::vector<DomainInfo> kEngagedSites = {
+ GetDomainInfo(GURL("https://commonword.com")),
+ GetDomainInfo(GURL("https://uncommonword.com")),
+ };
+
+ reputation::SetSafetyTipAllowlistPatterns({}, {}, {"commonword"});
+ auto* config_proto = reputation::GetSafetyTipsRemoteConfigProto();
+ TargetEmbeddingType embedding_type;
+ std::string safe_hostname;
+
+ // Engaged sites using uncommon words are still blocked.
+ embedding_type = GetTargetEmbeddingType(
+ "uncommonword.com.evil.com", kEngagedSites,
+ base::BindRepeating(&IsGoogleScholar), config_proto, &safe_hostname);
+ EXPECT_EQ(embedding_type, TargetEmbeddingType::kInterstitial);
+
+ // But engaged sites using common words are not blocked.
+ embedding_type = GetTargetEmbeddingType(
+ "commonword.com.evil.com", kEngagedSites,
+ base::BindRepeating(&IsGoogleScholar), config_proto, &safe_hostname);
+ EXPECT_EQ(embedding_type, TargetEmbeddingType::kNone);
+}
+
struct GetETLDPlusOneTestCase {
const std::string hostname;
const std::string expected_etldp1;
diff --git a/chromium/components/management_strings.grdp b/chromium/components/management_strings.grdp
index 81e44b74c5f..d0b6d04f3e5 100644
--- a/chromium/components/management_strings.grdp
+++ b/chromium/components/management_strings.grdp
@@ -116,6 +116,9 @@
<message name="IDS_MANAGEMENT_REPORT_PRINT_JOBS" desc="Message stating that administrators can see printing history associated with user, device, and printer.">
Printing history
</message>
+ <message name="IDS_MANAGEMENT_REPORT_DLP_EVENTS" desc="Message show the users of DLP reporting enabled devices that events are being reported.">
+ Actions taken with data flagged as confidential
+ </message>
<message name="IDS_MANAGEMENT_CROSTINI" desc="Message stating that administrators can see Crostini usage">
Linux apps installed and when they were last used
</message>
diff --git a/chromium/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_DLP_EVENTS.png.sha1 b/chromium/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_DLP_EVENTS.png.sha1
new file mode 100644
index 00000000000..f1a38802ddf
--- /dev/null
+++ b/chromium/components/management_strings_grdp/IDS_MANAGEMENT_REPORT_DLP_EVENTS.png.sha1
@@ -0,0 +1 @@
+e1f529576660b4167f1bbc0e9942313a5a8d87cb \ No newline at end of file
diff --git a/chromium/components/media_control/browser/media_blocker.h b/chromium/components/media_control/browser/media_blocker.h
index 427bba212cb..66e0cdd8636 100644
--- a/chromium/components/media_control/browser/media_blocker.h
+++ b/chromium/components/media_control/browser/media_blocker.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_MEDIA_CONTROL_BROWSER_MEDIA_BLOCKER_H_
#define COMPONENTS_MEDIA_CONTROL_BROWSER_MEDIA_BLOCKER_H_
-#include <vector>
-
#include "base/macros.h"
#include "content/public/browser/web_contents_observer.h"
diff --git a/chromium/components/media_control/renderer/media_playback_options.h b/chromium/components/media_control/renderer/media_playback_options.h
index f355d748e6d..54d536f10c4 100644
--- a/chromium/components/media_control/renderer/media_playback_options.h
+++ b/chromium/components/media_control/renderer/media_playback_options.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_MEDIA_CONTROL_RENDERER_MEDIA_PLAYBACK_OPTIONS_H_
#define COMPONENTS_MEDIA_CONTROL_RENDERER_MEDIA_PLAYBACK_OPTIONS_H_
-#include <string>
#include <vector>
#include "base/callback_forward.h"
diff --git a/chromium/components/media_message_center/BUILD.gn b/chromium/components/media_message_center/BUILD.gn
index 7becd24bbc8..3302c66d30d 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_artwork_view.cc",
+ "media_artwork_view.h",
"media_controls_progress_view.cc",
"media_controls_progress_view.h",
"media_notification_background.h",
diff --git a/chromium/components/media_message_center/media_artwork_view.cc b/chromium/components/media_message_center/media_artwork_view.cc
new file mode 100644
index 00000000000..e2b12a656b0
--- /dev/null
+++ b/chromium/components/media_message_center/media_artwork_view.cc
@@ -0,0 +1,110 @@
+// Copyright 2021 The Chromium Authors. 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_artwork_view.h"
+
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/skia_util.h"
+
+namespace media_message_center {
+
+namespace {
+
+// Get target bounds of the image fitting into |canvas_size|.
+// If |image_size| is greater than |expect_size| in any dimension,
+// we shrink it down to fit, keep the size otherwise.
+gfx::Rect GetTargetBound(const gfx::Size image_size,
+ const gfx::Size expect_size,
+ const gfx::Size canvas_size) {
+ gfx::Size target_size = image_size;
+ if (image_size.width() > expect_size.width() ||
+ image_size.height() > expect_size.height()) {
+ const float scale = std::min(
+ expect_size.width() / static_cast<float>(image_size.width()),
+ expect_size.height() / static_cast<float>(image_size.height()));
+ target_size = gfx::ScaleToFlooredSize(image_size, scale);
+ }
+
+ int offset_x = (canvas_size.width() - target_size.width()) / 2;
+ int offset_y = (canvas_size.height() - target_size.height()) / 2;
+ return gfx::Rect(offset_x, offset_y, target_size.width(),
+ target_size.height());
+}
+
+} // anonymous namespace
+
+MediaArtworkView::MediaArtworkView(float corner_radius,
+ const gfx::Size& artwork_size,
+ const gfx::Size& favicon_size)
+ : corner_radius_(corner_radius),
+ artwork_size_(artwork_size),
+ favicon_size_(favicon_size) {}
+
+void MediaArtworkView::SetVignetteColor(const SkColor& vignette_color) {
+ if (vignette_color_ == vignette_color)
+ return;
+ vignette_color_ = vignette_color;
+ OnPropertyChanged(&vignette_color_, views::kPropertyEffectsPaint);
+}
+
+SkColor MediaArtworkView::GetVignetteColor() const {
+ return vignette_color_;
+}
+
+void MediaArtworkView::SetBackgroundColor(const SkColor& background_color) {
+ background_color_ = background_color;
+}
+
+void MediaArtworkView::SetImage(const gfx::ImageSkia& image) {
+ image_ = image;
+}
+
+void MediaArtworkView::SetFavicon(const gfx::ImageSkia& favicon) {
+ favicon_ = favicon;
+}
+
+void MediaArtworkView::OnPaint(gfx::Canvas* canvas) {
+ views::View::OnPaint(canvas);
+
+ {
+ // Paint background.
+ cc::PaintFlags paint_flags;
+ paint_flags.setStyle(cc::PaintFlags::kFill_Style);
+ paint_flags.setAntiAlias(true);
+ paint_flags.setColor(background_color_);
+ canvas->DrawRect(gfx::Rect(artwork_size_), paint_flags);
+ }
+
+ // Draw image if we have artwork; fallback to favicon if we don't.
+ if (!image_.isNull()) {
+ gfx::Rect target =
+ GetTargetBound(image_.size(), artwork_size_, artwork_size_);
+ canvas->DrawImageInt(image_, 0, 0, image_.width(), image_.height(),
+ target.x(), target.y(), target.width(),
+ target.height(), false);
+ } else if (!favicon_.isNull()) {
+ gfx::Rect target =
+ GetTargetBound(favicon_.size(), favicon_size_, artwork_size_);
+ canvas->DrawImageInt(favicon_, 0, 0, favicon_.width(), favicon_.height(),
+ target.x(), target.y(), target.width(),
+ target.height(), false);
+ }
+
+ {
+ auto path = SkPath().addRoundRect(RectToSkRect(GetLocalBounds()),
+ corner_radius_, corner_radius_);
+ path.toggleInverseFillType();
+ cc::PaintFlags paint_flags;
+ paint_flags.setStyle(cc::PaintFlags::kFill_Style);
+ paint_flags.setAntiAlias(true);
+ paint_flags.setColor(vignette_color_);
+ canvas->DrawPath(path, paint_flags);
+ }
+}
+
+BEGIN_METADATA(MediaArtworkView, views::View)
+ADD_PROPERTY_METADATA(SkColor, VignetteColor)
+END_METADATA
+
+} // namespace media_message_center
diff --git a/chromium/components/media_message_center/media_artwork_view.h b/chromium/components/media_message_center/media_artwork_view.h
new file mode 100644
index 00000000000..1833c0eb566
--- /dev/null
+++ b/chromium/components/media_message_center/media_artwork_view.h
@@ -0,0 +1,49 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_ARTWORK_VIEW_H_
+#define COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_ARTWORK_VIEW_H_
+
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/views/view.h"
+
+namespace media_message_center {
+
+// An artwork view with a rounded rectangle vignette
+class MediaArtworkView : public views::View {
+ public:
+ METADATA_HEADER(MediaArtworkView);
+ MediaArtworkView(float corner_radius,
+ const gfx::Size& artwork_size,
+ const gfx::Size& favicon_size);
+ ~MediaArtworkView() override = default;
+
+ void SetVignetteColor(const SkColor& vignette_color);
+ SkColor GetVignetteColor() const;
+
+ void SetBackgroundColor(const SkColor& background_color);
+
+ void SetImage(const gfx::ImageSkia& image);
+ void SetFavicon(const gfx::ImageSkia& favicon);
+
+ // views::View
+ void OnPaint(gfx::Canvas* canvas) override;
+
+ private:
+ SkColor vignette_color_ = gfx::kPlaceholderColor;
+ SkColor background_color_ = gfx::kPlaceholderColor;
+
+ gfx::ImageSkia image_;
+ gfx::ImageSkia favicon_;
+
+ const float corner_radius_;
+ const gfx::Size artwork_size_;
+ const gfx::Size favicon_size_;
+};
+
+} // namespace media_message_center
+
+#endif // COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_ARTWORK_VIEW_H_
diff --git a/chromium/components/media_message_center/media_controls_progress_view.cc b/chromium/components/media_message_center/media_controls_progress_view.cc
index 0925128e57d..f502ccc2214 100644
--- a/chromium/components/media_message_center/media_controls_progress_view.cc
+++ b/chromium/components/media_message_center/media_controls_progress_view.cc
@@ -6,6 +6,7 @@
#include "base/i18n/time_formatting.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/font_list.h"
#include "ui/views/border.h"
@@ -14,7 +15,6 @@
#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/metadata/metadata_impl_macros.h"
#include "ui/views/view_class_properties.h"
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
index e74367de290..5bf699b666f 100644
--- a/chromium/components/media_message_center/media_controls_progress_view.h
+++ b/chromium/components/media_message_center/media_controls_progress_view.h
@@ -6,10 +6,13 @@
#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/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/view.h"
+namespace media_session {
+struct MediaPosition;
+} // namespace media_session
+
namespace views {
class ProgressBar;
class Label;
diff --git a/chromium/components/media_message_center/media_notification_background_ash_impl.cc b/chromium/components/media_message_center/media_notification_background_ash_impl.cc
index 88422c5a6be..1fb7b3cf034 100644
--- a/chromium/components/media_message_center/media_notification_background_ash_impl.cc
+++ b/chromium/components/media_message_center/media_notification_background_ash_impl.cc
@@ -4,6 +4,7 @@
#include "components/media_message_center/media_notification_background_ash_impl.h"
+#include "base/i18n/rtl.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/skia_util.h"
diff --git a/chromium/components/media_message_center/media_notification_background_impl.cc b/chromium/components/media_message_center/media_notification_background_impl.cc
index d937748b84c..072f4c817f9 100644
--- a/chromium/components/media_message_center/media_notification_background_impl.cc
+++ b/chromium/components/media_message_center/media_notification_background_impl.cc
@@ -7,11 +7,13 @@
#include <algorithm>
#include <vector>
+#include "base/i18n/rtl.h"
#include "skia/ext/image_operations.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_analysis.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/scoped_canvas.h"
+#include "ui/gfx/skia_util.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/style/typography.h"
#include "ui/views/view.h"
@@ -67,20 +69,20 @@ bool IsForegroundColorSwatchAllowed(const SkColor& background,
return diff > 10 && diff < 350;
}
-base::Optional<SkColor> GetNotificationBackgroundColor(const SkBitmap* source) {
+absl::optional<SkColor> GetNotificationBackgroundColor(const SkBitmap* source) {
if (!source || source->empty() || source->isNull())
- return base::nullopt;
+ return absl::nullopt;
std::vector<color_utils::Swatch> swatches =
color_utils::CalculateColorSwatches(
*source, 16, gfx::Rect(source->width() / 2, source->height()),
- base::nullopt);
+ absl::nullopt);
if (swatches.empty())
- return base::nullopt;
+ return absl::nullopt;
- base::Optional<color_utils::Swatch> most_popular;
- base::Optional<color_utils::Swatch> non_white_black;
+ absl::optional<color_utils::Swatch> most_popular;
+ absl::optional<color_utils::Swatch> non_white_black;
// Find the most popular color with the most weight and the color which
// is the color with the most weight that is not white or black.
@@ -138,11 +140,11 @@ color_utils::Swatch SelectMutedSwatch(const color_utils::Swatch& muted,
: more_muted;
}
-base::Optional<SkColor> GetNotificationForegroundColor(
- const base::Optional<SkColor>& background_color,
+absl::optional<SkColor> GetNotificationForegroundColor(
+ const absl::optional<SkColor>& background_color,
const SkBitmap* source) {
if (!background_color || !source || source->empty() || source->isNull())
- return base::nullopt;
+ return absl::nullopt;
const bool is_light =
color_utils::GetRelativeLuminance(*background_color) > 0.5;
@@ -197,7 +199,7 @@ base::Optional<SkColor> GetNotificationForegroundColor(
// the most popular color and then either white/black. Any swatch has to be
// above a minimum population threshold to be determined significant enough in
// the artwork to be used.
- base::Optional<color_utils::Swatch> swatch;
+ absl::optional<color_utils::Swatch> swatch;
if (more_vibrant.population > population_min &&
vibrant.population > population_min) {
swatch = SelectVibrantSwatch(more_vibrant, vibrant);
@@ -388,7 +390,7 @@ SkColor MediaNotificationBackgroundImpl::GetForegroundColor(
: views::style::GetColor(owner, views::style::CONTEXT_LABEL,
views::style::STYLE_PRIMARY);
return color_utils::BlendForMinContrast(
- foreground, GetBackgroundColor(owner), base::nullopt,
+ foreground, GetBackgroundColor(owner), absl::nullopt,
kMediaNotificationMinimumContrastRatio)
.color;
}
diff --git a/chromium/components/media_message_center/media_notification_background_impl.h b/chromium/components/media_message_center/media_notification_background_impl.h
index beb99f826b6..52642c46bc5 100644
--- a/chromium/components/media_message_center/media_notification_background_impl.h
+++ b/chromium/components/media_message_center/media_notification_background_impl.h
@@ -5,11 +5,9 @@
#ifndef COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_BACKGROUND_IMPL_H_
#define COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_BACKGROUND_IMPL_H_
-#include <vector>
-
#include "base/component_export.h"
-#include "base/optional.h"
#include "components/media_message_center/media_notification_background.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/image/image_skia.h"
namespace gfx {
@@ -75,8 +73,8 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationBackgroundImpl
double artwork_max_width_pct_;
bool audio_device_selector_availability_ = false;
- base::Optional<SkColor> background_color_;
- base::Optional<SkColor> foreground_color_;
+ absl::optional<SkColor> background_color_;
+ absl::optional<SkColor> foreground_color_;
DISALLOW_COPY_AND_ASSIGN(MediaNotificationBackgroundImpl);
};
diff --git a/chromium/components/media_message_center/media_notification_background_impl_unittest.cc b/chromium/components/media_message_center/media_notification_background_impl_unittest.cc
index c1725112e43..07356cc9e80 100644
--- a/chromium/components/media_message_center/media_notification_background_impl_unittest.cc
+++ b/chromium/components/media_message_center/media_notification_background_impl_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/i18n/base_i18n_switches.h"
+#include "base/i18n/rtl.h"
#include "base/test/icu_test_util.h"
#include "base/test/scoped_command_line.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -104,11 +105,11 @@ class MediaNotificationBackgroundImplTest : public testing::Test {
return background_.get();
}
- base::Optional<SkColor> GetBackgroundColor() const {
+ absl::optional<SkColor> GetBackgroundColor() const {
return background_->background_color_;
}
- base::Optional<SkColor> GetForegroundColor() const {
+ absl::optional<SkColor> GetForegroundColor() const {
return background_->foreground_color_;
}
diff --git a/chromium/components/media_message_center/media_notification_item.h b/chromium/components/media_message_center/media_notification_item.h
index 819da49bf8b..867d2bac1f3 100644
--- a/chromium/components/media_message_center/media_notification_item.h
+++ b/chromium/components/media_message_center/media_notification_item.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ITEM_H_
#define COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ITEM_H_
-#include <string>
-
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/media_message_center/media_notification_view.h b/chromium/components/media_message_center/media_notification_view.h
index 9d25db8cd81..dcf2a938fd2 100644
--- a/chromium/components/media_message_center/media_notification_view.h
+++ b/chromium/components/media_message_center/media_notification_view.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_VIEW_H_
#define COMPONENTS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_VIEW_H_
+#include "base/containers/flat_set.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "ui/views/view.h"
diff --git a/chromium/components/media_message_center/media_notification_view_impl.cc b/chromium/components/media_message_center/media_notification_view_impl.cc
index fb7a317d497..b293c8c0682 100644
--- a/chromium/components/media_message_center/media_notification_view_impl.cc
+++ b/chromium/components/media_message_center/media_notification_view_impl.cc
@@ -18,6 +18,7 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/font.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/paint_vector_icon.h"
@@ -26,7 +27,6 @@
#include "ui/views/controls/button/image_button_factory.h"
#include "ui/views/controls/highlight_path_generator.h"
#include "ui/views/layout/box_layout.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/typography.h"
#include "ui/views/view_class_properties.h"
@@ -104,6 +104,7 @@ const gfx::VectorIcon* GetVectorIconForMediaAction(MediaSessionAction action) {
case MediaSessionAction::kToggleMicrophone:
case MediaSessionAction::kToggleCamera:
case MediaSessionAction::kHangUp:
+ case MediaSessionAction::kRaise:
NOTREACHED();
break;
}
@@ -133,7 +134,7 @@ MediaNotificationViewImpl::MediaNotificationViewImpl(
const std::u16string& default_app_name,
int notification_width,
bool should_show_icon,
- base::Optional<NotificationTheme> theme)
+ absl::optional<NotificationTheme> theme)
: container_(container),
item_(std::move(item)),
default_app_name_(default_app_name),
@@ -344,7 +345,7 @@ void MediaNotificationViewImpl::SetForcedExpandedState(
} else {
if (!forced_expanded_state_.has_value())
return;
- forced_expanded_state_ = base::nullopt;
+ forced_expanded_state_ = absl::nullopt;
}
if (header_row_)
diff --git a/chromium/components/media_message_center/media_notification_view_impl.h b/chromium/components/media_message_center/media_notification_view_impl.h
index e758301c44f..8208eb985cf 100644
--- a/chromium/components/media_message_center/media_notification_view_impl.h
+++ b/chromium/components/media_message_center/media_notification_view_impl.h
@@ -7,12 +7,12 @@
#include "base/component_export.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/media_message_center/media_notification_view.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/label.h"
-#include "ui/views/metadata/metadata_header_macros.h"
namespace message_center {
class NotificationHeaderView;
@@ -69,7 +69,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewImpl
const std::u16string& default_app_name,
int notification_width,
bool should_show_icon,
- base::Optional<NotificationTheme> theme = base::nullopt);
+ absl::optional<NotificationTheme> theme = absl::nullopt);
MediaNotificationViewImpl(const MediaNotificationViewImpl&) = delete;
MediaNotificationViewImpl& operator=(const MediaNotificationViewImpl&) =
delete;
@@ -171,7 +171,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewImpl
bool expanded_ = false;
// Used to force the notification to remain in a specific expanded state.
- base::Optional<bool> forced_expanded_state_;
+ absl::optional<bool> forced_expanded_state_;
// Set of enabled actions.
base::flat_set<media_session::mojom::MediaSessionAction> enabled_actions_;
@@ -197,7 +197,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewImpl
views::BoxLayout* title_artist_row_layout_ = nullptr;
const gfx::VectorIcon* vector_header_icon_ = nullptr;
- base::Optional<NotificationTheme> theme_;
+ absl::optional<NotificationTheme> theme_;
const bool is_cros_;
};
diff --git a/chromium/components/media_message_center/media_notification_view_impl_unittest.cc b/chromium/components/media_message_center/media_notification_view_impl_unittest.cc
index eff0f345ce5..573d944367f 100644
--- a/chromium/components/media_message_center/media_notification_view_impl_unittest.cc
+++ b/chromium/components/media_message_center/media_notification_view_impl_unittest.cc
@@ -54,8 +54,8 @@ const int kMediaButtonIconSize = 24;
// The title artist row should always have the same height.
const int kMediaTitleArtistRowExpectedHeight = 48;
-const char kTestDefaultAppName[] = "default app name";
-const char kTestAppName[] = "app name";
+const char16_t kTestDefaultAppName[] = u"default app name";
+const char16_t kTestAppName[] = u"app name";
const gfx::Size kWidgetSize(500, 500);
@@ -254,7 +254,7 @@ class MediaNotificationViewImplTest : public views::ViewsTestBase {
->artwork_;
}
- const gfx::ImageSkia& GetAppIcon() const {
+ gfx::ImageSkia GetAppIcon() const {
return header_row()->app_icon_for_testing();
}
@@ -319,8 +319,7 @@ class MediaNotificationViewImplTest : public views::ViewsTestBase {
// Create a MediaNotificationViewImpl.
auto view = std::make_unique<MediaNotificationViewImpl>(
&container_, item_->GetWeakPtr(),
- nullptr /* header_row_controls_view */,
- base::ASCIIToUTF16(kTestDefaultAppName), kViewWidth,
+ nullptr /* header_row_controls_view */, kTestDefaultAppName, kViewWidth,
/*should_show_icon=*/true);
view->SetSize(kViewSize);
@@ -657,19 +656,17 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, UpdateMetadata_FromObserver) {
}
TEST_F(MAYBE_MediaNotificationViewImplTest, UpdateMetadata_AppName) {
- EXPECT_EQ(base::ASCIIToUTF16(kTestDefaultAppName),
- header_row()->app_name_for_testing());
+ EXPECT_EQ(kTestDefaultAppName, header_row()->app_name_for_testing());
{
media_session::MediaMetadata metadata;
metadata.title = u"title";
metadata.artist = u"artist";
- metadata.source_title = base::ASCIIToUTF16(kTestAppName);
+ metadata.source_title = kTestAppName;
GetItem()->MediaSessionMetadataChanged(metadata);
}
- EXPECT_EQ(base::ASCIIToUTF16(kTestAppName),
- header_row()->app_name_for_testing());
+ EXPECT_EQ(kTestAppName, header_row()->app_name_for_testing());
{
media_session::MediaMetadata metadata;
@@ -678,8 +675,7 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, UpdateMetadata_AppName) {
GetItem()->MediaSessionMetadataChanged(metadata);
}
- EXPECT_EQ(base::ASCIIToUTF16(kTestDefaultAppName),
- header_row()->app_name_for_testing());
+ EXPECT_EQ(kTestDefaultAppName, header_row()->app_name_for_testing());
}
TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) {
@@ -1100,7 +1096,7 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, UnfreezingDoesntMissUpdates) {
EXPECT_CALL(unfrozen_callback, Run).Times(0);
GetItem()->Freeze(unfrozen_callback.Get());
GetItem()->MediaSessionInfoChanged(nullptr);
- GetItem()->MediaSessionMetadataChanged(base::nullopt);
+ GetItem()->MediaSessionMetadataChanged(absl::nullopt);
// The item should be frozen and the view should contain the old data.
EXPECT_TRUE(GetItem()->frozen());
@@ -1163,7 +1159,7 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, UnfreezingWaitsForArtwork_Timeout) {
EXPECT_CALL(unfrozen_callback, Run).Times(0);
GetItem()->Freeze(unfrozen_callback.Get());
GetItem()->MediaSessionInfoChanged(nullptr);
- GetItem()->MediaSessionMetadataChanged(base::nullopt);
+ GetItem()->MediaSessionMetadataChanged(absl::nullopt);
GetItem()->MediaControllerImageChanged(
media_session::mojom::MediaSessionImageType::kArtwork, SkBitmap());
@@ -1236,7 +1232,7 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, UnfreezingWaitsForActions) {
EXPECT_CALL(unfrozen_callback, Run).Times(0);
GetItem()->Freeze(unfrozen_callback.Get());
GetItem()->MediaSessionInfoChanged(nullptr);
- GetItem()->MediaSessionMetadataChanged(base::nullopt);
+ GetItem()->MediaSessionMetadataChanged(absl::nullopt);
DisableAction(MediaSessionAction::kPlay);
DisableAction(MediaSessionAction::kPause);
DisableAction(MediaSessionAction::kNextTrack);
@@ -1324,7 +1320,7 @@ TEST_F(MAYBE_MediaNotificationViewImplTest,
EXPECT_CALL(unfrozen_callback, Run).Times(0);
GetItem()->Freeze(unfrozen_callback.Get());
GetItem()->MediaSessionInfoChanged(nullptr);
- GetItem()->MediaSessionMetadataChanged(base::nullopt);
+ GetItem()->MediaSessionMetadataChanged(absl::nullopt);
GetItem()->MediaControllerImageChanged(
media_session::mojom::MediaSessionImageType::kArtwork, SkBitmap());
diff --git a/chromium/components/media_message_center/media_notification_view_modern_impl.cc b/chromium/components/media_message_center/media_notification_view_modern_impl.cc
index a05ab1c7931..7cdd4dbb4f5 100644
--- a/chromium/components/media_message_center/media_notification_view_modern_impl.cc
+++ b/chromium/components/media_message_center/media_notification_view_modern_impl.cc
@@ -7,6 +7,7 @@
#include "base/containers/contains.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
+#include "components/media_message_center/media_artwork_view.h"
#include "components/media_message_center/media_controls_progress_view.h"
#include "components/media_message_center/media_notification_background_impl.h"
#include "components/media_message_center/media_notification_constants.h"
@@ -19,17 +20,18 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/font.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/skia_util.h"
#include "ui/message_center/public/cpp/message_center_constants.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/image_button_factory.h"
#include "ui/views/layout/box_layout.h"
-#include "ui/views/metadata/metadata_header_macros.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/typography.h"
#include "ui/views/view_class_properties.h"
@@ -67,46 +69,10 @@ constexpr int kUtilButtonsSpacing = 8;
constexpr int kTitleArtistLineHeight = 20;
constexpr gfx::Size kMediaButtonSize = {24, 24};
constexpr gfx::Size kPlayPauseButtonSize = {32, 32};
-constexpr int kMediaButtonIconSize = 18;
-
-// An image view with a rounded rectangle vignette
-class MediaArtworkView : public views::ImageView {
- public:
- METADATA_HEADER(MediaArtworkView);
- explicit MediaArtworkView(float corner_radius)
- : corner_radius_(corner_radius) {}
-
- void SetVignetteColor(const SkColor& vignette_color) {
- if (vignette_color_ == vignette_color)
- return;
- vignette_color_ = vignette_color;
- OnPropertyChanged(&vignette_color_, views::kPropertyEffectsPaint);
- }
- SkColor GetVignetteColor() const { return vignette_color_; }
-
- // ImageView
- void OnPaint(gfx::Canvas* canvas) override;
-
- private:
- SkColor vignette_color_ = gfx::kPlaceholderColor;
- float corner_radius_;
-};
-
-BEGIN_METADATA(MediaArtworkView, views::ImageView)
-ADD_PROPERTY_METADATA(SkColor, VignetteColor)
-END_METADATA
-
-void MediaArtworkView::OnPaint(gfx::Canvas* canvas) {
- views::ImageView::OnPaint(canvas);
- auto path = SkPath().addRoundRect(RectToSkRect(GetLocalBounds()),
- corner_radius_, corner_radius_);
- path.toggleInverseFillType();
- cc::PaintFlags paint_flags;
- paint_flags.setStyle(cc::PaintFlags::kFill_Style);
- paint_flags.setAntiAlias(true);
- paint_flags.setColor(vignette_color_);
- canvas->DrawPath(path, paint_flags);
-}
+constexpr int kMediaButtonIconSize = 14;
+constexpr int kPlayPauseIconSize = 20;
+constexpr int kMediaButtonBorderThickness = 1;
+constexpr gfx::Size kFaviconSize = {20, 20};
void RecordMetadataHistogram(
MediaNotificationViewModernImpl::Metadata metadata) {
@@ -140,6 +106,7 @@ const gfx::VectorIcon* GetVectorIconForMediaAction(MediaSessionAction action) {
case MediaSessionAction::kToggleMicrophone:
case MediaSessionAction::kToggleCamera:
case MediaSessionAction::kHangUp:
+ case MediaSessionAction::kRaise:
NOTREACHED();
break;
}
@@ -147,6 +114,105 @@ const gfx::VectorIcon* GetVectorIconForMediaAction(MediaSessionAction action) {
return nullptr;
}
+const std::u16string GetAccessibleNameForMediaAction(
+ MediaSessionAction action) {
+ switch (action) {
+ case MediaSessionAction::kPreviousTrack:
+ return l10n_util::GetStringUTF16(
+ IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_PREVIOUS_TRACK);
+ case MediaSessionAction::kSeekBackward:
+ return l10n_util::GetStringUTF16(
+ IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_SEEK_BACKWARD);
+ case MediaSessionAction::kPlay:
+ return l10n_util::GetStringUTF16(
+ IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_PLAY);
+ case MediaSessionAction::kPause:
+ return l10n_util::GetStringUTF16(
+ IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_PAUSE);
+ case MediaSessionAction::kSeekForward:
+ return l10n_util::GetStringUTF16(
+ IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_SEEK_FORWARD);
+ case MediaSessionAction::kNextTrack:
+ return l10n_util::GetStringUTF16(
+ IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_NEXT_TRACK);
+ case MediaSessionAction::kEnterPictureInPicture:
+ return l10n_util::GetStringUTF16(
+ IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_ENTER_PIP);
+ case MediaSessionAction::kExitPictureInPicture:
+ return l10n_util::GetStringUTF16(
+ IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_EXIT_PIP);
+ case MediaSessionAction::kStop:
+ case MediaSessionAction::kSkipAd:
+ case MediaSessionAction::kSeekTo:
+ case MediaSessionAction::kScrubTo:
+ case MediaSessionAction::kSwitchAudioDevice:
+ case MediaSessionAction::kToggleMicrophone:
+ case MediaSessionAction::kToggleCamera:
+ case MediaSessionAction::kHangUp:
+ case MediaSessionAction::kRaise:
+ NOTREACHED();
+ break;
+ }
+
+ return std::u16string();
+}
+
+class MediaButton : public views::ImageButton {
+ public:
+ MediaButton(PressedCallback callback, int icon_size, gfx::Size button_size)
+ : ImageButton(callback), icon_size_(icon_size) {
+ SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
+ SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
+ SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
+ SetFlipCanvasOnPaintForRTLUI(false);
+ SetPreferredSize(button_size);
+ SetBorder(views::CreateRoundedRectBorder(
+ kMediaButtonBorderThickness,
+ std::min(button_size.width(), button_size.height()) / 2,
+ SK_ColorWHITE));
+ }
+
+ void SetButtonColor(SkColor foreground_color, SkColor disabled_color) {
+ foreground_color_ = foreground_color;
+ disabled_color_ = disabled_color;
+
+ GetBorder()->set_color(IsMouseHovered() ? foreground_color
+ : disabled_color_);
+ views::SetImageFromVectorIconWithColor(
+ this, *GetVectorIconForMediaAction(GetActionFromButtonTag(*this)),
+ icon_size_, foreground_color_);
+
+ SchedulePaint();
+ }
+
+ void set_tag(int tag) {
+ views::ImageButton::set_tag(tag);
+
+ SetTooltipText(
+ GetAccessibleNameForMediaAction(GetActionFromButtonTag(*this)));
+ SetAccessibleName(
+ GetAccessibleNameForMediaAction(GetActionFromButtonTag(*this)));
+ views::SetImageFromVectorIconWithColor(
+ this, *GetVectorIconForMediaAction(GetActionFromButtonTag(*this)),
+ icon_size_, foreground_color_);
+ }
+
+ void OnMouseEntered(const ui::MouseEvent& event) override {
+ GetBorder()->set_color(foreground_color_);
+ SchedulePaint();
+ }
+
+ void OnMouseExited(const ui::MouseEvent& event) override {
+ GetBorder()->set_color(disabled_color_);
+ SchedulePaint();
+ }
+
+ private:
+ SkColor foreground_color_ = gfx::kPlaceholderColor;
+ SkColor disabled_color_ = gfx::kPlaceholderColor;
+ int icon_size_;
+};
+
} // anonymous namespace
// static
@@ -212,41 +278,27 @@ MediaNotificationViewModernImpl::MediaNotificationViewModernImpl(
// regardless of the local UI direction.
media_controls_container->SetMirrored(false);
- CreateMediaButton(
- media_controls_container.get(), MediaSessionAction::kPreviousTrack,
- l10n_util::GetStringUTF16(
- IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_PREVIOUS_TRACK));
- CreateMediaButton(
- media_controls_container.get(), MediaSessionAction::kSeekBackward,
- l10n_util::GetStringUTF16(
- IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_SEEK_BACKWARD));
+ CreateMediaButton(media_controls_container.get(),
+ MediaSessionAction::kPreviousTrack);
+ CreateMediaButton(media_controls_container.get(),
+ MediaSessionAction::kSeekBackward);
{
- auto play_pause_button = views::CreateVectorToggleImageButton(
- views::Button::PressedCallback());
+ auto play_pause_button = std::make_unique<MediaButton>(
+ views::Button::PressedCallback(), kPlayPauseIconSize,
+ kPlayPauseButtonSize);
play_pause_button->SetCallback(
base::BindRepeating(&MediaNotificationViewModernImpl::ButtonPressed,
base::Unretained(this), play_pause_button.get()));
play_pause_button->set_tag(static_cast<int>(MediaSessionAction::kPlay));
- play_pause_button->SetPreferredSize(kPlayPauseButtonSize);
- play_pause_button->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
- play_pause_button->SetTooltipText(l10n_util::GetStringUTF16(
- IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_PLAY));
- play_pause_button->SetToggledTooltipText(l10n_util::GetStringUTF16(
- IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_PAUSE));
- play_pause_button->SetFlipCanvasOnPaintForRTLUI(false);
play_pause_button_ =
media_controls_container->AddChildView(std::move(play_pause_button));
}
- CreateMediaButton(
- media_controls_container.get(), MediaSessionAction::kSeekForward,
- l10n_util::GetStringUTF16(
- IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_SEEK_FORWARD));
- CreateMediaButton(
- media_controls_container.get(), MediaSessionAction::kNextTrack,
- l10n_util::GetStringUTF16(
- IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_NEXT_TRACK));
+ CreateMediaButton(media_controls_container.get(),
+ MediaSessionAction::kSeekForward);
+ CreateMediaButton(media_controls_container.get(),
+ MediaSessionAction::kNextTrack);
media_controls_container_ =
buttons_container->AddChildView(std::move(media_controls_container));
@@ -285,10 +337,6 @@ MediaNotificationViewModernImpl::MediaNotificationViewModernImpl(
auto artwork_container = std::make_unique<views::View>();
artwork_container->SetPreferredSize(kArtworkSize);
- // The artwork container will become visible once artwork has been set in
- // UpdateWithMediaArtwork
- artwork_container->SetVisible(false);
-
auto* artwork_container_layout = artwork_container->SetLayoutManager(
std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), 0));
@@ -298,8 +346,8 @@ MediaNotificationViewModernImpl::MediaNotificationViewModernImpl(
views::BoxLayout::CrossAxisAlignment::kCenter);
{
- auto artwork =
- std::make_unique<MediaArtworkView>(kArtworkVignetteCornerRadius);
+ auto artwork = std::make_unique<MediaArtworkView>(
+ kArtworkVignetteCornerRadius, kArtworkSize, kFaviconSize);
artwork_ = artwork_container->AddChildView(std::move(artwork));
}
@@ -364,27 +412,13 @@ MediaNotificationViewModernImpl::MediaNotificationViewModernImpl(
{
// The picture-in-picture button appears directly under the media
// labels.
- auto picture_in_picture_button = views::CreateVectorToggleImageButton(
- views::Button::PressedCallback());
+ auto picture_in_picture_button = std::make_unique<MediaButton>(
+ views::Button::PressedCallback(), kPipButtonIconSize, kPipButtonSize);
picture_in_picture_button->SetCallback(base::BindRepeating(
&MediaNotificationViewModernImpl::ButtonPressed,
base::Unretained(this), picture_in_picture_button.get()));
picture_in_picture_button->set_tag(
static_cast<int>(MediaSessionAction::kEnterPictureInPicture));
- picture_in_picture_button->SetPreferredSize(kPipButtonSize);
- picture_in_picture_button->SetFocusBehavior(
- views::View::FocusBehavior::ALWAYS);
- picture_in_picture_button->SetTooltipText(l10n_util::GetStringUTF16(
- IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_ENTER_PIP));
- picture_in_picture_button->SetToggledTooltipText(
- l10n_util::GetStringUTF16(
- IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_EXIT_PIP));
- picture_in_picture_button->SetFlipCanvasOnPaintForRTLUI(false);
- views::SetImageFromVectorIconWithColor(
- picture_in_picture_button.get(),
- *GetVectorIconForMediaAction(
- MediaSessionAction::kEnterPictureInPicture),
- kPipButtonIconSize, SK_ColorBLACK);
picture_in_picture_button_ = util_buttons_container->AddChildView(
std::move(picture_in_picture_button));
}
@@ -426,7 +460,6 @@ void MediaNotificationViewModernImpl::UpdateWithMediaSessionInfo(
bool playing =
session_info && session_info->playback_state ==
media_session::mojom::MediaPlaybackState::kPlaying;
- play_pause_button_->SetToggled(playing);
MediaSessionAction action =
playing ? MediaSessionAction::kPause : MediaSessionAction::kPlay;
@@ -436,7 +469,6 @@ void MediaNotificationViewModernImpl::UpdateWithMediaSessionInfo(
session_info &&
session_info->picture_in_picture_state ==
media_session::mojom::MediaPictureInPictureState::kInPictureInPicture;
- picture_in_picture_button_->SetToggled(in_picture_in_picture);
action = in_picture_in_picture ? MediaSessionAction::kExitPictureInPicture
: MediaSessionAction::kEnterPictureInPicture;
@@ -507,14 +539,8 @@ void MediaNotificationViewModernImpl::UpdateWithMediaArtwork(
GetMediaNotificationBackground()->UpdateArtwork(image);
UMA_HISTOGRAM_BOOLEAN(kArtworkHistogramName, !image.isNull());
-
- if (!image.isNull())
- artwork_container_->SetVisible(true);
-
artwork_->SetImage(image);
artwork_->SetPreferredSize(kArtworkSize);
- artwork_->SetVignetteColor(
- GetMediaNotificationBackground()->GetBackgroundColor(*this));
UpdateForegroundColor();
@@ -529,6 +555,8 @@ void MediaNotificationViewModernImpl::UpdateWithFavicon(
const gfx::ImageSkia& icon) {
GetMediaNotificationBackground()->UpdateFavicon(icon);
+ artwork_->SetFavicon(icon);
+ artwork_->SetPreferredSize(kArtworkSize);
UpdateForegroundColor();
SchedulePaint();
}
@@ -562,19 +590,13 @@ void MediaNotificationViewModernImpl::UpdateActionButtonsVisibility() {
void MediaNotificationViewModernImpl::CreateMediaButton(
views::View* parent_view,
- MediaSessionAction action,
- const std::u16string& accessible_name) {
- auto button =
- views::CreateVectorImageButton(views::Button::PressedCallback());
+ MediaSessionAction action) {
+ auto button = std::make_unique<MediaButton>(
+ views::Button::PressedCallback(), kMediaButtonIconSize, kMediaButtonSize);
button->SetCallback(
base::BindRepeating(&MediaNotificationViewModernImpl::ButtonPressed,
base::Unretained(this), button.get()));
button->set_tag(static_cast<int>(action));
- button->SetPreferredSize(kMediaButtonSize);
- button->SetAccessibleName(accessible_name);
- button->SetTooltipText(accessible_name);
- button->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
- button->SetFlipCanvasOnPaintForRTLUI(false);
parent_view->AddChildView(std::move(button));
}
@@ -591,6 +613,9 @@ void MediaNotificationViewModernImpl::UpdateForegroundColor() {
const SkColor disabled_icon_color =
SkColorSetA(foreground, gfx::kDisabledControlAlpha);
+ artwork_->SetBackgroundColor(disabled_icon_color);
+ artwork_->SetVignetteColor(background);
+
progress_->SetForegroundColor(foreground);
progress_->SetBackgroundColor(disabled_icon_color);
progress_->SetTextColor(foreground);
@@ -604,23 +629,8 @@ void MediaNotificationViewModernImpl::UpdateForegroundColor() {
// Update the colors for the toggle buttons (play/pause and
// picture-in-picture)
- views::SetImageFromVectorIconWithColor(
- play_pause_button_,
- *GetVectorIconForMediaAction(MediaSessionAction::kPlay),
- kMediaButtonIconSize, foreground);
- views::SetToggledImageFromVectorIconWithColor(
- play_pause_button_,
- *GetVectorIconForMediaAction(MediaSessionAction::kPause),
- kMediaButtonIconSize, foreground, disabled_icon_color);
-
- views::SetImageFromVectorIconWithColor(
- picture_in_picture_button_,
- *GetVectorIconForMediaAction(MediaSessionAction::kEnterPictureInPicture),
- kPipButtonIconSize, foreground);
- views::SetToggledImageFromVectorIconWithColor(
- picture_in_picture_button_,
- *GetVectorIconForMediaAction(MediaSessionAction::kExitPictureInPicture),
- kPipButtonIconSize, foreground, disabled_icon_color);
+ play_pause_button_->SetButtonColor(foreground, disabled_icon_color);
+ picture_in_picture_button_->SetButtonColor(foreground, disabled_icon_color);
// Update the colors for the media control buttons.
for (views::View* child : media_controls_container_->children()) {
@@ -628,13 +638,9 @@ void MediaNotificationViewModernImpl::UpdateForegroundColor() {
if (child == play_pause_button_)
continue;
- views::ImageButton* button = static_cast<views::ImageButton*>(child);
+ MediaButton* button = static_cast<MediaButton*>(child);
- views::SetImageFromVectorIconWithColor(
- button, *GetVectorIconForMediaAction(GetActionFromButtonTag(*button)),
- kMediaButtonIconSize, foreground);
-
- button->SchedulePaint();
+ button->SetButtonColor(foreground, disabled_icon_color);
}
SchedulePaint();
@@ -650,6 +656,11 @@ void MediaNotificationViewModernImpl::SeekTo(double seek_progress) {
item_->SeekTo(seek_progress * position_.duration());
}
+views::Button*
+MediaNotificationViewModernImpl::picture_in_picture_button_for_testing() const {
+ return picture_in_picture_button_;
+}
+
BEGIN_METADATA(MediaNotificationViewModernImpl, views::View)
END_METADATA
diff --git a/chromium/components/media_message_center/media_notification_view_modern_impl.h b/chromium/components/media_message_center/media_notification_view_modern_impl.h
index 8eae911b881..38c34a9c3a5 100644
--- a/chromium/components/media_message_center/media_notification_view_modern_impl.h
+++ b/chromium/components/media_message_center/media_notification_view_modern_impl.h
@@ -9,25 +9,25 @@
#include "base/component_export.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/media_message_center/media_notification_view.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
-#include "ui/views/metadata/metadata_header_macros.h"
namespace views {
class Button;
-class ToggleImageButton;
} // namespace views
namespace media_message_center {
namespace {
-class MediaArtworkView;
+class MediaButton;
} // anonymous namespace
+class MediaArtworkView;
class MediaControlsProgressView;
class MediaNotificationBackground;
class MediaNotificationContainer;
@@ -97,9 +97,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewModernImpl
return subtitle_label_;
}
- const views::Button* picture_in_picture_button_for_testing() const {
- return picture_in_picture_button_;
- }
+ views::Button* picture_in_picture_button_for_testing() const;
const views::View* media_controls_container_for_testing() const {
return media_controls_container_;
@@ -113,8 +111,7 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewModernImpl
// |accessible_name| is the text used for screen readers and the
// button's tooltip.
void CreateMediaButton(views::View* parent_view,
- media_session::mojom::MediaSessionAction action,
- const std::u16string& accessible_name);
+ media_session::mojom::MediaSessionAction action);
void UpdateActionButtonsVisibility();
@@ -151,10 +148,10 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewModernImpl
MediaArtworkView* artwork_ = nullptr;
views::Label* title_label_ = nullptr;
views::Label* subtitle_label_ = nullptr;
- views::ToggleImageButton* picture_in_picture_button_ = nullptr;
+ MediaButton* picture_in_picture_button_ = nullptr;
views::View* notification_controls_spacer_ = nullptr;
views::View* media_controls_container_ = nullptr;
- views::ToggleImageButton* play_pause_button_ = nullptr;
+ MediaButton* play_pause_button_ = nullptr;
MediaControlsProgressView* progress_ = nullptr;
};
diff --git a/chromium/components/media_message_center/media_notification_view_modern_impl_unittest.cc b/chromium/components/media_message_center/media_notification_view_modern_impl_unittest.cc
index 54ff7aac56d..52625ea4df9 100644
--- a/chromium/components/media_message_center/media_notification_view_modern_impl_unittest.cc
+++ b/chromium/components/media_message_center/media_notification_view_modern_impl_unittest.cc
@@ -216,21 +216,20 @@ class MediaNotificationViewModernImplTest : public views::ViewsTestBase {
return view()->media_controls_container_;
}
+ views::Button* picture_in_picture_button() const {
+ return view()->picture_in_picture_button_for_testing();
+ }
+
std::vector<views::Button*> media_control_buttons() const {
std::vector<views::Button*> buttons;
auto children = view()->media_controls_container_->children();
std::transform(
children.begin(), children.end(), std::back_inserter(buttons),
[](views::View* child) { return views::Button::AsButton(child); });
- buttons.push_back(
- views::Button::AsButton(view()->picture_in_picture_button_));
+ buttons.push_back(views::Button::AsButton(picture_in_picture_button()));
return buttons;
}
- views::Button* picture_in_picture_button() const {
- return view()->picture_in_picture_button_;
- }
-
MediaControlsProgressView* progress_view() const { return view()->progress_; }
views::Button* GetButtonForAction(MediaSessionAction action) const {
@@ -525,20 +524,18 @@ TEST_F(MAYBE_MediaNotificationViewModernImplTest,
EnableAction(MediaSessionAction::kPlay);
{
- views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>(
- GetButtonForAction(MediaSessionAction::kPlay));
- ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName());
- EXPECT_FALSE(button->GetToggled());
+ views::Button* button = GetButtonForAction(MediaSessionAction::kPlay);
+ EXPECT_NE(button, nullptr);
+ EXPECT_EQ(button->tag(), static_cast<int>(MediaSessionAction::kPlay));
}
view()->UpdateWithMediaSessionInfo(
media_session::mojom::MediaSessionInfo::New());
{
- views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>(
- GetButtonForAction(MediaSessionAction::kPlay));
- ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName());
- EXPECT_FALSE(button->GetToggled());
+ views::Button* button = GetButtonForAction(MediaSessionAction::kPlay);
+ EXPECT_NE(button, nullptr);
+ EXPECT_EQ(button->tag(), static_cast<int>(MediaSessionAction::kPlay));
}
}
@@ -548,10 +545,9 @@ TEST_F(MAYBE_MediaNotificationViewModernImplTest,
EnableAction(MediaSessionAction::kPause);
{
- views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>(
- GetButtonForAction(MediaSessionAction::kPlay));
- ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName());
- EXPECT_FALSE(button->GetToggled());
+ views::Button* button = GetButtonForAction(MediaSessionAction::kPlay);
+ EXPECT_NE(button, nullptr);
+ EXPECT_EQ(button->tag(), static_cast<int>(MediaSessionAction::kPlay));
}
media_session::mojom::MediaSessionInfoPtr session_info(
@@ -562,10 +558,9 @@ TEST_F(MAYBE_MediaNotificationViewModernImplTest,
view()->UpdateWithMediaSessionInfo(session_info.Clone());
{
- views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>(
- GetButtonForAction(MediaSessionAction::kPause));
- ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName());
- EXPECT_TRUE(button->GetToggled());
+ views::Button* button = GetButtonForAction(MediaSessionAction::kPause);
+ EXPECT_NE(button, nullptr);
+ EXPECT_EQ(button->tag(), static_cast<int>(MediaSessionAction::kPause));
}
session_info->playback_state =
@@ -573,10 +568,9 @@ TEST_F(MAYBE_MediaNotificationViewModernImplTest,
view()->UpdateWithMediaSessionInfo(session_info.Clone());
{
- views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>(
- GetButtonForAction(MediaSessionAction::kPlay));
- ASSERT_EQ(views::ToggleImageButton::kViewClassName, button->GetClassName());
- EXPECT_FALSE(button->GetToggled());
+ views::Button* button = GetButtonForAction(MediaSessionAction::kPlay);
+ EXPECT_NE(button, nullptr);
+ EXPECT_EQ(button->tag(), static_cast<int>(MediaSessionAction::kPlay));
}
}
@@ -792,7 +786,7 @@ TEST_F(MAYBE_MediaNotificationViewModernImplTest, UnfreezingDoesntMissUpdates) {
EXPECT_CALL(unfrozen_callback, Run).Times(0);
GetItem()->Freeze(unfrozen_callback.Get());
GetItem()->MediaSessionInfoChanged(nullptr);
- GetItem()->MediaSessionMetadataChanged(base::nullopt);
+ GetItem()->MediaSessionMetadataChanged(absl::nullopt);
// The item should be frozen and the view should contain the old data.
EXPECT_TRUE(GetItem()->frozen());
@@ -856,7 +850,7 @@ TEST_F(MAYBE_MediaNotificationViewModernImplTest,
EXPECT_CALL(unfrozen_callback, Run).Times(0);
GetItem()->Freeze(unfrozen_callback.Get());
GetItem()->MediaSessionInfoChanged(nullptr);
- GetItem()->MediaSessionMetadataChanged(base::nullopt);
+ GetItem()->MediaSessionMetadataChanged(absl::nullopt);
GetItem()->MediaControllerImageChanged(
media_session::mojom::MediaSessionImageType::kArtwork, SkBitmap());
@@ -929,7 +923,7 @@ TEST_F(MAYBE_MediaNotificationViewModernImplTest, UnfreezingWaitsForActions) {
EXPECT_CALL(unfrozen_callback, Run).Times(0);
GetItem()->Freeze(unfrozen_callback.Get());
GetItem()->MediaSessionInfoChanged(nullptr);
- GetItem()->MediaSessionMetadataChanged(base::nullopt);
+ GetItem()->MediaSessionMetadataChanged(absl::nullopt);
DisableAction(MediaSessionAction::kPlay);
DisableAction(MediaSessionAction::kPause);
DisableAction(MediaSessionAction::kNextTrack);
@@ -1017,7 +1011,7 @@ TEST_F(MAYBE_MediaNotificationViewModernImplTest,
EXPECT_CALL(unfrozen_callback, Run).Times(0);
GetItem()->Freeze(unfrozen_callback.Get());
GetItem()->MediaSessionInfoChanged(nullptr);
- GetItem()->MediaSessionMetadataChanged(base::nullopt);
+ GetItem()->MediaSessionMetadataChanged(absl::nullopt);
GetItem()->MediaControllerImageChanged(
media_session::mojom::MediaSessionImageType::kArtwork, SkBitmap());
diff --git a/chromium/components/media_message_center/media_session_notification_item.cc b/chromium/components/media_message_center/media_session_notification_item.cc
index 36ebba6fd74..1262d79b26b 100644
--- a/chromium/components/media_message_center/media_session_notification_item.cc
+++ b/chromium/components/media_message_center/media_session_notification_item.cc
@@ -75,7 +75,7 @@ void MediaSessionNotificationItem::MediaSessionInfoChanged(
}
void MediaSessionNotificationItem::MediaSessionMetadataChanged(
- const base::Optional<media_session::MediaMetadata>& metadata) {
+ const absl::optional<media_session::MediaMetadata>& metadata) {
session_metadata_ = metadata.value_or(media_session::MediaMetadata());
view_needs_metadata_update_ = true;
@@ -110,7 +110,7 @@ void MediaSessionNotificationItem::MediaSessionActionsChanged(
}
void MediaSessionNotificationItem::MediaSessionPositionChanged(
- const base::Optional<media_session::MediaPosition>& position) {
+ const absl::optional<media_session::MediaPosition>& position) {
session_position_ = position;
if (!position.has_value())
return;
@@ -187,6 +187,13 @@ media_message_center::SourceType MediaSessionNotificationItem::SourceType() {
return media_message_center::SourceType::kLocalMediaSession;
}
+void MediaSessionNotificationItem::Raise() {
+ if (!media_controller_remote_.is_bound())
+ return;
+
+ media_controller_remote_->Raise();
+}
+
void MediaSessionNotificationItem::SetController(
mojo::Remote<media_session::mojom::MediaController> controller,
media_session::mojom::MediaSessionInfoPtr session_info) {
diff --git a/chromium/components/media_message_center/media_session_notification_item.h b/chromium/components/media_message_center/media_session_notification_item.h
index 39c451e25b4..7d52f859ff9 100644
--- a/chromium/components/media_message_center/media_session_notification_item.h
+++ b/chromium/components/media_message_center/media_session_notification_item.h
@@ -12,12 +12,12 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/media_message_center/media_notification_item.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 "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/image/image_skia.h"
namespace media_message_center {
@@ -47,14 +47,14 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaSessionNotificationItem
void MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr session_info) override;
void MediaSessionMetadataChanged(
- const base::Optional<media_session::MediaMetadata>& metadata) override;
+ const absl::optional<media_session::MediaMetadata>& metadata) override;
void MediaSessionActionsChanged(
const std::vector<media_session::mojom::MediaSessionAction>& actions)
override;
void MediaSessionChanged(
- const base::Optional<base::UnguessableToken>& request_id) override {}
+ const absl::optional<base::UnguessableToken>& request_id) override {}
void MediaSessionPositionChanged(
- const base::Optional<media_session::MediaPosition>& position) override;
+ const absl::optional<media_session::MediaPosition>& position) override;
// media_session::mojom::MediaControllerImageObserver:
void MediaControllerImageChanged(
@@ -71,6 +71,10 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaSessionNotificationItem
void Dismiss() override;
media_message_center::SourceType SourceType() override;
+ // Calls |Raise()| on the underlying MediaSession, which will focus the
+ // WebContents if the MediaSession is associated with one.
+ void Raise();
+
base::WeakPtr<MediaSessionNotificationItem> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
@@ -131,11 +135,11 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaSessionNotificationItem
base::flat_set<media_session::mojom::MediaSessionAction> session_actions_;
- base::Optional<media_session::MediaPosition> session_position_;
+ absl::optional<media_session::MediaPosition> session_position_;
- base::Optional<gfx::ImageSkia> session_artwork_;
+ absl::optional<gfx::ImageSkia> session_artwork_;
- base::Optional<gfx::ImageSkia> session_favicon_;
+ absl::optional<gfx::ImageSkia> session_favicon_;
// True if the metadata needs to be updated on |view_|. Used to prevent
// updating |view_|'s metadata twice on a single change.
diff --git a/chromium/components/media_router/browser/android/DIR_METADATA b/chromium/components/media_router/browser/android/DIR_METADATA
deleted file mode 100644
index 1d3a283dc43..00000000000
--- a/chromium/components/media_router/browser/android/DIR_METADATA
+++ /dev/null
@@ -1,4 +0,0 @@
-monorail {
- component: "Internals>Cast"
-}
-team_email: "media-dev@chromium.org"
diff --git a/chromium/components/media_router/browser/android/media_router_android.cc b/chromium/components/media_router/browser/android/media_router_android.cc
index 51d7c7d9098..563af73cab6 100644
--- a/chromium/components/media_router/browser/android/media_router_android.cc
+++ b/chromium/components/media_router/browser/android/media_router_android.cc
@@ -309,7 +309,7 @@ void MediaRouterAndroid::OnRouteTerminated(const MediaRoute::Id& route_id) {
void MediaRouterAndroid::OnRouteClosed(
const MediaRoute::Id& route_id,
- const base::Optional<std::string>& error) {
+ const absl::optional<std::string>& error) {
RemoveRoute(route_id);
// TODO(crbug.com/882690): When the sending context is destroyed, tell MRP to
// clean up the connection.
diff --git a/chromium/components/media_router/browser/android/media_router_android.h b/chromium/components/media_router/browser/android/media_router_android.h
index 911ca941f00..b48e7c6e8e9 100644
--- a/chromium/components/media_router/browser/android/media_router_android.h
+++ b/chromium/components/media_router/browser/android/media_router_android.h
@@ -84,7 +84,7 @@ class MediaRouterAndroid : public MediaRouterBase {
// Notifies the media router when the route was closed with an optional error.
// Null error indicates no error.
void OnRouteClosed(const MediaRoute::Id& route_id,
- const base::Optional<std::string>& error);
+ const absl::optional<std::string>& error);
// Notifies the media router about a message received from the media route.
void OnMessage(const MediaRoute::Id& route_id, const std::string& message);
diff --git a/chromium/components/media_router/browser/android/media_router_android_bridge.cc b/chromium/components/media_router/browser/android/media_router_android_bridge.cc
index 621a7d76d85..669cdf3d3f7 100644
--- a/chromium/components/media_router/browser/android/media_router_android_bridge.cc
+++ b/chromium/components/media_router/browser/android/media_router_android_bridge.cc
@@ -208,8 +208,8 @@ void MediaRouterAndroidBridge::OnRouteClosed(
native_media_router_->OnRouteClosed(
ConvertJavaStringToUTF8(env, jmedia_route_id),
jerror.is_null()
- ? base::nullopt
- : base::make_optional(ConvertJavaStringToUTF8(env, jerror)));
+ ? absl::nullopt
+ : absl::make_optional(ConvertJavaStringToUTF8(env, jerror)));
}
void MediaRouterAndroidBridge::OnMessage(
diff --git a/chromium/components/media_router/browser/android/media_router_android_unittest.cc b/chromium/components/media_router/browser/android/media_router_android_unittest.cc
index d6f6fcf5647..fb7a95bf05b 100644
--- a/chromium/components/media_router/browser/android/media_router_android_unittest.cc
+++ b/chromium/components/media_router/browser/android/media_router_android_unittest.cc
@@ -142,7 +142,7 @@ TEST_F(MediaRouterAndroidTest, OnRouteClosed) {
base::CallbackListSubscription subscription =
router_->AddPresentationConnectionStateChangedCallback("route",
callback.Get());
- router_->OnRouteClosed("route", base::nullopt);
+ router_->OnRouteClosed("route", absl::nullopt);
EXPECT_EQ(nullptr, router_->FindRouteBySource("source"));
}
diff --git a/chromium/components/media_router/browser/android/media_router_dialog_controller_android.h b/chromium/components/media_router/browser/android/media_router_dialog_controller_android.h
index c4bed419166..1f34b0572cf 100644
--- a/chromium/components/media_router/browser/android/media_router_dialog_controller_android.h
+++ b/chromium/components/media_router/browser/android/media_router_dialog_controller_android.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_MEDIA_ROUTER_BROWSER_ANDROID_MEDIA_ROUTER_DIALOG_CONTROLLER_ANDROID_H_
#define COMPONENTS_MEDIA_ROUTER_BROWSER_ANDROID_MEDIA_ROUTER_DIALOG_CONTROLLER_ANDROID_H_
-#include <memory>
-
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "components/media_router/browser/media_router_dialog_controller.h"
diff --git a/chromium/components/media_router/browser/logger_impl.cc b/chromium/components/media_router/browser/logger_impl.cc
index 6a9b9671672..48bb1872cf5 100644
--- a/chromium/components/media_router/browser/logger_impl.cc
+++ b/chromium/components/media_router/browser/logger_impl.cc
@@ -6,6 +6,7 @@
#include "base/i18n/time_formatting.h"
#include "base/json/json_string_value_serializer.h"
+#include "base/strings/string_piece.h"
#include "base/values.h"
#include "components/media_router/common/media_source.h"
#include "components/media_router/common/mojom/logger.mojom-shared.h"
@@ -128,11 +129,11 @@ LoggerImpl::Entry::Entry(Severity severity,
: severity(severity),
category(category),
time(time),
- component(component.as_string()),
- message(message.as_string()),
- sink_id(sink_id.as_string()),
+ component(component),
+ message(message),
+ sink_id(sink_id),
media_source(std::move(media_source)),
- session_id(session_id.as_string()) {}
+ session_id(session_id) {}
LoggerImpl::Entry::Entry(Entry&& other)
: severity(other.severity),
diff --git a/chromium/components/media_router/browser/media_router_dialog_controller.h b/chromium/components/media_router/browser/media_router_dialog_controller.h
index 6a9c7fb4f7c..ac6880fcbc2 100644
--- a/chromium/components/media_router/browser/media_router_dialog_controller.h
+++ b/chromium/components/media_router/browser/media_router_dialog_controller.h
@@ -6,15 +6,12 @@
#define COMPONENTS_MEDIA_ROUTER_BROWSER_MEDIA_ROUTER_DIALOG_CONTROLLER_H_
#include <memory>
-#include <string>
#include "base/callback.h"
#include "base/macros.h"
-#include "components/media_router/common/mojom/media_router.mojom.h"
#include "content/public/browser/presentation_request.h"
#include "content/public/browser/presentation_service_delegate.h"
#include "content/public/browser/web_contents_observer.h"
-#include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
namespace content {
class WebContents;
diff --git a/chromium/components/media_router/browser/media_router_dialog_controller_unittest.cc b/chromium/components/media_router/browser/media_router_dialog_controller_unittest.cc
index 498e88b4848..725a9705296 100644
--- a/chromium/components/media_router/browser/media_router_dialog_controller_unittest.cc
+++ b/chromium/components/media_router/browser/media_router_dialog_controller_unittest.cc
@@ -13,6 +13,7 @@
#include "components/media_router/browser/presentation/start_presentation_context.h"
#include "components/media_router/common/media_route.h"
#include "components/media_router/common/media_source.h"
+#include "components/media_router/common/mojom/media_router.mojom.h"
#include "components/media_router/common/route_request_result.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
diff --git a/chromium/components/media_router/browser/media_router_metrics.h b/chromium/components/media_router/browser/media_router_metrics.h
index 6e55161d590..ebe581bfc72 100644
--- a/chromium/components/media_router/browser/media_router_metrics.h
+++ b/chromium/components/media_router/browser/media_router_metrics.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_MEDIA_ROUTER_BROWSER_MEDIA_ROUTER_METRICS_H_
#define COMPONENTS_MEDIA_ROUTER_BROWSER_MEDIA_ROUTER_METRICS_H_
-#include <memory>
-
#include "base/gtest_prod_util.h"
#include "base/time/time.h"
#include "components/media_router/common/media_route_provider_helper.h"
diff --git a/chromium/components/media_router/browser/media_router_metrics_unittest.cc b/chromium/components/media_router/browser/media_router_metrics_unittest.cc
index 91ad2b0057b..efd5459244d 100644
--- a/chromium/components/media_router/browser/media_router_metrics_unittest.cc
+++ b/chromium/components/media_router/browser/media_router_metrics_unittest.cc
@@ -218,16 +218,14 @@ TEST(MediaRouterMetricsTest, RecordMediaSinkType) {
MediaRouterMetrics::RecordMediaSinkType(SinkIconType::WIRED_DISPLAY);
MediaRouterMetrics::RecordMediaSinkType(SinkIconType::CAST);
MediaRouterMetrics::RecordMediaSinkType(SinkIconType::CAST_AUDIO);
- MediaRouterMetrics::RecordMediaSinkType(SinkIconType::HANGOUT);
MediaRouterMetrics::RecordMediaSinkType(SinkIconType::CAST);
MediaRouterMetrics::RecordMediaSinkType(SinkIconType::GENERIC);
- tester.ExpectTotalCount(MediaRouterMetrics::kHistogramMediaSinkType, 6);
+ tester.ExpectTotalCount(MediaRouterMetrics::kHistogramMediaSinkType, 5);
EXPECT_THAT(
tester.GetAllSamples(MediaRouterMetrics::kHistogramMediaSinkType),
ElementsAre(Bucket(static_cast<int>(SinkIconType::CAST), 2),
Bucket(static_cast<int>(SinkIconType::CAST_AUDIO), 1),
- Bucket(static_cast<int>(SinkIconType::HANGOUT), 1),
Bucket(static_cast<int>(SinkIconType::WIRED_DISPLAY), 1),
Bucket(static_cast<int>(SinkIconType::GENERIC), 1)));
}
diff --git a/chromium/components/media_router/browser/media_sinks_observer.h b/chromium/components/media_router/browser/media_sinks_observer.h
index bdcd09dd9c7..f528635dec8 100644
--- a/chromium/components/media_router/browser/media_sinks_observer.h
+++ b/chromium/components/media_router/browser/media_sinks_observer.h
@@ -51,7 +51,7 @@ class MediaSinksObserver {
virtual void OnSinksUpdated(const std::vector<MediaSink>& sinks,
const std::vector<url::Origin>& origins);
- const base::Optional<const MediaSource>& source() const { return source_; }
+ const absl::optional<const MediaSource>& source() const { return source_; }
protected:
// This function is invoked from |OnSinksUpdated(sinks, origins)|.
@@ -61,7 +61,7 @@ class MediaSinksObserver {
virtual void OnSinksReceived(const std::vector<MediaSink>& sinks) = 0;
private:
- const base::Optional<const MediaSource> source_;
+ const absl::optional<const MediaSource> source_;
const url::Origin origin_;
MediaRouter* const router_;
bool initialized_;
diff --git a/chromium/components/media_router/browser/presentation/local_presentation_manager.h b/chromium/components/media_router/browser/presentation/local_presentation_manager.h
index aad2cfcd84c..4febd05de84 100644
--- a/chromium/components/media_router/browser/presentation/local_presentation_manager.h
+++ b/chromium/components/media_router/browser/presentation/local_presentation_manager.h
@@ -11,7 +11,6 @@
#include <unordered_map>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/media_router/common/media_route.h"
@@ -19,6 +18,7 @@
#include "content/public/browser/presentation_service_delegate.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
namespace content {
@@ -207,7 +207,7 @@ class LocalPresentationManager : public KeyedService {
bool IsValid() const;
const blink::mojom::PresentationInfo presentation_info_;
- base::Optional<MediaRoute> route_;
+ absl::optional<MediaRoute> route_;
content::WebContents* receiver_web_contents_ = nullptr;
// Callback to invoke whenever a receiver connection is available.
diff --git a/chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.cc b/chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.cc
index 854ecd93a75..27e85327537 100644
--- a/chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.cc
+++ b/chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.cc
@@ -710,7 +710,7 @@ bool PresentationServiceDelegateImpl::ShouldCancelAutoJoinForOrigin(
user_prefs::UserPrefs::Get(web_contents_->GetBrowserContext())
->GetList(prefs::kMediaRouterTabMirroringSources);
return origins &&
- origins->Find(base::Value(origin.Serialize())) != origins->end();
+ base::Contains(origins->GetList(), base::Value(origin.Serialize()));
}
#endif // !defined(OS_ANDROID)
diff --git a/chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.h b/chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.h
index a243f8ab2ac..894ba3b5dfa 100644
--- a/chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.h
+++ b/chromium/components/media_router/browser/presentation/presentation_service_delegate_impl.h
@@ -15,7 +15,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/media_router/browser/media_router.h"
#include "components/media_router/browser/presentation/presentation_service_delegate_observers.h"
@@ -27,6 +26,7 @@
#include "content/public/browser/presentation_service_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class PresentationScreenAvailabilityListener;
@@ -238,7 +238,7 @@ class PresentationServiceDelegateImpl
presentation_observers_;
// Default presentation request for the owning WebContents.
- base::Optional<content::PresentationRequest> default_presentation_request_;
+ absl::optional<content::PresentationRequest> default_presentation_request_;
// Callback to invoke when the default presentation has started.
content::DefaultPresentationConnectionCallback
diff --git a/chromium/components/media_router/browser/presentation/start_presentation_context.h b/chromium/components/media_router/browser/presentation/start_presentation_context.h
index f47fa7fdbf7..4ea2eca2fd2 100644
--- a/chromium/components/media_router/browser/presentation/start_presentation_context.h
+++ b/chromium/components/media_router/browser/presentation/start_presentation_context.h
@@ -9,7 +9,6 @@
#include "components/media_router/common/mojom/media_router.mojom-forward.h"
#include "content/public/browser/presentation_request.h"
#include "content/public/browser/presentation_service_delegate.h"
-#include "third_party/blink/public/mojom/presentation/presentation.mojom-forward.h"
namespace content {
struct PresentationRequest;
diff --git a/chromium/components/media_router/browser/route_message_observer.h b/chromium/components/media_router/browser/route_message_observer.h
index 8c2452de015..675b5030782 100644
--- a/chromium/components/media_router/browser/route_message_observer.h
+++ b/chromium/components/media_router/browser/route_message_observer.h
@@ -7,7 +7,6 @@
#include <stdint.h>
-#include <string>
#include <vector>
#include "base/macros.h"
diff --git a/chromium/components/media_router/common/media_route.cc b/chromium/components/media_router/common/media_route.cc
index 788e3f06e98..6986549d82a 100644
--- a/chromium/components/media_router/common/media_route.cc
+++ b/chromium/components/media_router/common/media_route.cc
@@ -98,7 +98,8 @@ bool MediaRoute::operator==(const MediaRoute& other) const {
controller_type_ == other.controller_type_ &&
for_display_ == other.for_display_ &&
is_off_the_record_ == other.is_off_the_record_ &&
- is_local_presentation_ == other.is_local_presentation_;
+ is_local_presentation_ == other.is_local_presentation_ &&
+ is_connecting_ == other.is_connecting_;
}
std::ostream& operator<<(std::ostream& stream, const MediaRoute& route) {
diff --git a/chromium/components/media_router/common/media_route.h b/chromium/components/media_router/common/media_route.h
index 6dc06d9fe62..d4521edc3ba 100644
--- a/chromium/components/media_router/common/media_route.h
+++ b/chromium/components/media_router/common/media_route.h
@@ -8,7 +8,6 @@
#include <iosfwd>
#include <string>
-#include "base/values.h"
#include "components/media_router/common/media_sink.h"
#include "components/media_router/common/media_source.h"
@@ -110,6 +109,9 @@ class MediaRoute {
}
bool is_local_presentation() const { return is_local_presentation_; }
+ void set_is_connecting(bool is_connecting) { is_connecting_ = is_connecting; }
+ bool is_connecting() const { return is_connecting_; }
+
bool operator==(const MediaRoute& other) const;
private:
@@ -151,6 +153,10 @@ class MediaRoute {
// |true| if the presentation associated with this route is a local
// presentation.
bool is_local_presentation_ = false;
+
+ // |true| if the route is created by the MRP but is waiting for receivers'
+ // response.
+ bool is_connecting_ = false;
};
} // namespace media_router
diff --git a/chromium/components/media_router/common/media_route_provider_helper.h b/chromium/components/media_router/common/media_route_provider_helper.h
index 7e9b667a896..d4bb2a7486a 100644
--- a/chromium/components/media_router/common/media_route_provider_helper.h
+++ b/chromium/components/media_router/common/media_route_provider_helper.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_MEDIA_ROUTER_COMMON_MEDIA_ROUTE_PROVIDER_HELPER_H_
#define COMPONENTS_MEDIA_ROUTER_COMMON_MEDIA_ROUTE_PROVIDER_HELPER_H_
-#include <string>
-
#include "base/strings/string_piece_forward.h"
namespace media_router {
diff --git a/chromium/components/media_router/common/media_sink.cc b/chromium/components/media_router/common/media_sink.cc
index ef5eb14bbe9..d0a51671309 100644
--- a/chromium/components/media_router/common/media_sink.cc
+++ b/chromium/components/media_router/common/media_sink.cc
@@ -26,17 +26,6 @@ MediaSink::~MediaSink() = default;
MediaSink& MediaSink::operator=(const MediaSink& other) = default;
MediaSink& MediaSink::operator=(MediaSink&& other) noexcept = default;
-bool MediaSink::IsMaybeCloudSink() const {
- switch (icon_type_) {
- case SinkIconType::MEETING:
- case SinkIconType::HANGOUT:
- case SinkIconType::EDUCATION:
- return true;
- default:
- return false;
- }
-}
-
bool MediaSink::operator==(const MediaSink& other) const {
return sink_id_ == other.sink_id_ && name_ == other.name_ &&
description_ == other.description_ && domain_ == other.domain_ &&
diff --git a/chromium/components/media_router/common/media_sink.h b/chromium/components/media_router/common/media_sink.h
index 24994a94707..e50aad9a588 100644
--- a/chromium/components/media_router/common/media_sink.h
+++ b/chromium/components/media_router/common/media_sink.h
@@ -7,8 +7,8 @@
#include <string>
-#include "base/optional.h"
#include "components/media_router/common/media_route_provider_helper.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/icu/source/common/unicode/uversion.h"
namespace U_ICU_NAMESPACE {
@@ -18,8 +18,8 @@ class Collator;
namespace media_router {
// IconTypes are listed in the order in which sinks should be sorted.
-// The order must stay in sync with
-// chrome/browser/resources/media_router/media_router_data.js.
+// The values must match media_router::mojom::SinkIconType and
+// ash::SinkIconType.
//
// NOTE: This enum is used for recording the MediaRouter.Sink.SelectedType
// metrics, so if we want to reorder it, we must create a separate enum that
@@ -29,9 +29,6 @@ enum class SinkIconType {
CAST = 0,
CAST_AUDIO_GROUP = 1,
CAST_AUDIO = 2,
- MEETING = 3,
- HANGOUT = 4,
- EDUCATION = 5,
WIRED_DISPLAY = 6,
GENERIC = 7,
TOTAL_COUNT = 8 // Add new types above this line.
@@ -65,12 +62,12 @@ class MediaSink {
void set_description(const std::string& description) {
description_ = description;
}
- const base::Optional<std::string>& description() const {
+ const absl::optional<std::string>& description() const {
return description_;
}
void set_domain(const std::string& domain) { domain_ = domain; }
- const base::Optional<std::string>& domain() const { return domain_; }
+ const absl::optional<std::string>& domain() const { return domain_; }
void set_icon_type(SinkIconType icon_type) { icon_type_ = icon_type; }
SinkIconType icon_type() const { return icon_type_; }
@@ -80,10 +77,6 @@ class MediaSink {
}
MediaRouteProviderId provider_id() const { return provider_id_; }
- // Returns true if the sink is from the Cloud MRP; however, as this is based
- // solely on the icon type, is not guaranteed to be correct 100% of the time.
- bool IsMaybeCloudSink() const;
-
bool operator==(const MediaSink& other) const;
bool operator!=(const MediaSink& other) const;
@@ -100,10 +93,10 @@ class MediaSink {
std::string name_;
// Optional description of the MediaSink.
- base::Optional<std::string> description_;
+ absl::optional<std::string> description_;
// Optional domain of the MediaSink.
- base::Optional<std::string> domain_;
+ absl::optional<std::string> domain_;
// The type of icon that corresponds with the MediaSink.
SinkIconType icon_type_ = SinkIconType::GENERIC;
diff --git a/chromium/components/media_router/common/media_sink_unittest.cc b/chromium/components/media_router/common/media_sink_unittest.cc
index b38557b4d75..9fb9cb238fa 100644
--- a/chromium/components/media_router/common/media_sink_unittest.cc
+++ b/chromium/components/media_router/common/media_sink_unittest.cc
@@ -8,19 +8,6 @@
namespace media_router {
-TEST(MediaSinkTest, IsMaybeCloudSink) {
- MediaSink meeting("sinkId", "Sink", SinkIconType::MEETING,
- MediaRouteProviderId::EXTENSION);
- MediaSink eduReceiver("sinkId2", "Sink", SinkIconType::EDUCATION,
- MediaRouteProviderId::EXTENSION);
- MediaSink chromeCast("sinkId3", "Sink", SinkIconType::CAST,
- MediaRouteProviderId::EXTENSION);
-
- EXPECT_TRUE(meeting.IsMaybeCloudSink());
- EXPECT_TRUE(eduReceiver.IsMaybeCloudSink());
- EXPECT_FALSE(chromeCast.IsMaybeCloudSink());
-}
-
TEST(MediaSinkTest, TestEquals) {
MediaSink sink1("sinkId", "Sink", SinkIconType::CAST,
MediaRouteProviderId::EXTENSION);
diff --git a/chromium/components/media_router/common/media_source.cc b/chromium/components/media_router/common/media_source.cc
index 407f5266ac9..4d9c56af23d 100644
--- a/chromium/components/media_router/common/media_source.cc
+++ b/chromium/components/media_router/common/media_source.cc
@@ -10,6 +10,7 @@
#include <ostream>
#include <string>
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "components/media_router/common/media_source.h"
@@ -113,16 +114,16 @@ MediaSource MediaSource::ForDesktop(
bool with_audio) {
DCHECK(!registered_desktop_stream_id.empty());
std::string id =
- kDesktopMediaUrnPrefix.as_string() + registered_desktop_stream_id;
+ std::string(kDesktopMediaUrnPrefix) + registered_desktop_stream_id;
if (with_audio) {
- id += kDesktopMediaUrnAudioParam.as_string();
+ id += std::string(kDesktopMediaUrnAudioParam);
}
return MediaSource(id);
}
// static
MediaSource MediaSource::ForUnchosenDesktop() {
- return MediaSource(kUnchosenDesktopMediaUrn.as_string());
+ return MediaSource(std::string(kUnchosenDesktopMediaUrn));
}
// static
@@ -156,7 +157,7 @@ int MediaSource::TabId() const {
return tab_id;
}
-base::Optional<std::string> MediaSource::DesktopStreamId() const {
+absl::optional<std::string> MediaSource::DesktopStreamId() const {
if (base::StartsWith(id_, kDesktopMediaUrnPrefix,
base::CompareCase::SENSITIVE)) {
const auto begin = id_.begin() + kDesktopMediaUrnPrefix.size();
@@ -167,7 +168,7 @@ base::Optional<std::string> MediaSource::DesktopStreamId() const {
}
return std::string(begin, end);
}
- return base::nullopt;
+ return absl::nullopt;
}
bool MediaSource::IsDesktopSourceWithAudio() const {
diff --git a/chromium/components/media_router/common/media_source.h b/chromium/components/media_router/common/media_source.h
index 2abc3648ce5..2e264d49f54 100644
--- a/chromium/components/media_router/common/media_source.h
+++ b/chromium/components/media_router/common/media_source.h
@@ -132,8 +132,8 @@ class MediaSource {
// When this source was created by ForDesktop(), returns the stream ID to pass
// to content::DesktopStreamsRegistry::RequestMediaForStreamId(). Otherwise,
- // returns base::nullopt.
- base::Optional<std::string> DesktopStreamId() const;
+ // returns absl::nullopt.
+ absl::optional<std::string> DesktopStreamId() const;
// Returns true if this source represents desktop capture that also provides
// audio loopback capture. Returns false otherwise.
diff --git a/chromium/components/media_router/common/mojom/media_router.mojom b/chromium/components/media_router/common/mojom/media_router.mojom
index a423f79b60e..86f3eac90f0 100644
--- a/chromium/components/media_router/common/mojom/media_router.mojom
+++ b/chromium/components/media_router/common/mojom/media_router.mojom
@@ -15,16 +15,13 @@ import "third_party/blink/public/mojom/presentation/presentation.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";
-// This must stay in sync with ash.mojom.SinkIconType.
+// This must stay in sync with media_router::SinkIconType and ash::SinkIconType.
enum SinkIconType {
- CAST,
- CAST_AUDIO_GROUP,
- CAST_AUDIO,
- MEETING,
- HANGOUT,
- EDUCATION,
- WIRED_DISPLAY,
- GENERIC
+ CAST = 0,
+ CAST_AUDIO_GROUP = 1,
+ CAST_AUDIO = 2,
+ WIRED_DISPLAY = 6,
+ GENERIC = 7
};
// Represents an output sink to which media can be routed.
@@ -126,6 +123,9 @@ struct MediaRoute {
bool is_off_the_record;
// Set to true if this route corresponds to a local presentation.
bool is_local_presentation;
+ // Set to true if this route has been created by the MRP but is waiting for
+ // the receiver's response.
+ bool is_connecting;
};
// Notifications or an actionable events to be shown to the user.
diff --git a/chromium/components/media_router/common/mojom/media_router_mojom_traits.cc b/chromium/components/media_router/common/mojom/media_router_mojom_traits.cc
index 0cc98937e7f..886bc958dc2 100644
--- a/chromium/components/media_router/common/mojom/media_router_mojom_traits.cc
+++ b/chromium/components/media_router/common/mojom/media_router_mojom_traits.cc
@@ -25,7 +25,7 @@ bool StructTraits<media_router::mojom::IssueDataView, media_router::IssueInfo>::
if (!data.ReadSeverity(&out->severity))
return false;
- base::Optional<std::string> message;
+ absl::optional<std::string> message;
if (!data.ReadMessage(&message))
return false;
@@ -81,14 +81,14 @@ bool StructTraits<media_router::mojom::MediaSinkDataView,
out->sink().set_name(name);
- base::Optional<std::string> description;
+ absl::optional<std::string> description;
if (!data.ReadDescription(&description))
return false;
if (description)
out->sink().set_description(*description);
- base::Optional<std::string> domain;
+ absl::optional<std::string> domain;
if (!data.ReadDomain(&domain))
return false;
@@ -189,7 +189,7 @@ bool StructTraits<media_router::mojom::MediaRouteDataView,
return false;
out->set_presentation_id(presentation_id);
- base::Optional<media_router::MediaSource::Id> media_source_id;
+ absl::optional<media_router::MediaSource::Id> media_source_id;
if (!data.ReadMediaSource(&media_source_id))
return false;
if (media_source_id)
@@ -219,6 +219,7 @@ bool StructTraits<media_router::mojom::MediaRouteDataView,
out->set_for_display(data.for_display());
out->set_off_the_record(data.is_off_the_record());
out->set_local_presentation(data.is_local_presentation());
+ out->set_is_connecting(data.is_connecting());
return true;
}
diff --git a/chromium/components/media_router/common/mojom/media_router_mojom_traits.h b/chromium/components/media_router/common/mojom/media_router_mojom_traits.h
index 80a77f4d58e..d0e10e6435f 100644
--- a/chromium/components/media_router/common/mojom/media_router_mojom_traits.h
+++ b/chromium/components/media_router/common/mojom/media_router_mojom_traits.h
@@ -215,12 +215,6 @@ struct EnumTraits<media_router::mojom::SinkIconType,
return media_router::mojom::SinkIconType::CAST_AUDIO_GROUP;
case media_router::SinkIconType::CAST_AUDIO:
return media_router::mojom::SinkIconType::CAST_AUDIO;
- case media_router::SinkIconType::MEETING:
- return media_router::mojom::SinkIconType::MEETING;
- case media_router::SinkIconType::HANGOUT:
- return media_router::mojom::SinkIconType::HANGOUT;
- case media_router::SinkIconType::EDUCATION:
- return media_router::mojom::SinkIconType::EDUCATION;
case media_router::SinkIconType::WIRED_DISPLAY:
return media_router::mojom::SinkIconType::WIRED_DISPLAY;
case media_router::SinkIconType::GENERIC:
@@ -244,15 +238,6 @@ struct EnumTraits<media_router::mojom::SinkIconType,
case media_router::mojom::SinkIconType::CAST_AUDIO:
*output = media_router::SinkIconType::CAST_AUDIO;
return true;
- case media_router::mojom::SinkIconType::MEETING:
- *output = media_router::SinkIconType::MEETING;
- return true;
- case media_router::mojom::SinkIconType::HANGOUT:
- *output = media_router::SinkIconType::HANGOUT;
- return true;
- case media_router::mojom::SinkIconType::EDUCATION:
- *output = media_router::SinkIconType::EDUCATION;
- return true;
case media_router::mojom::SinkIconType::WIRED_DISPLAY:
*output = media_router::SinkIconType::WIRED_DISPLAY;
return true;
@@ -280,12 +265,12 @@ struct StructTraits<media_router::mojom::MediaSinkDataView,
return sink_internal.sink().name();
}
- static const base::Optional<std::string>& description(
+ static const absl::optional<std::string>& description(
const media_router::MediaSinkInternal& sink_internal) {
return sink_internal.sink().description();
}
- static const base::Optional<std::string>& domain(
+ static const absl::optional<std::string>& domain(
const media_router::MediaSinkInternal& sink_internal) {
return sink_internal.sink().domain();
}
@@ -359,15 +344,15 @@ struct StructTraits<media_router::mojom::MediaRouteDataView,
return route.presentation_id();
}
- static base::Optional<std::string> media_source(
+ static absl::optional<std::string> media_source(
const media_router::MediaRoute& route) {
// TODO(imcheng): If we ever convert from C++ to Mojo outside of unit tests,
// it would be better to make the |media_source_| field on MediaRoute a
- // base::Optional<MediaSource::Id> instead so it can be returned directly
+ // absl::optional<MediaSource::Id> instead so it can be returned directly
// here.
return route.media_source().id().empty()
- ? base::Optional<std::string>()
- : base::make_optional(route.media_source().id());
+ ? absl::optional<std::string>()
+ : absl::make_optional(route.media_source().id());
}
static const std::string& media_sink_id(
@@ -404,6 +389,10 @@ struct StructTraits<media_router::mojom::MediaRouteDataView,
static bool is_local_presentation(const media_router::MediaRoute& route) {
return route.is_local_presentation();
}
+
+ static bool is_connecting(const media_router::MediaRoute& route) {
+ return route.is_connecting();
+ }
};
// RouteRequestResultCode
diff --git a/chromium/components/media_router/common/providers/cast/cast_media_source.cc b/chromium/components/media_router/common/providers/cast/cast_media_source.cc
index e0e04d5c842..8cbdef61f21 100644
--- a/chromium/components/media_router/common/providers/cast/cast_media_source.cc
+++ b/chromium/components/media_router/common/providers/cast/cast_media_source.cc
@@ -91,8 +91,8 @@ constexpr int kMaxCastPresentationUrlLength = 64 * 1024;
namespace {
-// A nonmember version of base::Optional::value_or that works on pointers as
-// well as instance of base::Optional.
+// A nonmember version of absl::optional::value_or that works on pointers as
+// well as instance of absl::optional.
template <typename T>
inline auto value_or(const T& optional,
const std::decay_t<decltype(*optional)>& default_value)
diff --git a/chromium/components/media_router/common/providers/cast/cast_media_source.h b/chromium/components/media_router/common/providers/cast/cast_media_source.h
index fa4bdd07793..b569ab2ee88 100644
--- a/chromium/components/media_router/common/providers/cast/cast_media_source.h
+++ b/chromium/components/media_router/common/providers/cast/cast_media_source.h
@@ -12,10 +12,10 @@
#include <vector>
#include "base/check.h"
-#include "base/optional.h"
#include "components/cast_channel/cast_message_util.h"
#include "components/cast_channel/cast_socket.h"
#include "components/media_router/common/media_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using cast_channel::ReceiverAppType;
@@ -182,7 +182,7 @@ class CastMediaSource {
void set_launch_timeout(base::TimeDelta launch_timeout) {
launch_timeout_ = launch_timeout;
}
- const base::Optional<cast_channel::BroadcastRequest>& broadcast_request()
+ const absl::optional<cast_channel::BroadcastRequest>& broadcast_request()
const {
return broadcast_request_;
}
@@ -193,11 +193,11 @@ class CastMediaSource {
DefaultActionPolicy default_action_policy() const {
return default_action_policy_;
}
- base::Optional<base::TimeDelta> target_playout_delay() const {
+ absl::optional<base::TimeDelta> target_playout_delay() const {
return target_playout_delay_;
}
void set_target_playout_delay(
- const base::Optional<base::TimeDelta>& target_playout_delay) {
+ const absl::optional<base::TimeDelta>& target_playout_delay) {
target_playout_delay_ = target_playout_delay;
}
// See also: ProvidesStreamingAudioCapture().
@@ -231,8 +231,8 @@ class CastMediaSource {
base::TimeDelta launch_timeout_ = kDefaultLaunchTimeout;
// Optional parameters.
std::string client_id_;
- base::Optional<cast_channel::BroadcastRequest> broadcast_request_;
- base::Optional<base::TimeDelta> target_playout_delay_;
+ absl::optional<cast_channel::BroadcastRequest> broadcast_request_;
+ absl::optional<base::TimeDelta> target_playout_delay_;
bool site_requested_audio_capture_ = true;
std::vector<ReceiverAppType> supported_app_types_ = {ReceiverAppType::kWeb};
std::string app_params_;
diff --git a/chromium/components/media_router/common/providers/cast/cast_media_source_unittest.cc b/chromium/components/media_router/common/providers/cast/cast_media_source_unittest.cc
index 87ef561e0a2..2b7a5d9009f 100644
--- a/chromium/components/media_router/common/providers/cast/cast_media_source_unittest.cc
+++ b/chromium/components/media_router/common/providers/cast/cast_media_source_unittest.cc
@@ -31,7 +31,7 @@ TEST(CastMediaSourceTest, FromCastURLWithDefaults) {
EXPECT_EQ(DefaultActionPolicy::kCreateSession,
source->default_action_policy());
EXPECT_EQ(ReceiverAppType::kWeb, source->supported_app_types()[0]);
- EXPECT_EQ(base::nullopt, source->target_playout_delay());
+ EXPECT_EQ(absl::nullopt, source->target_playout_delay());
EXPECT_EQ(true, source->site_requested_audio_capture());
EXPECT_EQ(cast_channel::VirtualConnectionType::kStrong,
source->connection_type());
diff --git a/chromium/components/messages/android/BUILD.gn b/chromium/components/messages/android/BUILD.gn
index c1c76384e8b..e5e1056e8bb 100644
--- a/chromium/components/messages/android/BUILD.gn
+++ b/chromium/components/messages/android/BUILD.gn
@@ -7,6 +7,7 @@ import("//chrome/android/features/android_library_factory_tmpl.gni")
android_library("java") {
sources = [
+ "java/src/org/chromium/components/messages/MessageAutodismissDurationProvider.java",
"java/src/org/chromium/components/messages/MessageBannerProperties.java",
"java/src/org/chromium/components/messages/MessageContainer.java",
"java/src/org/chromium/components/messages/MessageDispatcher.java",
diff --git a/chromium/components/messages/android/internal/BUILD.gn b/chromium/components/messages/android/internal/BUILD.gn
index 76c28eb9177..818f79b6466 100644
--- a/chromium/components/messages/android/internal/BUILD.gn
+++ b/chromium/components/messages/android/internal/BUILD.gn
@@ -16,6 +16,7 @@ android_library("java") {
"java/src/org/chromium/components/messages/MessageScopeChange.java",
"java/src/org/chromium/components/messages/MessageStateHandler.java",
"java/src/org/chromium/components/messages/MessagesFactory.java",
+ "java/src/org/chromium/components/messages/MessagesMetrics.java",
"java/src/org/chromium/components/messages/ScopeChangeController.java",
"java/src/org/chromium/components/messages/ScopeKey.java",
"java/src/org/chromium/components/messages/SingleActionMessage.java",
diff --git a/chromium/components/messages/android/internal/java/res/layout/message_banner_view.xml b/chromium/components/messages/android/internal/java/res/layout/message_banner_view.xml
index d688c59b778..a3891f56246 100644
--- a/chromium/components/messages/android/internal/java/res/layout/message_banner_view.xml
+++ b/chromium/components/messages/android/internal/java/res/layout/message_banner_view.xml
@@ -11,35 +11,35 @@
android:layout_width="match_parent"
android:minHeight="@dimen/message_banner_height"
android:layout_gravity="center_horizontal"
+ android:gravity="center_vertical"
android:orientation="horizontal"
android:layout_marginTop="@dimen/message_shadow_top_margin"
android:layout_marginBottom="@dimen/message_shadow_bottom_margin"
android:layout_marginStart="@dimen/message_shadow_lateral_margin"
android:layout_marginEnd="@dimen/message_shadow_lateral_margin"
android:elevation="@dimen/message_banner_elevation"
- android:paddingTop="@dimen/message_banner_vertical_padding"
- android:paddingBottom="@dimen/message_banner_vertical_padding"
app:maxWidthPortrait="@dimen/message_max_width"
app:maxWidthLandscape="@dimen/message_max_width"
android:background="@drawable/message_bg_tinted">
<ImageView
android:id="@+id/message_icon"
+ app:tint="@color/default_icon_color_blue"
android:paddingStart="@dimen/message_icon_padding"
android:paddingEnd="@dimen/message_icon_padding"
- app:tint="@color/default_icon_color_blue"
- android:layout_weight="0"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
+ android:layout_height="24dp"
android:importantForAccessibility="no" />
<LinearLayout
android:layout_width="0dp"
- android:layout_weight="3"
+ android:layout_weight="1"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:orientation="vertical"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/message_banner_vertical_padding"
+ android:paddingBottom="@dimen/message_banner_vertical_padding">
<TextView
android:id="@+id/message_title"
@@ -58,7 +58,6 @@
<org.chromium.components.browser_ui.widget.listmenu.ListMenuButton
android:id="@+id/message_secondary_button"
app:tint="@color/default_icon_color_secondary"
- android:layout_weight="0"
android:paddingStart="@dimen/message_icon_padding"
android:paddingEnd="@dimen/message_icon_padding"
android:visibility="gone"
@@ -76,14 +75,18 @@
android:visibility="gone"
android:importantForAccessibility="no"
android:layout_width="1dp"
- android:layout_height="match_parent" />
+ android:layout_height="24dp" />
<org.chromium.ui.widget.ButtonCompat
style="@style/TextButton"
android:id="@+id/message_primary_button"
- android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
+ app:verticalInset="0dp"
+ app:rippleCornerRadiusTopStart="0dp"
+ app:rippleCornerRadiusBottomStart="0dp"
+ app:rippleCornerRadiusBottomEnd="@dimen/message_banner_radius"
+ app:rippleCornerRadiusTopEnd="@dimen/message_banner_radius"
+ android:layout_width="@dimen/button_min_width"
+ android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:visibility="gone" />
-</org.chromium.components.messages.MessageBannerView> \ No newline at end of file
+</org.chromium.components.messages.MessageBannerView>
diff --git a/chromium/components/messages/android/internal/java/res/values/dimens.xml b/chromium/components/messages/android/internal/java/res/values/dimens.xml
index b0394de8a75..6126cab4ccb 100644
--- a/chromium/components/messages/android/internal/java/res/values/dimens.xml
+++ b/chromium/components/messages/android/internal/java/res/values/dimens.xml
@@ -5,7 +5,7 @@
<resources>
- <dimen name="message_banner_height">64dp</dimen>
+ <dimen name="message_banner_height">72dp</dimen>
<dimen name="message_banner_radius">12dp</dimen>
<dimen name="message_banner_vertical_padding">12dp</dimen>
<dimen name="message_banner_elevation">6dp</dimen>
@@ -20,4 +20,4 @@
<dimen name="message_max_horizontal_translation">360dp</dimen>
<dimen name="message_max_width">380dp</dimen>
-</resources> \ No newline at end of file
+</resources>
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerMediatorUnitTest.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerMediatorUnitTest.java
index b08b9cac526..5511997fbac 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerMediatorUnitTest.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerMediatorUnitTest.java
@@ -67,6 +67,8 @@ public class MessageBannerMediatorUnitTest {
@Before
public void setUp() {
mModel = new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
+ .with(MessageBannerProperties.MESSAGE_IDENTIFIER,
+ MessageIdentifier.TEST_MESSAGE)
.with(MessageBannerProperties.TITLE, "Title")
.with(MessageBannerProperties.DESCRIPTION, "Desc")
.build();
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerRenderTest.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerRenderTest.java
index c0851af3f89..01b65550b44 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerRenderTest.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerRenderTest.java
@@ -60,6 +60,8 @@ public class MessageBannerRenderTest extends DummyUiActivityTestCase {
Drawable drawable = ApiCompatibilityUtils.getDrawable(
activity.getResources(), android.R.drawable.ic_delete);
PropertyModel model = new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
+ .with(MessageBannerProperties.MESSAGE_IDENTIFIER,
+ MessageIdentifier.TEST_MESSAGE)
.with(MessageBannerProperties.ICON, drawable)
.with(MessageBannerProperties.TITLE, "Primary Title")
.with(MessageBannerProperties.DESCRIPTION, "Secondary Title")
@@ -86,6 +88,8 @@ public class MessageBannerRenderTest extends DummyUiActivityTestCase {
Drawable drawable2 = ApiCompatibilityUtils.getDrawable(
activity.getResources(), android.R.drawable.ic_btn_speak_now);
PropertyModel model = new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
+ .with(MessageBannerProperties.MESSAGE_IDENTIFIER,
+ MessageIdentifier.TEST_MESSAGE)
.with(MessageBannerProperties.ICON, drawable)
.with(MessageBannerProperties.TITLE, "Primary Title")
.with(MessageBannerProperties.DESCRIPTION, "Secondary Title")
@@ -114,6 +118,8 @@ public class MessageBannerRenderTest extends DummyUiActivityTestCase {
StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);
spannable.setSpan(boldSpan, 0, spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
PropertyModel model = new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
+ .with(MessageBannerProperties.MESSAGE_IDENTIFIER,
+ MessageIdentifier.TEST_MESSAGE)
.with(MessageBannerProperties.ICON, drawable)
.with(MessageBannerProperties.TITLE, "Primary Title")
.with(MessageBannerProperties.DESCRIPTION, spannable)
@@ -129,4 +135,30 @@ public class MessageBannerRenderTest extends DummyUiActivityTestCase {
() -> { getActivity().setContentView(view, params); });
mRenderTestRule.render(view, "message_banner_basic_with_spannable_description");
}
+
+ @Test
+ @SmallTest
+ @Feature({"RenderTest", "Messages"})
+ public void testBasic_multilineDescriptionMaxLines() throws Exception {
+ Activity activity = getActivity();
+ final String multilineDescription = "Line 1\nLine 2\nLine 3\nLine 4";
+ PropertyModel model =
+ new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
+ .with(MessageBannerProperties.MESSAGE_IDENTIFIER,
+ MessageIdentifier.TEST_MESSAGE)
+ .with(MessageBannerProperties.TITLE, "Primary Title")
+ .with(MessageBannerProperties.DESCRIPTION, multilineDescription)
+ .with(MessageBannerProperties.DESCRIPTION_MAX_LINES, 2)
+ .with(MessageBannerProperties.PRIMARY_BUTTON_TEXT, "Action")
+ .build();
+ MessageBannerView view = (MessageBannerView) LayoutInflater.from(activity).inflate(
+ R.layout.message_banner_view, null, false);
+ PropertyModelChangeProcessor.create(model, view, MessageBannerViewBinder::bind);
+ LayoutParams params =
+ new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+
+ TestThreadUtils.runOnUiThreadBlocking(
+ () -> { getActivity().setContentView(view, params); });
+ mRenderTestRule.render(view, "message_banner_basic_with_multiline_description");
+ }
} \ No newline at end of file
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerView.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerView.java
index 7615ef133ab..8d882ec77ee 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerView.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerView.java
@@ -8,6 +8,7 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -70,6 +71,11 @@ public class MessageBannerView extends BoundedLinearLayout {
mDescription.setText(description);
}
+ void setDescriptionMaxLines(int maxLines) {
+ mDescription.setMaxLines(maxLines);
+ mDescription.setEllipsize(TextUtils.TruncateAt.END);
+ }
+
void setIcon(Drawable icon) {
mIconView.setImageDrawable(icon);
}
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewBinder.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewBinder.java
index f4b147f7bdc..988c5a03255 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewBinder.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewBinder.java
@@ -6,6 +6,7 @@ package org.chromium.components.messages;
import static org.chromium.components.messages.MessageBannerProperties.ALPHA;
import static org.chromium.components.messages.MessageBannerProperties.DESCRIPTION;
+import static org.chromium.components.messages.MessageBannerProperties.DESCRIPTION_MAX_LINES;
import static org.chromium.components.messages.MessageBannerProperties.ICON;
import static org.chromium.components.messages.MessageBannerProperties.ICON_RESOURCE_ID;
import static org.chromium.components.messages.MessageBannerProperties.ICON_TINT_COLOR;
@@ -42,6 +43,8 @@ public class MessageBannerViewBinder {
view.setTitle(model.get(TITLE));
} else if (propertyKey == DESCRIPTION) {
view.setDescription(model.get(DESCRIPTION));
+ } else if (propertyKey == DESCRIPTION_MAX_LINES) {
+ view.setDescriptionMaxLines(model.get(DESCRIPTION_MAX_LINES));
} else if (propertyKey == ICON) {
view.setIcon(model.get(ICON));
} else if (propertyKey == ICON_RESOURCE_ID) {
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewTest.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewTest.java
index 6b54d689479..360a4ce7f84 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewTest.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewTest.java
@@ -92,6 +92,8 @@ public class MessageBannerViewTest {
public void testSecondaryActionDirectCallback() {
PropertyModel propertyModel =
new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
+ .with(MessageBannerProperties.MESSAGE_IDENTIFIER,
+ MessageIdentifier.TEST_MESSAGE)
.with(MessageBannerProperties.SECONDARY_ICON_RESOURCE_ID,
android.R.drawable.ic_menu_add)
.with(MessageBannerProperties.ON_SECONDARY_ACTION, mSecondaryActionCallback)
@@ -114,6 +116,8 @@ public class MessageBannerViewTest {
public void testSecondaryActionMenu() {
PropertyModel propertyModel =
new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
+ .with(MessageBannerProperties.MESSAGE_IDENTIFIER,
+ MessageIdentifier.TEST_MESSAGE)
.with(MessageBannerProperties.SECONDARY_ICON_RESOURCE_ID,
android.R.drawable.ic_menu_add)
.with(MessageBannerProperties.SECONDARY_BUTTON_MENU_TEXT,
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageDispatcherImpl.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageDispatcherImpl.java
index 55ad554835a..3173de49ce9 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageDispatcherImpl.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageDispatcherImpl.java
@@ -19,7 +19,7 @@ public class MessageDispatcherImpl implements ManagedMessageDispatcher {
private final MessageQueueManager mMessageQueueManager = new MessageQueueManager();
private final MessageContainer mMessageContainer;
private final Supplier<Integer> mMessageMaxTranslationSupplier;
- private final Supplier<Long> mAutodismissDurationMs;
+ private final MessageAutodismissDurationProvider mAutodismissDurationProvider;
private final Callback<Animator> mAnimatorStartCallback;
/**
@@ -27,29 +27,30 @@ public class MessageDispatcherImpl implements ManagedMessageDispatcher {
* @param messageContainer A container view for displaying message banners.
* @param messageMaxTranslation A {@link Supplier} that supplies the maximum translation Y value
* the message banner can have as a result of the animations or the gestures.
- * @param autodismissDurationMs A {@link Supplier} providing autodismiss duration for message
- * banner.
+ * @param autodismissDurationProvider A {@link MessageAutodismissDurationProvider} providing
+ * autodismiss duration for message banner.
* @param animatorStartCallback The {@link Callback} that will be used by the message to
* delegate starting the animations to the {@link WindowAndroid}.
*/
public MessageDispatcherImpl(MessageContainer messageContainer,
- Supplier<Integer> messageMaxTranslation, Supplier<Long> autodismissDurationMs,
+ Supplier<Integer> messageMaxTranslation,
+ MessageAutodismissDurationProvider autodismissDurationProvider,
Callback<Animator> animatorStartCallback) {
mMessageContainer = messageContainer;
mMessageMaxTranslationSupplier = messageMaxTranslation;
mAnimatorStartCallback = animatorStartCallback;
- mAutodismissDurationMs = autodismissDurationMs;
+ mAutodismissDurationProvider = autodismissDurationProvider;
}
@Override
public void enqueueMessage(PropertyModel messageProperties, WebContents webContents,
- @MessageScopeType int scopeType) {
+ @MessageScopeType int scopeType, boolean highPriority) {
MessageStateHandler messageStateHandler = new SingleActionMessage(mMessageContainer,
messageProperties, this::dismissMessage, mMessageMaxTranslationSupplier,
- mAutodismissDurationMs, mAnimatorStartCallback);
+ mAutodismissDurationProvider, mAnimatorStartCallback);
ScopeKey scopeKey = new ScopeKey(scopeType, webContents);
mMessageQueueManager.enqueueMessage(
- messageStateHandler, messageProperties, scopeType, scopeKey);
+ messageStateHandler, messageProperties, scopeKey, highPriority);
}
@Override
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManager.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManager.java
index df13286a5f9..1e82fc7507d 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManager.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManager.java
@@ -59,11 +59,11 @@ class MessageQueueManager implements ScopeChangeController.Delegate {
* message. Displays the message if there is no other message shown.
* @param message The message to enqueue
* @param messageKey The key to associate with this message.
- * @param scopeType The type of scope.
* @param scopeKey The key of a scope instance.
+ * @param highPriority True if the message should be displayed ASAP.
*/
- public void enqueueMessage(
- MessageStateHandler message, Object messageKey, int scopeType, ScopeKey scopeKey) {
+ public void enqueueMessage(MessageStateHandler message, Object messageKey, ScopeKey scopeKey,
+ boolean highPriority) {
if (mMessages.containsKey(messageKey)) {
throw new IllegalStateException("Message with the given key has already been enqueued");
}
@@ -75,11 +75,12 @@ class MessageQueueManager implements ScopeChangeController.Delegate {
mScopeChangeController.firstMessageEnqueued(scopeKey);
}
- MessageState messageState = new MessageState(scopeKey, messageKey, message);
+ MessageState messageState = new MessageState(scopeKey, messageKey, message, highPriority);
messageQueue.add(messageState);
mMessages.put(messageKey, messageState);
updateCurrentDisplayedMessage();
+ MessagesMetrics.recordMessageEnqueued(message.getMessageIdentifier());
}
/**
@@ -114,15 +115,12 @@ class MessageQueueManager implements ScopeChangeController.Delegate {
}
if (mCurrentDisplayedMessage == messageState) {
- mCurrentDisplayedMessage.handler.hide(updateCurrentMessage, () -> {
- mMessageQueueDelegate.onFinishHiding();
- mCurrentDisplayedMessage = null;
- message.dismiss(dismissReason);
- if (updateCurrentMessage) updateCurrentDisplayedMessage();
- });
+ hideMessage(updateCurrentMessage,
+ () -> message.dismiss(dismissReason), updateCurrentMessage);
} else {
message.dismiss(dismissReason);
}
+ MessagesMetrics.recordDismissReason(message.getMessageIdentifier(), dismissReason);
}
public int suspend() {
@@ -148,8 +146,7 @@ class MessageQueueManager implements ScopeChangeController.Delegate {
if (messages != null) {
while (!messages.isEmpty()) {
// message will be removed from messages list.
- dismissMessage(messages.get(0).messageKey,
- org.chromium.components.messages.DismissReason.SCOPE_DESTROYED);
+ dismissMessage(messages.get(0).messageKey, DismissReason.SCOPE_DESTROYED);
}
}
} else if (change.changeType == ChangeType.INACTIVE) {
@@ -180,15 +177,10 @@ class MessageQueueManager implements ScopeChangeController.Delegate {
mMessageQueueDelegate.onStartShowing(mCurrentDisplayedMessage.handler::show);
}
} else if (mCurrentDisplayedMessage != null) {
- // Scope state may be removed if it has been destroyed.
- boolean isScopeActive = mScopeStates.containsKey(mCurrentDisplayedMessage.scopeKey)
- && mScopeStates.get(mCurrentDisplayedMessage.scopeKey);
- if (isQueueSuspended() || !isScopeActive) {
- mCurrentDisplayedMessage.handler.hide(
- !isQueueSuspended() && animateTransition, () -> {
- mMessageQueueDelegate.onFinishHiding();
- mCurrentDisplayedMessage = null;
- });
+ MessageState candidate = getNextMessage();
+ // Another higher priority message has been enqueued.
+ if (candidate != mCurrentDisplayedMessage || isQueueSuspended()) {
+ hideMessage(!isQueueSuspended() && animateTransition, null, !isQueueSuspended());
}
}
}
@@ -208,6 +200,16 @@ class MessageQueueManager implements ScopeChangeController.Delegate {
return mMessages;
}
+ private void hideMessage(
+ boolean animate, Runnable dismissAfterHiding, boolean updateCurrentMessage) {
+ mCurrentDisplayedMessage.handler.hide(animate, () -> {
+ mMessageQueueDelegate.onFinishHiding();
+ mCurrentDisplayedMessage = null;
+ if (dismissAfterHiding != null) dismissAfterHiding.run();
+ if (updateCurrentMessage) updateCurrentDisplayedMessage(true);
+ });
+ }
+
/**
* Iterate the queues of each scope to get the next messages. If multiple messages meet the
* requirements, which can show in the given scope, then the message queued earliest will be
@@ -217,10 +219,14 @@ class MessageQueueManager implements ScopeChangeController.Delegate {
MessageState nextMessage = null;
for (List<MessageState> queue : mMessageQueues.values()) {
if (queue.isEmpty()) continue;
- MessageState candidate = queue.get(0);
- Boolean isActive = mScopeStates.get(candidate.scopeKey);
+ Boolean isActive = mScopeStates.get(queue.get(0).scopeKey);
if (isActive == null || !isActive) continue;
- if (nextMessage == null || candidate.id < nextMessage.id) nextMessage = candidate;
+ for (MessageState candidate : queue) {
+ if (nextMessage == null || (candidate.highPriority && !nextMessage.highPriority)
+ || candidate.id < nextMessage.id) {
+ nextMessage = candidate;
+ }
+ }
}
return nextMessage;
}
@@ -233,11 +239,14 @@ class MessageQueueManager implements ScopeChangeController.Delegate {
public final ScopeKey scopeKey;
public final Object messageKey;
public final MessageStateHandler handler;
+ public final boolean highPriority;
- MessageState(ScopeKey scopeKey, Object messageKey, MessageStateHandler handler) {
+ MessageState(ScopeKey scopeKey, Object messageKey, MessageStateHandler handler,
+ boolean highPriority) {
this.scopeKey = scopeKey;
this.messageKey = messageKey;
this.handler = handler;
+ this.highPriority = highPriority;
id = sIdNext++;
}
}
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java
index b6a00730d7f..44166052140 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java
@@ -21,11 +21,14 @@ import android.os.Build;
import androidx.test.filters.SmallTest;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
+import org.robolectric.annotation.Config;
import org.chromium.base.ActivityState;
+import org.chromium.base.metrics.test.ShadowRecordHistogram;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.DisableIf;
import org.chromium.components.messages.MessageScopeChange.ChangeType;
@@ -37,6 +40,7 @@ import org.chromium.ui.base.WindowAndroid;
* Unit tests for MessageQueueManager.
*/
@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {ShadowRecordHistogram.class})
public class MessageQueueManagerTest {
private MessageQueueDelegate mEmptyDelegate = new MessageQueueDelegate() {
@Override
@@ -59,6 +63,11 @@ public class MessageQueueManagerTest {
@Override
public void dismiss(@DismissReason int dismissReason) {}
+
+ @Override
+ public int getMessageIdentifier() {
+ return MessageIdentifier.TEST_MESSAGE;
+ }
}
private static class InactiveMockWebContents extends MockWebContents {
@@ -87,6 +96,11 @@ public class MessageQueueManagerTest {
private static final ScopeKey SCOPE_INSTANCE_ID_A =
new ScopeKey(SCOPE_TYPE, new MockWebContents());
+ @Before
+ public void setUp() {
+ ShadowRecordHistogram.reset();
+ }
+
/**
* Tests lifecycle of a single message:
* - enqueueMessage() calls show()
@@ -100,15 +114,25 @@ public class MessageQueueManagerTest {
MessageStateHandler m1 = Mockito.spy(new EmptyMessageStateHandler());
MessageStateHandler m2 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
+ Assert.assertEquals(1,
+ MessagesMetrics.getEnqueuedMessageCountForTesting(MessageIdentifier.TEST_MESSAGE));
verify(m1).show();
queueManager.dismissMessage(m1, DismissReason.TIMER);
verify(m1).hide(anyBoolean(), any());
verify(m1).dismiss(DismissReason.TIMER);
+ Assert.assertEquals(1,
+ MessagesMetrics.getDismissReasonForTesting(
+ MessageIdentifier.TEST_MESSAGE, DismissReason.TIMER));
- queueManager.enqueueMessage(m2, m2, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m2, m2, SCOPE_INSTANCE_ID, false);
+ Assert.assertEquals(2,
+ MessagesMetrics.getEnqueuedMessageCountForTesting(MessageIdentifier.TEST_MESSAGE));
verify(m2).show();
queueManager.dismissMessage(m2, DismissReason.TIMER);
+ Assert.assertEquals(2,
+ MessagesMetrics.getDismissReasonForTesting(
+ MessageIdentifier.TEST_MESSAGE, DismissReason.TIMER));
verify(m2).hide(anyBoolean(), any());
verify(m2).dismiss(DismissReason.TIMER);
}
@@ -125,11 +149,14 @@ public class MessageQueueManagerTest {
MessageStateHandler m2 = Mockito.spy(new EmptyMessageStateHandler());
MessageStateHandler m3 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, SCOPE_INSTANCE_ID);
- queueManager.enqueueMessage(m2, m2, SCOPE_TYPE, SCOPE_INSTANCE_ID);
- queueManager.enqueueMessage(m3, m3, SCOPE_TYPE, SCOPE_INSTANCE_ID_A);
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
+ queueManager.enqueueMessage(m2, m2, SCOPE_INSTANCE_ID, false);
+ queueManager.enqueueMessage(m3, m3, SCOPE_INSTANCE_ID_A, false);
queueManager.dismissAllMessages(DismissReason.ACTIVITY_DESTROYED);
+ Assert.assertEquals(3,
+ MessagesMetrics.getDismissReasonForTesting(
+ MessageIdentifier.TEST_MESSAGE, DismissReason.ACTIVITY_DESTROYED));
verify(m1).dismiss(DismissReason.ACTIVITY_DESTROYED);
verify(m2).dismiss(DismissReason.ACTIVITY_DESTROYED);
verify(m3).dismiss(DismissReason.ACTIVITY_DESTROYED);
@@ -150,8 +177,8 @@ public class MessageQueueManagerTest {
MessageStateHandler m1 = Mockito.spy(new EmptyMessageStateHandler());
MessageStateHandler m2 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, SCOPE_INSTANCE_ID);
- queueManager.enqueueMessage(m2, m2, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
+ queueManager.enqueueMessage(m2, m2, SCOPE_INSTANCE_ID, false);
queueManager.onScopeChange(
new MessageScopeChange(SCOPE_TYPE, SCOPE_INSTANCE_ID, ChangeType.ACTIVE));
verify(m1).show();
@@ -175,8 +202,8 @@ public class MessageQueueManagerTest {
MessageStateHandler m1 = Mockito.mock(MessageStateHandler.class);
MessageStateHandler m2 = Mockito.mock(MessageStateHandler.class);
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, SCOPE_INSTANCE_ID);
- queueManager.enqueueMessage(m2, m2, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
+ queueManager.enqueueMessage(m2, m2, SCOPE_INSTANCE_ID, false);
verify(m1).show();
verify(m2, never()).show();
@@ -201,8 +228,8 @@ public class MessageQueueManagerTest {
MessageStateHandler m2 = Mockito.mock(MessageStateHandler.class);
Object key = new Object();
- queueManager.enqueueMessage(m1, key, SCOPE_TYPE, SCOPE_INSTANCE_ID);
- queueManager.enqueueMessage(m2, key, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m1, key, SCOPE_INSTANCE_ID, false);
+ queueManager.enqueueMessage(m2, key, SCOPE_INSTANCE_ID, false);
queueManager.onScopeChange(
new MessageScopeChange(SCOPE_TYPE, SCOPE_INSTANCE_ID, ChangeType.ACTIVE));
}
@@ -216,7 +243,7 @@ public class MessageQueueManagerTest {
MessageQueueManager queueManager = new MessageQueueManager();
queueManager.setDelegate(mEmptyDelegate);
MessageStateHandler m1 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
queueManager.dismissMessage(m1, DismissReason.TIMER);
queueManager.dismissMessage(m1, DismissReason.TIMER);
verify(m1, times(1)).dismiss(DismissReason.TIMER);
@@ -234,7 +261,7 @@ public class MessageQueueManagerTest {
queueManager.setDelegate(delegate);
int token = queueManager.suspend();
MessageStateHandler m1 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
verify(delegate, never()).onStartShowing(any());
verify(delegate, never()).onFinishHiding();
verify(m1, never()).show();
@@ -261,7 +288,7 @@ public class MessageQueueManagerTest {
queueManager.setDelegate(delegate);
queueManager.suspend();
MessageStateHandler m1 = Mockito.mock(MessageStateHandler.class);
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
verify(delegate, never()).onStartShowing(any());
verify(delegate, never()).onFinishHiding();
verify(m1, never()).show();
@@ -289,10 +316,10 @@ public class MessageQueueManagerTest {
final ScopeKey inactiveScopeKey = new ScopeKey(SCOPE_TYPE, new InactiveMockWebContents());
final ScopeKey inactiveScopeKey2 = new ScopeKey(SCOPE_TYPE, new InactiveMockWebContents());
MessageStateHandler m1 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, inactiveScopeKey2);
+ queueManager.enqueueMessage(m1, m1, inactiveScopeKey2, false);
MessageStateHandler m2 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m2, m2, SCOPE_TYPE, inactiveScopeKey);
+ queueManager.enqueueMessage(m2, m2, inactiveScopeKey, false);
queueManager.onScopeChange(
new MessageScopeChange(SCOPE_TYPE, inactiveScopeKey, ChangeType.ACTIVE));
@@ -340,10 +367,10 @@ public class MessageQueueManagerTest {
new ScopeKey(MessageScopeType.WEB_CONTENTS, new MockWindowAndroidWebContents());
MessageStateHandler m1 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m1, m1, MessageScopeType.NAVIGATION, navScopeKey);
+ queueManager.enqueueMessage(m1, m1, navScopeKey, false);
MessageStateHandler m2 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m2, m2, MessageScopeType.WINDOW, windowScopeKey);
+ queueManager.enqueueMessage(m2, m2, windowScopeKey, false);
verify(m1, description("A message should be shown when the associated scope is active"))
.show();
@@ -388,7 +415,7 @@ public class MessageQueueManagerTest {
MessageQueueManager queueManager = new MessageQueueManager();
queueManager.setDelegate(delegate);
MessageStateHandler m1 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
queueManager.onScopeChange(
new MessageScopeChange(SCOPE_TYPE, SCOPE_INSTANCE_ID, ChangeType.INACTIVE, true));
@@ -419,7 +446,7 @@ public class MessageQueueManagerTest {
queueManager.setDelegate(delegate);
MessageStateHandler m1 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
verify(m1,
description("The message should show when its target scope instance is activated."))
.show();
@@ -448,19 +475,19 @@ public class MessageQueueManagerTest {
MessageStateHandler m2 = Mockito.spy(new EmptyMessageStateHandler());
MessageStateHandler m3 = Mockito.spy(new EmptyMessageStateHandler());
- queueManager.enqueueMessage(m1, m1, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
verify(controller,
description(
"ScopeChangeController should be notified when the queue of scope gets its first message"))
.firstMessageEnqueued(SCOPE_INSTANCE_ID);
- queueManager.enqueueMessage(m2, m2, SCOPE_TYPE, SCOPE_INSTANCE_ID);
+ queueManager.enqueueMessage(m2, m2, SCOPE_INSTANCE_ID, false);
verify(controller,
times(1).description(
"ScopeChangeController should be notified **only** when the queue of scope gets its first message"))
.firstMessageEnqueued(SCOPE_INSTANCE_ID);
- queueManager.enqueueMessage(m3, m3, SCOPE_TYPE, SCOPE_INSTANCE_ID_A);
+ queueManager.enqueueMessage(m3, m3, SCOPE_INSTANCE_ID_A, false);
verify(controller,
times(1).description(
"ScopeChangeController should be notified **only** when the queue of scope gets its first message"))
@@ -491,4 +518,27 @@ public class MessageQueueManagerTest {
"ScopeChangeController should be notified when the queue of scope is empty."))
.lastMessageDismissed(SCOPE_INSTANCE_ID);
}
+
+ /**
+ * Test that the higher priority message is displayed when being enqueued.
+ */
+ @Test
+ @SmallTest
+ public void testEnqueueHigherPriorityMessage() {
+ MessageQueueManager queueManager = new MessageQueueManager();
+ queueManager.setDelegate(mEmptyDelegate);
+ MessageStateHandler m1 = Mockito.spy(new EmptyMessageStateHandler());
+ MessageStateHandler m2 = Mockito.spy(new EmptyMessageStateHandler());
+
+ queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false);
+ verify(m1).show();
+
+ queueManager.enqueueMessage(m2, m2, SCOPE_INSTANCE_ID, true);
+ verify(m1).hide(anyBoolean(), any());
+ verify(m2).show();
+ queueManager.dismissMessage(m2, DismissReason.TIMER);
+ verify(m2).hide(anyBoolean(), any());
+ verify(m2).dismiss(DismissReason.TIMER);
+ verify(m1, times(2)).show();
+ }
}
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageStateHandler.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageStateHandler.java
index 74064639a1b..cc338c81b51 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageStateHandler.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessageStateHandler.java
@@ -26,4 +26,8 @@ public interface MessageStateHandler {
* @param dismissReason The reason why the message is being dismissed.
*/
void dismiss(@DismissReason int dismissReason);
+
+ /** Returns MessageIdentifier of the current message. */
+ @MessageIdentifier
+ int getMessageIdentifier();
}
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessagesFactory.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessagesFactory.java
index 32923a9607a..c864138c488 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessagesFactory.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessagesFactory.java
@@ -20,14 +20,15 @@ public class MessagesFactory {
* to the MessageContainer. When messages are shown, they will be animated down the
* screen, starting at the negative |messageMaxTranslation| y translation to the resting
* position in the MessageContainer.
- * @param autodismissDurationMs The {@link Supplier} providing autodismiss duration for message
- * banner.
+ * @param autodismissDurationMs The {@link MessageAutodismissDurationProvider} providing
+ * autodismiss duration for message banner.
* @param animatorStartCallback The {@link Callback} that will be used by the message to
* delegate starting the animations to the {@link WindowAndroid}.
* @return The constructed ManagedMessageDispatcher.
*/
public static ManagedMessageDispatcher createMessageDispatcher(MessageContainer container,
- Supplier<Integer> messageMaxTranslation, Supplier<Long> autodismissDurationMs,
+ Supplier<Integer> messageMaxTranslation,
+ MessageAutodismissDurationProvider autodismissDurationMs,
Callback<Animator> animatorStartCallback) {
return new MessageDispatcherImpl(
container, messageMaxTranslation, autodismissDurationMs, animatorStartCallback);
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessagesMetrics.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessagesMetrics.java
new file mode 100644
index 00000000000..f54ff391713
--- /dev/null
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/MessagesMetrics.java
@@ -0,0 +1,98 @@
+// Copyright 2021 The Chromium 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.messages;
+
+import android.os.SystemClock;
+
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.metrics.RecordHistogram;
+
+/**
+ * Static utility methods for recording messages related metrics.
+ */
+public class MessagesMetrics {
+ private static final String ENQUEUED_HISTOGRAM_NAME = "Android.Messages.Enqueued";
+ private static final String DISMISSED_HISTOGRAM_PREFIX = "Android.Messages.Dismissed.";
+ private static final String TIME_TO_ACTION_HISTOGRAM_PREFIX = "Android.Messages.TimeToAction.";
+
+ /** Records metrics when a message is enqueued. */
+ public static void recordMessageEnqueued(@MessageIdentifier int messageIdentifier) {
+ RecordHistogram.recordEnumeratedHistogram(
+ ENQUEUED_HISTOGRAM_NAME, messageIdentifier, MessageIdentifier.COUNT);
+ }
+
+ /** Records metrics when a message is dismissed. */
+ public static void recordDismissReason(
+ @MessageIdentifier int messageIdentifier, @DismissReason int dismissReason) {
+ String histogramName =
+ DISMISSED_HISTOGRAM_PREFIX + messageIdentifierToHistogramSuffix(messageIdentifier);
+ RecordHistogram.recordEnumeratedHistogram(
+ histogramName, dismissReason, DismissReason.COUNT);
+ }
+
+ /**
+ * Records metrics with duration of time a message was visible before it was dismissed by a user
+ * action.
+ */
+ public static void recordTimeToAction(
+ @MessageIdentifier int messageIdentifier, long durationMs) {
+ String histogramName = TIME_TO_ACTION_HISTOGRAM_PREFIX
+ + messageIdentifierToHistogramSuffix(messageIdentifier);
+ RecordHistogram.recordMediumTimesHistogram(histogramName, durationMs);
+ }
+
+ /**
+ * Returns current timestamp in milliseconds to be used when recording message's visible
+ * duration.
+ */
+ public static long now() {
+ return SystemClock.uptimeMillis();
+ }
+
+ /**
+ * Returns a histogram suffix string that corresponds to message identifier of the current
+ * message.
+ * Update this function when adding a new message identifier.
+ */
+ static String messageIdentifierToHistogramSuffix(@MessageIdentifier int messageIdentifier) {
+ switch (messageIdentifier) {
+ case MessageIdentifier.TEST_MESSAGE:
+ return "TestMessage";
+ case MessageIdentifier.SAVE_PASSWORD:
+ return "SavePassword";
+ case MessageIdentifier.UPDATE_PASSWORD:
+ return "UpdatePassword";
+ case MessageIdentifier.GENERATED_PASSWORD_SAVED:
+ return "GeneratedPasswordSaved";
+ case MessageIdentifier.POPUP_BLOCKED:
+ return "PopupBlocked";
+ case MessageIdentifier.SAFETY_TIP:
+ return "SafetyTip";
+ case MessageIdentifier.SAVE_ADDRESS_PROFILE:
+ return "SaveAddressProfile";
+ case MessageIdentifier.MERCHANT_TRUST:
+ return "MerchantTrust";
+ case MessageIdentifier.ADD_TO_HOMESCREEN_IPH:
+ return "AddToHomescreenIPH";
+ default:
+ return "Unknown";
+ }
+ }
+
+ @VisibleForTesting
+ public static int getEnqueuedMessageCountForTesting(@MessageIdentifier int messageIdentifier) {
+ return RecordHistogram.getHistogramValueCountForTesting(
+ ENQUEUED_HISTOGRAM_NAME, messageIdentifier);
+ }
+
+ @VisibleForTesting
+ public static int getDismissReasonForTesting(
+ @MessageIdentifier int messageIdentifier, @DismissReason int dismissReason) {
+ String histogramName =
+ DISMISSED_HISTOGRAM_PREFIX + messageIdentifierToHistogramSuffix(messageIdentifier);
+ return RecordHistogram.getHistogramValueCountForTesting(histogramName, dismissReason);
+ }
+}
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeController.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeController.java
index 02091bca95b..b64a45dbd52 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeController.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeController.java
@@ -21,7 +21,9 @@ import java.util.HashMap;
import java.util.Map;
/**
- * Observe the webContents and notify queue manager of proper scope changes.
+ * Observe the webContents to notify queue manager of proper scope changes of {@link
+ * MessageScopeType#NAVIGATION} and {@link MessageScopeType#WEB_CONTENTS}. Observe the windowAndroid
+ * to notify queue manager of proper scope changes of {@link MessageScopeType#WINDOW}.
*/
class ScopeChangeController {
/**
@@ -49,9 +51,9 @@ class ScopeChangeController {
*/
void firstMessageEnqueued(ScopeKey scopeKey) {
assert !mObservers.containsKey(scopeKey) : "This scope key has already been observed.";
- ScopeObserver observer = scopeKey.scopeType == MessageScopeType.NAVIGATION
- ? new NavigationScopeObserver(mDelegate, scopeKey)
- : new WindowScopeObserver(mDelegate, scopeKey);
+ ScopeObserver observer = scopeKey.scopeType == MessageScopeType.WINDOW
+ ? new WindowScopeObserver(mDelegate, scopeKey)
+ : new NavigationWebContentsScopeObserver(mDelegate, scopeKey);
mObservers.put(scopeKey, observer);
}
@@ -64,11 +66,16 @@ class ScopeChangeController {
observer.destroy();
}
- static class NavigationScopeObserver extends WebContentsObserver implements ScopeObserver {
+ /**
+ * This handles both navigation type and webContents type. Only navigation type
+ * will destroy scopes on page navigation.
+ */
+ static class NavigationWebContentsScopeObserver
+ extends WebContentsObserver implements ScopeObserver {
private final Delegate mDelegate;
private final ScopeKey mScopeKey;
- public NavigationScopeObserver(Delegate delegate, ScopeKey scopeKey) {
+ public NavigationWebContentsScopeObserver(Delegate delegate, ScopeKey scopeKey) {
super(scopeKey.webContents);
mDelegate = delegate;
mScopeKey = scopeKey;
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeControllerTest.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeControllerTest.java
index f0707fe4a74..f6fd25210e1 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeControllerTest.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/ScopeChangeControllerTest.java
@@ -6,6 +6,7 @@ package org.chromium.components.messages;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.description;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -87,15 +88,13 @@ public class ScopeChangeControllerTest {
Assert.assertEquals("Scope type should be inactive when page is hidden",
ChangeType.INACTIVE, captor.getValue().changeType);
- observer.navigationEntryCommitted(
- new LoadCommittedDetails(-1, null, true, false, true, -1));
+ observer.navigationEntryCommitted(createLoadCommittedDetails(true));
verify(delegate,
times(expectedOnScopeChangeCalls)
.description("Delegate should not be called when entry is replaced"))
.onScopeChange(any());
- observer.navigationEntryCommitted(
- new LoadCommittedDetails(-1, null, false, false, true, -1));
+ observer.navigationEntryCommitted(createLoadCommittedDetails(false));
expectedOnScopeChangeCalls++;
verify(delegate,
@@ -117,4 +116,39 @@ public class ScopeChangeControllerTest {
Assert.assertEquals("Scope type should be destroy when top level native window changes",
ChangeType.DESTROY, captor.getValue().changeType);
}
+
+ @Test
+ @SmallTest
+ public void testIgnoreNavigation() {
+ ScopeChangeController.Delegate delegate =
+ Mockito.mock(ScopeChangeController.Delegate.class);
+ ScopeChangeController controller = new ScopeChangeController(delegate);
+
+ MockWebContents webContents = mock(MockWebContents.class);
+ ScopeKey key = new ScopeKey(MessageScopeType.WEB_CONTENTS, webContents);
+ controller.firstMessageEnqueued(key);
+
+ final ArgumentCaptor<WebContentsObserver> runnableCaptor =
+ ArgumentCaptor.forClass(WebContentsObserver.class);
+ verify(webContents).addObserver(runnableCaptor.capture());
+
+ WebContentsObserver observer = runnableCaptor.getValue();
+
+ // Default visibility of web contents is invisible.
+ ArgumentCaptor<MessageScopeChange> captor =
+ ArgumentCaptor.forClass(MessageScopeChange.class);
+ verify(delegate, description("Delegate should be called when page is hidden"))
+ .onScopeChange(captor.capture());
+ Assert.assertEquals("Scope type should be inactive when page is hidden",
+ ChangeType.INACTIVE, captor.getValue().changeType);
+
+ observer.navigationEntryCommitted(createLoadCommittedDetails(false));
+ verify(delegate,
+ times(1).description("Delegate should not be called when navigation is ignored"))
+ .onScopeChange(any());
+ }
+
+ private LoadCommittedDetails createLoadCommittedDetails(boolean didReplaceEntry) {
+ return new LoadCommittedDetails(-1, null, didReplaceEntry, false, true, -1);
+ }
}
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessage.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessage.java
index 52ffc5f8e9a..b54b5c6ea83 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessage.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessage.java
@@ -39,27 +39,38 @@ public class SingleActionMessage implements MessageStateHandler {
private final Supplier<Integer> mMaxTranslationSupplier;
private final Callback<Animator> mAnimatorStartCallback;
+ // The timestamp when the message was shown. Used for reproting visible duration.
+ private long mMessageShownTime;
+
/**
* @param container The container holding messages.
* @param model The PropertyModel with {@link MessageBannerProperties#ALL_KEYS}.
* @param dismissHandler The {@link DismissCallback} able to dismiss a message by given property
* model.
- * @param autodismissDurationMs A {@link Supplier} providing autodismiss duration for message
- * banner.
+ * @param autodismissDurationMs A {@link MessageAutodismissDurationProvider} providing
+ * autodismiss duration for message banner. The actual duration can be extended by
+ * clients.
* @param maxTranslationSupplier A {@link Supplier} that supplies the maximum translation Y
* @param animatorStartCallback The {@link Callback} that will be used by the message banner to
* delegate starting the animations to the {@link WindowAndroid}.
*/
public SingleActionMessage(MessageContainer container, PropertyModel model,
DismissCallback dismissHandler, Supplier<Integer> maxTranslationSupplier,
- Supplier<Long> autodismissDurationMs, Callback<Animator> animatorStartCallback) {
+ MessageAutodismissDurationProvider autodismissDurationProvider,
+ Callback<Animator> animatorStartCallback) {
mModel = model;
mContainer = container;
mDismissHandler = dismissHandler;
- mAutodismissDurationMs = autodismissDurationMs;
mMaxTranslationSupplier = maxTranslationSupplier;
mAnimatorStartCallback = animatorStartCallback;
+ long dismissalDuration =
+ mModel.getAllSetProperties().contains(MessageBannerProperties.DISMISSAL_DURATION)
+ ? mModel.get(MessageBannerProperties.DISMISSAL_DURATION)
+ : 0;
+
+ mAutodismissDurationMs = () -> autodismissDurationProvider.get(dismissalDuration);
+
mModel.set(
MessageBannerProperties.PRIMARY_BUTTON_CLICK_LISTENER, this::handlePrimaryAction);
}
@@ -87,6 +98,7 @@ public class SingleActionMessage implements MessageStateHandler {
// is required in case the animation set-up requires the height of the container, e.g.
// showing messages without the top controls visible.
mContainer.runAfterInitialMessageLayout(mMessageBanner::show);
+ mMessageShownTime = MessagesMetrics.now();
}
/**
@@ -110,6 +122,13 @@ public class SingleActionMessage implements MessageStateHandler {
if (mMessageBanner != null) mMessageBanner.dismiss();
Callback<Integer> onDismissed = mModel.get(MessageBannerProperties.ON_DISMISSED);
if (onDismissed != null) onDismissed.onResult(dismissReason);
+ if (dismissReason == DismissReason.PRIMARY_ACTION
+ || dismissReason == DismissReason.SECONDARY_ACTION
+ || dismissReason == DismissReason.GESTURE) {
+ // Only record time to dismiss when the user explicitly dismissed the message.
+ MessagesMetrics.recordTimeToAction(
+ getMessageIdentifier(), MessagesMetrics.now() - mMessageShownTime);
+ }
}
private void handlePrimaryAction(View v) {
@@ -131,4 +150,12 @@ public class SingleActionMessage implements MessageStateHandler {
void setViewForTesting(MessageBannerView view) {
mView = view;
}
+
+ @Override
+ @MessageIdentifier
+ public int getMessageIdentifier() {
+ Integer messageIdentifier = mModel.get(MessageBannerProperties.MESSAGE_IDENTIFIER);
+ assert messageIdentifier != null;
+ return messageIdentifier;
+ }
}
diff --git a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessageTest.java b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessageTest.java
index 7bacd3edb32..915b0148927 100644
--- a/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessageTest.java
+++ b/chromium/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessageTest.java
@@ -49,6 +49,18 @@ public class SingleActionMessageTest {
private static Activity sActivity;
+ private class MockDurationProvider implements MessageAutodismissDurationProvider {
+ private long mDuration;
+ public MockDurationProvider(long duration) {
+ mDuration = duration;
+ }
+
+ @Override
+ public long get(long extension) {
+ return mDuration;
+ }
+ }
+
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock
@@ -75,8 +87,9 @@ public class SingleActionMessageTest {
public void testAddAndRemoveSingleActionMessage() throws Exception {
MessageContainer container = new MessageContainer(sActivity, null);
PropertyModel model = createBasicSingleActionMessageModel();
- SingleActionMessage message = new SingleActionMessage(
- container, model, mEmptyDismissCallback, () -> 0, () -> 0L, mAnimatorStartCallback);
+ SingleActionMessage message =
+ new SingleActionMessage(container, model, mEmptyDismissCallback,
+ () -> 0, new MockDurationProvider(0L), mAnimatorStartCallback);
final MessageBannerCoordinator messageBanner = Mockito.mock(MessageBannerCoordinator.class);
final MessageBannerView view = new MessageBannerView(sActivity, null);
view.setId(R.id.message_banner);
@@ -105,28 +118,43 @@ public class SingleActionMessageTest {
MessageContainer container = new MessageContainer(sActivity, null);
PropertyModel model = createBasicSingleActionMessageModel();
long duration = 42;
- SingleActionMessage message = new SingleActionMessage(container, model,
- mEmptyDismissCallback, () -> 0, () -> duration, mAnimatorStartCallback);
+ SingleActionMessage message =
+ new SingleActionMessage(container, model, mEmptyDismissCallback,
+ () -> 0, new MockDurationProvider(duration), mAnimatorStartCallback);
Assert.assertEquals("Autodismiss duration is not propagated correctly.", duration,
message.getAutoDismissDuration());
}
+ @Test
+ @MediumTest
+ public void testAutoDismissDurationExtended() {
+ MessageContainer container = new MessageContainer(sActivity, null);
+ PropertyModel model = createBasicSingleActionMessageModel();
+ model.set(MessageBannerProperties.DISMISSAL_DURATION, 1000);
+ long duration = 42;
+ SingleActionMessage message =
+ new SingleActionMessage(container, model, mEmptyDismissCallback,
+ () -> 0, new MockDurationProvider(duration + 1000), mAnimatorStartCallback);
+ Assert.assertEquals("Autodismiss duration is not propagated correctly.", duration + 1000,
+ message.getAutoDismissDuration());
+ }
+
@Test(expected = IllegalStateException.class)
@MediumTest
public void testAddMultipleSingleActionMessage() {
MessageContainer container = new MessageContainer(sActivity, null);
PropertyModel m1 = createBasicSingleActionMessageModel();
PropertyModel m2 = createBasicSingleActionMessageModel();
- SingleActionMessage message1 = new SingleActionMessage(
- container, m1, mEmptyDismissCallback, () -> 0, () -> 0L, mAnimatorStartCallback);
+ SingleActionMessage message1 = new SingleActionMessage(container, m1, mEmptyDismissCallback,
+ () -> 0, new MockDurationProvider(0L), mAnimatorStartCallback);
final MessageBannerCoordinator messageBanner1 =
Mockito.mock(MessageBannerCoordinator.class);
final MessageBannerView view1 = new MessageBannerView(sActivity, null);
view1.setId(R.id.message_banner);
message1.setMessageBannerForTesting(messageBanner1);
message1.setViewForTesting(view1);
- SingleActionMessage message2 = new SingleActionMessage(
- container, m2, mEmptyDismissCallback, () -> 0, () -> 0L, mAnimatorStartCallback);
+ SingleActionMessage message2 = new SingleActionMessage(container, m2, mEmptyDismissCallback,
+ () -> 0, new MockDurationProvider(0L), mAnimatorStartCallback);
final MessageBannerCoordinator messageBanner2 =
Mockito.mock(MessageBannerCoordinator.class);
final MessageBannerView view2 = new MessageBannerView(sActivity, null);
@@ -139,6 +167,7 @@ public class SingleActionMessageTest {
private PropertyModel createBasicSingleActionMessageModel() {
return new PropertyModel.Builder(MessageBannerProperties.ALL_KEYS)
+ .with(MessageBannerProperties.MESSAGE_IDENTIFIER, MessageIdentifier.TEST_MESSAGE)
.with(MessageBannerProperties.TITLE, "test")
.with(MessageBannerProperties.DESCRIPTION, "Description")
.with(MessageBannerProperties.ICON,
diff --git a/chromium/components/messages/android/message_dispatcher_bridge.cc b/chromium/components/messages/android/message_dispatcher_bridge.cc
index f19a4078e80..fdeda105f6e 100644
--- a/chromium/components/messages/android/message_dispatcher_bridge.cc
+++ b/chromium/components/messages/android/message_dispatcher_bridge.cc
@@ -34,13 +34,19 @@ void MessageDispatcherBridge::SetInstanceForTesting(
g_message_dospatcher_bridge_for_testing = instance;
}
-void MessageDispatcherBridge::EnqueueMessage(MessageWrapper* message,
+bool MessageDispatcherBridge::EnqueueMessage(MessageWrapper* message,
content::WebContents* web_contents,
- MessageScopeType scopeType) {
+ MessageScopeType scope_type,
+ MessagePriority priority) {
JNIEnv* env = base::android::AttachCurrentThread();
- Java_MessageDispatcherBridge_enqueueMessage(
- env, message->GetJavaMessageWrapper(), web_contents->GetJavaWebContents(),
- static_cast<int>(scopeType));
+ if (Java_MessageDispatcherBridge_enqueueMessage(
+ env, message->GetJavaMessageWrapper(),
+ web_contents->GetJavaWebContents(), static_cast<int>(scope_type),
+ priority == MessagePriority::kUrgent) == JNI_TRUE) {
+ message->SetMessageEnqueued();
+ return true;
+ }
+ return false;
}
void MessageDispatcherBridge::DismissMessage(MessageWrapper* message,
@@ -60,4 +66,4 @@ void MessageDispatcherBridge::DismissMessage(MessageWrapper* message,
}
}
-} // namespace messages \ No newline at end of file
+} // namespace messages
diff --git a/chromium/components/messages/android/message_dispatcher_bridge.h b/chromium/components/messages/android/message_dispatcher_bridge.h
index 48720260602..43c75a38756 100644
--- a/chromium/components/messages/android/message_dispatcher_bridge.h
+++ b/chromium/components/messages/android/message_dispatcher_bridge.h
@@ -22,9 +22,10 @@ class MessageDispatcherBridge {
static void SetInstanceForTesting(MessageDispatcherBridge* instance);
- virtual void EnqueueMessage(MessageWrapper* message,
+ virtual bool EnqueueMessage(MessageWrapper* message,
content::WebContents* web_contents,
- MessageScopeType scopeType);
+ MessageScopeType scope_type,
+ MessagePriority priority);
virtual void DismissMessage(MessageWrapper* message,
content::WebContents* web_contents,
DismissReason dismiss_reason);
@@ -35,4 +36,4 @@ class MessageDispatcherBridge {
} // namespace messages
-#endif // COMPONENTS_MESSAGES_ANDROID_MESSAGE_DISPATCHER_BRIDGE_H_ \ No newline at end of file
+#endif // COMPONENTS_MESSAGES_ANDROID_MESSAGE_DISPATCHER_BRIDGE_H_
diff --git a/chromium/components/messages/android/message_enums.h b/chromium/components/messages/android/message_enums.h
index 10de6c39a1b..da474da20a2 100644
--- a/chromium/components/messages/android/message_enums.h
+++ b/chromium/components/messages/android/message_enums.h
@@ -12,6 +12,9 @@ namespace messages {
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.messages
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
+// TODO(crbug.com/1188983): Revisit enum values. TAB_SWITCHED is not currently
+// used. Likely the same for TAB_DESTROYED and ACTIVITY_DESTROYED. We also need
+// a dedicated value for message dismissed from feature code.
enum class DismissReason {
// Dismiss reasons that are fully controlled by clients (i.e. are not used
// inside the Messages implementation are marked "Controlled by client" on
@@ -38,15 +41,49 @@ enum class DismissReason {
// A message was dismissed due to the destruction of the corresponding scopes.
SCOPE_DESTROYED = 8,
- // Always update MAX_VALUE to match the last reason in the list.
- MAX_VALUE = 8
+ // Insert new values before this line.
+ COUNT
};
+// "Urgent" means the user should take actions ASAP, such as responding to
+// permissions or safety warnings.
+enum class MessagePriority { kUrgent, kNormal };
+
// The constants of message scope type.
//
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.messages
enum class MessageScopeType { WINDOW = 0, WEB_CONTENTS = 1, NAVIGATION = 2 };
+// Enumerates unique identifiers for various messages. Used for recording
+// messages related histograms.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+//
+// When adding a new message identifier, make corresponding changes in the
+// following locations:
+// - tools/metrics/histograms/enums.xml: <enum name="MessageIdentifier">
+// - tools/metrics/histograms/histograms_xml/android/histograms.xml:
+// <variants name="MessageIdentifiers">
+// - MessagesMetrics.java: #messageIdentifierToHistogramSuffix()
+//
+// A Java counterpart is generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.messages
+enum class MessageIdentifier {
+ TEST_MESSAGE = 0,
+ SAVE_PASSWORD = 1,
+ UPDATE_PASSWORD = 2,
+ GENERATED_PASSWORD_SAVED = 3,
+ POPUP_BLOCKED = 4,
+ SAFETY_TIP = 5,
+ SAVE_ADDRESS_PROFILE = 6,
+ MERCHANT_TRUST = 7,
+ ADD_TO_HOMESCREEN_IPH = 8,
+
+ // Insert new values before this line.
+ COUNT
+};
+
} // namespace messages
#endif // COMPONENTS_MESSAGES_ANDROID_MESSAGE_ENUMS_H_
diff --git a/chromium/components/messages/android/message_wrapper.cc b/chromium/components/messages/android/message_wrapper.cc
index f08bd478ba4..b5c30ee5707 100644
--- a/chromium/components/messages/android/message_wrapper.cc
+++ b/chromium/components/messages/android/message_wrapper.cc
@@ -11,18 +11,20 @@
namespace messages {
-MessageWrapper::MessageWrapper(base::OnceClosure action_callback,
+MessageWrapper::MessageWrapper(MessageIdentifier message_identifier,
+ base::OnceClosure action_callback,
DismissCallback dismiss_callback)
: action_callback_(std::move(action_callback)),
dismiss_callback_(std::move(dismiss_callback)),
- message_dismissed_(false) {
+ message_enqueued_(false) {
JNIEnv* env = base::android::AttachCurrentThread();
java_message_wrapper_ =
- Java_MessageWrapper_create(env, reinterpret_cast<int64_t>(this));
+ Java_MessageWrapper_create(env, reinterpret_cast<int64_t>(this),
+ static_cast<int>(message_identifier));
}
MessageWrapper::~MessageWrapper() {
- CHECK(message_dismissed_);
+ CHECK(!message_enqueued_);
}
std::u16string MessageWrapper::GetTitle() {
@@ -56,6 +58,17 @@ void MessageWrapper::SetDescription(const std::u16string& description) {
Java_MessageWrapper_setDescription(env, java_message_wrapper_, jdescription);
}
+int MessageWrapper::GetDescriptionMaxLines() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ return Java_MessageWrapper_getDescriptionMaxLines(env, java_message_wrapper_);
+}
+
+void MessageWrapper::SetDescriptionMaxLines(int max_lines) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_MessageWrapper_setDescriptionMaxLines(env, java_message_wrapper_,
+ max_lines);
+}
+
std::u16string MessageWrapper::GetPrimaryButtonText() {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> jprimary_button_text =
@@ -105,6 +118,11 @@ void MessageWrapper::SetIconResourceId(int resource_id) {
resource_id);
}
+void MessageWrapper::DisableIconTint() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_MessageWrapper_disableIconTint(env, java_message_wrapper_);
+}
+
int MessageWrapper::GetSecondaryIconResourceId() {
JNIEnv* env = base::android::AttachCurrentThread();
return Java_MessageWrapper_getSecondaryIconResourceId(env,
@@ -121,6 +139,11 @@ void MessageWrapper::SetSecondaryActionCallback(base::OnceClosure callback) {
secondary_action_callback_ = std::move(callback);
}
+void MessageWrapper::SetDuration(long customDuration) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_MessageWrapper_setDuration(env, java_message_wrapper_, customDuration);
+}
+
void MessageWrapper::HandleActionClick(JNIEnv* env) {
if (!action_callback_.is_null())
std::move(action_callback_).Run();
@@ -133,8 +156,7 @@ void MessageWrapper::HandleSecondaryActionClick(JNIEnv* env) {
void MessageWrapper::HandleDismissCallback(JNIEnv* env, int dismiss_reason) {
// Make sure message dismissed callback is called exactly once.
- CHECK(!message_dismissed_);
- message_dismissed_ = true;
+ message_enqueued_ = false;
Java_MessageWrapper_clearNativePtr(env, java_message_wrapper_);
if (!dismiss_callback_.is_null())
std::move(dismiss_callback_)
@@ -149,4 +171,8 @@ const base::android::JavaRef<jobject>& MessageWrapper::GetJavaMessageWrapper()
return java_message_wrapper_;
}
-} // namespace messages \ No newline at end of file
+void MessageWrapper::SetMessageEnqueued() {
+ message_enqueued_ = true;
+}
+
+} // namespace messages
diff --git a/chromium/components/messages/android/message_wrapper.h b/chromium/components/messages/android/message_wrapper.h
index 50e02e127b7..74ab3482636 100644
--- a/chromium/components/messages/android/message_wrapper.h
+++ b/chromium/components/messages/android/message_wrapper.h
@@ -24,7 +24,8 @@ class MessageWrapper {
public:
using DismissCallback = base::OnceCallback<void(DismissReason)>;
- MessageWrapper(base::OnceClosure action_callback,
+ MessageWrapper(MessageIdentifier message_identifier,
+ base::OnceClosure action_callback,
DismissCallback dismiss_callback);
~MessageWrapper();
@@ -37,6 +38,12 @@ class MessageWrapper {
void SetTitle(const std::u16string& title);
std::u16string GetDescription();
void SetDescription(const std::u16string& description);
+
+ // SetDescriptionMaxLines allows limiting description view to the specified
+ // number of lines. The description will be ellipsized with TruncateAt.END
+ // option.
+ int GetDescriptionMaxLines();
+ void SetDescriptionMaxLines(int max_lines);
std::u16string GetPrimaryButtonText();
void SetPrimaryButtonText(const std::u16string& primary_button_text);
std::u16string GetSecondaryButtonMenuText();
@@ -47,11 +54,16 @@ class MessageWrapper {
// translate from chromium resource_id to Android drawable resource_id.
int GetIconResourceId();
void SetIconResourceId(int resource_id);
+ // The icon is tinted to default_icon_color_blue by default.
+ // Call this method to display icons of original colors.
+ void DisableIconTint();
int GetSecondaryIconResourceId();
void SetSecondaryIconResourceId(int resource_id);
void SetSecondaryActionCallback(base::OnceClosure callback);
+ void SetDuration(long customDuration);
+
// Following methods forward calls from java to provided callbacks.
void HandleActionClick(JNIEnv* env);
void HandleSecondaryActionClick(JNIEnv* env);
@@ -59,14 +71,18 @@ class MessageWrapper {
const base::android::JavaRef<jobject>& GetJavaMessageWrapper() const;
+ // Called by bridge when message is successfully enqueued.
+ void SetMessageEnqueued();
+
private:
base::android::ScopedJavaGlobalRef<jobject> java_message_wrapper_;
base::OnceClosure action_callback_;
base::OnceClosure secondary_action_callback_;
DismissCallback dismiss_callback_;
- bool message_dismissed_;
+ // True if message is in queue.
+ bool message_enqueued_;
};
} // namespace messages
-#endif // COMPONENTS_MESSAGES_ANDROID_MESSAGE_WRAPPER_H_ \ No newline at end of file
+#endif // COMPONENTS_MESSAGES_ANDROID_MESSAGE_WRAPPER_H_
diff --git a/chromium/components/messages/android/messages_feature.cc b/chromium/components/messages/android/messages_feature.cc
index 0864a699de7..7529e191b45 100644
--- a/chromium/components/messages/android/messages_feature.cc
+++ b/chromium/components/messages/android/messages_feature.cc
@@ -15,6 +15,15 @@ const base::Feature kMessagesForAndroidPasswords{
extern const base::Feature kMessagesForAndroidPopupBlocked{
"MessagesForAndroidPopupBlocked", base::FEATURE_DISABLED_BY_DEFAULT};
+extern const base::Feature kMessagesForAndroidSafetyTip{
+ "MessagesForAndroidSafetyTip", base::FEATURE_DISABLED_BY_DEFAULT};
+
+extern const base::Feature kMessagesForAndroidSaveCard{
+ "MessagesForAndroidSaveCard", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kMessagesForAndroidUpdatePassword{
+ "MessagesForAndroidUpdatePassword", base::FEATURE_DISABLED_BY_DEFAULT};
+
bool IsPasswordMessagesUiEnabled() {
return base::FeatureList::IsEnabled(kMessagesForAndroidInfrastructure) &&
base::FeatureList::IsEnabled(kMessagesForAndroidPasswords);
@@ -25,4 +34,19 @@ bool IsPopupBlockedMessagesUiEnabled() {
base::FeatureList::IsEnabled(kMessagesForAndroidPopupBlocked);
}
+bool IsSafetyTipMessagesUiEnabled() {
+ return base::FeatureList::IsEnabled(kMessagesForAndroidInfrastructure) &&
+ base::FeatureList::IsEnabled(kMessagesForAndroidSafetyTip);
+}
+
+bool IsSaveCardMessagesUiEnabled() {
+ return base::FeatureList::IsEnabled(kMessagesForAndroidInfrastructure) &&
+ base::FeatureList::IsEnabled(kMessagesForAndroidSaveCard);
+}
+
+bool IsUpdatePasswordMessagesUiEnabled() {
+ return base::FeatureList::IsEnabled(kMessagesForAndroidInfrastructure) &&
+ base::FeatureList::IsEnabled(kMessagesForAndroidUpdatePassword);
+}
+
} // namespace messages
diff --git a/chromium/components/messages/android/messages_feature.h b/chromium/components/messages/android/messages_feature.h
index 64f57b314eb..6dfef8ab748 100644
--- a/chromium/components/messages/android/messages_feature.h
+++ b/chromium/components/messages/android/messages_feature.h
@@ -14,18 +14,36 @@ namespace messages {
// implementations also fallback to Infobar implementations.
extern const base::Feature kMessagesForAndroidInfrastructure;
-// Feature that controls whether "save password" and "update password" prompts
-// use Messages or Infobars infrastructure.
+// Feature that controls whether "save password" and "saved password
+// confirmation" prompts use Messages or Infobars infrastructure.
extern const base::Feature kMessagesForAndroidPasswords;
// Feature that controls whether "popup blocked" prompts use Messages or
// Infobars infrastructure.
extern const base::Feature kMessagesForAndroidPopupBlocked;
+// Feature that controls whether "safety tip" prompts use Messages or
+// Infobars infrastructure.
+extern const base::Feature kMessagesForAndroidSafetyTip;
+
+// Feature that controls whether "save card" prompts use Messages or
+// Infobars infrastructure.
+extern const base::Feature kMessagesForAndroidSaveCard;
+
+// Feature that controls whether "update password" prompt uses Messages or
+// Infobars infrastructure.
+extern const base::Feature kMessagesForAndroidUpdatePassword;
+
bool IsPasswordMessagesUiEnabled();
bool IsPopupBlockedMessagesUiEnabled();
+bool IsSafetyTipMessagesUiEnabled();
+
+bool IsSaveCardMessagesUiEnabled();
+
+bool IsUpdatePasswordMessagesUiEnabled();
+
} // namespace messages
#endif // COMPONENTS_MESSAGES_ANDROID_MESSAGES_FEATURE_H_
diff --git a/chromium/components/messages/android/mock_message_dispatcher_bridge.cc b/chromium/components/messages/android/mock_message_dispatcher_bridge.cc
index 764c2d1df76..b8c43e65666 100644
--- a/chromium/components/messages/android/mock_message_dispatcher_bridge.cc
+++ b/chromium/components/messages/android/mock_message_dispatcher_bridge.cc
@@ -9,4 +9,4 @@ namespace messages {
MockMessageDispatcherBridge::MockMessageDispatcherBridge() = default;
MockMessageDispatcherBridge::~MockMessageDispatcherBridge() = default;
-} // namespace messages \ No newline at end of file
+} // namespace messages
diff --git a/chromium/components/messages/android/mock_message_dispatcher_bridge.h b/chromium/components/messages/android/mock_message_dispatcher_bridge.h
index b4cfcac292d..078a24c06ae 100644
--- a/chromium/components/messages/android/mock_message_dispatcher_bridge.h
+++ b/chromium/components/messages/android/mock_message_dispatcher_bridge.h
@@ -15,11 +15,12 @@ class MockMessageDispatcherBridge : public MessageDispatcherBridge {
MockMessageDispatcherBridge();
~MockMessageDispatcherBridge() override;
- MOCK_METHOD(void,
+ MOCK_METHOD(bool,
EnqueueMessage,
(MessageWrapper * message,
content::WebContents* web_contents,
- MessageScopeType scopeType),
+ MessageScopeType scope_type,
+ MessagePriority priority),
(override));
MOCK_METHOD(void,
DismissMessage,
@@ -31,4 +32,4 @@ class MockMessageDispatcherBridge : public MessageDispatcherBridge {
} // namespace messages
-#endif // COMPONENTS_MESSAGES_ANDROID_MOCK_MESSAGE_DISPATCHER_BRIDGE_H_ \ No newline at end of file
+#endif // COMPONENTS_MESSAGES_ANDROID_MOCK_MESSAGE_DISPATCHER_BRIDGE_H_
diff --git a/chromium/components/metrics/BUILD.gn b/chromium/components/metrics/BUILD.gn
index 2e7364c47c9..4978a1dc3a1 100644
--- a/chromium/components/metrics/BUILD.gn
+++ b/chromium/components/metrics/BUILD.gn
@@ -407,6 +407,7 @@ source_set("unit_tests") {
"call_stack_profile_metadata_unittest.cc",
"call_stack_profile_metrics_provider_unittest.cc",
"child_call_stack_profile_collector_unittest.cc",
+ "clean_exit_beacon_unittest.cc",
"cloned_install_detector_unittest.cc",
"component_metrics_provider_unittest.cc",
"daily_event_unittest.cc",
@@ -449,6 +450,7 @@ source_set("unit_tests") {
":single_sample_metrics",
":test_support",
":ui",
+ "//base",
"//base/test:test_support",
"//build:chromeos_buildflags",
"//components/component_updater:test_support",
diff --git a/chromium/components/metrics/call_stack_profile_builder.h b/chromium/components/metrics/call_stack_profile_builder.h
index 004a4978303..2bab5f17530 100644
--- a/chromium/components/metrics/call_stack_profile_builder.h
+++ b/chromium/components/metrics/call_stack_profile_builder.h
@@ -13,7 +13,6 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/profiler/metadata_recorder.h"
#include "base/profiler/module_cache.h"
#include "base/profiler/profile_builder.h"
@@ -22,6 +21,7 @@
#include "components/metrics/call_stack_profile_params.h"
#include "components/metrics/child_call_stack_profile_collector.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/metrics_proto/sampled_profile.pb.h"
namespace metrics {
diff --git a/chromium/components/metrics/call_stack_profile_builder_unittest.cc b/chromium/components/metrics/call_stack_profile_builder_unittest.cc
index f3b5578c93a..87ee4d4540b 100644
--- a/chromium/components/metrics/call_stack_profile_builder_unittest.cc
+++ b/chromium/components/metrics/call_stack_profile_builder_unittest.cc
@@ -488,7 +488,7 @@ TEST(CallStackProfileBuilderTest, RecordMetadata) {
TestModule module;
base::Frame frame = {0x10, &module};
- metadata_recorder.Set(100, base::nullopt, 10);
+ metadata_recorder.Set(100, absl::nullopt, 10);
profile_builder->RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
profile_builder->OnSampleCompleted({frame}, base::TimeTicks());
diff --git a/chromium/components/metrics/call_stack_profile_metadata.cc b/chromium/components/metrics/call_stack_profile_metadata.cc
index ecf03649515..247ff1a6f8f 100644
--- a/chromium/components/metrics/call_stack_profile_metadata.cc
+++ b/chromium/components/metrics/call_stack_profile_metadata.cc
@@ -14,27 +14,27 @@ namespace {
class MatchesNameHashIndexAndKey {
public:
- MatchesNameHashIndexAndKey(int name_hash_index, base::Optional<int64_t> key)
+ MatchesNameHashIndexAndKey(int name_hash_index, absl::optional<int64_t> key)
: name_hash_index_(name_hash_index), key_(key) {}
bool operator()(const CallStackProfile::MetadataItem& item) const {
- base::Optional<int64_t> item_key_as_optional =
- item.has_key() ? item.key() : base::Optional<int64_t>();
+ absl::optional<int64_t> item_key_as_optional =
+ item.has_key() ? item.key() : absl::optional<int64_t>();
return item.name_hash_index() == name_hash_index_ &&
key_ == item_key_as_optional;
}
private:
int name_hash_index_;
- base::Optional<int64_t> key_;
+ absl::optional<int64_t> key_;
};
// Finds the last value for a prior metadata application with |name_hash_index|
// and |key| from |begin| that was still active at |end|. Returns nullopt if no
// such application exists.
-base::Optional<int64_t> FindLastOpenEndedMetadataValue(
+absl::optional<int64_t> FindLastOpenEndedMetadataValue(
int name_hash_index,
- base::Optional<int64_t> key,
+ absl::optional<int64_t> key,
google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>::iterator
begin,
google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>::iterator
@@ -56,7 +56,7 @@ base::Optional<int64_t> FindLastOpenEndedMetadataValue(
if (!item->has_value()) {
// A matching item was previously applied, but stopped being applied
// before the last sample in the range.
- return base::nullopt;
+ return absl::nullopt;
}
// Else, a matching item was applied at this sample.
@@ -64,13 +64,13 @@ base::Optional<int64_t> FindLastOpenEndedMetadataValue(
}
// No matching items were previously applied.
- return base::nullopt;
+ return absl::nullopt;
}
// Clears any existing metadata changes between |begin| and |end|.
void ClearExistingMetadata(
const int name_hash_index,
- base::Optional<int64_t> key,
+ absl::optional<int64_t> key,
google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>::iterator
begin,
google::protobuf::RepeatedPtrField<CallStackProfile::StackSample>::iterator
@@ -87,8 +87,8 @@ void ClearExistingMetadata(
// Sets the state of |item| to the provided values.
void SetMetadataItem(int name_hash_index,
- base::Optional<int64_t> key,
- base::Optional<int64_t> value,
+ absl::optional<int64_t> key,
+ absl::optional<int64_t> value,
CallStackProfile::MetadataItem* item) {
item->set_name_hash_index(name_hash_index);
if (key.has_value())
@@ -181,7 +181,7 @@ void CallStackProfileMetadata::ApplyMetadata(
// The previously set metadata value immediately prior to begin, or nullopt if
// none.
- const base::Optional<int64_t> previous_value_before_begin =
+ const absl::optional<int64_t> previous_value_before_begin =
FindLastOpenEndedMetadataValue(name_hash_index, item.key,
stack_samples->begin(), begin);
@@ -195,7 +195,7 @@ void CallStackProfileMetadata::ApplyMetadata(
// The previously set metadata value at *end (or the one to be set on the next
// sample if range_terminates_at_last_sample).
- const base::Optional<int64_t> previous_value_at_end =
+ const absl::optional<int64_t> previous_value_at_end =
FindLastOpenEndedMetadataValue(
name_hash_index, item.key, stack_samples->begin(),
// If a sample past the end exists check its value as well, since
@@ -229,7 +229,7 @@ void CallStackProfileMetadata::ApplyMetadata(
// that it is being unset.
previous_value_at_end.has_value()
? *previous_value_at_end
- : base::Optional<int64_t>(),
+ : absl::optional<int64_t>(),
end->mutable_metadata()->Add());
}
}
@@ -241,7 +241,7 @@ bool CallStackProfileMetadata::MetadataKeyCompare::operator()(
}
CallStackProfileMetadata::MetadataKey::MetadataKey(uint64_t name_hash,
- base::Optional<int64_t> key)
+ absl::optional<int64_t> key)
: name_hash(name_hash), key(key) {}
CallStackProfileMetadata::MetadataKey::MetadataKey(const MetadataKey& other) =
diff --git a/chromium/components/metrics/call_stack_profile_metadata.h b/chromium/components/metrics/call_stack_profile_metadata.h
index 18d9ea0b33a..4c6ea496052 100644
--- a/chromium/components/metrics/call_stack_profile_metadata.h
+++ b/chromium/components/metrics/call_stack_profile_metadata.h
@@ -9,8 +9,8 @@
#include <unordered_map>
#include <utility>
-#include "base/optional.h"
#include "base/profiler/metadata_recorder.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/metrics_proto/sampled_profile.pb.h"
namespace metrics {
@@ -60,7 +60,7 @@ class CallStackProfileMetadata {
// Definitions for a map-based representation of sample metadata.
struct MetadataKey {
- MetadataKey(uint64_t name_hash, base::Optional<int64_t> key);
+ MetadataKey(uint64_t name_hash, absl::optional<int64_t> key);
MetadataKey(const MetadataKey& other);
MetadataKey& operator=(const MetadataKey& other);
@@ -68,7 +68,7 @@ class CallStackProfileMetadata {
// The name_hash and optional user-specified key uniquely identifies a
// metadata value. See base::MetadataRecorder for details.
uint64_t name_hash;
- base::Optional<int64_t> key;
+ absl::optional<int64_t> key;
};
using MetadataMap = std::map<MetadataKey, int64_t, MetadataKeyCompare>;
diff --git a/chromium/components/metrics/call_stack_profile_metadata_unittest.cc b/chromium/components/metrics/call_stack_profile_metadata_unittest.cc
index 6541ca3e315..40f85e30b30 100644
--- a/chromium/components/metrics/call_stack_profile_metadata_unittest.cc
+++ b/chromium/components/metrics/call_stack_profile_metadata_unittest.cc
@@ -98,7 +98,7 @@ TEST(CallStackProfileMetadataTest, MetadataRecorder_SetItem) {
CallStackProfileMetadata metadata;
google::protobuf::RepeatedField<uint64_t> name_hashes;
- metadata_recorder.Set(100, base::nullopt, 10);
+ metadata_recorder.Set(100, absl::nullopt, 10);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
@@ -139,7 +139,7 @@ TEST(CallStackProfileMetadataTest, MetadataRecorder_RepeatItem) {
CallStackProfileMetadata metadata;
google::protobuf::RepeatedField<uint64_t> name_hashes;
- metadata_recorder.Set(100, base::nullopt, 10);
+ metadata_recorder.Set(100, absl::nullopt, 10);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
(void)metadata.CreateSampleMetadata(&name_hashes);
@@ -181,12 +181,12 @@ TEST(CallStackProfileMetadataTest, MetadataRecorder_ModifiedItem) {
CallStackProfileMetadata metadata;
google::protobuf::RepeatedField<uint64_t> name_hashes;
- metadata_recorder.Set(100, base::nullopt, 10);
+ metadata_recorder.Set(100, absl::nullopt, 10);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
(void)metadata.CreateSampleMetadata(&name_hashes);
- metadata_recorder.Set(100, base::nullopt, 11);
+ metadata_recorder.Set(100, absl::nullopt, 11);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
@@ -230,12 +230,12 @@ TEST(CallStackProfileMetadataTest, MetadataRecorder_NewItem) {
CallStackProfileMetadata metadata;
google::protobuf::RepeatedField<uint64_t> name_hashes;
- metadata_recorder.Set(100, base::nullopt, 10);
+ metadata_recorder.Set(100, absl::nullopt, 10);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
(void)metadata.CreateSampleMetadata(&name_hashes);
- metadata_recorder.Set(101, base::nullopt, 11);
+ metadata_recorder.Set(101, absl::nullopt, 11);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
@@ -281,12 +281,12 @@ TEST(CallStackProfileMetadataTest, MetadataRecorder_RemovedItem) {
CallStackProfileMetadata metadata;
google::protobuf::RepeatedField<uint64_t> name_hashes;
- metadata_recorder.Set(100, base::nullopt, 10);
+ metadata_recorder.Set(100, absl::nullopt, 10);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
(void)metadata.CreateSampleMetadata(&name_hashes);
- metadata_recorder.Remove(100, base::nullopt);
+ metadata_recorder.Remove(100, absl::nullopt);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
@@ -331,7 +331,7 @@ TEST(CallStackProfileMetadataTest,
CallStackProfileMetadata metadata;
google::protobuf::RepeatedField<uint64_t> name_hashes;
- metadata_recorder.Set(100, base::nullopt, 20);
+ metadata_recorder.Set(100, absl::nullopt, 20);
metadata_recorder.Set(100, 50, 10);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
@@ -356,13 +356,13 @@ TEST(CallStackProfileMetadataTest,
CallStackProfileMetadata metadata;
google::protobuf::RepeatedField<uint64_t> name_hashes;
- metadata_recorder.Set(100, base::nullopt, 20);
+ metadata_recorder.Set(100, absl::nullopt, 20);
metadata_recorder.Set(100, 50, 10);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
(void)metadata.CreateSampleMetadata(&name_hashes);
- metadata_recorder.Remove(100, base::nullopt);
+ metadata_recorder.Remove(100, absl::nullopt);
metadata.RecordMetadata(
base::MetadataRecorder::MetadataProvider(&metadata_recorder));
google::protobuf::RepeatedPtrField<CallStackProfile::MetadataItem> items =
@@ -457,7 +457,7 @@ TEST(CallStackProfileMetadataTest, ApplyMetadata_DifferentKeys) {
const base::MetadataRecorder::Item item1(3, 30, 300);
const base::MetadataRecorder::Item item2(3, 40, 300);
- const base::MetadataRecorder::Item item3(3, base::nullopt, 300);
+ const base::MetadataRecorder::Item item3(3, absl::nullopt, 300);
metadata.ApplyMetadata(item1, stack_samples.begin() + 1,
stack_samples.begin() + 4, &stack_samples,
&name_hashes);
diff --git a/chromium/components/metrics/call_stack_profile_params.h b/chromium/components/metrics/call_stack_profile_params.h
index 7fc8f61711f..72bd9e3cab7 100644
--- a/chromium/components/metrics/call_stack_profile_params.h
+++ b/chromium/components/metrics/call_stack_profile_params.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_METRICS_CALL_STACK_PROFILE_PARAMS_H_
#define COMPONENTS_METRICS_CALL_STACK_PROFILE_PARAMS_H_
-#include "base/time/time.h"
namespace metrics {
diff --git a/chromium/components/metrics/clean_exit_beacon.cc b/chromium/components/metrics/clean_exit_beacon.cc
index a6c090474a9..9ede7e658c1 100644
--- a/chromium/components/metrics/clean_exit_beacon.cc
+++ b/chromium/components/metrics/clean_exit_beacon.cc
@@ -5,10 +5,13 @@
#include "components/metrics/clean_exit_beacon.h"
#include "base/check_op.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/numerics/ranges.h"
#include "build/build_config.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
+#include "components/variations/pref_names.h"
#if defined(OS_WIN)
#include <windows.h>
@@ -19,17 +22,52 @@
#endif
namespace metrics {
+namespace {
+
+// Increments kVariationsCrashStreak if |did_previous_session_exit_cleanly| is
+// false. Also, emits the crash streak to a histogram.
+void MaybeIncrementCrashStreak(bool did_previous_session_exit_cleanly,
+ PrefService* local_state) {
+ // Increment the crash streak if the previous session crashed. Note that the
+ // streak is not cleared if the previous run didn’t crash. Instead, it’s
+ // incremented on each crash until Chrome is able to successfully fetch a new
+ // seed. This way, a seed update that mostly destabilizes Chrome still results
+ // in a fallback to safe mode.
+ //
+ // The crash streak is incremented here rather than in a variations-related
+ // class for two reasons. First, the crash streak depends on the value of
+ // kStabilityExitedCleanly. Second, if kVariationsCrashStreak were updated in
+ // another function, any crash between CleanExitBeacon() and that function
+ // would cause the crash streak to not be to incremented. A consequence of
+ // failing to increment the crash streak is that variations safe mode might
+ // undercount or be completely unaware of repeated crashes early on in
+ // startup.
+ int num_crashes =
+ local_state->GetInteger(variations::prefs::kVariationsCrashStreak);
+ if (!did_previous_session_exit_cleanly) {
+ ++num_crashes;
+ local_state->SetInteger(variations::prefs::kVariationsCrashStreak,
+ num_crashes);
+ }
+ base::UmaHistogramSparse("Variations.SafeMode.Streak.Crashes",
+ base::ClampToRange(num_crashes, 0, 100));
+}
+
+} // namespace
CleanExitBeacon::CleanExitBeacon(const std::wstring& backup_registry_key,
PrefService* local_state)
: local_state_(local_state),
- initial_value_(local_state->GetBoolean(prefs::kStabilityExitedCleanly)),
+ did_previous_session_exit_cleanly_(
+ local_state->GetBoolean(prefs::kStabilityExitedCleanly)),
initial_browser_last_live_timestamp_(
local_state->GetTime(prefs::kStabilityBrowserLastLiveTimeStamp)),
backup_registry_key_(backup_registry_key) {
DCHECK_NE(PrefService::INITIALIZATION_STATUS_WAITING,
local_state_->GetInitializationStatus());
+ MaybeIncrementCrashStreak(did_previous_session_exit_cleanly_, local_state_);
+
#if defined(OS_WIN)
// An enumeration of all possible permutations of the the beacon state in the
// registry and in Local State.
@@ -50,29 +88,24 @@ CleanExitBeacon::CleanExitBeacon(const std::wstring& backup_registry_key,
regkey.ReadValueDW(
base::ASCIIToWide(prefs::kStabilityExitedCleanly).c_str(), &value) ==
ERROR_SUCCESS) {
- if (value)
- consistency = initial_value_ ? CLEAN_CLEAN : CLEAN_DIRTY;
- else
- consistency = initial_value_ ? DIRTY_CLEAN : DIRTY_DIRTY;
+ if (value) {
+ consistency =
+ did_previous_session_exit_cleanly_ ? CLEAN_CLEAN : CLEAN_DIRTY;
+ } else {
+ consistency =
+ did_previous_session_exit_cleanly_ ? DIRTY_CLEAN : DIRTY_DIRTY;
+ }
} else {
- consistency = initial_value_ ? MISSING_CLEAN : MISSING_DIRTY;
+ consistency =
+ did_previous_session_exit_cleanly_ ? MISSING_CLEAN : MISSING_DIRTY;
}
UMA_HISTOGRAM_ENUMERATION(
"UMA.CleanExitBeaconConsistency", consistency, NUM_CONSISTENCY_ENUMS);
-#endif
-}
-
-CleanExitBeacon::~CleanExitBeacon() {
+#endif // defined(OS_WIN)
}
-// static
-void CleanExitBeacon::RegisterPrefs(PrefRegistrySimple* registry) {
- registry->RegisterBooleanPref(prefs::kStabilityExitedCleanly, true);
-
- registry->RegisterTimePref(prefs::kStabilityBrowserLastLiveTimeStamp,
- base::Time(), PrefRegistry::LOSSY_PREF);
-}
+CleanExitBeacon::~CleanExitBeacon() = default;
void CleanExitBeacon::WriteBeaconValue(bool value) {
UpdateLastLiveTimestamp();
@@ -85,7 +118,7 @@ void CleanExitBeacon::WriteBeaconValue(bool value) {
regkey.WriteValue(base::ASCIIToWide(prefs::kStabilityExitedCleanly).c_str(),
value ? 1u : 0u);
}
-#endif
+#endif // defined(OS_WIN)
}
void CleanExitBeacon::UpdateLastLiveTimestamp() {
@@ -93,4 +126,23 @@ void CleanExitBeacon::UpdateLastLiveTimestamp() {
base::Time::Now());
}
+// static
+void CleanExitBeacon::RegisterPrefs(PrefRegistrySimple* registry) {
+ registry->RegisterBooleanPref(prefs::kStabilityExitedCleanly, true);
+
+ registry->RegisterTimePref(prefs::kStabilityBrowserLastLiveTimeStamp,
+ base::Time(), PrefRegistry::LOSSY_PREF);
+
+ // This variations-safe-mode-related pref is registered here rather than in
+ // SafeSeedManager::RegisterPrefs() because the CleanExitBeacon is
+ // responsible for incrementing this value. (See the comments in
+ // MaybeIncrementCrashStreak() for more details.)
+ registry->RegisterIntegerPref(variations::prefs::kVariationsCrashStreak, 0);
+}
+
+// static
+void CleanExitBeacon::EnsureCleanShutdown(PrefService* local_state) {
+ CHECK(local_state->GetBoolean(prefs::kStabilityExitedCleanly));
+}
+
} // namespace metrics
diff --git a/chromium/components/metrics/clean_exit_beacon.h b/chromium/components/metrics/clean_exit_beacon.h
index 28f1ae70fe1..0f1f10e3448 100644
--- a/chromium/components/metrics/clean_exit_beacon.h
+++ b/chromium/components/metrics/clean_exit_beacon.h
@@ -19,17 +19,22 @@ namespace metrics {
// process exited cleanly.
class CleanExitBeacon {
public:
- // Instantiates a CleanExitBeacon whose value is stored in |local_state|.
- // |local_state| must be fully initialized.
- // On Windows, |backup_registry_key| is used to store a backup of the beacon.
- // It is ignored on other platforms.
+ // Instantiates a CleanExitBeacon whose value is stored in |local_state|'s
+ // kStabilityExitedCleanly pref. |local_state| must be fully initialized.
+ //
+ // On Windows, |backup_registry_key| stores a backup of the beacon to verify
+ // that the pref's value corresponds to the registry's. |backup_registry_key|
+ // is ignored on other platforms, but iOS has a similar verification
+ // mechanism using LastSessionExitedCleanly in
+ // ios/chrome/browser/pref_names.cc.
+ // TODO(crbug.com/1208077): Use the CleanExitBeacon for verification on iOS.
CleanExitBeacon(const std::wstring& backup_registry_key,
PrefService* local_state);
~CleanExitBeacon();
// Returns the original value of the beacon.
- bool exited_cleanly() const { return initial_value_; }
+ bool exited_cleanly() const { return did_previous_session_exit_cleanly_; }
// Returns the original value of the last live timestamp.
base::Time browser_last_live_timestamp() const {
@@ -45,9 +50,12 @@ class CleanExitBeacon {
// Registers local state prefs used by this class.
static void RegisterPrefs(PrefRegistrySimple* registry);
+ // CHECKs that Chrome exited cleanly.
+ static void EnsureCleanShutdown(PrefService* local_state);
+
private:
PrefService* const local_state_;
- const bool initial_value_;
+ const bool did_previous_session_exit_cleanly_;
// This is the value of the last live timestamp from local state at the
// time of construction. It notes a timestamp from the previous browser
diff --git a/chromium/components/metrics/clean_exit_beacon_unittest.cc b/chromium/components/metrics/clean_exit_beacon_unittest.cc
new file mode 100644
index 00000000000..05547e1b856
--- /dev/null
+++ b/chromium/components/metrics/clean_exit_beacon_unittest.cc
@@ -0,0 +1,90 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/metrics/clean_exit_beacon.h"
+
+#include <string>
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/time/time.h"
+#include "components/metrics/metrics_pref_names.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/variations/pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace metrics {
+namespace {
+
+const wchar_t kDummyWindowsRegistryKey[] = L"";
+
+} // namespace
+
+TEST(CleanExitBeaconTest, CrashStreakMetricWithDefaultPrefs) {
+ TestingPrefServiceSimple pref_service;
+ CleanExitBeacon::RegisterPrefs(pref_service.registry());
+ base::HistogramTester histogram_tester;
+
+ CleanExitBeacon clean_exit_beacon(kDummyWindowsRegistryKey, &pref_service);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 0,
+ 1);
+}
+
+TEST(CleanExitBeaconTest, CrashStreakMetricWithNoCrashes) {
+ TestingPrefServiceSimple pref_service;
+ CleanExitBeacon::RegisterPrefs(pref_service.registry());
+ // The default value for kStabilityExitedCleanly is true, but defaults can
+ // change, so we explicitly set it to true here. Similarly, we explicitly set
+ // kVariationsCrashStreak to 0.
+ pref_service.SetBoolean(prefs::kStabilityExitedCleanly, true);
+ pref_service.SetInteger(variations::prefs::kVariationsCrashStreak, 0);
+ base::HistogramTester histogram_tester;
+
+ CleanExitBeacon clean_exit_beacon(kDummyWindowsRegistryKey, &pref_service);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 0,
+ 1);
+}
+
+TEST(CleanExitBeaconTest, CrashStreakMetricWithSomeCrashes) {
+ TestingPrefServiceSimple pref_service;
+ CleanExitBeacon::RegisterPrefs(pref_service.registry());
+ // The default value for kStabilityExitedCleanly is true, but defaults can
+ // change, so we explicitly set it to true here.
+ pref_service.SetBoolean(prefs::kStabilityExitedCleanly, true);
+ pref_service.SetInteger(variations::prefs::kVariationsCrashStreak, 1);
+ base::HistogramTester histogram_tester;
+
+ CleanExitBeacon clean_exit_beacon(kDummyWindowsRegistryKey, &pref_service);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 1,
+ 1);
+}
+
+TEST(CleanExitBeaconTest, CrashIncrementsCrashStreak) {
+ TestingPrefServiceSimple pref_service;
+ CleanExitBeacon::RegisterPrefs(pref_service.registry());
+ pref_service.SetBoolean(prefs::kStabilityExitedCleanly, false);
+ pref_service.SetInteger(variations::prefs::kVariationsCrashStreak, 1);
+ base::HistogramTester histogram_tester;
+
+ CleanExitBeacon clean_exit_beacon(kDummyWindowsRegistryKey, &pref_service);
+ EXPECT_EQ(pref_service.GetInteger(variations::prefs::kVariationsCrashStreak),
+ 2);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 2,
+ 1);
+}
+
+TEST(CleanExitBeaconTest,
+ CrashIncrementsCrashStreakWithDefaultCrashStreakPref) {
+ TestingPrefServiceSimple pref_service;
+ CleanExitBeacon::RegisterPrefs(pref_service.registry());
+ pref_service.SetBoolean(prefs::kStabilityExitedCleanly, false);
+ base::HistogramTester histogram_tester;
+
+ CleanExitBeacon clean_exit_beacon(kDummyWindowsRegistryKey, &pref_service);
+ EXPECT_EQ(pref_service.GetInteger(variations::prefs::kVariationsCrashStreak),
+ 1);
+ histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 1,
+ 1);
+}
+
+} // namespace metrics
diff --git a/chromium/components/metrics/daily_event_unittest.cc b/chromium/components/metrics/daily_event_unittest.cc
index f9a6f52c7f0..5adf718519c 100644
--- a/chromium/components/metrics/daily_event_unittest.cc
+++ b/chromium/components/metrics/daily_event_unittest.cc
@@ -6,9 +6,9 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/optional.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace metrics {
@@ -30,7 +30,7 @@ class TestDailyObserver : public DailyEvent::Observer {
private:
// Last-received type, or unset if OnDailyEvent() hasn't been called.
- base::Optional<DailyEvent::IntervalType> type_;
+ absl::optional<DailyEvent::IntervalType> type_;
DISALLOW_COPY_AND_ASSIGN(TestDailyObserver);
};
diff --git a/chromium/components/metrics/data_use_tracker.cc b/chromium/components/metrics/data_use_tracker.cc
index 1588b895b41..23eb81a7236 100644
--- a/chromium/components/metrics/data_use_tracker.cc
+++ b/chromium/components/metrics/data_use_tracker.cc
@@ -4,10 +4,12 @@
#include "components/metrics/data_use_tracker.h"
+#include <memory>
#include <string>
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/prefs/scoped_user_pref_update.h"
@@ -37,7 +39,7 @@ std::unique_ptr<DataUseTracker> DataUseTracker::Create(
// Instantiate DataUseTracker only on Android. UpdateMetricsUsagePrefs() honors
// this rule too.
#if defined(OS_ANDROID)
- data_use_tracker.reset(new DataUseTracker(local_state));
+ data_use_tracker = std::make_unique<DataUseTracker>(local_state);
#endif
return data_use_tracker;
}
@@ -138,7 +140,8 @@ void DataUseTracker::RemoveExpiredEntriesForPref(const std::string& pref_name) {
base::Time key_date;
if (base::Time::FromUTCString(it.key().c_str(), &key_date) &&
key_date > week_ago)
- user_pref_new_dict.Set(it.key(), it.value().CreateDeepCopy());
+ user_pref_new_dict.Set(it.key(),
+ base::Value::ToUniquePtrValue(it.value().Clone()));
}
local_state_->Set(pref_name, user_pref_new_dict);
}
@@ -155,9 +158,7 @@ int DataUseTracker::ComputeTotalDataUse(const std::string& pref_name) {
local_state_->GetDictionary(pref_name);
for (base::DictionaryValue::Iterator it(*pref_dict); !it.IsAtEnd();
it.Advance()) {
- int value = 0;
- it.value().GetAsInteger(&value);
- total_data_use += value;
+ total_data_use += it.value().GetIfInt().value_or(0);
}
return total_data_use;
}
diff --git a/chromium/components/metrics/data_use_tracker_unittest.cc b/chromium/components/metrics/data_use_tracker_unittest.cc
index 7174823cf51..674cb254da7 100644
--- a/chromium/components/metrics/data_use_tracker_unittest.cc
+++ b/chromium/components/metrics/data_use_tracker_unittest.cc
@@ -4,7 +4,6 @@
#include "components/metrics/data_use_tracker.h"
-#include "base/strings/stringprintf.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
diff --git a/chromium/components/metrics/demographics/demographic_metrics_provider.cc b/chromium/components/metrics/demographics/demographic_metrics_provider.cc
index ec05167873e..7dd42b16e7d 100644
--- a/chromium/components/metrics/demographics/demographic_metrics_provider.cc
+++ b/chromium/components/metrics/demographics/demographic_metrics_provider.cc
@@ -6,9 +6,9 @@
#include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
-#include "base/optional.h"
#include "build/chromeos_buildflags.h"
#include "components/sync/driver/sync_service_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/metrics_proto/ukm/report.pb.h"
namespace metrics {
@@ -51,11 +51,11 @@ DemographicMetricsProvider::DemographicMetricsProvider(
DemographicMetricsProvider::~DemographicMetricsProvider() {}
-base::Optional<UserDemographics>
+absl::optional<UserDemographics>
DemographicMetricsProvider::ProvideSyncedUserNoisedBirthYearAndGender() {
// Skip if feature disabled.
if (!base::FeatureList::IsEnabled(kDemographicMetricsReporting))
- return base::nullopt;
+ return absl::nullopt;
#if !BUILDFLAG(IS_CHROMEOS_ASH)
// Skip if not exactly one Profile on disk. Having more than one Profile that
@@ -71,7 +71,7 @@ DemographicMetricsProvider::ProvideSyncedUserNoisedBirthYearAndGender() {
if (profile_client_->GetNumberOfProfilesOnDisk() != 1) {
LogUserDemographicsStatusInHistogram(
UserDemographicsStatus::kMoreThanOneProfile);
- return base::nullopt;
+ return absl::nullopt;
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
@@ -80,13 +80,13 @@ DemographicMetricsProvider::ProvideSyncedUserNoisedBirthYearAndGender() {
if (!sync_service) {
LogUserDemographicsStatusInHistogram(
UserDemographicsStatus::kNoSyncService);
- return base::nullopt;
+ return absl::nullopt;
}
if (!CanUploadDemographicsToGoogle(sync_service)) {
LogUserDemographicsStatusInHistogram(
UserDemographicsStatus::kSyncNotEnabled);
- return base::nullopt;
+ return absl::nullopt;
}
UserDemographicsResult demographics_result =
@@ -97,7 +97,7 @@ DemographicMetricsProvider::ProvideSyncedUserNoisedBirthYearAndGender() {
if (demographics_result.IsSuccess())
return demographics_result.value();
- return base::nullopt;
+ return absl::nullopt;
}
void DemographicMetricsProvider::ProvideCurrentSessionData(
diff --git a/chromium/components/metrics/demographics/demographic_metrics_provider.h b/chromium/components/metrics/demographics/demographic_metrics_provider.h
index 074c3849410..fe4aa99f05e 100644
--- a/chromium/components/metrics/demographics/demographic_metrics_provider.h
+++ b/chromium/components/metrics/demographics/demographic_metrics_provider.h
@@ -13,6 +13,7 @@
#include "components/metrics/metrics_provider.h"
#include "components/metrics/ukm_demographic_metrics_provider.h"
#include "components/sync/driver/sync_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
#include "third_party/metrics_proto/user_demographics.pb.h"
@@ -72,7 +73,7 @@ class DemographicMetricsProvider : public MetricsProvider,
void ProvideSyncedUserNoisedBirthYearAndGender(ReportType* report) {
DCHECK(report);
- base::Optional<UserDemographics> user_demographics =
+ absl::optional<UserDemographics> user_demographics =
ProvideSyncedUserNoisedBirthYearAndGender();
if (user_demographics.has_value()) {
report->mutable_user_demographics()->set_birth_year(
@@ -95,7 +96,7 @@ class DemographicMetricsProvider : public MetricsProvider,
private:
// Provides the synced user's noised birth year and gender.
- base::Optional<UserDemographics> ProvideSyncedUserNoisedBirthYearAndGender();
+ absl::optional<UserDemographics> ProvideSyncedUserNoisedBirthYearAndGender();
void LogUserDemographicsStatusInHistogram(UserDemographicsStatus status);
diff --git a/chromium/components/metrics/demographics/user_demographics.cc b/chromium/components/metrics/demographics/user_demographics.cc
index 6ad61d4fa62..2d6490f1a38 100644
--- a/chromium/components/metrics/demographics/user_demographics.cc
+++ b/chromium/components/metrics/demographics/user_demographics.cc
@@ -7,11 +7,11 @@
#include <utility>
#include "base/check.h"
-#include "base/optional.h"
#include "base/rand_util.h"
#include "base/values.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace metrics {
@@ -101,7 +101,7 @@ bool HasEligibleBirthYear(base::Time now, int user_birth_year, int offset) {
// Gets the synced user's birth year from synced prefs, see doc of
// DemographicMetricsProvider in demographic_metrics_provider.h for more
// details.
-base::Optional<int> GetUserBirthYear(
+absl::optional<int> GetUserBirthYear(
const base::DictionaryValue* demographics) {
const base::Value* value =
demographics->FindPath(kSyncDemographicsBirthYearPath);
@@ -111,7 +111,7 @@ base::Optional<int> GetUserBirthYear(
// Verify that there is a birth year.
if (birth_year == kUserDemographicsBirthYearDefaultValue)
- return base::nullopt;
+ return absl::nullopt;
return birth_year;
}
@@ -119,7 +119,7 @@ base::Optional<int> GetUserBirthYear(
// Gets the synced user's gender from synced prefs, see doc of
// DemographicMetricsProvider in demographic_metrics_provider.h for more
// details.
-base::Optional<UserDemographicsProto_Gender> GetUserGender(
+absl::optional<UserDemographicsProto_Gender> GetUserGender(
const base::DictionaryValue* demographics) {
const base::Value* value =
demographics->FindPath(kSyncDemographicsGenderPath);
@@ -129,12 +129,12 @@ base::Optional<UserDemographicsProto_Gender> GetUserGender(
// Verify that the gender is not default.
if (gender_int == kUserDemographicsGenderDefaultValue)
- return base::nullopt;
+ return absl::nullopt;
// Verify that the gender number is a valid UserDemographicsProto_Gender
// encoding.
if (!UserDemographicsProto_Gender_IsValid(gender_int))
- return base::nullopt;
+ return absl::nullopt;
auto gender = UserDemographicsProto_Gender(gender_int);
@@ -142,7 +142,7 @@ base::Optional<UserDemographicsProto_Gender> GetUserGender(
// anonymity.
if (gender != UserDemographicsProto::GENDER_FEMALE &&
gender != UserDemographicsProto::GENDER_MALE) {
- return base::nullopt;
+ return absl::nullopt;
}
return gender;
@@ -221,14 +221,14 @@ UserDemographicsResult GetUserNoisedBirthYearAndGenderFromPrefs(
DCHECK(demographics != nullptr);
// Get the user's birth year.
- base::Optional<int> birth_year = GetUserBirthYear(demographics);
+ absl::optional<int> birth_year = GetUserBirthYear(demographics);
if (!birth_year.has_value()) {
return UserDemographicsResult::ForStatus(
UserDemographicsStatus::kIneligibleDemographicsData);
}
// Get the user's gender.
- base::Optional<UserDemographicsProto_Gender> gender =
+ absl::optional<UserDemographicsProto_Gender> gender =
GetUserGender(demographics);
if (!gender.has_value()) {
return UserDemographicsResult::ForStatus(
diff --git a/chromium/components/metrics/drive_metrics_provider_win.cc b/chromium/components/metrics/drive_metrics_provider_win.cc
index 6c1334e217c..9e3a3f84781 100644
--- a/chromium/components/metrics/drive_metrics_provider_win.cc
+++ b/chromium/components/metrics/drive_metrics_provider_win.cc
@@ -10,7 +10,6 @@
#include "base/files/file.h"
#include "base/files/file_path.h"
-#include "base/strings/stringprintf.h"
namespace metrics {
diff --git a/chromium/components/metrics/expired_histogram_util.cc b/chromium/components/metrics/expired_histogram_util.cc
index fc591963582..b1ffb445591 100644
--- a/chromium/components/metrics/expired_histogram_util.cc
+++ b/chromium/components/metrics/expired_histogram_util.cc
@@ -24,7 +24,7 @@ const base::FeatureParam<std::string> kAllowlistParam{
} // namespace
-void EnableExpiryChecker(const uint64_t* expired_histograms_hashes,
+void EnableExpiryChecker(const uint32_t* expired_histograms_hashes,
size_t num_expired_histograms) {
DCHECK(base::FeatureList::GetInstance());
if (base::FeatureList::IsEnabled(kExpiredHistogramLogicFeature)) {
diff --git a/chromium/components/metrics/expired_histogram_util.h b/chromium/components/metrics/expired_histogram_util.h
index cf6c455ed93..d0e25e70404 100644
--- a/chromium/components/metrics/expired_histogram_util.h
+++ b/chromium/components/metrics/expired_histogram_util.h
@@ -13,7 +13,7 @@ namespace metrics {
// Enables histogram expiry checker if it is enabled by field trial. Histogram
// expiry is disbaled by default so that unit tests don't fail unexpectedly when
// a histogram expires.
-void EnableExpiryChecker(const uint64_t* expired_histograms_hashes,
+void EnableExpiryChecker(const uint32_t* expired_histograms_hashes,
size_t num_expired_histograms);
} // namespace metrics
diff --git a/chromium/components/metrics/expired_histograms_checker.cc b/chromium/components/metrics/expired_histograms_checker.cc
index 878399290f3..23665542ce9 100644
--- a/chromium/components/metrics/expired_histograms_checker.cc
+++ b/chromium/components/metrics/expired_histograms_checker.cc
@@ -15,7 +15,7 @@
namespace metrics {
ExpiredHistogramsChecker::ExpiredHistogramsChecker(
- const uint64_t* expired_histogram_hashes,
+ const uint32_t* expired_histogram_hashes,
size_t size,
const std::string& allowlist_str)
: expired_histogram_hashes_(expired_histogram_hashes), size_(size) {
@@ -24,7 +24,7 @@ ExpiredHistogramsChecker::ExpiredHistogramsChecker(
ExpiredHistogramsChecker::~ExpiredHistogramsChecker() {}
-bool ExpiredHistogramsChecker::ShouldRecord(uint64_t histogram_hash) const {
+bool ExpiredHistogramsChecker::ShouldRecord(uint32_t histogram_hash) const {
// If histogram is explicitly allowed then it should always be recorded.
if (base::Contains(allowlist_, histogram_hash))
return true;
@@ -36,7 +36,7 @@ void ExpiredHistogramsChecker::InitAllowlist(const std::string& allowlist_str) {
std::vector<base::StringPiece> allowlist_names = base::SplitStringPiece(
allowlist_str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
for (base::StringPiece name : allowlist_names)
- allowlist_.insert(base::HashMetricName(name));
+ allowlist_.insert(base::HashMetricNameAs32Bits(name));
}
} // namespace metrics
diff --git a/chromium/components/metrics/expired_histograms_checker.h b/chromium/components/metrics/expired_histograms_checker.h
index 510d4441709..4fddd0c208d 100644
--- a/chromium/components/metrics/expired_histograms_checker.h
+++ b/chromium/components/metrics/expired_histograms_checker.h
@@ -22,13 +22,13 @@ class ExpiredHistogramsChecker final : public base::RecordHistogramChecker {
// list of explicitly allowed histogram names as a comma-separated string.
// Histograms in the |allowlist_str| are logged even if their hash is in the
// |expired_histograms_hashes|.
- ExpiredHistogramsChecker(const uint64_t* expired_histogram_hashes,
+ ExpiredHistogramsChecker(const uint32_t* expired_histogram_hashes,
size_t size,
const std::string& allowlist_str);
~ExpiredHistogramsChecker() override;
// Checks if the given |histogram_hash| corresponds to an expired histogram.
- bool ShouldRecord(uint64_t histogram_hash) const override;
+ bool ShouldRecord(uint32_t histogram_hash) const override;
private:
// Initializes the |allowlist_| array of histogram hashes that should be
@@ -36,13 +36,13 @@ class ExpiredHistogramsChecker final : public base::RecordHistogramChecker {
void InitAllowlist(const std::string& allowlist_str);
// Array of expired histogram hashes.
- const uint64_t* const expired_histogram_hashes_;
+ const uint32_t* const expired_histogram_hashes_;
// Size of the |expired_histogram_hashes_|.
const size_t size_;
// Set of expired histogram hashes that should be recorded.
- std::set<uint64_t> allowlist_;
+ std::set<uint32_t> allowlist_;
DISALLOW_COPY_AND_ASSIGN(ExpiredHistogramsChecker);
};
diff --git a/chromium/components/metrics/expired_histograms_checker_unittest.cc b/chromium/components/metrics/expired_histograms_checker_unittest.cc
index 4ae6ba23d91..b31d58ccd19 100644
--- a/chromium/components/metrics/expired_histograms_checker_unittest.cc
+++ b/chromium/components/metrics/expired_histograms_checker_unittest.cc
@@ -10,7 +10,7 @@
namespace metrics {
TEST(ExpiredHistogramsCheckerTests, BasicTest) {
- uint64_t expired_hashes[] = {1, 2, 3};
+ uint32_t expired_hashes[] = {1, 2, 3};
size_t size = 3;
std::string allowlist_str = "";
ExpiredHistogramsChecker checker(expired_hashes, size, allowlist_str);
@@ -25,16 +25,16 @@ TEST(ExpiredHistogramsCheckerTests, AllowlistTest) {
std::string hist3 = "hist3";
std::string hist4 = "hist4";
- uint64_t expired_hashes[] = {base::HashMetricName(hist1),
- base::HashMetricName(hist2)};
+ uint32_t expired_hashes[] = {base::HashMetricNameAs32Bits(hist1),
+ base::HashMetricNameAs32Bits(hist2)};
size_t size = 2;
std::string allowlist_str = hist2 + "," + hist4;
ExpiredHistogramsChecker checker(expired_hashes, size, allowlist_str);
- EXPECT_FALSE(checker.ShouldRecord(base::HashMetricName(hist1)));
- EXPECT_TRUE(checker.ShouldRecord(base::HashMetricName(hist2)));
- EXPECT_TRUE(checker.ShouldRecord(base::HashMetricName(hist3)));
- EXPECT_TRUE(checker.ShouldRecord(base::HashMetricName(hist4)));
+ EXPECT_FALSE(checker.ShouldRecord(base::HashMetricNameAs32Bits(hist1)));
+ EXPECT_TRUE(checker.ShouldRecord(base::HashMetricNameAs32Bits(hist2)));
+ EXPECT_TRUE(checker.ShouldRecord(base::HashMetricNameAs32Bits(hist3)));
+ EXPECT_TRUE(checker.ShouldRecord(base::HashMetricNameAs32Bits(hist4)));
}
} // namespace metrics
diff --git a/chromium/components/metrics/file_metrics_provider.cc b/chromium/components/metrics/file_metrics_provider.cc
index cf0d7ab4a81..9c3a0680138 100644
--- a/chromium/components/metrics/file_metrics_provider.cc
+++ b/chromium/components/metrics/file_metrics_provider.cc
@@ -238,8 +238,8 @@ void FileMetricsProvider::RegisterSource(const Params& params) {
void FileMetricsProvider::RegisterSourcePrefs(
PrefRegistrySimple* prefs,
const base::StringPiece prefs_key) {
- prefs->RegisterInt64Pref(metrics::prefs::kMetricsLastSeenPrefix +
- prefs_key.as_string(), 0);
+ prefs->RegisterInt64Pref(
+ metrics::prefs::kMetricsLastSeenPrefix + std::string(prefs_key), 0);
}
// static
@@ -479,6 +479,41 @@ FileMetricsProvider::AccessResult FileMetricsProvider::CheckAndMapMetricSource(
if (!file.IsValid())
return ACCESS_RESULT_NO_OPEN;
+ // Check that file is writable if that is expected. If a write is attempted
+ // on an unwritable memory-mapped file, a SIGBUS will cause a crash.
+ const bool read_only = kSourceOptions[source->type].is_read_only;
+ if (!read_only) {
+ constexpr int kTestSize = 16;
+ char header[kTestSize];
+ int amount = file.Read(0, header, kTestSize);
+ if (amount != kTestSize)
+ return ACCESS_RESULT_INVALID_CONTENTS;
+
+ char zeros[kTestSize] = {0};
+ file.Write(0, zeros, kTestSize);
+ file.Flush();
+
+ // A crash here would be unfortunate as the file would be left invalid
+ // and skipped/deleted by later attempts. This is unlikely, however, and
+ // the benefit of avoiding crashes from mapping as read/write a file that
+ // can't be written more than justifies the risk.
+
+ char check[kTestSize];
+ amount = file.Read(0, check, kTestSize);
+ if (amount != kTestSize)
+ return ACCESS_RESULT_INVALID_CONTENTS;
+ if (memcmp(check, zeros, kTestSize) != 0)
+ return ACCESS_RESULT_NOT_WRITABLE;
+
+ file.Write(0, header, kTestSize);
+ file.Flush();
+ amount = file.Read(0, check, kTestSize);
+ if (amount != kTestSize)
+ return ACCESS_RESULT_INVALID_CONTENTS;
+ if (memcmp(check, header, kTestSize) != 0)
+ return ACCESS_RESULT_NOT_WRITABLE;
+ }
+
std::unique_ptr<base::MemoryMappedFile> mapped(new base::MemoryMappedFile());
if (!mapped->Initialize(std::move(file),
kSourceOptions[source->type].memory_mapped_access)) {
@@ -489,7 +524,6 @@ FileMetricsProvider::AccessResult FileMetricsProvider::CheckAndMapMetricSource(
source->last_seen = info.last_modified;
// Test the validity of the file contents.
- const bool read_only = kSourceOptions[source->type].is_read_only;
if (!base::FilePersistentMemoryAllocator::IsFileAcceptable(*mapped,
read_only)) {
return ACCESS_RESULT_INVALID_CONTENTS;
diff --git a/chromium/components/metrics/file_metrics_provider.h b/chromium/components/metrics/file_metrics_provider.h
index c7e195c7445..fe782751a89 100644
--- a/chromium/components/metrics/file_metrics_provider.h
+++ b/chromium/components/metrics/file_metrics_provider.h
@@ -7,7 +7,6 @@
#include <list>
#include <memory>
-#include <string>
#include "base/callback_forward.h"
#include "base/files/file_path.h"
@@ -240,6 +239,9 @@ class FileMetricsProvider : public MetricsProvider,
// The file had internal data corruption.
ACCESS_RESULT_DATA_CORRUPTION,
+ // The file is not writable when it should be.
+ ACCESS_RESULT_NOT_WRITABLE,
+
ACCESS_RESULT_MAX
};
diff --git a/chromium/components/metrics/generate_expired_histograms_array.gni b/chromium/components/metrics/generate_expired_histograms_array.gni
index cc9fabb70aa..ed071ca80f0 100644
--- a/chromium/components/metrics/generate_expired_histograms_array.gni
+++ b/chromium/components/metrics/generate_expired_histograms_array.gni
@@ -50,13 +50,14 @@ template("generate_expired_histograms_array") {
"//tools/metrics/histograms/histograms_xml/chrome/histograms.xml",
"//tools/metrics/histograms/histograms_xml/chromeos/histograms.xml",
"//tools/metrics/histograms/histograms_xml/cloud/histograms.xml",
+ "//tools/metrics/histograms/histograms_xml/commerce/histograms.xml",
"//tools/metrics/histograms/histograms_xml/compositing/histograms.xml",
"//tools/metrics/histograms/histograms_xml/content/histograms.xml",
"//tools/metrics/histograms/histograms_xml/cookie/histograms.xml",
"//tools/metrics/histograms/histograms_xml/cras/histograms.xml",
"//tools/metrics/histograms/histograms_xml/cros/histograms.xml",
+ "//tools/metrics/histograms/histograms_xml/cross_device/histograms.xml",
"//tools/metrics/histograms/histograms_xml/crostini/histograms.xml",
- "//tools/metrics/histograms/histograms_xml/crypt/histograms.xml",
"//tools/metrics/histograms/histograms_xml/cryptohome/histograms.xml",
"//tools/metrics/histograms/histograms_xml/custom_tabs/histograms.xml",
"//tools/metrics/histograms/histograms_xml/data_reduction_proxy/histograms.xml",
@@ -83,7 +84,6 @@ template("generate_expired_histograms_array") {
"//tools/metrics/histograms/histograms_xml/image/histograms.xml",
"//tools/metrics/histograms/histograms_xml/input/histograms.xml",
"//tools/metrics/histograms/histograms_xml/installer/histograms.xml",
- "//tools/metrics/histograms/histograms_xml/instant/histograms.xml",
"//tools/metrics/histograms/histograms_xml/interstitial/histograms.xml",
"//tools/metrics/histograms/histograms_xml/ios/histograms.xml",
"//tools/metrics/histograms/histograms_xml/local/histograms.xml",
@@ -91,7 +91,6 @@ template("generate_expired_histograms_array") {
"//tools/metrics/histograms/histograms_xml/media/histograms.xml",
"//tools/metrics/histograms/histograms_xml/memory/histograms.xml",
"//tools/metrics/histograms/histograms_xml/mobile/histograms.xml",
- "//tools/metrics/histograms/histograms_xml/multi_device/histograms.xml",
"//tools/metrics/histograms/histograms_xml/na_cl/histograms.xml",
"//tools/metrics/histograms/histograms_xml/navigation/histograms.xml",
"//tools/metrics/histograms/histograms_xml/nearby/histograms.xml",
@@ -127,13 +126,13 @@ template("generate_expired_histograms_array") {
"//tools/metrics/histograms/histograms_xml/scheduler/histograms.xml",
"//tools/metrics/histograms/histograms_xml/search/histograms.xml",
"//tools/metrics/histograms/histograms_xml/security/histograms.xml",
+ "//tools/metrics/histograms/histograms_xml/segmentation_platform/histograms.xml",
"//tools/metrics/histograms/histograms_xml/service/histograms.xml",
"//tools/metrics/histograms/histograms_xml/session/histograms.xml",
"//tools/metrics/histograms/histograms_xml/settings/histograms.xml",
"//tools/metrics/histograms/histograms_xml/sharing/histograms.xml",
"//tools/metrics/histograms/histograms_xml/signin/histograms.xml",
"//tools/metrics/histograms/histograms_xml/simple/histograms.xml",
- "//tools/metrics/histograms/histograms_xml/smart/histograms.xml",
"//tools/metrics/histograms/histograms_xml/software/histograms.xml",
"//tools/metrics/histograms/histograms_xml/stability/histograms.xml",
"//tools/metrics/histograms/histograms_xml/startup/histograms.xml",
diff --git a/chromium/components/metrics/library_support/histogram_manager.h b/chromium/components/metrics/library_support/histogram_manager.h
index 331eca06da5..1465284bae9 100644
--- a/chromium/components/metrics/library_support/histogram_manager.h
+++ b/chromium/components/metrics/library_support/histogram_manager.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <memory>
-#include <string>
#include <vector>
#include "base/lazy_instance.h"
diff --git a/chromium/components/metrics/metrics_log.cc b/chromium/components/metrics/metrics_log.cc
index 807f90c0b7c..384f8490012 100644
--- a/chromium/components/metrics/metrics_log.cc
+++ b/chromium/components/metrics/metrics_log.cc
@@ -10,6 +10,7 @@
#include <string>
#include "base/build_time.h"
+#include "base/command_line.h"
#include "base/cpu.h"
#include "base/logging.h"
#include "base/metrics/histogram_base.h"
@@ -20,7 +21,6 @@
#include "base/metrics/histogram_snapshot_manager.h"
#include "base/metrics/metrics_hashes.h"
#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -33,6 +33,7 @@
#include "components/metrics/metrics_service_client.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
+#include "components/variations/hashing.h"
#include "third_party/metrics_proto/histogram_event.pb.h"
#include "third_party/metrics_proto/system_profile.pb.h"
#include "third_party/metrics_proto/user_action_event.pb.h"
@@ -190,6 +191,14 @@ void MetricsLog::RecordCoreSystemProfile(MetricsServiceClient* client,
std::string brand_code;
if (client->GetBrand(&brand_code))
system_profile->set_brand_code(brand_code);
+
+ // Records 32-bit hashes of the command line keys.
+ const auto command_line_switches =
+ base::CommandLine::ForCurrentProcess()->GetSwitches();
+ for (const auto& command_line_switch : command_line_switches) {
+ system_profile->add_command_line_key_hash(
+ variations::HashName(command_line_switch.first));
+ }
}
// static
diff --git a/chromium/components/metrics/metrics_log.h b/chromium/components/metrics/metrics_log.h
index e0b9f465a40..4043e92f045 100644
--- a/chromium/components/metrics/metrics_log.h
+++ b/chromium/components/metrics/metrics_log.h
@@ -113,11 +113,11 @@ class MetricsLog {
// always incrementing for use in measuring time durations.
static int64_t GetCurrentTime();
- // Record core profile settings into the SystemProfileProto.
+ // Records core profile settings into the SystemProfileProto.
static void RecordCoreSystemProfile(MetricsServiceClient* client,
SystemProfileProto* system_profile);
- // Record core profile settings into the SystemProfileProto without a client.
+ // Records core profile settings into the SystemProfileProto without a client.
static void RecordCoreSystemProfile(
const std::string& version,
metrics::SystemProfileProto::Channel channel,
diff --git a/chromium/components/metrics/metrics_log_manager.cc b/chromium/components/metrics/metrics_log_manager.cc
index 28794486a76..072ea3ec36c 100644
--- a/chromium/components/metrics/metrics_log_manager.cc
+++ b/chromium/components/metrics/metrics_log_manager.cc
@@ -30,7 +30,7 @@ void MetricsLogManager::FinishCurrentLog(MetricsLogStore* log_store) {
current_log_->GetEncodedLog(&log_data);
if (!log_data.empty()) {
log_store->StoreLog(log_data, current_log_->log_type(),
- base::make_optional(current_log_->samples_count()));
+ absl::make_optional(current_log_->samples_count()));
}
current_log_.reset();
}
diff --git a/chromium/components/metrics/metrics_log_manager.h b/chromium/components/metrics/metrics_log_manager.h
index 88d8fe2ce44..123a186c028 100644
--- a/chromium/components/metrics/metrics_log_manager.h
+++ b/chromium/components/metrics/metrics_log_manager.h
@@ -8,7 +8,6 @@
#include <stddef.h>
#include <memory>
-#include <string>
#include <vector>
#include "base/macros.h"
diff --git a/chromium/components/metrics/metrics_log_store.cc b/chromium/components/metrics/metrics_log_store.cc
index 6fdcc7e5b9e..8dfbddf176e 100644
--- a/chromium/components/metrics/metrics_log_store.cc
+++ b/chromium/components/metrics/metrics_log_store.cc
@@ -51,7 +51,7 @@ void MetricsLogStore::LoadPersistedUnsentLogs() {
void MetricsLogStore::StoreLog(
const std::string& log_data,
MetricsLog::LogType log_type,
- base::Optional<base::HistogramBase::Count> samples_count) {
+ absl::optional<base::HistogramBase::Count> samples_count) {
switch (log_type) {
case MetricsLog::INITIAL_STABILITY_LOG:
initial_log_queue_.StoreLog(log_data, samples_count);
diff --git a/chromium/components/metrics/metrics_log_store.h b/chromium/components/metrics/metrics_log_store.h
index ed0ee01b26a..14f1552d3f1 100644
--- a/chromium/components/metrics/metrics_log_store.h
+++ b/chromium/components/metrics/metrics_log_store.h
@@ -9,10 +9,10 @@
#include "base/macros.h"
#include "base/metrics/histogram_base.h"
-#include "base/optional.h"
#include "components/metrics/log_store.h"
#include "components/metrics/metrics_log.h"
#include "components/metrics/unsent_log_store.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
class PrefRegistrySimple;
@@ -64,7 +64,7 @@ class MetricsLogStore : public LogStore {
// Saves |log_data| as the given type.
void StoreLog(const std::string& log_data,
MetricsLog::LogType log_type,
- base::Optional<base::HistogramBase::Count> samples_count);
+ absl::optional<base::HistogramBase::Count> samples_count);
// LogStore:
bool has_unsent_logs() const override;
diff --git a/chromium/components/metrics/metrics_log_store_unittest.cc b/chromium/components/metrics/metrics_log_store_unittest.cc
index e90b25e0ab2..da9ee767533 100644
--- a/chromium/components/metrics/metrics_log_store_unittest.cc
+++ b/chromium/components/metrics/metrics_log_store_unittest.cc
@@ -50,7 +50,7 @@ TEST_F(MetricsLogStoreTest, StandardFlow) {
EXPECT_FALSE(log_store.has_staged_log());
EXPECT_FALSE(log_store.has_unsent_logs());
- log_store.StoreLog("a", MetricsLog::ONGOING_LOG, base::nullopt);
+ log_store.StoreLog("a", MetricsLog::ONGOING_LOG, absl::nullopt);
EXPECT_TRUE(log_store.has_unsent_logs());
EXPECT_FALSE(log_store.has_staged_log());
@@ -71,7 +71,7 @@ TEST_F(MetricsLogStoreTest, StoreAndLoad) {
std::string());
log_store.LoadPersistedUnsentLogs();
EXPECT_FALSE(log_store.has_unsent_logs());
- log_store.StoreLog("a", MetricsLog::ONGOING_LOG, base::nullopt);
+ log_store.StoreLog("a", MetricsLog::ONGOING_LOG, absl::nullopt);
log_store.TrimAndPersistUnsentLogs();
EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
EXPECT_EQ(1U, TypeCount(MetricsLog::ONGOING_LOG));
@@ -85,9 +85,9 @@ TEST_F(MetricsLogStoreTest, StoreAndLoad) {
EXPECT_TRUE(log_store.has_unsent_logs());
EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
EXPECT_EQ(1U, TypeCount(MetricsLog::ONGOING_LOG));
- log_store.StoreLog("x", MetricsLog::INITIAL_STABILITY_LOG, base::nullopt);
+ log_store.StoreLog("x", MetricsLog::INITIAL_STABILITY_LOG, absl::nullopt);
log_store.StageNextLog();
- log_store.StoreLog("b", MetricsLog::ONGOING_LOG, base::nullopt);
+ log_store.StoreLog("b", MetricsLog::ONGOING_LOG, absl::nullopt);
EXPECT_TRUE(log_store.has_unsent_logs());
EXPECT_TRUE(log_store.has_staged_log());
@@ -139,7 +139,7 @@ TEST_F(MetricsLogStoreTest, StoreStagedOngoingLog) {
MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
std::string());
log_store.LoadPersistedUnsentLogs();
- log_store.StoreLog("a", MetricsLog::ONGOING_LOG, base::nullopt);
+ log_store.StoreLog("a", MetricsLog::ONGOING_LOG, absl::nullopt);
log_store.StageNextLog();
log_store.TrimAndPersistUnsentLogs();
@@ -152,7 +152,7 @@ TEST_F(MetricsLogStoreTest, StoreStagedInitialLog) {
MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
std::string());
log_store.LoadPersistedUnsentLogs();
- log_store.StoreLog("b", MetricsLog::INITIAL_STABILITY_LOG, base::nullopt);
+ log_store.StoreLog("b", MetricsLog::INITIAL_STABILITY_LOG, absl::nullopt);
log_store.StageNextLog();
log_store.TrimAndPersistUnsentLogs();
@@ -168,8 +168,8 @@ TEST_F(MetricsLogStoreTest, LargeLogDiscarding) {
log_store.LoadPersistedUnsentLogs();
log_store.StoreLog("persisted", MetricsLog::INITIAL_STABILITY_LOG,
- base::nullopt);
- log_store.StoreLog("not_persisted", MetricsLog::ONGOING_LOG, base::nullopt);
+ absl::nullopt);
+ log_store.StoreLog("not_persisted", MetricsLog::ONGOING_LOG, absl::nullopt);
// Only the stability log should be written out, due to the threshold.
log_store.TrimAndPersistUnsentLogs();
@@ -184,10 +184,10 @@ TEST_F(MetricsLogStoreTest, DiscardOrder) {
std::string());
log_store.LoadPersistedUnsentLogs();
- log_store.StoreLog("a", MetricsLog::ONGOING_LOG, base::nullopt);
- log_store.StoreLog("b", MetricsLog::ONGOING_LOG, base::nullopt);
+ log_store.StoreLog("a", MetricsLog::ONGOING_LOG, absl::nullopt);
+ log_store.StoreLog("b", MetricsLog::ONGOING_LOG, absl::nullopt);
log_store.StageNextLog();
- log_store.StoreLog("c", MetricsLog::INITIAL_STABILITY_LOG, base::nullopt);
+ log_store.StoreLog("c", MetricsLog::INITIAL_STABILITY_LOG, absl::nullopt);
EXPECT_EQ(2U, log_store.ongoing_log_count());
EXPECT_EQ(1U, log_store.initial_log_count());
// Should discard the ongoing log staged earlier.
diff --git a/chromium/components/metrics/metrics_log_unittest.cc b/chromium/components/metrics/metrics_log_unittest.cc
index 19462db63a8..0393b819e31 100644
--- a/chromium/components/metrics/metrics_log_unittest.cc
+++ b/chromium/components/metrics/metrics_log_unittest.cc
@@ -16,7 +16,6 @@
#include "base/metrics/sample_vector.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -149,6 +148,14 @@ TEST_F(MetricsLogTest, BasicRecord) {
client.set_version_string("bogus version");
const std::string kClientId = "totally bogus client ID";
TestingPrefServiceSimple prefs;
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ // Clears existing command line flags and sets mock flags:
+ // "--mock-flag-1 --mock-flag-2=unused_value"
+ // Hashes of these flags should be populated on the system_profile field.
+ command_line->InitFromArgv(0, nullptr);
+ command_line->AppendSwitch("mock-flag-1");
+ command_line->AppendSwitchASCII("mock-flag-2", "unused_value");
+
MetricsLog log(kClientId, 137, MetricsLog::ONGOING_LOG, &client);
log.CloseLog();
@@ -172,6 +179,9 @@ TEST_F(MetricsLogTest, BasicRecord) {
system_profile->set_channel(client.GetChannel());
system_profile->set_application_locale(client.GetApplicationLocale());
system_profile->set_brand_code(TestMetricsServiceClient::kBrandForTesting);
+ // Hashes of "mock-flag-1" and "mock-flag-2" from SetUpCommandLine.
+ system_profile->add_command_line_key_hash(2578836236);
+ system_profile->add_command_line_key_hash(2867288449);
#if defined(ADDRESS_SANITIZER) || DCHECK_IS_ON()
system_profile->set_is_instrumented_build(true);
diff --git a/chromium/components/metrics/metrics_service.cc b/chromium/components/metrics/metrics_service.cc
index ec20bfdeaa1..d6fee1d197a 100644
--- a/chromium/components/metrics/metrics_service.cc
+++ b/chromium/components/metrics/metrics_service.cc
@@ -5,7 +5,7 @@
//------------------------------------------------------------------------------
// Description of the life cycle of a instance of MetricsService.
//
-// OVERVIEW
+// OVERVIEW
//
// A MetricsService instance is typically created at application startup. It is
// the central controller for the acquisition of log data, and the automatic
@@ -141,6 +141,7 @@
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "components/metrics/clean_exit_beacon.h"
#include "components/metrics/environment_recorder.h"
#include "components/metrics/field_trials_provider.h"
#include "components/metrics/metrics_log.h"
@@ -176,22 +177,9 @@ const int kInitializationDelaySeconds = 30;
// The browser last live timestamp is updated every 15 minutes.
const int kUpdateAliveTimestampSeconds = 15 * 60;
-#if defined(OS_ANDROID) || defined(OS_IOS)
-void MarkAppCleanShutdownAndCommit(CleanExitBeacon* clean_exit_beacon,
- PrefService* local_state) {
- clean_exit_beacon->WriteBeaconValue(true);
- // Start writing right away (write happens on a different thread).
- local_state->CommitPendingWrite();
-}
-#endif // defined(OS_ANDROID) || defined(OS_IOS)
-
} // namespace
// static
-MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ =
- MetricsService::CLEANLY_SHUTDOWN;
-
-// static
void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) {
CleanExitBeacon::RegisterPrefs(registry);
MetricsStateManager::RegisterPrefs(registry);
@@ -402,8 +390,9 @@ void MetricsService::OnAppEnterBackground(bool keep_recording_in_background) {
reporting_service_.Stop();
}
- MarkAppCleanShutdownAndCommit(state_manager_->clean_exit_beacon(),
- local_state_);
+ state_manager_->LogHasSessionShutdownCleanly(true);
+ // Schedule a write, which happens on a different thread.
+ local_state_->CommitPendingWrite();
// Give providers a chance to persist histograms as part of being
// backgrounded.
@@ -424,7 +413,7 @@ void MetricsService::OnAppEnterBackground(bool keep_recording_in_background) {
void MetricsService::OnAppEnterForeground(bool force_open_new_log) {
is_in_foreground_ = true;
- state_manager_->clean_exit_beacon()->WriteBeaconValue(false);
+ state_manager_->LogHasSessionShutdownCleanly(false);
StartSchedulerIfNecessary();
if (force_open_new_log && recording_active() && state_ >= SENDING_LOGS) {
@@ -437,13 +426,10 @@ void MetricsService::OnAppEnterForeground(bool force_open_new_log) {
#else
void MetricsService::LogNeedForCleanShutdown() {
- state_manager_->clean_exit_beacon()->WriteBeaconValue(false);
- // Redundant setting to be sure we call for a clean shutdown.
- clean_shutdown_status_ = NEED_TO_SHUTDOWN;
+ state_manager_->LogHasSessionShutdownCleanly(false);
}
#endif // defined(OS_ANDROID) || defined(OS_IOS)
-
void MetricsService::ClearSavedStabilityMetrics() {
delegating_provider_.ClearSavedStabilityMetrics();
}
@@ -489,9 +475,6 @@ void MetricsService::InitializeMetricsState() {
if (!state_manager_->clean_exit_beacon()->exited_cleanly()) {
provider.LogCrash(
state_manager_->clean_exit_beacon()->browser_last_live_timestamp());
- // Reset flag, and wait until we call LogNeedForCleanShutdown() before
- // monitoring.
- state_manager_->clean_exit_beacon()->WriteBeaconValue(true);
}
// HasPreviousSessionData is called first to ensure it is never bypassed.
@@ -809,12 +792,6 @@ void MetricsService::IncrementLongPrefsValue(const char* path) {
local_state_->SetInt64(path, value + 1);
}
-bool MetricsService::UmaMetricsProperlyShutdown() {
- CHECK(clean_shutdown_status_ == CLEANLY_SHUTDOWN ||
- clean_shutdown_status_ == NEED_TO_SHUTDOWN);
- return clean_shutdown_status_ == CLEANLY_SHUTDOWN;
-}
-
void MetricsService::RegisterMetricsProvider(
std::unique_ptr<MetricsProvider> provider) {
DCHECK_EQ(CONSTRUCTED, state_);
@@ -958,11 +935,7 @@ void MetricsService::PrepareProviderMetricsTask() {
void MetricsService::LogCleanShutdown(bool end_completed) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Redundant setting to assure that we always reset this value at shutdown
- // (and that we don't use some alternate path, and not call LogCleanShutdown).
- clean_shutdown_status_ = CLEANLY_SHUTDOWN;
- client_->OnLogCleanShutdown();
- state_manager_->clean_exit_beacon()->WriteBeaconValue(true);
+ state_manager_->LogHasSessionShutdownCleanly(true);
StabilityMetricsProvider(local_state_).MarkSessionEndCompleted(end_completed);
}
diff --git a/chromium/components/metrics/metrics_service.h b/chromium/components/metrics/metrics_service.h
index 8594e50d846..7fbcf1a486f 100644
--- a/chromium/components/metrics/metrics_service.h
+++ b/chromium/components/metrics/metrics_service.h
@@ -25,7 +25,6 @@
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "components/metrics/clean_exit_beacon.h"
#include "components/metrics/delegating_provider.h"
#include "components/metrics/metrics_log.h"
#include "components/metrics/metrics_log_manager.h"
@@ -136,7 +135,8 @@ class MetricsService : public base::HistogramFlattener {
// Called when the application is coming out of background mode.
void OnAppEnterForeground(bool force_open_new_log = false);
#else
- // Set the dirty flag, which will require a later call to LogCleanShutdown().
+ // Signals that the session has not yet exited cleanly. Calling this later
+ // requires a call to LogCleanShutdown().
void LogNeedForCleanShutdown();
#endif // defined(OS_ANDROID) || defined(OS_IOS)
@@ -144,10 +144,6 @@ class MetricsService : public base::HistogramFlattener {
bool reporting_active() const;
bool has_unsent_logs() const;
- // Redundant test to ensure that we are notified of a clean exit.
- // This value should be true when process has completed shutdown.
- static bool UmaMetricsProperlyShutdown();
-
// Register the specified |provider| to provide additional metrics into the
// UMA log. Should be called during MetricsService initialization only.
void RegisterMetricsProvider(std::unique_ptr<MetricsProvider> provider);
@@ -208,11 +204,6 @@ class MetricsService : public base::HistogramFlattener {
State state() const { return state_; }
private:
- enum ShutdownCleanliness {
- CLEANLY_SHUTDOWN = 0xdeadbeef,
- NEED_TO_SHUTDOWN = ~CLEANLY_SHUTDOWN
- };
-
// The current state of recording for the MetricsService. The state is UNSET
// until set to something else, at which point it remains INACTIVE or ACTIVE
// for the lifetime of the object.
@@ -403,10 +394,6 @@ class MetricsService : public base::HistogramFlattener {
bool is_in_foreground_ = false;
#endif
- // Redundant marker to check that we completed our shutdown, and set the
- // exited-cleanly bit in the prefs.
- static ShutdownCleanliness clean_shutdown_status_;
-
FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, ActiveFieldTrialsReported);
FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, IsPluginProcess);
FRIEND_TEST_ALL_PREFIXES(::ChromeMetricsServiceClientTest,
diff --git a/chromium/components/metrics/metrics_service_accessor.h b/chromium/components/metrics/metrics_service_accessor.h
index 967ad5a69b9..ba31bcb3482 100644
--- a/chromium/components/metrics/metrics_service_accessor.h
+++ b/chromium/components/metrics/metrics_service_accessor.h
@@ -6,7 +6,6 @@
#define COMPONENTS_METRICS_METRICS_SERVICE_ACCESSOR_H_
#include <stdint.h>
-#include <vector>
#include "base/macros.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/components/metrics/metrics_service_client.cc b/chromium/components/metrics/metrics_service_client.cc
index 9ad8361748c..5054743529d 100644
--- a/chromium/components/metrics/metrics_service_client.cc
+++ b/chromium/components/metrics/metrics_service_client.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "build/build_config.h"
#include "components/metrics/metrics_switches.h"
#include "components/metrics/url_constants.h"
@@ -25,7 +26,12 @@ constexpr int kMetricsUploadIntervalSecMinimum = 20;
// then we will discard the log, and not try to retransmit it. We also don't
// persist the log to the prefs for transmission during the next chrome session
// if this limit is exceeded.
+#if defined(OS_CHROMEOS)
+// Increase CrOS limit to accommodate SampledProfile data (crbug.com/1210595).
+constexpr size_t kMaxOngoingLogSize = 1024 * 1024; // 1 MiB
+#else
constexpr size_t kMaxOngoingLogSize = 100 * 1024; // 100 KiB
+#endif // defined(OS_CHROMEOS)
// The number of bytes of logs to save of each type (initial/ongoing). This
// ensures that a reasonable amount of history will be stored even if there is a
@@ -58,6 +64,11 @@ ukm::UkmService* MetricsServiceClient::GetUkmService() {
return nullptr;
}
+bool MetricsServiceClient::ShouldUploadMetricsForUserId(
+ const uint64_t user_id) {
+ return true;
+}
+
GURL MetricsServiceClient::GetMetricsServerUrl() {
return GURL(kNewMetricsServerUrl);
}
diff --git a/chromium/components/metrics/metrics_service_client.h b/chromium/components/metrics/metrics_service_client.h
index 9a925993663..277cbd69f8b 100644
--- a/chromium/components/metrics/metrics_service_client.h
+++ b/chromium/components/metrics/metrics_service_client.h
@@ -47,6 +47,10 @@ class MetricsServiceClient {
// Returns the UkmService instance that this client is associated with.
virtual ukm::UkmService* GetUkmService();
+ // Returns true if metrics should be uploaded for the given |user_id|, which
+ // corresponds to the |user_id| field in ChromeUserMetricsExtension.
+ virtual bool ShouldUploadMetricsForUserId(const uint64_t user_id);
+
// Registers the client id with other services (e.g. crash reporting), called
// when metrics recording gets enabled.
virtual void SetMetricsClientId(const std::string& client_id) = 0;
@@ -78,9 +82,6 @@ class MetricsServiceClient {
// ownership.
virtual void OnEnvironmentUpdate(std::string* serialized_environment) {}
- // Called by the metrics service to record a clean shutdown.
- virtual void OnLogCleanShutdown() {}
-
// Called prior to a metrics log being closed, allowing the client to collect
// extra histograms that will go in that log. Asynchronous API - the client
// implementation should call |done_callback| when complete.
diff --git a/chromium/components/metrics/metrics_service_unittest.cc b/chromium/components/metrics/metrics_service_unittest.cc
index 036dc1eb14e..052733eb9f8 100644
--- a/chromium/components/metrics/metrics_service_unittest.cc
+++ b/chromium/components/metrics/metrics_service_unittest.cc
@@ -193,7 +193,7 @@ class MetricsServiceTest : public testing::Test {
// the histogram was not found.
int GetHistogramSampleCount(const ChromeUserMetricsExtension& uma_log,
base::StringPiece histogram_name) {
- const auto histogram_name_hash = HashMetricName(histogram_name);
+ const auto histogram_name_hash = base::HashMetricName(histogram_name);
int samples = 0;
for (int i = 0; i < uma_log.histogram_event_size(); ++i) {
const auto& histogram = uma_log.histogram_event(i);
@@ -469,7 +469,7 @@ TEST_F(MetricsServiceTest, FirstLogCreatedBeforeUnsentLogsSent) {
// is never deserialized to proto, so we're just passing some dummy content.
ASSERT_EQ(0u, test_log_store->initial_log_count());
ASSERT_EQ(0u, test_log_store->ongoing_log_count());
- test_log_store->StoreLog("blah_blah", MetricsLog::ONGOING_LOG, base::nullopt);
+ test_log_store->StoreLog("blah_blah", MetricsLog::ONGOING_LOG, absl::nullopt);
// Note: |initial_log_count()| refers to initial stability logs, so the above
// log is counted an ongoing log (per its type).
ASSERT_EQ(0u, test_log_store->initial_log_count());
diff --git a/chromium/components/metrics/metrics_state_manager.cc b/chromium/components/metrics/metrics_state_manager.cc
index 44f3df50adf..77a708d3c76 100644
--- a/chromium/components/metrics/metrics_state_manager.cc
+++ b/chromium/components/metrics/metrics_state_manager.cc
@@ -221,6 +221,11 @@ int MetricsStateManager::GetLowEntropySource() {
return entropy_state_.GetLowEntropySource();
}
+void MetricsStateManager::LogHasSessionShutdownCleanly(
+ bool has_session_shutdown_cleanly) {
+ clean_exit_beacon_.WriteBeaconValue(has_session_shutdown_cleanly);
+}
+
void MetricsStateManager::ForceClientIdCreation() {
// TODO(asvitkine): Ideally, all tests would actually set up consent properly,
// so the command-line check wouldn't be needed here.
diff --git a/chromium/components/metrics/metrics_state_manager.h b/chromium/components/metrics/metrics_state_manager.h
index 0ae78a31c06..f9c98c4644a 100644
--- a/chromium/components/metrics/metrics_state_manager.h
+++ b/chromium/components/metrics/metrics_state_manager.h
@@ -66,6 +66,15 @@ class MetricsStateManager final {
return &clean_exit_beacon_;
}
+ // Signals whether the session has shutdown cleanly. Passing `false` means
+ // that Chrome has launched and has not yet shut down safely. Passing `true`
+ // signals that Chrome has shut down safely.
+ //
+ // Seeing a call with `false` without a matching call with `true` suggests
+ // that Chrome crashed or otherwise did not shut down cleanly, e.g. maybe the
+ // OS crashed.
+ void LogHasSessionShutdownCleanly(bool has_session_shutdown_cleanly);
+
// Forces the client ID to be generated. This is useful in case it's needed
// before recording.
void ForceClientIdCreation();
diff --git a/chromium/components/metrics/metrics_state_manager_unittest.cc b/chromium/components/metrics/metrics_state_manager_unittest.cc
index 2b04e590181..6c45c142acf 100644
--- a/chromium/components/metrics/metrics_state_manager_unittest.cc
+++ b/chromium/components/metrics/metrics_state_manager_unittest.cc
@@ -30,7 +30,6 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace metrics {
-
namespace {
// Verifies that the client id follows the expected pattern.
@@ -222,6 +221,22 @@ TEST_F(MetricsStateManagerTest, ResetMetricsIDs) {
EXPECT_NE(kInitialClientId, prefs_.GetString(prefs::kMetricsClientID));
}
+TEST_F(MetricsStateManagerTest, LogHasSessionShutdownCleanly) {
+ std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
+ prefs_.SetBoolean(prefs::kStabilityExitedCleanly, false);
+ state_manager->LogHasSessionShutdownCleanly(
+ /*has_session_shutdown_cleanly=*/true);
+ EXPECT_TRUE(prefs_.GetBoolean(prefs::kStabilityExitedCleanly));
+}
+
+TEST_F(MetricsStateManagerTest, LogSessionHasNotYetShutdownCleanly) {
+ std::unique_ptr<MetricsStateManager> state_manager(CreateStateManager());
+ ASSERT_TRUE(prefs_.GetBoolean(prefs::kStabilityExitedCleanly));
+ state_manager->LogHasSessionShutdownCleanly(
+ /*has_session_shutdown_cleanly=*/false);
+ EXPECT_FALSE(prefs_.GetBoolean(prefs::kStabilityExitedCleanly));
+}
+
TEST_F(MetricsStateManagerTest, ForceClientIdCreation) {
const int64_t kFakeInstallationDate = 12345;
prefs_.SetInt64(prefs::kInstallDate, kFakeInstallationDate);
diff --git a/chromium/components/metrics/net/net_metrics_log_uploader.cc b/chromium/components/metrics/net/net_metrics_log_uploader.cc
index 29c11c26fb3..49baad66495 100644
--- a/chromium/components/metrics/net/net_metrics_log_uploader.cc
+++ b/chromium/components/metrics/net/net_metrics_log_uploader.cc
@@ -9,14 +9,10 @@
#include "base/base64.h"
#include "base/bind.h"
#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/statistics_recorder.h"
-#include "base/rand_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
-#include "base/threading/sequenced_task_runner_handle.h"
#include "components/encrypted_messages/encrypted_message.pb.h"
#include "components/encrypted_messages/message_encrypter.h"
#include "components/metrics/metrics_log_uploader.h"
@@ -36,26 +32,6 @@ namespace {
const base::Feature kHttpRetryFeature{"UMAHttpRetry",
base::FEATURE_ENABLED_BY_DEFAULT};
-// Run ablation on UMA collector connectivity to client. This study will
-// ablate a clients upload of all logs that use |metrics::ReportingService|
-// to upload logs. This include |metrics::MetricsReportingService| for uploading
-// UMA logs. |ukm::UKMReportionService| for uploading UKM logs.
-// To restrict the study to UMA or UKM, set the "service-affected" param.
-const base::Feature kAblateMetricsLogUploadFeature{
- "AblateMetricsLogUpload", base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Fraction of Collector uploads that should be failed artificially.
-constexpr base::FeatureParam<int> kParamFailureRate{
- &kAblateMetricsLogUploadFeature, "failure-rate", 100};
-
-// HTTP Error code to pass when artificially failing uploads.
-constexpr base::FeatureParam<int> kParamErrorCode{
- &kAblateMetricsLogUploadFeature, "error-code", 503};
-
-// Service type to ablate. Can be "UMA" or "UKM". Leave it empty to ablate all.
-constexpr base::FeatureParam<std::string> kParamAblateServiceType{
- &kAblateMetricsLogUploadFeature, "service-type", ""};
-
// Constants used for encrypting logs that are sent over HTTP. The
// corresponding private key is used by the metrics server to decrypt logs.
const char kEncryptedMessageLabel[] = "metrics log";
@@ -365,25 +341,6 @@ void NetMetricsLogUploader::UploadLogToURL(
url_loader_->AttachStringForUpload(compressed_log_data, mime_type_);
}
- if (base::FeatureList::IsEnabled(kAblateMetricsLogUploadFeature)) {
- int failure_rate = kParamFailureRate.Get();
- std::string service_restrict = kParamAblateServiceType.Get();
- bool should_ablate =
- service_restrict.empty() ||
- (service_type_ == MetricsLogUploader::UMA &&
- service_restrict == "UMA") ||
- (service_type_ == MetricsLogUploader::UKM && service_restrict == "UKM");
- if (should_ablate && base::RandInt(0, 99) < failure_rate) {
- // Simulate collector outage by not actually trying to upload the
- // logs but instead call on_upload_complete_ immediately.
- bool was_https = url.SchemeIs(url::kHttpsScheme);
- url_loader_.reset();
- base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(on_upload_complete_, kParamErrorCode.Get(),
- net::ERR_FAILED, was_https));
- return;
- }
- }
// It's safe to use |base::Unretained(this)| here, because |this| owns
// the |url_loader_|, and the callback will be cancelled if the |url_loader_|
// is destroyed.
diff --git a/chromium/components/metrics/net/network_metrics_provider.cc b/chromium/components/metrics/net/network_metrics_provider.cc
index 08ca707ca83..b91031f3eca 100644
--- a/chromium/components/metrics/net/network_metrics_provider.cc
+++ b/chromium/components/metrics/net/network_metrics_provider.cc
@@ -12,7 +12,6 @@
#include <vector>
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
#include "base/metrics/histogram_macros.h"
@@ -276,6 +275,12 @@ NetworkMetricsProvider::GetWifiPHYLayerProtocol() const {
return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_G;
case net::WIFI_PHY_LAYER_PROTOCOL_N:
return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_N;
+ case net::WIFI_PHY_LAYER_PROTOCOL_AC:
+ return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_AC;
+ case net::WIFI_PHY_LAYER_PROTOCOL_AD:
+ return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_AD;
+ case net::WIFI_PHY_LAYER_PROTOCOL_AX:
+ return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_AX;
case net::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN:
return SystemProfileProto::Network::WIFI_PHY_LAYER_PROTOCOL_UNKNOWN;
}
diff --git a/chromium/components/metrics/net/network_metrics_provider_unittest.cc b/chromium/components/metrics/net/network_metrics_provider_unittest.cc
index e462beeea9d..e9f1203e76c 100644
--- a/chromium/components/metrics/net/network_metrics_provider_unittest.cc
+++ b/chromium/components/metrics/net/network_metrics_provider_unittest.cc
@@ -18,8 +18,7 @@
#include "third_party/metrics_proto/system_profile.pb.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_handler_test_helper.h"
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
#if defined(OS_IOS)
@@ -39,22 +38,11 @@ class NetworkMetricsProviderTest : public testing::Test {
: task_environment_(MetricsTaskEnvironment::IO_MAINLOOP) {}
~NetworkMetricsProviderTest() override {}
- void SetUp() override {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
- chromeos::DBusThreadManager::Initialize();
- chromeos::NetworkHandler::Initialize();
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
- }
-
- void TearDown() override {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
- chromeos::NetworkHandler::Shutdown();
- chromeos::DBusThreadManager::Shutdown();
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
- }
-
private:
MetricsTaskEnvironment task_environment_;
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ chromeos::NetworkHandlerTestHelper network_handler_test_helper_;
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
DISALLOW_COPY_AND_ASSIGN(NetworkMetricsProviderTest);
};
diff --git a/chromium/components/metrics/persistent_system_profile.h b/chromium/components/metrics/persistent_system_profile.h
index 6c854a92753..5511be939f3 100644
--- a/chromium/components/metrics/persistent_system_profile.h
+++ b/chromium/components/metrics/persistent_system_profile.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 BASE_METRICS_PERSISTENT_SYSTEM_PROFILE_H_
-#define BASE_METRICS_PERSISTENT_SYSTEM_PROFILE_H_
+#ifndef COMPONENTS_METRICS_PERSISTENT_SYSTEM_PROFILE_H_
+#define COMPONENTS_METRICS_PERSISTENT_SYSTEM_PROFILE_H_
#include <vector>
@@ -157,4 +157,4 @@ class GlobalPersistentSystemProfile : public PersistentSystemProfile {
} // namespace metrics
-#endif // BASE_METRICS_PERSISTENT_SYSTEM_PROFILE_H_
+#endif // COMPONENTS_METRICS_PERSISTENT_SYSTEM_PROFILE_H_
diff --git a/chromium/components/metrics/public/mojom/call_stack_profile_collector.mojom b/chromium/components/metrics/public/mojom/call_stack_profile_collector.mojom
index 51fcf816bad..3d38d90b2fe 100644
--- a/chromium/components/metrics/public/mojom/call_stack_profile_collector.mojom
+++ b/chromium/components/metrics/public/mojom/call_stack_profile_collector.mojom
@@ -4,6 +4,7 @@
module metrics.mojom;
+import "mojo/public/mojom/base/byte_string.mojom";
import "mojo/public/mojom/base/time.mojom";
// |contents| is a serialized protobuf from
@@ -12,7 +13,7 @@ import "mojo/public/mojom/base/time.mojom";
// We pass this state via serialized protobuf because that is the ultimate
// metrics upload format.
struct SampledProfile {
- string contents;
+ mojo_base.mojom.ByteString contents;
};
interface CallStackProfileCollector {
diff --git a/chromium/components/metrics/serialization/metric_sample.cc b/chromium/components/metrics/serialization/metric_sample.cc
index 3876fc37fe6..d6549a6761d 100644
--- a/chromium/components/metrics/serialization/metric_sample.cc
+++ b/chromium/components/metrics/serialization/metric_sample.cc
@@ -9,6 +9,7 @@
#include "base/check_op.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"
@@ -129,7 +130,7 @@ std::unique_ptr<MetricSample> MetricSample::ParseHistogram(
return nullptr;
}
- return HistogramSample(parts[0].as_string(), sample, min, max, bucket_count);
+ return HistogramSample(std::string(parts[0]), sample, min, max, bucket_count);
}
// static
@@ -151,7 +152,7 @@ std::unique_ptr<MetricSample> MetricSample::ParseSparseHistogram(
if (parts[0].empty() || !base::StringToInt(parts[1], &sample))
return nullptr;
- return SparseHistogramSample(parts[0].as_string(), sample);
+ return SparseHistogramSample(std::string(parts[0]), sample);
}
// static
@@ -176,7 +177,7 @@ std::unique_ptr<MetricSample> MetricSample::ParseLinearHistogram(
return nullptr;
}
- return LinearHistogramSample(parts[0].as_string(), sample, max);
+ return LinearHistogramSample(std::string(parts[0]), sample, max);
}
// static
diff --git a/chromium/components/metrics/serialization/serialization_utils.cc b/chromium/components/metrics/serialization/serialization_utils.cc
index 223d0cbeeaa..4ab151b1cb4 100644
--- a/chromium/components/metrics/serialization/serialization_utils.cc
+++ b/chromium/components/metrics/serialization/serialization_utils.cc
@@ -10,6 +10,7 @@
#include <utility>
+#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
@@ -205,15 +206,14 @@ bool SerializationUtils::WriteMetricToFile(const MetricSample& sample,
// The file containing the metrics samples will only be read by programs on
// the same device so we do not check endianness.
uint32_t encoded_size = base::checked_cast<uint32_t>(size);
- if (!base::WriteFileDescriptor(file_descriptor.get(),
- reinterpret_cast<char*>(&encoded_size),
- sizeof(uint32_t))) {
+ if (!base::WriteFileDescriptor(
+ file_descriptor.get(),
+ base::as_bytes(base::make_span(&encoded_size, 1)))) {
DPLOG(ERROR) << "error writing message length: " << filename;
return false;
}
- if (!base::WriteFileDescriptor(
- file_descriptor.get(), msg.c_str(), msg.size())) {
+ if (!base::WriteFileDescriptor(file_descriptor.get(), msg)) {
DPLOG(ERROR) << "error writing message: " << filename;
return false;
}
diff --git a/chromium/components/metrics/single_sample_metrics_factory_impl.h b/chromium/components/metrics/single_sample_metrics_factory_impl.h
index 97e343bbee0..7200f063666 100644
--- a/chromium/components/metrics/single_sample_metrics_factory_impl.h
+++ b/chromium/components/metrics/single_sample_metrics_factory_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_METRICS_SINGLE_VALUE_HISTOGRAM_FACTORY_IMPL_H_
-#define COMPONENTS_METRICS_SINGLE_VALUE_HISTOGRAM_FACTORY_IMPL_H_
+#ifndef COMPONENTS_METRICS_SINGLE_SAMPLE_METRICS_FACTORY_IMPL_H_
+#define COMPONENTS_METRICS_SINGLE_SAMPLE_METRICS_FACTORY_IMPL_H_
#include <string>
@@ -70,4 +70,4 @@ class SingleSampleMetricsFactoryImpl : public base::SingleSampleMetricsFactory {
} // namespace metrics
-#endif // COMPONENTS_METRICS_SINGLE_VALUE_HISTOGRAM_FACTORY_IMPL_H_
+#endif // COMPONENTS_METRICS_SINGLE_SAMPLE_METRICS_FACTORY_IMPL_H_
diff --git a/chromium/components/metrics/structured/DIR_METADATA b/chromium/components/metrics/structured/DIR_METADATA
deleted file mode 100644
index 540f41c94fe..00000000000
--- a/chromium/components/metrics/structured/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Internals>Metrics"
-}
diff --git a/chromium/components/metrics/structured/event_base.cc b/chromium/components/metrics/structured/event_base.cc
index e4e556255ec..0084541bb89 100644
--- a/chromium/components/metrics/structured/event_base.cc
+++ b/chromium/components/metrics/structured/event_base.cc
@@ -9,9 +9,12 @@
namespace metrics {
namespace structured {
-EventBase::EventBase(uint64_t event_name_hash, uint64_t project_name_hash)
+EventBase::EventBase(uint64_t event_name_hash,
+ uint64_t project_name_hash,
+ IdType id_type)
: event_name_hash_(event_name_hash),
- project_name_hash_(project_name_hash) {}
+ project_name_hash_(project_name_hash),
+ id_type_(id_type) {}
EventBase::EventBase(const EventBase& other) = default;
EventBase::~EventBase() = default;
@@ -25,7 +28,7 @@ void EventBase::AddStringMetric(uint64_t name_hash, const std::string& value) {
metrics_.push_back(metric);
}
-void EventBase::AddIntMetric(uint64_t name_hash, int value) {
+void EventBase::AddIntMetric(uint64_t name_hash, int64_t value) {
Metric metric(name_hash, MetricType::kInt);
metric.int_value = value;
metrics_.push_back(metric);
diff --git a/chromium/components/metrics/structured/event_base.h b/chromium/components/metrics/structured/event_base.h
index 90b840cc719..2d5ac75ff7a 100644
--- a/chromium/components/metrics/structured/event_base.h
+++ b/chromium/components/metrics/structured/event_base.h
@@ -20,7 +20,7 @@ class EventBase {
virtual ~EventBase();
// Specifies the type of identifier attached to an event.
- enum class IdentifierType {
+ enum class IdType {
// Events are attached to a per-event (or per-project) id.
kProjectId = 0,
// Events are attached to the UMA client_id.
@@ -53,7 +53,7 @@ class EventBase {
// only the HMAC digest will be reported, so it is safe to put any value
// here.
std::string string_value;
- int int_value;
+ int64_t int_value;
};
// Finalizes the event and sends it for recording. After this call, the event
@@ -66,12 +66,16 @@ class EventBase {
uint64_t project_name_hash() const { return project_name_hash_; }
+ IdType id_type() const { return id_type_; }
+
protected:
- explicit EventBase(uint64_t event_name_hash, uint64_t project_name_hash);
+ explicit EventBase(uint64_t event_name_hash,
+ uint64_t project_name_hash,
+ IdType id_type);
void AddStringMetric(uint64_t name_hash, const std::string& value);
- void AddIntMetric(uint64_t name_hash, int value);
+ void AddIntMetric(uint64_t name_hash, int64_t value);
private:
// First 8 bytes of the MD5 hash of the event name, as defined in
@@ -91,6 +95,8 @@ class EventBase {
// name.
uint64_t project_name_hash_;
+ IdType id_type_;
+
std::vector<Metric> metrics_;
};
diff --git a/chromium/components/metrics/structured/external_metrics.h b/chromium/components/metrics/structured/external_metrics.h
index 095d6b28bb5..2360fb327a2 100644
--- a/chromium/components/metrics/structured/external_metrics.h
+++ b/chromium/components/metrics/structured/external_metrics.h
@@ -5,16 +5,11 @@
#ifndef COMPONENTS_METRICS_STRUCTURED_EXTERNAL_METRICS_H_
#define COMPONENTS_METRICS_STRUCTURED_EXTERNAL_METRICS_H_
-#include <memory>
-#include <string>
-#include <vector>
-
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
-#include "base/values.h"
namespace metrics {
namespace structured {
diff --git a/chromium/components/metrics/structured/external_metrics_unittest.cc b/chromium/components/metrics/structured/external_metrics_unittest.cc
index b60f9cbaeea..665f2226608 100644
--- a/chromium/components/metrics/structured/external_metrics_unittest.cc
+++ b/chromium/components/metrics/structured/external_metrics_unittest.cc
@@ -88,7 +88,7 @@ class ExternalMetricsTest : public testing::Test {
base::ScopedTempDir temp_dir_;
std::unique_ptr<ExternalMetrics> external_metrics_;
- base::Optional<EventsProto> proto_;
+ absl::optional<EventsProto> proto_;
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::MainThreadType::UI,
diff --git a/chromium/components/metrics/structured/histogram_util.h b/chromium/components/metrics/structured/histogram_util.h
index 1e1799a5f47..16f7694ffc4 100644
--- a/chromium/components/metrics/structured/histogram_util.h
+++ b/chromium/components/metrics/structured/histogram_util.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_METRICS_STRUCTURED_HISTOGRAM_UTIL_H_
#define COMPONENTS_METRICS_STRUCTURED_HISTOGRAM_UTIL_H_
-#include <string>
-#include <vector>
-
#include "components/prefs/persistent_pref_store.h"
namespace metrics {
diff --git a/chromium/components/metrics/structured/key_data.cc b/chromium/components/metrics/structured/key_data.cc
index 83168f7b04a..b6ccbd01153 100644
--- a/chromium/components/metrics/structured/key_data.cc
+++ b/chromium/components/metrics/structured/key_data.cc
@@ -92,11 +92,11 @@ void KeyData::WriteNowForTest() {
// Key management
//---------------
-base::Optional<std::string> KeyData::ValidateAndGetKey(
+absl::optional<std::string> KeyData::ValidateAndGetKey(
const uint64_t project_name_hash) {
if (!is_initialized_) {
NOTREACHED();
- return base::nullopt;
+ return absl::nullopt;
}
const int now = (base::Time::Now() - base::Time::UnixEpoch()).InDays();
@@ -126,7 +126,7 @@ base::Optional<std::string> KeyData::ValidateAndGetKey(
const std::string key_string = key.key();
if (key_string.size() != kKeySize) {
LogInternalError(StructuredMetricsError::kWrongKeyLength);
- return base::nullopt;
+ return absl::nullopt;
}
return key_string;
}
@@ -148,7 +148,7 @@ uint64_t KeyData::Id(const uint64_t project_name_hash) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Retrieve the key for |project_name_hash|.
- const base::Optional<std::string> key = ValidateAndGetKey(project_name_hash);
+ const absl::optional<std::string> key = ValidateAndGetKey(project_name_hash);
if (!key) {
NOTREACHED();
return 0u;
@@ -166,7 +166,7 @@ uint64_t KeyData::HmacMetric(const uint64_t project_name_hash,
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Retrieve the key for |project_name_hash|.
- const base::Optional<std::string> key = ValidateAndGetKey(project_name_hash);
+ const absl::optional<std::string> key = ValidateAndGetKey(project_name_hash);
if (!key) {
NOTREACHED();
return 0u;
diff --git a/chromium/components/metrics/structured/key_data.h b/chromium/components/metrics/structured/key_data.h
index f04fe791d17..b124649dfa6 100644
--- a/chromium/components/metrics/structured/key_data.h
+++ b/chromium/components/metrics/structured/key_data.h
@@ -11,11 +11,11 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "components/metrics/structured/persistent_proto.h"
#include "components/metrics/structured/storage.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace metrics {
namespace structured {
@@ -101,8 +101,8 @@ class KeyData {
void OnWrite(WriteStatus status);
// Ensure that a valid key exists for |project|, and return it. Either returns
- // a string of size |kKeySize| or base::nullopt, which indicates an error.
- base::Optional<std::string> ValidateAndGetKey(uint64_t project_name_hash);
+ // a string of size |kKeySize| or absl::nullopt, which indicates an error.
+ absl::optional<std::string> ValidateAndGetKey(uint64_t project_name_hash);
// Regenerate |key|, also updating the |last_rotation| and |rotation_period|.
// This triggers a save.
diff --git a/chromium/components/metrics/structured/persistent_proto.h b/chromium/components/metrics/structured/persistent_proto.h
index 537f2368d2b..8f73a4448ed 100644
--- a/chromium/components/metrics/structured/persistent_proto.h
+++ b/chromium/components/metrics/structured/persistent_proto.h
@@ -5,15 +5,13 @@
#ifndef COMPONENTS_METRICS_STRUCTURED_PERSISTENT_PROTO_H_
#define COMPONENTS_METRICS_STRUCTURED_PERSISTENT_PROTO_H_
-#include <string>
-
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace metrics {
namespace structured {
diff --git a/chromium/components/metrics/structured/recorder.h b/chromium/components/metrics/structured/recorder.h
index 907288b59f8..4611da6b8b2 100644
--- a/chromium/components/metrics/structured/recorder.h
+++ b/chromium/components/metrics/structured/recorder.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_METRICS_STRUCTURED_RECORDER_H_
#define COMPONENTS_METRICS_STRUCTURED_RECORDER_H_
-#include <memory>
-
#include "base/callback_list.h"
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
diff --git a/chromium/components/metrics/structured/structured_metrics_features.cc b/chromium/components/metrics/structured/structured_metrics_features.cc
index 8ec8e2a6ebb..0669b562824 100644
--- a/chromium/components/metrics/structured/structured_metrics_features.cc
+++ b/chromium/components/metrics/structured/structured_metrics_features.cc
@@ -4,12 +4,22 @@
#include "components/metrics/structured/structured_metrics_features.h"
+#include "base/metrics/field_trial_params.h"
+
namespace metrics {
namespace structured {
+const base::Feature kStructuredMetrics{"EnableStructuredMetrics",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
// TODO(b/181724341): Remove this experimental once the feature is rolled out.
const base::Feature kBluetoothSessionizedMetrics{
"BluetoothSessionizedMetrics", base::FEATURE_DISABLED_BY_DEFAULT};
+bool IsIndependentMetricsUploadEnabled() {
+ return base::GetFieldTrialParamByFeatureAsBool(
+ kStructuredMetrics, "enable_independent_metrics_upload", true);
+}
+
} // namespace structured
} // namespace metrics
diff --git a/chromium/components/metrics/structured/structured_metrics_features.h b/chromium/components/metrics/structured/structured_metrics_features.h
index 0dca6b8b149..b4c3e3328f3 100644
--- a/chromium/components/metrics/structured/structured_metrics_features.h
+++ b/chromium/components/metrics/structured/structured_metrics_features.h
@@ -10,8 +10,22 @@
namespace metrics {
namespace structured {
+// This can be used to disable structured metrics as a whole.
+extern const base::Feature kStructuredMetrics;
+
extern const base::Feature kBluetoothSessionizedMetrics;
+// TODO(crbug.com/1148168): This is a temporary switch to revert structured
+// metrics upload to its old behaviour. Old behaviour:
+// - all metrics are uploaded in the main UMA upload
+//
+// New behaviour:
+// - Projects with id type 'uma' are uploaded in the main UMA uploaded
+// - Projects with id type 'project-id' or 'none' are uploaded independently.
+//
+// Once we are comfortable with this change, this parameter can be removed.
+bool IsIndependentMetricsUploadEnabled();
+
} // namespace structured
} // namespace metrics
diff --git a/chromium/components/metrics/structured/structured_metrics_provider.cc b/chromium/components/metrics/structured/structured_metrics_provider.cc
index 20ac0344d8e..cabd551f859 100644
--- a/chromium/components/metrics/structured/structured_metrics_provider.cc
+++ b/chromium/components/metrics/structured/structured_metrics_provider.cc
@@ -12,6 +12,7 @@
#include "components/metrics/structured/external_metrics.h"
#include "components/metrics/structured/histogram_util.h"
#include "components/metrics/structured/storage.pb.h"
+#include "components/metrics/structured/structured_metrics_features.h"
#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
namespace metrics {
@@ -26,6 +27,13 @@ constexpr int kSaveDelayMs = 1000;
// The interval between chrome's collection of metrics logged from cros.
constexpr int kExternalMetricsIntervalMins = 10;
+// The minimum waiting time between successive deliveries of independent metrics
+// to the metrics service via ProvideIndependentMetrics. This is set carefully:
+// metrics logs are stored in a queue of limited size, and are uploaded roughly
+// every 30 minutes.
+constexpr base::TimeDelta kMinIndependentMetricsInterval =
+ base::TimeDelta::FromMinutes(45);
+
// Directory containing serialized event protos to read.
constexpr char kExternalMetricsDir[] = "/var/lib/metrics/structured/events";
@@ -165,9 +173,29 @@ void StructuredMetricsProvider::OnRecord(const EventBase& event) {
DCHECK(key_data_->is_initialized());
- // TODO(crbug.com/1148168): use the identifier type for an event to choose
- // which list of events to save to: uma or non-uma.
- auto* event_proto = events_.get()->get()->add_uma_events();
+ // TODO(crbug.com/1148168): We are transitioning to new upload behaviour for
+ // non-client_id-identified metrics. See structured_metrics_features.h for
+ // more information. If IsIndependentMetricsUploadEnabled below returns false,
+ // this reverts to the old behaviour. The call can be removed once we are
+ // confident with the change.
+
+ // The |events_| persistent proto contains two repeated fields, uma_events
+ // and non_uma_events. uma_events is added to the ChromeUserMetricsExtension
+ // on a call to ProvideCurrentSessionData, which is the standard UMA upload
+ // and contains the UMA client_id. non_uma_events is added to the proto on
+ // a call to ProvideIndependentMetrics, which is a separate upload that does
+ // _not_ contain the UMA client_id.
+ //
+ // We decide which field to add this event to based on the event's IdType.
+ // kUmaId events should go in the UMA upload, and all others in the non-UMA
+ // upload.
+ StructuredEventProto* event_proto;
+ if (event.id_type() == EventBase::IdType::kUmaId ||
+ !IsIndependentMetricsUploadEnabled()) {
+ event_proto = events_.get()->get()->add_uma_events();
+ } else {
+ event_proto = events_.get()->get()->add_non_uma_events();
+ }
event_proto->set_profile_event_id(key_data_->Id(event.project_name_hash()));
event_proto->set_event_name_hash(event.name_hash());
@@ -192,7 +220,8 @@ void StructuredMetricsProvider::OnRecord(const EventBase& event) {
void StructuredMetricsProvider::OnRecordingEnabled() {
DCHECK(base::CurrentUIThread::IsSet());
- recording_enabled_ = true;
+ // Enable recording only if structured metrics' feature flag is enabled.
+ recording_enabled_ = base::FeatureList::IsEnabled(kStructuredMetrics);
}
void StructuredMetricsProvider::OnRecordingDisabled() {
@@ -220,11 +249,10 @@ void StructuredMetricsProvider::OnRecordingDisabled() {
void StructuredMetricsProvider::ProvideCurrentSessionData(
ChromeUserMetricsExtension* uma_proto) {
DCHECK(base::CurrentUIThread::IsSet());
- if (!recording_enabled_ || init_state_ != InitState::kInitialized)
+ if (!recording_enabled_ || init_state_ != InitState::kInitialized) {
return;
+ }
- // TODO(crbug.com/1148168): Consider splitting this into two metrics, one for
- // UMA metrics and one for non-UMA metrics.
LogNumEventsInUpload(events_.get()->get()->uma_events_size());
auto* structured_data = uma_proto->mutable_structured_data();
@@ -235,10 +263,20 @@ void StructuredMetricsProvider::ProvideCurrentSessionData(
}
bool StructuredMetricsProvider::HasIndependentMetrics() {
- // TODO(crbug.com/1148168): We cannot enable independent metrics uploads yet,
- // because we will overwhelm the unsent log store shared across UMA, resulting
- // in logs being dropped for long sessions.
- return false;
+ if (!IsIndependentMetricsUploadEnabled()) {
+ return false;
+ }
+
+ if (!recording_enabled_ || init_state_ != InitState::kInitialized) {
+ return false;
+ }
+
+ if (base::Time::Now() - last_provided_independent_metrics_ <
+ kMinIndependentMetricsInterval) {
+ return false;
+ }
+
+ return events_.get()->get()->non_uma_events_size() != 0;
}
void StructuredMetricsProvider::ProvideIndependentMetrics(
@@ -251,16 +289,15 @@ void StructuredMetricsProvider::ProvideIndependentMetrics(
return;
}
- // TODO(crbug.com/1148168): Add unit tests for independent metrics once we are
- // able to record them.
+ last_provided_independent_metrics_ = base::Time::Now();
- // TODO(crbug.com/1148168): Add histograms for independent metrics upload
- // size.
+ LogNumEventsInUpload(events_.get()->get()->non_uma_events_size());
auto* structured_data = uma_proto->mutable_structured_data();
structured_data->mutable_events()->Swap(
events_.get()->get()->mutable_non_uma_events());
events_.get()->get()->clear_non_uma_events();
+ events_->StartWrite();
// Independent events should not be associated with the client_id, so clear
// it.
@@ -272,5 +309,14 @@ void StructuredMetricsProvider::WriteNowForTest() {
events_->StartWrite();
}
+void StructuredMetricsProvider::SetExternalMetricsDirForTest(
+ const base::FilePath& dir) {
+ external_metrics_ = std::make_unique<ExternalMetrics>(
+ dir, base::TimeDelta::FromMinutes(kExternalMetricsIntervalMins),
+ base::BindRepeating(
+ &StructuredMetricsProvider::OnExternalMetricsCollected,
+ weak_factory_.GetWeakPtr()));
+}
+
} // namespace structured
} // namespace metrics
diff --git a/chromium/components/metrics/structured/structured_metrics_provider.h b/chromium/components/metrics/structured/structured_metrics_provider.h
index 660886d2212..d7d6b879353 100644
--- a/chromium/components/metrics/structured/structured_metrics_provider.h
+++ b/chromium/components/metrics/structured/structured_metrics_provider.h
@@ -6,13 +6,11 @@
#define COMPONENTS_METRICS_STRUCTURED_STRUCTURED_METRICS_PROVIDER_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/values.h"
#include "components/metrics/metrics_provider.h"
#include "components/metrics/structured/event_base.h"
#include "components/metrics/structured/key_data.h"
@@ -103,6 +101,7 @@ class StructuredMetricsProvider : public metrics::MetricsProvider,
base::HistogramSnapshotManager*) override;
void WriteNowForTest();
+ void SetExternalMetricsDirForTest(const base::FilePath& dir);
// Beyond this number of logging events between successive calls to
// ProvideCurrentSessionData, we stop recording events.
@@ -129,7 +128,9 @@ class StructuredMetricsProvider : public metrics::MetricsProvider,
InitState init_state_ = InitState::kUninitialized;
// Tracks the recording state signalled to the metrics provider by
- // OnRecordingEnabled and OnRecordingDisabled.
+ // OnRecordingEnabled and OnRecordingDisabled. This is false until
+ // OnRecordingEnabled is called, which sets it true if structured metrics'
+ // feature flag is enabled.
bool recording_enabled_ = false;
// Set by OnRecordingDisabled if |events_| hasn't been initialized yet to
@@ -137,6 +138,9 @@ class StructuredMetricsProvider : public metrics::MetricsProvider,
// See OnRecordingDisabled for more information.
bool wipe_events_on_init_ = false;
+ // The last time we provided independent metrics.
+ base::Time last_provided_independent_metrics_;
+
// Periodically reports metrics from cros.
std::unique_ptr<ExternalMetrics> external_metrics_;
diff --git a/chromium/components/metrics/structured/structured_metrics_provider_unittest.cc b/chromium/components/metrics/structured/structured_metrics_provider_unittest.cc
index ef342f675ba..99f906a71b7 100644
--- a/chromium/components/metrics/structured/structured_metrics_provider_unittest.cc
+++ b/chromium/components/metrics/structured/structured_metrics_provider_unittest.cc
@@ -13,12 +13,15 @@
#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_mock_clock_override.h"
#include "base/test/task_environment.h"
#include "base/values.h"
#include "components/metrics/structured/event_base.h"
#include "components/metrics/structured/recorder.h"
#include "components/metrics/structured/storage.pb.h"
#include "components/metrics/structured/structured_events.h"
+#include "components/metrics/structured/structured_metrics_features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
@@ -42,6 +45,8 @@ namespace {
constexpr uint64_t kProjectOneHash = UINT64_C(16881314472396226433);
// The name hash of "TestProjectTwo".
constexpr uint64_t kProjectTwoHash = UINT64_C(5876808001962504629);
+// The name hash of "TestProjectTwo".
+constexpr uint64_t kProjectThreeHash = UINT64_C(10860358748803291132);
// The name hash of "chrome::TestProjectOne::TestEventOne".
constexpr uint64_t kEventOneHash = UINT64_C(13593049295042080097);
@@ -49,6 +54,8 @@ constexpr uint64_t kEventOneHash = UINT64_C(13593049295042080097);
constexpr uint64_t kEventTwoHash = UINT64_C(8995967733561999410);
// The name hash of "chrome::TestProjectTwo::TestEventThree".
constexpr uint64_t kEventThreeHash = UINT64_C(5848687377041124372);
+// The name hash of "chrome::TestProjectThree::TestEventFour".
+constexpr uint64_t kEventFourHash = UINT64_C(1718797808092246258);
// The name hash of "TestMetricOne".
constexpr uint64_t kMetricOneHash = UINT64_C(637929385654885975);
@@ -56,11 +63,15 @@ constexpr uint64_t kMetricOneHash = UINT64_C(637929385654885975);
constexpr uint64_t kMetricTwoHash = UINT64_C(14083999144141567134);
// The name hash of "TestMetricThree".
constexpr uint64_t kMetricThreeHash = UINT64_C(13469300759843809564);
+// The name hash of "TestMetricFour".
+constexpr uint64_t kMetricFourHash = UINT64_C(2917855408523247722);
// The hex-encoded first 8 bytes of SHA256("aaa...a")
constexpr char kProjectOneId[] = "3BA3F5F43B926026";
// The hex-encoded first 8 bytes of SHA256("bbb...b")
constexpr char kProjectTwoId[] = "BDB339768BC5E4FE";
+// The hex-encoded first 8 bytes of SHA256("ccc...c")
+constexpr char kProjectThreeId[] = "CD93782B7FB95559";
// Test values.
constexpr char kValueOne[] = "value one";
@@ -70,6 +81,19 @@ std::string HashToHex(const uint64_t hash) {
return base::HexEncode(&hash, sizeof(uint64_t));
}
+// Make a simple testing proto with one |uma_events| message for each id in
+// |ids|.
+EventsProto MakeExternalEventProto(const std::vector<uint64_t>& ids) {
+ EventsProto proto;
+
+ for (const auto id : ids) {
+ auto* event = proto.add_uma_events();
+ event->set_profile_event_id(id);
+ }
+
+ return proto;
+}
+
} // namespace
class StructuredMetricsProviderTest : public testing::Test {
@@ -78,6 +102,9 @@ class StructuredMetricsProviderTest : public testing::Test {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
Recorder::GetInstance()->SetUiTaskRunner(
task_environment_.GetMainThreadTaskRunner());
+ // Move the mock date forward from day 0, because KeyData assumes that day 0
+ // is a bug.
+ task_environment_.AdvanceClock(base::TimeDelta::FromDays(1000));
}
base::FilePath TempDirPath() { return temp_dir_.GetPath(); }
@@ -102,8 +129,14 @@ class StructuredMetricsProviderTest : public testing::Test {
key_two.set_last_rotation(today);
key_two.set_rotation_period(90);
+ KeyProto& key_three = (*proto.mutable_keys())[kProjectThreeHash];
+ key_three.set_key("cccccccccccccccccccccccccccccccc");
+ key_three.set_last_rotation(today);
+ key_three.set_rotation_period(90);
+
base::CreateDirectory(KeyFilePath().DirName());
ASSERT_TRUE(base::WriteFile(KeyFilePath(), proto.SerializeAsString()));
+ Wait();
}
// Simulates the three external events that the structure metrics system cares
@@ -125,6 +158,7 @@ class StructuredMetricsProviderTest : public testing::Test {
return provider_->init_state_ ==
StructuredMetricsProvider::InitState::kInitialized;
}
+
bool is_recording_enabled() { return provider_->recording_enabled_; }
void OnRecordingEnabled() { provider_->OnRecordingEnabled(); }
@@ -143,16 +177,27 @@ class StructuredMetricsProviderTest : public testing::Test {
StructuredDataProto GetSessionData() {
ChromeUserMetricsExtension uma_proto;
provider_->ProvideCurrentSessionData(&uma_proto);
+ Wait();
return uma_proto.structured_data();
}
StructuredDataProto GetIndependentMetrics() {
- CHECK(provider_->HasIndependentMetrics());
+ // Independent metrics are only reported at intervals. So advance time to
+ // ensure HasIndependentMetrics will return true if there are recorded
+ // metrics.
+ task_environment_.AdvanceClock(base::TimeDelta::FromHours(1));
+
ChromeUserMetricsExtension uma_proto;
- provider_->ProvideIndependentMetrics(
- base::BindOnce([](bool success) { CHECK(success); }), &uma_proto,
- nullptr);
- return uma_proto.structured_data();
+ if (provider_->HasIndependentMetrics()) {
+ provider_->ProvideIndependentMetrics(
+ base::BindOnce([](bool success) { CHECK(success); }), &uma_proto,
+ nullptr);
+ Wait();
+ return uma_proto.structured_data();
+ }
+
+ auto p = StructuredDataProto();
+ return p;
}
void ExpectNoErrors() {
@@ -160,14 +205,19 @@ class StructuredMetricsProviderTest : public testing::Test {
0);
}
+ void SetExternalMetricsDirForTest(const base::FilePath dir) {
+ provider_->SetExternalMetricsDirForTest(dir);
+ }
+
protected:
std::unique_ptr<StructuredMetricsProvider> provider_;
- base::HistogramTester histogram_tester_;
-
- private:
+ // Feature list should be constructed before task environment.
+ base::test::ScopedFeatureList scoped_feature_list_;
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::MainThreadType::UI,
- base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED};
+ base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED,
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ base::HistogramTester histogram_tester_;
base::ScopedTempDir temp_dir_;
};
@@ -185,10 +235,43 @@ TEST_F(StructuredMetricsProviderTest, EventsNotReportedWhenRecordingDisabled) {
Init();
OnRecordingDisabled();
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
+ events::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
EXPECT_EQ(GetSessionData().events_size(), 0);
ExpectNoErrors();
}
+// Ensure that disabling the structured metrics feature flag prevents all
+// structured metrics reporting.
+TEST_F(StructuredMetricsProviderTest, EventsNotReportedWhenFeatureDisabled) {
+ scoped_feature_list_.InitAndDisableFeature(kStructuredMetrics);
+
+ Init();
+ // OnRecordingEnabled should not actually enable recording because the flag is
+ // disabled.
+ OnRecordingEnabled();
+ events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
+ events::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
+ EXPECT_EQ(GetSessionData().events_size(), 0);
+ ExpectNoErrors();
+}
+
+// Ensure that disabling independent upload of non-client_id metrics via feature
+// flag instead uploads them in the main UMA upload.
+TEST_F(StructuredMetricsProviderTest, DisableIndependentUploads) {
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ kStructuredMetrics, {{"enable_independent_metrics_upload", "false"}});
+
+ Init();
+ OnRecordingEnabled();
+ events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
+ events::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
+ EXPECT_EQ(GetSessionData().events_size(), 2);
+ ExpectNoErrors();
+}
+
// Ensure that, if recording is disabled part-way through initialization, the
// initialization still completes correctly, but recording is correctly set to
// disabled.
@@ -239,11 +322,46 @@ TEST_F(StructuredMetricsProviderTest, RecordedEventAppearsInReport) {
.SetTestMetricTwo(12345)
.Record();
- EXPECT_EQ(GetSessionData().events_size(), 3);
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 3);
+ // TestProjectOne is not UMA ID'd, so GetSessionData should be empty.
+ EXPECT_EQ(GetSessionData().events_size(), 0);
ExpectNoErrors();
}
-TEST_F(StructuredMetricsProviderTest, EventsReportedCorrectly) {
+TEST_F(StructuredMetricsProviderTest, UmaEventsReportedCorrectly) {
+ WriteTestingKeys();
+ Init();
+
+ events::test_project_three::TestEventFour().SetTestMetricFour(12345).Record();
+ events::test_project_three::TestEventFour().SetTestMetricFour(67890).Record();
+
+ const auto data = GetSessionData();
+ ASSERT_EQ(data.events_size(), 2);
+
+ { // First event
+ const auto& event = data.events(0);
+ EXPECT_EQ(event.event_name_hash(), kEventFourHash);
+ EXPECT_EQ(HashToHex(event.profile_event_id()), kProjectThreeId);
+ ASSERT_EQ(event.metrics_size(), 1);
+ const auto& metric = event.metrics(0);
+ EXPECT_EQ(metric.name_hash(), kMetricFourHash);
+ EXPECT_EQ(metric.value_int64(), 12345);
+ }
+
+ { // Second event
+ const auto& event = data.events(1);
+ EXPECT_EQ(event.event_name_hash(), kEventFourHash);
+ EXPECT_EQ(HashToHex(event.profile_event_id()), kProjectThreeId);
+ ASSERT_EQ(event.metrics_size(), 1);
+ const auto& metric = event.metrics(0);
+ EXPECT_EQ(metric.name_hash(), kMetricFourHash);
+ EXPECT_EQ(metric.value_int64(), 67890);
+ }
+
+ histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.InternalError", 0);
+}
+
+TEST_F(StructuredMetricsProviderTest, IndependentEventsReportedCorrectly) {
WriteTestingKeys();
Init();
@@ -255,7 +373,7 @@ TEST_F(StructuredMetricsProviderTest, EventsReportedCorrectly) {
.SetTestMetricThree(kValueTwo)
.Record();
- const auto data = GetSessionData();
+ const auto data = GetIndependentMetrics();
ASSERT_EQ(data.events_size(), 2);
{ // First event
@@ -297,7 +415,20 @@ TEST_F(StructuredMetricsProviderTest, EventsReportedCorrectly) {
}
histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.InternalError", 0);
- histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.PrefReadError", 0);
+}
+
+// Check that a full int64 can be recorded, and is not truncated to an int32.
+TEST_F(StructuredMetricsProviderTest, Int64MetricsNotTruncated) {
+ Init();
+ const int64_t big = 1ll << 60;
+ events::test_project_one::TestEventOne().SetTestMetricTwo(big).Record();
+
+ const auto data = GetIndependentMetrics();
+ ASSERT_EQ(data.events_size(), 1);
+ const auto& event = data.events(0);
+ ASSERT_EQ(event.metrics_size(), 1);
+ const auto& metric = event.metrics(0);
+ EXPECT_EQ(metric.value_int64(), big);
}
TEST_F(StructuredMetricsProviderTest, EventsWithinProjectReportedWithSameID) {
@@ -308,7 +439,9 @@ TEST_F(StructuredMetricsProviderTest, EventsWithinProjectReportedWithSameID) {
events::test_project_two::TestEventTwo().Record();
events::test_project_two::TestEventThree().Record();
- const auto data = GetSessionData();
+ const auto data = GetIndependentMetrics();
+ // TestProjectOne is not UMA ID'd, so GetSessionData should be empty.
+ EXPECT_EQ(GetSessionData().events_size(), 0);
ASSERT_EQ(data.events_size(), 3);
const auto& event_one = data.events(0);
@@ -327,7 +460,6 @@ TEST_F(StructuredMetricsProviderTest, EventsWithinProjectReportedWithSameID) {
EXPECT_EQ(HashToHex(event_three.profile_event_id()), kProjectTwoId);
histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.InternalError", 0);
- histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.PrefReadError", 0);
}
// Test that a call to ProvideCurrentSessionData clears the provided events from
@@ -337,15 +469,17 @@ TEST_F(StructuredMetricsProviderTest, EventsClearedAfterReport) {
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
events::test_project_one::TestEventOne().SetTestMetricTwo(2).Record();
+ // TestProjectOne is not UMA ID'd, so GetSessionData should be empty.
+ EXPECT_EQ(GetSessionData().events_size(), 0);
// Should provide both the previous events.
- EXPECT_EQ(GetSessionData().events_size(), 2);
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 2);
// But the previous events shouldn't appear in the second report.
- EXPECT_EQ(GetSessionData().events_size(), 0);
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
events::test_project_one::TestEventOne().SetTestMetricTwo(3).Record();
// The third request should only contain the third event.
- EXPECT_EQ(GetSessionData().events_size(), 1);
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 1);
ExpectNoErrors();
}
@@ -363,14 +497,32 @@ TEST_F(StructuredMetricsProviderTest, EventsFromPreviousSessionAreReported) {
// Start a second session and ensure the event is reported.
Init();
- const auto data = GetSessionData();
+ const auto data = GetIndependentMetrics();
ASSERT_EQ(data.events_size(), 1);
ASSERT_EQ(data.events(0).metrics_size(), 1);
EXPECT_EQ(data.events(0).metrics(0).value_int64(), 1234);
+ EXPECT_EQ(GetSessionData().events_size(), 0);
ExpectNoErrors();
}
+TEST_F(StructuredMetricsProviderTest, ExternalMetricsAreReported) {
+ const base::FilePath events_dir(TempDirPath().Append("events"));
+ base::CreateDirectory(events_dir);
+
+ const auto proto = MakeExternalEventProto({111, 222, 333});
+ ASSERT_TRUE(
+ base::WriteFile(events_dir.Append("event"), proto.SerializeAsString()));
+
+ provider_ = std::make_unique<StructuredMetricsProvider>();
+ OnProfileAdded(TempDirPath());
+ OnRecordingEnabled();
+ SetExternalMetricsDirForTest(events_dir);
+ task_environment_.AdvanceClock(base::TimeDelta::FromHours(10));
+ Wait();
+ EXPECT_EQ(GetSessionData().events_size(), 3);
+}
+
// Test that events reported at various stages before and during initialization
// are ignored (and don't cause a crash).
TEST_F(StructuredMetricsProviderTest, EventsNotRecordedBeforeInitialization) {
@@ -387,6 +539,7 @@ TEST_F(StructuredMetricsProviderTest, EventsNotRecordedBeforeInitialization) {
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
Wait();
EXPECT_EQ(GetSessionData().events_size(), 0);
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
ExpectNoErrors();
}
@@ -399,9 +552,12 @@ TEST_F(StructuredMetricsProviderTest,
Init();
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
+ events::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
OnRecordingDisabled();
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
+ events::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
EXPECT_EQ(GetSessionData().events_size(), 0);
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
ExpectNoErrors();
}
@@ -412,13 +568,19 @@ TEST_F(StructuredMetricsProviderTest, ReportingResumesWhenEnabled) {
Init();
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
+ events::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
+
OnRecordingDisabled();
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
+ events::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
OnRecordingEnabled();
+ events::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
events::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
- EXPECT_EQ(GetSessionData().events_size(), 2);
+
+ EXPECT_EQ(GetSessionData().events_size(), 1);
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 2);
ExpectNoErrors();
}
@@ -429,13 +591,14 @@ TEST_F(StructuredMetricsProviderTest,
ReportsNothingBeforeInitializationComplete) {
provider_ = std::make_unique<StructuredMetricsProvider>();
EXPECT_EQ(GetSessionData().events_size(), 0);
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
OnRecordingEnabled();
EXPECT_EQ(GetSessionData().events_size(), 0);
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
OnProfileAdded(TempDirPath());
EXPECT_EQ(GetSessionData().events_size(), 0);
+ EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
}
-// TODO(crbug.com/1148168): Add a unit test for external metrics.
-
} // namespace structured
} // namespace metrics
diff --git a/chromium/components/metrics/system_session_analyzer/DIR_METADATA b/chromium/components/metrics/system_session_analyzer/DIR_METADATA
deleted file mode 100644
index 540f41c94fe..00000000000
--- a/chromium/components/metrics/system_session_analyzer/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Internals>Metrics"
-}
diff --git a/chromium/components/metrics/ui/screen_info_metrics_provider.cc b/chromium/components/metrics/ui/screen_info_metrics_provider.cc
index 87a444f8375..7dcbcd608a1 100644
--- a/chromium/components/metrics/ui/screen_info_metrics_provider.cc
+++ b/chromium/components/metrics/ui/screen_info_metrics_provider.cc
@@ -70,7 +70,7 @@ 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();
+ const absl::optional<gfx::Size> display_size = GetScreenSize();
if (!display_size.has_value())
return;
@@ -87,11 +87,11 @@ void ScreenInfoMetricsProvider::ProvideSystemProfileMetrics(
#endif
}
-base::Optional<gfx::Size> ScreenInfoMetricsProvider::GetScreenSize() const {
+absl::optional<gfx::Size> ScreenInfoMetricsProvider::GetScreenSize() const {
auto* screen = display::Screen::GetScreen();
if (!screen)
- return base::nullopt;
- return base::make_optional(screen->GetPrimaryDisplay().GetSizeInPixel());
+ return absl::nullopt;
+ return absl::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 f92caac0b5c..edf9fae4f43 100644
--- a/chromium/components/metrics/ui/screen_info_metrics_provider.h
+++ b/chromium/components/metrics/ui/screen_info_metrics_provider.h
@@ -6,8 +6,8 @@
#define COMPONENTS_METRICS_UI_SCREEN_INFO_METRICS_PROVIDER_H_
#include "base/macros.h"
-#include "base/optional.h"
#include "components/metrics/metrics_provider.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
namespace metrics {
@@ -26,7 +26,7 @@ class ScreenInfoMetricsProvider : public MetricsProvider {
// Exposed for the sake of mocking in test code.
// Returns the screen size for the primary monitor if available.
- virtual base::Optional<gfx::Size> GetScreenSize() const;
+ virtual absl::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 0c74ac4e003..16125ad1d51 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:
- base::Optional<gfx::Size> GetScreenSize() const override {
- return base::make_optional(gfx::Size(kScreenWidth, kScreenHeight));
+ absl::optional<gfx::Size> GetScreenSize() const override {
+ return absl::make_optional(gfx::Size(kScreenWidth, kScreenHeight));
}
float GetScreenDeviceScaleFactor() const override {
diff --git a/chromium/components/metrics/unsent_log_store.cc b/chromium/components/metrics/unsent_log_store.cc
index a48f25b4766..e1515c8ca71 100644
--- a/chromium/components/metrics/unsent_log_store.cc
+++ b/chromium/components/metrics/unsent_log_store.cc
@@ -58,7 +58,7 @@ void UnsentLogStore::LogInfo::Init(
const std::string& log_data,
const std::string& log_timestamp,
const std::string& signing_key,
- base::Optional<base::HistogramBase::Count> samples_count) {
+ absl::optional<base::HistogramBase::Count> samples_count) {
DCHECK(!log_data.empty());
if (!compression::GzipCompress(log_data, &compressed_log_data)) {
@@ -172,9 +172,6 @@ void UnsentLogStore::MarkStagedLogAsSent() {
void UnsentLogStore::TrimAndPersistUnsentLogs() {
ListPrefUpdate update(local_state_, log_data_pref_name_);
- // TODO(crbug.com/859477): Verify that the preference has been properly
- // registered.
- CHECK(update.Get());
TrimLogs();
WriteLogsToPrefList(update.Get());
}
@@ -186,7 +183,7 @@ void UnsentLogStore::LoadPersistedUnsentLogs() {
void UnsentLogStore::StoreLog(
const std::string& log_data,
- base::Optional<base::HistogramBase::Count> samples_count) {
+ absl::optional<base::HistogramBase::Count> samples_count) {
LogInfo info;
info.Init(metrics_.get(), log_data,
base::NumberToString(base::Time::Now().ToTimeT()), signing_key_,
@@ -203,7 +200,7 @@ const std::string& UnsentLogStore::GetLogAtIndex(size_t index) {
std::string UnsentLogStore::ReplaceLogAtIndex(
size_t index,
const std::string& new_log_data,
- base::Optional<base::HistogramBase::Count> samples_count) {
+ absl::optional<base::HistogramBase::Count> samples_count) {
DCHECK_GE(index, 0U);
DCHECK_LT(index, list_.size());
diff --git a/chromium/components/metrics/unsent_log_store.h b/chromium/components/metrics/unsent_log_store.h
index 388e9c993ed..af78618234f 100644
--- a/chromium/components/metrics/unsent_log_store.h
+++ b/chromium/components/metrics/unsent_log_store.h
@@ -15,9 +15,9 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_base.h"
-#include "base/optional.h"
#include "base/values.h"
#include "components/metrics/log_store.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
@@ -71,7 +71,7 @@ class UnsentLogStore : public LogStore {
// Adds a UMA log to the list, |samples_count| is the total number of samples
// in the log (if available).
void StoreLog(const std::string& log_data,
- base::Optional<base::HistogramBase::Count> samples_count);
+ absl::optional<base::HistogramBase::Count> samples_count);
// Gets log data at the given index in the list.
const std::string& GetLogAtIndex(size_t index);
@@ -81,7 +81,7 @@ class UnsentLogStore : public LogStore {
std::string ReplaceLogAtIndex(
size_t index,
const std::string& new_log_data,
- base::Optional<base::HistogramBase::Count> samples_count);
+ absl::optional<base::HistogramBase::Count> samples_count);
// Deletes all logs, in memory and on disk.
void Purge();
@@ -165,7 +165,7 @@ class UnsentLogStore : public LogStore {
const std::string& log_data,
const std::string& log_timestamp,
const std::string& signing_key,
- base::Optional<base::HistogramBase::Count> samples_count);
+ absl::optional<base::HistogramBase::Count> samples_count);
// Compressed log data - a serialized protobuf that's been gzipped.
std::string compressed_log_data;
@@ -183,7 +183,7 @@ class UnsentLogStore : public LogStore {
std::string timestamp;
// The total number of samples in this log if applicable.
- base::Optional<base::HistogramBase::Count> samples_count;
+ absl::optional<base::HistogramBase::Count> samples_count;
};
// A list of all of the stored logs, stored with SHA1 hashes to check for
// corruption while they are stored in memory.
diff --git a/chromium/components/metrics/unsent_log_store_unittest.cc b/chromium/components/metrics/unsent_log_store_unittest.cc
index 5c3ffa42496..c769fc32c8f 100644
--- a/chromium/components/metrics/unsent_log_store_unittest.cc
+++ b/chromium/components/metrics/unsent_log_store_unittest.cc
@@ -150,7 +150,7 @@ TEST_F(UnsentLogStoreTest, EmptyLogList) {
TEST_F(UnsentLogStoreTest, SingleElementLogList) {
TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- unsent_log_store.StoreLog("Hello world!", base::nullopt);
+ unsent_log_store.StoreLog("Hello world!", absl::nullopt);
unsent_log_store.TrimAndPersistUnsentLogs();
TestUnsentLogStore result_unsent_log_store(&prefs_, kLogByteLimit);
@@ -177,7 +177,7 @@ TEST_F(UnsentLogStoreTest, LongButTinyLogList) {
size_t log_count = kLogCountLimit * 5;
for (size_t i = 0; i < log_count; ++i)
- unsent_log_store.StoreLog("x", base::nullopt);
+ unsent_log_store.StoreLog("x", absl::nullopt);
EXPECT_EQ(log_count, unsent_log_store.size());
unsent_log_store.TrimAndPersistUnsentLogs();
@@ -210,13 +210,13 @@ TEST_F(UnsentLogStoreTest, LongButSmallLogList) {
(log_count - 4) * Compress(blank_log).length();
TestUnsentLogStore unsent_log_store(&prefs_, min_log_bytes);
- unsent_log_store.StoreLog("one", base::nullopt);
- unsent_log_store.StoreLog("two", base::nullopt);
- unsent_log_store.StoreLog(first_kept, base::nullopt);
+ unsent_log_store.StoreLog("one", absl::nullopt);
+ unsent_log_store.StoreLog("two", absl::nullopt);
+ unsent_log_store.StoreLog(first_kept, absl::nullopt);
for (size_t i = unsent_log_store.size(); i < log_count - 1; ++i) {
- unsent_log_store.StoreLog(blank_log, base::nullopt);
+ unsent_log_store.StoreLog(blank_log, absl::nullopt);
}
- unsent_log_store.StoreLog(last_kept, base::nullopt);
+ unsent_log_store.StoreLog(last_kept, absl::nullopt);
size_t original_size = unsent_log_store.size();
unsent_log_store.TrimAndPersistUnsentLogs();
@@ -245,7 +245,7 @@ TEST_F(UnsentLogStoreTest, ShortButLargeLogList) {
TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
for (size_t i = 0; i < log_count; ++i) {
- unsent_log_store.StoreLog(log_data, base::nullopt);
+ unsent_log_store.StoreLog(log_data, absl::nullopt);
}
unsent_log_store.TrimAndPersistUnsentLogs();
@@ -272,9 +272,9 @@ TEST_F(UnsentLogStoreTest, LongAndLargeLogList) {
std::string log_data = GenerateLogWithMinCompressedSize(log_size);
for (size_t i = 0; i < log_count; ++i) {
if (i == log_count - kLogCountLimit)
- unsent_log_store.StoreLog(target_log, base::nullopt);
+ unsent_log_store.StoreLog(target_log, absl::nullopt);
else
- unsent_log_store.StoreLog(log_data, base::nullopt);
+ unsent_log_store.StoreLog(log_data, absl::nullopt);
}
unsent_log_store.TrimAndPersistUnsentLogs();
@@ -297,13 +297,13 @@ TEST_F(UnsentLogStoreTest, Staging) {
std::string tmp;
EXPECT_FALSE(unsent_log_store.has_staged_log());
- unsent_log_store.StoreLog("one", base::nullopt);
+ unsent_log_store.StoreLog("one", absl::nullopt);
EXPECT_FALSE(unsent_log_store.has_staged_log());
- unsent_log_store.StoreLog("two", base::nullopt);
+ unsent_log_store.StoreLog("two", absl::nullopt);
unsent_log_store.StageNextLog();
EXPECT_TRUE(unsent_log_store.has_staged_log());
EXPECT_EQ(unsent_log_store.staged_log(), Compress("two"));
- unsent_log_store.StoreLog("three", base::nullopt);
+ unsent_log_store.StoreLog("three", absl::nullopt);
EXPECT_EQ(unsent_log_store.staged_log(), Compress("two"));
EXPECT_EQ(unsent_log_store.size(), 3U);
unsent_log_store.DiscardStagedLog();
@@ -324,9 +324,9 @@ TEST_F(UnsentLogStoreTest, DiscardOrder) {
// a log is staged.
TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- unsent_log_store.StoreLog("one", base::nullopt);
+ unsent_log_store.StoreLog("one", absl::nullopt);
unsent_log_store.StageNextLog();
- unsent_log_store.StoreLog("two", base::nullopt);
+ unsent_log_store.StoreLog("two", absl::nullopt);
unsent_log_store.DiscardStagedLog();
unsent_log_store.TrimAndPersistUnsentLogs();
@@ -342,7 +342,7 @@ TEST_F(UnsentLogStoreTest, Hashes) {
const std::string foo_hash = base::SHA1HashString(kFooText);
TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- unsent_log_store.StoreLog(kFooText, base::nullopt);
+ unsent_log_store.StoreLog(kFooText, absl::nullopt);
unsent_log_store.StageNextLog();
EXPECT_EQ(Compress(kFooText), unsent_log_store.staged_log());
@@ -353,7 +353,7 @@ TEST_F(UnsentLogStoreTest, Signatures) {
const char kFooText[] = "foo";
TestUnsentLogStore unsent_log_store(&prefs_, kLogByteLimit);
- unsent_log_store.StoreLog(kFooText, base::nullopt);
+ unsent_log_store.StoreLog(kFooText, absl::nullopt);
unsent_log_store.StageNextLog();
EXPECT_EQ(Compress(kFooText), unsent_log_store.staged_log());
@@ -379,7 +379,7 @@ TEST_F(UnsentLogStoreTest, Signatures) {
TestUnsentLogStore unsent_log_store_different_key(&prefs_, kLogByteLimit,
key);
- unsent_log_store_different_key.StoreLog(kFooText, base::nullopt);
+ unsent_log_store_different_key.StoreLog(kFooText, absl::nullopt);
unsent_log_store_different_key.StageNextLog();
EXPECT_EQ(Compress(kFooText), unsent_log_store_different_key.staged_log());
@@ -420,14 +420,14 @@ TEST_F(UnsentLogStoreTest, UnsentLogMetadataMetrics) {
unsent_log_store.StoreLog(
oversize_log,
- base::make_optional<base::HistogramBase::Count>(kOversizeLogSampleCount));
- unsent_log_store.StoreLog(kNoSampleLog, base::nullopt);
+ absl::make_optional<base::HistogramBase::Count>(kOversizeLogSampleCount));
+ unsent_log_store.StoreLog(kNoSampleLog, absl::nullopt);
unsent_log_store.StoreLog(
- kFooText, base::Optional<base::HistogramBase::Count>(kFooSampleCount));
+ kFooText, absl::optional<base::HistogramBase::Count>(kFooSampleCount));
// The foobar_log will be staged first.
unsent_log_store.StoreLog(
foobar_log,
- base::Optional<base::HistogramBase::Count>(kFooBarSampleCount));
+ absl::optional<base::HistogramBase::Count>(kFooBarSampleCount));
unsent_log_store.TrimAndPersistUnsentLogs();
diff --git a/chromium/components/metrics_services_manager/metrics_services_manager_client.h b/chromium/components/metrics_services_manager/metrics_services_manager_client.h
index 31e004c16f7..77302fd0266 100644
--- a/chromium/components/metrics_services_manager/metrics_services_manager_client.h
+++ b/chromium/components/metrics_services_manager/metrics_services_manager_client.h
@@ -7,7 +7,6 @@
#include <memory>
-#include "base/callback_forward.h"
#include "base/memory/scoped_refptr.h"
namespace metrics {
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 3584bdfdf3e..7ad8247a24b 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
@@ -22,6 +22,8 @@ namespace mirroring {
namespace {
+constexpr bool kNotPremapped = false;
+
class MockVideoCaptureDevice final
: public content::LaunchedVideoCaptureDevice {
public:
@@ -164,8 +166,8 @@ class MockVideoCaptureObserver final
media::mojom::VideoFrameInfoPtr GetVideoFrameInfo() {
return media::mojom::VideoFrameInfo::New(
base::TimeDelta(), media::VideoFrameMetadata(), media::PIXEL_FORMAT_I420,
- gfx::Size(320, 180), gfx::Rect(320, 180), gfx::ColorSpace::CreateREC709(),
- nullptr);
+ gfx::Size(320, 180), gfx::Rect(320, 180), kNotPremapped,
+ gfx::ColorSpace::CreateREC709(), nullptr);
}
} // namespace
diff --git a/chromium/components/mirroring/service/BUILD.gn b/chromium/components/mirroring/service/BUILD.gn
index fd23c82a21a..89a59aa9343 100644
--- a/chromium/components/mirroring/service/BUILD.gn
+++ b/chromium/components/mirroring/service/BUILD.gn
@@ -32,8 +32,6 @@ component("mirroring_service") {
"value_util.h",
"video_capture_client.cc",
"video_capture_client.h",
- "wifi_status_monitor.cc",
- "wifi_status_monitor.h",
]
public_deps = [ "//base" ]
@@ -90,7 +88,6 @@ source_set("unittests") {
"session_unittest.cc",
"udp_socket_client_unittest.cc",
"video_capture_client_unittest.cc",
- "wifi_status_monitor_unittest.cc",
]
deps = [
diff --git a/chromium/components/mirroring/service/captured_audio_input.cc b/chromium/components/mirroring/service/captured_audio_input.cc
index ce85343fd0a..2e543c6f751 100644
--- a/chromium/components/mirroring/service/captured_audio_input.cc
+++ b/chromium/components/mirroring/service/captured_audio_input.cc
@@ -6,6 +6,7 @@
#include "base/check_op.h"
#include "base/notreached.h"
+#include "media/mojo/common/input_error_code_converter.h"
#include "media/mojo/mojom/audio_data_pipe.mojom.h"
#include "mojo/public/cpp/system/platform_handle.h"
@@ -81,10 +82,11 @@ void CapturedAudioInput::StreamCreated(
/* initally_muted */ false);
}
-void CapturedAudioInput::OnError() {
+void CapturedAudioInput::OnError(media::mojom::InputStreamErrorCode code) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(delegate_);
- delegate_->OnError();
+
+ delegate_->OnError(media::ConvertToCaptureCallbackCode(code));
}
void CapturedAudioInput::OnMutedStateChanged(bool is_muted) {
diff --git a/chromium/components/mirroring/service/captured_audio_input.h b/chromium/components/mirroring/service/captured_audio_input.h
index 0d4d7fbea80..a67abf32b0a 100644
--- a/chromium/components/mirroring/service/captured_audio_input.h
+++ b/chromium/components/mirroring/service/captured_audio_input.h
@@ -51,7 +51,7 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) CapturedAudioInput final
media::mojom::ReadOnlyAudioDataPipePtr data_pipe) override;
// media::mojom::AudioInputStreamClient implementation.
- void OnError() override;
+ void OnError(media::mojom::InputStreamErrorCode code) override;
void OnMutedStateChanged(bool is_muted) override;
SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chromium/components/mirroring/service/captured_audio_input_unittest.cc b/chromium/components/mirroring/service/captured_audio_input_unittest.cc
index 7de1a5a55c2..102263dba75 100644
--- a/chromium/components/mirroring/service/captured_audio_input_unittest.cc
+++ b/chromium/components/mirroring/service/captured_audio_input_unittest.cc
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
+#include "media/base/audio_capturer_source.h"
#include "media/base/audio_parameters.h"
#include "media/mojo/mojom/audio_data_pipe.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -22,6 +23,8 @@ using ::testing::InvokeWithoutArgs;
namespace mirroring {
+using AudioSourceErrorCode = media::AudioCapturerSource::ErrorCode;
+
namespace {
class MockStream final : public media::mojom::AudioInputStream {
@@ -36,7 +39,7 @@ class MockDelegate final : public media::AudioInputIPCDelegate {
~MockDelegate() override {}
MOCK_METHOD0(StreamCreated, void());
- MOCK_METHOD0(OnError, void());
+ MOCK_METHOD1(OnError, void(AudioSourceErrorCode code));
MOCK_METHOD1(OnMuted, void(bool muted));
MOCK_METHOD0(OnIPCClosed, void());
@@ -102,9 +105,19 @@ class CapturedAudioInputTest : public ::testing::Test {
void SignalStreamError() {
EXPECT_TRUE(stream_client_.is_bound());
base::RunLoop run_loop;
- EXPECT_CALL(delegate_, OnError())
+ EXPECT_CALL(delegate_, OnError(AudioSourceErrorCode::kUnknown))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
- stream_client_->OnError();
+ stream_client_->OnError(media::mojom::InputStreamErrorCode::kUnknown);
+ run_loop.Run();
+ }
+
+ void SignalStreamPermissionsError() {
+ EXPECT_TRUE(stream_client_.is_bound());
+ base::RunLoop run_loop;
+ EXPECT_CALL(delegate_, OnError(AudioSourceErrorCode::kSystemPermissions))
+ .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+ stream_client_->OnError(
+ media::mojom::InputStreamErrorCode::kSystemPermissions);
run_loop.Run();
}
@@ -158,6 +171,12 @@ TEST_F(CapturedAudioInputTest, PropagatesStreamError) {
CloseStream();
}
+TEST_F(CapturedAudioInputTest, PropagatesStreamPermissionsError) {
+ CreateStream();
+ SignalStreamPermissionsError();
+ CloseStream();
+}
+
TEST_F(CapturedAudioInputTest, PropagatesMutedStateChange) {
CreateStream();
SignalMutedStateChanged(true);
diff --git a/chromium/components/mirroring/service/fake_network_service.cc b/chromium/components/mirroring/service/fake_network_service.cc
index 80ebddc271c..6fd588c4a37 100644
--- a/chromium/components/mirroring/service/fake_network_service.cc
+++ b/chromium/components/mirroring/service/fake_network_service.cc
@@ -40,7 +40,7 @@ void MockUdpSocket::Send(
void MockUdpSocket::OnReceivedPacket(const media::cast::Packet& packet) {
if (num_ask_for_receive_) {
listener_->OnReceived(
- net::OK, base::nullopt,
+ net::OK, absl::nullopt,
base::span<const uint8_t>(
reinterpret_cast<const uint8_t*>(packet.data()), packet.size()));
ASSERT_LT(0, num_ask_for_receive_);
diff --git a/chromium/components/mirroring/service/fake_video_capture_host.cc b/chromium/components/mirroring/service/fake_video_capture_host.cc
index 20d2f25062e..a2855bcb146 100644
--- a/chromium/components/mirroring/service/fake_video_capture_host.cc
+++ b/chromium/components/mirroring/service/fake_video_capture_host.cc
@@ -10,6 +10,13 @@
namespace mirroring {
+namespace {
+
+// Video buffer parameters.
+constexpr bool kNotPremapped = false;
+
+} // namespace
+
FakeVideoCaptureHost::FakeVideoCaptureHost(
mojo::PendingReceiver<media::mojom::VideoCaptureHost> receiver)
: receiver_(this, std::move(receiver)) {}
@@ -50,7 +57,8 @@ void FakeVideoCaptureHost::SendOneFrame(const gfx::Size& size,
media::mojom::ReadyBufferPtr buffer = media::mojom::ReadyBuffer::New(
0, media::mojom::VideoFrameInfo::New(
base::TimeDelta(), metadata, media::PIXEL_FORMAT_I420, size,
- gfx::Rect(size), gfx::ColorSpace::CreateREC709(), nullptr));
+ gfx::Rect(size), kNotPremapped, gfx::ColorSpace::CreateREC709(),
+ nullptr));
observer_->OnBufferReady(std::move(buffer), {});
}
diff --git a/chromium/components/mirroring/service/message_dispatcher.cc b/chromium/components/mirroring/service/message_dispatcher.cc
index 8503563e6dd..27cc61c9b1a 100644
--- a/chromium/components/mirroring/service/message_dispatcher.cc
+++ b/chromium/components/mirroring/service/message_dispatcher.cc
@@ -96,13 +96,13 @@ void MessageDispatcher::Send(mojom::CastMessagePtr message) {
DCHECK_EQ(mojom::kWebRtcNamespace, message->message_namespace);
#endif // DCHECK_IS_ON()
+ // NOTE: getting a message that we are not subscribed to is purposely
+ // not an error--subscribers are allowed to pick and choose message types
+ // to subscribe to.
const auto callback_iter = callback_map_.find(response->type());
- if (callback_iter == callback_map_.end()) {
- error_callback_.Run("No callback subscribed. message=" +
- message->json_format_data);
- return;
+ if (callback_iter != callback_map_.end()) {
+ callback_iter->second.Run(*response);
}
- callback_iter->second.Run(*response);
}
void MessageDispatcher::Subscribe(ResponseType type,
diff --git a/chromium/components/mirroring/service/message_dispatcher_unittest.cc b/chromium/components/mirroring/service/message_dispatcher_unittest.cc
index 1f01b8ba8e2..6312d4eb584 100644
--- a/chromium/components/mirroring/service/message_dispatcher_unittest.cc
+++ b/chromium/components/mirroring/service/message_dispatcher_unittest.cc
@@ -38,6 +38,16 @@ constexpr char kValidAnswerResponse[] = R"(
}
})";
+constexpr char kValidCapabilitiesResponse[] = R"({
+ "capabilities": {
+ "keySystems": [],
+ "mediaCaps": ["video", "h264", "vp8", "hevc", "vp9", "audio", "aac", "opus"]
+ },
+ "result": "ok",
+ "seqNum": 820263770,
+ "type": "CAPABILITIES_RESPONSE"
+})";
+
bool IsEqual(const CastMessage& message1, const CastMessage& message2) {
return message1.message_namespace == message2.message_namespace &&
message1.json_format_data == message2.json_format_data;
@@ -61,8 +71,8 @@ class MessageDispatcherTest : public mojom::CastMessageChannel,
base::BindRepeating(&MessageDispatcherTest::OnAnswerResponse,
base::Unretained(this)));
message_dispatcher_->Subscribe(
- ResponseType::STATUS_RESPONSE,
- base::BindRepeating(&MessageDispatcherTest::OnStatusResponse,
+ ResponseType::RPC,
+ base::BindRepeating(&MessageDispatcherTest::OnRpcMessage,
base::Unretained(this)));
}
~MessageDispatcherTest() override { task_environment_.RunUntilIdle(); }
@@ -75,8 +85,8 @@ class MessageDispatcherTest : public mojom::CastMessageChannel,
last_answer_response_ = response.CloneForTesting();
}
- void OnStatusResponse(const ReceiverResponse& response) {
- last_status_response_ = response.CloneForTesting();
+ void OnRpcMessage(const ReceiverResponse& response) {
+ last_rpc_ = response.CloneForTesting();
}
protected:
@@ -96,7 +106,7 @@ class MessageDispatcherTest : public mojom::CastMessageChannel,
CastMessage last_outbound_message_;
std::string last_error_message_;
std::unique_ptr<ReceiverResponse> last_answer_response_;
- std::unique_ptr<ReceiverResponse> last_status_response_;
+ std::unique_ptr<ReceiverResponse> last_rpc_;
private:
mojo::Receiver<mojom::CastMessageChannel> receiver_{this};
@@ -128,7 +138,7 @@ TEST_F(MessageDispatcherTest, DispatchMessageToSubscriber) {
SendInboundMessage(answer_message);
task_environment_.RunUntilIdle();
ASSERT_TRUE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
+ EXPECT_FALSE(last_rpc_);
EXPECT_EQ(12345, last_answer_response_->sequence_number());
EXPECT_EQ(ResponseType::ANSWER, last_answer_response_->type());
ASSERT_TRUE(last_answer_response_->valid());
@@ -136,22 +146,28 @@ TEST_F(MessageDispatcherTest, DispatchMessageToSubscriber) {
last_answer_response_.reset();
EXPECT_TRUE(last_error_message_.empty());
- // Simulate a receiver STATUS_RESPONSE and expect that just the
- // STATUS_RESPONSE subscriber processes the message.
- const std::string status_response =
- "{\"type\":\"STATUS_RESPONSE\",\"seqNum\":12345,\"result\":\"ok\","
- "\"status\":{\"wifiSnr\":42}}";
- const CastMessage status_message =
- CastMessage{mojom::kWebRtcNamespace, status_response};
- SendInboundMessage(status_message);
+ // Simulate a receiver RPC and expect that just the
+ // RPC subscriber processes the message.
+ const std::string message = "Hello from the Cast Receiver!";
+ std::string rpc_base64;
+ base::Base64Encode(message, &rpc_base64);
+ const std::string rpc =
+ R"({"sessionId": 735189,
+ "seqNum": 6789,
+ "type": "RPC",
+ "result": "ok",
+ "rpc": ")" +
+ rpc_base64 + R"("})";
+
+ const CastMessage rpc_message = CastMessage{mojom::kRemotingNamespace, rpc};
+ SendInboundMessage(rpc_message);
task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
- ASSERT_TRUE(last_status_response_);
- EXPECT_EQ(12345, last_status_response_->sequence_number());
- EXPECT_EQ(ResponseType::STATUS_RESPONSE, last_status_response_->type());
- ASSERT_TRUE(last_status_response_->valid());
- EXPECT_EQ(42, last_status_response_->status().wifi_snr);
- last_status_response_.reset();
+ ASSERT_TRUE(last_rpc_);
+ EXPECT_EQ(6789, last_rpc_->sequence_number());
+ EXPECT_EQ(ResponseType::RPC, last_rpc_->type());
+ ASSERT_TRUE(last_rpc_->valid());
+ last_rpc_.reset();
EXPECT_TRUE(last_error_message_.empty());
// Unsubscribe from ANSWER messages, and when feeding-in an ANSWER message,
@@ -159,34 +175,37 @@ TEST_F(MessageDispatcherTest, DispatchMessageToSubscriber) {
message_dispatcher_->Unsubscribe(ResponseType::ANSWER);
SendInboundMessage(answer_message);
task_environment_.RunUntilIdle();
+ // The answer should be ignored now that we are unsubscribed.
EXPECT_FALSE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
- EXPECT_FALSE(last_error_message_.empty()); // Expect an error reported.
+ EXPECT_FALSE(last_rpc_);
+ EXPECT_TRUE(last_error_message_.empty());
last_error_message_.clear();
- // However, STATUS_RESPONSE messages should still be dispatcher to the
+ // However, RPC messages should still be dispatched to the
// remaining subscriber.
- SendInboundMessage(status_message);
+ SendInboundMessage(rpc_message);
task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
- EXPECT_TRUE(last_status_response_);
- last_status_response_.reset();
+ EXPECT_TRUE(last_rpc_);
+ last_rpc_.reset();
EXPECT_TRUE(last_error_message_.empty());
- // Finally, unsubscribe from STATUS_RESPONSE messages, and when feeding-in
- // either an ANSWER or a STATUS_RESPONSE message, nothing should happen.
- message_dispatcher_->Unsubscribe(ResponseType::STATUS_RESPONSE);
+ // Finally, unsubscribe from RPC messages, and when feeding-in
+ // either an ANSWER or a RPC message, nothing should happen.
+ message_dispatcher_->Unsubscribe(ResponseType::RPC);
SendInboundMessage(answer_message);
+
task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
- EXPECT_FALSE(last_error_message_.empty());
+ EXPECT_FALSE(last_rpc_);
+ EXPECT_TRUE(last_error_message_.empty());
last_error_message_.clear();
- SendInboundMessage(status_message);
+ SendInboundMessage(rpc_message);
+
task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
- EXPECT_FALSE(last_error_message_.empty());
+ EXPECT_FALSE(last_rpc_);
+ EXPECT_TRUE(last_error_message_.empty());
}
TEST_F(MessageDispatcherTest, IgnoreMalformedMessage) {
@@ -195,7 +214,7 @@ TEST_F(MessageDispatcherTest, IgnoreMalformedMessage) {
SendInboundMessage(message);
task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
+ EXPECT_FALSE(last_rpc_);
EXPECT_FALSE(last_error_message_.empty());
}
@@ -205,19 +224,29 @@ TEST_F(MessageDispatcherTest, IgnoreMessageWithWrongNamespace) {
SendInboundMessage(answer_message);
task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
+ EXPECT_FALSE(last_rpc_);
// Messages with different namespace are ignored with no error reported.
EXPECT_TRUE(last_error_message_.empty());
}
+TEST_F(MessageDispatcherTest, IgnoreMessageWithNoSubscribers) {
+ const CastMessage unexpected_message{mojom::kWebRtcNamespace,
+ kValidCapabilitiesResponse};
+ SendInboundMessage(unexpected_message);
+ task_environment_.RunUntilIdle();
+ // Messages with no subscribers are ignored with no error reported.
+ EXPECT_FALSE(last_answer_response_);
+ EXPECT_FALSE(last_rpc_);
+ EXPECT_TRUE(last_error_message_.empty());
+}
TEST_F(MessageDispatcherTest, RequestReply) {
EXPECT_FALSE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
+ EXPECT_FALSE(last_rpc_);
message_dispatcher_->Unsubscribe(ResponseType::ANSWER);
task_environment_.RunUntilIdle();
- const std::string fake_offer = "{\"type\":\"OFFER\",\"seqNum\":45623}";
+ constexpr char kFakeOffer[] = "{\"type\":\"OFFER\",\"seqNum\":45623}";
const CastMessage offer_message =
- CastMessage{mojom::kWebRtcNamespace, fake_offer};
+ CastMessage{mojom::kWebRtcNamespace, kFakeOffer};
message_dispatcher_->RequestReply(
offer_message.Clone(), ResponseType::ANSWER, 45623,
base::TimeDelta::FromMilliseconds(100),
@@ -233,7 +262,7 @@ TEST_F(MessageDispatcherTest, RequestReply) {
task_environment_.RunUntilIdle();
// The answer message with mismatched sequence number is ignored.
EXPECT_FALSE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
+ EXPECT_FALSE(last_rpc_);
EXPECT_TRUE(last_error_message_.empty());
constexpr char kAnswerWithCorrectSeqNum[] = R"(
@@ -252,7 +281,7 @@ TEST_F(MessageDispatcherTest, RequestReply) {
SendInboundMessage(answer_message);
task_environment_.RunUntilIdle();
ASSERT_TRUE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
+ EXPECT_FALSE(last_rpc_);
EXPECT_TRUE(last_error_message_.empty());
EXPECT_EQ(45623, last_answer_response_->sequence_number());
EXPECT_EQ(ResponseType::ANSWER, last_answer_response_->type());
@@ -264,8 +293,8 @@ TEST_F(MessageDispatcherTest, RequestReply) {
SendInboundMessage(answer_message);
task_environment_.RunUntilIdle();
EXPECT_FALSE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
- EXPECT_FALSE(last_error_message_.empty());
+ EXPECT_FALSE(last_rpc_);
+ EXPECT_TRUE(last_error_message_.empty());
last_error_message_.clear();
const CastMessage fake_message = CastMessage{
@@ -279,13 +308,13 @@ TEST_F(MessageDispatcherTest, RequestReply) {
// Received the request to send the outbound message.
EXPECT_TRUE(IsEqual(fake_message, last_outbound_message_));
EXPECT_FALSE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
+ EXPECT_FALSE(last_rpc_);
// Destroy the dispatcher.
message_dispatcher_.reset();
task_environment_.RunUntilIdle();
ASSERT_FALSE(last_answer_response_);
- EXPECT_FALSE(last_status_response_);
+ EXPECT_FALSE(last_rpc_);
}
} // namespace mirroring
diff --git a/chromium/components/mirroring/service/mirror_settings.h b/chromium/components/mirroring/service/mirror_settings.h
index 4ac440ff6a1..a8ce601ae4b 100644
--- a/chromium/components/mirroring/service/mirror_settings.h
+++ b/chromium/components/mirroring/service/mirror_settings.h
@@ -6,8 +6,6 @@
#define COMPONENTS_MIRRORING_SERVICE_MIRROR_SETTINGS_H_
#include "base/component_export.h"
-#include "base/time/time.h"
-#include "base/values.h"
#include "media/capture/video_capture_types.h"
#include "media/cast/cast_config.h"
diff --git a/chromium/components/mirroring/service/receiver_response.cc b/chromium/components/mirroring/service/receiver_response.cc
index f3f992347e8..8f166523692 100644
--- a/chromium/components/mirroring/service/receiver_response.cc
+++ b/chromium/components/mirroring/service/receiver_response.cc
@@ -20,8 +20,6 @@ namespace {
ResponseType ResponseTypeFromString(const std::string& type) {
if (type == "ANSWER")
return ResponseType::ANSWER;
- if (type == "STATUS_RESPONSE")
- return ResponseType::STATUS_RESPONSE;
if (type == "CAPABILITIES_RESPONSE")
return ResponseType::CAPABILITIES_RESPONSE;
if (type == "RPC")
@@ -53,22 +51,6 @@ bool GetInt(const Json::Value& value, int* out) {
return true;
}
-bool GetDouble(const Json::Value& value, double* out) {
- if (!value) {
- *out = 0.0;
- return true;
- }
- if (!value.isDouble()) {
- return false;
- }
- const double i = value.asDouble();
- if (i < 0) {
- return false;
- }
- *out = i;
- return true;
-}
-
bool GetString(const Json::Value& value, std::string* out) {
if (!value) {
*out = {};
@@ -107,10 +89,6 @@ bool GetArray(const Json::Value& value, Parser<T> parser, std::vector<T>* out) {
return true;
}
-bool GetIntArray(const Json::Value& value, std::vector<int>* out) {
- return GetArray<int>(value, base::BindRepeating(&GetInt), out);
-}
-
bool GetStringArray(const Json::Value& value, std::vector<std::string>* out) {
return GetArray<std::string>(value, base::BindRepeating(&GetString), out);
}
@@ -165,27 +143,8 @@ std::unique_ptr<ReceiverCapability> ParseCapability(const Json::Value& value) {
return capability;
}
-std::unique_ptr<ReceiverStatus> ParseStatus(const Json::Value& value) {
- auto status = std::make_unique<ReceiverStatus>();
- if (!GetDouble(value["wifiSnr"], &(status->wifi_snr)) ||
- !GetIntArray(value["wifiSpeed"], &(status->wifi_speed))) {
- return {};
- }
- return status;
-}
-
} // namespace
-ReceiverStatus::ReceiverStatus() = default;
-ReceiverStatus::~ReceiverStatus() = default;
-ReceiverStatus::ReceiverStatus(ReceiverStatus&& receiver_response) = default;
-ReceiverStatus::ReceiverStatus(const ReceiverStatus& receiver_response) =
- default;
-ReceiverStatus& ReceiverStatus::operator=(ReceiverStatus&& receiver_response) =
- default;
-ReceiverStatus& ReceiverStatus::operator=(
- const ReceiverStatus& receiver_response) = default;
-
ReceiverCapability::ReceiverCapability() = default;
ReceiverCapability::~ReceiverCapability() = default;
ReceiverCapability::ReceiverCapability(ReceiverCapability&& receiver_response) =
@@ -256,13 +215,6 @@ std::unique_ptr<ReceiverResponse> ReceiverResponse::Parse(
}
break;
- case ResponseType::STATUS_RESPONSE:
- response->status_ = ParseStatus(root_node["status"]);
- if (!response->status_) {
- response->valid_ = false;
- }
- break;
-
case ResponseType::CAPABILITIES_RESPONSE:
response->capabilities_ = ParseCapability(root_node["capabilities"]);
if (!response->capabilities_) {
@@ -306,9 +258,6 @@ std::unique_ptr<ReceiverResponse> ReceiverResponse::CloneForTesting() const {
case ResponseType::ANSWER:
clone->answer_ = std::make_unique<openscreen::cast::Answer>(*answer_);
break;
- case ResponseType::STATUS_RESPONSE:
- clone->status_ = std::make_unique<ReceiverStatus>(*status_);
- break;
case ResponseType::CAPABILITIES_RESPONSE:
clone->capabilities_ =
std::make_unique<ReceiverCapability>(*capabilities_);
diff --git a/chromium/components/mirroring/service/receiver_response.h b/chromium/components/mirroring/service/receiver_response.h
index ba68b254c35..b86a464565b 100644
--- a/chromium/components/mirroring/service/receiver_response.h
+++ b/chromium/components/mirroring/service/receiver_response.h
@@ -20,27 +20,10 @@ namespace mirroring {
enum class ResponseType {
UNKNOWN,
ANSWER, // Response to OFFER message.
- STATUS_RESPONSE, // Response to GET_STATUS message.
CAPABILITIES_RESPONSE, // Response to GET_CAPABILITIES message.
RPC, // Rpc binary messages. The payload is base64 encoded.
};
-struct COMPONENT_EXPORT(MIRRORING_SERVICE) ReceiverStatus {
- ReceiverStatus();
- ~ReceiverStatus();
- ReceiverStatus(ReceiverStatus&& receiver_response);
- ReceiverStatus(const ReceiverStatus& receiver_response);
- ReceiverStatus& operator=(ReceiverStatus&& receiver_response);
- ReceiverStatus& operator=(const ReceiverStatus& receiver_response);
-
- // Current WiFi signal to noise ratio in decibels.
- double wifi_snr = 0.0;
-
- // Min, max, average, and current bandwidth in bps in order of the WiFi link.
- // Example: [1200, 1300, 1250, 1230].
- std::vector<int32_t> wifi_speed;
-};
-
struct COMPONENT_EXPORT(MIRRORING_SERVICE) ReceiverCapability {
ReceiverCapability();
~ReceiverCapability();
@@ -128,11 +111,6 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) ReceiverResponse {
return rpc_;
}
- const ReceiverStatus& status() const {
- DCHECK(valid_ && type_ == ResponseType::STATUS_RESPONSE);
- return *status_;
- }
-
const ReceiverCapability& capabilities() const {
DCHECK(valid_ && type_ == ResponseType::CAPABILITIES_RESPONSE);
return *capabilities_;
@@ -163,9 +141,6 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) ReceiverResponse {
// Contains the decoded (i.e. raw binary) RPC data.
std::string rpc_;
- // ResponseType::STATUS_RESPONSE
- std::unique_ptr<ReceiverStatus> status_;
-
// ResponseType::CAPABILITIES_RESPONSE
std::unique_ptr<ReceiverCapability> capabilities_;
diff --git a/chromium/components/mirroring/service/receiver_response_unittest.cc b/chromium/components/mirroring/service/receiver_response_unittest.cc
index d9983facbce..9005612d8d8 100644
--- a/chromium/components/mirroring/service/receiver_response_unittest.cc
+++ b/chromium/components/mirroring/service/receiver_response_unittest.cc
@@ -79,7 +79,6 @@ TEST_F(ReceiverResponseTest, ParseRealWorldAnswerMessage) {
EXPECT_EQ(50691, response->answer().udp_port);
EXPECT_EQ(std::vector<int32_t>({0, 1}), response->answer().send_indexes);
EXPECT_EQ(std::vector<uint32_t>({40863u, 759293u}), response->answer().ssrcs);
- EXPECT_EQ(false, response->answer().supports_wifi_status_reporting);
}
TEST_F(ReceiverResponseTest, ParseErrorMessage) {
@@ -114,28 +113,6 @@ TEST_F(ReceiverResponseTest, ParseErrorMessage) {
EXPECT_EQ(88, bar_value);
}
-TEST_F(ReceiverResponseTest, ParseStatusMessage) {
- const std::string response_string =
- R"({"seqNum": 777,
- "type": "STATUS_RESPONSE",
- "result": "ok",
- "sessionId": 12345323,
- "status": {
- "wifiSnr": 36.7,
- "wifiSpeed": [1234, 5678, 3000, 3001],
- "wifiFcsError": [12, 13, 12, 12]
- }
- })";
- auto response = ReceiverResponse::Parse(response_string);
- ASSERT_TRUE(response);
- EXPECT_EQ(777, response->sequence_number());
- EXPECT_EQ(ResponseType::STATUS_RESPONSE, response->type());
- ASSERT_TRUE(response->valid());
- EXPECT_EQ(36.7, response->status().wifi_snr);
- const std::vector<int32_t> expect_speed({1234, 5678, 3000, 3001});
- EXPECT_EQ(expect_speed, response->status().wifi_speed);
-}
-
TEST_F(ReceiverResponseTest, ParseCapabilityMessage) {
const std::string response_string =
R"({"sessionId": 999888777,
@@ -229,7 +206,6 @@ TEST_F(ReceiverResponseTest, ParseResponseWithNullField) {
"sendIndexes": [0,1],
"ssrcs": [152818,556029],
"IV": null,
- "receiverGetStatus": true,
"castMode": "mirroring"
},
"status": null,
@@ -245,7 +221,6 @@ TEST_F(ReceiverResponseTest, ParseResponseWithNullField) {
EXPECT_EQ(std::vector<int32_t>({0, 1}), response->answer().send_indexes);
EXPECT_EQ(std::vector<uint32_t>({152818u, 556029u}),
response->answer().ssrcs);
- EXPECT_EQ(true, response->answer().supports_wifi_status_reporting);
}
} // namespace mirroring
diff --git a/chromium/components/mirroring/service/receiver_setup_querier.cc b/chromium/components/mirroring/service/receiver_setup_querier.cc
index c06ef754e18..8ccfdbc6f0f 100644
--- a/chromium/components/mirroring/service/receiver_setup_querier.cc
+++ b/chromium/components/mirroring/service/receiver_setup_querier.cc
@@ -36,7 +36,7 @@ constexpr char kSetupQueryMethod[] = "GET";
bool ParseReceiverSetupInfo(const std::string& response,
std::string* build_version,
std::string* name) {
- const base::Optional<base::Value> root = base::JSONReader::Read(response);
+ const absl::optional<base::Value> root = base::JSONReader::Read(response);
return root && root->is_dict() &&
GetString(*root, "cast_build_revision", build_version) &&
diff --git a/chromium/components/mirroring/service/receiver_setup_querier.h b/chromium/components/mirroring/service/receiver_setup_querier.h
index 3a3e9938392..d931486bc56 100644
--- a/chromium/components/mirroring/service/receiver_setup_querier.h
+++ b/chromium/components/mirroring/service/receiver_setup_querier.h
@@ -12,13 +12,12 @@
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/timer/timer.h"
-#include "base/values.h"
#include "components/mirroring/mojom/session_observer.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace network {
class SimpleURLLoader;
diff --git a/chromium/components/mirroring/service/rtp_stream.cc b/chromium/components/mirroring/service/rtp_stream.cc
index 637ebd2214a..a6fb2aeb69f 100644
--- a/chromium/components/mirroring/service/rtp_stream.cc
+++ b/chromium/components/mirroring/service/rtp_stream.cc
@@ -73,6 +73,7 @@ void VideoRtpStream::InsertVideoFrame(
}
if (!(video_frame->format() == media::PIXEL_FORMAT_I420 ||
+ video_frame->format() == media::PIXEL_FORMAT_NV12 ||
video_frame->format() == media::PIXEL_FORMAT_YV12 ||
video_frame->format() == media::PIXEL_FORMAT_I420A)) {
client_->OnError("Incompatible video frame format.");
diff --git a/chromium/components/mirroring/service/rtp_stream.h b/chromium/components/mirroring/service/rtp_stream.h
index eff804f7cb9..23f91078449 100644
--- a/chromium/components/mirroring/service/rtp_stream.h
+++ b/chromium/components/mirroring/service/rtp_stream.h
@@ -43,16 +43,10 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) RtpStreamClient {
// Request a fresh video frame from the capturer.
virtual void RequestRefreshFrame() = 0;
- // The following are for hardware video encoding.
-
+ // The VEA is necessary for hardware encoding.
virtual void CreateVideoEncodeAccelerator(
media::cast::ReceiveVideoEncodeAcceleratorCallback callback) = 0;
- // TODO(crbug.com/1015472): Remove this interface. Instead, create the shared
- // memory in external video encoder through mojo::ScopedSharedBufferHandle.
- virtual void CreateVideoEncodeMemory(
- size_t size,
- media::cast::ReceiveVideoEncodeMemoryCallback callback) = 0;
};
// Receives video frames and submits the data to media::cast::VideoSender. It
diff --git a/chromium/components/mirroring/service/rtp_stream_unittest.cc b/chromium/components/mirroring/service/rtp_stream_unittest.cc
index 6effab0c424..3810392c288 100644
--- a/chromium/components/mirroring/service/rtp_stream_unittest.cc
+++ b/chromium/components/mirroring/service/rtp_stream_unittest.cc
@@ -39,9 +39,6 @@ class DummyClient final : public RtpStreamClient {
void RequestRefreshFrame() override {}
void CreateVideoEncodeAccelerator(
media::cast::ReceiveVideoEncodeAcceleratorCallback callback) override {}
- void CreateVideoEncodeMemory(
- size_t size,
- media::cast::ReceiveVideoEncodeMemoryCallback callback) override {}
base::WeakPtr<RtpStreamClient> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
@@ -90,8 +87,8 @@ TEST_F(RtpStreamTest, VideoStreaming) {
auto video_sender = std::make_unique<media::cast::VideoSender>(
cast_environment_, media::cast::GetDefaultVideoSenderConfig(),
- base::DoNothing(), base::DoNothing(), base::DoNothing(), &transport_,
- base::DoNothing(), base::DoNothing());
+ base::DoNothing(), base::DoNothing(), &transport_, base::DoNothing(),
+ base::DoNothing());
VideoRtpStream video_stream(std::move(video_sender), client_.GetWeakPtr());
{
base::RunLoop run_loop;
diff --git a/chromium/components/mirroring/service/session.cc b/chromium/components/mirroring/service/session.cc
index 0e692a9d58b..dc6e3ce5281 100644
--- a/chromium/components/mirroring/service/session.cc
+++ b/chromium/components/mirroring/service/session.cc
@@ -14,7 +14,6 @@
#include "base/cpu.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
-#include "base/memory/unsafe_shared_memory_region.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/rand_util.h"
@@ -22,6 +21,7 @@
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
@@ -259,25 +259,6 @@ void AddStreamObject(int stream_index,
stream_list->emplace_back(std::move(stream));
}
-// Checks whether receiver's build version is less than "1.|base_version|.xxxx".
-// Returns true if given version doesn't have the format of "1.xx.xxxx", so that
-// we don't assume that the receiver has the required new capabilities.
-bool NeedsWorkaroundForOlder1DotXVersions(
- const std::string& receiver_build_version,
- int base_version) {
- if (!base::StartsWith(receiver_build_version, "1.",
- base::CompareCase::SENSITIVE)) {
- return true;
- }
- const size_t end_pos = receiver_build_version.find_first_of('.', 2);
- if (end_pos == std::string::npos)
- return false;
- int version = 0;
- return (base::StringToInt(receiver_build_version.substr(2, end_pos - 2),
- &version) &&
- version < base_version);
-}
-
// Convert the sink capabilities to media::mojom::RemotingSinkMetadata.
media::mojom::RemotingSinkMetadata ToRemotingSinkMetadata(
const std::vector<std::string>& capabilities,
@@ -310,19 +291,15 @@ media::mojom::RemotingSinkMetadata ToRemotingSinkMetadata(
sink_metadata.video_capabilities.push_back(
RemotingSinkVideoCapability::CODEC_VP8);
} else if (capability == "vp9") {
- // Before 1.27 Earth receivers report "vp9" even though they don't support
- // remoting the VP9 encoded video.
- if (!NeedsWorkaroundForOlder1DotXVersions(receiver_build_version, 27) ||
- base::StartsWith(params.receiver_model_name, "Chromecast Ultra",
+ // TODO(crbug.com/1198616): receiver_model_name hacks should be removed.
+ if (base::StartsWith(params.receiver_model_name, "Chromecast Ultra",
base::CompareCase::SENSITIVE)) {
sink_metadata.video_capabilities.push_back(
RemotingSinkVideoCapability::CODEC_VP9);
}
} else if (capability == "hevc") {
- // Before 1.27 Earth receivers report "hevc" even though they don't
- // support remoting the HEVC encoded video.
- if (!NeedsWorkaroundForOlder1DotXVersions(receiver_build_version, 27) ||
- base::StartsWith(params.receiver_model_name, "Chromecast Ultra",
+ // TODO(crbug.com/1198616): receiver_model_name hacks should be removed.
+ if (base::StartsWith(params.receiver_model_name, "Chromecast Ultra",
base::CompareCase::SENSITIVE)) {
sink_metadata.video_capabilities.push_back(
RemotingSinkVideoCapability::CODEC_HEVC);
@@ -334,7 +311,7 @@ media::mojom::RemotingSinkMetadata ToRemotingSinkMetadata(
// Enable remoting 1080p 30fps or higher resolution/fps content for Chromecast
// Ultra receivers only.
- // TODO(crbug.com/1015467): Receiver should report this capability.
+ // TODO(crbug.com/1198616): receiver_model_name hacks should be removed.
if (params.receiver_model_name == "Chromecast Ultra") {
sink_metadata.video_capabilities.push_back(
RemotingSinkVideoCapability::SUPPORT_4K);
@@ -377,7 +354,8 @@ class Session::AudioCapturingCallback final
audio_data_callback_.Run(std::move(captured_audio), audio_capture_time);
}
- void OnCaptureError(const std::string& message) override {
+ void OnCaptureError(media::AudioCapturerSource::ErrorCode code,
+ const std::string& message) override {
if (!error_callback_.is_null())
std::move(error_callback_).Run();
}
@@ -571,27 +549,14 @@ void Session::CreateVideoEncodeAccelerator(
vea_provider_->CreateVideoEncodeAccelerator(
vea.InitWithNewPipeAndPassReceiver());
// std::make_unique doesn't work to create a unique pointer of the subclass.
- mojo_vea.reset(new media::MojoVideoEncodeAccelerator(std::move(vea),
- supported_profiles_));
+ mojo_vea = base::WrapUnique<media::VideoEncodeAccelerator>(
+ new media::MojoVideoEncodeAccelerator(std::move(vea),
+ supported_profiles_));
}
std::move(callback).Run(base::ThreadTaskRunnerHandle::Get(),
std::move(mojo_vea));
}
-void Session::CreateVideoEncodeMemory(
- size_t size,
- media::cast::ReceiveVideoEncodeMemoryCallback callback) {
- DVLOG(1) << __func__;
-
- base::UnsafeSharedMemoryRegion buf =
- base::UnsafeSharedMemoryRegion::Create(size);
-
- if (!buf.IsValid())
- LOG(WARNING) << "Browser failed to allocate shared memory.";
-
- std::move(callback).Run(std::move(buf));
-}
-
void Session::OnTransportStatusChanged(CastTransportStatus status) {
DVLOG(1) << __func__ << ": status=" << status;
switch (status) {
@@ -798,8 +763,6 @@ void Session::OnAnswer(const std::vector<FrameSenderConfig>& audio_configs,
weak_factory_.GetWeakPtr()),
base::BindRepeating(&Session::CreateVideoEncodeAccelerator,
weak_factory_.GetWeakPtr()),
- base::BindRepeating(&Session::CreateVideoEncodeMemory,
- weak_factory_.GetWeakPtr()),
cast_transport_.get(),
base::BindRepeating(&Session::SetTargetPlayoutDelay,
weak_factory_.GetWeakPtr()),
@@ -827,24 +790,15 @@ void Session::OnAnswer(const std::vector<FrameSenderConfig>& audio_configs,
media_remoter_->OnMirroringResumed();
}
- std::unique_ptr<WifiStatusMonitor> wifi_status_monitor;
- if (answer.supports_wifi_status_reporting) {
- wifi_status_monitor =
- std::make_unique<WifiStatusMonitor>(message_dispatcher_.get());
- // Nest Hub devices do not support remoting despite having a relatively new
- // build version, so we cannot filter with
- // NeedsWorkaroundForOlder1DotXVersions() here.
- if (initially_starting_session &&
- (base::StartsWith(session_params_.receiver_model_name, "Chromecast",
- base::CompareCase::SENSITIVE) ||
- base::StartsWith(session_params_.receiver_model_name, "Eureka Dongle",
- base::CompareCase::SENSITIVE))) {
- QueryCapabilitiesForRemoting();
- }
- } else {
- LogInfoMessage(
- base::StrCat({"Remoting is not supported on this receiver model: ",
- session_params_.receiver_model_name}));
+ // This is a workaround for Nest Hub devices, which do not support remoting.
+ // TODO(crbug.com/1198616): filtering hack should be removed. See
+ // issuetracker.google.com/135725157 for more information.
+ if (initially_starting_session &&
+ (base::StartsWith(session_params_.receiver_model_name, "Chromecast",
+ base::CompareCase::SENSITIVE) ||
+ base::StartsWith(session_params_.receiver_model_name, "Eureka Dongle",
+ base::CompareCase::SENSITIVE))) {
+ QueryCapabilitiesForRemoting();
}
if (initially_starting_session && observer_)
diff --git a/chromium/components/mirroring/service/session.h b/chromium/components/mirroring/service/session.h
index 623995acf19..93f509db43a 100644
--- a/chromium/components/mirroring/service/session.h
+++ b/chromium/components/mirroring/service/session.h
@@ -7,7 +7,6 @@
#include "base/component_export.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "components/mirroring/mojom/cast_message_channel.mojom.h"
#include "components/mirroring/mojom/resource_provider.mojom.h"
@@ -18,7 +17,6 @@
#include "components/mirroring/service/mirror_settings.h"
#include "components/mirroring/service/receiver_setup_querier.h"
#include "components/mirroring/service/rtp_stream.h"
-#include "components/mirroring/service/wifi_status_monitor.h"
#include "gpu/config/gpu_info.h"
#include "media/capture/video/video_capture_feedback.h"
#include "media/cast/cast_environment.h"
@@ -28,6 +26,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/mojom/network_context.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace media {
class AudioInputDevice;
@@ -78,9 +77,6 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) Session final
void RequestRefreshFrame() override;
void CreateVideoEncodeAccelerator(
media::cast::ReceiveVideoEncodeAcceleratorCallback callback) override;
- void CreateVideoEncodeMemory(
- size_t size,
- media::cast::ReceiveVideoEncodeMemoryCallback callback) override;
// Callbacks by media::cast::CastTransport::Client.
void OnTransportStatusChanged(media::cast::CastTransportStatus status);
@@ -185,10 +181,10 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) Session final
std::unique_ptr<AudioRtpStream> audio_stream_;
std::unique_ptr<VideoRtpStream> video_stream_;
std::unique_ptr<VideoCaptureClient> video_capture_client_;
- scoped_refptr<media::cast::CastEnvironment> cast_environment_ = nullptr;
+ scoped_refptr<media::cast::CastEnvironment> cast_environment_;
std::unique_ptr<media::cast::CastTransport> cast_transport_;
- scoped_refptr<base::SingleThreadTaskRunner> audio_encode_thread_ = nullptr;
- scoped_refptr<base::SingleThreadTaskRunner> video_encode_thread_ = nullptr;
+ scoped_refptr<base::SingleThreadTaskRunner> audio_encode_thread_;
+ scoped_refptr<base::SingleThreadTaskRunner> video_encode_thread_;
std::unique_ptr<AudioCapturingCallback> audio_capturing_callback_;
scoped_refptr<media::AudioInputDevice> audio_input_device_;
std::unique_ptr<MediaRemoter> media_remoter_;
diff --git a/chromium/components/mirroring/service/session_unittest.cc b/chromium/components/mirroring/service/session_unittest.cc
index f61003a8ee4..0e547f241ba 100644
--- a/chromium/components/mirroring/service/session_unittest.cc
+++ b/chromium/components/mirroring/service/session_unittest.cc
@@ -65,11 +65,6 @@ const openscreen::cast::Answer kAnswerWithConstraints{
openscreen::cast::AspectRatio{16, 9},
openscreen::cast::AspectRatioConstraint::kFixed,
},
- // We don't currently use the RTCP event log, or DSCP, or extensions.
- {},
- {},
- true, // receiver_get_status
- {},
};
class MockRemotingSource final : public media::mojom::RemotingSource {
@@ -213,7 +208,6 @@ class SessionTest : public mojom::ResourceProvider,
answer.swap(answer_);
} else {
answer = std::make_unique<openscreen::cast::Answer>();
- answer->supports_wifi_status_reporting = true;
}
answer->udp_port = receiver_endpoint_.port();
@@ -275,7 +269,6 @@ class SessionTest : public mojom::ResourceProvider,
EXPECT_CALL(*this, OnGetVideoCaptureHost()).Times(num_to_get_video_host);
EXPECT_CALL(*this, OnCreateAudioStream()).Times(num_to_create_audio_stream);
EXPECT_CALL(*this, OnError(_)).Times(0);
- EXPECT_CALL(*this, OnOutboundMessage("GET_STATUS")).Times(AtLeast(1));
EXPECT_CALL(*this, OnOutboundMessage("GET_CAPABILITIES")).Times(1);
EXPECT_CALL(*this, DidStart()).Times(1);
SendAnswer();
diff --git a/chromium/components/mirroring/service/udp_socket_client.cc b/chromium/components/mirroring/service/udp_socket_client.cc
index 2e3a644e78e..7a282262fd2 100644
--- a/chromium/components/mirroring/service/udp_socket_client.cc
+++ b/chromium/components/mirroring/service/udp_socket_client.cc
@@ -114,7 +114,7 @@ void UdpSocketClient::StartReceiving(
void UdpSocketClient::OnSocketConnected(
int result,
- const base::Optional<net::IPEndPoint>& addr) {
+ const absl::optional<net::IPEndPoint>& addr) {
DVLOG(2) << __func__ << ": result=" << result;
if (result == net::OK) {
@@ -146,8 +146,8 @@ void UdpSocketClient::StopReceiving() {
void UdpSocketClient::OnReceived(
int32_t result,
- const base::Optional<net::IPEndPoint>& src_addr,
- base::Optional<base::span<const uint8_t>> data) {
+ const absl::optional<net::IPEndPoint>& src_addr,
+ absl::optional<base::span<const uint8_t>> data) {
DVLOG(3) << __func__ << ": result=" << result;
DCHECK_GT(num_packets_pending_receive_, 0);
DCHECK(!packet_receiver_callback_.is_null());
diff --git a/chromium/components/mirroring/service/udp_socket_client.h b/chromium/components/mirroring/service/udp_socket_client.h
index f97b6fc902b..420b742b472 100644
--- a/chromium/components/mirroring/service/udp_socket_client.h
+++ b/chromium/components/mirroring/service/udp_socket_client.h
@@ -41,8 +41,8 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) UdpSocketClient final
// 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;
+ const absl::optional<net::IPEndPoint>& src_addr,
+ absl::optional<base::span<const uint8_t>> data) override;
private:
// The callback of network::mojom::UDPSocket::Send(). Further sending is
@@ -53,7 +53,7 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) UdpSocketClient final
// allowed to send after the socket is successfully connected to the
// |remote_endpoint_|.
void OnSocketConnected(int result,
- const base::Optional<net::IPEndPoint>& addr);
+ const absl::optional<net::IPEndPoint>& addr);
const net::IPEndPoint remote_endpoint_;
network::mojom::NetworkContext* const network_context_;
diff --git a/chromium/components/mirroring/service/video_capture_client.cc b/chromium/components/mirroring/service/video_capture_client.cc
index 4c8233ea3c4..3eb107a8831 100644
--- a/chromium/components/mirroring/service/video_capture_client.cc
+++ b/chromium/components/mirroring/service/video_capture_client.cc
@@ -10,6 +10,8 @@
#include "build/build_config.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/video_frame.h"
+#include "media/base/video_frame_pool.h"
+#include "media/base/video_util.h"
#include "media/capture/mojom/video_capture_types.mojom.h"
namespace mirroring {
@@ -265,6 +267,26 @@ void VideoCaptureClient::OnBufferReady(
base::BindOnce(&VideoCaptureClient::DidFinishConsumingFrame,
std::move(buffer_finished_callback)));
+ // Convert NV12 frames to I420, because NV12 is not supported by Cast
+ // Streaming.
+ // https://crbug.com/1206325
+ if (frame->format() == media::PIXEL_FORMAT_NV12) {
+ if (!nv12_to_i420_pool_)
+ nv12_to_i420_pool_ = std::make_unique<media::VideoFramePool>();
+ scoped_refptr<media::VideoFrame> new_frame =
+ nv12_to_i420_pool_->CreateFrame(
+ media::PIXEL_FORMAT_I420, frame->coded_size(),
+ frame->visible_rect(), frame->natural_size(), frame->timestamp());
+ media::Status status =
+ media::ConvertAndScaleFrame(*frame, *new_frame, nv12_to_i420_tmp_buf_);
+ if (!status.is_ok()) {
+ LOG(DFATAL) << "Unable to convert frame to I420.";
+ OnStateChanged(media::mojom::VideoCaptureState::FAILED);
+ return;
+ }
+ frame = new_frame;
+ }
+
frame->set_metadata(buffer->info->metadata);
if (buffer->info->color_space.has_value())
frame->set_color_space(buffer->info->color_space.value());
diff --git a/chromium/components/mirroring/service/video_capture_client.h b/chromium/components/mirroring/service/video_capture_client.h
index bcc18a7846e..5ae4be39398 100644
--- a/chromium/components/mirroring/service/video_capture_client.h
+++ b/chromium/components/mirroring/service/video_capture_client.h
@@ -20,6 +20,7 @@
namespace media {
class VideoFrame;
+class VideoFramePool;
struct VideoCaptureFeedback;
} // namespace media
@@ -108,6 +109,12 @@ class COMPONENT_EXPORT(MIRRORING_SERVICE) VideoCaptureClient
// Latest received feedback.
media::VideoCaptureFeedback feedback_;
+ // Cast Streaming does not support NV12 frames. When NV12 frames are received,
+ // these structures are used to convert them to I420 on the CPU.
+ // https://crbug.com/1206325
+ std::unique_ptr<media::VideoFramePool> nv12_to_i420_pool_;
+ std::vector<uint8_t> nv12_to_i420_tmp_buf_;
+
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<VideoCaptureClient> weak_factory_{this};
diff --git a/chromium/components/mirroring/service/video_capture_client_unittest.cc b/chromium/components/mirroring/service/video_capture_client_unittest.cc
index d9d4e654075..feaebc401a9 100644
--- a/chromium/components/mirroring/service/video_capture_client_unittest.cc
+++ b/chromium/components/mirroring/service/video_capture_client_unittest.cc
@@ -26,13 +26,15 @@ namespace {
const media::VideoCaptureFeedback kFeedback(0.6, 30.0, 1000);
+constexpr bool kNotPremapped = false;
+
media::mojom::VideoFrameInfoPtr GetVideoFrameInfo(const gfx::Size& size) {
media::VideoFrameMetadata metadata;
metadata.frame_rate = 30;
metadata.reference_time = base::TimeTicks();
return media::mojom::VideoFrameInfo::New(
base::TimeDelta(), metadata, media::PIXEL_FORMAT_I420, size,
- gfx::Rect(size), gfx::ColorSpace::CreateREC709(), nullptr);
+ gfx::Rect(size), kNotPremapped, gfx::ColorSpace::CreateREC709(), nullptr);
}
} // namespace
diff --git a/chromium/components/mirroring/service/wifi_status_monitor.cc b/chromium/components/mirroring/service/wifi_status_monitor.cc
deleted file mode 100644
index 549efa4fc5d..00000000000
--- a/chromium/components/mirroring/service/wifi_status_monitor.cc
+++ /dev/null
@@ -1,81 +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/mirroring/service/wifi_status_monitor.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/check.h"
-#include "base/json/json_writer.h"
-#include "base/values.h"
-#include "components/mirroring/service/message_dispatcher.h"
-
-namespace mirroring {
-
-namespace {
-
-// The interval to query the status.
-constexpr base::TimeDelta kQueryInterval = base::TimeDelta::FromMinutes(2);
-
-// The maximum number of recent status to be kept.
-constexpr int kMaxRecords = 30;
-
-} // namespace
-
-WifiStatusMonitor::WifiStatusMonitor(MessageDispatcher* message_dispatcher)
- : message_dispatcher_(message_dispatcher) {
- DCHECK(message_dispatcher_);
- message_dispatcher_->Subscribe(
- ResponseType::STATUS_RESPONSE,
- base::BindRepeating(&WifiStatusMonitor::RecordStatus,
- base::Unretained(this)));
- query_timer_.Start(FROM_HERE, kQueryInterval,
- base::BindRepeating(&WifiStatusMonitor::QueryStatus,
- base::Unretained(this)));
- QueryStatus();
-}
-
-WifiStatusMonitor::~WifiStatusMonitor() {
- message_dispatcher_->Unsubscribe(ResponseType::STATUS_RESPONSE);
-}
-
-std::vector<WifiStatus> WifiStatusMonitor::GetRecentValues() {
- std::vector<WifiStatus> recent_status(recent_status_.begin(),
- recent_status_.end());
- recent_status_.clear();
- return recent_status;
-}
-
-void WifiStatusMonitor::QueryStatus() {
- base::Value query(base::Value::Type::DICTIONARY);
- query.SetKey("type", base::Value("GET_STATUS"));
- query.SetKey("seqNum", base::Value(message_dispatcher_->GetNextSeqNumber()));
- base::Value::ListStorage status;
- status.emplace_back(base::Value("wifiSnr"));
- status.emplace_back(base::Value("wifiSpeed"));
- query.SetKey("get_status", base::Value(status));
- mojom::CastMessagePtr get_status_message = mojom::CastMessage::New();
- get_status_message->message_namespace = mojom::kWebRtcNamespace;
- const bool did_serialize_query =
- base::JSONWriter::Write(query, &get_status_message->json_format_data);
- DCHECK(did_serialize_query);
- message_dispatcher_->SendOutboundMessage(std::move(get_status_message));
-}
-
-void WifiStatusMonitor::RecordStatus(const ReceiverResponse& response) {
- if (!response.valid() || response.status().wifi_speed.size() != 4)
- return;
-
- if (recent_status_.size() == kMaxRecords)
- recent_status_.pop_front();
-
- WifiStatus received_status;
- received_status.snr = response.status().wifi_snr;
- // Only records the current speed.
- received_status.speed = response.status().wifi_speed[3];
- received_status.timestamp = base::Time::Now();
- recent_status_.emplace_back(received_status);
-}
-
-} // namespace mirroring
diff --git a/chromium/components/mirroring/service/wifi_status_monitor.h b/chromium/components/mirroring/service/wifi_status_monitor.h
deleted file mode 100644
index ba25a3fe968..00000000000
--- a/chromium/components/mirroring/service/wifi_status_monitor.h
+++ /dev/null
@@ -1,60 +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_MIRRORING_SERVICE_WIFI_STATUS_MONITOR_H_
-#define COMPONENTS_MIRRORING_SERVICE_WIFI_STATUS_MONITOR_H_
-
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/containers/circular_deque.h"
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-
-namespace mirroring {
-
-class MessageDispatcher;
-class ReceiverResponse;
-
-struct WifiStatus {
- double snr;
- int32_t speed; // The current WiFi speed.
- base::Time timestamp; // Recording time of this status.
-};
-
-// Periodically sends requests to the Cast device for WiFi network status
-// updates, processes responses, and maintains a recent history of data points.
-// This data can be included in feedback logs to help identify and diagnose
-// issues related to lousy network performance.
-class COMPONENT_EXPORT(MIRRORING_SERVICE) WifiStatusMonitor {
- public:
- // |message_dispatcher| must keep alive during the lifetime of this class.
- explicit WifiStatusMonitor(MessageDispatcher* message_dispatcher);
- ~WifiStatusMonitor();
-
- // Gets the recorded status and clear |recent_status_|.
- std::vector<WifiStatus> GetRecentValues();
-
- // Sends GET_STATUS message to receiver.
- void QueryStatus();
-
- // Callback for the STATUS_RESPONSE message. Records the WiFi status reported
- // by receiver.
- void RecordStatus(const ReceiverResponse& response);
-
- private:
- MessageDispatcher* const message_dispatcher_; // Outlives this class.
-
- base::RepeatingTimer query_timer_;
-
- // Stores the recent status. Will be reset when GetRecentValues() is called.
- base::circular_deque<WifiStatus> recent_status_;
-
- DISALLOW_COPY_AND_ASSIGN(WifiStatusMonitor);
-};
-
-} // namespace mirroring
-
-#endif // COMPONENTS_MIRRORING_SERVICE_WIFI_STATUS_MONITOR_H_
diff --git a/chromium/components/mirroring/service/wifi_status_monitor_unittest.cc b/chromium/components/mirroring/service/wifi_status_monitor_unittest.cc
deleted file mode 100644
index 68f8aad0d17..00000000000
--- a/chromium/components/mirroring/service/wifi_status_monitor_unittest.cc
+++ /dev/null
@@ -1,185 +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/mirroring/service/wifi_status_monitor.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/json/json_reader.h"
-#include "base/macros.h"
-#include "base/test/mock_callback.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"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using mirroring::mojom::CastMessage;
-
-namespace mirroring {
-
-namespace {
-
-bool IsNullMessage(const CastMessage& message) {
- return message.message_namespace.empty() && message.json_format_data.empty();
-}
-
-std::string GetMessageType(const CastMessage& message) {
- std::string type;
- std::unique_ptr<base::Value> value =
- base::JSONReader::ReadDeprecated(message.json_format_data);
- EXPECT_TRUE(value);
- EXPECT_TRUE(GetString(*value, "type", &type));
- return type;
-}
-
-void VerifyRecordedStatus(const std::vector<WifiStatus> recorded_status,
- double starting_snr,
- int starting_speed,
- int num_of_responses) {
- EXPECT_EQ(num_of_responses, static_cast<int>(recorded_status.size()));
- for (int i = 0; i < num_of_responses; ++i) {
- EXPECT_EQ(starting_snr + i, recorded_status[i].snr);
- EXPECT_EQ(starting_speed + i, recorded_status[i].speed);
- }
-}
-
-} // namespace
-
-class WifiStatusMonitorTest : public mojom::CastMessageChannel,
- public ::testing::Test {
- public:
- WifiStatusMonitorTest()
- : message_dispatcher_(receiver_.BindNewPipeAndPassRemote(),
- inbound_channel_.BindNewPipeAndPassReceiver(),
- error_callback_.Get()) {}
-
- ~WifiStatusMonitorTest() override {}
-
- // mojom::CastMessageChannel implementation. For outbound messages.
- void Send(mojom::CastMessagePtr message) override {
- last_outbound_message_.message_namespace = message->message_namespace;
- last_outbound_message_.json_format_data = message->json_format_data;
- }
-
- protected:
- // Generates and sends |num_of_responses| responses.
- void SendStatusResponses(double starting_snr,
- int starting_speed,
- int num_of_responses) {
- for (int i = 0; i < num_of_responses; ++i) {
- const std::string response =
- "{\"seqNum\":" +
- std::to_string(message_dispatcher_.GetNextSeqNumber()) +
- ","
- "\"type\": \"STATUS_RESPONSE\","
- "\"result\": \"ok\","
- "\"status\": {"
- "\"wifiSnr\":" +
- std::to_string(starting_snr + i) +
- ","
- "\"wifiSpeed\": [1234, 5678, 3000, " +
- std::to_string(starting_speed + i) +
- "],"
- "\"wifiFcsError\": [12, 13, 12, 12]}" // This will be ignored.
- "}";
- SendInboundMessage(response);
- }
- }
-
- // Sends an inbound message to |message_dispatcher|.
- void SendInboundMessage(const std::string& response) {
- CastMessage message;
- message.message_namespace = mojom::kWebRtcNamespace;
- message.json_format_data = response;
- inbound_channel_->Send(message.Clone());
- task_environment_.RunUntilIdle();
- }
-
- // Creates a WifiStatusMonitor and start monitoring the status.
- std::unique_ptr<WifiStatusMonitor> StartMonitoring() {
- EXPECT_TRUE(IsNullMessage(last_outbound_message_));
- EXPECT_CALL(error_callback_, Run(_)).Times(0);
- auto status_monitor =
- std::make_unique<WifiStatusMonitor>(&message_dispatcher_);
- task_environment_.RunUntilIdle();
- // Expect to receive request to send GET_STATUS message when create a
- // WifiStatusMonitor.
- EXPECT_EQ(mojom::kWebRtcNamespace,
- last_outbound_message_.message_namespace);
- EXPECT_EQ("GET_STATUS", GetMessageType(last_outbound_message_));
- // Clear the old outbound message.
- last_outbound_message_.message_namespace.clear();
- last_outbound_message_.json_format_data.clear();
- EXPECT_TRUE(IsNullMessage(last_outbound_message_));
- return status_monitor;
- }
-
- void RunUntilIdle() { task_environment_.RunUntilIdle(); }
-
- private:
- base::test::TaskEnvironment task_environment_;
- mojo::Receiver<mojom::CastMessageChannel> receiver_{this};
- mojo::Remote<mojom::CastMessageChannel> inbound_channel_;
- base::MockCallback<MessageDispatcher::ErrorCallback> error_callback_;
- MessageDispatcher message_dispatcher_;
- CastMessage last_outbound_message_;
-
- DISALLOW_COPY_AND_ASSIGN(WifiStatusMonitorTest);
-};
-
-TEST_F(WifiStatusMonitorTest, QueryStatusAndRecordResponse) {
- std::unique_ptr<WifiStatusMonitor> status_monitor = StartMonitoring();
-
- // Send two responses and verify the data are stored.
- SendStatusResponses(36.7, 3001, 2);
- std::vector<WifiStatus> recent_status = status_monitor->GetRecentValues();
- VerifyRecordedStatus(recent_status, 36.7, 3001, 2);
-
- // There should be no further status stored.
- recent_status = status_monitor->GetRecentValues();
- EXPECT_TRUE(recent_status.empty());
-
- // Sends more than the maximum number (30) of records that can be stored.
- SendStatusResponses(36.7, 3001, 40);
- // Expect that only the recent 30 records were stored.
- recent_status = status_monitor->GetRecentValues();
- VerifyRecordedStatus(recent_status, 46.7, 3011, 30);
-}
-
-TEST_F(WifiStatusMonitorTest, IgnoreMalformedStatusMessage) {
- std::unique_ptr<WifiStatusMonitor> status_monitor = StartMonitoring();
-
- // Sends a response with incomplete wifiSpeed data and expects it is ignored.
- const std::string response1 =
- "{\"seqNum\": 123,"
- "\"type\": \"STATUS_RESPONSE\","
- "\"result\": \"ok\","
- "\"status\": {"
- "\"wifiSnr\": 32,"
- "\"wifiSpeed\": [1234, 5678, 3000],"
- "\"wifiFcsError\": [12, 13, 12, 12]}"
- "}";
- SendInboundMessage(response1);
- std::vector<WifiStatus> recent_status = status_monitor->GetRecentValues();
- RunUntilIdle();
- EXPECT_TRUE(recent_status.empty());
-
- // Sends a response with null status field and expects it is ignored.
- const std::string response2 =
- "{\"seqNum\": 123,"
- "\"type\": \"STATUS_RESPONSE\","
- "\"status\": null}";
- SendInboundMessage(response2);
- recent_status = status_monitor->GetRecentValues();
- RunUntilIdle();
- EXPECT_TRUE(recent_status.empty());
-}
-
-} // namespace mirroring
diff --git a/chromium/components/navigation_interception/navigation_params.cc b/chromium/components/navigation_interception/navigation_params.cc
index fb3d76694bc..a0d1a5572af 100644
--- a/chromium/components/navigation_interception/navigation_params.cc
+++ b/chromium/components/navigation_interception/navigation_params.cc
@@ -18,7 +18,7 @@ NavigationParams::NavigationParams(
bool is_main_frame,
bool is_renderer_initiated,
const GURL& base_url_for_data_url,
- const base::Optional<url::Origin>& initiator_origin)
+ const absl::optional<url::Origin>& initiator_origin)
: url_(url),
referrer_(referrer),
navigation_id_(navigation_id),
diff --git a/chromium/components/navigation_interception/navigation_params.h b/chromium/components/navigation_interception/navigation_params.h
index bd6ae63de13..a9b567e332f 100644
--- a/chromium/components/navigation_interception/navigation_params.h
+++ b/chromium/components/navigation_interception/navigation_params.h
@@ -24,7 +24,7 @@ class NavigationParams {
bool is_main_frame,
bool is_renderer_initiated,
const GURL& base_url_for_data_url,
- const base::Optional<url::Origin>& initiator_origin);
+ const absl::optional<url::Origin>& initiator_origin);
~NavigationParams();
NavigationParams(const NavigationParams&);
NavigationParams& operator=(const NavigationParams&) = delete;
@@ -44,7 +44,7 @@ class NavigationParams {
bool is_main_frame() const { return is_main_frame_; }
bool is_renderer_initiated() const { return is_renderer_initiated_; }
const GURL& base_url_for_data_url() const { return base_url_for_data_url_; }
- const base::Optional<url::Origin>& initiator_origin() const {
+ const absl::optional<url::Origin>& initiator_origin() const {
return initiator_origin_;
}
@@ -61,7 +61,7 @@ class NavigationParams {
bool is_main_frame_;
bool is_renderer_initiated_;
GURL base_url_for_data_url_;
- base::Optional<url::Origin> initiator_origin_;
+ absl::optional<url::Origin> initiator_origin_;
};
} // namespace navigation_interception
diff --git a/chromium/components/net_log/net_export_file_writer.h b/chromium/components/net_log/net_export_file_writer.h
index 2987478ab2c..eb27c1ba95c 100644
--- a/chromium/components/net_log/net_export_file_writer.h
+++ b/chromium/components/net_log/net_export_file_writer.h
@@ -230,4 +230,4 @@ class NetExportFileWriter {
} // namespace net_log
-#endif // COMPONENTS_NET_LOG_NET_LOG_FILE_WRITER_H_
+#endif // COMPONENTS_NET_LOG_NET_EXPORT_FILE_WRITER_H_
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 891a0a3354f..8ad01ea87b9 100644
--- a/chromium/components/net_log/net_export_file_writer_unittest.cc
+++ b/chromium/components/net_log/net_export_file_writer_unittest.cc
@@ -17,6 +17,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_reader.h"
#include "base/json/json_string_value_serializer.h"
+#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/task_environment.h"
#include "base/values.h"
@@ -603,8 +604,7 @@ TEST_F(NetExportFileWriterTest, StartClearsFile) {
// Add some junk at the end of the file.
std::string junk_data("Hello");
- EXPECT_TRUE(base::AppendToFile(default_log_path(), junk_data.c_str(),
- junk_data.size()));
+ EXPECT_TRUE(base::AppendToFile(default_log_path(), junk_data));
int64_t junk_file_size;
EXPECT_TRUE(base::GetFileSize(default_log_path(), &junk_file_size));
diff --git a/chromium/components/net_log/net_export_ui_constants.cc b/chromium/components/net_log/net_export_ui_constants.cc
index 3d367bb931d..e27d6968019 100644
--- a/chromium/components/net_log/net_export_ui_constants.cc
+++ b/chromium/components/net_log/net_export_ui_constants.cc
@@ -7,6 +7,7 @@
namespace net_log {
// Resource paths.
+const char kNetExportUICSS[] = "net_export.css";
const char kNetExportUIJS[] = "net_export.js";
// Message handlers.
@@ -17,7 +18,6 @@ const char kStartNetLogHandler[] = "startNetLog";
const char kStopNetLogHandler[] = "stopNetLog";
// Other values.
-const char kOnExportNetLogInfoChanged[] =
- "NetExportView.getInstance().onExportNetLogInfoChanged";
+const char kNetLogInfoChangedEvent[] = "net-log-info-changed";
} // namespace net_log
diff --git a/chromium/components/net_log/net_export_ui_constants.h b/chromium/components/net_log/net_export_ui_constants.h
index ab9119eb4b9..85b3c3128b8 100644
--- a/chromium/components/net_log/net_export_ui_constants.h
+++ b/chromium/components/net_log/net_export_ui_constants.h
@@ -9,6 +9,7 @@ namespace net_log {
// Resource paths.
// Must match the resource file names.
+extern const char kNetExportUICSS[];
extern const char kNetExportUIJS[];
// Message handlers.
@@ -21,7 +22,7 @@ extern const char kStopNetLogHandler[];
// Other values.
// Must match the constants used in the resource files.
-extern const char kOnExportNetLogInfoChanged[];
+extern const char kNetLogInfoChangedEvent[];
} // namespace net_log
diff --git a/chromium/components/net_log/resources/net_export.html b/chromium/components/net_log/resources/net_export.html
index 43ec9d24bd3..11e4dbdb5dc 100644
--- a/chromium/components/net_log/resources/net_export.html
+++ b/chromium/components/net_log/resources/net_export.html
@@ -5,16 +5,7 @@
<if expr="is_android">
<meta name="viewport" content="width=device-width">
</if>
-
-<if expr="is_ios">
-<!-- TODO(crbug.com/487000): Remove this once injected by web. -->
-<script src="chrome://resources/js/ios/web_ui.js"></script>
-</if>
-
-<script src="chrome://resources/js/assert.js"></script>
-<script src="chrome://resources/js/util.js"></script>
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://net-export/net_export.js"></script>
+<script type="module" src="net_export.js"></script>
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<link rel="stylesheet" href="net_export.css">
<link rel="icon" id="fav-icon">
diff --git a/chromium/components/net_log/resources/net_export.js b/chromium/components/net_log/resources/net_export.js
index 520fce30207..0b42fd964ed 100644
--- a/chromium/components/net_log/resources/net_export.js
+++ b/chromium/components/net_log/resources/net_export.js
@@ -2,303 +2,303 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+
+// <if expr="is_ios">
+import 'chrome://resources/js/ios/web_ui.js';
+// </if>
+
+import {addSingletonGetter, addWebUIListener} from 'chrome://resources/js/cr.m.js';
+import {$} from 'chrome://resources/js/util.m.js';
+
/**
* Main entry point called once the page has loaded.
*/
function onLoad() {
- NetExportView.getInstance();
+ const view = NetExportView.getInstance();
+ view.initialize();
}
document.addEventListener('DOMContentLoaded', onLoad);
+const kIdStateDivUninitialized = 'state-uninitialized';
+const kIdStateDivInitial = 'state-initial';
+const kIdStateDivLogging = 'state-logging';
+const kIdStateDivStopped = 'state-stopped';
+const kIdStartLoggingButton = 'start-logging';
+const kIdStopLoggingButton = 'stop-logging';
+const kIdEmailLogButton = 'mobile-email';
+const kIdShowFileButton = 'show-file';
+const kIdCaptureModeLogging = 'capture-mode-logging';
+const kIdFilePathLogging = 'file-path-logging';
+const kIdCaptureModeStopped = 'capture-mode-stopped';
+const kIdFilePathStoppedLogging = 'file-path-stopped';
+const kIdStartOverButton = 'startover';
+const kIdPrivacyReadMoreLink = 'privacy-read-more-link';
+const kIdPrivacyReadMoreDiv = 'privacy-read-more';
+const kIdTooBigReadMoreLink = 'toobig-read-more-link';
+const kIdTooBigReadMoreDiv = 'toobig-read-more';
+const kIdLogMaxFileSizeInput = 'log-max-filesize';
+
/**
* This class handles the presentation of the net-export view. Used as a
* singleton.
*/
-const NetExportView = (function() {
- 'use strict';
-
- // --------------------------------------------------------------------------
-
- const kIdStateDivUninitialized = 'state-uninitialized';
- const kIdStateDivInitial = 'state-initial';
- const kIdStateDivLogging = 'state-logging';
- const kIdStateDivStopped = 'state-stopped';
- const kIdStartLoggingButton = 'start-logging';
- const kIdStopLoggingButton = 'stop-logging';
- const kIdEmailLogButton = 'mobile-email';
- const kIdShowFileButton = 'show-file';
- const kIdCaptureModeLogging = 'capture-mode-logging';
- const kIdFilePathLogging = 'file-path-logging';
- const kIdCaptureModeStopped = 'capture-mode-stopped';
- const kIdFilePathStoppedLogging = 'file-path-stopped';
- const kIdStartOverButton = 'startover';
- const kIdPrivacyReadMoreLink = 'privacy-read-more-link';
- const kIdPrivacyReadMoreDiv = 'privacy-read-more';
- const kIdTooBigReadMoreLink = 'toobig-read-more-link';
- const kIdTooBigReadMoreDiv = 'toobig-read-more';
- const kIdLogMaxFileSizeInput = 'log-max-filesize';
+class NetExportView {
+ constructor() {
+ this.infoForLoggedFile_ = null;
+ }
- /**
- * @constructor
- */
- function NetExportView() {
+ initialize() {
// Tell NetExportMessageHandler to notify the UI of future state changes
- // from this point on (through onExportNetLogInfoChanged()).
+ // from this point on and listen for net-log-info-changed events.
+ addWebUIListener(
+ 'net-log-info-changed', info => this.onExportNetLogInfoChanged_(info));
chrome.send('enableNotifyUIWithState');
+ }
+
+ /**
+ * Starts saving NetLog data to a file.
+ */
+ onStartLogging_() {
+ // Determine the capture mode to use.
+ const logMode =
+ document.querySelector('input[name="log-mode"]:checked').value;
+
+ // Determine the maximum file size, as the number of bytes (or -1 to mean
+ // no limit)
+ let maxLogFileSizeBytes = -1;
+ const fileSizeString = $(kIdLogMaxFileSizeInput).value;
+ const numMegabytes = parseFloat(fileSizeString);
+ if (!isNaN(numMegabytes)) {
+ // Convert to an integral number of bytes.
+ maxLogFileSizeBytes = Math.round(numMegabytes * 1024 * 1024);
+ }
+
+ chrome.send('startNetLog', [logMode, maxLogFileSizeBytes]);
+ }
+
+ /**
+ * Stops saving NetLog data to a file.
+ */
+ onStopLogging_() {
+ chrome.send('stopNetLog');
+ }
+ /**
+ * Sends NetLog data via email from browser (mobile only).
+ */
+ onSendEmail_() {
+ chrome.send('sendNetLog');
+ }
+
+ /**
+ * Reveals the log file in the shell (i.e. selects it in the Finder on
+ * Mac).
+ */
+ onShowFile_() {
+ chrome.send('showFile');
+ }
+
+ /**
+ * Transitions back to the "Start logging to disk" state.
+ */
+ onStartOver_() {
this.infoForLoggedFile_ = null;
+ this.renderInitial_();
}
- cr.addSingletonGetter(NetExportView);
-
- NetExportView.prototype = {
- /**
- * Starts saving NetLog data to a file.
- */
- onStartLogging_() {
- // Determine the capture mode to use.
- const logMode =
- document.querySelector('input[name="log-mode"]:checked').value;
-
- // Determine the maximum file size, as the number of bytes (or -1 to mean
- // no limit)
- let maxLogFileSizeBytes = -1;
- const fileSizeString = $(kIdLogMaxFileSizeInput).value;
- const numMegabytes = parseFloat(fileSizeString);
- if (!isNaN(numMegabytes)) {
- // Convert to an integral number of bytes.
- maxLogFileSizeBytes = Math.round(numMegabytes * 1024 * 1024);
- }
-
- chrome.send('startNetLog', [logMode, maxLogFileSizeBytes]);
- },
-
- /**
- * Stops saving NetLog data to a file.
- */
- onStopLogging_() {
- chrome.send('stopNetLog');
- },
-
- /**
- * Sends NetLog data via email from browser (mobile only).
- */
- onSendEmail_() {
- chrome.send('sendNetLog');
- },
-
- /**
- * Reveals the log file in the shell (i.e. selects it in the Finder on
- * Mac).
- */
- onShowFile_() {
- chrome.send('showFile');
- },
-
- /**
- * Transitions back to the "Start logging to disk" state.
- */
- onStartOver_() {
- this.infoForLoggedFile_ = null;
- this.renderInitial_();
- },
-
- /**
- * Updates the UI to reflect the current state. The state transitions are
- * sent by the browser controller (NetLogFileWriter):
- *
- * * UNINITIALIZED - This is the initial state when net-export is opened
- * for the first time, or there was an error during initialization.
- * This state is short-lived and likely not observed; will
- * immediately transition to INITIALIZING).
- *
- * * INITIALIZING - On desktop UI this is pretty much a no-op. On the
- * mobile UI, this state is when the controller checks the disk for
- * a previous net-log file (from past run of the browser). After
- * success will transition to NOT_LOGGING. On failure will
- * transition to UNINITIALIZED (rare).
- *
- * * NOT_LOGGING - This is the steady-state. It means initialization
- * completed and we are not currently logging. Being in this state
- * either means:
- * (1) We were logging and then the user stopped (earlier states
- * were STATE_LOGGING / STATE_STOPPING_LOG).
- * (2) We have never started logging (previous state was
- * INITIALIZING).
- *
- * * STARTING_LOG - This state means the user has clicked the "Start log"
- * button and logging is about to get started (files may not have
- * been created yet).
- *
- * * LOGGING - This state means that logging is currently in progress.
- * The destination path of the log, and the capture mode are known
- * and will be reflected in the parameters.
- *
- * * STOPPING_LOG - This state means the user has clicked the "Stop
- * logging" button, and the log file is in the process of being
- * finalized. Once the state transitions to NOT_LOGGING then the log
- * is complete, and can safely be copied/emailed.
- */
- onExportNetLogInfoChanged(info) {
- switch (info.state) {
- case 'UNINITIALIZED':
- case 'INITIALIZING':
- this.renderUninitialized_();
- break;
-
- case 'NOT_LOGGING':
- if (this.infoForLoggedFile_) {
- // There is no "stopped logging" state. We manufacture that in the
- // UI in response to a transition from LOGGING --> NOT_LOGGING.
- this.renderStoppedLogging_(this.infoForLoggedFile_);
-
- // TODO(eroman): prevent future state transitions. In desktop UI
- // could start logging in a new tab, and it would reset this one.
- } else if (info.logExists) {
- // In the mobile UI, initialization may have found a
- // pre-existing log file.
- this.renderStoppedLogging_(info);
- } else {
- this.renderInitial_();
- }
- break;
-
- case 'STARTING_LOG':
- // This is a short-lived state, no need to do anything special.
- // Disabling the buttons would be nice, however it is not crucial as
- // the controller will reject commands while in this state anyway.
+ /**
+ * Updates the UI to reflect the current state. The state transitions are
+ * sent by the browser controller (NetLogFileWriter):
+ *
+ * * UNINITIALIZED - This is the initial state when net-export is opened
+ * for the first time, or there was an error during initialization.
+ * This state is short-lived and likely not observed; will
+ * immediately transition to INITIALIZING).
+ *
+ * * INITIALIZING - On desktop UI this is pretty much a no-op. On the
+ * mobile UI, this state is when the controller checks the disk for
+ * a previous net-log file (from past run of the browser). After
+ * success will transition to NOT_LOGGING. On failure will
+ * transition to UNINITIALIZED (rare).
+ *
+ * * NOT_LOGGING - This is the steady-state. It means initialization
+ * completed and we are not currently logging. Being in this state
+ * either means:
+ * (1) We were logging and then the user stopped (earlier states
+ * were STATE_LOGGING / STATE_STOPPING_LOG).
+ * (2) We have never started logging (previous state was
+ * INITIALIZING).
+ *
+ * * STARTING_LOG - This state means the user has clicked the "Start log"
+ * button and logging is about to get started (files may not have
+ * been created yet).
+ *
+ * * LOGGING - This state means that logging is currently in progress.
+ * The destination path of the log, and the capture mode are known
+ * and will be reflected in the parameters.
+ *
+ * * STOPPING_LOG - This state means the user has clicked the "Stop
+ * logging" button, and the log file is in the process of being
+ * finalized. Once the state transitions to NOT_LOGGING then the log
+ * is complete, and can safely be copied/emailed.
+ */
+ onExportNetLogInfoChanged_(info) {
+ switch (info.state) {
+ case 'UNINITIALIZED':
+ case 'INITIALIZING':
+ this.renderUninitialized_();
+ break;
+
+ case 'NOT_LOGGING':
+ if (this.infoForLoggedFile_) {
+ // There is no "stopped logging" state. We manufacture that in the
+ // UI in response to a transition from LOGGING --> NOT_LOGGING.
+ this.renderStoppedLogging_(this.infoForLoggedFile_);
+
+ // TODO(eroman): prevent future state transitions. In desktop UI
+ // could start logging in a new tab, and it would reset this one.
+ } else if (info.logExists) {
+ // In the mobile UI, initialization may have found a
+ // pre-existing log file.
+ this.renderStoppedLogging_(info);
+ } else {
this.renderInitial_();
- break;
-
- case 'LOGGING':
- // Cache the last information for this logging session, so once
- // logging is stopped will know what path information to display.
- this.infoForLoggedFile_ = info;
- this.renderLogging_(info);
- break;
-
- case 'STOPPING_LOG':
- // This is a short-lived state, no need to do anything special.
- this.renderLogging_(info);
- break;
- }
- },
-
- /**
- * Updates the UI to display the "uninitialized" state. This is only
- * visible for a short period of time, or longer if initialization failed
- * (and didn't transition to a different state).
- */
- renderUninitialized_() {
- this.showStateDiv_(kIdStateDivUninitialized);
- },
-
- /**
- * Updates the UI to display the "initial" state. This is the state when
- * logging has not been started yet, and there are controls to start
- * logging.
- */
- renderInitial_() {
- this.showStateDiv_(kIdStateDivInitial);
- $(kIdStartLoggingButton).onclick = this.onStartLogging_.bind(this);
- },
-
- /**
- * Updates the UI to display the "logging" state. This is the state while
- * capturing is in progress and being written to disk.
- */
- renderLogging_(info) {
- this.showStateDiv_(kIdStateDivLogging);
- this.setFavicon_(
- 'data:image/svg+xml,<svg version="1.1" ' +
- 'xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">' +
- '<circle cx="16" cy="16" r="14" fill="red" stroke="black" /></svg>');
- $(kIdStopLoggingButton).onclick = this.onStopLogging_.bind(this);
- $(kIdCaptureModeLogging).textContent = this.getCaptureModeText_(info);
- $(kIdFilePathLogging).textContent = info.file;
- },
-
- /*
- * Updates the UI to display the state when logging has stopped.
- */
- renderStoppedLogging_(info) {
- this.setFavicon_('data:image/x-icon;base64,');
- this.showStateDiv_(kIdStateDivStopped);
-
- // The email button is only available in the mobile UI.
- if ($(kIdEmailLogButton)) {
- $(kIdEmailLogButton).onclick = this.onSendEmail_.bind(this);
- }
- // The show file button is only available in the desktop UI.
- if ($(kIdShowFileButton)) {
- $(kIdShowFileButton).onclick = this.onShowFile_.bind(this);
- }
- $(kIdStartOverButton).onclick = this.onStartOver_.bind(this);
-
- $(kIdFilePathStoppedLogging).textContent = info.file;
-
- $(kIdCaptureModeStopped).textContent = this.getCaptureModeText_(info);
-
- // Hook up the "read more..." link for privacy information.
- $(kIdPrivacyReadMoreLink).onclick =
- this.showPrivacyReadMore_.bind(this, true);
- this.showPrivacyReadMore_(false);
-
- // Hook up the "read more..." link for reducing log size information.
- $(kIdTooBigReadMoreLink).onclick =
- this.showTooBigReadMore_.bind(this, true);
- this.showTooBigReadMore_(false);
- },
-
- /**
- * Gets the textual label for a capture mode from the HTML.
- */
- getCaptureModeText_(info) {
- // TODO(eroman): Should not hardcode "Unknown" (will not work properly if
- // the HTML is internationalized).
- if (!info.logCaptureModeKnown) {
- return 'Unknown';
- }
-
- const radioButton = document.querySelector(
- 'input[name="log-mode"][value="' + info.captureMode + '"]');
- if (!radioButton) {
- return 'Unknown';
- }
- return radioButton.parentElement.textContent;
- },
-
- showPrivacyReadMore_(show) {
- $(kIdPrivacyReadMoreDiv).hidden = !show;
- $(kIdPrivacyReadMoreLink).hidden = show;
- },
-
- showTooBigReadMore_(show) {
- $(kIdTooBigReadMoreDiv).hidden = !show;
- $(kIdTooBigReadMoreLink).hidden = show;
- },
-
- showStateDiv_(divId) {
- const kAllDivIds = [
- kIdStateDivUninitialized,
- kIdStateDivInitial,
- kIdStateDivLogging,
- kIdStateDivStopped
- ];
-
- for (const curDivId of kAllDivIds) {
- $(curDivId).hidden = divId !== curDivId;
- }
- },
-
- /**
- * Sets the icon for the tab to reflect current capturing state.
- */
- setFavicon_(dataUrl) {
- document.getElementById('fav-icon').href = dataUrl;
+ }
+ break;
+
+ case 'STARTING_LOG':
+ // This is a short-lived state, no need to do anything special.
+ // Disabling the buttons would be nice, however it is not crucial as
+ // the controller will reject commands while in this state anyway.
+ this.renderInitial_();
+ break;
+
+ case 'LOGGING':
+ // Cache the last information for this logging session, so once
+ // logging is stopped will know what path information to display.
+ this.infoForLoggedFile_ = info;
+ this.renderLogging_(info);
+ break;
+
+ case 'STOPPING_LOG':
+ // This is a short-lived state, no need to do anything special.
+ this.renderLogging_(info);
+ break;
+ }
+ }
+
+ /**
+ * Updates the UI to display the "uninitialized" state. This is only
+ * visible for a short period of time, or longer if initialization failed
+ * (and didn't transition to a different state).
+ */
+ renderUninitialized_() {
+ this.showStateDiv_(kIdStateDivUninitialized);
+ }
+
+ /**
+ * Updates the UI to display the "initial" state. This is the state when
+ * logging has not been started yet, and there are controls to start
+ * logging.
+ */
+ renderInitial_() {
+ this.showStateDiv_(kIdStateDivInitial);
+ $(kIdStartLoggingButton).onclick = this.onStartLogging_.bind(this);
+ }
+
+ /**
+ * Updates the UI to display the "logging" state. This is the state while
+ * capturing is in progress and being written to disk.
+ */
+ renderLogging_(info) {
+ this.showStateDiv_(kIdStateDivLogging);
+ this.setFavicon_(
+ 'data:image/svg+xml,<svg version="1.1" ' +
+ 'xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">' +
+ '<circle cx="16" cy="16" r="14" fill="red" stroke="black" /></svg>');
+ $(kIdStopLoggingButton).onclick = this.onStopLogging_.bind(this);
+ $(kIdCaptureModeLogging).textContent = this.getCaptureModeText_(info);
+ $(kIdFilePathLogging).textContent = info.file;
+ }
+
+ /*
+ * Updates the UI to display the state when logging has stopped.
+ */
+ renderStoppedLogging_(info) {
+ this.setFavicon_('data:image/x-icon;base64,');
+ this.showStateDiv_(kIdStateDivStopped);
+
+ // The email button is only available in the mobile UI.
+ if ($(kIdEmailLogButton)) {
+ $(kIdEmailLogButton).onclick = this.onSendEmail_.bind(this);
+ }
+ // The show file button is only available in the desktop UI.
+ if ($(kIdShowFileButton)) {
+ $(kIdShowFileButton).onclick = this.onShowFile_.bind(this);
}
- };
+ $(kIdStartOverButton).onclick = this.onStartOver_.bind(this);
+
+ $(kIdFilePathStoppedLogging).textContent = info.file;
+
+ $(kIdCaptureModeStopped).textContent = this.getCaptureModeText_(info);
+
+ // Hook up the "read more..." link for privacy information.
+ $(kIdPrivacyReadMoreLink).onclick =
+ this.showPrivacyReadMore_.bind(this, true);
+ this.showPrivacyReadMore_(false);
+
+ // Hook up the "read more..." link for reducing log size information.
+ $(kIdTooBigReadMoreLink).onclick =
+ this.showTooBigReadMore_.bind(this, true);
+ this.showTooBigReadMore_(false);
+ }
+
+ /**
+ * Gets the textual label for a capture mode from the HTML.
+ */
+ getCaptureModeText_(info) {
+ // TODO(eroman): Should not hardcode "Unknown" (will not work properly if
+ // the HTML is internationalized).
+ if (!info.logCaptureModeKnown) {
+ return 'Unknown';
+ }
+
+ const radioButton = document.querySelector(
+ 'input[name="log-mode"][value="' + info.captureMode + '"]');
+ if (!radioButton) {
+ return 'Unknown';
+ }
+ return radioButton.parentElement.textContent;
+ }
+
+ showPrivacyReadMore_(show) {
+ $(kIdPrivacyReadMoreDiv).hidden = !show;
+ $(kIdPrivacyReadMoreLink).hidden = show;
+ }
+
+ showTooBigReadMore_(show) {
+ $(kIdTooBigReadMoreDiv).hidden = !show;
+ $(kIdTooBigReadMoreLink).hidden = show;
+ }
+
+ showStateDiv_(divId) {
+ const kAllDivIds = [
+ kIdStateDivUninitialized, kIdStateDivInitial, kIdStateDivLogging,
+ kIdStateDivStopped
+ ];
+
+ for (const curDivId of kAllDivIds) {
+ $(curDivId).hidden = divId !== curDivId;
+ }
+ }
+
+ /**
+ * Sets the icon for the tab to reflect current capturing state.
+ */
+ setFavicon_(dataUrl) {
+ document.getElementById('fav-icon').href = dataUrl;
+ }
+}
- return NetExportView;
-})();
+addSingletonGetter(NetExportView);
diff --git a/chromium/components/neterror/resources/neterror.css b/chromium/components/neterror/resources/neterror.css
index c67d28ff280..d16e7ae5250 100644
--- a/chromium/components/neterror/resources/neterror.css
+++ b/chromium/components/neterror/resources/neterror.css
@@ -812,16 +812,9 @@ html[dir='rtl'].offline .icon-offline {
display: none;
}
-/* iOS WKWebView inverts the background color set at the HTML level
-whereas Blink does not. */
.offline.inverted {
- filter: invert(1);
-<if expr="not is_ios">
- background-color: #000;
-</if>
-<if expr="is_ios">
background-color: #fff;
-</if>
+ filter: invert(1);
}
.offline.inverted body {
@@ -835,6 +828,7 @@ whereas Blink does not. */
margin: 0 auto;
max-width: 600px;
padding-top: 100px;
+ position: relative;
width: 100%;
}
@@ -896,6 +890,90 @@ whereas Blink does not. */
font-size: xx-small;
position: absolute;
text-align: center;
+ transition: color 1.5s cubic-bezier(0.65, 0.05, 0.36, 1);
+}
+
+/* Custom toggle */
+.slow-speed-toggle {
+ align-items: center;
+ background: var(--google-gray-50);
+ border-radius: 24px/50%;
+ bottom: 0;
+ color: var(--error-code-color);
+ display: inline-flex;
+ font-size: 1em;
+ left: 0;
+ line-height: 1.1em;
+ margin: 5px auto;
+ padding: 2px 12px 3px 20px;
+ position: absolute;
+ right: 0;
+ width: max-content;
+ z-index: 999;
+}
+
+.slow-speed-toggle.hidden {
+ display: none;
+}
+
+.slow-speed-toggle [type=checkbox] {
+ opacity: 0;
+ pointer-events: none;
+ position: absolute;
+}
+
+.slow-speed-toggle .slow-speed-toggle {
+ cursor: pointer;
+ margin-inline-start: 8px;
+ padding: 8px 4px;
+ position: relative;
+}
+
+.slow-speed-toggle [type=checkbox] {
+ opacity: 0;
+ pointer-events: none;
+ position: absolute;
+}
+
+.slow-speed-toggle .slow-speed-toggle::before,
+.slow-speed-toggle .slow-speed-toggle::after {
+ content: '';
+ display: block;
+ margin: 0 3px;
+ transition: all 100ms cubic-bezier(0.4, 0, 1, 1);
+}
+
+.slow-speed-toggle .slow-speed-toggle::before {
+ background: rgb(189,193,198);
+ border-radius: 0.65em;
+ height: 0.9em;
+ width: 2em;
+}
+
+.slow-speed-toggle .slow-speed-toggle::after {
+ background: #fff;
+ border-radius: 50%;
+ box-shadow: 0 1px 3px 0 rgb(0 0 0 / 40%);
+ height: 1.2em;
+ position: absolute;
+ top: 51%;
+ transform: translate(-20%, -50%);
+ width: 1.1em;
+}
+
+.slow-speed-toggle [type=checkbox]:focus + .slow-speed-toggle {
+ box-shadow: 0 0 8px rgb(94, 158, 214);
+ outline: 1px solid rgb(93, 157, 213);
+}
+
+.slow-speed-toggle [type=checkbox]:checked + .slow-speed-toggle::before {
+ background: var(--google-blue-600);
+ opacity: 0.5;
+}
+
+.slow-speed-toggle [type=checkbox]:checked + .slow-speed-toggle::after {
+ background: var(--google-blue-600);
+ transform: translate(calc(2em - 90%), -50%);
}
@media (max-width: 420px) {
@@ -1030,19 +1108,18 @@ whereas Blink does not. */
}
.offline.inverted {
- filter: invert(0);
- <if expr="not is_ios">
background-color: var(--background-color);
- </if>
- <if expr="is_ios">
- background-color: #fff;
- </if>
+ filter: invert(0);
}
.offline.inverted body {
background-color: #fff;
}
+ .offline.inverted .offline-runner-live-region {
+ color: #fff;
+ }
+
#suggestions-list a {
color: var(--link-color);
}
@@ -1050,4 +1127,18 @@ whereas Blink does not. */
#error-information-button {
filter: invert(0.6);
}
+
+ .slow-speed-toggle {
+ background: var(--google-gray-800);
+ color: var(--google-gray-100);
+ }
+
+ .slow-speed-toggle .slow-speed-toggle::before {
+ background: rgb(189,193,198);
+ }
+
+ .slow-speed-toggle [type=checkbox]:checked + .slow-speed-toggle::after,
+ .slow-speed-toggle [type=checkbox]:checked + .slow-speed-toggle::before {
+ background: var(--google-blue-300);
+ }
}
diff --git a/chromium/components/neterror/resources/offline.js b/chromium/components/neterror/resources/offline.js
index 024a6fb678a..b8f34a0f0a4 100644
--- a/chromium/components/neterror/resources/offline.js
+++ b/chromium/components/neterror/resources/offline.js
@@ -23,7 +23,7 @@ function Runner(outerContainerId, opt_config) {
// A div to intercept touch events. Only set while (playing && useTouch).
this.touchController = null;
- this.config = opt_config || Runner.config;
+ this.config = opt_config || Object.assign(Runner.config, Runner.normalConfig);
// Logical dimensions of the container.
this.dimensions = Runner.defaultDimensions;
@@ -50,6 +50,7 @@ function Runner(outerContainerId, opt_config) {
this.runningTime = 0;
this.msPerFrame = 1000 / FPS;
this.currentSpeed = this.config.SPEED;
+ Runner.slowDown = false;
this.obstacles = [];
@@ -132,14 +133,16 @@ const A11Y_STRINGS = {
gameOver: 'dinoGameA11yGameOver',
highScore: 'dinoGameA11yHighScore',
jump: 'dinoGameA11yJump',
- started: 'dinoGameA11yStartGame'
+ started: 'dinoGameA11yStartGame',
+ speedLabel: 'dinoGameA11ySpeedToggle'
};
/**
* Default game configuration.
+ * Shared config for all versions of the game. Additional parameters are
+ * defined in Runner.normalConfig and Runner.slowConfig.
*/
Runner.config = {
- ACCELERATION: 0.001,
AUDIOCUE_PROXIMITY_THRESHOLD: 190,
AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y: 250,
BG_CLOUD_SPEED: 0.2,
@@ -151,18 +154,12 @@ Runner.config = {
FADE_DURATION: 1,
FLASH_DURATION: 1000,
GAMEOVER_CLEAR_TIME: 1200,
- GAP_COEFFICIENT: 0.6,
- GRAVITY: 0.6,
INITIAL_JUMP_VELOCITY: 12,
INVERT_FADE_DURATION: 12000,
- INVERT_DISTANCE: 700,
MAX_BLINK_COUNT: 3,
MAX_CLOUDS: 6,
MAX_OBSTACLE_LENGTH: 3,
MAX_OBSTACLE_DUPLICATION: 2,
- MAX_SPEED: 13,
- MIN_JUMP_HEIGHT: 35,
- MOBILE_SPEED_COEFFICIENT: 1.2,
RESOURCE_TEMPLATE_ID: 'audio-resources',
SPEED: 6,
SPEED_DROP_COEFFICIENT: 3,
@@ -170,6 +167,29 @@ Runner.config = {
ARCADE_MODE_TOP_POSITION_PERCENT: 0.1
};
+Runner.normalConfig = {
+ ACCELERATION: 0.001,
+ AUDIOCUE_PROXIMITY_THRESHOLD: 190,
+ AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y: 250,
+ GAP_COEFFICIENT: 0.6,
+ INVERT_DISTANCE: 700,
+ MAX_SPEED: 13,
+ MOBILE_SPEED_COEFFICIENT: 1.2,
+ SPEED: 6
+};
+
+
+Runner.slowConfig = {
+ ACCELERATION: 0.0005,
+ AUDIOCUE_PROXIMITY_THRESHOLD: 170,
+ AUDIOCUE_PROXIMITY_THRESHOLD_MOBILE_A11Y: 220,
+ GAP_COEFFICIENT: 0.3,
+ INVERT_DISTANCE: 350,
+ MAX_SPEED: 9,
+ MOBILE_SPEED_COEFFICIENT: 1.5,
+ SPEED: 4.2
+};
+
/**
* Default dimensions.
@@ -393,8 +413,9 @@ Runner.prototype = {
// Reduce the speed on smaller mobile screens.
if (this.dimensions.WIDTH < DEFAULT_WIDTH) {
- const mobileSpeed = speed * this.dimensions.WIDTH / DEFAULT_WIDTH *
- this.config.MOBILE_SPEED_COEFFICIENT;
+ const mobileSpeed = Runner.slowDown ? speed :
+ speed * this.dimensions.WIDTH /
+ DEFAULT_WIDTH * this.config.MOBILE_SPEED_COEFFICIENT;
this.currentSpeed = mobileSpeed > speed ? speed : mobileSpeed;
} else if (opt_speed) {
this.currentSpeed = opt_speed;
@@ -431,6 +452,25 @@ Runner.prototype = {
this.a11yStatusEl.textContent = '';
Runner.a11yStatusEl = this.a11yStatusEl;
+ // Add checkbox to slow down the game.
+ this.slowSpeedCheckboxLabel = document.createElement('label');
+ this.slowSpeedCheckboxLabel.className = 'slow-speed-toggle hidden';
+ this.slowSpeedCheckboxLabel.textContent =
+ getA11yString(A11Y_STRINGS.speedLabel);
+
+ this.slowSpeedCheckbox = document.createElement('input');
+ this.slowSpeedCheckbox.setAttribute('type', 'checkbox');
+ this.slowSpeedCheckbox.setAttribute(
+ 'title', getA11yString(A11Y_STRINGS.speedLabel));
+ this.slowSpeedCheckbox.setAttribute('tabindex', '0');
+ this.slowSpeedCheckbox.setAttribute('checked', 'checked');
+
+ this.slowSpeedToggleEl = document.createElement('span');
+ this.slowSpeedToggleEl.className = 'slow-speed-toggle';
+
+ this.slowSpeedCheckboxLabel.appendChild(this.slowSpeedCheckbox);
+ this.slowSpeedCheckboxLabel.appendChild(this.slowSpeedToggleEl);
+
if (IS_IOS) {
this.outerContainerEl.appendChild(this.a11yStatusEl);
} else {
@@ -457,6 +497,7 @@ Runner.prototype = {
this.tRex = new Trex(this.canvas, this.spriteDef.TREX);
this.outerContainerEl.appendChild(this.containerEl);
+ this.outerContainerEl.appendChild(this.slowSpeedCheckboxLabel);
this.startListening();
this.update();
@@ -580,6 +621,7 @@ Runner.prototype = {
if (this.isArcadeMode()) {
this.setArcadeMode();
}
+ this.toggleSpeed();
this.runningTime = 0;
this.playingIntro = false;
this.tRex.playingIntro = false;
@@ -808,6 +850,7 @@ Runner.prototype = {
*/
handleCanvasKeyPress(e) {
if (!this.activated) {
+ this.toggleSpeed();
Runner.audioCues = true;
this.generatedSoundFx.init();
Runner.generatedSoundFx = this.generatedSoundFx;
@@ -828,12 +871,62 @@ Runner.prototype = {
},
/**
+ * Toggle speed setting if toggle is shown.
+ */
+ toggleSpeed() {
+ if (Runner.audioCues) {
+ const speedChange = Runner.slowDown != this.slowSpeedCheckbox.checked;
+
+ if (speedChange) {
+ Runner.slowDown = this.slowSpeedCheckbox.checked;
+ const updatedConfig =
+ Runner.slowDown ? Runner.slowConfig : Runner.normalConfig;
+
+ Runner.config = Object.assign(Runner.config, updatedConfig);
+ this.currentSpeed = updatedConfig.SPEED;
+ this.tRex.enableSlowConfig();
+ this.horizon.adjustObstacleSpeed();
+ }
+ this.disableSpeedToggle(true);
+ }
+ },
+
+ /**
+ * Show the speed toggle.
+ * From focus event or when audio cues are activated.
+ * @param {Event=} e
+ */
+ showSpeedToggle(e) {
+ const isFocusEvent = e && e.type == 'focus';
+ if (Runner.audioCues || isFocusEvent) {
+ this.slowSpeedCheckboxLabel.classList.toggle(
+ HIDDEN_CLASS, isFocusEvent ? false : !this.crashed);
+ }
+ },
+
+ /**
+ * Disable the speed toggle.
+ * @param {boolean} disable
+ */
+ disableSpeedToggle(disable) {
+ if (disable) {
+ this.slowSpeedCheckbox.setAttribute('disabled', 'disabled');
+ } else {
+ this.slowSpeedCheckbox.removeAttribute('disabled');
+ }
+ },
+
+ /**
* Bind relevant key / mouse / touch listeners.
*/
startListening() {
// A11y keyboard / screen reader activation.
this.containerEl.addEventListener(
Runner.events.KEYDOWN, this.handleCanvasKeyPress.bind(this));
+ if (!IS_MOBILE) {
+ this.containerEl.addEventListener(
+ Runner.events.FOCUS, this.showSpeedToggle.bind(this));
+ }
this.canvas.addEventListener(
Runner.events.KEYDOWN, this.preventScrolling.bind(this));
this.canvas.addEventListener(
@@ -886,6 +979,12 @@ Runner.prototype = {
}
if (this.isCanvasInView()) {
+ // Allow toggling of speed toggle.
+ if (Runner.keycodes.JUMP[e.keyCode] &&
+ e.target == this.slowSpeedCheckbox) {
+ return;
+ }
+
if (!this.crashed && !this.paused) {
// For a11y, screen reader activation.
const isMobileMouseInput = IS_MOBILE &&
@@ -937,11 +1036,6 @@ Runner.prototype = {
this.tRex.setDuck(true);
}
}
- // iOS only triggers touchstart and no pointer events.
- } else if (
- IS_IOS && this.crashed && e.type === Runner.events.TOUCHSTART &&
- e.currentTarget === this.containerEl) {
- this.handleGameOverClicks(e);
}
}
},
@@ -1072,19 +1166,21 @@ Runner.prototype = {
* @param {Event} e
*/
handleGameOverClicks(e) {
- e.preventDefault();
- if (this.distanceMeter.hasClickedOnHighScore(e) && this.highestScore) {
- if (this.distanceMeter.isHighScoreFlashing()) {
- // Subsequent click, reset the high score.
- this.saveHighScore(0, true);
- this.distanceMeter.resetHighScore();
+ if (e.target != this.slowSpeedCheckbox) {
+ e.preventDefault();
+ if (this.distanceMeter.hasClickedOnHighScore(e) && this.highestScore) {
+ if (this.distanceMeter.isHighScoreFlashing()) {
+ // Subsequent click, reset the high score.
+ this.saveHighScore(0, true);
+ this.distanceMeter.resetHighScore();
+ } else {
+ // First click, flash the high score.
+ this.distanceMeter.startHighScoreFlashing();
+ }
} else {
- // First click, flash the high score.
- this.distanceMeter.startHighScoreFlashing();
+ this.distanceMeter.cancelHighScoreFlashing();
+ this.restart();
}
- } else {
- this.distanceMeter.cancelHighScoreFlashing();
- this.restart();
}
},
@@ -1214,6 +1310,8 @@ Runner.prototype = {
this.distanceMeter.getActualDistance(this.highestScore)
.toString()));
}
+ this.showSpeedToggle();
+ this.disableSpeedToggle(false);
},
stop() {
@@ -1240,6 +1338,7 @@ Runner.prototype = {
this.playCount++;
this.runningTime = 0;
this.setPlayStatus(true);
+ this.toggleSpeed();
this.paused = false;
this.crashed = false;
this.distanceRan = 0;
@@ -1531,8 +1630,8 @@ GeneratedSoundFx.prototype = {
jump() {
if (this.audioCues) {
const now = this.context.currentTime;
- this.playNote(659.25, now, 0.116, null, -0.6);
- this.playNote(880, now + 0.116, 0.232, null, -0.6);
+ this.playNote(659.25, now, 0.116, 0.3, -0.6);
+ this.playNote(880, now + 0.116, 0.232, 0.3, -0.6);
}
},
};
@@ -2089,7 +2188,7 @@ function Obstacle(
this.canvasCtx = canvasCtx;
this.spritePos = spriteImgPos;
this.typeConfig = type;
- this.gapCoefficient = gapCoefficient;
+ this.gapCoefficient = Runner.slowDown ? gapCoefficient * 2 : gapCoefficient;
this.size = getRandomNum(1, Obstacle.MAX_OBSTACLE_LENGTH);
this.dimensions = dimensions;
this.remove = false;
@@ -2296,7 +2395,7 @@ function Trex(canvas, spritePos) {
this.animStartTime = 0;
this.timer = 0;
this.msPerFrame = 1000 / FPS;
- this.config = Trex.config;
+ this.config = Object.assign(Trex.config, Trex.normalJumpConfig);
// Current status.
this.status = Trex.status.WAITING;
this.jumping = false;
@@ -2320,13 +2419,9 @@ Trex.config = {
DROP_VELOCITY: -5,
FLASH_OFF: 175,
FLASH_ON: 100,
- GRAVITY: 0.6,
HEIGHT: 47,
HEIGHT_DUCK: 25,
- INITIAL_JUMP_VELOCITY: -10,
INTRO_DURATION: 1500,
- MAX_JUMP_HEIGHT: 30,
- MIN_JUMP_HEIGHT: 30,
SPEED_DROP_COEFFICIENT: 3,
SPRITE_WIDTH: 262,
START_X_POS: 50,
@@ -2334,22 +2429,30 @@ Trex.config = {
WIDTH_DUCK: 59
};
+Trex.slowJumpConfig = {
+ GRAVITY: 0.25,
+ MAX_JUMP_HEIGHT: 50,
+ MIN_JUMP_HEIGHT: 45,
+ INITIAL_JUMP_VELOCITY: -20,
+};
+
+Trex.normalJumpConfig = {
+ GRAVITY: 0.6,
+ MAX_JUMP_HEIGHT: 30,
+ MIN_JUMP_HEIGHT: 30,
+ INITIAL_JUMP_VELOCITY: -10,
+};
/**
* Used in collision detection.
* @enum {Array<CollisionBox>}
*/
Trex.collisionBoxes = {
- DUCKING: [
- new CollisionBox(1, 18, 55, 25)
- ],
+ DUCKING: [new CollisionBox(1, 18, 55, 25)],
RUNNING: [
- new CollisionBox(22, 0, 17, 16),
- new CollisionBox(1, 18, 30, 9),
- new CollisionBox(10, 35, 14, 8),
- new CollisionBox(1, 24, 29, 5),
- new CollisionBox(5, 30, 21, 4),
- new CollisionBox(9, 34, 15, 4)
+ new CollisionBox(22, 0, 17, 16), new CollisionBox(1, 18, 30, 9),
+ new CollisionBox(10, 35, 14, 8), new CollisionBox(1, 24, 29, 5),
+ new CollisionBox(5, 30, 21, 4), new CollisionBox(9, 34, 15, 4)
]
};
@@ -2416,6 +2519,16 @@ Trex.prototype = {
this.update(0, Trex.status.WAITING);
},
+ /**
+ * Assign the appropriate jump parameters based on the game speed.
+ */
+ enableSlowConfig: function() {
+ const jumpConfig =
+ Runner.slowDown ? Trex.slowJumpConfig : Trex.normalJumpConfig;
+ Trex.config = Object.assign(Trex.config, jumpConfig);
+
+ this.adjustAltGameConfigForSlowSpeed();
+ },
/**
* Enables the alternative game. Redefines the dino config.
@@ -2450,6 +2563,7 @@ Trex.prototype = {
Trex.config.WIDTH_JUMP = spriteDefinition.JUMPING.w;
Trex.config.INVERT_JUMP = spriteDefinition.INVERT_JUMP;
+ this.adjustAltGameConfigForSlowSpeed(spriteDefinition.GRAVITY);
this.config = Trex.config;
// Adjust bottom horizon placement.
@@ -2460,6 +2574,22 @@ Trex.prototype = {
},
/**
+ * Slow speeds adjustments for the alt game modes.
+ * @param {number=} opt_gravityValue
+ */
+ adjustAltGameConfigForSlowSpeed: function(opt_gravityValue) {
+ if (Runner.slowDown) {
+ if (opt_gravityValue) {
+ Trex.config.GRAVITY = opt_gravityValue / 1.5;
+ }
+ Trex.config.MIN_JUMP_HEIGHT *= 1.5;
+ Trex.config.MAX_JUMP_HEIGHT *= 1.5;
+ Trex.config.INITIAL_JUMP_VELOCITY =
+ Trex.config.INITIAL_JUMP_VELOCITY * 1.5;
+ }
+ },
+
+ /**
* Setter whether dino is flashing.
* @param {boolean} status
*/
@@ -3739,6 +3869,25 @@ Horizon.prototype = {
},
/**
+ * Update obstacle definitions based on the speed of the game.
+ */
+ adjustObstacleSpeed: function() {
+ for (let i = 0; i < Obstacle.types.length; i++) {
+ if (Runner.slowDown) {
+ Obstacle.types[i].multipleSpeed = Obstacle.types[i].multipleSpeed / 2;
+ Obstacle.types[i].minGap *= 1.5;
+ Obstacle.types[i].minSpeed = Obstacle.types[i].minSpeed / 2;
+
+ // Convert variable y position obstacles to fixed.
+ if (typeof (Obstacle.types[i].yPos) == 'object') {
+ Obstacle.types[i].yPos = Obstacle.types[i].yPos[0];
+ Obstacle.types[i].yPosMobile = Obstacle.types[i].yPos[0];
+ }
+ }
+ }
+ },
+
+ /**
* Update sprites to correspond to change in sprite sheet.
* @param {number} spritePos
*/
@@ -3751,6 +3900,8 @@ Horizon.prototype = {
this.spritePos = spritePos;
Obstacle.types = Runner.spriteDefinition.OBSTACLES;
+ this.adjustObstacleSpeed();
+
Obstacle.MAX_GAP_COEFFICIENT = Runner.spriteDefinition.MAX_GAP_COEFFICIENT;
Obstacle.MAX_OBSTACLE_LENGTH = Runner.spriteDefinition.MAX_OBSTACLE_LENGTH;
diff --git a/chromium/components/network_hints/browser/simple_network_hints_handler_impl.cc b/chromium/components/network_hints/browser/simple_network_hints_handler_impl.cc
index 4bbb7c97e44..7ea39e3a442 100644
--- a/chromium/components/network_hints/browser/simple_network_hints_handler_impl.cc
+++ b/chromium/components/network_hints/browser/simple_network_hints_handler_impl.cc
@@ -66,7 +66,7 @@ class DnsLookupRequest : public network::ResolveHostClientBase {
content::RenderFrameHost::FromID(render_process_id_, render_frame_id_);
if (!render_frame_host) {
OnComplete(net::ERR_NAME_NOT_RESOLVED,
- net::ResolveErrorInfo(net::ERR_FAILED), base::nullopt);
+ net::ResolveErrorInfo(net::ERR_FAILED), absl::nullopt);
return;
}
@@ -90,7 +90,7 @@ class DnsLookupRequest : public network::ResolveHostClientBase {
receiver_.set_disconnect_handler(
base::BindOnce(&DnsLookupRequest::OnComplete, base::Unretained(this),
net::ERR_NAME_NOT_RESOLVED,
- net::ResolveErrorInfo(net::ERR_FAILED), base::nullopt));
+ net::ResolveErrorInfo(net::ERR_FAILED), absl::nullopt));
}
private:
@@ -98,7 +98,7 @@ class DnsLookupRequest : public network::ResolveHostClientBase {
void OnComplete(
int result,
const net::ResolveErrorInfo& resolve_error_info,
- const base::Optional<net::AddressList>& resolved_addresses) override {
+ const absl::optional<net::AddressList>& resolved_addresses) override {
VLOG(2) << __FUNCTION__ << ": " << hostname_
<< ", result=" << resolve_error_info.error;
request_.reset();
diff --git a/chromium/components/network_session_configurator/OWNERS b/chromium/components/network_session_configurator/OWNERS
index 2aaabd09fe4..0013c68577c 100644
--- a/chromium/components/network_session_configurator/OWNERS
+++ b/chromium/components/network_session_configurator/OWNERS
@@ -1,3 +1,5 @@
bnc@chromium.org
+rch@chromium.org
+
file://net/OWNERS
file://net/quic/OWNERS # For QUICHE rolls only.
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 d1e5910c9fa..573d054d3c4 100644
--- a/chromium/components/network_session_configurator/browser/network_session_configurator.cc
+++ b/chromium/components/network_session_configurator/browser/network_session_configurator.cc
@@ -150,7 +150,7 @@ void ConfigureHttp2Params(const base::CommandLine& command_line,
(length > 0) ? base::RandBytesAsString(length) : std::string();
params->greased_http2_frame =
- base::Optional<net::SpdySessionPool::GreasedHttp2Frame>(
+ absl::optional<net::SpdySessionPool::GreasedHttp2Frame>(
{type, flags, payload});
}
diff --git a/chromium/components/network_session_configurator/common/network_session_configurator_export.h b/chromium/components/network_session_configurator/common/network_session_configurator_export.h
index d4a224d270f..d24f7a8f0d6 100644
--- a/chromium/components/network_session_configurator/common/network_session_configurator_export.h
+++ b/chromium/components/network_session_configurator/common/network_session_configurator_export.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_NETWORK_SESSION_CONFIGURATOR_NETWORK_SESSION_CONFIGURATOR_EXPORT_H_
-#define COMPONENTS_NETWORK_SESSION_CONFIGURATOR_NETWORK_SESSION_CONFIGURATOR_EXPORT_H_
+#ifndef COMPONENTS_NETWORK_SESSION_CONFIGURATOR_COMMON_NETWORK_SESSION_CONFIGURATOR_EXPORT_H_
+#define COMPONENTS_NETWORK_SESSION_CONFIGURATOR_COMMON_NETWORK_SESSION_CONFIGURATOR_EXPORT_H_
#if defined(COMPONENT_BUILD)
@@ -32,4 +32,4 @@
#endif // defined(COMPONENT_BUILD)
-#endif // COMPONENTS_NETWORK_SESSION_CONFIGURATOR_NETWORK_SESSION_CONFIGURATOR_EXPORT_H_
+#endif // COMPONENTS_NETWORK_SESSION_CONFIGURATOR_COMMON_NETWORK_SESSION_CONFIGURATOR_EXPORT_H_
diff --git a/chromium/components/network_time/network_time_test_utils.cc b/chromium/components/network_time/network_time_test_utils.cc
index 2053990c1a6..87b7890cc42 100644
--- a/chromium/components/network_time/network_time_test_utils.cc
+++ b/chromium/components/network_time/network_time_test_utils.cc
@@ -15,27 +15,27 @@ namespace network_time {
// Update as follows:
//
-// curl -i http://clients2.google.com/time/1/current?cup2key=4:123123123
+// curl -i http://clients2.google.com/time/1/current?cup2key=5:123123123
//
-// where 4 is the key version and 123123123 is the nonce. Copy the response
+// where 5 is the key version and 123123123 is the nonce. Copy the response
// and the x-cup-server-proof header into |kGoodTimeResponseBody| and
// |kGoodTimeResponseServerProofHeader| respectively, and the
// 'current_time_millis' value of the response into
// |kGoodTimeResponseHandlerJsTime|. Do this twice, so that the two requests
// appear in order below.
const char* kGoodTimeResponseBody[] = {
- ")]}'\n{\"current_time_millis\":1583777597124,"
- "\"server_nonce\":-1.2173462458909911E256}",
- ")]}'\n{\"current_time_millis\":1583777940456,"
- "\"server_nonce\":1.0627453636135456E-51}"};
+ ")]}'\n{\"current_time_millis\":1619464140565,"
+ "\"server_nonce\":-1.656679479914492E230}",
+ ")]}'\n{\"current_time_millis\":1619464273366,"
+ "\"server_nonce\":2.1195306862817135E-5}"};
const char* kGoodTimeResponseServerProofHeader[] = {
- "3045022100f486431d9e9c8d4b7bef1eb9505eefef326bda6e903615543ed934b7741f4609"
- "022019d3edc1b14f7dd404cbe42e70c813d2351468b4fbefdbde101494d4f02d1b9d:"
+ "3045022100f829ced2af34ade53400f66eef6df9af732fa8bfe08517287c2805c92891e321"
+ "022062fb405b2cf12bc3e2ac037985c4b8065a62e86e29a2e745ebff80fd52189c6a:"
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
- "3045022100c98cb7288bcd56d4bcb83aefc3c137dfc77bbbd9b793155b28af02df51fb2074"
- "022022f1436e92febeccefab5dfadbe61ca2dc92447b63426a573fcf6419cfbfdba7:"
+ "3046022100c78436ad47904634aacd33f4c4bcb55bd6f7f2ed84a620fda0deaede99c32de6"
+ "022100b595458bd03d83f33bfb891de1327b26620d576937f3713af59bb1f2c53f2e8b:"
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"};
-const double kGoodTimeResponseHandlerJsTime[] = {1583777597124, 1583777940456};
+const double kGoodTimeResponseHandlerJsTime[] = {1619464140565, 1619464273366};
std::unique_ptr<net::test_server::HttpResponse> GoodTimeResponseHandler(
const net::test_server::HttpRequest& request) {
diff --git a/chromium/components/network_time/network_time_tracker.cc b/chromium/components/network_time/network_time_tracker.cc
index d202a31d180..3feec29256c 100644
--- a/chromium/components/network_time/network_time_tracker.cc
+++ b/chromium/components/network_time/network_time_tracker.cc
@@ -125,16 +125,16 @@ const char kVariationsServiceRandomQueryProbability[] =
const char kVariationsServiceFetchBehavior[] = "FetchBehavior";
// This is an ECDSA prime256v1 named-curve key.
-const int kKeyVersion = 4;
+const int kKeyVersion = 5;
const uint8_t kKeyPubBytes[] = {
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
- 0x42, 0x00, 0x04, 0x6E, 0xF3, 0xC6, 0x54, 0xA9, 0x86, 0x09, 0xF1, 0x1C,
- 0xEE, 0x7B, 0x9D, 0x33, 0xA6, 0x04, 0x8C, 0x44, 0xA2, 0xF7, 0x8C, 0x2D,
- 0x62, 0x35, 0xB3, 0x67, 0x6F, 0x1D, 0x38, 0x66, 0xF3, 0xBB, 0xAB, 0x0D,
- 0x6C, 0xCE, 0x93, 0x30, 0x73, 0xBB, 0x33, 0x1D, 0x94, 0xF1, 0xB5, 0xE9,
- 0x37, 0x13, 0xD9, 0xB2, 0x64, 0x37, 0x89, 0xD0, 0xE2, 0x49, 0xE3, 0x4B,
- 0x34, 0x0F, 0x81, 0x8E, 0x5C, 0xA8, 0x61};
+ 0x42, 0x00, 0x04, 0xE4, 0xA5, 0xA5, 0xA1, 0x99, 0x27, 0x83, 0x2B, 0x93,
+ 0xF6, 0x30, 0xA6, 0x87, 0x78, 0x62, 0xB1, 0x81, 0x72, 0xD1, 0xA0, 0xB0,
+ 0xFD, 0x48, 0x5F, 0x29, 0x60, 0x9C, 0x96, 0xC5, 0x10, 0xE3, 0x42, 0x43,
+ 0x61, 0xB9, 0xDA, 0xEC, 0x30, 0xA8, 0x22, 0xA8, 0x69, 0xF7, 0x1F, 0x17,
+ 0x5D, 0x83, 0xF7, 0xFD, 0xAE, 0x41, 0xDB, 0x31, 0x40, 0xAF, 0xA2, 0x32,
+ 0xAE, 0x68, 0xFE, 0xD1, 0x6B, 0xB4, 0xB0};
std::string GetServerProof(
scoped_refptr<net::HttpResponseHeaders> response_headers) {
diff --git a/chromium/components/network_time/network_time_tracker_unittest.cc b/chromium/components/network_time/network_time_tracker_unittest.cc
index 0a193a1703f..e46af1d12cc 100644
--- a/chromium/components/network_time/network_time_tracker_unittest.cc
+++ b/chromium/components/network_time/network_time_tracker_unittest.cc
@@ -12,7 +12,6 @@
#include "base/compiler_specific.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_clock.h"
#include "base/test/simple_test_tick_clock.h"
diff --git a/chromium/components/new_or_sad_tab_strings.grdp b/chromium/components/new_or_sad_tab_strings.grdp
index f2e71538cd7..43ce1b8f181 100644
--- a/chromium/components/new_or_sad_tab_strings.grdp
+++ b/chromium/components/new_or_sad_tab_strings.grdp
@@ -120,11 +120,11 @@
<if expr="not is_android">
<message name="IDS_NEW_TAB_OTR_HEADING"
desc="Heading used when a person opens an OTR window">
- You’ve gone incognito
+ You’ve gone Incognito
</message>
<message name="IDS_NEW_TAB_OTR_DESCRIPTION"
desc="Used when a person opens an OTR window">
- Pages you view in incognito tabs won’t stick around in your browser’s history, cookie store, or search history after you’ve closed all of your incognito tabs. Any files you download or bookmarks you create will be kept.
+ Pages you view in Incognito tabs won’t stick around in your browser’s history, cookie store, or search history after you’ve closed all of your Incognito tabs. Any files you download or bookmarks you create will be kept.
</message>
<message name="IDS_NEW_TAB_OTR_LEARN_MORE_LINK"
desc="OTR window link text to learn more">
@@ -132,7 +132,7 @@
</message>
<message name="IDS_NEW_TAB_OTR_MESSAGE_WARNING"
desc="OTR window warning message. This follows the IDS_NEW_TAB_OTR_DESCRIPTION paragraph">
- However, you aren’t invisible. Going incognito doesn’t hide your browsing from your employer, your internet service provider, or the websites you visit.
+ However, you aren’t invisible. Going Incognito doesn’t hide your browsing from your employer, your internet service provider, or the websites you visit.
</message>
</if>
<message name="IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE"
@@ -144,7 +144,7 @@
<!-- TODO(msramek): Merge with the above section once this is fully launched. -->
<message name="IDS_NEW_TAB_OTR_TITLE" desc="Title of the Incognito new tab page. The Incognito mode provides private browsing experience by hiding browsing activity from other people using the same device. However, it does not make the user completely invisible or anonymous; please don't translate it as such." formatter_data="android_java">
- You’ve gone incognito
+ You’ve gone Incognito
</message>
<message name="IDS_NEW_TAB_OTR_SUBTITLE" desc="Subtitle of the Incognito new tab page, explaining to the user that the Incognito mode hides their browsing activity from other people using the same device. The second sentence clarifies that there are two important exceptions from this rule - downloaded files and added bookmarks will be persisted even after the Incognito session is closed." formatter_data="android_java">
Now you can browse privately, and other people who use this device won’t see your activity. However, downloads and bookmarks will be saved.
diff --git a/chromium/components/no_state_prefetch/browser/BUILD.gn b/chromium/components/no_state_prefetch/browser/BUILD.gn
index 88010bdfbe8..f997d130254 100644
--- a/chromium/components/no_state_prefetch/browser/BUILD.gn
+++ b/chromium/components/no_state_prefetch/browser/BUILD.gn
@@ -21,14 +21,14 @@ static_library("browser") {
"no_state_prefetch_processor_impl.cc",
"no_state_prefetch_processor_impl.h",
"no_state_prefetch_processor_impl_delegate.h",
+ "no_state_prefetch_utils.cc",
+ "no_state_prefetch_utils.h",
"prerender_config.cc",
"prerender_config.h",
"prerender_histograms.cc",
"prerender_histograms.h",
"prerender_history.cc",
"prerender_history.h",
- "prerender_util.cc",
- "prerender_util.h",
]
deps = [
@@ -54,8 +54,8 @@ source_set("unit_tests") {
testonly = true
sources = [
"no_state_prefetch_processor_impl_unittest.cc",
+ "no_state_prefetch_utils_unittest.cc",
"prerender_history_unittest.cc",
- "prerender_util_unittest.cc",
]
deps = [
diff --git a/chromium/components/no_state_prefetch/browser/no_state_prefetch_contents.cc b/chromium/components/no_state_prefetch/browser/no_state_prefetch_contents.cc
index d3addeaaa8b..dcccaf0be92 100644
--- a/chromium/components/no_state_prefetch/browser/no_state_prefetch_contents.cc
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_contents.cc
@@ -17,8 +17,8 @@
#include "build/build_config.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_contents_delegate.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
+#include "components/no_state_prefetch/common/no_state_prefetch_utils.h"
#include "components/no_state_prefetch/common/prerender_final_status.h"
-#include "components/no_state_prefetch/common/prerender_util.h"
#include "components/no_state_prefetch/common/render_frame_prerender_messages.mojom.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
@@ -55,7 +55,7 @@ class NoStatePrefetchContentsFactoryImpl
content::BrowserContext* browser_context,
const GURL& url,
const content::Referrer& referrer,
- const base::Optional<url::Origin>& initiator_origin,
+ const absl::optional<url::Origin>& initiator_origin,
Origin origin) override {
return new NoStatePrefetchContents(
std::move(delegate), no_state_prefetch_manager, browser_context, url,
@@ -127,7 +127,7 @@ NoStatePrefetchContents::NoStatePrefetchContents(
content::BrowserContext* browser_context,
const GURL& url,
const content::Referrer& referrer,
- const base::Optional<url::Origin>& initiator_origin,
+ const absl::optional<url::Origin>& initiator_origin,
Origin origin)
: prerendering_has_started_(false),
no_state_prefetch_manager_(no_state_prefetch_manager),
@@ -155,6 +155,7 @@ NoStatePrefetchContents::NoStatePrefetchContents(
case ORIGIN_LINK_REL_PRERENDER_SAMEDOMAIN:
case ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN:
case ORIGIN_LINK_REL_NEXT:
+ case ORIGIN_SAME_ORIGIN_SPECULATION:
DCHECK(initiator_origin_.has_value());
break;
case ORIGIN_NONE:
@@ -245,12 +246,12 @@ NoStatePrefetchContents::~NoStatePrefetchContents() {
no_state_prefetch_manager_->RecordNetworkBytesConsumed(origin(),
network_bytes_);
- if (!no_state_prefetch_contents_)
- return;
-
- // If we still have a WebContents, clean up anything we need to and then
- // destroy it.
- std::unique_ptr<WebContents> contents = ReleaseNoStatePrefetchContents();
+ if (no_state_prefetch_contents_) {
+ no_state_prefetch_contents_->SetDelegate(nullptr);
+ content::WebContentsObserver::Observe(nullptr);
+ delegate_->ReleaseNoStatePrefetchContents(
+ no_state_prefetch_contents_.get());
+ }
}
void NoStatePrefetchContents::AddObserver(Observer* observer) {
@@ -452,13 +453,11 @@ void NoStatePrefetchContents::DestroyWhenUsingTooManyResources() {
if (process_pid_ == base::kNullProcessId)
return;
- // Using AdaptCallbackForRepeating allows for an easier transition to
- // OnceCallbacks for https://crbug.com/714018.
memory_instrumentation::MemoryInstrumentation::GetInstance()
->RequestPrivateMemoryFootprint(
- process_pid_, base::AdaptCallbackForRepeating(base::BindOnce(
- &NoStatePrefetchContents::DidGetMemoryUsage,
- weak_factory_.GetWeakPtr())));
+ process_pid_,
+ base::BindOnce(&NoStatePrefetchContents::DidGetMemoryUsage,
+ weak_factory_.GetWeakPtr()));
}
void NoStatePrefetchContents::DidGetMemoryUsage(
@@ -483,16 +482,6 @@ void NoStatePrefetchContents::DidGetMemoryUsage(
}
}
-std::unique_ptr<WebContents>
-NoStatePrefetchContents::ReleaseNoStatePrefetchContents() {
- no_state_prefetch_contents_->SetDelegate(nullptr);
- content::WebContentsObserver::Observe(nullptr);
-
- delegate_->ReleaseNoStatePrefetchContents(no_state_prefetch_contents_.get());
-
- return std::move(no_state_prefetch_contents_);
-}
-
RenderFrameHost* NoStatePrefetchContents::GetMainFrame() {
return no_state_prefetch_contents_
? no_state_prefetch_contents_->GetMainFrame()
diff --git a/chromium/components/no_state_prefetch/browser/no_state_prefetch_contents.h b/chromium/components/no_state_prefetch/browser/no_state_prefetch_contents.h
index 0695ac93ce9..7755e707ebf 100644
--- a/chromium/components/no_state_prefetch/browser/no_state_prefetch_contents.h
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_contents.h
@@ -15,7 +15,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_contents_delegate.h"
@@ -25,6 +24,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/referrer.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "url/origin.h"
@@ -66,7 +66,7 @@ class NoStatePrefetchContents : public content::WebContentsObserver,
content::BrowserContext* browser_context,
const GURL& url,
const content::Referrer& referrer,
- const base::Optional<url::Origin>& initiator_origin,
+ const absl::optional<url::Origin>& initiator_origin,
Origin origin) = 0;
private:
@@ -170,8 +170,6 @@ class NoStatePrefetchContents : public content::WebContentsObserver,
return no_state_prefetch_contents_.get();
}
- std::unique_ptr<content::WebContents> ReleaseNoStatePrefetchContents();
-
// Sets the final status, calls OnDestroy and adds |this| to the
// NoStatePrefetchManager's pending deletes list.
void Destroy(FinalStatus reason);
@@ -203,7 +201,7 @@ class NoStatePrefetchContents : public content::WebContentsObserver,
content::BrowserContext* browser_context,
const GURL& url,
const content::Referrer& referrer,
- const base::Optional<url::Origin>& initiator_origin,
+ const absl::optional<url::Origin>& initiator_origin,
Origin origin);
// Set the final status for how the NoStatePrefetchContents was used. This
@@ -269,7 +267,7 @@ class NoStatePrefetchContents : public content::WebContentsObserver,
// The origin of the page requesting the prerender. Empty when the prerender
// is browser initiated.
- const base::Optional<url::Origin> initiator_origin_;
+ const absl::optional<url::Origin> initiator_origin_;
// The browser context being used
content::BrowserContext* browser_context_;
diff --git a/chromium/components/no_state_prefetch/browser/no_state_prefetch_handle.h b/chromium/components/no_state_prefetch/browser/no_state_prefetch_handle.h
index 19d26f1eb89..dc5c9d8bd87 100644
--- a/chromium/components/no_state_prefetch/browser/no_state_prefetch_handle.h
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_handle.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_NO_STATE_PREFETCH_BROWSER_NO_STATE_PREFETCH_HANDLE_H_
#define COMPONENTS_NO_STATE_PREFETCH_BROWSER_NO_STATE_PREFETCH_HANDLE_H_
-#include <memory>
-
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
diff --git a/chromium/components/no_state_prefetch/browser/no_state_prefetch_link_manager.cc b/chromium/components/no_state_prefetch/browser/no_state_prefetch_link_manager.cc
index da486ab8a43..ba34ef363da 100644
--- a/chromium/components/no_state_prefetch/browser/no_state_prefetch_link_manager.cc
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_link_manager.cc
@@ -58,7 +58,7 @@ NoStatePrefetchLinkManager::LinkTrigger::LinkTrigger(
: launcher_render_process_id(launcher_render_process_id),
launcher_render_view_id(launcher_render_view_id),
url(attributes->url),
- rel_type(attributes->rel_type),
+ trigger_type(attributes->trigger_type),
referrer(content::Referrer(*attributes->referrer)),
initiator_origin(initiator_origin),
size(attributes->view_size),
@@ -87,7 +87,7 @@ NoStatePrefetchLinkManager::~NoStatePrefetchLinkManager() {
}
}
-base::Optional<int> NoStatePrefetchLinkManager::OnStartLinkTrigger(
+absl::optional<int> NoStatePrefetchLinkManager::OnStartLinkTrigger(
int launcher_render_process_id,
int launcher_render_view_id,
blink::mojom::PrerenderAttributesPtr attributes,
@@ -101,7 +101,7 @@ base::Optional<int> NoStatePrefetchLinkManager::OnStartLinkTrigger(
// Guests inside <webview> do not support cross-process navigation and so we
// do not allow guests to prerender content.
if (guest_view::GuestViewBase::IsGuest(web_contents))
- return base::nullopt;
+ return absl::nullopt;
#endif
// Check if the launcher is itself an unswapped prerender.
@@ -113,7 +113,7 @@ base::Optional<int> NoStatePrefetchLinkManager::OnStartLinkTrigger(
// The launcher is a prerender about to be destroyed asynchronously, but
// its AddLinkRelPrerender message raced with shutdown. Ignore it.
DCHECK_NE(FINAL_STATUS_USED, no_state_prefetch_contents->final_status());
- return base::nullopt;
+ return absl::nullopt;
}
auto trigger = std::make_unique<LinkTrigger>(
@@ -133,7 +133,7 @@ base::Optional<int> NoStatePrefetchLinkManager::OnStartLinkTrigger(
// may have been discarded by StartLinkTriggers().
if (!triggers_.empty() && triggers_.back().get() == trigger_ptr)
return trigger_ptr->link_trigger_id;
- return base::nullopt;
+ return absl::nullopt;
}
void NoStatePrefetchLinkManager::OnCancelLinkTrigger(int link_trigger_id) {
@@ -265,7 +265,7 @@ void NoStatePrefetchLinkManager::StartLinkTriggers() {
manager_->AddPrerenderFromLinkRelPrerender(
pending_trigger->launcher_render_process_id,
pending_trigger->launcher_render_view_id, pending_trigger->url,
- pending_trigger->rel_type, pending_trigger->referrer,
+ pending_trigger->trigger_type, pending_trigger->referrer,
pending_trigger->initiator_origin, pending_trigger->size);
if (!handle) {
// This trigger couldn't be launched, it's gone.
diff --git a/chromium/components/no_state_prefetch/browser/no_state_prefetch_link_manager.h b/chromium/components/no_state_prefetch/browser/no_state_prefetch_link_manager.h
index 6786f158126..ce29a4c158c 100644
--- a/chromium/components/no_state_prefetch/browser/no_state_prefetch_link_manager.h
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_link_manager.h
@@ -13,10 +13,10 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_handle.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -39,8 +39,8 @@ class NoStatePrefetchLinkManager : public KeyedService,
// Called when a <link rel=prerender ...> element has been inserted into the
// document. Returns the link trigger id that is used for canceling or
- // abandoning prefetch. Returns base::nullopt if the prefetch was not started.
- virtual base::Optional<int> OnStartLinkTrigger(
+ // abandoning prefetch. Returns absl::nullopt if the prefetch was not started.
+ virtual absl::optional<int> OnStartLinkTrigger(
int launcher_render_process_id,
int launcher_render_view_id,
blink::mojom::PrerenderAttributesPtr attributes,
@@ -80,7 +80,7 @@ class NoStatePrefetchLinkManager : public KeyedService,
const int launcher_render_process_id;
const int launcher_render_view_id;
const GURL url;
- const blink::mojom::PrerenderRelType rel_type;
+ const blink::mojom::PrerenderTriggerType trigger_type;
const content::Referrer referrer;
const url::Origin initiator_origin;
const gfx::Size size;
diff --git a/chromium/components/no_state_prefetch/browser/no_state_prefetch_manager.cc b/chromium/components/no_state_prefetch/browser/no_state_prefetch_manager.cc
index 9c4408c9a4e..b3085b80a98 100644
--- a/chromium/components/no_state_prefetch/browser/no_state_prefetch_manager.cc
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_manager.cc
@@ -37,9 +37,9 @@
#include "components/no_state_prefetch/browser/no_state_prefetch_field_trial.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_handle.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_manager_delegate.h"
+#include "components/no_state_prefetch/browser/no_state_prefetch_utils.h"
#include "components/no_state_prefetch/browser/prerender_histograms.h"
#include "components/no_state_prefetch/browser/prerender_history.h"
-#include "components/no_state_prefetch/browser/prerender_util.h"
#include "components/no_state_prefetch/common/prerender_final_status.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
@@ -168,16 +168,16 @@ NoStatePrefetchManager::AddPrerenderFromLinkRelPrerender(
int process_id,
int route_id,
const GURL& url,
- blink::mojom::PrerenderRelType rel_type,
+ blink::mojom::PrerenderTriggerType trigger_type,
const content::Referrer& referrer,
const url::Origin& initiator_origin,
const gfx::Size& size) {
Origin origin = ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN;
- switch (rel_type) {
- case blink::mojom::PrerenderRelType::kPrerender:
+ switch (trigger_type) {
+ case blink::mojom::PrerenderTriggerType::kLinkRelPrerender:
origin = ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN;
break;
- case blink::mojom::PrerenderRelType::kNext:
+ case blink::mojom::PrerenderTriggerType::kLinkRelNext:
origin = ORIGIN_LINK_REL_NEXT;
break;
}
@@ -212,7 +212,7 @@ NoStatePrefetchManager::AddPrerenderFromOmnibox(
SessionStorageNamespace* session_storage_namespace,
const gfx::Size& size) {
return AddPrerenderWithPreconnectFallback(
- ORIGIN_OMNIBOX, url, content::Referrer(), base::nullopt, gfx::Rect(size),
+ ORIGIN_OMNIBOX, url, content::Referrer(), absl::nullopt, gfx::Rect(size),
session_storage_namespace);
}
@@ -222,7 +222,7 @@ NoStatePrefetchManager::AddPrerenderFromNavigationPredictor(
SessionStorageNamespace* session_storage_namespace,
const gfx::Size& size) {
return AddPrerenderWithPreconnectFallback(
- ORIGIN_NAVIGATION_PREDICTOR, url, content::Referrer(), base::nullopt,
+ ORIGIN_NAVIGATION_PREDICTOR, url, content::Referrer(), absl::nullopt,
gfx::Rect(size), session_storage_namespace);
}
@@ -233,18 +233,30 @@ NoStatePrefetchManager::AddIsolatedPrerender(
const gfx::Size& size) {
// The preconnect fallback won't happen.
return AddPrerenderWithPreconnectFallback(
- ORIGIN_ISOLATED_PRERENDER, url, content::Referrer(), base::nullopt,
+ ORIGIN_ISOLATED_PRERENDER, url, content::Referrer(), absl::nullopt,
gfx::Rect(size), session_storage_namespace);
}
std::unique_ptr<NoStatePrefetchHandle>
+NoStatePrefetchManager::AddSameOriginSpeculation(
+ const GURL& url,
+ content::SessionStorageNamespace* session_storage_namespace,
+ const gfx::Size& size,
+ const url::Origin& initiator_origin) {
+ // The preconnect fallback won't happen.
+ return AddPrerenderWithPreconnectFallback(
+ ORIGIN_SAME_ORIGIN_SPECULATION, url, content::Referrer(),
+ initiator_origin, gfx::Rect(size), session_storage_namespace);
+}
+
+std::unique_ptr<NoStatePrefetchHandle>
NoStatePrefetchManager::AddPrerenderFromExternalRequest(
const GURL& url,
const content::Referrer& referrer,
SessionStorageNamespace* session_storage_namespace,
const gfx::Rect& bounds) {
return AddPrerenderWithPreconnectFallback(ORIGIN_EXTERNAL_REQUEST, url,
- referrer, base::nullopt, bounds,
+ referrer, absl::nullopt, bounds,
session_storage_namespace);
}
@@ -255,7 +267,7 @@ NoStatePrefetchManager::AddForcedPrerenderFromExternalRequest(
SessionStorageNamespace* session_storage_namespace,
const gfx::Rect& bounds) {
return AddPrerenderWithPreconnectFallback(
- ORIGIN_EXTERNAL_REQUEST_FORCED_PRERENDER, url, referrer, base::nullopt,
+ ORIGIN_EXTERNAL_REQUEST_FORCED_PRERENDER, url, referrer, absl::nullopt,
bounds, session_storage_namespace);
}
@@ -268,6 +280,15 @@ void NoStatePrefetchManager::CancelAllPrerenders() {
}
}
+void NoStatePrefetchManager::DestroyAllContents(FinalStatus final_status) {
+ DeleteOldWebContents();
+ while (!active_prefetches_.empty()) {
+ NoStatePrefetchContents* contents = active_prefetches_.front()->contents();
+ contents->Destroy(final_status);
+ }
+ DeleteToDeletePrerenders();
+}
+
void NoStatePrefetchManager::MoveEntryToPendingDelete(
NoStatePrefetchContents* entry,
FinalStatus final_status) {
@@ -493,7 +514,7 @@ NoStatePrefetchManager::AddPrerenderWithPreconnectFallback(
Origin origin,
const GURL& url_arg,
const content::Referrer& referrer,
- const base::Optional<url::Origin>& initiator_origin,
+ const absl::optional<url::Origin>& initiator_origin,
const gfx::Rect& bounds,
SessionStorageNamespace* session_storage_namespace) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -760,7 +781,7 @@ std::unique_ptr<NoStatePrefetchContents>
NoStatePrefetchManager::CreateNoStatePrefetchContents(
const GURL& url,
const content::Referrer& referrer,
- const base::Optional<url::Origin>& initiator_origin,
+ const absl::optional<url::Origin>& initiator_origin,
Origin origin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return base::WrapUnique(
@@ -923,15 +944,6 @@ NoStatePrefetchManager::GetActivePrerendersAsValue() const {
return list_value;
}
-void NoStatePrefetchManager::DestroyAllContents(FinalStatus final_status) {
- DeleteOldWebContents();
- while (!active_prefetches_.empty()) {
- NoStatePrefetchContents* contents = active_prefetches_.front()->contents();
- contents->Destroy(final_status);
- }
- DeleteToDeletePrerenders();
-}
-
void NoStatePrefetchManager::SkipNoStatePrefetchContentsAndMaybePreconnect(
const GURL& url,
Origin origin,
@@ -940,9 +952,11 @@ void NoStatePrefetchManager::SkipNoStatePrefetchContentsAndMaybePreconnect(
prerender_history_->AddEntry(entry);
histograms_->RecordFinalStatus(origin, final_status);
- if (origin == ORIGIN_ISOLATED_PRERENDER) {
+ if (origin == ORIGIN_ISOLATED_PRERENDER ||
+ origin == ORIGIN_SAME_ORIGIN_SPECULATION) {
// Prefetch Proxy should not preconnect since that can't be done in a fully
- // isolated way.
+ // isolated way. Same origin speculation should already have an open
+ // connection.
return;
}
@@ -1009,7 +1023,7 @@ std::unique_ptr<NoStatePrefetchHandle>
NoStatePrefetchManager::AddPrerenderWithPreconnectFallbackForTesting(
Origin origin,
const GURL& url,
- const base::Optional<url::Origin>& initiator_origin) {
+ const absl::optional<url::Origin>& initiator_origin) {
return AddPrerenderWithPreconnectFallback(
origin, url, content::Referrer(), initiator_origin, gfx::Rect(), nullptr);
}
diff --git a/chromium/components/no_state_prefetch/browser/no_state_prefetch_manager.h b/chromium/components/no_state_prefetch/browser/no_state_prefetch_manager.h
index 72dbdbc7be2..c1b02dd61df 100644
--- a/chromium/components/no_state_prefetch/browser/no_state_prefetch_manager.h
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_manager.h
@@ -9,12 +9,10 @@
#include <memory>
#include <set>
-#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -26,6 +24,7 @@
#include "components/no_state_prefetch/common/prerender_final_status.h"
#include "components/no_state_prefetch/common/prerender_origin.h"
#include "content/public/browser/render_process_host_observer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -102,7 +101,7 @@ class NoStatePrefetchManager : public content::RenderProcessHostObserver,
int process_id,
int route_id,
const GURL& url,
- blink::mojom::PrerenderRelType rel_type,
+ blink::mojom::PrerenderTriggerType trigger_type,
const content::Referrer& referrer,
const url::Origin& initiator_origin,
const gfx::Size& size);
@@ -138,6 +137,14 @@ class NoStatePrefetchManager : public content::RenderProcessHostObserver,
content::SessionStorageNamespace* session_storage_namespace,
const gfx::Size& size);
+ // Adds a NoStatePrefetch that only allows for same origin requests (i.e.,
+ // requests that only redirect to the same origin).
+ std::unique_ptr<NoStatePrefetchHandle> AddSameOriginSpeculation(
+ const GURL& url,
+ content::SessionStorageNamespace* session_storage_namespace,
+ const gfx::Size& size,
+ const url::Origin& initiator_origin);
+
std::unique_ptr<NoStatePrefetchHandle> AddPrerenderFromExternalRequest(
const GURL& url,
const content::Referrer& referrer,
@@ -155,6 +162,11 @@ class NoStatePrefetchManager : public content::RenderProcessHostObserver,
// Cancels all active prerenders.
void CancelAllPrerenders();
+ // Destroys all pending prerenders using FinalStatus. Also deletes them as
+ // well as any swapped out WebContents queued for destruction.
+ // Used both on destruction, and when clearing the browsing history.
+ void DestroyAllContents(FinalStatus final_status);
+
// Moves a NoStatePrefetchContents to the pending delete list from the list of
// active prerenders when prerendering should be cancelled.
virtual void MoveEntryToPendingDelete(NoStatePrefetchContents* entry,
@@ -275,7 +287,7 @@ class NoStatePrefetchManager : public content::RenderProcessHostObserver,
AddPrerenderWithPreconnectFallbackForTesting(
Origin origin,
const GURL& url,
- const base::Optional<url::Origin>& initiator_origin);
+ const absl::optional<url::Origin>& initiator_origin);
protected:
class NoStatePrefetchData
@@ -376,7 +388,7 @@ class NoStatePrefetchManager : public content::RenderProcessHostObserver,
Origin origin,
const GURL& url,
const content::Referrer& referrer,
- const base::Optional<url::Origin>& initiator_origin,
+ const absl::optional<url::Origin>& initiator_origin,
const gfx::Rect& bounds,
content::SessionStorageNamespace* session_storage_namespace);
@@ -408,7 +420,7 @@ class NoStatePrefetchManager : public content::RenderProcessHostObserver,
CreateNoStatePrefetchContents(
const GURL& url,
const content::Referrer& referrer,
- const base::Optional<url::Origin>& initiator_origin,
+ const absl::optional<url::Origin>& initiator_origin,
Origin origin);
// Insures the |active_prefetches_| are sorted by increasing expiry time. Call
@@ -457,11 +469,6 @@ class NoStatePrefetchManager : public content::RenderProcessHostObserver,
// Returns a new Value representing the pages currently being prerendered.
std::unique_ptr<base::ListValue> GetActivePrerendersAsValue() const;
- // Destroys all pending prerenders using FinalStatus. Also deletes them as
- // well as any swapped out WebContents queued for destruction.
- // Used both on destruction, and when clearing the browsing history.
- void DestroyAllContents(FinalStatus final_status);
-
// Records the final status a prerender in the case that a
// NoStatePrefetchContents was never created, adds a PrerenderHistory entry,
// and may also initiate a preconnect to |url|.
diff --git a/chromium/components/no_state_prefetch/browser/no_state_prefetch_processor_impl.h b/chromium/components/no_state_prefetch/browser/no_state_prefetch_processor_impl.h
index efaf66dff86..7d27ad47087 100644
--- a/chromium/components/no_state_prefetch/browser/no_state_prefetch_processor_impl.h
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_processor_impl.h
@@ -54,7 +54,7 @@ class NoStatePrefetchProcessorImpl
// The ID of NoStatePrefetchLinkManager::LinkTrigger. Used for canceling or
// abandoning prefetch.
- base::Optional<int> link_trigger_id_;
+ absl::optional<int> link_trigger_id_;
mojo::Receiver<blink::mojom::NoStatePrefetchProcessor> receiver_{this};
};
diff --git a/chromium/components/no_state_prefetch/browser/no_state_prefetch_processor_impl_unittest.cc b/chromium/components/no_state_prefetch/browser/no_state_prefetch_processor_impl_unittest.cc
index 7b00ca5cc13..008b1d37755 100644
--- a/chromium/components/no_state_prefetch/browser/no_state_prefetch_processor_impl_unittest.cc
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_processor_impl_unittest.cc
@@ -20,7 +20,7 @@ class MockNoStatePrefetchLinkManager final : public NoStatePrefetchLinkManager {
MockNoStatePrefetchLinkManager()
: NoStatePrefetchLinkManager(/*manager=*/nullptr) {}
- base::Optional<int> OnStartLinkTrigger(
+ absl::optional<int> OnStartLinkTrigger(
int launcher_render_process_id,
int launcher_render_view_id,
blink::mojom::PrerenderAttributesPtr attributes,
diff --git a/chromium/components/no_state_prefetch/browser/prerender_util.cc b/chromium/components/no_state_prefetch/browser/no_state_prefetch_utils.cc
index bb5095b235a..01ae2502754 100644
--- a/chromium/components/no_state_prefetch/browser/prerender_util.cc
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_utils.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/no_state_prefetch/browser/prerender_util.h"
+#include "components/no_state_prefetch/browser/no_state_prefetch_utils.h"
#include "base/metrics/histogram_macros.h"
#include "components/google/core/common/google_util.h"
@@ -32,14 +32,14 @@ bool IsGoogleOriginURL(const GURL& origin_url) {
void RecordNoStatePrefetchMetrics(
content::NavigationHandle* navigation_handle,
ukm::SourceId source_id,
- prerender::NoStatePrefetchManager* no_state_prefetch_manager) {
+ NoStatePrefetchManager* no_state_prefetch_manager) {
DCHECK(no_state_prefetch_manager);
const std::vector<GURL>& redirects = navigation_handle->GetRedirectChain();
base::TimeDelta prefetch_age;
- prerender::FinalStatus final_status;
- prerender::Origin prefetch_origin;
+ FinalStatus final_status;
+ Origin prefetch_origin;
bool nostate_prefetch_entry_found =
no_state_prefetch_manager->GetPrefetchInformation(
diff --git a/chromium/components/no_state_prefetch/browser/prerender_util.h b/chromium/components/no_state_prefetch/browser/no_state_prefetch_utils.h
index 77a3cc54eb9..aaef6fcac67 100644
--- a/chromium/components/no_state_prefetch/browser/prerender_util.h
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_utils.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_NO_STATE_PREFETCH_BROWSER_PRERENDER_UTIL_H_
-#define COMPONENTS_NO_STATE_PREFETCH_BROWSER_PRERENDER_UTIL_H_
+#ifndef COMPONENTS_NO_STATE_PREFETCH_BROWSER_NO_STATE_PREFETCH_UTILS_H_
+#define COMPONENTS_NO_STATE_PREFETCH_BROWSER_NO_STATE_PREFETCH_UTILS_H_
#include "services/metrics/public/cpp/ukm_source_id.h"
@@ -25,8 +25,8 @@ bool IsGoogleOriginURL(const GURL& origin_url);
void RecordNoStatePrefetchMetrics(
content::NavigationHandle* navigation_handle,
ukm::SourceId source_id,
- prerender::NoStatePrefetchManager* no_state_prefetch_manager);
+ NoStatePrefetchManager* no_state_prefetch_manager);
} // namespace prerender
-#endif // COMPONENTS_NO_STATE_PREFETCH_BROWSER_PRERENDER_UTIL_H_
+#endif // COMPONENTS_NO_STATE_PREFETCH_BROWSER_NO_STATE_PREFETCH_UTILS_H_
diff --git a/chromium/components/no_state_prefetch/browser/prerender_util_unittest.cc b/chromium/components/no_state_prefetch/browser/no_state_prefetch_utils_unittest.cc
index aa06da196c8..19b5e978e4f 100644
--- a/chromium/components/no_state_prefetch/browser/prerender_util_unittest.cc
+++ b/chromium/components/no_state_prefetch/browser/no_state_prefetch_utils_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/no_state_prefetch/browser/prerender_util.h"
+#include "components/no_state_prefetch/browser/no_state_prefetch_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -10,7 +10,7 @@
namespace prerender {
// Ensure that we detect GWS origin URLs correctly.
-TEST(PrerenderUtilTest, DetectGWSOriginURLTest) {
+TEST(NoStatePrefetchUtilsTest, DetectGWSOriginURLTest) {
EXPECT_TRUE(IsGoogleOriginURL(GURL("http://www.google.com/#asdf")));
EXPECT_TRUE(IsGoogleOriginURL(GURL("http://www.google.com/")));
EXPECT_TRUE(IsGoogleOriginURL(GURL("https://www.google.com")));
diff --git a/chromium/components/no_state_prefetch/browser/prerender_config.h b/chromium/components/no_state_prefetch/browser/prerender_config.h
index dc3be48cdec..42786e1f80d 100644
--- a/chromium/components/no_state_prefetch/browser/prerender_config.h
+++ b/chromium/components/no_state_prefetch/browser/prerender_config.h
@@ -7,8 +7,6 @@
#include <stddef.h>
-#include <string>
-
#include "base/time/time.h"
#include "ui/gfx/geometry/rect.h"
diff --git a/chromium/components/no_state_prefetch/browser/prerender_histograms.cc b/chromium/components/no_state_prefetch/browser/prerender_histograms.cc
index 04a993b4fc1..8285dae7998 100644
--- a/chromium/components/no_state_prefetch/browser/prerender_histograms.cc
+++ b/chromium/components/no_state_prefetch/browser/prerender_histograms.cc
@@ -12,9 +12,8 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
-#include "base/strings/stringprintf.h"
#include "components/google/core/common/google_util.h"
-#include "components/no_state_prefetch/common/prerender_util.h"
+#include "components/no_state_prefetch/common/no_state_prefetch_utils.h"
#include "net/http/http_cache.h"
namespace prerender {
@@ -52,6 +51,8 @@ std::string PrerenderHistograms::GetHistogramPrefix(Origin origin) {
return "navigationpredictor";
case ORIGIN_ISOLATED_PRERENDER:
return "isolatedprerender";
+ case ORIGIN_SAME_ORIGIN_SPECULATION:
+ return "sameoriginspeculation";
case ORIGIN_MAX:
NOTREACHED();
break;
diff --git a/chromium/components/no_state_prefetch/browser/prerender_history_unittest.cc b/chromium/components/no_state_prefetch/browser/prerender_history_unittest.cc
index 52b796cbcf1..9a0d67f34ab 100644
--- a/chromium/components/no_state_prefetch/browser/prerender_history_unittest.cc
+++ b/chromium/components/no_state_prefetch/browser/prerender_history_unittest.cc
@@ -15,45 +15,44 @@ namespace prerender {
namespace {
-bool ListEntryMatches(base::ListValue* list,
+bool ListEntryMatches(base::Value::ListView list,
size_t index,
const char* expected_url,
FinalStatus expected_final_status,
Origin expected_origin,
const std::string& expected_end_time) {
- if (index >= list->GetSize())
+ if (index >= list.size())
return false;
- base::DictionaryValue* dict = nullptr;
- if (!list->GetDictionary(index, &dict))
+ base::Value& dict = list[index];
+ if (!dict.is_dict())
return false;
- if (dict->size() != 4u)
+ if (dict.DictSize() != 4u)
return false;
- std::string url;
- if (!dict->GetString("url", &url))
+ std::string* url = dict.FindStringPath("url");
+ if (!url)
return false;
- if (url != expected_url)
+ if (*url != expected_url)
return false;
- std::string final_status;
- if (!dict->GetString("final_status", &final_status))
+ std::string* final_status = dict.FindStringPath("final_status");
+ if (!final_status)
return false;
- if (final_status != NameFromFinalStatus(expected_final_status))
+ if (*final_status != NameFromFinalStatus(expected_final_status))
return false;
- std::string origin;
- if (!dict->GetString("origin", &origin))
+ std::string* origin = dict.FindStringPath("origin");
+ if (!origin)
return false;
- if (origin != NameFromOrigin(expected_origin))
+ if (*origin != NameFromOrigin(expected_origin))
return false;
- std::string end_time;
- if (!dict->GetString("end_time", &end_time))
+ std::string* end_time = dict.FindStringPath("end_time");
+ if (!end_time)
return false;
- if (end_time != expected_end_time)
+ if (*end_time != expected_end_time)
return false;
return true;
}
TEST(PrerenderHistoryTest, GetAsValue) {
std::unique_ptr<base::Value> entry_value;
- base::ListValue* entry_list = nullptr;
// Create a history with only 2 values.
PrerenderHistory history(2);
@@ -61,8 +60,8 @@ TEST(PrerenderHistoryTest, GetAsValue) {
// Make sure an empty list exists when retrieving as value.
entry_value = history.CopyEntriesAsValue();
ASSERT_TRUE(entry_value.get() != nullptr);
- ASSERT_TRUE(entry_value->GetAsList(&entry_list));
- EXPECT_TRUE(entry_list->empty());
+ ASSERT_TRUE(entry_value->is_list());
+ EXPECT_TRUE(entry_value->GetList().empty());
// Base time used for all events. Each event is given a time 1 millisecond
// after that of the previous one.
@@ -77,10 +76,10 @@ TEST(PrerenderHistoryTest, GetAsValue) {
history.AddEntry(entry_first);
entry_value = history.CopyEntriesAsValue();
ASSERT_TRUE(entry_value.get() != nullptr);
- ASSERT_TRUE(entry_value->GetAsList(&entry_list));
- EXPECT_EQ(1u, entry_list->GetSize());
- EXPECT_TRUE(ListEntryMatches(entry_list, 0u, kFirstUrl, kFirstFinalStatus,
- kFirstOrigin, "0"));
+ ASSERT_TRUE(entry_value->is_list());
+ EXPECT_EQ(1u, entry_value->GetList().size());
+ EXPECT_TRUE(ListEntryMatches(entry_value->GetList(), 0u, kFirstUrl,
+ kFirstFinalStatus, kFirstOrigin, "0"));
// Add a second entry and make sure both first and second appear.
const char* const kSecondUrl = "http://www.beta.com/";
@@ -92,12 +91,12 @@ TEST(PrerenderHistoryTest, GetAsValue) {
history.AddEntry(entry_second);
entry_value = history.CopyEntriesAsValue();
ASSERT_TRUE(entry_value.get() != nullptr);
- ASSERT_TRUE(entry_value->GetAsList(&entry_list));
- EXPECT_EQ(2u, entry_list->GetSize());
- EXPECT_TRUE(ListEntryMatches(entry_list, 0u, kSecondUrl, kSecondFinalStatus,
- kSecondOrigin, "1"));
- EXPECT_TRUE(ListEntryMatches(entry_list, 1u, kFirstUrl, kFirstFinalStatus,
- kFirstOrigin, "0"));
+ ASSERT_TRUE(entry_value->is_list());
+ EXPECT_EQ(2u, entry_value->GetList().size());
+ EXPECT_TRUE(ListEntryMatches(entry_value->GetList(), 0u, kSecondUrl,
+ kSecondFinalStatus, kSecondOrigin, "1"));
+ EXPECT_TRUE(ListEntryMatches(entry_value->GetList(), 1u, kFirstUrl,
+ kFirstFinalStatus, kFirstOrigin, "0"));
// Add a third entry and make sure that the first one drops off.
const char* const kThirdUrl = "http://www.gamma.com/";
@@ -109,19 +108,19 @@ TEST(PrerenderHistoryTest, GetAsValue) {
history.AddEntry(entry_third);
entry_value = history.CopyEntriesAsValue();
ASSERT_TRUE(entry_value.get() != nullptr);
- ASSERT_TRUE(entry_value->GetAsList(&entry_list));
- EXPECT_EQ(2u, entry_list->GetSize());
- EXPECT_TRUE(ListEntryMatches(entry_list, 0u, kThirdUrl, kThirdFinalStatus,
- kThirdOrigin, "2"));
- EXPECT_TRUE(ListEntryMatches(entry_list, 1u, kSecondUrl, kSecondFinalStatus,
- kSecondOrigin, "1"));
+ ASSERT_TRUE(entry_value->is_list());
+ EXPECT_EQ(2u, entry_value->GetList().size());
+ EXPECT_TRUE(ListEntryMatches(entry_value->GetList(), 0u, kThirdUrl,
+ kThirdFinalStatus, kThirdOrigin, "2"));
+ EXPECT_TRUE(ListEntryMatches(entry_value->GetList(), 1u, kSecondUrl,
+ kSecondFinalStatus, kSecondOrigin, "1"));
// Make sure clearing history acts as expected.
history.Clear();
entry_value = history.CopyEntriesAsValue();
ASSERT_TRUE(entry_value.get() != nullptr);
- ASSERT_TRUE(entry_value->GetAsList(&entry_list));
- EXPECT_TRUE(entry_list->empty());
+ ASSERT_TRUE(entry_value->is_list());
+ EXPECT_TRUE(entry_value->GetList().empty());
}
} // namespace
diff --git a/chromium/components/no_state_prefetch/common/BUILD.gn b/chromium/components/no_state_prefetch/common/BUILD.gn
index e543ccf94ac..f5c1bcdcc2f 100644
--- a/chromium/components/no_state_prefetch/common/BUILD.gn
+++ b/chromium/components/no_state_prefetch/common/BUILD.gn
@@ -6,14 +6,14 @@ import("//mojo/public/tools/bindings/mojom.gni")
static_library("common") {
sources = [
+ "no_state_prefetch_utils.cc",
+ "no_state_prefetch_utils.h",
"prerender_final_status.cc",
"prerender_final_status.h",
"prerender_origin.cc",
"prerender_origin.h",
"prerender_url_loader_throttle.cc",
"prerender_url_loader_throttle.h",
- "prerender_util.cc",
- "prerender_util.h",
]
deps = [
":mojo_bindings",
diff --git a/chromium/components/no_state_prefetch/common/prerender_util.cc b/chromium/components/no_state_prefetch/common/no_state_prefetch_utils.cc
index d281e29c323..ccf5e5bff8a 100644
--- a/chromium/components/no_state_prefetch/common/prerender_util.cc
+++ b/chromium/components/no_state_prefetch/common/no_state_prefetch_utils.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/no_state_prefetch/common/prerender_util.h"
+#include "components/no_state_prefetch/common/no_state_prefetch_utils.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
diff --git a/chromium/components/no_state_prefetch/common/prerender_util.h b/chromium/components/no_state_prefetch/common/no_state_prefetch_utils.h
index f3555747fc6..9219fc9dab7 100644
--- a/chromium/components/no_state_prefetch/common/prerender_util.h
+++ b/chromium/components/no_state_prefetch/common/no_state_prefetch_utils.h
@@ -2,21 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_NO_STATE_PREFETCH_COMMON_PRERENDER_UTIL_H_
-#define COMPONENTS_NO_STATE_PREFETCH_COMMON_PRERENDER_UTIL_H_
+#ifndef COMPONENTS_NO_STATE_PREFETCH_COMMON_NO_STATE_PREFETCH_UTILS_H_
+#define COMPONENTS_NO_STATE_PREFETCH_COMMON_NO_STATE_PREFETCH_UTILS_H_
#include <string>
class GURL;
namespace prerender {
+
extern const char kFollowOnlyWhenPrerenderShown[];
-// Returns true iff the scheme of the URL given is valid for prerendering.
+// Returns true iff the scheme of the URL given is valid for prefetch.
bool DoesURLHaveValidScheme(const GURL& url);
// Returns true iff the scheme of the subresource URL given is valid for
-// prerendering.
+// prefetch.
bool DoesSubresourceURLHaveValidScheme(const GURL& url);
// Returns true iff the method given is valid for NoStatePrefetch.
@@ -40,4 +41,4 @@ void RecordPrefetchRedirectCount(const std::string& histogram_prefix,
} // namespace prerender
-#endif // COMPONENTS_NO_STATE_PREFETCH_COMMON_PRERENDER_UTIL_H_
+#endif // COMPONENTS_NO_STATE_PREFETCH_COMMON_NO_STATE_PREFETCH_UTILS_H_
diff --git a/chromium/components/no_state_prefetch/common/prerender_origin.cc b/chromium/components/no_state_prefetch/common/prerender_origin.cc
index 4d0c63b2c21..eb43f8d4f45 100644
--- a/chromium/components/no_state_prefetch/common/prerender_origin.cc
+++ b/chromium/components/no_state_prefetch/common/prerender_origin.cc
@@ -29,6 +29,7 @@ const char* kOriginNames[] = {
"[Deprecated] Offline",
"Navigation Predictor",
"Isolated Prerender",
+ "Speculation Rules Same Origin Prerender",
"Max",
};
static_assert(base::size(kOriginNames) == ORIGIN_MAX + 1,
diff --git a/chromium/components/no_state_prefetch/common/prerender_origin.h b/chromium/components/no_state_prefetch/common/prerender_origin.h
index 8de35dc9423..781f5ed2418 100644
--- a/chromium/components/no_state_prefetch/common/prerender_origin.h
+++ b/chromium/components/no_state_prefetch/common/prerender_origin.h
@@ -32,7 +32,8 @@ enum Origin {
// Obsolete: ORIGIN_OFFLINE = 14,
ORIGIN_NAVIGATION_PREDICTOR = 15,
ORIGIN_ISOLATED_PRERENDER = 16,
- ORIGIN_MAX = 17,
+ ORIGIN_SAME_ORIGIN_SPECULATION = 17,
+ ORIGIN_MAX = 18,
};
// Return a human-readable name for |origin|.
diff --git a/chromium/components/no_state_prefetch/common/prerender_url_loader_throttle.cc b/chromium/components/no_state_prefetch/common/prerender_url_loader_throttle.cc
index 9c2f73da43d..b71720b4b76 100644
--- a/chromium/components/no_state_prefetch/common/prerender_url_loader_throttle.cc
+++ b/chromium/components/no_state_prefetch/common/prerender_url_loader_throttle.cc
@@ -6,7 +6,7 @@
#include "base/bind.h"
#include "build/build_config.h"
-#include "components/no_state_prefetch/common/prerender_util.h"
+#include "components/no_state_prefetch/common/no_state_prefetch_utils.h"
#include "content/public/common/content_constants.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/load_flags.h"
diff --git a/chromium/components/no_state_prefetch/common/prerender_url_loader_throttle.h b/chromium/components/no_state_prefetch/common/prerender_url_loader_throttle.h
index 47fa114276f..b9ce70a1fab 100644
--- a/chromium/components/no_state_prefetch/common/prerender_url_loader_throttle.h
+++ b/chromium/components/no_state_prefetch/common/prerender_url_loader_throttle.h
@@ -7,12 +7,12 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/timer/timer.h"
#include "components/no_state_prefetch/common/prerender_canceler.mojom.h"
#include "net/base/request_priority.h"
#include "services/network/public/mojom/fetch_api.mojom-shared.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
namespace prerender {
@@ -64,7 +64,7 @@ class PrerenderURLLoaderThrottle
// The throttle changes most request priorities to IDLE during prerendering.
// The priority is reset back to the original priority when prerendering is
// finished.
- base::Optional<net::RequestPriority> original_request_priority_;
+ absl::optional<net::RequestPriority> original_request_priority_;
base::OnceClosure destruction_closure_;
diff --git a/chromium/components/no_state_prefetch/renderer/BUILD.gn b/chromium/components/no_state_prefetch/renderer/BUILD.gn
index 9c6c04fedec..651c0a1a6c7 100644
--- a/chromium/components/no_state_prefetch/renderer/BUILD.gn
+++ b/chromium/components/no_state_prefetch/renderer/BUILD.gn
@@ -8,13 +8,13 @@ static_library("renderer") {
"no_state_prefetch_client.h",
"no_state_prefetch_helper.cc",
"no_state_prefetch_helper.h",
+ "no_state_prefetch_utils.cc",
+ "no_state_prefetch_utils.h",
"prerender_observer.h",
"prerender_observer_list.cc",
"prerender_observer_list.h",
"prerender_render_frame_observer.cc",
"prerender_render_frame_observer.h",
- "prerender_utils.cc",
- "prerender_utils.h",
]
deps = [
diff --git a/chromium/components/no_state_prefetch/renderer/prerender_utils.cc b/chromium/components/no_state_prefetch/renderer/no_state_prefetch_utils.cc
index b6d2c5742d1..37c010c7995 100644
--- a/chromium/components/no_state_prefetch/renderer/prerender_utils.cc
+++ b/chromium/components/no_state_prefetch/renderer/no_state_prefetch_utils.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/no_state_prefetch/renderer/prerender_utils.h"
+#include "components/no_state_prefetch/renderer/no_state_prefetch_utils.h"
#include "components/no_state_prefetch/renderer/no_state_prefetch_helper.h"
#include "content/public/common/page_visibility_state.h"
@@ -53,7 +53,7 @@ bool DeferMediaLoad(content::RenderFrame* render_frame,
if ((render_frame->GetWebFrame()->View()->GetVisibilityState() !=
content::PageVisibilityState::kVisible &&
!has_played_media_before) ||
- prerender::NoStatePrefetchHelper::IsPrefetching(render_frame)) {
+ NoStatePrefetchHelper::IsPrefetching(render_frame)) {
new MediaLoadDeferrer(render_frame->GetWebFrame()->View(),
std::move(closure));
return true;
diff --git a/chromium/components/no_state_prefetch/renderer/prerender_utils.h b/chromium/components/no_state_prefetch/renderer/no_state_prefetch_utils.h
index c16c3b3e667..6758272212c 100644
--- a/chromium/components/no_state_prefetch/renderer/prerender_utils.h
+++ b/chromium/components/no_state_prefetch/renderer/no_state_prefetch_utils.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_NO_STATE_PREFETCH_RENDERER_PRERENDER_UTILS_H_
-#define COMPONENTS_NO_STATE_PREFETCH_RENDERER_PRERENDER_UTILS_H_
+#ifndef COMPONENTS_NO_STATE_PREFETCH_RENDERER_NO_STATE_PREFETCH_UTILS_H_
+#define COMPONENTS_NO_STATE_PREFETCH_RENDERER_NO_STATE_PREFETCH_UTILS_H_
#include "base/callback_forward.h"
@@ -22,4 +22,4 @@ bool DeferMediaLoad(content::RenderFrame* render_frame,
} // namespace prerender
-#endif // COMPONENTS_NO_STATE_PREFETCH_RENDERER_PRERENDER_UTILS_H_
+#endif // COMPONENTS_NO_STATE_PREFETCH_RENDERER_NO_STATE_PREFETCH_UTILS_H_
diff --git a/chromium/components/ntp_snippets/category_rankers/click_based_category_ranker.cc b/chromium/components/ntp_snippets/category_rankers/click_based_category_ranker.cc
index 289e91df4a5..108e269f2ae 100644
--- a/chromium/components/ntp_snippets/category_rankers/click_based_category_ranker.cc
+++ b/chromium/components/ntp_snippets/category_rankers/click_based_category_ranker.cc
@@ -353,7 +353,7 @@ bool ClickBasedCategoryRanker::ReadOrderFromPrefs(
return false;
}
- for (const base::Value& value : *list) {
+ for (const base::Value& value : list->GetList()) {
const base::DictionaryValue* dictionary;
if (!value.GetAsDictionary(&dictionary)) {
LOG(DFATAL) << "Failed to parse category data from prefs param "
diff --git a/chromium/components/ntp_snippets/category_rankers/constant_category_ranker.h b/chromium/components/ntp_snippets/category_rankers/constant_category_ranker.h
index 2416e3ac7a6..3307f8b4131 100644
--- a/chromium/components/ntp_snippets/category_rankers/constant_category_ranker.h
+++ b/chromium/components/ntp_snippets/category_rankers/constant_category_ranker.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_NTP_SNIPPETS_SECTION_RANKERS_CONSTANT_SECTION_RANKER_H_
-#define COMPONENTS_NTP_SNIPPETS_SECTION_RANKERS_CONSTANT_SECTION_RANKER_H_
+#ifndef COMPONENTS_NTP_SNIPPETS_CATEGORY_RANKERS_CONSTANT_CATEGORY_RANKER_H_
+#define COMPONENTS_NTP_SNIPPETS_CATEGORY_RANKERS_CONSTANT_CATEGORY_RANKER_H_
-#include <string>
#include <vector>
#include "base/macros.h"
@@ -49,4 +48,4 @@ class ConstantCategoryRanker : public CategoryRanker {
} // namespace ntp_snippets
-#endif // COMPONENTS_NTP_SNIPPETS_SECTION_RANKERS_CONSTANT_SECTION_RANKER_H_
+#endif // COMPONENTS_NTP_SNIPPETS_CATEGORY_RANKERS_CONSTANT_CATEGORY_RANKER_H_
diff --git a/chromium/components/ntp_snippets/content_suggestion.h b/chromium/components/ntp_snippets/content_suggestion.h
index 04bcd0f8408..972a87478be 100644
--- a/chromium/components/ntp_snippets/content_suggestion.h
+++ b/chromium/components/ntp_snippets/content_suggestion.h
@@ -9,11 +9,10 @@
#include <memory>
#include <string>
-#include "base/files/file_path.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/ntp_snippets/category.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace ntp_snippets {
@@ -155,11 +154,11 @@ class ContentSuggestion {
fetch_date_ = fetch_date;
}
- const base::Optional<uint32_t>& optional_image_dominant_color() const {
+ const absl::optional<uint32_t>& optional_image_dominant_color() const {
return image_dominant_color_;
}
void set_optional_image_dominant_color(
- const base::Optional<uint32_t>& optional_color_int) {
+ const absl::optional<uint32_t>& optional_color_int) {
image_dominant_color_ = optional_color_int;
}
@@ -184,7 +183,7 @@ class ContentSuggestion {
bool is_video_suggestion_;
// Encoded as an Android @ColorInt.
- base::Optional<uint32_t> image_dominant_color_;
+ absl::optional<uint32_t> image_dominant_color_;
DISALLOW_COPY_AND_ASSIGN(ContentSuggestion);
};
diff --git a/chromium/components/ntp_snippets/content_suggestions_metrics.h b/chromium/components/ntp_snippets/content_suggestions_metrics.h
index 4670f99962d..760cad6af25 100644
--- a/chromium/components/ntp_snippets/content_suggestions_metrics.h
+++ b/chromium/components/ntp_snippets/content_suggestions_metrics.h
@@ -75,4 +75,4 @@ void RecordFetchAction();
} // namespace metrics
} // namespace ntp_snippets
-#endif // COMPONENTS_NTP_SNIPPETS_CONTENT_SUGGESTIONS_SERVICE_H_
+#endif // COMPONENTS_NTP_SNIPPETS_CONTENT_SUGGESTIONS_METRICS_H_
diff --git a/chromium/components/ntp_snippets/content_suggestions_service.cc b/chromium/components/ntp_snippets/content_suggestions_service.cc
index 25124164699..e0c793cc705 100644
--- a/chromium/components/ntp_snippets/content_suggestions_service.cc
+++ b/chromium/components/ntp_snippets/content_suggestions_service.cc
@@ -15,7 +15,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
#include "base/values.h"
@@ -119,11 +118,11 @@ CategoryStatus ContentSuggestionsService::GetCategoryStatus(
return iterator->second->GetCategoryStatus(category);
}
-base::Optional<CategoryInfo> ContentSuggestionsService::GetCategoryInfo(
+absl::optional<CategoryInfo> ContentSuggestionsService::GetCategoryInfo(
Category category) const {
auto iterator = providers_by_category_.find(category);
if (iterator == providers_by_category_.end()) {
- return base::Optional<CategoryInfo>();
+ return absl::optional<CategoryInfo>();
}
return iterator->second->GetCategoryInfo(category);
}
@@ -676,15 +675,15 @@ void ContentSuggestionsService::RestoreDismissedCategoriesFromPrefs() {
const base::ListValue* list =
pref_service_->GetList(prefs::kDismissedCategories);
- for (const base::Value& entry : *list) {
- int id = 0;
- if (!entry.GetAsInteger(&id)) {
+ for (const base::Value& entry : list->GetList()) {
+ if (!entry.is_int()) {
DLOG(WARNING) << "Invalid category pref value: " << entry;
continue;
}
// When the provider is registered, it will be stored in this map.
- dismissed_providers_by_category_[Category::FromIDValue(id)] = nullptr;
+ dismissed_providers_by_category_[Category::FromIDValue(entry.GetInt())] =
+ nullptr;
}
}
diff --git a/chromium/components/ntp_snippets/content_suggestions_service.h b/chromium/components/ntp_snippets/content_suggestions_service.h
index 42cb8c10d1c..ecfb65597a6 100644
--- a/chromium/components/ntp_snippets/content_suggestions_service.h
+++ b/chromium/components/ntp_snippets/content_suggestions_service.h
@@ -13,7 +13,6 @@
#include "base/callback_forward.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/time/time.h"
@@ -28,6 +27,7 @@
#include "components/ntp_snippets/remote/remote_suggestions_scheduler.h"
#include "components/ntp_snippets/user_classifier.h"
#include "components/signin/public/identity_manager/identity_manager.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
class PrefRegistrySimple;
@@ -125,7 +125,7 @@ class ContentSuggestionsService : public KeyedService,
CategoryStatus GetCategoryStatus(Category category) const;
// Gets the meta information of a category.
- base::Optional<CategoryInfo> GetCategoryInfo(Category category) const;
+ absl::optional<CategoryInfo> GetCategoryInfo(Category category) const;
// Gets the available suggestions for a category. The result is empty if the
// category is available and empty, but also if the category is unavailable
diff --git a/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc b/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc
index 2f6036177ab..b7228e7516f 100644
--- a/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc
+++ b/chromium/components/ntp_snippets/content_suggestions_service_unittest.cc
@@ -353,7 +353,7 @@ TEST_F(ContentSuggestionsServiceTest,
ShouldNotReturnCategoryInfoForNonexistentCategory) {
Category category =
Category::FromKnownCategory(KnownCategories::READING_LIST);
- base::Optional<CategoryInfo> result = service()->GetCategoryInfo(category);
+ absl::optional<CategoryInfo> result = service()->GetCategoryInfo(category);
EXPECT_FALSE(result.has_value());
}
@@ -363,7 +363,7 @@ TEST_F(ContentSuggestionsServiceTest, ShouldReturnCategoryInfo) {
MockContentSuggestionsProvider* provider =
MakeRegisteredMockProvider(category);
provider->FireCategoryStatusChangedWithCurrentStatus(category);
- base::Optional<CategoryInfo> result = service()->GetCategoryInfo(category);
+ absl::optional<CategoryInfo> result = service()->GetCategoryInfo(category);
ASSERT_TRUE(result.has_value());
CategoryInfo expected = provider->GetCategoryInfo(category);
const CategoryInfo& actual = result.value();
diff --git a/chromium/components/ntp_snippets/pref_util.cc b/chromium/components/ntp_snippets/pref_util.cc
index 3973cda1b1d..74d7fcadf84 100644
--- a/chromium/components/ntp_snippets/pref_util.cc
+++ b/chromium/components/ntp_snippets/pref_util.cc
@@ -16,7 +16,7 @@ std::set<std::string> ReadDismissedIDsFromPrefs(const PrefService& pref_service,
const std::string& pref_name) {
std::set<std::string> dismissed_ids;
const base::ListValue* list = pref_service.GetList(pref_name);
- for (const base::Value& value : *list) {
+ for (const base::Value& value : list->GetList()) {
std::string dismissed_id;
bool success = value.GetAsString(&dismissed_id);
DCHECK(success) << "Failed to parse dismissed id from prefs param "
diff --git a/chromium/components/ntp_snippets/remote/json_request.cc b/chromium/components/ntp_snippets/remote/json_request.cc
index 070595f7b31..6f66dbc4f90 100644
--- a/chromium/components/ntp_snippets/remote/json_request.cc
+++ b/chromium/components/ntp_snippets/remote/json_request.cc
@@ -121,7 +121,7 @@ std::string GetUserClassString(UserClassifier::UserClass user_class) {
} // namespace
JsonRequest::JsonRequest(
- base::Optional<Category> exclusive_category,
+ absl::optional<Category> exclusive_category,
const base::Clock* clock, // Needed until destruction of the request.
const ParseJSONCallback& callback)
: exclusive_category_(exclusive_category),
diff --git a/chromium/components/ntp_snippets/remote/json_request.h b/chromium/components/ntp_snippets/remote/json_request.h
index 3fd6f965d47..6d7a2165be6 100644
--- a/chromium/components/ntp_snippets/remote/json_request.h
+++ b/chromium/components/ntp_snippets/remote/json_request.h
@@ -11,13 +11,13 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace base {
@@ -133,7 +133,7 @@ class JsonRequest {
DISALLOW_COPY_AND_ASSIGN(Builder);
};
- JsonRequest(base::Optional<Category> exclusive_category,
+ JsonRequest(absl::optional<Category> exclusive_category,
const base::Clock* clock,
const ParseJSONCallback& callback);
JsonRequest(JsonRequest&&);
@@ -143,7 +143,7 @@ class JsonRequest {
static int Get5xxRetryCount(bool interactive_request);
- const base::Optional<Category>& exclusive_category() const {
+ const absl::optional<Category>& exclusive_category() const {
return exclusive_category_;
}
@@ -165,7 +165,7 @@ class JsonRequest {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// If set, only return results for this category.
- base::Optional<Category> exclusive_category_;
+ absl::optional<Category> exclusive_category_;
// Use the Clock from the Fetcher to measure the fetch time. It will be
// used on creation and after the fetch returned. It has to be alive until the
diff --git a/chromium/components/ntp_snippets/remote/json_request_unittest.cc b/chromium/components/ntp_snippets/remote/json_request_unittest.cc
index 85d2d1fa532..7919eaf94c0 100644
--- a/chromium/components/ntp_snippets/remote/json_request_unittest.cc
+++ b/chromium/components/ntp_snippets/remote/json_request_unittest.cc
@@ -45,7 +45,7 @@ using testing::NotNull;
using testing::StrEq;
MATCHER_P(EqualsJSON, json, "equals JSON") {
- base::Optional<base::Value> expected = base::JSONReader::Read(json);
+ absl::optional<base::Value> expected = base::JSONReader::Read(json);
if (!expected) {
*result_listener << "INTERNAL ERROR: couldn't parse expected JSON";
return false;
diff --git a/chromium/components/ntp_snippets/remote/json_to_categories.cc b/chromium/components/ntp_snippets/remote/json_to_categories.cc
index 19acfb61194..f4685a49209 100644
--- a/chromium/components/ntp_snippets/remote/json_to_categories.cc
+++ b/chromium/components/ntp_snippets/remote/json_to_categories.cc
@@ -4,9 +4,9 @@
#include "components/ntp_snippets/remote/json_to_categories.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "components/strings/grit/components_strings.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/l10n/l10n_util.h"
namespace ntp_snippets {
@@ -19,7 +19,7 @@ bool AddSuggestionsFromListValue(int remote_category_id,
const base::ListValue& list,
RemoteSuggestion::PtrVector* suggestions,
const base::Time& fetch_time) {
- for (const auto& value : list) {
+ for (const base::Value& value : list.GetList()) {
const base::DictionaryValue* dict = nullptr;
if (!value.GetAsDictionary(&dict)) {
return false;
@@ -51,7 +51,7 @@ FetchedCategory::~FetchedCategory() = default;
FetchedCategory& FetchedCategory::operator=(FetchedCategory&&) = default;
CategoryInfo BuildArticleCategoryInfo(
- const base::Optional<std::u16string>& title) {
+ const absl::optional<std::u16string>& title) {
return CategoryInfo(
title.has_value() ? title.value()
: l10n_util::GetStringUTF16(
@@ -91,7 +91,7 @@ bool JsonToCategories(const base::Value& parsed,
return false;
}
- for (const auto& v : *categories_value) {
+ for (const base::Value& v : categories_value->GetList()) {
std::string utf8_title;
int remote_category_id = -1;
const base::DictionaryValue* category_value = nullptr;
diff --git a/chromium/components/ntp_snippets/remote/json_to_categories.h b/chromium/components/ntp_snippets/remote/json_to_categories.h
index 21a51168713..26e593c568a 100644
--- a/chromium/components/ntp_snippets/remote/json_to_categories.h
+++ b/chromium/components/ntp_snippets/remote/json_to_categories.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_NTP_SNIPPETS_REMOTE_REMOTE_SUGGESTIONS_HELPER_H_
-#define COMPONENTS_NTP_SNIPPETS_REMOTE_REMOTE_SUGGESTIONS_HELPER_H_
+#ifndef COMPONENTS_NTP_SNIPPETS_REMOTE_JSON_TO_CATEGORIES_H_
+#define COMPONENTS_NTP_SNIPPETS_REMOTE_JSON_TO_CATEGORIES_H_
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/ntp_snippets/category.h"
#include "components/ntp_snippets/category_info.h"
#include "components/ntp_snippets/remote/remote_suggestion.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ntp_snippets {
@@ -30,7 +30,7 @@ using FetchedCategoriesVector = std::vector<FetchedCategory>;
// Provides the CategoryInfo data for article suggestions. If |title| is
// nullopt, then the default, hard-coded title will be used.
CategoryInfo BuildArticleCategoryInfo(
- const base::Optional<std::u16string>& title);
+ const absl::optional<std::u16string>& title);
// Provides the CategoryInfo data for other remote suggestions.
CategoryInfo BuildRemoteCategoryInfo(const std::u16string& title,
@@ -42,4 +42,4 @@ bool JsonToCategories(const base::Value& parsed,
} // namespace ntp_snippets
-#endif // COMPONENTS_NTP_SNIPPETS_REMOTE_REMOTE_SUGGESTIONS_HELPER_H_
+#endif // COMPONENTS_NTP_SNIPPETS_REMOTE_JSON_TO_CATEGORIES_H_
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestion.cc b/chromium/components/ntp_snippets/remote/remote_suggestion.cc
index 896bc3eb5c0..e56e67efe9f 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestion.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestion.cc
@@ -9,7 +9,6 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "components/ntp_snippets/category.h"
@@ -73,7 +72,7 @@ RemoteSuggestion::CreateFromContentSuggestionsDictionary(
return nullptr;
}
std::vector<std::string> parsed_ids;
- for (const auto& value : *ids) {
+ for (const base::Value& value : ids->GetList()) {
std::string id;
if (!value.GetAsString(&id)) {
return nullptr;
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestion.h b/chromium/components/ntp_snippets/remote/remote_suggestion.h
index 7bd138d548f..f7ee311fc8e 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestion.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestion.h
@@ -12,9 +12,9 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/ntp_snippets/content_suggestion.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace base {
@@ -80,7 +80,7 @@ class RemoteSuggestion {
// directly.
const GURL& salient_image_url() const { return salient_image_url_; }
- const base::Optional<uint32_t>& optional_image_dominant_color() const {
+ const absl::optional<uint32_t>& optional_image_dominant_color() const {
return image_dominant_color_;
}
@@ -140,7 +140,7 @@ class RemoteSuggestion {
GURL salient_image_url_;
// Encoded as an Android @ColorInt.
- base::Optional<uint32_t> image_dominant_color_;
+ absl::optional<uint32_t> image_dominant_color_;
std::string snippet_;
base::Time publish_date_;
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestion_builder.h b/chromium/components/ntp_snippets/remote/remote_suggestion_builder.h
index 6e714c19928..e92902ee45e 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestion_builder.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestion_builder.h
@@ -8,9 +8,9 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "components/ntp_snippets/remote/json_to_categories.h"
#include "components/ntp_snippets/remote/remote_suggestion.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ntp_snippets {
@@ -43,22 +43,22 @@ class RemoteSuggestionBuilder {
std::unique_ptr<RemoteSuggestion> Build() const;
private:
- base::Optional<std::vector<std::string>> ids_;
- base::Optional<std::string> title_;
- base::Optional<std::string> snippet_;
- base::Optional<std::string> salient_image_url_;
- base::Optional<base::Time> publish_date_;
- base::Optional<base::Time> expiry_date_;
- base::Optional<double> score_;
- base::Optional<bool> is_dismissed_;
- base::Optional<int> remote_category_id_;
- base::Optional<std::string> url_;
- base::Optional<std::string> publisher_name_;
- base::Optional<std::string> amp_url_;
- base::Optional<base::Time> fetch_date_;
- base::Optional<int> rank_;
- base::Optional<bool> should_notify_;
- base::Optional<base::Time> notification_deadline_;
+ absl::optional<std::vector<std::string>> ids_;
+ absl::optional<std::string> title_;
+ absl::optional<std::string> snippet_;
+ absl::optional<std::string> salient_image_url_;
+ absl::optional<base::Time> publish_date_;
+ absl::optional<base::Time> expiry_date_;
+ absl::optional<double> score_;
+ absl::optional<bool> is_dismissed_;
+ absl::optional<int> remote_category_id_;
+ absl::optional<std::string> url_;
+ absl::optional<std::string> publisher_name_;
+ absl::optional<std::string> amp_url_;
+ absl::optional<base::Time> fetch_date_;
+ absl::optional<int> rank_;
+ absl::optional<bool> should_notify_;
+ absl::optional<base::Time> notification_deadline_;
};
class FetchedCategoryBuilder {
@@ -82,13 +82,13 @@ class FetchedCategoryBuilder {
FetchedCategory Build() const;
private:
- base::Optional<Category> category_;
- base::Optional<std::u16string> title_;
- base::Optional<ContentSuggestionsCardLayout> card_layout_;
- base::Optional<ContentSuggestionsAdditionalAction> additional_action_;
- base::Optional<bool> show_if_empty_;
- base::Optional<std::u16string> no_suggestions_message_;
- base::Optional<std::vector<RemoteSuggestionBuilder>> suggestion_builders_;
+ absl::optional<Category> category_;
+ absl::optional<std::u16string> title_;
+ absl::optional<ContentSuggestionsCardLayout> card_layout_;
+ absl::optional<ContentSuggestionsAdditionalAction> additional_action_;
+ absl::optional<bool> show_if_empty_;
+ absl::optional<std::u16string> no_suggestions_message_;
+ absl::optional<std::vector<RemoteSuggestionBuilder>> suggestion_builders_;
};
} // namespace test
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestion_unittest.cc b/chromium/components/ntp_snippets/remote/remote_suggestion_unittest.cc
index 9656b60fe00..5778688f788 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestion_unittest.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestion_unittest.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/json/json_reader.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher.h b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher.h
index fb4758dea74..138a741d33e 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher.h
@@ -9,13 +9,13 @@
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
#include "components/ntp_snippets/category.h"
#include "components/ntp_snippets/category_info.h"
#include "components/ntp_snippets/remote/json_to_categories.h"
#include "components/ntp_snippets/remote/remote_suggestion.h"
#include "components/ntp_snippets/remote/request_params.h"
#include "components/ntp_snippets/status.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace ntp_snippets {
@@ -27,7 +27,7 @@ GURL GetFetchEndpoint();
// Fetches suggestion data for the NTP from the server.
class RemoteSuggestionsFetcher {
public:
- using OptionalFetchedCategories = base::Optional<FetchedCategoriesVector>;
+ using OptionalFetchedCategories = absl::optional<FetchedCategoriesVector>;
using SnippetsAvailableCallback =
base::OnceCallback<void(Status status,
OptionalFetchedCategories fetched_categories)>;
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 4ad03961f92..ae6bc31042e 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.cc
@@ -132,7 +132,7 @@ int GetMinuteOfTheDay(bool local_time,
// categories. If only a single category was requested, this function filters
// all other categories out.
void FilterCategories(FetchedCategoriesVector* categories,
- base::Optional<Category> exclusive_category) {
+ absl::optional<Category> exclusive_category) {
if (!exclusive_category.has_value()) {
return;
}
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h
index 23110e34008..7db375e9257 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_fetcher_impl.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/containers/queue.h"
-#include "base/optional.h"
#include "base/time/clock.h"
#include "components/ntp_snippets/remote/json_request.h"
#include "components/ntp_snippets/remote/json_to_categories.h"
@@ -20,6 +19,7 @@
#include "components/ntp_snippets/remote/request_params.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "google_apis/gaia/google_service_auth_error.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
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 5014f9702f2..e43b44adc50 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
@@ -11,7 +11,6 @@
#include "base/bind.h"
#include "base/containers/circular_deque.h"
#include "base/json/json_reader.h"
-#include "base/optional.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
@@ -39,6 +38,7 @@
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ntp_snippets {
@@ -713,7 +713,7 @@ TEST_F(RemoteSuggestionsFetcherImplTest, ExclusiveCategoryOnly) {
RequestParams params = test_params();
params.exclusive_category =
- base::Optional<Category>(Category::FromRemoteCategory(2));
+ absl::optional<Category>(Category::FromRemoteCategory(2));
fetcher().FetchSnippets(params,
ToSnippetsAvailableCallback(&mock_callback()));
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_provider.h b/chromium/components/ntp_snippets/remote/remote_suggestions_provider.h
index b84de0f015d..7529940c7ba 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_provider.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_provider.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_NTP_SNIPPETS_REMOTE_REMOTE_SUGGESTIONS_PROVIDER_H_
#define COMPONENTS_NTP_SNIPPETS_REMOTE_REMOTE_SUGGESTIONS_PROVIDER_H_
-#include <memory>
-
#include "base/callback_forward.h"
#include "base/macros.h"
#include "components/ntp_snippets/content_suggestions_provider.h"
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
index a94b84ce62d..68ea1100186 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.cc
@@ -332,7 +332,7 @@ RemoteSuggestionsProviderImpl::RemoteSuggestionsProviderImpl(
// TODO(treib): Rethink this.
category_contents_.insert(
std::make_pair(articles_category_,
- CategoryContent(BuildArticleCategoryInfo(base::nullopt))));
+ CategoryContent(BuildArticleCategoryInfo(absl::nullopt))));
// Tell the observer about all the categories.
for (const auto& entry : category_contents_) {
observer->OnCategoryStatusChanged(this, entry.first, entry.second.status);
@@ -507,7 +507,7 @@ void RemoteSuggestionsProviderImpl::FetchSuggestions(
// |count_to_fetch| is actually ignored, because the server does not support
// this functionality.
- RequestParams params = BuildFetchParams(/*fetched_category=*/base::nullopt,
+ RequestParams params = BuildFetchParams(/*fetched_category=*/absl::nullopt,
/*count_to_fetch=*/10);
params.interactive_request = interactive_request;
suggestions_fetcher_->FetchSnippets(
@@ -556,7 +556,7 @@ void RemoteSuggestionsProviderImpl::Fetch(
// Builds default fetcher params.
RequestParams RemoteSuggestionsProviderImpl::BuildFetchParams(
- base::Optional<Category> fetched_category,
+ absl::optional<Category> fetched_category,
int count_to_fetch) const {
RequestParams result;
result.language_code = application_language_code_;
@@ -1558,7 +1558,7 @@ void RemoteSuggestionsProviderImpl::RestoreCategoriesFromPrefs() {
const base::ListValue* list =
pref_service_->GetList(prefs::kRemoteSuggestionCategories);
- for (const base::Value& entry : *list) {
+ for (const base::Value& entry : list->GetList()) {
const base::DictionaryValue* dict = nullptr;
if (!entry.GetAsDictionary(&dict)) {
DLOG(WARNING) << "Invalid category pref value: " << entry;
@@ -1599,7 +1599,7 @@ void RemoteSuggestionsProviderImpl::RestoreCategoriesFromPrefs() {
// avoid using a title that was calculated for a stale locale.
CategoryInfo info =
category == articles_category_
- ? BuildArticleCategoryInfo(base::nullopt)
+ ? BuildArticleCategoryInfo(absl::nullopt)
: BuildRemoteCategoryInfo(title, allow_fetching_more_results);
CategoryContent* content = UpdateCategoryInfo(category, info);
content->included_in_last_server_response =
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.h b/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.h
index d2e0d5512c4..1c6da418f66 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_provider_impl.h
@@ -17,7 +17,6 @@
#include "base/containers/circular_deque.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -33,6 +32,7 @@
#include "components/ntp_snippets/remote/remote_suggestions_status_service.h"
#include "components/ntp_snippets/remote/request_params.h"
#include "components/ntp_snippets/remote/request_throttler.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefRegistrySimple;
class PrefService;
@@ -396,7 +396,7 @@ class RemoteSuggestionsProviderImpl final : public RemoteSuggestionsProvider {
// fetches at most |count_to_fetch| suggestions only from |fetched_category|.
// TODO(vitaliii): Also support |count_to_fetch| when |fetched_category| is
// nullopt.
- RequestParams BuildFetchParams(base::Optional<Category> fetched_category,
+ RequestParams BuildFetchParams(absl::optional<Category> fetched_category,
int count_to_fetch) const;
bool AreArticlesEmpty() const;
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 01b07213fd1..8eca4241ef8 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
@@ -124,7 +124,7 @@ const char kImageUrl[] = "http://image/image.png";
const char kSuggestionUrl2[] = "http://foo.com/bar";
-const char kTestJsonDefaultCategoryTitle[] = "Some title";
+const char16_t kTestJsonDefaultCategoryTitle[] = u"Some title";
const int kOtherCategoryId = 2;
const int kUnknownRemoteCategoryId = 1234;
@@ -284,7 +284,8 @@ class RemoteSuggestionsProviderImplTest : public ::testing::Test {
} else {
remote_suggestions_status_service =
std::make_unique<RemoteSuggestionsStatusServiceImpl>(
- /*has_signed_in=*/false, utils_.pref_service(), std::string());
+ /*has_signed_in=*/false, utils_.pref_service(),
+ std::vector<std::string>());
}
remote_suggestions_status_service_ =
remote_suggestions_status_service.get();
@@ -395,7 +396,7 @@ class RemoteSuggestionsProviderImplTest : public ::testing::Test {
void FetchTheseSuggestions(
bool interactive_request,
Status status,
- base::Optional<std::vector<FetchedCategory>> fetched_categories) {
+ absl::optional<std::vector<FetchedCategory>> fetched_categories) {
RemoteSuggestionsFetcher::SnippetsAvailableCallback snippets_callback;
EXPECT_CALL(*mock_suggestions_fetcher(), FetchSnippets(_, _))
.WillOnce(MoveSecondArgumentPointeeTo(&snippets_callback))
@@ -410,7 +411,7 @@ class RemoteSuggestionsProviderImplTest : public ::testing::Test {
const std::set<std::string>& known_suggestion_ids,
FetchDoneCallback fetch_done_callback,
Status status,
- base::Optional<std::vector<FetchedCategory>> fetched_categories) {
+ absl::optional<std::vector<FetchedCategory>> fetched_categories) {
RemoteSuggestionsFetcher::SnippetsAvailableCallback snippets_callback;
EXPECT_CALL(*mock_suggestions_fetcher(), FetchSnippets(_, _))
.WillOnce(MoveSecondArgumentPointeeTo(&snippets_callback))
@@ -591,8 +592,7 @@ TEST_F(RemoteSuggestionsProviderImplTest, Full) {
}
TEST_F(RemoteSuggestionsProviderImplTest, CategoryTitle) {
- const std::u16string test_default_title =
- base::UTF8ToUTF16(kTestJsonDefaultCategoryTitle);
+ const std::u16string test_default_title = kTestJsonDefaultCategoryTitle;
// Don't send an initial response -- we want to test what happens without any
// server status.
@@ -1476,7 +1476,7 @@ TEST_F(RemoteSuggestionsProviderImplTest,
ASSERT_FALSE(snippets_callback.is_null());
std::move(snippets_callback)
.Run(Status(StatusCode::TEMPORARY_ERROR, "Received invalid JSON"),
- base::nullopt);
+ absl::nullopt);
}
TEST_F(RemoteSuggestionsProviderImplTest,
@@ -1487,7 +1487,7 @@ TEST_F(RemoteSuggestionsProviderImplTest,
FetchTheseSuggestions(
/*interactive_request=*/false,
Status(StatusCode::TEMPORARY_ERROR, "Received invalid JSON"),
- base::nullopt);
+ absl::nullopt);
EXPECT_THAT(provider()->GetSuggestionsForTesting(articles_category()),
IsEmpty());
}
@@ -1514,7 +1514,7 @@ TEST_F(RemoteSuggestionsProviderImplTest,
FetchTheseSuggestions(
/*interactive_request=*/false,
Status(StatusCode::TEMPORARY_ERROR, "Received invalid JSON"),
- base::nullopt);
+ absl::nullopt);
// This should not have changed the existing suggestions.
EXPECT_THAT(
provider()->GetSuggestionsForTesting(articles_category()),
@@ -1760,7 +1760,7 @@ TEST_F(RemoteSuggestionsProviderImplTest, LogNumArticlesHistogram) {
FetchTheseSuggestions(/*interactive_request=*/true,
Status(StatusCode::TEMPORARY_ERROR, "message"),
- base::nullopt);
+ absl::nullopt);
// Error responses don't update the list of suggestions and shouldn't
// influence these metrics.
EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"),
@@ -2116,7 +2116,7 @@ TEST_F(RemoteSuggestionsProviderImplTest,
provider()->RefetchInTheBackground(
RemoteSuggestionsProvider::FetchStatusCallback());
RunUntilIdle();
- std::move(snippets_callback).Run(Status::Success(), base::nullopt);
+ std::move(snippets_callback).Run(Status::Success(), absl::nullopt);
// TODO(jkrcal): Move together with the pref storage into the scheduler.
EXPECT_EQ(
SerializeTime(simple_test_clock.Now()),
@@ -3024,7 +3024,7 @@ TEST_F(RemoteSuggestionsProviderImplTest,
// Next fetch returns an error (with an empty section).
FetchTheseSuggestions(/*interactive_request=*/true,
Status(StatusCode::TEMPORARY_ERROR, "some error"),
- base::nullopt);
+ absl::nullopt);
// Articles category should stay unchanged.
EXPECT_EQ(CategoryStatus::AVAILABLE,
@@ -3140,7 +3140,7 @@ TEST_F(RemoteSuggestionsProviderImplTest,
// After the results come, the status is flipped back to AVAILABLE.
std::move(response_callback)
- .Run(Status(StatusCode::TEMPORARY_ERROR, "some error"), base::nullopt);
+ .Run(Status(StatusCode::TEMPORARY_ERROR, "some error"), absl::nullopt);
// The category is available with the previous suggestion.
EXPECT_EQ(CategoryStatus::AVAILABLE,
observer().StatusForCategory(articles_category()));
@@ -3281,7 +3281,7 @@ TEST_F(RemoteSuggestionsProviderImplTest,
// After the results come, the status is flipped back to AVAILABLE.
std::move(response_callback)
- .Run(Status(StatusCode::TEMPORARY_ERROR, "some error"), base::nullopt);
+ .Run(Status(StatusCode::TEMPORARY_ERROR, "some error"), absl::nullopt);
// The category is available, with no suggestions.
EXPECT_EQ(CategoryStatus::AVAILABLE,
observer().StatusForCategory(articles_category()));
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_scheduler_impl.h b/chromium/components/ntp_snippets/remote/remote_suggestions_scheduler_impl.h
index 3558ffb985d..35aa46a12ea 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_scheduler_impl.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_scheduler_impl.h
@@ -7,7 +7,6 @@
#include <memory>
#include <set>
-#include <string>
#include <utility>
#include <vector>
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.cc
index 9198c84aad2..c42342f955c 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.cc
@@ -22,9 +22,9 @@ namespace ntp_snippets {
RemoteSuggestionsStatusServiceImpl::RemoteSuggestionsStatusServiceImpl(
bool is_signed_in,
PrefService* pref_service,
- const std::string& additional_toggle_pref)
+ const std::vector<std::string>& additional_toggle_prefs)
: status_(RemoteSuggestionsStatus::EXPLICITLY_DISABLED),
- additional_toggle_pref_(additional_toggle_pref),
+ additional_toggle_prefs_(additional_toggle_prefs),
is_signed_in_(is_signed_in),
list_visible_during_session_(true),
pref_service_(pref_service) {
@@ -62,9 +62,9 @@ void RemoteSuggestionsStatusServiceImpl::Init(
&RemoteSuggestionsStatusServiceImpl::OnListVisibilityChanged,
base::Unretained(this)));
- if (!additional_toggle_pref_.empty()) {
+ for (const std::string& additional_toggle_pref : additional_toggle_prefs_) {
pref_change_registrar_.Add(
- additional_toggle_pref_,
+ additional_toggle_pref,
base::BindRepeating(
&RemoteSuggestionsStatusServiceImpl::OnSnippetsEnabledChanged,
base::Unretained(this)));
@@ -113,9 +113,9 @@ bool RemoteSuggestionsStatusServiceImpl::IsExplicitlyDisabled() const {
return true;
}
- // |additional_toggle_pref_| will always be empty on Android.
- if (!additional_toggle_pref_.empty()) {
- if (!pref_service_->GetBoolean(additional_toggle_pref_)) {
+ // |additional_toggle_prefs_| will always be empty on Android.
+ for (const std::string& additional_toggle_pref : additional_toggle_prefs_) {
+ if (!pref_service_->GetBoolean(additional_toggle_pref)) {
DVLOG(1) << "[GetStatusFromDeps] Disabled via additional pref";
return true;
}
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.h b/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.h
index edf537adafc..9eaf0c626ce 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.h
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl.h
@@ -17,9 +17,10 @@ namespace ntp_snippets {
class RemoteSuggestionsStatusServiceImpl
: public RemoteSuggestionsStatusService {
public:
- RemoteSuggestionsStatusServiceImpl(bool is_signed_in,
- PrefService* pref_service,
- const std::string& additional_toggle_pref);
+ RemoteSuggestionsStatusServiceImpl(
+ bool is_signed_in,
+ PrefService* pref_service,
+ const std::vector<std::string>& additional_toggle_prefs);
~RemoteSuggestionsStatusServiceImpl() override;
@@ -45,9 +46,9 @@ class RemoteSuggestionsStatusServiceImpl
RemoteSuggestionsStatus status_;
StatusChangeCallback status_change_callback_;
- // Name of a preference to be used as an additional toggle to guard the
- // remote suggestions provider.
- std::string additional_toggle_pref_;
+ // Name of preferences to be used as additional toggles to guard the remote
+ // suggestions provider.
+ std::vector<std::string> additional_toggle_prefs_;
bool is_signed_in_;
// Whether the list of remote suggestions was ever visible during the session.
// In case it was visible and then gets hidden, the service will only be
diff --git a/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl_unittest.cc b/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl_unittest.cc
index 185131b08ba..2484015ce0c 100644
--- a/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl_unittest.cc
+++ b/chromium/components/ntp_snippets/remote/remote_suggestions_status_service_impl_unittest.cc
@@ -43,7 +43,8 @@ class RemoteSuggestionsStatusServiceImplTest : public ::testing::Test {
bool empty_additional_pref) {
auto service = std::make_unique<RemoteSuggestionsStatusServiceImpl>(
false, utils_.pref_service(),
- empty_additional_pref ? std::string() : kTestPrefName);
+ empty_additional_pref ? std::vector<std::string>()
+ : std::vector<std::string>{kTestPrefName});
service->Init(base::BindRepeating(
&RemoteSuggestionsStatusServiceImplTest::OnStatusChange,
base::Unretained(this)));
diff --git a/chromium/components/ntp_snippets/remote/request_params.h b/chromium/components/ntp_snippets/remote/request_params.h
index 5dfadb12882..943d778ef70 100644
--- a/chromium/components/ntp_snippets/remote/request_params.h
+++ b/chromium/components/ntp_snippets/remote/request_params.h
@@ -10,9 +10,9 @@
#include <string>
#include "base/callback.h"
-#include "base/optional.h"
#include "base/values.h"
#include "components/ntp_snippets/category.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace ntp_snippets {
@@ -37,7 +37,7 @@ struct RequestParams {
bool interactive_request = false;
// If set, only return results for this category.
- base::Optional<Category> exclusive_category;
+ absl::optional<Category> exclusive_category;
};
// Callbacks for JSON parsing to allow injecting platform-dependent code.
diff --git a/chromium/components/ntp_snippets/remote/request_throttler.h b/chromium/components/ntp_snippets/remote/request_throttler.h
index 3435799097c..de38b5e2239 100644
--- a/chromium/components/ntp_snippets/remote/request_throttler.h
+++ b/chromium/components/ntp_snippets/remote/request_throttler.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_NTP_SNIPPETS_REMOTE_REQUEST_THROTTLER_H_
#define COMPONENTS_NTP_SNIPPETS_REMOTE_REQUEST_THROTTLER_H_
-#include <string>
-
#include "base/macros.h"
class PrefRegistrySimple;
diff --git a/chromium/components/ntp_snippets/remote/request_throttler_unittest.cc b/chromium/components/ntp_snippets/remote/request_throttler_unittest.cc
index 405c049ea62..58cae66cf43 100644
--- a/chromium/components/ntp_snippets/remote/request_throttler_unittest.cc
+++ b/chromium/components/ntp_snippets/remote/request_throttler_unittest.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/strings/stringprintf.h"
#include "components/ntp_snippets/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
diff --git a/chromium/components/ntp_tiles/OWNERS b/chromium/components/ntp_tiles/OWNERS
index a569ff59df4..ed82277e8ff 100644
--- a/chromium/components/ntp_tiles/OWNERS
+++ b/chromium/components/ntp_tiles/OWNERS
@@ -1,4 +1,3 @@
-aee@chromium.org
kristipark@chromium.org
mahmadi@chromium.org
tiborg@chromium.org
diff --git a/chromium/components/ntp_tiles/constants.h b/chromium/components/ntp_tiles/constants.h
index 755a0ecbcf4..50a607d830f 100644
--- a/chromium/components/ntp_tiles/constants.h
+++ b/chromium/components/ntp_tiles/constants.h
@@ -7,8 +7,6 @@
#include <stddef.h>
-#include <utility>
-
namespace ntp_tiles {
// Maximum number of custom links that can be set by the user. Used on desktop.
diff --git a/chromium/components/ntp_tiles/custom_links_manager_impl.cc b/chromium/components/ntp_tiles/custom_links_manager_impl.cc
index f7551933a52..1f73656c1bb 100644
--- a/chromium/components/ntp_tiles/custom_links_manager_impl.cc
+++ b/chromium/components/ntp_tiles/custom_links_manager_impl.cc
@@ -166,7 +166,7 @@ bool CustomLinksManagerImpl::UndoAction() {
// Replace the current links with the previous state.
current_links_ = *previous_links_;
- previous_links_ = base::nullopt;
+ previous_links_ = absl::nullopt;
StoreLinks();
return true;
}
@@ -177,7 +177,7 @@ void CustomLinksManagerImpl::ClearLinks() {
store_.ClearLinks();
}
current_links_.clear();
- previous_links_ = base::nullopt;
+ previous_links_ = absl::nullopt;
}
void CustomLinksManagerImpl::StoreLinks() {
@@ -217,7 +217,7 @@ void CustomLinksManagerImpl::OnURLsDeleted(
}
}
StoreLinks();
- previous_links_ = base::nullopt;
+ previous_links_ = absl::nullopt;
// Alert MostVisitedSites that some links have been deleted.
if (initial_size != current_links_.size())
@@ -238,7 +238,7 @@ void CustomLinksManagerImpl::OnPreferenceChanged() {
current_links_ = store_.RetrieveLinks();
else
current_links_.clear();
- previous_links_ = base::nullopt;
+ previous_links_ = absl::nullopt;
closure_list_.Notify();
}
diff --git a/chromium/components/ntp_tiles/custom_links_manager_impl.h b/chromium/components/ntp_tiles/custom_links_manager_impl.h
index b7dc1ad5c16..d0c72d17a1e 100644
--- a/chromium/components/ntp_tiles/custom_links_manager_impl.h
+++ b/chromium/components/ntp_tiles/custom_links_manager_impl.h
@@ -10,7 +10,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_service_observer.h"
@@ -18,6 +17,7 @@
#include "components/ntp_tiles/custom_links_store.h"
#include "components/ntp_tiles/ntp_tile.h"
#include "components/prefs/pref_change_registrar.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
@@ -88,7 +88,7 @@ class CustomLinksManagerImpl : public CustomLinksManager,
std::vector<Link> current_links_;
// The state of the current list of links before the last action was
// performed.
- base::Optional<std::vector<Link>> previous_links_;
+ absl::optional<std::vector<Link>> previous_links_;
// List of closures to be invoked when custom links are updated by outside
// sources.
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 1c36355c069..0776190dda2 100644
--- a/chromium/components/ntp_tiles/custom_links_manager_impl_unittest.cc
+++ b/chromium/components/ntp_tiles/custom_links_manager_impl_unittest.cc
@@ -26,28 +26,29 @@ namespace {
struct TestCaseItem {
const char* url;
- const char* title;
+ const char16_t* title;
};
-const TestCaseItem kTestCase1[] = {{"http://foo1.com/", "Foo1"}};
+const TestCaseItem kTestCase1[] = {{"http://foo1.com/", u"Foo1"}};
const TestCaseItem kTestCase2[] = {
- {"http://foo1.com/", "Foo1"},
- {"http://foo2.com/", "Foo2"},
+ {"http://foo1.com/", u"Foo1"},
+ {"http://foo2.com/", u"Foo2"},
};
const TestCaseItem kTestCase3[] = {
- {"http://foo1.com/", "Foo1"},
- {"http://foo2.com/", "Foo2"},
- {"http://foo3.com/", "Foo3"},
+ {"http://foo1.com/", u"Foo1"},
+ {"http://foo2.com/", u"Foo2"},
+ {"http://foo3.com/", u"Foo3"},
};
const TestCaseItem kTestCaseMax[] = {
- {"http://foo1.com/", "Foo1"}, {"http://foo2.com/", "Foo2"},
- {"http://foo3.com/", "Foo3"}, {"http://foo4.com/", "Foo4"},
- {"http://foo5.com/", "Foo5"}, {"http://foo6.com/", "Foo6"},
- {"http://foo7.com/", "Foo7"}, {"http://foo8.com/", "Foo8"},
- {"http://foo9.com/", "Foo9"}, {"http://foo10.com/", "Foo10"},
+ {"http://foo1.com/", u"Foo1"}, {"http://foo2.com/", u"Foo2"},
+ {"http://foo3.com/", u"Foo3"}, {"http://foo4.com/", u"Foo4"},
+ {"http://foo5.com/", u"Foo5"}, {"http://foo6.com/", u"Foo6"},
+ {"http://foo7.com/", u"Foo7"}, {"http://foo8.com/", u"Foo8"},
+ {"http://foo9.com/", u"Foo9"}, {"http://foo10.com/", u"Foo10"},
};
const char kTestTitle[] = "Test";
+const char16_t kTestTitle16[] = u"Test";
const char kTestUrl[] = "http://test.com/";
base::Value::ListStorage FillTestListStorage(const char* url,
@@ -62,10 +63,10 @@ base::Value::ListStorage FillTestListStorage(const char* url,
return new_link_list;
}
-void AddTile(NTPTilesVector* tiles, const char* url, const char* title) {
+void AddTile(NTPTilesVector* tiles, const char* url, const char16_t* title) {
NTPTile tile;
tile.url = GURL(url);
- tile.title = base::UTF8ToUTF16(title);
+ tile.title = title;
tiles->push_back(std::move(tile));
}
@@ -80,8 +81,7 @@ NTPTilesVector FillTestTiles(base::span<const TestCaseItem> test_cases) {
std::vector<Link> FillTestLinks(base::span<const TestCaseItem> test_cases) {
std::vector<Link> links;
for (const auto& test_case : test_cases) {
- links.emplace_back(
- Link{GURL(test_case.url), base::UTF8ToUTF16(test_case.title), true});
+ links.emplace_back(Link{GURL(test_case.url), test_case.title, true});
}
return links;
}
@@ -160,10 +160,8 @@ TEST_F(CustomLinksManagerImplTest, AddLink) {
// Add link.
std::vector<Link> expected_links = initial_links;
- expected_links.emplace_back(
- Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), false});
- EXPECT_TRUE(
- custom_links_->AddLink(GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle)));
+ expected_links.emplace_back(Link{GURL(kTestUrl), kTestTitle16, false});
+ EXPECT_TRUE(custom_links_->AddLink(GURL(kTestUrl), kTestTitle16));
EXPECT_EQ(expected_links, custom_links_->GetLinks());
}
@@ -174,8 +172,7 @@ TEST_F(CustomLinksManagerImplTest, AddLinkWhenAtMaxLinks) {
ASSERT_EQ(initial_links, custom_links_->GetLinks());
// Try to add link. This should fail and not modify the list.
- EXPECT_FALSE(
- custom_links_->AddLink(GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle)));
+ EXPECT_FALSE(custom_links_->AddLink(GURL(kTestUrl), kTestTitle16));
EXPECT_EQ(initial_links, custom_links_->GetLinks());
}
@@ -186,8 +183,8 @@ TEST_F(CustomLinksManagerImplTest, AddDuplicateLink) {
ASSERT_EQ(initial_links, custom_links_->GetLinks());
// Try to add duplicate link. This should fail and not modify the list.
- EXPECT_FALSE(custom_links_->AddLink(GURL(kTestCase1[0].url),
- base::UTF8ToUTF16(kTestCase1[0].title)));
+ EXPECT_FALSE(
+ custom_links_->AddLink(GURL(kTestCase1[0].url), kTestCase1[0].title));
EXPECT_EQ(initial_links, custom_links_->GetLinks());
}
@@ -200,25 +197,20 @@ TEST_F(CustomLinksManagerImplTest, UpdateLink) {
EXPECT_TRUE(custom_links_->UpdateLink(GURL(kTestCase1[0].url), GURL(kTestUrl),
std::u16string()));
EXPECT_EQ(
- std::vector<Link>({Link{GURL(kTestUrl),
- base::UTF8ToUTF16(kTestCase1[0].title), false}}),
+ std::vector<Link>({Link{GURL(kTestUrl), kTestCase1[0].title, false}}),
custom_links_->GetLinks());
// Update the link's title.
- EXPECT_TRUE(custom_links_->UpdateLink(GURL(kTestUrl), GURL(),
- base::UTF8ToUTF16(kTestTitle)));
- EXPECT_EQ(std::vector<Link>(
- {Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), false}}),
+ EXPECT_TRUE(custom_links_->UpdateLink(GURL(kTestUrl), GURL(), kTestTitle16));
+ EXPECT_EQ(std::vector<Link>({Link{GURL(kTestUrl), kTestTitle16, false}}),
custom_links_->GetLinks());
// Update the link's URL and title.
- EXPECT_TRUE(
- custom_links_->UpdateLink(GURL(kTestUrl), GURL(kTestCase1[0].url),
- base::UTF8ToUTF16(kTestCase1[0].title)));
- EXPECT_EQ(
- std::vector<Link>({Link{GURL(kTestCase1[0].url),
- base::UTF8ToUTF16(kTestCase1[0].title), false}}),
- custom_links_->GetLinks());
+ EXPECT_TRUE(custom_links_->UpdateLink(GURL(kTestUrl), GURL(kTestCase1[0].url),
+ kTestCase1[0].title));
+ EXPECT_EQ(std::vector<Link>(
+ {Link{GURL(kTestCase1[0].url), kTestCase1[0].title, false}}),
+ custom_links_->GetLinks());
}
TEST_F(CustomLinksManagerImplTest, UpdateLinkWithInvalidParams) {
@@ -229,8 +221,7 @@ TEST_F(CustomLinksManagerImplTest, UpdateLinkWithInvalidParams) {
// Try to update a link that does not exist. This should fail and not modify
// the list.
- EXPECT_FALSE(custom_links_->UpdateLink(GURL(kTestUrl), GURL(),
- base::UTF8ToUTF16(kTestTitle)));
+ EXPECT_FALSE(custom_links_->UpdateLink(GURL(kTestUrl), GURL(), kTestTitle16));
EXPECT_EQ(initial_links, custom_links_->GetLinks());
// Try to pass empty params. This should fail and not modify the list.
@@ -239,8 +230,7 @@ TEST_F(CustomLinksManagerImplTest, UpdateLinkWithInvalidParams) {
EXPECT_EQ(initial_links, custom_links_->GetLinks());
// Try to pass an invalid URL. This should fail and not modify the list.
- EXPECT_FALSE(custom_links_->UpdateLink(GURL("test"), GURL(),
- base::UTF8ToUTF16(kTestTitle)));
+ EXPECT_FALSE(custom_links_->UpdateLink(GURL("test"), GURL(), kTestTitle16));
EXPECT_EQ(initial_links, custom_links_->GetLinks());
EXPECT_FALSE(custom_links_->UpdateLink(GURL(kTestCase1[0].url), GURL("test"),
std::u16string()));
@@ -288,25 +278,19 @@ TEST_F(CustomLinksManagerImplTest, ReorderLink) {
// Move the last link to the front.
EXPECT_TRUE(custom_links_->ReorderLink(GURL(kTestCase3[2].url), (size_t)0));
- EXPECT_EQ(
- std::vector<Link>({Link{GURL(kTestCase3[2].url),
- base::UTF8ToUTF16(kTestCase3[2].title), true},
- Link{GURL(kTestCase3[0].url),
- base::UTF8ToUTF16(kTestCase3[0].title), true},
- Link{GURL(kTestCase3[1].url),
- base::UTF8ToUTF16(kTestCase3[1].title), true}}),
- custom_links_->GetLinks());
+ EXPECT_EQ(std::vector<Link>(
+ {Link{GURL(kTestCase3[2].url), kTestCase3[2].title, true},
+ Link{GURL(kTestCase3[0].url), kTestCase3[0].title, true},
+ Link{GURL(kTestCase3[1].url), kTestCase3[1].title, true}}),
+ custom_links_->GetLinks());
// Move the same link to the right.
EXPECT_TRUE(custom_links_->ReorderLink(GURL(kTestCase3[2].url), (size_t)1));
- EXPECT_EQ(
- std::vector<Link>({Link{GURL(kTestCase3[0].url),
- base::UTF8ToUTF16(kTestCase3[0].title), true},
- Link{GURL(kTestCase3[2].url),
- base::UTF8ToUTF16(kTestCase3[2].title), true},
- Link{GURL(kTestCase3[1].url),
- base::UTF8ToUTF16(kTestCase3[1].title), true}}),
- custom_links_->GetLinks());
+ EXPECT_EQ(std::vector<Link>(
+ {Link{GURL(kTestCase3[0].url), kTestCase3[0].title, true},
+ Link{GURL(kTestCase3[2].url), kTestCase3[2].title, true},
+ Link{GURL(kTestCase3[1].url), kTestCase3[1].title, true}}),
+ custom_links_->GetLinks());
// Move the same link to the end.
EXPECT_TRUE(custom_links_->ReorderLink(GURL(kTestCase3[2].url), (size_t)2));
@@ -316,10 +300,9 @@ TEST_F(CustomLinksManagerImplTest, ReorderLink) {
TEST_F(CustomLinksManagerImplTest, DeleteLink) {
// Initialize.
NTPTilesVector initial_tiles;
- AddTile(&initial_tiles, kTestUrl, kTestTitle);
+ AddTile(&initial_tiles, kTestUrl, kTestTitle16);
ASSERT_TRUE(custom_links_->Initialize(initial_tiles));
- ASSERT_EQ(std::vector<Link>(
- {Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), true}}),
+ ASSERT_EQ(std::vector<Link>({Link{GURL(kTestUrl), kTestTitle16, true}}),
custom_links_->GetLinks());
// Delete link.
@@ -348,12 +331,10 @@ TEST_F(CustomLinksManagerImplTest, UndoAddLink) {
EXPECT_EQ(initial_links, custom_links_->GetLinks());
// Add link.
- EXPECT_TRUE(
- custom_links_->AddLink(GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle)));
+ EXPECT_TRUE(custom_links_->AddLink(GURL(kTestUrl), kTestTitle16));
EXPECT_EQ(std::vector<Link>(
- {Link{GURL(kTestCase1[0].url),
- base::UTF8ToUTF16(kTestCase1[0].title), true},
- {Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), false}}}),
+ {Link{GURL(kTestCase1[0].url), kTestCase1[0].title, true},
+ {Link{GURL(kTestUrl), kTestTitle16, false}}}),
custom_links_->GetLinks());
// Undo add link.
@@ -375,8 +356,7 @@ TEST_F(CustomLinksManagerImplTest, UndoUpdateLink) {
EXPECT_TRUE(custom_links_->UpdateLink(GURL(kTestCase1[0].url), GURL(kTestUrl),
std::u16string()));
EXPECT_EQ(
- std::vector<Link>({Link{GURL(kTestUrl),
- base::UTF8ToUTF16(kTestCase1[0].title), false}}),
+ std::vector<Link>({Link{GURL(kTestUrl), kTestCase1[0].title, false}}),
custom_links_->GetLinks());
// Undo update link.
@@ -384,11 +364,11 @@ TEST_F(CustomLinksManagerImplTest, UndoUpdateLink) {
EXPECT_EQ(initial_links, custom_links_->GetLinks());
// Update the link's title.
- EXPECT_TRUE(custom_links_->UpdateLink(GURL(kTestCase1[0].url), GURL(),
- base::UTF8ToUTF16(kTestTitle)));
- EXPECT_EQ(std::vector<Link>({Link{GURL(kTestCase1[0].url),
- base::UTF8ToUTF16(kTestTitle), false}}),
- custom_links_->GetLinks());
+ EXPECT_TRUE(
+ custom_links_->UpdateLink(GURL(kTestCase1[0].url), GURL(), kTestTitle16));
+ EXPECT_EQ(
+ std::vector<Link>({Link{GURL(kTestCase1[0].url), kTestTitle16, false}}),
+ custom_links_->GetLinks());
// Undo update link.
EXPECT_TRUE(custom_links_->UndoAction());
@@ -402,9 +382,8 @@ TEST_F(CustomLinksManagerImplTest, UndoUpdateLink) {
TEST_F(CustomLinksManagerImplTest, UndoDeleteLink) {
// Initialize.
NTPTilesVector initial_tiles;
- AddTile(&initial_tiles, kTestUrl, kTestTitle);
- std::vector<Link> expected_links(
- {Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), true}});
+ AddTile(&initial_tiles, kTestUrl, kTestTitle16);
+ std::vector<Link> expected_links({Link{GURL(kTestUrl), kTestTitle16, true}});
ASSERT_TRUE(custom_links_->Initialize(initial_tiles));
ASSERT_EQ(expected_links, custom_links_->GetLinks());
@@ -423,10 +402,8 @@ TEST_F(CustomLinksManagerImplTest, UndoDeleteLinkAfterAdd) {
ASSERT_TRUE(custom_links_->GetLinks().empty());
// Add link.
- std::vector<Link> expected_links(
- {Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), false}});
- ASSERT_TRUE(
- custom_links_->AddLink(GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle)));
+ std::vector<Link> expected_links({Link{GURL(kTestUrl), kTestTitle16, false}});
+ ASSERT_TRUE(custom_links_->AddLink(GURL(kTestUrl), kTestTitle16));
ASSERT_EQ(expected_links, custom_links_->GetLinks());
// Delete link.
@@ -463,11 +440,10 @@ TEST_F(CustomLinksManagerImplTest, ShouldDeleteMostVisitedOnHistoryDeletion) {
/*expired=*/false,
{history::URLRow(GURL(kTestCase2[1].url))},
/*favicon_urls=*/std::set<GURL>(),
- /*restrict_urls=*/base::nullopt));
- EXPECT_EQ(
- std::vector<Link>({Link{GURL(kTestCase2[0].url),
- base::UTF8ToUTF16(kTestCase2[0].title), true}}),
- custom_links_->GetLinks());
+ /*restrict_urls=*/absl::nullopt));
+ EXPECT_EQ(std::vector<Link>(
+ {Link{GURL(kTestCase2[0].url), kTestCase2[0].title, true}}),
+ custom_links_->GetLinks());
task_environment_.RunUntilIdle();
}
@@ -491,7 +467,7 @@ TEST_F(CustomLinksManagerImplTest,
history::DeletionInfo(history::DeletionTimeRange::AllTime(),
/*expired=*/false, history::URLRows(),
/*favicon_urls=*/std::set<GURL>(),
- /*restrict_urls=*/base::nullopt));
+ /*restrict_urls=*/absl::nullopt));
EXPECT_TRUE(custom_links_->GetLinks().empty());
task_environment_.RunUntilIdle();
@@ -520,7 +496,7 @@ TEST_F(CustomLinksManagerImplTest, ShouldDeleteOnHistoryDeletionAfterShutdown) {
history::DeletionInfo(history::DeletionTimeRange::AllTime(),
/*expired=*/false, history::URLRows(),
/*favicon_urls=*/std::set<GURL>(),
- /*restrict_urls=*/base::nullopt));
+ /*restrict_urls=*/absl::nullopt));
EXPECT_TRUE(custom_links_->GetLinks().empty());
task_environment_.RunUntilIdle();
@@ -534,14 +510,12 @@ TEST_F(CustomLinksManagerImplTest, ShouldNotDeleteCustomLinkOnHistoryDeletion) {
// Initialize.
std::vector<Link> links_after_add(
- {Link{GURL(kTestCase1[0].url), base::UTF8ToUTF16(kTestCase1[0].title),
- true},
- Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), false}});
+ {Link{GURL(kTestCase1[0].url), kTestCase1[0].title, true},
+ Link{GURL(kTestUrl), kTestTitle16, false}});
ASSERT_TRUE(custom_links_->Initialize(FillTestTiles(kTestCase1)));
ASSERT_EQ(FillTestLinks(kTestCase1), custom_links_->GetLinks());
// Add link.
- ASSERT_TRUE(
- custom_links_->AddLink(GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle)));
+ ASSERT_TRUE(custom_links_->AddLink(GURL(kTestUrl), kTestTitle16));
ASSERT_EQ(links_after_add, custom_links_->GetLinks());
// Try to delete the added link. This should fail and not modify the list.
@@ -551,7 +525,7 @@ TEST_F(CustomLinksManagerImplTest, ShouldNotDeleteCustomLinkOnHistoryDeletion) {
history::DeletionTimeRange::Invalid(),
/*expired=*/false, {history::URLRow(GURL(kTestUrl))},
/*favicon_urls=*/std::set<GURL>(),
- /*restrict_urls=*/base::nullopt));
+ /*restrict_urls=*/absl::nullopt));
EXPECT_EQ(links_after_add, custom_links_->GetLinks());
// Delete all Most Visited links.
@@ -562,9 +536,8 @@ TEST_F(CustomLinksManagerImplTest, ShouldNotDeleteCustomLinkOnHistoryDeletion) {
history::DeletionInfo(history::DeletionTimeRange::AllTime(),
/*expired=*/false, history::URLRows(),
/*favicon_urls=*/std::set<GURL>(),
- /*restrict_urls=*/base::nullopt));
- EXPECT_EQ(std::vector<Link>(
- {Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), false}}),
+ /*restrict_urls=*/absl::nullopt));
+ EXPECT_EQ(std::vector<Link>({Link{GURL(kTestUrl), kTestTitle16, false}}),
custom_links_->GetLinks());
task_environment_.RunUntilIdle();
@@ -588,7 +561,7 @@ TEST_F(CustomLinksManagerImplTest, ShouldIgnoreHistoryExpiredDeletions) {
history::DeletionInfo(history::DeletionTimeRange::AllTime(),
/*expired=*/true, history::URLRows(),
/*favicon_urls=*/std::set<GURL>(),
- /*restrict_urls=*/base::nullopt));
+ /*restrict_urls=*/absl::nullopt));
static_cast<history::HistoryServiceObserver*>(custom_links_.get())
->OnURLsDeleted(
// /*history_service=*/nullptr,
@@ -597,7 +570,7 @@ TEST_F(CustomLinksManagerImplTest, ShouldIgnoreHistoryExpiredDeletions) {
/*expired=*/true,
{history::URLRow(GURL(kTestCase1[0].url))},
/*favicon_urls=*/std::set<GURL>(),
- /*restrict_urls=*/base::nullopt));
+ /*restrict_urls=*/absl::nullopt));
EXPECT_EQ(initial_links, custom_links_->GetLinks());
@@ -636,11 +609,9 @@ TEST_F(CustomLinksManagerImplTest, ShouldNotUndoAfterHistoryDeletion) {
ASSERT_EQ(FillTestLinks(kTestCase1), custom_links_->GetLinks());
// Add link.
std::vector<Link> links_after_add(
- {Link{GURL(kTestCase1[0].url), base::UTF8ToUTF16(kTestCase1[0].title),
- true},
- Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), false}});
- ASSERT_TRUE(
- custom_links_->AddLink(GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle)));
+ {Link{GURL(kTestCase1[0].url), kTestCase1[0].title, true},
+ Link{GURL(kTestUrl), kTestTitle16, false}});
+ ASSERT_TRUE(custom_links_->AddLink(GURL(kTestUrl), kTestTitle16));
ASSERT_EQ(links_after_add, custom_links_->GetLinks());
// Try an empty history deletion. This should do nothing.
@@ -669,12 +640,11 @@ TEST_F(CustomLinksManagerImplTest, UpdateListAfterRemoteChange) {
// Modifying ourselves should not notify.
EXPECT_CALL(callback, Run()).Times(0);
- EXPECT_TRUE(custom_links_->AddLink(GURL(kTestCase1[0].url),
- base::UTF8ToUTF16(kTestCase1[0].title)));
- EXPECT_EQ(
- std::vector<Link>({Link{GURL(kTestCase1[0].url),
- base::UTF8ToUTF16(kTestCase1[0].title), false}}),
- custom_links_->GetLinks());
+ EXPECT_TRUE(
+ custom_links_->AddLink(GURL(kTestCase1[0].url), kTestCase1[0].title));
+ EXPECT_EQ(std::vector<Link>(
+ {Link{GURL(kTestCase1[0].url), kTestCase1[0].title, false}}),
+ custom_links_->GetLinks());
// Modify the preference. This should notify and update the current list of
// links.
@@ -682,8 +652,7 @@ TEST_F(CustomLinksManagerImplTest, UpdateListAfterRemoteChange) {
prefs_.SetUserPref(prefs::kCustomLinksList,
std::make_unique<base::Value>(
FillTestListStorage(kTestUrl, kTestTitle, true)));
- EXPECT_EQ(std::vector<Link>(
- {Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), true}}),
+ EXPECT_EQ(std::vector<Link>({Link{GURL(kTestUrl), kTestTitle16, true}}),
custom_links_->GetLinks());
}
@@ -703,8 +672,7 @@ TEST_F(CustomLinksManagerImplTest, InitializeListAfterRemoteChange) {
std::make_unique<base::Value>(
FillTestListStorage(kTestUrl, kTestTitle, false)));
EXPECT_TRUE(custom_links_->IsInitialized());
- EXPECT_EQ(std::vector<Link>(
- {Link{GURL(kTestUrl), base::UTF8ToUTF16(kTestTitle), false}}),
+ EXPECT_EQ(std::vector<Link>({Link{GURL(kTestUrl), kTestTitle16, false}}),
custom_links_->GetLinks());
}
diff --git a/chromium/components/ntp_tiles/custom_links_store_unittest.cc b/chromium/components/ntp_tiles/custom_links_store_unittest.cc
index efa4cfa186f..36aa91319ef 100644
--- a/chromium/components/ntp_tiles/custom_links_store_unittest.cc
+++ b/chromium/components/ntp_tiles/custom_links_store_unittest.cc
@@ -19,8 +19,8 @@ namespace ntp_tiles {
namespace {
-const char kTestTitle1[] = "Foo1";
-const char kTestTitle2[] = "Foo2";
+const char16_t kTestTitle1[] = u"Foo1";
+const char16_t kTestTitle2[] = u"Foo2";
const char kTestUrl1[] = "http://foo1.com/";
const char kTestUrl2[] = "http://foo2.com/";
@@ -41,8 +41,8 @@ class CustomLinksStoreTest : public testing::Test {
};
TEST_F(CustomLinksStoreTest, StoreAndRetrieveLinks) {
- std::vector<CustomLinksManager::Link> initial_links({CustomLinksManager::Link{
- GURL(kTestUrl1), base::UTF8ToUTF16(kTestTitle1), true}});
+ std::vector<CustomLinksManager::Link> initial_links(
+ {CustomLinksManager::Link{GURL(kTestUrl1), kTestTitle1, true}});
custom_links_store_->StoreLinks(initial_links);
std::vector<CustomLinksManager::Link> retrieved_links =
@@ -52,10 +52,8 @@ TEST_F(CustomLinksStoreTest, StoreAndRetrieveLinks) {
TEST_F(CustomLinksStoreTest, StoreEmptyList) {
std::vector<CustomLinksManager::Link> populated_links(
- {CustomLinksManager::Link{GURL(kTestUrl1), base::UTF8ToUTF16(kTestTitle1),
- false},
- CustomLinksManager::Link{GURL(kTestUrl2), base::UTF8ToUTF16(kTestTitle2),
- true}});
+ {CustomLinksManager::Link{GURL(kTestUrl1), kTestTitle1, false},
+ CustomLinksManager::Link{GURL(kTestUrl2), kTestTitle2, true}});
custom_links_store_->StoreLinks(populated_links);
std::vector<CustomLinksManager::Link> retrieved_links =
@@ -68,8 +66,8 @@ TEST_F(CustomLinksStoreTest, StoreEmptyList) {
}
TEST_F(CustomLinksStoreTest, ClearLinks) {
- std::vector<CustomLinksManager::Link> initial_links({CustomLinksManager::Link{
- GURL(kTestUrl1), base::UTF8ToUTF16(kTestTitle1)}});
+ std::vector<CustomLinksManager::Link> initial_links(
+ {CustomLinksManager::Link{GURL(kTestUrl1), kTestTitle1}});
custom_links_store_->StoreLinks(initial_links);
std::vector<CustomLinksManager::Link> retrieved_links =
@@ -83,10 +81,8 @@ TEST_F(CustomLinksStoreTest, ClearLinks) {
TEST_F(CustomLinksStoreTest, LinksSavedAfterShutdown) {
std::vector<CustomLinksManager::Link> initial_links(
- {CustomLinksManager::Link{GURL(kTestUrl1), base::UTF8ToUTF16(kTestTitle1),
- false},
- CustomLinksManager::Link{GURL(kTestUrl2), base::UTF8ToUTF16(kTestTitle2),
- true}});
+ {CustomLinksManager::Link{GURL(kTestUrl1), kTestTitle1, false},
+ CustomLinksManager::Link{GURL(kTestUrl2), kTestTitle2, true}});
custom_links_store_->StoreLinks(initial_links);
std::vector<CustomLinksManager::Link> retrieved_links =
diff --git a/chromium/components/ntp_tiles/icon_cacher_impl.cc b/chromium/components/ntp_tiles/icon_cacher_impl.cc
index 84c137e92ac..a0bcf179b9b 100644
--- a/chromium/components/ntp_tiles/icon_cacher_impl.cc
+++ b/chromium/components/ntp_tiles/icon_cacher_impl.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_piece.h"
#include "components/favicon/core/favicon_service.h"
#include "components/favicon/core/favicon_util.h"
#include "components/favicon/core/large_icon_service.h"
@@ -181,7 +182,7 @@ IconCacherImpl::MaybeProvideDefaultIcon(
const PopularSites::Site& site,
base::OnceClosure preliminary_icon_available) {
if (site.default_icon_resource < 0) {
- return std::unique_ptr<CancelableImageCallback>();
+ return nullptr;
}
std::unique_ptr<CancelableImageCallback> preliminary_callback(
new CancelableImageCallback(
@@ -189,9 +190,8 @@ IconCacherImpl::MaybeProvideDefaultIcon(
weak_ptr_factory_.GetWeakPtr(), site,
std::move(preliminary_icon_available))));
image_fetcher_->GetImageDecoder()->DecodeImage(
- ui::ResourceBundle::GetSharedInstance()
- .GetRawDataResource(site.default_icon_resource)
- .as_string(),
+ std::string(ui::ResourceBundle::GetSharedInstance().GetRawDataResource(
+ site.default_icon_resource)),
gfx::Size(kDesiredFrameSize, kDesiredFrameSize),
preliminary_callback->callback());
return preliminary_callback;
diff --git a/chromium/components/ntp_tiles/icon_cacher_impl.h b/chromium/components/ntp_tiles/icon_cacher_impl.h
index 768c076acfd..96e7a7244e7 100644
--- a/chromium/components/ntp_tiles/icon_cacher_impl.h
+++ b/chromium/components/ntp_tiles/icon_cacher_impl.h
@@ -7,7 +7,6 @@
#include <memory>
#include <set>
-#include <string>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/components/ntp_tiles/most_visited_sites.cc b/chromium/components/ntp_tiles/most_visited_sites.cc
index bed76a2488b..c0ed44d2f1b 100644
--- a/chromium/components/ntp_tiles/most_visited_sites.cc
+++ b/chromium/components/ntp_tiles/most_visited_sites.cc
@@ -134,9 +134,9 @@ MostVisitedSites::MostVisitedSites(
custom_links_(std::move(custom_links)),
icon_cacher_(std::move(icon_cacher)),
supervisor_(std::move(supervisor)),
- observer_(nullptr),
max_num_sites_(0u),
- mv_source_(TileSource::TOP_SITES) {
+ mv_source_(TileSource::TOP_SITES),
+ is_observing_(false) {
DCHECK(prefs_);
// top_sites_ can be null in tests.
// TODO(sfiera): have iOS use a dummy TopSites in its tests.
@@ -148,6 +148,7 @@ MostVisitedSites::MostVisitedSites(
MostVisitedSites::~MostVisitedSites() {
if (supervisor_)
supervisor_->SetObserver(nullptr);
+ observers_.Clear();
}
// static
@@ -199,40 +200,46 @@ void MostVisitedSites::SetExploreSitesClient(
explore_sites_client_ = std::move(client);
}
-void MostVisitedSites::SetMostVisitedURLsObserver(Observer* observer,
+void MostVisitedSites::AddMostVisitedURLsObserver(Observer* observer,
size_t max_num_sites) {
- DCHECK(observer);
- observer_ = observer;
+ observers_.AddObserver(observer);
+
+ // All observer must provide the same |max_num_sites| value.
+ DCHECK(max_num_sites_ == 0u || max_num_sites_ == max_num_sites);
max_num_sites_ = max_num_sites;
- // The order for this condition is important, ShouldShowPopularSites() should
- // always be called last to keep metrics as relevant as possible.
- if (popular_sites_ && NeedPopularSites(prefs_, GetMaxNumSites()) &&
- ShouldShowPopularSites()) {
- popular_sites_->MaybeStartFetch(
- false, base::BindOnce(&MostVisitedSites::OnPopularSitesDownloaded,
- base::Unretained(this)));
- }
+ // Starts observing the following sources when the first observer is added.
+ if (!is_observing_) {
+ is_observing_ = true;
+ // The order for this condition is important, ShouldShowPopularSites()
+ // should always be called last to keep metrics as relevant as possible.
+ if (popular_sites_ && NeedPopularSites(prefs_, GetMaxNumSites()) &&
+ ShouldShowPopularSites()) {
+ popular_sites_->MaybeStartFetch(
+ false, base::BindOnce(&MostVisitedSites::OnPopularSitesDownloaded,
+ base::Unretained(this)));
+ }
- if (top_sites_) {
- // Register as TopSitesObserver so that we can update ourselves when the
- // TopSites changes.
- top_sites_observation_.Observe(top_sites_.get());
- }
+ if (top_sites_) {
+ // Register as TopSitesObserver so that we can update ourselves when the
+ // TopSites changes.
+ top_sites_observation_.Observe(top_sites_.get());
+ }
- if (repeatable_queries_) {
- repeatable_queries_observation_.Observe(repeatable_queries_);
- }
+ if (repeatable_queries_) {
+ repeatable_queries_observation_.Observe(repeatable_queries_);
+ }
- if (custom_links_) {
- custom_links_subscription_ =
- custom_links_->RegisterCallbackForOnChanged(base::BindRepeating(
- &MostVisitedSites::OnCustomLinksChanged, base::Unretained(this)));
- }
+ if (custom_links_) {
+ custom_links_subscription_ =
+ custom_links_->RegisterCallbackForOnChanged(base::BindRepeating(
+ &MostVisitedSites::OnCustomLinksChanged, base::Unretained(this)));
+ }
- suggestions_subscription_ = suggestions_service_->AddCallback(
- base::BindRepeating(&MostVisitedSites::OnSuggestionsProfileChanged,
- base::Unretained(this)));
+ suggestions_subscription_ = suggestions_service_->AddCallback(
+ base::BindRepeating(&MostVisitedSites::OnSuggestionsProfileChanged,
+ base::Unretained(this)));
+ }
// Immediately build the current set of tiles, getting suggestions from the
// SuggestionsService's cache or, if that is empty, sites from TopSites.
@@ -241,6 +248,10 @@ void MostVisitedSites::SetMostVisitedURLsObserver(Observer* observer,
Refresh();
}
+void MostVisitedSites::RemoveMostVisitedURLsObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
void MostVisitedSites::Refresh() {
if (top_sites_) {
// TopSites updates itself after a delay. To ensure up-to-date results,
@@ -718,7 +729,7 @@ NTPTilesVector MostVisitedSites::CreatePopularSitesTiles(
void MostVisitedSites::OnHomepageTitleDetermined(
NTPTilesVector tiles,
- const base::Optional<std::u16string>& title) {
+ const absl::optional<std::u16string>& title) {
if (!title.has_value())
return; // If there is no title, the most recent tile was already sent out.
@@ -769,9 +780,9 @@ NTPTilesVector MostVisitedSites::InsertHomeTile(
return new_tiles;
}
-base::Optional<NTPTile> MostVisitedSites::CreateExploreSitesTile() {
+absl::optional<NTPTile> MostVisitedSites::CreateExploreSitesTile() {
if (!explore_sites_client_)
- return base::nullopt;
+ return absl::nullopt;
NTPTile explore_sites_tile;
explore_sites_tile.url = explore_sites_client_->GetExploreSitesUrl();
@@ -843,12 +854,13 @@ void MostVisitedSites::InitiateNotificationForNewTiles(
void MostVisitedSites::MergeMostVisitedTiles(NTPTilesVector personal_tiles) {
std::set<std::string> used_hosts;
- base::Optional<NTPTile> explore_tile = CreateExploreSitesTile();
+ absl::optional<NTPTile> explore_tile = CreateExploreSitesTile();
size_t num_actual_tiles = explore_tile ? 1 : 0;
// The explore sites tile may have taken a space that was utilized by the
// personal tiles.
- if (personal_tiles.size() + num_actual_tiles > GetMaxNumSites()) {
+ if (!personal_tiles.empty() &&
+ personal_tiles.size() + num_actual_tiles > GetMaxNumSites()) {
personal_tiles.pop_back();
}
AddToHostsAndTotalCount(personal_tiles, &used_hosts, &num_actual_tiles);
@@ -884,10 +896,12 @@ void MostVisitedSites::SaveTilesAndNotify(
}
}
prefs_->SetInteger(prefs::kNumPersonalTiles, num_personal_tiles);
- if (!observer_)
+
+ if (observers_.empty())
return;
sections[SectionType::PERSONALIZED] = *current_tiles_;
- observer_->OnURLsAvailable(sections);
+ for (auto& observer : observers_)
+ observer.OnURLsAvailable(sections);
}
// static
@@ -895,7 +909,7 @@ NTPTilesVector MostVisitedSites::MergeTiles(
NTPTilesVector personal_tiles,
NTPTilesVector allowlist_tiles,
NTPTilesVector popular_tiles,
- base::Optional<NTPTile> explore_tile) {
+ absl::optional<NTPTile> explore_tile) {
NTPTilesVector merged_tiles;
std::move(personal_tiles.begin(), personal_tiles.end(),
std::back_inserter(merged_tiles));
@@ -925,7 +939,8 @@ void MostVisitedSites::OnPopularSitesDownloaded(bool success) {
}
void MostVisitedSites::OnIconMadeAvailable(const GURL& site_url) {
- observer_->OnIconMadeAvailable(site_url);
+ for (auto& observer : observers_)
+ observer.OnIconMadeAvailable(site_url);
}
void MostVisitedSites::TopSitesLoaded(TopSites* top_sites) {}
diff --git a/chromium/components/ntp_tiles/most_visited_sites.h b/chromium/components/ntp_tiles/most_visited_sites.h
index 63849af907b..9ccb7b17292 100644
--- a/chromium/components/ntp_tiles/most_visited_sites.h
+++ b/chromium/components/ntp_tiles/most_visited_sites.h
@@ -20,7 +20,8 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
+#include "base/observer_list.h"
+#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
#include "components/history/core/browser/history_types.h"
#include "components/history/core/browser/top_sites.h"
@@ -34,6 +35,7 @@
#include "components/search/repeatable_queries/repeatable_queries_service_observer.h"
#include "components/suggestions/proto/suggestions.pb.h"
#include "components/suggestions/suggestions_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace user_prefs {
@@ -88,15 +90,12 @@ class MostVisitedSites : public history::TopSitesObserver,
public RepeatableQueriesServiceObserver {
public:
// The observer to be notified when the list of most visited sites changes.
- class Observer {
+ class Observer : public base::CheckedObserver {
public:
// |sections| must at least contain the PERSONALIZED section.
virtual void OnURLsAvailable(
const std::map<SectionType, NTPTilesVector>& sections) = 0;
virtual void OnIconMadeAvailable(const GURL& site_url) = 0;
-
- protected:
- virtual ~Observer() {}
};
// This interface delegates the retrieval of the homepage to the
@@ -104,7 +103,7 @@ class MostVisitedSites : public history::TopSitesObserver,
class HomepageClient {
public:
using TitleCallback =
- base::OnceCallback<void(const base::Optional<std::u16string>& title)>;
+ base::OnceCallback<void(const absl::optional<std::u16string>& title)>;
virtual ~HomepageClient() = default;
virtual bool IsHomepageTileEnabled() const = 0;
@@ -148,11 +147,20 @@ class MostVisitedSites : public history::TopSitesObserver,
PopularSites* popular_sites() { return popular_sites_.get(); }
MostVisitedSitesSupervisor* supervisor() { return supervisor_.get(); }
- // Sets the observer, and immediately fetches the current suggestions.
+ // Adds the observer and immediately fetches the current suggestions.
+ // All observers will be notified when the suggestions are fetched.
+ //
+ // Note: only observers that require the same |max_num_sites| could observe
+ // the same MostVisitedSites instance. Otherwise, a new Instance should be
+ // created for the observer.
+ //
// Does not take ownership of |observer|, which must outlive this object and
// must not be null. |max_num_sites| indicates the the maximum number of most
// visited sites to return.
- void SetMostVisitedURLsObserver(Observer* observer, size_t max_num_sites);
+ void AddMostVisitedURLsObserver(Observer* observer, size_t max_num_sites);
+
+ // Removes the observer.
+ void RemoveMostVisitedURLsObserver(Observer* observer);
// Sets the client that provides platform-specific homepage preferences.
// When used to replace an existing client, the new client will first be
@@ -229,7 +237,7 @@ class MostVisitedSites : public history::TopSitesObserver,
static NTPTilesVector MergeTiles(NTPTilesVector personal_tiles,
NTPTilesVector allowlist_tiles,
NTPTilesVector popular_tiles,
- base::Optional<NTPTile> explore_tile);
+ absl::optional<NTPTile> explore_tile);
private:
FRIEND_TEST_ALL_PREFIXES(MostVisitedSitesTest,
@@ -336,10 +344,10 @@ class MostVisitedSites : public history::TopSitesObserver,
// Creates a tile for the Explore Sites page, if enabled. The tile is added to
// the front of the list.
- base::Optional<NTPTile> CreateExploreSitesTile();
+ absl::optional<NTPTile> CreateExploreSitesTile();
void OnHomepageTitleDetermined(NTPTilesVector tiles,
- const base::Optional<std::u16string>& title);
+ const absl::optional<std::u16string>& title);
// Returns true if there is a valid homepage that can be pinned as tile.
bool ShouldAddHomeTile() const;
@@ -364,7 +372,7 @@ class MostVisitedSites : public history::TopSitesObserver,
std::unique_ptr<HomepageClient> homepage_client_;
std::unique_ptr<ExploreSitesClient> explore_sites_client_;
- Observer* observer_;
+ base::ObserverList<Observer> observers_;
// The maximum number of most visited sites to return.
// Do not use directly. Use GetMaxNumSites() instead.
@@ -394,7 +402,10 @@ class MostVisitedSites : public history::TopSitesObserver,
// Current set of tiles. Optional so that the observer can be notified
// whenever it changes, including possibily an initial change from
// !current_tiles_.has_value() to current_tiles_->empty().
- base::Optional<NTPTilesVector> current_tiles_;
+ absl::optional<NTPTilesVector> current_tiles_;
+
+ // Whether has started observing data sources.
+ bool is_observing_;
// For callbacks may be run after destruction, used exclusively for TopSites
// (since it's used to detect whether there's a query in flight).
diff --git a/chromium/components/ntp_tiles/most_visited_sites_unittest.cc b/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
index db1aa660af4..14c390a4f2d 100644
--- a/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
+++ b/chromium/components/ntp_tiles/most_visited_sites_unittest.cc
@@ -83,21 +83,20 @@ using testing::SizeIs;
using testing::StrictMock;
const char kHomepageUrl[] = "http://homepa.ge/";
-const char kHomepageTitle[] = "Homepage";
+const char16_t kHomepageTitle[] = u"Homepage";
const char kTestExploreUrl[] = "https://example.com/";
-const char kTestExploreTitle[] = "Example";
+const char16_t kTestExploreTitle[] = u"Example";
-std::string PrintTile(const std::string& title,
+std::string PrintTile(const std::u16string& title,
const std::string& url,
TileSource source) {
- return std::string("has title \"") + title + std::string("\" and url \"") +
- url + std::string("\" and source ") +
+ return std::string("has title \"") + base::UTF16ToUTF8(title) +
+ std::string("\" and url \"") + url + std::string("\" and source ") +
testing::PrintToString(static_cast<int>(source));
}
MATCHER_P3(MatchesTile, title, url, source, PrintTile(title, url, source)) {
- return arg.title == base::ASCIIToUTF16(title) && arg.url == GURL(url) &&
- arg.source == source;
+ return arg.title == title && arg.url == GURL(url) && arg.source == source;
}
std::string PrintTileSource(TileSource source) {
@@ -119,8 +118,7 @@ MATCHER_P3(LastTileIs,
return false;
const NTPTile& last = tiles.back();
- return last.title == base::ASCIIToUTF16(title) && last.url == GURL(url) &&
- last.source == source;
+ return last.title == title && last.url == GURL(url) && last.source == source;
}
MATCHER_P3(FirstPersonalizedTileIs,
@@ -132,15 +130,15 @@ MATCHER_P3(FirstPersonalizedTileIs,
return false;
}
const NTPTilesVector& tiles = arg.at(SectionType::PERSONALIZED);
- return !tiles.empty() && tiles[0].title == base::ASCIIToUTF16(title) &&
+ return !tiles.empty() && tiles[0].title == title &&
tiles[0].url == GURL(url) && tiles[0].source == source;
}
-NTPTile MakeTile(const std::string& title,
+NTPTile MakeTile(const std::u16string& title,
const std::string& url,
TileSource source) {
NTPTile tile;
- tile.title = base::ASCIIToUTF16(title);
+ tile.title = title;
tile.url = GURL(url);
tile.source = source;
return tile;
@@ -163,10 +161,10 @@ SuggestionsProfile MakeProfile(
return profile;
}
-MostVisitedURL MakeMostVisitedURL(const std::string& title,
+MostVisitedURL MakeMostVisitedURL(const std::u16string& title,
const std::string& url) {
MostVisitedURL result;
- result.title = base::ASCIIToUTF16(title);
+ result.title = title;
result.url = GURL(url);
return result;
}
@@ -202,7 +200,7 @@ class MockSuggestionsService : public SuggestionsService {
public:
MOCK_METHOD0(FetchSuggestionsData, bool());
MOCK_CONST_METHOD0(GetSuggestionsDataFromCache,
- base::Optional<SuggestionsProfile>());
+ absl::optional<SuggestionsProfile>());
MOCK_METHOD1(
AddCallback,
base::CallbackListSubscription(const ResponseCallback& callback));
@@ -238,14 +236,14 @@ class FakeHomepageClient : public MostVisitedSites::HomepageClient {
void SetHomepageUrl(GURL homepage_url) { homepage_url_ = homepage_url; }
- void SetHomepageTitle(const base::Optional<std::u16string>& homepage_title) {
+ void SetHomepageTitle(const absl::optional<std::u16string>& homepage_title) {
homepage_title_ = homepage_title;
}
private:
bool homepage_tile_enabled_;
GURL homepage_url_;
- base::Optional<std::u16string> homepage_title_;
+ absl::optional<std::u16string> homepage_title_;
};
class FakeExploreSitesClient : public MostVisitedSites::ExploreSitesClient {
@@ -255,7 +253,7 @@ class FakeExploreSitesClient : public MostVisitedSites::ExploreSitesClient {
GURL GetExploreSitesUrl() const override { return GURL(kTestExploreUrl); }
std::u16string GetExploreSitesTitle() const override {
- return base::ASCIIToUTF16(kTestExploreTitle);
+ return kTestExploreTitle;
}
};
@@ -540,6 +538,7 @@ class MostVisitedSitesTest
base::MakeRefCounted<StrictMock<MockTopSites>>();
StrictMock<MockSuggestionsService> mock_suggestions_service_;
StrictMock<MockMostVisitedSitesObserver> mock_observer_;
+ StrictMock<MockMostVisitedSitesObserver> mock_other_observer_;
std::unique_ptr<MostVisitedSites> most_visited_sites_;
base::test::ScopedFeatureList feature_list_;
MockCustomLinksManager* mock_custom_links_;
@@ -569,9 +568,9 @@ TEST_P(MostVisitedSitesTest, ShouldIncludeTileForHomepage) {
.Times(AnyNumber())
.WillRepeatedly(Return(false));
EXPECT_CALL(mock_observer_, OnURLsAvailable(FirstPersonalizedTileIs(
- "", kHomepageUrl, TileSource::HOMEPAGE)));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ u"", kHomepageUrl, TileSource::HOMEPAGE)));
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
}
@@ -583,10 +582,10 @@ TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageWithoutClient) {
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(
Pair(SectionType::PERSONALIZED,
- Not(Contains(MatchesTile("", kHomepageUrl,
+ Not(Contains(MatchesTile(u"", kHomepageUrl,
TileSource::HOMEPAGE)))))));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
}
@@ -596,7 +595,7 @@ TEST_P(MostVisitedSitesTest, ShouldIncludeHomeTileWithUrlBeforeQueryingName) {
// real title was found.
FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
homepage_client->SetHomepageTileEnabled(true);
- homepage_client->SetHomepageTitle(base::UTF8ToUTF16(kHomepageTitle));
+ homepage_client->SetHomepageTitle(kHomepageTitle);
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillRepeatedly(base::test::RunOnceCallback<0>(MostVisitedURLList{}));
@@ -609,7 +608,7 @@ TEST_P(MostVisitedSitesTest, ShouldIncludeHomeTileWithUrlBeforeQueryingName) {
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(
Pair(SectionType::PERSONALIZED,
- Not(Contains(MatchesTile("", kHomepageUrl,
+ Not(Contains(MatchesTile(u"", kHomepageUrl,
TileSource::HOMEPAGE)))))));
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(
@@ -617,8 +616,8 @@ TEST_P(MostVisitedSitesTest, ShouldIncludeHomeTileWithUrlBeforeQueryingName) {
Not(Contains(MatchesTile(kHomepageTitle, kHomepageUrl,
TileSource::HOMEPAGE)))))));
}
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
}
@@ -635,9 +634,9 @@ TEST_P(MostVisitedSitesTest, ShouldUpdateHomepageTileWhenRefreshHomepageTile) {
.Times(AnyNumber())
.WillRepeatedly(Return(false));
EXPECT_CALL(mock_observer_, OnURLsAvailable(FirstPersonalizedTileIs(
- "", kHomepageUrl, TileSource::HOMEPAGE)));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ u"", kHomepageUrl, TileSource::HOMEPAGE)));
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
VerifyAndClearExpectations();
@@ -648,7 +647,7 @@ TEST_P(MostVisitedSitesTest, ShouldUpdateHomepageTileWhenRefreshHomepageTile) {
.WillRepeatedly(base::test::RunOnceCallback<0>(MostVisitedURLList{}));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory()).Times(0);
EXPECT_CALL(mock_observer_, OnURLsAvailable(Not(FirstPersonalizedTileIs(
- "", kHomepageUrl, TileSource::HOMEPAGE))));
+ u"", kHomepageUrl, TileSource::HOMEPAGE))));
most_visited_sites_->RefreshTiles();
base::RunLoop().RunUntilIdle();
}
@@ -666,8 +665,8 @@ TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfNoTileRequested) {
EXPECT_CALL(
mock_observer_,
OnURLsAvailable(Contains(Pair(SectionType::PERSONALIZED, IsEmpty()))));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/0);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/0);
base::RunLoop().RunUntilIdle();
}
@@ -676,8 +675,8 @@ TEST_P(MostVisitedSitesTest, ShouldReturnHomepageIfOneTileRequested) {
homepage_client->SetHomepageTileEnabled(true);
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
- .WillRepeatedly(base::test::RunOnceCallback<0>(
- (MostVisitedURLList{MakeMostVisitedURL("Site 1", "http://site1/")})));
+ .WillRepeatedly(base::test::RunOnceCallback<0>((
+ MostVisitedURLList{MakeMostVisitedURL(u"Site 1", "http://site1/")})));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(*mock_top_sites_, IsBlocked(Eq(GURL(kHomepageUrl))))
.Times(AnyNumber())
@@ -686,9 +685,9 @@ TEST_P(MostVisitedSitesTest, ShouldReturnHomepageIfOneTileRequested) {
mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE))))));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/1);
+ ElementsAre(MatchesTile(u"", kHomepageUrl, TileSource::HOMEPAGE))))));
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/1);
base::RunLoop().RunUntilIdle();
}
@@ -698,11 +697,11 @@ TEST_P(MostVisitedSitesTest, ShouldHaveHomepageFirstInListWhenFull) {
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillRepeatedly(base::test::RunOnceCallback<0>((MostVisitedURLList{
- MakeMostVisitedURL("Site 1", "http://site1/"),
- MakeMostVisitedURL("Site 2", "http://site2/"),
- MakeMostVisitedURL("Site 3", "http://site3/"),
- MakeMostVisitedURL("Site 4", "http://site4/"),
- MakeMostVisitedURL("Site 5", "http://site5/"),
+ MakeMostVisitedURL(u"Site 1", "http://site1/"),
+ MakeMostVisitedURL(u"Site 2", "http://site2/"),
+ MakeMostVisitedURL(u"Site 3", "http://site3/"),
+ MakeMostVisitedURL(u"Site 4", "http://site4/"),
+ MakeMostVisitedURL(u"Site 5", "http://site5/"),
})));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(*mock_top_sites_, IsBlocked(Eq(GURL(kHomepageUrl))))
@@ -711,14 +710,14 @@ TEST_P(MostVisitedSitesTest, ShouldHaveHomepageFirstInListWhenFull) {
std::map<SectionType, NTPTilesVector> sections;
EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
.WillOnce(SaveArg<0>(&sections));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/4);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/4);
base::RunLoop().RunUntilIdle();
ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(4ul));
// Assert that the home page is appended as the final tile.
- EXPECT_THAT(tiles[0], MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE));
+ EXPECT_THAT(tiles[0], MatchesTile(u"", kHomepageUrl, TileSource::HOMEPAGE));
}
TEST_P(MostVisitedSitesTest, ShouldHaveHomepageFirstInListWhenNotFull) {
@@ -727,11 +726,11 @@ TEST_P(MostVisitedSitesTest, ShouldHaveHomepageFirstInListWhenNotFull) {
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillRepeatedly(base::test::RunOnceCallback<0>((MostVisitedURLList{
- MakeMostVisitedURL("Site 1", "http://site1/"),
- MakeMostVisitedURL("Site 2", "http://site2/"),
- MakeMostVisitedURL("Site 3", "http://site3/"),
- MakeMostVisitedURL("Site 4", "http://site4/"),
- MakeMostVisitedURL("Site 5", "http://site5/"),
+ MakeMostVisitedURL(u"Site 1", "http://site1/"),
+ MakeMostVisitedURL(u"Site 2", "http://site2/"),
+ MakeMostVisitedURL(u"Site 3", "http://site3/"),
+ MakeMostVisitedURL(u"Site 4", "http://site4/"),
+ MakeMostVisitedURL(u"Site 5", "http://site5/"),
})));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(*mock_top_sites_, IsBlocked(Eq(GURL(kHomepageUrl))))
@@ -740,14 +739,14 @@ TEST_P(MostVisitedSitesTest, ShouldHaveHomepageFirstInListWhenNotFull) {
std::map<SectionType, NTPTilesVector> sections;
EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
.WillOnce(SaveArg<0>(&sections));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/8);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/8);
base::RunLoop().RunUntilIdle();
ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(6ul));
// Assert that the home page is the first tile.
- EXPECT_THAT(tiles[0], MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE));
+ EXPECT_THAT(tiles[0], MatchesTile(u"", kHomepageUrl, TileSource::HOMEPAGE));
}
TEST_P(MostVisitedSitesTest, ShouldDeduplicateHomepageWithTopSites) {
@@ -756,8 +755,8 @@ TEST_P(MostVisitedSitesTest, ShouldDeduplicateHomepageWithTopSites) {
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillRepeatedly(base::test::RunOnceCallback<0>(
- (MostVisitedURLList{MakeMostVisitedURL("Site 1", "http://site1/"),
- MakeMostVisitedURL("", kHomepageUrl)})));
+ (MostVisitedURLList{MakeMostVisitedURL(u"Site 1", "http://site1/"),
+ MakeMostVisitedURL(u"", kHomepageUrl)})));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(*mock_top_sites_, IsBlocked(Eq(GURL(kHomepageUrl))))
.Times(AnyNumber())
@@ -766,11 +765,11 @@ TEST_P(MostVisitedSitesTest, ShouldDeduplicateHomepageWithTopSites) {
mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
- AllOf(Contains(MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE)),
- Not(Contains(
- MatchesTile("", kHomepageUrl, TileSource::TOP_SITES))))))));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ AllOf(Contains(MatchesTile(u"", kHomepageUrl, TileSource::HOMEPAGE)),
+ Not(Contains(MatchesTile(u"", kHomepageUrl,
+ TileSource::TOP_SITES))))))));
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
}
@@ -787,10 +786,10 @@ TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfThereIsNone) {
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(
Pair(SectionType::PERSONALIZED,
- Not(Contains(MatchesTile("", kHomepageUrl,
+ Not(Contains(MatchesTile(u"", kHomepageUrl,
TileSource::HOMEPAGE)))))));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
}
@@ -808,9 +807,9 @@ TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfEmptyUrl) {
.WillRepeatedly(Return(false));
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Not(FirstPersonalizedTileIs(
- "", kEmptyHomepageUrl, TileSource::HOMEPAGE))));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ u"", kEmptyHomepageUrl, TileSource::HOMEPAGE))));
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
}
@@ -820,7 +819,7 @@ TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfBlocked) {
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillRepeatedly(base::test::RunOnceCallback<0>(
- (MostVisitedURLList{MakeMostVisitedURL("", kHomepageUrl)})));
+ (MostVisitedURLList{MakeMostVisitedURL(u"", kHomepageUrl)})));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(*mock_top_sites_, IsBlocked(Eq(GURL(kHomepageUrl))))
.Times(AnyNumber())
@@ -832,11 +831,11 @@ TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfBlocked) {
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(
Pair(SectionType::PERSONALIZED,
- Not(Contains(MatchesTile("", kHomepageUrl,
+ Not(Contains(MatchesTile(u"", kHomepageUrl,
TileSource::HOMEPAGE)))))));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
}
@@ -847,7 +846,7 @@ TEST_P(MostVisitedSitesTest, ShouldPinHomepageAgainIfBlockedUndone) {
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillOnce(base::test::RunOnceCallback<0>(
- (MostVisitedURLList{MakeMostVisitedURL("", kHomepageUrl)})));
+ (MostVisitedURLList{MakeMostVisitedURL(u"", kHomepageUrl)})));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(*mock_top_sites_, IsBlocked(Eq(GURL(kHomepageUrl))))
.Times(AtLeast(1))
@@ -855,11 +854,11 @@ TEST_P(MostVisitedSitesTest, ShouldPinHomepageAgainIfBlockedUndone) {
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(
Pair(SectionType::PERSONALIZED,
- Not(Contains(MatchesTile("", kHomepageUrl,
+ Not(Contains(MatchesTile(u"", kHomepageUrl,
TileSource::HOMEPAGE)))))));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
VerifyAndClearExpectations();
@@ -873,7 +872,7 @@ TEST_P(MostVisitedSitesTest, ShouldPinHomepageAgainIfBlockedUndone) {
mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
- Contains(MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE))))));
+ Contains(MatchesTile(u"", kHomepageUrl, TileSource::HOMEPAGE))))));
most_visited_sites_->OnBlockedSitesChanged();
base::RunLoop().RunUntilIdle();
@@ -885,9 +884,9 @@ TEST_P(MostVisitedSitesTest, ShouldNotIncludeTileForExploreSitesIfNoClient) {
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillRepeatedly(base::test::RunOnceCallback<0>(MostVisitedURLList{
- MakeMostVisitedURL("ESPN", "http://espn.com/"),
- MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
- MakeMostVisitedURL("Google", "http://www.google.com/")}));
+ MakeMostVisitedURL(u"ESPN", "http://espn.com/"),
+ MakeMostVisitedURL(u"Mobile", "http://m.mobile.de/"),
+ MakeMostVisitedURL(u"Google", "http://www.google.com/")}));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Not(Contains(
@@ -895,8 +894,8 @@ TEST_P(MostVisitedSitesTest, ShouldNotIncludeTileForExploreSitesIfNoClient) {
Contains(TileWithSource(TileSource::EXPLORE)))))));
// Note that 5 sites are requested, this means that there should be the 3 from
// top sites and two from popular sites.
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/5);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/5);
base::RunLoop().RunUntilIdle();
}
@@ -907,17 +906,17 @@ TEST_P(MostVisitedSitesTest, ShouldIncludeTileForExploreSites) {
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillRepeatedly(base::test::RunOnceCallback<0>(MostVisitedURLList{
- MakeMostVisitedURL("ESPN", "http://espn.com/"),
- MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
- MakeMostVisitedURL("Google", "http://www.google.com/")}));
+ MakeMostVisitedURL(u"ESPN", "http://espn.com/"),
+ MakeMostVisitedURL(u"Mobile", "http://m.mobile.de/"),
+ MakeMostVisitedURL(u"Google", "http://www.google.com/")}));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(mock_observer_,
OnURLsAvailable(LastTileIs(kTestExploreTitle, kTestExploreUrl,
TileSource::EXPLORE)));
// Note that 5 sites are requested, this means that there should be the 3 from
// top sites, one from popular sites, and one explore tile.
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/5);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/5);
base::RunLoop().RunUntilIdle();
}
@@ -926,21 +925,21 @@ TEST_P(MostVisitedSitesTest, RemovesPersonalSiteIfExploreSitesTilePresent) {
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillRepeatedly(base::test::RunOnceCallback<0>(MostVisitedURLList{
- MakeMostVisitedURL("ESPN", "http://espn.com/"),
- MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
- MakeMostVisitedURL("Google", "http://www.google.com/")}));
+ MakeMostVisitedURL(u"ESPN", "http://espn.com/"),
+ MakeMostVisitedURL(u"Mobile", "http://m.mobile.de/"),
+ MakeMostVisitedURL(u"Google", "http://www.google.com/")}));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("ESPN", "http://espn.com/",
+ ElementsAre(MatchesTile(u"ESPN", "http://espn.com/",
TileSource::TOP_SITES),
- MatchesTile("Mobile", "http://m.mobile.de/",
+ MatchesTile(u"Mobile", "http://m.mobile.de/",
TileSource::TOP_SITES),
MatchesTile(kTestExploreTitle, kTestExploreUrl,
TileSource::EXPLORE))))));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
}
@@ -966,34 +965,34 @@ TEST_P(MostVisitedSitesTest,
DisableRemoteSuggestions();
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillRepeatedly(base::test::RunOnceCallback<0>(MostVisitedURLList{
- MakeMostVisitedURL("ESPN", "http://espn.com/"),
- MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
- MakeMostVisitedURL("Google", "http://www.google.com/")}));
+ MakeMostVisitedURL(u"ESPN", "http://espn.com/"),
+ MakeMostVisitedURL(u"Mobile", "http://m.mobile.de/"),
+ MakeMostVisitedURL(u"Google", "http://www.google.com/")}));
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
std::map<SectionType, NTPTilesVector> sections;
EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
.WillOnce(SaveArg<0>(&sections));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/6);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/6);
base::RunLoop().RunUntilIdle();
ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
- Contains(MatchesTile("Google", "http://www.google.com/",
+ Contains(MatchesTile(u"Google", "http://www.google.com/",
TileSource::TOP_SITES)));
if (IsPopularSitesFeatureEnabled()) {
EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
- Contains(MatchesTile("Google News", "http://news.google.com/",
+ Contains(MatchesTile(u"Google News", "http://news.google.com/",
TileSource::POPULAR)));
}
EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
- AllOf(Contains(MatchesTile("ESPN", "http://espn.com/",
+ AllOf(Contains(MatchesTile(u"ESPN", "http://espn.com/",
TileSource::TOP_SITES)),
- Contains(MatchesTile("Mobile", "http://m.mobile.de/",
+ Contains(MatchesTile(u"Mobile", "http://m.mobile.de/",
TileSource::TOP_SITES)),
- Not(Contains(MatchesTile("ESPN", "http://www.espn.com/",
+ Not(Contains(MatchesTile(u"ESPN", "http://www.espn.com/",
TileSource::POPULAR))),
- Not(Contains(MatchesTile("Mobile", "http://www.mobile.de/",
+ Not(Contains(MatchesTile(u"Mobile", "http://www.mobile.de/",
TileSource::POPULAR)))));
}
@@ -1002,7 +1001,7 @@ TEST_P(MostVisitedSitesTest, ShouldHandleTopSitesCacheHit) {
// even before the function returns.
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillRepeatedly(base::test::RunOnceCallback<0>(
- MostVisitedURLList{MakeMostVisitedURL("Site 1", "http://site1/")}));
+ MostVisitedURLList{MakeMostVisitedURL(u"Site 1", "http://site1/")}));
InSequence seq;
EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
@@ -1016,24 +1015,24 @@ TEST_P(MostVisitedSitesTest, ShouldHandleTopSitesCacheHit) {
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
ElementsAre(
- MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
- MatchesTile("PopularSite1", "http://popularsite1/",
+ MatchesTile(u"Site 1", "http://site1/", TileSource::TOP_SITES),
+ MatchesTile(u"PopularSite1", "http://popularsite1/",
TileSource::POPULAR),
- MatchesTile("PopularSite2", "http://popularsite2/",
+ MatchesTile(u"PopularSite2", "http://popularsite2/",
TileSource::POPULAR))))));
} else {
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(
Pair(SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 1", "http://site1/",
+ ElementsAre(MatchesTile(u"Site 1", "http://site1/",
TileSource::TOP_SITES))))));
}
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
.WillOnce(Return(true));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
VerifyAndClearExpectations();
EXPECT_FALSE(suggestions_service_callbacks_.empty());
CHECK(top_sites_callbacks_.empty());
@@ -1041,7 +1040,7 @@ TEST_P(MostVisitedSitesTest, ShouldHandleTopSitesCacheHit) {
// Update by TopSites is propagated.
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillOnce(base::test::RunOnceCallback<0>(
- MostVisitedURLList{MakeMostVisitedURL("Site 2", "http://site2/")}));
+ MostVisitedURLList{MakeMostVisitedURL(u"Site 2", "http://site2/")}));
if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(*mock_top_sites_, IsBlocked(_)).WillRepeatedly(Return(false));
}
@@ -1143,10 +1142,9 @@ class MostVisitedSitesWithCustomLinksTest : public MostVisitedSitesTest {
TEST_P(MostVisitedSitesWithCustomLinksTest,
ShouldOnlyBuildCustomLinksWhenInitialized) {
const char kTestUrl[] = "http://site1/";
- const char kTestTitle[] = "Site 1";
+ const char16_t kTestTitle[] = u"Site 1";
std::vector<CustomLinksManager::Link> expected_links(
- {CustomLinksManager::Link{GURL(kTestUrl),
- base::UTF8ToUTF16(kTestTitle)}});
+ {CustomLinksManager::Link{GURL(kTestUrl), kTestTitle}});
std::map<SectionType, NTPTilesVector> sections;
DisableRemoteSuggestions();
@@ -1155,8 +1153,8 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
ExpectBuildWithTopSites(
MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/1);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/1);
base::RunLoop().RunUntilIdle();
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(1ul));
@@ -1193,10 +1191,9 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
TEST_P(MostVisitedSitesWithCustomLinksTest,
ShouldFavorCustomLinksOverTopSites) {
const char kTestUrl[] = "http://site1/";
- const char kTestTitle[] = "Site 1";
+ const char16_t kTestTitle[] = u"Site 1";
std::vector<CustomLinksManager::Link> expected_links(
- {CustomLinksManager::Link{GURL(kTestUrl),
- base::UTF8ToUTF16(kTestTitle)}});
+ {CustomLinksManager::Link{GURL(kTestUrl), kTestTitle}});
std::map<SectionType, NTPTilesVector> sections;
DisableRemoteSuggestions();
@@ -1205,8 +1202,8 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
ExpectBuildWithTopSites(
MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/1);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/1);
base::RunLoop().RunUntilIdle();
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(1ul));
@@ -1231,7 +1228,7 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
VerifyAndClearExpectations();
EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
top_sites_callbacks_.Notify(
- MostVisitedURLList({MakeMostVisitedURL("Site 2", "http://site2/")}));
+ MostVisitedURLList({MakeMostVisitedURL(u"Site 2", "http://site2/")}));
base::RunLoop().RunUntilIdle();
}
@@ -1239,21 +1236,21 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
ShouldFavorCustomLinksOverSuggestions) {
const char kTestUrl[] = "http://site1/";
const char kTestTitle[] = "Site 1";
+ const char16_t kTestTitle16[] = u"Site 1";
std::vector<CustomLinksManager::Link> expected_links(
- {CustomLinksManager::Link{GURL(kTestUrl),
- base::UTF8ToUTF16(kTestTitle)}});
+ {CustomLinksManager::Link{GURL(kTestUrl), kTestTitle16}});
std::map<SectionType, NTPTilesVector> sections;
// Build tiles when custom links is not initialized. Tiles should be from
// suggestions.
EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
ExpectBuildWithSuggestions({MakeSuggestion(kTestTitle, kTestUrl)}, &sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/1);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/1);
base::RunLoop().RunUntilIdle();
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(1ul));
- ASSERT_THAT(tiles[0], MatchesTile(kTestTitle, kTestUrl,
+ ASSERT_THAT(tiles[0], MatchesTile(kTestTitle16, kTestUrl,
TileSource::SUGGESTIONS_SERVICE));
// Initialize custom links and rebuild tiles. Tiles should be custom links.
@@ -1262,9 +1259,9 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
most_visited_sites_->InitializeCustomLinks();
most_visited_sites_->RefreshTiles();
base::RunLoop().RunUntilIdle();
- ASSERT_THAT(
- sections.at(SectionType::PERSONALIZED),
- ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
+ ASSERT_THAT(sections.at(SectionType::PERSONALIZED),
+ ElementsAre(MatchesTile(kTestTitle16, kTestUrl,
+ TileSource::CUSTOM_LINKS)));
// Initiate notification for new suggestions. This should be ignored.
EXPECT_CALL(*mock_custom_links_, IsInitialized())
@@ -1279,21 +1276,21 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
DisableCustomLinksWhenNotInitialized) {
const char kTestUrl[] = "http://site1/";
const char kTestTitle[] = "Site 1";
+ const char16_t kTestTitle16[] = u"Site 1";
std::vector<CustomLinksManager::Link> expected_links(
- {CustomLinksManager::Link{GURL(kTestUrl),
- base::UTF8ToUTF16(kTestTitle)}});
+ {CustomLinksManager::Link{GURL(kTestUrl), kTestTitle16}});
std::map<SectionType, NTPTilesVector> sections;
// Build tiles when custom links is not initialized. Tiles should be from
// suggestions.
EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
ExpectBuildWithSuggestions({MakeSuggestion(kTestTitle, kTestUrl)}, &sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/1);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/1);
base::RunLoop().RunUntilIdle();
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(1ul));
- ASSERT_THAT(tiles[0], MatchesTile(kTestTitle, kTestUrl,
+ ASSERT_THAT(tiles[0], MatchesTile(kTestTitle16, kTestUrl,
TileSource::SUGGESTIONS_SERVICE));
// Disable custom links. Tiles should rebuild.
@@ -1315,9 +1312,9 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
TEST_P(MostVisitedSitesWithCustomLinksTest, DisableCustomLinksWhenInitialized) {
const char kTestUrl[] = "http://site1/";
const char kTestTitle[] = "Site 1";
+ const char16_t kTestTitle16[] = u"Site 1";
std::vector<CustomLinksManager::Link> expected_links(
- {CustomLinksManager::Link{GURL(kTestUrl),
- base::UTF8ToUTF16(kTestTitle)}});
+ {CustomLinksManager::Link{GURL(kTestUrl), kTestTitle16}});
std::map<SectionType, NTPTilesVector> sections;
// Build tiles when custom links is initialized and not disabled. Tiles should
@@ -1330,12 +1327,12 @@ TEST_P(MostVisitedSitesWithCustomLinksTest, DisableCustomLinksWhenInitialized) {
EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
.WillOnce(Return(false));
ExpectBuildWithCustomLinks(expected_links, &sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/1);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/1);
base::RunLoop().RunUntilIdle();
- ASSERT_THAT(
- sections.at(SectionType::PERSONALIZED),
- ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
+ ASSERT_THAT(sections.at(SectionType::PERSONALIZED),
+ ElementsAre(MatchesTile(kTestTitle16, kTestUrl,
+ TileSource::CUSTOM_LINKS)));
// Disable custom links. Tiles should rebuild and return suggestions.
EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
@@ -1347,29 +1344,30 @@ TEST_P(MostVisitedSitesWithCustomLinksTest, DisableCustomLinksWhenInitialized) {
most_visited_sites_->EnableCustomLinks(false);
base::RunLoop().RunUntilIdle();
EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
- ElementsAre(MatchesTile(kTestTitle, kTestUrl,
+ ElementsAre(MatchesTile(kTestTitle16, kTestUrl,
TileSource::SUGGESTIONS_SERVICE)));
// Re-enable custom links. Tiles should rebuild and return custom links.
ExpectBuildWithCustomLinks(expected_links, &sections);
most_visited_sites_->EnableCustomLinks(true);
base::RunLoop().RunUntilIdle();
- ASSERT_THAT(
- sections.at(SectionType::PERSONALIZED),
- ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
+ ASSERT_THAT(sections.at(SectionType::PERSONALIZED),
+ ElementsAre(MatchesTile(kTestTitle16, kTestUrl,
+ TileSource::CUSTOM_LINKS)));
}
TEST_P(MostVisitedSitesWithCustomLinksTest,
ShouldGenerateShortTitleForTopSites) {
std::string kTestUrl1 = "https://www.imdb.com/";
- std::string kTestTitle1 = "IMDb - Movies, TV and Celebrities - IMDb";
+ std::u16string kTestTitle1 = u"IMDb - Movies, TV and Celebrities - IMDb";
std::string kTestUrl2 = "https://drive.google.com/";
- std::string kTestTitle2 =
- "Google Drive - Cloud Storage & File Backup for Photos, Docs & More";
+ std::u16string kTestTitle2 =
+ u"Google Drive - Cloud Storage & File Backup for Photos, Docs & More";
std::string kTestUrl3 = "https://amazon.com/";
- std::string kTestTitle3 =
- "Amazon.com: Online Shopping for Electronics, Apparel, Computers, Books, "
- "DVDs & more";
+ std::u16string kTestTitle3 =
+ u"Amazon.com: Online Shopping for Electronics, Apparel, Computers, "
+ u"Books, "
+ u"DVDs & more";
std::map<SectionType, NTPTilesVector> sections;
DisableRemoteSuggestions();
@@ -1380,25 +1378,26 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
MakeMostVisitedURL(kTestTitle2, kTestUrl2),
MakeMostVisitedURL(kTestTitle3, kTestUrl3)},
&sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(3ul));
ASSERT_THAT(
tiles[0],
- MatchesTile(/* The short title generated by the heuristic */ "IMDb",
+ MatchesTile(/* The short title generated by the heuristic */ u"IMDb",
kTestUrl1, TileSource::TOP_SITES));
ASSERT_THAT(
tiles[1],
MatchesTile(
- /* The short title generated by the heuristic */ "Google Drive",
+ /* The short title generated by the heuristic */ u"Google Drive",
kTestUrl2, TileSource::TOP_SITES));
- ASSERT_THAT(tiles[2],
- MatchesTile(
- /* The short title generated by the heuristic */ "Amazon.com",
- kTestUrl3, TileSource::TOP_SITES));
+ ASSERT_THAT(
+ tiles[2],
+ MatchesTile(
+ /* The short title generated by the heuristic */ u"Amazon.com",
+ kTestUrl3, TileSource::TOP_SITES));
}
TEST_P(MostVisitedSitesWithCustomLinksTest,
@@ -1420,33 +1419,34 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
MakeSuggestion(kTestTitle2, kTestUrl2),
MakeSuggestion(kTestTitle3, kTestUrl3)},
&sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
base::RunLoop().RunUntilIdle();
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(3ul));
ASSERT_THAT(
tiles[0],
- MatchesTile(/* The short title generated by the heuristic */ "IMDb",
+ MatchesTile(/* The short title generated by the heuristic */ u"IMDb",
kTestUrl1, TileSource::SUGGESTIONS_SERVICE));
ASSERT_THAT(
tiles[1],
MatchesTile(
- /* The short title generated by the heuristic */ "Google Drive",
+ /* The short title generated by the heuristic */ u"Google Drive",
kTestUrl2, TileSource::SUGGESTIONS_SERVICE));
- ASSERT_THAT(tiles[2],
- MatchesTile(
- /* The short title generated by the heuristic */ "Amazon.com",
- kTestUrl3, TileSource::SUGGESTIONS_SERVICE));
+ ASSERT_THAT(
+ tiles[2],
+ MatchesTile(
+ /* The short title generated by the heuristic */ u"Amazon.com",
+ kTestUrl3, TileSource::SUGGESTIONS_SERVICE));
}
TEST_P(MostVisitedSitesWithCustomLinksTest,
ShouldNotCrashIfReceiveAnEmptyTitle) {
std::string kTestUrl1 = "https://site1/";
- std::string kTestTitle1 = ""; // Empty title
+ std::u16string kTestTitle1 = u""; // Empty title
std::string kTestUrl2 = "https://site2/";
- std::string kTestTitle2 = " "; // Title only contains spaces
+ std::u16string kTestTitle2 = u" "; // Title only contains spaces
std::map<SectionType, NTPTilesVector> sections;
DisableRemoteSuggestions();
@@ -1456,24 +1456,23 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1),
MakeMostVisitedURL(kTestTitle2, kTestUrl2)},
&sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/2);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/2);
base::RunLoop().RunUntilIdle();
// Both cases should not crash and generate an empty title tile.
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(2ul));
- ASSERT_THAT(tiles[0], MatchesTile("", kTestUrl1, TileSource::TOP_SITES));
- ASSERT_THAT(tiles[1], MatchesTile("", kTestUrl2, TileSource::TOP_SITES));
+ ASSERT_THAT(tiles[0], MatchesTile(u"", kTestUrl1, TileSource::TOP_SITES));
+ ASSERT_THAT(tiles[1], MatchesTile(u"", kTestUrl2, TileSource::TOP_SITES));
}
TEST_P(MostVisitedSitesWithCustomLinksTest,
UninitializeCustomLinksOnUndoAfterFirstAction) {
const char kTestUrl[] = "http://site1/";
- const char kTestTitle[] = "Site 1";
+ const char16_t kTestTitle[] = u"Site 1";
std::vector<CustomLinksManager::Link> expected_links(
- {CustomLinksManager::Link{GURL(kTestUrl),
- base::UTF8ToUTF16(kTestTitle)}});
+ {CustomLinksManager::Link{GURL(kTestUrl), kTestTitle}});
std::map<SectionType, NTPTilesVector> sections;
DisableRemoteSuggestions();
@@ -1481,8 +1480,8 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
ExpectBuildWithTopSites(
MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/1);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/1);
base::RunLoop().RunUntilIdle();
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(1ul));
@@ -1525,10 +1524,9 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
TEST_P(MostVisitedSitesWithCustomLinksTest,
DontUninitializeCustomLinksOnUndoAfterMultipleActions) {
const char kTestUrl[] = "http://site1/";
- const char kTestTitle[] = "Site 1";
+ const char16_t kTestTitle[] = u"Site 1";
std::vector<CustomLinksManager::Link> expected_links(
- {CustomLinksManager::Link{GURL(kTestUrl),
- base::UTF8ToUTF16(kTestTitle)}});
+ {CustomLinksManager::Link{GURL(kTestUrl), kTestTitle}});
std::map<SectionType, NTPTilesVector> sections;
DisableRemoteSuggestions();
@@ -1536,8 +1534,8 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
ExpectBuildWithTopSites(
MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/1);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/1);
base::RunLoop().RunUntilIdle();
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(1ul));
@@ -1583,10 +1581,9 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
TEST_P(MostVisitedSitesWithCustomLinksTest,
UninitializeCustomLinksIfFirstActionFails) {
const char kTestUrl[] = "http://site1/";
- const char kTestTitle[] = "Site 1";
+ const char16_t kTestTitle[] = u"Site 1";
std::vector<CustomLinksManager::Link> expected_links(
- {CustomLinksManager::Link{GURL(kTestUrl),
- base::UTF8ToUTF16(kTestTitle)}});
+ {CustomLinksManager::Link{GURL(kTestUrl), kTestTitle}});
std::map<SectionType, NTPTilesVector> sections;
DisableRemoteSuggestions();
@@ -1594,8 +1591,8 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
ExpectBuildWithTopSites(
MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, &sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/1);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/1);
base::RunLoop().RunUntilIdle();
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(1ul));
@@ -1651,11 +1648,10 @@ TEST_P(MostVisitedSitesWithCustomLinksTest,
TEST_P(MostVisitedSitesWithCustomLinksTest, RebuildTilesOnCustomLinksChanged) {
const char kTestUrl1[] = "http://site1/";
const char kTestUrl2[] = "http://site2/";
- const char kTestTitle1[] = "Site 1";
- const char kTestTitle2[] = "Site 2";
+ const char16_t kTestTitle1[] = u"Site 1";
+ const char16_t kTestTitle2[] = u"Site 2";
std::vector<CustomLinksManager::Link> expected_links(
- {CustomLinksManager::Link{GURL(kTestUrl2),
- base::UTF8ToUTF16(kTestTitle2)}});
+ {CustomLinksManager::Link{GURL(kTestUrl2), kTestTitle2}});
std::map<SectionType, NTPTilesVector> sections;
DisableRemoteSuggestions();
@@ -1667,8 +1663,8 @@ TEST_P(MostVisitedSitesWithCustomLinksTest, RebuildTilesOnCustomLinksChanged) {
ExpectBuildWithTopSites(
MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1)},
&sections);
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/1);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/1);
base::RunLoop().RunUntilIdle();
NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
ASSERT_THAT(tiles.size(), Ge(1ul));
@@ -1737,32 +1733,32 @@ class MostVisitedSitesWithCacheHitTest : public MostVisitedSitesTest {
mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 1", "http://site1/",
+ ElementsAre(MatchesTile(u"Site 1", "http://site1/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 2", "http://site2/",
+ MatchesTile(u"Site 2", "http://site2/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 3", "http://site3/",
+ MatchesTile(u"Site 3", "http://site3/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("PopularSite1", "http://popularsite1/",
+ MatchesTile(u"PopularSite1", "http://popularsite1/",
TileSource::POPULAR))))));
} else {
EXPECT_CALL(
mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 1", "http://site1/",
+ ElementsAre(MatchesTile(u"Site 1", "http://site1/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 2", "http://site2/",
+ MatchesTile(u"Site 2", "http://site2/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 3", "http://site3/",
+ MatchesTile(u"Site 3", "http://site3/",
TileSource::SUGGESTIONS_SERVICE))))));
}
EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
.WillOnce(Return(true));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/4);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/4);
VerifyAndClearExpectations();
EXPECT_FALSE(suggestions_service_callbacks_.empty());
@@ -1779,13 +1775,13 @@ TEST_P(MostVisitedSitesWithCacheHitTest,
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 4", "http://site4/",
+ ElementsAre(MatchesTile(u"Site 4", "http://site4/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 5", "http://site5/",
+ MatchesTile(u"Site 5", "http://site5/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 6", "http://site6/",
+ MatchesTile(u"Site 6", "http://site6/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 7", "http://site7/",
+ MatchesTile(u"Site 7", "http://site7/",
TileSource::SUGGESTIONS_SERVICE))))));
suggestions_service_callbacks_.Notify(
MakeProfile({MakeSuggestion("Site 4", "http://site4/"),
@@ -1813,20 +1809,20 @@ TEST_P(MostVisitedSitesWithCacheHitTest,
if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(
mock_observer_,
- OnURLsAvailable(Contains(
- Pair(SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 4", "http://site4/",
- TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("PopularSite1", "http://popularsite1/",
- TileSource::POPULAR),
- MatchesTile("PopularSite2", "http://popularsite2/",
- TileSource::POPULAR))))));
+ OnURLsAvailable(Contains(Pair(
+ SectionType::PERSONALIZED,
+ ElementsAre(MatchesTile(u"Site 4", "http://site4/",
+ TileSource::SUGGESTIONS_SERVICE),
+ MatchesTile(u"PopularSite1", "http://popularsite1/",
+ TileSource::POPULAR),
+ MatchesTile(u"PopularSite2", "http://popularsite2/",
+ TileSource::POPULAR))))));
} else {
EXPECT_CALL(
mock_observer_,
OnURLsAvailable(Contains(
Pair(SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 4", "http://site4/",
+ ElementsAre(MatchesTile(u"Site 4", "http://site4/",
TileSource::SUGGESTIONS_SERVICE))))));
}
suggestions_service_callbacks_.Notify(
@@ -1847,16 +1843,16 @@ TEST_P(MostVisitedSitesWithCacheHitTest,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
ElementsAre(
- MatchesTile("Site 4", "http://site4/", TileSource::TOP_SITES),
- MatchesTile("Site 5", "http://site5/", TileSource::TOP_SITES),
- MatchesTile("Site 6", "http://site6/", TileSource::TOP_SITES),
- MatchesTile("Site 7", "http://site7/",
+ MatchesTile(u"Site 4", "http://site4/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 5", "http://site5/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 6", "http://site6/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 7", "http://site7/",
TileSource::TOP_SITES))))));
top_sites_callbacks_.Notify(
- MostVisitedURLList({MakeMostVisitedURL("Site 4", "http://site4/"),
- MakeMostVisitedURL("Site 5", "http://site5/"),
- MakeMostVisitedURL("Site 6", "http://site6/"),
- MakeMostVisitedURL("Site 7", "http://site7/")}));
+ MostVisitedURLList({MakeMostVisitedURL(u"Site 4", "http://site4/"),
+ MakeMostVisitedURL(u"Site 5", "http://site5/"),
+ MakeMostVisitedURL(u"Site 6", "http://site6/"),
+ MakeMostVisitedURL(u"Site 7", "http://site7/")}));
base::RunLoop().RunUntilIdle();
}
@@ -1896,8 +1892,8 @@ class MostVisitedSitesWithEmptyCacheTest : public MostVisitedSitesTest {
EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
.WillOnce(Return(true));
- most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
- /*num_sites=*/3);
+ most_visited_sites_->AddMostVisitedURLsObserver(&mock_observer_,
+ /*max_num_sites=*/3);
VerifyAndClearExpectations();
EXPECT_FALSE(suggestions_service_callbacks_.empty());
@@ -1915,20 +1911,20 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(
mock_observer_,
- OnURLsAvailable(Contains(
- Pair(SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 4", "http://site4/",
- TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("PopularSite1", "http://popularsite1/",
- TileSource::POPULAR),
- MatchesTile("PopularSite2", "http://popularsite2/",
- TileSource::POPULAR))))));
+ OnURLsAvailable(Contains(Pair(
+ SectionType::PERSONALIZED,
+ ElementsAre(MatchesTile(u"Site 4", "http://site4/",
+ TileSource::SUGGESTIONS_SERVICE),
+ MatchesTile(u"PopularSite1", "http://popularsite1/",
+ TileSource::POPULAR),
+ MatchesTile(u"PopularSite2", "http://popularsite2/",
+ TileSource::POPULAR))))));
} else {
EXPECT_CALL(
mock_observer_,
OnURLsAvailable(Contains(
Pair(SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 4", "http://site4/",
+ ElementsAre(MatchesTile(u"Site 4", "http://site4/",
TileSource::SUGGESTIONS_SERVICE))))));
}
suggestions_service_callbacks_.Notify(
@@ -1942,11 +1938,11 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 1", "http://site1/",
+ ElementsAre(MatchesTile(u"Site 1", "http://site1/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 2", "http://site2/",
+ MatchesTile(u"Site 2", "http://site2/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 3", "http://site3/",
+ MatchesTile(u"Site 3", "http://site3/",
TileSource::SUGGESTIONS_SERVICE))))));
suggestions_service_callbacks_.Notify(
MakeProfile({MakeSuggestion("Site 1", "http://site1/"),
@@ -1956,7 +1952,7 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
// Reply from top sites is ignored (i.e. not reported to observer).
top_sites_callbacks_.Notify(
- MostVisitedURLList({MakeMostVisitedURL("Site 4", "http://site4/")}));
+ MostVisitedURLList({MakeMostVisitedURL(u"Site 4", "http://site4/")}));
VerifyAndClearExpectations();
// Update by TopSites is also ignored.
@@ -1977,14 +1973,14 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
ElementsAre(
- MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
- MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
- MatchesTile("Site 3", "http://site3/",
+ MatchesTile(u"Site 1", "http://site1/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 2", "http://site2/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 3", "http://site3/",
TileSource::TOP_SITES))))));
top_sites_callbacks_.Notify(
- MostVisitedURLList({MakeMostVisitedURL("Site 1", "http://site1/"),
- MakeMostVisitedURL("Site 2", "http://site2/"),
- MakeMostVisitedURL("Site 3", "http://site3/")}));
+ MostVisitedURLList({MakeMostVisitedURL(u"Site 1", "http://site1/"),
+ MakeMostVisitedURL(u"Site 2", "http://site2/"),
+ MakeMostVisitedURL(u"Site 3", "http://site3/")}));
base::RunLoop().RunUntilIdle();
}
@@ -1996,14 +1992,14 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
ElementsAre(
- MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
- MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
- MatchesTile("Site 3", "http://site3/",
+ MatchesTile(u"Site 1", "http://site1/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 2", "http://site2/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 3", "http://site3/",
TileSource::TOP_SITES))))));
top_sites_callbacks_.Notify(
- MostVisitedURLList({MakeMostVisitedURL("Site 1", "http://site1/"),
- MakeMostVisitedURL("Site 2", "http://site2/"),
- MakeMostVisitedURL("Site 3", "http://site3/")}));
+ MostVisitedURLList({MakeMostVisitedURL(u"Site 1", "http://site1/"),
+ MakeMostVisitedURL(u"Site 2", "http://site2/"),
+ MakeMostVisitedURL(u"Site 3", "http://site3/")}));
VerifyAndClearExpectations();
// Reply from suggestions service overrides top sites.
@@ -2011,11 +2007,11 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 4", "http://site4/",
+ ElementsAre(MatchesTile(u"Site 4", "http://site4/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 5", "http://site5/",
+ MatchesTile(u"Site 5", "http://site5/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 6", "http://site6/",
+ MatchesTile(u"Site 6", "http://site6/",
TileSource::SUGGESTIONS_SERVICE))))));
suggestions_service_callbacks_.Notify(
MakeProfile({MakeSuggestion("Site 4", "http://site4/"),
@@ -2032,14 +2028,14 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
ElementsAre(
- MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
- MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
- MatchesTile("Site 3", "http://site3/",
+ MatchesTile(u"Site 1", "http://site1/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 2", "http://site2/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 3", "http://site3/",
TileSource::TOP_SITES))))));
top_sites_callbacks_.Notify(
- MostVisitedURLList({MakeMostVisitedURL("Site 1", "http://site1/"),
- MakeMostVisitedURL("Site 2", "http://site2/"),
- MakeMostVisitedURL("Site 3", "http://site3/")}));
+ MostVisitedURLList({MakeMostVisitedURL(u"Site 1", "http://site1/"),
+ MakeMostVisitedURL(u"Site 2", "http://site2/"),
+ MakeMostVisitedURL(u"Site 3", "http://site3/")}));
VerifyAndClearExpectations();
// Reply from suggestions service is empty and thus ignored.
@@ -2054,14 +2050,14 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest, ShouldPropagateUpdateByTopSites) {
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
ElementsAre(
- MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
- MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
- MatchesTile("Site 3", "http://site3/",
+ MatchesTile(u"Site 1", "http://site1/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 2", "http://site2/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 3", "http://site3/",
TileSource::TOP_SITES))))));
top_sites_callbacks_.Notify(
- MostVisitedURLList({MakeMostVisitedURL("Site 1", "http://site1/"),
- MakeMostVisitedURL("Site 2", "http://site2/"),
- MakeMostVisitedURL("Site 3", "http://site3/")}));
+ MostVisitedURLList({MakeMostVisitedURL(u"Site 1", "http://site1/"),
+ MakeMostVisitedURL(u"Site 2", "http://site2/"),
+ MakeMostVisitedURL(u"Site 3", "http://site3/")}));
VerifyAndClearExpectations();
// Reply from suggestions service is empty and thus ignored.
@@ -2072,17 +2068,17 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest, ShouldPropagateUpdateByTopSites) {
// Update from top sites is propagated to observer.
EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
.WillOnce(base::test::RunOnceCallback<0>(
- MostVisitedURLList{MakeMostVisitedURL("Site 4", "http://site4/"),
- MakeMostVisitedURL("Site 5", "http://site5/"),
- MakeMostVisitedURL("Site 6", "http://site6/")}));
+ MostVisitedURLList{MakeMostVisitedURL(u"Site 4", "http://site4/"),
+ MakeMostVisitedURL(u"Site 5", "http://site5/"),
+ MakeMostVisitedURL(u"Site 6", "http://site6/")}));
EXPECT_CALL(
mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
ElementsAre(
- MatchesTile("Site 4", "http://site4/", TileSource::TOP_SITES),
- MatchesTile("Site 5", "http://site5/", TileSource::TOP_SITES),
- MatchesTile("Site 6", "http://site6/",
+ MatchesTile(u"Site 4", "http://site4/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 5", "http://site5/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 6", "http://site6/",
TileSource::TOP_SITES))))));
mock_top_sites_->NotifyTopSitesChanged(
history::TopSitesObserver::ChangeReason::MOST_VISITED);
@@ -2094,12 +2090,12 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
if (IsPopularSitesFeatureEnabled()) {
EXPECT_CALL(
mock_observer_,
- OnURLsAvailable(Contains(
- Pair(SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("PopularSite1", "http://popularsite1/",
- TileSource::POPULAR),
- MatchesTile("PopularSite2", "http://popularsite2/",
- TileSource::POPULAR))))));
+ OnURLsAvailable(Contains(Pair(
+ SectionType::PERSONALIZED,
+ ElementsAre(MatchesTile(u"PopularSite1", "http://popularsite1/",
+ TileSource::POPULAR),
+ MatchesTile(u"PopularSite2", "http://popularsite2/",
+ TileSource::POPULAR))))));
} else {
// The Android NTP doesn't finish initialization until it gets tiles, so a
// 0-tile notification is always needed.
@@ -2119,17 +2115,17 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
ElementsAre(
- MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
- MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
- MatchesTile("Site 3", "http://site3/",
+ MatchesTile(u"Site 1", "http://site1/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 2", "http://site2/", TileSource::TOP_SITES),
+ MatchesTile(u"Site 3", "http://site3/",
TileSource::TOP_SITES))))));
suggestions_service_callbacks_.Notify(SuggestionsProfile());
top_sites_callbacks_.Notify(
- MostVisitedURLList({MakeMostVisitedURL("Site 1", "http://site1/"),
- MakeMostVisitedURL("Site 2", "http://site2/"),
- MakeMostVisitedURL("Site 3", "http://site3/")}));
+ MostVisitedURLList({MakeMostVisitedURL(u"Site 1", "http://site1/"),
+ MakeMostVisitedURL(u"Site 2", "http://site2/"),
+ MakeMostVisitedURL(u"Site 3", "http://site3/")}));
base::RunLoop().RunUntilIdle();
for (int i = 0; i < 4; ++i) {
@@ -2140,9 +2136,9 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
history::TopSitesObserver::ChangeReason::MOST_VISITED);
EXPECT_FALSE(top_sites_callbacks_.empty());
top_sites_callbacks_.Notify(
- MostVisitedURLList({MakeMostVisitedURL("Site 1", "http://site1/"),
- MakeMostVisitedURL("Site 2", "http://site2/"),
- MakeMostVisitedURL("Site 3", "http://site3/")}));
+ MostVisitedURLList({MakeMostVisitedURL(u"Site 1", "http://site1/"),
+ MakeMostVisitedURL(u"Site 2", "http://site2/"),
+ MakeMostVisitedURL(u"Site 3", "http://site3/")}));
base::RunLoop().RunUntilIdle();
}
}
@@ -2152,11 +2148,11 @@ TEST_P(MostVisitedSitesWithEmptyCacheTest,
EXPECT_CALL(mock_observer_,
OnURLsAvailable(Contains(Pair(
SectionType::PERSONALIZED,
- ElementsAre(MatchesTile("Site 1", "http://site1/",
+ ElementsAre(MatchesTile(u"Site 1", "http://site1/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 2", "http://site2/",
+ MatchesTile(u"Site 2", "http://site2/",
TileSource::SUGGESTIONS_SERVICE),
- MatchesTile("Site 3", "http://site3/",
+ MatchesTile(u"Site 3", "http://site3/",
TileSource::SUGGESTIONS_SERVICE))))));
for (int i = 0; i < 5; ++i) {
@@ -2182,33 +2178,33 @@ INSTANTIATE_TEST_SUITE_P(MostVisitedSitesWithEmptyCacheTest,
// - Ensuring personal tiles are not duplicated in popular tiles.
TEST(MostVisitedSitesMergeTest, ShouldMergeTilesWithPersonalOnly) {
std::vector<NTPTile> personal_tiles{
- MakeTile("Site 1", "https://www.site1.com/", TileSource::TOP_SITES),
- MakeTile("Site 2", "https://www.site2.com/", TileSource::TOP_SITES),
- MakeTile("Site 3", "https://www.site3.com/", TileSource::TOP_SITES),
- MakeTile("Site 4", "https://www.site4.com/", TileSource::TOP_SITES),
+ MakeTile(u"Site 1", "https://www.site1.com/", TileSource::TOP_SITES),
+ MakeTile(u"Site 2", "https://www.site2.com/", TileSource::TOP_SITES),
+ MakeTile(u"Site 3", "https://www.site3.com/", TileSource::TOP_SITES),
+ MakeTile(u"Site 4", "https://www.site4.com/", TileSource::TOP_SITES),
};
// Without any popular tiles, the result after merge should be the personal
// tiles.
EXPECT_THAT(MostVisitedSites::MergeTiles(std::move(personal_tiles),
/*allowlist_tiles=*/NTPTilesVector(),
/*popular_tiles=*/NTPTilesVector(),
- /*explore_tile=*/base::nullopt),
- ElementsAre(MatchesTile("Site 1", "https://www.site1.com/",
+ /*explore_tile=*/absl::nullopt),
+ ElementsAre(MatchesTile(u"Site 1", "https://www.site1.com/",
TileSource::TOP_SITES),
- MatchesTile("Site 2", "https://www.site2.com/",
+ MatchesTile(u"Site 2", "https://www.site2.com/",
TileSource::TOP_SITES),
- MatchesTile("Site 3", "https://www.site3.com/",
+ MatchesTile(u"Site 3", "https://www.site3.com/",
TileSource::TOP_SITES),
- MatchesTile("Site 4", "https://www.site4.com/",
+ MatchesTile(u"Site 4", "https://www.site4.com/",
TileSource::TOP_SITES)));
}
TEST(MostVisitedSitesMergeTest, ShouldMergeTilesWithPopularOnly) {
std::vector<NTPTile> popular_tiles{
- MakeTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
- MakeTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
- MakeTile("Site 3", "https://www.site3.com/", TileSource::POPULAR),
- MakeTile("Site 4", "https://www.site4.com/", TileSource::POPULAR),
+ MakeTile(u"Site 1", "https://www.site1.com/", TileSource::POPULAR),
+ MakeTile(u"Site 2", "https://www.site2.com/", TileSource::POPULAR),
+ MakeTile(u"Site 3", "https://www.site3.com/", TileSource::POPULAR),
+ MakeTile(u"Site 4", "https://www.site4.com/", TileSource::POPULAR),
};
// Without any personal tiles, the result after merge should be the popular
// tiles.
@@ -2216,26 +2212,26 @@ TEST(MostVisitedSitesMergeTest, ShouldMergeTilesWithPopularOnly) {
MostVisitedSites::MergeTiles(/*personal_tiles=*/NTPTilesVector(),
/*allowlist_tiles=*/NTPTilesVector(),
/*popular_tiles=*/std::move(popular_tiles),
- /*explore_tile=*/base::nullopt),
+ /*explore_tile=*/absl::nullopt),
ElementsAre(
- MatchesTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
- MatchesTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
- MatchesTile("Site 3", "https://www.site3.com/", TileSource::POPULAR),
- MatchesTile("Site 4", "https://www.site4.com/",
+ MatchesTile(u"Site 1", "https://www.site1.com/", TileSource::POPULAR),
+ MatchesTile(u"Site 2", "https://www.site2.com/", TileSource::POPULAR),
+ MatchesTile(u"Site 3", "https://www.site3.com/", TileSource::POPULAR),
+ MatchesTile(u"Site 4", "https://www.site4.com/",
TileSource::POPULAR)));
}
TEST(MostVisitedSitesMergeTest, ShouldMergeTilesFavoringPersonalOverPopular) {
std::vector<NTPTile> popular_tiles{
- MakeTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
- MakeTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
+ MakeTile(u"Site 1", "https://www.site1.com/", TileSource::POPULAR),
+ MakeTile(u"Site 2", "https://www.site2.com/", TileSource::POPULAR),
};
std::vector<NTPTile> personal_tiles{
- MakeTile("Site 3", "https://www.site3.com/", TileSource::TOP_SITES),
- MakeTile("Site 4", "https://www.site4.com/", TileSource::TOP_SITES),
+ MakeTile(u"Site 3", "https://www.site3.com/", TileSource::TOP_SITES),
+ MakeTile(u"Site 4", "https://www.site4.com/", TileSource::TOP_SITES),
};
- base::Optional<NTPTile> explore_tile{
- MakeTile("Explore", "https://explore.example.com/", TileSource::EXPLORE),
+ absl::optional<NTPTile> explore_tile{
+ MakeTile(u"Explore", "https://explore.example.com/", TileSource::EXPLORE),
};
EXPECT_THAT(
MostVisitedSites::MergeTiles(std::move(personal_tiles),
@@ -2243,13 +2239,13 @@ TEST(MostVisitedSitesMergeTest, ShouldMergeTilesFavoringPersonalOverPopular) {
/*popular_tiles=*/std::move(popular_tiles),
/*explore_tiles=*/explore_tile),
ElementsAre(
- MatchesTile("Site 3", "https://www.site3.com/",
+ MatchesTile(u"Site 3", "https://www.site3.com/",
TileSource::TOP_SITES),
- MatchesTile("Site 4", "https://www.site4.com/",
+ MatchesTile(u"Site 4", "https://www.site4.com/",
TileSource::TOP_SITES),
- MatchesTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
- MatchesTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
- MatchesTile("Explore", "https://explore.example.com/",
+ MatchesTile(u"Site 1", "https://www.site1.com/", TileSource::POPULAR),
+ MatchesTile(u"Site 2", "https://www.site2.com/", TileSource::POPULAR),
+ MatchesTile(u"Explore", "https://explore.example.com/",
TileSource::EXPLORE)));
}
diff --git a/chromium/components/ntp_tiles/popular_sites_impl.cc b/chromium/components/ntp_tiles/popular_sites_impl.cc
index e44b26aa771..98e7ed90d73 100644
--- a/chromium/components/ntp_tiles/popular_sites_impl.cc
+++ b/chromium/components/ntp_tiles/popular_sites_impl.cc
@@ -215,7 +215,7 @@ base::Value DefaultPopularSites() {
if (!base::FeatureList::IsEnabled(kPopularSitesBakedInContentFeature))
return base::Value(base::Value::Type::LIST);
- base::Optional<base::Value> sites = base::JSONReader::Read(
+ absl::optional<base::Value> sites = base::JSONReader::Read(
ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
IDR_DEFAULT_POPULAR_SITES_JSON));
for (base::Value& site : sites.value().GetList())
diff --git a/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc b/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
index ea72a96040b..93b8b8fb852 100644
--- a/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
+++ b/chromium/components/ntp_tiles/popular_sites_impl_unittest.cc
@@ -13,7 +13,6 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/json/json_writer.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
@@ -35,6 +34,7 @@
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using testing::_;
using testing::Contains;
@@ -168,10 +168,10 @@ class PopularSitesTest : public ::testing::Test {
// Returns an optional bool representing whether the completion callback was
// called at all, and if yes which was the returned bool value.
- base::Optional<bool> FetchPopularSites(bool force_download,
+ absl::optional<bool> FetchPopularSites(bool force_download,
PopularSites::SitesVector* sites) {
std::map<SectionType, PopularSites::SitesVector> sections;
- base::Optional<bool> save_success =
+ absl::optional<bool> save_success =
FetchAllSections(force_download, &sections);
*sites = sections.at(SectionType::PERSONALIZED);
return save_success;
@@ -179,16 +179,16 @@ class PopularSitesTest : public ::testing::Test {
// Returns an optional bool representing whether the completion callback was
// called at all, and if yes which was the returned bool value.
- base::Optional<bool> FetchAllSections(
+ absl::optional<bool> FetchAllSections(
bool force_download,
std::map<SectionType, PopularSites::SitesVector>* sections) {
std::unique_ptr<PopularSites> popular_sites = CreatePopularSites();
base::RunLoop loop;
- base::Optional<bool> save_success;
+ absl::optional<bool> save_success;
if (popular_sites->MaybeStartFetch(
force_download, base::BindOnce(
- [](base::Optional<bool>* save_success,
+ [](absl::optional<bool>* save_success,
base::RunLoop* loop, bool success) {
save_success->emplace(success);
loop->Quit();
@@ -246,7 +246,7 @@ TEST_F(PopularSitesTest, ShouldSucceedFetching) {
PopularSites::SitesVector sites;
EXPECT_THAT(FetchPopularSites(/*force_download=*/true, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
ASSERT_THAT(sites.size(), Eq(1u));
EXPECT_THAT(sites[0].title, Str16Eq("Wikipedia, fhta Ph'nglui mglw'nafh"));
@@ -267,7 +267,7 @@ TEST_F(PopularSitesTest, Fallback) {
PopularSites::SitesVector sites;
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
ASSERT_THAT(sites.size(), Eq(2u));
EXPECT_THAT(sites[0].title, Str16Eq("YouTube"));
@@ -295,7 +295,7 @@ TEST_F(PopularSitesTest, PopulatesWithDefaultResoucesOnFailure) {
PopularSites::SitesVector sites;
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(false)));
+ Eq(absl::optional<bool>(false)));
EXPECT_THAT(sites.size(), Eq(GetNumberOfDefaultPopularSitesForPlatform()));
}
@@ -323,11 +323,11 @@ TEST_F(PopularSitesTest, ProvidesDefaultSitesUntilCallbackReturns) {
std::unique_ptr<PopularSites> popular_sites = CreatePopularSites();
base::RunLoop loop;
- base::Optional<bool> save_success = false;
+ absl::optional<bool> save_success = false;
bool callback_was_scheduled = popular_sites->MaybeStartFetch(
/*force_download=*/true, base::BindOnce(
- [](base::Optional<bool>* save_success,
+ [](absl::optional<bool>* save_success,
base::RunLoop* loop, bool success) {
save_success->emplace(success);
loop->Quit();
@@ -357,13 +357,13 @@ TEST_F(PopularSitesTest, UsesCachedJson) {
// First request succeeds and gets cached.
PopularSites::SitesVector sites;
ASSERT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
// File disappears from server, but we don't need it because it's cached.
RespondWith404(
"https://www.gstatic.com/chrome/ntp/suggested_sites_ZZ_5.json");
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::nullopt));
+ Eq(absl::nullopt));
EXPECT_THAT(sites[0].url, URLEq("https://zz.m.wikipedia.org/"));
}
@@ -378,7 +378,7 @@ TEST_F(PopularSitesTest, CachesEmptyFile) {
// First request succeeds and caches empty suggestions list (no fallback).
PopularSites::SitesVector sites;
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
EXPECT_THAT(sites, IsEmpty());
// File appears on server, but we continue to use our cached empty file.
@@ -386,7 +386,7 @@ TEST_F(PopularSitesTest, CachesEmptyFile) {
"https://www.gstatic.com/chrome/ntp/suggested_sites_ZZ_5.json",
{kWikipedia});
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::nullopt));
+ Eq(absl::nullopt));
EXPECT_THAT(sites, IsEmpty());
}
@@ -399,7 +399,7 @@ TEST_F(PopularSitesTest, DoesntUseCachedFileIfDownloadForced) {
// First request succeeds and gets cached.
PopularSites::SitesVector sites;
EXPECT_THAT(FetchPopularSites(/*force_download=*/true, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
EXPECT_THAT(sites[0].url, URLEq("https://zz.m.wikipedia.org/"));
// File disappears from server. Download is forced, so we get the new file.
@@ -407,7 +407,7 @@ TEST_F(PopularSitesTest, DoesntUseCachedFileIfDownloadForced) {
"https://www.gstatic.com/chrome/ntp/suggested_sites_ZZ_5.json",
{kChromium});
EXPECT_THAT(FetchPopularSites(/*force_download=*/true, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
EXPECT_THAT(sites[0].url, URLEq("https://www.chromium.org/"));
}
@@ -420,7 +420,7 @@ TEST_F(PopularSitesTest, DoesntUseCacheWithDeprecatedVersion) {
// First request succeeds and gets cached.
PopularSites::SitesVector sites;
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
EXPECT_THAT(sites[0].url, URLEq("https://zz.m.wikipedia.org/"));
EXPECT_THAT(prefs_->GetInteger(prefs::kPopularSitesVersionPref), Eq(5));
@@ -430,7 +430,7 @@ TEST_F(PopularSitesTest, DoesntUseCacheWithDeprecatedVersion) {
"https://www.gstatic.com/chrome/ntp/suggested_sites_ZZ_6.json",
{{SectionType::PERSONALIZED, {kChromium}}});
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
EXPECT_THAT(sites[0].url, URLEq("https://www.chromium.org/"));
EXPECT_THAT(prefs_->GetInteger(prefs::kPopularSitesVersionPref), Eq(6));
}
@@ -443,7 +443,7 @@ TEST_F(PopularSitesTest, FallsBackToDefaultParserIfVersionContainsNoNumber) {
{kChromium});
PopularSites::SitesVector sites;
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
ASSERT_THAT(sites.size(), Eq(1u));
EXPECT_THAT(sites[0].url, URLEq("https://www.chromium.org/"));
}
@@ -461,13 +461,13 @@ TEST_F(PopularSitesTest, RefetchesAfterCountryMoved) {
// First request (in ZZ) saves Wikipedia.
SetCountryAndVersion("ZZ", "5");
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
EXPECT_THAT(sites[0].url, URLEq("https://zz.m.wikipedia.org/"));
// Second request (now in ZX) saves Chromium.
SetCountryAndVersion("ZX", "5");
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- base::Optional<bool>(true));
+ absl::optional<bool>(true));
EXPECT_THAT(sites[0].url, URLEq("https://www.chromium.org/"));
}
@@ -482,14 +482,14 @@ TEST_F(PopularSitesTest, DoesntCacheInvalidFile) {
// First request falls back and gets nothing there either.
PopularSites::SitesVector sites;
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(false)));
+ Eq(absl::optional<bool>(false)));
// Second request refetches ZZ_9, which now has data.
RespondWithV5JSON(
"https://www.gstatic.com/chrome/ntp/suggested_sites_ZZ_5.json",
{kChromium});
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
ASSERT_THAT(sites.size(), Eq(1u));
EXPECT_THAT(sites[0].url, URLEq("https://www.chromium.org/"));
}
@@ -505,7 +505,7 @@ TEST_F(PopularSitesTest, RefetchesAfterFallback) {
// First request falls back.
PopularSites::SitesVector sites;
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
ASSERT_THAT(sites.size(), Eq(1u));
EXPECT_THAT(sites[0].url, URLEq("https://zz.m.wikipedia.org/"));
@@ -514,7 +514,7 @@ TEST_F(PopularSitesTest, RefetchesAfterFallback) {
"https://www.gstatic.com/chrome/ntp/suggested_sites_ZZ_5.json",
{kChromium});
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
ASSERT_THAT(sites.size(), Eq(1u));
EXPECT_THAT(sites[0].url, URLEq("https://www.chromium.org/"));
}
@@ -527,7 +527,7 @@ TEST_F(PopularSitesTest, ShouldOverrideDirectory) {
PopularSites::SitesVector sites;
EXPECT_THAT(FetchPopularSites(/*force_download=*/false, &sites),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
EXPECT_THAT(sites.size(), Eq(1u));
}
@@ -541,7 +541,7 @@ TEST_F(PopularSitesTest, DoesNotFetchExplorationSites) {
std::map<SectionType, PopularSites::SitesVector> sections;
EXPECT_THAT(FetchAllSections(/*force_download=*/false, &sections),
- Eq(base::Optional<bool>(true)));
+ Eq(absl::optional<bool>(true)));
// The fetched news section should not be propagated without enabled feature.
EXPECT_THAT(sections, Not(Contains(Pair(SectionType::NEWS, _))));
diff --git a/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc b/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
index 6fdf0fb73b9..b2eceebc0a1 100644
--- a/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
+++ b/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.cc
@@ -100,8 +100,9 @@ void NTPTilesInternalsMessageHandler::HandleRegisterForEvents(
disabled.SetBoolean("popular", false);
disabled.SetBoolean("customLinks", false);
disabled.SetBoolean("allowlist", false);
- client_->CallJavascriptFunction(
- "chrome.ntp_tiles_internals.receiveSourceInfo", disabled);
+ client_->CallJavascriptFunction("cr.webUIListenerCallback",
+ base::Value("receive-source-info"),
+ disabled);
SendTiles(NTPTilesVector(), FaviconResultMap());
return;
}
@@ -110,7 +111,7 @@ void NTPTilesInternalsMessageHandler::HandleRegisterForEvents(
suggestions_status_.clear();
popular_sites_json_.clear();
most_visited_sites_ = client_->MakeMostVisitedSites();
- most_visited_sites_->SetMostVisitedURLsObserver(this, site_count_);
+ most_visited_sites_->AddMostVisitedURLsObserver(this, site_count_);
SendSourceInfo();
}
@@ -169,7 +170,7 @@ void NTPTilesInternalsMessageHandler::HandleUpdate(
// TODO(sfiera): refresh MostVisitedSites without re-creating it, as soon as
// that will pick up changes to the Popular Sites overrides.
most_visited_sites_ = client_->MakeMostVisitedSites();
- most_visited_sites_->SetMostVisitedURLsObserver(this, site_count_);
+ most_visited_sites_->AddMostVisitedURLsObserver(this, site_count_);
SendSourceInfo();
}
@@ -243,8 +244,8 @@ void NTPTilesInternalsMessageHandler::SendSourceInfo() {
value.SetBoolean("popular", false);
}
- client_->CallJavascriptFunction(
- "chrome.ntp_tiles_internals.receiveSourceInfo", value);
+ client_->CallJavascriptFunction("cr.webUIListenerCallback",
+ base::Value("receive-source-info"), value);
}
void NTPTilesInternalsMessageHandler::SendTiles(
@@ -285,8 +286,8 @@ void NTPTilesInternalsMessageHandler::SendTiles(
base::DictionaryValue result;
result.Set("sites", std::move(sites_list));
- client_->CallJavascriptFunction("chrome.ntp_tiles_internals.receiveSites",
- result);
+ client_->CallJavascriptFunction("cr.webUIListenerCallback",
+ base::Value("receive-sites"), result);
}
void NTPTilesInternalsMessageHandler::OnURLsAvailable(
diff --git a/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.h b/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.h
index 5a03220237f..63ee466e032 100644
--- a/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.h
+++ b/chromium/components/ntp_tiles/webui/ntp_tiles_internals_message_handler.h
@@ -11,10 +11,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/task/cancelable_task_tracker.h"
#include "components/favicon_base/favicon_types.h"
#include "components/ntp_tiles/most_visited_sites.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class ListValue;
diff --git a/chromium/components/ntp_tiles/webui/resources/ntp_tiles_internals.html b/chromium/components/ntp_tiles/webui/resources/ntp_tiles_internals.html
index ac8fe676c65..3a97d0efea2 100644
--- a/chromium/components/ntp_tiles/webui/resources/ntp_tiles_internals.html
+++ b/chromium/components/ntp_tiles/webui/resources/ntp_tiles_internals.html
@@ -14,16 +14,7 @@ found in the LICENSE file.
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<link rel="stylesheet" href="chrome://resources/css/list.css">
<link rel="stylesheet" href="ntp_tiles_internals.css">
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://resources/js/jstemplate_compiled.js"></script>
-<script src="chrome://resources/js/load_time_data.js"></script>
-<script src="chrome://resources/js/assert.js"></script>
-<script src="chrome://resources/js/util.js"></script>
-<if expr="is_ios">
-<!-- TODO(crbug.com/487000): Remove this once injected by web. -->
-<script src="chrome://resources/js/ios/web_ui.js"></script>
-</if>
-<script src="ntp_tiles_internals.js"></script>
+<script type="module" src="ntp_tiles_internals.js"></script>
</head>
<body>
diff --git a/chromium/components/ntp_tiles/webui/resources/ntp_tiles_internals.js b/chromium/components/ntp_tiles/webui/resources/ntp_tiles_internals.js
index a69f65079df..ff27a084011 100644
--- a/chromium/components/ntp_tiles/webui/resources/ntp_tiles_internals.js
+++ b/chromium/components/ntp_tiles/webui/resources/ntp_tiles_internals.js
@@ -2,54 +2,48 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-cr.define('chrome.ntp_tiles_internals', function() {
- 'use strict';
-
- const initialize = function() {
- $('submit-update').addEventListener('click', function(event) {
- event.preventDefault();
- chrome.send('update', [{
- "popular": {
- "overrideURL": $('override-url').value,
- "overrideDirectory": $('override-directory').value,
- "overrideCountry": $('override-country').value,
- "overrideVersion": $('override-version').value,
- },
- }]);
- });
-
- $('suggestions-fetch').addEventListener('click', function(event) {
- event.preventDefault();
- chrome.send('fetchSuggestions');
- });
-
- $('popular-view-json').addEventListener('click', function(event) {
- event.preventDefault();
- if ($('popular-json-value').textContent === "") {
- chrome.send('viewPopularSitesJson');
- } else {
- $('popular-json-value').textContent = "";
- }
- });
-
- chrome.send('registerForEvents');
- };
-
- const receiveSourceInfo = function(state) {
+// <if expr="is_ios">
+import 'chrome://resources/js/ios/web_ui.js';
+// </if>
+
+import 'chrome://resources/js/jstemplate_compiled.js';
+import {addWebUIListener} from 'chrome://resources/js/cr.m.js';
+import {$} from 'chrome://resources/js/util.m.js';
+
+const initialize = function() {
+ $('submit-update').addEventListener('click', function(event) {
+ event.preventDefault();
+ chrome.send('update', [{
+ popular: {
+ overrideURL: $('override-url').value,
+ overrideDirectory: $('override-directory').value,
+ overrideCountry: $('override-country').value,
+ overrideVersion: $('override-version').value,
+ },
+ }]);
+ });
+
+ $('suggestions-fetch').addEventListener('click', function(event) {
+ event.preventDefault();
+ chrome.send('fetchSuggestions');
+ });
+
+ $('popular-view-json').addEventListener('click', function(event) {
+ event.preventDefault();
+ if ($('popular-json-value').textContent === '') {
+ chrome.send('viewPopularSitesJson');
+ } else {
+ $('popular-json-value').textContent = '';
+ }
+ });
+
+ addWebUIListener('receive-source-info', state => {
jstProcess(new JsEvalContext(state), $('sources'));
- };
-
- const receiveSites = function(sites) {
+ });
+ addWebUIListener('receive-sites', sites => {
jstProcess(new JsEvalContext(sites), $('sites'));
- };
-
- // Return an object with all of the exports.
- return {
- initialize: initialize,
- receiveSourceInfo: receiveSourceInfo,
- receiveSites: receiveSites,
- };
-});
+ });
+ chrome.send('registerForEvents');
+};
-document.addEventListener('DOMContentLoaded',
- chrome.ntp_tiles_internals.initialize);
+document.addEventListener('DOMContentLoaded', initialize);
diff --git a/chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc b/chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc
index 46dc5a269ae..7a3e4f85628 100644
--- a/chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc
+++ b/chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc
@@ -82,7 +82,7 @@ void RunGetAllItemsCallback(const base::android::JavaRef<jobject>& j_callback,
}
void RunGetItemByIdCallback(const base::android::JavaRef<jobject>& j_callback,
- const base::Optional<OfflineItem>& item) {
+ const absl::optional<OfflineItem>& item) {
JNIEnv* env = AttachCurrentThread();
RunObjectCallbackAndroid(
j_callback, item.has_value()
@@ -255,11 +255,11 @@ void OfflineContentAggregatorBridge::ChangeSchedule(
const base::android::JavaParamRef<jstring>& j_id,
jboolean j_only_on_wifi,
jlong j_start_time_ms) {
- base::Optional<OfflineItemSchedule> schedule;
+ absl::optional<OfflineItemSchedule> schedule;
if (j_only_on_wifi)
- schedule = base::make_optional<OfflineItemSchedule>(true, base::nullopt);
+ schedule = absl::make_optional<OfflineItemSchedule>(true, absl::nullopt);
else if (j_start_time_ms > 0) {
- schedule = base::make_optional<OfflineItemSchedule>(
+ schedule = absl::make_optional<OfflineItemSchedule>(
false, base::Time::FromJavaTime(j_start_time_ms));
}
@@ -290,7 +290,7 @@ void OfflineContentAggregatorBridge::OnItemRemoved(const ContentId& id) {
void OfflineContentAggregatorBridge::OnItemUpdated(
const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) {
+ const absl::optional<UpdateDelta>& update_delta) {
if (java_ref_.is_null())
return;
diff --git a/chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.h b/chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.h
index 8899d1de93a..8213b216549 100644
--- a/chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.h
+++ b/chromium/components/offline_items_collection/core/android/offline_content_aggregator_bridge.h
@@ -102,7 +102,7 @@ class OfflineContentAggregatorBridge : public OfflineContentProvider::Observer,
const OfflineContentProvider::OfflineItemList& items) override;
void OnItemRemoved(const ContentId& id) override;
void OnItemUpdated(const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) override;
+ const absl::optional<UpdateDelta>& update_delta) override;
void OnContentProviderGoingDown() override;
// A reference to the Java counterpart of this class. See
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 984de097efd..f9f685fe214 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
@@ -38,7 +38,7 @@ JNI_OfflineItemBridge_createOfflineItemAndMaybeAddToList(
item.completion_time.ToJavaTime(), item.last_accessed_time.ToJavaTime(),
item.is_openable, ConvertUTF8ToJavaString(env, item.file_path.value()),
ConvertUTF8ToJavaString(env, item.mime_type),
- ConvertUTF8ToJavaString(env, item.page_url.spec()),
+ ConvertUTF8ToJavaString(env, item.url.spec()),
ConvertUTF8ToJavaString(env, item.original_url.spec()),
item.is_off_the_record, ConvertUTF8ToJavaString(env, item.otr_profile_id),
static_cast<jint>(item.state), static_cast<jint>(item.fail_state),
@@ -74,7 +74,7 @@ ScopedJavaLocalRef<jobject> OfflineItemBridge::CreateOfflineItemList(
// static
ScopedJavaLocalRef<jobject> OfflineItemBridge::CreateUpdateDelta(
JNIEnv* env,
- const base::Optional<UpdateDelta>& update_delta) {
+ const absl::optional<UpdateDelta>& update_delta) {
if (!update_delta.has_value())
return ScopedJavaLocalRef<jobject>();
@@ -86,7 +86,7 @@ ScopedJavaLocalRef<jobject> OfflineItemBridge::CreateUpdateDelta(
// static
ScopedJavaLocalRef<jobject> OfflineItemBridge::CreateOfflineItemSchedule(
JNIEnv* env,
- const base::Optional<OfflineItemSchedule>& schedule) {
+ const absl::optional<OfflineItemSchedule>& schedule) {
if (!schedule.has_value())
return ScopedJavaLocalRef<jobject>();
diff --git a/chromium/components/offline_items_collection/core/android/offline_item_bridge.h b/chromium/components/offline_items_collection/core/android/offline_item_bridge.h
index 84167113ebb..d1ec8d4bd85 100644
--- a/chromium/components/offline_items_collection/core/android/offline_item_bridge.h
+++ b/chromium/components/offline_items_collection/core/android/offline_item_bridge.h
@@ -32,12 +32,12 @@ class OfflineItemBridge {
// Creates a Java UpdateDelta from |update_delta|.
static base::android::ScopedJavaLocalRef<jobject> CreateUpdateDelta(
JNIEnv* env,
- const base::Optional<UpdateDelta>& update_delta);
+ const absl::optional<UpdateDelta>& update_delta);
// Creates a Java OfflineItemSchedule.
static base::android::ScopedJavaLocalRef<jobject> CreateOfflineItemSchedule(
JNIEnv* env,
- const base::Optional<OfflineItemSchedule>& schedule);
+ const absl::optional<OfflineItemSchedule>& schedule);
private:
OfflineItemBridge();
diff --git a/chromium/components/offline_items_collection/core/android/offline_item_bridge_unittest.cc b/chromium/components/offline_items_collection/core/android/offline_item_bridge_unittest.cc
index 014dc64999e..d9d7ff1ab8d 100644
--- a/chromium/components/offline_items_collection/core/android/offline_item_bridge_unittest.cc
+++ b/chromium/components/offline_items_collection/core/android/offline_item_bridge_unittest.cc
@@ -44,8 +44,8 @@ TEST_F(OfflineItemBridgeTest, OfflineItemSchedule) {
// OfflineItemSchedule only on wifi.
auto* env = AttachCurrentThread();
OfflineItem item;
- item.schedule = base::make_optional<OfflineItemSchedule>(
- true /*only_on_wifi*/, base::nullopt);
+ item.schedule = absl::make_optional<OfflineItemSchedule>(
+ true /*only_on_wifi*/, absl::nullopt);
auto j_offline_item = OfflineItemBridge::CreateOfflineItem(env, item);
Java_OfflineItemBridgeUnitTest_testOfflineItemSchedule(
env, j_test(), j_offline_item, true /*only_on_wifi*/, 0);
@@ -53,7 +53,7 @@ TEST_F(OfflineItemBridgeTest, OfflineItemSchedule) {
// OfflineItemSchedule with specific start time.
auto start_time =
base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromDays(1));
- item.schedule = base::make_optional<OfflineItemSchedule>(
+ item.schedule = absl::make_optional<OfflineItemSchedule>(
false /*only_on_wifi*/, start_time);
EXPECT_EQ(start_time, item.schedule->start_time);
EXPECT_FALSE(start_time.is_null());
diff --git a/chromium/components/offline_items_collection/core/filtered_offline_item_observer.cc b/chromium/components/offline_items_collection/core/filtered_offline_item_observer.cc
index cf280e4df3c..a13e70101fa 100644
--- a/chromium/components/offline_items_collection/core/filtered_offline_item_observer.cc
+++ b/chromium/components/offline_items_collection/core/filtered_offline_item_observer.cc
@@ -53,7 +53,7 @@ void FilteredOfflineItemObserver::OnItemRemoved(const ContentId& id) {
void FilteredOfflineItemObserver::OnItemUpdated(
const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) {
+ const absl::optional<UpdateDelta>& update_delta) {
auto it = observers_.find(item.id);
if (it == observers_.end())
return;
diff --git a/chromium/components/offline_items_collection/core/filtered_offline_item_observer.h b/chromium/components/offline_items_collection/core/filtered_offline_item_observer.h
index e7289be03e3..2ae4dd89669 100644
--- a/chromium/components/offline_items_collection/core/filtered_offline_item_observer.h
+++ b/chromium/components/offline_items_collection/core/filtered_offline_item_observer.h
@@ -26,7 +26,7 @@ class FilteredOfflineItemObserver : public OfflineContentProvider::Observer {
virtual void OnItemRemoved(const ContentId& id) = 0;
virtual void OnItemUpdated(
const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) = 0;
+ const absl::optional<UpdateDelta>& update_delta) = 0;
protected:
virtual ~Observer() = default;
@@ -47,7 +47,7 @@ class FilteredOfflineItemObserver : public OfflineContentProvider::Observer {
const OfflineContentProvider::OfflineItemList& items) override;
void OnItemRemoved(const ContentId& id) override;
void OnItemUpdated(const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) override;
+ const absl::optional<UpdateDelta>& update_delta) override;
void OnContentProviderGoingDown() override;
OfflineContentProvider* provider_;
diff --git a/chromium/components/offline_items_collection/core/filtered_offline_item_observer_unittest.cc b/chromium/components/offline_items_collection/core/filtered_offline_item_observer_unittest.cc
index 781d5388a82..a925c78ef56 100644
--- a/chromium/components/offline_items_collection/core/filtered_offline_item_observer_unittest.cc
+++ b/chromium/components/offline_items_collection/core/filtered_offline_item_observer_unittest.cc
@@ -32,11 +32,11 @@ TEST(FilteredOfflineItemObserverTest, TestBasicUsage) {
MockFilteredOfflineItemObserver::ScopedMockObserver obs2(&filter, id2);
MockFilteredOfflineItemObserver::ScopedMockObserver obs3(&filter, id3);
- EXPECT_CALL(obs2, OnItemUpdated(item2, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(obs2, OnItemUpdated(item2, Eq(absl::nullopt))).Times(1);
EXPECT_CALL(obs3, OnItemRemoved(id3)).Times(1);
provider.NotifyOnItemsAdded({item1});
- provider.NotifyOnItemUpdated(item2, base::nullopt);
+ provider.NotifyOnItemUpdated(item2, absl::nullopt);
provider.NotifyOnItemRemoved(id3);
provider.NotifyOnItemRemoved(id4);
}
@@ -52,21 +52,21 @@ TEST(FilteredOfflineItemObserverTest, AddRemoveObservers) {
{
EXPECT_CALL(obs1, OnItemUpdated(_, _)).Times(0);
- provider.NotifyOnItemUpdated(item1, base::nullopt);
+ provider.NotifyOnItemUpdated(item1, absl::nullopt);
}
filter.AddObserver(id1, &obs1);
{
EXPECT_CALL(obs1, OnItemUpdated(_, _)).Times(1);
- provider.NotifyOnItemUpdated(item1, base::nullopt);
+ provider.NotifyOnItemUpdated(item1, absl::nullopt);
}
filter.RemoveObserver(id1, &obs1);
{
EXPECT_CALL(obs1, OnItemUpdated(_, _)).Times(0);
- provider.NotifyOnItemUpdated(item1, base::nullopt);
+ provider.NotifyOnItemUpdated(item1, absl::nullopt);
}
}
diff --git a/chromium/components/offline_items_collection/core/offline_content_aggregator.cc b/chromium/components/offline_items_collection/core/offline_content_aggregator.cc
index 6ea0cced543..c75e87a1922 100644
--- a/chromium/components/offline_items_collection/core/offline_content_aggregator.cc
+++ b/chromium/components/offline_items_collection/core/offline_content_aggregator.cc
@@ -132,7 +132,7 @@ void OfflineContentAggregator::GetItemById(const ContentId& id,
auto it = providers_.find(id.name_space);
if (it == providers_.end()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
+ FROM_HERE, base::BindOnce(std::move(callback), absl::nullopt));
return;
}
@@ -143,7 +143,7 @@ void OfflineContentAggregator::GetItemById(const ContentId& id,
void OfflineContentAggregator::OnGetItemByIdDone(
SingleItemCallback callback,
- const base::Optional<OfflineItem>& item) {
+ const absl::optional<OfflineItem>& item) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::move(callback).Run(item);
}
@@ -236,7 +236,7 @@ void OfflineContentAggregator::RenameItem(const ContentId& id,
void OfflineContentAggregator::ChangeSchedule(
const ContentId& id,
- base::Optional<OfflineItemSchedule> schedule) {
+ absl::optional<OfflineItemSchedule> schedule) {
auto it = providers_.find(id.name_space);
if (it == providers_.end())
return;
@@ -256,7 +256,7 @@ void OfflineContentAggregator::OnItemRemoved(const ContentId& id) {
void OfflineContentAggregator::OnItemUpdated(
const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) {
+ const absl::optional<UpdateDelta>& update_delta) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NotifyItemUpdated(item, update_delta);
}
diff --git a/chromium/components/offline_items_collection/core/offline_content_aggregator.h b/chromium/components/offline_items_collection/core/offline_content_aggregator.h
index 03d89902266..1ef233f6aa2 100644
--- a/chromium/components/offline_items_collection/core/offline_content_aggregator.h
+++ b/chromium/components/offline_items_collection/core/offline_content_aggregator.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_OFFLINE_ITEMS_COLLETION_CORE_OFFLINE_CONTENT_AGGREGATOR_H_
-#define COMPONENTS_OFFLINE_ITEMS_COLLETION_CORE_OFFLINE_CONTENT_AGGREGATOR_H_
+#ifndef COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_OFFLINE_CONTENT_AGGREGATOR_H_
+#define COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_OFFLINE_CONTENT_AGGREGATOR_H_
#include <map>
#include <set>
@@ -82,20 +82,20 @@ class OfflineContentAggregator : public OfflineContentProvider,
const std::string& name,
RenameCallback callback) override;
void ChangeSchedule(const ContentId& id,
- base::Optional<OfflineItemSchedule> schedule) override;
+ absl::optional<OfflineItemSchedule> schedule) override;
private:
// OfflineContentProvider::Observer implementation.
void OnItemsAdded(const OfflineItemList& items) override;
void OnItemRemoved(const ContentId& id) override;
void OnItemUpdated(const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) override;
+ const absl::optional<UpdateDelta>& update_delta) override;
void OnContentProviderGoingDown() override;
void OnGetAllItemsDone(OfflineContentProvider* provider,
const OfflineItemList& items);
void OnGetItemByIdDone(SingleItemCallback callback,
- const base::Optional<OfflineItem>& item);
+ const absl::optional<OfflineItem>& item);
// Stores a map of name_space -> OfflineContentProvider. These
// OfflineContentProviders are all aggregated by this class and exposed to the
@@ -117,4 +117,4 @@ class OfflineContentAggregator : public OfflineContentProvider,
} // namespace offline_items_collection
-#endif // COMPONENTS_OFFLINE_ITEMS_COLLETION_CORE_OFFLINE_CONTENT_AGGREGATOR_H_
+#endif // COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_OFFLINE_CONTENT_AGGREGATOR_H_
diff --git a/chromium/components/offline_items_collection/core/offline_content_aggregator_unittest.cc b/chromium/components/offline_items_collection/core/offline_content_aggregator_unittest.cc
index 964a4fd3e44..3f2b104b173 100644
--- a/chromium/components/offline_items_collection/core/offline_content_aggregator_unittest.cc
+++ b/chromium/components/offline_items_collection/core/offline_content_aggregator_unittest.cc
@@ -84,14 +84,14 @@ class OfflineContentAggregatorTest : public testing::Test {
protected:
MOCK_METHOD1(OnGetAllItemsDone,
void(const OfflineContentProvider::OfflineItemList&));
- MOCK_METHOD1(OnGetItemByIdDone, void(const base::Optional<OfflineItem>&));
+ MOCK_METHOD1(OnGetItemByIdDone, void(const absl::optional<OfflineItem>&));
void GetAllItemsAndVerify(
OfflineContentProvider* provider,
const OfflineContentProvider::OfflineItemList& expected);
void GetSingleItemAndVerify(OfflineContentProvider* provider,
const ContentId& id,
- const base::Optional<OfflineItem>& expected);
+ const absl::optional<OfflineItem>& expected);
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
base::ThreadTaskRunnerHandle handle_;
@@ -112,7 +112,7 @@ void OfflineContentAggregatorTest::GetAllItemsAndVerify(
void OfflineContentAggregatorTest::GetSingleItemAndVerify(
OfflineContentProvider* provider,
const ContentId& id,
- const base::Optional<OfflineItem>& expected) {
+ const absl::optional<OfflineItem>& expected) {
EXPECT_CALL(*this, OnGetItemByIdDone(expected)).Times(1);
provider->GetItemById(
id, base::BindOnce(&OfflineContentAggregatorTest::OnGetItemByIdDone,
@@ -152,7 +152,7 @@ TEST_F(OfflineContentAggregatorTest, QueryingItemFromRemovedProvider) {
GetSingleItemAndVerify(&aggregator_, id, item);
}
- GetSingleItemAndVerify(&aggregator_, id, base::nullopt);
+ GetSingleItemAndVerify(&aggregator_, id, absl::nullopt);
}
TEST_F(OfflineContentAggregatorTest, GetItemByIdPropagatesToRightProvider) {
@@ -170,8 +170,8 @@ TEST_F(OfflineContentAggregatorTest, GetItemByIdPropagatesToRightProvider) {
provider2.SetItems({item2});
GetSingleItemAndVerify(&aggregator_, id1, item1);
GetSingleItemAndVerify(&aggregator_, id2, item2);
- GetSingleItemAndVerify(&aggregator_, id3, base::nullopt);
- GetSingleItemAndVerify(&aggregator_, id4, base::nullopt);
+ GetSingleItemAndVerify(&aggregator_, id3, absl::nullopt);
+ GetSingleItemAndVerify(&aggregator_, id4, absl::nullopt);
}
TEST_F(OfflineContentAggregatorTest, ActionPropagatesToRightProvider) {
@@ -304,12 +304,12 @@ TEST_F(OfflineContentAggregatorTest, OnItemUpdatedPropagatedToObservers) {
OfflineItem item1(ContentId("1", "A"));
OfflineItem item2(ContentId("2", "B"));
- EXPECT_CALL(observer1, OnItemUpdated(item1, Eq(base::nullopt))).Times(1);
- EXPECT_CALL(observer1, OnItemUpdated(item2, Eq(base::nullopt))).Times(1);
- EXPECT_CALL(observer2, OnItemUpdated(item1, Eq(base::nullopt))).Times(1);
- EXPECT_CALL(observer2, OnItemUpdated(item2, Eq(base::nullopt))).Times(1);
- provider1.NotifyOnItemUpdated(item1, base::nullopt);
- provider2.NotifyOnItemUpdated(item2, base::nullopt);
+ EXPECT_CALL(observer1, OnItemUpdated(item1, Eq(absl::nullopt))).Times(1);
+ EXPECT_CALL(observer1, OnItemUpdated(item2, Eq(absl::nullopt))).Times(1);
+ EXPECT_CALL(observer2, OnItemUpdated(item1, Eq(absl::nullopt))).Times(1);
+ EXPECT_CALL(observer2, OnItemUpdated(item2, Eq(absl::nullopt))).Times(1);
+ provider1.NotifyOnItemUpdated(item1, absl::nullopt);
+ provider2.NotifyOnItemUpdated(item2, absl::nullopt);
}
TEST_F(OfflineContentAggregatorTest, ProviderRemovedDuringCallbackFlush) {
@@ -352,7 +352,7 @@ TEST_F(OfflineContentAggregatorTest, SameProviderWithMultipleNamespaces) {
aggregator_.UnregisterProvider("1");
EXPECT_TRUE(provider.HasObserver(&aggregator_));
- GetSingleItemAndVerify(&aggregator_, id1, base::nullopt);
+ GetSingleItemAndVerify(&aggregator_, id1, absl::nullopt);
GetSingleItemAndVerify(&aggregator_, id2, item2);
aggregator_.UnregisterProvider("2");
diff --git a/chromium/components/offline_items_collection/core/offline_content_provider.cc b/chromium/components/offline_items_collection/core/offline_content_provider.cc
index 0eae0114254..40abff1a760 100644
--- a/chromium/components/offline_items_collection/core/offline_content_provider.cc
+++ b/chromium/components/offline_items_collection/core/offline_content_provider.cc
@@ -37,7 +37,7 @@ void OfflineContentProvider::NotifyItemRemoved(const ContentId& id) {
void OfflineContentProvider::NotifyItemUpdated(
const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) {
+ const absl::optional<UpdateDelta>& update_delta) {
for (auto& observer : observers_)
observer.OnItemUpdated(item, update_delta);
}
diff --git a/chromium/components/offline_items_collection/core/offline_content_provider.h b/chromium/components/offline_items_collection/core/offline_content_provider.h
index cac258d71cb..3bd3dbc8e65 100644
--- a/chromium/components/offline_items_collection/core/offline_content_provider.h
+++ b/chromium/components/offline_items_collection/core/offline_content_provider.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_OFFLINE_ITEMS_COLLETION_CORE_OFFLINE_CONTENT_PROVIDER_H_
-#define COMPONENTS_OFFLINE_ITEMS_COLLETION_CORE_OFFLINE_CONTENT_PROVIDER_H_
+#ifndef COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_OFFLINE_CONTENT_PROVIDER_H_
+#define COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_OFFLINE_CONTENT_PROVIDER_H_
#include <string>
#include <vector>
@@ -11,11 +11,11 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "components/offline_items_collection/core/launch_location.h"
#include "components/offline_items_collection/core/open_params.h"
#include "components/offline_items_collection/core/rename_result.h"
#include "components/offline_items_collection/core/update_delta.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace offline_items_collection {
@@ -38,7 +38,7 @@ class OfflineContentProvider {
std::unique_ptr<OfflineItemShareInfo>)>;
using MultipleItemCallback = base::OnceCallback<void(const OfflineItemList&)>;
using SingleItemCallback =
- base::OnceCallback<void(const base::Optional<OfflineItem>&)>;
+ base::OnceCallback<void(const absl::optional<OfflineItem>&)>;
using RenameCallback = base::OnceCallback<void(RenameResult)>;
using DownloadRenameCallback = base::OnceCallback<RenameCallback>;
@@ -96,7 +96,7 @@ class OfflineContentProvider {
// determine whether this call should be ignored.
virtual void OnItemUpdated(
const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) = 0;
+ const absl::optional<UpdateDelta>& update_delta) = 0;
// Called right before this object gets destroyed, to lets observers
// perform cleanup.
@@ -162,7 +162,7 @@ class OfflineContentProvider {
// Called to change when to start the OfflineItem represented by |id|.
virtual void ChangeSchedule(const ContentId& id,
- base::Optional<OfflineItemSchedule> schedule) = 0;
+ absl::optional<OfflineItemSchedule> schedule) = 0;
// Adds an observer that should be notified of OfflineItem list modifications.
void AddObserver(Observer* observer);
@@ -181,7 +181,7 @@ class OfflineContentProvider {
void NotifyItemsAdded(const OfflineItemList& items);
void NotifyItemRemoved(const ContentId& id);
void NotifyItemUpdated(const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta);
+ const absl::optional<UpdateDelta>& update_delta);
private:
base::ObserverList<Observer> observers_;
@@ -189,4 +189,4 @@ class OfflineContentProvider {
} // namespace offline_items_collection
-#endif // COMPONENTS_OFFLINE_ITEMS_COLLETION_CORE_OFFLINE_CONTENT_PROVIDER_H_
+#endif // COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_OFFLINE_CONTENT_PROVIDER_H_
diff --git a/chromium/components/offline_items_collection/core/offline_item.cc b/chromium/components/offline_items_collection/core/offline_item.cc
index 038ea68e6a3..3e63913b7f2 100644
--- a/chromium/components/offline_items_collection/core/offline_item.cc
+++ b/chromium/components/offline_items_collection/core/offline_item.cc
@@ -33,7 +33,7 @@ bool ContentId::operator<(const ContentId& content_id) const {
// -----------------------------------------------------------------------------
// OfflineItemSchedule.
OfflineItemSchedule::OfflineItemSchedule(bool only_on_wifi,
- base::Optional<base::Time> start_time)
+ absl::optional<base::Time> start_time)
: only_on_wifi(only_on_wifi), start_time(std::move(start_time)) {}
OfflineItemSchedule::OfflineItemSchedule(const OfflineItemSchedule& other) =
@@ -112,8 +112,7 @@ bool OfflineItem::operator==(const OfflineItem& offline_item) const {
last_accessed_time == offline_item.last_accessed_time &&
is_openable == offline_item.is_openable &&
file_path == offline_item.file_path &&
- mime_type == offline_item.mime_type &&
- page_url == offline_item.page_url &&
+ mime_type == offline_item.mime_type && url == offline_item.url &&
original_url == offline_item.original_url &&
is_off_the_record == offline_item.is_off_the_record &&
otr_profile_id == offline_item.otr_profile_id &&
diff --git a/chromium/components/offline_items_collection/core/offline_item.h b/chromium/components/offline_items_collection/core/offline_item.h
index 53b4c015da2..bb43795d60d 100644
--- a/chromium/components/offline_items_collection/core/offline_item.h
+++ b/chromium/components/offline_items_collection/core/offline_item.h
@@ -8,12 +8,12 @@
#include <string>
#include "base/files/file_path.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/offline_items_collection/core/fail_state.h"
#include "components/offline_items_collection/core/offline_item_filter.h"
#include "components/offline_items_collection/core/offline_item_state.h"
#include "components/offline_items_collection/core/pending_state.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/image/image.h"
#include "url/gurl.h"
@@ -45,7 +45,7 @@ struct ContentId {
// Contains all the information to schedule the download of the offline item.
struct OfflineItemSchedule {
public:
- OfflineItemSchedule(bool only_on_wifi, base::Optional<base::Time> start_time);
+ OfflineItemSchedule(bool only_on_wifi, absl::optional<base::Time> start_time);
OfflineItemSchedule(const OfflineItemSchedule& other);
OfflineItemSchedule& operator=(const OfflineItemSchedule& other);
@@ -58,7 +58,7 @@ struct OfflineItemSchedule {
// Time to start downloading the offline item. Will be ignored if
// |only_on_wifi_| is true.
- base::Optional<base::Time> start_time;
+ absl::optional<base::Time> start_time;
};
// A Java counterpart will be generated for this enum.
@@ -91,7 +91,7 @@ struct OfflineItem {
// The maximum value of the download progress. Absence of the value implies
// indeterminate progress.
- base::Optional<int64_t> max;
+ absl::optional<int64_t> max;
// The unit of progress to be displayed in the UI.
OfflineItemProgressUnit unit;
@@ -185,8 +185,8 @@ struct OfflineItem {
// Request Metadata.
// ---------------------------------------------------------------------------
- // The URL of the top level frame at the time the content was offlined.
- GURL page_url;
+ // The URL of the offline item, after all redirections.
+ GURL url;
// The URL that represents the original request (before any redirection).
GURL original_url;
@@ -237,7 +237,7 @@ struct OfflineItem {
bool is_dangerous;
// The criteria for when the offline item is likely to download.
- base::Optional<OfflineItemSchedule> schedule;
+ absl::optional<OfflineItemSchedule> schedule;
};
// Implemented for test-only. See test_support/offline_item_test_support.cc.
diff --git a/chromium/components/offline_items_collection/core/offline_item_unittest.cc b/chromium/components/offline_items_collection/core/offline_item_unittest.cc
index b099d714ac1..c853139ea54 100644
--- a/chromium/components/offline_items_collection/core/offline_item_unittest.cc
+++ b/chromium/components/offline_items_collection/core/offline_item_unittest.cc
@@ -4,15 +4,15 @@
#include "components/offline_items_collection/core/offline_item.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace offline_items_collection {
namespace {
TEST(OfflineItemTest, OfflineItemSchedule) {
- OfflineItemSchedule schedule(true, base::nullopt);
+ OfflineItemSchedule schedule(true, absl::nullopt);
EXPECT_TRUE(schedule.only_on_wifi);
EXPECT_FALSE(schedule.start_time.has_value());
diff --git a/chromium/components/offline_items_collection/core/test_support/mock_filtered_offline_item_observer.h b/chromium/components/offline_items_collection/core/test_support/mock_filtered_offline_item_observer.h
index 76ac0be2307..92ded2776c9 100644
--- a/chromium/components/offline_items_collection/core/test_support/mock_filtered_offline_item_observer.h
+++ b/chromium/components/offline_items_collection/core/test_support/mock_filtered_offline_item_observer.h
@@ -22,7 +22,7 @@ class MockFilteredOfflineItemObserver {
// FilteredOfflineItemObserver::Observer implementation.
MOCK_METHOD1(OnItemRemoved, void(const ContentId&));
MOCK_METHOD2(OnItemUpdated,
- void(const OfflineItem&, const base::Optional<UpdateDelta>&));
+ void(const OfflineItem&, const absl::optional<UpdateDelta>&));
};
class ScopedMockObserver : public MockObserver {
diff --git a/chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.cc b/chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.cc
index fbb525c8aef..ad0ed7b7910 100644
--- a/chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.cc
+++ b/chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.cc
@@ -36,7 +36,7 @@ void MockOfflineContentProvider::NotifyOnItemRemoved(const ContentId& id) {
void MockOfflineContentProvider::NotifyOnItemUpdated(
const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) {
+ const absl::optional<UpdateDelta>& update_delta) {
NotifyItemUpdated(item, update_delta);
}
@@ -63,7 +63,7 @@ void MockOfflineContentProvider::GetAllItems(MultipleItemCallback callback) {
void MockOfflineContentProvider::GetItemById(const ContentId& id,
SingleItemCallback callback) {
- base::Optional<OfflineItem> result;
+ absl::optional<OfflineItem> result;
for (auto item : items_) {
if (item.id == id) {
result = item;
diff --git a/chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.h b/chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.h
index ad35a3fe37f..582db0b3d2b 100644
--- a/chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.h
+++ b/chromium/components/offline_items_collection/core/test_support/mock_offline_content_provider.h
@@ -23,7 +23,7 @@ class MockOfflineContentProvider : public OfflineContentProvider {
MOCK_METHOD1(OnItemsAdded, void(const OfflineItemList&));
MOCK_METHOD1(OnItemRemoved, void(const ContentId&));
MOCK_METHOD2(OnItemUpdated,
- void(const OfflineItem&, const base::Optional<UpdateDelta>&));
+ void(const OfflineItem&, const absl::optional<UpdateDelta>&));
MOCK_METHOD0(OnContentProviderGoingDown, void());
};
@@ -40,7 +40,7 @@ class MockOfflineContentProvider : public OfflineContentProvider {
void NotifyOnItemsAdded(const OfflineItemList& items);
void NotifyOnItemRemoved(const ContentId& id);
void NotifyOnItemUpdated(const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta);
+ const absl::optional<UpdateDelta>& update_delta);
// OfflineContentProvider implementation.
MOCK_METHOD2(OpenItem, void(const OpenParams&, const ContentId&));
@@ -62,7 +62,7 @@ class MockOfflineContentProvider : public OfflineContentProvider {
void(const ContentId&, const std::string&, RenameCallback));
MOCK_METHOD(void,
ChangeSchedule,
- (const ContentId&, base::Optional<OfflineItemSchedule>),
+ (const ContentId&, absl::optional<OfflineItemSchedule>),
(override));
private:
diff --git a/chromium/components/offline_items_collection/core/test_support/offline_item_test_support.cc b/chromium/components/offline_items_collection/core/test_support/offline_item_test_support.cc
index 7ebecb57469..a8955326289 100644
--- a/chromium/components/offline_items_collection/core/test_support/offline_item_test_support.cc
+++ b/chromium/components/offline_items_collection/core/test_support/offline_item_test_support.cc
@@ -30,7 +30,7 @@ std::ostream& operator<<(std::ostream& os, const OfflineItem& item) {
os << ", is_openable: " << item.is_openable;
os << ", file_path: " << item.file_path;
os << ", mime_type: " << item.mime_type;
- os << ", page_url: " << item.page_url;
+ os << ", url: " << item.url;
os << ", original_url: " << item.original_url;
os << ", is_off_the_record: " << item.is_off_the_record;
os << ", attribution: " << item.attribution;
diff --git a/chromium/components/offline_items_collection/core/throttled_offline_content_provider.cc b/chromium/components/offline_items_collection/core/throttled_offline_content_provider.cc
index 35a61a4a925..25445ca2ac4 100644
--- a/chromium/components/offline_items_collection/core/throttled_offline_content_provider.cc
+++ b/chromium/components/offline_items_collection/core/throttled_offline_content_provider.cc
@@ -86,7 +86,7 @@ void ThrottledOfflineContentProvider::OnGetAllItemsDone(
void ThrottledOfflineContentProvider::OnGetItemByIdDone(
SingleItemCallback callback,
- const base::Optional<OfflineItem>& item) {
+ const absl::optional<OfflineItem>& item) {
if (item.has_value())
UpdateItemIfPresent(item.value());
std::move(callback).Run(item);
@@ -113,7 +113,7 @@ void ThrottledOfflineContentProvider::RenameItem(const ContentId& id,
void ThrottledOfflineContentProvider::ChangeSchedule(
const ContentId& id,
- base::Optional<OfflineItemSchedule> schedule) {
+ absl::optional<OfflineItemSchedule> schedule) {
wrapped_provider_->ChangeSchedule(id, std::move(schedule));
}
@@ -129,8 +129,8 @@ void ThrottledOfflineContentProvider::OnItemRemoved(const ContentId& id) {
void ThrottledOfflineContentProvider::OnItemUpdated(
const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) {
- base::Optional<UpdateDelta> merged = update_delta;
+ const absl::optional<UpdateDelta>& update_delta) {
+ absl::optional<UpdateDelta> merged = update_delta;
if (updates_.find(item.id) != updates_.end()) {
merged = UpdateDelta::MergeUpdates(updates_[item.id].second, update_delta);
}
diff --git a/chromium/components/offline_items_collection/core/throttled_offline_content_provider.h b/chromium/components/offline_items_collection/core/throttled_offline_content_provider.h
index dd2cc8491c9..822e7b5b9a4 100644
--- a/chromium/components/offline_items_collection/core/throttled_offline_content_provider.h
+++ b/chromium/components/offline_items_collection/core/throttled_offline_content_provider.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_OFFLINE_ITEMS_COLLETION_CORE_THROTTLED_OFFLINE_CONTENT_PROVIDER_H_
-#define COMPONENTS_OFFLINE_ITEMS_COLLETION_CORE_THROTTLED_OFFLINE_CONTENT_PROVIDER_H_
+#ifndef COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_THROTTLED_OFFLINE_CONTENT_PROVIDER_H_
+#define COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_THROTTLED_OFFLINE_CONTENT_PROVIDER_H_
#include <map>
#include <utility>
@@ -54,7 +54,7 @@ class ThrottledOfflineContentProvider
const std::string& name,
RenameCallback callback) override;
void ChangeSchedule(const ContentId& id,
- base::Optional<OfflineItemSchedule> schedule) override;
+ absl::optional<OfflineItemSchedule> schedule) override;
// Visible for testing. Overrides the time at which this throttle last pushed
// updates to observers.
@@ -65,13 +65,13 @@ class ThrottledOfflineContentProvider
void OnItemsAdded(const OfflineItemList& items) override;
void OnItemRemoved(const ContentId& id) override;
void OnItemUpdated(const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) override;
+ const absl::optional<UpdateDelta>& update_delta) override;
void OnContentProviderGoingDown() override;
void OnGetAllItemsDone(MultipleItemCallback callback,
const OfflineItemList& items);
void OnGetItemByIdDone(SingleItemCallback callback,
- const base::Optional<OfflineItem>& item);
+ const absl::optional<OfflineItem>& item);
// Checks if |item| already has an update pending. If so, replaces the content
// of the update with |item|.
@@ -92,7 +92,7 @@ class ThrottledOfflineContentProvider
observation_{this};
typedef std::map<ContentId,
- std::pair<OfflineItem, base::Optional<UpdateDelta>>>
+ std::pair<OfflineItem, absl::optional<UpdateDelta>>>
OfflineItemMap;
OfflineItemMap updates_;
@@ -103,4 +103,4 @@ class ThrottledOfflineContentProvider
} // namespace offline_items_collection
-#endif // COMPONENTS_OFFLINE_ITEMS_COLLETION_CORE_THROTTLED_OFFLINE_CONTENT_PROVIDER_H_
+#endif // COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_THROTTLED_OFFLINE_CONTENT_PROVIDER_H_
diff --git a/chromium/components/offline_items_collection/core/throttled_offline_content_provider_unittest.cc b/chromium/components/offline_items_collection/core/throttled_offline_content_provider_unittest.cc
index 4b8df3f8f07..7c6a9044663 100644
--- a/chromium/components/offline_items_collection/core/throttled_offline_content_provider_unittest.cc
+++ b/chromium/components/offline_items_collection/core/throttled_offline_content_provider_unittest.cc
@@ -41,7 +41,7 @@ class TriggerSingleReentrantUpdateHelper
~TriggerSingleReentrantUpdateHelper() override {}
void OnItemUpdated(const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) override {
+ const absl::optional<UpdateDelta>& update_delta) override {
if (wrapped_provider_) {
if (item.id == new_item_.id)
wrapped_provider_->NotifyOnItemUpdated(new_item_, update_delta);
@@ -66,7 +66,7 @@ class ThrottledOfflineContentProviderTest : public testing::Test {
MOCK_METHOD1(OnGetAllItemsDone,
void(const OfflineContentProvider::OfflineItemList&));
- MOCK_METHOD1(OnGetItemByIdDone, void(const base::Optional<OfflineItem>&));
+ MOCK_METHOD1(OnGetItemByIdDone, void(const absl::optional<OfflineItem>&));
protected:
base::TimeTicks GetTimeThatWillAllowAnUpdate() {
@@ -114,7 +114,7 @@ TEST_F(ThrottledOfflineContentProviderTest, TestBasicPassthrough) {
base::BindOnce(&ThrottledOfflineContentProviderTest::OnGetAllItemsDone,
weak_ptr_factory_.GetWeakPtr()));
- EXPECT_CALL(*this, OnGetItemByIdDone(base::make_optional(item))).Times(1);
+ EXPECT_CALL(*this, OnGetItemByIdDone(absl::make_optional(item))).Times(1);
provider_.GetItemById(
id,
base::BindOnce(&ThrottledOfflineContentProviderTest::OnGetItemByIdDone,
@@ -128,11 +128,11 @@ TEST_F(ThrottledOfflineContentProviderTest, TestRemoveCancelsUpdate) {
ContentId id("1", "A");
OfflineItem item(id);
- EXPECT_CALL(observer, OnItemUpdated(item, Eq(base::nullopt))).Times(0);
+ EXPECT_CALL(observer, OnItemUpdated(item, Eq(absl::nullopt))).Times(0);
EXPECT_CALL(observer, OnItemRemoved(id)).Times(1);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item, absl::nullopt);
wrapped_provider_.NotifyOnItemRemoved(id);
task_runner_->FastForwardUntilNoTasksRemain();
}
@@ -151,16 +151,16 @@ TEST_F(ThrottledOfflineContentProviderTest, TestOnItemUpdatedSquashed) {
OfflineItem updated_item2(id2);
updated_item2.title = "updated2";
- EXPECT_CALL(observer, OnItemUpdated(updated_item1, Eq(base::nullopt)))
+ EXPECT_CALL(observer, OnItemUpdated(updated_item1, Eq(absl::nullopt)))
.Times(1);
- EXPECT_CALL(observer, OnItemUpdated(updated_item2, Eq(base::nullopt)))
+ EXPECT_CALL(observer, OnItemUpdated(updated_item2, Eq(absl::nullopt)))
.Times(1);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item1, base::nullopt);
- wrapped_provider_.NotifyOnItemUpdated(item2, base::nullopt);
- wrapped_provider_.NotifyOnItemUpdated(updated_item2, base::nullopt);
- wrapped_provider_.NotifyOnItemUpdated(updated_item1, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1, absl::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item2, absl::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(updated_item2, absl::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(updated_item1, absl::nullopt);
task_runner_->FastForwardUntilNoTasksRemain();
}
@@ -180,22 +180,22 @@ TEST_F(ThrottledOfflineContentProviderTest, TestGetItemByIdOverridesUpdate) {
std::vector<OfflineItem> items = {item1, item2};
wrapped_provider_.SetItems(items);
- EXPECT_CALL(observer, OnItemUpdated(updated_item1, Eq(base::nullopt)))
+ EXPECT_CALL(observer, OnItemUpdated(updated_item1, Eq(absl::nullopt)))
.Times(1);
- EXPECT_CALL(observer, OnItemUpdated(item2, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item2, Eq(absl::nullopt))).Times(1);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item1, base::nullopt);
- wrapped_provider_.NotifyOnItemUpdated(item2, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1, absl::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item2, absl::nullopt);
items = {updated_item1, item2};
wrapped_provider_.SetItems(items);
- auto single_item_callback = [](const base::Optional<OfflineItem>& item) {};
+ auto single_item_callback = [](const absl::optional<OfflineItem>& item) {};
provider_.GetItemById(id1, base::BindOnce(single_item_callback));
provider_.set_last_update_time(GetTimeThatWillAllowAnUpdate());
- wrapped_provider_.NotifyOnItemUpdated(item2, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item2, absl::nullopt);
task_runner_->FastForwardUntilNoTasksRemain();
}
@@ -216,14 +216,14 @@ TEST_F(ThrottledOfflineContentProviderTest, TestGetAllItemsOverridesUpdate) {
items.push_back(updated_item1);
items.push_back(item2);
- EXPECT_CALL(observer, OnItemUpdated(updated_item1, Eq(base::nullopt)))
+ EXPECT_CALL(observer, OnItemUpdated(updated_item1, Eq(absl::nullopt)))
.Times(1);
- EXPECT_CALL(observer, OnItemUpdated(item2, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item2, Eq(absl::nullopt))).Times(1);
wrapped_provider_.SetItems(items);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item1, base::nullopt);
- wrapped_provider_.NotifyOnItemUpdated(item2, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1, absl::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item2, absl::nullopt);
auto callback = [](const OfflineContentProvider::OfflineItemList& items) {};
provider_.GetAllItems(base::BindOnce(callback));
@@ -248,23 +248,23 @@ TEST_F(ThrottledOfflineContentProviderTest, TestThrottleWorksProperly) {
item4.title = "updated3";
{
- EXPECT_CALL(observer, OnItemUpdated(item1, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item1, Eq(absl::nullopt))).Times(1);
provider_.set_last_update_time(GetTimeThatWillAllowAnUpdate());
- wrapped_provider_.NotifyOnItemUpdated(item1, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1, absl::nullopt);
}
{
- EXPECT_CALL(observer, OnItemUpdated(item3, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item3, Eq(absl::nullopt))).Times(1);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item2, base::nullopt);
- wrapped_provider_.NotifyOnItemUpdated(item3, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item2, absl::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item3, absl::nullopt);
task_runner_->FastForwardBy(delay_);
}
{
- EXPECT_CALL(observer, OnItemUpdated(item4, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item4, Eq(absl::nullopt))).Times(1);
provider_.set_last_update_time(GetTimeThatWillAllowAnUpdate());
- wrapped_provider_.NotifyOnItemUpdated(item4, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item4, absl::nullopt);
task_runner_->FastForwardUntilNoTasksRemain();
}
}
@@ -280,19 +280,19 @@ TEST_F(ThrottledOfflineContentProviderTest, TestInitialRequestGoesThrough) {
item1_updated.title = "updated1";
{
- EXPECT_CALL(observer, OnItemUpdated(item1, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item1, Eq(absl::nullopt))).Times(1);
provider_.set_last_update_time(GetTimeThatWillAllowAnUpdate());
- wrapped_provider_.NotifyOnItemUpdated(item1, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1, absl::nullopt);
}
{
EXPECT_CALL(observer, OnItemUpdated(_, _)).Times(0);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item1_updated, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1_updated, absl::nullopt);
}
{
- EXPECT_CALL(observer, OnItemUpdated(item1_updated, Eq(base::nullopt)))
+ EXPECT_CALL(observer, OnItemUpdated(item1_updated, Eq(absl::nullopt)))
.Times(1);
task_runner_->FastForwardUntilNoTasksRemain();
}
@@ -308,13 +308,13 @@ TEST_F(ThrottledOfflineContentProviderTest, TestReentrantUpdatesGetQueued) {
TriggerSingleReentrantUpdateHelper observer(&provider_, &wrapped_provider_,
updated_item);
{
- wrapped_provider_.NotifyOnItemUpdated(item, base::nullopt);
- EXPECT_CALL(observer, OnItemUpdated(item, Eq(base::nullopt))).Times(1);
+ wrapped_provider_.NotifyOnItemUpdated(item, absl::nullopt);
+ EXPECT_CALL(observer, OnItemUpdated(item, Eq(absl::nullopt))).Times(1);
task_runner_->FastForwardBy(delay_);
}
{
- EXPECT_CALL(observer, OnItemUpdated(updated_item, Eq(base::nullopt)))
+ EXPECT_CALL(observer, OnItemUpdated(updated_item, Eq(absl::nullopt)))
.Times(1);
task_runner_->FastForwardUntilNoTasksRemain();
}
@@ -335,62 +335,62 @@ TEST_F(ThrottledOfflineContentProviderTest, TestPokingProviderFlushesQueue) {
// Set up reentrancy calls back into the provider.
EXPECT_CALL(wrapped_provider_, OpenItem(_, _))
.WillRepeatedly(InvokeWithoutArgs([=]() {
- wrapped_provider_.NotifyOnItemUpdated(item2, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item2, absl::nullopt);
}));
EXPECT_CALL(wrapped_provider_, RemoveItem(_))
.WillRepeatedly(InvokeWithoutArgs([=]() {
- wrapped_provider_.NotifyOnItemUpdated(item3, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item3, absl::nullopt);
}));
EXPECT_CALL(wrapped_provider_, CancelDownload(_))
.WillRepeatedly(InvokeWithoutArgs([=]() {
- wrapped_provider_.NotifyOnItemUpdated(item4, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item4, absl::nullopt);
}));
EXPECT_CALL(wrapped_provider_, PauseDownload(_))
.WillRepeatedly(InvokeWithoutArgs([=]() {
- wrapped_provider_.NotifyOnItemUpdated(item5, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item5, absl::nullopt);
}));
EXPECT_CALL(wrapped_provider_, ResumeDownload(_, _))
.WillRepeatedly(InvokeWithoutArgs([=]() {
- wrapped_provider_.NotifyOnItemUpdated(item6, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item6, absl::nullopt);
}));
{
- EXPECT_CALL(observer, OnItemUpdated(item1, Eq(base::nullopt))).Times(1);
- EXPECT_CALL(observer, OnItemUpdated(item2, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item1, Eq(absl::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item2, Eq(absl::nullopt))).Times(1);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item1, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1, absl::nullopt);
provider_.OpenItem(OpenParams(LaunchLocation::DOWNLOAD_HOME), id1);
}
{
- EXPECT_CALL(observer, OnItemUpdated(item1, Eq(base::nullopt))).Times(1);
- EXPECT_CALL(observer, OnItemUpdated(item3, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item1, Eq(absl::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item3, Eq(absl::nullopt))).Times(1);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item1, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1, absl::nullopt);
provider_.RemoveItem(id1);
}
{
- EXPECT_CALL(observer, OnItemUpdated(item1, Eq(base::nullopt))).Times(1);
- EXPECT_CALL(observer, OnItemUpdated(item4, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item1, Eq(absl::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item4, Eq(absl::nullopt))).Times(1);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item1, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1, absl::nullopt);
provider_.CancelDownload(id1);
}
{
- EXPECT_CALL(observer, OnItemUpdated(item1, Eq(base::nullopt))).Times(1);
- EXPECT_CALL(observer, OnItemUpdated(item5, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item1, Eq(absl::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item5, Eq(absl::nullopt))).Times(1);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item1, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1, absl::nullopt);
provider_.PauseDownload(id1);
}
{
- EXPECT_CALL(observer, OnItemUpdated(item1, Eq(base::nullopt))).Times(1);
- EXPECT_CALL(observer, OnItemUpdated(item6, Eq(base::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item1, Eq(absl::nullopt))).Times(1);
+ EXPECT_CALL(observer, OnItemUpdated(item6, Eq(absl::nullopt))).Times(1);
provider_.set_last_update_time(base::TimeTicks::Now());
- wrapped_provider_.NotifyOnItemUpdated(item1, base::nullopt);
+ wrapped_provider_.NotifyOnItemUpdated(item1, absl::nullopt);
provider_.ResumeDownload(id1, false);
}
}
diff --git a/chromium/components/offline_items_collection/core/update_delta.cc b/chromium/components/offline_items_collection/core/update_delta.cc
index 94636e52852..f3e01a3cb67 100644
--- a/chromium/components/offline_items_collection/core/update_delta.cc
+++ b/chromium/components/offline_items_collection/core/update_delta.cc
@@ -7,9 +7,9 @@
namespace offline_items_collection {
// static
-base::Optional<UpdateDelta> UpdateDelta::MergeUpdates(
- const base::Optional<UpdateDelta>& update1,
- const base::Optional<UpdateDelta>& update2) {
+absl::optional<UpdateDelta> UpdateDelta::MergeUpdates(
+ const absl::optional<UpdateDelta>& update1,
+ const absl::optional<UpdateDelta>& update2) {
if (!update1.has_value())
return update2;
diff --git a/chromium/components/offline_items_collection/core/update_delta.h b/chromium/components/offline_items_collection/core/update_delta.h
index fdfbd0d8624..58eb779a15a 100644
--- a/chromium/components/offline_items_collection/core/update_delta.h
+++ b/chromium/components/offline_items_collection/core/update_delta.h
@@ -5,7 +5,7 @@
#ifndef COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_UPDATE_DELTA_H_
#define COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_UPDATE_DELTA_H_
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace offline_items_collection {
@@ -14,9 +14,9 @@ namespace offline_items_collection {
// to make a decision on whether to act on the new info contained in the offline
// item.
struct UpdateDelta {
- static base::Optional<UpdateDelta> MergeUpdates(
- const base::Optional<UpdateDelta>& update1,
- const base::Optional<UpdateDelta>& update2);
+ static absl::optional<UpdateDelta> MergeUpdates(
+ const absl::optional<UpdateDelta>& update1,
+ const absl::optional<UpdateDelta>& update2);
UpdateDelta();
UpdateDelta(const UpdateDelta& other);
diff --git a/chromium/components/offline_pages/core/BUILD.gn b/chromium/components/offline_pages/core/BUILD.gn
index e674e792eea..f686e932662 100644
--- a/chromium/components/offline_pages/core/BUILD.gn
+++ b/chromium/components/offline_pages/core/BUILD.gn
@@ -166,7 +166,6 @@ source_set("unit_tests") {
"model/visuals_availability_task_unittest.cc",
"offline_event_logger_unittest.cc",
"offline_page_client_policy_unittest.cc",
- "offline_page_feature_unittest.cc",
"offline_page_item_utils_unittest.cc",
"offline_page_metadata_store_unittest.cc",
"offline_page_model_event_logger_unittest.cc",
diff --git a/chromium/components/offline_pages/core/auto_fetch.cc b/chromium/components/offline_pages/core/auto_fetch.cc
index 95b55698500..c81308de026 100644
--- a/chromium/components/offline_pages/core/auto_fetch.cc
+++ b/chromium/components/offline_pages/core/auto_fetch.cc
@@ -21,15 +21,15 @@ ClientId MakeClientId(const ClientIdMetadata& metadata) {
base::StrCat({"A", std::to_string(metadata.android_tab_id)}));
}
-base::Optional<ClientIdMetadata> ExtractMetadata(const ClientId& id) {
+absl::optional<ClientIdMetadata> ExtractMetadata(const ClientId& id) {
if (id.name_space != kAutoAsyncNamespace)
- return base::nullopt;
+ return absl::nullopt;
if (id.id.empty() || id.id[0] != 'A')
- return base::nullopt;
+ return absl::nullopt;
ClientIdMetadata metadata;
if (!base::StringToInt(base::StringPiece(id.id).substr(1),
&metadata.android_tab_id))
- return base::nullopt;
+ return absl::nullopt;
return metadata;
}
diff --git a/chromium/components/offline_pages/core/auto_fetch.h b/chromium/components/offline_pages/core/auto_fetch.h
index 25ecee5a540..791d0702d06 100644
--- a/chromium/components/offline_pages/core/auto_fetch.h
+++ b/chromium/components/offline_pages/core/auto_fetch.h
@@ -5,8 +5,8 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_AUTO_FETCH_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_AUTO_FETCH_H_
-#include "base/optional.h"
#include "components/offline_pages/core/client_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
// Most auto-fetch code is in browser/offline_pages. This file contains code
// that needs to be accessed within components/offline_pages.
@@ -26,7 +26,7 @@ struct ClientIdMetadata {
ClientId MakeClientId(const ClientIdMetadata& metadata);
// Extract metadata from a |ClientId| that was created with |MakeClientId|.
-base::Optional<ClientIdMetadata> ExtractMetadata(const ClientId& id);
+absl::optional<ClientIdMetadata> ExtractMetadata(const ClientId& id);
} // namespace auto_fetch
} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/auto_fetch_unittest.cc b/chromium/components/offline_pages/core/auto_fetch_unittest.cc
index e677426c88d..2a0d97ee4cc 100644
--- a/chromium/components/offline_pages/core/auto_fetch_unittest.cc
+++ b/chromium/components/offline_pages/core/auto_fetch_unittest.cc
@@ -17,7 +17,7 @@ TEST(AutoFetch, MakeClientId) {
}
TEST(AutoFetch, ExtractMetadataSuccess) {
- base::Optional<auto_fetch::ClientIdMetadata> metadata =
+ absl::optional<auto_fetch::ClientIdMetadata> metadata =
auto_fetch::ExtractMetadata(
auto_fetch::MakeClientId(auto_fetch::ClientIdMetadata(123)));
ASSERT_TRUE(metadata);
diff --git a/chromium/components/offline_pages/core/background/change_requests_state_task_unittest.cc b/chromium/components/offline_pages/core/background/change_requests_state_task_unittest.cc
index 79e5bb0c105..18ebab22988 100644
--- a/chromium/components/offline_pages/core/background/change_requests_state_task_unittest.cc
+++ b/chromium/components/offline_pages/core/background/change_requests_state_task_unittest.cc
@@ -18,6 +18,7 @@
namespace offline_pages {
namespace {
+
const int64_t kRequestId1 = 42;
const int64_t kRequestId2 = 43;
const int64_t kRequestId3 = 44;
@@ -25,15 +26,6 @@ const int64_t kRequestId3 = 44;
const ClientId kClientId1("bookmark", "1234");
const ClientId kClientId2("async", "5678");
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("http://example.com");
-}
-GURL Url2() {
- return GURL("http://another-example.com");
-}
-
class ChangeRequestsStateTaskTest : public RequestQueueTaskTestBase {
public:
~ChangeRequestsStateTaskTest() override = default;
@@ -52,13 +44,13 @@ class ChangeRequestsStateTaskTest : public RequestQueueTaskTestBase {
void ChangeRequestsStateTaskTest::AddItemsToStore() {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time,
- true);
+ SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1,
+ creation_time, true);
store_.AddRequest(request_1, RequestQueue::AddOptions(),
base::BindOnce(&ChangeRequestsStateTaskTest::AddRequestDone,
base::Unretained(this)));
- SavePageRequest request_2(kRequestId2, Url2(), kClientId2, creation_time,
- true);
+ SavePageRequest request_2(kRequestId2, GURL("http://another-example.com"),
+ kClientId2, creation_time, true);
store_.AddRequest(request_2, RequestQueue::AddOptions(),
base::BindOnce(&ChangeRequestsStateTaskTest::AddRequestDone,
base::Unretained(this)));
diff --git a/chromium/components/offline_pages/core/background/cleanup_task_unittest.cc b/chromium/components/offline_pages/core/background/cleanup_task_unittest.cc
index 5b5f70ababc..b2f1a909b59 100644
--- a/chromium/components/offline_pages/core/background/cleanup_task_unittest.cc
+++ b/chromium/components/offline_pages/core/background/cleanup_task_unittest.cc
@@ -23,8 +23,8 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace offline_pages {
-
namespace {
+
// Data for request 1.
const int64_t kRequestId1 = 17;
const ClientId kClientId1("bookmark", "1234");
@@ -34,16 +34,6 @@ const int64_t kRequestId2 = 42;
const ClientId kClientId2("bookmark", "5678");
const bool kUserRequested = true;
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("https://google.com");
-}
-
-GURL Url2() {
- return GURL("http://nytimes.com");
-}
-
// Default request
SavePageRequest EmptyRequest() {
return SavePageRequest(0UL, GURL(""), ClientId("", ""), base::Time(), true);
@@ -171,10 +161,10 @@ TEST_F(CleanupTaskTest, CleanupExpiredRequest) {
creation_time - base::TimeDelta::FromSeconds(
policy()->GetRequestExpirationTimeInSeconds() + 10);
// Request2 will be expired, request1 will be current.
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, expired_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ expired_time, kUserRequested);
QueueRequests(request1, request2);
// Initiate cleanup.
@@ -192,10 +182,10 @@ TEST_F(CleanupTaskTest, CleanupExpiredRequest) {
TEST_F(CleanupTaskTest, CleanupStartCountExceededRequest) {
base::Time creation_time = OfflineTimeNow();
// Request2 will have an exceeded start count.
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
request2.set_started_attempt_count(policy()->GetMaxStartedTries());
QueueRequests(request1, request2);
@@ -214,10 +204,10 @@ TEST_F(CleanupTaskTest, CleanupStartCountExceededRequest) {
TEST_F(CleanupTaskTest, CleanupCompletionCountExceededRequest) {
base::Time creation_time = OfflineTimeNow();
// Request2 will have an exceeded completion count.
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
request2.set_completed_attempt_count(policy()->GetMaxCompletedTries());
QueueRequests(request1, request2);
@@ -237,12 +227,12 @@ TEST_F(CleanupTaskTest, IgnoreRequestInProgress) {
base::Time creation_time = OfflineTimeNow();
// Both requests will have an exceeded completion count.
// The first request will be marked as started.
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
request1.set_completed_attempt_count(policy()->GetMaxCompletedTries());
request1.MarkAttemptStarted(creation_time);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
request2.set_completed_attempt_count(policy()->GetMaxCompletedTries());
QueueRequests(request1, request2);
diff --git a/chromium/components/offline_pages/core/background/connection_notifier.h b/chromium/components/offline_pages/core/background/connection_notifier.h
index 4edde82e960..b51d7d35c55 100644
--- a/chromium/components/offline_pages/core/background/connection_notifier.h
+++ b/chromium/components/offline_pages/core/background/connection_notifier.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_OFFLINE_PAGES_BACKGROUND____CORE_BACKGROUND_CONNECTION_NOTIFIER_H_
-#define COMPONENTS_OFFLINE_PAGES_BACKGROUND____CORE_BACKGROUND_CONNECTION_NOTIFIER_H_
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_CONNECTION_NOTIFIER_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_CONNECTION_NOTIFIER_H_
#include "base/callback.h"
#include "net/base/network_change_notifier.h"
@@ -31,4 +31,4 @@ class ConnectionNotifier
} // namespace offline_pages
-#endif // COMPONENTS_OFFLINE_PAGES_BACKGROUND____CORE_BACKGROUND_CONNECTION_NOTIFIER_H_
+#endif // COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_CONNECTION_NOTIFIER_H_
diff --git a/chromium/components/offline_pages/core/background/get_requests_task.h b/chromium/components/offline_pages/core/background/get_requests_task.h
index edf68004527..287b96c31e9 100644
--- a/chromium/components/offline_pages/core/background/get_requests_task.h
+++ b/chromium/components/offline_pages/core/background/get_requests_task.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_OFFLINE_PAGES_BACKGROUND____CORE_BACKGROUND_GET_REQUESTS_TASK_H_
-#define COMPONENTS_OFFLINE_PAGES_BACKGROUND____CORE_BACKGROUND_GET_REQUESTS_TASK_H_
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_GET_REQUESTS_TASK_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_GET_REQUESTS_TASK_H_
#include <memory>
#include <vector>
@@ -41,4 +41,4 @@ class GetRequestsTask : public Task {
} // namespace offline_pages
-#endif // COMPONENTS_OFFLINE_PAGES_BACKGROUND____CORE_BACKGROUND_GET_REQUESTS_TASK_H_
+#endif // COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_GET_REQUESTS_TASK_H_
diff --git a/chromium/components/offline_pages/core/background/get_requests_task_unittest.cc b/chromium/components/offline_pages/core/background/get_requests_task_unittest.cc
index e9f98f2b329..162de234c71 100644
--- a/chromium/components/offline_pages/core/background/get_requests_task_unittest.cc
+++ b/chromium/components/offline_pages/core/background/get_requests_task_unittest.cc
@@ -18,21 +18,13 @@
namespace offline_pages {
namespace {
+
const int64_t kRequestId1 = 42;
const int64_t kRequestId2 = 44;
const ClientId kClientId1("download", "1234");
const ClientId kClientId2("download", "5678");
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("http://example.com");
-}
-GURL Url2() {
- return GURL("http://otherexample.com");
-}
-
class GetRequestsTaskTest : public RequestQueueTaskTestBase {
public:
GetRequestsTaskTest() = default;
@@ -63,13 +55,13 @@ class GetRequestsTaskTest : public RequestQueueTaskTestBase {
void GetRequestsTaskTest::AddItemsToStore(RequestQueueStore* store) {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time,
- true);
+ SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1,
+ creation_time, true);
store->AddRequest(request_1, RequestQueue::AddOptions(),
base::BindOnce(&GetRequestsTaskTest::AddRequestDone));
creation_time = OfflineTimeNow();
- SavePageRequest request_2(kRequestId2, Url2(), kClientId2, creation_time,
- true);
+ SavePageRequest request_2(kRequestId2, GURL("http://otherexample.com"),
+ kClientId2, creation_time, true);
store->AddRequest(request_2, RequestQueue::AddOptions(),
base::BindOnce(&GetRequestsTaskTest::AddRequestDone));
PumpLoop();
diff --git a/chromium/components/offline_pages/core/background/initialize_store_task.h b/chromium/components/offline_pages/core/background/initialize_store_task.h
index 9b155a3f0a3..ff6dc1e2d6e 100644
--- a/chromium/components/offline_pages/core/background/initialize_store_task.h
+++ b/chromium/components/offline_pages/core/background/initialize_store_task.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_OFFLINE_PAGES_BACKGROUND____CORE_BACKGROUND_INITIALIZE_STORE_TASK_H_
-#define COMPONENTS_OFFLINE_PAGES_BACKGROUND____CORE_BACKGROUND_INITIALIZE_STORE_TASK_H_
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_INITIALIZE_STORE_TASK_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_INITIALIZE_STORE_TASK_H_
#include <stdint.h>
@@ -54,4 +54,4 @@ class InitializeStoreTask : public Task {
} // namespace offline_pages
-#endif // COMPONENTS_OFFLINE_PAGES_BACKGROUND____CORE_BACKGROUND_INITIALIZE_STORE_TASK_H_
+#endif // COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_INITIALIZE_STORE_TASK_H_
diff --git a/chromium/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc b/chromium/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc
index 4c9c1ccd506..187c894c3f2 100644
--- a/chromium/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc
+++ b/chromium/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc
@@ -21,17 +21,12 @@
namespace offline_pages {
namespace {
+
const int64_t kRequestId1 = 42;
const int64_t kRequestId2 = 44;
const ClientId kClientId1("download", "1234");
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("http://example.com");
-}
-
class MarkAttemptAbortedTaskTest : public RequestQueueTaskTestBase {
public:
MarkAttemptAbortedTaskTest() {}
@@ -53,8 +48,8 @@ class MarkAttemptAbortedTaskTest : public RequestQueueTaskTestBase {
void MarkAttemptAbortedTaskTest::AddItemToStore(RequestQueueStore* store) {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time,
- true);
+ SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1,
+ creation_time, true);
store->AddRequest(request_1, RequestQueue::AddOptions(),
base::BindOnce(&MarkAttemptAbortedTaskTest::AddRequestDone,
base::Unretained(this)));
diff --git a/chromium/components/offline_pages/core/background/mark_attempt_completed_task.h b/chromium/components/offline_pages/core/background/mark_attempt_completed_task.h
index 355449c989b..dae8b2b44a8 100644
--- a/chromium/components/offline_pages/core/background/mark_attempt_completed_task.h
+++ b/chromium/components/offline_pages/core/background/mark_attempt_completed_task.h
@@ -6,7 +6,6 @@
#define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_MARK_ATTEMPT_COMPLETED_TASK_H_
#include <stdint.h>
-#include <memory>
#include "components/offline_items_collection/core/fail_state.h"
#include "components/offline_pages/core/background/request_queue_results.h"
diff --git a/chromium/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc b/chromium/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc
index 2a4dba37063..17930bb596b 100644
--- a/chromium/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc
+++ b/chromium/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc
@@ -17,17 +17,12 @@
namespace offline_pages {
namespace {
+
const int64_t kRequestId1 = 42;
const int64_t kRequestId2 = 44;
const ClientId kClientId1("download", "1234");
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("http://example.com");
-}
-
class MarkAttemptCompletedTaskTest : public RequestQueueTaskTestBase {
public:
MarkAttemptCompletedTaskTest() {}
@@ -48,8 +43,8 @@ class MarkAttemptCompletedTaskTest : public RequestQueueTaskTestBase {
void MarkAttemptCompletedTaskTest::AddStartedItemToStore() {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time,
- true);
+ SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1,
+ creation_time, true);
request_1.MarkAttemptStarted(OfflineTimeNow());
store_.AddRequest(
request_1, RequestQueue::AddOptions(),
diff --git a/chromium/components/offline_pages/core/background/mark_attempt_deferred_task.h b/chromium/components/offline_pages/core/background/mark_attempt_deferred_task.h
index 35de79e35ae..0ae2f545f3d 100644
--- a/chromium/components/offline_pages/core/background/mark_attempt_deferred_task.h
+++ b/chromium/components/offline_pages/core/background/mark_attempt_deferred_task.h
@@ -6,7 +6,6 @@
#define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_MARK_ATTEMPT_DEFERRED_TASK_H_
#include <stdint.h>
-#include <memory>
#include "components/offline_items_collection/core/fail_state.h"
#include "components/offline_pages/core/background/request_queue_results.h"
diff --git a/chromium/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc b/chromium/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc
index f48de0eefa4..29ee97121cc 100644
--- a/chromium/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc
+++ b/chromium/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc
@@ -18,16 +18,11 @@
namespace offline_pages {
namespace {
+
const int64_t kRequestId1 = 42;
const int64_t kRequestId2 = 44;
const ClientId kClientId1("download", "1234");
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("http://example.com");
-}
-
class MarkAttemptStartedTaskTest : public RequestQueueTaskTestBase {
public:
MarkAttemptStartedTaskTest() {}
@@ -48,8 +43,8 @@ class MarkAttemptStartedTaskTest : public RequestQueueTaskTestBase {
void MarkAttemptStartedTaskTest::AddItemToStore() {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time,
- true);
+ SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1,
+ creation_time, true);
store_.AddRequest(
request_1, RequestQueue::AddOptions(),
base::BindOnce(&MarkAttemptStartedTaskTest::AddRequestDone));
diff --git a/chromium/components/offline_pages/core/background/pick_request_task_unittest.cc b/chromium/components/offline_pages/core/background/pick_request_task_unittest.cc
index de1cf1b70f0..d6c263913f1 100644
--- a/chromium/components/offline_pages/core/background/pick_request_task_unittest.cc
+++ b/chromium/components/offline_pages/core/background/pick_request_task_unittest.cc
@@ -44,16 +44,6 @@ const bool kPreferEarlier = true;
const bool kPreferRetryCount = true;
const int kBackgroundProcessingTimeBudgetSeconds = 170;
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("https://google.com");
-}
-
-GURL Url2() {
- return GURL("http://nytimes.com");
-}
-
// Default request
SavePageRequest EmptyRequest() {
return SavePageRequest(0UL, GURL(""), ClientId("", ""), base::Time(), true);
@@ -231,10 +221,10 @@ TEST_F(PickRequestTaskTest, ChooseRequestWithHigherRetryCount) {
MakePickRequestTask();
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
request2.set_completed_attempt_count(kAttemptCount);
QueueRequests(request1, request2);
@@ -253,10 +243,10 @@ TEST_F(PickRequestTaskTest, ChooseRequestWithSameRetryCountButEarlier) {
base::Time creation_time1 =
OfflineTimeNow() - base::TimeDelta::FromSeconds(10);
base::Time creation_time2 = OfflineTimeNow();
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time1,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time2,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time1, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time2, kUserRequested);
QueueRequests(request1, request2);
@@ -278,10 +268,10 @@ TEST_F(PickRequestTaskTest, ChooseEarlierRequest) {
base::Time creation_time1 =
OfflineTimeNow() - base::TimeDelta::FromSeconds(10);
base::Time creation_time2 = OfflineTimeNow();
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time1,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time2,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time1, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time2, kUserRequested);
request2.set_completed_attempt_count(kAttemptCount);
QueueRequests(request1, request2);
@@ -302,10 +292,10 @@ TEST_F(PickRequestTaskTest, ChooseSameTimeRequestWithHigherRetryCount) {
MakePickRequestTask();
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
request2.set_completed_attempt_count(kAttemptCount);
QueueRequests(request1, request2);
@@ -326,10 +316,10 @@ TEST_F(PickRequestTaskTest, ChooseRequestWithLowerRetryCount) {
MakePickRequestTask();
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
request2.set_completed_attempt_count(kAttemptCount);
QueueRequests(request1, request2);
@@ -352,10 +342,10 @@ TEST_F(PickRequestTaskTest, ChooseLaterRequest) {
base::Time creation_time1 =
OfflineTimeNow() - base::TimeDelta::FromSeconds(10);
base::Time creation_time2 = OfflineTimeNow();
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time1,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time2,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time1, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time2, kUserRequested);
QueueRequests(request1, request2);
@@ -372,10 +362,10 @@ TEST_F(PickRequestTaskTest, ChooseNonExpiredRequest) {
base::Time expired_time =
creation_time - base::TimeDelta::FromSeconds(
policy_->GetRequestExpirationTimeInSeconds() + 60);
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, expired_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ expired_time, kUserRequested);
QueueRequests(request1, request2);
@@ -394,10 +384,10 @@ TEST_F(PickRequestTaskTest, ChooseRequestThatHasNotExceededStartLimit) {
base::Time creation_time1 =
OfflineTimeNow() - base::TimeDelta::FromSeconds(1);
base::Time creation_time2 = OfflineTimeNow();
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time1,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time2,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time1, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time2, kUserRequested);
// With default policy settings, we should choose the earlier request.
// However, we will make the earlier reqeust exceed the limit.
@@ -420,10 +410,10 @@ TEST_F(PickRequestTaskTest, ChooseRequestThatHasNotExceededCompletionLimit) {
base::Time creation_time1 =
OfflineTimeNow() - base::TimeDelta::FromSeconds(1);
base::Time creation_time2 = OfflineTimeNow();
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time1,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time2,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time1, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time2, kUserRequested);
// With default policy settings, we should choose the earlier request.
// However, we will make the earlier reqeust exceed the limit.
@@ -451,10 +441,10 @@ TEST_F(PickRequestTaskTest, ChooseRequestThatIsNotDisabled) {
MakePickRequestTask();
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
request2.set_completed_attempt_count(kAttemptCount);
// Add test requests on the Queue.
@@ -480,10 +470,10 @@ TEST_F(PickRequestTaskTest, ChoosePrioritizedRequests) {
MakePickRequestTask();
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
// Since default policy prefer untried requests, make request1 the favorable
// pick if no prioritized requests. But request2 is prioritized so it should
// be picked.
@@ -521,10 +511,10 @@ TEST_F(PickRequestTaskTest, ChooseFromTwoPrioritizedRequests) {
base::Time creation_time = OfflineTimeNow();
base::Time older_creation_time =
creation_time - base::TimeDelta::FromMinutes(10);
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, older_creation_time,
- kUserRequested);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ older_creation_time, kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
request2.set_completed_attempt_count(kAttemptCount);
// Add test requests on the Queue.
diff --git a/chromium/components/offline_pages/core/background/reconcile_task_unittest.cc b/chromium/components/offline_pages/core/background/reconcile_task_unittest.cc
index b35be552d30..6817b28b4c7 100644
--- a/chromium/components/offline_pages/core/background/reconcile_task_unittest.cc
+++ b/chromium/components/offline_pages/core/background/reconcile_task_unittest.cc
@@ -20,8 +20,8 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace offline_pages {
-
namespace {
+
// Data for request 1.
const int64_t kRequestId1 = 17;
const ClientId kClientId1("bookmark", "1234");
@@ -30,15 +30,6 @@ const int64_t kRequestId2 = 42;
const ClientId kClientId2("bookmark", "5678");
const bool kUserRequested = true;
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("https://google.com");
-}
-GURL Url2() {
- return GURL("http://nytimes.com");
-}
-
class ReconcileTaskTest : public RequestQueueTaskTestBase {
public:
ReconcileTaskTest() {}
@@ -118,11 +109,11 @@ void ReconcileTaskTest::MakeTask() {
TEST_F(ReconcileTaskTest, Reconcile) {
base::Time creation_time = OfflineTimeNow();
// Request2 will be expired, request1 will be current.
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
request1.set_request_state(SavePageRequest::RequestState::PAUSED);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
request2.set_request_state(SavePageRequest::RequestState::OFFLINING);
QueueRequests(request1, request2);
@@ -153,11 +144,11 @@ TEST_F(ReconcileTaskTest, Reconcile) {
TEST_F(ReconcileTaskTest, NothingToReconcile) {
base::Time creation_time = OfflineTimeNow();
// Request2 will be expired, request1 will be current.
- SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1,
+ creation_time, kUserRequested);
request1.set_request_state(SavePageRequest::RequestState::PAUSED);
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2,
+ creation_time, kUserRequested);
request2.set_request_state(SavePageRequest::RequestState::AVAILABLE);
QueueRequests(request1, request2);
diff --git a/chromium/components/offline_pages/core/background/remove_requests_task_unittest.cc b/chromium/components/offline_pages/core/background/remove_requests_task_unittest.cc
index a022f2d9a38..46b481d161d 100644
--- a/chromium/components/offline_pages/core/background/remove_requests_task_unittest.cc
+++ b/chromium/components/offline_pages/core/background/remove_requests_task_unittest.cc
@@ -25,15 +25,6 @@ const int64_t kRequestId3 = 44;
const ClientId kClientId1("bookmark", "1234");
const ClientId kClientId2("async", "5678");
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("http://example.com");
-}
-GURL Url2() {
- return GURL("http://another-example.com");
-}
-
class RemoveRequestsTaskTest : public RequestQueueTaskTestBase {
public:
RemoveRequestsTaskTest() {}
@@ -60,12 +51,12 @@ void RemoveRequestsTaskTest::PumpLoop() {
void RemoveRequestsTaskTest::AddRequestsToStore() {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time,
- true);
+ SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1,
+ creation_time, true);
store_.AddRequest(request_1, RequestQueue::AddOptions(),
base::BindOnce(&RemoveRequestsTaskTest::AddRequestDone));
- SavePageRequest request_2(kRequestId2, Url2(), kClientId2, creation_time,
- true);
+ SavePageRequest request_2(kRequestId2, GURL("http://another-example.com"),
+ kClientId2, creation_time, true);
store_.AddRequest(request_2, RequestQueue::AddOptions(),
base::BindOnce(&RemoveRequestsTaskTest::AddRequestDone));
PumpLoop();
diff --git a/chromium/components/offline_pages/core/background/request_coordinator.cc b/chromium/components/offline_pages/core/background/request_coordinator.cc
index 7ad85ef07fc..ab220e9d3d6 100644
--- a/chromium/components/offline_pages/core/background/request_coordinator.cc
+++ b/chromium/components/offline_pages/core/background/request_coordinator.cc
@@ -206,9 +206,9 @@ constexpr bool IsCanceledOrInternalFailure(Offliner::RequestStatus status) {
}
// Returns the |BackgroundSavePageResult| appropriate for a single attempt
-// status. Returns |base::nullopt| for indeterminate status values that can be
+// status. Returns |absl::nullopt| for indeterminate status values that can be
// retried.
-base::Optional<RequestNotifier::BackgroundSavePageResult> SingleAttemptResult(
+absl::optional<RequestNotifier::BackgroundSavePageResult> SingleAttemptResult(
Offliner::RequestStatus status) {
switch (status) {
// Success status values.
@@ -224,7 +224,7 @@ base::Optional<RequestNotifier::BackgroundSavePageResult> SingleAttemptResult(
case Offliner::RequestStatus::LOADING_DEFERRED:
case Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED:
case Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED:
- return base::nullopt;
+ return absl::nullopt;
// Other failure status values.
case Offliner::RequestStatus::LOADING_FAILED_NO_RETRY:
@@ -241,7 +241,7 @@ base::Optional<RequestNotifier::BackgroundSavePageResult> SingleAttemptResult(
case Offliner::RequestStatus::LOADING_FAILED_HTTP_ERROR:
case Offliner::RequestStatus::LOADING_FAILED_NO_NEXT:
case Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT:
- return base::nullopt;
+ return absl::nullopt;
// Only used by |Offliner| internally.
case Offliner::RequestStatus::UNKNOWN:
@@ -251,7 +251,7 @@ base::Optional<RequestNotifier::BackgroundSavePageResult> SingleAttemptResult(
// Only recorded by |RequestCoordinator| directly.
case Offliner::RequestStatus::BROWSER_KILLED:
DCHECK(false) << "Received invalid status: " << static_cast<int>(status);
- return base::nullopt;
+ return absl::nullopt;
}
}
@@ -1012,7 +1012,7 @@ void RequestCoordinator::OfflinerDoneCallback(const SavePageRequest& request,
void RequestCoordinator::UpdateRequestForAttempt(
const SavePageRequest& request,
Offliner::RequestStatus status) {
- base::Optional<RequestNotifier::BackgroundSavePageResult> attempt_result =
+ absl::optional<RequestNotifier::BackgroundSavePageResult> attempt_result =
SingleAttemptResult(status);
// If the request failed, report the connection type as of the start of the
diff --git a/chromium/components/offline_pages/core/background/request_coordinator_unittest.cc b/chromium/components/offline_pages/core/background/request_coordinator_unittest.cc
index 3ab671ab1c0..2a68f9ac1b3 100644
--- a/chromium/components/offline_pages/core/background/request_coordinator_unittest.cc
+++ b/chromium/components/offline_pages/core/background/request_coordinator_unittest.cc
@@ -56,15 +56,6 @@ const bool kUserRequested = true;
const int kAttemptCount = 1;
const std::string kRequestOrigin("abc.xyz");
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("http://universe.com/everything");
-}
-GURL Url2() {
- return GURL("http://universe.com/toinfinityandbeyond");
-}
-
class BoolCallbackResult {
public:
base::RepeatingCallback<void(bool)> Bind() {
@@ -327,7 +318,7 @@ class RequestCoordinatorTest : public testing::Test {
int64_t SavePageLater() {
RequestCoordinator::SavePageLaterParams params;
- params.url = Url1();
+ params.url = GURL("http://universe.com/everything");
params.client_id = kClientId1;
params.user_requested = kUserRequested;
params.request_origin = kRequestOrigin;
@@ -339,7 +330,7 @@ class RequestCoordinatorTest : public testing::Test {
int64_t SavePageLaterWithAvailability(
RequestCoordinator::RequestAvailability availability) {
RequestCoordinator::SavePageLaterParams params;
- params.url = Url1();
+ params.url = GURL("http://universe.com/everything");
params.client_id = kClientId1;
params.user_requested = kUserRequested;
params.availability = availability;
@@ -524,15 +515,17 @@ void RequestCoordinatorTest::SendOfflinerDoneCallback(
}
SavePageRequest RequestCoordinatorTest::AddRequest1() {
- offline_pages::SavePageRequest request1(kRequestId1, Url1(), kClientId1,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request1(
+ kRequestId1, GURL("http://universe.com/everything"), kClientId1,
+ OfflineTimeNow(), kUserRequested);
queue()->AddRequest(request1, RequestQueue::AddOptions(), base::DoNothing());
return request1;
}
SavePageRequest RequestCoordinatorTest::AddRequest2() {
- offline_pages::SavePageRequest request2(kRequestId2, Url2(), kClientId2,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request2(
+ kRequestId2, GURL("http://universe.com/toinfinityandbeyond"), kClientId2,
+ OfflineTimeNow(), kUserRequested);
queue()->AddRequest(request2, RequestQueue::AddOptions(), base::DoNothing());
return request2;
}
@@ -645,10 +638,12 @@ TEST_F(RequestCoordinatorTest, SavePageLater) {
processing_callback());
// Use default values for |user_requested| and |availability|.
+ const GURL kUrl1("http://universe.com/everything");
+ const GURL kUrl2("http://universe.com/toinfinityandbeyond");
RequestCoordinator::SavePageLaterParams params;
- params.url = Url1();
+ params.url = kUrl1;
params.client_id = kClientId1;
- params.original_url = Url2();
+ params.original_url = kUrl2;
params.request_origin = kRequestOrigin;
EXPECT_NE(0, coordinator()->SavePageLater(
params, base::BindOnce(
@@ -669,10 +664,10 @@ TEST_F(RequestCoordinatorTest, SavePageLater) {
// Check the request queue is as expected.
ASSERT_EQ(1UL, last_requests().size());
- EXPECT_EQ(Url1(), last_requests().at(0)->url());
+ EXPECT_EQ(kUrl1, last_requests().at(0)->url());
EXPECT_EQ(kClientId1, last_requests().at(0)->client_id());
EXPECT_TRUE(last_requests().at(0)->user_requested());
- EXPECT_EQ(Url2(), last_requests().at(0)->original_url());
+ EXPECT_EQ(kUrl2, last_requests().at(0)->original_url());
EXPECT_EQ(kRequestOrigin, last_requests().at(0)->request_origin());
// Expect that the scheduler got notified.
@@ -720,7 +715,8 @@ TEST_F(RequestCoordinatorTest, SavePageLaterFailed) {
EXPECT_TRUE(add_request_callback_called());
// Check the request queue is as expected.
EXPECT_EQ(1UL, last_requests().size());
- EXPECT_EQ(Url1(), last_requests().at(0)->url());
+ EXPECT_EQ(GURL("http://universe.com/everything"),
+ last_requests().at(0)->url());
EXPECT_EQ(kClientId1, last_requests().at(0)->client_id());
// Expect that the scheduler got notified.
@@ -736,8 +732,9 @@ TEST_F(RequestCoordinatorTest, SavePageLaterFailed) {
TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceeded) {
// Add a request to the queue, wait for callbacks to finish.
- offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request(
+ kRequestId1, GURL("http://universe.com/everything"), kClientId1,
+ OfflineTimeNow(), kUserRequested);
SetupForOfflinerDoneCallbackTest(&request);
// Call the OfflinerDoneCallback to simulate the page being completed, wait
@@ -767,8 +764,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceeded) {
TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceededButLostNetwork) {
// Add a request to the queue and set offliner done callback for it.
- offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request(
+ kRequestId1, GURL("http://universe.com/everything"), kClientId1,
+ OfflineTimeNow(), kUserRequested);
SetupForOfflinerDoneCallbackTest(&request);
EnableOfflinerCallback(false);
@@ -796,8 +794,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceededButLostNetwork) {
TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailed) {
// Add a request to the queue, wait for callbacks to finish.
- offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request(
+ kRequestId1, GURL("http://universe.com/everything"), kClientId1,
+ OfflineTimeNow(), kUserRequested);
request.set_completed_attempt_count(kMaxCompletedTries - 1);
SetupForOfflinerDoneCallbackTest(&request);
// Stop processing before completing the second request on the queue.
@@ -839,8 +838,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailed) {
TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoRetryFailure) {
// Add a request to the queue, wait for callbacks to finish.
- offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request(
+ kRequestId1, GURL("http://universe.com/everything"), kClientId1,
+ OfflineTimeNow(), kUserRequested);
SetupForOfflinerDoneCallbackTest(&request);
EnableOfflinerCallback(false);
@@ -882,8 +882,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoRetryFailure) {
TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoNextFailure) {
// Add a request to the queue, wait for callbacks to finish.
- offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request(
+ kRequestId1, GURL("http://universe.com/everything"), kClientId1,
+ OfflineTimeNow(), kUserRequested);
SetupForOfflinerDoneCallbackTest(&request);
EnableOfflinerCallback(false);
@@ -914,8 +915,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoNextFailure) {
TEST_F(RequestCoordinatorTest, OfflinerDoneForegroundCancel) {
// Add a request to the queue, wait for callbacks to finish.
- offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request(
+ kRequestId1, GURL("http://universe.com/everything"), kClientId1,
+ OfflineTimeNow(), kUserRequested);
SetupForOfflinerDoneCallbackTest(&request);
// Call the OfflinerDoneCallback to simulate the request failed, wait
@@ -941,7 +943,7 @@ TEST_F(RequestCoordinatorTest, RequestDeferred) {
// defer_while_page_is_active.
active_tab_info_->set_does_active_tab_match(true);
RequestCoordinator::SavePageLaterParams params;
- params.url = Url1();
+ params.url = GURL("http://universe.com/everything");
// Auto-async uses defer_background_fetch_while_page_is_active.
params.client_id = ClientId(kAutoAsyncNamespace, "1");
coordinator()->SavePageLater(params, base::DoNothing());
@@ -977,7 +979,7 @@ TEST_F(RequestCoordinatorTest, RequestNotDeferred) {
// false. The page should be offlined.
active_tab_info_->set_does_active_tab_match(false);
RequestCoordinator::SavePageLaterParams params;
- params.url = Url1();
+ params.url = GURL("http://universe.com/everything");
// Auto-async uses defer_background_fetch_while_page_is_active.
params.client_id = ClientId(kAutoAsyncNamespace, "1");
coordinator()->SavePageLater(params, base::DoNothing());
@@ -1045,8 +1047,9 @@ TEST_F(RequestCoordinatorTest, SchedulerGetsLeastRestrictiveConditions) {
// the second is not user requested.
AddRequest1();
- offline_pages::SavePageRequest request2(kRequestId2, Url2(), kClientId2,
- OfflineTimeNow(), !kUserRequested);
+ offline_pages::SavePageRequest request2(
+ kRequestId2, GURL("http://universe.com/toinfinityandbeyond"), kClientId2,
+ OfflineTimeNow(), !kUserRequested);
queue()->AddRequest(request2, RequestQueue::AddOptions(), base::DoNothing());
PumpLoop();
@@ -1268,7 +1271,7 @@ TEST_F(RequestCoordinatorTest, RemoveInflightRequestAndAddAnother) {
// Add a new request, and remove current request while it is processing.
RequestCoordinator::SavePageLaterParams request2;
- request2.url = Url2();
+ request2.url = GURL("http://universe.com/toinfinityandbeyond");
request2.client_id = kClientId2;
request2.user_requested = true;
coordinator()->SavePageLater(request2, base::DoNothing());
@@ -1344,8 +1347,9 @@ TEST_F(RequestCoordinatorTest, EnableForOffliner) {
TEST_F(RequestCoordinatorTest,
WatchdogTimeoutForScheduledProcessingNoLastSnapshot) {
// Build a request to use with the pre-renderer, and put it on the queue.
- offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request(
+ kRequestId1, GURL("http://universe.com/everything"), kClientId1,
+ OfflineTimeNow(), kUserRequested);
// Set request to allow one more completed attempt.
int max_tries = coordinator()->policy()->GetMaxCompletedTries();
request.set_completed_attempt_count(max_tries - 1);
@@ -1417,8 +1421,9 @@ TEST_F(RequestCoordinatorTest, TimeBudgetExceeded) {
// Build two requests to use with the pre-renderer, and put it on the queue.
AddRequest1();
// The second request will have a larger completed attempt count.
- offline_pages::SavePageRequest request2(kRequestId1 + 1, Url1(), kClientId1,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request2(
+ kRequestId1 + 1, GURL("http://universe.com/everything"), kClientId1,
+ OfflineTimeNow(), kUserRequested);
request2.set_completed_attempt_count(kAttemptCount);
queue()->AddRequest(request2, RequestQueue::AddOptions(), base::DoNothing());
PumpLoop();
@@ -1701,8 +1706,9 @@ TEST_F(RequestCoordinatorTest,
TEST_F(RequestCoordinatorTest, SnapshotOnLastTryForScheduledProcessing) {
// Build a request to use with the pre-renderer, and put it on the queue.
- offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1,
- OfflineTimeNow(), kUserRequested);
+ offline_pages::SavePageRequest request(
+ kRequestId1, GURL("http://universe.com/everything"), kClientId1,
+ OfflineTimeNow(), kUserRequested);
// Set request to allow one more completed attempt. So that the next try would
// be the last retry.
int max_tries = coordinator()->policy()->GetMaxCompletedTries();
@@ -1867,7 +1873,7 @@ TEST_F(RequestCoordinatorTest,
// Make a second request.
RequestCoordinator::SavePageLaterParams params;
- params.url = Url2();
+ params.url = GURL("http://universe.com/toinfinityandbeyond");
params.client_id = kClientId2;
params.user_requested = kUserRequested;
EXPECT_NE(0, coordinator()->SavePageLater(
@@ -1888,7 +1894,7 @@ TEST_F(RequestCoordinatorTest, SavePageLaterRejectedDuplicateUrl) {
EnableOfflinerCallback(false);
RequestCoordinator::SavePageLaterParams params;
- params.url = Url1();
+ params.url = GURL("http://universe.com/everything");
params.client_id = kClientId1;
params.add_options.disallow_duplicate_requests = true;
std::vector<AddRequestResult> results;
diff --git a/chromium/components/offline_pages/core/background/request_queue.h b/chromium/components/offline_pages/core/background/request_queue.h
index e55e1f6b400..2bd0b696eac 100644
--- a/chromium/components/offline_pages/core/background/request_queue.h
+++ b/chromium/components/offline_pages/core/background/request_queue.h
@@ -9,7 +9,6 @@
#include <memory>
#include <set>
-#include <string>
#include <utility>
#include <vector>
diff --git a/chromium/components/offline_pages/core/background/request_queue_results.h b/chromium/components/offline_pages/core/background/request_queue_results.h
index 92567a14870..1d20ec160c3 100644
--- a/chromium/components/offline_pages/core/background/request_queue_results.h
+++ b/chromium/components/offline_pages/core/background/request_queue_results.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_OFFLINE_PAGES_BACKGROUND_REQUEST_QUEUE_RESULTS_H_
-#define COMPONENTS_OFFLINE_PAGES_BACKGROUND_REQUEST_QUEUE_RESULTS_H_
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_REQUEST_QUEUE_RESULTS_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_REQUEST_QUEUE_RESULTS_H_
#include "components/offline_pages/core/background/save_page_request.h"
#include "components/offline_pages/core/offline_store_types.h"
@@ -40,4 +40,4 @@ enum class UpdateRequestResult {
} // namespace offline_pages
-#endif // COMPONENTS_OFFLINE_PAGES_BACKGROUND_REQUEST_QUEUE_RESULTS_H_
+#endif // COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_REQUEST_QUEUE_RESULTS_H_
diff --git a/chromium/components/offline_pages/core/background/request_queue_store.cc b/chromium/components/offline_pages/core/background/request_queue_store.cc
index 10f4facba1a..68f58de1c00 100644
--- a/chromium/components/offline_pages/core/background/request_queue_store.cc
+++ b/chromium/components/offline_pages/core/background/request_queue_store.cc
@@ -389,7 +389,7 @@ bool InitDatabaseSync(sql::Database* db, const base::FilePath& path) {
return CreateSchemaSync(db);
}
-base::Optional<std::vector<std::unique_ptr<SavePageRequest>>>
+absl::optional<std::vector<std::unique_ptr<SavePageRequest>>>
GetAllRequestsSync(sql::Database* db) {
static const char kSql[] =
"SELECT " REQUEST_QUEUE_FIELDS " FROM " REQUEST_QUEUE_TABLE_NAME;
@@ -398,14 +398,14 @@ GetAllRequestsSync(sql::Database* db) {
while (statement.Step())
requests.push_back(MakeSavePageRequest(statement));
if (!statement.Succeeded())
- return base::nullopt;
+ return absl::nullopt;
return requests;
}
// Calls |callback| with the result of |requests|.
void InvokeGetRequestsCallback(
RequestQueueStore::GetRequestsCallback callback,
- base::Optional<std::vector<std::unique_ptr<SavePageRequest>>> requests) {
+ absl::optional<std::vector<std::unique_ptr<SavePageRequest>>> requests) {
if (requests) {
std::move(callback).Run(true, std::move(requests).value());
} else {
@@ -452,7 +452,7 @@ AddRequestResult AddRequestSync(sql::Database* db,
// check preconditions.
if (options.maximum_in_flight_requests_for_namespace > 0 ||
options.disallow_duplicate_requests) {
- base::Optional<std::vector<std::unique_ptr<SavePageRequest>>> requests =
+ absl::optional<std::vector<std::unique_ptr<SavePageRequest>>> requests =
GetAllRequestsSync(db);
if (!requests)
return AddRequestResult::STORE_FAILURE;
@@ -559,7 +559,7 @@ UpdateRequestsResult RemoveRequestsIfSync(
sql::Database* db,
const base::RepeatingCallback<bool(const SavePageRequest&)>&
remove_predicate) {
- base::Optional<std::vector<std::unique_ptr<SavePageRequest>>> requests =
+ absl::optional<std::vector<std::unique_ptr<SavePageRequest>>> requests =
GetAllRequestsSync(db);
if (!requests)
return UpdateRequestsResult(StoreState::LOADED);
diff --git a/chromium/components/offline_pages/core/background/request_queue_store_unittest.cc b/chromium/components/offline_pages/core/background/request_queue_store_unittest.cc
index 3d9eda8db82..11a2714e52c 100644
--- a/chromium/components/offline_pages/core/background/request_queue_store_unittest.cc
+++ b/chromium/components/offline_pages/core/background/request_queue_store_unittest.cc
@@ -28,6 +28,7 @@ namespace offline_pages {
using UpdateStatus = RequestQueueStore::UpdateStatus;
namespace {
+
const int64_t kRequestId = 42;
const int64_t kRequestId2 = 44;
const int64_t kRequestId3 = 47;
@@ -42,17 +43,8 @@ enum class LastResult {
RESULT_TRUE,
};
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("http://example.com");
-}
-GURL Url2() {
- return GURL("http://another-example.com");
-}
-
-SavePageRequest GetTestRequest() {
- SavePageRequest request(kRequestId, Url1(), kClientId,
+SavePageRequest GetTestRequest(const GURL& url, const GURL& original_url) {
+ SavePageRequest request(kRequestId, url, kClientId,
base::Time::FromDeltaSinceWindowsEpoch(
base::TimeDelta::FromSeconds(1000)),
kUserRequested);
@@ -64,13 +56,14 @@ SavePageRequest GetTestRequest() {
base::TimeDelta::FromSeconds(400)));
request.set_request_origin("http://www.origin.com");
// Note: pending_state is not stored.
- request.set_original_url(Url2());
+ request.set_original_url(original_url);
request.set_auto_fetch_notification_state(
SavePageRequest::AutoFetchNotificationState::kShown);
return request;
}
-void BuildTestStoreWithSchemaFromM57(const base::FilePath& file) {
+void BuildTestStoreWithSchemaFromM57(const base::FilePath& file,
+ const GURL& url) {
sql::Database connection;
ASSERT_TRUE(
connection.Open(file.Append(FILE_PATH_LITERAL("RequestQueue.db"))));
@@ -106,7 +99,7 @@ void BuildTestStoreWithSchemaFromM57(const base::FilePath& file) {
statement.BindInt64(4, 0);
statement.BindInt64(5, 0);
statement.BindInt64(6, 0);
- statement.BindString(7, Url1().spec());
+ statement.BindString(7, url.spec());
statement.BindString(8, kClientId.name_space);
statement.BindString(9, kClientId.id);
ASSERT_TRUE(statement.Run());
@@ -115,7 +108,9 @@ void BuildTestStoreWithSchemaFromM57(const base::FilePath& file) {
connection.DoesColumnExist(REQUEST_QUEUE_TABLE_NAME, "original_url"));
}
-void BuildTestStoreWithSchemaFromM58(const base::FilePath& file) {
+void BuildTestStoreWithSchemaFromM58(const base::FilePath& file,
+ const GURL& url,
+ const GURL& original_url) {
sql::Database connection;
ASSERT_TRUE(
connection.Open(file.Append(FILE_PATH_LITERAL("RequestQueue.db"))));
@@ -152,17 +147,19 @@ void BuildTestStoreWithSchemaFromM58(const base::FilePath& file) {
statement.BindInt64(4, 0);
statement.BindInt64(5, 0);
statement.BindInt64(6, 0);
- statement.BindString(7, Url1().spec());
+ statement.BindString(7, url.spec());
statement.BindString(8, kClientId.name_space);
statement.BindString(9, kClientId.id);
- statement.BindString(10, Url2().spec());
+ statement.BindString(10, original_url.spec());
ASSERT_TRUE(statement.Run());
ASSERT_TRUE(connection.DoesTableExist(REQUEST_QUEUE_TABLE_NAME));
ASSERT_FALSE(
connection.DoesColumnExist(REQUEST_QUEUE_TABLE_NAME, "request_origin"));
}
-void BuildTestStoreWithSchemaFromM61(const base::FilePath& file) {
+void BuildTestStoreWithSchemaFromM61(const base::FilePath& file,
+ const GURL& url,
+ const GURL& original_url) {
sql::Database connection;
ASSERT_TRUE(
connection.Open(file.Append(FILE_PATH_LITERAL("RequestQueue.db"))));
@@ -200,10 +197,10 @@ void BuildTestStoreWithSchemaFromM61(const base::FilePath& file) {
statement.BindInt64(4, 0);
statement.BindInt64(5, 0);
statement.BindInt64(6, 0);
- statement.BindString(7, Url1().spec());
+ statement.BindString(7, url.spec());
statement.BindString(8, kClientId.name_space);
statement.BindString(9, kClientId.id);
- statement.BindString(10, Url2().spec());
+ statement.BindString(10, original_url.spec());
statement.BindString(11, kRequestOrigin);
ASSERT_TRUE(statement.Run());
ASSERT_TRUE(connection.DoesTableExist(REQUEST_QUEUE_TABLE_NAME));
@@ -211,7 +208,9 @@ void BuildTestStoreWithSchemaFromM61(const base::FilePath& file) {
connection.DoesColumnExist(REQUEST_QUEUE_TABLE_NAME, "fail_state"));
}
-void BuildTestStoreWithSchemaFromM72(const base::FilePath& file) {
+void BuildTestStoreWithSchemaFromM72(const base::FilePath& file,
+ const GURL& url,
+ const GURL& original_url) {
sql::Database connection;
ASSERT_TRUE(
connection.Open(file.Append(FILE_PATH_LITERAL("RequestQueue.db"))));
@@ -251,10 +250,10 @@ void BuildTestStoreWithSchemaFromM72(const base::FilePath& file) {
statement.BindInt64(4, 0);
statement.BindInt64(5, 0);
statement.BindInt64(6, 0);
- statement.BindString(7, Url1().spec());
+ statement.BindString(7, url.spec());
statement.BindString(8, kClientId.name_space);
statement.BindString(9, kClientId.id);
- statement.BindString(10, Url2().spec());
+ statement.BindString(10, original_url.spec());
statement.BindString(11, kRequestOrigin);
statement.BindInt64(12, 1);
ASSERT_TRUE(statement.Run());
@@ -291,7 +290,7 @@ class RequestQueueStoreTestBase : public testing::Test {
const std::vector<std::unique_ptr<SavePageRequest>>& last_requests() const {
return last_requests_;
}
- base::Optional<AddRequestResult> last_add_result() const {
+ absl::optional<AddRequestResult> last_add_result() const {
return last_add_result_;
}
@@ -305,7 +304,7 @@ class RequestQueueStoreTestBase : public testing::Test {
private:
LastResult last_result_;
UpdateStatus last_update_status_;
- base::Optional<AddRequestResult> last_add_result_;
+ absl::optional<AddRequestResult> last_add_result_;
std::unique_ptr<UpdateRequestsResult> last_update_result_;
std::vector<std::unique_ptr<SavePageRequest>> last_requests_;
@@ -333,7 +332,7 @@ void RequestQueueStoreTestBase::PumpLoop() {
void RequestQueueStoreTestBase::ClearResults() {
last_result_ = LastResult::RESULT_NONE;
last_update_status_ = UpdateStatus::FAILED;
- last_add_result_ = base::nullopt;
+ last_add_result_ = absl::nullopt;
last_requests_.clear();
last_update_result_.reset(nullptr);
}
@@ -381,15 +380,21 @@ class RequestQueueStoreTest : public RequestQueueStoreTestBase {
return std::make_unique<RequestQueueStore>(
base::ThreadTaskRunnerHandle::Get(), temp_directory_.GetPath());
}
- std::unique_ptr<RequestQueueStore> BuildStoreWithOldSchema(int version) {
+ std::unique_ptr<RequestQueueStore> BuildStoreWithOldSchema(
+ int version,
+ const GURL& url,
+ const GURL& original_url) {
if (version == 57) {
- BuildTestStoreWithSchemaFromM57(temp_directory_.GetPath());
+ BuildTestStoreWithSchemaFromM57(temp_directory_.GetPath(), url);
} else if (version == 58) {
- BuildTestStoreWithSchemaFromM58(temp_directory_.GetPath());
+ BuildTestStoreWithSchemaFromM58(temp_directory_.GetPath(), url,
+ original_url);
} else if (version == 61) {
- BuildTestStoreWithSchemaFromM61(temp_directory_.GetPath());
+ BuildTestStoreWithSchemaFromM61(temp_directory_.GetPath(), url,
+ original_url);
} else if (version == 72) {
- BuildTestStoreWithSchemaFromM72(temp_directory_.GetPath());
+ BuildTestStoreWithSchemaFromM72(temp_directory_.GetPath(), url,
+ original_url);
} else {
LOG(ERROR) << "Version " << version << " not implemented";
return nullptr;
@@ -400,7 +405,7 @@ class RequestQueueStoreTest : public RequestQueueStoreTestBase {
}
// Performs checks on the database to verify it works after upgrading.
- void PostUpgradeChecks(RequestQueueStore* store) {
+ void PostUpgradeChecks(RequestQueueStore* store, const GURL& url) {
// First, remove all requests.
{
store->GetRequests(base::BindOnce(
@@ -421,7 +426,7 @@ class RequestQueueStoreTest : public RequestQueueStoreTestBase {
}
// Verify a request can be added and retrieved.
- SavePageRequest request(kRequestId, Url1(), kClientId, OfflineTimeNow(),
+ SavePageRequest request(kRequestId, url, kClientId, OfflineTimeNow(),
kUserRequested);
store->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
@@ -443,7 +448,9 @@ class RequestQueueStoreTest : public RequestQueueStoreTestBase {
// defined on the |RequestQuieueStoreBaseTest| class. That's by design.
TEST_F(RequestQueueStoreTest, UpgradeFromVersion57Store) {
- std::unique_ptr<RequestQueueStore> store = BuildStoreWithOldSchema(57);
+ const GURL kUrl1("http://example.com");
+ std::unique_ptr<RequestQueueStore> store =
+ BuildStoreWithOldSchema(57, kUrl1, GURL());
this->InitializeStore(store.get());
store->GetRequests(base::BindOnce(&RequestQueueStoreTestBase::GetRequestsDone,
@@ -452,14 +459,17 @@ TEST_F(RequestQueueStoreTest, UpgradeFromVersion57Store) {
ASSERT_EQ(LastResult::RESULT_TRUE, this->last_result());
ASSERT_EQ(1u, this->last_requests().size());
EXPECT_EQ(kRequestId, this->last_requests()[0]->request_id());
- EXPECT_EQ(Url1(), this->last_requests()[0]->url());
+ EXPECT_EQ(kUrl1, this->last_requests()[0]->url());
EXPECT_EQ(GURL(), this->last_requests()[0]->original_url());
- PostUpgradeChecks(store.get());
+ PostUpgradeChecks(store.get(), kUrl1);
}
TEST_F(RequestQueueStoreTest, UpgradeFromVersion58Store) {
- std::unique_ptr<RequestQueueStore> store(BuildStoreWithOldSchema(58));
+ const GURL kUrl1("http://example.com");
+ const GURL kUrl2("http://another-example.com");
+ std::unique_ptr<RequestQueueStore> store(
+ BuildStoreWithOldSchema(58, kUrl1, kUrl2));
this->InitializeStore(store.get());
store->GetRequests(base::BindOnce(&RequestQueueStoreTestBase::GetRequestsDone,
@@ -468,15 +478,18 @@ TEST_F(RequestQueueStoreTest, UpgradeFromVersion58Store) {
ASSERT_EQ(LastResult::RESULT_TRUE, this->last_result());
ASSERT_EQ(1u, this->last_requests().size());
EXPECT_EQ(kRequestId, this->last_requests()[0]->request_id());
- EXPECT_EQ(Url1(), this->last_requests()[0]->url());
- EXPECT_EQ(Url2(), this->last_requests()[0]->original_url());
+ EXPECT_EQ(kUrl1, this->last_requests()[0]->url());
+ EXPECT_EQ(kUrl2, this->last_requests()[0]->original_url());
EXPECT_EQ("", this->last_requests()[0]->request_origin());
- PostUpgradeChecks(store.get());
+ PostUpgradeChecks(store.get(), kUrl1);
}
TEST_F(RequestQueueStoreTest, UpgradeFromVersion61Store) {
- std::unique_ptr<RequestQueueStore> store(BuildStoreWithOldSchema(61));
+ const GURL kUrl1("http://example.com");
+ const GURL kUrl2("http://another-example.com");
+ std::unique_ptr<RequestQueueStore> store(
+ BuildStoreWithOldSchema(61, kUrl1, kUrl2));
this->InitializeStore(store.get());
store->GetRequests(base::BindOnce(&RequestQueueStoreTestBase::GetRequestsDone,
@@ -485,16 +498,19 @@ TEST_F(RequestQueueStoreTest, UpgradeFromVersion61Store) {
ASSERT_EQ(LastResult::RESULT_TRUE, this->last_result());
ASSERT_EQ(1u, this->last_requests().size());
EXPECT_EQ(kRequestId, this->last_requests()[0]->request_id());
- EXPECT_EQ(Url1(), this->last_requests()[0]->url());
- EXPECT_EQ(Url2(), this->last_requests()[0]->original_url());
+ EXPECT_EQ(kUrl1, this->last_requests()[0]->url());
+ EXPECT_EQ(kUrl2, this->last_requests()[0]->original_url());
EXPECT_EQ(kRequestOrigin, this->last_requests()[0]->request_origin());
EXPECT_EQ(0, static_cast<int>(this->last_requests()[0]->fail_state()));
- PostUpgradeChecks(store.get());
+ PostUpgradeChecks(store.get(), kUrl1);
}
TEST_F(RequestQueueStoreTest, UpgradeFromVersion72Store) {
- std::unique_ptr<RequestQueueStore> store(BuildStoreWithOldSchema(72));
+ const GURL kUrl1("http://example.com");
+ const GURL kUrl2("http://another-example.com");
+ std::unique_ptr<RequestQueueStore> store(
+ BuildStoreWithOldSchema(72, kUrl1, kUrl2));
this->InitializeStore(store.get());
store->GetRequests(base::BindOnce(&RequestQueueStoreTestBase::GetRequestsDone,
@@ -505,13 +521,13 @@ TEST_F(RequestQueueStoreTest, UpgradeFromVersion72Store) {
this->last_requests();
ASSERT_EQ(1u, requests.size());
EXPECT_EQ(kRequestId, requests[0]->request_id());
- EXPECT_EQ(Url1(), requests[0]->url());
- EXPECT_EQ(Url2(), requests[0]->original_url());
+ EXPECT_EQ(kUrl1, requests[0]->url());
+ EXPECT_EQ(kUrl2, requests[0]->original_url());
EXPECT_EQ(kRequestOrigin, requests[0]->request_origin());
EXPECT_EQ(1, static_cast<int>(requests[0]->fail_state()));
EXPECT_EQ(0, static_cast<int>(requests[0]->auto_fetch_notification_state()));
- PostUpgradeChecks(store.get());
+ PostUpgradeChecks(store.get(), kUrl1);
}
TEST_F(RequestQueueStoreTest, GetRequestsEmpty) {
@@ -531,13 +547,13 @@ TEST_F(RequestQueueStoreTest, GetRequestsByIds) {
this->InitializeStore(store.get());
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request1(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
store->AddRequest(request1, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
base::Unretained(this)));
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://another-example.com"),
+ kClientId2, creation_time, kUserRequested);
store->AddRequest(request2, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
base::Unretained(this)));
@@ -592,14 +608,14 @@ TEST_F(RequestQueueStoreTest, AddRequest) {
this->InitializeStore(store.get());
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
- request.set_original_url(Url2());
+ SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
+ request.set_original_url(GURL("http://another-example.com"));
store->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
base::Unretained(this)));
- ASSERT_EQ(base::nullopt, this->last_add_result());
+ ASSERT_EQ(absl::nullopt, this->last_add_result());
this->PumpLoop();
ASSERT_EQ(AddRequestResult::SUCCESS, this->last_add_result());
@@ -618,7 +634,7 @@ TEST_F(RequestQueueStoreTest, AddRequest) {
store->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
base::Unretained(this)));
- ASSERT_EQ(base::nullopt, this->last_add_result());
+ ASSERT_EQ(absl::nullopt, this->last_add_result());
this->PumpLoop();
ASSERT_EQ(AddRequestResult::ALREADY_EXISTS, this->last_add_result());
@@ -635,7 +651,8 @@ TEST_F(RequestQueueStoreTest, AddRequest) {
TEST_F(RequestQueueStoreTest, AddAndGetRequestsMatch) {
std::unique_ptr<RequestQueueStore> store(this->BuildStore());
this->InitializeStore(store.get());
- const SavePageRequest request = GetTestRequest();
+ const SavePageRequest request = GetTestRequest(
+ GURL("http://example.com"), GURL("http://another-example.com"));
store->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
base::Unretained(this)));
@@ -650,11 +667,12 @@ TEST_F(RequestQueueStoreTest, AddAndGetRequestsMatch) {
}
TEST_F(RequestQueueStoreTest, UpdateRequest) {
+ const GURL kUrl1("http://example.com");
std::unique_ptr<RequestQueueStore> store(this->BuildStore());
this->InitializeStore(store.get());
base::Time creation_time = OfflineTimeNow();
- SavePageRequest original_request(kRequestId, Url1(), kClientId, creation_time,
+ SavePageRequest original_request(kRequestId, kUrl1, kClientId, creation_time,
kUserRequested);
store->AddRequest(original_request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
@@ -665,12 +683,12 @@ TEST_F(RequestQueueStoreTest, UpdateRequest) {
base::Time new_creation_time =
creation_time + base::TimeDelta::FromMinutes(1);
// Try updating an existing request.
- SavePageRequest updated_request(kRequestId, Url1(), kClientId,
+ SavePageRequest updated_request(kRequestId, kUrl1, kClientId,
new_creation_time, kUserRequested);
- updated_request.set_original_url(Url2());
+ updated_request.set_original_url(GURL("http://another-example.com"));
updated_request.set_request_origin(kRequestOrigin);
// Try to update a non-existing request.
- SavePageRequest updated_request2(kRequestId2, Url1(), kClientId,
+ SavePageRequest updated_request2(kRequestId2, kUrl1, kClientId,
new_creation_time, kUserRequested);
std::vector<SavePageRequest> requests_to_update{updated_request,
updated_request2};
@@ -710,13 +728,13 @@ TEST_F(RequestQueueStoreTest, RemoveRequests) {
this->InitializeStore(store.get());
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request1(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
store->AddRequest(request1, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
base::Unretained(this)));
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://another-example.com"),
+ kClientId2, creation_time, kUserRequested);
store->AddRequest(request2, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
base::Unretained(this)));
@@ -774,8 +792,8 @@ TEST_F(RequestQueueStoreTest, ResetStore) {
this->InitializeStore(store.get());
base::Time creation_time = OfflineTimeNow();
- SavePageRequest original_request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest original_request(kRequestId, GURL("http://example.com"),
+ kClientId, creation_time, kUserRequested);
store->AddRequest(original_request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
base::Unretained(this)));
@@ -804,8 +822,8 @@ TEST_F(RequestQueueStoreTest, SaveCloseReopenRead) {
this->InitializeStore(store.get());
base::Time creation_time = OfflineTimeNow();
- SavePageRequest original_request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest original_request(kRequestId, GURL("http://example.com"),
+ kClientId, creation_time, kUserRequested);
store->AddRequest(original_request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone,
base::Unretained(this)));
diff --git a/chromium/components/offline_pages/core/background/request_queue_unittest.cc b/chromium/components/offline_pages/core/background/request_queue_unittest.cc
index cf7359f0295..83914250ee5 100644
--- a/chromium/components/offline_pages/core/background/request_queue_unittest.cc
+++ b/chromium/components/offline_pages/core/background/request_queue_unittest.cc
@@ -28,6 +28,7 @@ using GetRequestsResult = GetRequestsResult;
using UpdateRequestResult = UpdateRequestResult;
namespace {
+
// Data for request 1.
const int64_t kRequestId = 42;
const ClientId kClientId("bookmark", "1234");
@@ -38,15 +39,6 @@ const bool kUserRequested = true;
const int64_t kRequestId3 = 99;
const int kOneWeekInSeconds = 7 * 24 * 60 * 60;
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("http://example.com");
-}
-GURL Url2() {
- return GURL("http://test.com");
-}
-
// Default request
SavePageRequest EmptyRequest() {
return SavePageRequest(0UL, GURL(""), ClientId("", ""), base::Time(), true);
@@ -215,8 +207,8 @@ TEST_F(RequestQueueTest, GetRequestsEmpty) {
TEST_F(RequestQueueTest, AddRequest) {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
queue()->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
@@ -234,8 +226,8 @@ TEST_F(RequestQueueTest, AddRequest) {
TEST_F(RequestQueueTest, RemoveRequest) {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
queue()->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
@@ -263,16 +255,16 @@ TEST_F(RequestQueueTest, RemoveRequest) {
TEST_F(RequestQueueTest, RemoveSeveralRequests) {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
queue()->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
PumpLoop();
ASSERT_EQ(kRequestId, last_added_request()->request_id());
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://test.com"), kClientId2,
+ creation_time, kUserRequested);
queue()->AddRequest(request2, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
@@ -312,8 +304,8 @@ TEST_F(RequestQueueTest, RemoveSeveralRequests) {
TEST_F(RequestQueueTest, PauseAndResume) {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
queue()->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
@@ -382,15 +374,15 @@ TEST_F(RequestQueueTest, PauseAndResume) {
// listing multiple items and removing the right item.
TEST_F(RequestQueueTest, MultipleRequestsAddGetRemove) {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request1(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
queue()->AddRequest(request1, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
PumpLoop();
ASSERT_EQ(request1.request_id(), last_added_request()->request_id());
- SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time,
- kUserRequested);
+ SavePageRequest request2(kRequestId2, GURL("http://test.com"), kClientId2,
+ creation_time, kUserRequested);
queue()->AddRequest(request2, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
@@ -425,8 +417,8 @@ TEST_F(RequestQueueTest, MultipleRequestsAddGetRemove) {
TEST_F(RequestQueueTest, MarkAttemptStarted) {
// First add a request. Retry count will be set to 0.
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
queue()->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
@@ -465,8 +457,8 @@ TEST_F(RequestQueueTest, MarkAttempStartedRequestNotPresent) {
// First add a request. Retry count will be set to 0.
base::Time creation_time = OfflineTimeNow();
// This request is never put into the queue.
- SavePageRequest request1(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
queue()->MarkAttemptStarted(
kRequestId, base::BindOnce(&RequestQueueTest::UpdateRequestsDone,
@@ -481,8 +473,8 @@ TEST_F(RequestQueueTest, MarkAttempStartedRequestNotPresent) {
TEST_F(RequestQueueTest, MarkAttemptAborted) {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
queue()->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
@@ -514,8 +506,8 @@ TEST_F(RequestQueueTest, MarkAttemptAbortedRequestNotPresent) {
// First add a request. Retry count will be set to 0.
base::Time creation_time = OfflineTimeNow();
// This request is never put into the queue.
- SavePageRequest request1(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request1(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
queue()->MarkAttemptAborted(
kRequestId, base::BindOnce(&RequestQueueTest::UpdateRequestsDone,
@@ -530,8 +522,8 @@ TEST_F(RequestQueueTest, MarkAttemptAbortedRequestNotPresent) {
TEST_F(RequestQueueTest, MarkAttemptCompleted) {
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId,
+ creation_time, kUserRequested);
queue()->AddRequest(request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
@@ -565,8 +557,8 @@ TEST_F(RequestQueueTest, CleanStaleRequests) {
base::Time creation_time =
OfflineTimeNow() - base::TimeDelta::FromSeconds(2 * kOneWeekInSeconds);
- SavePageRequest original_request(kRequestId, Url1(), kClientId, creation_time,
- kUserRequested);
+ SavePageRequest original_request(kRequestId, GURL("http://example.com"),
+ kClientId, creation_time, kUserRequested);
queue()->AddRequest(original_request, RequestQueue::AddOptions(),
base::BindOnce(&RequestQueueTest::AddRequestDone,
base::Unretained(this)));
diff --git a/chromium/components/offline_pages/core/background/save_page_request_unittest.cc b/chromium/components/offline_pages/core/background/save_page_request_unittest.cc
index 6fef0daa1ba..a7b6ab87b00 100644
--- a/chromium/components/offline_pages/core/background/save_page_request_unittest.cc
+++ b/chromium/components/offline_pages/core/background/save_page_request_unittest.cc
@@ -10,20 +10,12 @@
namespace offline_pages {
namespace {
+
const int64_t kRequestId = 42;
const ClientId kClientId("bookmark", "1234");
const bool kUserRequested = true;
const std::string kRequestOrigin = "abc.xyz";
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL Url1() {
- return GURL("http://example.com");
-}
-GURL Url2() {
- return GURL("http://example.com/test");
-}
-
} // namespace
class SavePageRequestTest : public testing::Test {
@@ -34,12 +26,14 @@ class SavePageRequestTest : public testing::Test {
SavePageRequestTest::~SavePageRequestTest() {}
TEST_F(SavePageRequestTest, CreatePendingReqeust) {
+ const GURL kUrl1("http://example.com");
+ const GURL kUrl2("http://example.com/test");
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
+ SavePageRequest request(kRequestId, kUrl1, kClientId, creation_time,
kUserRequested);
- request.set_original_url(Url2());
+ request.set_original_url(kUrl2);
EXPECT_EQ(kRequestId, request.request_id());
- EXPECT_EQ(Url1(), request.url());
+ EXPECT_EQ(kUrl1, request.url());
EXPECT_EQ(kClientId, request.client_id());
EXPECT_EQ(creation_time, request.creation_time());
EXPECT_EQ(base::Time(), request.last_attempt_time());
@@ -47,13 +41,14 @@ TEST_F(SavePageRequestTest, CreatePendingReqeust) {
EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, request.request_state());
EXPECT_EQ(0, request.started_attempt_count());
EXPECT_EQ(0, request.completed_attempt_count());
- EXPECT_EQ(Url2(), request.original_url());
+ EXPECT_EQ(kUrl2, request.original_url());
EXPECT_EQ("", request.request_origin());
}
TEST_F(SavePageRequestTest, StartAndCompleteRequest) {
+ const GURL kUrl1("http://example.com");
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
+ SavePageRequest request(kRequestId, kUrl1, kClientId, creation_time,
kUserRequested);
request.set_request_origin(kRequestOrigin);
@@ -62,7 +57,7 @@ TEST_F(SavePageRequestTest, StartAndCompleteRequest) {
// Most things don't change about the request.
EXPECT_EQ(kRequestId, request.request_id());
- EXPECT_EQ(Url1(), request.url());
+ EXPECT_EQ(kUrl1, request.url());
EXPECT_EQ(kClientId, request.client_id());
EXPECT_EQ(creation_time, request.creation_time());
EXPECT_EQ(kRequestOrigin, request.request_origin());
@@ -76,7 +71,7 @@ TEST_F(SavePageRequestTest, StartAndCompleteRequest) {
// Again, most things don't change about the request.
EXPECT_EQ(kRequestId, request.request_id());
- EXPECT_EQ(Url1(), request.url());
+ EXPECT_EQ(kUrl1, request.url());
EXPECT_EQ(kClientId, request.client_id());
EXPECT_EQ(creation_time, request.creation_time());
@@ -86,8 +81,9 @@ TEST_F(SavePageRequestTest, StartAndCompleteRequest) {
}
TEST_F(SavePageRequestTest, StartAndAbortRequest) {
+ const GURL kUrl1("http://example.com");
base::Time creation_time = OfflineTimeNow();
- SavePageRequest request(kRequestId, Url1(), kClientId, creation_time,
+ SavePageRequest request(kRequestId, kUrl1, kClientId, creation_time,
kUserRequested);
base::Time start_time = creation_time + base::TimeDelta::FromHours(3);
@@ -95,7 +91,7 @@ TEST_F(SavePageRequestTest, StartAndAbortRequest) {
// Most things don't change about the request.
EXPECT_EQ(kRequestId, request.request_id());
- EXPECT_EQ(Url1(), request.url());
+ EXPECT_EQ(kUrl1, request.url());
EXPECT_EQ(kClientId, request.client_id());
EXPECT_EQ(creation_time, request.creation_time());
EXPECT_EQ("", request.request_origin());
@@ -109,7 +105,7 @@ TEST_F(SavePageRequestTest, StartAndAbortRequest) {
// Again, most things don't change about the request.
EXPECT_EQ(kRequestId, request.request_id());
- EXPECT_EQ(Url1(), request.url());
+ EXPECT_EQ(kUrl1, request.url());
EXPECT_EQ(kClientId, request.client_id());
EXPECT_EQ(creation_time, request.creation_time());
EXPECT_EQ("", request.request_origin());
diff --git a/chromium/components/offline_pages/core/background/update_request_task.h b/chromium/components/offline_pages/core/background/update_request_task.h
index d1e44f14dbd..3ad4eb38309 100644
--- a/chromium/components/offline_pages/core/background/update_request_task.h
+++ b/chromium/components/offline_pages/core/background/update_request_task.h
@@ -7,8 +7,6 @@
#include <stdint.h>
-#include <memory>
-
#include "base/memory/weak_ptr.h"
#include "components/offline_pages/core/background/request_queue_store.h"
#include "components/offline_pages/task/task.h"
diff --git a/chromium/components/offline_pages/core/downloads/download_ui_adapter.cc b/chromium/components/offline_pages/core/downloads/download_ui_adapter.cc
index 7b6da7a8eb2..0a7e2def886 100644
--- a/chromium/components/offline_pages/core/downloads/download_ui_adapter.cc
+++ b/chromium/components/offline_pages/core/downloads/download_ui_adapter.cc
@@ -121,7 +121,7 @@ void DownloadUIAdapter::OfflinePageAdded(OfflinePageModel* model,
// since they're added to Offline Page database directly, so OnItemsAdded is
// used.
if (!is_suggested)
- NotifyItemUpdated(offline_item, base::nullopt);
+ NotifyItemUpdated(offline_item, absl::nullopt);
else
NotifyItemsAdded({offline_item});
}
@@ -180,7 +180,7 @@ void DownloadUIAdapter::OnCompleted(
// Actual cause could be server or network related, but we need to pick
// a fail_state.
item.fail_state = offline_items_collection::FailState::SERVER_FAILED;
- NotifyItemUpdated(item, base::nullopt);
+ NotifyItemUpdated(item, absl::nullopt);
}
}
@@ -190,7 +190,7 @@ void DownloadUIAdapter::OnChanged(const SavePageRequest& request) {
return;
OfflineItem offline_item(OfflineItemConversions::CreateOfflineItem(request));
- NotifyItemUpdated(offline_item, base::nullopt);
+ NotifyItemUpdated(offline_item, absl::nullopt);
}
// RequestCoordinator::Observer
@@ -201,7 +201,7 @@ void DownloadUIAdapter::OnNetworkProgress(const SavePageRequest& request,
OfflineItem offline_item(OfflineItemConversions::CreateOfflineItem(request));
offline_item.received_bytes = received_bytes;
- NotifyItemUpdated(offline_item, base::nullopt);
+ NotifyItemUpdated(offline_item, absl::nullopt);
}
void DownloadUIAdapter::GetAllItems(
@@ -238,7 +238,7 @@ void DownloadUIAdapter::RenameItem(const ContentId& id,
void DownloadUIAdapter::ChangeSchedule(
const ContentId& id,
- base::Optional<OfflineItemSchedule> schedule) {
+ absl::optional<OfflineItemSchedule> schedule) {
NOTREACHED();
}
@@ -382,7 +382,7 @@ void DownloadUIAdapter::OnAllRequestsGetForGetItem(
const ContentId& id,
OfflineContentProvider::SingleItemCallback callback,
std::vector<std::unique_ptr<SavePageRequest>> requests) {
- base::Optional<OfflineItem> offline_item;
+ absl::optional<OfflineItem> offline_item;
for (const auto& request : requests) {
if (request->client_id().id == id.id)
offline_item = OfflineItemConversions::CreateOfflineItem(*request);
diff --git a/chromium/components/offline_pages/core/downloads/download_ui_adapter.h b/chromium/components/offline_pages/core/downloads/download_ui_adapter.h
index 411b130030c..06064fbecad 100644
--- a/chromium/components/offline_pages/core/downloads/download_ui_adapter.h
+++ b/chromium/components/offline_pages/core/downloads/download_ui_adapter.h
@@ -109,7 +109,7 @@ class DownloadUIAdapter : public OfflineContentProvider,
const std::string& name,
RenameCallback callback) override;
void ChangeSchedule(const ContentId& id,
- base::Optional<OfflineItemSchedule> schedule) override;
+ absl::optional<OfflineItemSchedule> schedule) override;
// OfflinePageModel::Observer
void OfflinePageModelLoaded(OfflinePageModel* model) override;
diff --git a/chromium/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc b/chromium/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc
index b8b5cae68d5..29ed2f23409 100644
--- a/chromium/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc
+++ b/chromium/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc
@@ -68,8 +68,8 @@ static const int kFileSize = 1000;
static const base::Time kTestCreationTime = base::Time::Now();
static const std::u16string kTestTitle = u"test title";
-void GetItemAndVerify(const base::Optional<OfflineItem>& expected,
- const base::Optional<OfflineItem>& actual) {
+void GetItemAndVerify(const absl::optional<OfflineItem>& expected,
+ const absl::optional<OfflineItem>& actual) {
EXPECT_EQ(expected.has_value(), actual.has_value());
if (!expected.has_value() || !actual.has_value())
return;
@@ -238,7 +238,7 @@ class DownloadUIAdapterTest : public testing::Test,
// DownloadUIAdapter::Observer
void OnItemsAdded(const std::vector<OfflineItem>& items) override;
void OnItemUpdated(const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) override;
+ const absl::optional<UpdateDelta>& update_delta) override;
void OnItemRemoved(const ContentId& id) override;
void OnContentProviderGoingDown() override;
@@ -306,7 +306,7 @@ void DownloadUIAdapterTest::OnItemsAdded(
void DownloadUIAdapterTest::OnItemUpdated(
const OfflineItem& item,
- const base::Optional<UpdateDelta>& update_delta) {
+ const absl::optional<UpdateDelta>& update_delta) {
updated_guids.push_back(item.id.id);
download_progress_bytes += item.received_bytes;
}
@@ -352,9 +352,9 @@ TEST_F(DownloadUIAdapterTest, InitialItemConversion) {
bool called = false;
auto callback =
- base::BindLambdaForTesting([&](const base::Optional<OfflineItem>& item) {
+ base::BindLambdaForTesting([&](const absl::optional<OfflineItem>& item) {
EXPECT_EQ(kTestGuid1, item.value().id.id);
- EXPECT_EQ(kTestUrl, item.value().page_url.spec());
+ EXPECT_EQ(kTestUrl, item.value().url.spec());
EXPECT_EQ(OfflineItemState::COMPLETE, item.value().state);
EXPECT_EQ(kFileSize, item.value().received_bytes);
EXPECT_EQ(kTestFilePath, item.value().file_path);
@@ -477,7 +477,7 @@ TEST_F(DownloadUIAdapterTest, RemoveRequest) {
EXPECT_EQ(1UL, deleted_guids.size());
EXPECT_EQ(kTestClientId1.id, deleted_guids[0]);
adapter->GetItemById(kTestContentId1,
- base::BindOnce(&GetItemAndVerify, base::nullopt));
+ base::BindOnce(&GetItemAndVerify, absl::nullopt));
PumpLoop();
}
diff --git a/chromium/components/offline_pages/core/downloads/offline_item_conversions.cc b/chromium/components/offline_pages/core/downloads/offline_item_conversions.cc
index bdb68242369..fdb032e1516 100644
--- a/chromium/components/offline_pages/core/downloads/offline_item_conversions.cc
+++ b/chromium/components/offline_pages/core/downloads/offline_item_conversions.cc
@@ -57,7 +57,7 @@ OfflineItem OfflineItemConversions::CreateOfflineItem(
item.last_accessed_time = page.last_access_time;
item.file_path = page.file_path;
item.mime_type = GetMimeType();
- item.page_url = page.url;
+ item.url = page.url;
item.original_url = page.original_url_if_different;
item.progress.value = 100;
item.progress.max = 100;
@@ -82,7 +82,7 @@ OfflineItem OfflineItemConversions::CreateOfflineItem(
item.total_size_bytes = -1L;
item.received_bytes = 0;
item.mime_type = GetMimeType();
- item.page_url = request.url();
+ item.url = request.url();
item.original_url = request.original_url();
switch (request.request_state()) {
case SavePageRequest::RequestState::AVAILABLE:
diff --git a/chromium/components/offline_pages/core/downloads/offline_item_conversions_unittest.cc b/chromium/components/offline_pages/core/downloads/offline_item_conversions_unittest.cc
index e2b71fe5fcf..6c3c8a351d8 100644
--- a/chromium/components/offline_pages/core/downloads/offline_item_conversions_unittest.cc
+++ b/chromium/components/offline_pages/core/downloads/offline_item_conversions_unittest.cc
@@ -19,18 +19,6 @@ using OfflineItemProgressUnit =
namespace offline_pages {
-namespace {
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL TestUrl() {
- return GURL("http://www.example.com");
-}
-GURL TestOriginalUrl() {
- return GURL("http://www.exampleoriginalurl.com");
-}
-
-} // namespace
-
TEST(OfflineItemConversionsTest, OfflinePageItemConversion) {
std::string name_space = "test_namespace";
std::string guid = "test_guid";
@@ -42,9 +30,11 @@ TEST(OfflineItemConversionsTest, OfflinePageItemConversion) {
base::Time last_access_time = base::Time::Now();
std::string title = "test title";
- OfflinePageItem offline_page_item(TestUrl(), offline_id, client_id, file_path,
+ const GURL kTestUrl("http://www.example.com");
+ const GURL kTestOriginalUrl("http://www.exampleoriginalurl.com");
+ OfflinePageItem offline_page_item(kTestUrl, offline_id, client_id, file_path,
file_size, creation_time);
- offline_page_item.original_url_if_different = TestOriginalUrl();
+ offline_page_item.original_url_if_different = kTestOriginalUrl;
offline_page_item.title = base::UTF8ToUTF16(title);
offline_page_item.last_access_time = last_access_time;
offline_page_item.file_missing_time = base::Time::Now();
@@ -53,8 +43,8 @@ TEST(OfflineItemConversionsTest, OfflinePageItemConversion) {
OfflineItemConversions::CreateOfflineItem(offline_page_item, true);
EXPECT_EQ(ContentId(kOfflinePageNamespace, guid), offline_item.id);
- EXPECT_EQ(TestUrl(), offline_item.page_url);
- EXPECT_EQ(TestOriginalUrl(), offline_item.original_url);
+ EXPECT_EQ(kTestUrl, offline_item.url);
+ EXPECT_EQ(kTestOriginalUrl, offline_item.original_url);
EXPECT_EQ(title, offline_item.title);
EXPECT_EQ(file_path, offline_item.file_path);
EXPECT_EQ(creation_time, offline_item.creation_time);
@@ -93,9 +83,11 @@ TEST(OfflineItemConversionsTest, SavePageRequestConversion) {
int64_t request_id = 5;
base::Time creation_time = base::Time::Now();
- SavePageRequest save_page_request(request_id, TestUrl(), client_id,
+ const GURL kTestUrl("http://www.example.com");
+ const GURL kTestOriginalUrl("http://www.exampleoriginalurl.com");
+ SavePageRequest save_page_request(request_id, kTestUrl, client_id,
creation_time, false);
- save_page_request.set_original_url(TestOriginalUrl());
+ save_page_request.set_original_url(kTestOriginalUrl);
save_page_request.set_request_state(SavePageRequest::RequestState::OFFLINING);
save_page_request.set_fail_state(FailState::NETWORK_FAILED);
save_page_request.set_pending_state(PendingState::PENDING_ANOTHER_DOWNLOAD);
@@ -104,9 +96,9 @@ TEST(OfflineItemConversionsTest, SavePageRequestConversion) {
OfflineItemConversions::CreateOfflineItem(save_page_request);
EXPECT_EQ(ContentId(kOfflinePageNamespace, guid), offline_item.id);
- EXPECT_EQ(TestUrl(), offline_item.page_url);
- EXPECT_EQ(TestOriginalUrl(), offline_item.original_url);
- EXPECT_EQ(TestUrl().host(), offline_item.title);
+ EXPECT_EQ(kTestUrl, offline_item.url);
+ EXPECT_EQ(kTestOriginalUrl, offline_item.original_url);
+ EXPECT_EQ(kTestUrl.host(), offline_item.title);
EXPECT_EQ(base::FilePath(), offline_item.file_path);
EXPECT_EQ(creation_time, offline_item.creation_time);
EXPECT_EQ(base::Time(), offline_item.completion_time);
diff --git a/chromium/components/offline_pages/core/model/add_page_task_unittest.cc b/chromium/components/offline_pages/core/model/add_page_task_unittest.cc
index 5d23e383520..ffcc91171c4 100644
--- a/chromium/components/offline_pages/core/model/add_page_task_unittest.cc
+++ b/chromium/components/offline_pages/core/model/add_page_task_unittest.cc
@@ -12,7 +12,6 @@
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/offline_pages/core/model/model_task_test_base.h"
@@ -20,6 +19,7 @@
#include "components/offline_pages/core/offline_page_types.h"
#include "components/offline_pages/core/offline_store_types.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace offline_pages {
@@ -38,15 +38,6 @@ const std::string kTestDigest("TesTIngDigEst==");
const std::string kTestAttribution = "attribution";
const std::string kTestSnippet = "snippet";
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL TestUrl1() {
- return GURL("http://example.com");
-}
-GURL TestUrl2() {
- return GURL("http://other.page.com");
-}
-
} // namespace
class AddPageTaskTest : public ModelTaskTestBase {
@@ -58,12 +49,12 @@ class AddPageTaskTest : public ModelTaskTestBase {
void AddPage(const OfflinePageItem& page);
bool CheckPageStored(const OfflinePageItem& page);
- const base::Optional<AddPageResult>& last_add_page_result() {
+ const absl::optional<AddPageResult>& last_add_page_result() {
return last_add_page_result_;
}
private:
- base::Optional<AddPageResult> last_add_page_result_;
+ absl::optional<AddPageResult> last_add_page_result_;
};
void AddPageTaskTest::ResetResults() {
@@ -100,11 +91,12 @@ TEST_F(AddPageTaskTest, AddPage) {
}
TEST_F(AddPageTaskTest, AddPageWithAllFieldsSet) {
- OfflinePageItem page(TestUrl1(), kTestOfflineId1, kTestClientId1,
- kTestFilePath, kTestFileSize, base::Time::Now());
+ OfflinePageItem page(GURL("http://example.com"), kTestOfflineId1,
+ kTestClientId1, kTestFilePath, kTestFileSize,
+ base::Time::Now());
page.request_origin = kTestOrigin;
page.title = kTestTitle;
- page.original_url_if_different = TestUrl2();
+ page.original_url_if_different = GURL("http://other.page.com");
page.system_download_id = kTestDownloadId;
page.file_missing_time = base::Time::Now();
page.digest = kTestDigest;
diff --git a/chromium/components/offline_pages/core/model/cleanup_visuals_task.h b/chromium/components/offline_pages/core/model/cleanup_visuals_task.h
index 83ddd26d814..3c6da77d787 100644
--- a/chromium/components/offline_pages/core/model/cleanup_visuals_task.h
+++ b/chromium/components/offline_pages/core/model/cleanup_visuals_task.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_MODEL_CLEANUP_VISUALS_TASK_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_CLEANUP_VISUALS_TASK_H_
-#include <vector>
-
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/offline_pages/core/offline_page_types.h"
diff --git a/chromium/components/offline_pages/core/model/delete_page_task_unittest.cc b/chromium/components/offline_pages/core/model/delete_page_task_unittest.cc
index 37c4a2739d8..7c49bad25e7 100644
--- a/chromium/components/offline_pages/core/model/delete_page_task_unittest.cc
+++ b/chromium/components/offline_pages/core/model/delete_page_task_unittest.cc
@@ -12,7 +12,6 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
@@ -23,6 +22,7 @@
#include "components/offline_pages/core/offline_page_types.h"
#include "components/offline_pages/core/offline_store_types.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace offline_pages {
@@ -32,19 +32,6 @@ namespace {
const char kTestNamespace[] = "default";
const ClientId kTestClientIdNoMatch(kTestNamespace, "20170905");
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL TestUrl1() {
- return GURL("http://example.com");
-}
-GURL TestUrl2() {
- return GURL("http://other.page.com");
-}
-
-GURL OriginalUrl() {
- return GURL("http://original.com");
-}
-
} // namespace
class DeletePageTaskTest : public ModelTaskTestBase {
@@ -62,7 +49,7 @@ class DeletePageTaskTest : public ModelTaskTestBase {
DeletePageTask::DeletePageTaskCallback delete_page_callback();
base::HistogramTester* histogram_tester() { return histogram_tester_.get(); }
- const base::Optional<DeletePageResult>& last_delete_page_result() {
+ const absl::optional<DeletePageResult>& last_delete_page_result() {
return last_delete_page_result_;
}
const std::vector<OfflinePageItem>& last_deleted_page_items() {
@@ -72,7 +59,7 @@ class DeletePageTaskTest : public ModelTaskTestBase {
private:
std::unique_ptr<base::HistogramTester> histogram_tester_;
- base::Optional<DeletePageResult> last_delete_page_result_;
+ absl::optional<DeletePageResult> last_delete_page_result_;
std::vector<OfflinePageItem> last_deleted_page_items_;
};
@@ -105,10 +92,11 @@ bool DeletePageTaskTest::CheckPageDeleted(const OfflinePageItem& page) {
// Delete a page and verify all the information in deleted_pages is accurate.
TEST_F(DeletePageTaskTest, OfflinePageItemIsPopulated) {
+ const GURL kOriginalUrl("http://original.com");
generator()->SetNamespace(kTestNamespace);
OfflinePageItem page1 = generator()->CreateItemWithTempFile();
- page1.url = TestUrl1();
- page1.original_url_if_different = OriginalUrl();
+ page1.url = GURL("http://example.com");
+ page1.original_url_if_different = kOriginalUrl;
page1.request_origin = "test-origin";
page1.system_download_id = 1234;
store_test_util()->InsertItem(page1);
@@ -130,18 +118,19 @@ TEST_F(DeletePageTaskTest, OfflinePageItemIsPopulated) {
EXPECT_EQ(page1.request_origin, item.request_origin);
EXPECT_EQ(page1.system_download_id, item.system_download_id);
EXPECT_EQ(page1.offline_id, item.offline_id);
- EXPECT_EQ(OriginalUrl(), item.original_url_if_different);
- EXPECT_EQ(OriginalUrl(), item.GetOriginalUrl());
+ EXPECT_EQ(kOriginalUrl, item.original_url_if_different);
+ EXPECT_EQ(kOriginalUrl, item.GetOriginalUrl());
}
TEST_F(DeletePageTaskTest, DeletePageByUrlPredicate) {
// Add 3 pages and try to delete 2 of them using url predicate.
+ const std::string kExample = "example.com";
generator()->SetNamespace(kTestNamespace);
- generator()->SetUrl(TestUrl1());
+ generator()->SetUrl(GURL("http://" + kExample));
OfflinePageItem page1 = generator()->CreateItemWithTempFile();
generator()->SetAccessCount(200);
OfflinePageItem page2 = generator()->CreateItemWithTempFile();
- generator()->SetUrl(TestUrl2());
+ generator()->SetUrl(GURL("http://other.page.com"));
OfflinePageItem page3 = generator()->CreateItemWithTempFile();
store_test_util()->InsertItem(page1);
@@ -153,10 +142,12 @@ TEST_F(DeletePageTaskTest, DeletePageByUrlPredicate) {
EXPECT_TRUE(base::PathExists(page2.file_path));
EXPECT_TRUE(base::PathExists(page3.file_path));
- // Delete all pages with url contains example.com, which are with TestUrl1().
- UrlPredicate predicate = base::BindRepeating([](const GURL& url) -> bool {
- return url.spec().find("example.com") != std::string::npos;
- });
+ // Delete all pages with url contains kExample.
+ UrlPredicate predicate = base::BindRepeating(
+ [](const std::string& to_find, const GURL& url) -> bool {
+ return url.spec().find(to_find) != std::string::npos;
+ },
+ kExample);
auto task = DeletePageTask::CreateTaskMatchingUrlPredicateForCachedPages(
store(), delete_page_callback(), predicate);
@@ -188,10 +179,10 @@ TEST_F(DeletePageTaskTest, DeletePageByUrlPredicate) {
TEST_F(DeletePageTaskTest, DeletePageByUrlPredicateNotFound) {
// Add 3 pages and try to delete 2 of them using url predicate.
generator()->SetNamespace(kTestNamespace);
- generator()->SetUrl(TestUrl1());
+ generator()->SetUrl(GURL("http://example.com"));
OfflinePageItem page1 = generator()->CreateItemWithTempFile();
OfflinePageItem page2 = generator()->CreateItemWithTempFile();
- generator()->SetUrl(TestUrl2());
+ generator()->SetUrl(GURL("http://other.page.com"));
OfflinePageItem page3 = generator()->CreateItemWithTempFile();
store_test_util()->InsertItem(page1);
@@ -229,7 +220,7 @@ TEST_F(DeletePageTaskTest, DeletePageByUrlPredicateNotFound) {
TEST_F(DeletePageTaskTest, DeletePageForPageLimit) {
// Add 3 pages, the kTestNamespace has a limit of 1 for page per url.
generator()->SetNamespace(kTestNamespace);
- generator()->SetUrl(TestUrl1());
+ generator()->SetUrl(GURL("http://example.com"));
// Guarantees that page1 will be deleted by making it older.
base::Time now = OfflineTimeNow();
generator()->SetLastAccessTime(now - base::TimeDelta::FromMinutes(5));
@@ -237,7 +228,7 @@ TEST_F(DeletePageTaskTest, DeletePageForPageLimit) {
generator()->SetLastAccessTime(now);
OfflinePageItem page2 = generator()->CreateItemWithTempFile();
OfflinePageItem page = generator()->CreateItem();
- generator()->SetUrl(TestUrl2());
+ generator()->SetUrl(GURL("http://other.page.com"));
OfflinePageItem page3 = generator()->CreateItemWithTempFile();
store_test_util()->InsertItem(page1);
@@ -271,11 +262,11 @@ TEST_F(DeletePageTaskTest, DeletePageForPageLimit) {
TEST_F(DeletePageTaskTest, DeletePageForPageLimit_UnlimitedNamespace) {
// Add 3 pages, the kTestNamespace has a limit of 1 for page per url.
generator()->SetNamespace(kDownloadNamespace);
- generator()->SetUrl(TestUrl1());
+ generator()->SetUrl(GURL("http://example.com"));
OfflinePageItem page1 = generator()->CreateItemWithTempFile();
OfflinePageItem page2 = generator()->CreateItemWithTempFile();
OfflinePageItem page = generator()->CreateItem();
- generator()->SetUrl(TestUrl2());
+ generator()->SetUrl(GURL("http://other.page.com"));
OfflinePageItem page3 = generator()->CreateItemWithTempFile();
store_test_util()->InsertItem(page1);
diff --git a/chromium/components/offline_pages/core/model/get_pages_task.cc b/chromium/components/offline_pages/core/model/get_pages_task.cc
index 7cdfee35d39..340a427a067 100644
--- a/chromium/components/offline_pages/core/model/get_pages_task.cc
+++ b/chromium/components/offline_pages/core/model/get_pages_task.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
#include "components/offline_pages/core/offline_page_client_policy.h"
#include "components/offline_pages/core/offline_page_item_utils.h"
#include "components/offline_pages/core/offline_store_utils.h"
diff --git a/chromium/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc b/chromium/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc
index 2b4eac59bbb..9d83c1400ee 100644
--- a/chromium/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc
+++ b/chromium/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc
@@ -16,18 +16,13 @@
namespace offline_pages {
namespace {
+
const int64_t kTestOfflineId = 1234LL;
const char kTestClientNamespace[] = "default";
const ClientId kTestClientId(kTestClientNamespace, "1234");
const base::FilePath kTestFilePath(FILE_PATH_LITERAL("/test/path/file"));
const int64_t kTestFileSize = 876543LL;
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL TestUrl() {
- return GURL("http://example.com");
-}
-
} // namespace
class MarkPageAccessedTaskTest : public ModelTaskTestBase {
@@ -39,7 +34,8 @@ class MarkPageAccessedTaskTest : public ModelTaskTestBase {
};
TEST_F(MarkPageAccessedTaskTest, MarkPageAccessed) {
- OfflinePageItem page(TestUrl(), kTestOfflineId, kTestClientId, kTestFilePath,
+ const GURL kTestUrl("http://example.com");
+ OfflinePageItem page(kTestUrl, kTestOfflineId, kTestClientId, kTestFilePath,
kTestFileSize);
store_test_util()->InsertItem(page);
@@ -49,7 +45,7 @@ TEST_F(MarkPageAccessedTaskTest, MarkPageAccessed) {
RunTask(std::move(task));
auto offline_page = store_test_util()->GetPageByOfflineId(kTestOfflineId);
- EXPECT_EQ(TestUrl(), offline_page->url);
+ EXPECT_EQ(kTestUrl, offline_page->url);
EXPECT_EQ(kTestClientId, offline_page->client_id);
EXPECT_EQ(kTestFileSize, offline_page->file_size);
EXPECT_EQ(1, offline_page->access_count);
@@ -65,7 +61,8 @@ TEST_F(MarkPageAccessedTaskTest, MarkPageAccessed) {
}
TEST_F(MarkPageAccessedTaskTest, MarkPageAccessedTwice) {
- OfflinePageItem page(TestUrl(), kTestOfflineId, kTestClientId, kTestFilePath,
+ const GURL kTestUrl("http://example.com");
+ OfflinePageItem page(kTestUrl, kTestOfflineId, kTestClientId, kTestFilePath,
kTestFileSize);
store_test_util()->InsertItem(page);
@@ -76,7 +73,7 @@ TEST_F(MarkPageAccessedTaskTest, MarkPageAccessedTwice) {
auto offline_page = store_test_util()->GetPageByOfflineId(kTestOfflineId);
EXPECT_EQ(kTestOfflineId, offline_page->offline_id);
- EXPECT_EQ(TestUrl(), offline_page->url);
+ EXPECT_EQ(kTestUrl, offline_page->url);
EXPECT_EQ(kTestClientId, offline_page->client_id);
EXPECT_EQ(kTestFileSize, offline_page->file_size);
EXPECT_EQ(1, offline_page->access_count);
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 3fa93f69b5c..0389907947c 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
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
@@ -55,6 +56,7 @@ using ArchiverResult = OfflinePageArchiver::ArchiverResult;
using ClearStorageResult = ClearStorageTask::ClearStorageResult;
namespace {
+
const ClientId kTestClientId1(kDefaultNamespace, "1234");
const ClientId kTestClientId2(kDefaultNamespace, "5678");
const ClientId kTestUserRequestedClientId(kDownloadNamespace, "714");
@@ -67,27 +69,6 @@ const char kEmptyRequestOrigin[] = "";
const char kTestDigest[] = "test digest";
const int64_t kDownloadId = 42LL;
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL TestUrl() {
- return GURL("http://example.com");
-}
-GURL TestUrl2() {
- return GURL("http://other.page.com");
-}
-GURL TestUrlWithFragment() {
- return GURL("http://example.com#frag");
-}
-GURL TestUrl2WithFragment() {
- return GURL("http://other.page.com#frag");
-}
-GURL OtherUrl() {
- return GURL("http://foo");
-}
-GURL FileUrl() {
- return GURL("file:///foo");
-}
-
} // namespace
class OfflinePageModelTaskifiedTest : public testing::Test,
@@ -368,11 +349,12 @@ void OfflinePageModelTaskifiedTest::CheckTaskQueueIdle() {
// Tests saving successfully a non-user-requested offline page.
TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessful) {
- auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
+ const GURL kTestUrl2("http://other.page.com");
int64_t offline_id = SavePageWithExpectedResult(
- TestUrl(), kTestClientId1, TestUrl2(), kEmptyRequestOrigin,
+ kTestUrl, kTestClientId1, kTestUrl2, kEmptyRequestOrigin,
std::move(archiver), SavePageResult::SUCCESS);
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path()));
@@ -380,7 +362,7 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessful) {
auto saved_page_ptr = store_test_util()->GetPageByOfflineId(offline_id);
ASSERT_TRUE(saved_page_ptr);
- EXPECT_EQ(TestUrl(), saved_page_ptr->url);
+ EXPECT_EQ(kTestUrl, saved_page_ptr->url);
EXPECT_EQ(kTestClientId1.id, saved_page_ptr->client_id.id);
EXPECT_EQ(kTestClientId1.name_space, saved_page_ptr->client_id.name_space);
EXPECT_EQ(last_path_created_by_archiver(), saved_page_ptr->file_path);
@@ -388,7 +370,7 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessful) {
EXPECT_EQ(0, saved_page_ptr->access_count);
EXPECT_EQ(0, saved_page_ptr->flags);
EXPECT_EQ(kTestTitle, saved_page_ptr->title);
- EXPECT_EQ(TestUrl2(), saved_page_ptr->original_url_if_different);
+ EXPECT_EQ(kTestUrl2, saved_page_ptr->original_url_if_different);
EXPECT_EQ("", saved_page_ptr->request_origin);
EXPECT_EQ(kTestDigest, saved_page_ptr->digest);
@@ -430,12 +412,12 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessful) {
}
TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithSameOriginalUrl) {
- auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
// Pass the original URL same as the final URL.
int64_t offline_id = SavePageWithExpectedResult(
- TestUrl(), kTestClientId1, TestUrl(), kEmptyRequestOrigin,
+ kTestUrl, kTestClientId1, kTestUrl, kEmptyRequestOrigin,
std::move(archiver), SavePageResult::SUCCESS);
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path()));
@@ -443,7 +425,7 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithSameOriginalUrl) {
auto saved_page_ptr = store_test_util()->GetPageByOfflineId(offline_id);
ASSERT_TRUE(saved_page_ptr);
- EXPECT_EQ(TestUrl(), saved_page_ptr->url);
+ EXPECT_EQ(kTestUrl, saved_page_ptr->url);
// The original URL should be empty.
EXPECT_TRUE(saved_page_ptr->original_url_if_different.is_empty());
@@ -462,11 +444,12 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithSameOriginalUrl) {
}
TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithRequestOrigin) {
- auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
+ const GURL kTestUrl2("http://other.page.com");
int64_t offline_id = SavePageWithExpectedResult(
- TestUrl(), kTestClientId1, TestUrl2(), kTestRequestOrigin,
+ kTestUrl, kTestClientId1, kTestUrl2, kTestRequestOrigin,
std::move(archiver), SavePageResult::SUCCESS);
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path()));
@@ -474,7 +457,7 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithRequestOrigin) {
auto saved_page_ptr = store_test_util()->GetPageByOfflineId(offline_id);
ASSERT_TRUE(saved_page_ptr);
- EXPECT_EQ(TestUrl(), saved_page_ptr->url);
+ EXPECT_EQ(kTestUrl, saved_page_ptr->url);
EXPECT_EQ(kTestClientId1.id, saved_page_ptr->client_id.id);
EXPECT_EQ(kTestClientId1.name_space, saved_page_ptr->client_id.name_space);
EXPECT_EQ(last_path_created_by_archiver(), saved_page_ptr->file_path);
@@ -482,7 +465,7 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithRequestOrigin) {
EXPECT_EQ(0, saved_page_ptr->access_count);
EXPECT_EQ(0, saved_page_ptr->flags);
EXPECT_EQ(kTestTitle, saved_page_ptr->title);
- EXPECT_EQ(TestUrl2(), saved_page_ptr->original_url_if_different);
+ EXPECT_EQ(kTestUrl2, saved_page_ptr->original_url_if_different);
EXPECT_EQ(kTestRequestOrigin, saved_page_ptr->request_origin);
histogram_tester()->ExpectUniqueSample(
@@ -500,10 +483,11 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithRequestOrigin) {
}
TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverCancelled) {
- auto archiver = BuildArchiver(TestUrl(), ArchiverResult::ERROR_CANCELED);
- SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(),
- kEmptyRequestOrigin, std::move(archiver),
- SavePageResult::CANCELLED);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::ERROR_CANCELED);
+ SavePageWithExpectedResult(kTestUrl, kTestClientId1,
+ GURL("http://other.page.com"), kEmptyRequestOrigin,
+ std::move(archiver), SavePageResult::CANCELLED);
histogram_tester()->ExpectUniqueSample(
model_utils::AddHistogramSuffix(kTestClientId1.name_space,
@@ -520,10 +504,11 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverCancelled) {
}
TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverDeviceFull) {
- auto archiver = BuildArchiver(TestUrl(), ArchiverResult::ERROR_DEVICE_FULL);
- SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(),
- kEmptyRequestOrigin, std::move(archiver),
- SavePageResult::DEVICE_FULL);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::ERROR_DEVICE_FULL);
+ SavePageWithExpectedResult(kTestUrl, kTestClientId1,
+ GURL("http://other.page.com"), kEmptyRequestOrigin,
+ std::move(archiver), SavePageResult::DEVICE_FULL);
histogram_tester()->ExpectUniqueSample(
model_utils::AddHistogramSuffix(kTestClientId1.name_space,
@@ -541,10 +526,12 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverDeviceFull) {
TEST_F(OfflinePageModelTaskifiedTest,
SavePageOfflineArchiverContentUnavailable) {
+ const GURL kTestUrl("http://example.com");
auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::ERROR_CONTENT_UNAVAILABLE);
- SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(),
- kEmptyRequestOrigin, std::move(archiver),
+ BuildArchiver(kTestUrl, ArchiverResult::ERROR_CONTENT_UNAVAILABLE);
+ SavePageWithExpectedResult(kTestUrl, kTestClientId1,
+ GURL("http://other.page.com"), kEmptyRequestOrigin,
+ std::move(archiver),
SavePageResult::CONTENT_UNAVAILABLE);
histogram_tester()->ExpectUniqueSample(
@@ -562,10 +549,12 @@ TEST_F(OfflinePageModelTaskifiedTest,
}
TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineCreationFailed) {
+ const GURL kTestUrl("http://example.com");
auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED);
- SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(),
- kEmptyRequestOrigin, std::move(archiver),
+ BuildArchiver(kTestUrl, ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED);
+ SavePageWithExpectedResult(kTestUrl, kTestClientId1,
+ GURL("http://other.page.com"), kEmptyRequestOrigin,
+ std::move(archiver),
SavePageResult::ARCHIVE_CREATION_FAILED);
histogram_tester()->ExpectUniqueSample(
@@ -585,9 +574,9 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineCreationFailed) {
TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverReturnedWrongUrl) {
auto archiver = BuildArchiver(GURL("http://other.random.url.com"),
ArchiverResult::SUCCESSFULLY_CREATED);
- SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(),
- kEmptyRequestOrigin, std::move(archiver),
- SavePageResult::INCORRECT_URL);
+ SavePageWithExpectedResult(
+ GURL("http://example.com"), kTestClientId1, GURL("http://other.page.com"),
+ kEmptyRequestOrigin, std::move(archiver), SavePageResult::INCORRECT_URL);
histogram_tester()->ExpectUniqueSample(
model_utils::AddHistogramSuffix(kTestClientId1.name_space,
@@ -610,9 +599,10 @@ TEST_F(OfflinePageModelTaskifiedTest,
DISABLED_SavePageOfflineCreationStoreWriteFailure) {}
TEST_F(OfflinePageModelTaskifiedTest, SavePageLocalFileFailed) {
- SavePageWithExpectedResult(
- FileUrl(), kTestClientId1, TestUrl2(), kEmptyRequestOrigin,
- std::unique_ptr<OfflinePageTestArchiver>(), SavePageResult::SKIPPED);
+ SavePageWithExpectedResult(GURL("file:///foo"), kTestClientId1,
+ GURL("http://other.page.com"), kEmptyRequestOrigin,
+ std::unique_ptr<OfflinePageTestArchiver>(),
+ SavePageResult::SKIPPED);
histogram_tester()->ExpectUniqueSample(
model_utils::AddHistogramSuffix(kTestClientId1.name_space,
@@ -649,16 +639,17 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverTwoPages) {
// delayed_archiver_ptr will be valid until after first PumpLoop() call after
// CompleteCreateArchive() is called. Keeping the raw pointer because the
// ownership is transferring to the model.
- auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
OfflinePageTestArchiver* delayed_archiver_ptr = archiver.get();
delayed_archiver_ptr->set_delayed(true);
- SavePageWithCallback(TestUrl(), kTestClientId1, GURL(), kEmptyRequestOrigin,
+ SavePageWithCallback(kTestUrl, kTestClientId1, GURL(), kEmptyRequestOrigin,
std::move(archiver), callback.Get());
// Request to save another page, with request origin.
- archiver = BuildArchiver(TestUrl2(), ArchiverResult::SUCCESSFULLY_CREATED);
- SavePageWithCallback(TestUrl2(), kTestClientId2, GURL(), kTestRequestOrigin,
+ const GURL kTestUrl2("http://other.page.com");
+ archiver = BuildArchiver(kTestUrl2, ArchiverResult::SUCCESSFULLY_CREATED);
+ SavePageWithCallback(kTestUrl2, kTestClientId2, GURL(), kTestRequestOrigin,
std::move(archiver), callback.Get());
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path()));
@@ -694,13 +685,13 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverTwoPages) {
ASSERT_TRUE(saved_page_ptr1);
ASSERT_TRUE(saved_page_ptr2);
- EXPECT_EQ(TestUrl2(), saved_page_ptr1->url);
+ EXPECT_EQ(kTestUrl2, saved_page_ptr1->url);
EXPECT_EQ(kTestClientId2, saved_page_ptr1->client_id);
EXPECT_EQ(saved_file_path1, saved_page_ptr1->file_path);
EXPECT_EQ(kTestFileSize, saved_page_ptr1->file_size);
EXPECT_EQ(kTestRequestOrigin, saved_page_ptr1->request_origin);
- EXPECT_EQ(TestUrl(), saved_page_ptr2->url);
+ EXPECT_EQ(GURL("http://example.com"), saved_page_ptr2->url);
EXPECT_EQ(kTestClientId1, saved_page_ptr2->client_id);
EXPECT_EQ(saved_file_path2, saved_page_ptr2->file_path);
EXPECT_EQ(kTestFileSize, saved_page_ptr2->file_size);
@@ -720,14 +711,14 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverTwoPages) {
}
TEST_F(OfflinePageModelTaskifiedTest, SavePageOnBackground) {
- auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
OfflinePageTestArchiver* archiver_ptr = archiver.get();
OfflinePageModel::SavePageParams save_page_params;
- save_page_params.url = TestUrl();
+ save_page_params.url = kTestUrl;
save_page_params.client_id = kTestClientId1;
- save_page_params.original_url = TestUrl2();
+ save_page_params.original_url = GURL("http://other.page.com");
save_page_params.is_background = true;
save_page_params.use_page_problem_detectors = false;
@@ -743,7 +734,7 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageOnBackground) {
}
TEST_F(OfflinePageModelTaskifiedTest, SavePageWithNullArchiver) {
- SavePageWithExpectedResult(TestUrl(), kTestClientId1, GURL(),
+ SavePageWithExpectedResult(GURL("http://example.com"), kTestClientId1, GURL(),
kEmptyRequestOrigin, nullptr,
SavePageResult::CONTENT_UNAVAILABLE);
histogram_tester()->ExpectUniqueSample(
@@ -872,11 +863,12 @@ TEST_F(OfflinePageModelTaskifiedTest, DeletePagesWithCriteria) {
}
TEST_F(OfflinePageModelTaskifiedTest, DeletePagesByUrlPredicate) {
+ const GURL kTestUrl("http://example.com");
page_generator()->SetArchiveDirectory(temporary_dir_path());
page_generator()->SetNamespace(kDefaultNamespace);
- page_generator()->SetUrl(TestUrl());
+ page_generator()->SetUrl(kTestUrl);
OfflinePageItem page1 = page_generator()->CreateItemWithTempFile();
- page_generator()->SetUrl(TestUrl2());
+ page_generator()->SetUrl(GURL("http://other.page.com"));
OfflinePageItem page2 = page_generator()->CreateItemWithTempFile();
InsertPageIntoStore(page1);
InsertPageIntoStore(page2);
@@ -891,7 +883,7 @@ TEST_F(OfflinePageModelTaskifiedTest, DeletePagesByUrlPredicate) {
[](const GURL& expected_url, const GURL& url) -> bool {
return url == expected_url;
},
- TestUrl());
+ kTestUrl);
model()->DeleteCachedPagesByURLPredicate(predicate, callback.Get());
EXPECT_TRUE(task_queue()->HasRunningTask());
@@ -921,7 +913,7 @@ TEST_F(OfflinePageModelTaskifiedTest, DeletePagesByUrlPredicate) {
TEST_F(OfflinePageModelTaskifiedTest, GetPageByOfflineId) {
page_generator()->SetNamespace(kDefaultNamespace);
- page_generator()->SetUrl(TestUrl());
+ page_generator()->SetUrl(GURL("http://example.com"));
OfflinePageItem page = page_generator()->CreateItem();
InsertPageIntoStore(page);
@@ -935,31 +927,33 @@ TEST_F(OfflinePageModelTaskifiedTest, GetPageByOfflineId) {
}
TEST_F(OfflinePageModelTaskifiedTest, GetPagesWithCriteria_FinalUrl) {
- page_generator()->SetUrl(TestUrl());
+ const GURL kTestUrl("http://example.com");
+ const GURL kTestUrl2("http://other.page.com");
+ page_generator()->SetUrl(kTestUrl);
OfflinePageItem page1 = page_generator()->CreateItem();
InsertPageIntoStore(page1);
- page_generator()->SetUrl(TestUrl2());
+ page_generator()->SetUrl(kTestUrl2);
OfflinePageItem page2 = page_generator()->CreateItem();
InsertPageIntoStore(page2);
- // Search by TestUrl().
+ // Search by kTestUrl.
base::MockCallback<MultipleOfflinePageItemCallback> callback;
EXPECT_CALL(callback, Run(ElementsAre(page1)));
PageCriteria criteria;
- criteria.url = TestUrl();
+ criteria.url = kTestUrl;
model()->GetPagesWithCriteria(criteria, callback.Get());
EXPECT_TRUE(task_queue()->HasRunningTask());
PumpLoop();
- // Search by TestUrl2().
+ // Search by kTestUrl2.
EXPECT_CALL(callback, Run(ElementsAre(page2)));
- criteria.url = TestUrl2();
+ criteria.url = kTestUrl2;
model()->GetPagesWithCriteria(criteria, callback.Get());
PumpLoop();
// Search by random url, which should return no pages.
EXPECT_CALL(callback, Run(IsEmpty()));
- criteria.url = OtherUrl();
+ criteria.url = GURL("http://foo");
model()->GetPagesWithCriteria(criteria, callback.Get());
EXPECT_TRUE(task_queue()->HasRunningTask());
PumpLoop();
@@ -967,43 +961,48 @@ TEST_F(OfflinePageModelTaskifiedTest, GetPagesWithCriteria_FinalUrl) {
TEST_F(OfflinePageModelTaskifiedTest,
GetPagesByUrl_FinalUrlWithFragmentStripped) {
- page_generator()->SetUrl(TestUrl());
+ const GURL kTestUrl("http://example.com");
+ const GURL kTestUrlWithFragment("http://example.com#frag");
+ const GURL kTestUrl2("http://other.page.com");
+ const GURL kTestUrl2WithFragment("http://other.page.com#frag");
+ page_generator()->SetUrl(kTestUrl);
OfflinePageItem page1 = page_generator()->CreateItem();
InsertPageIntoStore(page1);
- page_generator()->SetUrl(TestUrl2WithFragment());
+ page_generator()->SetUrl(kTestUrl2WithFragment);
OfflinePageItem page2 = page_generator()->CreateItem();
InsertPageIntoStore(page2);
- // Search by TestUrlWithFragment().
+ // Search by kTestUrlWithFragment.
base::MockCallback<MultipleOfflinePageItemCallback> callback;
EXPECT_CALL(callback, Run(ElementsAre(page1)));
PageCriteria criteria;
- criteria.url = TestUrlWithFragment();
+ criteria.url = kTestUrlWithFragment;
model()->GetPagesWithCriteria(criteria, callback.Get());
EXPECT_TRUE(task_queue()->HasRunningTask());
PumpLoop();
- // Search by TestUrl2().
+ // Search by kTestUrl2.
EXPECT_CALL(callback, Run(ElementsAre(page2)));
- criteria.url = TestUrl2();
+ criteria.url = kTestUrl2;
model()->GetPagesWithCriteria(criteria, callback.Get());
EXPECT_TRUE(task_queue()->HasRunningTask());
PumpLoop();
- // Search by TestUrl2WithFragment().
+ // Search by kTestUrl2WithFragment.
EXPECT_CALL(callback, Run(ElementsAre(page2)));
- criteria.url = TestUrl2WithFragment();
+ criteria.url = kTestUrl2WithFragment;
model()->GetPagesWithCriteria(criteria, callback.Get());
EXPECT_TRUE(task_queue()->HasRunningTask());
PumpLoop();
}
TEST_F(OfflinePageModelTaskifiedTest, GetPagesWithCriteria_AllUrls) {
- page_generator()->SetUrl(TestUrl());
- page_generator()->SetOriginalUrl(TestUrl2());
+ const GURL kTestUrl2("http://other.page.com");
+ page_generator()->SetUrl(GURL("http://example.com"));
+ page_generator()->SetOriginalUrl(kTestUrl2);
OfflinePageItem page1 = page_generator()->CreateItem();
InsertPageIntoStore(page1);
- page_generator()->SetUrl(TestUrl2());
+ page_generator()->SetUrl(kTestUrl2);
page_generator()->SetOriginalUrl(GURL());
OfflinePageItem page2 = page_generator()->CreateItem();
InsertPageIntoStore(page2);
@@ -1011,7 +1010,7 @@ TEST_F(OfflinePageModelTaskifiedTest, GetPagesWithCriteria_AllUrls) {
base::MockCallback<MultipleOfflinePageItemCallback> callback;
EXPECT_CALL(callback, Run(UnorderedElementsAre(page1, page2)));
PageCriteria criteria;
- criteria.url = TestUrl2();
+ criteria.url = kTestUrl2;
model()->GetPagesWithCriteria(criteria, callback.Get());
PumpLoop();
}
@@ -1054,10 +1053,10 @@ TEST_F(OfflinePageModelTaskifiedTest, GetOfflineIdsForClientId) {
#endif
TEST_F(OfflinePageModelTaskifiedTest, MAYBE_CheckTempPagesSavedInCorrectDir) {
// Save a temporary page.
- auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
int64_t temporary_id = SavePageWithExpectedResult(
- TestUrl(), kTestLastNClientId, GURL(), kEmptyRequestOrigin,
+ kTestUrl, kTestLastNClientId, GURL(), kEmptyRequestOrigin,
std::move(archiver), SavePageResult::SUCCESS);
std::unique_ptr<OfflinePageItem> temporary_page =
@@ -1094,10 +1093,10 @@ TEST_F(OfflinePageModelTaskifiedTest, MAYBE_CheckTempPagesSavedInCorrectDir) {
TEST_F(OfflinePageModelTaskifiedTest,
MAYBE_CheckPersistenPagesSavedInCorrectDir) {
// Save a persistent page that will be published to the public folder.
- auto archiver =
- BuildArchiver(TestUrl2(), ArchiverResult::SUCCESSFULLY_CREATED);
+ const GURL kTestUrl("http://other.page.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
int64_t persistent_id = SavePageWithExpectedResult(
- TestUrl2(), kTestUserRequestedClientId, GURL(), kEmptyRequestOrigin,
+ kTestUrl, kTestUserRequestedClientId, GURL(), kEmptyRequestOrigin,
std::move(archiver), SavePageResult::SUCCESS);
std::unique_ptr<OfflinePageItem> persistent_page =
@@ -1132,8 +1131,8 @@ TEST_F(OfflinePageModelTaskifiedTest,
TEST_F(OfflinePageModelTaskifiedTest, MAYBE_PublishPageFailure) {
// Save a persistent page that will report failure to be copied to a public
// dir.
- auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
// Expect that PublishArchive is called and force returning FILE_MOVE_FAILED.
auto publisher = std::make_unique<OfflinePageTestArchivePublisher>(
@@ -1142,7 +1141,7 @@ TEST_F(OfflinePageModelTaskifiedTest, MAYBE_PublishPageFailure) {
publisher->set_archive_attempt_failure(true);
SetTestArchivePublisher(std::move(publisher));
- SavePageWithExpectedResult(TestUrl(), kTestUserRequestedClientId, GURL(),
+ SavePageWithExpectedResult(kTestUrl, kTestUserRequestedClientId, GURL(),
kEmptyRequestOrigin, std::move(archiver),
SavePageResult::FILE_MOVE_FAILED);
@@ -1163,10 +1162,11 @@ TEST_F(OfflinePageModelTaskifiedTest, MAYBE_PublishPageFailure) {
TEST_F(OfflinePageModelTaskifiedTest, MAYBE_CheckPublishInternalArchive) {
// Save a persistent page into our internal directory that will not be
// published. We use a "browser actions" page for this purpose.
+ const GURL kTestUrl("http://other.page.com");
std::unique_ptr<OfflinePageTestArchiver> test_archiver =
- BuildArchiver(TestUrl2(), ArchiverResult::SUCCESSFULLY_CREATED);
+ BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
int64_t persistent_id = SavePageWithExpectedResult(
- TestUrl2(), kTestBrowserActionsClientId, GURL(), kEmptyRequestOrigin,
+ kTestUrl, kTestBrowserActionsClientId, GURL(), kEmptyRequestOrigin,
std::move(test_archiver), SavePageResult::SUCCESS);
std::unique_ptr<OfflinePageItem> persistent_page =
@@ -1191,9 +1191,10 @@ TEST_F(OfflinePageModelTaskifiedTest, ExtraActionTriggeredWhenSaveSuccess) {
// Add pages that have the same namespace and url directly into store, in
// order to avoid triggering the removal.
// The 'default' namespace has a limit of 1 per url.
+ const GURL kTestUrl("http://example.com");
page_generator()->SetArchiveDirectory(temporary_dir_path());
page_generator()->SetNamespace(kDefaultNamespace);
- page_generator()->SetUrl(TestUrl());
+ page_generator()->SetUrl(kTestUrl);
OfflinePageItem page1 = page_generator()->CreateItemWithTempFile();
OfflinePageItem page2 = page_generator()->CreateItemWithTempFile();
InsertPageIntoStore(page1);
@@ -1202,10 +1203,10 @@ TEST_F(OfflinePageModelTaskifiedTest, ExtraActionTriggeredWhenSaveSuccess) {
ResetResults();
std::unique_ptr<OfflinePageTestArchiver> archiver(
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED));
- SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(),
- kEmptyRequestOrigin, std::move(archiver),
- SavePageResult::SUCCESS);
+ BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED));
+ SavePageWithExpectedResult(kTestUrl, kTestClientId1,
+ GURL("http://other.page.com"), kEmptyRequestOrigin,
+ std::move(archiver), SavePageResult::SUCCESS);
EXPECT_TRUE(observer_add_page_called());
EXPECT_TRUE(observer_delete_page_called());
@@ -1337,11 +1338,11 @@ TEST_F(OfflinePageModelTaskifiedTest, ClearStorage) {
FastForwardBy(OfflinePageModelTaskified::kClearStorageInterval / 2 +
base::TimeDelta::FromSeconds(1));
// Saving a page should also immediately enqueue the ClearStorage task.
- auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED);
- SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(),
- kEmptyRequestOrigin, std::move(archiver),
- SavePageResult::SUCCESS);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
+ SavePageWithExpectedResult(kTestUrl, kTestClientId1,
+ GURL("http://other.page.com"), kEmptyRequestOrigin,
+ std::move(archiver), SavePageResult::SUCCESS);
last_scheduling_time = clock()->Now();
// Advance the delay again.
FastForwardBy(run_delay);
@@ -1444,11 +1445,11 @@ TEST_F(OfflinePageModelTaskifiedTest, PersistentPageConsistencyCheckExecuted) {
// get expired.
FastForwardBy(base::TimeDelta::FromDays(400));
// Saving a page should also immediately enqueue the consistency check task.
- auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED);
- SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(),
- kEmptyRequestOrigin, std::move(archiver),
- SavePageResult::SUCCESS);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
+ SavePageWithExpectedResult(kTestUrl, kTestClientId1,
+ GURL("http://other.page.com"), kEmptyRequestOrigin,
+ std::move(archiver), SavePageResult::SUCCESS);
// Advance the delay to activate task execution.
FastForwardBy(run_delay);
// Confirm persistent page consistency check is executed, and the page is
@@ -1470,11 +1471,11 @@ TEST_F(OfflinePageModelTaskifiedTest, MaintenanceTasksAreDisabled) {
// maintenance tasks.
base::MockCallback<MultipleOfflinePageItemCallback> callback;
model()->GetAllPages(callback.Get());
- auto archiver =
- BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED);
- SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(),
- kEmptyRequestOrigin, std::move(archiver),
- SavePageResult::SUCCESS);
+ const GURL kTestUrl("http://example.com");
+ auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED);
+ SavePageWithExpectedResult(kTestUrl, kTestClientId1,
+ GURL("http://other.page.com"), kEmptyRequestOrigin,
+ std::move(archiver), SavePageResult::SUCCESS);
PumpLoop();
EXPECT_EQ(base::Time(), last_maintenance_tasks_schedule_time());
@@ -1504,7 +1505,7 @@ TEST_F(OfflinePageModelTaskifiedTest, StoreAndCheckThumbnail) {
PumpLoop();
// Check it exists
- base::Optional<VisualsAvailability> availability;
+ absl::optional<VisualsAvailability> availability;
auto exists_callback = base::BindLambdaForTesting(
[&](VisualsAvailability value) { availability = value; });
model()->GetVisualsAvailability(visuals.offline_id, exists_callback);
@@ -1534,7 +1535,7 @@ TEST_F(OfflinePageModelTaskifiedTest, StoreAndCheckFavicon) {
PumpLoop();
// Check if it exists.
- base::Optional<VisualsAvailability> availability;
+ absl::optional<VisualsAvailability> availability;
auto exists_callback = base::BindLambdaForTesting(
[&](VisualsAvailability value) { availability = value; });
model()->GetVisualsAvailability(visuals.offline_id, exists_callback);
diff --git a/chromium/components/offline_pages/core/model/offline_page_test_utils.h b/chromium/components/offline_pages/core/model/offline_page_test_utils.h
index 421d1b45e95..b1d7544234b 100644
--- a/chromium/components/offline_pages/core/model/offline_page_test_utils.h
+++ b/chromium/components/offline_pages/core/model/offline_page_test_utils.h
@@ -2,12 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_TEST_UTILS_H_
-#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_TEST_UTILS_H_
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_PAGE_TEST_UTILS_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_PAGE_TEST_UTILS_H_
-#include <stdint.h>
-
-#include <string>
+#include <stddef.h>
namespace base {
@@ -28,4 +26,4 @@ size_t GetFileCountInDirectory(const base::FilePath& directory);
} // namespace offline_pages
-#endif // COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_TEST_UTILS_H_
+#endif // COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_PAGE_TEST_UTILS_H_
diff --git a/chromium/components/offline_pages/core/model/offline_page_upgrade_types.h b/chromium/components/offline_pages/core/model/offline_page_upgrade_types.h
index 3fd1b95a9a0..e9b5975ab4f 100644
--- a/chromium/components/offline_pages/core/model/offline_page_upgrade_types.h
+++ b/chromium/components/offline_pages/core/model/offline_page_upgrade_types.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_OFFLINE_PAGES_CORE_MODEL_OFFLINE_PAGE_UPRGRADE_TYPES_H_
-#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_PAGE_UPRGRADE_TYPES_H_
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_PAGE_UPGRADE_TYPES_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_PAGE_UPGRADE_TYPES_H_
#include <string>
@@ -58,4 +58,4 @@ typedef base::OnceCallback<void(CompleteUpgradeStatus)> CompleteUpgradeCallback;
} // namespace offline_pages
-#endif // COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_PAGE_UPRGRADE_TYPES_H_
+#endif // COMPONENTS_OFFLINE_PAGES_CORE_MODEL_OFFLINE_PAGE_UPGRADE_TYPES_H_
diff --git a/chromium/components/offline_pages/core/model/update_publish_id_task.h b/chromium/components/offline_pages/core/model/update_publish_id_task.h
index 75b1d097f5c..5b4e1cab5cf 100644
--- a/chromium/components/offline_pages/core/model/update_publish_id_task.h
+++ b/chromium/components/offline_pages/core/model/update_publish_id_task.h
@@ -6,7 +6,6 @@
#define COMPONENTS_OFFLINE_PAGES_CORE_MODEL_UPDATE_PUBLISH_ID_TASK_H_
#include "base/callback.h"
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/offline_pages/core/model/get_pages_task.h"
diff --git a/chromium/components/offline_pages/core/offline_page_archive_publisher.h b/chromium/components/offline_pages/core/offline_page_archive_publisher.h
index 5d906574497..cea4b63428f 100644
--- a/chromium/components/offline_pages/core/offline_page_archive_publisher.h
+++ b/chromium/components/offline_pages/core/offline_page_archive_publisher.h
@@ -6,7 +6,6 @@
#define COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_PAGE_ARCHIVE_PUBLISHER_H_
#include <cstdint>
-#include <string>
#include "base/callback.h"
#include "base/files/file_path.h"
diff --git a/chromium/components/offline_pages/core/offline_page_feature.cc b/chromium/components/offline_pages/core/offline_page_feature.cc
index 38a3858c6a9..1d53df4c69c 100644
--- a/chromium/components/offline_pages/core/offline_page_feature.cc
+++ b/chromium/components/offline_pages/core/offline_page_feature.cc
@@ -20,9 +20,6 @@ const char kOfflinePagesUseTestingSnapshotDelay[] =
namespace offline_pages {
-const base::Feature kOffliningRecentPagesFeature{
- "OfflineRecentPages", base::FEATURE_ENABLED_BY_DEFAULT};
-
const base::Feature kOfflinePagesCTFeature{"OfflinePagesCT",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -47,24 +44,14 @@ const base::Feature kOfflinePagesInDownloadHomeOpenInCctFeature{
const base::Feature kOfflinePagesCTSuppressNotificationsFeature{
"OfflinePagesCTSuppressNotifications", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kOfflinePagesShowAlternateDinoPageFeature{
- "OfflinePagesShowAlternateDinoPage", base::FEATURE_DISABLED_BY_DEFAULT};
-
const base::Feature kOfflineIndicatorFeature{"OfflineIndicator",
base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kOfflineIndicatorAlwaysHttpProbeFeature{
- "OfflineIndicatorAlwaysHttpProbe", base::FEATURE_DISABLED_BY_DEFAULT};
-
const base::Feature kOfflinePagesNetworkStateLikelyUnknown{
"OfflinePagesNetworkStateLikelyUnknown", base::FEATURE_DISABLED_BY_DEFAULT};
const char kPrefetchingOfflinePagesExperimentsOption[] = "exp";
-bool IsOffliningRecentPagesEnabled() {
- return base::FeatureList::IsEnabled(kOffliningRecentPagesFeature);
-}
-
bool IsOfflinePagesCTEnabled() {
return base::FeatureList::IsEnabled(kOfflinePagesCTFeature);
}
@@ -106,11 +93,6 @@ bool IsOfflinePagesSuppressNotificationsEnabled() {
kOfflinePagesCTSuppressNotificationsFeature);
}
-bool ShouldShowAlternateDinoPage() {
- return base::FeatureList::IsEnabled(
- kOfflinePagesShowAlternateDinoPageFeature);
-}
-
std::string GetPrefetchingOfflinePagesExperimentTag() {
return base::GetFieldTrialParamValueByFeature(
kPrefetchingOfflinePagesFeature,
@@ -121,10 +103,6 @@ bool IsOfflineIndicatorFeatureEnabled() {
return base::FeatureList::IsEnabled(kOfflineIndicatorFeature);
}
-bool IsOfflineIndicatorAlwaysHttpProbeEnabled() {
- return base::FeatureList::IsEnabled(kOfflineIndicatorAlwaysHttpProbeFeature);
-}
-
bool IsOnTheFlyMhtmlHashComputationEnabled() {
return false;
}
diff --git a/chromium/components/offline_pages/core/offline_page_feature.h b/chromium/components/offline_pages/core/offline_page_feature.h
index 6295a79b5a3..40889b96a5b 100644
--- a/chromium/components/offline_pages/core/offline_page_feature.h
+++ b/chromium/components/offline_pages/core/offline_page_feature.h
@@ -10,7 +10,6 @@
namespace offline_pages {
-extern const base::Feature kOffliningRecentPagesFeature;
extern const base::Feature kOfflinePagesCTFeature;
extern const base::Feature kOfflinePagesLivePageSharingFeature;
extern const base::Feature kBackgroundLoaderForDownloadsFeature;
@@ -20,9 +19,7 @@ extern const base::Feature kOfflinePagesDescriptivePendingStatusFeature;
extern const base::Feature kOfflinePagesInDownloadHomeOpenInCctFeature;
extern const base::Feature kOfflinePagesDescriptiveFailStatusFeature;
extern const base::Feature kOfflinePagesCTSuppressNotificationsFeature;
-extern const base::Feature kOfflinePagesShowAlternateDinoPageFeature;
extern const base::Feature kOfflineIndicatorFeature;
-extern const base::Feature kOfflineIndicatorAlwaysHttpProbeFeature;
extern const base::Feature kOnTheFlyMhtmlHashComputationFeature;
extern const base::Feature kOfflinePagesNetworkStateLikelyUnknown;
@@ -30,9 +27,6 @@ extern const base::Feature kOfflinePagesNetworkStateLikelyUnknown;
// pages.
extern const char kPrefetchingOfflinePagesExperimentsOption[];
-// Returns true if offlining of recent pages (aka 'Last N pages') is enabled.
-bool IsOffliningRecentPagesEnabled();
-
// Returns true if offline CT features are enabled. See crbug.com/620421.
bool IsOfflinePagesCTEnabled();
@@ -77,12 +71,6 @@ std::string GetPrefetchingOfflinePagesExperimentTag();
// Returns true if offline indicator UI is shown when the user is offline.
bool IsOfflineIndicatorFeatureEnabled();
-// Returns true if we should always do http probes to detect network
-// connectivity instead of retrieving it from the system. This enables the user
-// to test our http probe detection on Android devices with Marshmallow and
-// above.
-bool IsOfflineIndicatorAlwaysHttpProbeEnabled();
-
// Returns true if we are saving MHTML files to the target location and
// calculating their content digests in one step.
bool IsOnTheFlyMhtmlHashComputationEnabled();
@@ -94,4 +82,4 @@ bool IsOfflinePagesNetworkStateLikelyUnknown();
} // namespace offline_pages
-#endif // COMPONENTS_OFFLINE_PAGES_OFFLINE_PAGE_FEATURE_H_
+#endif // COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_PAGE_FEATURE_H_
diff --git a/chromium/components/offline_pages/core/offline_page_feature_unittest.cc b/chromium/components/offline_pages/core/offline_page_feature_unittest.cc
deleted file mode 100644
index 35362d268f2..00000000000
--- a/chromium/components/offline_pages/core/offline_page_feature_unittest.cc
+++ /dev/null
@@ -1,88 +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/offline_pages/core/offline_page_feature.h"
-
-#include "base/feature_list.h"
-#include "base/test/scoped_feature_list.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace offline_pages {
-
-TEST(OfflinePageFeatureTest, OffliningRecentPages) {
- // Enabled by default.
- EXPECT_TRUE(offline_pages::IsOffliningRecentPagesEnabled());
-
- // Check if helper method works correctly when the features is disabled.
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndDisableFeature(kOffliningRecentPagesFeature);
- EXPECT_FALSE(offline_pages::IsOffliningRecentPagesEnabled());
-}
-
-TEST(OfflinePageFeatureTest, OfflinePagesLivePageSharing) {
- // Disabled by default.
- EXPECT_FALSE(
- base::FeatureList::IsEnabled(kOfflinePagesLivePageSharingFeature));
-
- // Check if helper method works correctly when the feature is disabled.
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(kOfflinePagesLivePageSharingFeature);
- EXPECT_TRUE(offline_pages::IsOfflinePagesLivePageSharingEnabled());
-}
-
-TEST(OfflinePageFeatureTest, OfflinePagesPrefetching) {
- // Enabled by default.
- EXPECT_TRUE(offline_pages::IsPrefetchingOfflinePagesEnabled());
-
- // Check if helper method works correctly when the features is disabled.
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndDisableFeature(kPrefetchingOfflinePagesFeature);
- EXPECT_FALSE(offline_pages::IsPrefetchingOfflinePagesEnabled());
-}
-
-TEST(OfflinePageFeatureTest, OfflinePagesInDownloadHomeOpenInCct) {
- // Enabled by default.
- EXPECT_TRUE(offline_pages::ShouldOfflinePagesInDownloadHomeOpenInCct());
-
- // Check if helper method works correctly when the features is disabled.
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndDisableFeature(
- kOfflinePagesInDownloadHomeOpenInCctFeature);
- EXPECT_FALSE(offline_pages::ShouldOfflinePagesInDownloadHomeOpenInCct());
-}
-
-TEST(OfflinePageFeatureTest, OfflinePagesDescriptiveFailStatus) {
- // Disabled by default.
- EXPECT_FALSE(offline_pages::IsOfflinePagesDescriptiveFailStatusEnabled());
-
- // Check if helper method works correctly when the features is enabled.
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(
- kOfflinePagesDescriptiveFailStatusFeature);
- EXPECT_TRUE(offline_pages::IsOfflinePagesDescriptiveFailStatusEnabled());
-}
-
-TEST(OfflinePageFeatureTest, OfflinePagesDescriptivePendingStatus) {
- // Enabled by default.
- EXPECT_TRUE(offline_pages::IsOfflinePagesDescriptivePendingStatusEnabled());
-
- // Check if helper method works correctly when the features is enabled.
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndDisableFeature(
- kOfflinePagesDescriptivePendingStatusFeature);
- EXPECT_FALSE(offline_pages::IsOfflinePagesDescriptivePendingStatusEnabled());
-}
-
-TEST(OfflinePageFeatureTest, AlternateDinoPage) {
- // Disabled by default.
- EXPECT_FALSE(offline_pages::ShouldShowAlternateDinoPage());
-
- // Check if helper method works correctly when the features is enabled.
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(
- kOfflinePagesShowAlternateDinoPageFeature);
- EXPECT_TRUE(offline_pages::ShouldShowAlternateDinoPage());
-}
-
-} // namespace offline_pages
diff --git a/chromium/components/offline_pages/core/offline_page_metadata_store.cc b/chromium/components/offline_pages/core/offline_page_metadata_store.cc
index b150e00cdc7..1cc7686ab6d 100644
--- a/chromium/components/offline_pages/core/offline_page_metadata_store.cc
+++ b/chromium/components/offline_pages/core/offline_page_metadata_store.cc
@@ -14,6 +14,7 @@
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/offline_page_item.h"
#include "components/offline_pages/core/offline_store_types.h"
diff --git a/chromium/components/offline_pages/core/offline_page_metadata_store.h b/chromium/components/offline_pages/core/offline_page_metadata_store.h
index e823c8870a0..142e851b7bc 100644
--- a/chromium/components/offline_pages/core/offline_page_metadata_store.h
+++ b/chromium/components/offline_pages/core/offline_page_metadata_store.h
@@ -7,16 +7,12 @@
#include <stdint.h>
-#include <memory>
-#include <vector>
-
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
#include "components/offline_pages/core/offline_page_item.h"
#include "components/offline_pages/core/offline_store_types.h"
#include "components/offline_pages/task/sql_store_base.h"
diff --git a/chromium/components/offline_pages/core/offline_page_metadata_store_test_util.cc b/chromium/components/offline_pages/core/offline_page_metadata_store_test_util.cc
index bf0f5eb1c7c..49ce272eb39 100644
--- a/chromium/components/offline_pages/core/offline_page_metadata_store_test_util.cc
+++ b/chromium/components/offline_pages/core/offline_page_metadata_store_test_util.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
diff --git a/chromium/components/offline_pages/core/offline_page_test_archive_publisher.h b/chromium/components/offline_pages/core/offline_page_test_archive_publisher.h
index ab285f885b7..55a8202a095 100644
--- a/chromium/components/offline_pages/core/offline_page_test_archive_publisher.h
+++ b/chromium/components/offline_pages/core/offline_page_test_archive_publisher.h
@@ -6,10 +6,8 @@
#define COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_PAGE_TEST_ARCHIVE_PUBLISHER_H_
#include <cstdint>
-#include <string>
#include "base/callback.h"
-#include "base/files/file_path.h"
#include "components/offline_pages/core/offline_page_archive_publisher.h"
#include "components/offline_pages/core/offline_page_item.h"
#include "components/offline_pages/core/offline_page_types.h"
diff --git a/chromium/components/offline_pages/core/page_criteria.h b/chromium/components/offline_pages/core/page_criteria.h
index df4b34d029f..7380d73f5a4 100644
--- a/chromium/components/offline_pages/core/page_criteria.h
+++ b/chromium/components/offline_pages/core/page_criteria.h
@@ -11,9 +11,9 @@
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
#include "components/offline_pages/core/client_id.h"
#include "components/offline_pages/core/offline_page_client_policy.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace offline_pages {
@@ -42,26 +42,26 @@ struct PageCriteria {
// If specified, accepts pages that can be displayed in the specified tab.
// That is, tab-bound pages are filtered out unless the tab ID matches this
// field and non-tab-bound pages are always included.
- base::Optional<int> pages_for_tab_id;
+ absl::optional<int> pages_for_tab_id;
// Whether to restrict pages to those in namespaces supported by the
// downloads UI.
bool supported_by_downloads = false;
// If set, the page's lifetime type must match this.
- base::Optional<LifetimeType> lifetime_type;
+ absl::optional<LifetimeType> lifetime_type;
// If set, the page's file_size must match.
- base::Optional<int64_t> file_size;
+ absl::optional<int64_t> file_size;
// If non-empty, the page's digest must match.
std::string digest;
// If set, the page's namespace must match.
- base::Optional<std::vector<std::string>> client_namespaces;
+ absl::optional<std::vector<std::string>> client_namespaces;
// If set, the page's client_id must match one of these.
- base::Optional<std::vector<ClientId>> client_ids;
+ absl::optional<std::vector<ClientId>> client_ids;
// If non-empty, the page's client_id.id must match this.
std::string guid;
// If non-empty, the page's request_origin must match.
std::string request_origin;
// If set, the page's offline_id must match.
- base::Optional<std::vector<int64_t>> offline_ids;
+ absl::optional<std::vector<int64_t>> offline_ids;
// If non-null, this function is executed for each matching item. If it
// returns false, the item will not be returned. This is evaluated last, and
// only for pages that otherwise meet all other criteria.
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_background_task_handler.h b/chromium/components/offline_pages/core/prefetch/prefetch_background_task_handler.h
index cf06732d2a1..dd349040983 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_background_task_handler.h
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_background_task_handler.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_BACKGROUND_TASK_HANDLER_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_BACKGROUND_TASK_HANDLER_H_
-#include <memory>
-
namespace offline_pages {
// Interface for system-specific integrations with background task scheduling.
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc b/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
index 27f4efac6a2..2184601e152 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
@@ -69,18 +69,9 @@ const char kThumbnailData[] = "thumbnail_data";
const char kFaviconData[] = "favicon_data";
const base::Time kRenderTime = base::Time::Now();
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL TestURL1() {
- return GURL("https://www.chromium.org");
-}
-GURL TestURL2() {
- return GURL("https://www.chromium.org/2");
-}
-
-PrefetchSuggestion TestSuggestion1() {
+PrefetchSuggestion TestSuggestion1(GURL url = GURL("http://www.news.com")) {
PrefetchSuggestion suggestion;
- suggestion.article_url = TestURL1();
+ suggestion.article_url = url;
suggestion.article_title = "Article Title";
suggestion.article_attribution = "From news.com";
suggestion.article_snippet = "This is an article";
@@ -91,7 +82,7 @@ PrefetchSuggestion TestSuggestion1() {
PrefetchSuggestion TestSuggestion2() {
PrefetchSuggestion suggestion;
- suggestion.article_url = TestURL2();
+ suggestion.article_url = GURL("http://www.fun.com");
suggestion.article_title = "Second Title";
suggestion.article_attribution = "From fun.com";
suggestion.article_snippet = "More fun stuff";
@@ -562,7 +553,8 @@ TEST_F(PrefetchDispatcherTest,
}
TEST_F(PrefetchDispatcherTest, DispatcherReleasesBackgroundTask) {
- PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string());
+ PrefetchURL prefetch_url(kTestID, GURL("https://www.chromium.org"),
+ std::u16string());
prefetch_dispatcher()->AddCandidatePrefetchURLs(
kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url));
RunUntilIdle();
@@ -609,7 +601,8 @@ TEST_F(PrefetchDispatcherTest, DispatcherReleasesBackgroundTask) {
}
TEST_F(PrefetchDispatcherTest, RetryWithBackoffAfterFailedNetworkRequest) {
- PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string());
+ PrefetchURL prefetch_url(kTestID, GURL("https://www.chromium.org"),
+ std::u16string());
prefetch_dispatcher()->AddCandidatePrefetchURLs(
kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url));
RunUntilIdle();
@@ -618,7 +611,8 @@ TEST_F(PrefetchDispatcherTest, RetryWithBackoffAfterFailedNetworkRequest) {
RunUntilIdle();
// Trigger another request to make sure we have more work to do.
- PrefetchURL prefetch_url2(kTestID, TestURL2(), std::u16string());
+ PrefetchURL prefetch_url2(kTestID, GURL("https://www.chromium.org/2"),
+ std::u16string());
prefetch_dispatcher()->AddCandidatePrefetchURLs(
kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2));
RunUntilIdle();
@@ -641,7 +635,8 @@ TEST_F(PrefetchDispatcherTest, RetryWithBackoffAfterFailedNetworkRequest) {
}
TEST_F(PrefetchDispatcherTest, RetryWithoutBackoffAfterFailedNetworkRequest) {
- PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string());
+ PrefetchURL prefetch_url(kTestID, GURL("https://www.chromium.org"),
+ std::u16string());
prefetch_dispatcher()->AddCandidatePrefetchURLs(
kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url));
RunUntilIdle();
@@ -650,7 +645,8 @@ TEST_F(PrefetchDispatcherTest, RetryWithoutBackoffAfterFailedNetworkRequest) {
RunUntilIdle();
// Trigger another request to make sure we have more work to do.
- PrefetchURL prefetch_url2(kTestID, TestURL2(), std::u16string());
+ PrefetchURL prefetch_url2(kTestID, GURL("https://www.chromium.org/2"),
+ std::u16string());
prefetch_dispatcher()->AddCandidatePrefetchURLs(
kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2));
@@ -672,7 +668,8 @@ TEST_F(PrefetchDispatcherTest, RetryWithoutBackoffAfterFailedNetworkRequest) {
}
TEST_F(PrefetchDispatcherTest, SuspendAfterFailedNetworkRequest) {
- PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string());
+ PrefetchURL prefetch_url(kTestID, GURL("https://www.chromium.org"),
+ std::u16string());
prefetch_dispatcher()->AddCandidatePrefetchURLs(
kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url));
RunUntilIdle();
@@ -681,7 +678,8 @@ TEST_F(PrefetchDispatcherTest, SuspendAfterFailedNetworkRequest) {
RunUntilIdle();
// Trigger another request to make sure we have more work to do.
- PrefetchURL prefetch_url2(kTestID, TestURL2(), std::u16string());
+ PrefetchURL prefetch_url2(kTestID, GURL("https://www.chromium.org/2"),
+ std::u16string());
prefetch_dispatcher()->AddCandidatePrefetchURLs(
kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2));
@@ -718,7 +716,8 @@ TEST_F(PrefetchDispatcherTest, SuspendAfterFailedNetworkRequest) {
}
TEST_F(PrefetchDispatcherTest, SuspendRemovedAfterNewBackgroundTask) {
- PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string());
+ PrefetchURL prefetch_url(kTestID, GURL("https://www.chromium.org"),
+ std::u16string());
prefetch_dispatcher()->AddCandidatePrefetchURLs(
kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url));
RunUntilIdle();
@@ -744,7 +743,8 @@ TEST_F(PrefetchDispatcherTest, SuspendRemovedAfterNewBackgroundTask) {
EXPECT_EQ(nullptr, GetBackgroundTask());
// Trigger another request to make sure we have more work to do.
- PrefetchURL prefetch_url2(kTestID, TestURL2(), std::u16string());
+ PrefetchURL prefetch_url2(kTestID, GURL("https://www.chromium.org/2"),
+ std::u16string());
prefetch_dispatcher()->AddCandidatePrefetchURLs(
kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2));
@@ -825,9 +825,10 @@ TEST_F(PrefetchDispatcherTest, ThumbnailImageFetch_SeveralThumbnailDownloads) {
}
TEST_F(PrefetchDispatcherTest, FeedNoNetworkRequestsAfterNewURLs) {
- suggestions_provider_->SetSuggestions({TestSuggestion1()});
+ const GURL kUrl("https://www.chromium.org");
+ suggestions_provider_->SetSuggestions({TestSuggestion1(kUrl)});
- PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string());
+ PrefetchURL prefetch_url(kTestID, kUrl, std::u16string());
prefetch_service()->NewSuggestionsAvailable();
RunUntilIdle();
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc b/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc
index e7b979e1b48..f20cb7a1cd8 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc
@@ -108,9 +108,8 @@ void PrefetchDownloaderImpl::StartDownload(const std::string& download_id,
net::MutableNetworkTrafficAnnotationTag(traffic_annotation);
params.client = download::DownloadClient::OFFLINE_PAGE_PREFETCH;
params.guid = download_id;
- params.callback = base::AdaptCallbackForRepeating(
- base::BindOnce(&PrefetchDownloaderImpl::OnStartDownload,
- weak_ptr_factory_.GetWeakPtr()));
+ params.callback = base::BindOnce(&PrefetchDownloaderImpl::OnStartDownload,
+ weak_ptr_factory_.GetWeakPtr());
params.scheduling_params.network_requirements =
download::SchedulingParams::NetworkRequirements::UNMETERED;
params.scheduling_params.battery_requirements =
@@ -147,7 +146,7 @@ void PrefetchDownloaderImpl::StartDownload(const std::string& download_id,
}
// The download service can queue the download even if it is not fully up yet.
- download_service_->StartDownload(params);
+ download_service_->StartDownload(std::move(params));
}
void PrefetchDownloaderImpl::OnDownloadServiceReady(
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl_unittest.cc b/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl_unittest.cc
index 1678e25d3c6..35e1c21eaf1 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl_unittest.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_downloader_impl_unittest.cc
@@ -76,7 +76,7 @@ class PrefetchDownloaderImplTest : public PrefetchRequestTestBase {
operation_name);
}
- base::Optional<download::DownloadParams> GetDownload(
+ const absl::optional<download::DownloadParams>& GetDownload(
const std::string& guid) const {
return download_service_.GetDownload(guid);
}
@@ -109,7 +109,8 @@ TEST_F(PrefetchDownloaderImplTest, DownloadParams) {
clock()->SetNow(epoch);
StartDownload(kDownloadId, kDownloadLocation, kOperationName);
- base::Optional<download::DownloadParams> params = GetDownload(kDownloadId);
+ const absl::optional<download::DownloadParams>& params =
+ GetDownload(kDownloadId);
ASSERT_TRUE(params.has_value());
EXPECT_EQ(kDownloadId, params->guid);
EXPECT_EQ(download::DownloadClient::OFFLINE_PAGE_PREFETCH, params->client);
@@ -137,7 +138,8 @@ TEST_F(PrefetchDownloaderImplTest, ExperimentHeaderInDownloadParams) {
SetUpExperimentOption();
StartDownload(kDownloadId, kDownloadLocation, kOperationName);
- base::Optional<download::DownloadParams> params = GetDownload(kDownloadId);
+ const absl::optional<download::DownloadParams>& params =
+ GetDownload(kDownloadId);
ASSERT_TRUE(params.has_value());
std::string header_value;
EXPECT_TRUE(params->request_params.request_headers.GetHeader(
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 5fee09f38ae..7da3a7ab1ff 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
@@ -26,18 +26,6 @@ const std::u16string kTestTitle = u"Hello";
const base::FilePath kTestFilePath(FILE_PATH_LITERAL("foo"));
const int64_t kTestFileSize = 88888;
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL TestURL() {
- return GURL("http://sample.org");
-}
-GURL TestFinalURL() {
- return GURL("https://sample.org/foo");
-}
-
-GURL TestFaviconURL() {
- return GURL("http://sample.org/favicon.png");
-}
std::string TestSnippet() {
return "test snippet";
}
@@ -84,18 +72,21 @@ class PrefetchImporterImplTest : public testing::Test {
void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
- void ImportArchive(int64_t offline_id, const base::FilePath& file_path) {
+ void ImportArchive(int64_t offline_id,
+ GURL url,
+ GURL final_url,
+ const base::FilePath& file_path) {
PrefetchImporterImpl importer(dispatcher(), &model_, task_runner_);
PrefetchArchiveInfo archive;
archive.offline_id = offline_id;
archive.client_id = kTestClientID;
- archive.url = TestURL();
- archive.final_archived_url = TestFinalURL();
+ archive.url = std::move(url);
+ archive.final_archived_url = std::move(final_url);
archive.title = kTestTitle;
archive.file_path = file_path;
archive.file_size = kTestFileSize;
- archive.favicon_url = TestFaviconURL();
+ archive.favicon_url = GURL("http://sample.org/favicon.png");
archive.snippet = TestSnippet();
archive.attribution = TestAttribution();
importer.ImportArchive(archive);
@@ -119,9 +110,11 @@ class PrefetchImporterImplTest : public testing::Test {
};
TEST_F(PrefetchImporterImplTest, ImportSuccess) {
+ const GURL kUrl("http://sample.org");
+ const GURL kFinalUrl("https://sample.org/foo");
base::FilePath path;
base::CreateTemporaryFileInDir(temp_dir_path(), &path);
- ImportArchive(kTestOfflineID, path);
+ ImportArchive(kTestOfflineID, kUrl, kFinalUrl, path);
ASSERT_EQ(1u, dispatcher()->import_results.size());
EXPECT_EQ(kTestOfflineID, dispatcher()->import_results[0].first);
@@ -130,8 +123,8 @@ TEST_F(PrefetchImporterImplTest, ImportSuccess) {
EXPECT_TRUE(offline_page_model()->page_added());
EXPECT_EQ(kTestOfflineID, offline_page_model()->last_added_page().offline_id);
EXPECT_EQ(kTestClientID, offline_page_model()->last_added_page().client_id);
- EXPECT_EQ(TestFinalURL(), offline_page_model()->last_added_page().url);
- EXPECT_EQ(TestURL(),
+ EXPECT_EQ(kFinalUrl, offline_page_model()->last_added_page().url);
+ EXPECT_EQ(kUrl,
offline_page_model()->last_added_page().original_url_if_different);
EXPECT_EQ(kTestTitle, offline_page_model()->last_added_page().title);
EXPECT_EQ(kTestFileSize, offline_page_model()->last_added_page().file_size);
@@ -142,7 +135,8 @@ TEST_F(PrefetchImporterImplTest, ImportSuccess) {
}
TEST_F(PrefetchImporterImplTest, MoveFileError) {
- ImportArchive(kTestOfflineID, kTestFilePath);
+ ImportArchive(kTestOfflineID, GURL("http://sample.org"),
+ GURL("https://sample.org/foo"), kTestFilePath);
ASSERT_EQ(1u, dispatcher()->import_results.size());
EXPECT_EQ(kTestOfflineID, dispatcher()->import_results[0].first);
@@ -154,7 +148,8 @@ TEST_F(PrefetchImporterImplTest, MoveFileError) {
TEST_F(PrefetchImporterImplTest, AddPageError) {
base::FilePath path;
base::CreateTemporaryFileInDir(temp_dir_path(), &path);
- ImportArchive(kTestOfflineIDFailedToAdd, path);
+ ImportArchive(kTestOfflineIDFailedToAdd, GURL("http://sample.org"),
+ GURL("https://sample.org/foo"), path);
ASSERT_EQ(1u, dispatcher()->import_results.size());
EXPECT_EQ(kTestOfflineIDFailedToAdd, dispatcher()->import_results[0].first);
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_item_unittest.cc b/chromium/components/offline_pages/core/prefetch/prefetch_item_unittest.cc
index 380f53d4486..af752c14160 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_item_unittest.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_item_unittest.cc
@@ -5,7 +5,6 @@
#include "components/offline_pages/core/prefetch/prefetch_item.h"
#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/offline_pages/core/prefetch/prefetch_types.h"
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_prefs.h b/chromium/components/offline_pages/core/prefetch/prefetch_prefs.h
index 24a167839e2..eb0d2447f30 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_prefs.h
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_prefs.h
@@ -7,7 +7,6 @@
#include <string>
-#include "base/time/time.h"
class PrefService;
class PrefRegistrySimple;
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc b/chromium/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc
index 32b317882fd..8f5c9d8f8c2 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc
@@ -19,16 +19,6 @@ using testing::SaveArg;
namespace offline_pages {
-namespace {
-const char kTestMessage[] = "Testing";
-
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-GURL TestURL() {
- return GURL("http://example.org");
-}
-} // namespace
-
class PrefetchRequestFetcherTest : public PrefetchRequestTestBase {
public:
PrefetchRequestStatus RunFetcherWithNetError(net::Error net_error);
@@ -94,8 +84,8 @@ PrefetchRequestStatus PrefetchRequestFetcherTest::RunFetcher(
base::MockCallback<PrefetchRequestFetcher::FinishedCallback> callback;
std::unique_ptr<PrefetchRequestFetcher> fetcher =
PrefetchRequestFetcher::CreateForPost(
- TestURL(), kTestMessage, /*testing_header_value=*/"", empty_request_,
- shared_url_loader_factory(), callback.Get());
+ GURL("http://example.org"), "Testing", /*testing_header_value=*/"",
+ empty_request_, shared_url_loader_factory(), callback.Get());
PrefetchRequestStatus status;
std::string data;
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_request_test_base.h b/chromium/components/offline_pages/core/prefetch/prefetch_request_test_base.h
index c3b1a509cb0..7b1fc6a91c3 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_request_test_base.h
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_request_test_base.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_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_REQUEST_FETCHER_TEST_BASE_H_
-#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_REQUEST_FETCHER_TEST_BASE_H_
+#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_REQUEST_TEST_BASE_H_
+#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_REQUEST_TEST_BASE_H_
#include "base/memory/ref_counted.h"
#include "base/metrics/field_trial.h"
@@ -63,4 +63,4 @@ class PrefetchRequestTestBase : public testing::Test {
} // namespace offline_pages
-#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_REQUEST_FETCHER_TEST_BASE_H_
+#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_REQUEST_TEST_BASE_H_
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_types.cc b/chromium/components/offline_pages/core/prefetch/prefetch_types.cc
index 934a4571fa1..caf2899babe 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_types.cc
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_types.cc
@@ -197,7 +197,7 @@ bool PrefetchArchiveInfo::empty() const {
return offline_id == 0;
}
-base::Optional<PrefetchItemState> ToPrefetchItemState(int value) {
+absl::optional<PrefetchItemState> ToPrefetchItemState(int value) {
switch (static_cast<PrefetchItemState>(value)) {
case PrefetchItemState::NEW_REQUEST:
case PrefetchItemState::SENT_GENERATE_PAGE_BUNDLE:
@@ -212,10 +212,10 @@ base::Optional<PrefetchItemState> ToPrefetchItemState(int value) {
case PrefetchItemState::ZOMBIE:
return static_cast<PrefetchItemState>(value);
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<PrefetchItemErrorCode> ToPrefetchItemErrorCode(int value) {
+absl::optional<PrefetchItemErrorCode> ToPrefetchItemErrorCode(int value) {
switch (static_cast<PrefetchItemErrorCode>(value)) {
case PrefetchItemErrorCode::SUCCESS:
case PrefetchItemErrorCode::TOO_MANY_NEW_URLS:
@@ -241,7 +241,7 @@ base::Optional<PrefetchItemErrorCode> ToPrefetchItemErrorCode(int value) {
case PrefetchItemErrorCode::SUGGESTION_INVALIDATED:
return static_cast<PrefetchItemErrorCode>(value);
}
- return base::nullopt;
+ return absl::nullopt;
}
std::ostream& operator<<(std::ostream& out,
diff --git a/chromium/components/offline_pages/core/prefetch/prefetch_types.h b/chromium/components/offline_pages/core/prefetch/prefetch_types.h
index e804b0ea74a..40389d25cca 100644
--- a/chromium/components/offline_pages/core/prefetch/prefetch_types.h
+++ b/chromium/components/offline_pages/core/prefetch/prefetch_types.h
@@ -11,9 +11,9 @@
#include "base/callback.h"
#include "base/files/file_path.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/offline_pages/core/client_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace offline_pages {
@@ -150,7 +150,7 @@ enum class PrefetchItemState : int {
kMaxValue = ZOMBIE
};
-base::Optional<PrefetchItemState> ToPrefetchItemState(int value);
+absl::optional<PrefetchItemState> ToPrefetchItemState(int value);
// Error codes used to identify the reason why a prefetch entry has finished
// processing in the pipeline. This values are only meaningful for entries in
@@ -217,7 +217,7 @@ enum class PrefetchItemErrorCode : int {
kMaxValue = SUGGESTION_INVALIDATED
};
-base::Optional<PrefetchItemErrorCode> ToPrefetchItemErrorCode(int value);
+absl::optional<PrefetchItemErrorCode> ToPrefetchItemErrorCode(int value);
// Callback invoked upon completion of a prefetch request.
using PrefetchRequestFinishedCallback =
diff --git a/chromium/components/offline_pages/core/prefetch/server_forbidden_check_request.h b/chromium/components/offline_pages/core/prefetch/server_forbidden_check_request.h
index bb0578313f0..491cca0c3ae 100644
--- a/chromium/components/offline_pages/core/prefetch/server_forbidden_check_request.h
+++ b/chromium/components/offline_pages/core/prefetch/server_forbidden_check_request.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_SERVER_FORBIDDEN_CHECK_REQUEST_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_SERVER_FORBIDDEN_CHECK_REQUEST_H_
-#include <vector>
-
#include "components/offline_pages/core/prefetch/prefetch_network_request_factory.h"
#include "components/offline_pages/core/prefetch/prefetch_service.h"
#include "components/prefs/pref_service.h"
diff --git a/chromium/components/offline_pages/core/prefetch/store/prefetch_store.cc b/chromium/components/offline_pages/core/prefetch/store/prefetch_store.cc
index 0018032146e..36d0c758812 100644
--- a/chromium/components/offline_pages/core/prefetch/store/prefetch_store.cc
+++ b/chromium/components/offline_pages/core/prefetch/store/prefetch_store.cc
@@ -15,6 +15,7 @@
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
#include "components/offline_pages/core/offline_store_types.h"
#include "components/offline_pages/core/prefetch/store/prefetch_store_schema.h"
#include "sql/database.h"
diff --git a/chromium/components/offline_pages/core/prefetch/store/prefetch_store.h b/chromium/components/offline_pages/core/prefetch/store/prefetch_store.h
index 5d80e181e4d..653025cbeba 100644
--- a/chromium/components/offline_pages/core/prefetch/store/prefetch_store.h
+++ b/chromium/components/offline_pages/core/prefetch/store/prefetch_store.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_STORE_PREFETCH_STORE_H_
-#include <memory>
-
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_path.h"
@@ -15,7 +13,6 @@
#include "base/sequenced_task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
#include "components/offline_pages/task/sql_store_base.h"
namespace sql {
diff --git a/chromium/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc b/chromium/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc
index 7ab724b6383..3fd64fe6409 100644
--- a/chromium/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc
+++ b/chromium/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc
@@ -102,17 +102,17 @@ int CountPrefetchItemsSync(sql::Database* db) {
// Populates the PrefetchItem with the data from the current row of the passed
// in statement following the natural column ordering.
-base::Optional<PrefetchItem> ReadPrefetchItem(const sql::Statement& statement) {
+absl::optional<PrefetchItem> ReadPrefetchItem(const sql::Statement& statement) {
PrefetchItem item;
DCHECK_EQ(23, statement.ColumnCount());
// Fields are assigned to the item in the order they are stored in the SQL
// store (integer fields first).
item.offline_id = statement.ColumnInt64(0);
- base::Optional<PrefetchItemState> state =
+ absl::optional<PrefetchItemState> state =
ToPrefetchItemState(statement.ColumnInt(1));
if (!state)
- return base::nullopt;
+ return absl::nullopt;
item.state = state.value();
item.generate_bundle_attempts = statement.ColumnInt(2);
item.get_operation_attempts = statement.ColumnInt(3);
@@ -120,10 +120,10 @@ base::Optional<PrefetchItem> ReadPrefetchItem(const sql::Statement& statement) {
item.archive_body_length = statement.ColumnInt64(5);
item.creation_time = store_utils::FromDatabaseTime(statement.ColumnInt64(6));
item.freshness_time = store_utils::FromDatabaseTime(statement.ColumnInt64(7));
- base::Optional<PrefetchItemErrorCode> error_code =
+ absl::optional<PrefetchItemErrorCode> error_code =
ToPrefetchItemErrorCode(statement.ColumnInt(8));
if (!error_code)
- return base::nullopt;
+ return absl::nullopt;
item.error_code = error_code.value();
item.guid = statement.ColumnString(9);
item.client_id.name_space = statement.ColumnString(10);
@@ -143,7 +143,7 @@ base::Optional<PrefetchItem> ReadPrefetchItem(const sql::Statement& statement) {
return item;
}
-base::Optional<PrefetchItem> GetPrefetchItemSync(int64_t offline_id,
+absl::optional<PrefetchItem> GetPrefetchItemSync(int64_t offline_id,
sql::Database* db) {
static const std::string kSql = base::StringPrintf(
"SELECT %s FROM prefetch_items WHERE offline_id = ?", kSqlAllColumnNames);
@@ -152,7 +152,7 @@ base::Optional<PrefetchItem> GetPrefetchItemSync(int64_t offline_id,
statement.BindInt64(0, offline_id);
if (!statement.Step())
- return base::nullopt;
+ return absl::nullopt;
return ReadPrefetchItem(statement);
}
@@ -164,7 +164,7 @@ std::set<PrefetchItem> GetAllItemsSync(sql::Database* db) {
base::StringPrintf("SELECT %s FROM prefetch_items", kSqlAllColumnNames);
sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql.c_str()));
while (statement.Step()) {
- base::Optional<PrefetchItem> item = ReadPrefetchItem(statement);
+ absl::optional<PrefetchItem> item = ReadPrefetchItem(statement);
if (item)
items.insert(std::move(item).value());
}
@@ -271,13 +271,13 @@ std::unique_ptr<PrefetchItem> PrefetchStoreTestUtil::GetPrefetchItem(
store_->Execute(
base::BindOnce(&GetPrefetchItemSync, offline_id),
base::BindOnce(
- base::BindLambdaForTesting([&](base::Optional<PrefetchItem> result) {
+ base::BindLambdaForTesting([&](absl::optional<PrefetchItem> result) {
if (result) {
item = std::make_unique<PrefetchItem>(std::move(result).value());
}
run_loop.Quit();
})),
- base::Optional<PrefetchItem>());
+ absl::optional<PrefetchItem>());
run_loop.Run();
return item;
}
diff --git a/chromium/components/offline_pages/core/prefetch/store/prefetch_store_test_util.h b/chromium/components/offline_pages/core/prefetch/store/prefetch_store_test_util.h
index 7f5926022a1..c3a7f1455ee 100644
--- a/chromium/components/offline_pages/core/prefetch/store/prefetch_store_test_util.h
+++ b/chromium/components/offline_pages/core/prefetch/store/prefetch_store_test_util.h
@@ -10,7 +10,6 @@
#include <string>
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/test/simple_test_clock.h"
diff --git a/chromium/components/offline_pages/core/prefetch/tasks/get_visuals_info_task.h b/chromium/components/offline_pages/core/prefetch/tasks/get_visuals_info_task.h
index 09fbdbbb866..13412484aa0 100644
--- a/chromium/components/offline_pages/core/prefetch/tasks/get_visuals_info_task.h
+++ b/chromium/components/offline_pages/core/prefetch/tasks/get_visuals_info_task.h
@@ -5,10 +5,6 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TASKS_GET_VISUALS_INFO_TASK_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TASKS_GET_VISUALS_INFO_TASK_H_
-#include <memory>
-#include <string>
-#include <vector>
-
#include "base/memory/weak_ptr.h"
#include "components/offline_pages/task/task.h"
#include "url/gurl.h"
diff --git a/chromium/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.cc b/chromium/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.cc
index ada0708bf02..775b9a44dd9 100644
--- a/chromium/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.cc
+++ b/chromium/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.cc
@@ -114,7 +114,7 @@ void CountEntriesInEachState(sql::Database* db) {
"SELECT state, COUNT (*) FROM prefetch_items GROUP BY state";
sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
while (statement.Step()) {
- base::Optional<PrefetchItemState> state =
+ absl::optional<PrefetchItemState> state =
ToPrefetchItemState(statement.ColumnInt(0));
if (!state)
continue;
diff --git a/chromium/components/offline_pages/core/prefetch/tasks/remove_url_task.h b/chromium/components/offline_pages/core/prefetch/tasks/remove_url_task.h
index e5f4c22dad0..d1f3f1deb5b 100644
--- a/chromium/components/offline_pages/core/prefetch/tasks/remove_url_task.h
+++ b/chromium/components/offline_pages/core/prefetch/tasks/remove_url_task.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TASKS_REMOVE_URL_TASK_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TASKS_REMOVE_URL_TASK_H_
-#include <string>
#include <vector>
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/offline_pages/core/prefetch/tasks/sent_get_operation_cleanup_task_unittest.cc b/chromium/components/offline_pages/core/prefetch/tasks/sent_get_operation_cleanup_task_unittest.cc
index cc3515dc12f..9bcb058ea5c 100644
--- a/chromium/components/offline_pages/core/prefetch/tasks/sent_get_operation_cleanup_task_unittest.cc
+++ b/chromium/components/offline_pages/core/prefetch/tasks/sent_get_operation_cleanup_task_unittest.cc
@@ -36,7 +36,7 @@ class TestingPrefetchNetworkRequestFactory
const std::string& gcm_registration_id,
PrefetchRequestFinishedCallback callback) override {}
std::unique_ptr<std::set<std::string>> GetAllUrlsRequested() const override {
- return std::unique_ptr<std::set<std::string>>();
+ return nullptr;
}
void MakeGetOperationRequest(
const std::string& operation_name,
diff --git a/chromium/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.h b/chromium/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.h
index dfded345ace..29c3bb3a5dd 100644
--- a/chromium/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.h
+++ b/chromium/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TASKS_STALE_ENTRY_FINALIZER_TASK_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TASKS_STALE_ENTRY_FINALIZER_TASK_H_
-#include <vector>
-
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/offline_pages/core/prefetch/test_download_service.cc b/chromium/components/offline_pages/core/prefetch/test_download_service.cc
index 5ae7f988191..973611d429d 100644
--- a/chromium/components/offline_pages/core/prefetch/test_download_service.cc
+++ b/chromium/components/offline_pages/core/prefetch/test_download_service.cc
@@ -51,13 +51,13 @@ const download::ServiceConfig& TestDownloadService::GetConfig() {
}
void TestDownloadService::StartDownload(
- const download::DownloadParams& download_params) {
+ download::DownloadParams download_params) {
if (!download_dir_.IsValid())
CHECK(download_dir_.CreateUniqueTempDir());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindRepeating(download_params.callback, download_params.guid,
- download::DownloadParams::ACCEPTED));
+ base::BindOnce(std::move(download_params.callback), download_params.guid,
+ download::DownloadParams::ACCEPTED));
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&TestDownloadService::FinishDownload,
base::Unretained(this), download_params.guid));
diff --git a/chromium/components/offline_pages/core/prefetch/test_download_service.h b/chromium/components/offline_pages/core/prefetch/test_download_service.h
index d5ef24dcfad..2e98e52c52a 100644
--- a/chromium/components/offline_pages/core/prefetch/test_download_service.h
+++ b/chromium/components/offline_pages/core/prefetch/test_download_service.h
@@ -9,11 +9,11 @@
#include <string>
#include "base/files/scoped_temp_dir.h"
-#include "base/optional.h"
#include "components/download/public/background_service/client.h"
#include "components/download/public/background_service/download_params.h"
#include "components/download/public/background_service/download_service.h"
#include "components/offline_pages/core/prefetch/test_download_client.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace offline_pages {
@@ -29,7 +29,7 @@ class TestDownloadService : public download::DownloadService {
download::TaskFinishedCallback callback) override;
bool OnStopScheduledTask(download::DownloadTaskType task_type) override;
DownloadService::ServiceStatus GetStatus() override;
- void StartDownload(const download::DownloadParams& download_params) override;
+ void StartDownload(download::DownloadParams download_params) override;
void PauseDownload(const std::string& guid) override;
void ResumeDownload(const std::string& guid) override;
void CancelDownload(const std::string& guid) override;
diff --git a/chromium/components/offline_pages/core/prefetch/test_prefetch_network_request_factory.h b/chromium/components/offline_pages/core/prefetch/test_prefetch_network_request_factory.h
index 5d5a7ff5963..f1e68ced86c 100644
--- a/chromium/components/offline_pages/core/prefetch/test_prefetch_network_request_factory.h
+++ b/chromium/components/offline_pages/core/prefetch/test_prefetch_network_request_factory.h
@@ -5,10 +5,6 @@
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TEST_PREFETCH_NETWORK_REQUEST_FACTORY_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TEST_PREFETCH_NETWORK_REQUEST_FACTORY_H_
-#include <memory>
-#include <string>
-#include <vector>
-
#include "base/memory/ref_counted.h"
#include "components/offline_pages/core/prefetch/prefetch_network_request_factory_impl.h"
#include "components/offline_pages/core/prefetch/prefetch_types.h"
diff --git a/chromium/components/offline_pages/core/request_header/offline_page_header.cc b/chromium/components/offline_pages/core/request_header/offline_page_header.cc
index cfe925eb41c..ae5f120e261 100644
--- a/chromium/components/offline_pages/core/request_header/offline_page_header.cc
+++ b/chromium/components/offline_pages/core/request_header/offline_page_header.cc
@@ -37,16 +37,17 @@ bool ParseOfflineHeaderValue(const std::string& header_value,
if (header_value.empty())
return false;
+ // TODO(dcheng): Use net::HttpUtil::NameValuePairsIterator instead?
bool token_found = false;
base::StringTokenizer tokenizer(header_value, ", ");
while (tokenizer.GetNext()) {
token_found = true;
- std::string pair = tokenizer.token();
+ base::StringPiece pair = tokenizer.token_piece();
std::size_t pos = pair.find('=');
if (pos == std::string::npos)
return false;
std::string key = base::ToLowerASCII(pair.substr(0, pos));
- std::string value = pair.substr(pos + 1);
+ base::StringPiece value = pair.substr(pos + 1);
std::string lower_value = base::ToLowerASCII(value);
if (key == kOfflinePageHeaderPersistKey) {
if (lower_value == "1")
@@ -77,7 +78,7 @@ bool ParseOfflineHeaderValue(const std::string& header_value,
else
return false;
} else if (key == kOfflinePageHeaderIDKey) {
- *id = value;
+ *id = std::string(value);
} else if (key == kOfflinePageHeaderIntentUrlKey) {
std::string decoded_url;
if (!base::Base64Decode(value, &decoded_url))
diff --git a/chromium/components/offline_pages/task/sql_store_base.h b/chromium/components/offline_pages/task/sql_store_base.h
index 32732ff5e32..6913c4a2cd5 100644
--- a/chromium/components/offline_pages/task/sql_store_base.h
+++ b/chromium/components/offline_pages/task/sql_store_base.h
@@ -16,7 +16,6 @@
#include "base/memory/weak_ptr.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
#include "sql/database.h"
namespace offline_pages {
diff --git a/chromium/components/omnibox/browser/BUILD.gn b/chromium/components/omnibox/browser/BUILD.gn
index d05f178f6be..43035485af8 100644
--- a/chromium/components/omnibox/browser/BUILD.gn
+++ b/chromium/components/omnibox/browser/BUILD.gn
@@ -52,17 +52,17 @@ aggregate_vector_icons("omnibox_vector_icons") {
"google_sites.icon",
"google_super_g.icon",
"http.icon",
- "https_valid.icon",
"https_valid_in_chip.icon",
"install_desktop.icon",
"install_download.icon",
"keyword_search.icon",
- "not_secure_warning.icon",
"offline_pin.icon",
"page.icon",
"pedal.icon",
"plus.icon",
"product.icon",
+ "send.icon",
+ "share.icon",
"star.icon",
"star_active.icon",
"switch.icon",
@@ -83,6 +83,15 @@ static_library("vector_icons") {
static_library("browser") {
sources = [
+ "actions/omnibox_action.cc",
+ "actions/omnibox_action.h",
+ "actions/omnibox_pedal.cc",
+ "actions/omnibox_pedal.h",
+ "actions/omnibox_pedal_concepts.h",
+ "actions/omnibox_pedal_implementations.cc",
+ "actions/omnibox_pedal_implementations.h",
+ "actions/omnibox_pedal_provider.cc",
+ "actions/omnibox_pedal_provider.h",
"answers_cache.cc",
"answers_cache.h",
"autocomplete_classifier.cc",
@@ -161,13 +170,6 @@ static_library("browser") {
"omnibox_metrics_provider.cc",
"omnibox_metrics_provider.h",
"omnibox_navigation_observer.h",
- "omnibox_pedal.cc",
- "omnibox_pedal.h",
- "omnibox_pedal_concepts.h",
- "omnibox_pedal_implementations.cc",
- "omnibox_pedal_implementations.h",
- "omnibox_pedal_provider.cc",
- "omnibox_pedal_provider.h",
"omnibox_popup_model.cc",
"omnibox_popup_model.h",
"omnibox_popup_view.h",
@@ -243,6 +245,7 @@ static_library("browser") {
"//components/keyed_service/core",
"//components/metrics",
"//components/navigation_metrics",
+ "//components/ntp_tiles",
"//components/open_from_clipboard",
"//components/pref_registry",
"//components/prefs",
@@ -497,6 +500,9 @@ bundle_data("unit_tests_bundle_data") {
source_set("unit_tests") {
testonly = true
sources = [
+ "actions/omnibox_pedal_implementations_unittest.cc",
+ "actions/omnibox_pedal_provider_unittest.cc",
+ "actions/omnibox_pedal_unittest.cc",
"answers_cache_unittest.cc",
"autocomplete_input_unittest.cc",
"autocomplete_match_type_unittest.cc",
@@ -523,9 +529,6 @@ source_set("unit_tests") {
"omnibox_controller_unittest.cc",
"omnibox_edit_model_unittest.cc",
"omnibox_field_trial_unittest.cc",
- "omnibox_pedal_implementations_unittest.cc",
- "omnibox_pedal_provider_unittest.cc",
- "omnibox_pedal_unittest.cc",
"omnibox_popup_model_unittest.cc",
"omnibox_prefs_unittest.cc",
"omnibox_view_unittest.cc",
diff --git a/chromium/components/omnibox_strings.grdp b/chromium/components/omnibox_strings.grdp
index 6bcbcc6215f..260d81bfdc8 100644
--- a/chromium/components/omnibox_strings.grdp
+++ b/chromium/components/omnibox_strings.grdp
@@ -65,9 +65,6 @@
<message name="IDS_OMNIBOX_TAB_SUGGEST_HINT" desc="The button text contents to say that this suggestion will switch to another tab.">
Switch to this tab
</message>
- <message name="IDS_OMNIBOX_TAB_SUGGEST_SHORT_HINT" desc="A shortened, one word version of button text to say that this suggestion will switch to another tab.">
- Switch
- </message>
<message name="IDS_OMNIBOX_FILE" desc="Text shown in the omnibox to indicate a user is viewing a file.">
File
</message>
@@ -139,16 +136,16 @@
Manage payment methods button, press Enter to manage your payments and credit card info in Chrome settings
</message>
- <message name="IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_HINT" desc="The button text contents to suggest pedal action, launch incognito.">
+ <message name="IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_HINT" desc="The button text contents to suggest pedal action, launch Incognito.">
Open Incognito window
</message>
- <message name="IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUGGESTION_CONTENTS" desc="The suggestion content text to suggest pedal action, launch incognito.">
+ <message name="IDS_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUGGESTION_CONTENTS" desc="The suggestion content text to suggest pedal action, launch Incognito.">
Open a new Incognito window to browse privately
</message>
- <message name="IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUFFIX" desc="Suffix for spoken suggestion description with launch incognito pedal action to explain keystroke used to launch incognito.">
+ <message name="IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO_SUFFIX" desc="Suffix for spoken suggestion description with launch Incognito pedal action to explain keystroke used to launch Incognito.">
<ph name="LAUNCH_INCOGNITO_FOCUSED_FRIENDLY_MATCH_TEXT">$1<ex>The Chromium Projects http://www.chromium.org bookmark</ex></ph>, press Tab then Enter to open a new Incognito window to browse privately
</message>
- <message name="IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO" desc="Announcement when launch incognito pedal button is focused.">
+ <message name="IDS_ACC_OMNIBOX_PEDAL_LAUNCH_INCOGNITO" desc="Announcement when launch Incognito pedal button is focused.">
Open Incognito Window button, press Enter to open a new Incognito window to browse privately
</message>
diff --git a/chromium/components/on_load_script_injector/browser/on_load_script_injector_host.h b/chromium/components/on_load_script_injector/browser/on_load_script_injector_host.h
index 5e36a806f99..bbe65a7d779 100644
--- a/chromium/components/on_load_script_injector/browser/on_load_script_injector_host.h
+++ b/chromium/components/on_load_script_injector/browser/on_load_script_injector_host.h
@@ -6,7 +6,6 @@
#define COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_BROWSER_ON_LOAD_SCRIPT_INJECTOR_HOST_H_
#include <map>
-#include <string>
#include <vector>
#include "base/memory/read_only_shared_memory_region.h"
@@ -84,4 +83,4 @@ class ON_LOAD_SCRIPT_INJECTOR_EXPORT OnLoadScriptInjectorHost {
} // namespace on_load_script_injector
-#endif // COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_BROWSER_ON_LOAD_SCRIPT_INJECTOR_HOST_
+#endif // COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_BROWSER_ON_LOAD_SCRIPT_INJECTOR_HOST_H_
diff --git a/chromium/components/on_load_script_injector/renderer/on_load_script_injector.h b/chromium/components/on_load_script_injector/renderer/on_load_script_injector.h
index 99411fe77de..bccf3fb16e9 100644
--- a/chromium/components/on_load_script_injector/renderer/on_load_script_injector.h
+++ b/chromium/components/on_load_script_injector/renderer/on_load_script_injector.h
@@ -49,4 +49,4 @@ class ON_LOAD_SCRIPT_INJECTOR_EXPORT OnLoadScriptInjector
} // namespace on_load_script_injector
-#endif // COMPONENTS_CAST_API_BINDINGS_API_BINDINGS_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
+#endif // COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
diff --git a/chromium/components/onc/onc_pref_names.h b/chromium/components/onc/onc_pref_names.h
index 372e9c8df15..cd73f53a29c 100644
--- a/chromium/components/onc/onc_pref_names.h
+++ b/chromium/components/onc/onc_pref_names.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_ONC_PREF_NAMES_H_
-#define COMPONENTS_ONC_PREF_NAMES_H_
+#ifndef COMPONENTS_ONC_ONC_PREF_NAMES_H_
+#define COMPONENTS_ONC_ONC_PREF_NAMES_H_
#include "components/onc/onc_export.h"
@@ -29,4 +29,4 @@ ONC_EXPORT void RegisterProfilePrefs(
} // namespace onc
-#endif // COMPONENTS_ONC_PREF_NAMES_H_
+#endif // COMPONENTS_ONC_ONC_PREF_NAMES_H_
diff --git a/chromium/components/open_from_clipboard/clipboard_recent_content.h b/chromium/components/open_from_clipboard/clipboard_recent_content.h
index 486d350380d..695b78348bc 100644
--- a/chromium/components/open_from_clipboard/clipboard_recent_content.h
+++ b/chromium/components/open_from_clipboard/clipboard_recent_content.h
@@ -35,12 +35,12 @@ class ClipboardRecentContent {
// Returns clipboard content as URL, if it has a compatible type,
// is recent enough, has not been suppressed and will not trigger a system
// notification that the clipboard has been accessed.
- virtual base::Optional<GURL> GetRecentURLFromClipboard() = 0;
+ virtual absl::optional<GURL> GetRecentURLFromClipboard() = 0;
// Returns clipboard content as text, if it has a compatible type,
// is recent enough, has not been suppressed and will not trigger a system
// notification that the clipboard has been accessed.
- virtual base::Optional<std::u16string> GetRecentTextFromClipboard() = 0;
+ virtual absl::optional<std::u16string> GetRecentTextFromClipboard() = 0;
// Return if system's clipboard contains an image that will not trigger a
// system notification that the clipboard has been accessed.
@@ -52,11 +52,11 @@ class ClipboardRecentContent {
*/
using HasDataCallback =
base::OnceCallback<void(std::set<ClipboardContentType>)>;
- using GetRecentURLCallback = base::OnceCallback<void(base::Optional<GURL>)>;
+ using GetRecentURLCallback = base::OnceCallback<void(absl::optional<GURL>)>;
using GetRecentTextCallback =
- base::OnceCallback<void(base::Optional<std::u16string>)>;
+ base::OnceCallback<void(absl::optional<std::u16string>)>;
using GetRecentImageCallback =
- base::OnceCallback<void(base::Optional<gfx::Image>)>;
+ base::OnceCallback<void(absl::optional<gfx::Image>)>;
// Returns whether the clipboard contains a URL to |HasDataCallback| if it
// is recent enough and has not been suppressed.
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 e394181f54b..deaa34e0d43 100644
--- a/chromium/components/open_from_clipboard/clipboard_recent_content_generic.cc
+++ b/chromium/components/open_from_clipboard/clipboard_recent_content_generic.cc
@@ -31,7 +31,7 @@ void OnGetRecentImageFromClipboard(
ClipboardRecentContent::GetRecentImageCallback callback,
const SkBitmap& sk_bitmap) {
if (sk_bitmap.empty()) {
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
return;
}
@@ -61,10 +61,10 @@ bool HasRecentTextFromClipboard() {
ClipboardRecentContentGeneric::ClipboardRecentContentGeneric() = default;
ClipboardRecentContentGeneric::~ClipboardRecentContentGeneric() = default;
-base::Optional<GURL>
+absl::optional<GURL>
ClipboardRecentContentGeneric::GetRecentURLFromClipboard() {
if (GetClipboardContentAge() > MaximumAgeOfClipboard())
- return base::nullopt;
+ return absl::nullopt;
// Get and clean up the clipboard before processing.
std::string gurl_string;
@@ -87,7 +87,7 @@ ClipboardRecentContentGeneric::GetRecentURLFromClipboard() {
// "http://example.com extra words" into "http://example.com%20extra%20words",
// which is not likely to be a useful or intended destination.)
if (gurl_string.find_first_of(base::kWhitespaceASCII) != std::string::npos)
- return base::nullopt;
+ return absl::nullopt;
if (!gurl_string.empty()) {
url = GURL(gurl_string);
} else {
@@ -100,20 +100,20 @@ ClipboardRecentContentGeneric::GetRecentURLFromClipboard() {
&gurl_string16);
if (gurl_string16.find_first_of(base::kWhitespaceUTF16) !=
std::string::npos)
- return base::nullopt;
+ return absl::nullopt;
if (!gurl_string16.empty())
url = GURL(gurl_string16);
}
if (!url.is_valid() || !IsAppropriateSuggestion(url)) {
- return base::nullopt;
+ return absl::nullopt;
}
return url;
}
-base::Optional<std::u16string>
+absl::optional<std::u16string>
ClipboardRecentContentGeneric::GetRecentTextFromClipboard() {
if (GetClipboardContentAge() > MaximumAgeOfClipboard())
- return base::nullopt;
+ return absl::nullopt;
std::u16string text_from_clipboard;
ui::DataTransferEndpoint data_dst = ui::DataTransferEndpoint(
@@ -123,7 +123,7 @@ ClipboardRecentContentGeneric::GetRecentTextFromClipboard() {
base::TrimWhitespace(text_from_clipboard, base::TrimPositions::TRIM_ALL,
&text_from_clipboard);
if (text_from_clipboard.empty()) {
- return base::nullopt;
+ return absl::nullopt;
}
return text_from_clipboard;
diff --git a/chromium/components/open_from_clipboard/clipboard_recent_content_generic.h b/chromium/components/open_from_clipboard/clipboard_recent_content_generic.h
index d30dbc7b36d..df9d4a332f0 100644
--- a/chromium/components/open_from_clipboard/clipboard_recent_content_generic.h
+++ b/chromium/components/open_from_clipboard/clipboard_recent_content_generic.h
@@ -24,8 +24,8 @@ class ClipboardRecentContentGeneric : public ClipboardRecentContent {
~ClipboardRecentContentGeneric() override;
// ClipboardRecentContent implementation.
- base::Optional<GURL> GetRecentURLFromClipboard() override;
- base::Optional<std::u16string> GetRecentTextFromClipboard() override;
+ absl::optional<GURL> GetRecentURLFromClipboard() override;
+ absl::optional<std::u16string> GetRecentTextFromClipboard() override;
void GetRecentImageFromClipboard(GetRecentImageCallback callback) override;
bool HasRecentImageFromClipboard() override;
void HasRecentContentFromClipboard(std::set<ClipboardContentType> types,
diff --git a/chromium/components/open_from_clipboard/clipboard_recent_content_ios.h b/chromium/components/open_from_clipboard/clipboard_recent_content_ios.h
index 18f902ba1ba..d7734ffbea8 100644
--- a/chromium/components/open_from_clipboard/clipboard_recent_content_ios.h
+++ b/chromium/components/open_from_clipboard/clipboard_recent_content_ios.h
@@ -40,8 +40,8 @@ class ClipboardRecentContentIOS : public ClipboardRecentContent {
~ClipboardRecentContentIOS() override;
// ClipboardRecentContent implementation.
- base::Optional<GURL> GetRecentURLFromClipboard() override;
- base::Optional<std::u16string> GetRecentTextFromClipboard() override;
+ absl::optional<GURL> GetRecentURLFromClipboard() override;
+ absl::optional<std::u16string> GetRecentTextFromClipboard() override;
void GetRecentImageFromClipboard(GetRecentImageCallback callback) override;
bool HasRecentImageFromClipboard() override;
void HasRecentContentFromClipboard(std::set<ClipboardContentType> types,
@@ -53,7 +53,7 @@ class ClipboardRecentContentIOS : public ClipboardRecentContent {
void ClearClipboardContent() override;
private:
- base::Optional<gfx::Image> GetRecentImageFromClipboardInternal();
+ absl::optional<gfx::Image> GetRecentImageFromClipboardInternal();
void OnGetRecentImageFromClipboard(GetRecentImageCallback callback,
const SkBitmap& sk_bitmap);
diff --git a/chromium/components/open_from_clipboard/clipboard_recent_content_ios.mm b/chromium/components/open_from_clipboard/clipboard_recent_content_ios.mm
index 9943c11c05f..7de70fd5df5 100644
--- a/chromium/components/open_from_clipboard/clipboard_recent_content_ios.mm
+++ b/chromium/components/open_from_clipboard/clipboard_recent_content_ios.mm
@@ -97,21 +97,21 @@ ClipboardRecentContentIOS::ClipboardRecentContentIOS(
implementation_ = implementation;
}
-base::Optional<GURL> ClipboardRecentContentIOS::GetRecentURLFromClipboard() {
+absl::optional<GURL> ClipboardRecentContentIOS::GetRecentURLFromClipboard() {
NSURL* url_from_pasteboard = [implementation_ recentURLFromClipboard];
GURL converted_url = net::GURLWithNSURL(url_from_pasteboard);
if (!converted_url.is_valid()) {
- return base::nullopt;
+ return absl::nullopt;
}
return converted_url;
}
-base::Optional<std::u16string>
+absl::optional<std::u16string>
ClipboardRecentContentIOS::GetRecentTextFromClipboard() {
NSString* text_from_pasteboard = [implementation_ recentTextFromClipboard];
if (!text_from_pasteboard) {
- return base::nullopt;
+ return absl::nullopt;
}
return base::SysNSStringToUTF16(text_from_pasteboard);
@@ -163,7 +163,7 @@ void ClipboardRecentContentIOS::GetRecentURLFromClipboard(
GURL converted_url = net::GURLWithNSURL(url);
if (!converted_url.is_valid()) {
task_runner->PostTask(FROM_HERE, base::BindOnce(^{
- std::move(callback_for_block).Run(base::nullopt);
+ std::move(callback_for_block).Run(absl::nullopt);
}));
return;
}
@@ -185,7 +185,7 @@ void ClipboardRecentContentIOS::GetRecentTextFromClipboard(
[implementation_ recentTextFromClipboardAsync:^(NSString* text) {
if (!text) {
task_runner->PostTask(FROM_HERE, base::BindOnce(^{
- std::move(callback_for_block).Run(base::nullopt);
+ std::move(callback_for_block).Run(absl::nullopt);
}));
return;
}
@@ -208,7 +208,7 @@ void ClipboardRecentContentIOS::GetRecentImageFromClipboard(
[implementation_ recentImageFromClipboardAsync:^(UIImage* image) {
if (!image) {
task_runner->PostTask(FROM_HERE, base::BindOnce(^{
- std::move(callback_for_block).Run(base::nullopt);
+ std::move(callback_for_block).Run(absl::nullopt);
}));
return;
}
@@ -235,11 +235,11 @@ void ClipboardRecentContentIOS::ClearClipboardContent() {
return;
}
-base::Optional<gfx::Image>
+absl::optional<gfx::Image>
ClipboardRecentContentIOS::GetRecentImageFromClipboardInternal() {
UIImage* image_from_pasteboard = [implementation_ recentImageFromClipboard];
if (!image_from_pasteboard) {
- return base::nullopt;
+ return absl::nullopt;
}
return gfx::Image(image_from_pasteboard);
diff --git a/chromium/components/open_from_clipboard/clipboard_recent_content_ios_unittest.mm b/chromium/components/open_from_clipboard/clipboard_recent_content_ios_unittest.mm
index 4219bb8daf3..08af85371d1 100644
--- a/chromium/components/open_from_clipboard/clipboard_recent_content_ios_unittest.mm
+++ b/chromium/components/open_from_clipboard/clipboard_recent_content_ios_unittest.mm
@@ -172,9 +172,9 @@ class ClipboardRecentContentIOSTest : public ::testing::Test {
VerifyClipboardTypeExists(ClipboardContentType::URL, true);
__block BOOL callback_called = NO;
- __block base::Optional<GURL> optional_gurl;
+ __block absl::optional<GURL> optional_gurl;
clipboard_content_->GetRecentURLFromClipboard(
- base::BindOnce(^(base::Optional<GURL> copied_url) {
+ base::BindOnce(^(absl::optional<GURL> copied_url) {
optional_gurl = copied_url;
callback_called = YES;
}));
@@ -197,9 +197,9 @@ class ClipboardRecentContentIOSTest : public ::testing::Test {
}
__block BOOL callback_called = NO;
- __block base::Optional<GURL> optional_gurl;
+ __block absl::optional<GURL> optional_gurl;
clipboard_content_->GetRecentURLFromClipboard(
- base::BindOnce(^(base::Optional<GURL> copied_url) {
+ base::BindOnce(^(absl::optional<GURL> copied_url) {
optional_gurl = copied_url;
callback_called = YES;
}));
diff --git a/chromium/components/open_from_clipboard/fake_clipboard_recent_content.cc b/chromium/components/open_from_clipboard/fake_clipboard_recent_content.cc
index d24018954af..f19326ab782 100644
--- a/chromium/components/open_from_clipboard/fake_clipboard_recent_content.cc
+++ b/chromium/components/open_from_clipboard/fake_clipboard_recent_content.cc
@@ -9,17 +9,17 @@ FakeClipboardRecentContent::FakeClipboardRecentContent()
FakeClipboardRecentContent::~FakeClipboardRecentContent() {}
-base::Optional<GURL> FakeClipboardRecentContent::GetRecentURLFromClipboard() {
+absl::optional<GURL> FakeClipboardRecentContent::GetRecentURLFromClipboard() {
if (suppress_content_)
- return base::nullopt;
+ return absl::nullopt;
return clipboard_url_content_;
}
-base::Optional<std::u16string>
+absl::optional<std::u16string>
FakeClipboardRecentContent::GetRecentTextFromClipboard() {
if (suppress_content_)
- return base::nullopt;
+ return absl::nullopt;
return clipboard_text_content_;
}
@@ -27,7 +27,7 @@ FakeClipboardRecentContent::GetRecentTextFromClipboard() {
void FakeClipboardRecentContent::GetRecentImageFromClipboard(
GetRecentImageCallback callback) {
if (suppress_content_) {
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
return;
}
@@ -85,9 +85,9 @@ void FakeClipboardRecentContent::SuppressClipboardContent() {
}
void FakeClipboardRecentContent::ClearClipboardContent() {
- clipboard_url_content_ = base::nullopt;
- clipboard_text_content_ = base::nullopt;
- clipboard_image_content_ = base::nullopt;
+ clipboard_url_content_ = absl::nullopt;
+ clipboard_text_content_ = absl::nullopt;
+ clipboard_image_content_ = absl::nullopt;
content_age_ = base::TimeDelta::Max();
suppress_content_ = false;
}
@@ -96,17 +96,17 @@ void FakeClipboardRecentContent::SetClipboardURL(const GURL& url,
base::TimeDelta content_age) {
DCHECK(url.is_valid());
clipboard_url_content_ = url;
- clipboard_text_content_ = base::nullopt;
- clipboard_image_content_ = base::nullopt;
+ clipboard_text_content_ = absl::nullopt;
+ clipboard_image_content_ = absl::nullopt;
content_age_ = content_age;
suppress_content_ = false;
}
void FakeClipboardRecentContent::SetClipboardText(const std::u16string& text,
base::TimeDelta content_age) {
- clipboard_url_content_ = base::nullopt;
+ clipboard_url_content_ = absl::nullopt;
clipboard_text_content_ = text;
- clipboard_image_content_ = base::nullopt;
+ clipboard_image_content_ = absl::nullopt;
content_age_ = content_age;
suppress_content_ = false;
}
@@ -114,8 +114,8 @@ void FakeClipboardRecentContent::SetClipboardText(const std::u16string& text,
void FakeClipboardRecentContent::SetClipboardImage(
const gfx::Image& image,
base::TimeDelta content_age) {
- clipboard_url_content_ = base::nullopt;
- clipboard_text_content_ = base::nullopt;
+ clipboard_url_content_ = absl::nullopt;
+ clipboard_text_content_ = absl::nullopt;
clipboard_image_content_ = image;
content_age_ = content_age;
suppress_content_ = false;
diff --git a/chromium/components/open_from_clipboard/fake_clipboard_recent_content.h b/chromium/components/open_from_clipboard/fake_clipboard_recent_content.h
index 7273be2e610..c5490f64370 100644
--- a/chromium/components/open_from_clipboard/fake_clipboard_recent_content.h
+++ b/chromium/components/open_from_clipboard/fake_clipboard_recent_content.h
@@ -19,8 +19,8 @@ class FakeClipboardRecentContent : public ClipboardRecentContent {
~FakeClipboardRecentContent() override;
// ClipboardRecentContent implementation.
- base::Optional<GURL> GetRecentURLFromClipboard() override;
- base::Optional<std::u16string> GetRecentTextFromClipboard() override;
+ absl::optional<GURL> GetRecentURLFromClipboard() override;
+ absl::optional<std::u16string> GetRecentTextFromClipboard() override;
void GetRecentImageFromClipboard(GetRecentImageCallback callback) override;
bool HasRecentImageFromClipboard() override;
void HasRecentContentFromClipboard(std::set<ClipboardContentType> types,
@@ -40,9 +40,9 @@ class FakeClipboardRecentContent : public ClipboardRecentContent {
void SetClipboardImage(const gfx::Image& image, base::TimeDelta content_age);
private:
- base::Optional<GURL> clipboard_url_content_;
- base::Optional<std::u16string> clipboard_text_content_;
- base::Optional<gfx::Image> clipboard_image_content_;
+ absl::optional<GURL> clipboard_url_content_;
+ absl::optional<std::u16string> clipboard_text_content_;
+ absl::optional<gfx::Image> clipboard_image_content_;
base::TimeDelta content_age_;
bool suppress_content_;
diff --git a/chromium/components/openscreen_platform/BUILD.gn b/chromium/components/openscreen_platform/BUILD.gn
index 928f8e962cc..c57f5b54792 100644
--- a/chromium/components/openscreen_platform/BUILD.gn
+++ b/chromium/components/openscreen_platform/BUILD.gn
@@ -26,7 +26,6 @@ source_set("openscreen_platform") {
# //net-based implementation of UdpSocket.
# Incompatible with ":openscreen_platform_network_service".
source_set("openscreen_platform_net") {
- testonly = true
sources = [
"net_udp_socket.cc",
"net_udp_socket.h",
diff --git a/chromium/components/openscreen_platform/net_udp_socket.h b/chromium/components/openscreen_platform/net_udp_socket.h
index d7f631901f9..ad7703d38f3 100644
--- a/chromium/components/openscreen_platform/net_udp_socket.h
+++ b/chromium/components/openscreen_platform/net_udp_socket.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_OPENSCREEN_PLATFORM_NET_UDP_SOCKET_H_
#define COMPONENTS_OPENSCREEN_PLATFORM_NET_UDP_SOCKET_H_
-#include <memory>
-
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/socket/udp_socket.h"
diff --git a/chromium/components/openscreen_platform/network_util.h b/chromium/components/openscreen_platform/network_util.h
index a236af23b45..c59ead1bba4 100644
--- a/chromium/components/openscreen_platform/network_util.h
+++ b/chromium/components/openscreen_platform/network_util.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_OPENSCREEN_PLATFORM_NETWORK_UTIL_H_
#define COMPONENTS_OPENSCREEN_PLATFORM_NETWORK_UTIL_H_
-#include <memory>
-
#include "net/base/address_family.h"
#include "third_party/openscreen/src/platform/base/ip_address.h"
diff --git a/chromium/components/openscreen_platform/tls_connection_factory.cc b/chromium/components/openscreen_platform/tls_connection_factory.cc
index 01424aa304f..c9d390fbbe2 100644
--- a/chromium/components/openscreen_platform/tls_connection_factory.cc
+++ b/chromium/components/openscreen_platform/tls_connection_factory.cc
@@ -89,7 +89,7 @@ void TlsConnectionFactory::Connect(const IPEndpoint& remote_address,
request.tcp_socket.BindNewPipeAndPassReceiver();
network_context->CreateTCPConnectedSocket(
- base::nullopt /* local_addr */, address_list,
+ absl::nullopt /* local_addr */, address_list,
nullptr /* tcp_connected_socket_options */,
net::MutableNetworkTrafficAnnotationTag(kTrafficAnnotation),
std::move(receiver), mojo::NullRemote(), /* observer */
@@ -146,8 +146,8 @@ TlsConnectionFactory::TlsUpgradeRequest::~TlsUpgradeRequest() = default;
void TlsConnectionFactory::OnTcpConnect(
TcpConnectRequest request,
int32_t net_result,
- const base::Optional<net::IPEndPoint>& local_address,
- const base::Optional<net::IPEndPoint>& remote_address,
+ const absl::optional<net::IPEndPoint>& local_address,
+ const absl::optional<net::IPEndPoint>& remote_address,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream) {
// We only care about net_result, since local_address doesn't matter,
@@ -194,7 +194,7 @@ void TlsConnectionFactory::OnTlsUpgrade(
int32_t net_result,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream,
- const base::Optional<net::SSLInfo>& ssl_info) {
+ const absl::optional<net::SSLInfo>& ssl_info) {
if (net_result != net::OK) {
client_->OnConnectionFailed(this, request.remote_address);
return;
diff --git a/chromium/components/openscreen_platform/tls_connection_factory.h b/chromium/components/openscreen_platform/tls_connection_factory.h
index 4804c63392d..379aec3c06a 100644
--- a/chromium/components/openscreen_platform/tls_connection_factory.h
+++ b/chromium/components/openscreen_platform/tls_connection_factory.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_OPENSCREEN_PLATFORM_TLS_CONNECTION_FACTORY_H_
#define COMPONENTS_OPENSCREEN_PLATFORM_TLS_CONNECTION_FACTORY_H_
-#include <memory>
-
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -91,8 +89,8 @@ class TlsConnectionFactory final : public openscreen::TlsConnectionFactory {
void OnTcpConnect(TcpConnectRequest request,
int32_t net_result,
- const base::Optional<net::IPEndPoint>& local_address,
- const base::Optional<net::IPEndPoint>& remote_address,
+ const absl::optional<net::IPEndPoint>& local_address,
+ const absl::optional<net::IPEndPoint>& remote_address,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream);
@@ -100,7 +98,7 @@ class TlsConnectionFactory final : public openscreen::TlsConnectionFactory {
int32_t net_result,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream,
- const base::Optional<net::SSLInfo>& ssl_info);
+ const absl::optional<net::SSLInfo>& ssl_info);
openscreen::TlsConnectionFactory::Client* client_;
openscreen::TaskRunner* const task_runner_;
diff --git a/chromium/components/openscreen_platform/tls_connection_factory_unittest.cc b/chromium/components/openscreen_platform/tls_connection_factory_unittest.cc
index e92fc7e7e5a..5f479911b25 100644
--- a/chromium/components/openscreen_platform/tls_connection_factory_unittest.cc
+++ b/chromium/components/openscreen_platform/tls_connection_factory_unittest.cc
@@ -65,7 +65,7 @@ class MockTlsConnectionFactoryClient
class FakeNetworkContext : public network::TestNetworkContext {
public:
void CreateTCPConnectedSocket(
- const base::Optional<net::IPEndPoint>& local_addr,
+ const absl::optional<net::IPEndPoint>& local_addr,
const net::AddressList& remote_addr_list,
network::mojom::TCPConnectedSocketOptionsPtr tcp_connected_socket_options,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
@@ -79,7 +79,7 @@ class FakeNetworkContext : public network::TestNetworkContext {
int times_called() { return times_called_; }
void ExecuteCreateCallback(int32_t net_result) {
- std::move(callback_).Run(net_result, base::nullopt, base::nullopt,
+ std::move(callback_).Run(net_result, absl::nullopt, absl::nullopt,
mojo::ScopedDataPipeConsumerHandle{},
mojo::ScopedDataPipeProducerHandle{});
}
diff --git a/chromium/components/openscreen_platform/udp_socket.cc b/chromium/components/openscreen_platform/udp_socket.cc
index ab9aac553a1..9bbda2261ce 100644
--- a/chromium/components/openscreen_platform/udp_socket.cc
+++ b/chromium/components/openscreen_platform/udp_socket.cc
@@ -152,8 +152,8 @@ void UdpSocket::SetDscp(openscreen::UdpSocket::DscpMode state) {}
void UdpSocket::OnReceived(
int32_t net_result,
- const base::Optional<net::IPEndPoint>& source_endpoint,
- base::Optional<base::span<const uint8_t>> data) {
+ const absl::optional<net::IPEndPoint>& source_endpoint,
+ absl::optional<base::span<const uint8_t>> data) {
if (net_result != net::OK) {
client_->OnRead(this, Error::Code::kSocketReadFailure);
} else if (data) {
@@ -170,7 +170,7 @@ void UdpSocket::OnReceived(
}
void UdpSocket::BindCallback(int32_t result,
- const base::Optional<net::IPEndPoint>& address) {
+ const absl::optional<net::IPEndPoint>& address) {
if (result != net::OK) {
client_->OnError(this, Error(Error::Code::kSocketBindFailure,
net::ErrorToString(result)));
diff --git a/chromium/components/openscreen_platform/udp_socket.h b/chromium/components/openscreen_platform/udp_socket.h
index 62b98ee24dd..c0fa1d9c201 100644
--- a/chromium/components/openscreen_platform/udp_socket.h
+++ b/chromium/components/openscreen_platform/udp_socket.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_OPENSCREEN_PLATFORM_UDP_SOCKET_H_
#define COMPONENTS_OPENSCREEN_PLATFORM_UDP_SOCKET_H_
-#include <memory>
-
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
@@ -49,12 +47,12 @@ class UdpSocket final : public openscreen::UdpSocket,
// network::mojom::UDPSocketListener overrides:
void OnReceived(int32_t net_result,
- const base::Optional<net::IPEndPoint>& source_endpoint,
- base::Optional<base::span<const uint8_t>> data) override;
+ const absl::optional<net::IPEndPoint>& source_endpoint,
+ absl::optional<base::span<const uint8_t>> data) override;
private:
void BindCallback(int32_t result,
- const base::Optional<net::IPEndPoint>& address);
+ const absl::optional<net::IPEndPoint>& address);
void JoinGroupCallback(int32_t result);
void SendCallback(int32_t result);
diff --git a/chromium/components/optimization_guide/DEPS b/chromium/components/optimization_guide/DEPS
index 9a4a580b389..c7b5a4d683c 100644
--- a/chromium/components/optimization_guide/DEPS
+++ b/chromium/components/optimization_guide/DEPS
@@ -12,6 +12,7 @@ include_rules = [
"+third_party/re2",
"+third_party/smhasher",
"+third_party/tflite",
+ "+third_party/tflite-support",
# Optimization Guide is a layered component; subdirectories must explicitly
# introduce the ability to use the content layer as appropriate.
diff --git a/chromium/components/optimization_guide/content/browser/BUILD.gn b/chromium/components/optimization_guide/content/browser/BUILD.gn
index 1ca94bff5d7..9f608e26f5d 100644
--- a/chromium/components/optimization_guide/content/browser/BUILD.gn
+++ b/chromium/components/optimization_guide/content/browser/BUILD.gn
@@ -21,11 +21,6 @@ static_library("browser") {
]
if (build_with_tflite_lib) {
sources += [
- "base_model_executor.h",
- "base_model_executor_helpers.h",
- "bert_model_executor.cc",
- "bert_model_executor.h",
- "optimization_target_model_executor.h",
"page_content_annotations_model_manager.cc",
"page_content_annotations_model_manager.h",
]
@@ -73,15 +68,12 @@ source_set("unit_tests") {
"page_text_observer_unittest.cc",
]
if (build_with_tflite_lib) {
- sources += [
- "bert_model_executor_unittest.cc",
- "optimization_target_model_executor_unittest.cc",
- "page_content_annotations_model_manager_unittest.cc",
- ]
+ sources += [ "page_content_annotations_model_manager_unittest.cc" ]
}
deps = [
":browser",
":test_support",
+ "//components/optimization_guide/core:test_support",
"//content/test:test_support",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/optimization_guide/content/browser/DEPS b/chromium/components/optimization_guide/content/browser/DEPS
index e9a2bafcb8d..d1731611f7d 100644
--- a/chromium/components/optimization_guide/content/browser/DEPS
+++ b/chromium/components/optimization_guide/content/browser/DEPS
@@ -8,6 +8,4 @@ include_rules = [
"+mojo/public",
"+services/service_manager/public",
"+third_party/blink/public",
- "+third_party/tflite",
- "+third_party/tflite-support",
]
diff --git a/chromium/components/optimization_guide/content/browser/bert_model_executor.h b/chromium/components/optimization_guide/content/browser/bert_model_executor.h
deleted file mode 100644
index 29d756aa9c3..00000000000
--- a/chromium/components/optimization_guide/content/browser/bert_model_executor.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_BERT_MODEL_EXECUTOR_H_
-#define COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_BERT_MODEL_EXECUTOR_H_
-
-#include "components/optimization_guide/content/browser/optimization_target_model_executor.h"
-#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/category.h"
-
-namespace optimization_guide {
-
-// An OptimizationTargetModelExecutor that executes BERT models.
-//
-// Note that sentencepiece tokenizers are not supported by Chromium's copy of
-// the TFLite Support library.
-class BertModelExecutor : public OptimizationTargetModelExecutor<
- std::vector<tflite::task::core::Category>,
- const std::string&> {
- public:
- BertModelExecutor(OptimizationGuideDecider* decider,
- proto::OptimizationTarget optimization_target,
- const base::Optional<proto::Any>& model_metadata,
- const scoped_refptr<base::SequencedTaskRunner>&
- model_execution_task_runner);
- ~BertModelExecutor() override;
- BertModelExecutor(const BertModelExecutor&) = delete;
- BertModelExecutor& operator=(const BertModelExecutor&) = delete;
-
- protected:
- using ModelExecutionTask =
- tflite::task::core::BaseTaskApi<std::vector<tflite::task::core::Category>,
- const std::string&>;
-
- // OptimizationTargetModelExecutor:
- base::Optional<std::vector<tflite::task::core::Category>> Execute(
- ModelExecutionTask* execution_task,
- const std::string& input) override;
- std::unique_ptr<ModelExecutionTask> BuildModelExecutionTask(
- base::MemoryMappedFile* model_file) override;
-};
-
-} // namespace optimization_guide
-
-#endif // COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_BERT_MODEL_EXECUTOR_H_
diff --git a/chromium/components/optimization_guide/content/browser/optimization_guide_decider.h b/chromium/components/optimization_guide/content/browser/optimization_guide_decider.h
index 5507c256da4..3f6f34b5990 100644
--- a/chromium/components/optimization_guide/content/browser/optimization_guide_decider.h
+++ b/chromium/components/optimization_guide/content/browser/optimization_guide_decider.h
@@ -9,11 +9,10 @@
#include "base/callback_forward.h"
#include "base/containers/flat_map.h"
-#include "base/optional.h"
#include "components/optimization_guide/core/optimization_metadata.h"
-#include "components/optimization_guide/core/optimization_target_model_observer.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class NavigationHandle;
@@ -67,28 +66,6 @@ class OptimizationGuideDecider {
proto::OptimizationTarget optimization_target,
OptimizationGuideTargetDecisionCallback callback) = 0;
- // Adds an observer for updates to the model for |optimization_target|.
- //
- // It is assumed that any model retrieved this way will be passed to the
- // Machine Learning Service for inference.
- //
- // It is also assumed that there will only be one observer per optimization
- // target, so if multiple observers are registered, this will crash in debug
- // builds and be a no-op in release builds.
- virtual void AddObserverForOptimizationTargetModel(
- proto::OptimizationTarget optimization_target,
- const base::Optional<proto::Any>& model_metadata,
- OptimizationTargetModelObserver* observer) = 0;
-
- // Removes an observer for updates to the model for |optimization_target|.
- //
- // If |observer| is registered for multiple targets, |observer| must be
- // removed for all targets that it is added for in order for it to be fully
- // removed from receiving any calls.
- virtual void RemoveObserverForOptimizationTargetModel(
- proto::OptimizationTarget optimization_target,
- OptimizationTargetModelObserver* observer) = 0;
-
// Registers the optimization types that intend to be queried during the
// session. It is expected for this to be called after the browser has been
// initialized.
diff --git a/chromium/components/optimization_guide/content/browser/optimization_target_model_executor.h b/chromium/components/optimization_guide/content/browser/optimization_target_model_executor.h
deleted file mode 100644
index 7ef5a1e9ad0..00000000000
--- a/chromium/components/optimization_guide/content/browser/optimization_target_model_executor.h
+++ /dev/null
@@ -1,324 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_OPTIMIZATION_TARGET_MODEL_EXECUTOR_H_
-#define COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_OPTIMIZATION_TARGET_MODEL_EXECUTOR_H_
-
-#include "base/bind.h"
-#include "base/callback_forward.h"
-#include "base/files/memory_mapped_file.h"
-#include "base/logging.h"
-#include "base/memory/weak_ptr.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/optional.h"
-#include "base/task/task_traits.h"
-#include "base/task/thread_pool.h"
-#include "base/time/time.h"
-#include "components/optimization_guide/content/browser/optimization_guide_decider.h"
-#include "components/optimization_guide/core/optimization_guide_enums.h"
-#include "components/optimization_guide/core/optimization_guide_features.h"
-#include "components/optimization_guide/core/optimization_guide_util.h"
-#include "components/optimization_guide/core/optimization_target_model_observer.h"
-#include "content/public/browser/browser_thread.h"
-#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/base_task_api.h"
-#include "third_party/tflite/src/tensorflow/lite/c/common.h"
-
-namespace optimization_guide {
-
-namespace {
-
-// Util class for recording the result of loading the detection model. The
-// result is recorded when it goes out of scope and its destructor is called.
-class ScopedModelExecutorLoadingResultRecorder {
- public:
- ScopedModelExecutorLoadingResultRecorder(
- proto::OptimizationTarget optimization_target,
- ModelExecutorLoadingState model_loading_state)
- : optimization_target_(optimization_target),
- model_loading_state_(model_loading_state),
- start_time_(base::TimeTicks::Now()) {}
-
- ~ScopedModelExecutorLoadingResultRecorder() {
- base::UmaHistogramEnumeration(
- "OptimizationGuide.ModelExecutor.ModelLoadingResult." +
- optimization_guide::GetStringNameForOptimizationTarget(
- optimization_target_),
- model_loading_state_);
-
- base::UmaHistogramTimes(
- "OptimizationGuide.ModelExecutor.ModelLoadingDuration." +
- optimization_guide::GetStringNameForOptimizationTarget(
- optimization_target_),
- base::TimeTicks::Now() - start_time_);
- }
-
- void set_model_loading_state(ModelExecutorLoadingState model_executor_state) {
- model_loading_state_ = model_executor_state;
- }
-
- private:
- proto::OptimizationTarget optimization_target_;
- ModelExecutorLoadingState model_loading_state_;
-
- // The time at which this instance was constructed.
- const base::TimeTicks start_time_;
-};
-
-} // namespace
-
-template <class OutputType, class... InputTypes>
-class OptimizationTargetModelExecutor : public OptimizationTargetModelObserver {
- public:
- using ModelExecutionTask =
- tflite::task::core::BaseTaskApi<OutputType, InputTypes...>;
-
- OptimizationTargetModelExecutor(
- OptimizationGuideDecider* decider,
- proto::OptimizationTarget optimization_target,
- const base::Optional<proto::Any>& model_metadata,
- const scoped_refptr<base::SequencedTaskRunner>&
- model_execution_task_runner)
- : decider_(decider),
- optimization_target_(optimization_target),
- model_execution_task_runner_(model_execution_task_runner) {
- DCHECK(decider_);
- DCHECK_NE(optimization_target_,
- proto::OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN);
-
- decider_->AddObserverForOptimizationTargetModel(optimization_target_,
- model_metadata, this);
- }
- ~OptimizationTargetModelExecutor() override {
- base::UmaHistogramCounts100(
- "OptimizationGuide.ModelExecutor.RunCount." +
- GetStringNameForOptimizationTarget(optimization_target_),
- run_count_);
- decider_->RemoveObserverForOptimizationTargetModel(optimization_target_,
- this);
- }
- OptimizationTargetModelExecutor(const OptimizationTargetModelExecutor&) =
- delete;
- OptimizationTargetModelExecutor& operator=(
- const OptimizationTargetModelExecutor&) = delete;
-
- // Executes the model using |input| and invokes |callback| when completed.
- // TODO(crbug/1173328): Add a way to surface errors.
- using ExecutionCallback =
- base::OnceCallback<void(const base::Optional<OutputType>&)>;
- void ExecuteModelWithInput(ExecutionCallback callback, InputTypes... input) {
- // base::Unretained is safe here since the execution will not run if
- // |model_execution_task_runner_| gets destructed.
- model_execution_task_runner_->PostTaskAndReplyWithResult(
- FROM_HERE,
- base::BindOnce(&OptimizationTargetModelExecutor::SendForExecution,
- base::Unretained(this), input...),
- base::BindOnce(&OptimizationTargetModelExecutor::OnExecutionCompleted,
- weak_ptr_factory_.GetWeakPtr(), std::move(callback),
- base::TimeTicks::Now()));
- }
-
- // OptimizationTargetModelObserver:
- void OnModelFileUpdated(proto::OptimizationTarget optimization_target,
- const base::Optional<proto::Any>& model_metadata,
- const base::FilePath& file_path) override {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- if (optimization_target_ != optimization_target)
- return;
-
- model_metadata_to_load_ = model_metadata;
- file_path_to_load_ = file_path;
-
- if (features::LoadModelFileForEachExecution()) {
- // Wait for an actual execution before the model gets loaded.
- return;
- }
-
- // base::Unretained is safe here since model loading will not run if
- // |model_execution_task_runner_| gets destructed.
- model_execution_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(
- base::IgnoreResult(&OptimizationTargetModelExecutor::LoadModelFile),
- base::Unretained(this)));
- }
-
- // Returns whether a model is currently loaded.
- bool HasLoadedModel() const { return loaded_model_ != nullptr; }
-
- // Returns the supported features for the loaded model, if the server provided
- // any.
- base::Optional<proto::Any> supported_features_for_loaded_model() const {
- return supported_features_for_loaded_model_;
- }
- // Validates that |supported_features_for_loaded_model_| is of the same type
- // and is parseable as |T|. Will return metadata if all checks pass.
- template <
- class T,
- class = typename std::enable_if<
- std::is_convertible<T*, google::protobuf::MessageLite*>{}>::type>
- base::Optional<T> ParsedSupportedFeaturesForLoadedModel() const {
- if (!supported_features_for_loaded_model_)
- return base::nullopt;
- return ParsedAnyMetadata<T>(*supported_features_for_loaded_model_);
- }
-
- protected:
- // Executes the model using |execution_task| on |args|.
- virtual base::Optional<OutputType> Execute(ModelExecutionTask* execution_task,
- InputTypes... args) = 0;
-
- // Builds a model execution task using |model_file|.
- virtual std::unique_ptr<ModelExecutionTask> BuildModelExecutionTask(
- base::MemoryMappedFile* model_file) = 0;
-
- private:
- void ResetLoadedModel() {
- DCHECK(model_execution_task_runner_->RunsTasksInCurrentSequence());
- loaded_model_.reset();
- model_fb_.reset();
- supported_features_for_loaded_model_ = base::nullopt;
- }
-
- // Callback invoked when a model file for |optimization_target| has been
- // loaded. A true return value indicates the model was loaded successfully,
- // false otherwise.
- bool LoadModelFile() {
- DCHECK(model_execution_task_runner_->RunsTasksInCurrentSequence());
- ScopedModelExecutorLoadingResultRecorder scoped_model_loading_recorder(
- optimization_target_, ModelExecutorLoadingState::kModelFileInvalid);
-
- // We received a new model file. Reset any loaded models.
- ResetLoadedModel();
-
- if (!file_path_to_load_)
- return false;
-
- std::unique_ptr<base::MemoryMappedFile> model_fb =
- std::make_unique<base::MemoryMappedFile>();
- if (!model_fb->Initialize(*file_path_to_load_))
- return false;
- model_fb_ = std::move(model_fb);
-
- supported_features_for_loaded_model_ = model_metadata_to_load_;
-
- loaded_model_ = BuildModelExecutionTask(model_fb_.get());
- if (loaded_model_) {
- scoped_model_loading_recorder.set_model_loading_state(
- ModelExecutorLoadingState::kModelFileValidAndMemoryMapped);
- }
-
- return !!loaded_model_;
- }
-
- base::Optional<OutputType> SendForExecution(InputTypes... args) {
- DCHECK(model_execution_task_runner_->RunsTasksInCurrentSequence());
-
- // If there's no model to be loaded, no model can be loaded.
- if (!file_path_to_load_) {
- DCHECK(!loaded_model_);
- return base::nullopt;
- }
-
- // Attempt to load the model file if it isn't loaded yet, fail if loading is
- // unsuccessful.
- if (!loaded_model_ && !LoadModelFile())
- return base::nullopt;
-
- run_count_++;
- if (last_execution_time_) {
- // The max of this histogram is 3m since only the distribution and count
- // of smaller values is important.
- base::UmaHistogramMediumTimes(
- "OptimizationGuide.ModelExecutor.TimeSincePreviousRun." +
- GetStringNameForOptimizationTarget(optimization_target_),
- base::TimeTicks::Now() - *last_execution_time_);
- }
- last_execution_time_ = base::TimeTicks::Now();
-
- DCHECK(loaded_model_);
- return Execute(loaded_model_.get(), args...);
- }
-
- void OnExecutionCompleted(ExecutionCallback callback,
- base::TimeTicks model_execute_start_time,
- base::Optional<OutputType> output) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- // If the model file should only be loaded for execution, then unload it
- // from memory. This should be done in a PostTask since it may take a while
- // for big models and the metrics below shouldn't be skewed, and
- // |loaded_model_| should only be accessed by
- // |model_execution_task_runner_|.
- if (features::LoadModelFileForEachExecution()) {
- model_execution_task_runner_->PostTask(
- FROM_HERE,
- // base::Unretained is safe here since |model_execution_task_runner_|
- // is owned by |this|.
- base::BindOnce(&OptimizationTargetModelExecutor::ResetLoadedModel,
- base::Unretained(this)));
- }
-
- if (!output) {
- std::move(callback).Run(output);
- return;
- }
-
- base::TimeDelta execution_time =
- base::TimeTicks::Now() - model_execute_start_time;
-
- base::UmaHistogramMediumTimes(
- "OptimizationGuide.ModelExecutor.TaskExecutionLatency." +
- optimization_guide::GetStringNameForOptimizationTarget(
- optimization_target_),
- execution_time);
- std::move(callback).Run(output);
- }
-
- // Not owned. Guaranteed to outlive |this|.
- OptimizationGuideDecider* decider_;
-
- proto::OptimizationTarget optimization_target_;
-
- // Incremented every time the model is run and logged in metrics on
- // destruction.
- size_t run_count_ = 0;
-
- // The time that the model was last executed. Logged in metrics for the second
- // and following runs.
- base::Optional<base::TimeTicks> last_execution_time_;
-
- scoped_refptr<base::SequencedTaskRunner> model_execution_task_runner_;
-
- // When the model file is updated, the server may pass this metadata that
- // accompanies the model. This can be nullopt even after a model file update
- // occurs since.
- base::Optional<proto::Any> model_metadata_to_load_;
-
- // The model file path to be loaded. May be nullopt if no model has been
- // downloaded yet.
- base::Optional<base::FilePath> file_path_to_load_;
-
- // Note on lifetimes: |model_fb_|, |loaded_model_|, and
- // |supported_features_for_loaded_model_| all share the same lifetime, being
- // set in |LoadModelFile()| and being destroyed in |ResetModelFile()|.
-
- // This will only be non-null when |file_path_to_load_| is set, and while the
- // model is loaded which is manged by a feature flag. See also the above note
- // regarding lifetime.
- std::unique_ptr<base::MemoryMappedFile> model_fb_;
-
- // |loaded_model_| should only be accessed on |model_execution_task_runner_|.
- // See also the above note regarding lifetime.
- std::unique_ptr<ModelExecutionTask> loaded_model_;
-
- // See the above note regarding lifetime.
- base::Optional<proto::Any> supported_features_for_loaded_model_;
-
- base::WeakPtrFactory<OptimizationTargetModelExecutor> weak_ptr_factory_{this};
-};
-
-} // namespace optimization_guide
-
-#endif // COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_OPTIMIZATION_TARGET_MODEL_EXECUTOR_H_
diff --git a/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager.cc b/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager.cc
index 629c3a39266..a7393968da9 100644
--- a/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager.cc
+++ b/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager.cc
@@ -8,7 +8,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
-#include "components/optimization_guide/content/browser/optimization_guide_decider.h"
+#include "components/optimization_guide/core/optimization_guide_model_provider.h"
namespace optimization_guide {
@@ -26,7 +26,7 @@ const int kNoneCategoryId = -2;
} // namespace
PageContentAnnotationsModelManager::PageContentAnnotationsModelManager(
- optimization_guide::OptimizationGuideDecider* optimization_guide_decider) {
+ OptimizationGuideModelProvider* optimization_guide_model_provider) {
proto::Any model_metadata;
model_metadata.set_type_url(kPageTopicsModelMetadataTypeUrl);
proto::PageTopicsModelMetadata page_topics_model_metadata;
@@ -36,11 +36,12 @@ PageContentAnnotationsModelManager::PageContentAnnotationsModelManager(
proto::PAGE_TOPICS_SUPPORTED_OUTPUT_CATEGORIES);
page_topics_model_metadata.SerializeToString(model_metadata.mutable_value());
- page_topics_model_executor_ = std::make_unique<BertModelExecutor>(
- optimization_guide_decider, proto::OPTIMIZATION_TARGET_PAGE_TOPICS,
- model_metadata,
- base::ThreadPool::CreateSequencedTaskRunner(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT}));
+ page_topics_model_executor_handle_ =
+ std::make_unique<BertModelExecutorHandle>(
+ optimization_guide_model_provider,
+ base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT}),
+ proto::OPTIMIZATION_TARGET_PAGE_TOPICS, model_metadata);
}
PageContentAnnotationsModelManager::~PageContentAnnotationsModelManager() =
@@ -49,15 +50,21 @@ PageContentAnnotationsModelManager::~PageContentAnnotationsModelManager() =
void PageContentAnnotationsModelManager::Annotate(
const std::string& text,
PageContentAnnotatedCallback callback) {
- base::Optional<proto::PageTopicsModelMetadata> model_metadata =
- page_topics_model_executor_->ParsedSupportedFeaturesForLoadedModel<
- proto::PageTopicsModelMetadata>();
- if (!model_metadata) {
+ if (!page_topics_model_executor_handle_->ModelAvailable()) {
// TODO(crbug/1177102): Figure out if we want to enqueue it for later if
// model isn't ready, but if we call this when the model isn't ready, it
- // will just return base::nullopt for now.
+ // will just return absl::nullopt for now.
+ return;
+ }
+
+ absl::optional<proto::PageTopicsModelMetadata> model_metadata =
+ page_topics_model_executor_handle_->ParsedSupportedFeaturesForLoadedModel<
+ proto::PageTopicsModelMetadata>();
+ if (!model_metadata) {
+ NOTREACHED();
return;
}
+
bool has_supported_output = false;
for (const auto supported_output : model_metadata->supported_output()) {
if (supported_output == proto::PAGE_TOPICS_SUPPORTED_OUTPUT_CATEGORIES ||
@@ -71,7 +78,7 @@ void PageContentAnnotationsModelManager::Annotate(
// TODO(crbug/1177102): Add histogram.
return;
}
- page_topics_model_executor_->ExecuteModelWithInput(
+ page_topics_model_executor_handle_->ExecuteModelWithInput(
base::BindOnce(&PageContentAnnotationsModelManager::
OnPageTopicsModelExecutionCompleted,
weak_ptr_factory_.GetWeakPtr(), std::move(callback),
@@ -82,8 +89,8 @@ void PageContentAnnotationsModelManager::Annotate(
void PageContentAnnotationsModelManager::OnPageTopicsModelExecutionCompleted(
PageContentAnnotatedCallback callback,
const proto::PageTopicsModelMetadata& model_metadata,
- const base::Optional<std::vector<tflite::task::core::Category>>& output) {
- base::Optional<history::VisitContentModelAnnotations> content_annotations;
+ const absl::optional<std::vector<tflite::task::core::Category>>& output) {
+ absl::optional<history::VisitContentModelAnnotations> content_annotations;
if (output) {
content_annotations =
GetContentModelAnnotationsFromOutput(model_metadata, *output);
@@ -91,21 +98,21 @@ void PageContentAnnotationsModelManager::OnPageTopicsModelExecutionCompleted(
std::move(callback).Run(content_annotations);
}
-base::Optional<int64_t>
+absl::optional<int64_t>
PageContentAnnotationsModelManager::GetPageTopicsModelVersion() const {
- base::Optional<proto::PageTopicsModelMetadata> model_metadata =
- page_topics_model_executor_->ParsedSupportedFeaturesForLoadedModel<
+ absl::optional<proto::PageTopicsModelMetadata> model_metadata =
+ page_topics_model_executor_handle_->ParsedSupportedFeaturesForLoadedModel<
proto::PageTopicsModelMetadata>();
if (model_metadata)
return model_metadata->version();
- return base::nullopt;
+ return absl::nullopt;
}
history::VisitContentModelAnnotations
PageContentAnnotationsModelManager::GetContentModelAnnotationsFromOutput(
const proto::PageTopicsModelMetadata& model_metadata,
const std::vector<tflite::task::core::Category>& model_output) const {
- base::Optional<std::string> floc_protected_category_name;
+ absl::optional<std::string> floc_protected_category_name;
if (model_metadata.output_postprocessing_params()
.has_floc_protected_params()) {
floc_protected_category_name = model_metadata.output_postprocessing_params()
@@ -150,7 +157,7 @@ PageContentAnnotationsModelManager::GetContentModelAnnotationsFromOutput(
size_t max_categories = static_cast<size_t>(category_params.max_categories());
float total_weight = 0.0;
float sum_positive_scores = 0.0;
- base::Optional<std::pair<size_t, float>> none_idx_and_weight;
+ absl::optional<std::pair<size_t, float>> none_idx_and_weight;
std::vector<std::pair<int, float>> categories;
categories.reserve(max_categories);
for (size_t i = 0; i < category_candidates.size() && i < max_categories;
diff --git a/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager.h b/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager.h
index 13146adb24b..48ebc0df580 100644
--- a/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager.h
+++ b/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager.h
@@ -6,22 +6,22 @@
#define COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_PAGE_CONTENT_ANNOTATIONS_MODEL_MANAGER_H_
#include "components/history/core/browser/url_row.h"
-#include "components/optimization_guide/content/browser/bert_model_executor.h"
+#include "components/optimization_guide/core/bert_model_executor.h"
#include "components/optimization_guide/proto/page_topics_model_metadata.pb.h"
namespace optimization_guide {
-class OptimizationGuideDecider;
+class OptimizationGuideModelProvider;
// Callback to inform the caller that the page content has been annotated.
using PageContentAnnotatedCallback = base::OnceCallback<void(
- const base::Optional<history::VisitContentModelAnnotations>&)>;
+ const absl::optional<history::VisitContentModelAnnotations>&)>;
// Manages the loading and execution of models used to annotate page content.
class PageContentAnnotationsModelManager {
public:
explicit PageContentAnnotationsModelManager(
- OptimizationGuideDecider* optimization_guide_decider);
+ OptimizationGuideModelProvider* optimization_guide_model_provider);
~PageContentAnnotationsModelManager();
PageContentAnnotationsModelManager(
const PageContentAnnotationsModelManager&) = delete;
@@ -32,9 +32,9 @@ class PageContentAnnotationsModelManager {
void Annotate(const std::string& text, PageContentAnnotatedCallback callback);
// Returns the version of the page topics model that is currently being used
- // to annotate page content. Will return |base::nullopt| if no model is being
+ // to annotate page content. Will return |absl::nullopt| if no model is being
// used to annotate page topics for received page content.
- base::Optional<int64_t> GetPageTopicsModelVersion() const;
+ absl::optional<int64_t> GetPageTopicsModelVersion() const;
private:
friend class PageContentAnnotationsModelManagerTest;
@@ -43,7 +43,7 @@ class PageContentAnnotationsModelManager {
void OnPageTopicsModelExecutionCompleted(
PageContentAnnotatedCallback callback,
const proto::PageTopicsModelMetadata& model_metadata,
- const base::Optional<std::vector<tflite::task::core::Category>>& output);
+ const absl::optional<std::vector<tflite::task::core::Category>>& output);
// Converts |model_output| into content model annotations based on
// |model_metadata|.
@@ -52,7 +52,7 @@ class PageContentAnnotationsModelManager {
const std::vector<tflite::task::core::Category>& model_output) const;
// The model executor responsible for executing the page topics model.
- std::unique_ptr<BertModelExecutor> page_topics_model_executor_;
+ std::unique_ptr<BertModelExecutorHandle> page_topics_model_executor_handle_;
base::WeakPtrFactory<PageContentAnnotationsModelManager> weak_ptr_factory_{
this};
diff --git a/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager_unittest.cc b/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager_unittest.cc
index 54cd1de1501..9df98ca7a2a 100644
--- a/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager_unittest.cc
+++ b/chromium/components/optimization_guide/content/browser/page_content_annotations_model_manager_unittest.cc
@@ -5,7 +5,7 @@
#include "components/optimization_guide/content/browser/page_content_annotations_model_manager.h"
#include "base/path_service.h"
-#include "components/optimization_guide/content/browser/test_optimization_guide_decider.h"
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
#include "components/optimization_guide/machine_learning_tflite_buildflags.h"
#include "components/optimization_guide/proto/page_topics_model_metadata.pb.h"
#include "content/public/test/browser_task_environment.h"
@@ -16,11 +16,12 @@ namespace optimization_guide {
using testing::UnorderedElementsAre;
-class PageTopicsModelObserverTracker : public TestOptimizationGuideDecider {
+class PageTopicsModelObserverTracker
+ : public TestOptimizationGuideModelProvider {
public:
void AddObserverForOptimizationTargetModel(
proto::OptimizationTarget target,
- const base::Optional<proto::Any>& model_metadata,
+ const absl::optional<proto::Any>& model_metadata,
OptimizationTargetModelObserver* observer) override {
// Make sure we send what is expected.
if (target != proto::OptimizationTarget::OPTIMIZATION_TARGET_PAGE_TOPICS) {
@@ -29,12 +30,12 @@ class PageTopicsModelObserverTracker : public TestOptimizationGuideDecider {
registered_model_metadata_ = model_metadata;
}
- base::Optional<proto::Any> registered_model_metadata() const {
+ absl::optional<proto::Any> registered_model_metadata() const {
return registered_model_metadata_;
}
private:
- base::Optional<proto::Any> registered_model_metadata_;
+ absl::optional<proto::Any> registered_model_metadata_;
};
class PageContentAnnotationsModelManagerTest : public testing::Test {
@@ -63,7 +64,7 @@ class PageContentAnnotationsModelManagerTest : public testing::Test {
.AppendASCII("data")
.AppendASCII("optimization_guide")
.AppendASCII("bert_page_topics_model.tflite");
- model_manager()->page_topics_model_executor_->OnModelFileUpdated(
+ model_manager()->page_topics_model_executor_handle_->OnModelFileUpdated(
proto::OPTIMIZATION_TARGET_PAGE_TOPICS, model_metadata,
model_file_path);
RunUntilIdle();
@@ -94,11 +95,11 @@ class PageContentAnnotationsModelManagerTest : public testing::Test {
};
TEST_F(PageContentAnnotationsModelManagerTest, RegistersCorrectModelMetadata) {
- base::Optional<proto::Any> registered_model_metadata =
+ absl::optional<proto::Any> registered_model_metadata =
model_observer_tracker()->registered_model_metadata();
#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
EXPECT_TRUE(registered_model_metadata.has_value());
- base::Optional<proto::PageTopicsModelMetadata> page_topics_model_metadata =
+ absl::optional<proto::PageTopicsModelMetadata> page_topics_model_metadata =
ParsedAnyMetadata<proto::PageTopicsModelMetadata>(
*registered_model_metadata);
EXPECT_TRUE(page_topics_model_metadata.has_value());
@@ -127,7 +128,7 @@ TEST_F(PageContentAnnotationsModelManagerTest,
page_topics_model_metadata.SerializeToString(any_metadata.mutable_value());
SendPageTopicsModelToExecutor(any_metadata);
- base::Optional<int64_t> model_version =
+ absl::optional<int64_t> model_version =
model_manager()->GetPageTopicsModelVersion();
EXPECT_TRUE(model_version.has_value());
EXPECT_EQ(model_version.value(), 123);
@@ -141,7 +142,7 @@ TEST_F(PageContentAnnotationsModelManagerTest,
any_metadata.set_value("123");
SendPageTopicsModelToExecutor(any_metadata);
- base::Optional<int64_t> model_version =
+ absl::optional<int64_t> model_version =
model_manager()->GetPageTopicsModelVersion();
EXPECT_FALSE(model_version.has_value());
}
diff --git a/chromium/components/optimization_guide/content/browser/page_content_annotations_service.cc b/chromium/components/optimization_guide/content/browser/page_content_annotations_service.cc
index 35dd1cb9f47..ec39ffdef66 100644
--- a/chromium/components/optimization_guide/content/browser/page_content_annotations_service.cc
+++ b/chromium/components/optimization_guide/content/browser/page_content_annotations_service.cc
@@ -6,9 +6,9 @@
#include "base/metrics/histogram_functions.h"
#include "components/history/core/browser/history_service.h"
-#include "components/optimization_guide/content/browser/optimization_guide_decider.h"
#include "components/optimization_guide/core/optimization_guide_enums.h"
#include "components/optimization_guide/core/optimization_guide_features.h"
+#include "components/optimization_guide/core/optimization_guide_model_provider.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
@@ -34,14 +34,14 @@ void LogPageContentAnnotationsStorageStatus(
#endif
PageContentAnnotationsService::PageContentAnnotationsService(
- OptimizationGuideDecider* optimization_guide_decider,
+ OptimizationGuideModelProvider* optimization_guide_model_provider,
history::HistoryService* history_service) {
- DCHECK(optimization_guide_decider);
+ DCHECK(optimization_guide_model_provider);
DCHECK(history_service);
#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
history_service_ = history_service;
model_manager_ = std::make_unique<PageContentAnnotationsModelManager>(
- optimization_guide_decider);
+ optimization_guide_model_provider);
#endif
}
@@ -60,7 +60,7 @@ void PageContentAnnotationsService::Annotate(const HistoryVisit& visit,
#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
void PageContentAnnotationsService::OnPageContentAnnotated(
const HistoryVisit& visit,
- const base::Optional<history::VisitContentModelAnnotations>&
+ const absl::optional<history::VisitContentModelAnnotations>&
content_annotations) {
base::UmaHistogramBoolean(
"OptimizationGuide.PageContentAnnotationsService.ContentAnnotated",
@@ -107,12 +107,12 @@ void PageContentAnnotationsService::OnURLQueried(
}
#endif
-base::Optional<int64_t>
+absl::optional<int64_t>
PageContentAnnotationsService::GetPageTopicsModelVersion() const {
#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
return model_manager_->GetPageTopicsModelVersion();
#else
- return base::nullopt;
+ return absl::nullopt;
#endif
}
diff --git a/chromium/components/optimization_guide/content/browser/page_content_annotations_service.h b/chromium/components/optimization_guide/content/browser/page_content_annotations_service.h
index 04036b7fab1..296e5e06364 100644
--- a/chromium/components/optimization_guide/content/browser/page_content_annotations_service.h
+++ b/chromium/components/optimization_guide/content/browser/page_content_annotations_service.h
@@ -25,7 +25,7 @@ class HistoryService;
namespace optimization_guide {
-class OptimizationGuideDecider;
+class OptimizationGuideModelProvider;
class PageContentAnnotationsModelManager;
// The information used by HistoryService to identify a visit to a URL.
@@ -38,7 +38,7 @@ struct HistoryVisit {
class PageContentAnnotationsService : public KeyedService {
public:
explicit PageContentAnnotationsService(
- OptimizationGuideDecider* optimization_guide_decider,
+ OptimizationGuideModelProvider* optimization_guide_model_provider,
history::HistoryService* history_service);
~PageContentAnnotationsService() override;
PageContentAnnotationsService(const PageContentAnnotationsService&) = delete;
@@ -58,16 +58,16 @@ class PageContentAnnotationsService : public KeyedService {
virtual void Annotate(const HistoryVisit& visit, const std::string& text);
// Returns the version of the page topics model that is currently being used
- // to annotate page content. Will return |base::nullopt| if no model is being
+ // to annotate page content. Will return |absl::nullopt| if no model is being
// used to annotate page topics for received page content.
- base::Optional<int64_t> GetPageTopicsModelVersion() const;
+ absl::optional<int64_t> GetPageTopicsModelVersion() const;
private:
#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
// Callback invoked when |visit| has been annotated.
void OnPageContentAnnotated(
const HistoryVisit& visit,
- const base::Optional<history::VisitContentModelAnnotations>&
+ const absl::optional<history::VisitContentModelAnnotations>&
content_annotations);
// Callback invoked when |history_service| has returned results for the visits
diff --git a/chromium/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper_unittest.cc b/chromium/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper_unittest.cc
index b219cd9e8fa..d55436b8717 100644
--- a/chromium/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper_unittest.cc
+++ b/chromium/components/optimization_guide/content/browser/page_content_annotations_web_contents_helper_unittest.cc
@@ -8,8 +8,8 @@
#include "components/history/core/browser/history_service.h"
#include "components/optimization_guide/content/browser/page_content_annotations_service.h"
#include "components/optimization_guide/content/browser/page_text_dump_result.h"
-#include "components/optimization_guide/content/browser/test_optimization_guide_decider.h"
#include "components/optimization_guide/core/optimization_guide_features.h"
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
#include "content/public/test/mock_navigation_handle.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
@@ -37,9 +37,9 @@ class TestPageTextObserver : public PageTextObserver {
class FakePageContentAnnotationsService : public PageContentAnnotationsService {
public:
explicit FakePageContentAnnotationsService(
- OptimizationGuideDecider* optimization_guide_decider,
+ OptimizationGuideModelProvider* optimization_guide_model_provider,
history::HistoryService* history_service)
- : PageContentAnnotationsService(optimization_guide_decider,
+ : PageContentAnnotationsService(optimization_guide_model_provider,
history_service) {}
~FakePageContentAnnotationsService() override = default;
@@ -47,13 +47,13 @@ class FakePageContentAnnotationsService : public PageContentAnnotationsService {
last_annotation_request_.emplace(std::make_pair(visit, text));
}
- base::Optional<std::pair<HistoryVisit, std::string>> last_annotation_request()
+ absl::optional<std::pair<HistoryVisit, std::string>> last_annotation_request()
const {
return last_annotation_request_;
}
private:
- base::Optional<std::pair<HistoryVisit, std::string>> last_annotation_request_;
+ absl::optional<std::pair<HistoryVisit, std::string>> last_annotation_request_;
};
class PageContentAnnotationsWebContentsHelperTest
@@ -62,12 +62,12 @@ class PageContentAnnotationsWebContentsHelperTest
void SetUp() override {
content::RenderViewHostTestHarness::SetUp();
- optimization_guide_decider_ =
- std::make_unique<TestOptimizationGuideDecider>();
+ optimization_guide_model_provider_ =
+ std::make_unique<TestOptimizationGuideModelProvider>();
history_service_ = std::make_unique<history::HistoryService>();
page_content_annotations_service_ =
std::make_unique<FakePageContentAnnotationsService>(
- optimization_guide_decider_.get(), history_service_.get());
+ optimization_guide_model_provider_.get(), history_service_.get());
page_text_observer_ = new TestPageTextObserver(web_contents());
web_contents()->SetUserData(TestPageTextObserver::UserDataKey(),
@@ -80,7 +80,7 @@ class PageContentAnnotationsWebContentsHelperTest
void TearDown() override {
page_text_observer_ = nullptr;
page_content_annotations_service_.reset();
- optimization_guide_decider_.reset();
+ optimization_guide_model_provider_.reset();
content::RenderViewHostTestHarness::TearDown();
}
@@ -107,7 +107,8 @@ class PageContentAnnotationsWebContentsHelperTest
}
private:
- std::unique_ptr<TestOptimizationGuideDecider> optimization_guide_decider_;
+ std::unique_ptr<TestOptimizationGuideModelProvider>
+ optimization_guide_model_provider_;
std::unique_ptr<history::HistoryService> history_service_;
std::unique_ptr<FakePageContentAnnotationsService>
page_content_annotations_service_;
@@ -150,7 +151,7 @@ TEST_F(PageContentAnnotationsWebContentsHelperTest,
result.AddFrameTextDumpResult(frame_result);
std::move(request->callback).Run(std::move(result));
- base::Optional<std::pair<HistoryVisit, std::string>> last_annotation_request =
+ absl::optional<std::pair<HistoryVisit, std::string>> last_annotation_request =
service()->last_annotation_request();
EXPECT_TRUE(last_annotation_request.has_value());
EXPECT_EQ(last_annotation_request->first.url, GURL("http://test.com"));
diff --git a/chromium/components/optimization_guide/content/browser/page_text_dump_result.cc b/chromium/components/optimization_guide/content/browser/page_text_dump_result.cc
index ce8b182c0e7..46ad3662645 100644
--- a/chromium/components/optimization_guide/content/browser/page_text_dump_result.cc
+++ b/chromium/components/optimization_guide/content/browser/page_text_dump_result.cc
@@ -8,6 +8,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
namespace optimization_guide {
@@ -34,14 +35,14 @@ void PageTextDumpResult::AddFrameTextDumpResult(
frame_results_.emplace(frame_result);
}
-base::Optional<std::string> PageTextDumpResult::GetAMPTextContent() const {
+absl::optional<std::string> PageTextDumpResult::GetAMPTextContent() const {
if (empty()) {
- return base::nullopt;
+ return absl::nullopt;
}
// AMP frames are sorted in beginning, so if there are none then return null.
if (!frame_results_.begin()->amp_frame()) {
- return base::nullopt;
+ return absl::nullopt;
}
std::vector<std::string> amp_text;
@@ -59,15 +60,15 @@ base::Optional<std::string> PageTextDumpResult::GetAMPTextContent() const {
return base::JoinString(amp_text, " ");
}
-base::Optional<std::string> PageTextDumpResult::GetMainFrameTextContent()
+absl::optional<std::string> PageTextDumpResult::GetMainFrameTextContent()
const {
if (empty()) {
- return base::nullopt;
+ return absl::nullopt;
}
// Mainframes are sorted to the end.
if (frame_results_.rbegin()->amp_frame()) {
- return base::nullopt;
+ return absl::nullopt;
}
// There should only be one mainframe.
@@ -75,10 +76,10 @@ base::Optional<std::string> PageTextDumpResult::GetMainFrameTextContent()
return *frame_results_.rbegin()->utf8_contents();
}
-base::Optional<std::string> PageTextDumpResult::GetAllFramesTextContent()
+absl::optional<std::string> PageTextDumpResult::GetAllFramesTextContent()
const {
if (empty()) {
- return base::nullopt;
+ return absl::nullopt;
}
std::vector<std::string> text;
@@ -122,9 +123,9 @@ bool FrameTextDumpResult::IsCompleted() const {
return !!contents();
}
-base::Optional<std::string> FrameTextDumpResult::utf8_contents() const {
+absl::optional<std::string> FrameTextDumpResult::utf8_contents() const {
if (!contents_) {
- return base::nullopt;
+ return absl::nullopt;
}
return base::UTF16ToUTF8(*contents_);
}
diff --git a/chromium/components/optimization_guide/content/browser/page_text_dump_result.h b/chromium/components/optimization_guide/content/browser/page_text_dump_result.h
index 26b2150b3be..4a6a31aece8 100644
--- a/chromium/components/optimization_guide/content/browser/page_text_dump_result.h
+++ b/chromium/components/optimization_guide/content/browser/page_text_dump_result.h
@@ -8,9 +8,9 @@
#include <set>
#include <string>
-#include "base/optional.h"
#include "components/optimization_guide/content/mojom/page_text_service.mojom.h"
#include "content/public/browser/global_routing_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
@@ -38,12 +38,14 @@ class FrameTextDumpResult {
// Whether the class instance is completed yet.
bool IsCompleted() const;
- // The text dump contents. Set only for completed instances.
- const base::Optional<std::u16string>& contents() const { return contents_; }
+ // The text dump contents. Set only for completed instances. Note that
+ // the string must be treated as untrusted data.
+ const absl::optional<std::u16string>& contents() const { return contents_; }
// The text dump contents, decoded to UTF-8 as a best effort. Set only for
- // completed instances.
- base::Optional<std::string> utf8_contents() const;
+ // completed instances. Note that the string must be treated as untrusted
+ // data.
+ absl::optional<std::string> utf8_contents() const;
// The event at which the text dump is taken. Set for both preliminary and
// completed instances.
@@ -103,7 +105,7 @@ class FrameTextDumpResult {
FrameTextDumpResult();
mojom::TextDumpEvent event_;
- base::Optional<std::u16string> contents_;
+ absl::optional<std::u16string> contents_;
content::GlobalFrameRoutingId rfh_id_;
bool amp_frame_ = false;
int unique_navigation_id_ = -1;
@@ -120,14 +122,16 @@ class PageTextDumpResult {
void AddFrameTextDumpResult(const FrameTextDumpResult& frame_result);
// Returns the concatenation of all AMP frames. nullopt if no AMP frames are
- // present.
- base::Optional<std::string> GetAMPTextContent() const;
+ // present. Note that the string must be treated as untrusted data.
+ absl::optional<std::string> GetAMPTextContent() const;
// Returns the concatenation of the mainframe. nullopt if not present.
- base::Optional<std::string> GetMainFrameTextContent() const;
+ // Note that the string must be treated as untrusted data.
+ absl::optional<std::string> GetMainFrameTextContent() const;
// Returns the concatenation of all frames, AMP or main. nullopt if |empty()|.
- base::Optional<std::string> GetAllFramesTextContent() const;
+ // Note that the string must be treated as untrusted data.
+ absl::optional<std::string> GetAllFramesTextContent() const;
bool empty() const { return frame_results_.empty(); }
diff --git a/chromium/components/optimization_guide/content/browser/page_text_dump_result_unittest.cc b/chromium/components/optimization_guide/content/browser/page_text_dump_result_unittest.cc
index 44e282f8087..7c1aa51d13f 100644
--- a/chromium/components/optimization_guide/content/browser/page_text_dump_result_unittest.cc
+++ b/chromium/components/optimization_guide/content/browser/page_text_dump_result_unittest.cc
@@ -4,6 +4,7 @@
#include "components/optimization_guide/content/browser/page_text_dump_result.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -129,9 +130,9 @@ TEST(FrameTextDumpResultTest, Ordering) {
TEST(PageTextDumpResultTest, Empty) {
PageTextDumpResult page_result;
EXPECT_TRUE(page_result.empty());
- EXPECT_EQ(base::nullopt, page_result.GetAMPTextContent());
- EXPECT_EQ(base::nullopt, page_result.GetMainFrameTextContent());
- EXPECT_EQ(base::nullopt, page_result.GetAllFramesTextContent());
+ EXPECT_EQ(absl::nullopt, page_result.GetAMPTextContent());
+ EXPECT_EQ(absl::nullopt, page_result.GetMainFrameTextContent());
+ EXPECT_EQ(absl::nullopt, page_result.GetAllFramesTextContent());
}
TEST(PageTextDumpResultTest, OneAMP) {
diff --git a/chromium/components/optimization_guide/content/browser/page_text_observer.cc b/chromium/components/optimization_guide/content/browser/page_text_observer.cc
index bddd4d32466..78322bed099 100644
--- a/chromium/components/optimization_guide/content/browser/page_text_observer.cc
+++ b/chromium/components/optimization_guide/content/browser/page_text_observer.cc
@@ -14,7 +14,6 @@
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/strcat.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "components/optimization_guide/core/optimization_guide_features.h"
@@ -65,7 +64,7 @@ class PageTextChunkConsumer : public mojom::PageTextConsumer {
PageTextChunkConsumer(
mojo::PendingReceiver<mojom::PageTextConsumer> receiver,
uint32_t max_size,
- base::OnceCallback<void(const base::Optional<std::u16string>&)>
+ base::OnceCallback<void(const absl::optional<std::u16string>&)>
on_complete)
: remaining_size_(max_size),
on_complete_(std::move(on_complete)),
@@ -110,7 +109,7 @@ class PageTextChunkConsumer : public mojom::PageTextConsumer {
void OnDisconnect() {
receiver_.reset();
- std::move(on_complete_).Run(base::nullopt);
+ std::move(on_complete_).Run(absl::nullopt);
// Don't do anything else. This callback may have destroyed |this|.
}
@@ -121,7 +120,7 @@ class PageTextChunkConsumer : public mojom::PageTextConsumer {
// While |on_complete_| is non-null, the mojo pipe is also bound. Once the
// |on_complete_| callback is run, this class is no longer active and can be
// deleted (in stack with the callback).
- base::OnceCallback<void(const base::Optional<std::u16string>&)> on_complete_;
+ base::OnceCallback<void(const absl::optional<std::u16string>&)> on_complete_;
mojo::Receiver<mojom::PageTextConsumer> receiver_;
// All chunks that have been read from the data pipe. These will be
@@ -210,7 +209,7 @@ class RequestMediator : public base::RefCounted<RequestMediator> {
size_t MakeSelfOwnedAndDispatchRequests(
scoped_refptr<RequestMediator> self,
- base::RepeatingCallback<void(base::Optional<FrameTextDumpResult>)>
+ base::RepeatingCallback<void(absl::optional<FrameTextDumpResult>)>
on_frame_text_dump_complete,
content::RenderFrameHost* rfh) {
DCHECK_EQ(self.get(), this);
@@ -276,7 +275,7 @@ class RequestMediator : public base::RefCounted<RequestMediator> {
void OnPageTextAsString(scoped_refptr<RequestMediator> self,
const FrameTextDumpResult& preliminary_result,
- const base::Optional<std::u16string>& page_text) {
+ const absl::optional<std::u16string>& page_text) {
DCHECK(on_frame_text_dump_complete_);
std::string event_suffix =
@@ -286,7 +285,7 @@ class RequestMediator : public base::RefCounted<RequestMediator> {
base::UmaHistogramMediumTimes(
kTimeUntilDisconnectHistogram + event_suffix,
base::TimeTicks::Now() - requests_sent_time_);
- on_frame_text_dump_complete_.Run(base::nullopt);
+ on_frame_text_dump_complete_.Run(absl::nullopt);
return;
}
@@ -302,7 +301,7 @@ class RequestMediator : public base::RefCounted<RequestMediator> {
// Called whenever a text dump is completed for an event. This called as many
// times as events requested, which can be greater than 1.
- base::RepeatingCallback<void(base::Optional<FrameTextDumpResult>)>
+ base::RepeatingCallback<void(absl::optional<FrameTextDumpResult>)>
on_frame_text_dump_complete_;
// All |PageTextChunkConsumer|'s that are owned by this.
@@ -400,7 +399,7 @@ void PageTextObserver::RenderFrameCreated(content::RenderFrameHost* rfh) {
}
void PageTextObserver::OnFrameTextDumpCompleted(
- base::Optional<FrameTextDumpResult> frame_result) {
+ absl::optional<FrameTextDumpResult> frame_result) {
// Ensure that the generated frame result is not for a previous page load.
// This should be done before decrementing |outstanding_requests_| so that
// each page load handles its own state.
diff --git a/chromium/components/optimization_guide/content/browser/page_text_observer.h b/chromium/components/optimization_guide/content/browser/page_text_observer.h
index 5bec33b19b3..4e6ed3e3058 100644
--- a/chromium/components/optimization_guide/content/browser/page_text_observer.h
+++ b/chromium/components/optimization_guide/content/browser/page_text_observer.h
@@ -7,7 +7,6 @@
#include <stdint.h>
#include <set>
-#include <string>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
@@ -108,7 +107,7 @@ class PageTextObserver : public content::WebContentsObserver,
friend class content::WebContentsUserData<PageTextObserver>;
void OnFrameTextDumpCompleted(
- base::Optional<FrameTextDumpResult> frame_result);
+ absl::optional<FrameTextDumpResult> frame_result);
void DispatchResponses();
diff --git a/chromium/components/optimization_guide/content/browser/page_text_observer_unittest.cc b/chromium/components/optimization_guide/content/browser/page_text_observer_unittest.cc
index 3016ce39edb..96eda3956bb 100644
--- a/chromium/components/optimization_guide/content/browser/page_text_observer_unittest.cc
+++ b/chromium/components/optimization_guide/content/browser/page_text_observer_unittest.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
@@ -25,6 +24,7 @@
#include "services/service_manager/public/cpp/interface_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
namespace optimization_guide {
@@ -71,7 +71,7 @@ class TestConsumer : public PageTextObserver::Consumer {
bool was_called() const { return was_called_; }
- base::Optional<PageTextDumpResult> result() {
+ absl::optional<PageTextDumpResult> result() {
return base::OptionalFromPtr(result_.get());
}
@@ -123,7 +123,7 @@ class FakePageTextService : public mojom::PageTextService {
// called.
void SetRemoteResponsesForEvent(
mojom::TextDumpEvent event,
- const std::vector<base::Optional<std::u16string>> responses) {
+ const std::vector<absl::optional<std::u16string>> responses) {
responses_.emplace(event, responses);
}
@@ -150,7 +150,7 @@ class FakePageTextService : public mojom::PageTextService {
mojo::Remote<mojom::PageTextConsumer> consumer_remote;
consumer_remote.Bind(std::move(consumer));
- for (const base::Optional<std::u16string>& resp : responses_iter->second) {
+ for (const absl::optional<std::u16string>& resp : responses_iter->second) {
if (resp) {
consumer_remote->OnTextDumpChunk(*resp);
} else {
@@ -167,13 +167,13 @@ class FakePageTextService : public mojom::PageTextService {
bool disconnect_all_ = false;
// Used to timeout a request.
- base::Optional<mojom::TextDumpEvent> hang_event_;
+ absl::optional<mojom::TextDumpEvent> hang_event_;
mojo::Remote<mojom::PageTextConsumer> hung_consumer_remote_;
// For each event, a sequence of responses to send on the next page dump
// request. If an element has a value, |OnTextDumpChunk| is called with the
// text chunk. If an element does not have a value, |OnChunksEnd| is called.
- std::map<mojom::TextDumpEvent, std::vector<base::Optional<std::u16string>>>
+ std::map<mojom::TextDumpEvent, std::vector<absl::optional<std::u16string>>>
responses_;
};
@@ -301,7 +301,7 @@ TEST_F(PageTextObserverTest, MojoPlumbingSuccessCase) {
u"a",
u"b",
u"c",
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -348,7 +348,7 @@ TEST_F(PageTextObserverTest, CompletedFrameDumpMetrics_Empty) {
FakePageTextService fake_renderer_service;
fake_renderer_service.SetRemoteResponsesForEvent(
mojom::TextDumpEvent::kFirstLayout, {
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -390,7 +390,7 @@ TEST_F(PageTextObserverTest, CompletedFrameDumpMetrics_NotEmpty) {
u"a",
u"b",
u"c",
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -466,7 +466,7 @@ TEST_F(PageTextObserverTest, MaxLengthOnChunkBorder) {
mojom::TextDumpEvent::kFirstLayout, {
u"abc",
u"def",
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -514,7 +514,7 @@ TEST_F(PageTextObserverTest, MaxLengthWithinChunk) {
mojom::TextDumpEvent::kFirstLayout, {
u"abc",
u"def",
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -614,7 +614,7 @@ TEST_F(PageTextObserverTest, TwoConsumers) {
u"a",
u"b",
u"c",
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -681,7 +681,7 @@ TEST_F(PageTextObserverTest, RemoveConsumer) {
u"a",
u"b",
u"c",
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -734,12 +734,12 @@ TEST_F(PageTextObserverTest, TwoEventsRequested) {
fake_renderer_service.SetRemoteResponsesForEvent(
mojom::TextDumpEvent::kFirstLayout, {
u"abc",
- base::nullopt,
+ absl::nullopt,
});
fake_renderer_service.SetRemoteResponsesForEvent(
mojom::TextDumpEvent::kFinishedLoad, {
u"xyz",
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -800,7 +800,7 @@ TEST_F(PageTextObserverTest, AbandonedRequest) {
fake_renderer_service.SetRemoteResponsesForEvent(
mojom::TextDumpEvent::kFirstLayout, {
u"abc",
- base::nullopt,
+ absl::nullopt,
});
fake_renderer_service.SetEventToHangForver(
mojom::TextDumpEvent::kFinishedLoad);
@@ -860,7 +860,7 @@ TEST_F(PageTextObserverTest, AMPRequestedOnOOPIF) {
mojom::TextDumpEvent::kFirstLayout, {
u"abc",
u"def",
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -889,7 +889,7 @@ TEST_F(PageTextObserverTest, AMPRequestedOnOOPIF) {
subframe_fake_renderer_service.SetRemoteResponsesForEvent(
mojom::TextDumpEvent::kFinishedLoad, {
u"amp",
- base::nullopt,
+ absl::nullopt,
});
observer()->RenderFrameCreated(oopif_subframe);
@@ -940,7 +940,7 @@ TEST_F(PageTextObserverTest, AMPNotRequestedOnOOPIF) {
mojom::TextDumpEvent::kFirstLayout, {
u"abc",
u"def",
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -970,7 +970,7 @@ TEST_F(PageTextObserverTest, AMPNotRequestedOnOOPIF) {
mojom::TextDumpEvent::kFinishedLoad, {
u"\n",
u"amp",
- base::nullopt,
+ absl::nullopt,
});
observer()->RenderFrameCreated(oopif_subframe);
@@ -1011,7 +1011,7 @@ TEST_F(PageTextObserverTest, AMPRequestedOnNonOOPIF) {
mojom::TextDumpEvent::kFirstLayout, {
u"abc",
u"def",
- base::nullopt,
+ absl::nullopt,
});
blink::AssociatedInterfaceProvider* remote_interfaces =
@@ -1041,7 +1041,7 @@ TEST_F(PageTextObserverTest, AMPRequestedOnNonOOPIF) {
mojom::TextDumpEvent::kFinishedLoad, {
u"\n",
u"amp",
- base::nullopt,
+ absl::nullopt,
});
observer()->RenderFrameCreated(subframe);
diff --git a/chromium/components/optimization_guide/content/browser/test_optimization_guide_decider.cc b/chromium/components/optimization_guide/content/browser/test_optimization_guide_decider.cc
index ca40abe38bf..8042a07980c 100644
--- a/chromium/components/optimization_guide/content/browser/test_optimization_guide_decider.cc
+++ b/chromium/components/optimization_guide/content/browser/test_optimization_guide_decider.cc
@@ -32,15 +32,6 @@ void TestOptimizationGuideDecider::CanApplyOptimizationAsync(
/*optimization_metadata=*/{});
}
-void TestOptimizationGuideDecider::AddObserverForOptimizationTargetModel(
- optimization_guide::proto::OptimizationTarget optimization_target,
- const base::Optional<proto::Any>& model_metadata,
- optimization_guide::OptimizationTargetModelObserver* observer) {}
-
-void TestOptimizationGuideDecider::RemoveObserverForOptimizationTargetModel(
- optimization_guide::proto::OptimizationTarget optimization_target,
- optimization_guide::OptimizationTargetModelObserver* observer) {}
-
OptimizationGuideDecision TestOptimizationGuideDecider::CanApplyOptimization(
const GURL& url,
proto::OptimizationType optimization_type,
diff --git a/chromium/components/optimization_guide/content/browser/test_optimization_guide_decider.h b/chromium/components/optimization_guide/content/browser/test_optimization_guide_decider.h
index e1044da62f5..17e91f27c88 100644
--- a/chromium/components/optimization_guide/content/browser/test_optimization_guide_decider.h
+++ b/chromium/components/optimization_guide/content/browser/test_optimization_guide_decider.h
@@ -27,13 +27,6 @@ class TestOptimizationGuideDecider : public OptimizationGuideDecider {
content::NavigationHandle* navigation_handle,
proto::OptimizationTarget optimization_target,
OptimizationGuideTargetDecisionCallback callback) override;
- void AddObserverForOptimizationTargetModel(
- proto::OptimizationTarget optimization_target,
- const base::Optional<proto::Any>& model_metadata,
- OptimizationTargetModelObserver* observer) override;
- void RemoveObserverForOptimizationTargetModel(
- proto::OptimizationTarget optimization_target,
- OptimizationTargetModelObserver* observer) override;
void RegisterOptimizationTypes(
const std::vector<proto::OptimizationType>& optimization_types) override;
void CanApplyOptimizationAsync(
diff --git a/chromium/components/optimization_guide/content/mojom/page_text_service.mojom b/chromium/components/optimization_guide/content/mojom/page_text_service.mojom
index addff3b9cff..6dd6113a78b 100644
--- a/chromium/components/optimization_guide/content/mojom/page_text_service.mojom
+++ b/chromium/components/optimization_guide/content/mojom/page_text_service.mojom
@@ -34,6 +34,7 @@ struct PageTextDumpRequest {
// instance.
interface PageTextConsumer {
// Called for each chunk of page text.
+ // Security note: |chunk| should be treated as untrusted data.
OnTextDumpChunk(mojo_base.mojom.String16 chunk);
// Called when no more chunks will be sent.
diff --git a/chromium/components/optimization_guide/content/renderer/page_text_agent.cc b/chromium/components/optimization_guide/content/renderer/page_text_agent.cc
index 749fda7b185..f29f3dfe172 100644
--- a/chromium/components/optimization_guide/content/renderer/page_text_agent.cc
+++ b/chromium/components/optimization_guide/content/renderer/page_text_agent.cc
@@ -16,7 +16,7 @@ namespace {
constexpr size_t kChunkSize = 4096;
-base::Optional<mojom::TextDumpEvent> LayoutEventAsMojoEvent(
+absl::optional<mojom::TextDumpEvent> LayoutEventAsMojoEvent(
blink::WebMeaningfulLayout layout_event) {
switch (layout_event) {
case blink::WebMeaningfulLayout::kFinishedParsing:
@@ -26,7 +26,7 @@ base::Optional<mojom::TextDumpEvent> LayoutEventAsMojoEvent(
default:
break;
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace
@@ -57,7 +57,7 @@ PageTextAgent::MaybeRequestTextDumpOnLayoutEvent(
return base::NullCallback();
}
- base::Optional<mojom::TextDumpEvent> mojo_event =
+ absl::optional<mojom::TextDumpEvent> mojo_event =
LayoutEventAsMojoEvent(event);
if (!mojo_event) {
return base::NullCallback();
@@ -136,7 +136,7 @@ void PageTextAgent::DidFinishLoad() {
void PageTextAgent::DidStartNavigation(
const GURL& url,
- base::Optional<blink::WebNavigationType> navigation_type) {
+ absl::optional<blink::WebNavigationType> navigation_type) {
is_amp_page_ = false;
// Note that |requests_by_event_| should NOT be reset here. Requests and
// navigations from the browser race with each other, and the text dump
diff --git a/chromium/components/optimization_guide/content/renderer/page_text_agent.h b/chromium/components/optimization_guide/content/renderer/page_text_agent.h
index b76e630aeba..d7d7c1c63da 100644
--- a/chromium/components/optimization_guide/content/renderer/page_text_agent.h
+++ b/chromium/components/optimization_guide/content/renderer/page_text_agent.h
@@ -12,12 +12,12 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/optimization_guide/content/mojom/page_text_service.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_frame_observer_tracker.h"
#include "mojo/public/cpp/bindings/associated_receiver_set.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/web/web_meaningful_layout.h"
namespace content {
@@ -59,7 +59,7 @@ class PageTextAgent
void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior) override;
void DidStartNavigation(
const GURL& url,
- base::Optional<blink::WebNavigationType> navigation_type) override;
+ absl::optional<blink::WebNavigationType> navigation_type) override;
void DidFinishLoad() override;
PageTextAgent(const PageTextAgent&) = delete;
diff --git a/chromium/components/optimization_guide/content/renderer/page_text_agent_browsertest.cc b/chromium/components/optimization_guide/content/renderer/page_text_agent_browsertest.cc
index 19b3c657f4e..8dfdb718736 100644
--- a/chromium/components/optimization_guide/content/renderer/page_text_agent_browsertest.cc
+++ b/chromium/components/optimization_guide/content/renderer/page_text_agent_browsertest.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/optional.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/renderer/render_frame.h"
@@ -17,6 +16,7 @@
#include "content/public/test/render_view_test.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/web/web_local_frame.h"
namespace optimization_guide {
diff --git a/chromium/components/optimization_guide/content/renderer/page_text_agent_unittest.cc b/chromium/components/optimization_guide/content/renderer/page_text_agent_unittest.cc
index 20f3689b2de..337ba1af319 100644
--- a/chromium/components/optimization_guide/content/renderer/page_text_agent_unittest.cc
+++ b/chromium/components/optimization_guide/content/renderer/page_text_agent_unittest.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/optional.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/task_environment.h"
@@ -18,6 +17,7 @@
#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/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
diff --git a/chromium/components/optimization_guide/core/BUILD.gn b/chromium/components/optimization_guide/core/BUILD.gn
index 876bd323418..016951a31f3 100644
--- a/chromium/components/optimization_guide/core/BUILD.gn
+++ b/chromium/components/optimization_guide/core/BUILD.gn
@@ -26,8 +26,11 @@ static_library("core") {
"hints_fetcher_factory.h",
"hints_processing_util.cc",
"hints_processing_util.h",
+ "insertion_ordered_set.h",
"memory_hint.cc",
"memory_hint.h",
+ "noisy_metrics_recorder.cc",
+ "noisy_metrics_recorder.h",
"optimization_filter.cc",
"optimization_filter.h",
"optimization_guide_constants.cc",
@@ -35,6 +38,7 @@ static_library("core") {
"optimization_guide_enums.h",
"optimization_guide_features.cc",
"optimization_guide_features.h",
+ "optimization_guide_model_provider.h",
"optimization_guide_permissions_util.cc",
"optimization_guide_permissions_util.h",
"optimization_guide_prefs.cc",
@@ -57,6 +61,7 @@ static_library("core") {
"prediction_model_fetcher.h",
"prediction_model_file.cc",
"prediction_model_file.h",
+ "push_notification_manager.h",
"store_update_data.cc",
"store_update_data.h",
"tab_url_provider.h",
@@ -64,11 +69,29 @@ static_library("core") {
"url_pattern_with_wildcards.cc",
"url_pattern_with_wildcards.h",
]
+ if (build_with_tflite_lib) {
+ sources += [
+ "base_model_executor.h",
+ "base_model_executor_helpers.h",
+ "bert_model_executor.cc",
+ "bert_model_executor.h",
+ "model_executor.h",
+ ]
+ }
public_deps = [
"//components/optimization_guide:machine_learning_tflite_buildflags",
"//third_party/re2",
]
+ if (build_with_tflite_lib) {
+ public_deps += [
+ "//components/optimization_guide/core:machine_learning",
+ "//third_party/tflite",
+ "//third_party/tflite:tflite_public_headers",
+ "//third_party/tflite-support",
+ "//third_party/tflite-support:tflite-support-proto",
+ ]
+ }
deps = [
"//base",
@@ -109,6 +132,8 @@ static_library("test_support") {
"proto_database_provider_test_base.h",
"test_hints_component_creator.cc",
"test_hints_component_creator.h",
+ "test_optimization_guide_model_provider.cc",
+ "test_optimization_guide_model_provider.h",
]
deps = [
":core",
@@ -129,6 +154,8 @@ source_set("unit_tests") {
"hints_component_util_unittest.cc",
"hints_fetcher_unittest.cc",
"hints_processing_util_unittest.cc",
+ "insertion_ordered_set_unittest.cc",
+ "noisy_metrics_recorder_unittest.cc",
"optimization_filter_unittest.cc",
"optimization_guide_features_unittest.cc",
"optimization_guide_permissions_util_unittest.cc",
@@ -142,6 +169,12 @@ source_set("unit_tests") {
"store_update_data_unittest.cc",
"url_pattern_with_wildcards_unittest.cc",
]
+ if (build_with_tflite_lib) {
+ sources += [
+ "bert_model_executor_unittest.cc",
+ "model_executor_unittest.cc",
+ ]
+ }
deps = [
":core",
@@ -162,4 +195,12 @@ source_set("unit_tests") {
"//testing/gtest",
"//url:url",
]
+ if (build_with_tflite_lib) {
+ deps += [
+ "//third_party/tflite",
+ "//third_party/tflite:tflite_public_headers",
+ "//third_party/tflite-support",
+ "//third_party/tflite-support:tflite-support-proto",
+ ]
+ }
}
diff --git a/chromium/components/optimization_guide/content/browser/base_model_executor.h b/chromium/components/optimization_guide/core/base_model_executor.h
index 3d7e3f38730..036370ab847 100644
--- a/chromium/components/optimization_guide/content/browser/base_model_executor.h
+++ b/chromium/components/optimization_guide/core/base_model_executor.h
@@ -2,42 +2,34 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_BASE_MODEL_EXECUTOR_H_
-#define COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_BASE_MODEL_EXECUTOR_H_
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_BASE_MODEL_EXECUTOR_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_BASE_MODEL_EXECUTOR_H_
-#include "components/optimization_guide/content/browser/base_model_executor_helpers.h"
-#include "components/optimization_guide/content/browser/optimization_target_model_executor.h"
+#include "components/optimization_guide/core/base_model_executor_helpers.h"
+#include "components/optimization_guide/core/model_executor.h"
#include "components/optimization_guide/core/tflite_op_resolver.h"
#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/base_task_api.h"
namespace optimization_guide {
-// An OptimizationTargetModelExecutor that executes models with arbitrary input
-// and output types.
+// An ModelExecutor that executes models with arbitrary
+// input and output types. Note that callers will need to give an implementation
+// of this class to a |ModelHandler|, whereas the
+// handle is the actual class that calling code would own and call into.
template <class OutputType, class... InputTypes>
-class BaseModelExecutor
- : public OptimizationTargetModelExecutor<OutputType, InputTypes...>,
- public InferenceDelegate<OutputType, InputTypes...> {
+class BaseModelExecutor : public ModelExecutor<OutputType, InputTypes...>,
+ public InferenceDelegate<OutputType, InputTypes...> {
public:
using ModelExecutionTask =
tflite::task::core::BaseTaskApi<OutputType, InputTypes...>;
- BaseModelExecutor(OptimizationGuideDecider* decider,
- proto::OptimizationTarget optimization_target,
- const base::Optional<proto::Any>& model_metadata,
- const scoped_refptr<base::SequencedTaskRunner>&
- model_execution_task_runner)
- : OptimizationTargetModelExecutor<OutputType, InputTypes...>(
- decider,
- optimization_target,
- model_metadata,
- model_execution_task_runner) {}
+ BaseModelExecutor() = default;
~BaseModelExecutor() override = default;
BaseModelExecutor(const BaseModelExecutor&) = delete;
BaseModelExecutor& operator=(const BaseModelExecutor&) = delete;
protected:
- base::Optional<OutputType> Execute(ModelExecutionTask* execution_task,
+ absl::optional<OutputType> Execute(ModelExecutionTask* execution_task,
InputTypes... args) override {
return static_cast<GenericModelExecutionTask<OutputType, InputTypes...>*>(
execution_task)
@@ -72,12 +64,12 @@ class BaseModelExecutor
}
// InferenceDelegate:
- void Preprocess(const std::vector<TfLiteTensor*>& input_tensors,
- InputTypes... input) override = 0;
+ absl::Status Preprocess(const std::vector<TfLiteTensor*>& input_tensors,
+ InputTypes... input) override = 0;
OutputType Postprocess(
const std::vector<const TfLiteTensor*>& output_tensors) override = 0;
};
} // namespace optimization_guide
-#endif // COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_BASE_MODEL_EXECUTOR_H_
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_BASE_MODEL_EXECUTOR_H_
diff --git a/chromium/components/optimization_guide/content/browser/base_model_executor_helpers.h b/chromium/components/optimization_guide/core/base_model_executor_helpers.h
index d446e969a41..183a86e704c 100644
--- a/chromium/components/optimization_guide/content/browser/base_model_executor_helpers.h
+++ b/chromium/components/optimization_guide/core/base_model_executor_helpers.h
@@ -2,21 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_BASE_MODEL_EXECUTOR_HELPERS_H_
-#define COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_BASE_MODEL_EXECUTOR_HELPERS_H_
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_BASE_MODEL_EXECUTOR_HELPERS_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_BASE_MODEL_EXECUTOR_HELPERS_H_
+#include <memory>
+#include <vector>
+
+#include "base/check.h"
#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/base_task_api.h"
namespace optimization_guide {
-class OptimizationGuideDecider;
-
template <class OutputType, class... InputTypes>
class InferenceDelegate {
public:
// Preprocesses |args| into |input_tensors|.
- virtual void Preprocess(const std::vector<TfLiteTensor*>& input_tensors,
- InputTypes... args) = 0;
+ virtual absl::Status Preprocess(
+ const std::vector<TfLiteTensor*>& input_tensors,
+ InputTypes... args) = 0;
// Postprocesses |output_tensors| into the desired |OutputType|.
virtual OutputType Postprocess(
@@ -39,19 +42,18 @@ class GenericModelExecutionTask
// Executes the model using |args| and returns the output if the model was
// executed successfully.
- base::Optional<OutputType> Execute(InputTypes... args) {
+ absl::optional<OutputType> Execute(InputTypes... args) {
tflite::support::StatusOr<OutputType> maybe_output = this->Infer(args...);
if (maybe_output.ok())
return maybe_output.value();
- return base::nullopt;
+ return absl::nullopt;
}
protected:
// BaseTaskApi:
absl::Status Preprocess(const std::vector<TfLiteTensor*>& input_tensors,
InputTypes... args) override {
- delegate_->Preprocess(input_tensors, args...);
- return absl::OkStatus();
+ return delegate_->Preprocess(input_tensors, args...);
}
tflite::support::StatusOr<OutputType> Postprocess(
const std::vector<const TfLiteTensor*>& output_tensors,
@@ -66,4 +68,4 @@ class GenericModelExecutionTask
} // namespace optimization_guide
-#endif // COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_BASE_MODEL_EXECUTOR_HELPERS_H_
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_BASE_MODEL_EXECUTOR_HELPERS_H_
diff --git a/chromium/components/optimization_guide/content/browser/bert_model_executor.cc b/chromium/components/optimization_guide/core/bert_model_executor.cc
index 6c404f2ad9a..734dd4efe33 100644
--- a/chromium/components/optimization_guide/content/browser/bert_model_executor.cc
+++ b/chromium/components/optimization_guide/core/bert_model_executor.cc
@@ -2,31 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/optimization_guide/content/browser/bert_model_executor.h"
+#include "components/optimization_guide/core/bert_model_executor.h"
+#include "base/trace_event/trace_event.h"
+#include "components/optimization_guide/core/optimization_guide_util.h"
#include "components/optimization_guide/core/tflite_op_resolver.h"
#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/text/nlclassifier/bert_nl_classifier.h"
namespace optimization_guide {
BertModelExecutor::BertModelExecutor(
- OptimizationGuideDecider* decider,
- proto::OptimizationTarget optimization_target,
- const base::Optional<proto::Any>& model_metadata,
- const scoped_refptr<base::SequencedTaskRunner>& model_execution_task_runner)
- : OptimizationTargetModelExecutor<std::vector<tflite::task::core::Category>,
- const std::string&>(
- decider,
- optimization_target,
- model_metadata,
- model_execution_task_runner) {}
-
+ proto::OptimizationTarget optimization_target)
+ : optimization_target_(optimization_target) {}
BertModelExecutor::~BertModelExecutor() = default;
-base::Optional<std::vector<tflite::task::core::Category>>
-BertModelExecutor::Execute(
- BertModelExecutor::ModelExecutionTask* execution_task,
- const std::string& input) {
+absl::optional<std::vector<tflite::task::core::Category>>
+BertModelExecutor::Execute(ModelExecutionTask* execution_task,
+ const std::string& input) {
+ TRACE_EVENT2("browser", "BertModelExecutor::Execute", "optimization_target",
+ GetStringNameForOptimizationTarget(optimization_target_),
+ "input_length", input.size());
return static_cast<tflite::task::text::nlclassifier::BertNLClassifier*>(
execution_task)
->Classify(input);
@@ -45,4 +40,19 @@ BertModelExecutor::BuildModelExecutionTask(base::MemoryMappedFile* model_file) {
return nullptr;
}
+BertModelExecutorHandle::BertModelExecutorHandle(
+ OptimizationGuideModelProvider* model_provider,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ proto::OptimizationTarget optimization_target,
+ const absl::optional<proto::Any>& model_metadata)
+ : ModelHandler<std::vector<tflite::task::core::Category>,
+ const std::string&>(
+ model_provider,
+ background_task_runner,
+ std::make_unique<BertModelExecutor>(optimization_target),
+ optimization_target,
+ model_metadata) {}
+
+BertModelExecutorHandle::~BertModelExecutorHandle() = default;
+
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/bert_model_executor.h b/chromium/components/optimization_guide/core/bert_model_executor.h
new file mode 100644
index 00000000000..abef8428c81
--- /dev/null
+++ b/chromium/components/optimization_guide/core/bert_model_executor.h
@@ -0,0 +1,57 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_BERT_MODEL_EXECUTOR_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_BERT_MODEL_EXECUTOR_H_
+
+#include "components/optimization_guide/core/model_executor.h"
+#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/category.h"
+
+namespace optimization_guide {
+
+// An implementation of a ModelHandler that executes BERT models.
+//
+// Note that sentencepiece tokenizers are not supported by Chromium's copy of
+// the TFLite Support library.
+class BertModelExecutorHandle
+ : public ModelHandler<std::vector<tflite::task::core::Category>,
+ const std::string&> {
+ public:
+ BertModelExecutorHandle(
+ OptimizationGuideModelProvider* model_provider,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ proto::OptimizationTarget optimization_target,
+ const absl::optional<proto::Any>& model_metadata);
+ ~BertModelExecutorHandle() override;
+
+ BertModelExecutorHandle(const BertModelExecutorHandle&) = delete;
+ BertModelExecutorHandle& operator=(const BertModelExecutorHandle&) = delete;
+};
+
+// A full implementation of a ModelExecutor that executes BERT models.
+class BertModelExecutor
+ : public ModelExecutor<std::vector<tflite::task::core::Category>,
+ const std::string&> {
+ public:
+ explicit BertModelExecutor(proto::OptimizationTarget optimization_target);
+ ~BertModelExecutor() override;
+
+ using ModelExecutionTask =
+ tflite::task::core::BaseTaskApi<std::vector<tflite::task::core::Category>,
+ const std::string&>;
+
+ // ModelExecutor:
+ absl::optional<std::vector<tflite::task::core::Category>> Execute(
+ ModelExecutionTask* execution_task,
+ const std::string& input) override;
+ std::unique_ptr<ModelExecutionTask> BuildModelExecutionTask(
+ base::MemoryMappedFile* model_file) override;
+
+ private:
+ const proto::OptimizationTarget optimization_target_;
+};
+
+} // namespace optimization_guide
+
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_BERT_MODEL_EXECUTOR_H_
diff --git a/chromium/components/optimization_guide/content/browser/bert_model_executor_unittest.cc b/chromium/components/optimization_guide/core/bert_model_executor_unittest.cc
index f51bfc5275d..1a756e528dd 100644
--- a/chromium/components/optimization_guide/content/browser/bert_model_executor_unittest.cc
+++ b/chromium/components/optimization_guide/core/bert_model_executor_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/optimization_guide/content/browser/bert_model_executor.h"
+#include "components/optimization_guide/core/bert_model_executor.h"
#include "base/path_service.h"
-#include "components/optimization_guide/content/browser/test_optimization_guide_decider.h"
-#include "content/public/test/browser_task_environment.h"
+#include "base/test/task_environment.h"
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace optimization_guide {
@@ -14,25 +14,25 @@ namespace optimization_guide {
class BertModelExecutorTest : public testing::Test {
public:
void SetUp() override {
- optimization_guide_decider_ =
- std::make_unique<TestOptimizationGuideDecider>();
+ optimization_guide_model_provider_ =
+ std::make_unique<TestOptimizationGuideModelProvider>();
}
- void CreateModelExecutor() {
- if (model_executor_)
- model_executor_.reset();
+ void TearDown() override {
+ model_executor_handle_.reset();
+ task_environment_.RunUntilIdle();
+ }
- model_executor_ = std::make_unique<BertModelExecutor>(
- optimization_guide_decider_.get(),
+ void CreateModelExecutor() {
+ model_executor_handle_ = std::make_unique<BertModelExecutorHandle>(
+ optimization_guide_model_provider_.get(),
+ task_environment_.GetMainThreadTaskRunner(),
proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
- /*model_metadata=*/base::nullopt,
- task_environment_.GetMainThreadTaskRunner());
+ /*model_metadata=*/absl::nullopt);
}
- void ResetModelExecutor() { model_executor_.reset(); }
-
void PushModelFileToModelExecutor(bool is_valid) {
- DCHECK(model_executor_);
+ DCHECK(model_executor_handle_);
base::FilePath source_root_dir;
base::PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir);
@@ -43,36 +43,38 @@ class BertModelExecutorTest : public testing::Test {
model_file_path =
is_valid ? model_file_path.AppendASCII("bert_page_topics_model.tflite")
: model_file_path.AppendASCII("simple_test.tflite");
- model_executor_->OnModelFileUpdated(
- proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, base::nullopt,
+ model_executor_handle_->OnModelFileUpdated(
+ proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD, absl::nullopt,
model_file_path);
task_environment_.RunUntilIdle();
}
- BertModelExecutor* model_executor() { return model_executor_.get(); }
+ BertModelExecutorHandle* model_executor_handle() {
+ return model_executor_handle_.get();
+ }
private:
- content::BrowserTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
- std::unique_ptr<TestOptimizationGuideDecider> optimization_guide_decider_;
- std::unique_ptr<BertModelExecutor> model_executor_;
+ std::unique_ptr<TestOptimizationGuideModelProvider>
+ optimization_guide_model_provider_;
+ std::unique_ptr<BertModelExecutorHandle> model_executor_handle_;
};
TEST_F(BertModelExecutorTest, ValidBertModel) {
CreateModelExecutor();
PushModelFileToModelExecutor(/*is_valid=*/true);
- EXPECT_TRUE(model_executor()->HasLoadedModel());
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
std::string input = "some text";
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
- model_executor()->ExecuteModelWithInput(
+ model_executor_handle()->ExecuteModelWithInput(
base::BindOnce(
[](base::RunLoop* run_loop,
- const base::Optional<std::vector<tflite::task::core::Category>>&
+ const absl::optional<std::vector<tflite::task::core::Category>>&
output) {
EXPECT_TRUE(output.has_value());
-
run_loop->Quit();
},
run_loop.get()),
@@ -84,9 +86,21 @@ TEST_F(BertModelExecutorTest, InvalidBertModel) {
CreateModelExecutor();
PushModelFileToModelExecutor(/*is_valid=*/false);
- EXPECT_FALSE(model_executor()->HasLoadedModel());
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
- ResetModelExecutor();
+ std::string input = "some text";
+ std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
+ model_executor_handle()->ExecuteModelWithInput(
+ base::BindOnce(
+ [](base::RunLoop* run_loop,
+ const absl::optional<std::vector<tflite::task::core::Category>>&
+ output) {
+ EXPECT_FALSE(output.has_value());
+ run_loop->Quit();
+ },
+ run_loop.get()),
+ input);
+ run_loop->Run();
}
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/command_line_top_host_provider.cc b/chromium/components/optimization_guide/core/command_line_top_host_provider.cc
index 4d274953e41..baa31160abc 100644
--- a/chromium/components/optimization_guide/core/command_line_top_host_provider.cc
+++ b/chromium/components/optimization_guide/core/command_line_top_host_provider.cc
@@ -5,15 +5,15 @@
#include "components/optimization_guide/core/command_line_top_host_provider.h"
#include "base/memory/ptr_util.h"
-#include "base/optional.h"
#include "components/optimization_guide/core/optimization_guide_switches.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
// static
std::unique_ptr<CommandLineTopHostProvider>
CommandLineTopHostProvider::CreateIfEnabled() {
- base::Optional<std::vector<std::string>> top_hosts =
+ absl::optional<std::vector<std::string>> top_hosts =
switches::ParseHintsFetchOverrideFromCommandLine();
if (top_hosts) {
// Note: wrap_unique is used because the constructor is private.
diff --git a/chromium/components/optimization_guide/core/hint_cache.cc b/chromium/components/optimization_guide/core/hint_cache.cc
index cfe27331e99..227e0d603b9 100644
--- a/chromium/components/optimization_guide/core/hint_cache.cc
+++ b/chromium/components/optimization_guide/core/hint_cache.cc
@@ -108,6 +108,32 @@ void HintCache::UpdateFetchedHints(
}
}
+void HintCache::RemoveHintsForURLs(const base::flat_set<GURL>& urls) {
+ for (const GURL& url : urls) {
+ auto it = url_keyed_hint_cache_.Get(url.spec());
+ if (it != url_keyed_hint_cache_.end()) {
+ url_keyed_hint_cache_.Erase(it);
+ }
+ }
+}
+
+void HintCache::RemoveHintsForHosts(base::OnceClosure on_success,
+ const base::flat_set<std::string>& hosts) {
+ for (const std::string& host : hosts) {
+ auto it = host_keyed_cache_.Get(host);
+ if (it != host_keyed_cache_.end()) {
+ host_keyed_cache_.Erase(it);
+ }
+ }
+
+ if (optimization_guide_store_) {
+ optimization_guide_store_->RemoveFetchedHintsByKey(std::move(on_success),
+ hosts);
+ return;
+ }
+ std::move(on_success).Run();
+}
+
void HintCache::PurgeExpiredFetchedHints() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -269,6 +295,7 @@ base::Time HintCache::GetFetchedHintsUpdateTime() const {
void HintCache::OnStoreInitialized(base::OnceClosure callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(optimization_guide_store_);
+
std::move(callback).Run();
}
diff --git a/chromium/components/optimization_guide/core/hint_cache.h b/chromium/components/optimization_guide/core/hint_cache.h
index be1a2f6efa7..963c8d0d8b9 100644
--- a/chromium/components/optimization_guide/core/hint_cache.h
+++ b/chromium/components/optimization_guide/core/hint_cache.h
@@ -11,12 +11,12 @@
#include "base/containers/mru_cache.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/clock.h"
#include "components/optimization_guide/core/memory_hint.h"
#include "components/optimization_guide/core/optimization_guide_store.h"
#include "components/optimization_guide/proto/hints.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -126,6 +126,17 @@ class HintCache {
// the entry is empty. If a hint exists but is expired, it returns false.
bool HasURLKeyedEntryForURL(const GURL& url);
+ // Removes any URL-keyed hints that are in |urls|.
+ void RemoveHintsForURLs(const base::flat_set<GURL>& urls);
+
+ // Removes any host-keyed hints that are in |hosts|. Note that this will also
+ // remove any persisted hints from |hint_store()|. |on_success| will be called
+ // when the operation completes successfully. If the operation does not
+ // complete successfully, the callback will not be run so calling code must
+ // not expect it be called in every circumstance.
+ void RemoveHintsForHosts(base::OnceClosure on_success,
+ const base::flat_set<std::string>& hosts);
+
// Verifies and processes |hints| and moves the ones it supports into
// |update_data| and caches any valid URL keyed hints.
//
diff --git a/chromium/components/optimization_guide/core/hint_cache_unittest.cc b/chromium/components/optimization_guide/core/hint_cache_unittest.cc
index c300a647547..a1089520bab 100644
--- a/chromium/components/optimization_guide/core/hint_cache_unittest.cc
+++ b/chromium/components/optimization_guide/core/hint_cache_unittest.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
@@ -22,6 +21,7 @@
#include "components/optimization_guide/proto/hint_cache.pb.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace optimization_guide {
@@ -129,8 +129,8 @@ class HintCacheTest : public ProtoDatabaseProviderTestBase,
const proto::Hint* GetLoadedHint() const { return loaded_hint_; }
proto::Hint CreateHintForURL(
- const GURL url,
- base::Optional<int> cache_duration_in_secs = base::Optional<int>()) {
+ const GURL& url,
+ absl::optional<int> cache_duration_in_secs = absl::optional<int>()) {
proto::Hint hint;
hint.set_key(url.spec());
hint.set_key_representation(proto::FULL_URL);
@@ -1011,6 +1011,72 @@ TEST_P(HintCacheTest, ProcessHintsWithPageHintsAndUpdateData) {
}
}
+TEST_P(HintCacheTest, RemoveHintsForURLs) {
+ const int kMemoryCacheSize = 5;
+ CreateAndInitializeHintCache(kMemoryCacheSize);
+
+ int cache_duration_in_secs = 60;
+ std::string host = "host.com";
+ GURL url("https://bar.com/r/baz");
+
+ std::unique_ptr<proto::GetHintsResponse> get_hints_response =
+ std::make_unique<proto::GetHintsResponse>();
+
+ *(get_hints_response->add_hints()) =
+ CreateHintForURL(url, cache_duration_in_secs);
+
+ proto::Hint* hint = get_hints_response->add_hints();
+ hint->set_key_representation(proto::HOST);
+ hint->set_key(host);
+ proto::PageHint* page_hint = hint->add_page_hints();
+ page_hint->set_page_pattern("page pattern");
+
+ UpdateFetchedHintsAndWait(std::move(get_hints_response), base::Time().Now(),
+ {host}, {url});
+ EXPECT_TRUE(are_fetched_hints_updated());
+ EXPECT_TRUE(hint_cache()->HasHint(host));
+ EXPECT_TRUE(hint_cache()->HasURLKeyedEntryForURL(url));
+
+ hint_cache()->RemoveHintsForURLs({url, GURL(host)});
+ EXPECT_TRUE(hint_cache()->HasHint(host));
+ EXPECT_FALSE(hint_cache()->HasURLKeyedEntryForURL(url));
+}
+
+TEST_P(HintCacheTest, RemoveHintsForHosts) {
+ const int kMemoryCacheSize = 5;
+ CreateAndInitializeHintCache(kMemoryCacheSize);
+
+ int cache_duration_in_secs = 60;
+ std::string host = "host.com";
+ GURL url("https://bar.com/r/baz");
+
+ std::unique_ptr<proto::GetHintsResponse> get_hints_response =
+ std::make_unique<proto::GetHintsResponse>();
+
+ *(get_hints_response->add_hints()) =
+ CreateHintForURL(url, cache_duration_in_secs);
+
+ proto::Hint* hint = get_hints_response->add_hints();
+ hint->set_key_representation(proto::HOST);
+ hint->set_key(host);
+ proto::PageHint* page_hint = hint->add_page_hints();
+ page_hint->set_page_pattern("page pattern");
+
+ UpdateFetchedHintsAndWait(std::move(get_hints_response), base::Time().Now(),
+ {host}, {url});
+ EXPECT_TRUE(are_fetched_hints_updated());
+ EXPECT_TRUE(hint_cache()->HasHint(host));
+ EXPECT_TRUE(hint_cache()->HasURLKeyedEntryForURL(url));
+
+ std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
+ hint_cache()->RemoveHintsForHosts(run_loop->QuitClosure(),
+ {url.spec(), host});
+ run_loop->Run();
+
+ EXPECT_FALSE(hint_cache()->HasHint(host));
+ EXPECT_TRUE(hint_cache()->HasURLKeyedEntryForURL(url));
+}
+
} // namespace
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/hints_fetcher.cc b/chromium/components/optimization_guide/core/hints_fetcher.cc
index fa4d393a1b4..6fbe7c1edf6 100644
--- a/chromium/components/optimization_guide/core/hints_fetcher.cc
+++ b/chromium/components/optimization_guide/core/hints_fetcher.cc
@@ -98,7 +98,7 @@ HintsFetcher::HintsFetcher(
HintsFetcher::~HintsFetcher() {
if (active_url_loader_) {
if (hints_fetched_callback_)
- std::move(hints_fetched_callback_).Run(base::nullopt);
+ std::move(hints_fetched_callback_).Run(absl::nullopt);
base::UmaHistogramExactLinear(
"OptimizationGuide.HintsFetcher.GetHintsRequest."
"ActiveRequestCanceled." +
@@ -136,7 +136,7 @@ bool HintsFetcher::WasHostCoveredByFetch(PrefService* pref_service,
DictionaryPrefUpdate hosts_fetched(
pref_service, prefs::kHintsFetcherHostsSuccessfullyFetched);
- base::Optional<double> value =
+ absl::optional<double> value =
hosts_fetched->FindDoubleKey(HashHostForDictionary(host));
if (!value)
return false;
@@ -146,6 +146,25 @@ bool HintsFetcher::WasHostCoveredByFetch(PrefService* pref_service,
return host_valid_time > time_clock->Now();
}
+// static
+void HintsFetcher::ClearSingleFetchedHost(PrefService* pref_service,
+ const std::string& host) {
+ DictionaryPrefUpdate hosts_fetched_list(
+ pref_service, prefs::kHintsFetcherHostsSuccessfullyFetched);
+ hosts_fetched_list->Remove(HashHostForDictionary(host), nullptr);
+}
+
+// static
+void HintsFetcher::AddFetchedHostForTesting(PrefService* pref_service,
+ const std::string& host,
+ base::Time time) {
+ DictionaryPrefUpdate hosts_fetched_list(
+ pref_service, prefs::kHintsFetcherHostsSuccessfullyFetched);
+ hosts_fetched_list->SetDoubleKey(
+ HashHostForDictionary(host),
+ time.ToDeltaSinceWindowsEpoch().InSecondsF());
+}
+
bool HintsFetcher::FetchOptimizationGuideServiceHints(
const std::vector<std::string>& hosts,
const std::vector<GURL>& urls,
@@ -160,14 +179,14 @@ bool HintsFetcher::FetchOptimizationGuideServiceHints(
if (network_connection_tracker_->IsOffline()) {
RecordRequestStatusHistogram(request_context,
HintsFetcherRequestStatus::kNetworkOffline);
- std::move(hints_fetched_callback).Run(base::nullopt);
+ std::move(hints_fetched_callback).Run(absl::nullopt);
return false;
}
if (active_url_loader_) {
RecordRequestStatusHistogram(request_context,
HintsFetcherRequestStatus::kFetcherBusy);
- std::move(hints_fetched_callback).Run(base::nullopt);
+ std::move(hints_fetched_callback).Run(absl::nullopt);
return false;
}
@@ -177,7 +196,7 @@ bool HintsFetcher::FetchOptimizationGuideServiceHints(
if (filtered_hosts.empty() && valid_urls.empty()) {
RecordRequestStatusHistogram(
request_context, HintsFetcherRequestStatus::kNoHostsOrURLsToFetch);
- std::move(hints_fetched_callback).Run(base::nullopt);
+ std::move(hints_fetched_callback).Run(absl::nullopt);
return false;
}
@@ -190,7 +209,7 @@ bool HintsFetcher::FetchOptimizationGuideServiceHints(
RecordRequestStatusHistogram(
request_context,
HintsFetcherRequestStatus::kNoSupportedOptimizationTypes);
- std::move(hints_fetched_callback).Run(base::nullopt);
+ std::move(hints_fetched_callback).Run(absl::nullopt);
return false;
}
@@ -333,7 +352,7 @@ void HintsFetcher::HandleResponse(const std::string& get_hints_response_data,
hosts_fetched_.clear();
RecordRequestStatusHistogram(request_context_,
HintsFetcherRequestStatus::kResponseError);
- std::move(hints_fetched_callback_).Run(base::nullopt);
+ std::move(hints_fetched_callback_).Run(absl::nullopt);
}
}
@@ -364,11 +383,11 @@ void HintsFetcher::UpdateHostsSuccessfullyFetched(
// 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() >
+ if (hosts_fetched_list->DictSize() + hosts_fetched_.size() >
features::MaxHostsForRecordingSuccessfullyCovered()) {
entries_to_remove.clear();
size_t num_entries_to_remove =
- hosts_fetched_list->size() + hosts_fetched_.size() -
+ hosts_fetched_list->DictSize() + hosts_fetched_.size() -
features::MaxHostsForRecordingSuccessfullyCovered();
for (const auto& it : hosts_fetched_list->DictItems()) {
if (entries_to_remove.size() >= num_entries_to_remove)
@@ -387,7 +406,7 @@ void HintsFetcher::UpdateHostsSuccessfullyFetched(
HashHostForDictionary(host),
host_invalid_time.ToDeltaSinceWindowsEpoch().InSecondsF());
}
- DCHECK_LE(hosts_fetched_list->size(),
+ DCHECK_LE(hosts_fetched_list->DictSize(),
features::MaxHostsForRecordingSuccessfullyCovered());
hosts_fetched_.clear();
}
@@ -434,7 +453,7 @@ std::vector<std::string> HintsFetcher::GetSizeLimitedHostsDueForHintsRefresh(
bool host_hints_due_for_refresh = true;
- base::Optional<double> value =
+ absl::optional<double> value =
hosts_fetched->FindDoubleKey(HashHostForDictionary(host));
if (value && optimization_guide::features::ShouldPersistHintsToDisk()) {
base::Time host_valid_time = base::Time::FromDeltaSinceWindowsEpoch(
diff --git a/chromium/components/optimization_guide/core/hints_fetcher.h b/chromium/components/optimization_guide/core/hints_fetcher.h
index d75d9c6a829..9ff469727a0 100644
--- a/chromium/components/optimization_guide/core/hints_fetcher.h
+++ b/chromium/components/optimization_guide/core/hints_fetcher.h
@@ -13,11 +13,11 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "components/optimization_guide/proto/hints.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
class PrefService;
@@ -59,7 +59,7 @@ enum class HintsFetcherRequestStatus {
// 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>>)>;
+ absl::optional<std::unique_ptr<proto::GetHintsResponse>>)>;
// A class to handle requests for optimization hints from a remote Optimization
// Guide Service.
@@ -101,6 +101,16 @@ class HintsFetcher {
// HintsFetcherHostsSuccessfullyFetched dictionary pref.
static void ClearHostsSuccessfullyFetched(PrefService* pref_service);
+ // Clear the given host from the HintsFetcherHostsSuccessfullyFetched
+ // dictionary pref.
+ static void ClearSingleFetchedHost(PrefService* pref_service,
+ const std::string& host);
+
+ // Adds a fetched host at the given time. Used only for testing.
+ static void AddFetchedHostForTesting(PrefService* pref_service,
+ const std::string& host,
+ base::Time time);
+
// Return whether the host was covered by a hints fetch and any returned hints
// would not have expired.
static bool WasHostCoveredByFetch(PrefService* pref_service,
diff --git a/chromium/components/optimization_guide/core/hints_fetcher_unittest.cc b/chromium/components/optimization_guide/core/hints_fetcher_unittest.cc
index 293df694de1..dc4a5533db7 100644
--- a/chromium/components/optimization_guide/core/hints_fetcher_unittest.cc
+++ b/chromium/components/optimization_guide/core/hints_fetcher_unittest.cc
@@ -9,7 +9,6 @@
#include "base/callback.h"
#include "base/macros.h"
#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"
@@ -28,6 +27,7 @@
#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"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
@@ -62,7 +62,7 @@ class HintsFetcherTest : public testing::Test,
~HintsFetcherTest() override = default;
- void OnHintsFetched(base::Optional<std::unique_ptr<proto::GetHintsResponse>>
+ void OnHintsFetched(absl::optional<std::unique_ptr<proto::GetHintsResponse>>
get_hints_response) {
if (get_hints_response)
hints_fetched_ = true;
@@ -392,7 +392,7 @@ TEST_P(HintsFetcherTest, HintsFetchSuccessfulHostsRecorded) {
const base::DictionaryValue* hosts_fetched = pref_service()->GetDictionary(
prefs::kHintsFetcherHostsSuccessfullyFetched);
- base::Optional<double> value;
+ absl::optional<double> value;
for (const std::string& host : hosts) {
value = hosts_fetched->FindDoubleKey(HashHostForDictionary(host));
// This reduces the necessary precision for the check on the expiry time for
@@ -451,6 +451,33 @@ TEST_P(HintsFetcherTest, HintsFetchClearHostsSuccessfullyFetched) {
}
}
+TEST_P(HintsFetcherTest, HintsFetchClearSingleFetchedHost) {
+ std::vector<std::string> hosts{"host1.com", "host2.com"};
+ std::string response_content;
+
+ EXPECT_TRUE(FetchHints(hosts, {} /* urls */));
+ VerifyHasPendingFetchRequests();
+ EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
+ EXPECT_TRUE(hints_fetched());
+
+ if (!ShouldPersistHintsToDisk())
+ return;
+
+ const base::DictionaryValue* hosts_fetched = pref_service()->GetDictionary(
+ prefs::kHintsFetcherHostsSuccessfullyFetched);
+ for (const std::string& host : hosts) {
+ EXPECT_TRUE(hosts_fetched->FindDoubleKey(HashHostForDictionary(host)));
+ }
+
+ HintsFetcher::ClearSingleFetchedHost(pref_service(), "host1.com");
+ hosts_fetched = pref_service()->GetDictionary(
+ prefs::kHintsFetcherHostsSuccessfullyFetched);
+
+ EXPECT_FALSE(
+ hosts_fetched->FindDoubleKey(HashHostForDictionary("host1.com")));
+ EXPECT_TRUE(hosts_fetched->FindDoubleKey(HashHostForDictionary("host2.com")));
+}
+
TEST_P(HintsFetcherTest, HintsFetcherHostsCovered) {
if (!ShouldPersistHintsToDisk())
return;
@@ -492,7 +519,7 @@ TEST_P(HintsFetcherTest, HintsFetcherCoveredHostExpired) {
// pref as they have expired.
DictionaryPrefUpdate hosts_fetched(
pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
- EXPECT_EQ(2u, hosts_fetched->size());
+ EXPECT_EQ(2u, hosts_fetched->DictSize());
// Navigations to the valid hosts should be recorded as successfully
// covered.
@@ -508,7 +535,7 @@ TEST_P(HintsFetcherTest, HintsFetcherHostNotCovered) {
SeedCoveredHosts(hosts, host_invalid_time);
DictionaryPrefUpdate hosts_fetched(
pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
- EXPECT_EQ(2u, hosts_fetched->size());
+ EXPECT_EQ(2u, hosts_fetched->DictSize());
EXPECT_TRUE(WasHostCoveredByFetch(hosts[0]));
EXPECT_TRUE(WasHostCoveredByFetch(hosts[1]));
@@ -537,7 +564,7 @@ TEST_P(HintsFetcherTest, HintsFetcherRemoveExpiredOnSuccessfullyFetched) {
// have expired.
DictionaryPrefUpdate hosts_fetched(
pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
- EXPECT_EQ(2u, hosts_fetched->size());
+ EXPECT_EQ(2u, hosts_fetched->DictSize());
EXPECT_FALSE(WasHostCoveredByFetch(hosts_expired[0]));
EXPECT_FALSE(WasHostCoveredByFetch(hosts_expired[1]));
@@ -572,7 +599,7 @@ TEST_P(HintsFetcherTest, HintsFetcherSuccessfullyFetchedHostsFull) {
// Navigations to both the extra hosts should be recorded.
DictionaryPrefUpdate hosts_fetched(
pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
- EXPECT_EQ(200u, hosts_fetched->size());
+ EXPECT_EQ(200u, hosts_fetched->DictSize());
EXPECT_TRUE(WasHostCoveredByFetch(extra_hosts[0]));
EXPECT_TRUE(WasHostCoveredByFetch(extra_hosts[1]));
@@ -606,7 +633,7 @@ TEST_P(HintsFetcherTest, MaxHostsForOptimizationGuideServiceHintsFetch) {
DictionaryPrefUpdate hosts_fetched(
pref_service(), prefs::kHintsFetcherHostsSuccessfullyFetched);
- EXPECT_EQ(max_hosts_in_fetch_request, hosts_fetched->size());
+ EXPECT_EQ(max_hosts_in_fetch_request, hosts_fetched->DictSize());
EXPECT_EQ(all_hosts.size(), max_hosts_in_fetch_request + 5);
for (size_t i = 0; i < max_hosts_in_fetch_request; ++i) {
diff --git a/chromium/components/optimization_guide/core/hints_processing_util.cc b/chromium/components/optimization_guide/core/hints_processing_util.cc
index 511c02513a9..873c7a2ec75 100644
--- a/chromium/components/optimization_guide/core/hints_processing_util.cc
+++ b/chromium/components/optimization_guide/core/hints_processing_util.cc
@@ -7,6 +7,7 @@
#include <string>
#include "base/containers/flat_set.h"
+#include "base/hash/hash.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/stringprintf.h"
#include "components/optimization_guide/core/optimization_guide_features.h"
diff --git a/chromium/components/optimization_guide/core/insertion_ordered_set.h b/chromium/components/optimization_guide/core/insertion_ordered_set.h
new file mode 100644
index 00000000000..6ba1f9ab5f6
--- /dev/null
+++ b/chromium/components/optimization_guide/core/insertion_ordered_set.h
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_INSERTION_ORDERED_SET_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_INSERTION_ORDERED_SET_H_
+
+#include <vector>
+
+#include "base/containers/flat_set.h"
+
+// Keeps a set of unique element, while preserving the insertion order. vector()
+// can be accessed to get the ordered elements.
+template <typename T>
+class InsertionOrderedSet {
+ public:
+ InsertionOrderedSet() = default;
+
+ void insert(const T& elem) {
+ auto ret = set_.insert(elem);
+ if (ret.second) {
+ // The element wasn't already in the container.
+ vector_.push_back(elem);
+ }
+ }
+
+ void clear() {
+ set_.clear();
+ vector_.clear();
+ }
+
+ bool empty() const { return vector_.empty(); }
+
+ const std::vector<T>& vector() { return vector_; }
+
+ const base::flat_set<T>& set() { return set_; }
+
+ private:
+ base::flat_set<T> set_;
+ std::vector<T> vector_;
+};
+
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_INSERTION_ORDERED_SET_H_
diff --git a/chromium/components/optimization_guide/core/insertion_ordered_set_unittest.cc b/chromium/components/optimization_guide/core/insertion_ordered_set_unittest.cc
new file mode 100644
index 00000000000..2463895b6a6
--- /dev/null
+++ b/chromium/components/optimization_guide/core/insertion_ordered_set_unittest.cc
@@ -0,0 +1,57 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/optimization_guide/core/insertion_ordered_set.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace optimization_guide {
+
+TEST(InsertionOrderedSetTest, InsertOneElement) {
+ InsertionOrderedSet<int> set;
+ set.insert(1);
+ EXPECT_EQ(1u, set.set().size());
+ EXPECT_EQ(1u, set.vector().size());
+ EXPECT_TRUE(set.set().contains(1));
+ EXPECT_EQ(1, set.vector()[0]);
+}
+
+TEST(InsertionOrderedSetTest, InsertTwoDistinctElements) {
+ InsertionOrderedSet<int> set;
+ set.insert(1);
+ set.insert(2);
+ EXPECT_EQ(2u, set.set().size());
+ EXPECT_EQ(2u, set.vector().size());
+ EXPECT_TRUE(set.set().contains(1));
+ EXPECT_TRUE(set.set().contains(2));
+ EXPECT_EQ(1, set.vector()[0]);
+ EXPECT_EQ(2, set.vector()[1]);
+}
+
+TEST(InsertionOrderedSetTest, InsertTwoIdenticalElements) {
+ InsertionOrderedSet<int> set;
+ set.insert(1);
+ set.insert(1);
+ EXPECT_EQ(1u, set.set().size());
+ EXPECT_EQ(1u, set.vector().size());
+ EXPECT_TRUE(set.set().contains(1));
+ EXPECT_EQ(1, set.vector()[0]);
+}
+
+TEST(InsertionOrderedSetTest, Empty) {
+ InsertionOrderedSet<int> set;
+ EXPECT_TRUE(set.empty());
+ set.insert(1);
+ EXPECT_FALSE(set.empty());
+}
+
+TEST(InsertionOrderedSetTest, Clear) {
+ InsertionOrderedSet<int> set;
+ set.insert(1);
+ EXPECT_FALSE(set.empty());
+ set.clear();
+ EXPECT_TRUE(set.empty());
+}
+
+} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/memory_hint.cc b/chromium/components/optimization_guide/core/memory_hint.cc
index 9ef15ef40ec..02fc5489ca3 100644
--- a/chromium/components/optimization_guide/core/memory_hint.cc
+++ b/chromium/components/optimization_guide/core/memory_hint.cc
@@ -6,12 +6,12 @@
namespace optimization_guide {
-MemoryHint::MemoryHint(const base::Optional<base::Time>& expiry_time,
+MemoryHint::MemoryHint(const absl::optional<base::Time>& expiry_time,
std::unique_ptr<proto::Hint> hint)
: expiry_time_(expiry_time), hint_(std::move(hint)) {}
MemoryHint::MemoryHint(const base::Time expiry_time, proto::Hint&& hint)
- : expiry_time_(base::Optional<base::Time>(expiry_time)),
+ : expiry_time_(absl::optional<base::Time>(expiry_time)),
hint_(std::make_unique<proto::Hint>(hint)) {}
MemoryHint::~MemoryHint() = default;
diff --git a/chromium/components/optimization_guide/core/memory_hint.h b/chromium/components/optimization_guide/core/memory_hint.h
index 84c9f8839dc..32d9431e972 100644
--- a/chromium/components/optimization_guide/core/memory_hint.h
+++ b/chromium/components/optimization_guide/core/memory_hint.h
@@ -5,17 +5,17 @@
#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_MEMORY_HINT_H_
#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_MEMORY_HINT_H_
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/optimization_guide/proto/hint_cache.pb.h"
#include "components/optimization_guide/proto/hints.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
// A representation of a hint to be used by in-memory caches.
class MemoryHint {
public:
- MemoryHint(const base::Optional<base::Time>& expiry_time,
+ MemoryHint(const absl::optional<base::Time>& expiry_time,
std::unique_ptr<proto::Hint> hint);
MemoryHint(base::Time expiry_time, proto::Hint&& hint);
MemoryHint(const MemoryHint&) = delete;
@@ -24,14 +24,14 @@ class MemoryHint {
// This value is not available if |hint_| was sourced from the Optimization
// Hints component. Otherwise, it is set.
- const base::Optional<base::Time> expiry_time() const { return expiry_time_; }
+ const absl::optional<base::Time> expiry_time() const { return expiry_time_; }
// It is the responsibility of the callers to avoid use-after-free references
// that may occur if the containing object is evicted from an in-memory
// cache.
optimization_guide::proto::Hint* hint() const { return hint_.get(); }
private:
- base::Optional<base::Time> expiry_time_;
+ absl::optional<base::Time> expiry_time_;
std::unique_ptr<proto::Hint> hint_;
};
diff --git a/chromium/components/optimization_guide/core/model_executor.h b/chromium/components/optimization_guide/core/model_executor.h
new file mode 100644
index 00000000000..a93d158732b
--- /dev/null
+++ b/chromium/components/optimization_guide/core/model_executor.h
@@ -0,0 +1,454 @@
+// Copyright 2021 The Chromium Authors. 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_CORE_MODEL_EXECUTOR_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_MODEL_EXECUTOR_H_
+
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/sequence_checker.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
+#include "components/optimization_guide/core/optimization_guide_enums.h"
+#include "components/optimization_guide/core/optimization_guide_features.h"
+#include "components/optimization_guide/core/optimization_guide_model_provider.h"
+#include "components/optimization_guide/core/optimization_guide_util.h"
+#include "components/optimization_guide/core/optimization_target_model_observer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/base_task_api.h"
+#include "third_party/tflite/src/tensorflow/lite/c/common.h"
+
+namespace optimization_guide {
+
+namespace {
+
+// Util class for recording the result of loading the detection model. The
+// result is recorded when it goes out of scope and its destructor is called.
+class ScopedModelExecutorLoadingResultRecorder {
+ public:
+ ScopedModelExecutorLoadingResultRecorder(
+ proto::OptimizationTarget optimization_target,
+ ModelExecutorLoadingState model_loading_state)
+ : optimization_target_(optimization_target),
+ model_loading_state_(model_loading_state),
+ start_time_(base::TimeTicks::Now()) {}
+
+ ~ScopedModelExecutorLoadingResultRecorder() {
+ base::UmaHistogramEnumeration(
+ "OptimizationGuide.ModelExecutor.ModelLoadingResult." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ optimization_target_),
+ model_loading_state_);
+
+ base::UmaHistogramTimes(
+ "OptimizationGuide.ModelExecutor.ModelLoadingDuration." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ optimization_target_),
+ base::TimeTicks::Now() - start_time_);
+ }
+
+ void set_model_loading_state(ModelExecutorLoadingState model_executor_state) {
+ model_loading_state_ = model_executor_state;
+ }
+
+ private:
+ proto::OptimizationTarget optimization_target_;
+ ModelExecutorLoadingState model_loading_state_;
+
+ // The time at which this instance was constructed.
+ const base::TimeTicks start_time_;
+};
+
+} // namespace
+
+// This class handles the execution, loading, unloading, and associated metrics
+// of machine learning models in Optimization Guide on a background thread. This
+// class is meant to be used and owned by an instance of |ModelHandler|. A
+// ModelExecutor must be passed to a ModelHandler's constructor, this design
+// allows the implementer of a ModelExecutor to define how the model is built
+// and executed.. See also base_model_executor.h and
+// base_model_executor_helpers.h in this directory for helpful derived classes.
+//
+// Lifetime: This class can be constructed on any thread but cannot do anything
+// useful until |InitializeAndMoveToBackgroundThread| is called. After that
+// method is called, all subsequent calls to this class must be made through the
+// |background_task_runner| that was passed to initialize. Furthermore, all
+// WeakPointers of this class must only be dereferenced on the background thread
+// as well. This in turn means that this class must be destroyed on the
+// background thread as well.
+template <class OutputType, class... InputTypes>
+class ModelExecutor {
+ public:
+ ModelExecutor() = default;
+ virtual ~ModelExecutor() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ }
+
+ // Should be called on the same sequence as the ctor, but once called |this|
+ // must only be used from a background thread/sequence.
+ void InitializeAndMoveToBackgroundThread(
+ proto::OptimizationTarget optimization_target,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ scoped_refptr<base::SequencedTaskRunner> reply_task_runner) {
+ DCHECK(!background_task_runner_);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_NE(optimization_target,
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN);
+
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+ optimization_target_ = optimization_target;
+ background_task_runner_ = background_task_runner;
+ reply_task_runner_ = reply_task_runner;
+ }
+
+ // Called when a model file is available to load. Depending on feature flags,
+ // the model may or may not be immediately loaded.
+ void UpdateModelFile(const base::FilePath& file_path) {
+ DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ ResetLoadedModel();
+
+ model_file_path_ = file_path;
+
+ if (!features::LoadModelFileForEachExecution()) {
+ LoadModelFile();
+ }
+ }
+
+ // Starts the execution of the model. When complete, |ui_callback_on_complete|
+ // will be run on the UI thread with the output of the model.
+ using ExecutionCallback =
+ base::OnceCallback<void(const absl::optional<OutputType>&)>;
+ void SendForExecution(ExecutionCallback ui_callback_on_complete,
+ base::TimeTicks start_time,
+ InputTypes... args) {
+ DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(reply_task_runner_);
+
+ base::TimeDelta task_scheduling_latency =
+ base::TimeTicks::Now() - start_time;
+ base::UmaHistogramMediumTimes(
+ "OptimizationGuide.ModelExecutor.TaskSchedulingLatency." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ optimization_target_),
+ task_scheduling_latency);
+
+ // Attempt to load the model file if it isn't loaded yet, fail if loading is
+ // unsuccessful or no model is available to load.
+ if (!loaded_model_ && !LoadModelFile()) {
+ reply_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(ui_callback_on_complete), absl::nullopt));
+ return;
+ }
+
+ if (last_execution_time_) {
+ // The max of this histogram is 3m since only the distribution and count
+ // of smaller values is important.
+ base::UmaHistogramMediumTimes(
+ "OptimizationGuide.ModelExecutor.TimeSincePreviousRun." +
+ GetStringNameForOptimizationTarget(optimization_target_),
+ base::TimeTicks::Now() - *last_execution_time_);
+ }
+ last_execution_time_ = base::TimeTicks::Now();
+
+ DCHECK(loaded_model_);
+ absl::optional<OutputType> output;
+ {
+ TRACE_EVENT1("browser", "OptGuideModelExecutor::Execute",
+ "OptimizationTarget",
+ optimization_guide::GetStringNameForOptimizationTarget(
+ optimization_target_));
+ output = Execute(loaded_model_.get(), args...);
+ }
+
+ DCHECK(ui_callback_on_complete);
+ reply_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(std::move(ui_callback_on_complete), output));
+
+ // If the model file should only be loaded for execution, then unload it
+ // from memory. This can be done in a PostTask since it may take a while
+ // for big models and isn't very important.
+ if (features::LoadModelFileForEachExecution()) {
+ background_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&ModelExecutor::ResetLoadedModel,
+ GetBackgroundWeakPtr()));
+ }
+ }
+
+ // IMPORTANT: These WeakPointers must only be dereferenced on the background
+ // thread.
+ base::WeakPtr<ModelExecutor> GetBackgroundWeakPtr() {
+ return background_weak_ptr_factory_.GetWeakPtr();
+ }
+
+ ModelExecutor(const ModelExecutor&) = delete;
+ ModelExecutor& operator=(const ModelExecutor&) = delete;
+
+ protected:
+ using ModelExecutionTask =
+ tflite::task::core::BaseTaskApi<OutputType, InputTypes...>;
+
+ // Executes the model using |execution_task| on |args|.
+ virtual absl::optional<OutputType> Execute(ModelExecutionTask* execution_task,
+ InputTypes... args) = 0;
+
+ // Builds a model execution task using |model_file|.
+ virtual std::unique_ptr<ModelExecutionTask> BuildModelExecutionTask(
+ base::MemoryMappedFile* model_file) = 0;
+
+ private:
+ void ResetLoadedModel() {
+ TRACE_EVENT1("browser", "OptGuideModelExecutor::ResetLoadedModel",
+ "OptimizationTarget",
+ optimization_guide::GetStringNameForOptimizationTarget(
+ optimization_target_));
+ DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ loaded_model_.reset();
+ model_fb_.reset();
+ }
+
+ // A true return value indicates the model was loaded successfully, false
+ // otherwise.
+ bool LoadModelFile() {
+ TRACE_EVENT1("browser", "OptGuideModelExecutor::LoadModelFile",
+ "OptimizationTarget",
+ optimization_guide::GetStringNameForOptimizationTarget(
+ optimization_target_));
+ DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ ScopedModelExecutorLoadingResultRecorder scoped_model_loading_recorder(
+ optimization_target_, ModelExecutorLoadingState::kModelFileInvalid);
+
+ ResetLoadedModel();
+
+ base::UmaHistogramBoolean(
+ "OptimizationGuide.ModelExecutor.ModelAvailableToLoad." +
+ GetStringNameForOptimizationTarget(optimization_target_),
+ !!model_file_path_);
+
+ if (!model_file_path_)
+ return false;
+
+ std::unique_ptr<base::MemoryMappedFile> model_fb =
+ std::make_unique<base::MemoryMappedFile>();
+ if (!model_fb->Initialize(*model_file_path_))
+ return false;
+ model_fb_ = std::move(model_fb);
+
+ loaded_model_ = BuildModelExecutionTask(model_fb_.get());
+ if (loaded_model_) {
+ scoped_model_loading_recorder.set_model_loading_state(
+ ModelExecutorLoadingState::kModelFileValidAndMemoryMapped);
+ }
+
+ return !!loaded_model_;
+ }
+
+ proto::OptimizationTarget optimization_target_ =
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN;
+
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
+
+ scoped_refptr<base::SequencedTaskRunner> reply_task_runner_;
+
+ // The time that the model was last executed. Logged in metrics for the second
+ // and following runs.
+ absl::optional<base::TimeTicks> last_execution_time_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+
+ // The model file path to be loaded. May be nullopt if no model has been
+ // downloaded yet.
+ absl::optional<base::FilePath> model_file_path_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+
+ // Note on lifetimes: |loaded_model_| and |model_fb_| both share the same
+ // lifetime, being set in |LoadModelFile()| and being destroyed in
+ // |ResetModelFile()|.
+
+ std::unique_ptr<ModelExecutionTask> loaded_model_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+
+ // This will only be non-null when |model_file_path_| is set, and while the
+ // model is loaded which is managed by a feature flag.
+ std::unique_ptr<base::MemoryMappedFile> model_fb_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ base::WeakPtrFactory<ModelExecutor> background_weak_ptr_factory_{this};
+};
+
+// This class owns and handles the execution of models on the UI thread. Derived
+// classes must provide an implementation of |ModelExecutor|
+// (see above) which is then owned by |this|. The passed executor will be called
+// and destroyed on a background thread, which is all handled by this class.
+template <class OutputType, class... InputTypes>
+class ModelHandler : public OptimizationTargetModelObserver {
+ public:
+ ModelHandler(OptimizationGuideModelProvider* model_provider,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ std::unique_ptr<ModelExecutor<OutputType, InputTypes...>>
+ background_executor,
+ proto::OptimizationTarget optimization_target,
+ const absl::optional<proto::Any>& model_metadata)
+ : model_provider_(model_provider),
+ optimization_target_(optimization_target),
+ background_executor_(std::move(background_executor)),
+ background_task_runner_(background_task_runner) {
+ DCHECK(model_provider_);
+ DCHECK(background_executor_);
+ DCHECK_NE(optimization_target_,
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN);
+
+ model_provider_->AddObserverForOptimizationTargetModel(
+ optimization_target_, model_metadata, this);
+ background_executor_->InitializeAndMoveToBackgroundThread(
+ optimization_target_, background_task_runner_,
+ base::SequencedTaskRunnerHandle::Get());
+ }
+ ~ModelHandler() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ model_provider_->RemoveObserverForOptimizationTargetModel(
+ optimization_target_, this);
+
+ // |background_executor_|'s WeakPtrs are used on the background thread, so
+ // that is also where the class must be destroyed.
+ background_task_runner_->DeleteSoon(FROM_HERE,
+ std::move(background_executor_));
+ }
+ ModelHandler(const ModelHandler&) = delete;
+ ModelHandler& operator=(const ModelHandler&) = delete;
+
+ // Executes the model using |input| and invokes |callback| on the UI thread
+ // when completed. Virtual for testing.
+ // TODO(crbug/1173328): Add a way to surface errors.
+ using ExecutionCallback =
+ base::OnceCallback<void(const absl::optional<OutputType>&)>;
+ virtual void ExecuteModelWithInput(ExecutionCallback callback,
+ InputTypes... input) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ base::TimeTicks now = base::TimeTicks::Now();
+
+ ExecutionCallback on_complete_callback =
+ base::BindOnce(&ModelHandler::OnExecutionCompleted, std::move(callback),
+ optimization_target_, now);
+ background_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &ModelExecutor<OutputType, InputTypes...>::SendForExecution,
+ background_executor_->GetBackgroundWeakPtr(),
+ std::move(on_complete_callback), now, input...));
+ }
+
+ // OptimizationTargetModelObserver:
+ void OnModelFileUpdated(proto::OptimizationTarget optimization_target,
+ const absl::optional<proto::Any>& model_metadata,
+ const base::FilePath& file_path) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (optimization_target_ != optimization_target)
+ return;
+
+ supported_features_for_loaded_model_ = model_metadata;
+ model_available_ = true;
+
+ background_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &ModelExecutor<OutputType, InputTypes...>::UpdateModelFile,
+ background_executor_->GetBackgroundWeakPtr(), file_path));
+ }
+
+ // Returns whether a model is available to be executed. Virtual for testing.
+ virtual bool ModelAvailable() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return model_available_;
+ }
+
+ // Returns the supported features for the loaded model, if the server provided
+ // any.
+ absl::optional<proto::Any> supported_features_for_loaded_model() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return supported_features_for_loaded_model_;
+ }
+
+ // Validates that |supported_features_for_loaded_model_| is of the same type
+ // and is parseable as |T|. Will return metadata if all checks pass.
+ template <
+ class T,
+ class = typename std::enable_if<
+ std::is_convertible<T*, google::protobuf::MessageLite*>{}>::type>
+ absl::optional<T> ParsedSupportedFeaturesForLoadedModel() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!supported_features_for_loaded_model_)
+ return absl::nullopt;
+ return ParsedAnyMetadata<T>(*supported_features_for_loaded_model_);
+ }
+
+ private:
+ // This is called by |background_executor_|. This method does not have to be
+ // static, but because it is stateless we've made it static so that we don't
+ // have to have this class support WeakPointers.
+ static void OnExecutionCompleted(
+ ExecutionCallback callback,
+ proto::OptimizationTarget optimization_target,
+ base::TimeTicks model_execute_start_time,
+ const absl::optional<OutputType>& output) {
+ if (!output) {
+ std::move(callback).Run(output);
+ return;
+ }
+
+ base::TimeDelta execution_time =
+ base::TimeTicks::Now() - model_execute_start_time;
+
+ base::UmaHistogramMediumTimes(
+ "OptimizationGuide.ModelExecutor.TaskExecutionLatency." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ optimization_target),
+ execution_time);
+ std::move(callback).Run(output);
+ }
+
+ // Not owned. Guaranteed to outlive |this|.
+ OptimizationGuideModelProvider* model_provider_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+
+ const proto::OptimizationTarget optimization_target_;
+
+ // The owned background executor.
+ std::unique_ptr<ModelExecutor<OutputType, InputTypes...>>
+ background_executor_;
+
+ // The background task runner. Note that whenever a task is posted here, the
+ // task takes a reference to the TaskRunner (in a cyclic dependency) so
+ // |base::Unretained| is not safe anywhere in this class or the
+ // |background_executor_|.
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
+
+ // Set in |OnModelFileUpdated|.
+ absl::optional<proto::Any> supported_features_for_loaded_model_
+ GUARDED_BY_CONTEXT(sequence_checker_);
+
+ // Set in |OnModelFileUpdated|.
+ bool model_available_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+};
+
+} // namespace optimization_guide
+
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_MODEL_EXECUTOR_H_
diff --git a/chromium/components/optimization_guide/content/browser/optimization_target_model_executor_unittest.cc b/chromium/components/optimization_guide/core/model_executor_unittest.cc
index 59763ae0a05..61e02ace53f 100644
--- a/chromium/components/optimization_guide/content/browser/optimization_target_model_executor_unittest.cc
+++ b/chromium/components/optimization_guide/core/model_executor_unittest.cc
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/optimization_guide/content/browser/optimization_target_model_executor.h"
+#include "components/optimization_guide/core/model_executor.h"
#include "base/path_service.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
-#include "components/optimization_guide/content/browser/base_model_executor.h"
-#include "components/optimization_guide/content/browser/test_optimization_guide_decider.h"
+#include "base/test/task_environment.h"
+#include "components/optimization_guide/core/base_model_executor.h"
#include "components/optimization_guide/core/optimization_guide_features.h"
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
#include "components/optimization_guide/proto/common_types.pb.h"
-#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/task_utils.h"
@@ -20,28 +20,14 @@ namespace optimization_guide {
class TestModelExecutor
: public BaseModelExecutor<std::vector<float>, const std::vector<float>&> {
public:
- // Feature team specifies their target and the features they support along
- // with a background task runner that has the appropriate properties for
- // executing models.
- TestModelExecutor(OptimizationGuideDecider* decider,
- const scoped_refptr<base::SequencedTaskRunner>& task_runner)
- : BaseModelExecutor<std::vector<float>, const std::vector<float>&>(
- decider,
- proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
- /*model_metadata=*/base::nullopt,
- task_runner) {}
+ TestModelExecutor() = default;
~TestModelExecutor() override = default;
- TestModelExecutor(const TestModelExecutor&) = delete;
- TestModelExecutor& operator=(const TestModelExecutor&) = delete;
-
- // There is a method on the base class that exposes the returned supported
- // features, if provided by the loaded model received from the server.
- // base::Optional<proto::Any> supported_features_for_loaded_model();
protected:
- void Preprocess(const std::vector<TfLiteTensor*>& input_tensors,
- const std::vector<float>& input) override {
+ absl::Status Preprocess(const std::vector<TfLiteTensor*>& input_tensors,
+ const std::vector<float>& input) override {
tflite::task::core::PopulateTensor<float>(input, input_tensors[0]);
+ return absl::OkStatus();
}
std::vector<float> Postprocess(
@@ -52,19 +38,40 @@ class TestModelExecutor
}
};
-class ModelObserverTracker : public TestOptimizationGuideDecider {
+class TestModelExecutorHandle
+ : public ModelHandler<std::vector<float>, const std::vector<float>&> {
+ public:
+ explicit TestModelExecutorHandle(
+ OptimizationGuideModelProvider* model_provider,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner)
+ : ModelHandler<std::vector<float>, const std::vector<float>&>(
+ model_provider,
+ background_task_runner,
+ std::make_unique<TestModelExecutor>(),
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
+ /*model_metadata=*/absl::nullopt) {}
+ ~TestModelExecutorHandle() override = default;
+ TestModelExecutorHandle(const TestModelExecutorHandle&) = delete;
+ TestModelExecutorHandle& operator=(const TestModelExecutorHandle&) = delete;
+
+ // There is a method on the base class that exposes the returned supported
+ // features, if provided by the loaded model received from the server.
+ // absl::optional<proto::Any> supported_features_for_loaded_model();
+};
+
+class ModelObserverTracker : public TestOptimizationGuideModelProvider {
public:
void AddObserverForOptimizationTargetModel(
proto::OptimizationTarget target,
- const base::Optional<proto::Any>& model_metadata,
+ const absl::optional<proto::Any>& model_metadata,
OptimizationTargetModelObserver* observer) override {
// Make sure we send what is expected based on
- // TestModelExecutor ctor.
+ // TestModelExecutorHandle ctor.
if (target !=
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD) {
return;
}
- if (model_metadata != base::nullopt)
+ if (model_metadata != absl::nullopt)
return;
add_observer_called_ = true;
@@ -89,10 +96,10 @@ class ModelObserverTracker : public TestOptimizationGuideDecider {
bool remove_observer_called_ = false;
};
-class BaseOptimizationTargetModelExecutorTest : public testing::Test {
+class BaseModelExecutorTest : public testing::Test {
public:
- BaseOptimizationTargetModelExecutorTest() = default;
- ~BaseOptimizationTargetModelExecutorTest() override = default;
+ BaseModelExecutorTest() = default;
+ ~BaseModelExecutorTest() override = default;
void SetUp() override {
base::FilePath source_root_dir;
@@ -106,29 +113,35 @@ class BaseOptimizationTargetModelExecutorTest : public testing::Test {
model_observer_tracker_ = std::make_unique<ModelObserverTracker>();
}
- void TearDown() override { model_executor_.reset(); }
+ void TearDown() override { ResetModelExecutor(); }
void CreateModelExecutor() {
- if (model_executor_)
- model_executor_.reset();
+ if (model_executor_handle_)
+ model_executor_handle_.reset();
- model_executor_ = std::make_unique<TestModelExecutor>(
+ model_executor_handle_ = std::make_unique<TestModelExecutorHandle>(
model_observer_tracker_.get(),
task_environment_.GetMainThreadTaskRunner());
}
- void ResetModelExecutor() { model_executor_.reset(); }
+ void ResetModelExecutor() {
+ model_executor_handle_.reset();
+ // Allow for the background class to be destroyed.
+ RunUntilIdle();
+ }
void PushModelFileToModelExecutor(
proto::OptimizationTarget optimization_target,
- const base::Optional<proto::Any>& model_metadata) {
- DCHECK(model_executor_);
- model_executor_->OnModelFileUpdated(optimization_target, model_metadata,
- model_file_path_);
+ const absl::optional<proto::Any>& model_metadata) {
+ DCHECK(model_executor_handle_);
+ model_executor_handle_->OnModelFileUpdated(
+ optimization_target, model_metadata, model_file_path_);
RunUntilIdle();
}
- TestModelExecutor* model_executor() { return model_executor_.get(); }
+ TestModelExecutorHandle* model_executor_handle() {
+ return model_executor_handle_.get();
+ }
ModelObserverTracker* model_observer_tracker() {
return model_observer_tracker_.get();
@@ -137,28 +150,27 @@ class BaseOptimizationTargetModelExecutorTest : public testing::Test {
void RunUntilIdle() { task_environment_.RunUntilIdle(); }
private:
- content::BrowserTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
base::FilePath model_file_path_;
std::unique_ptr<ModelObserverTracker> model_observer_tracker_;
- std::unique_ptr<TestModelExecutor> model_executor_;
+ std::unique_ptr<TestModelExecutorHandle> model_executor_handle_;
};
-class OptimizationTargetModelExecutorTest
- : public BaseOptimizationTargetModelExecutorTest {
+class ModelExecutorTest : public BaseModelExecutorTest {
public:
- OptimizationTargetModelExecutorTest() {
+ ModelExecutorTest() {
scoped_feature_list_.InitAndDisableFeature(
features::kLoadModelFileForEachExecution);
}
- ~OptimizationTargetModelExecutorTest() override = default;
+ ~ModelExecutorTest() override = default;
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
-TEST_F(OptimizationTargetModelExecutorTest, ObserverIsAttachedCorrectly) {
+TEST_F(ModelExecutorTest, ObserverIsAttachedCorrectly) {
CreateModelExecutor();
EXPECT_TRUE(model_observer_tracker()->add_observer_called());
@@ -166,25 +178,25 @@ TEST_F(OptimizationTargetModelExecutorTest, ObserverIsAttachedCorrectly) {
EXPECT_TRUE(model_observer_tracker()->remove_observer_called());
}
-TEST_F(OptimizationTargetModelExecutorTest, ModelFileUpdatedWrongTarget) {
+TEST_F(ModelExecutorTest, ModelFileUpdatedWrongTarget) {
CreateModelExecutor();
PushModelFileToModelExecutor(
proto::OptimizationTarget::OPTIMIZATION_TARGET_LANGUAGE_DETECTION,
- /*model_metadata=*/base::nullopt);
+ /*model_metadata=*/absl::nullopt);
- EXPECT_FALSE(model_executor()->HasLoadedModel());
+ EXPECT_FALSE(model_executor_handle()->ModelAvailable());
}
-TEST_F(OptimizationTargetModelExecutorTest, ModelFileUpdatedCorrectTarget) {
+TEST_F(ModelExecutorTest, ModelFileUpdatedCorrectTarget) {
base::HistogramTester histogram_tester;
CreateModelExecutor();
PushModelFileToModelExecutor(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
- /*model_metadata=*/base::nullopt);
+ /*model_metadata=*/absl::nullopt);
- EXPECT_TRUE(model_executor()->HasLoadedModel());
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
histogram_tester.ExpectBucketCount(
"OptimizationGuide.ModelExecutor.ModelLoadingResult." +
optimization_guide::GetStringNameForOptimizationTarget(
@@ -199,16 +211,15 @@ TEST_F(OptimizationTargetModelExecutorTest, ModelFileUpdatedCorrectTarget) {
1);
}
-TEST_F(OptimizationTargetModelExecutorTest,
- ExecuteReturnsImmediatelyIfNoModelLoaded) {
+TEST_F(ModelExecutorTest, ExecuteReturnsImmediatelyIfNoModelLoaded) {
base::HistogramTester histogram_tester;
CreateModelExecutor();
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
- model_executor()->ExecuteModelWithInput(
+ model_executor_handle()->ExecuteModelWithInput(
base::BindOnce(
[](base::RunLoop* run_loop,
- const base::Optional<std::vector<float>>& output) {
+ const absl::optional<std::vector<float>>& output) {
EXPECT_FALSE(output.has_value());
run_loop->Quit();
},
@@ -220,23 +231,26 @@ TEST_F(OptimizationTargetModelExecutorTest,
optimization_guide::GetStringNameForOptimizationTarget(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
0);
- // The run count histogram is only recorded on destruction.
- ResetModelExecutor();
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.ModelExecutor.TaskSchedulingLatency." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
+ 1);
histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.ModelExecutor.RunCount." +
+ "OptimizationGuide.ModelExecutor.ModelAvailableToLoad." +
optimization_guide::GetStringNameForOptimizationTarget(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
- 0, 1);
+ false, 1);
}
-TEST_F(OptimizationTargetModelExecutorTest, ExecuteWithLoadedModel) {
+TEST_F(ModelExecutorTest, ExecuteWithLoadedModel) {
base::HistogramTester histogram_tester;
CreateModelExecutor();
PushModelFileToModelExecutor(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
- /*model_metadata=*/base::nullopt);
- EXPECT_TRUE(model_executor()->HasLoadedModel());
+ /*model_metadata=*/absl::nullopt);
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
std::vector<float> input;
int expected_dims = 1 * 32 * 32 * 3;
@@ -245,10 +259,10 @@ TEST_F(OptimizationTargetModelExecutorTest, ExecuteWithLoadedModel) {
input.emplace_back(1);
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
- model_executor()->ExecuteModelWithInput(
+ model_executor_handle()->ExecuteModelWithInput(
base::BindOnce(
[](base::RunLoop* run_loop,
- const base::Optional<std::vector<float>>& output) {
+ const absl::optional<std::vector<float>>& output) {
EXPECT_TRUE(output.has_value());
std::vector<float> expected_output = {
@@ -267,23 +281,26 @@ TEST_F(OptimizationTargetModelExecutorTest, ExecuteWithLoadedModel) {
optimization_guide::GetStringNameForOptimizationTarget(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
1);
- // The run count histogram is only recorded on destruction.
- ResetModelExecutor();
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.ModelExecutor.TaskSchedulingLatency." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
+ 1);
histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.ModelExecutor.RunCount." +
+ "OptimizationGuide.ModelExecutor.ModelAvailableToLoad." +
optimization_guide::GetStringNameForOptimizationTarget(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
- 1, 1);
+ true, 1);
}
-TEST_F(OptimizationTargetModelExecutorTest, ExecuteTwiceWithLoadedModel) {
+TEST_F(ModelExecutorTest, ExecuteTwiceWithLoadedModel) {
base::HistogramTester histogram_tester;
CreateModelExecutor();
PushModelFileToModelExecutor(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
- /*model_metadata=*/base::nullopt);
- EXPECT_TRUE(model_executor()->HasLoadedModel());
+ /*model_metadata=*/absl::nullopt);
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
std::vector<float> input;
int expected_dims = 1 * 32 * 32 * 3;
@@ -293,10 +310,10 @@ TEST_F(OptimizationTargetModelExecutorTest, ExecuteTwiceWithLoadedModel) {
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
// First run.
- model_executor()->ExecuteModelWithInput(
+ model_executor_handle()->ExecuteModelWithInput(
base::BindOnce(
[](base::RunLoop* run_loop,
- const base::Optional<std::vector<float>>& output) {
+ const absl::optional<std::vector<float>>& output) {
EXPECT_TRUE(output.has_value());
run_loop->Quit();
},
@@ -312,10 +329,10 @@ TEST_F(OptimizationTargetModelExecutorTest, ExecuteTwiceWithLoadedModel) {
// Second run.
run_loop = std::make_unique<base::RunLoop>();
- model_executor()->ExecuteModelWithInput(
+ model_executor_handle()->ExecuteModelWithInput(
base::BindOnce(
[](base::RunLoop* run_loop,
- const base::Optional<std::vector<float>>& output) {
+ const absl::optional<std::vector<float>>& output) {
EXPECT_TRUE(output.has_value());
run_loop->Quit();
},
@@ -329,36 +346,36 @@ TEST_F(OptimizationTargetModelExecutorTest, ExecuteTwiceWithLoadedModel) {
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
2);
histogram_tester.ExpectTotalCount(
- "OptimizationGuide.ModelExecutor.TimeSincePreviousRun." +
+ "OptimizationGuide.ModelExecutor.TaskSchedulingLatency." +
optimization_guide::GetStringNameForOptimizationTarget(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
- 1);
-
- // The run count histogram is only recorded on destruction.
- ResetModelExecutor();
+ 2);
histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.ModelExecutor.RunCount." +
+ "OptimizationGuide.ModelExecutor.ModelAvailableToLoad." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
+ true, 1);
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.ModelExecutor.TimeSincePreviousRun." +
optimization_guide::GetStringNameForOptimizationTarget(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
- 2, 1);
+ 1);
}
-TEST_F(OptimizationTargetModelExecutorTest,
- ParsedSupportedFeaturesForLoadedModelNoMetadata) {
+TEST_F(ModelExecutorTest, ParsedSupportedFeaturesForLoadedModelNoMetadata) {
CreateModelExecutor();
PushModelFileToModelExecutor(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
- /*model_metadata=*/base::nullopt);
- EXPECT_TRUE(model_executor()->HasLoadedModel());
+ /*model_metadata=*/absl::nullopt);
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
- EXPECT_FALSE(model_executor()
+ EXPECT_FALSE(model_executor_handle()
->ParsedSupportedFeaturesForLoadedModel<proto::Duration>()
.has_value());
}
-TEST_F(OptimizationTargetModelExecutorTest,
- ParsedSupportedFeaturesForLoadedModelWithMetadata) {
+TEST_F(ModelExecutorTest, ParsedSupportedFeaturesForLoadedModelWithMetadata) {
CreateModelExecutor();
proto::Any any_metadata;
@@ -369,30 +386,29 @@ TEST_F(OptimizationTargetModelExecutorTest,
PushModelFileToModelExecutor(
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
any_metadata);
- EXPECT_TRUE(model_executor()->HasLoadedModel());
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
- base::Optional<proto::Duration> supported_features_for_loaded_model =
- model_executor()
+ absl::optional<proto::Duration> supported_features_for_loaded_model =
+ model_executor_handle()
->ParsedSupportedFeaturesForLoadedModel<proto::Duration>();
- EXPECT_TRUE(supported_features_for_loaded_model.has_value());
+ ASSERT_TRUE(supported_features_for_loaded_model.has_value());
EXPECT_EQ(123, supported_features_for_loaded_model->seconds());
}
-class OptimizationTargetModelExecutorWithModelLoadingTest
- : public BaseOptimizationTargetModelExecutorTest {
+class ModelExecutorWithModelLoadingTest : public BaseModelExecutorTest {
public:
- OptimizationTargetModelExecutorWithModelLoadingTest() {
+ ModelExecutorWithModelLoadingTest() {
scoped_feature_list_.InitAndEnableFeature(
features::kLoadModelFileForEachExecution);
}
- ~OptimizationTargetModelExecutorWithModelLoadingTest() override = default;
+ ~ModelExecutorWithModelLoadingTest() override = default;
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
-TEST_F(OptimizationTargetModelExecutorWithModelLoadingTest,
- LoadModelFileForEachExecution) {
+TEST_F(ModelExecutorWithModelLoadingTest, LoadModelFileForEachExecution) {
+ base::HistogramTester histogram_tester;
CreateModelExecutor();
proto::Any any_metadata;
@@ -404,9 +420,11 @@ TEST_F(OptimizationTargetModelExecutorWithModelLoadingTest,
proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
any_metadata);
- // Model shouldn't be loaded until there is something to execute.
- EXPECT_FALSE(model_executor()->HasLoadedModel());
- EXPECT_FALSE(model_executor()->supported_features_for_loaded_model());
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
+
+ // While the model isn't actually loaded yet, the supported features are
+ // already known and do not change when the model is loaded or unloaded.
+ EXPECT_TRUE(model_executor_handle()->supported_features_for_loaded_model());
std::vector<float> input;
size_t expected_dims = 1 * 32 * 32 * 3;
@@ -415,23 +433,63 @@ TEST_F(OptimizationTargetModelExecutorWithModelLoadingTest,
input.emplace_back(1);
}
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
- model_executor()->ExecuteModelWithInput(
+ model_executor_handle()->ExecuteModelWithInput(
base::BindOnce(
- [](base::RunLoop* run_loop, TestModelExecutor* model_executor,
- const base::Optional<std::vector<float>>& output) {
+ [](base::RunLoop* run_loop,
+ const absl::optional<std::vector<float>>& output) {
EXPECT_TRUE(output.has_value());
- EXPECT_TRUE(model_executor->HasLoadedModel());
- EXPECT_TRUE(model_executor->supported_features_for_loaded_model());
run_loop->Quit();
},
- run_loop.get(), model_executor()),
+ run_loop.get()),
input);
run_loop->Run();
- // After execution, the model should be unloaded in a PostTask.
RunUntilIdle();
- EXPECT_FALSE(model_executor()->HasLoadedModel());
- EXPECT_FALSE(model_executor()->supported_features_for_loaded_model());
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
+
+ // After execution, the model should be unloaded in a PostTask, but the
+ // metadata should still be available.
+
+ EXPECT_TRUE(model_executor_handle()->supported_features_for_loaded_model());
+
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.ModelExecutor.TaskSchedulingLatency." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
+ 1);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.ModelExecutor.ModelAvailableToLoad." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
+ true, 1);
+
+ // After execution, the model should be unloaded in a PostTask, so give it a
+ // change to do so.
+ RunUntilIdle();
+
+ // Run again and expect a second model load histogram count.
+ run_loop = std::make_unique<base::RunLoop>();
+ model_executor_handle()->ExecuteModelWithInput(
+ base::BindOnce(
+ [](base::RunLoop* run_loop,
+ const absl::optional<std::vector<float>>& output) {
+ EXPECT_TRUE(output.has_value());
+ run_loop->Quit();
+ },
+ run_loop.get()),
+ input);
+ run_loop->Run();
+
+ histogram_tester.ExpectTotalCount(
+ "OptimizationGuide.ModelExecutor.TaskSchedulingLatency." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
+ 2);
+ histogram_tester.ExpectUniqueSample(
+ "OptimizationGuide.ModelExecutor.ModelAvailableToLoad." +
+ optimization_guide::GetStringNameForOptimizationTarget(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD),
+ true, 2);
}
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/noisy_metrics_recorder.cc b/chromium/components/optimization_guide/core/noisy_metrics_recorder.cc
new file mode 100644
index 00000000000..d61fbd1a000
--- /dev/null
+++ b/chromium/components/optimization_guide/core/noisy_metrics_recorder.cc
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/optimization_guide/core/noisy_metrics_recorder.h"
+
+#include <cmath>
+
+#include "base/check_op.h"
+#include "base/logging.h"
+#include "base/rand_util.h"
+
+NoisyMetricsRecorder::NoisyMetricsRecorder() = default;
+NoisyMetricsRecorder::~NoisyMetricsRecorder() = default;
+
+uint32_t NoisyMetricsRecorder::GetNoisyMetric(float flip_probability,
+ uint32_t original_metric,
+ uint8_t count_bits) {
+ DCHECK_LE(flip_probability, 1.0f);
+ DCHECK_GE(flip_probability, 0.0f);
+
+ // |original_metric| should fit within least significant |count_bits|.
+ DCHECK_LE(original_metric, std::pow(2, count_bits) - 1);
+
+ uint32_t flipped_value = 0u;
+
+ for (size_t idx = 0; idx < count_bits; ++idx) {
+ uint32_t flipped_bit = 0;
+ uint32_t bit = original_metric & 0x1;
+ original_metric = original_metric >> 1;
+ float first_coin_flip = GetRandBetween0And1();
+ if (first_coin_flip < flip_probability) {
+ flipped_bit = GetRandEither0Or1();
+ } else {
+ flipped_bit = bit;
+ }
+ flipped_value |= (flipped_bit << idx);
+ }
+
+ // The method has iterated through least significant |count_bits| and did that
+ // many right shifts. At this point, rest of the bits in |original_metric|
+ // should be 0.
+ DCHECK_EQ(original_metric, 0u);
+ DCHECK_EQ(flipped_value >> count_bits, 0u);
+ return flipped_value;
+}
+
+float NoisyMetricsRecorder::GetRandBetween0And1() const {
+ return base::RandDouble();
+}
+
+int NoisyMetricsRecorder::GetRandEither0Or1() const {
+ return base::RandInt(0, 1);
+} \ No newline at end of file
diff --git a/chromium/components/optimization_guide/core/noisy_metrics_recorder.h b/chromium/components/optimization_guide/core/noisy_metrics_recorder.h
new file mode 100644
index 00000000000..7fd5f3109f6
--- /dev/null
+++ b/chromium/components/optimization_guide/core/noisy_metrics_recorder.h
@@ -0,0 +1,32 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_NOISY_METRICS_RECORDER_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_NOISY_METRICS_RECORDER_H_
+
+#include <stdint.h>
+
+// NoisyMetricsRecorder can be used to add noise to metrics before recording
+// them.
+class NoisyMetricsRecorder {
+ public:
+ NoisyMetricsRecorder();
+ ~NoisyMetricsRecorder();
+ // |flip_probability| is the probability that an individual bit will get
+ // flipped. Typical value of flip_probability is 0.5. |original_metric| is the
+ // metric that contains a value that typically needs at most |count_bits| to
+ // be expressed. The method returns the flipped value of |original_metric|.
+ uint32_t GetNoisyMetric(float flip_probability,
+ uint32_t original_metric,
+ uint8_t count_bits);
+
+ protected:
+ // Returns a random float between 0 and 1 (both inclusive).
+ virtual float GetRandBetween0And1() const;
+
+ // Returns a random number that's either 0 or 1.
+ virtual int GetRandEither0Or1() const;
+};
+
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_NOISY_METRICS_RECORDER_H_ \ No newline at end of file
diff --git a/chromium/components/optimization_guide/core/noisy_metrics_recorder_unittest.cc b/chromium/components/optimization_guide/core/noisy_metrics_recorder_unittest.cc
new file mode 100644
index 00000000000..7349c6dcd2b
--- /dev/null
+++ b/chromium/components/optimization_guide/core/noisy_metrics_recorder_unittest.cc
@@ -0,0 +1,128 @@
+// Copyright 2021 The Chromium Authors. 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/core/noisy_metrics_recorder.h"
+
+#include <cmath>
+
+#include "base/check_op.h"
+#include "base/logging.h"
+#include "base/rand_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Tests that the original metric is returned as it is when the bit flip
+// probability is set to 0.
+TEST(NoisyMetricsRecorderTest, BasicsNoNoise) {
+ const struct TestCase {
+ uint32_t original_metric;
+ uint8_t bits_count;
+ } kTestCases[] = {{0, 1}, {1, 1}, {10, 4}, {10, 31}, {100, 7}, {4242, 31}};
+
+ for (const auto& test_case : kTestCases) {
+ NoisyMetricsRecorder recorder;
+ uint32_t flipped = recorder.GetNoisyMetric(0.0f, test_case.original_metric,
+ test_case.bits_count);
+ EXPECT_EQ(flipped, test_case.original_metric);
+ }
+}
+
+// Tests that the original metric is within the expected bounds.
+TEST(NoisyMetricsRecorderTest, RandomNoise) {
+ const struct TestCase {
+ uint32_t original_metric;
+ uint8_t bits_count;
+ } kTestCases[] = {{0, 1}, {1, 1}, {10, 4}, {10, 31}, {100, 7}, {4242, 31}};
+
+ for (const auto& test_case : kTestCases) {
+ NoisyMetricsRecorder recorder;
+ uint32_t flipped = recorder.GetNoisyMetric(0.5f, test_case.original_metric,
+ test_case.bits_count);
+ EXPECT_GE(flipped, 0u);
+ EXPECT_LE(static_cast<int>(flipped), std::pow(2, test_case.bits_count) - 1);
+ }
+}
+
+// TestNoisyMetricsRecorder returns deterministic random number based on how
+// it's configured.
+class TestNoisyMetricsRecorder : public NoisyMetricsRecorder {
+ public:
+ enum class Mode { kAlternate0And1, kAll0, kAll1 };
+
+ explicit TestNoisyMetricsRecorder(Mode mode) : mode_(mode) {}
+ ~TestNoisyMetricsRecorder() = default;
+
+ uint32_t GenerateNumberWithAlternate0And1Bits(size_t count_bits) const {
+ int flipped_value = 0;
+ int next_bit = 1;
+ for (size_t i = 0; i < count_bits; ++i) {
+ flipped_value |= (next_bit << i);
+ next_bit = next_bit == 0 ? 1 : 0;
+ }
+ return flipped_value;
+ }
+
+ private:
+ int GetRandEither0Or1() const override {
+ if (mode_ == Mode::kAll0)
+ return 0;
+ if (mode_ == Mode::kAll1)
+ return 1;
+
+ if (last_bit_returned_ == 0) {
+ last_bit_returned_ = 1;
+ } else {
+ last_bit_returned_ = 0;
+ }
+ return last_bit_returned_;
+ }
+
+ mutable int last_bit_returned_ = 0;
+ const Mode mode_;
+};
+
+TEST(NoisyMetricsRecorderTest, All0s) {
+ const struct TestCase {
+ uint32_t original_metric;
+ uint8_t bits_count;
+ } kTestCases[] = {{0, 1}, {1, 1}, {10, 4}, {10, 31}, {100, 7}, {4242, 31}};
+
+ for (const auto& test_case : kTestCases) {
+ TestNoisyMetricsRecorder recorder(TestNoisyMetricsRecorder::Mode::kAll0);
+ uint32_t flipped = recorder.GetNoisyMetric(1.0f, test_case.original_metric,
+ test_case.bits_count);
+ EXPECT_EQ(flipped, 0u);
+ }
+}
+
+TEST(NoisyMetricsRecorderTest, All1s) {
+ const struct TestCase {
+ uint32_t original_metric;
+ uint8_t bits_count;
+ } kTestCases[] = {{0, 1}, {1, 1}, {10, 4}, {10, 31}, {100, 7}, {4242, 31}};
+
+ for (const auto& test_case : kTestCases) {
+ TestNoisyMetricsRecorder recorder(TestNoisyMetricsRecorder::Mode::kAll1);
+ uint32_t flipped = recorder.GetNoisyMetric(1.0f, test_case.original_metric,
+ test_case.bits_count);
+ EXPECT_EQ(flipped, std::pow(2, test_case.bits_count) - 1);
+ }
+}
+
+// Tests that the flipped return value matches the expected value. The noise is
+// added deterministically using TestNoisyMetricsRecorder.
+TEST(NoisyMetricsRecorderTest, AlternateBits) {
+ const struct TestCase {
+ uint32_t original_metric;
+ uint8_t bits_count;
+ } kTestCases[] = {{0, 1}, {1, 1}, {10, 4}, {10, 31}, {100, 7}, {4242, 31}};
+
+ for (const auto& test_case : kTestCases) {
+ TestNoisyMetricsRecorder recorder(
+ TestNoisyMetricsRecorder::Mode::kAlternate0And1);
+ uint32_t flipped = recorder.GetNoisyMetric(1.0f, test_case.original_metric,
+ test_case.bits_count);
+ EXPECT_EQ(flipped, recorder.GenerateNumberWithAlternate0And1Bits(
+ test_case.bits_count));
+ }
+}
diff --git a/chromium/components/optimization_guide/core/optimization_guide_enums.h b/chromium/components/optimization_guide/core/optimization_guide_enums.h
index fb65ebced99..a48c6ca617b 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_enums.h
+++ b/chromium/components/optimization_guide/core/optimization_guide_enums.h
@@ -129,30 +129,32 @@ enum class PredictionManagerModelStatus {
// Keep in sync with OptimizationGuidePredictionModelDownloadStatus
// in enums.xml.
enum class PredictionModelDownloadStatus {
- kUnknown,
+ kUnknown = 0,
// The downloaded file was successfully verified and processed.
- kSuccess,
+ kSuccess = 1,
// The downloaded file was not a valid CRX file.
- kFailedCrxVerification,
+ kFailedCrxVerification = 2,
// A temporary directory for unzipping the CRX file failed to be created.
- kFailedUnzipDirectoryCreation,
+ kFailedUnzipDirectoryCreation = 3,
// The CRX file failed to be unzipped.
- kFailedCrxUnzip,
+ kFailedCrxUnzip = 4,
// The model info failed to be read from disk.
- kFailedModelInfoFileRead,
+ kFailedModelInfoFileRead = 5,
// The model info failed to be parsed.
- kFailedModelInfoParsing,
+ kFailedModelInfoParsing = 6,
// The model file was not found in the CRX file.
- kFailedModelFileNotFound,
+ kFailedModelFileNotFound = 7,
// The model file failed to be moved to a more permanent directory.
- kFailedModelFileOtherError,
+ kFailedModelFileOtherError = 8,
// The model info was invalid.
- kFailedModelInfoInvalid,
+ kFailedModelInfoInvalid = 9,
// The CRX file was a valid CRX file but did not come from a valid publisher.
- kFailedCrxInvalidPublisher,
+ kFailedCrxInvalidPublisher = 10,
+ // The model directory for storing model files does not exist.
+ kModelDirectoryDoesNotExist = 11,
// Add new values above this line.
- kMaxValue = kFailedCrxInvalidPublisher,
+ kMaxValue = kModelDirectoryDoesNotExist,
};
// The state of the model file needed for execution.
diff --git a/chromium/components/optimization_guide/core/optimization_guide_features.cc b/chromium/components/optimization_guide/core/optimization_guide_features.cc
index 26d5b2af6b0..a3b189bd473 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_features.cc
+++ b/chromium/components/optimization_guide/core/optimization_guide_features.cc
@@ -10,6 +10,7 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "components/optimization_guide/core/optimization_guide_constants.h"
#include "components/optimization_guide/core/optimization_guide_switches.h"
@@ -22,15 +23,9 @@ namespace optimization_guide {
namespace features {
// Enables the syncing of the Optimization Hints component, which provides
-// hints for what Previews can be applied on a page load.
-const base::Feature kOptimizationHints {
- "OptimizationHints",
-#if defined(OS_ANDROID)
- base::FEATURE_ENABLED_BY_DEFAULT
-#else // !defined(OS_ANDROID)
- base::FEATURE_DISABLED_BY_DEFAULT
-#endif // defined(OS_ANDROID)
-};
+// hints for what optimizations can be applied on a page load.
+const base::Feature kOptimizationHints{"OptimizationHints",
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Feature flag that contains a feature param that specifies the field trials
// that are allowed to be sent up to the Optimization Guide Server.
@@ -38,8 +33,11 @@ const base::Feature kOptimizationHintsFieldTrials{
"OptimizationHintsFieldTrials", base::FEATURE_DISABLED_BY_DEFAULT};
// Enables fetching from a remote Optimization Guide Service.
-const base::Feature kRemoteOptimizationGuideFetching {
- "OptimizationHintsFetching",
+const base::Feature kRemoteOptimizationGuideFetching{
+ "OptimizationHintsFetching", base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kRemoteOptimizationGuideFetchingAnonymousDataConsent{
+ "OptimizationHintsFetchingAnonymousDataConsent",
#if defined(OS_ANDROID)
base::FEATURE_ENABLED_BY_DEFAULT
#else // !defined(OS_ANDROID)
@@ -47,10 +45,6 @@ const base::Feature kRemoteOptimizationGuideFetching {
#endif // defined(OS_ANDROID)
};
-const base::Feature kRemoteOptimizationGuideFetchingAnonymousDataConsent{
- "OptimizationHintsFetchingAnonymousDataConsent",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// Enables performance info in the context menu and fetching from a remote
// Optimization Guide Service.
const base::Feature kContextMenuPerformanceInfoAndRemoteHintFetching{
@@ -75,6 +69,10 @@ const base::Feature kOptimizationGuideModelDownloading {
const base::Feature kPageContentAnnotations{"PageContentAnnotations",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables push notification of hints.
+const base::Feature kPushNotifications{"OptimizationGuidePushNotifications",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// This feature flag does not turn off any behavior, it is only used for
// experiment parameters.
const base::Feature kPageTextExtraction{
@@ -208,6 +206,10 @@ bool IsRemoteFetchingEnabled() {
return base::FeatureList::IsEnabled(kRemoteOptimizationGuideFetching);
}
+bool IsPushNotificationsEnabled() {
+ return base::FeatureList::IsEnabled(kPushNotifications);
+}
+
bool IsRemoteFetchingForAnonymousDataConsentEnabled() {
return base::FeatureList::IsEnabled(
kRemoteOptimizationGuideFetchingAnonymousDataConsent);
@@ -223,7 +225,7 @@ int MaxServerBloomFilterByteSize() {
kOptimizationHints, "max_bloom_filter_byte_size", 250 * 1024 /* 250KB */);
}
-base::Optional<net::EffectiveConnectionType>
+absl::optional<net::EffectiveConnectionType>
GetMaxEffectiveConnectionTypeForNavigationHintsFetch() {
std::string param_value = base::GetFieldTrialParamValueByFeature(
kRemoteOptimizationGuideFetching,
@@ -351,18 +353,6 @@ base::TimeDelta PredictionModelFetchInterval() {
kOptimizationTargetPrediction, "fetch_interval_hours", 24));
}
-base::flat_set<std::string> ExternalAppPackageNamesApprovedForFetch() {
- std::string value = base::GetFieldTrialParamValueByFeature(
- kRemoteOptimizationGuideFetching, "approved_external_app_packages");
- if (value.empty())
- return {};
-
- std::vector<std::string> app_packages_list = base::SplitString(
- value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- return base::flat_set<std::string>(app_packages_list.begin(),
- app_packages_list.end());
-}
-
base::flat_set<uint32_t> FieldTrialNameHashesAllowedForFetch() {
std::string value = base::GetFieldTrialParamValueByFeature(
kOptimizationHintsFieldTrials, "allowed_field_trial_names");
@@ -407,5 +397,11 @@ bool LoadModelFileForEachExecution() {
return base::FeatureList::IsEnabled(kLoadModelFileForEachExecution);
}
+base::TimeDelta GetOnloadDelayForHintsFetching() {
+ return base::TimeDelta::FromMilliseconds(GetFieldTrialParamByFeatureAsInt(
+ kRemoteOptimizationGuideFetching, "onload_delay_for_hints_fetching_ms",
+ 0));
+}
+
} // namespace features
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/optimization_guide_features.h b/chromium/components/optimization_guide/core/optimization_guide_features.h
index 16a80b46f9c..844e423541a 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_features.h
+++ b/chromium/components/optimization_guide/core/optimization_guide_features.h
@@ -10,10 +10,11 @@
#include "base/containers/flat_set.h"
#include "base/feature_list.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "components/optimization_guide/proto/hints.pb.h"
#include "components/optimization_guide/proto/models.pb.h"
#include "net/nqe/effective_connection_type.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace optimization_guide {
@@ -29,6 +30,7 @@ extern const base::Feature kOptimizationGuideModelDownloading;
extern const base::Feature kPageContentAnnotations;
extern const base::Feature kPageTextExtraction;
extern const base::Feature kLoadModelFileForEachExecution;
+extern const base::Feature kPushNotifications;
// The grace period duration for how long to give outstanding page text dump
// requests to respond after DidFinishLoad.
@@ -95,6 +97,9 @@ bool IsRemoteFetchingForAnonymousDataConsentEnabled();
// enabled.
bool IsRemoteFetchingExplicitlyAllowedForPerformanceInfo();
+// Returns true if the feature to use push notifications is enabled.
+bool IsPushNotificationsEnabled();
+
// 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.
@@ -103,7 +108,7 @@ int MaxServerBloomFilterByteSize();
// Maximum effective connection type at which hints can be fetched for
// navigations in real-time. Returns null if the hints fetching for navigations
// is disabled.
-base::Optional<net::EffectiveConnectionType>
+absl::optional<net::EffectiveConnectionType>
GetMaxEffectiveConnectionTypeForNavigationHintsFetch();
// Returns the duration of the time window before hints expiration during which
@@ -186,10 +191,6 @@ base::TimeDelta PredictionModelFetchRetryDelay();
// refresh models.
base::TimeDelta PredictionModelFetchInterval();
-// Returns a set of external Android app packages whose predictions have been
-// approved for fetching from the remote Optimization Guide Service.
-base::flat_set<std::string> ExternalAppPackageNamesApprovedForFetch();
-
// Returns a set of field trial name hashes that can be sent in the request to
// the remote Optimization Guide Service if the client is in one of the
// specified field trials.
@@ -215,6 +216,10 @@ bool ShouldWriteContentAnnotationsToHistoryService();
// loaded for each execution, and then unloaded once complete.
bool LoadModelFileForEachExecution();
+// The time to wait beyond the onload event before sending the hints request for
+// link predictions.
+base::TimeDelta GetOnloadDelayForHintsFetching();
+
} // namespace features
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/optimization_guide_model_provider.h b/chromium/components/optimization_guide/core/optimization_guide_model_provider.h
new file mode 100644
index 00000000000..3e8356403ca
--- /dev/null
+++ b/chromium/components/optimization_guide/core/optimization_guide_model_provider.h
@@ -0,0 +1,47 @@
+// Copyright 2021 The Chromium Authors. 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_CORE_OPTIMIZATION_GUIDE_MODEL_PROVIDER_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_OPTIMIZATION_GUIDE_MODEL_PROVIDER_H_
+
+#include "components/optimization_guide/core/optimization_target_model_observer.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace optimization_guide {
+
+// Provides models configured to be served by the Optimization Guide to be used
+// for inference.
+class OptimizationGuideModelProvider {
+ public:
+ // Adds an observer for updates to the model for |optimization_target|.
+ //
+ // It is assumed that any model retrieved this way will be passed to the
+ // Machine Learning Service for inference.
+ //
+ // It is also assumed that there will only be one observer per optimization
+ // target, so if multiple observers are registered, this will crash in debug
+ // builds and be a no-op in release builds.
+ virtual void AddObserverForOptimizationTargetModel(
+ proto::OptimizationTarget optimization_target,
+ const absl::optional<proto::Any>& model_metadata,
+ OptimizationTargetModelObserver* observer) = 0;
+
+ // Removes an observer for updates to the model for |optimization_target|.
+ //
+ // If |observer| is registered for multiple targets, |observer| must be
+ // removed for all targets that it is added for in order for it to be fully
+ // removed from receiving any calls.
+ virtual void RemoveObserverForOptimizationTargetModel(
+ proto::OptimizationTarget optimization_target,
+ OptimizationTargetModelObserver* observer) = 0;
+
+ protected:
+ OptimizationGuideModelProvider() = default;
+ virtual ~OptimizationGuideModelProvider() = default;
+};
+
+} // namespace optimization_guide
+
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_OPTIMIZATION_GUIDE_MODEL_PROVIDER_H_
diff --git a/chromium/components/optimization_guide/core/optimization_guide_store.cc b/chromium/components/optimization_guide/core/optimization_guide_store.cc
index cfae84ffd48..07e617c96f1 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_store.cc
+++ b/chromium/components/optimization_guide/core/optimization_guide_store.cc
@@ -338,6 +338,53 @@ void OptimizationGuideStore::OnLoadEntriesToPurgeExpired(
weak_ptr_factory_.GetWeakPtr(), base::DoNothing::Once()));
}
+void OptimizationGuideStore::RemoveFetchedHintsByKey(
+ base::OnceClosure on_success,
+ const base::flat_set<std::string>& hint_keys) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ EntryKeySet keys_to_remove;
+ for (const std::string& key : hint_keys) {
+ EntryKey store_key;
+ if (FindEntryKeyForHostWithPrefix(key, &store_key,
+ GetFetchedHintEntryKeyPrefix())) {
+ keys_to_remove.insert(store_key);
+ }
+ }
+
+ if (keys_to_remove.empty()) {
+ std::move(on_success).Run();
+ return;
+ }
+
+ for (const EntryKey& key : keys_to_remove) {
+ entry_keys_->erase(key);
+ }
+
+ database_->UpdateEntriesWithRemoveFilter(
+ std::make_unique<EntryVector>(),
+ base::BindRepeating(&KeySetFilter, keys_to_remove),
+ base::BindOnce(&OptimizationGuideStore::OnFetchedEntriesRemoved,
+ weak_ptr_factory_.GetWeakPtr(), std::move(on_success),
+ keys_to_remove));
+}
+
+void OptimizationGuideStore::OnFetchedEntriesRemoved(
+ base::OnceClosure on_success,
+ const EntryKeySet& keys,
+ bool success) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (!success) {
+ UpdateStatus(Status::kFailed);
+ // |on_success| is intentionally not run here since the operation did not
+ // succeed.
+ return;
+ }
+
+ std::move(on_success).Run();
+}
+
bool OptimizationGuideStore::FindHintEntryKey(
const std::string& host,
EntryKey* out_hint_entry_key) const {
@@ -355,8 +402,9 @@ bool OptimizationGuideStore::FindHintEntryKey(
component_hint_entry_key_prefix_ ==
GetComponentHintEntryKeyPrefix(component_version_.value()));
if (FindEntryKeyForHostWithPrefix(host, out_hint_entry_key,
- component_hint_entry_key_prefix_))
+ component_hint_entry_key_prefix_)) {
return true;
+ }
return false;
}
@@ -816,7 +864,7 @@ void OptimizationGuideStore::OnLoadHint(
UMA_HISTOGRAM_ENUMERATION("OptimizationGuide.HintCache.HintType.Loaded",
store_entry_type);
- base::Optional<base::Time> expiry_time;
+ absl::optional<base::Time> expiry_time;
if (entry->has_expiry_time_secs()) {
expiry_time = base::Time::FromDeltaSinceWindowsEpoch(
base::TimeDelta::FromSeconds(entry->expiry_time_secs()));
diff --git a/chromium/components/optimization_guide/core/optimization_guide_store.h b/chromium/components/optimization_guide/core/optimization_guide_store.h
index 1e812c2914a..c4a98047b7c 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_store.h
+++ b/chromium/components/optimization_guide/core/optimization_guide_store.h
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/version.h"
#include "components/leveldb_proto/public/proto_database.h"
@@ -21,6 +20,7 @@
#include "components/optimization_guide/core/memory_hint.h"
#include "components/optimization_guide/core/store_update_data.h"
#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class SequencedTaskRunner;
@@ -261,6 +261,11 @@ class OptimizationGuideStore {
// If |this| is not available, base::Time() is returned.
base::Time GetHostModelFeaturesUpdateTime() const;
+ // Removes fetched hints whose keys are in |hint_keys| and runs |on_success|
+ // if successful, otherwise the callback is not run.
+ void RemoveFetchedHintsByKey(base::OnceClosure on_success,
+ const base::flat_set<std::string>& hint_keys);
+
// Clears all host model features from the database and resets the entry keys.
void ClearHostModelFeaturesFromDatabase();
@@ -389,11 +394,19 @@ class OptimizationGuideStore {
// entry keys contained within the database.
void OnUpdateStore(base::OnceClosure callback, bool success);
+ // Callback that runs after |keys| have been removed from the store. If
+ // |success|, |on_success| is run. Note that |on_success| is not guaranteed to
+ // run and that the calling code must be able to handle the callback not
+ // coming back.
+ void OnFetchedEntriesRemoved(base::OnceClosure on_success,
+ const EntryKeySet& keys,
+ bool success);
+
// Callback that runs after the hint entry keys are fully loaded. If there's
// currently an in-flight component update, then the hint entry keys will be
// loaded again after the component update completes, so the results are
- // tossed; otherwise, |entry_keys| is moved into |entry_keys_|.
- // Regardless of the outcome of loading the keys, the callback always runs.
+ // tossed; otherwise, |entry_keys| is moved into |entry_keys_|. Regardless of
+ // the outcome of loading the keys, the callback always runs.
void OnLoadEntryKeys(std::unique_ptr<EntryKeySet> entry_keys,
base::OnceClosure callback,
bool success,
@@ -474,7 +487,7 @@ class OptimizationGuideStore {
// The current component version of the store. This should only be updated
// via SetComponentVersion(), which ensures that both |component_version_|
// and |component_hint_key_prefix_| are updated at the same time.
- base::Optional<base::Version> component_version_;
+ absl::optional<base::Version> component_version_;
// The current entry key prefix shared by all component hints containd within
// the store. While this could be generated on the fly using
diff --git a/chromium/components/optimization_guide/core/optimization_guide_store_unittest.cc b/chromium/components/optimization_guide/core/optimization_guide_store_unittest.cc
index 08c89950fc5..4d6669cf57d 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_store_unittest.cc
+++ b/chromium/components/optimization_guide/core/optimization_guide_store_unittest.cc
@@ -11,7 +11,6 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
@@ -23,6 +22,7 @@
#include "components/optimization_guide/proto/models.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
using leveldb_proto::test::FakeDB;
@@ -81,11 +81,11 @@ class OptimizationGuideStoreTest : public testing::Test {
// Initializes the entries contained within the database on startup.
void SeedInitialData(
MetadataSchemaState state,
- base::Optional<size_t> component_hint_count = base::Optional<size_t>(),
- base::Optional<base::Time> fetched_hints_update =
- base::Optional<base::Time>(),
- base::Optional<base::Time> host_model_features_update =
- base::Optional<base::Time>()) {
+ absl::optional<size_t> component_hint_count = absl::optional<size_t>(),
+ absl::optional<base::Time> fetched_hints_update =
+ absl::optional<base::Time>(),
+ absl::optional<base::Time> host_model_features_update =
+ absl::optional<base::Time>()) {
db_store_.clear();
// Add a metadata schema entry if its state isn't kMissing. The version
@@ -171,7 +171,7 @@ class OptimizationGuideStoreTest : public testing::Test {
void SeedPredictionModelUpdateData(
StoreUpdateData* update_data,
optimization_guide::proto::OptimizationTarget optimization_target,
- base::Optional<base::FilePath> model_file_path = base::nullopt) {
+ absl::optional<base::FilePath> model_file_path = absl::nullopt) {
std::unique_ptr<optimization_guide::proto::PredictionModel>
prediction_model = CreatePredictionModel();
prediction_model->mutable_model_info()->set_optimization_target(
@@ -1509,6 +1509,117 @@ TEST_F(OptimizationGuideStoreTest,
EXPECT_EQ(hint_entry_key, "2_2.0.0_domain1.org");
}
+TEST_F(OptimizationGuideStoreTest, SuccessfulRemovedFetchedHintsByKey) {
+ MetadataSchemaState schema_state = MetadataSchemaState::kValid;
+ SeedInitialData(schema_state, 10);
+ CreateDatabase();
+ InitializeStore(schema_state);
+
+ std::unique_ptr<StoreUpdateData> component_update_data =
+ guide_store()->MaybeCreateUpdateDataForComponentHints(
+ base::Version(kUpdateComponentVersion));
+ ASSERT_TRUE(component_update_data);
+
+ proto::Hint hint1;
+ hint1.set_key("domain1.org");
+ hint1.set_key_representation(proto::HOST);
+ component_update_data->MoveHintIntoUpdateData(std::move(hint1));
+ proto::Hint hint2;
+ hint2.set_key("domain2.org");
+ hint2.set_key_representation(proto::HOST);
+ component_update_data->MoveHintIntoUpdateData(std::move(hint2));
+ UpdateComponentHints(std::move(component_update_data));
+
+ std::unique_ptr<StoreUpdateData> fetched_update_data =
+ guide_store()->CreateUpdateDataForFetchedHints(base::Time().Now());
+
+ proto::Hint fetched_hint1;
+ fetched_hint1.set_key("domain2.org");
+ fetched_hint1.set_key_representation(proto::HOST);
+ fetched_update_data->MoveHintIntoUpdateData(std::move(fetched_hint1));
+ proto::Hint fetched_hint2;
+ fetched_hint2.set_key("domain3.org");
+ fetched_hint2.set_key_representation(proto::HOST);
+ fetched_update_data->MoveHintIntoUpdateData(std::move(fetched_hint2));
+ UpdateFetchedHints(std::move(fetched_update_data));
+
+ base::RunLoop run_loop;
+ guide_store()->RemoveFetchedHintsByKey(run_loop.QuitClosure(),
+ {
+ "domain1.org",
+ "domain2.org",
+ "domain3.org",
+ "domain4.org",
+ });
+ db()->UpdateCallback(/*success=*/true);
+ run_loop.Run();
+
+ OptimizationGuideStore::EntryKey hint_entry_key;
+
+ // Check for keys that should exist.
+ EXPECT_TRUE(guide_store()->FindHintEntryKey("domain1.org", &hint_entry_key));
+ EXPECT_EQ("2_2.0.0_domain1.org", hint_entry_key);
+ EXPECT_TRUE(guide_store()->FindHintEntryKey("domain2.org", &hint_entry_key));
+ EXPECT_EQ("2_2.0.0_domain2.org", hint_entry_key);
+
+ // Check for keys that should not exist.
+ EXPECT_FALSE(guide_store()->FindHintEntryKey("domain3.org", &hint_entry_key));
+}
+
+TEST_F(OptimizationGuideStoreTest, FailedRemovedFetchedHintsByKey) {
+ MetadataSchemaState schema_state = MetadataSchemaState::kValid;
+ SeedInitialData(schema_state, 10);
+ CreateDatabase();
+ InitializeStore(schema_state);
+
+ std::unique_ptr<StoreUpdateData> component_update_data =
+ guide_store()->MaybeCreateUpdateDataForComponentHints(
+ base::Version(kUpdateComponentVersion));
+ ASSERT_TRUE(component_update_data);
+
+ proto::Hint hint1;
+ hint1.set_key("domain1.org");
+ hint1.set_key_representation(proto::HOST);
+ component_update_data->MoveHintIntoUpdateData(std::move(hint1));
+ proto::Hint hint2;
+ hint2.set_key("domain2.org");
+ hint2.set_key_representation(proto::HOST);
+ component_update_data->MoveHintIntoUpdateData(std::move(hint2));
+ UpdateComponentHints(std::move(component_update_data));
+
+ std::unique_ptr<StoreUpdateData> fetched_update_data =
+ guide_store()->CreateUpdateDataForFetchedHints(base::Time().Now());
+ ASSERT_TRUE(fetched_update_data);
+
+ proto::Hint fetched_hint1;
+ fetched_hint1.set_key("domain2.org");
+ fetched_hint1.set_key_representation(proto::HOST);
+ fetched_update_data->MoveHintIntoUpdateData(std::move(fetched_hint1));
+ proto::Hint fetched_hint2;
+ fetched_hint2.set_key("domain3.org");
+ fetched_hint2.set_key_representation(proto::HOST);
+ fetched_update_data->MoveHintIntoUpdateData(std::move(fetched_hint2));
+ UpdateFetchedHints(std::move(fetched_update_data));
+
+ bool did_callback_run = false;
+ base::OnceClosure callback = base::BindOnce(
+ [](bool* set_when_run) { *set_when_run = true; }, &did_callback_run);
+ guide_store()->RemoveFetchedHintsByKey(std::move(callback), {
+ "domain1.org",
+ "domain2.org",
+ "domain3.org",
+ "domain4.org",
+ });
+ RunUntilIdle();
+ db()->UpdateCallback(/*success=*/false);
+ RunUntilIdle();
+ EXPECT_FALSE(did_callback_run);
+
+ // The callback did not succeed, so the store should no longer be available.
+ EXPECT_EQ(0U, GetStoreEntryKeyCount());
+ EXPECT_FALSE(guide_store()->IsAvailable());
+}
+
TEST_F(OptimizationGuideStoreTest, ClearFetchedHints) {
base::HistogramTester histogram_tester;
MetadataSchemaState schema_state = MetadataSchemaState::kValid;
diff --git a/chromium/components/optimization_guide/core/optimization_guide_switches.cc b/chromium/components/optimization_guide/core/optimization_guide_switches.cc
index a4a9508ebc0..b9b9a7d1e6b 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_switches.cc
+++ b/chromium/components/optimization_guide/core/optimization_guide_switches.cc
@@ -7,9 +7,9 @@
#include "base/base64.h"
#include "base/command_line.h"
#include "base/logging.h"
-#include "base/optional.h"
#include "base/strings/string_split.h"
#include "components/optimization_guide/proto/hints.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
namespace switches {
@@ -99,11 +99,11 @@ bool ShouldPurgeModelAndFeaturesStoreOnStartup() {
// Parses a list of hosts to have hints fetched for. This overrides scheduling
// of the first hints fetch and forces it to occur immediately. If no hosts are
// provided, nullopt is returned.
-base::Optional<std::vector<std::string>>
+absl::optional<std::vector<std::string>>
ParseHintsFetchOverrideFromCommandLine() {
base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
if (!cmd_line->HasSwitch(kFetchHintsOverride))
- return base::nullopt;
+ return absl::nullopt;
std::string override_hosts_value =
cmd_line->GetSwitchValueASCII(kFetchHintsOverride);
@@ -113,7 +113,7 @@ ParseHintsFetchOverrideFromCommandLine() {
base::SPLIT_WANT_NONEMPTY);
if (hosts.size() == 0)
- return base::nullopt;
+ return absl::nullopt;
return hosts;
}
@@ -174,13 +174,13 @@ bool IsModelOverridePresent() {
return command_line->HasSwitch(kModelOverride);
}
-base::Optional<
- std::pair<std::string, base::Optional<optimization_guide::proto::Any>>>
+absl::optional<
+ std::pair<std::string, absl::optional<optimization_guide::proto::Any>>>
GetModelOverrideForOptimizationTarget(
optimization_guide::proto::OptimizationTarget optimization_target) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(kModelOverride))
- return base::nullopt;
+ return absl::nullopt;
std::string model_override_switch_value =
command_line->GetSwitchValueASCII(kModelOverride);
@@ -193,7 +193,7 @@ GetModelOverrideForOptimizationTarget(
if (override_parts.size() != 2 && override_parts.size() != 3) {
// Input is malformed.
DLOG(ERROR) << "Invalid string format provided to the Model Override";
- return base::nullopt;
+ return absl::nullopt;
}
optimization_guide::proto::OptimizationTarget recv_optimization_target;
@@ -202,33 +202,33 @@ GetModelOverrideForOptimizationTarget(
// Optimization target is invalid.
DLOG(ERROR)
<< "Invalid optimization target provided to the Model Override";
- return base::nullopt;
+ return absl::nullopt;
}
if (optimization_target != recv_optimization_target)
continue;
if (override_parts.size() == 2) {
- std::pair<std::string, base::Optional<optimization_guide::proto::Any>>
+ std::pair<std::string, absl::optional<optimization_guide::proto::Any>>
file_path_and_metadata =
- std::make_pair(override_parts[1], base::nullopt);
+ std::make_pair(override_parts[1], absl::nullopt);
return file_path_and_metadata;
}
std::string binary_pb;
if (!base::Base64Decode(override_parts[2], &binary_pb)) {
DLOG(ERROR) << "Invalid base64 encoding of the Model Override";
- return base::nullopt;
+ return absl::nullopt;
}
optimization_guide::proto::Any model_metadata;
if (!model_metadata.ParseFromString(binary_pb)) {
DLOG(ERROR) << "Invalid model metadata provided to the Model Override";
- return base::nullopt;
+ return absl::nullopt;
}
- std::pair<std::string, base::Optional<optimization_guide::proto::Any>>
+ std::pair<std::string, absl::optional<optimization_guide::proto::Any>>
file_path_and_metadata =
std::make_pair(override_parts[1], model_metadata);
return file_path_and_metadata;
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace switches
diff --git a/chromium/components/optimization_guide/core/optimization_guide_switches.h b/chromium/components/optimization_guide/core/optimization_guide_switches.h
index 5830d6d4b08..a183c3e026d 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_switches.h
+++ b/chromium/components/optimization_guide/core/optimization_guide_switches.h
@@ -9,8 +9,8 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
namespace proto {
@@ -50,7 +50,7 @@ bool ShouldPurgeModelAndFeaturesStoreOnStartup();
// Parses a list of hosts to have hints fetched for. This overrides scheduling
// of the first hints fetch and forces it to occur immediately. If no hosts are
// provided, nullopt is returned.
-base::Optional<std::vector<std::string>>
+absl::optional<std::vector<std::string>>
ParseHintsFetchOverrideFromCommandLine();
// Whether the hints fetcher timer should be overridden.
@@ -83,8 +83,8 @@ bool IsModelOverridePresent();
// Returns the file path string and metadata for the model provided via
// command-line for |optimization_target|, if applicable.
-base::Optional<
- std::pair<std::string, base::Optional<optimization_guide::proto::Any>>>
+absl::optional<
+ std::pair<std::string, absl::optional<optimization_guide::proto::Any>>>
GetModelOverrideForOptimizationTarget(
optimization_guide::proto::OptimizationTarget optimization_target);
diff --git a/chromium/components/optimization_guide/core/optimization_guide_switches_unittest.cc b/chromium/components/optimization_guide/core/optimization_guide_switches_unittest.cc
index c9c16aa9e1d..cb133c97169 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_switches_unittest.cc
+++ b/chromium/components/optimization_guide/core/optimization_guide_switches_unittest.cc
@@ -6,9 +6,9 @@
#include "base/base64.h"
#include "base/command_line.h"
-#include "base/optional.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
namespace switches {
@@ -17,7 +17,7 @@ TEST(OptimizationGuideSwitchesTest, ParseHintsFetchOverrideFromCommandLine) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(kFetchHintsOverride,
"whatever.com");
- base::Optional<std::vector<std::string>> parsed_hosts =
+ absl::optional<std::vector<std::string>> parsed_hosts =
ParseHintsFetchOverrideFromCommandLine();
EXPECT_TRUE(parsed_hosts.has_value());
@@ -30,7 +30,7 @@ TEST(OptimizationGuideSwitchesTest,
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
kFetchHintsOverride, "whatever.com, whatever-2.com, ,");
- base::Optional<std::vector<std::string>> parsed_hosts =
+ absl::optional<std::vector<std::string>> parsed_hosts =
ParseHintsFetchOverrideFromCommandLine();
EXPECT_TRUE(parsed_hosts.has_value());
@@ -41,7 +41,7 @@ TEST(OptimizationGuideSwitchesTest,
TEST(OptimizationGuideSwitchesTest,
ParseHintsFetchOverrideFromCommandLineNoSwitch) {
- base::Optional<std::vector<std::string>> parsed_hosts =
+ absl::optional<std::vector<std::string>> parsed_hosts =
ParseHintsFetchOverrideFromCommandLine();
EXPECT_FALSE(parsed_hosts.has_value());
@@ -105,12 +105,12 @@ TEST(OptimizationGuideSwitchesTest,
TEST(OptimizationGuideSwitchesTest,
GetModelOverrideForOptimizationTargetSwitchNotSet) {
- base::Optional<
- std::pair<std::string, base::Optional<optimization_guide::proto::Any>>>
+ absl::optional<
+ std::pair<std::string, absl::optional<optimization_guide::proto::Any>>>
file_path_and_metadata = GetModelOverrideForOptimizationTarget(
optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
- EXPECT_EQ(base::nullopt, file_path_and_metadata);
+ EXPECT_EQ(absl::nullopt, file_path_and_metadata);
EXPECT_FALSE(IsModelOverridePresent());
}
@@ -118,12 +118,12 @@ TEST(OptimizationGuideSwitchesTest,
GetModelOverrideForOptimizationTargetEmptyInput) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(kModelOverride);
- base::Optional<
- std::pair<std::string, base::Optional<optimization_guide::proto::Any>>>
+ absl::optional<
+ std::pair<std::string, absl::optional<optimization_guide::proto::Any>>>
file_path_and_metadata = GetModelOverrideForOptimizationTarget(
optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
- EXPECT_EQ(base::nullopt, file_path_and_metadata);
+ EXPECT_EQ(absl::nullopt, file_path_and_metadata);
}
TEST(OptimizationGuideSwitchesTest,
@@ -131,12 +131,12 @@ TEST(OptimizationGuideSwitchesTest,
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(kModelOverride,
"whatever");
- base::Optional<
- std::pair<std::string, base::Optional<optimization_guide::proto::Any>>>
+ absl::optional<
+ std::pair<std::string, absl::optional<optimization_guide::proto::Any>>>
file_path_and_metadata = GetModelOverrideForOptimizationTarget(
optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
- EXPECT_EQ(base::nullopt, file_path_and_metadata);
+ EXPECT_EQ(absl::nullopt, file_path_and_metadata);
}
TEST(OptimizationGuideSwitchesTest,
@@ -144,12 +144,12 @@ TEST(OptimizationGuideSwitchesTest,
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
kModelOverride, "notanoptimizationtarget:somefilepath");
- base::Optional<
- std::pair<std::string, base::Optional<optimization_guide::proto::Any>>>
+ absl::optional<
+ std::pair<std::string, absl::optional<optimization_guide::proto::Any>>>
file_path_and_metadata = GetModelOverrideForOptimizationTarget(
optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
- EXPECT_EQ(base::nullopt, file_path_and_metadata);
+ EXPECT_EQ(absl::nullopt, file_path_and_metadata);
}
TEST(OptimizationGuideSwitchesTest,
@@ -163,8 +163,8 @@ TEST(OptimizationGuideSwitchesTest,
kModelOverride,
"OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD:somefilepath:" + encoded_metadata);
- base::Optional<
- std::pair<std::string, base::Optional<optimization_guide::proto::Any>>>
+ absl::optional<
+ std::pair<std::string, absl::optional<optimization_guide::proto::Any>>>
file_path_and_metadata = GetModelOverrideForOptimizationTarget(
optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
@@ -185,8 +185,8 @@ TEST(OptimizationGuideSwitchesTest,
"PAGE_TOPICS:otherfilepath:" +
encoded_metadata);
- base::Optional<
- std::pair<std::string, base::Optional<optimization_guide::proto::Any>>>
+ absl::optional<
+ std::pair<std::string, absl::optional<optimization_guide::proto::Any>>>
file_path_and_metadata = GetModelOverrideForOptimizationTarget(
optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
EXPECT_EQ("somefilepath", file_path_and_metadata->first);
diff --git a/chromium/components/optimization_guide/core/optimization_guide_util.cc b/chromium/components/optimization_guide/core/optimization_guide_util.cc
index 45a1cd86175..183f6760df7 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_util.cc
+++ b/chromium/components/optimization_guide/core/optimization_guide_util.cc
@@ -26,6 +26,12 @@ std::string GetStringNameForOptimizationTarget(
return "LanguageDetection";
case proto::OPTIMIZATION_TARGET_PAGE_TOPICS:
return "PageTopics";
+ case proto::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
+ return "SegmentationNewTab";
+ case proto::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
+ return "SegmentationShare";
+ case proto::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
+ return "SegmentationVoice";
}
NOTREACHED();
return std::string();
@@ -76,10 +82,10 @@ GetActiveFieldTrialsAllowedForFetch() {
return filtered_active_field_trials;
}
-base::Optional<base::FilePath> GetFilePathFromPredictionModel(
+absl::optional<base::FilePath> GetFilePathFromPredictionModel(
const proto::PredictionModel& model) {
if (!model.model().has_download_url())
- return base::nullopt;
+ return absl::nullopt;
#if defined(OS_WIN)
return base::FilePath(base::UTF8ToWide(model.model().download_url()));
diff --git a/chromium/components/optimization_guide/core/optimization_guide_util.h b/chromium/components/optimization_guide/core/optimization_guide_util.h
index d62748766b4..e27f6ba2f5e 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_util.h
+++ b/chromium/components/optimization_guide/core/optimization_guide_util.h
@@ -8,11 +8,11 @@
#include <string>
#include "base/files/file_path.h"
-#include "base/optional.h"
#include "base/strings/string_split.h"
#include "components/optimization_guide/core/optimization_guide_enums.h"
#include "components/optimization_guide/proto/common_types.pb.h"
#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
@@ -33,7 +33,7 @@ google::protobuf::RepeatedPtrField<proto::FieldTrial>
GetActiveFieldTrialsAllowedForFetch();
// Returns the file path that holds the model file for |model|, if applicable.
-base::Optional<base::FilePath> GetFilePathFromPredictionModel(
+absl::optional<base::FilePath> GetFilePathFromPredictionModel(
const proto::PredictionModel& model);
// Fills |model| with the path for which the corresponding model file can be
@@ -46,29 +46,29 @@ void SetFilePathInPredictionModel(const base::FilePath& file_path,
template <class T,
class = typename std::enable_if<
std::is_convertible<T*, google::protobuf::MessageLite*>{}>::type>
-base::Optional<T> ParsedAnyMetadata(const proto::Any& any_metadata) {
+absl::optional<T> ParsedAnyMetadata(const proto::Any& any_metadata) {
// Verify type is the same - the Any type URL should be wrapped as:
// "type.googleapis.com/com.foo.Name".
std::vector<std::string> any_type_parts =
base::SplitString(any_metadata.type_url(), ".", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
if (any_type_parts.empty())
- return base::nullopt;
+ return absl::nullopt;
T metadata;
std::vector<std::string> type_parts =
base::SplitString(metadata.GetTypeName(), ".", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
if (type_parts.empty())
- return base::nullopt;
+ return absl::nullopt;
std::string any_type_name = any_type_parts.back();
std::string type_name = type_parts.back();
if (type_name != any_type_name)
- return base::nullopt;
+ return absl::nullopt;
// Return metadata if parseable.
if (metadata.ParseFromString(any_metadata.value()))
return metadata;
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/optimization_guide_util_unittest.cc b/chromium/components/optimization_guide/core/optimization_guide_util_unittest.cc
index d5dafddb524..8793247d7a5 100644
--- a/chromium/components/optimization_guide/core/optimization_guide_util_unittest.cc
+++ b/chromium/components/optimization_guide/core/optimization_guide_util_unittest.cc
@@ -16,7 +16,7 @@ TEST(OptimizationGuideUtilTest, ParsedAnyMetadataMismatchedTypeTest) {
dase_metadata.set_delay_type(proto::DELAY_TYPE_FINISHED_PARSING);
dase_metadata.SerializeToString(any_metadata.mutable_value());
- base::Optional<proto::DelayAsyncScriptExecutionMetadata>
+ absl::optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
ParsedAnyMetadata<proto::DelayAsyncScriptExecutionMetadata>(
any_metadata);
@@ -29,7 +29,7 @@ TEST(OptimizationGuideUtilTest, ParsedAnyMetadataNotSerializableTest) {
"type.googleapis.com/com.foo.DelayAsyncScriptExecutionMetadata");
any_metadata.set_value("12345678garbage");
- base::Optional<proto::DelayAsyncScriptExecutionMetadata>
+ absl::optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
ParsedAnyMetadata<proto::DelayAsyncScriptExecutionMetadata>(
any_metadata);
@@ -44,7 +44,7 @@ TEST(OptimizationGuideUtilTest, ParsedAnyMetadataTest) {
dase_metadata.set_delay_type(proto::DELAY_TYPE_FINISHED_PARSING);
dase_metadata.SerializeToString(any_metadata.mutable_value());
- base::Optional<proto::DelayAsyncScriptExecutionMetadata>
+ absl::optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
ParsedAnyMetadata<proto::DelayAsyncScriptExecutionMetadata>(
any_metadata);
diff --git a/chromium/components/optimization_guide/core/optimization_hints_component_update_listener.cc b/chromium/components/optimization_guide/core/optimization_hints_component_update_listener.cc
index 3c2b04d14d5..4ea36ecd4cb 100644
--- a/chromium/components/optimization_guide/core/optimization_hints_component_update_listener.cc
+++ b/chromium/components/optimization_guide/core/optimization_hints_component_update_listener.cc
@@ -61,7 +61,7 @@ void OptimizationHintsComponentUpdateListener::MaybeUpdateHintsComponent(
}
void OptimizationHintsComponentUpdateListener::ResetStateForTesting() {
- hints_component_info_ = base::nullopt;
+ hints_component_info_ = absl::nullopt;
}
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/optimization_hints_component_update_listener.h b/chromium/components/optimization_guide/core/optimization_hints_component_update_listener.h
index 0cf4be6a97f..a4c5bdae0d7 100644
--- a/chromium/components/optimization_guide/core/optimization_hints_component_update_listener.h
+++ b/chromium/components/optimization_guide/core/optimization_hints_component_update_listener.h
@@ -7,10 +7,10 @@
#include "base/no_destructor.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "components/optimization_guide/core/hints_component_info.h"
#include "components/optimization_guide/core/optimization_hints_component_observer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
@@ -41,7 +41,7 @@ class OptimizationHintsComponentUpdateListener {
void MaybeUpdateHintsComponent(const HintsComponentInfo& info);
// Currently received HintsComponentInfo.
- base::Optional<HintsComponentInfo> hints_component_info() {
+ absl::optional<HintsComponentInfo> hints_component_info() {
return hints_component_info_;
}
@@ -62,7 +62,7 @@ class OptimizationHintsComponentUpdateListener {
// The current HintsComponentInfo available to observers. This is unset until
// the first time MaybeUpdateHintsComponent() is called.
- base::Optional<HintsComponentInfo> hints_component_info_;
+ absl::optional<HintsComponentInfo> hints_component_info_;
};
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/optimization_metadata.h b/chromium/components/optimization_guide/core/optimization_metadata.h
index e80bacd8e4d..f2b5dd4efe4 100644
--- a/chromium/components/optimization_guide/core/optimization_metadata.h
+++ b/chromium/components/optimization_guide/core/optimization_metadata.h
@@ -6,9 +6,9 @@
#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_OPTIMIZATION_METADATA_H_
#include "base/logging.h"
-#include "base/optional.h"
#include "components/optimization_guide/core/optimization_guide_util.h"
#include "components/optimization_guide/proto/hints.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
@@ -30,12 +30,12 @@ class OptimizationMetadata {
class T,
class = typename std::enable_if<
std::is_convertible<T*, google::protobuf::MessageLite*>{}>::type>
- base::Optional<T> ParsedMetadata() const {
+ absl::optional<T> ParsedMetadata() const {
if (!any_metadata_)
- return base::nullopt;
+ return absl::nullopt;
return ParsedAnyMetadata<T>(*any_metadata_);
}
- const base::Optional<proto::Any>& any_metadata() const {
+ const absl::optional<proto::Any>& any_metadata() const {
return any_metadata_;
}
void set_any_metadata(const proto::Any& any_metadata) {
@@ -45,7 +45,7 @@ class OptimizationMetadata {
// used for testing purposes.
void SetAnyMetadataForTesting(const google::protobuf::MessageLite& metadata);
- const base::Optional<proto::PerformanceHintsMetadata>&
+ const absl::optional<proto::PerformanceHintsMetadata>&
performance_hints_metadata() const {
return performance_hints_metadata_;
}
@@ -54,7 +54,7 @@ class OptimizationMetadata {
performance_hints_metadata_ = performance_hints_metadata;
}
- const base::Optional<proto::PublicImageMetadata>& public_image_metadata()
+ const absl::optional<proto::PublicImageMetadata>& public_image_metadata()
const {
return public_image_metadata_;
}
@@ -63,7 +63,7 @@ class OptimizationMetadata {
public_image_metadata_ = public_image_metadata;
}
- const base::Optional<proto::LoadingPredictorMetadata>&
+ const absl::optional<proto::LoadingPredictorMetadata>&
loading_predictor_metadata() const {
return loading_predictor_metadata_;
}
@@ -77,16 +77,16 @@ class OptimizationMetadata {
//
// Optimization types that are not specifically specified below will have
// metadata populated with this field.
- base::Optional<proto::Any> any_metadata_;
+ absl::optional<proto::Any> any_metadata_;
// Only applicable for the PERFORMANCE_HINTS optimization type.
- base::Optional<proto::PerformanceHintsMetadata> performance_hints_metadata_;
+ absl::optional<proto::PerformanceHintsMetadata> performance_hints_metadata_;
// Only applicable for the COMPRESS_PUBLIC_IMAGES optimization type.
- base::Optional<proto::PublicImageMetadata> public_image_metadata_;
+ absl::optional<proto::PublicImageMetadata> public_image_metadata_;
// Only applicable for the LOADING_PREDICTOR optimization type.
- base::Optional<proto::LoadingPredictorMetadata> loading_predictor_metadata_;
+ absl::optional<proto::LoadingPredictorMetadata> loading_predictor_metadata_;
};
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/optimization_metadata_unittest.cc b/chromium/components/optimization_guide/core/optimization_metadata_unittest.cc
index eb68093e2c9..3b3025a75b2 100644
--- a/chromium/components/optimization_guide/core/optimization_metadata_unittest.cc
+++ b/chromium/components/optimization_guide/core/optimization_metadata_unittest.cc
@@ -12,7 +12,7 @@ namespace optimization_guide {
TEST(OptimizationMetadataTest, ParsedMetadataAnyMetadataNotPopulatedTest) {
OptimizationMetadata optimization_metadata;
- base::Optional<proto::DelayAsyncScriptExecutionMetadata>
+ absl::optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
@@ -27,7 +27,7 @@ TEST(OptimizationMetadataTest, ParsedMetadataNoTypeURLTest) {
OptimizationMetadata optimization_metadata;
optimization_metadata.set_any_metadata(any_metadata);
- base::Optional<proto::DelayAsyncScriptExecutionMetadata>
+ absl::optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
@@ -43,7 +43,7 @@ TEST(OptimizationMetadataTest, ParsedMetadataMismatchedTypeTest) {
OptimizationMetadata optimization_metadata;
optimization_metadata.set_any_metadata(any_metadata);
- base::Optional<proto::DelayAsyncScriptExecutionMetadata>
+ absl::optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
@@ -58,7 +58,7 @@ TEST(OptimizationMetadataTest, ParsedMetadataNotSerializableTest) {
OptimizationMetadata optimization_metadata;
optimization_metadata.set_any_metadata(any_metadata);
- base::Optional<proto::DelayAsyncScriptExecutionMetadata>
+ absl::optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
@@ -75,7 +75,7 @@ TEST(OptimizationMetadataTest, ParsedMetadataTest) {
OptimizationMetadata optimization_metadata;
optimization_metadata.set_any_metadata(any_metadata);
- base::Optional<proto::DelayAsyncScriptExecutionMetadata>
+ absl::optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
@@ -90,7 +90,7 @@ TEST(OptimizationMetadataTest, SetAnyMetadataForTestingTest) {
OptimizationMetadata optimization_metadata;
optimization_metadata.SetAnyMetadataForTesting(dase_metadata);
- base::Optional<proto::DelayAsyncScriptExecutionMetadata>
+ absl::optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
diff --git a/chromium/components/optimization_guide/core/optimization_target_model_observer.h b/chromium/components/optimization_guide/core/optimization_target_model_observer.h
index cb8b90f4aff..fb1e64ea679 100644
--- a/chromium/components/optimization_guide/core/optimization_target_model_observer.h
+++ b/chromium/components/optimization_guide/core/optimization_target_model_observer.h
@@ -7,8 +7,8 @@
#include "base/files/file_path.h"
#include "base/observer_list_types.h"
-#include "base/optional.h"
#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
@@ -25,7 +25,7 @@ class OptimizationTargetModelObserver : public base::CheckedObserver {
// file path it already has on device, if applicable.
virtual void OnModelFileUpdated(
proto::OptimizationTarget optimization_target,
- const base::Optional<proto::Any>& model_metadata,
+ const absl::optional<proto::Any>& model_metadata,
const base::FilePath& file_path) = 0;
};
diff --git a/chromium/components/optimization_guide/core/prediction_model_fetcher.cc b/chromium/components/optimization_guide/core/prediction_model_fetcher.cc
index 06ac0066b8f..35bb68ac6d0 100644
--- a/chromium/components/optimization_guide/core/prediction_model_fetcher.cc
+++ b/chromium/components/optimization_guide/core/prediction_model_fetcher.cc
@@ -47,7 +47,6 @@ PredictionModelFetcher::~PredictionModelFetcher() = default;
bool PredictionModelFetcher::FetchOptimizationGuideServiceModels(
const std::vector<proto::ModelInfo>& models_request_info,
- const std::vector<std::string>& hosts,
const std::vector<proto::FieldTrial>& active_field_trials,
proto::RequestContext request_context,
const std::string& locale,
@@ -55,16 +54,16 @@ bool PredictionModelFetcher::FetchOptimizationGuideServiceModels(
SEQUENCE_CHECKER(sequence_checker_);
if (network_connection_tracker_->IsOffline()) {
- std::move(models_fetched_callback).Run(base::nullopt);
+ std::move(models_fetched_callback).Run(absl::nullopt);
return false;
}
if (url_loader_)
return false;
- // If there are no hosts or models to request, do not make a GetModelsRequest.
- if (hosts.size() == 0 && models_request_info.size() == 0) {
- std::move(models_fetched_callback).Run(base::nullopt);
+ // If there are no models to request, do not make a GetModelsRequest.
+ if (models_request_info.empty()) {
+ std::move(models_fetched_callback).Run(absl::nullopt);
return false;
}
@@ -77,20 +76,6 @@ bool PredictionModelFetcher::FetchOptimizationGuideServiceModels(
*pending_models_request_->mutable_active_field_trials() = {
active_field_trials.begin(), active_field_trials.end()};
- // Limit the number of hosts to fetch features for, the list of hosts
- // is assumed to be ordered from most to least important by the top
- // host provider.
- for (const auto& host : hosts) {
- // Skip over localhosts, IP addresses, and invalid hosts.
- if (!IsHostValidToFetchFromRemoteOptimizationGuide(host))
- continue;
- pending_models_request_->add_hosts(host);
- if (static_cast<size_t>(pending_models_request_->hosts_size()) >=
- features::MaxHostsForOptimizationGuideServiceModelsFetch()) {
- break;
- }
- }
-
for (const auto& model_request_info : models_request_info)
*pending_models_request_->add_requested_models() = model_request_info;
@@ -141,11 +126,6 @@ bool PredictionModelFetcher::FetchOptimizationGuideServiceModels(
url_loader_->AttachStringForUpload(serialized_request,
"application/x-protobuf");
- UMA_HISTOGRAM_COUNTS_100(
- "OptimizationGuide.PredictionModelFetcher."
- "GetModelsRequest.HostCount",
- pending_models_request_->hosts_size());
-
// |url_loader_| should not retry on 5xx errors since the server may already
// be overloaded. |url_loader_| should retry on network changes since the
// network stack may receive the connection change event later than |this|.
@@ -183,13 +163,9 @@ void PredictionModelFetcher::HandleResponse(
if (net_status == net::OK && response_code == net::HTTP_OK &&
get_models_response->ParseFromString(get_models_response_data)) {
- UMA_HISTOGRAM_COUNTS_100(
- "OptimizationGuide.PredictionModelFetcher."
- "GetModelsResponse.HostModelFeatureCount",
- get_models_response->host_model_features_size());
std::move(models_fetched_callback_).Run(std::move(get_models_response));
} else {
- std::move(models_fetched_callback_).Run(base::nullopt);
+ std::move(models_fetched_callback_).Run(absl::nullopt);
}
}
diff --git a/chromium/components/optimization_guide/core/prediction_model_fetcher.h b/chromium/components/optimization_guide/core/prediction_model_fetcher.h
index 35afeaed83e..49349b5c4ef 100644
--- a/chromium/components/optimization_guide/core/prediction_model_fetcher.h
+++ b/chromium/components/optimization_guide/core/prediction_model_fetcher.h
@@ -12,9 +12,9 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace network {
@@ -29,7 +29,7 @@ namespace optimization_guide {
// to pass back the fetched hints response from the remote Optimization Guide
// Service.
using ModelsFetchedCallback = base::OnceCallback<void(
- base::Optional<
+ absl::optional<
std::unique_ptr<optimization_guide::proto::GetModelsResponse>>)>;
// A class to handle requests for prediction models (and prediction data) from
@@ -51,7 +51,6 @@ class PredictionModelFetcher {
// nullopt if the fetch failed or no fetch is needed. Virtualized for testing.
virtual bool FetchOptimizationGuideServiceModels(
const std::vector<proto::ModelInfo>& models_request_info,
- const std::vector<std::string>& hosts,
const std::vector<proto::FieldTrial>& active_field_trials,
proto::RequestContext request_context,
const std::string& locale,
diff --git a/chromium/components/optimization_guide/core/prediction_model_fetcher_unittest.cc b/chromium/components/optimization_guide/core/prediction_model_fetcher_unittest.cc
index 8e35a15f42d..ec4ba40340b 100644
--- a/chromium/components/optimization_guide/core/prediction_model_fetcher_unittest.cc
+++ b/chromium/components/optimization_guide/core/prediction_model_fetcher_unittest.cc
@@ -11,7 +11,6 @@
#include "base/callback.h"
#include "base/macros.h"
#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"
@@ -24,6 +23,7 @@
#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"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
@@ -45,7 +45,7 @@ class PredictionModelFetcherTest : public testing::Test {
~PredictionModelFetcherTest() override {}
- void OnModelsFetched(base::Optional<std::unique_ptr<proto::GetModelsResponse>>
+ void OnModelsFetched(absl::optional<std::unique_ptr<proto::GetModelsResponse>>
get_models_response) {
if (get_models_response)
models_fetched_ = true;
@@ -65,14 +65,12 @@ class PredictionModelFetcherTest : public testing::Test {
protected:
bool FetchModels(const std::vector<proto::ModelInfo> models_request_info,
- const std::vector<std::string>& hosts,
const std::vector<proto::FieldTrial>& active_field_trials,
proto::RequestContext request_context,
const std::string& locale) {
bool status =
prediction_model_fetcher_->FetchOptimizationGuideServiceModels(
- models_request_info, hosts, active_field_trials, request_context,
- locale,
+ models_request_info, active_field_trials, request_context, locale,
base::BindOnce(&PredictionModelFetcherTest::OnModelsFetched,
base::Unretained(this)));
RunUntilIdle();
@@ -117,85 +115,17 @@ class PredictionModelFetcherTest : public testing::Test {
};
TEST_F(PredictionModelFetcherTest, FetchOptimizationGuideServiceModels) {
- base::HistogramTester histogram_tester;
- std::string response_content;
- std::vector<std::string> hosts = {"foo.com", "bar.com"};
- std::vector<proto::ModelInfo> models_request_info({});
- std::vector<proto::FieldTrial> active_field_trials({});
- EXPECT_TRUE(FetchModels(models_request_info, hosts, active_field_trials,
- proto::RequestContext::CONTEXT_BATCH_UPDATE,
- "en-US"));
- VerifyHasPendingFetchRequests();
-
- histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.PredictionModelFetcher.GetModelsRequest.HostCount", 2,
- 1);
-
- EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
- EXPECT_TRUE(models_fetched());
-
- // No HostModelFeatures are returned.
- histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.PredictionModelFetcher.GetModelsResponse."
- "HostModelFeatureCount",
- 0, 1);
-}
-
-TEST_F(PredictionModelFetcherTest,
- FetchOptimizationGuideServiceModelsLimitHosts) {
- base::HistogramTester histogram_tester;
- std::string response_content;
- std::vector<std::string> hosts;
- for (size_t i = 0;
- i <= features::MaxHostsForOptimizationGuideServiceModelsFetch() + 1;
- i++) {
- hosts.push_back("host" + base::NumberToString(i) + ".com");
- }
- std::vector<proto::ModelInfo> models_request_info({});
- std::vector<proto::FieldTrial> active_field_trials({});
- EXPECT_TRUE(FetchModels(models_request_info, hosts, active_field_trials,
- proto::RequestContext::CONTEXT_BATCH_UPDATE,
- "en-US"));
- VerifyHasPendingFetchRequests();
-
- histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.PredictionModelFetcher.GetModelsRequest.HostCount",
- features::MaxHostsForOptimizationGuideServiceModelsFetch(), 1);
-
- EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
- EXPECT_TRUE(models_fetched());
-
- // No HostModelFeatures are returned.
- histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.PredictionModelFetcher.GetModelsResponse."
- "HostModelFeatureCount",
- 0, 1);
-}
-
-TEST_F(PredictionModelFetcherTest, FetchFilterInvalidHosts) {
- base::HistogramTester histogram_tester;
std::string response_content;
- std::vector<std::string> hosts = {"192.168.1.1", "_abc", "localhost",
- "foo.com"};
- std::vector<proto::ModelInfo> models_request_info({});
- std::vector<proto::FieldTrial> active_field_trials({});
- EXPECT_TRUE(FetchModels(models_request_info, hosts, active_field_trials,
+ proto::ModelInfo model_info;
+ model_info.set_optimization_target(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
+ EXPECT_TRUE(FetchModels({model_info}, /*active_field_trials=*/{},
proto::RequestContext::CONTEXT_BATCH_UPDATE,
"en-US"));
VerifyHasPendingFetchRequests();
- histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.PredictionModelFetcher.GetModelsRequest.HostCount", 1,
- 1);
-
EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
EXPECT_TRUE(models_fetched());
-
- // No HostModelFeatures are returned.
- histogram_tester.ExpectUniqueSample(
- "OptimizationGuide.PredictionModelFetcher.GetModelsResponse."
- "HostModelFeatureCount",
- 0, 1);
}
// Tests 404 response from request.
@@ -203,10 +133,10 @@ TEST_F(PredictionModelFetcherTest, FetchReturned404) {
base::HistogramTester histogram_tester;
std::string response_content;
- std::vector<std::string> hosts = {"foo.com", "bar.com"};
- std::vector<proto::ModelInfo> models_request_info({});
- std::vector<proto::FieldTrial> active_field_trials({});
- EXPECT_TRUE(FetchModels(models_request_info, hosts, active_field_trials,
+ proto::ModelInfo model_info;
+ model_info.set_optimization_target(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
+ EXPECT_TRUE(FetchModels({model_info}, /*active_field_trials=*/{},
proto::RequestContext::CONTEXT_BATCH_UPDATE,
"en-US"));
// Send a 404 to HintsFetcher.
@@ -225,10 +155,10 @@ TEST_F(PredictionModelFetcherTest, FetchReturned404) {
TEST_F(PredictionModelFetcherTest, FetchReturnBadResponse) {
std::string response_content = "not proto";
- std::vector<std::string> hosts = {"foo.com", "bar.com"};
- std::vector<proto::ModelInfo> models_request_info({});
- std::vector<proto::FieldTrial> active_field_trials({});
- EXPECT_TRUE(FetchModels(models_request_info, hosts, active_field_trials,
+ proto::ModelInfo model_info;
+ model_info.set_optimization_target(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
+ EXPECT_TRUE(FetchModels({model_info}, /*active_field_trials=*/{},
proto::RequestContext::CONTEXT_BATCH_UPDATE,
"en-US"));
VerifyHasPendingFetchRequests();
@@ -239,16 +169,16 @@ TEST_F(PredictionModelFetcherTest, FetchReturnBadResponse) {
TEST_F(PredictionModelFetcherTest, FetchAttemptWhenNetworkOffline) {
SetConnectionOffline();
std::string response_content;
- std::vector<std::string> hosts = {"foo.com", "bar.com"};
- std::vector<proto::ModelInfo> models_request_info({});
- std::vector<proto::FieldTrial> active_field_trials({});
- EXPECT_FALSE(FetchModels(models_request_info, hosts, active_field_trials,
+ proto::ModelInfo model_info;
+ model_info.set_optimization_target(
+ proto::OptimizationTarget::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD);
+ EXPECT_FALSE(FetchModels({model_info}, /*active_field_trials=*/{},
proto::RequestContext::CONTEXT_BATCH_UPDATE,
"en-US"));
EXPECT_FALSE(models_fetched());
SetConnectionOnline();
- EXPECT_TRUE(FetchModels(models_request_info, hosts, active_field_trials,
+ EXPECT_TRUE(FetchModels({model_info}, /*active_field_trials=*/{},
proto::RequestContext::CONTEXT_BATCH_UPDATE,
"en-US"));
VerifyHasPendingFetchRequests();
@@ -256,13 +186,12 @@ TEST_F(PredictionModelFetcherTest, FetchAttemptWhenNetworkOffline) {
EXPECT_TRUE(models_fetched());
}
-TEST_F(PredictionModelFetcherTest, EmptyModelInfoAndHosts) {
+TEST_F(PredictionModelFetcherTest, EmptyModelInfo) {
base::HistogramTester histogram_tester;
std::string response_content;
- std::vector<std::string> hosts = {};
- std::vector<proto::ModelInfo> models_request_info({});
- std::vector<proto::FieldTrial> active_field_trials({});
- EXPECT_FALSE(FetchModels(models_request_info, hosts, active_field_trials,
+ proto::FieldTrial field_trial;
+ field_trial.set_name_hash(123);
+ EXPECT_FALSE(FetchModels(/*model_request_info=*/{}, {field_trial},
proto::RequestContext::CONTEXT_BATCH_UPDATE,
"en-US"));
diff --git a/chromium/components/optimization_guide/core/prediction_model_file.cc b/chromium/components/optimization_guide/core/prediction_model_file.cc
index c2ebdb25147..26ca57657c8 100644
--- a/chromium/components/optimization_guide/core/prediction_model_file.cc
+++ b/chromium/components/optimization_guide/core/prediction_model_file.cc
@@ -12,7 +12,7 @@ namespace optimization_guide {
PredictionModelFile::PredictionModelFile(
const base::FilePath& model_file_path,
const int64_t version,
- const base::Optional<proto::Any>& model_metadata)
+ const absl::optional<proto::Any>& model_metadata)
: model_file_path_(model_file_path),
version_(version),
model_metadata_(model_metadata) {}
@@ -22,14 +22,14 @@ PredictionModelFile::~PredictionModelFile() = default;
// static
std::unique_ptr<PredictionModelFile> PredictionModelFile::Create(
const proto::PredictionModel& model) {
- base::Optional<base::FilePath> model_file_path =
+ absl::optional<base::FilePath> model_file_path =
GetFilePathFromPredictionModel(model);
if (!model_file_path)
return nullptr;
if (!model.model_info().has_version())
return nullptr;
- base::Optional<proto::Any> model_metadata;
+ absl::optional<proto::Any> model_metadata;
if (model.model_info().has_model_metadata())
model_metadata = model.model_info().model_metadata();
@@ -46,7 +46,7 @@ int64_t PredictionModelFile::GetVersion() const {
return version_;
}
-base::Optional<proto::Any> PredictionModelFile::GetModelMetadata() const {
+absl::optional<proto::Any> PredictionModelFile::GetModelMetadata() const {
return model_metadata_;
}
diff --git a/chromium/components/optimization_guide/core/prediction_model_file.h b/chromium/components/optimization_guide/core/prediction_model_file.h
index 4dbd35ca579..c243346f271 100644
--- a/chromium/components/optimization_guide/core/prediction_model_file.h
+++ b/chromium/components/optimization_guide/core/prediction_model_file.h
@@ -8,8 +8,8 @@
#include <memory>
#include "base/files/file_path.h"
-#include "base/optional.h"
#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
@@ -31,15 +31,15 @@ class PredictionModelFile {
// Returns the metadata that the server provided specific to this model, if
// applicable.
- base::Optional<proto::Any> GetModelMetadata() const;
+ absl::optional<proto::Any> GetModelMetadata() const;
private:
PredictionModelFile(const base::FilePath& model_file_path,
const int64_t version,
- const base::Optional<proto::Any>& model_metadata);
+ const absl::optional<proto::Any>& model_metadata);
base::FilePath model_file_path_;
int64_t version_;
- base::Optional<proto::Any> model_metadata_;
+ absl::optional<proto::Any> model_metadata_;
};
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/push_notification_manager.h b/chromium/components/optimization_guide/core/push_notification_manager.h
new file mode 100644
index 00000000000..de2e142ab52
--- /dev/null
+++ b/chromium/components/optimization_guide/core/push_notification_manager.h
@@ -0,0 +1,53 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_PUSH_NOTIFICATION_MANAGER_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_PUSH_NOTIFICATION_MANAGER_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/containers/flat_set.h"
+#include "components/optimization_guide/proto/hints.pb.h"
+#include "components/optimization_guide/proto/push_notification.pb.h"
+
+namespace optimization_guide {
+
+// An interface for classes that implement the handling of push hint
+// notifications. The primary task of this interface is to remove any hints from
+// persistent storage that are invalidated by a more recent hint being pushed.
+class PushNotificationManager {
+ public:
+ // Receives actions from the PushNotificationManager to execute when a new
+ // pushed hint is being processed. The Delegate should be implemented by the
+ // owner of the PushNotificationManager.
+ class Delegate {
+ public:
+ // Corresponds to a batch of hints being processed, typically from a cache.
+ virtual void RemoveFetchedEntriesByHintKeys(
+ base::OnceClosure on_success,
+ proto::KeyRepresentation key_representation,
+ const base::flat_set<std::string>& hint_keys) = 0;
+
+ // If a cache of notifications overflowed and the set of hints to invalidate
+ // were lost, this asks the delegate to purge the whole database.
+ virtual void PurgeFetchedEntries(base::OnceClosure on_success) = 0;
+ };
+
+ virtual ~PushNotificationManager() = default;
+
+ // Sets |this|'s delegate.
+ virtual void SetDelegate(Delegate* delegate) = 0;
+
+ // Informs |this| that the delegate is ready to process pushed hints.
+ virtual void OnDelegateReady() = 0;
+
+ // Called when a new push notification arrives.
+ virtual void OnNewPushNotification(
+ const proto::HintNotificationPayload& notification) = 0;
+};
+
+} // namespace optimization_guide
+
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_PUSH_NOTIFICATION_MANAGER_H_
diff --git a/chromium/components/optimization_guide/core/store_update_data.cc b/chromium/components/optimization_guide/core/store_update_data.cc
index 4713c17d04c..8ef2b519673 100644
--- a/chromium/components/optimization_guide/core/store_update_data.cc
+++ b/chromium/components/optimization_guide/core/store_update_data.cc
@@ -19,17 +19,17 @@ std::unique_ptr<StoreUpdateData>
StoreUpdateData::CreateComponentStoreUpdateData(
const base::Version& component_version) {
return base::WrapUnique<StoreUpdateData>(new StoreUpdateData(
- base::Optional<base::Version>(component_version),
- base::Optional<base::Time>(), base::Optional<base::Time>()));
+ absl::optional<base::Version>(component_version),
+ absl::optional<base::Time>(), absl::optional<base::Time>()));
}
// static
std::unique_ptr<StoreUpdateData> StoreUpdateData::CreateFetchedStoreUpdateData(
base::Time fetch_update_time) {
return base::WrapUnique<StoreUpdateData>(
- new StoreUpdateData(base::Optional<base::Version>(),
- base::Optional<base::Time>(fetch_update_time),
- base::Optional<base::Time>()));
+ new StoreUpdateData(absl::optional<base::Version>(),
+ absl::optional<base::Time>(fetch_update_time),
+ absl::optional<base::Time>()));
}
// static
@@ -85,9 +85,9 @@ StoreUpdateData::StoreUpdateData(base::Time expiry_time)
}
StoreUpdateData::StoreUpdateData(
- base::Optional<base::Version> component_version,
- base::Optional<base::Time> fetch_update_time,
- base::Optional<base::Time> expiry_time)
+ absl::optional<base::Version> component_version,
+ absl::optional<base::Time> fetch_update_time,
+ absl::optional<base::Time> expiry_time)
: component_version_(component_version),
update_time_(fetch_update_time),
expiry_time_(expiry_time),
diff --git a/chromium/components/optimization_guide/core/store_update_data.h b/chromium/components/optimization_guide/core/store_update_data.h
index bb6ed0c32c1..9dfd6455307 100644
--- a/chromium/components/optimization_guide/core/store_update_data.h
+++ b/chromium/components/optimization_guide/core/store_update_data.h
@@ -8,11 +8,11 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/version.h"
#include "components/leveldb_proto/public/proto_database.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace optimization_guide {
namespace proto {
@@ -50,15 +50,15 @@ class StoreUpdateData {
base::Time expiry_time);
// Returns the component version of a component hint update.
- const base::Optional<base::Version> component_version() const {
+ const absl::optional<base::Version> component_version() const {
return component_version_;
}
// Returns the next update time for the entries in the store update.
- const base::Optional<base::Time> update_time() const { return update_time_; }
+ const absl::optional<base::Time> update_time() const { return update_time_; }
// Returns the expiry time for the hints in a fetched hint update.
- const base::Optional<base::Time> expiry_time() const { return expiry_time_; }
+ const absl::optional<base::Time> expiry_time() const { return expiry_time_; }
// Moves |hint| into this update data. After MoveHintIntoUpdateData() is
// called, |hint| is no longer valid.
@@ -76,21 +76,21 @@ class StoreUpdateData {
std::unique_ptr<EntryVector> TakeUpdateEntries();
private:
- StoreUpdateData(base::Optional<base::Version> component_version,
- base::Optional<base::Time> fetch_update_time,
- base::Optional<base::Time> expiry_time);
+ StoreUpdateData(absl::optional<base::Version> component_version,
+ absl::optional<base::Time> fetch_update_time,
+ absl::optional<base::Time> expiry_time);
StoreUpdateData(base::Time host_model_features_update_time,
base::Time expiry_time);
explicit StoreUpdateData(base::Time expiry_time);
// The component version of the update data for a component update.
- base::Optional<base::Version> component_version_;
+ absl::optional<base::Version> component_version_;
// The time when the entries in this update need to be updated.
- base::Optional<base::Time> update_time_;
+ absl::optional<base::Time> update_time_;
// The time when entries in this update expire.
- base::Optional<base::Time> expiry_time_;
+ absl::optional<base::Time> expiry_time_;
// The prefix to add to the key of every store entry. It is set
// during construction for appropriate type of update.
diff --git a/chromium/components/optimization_guide/core/test_optimization_guide_model_provider.cc b/chromium/components/optimization_guide/core/test_optimization_guide_model_provider.cc
new file mode 100644
index 00000000000..8cf7af1ee38
--- /dev/null
+++ b/chromium/components/optimization_guide/core/test_optimization_guide_model_provider.cc
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
+
+namespace optimization_guide {
+
+TestOptimizationGuideModelProvider::TestOptimizationGuideModelProvider() =
+ default;
+TestOptimizationGuideModelProvider::~TestOptimizationGuideModelProvider() =
+ default;
+
+void TestOptimizationGuideModelProvider::AddObserverForOptimizationTargetModel(
+ optimization_guide::proto::OptimizationTarget optimization_target,
+ const absl::optional<proto::Any>& model_metadata,
+ optimization_guide::OptimizationTargetModelObserver* observer) {}
+
+void TestOptimizationGuideModelProvider::
+ RemoveObserverForOptimizationTargetModel(
+ optimization_guide::proto::OptimizationTarget optimization_target,
+ optimization_guide::OptimizationTargetModelObserver* observer) {}
+
+} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/core/test_optimization_guide_model_provider.h b/chromium/components/optimization_guide/core/test_optimization_guide_model_provider.h
new file mode 100644
index 00000000000..a29d25302c0
--- /dev/null
+++ b/chromium/components/optimization_guide/core/test_optimization_guide_model_provider.h
@@ -0,0 +1,37 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_CORE_TEST_OPTIMIZATION_GUIDE_MODEL_PROVIDER_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_CORE_TEST_OPTIMIZATION_GUIDE_MODEL_PROVIDER_H_
+
+#include "components/optimization_guide/core/optimization_guide_model_provider.h"
+
+namespace optimization_guide {
+
+// An implementation of |OptimizationGuideModelProvider| that can be selectively
+// mocked out for unit testing features that rely on the Optimization Guide in
+// //components/...
+class TestOptimizationGuideModelProvider
+ : public OptimizationGuideModelProvider {
+ public:
+ TestOptimizationGuideModelProvider();
+ ~TestOptimizationGuideModelProvider() override;
+ TestOptimizationGuideModelProvider(
+ const TestOptimizationGuideModelProvider&) = delete;
+ TestOptimizationGuideModelProvider& operator=(
+ const TestOptimizationGuideModelProvider&) = delete;
+
+ // OptimizationGuideModelProvider implementation:
+ void AddObserverForOptimizationTargetModel(
+ proto::OptimizationTarget optimization_target,
+ const absl::optional<proto::Any>& model_metadata,
+ OptimizationTargetModelObserver* observer) override;
+ void RemoveObserverForOptimizationTargetModel(
+ proto::OptimizationTarget optimization_target,
+ OptimizationTargetModelObserver* observer) override;
+};
+
+} // namespace optimization_guide
+
+#endif // COMPONENTS_OPTIMIZATION_GUIDE_CORE_TEST_OPTIMIZATION_GUIDE_MODEL_PROVIDER_H_
diff --git a/chromium/components/optimization_guide/core/tflite_op_resolver.cc b/chromium/components/optimization_guide/core/tflite_op_resolver.cc
index 9d65a4866ec..1cd89433031 100644
--- a/chromium/components/optimization_guide/core/tflite_op_resolver.cc
+++ b/chromium/components/optimization_guide/core/tflite_op_resolver.cc
@@ -70,7 +70,7 @@ TFLiteOpResolver::TFLiteOpResolver() {
AddBuiltin(tflite::BuiltinOperator_FULLY_CONNECTED,
tflite::ops::builtin::Register_FULLY_CONNECTED(),
/* min_version = */ 1,
- /* max_version = */ 8);
+ /* max_version = */ 9);
AddBuiltin(tflite::BuiltinOperator_LSH_PROJECTION,
tflite::ops::builtin::Register_LSH_PROJECTION());
AddBuiltin(tflite::BuiltinOperator_HASHTABLE_LOOKUP,
@@ -370,7 +370,7 @@ TFLiteOpResolver::TFLiteOpResolver() {
AddBuiltin(tflite::BuiltinOperator_BATCH_MATMUL,
tflite::ops::builtin::Register_BATCH_MATMUL(),
/* min_version = */ 1,
- /* max_version = */ 2);
+ /* max_version = */ 4);
}
} // namespace optimization_guide
diff --git a/chromium/components/optimization_guide/features.gni b/chromium/components/optimization_guide/features.gni
index 7c43da5f2fc..f5fa26d3e3c 100644
--- a/chromium/components/optimization_guide/features.gni
+++ b/chromium/components/optimization_guide/features.gni
@@ -5,8 +5,6 @@
declare_args() {
# This enables build with TFLite library.
# Currently only available for Desktop and Android.
- # Disable tflite build on Windows on ARM
- # http://crbug.com/1169611
- build_with_tflite_lib = is_android || (is_win && target_cpu != "arm64") ||
- is_linux || is_mac || is_chromeos
+ build_with_tflite_lib =
+ is_android || is_win || is_linux || is_mac || is_chromeos
}
diff --git a/chromium/components/optimization_guide/proto/BUILD.gn b/chromium/components/optimization_guide/proto/BUILD.gn
index d85a4f85530..51136ae7029 100644
--- a/chromium/components/optimization_guide/proto/BUILD.gn
+++ b/chromium/components/optimization_guide/proto/BUILD.gn
@@ -9,6 +9,7 @@ if (is_android) {
}
proto_library("optimization_guide_proto") {
+ proto_in_dir = "//"
sources = [
"common_types.proto",
"delay_async_script_execution_metadata.proto",
@@ -21,12 +22,13 @@ proto_library("optimization_guide_proto") {
"page_topics_model_metadata.proto",
"performance_hints_metadata.proto",
"public_image_metadata.proto",
+ "push_notification.proto",
]
}
if (is_android) {
proto_java_library("optimization_guide_proto_java") {
- proto_path = "."
+ proto_path = "//"
sources = [
"common_types.proto",
"delay_async_script_execution_metadata.proto",
@@ -37,6 +39,7 @@ if (is_android) {
"models.proto",
"performance_hints_metadata.proto",
"public_image_metadata.proto",
+ "push_notification.proto",
]
}
}
diff --git a/chromium/components/optimization_guide/proto/delay_async_script_execution_metadata.proto b/chromium/components/optimization_guide/proto/delay_async_script_execution_metadata.proto
index a707460ee0d..a502c520864 100644
--- a/chromium/components/optimization_guide/proto/delay_async_script_execution_metadata.proto
+++ b/chromium/components/optimization_guide/proto/delay_async_script_execution_metadata.proto
@@ -10,7 +10,7 @@ option java_outer_classname = "DelayAsyncScriptExecutionMetadataProto";
package optimization_guide.proto;
-import "common_types.proto";
+import "components/optimization_guide/proto/common_types.proto";
// Optimization metadata for OptimizationType::DELAY_ASYNC_SCRIPT_EXECUTION.
message DelayAsyncScriptExecutionMetadata {
diff --git a/chromium/components/optimization_guide/proto/delay_competing_low_priority_requests_metadata.proto b/chromium/components/optimization_guide/proto/delay_competing_low_priority_requests_metadata.proto
index 12b6fe1e1ae..28d2f057332 100644
--- a/chromium/components/optimization_guide/proto/delay_competing_low_priority_requests_metadata.proto
+++ b/chromium/components/optimization_guide/proto/delay_competing_low_priority_requests_metadata.proto
@@ -10,7 +10,7 @@ option java_outer_classname = "DelayCompetingLowPriorityRequestsMetadataProto";
package optimization_guide.proto;
-import "common_types.proto";
+import "components/optimization_guide/proto/common_types.proto";
// Enumerates the different request priorities that the Chromium experiment will
// consider "important". For example, low priority requests will be queued
diff --git a/chromium/components/optimization_guide/proto/hint_cache.proto b/chromium/components/optimization_guide/proto/hint_cache.proto
index 255a74d42c8..a27430d3e53 100644
--- a/chromium/components/optimization_guide/proto/hint_cache.proto
+++ b/chromium/components/optimization_guide/proto/hint_cache.proto
@@ -8,8 +8,8 @@ option optimize_for = LITE_RUNTIME;
package optimization_guide.proto;
-import "hints.proto";
-import "models.proto";
+import "components/optimization_guide/proto/hints.proto";
+import "components/optimization_guide/proto/models.proto";
// The types of StoreEntries.
//
diff --git a/chromium/components/optimization_guide/proto/hints.proto b/chromium/components/optimization_guide/proto/hints.proto
index 70995a6eb14..18fa7cee9ee 100644
--- a/chromium/components/optimization_guide/proto/hints.proto
+++ b/chromium/components/optimization_guide/proto/hints.proto
@@ -9,10 +9,10 @@ option java_outer_classname = "HintsProto";
package optimization_guide.proto;
-import "common_types.proto";
-import "loading_predictor_metadata.proto";
-import "performance_hints_metadata.proto";
-import "public_image_metadata.proto";
+import "components/optimization_guide/proto/common_types.proto";
+import "components/optimization_guide/proto/loading_predictor_metadata.proto";
+import "components/optimization_guide/proto/performance_hints_metadata.proto";
+import "components/optimization_guide/proto/public_image_metadata.proto";
// Information about the hint that the client already has for a host.
message MatchedHintInfo {
diff --git a/chromium/components/optimization_guide/proto/lite_video_metadata.proto b/chromium/components/optimization_guide/proto/lite_video_metadata.proto
index 490d3c0f212..b9144968a4d 100644
--- a/chromium/components/optimization_guide/proto/lite_video_metadata.proto
+++ b/chromium/components/optimization_guide/proto/lite_video_metadata.proto
@@ -10,7 +10,7 @@ option java_outer_classname = "LiteVideoMetadataProto";
package optimization_guide.proto;
-import "common_types.proto";
+import "components/optimization_guide/proto/common_types.proto";
message LiteVideoHint {
// The target video resolution for throttling. Initially unused.
diff --git a/chromium/components/optimization_guide/proto/models.proto b/chromium/components/optimization_guide/proto/models.proto
index 18216060e74..6bf371b943e 100644
--- a/chromium/components/optimization_guide/proto/models.proto
+++ b/chromium/components/optimization_guide/proto/models.proto
@@ -9,7 +9,7 @@ option java_outer_classname = "ModelsProto";
package optimization_guide.proto;
-import "common_types.proto";
+import "components/optimization_guide/proto/common_types.proto";
// A generic handle for any type of model.
message Model {
@@ -151,10 +151,10 @@ message DoubleValue {
// Requests prediction models to be used for a set of optimization targets.
message GetModelsRequest {
+ reserved 2;
+
// Information about the requested models.
repeated ModelInfo requested_models = 1;
- // The set of hosts to get additional metadata for, if applicable.
- repeated string hosts = 2;
// Context in which this request is made.
//
// If the context matches one that requires more urgency (i.e.
@@ -230,6 +230,12 @@ enum OptimizationTarget {
OPTIMIZATION_TARGET_LANGUAGE_DETECTION = 2;
// Target for determining topics present on a page.
OPTIMIZATION_TARGET_PAGE_TOPICS = 3;
+ // Target for segmentation: New tab page user.
+ OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB = 4;
+ // Target for segmentation: Share user.
+ OPTIMIZATION_TARGET_SEGMENTATION_SHARE = 5;
+ // Target for segmentation: Voice user.
+ OPTIMIZATION_TARGET_SEGMENTATION_VOICE = 6;
}
// The types of models that can be evaluated.
@@ -239,6 +245,9 @@ enum ModelType {
MODEL_TYPE_DECISION_TREE = 1;
// A model using only operations that are supported by TensorflowLite 2.3.0.
MODEL_TYPE_TFLITE_2_3_0 = 2;
+ // A model using only operations that are supported by TensorflowLite 2.3.0
+ // with updated FULLY_CONNECTED and BATCH_MUL versions for quantized models.
+ MODEL_TYPE_TFLITE_2_3_0_1 = 3;
}
// A set of model features and the host that it applies to.
diff --git a/chromium/components/optimization_guide/proto/push_notification.proto b/chromium/components/optimization_guide/proto/push_notification.proto
new file mode 100644
index 00000000000..a95552d2849
--- /dev/null
+++ b/chromium/components/optimization_guide/proto/push_notification.proto
@@ -0,0 +1,29 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+option java_package = "org.chromium.components.optimization_guide.proto";
+option java_outer_classname = "PushNotificationProto";
+
+package optimization_guide.proto;
+
+import "components/optimization_guide/proto/common_types.proto";
+import "components/optimization_guide/proto/hints.proto";
+
+// This message is attached as a payload to push notifications in Optimization
+// Guide and contains all the needed information to invalidate stored hints that
+// the notification is meant to supersede, as well as an Any payload that can be
+// passed to consumers.
+message HintNotificationPayload {
+ optional OptimizationType optimization_type = 1;
+
+ // This is the unique key that will get cleared from the persistent hint store
+ // for the given optimization type. The |hint_key| must match exactly for
+ // hints to be cleared.
+ optional KeyRepresentation key_representation = 2;
+ optional string hint_key = 3;
+
+ optional Any payload = 4;
+}
diff --git a/chromium/components/os_crypt/BUILD.gn b/chromium/components/os_crypt/BUILD.gn
index 79f9744a94d..bd376411505 100644
--- a/chromium/components/os_crypt/BUILD.gn
+++ b/chromium/components/os_crypt/BUILD.gn
@@ -49,8 +49,13 @@ component("os_crypt") {
"//crypto:platform",
]
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
defines = [ "IS_OS_CRYPT_IMPL" ]
+ if (allow_runtime_configurable_key_storage) {
+ defines += [ "ALLOW_RUNTIME_CONFIGURABLE_KEY_STORAGE" ]
+ }
+
if ((is_posix || is_fuchsia) && !is_apple &&
(!(is_linux || is_chromeos_lacros) || is_chromecast)) {
sources += [ "os_crypt_posix.cc" ]
diff --git a/chromium/components/os_crypt/features.gni b/chromium/components/os_crypt/features.gni
index a145e0530d3..73b6e870329 100644
--- a/chromium/components/os_crypt/features.gni
+++ b/chromium/components/os_crypt/features.gni
@@ -9,4 +9,10 @@ declare_args() {
# Whether to use libgnome-keyring (deprecated by libsecret).
# See http://crbug.com/466975 and http://crbug.com/355223.
use_gnome_keyring = (is_linux || is_chromeos_lacros) && use_glib
+
+ # Whether to make account and service names for the crypto key storage
+ # configurable at runtime for embedders.
+ #
+ # Currently only has an effect on macOS via KeychainPassword
+ allow_runtime_configurable_key_storage = false
}
diff --git a/chromium/components/os_crypt/key_storage_config_linux.h b/chromium/components/os_crypt/key_storage_config_linux.h
index a856604756a..72c16682e5d 100644
--- a/chromium/components/os_crypt/key_storage_config_linux.h
+++ b/chromium/components/os_crypt/key_storage_config_linux.h
@@ -26,6 +26,12 @@ struct COMPONENT_EXPORT(OS_CRYPT) Config {
std::string store;
// The product name to use for permission prompts.
std::string product_name;
+ // The application name to store the key under. For Chromium/Chrome builds
+ // leave this unset and it will default correctly. This config option is
+ // for embedders to provide their application name in place of "Chromium".
+ // Only used when the allow_runtime_configurable_key_storage feature is
+ // enabled.
+ std::string application_name;
// A runner on the main thread for gnome-keyring to be called from.
// TODO(crbug/466975): Libsecret and KWallet don't need this. We can remove
// this when we stop supporting keyring.
diff --git a/chromium/components/os_crypt/key_storage_keyring.cc b/chromium/components/os_crypt/key_storage_keyring.cc
index 409bd27cbc0..3ad654cf4a8 100644
--- a/chromium/components/os_crypt/key_storage_keyring.cc
+++ b/chromium/components/os_crypt/key_storage_keyring.cc
@@ -15,12 +15,6 @@
namespace {
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-const char kApplicationName[] = "chrome";
-#else
-const char kApplicationName[] = "chromium";
-#endif
-
const GnomeKeyringPasswordSchema kSchema = {
GNOME_KEYRING_ITEM_GENERIC_SECRET,
{{"application", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING}, {nullptr}}};
@@ -28,8 +22,10 @@ const GnomeKeyringPasswordSchema kSchema = {
} // namespace
KeyStorageKeyring::KeyStorageKeyring(
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner)
- : main_thread_runner_(main_thread_runner) {}
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner,
+ std::string application_name)
+ : main_thread_runner_(main_thread_runner),
+ application_name_(std::move(application_name)) {}
KeyStorageKeyring::~KeyStorageKeyring() {}
@@ -42,14 +38,15 @@ bool KeyStorageKeyring::Init() {
return GnomeKeyringLoader::LoadGnomeKeyring();
}
-base::Optional<std::string> KeyStorageKeyring::GetKeyImpl() {
+absl::optional<std::string> KeyStorageKeyring::GetKeyImpl() {
DCHECK(main_thread_runner_->RunsTasksInCurrentSequence());
- base::Optional<std::string> password;
+ absl::optional<std::string> password;
gchar* password_c = nullptr;
GnomeKeyringResult result =
GnomeKeyringLoader::gnome_keyring_find_password_sync_ptr(
- &kSchema, &password_c, "application", kApplicationName, nullptr);
+ &kSchema, &password_c, "application", application_name_.c_str(),
+ nullptr);
if (result == GNOME_KEYRING_RESULT_OK) {
password = password_c;
GnomeKeyringLoader::gnome_keyring_free_password_ptr(password_c);
@@ -62,7 +59,7 @@ base::Optional<std::string> KeyStorageKeyring::GetKeyImpl() {
return password;
}
-base::Optional<std::string> KeyStorageKeyring::AddRandomPasswordInKeyring() {
+absl::optional<std::string> KeyStorageKeyring::AddRandomPasswordInKeyring() {
// Generate password
std::string password;
base::Base64Encode(base::RandBytesAsString(16), &password);
@@ -71,10 +68,10 @@ base::Optional<std::string> KeyStorageKeyring::AddRandomPasswordInKeyring() {
GnomeKeyringResult result =
GnomeKeyringLoader::gnome_keyring_store_password_sync_ptr(
&kSchema, nullptr /* default keyring */, KeyStorageLinux::kKey,
- password.c_str(), "application", kApplicationName, nullptr);
+ password.c_str(), "application", application_name_.c_str(), nullptr);
if (result != GNOME_KEYRING_RESULT_OK) {
VLOG(1) << "OSCrypt failed to store generated password to gnome-keyring";
- return base::nullopt;
+ return absl::nullopt;
}
VLOG(1) << "OSCrypt generated a new password and stored it to gnome-keyring";
diff --git a/chromium/components/os_crypt/key_storage_keyring.h b/chromium/components/os_crypt/key_storage_keyring.h
index 6406f282599..598c8b8ad35 100644
--- a/chromium/components/os_crypt/key_storage_keyring.h
+++ b/chromium/components/os_crypt/key_storage_keyring.h
@@ -10,8 +10,8 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "components/os_crypt/key_storage_linux.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class SingleThreadTaskRunner;
@@ -20,23 +20,26 @@ class SingleThreadTaskRunner;
// Specialisation of KeyStorageLinux that uses Libsecret.
class COMPONENT_EXPORT(OS_CRYPT) KeyStorageKeyring : public KeyStorageLinux {
public:
- explicit KeyStorageKeyring(
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner);
+ KeyStorageKeyring(
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner,
+ std::string application_name);
~KeyStorageKeyring() override;
protected:
// KeyStorageLinux
base::SequencedTaskRunner* GetTaskRunner() override;
bool Init() override;
- base::Optional<std::string> GetKeyImpl() override;
+ absl::optional<std::string> GetKeyImpl() override;
private:
// Generate a random string and store it as OScrypt's new password.
- base::Optional<std::string> AddRandomPasswordInKeyring();
+ absl::optional<std::string> AddRandomPasswordInKeyring();
// Keyring calls need to originate from the main thread.
scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner_;
+ const std::string application_name_;
+
DISALLOW_COPY_AND_ASSIGN(KeyStorageKeyring);
};
diff --git a/chromium/components/os_crypt/key_storage_keyring_unittest.cc b/chromium/components/os_crypt/key_storage_keyring_unittest.cc
index 010febfe974..93fc216d541 100644
--- a/chromium/components/os_crypt/key_storage_keyring_unittest.cc
+++ b/chromium/components/os_crypt/key_storage_keyring_unittest.cc
@@ -130,7 +130,7 @@ class GnomeKeyringTest : public testing::Test {
};
GnomeKeyringTest::GnomeKeyringTest()
- : task_runner_(new base::TestSimpleTaskRunner()), keyring_(task_runner_) {
+ : task_runner_(new base::TestSimpleTaskRunner()), keyring_(task_runner_, "chromium") {
MockGnomeKeyringLoader::ResetForOSCrypt();
}
@@ -139,18 +139,18 @@ GnomeKeyringTest::~GnomeKeyringTest() {
}
TEST_F(GnomeKeyringTest, KeyringRepeats) {
- base::Optional<std::string> password = keyring_.GetKey();
+ absl::optional<std::string> password = keyring_.GetKey();
EXPECT_TRUE(password.has_value());
EXPECT_FALSE(password.value().empty());
- base::Optional<std::string> password_repeat = keyring_.GetKey();
+ absl::optional<std::string> password_repeat = keyring_.GetKey();
EXPECT_TRUE(password_repeat.has_value());
EXPECT_EQ(password.value(), password_repeat.value());
}
TEST_F(GnomeKeyringTest, KeyringCreatesRandomised) {
- base::Optional<std::string> password = keyring_.GetKey();
+ absl::optional<std::string> password = keyring_.GetKey();
MockGnomeKeyringLoader::ResetForOSCrypt();
- base::Optional<std::string> password_new = keyring_.GetKey();
+ absl::optional<std::string> password_new = keyring_.GetKey();
EXPECT_TRUE(password.has_value());
EXPECT_TRUE(password_new.has_value());
EXPECT_NE(password.value(), password_new.value());
diff --git a/chromium/components/os_crypt/key_storage_kwallet.cc b/chromium/components/os_crypt/key_storage_kwallet.cc
index 10eb2a15cf7..f5d01ff4c9f 100644
--- a/chromium/components/os_crypt/key_storage_kwallet.cc
+++ b/chromium/components/os_crypt/key_storage_kwallet.cc
@@ -80,24 +80,24 @@ KeyStorageKWallet::InitResult KeyStorageKWallet::InitWallet() {
return InitResult::PERMANENT_FAIL;
}
-base::Optional<std::string> KeyStorageKWallet::GetKeyImpl() {
+absl::optional<std::string> KeyStorageKWallet::GetKeyImpl() {
// Get handle
KWalletDBus::Error error =
kwallet_dbus_->Open(wallet_name_, app_name_, &handle_);
if (error || handle_ == kInvalidHandle)
- return base::nullopt;
+ return absl::nullopt;
// Create folder
if (!InitFolder())
- return base::nullopt;
+ return absl::nullopt;
// Read password
- base::Optional<std::string> password;
+ absl::optional<std::string> password;
error =
kwallet_dbus_->ReadPassword(handle_, KeyStorageLinux::kFolderName,
KeyStorageLinux::kKey, app_name_, &password);
if (error)
- return base::nullopt;
+ return absl::nullopt;
// If there is no entry, generate and write a new password.
if (!password.has_value()) {
@@ -108,7 +108,7 @@ base::Optional<std::string> KeyStorageKWallet::GetKeyImpl() {
KeyStorageLinux::kKey, password_,
app_name_, &success);
if (error || !success)
- return base::nullopt;
+ return absl::nullopt;
password = std::move(password_);
}
diff --git a/chromium/components/os_crypt/key_storage_kwallet.h b/chromium/components/os_crypt/key_storage_kwallet.h
index 6fdff4116b5..6f48d43c528 100644
--- a/chromium/components/os_crypt/key_storage_kwallet.h
+++ b/chromium/components/os_crypt/key_storage_kwallet.h
@@ -26,7 +26,7 @@ class COMPONENT_EXPORT(OS_CRYPT) KeyStorageKWallet : public KeyStorageLinux {
protected:
// KeyStorageLinux
bool Init() override;
- base::Optional<std::string> GetKeyImpl() override;
+ absl::optional<std::string> GetKeyImpl() override;
private:
enum class InitResult {
diff --git a/chromium/components/os_crypt/key_storage_kwallet_unittest.cc b/chromium/components/os_crypt/key_storage_kwallet_unittest.cc
index d7866d94579..90daa364a38 100644
--- a/chromium/components/os_crypt/key_storage_kwallet_unittest.cc
+++ b/chromium/components/os_crypt/key_storage_kwallet_unittest.cc
@@ -77,7 +77,7 @@ class MockKWalletDBus : public KWalletDBus {
const std::string&,
const std::string&,
const std::string&,
- base::Optional<std::string>*));
+ absl::optional<std::string>*));
MOCK_METHOD6(WritePassword,
KWalletDBus::Error(int,
@@ -164,7 +164,7 @@ TEST_F(KeyStorageKWalletTest, GenerateNewPassword) {
.WillOnce(DoAll(SetArgPointee<3>(true), Return(SUCCESS)));
EXPECT_CALL(*kwallet_dbus_mock_,
ReadPassword(123, kExpectedFolderName, kExpectedEntryName, _, _))
- .WillOnce(DoAll(SetArgPointee<4>(base::nullopt), Return(SUCCESS)));
+ .WillOnce(DoAll(SetArgPointee<4>(absl::nullopt), Return(SUCCESS)));
EXPECT_CALL(*kwallet_dbus_mock_, WritePassword(123, kExpectedFolderName,
kExpectedEntryName, _, _, _))
.WillOnce(DoAll(SaveArg<3>(&generated_password), SetArgPointee<5>(true),
@@ -309,7 +309,7 @@ TEST_P(KeyStorageKWalletFailuresTest, PostInitFailureWritePassword) {
EXPECT_CALL(*kwallet_dbus_mock_, HasFolder(123, _, _, _))
.WillOnce(DoAll(SetArgPointee<3>(true), Return(SUCCESS)));
EXPECT_CALL(*kwallet_dbus_mock_, ReadPassword(123, _, _, _, _))
- .WillOnce(DoAll(SetArgPointee<4>(base::nullopt), Return(SUCCESS)));
+ .WillOnce(DoAll(SetArgPointee<4>(absl::nullopt), Return(SUCCESS)));
EXPECT_CALL(*kwallet_dbus_mock_, WritePassword(123, _, _, _, _, _))
.WillOnce(Return(GetParam()));
diff --git a/chromium/components/os_crypt/key_storage_libsecret.cc b/chromium/components/os_crypt/key_storage_libsecret.cc
index 312570612cc..ccc60522791 100644
--- a/chromium/components/os_crypt/key_storage_libsecret.cc
+++ b/chromium/components/os_crypt/key_storage_libsecret.cc
@@ -14,12 +14,6 @@
namespace {
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-const char kApplicationName[] = "chrome";
-#else
-const char kApplicationName[] = "chromium";
-#endif
-
const SecretSchema kKeystoreSchemaV2 = {
"chrome_libsecret_os_crypt_password_v2",
SECRET_SCHEMA_DONT_MATCH_NAME,
@@ -64,38 +58,41 @@ void AnalyseKeyHistory(GList* secret_items) {
} // namespace
-base::Optional<std::string>
+KeyStorageLibsecret::KeyStorageLibsecret(std::string application_name)
+ : application_name_(std::move(application_name)) {}
+
+absl::optional<std::string>
KeyStorageLibsecret::AddRandomPasswordInLibsecret() {
std::string password;
base::Base64Encode(base::RandBytesAsString(16), &password);
GError* error = nullptr;
bool success = LibsecretLoader::secret_password_store_sync(
&kKeystoreSchemaV2, nullptr, KeyStorageLinux::kKey, password.c_str(),
- nullptr, &error, "application", kApplicationName, nullptr);
+ nullptr, &error, "application", application_name_.c_str(), nullptr);
if (error) {
VLOG(1) << "Libsecret lookup failed: " << error->message;
g_error_free(error);
- return base::nullopt;
+ return absl::nullopt;
}
if (!success) {
VLOG(1) << "Libsecret lookup failed.";
- return base::nullopt;
+ return absl::nullopt;
}
VLOG(1) << "OSCrypt generated a new password.";
return password;
}
-base::Optional<std::string> KeyStorageLibsecret::GetKeyImpl() {
+absl::optional<std::string> KeyStorageLibsecret::GetKeyImpl() {
LibsecretAttributesBuilder attrs;
- attrs.Append("application", kApplicationName);
+ attrs.Append("application", application_name_);
LibsecretLoader::SearchHelper helper;
helper.Search(&kKeystoreSchemaV2, attrs.Get(),
SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS);
if (!helper.success()) {
VLOG(1) << "Libsecret lookup failed: " << helper.error()->message;
- return base::nullopt;
+ return absl::nullopt;
}
SecretValue* password_libsecret = ToSingleSecret(helper.results());
@@ -103,7 +100,7 @@ base::Optional<std::string> KeyStorageLibsecret::GetKeyImpl() {
return AddRandomPasswordInLibsecret();
}
AnalyseKeyHistory(helper.results());
- base::Optional<std::string> password(
+ absl::optional<std::string> password(
LibsecretLoader::secret_value_get_text(password_libsecret));
LibsecretLoader::secret_value_unref(password_libsecret);
return password;
diff --git a/chromium/components/os_crypt/key_storage_libsecret.h b/chromium/components/os_crypt/key_storage_libsecret.h
index e59a2a1b5a7..5292e21b8e7 100644
--- a/chromium/components/os_crypt/key_storage_libsecret.h
+++ b/chromium/components/os_crypt/key_storage_libsecret.h
@@ -9,22 +9,24 @@
#include "base/component_export.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/os_crypt/key_storage_linux.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
// Specialisation of KeyStorageLinux that uses Libsecret.
class COMPONENT_EXPORT(OS_CRYPT) KeyStorageLibsecret : public KeyStorageLinux {
public:
- KeyStorageLibsecret() = default;
+ explicit KeyStorageLibsecret(std::string application_name);
~KeyStorageLibsecret() override = default;
protected:
// KeyStorageLinux
bool Init() override;
- base::Optional<std::string> GetKeyImpl() override;
+ absl::optional<std::string> GetKeyImpl() override;
private:
- base::Optional<std::string> AddRandomPasswordInLibsecret();
+ absl::optional<std::string> AddRandomPasswordInLibsecret();
+
+ const std::string application_name_;
DISALLOW_COPY_AND_ASSIGN(KeyStorageLibsecret);
};
diff --git a/chromium/components/os_crypt/key_storage_libsecret_unittest.cc b/chromium/components/os_crypt/key_storage_libsecret_unittest.cc
index ca54c3f27b4..a17bbc1f806 100644
--- a/chromium/components/os_crypt/key_storage_libsecret_unittest.cc
+++ b/chromium/components/os_crypt/key_storage_libsecret_unittest.cc
@@ -236,23 +236,23 @@ class LibsecretTest : public testing::Test {
};
TEST_F(LibsecretTest, LibsecretRepeats) {
- KeyStorageLibsecret libsecret;
+ KeyStorageLibsecret libsecret("chromium");
MockLibsecretLoader::ResetForOSCrypt();
g_password_store.Pointer()->SetPassword("initial password");
- base::Optional<std::string> password = libsecret.GetKey();
+ absl::optional<std::string> password = libsecret.GetKey();
EXPECT_TRUE(password.has_value());
EXPECT_FALSE(password.value().empty());
- base::Optional<std::string> password_repeat = libsecret.GetKey();
+ absl::optional<std::string> password_repeat = libsecret.GetKey();
EXPECT_TRUE(password_repeat.has_value());
EXPECT_EQ(password.value(), password_repeat.value());
}
TEST_F(LibsecretTest, LibsecretCreatesRandomised) {
- KeyStorageLibsecret libsecret;
+ KeyStorageLibsecret libsecret("chromium");
MockLibsecretLoader::ResetForOSCrypt();
- base::Optional<std::string> password = libsecret.GetKey();
+ absl::optional<std::string> password = libsecret.GetKey();
MockLibsecretLoader::ResetForOSCrypt();
- base::Optional<std::string> password_new = libsecret.GetKey();
+ absl::optional<std::string> password_new = libsecret.GetKey();
EXPECT_TRUE(password.has_value());
EXPECT_TRUE(password_new.has_value());
EXPECT_NE(password.value(), password_new.value());
diff --git a/chromium/components/os_crypt/key_storage_linux.cc b/chromium/components/os_crypt/key_storage_linux.cc
index 33fed0fa438..53b1903ff04 100644
--- a/chromium/components/os_crypt/key_storage_linux.cc
+++ b/chromium/components/os_crypt/key_storage_linux.cc
@@ -4,11 +4,14 @@
#include "components/os_crypt/key_storage_linux.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/environment.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/nix/xdg_util.h"
+#include "base/no_destructor.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/task_runner_util.h"
@@ -145,12 +148,29 @@ std::unique_ptr<KeyStorageLinux> KeyStorageLinux::CreateService(
std::unique_ptr<KeyStorageLinux> KeyStorageLinux::CreateServiceInternal(
os_crypt::SelectedLinuxBackend selected_backend,
const os_crypt::Config& config) {
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ static const base::NoDestructor<std::string> kDefaultApplicationName("chrome");
+#else
+ static const base::NoDestructor<std::string> kDefaultApplicationName("chromium");
+#endif
+
std::unique_ptr<KeyStorageLinux> key_storage;
+#if defined(USE_LIBSECRET) || defined(USE_KEYRING)
+#if defined(ALLOW_RUNTIME_CONFIGURABLE_KEY_STORAGE)
+ std::string application_name = config.application_name;
+ if (application_name.empty()) {
+ application_name = *kDefaultApplicationName;
+ }
+#else
+ std::string application_name = *kDefaultApplicationName;
+#endif
+#endif
+
#if defined(USE_LIBSECRET)
if (selected_backend == os_crypt::SelectedLinuxBackend::GNOME_ANY ||
selected_backend == os_crypt::SelectedLinuxBackend::GNOME_LIBSECRET) {
- key_storage.reset(new KeyStorageLibsecret());
+ key_storage = std::make_unique<KeyStorageLibsecret>(std::move(application_name));
if (key_storage->WaitForInitOnTaskRunner()) {
VLOG(1) << "OSCrypt using Libsecret as backend.";
return key_storage;
@@ -162,7 +182,8 @@ std::unique_ptr<KeyStorageLinux> KeyStorageLinux::CreateServiceInternal(
#if defined(USE_KEYRING)
if (selected_backend == os_crypt::SelectedLinuxBackend::GNOME_ANY ||
selected_backend == os_crypt::SelectedLinuxBackend::GNOME_KEYRING) {
- key_storage.reset(new KeyStorageKeyring(config.main_thread_runner));
+ key_storage = std::make_unique<KeyStorageKeyring>(config.main_thread_runner,
+ std::move(application_name));
if (key_storage->WaitForInitOnTaskRunner()) {
VLOG(1) << "OSCrypt using Keyring as backend.";
return key_storage;
@@ -179,8 +200,8 @@ std::unique_ptr<KeyStorageLinux> KeyStorageLinux::CreateServiceInternal(
selected_backend == os_crypt::SelectedLinuxBackend::KWALLET
? base::nix::DESKTOP_ENVIRONMENT_KDE4
: base::nix::DESKTOP_ENVIRONMENT_KDE5;
- key_storage.reset(
- new KeyStorageKWallet(used_desktop_env, config.product_name));
+ key_storage = std::make_unique<KeyStorageKWallet>(used_desktop_env,
+ config.product_name);
if (key_storage->WaitForInitOnTaskRunner()) {
VLOG(1) << "OSCrypt using KWallet as backend.";
return key_storage;
@@ -215,7 +236,7 @@ bool KeyStorageLinux::WaitForInitOnTaskRunner() {
return success;
}
-base::Optional<std::string> KeyStorageLinux::GetKey() {
+absl::optional<std::string> KeyStorageLinux::GetKey() {
base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_sync_primitives;
base::SequencedTaskRunner* task_runner = GetTaskRunner();
@@ -227,7 +248,7 @@ base::Optional<std::string> KeyStorageLinux::GetKey() {
base::WaitableEvent password_loaded(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
- base::Optional<std::string> password;
+ absl::optional<std::string> password;
task_runner->PostTask(
FROM_HERE,
base::BindOnce(&KeyStorageLinux::BlockOnGetKeyImplThenSignal,
@@ -242,7 +263,7 @@ base::SequencedTaskRunner* KeyStorageLinux::GetTaskRunner() {
void KeyStorageLinux::BlockOnGetKeyImplThenSignal(
base::WaitableEvent* on_password_received,
- base::Optional<std::string>* password) {
+ absl::optional<std::string>* password) {
*password = GetKeyImpl();
on_password_received->Signal();
}
diff --git a/chromium/components/os_crypt/key_storage_linux.h b/chromium/components/os_crypt/key_storage_linux.h
index 878425379e0..8afab67f07a 100644
--- a/chromium/components/os_crypt/key_storage_linux.h
+++ b/chromium/components/os_crypt/key_storage_linux.h
@@ -10,8 +10,8 @@
#include "base/component_export.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/os_crypt/key_storage_util_linux.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class SequencedTaskRunner;
@@ -36,7 +36,7 @@ class COMPONENT_EXPORT(OS_CRYPT) KeyStorageLinux {
// Gets the encryption key from the OS password-managing library. If a key is
// not found, a new key will be generated, stored and returned.
- base::Optional<std::string> GetKey();
+ absl::optional<std::string> GetKey();
protected:
// Get the backend's favourite task runner, or nullptr for no preference.
@@ -48,7 +48,7 @@ class COMPONENT_EXPORT(OS_CRYPT) KeyStorageLinux {
// The implementation of GetKey() for a specific backend. This will be called
// on the backend's preferred thread.
- virtual base::Optional<std::string> GetKeyImpl() = 0;
+ virtual absl::optional<std::string> GetKeyImpl() = 0;
// The name of the group, if any, containing the key.
static const char kFolderName[];
@@ -70,7 +70,7 @@ class COMPONENT_EXPORT(OS_CRYPT) KeyStorageLinux {
// Perform the blocking calls to the backend to get the Key. Store it in
// |password| and signal completion on |on_password_received|.
void BlockOnGetKeyImplThenSignal(base::WaitableEvent* on_password_received,
- base::Optional<std::string>* password);
+ absl::optional<std::string>* password);
// Perform the blocking calls to the backend to initialise. Store the
// initialisation result in |success| and signal completion on |on_inited|.
diff --git a/chromium/components/os_crypt/key_storage_linux_unittest.cc b/chromium/components/os_crypt/key_storage_linux_unittest.cc
index ac9895c8cce..1f37bf00d58 100644
--- a/chromium/components/os_crypt/key_storage_linux_unittest.cc
+++ b/chromium/components/os_crypt/key_storage_linux_unittest.cc
@@ -19,7 +19,7 @@ class FakeKeyStorageLinux : public KeyStorageLinux {
protected:
bool Init() override { return true; }
- base::Optional<std::string> GetKeyImpl() override {
+ absl::optional<std::string> GetKeyImpl() override {
return std::string("1234");
}
diff --git a/chromium/components/os_crypt/keychain_password_mac.h b/chromium/components/os_crypt/keychain_password_mac.h
index 6fda0244667..40b2522b879 100644
--- a/chromium/components/os_crypt/keychain_password_mac.h
+++ b/chromium/components/os_crypt/keychain_password_mac.h
@@ -9,6 +9,7 @@
#include "base/component_export.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
namespace crypto {
class AppleKeychain;
@@ -16,6 +17,12 @@ class AppleKeychain;
class COMPONENT_EXPORT(OS_CRYPT) KeychainPassword {
public:
+#if defined(ALLOW_RUNTIME_CONFIGURABLE_KEY_STORAGE)
+ using KeychainNameType = base::NoDestructor<std::string>;
+#else
+ using KeychainNameType = const base::NoDestructor<std::string>;
+#endif
+
KeychainPassword(const crypto::AppleKeychain& keychain);
~KeychainPassword();
@@ -28,8 +35,8 @@ class COMPONENT_EXPORT(OS_CRYPT) KeychainPassword {
std::string GetPassword() const;
// The service and account names used in Chrome's Safe Storage keychain item.
- static COMPONENT_EXPORT(OS_CRYPT) const char service_name[];
- static COMPONENT_EXPORT(OS_CRYPT) const char account_name[];
+ static COMPONENT_EXPORT(OS_CRYPT) KeychainNameType service_name;
+ static COMPONENT_EXPORT(OS_CRYPT) KeychainNameType account_name;
private:
const crypto::AppleKeychain& keychain_;
diff --git a/chromium/components/os_crypt/keychain_password_mac.mm b/chromium/components/os_crypt/keychain_password_mac.mm
index 6654c46eb0a..f8973f5ed0e 100644
--- a/chromium/components/os_crypt/keychain_password_mac.mm
+++ b/chromium/components/os_crypt/keychain_password_mac.mm
@@ -48,11 +48,11 @@ std::string AddRandomPasswordToKeychain(const AppleKeychain& keychain,
// the encryption keyword. So as to not lose encrypted data when system
// locale changes we DO NOT LOCALIZE.
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
-const char KeychainPassword::service_name[] = "Chrome Safe Storage";
-const char KeychainPassword::account_name[] = "Chrome";
+KeychainPassword::KeychainNameType KeychainPassword::service_name("Chrome Safe Storage");
+KeychainPassword::KeychainNameType KeychainPassword::account_name("Chrome");
#else
-const char KeychainPassword::service_name[] = "Chromium Safe Storage";
-const char KeychainPassword::account_name[] = "Chromium";
+KeychainPassword::KeychainNameType KeychainPassword::service_name("Chromium Safe Storage");
+KeychainPassword::KeychainNameType KeychainPassword::account_name("Chromium");
#endif
KeychainPassword::KeychainPassword(const AppleKeychain& keychain)
@@ -64,8 +64,9 @@ std::string KeychainPassword::GetPassword() const {
UInt32 password_length = 0;
void* password_data = nullptr;
OSStatus error = keychain_.FindGenericPassword(
- strlen(service_name), service_name, strlen(account_name), account_name,
- &password_length, &password_data, nullptr);
+ service_name->size(), service_name->c_str(),
+ account_name->size(), account_name->c_str(), &password_length,
+ &password_data, nullptr);
if (error == noErr) {
std::string password =
@@ -75,8 +76,8 @@ std::string KeychainPassword::GetPassword() const {
}
if (error == errSecItemNotFound) {
- std::string password =
- AddRandomPasswordToKeychain(keychain_, service_name, account_name);
+ std::string password = AddRandomPasswordToKeychain(
+ keychain_, *service_name, *account_name);
return password;
}
diff --git a/chromium/components/os_crypt/kwallet_dbus.cc b/chromium/components/os_crypt/kwallet_dbus.cc
index 874a5e48e17..ba4d8395385 100644
--- a/chromium/components/os_crypt/kwallet_dbus.cc
+++ b/chromium/components/os_crypt/kwallet_dbus.cc
@@ -378,7 +378,7 @@ KWalletDBus::Error KWalletDBus::ReadPassword(
const std::string& folder_name,
const std::string& key,
const std::string& app_name,
- base::Optional<std::string>* const password_ptr) {
+ absl::optional<std::string>* const password_ptr) {
dbus::MethodCall method_call(kKWalletInterface, "readPassword");
dbus::MessageWriter builder(&method_call);
builder.AppendInt32(handle);
@@ -396,7 +396,7 @@ KWalletDBus::Error KWalletDBus::ReadPassword(
if (!reader.PopString(&password)) {
LOG(ERROR) << "Error reading response from " << kwalletd_name_
<< " (readPassword): " << response->ToString();
- *password_ptr = base::nullopt;
+ *password_ptr = absl::nullopt;
return CANNOT_READ;
}
*password_ptr = std::move(password);
diff --git a/chromium/components/os_crypt/kwallet_dbus.h b/chromium/components/os_crypt/kwallet_dbus.h
index f9c1c13e4ac..eb507dac7b7 100644
--- a/chromium/components/os_crypt/kwallet_dbus.h
+++ b/chromium/components/os_crypt/kwallet_dbus.h
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/nix/xdg_util.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace dbus {
class Bus;
@@ -119,7 +119,7 @@ class COMPONENT_EXPORT(OS_CRYPT) KWalletDBus {
const std::string& folder_name,
const std::string& key,
const std::string& app_name,
- base::Optional<std::string>* const password_ptr)
+ absl::optional<std::string>* const password_ptr)
WARN_UNUSED_RESULT;
// Close the wallet. The wallet will only be closed if it is open but not in
diff --git a/chromium/components/os_crypt/kwallet_dbus_unittest.cc b/chromium/components/os_crypt/kwallet_dbus_unittest.cc
index a1702ea02a7..08559fcac79 100644
--- a/chromium/components/os_crypt/kwallet_dbus_unittest.cc
+++ b/chromium/components/os_crypt/kwallet_dbus_unittest.cc
@@ -808,7 +808,7 @@ TEST_P(KWalletDBusTest, ReadPassword) {
_))
.WillOnce(Return(ByMove(RespondString("password"))));
- base::Optional<std::string> password;
+ absl::optional<std::string> password;
EXPECT_EQ(KWalletDBus::Error::SUCCESS,
kwallet_dbus_.ReadPassword(123, "folder", "key", "app", &password));
EXPECT_TRUE(password.has_value());
@@ -821,7 +821,7 @@ TEST_P(KWalletDBusTest, ReadPasswordErrorRead) {
CallMethodAndBlock(Calls(kKWalletInterface, "readPassword"), _))
.WillOnce(Return(ByMove(dbus::Response::CreateEmpty())));
- base::Optional<std::string> password;
+ absl::optional<std::string> password;
EXPECT_EQ(KWalletDBus::Error::CANNOT_READ,
kwallet_dbus_.ReadPassword(123, "folder", "key", "app", &password));
EXPECT_FALSE(password.has_value());
@@ -833,7 +833,7 @@ TEST_P(KWalletDBusTest, ReadPasswordErrorContact) {
CallMethodAndBlock(Calls(kKWalletInterface, "readPassword"), _))
.WillOnce(Return(ByMove(nullptr)));
- base::Optional<std::string> password;
+ absl::optional<std::string> password;
EXPECT_EQ(KWalletDBus::Error::CANNOT_CONTACT,
kwallet_dbus_.ReadPassword(123, "folder", "key", "app", &password));
EXPECT_FALSE(password.has_value());
diff --git a/chromium/components/os_crypt/os_crypt_linux.cc b/chromium/components/os_crypt/os_crypt_linux.cc
index 8a0af901cd6..4dd0a6aff87 100644
--- a/chromium/components/os_crypt/os_crypt_linux.cc
+++ b/chromium/components/os_crypt/os_crypt_linux.cc
@@ -8,6 +8,7 @@
#include <algorithm>
#include <iterator>
+#include <memory>
#include "base/lazy_instance.h"
#include "base/logging.h"
@@ -86,7 +87,7 @@ std::unique_ptr<KeyStorageLinux> (*g_key_storage_provider)() =
std::string* GetPasswordV10() {
base::AutoLock auto_lock(g_cache.Get().lock);
if (!g_cache.Get().password_v10_cache.get()) {
- g_cache.Get().password_v10_cache.reset(new std::string("peanuts"));
+ g_cache.Get().password_v10_cache = std::make_unique<std::string>("peanuts");
}
return g_cache.Get().password_v10_cache.get();
}
@@ -98,7 +99,7 @@ std::string* GetPasswordV11() {
if (!g_cache.Get().is_password_v11_cached) {
std::unique_ptr<KeyStorageLinux> key_storage = g_key_storage_provider();
if (key_storage) {
- base::Optional<std::string> key = key_storage->GetKey();
+ absl::optional<std::string> key = key_storage->GetKey();
if (key.has_value()) {
g_cache.Get().password_v11_cache =
std::make_unique<std::string>(std::move(*key));
diff --git a/chromium/components/os_crypt/os_crypt_mocker_linux.cc b/chromium/components/os_crypt/os_crypt_mocker_linux.cc
index 174e5444851..e40c99a7771 100644
--- a/chromium/components/os_crypt/os_crypt_mocker_linux.cc
+++ b/chromium/components/os_crypt/os_crypt_mocker_linux.cc
@@ -20,7 +20,7 @@ std::unique_ptr<KeyStorageLinux> CreateNewMock() {
}
-base::Optional<std::string> OSCryptMockerLinux::GetKeyImpl() {
+absl::optional<std::string> OSCryptMockerLinux::GetKeyImpl() {
return key_;
}
diff --git a/chromium/components/os_crypt/os_crypt_mocker_linux.h b/chromium/components/os_crypt/os_crypt_mocker_linux.h
index d14535c3763..cddad20a96b 100644
--- a/chromium/components/os_crypt/os_crypt_mocker_linux.h
+++ b/chromium/components/os_crypt/os_crypt_mocker_linux.h
@@ -8,9 +8,9 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "components/os_crypt/key_storage_linux.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
// Holds and serves a password from memory.
class OSCryptMockerLinux : public KeyStorageLinux {
@@ -30,7 +30,7 @@ class OSCryptMockerLinux : public KeyStorageLinux {
protected:
// KeyStorageLinux
bool Init() override;
- base::Optional<std::string> GetKeyImpl() override;
+ absl::optional<std::string> GetKeyImpl() override;
private:
std::string key_;
diff --git a/chromium/components/os_crypt/os_crypt_unittest.cc b/chromium/components/os_crypt/os_crypt_unittest.cc
index a7d2b35332c..dd03eed661f 100644
--- a/chromium/components/os_crypt/os_crypt_unittest.cc
+++ b/chromium/components/os_crypt/os_crypt_unittest.cc
@@ -26,7 +26,6 @@
#endif
#if defined(OS_WIN)
-#include "base/strings/string_util.h"
#include "components/prefs/testing_pref_service.h"
#include "crypto/random.h"
#endif
diff --git a/chromium/components/ownership/mock_owner_key_util.h b/chromium/components/ownership/mock_owner_key_util.h
index 86c37988735..1a8a9512720 100644
--- a/chromium/components/ownership/mock_owner_key_util.h
+++ b/chromium/components/ownership/mock_owner_key_util.h
@@ -11,7 +11,6 @@
#include <vector>
#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "components/ownership/owner_key_util.h"
#include "components/ownership/ownership_export.h"
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 d02e2ecb758..7b9c83444e2 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
@@ -6,10 +6,10 @@
#include "base/base64.h"
#include "base/bind.h"
-#include "base/optional.h"
#include "content/public/renderer/render_frame.h"
#include "crypto/sha2.h"
#include "services/image_annotation/public/mojom/image_annotation.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/web/web_document.h"
@@ -28,14 +28,14 @@ constexpr int kDomCrawlDelayMs = 3000;
// Attempts to produce image metadata for the given element. Will produce a null
// value if the element has a missing or malformed src attribute.
-base::Optional<PageAnnotator::ImageMetadata> ProduceMetadata(
+absl::optional<PageAnnotator::ImageMetadata> ProduceMetadata(
const GURL& page_url,
const blink::WebElement element,
const uint64_t node_id) {
const std::string source_id = ContentPageAnnotatorDriver::GenerateSourceId(
page_url, element.GetAttribute("src").Utf8());
if (source_id.empty())
- return base::nullopt;
+ return absl::nullopt;
return PageAnnotator::ImageMetadata{node_id, source_id};
}
@@ -157,7 +157,7 @@ void ContentPageAnnotatorDriver::FindImages(const GURL& page_url,
} else {
// This element is an image; attempt to produce metadata for it and begin
// tracking.
- const base::Optional<PageAnnotator::ImageMetadata> metadata =
+ const absl::optional<PageAnnotator::ImageMetadata> metadata =
ProduceMetadata(page_url, element, next_node_id_);
if (metadata.has_value())
diff --git a/chromium/components/page_info/BUILD.gn b/chromium/components/page_info/BUILD.gn
index c897a2e35d9..1de931eaf7a 100644
--- a/chromium/components/page_info/BUILD.gn
+++ b/chromium/components/page_info/BUILD.gn
@@ -49,6 +49,8 @@ static_library("page_info") {
"//components/password_manager/core/browser:password_manager_java_enums_srcjar",
"//components/resources:android_resources",
]
+ } else {
+ deps += [ "//ui/native_theme" ]
}
}
diff --git a/chromium/components/page_info/DEPS b/chromium/components/page_info/DEPS
index 63b498d56ca..2eeb337de8d 100644
--- a/chromium/components/page_info/DEPS
+++ b/chromium/components/page_info/DEPS
@@ -1,34 +1,30 @@
include_rules = [
- "+components/browser_ui/util/android/url_constants.h",
- "+components/browsing_data/content",
- "+components/content_settings/core",
- "+components/content_settings/browser",
- "+components/password_manager/core/browser/password_manager_metrics_util.h",
+ "+components/browser_ui",
+ "+components/browsing_data",
+ "+components/content_settings",
+ "+components/password_manager",
"+components/permissions",
- "+components/prefs/pref_service.h",
- "+components/resources/android",
+ "+components/prefs",
+ "+components/resources",
"+components/safe_browsing",
- "+components/security_interstitials/content/stateful_ssl_host_state_delegate.h",
- "+components/security_interstitials/core/common_string_util.h",
- "+components/security_state/core",
- "+components/signin/public/identity_manager/account_info.h",
- "+components/ssl_errors/error_info.h",
- "+components/strings/grit",
- "+components/subresource_filter/core/browser/subresource_filter_features.h",
- "+components/ukm/content/source_url_recorder.h",
- "+components/url_formatter/elide_url.h",
- "+components/vector_icons/vector_icons.h",
- "+content/public/browser",
- "+content/public/common",
- "+media/base/media_switches.h",
- "+net/cert/cert_status_flags.h",
- "+net/cert/x509_certificate.h",
- "+net/ssl/ssl_cipher_suite_names.h",
- "+net/ssl/ssl_connection_status_flags.h",
- "+ppapi/buildflags/buildflags.h",
- "+services/device/public/cpp/device_features.h",
- "+services/metrics/public/cpp",
- "+third_party/boringssl/src/include/openssl/ssl.h",
- "+ui/base/l10n/l10n_util.h",
+ "+components/security_interstitials",
+ "+components/security_state",
+ "+components/signin",
+ "+components/ssl_errors",
+ "+components/strings",
+ "+components/subresource_filter",
+ "+components/ukm",
+ "+components/url_formatter",
+ "+components/vector_icons",
+ "+content/public",
+ "+media/base",
+ "+net/cert",
+ "+net/ssl",
+ "+ppapi",
+ "+services/device/public",
+ "+services/metrics/public",
+ "+third_party/boringssl/src/include",
+ "+ui/base",
"+ui/gfx",
+ "+ui/native_theme",
]
diff --git a/chromium/components/page_info/android/BUILD.gn b/chromium/components/page_info/android/BUILD.gn
index 03d6ca62be8..a18094af4e1 100644
--- a/chromium/components/page_info/android/BUILD.gn
+++ b/chromium/components/page_info/android/BUILD.gn
@@ -14,7 +14,7 @@ static_library("android") {
"page_info_client.h",
"page_info_controller_android.cc",
"page_info_controller_android.h",
- "page_info_feature_list.cc",
+ "page_info_features.cc",
]
deps = [
"//base",
@@ -32,36 +32,16 @@ static_library("android") {
android_resources("java_resources") {
sources = [
- "java/res/drawable-hdpi/pageinfo_bad.png",
- "java/res/drawable-hdpi/pageinfo_good.png",
- "java/res/drawable-hdpi/pageinfo_warning.png",
- "java/res/drawable-mdpi/pageinfo_bad.png",
- "java/res/drawable-mdpi/pageinfo_good.png",
- "java/res/drawable-mdpi/pageinfo_warning.png",
- "java/res/drawable-xhdpi/pageinfo_bad.png",
- "java/res/drawable-xhdpi/pageinfo_good.png",
- "java/res/drawable-xhdpi/pageinfo_warning.png",
- "java/res/drawable-xxhdpi/pageinfo_bad.png",
- "java/res/drawable-xxhdpi/pageinfo_good.png",
- "java/res/drawable-xxhdpi/pageinfo_warning.png",
- "java/res/drawable-xxxhdpi/pageinfo_bad.png",
- "java/res/drawable-xxxhdpi/pageinfo_good.png",
- "java/res/drawable-xxxhdpi/pageinfo_warning.png",
"java/res/drawable/ic_tune_24dp.xml",
"java/res/drawable/page_info_bg.xml",
"java/res/layout/connection_info.xml",
- "java/res/layout/connection_info_v2.xml",
- "java/res/layout/cookie_controls_view.xml",
"java/res/layout/page_info.xml",
"java/res/layout/page_info_container.xml",
- "java/res/layout/page_info_permission_row.xml",
"java/res/layout/page_info_row.xml",
"java/res/layout/page_info_summary.xml",
- "java/res/layout/page_info_v2.xml",
"java/res/values/colors.xml",
"java/res/values/dimens.xml",
"java/res/values/ids.xml",
- "java/res/values/styles.xml",
"java/res/xml/page_info_cookie_preference.xml",
]
deps = [
@@ -77,7 +57,7 @@ android_library("java") {
"java/src/org/chromium/components/page_info/CertificateChainHelper.java",
"java/src/org/chromium/components/page_info/CertificateViewer.java",
"java/src/org/chromium/components/page_info/ConnectionInfoView.java",
- "java/src/org/chromium/components/page_info/CookieControlsView.java",
+ "java/src/org/chromium/components/page_info/ElidedUrlTextView.java",
"java/src/org/chromium/components/page_info/PageInfoConnectionController.java",
"java/src/org/chromium/components/page_info/PageInfoContainer.java",
"java/src/org/chromium/components/page_info/PageInfoController.java",
@@ -86,15 +66,13 @@ android_library("java") {
"java/src/org/chromium/components/page_info/PageInfoCookiesPreference.java",
"java/src/org/chromium/components/page_info/PageInfoDialog.java",
"java/src/org/chromium/components/page_info/PageInfoDiscoverabilityMetrics.java",
- "java/src/org/chromium/components/page_info/PageInfoFeatureList.java",
+ "java/src/org/chromium/components/page_info/PageInfoFeatures.java",
"java/src/org/chromium/components/page_info/PageInfoMainController.java",
"java/src/org/chromium/components/page_info/PageInfoPermissionsController.java",
"java/src/org/chromium/components/page_info/PageInfoRowView.java",
"java/src/org/chromium/components/page_info/PageInfoSubpageController.java",
"java/src/org/chromium/components/page_info/PageInfoView.java",
- "java/src/org/chromium/components/page_info/PageInfoViewV2.java",
"java/src/org/chromium/components/page_info/PermissionParamsListBuilder.java",
- "java/src/org/chromium/components/page_info/PermissionParamsListBuilderDelegate.java",
"java/src/org/chromium/components/page_info/SystemSettingsActivityRequiredListener.java",
"java/src/org/chromium/components/page_info/VrHandler.java",
]
@@ -138,7 +116,7 @@ generate_jni("jni_headers") {
"java/src/org/chromium/components/page_info/CertificateViewer.java",
"java/src/org/chromium/components/page_info/ConnectionInfoView.java",
"java/src/org/chromium/components/page_info/PageInfoController.java",
- "java/src/org/chromium/components/page_info/PageInfoFeatureList.java",
+ "java/src/org/chromium/components/page_info/PageInfoFeatures.java",
]
}
diff --git a/chromium/components/page_info/android/DIR_METADATA b/chromium/components/page_info/android/DIR_METADATA
deleted file mode 100644
index 0c8becc54da..00000000000
--- a/chromium/components/page_info/android/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "UI>Browser>Bubbles>PageInfo"
-}
diff --git a/chromium/components/page_info/android/connection_info_view_android.cc b/chromium/components/page_info/android/connection_info_view_android.cc
index c3aeecbd8bb..62935d2444e 100644
--- a/chromium/components/page_info/android/connection_info_view_android.cc
+++ b/chromium/components/page_info/android/connection_info_view_android.cc
@@ -142,19 +142,3 @@ void ConnectionInfoViewAndroid::SetIdentityInfo(
env, l10n_util::GetStringUTF8(IDS_PAGE_INFO_HELP_CENTER_LINK)));
Java_ConnectionInfoView_onReady(env, popup_jobject_);
}
-
-void ConnectionInfoViewAndroid::SetCookieInfo(
- const CookieInfoList& cookie_info_list) {
- NOTIMPLEMENTED();
-}
-
-void ConnectionInfoViewAndroid::SetPageFeatureInfo(
- const PageFeatureInfo& info) {
- NOTIMPLEMENTED();
-}
-
-void ConnectionInfoViewAndroid::SetPermissionInfo(
- const PermissionInfoList& permission_info_list,
- ChosenObjectInfoList chosen_object_info_list) {
- NOTIMPLEMENTED();
-}
diff --git a/chromium/components/page_info/android/connection_info_view_android.h b/chromium/components/page_info/android/connection_info_view_android.h
index 1202d45a1b0..51100c9772e 100644
--- a/chromium/components/page_info/android/connection_info_view_android.h
+++ b/chromium/components/page_info/android/connection_info_view_android.h
@@ -39,11 +39,7 @@ class ConnectionInfoViewAndroid : public PageInfoUI {
const base::android::JavaParamRef<jobject>& java_web_contents);
// PageInfoUI implementations.
- void SetCookieInfo(const CookieInfoList& cookie_info_list) override;
- void SetPermissionInfo(const PermissionInfoList& permission_info_list,
- ChosenObjectInfoList chosen_object_info_list) override;
void SetIdentityInfo(const IdentityInfo& identity_info) override;
- void SetPageFeatureInfo(const PageFeatureInfo& info) override;
private:
// The presenter that controls the Page Info UI.
@@ -58,4 +54,4 @@ class ConnectionInfoViewAndroid : public PageInfoUI {
DISALLOW_COPY_AND_ASSIGN(ConnectionInfoViewAndroid);
};
-#endif // COMPONENTS_PAGE_INFO_ANDROID_CONNECTION_INFO_VIEW_ANDROID_H_s
+#endif // COMPONENTS_PAGE_INFO_ANDROID_CONNECTION_INFO_VIEW_ANDROID_H_
diff --git a/chromium/components/page_info/android/page_info_controller_android.cc b/chromium/components/page_info/android/page_info_controller_android.cc
index 82b2f295f49..404e75c8a09 100644
--- a/chromium/components/page_info/android/page_info_controller_android.cc
+++ b/chromium/components/page_info/android/page_info_controller_android.cc
@@ -148,7 +148,7 @@ void PageInfoControllerAndroid::SetPermissionInfo(
for (const auto& permission : permission_info_list) {
if (base::Contains(permissions_to_display, permission.type)) {
- base::Optional<ContentSetting> setting_to_display =
+ absl::optional<ContentSetting> setting_to_display =
GetSettingToDisplay(permission);
if (setting_to_display) {
user_specified_settings_to_display[permission.type] =
@@ -184,7 +184,7 @@ void PageInfoControllerAndroid::SetPermissionInfo(
Java_PageInfoController_updatePermissionDisplay(env, controller_jobject_);
}
-base::Optional<ContentSetting> PageInfoControllerAndroid::GetSettingToDisplay(
+absl::optional<ContentSetting> PageInfoControllerAndroid::GetSettingToDisplay(
const PageInfo::PermissionInfo& permission) {
// All permissions should be displayed if they are non-default.
if (permission.setting != CONTENT_SETTING_DEFAULT &&
@@ -200,8 +200,7 @@ base::Optional<ContentSetting> PageInfoControllerAndroid::GetSettingToDisplay(
// setting should show up in Page Info is in ShouldShowPermission in
// page_info.cc.
return permission.default_setting;
- } else if (permission.type == ContentSettingsType::JAVASCRIPT &&
- base::FeatureList::IsEnabled(page_info::kPageInfoV2)) {
+ } else if (permission.type == ContentSettingsType::JAVASCRIPT) {
// The javascript content setting should show up if it is blocked globally
// to give users an easy way to create exceptions.
return permission.default_setting;
@@ -216,5 +215,5 @@ base::Optional<ContentSetting> PageInfoControllerAndroid::GetSettingToDisplay(
// factory-default after we add the functionality to populate the permissions
// subpage directly from the permissions returned from this controller.
- return base::Optional<ContentSetting>();
+ return absl::optional<ContentSetting>();
}
diff --git a/chromium/components/page_info/android/page_info_controller_android.h b/chromium/components/page_info/android/page_info_controller_android.h
index 6e1a11d4f1f..f6dcb14ffa2 100644
--- a/chromium/components/page_info/android/page_info_controller_android.h
+++ b/chromium/components/page_info/android/page_info_controller_android.h
@@ -11,8 +11,8 @@
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/page_info/page_info_ui.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class WebContents;
@@ -44,7 +44,7 @@ class PageInfoControllerAndroid : public PageInfoUI {
// displayed in Page Info. Most permissions will only be displayed if they are
// set to some non-default value, but there are some permissions which require
// customized behavior.
- base::Optional<ContentSetting> GetSettingToDisplay(
+ absl::optional<ContentSetting> GetSettingToDisplay(
const PageInfo::PermissionInfo& permission);
// The presenter that controlls the Page Info UI.
diff --git a/chromium/components/page_info/android/page_info_features.cc b/chromium/components/page_info/android/page_info_features.cc
new file mode 100644
index 00000000000..96bd37f4766
--- /dev/null
+++ b/chromium/components/page_info/android/page_info_features.cc
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_string.h"
+#include "components/page_info/android/jni_headers/PageInfoFeatures_jni.h"
+#include "components/page_info/features.h"
+
+namespace page_info {
+
+namespace {
+
+// Array of features exposed through the Java Features brdige class. Entries in
+// this array may either refer to features defined in the header of this file or
+// in other locations in the code base (e.g. content_features.h), and must be
+// replicated in the same order in PageInfoFeatures.java.
+const base::Feature* kFeaturesExposedToJava[] = {
+ &kPageInfoDiscoverability,
+ &kPageInfoHistory,
+};
+
+} // namespace
+
+static jlong JNI_PageInfoFeatures_GetFeature(JNIEnv* env, jint ordinal) {
+ return reinterpret_cast<jlong>(kFeaturesExposedToJava[ordinal]);
+}
+
+} // namespace page_info
diff --git a/chromium/components/page_info/features.cc b/chromium/components/page_info/features.cc
index 9d9f81da866..e86dbf96f9d 100644
--- a/chromium/components/page_info/features.cc
+++ b/chromium/components/page_info/features.cc
@@ -14,7 +14,6 @@ const base::Feature kPageInfoDiscoverability{"PageInfoDiscoverability",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kPageInfoHistory{"PageInfoHistory",
base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kPageInfoV2{"PageInfoV2", base::FEATURE_ENABLED_BY_DEFAULT};
#endif
#if !defined(OS_ANDROID)
diff --git a/chromium/components/page_info/features.h b/chromium/components/page_info/features.h
index 1e053b61748..1f70655ef15 100644
--- a/chromium/components/page_info/features.h
+++ b/chromium/components/page_info/features.h
@@ -18,8 +18,6 @@ namespace page_info {
extern const base::Feature kPageInfoDiscoverability;
// Enables the history sub page for Page Info.
extern const base::Feature kPageInfoHistory;
-// Enables the second version of the Page Info View.
-extern const base::Feature kPageInfoV2;
#endif
#if !defined(OS_ANDROID)
@@ -29,4 +27,4 @@ extern const base::Feature kPageInfoV2Desktop;
} // namespace page_info
-#endif // COMPONENTS_PAGE_INFO_ANDROID_FEATURES_H_
+#endif // COMPONENTS_PAGE_INFO_FEATURES_H_
diff --git a/chromium/components/page_info/page_info.cc b/chromium/components/page_info/page_info.cc
index 1323a87b0df..4d970f45ddc 100644
--- a/chromium/components/page_info/page_info.cc
+++ b/chromium/components/page_info/page_info.cc
@@ -34,7 +34,7 @@
#include "components/page_info/page_info_delegate.h"
#include "components/page_info/page_info_ui.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
-#include "components/permissions/chooser_context_base.h"
+#include "components/permissions/object_permission_context_base.h"
#include "components/permissions/permission_decision_auto_blocker.h"
#include "components/permissions/permission_manager.h"
#include "components/permissions/permission_result.h"
@@ -100,7 +100,7 @@ ContentSettingsType kPermissionType[] = {
ContentSettingsType::BACKGROUND_SYNC,
ContentSettingsType::SOUND,
ContentSettingsType::AUTOMATIC_DOWNLOADS,
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
#endif
ContentSettingsType::MIDI_SYSEX,
@@ -258,11 +258,6 @@ void ReportAnyInsecureContent(
}
}
-std::u16string GetSimpleSiteName(const GURL& url) {
- return url_formatter::FormatUrlForSecurityDisplay(
- url, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
-}
-
// The list of chooser types that need to display entries in the Website
// Settings UI. THE ORDER OF THESE ITEMS IS IMPORTANT. To propose changing it,
// email security-dev@chromium.org.
@@ -278,7 +273,7 @@ const PageInfo::ChooserUIInfo kChooserUIInfo[] = {
IDS_PAGE_INFO_DELETE_HID_DEVICE},
{ContentSettingsType::SERIAL_CHOOSER_DATA,
IDS_PAGE_INFO_SERIAL_PORT_SECONDARY_LABEL,
- /*allowed_by_policy_description_string_id=*/-1,
+ IDS_PAGE_INFO_SERIAL_PORT_ALLOWED_BY_POLICY_LABEL,
IDS_PAGE_INFO_DELETE_SERIAL_PORT},
#endif
{ContentSettingsType::BLUETOOTH_CHOOSER_DATA,
@@ -549,8 +544,7 @@ void PageInfo::OnSitePermissionChanged(ContentSettingsType type,
void PageInfo::OnSiteChosenObjectDeleted(const ChooserUIInfo& ui_info,
const base::Value& object) {
- // TODO(reillyg): Create metrics for revocations. crbug.com/556845
- permissions::ChooserContextBase* context =
+ permissions::ObjectPermissionContextBase* context =
delegate_->GetChooserContext(ui_info.content_settings_type);
const auto origin = url::Origin::Create(site_url_);
context->RevokeObjectPermission(origin, object);
@@ -649,11 +643,16 @@ void PageInfo::OnAllowlistPasswordReuseButtonPressed() {
#endif
}
-permissions::ChooserContextBase* PageInfo::GetChooserContextFromUIInfo(
+permissions::ObjectPermissionContextBase* PageInfo::GetChooserContextFromUIInfo(
const ChooserUIInfo& ui_info) const {
return delegate_->GetChooserContext(ui_info.content_settings_type);
}
+std::u16string PageInfo::GetSimpleSiteName() const {
+ return url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
+ site_url_);
+}
+
void PageInfo::ComputeUIInputs(const GURL& url) {
auto security_level = delegate_->GetSecurityLevel();
auto visible_security_state = delegate_->GetVisibleSecurityState();
@@ -742,7 +741,7 @@ void PageInfo::ComputeUIInputs(const GURL& url) {
#if defined(OS_ANDROID)
identity_status_description_android_ +=
- UTF8ToUTF16("\n\n") +
+ u"\n\n" +
l10n_util::GetStringUTF16(
IDS_PAGE_INFO_SECURITY_TAB_DEPRECATED_SIGNATURE_ALGORITHM);
#endif
@@ -757,7 +756,7 @@ void PageInfo::ComputeUIInputs(const GURL& url) {
site_identity_status_ = SITE_IDENTITY_STATUS_ERROR;
}
#if defined(OS_ANDROID)
- const std::u16string bullet = UTF8ToUTF16("\n • ");
+ const std::u16string bullet = u"\n • ";
std::vector<ssl_errors::ErrorInfo> errors;
ssl_errors::ErrorInfo::GetErrorsForCertStatus(
certificate_, visible_security_state.cert_status, url, &errors);
@@ -830,7 +829,7 @@ void PageInfo::ComputeUIInputs(const GURL& url) {
// weakly encrypted connections.
site_connection_status_ = SITE_CONNECTION_STATUS_UNKNOWN;
- std::u16string subject_name(GetSimpleSiteName(url));
+ std::u16string subject_name(GetSimpleSiteName());
if (subject_name.empty()) {
subject_name.assign(
l10n_util::GetStringUTF16(IDS_PAGE_INFO_SECURITY_TAB_UNKNOWN_PARTY));
@@ -990,13 +989,13 @@ void PageInfo::PresentSitePermissions() {
const auto origin = url::Origin::Create(site_url_);
for (const ChooserUIInfo& ui_info : kChooserUIInfo) {
- permissions::ChooserContextBase* context =
+ permissions::ObjectPermissionContextBase* context =
delegate_->GetChooserContext(ui_info.content_settings_type);
if (!context)
continue;
auto chosen_objects = context->GetGrantedObjects(origin);
- for (std::unique_ptr<permissions::ChooserContextBase::Object>& object :
- chosen_objects) {
+ for (std::unique_ptr<permissions::ObjectPermissionContextBase::Object>&
+ object : chosen_objects) {
chosen_object_info_list.push_back(
std::make_unique<PageInfoUI::ChosenObjectInfo>(ui_info,
std::move(object)));
@@ -1034,7 +1033,7 @@ void PageInfo::PresentSiteIdentity() {
DCHECK_NE(site_identity_status_, SITE_IDENTITY_STATUS_UNKNOWN);
DCHECK_NE(site_connection_status_, SITE_CONNECTION_STATUS_UNKNOWN);
PageInfoUI::IdentityInfo info;
- info.site_identity = UTF16ToUTF8(GetSimpleSiteName(site_url_));
+ info.site_identity = UTF16ToUTF8(GetSimpleSiteName());
info.connection_status = site_connection_status_;
info.connection_status_description = UTF16ToUTF8(site_connection_details_);
diff --git a/chromium/components/page_info/page_info.h b/chromium/components/page_info/page_info.h
index 908efa6b567..dd35e5a402e 100644
--- a/chromium/components/page_info/page_info.h
+++ b/chromium/components/page_info/page_info.h
@@ -33,7 +33,7 @@ class X509Certificate;
}
namespace permissions {
-class ChooserContextBase;
+class ObjectPermissionContextBase;
}
namespace ui {
@@ -43,7 +43,6 @@ class Event;
class HostContentSettingsMap;
class PageInfoDelegate;
class PageInfoUI;
-class PageInfoBubbleViewBrowserTest;
using password_manager::metrics_util::PasswordType;
@@ -251,10 +250,10 @@ class PageInfo : public content::WebContentsObserver {
// This method is called when the user pressed "Mark as legitimate" button.
void OnAllowlistPasswordReuseButtonPressed();
- // Return a pointer to the ChooserContextBase corresponding to the
+ // Return a pointer to the ObjectPermissionContextBase corresponding to the
// content settings type, |type|. Returns nullptr for content settings
- // for which there's no ChooserContextBase.
- permissions::ChooserContextBase* GetChooserContextFromUIInfo(
+ // for which there's no ObjectPermissionContextBase.
+ permissions::ObjectPermissionContextBase* GetChooserContextFromUIInfo(
const ChooserUIInfo& ui_info) const;
// Accessors.
@@ -272,12 +271,20 @@ class PageInfo : public content::WebContentsObserver {
return safe_browsing_status_;
}
+ // Returns site origin in a concise and human-friendly way, without the
+ // HTTP/HTTPS scheme, the username and password, the path and trivial
+ // subdomains.
+ std::u16string GetSimpleSiteName() const;
+
+ // Retrieves all the permissions that are shown in Page Info.
+ // Exposed for testing.
+ static std::vector<ContentSettingsType> GetAllPermissionsForTesting();
+
private:
FRIEND_TEST_ALL_PREFIXES(PageInfoTest,
NonFactoryDefaultAndRecentlyChangedPermissionsShown);
FRIEND_TEST_ALL_PREFIXES(PageInfoTest, IncognitoPermissionsEmptyByDefault);
FRIEND_TEST_ALL_PREFIXES(PageInfoTest, IncognitoPermissionsDontShowAsk);
- friend class PageInfoBubbleViewBrowserTest;
// Populates this object's UI state with provided security context. This
// function does not update visible UI-- that's part of Present*().
@@ -315,10 +322,6 @@ class PageInfo : public content::WebContentsObserver {
PageInfo::SafeBrowsingStatus* status,
std::u16string* details);
- // Retrieves all the permissions that are shown in Page Info.
- // Exposed for testing.
- static std::vector<ContentSettingsType> GetAllPermissionsForTesting();
-
// Returns PageSpecificContentSettings for the observed WebContents if
// present, nullptr otherwise.
content_settings::PageSpecificContentSettings*
diff --git a/chromium/components/page_info/page_info_delegate.h b/chromium/components/page_info/page_info_delegate.h
index 30cfa6c3b1d..599d25310ac 100644
--- a/chromium/components/page_info/page_info_delegate.h
+++ b/chromium/components/page_info/page_info_delegate.h
@@ -17,7 +17,7 @@
#include "components/security_state/core/security_state.h"
namespace permissions {
-class ChooserContextBase;
+class ObjectPermissionContextBase;
class PermissionDecisionAutoBlocker;
} // namespace permissions
@@ -37,10 +37,10 @@ class PageInfoDelegate {
public:
virtual ~PageInfoDelegate() = default;
- // Return the |ChooserContextBase| corresponding to the content settings
- // type, |type|. Returns a nullptr for content settings for which there's no
- // ChooserContextBase.
- virtual permissions::ChooserContextBase* GetChooserContext(
+ // Return the |ObjectPermissionContextBase| corresponding to the content
+ // settings type, |type|. Returns a nullptr for content settings for which
+ // there's no ObjectPermissionContextBase.
+ virtual permissions::ObjectPermissionContextBase* GetChooserContext(
ContentSettingsType type) = 0;
#if BUILDFLAG(FULL_SAFE_BROWSING)
@@ -57,8 +57,9 @@ class PageInfoDelegate {
ContentSettingsType type,
const GURL& site_url) = 0;
#if !defined(OS_ANDROID)
- // Creates an InfoBarService and an InfoBarDelegate using it, if possible.
- // Returns true if an InfoBarDelegate was created, false otherwise.
+ // Creates an infobars::ContentInfoBarManager and an InfoBarDelegate using it,
+ // if possible. Returns true if an InfoBarDelegate was created, false
+ // otherwise.
virtual bool CreateInfoBarDelegate() = 0;
virtual void ShowSiteSettings(const GURL& site_url) = 0;
diff --git a/chromium/components/page_info/page_info_ui.cc b/chromium/components/page_info/page_info_ui.cc
index 79430dce8b2..f28a5deedae 100644
--- a/chromium/components/page_info/page_info_ui.cc
+++ b/chromium/components/page_info/page_info_ui.cc
@@ -34,6 +34,7 @@
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/paint_vector_icon.h"
+#include "ui/native_theme/native_theme.h" // nogncheck
#endif
#if BUILDFLAG(FULL_SAFE_BROWSING)
@@ -155,7 +156,7 @@ base::span<const PermissionsUIInfo> GetContentSettingsUIInfo() {
IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL},
{ContentSettingsType::MIDI_SYSEX, IDS_PAGE_INFO_TYPE_MIDI_SYSEX},
{ContentSettingsType::BACKGROUND_SYNC, IDS_PAGE_INFO_TYPE_BACKGROUND_SYNC},
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
{ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
IDS_PAGE_INFO_TYPE_PROTECTED_MEDIA_IDENTIFIER},
#endif
@@ -257,7 +258,8 @@ PageInfoUI::CookieInfo::CookieInfo() : allowed(-1), blocked(-1) {}
PageInfoUI::ChosenObjectInfo::ChosenObjectInfo(
const PageInfo::ChooserUIInfo& ui_info,
- std::unique_ptr<permissions::ChooserContextBase::Object> chooser_object)
+ std::unique_ptr<permissions::ObjectPermissionContextBase::Object>
+ chooser_object)
: ui_info(ui_info), chooser_object(std::move(chooser_object)) {}
PageInfoUI::ChosenObjectInfo::~ChosenObjectInfo() = default;
@@ -277,10 +279,6 @@ PageInfoUI::PageFeatureInfo::PageFeatureInfo()
std::unique_ptr<PageInfoUI::SecurityDescription>
PageInfoUI::GetSecurityDescription(const IdentityInfo& identity_info) const {
- bool page_info_v2_enabled = false;
-#if defined(OS_ANDROID)
- page_info_v2_enabled = base::FeatureList::IsEnabled(page_info::kPageInfoV2);
-#endif
switch (identity_info.safe_browsing_status) {
case PageInfo::SAFE_BROWSING_STATUS_NONE:
break;
@@ -327,73 +325,97 @@ PageInfoUI::GetSecurityDescription(const IdentityInfo& identity_info) const {
}
switch (identity_info.identity_status) {
- case PageInfo::SITE_IDENTITY_STATUS_INTERNAL_PAGE:
#if defined(OS_ANDROID)
+ case PageInfo::SITE_IDENTITY_STATUS_INTERNAL_PAGE:
return CreateSecurityDescription(SecuritySummaryColor::GREEN, 0,
IDS_PAGE_INFO_INTERNAL_PAGE,
SecurityDescriptionType::INTERNAL);
-#else
- // Internal pages on desktop have their own UI implementations which
- // should never call this function.
- NOTREACHED();
- FALLTHROUGH;
-#endif
case PageInfo::SITE_IDENTITY_STATUS_EV_CERT:
- FALLTHROUGH;
case PageInfo::SITE_IDENTITY_STATUS_CERT:
- FALLTHROUGH;
case PageInfo::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT:
switch (identity_info.connection_status) {
case PageInfo::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE:
return CreateSecurityDescription(
- SecuritySummaryColor::RED,
- page_info_v2_enabled ? IDS_PAGE_INFO_NOT_SECURE_SUMMARY_SHORT
- : IDS_PAGE_INFO_NOT_SECURE_SUMMARY,
+ SecuritySummaryColor::RED, IDS_PAGE_INFO_NOT_SECURE_SUMMARY_SHORT,
IDS_PAGE_INFO_NOT_SECURE_DETAILS,
SecurityDescriptionType::CONNECTION);
case PageInfo::SITE_CONNECTION_STATUS_INSECURE_FORM_ACTION:
return CreateSecurityDescription(
SecuritySummaryColor::RED,
- page_info_v2_enabled ? IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY_SHORT
- : IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY,
+ IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY_SHORT,
IDS_PAGE_INFO_NOT_SECURE_DETAILS,
SecurityDescriptionType::CONNECTION);
case PageInfo::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE:
return CreateSecurityDescription(
SecuritySummaryColor::RED,
- page_info_v2_enabled ? IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY_SHORT
- : IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY,
+ IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY_SHORT,
IDS_PAGE_INFO_MIXED_CONTENT_DETAILS,
SecurityDescriptionType::CONNECTION);
case PageInfo::SITE_CONNECTION_STATUS_LEGACY_TLS:
return CreateSecurityDescription(
SecuritySummaryColor::RED,
- page_info_v2_enabled ? IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY_SHORT
- : IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY,
+ IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY_SHORT,
IDS_PAGE_INFO_LEGACY_TLS_DETAILS,
SecurityDescriptionType::CONNECTION);
default:
- int secure_details = IDS_PAGE_INFO_SECURE_DETAILS;
-#if defined(OS_ANDROID)
- if (page_info_v2_enabled) {
- // Do not show details for secure connections.
- secure_details = 0;
- }
-#endif
- return CreateSecurityDescription(
- SecuritySummaryColor::GREEN, IDS_PAGE_INFO_SECURE_SUMMARY,
- secure_details, SecurityDescriptionType::CONNECTION);
+ // Do not show details for secure connections.
+ return CreateSecurityDescription(SecuritySummaryColor::GREEN,
+ IDS_PAGE_INFO_SECURE_SUMMARY, 0,
+ SecurityDescriptionType::CONNECTION);
}
case PageInfo::SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM:
case PageInfo::SITE_IDENTITY_STATUS_UNKNOWN:
case PageInfo::SITE_IDENTITY_STATUS_NO_CERT:
default:
- return CreateSecurityDescription(
- SecuritySummaryColor::RED,
- page_info_v2_enabled ? IDS_PAGE_INFO_NOT_SECURE_SUMMARY_SHORT
- : IDS_PAGE_INFO_NOT_SECURE_SUMMARY,
- IDS_PAGE_INFO_NOT_SECURE_DETAILS,
- SecurityDescriptionType::CONNECTION);
+ return CreateSecurityDescription(SecuritySummaryColor::RED,
+ IDS_PAGE_INFO_NOT_SECURE_SUMMARY_SHORT,
+ IDS_PAGE_INFO_NOT_SECURE_DETAILS,
+ SecurityDescriptionType::CONNECTION);
+#else
+ case PageInfo::SITE_IDENTITY_STATUS_INTERNAL_PAGE:
+ // Internal pages on desktop have their own UI implementations which
+ // should never call this function.
+ NOTREACHED();
+ FALLTHROUGH;
+ case PageInfo::SITE_IDENTITY_STATUS_EV_CERT:
+ case PageInfo::SITE_IDENTITY_STATUS_CERT:
+ case PageInfo::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT:
+ switch (identity_info.connection_status) {
+ case PageInfo::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE:
+ return CreateSecurityDescription(SecuritySummaryColor::RED,
+ IDS_PAGE_INFO_NOT_SECURE_SUMMARY,
+ IDS_PAGE_INFO_NOT_SECURE_DETAILS,
+ SecurityDescriptionType::CONNECTION);
+ case PageInfo::SITE_CONNECTION_STATUS_INSECURE_FORM_ACTION:
+ return CreateSecurityDescription(SecuritySummaryColor::RED,
+ IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY,
+ IDS_PAGE_INFO_NOT_SECURE_DETAILS,
+ SecurityDescriptionType::CONNECTION);
+ case PageInfo::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE:
+ return CreateSecurityDescription(SecuritySummaryColor::RED,
+ IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY,
+ IDS_PAGE_INFO_MIXED_CONTENT_DETAILS,
+ SecurityDescriptionType::CONNECTION);
+ case PageInfo::SITE_CONNECTION_STATUS_LEGACY_TLS:
+ return CreateSecurityDescription(SecuritySummaryColor::RED,
+ IDS_PAGE_INFO_MIXED_CONTENT_SUMMARY,
+ IDS_PAGE_INFO_LEGACY_TLS_DETAILS,
+ SecurityDescriptionType::CONNECTION);
+ default:
+ return CreateSecurityDescription(SecuritySummaryColor::GREEN,
+ IDS_PAGE_INFO_SECURE_SUMMARY,
+ IDS_PAGE_INFO_SECURE_DETAILS,
+ SecurityDescriptionType::CONNECTION);
+ }
+ case PageInfo::SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM:
+ case PageInfo::SITE_IDENTITY_STATUS_UNKNOWN:
+ case PageInfo::SITE_IDENTITY_STATUS_NO_CERT:
+ default:
+ return CreateSecurityDescription(SecuritySummaryColor::RED,
+ IDS_PAGE_INFO_NOT_SECURE_SUMMARY,
+ IDS_PAGE_INFO_NOT_SECURE_DETAILS,
+ SecurityDescriptionType::CONNECTION);
+#endif
}
}
@@ -523,95 +545,39 @@ SkColor PageInfoUI::GetSecondaryTextColor() {
#if defined(OS_ANDROID)
// static
int PageInfoUI::GetIdentityIconID(PageInfo::SiteIdentityStatus status) {
- if (base::FeatureList::IsEnabled(page_info::kPageInfoV2)) {
- switch (status) {
- case PageInfo::SITE_IDENTITY_STATUS_UNKNOWN:
- case PageInfo::SITE_IDENTITY_STATUS_INTERNAL_PAGE:
- case PageInfo::SITE_IDENTITY_STATUS_CERT:
- case PageInfo::SITE_IDENTITY_STATUS_EV_CERT:
- return IDR_PAGEINFO_GOOD_V2;
- case PageInfo::SITE_IDENTITY_STATUS_NO_CERT:
- case PageInfo::SITE_IDENTITY_STATUS_ERROR:
- case PageInfo::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT:
- case PageInfo::SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM:
- return IDR_PAGEINFO_BAD_V2;
- }
-
- return 0;
- }
-
- int resource_id = IDR_PAGEINFO_INFO;
switch (status) {
case PageInfo::SITE_IDENTITY_STATUS_UNKNOWN:
case PageInfo::SITE_IDENTITY_STATUS_INTERNAL_PAGE:
- break;
case PageInfo::SITE_IDENTITY_STATUS_CERT:
case PageInfo::SITE_IDENTITY_STATUS_EV_CERT:
- resource_id = IDR_PAGEINFO_GOOD;
- break;
+ return IDR_PAGEINFO_GOOD;
case PageInfo::SITE_IDENTITY_STATUS_NO_CERT:
- resource_id = IDR_PAGEINFO_WARNING_MAJOR;
- break;
case PageInfo::SITE_IDENTITY_STATUS_ERROR:
- resource_id = IDR_PAGEINFO_BAD;
- break;
case PageInfo::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT:
- resource_id = IDR_PAGEINFO_ENTERPRISE_MANAGED;
- break;
case PageInfo::SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM:
- resource_id = IDR_PAGEINFO_WARNING_MINOR;
- break;
- default:
- NOTREACHED();
- break;
+ return IDR_PAGEINFO_BAD;
}
- return resource_id;
+ return 0;
}
// static
int PageInfoUI::GetConnectionIconID(PageInfo::SiteConnectionStatus status) {
- if (base::FeatureList::IsEnabled(page_info::kPageInfoV2)) {
- switch (status) {
- case PageInfo::SITE_CONNECTION_STATUS_UNKNOWN:
- case PageInfo::SITE_CONNECTION_STATUS_INTERNAL_PAGE:
- case PageInfo::SITE_CONNECTION_STATUS_ENCRYPTED:
- return IDR_PAGEINFO_GOOD_V2;
- case PageInfo::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE:
- case PageInfo::SITE_CONNECTION_STATUS_INSECURE_FORM_ACTION:
- case PageInfo::SITE_CONNECTION_STATUS_LEGACY_TLS:
- case PageInfo::SITE_CONNECTION_STATUS_UNENCRYPTED:
- case PageInfo::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE:
- case PageInfo::SITE_CONNECTION_STATUS_ENCRYPTED_ERROR:
- return IDR_PAGEINFO_BAD_V2;
- }
-
- return 0;
- }
- int resource_id = IDR_PAGEINFO_INFO;
-
switch (status) {
case PageInfo::SITE_CONNECTION_STATUS_UNKNOWN:
case PageInfo::SITE_CONNECTION_STATUS_INTERNAL_PAGE:
- break;
case PageInfo::SITE_CONNECTION_STATUS_ENCRYPTED:
- resource_id = IDR_PAGEINFO_GOOD;
- break;
+ return IDR_PAGEINFO_GOOD;
case PageInfo::SITE_CONNECTION_STATUS_INSECURE_PASSIVE_SUBRESOURCE:
case PageInfo::SITE_CONNECTION_STATUS_INSECURE_FORM_ACTION:
case PageInfo::SITE_CONNECTION_STATUS_LEGACY_TLS:
- resource_id = IDR_PAGEINFO_WARNING_MINOR;
- break;
case PageInfo::SITE_CONNECTION_STATUS_UNENCRYPTED:
- resource_id = IDR_PAGEINFO_WARNING_MAJOR;
- break;
case PageInfo::SITE_CONNECTION_STATUS_INSECURE_ACTIVE_SUBRESOURCE:
case PageInfo::SITE_CONNECTION_STATUS_ENCRYPTED_ERROR:
- resource_id = IDR_PAGEINFO_BAD;
- break;
+ return IDR_PAGEINFO_BAD;
}
- return resource_id;
+ return 0;
}
int PageInfoUI::GetIdentityIconColorID(PageInfo::SiteIdentityStatus status) {
@@ -652,9 +618,8 @@ int PageInfoUI::GetConnectionIconColorID(
#else // !defined(OS_ANDROID)
// static
-const gfx::ImageSkia PageInfoUI::GetPermissionIcon(
- const PageInfo::PermissionInfo& info,
- SkColor related_text_color) {
+const ui::ImageModel PageInfoUI::GetPermissionIcon(
+ const PageInfo::PermissionInfo& info) {
const gfx::VectorIcon* icon = &gfx::kNoneIcon;
switch (info.type) {
case ContentSettingsType::COOKIES:
@@ -685,7 +650,7 @@ const gfx::ImageSkia PageInfoUI::GetPermissionIcon(
case ContentSettingsType::AUTOMATIC_DOWNLOADS:
icon = &vector_icons::kFileDownloadIcon;
break;
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER:
icon = &vector_icons::kProtectedContentIcon;
break;
@@ -752,22 +717,16 @@ const gfx::ImageSkia PageInfoUI::GetPermissionIcon(
ContentSetting setting = info.setting == CONTENT_SETTING_DEFAULT
? info.default_setting
: info.setting;
- if (setting == CONTENT_SETTING_BLOCK) {
- return gfx::CreateVectorIconWithBadge(
- *icon, kVectorIconSize,
- color_utils::DeriveDefaultIconColor(related_text_color),
- vector_icons::kBlockedBadgeIcon);
- }
- return gfx::CreateVectorIcon(
- *icon, kVectorIconSize,
- color_utils::DeriveDefaultIconColor(related_text_color));
+ return ui::ImageModel::FromVectorIcon(
+ *icon, ui::NativeTheme::kColorId_DefaultIconColor, kVectorIconSize,
+ (setting == CONTENT_SETTING_BLOCK) ? &vector_icons::kBlockedBadgeIcon
+ : nullptr);
}
// static
-const gfx::ImageSkia PageInfoUI::GetChosenObjectIcon(
+const ui::ImageModel PageInfoUI::GetChosenObjectIcon(
const ChosenObjectInfo& object,
- bool deleted,
- SkColor related_text_color) {
+ bool deleted) {
// The permissions data for device APIs will always appear even if the device
// is not currently conncted to the system.
// TODO(https://crbug.com/1048860): Check the connected status of devices and
@@ -793,39 +752,68 @@ const gfx::ImageSkia PageInfoUI::GetChosenObjectIcon(
break;
}
- if (deleted) {
- return gfx::CreateVectorIconWithBadge(
- *icon, kVectorIconSize,
- color_utils::DeriveDefaultIconColor(related_text_color),
- vector_icons::kBlockedBadgeIcon);
- }
- return gfx::CreateVectorIcon(
- *icon, kVectorIconSize,
- color_utils::DeriveDefaultIconColor(related_text_color));
+ return ui::ImageModel::FromVectorIcon(
+ *icon, ui::NativeTheme::kColorId_DefaultIconColor, kVectorIconSize,
+ deleted ? &vector_icons::kBlockedBadgeIcon : nullptr);
+}
+
+// static
+const ui::ImageModel PageInfoUI::GetValidCertificateIcon() {
+ return ui::ImageModel::FromVectorIcon(
+ vector_icons::kCertificateIcon,
+ ui::NativeTheme::kColorId_DefaultIconColor, kVectorIconSize);
+}
+
+// static
+const ui::ImageModel PageInfoUI::GetInvalidCertificateIcon() {
+ return ui::ImageModel::FromVectorIcon(
+ vector_icons::kCertificateIcon,
+ ui::NativeTheme::kColorId_DefaultIconColor, kVectorIconSize,
+ &vector_icons::kBlockedBadgeIcon);
}
// static
-const gfx::ImageSkia PageInfoUI::GetCertificateIcon(
- const SkColor related_text_color) {
- return gfx::CreateVectorIcon(
- vector_icons::kCertificateIcon, kVectorIconSize,
- color_utils::DeriveDefaultIconColor(related_text_color));
+const ui::ImageModel PageInfoUI::GetSiteSettingsIcon() {
+ return ui::ImageModel::FromVectorIcon(
+ vector_icons::kSettingsIcon, ui::NativeTheme::kColorId_DefaultIconColor,
+ kVectorIconSize);
}
// static
-const gfx::ImageSkia PageInfoUI::GetSiteSettingsIcon(
- const SkColor related_text_color) {
- return gfx::CreateVectorIcon(
- vector_icons::kSettingsIcon, kVectorIconSize,
- color_utils::DeriveDefaultIconColor(related_text_color));
+const ui::ImageModel PageInfoUI::GetVrSettingsIcon() {
+ return ui::ImageModel::FromVectorIcon(
+ vector_icons::kVrHeadsetIcon, ui::NativeTheme::kColorId_DefaultIconColor,
+ kVectorIconSize);
}
// static
-const gfx::ImageSkia PageInfoUI::GetVrSettingsIcon(SkColor related_text_color) {
- return gfx::CreateVectorIcon(
- vector_icons::kVrHeadsetIcon, kVectorIconSize,
- color_utils::DeriveDefaultIconColor(related_text_color));
+const ui::ImageModel PageInfoUI::GetLaunchIcon() {
+ return ui::ImageModel::FromVectorIcon(
+ vector_icons::kLaunchIcon, ui::NativeTheme::kColorId_SecondaryIconColor,
+ kVectorIconSize);
}
+
+// static
+const ui::ImageModel PageInfoUI::GetConnectionNotSecureIcon() {
+ return ui::ImageModel::FromVectorIcon(
+ vector_icons::kNotSecureWarningIcon,
+ ui::NativeTheme::kColorId_AlertSeverityHigh);
+}
+
+// static
+const ui::ImageModel PageInfoUI::GetConnectionSecureIcon() {
+ return ui::ImageModel::FromVectorIcon(
+ vector_icons::kHttpsValidIcon,
+ ui::NativeTheme::kColorId_DefaultIconColor);
+}
+
+// static
+const ui::ImageModel PageInfoUI::GetOpenSubpageIcon() {
+ return ui::ImageModel::FromVectorIcon(
+ vector_icons::kSubmenuArrowIcon,
+ ui::NativeTheme::kColorId_DefaultIconColor);
+}
+
#endif
// static
diff --git a/chromium/components/page_info/page_info_ui.h b/chromium/components/page_info/page_info_ui.h
index 8ede156840e..3bced7bad81 100644
--- a/chromium/components/page_info/page_info_ui.h
+++ b/chromium/components/page_info/page_info_ui.h
@@ -13,8 +13,9 @@
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/page_info/page_info.h"
-#include "components/permissions/chooser_context_base.h"
+#include "components/permissions/object_permission_context_base.h"
#include "components/safe_browsing/buildflags.h"
+#include "ui/base/models/image_model.h"
#include "ui/gfx/native_widget_types.h"
#if !defined(OS_ANDROID)
@@ -86,14 +87,16 @@ class PageInfoUI {
// |ChosenObjectInfo| contains information about a single |chooser_object| of
// a chooser |type| that the current website has been granted access to.
struct ChosenObjectInfo {
- ChosenObjectInfo(const PageInfo::ChooserUIInfo& ui_info,
- std::unique_ptr<permissions::ChooserContextBase::Object>
- chooser_object);
+ ChosenObjectInfo(
+ const PageInfo::ChooserUIInfo& ui_info,
+ std::unique_ptr<permissions::ObjectPermissionContextBase::Object>
+ chooser_object);
~ChosenObjectInfo();
// |ui_info| for this chosen object type.
const PageInfo::ChooserUIInfo& ui_info;
// The opaque |chooser_object| representing the thing the user selected.
- std::unique_ptr<permissions::ChooserContextBase::Object> chooser_object;
+ std::unique_ptr<permissions::ObjectPermissionContextBase::Object>
+ chooser_object;
};
// |IdentityInfo| contains information about the site's identity and
@@ -195,26 +198,37 @@ class PageInfoUI {
// Returns icons for the given PageInfo::PermissionInfo |info|. If |info|'s
// current setting is CONTENT_SETTING_DEFAULT, it will return the icon for
// |info|'s default setting.
- static const gfx::ImageSkia GetPermissionIcon(
- const PageInfo::PermissionInfo& info,
- const SkColor related_text_color);
+ static const ui::ImageModel GetPermissionIcon(
+ const PageInfo::PermissionInfo& info);
// Returns the icon for the given object |info|.
- static const gfx::ImageSkia GetChosenObjectIcon(
- const ChosenObjectInfo& info,
- bool deleted,
- const SkColor related_text_color);
+ static const ui::ImageModel GetChosenObjectIcon(const ChosenObjectInfo& info,
+ bool deleted);
- // Returns the icon for the page Certificate.
- static const gfx::ImageSkia GetCertificateIcon(
- const SkColor related_text_color);
+ // Returns the icon for the page's certificate when it's valid.
+ static const ui::ImageModel GetValidCertificateIcon();
+
+ // Returns the icon for the page's certificate when it's invalid.
+ static const ui::ImageModel GetInvalidCertificateIcon();
// Returns the icon for the button / link to Site settings.
- static const gfx::ImageSkia GetSiteSettingsIcon(
- const SkColor related_text_color);
+ static const ui::ImageModel GetSiteSettingsIcon();
// Returns the icon for VR settings.
- static const gfx::ImageSkia GetVrSettingsIcon(SkColor related_text_color);
+ static const ui::ImageModel GetVrSettingsIcon();
+
+ // Returns the icon for a button which opens an external dialog or page (ex.
+ // cookies dialog or site settings page).
+ static const ui::ImageModel GetLaunchIcon();
+
+ // Returns the not secure state icon for the SecurityInformationView.
+ static const ui::ImageModel GetConnectionNotSecureIcon();
+
+ // Returns the icon for the secure connection button.
+ static const ui::ImageModel GetConnectionSecureIcon();
+
+ // Returns the icon for a button which opens a subpage within page info.
+ static const ui::ImageModel GetOpenSubpageIcon();
#endif
// Return true if the given ContentSettingsType is in PageInfoUI.
@@ -224,17 +238,19 @@ class PageInfoUI {
CreateSafetyTipSecurityDescription(const security_state::SafetyTipInfo& info);
// Sets cookie information.
- virtual void SetCookieInfo(const CookieInfoList& cookie_info_list) = 0;
+ virtual void SetCookieInfo(const CookieInfoList& cookie_info_list) {}
// Sets permission information.
- virtual void SetPermissionInfo(
- const PermissionInfoList& permission_info_list,
- ChosenObjectInfoList chosen_object_info_list) = 0;
+ virtual void SetPermissionInfo(const PermissionInfoList& permission_info_list,
+ ChosenObjectInfoList chosen_object_info_list) {
+ }
// Sets site identity information.
- virtual void SetIdentityInfo(const IdentityInfo& identity_info) = 0;
+ virtual void SetIdentityInfo(const IdentityInfo& identity_info) {}
- virtual void SetPageFeatureInfo(const PageFeatureInfo& page_feature_info) = 0;
+ // Sets feature related information; for now only if VR content is being
+ // presented in a headset.
+ virtual void SetPageFeatureInfo(const PageFeatureInfo& page_feature_info) {}
// Helper to get security description info to display to the user.
std::unique_ptr<SecurityDescription> GetSecurityDescription(
diff --git a/chromium/components/page_info/page_info_ui_delegate.h b/chromium/components/page_info/page_info_ui_delegate.h
index 011b15300d5..6dd918707bb 100644
--- a/chromium/components/page_info/page_info_ui_delegate.h
+++ b/chromium/components/page_info/page_info_ui_delegate.h
@@ -8,7 +8,6 @@
#include "build/build_config.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/permissions/permission_result.h"
-#include "url/gurl.h"
class PageInfoUiDelegate {
public:
@@ -18,8 +17,6 @@ class PageInfoUiDelegate {
#endif
virtual permissions::PermissionResult GetPermissionStatus(
ContentSettingsType type) = 0;
- virtual bool ShouldShowAllow(ContentSettingsType type) = 0;
- virtual bool ShouldShowAsk(ContentSettingsType type) = 0;
};
#endif // COMPONENTS_PAGE_INFO_PAGE_INFO_UI_DELEGATE_H_
diff --git a/chromium/components/page_info_strings.grdp b/chromium/components/page_info_strings.grdp
index 1ea97d97b94..bd91ad95132 100644
--- a/chromium/components/page_info_strings.grdp
+++ b/chromium/components/page_info_strings.grdp
@@ -249,6 +249,12 @@
<message name="IDS_PAGE_INFO_CERTIFICATE_INVALID_PARENTHESIZED" desc="Button text used as part of IDS_PAGE_INFO_CERTIFICATE_BUTTON_TEXT when the Page Information bubble has been opened for a site with an invalid certificate.">
(Invalid)
</message>
+ <message name="IDS_PAGE_INFO_CERTIFICATE_IS_VALID" desc="Title of the certificate area in the Page Info bubble, shown when a HTTPS site is loaded with a valid certificate.">
+ Certificate is valid
+ </message>
+ <message name="IDS_PAGE_INFO_CERTIFICATE_IS_NOT_VALID" desc="Title of the certificate area in the Page Info bubble, shown when a HTTPS site is loaded with an invalid certificate.">
+ Certificate is not valid
+ </message>
<message name="IDS_PAGE_INFO_CERTIFICATE_VALID_LINK_TOOLTIP" desc="The text of the tooltip on IDS_PAGE_INFO_CERTIFICATE_VALID_LINK.">
Show certificate (issued by <ph name="ISSUER">$1<ex>Let's Encrypt X3</ex></ph>)
</message>
@@ -276,6 +282,9 @@
<message name="IDS_PAGE_INFO_NUM_COOKIES_PARENTHESIZED" desc="The label of the counts for allowed cookies that are in use on the page. This text will be used in IDS_PAGE_INFO_COOKIES_BUTTON_TEXT.">
{NUM_COOKIES, plural, =1 {(1 in use)} other {(# in use)}}
</message>
+ <message name="IDS_PAGE_INFO_NUM_COOKIES" desc="The label of the counts for allowed cookies that are in use on the page. This text will be shown next to IDS_PAGE_INFO_COOKIES_BUTTON_TEXT. It is the same as IDS_PAGE_INFO_NUM_COOKIES_PARENTHESIZED, but without parenthesis">
+ {NUM_COOKIES, plural, =1 {1 in use} other {# in use}}
+ </message>
<message name="IDS_PAGE_INFO_COOKIES_TOOLTIP" desc="The text of the tooltip on IDS_PAGE_INFO_NUM_COOKIES_PARENTHESIZED.">
Show cookies
</message>
@@ -456,6 +465,9 @@
<message name="IDS_PAGE_INFO_SERIAL_PORT_SECONDARY_LABEL" desc="The label displayed underneath the port name to inform the user that the permission listed refers to a serial port.">
Serial port
</message>
+ <message name="IDS_PAGE_INFO_SERIAL_PORT_ALLOWED_BY_POLICY_LABEL" desc="The label displayed underneath the device name to inform the user that the item listed is refering to a serial port explicitly allowed by the user's enterprise policy.">
+ Serial port allowed by your administrator
+ </message>
<message name="IDS_PAGE_INFO_DELETE_SERIAL_PORT" desc="The tooltip displayed when hovering over the button that will remove permission to access a serial port that the user previously granted to the site.">
Revoke access
</message>
@@ -657,4 +669,9 @@
<message name="IDS_CERT_X509_SUBJECT_ALT_NAME" desc="description of extension Certificate Subject Alternative Name">
Certificate Subject Alternative Name
</message>
+
+ <!-- Subpages headers -->
+ <message name="IDS_PAGE_INFO_SECURITY_SUBPAGE_HEADER" desc="The header label of the Security subpage in page info bubble.">
+ Security
+ </message>
</grit-part>
diff --git a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_CERTIFICATE_IS_NOT_VALID.png.sha1 b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_CERTIFICATE_IS_NOT_VALID.png.sha1
new file mode 100644
index 00000000000..8d059c774c1
--- /dev/null
+++ b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_CERTIFICATE_IS_NOT_VALID.png.sha1
@@ -0,0 +1 @@
+6431f60ed41e4c11d919631d458a7a5692437e98 \ No newline at end of file
diff --git a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_CERTIFICATE_IS_VALID.png.sha1 b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_CERTIFICATE_IS_VALID.png.sha1
new file mode 100644
index 00000000000..66b3c2ad7c1
--- /dev/null
+++ b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_CERTIFICATE_IS_VALID.png.sha1
@@ -0,0 +1 @@
+3c1bec2a0db5e79f8855fd4db9b4cdb4b5a5aa8a \ No newline at end of file
diff --git a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_NUM_COOKIES.png.sha1 b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_NUM_COOKIES.png.sha1
new file mode 100644
index 00000000000..5a9520f61f2
--- /dev/null
+++ b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_NUM_COOKIES.png.sha1
@@ -0,0 +1 @@
+51a0015c5a3a3addcc049b806e938c932b3b948a \ No newline at end of file
diff --git a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SECURITY_SUBPAGE_HEADER.png.sha1 b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SECURITY_SUBPAGE_HEADER.png.sha1
new file mode 100644
index 00000000000..89138bf0c88
--- /dev/null
+++ b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SECURITY_SUBPAGE_HEADER.png.sha1
@@ -0,0 +1 @@
+ea19da9661a9ecc47efd6ede07771b6d3870fea8 \ No newline at end of file
diff --git a/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SERIAL_PORT_ALLOWED_BY_POLICY_LABEL.png.sha1 b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SERIAL_PORT_ALLOWED_BY_POLICY_LABEL.png.sha1
new file mode 100644
index 00000000000..e820b4a25e9
--- /dev/null
+++ b/chromium/components/page_info_strings_grdp/IDS_PAGE_INFO_SERIAL_PORT_ALLOWED_BY_POLICY_LABEL.png.sha1
@@ -0,0 +1 @@
+f02b992da10248becf8af681b57b620224fd825f \ No newline at end of file
diff --git a/chromium/components/page_load_metrics/browser/BUILD.gn b/chromium/components/page_load_metrics/browser/BUILD.gn
index b988a8c6fca..71de6cd0770 100644
--- a/chromium/components/page_load_metrics/browser/BUILD.gn
+++ b/chromium/components/page_load_metrics/browser/BUILD.gn
@@ -100,6 +100,7 @@ source_set("unit_tests") {
sources = [
"layout_shift_normalization_unittest.cc",
"metrics_web_contents_observer_unittest.cc",
+ "observers/back_forward_cache_page_load_metrics_observer_unittest.cc",
"observers/click_input_tracker_unittest.cc",
"observers/core/uma_page_load_metrics_observer_unittest.cc",
"observers/early_hints_page_load_metrics_observer_unittest.cc",
diff --git a/chromium/components/page_load_metrics/browser/DIR_METADATA b/chromium/components/page_load_metrics/browser/DIR_METADATA
deleted file mode 100644
index 9c0622fe217..00000000000
--- a/chromium/components/page_load_metrics/browser/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Speed>Metrics"
-}
diff --git a/chromium/components/page_load_metrics/browser/layout_shift_normalization.cc b/chromium/components/page_load_metrics/browser/layout_shift_normalization.cc
index 3ec674bca3f..d6df884657d 100644
--- a/chromium/components/page_load_metrics/browser/layout_shift_normalization.cc
+++ b/chromium/components/page_load_metrics/browser/layout_shift_normalization.cc
@@ -25,7 +25,7 @@ void LayoutShiftNormalization::AddInputTimeStamps(
void LayoutShiftNormalization::AddNewLayoutShifts(
const std::vector<page_load_metrics::mojom::LayoutShiftPtr>& new_shifts,
base::TimeTicks current_time,
- double cumulative_layout_shift_score) {
+ float cumulative_layout_shift_score) {
if (new_shifts.empty() || normalized_cls_data_.data_tainted)
return;
@@ -115,7 +115,7 @@ void LayoutShiftNormalization::UpdateSessionWindow(
std::vector<std::pair<base::TimeTicks, double>>::const_iterator begin,
std::vector<std::pair<base::TimeTicks, double>>::const_iterator end,
std::vector<base::TimeTicks>& input_timestamps,
- double& max_score,
+ float& max_score,
uint32_t& count) {
for (auto it = begin; it != end; ++it) {
if ((it->first - session_window->last_time > gap) ||
@@ -156,8 +156,8 @@ void LayoutShiftNormalization::UpdateWindowCLS(
std::vector<std::pair<base::TimeTicks, double>>::const_iterator
first_non_stale,
std::vector<std::pair<base::TimeTicks, double>>::const_iterator last,
- double cumulative_layout_shift_score) {
- double dummy_max = 0.0;
+ float cumulative_layout_shift_score) {
+ float dummy_max = 0.0;
uint32_t dummy_count = 0;
std::vector<base::TimeTicks> dummy_input_timestamps;
// Update Sliding Windows.
diff --git a/chromium/components/page_load_metrics/browser/layout_shift_normalization.h b/chromium/components/page_load_metrics/browser/layout_shift_normalization.h
index f202d3ed206..4f7068333b4 100644
--- a/chromium/components/page_load_metrics/browser/layout_shift_normalization.h
+++ b/chromium/components/page_load_metrics/browser/layout_shift_normalization.h
@@ -26,7 +26,7 @@ class LayoutShiftNormalization {
void AddNewLayoutShifts(
const std::vector<page_load_metrics::mojom::LayoutShiftPtr>& new_shifts,
base::TimeTicks current_time,
- /*Whole page CLS*/ double cumulative_layout_shift_score);
+ /*Whole page CLS*/ float cumulative_layout_shift_score);
void ClearAllLayoutShifts();
@@ -39,7 +39,7 @@ class LayoutShiftNormalization {
struct SessionWindow {
base::TimeTicks start_time;
base::TimeTicks last_time;
- double layout_shift_score = 0.0;
+ float layout_shift_score = 0.0;
};
void UpdateWindowCLS(
@@ -48,7 +48,7 @@ class LayoutShiftNormalization {
std::vector<std::pair<base::TimeTicks, double>>::const_iterator
first_non_stale,
std::vector<std::pair<base::TimeTicks, double>>::const_iterator last,
- double cumulative_layout_shift_score);
+ float cumulative_layout_shift_score);
void UpdateSlidingWindow(
std::vector<SlidingWindow>* sliding_windows,
@@ -65,7 +65,7 @@ class LayoutShiftNormalization {
std::vector<std::pair<base::TimeTicks, double>>::const_iterator begin,
std::vector<std::pair<base::TimeTicks, double>>::const_iterator end,
std::vector<base::TimeTicks>& input_timestamps,
- double& max_score,
+ float& max_score,
uint32_t& count);
// CLS normalization
@@ -87,7 +87,7 @@ class LayoutShiftNormalization {
// A new input in non-stale data can split the session window and make the
// max_cls smaller. We need to store the "max_cls" calculated by the stale
// data.
- double potential_max_cls_session_by_inputs_gap1000ms_max5000ms_ = 0.0;
+ float potential_max_cls_session_by_inputs_gap1000ms_max5000ms_ = 0.0;
uint32_t session_gap5000ms_count_ = 0;
DISALLOW_COPY_AND_ASSIGN(LayoutShiftNormalization);
diff --git a/chromium/components/page_load_metrics/browser/layout_shift_normalization_unittest.cc b/chromium/components/page_load_metrics/browser/layout_shift_normalization_unittest.cc
index 857f9cd3953..53617ff1e3e 100644
--- a/chromium/components/page_load_metrics/browser/layout_shift_normalization_unittest.cc
+++ b/chromium/components/page_load_metrics/browser/layout_shift_normalization_unittest.cc
@@ -44,7 +44,7 @@ class LayoutShiftNormalizationTest : public testing::Test {
private:
page_load_metrics::LayoutShiftNormalization layout_shift_normalization_;
- double cumulative_layoutshift_score_ = 0.0;
+ float cumulative_layoutshift_score_ = 0.0;
};
TEST_F(LayoutShiftNormalizationTest, MultipleShifts) {
diff --git a/chromium/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/chromium/components/page_load_metrics/browser/metrics_web_contents_observer.cc
index 3540ed59633..7c2f24721d4 100644
--- a/chromium/components/page_load_metrics/browser/metrics_web_contents_observer.cc
+++ b/chromium/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -13,6 +13,7 @@
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
+#include "base/trace_event/trace_event.h"
#include "components/page_load_metrics/browser/page_load_metrics_embedder_interface.h"
#include "components/page_load_metrics/browser/page_load_metrics_memory_tracker.h"
#include "components/page_load_metrics/browser/page_load_metrics_update_dispatcher.h"
@@ -82,13 +83,33 @@ bool ShouldProcessNavigation(content::NavigationHandle* navigation_handle) {
// static
void MetricsWebContentsObserver::RecordFeatureUsage(
content::RenderFrameHost* render_frame_host,
- const mojom::PageLoadFeatures& new_features) {
+ const std::vector<blink::mojom::WebFeature>& web_features) {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
MetricsWebContentsObserver* observer =
MetricsWebContentsObserver::FromWebContents(web_contents);
- if (observer)
- observer->OnBrowserFeatureUsage(render_frame_host, new_features);
+
+ if (observer) {
+ std::vector<blink::UseCounterFeature> features;
+ for (auto web_feature : web_features) {
+ DCHECK_NE(web_feature, blink::mojom::WebFeature::kPageVisits)
+ << "WebFeature::kPageVisits is a reserved feature.";
+ if (web_feature == blink::mojom::WebFeature::kPageVisits)
+ continue;
+
+ features.emplace_back(blink::mojom::UseCounterFeatureType::kWebFeature,
+ static_cast<uint32_t>(web_feature));
+ }
+ observer->OnBrowserFeatureUsage(render_frame_host, features);
+ }
+}
+
+// static
+void MetricsWebContentsObserver::RecordFeatureUsage(
+ content::RenderFrameHost* render_frame_host,
+ blink::mojom::WebFeature feature) {
+ MetricsWebContentsObserver::RecordFeatureUsage(
+ render_frame_host, std::vector<blink::mojom::WebFeature>{feature});
}
// static
@@ -208,9 +229,9 @@ MetricsWebContentsObserver::MetricsWebContentsObserver(
embedder_interface_(std::move(embedder_interface)),
has_navigated_(false),
page_load_metrics_receiver_(web_contents, this) {
- // Prerenders erroneously report that they are initially visible, so we
- // manually override visibility state for prerender.
- if (embedder_interface_->IsPrerender(web_contents))
+ // NoStatePrefetch loads erroneously report that they are initially visible,
+ // so we manually override visibility state for prerender.
+ if (embedder_interface_->IsNoStatePrefetch(web_contents))
in_foreground_ = false;
RegisterInputEventObserver(web_contents->GetMainFrame()->GetRenderViewHost());
@@ -853,7 +874,7 @@ void MetricsWebContentsObserver::OnTimingUpdated(
content::RenderFrameHost* render_frame_host,
mojom::PageLoadTimingPtr timing,
mojom::FrameMetadataPtr metadata,
- mojom::PageLoadFeaturesPtr new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
const std::vector<mojom::ResourceDataUpdatePtr>& resources,
mojom::FrameRenderDataUpdatePtr render_data,
mojom::CpuTimingPtr cpu_timing,
@@ -910,7 +931,7 @@ bool MetricsWebContentsObserver::DoesTimingUpdateHaveError() {
void MetricsWebContentsObserver::UpdateTiming(
mojom::PageLoadTimingPtr timing,
mojom::FrameMetadataPtr metadata,
- mojom::PageLoadFeaturesPtr new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
std::vector<mojom::ResourceDataUpdatePtr> resources,
mojom::FrameRenderDataUpdatePtr render_data,
mojom::CpuTimingPtr cpu_timing,
@@ -920,7 +941,7 @@ void MetricsWebContentsObserver::UpdateTiming(
content::RenderFrameHost* render_frame_host =
page_load_metrics_receiver_.GetCurrentTargetFrame();
OnTimingUpdated(render_frame_host, std::move(timing), std::move(metadata),
- std::move(new_features), resources, std::move(render_data),
+ new_features, resources, std::move(render_data),
std::move(cpu_timing), std::move(new_deferred_resource_data),
std::move(input_timing_delta),
std::move(mobile_friendliness));
@@ -981,10 +1002,16 @@ bool MetricsWebContentsObserver::ShouldTrackMainFrameNavigation(
void MetricsWebContentsObserver::OnBrowserFeatureUsage(
content::RenderFrameHost* render_frame_host,
- const mojom::PageLoadFeatures& new_features) {
+ const std::vector<blink::UseCounterFeature>& new_features) {
// Since this call is coming directly from the browser, it should not pass us
- // data from frames that have already been navigated away from.
- DCHECK(render_frame_host->GetMainFrame()->IsCurrent());
+ // data from frames that have already been navigated away from. However, this
+ // could be false if this is called for the page that is prerendering with
+ // MPArch. Therefore, ignore navigations not happening in the primary
+ // FrameTree. Using IsCurrent as a proxy for "is in primary FrameTree".
+ // TODO(https://crbug.com/1190112): Add proper support for prerendering when
+ // there are better content APIs.
+ if (!render_frame_host->GetMainFrame()->IsCurrent())
+ return;
if (!committed_load_) {
RecordInternalError(ERR_BROWSER_USAGE_WITH_NO_RELEVANT_LOAD);
diff --git a/chromium/components/page_load_metrics/browser/metrics_web_contents_observer.h b/chromium/components/page_load_metrics/browser/metrics_web_contents_observer.h
index fcd944bb14c..2629f045d75 100644
--- a/chromium/components/page_load_metrics/browser/metrics_web_contents_observer.h
+++ b/chromium/components/page_load_metrics/browser/metrics_web_contents_observer.h
@@ -89,11 +89,14 @@ class MetricsWebContentsObserver
DISALLOW_COPY_AND_ASSIGN(TestingObserver);
};
- // Record a set of PageLoadFeatures directly from the browser process. This
+ // Record a set of WebFeatures directly from the browser process. This
// should only be used for features that were detected browser-side; features
// sources from the renderer should go via MetricsRenderFrameObserver.
+ static void RecordFeatureUsage(
+ content::RenderFrameHost* render_frame_host,
+ const std::vector<blink::mojom::WebFeature>& features);
static void RecordFeatureUsage(content::RenderFrameHost* render_frame_host,
- const mojom::PageLoadFeatures& new_features);
+ blink::mojom::WebFeature feature);
// Note that the returned metrics is owned by the web contents.
static MetricsWebContentsObserver* CreateForWebContents(
@@ -168,7 +171,7 @@ class MetricsWebContentsObserver
content::RenderFrameHost* render_frame_host,
mojom::PageLoadTimingPtr timing,
mojom::FrameMetadataPtr metadata,
- mojom::PageLoadFeaturesPtr new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
const std::vector<mojom::ResourceDataUpdatePtr>& resources,
mojom::FrameRenderDataUpdatePtr render_data,
mojom::CpuTimingPtr cpu_timing,
@@ -207,7 +210,7 @@ class MetricsWebContentsObserver
void UpdateTiming(
mojom::PageLoadTimingPtr timing,
mojom::FrameMetadataPtr metadata,
- mojom::PageLoadFeaturesPtr new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
std::vector<mojom::ResourceDataUpdatePtr> resources,
mojom::FrameRenderDataUpdatePtr render_data,
mojom::CpuTimingPtr cpu_timing,
@@ -268,8 +271,9 @@ class MetricsWebContentsObserver
bool ShouldTrackMainFrameNavigation(
content::NavigationHandle* navigation_handle) const;
- void OnBrowserFeatureUsage(content::RenderFrameHost* render_frame_host,
- const mojom::PageLoadFeatures& new_features);
+ void OnBrowserFeatureUsage(
+ content::RenderFrameHost* render_frame_host,
+ const std::vector<blink::UseCounterFeature>& new_features);
// Before deleting PageLoadTracker, check if we need to keep it alive as the
// page is stored in back-forward cache. The page can either be restored later
diff --git a/chromium/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc b/chromium/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc
index ce757b68785..57d6923b0f9 100644
--- a/chromium/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc
+++ b/chromium/components/page_load_metrics/browser/metrics_web_contents_observer_unittest.cc
@@ -28,7 +28,9 @@
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/use_counter/use_counter_feature.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
+#include "third_party/blink/public/mojom/use_counter/use_counter_feature.mojom-shared.h"
#include "url/url_constants.h"
using content::NavigationSimulator;
@@ -110,7 +112,7 @@ class MetricsWebContentsObserverTest
observer()->OnTimingUpdated(
render_frame_host, previous_timing_->Clone(),
mojom::FrameMetadataPtr(base::in_place),
- mojom::PageLoadFeaturesPtr(base::in_place),
+ std::vector<blink::UseCounterFeature>(),
std::vector<mojom::ResourceDataUpdatePtr>(),
mojom::FrameRenderDataUpdatePtr(base::in_place), timing.Clone(),
mojom::DeferredResourceCountsPtr(base::in_place),
@@ -135,7 +137,7 @@ class MetricsWebContentsObserverTest
observer()->OnTimingUpdated(
render_frame_host, timing.Clone(),
mojom::FrameMetadataPtr(base::in_place),
- mojom::PageLoadFeaturesPtr(base::in_place),
+ std::vector<blink::UseCounterFeature>(),
std::vector<mojom::ResourceDataUpdatePtr>(),
mojom::FrameRenderDataUpdatePtr(base::in_place),
mojom::CpuTimingPtr(base::in_place),
@@ -214,11 +216,11 @@ class MetricsWebContentsObserverTest
return embedder_interface_->observed_aborted_urls();
}
- const std::vector<mojom::PageLoadFeatures>& observed_features() const {
+ const std::vector<blink::UseCounterFeature>& observed_features() const {
return embedder_interface_->observed_features();
}
- const base::Optional<bool>& is_first_navigation_in_web_contents() const {
+ const absl::optional<bool>& is_first_navigation_in_web_contents() const {
return embedder_interface_->is_first_navigation_in_web_contents();
}
@@ -1450,18 +1452,23 @@ TEST_F(MetricsWebContentsObserverTest, RecordFeatureUsage) {
web_contents(), GURL(kDefaultTestUrl));
ASSERT_EQ(main_rfh()->GetLastCommittedURL().spec(), GURL(kDefaultTestUrl));
- std::vector<blink::mojom::WebFeature> web_features;
- web_features.push_back(blink::mojom::WebFeature::kHTMLMarqueeElement);
- web_features.push_back(blink::mojom::WebFeature::kFormAttribute);
- mojom::PageLoadFeatures features(web_features, {}, {});
- MetricsWebContentsObserver::RecordFeatureUsage(main_rfh(), features);
-
- ASSERT_EQ(observed_features().size(), 1ul);
- ASSERT_EQ(observed_features()[0].features.size(), 2ul);
- EXPECT_EQ(observed_features()[0].features[0],
- blink::mojom::WebFeature::kHTMLMarqueeElement);
- EXPECT_EQ(observed_features()[0].features[1],
- blink::mojom::WebFeature::kFormAttribute);
+ MetricsWebContentsObserver::RecordFeatureUsage(
+ main_rfh(), {blink::mojom::WebFeature::kHTMLMarqueeElement,
+ blink::mojom::WebFeature::kFormAttribute});
+
+ blink::UseCounterFeature feature1 = {
+ blink::mojom::UseCounterFeatureType::kWebFeature,
+ static_cast<uint32_t>(blink::mojom::WebFeature::kHTMLMarqueeElement),
+ };
+
+ blink::UseCounterFeature feature2 = {
+ blink::mojom::UseCounterFeatureType::kWebFeature,
+ static_cast<uint32_t>(blink::mojom::WebFeature::kFormAttribute),
+ };
+
+ ASSERT_EQ(observed_features().size(), 2ul);
+ EXPECT_EQ(observed_features()[0], feature1);
+ EXPECT_EQ(observed_features()[1], feature2);
}
TEST_F(MetricsWebContentsObserverTest, RecordFeatureUsageNoObserver) {
@@ -1471,15 +1478,14 @@ TEST_F(MetricsWebContentsObserverTest, RecordFeatureUsageNoObserver) {
// This call should just do nothing, and should not crash - if that happens,
// we are good.
- std::vector<blink::mojom::WebFeature> web_features;
- web_features.push_back(blink::mojom::WebFeature::kHTMLMarqueeElement);
- web_features.push_back(blink::mojom::WebFeature::kFormAttribute);
- mojom::PageLoadFeatures features(web_features, {}, {});
- MetricsWebContentsObserver::RecordFeatureUsage(main_rfh(), features);
+ MetricsWebContentsObserver::RecordFeatureUsage(
+ main_rfh(), {blink::mojom::WebFeature::kHTMLMarqueeElement,
+ blink::mojom::WebFeature::kFormAttribute});
}
class MetricsWebContentsObserverBackForwardCacheTest
- : public MetricsWebContentsObserverTest {
+ : public MetricsWebContentsObserverTest,
+ public content::WebContentsDelegate {
class CreatedPageLoadTrackerObserver
: public MetricsWebContentsObserver::TestingObserver {
public:
@@ -1516,8 +1522,12 @@ class MetricsWebContentsObserverBackForwardCacheTest
created_page_load_tracker_observer_ =
std::make_unique<CreatedPageLoadTrackerObserver>(web_contents());
observer()->AddTestingObserver(created_page_load_tracker_observer_.get());
+ web_contents()->SetDelegate(this);
}
+ // content::WebContentsDelegate:
+ bool IsBackForwardCacheSupported() override { return true; }
+
private:
base::test::ScopedFeatureList feature_list_;
std::unique_ptr<CreatedPageLoadTrackerObserver>
@@ -1530,28 +1540,23 @@ TEST_F(MetricsWebContentsObserverBackForwardCacheTest,
web_contents(), GURL(kDefaultTestUrl));
ASSERT_EQ(main_rfh()->GetLastCommittedURL().spec(), GURL(kDefaultTestUrl));
- std::vector<blink::mojom::WebFeature> web_features1{
- blink::mojom::WebFeature::kHTMLMarqueeElement};
- mojom::PageLoadFeatures features1(web_features1, {}, {});
- MetricsWebContentsObserver::RecordFeatureUsage(main_rfh(), features1);
+ MetricsWebContentsObserver::RecordFeatureUsage(
+ main_rfh(), blink::mojom::WebFeature::kHTMLMarqueeElement);
content::NavigationSimulator::NavigateAndCommitFromBrowser(
web_contents(), GURL(kDefaultTestUrl2));
content::NavigationSimulator::GoBack(web_contents());
- std::vector<blink::mojom::WebFeature> web_features2{
- blink::mojom::WebFeature::kFormAttribute};
- mojom::PageLoadFeatures features2(web_features2, {}, {});
- MetricsWebContentsObserver::RecordFeatureUsage(main_rfh(), features2);
-
- std::vector<std::vector<blink::mojom::WebFeature>> features;
- for (const auto& observation : observed_features()) {
- features.push_back(observation.features);
- }
+ MetricsWebContentsObserver::RecordFeatureUsage(
+ main_rfh(), blink::mojom::WebFeature::kFormAttribute);
// For now back-forward cached navigations are not tracked and the events
// after the history navigation are not tracked.
- EXPECT_THAT(features, testing::ElementsAre(web_features1));
+ blink::UseCounterFeature feature = {
+ blink::mojom::UseCounterFeatureType::kWebFeature,
+ static_cast<uint32_t>(blink::mojom::WebFeature::kHTMLMarqueeElement),
+ };
+ EXPECT_THAT(observed_features(), testing::ElementsAre(feature));
}
// Checks OnEnterBackForwardCache is called appropriately with back-forward
diff --git a/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc b/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc
index e19d37e5c07..f86d8b76f26 100644
--- a/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc
+++ b/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc
@@ -100,13 +100,6 @@ content::RenderFrameHost* FindFrameMaybeUnsafe(
handle->GetFrameTreeNodeId());
}
-void RecordFeatureUsage(content::RenderFrameHost* rfh,
- blink::mojom::WebFeature web_feature) {
- mojom::PageLoadFeatures page_load_features(
- {web_feature}, {} /* css_properties */, {} /* animated_css_properties */);
- MetricsWebContentsObserver::RecordFeatureUsage(rfh, page_load_features);
-}
-
std::string GetHeavyAdReportMessage(const FrameTreeData& frame_data,
bool will_unload_adframe) {
const char kChromeStatusMessage[] =
@@ -480,7 +473,7 @@ void AdsPageLoadMetricsObserver::OnDidFinishSubFrameNavigation(
// logic should be moved into /subresource_filter/ and applied to all of ad
// tagging, rather than being implemented in AdsPLMO.
bool should_ignore_detected_ad = false;
- base::Optional<subresource_filter::LoadPolicy> load_policy =
+ absl::optional<subresource_filter::LoadPolicy> load_policy =
throttle_manager->LoadPolicyForLastCommittedNavigation(frame_host);
// Only un-tag frames as ads if the navigation has committed. This prevents
@@ -1275,8 +1268,8 @@ void AdsPageLoadMetricsObserver::MaybeTriggerHeavyAdIntervention(
// Record this UMA regardless of if we actually unload or not, as sending
// reports is subject to the same noise and throttling as the intervention.
- RecordFeatureUsage(render_frame_host,
- blink::mojom::WebFeature::kHeavyAdIntervention);
+ MetricsWebContentsObserver::RecordFeatureUsage(
+ render_frame_host, blink::mojom::WebFeature::kHeavyAdIntervention);
ADS_HISTOGRAM("HeavyAds.InterventionType2", UMA_HISTOGRAM_ENUMERATION,
FrameVisibility::kAnyVisibility,
diff --git a/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.h b/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.h
index 5e938bae37f..6401cd85ae5 100644
--- a/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.h
+++ b/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.h
@@ -295,7 +295,7 @@ class AdsPageLoadMetricsObserver
// on the URL of this page. Incognito Profiles will cause this to be set to
// true. Used as a cache to avoid checking the blocklist once the page is
// blocklisted. Once blocklisted, a page load cannot be unblocklisted.
- base::Optional<blocklist::BlocklistReason> heavy_ads_blocklist_reason_;
+ absl::optional<blocklist::BlocklistReason> heavy_ads_blocklist_reason_;
// Pointer to the HeavyAdService from which the heavy ad blocklist is obtained
// in production.
diff --git a/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc b/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
index 71471ea53ad..7d1930a0c0b 100644
--- a/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
+++ b/chromium/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
@@ -205,7 +205,7 @@ class ResourceLoadingCancellingThrottle
observer->OnTimingUpdated(
navigation_handle()->GetRenderFrameHost(), std::move(timing),
mojom::FrameMetadataPtr(base::in_place),
- mojom::PageLoadFeaturesPtr(base::in_place), resources,
+ std::vector<blink::UseCounterFeature>(), resources,
mojom::FrameRenderDataUpdatePtr(base::in_place),
mojom::CpuTimingPtr(base::in_place),
mojom::DeferredResourceCountsPtr(base::in_place),
@@ -561,8 +561,8 @@ class AdsPageLoadMetricsObserverTest
// of the first call.
void SimulateFirstEligibleToPaintOrFirstContentfulPaint(
RenderFrameHost* frame,
- base::Optional<base::TimeDelta> first_eligible_to_paint,
- base::Optional<base::TimeDelta> first_contentful_paint) {
+ absl::optional<base::TimeDelta> first_eligible_to_paint,
+ absl::optional<base::TimeDelta> first_contentful_paint) {
InitPageLoadTimingForTest(&timing_);
timing_.navigation_start = base::Time::Now();
timing_.parse_timing->parse_start = kParseStartTime;
@@ -576,7 +576,7 @@ class AdsPageLoadMetricsObserverTest
void SimulateFirstContentfulPaint(
RenderFrameHost* frame,
- base::Optional<base::TimeDelta> first_contentful_paint) {
+ absl::optional<base::TimeDelta> first_contentful_paint) {
SimulateFirstEligibleToPaintOrFirstContentfulPaint(
frame, first_contentful_paint /* first_eligible_to_paint */,
first_contentful_paint /* first_contentful_paint */);
@@ -710,10 +710,10 @@ class AdsPageLoadMetricsObserverTest
frames[i], eligible_time, fcp_time);
} else if (!is_throttled) {
SimulateFirstEligibleToPaintOrFirstContentfulPaint(
- frames[i], eligible_time, base::nullopt);
+ frames[i], eligible_time, absl::nullopt);
} else {
SimulateFirstEligibleToPaintOrFirstContentfulPaint(
- frames[i], base::nullopt, base::nullopt);
+ frames[i], absl::nullopt, absl::nullopt);
}
}
@@ -763,7 +763,7 @@ class AdsPageLoadMetricsObserverTest
// relevant histogram, ensuring it's empty if there is no task_time, or it
// has the correct task_time for the tasks performed otherwise.
void CheckTotalUsageHistogram(std::string prefix,
- base::Optional<int> task_time,
+ absl::optional<int> task_time,
std::string suffix = "") {
suffix = suffix.empty() ? "" : "." + suffix;
if (task_time.has_value()) {
@@ -778,9 +778,9 @@ class AdsPageLoadMetricsObserverTest
// A shorcut that given pre- and post-activation task time (if they exist),
// will check the three relevant TotalUsage histograms.
- void CheckActivatedTotalUsageHistograms(base::Optional<int> pre_task_time,
- base::Optional<int> post_task_time) {
- base::Optional<int> total_task_time;
+ void CheckActivatedTotalUsageHistograms(absl::optional<int> pre_task_time,
+ absl::optional<int> post_task_time) {
+ absl::optional<int> total_task_time;
if (pre_task_time.has_value() || post_task_time.has_value())
total_task_time = pre_task_time.value_or(0) + post_task_time.value_or(0);
@@ -1726,7 +1726,7 @@ TEST_F(AdsPageLoadMetricsObserverTest, TestCpuTimingMetricsNoActivation) {
// Check the cpu histograms.
CheckTotalUsageHistogram("FullPage", 500 + 500 + 1000 + 500);
CheckTotalUsageHistogram("NonAdFrames.Aggregate", 500 + 500);
- CheckActivatedTotalUsageHistograms(base::nullopt, base::nullopt);
+ CheckActivatedTotalUsageHistograms(absl::nullopt, absl::nullopt);
CheckTotalUsageHistogram("AdFrames.PerFrame", 500 + 1000, "Unactivated");
histogram_tester().ExpectUniqueSample(
SuffixedHistogram("Cpu.AdFrames.Aggregate.TotalUsage2"), 500 + 1000, 1);
@@ -1775,7 +1775,7 @@ TEST_F(AdsPageLoadMetricsObserverTest, TestCpuTimingMetricsOnActivation) {
// Check the cpu histograms.
CheckTotalUsageHistogram("FullPage", 500 + 500 + 1000 + 500);
CheckTotalUsageHistogram("NonAdFrames.Aggregate", 500 + 500);
- CheckTotalUsageHistogram("AdFrames.PerFrame", base::nullopt, "Unactivated");
+ CheckTotalUsageHistogram("AdFrames.PerFrame", absl::nullopt, "Unactivated");
CheckActivatedTotalUsageHistograms(500 + 500, 500);
histogram_tester().ExpectUniqueSample(
SuffixedHistogram("Cpu.AdFrames.Aggregate.TotalUsage2"), 1000 + 500, 1);
diff --git a/chromium/components/page_load_metrics/browser/observers/ad_metrics/frame_tree_data.cc b/chromium/components/page_load_metrics/browser/observers/ad_metrics/frame_tree_data.cc
index f9b6d29ea93..f3e636981bb 100644
--- a/chromium/components/page_load_metrics/browser/observers/ad_metrics/frame_tree_data.cc
+++ b/chromium/components/page_load_metrics/browser/observers/ad_metrics/frame_tree_data.cc
@@ -132,7 +132,7 @@ FrameTreeData::GetCreativeOriginStatusWithThrottling() const {
}
void FrameTreeData::SetFirstEligibleToPaint(
- base::Optional<base::TimeDelta> time_stamp) {
+ absl::optional<base::TimeDelta> time_stamp) {
if (time_stamp.has_value()) {
// If the ad frame tree hasn't already received an earlier paint
// eligibility stamp, mark it as eligible to paint. Since multiple frames
@@ -152,7 +152,7 @@ void FrameTreeData::SetFirstEligibleToPaint(
}
bool FrameTreeData::SetEarliestFirstContentfulPaint(
- base::Optional<base::TimeDelta> time_stamp) {
+ absl::optional<base::TimeDelta> time_stamp) {
if (!time_stamp.has_value() || time_stamp.value().is_zero())
return false;
diff --git a/chromium/components/page_load_metrics/browser/observers/ad_metrics/frame_tree_data.h b/chromium/components/page_load_metrics/browser/observers/ad_metrics/frame_tree_data.h
index ae29d166f47..cc7775a3890 100644
--- a/chromium/components/page_load_metrics/browser/observers/ad_metrics/frame_tree_data.h
+++ b/chromium/components/page_load_metrics/browser/observers/ad_metrics/frame_tree_data.h
@@ -7,16 +7,14 @@
#include <stdint.h>
-#include <unordered_map>
-
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/page_load_metrics/browser/observers/ad_metrics/frame_data_utils.h"
#include "components/page_load_metrics/browser/page_load_metrics_observer.h"
#include "components/page_load_metrics/common/page_load_metrics.mojom-forward.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
#include "url/origin.h"
@@ -193,11 +191,11 @@ class FrameTreeData : public base::SupportsWeakPtr<FrameTreeData> {
return creative_origin_status_;
}
- base::Optional<base::TimeDelta> first_eligible_to_paint() const {
+ absl::optional<base::TimeDelta> first_eligible_to_paint() const {
return first_eligible_to_paint_;
}
- base::Optional<base::TimeDelta> earliest_first_contentful_paint() const {
+ absl::optional<base::TimeDelta> earliest_first_contentful_paint() const {
return earliest_first_contentful_paint_;
}
// Sets the size of the frame and updates its visibility state.
@@ -236,11 +234,11 @@ class FrameTreeData : public base::SupportsWeakPtr<FrameTreeData> {
creative_origin_status_ = creative_origin_status;
}
- void SetFirstEligibleToPaint(base::Optional<base::TimeDelta> time_stamp);
+ void SetFirstEligibleToPaint(absl::optional<base::TimeDelta> time_stamp);
// Returns whether a new FCP is set.
bool SetEarliestFirstContentfulPaint(
- base::Optional<base::TimeDelta> time_stamp);
+ absl::optional<base::TimeDelta> time_stamp);
HeavyAdStatus heavy_ad_status_with_noise() const {
return heavy_ad_status_with_noise_;
@@ -311,11 +309,11 @@ class FrameTreeData : public base::SupportsWeakPtr<FrameTreeData> {
// as being eligible to paint, or null if all frames are currently
// render-throttled and there hasn't been a first paint. Note that this
// timestamp and the implied throttling status are best-effort.
- base::Optional<base::TimeDelta> first_eligible_to_paint_;
+ absl::optional<base::TimeDelta> first_eligible_to_paint_;
// The smallest FCP seen for any any frame in this ad frame tree, if a
// frame has painted.
- base::Optional<base::TimeDelta> earliest_first_contentful_paint_;
+ absl::optional<base::TimeDelta> earliest_first_contentful_paint_;
// Indicates whether or not this frame met the criteria for the heavy ad
// intervention with additional additive noise for the
diff --git a/chromium/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.cc b/chromium/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.cc
index 33d502c67ca..bc2b8284687 100644
--- a/chromium/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.cc
+++ b/chromium/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.cc
@@ -5,7 +5,7 @@
#include "components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/checked_math.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace page_load_metrics {
@@ -95,7 +95,7 @@ class SegmentLength {
// Calculate the combined length of segments in the active set of segments by
// iterating over the the sorted set of segment events.
- base::Optional<int> Length() {
+ absl::optional<int> Length() {
base::CheckedNumeric<int> length = 0;
int last_event_pos = -1;
int num_active = 0;
@@ -116,7 +116,7 @@ class SegmentLength {
}
}
- base::Optional<int> total_length;
+ absl::optional<int> total_length;
if (length.IsValid())
total_length = length.ValueOrDie();
@@ -234,7 +234,7 @@ void PageAdDensityTracker::CalculateDensity() {
DCHECK_LE(current_y, last_y);
// If the segment length value is invalid, skip this ad density calculation.
- base::Optional<int> segment_length = segment_length_tracker.Length();
+ absl::optional<int> segment_length = segment_length_tracker.Length();
if (!segment_length)
return;
diff --git a/chromium/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.h b/chromium/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.h
index 17c26baf95d..cadd162911f 100644
--- a/chromium/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.h
+++ b/chromium/components/page_load_metrics/browser/observers/ad_metrics/page_ad_density_tracker.h
@@ -8,7 +8,7 @@
#include <set>
#include <unordered_map>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
namespace page_load_metrics {
@@ -92,7 +92,7 @@ class PageAdDensityTracker {
int max_page_ad_density_by_area_ = -1;
int max_page_ad_density_by_height_ = -1;
- base::Optional<gfx::Rect> last_main_frame_size_;
+ absl::optional<gfx::Rect> last_main_frame_size_;
};
} // namespace page_load_metrics
diff --git a/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc b/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc
index 4d3db544762..36f922a4386 100644
--- a/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc
+++ b/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc
@@ -72,6 +72,16 @@ void BackForwardCachePageLoadMetricsObserver::OnRestoreFromBackForwardCache(
in_back_forward_cache_ = false;
back_forward_cache_navigation_ids_.push_back(
navigation_handle->GetNavigationId());
+
+ // HistoryNavigation is a singular event, and we share the same instance as
+ // long as we use the same source ID.
+ ukm::builders::HistoryNavigation builder(
+ GetUkmSourceIdForBackForwardCacheRestore(
+ back_forward_cache_navigation_ids_.size() - 1));
+ bool amp_flag = GetDelegate().GetMainFrameMetadata().behavior_flags &
+ blink::kLoadingBehaviorAmpDocumentLoaded;
+ builder.SetBackForwardCache_IsAmpPage(amp_flag);
+ builder.Record(ukm::UkmRecorder::Get());
}
void BackForwardCachePageLoadMetricsObserver::
@@ -251,23 +261,12 @@ void BackForwardCachePageLoadMetricsObserver::
normalized_cls_data.sliding_windows_duration1000ms_max_cls))
.SetMaxCumulativeShiftScoreAfterBackForwardCacheRestore_SlidingWindow_Duration300ms(
page_load_metrics::LayoutShiftUkmValue(
- normalized_cls_data.sliding_windows_duration300ms_max_cls))
- .SetMaxCumulativeShiftScoreAfterBackForwardCacheRestore_SessionWindowByInputs_Gap1000ms_Max5000ms(
- page_load_metrics::LayoutShiftUkmValue(
- normalized_cls_data
- .session_windows_by_inputs_gap1000ms_max5000ms_max_cls));
+ normalized_cls_data.sliding_windows_duration300ms_max_cls));
base::UmaHistogramCounts100(
"PageLoad.LayoutInstability.MaxCumulativeShiftScore."
"AfterBackForwardCacheRestore.SessionWindow.Gap1000ms.Max5000ms",
page_load_metrics::LayoutShiftUmaValue(
normalized_cls_data.session_windows_gap1000ms_max5000ms_max_cls));
- base::UmaHistogramCounts100(
- "PageLoad.LayoutInstability.MaxCumulativeShiftScore."
- "AfterBackForwardCacheRestore.SessionWindowByInputs.Gap1000ms."
- "Max5000ms",
- page_load_metrics::LayoutShiftUmaValue(
- normalized_cls_data
- .session_windows_by_inputs_gap1000ms_max5000ms_max_cls));
}
builder.Record(ukm::UkmRecorder::Get());
diff --git a/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.h b/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.h
index 33654eb5ba1..bc0287eb7ed 100644
--- a/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.h
+++ b/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.h
@@ -72,8 +72,8 @@ class BackForwardCachePageLoadMetricsObserver
// The layout shift score. These are recorded when the page is navigated away.
// These serve as "deliminators" between back-forward cache navigations.
- base::Optional<double> last_main_frame_layout_shift_score_;
- base::Optional<double> last_layout_shift_score_;
+ absl::optional<double> last_main_frame_layout_shift_score_;
+ absl::optional<double> last_layout_shift_score_;
// IDs for the navigations when the page is restored from the back-forward
// cache.
diff --git a/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer_unittest.cc b/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer_unittest.cc
new file mode 100644
index 00000000000..23a3c035c05
--- /dev/null
+++ b/chromium/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer_unittest.cc
@@ -0,0 +1,101 @@
+// Copyright 2021 The Chromium Authors. 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/browser/observers/back_forward_cache_page_load_metrics_observer.h"
+
+#include "components/page_load_metrics/browser/observers/page_load_metrics_observer_content_test_harness.h"
+#include "components/page_load_metrics/browser/page_load_tracker.h"
+#include "content/public/test/mock_navigation_handle.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/mojom/ukm_interface.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+const char kTestUrl1[] = "https://www.google.com";
+
+class BackForwardCachePageLoadMetricsObserverTest
+ : public page_load_metrics::PageLoadMetricsObserverContentTestHarness {
+ public:
+ void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
+ auto observer = std::make_unique<BackForwardCachePageLoadMetricsObserver>();
+ observer_ = observer.get();
+ tracker->AddObserver(std::move(observer));
+ }
+
+ void SetUp() override {
+ PageLoadMetricsObserverContentTestHarness::SetUp();
+
+ page_load_metrics::InitPageLoadTimingForTest(&timing_);
+
+ // Navigating here so |RegisterObservers| will get called before each test.
+ NavigateAndCommit(GURL(kTestUrl1));
+ }
+
+ void AssertHistoryNavigationRecordedAmpNavigation(bool was_amp) {
+ auto entry_map = tester()->test_ukm_recorder().GetMergedEntriesByName(
+ ukm::builders::HistoryNavigation::kEntryName);
+ ASSERT_EQ(entry_map.size(), 1ull);
+ ukm::mojom::UkmEntry* entry = entry_map.begin()->second.get();
+
+ tester()->test_ukm_recorder().ExpectEntryMetric(
+ entry,
+ ukm::builders::HistoryNavigation::kBackForwardCache_IsAmpPageName,
+ was_amp);
+ }
+
+ static const page_load_metrics::mojom::FrameMetadata& AmpMetadata() {
+ static page_load_metrics::mojom::FrameMetadata metadata;
+ metadata.behavior_flags |=
+ blink::LoadingBehaviorFlag::kLoadingBehaviorAmpDocumentLoaded;
+ return metadata;
+ }
+
+ static const page_load_metrics::mojom::FrameMetadata& NonAmpMetadata() {
+ static page_load_metrics::mojom::FrameMetadata metadata;
+ metadata.behavior_flags &=
+ ~blink::LoadingBehaviorFlag::kLoadingBehaviorAmpDocumentLoaded;
+ return metadata;
+ }
+
+ page_load_metrics::mojom::PageLoadTiming timing_;
+ BackForwardCachePageLoadMetricsObserver* observer_;
+};
+
+TEST_F(BackForwardCachePageLoadMetricsObserverTest,
+ OnRestoreFromBackForwardCache_NonAmpPageHasFalse) {
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_is_served_from_bfcache(true);
+
+ tester()->SimulateMetadataUpdate(NonAmpMetadata(),
+ web_contents()->GetMainFrame());
+ observer_->OnRestoreFromBackForwardCache(timing_, &navigation_handle);
+
+ AssertHistoryNavigationRecordedAmpNavigation(false);
+}
+
+TEST_F(BackForwardCachePageLoadMetricsObserverTest,
+ OnRestoreFromBackForwardCache_AmpPageHasTrue) {
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_is_served_from_bfcache(true);
+
+ tester()->SimulateMetadataUpdate(AmpMetadata(),
+ web_contents()->GetMainFrame());
+ observer_->OnRestoreFromBackForwardCache(timing_, &navigation_handle);
+
+ AssertHistoryNavigationRecordedAmpNavigation(true);
+}
+
+TEST_F(BackForwardCachePageLoadMetricsObserverTest,
+ OnNonBackForwardCacheNavigation_AmpPageIsUndefined) {
+ content::MockNavigationHandle navigation_handle;
+ navigation_handle.set_is_served_from_bfcache(false);
+
+ tester()->SimulateMetadataUpdate(NonAmpMetadata(),
+ web_contents()->GetMainFrame());
+
+ // Since there was no call to observer_->OnRestoreFromBackForwardCache, there
+ // should be no HistoryNavigation UKM entry.
+ auto entry_map = tester()->test_ukm_recorder().GetMergedEntriesByName(
+ ukm::builders::HistoryNavigation::kEntryName);
+ EXPECT_EQ(entry_map.size(), 0ull);
+}
diff --git a/chromium/components/page_load_metrics/browser/observers/core/DIR_METADATA b/chromium/components/page_load_metrics/browser/observers/core/DIR_METADATA
deleted file mode 100644
index 9c0622fe217..00000000000
--- a/chromium/components/page_load_metrics/browser/observers/core/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Speed>Metrics"
-}
diff --git a/chromium/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.cc b/chromium/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.cc
index 68a9eb654b0..4a02d89e99b 100644
--- a/chromium/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.cc
+++ b/chromium/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.cc
@@ -43,7 +43,7 @@ const ContentfulPaintTimingInfo& MergeTimingsBySizeAndTime(
void MergeForSubframesWithAdjustedTime(
ContentfulPaintTimingInfo* inout_timing,
- const base::Optional<base::TimeDelta>& candidate_new_time,
+ const absl::optional<base::TimeDelta>& candidate_new_time,
const uint64_t& candidate_new_size) {
DCHECK(inout_timing);
const ContentfulPaintTimingInfo new_candidate(
@@ -59,19 +59,19 @@ bool IsSubframe(content::RenderFrameHost* subframe_rfh) {
}
void Reset(ContentfulPaintTimingInfo& timing) {
- timing.Reset(base::nullopt, 0u);
+ timing.Reset(absl::nullopt, 0u);
}
} // namespace
ContentfulPaintTimingInfo::ContentfulPaintTimingInfo(LargestContentType type,
bool in_main_frame)
- : time_(base::Optional<base::TimeDelta>()),
+ : time_(absl::optional<base::TimeDelta>()),
size_(0),
type_(type),
in_main_frame_(in_main_frame) {}
ContentfulPaintTimingInfo::ContentfulPaintTimingInfo(
- const base::Optional<base::TimeDelta>& time,
+ const absl::optional<base::TimeDelta>& time,
const uint64_t& size,
const LargestContentType type,
bool in_main_frame)
@@ -109,7 +109,7 @@ void LargestContentfulPaintHandler::SetTestMode(bool enabled) {
}
void ContentfulPaintTimingInfo::Reset(
- const base::Optional<base::TimeDelta>& time,
+ const absl::optional<base::TimeDelta>& time,
const uint64_t& size) {
size_ = size;
time_ = time;
@@ -129,7 +129,7 @@ const ContentfulPaintTimingInfo& ContentfulPaint::MergeTextAndImageTiming()
bool LargestContentfulPaintHandler::AssignTimeAndSizeForLargestContentfulPaint(
const page_load_metrics::mojom::LargestContentfulPaintTiming&
largest_contentful_paint,
- base::Optional<base::TimeDelta>* largest_content_paint_time,
+ absl::optional<base::TimeDelta>* largest_content_paint_time,
uint64_t* largest_content_paint_size,
ContentfulPaintTimingInfo::LargestContentType* largest_content_type) {
// Size being 0 means the paint time is not recorded.
@@ -167,7 +167,7 @@ LargestContentfulPaintHandler::~LargestContentfulPaintHandler() = default;
void LargestContentfulPaintHandler::RecordTiming(
const page_load_metrics::mojom::LargestContentfulPaintTiming&
largest_contentful_paint,
- const base::Optional<base::TimeDelta>&
+ const absl::optional<base::TimeDelta>&
first_input_or_scroll_notified_timestamp,
content::RenderFrameHost* subframe_rfh) {
if (!IsSubframe(subframe_rfh)) {
@@ -206,7 +206,7 @@ LargestContentfulPaintHandler::MergeMainFrameAndSubframes() const {
void LargestContentfulPaintHandler::RecordSubframeTiming(
const page_load_metrics::mojom::LargestContentfulPaintTiming&
largest_contentful_paint,
- const base::Optional<base::TimeDelta>&
+ const absl::optional<base::TimeDelta>&
first_input_or_scroll_notified_timestamp,
const base::TimeDelta& navigation_start_offset) {
UpdateFirstInputOrScrollNotified(first_input_or_scroll_notified_timestamp,
@@ -224,7 +224,7 @@ void LargestContentfulPaintHandler::RecordSubframeTiming(
void LargestContentfulPaintHandler::RecordMainFrameTiming(
const page_load_metrics::mojom::LargestContentfulPaintTiming&
largest_contentful_paint,
- const base::Optional<base::TimeDelta>&
+ const absl::optional<base::TimeDelta>&
first_input_or_scroll_notified_timestamp) {
UpdateFirstInputOrScrollNotified(
first_input_or_scroll_notified_timestamp,
@@ -242,7 +242,7 @@ void LargestContentfulPaintHandler::RecordMainFrameTiming(
}
void LargestContentfulPaintHandler::UpdateFirstInputOrScrollNotified(
- const base::Optional<base::TimeDelta>& candidate_new_time,
+ const absl::optional<base::TimeDelta>& candidate_new_time,
const base::TimeDelta& navigation_start_offset) {
if (!candidate_new_time.has_value())
return;
@@ -298,10 +298,10 @@ void LargestContentfulPaintHandler::OnFrameDeleted(int frame_tree_node_id) {
void LargestContentfulPaintHandler::MergeForSubframes(
ContentfulPaintTimingInfo* inout_timing,
- const base::Optional<base::TimeDelta>& candidate_new_time,
+ const absl::optional<base::TimeDelta>& candidate_new_time,
const uint64_t& candidate_new_size,
base::TimeDelta navigation_start_offset) {
- base::Optional<base::TimeDelta> new_time = base::nullopt;
+ absl::optional<base::TimeDelta> new_time = absl::nullopt;
if (candidate_new_time) {
// If |candidate_new_time| is TimeDelta(), this means that the candidate is
// an image that has not finished loading. Preserve its meaning by not
diff --git a/chromium/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h b/chromium/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h
index 4dac00b738d..58d9ff29764 100644
--- a/chromium/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h
+++ b/chromium/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h
@@ -33,13 +33,13 @@ class ContentfulPaintTimingInfo {
explicit ContentfulPaintTimingInfo(LargestContentType largest_content_type,
bool in_main_frame);
explicit ContentfulPaintTimingInfo(
- const base::Optional<base::TimeDelta>&,
+ const absl::optional<base::TimeDelta>&,
const uint64_t& size,
const LargestContentType largest_content_type,
bool in_main_frame);
explicit ContentfulPaintTimingInfo(const ContentfulPaintTimingInfo& other);
- void Reset(const base::Optional<base::TimeDelta>&, const uint64_t& size);
- base::Optional<base::TimeDelta> Time() const { return time_; }
+ void Reset(const absl::optional<base::TimeDelta>&, const uint64_t& size);
+ absl::optional<base::TimeDelta> Time() const { return time_; }
bool InMainFrame() const { return in_main_frame_; }
uint64_t Size() const { return size_; }
LargestContentType Type() const { return type_; }
@@ -62,7 +62,7 @@ class ContentfulPaintTimingInfo {
private:
ContentfulPaintTimingInfo() = delete;
std::string TypeInString() const;
- base::Optional<base::TimeDelta> time_;
+ absl::optional<base::TimeDelta> time_;
uint64_t size_;
LargestContentType type_;
bool in_main_frame_;
@@ -93,14 +93,14 @@ class LargestContentfulPaintHandler {
static bool AssignTimeAndSizeForLargestContentfulPaint(
const page_load_metrics::mojom::LargestContentfulPaintTiming&
largest_contentful_paint,
- base::Optional<base::TimeDelta>* largest_content_paint_time,
+ absl::optional<base::TimeDelta>* largest_content_paint_time,
uint64_t* largest_content_paint_size,
ContentfulPaintTimingInfo::LargestContentType* largest_content_type);
void RecordTiming(
const page_load_metrics::mojom::LargestContentfulPaintTiming&
largest_contentful_paint,
- const base::Optional<base::TimeDelta>&
+ const absl::optional<base::TimeDelta>&
first_input_or_scroll_notified_timestamp,
content::RenderFrameHost* subframe_rfh);
inline void RecordMainFrameTreeNodeId(int main_frame_tree_node_id) {
@@ -138,23 +138,23 @@ class LargestContentfulPaintHandler {
void RecordSubframeTiming(
const page_load_metrics::mojom::LargestContentfulPaintTiming&
largest_contentful_paint,
- const base::Optional<base::TimeDelta>&
+ const absl::optional<base::TimeDelta>&
first_input_or_scroll_notified_timestamp,
const base::TimeDelta& navigation_start_offset);
void RecordMainFrameTiming(
const page_load_metrics::mojom::LargestContentfulPaintTiming&
largest_contentful_paint,
- const base::Optional<base::TimeDelta>&
+ const absl::optional<base::TimeDelta>&
first_input_or_scroll_notified_timestamp);
void UpdateFirstInputOrScrollNotified(
- const base::Optional<base::TimeDelta>& candidate_new_time,
+ const absl::optional<base::TimeDelta>& candidate_new_time,
const base::TimeDelta& navigation_start_offset);
void MergeForSubframes(
ContentfulPaintTimingInfo* inout_timing,
- const base::Optional<base::TimeDelta>& candidate_new_time,
+ const absl::optional<base::TimeDelta>& candidate_new_time,
const uint64_t& candidate_new_size,
base::TimeDelta navigation_start_offset);
- bool IsValid(const base::Optional<base::TimeDelta>& time) {
+ bool IsValid(const absl::optional<base::TimeDelta>& time) {
// When |time| is not present, this means that there is no current
// candidate. If |time| is 0, it corresponds to an image that has not
// finished loading. In both cases, we do not know the timestamp at which
@@ -169,7 +169,7 @@ class LargestContentfulPaintHandler {
// Used for Telemetry to distinguish the LCP events from different
// navigations.
- base::Optional<int> main_frame_tree_node_id_;
+ absl::optional<int> main_frame_tree_node_id_;
// The first input or scroll across all frames in the page. Used to filter out
// paints that occur on other frames but after this time.
diff --git a/chromium/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc b/chromium/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc
index 80ce3c4fc52..bfbd3cfd68f 100644
--- a/chromium/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc
+++ b/chromium/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.cc
@@ -14,6 +14,7 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
+#include "base/trace_event/trace_event.h"
#include "build/chromeos_buildflags.h"
#include "components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h"
#include "components/page_load_metrics/browser/page_load_metrics_memory_tracker.h"
@@ -1152,7 +1153,7 @@ void UmaPageLoadMetricsObserver::RecordTimingHistograms(
void UmaPageLoadMetricsObserver::RecordForegroundDurationHistograms(
const page_load_metrics::mojom::PageLoadTiming& timing,
base::TimeTicks app_background_time) {
- base::Optional<base::TimeDelta> foreground_duration =
+ absl::optional<base::TimeDelta> foreground_duration =
page_load_metrics::GetInitialForegroundDuration(GetDelegate(),
app_background_time);
if (!foreground_duration)
diff --git a/chromium/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer_unittest.cc b/chromium/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer_unittest.cc
index 4da2644eeba..b9c57733fb3 100644
--- a/chromium/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer_unittest.cc
+++ b/chromium/components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include "base/test/metrics/histogram_tester.h"
-#include "base/test/power_monitor_test_base.h"
+#include "base/test/power_monitor_test.h"
#include "base/test/scoped_feature_list.h"
#include "components/page_load_metrics/browser/metrics_web_contents_observer.h"
#include "components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h"
diff --git a/chromium/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.cc b/chromium/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.cc
index bfb9c40ea8b..75b477fc718 100644
--- a/chromium/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.cc
+++ b/chromium/components/page_load_metrics/browser/observers/layout_page_load_metrics_observer.cc
@@ -15,6 +15,13 @@ void Record(const PageRenderData& data) {
base::UmaHistogramPercentageObsoleteDoNotUse(
"Blink.Layout.NGRatio.Blocks",
data.ng_layout_block_count * 100 / data.all_layout_block_count);
+
+ base::UmaHistogramPercentage(
+ "Blink.Layout.NGRatio.FlexboxBlocks",
+ data.flexbox_ng_layout_block_count * 100 / data.all_layout_block_count);
+ base::UmaHistogramPercentage(
+ "Blink.Layout.NGRatio.GridBlocks",
+ data.grid_ng_layout_block_count * 100 / data.all_layout_block_count);
}
if (data.all_layout_call_count) {
base::UmaHistogramPercentageObsoleteDoNotUse(
diff --git a/chromium/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.cc b/chromium/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.cc
index dd82dadb30f..5c11fcb377f 100644
--- a/chromium/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.cc
+++ b/chromium/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.cc
@@ -57,7 +57,7 @@ class TestPageLoadMetricsEmbedderInterface
return std::move(timer);
}
- bool IsPrerender(content::WebContents* web_contents) override {
+ bool IsNoStatePrefetch(content::WebContents* web_contents) override {
return false;
}
@@ -123,7 +123,7 @@ void PageLoadMetricsObserverTester::SimulateTimingUpdate(
const mojom::PageLoadTiming& timing,
content::RenderFrameHost* rfh) {
SimulatePageLoadTimingUpdate(
- timing, mojom::FrameMetadata(), mojom::PageLoadFeatures(),
+ timing, mojom::FrameMetadata(), /* new_features= */ {},
mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
mojom::DeferredResourceCounts(), mojom::InputTiming(),
blink::MobileFriendliness(), rfh);
@@ -140,7 +140,7 @@ void PageLoadMetricsObserverTester::SimulateCpuTimingUpdate(
auto timing = page_load_metrics::mojom::PageLoadTimingPtr(base::in_place);
page_load_metrics::InitPageLoadTimingForTest(timing.get());
SimulatePageLoadTimingUpdate(
- *timing, mojom::FrameMetadata(), mojom::PageLoadFeatures(),
+ *timing, mojom::FrameMetadata(), /* new_features= */ {},
mojom::FrameRenderDataUpdate(), cpu_timing,
mojom::DeferredResourceCounts(), mojom::InputTiming(),
blink::MobileFriendliness(), rfh);
@@ -157,7 +157,7 @@ void PageLoadMetricsObserverTester::SimulateInputTimingUpdate(
auto timing = page_load_metrics::mojom::PageLoadTimingPtr(base::in_place);
page_load_metrics::InitPageLoadTimingForTest(timing.get());
SimulatePageLoadTimingUpdate(
- *timing, mojom::FrameMetadata(), mojom::PageLoadFeatures(),
+ *timing, mojom::FrameMetadata(), /* new_features= */ {},
mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
mojom::DeferredResourceCounts(), input_timing,
blink::MobileFriendliness(), rfh);
@@ -167,9 +167,8 @@ void PageLoadMetricsObserverTester::SimulateTimingAndMetadataUpdate(
const mojom::PageLoadTiming& timing,
const mojom::FrameMetadata& metadata) {
SimulatePageLoadTimingUpdate(
- timing, metadata, mojom::PageLoadFeatures(),
- mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
- mojom::DeferredResourceCounts(), mojom::InputTiming(),
+ timing, metadata, /* new_features= */ {}, mojom::FrameRenderDataUpdate(),
+ mojom::CpuTiming(), mojom::DeferredResourceCounts(), mojom::InputTiming(),
blink::MobileFriendliness(), web_contents()->GetMainFrame());
}
@@ -179,14 +178,13 @@ void PageLoadMetricsObserverTester::SimulateMetadataUpdate(
mojom::PageLoadTiming timing;
InitPageLoadTimingForTest(&timing);
SimulatePageLoadTimingUpdate(
- timing, metadata, mojom::PageLoadFeatures(),
- mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
- mojom::DeferredResourceCounts(), mojom::InputTiming(),
+ timing, metadata, /* new_features= */ {}, mojom::FrameRenderDataUpdate(),
+ mojom::CpuTiming(), mojom::DeferredResourceCounts(), mojom::InputTiming(),
blink::MobileFriendliness(), rfh);
}
void PageLoadMetricsObserverTester::SimulateFeaturesUpdate(
- const mojom::PageLoadFeatures& new_features) {
+ const std::vector<blink::UseCounterFeature>& new_features) {
SimulatePageLoadTimingUpdate(
mojom::PageLoadTiming(), mojom::FrameMetadata(), new_features,
mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
@@ -205,7 +203,7 @@ void PageLoadMetricsObserverTester::SimulateRenderDataUpdate(
mojom::PageLoadTiming timing;
InitPageLoadTimingForTest(&timing);
SimulatePageLoadTimingUpdate(
- timing, mojom::FrameMetadata(), mojom::PageLoadFeatures(), render_data,
+ timing, mojom::FrameMetadata(), /* new_features= */ {}, render_data,
mojom::CpuTiming(), mojom::DeferredResourceCounts(), mojom::InputTiming(),
blink::MobileFriendliness(), rfh);
}
@@ -213,7 +211,7 @@ void PageLoadMetricsObserverTester::SimulateRenderDataUpdate(
void PageLoadMetricsObserverTester::SimulatePageLoadTimingUpdate(
const mojom::PageLoadTiming& timing,
const mojom::FrameMetadata& metadata,
- const mojom::PageLoadFeatures& new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
const mojom::FrameRenderDataUpdate& render_data,
const mojom::CpuTiming& cpu_timing,
const mojom::DeferredResourceCounts& new_deferred_resource_data,
@@ -221,7 +219,7 @@ void PageLoadMetricsObserverTester::SimulatePageLoadTimingUpdate(
const blink::MobileFriendliness& mobile_friendliness,
content::RenderFrameHost* rfh) {
metrics_web_contents_observer_->OnTimingUpdated(
- rfh, timing.Clone(), metadata.Clone(), new_features.Clone(),
+ rfh, timing.Clone(), metadata.Clone(), new_features,
std::vector<mojom::ResourceDataUpdatePtr>(), render_data.Clone(),
cpu_timing.Clone(), new_deferred_resource_data.Clone(),
input_timing.Clone(), mobile_friendliness);
@@ -246,7 +244,7 @@ void PageLoadMetricsObserverTester::SimulateResourceDataUseUpdate(
metrics_web_contents_observer_->OnTimingUpdated(
render_frame_host, std::move(timing),
mojom::FrameMetadataPtr(base::in_place),
- mojom::PageLoadFeaturesPtr(base::in_place), resources,
+ std::vector<blink::UseCounterFeature>(), resources,
mojom::FrameRenderDataUpdatePtr(base::in_place),
mojom::CpuTimingPtr(base::in_place),
mojom::DeferredResourceCountsPtr(base::in_place),
@@ -328,9 +326,9 @@ void PageLoadMetricsObserverTester::SimulateStorageAccess(
void PageLoadMetricsObserverTester::SimulateMobileFriendlinessUpdate(
blink::MobileFriendliness& mobile_friendliness) {
SimulatePageLoadTimingUpdate(
- mojom::PageLoadTiming(), mojom::FrameMetadata(),
- mojom::PageLoadFeatures(), mojom::FrameRenderDataUpdate(),
- mojom::CpuTiming(), mojom::DeferredResourceCounts(), mojom::InputTiming(),
+ mojom::PageLoadTiming(), mojom::FrameMetadata(), /* new_features= */ {},
+ mojom::FrameRenderDataUpdate(), mojom::CpuTiming(),
+ mojom::DeferredResourceCounts(), mojom::InputTiming(),
mobile_friendliness, web_contents()->GetMainFrame());
}
diff --git a/chromium/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.h b/chromium/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.h
index 8491d696da2..ef077762ef7 100644
--- a/chromium/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.h
+++ b/chromium/components/page_load_metrics/browser/observers/page_load_metrics_observer_tester.h
@@ -36,7 +36,6 @@ struct GlobalRequestID;
namespace mojom {
class FrameRenderDataUpdate;
-class PageLoadFeatures;
class FrameMetadata;
class PageLoadTiming;
} // namespace mojom
@@ -99,7 +98,8 @@ class PageLoadMetricsObserverTester : public test::WeakMockTimerProvider {
const mojom::FrameMetadata& metadata);
void SimulateMetadataUpdate(const mojom::FrameMetadata& metadata,
content::RenderFrameHost* rfh);
- void SimulateFeaturesUpdate(const mojom::PageLoadFeatures& new_features);
+ void SimulateFeaturesUpdate(
+ const std::vector<blink::UseCounterFeature>& new_features);
void SimulateResourceDataUseUpdate(
const std::vector<mojom::ResourceDataUpdatePtr>& resources);
void SimulateResourceDataUseUpdate(
@@ -164,7 +164,7 @@ class PageLoadMetricsObserverTester : public test::WeakMockTimerProvider {
void SimulatePageLoadTimingUpdate(
const mojom::PageLoadTiming& timing,
const mojom::FrameMetadata& metadata,
- const mojom::PageLoadFeatures& new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
const mojom::FrameRenderDataUpdate& render_data,
const mojom::CpuTiming& cpu_timing,
const mojom::DeferredResourceCounts& new_deferred_resource_data,
diff --git a/chromium/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc b/chromium/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc
index b92e75d044d..ad1c2074344 100644
--- a/chromium/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc
+++ b/chromium/components/page_load_metrics/browser/observers/prerender_page_load_metrics_observer.cc
@@ -71,9 +71,6 @@ void PrerenderPageLoadMetricsObserver::OnStorageAccessed(
void PrerenderPageLoadMetricsObserver::RecordFeatureUse(
blink::mojom::WebFeature feature) {
- page_load_metrics::mojom::PageLoadFeatures page_load_features;
- page_load_features.features.push_back(feature);
-
page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage(
- GetDelegate().GetWebContents()->GetMainFrame(), page_load_features);
+ GetDelegate().GetWebContents()->GetMainFrame(), feature);
}
diff --git a/chromium/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc b/chromium/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
index dae50e6d914..ad50fb01df5 100644
--- a/chromium/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
+++ b/chromium/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
@@ -46,6 +46,7 @@ UseCounterPageLoadMetricsObserver::GetAllowedUkmFeatures() {
WebFeature::kXMLHttpRequestSynchronousInWorker,
WebFeature::kPaymentHandler,
WebFeature::kPaymentRequestShowWithoutGesture,
+ WebFeature::kPaymentRequestShowWithoutGestureOrToken,
WebFeature::kCredentialManagerCreatePublicKeyCredential,
WebFeature::kCredentialManagerGetPublicKeyCredential,
WebFeature::kCredentialManagerMakePublicKeyCredentialSuccess,
@@ -195,9 +196,19 @@ UseCounterPageLoadMetricsObserver::GetAllowedUkmFeatures() {
WebFeature::kGetCurrentBrowsingContextMedia,
WebFeature::kLaxAllowingUnsafeCookies,
WebFeature::kOpenWebDatabaseThirdPartyContext,
+ WebFeature::kOversrollBehaviorOnViewportBreaks,
WebFeature::kPaymentRequestCSPViolation,
+ WebFeature::kRequestedFileSystemPersistentThirdPartyContext,
+ WebFeature::kPrefixedStorageInfoThirdPartyContext,
WebFeature::
kCrossBrowsingContextGroupMainFrameNulledNonEmptyNameAccessed,
+ WebFeature::kUsbDeviceOpen,
+ WebFeature::kWebBluetoothRemoteServerConnect,
+ WebFeature::kSerialRequestPort,
+ WebFeature::kSerialPortOpen,
+ WebFeature::kHidRequestDevice,
+ WebFeature::kHidDeviceOpen,
+ WebFeature::kCrossOriginWasmModuleSharing,
}));
return *opt_in_features;
}
diff --git a/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc b/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc
index 521a6a1218e..70a7f855b9a 100644
--- a/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc
+++ b/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc
@@ -8,38 +8,16 @@
#include "base/rand_util.h"
#include "content/public/browser/render_frame_host.h"
#include "services/metrics/public/cpp/ukm_builders.h"
+#include "third_party/blink/public/mojom/use_counter/use_counter_feature.mojom.h"
-using Features = page_load_metrics::mojom::PageLoadFeatures;
+using FeatureType = blink::mojom::UseCounterFeatureType;
using UkmFeatureList = UseCounterPageLoadMetricsObserver::UkmFeatureList;
using WebFeature = blink::mojom::WebFeature;
-using WebFeatureBitSet =
- std::bitset<static_cast<size_t>(WebFeature::kNumberOfFeatures)>;
-
using CSSSampleId = blink::mojom::CSSSampleId;
+using PermissionsPolicyFeature = blink::mojom::PermissionsPolicyFeature;
namespace {
-void RecordUkmFeatures(const UkmFeatureList& features,
- const WebFeatureBitSet& features_recorded,
- const WebFeatureBitSet& main_frame_features_recorded,
- std::set<size_t>* ukm_features_recorded,
- ukm::SourceId source_id) {
- for (auto feature : features) {
- if (!features_recorded.test(static_cast<size_t>(feature)))
- continue;
- if (ukm_features_recorded->find(static_cast<size_t>(feature)) !=
- ukm_features_recorded->end()) {
- continue;
- }
- ukm::builders::Blink_UseCounter(source_id)
- .SetFeature(static_cast<size_t>(feature))
- .SetIsMainFrameFeature(
- main_frame_features_recorded.test(static_cast<size_t>(feature)))
- .Record(ukm::UkmRecorder::Get());
- ukm_features_recorded->insert(static_cast<size_t>(feature));
- }
-}
-
// It's always recommended to use the deprecation API in blink. If the feature
// was logged from the browser (or from both blink and the browser) where the
// deprecation API is not available, use this method for the console warning.
@@ -69,21 +47,12 @@ void PossiblyWarnFeatureDeprecation(content::RenderFrameHost* rfh,
}
}
-void RecordMainFrameFeature(blink::mojom::WebFeature feature) {
- UMA_HISTOGRAM_ENUMERATION(internal::kFeaturesHistogramMainFrameName, feature);
-}
-
-void RecordFeature(blink::mojom::WebFeature feature) {
- UMA_HISTOGRAM_ENUMERATION(internal::kFeaturesHistogramName, feature);
-}
-
-void RecordCssProperty(CSSSampleId property) {
- UMA_HISTOGRAM_ENUMERATION(internal::kCssPropertiesHistogramName, property);
-}
-
-void RecordAnimatedCssProperty(CSSSampleId animated_property) {
- UMA_HISTOGRAM_ENUMERATION(internal::kAnimatedCssPropertiesHistogramName,
- animated_property);
+template <size_t N>
+bool TestAndSet(std::bitset<N>& bitset,
+ blink::UseCounterFeature::EnumValue value) {
+ bool has_record = bitset.test(value);
+ bitset.set(value);
+ return has_record;
}
} // namespace
@@ -99,133 +68,65 @@ UseCounterPageLoadMetricsObserver::OnCommit(
content::NavigationHandle* navigation_handle,
ukm::SourceId source_id) {
// Verify that no feature usage is observed before commit
- DCHECK_LE(features_recorded_.count(), 0ul);
- DCHECK_LE(main_frame_features_recorded_.count(), 0ul);
+ DCHECK_EQ(features_recorded_.count(), 0ul);
+ DCHECK_EQ(main_frame_features_recorded_.count(), 0ul);
+ DCHECK_EQ(ukm_features_recorded_.count(), 0ul);
+ DCHECK_EQ(css_properties_recorded_.count(), 0ul);
+ DCHECK_EQ(animated_css_properties_recorded_.count(), 0ul);
+ DCHECK_EQ(violated_permissions_policy_features_recorded_.count(), 0ul);
+
+ content::RenderFrameHost* rfh = navigation_handle->GetRenderFrameHost();
+
+ auto web_feature_page_visit =
+ static_cast<blink::UseCounterFeature::EnumValue>(WebFeature::kPageVisits);
ukm::builders::Blink_UseCounter(source_id)
- .SetFeature(static_cast<size_t>(WebFeature::kPageVisits))
+ .SetFeature(web_feature_page_visit)
.SetIsMainFrameFeature(1)
.Record(ukm::UkmRecorder::Get());
- ukm_features_recorded_.insert(static_cast<size_t>(WebFeature::kPageVisits));
- RecordFeature(WebFeature::kPageVisits);
- RecordMainFrameFeature(WebFeature::kPageVisits);
- RecordCssProperty(CSSSampleId::kTotalPagesMeasured);
- RecordAnimatedCssProperty(CSSSampleId::kTotalPagesMeasured);
- features_recorded_.set(static_cast<size_t>(WebFeature::kPageVisits));
- main_frame_features_recorded_.set(
- static_cast<size_t>(WebFeature::kPageVisits));
+ ukm_features_recorded_.set(web_feature_page_visit);
+
+ RecordMainFrameWebFeature(rfh, WebFeature::kPageVisits);
+ RecordUseCounterFeature(rfh,
+ {FeatureType::kWebFeature, web_feature_page_visit});
+
+ auto css_total_pages_measured =
+ static_cast<blink::UseCounterFeature::EnumValue>(
+ CSSSampleId::kTotalPagesMeasured);
+ RecordUseCounterFeature(
+ rfh, {FeatureType::kCssProperty, css_total_pages_measured});
+ RecordUseCounterFeature(
+ rfh, {FeatureType::kAnimatedCssProperty, css_total_pages_measured});
+
return CONTINUE_OBSERVING;
}
void UseCounterPageLoadMetricsObserver::OnFeaturesUsageObserved(
content::RenderFrameHost* rfh,
- const Features& features) {
- for (WebFeature feature : features.features) {
- // Verify that kPageVisits is observed at most once per observer.
- if (feature == WebFeature::kPageVisits) {
- mojo::ReportBadMessage(
- "kPageVisits should not be passed to "
- "PageLoadMetricsObserver::OnFeaturesUsageObserved");
- return;
+ const std::vector<blink::UseCounterFeature>& features) {
+ for (const blink::UseCounterFeature& feature : features) {
+ if (feature.type() == FeatureType::kWebFeature) {
+ RecordMainFrameWebFeature(rfh, static_cast<WebFeature>(feature.value()));
}
-
- // Record feature usage in main frame.
- // If a feature is already recorded in the main frame, it is also recorded
- // on the page.
- if (main_frame_features_recorded_.test(static_cast<size_t>(feature)))
- continue;
- if (rfh->GetParent() == nullptr) {
- RecordMainFrameFeature(feature);
- main_frame_features_recorded_.set(static_cast<size_t>(feature));
- }
-
- if (features_recorded_.test(static_cast<size_t>(feature)))
- continue;
- PossiblyWarnFeatureDeprecation(rfh, feature);
- RecordFeature(feature);
- features_recorded_.set(static_cast<size_t>(feature));
- }
-
- for (CSSSampleId css_property : features.css_properties) {
- // Verify that page visit is observed at most once per observer.
- if (css_property == CSSSampleId::kTotalPagesMeasured) {
- mojo::ReportBadMessage(
- "CSSSampleId::kTotalPagesMeasured should not be passed to "
- "PageLoadMetricsObserver::OnFeaturesUsageObserved");
- return;
- }
- if (css_property > CSSSampleId::kMaxValue) {
- mojo::ReportBadMessage(
- "Invalid CSS property passed to "
- "PageLoadMetricsObserver::OnFeaturesUsageObserved");
- return;
- }
- // Same as above, the usage of each CSS property should be only measured
- // once.
- if (css_properties_recorded_.test(static_cast<size_t>(css_property)))
- continue;
- // There are about 600 enums, so the memory required for a vector histogram
- // is about 600 * 8 byes = 5KB
- // 50% of the time there are about 100 CSS properties recorded per page
- // load. Storage in sparce histogram entries are 48 bytes instead of 8
- // bytes so the memory required for a sparse histogram is about
- // 100 * 48 bytes = 5KB. On top there will be std::map overhead and the
- // acquire/release of a base::Lock to protect the map during each update.
- // Overal it is still better to use a vector histogram here since it is
- // faster to access and merge and uses about same amount of memory.
- RecordCssProperty(css_property);
- css_properties_recorded_.set(static_cast<size_t>(css_property));
- }
-
- for (CSSSampleId animated_css_property : features.animated_css_properties) {
- // Verify that page visit is observed at most once per observer.
- if (animated_css_property ==
- blink::mojom::CSSSampleId::kTotalPagesMeasured) {
- mojo::ReportBadMessage(
- "CSSSampleId::kTotalPagesMeasured should not be passed to "
- "PageLoadMetricsObserver::OnFeaturesUsageObserved");
- return;
- }
- if (animated_css_property > blink::mojom::CSSSampleId::kMaxValue) {
- mojo::ReportBadMessage(
- "Invalid animated CSS property passed to "
- "PageLoadMetricsObserver::OnFeaturesUsageObserved");
- return;
- }
- // Same as above, the usage of each animated CSS property should be only
- // measured once.
- if (animated_css_properties_recorded_.test(
- static_cast<size_t>(animated_css_property)))
- continue;
- // See comments above (in the css property section) for reasoning of using
- // a vector histogram here instead of a sparse histogram.
- RecordAnimatedCssProperty(animated_css_property);
- animated_css_properties_recorded_.set(
- static_cast<size_t>(animated_css_property));
+ RecordUseCounterFeature(rfh, feature);
}
}
void UseCounterPageLoadMetricsObserver::OnComplete(
const page_load_metrics::mojom::PageLoadTiming& timing) {
- RecordUkmFeatures(GetAllowedUkmFeatures(), features_recorded_,
- main_frame_features_recorded_, &ukm_features_recorded_,
- GetDelegate().GetPageUkmSourceId());
+ RecordUkmFeatures();
}
void UseCounterPageLoadMetricsObserver::OnFailedProvisionalLoad(
const page_load_metrics::FailedProvisionalLoadInfo&
failed_provisional_load_info) {
- RecordUkmFeatures(GetAllowedUkmFeatures(), features_recorded_,
- main_frame_features_recorded_, &ukm_features_recorded_,
- GetDelegate().GetPageUkmSourceId());
+ RecordUkmFeatures();
}
page_load_metrics::PageLoadMetricsObserver::ObservePolicy
UseCounterPageLoadMetricsObserver::FlushMetricsOnAppEnterBackground(
const page_load_metrics::mojom::PageLoadTiming& timing) {
- RecordUkmFeatures(GetAllowedUkmFeatures(), features_recorded_,
- main_frame_features_recorded_, &ukm_features_recorded_,
- GetDelegate().GetPageUkmSourceId());
+ RecordUkmFeatures();
return CONTINUE_OBSERVING;
}
@@ -244,3 +145,86 @@ UseCounterPageLoadMetricsObserver::OnEnterBackForwardCache(
const page_load_metrics::mojom::PageLoadTiming& timing) {
return CONTINUE_OBSERVING;
}
+
+void UseCounterPageLoadMetricsObserver::RecordUseCounterFeature(
+ content::RenderFrameHost* rfh,
+ const blink::UseCounterFeature& feature) {
+ // Note: UMA_HISTOGRAM_ENUMERATION does accept a 3rd parameter as value bound,
+ // when the second parameter is a general integer type, but it requires the
+ // 3rd parameter to be constexpr in order to pass an internal static check.
+ // Writing something like
+ // UMA_HISTOGRAM_ENUMERATION(histogram_name, feature.value(),
+ // feature.max_value());
+ // will cause compile error.
+ switch (feature.type()) {
+ case FeatureType::kWebFeature: {
+ auto web_feature = static_cast<WebFeature>(feature.value());
+ if (TestAndSet(features_recorded_, feature.value()))
+ return;
+ UMA_HISTOGRAM_ENUMERATION(internal::kFeaturesHistogramName, web_feature);
+ PossiblyWarnFeatureDeprecation(rfh, web_feature);
+ break;
+ }
+ // There are about 600 enums, so the memory required for a vector
+ // histogram is about 600 * 8 byes = 5KB 50% of the time there are about
+ // 100 CSS properties recorded per page load. Storage in sparce
+ // histogram entries are 48 bytes instead of 8 bytes so the memory
+ // required for a sparse histogram is about 100 * 48 bytes = 5KB. On top
+ // there will be std::map overhead and the acquire/release of a
+ // base::Lock to protect the map during each update. Overal it is still
+ // better to use a vector histogram here since it is faster to access
+ // and merge and uses about same amount of memory.
+ case FeatureType::kCssProperty:
+ if (TestAndSet(css_properties_recorded_, feature.value()))
+ return;
+ UMA_HISTOGRAM_ENUMERATION(internal::kCssPropertiesHistogramName,
+ static_cast<CSSSampleId>(feature.value()));
+ break;
+ case FeatureType::kAnimatedCssProperty:
+ if (TestAndSet(animated_css_properties_recorded_, feature.value()))
+ return;
+ UMA_HISTOGRAM_ENUMERATION(internal::kAnimatedCssPropertiesHistogramName,
+ static_cast<CSSSampleId>(feature.value()));
+ break;
+
+ case FeatureType::kPermissionsPolicyViolationEnforce:
+ if (TestAndSet(violated_permissions_policy_features_recorded_,
+ feature.value()))
+ return;
+ UMA_HISTOGRAM_ENUMERATION(
+ internal::kPermissionsPolicyViolationHistogramName,
+ static_cast<PermissionsPolicyFeature>(feature.value()));
+ }
+}
+
+void UseCounterPageLoadMetricsObserver::RecordMainFrameWebFeature(
+ content::RenderFrameHost* rfh,
+ blink::mojom::WebFeature web_feature) {
+ if (rfh->GetParent() != nullptr)
+ return;
+
+ if (TestAndSet(main_frame_features_recorded_,
+ static_cast<size_t>(web_feature))) {
+ return;
+ }
+ UMA_HISTOGRAM_ENUMERATION(internal::kFeaturesHistogramMainFrameName,
+ web_feature);
+}
+
+void UseCounterPageLoadMetricsObserver::RecordUkmFeatures() {
+ for (WebFeature web_feature : GetAllowedUkmFeatures()) {
+ auto feature_enum_value =
+ static_cast<blink::UseCounterFeature::EnumValue>(web_feature);
+ if (!features_recorded_.test(feature_enum_value))
+ continue;
+
+ if (TestAndSet(ukm_features_recorded_, feature_enum_value))
+ continue;
+
+ ukm::builders::Blink_UseCounter(GetDelegate().GetPageUkmSourceId())
+ .SetFeature(feature_enum_value)
+ .SetIsMainFrameFeature(
+ main_frame_features_recorded_.test(feature_enum_value))
+ .Record(ukm::UkmRecorder::Get());
+ }
+}
diff --git a/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.h b/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.h
index 4998a5af15f..4b5430280df 100644
--- a/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.h
+++ b/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.h
@@ -9,7 +9,9 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "components/page_load_metrics/browser/page_load_metrics_observer.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom.h"
#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom.h"
+#include "third_party/blink/public/mojom/use_counter/use_counter_feature.mojom-forward.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
namespace internal {
@@ -20,6 +22,8 @@ const char kFeaturesHistogramMainFrameName[] =
const char kCssPropertiesHistogramName[] = "Blink.UseCounter.CSSProperties";
const char kAnimatedCssPropertiesHistogramName[] =
"Blink.UseCounter.AnimatedCSSProperties";
+const char kPermissionsPolicyViolationHistogramName[] =
+ "Blink.UseCounter.PermissionsPolicy.Violation.Enforce";
} // namespace internal
@@ -34,7 +38,7 @@ class UseCounterPageLoadMetricsObserver
ukm::SourceId source_id) override;
void OnFeaturesUsageObserved(
content::RenderFrameHost* rfh,
- const page_load_metrics::mojom::PageLoadFeatures&) override;
+ const std::vector<blink::UseCounterFeature>&) override;
void OnComplete(
const page_load_metrics::mojom::PageLoadTiming& timing) override;
void OnFailedProvisionalLoad(
@@ -53,6 +57,20 @@ class UseCounterPageLoadMetricsObserver
// Returns a list of opt-in UKM features for use counter.
static const UkmFeatureList& GetAllowedUkmFeatures();
+ // Records an `UseCounterFeature` through UMA_HISTOGRAM_ENUMERATION if
+ // the feature has not been recorded before.
+ void RecordUseCounterFeature(content::RenderFrameHost*,
+ const blink::UseCounterFeature&);
+
+ // Records a WebFeature in main frame if `rfh` is a main frame and the feature
+ // has not been recorded before.
+ void RecordMainFrameWebFeature(content::RenderFrameHost*,
+ blink::mojom::WebFeature);
+
+ // Records UKM subset of WebFeatures, if the WebFeature is observed in the
+ // page.
+ void RecordUkmFeatures();
+
// To keep tracks of which features have been measured.
std::bitset<static_cast<size_t>(blink::mojom::WebFeature::kNumberOfFeatures)>
features_recorded_;
@@ -62,7 +80,12 @@ class UseCounterPageLoadMetricsObserver
css_properties_recorded_;
std::bitset<static_cast<size_t>(blink::mojom::CSSSampleId::kMaxValue) + 1>
animated_css_properties_recorded_;
- std::set<size_t> ukm_features_recorded_;
+ std::bitset<static_cast<size_t>(blink::mojom::WebFeature::kNumberOfFeatures)>
+ ukm_features_recorded_;
+ std::bitset<static_cast<size_t>(
+ blink::mojom::PermissionsPolicyFeature::kMaxValue) +
+ 1>
+ violated_permissions_policy_features_recorded_;
DISALLOW_COPY_AND_ASSIGN(UseCounterPageLoadMetricsObserver);
};
diff --git a/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer_unittest.cc b/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer_unittest.cc
index fb5bda54aaa..6991ad9cfba 100644
--- a/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer_unittest.cc
+++ b/chromium/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer_unittest.cc
@@ -20,6 +20,21 @@ namespace {
const char kTestUrl[] = "https://www.google.com";
using WebFeature = blink::mojom::WebFeature;
using CSSSampleId = blink::mojom::CSSSampleId;
+using FeatureType = blink::mojom::UseCounterFeatureType;
+
+const char* GetUseCounterHistogramName(
+ blink::mojom::UseCounterFeatureType feature_type) {
+ switch (feature_type) {
+ case FeatureType::kWebFeature:
+ return internal::kFeaturesHistogramName;
+ case FeatureType::kCssProperty:
+ return internal::kCssPropertiesHistogramName;
+ case FeatureType::kAnimatedCssProperty:
+ return internal::kAnimatedCssPropertiesHistogramName;
+ case FeatureType::kPermissionsPolicyViolationEnforce:
+ return internal::kPermissionsPolicyViolationHistogramName;
+ }
+}
} // namespace
@@ -28,11 +43,24 @@ class UseCounterPageLoadMetricsObserverTest
public:
UseCounterPageLoadMetricsObserverTest() {}
+ void ExpectBucketCount(const blink::UseCounterFeature& feature,
+ size_t count) {
+ if (feature.type() == blink::mojom::UseCounterFeatureType::kWebFeature) {
+ tester()->histogram_tester().ExpectBucketCount(
+ internal::kFeaturesHistogramMainFrameName,
+ static_cast<base::Histogram::Sample>(feature.value()), count);
+ }
+
+ tester()->histogram_tester().ExpectBucketCount(
+ GetUseCounterHistogramName(feature.type()),
+ static_cast<base::Histogram::Sample>(feature.value()), count);
+ }
+
void HistogramBasicTest(
- const page_load_metrics::mojom::PageLoadFeatures& first_features,
- const page_load_metrics::mojom::PageLoadFeatures& second_features =
- page_load_metrics::mojom::PageLoadFeatures()) {
+ const std::vector<blink::UseCounterFeature>& first_features,
+ const std::vector<blink::UseCounterFeature>& second_features = {}) {
NavigateAndCommit(GURL(kTestUrl));
+
tester()->SimulateFeaturesUpdate(first_features);
// Verify that kPageVisits is observed on commit.
tester()->histogram_tester().ExpectBucketCount(
@@ -49,86 +77,15 @@ class UseCounterPageLoadMetricsObserverTest
internal::kAnimatedCssPropertiesHistogramName,
blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
- for (auto feature : first_features.features) {
- tester()->histogram_tester().ExpectBucketCount(
- internal::kFeaturesHistogramName,
- static_cast<base::Histogram::Sample>(feature), 1);
- tester()->histogram_tester().ExpectBucketCount(
- internal::kFeaturesHistogramMainFrameName,
- static_cast<base::Histogram::Sample>(feature), 1);
- }
+ for (const auto& feature : first_features)
+ ExpectBucketCount(feature, 1ul);
tester()->SimulateFeaturesUpdate(second_features);
- for (auto feature : first_features.features) {
- tester()->histogram_tester().ExpectBucketCount(
- internal::kFeaturesHistogramName,
- static_cast<base::Histogram::Sample>(feature), 1);
- tester()->histogram_tester().ExpectBucketCount(
- internal::kFeaturesHistogramMainFrameName,
- static_cast<base::Histogram::Sample>(feature), 1);
- }
- for (auto feature : second_features.features) {
- tester()->histogram_tester().ExpectBucketCount(
- internal::kFeaturesHistogramName,
- static_cast<base::Histogram::Sample>(feature), 1);
- tester()->histogram_tester().ExpectBucketCount(
- internal::kFeaturesHistogramMainFrameName,
- static_cast<base::Histogram::Sample>(feature), 1);
- }
- }
- void CssHistogramBasicTest(
- const page_load_metrics::mojom::PageLoadFeatures& first_features,
- const page_load_metrics::mojom::PageLoadFeatures& second_features =
- page_load_metrics::mojom::PageLoadFeatures()) {
- NavigateAndCommit(GURL(kTestUrl));
- tester()->SimulateFeaturesUpdate(first_features);
- // Verify that page visit is recorded for CSS histograms.
- tester()->histogram_tester().ExpectBucketCount(
- internal::kCssPropertiesHistogramName,
- blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
-
- for (auto feature : first_features.css_properties) {
- tester()->histogram_tester().ExpectBucketCount(
- internal::kCssPropertiesHistogramName, feature, 1);
- }
-
- tester()->SimulateFeaturesUpdate(second_features);
- for (auto feature : first_features.css_properties) {
- tester()->histogram_tester().ExpectBucketCount(
- internal::kCssPropertiesHistogramName, feature, 1);
- }
- for (auto feature : second_features.css_properties) {
- tester()->histogram_tester().ExpectBucketCount(
- internal::kCssPropertiesHistogramName, feature, 1);
- }
- }
-
- void AnimatedCssHistogramBasicTest(
- const page_load_metrics::mojom::PageLoadFeatures& first_features,
- const page_load_metrics::mojom::PageLoadFeatures& second_features =
- page_load_metrics::mojom::PageLoadFeatures()) {
- NavigateAndCommit(GURL(kTestUrl));
- tester()->SimulateFeaturesUpdate(first_features);
- // Verify that page visit is recorded for CSS histograms.
- tester()->histogram_tester().ExpectBucketCount(
- internal::kAnimatedCssPropertiesHistogramName,
- blink::mojom::CSSSampleId::kTotalPagesMeasured, 1);
-
- for (auto feature : first_features.animated_css_properties) {
- tester()->histogram_tester().ExpectBucketCount(
- internal::kAnimatedCssPropertiesHistogramName, feature, 1);
- }
-
- tester()->SimulateFeaturesUpdate(second_features);
- for (auto feature : first_features.animated_css_properties) {
- tester()->histogram_tester().ExpectBucketCount(
- internal::kAnimatedCssPropertiesHistogramName, feature, 1);
- }
- for (auto feature : second_features.animated_css_properties) {
- tester()->histogram_tester().ExpectBucketCount(
- internal::kAnimatedCssPropertiesHistogramName, feature, 1);
- }
+ for (const auto& feature : first_features)
+ ExpectBucketCount(feature, 1ul);
+ for (const auto& feature : second_features)
+ ExpectBucketCount(feature, 1ul);
}
protected:
@@ -141,57 +98,45 @@ class UseCounterPageLoadMetricsObserverTest
};
TEST_F(UseCounterPageLoadMetricsObserverTest, CountOneFeature) {
- std::vector<WebFeature> features({WebFeature::kFetch});
- page_load_metrics::mojom::PageLoadFeatures page_load_features;
- page_load_features.features = features;
- HistogramBasicTest(page_load_features);
+ HistogramBasicTest({{blink::mojom::UseCounterFeatureType::kWebFeature, 0}});
}
TEST_F(UseCounterPageLoadMetricsObserverTest, CountFeatures) {
- std::vector<WebFeature> features_0(
- {WebFeature::kFetch, WebFeature::kFetchBodyStream});
- std::vector<WebFeature> features_1({WebFeature::kWindowFind});
- page_load_metrics::mojom::PageLoadFeatures page_load_features_0;
- page_load_metrics::mojom::PageLoadFeatures page_load_features_1;
- page_load_features_0.features = features_0;
- page_load_features_1.features = features_1;
- HistogramBasicTest(page_load_features_0, page_load_features_1);
+ HistogramBasicTest(
+ {
+ {blink::mojom::UseCounterFeatureType::kWebFeature, 0},
+ {blink::mojom::UseCounterFeatureType::kWebFeature, 1},
+ {blink::mojom::UseCounterFeatureType::kCssProperty, 1},
+ },
+ {
+ {blink::mojom::UseCounterFeatureType::kWebFeature, 2},
+ {blink::mojom::UseCounterFeatureType::kAnimatedCssProperty, 2},
+ {blink::mojom::UseCounterFeatureType::
+ kPermissionsPolicyViolationEnforce,
+ 3},
+ });
}
TEST_F(UseCounterPageLoadMetricsObserverTest, CountDuplicatedFeatures) {
- std::vector<WebFeature> features_0(
- {WebFeature::kFetch, WebFeature::kFetch, WebFeature::kFetchBodyStream});
- std::vector<WebFeature> features_1(
- {WebFeature::kFetch, WebFeature::kWindowFind});
- page_load_metrics::mojom::PageLoadFeatures page_load_features_0;
- page_load_metrics::mojom::PageLoadFeatures page_load_features_1;
- page_load_features_0.features = features_0;
- page_load_features_1.features = features_1;
- HistogramBasicTest(page_load_features_0, page_load_features_1);
-}
-
-TEST_F(UseCounterPageLoadMetricsObserverTest, RecordCSSProperties) {
- // CSSPropertyID::kFont (5), CSSPropertyID::kZoom (19)
- page_load_metrics::mojom::PageLoadFeatures page_load_features_0;
- page_load_metrics::mojom::PageLoadFeatures page_load_features_1;
- page_load_features_0.css_properties = {CSSSampleId::kFont,
- CSSSampleId::kZoom};
- page_load_features_1.css_properties = {CSSSampleId::kZoom};
- CssHistogramBasicTest(page_load_features_0, page_load_features_1);
-}
-
-TEST_F(UseCounterPageLoadMetricsObserverTest, RecordAnimatedCSSProperties) {
- page_load_metrics::mojom::PageLoadFeatures page_load_features_0;
- page_load_metrics::mojom::PageLoadFeatures page_load_features_1;
- page_load_features_0.css_properties = {CSSSampleId::kFont,
- CSSSampleId::kZoom};
- page_load_features_1.css_properties = {CSSSampleId::kZoom};
- AnimatedCssHistogramBasicTest(page_load_features_0, page_load_features_1);
-}
-
-TEST_F(UseCounterPageLoadMetricsObserverTest, RecordCSSPropertiesInRange) {
- page_load_metrics::mojom::PageLoadFeatures page_load_features;
- page_load_features.css_properties = {CSSSampleId::kColor,
- CSSSampleId::kMaxValue};
- CssHistogramBasicTest(page_load_features);
+ HistogramBasicTest(
+ {
+ {blink::mojom::UseCounterFeatureType::kWebFeature, 0},
+ {blink::mojom::UseCounterFeatureType::kWebFeature, 0},
+ {blink::mojom::UseCounterFeatureType::kWebFeature, 1},
+ {blink::mojom::UseCounterFeatureType::kCssProperty, 1},
+ {blink::mojom::UseCounterFeatureType::kCssProperty, 1},
+ {blink::mojom::UseCounterFeatureType::kAnimatedCssProperty, 2},
+ {blink::mojom::UseCounterFeatureType::
+ kPermissionsPolicyViolationEnforce,
+ 3},
+ {blink::mojom::UseCounterFeatureType::kCssProperty, 3},
+ },
+ {
+ {blink::mojom::UseCounterFeatureType::kWebFeature, 0},
+ {blink::mojom::UseCounterFeatureType::kWebFeature, 2},
+ {blink::mojom::UseCounterFeatureType::kAnimatedCssProperty, 2},
+ {blink::mojom::UseCounterFeatureType::
+ kPermissionsPolicyViolationEnforce,
+ 3},
+ });
}
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_base.cc b/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_base.cc
index 5a99058bddc..d067aa026c1 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_base.cc
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_base.cc
@@ -24,17 +24,13 @@ PageLoadMetricsEmbedderBase::~PageLoadMetricsEmbedderBase() = default;
void PageLoadMetricsEmbedderBase::RegisterObservers(PageLoadTracker* tracker) {
// Register observers used by all embedders
- if (!IsPrerendering()) {
+ if (!IsNoStatePrefetch(web_contents())) {
tracker->AddObserver(
std::make_unique<BackForwardCachePageLoadMetricsObserver>());
tracker->AddObserver(std::make_unique<UmaPageLoadMetricsObserver>());
tracker->AddObserver(std::make_unique<LayoutPageLoadMetricsObserver>());
tracker->AddObserver(std::make_unique<UseCounterPageLoadMetricsObserver>());
tracker->AddObserver(std::make_unique<EarlyHintsPageLoadMetricsObserver>());
-
- // So far, PrerenderPageLoadMetricsObserver is used to gather metrics from
- // normal (non-prerendering) page loads, to estimate future coverage of
- // prerendering, so it's in the !IsPrerendering() block.
tracker->AddObserver(std::make_unique<PrerenderPageLoadMetricsObserver>());
}
// Allow the embedder to register any embedder-specific observers
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_base.h b/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_base.h
index 4b50013d3e6..470a293b6fe 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_base.h
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_base.h
@@ -28,7 +28,6 @@ class PageLoadMetricsEmbedderBase : public PageLoadMetricsEmbedderInterface {
protected:
~PageLoadMetricsEmbedderBase() override;
virtual void RegisterEmbedderObservers(PageLoadTracker* tracker) = 0;
- virtual bool IsPrerendering() const = 0;
private:
content::WebContents* const web_contents_;
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_interface.h b/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_interface.h
index 0edef5041cc..e1f756742bd 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_interface.h
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_embedder_interface.h
@@ -31,7 +31,7 @@ class PageLoadMetricsEmbedderInterface {
virtual bool IsNewTabPageUrl(const GURL& url) = 0;
virtual void RegisterObservers(PageLoadTracker* metrics) = 0;
virtual std::unique_ptr<base::OneShotTimer> CreateTimer() = 0;
- virtual bool IsPrerender(content::WebContents* web_contents) = 0;
+ virtual bool IsNoStatePrefetch(content::WebContents* web_contents) = 0;
virtual bool IsExtensionUrl(const GURL& url) = 0;
// Returns the PageLoadMetricsMemoryTracker for the given BrowserContext if
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_memory_tracker_unittest.cc b/chromium/components/page_load_metrics/browser/page_load_metrics_memory_tracker_unittest.cc
index d69f9f2f7e9..b11574cc55e 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_memory_tracker_unittest.cc
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_memory_tracker_unittest.cc
@@ -44,7 +44,7 @@ class TestPageLoadMetricsEmbedder
// page_load_metrics::PageLoadMetricsEmbedderBase:
bool IsNewTabPageUrl(const GURL& url) override { return false; }
- bool IsPrerender(content::WebContents* web_contents) override {
+ bool IsNoStatePrefetch(content::WebContents* web_contents) override {
return false;
}
bool IsExtensionUrl(const GURL& url) override { return false; }
@@ -62,7 +62,6 @@ class TestPageLoadMetricsEmbedder
// page_load_metrics::PageLoadMetricsEmbedderBase:
void RegisterEmbedderObservers(
page_load_metrics::PageLoadTracker* tracker) override {}
- bool IsPrerendering() const override { return false; }
private:
page_load_metrics::PageLoadMetricsMemoryTracker memory_tracker_;
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_observer.h b/chromium/components/page_load_metrics/browser/page_load_metrics_observer.h
index ab086a5c623..1be339f8fa4 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_observer.h
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_observer.h
@@ -9,7 +9,6 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
#include "components/page_load_metrics/browser/page_load_metrics_event.h"
#include "components/page_load_metrics/browser/page_load_metrics_observer_delegate.h"
@@ -22,7 +21,9 @@
#include "net/cookies/canonical_cookie.h"
#include "services/metrics/public/cpp/ukm_source.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/input/web_input_event.h"
+#include "third_party/blink/public/common/use_counter/use_counter_feature.h"
#include "url/gurl.h"
namespace content {
@@ -125,6 +126,10 @@ struct PageRenderData {
// How many times LayoutNG-based LayoutObject::UpdateLayout() is called.
uint64_t ng_layout_call_count = 0;
+
+ uint64_t flexbox_ng_layout_block_count = 0;
+
+ uint64_t grid_ng_layout_block_count = 0;
};
// Information related to layout shift normalization for different strategies.
@@ -139,20 +144,20 @@ struct NormalizedCLSData {
// Maximum CLS of session windows. The gap between two consecutive shifts is
// not bigger than 1000ms and the maximum window size is 5000ms.
- double session_windows_gap1000ms_max5000ms_max_cls = 0.0;
+ float session_windows_gap1000ms_max5000ms_max_cls = 0.0;
// Maximum CLS of session windows. The gap between two consecutive shifts is
// not bigger than 1000ms.
- double session_windows_gap1000ms_maxMax_max_cls = 0.0;
+ float session_windows_gap1000ms_maxMax_max_cls = 0.0;
// The average CLS of session windows. The gap between two consecutive shifts
// is not bigger than 5000ms.
- double session_windows_gap5000ms_maxMax_average_cls = 0.0;
+ float session_windows_gap5000ms_maxMax_average_cls = 0.0;
// Maximum CLS of session windows. The gap between two consecutive shifts is
// not bigger than 1000ms or segmented by a user input. The maximum window
// size is 5000ms.
- double session_windows_by_inputs_gap1000ms_max5000ms_max_cls = 0.0;
+ float session_windows_by_inputs_gap1000ms_max5000ms_max_cls = 0.0;
// If true, will not report the data in UKM.
bool data_tainted = false;
@@ -438,7 +443,7 @@ class PageLoadMetricsObserver {
// Invoked when new use counter features are observed across all frames.
virtual void OnFeaturesUsageObserved(
content::RenderFrameHost* rfh,
- const mojom::PageLoadFeatures& features) {}
+ const std::vector<blink::UseCounterFeature>& features) {}
// The smoothness metrics is shared over shared-memory. The observer should
// create a mapping (by calling |shared_memory.Map()|) so that they are able
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h b/chromium/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h
index da6730224d0..9592f1ad467 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_observer_delegate.h
@@ -5,12 +5,12 @@
#ifndef COMPONENTS_PAGE_LOAD_METRICS_BROWSER_PAGE_LOAD_METRICS_OBSERVER_DELEGATE_H_
#define COMPONENTS_PAGE_LOAD_METRICS_BROWSER_PAGE_LOAD_METRICS_OBSERVER_DELEGATE_H_
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h"
#include "components/page_load_metrics/browser/resource_tracker.h"
#include "components/page_load_metrics/common/page_end_reason.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/scoped_visibility_tracker.h"
namespace content {
@@ -43,7 +43,7 @@ class PageLoadMetricsObserverDelegate {
// The first time when the page becomes backgrounded after the page is
// restored. The time is relative to the navigation start of bfcache restore
// avigation.
- base::Optional<base::TimeDelta> first_background_time;
+ absl::optional<base::TimeDelta> first_background_time;
// True if the page was in foreground when the page is restored.
bool was_in_foreground = false;
@@ -63,11 +63,11 @@ class PageLoadMetricsObserverDelegate {
virtual base::TimeTicks GetNavigationStart() const = 0;
// The first time that the page was backgrounded since the navigation started.
- virtual const base::Optional<base::TimeDelta>& GetFirstBackgroundTime()
+ virtual const absl::optional<base::TimeDelta>& GetFirstBackgroundTime()
const = 0;
// The first time that the page was foregrounded since the navigation started.
- virtual const base::Optional<base::TimeDelta>& GetFirstForegroundTime()
+ virtual const absl::optional<base::TimeDelta>& GetFirstForegroundTime()
const = 0;
// The state of index-th restore from the back-forward cache.
@@ -119,7 +119,7 @@ class PageLoadMetricsObserverDelegate {
// * a new navigation which later commits is initiated in the same tab
// This field will not be set if the page is still active and hasn't yet
// finished.
- virtual base::Optional<base::TimeDelta> GetPageEndTime() const = 0;
+ virtual absl::optional<base::TimeDelta> GetPageEndTime() const = 0;
// Extra information supplied to the page load metrics system from the
// renderer for the main frame.
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_test_waiter.cc b/chromium/components/page_load_metrics/browser/page_load_metrics_test_waiter.cc
index 3499984331e..b6ab690f781 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_test_waiter.cc
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_test_waiter.cc
@@ -96,6 +96,11 @@ void PageLoadMetricsTestWaiter::AddMemoryUpdateExpectation(int routing_id) {
expected_.memory_update_frame_ids_.insert(routing_id);
}
+void PageLoadMetricsTestWaiter::AddLoadingBehaviorExpectation(
+ int behavior_flags) {
+ expected_.loading_behavior_flags_ |= behavior_flags;
+}
+
bool PageLoadMetricsTestWaiter::DidObserveInPage(TimingField field) const {
return observed_.page_fields_.IsSet(field);
}
@@ -150,6 +155,12 @@ void PageLoadMetricsTestWaiter::OnCpuTimingUpdated(
run_loop_->Quit();
}
+void PageLoadMetricsTestWaiter::OnLoadingBehaviorObserved(int behavior_flags) {
+ observed_.loading_behavior_flags_ |= behavior_flags;
+ if (ExpectationsSatisfied() && run_loop_)
+ run_loop_->Quit();
+}
+
void PageLoadMetricsTestWaiter::OnLoadedResource(
const page_load_metrics::ExtraRequestCompleteInfo&
extra_request_complete_info) {
@@ -193,12 +204,13 @@ void PageLoadMetricsTestWaiter::OnResourceDataUseObserved(
void PageLoadMetricsTestWaiter::OnFeaturesUsageObserved(
content::RenderFrameHost* rfh,
- const mojom::PageLoadFeatures& features) {
- for (blink::mojom::WebFeature feature : features.features) {
- size_t feature_idx = static_cast<size_t>(feature);
- if (observed_.web_features_.test(feature_idx))
+ const std::vector<blink::UseCounterFeature>& features) {
+ for (const auto& feature : features) {
+ // TODO(crbug.com/1194678): Expand test converage to other feature types.
+ if (feature.type() != blink::mojom::UseCounterFeatureType::kWebFeature)
continue;
- observed_.web_features_.set(feature_idx);
+
+ observed_.web_features_.set(feature.value());
}
if (ExpectationsSatisfied() && run_loop_)
@@ -337,6 +349,14 @@ bool PageLoadMetricsTestWaiter::CpuTimeExpectationsSatisfied() const {
return current_aggregate_cpu_time_ >= expected_minimum_aggregate_cpu_time_;
}
+bool PageLoadMetricsTestWaiter::LoadingBehaviorExpectationsSatisfied() const {
+ // Once we've observed everything we've expected, we're satisfied. We allow
+ // other behaviors to be present incidentally.
+ return (expected_.loading_behavior_flags_ &
+ observed_.loading_behavior_flags_) ==
+ expected_.loading_behavior_flags_;
+}
+
bool PageLoadMetricsTestWaiter::ResourceUseExpectationsSatisfied() const {
return (expected_minimum_complete_resources_ == 0 ||
current_complete_resources_ >=
@@ -397,6 +417,7 @@ bool PageLoadMetricsTestWaiter::ExpectationsSatisfied() const {
SubframeNavigationExpectationsSatisfied() &&
SubframeDataExpectationsSatisfied() &&
IsSubset(expected_.frame_sizes_, observed_.frame_sizes_) &&
+ LoadingBehaviorExpectationsSatisfied() &&
CpuTimeExpectationsSatisfied() &&
MainFrameIntersectionExpectationsSatisfied() &&
MemoryUpdateExpectationsSatisfied();
@@ -431,6 +452,12 @@ void PageLoadMetricsTestWaiter::WaiterMetricsObserver::OnCpuTimingUpdate(
waiter_->OnCpuTimingUpdated(subframe_rfh, timing);
}
+void PageLoadMetricsTestWaiter::WaiterMetricsObserver::
+ OnLoadingBehaviorObserved(content::RenderFrameHost*, int behavior_flags) {
+ if (waiter_)
+ waiter_->OnLoadingBehaviorObserved(behavior_flags);
+}
+
void PageLoadMetricsTestWaiter::WaiterMetricsObserver::OnLoadedResource(
const page_load_metrics::ExtraRequestCompleteInfo&
extra_request_complete_info) {
@@ -449,7 +476,7 @@ void PageLoadMetricsTestWaiter::WaiterMetricsObserver::
void PageLoadMetricsTestWaiter::WaiterMetricsObserver::OnFeaturesUsageObserved(
content::RenderFrameHost* rfh,
- const mojom::PageLoadFeatures& features) {
+ const std::vector<blink::UseCounterFeature>& features) {
if (waiter_)
waiter_->OnFeaturesUsageObserved(nullptr, features);
}
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_test_waiter.h b/chromium/components/page_load_metrics/browser/page_load_metrics_test_waiter.h
index 503a416ca28..ec4b3d6fe73 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_test_waiter.h
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_test_waiter.h
@@ -87,6 +87,10 @@ class PageLoadMetricsTestWaiter
// frame routing IDs expected to receive a memory measurement update.
void AddMemoryUpdateExpectation(int routing_id);
+ // Adds all |blink::LoadingBehaviorFlag|s set in |behavior_flags| to the
+ // set of expected behaviors.
+ void AddLoadingBehaviorExpectation(int behavior_flags);
+
// Whether the given TimingField was observed in the page.
bool DidObserveInPage(TimingField field) const;
@@ -137,6 +141,8 @@ class PageLoadMetricsTestWaiter
content::RenderFrameHost* subframe_rfh,
const page_load_metrics::mojom::CpuTiming& timing) override;
+ void OnLoadingBehaviorObserved(content::RenderFrameHost* rfh,
+ int behavior_flags) override;
void OnLoadedResource(const page_load_metrics::ExtraRequestCompleteInfo&
extra_request_complete_info) override;
@@ -147,7 +153,7 @@ class PageLoadMetricsTestWaiter
void OnFeaturesUsageObserved(
content::RenderFrameHost* rfh,
- const page_load_metrics::mojom::PageLoadFeatures&) override;
+ const std::vector<blink::UseCounterFeature>&) override;
void OnDidFinishSubFrameNavigation(
content::NavigationHandle* navigation_handle) override;
@@ -222,6 +228,11 @@ class PageLoadMetricsTestWaiter
void OnCpuTimingUpdated(content::RenderFrameHost* subframe_rfh,
const page_load_metrics::mojom::CpuTiming& timing);
+ // Updates observed page fields when a loading behavior (see
+ // |blink::LoadingBehaviorFlag|) is observed by MetricsWebContentsObserver.
+ // Stops waiting if expectations are satsfied after update.
+ void OnLoadingBehaviorObserved(int behavior_flags);
+
// Updates observed page fields when a resource load is observed by
// MetricsWebContentsObserver. Stops waiting if expectations are satsfied
// after update.
@@ -237,8 +248,9 @@ class PageLoadMetricsTestWaiter
// Updates |observed_.web_features_| to record any new feature observed.
// Stops waiting if expectations are satisfied after update.
- void OnFeaturesUsageObserved(content::RenderFrameHost* rfh,
- const mojom::PageLoadFeatures& features);
+ void OnFeaturesUsageObserved(
+ content::RenderFrameHost* rfh,
+ const std::vector<blink::UseCounterFeature>& features);
void FrameSizeChanged(content::RenderFrameHost* render_frame_host,
const gfx::Size& frame_size);
@@ -264,6 +276,7 @@ class PageLoadMetricsTestWaiter
// These methods check whether expectations are satisfied for specific fields
// inside the State object, by comparing them in expected_ and observed_.
bool CpuTimeExpectationsSatisfied() const;
+ bool LoadingBehaviorExpectationsSatisfied() const;
bool ResourceUseExpectationsSatisfied() const;
bool WebFeaturesExpectationsSatisfied() const;
bool SubframeNavigationExpectationsSatisfied() const;
@@ -286,6 +299,7 @@ class PageLoadMetricsTestWaiter
std::bitset<static_cast<size_t>(
blink::mojom::WebFeature::kNumberOfFeatures)>
web_features_;
+ int loading_behavior_flags_ = 0;
bool subframe_navigation_ = false;
bool subframe_data_ = false;
std::set<gfx::Size, FrameSizeComparator> frame_sizes_;
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc b/chromium/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc
index 93c35f2efe8..5f02125dbe5 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.cc
@@ -11,13 +11,13 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "components/page_load_metrics/browser/page_load_metrics_embedder_interface.h"
#include "components/page_load_metrics/browser/page_load_metrics_util.h"
#include "components/page_load_metrics/browser/page_load_tracker.h"
#include "components/page_load_metrics/common/page_load_metrics_constants.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace page_load_metrics {
@@ -38,7 +38,7 @@ namespace {
// Helper to allow use of Optional<> values in LOG() messages.
std::ostream& operator<<(std::ostream& os,
- const base::Optional<base::TimeDelta>& opt) {
+ const absl::optional<base::TimeDelta>& opt) {
if (opt)
os << opt.value();
else
@@ -48,8 +48,8 @@ std::ostream& operator<<(std::ostream& os,
// If second is non-zero, first must also be non-zero and less than or equal to
// second.
-bool EventsInOrder(const base::Optional<base::TimeDelta>& first,
- const base::Optional<base::TimeDelta>& second) {
+bool EventsInOrder(const absl::optional<base::TimeDelta>& first,
+ const absl::optional<base::TimeDelta>& second) {
if (!second) {
return true;
}
@@ -239,8 +239,8 @@ internal::PageLoadTimingStatus IsValidPageLoadTiming(
// If the updated value has an earlier time than the current value, log so we
// can keep track of how often this happens.
-void LogIfOutOfOrderTiming(const base::Optional<base::TimeDelta>& current,
- const base::Optional<base::TimeDelta>& update) {
+void LogIfOutOfOrderTiming(const absl::optional<base::TimeDelta>& current,
+ const absl::optional<base::TimeDelta>& update) {
if (!current || !update)
return;
@@ -286,9 +286,9 @@ class PageLoadTimingMerger {
// |navigation_start_offset| contains the delta in navigation start time
// between the main frame and the frame for |optional_candidate_new_value|.
bool MaybeUpdateTimeDelta(
- base::Optional<base::TimeDelta>* inout_existing_value,
+ absl::optional<base::TimeDelta>* inout_existing_value,
base::TimeDelta navigation_start_offset,
- const base::Optional<base::TimeDelta>& optional_candidate_new_value) {
+ const absl::optional<base::TimeDelta>& optional_candidate_new_value) {
// If we don't get a new value, there's nothing to do
if (!optional_candidate_new_value)
return false;
@@ -467,7 +467,7 @@ void PageLoadMetricsUpdateDispatcher::UpdateMetrics(
content::RenderFrameHost* render_frame_host,
mojom::PageLoadTimingPtr new_timing,
mojom::FrameMetadataPtr new_metadata,
- mojom::PageLoadFeaturesPtr new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
const std::vector<mojom::ResourceDataUpdatePtr>& resources,
mojom::FrameRenderDataUpdatePtr render_data,
mojom::CpuTimingPtr new_cpu_timing,
@@ -509,7 +509,7 @@ void PageLoadMetricsUpdateDispatcher::UpdateMetrics(
OnSubFrameRenderDataChanged(render_frame_host, *render_data);
}
- client_->UpdateFeaturesUsage(render_frame_host, *new_features);
+ client_->UpdateFeaturesUsage(render_frame_host, new_features);
}
void PageLoadMetricsUpdateDispatcher::UpdateHasSeenInputOrScroll(
@@ -528,7 +528,7 @@ void PageLoadMetricsUpdateDispatcher::UpdateHasSeenInputOrScroll(
void PageLoadMetricsUpdateDispatcher::UpdateFeatures(
content::RenderFrameHost* render_frame_host,
- const mojom::PageLoadFeatures& new_features) {
+ const std::vector<blink::UseCounterFeature>& new_features) {
if (embedder_interface_->IsExtensionUrl(
render_frame_host->GetLastCommittedURL())) {
// Extensions can inject child frames into a page. We don't want to track
@@ -736,13 +736,9 @@ void PageLoadMetricsUpdateDispatcher::UpdateMobileFriendliness(
void PageLoadMetricsUpdateDispatcher::UpdatePageRenderData(
const mojom::FrameRenderDataUpdate& render_data) {
page_render_data_.layout_shift_score += render_data.layout_shift_delta;
- // Should add input timestamps before layout shifts.
- layout_shift_normalization_.AddInputTimeStamps(render_data.input_timestamps);
layout_shift_normalization_.AddNewLayoutShifts(
render_data.new_layout_shifts, base::TimeTicks::Now(),
page_render_data_.layout_shift_score);
- layout_shift_normalization_for_bfcache_.AddInputTimeStamps(
- render_data.input_timestamps);
layout_shift_normalization_for_bfcache_.AddNewLayoutShifts(
render_data.new_layout_shifts, base::TimeTicks::Now(),
page_render_data_.layout_shift_score -
@@ -765,6 +761,10 @@ void PageLoadMetricsUpdateDispatcher::UpdatePageRenderData(
render_data.all_layout_call_count_delta;
page_render_data_.ng_layout_call_count +=
render_data.ng_layout_call_count_delta;
+ page_render_data_.flexbox_ng_layout_block_count +=
+ render_data.flexbox_ng_layout_block_count_delta;
+ page_render_data_.grid_ng_layout_block_count +=
+ render_data.grid_ng_layout_block_count_delta;
}
void PageLoadMetricsUpdateDispatcher::UpdateMainFrameRenderData(
@@ -783,8 +783,10 @@ void PageLoadMetricsUpdateDispatcher::UpdateMainFrameRenderData(
render_data.ng_layout_block_count_delta;
main_frame_render_data_.all_layout_call_count +=
render_data.all_layout_call_count_delta;
- main_frame_render_data_.ng_layout_call_count +=
- render_data.ng_layout_call_count_delta;
+ main_frame_render_data_.flexbox_ng_layout_block_count +=
+ render_data.flexbox_ng_layout_block_count_delta;
+ page_render_data_.grid_ng_layout_block_count +=
+ render_data.grid_ng_layout_block_count_delta;
}
void PageLoadMetricsUpdateDispatcher::OnSubFrameRenderDataChanged(
@@ -803,12 +805,13 @@ void PageLoadMetricsUpdateDispatcher::FlushPendingTimingUpdates() {
void PageLoadMetricsUpdateDispatcher::MaybeDispatchTimingUpdates(
bool should_buffer_timing_update_callback) {
- // If we merged a new timing value, then we should buffer updates for
- // |kBufferTimerDelayMillis|, to allow for any other out of order timings to
- // arrive before we dispatch the minimum observed timings to observers.
+ // If we merged a new timing value, then we should buffer updates to allow for
+ // any other out of order timings to arrive before we dispatch to observers.
if (should_buffer_timing_update_callback) {
timer_->Start(
- FROM_HERE, base::TimeDelta::FromMilliseconds(kBufferTimerDelayMillis),
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(
+ GetBufferTimerDelayMillis(TimerType::kBrowser)),
base::BindOnce(&PageLoadMetricsUpdateDispatcher::DispatchTimingUpdates,
base::Unretained(this)));
} else if (!timer_->IsRunning()) {
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.h b/chromium/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.h
index 8f619d12a59..fdb9e2fb452 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.h
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_update_dispatcher.h
@@ -126,7 +126,7 @@ class PageLoadMetricsUpdateDispatcher {
const mojom::FrameRenderDataUpdate& render_data) = 0;
virtual void UpdateFeaturesUsage(
content::RenderFrameHost* rfh,
- const mojom::PageLoadFeatures& new_features) = 0;
+ const std::vector<blink::UseCounterFeature>& new_features) = 0;
virtual void UpdateResourceDataUse(
content::RenderFrameHost* rfh,
const std::vector<mojom::ResourceDataUpdatePtr>& resources) = 0;
@@ -152,7 +152,7 @@ class PageLoadMetricsUpdateDispatcher {
content::RenderFrameHost* render_frame_host,
mojom::PageLoadTimingPtr new_timing,
mojom::FrameMetadataPtr new_metadata,
- mojom::PageLoadFeaturesPtr new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
const std::vector<mojom::ResourceDataUpdatePtr>& resources,
mojom::FrameRenderDataUpdatePtr render_data,
mojom::CpuTimingPtr new_cpu_timing,
@@ -167,8 +167,9 @@ class PageLoadMetricsUpdateDispatcher {
// This method is only intended to be called for PageLoadFeatures being
// recorded directly from the browser process. Features coming from the
// renderer process should use the main flow into |UpdateMetrics|.
- void UpdateFeatures(content::RenderFrameHost* render_frame_host,
- const mojom::PageLoadFeatures& new_features);
+ void UpdateFeatures(
+ content::RenderFrameHost* render_frame_host,
+ const std::vector<blink::UseCounterFeature>& new_features);
void DidFinishSubFrameNavigation(
content::NavigationHandle* navigation_handle);
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_util.cc b/chromium/components/page_load_metrics/browser/page_load_metrics_util.cc
index 2353b69954b..9699d60a306 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_util.cc
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_util.cc
@@ -102,7 +102,7 @@ bool QueryContainsComponentHelper(const base::StringPiece query,
} // namespace
bool WasStartedInForegroundOptionalEventInForeground(
- const base::Optional<base::TimeDelta>& event,
+ const absl::optional<base::TimeDelta>& event,
const PageLoadMetricsObserverDelegate& delegate) {
return delegate.StartedInForeground() && event &&
(!delegate.GetFirstBackgroundTime() ||
@@ -110,12 +110,12 @@ bool WasStartedInForegroundOptionalEventInForeground(
}
bool WasStartedInForegroundOptionalEventInForegroundAfterBackForwardCacheRestore(
- const base::Optional<base::TimeDelta>& event,
+ const absl::optional<base::TimeDelta>& event,
const PageLoadMetricsObserverDelegate& delegate,
size_t index) {
const auto& back_forward_cache_restore =
delegate.GetBackForwardCacheRestore(index);
- base::Optional<base::TimeDelta> first_background_time =
+ absl::optional<base::TimeDelta> first_background_time =
back_forward_cache_restore.first_background_time;
return back_forward_cache_restore.was_in_foreground && event &&
(!first_background_time ||
@@ -123,7 +123,7 @@ bool WasStartedInForegroundOptionalEventInForegroundAfterBackForwardCacheRestore
}
bool WasStartedInBackgroundOptionalEventInForeground(
- const base::Optional<base::TimeDelta>& event,
+ const absl::optional<base::TimeDelta>& event,
const PageLoadMetricsObserverDelegate& delegate) {
return !delegate.StartedInForeground() && event &&
delegate.GetFirstForegroundTime() &&
@@ -156,13 +156,13 @@ PageAbortInfo GetPageAbortInfo(
delegate.GetPageEndTime().value()};
}
-base::Optional<base::TimeDelta> GetInitialForegroundDuration(
+absl::optional<base::TimeDelta> GetInitialForegroundDuration(
const PageLoadMetricsObserverDelegate& delegate,
base::TimeTicks app_background_time) {
if (!delegate.StartedInForeground())
- return base::Optional<base::TimeDelta>();
+ return absl::optional<base::TimeDelta>();
- base::Optional<base::TimeDelta> time_on_page =
+ absl::optional<base::TimeDelta> time_on_page =
OptionalMin(delegate.GetFirstBackgroundTime(), delegate.GetPageEndTime());
// If we don't have a time_on_page value yet, and we have an app background
@@ -188,7 +188,7 @@ bool DidObserveLoadingBehaviorInAnyFrame(
}
bool IsGoogleSearchHostname(const GURL& url) {
- base::Optional<std::string> result =
+ absl::optional<std::string> result =
page_load_metrics::GetGoogleHostnamePrefix(url);
return result && result.value() == "www";
}
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_util.h b/chromium/components/page_load_metrics/browser/page_load_metrics_util.h
index 33f62e05e37..8a6295853aa 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_util.h
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_util.h
@@ -6,10 +6,10 @@
#define COMPONENTS_PAGE_LOAD_METRICS_BROWSER_PAGE_LOAD_METRICS_UTIL_H_
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/page_load_metrics/browser/page_load_metrics_observer.h"
#include "components/page_load_metrics/common/page_load_metrics_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/loader/loading_behavior_flag.h"
// Up to 10 minutes, with 100 buckets.
@@ -100,11 +100,11 @@ struct PageAbortInfo {
// consider the event to be logged in the foreground histogram since any
// background specific handling would not yet have been applied to that event.
bool WasStartedInForegroundOptionalEventInForeground(
- const base::Optional<base::TimeDelta>& event,
+ const absl::optional<base::TimeDelta>& event,
const PageLoadMetricsObserverDelegate& delegate);
bool WasStartedInForegroundOptionalEventInForegroundAfterBackForwardCacheRestore(
- const base::Optional<base::TimeDelta>& event,
+ const absl::optional<base::TimeDelta>& event,
const PageLoadMetricsObserverDelegate& delegate,
size_t index);
@@ -114,7 +114,7 @@ bool WasStartedInForegroundOptionalEventInForegroundAfterBackForwardCacheRestore
// - Moved to the foreground prior to the event.
// - Not moved back to the background prior to the event.
bool WasStartedInBackgroundOptionalEventInForeground(
- const base::Optional<base::TimeDelta>& event,
+ const absl::optional<base::TimeDelta>& event,
const PageLoadMetricsObserverDelegate& delegate);
// Returns true if |delegate| started in the foreground or became foregrounded
@@ -131,7 +131,7 @@ PageAbortInfo GetPageAbortInfo(const PageLoadMetricsObserverDelegate& delegate);
// * the render process hosting the page goes away
// * a new navigation which later commits is initiated in the same tab
// * the tab hosting the page is backgrounded
-base::Optional<base::TimeDelta> GetInitialForegroundDuration(
+absl::optional<base::TimeDelta> GetInitialForegroundDuration(
const PageLoadMetricsObserverDelegate& delegate,
base::TimeTicks app_background_time);
diff --git a/chromium/components/page_load_metrics/browser/page_load_metrics_util_unittest.cc b/chromium/components/page_load_metrics/browser/page_load_metrics_util_unittest.cc
index 035a8dc891a..b98afbb50b0 100644
--- a/chromium/components/page_load_metrics/browser/page_load_metrics_util_unittest.cc
+++ b/chromium/components/page_load_metrics/browser/page_load_metrics_util_unittest.cc
@@ -68,7 +68,7 @@ TEST_F(PageLoadMetricsUtilTest, GetGoogleHostnamePrefix) {
{true, "www.www", "https://www.www.google.com/"},
};
for (const auto& test : test_cases) {
- base::Optional<std::string> result =
+ absl::optional<std::string> result =
page_load_metrics::GetGoogleHostnamePrefix(GURL(test.url));
EXPECT_EQ(test.expected_result, result.has_value())
<< "For URL: " << test.url;
diff --git a/chromium/components/page_load_metrics/browser/page_load_tracker.cc b/chromium/components/page_load_metrics/browser/page_load_tracker.cc
index 3d319b66a5a..bcc6c27fad9 100644
--- a/chromium/components/page_load_metrics/browser/page_load_tracker.cc
+++ b/chromium/components/page_load_metrics/browser/page_load_tracker.cc
@@ -254,7 +254,8 @@ PageLoadTracker::PageLoadTracker(
UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadStartedInForeground,
started_in_foreground_);
- if (embedder_interface_->IsPrerender(navigation_handle->GetWebContents()))
+ if (embedder_interface_->IsNoStatePrefetch(
+ navigation_handle->GetWebContents()))
UMA_HISTOGRAM_BOOLEAN(internal::kPageLoadPrerender, true);
}
@@ -799,7 +800,7 @@ void PageLoadTracker::DidActivatePortal(base::TimeTicks activation_time) {
void PageLoadTracker::UpdateFeaturesUsage(
content::RenderFrameHost* rfh,
- const mojom::PageLoadFeatures& new_features) {
+ const std::vector<blink::UseCounterFeature>& new_features) {
for (const auto& observer : observers_) {
observer->OnFeaturesUsageObserved(rfh, new_features);
}
@@ -853,12 +854,12 @@ base::TimeTicks PageLoadTracker::GetNavigationStart() const {
return navigation_start_;
}
-const base::Optional<base::TimeDelta>& PageLoadTracker::GetFirstBackgroundTime()
+const absl::optional<base::TimeDelta>& PageLoadTracker::GetFirstBackgroundTime()
const {
return first_background_time_;
}
-const base::Optional<base::TimeDelta>& PageLoadTracker::GetFirstForegroundTime()
+const absl::optional<base::TimeDelta>& PageLoadTracker::GetFirstForegroundTime()
const {
return first_foreground_time_;
}
@@ -896,8 +897,8 @@ const UserInitiatedInfo& PageLoadTracker::GetPageEndUserInitiatedInfo() const {
return page_end_user_initiated_info_;
}
-base::Optional<base::TimeDelta> PageLoadTracker::GetPageEndTime() const {
- base::Optional<base::TimeDelta> page_end_time;
+absl::optional<base::TimeDelta> PageLoadTracker::GetPageEndTime() const {
+ absl::optional<base::TimeDelta> page_end_time;
if (page_end_reason_ != END_NONE) {
DCHECK_GE(page_end_time_, navigation_start_);
diff --git a/chromium/components/page_load_metrics/browser/page_load_tracker.h b/chromium/components/page_load_metrics/browser/page_load_tracker.h
index a40df44d6d1..0d87aa0ebdd 100644
--- a/chromium/components/page_load_metrics/browser/page_load_tracker.h
+++ b/chromium/components/page_load_metrics/browser/page_load_tracker.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h"
#include "components/page_load_metrics/browser/page_load_metrics_event.h"
@@ -23,6 +22,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "net/cookies/canonical_cookie.h"
#include "services/metrics/public/cpp/ukm_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/scoped_visibility_tracker.h"
#include "ui/gfx/geometry/size.h"
@@ -195,7 +195,7 @@ class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client,
const mojom::FrameMetadata& metadata) override;
void UpdateFeaturesUsage(
content::RenderFrameHost* rfh,
- const mojom::PageLoadFeatures& new_features) override;
+ const std::vector<blink::UseCounterFeature>& new_features) override;
void UpdateResourceDataUse(
content::RenderFrameHost* rfh,
const std::vector<mojom::ResourceDataUpdatePtr>& resources) override;
@@ -212,9 +212,9 @@ class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client,
// PageLoadMetricsObserverDelegate implementation:
content::WebContents* GetWebContents() const override;
base::TimeTicks GetNavigationStart() const override;
- const base::Optional<base::TimeDelta>& GetFirstBackgroundTime()
+ const absl::optional<base::TimeDelta>& GetFirstBackgroundTime()
const override;
- const base::Optional<base::TimeDelta>& GetFirstForegroundTime()
+ const absl::optional<base::TimeDelta>& GetFirstForegroundTime()
const override;
const BackForwardCacheRestore& GetBackForwardCacheRestore(
size_t index) const override;
@@ -225,7 +225,7 @@ class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client,
bool DidCommit() const override;
PageEndReason GetPageEndReason() const override;
const UserInitiatedInfo& GetPageEndUserInitiatedInfo() const override;
- base::Optional<base::TimeDelta> GetPageEndTime() const override;
+ absl::optional<base::TimeDelta> GetPageEndTime() const override;
const mojom::FrameMetadata& GetMainFrameMetadata() const override;
const mojom::FrameMetadata& GetSubframeMetadata() const override;
const PageRenderData& GetPageRenderData() const override;
@@ -447,8 +447,8 @@ class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client,
// We record separate metrics for events that occur after a background,
// because metrics like layout/paint are delayed artificially
// when they occur in the background.
- base::Optional<base::TimeDelta> first_background_time_;
- base::Optional<base::TimeDelta> first_foreground_time_;
+ absl::optional<base::TimeDelta> first_background_time_;
+ absl::optional<base::TimeDelta> first_foreground_time_;
std::vector<BackForwardCacheRestore> back_forward_cache_restores_;
const bool started_in_foreground_;
@@ -457,7 +457,7 @@ class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client,
ui::PageTransition page_transition_;
- base::Optional<content::GlobalRequestID> navigation_request_id_;
+ absl::optional<content::GlobalRequestID> navigation_request_id_;
// Whether this page load was user initiated.
UserInitiatedInfo user_initiated_info_;
diff --git a/chromium/components/page_load_metrics/browser/test_metrics_web_contents_observer_embedder.cc b/chromium/components/page_load_metrics/browser/test_metrics_web_contents_observer_embedder.cc
index 26c6571faeb..82ab9b6273f 100644
--- a/chromium/components/page_load_metrics/browser/test_metrics_web_contents_observer_embedder.cc
+++ b/chromium/components/page_load_metrics/browser/test_metrics_web_contents_observer_embedder.cc
@@ -25,8 +25,8 @@ class TestPageLoadMetricsObserver : public PageLoadMetricsObserver {
std::vector<ExtraRequestCompleteInfo>* loaded_resources,
std::vector<GURL>* observed_committed_urls,
std::vector<GURL>* observed_aborted_urls,
- std::vector<mojom::PageLoadFeatures>* observed_features,
- base::Optional<bool>* is_first_navigation_in_web_contents,
+ std::vector<blink::UseCounterFeature>* observed_features,
+ absl::optional<bool>* is_first_navigation_in_web_contents,
int* count_on_enter_back_forward_cache)
: updated_timings_(updated_timings),
updated_subframe_timings_(updated_subframe_timings),
@@ -80,8 +80,9 @@ class TestPageLoadMetricsObserver : public PageLoadMetricsObserver {
void OnFeaturesUsageObserved(
content::RenderFrameHost* rfh,
- const mojom::PageLoadFeatures& features) override {
- observed_features_->push_back(features);
+ const std::vector<blink::UseCounterFeature>& features) override {
+ observed_features_->insert(observed_features_->end(), features.begin(),
+ features.end());
}
void OnDidInternalNavigationAbort(
@@ -101,10 +102,10 @@ class TestPageLoadMetricsObserver : public PageLoadMetricsObserver {
std::vector<mojom::PageLoadTimingPtr>* const complete_timings_;
std::vector<mojom::CpuTimingPtr>* const updated_cpu_timings_;
std::vector<ExtraRequestCompleteInfo>* const loaded_resources_;
- std::vector<mojom::PageLoadFeatures>* const observed_features_;
+ std::vector<blink::UseCounterFeature>* const observed_features_;
std::vector<GURL>* const observed_committed_urls_;
std::vector<GURL>* const observed_aborted_urls_;
- base::Optional<bool>* is_first_navigation_in_web_contents_;
+ absl::optional<bool>* is_first_navigation_in_web_contents_;
int* const count_on_enter_back_forward_cache_;
};
@@ -170,7 +171,7 @@ TestMetricsWebContentsObserverEmbedder::CreateTimer() {
return std::move(timer);
}
-bool TestMetricsWebContentsObserverEmbedder::IsPrerender(
+bool TestMetricsWebContentsObserverEmbedder::IsNoStatePrefetch(
content::WebContents* web_contents) {
return false;
}
diff --git a/chromium/components/page_load_metrics/browser/test_metrics_web_contents_observer_embedder.h b/chromium/components/page_load_metrics/browser/test_metrics_web_contents_observer_embedder.h
index ee48b81265b..3d5d546ae00 100644
--- a/chromium/components/page_load_metrics/browser/test_metrics_web_contents_observer_embedder.h
+++ b/chromium/components/page_load_metrics/browser/test_metrics_web_contents_observer_embedder.h
@@ -7,11 +7,11 @@
#include <vector>
-#include "base/optional.h"
#include "components/page_load_metrics/browser/page_load_metrics_embedder_interface.h"
#include "components/page_load_metrics/browser/page_load_metrics_observer.h"
#include "components/page_load_metrics/common/page_load_metrics.mojom.h"
#include "components/page_load_metrics/common/test/weak_mock_timer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace page_load_metrics {
@@ -29,7 +29,7 @@ class TestMetricsWebContentsObserverEmbedder
bool IsNewTabPageUrl(const GURL& url) override;
void RegisterObservers(PageLoadTracker* tracker) override;
std::unique_ptr<base::OneShotTimer> CreateTimer() override;
- bool IsPrerender(content::WebContents* web_contents) override;
+ bool IsNoStatePrefetch(content::WebContents* web_contents) override;
bool IsExtensionUrl(const GURL& url) override;
PageLoadMetricsMemoryTracker* GetMemoryTrackerForBrowserContext(
content::BrowserContext* browser_context) override;
@@ -59,11 +59,11 @@ class TestMetricsWebContentsObserverEmbedder
return observed_aborted_urls_;
}
- const std::vector<mojom::PageLoadFeatures>& observed_features() const {
+ const std::vector<blink::UseCounterFeature>& observed_features() const {
return observed_features_;
}
- const base::Optional<bool>& is_first_navigation_in_web_contents() const {
+ const absl::optional<bool>& is_first_navigation_in_web_contents() const {
return is_first_navigation_in_web_contents_;
}
@@ -89,8 +89,8 @@ class TestMetricsWebContentsObserverEmbedder
std::vector<GURL> observed_aborted_urls_;
std::vector<ExtraRequestCompleteInfo> loaded_resources_;
std::vector<GURL> completed_filtered_urls_;
- std::vector<mojom::PageLoadFeatures> observed_features_;
- base::Optional<bool> is_first_navigation_in_web_contents_;
+ std::vector<blink::UseCounterFeature> observed_features_;
+ absl::optional<bool> is_first_navigation_in_web_contents_;
bool is_ntp_ = false;
int count_on_enter_back_forward_cache_ = 0;
};
diff --git a/chromium/components/page_load_metrics/common/BUILD.gn b/chromium/components/page_load_metrics/common/BUILD.gn
index 3067a47192d..0979dbce915 100644
--- a/chromium/components/page_load_metrics/common/BUILD.gn
+++ b/chromium/components/page_load_metrics/common/BUILD.gn
@@ -46,8 +46,10 @@ mojom("page_load_metrics_mojom") {
public_deps = [
"//mojo/public/mojom/base",
"//third_party/blink/public/mojom:mobile_metrics",
- "//third_party/blink/public/mojom:web_feature_mojo_bindings",
+ "//third_party/blink/public/mojom:mojom_platform",
"//ui/gfx/geometry/mojom",
"//url/mojom:url_mojom_origin",
]
+ overridden_deps = [ "//third_party/blink/public/mojom:mojom_platform" ]
+ component_deps = [ "//third_party/blink/public/common" ]
}
diff --git a/chromium/components/page_load_metrics/common/page_end_reason.h b/chromium/components/page_load_metrics/common/page_end_reason.h
index bf618f80a75..d4e3b193999 100644
--- a/chromium/components/page_load_metrics/common/page_end_reason.h
+++ b/chromium/components/page_load_metrics/common/page_end_reason.h
@@ -11,9 +11,9 @@ namespace page_load_metrics {
// 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.
+// These values are persisted to logs and the history DB. 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). Pages that
// become hidden are logged in END_HIDDEN, so we expect low numbers in this
diff --git a/chromium/components/page_load_metrics/common/page_load_metrics.mojom b/chromium/components/page_load_metrics/common/page_load_metrics.mojom
index 1d8c2b9d2eb..bd509b67f0a 100644
--- a/chromium/components/page_load_metrics/common/page_load_metrics.mojom
+++ b/chromium/components/page_load_metrics/common/page_load_metrics.mojom
@@ -10,7 +10,7 @@ import "mojo/public/mojom/base/time.mojom";
import "third_party/blink/public/mojom/web_feature/web_feature.mojom";
import
"third_party/blink/public/mojom/mobile_metrics/mobile_friendliness.mojom";
-import "third_party/blink/public/mojom/use_counter/css_property_id.mojom";
+import "third_party/blink/public/mojom/use_counter/use_counter_feature.mojom";
import "url/mojom/origin.mojom";
// TimeDeltas below relative to navigation start.
@@ -163,6 +163,15 @@ struct PageLoadTiming {
// initiated by a link click in the renderer, or from the desktop omnibox.
mojo_base.mojom.TimeDelta? input_to_navigation_start;
+ // Time when the standard UserTiming mark `mark_fully_loaded` occurs.
+ mojo_base.mojom.TimeDelta? user_timing_mark_fully_loaded;
+
+ // Time when the standard UserTiming mark `mark_fully_visible` occurs.
+ mojo_base.mojom.TimeDelta? user_timing_mark_fully_visible;
+
+ // Time when the standard UserTiming mark `mark_interactive` occurs.
+ mojo_base.mojom.TimeDelta? user_timing_mark_interactive;
+
// If you add additional members, also be sure to update page_load_timing.h.
};
@@ -185,17 +194,6 @@ struct FrameMetadata {
FrameIntersectionUpdate? intersection_update;
};
-// 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.
@@ -293,6 +291,12 @@ struct FrameRenderDataUpdate {
// How many times LayoutNG-based LayoutObject::UpdateLayout() is called.
uint32 ng_layout_call_count_delta;
+ // How many LayoutNGFlexbox instances were created.
+ uint32 flexbox_ng_layout_block_count_delta;
+
+ // How many LayoutNGGrid instances were created.
+ uint32 grid_ng_layout_block_count_delta;
+
// New layout shifts with timestamps.
array<LayoutShift> new_layout_shifts;
@@ -343,7 +347,8 @@ interface PageLoadMetrics {
// Only called when at least one change has been observed within the frame.
UpdateTiming(PageLoadTiming page_load_timing,
FrameMetadata frame_metadata,
- PageLoadFeatures new_features,
+ // `new_features` will not contain any previously seen values.
+ array<blink.mojom.UseCounterFeature> new_features,
array<ResourceDataUpdate> resources,
FrameRenderDataUpdate render_data,
CpuTiming cpu_load_timing,
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
index 221bc589c0c..2eea75c292a 100644
--- a/chromium/components/page_load_metrics/common/page_load_metrics_constants.h
+++ b/chromium/components/page_load_metrics/common/page_load_metrics_constants.h
@@ -9,11 +9,6 @@
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;
-
const base::Feature kPageLoadMetricsTimerDelayFeature{
"PageLoadMetricsTimerDelay", base::FEATURE_DISABLED_BY_DEFAULT};
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
index 8768df8c82a..52431f68cd5 100644
--- a/chromium/components/page_load_metrics/common/page_load_metrics_util.cc
+++ b/chromium/components/page_load_metrics/common/page_load_metrics_util.cc
@@ -6,12 +6,32 @@
#include <algorithm>
+#include "base/metrics/field_trial_params.h"
#include "base/strings/string_util.h"
+#include "components/page_load_metrics/common/page_load_metrics_constants.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
namespace page_load_metrics {
-base::Optional<std::string> GetGoogleHostnamePrefix(const GURL& url) {
+namespace {
+
+// Default timer delay value. Can be overridden by field trial.
+const int kDefaultBufferTimerDelayMillis = 1000;
+
+// Maximum timer delay value.
+const int kMaxBufferTimerDelayMillis = 1000;
+
+// Additional delay for the browser timer relative to the renderer timer, to
+// allow for some variability in task queuing duration and IPC latency.
+const int kExtraBufferTimerDelayMillis = 50;
+
+// Parameter for the PageLoadMetricsTimerDelay feature which specifies a custom
+// timer delay value.
+const char* kBufferTimerDelayParamName = "BufferTimerDelayMillis";
+
+} // namespace
+
+absl::optional<std::string> GetGoogleHostnamePrefix(const GURL& url) {
const size_t registry_length =
net::registry_controlled_domains::GetRegistryLength(
url,
@@ -27,7 +47,7 @@ base::Optional<std::string> GetGoogleHostnamePrefix(const GURL& url) {
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>();
+ return absl::optional<std::string>();
}
// Removes the tld and the preceding dot.
@@ -39,7 +59,7 @@ base::Optional<std::string> GetGoogleHostnamePrefix(const GURL& url) {
if (!base::EndsWith(hostname_minus_registry, ".google",
base::CompareCase::INSENSITIVE_ASCII)) {
- return base::Optional<std::string>();
+ return absl::optional<std::string>();
}
return std::string(hostname_minus_registry.substr(
@@ -50,16 +70,30 @@ 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) {
+absl::optional<base::TimeDelta> OptionalMin(
+ const absl::optional<base::TimeDelta>& a,
+ const absl::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()));
+ return absl::optional<base::TimeDelta>(std::min(a.value(), b.value()));
+}
+
+int GetBufferTimerDelayMillis(TimerType timer_type) {
+ int result = base::GetFieldTrialParamByFeatureAsInt(
+ kPageLoadMetricsTimerDelayFeature, kBufferTimerDelayParamName,
+ kDefaultBufferTimerDelayMillis /* default value */);
+
+ DCHECK(timer_type == TimerType::kBrowser ||
+ timer_type == TimerType::kRenderer);
+ if (timer_type == TimerType::kBrowser) {
+ result += kExtraBufferTimerDelayMillis;
+ }
+
+ return std::min(result, kMaxBufferTimerDelayMillis);
}
} // 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
index 3958bd4118b..511ac29568d 100644
--- a/chromium/components/page_load_metrics/common/page_load_metrics_util.h
+++ b/chromium/components/page_load_metrics/common/page_load_metrics_util.h
@@ -7,8 +7,8 @@
#include <string>
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace page_load_metrics {
@@ -16,9 +16,9 @@ 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);
+absl::optional<base::TimeDelta> OptionalMin(
+ const absl::optional<base::TimeDelta>& a,
+ const absl::optional<base::TimeDelta>& b);
// Whether the given url has a google hostname.
bool IsGoogleHostname(const GURL& url);
@@ -33,7 +33,14 @@ bool IsGoogleHostname(const GURL& url);
// 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);
+absl::optional<std::string> GetGoogleHostnamePrefix(const GURL& url);
+
+// Distinguishes the renderer-side timer from the browser-side timer.
+enum class TimerType { kRenderer = 0, kBrowser = 1 };
+
+// Returns the maximum amount of time to delay dispatch of metrics updates
+// from the renderer process.
+int GetBufferTimerDelayMillis(TimerType timer_type);
} // namespace page_load_metrics
diff --git a/chromium/components/page_load_metrics/common/page_load_timing.cc b/chromium/components/page_load_metrics/common/page_load_timing.cc
index 09eae81d8e9..a480adabaae 100644
--- a/chromium/components/page_load_metrics/common/page_load_timing.cc
+++ b/chromium/components/page_load_metrics/common/page_load_timing.cc
@@ -8,16 +8,17 @@ namespace page_load_metrics {
mojom::PageLoadTimingPtr CreatePageLoadTiming() {
return mojom::PageLoadTiming::New(
- base::Time(), base::Optional<base::TimeDelta>(),
+ base::Time(), absl::optional<base::TimeDelta>(),
mojom::DocumentTiming::New(), mojom::InteractiveTiming::New(),
- mojom::PaintTiming::New(base::nullopt, base::nullopt, base::nullopt,
- base::nullopt,
+ mojom::PaintTiming::New(absl::nullopt, absl::nullopt, absl::nullopt,
+ absl::nullopt,
mojom::LargestContentfulPaintTiming::New(),
mojom::LargestContentfulPaintTiming::New(),
- base::nullopt, base::nullopt, base::nullopt),
+ absl::nullopt, absl::nullopt, absl::nullopt),
mojom::ParseTiming::New(),
std::vector<mojo::StructPtr<mojom::BackForwardCacheTiming>>{},
- base::Optional<base::TimeDelta>());
+ absl::optional<base::TimeDelta>(), absl::optional<base::TimeDelta>(),
+ absl::optional<base::TimeDelta>(), absl::optional<base::TimeDelta>());
}
bool IsEmpty(const page_load_metrics::mojom::DocumentTiming& timing) {
@@ -65,7 +66,10 @@ bool IsEmpty(const page_load_metrics::mojom::PageLoadTiming& timing) {
page_load_metrics::IsEmpty(*timing.paint_timing)) &&
(!timing.parse_timing ||
page_load_metrics::IsEmpty(*timing.parse_timing)) &&
- timing.back_forward_cache_timings.empty();
+ timing.back_forward_cache_timings.empty() &&
+ !timing.user_timing_mark_fully_loaded &&
+ !timing.user_timing_mark_fully_visible &&
+ !timing.user_timing_mark_interactive;
}
void InitPageLoadTimingForTest(mojom::PageLoadTiming* timing) {
diff --git a/chromium/components/page_load_metrics/common/page_load_timing.h b/chromium/components/page_load_metrics/common/page_load_timing.h
index 2520e20c4c7..7c55cd9333e 100644
--- a/chromium/components/page_load_metrics/common/page_load_timing.h
+++ b/chromium/components/page_load_metrics/common/page_load_timing.h
@@ -5,9 +5,8 @@
#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/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/loader/loading_behavior_flag.h"
namespace page_load_metrics {
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
index a68b1df5c37..23e52f67a51 100644
--- a/chromium/components/page_load_metrics/renderer/fake_page_timing_sender.cc
+++ b/chromium/components/page_load_metrics/renderer/fake_page_timing_sender.cc
@@ -6,6 +6,8 @@
#include <algorithm>
+#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace page_load_metrics {
@@ -18,7 +20,7 @@ FakePageTimingSender::~FakePageTimingSender() {}
void FakePageTimingSender::SendTiming(
const mojom::PageLoadTimingPtr& timing,
const mojom::FrameMetadataPtr& metadata,
- mojom::PageLoadFeaturesPtr new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
std::vector<mojom::ResourceDataUpdatePtr> resources,
const mojom::FrameRenderDataUpdate& render_data,
const mojom::CpuTimingPtr& cpu_timing,
@@ -107,49 +109,12 @@ void FakePageTimingSender::PageTimingValidator::VerifyExpectedCpuTimings()
}
void FakePageTimingSender::PageTimingValidator::UpdateExpectPageLoadFeatures(
- const blink::mojom::WebFeature feature) {
+ const blink::UseCounterFeature& 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";
+ EXPECT_THAT(actual_features_, ::testing::ContainerEq(expected_features_));
}
void FakePageTimingSender::PageTimingValidator::VerifyExpectedRenderData()
@@ -172,7 +137,7 @@ void FakePageTimingSender::PageTimingValidator::
void FakePageTimingSender::PageTimingValidator::UpdateTiming(
const mojom::PageLoadTimingPtr& timing,
const mojom::FrameMetadataPtr& metadata,
- const mojom::PageLoadFeaturesPtr& new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
const std::vector<mojom::ResourceDataUpdatePtr>& resources,
const mojom::FrameRenderDataUpdate& render_data,
const mojom::CpuTimingPtr& cpu_timing,
@@ -183,18 +148,13 @@ void FakePageTimingSender::PageTimingValidator::UpdateTiming(
if (!cpu_timing->task_time.is_zero()) {
actual_cpu_timings_.push_back(cpu_timing.Clone());
}
- for (const auto feature : new_features->features) {
+ for (const blink::UseCounterFeature& feature : new_features) {
EXPECT_EQ(actual_features_.find(feature), actual_features_.end())
- << "Feature " << feature << "has been sent more than once";
+ << "Feature " << feature.type() << ": " << feature.value()
+ << " 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;
actual_frame_intersection_update_ = metadata->intersection_update.Clone();
@@ -207,7 +167,6 @@ void FakePageTimingSender::PageTimingValidator::UpdateTiming(
VerifyExpectedTimings();
VerifyExpectedCpuTimings();
VerifyExpectedFeatures();
- VerifyExpectedCssProperties();
VerifyExpectedRenderData();
VerifyExpectedFrameIntersectionUpdate();
VerifyExpectedMobileFriendliness();
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
index c5da58eff6a..86db8f6a62e 100644
--- a/chromium/components/page_load_metrics/renderer/fake_page_timing_sender.h
+++ b/chromium/components/page_load_metrics/renderer/fake_page_timing_sender.h
@@ -11,6 +11,7 @@
#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"
+#include "third_party/blink/public/common/use_counter/use_counter_feature.h"
#include "third_party/blink/public/mojom/mobile_metrics/mobile_friendliness.mojom.h"
namespace page_load_metrics {
@@ -30,7 +31,7 @@ namespace page_load_metrics {
//
// 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
+// absl::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.
@@ -62,11 +63,7 @@ class FakePageTimingSender : public PageTimingSender {
// 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 UpdateExpectPageLoadFeatures(const blink::UseCounterFeature& feature);
void UpdateExpectFrameRenderDataUpdate(
const mojom::FrameRenderDataUpdate& render_data) {
@@ -86,9 +83,6 @@ class FakePageTimingSender : public PageTimingSender {
// 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;
void VerifyExpectedFrameIntersectionUpdate() const;
@@ -102,7 +96,7 @@ class FakePageTimingSender : public PageTimingSender {
void UpdateTiming(
const mojom::PageLoadTimingPtr& timing,
const mojom::FrameMetadataPtr& metadata,
- const mojom::PageLoadFeaturesPtr& new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
const std::vector<mojom::ResourceDataUpdatePtr>& resources,
const mojom::FrameRenderDataUpdate& render_data,
const mojom::CpuTimingPtr& cpu_timing,
@@ -115,10 +109,8 @@ class FakePageTimingSender : public PageTimingSender {
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_;
+ std::set<blink::UseCounterFeature> expected_features_;
+ std::set<blink::UseCounterFeature> actual_features_;
mojom::FrameRenderDataUpdatePtr expected_render_data_;
mojom::FrameRenderDataUpdate actual_render_data_;
mojom::FrameIntersectionUpdatePtr expected_frame_intersection_update_;
@@ -135,7 +127,7 @@ class FakePageTimingSender : public PageTimingSender {
void SendTiming(
const mojom::PageLoadTimingPtr& timing,
const mojom::FrameMetadataPtr& metadata,
- mojom::PageLoadFeaturesPtr new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
std::vector<mojom::ResourceDataUpdatePtr> resources,
const mojom::FrameRenderDataUpdate& render_data,
const mojom::CpuTimingPtr& cpu_timing,
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
index 3829ddc7743..534488730de 100644
--- a/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.cc
+++ b/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.cc
@@ -52,7 +52,7 @@ class MojoPageTimingSender : public PageTimingSender {
void SendTiming(
const mojom::PageLoadTimingPtr& timing,
const mojom::FrameMetadataPtr& metadata,
- mojom::PageLoadFeaturesPtr new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
std::vector<mojom::ResourceDataUpdatePtr> resources,
const mojom::FrameRenderDataUpdate& render_data,
const mojom::CpuTimingPtr& cpu_timing,
@@ -62,7 +62,7 @@ class MojoPageTimingSender : public PageTimingSender {
DCHECK(page_load_metrics_);
page_load_metrics_->UpdateTiming(
limited_sending_mode_ ? CreatePageLoadTiming() : timing->Clone(),
- metadata->Clone(), std::move(new_features), std::move(resources),
+ metadata->Clone(), new_features, std::move(resources),
render_data.Clone(), cpu_timing->Clone(),
std::move(new_deferred_resource_data), std::move(input_timing_delta),
std::move(mobile_friendliness));
@@ -126,20 +126,11 @@ void MetricsRenderFrameObserver::DidObserveLoadingBehavior(
}
void MetricsRenderFrameObserver::DidObserveNewFeatureUsage(
- blink::mojom::WebFeature feature) {
+ const blink::UseCounterFeature& 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) {
@@ -156,13 +147,17 @@ void MetricsRenderFrameObserver::DidObserveInputForLayoutShiftTracking(
}
}
-void MetricsRenderFrameObserver::DidObserveLayoutNg(uint32_t all_block_count,
- uint32_t ng_block_count,
- uint32_t all_call_count,
- uint32_t ng_call_count) {
+void MetricsRenderFrameObserver::DidObserveLayoutNg(
+ uint32_t all_block_count,
+ uint32_t ng_block_count,
+ uint32_t all_call_count,
+ uint32_t ng_call_count,
+ uint32_t flexbox_ng_block_count,
+ uint32_t grid_ng_block_count) {
if (page_timing_metrics_sender_)
page_timing_metrics_sender_->DidObserveLayoutNg(
- all_block_count, ng_block_count, all_call_count, ng_call_count);
+ all_block_count, ng_block_count, all_call_count, ng_call_count,
+ flexbox_ng_block_count, grid_ng_block_count);
}
void MetricsRenderFrameObserver::DidObserveLazyLoadBehavior(
@@ -259,7 +254,7 @@ void MetricsRenderFrameObserver::WillDetach() {
void MetricsRenderFrameObserver::DidStartNavigation(
const GURL& url,
- base::Optional<blink::WebNavigationType> navigation_type) {
+ absl::optional<blink::WebNavigationType> navigation_type) {
// Send current metrics, as we might create a new RenderFrame later due to
// this navigation (that might end up in a different process entirely, and
// won't notify us until the current RenderFrameHost in the browser changed).
@@ -543,7 +538,7 @@ MetricsRenderFrameObserver::Timing MetricsRenderFrameObserver::GetTiming()
for (const auto& restore_timing : restore_timings) {
double navigation_start = restore_timing.navigation_start;
double first_paint = restore_timing.first_paint;
- base::Optional<base::TimeDelta> first_input_delay =
+ absl::optional<base::TimeDelta> first_input_delay =
restore_timing.first_input_delay;
auto back_forward_cache_timing = mojom::BackForwardCacheTiming::New();
@@ -668,6 +663,15 @@ MetricsRenderFrameObserver::Timing MetricsRenderFrameObserver::GetTiming()
*perf.LastPortalActivatedPaint();
}
+ if (perf.UserTimingMarkFullyLoaded().has_value())
+ timing->user_timing_mark_fully_loaded = perf.UserTimingMarkFullyLoaded();
+
+ if (perf.UserTimingMarkFullyVisible().has_value())
+ timing->user_timing_mark_fully_visible = perf.UserTimingMarkFullyVisible();
+
+ if (perf.UserTimingMarkInteractive().has_value())
+ timing->user_timing_mark_interactive = perf.UserTimingMarkInteractive();
+
return Timing(std::move(timing), monotonic_timing);
}
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
index 82e12625fe6..ed2bf9afc01 100644
--- a/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.h
+++ b/chromium/components/page_load_metrics/renderer/metrics_render_frame_observer.h
@@ -47,16 +47,17 @@ class MetricsRenderFrameObserver
void DidObserveInputDelay(base::TimeDelta input_delay) override;
void DidChangeCpuTiming(base::TimeDelta time) override;
void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior) override;
- void DidObserveNewFeatureUsage(blink::mojom::WebFeature feature) override;
- void DidObserveNewCssPropertyUsage(blink::mojom::CSSSampleId css_property,
- bool is_animated) override;
+ void DidObserveNewFeatureUsage(
+ const blink::UseCounterFeature& feature) override;
void DidObserveLayoutShift(double score, bool after_input_or_scroll) override;
void DidObserveInputForLayoutShiftTracking(
base::TimeTicks timestamp) override;
void DidObserveLayoutNg(uint32_t all_block_count,
uint32_t ng_block_count,
uint32_t all_call_count,
- uint32_t ng_call_count) override;
+ uint32_t ng_call_count,
+ uint32_t flexbox_ng_block_count,
+ uint32_t grid_ng_block_count) override;
void DidObserveLazyLoadBehavior(
blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) override;
void DidStartResponse(const GURL& response_url,
@@ -77,7 +78,7 @@ class MetricsRenderFrameObserver
bool from_archive) override;
void DidStartNavigation(
const GURL& url,
- base::Optional<blink::WebNavigationType> navigation_type) override;
+ absl::optional<blink::WebNavigationType> navigation_type) override;
void DidSetPageLifecycleState() override;
void ReadyToCommitNavigation(
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
index a4789646bb0..5da6c0352fe 100644
--- 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
@@ -87,7 +87,7 @@ TEST_F(MetricsRenderFrameObserverTest, SingleMetric) {
page_load_metrics::InitPageLoadTimingForTest(&timing);
timing.navigation_start = nav_start;
observer.ExpectPageLoadTiming(timing);
- observer.DidStartNavigation(GURL(), base::nullopt);
+ observer.DidStartNavigation(GURL(), absl::nullopt);
observer.ReadyToCommitNavigation(nullptr);
observer.DidCommitProvisionalLoad(ui::PAGE_TRANSITION_LINK);
observer.GetMockTimer()->Fire();
@@ -110,7 +110,7 @@ TEST_F(MetricsRenderFrameObserverTest, SingleCpuMetric) {
page_load_metrics::InitPageLoadTimingForTest(&timing);
timing.navigation_start = nav_start;
observer.ExpectPageLoadTiming(timing);
- observer.DidStartNavigation(GURL(), base::nullopt);
+ observer.DidStartNavigation(GURL(), absl::nullopt);
observer.ReadyToCommitNavigation(nullptr);
observer.DidCommitProvisionalLoad(ui::PAGE_TRANSITION_LINK);
@@ -132,7 +132,7 @@ TEST_F(MetricsRenderFrameObserverTest, MultipleMetrics) {
page_load_metrics::InitPageLoadTimingForTest(&timing);
timing.navigation_start = nav_start;
observer.ExpectPageLoadTiming(timing);
- observer.DidStartNavigation(GURL(), base::nullopt);
+ observer.DidStartNavigation(GURL(), absl::nullopt);
observer.ReadyToCommitNavigation(nullptr);
observer.DidCommitProvisionalLoad(ui::PAGE_TRANSITION_LINK);
observer.GetMockTimer()->Fire();
@@ -178,7 +178,7 @@ TEST_F(MetricsRenderFrameObserverTest, MultipleNavigations) {
page_load_metrics::InitPageLoadTimingForTest(&timing);
timing.navigation_start = nav_start;
observer.ExpectPageLoadTiming(timing);
- observer.DidStartNavigation(GURL(), base::nullopt);
+ observer.DidStartNavigation(GURL(), absl::nullopt);
observer.ReadyToCommitNavigation(nullptr);
observer.DidCommitProvisionalLoad(ui::PAGE_TRANSITION_LINK);
observer.GetMockTimer()->Fire();
@@ -204,7 +204,7 @@ TEST_F(MetricsRenderFrameObserverTest, MultipleNavigations) {
observer.SetMockTimer(nullptr);
observer.ExpectPageLoadTiming(timing_2);
- observer.DidStartNavigation(GURL(), base::nullopt);
+ observer.DidStartNavigation(GURL(), absl::nullopt);
observer.ReadyToCommitNavigation(nullptr);
observer.DidCommitProvisionalLoad(ui::PAGE_TRANSITION_LINK);
observer.GetMockTimer()->Fire();
diff --git a/chromium/components/page_load_metrics/renderer/page_timing_metadata_recorder.h b/chromium/components/page_load_metrics/renderer/page_timing_metadata_recorder.h
index 3d8ee63f192..6bf38a9a2c8 100644
--- a/chromium/components/page_load_metrics/renderer/page_timing_metadata_recorder.h
+++ b/chromium/components/page_load_metrics/renderer/page_timing_metadata_recorder.h
@@ -5,8 +5,8 @@
#ifndef COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_TIMING_METADATA_RECORDER_H_
#define COMPONENTS_PAGE_LOAD_METRICS_RENDERER_PAGE_TIMING_METADATA_RECORDER_H_
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace page_load_metrics {
@@ -25,8 +25,8 @@ class PageTimingMetadataRecorder {
MonotonicTiming(MonotonicTiming&&);
MonotonicTiming& operator=(MonotonicTiming&&);
- base::Optional<base::TimeTicks> navigation_start;
- base::Optional<base::TimeTicks> first_contentful_paint;
+ absl::optional<base::TimeTicks> navigation_start;
+ absl::optional<base::TimeTicks> first_contentful_paint;
};
PageTimingMetadataRecorder(const MonotonicTiming& initial_timing);
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
index d7be2af71da..a660f737ba2 100644
--- a/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.cc
+++ b/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.cc
@@ -10,14 +10,15 @@
#include "base/callback.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/page_load_metrics/common/page_load_metrics.mojom.h"
-#include "components/page_load_metrics/common/page_load_metrics_constants.h"
+#include "components/page_load_metrics/common/page_load_metrics_util.h"
#include "components/page_load_metrics/renderer/page_timing_sender.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/blink/public/mojom/use_counter/use_counter_feature.mojom-shared.h"
+#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h"
#include "ui/gfx/geometry/rect.h"
namespace page_load_metrics {
@@ -44,17 +45,13 @@ PageTimingMetricsSender::PageTimingMetricsSender(
last_cpu_timing_(mojom::CpuTiming::New()),
input_timing_delta_(mojom::InputTiming::New()),
metadata_(mojom::FrameMetadata::New()),
- new_features_(mojom::PageLoadFeatures::New()),
new_deferred_resource_data_(mojom::DeferredResourceCounts::New()),
- buffer_timer_delay_ms_(kBufferTimerDelayMillis),
+ buffer_timer_delay_ms_(GetBufferTimerDelayMillis(TimerType::kRenderer)),
metadata_recorder_(initial_monotonic_timing) {
const auto resource_id = initial_request->resource_id();
page_resource_data_use_.emplace(
std::piecewise_construct, std::forward_as_tuple(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();
}
@@ -77,29 +74,12 @@ void PageTimingMetricsSender::DidObserveLoadingBehavior(
}
void PageTimingMetricsSender::DidObserveNewFeatureUsage(
- blink::mojom::WebFeature feature) {
- size_t feature_id = static_cast<size_t>(feature);
- if (features_sent_.test(feature_id)) {
+ const blink::UseCounterFeature& feature) {
+ if (feature_tracker_.TestAndSet(feature))
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();
- }
+ new_features_.push_back(feature);
+ EnsureSendTimer();
}
void PageTimingMetricsSender::DidObserveLayoutShift(
@@ -124,14 +104,19 @@ void PageTimingMetricsSender::DidObserveInputForLayoutShiftTracking(
EnsureSendTimer();
}
-void PageTimingMetricsSender::DidObserveLayoutNg(uint32_t all_block_count,
- uint32_t ng_block_count,
- uint32_t all_call_count,
- uint32_t ng_call_count) {
+void PageTimingMetricsSender::DidObserveLayoutNg(
+ uint32_t all_block_count,
+ uint32_t ng_block_count,
+ uint32_t all_call_count,
+ uint32_t ng_call_count,
+ uint32_t flexbox_ng_block_count,
+ uint32_t grid_ng_block_count) {
render_data_.all_layout_block_count_delta += all_block_count;
render_data_.ng_layout_block_count_delta += ng_block_count;
render_data_.all_layout_call_count_delta += all_call_count;
render_data_.ng_layout_call_count_delta += ng_call_count;
+ render_data_.flexbox_ng_layout_block_count_delta += flexbox_ng_block_count;
+ render_data_.grid_ng_layout_block_count_delta += grid_ng_block_count;
EnsureSendTimer();
}
@@ -355,7 +340,7 @@ void PageTimingMetricsSender::SendNow() {
std::move(input_timing_delta_), mobile_friendliness_);
input_timing_delta_ = mojom::InputTiming::New();
new_deferred_resource_data_ = mojom::DeferredResourceCounts::New();
- new_features_ = mojom::PageLoadFeatures::New();
+ new_features_.clear();
metadata_->intersection_update.reset();
last_cpu_timing_->task_time = base::TimeDelta();
modified_resources_.clear();
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
index 9d786a85fc9..826c5130aa4 100644
--- a/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.h
+++ b/chromium/components/page_load_metrics/renderer/page_timing_metrics_sender.h
@@ -5,7 +5,6 @@
#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"
@@ -17,8 +16,7 @@
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
#include "third_party/blink/public/common/loader/loading_behavior_flag.h"
#include "third_party/blink/public/common/loader/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/common/use_counter/use_counter_feature_tracker.h"
#include "third_party/blink/public/web/web_local_frame_client.h"
class GURL;
@@ -49,15 +47,15 @@ class PageTimingMetricsSender {
~PageTimingMetricsSender();
void DidObserveLoadingBehavior(blink::LoadingBehaviorFlag behavior);
- void DidObserveNewFeatureUsage(blink::mojom::WebFeature feature);
- void DidObserveNewCssPropertyUsage(blink::mojom::CSSSampleId css_property,
- bool is_animated);
+ void DidObserveNewFeatureUsage(const blink::UseCounterFeature& feature);
void DidObserveLayoutShift(double score, bool after_input_or_scroll);
void DidObserveInputForLayoutShiftTracking(base::TimeTicks timestamp);
void DidObserveLayoutNg(uint32_t all_block_count,
uint32_t ng_block_count,
uint32_t all_call_count,
- uint32_t ng_call_count);
+ uint32_t ng_call_count,
+ uint32_t flexbox_ng_block_count,
+ uint32_t grid_ng_block_count);
void DidObserveLazyLoadBehavior(
blink::WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior);
void DidObserveMobileFriendlinessChanged(const blink::MobileFriendliness&);
@@ -115,16 +113,11 @@ class PageTimingMetricsSender {
mojom::FrameMetadataPtr metadata_;
// A list of newly observed features during page load, to be sent to the
// browser.
- mojom::PageLoadFeaturesPtr new_features_;
+ std::vector<blink::UseCounterFeature> 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_;
+ blink::UseCounterFeatureTracker feature_tracker_;
bool have_sent_ipc_ = false;
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
index d87aa50bbd9..672022d5024 100644
--- 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
@@ -9,6 +9,8 @@
#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"
+#include "third_party/blink/public/common/use_counter/use_counter_feature.h"
+#include "third_party/blink/public/mojom/use_counter/use_counter_feature.mojom-shared.h"
using CSSSampleId = blink::mojom::CSSSampleId;
@@ -184,7 +186,8 @@ TEST_F(PageTimingMetricsSenderTest, SendMobileFriendlinessEvents) {
TEST_F(PageTimingMetricsSenderTest, SendSingleFeature) {
mojom::PageLoadTiming timing;
InitPageLoadTimingForTest(&timing);
- blink::mojom::WebFeature feature = blink::mojom::WebFeature::kFetch;
+ blink::UseCounterFeature feature = {
+ blink::mojom::UseCounterFeatureType::kWebFeature, 0};
metrics_sender_->Update(timing.Clone(),
PageTimingMetadataRecorder::MonotonicTiming());
@@ -200,9 +203,12 @@ TEST_F(PageTimingMetricsSenderTest, SendSingleFeature) {
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;
+ blink::UseCounterFeature feature_0 = {
+ blink::mojom::UseCounterFeatureType::kWebFeature, 0};
+ blink::UseCounterFeature feature_1 = {
+ blink::mojom::UseCounterFeatureType::kCssProperty, 1};
+ blink::UseCounterFeature feature_2 = {
+ blink::mojom::UseCounterFeatureType::kAnimatedCssProperty, 2};
metrics_sender_->Update(timing.Clone(),
PageTimingMetadataRecorder::MonotonicTiming());
@@ -213,6 +219,9 @@ TEST_F(PageTimingMetricsSenderTest, SendMultipleFeatures) {
// Observe the second feature, update expected features sent across IPC.
metrics_sender_->DidObserveNewFeatureUsage(feature_1);
validator_.UpdateExpectPageLoadFeatures(feature_1);
+ // Observe the third feature, update expected features sent across IPC.
+ metrics_sender_->DidObserveNewFeatureUsage(feature_2);
+ validator_.UpdateExpectPageLoadFeatures(feature_2);
// Fire the timer to trigger sending of features via an SendTiming call.
metrics_sender_->mock_timer()->Fire();
validator_.VerifyExpectedFeatures();
@@ -221,7 +230,8 @@ TEST_F(PageTimingMetricsSenderTest, SendMultipleFeatures) {
TEST_F(PageTimingMetricsSenderTest, SendDuplicatedFeatures) {
mojom::PageLoadTiming timing;
InitPageLoadTimingForTest(&timing);
- blink::mojom::WebFeature feature = blink::mojom::WebFeature::kFetch;
+ blink::UseCounterFeature feature = {
+ blink::mojom::UseCounterFeatureType::kWebFeature, 0};
metrics_sender_->Update(timing.Clone(),
PageTimingMetadataRecorder::MonotonicTiming());
@@ -239,10 +249,12 @@ TEST_F(PageTimingMetricsSenderTest, SendDuplicatedFeatures) {
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;
+ blink::UseCounterFeature feature_0 = {
+ blink::mojom::UseCounterFeatureType::kWebFeature, 0};
+ blink::UseCounterFeature feature_1 = {
+ blink::mojom::UseCounterFeatureType::kCssProperty, 1};
+ blink::UseCounterFeature feature_2 = {
+ blink::mojom::UseCounterFeatureType::kAnimatedCssProperty, 2};
metrics_sender_->Update(timing.Clone(),
PageTimingMetadataRecorder::MonotonicTiming());
@@ -281,132 +293,6 @@ TEST_F(PageTimingMetricsSenderTest, SendMultipleFeaturesTwice) {
validator_.VerifyExpectedFeatures();
}
-TEST_F(PageTimingMetricsSenderTest, SendSingleCssProperty) {
- mojom::PageLoadTiming timing;
- InitPageLoadTimingForTest(&timing);
-
- metrics_sender_->Update(timing.Clone(),
- PageTimingMetadataRecorder::MonotonicTiming());
- 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_->Update(timing.Clone(),
- PageTimingMetadataRecorder::MonotonicTiming());
- 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_->Update(timing.Clone(),
- PageTimingMetadataRecorder::MonotonicTiming());
- 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_->Update(timing.Clone(),
- PageTimingMetadataRecorder::MonotonicTiming());
- 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_->Update(timing.Clone(),
- PageTimingMetadataRecorder::MonotonicTiming());
- 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_->Update(timing.Clone(),
- PageTimingMetadataRecorder::MonotonicTiming());
- 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);
@@ -421,11 +307,12 @@ TEST_F(PageTimingMetricsSenderTest, SendPageRenderData) {
metrics_sender_->DidObserveLayoutShift(0.5, false);
metrics_sender_->DidObserveLayoutShift(0.5, false);
- metrics_sender_->DidObserveLayoutNg(3, 2, 10, 4);
- metrics_sender_->DidObserveLayoutNg(2, 0, 7, 5);
+ metrics_sender_->DidObserveLayoutNg(3, 2, 10, 4, 9, 11);
+ metrics_sender_->DidObserveLayoutNg(2, 0, 7, 5, 13, 15);
metrics_sender_->DidObserveLayoutShift(0.5, true);
- mojom::FrameRenderDataUpdate render_data(1.5, 1.0, 5, 2, 17, 9, {}, {});
+ mojom::FrameRenderDataUpdate render_data(1.5, 1.0, 5, 2, 17, 9, 21, 26, {},
+ {});
validator_.UpdateExpectFrameRenderDataUpdate(render_data);
metrics_sender_->mock_timer()->Fire();
diff --git a/chromium/components/page_load_metrics/renderer/page_timing_sender.h b/chromium/components/page_load_metrics/renderer/page_timing_sender.h
index ca7cfa29cdb..124af2e3f2c 100644
--- a/chromium/components/page_load_metrics/renderer/page_timing_sender.h
+++ b/chromium/components/page_load_metrics/renderer/page_timing_sender.h
@@ -17,7 +17,7 @@ class PageTimingSender {
virtual void SendTiming(
const mojom::PageLoadTimingPtr& timing,
const mojom::FrameMetadataPtr& metadata,
- mojom::PageLoadFeaturesPtr new_features,
+ const std::vector<blink::UseCounterFeature>& new_features,
std::vector<mojom::ResourceDataUpdatePtr> resources,
const mojom::FrameRenderDataUpdate& render_data,
const mojom::CpuTimingPtr& cpu_timing,
diff --git a/chromium/components/paint_preview/OWNERS b/chromium/components/paint_preview/OWNERS
index f14326f08eb..a56f4c78c0c 100644
--- a/chromium/components/paint_preview/OWNERS
+++ b/chromium/components/paint_preview/OWNERS
@@ -1,4 +1,3 @@
ckitagawa@chromium.org
-mahmoudi@chromium.org
-vollick@chromium.org
+fredmello@chromium.org
yfriedman@chromium.org
diff --git a/chromium/components/paint_preview/browser/file_manager.cc b/chromium/components/paint_preview/browser/file_manager.cc
index 1d84ee21d11..4a84cdafb39 100644
--- a/chromium/components/paint_preview/browser/file_manager.cc
+++ b/chromium/components/paint_preview/browser/file_manager.cc
@@ -63,16 +63,16 @@ size_t FileManager::GetSizeOfArtifacts(const DirectoryKey& key) const {
}
}
-base::Optional<base::File::Info> FileManager::GetInfo(
+absl::optional<base::File::Info> FileManager::GetInfo(
const DirectoryKey& key) const {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
base::FilePath path;
StorageType storage_type = GetPathForKey(key, &path);
if (storage_type == FileManager::StorageType::kNone)
- return base::nullopt;
+ return absl::nullopt;
base::File::Info info;
if (!base::GetFileInfo(path, &info))
- return base::nullopt;
+ return absl::nullopt;
return info;
}
@@ -101,7 +101,7 @@ bool FileManager::CaptureExists(const DirectoryKey& key) const {
}
}
-base::Optional<base::FilePath> FileManager::CreateOrGetDirectory(
+absl::optional<base::FilePath> FileManager::CreateOrGetDirectory(
const DirectoryKey& key,
bool clear) const {
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
@@ -119,7 +119,7 @@ base::Optional<base::FilePath> FileManager::CreateOrGetDirectory(
}
DVLOG(1) << "ERROR: failed to create directory: " << path
<< " with error code " << error;
- return base::nullopt;
+ return absl::nullopt;
}
case kDirectory:
return path;
@@ -129,17 +129,17 @@ base::Optional<base::FilePath> FileManager::CreateOrGetDirectory(
if (!base::CreateDirectoryAndGetError(dst_path, &error)) {
DVLOG(1) << "ERROR: failed to create directory: " << path
<< " with error code " << error;
- return base::nullopt;
+ return absl::nullopt;
}
if (!zip::Unzip(path, dst_path)) {
DVLOG(1) << "ERROR: failed to unzip: " << path << " to " << dst_path;
- return base::nullopt;
+ return absl::nullopt;
}
base::DeletePathRecursively(path);
return dst_path;
}
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
diff --git a/chromium/components/paint_preview/browser/file_manager.h b/chromium/components/paint_preview/browser/file_manager.h
index 5fa5c55761e..67a0c6dec2e 100644
--- a/chromium/components/paint_preview/browser/file_manager.h
+++ b/chromium/components/paint_preview/browser/file_manager.h
@@ -10,7 +10,6 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
-#include "base/time/time.h"
#include "components/paint_preview/browser/directory_key.h"
#include "components/paint_preview/common/proto/paint_preview.pb.h"
#include "url/gurl.h"
@@ -52,7 +51,7 @@ class FileManager : public base::RefCountedThreadSafe<FileManager> {
// Get statistics about the time of creation and size of artifacts.
size_t GetSizeOfArtifacts(const DirectoryKey& key) const;
- base::Optional<base::File::Info> GetInfo(const DirectoryKey& key) const;
+ absl::optional<base::File::Info> GetInfo(const DirectoryKey& key) const;
// Returns the total disk usage of all paint previews.
size_t GetTotalDiskUsage() const;
@@ -68,7 +67,7 @@ class FileManager : public base::RefCountedThreadSafe<FileManager> {
// assigns it to |directory|. The directory will be wiped if |clear| is true.
// Returns a path on success or nullopt on failure. If the directory was
// compressed then it will be uncompressed automatically.
- base::Optional<base::FilePath> CreateOrGetDirectory(const DirectoryKey& key,
+ absl::optional<base::FilePath> CreateOrGetDirectory(const DirectoryKey& key,
bool clear) const;
// Compresses the directory associated with |key|. Returns true on success or
diff --git a/chromium/components/paint_preview/browser/paint_preview_base_service.cc b/chromium/components/paint_preview/browser/paint_preview_base_service.cc
index 3181d624f78..9d12df92980 100644
--- a/chromium/components/paint_preview/browser/paint_preview_base_service.cc
+++ b/chromium/components/paint_preview/browser/paint_preview_base_service.cc
@@ -60,6 +60,10 @@ void PaintPreviewBaseService::CapturePaintPreview(CaptureParams capture_params,
(render_frame_host == web_contents->GetMainFrame());
params.inner.capture_links = capture_params.capture_links;
params.inner.max_capture_size = capture_params.max_per_capture_size;
+ params.inner.max_decoded_image_size_bytes =
+ capture_params.max_decoded_image_size_bytes;
+ params.inner.skip_accelerated_content =
+ capture_params.skip_accelerated_content;
// TODO(crbug/1064253): Consider moving to client so that this always happens.
// Although, it is harder to get this right in the client due to its
diff --git a/chromium/components/paint_preview/browser/paint_preview_base_service.h b/chromium/components/paint_preview/browser/paint_preview_base_service.h
index 84818fab236..2d742add21d 100644
--- a/chromium/components/paint_preview/browser/paint_preview_base_service.h
+++ b/chromium/components/paint_preview/browser/paint_preview_base_service.h
@@ -11,7 +11,6 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
@@ -24,6 +23,7 @@
#include "components/paint_preview/common/proto/paint_preview.pb.h"
#include "components/paint_preview/common/serialized_recording.h"
#include "content/public/browser/web_contents.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace paint_preview {
@@ -85,6 +85,22 @@ class PaintPreviewBaseService : public KeyedService {
// Cap the perframe SkPicture size to |max_per_capture_size| if non-zero.
size_t max_per_capture_size;
+
+ // Limit on the maximum size of a decoded image that can be serialized.
+ // Any images with a decoded size exceeding this value will be discarded.
+ // This can be used to reduce the chance of an OOM during serialization and
+ // later during playback.
+ uint64_t max_decoded_image_size_bytes{std::numeric_limits<uint64_t>::max()};
+
+ // This flag will skip GPU accelerated content where applicable when
+ // capturing. This reduces hangs, capture time and may also reduce OOM
+ // crashes, but results in a lower fideltiy capture (i.e. the contents
+ // captured may not accurately reflect the content visible to the user at
+ // time of capture).
+ //
+ // At present this flag:
+ // - Shows a poster or blank space instead of live video frames.
+ bool skip_accelerated_content{false};
};
using OnCapturedCallback =
@@ -132,8 +148,8 @@ class PaintPreviewBaseService : public KeyedService {
mojom::PaintPreviewStatus status,
std::unique_ptr<CaptureResult> result);
- std::unique_ptr<PaintPreviewFileMixin> file_mixin_ = nullptr;
- std::unique_ptr<PaintPreviewPolicy> policy_ = nullptr;
+ std::unique_ptr<PaintPreviewFileMixin> file_mixin_;
+ std::unique_ptr<PaintPreviewPolicy> policy_;
bool is_off_the_record_;
base::WeakPtrFactory<PaintPreviewBaseService> weak_ptr_factory_{this};
diff --git a/chromium/components/paint_preview/browser/paint_preview_base_service_unittest.cc b/chromium/components/paint_preview/browser/paint_preview_base_service_unittest.cc
index 002447566c7..dcbde0b22ed 100644
--- a/chromium/components/paint_preview/browser/paint_preview_base_service_unittest.cc
+++ b/chromium/components/paint_preview/browser/paint_preview_base_service_unittest.cc
@@ -64,7 +64,7 @@ base::FilePath CreateDir(scoped_refptr<FileManager> manager,
base::BindOnce(&FileManager::CreateOrGetDirectory, manager, key, false),
base::BindOnce(
[](base::OnceClosure quit, base::FilePath* out,
- const base::Optional<base::FilePath>& path) {
+ const absl::optional<base::FilePath>& path) {
EXPECT_TRUE(path.has_value());
EXPECT_FALSE(path->empty());
*out = path.value();
@@ -178,7 +178,8 @@ class PaintPreviewBaseServiceTest
RecordingPersistence persistence,
gfx::Rect clip_rect,
bool capture_links,
- size_t max_per_capture_size) {
+ size_t max_per_capture_size,
+ uint64_t max_decoded_image_size_bytes) {
PaintPreviewBaseService::CaptureParams capture_params;
capture_params.web_contents = web_contents;
capture_params.root_dir = root_dir;
@@ -186,12 +187,13 @@ class PaintPreviewBaseServiceTest
capture_params.clip_rect = clip_rect;
capture_params.capture_links = capture_links;
capture_params.max_per_capture_size = max_per_capture_size;
+ capture_params.max_decoded_image_size_bytes = max_decoded_image_size_bytes;
return capture_params;
}
private:
- std::unique_ptr<SimpleFactoryKey> key_ = nullptr;
- std::unique_ptr<SimpleFactoryKey> rejection_policy_key_ = nullptr;
+ std::unique_ptr<SimpleFactoryKey> key_;
+ std::unique_ptr<SimpleFactoryKey> rejection_policy_key_;
};
TEST_P(PaintPreviewBaseServiceTest, CaptureMainFrame) {
@@ -200,9 +202,10 @@ TEST_P(PaintPreviewBaseServiceTest, CaptureMainFrame) {
params->clip_rect = gfx::Rect(0, 0, 0, 0);
params->is_main_frame = true;
params->max_capture_size = 50;
+ params->max_decoded_image_size_bytes = 1000;
recorder.SetExpectedParams(std::move(params));
auto response = mojom::PaintPreviewCaptureResponse::New();
- response->embedding_token = base::nullopt;
+ response->embedding_token = absl::nullopt;
if (GetParam() == RecordingPersistence::kMemoryBuffer) {
response->skp.emplace(mojo_base::BigBuffer());
}
@@ -218,7 +221,7 @@ TEST_P(PaintPreviewBaseServiceTest, CaptureMainFrame) {
base::RunLoop loop;
service->CapturePaintPreview(
CreateCaptureParams(web_contents(), &path, GetParam(),
- gfx::Rect(0, 0, 0, 0), true, 50),
+ gfx::Rect(0, 0, 0, 0), true, 50, 1000),
base::BindOnce(
[](base::OnceClosure quit_closure,
PaintPreviewBaseService::CaptureStatus expected_status,
@@ -273,7 +276,7 @@ TEST_P(PaintPreviewBaseServiceTest, CaptureFailed) {
params->max_capture_size = 0;
recorder.SetExpectedParams(std::move(params));
auto response = mojom::PaintPreviewCaptureResponse::New();
- response->embedding_token = base::nullopt;
+ response->embedding_token = absl::nullopt;
recorder.SetResponse(mojom::PaintPreviewStatus::kFailed, std::move(response));
OverrideInterface(&recorder);
@@ -286,7 +289,8 @@ TEST_P(PaintPreviewBaseServiceTest, CaptureFailed) {
base::RunLoop loop;
service->CapturePaintPreview(
CreateCaptureParams(web_contents(), &path, GetParam(),
- gfx::Rect(0, 0, 0, 0), true, 0),
+ gfx::Rect(0, 0, 0, 0), true, 0,
+ std::numeric_limits<uint64_t>::max()),
base::BindOnce(
[](base::OnceClosure quit_closure,
PaintPreviewBaseService::CaptureStatus expected_status,
@@ -309,7 +313,7 @@ TEST_P(PaintPreviewBaseServiceTest, CaptureDisallowed) {
params->max_capture_size = 0;
recorder.SetExpectedParams(std::move(params));
auto response = mojom::PaintPreviewCaptureResponse::New();
- response->embedding_token = base::nullopt;
+ response->embedding_token = absl::nullopt;
recorder.SetResponse(mojom::PaintPreviewStatus::kFailed, std::move(response));
OverrideInterface(&recorder);
@@ -322,7 +326,8 @@ TEST_P(PaintPreviewBaseServiceTest, CaptureDisallowed) {
base::RunLoop loop;
service->CapturePaintPreview(
CreateCaptureParams(web_contents(), &path, GetParam(),
- gfx::Rect(0, 0, 0, 0), true, 0),
+ gfx::Rect(0, 0, 0, 0), true, 0,
+ std::numeric_limits<uint64_t>::max()),
base::BindOnce(
[](base::OnceClosure quit_closure,
PaintPreviewBaseService::CaptureStatus expected_status,
diff --git a/chromium/components/paint_preview/browser/paint_preview_client.cc b/chromium/components/paint_preview/browser/paint_preview_client.cc
index d51d2ae76a3..7232b9be21b 100644
--- a/chromium/components/paint_preview/browser/paint_preview_client.cc
+++ b/chromium/components/paint_preview/browser/paint_preview_client.cc
@@ -15,6 +15,7 @@
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
+#include "base/trace_event/trace_event.h"
#include "base/unguessable_token.h"
#include "components/paint_preview/common/capture_result.h"
#include "components/paint_preview/common/mojom/paint_preview_recorder.mojom-forward.h"
@@ -117,8 +118,12 @@ mojom::PaintPreviewCaptureParamsPtr CreateRecordingRequestParams(
// when clip_rects are used intentionally to limit capture time.
mojo_params->clip_rect_is_hint = true;
mojo_params->is_main_frame = capture_params.is_main_frame;
+ mojo_params->skip_accelerated_content =
+ capture_params.skip_accelerated_content;
mojo_params->file = std::move(file);
mojo_params->max_capture_size = capture_params.max_capture_size;
+ mojo_params->max_decoded_image_size_bytes =
+ capture_params.max_decoded_image_size_bytes;
return mojo_params;
}
@@ -313,6 +318,10 @@ void PaintPreviewClient::CapturePaintPreview(
document_data.accepted_tokens = CreateAcceptedTokenList(render_frame_host);
document_data.capture_links = params.inner.capture_links;
document_data.max_per_capture_size = params.inner.max_capture_size;
+ document_data.max_decoded_image_size_bytes =
+ params.inner.max_decoded_image_size_bytes;
+ document_data.skip_accelerated_content =
+ params.inner.skip_accelerated_content;
all_document_data_.insert(
{params.inner.document_guid, std::move(document_data)});
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
@@ -337,6 +346,8 @@ void PaintPreviewClient::CaptureSubframePaintPreview(
params.is_main_frame = false;
params.capture_links = it->second.capture_links;
params.max_capture_size = it->second.max_per_capture_size;
+ params.max_decoded_image_size_bytes = it->second.max_decoded_image_size_bytes;
+ params.skip_accelerated_content = it->second.skip_accelerated_content;
CapturePaintPreviewInternal(params, render_subframe_host);
}
diff --git a/chromium/components/paint_preview/browser/paint_preview_client.h b/chromium/components/paint_preview/browser/paint_preview_client.h
index 1b3537afcc5..7d7e2559ccf 100644
--- a/chromium/components/paint_preview/browser/paint_preview_client.h
+++ b/chromium/components/paint_preview/browser/paint_preview_client.h
@@ -103,10 +103,11 @@ class PaintPreviewClient
// This corresponds to RenderFrameHost::EmbeddingToken.
base::UnguessableToken root_frame_token;
- // Got from the first recording params. Whether to capture links and the
+ // From the first recording params. Whether to capture links and the
// size limit per capture respectively.
bool capture_links = true;
size_t max_per_capture_size = 0;
+ uint64_t max_decoded_image_size_bytes{std::numeric_limits<uint64_t>::max()};
// UKM Source ID of the WebContent.
ukm::SourceId source_id;
@@ -143,6 +144,14 @@ class PaintPreviewClient
// destruction
bool should_clean_up_files = false;
+ // This flag will skip GPU accelerated content where applicable when
+ // capturing. This reduces hangs, capture time and may also reduce OOM
+ // crashes, but results in a lower fideltiy capture (i.e. the contents
+ // captured may not accurately reflect the content visible to the user at
+ // time of capture). See PaintPreviewBaseService::CaptureParams for a
+ // description of the effects of this flag.
+ bool skip_accelerated_content = false;
+
// Generates a file path based off |root_dir| and |frame_guid|. Will be in
// the form "{hexadecimal}.skp".
base::FilePath FilePathForFrame(const base::UnguessableToken& frame_guid);
diff --git a/chromium/components/paint_preview/browser/paint_preview_client_unittest.cc b/chromium/components/paint_preview/browser/paint_preview_client_unittest.cc
index 8718a99d4e9..47c17055719 100644
--- a/chromium/components/paint_preview/browser/paint_preview_client_unittest.cc
+++ b/chromium/components/paint_preview/browser/paint_preview_client_unittest.cc
@@ -104,6 +104,7 @@ mojom::PaintPreviewCaptureParamsPtr ToMojoParams(
params_ptr->guid = params.inner.document_guid;
params_ptr->is_main_frame = params.inner.is_main_frame;
params_ptr->clip_rect = params.inner.clip_rect;
+ params_ptr->skip_accelerated_content = params.inner.skip_accelerated_content;
return params_ptr;
}
@@ -161,7 +162,7 @@ TEST_P(PaintPreviewClientRenderViewHostTest, CaptureMainFrameMock) {
GURL expected_url = rfh->GetLastCommittedURL();
auto response = NewMockPaintPreviewCaptureResponse();
- response->embedding_token = base::nullopt;
+ response->embedding_token = absl::nullopt;
response->scroll_offsets = gfx::Size(5, 10);
PaintPreviewProto expected_proto;
@@ -290,11 +291,12 @@ TEST_P(PaintPreviewClientRenderViewHostTest, RenderFrameDeletedDuringCapture) {
PaintPreviewClient::PaintPreviewParams params(GetParam());
params.root_dir = temp_dir_.GetPath();
params.inner.is_main_frame = true;
+ params.inner.skip_accelerated_content = true;
content::RenderFrameHost* rfh = main_rfh();
auto response = NewMockPaintPreviewCaptureResponse();
- response->embedding_token = base::nullopt;
+ response->embedding_token = absl::nullopt;
base::RunLoop loop;
auto callback = base::BindOnce(
diff --git a/chromium/components/paint_preview/browser/paint_preview_compositor_client_impl.cc b/chromium/components/paint_preview/browser/paint_preview_compositor_client_impl.cc
index a4a008015ff..271386c74a2 100644
--- a/chromium/components/paint_preview/browser/paint_preview_compositor_client_impl.cc
+++ b/chromium/components/paint_preview/browser/paint_preview_compositor_client_impl.cc
@@ -25,7 +25,7 @@ PaintPreviewCompositorClientImpl::~PaintPreviewCompositorClientImpl() {
NotifyServiceOfInvalidation();
}
-const base::Optional<base::UnguessableToken>&
+const absl::optional<base::UnguessableToken>&
PaintPreviewCompositorClientImpl::Token() const {
DCHECK(default_task_runner_->RunsTasksInCurrentSequence());
return token_;
diff --git a/chromium/components/paint_preview/browser/paint_preview_compositor_client_impl.h b/chromium/components/paint_preview/browser/paint_preview_compositor_client_impl.h
index b8ec2b510db..4cf62e155df 100644
--- a/chromium/components/paint_preview/browser/paint_preview_compositor_client_impl.h
+++ b/chromium/components/paint_preview/browser/paint_preview_compositor_client_impl.h
@@ -6,12 +6,12 @@
#define COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_COMPOSITOR_CLIENT_IMPL_H_
#include "base/callback_forward.h"
-#include "base/optional.h"
#include "base/unguessable_token.h"
#include "components/paint_preview/browser/paint_preview_compositor_service_impl.h"
#include "components/paint_preview/public/paint_preview_compositor_client.h"
#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
@@ -36,7 +36,7 @@ class PaintPreviewCompositorClientImpl : public PaintPreviewCompositorClient {
~PaintPreviewCompositorClientImpl() override;
// PaintPreviewCompositorClient implementation.
- const base::Optional<base::UnguessableToken>& Token() const override;
+ const absl::optional<base::UnguessableToken>& Token() const override;
void SetDisconnectHandler(base::OnceClosure closure) override;
void BeginSeparatedFrameComposite(
mojom::PaintPreviewBeginCompositeRequestPtr request,
@@ -89,7 +89,7 @@ class PaintPreviewCompositorClientImpl : public PaintPreviewCompositorClient {
base::WeakPtr<PaintPreviewCompositorServiceImpl> service_;
CompositorPtr compositor_;
- base::Optional<base::UnguessableToken> token_;
+ absl::optional<base::UnguessableToken> token_;
base::OnceClosure user_disconnect_closure_;
base::WeakPtrFactory<PaintPreviewCompositorClientImpl> weak_ptr_factory_{
diff --git a/chromium/components/paint_preview/browser/paint_preview_file_mixin.cc b/chromium/components/paint_preview/browser/paint_preview_file_mixin.cc
index 3ad349dc92f..54ad65f5bd9 100644
--- a/chromium/components/paint_preview/browser/paint_preview_file_mixin.cc
+++ b/chromium/components/paint_preview/browser/paint_preview_file_mixin.cc
@@ -35,13 +35,13 @@ PaintPreviewFileMixin::~PaintPreviewFileMixin() = default;
void PaintPreviewFileMixin::GetCapturedPaintPreviewProto(
const DirectoryKey& key,
- base::Optional<base::TimeDelta> expiry_horizon,
+ absl::optional<base::TimeDelta> expiry_horizon,
OnReadProtoCallback on_read_proto_callback) {
task_runner_->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(
[](scoped_refptr<FileManager> file_manager, const DirectoryKey& key,
- base::Optional<base::TimeDelta> expiry_horizon)
+ absl::optional<base::TimeDelta> expiry_horizon)
-> std::pair<PaintPreviewFileMixin::ProtoReadStatus,
std::unique_ptr<PaintPreviewProto>> {
if (expiry_horizon.has_value()) {
diff --git a/chromium/components/paint_preview/browser/paint_preview_file_mixin.h b/chromium/components/paint_preview/browser/paint_preview_file_mixin.h
index 0af1317ccd7..5a5b6fd14e0 100644
--- a/chromium/components/paint_preview/browser/paint_preview_file_mixin.h
+++ b/chromium/components/paint_preview/browser/paint_preview_file_mixin.h
@@ -57,7 +57,7 @@ class PaintPreviewFileMixin {
// will return the kExpired status.
virtual void GetCapturedPaintPreviewProto(
const DirectoryKey& key,
- base::Optional<base::TimeDelta> expiry_horizon,
+ absl::optional<base::TimeDelta> expiry_horizon,
OnReadProtoCallback on_read_proto_callback);
// Writes an Accessibility Tree snapshot to the directory listed in key.
@@ -76,4 +76,4 @@ class PaintPreviewFileMixin {
} // namespace paint_preview
-#endif // COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_FILE_HELPER_H_
+#endif // COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_FILE_MIXIN_H_
diff --git a/chromium/components/paint_preview/browser/test_paint_preview_policy.cc b/chromium/components/paint_preview/browser/test_paint_preview_policy.cc
index 986582ff6a7..8f29dab029c 100644
--- a/chromium/components/paint_preview/browser/test_paint_preview_policy.cc
+++ b/chromium/components/paint_preview/browser/test_paint_preview_policy.cc
@@ -5,9 +5,9 @@
#include "components/paint_preview/browser/test_paint_preview_policy.h"
#include "base/callback.h"
-#include "base/optional.h"
#include "components/paint_preview/browser/paint_preview_policy.h"
#include "content/public/browser/web_contents.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace paint_preview {
diff --git a/chromium/components/paint_preview/common/capture_result.h b/chromium/components/paint_preview/common/capture_result.h
index 8cebc54aa3d..0ccdaa014fd 100644
--- a/chromium/components/paint_preview/common/capture_result.h
+++ b/chromium/components/paint_preview/common/capture_result.h
@@ -41,6 +41,20 @@ struct RecordingParams {
// async ordering of captures from different frames making it hard to keep
// track of available headroom at the time of each capture triggering.
size_t max_capture_size;
+
+ // Limit on the maximum size of a decoded image that can be serialized.
+ // Any images with a decoded size exceeding this value will be discarded.
+ // This can be used to reduce the chance of an OOM during serialization and
+ // later during playback.
+ uint64_t max_decoded_image_size_bytes{std::numeric_limits<uint64_t>::max()};
+
+ // This flag will skip GPU accelerated content where applicable when
+ // capturing. This reduces hangs, capture time and may also reduce OOM
+ // crashes, but results in a lower fideltiy capture (i.e. the contents
+ // captured may not accurately reflect the content visible to the user at
+ // time of capture). See PaintPreviewBaseService::CaptureParams for a
+ // description of the effects of this flag.
+ bool skip_accelerated_content{false};
};
// The result of a capture of a WebContents, which may contain recordings of
diff --git a/chromium/components/paint_preview/common/mojom/paint_preview_recorder.mojom b/chromium/components/paint_preview/common/mojom/paint_preview_recorder.mojom
index 5779f87ecc3..e7f214e41b7 100644
--- a/chromium/components/paint_preview/common/mojom/paint_preview_recorder.mojom
+++ b/chromium/components/paint_preview/common/mojom/paint_preview_recorder.mojom
@@ -70,6 +70,18 @@ struct PaintPreviewCaptureParams {
// The maximum allowed size of a capture that can be produced. A value of
// 0 means the size is unrestricted.
uint64 max_capture_size;
+
+ // Limit on the maximum size of a decoded image that can be serialized.
+ // Any images with a decoded size exceeding this value will be discarded.
+ uint64 max_decoded_image_size_bytes;
+
+ // This flag will skip GPU accelerated content where applicable when
+ // capturing. This reduces hangs, capture time and may also reduce OOM
+ // crashes, but results in a lower fideltiy capture (i.e. the contents
+ // captured may not accurately reflect the content visible to the user at
+ // time of capture). See PaintPreviewBaseService::CaptureParams for a
+ // description of the effects of this flag.
+ bool skip_accelerated_content;
};
struct LinkData {
diff --git a/chromium/components/paint_preview/common/paint_preview_tracker.cc b/chromium/components/paint_preview/common/paint_preview_tracker.cc
index 4d87b57912c..280a5a24507 100644
--- a/chromium/components/paint_preview/common/paint_preview_tracker.cc
+++ b/chromium/components/paint_preview/common/paint_preview_tracker.cc
@@ -40,7 +40,7 @@ bool ShouldUseDenseGlyphUsage(SkTypeface* typeface) {
PaintPreviewTracker::PaintPreviewTracker(
const base::UnguessableToken& guid,
- const base::Optional<base::UnguessableToken>& embedding_token,
+ const absl::optional<base::UnguessableToken>& embedding_token,
bool is_main_frame)
: guid_(guid),
embedding_token_(embedding_token),
diff --git a/chromium/components/paint_preview/common/paint_preview_tracker.h b/chromium/components/paint_preview/common/paint_preview_tracker.h
index 2d3f5fcce5f..8bbe21454e7 100644
--- a/chromium/components/paint_preview/common/paint_preview_tracker.h
+++ b/chromium/components/paint_preview/common/paint_preview_tracker.h
@@ -29,14 +29,14 @@ class PaintPreviewTracker {
public:
PaintPreviewTracker(
const base::UnguessableToken& guid,
- const base::Optional<base::UnguessableToken>& embedding_token,
+ const absl::optional<base::UnguessableToken>& embedding_token,
bool is_main_frame);
~PaintPreviewTracker();
// Getters ------------------------------------------------------------------
const base::UnguessableToken& Guid() const { return guid_; }
- const base::Optional<base::UnguessableToken>& EmbeddingToken() const {
+ const absl::optional<base::UnguessableToken>& EmbeddingToken() const {
return embedding_token_;
}
bool IsMainFrame() const { return is_main_frame_; }
@@ -109,7 +109,7 @@ class PaintPreviewTracker {
private:
const base::UnguessableToken guid_;
- const base::Optional<base::UnguessableToken> embedding_token_;
+ const absl::optional<base::UnguessableToken> embedding_token_;
const bool is_main_frame_;
// TODO(crbug.com/1155544): Change this to an SkM44.
diff --git a/chromium/components/paint_preview/common/recording_map.h b/chromium/components/paint_preview/common/recording_map.h
index 9deeff43b20..597de94aa60 100644
--- a/chromium/components/paint_preview/common/recording_map.h
+++ b/chromium/components/paint_preview/common/recording_map.h
@@ -9,11 +9,11 @@
#include "base/containers/flat_map.h"
#include "base/files/file.h"
-#include "base/optional.h"
#include "components/paint_preview/common/capture_result.h"
#include "components/paint_preview/common/proto/paint_preview.pb.h"
#include "components/paint_preview/common/serialized_recording.h"
#include "mojo/public/cpp/base/big_buffer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkRefCnt.h"
diff --git a/chromium/components/paint_preview/common/serial_utils.cc b/chromium/components/paint_preview/common/serial_utils.cc
index bee4ffe8e72..901419004da 100644
--- a/chromium/components/paint_preview/common/serial_utils.cc
+++ b/chromium/components/paint_preview/common/serial_utils.cc
@@ -76,40 +76,47 @@ sk_sp<SkData> SerializeTypeface(SkTypeface* typeface, void* ctx) {
sk_sp<SkData> SerializeImage(SkImage* image, void* ctx) {
ImageSerializationContext* context =
reinterpret_cast<ImageSerializationContext*>(ctx);
+ // Ignore texture backed content if any slipped through. This shouldn't occur
+ // now that ToSkPicture has a dedicated ImageProvider that forces software
+ // SkImage inputs, but this is a safeguard.
if (context->skip_texture_backed && image->isTextureBacked()) {
return SkData::MakeEmpty();
}
+ // If the decoded form of the image would result in it exceeding the allowable
+ // size then effectively delete it by providing no data.
const SkImageInfo& image_info = image->imageInfo();
- // If decoding/encoding the image would result in it exceeding the allowable
- // size, effectively delete it by providing no data.
- if (context->max_representation_size != 0 &&
- image_info.computeMinByteSize() > context->max_representation_size) {
+ if (context->max_decoded_image_size_bytes !=
+ std::numeric_limits<uint64_t>::max() &&
+ image_info.computeMinByteSize() > context->max_decoded_image_size_bytes) {
return SkData::MakeEmpty();
}
// If there already exists encoded data use it directly.
sk_sp<SkData> encoded_data = image->refEncodedData();
if (!encoded_data) {
+ // Use the default PNG at quality 100 as it is safe.
+ // TODO(crbug/1198304): Investigate supporting JPEG at quality 100 for
+ // opaque images.
encoded_data = image->encodeToData();
}
- // If encoding failed then no-op.
if (!encoded_data)
return SkData::MakeEmpty();
- // Ensure the encoded data fits in the restrictions if they are present.
- if ((context->remaining_image_size == std::numeric_limits<uint64_t>::max() ||
- context->remaining_image_size >= encoded_data->size()) &&
- (context->max_representation_size == 0 ||
- encoded_data->size() < context->max_representation_size)) {
- if (context->remaining_image_size != std::numeric_limits<uint64_t>::max())
- context->remaining_image_size -= encoded_data->size();
-
- return encoded_data;
+ // Ensure the encoded data fits in the size restriction if present.
+ // OOM Prevention: This avoids creating/keeping large serialized images
+ // in-memory during serialization if the size budget is already exceeded due
+ // to images.
+ if (context->remaining_image_size != std::numeric_limits<uint64_t>::max()) {
+ if (context->remaining_image_size < encoded_data->size()) {
+ context->memory_budget_exceeded = true;
+ return SkData::MakeEmpty();
+ }
+ context->remaining_image_size -= encoded_data->size();
}
- return SkData::MakeEmpty();
+ return encoded_data;
}
// Deserializes a clip rect for a subframe within the main SkPicture. These
@@ -207,10 +214,15 @@ SkSerialProcs MakeSerialProcs(PictureSerializationContext* picture_ctx,
//
// At present this uses the native representation, but skips serializing if
// loading to a bitmap for encoding might cause an OOM.
- if (image_ctx->max_representation_size > 0 ||
- image_ctx->remaining_image_size != std::numeric_limits<uint64_t>::max()) {
- procs.fImageProc = SerializeImage;
- procs.fImageCtx = image_ctx;
+ if (image_ctx) {
+ image_ctx->memory_budget_exceeded = false;
+ if (image_ctx->max_decoded_image_size_bytes !=
+ std::numeric_limits<uint64_t>::max() ||
+ image_ctx->remaining_image_size !=
+ std::numeric_limits<uint64_t>::max()) {
+ procs.fImageProc = SerializeImage;
+ procs.fImageCtx = image_ctx;
+ }
}
return procs;
}
diff --git a/chromium/components/paint_preview/common/serial_utils.h b/chromium/components/paint_preview/common/serial_utils.h
index 01608911e19..645d86f330b 100644
--- a/chromium/components/paint_preview/common/serial_utils.h
+++ b/chromium/components/paint_preview/common/serial_utils.h
@@ -57,15 +57,17 @@ struct ImageSerializationContext {
// max value of uint64_t.
uint64_t remaining_image_size{std::numeric_limits<uint64_t>::max()};
- // The maximum size of the representation for serialization. Images
- // that are larger than this when encoded or will need to be inflated to a
- // bitmap larger than this are skipped to avoid OOMs. If this value is 0 image
- // procs are skipped and the default behavior is used.
- uint64_t max_representation_size{0};
+ // The maximum size of a decoded image allowed for serialization. Images that
+ // are larger than this when decoded are skipped.
+ uint64_t max_decoded_image_size_bytes{std::numeric_limits<uint64_t>::max()};
// Skip texture backed images. Must be true if serialized off the main
// thread.
bool skip_texture_backed{false};
+
+ // Will be set to true post serialization if the `remaining_image_size` budget
+ // was exceeded.
+ bool memory_budget_exceeded{false};
};
// Maps a content ID to a clip rect.
diff --git a/chromium/components/paint_preview/common/serial_utils_unittest.cc b/chromium/components/paint_preview/common/serial_utils_unittest.cc
index 35410e9f253..65284a85711 100644
--- a/chromium/components/paint_preview/common/serial_utils_unittest.cc
+++ b/chromium/components/paint_preview/common/serial_utils_unittest.cc
@@ -165,6 +165,7 @@ TEST(PaintPreviewSerialUtils, TestImageContextLimitBudget) {
sk_sp<SkData> data = pic->serialize(&serial_procs);
EXPECT_NE(data, nullptr);
+ EXPECT_TRUE(ictx.memory_budget_exceeded);
SkDeserialProcs deserial_procs;
size_t deserialized_images = 0;
deserial_procs.fImageCtx = &deserialized_images;
@@ -202,7 +203,7 @@ TEST(PaintPreviewSerialUtils, TestImageContextLimitSize) {
TypefaceUsageMap usage_map;
TypefaceSerializationContext typeface_ctx(&usage_map);
ImageSerializationContext ictx;
- ictx.max_representation_size = 200;
+ ictx.max_decoded_image_size_bytes = 200;
SkSerialProcs serial_procs =
MakeSerialProcs(&picture_ctx, &typeface_ctx, &ictx);
@@ -212,6 +213,7 @@ TEST(PaintPreviewSerialUtils, TestImageContextLimitSize) {
sk_sp<SkData> data = pic->serialize(&serial_procs);
EXPECT_NE(data, nullptr);
+ EXPECT_FALSE(ictx.memory_budget_exceeded);
SkDeserialProcs deserial_procs;
size_t deserialized_images = 0;
deserial_procs.fImageCtx = &deserialized_images;
diff --git a/chromium/components/paint_preview/common/serialized_recording.cc b/chromium/components/paint_preview/common/serialized_recording.cc
index b5db42264c7..c0a7e62d84a 100644
--- a/chromium/components/paint_preview/common/serialized_recording.cc
+++ b/chromium/components/paint_preview/common/serialized_recording.cc
@@ -5,13 +5,13 @@
#include "components/paint_preview/common/serialized_recording.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/trace_event/common/trace_event_common.h"
#include "base/trace_event/trace_event.h"
#include "components/paint_preview/common/file_stream.h"
#include "components/paint_preview/common/paint_preview_tracker.h"
#include "components/paint_preview/common/serial_utils.h"
#include "mojo/public/cpp/base/big_buffer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkStream.h"
namespace paint_preview {
@@ -24,13 +24,20 @@ bool SerializeSkPicture(sk_sp<const SkPicture> skp,
PaintPreviewTracker* tracker,
SkWStream* out_stream) {
TypefaceSerializationContext typeface_context(tracker->GetTypefaceUsageMap());
+ ImageSerializationContext* image_context =
+ tracker->GetImageSerializationContext();
auto serial_procs = MakeSerialProcs(tracker->GetPictureSerializationContext(),
- &typeface_context,
- tracker->GetImageSerializationContext());
+ &typeface_context, image_context);
skp->serialize(out_stream, &serial_procs);
out_stream->flush();
- return true;
+
+ // If the memory budget was exceeded while serializing images and it is not
+ // tolerated (inferred from setting a max decoded image size) then abort.
+ const bool tolerates_discarding =
+ image_context->max_decoded_image_size_bytes !=
+ std::numeric_limits<uint64_t>::max();
+ return tolerates_discarding || !image_context->memory_budget_exceeded;
}
} // namespace
@@ -76,7 +83,7 @@ bool SerializedRecording::IsValid() const {
}
}
-base::Optional<SkpResult> SerializedRecording::Deserialize() && {
+absl::optional<SkpResult> SerializedRecording::Deserialize() && {
TRACE_EVENT0("paint_preview", "SerializedRecording::Deserialize");
SkpResult result;
SkDeserialProcs procs = MakeDeserialProcs(&result.ctx);
@@ -120,7 +127,7 @@ sk_sp<SkPicture> SerializedRecording::DeserializeWithContext(
bool RecordToFile(base::File file,
sk_sp<const SkPicture> skp,
PaintPreviewTracker* tracker,
- base::Optional<size_t> max_capture_size,
+ absl::optional<size_t> max_capture_size,
size_t* serialized_size) {
if (!file.IsValid())
return false;
@@ -137,25 +144,25 @@ bool RecordToFile(base::File file,
return !file_stream.DidWriteFail();
}
-base::Optional<mojo_base::BigBuffer> RecordToBuffer(
+absl::optional<mojo_base::BigBuffer> RecordToBuffer(
sk_sp<const SkPicture> skp,
PaintPreviewTracker* tracker,
- base::Optional<size_t> maybe_max_capture_size,
+ absl::optional<size_t> maybe_max_capture_size,
size_t* serialized_size) {
SkDynamicMemoryWStream memory_stream;
if (!SerializeSkPicture(skp, tracker, &memory_stream))
- return base::nullopt;
+ return absl::nullopt;
size_t max_capture_size = maybe_max_capture_size.value_or(SIZE_MAX);
if (max_capture_size == 0)
- return base::nullopt;
+ return absl::nullopt;
sk_sp<SkData> data = memory_stream.detachAsData();
*serialized_size = std::min(data->size(), max_capture_size);
mojo_base::BigBuffer buffer(
base::span<const uint8_t>(data->bytes(), *serialized_size));
if (data->size() > max_capture_size)
- return base::nullopt;
+ return absl::nullopt;
return {std::move(buffer)};
}
diff --git a/chromium/components/paint_preview/common/serialized_recording.h b/chromium/components/paint_preview/common/serialized_recording.h
index 337d3b19180..925994fcd0f 100644
--- a/chromium/components/paint_preview/common/serialized_recording.h
+++ b/chromium/components/paint_preview/common/serialized_recording.h
@@ -5,18 +5,15 @@
#ifndef COMPONENTS_PAINT_PREVIEW_COMMON_SERIALIZED_RECORDING_H_
#define COMPONENTS_PAINT_PREVIEW_COMMON_SERIALIZED_RECORDING_H_
-#include <memory>
-#include <utility>
-
#include "base/containers/flat_map.h"
#include "base/files/file.h"
#include "base/gtest_prod_util.h"
-#include "base/optional.h"
#include "base/unguessable_token.h"
#include "components/paint_preview/common/mojom/paint_preview_types.mojom-shared.h"
#include "components/paint_preview/common/serial_utils.h"
#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/bindings/union_traits.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkRefCnt.h"
class SkPicture;
@@ -98,12 +95,22 @@ class SerializedRecording {
RecordingMapFromPaintPreviewProtoSingleFrame);
FRIEND_TEST_ALL_PREFIXES(PaintPreviewRecorderUtilsSerializeAsSkPictureTest,
Roundtrip);
+ FRIEND_TEST_ALL_PREFIXES(PaintPreviewRecorderUtilsSerializeAsSkPictureTest,
+ RoundtripWithImage);
+ FRIEND_TEST_ALL_PREFIXES(PaintPreviewRecorderUtilsSerializeAsSkPictureTest,
+ RoundtripWithLazyImage);
+ FRIEND_TEST_ALL_PREFIXES(PaintPreviewRecorderUtilsSerializeAsSkPictureTest,
+ RoundtripWithPaintWorklet);
+ FRIEND_TEST_ALL_PREFIXES(PaintPreviewRecorderUtilsSerializeAsSkPictureTest,
+ RoundtripWithTexture);
+ FRIEND_TEST_ALL_PREFIXES(PaintPreviewRecorderUtilsSerializeAsSkPictureTest,
+ RoundtripWithLazyTexture);
// Deserialize into an |SkPicture|. The result will not include any embedded
// subframes.
//
// This is not safe to call in the browser process.
- base::Optional<SkpResult> Deserialize() &&;
+ absl::optional<SkpResult> Deserialize() &&;
// Deserialize into an |SkPicture|. |ctx| should contain entries for any
// subframes that should be included in the output.
@@ -126,7 +133,7 @@ class SerializedRecording {
RecordingPersistence persistence_;
base::File file_;
- base::Optional<mojo_base::BigBuffer> buffer_;
+ absl::optional<mojo_base::BigBuffer> buffer_;
};
// Serialize and write |skp| to |file|.
@@ -140,7 +147,7 @@ class SerializedRecording {
bool RecordToFile(base::File file,
sk_sp<const SkPicture> skp,
PaintPreviewTracker* tracker,
- base::Optional<size_t> max_capture_size,
+ absl::optional<size_t> max_capture_size,
size_t* serialized_size);
// Serialize and write |recording| to a memory buffer.
@@ -151,10 +158,10 @@ bool RecordToFile(base::File file,
// serialized output.
//
// Returns the memory buffer on success.
-base::Optional<mojo_base::BigBuffer> RecordToBuffer(
+absl::optional<mojo_base::BigBuffer> RecordToBuffer(
sk_sp<const SkPicture> skp,
PaintPreviewTracker* tracker,
- base::Optional<size_t> max_capture_size,
+ absl::optional<size_t> max_capture_size,
size_t* serialized_size);
} // namespace paint_preview
diff --git a/chromium/components/paint_preview/common/serialized_recording_unittest.cc b/chromium/components/paint_preview/common/serialized_recording_unittest.cc
index 0cce745ac9a..1ba72b714c1 100644
--- a/chromium/components/paint_preview/common/serialized_recording_unittest.cc
+++ b/chromium/components/paint_preview/common/serialized_recording_unittest.cc
@@ -6,7 +6,6 @@
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/optional.h"
#include "base/threading/thread_restrictions.h"
#include "base/unguessable_token.h"
#include "components/paint_preview/common/capture_result.h"
@@ -15,6 +14,7 @@
#include "components/paint_preview/common/recording_map.h"
#include "components/paint_preview/common/serial_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPaint.h"
@@ -70,6 +70,26 @@ sk_sp<const SkPicture> PaintPictureSingleGrayPixel() {
&expected_deserialization_context, {});
}
+sk_sp<const SkPicture> PaintPictureLargeImage(gfx::Size bounds) {
+ SkBitmap bitmap;
+ {
+ bitmap.allocPixels(
+ SkImageInfo::MakeN32Premul(bounds.width(), bounds.height()));
+ SkCanvas canvas(bitmap, SkSurfaceProps{});
+ canvas.drawColor(SK_ColorDKGRAY);
+ }
+
+ SkRect sk_bounds = SkRect::MakeWH(bounds.width(), bounds.height());
+ SkPictureRecorder recorder;
+ SkCanvas* canvas = recorder.beginRecording(sk_bounds);
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(SK_ColorRED);
+ canvas->drawRect(sk_bounds, paint);
+ canvas->drawImage(SkImage::MakeFromBitmap(bitmap), 0, 0);
+ return recorder.finishRecordingAsPicture();
+}
+
SkBitmap CreateBitmapFromPicture(const SkPicture* pic) {
SkRect cull_rect = pic->cullRect();
SkBitmap bitmap;
@@ -113,18 +133,18 @@ TEST(PaintPreviewSerializedRecordingTest, RoundtripWithFileBacking) {
sk_sp<const SkPicture> pic = PaintPictureSingleGrayPixel();
base::FilePath path = temp_dir.GetPath().AppendASCII("root.skp");
- PaintPreviewTracker tracker(base::UnguessableToken::Create(), base::nullopt,
+ PaintPreviewTracker tracker(base::UnguessableToken::Create(), absl::nullopt,
/*is_main_frame=*/true);
size_t serialized_size = 0;
ASSERT_TRUE(RecordToFile(
base::File(path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE),
- pic, &tracker, base::nullopt, &serialized_size));
+ pic, &tracker, absl::nullopt, &serialized_size));
ASSERT_GE(serialized_size, 0u);
SerializedRecording recording(path);
ASSERT_TRUE(recording.IsValid());
- base::Optional<SkpResult> result = std::move(recording).Deserialize();
+ absl::optional<SkpResult> result = std::move(recording).Deserialize();
ASSERT_TRUE(result.has_value());
ASSERT_TRUE(result->ctx.empty());
ExpectPicturesEqual(result->skp, pic);
@@ -133,11 +153,11 @@ TEST(PaintPreviewSerializedRecordingTest, RoundtripWithFileBacking) {
TEST(PaintPreviewSerializedRecordingTest, RoundtripWithMemoryBufferBacking) {
sk_sp<const SkPicture> pic = PaintPictureSingleGrayPixel();
- PaintPreviewTracker tracker(base::UnguessableToken::Create(), base::nullopt,
+ PaintPreviewTracker tracker(base::UnguessableToken::Create(), absl::nullopt,
/*is_main_frame=*/true);
size_t serialized_size = 0;
- base::Optional<mojo_base::BigBuffer> buffer =
- RecordToBuffer(pic, &tracker, base::nullopt, &serialized_size);
+ absl::optional<mojo_base::BigBuffer> buffer =
+ RecordToBuffer(pic, &tracker, absl::nullopt, &serialized_size);
ASSERT_GE(serialized_size, 0u);
ASSERT_TRUE(buffer.has_value());
@@ -145,12 +165,47 @@ TEST(PaintPreviewSerializedRecordingTest, RoundtripWithMemoryBufferBacking) {
SerializedRecording(std::move(buffer.value()));
ASSERT_TRUE(recording.IsValid());
- base::Optional<SkpResult> result = std::move(recording).Deserialize();
+ absl::optional<SkpResult> result = std::move(recording).Deserialize();
ASSERT_TRUE(result.has_value());
ASSERT_TRUE(result->ctx.empty());
ExpectPicturesEqual(result->skp, pic);
}
+TEST(PaintPreviewSerializedRecordingTest, ImageDiscardingTolerated) {
+ sk_sp<const SkPicture> pic = PaintPictureLargeImage(gfx::Size(200, 200));
+
+ PaintPreviewTracker tracker(base::UnguessableToken::Create(), absl::nullopt,
+ /*is_main_frame=*/true);
+ auto* image_context = tracker.GetImageSerializationContext();
+ image_context->remaining_image_size = 200;
+ image_context->max_decoded_image_size_bytes = 300 * 300 * 4;
+ size_t serialized_size = 0;
+ absl::optional<mojo_base::BigBuffer> buffer =
+ RecordToBuffer(pic, &tracker, absl::nullopt, &serialized_size);
+ ASSERT_GE(serialized_size, 0u);
+ ASSERT_TRUE(buffer.has_value());
+ ASSERT_TRUE(image_context->memory_budget_exceeded);
+
+ SerializedRecording recording =
+ SerializedRecording(std::move(buffer.value()));
+ ASSERT_TRUE(recording.IsValid());
+}
+
+TEST(PaintPreviewSerializedRecordingTest, ImageDiscardingNotTolerated) {
+ sk_sp<const SkPicture> pic = PaintPictureLargeImage(gfx::Size(200, 200));
+
+ PaintPreviewTracker tracker(base::UnguessableToken::Create(), absl::nullopt,
+ /*is_main_frame=*/true);
+ auto* image_context = tracker.GetImageSerializationContext();
+ image_context->remaining_image_size = 200;
+ size_t serialized_size = 0;
+ absl::optional<mojo_base::BigBuffer> buffer =
+ RecordToBuffer(pic, &tracker, absl::nullopt, &serialized_size);
+ ASSERT_FALSE(buffer.has_value());
+ ASSERT_EQ(serialized_size, 0U);
+ ASSERT_TRUE(image_context->memory_budget_exceeded);
+}
+
TEST(PaintPreviewSerializedRecordingTest, InvalidBacking) {
SerializedRecording recording;
ASSERT_FALSE(recording.IsValid());
@@ -162,7 +217,7 @@ TEST(PaintPreviewSerializedRecordingTest, RoundtripHasEmbeddedContent) {
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath path = temp_dir.GetPath().AppendASCII("root.skp");
- PaintPreviewTracker tracker(base::UnguessableToken::Create(), base::nullopt,
+ PaintPreviewTracker tracker(base::UnguessableToken::Create(), absl::nullopt,
/*is_main_frame=*/true);
base::UnguessableToken subframe0 = base::UnguessableToken::Create();
@@ -178,13 +233,13 @@ TEST(PaintPreviewSerializedRecordingTest, RoundtripHasEmbeddedContent) {
size_t serialized_size = 0;
ASSERT_TRUE(RecordToFile(
base::File(path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE),
- pic, &tracker, base::nullopt, &serialized_size));
+ pic, &tracker, absl::nullopt, &serialized_size));
ASSERT_GE(serialized_size, 0u);
SerializedRecording recording(path);
ASSERT_TRUE(recording.IsValid());
- base::Optional<SkpResult> result = std::move(recording).Deserialize();
+ absl::optional<SkpResult> result = std::move(recording).Deserialize();
ASSERT_TRUE(result.has_value());
EXPECT_FALSE(result->ctx.empty());
@@ -199,11 +254,11 @@ TEST(PaintPreviewSerializedRecordingTest,
const base::UnguessableToken root_frame_guid =
base::UnguessableToken::Create();
- PaintPreviewTracker tracker(base::UnguessableToken::Create(), base::nullopt,
+ PaintPreviewTracker tracker(base::UnguessableToken::Create(), absl::nullopt,
/*is_main_frame=*/true);
size_t serialized_size = 0;
- base::Optional<mojo_base::BigBuffer> buffer =
- RecordToBuffer(pic, &tracker, base::nullopt, &serialized_size);
+ absl::optional<mojo_base::BigBuffer> buffer =
+ RecordToBuffer(pic, &tracker, absl::nullopt, &serialized_size);
ASSERT_GE(serialized_size, 0u);
ASSERT_TRUE(buffer.has_value());
@@ -218,7 +273,7 @@ TEST(PaintPreviewSerializedRecordingTest,
RecordingMap recording_map = std::move(pair.first);
EXPECT_FALSE(recording_map.empty());
ASSERT_NE(recording_map.find(root_frame_guid), recording_map.end());
- base::Optional<SkpResult> result =
+ absl::optional<SkpResult> result =
std::move(recording_map.at(root_frame_guid)).Deserialize();
ASSERT_TRUE(result.has_value());
@@ -237,13 +292,13 @@ TEST(PaintPreviewSerializedRecordingTest,
const base::UnguessableToken root_frame_guid =
base::UnguessableToken::Create();
- PaintPreviewTracker tracker(base::UnguessableToken::Create(), base::nullopt,
+ PaintPreviewTracker tracker(base::UnguessableToken::Create(), absl::nullopt,
/*is_main_frame=*/true);
size_t serialized_size = 0;
ASSERT_TRUE(RecordToFile(
base::File(root_path,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE),
- pic, &tracker, base::nullopt, &serialized_size));
+ pic, &tracker, absl::nullopt, &serialized_size));
ASSERT_GE(serialized_size, 0u);
PaintPreviewProto proto;
@@ -257,7 +312,7 @@ TEST(PaintPreviewSerializedRecordingTest,
RecordingMap recording_map = RecordingMapFromPaintPreviewProto(proto);
EXPECT_FALSE(recording_map.empty());
ASSERT_NE(recording_map.find(root_frame_guid), recording_map.end());
- base::Optional<SkpResult> result =
+ absl::optional<SkpResult> result =
std::move(recording_map.at(root_frame_guid)).Deserialize();
ASSERT_TRUE(result.has_value());
diff --git a/chromium/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java b/chromium/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java
index 3d372e64a2f..8b753b2e297 100644
--- a/chromium/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java
+++ b/chromium/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java
@@ -217,6 +217,9 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase {
public boolean isAccessibilityEnabled() {
return false;
}
+
+ @Override
+ public void onAccessibilityNotSupported() {}
}, 0xffffffff, false);
mPlayerManager.setCompressOnClose(false);
});
@@ -427,6 +430,9 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase {
public boolean isAccessibilityEnabled() {
return false;
}
+
+ @Override
+ public void onAccessibilityNotSupported() {}
}, 0xffffffff, false);
mPlayerManager.setCompressOnClose(false);
getActivity().setContentView(mPlayerManager.getView());
diff --git a/chromium/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinatorTest.java b/chromium/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinatorTest.java
index b7980196d3c..702e336e19b 100644
--- a/chromium/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinatorTest.java
+++ b/chromium/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinatorTest.java
@@ -30,11 +30,11 @@ public class PlayerFrameCoordinatorTest {
PlayerFrameCoordinator rootCoordinator = new PlayerFrameCoordinator(
RuntimeEnvironment.systemContext, Mockito.mock(PlayerCompositorDelegate.class),
Mockito.mock(UnguessableToken.class), 100, 2000, 0, 0, true, null,
- Mockito.mock(PlayerGestureListener.class), null, null);
+ Mockito.mock(PlayerGestureListener.class), null, null, null);
PlayerFrameCoordinator childCoordinator = new PlayerFrameCoordinator(
RuntimeEnvironment.systemContext, Mockito.mock(PlayerCompositorDelegate.class),
Mockito.mock(UnguessableToken.class), 100, 200, 0, 0, true, null,
- Mockito.mock(PlayerGestureListener.class), null, null);
+ Mockito.mock(PlayerGestureListener.class), null, null, null);
rootCoordinator.addSubFrame(childCoordinator, new Rect(10, 20, 35, 40));
rootCoordinator.getMediator().setLayoutDimensions(100, 200);
diff --git a/chromium/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java b/chromium/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java
index 200d69446a8..2b5e670c066 100644
--- a/chromium/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java
+++ b/chromium/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java
@@ -237,8 +237,8 @@ public class PlayerFrameMediatorTest {
mScroller = new OverScroller(ContextUtils.getApplicationContext());
mGestureListener = new PlayerGestureListener(null, () -> mHasUserInteraction = true, null);
Size contentSize = new Size(CONTENT_WIDTH, CONTENT_HEIGHT);
- mMediator = new PlayerFrameMediator(mModel, mCompositorDelegate, mGestureListener,
- mFrameGuid, contentSize, 0, 0);
+ mMediator = new PlayerFrameMediator(
+ mModel, mCompositorDelegate, mGestureListener, mFrameGuid, contentSize, 0, 0, null);
mScaleController =
new PlayerFrameScaleController(mModel.get(PlayerFrameProperties.SCALE_MATRIX),
mMediator, null, mGestureListener::onScale);
diff --git a/chromium/components/paint_preview/player/android/player_compositor_delegate_android.cc b/chromium/components/paint_preview/player/android/player_compositor_delegate_android.cc
index c9b11a35754..e827f4b6270 100644
--- a/chromium/components/paint_preview/player/android/player_compositor_delegate_android.cc
+++ b/chromium/components/paint_preview/player/android/player_compositor_delegate_android.cc
@@ -15,6 +15,7 @@
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/common/trace_event_common.h"
+#include "base/trace_event/trace_event.h"
#include "base/unguessable_token.h"
#include "components/paint_preview/browser/paint_preview_base_service.h"
#include "components/paint_preview/player/android/jni_headers/PlayerCompositorDelegateImpl_jni.h"
@@ -252,7 +253,7 @@ jint PlayerCompositorDelegateAndroid::RequestBitmap(
ScopedJavaGlobalRef<jobject>(j_error_callback), request_id_);
++request_id_;
- base::Optional<base::UnguessableToken> frame_guid;
+ absl::optional<base::UnguessableToken> frame_guid;
if (j_frame_guid) {
frame_guid =
base::android::UnguessableTokenAndroid::FromJavaUnguessableToken(
diff --git a/chromium/components/paint_preview/player/bitmap_request.cc b/chromium/components/paint_preview/player/bitmap_request.cc
index a09c52654e6..d777fae3652 100644
--- a/chromium/components/paint_preview/player/bitmap_request.cc
+++ b/chromium/components/paint_preview/player/bitmap_request.cc
@@ -7,7 +7,7 @@
namespace paint_preview {
BitmapRequest::BitmapRequest(
- const base::Optional<base::UnguessableToken>& frame_guid,
+ const absl::optional<base::UnguessableToken>& frame_guid,
const gfx::Rect& clip_rect,
float scale_factor,
BitmapRequestCallback callback)
diff --git a/chromium/components/paint_preview/player/bitmap_request.h b/chromium/components/paint_preview/player/bitmap_request.h
index b4de5299d3b..5b2fd37c819 100644
--- a/chromium/components/paint_preview/player/bitmap_request.h
+++ b/chromium/components/paint_preview/player/bitmap_request.h
@@ -6,9 +6,9 @@
#define COMPONENTS_PAINT_PREVIEW_PLAYER_BITMAP_REQUEST_H_
#include "base/callback.h"
-#include "base/optional.h"
#include "base/unguessable_token.h"
#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/rect.h"
@@ -19,7 +19,7 @@ struct BitmapRequest {
base::OnceCallback<void(mojom::PaintPreviewCompositor::BitmapStatus,
const SkBitmap&)>;
- BitmapRequest(const base::Optional<base::UnguessableToken>& frame_guid,
+ BitmapRequest(const absl::optional<base::UnguessableToken>& frame_guid,
const gfx::Rect& clip_rect,
float scale_factor,
BitmapRequestCallback callback);
@@ -28,7 +28,7 @@ struct BitmapRequest {
BitmapRequest& operator=(BitmapRequest&& other) noexcept;
BitmapRequest(BitmapRequest&& other) noexcept;
- base::Optional<base::UnguessableToken> frame_guid;
+ absl::optional<base::UnguessableToken> frame_guid;
gfx::Rect clip_rect;
float scale_factor;
BitmapRequestCallback callback;
diff --git a/chromium/components/paint_preview/player/player_compositor_delegate.cc b/chromium/components/paint_preview/player/player_compositor_delegate.cc
index 4b054152653..324d06dab1e 100644
--- a/chromium/components/paint_preview/player/player_compositor_delegate.cc
+++ b/chromium/components/paint_preview/player/player_compositor_delegate.cc
@@ -14,7 +14,6 @@
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
@@ -32,6 +31,7 @@
#include "components/paint_preview/public/paint_preview_compositor_service.h"
#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/rect.h"
@@ -62,15 +62,15 @@ BuildHitTesters(const PaintPreviewProto& proto) {
std::move(hit_testers));
}
-base::Optional<base::ReadOnlySharedMemoryRegion> ToReadOnlySharedMemory(
+absl::optional<base::ReadOnlySharedMemoryRegion> ToReadOnlySharedMemory(
const paint_preview::PaintPreviewProto& proto) {
auto region = base::WritableSharedMemoryRegion::Create(proto.ByteSizeLong());
if (!region.IsValid())
- return base::nullopt;
+ return absl::nullopt;
auto mapping = region.Map();
if (!mapping.IsValid())
- return base::nullopt;
+ return absl::nullopt;
proto.SerializeToArray(mapping.memory(), mapping.size());
return base::WritableSharedMemoryRegion::ConvertToReadOnly(std::move(region));
@@ -203,7 +203,7 @@ void PlayerCompositorDelegate::InitializeInternal(
}
int32_t PlayerCompositorDelegate::RequestBitmap(
- const base::Optional<base::UnguessableToken>& frame_guid,
+ const absl::optional<base::UnguessableToken>& frame_guid,
const gfx::Rect& clip_rect,
float scale_factor,
base::OnceCallback<void(mojom::PaintPreviewCompositor::BitmapStatus,
@@ -323,7 +323,7 @@ void PlayerCompositorDelegate::OnCompositorClientCreated(
TRACE_ID_LOCAL(this));
if (!proto_) {
paint_preview_service_->GetFileMixin()->GetCapturedPaintPreviewProto(
- key, base::nullopt,
+ key, absl::nullopt,
base::BindOnce(&PlayerCompositorDelegate::OnProtoAvailable,
weak_factory_.GetWeakPtr(), expected_url));
} else {
diff --git a/chromium/components/paint_preview/player/player_compositor_delegate.h b/chromium/components/paint_preview/player/player_compositor_delegate.h
index cf8bebf1814..8d4b803539f 100644
--- a/chromium/components/paint_preview/player/player_compositor_delegate.h
+++ b/chromium/components/paint_preview/player/player_compositor_delegate.h
@@ -10,7 +10,6 @@
#include "base/containers/flat_map.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/unguessable_token.h"
#include "components/paint_preview/browser/hit_tester.h"
#include "components/paint_preview/browser/paint_preview_base_service.h"
@@ -20,6 +19,7 @@
#include "components/paint_preview/public/paint_preview_compositor_service.h"
#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class MemoryPressureMonitor;
@@ -77,7 +77,7 @@ class PlayerCompositorDelegate {
// Pass this ID to `CancelBitmapRequest(int32_t)` to cancel the request if it
// hasn't already been sent.
int32_t RequestBitmap(
- const base::Optional<base::UnguessableToken>& frame_guid,
+ const absl::optional<base::UnguessableToken>& frame_guid,
const gfx::Rect& clip_rect,
float scale_factor,
base::OnceCallback<void(mojom::PaintPreviewCompositor::BitmapStatus,
diff --git a/chromium/components/paint_preview/player/player_compositor_delegate_unittest.cc b/chromium/components/paint_preview/player/player_compositor_delegate_unittest.cc
index e8fef04f627..90a85e86802 100644
--- a/chromium/components/paint_preview/player/player_compositor_delegate_unittest.cc
+++ b/chromium/components/paint_preview/player/player_compositor_delegate_unittest.cc
@@ -46,7 +46,7 @@ class FakePaintPreviewCompositorClient : public PaintPreviewCompositorClient {
FakePaintPreviewCompositorClient& operator=(
const FakePaintPreviewCompositorClient&) = delete;
- const base::Optional<base::UnguessableToken>& Token() const override {
+ const absl::optional<base::UnguessableToken>& Token() const override {
return token_;
}
@@ -123,7 +123,7 @@ class FakePaintPreviewCompositorClient : public PaintPreviewCompositorClient {
private:
mojom::PaintPreviewCompositor::BeginCompositeStatus response_status_;
- base::Optional<base::UnguessableToken> token_;
+ absl::optional<base::UnguessableToken> token_;
base::OnceClosure disconnect_handler_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
};
@@ -642,7 +642,7 @@ TEST_F(PlayerCompositorDelegateTest, CompressOnClose) {
false),
base::BindOnce(
[](base::FilePath* out,
- const base::Optional<base::FilePath>& file_path) {
+ const absl::optional<base::FilePath>& file_path) {
*out = file_path.value();
},
base::Unretained(&dir)));
@@ -845,7 +845,7 @@ TEST_F(PlayerCompositorDelegateTest, RequestMainFrameBitmapSuccess) {
base::RunLoop loop;
player_compositor_delegate.RequestBitmap(
- base::nullopt, gfx::Rect(10, 20, 30, 40), 1.0,
+ absl::nullopt, gfx::Rect(10, 20, 30, 40), 1.0,
base::BindOnce(
[](base::OnceClosure quit,
mojom::PaintPreviewCompositor::BitmapStatus status,
diff --git a/chromium/components/paint_preview/public/paint_preview_compositor_client.h b/chromium/components/paint_preview/public/paint_preview_compositor_client.h
index 9f49438c501..4fc22afdd16 100644
--- a/chromium/components/paint_preview/public/paint_preview_compositor_client.h
+++ b/chromium/components/paint_preview/public/paint_preview_compositor_client.h
@@ -6,9 +6,9 @@
#define COMPONENTS_PAINT_PREVIEW_PUBLIC_PAINT_PREVIEW_COMPOSITOR_CLIENT_H_
#include "base/callback_forward.h"
-#include "base/optional.h"
#include "base/unguessable_token.h"
#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace gfx {
@@ -27,7 +27,7 @@ class PaintPreviewCompositorClient {
// Returns the token associated with the client. Will be null if the client
// isn't started.
- virtual const base::Optional<base::UnguessableToken>& Token() const = 0;
+ virtual const absl::optional<base::UnguessableToken>& Token() const = 0;
// Adds `closure` as a disconnect handler.
virtual void SetDisconnectHandler(base::OnceClosure closure) = 0;
diff --git a/chromium/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc b/chromium/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
index b1a1e54f57a..fd928b6efc4 100644
--- a/chromium/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
+++ b/chromium/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
@@ -17,7 +17,10 @@
#include "content/public/test/render_view_test.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_testing_support.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "ui/native_theme/native_theme_features.h"
@@ -25,6 +28,8 @@ namespace paint_preview {
namespace {
+constexpr char kCompositeAfterPaint[] = "CompositeAfterPaint";
+
// Checks that |status| == |expected_status| and loads |response| into
// |out_response| if |expected_status| == kOk. If |expected_status| != kOk
// |out_response| can safely be nullptr.
@@ -37,22 +42,39 @@ void OnCaptureFinished(mojom::PaintPreviewStatus expected_status,
*out_response = std::move(response);
}
+std::string CompositeAfterPaintToString(
+ const ::testing::TestParamInfo<bool>& cap_enabled) {
+ if (cap_enabled.param) {
+ return "WithCompositeAfterPaint";
+ }
+ return "NoCompositeAfterPaint";
+}
+
} // namespace
-class PaintPreviewRecorderRenderViewTest : public content::RenderViewTest {
+class PaintPreviewRecorderRenderViewTest
+ : public content::RenderViewTest,
+ public ::testing::WithParamInterface<bool> {
public:
- PaintPreviewRecorderRenderViewTest() {}
- ~PaintPreviewRecorderRenderViewTest() override {}
-
- void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-
+ PaintPreviewRecorderRenderViewTest() {
+ std::vector<base::Feature> enabled;
// TODO(crbug/1022398): This is required to bypass a seemingly unrelated
// DCHECK for |use_overlay_scrollbars_| in NativeThemeAura on ChromeOS when
// painting scrollbars when first calling LoadHTML().
feature_list_.InitAndDisableFeature(features::kOverlayScrollbar);
+ blink::WebTestingSupport::SaveRuntimeFeatures();
+ }
+
+ ~PaintPreviewRecorderRenderViewTest() override {
+ // Restore blink runtime features to their original values.
+ blink::WebTestingSupport::ResetRuntimeFeatures();
+ }
+ void SetUp() override {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
RenderViewTest::SetUp();
+ blink::WebRuntimeFeatures::EnableFeatureFromString(kCompositeAfterPaint,
+ GetParam());
}
content::RenderFrame* GetFrame() { return view_->GetMainRenderFrame(); }
@@ -93,7 +115,7 @@ class PaintPreviewRecorderRenderViewTest : public content::RenderViewTest {
base::test::ScopedFeatureList feature_list_;
};
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameAndClipping) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameAndClipping) {
LoadHTML(
"<!doctype html>"
"<body>"
@@ -158,19 +180,20 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameAndClipping) {
0xFFFFFFFFU);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameWithScroll) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameWithScroll) {
LoadHTML(
"<!doctype html>"
"<body>"
- " <div style='width: 600px; height: 80vh; "
+ " <div style='width: 600px; height: 200px; "
" background-color: #ff0000'>&nbsp;</div>"
- " <div style='width: 600px; height: 1200px; "
+ " <div style='width: 600px; height: 5000px; "
" background-color: #00ff00'>&nbsp;</div>"
"</body>");
// Scroll to bottom of page to ensure scroll position has no effect on
// capture.
ExecuteJavaScriptForTests("window.scrollTo(0,document.body.scrollHeight);");
+ content::RunAllTasksUntilIdle();
auto out_response = mojom::PaintPreviewCaptureResponse::New();
content::RenderFrame* frame = GetFrame();
@@ -204,7 +227,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameWithScroll) {
EXPECT_EQ(bitmap.getColor(50, pic->cullRect().height() - 100), 0xFF00FF00U);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureFragment) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureFragment) {
// Use position absolute position to check that the captured link dimensions
// match what is specified.
LoadHTML(
@@ -232,7 +255,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureFragment) {
EXPECT_EQ(out_response->links[0]->rect.height(), 30);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureInvalidFile) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureInvalidFile) {
LoadHTML("<body></body>");
mojom::PaintPreviewCaptureParamsPtr params =
@@ -255,7 +278,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureInvalidFile) {
content::RunAllTasksUntilIdle();
}
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureInvalidXYClip) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureInvalidXYClip) {
LoadHTML("<body></body>");
mojom::PaintPreviewCaptureParamsPtr params =
@@ -280,7 +303,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureInvalidXYClip) {
content::RunAllTasksUntilIdle();
}
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameAndLocalFrame) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameAndLocalFrame) {
LoadHTML(
"<!doctype html>"
"<body style='min-height:1000px;'>"
@@ -299,7 +322,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureMainFrameAndLocalFrame) {
EXPECT_EQ(out_response->content_id_to_embedding_token.size(), 0U);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureLocalFrame) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureLocalFrame) {
LoadHTML(
"<!doctype html>"
"<body style='min-height:1000px;'>"
@@ -318,7 +341,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureLocalFrame) {
EXPECT_EQ(out_response->content_id_to_embedding_token.size(), 0U);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureUnclippedLocalFrame) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureUnclippedLocalFrame) {
LoadHTML(
"<!doctype html>"
"<body style='min-height:1000px;'>"
@@ -360,7 +383,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureUnclippedLocalFrame) {
EXPECT_EQ(bitmap.getColor(50, 800), 0xFFFF0000U);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureCustomClipRect) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureCustomClipRect) {
LoadHTML(
"<!doctype html>"
"<body>"
@@ -406,7 +429,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureCustomClipRect) {
EXPECT_EQ(out_response->links[0]->rect.height(), 30);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureWithClamp) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureWithClamp) {
LoadHTML(
"<!doctype html>"
"<body>"
@@ -440,7 +463,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureWithClamp) {
EXPECT_LT(pic->cullRect().width(), kLarge);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureFullIfWidthHeightAre0) {
+TEST_P(PaintPreviewRecorderRenderViewTest, TestCaptureFullIfWidthHeightAre0) {
LoadHTML(
"<!doctype html>"
"<body>"
@@ -473,7 +496,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureFullIfWidthHeightAre0) {
EXPECT_GT(pic->cullRect().width(), 0U);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithTranslate) {
+TEST_P(PaintPreviewRecorderRenderViewTest, CaptureWithTranslate) {
// URLs should be annotated correctly when a CSS transform is applied.
LoadHTML(
R"(
@@ -513,7 +536,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithTranslate) {
EXPECT_NEAR(out_response->links[0]->rect.height(), 20, 3);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithTranslateThenRotate) {
+TEST_P(PaintPreviewRecorderRenderViewTest, CaptureWithTranslateThenRotate) {
// URLs should be annotated correctly when a CSS transform is applied.
LoadHTML(
R"(
@@ -555,7 +578,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithTranslateThenRotate) {
#endif
}
-TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithRotateThenTranslate) {
+TEST_P(PaintPreviewRecorderRenderViewTest, CaptureWithRotateThenTranslate) {
// URLs should be annotated correctly when a CSS transform is applied.
LoadHTML(
R"(
@@ -597,7 +620,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithRotateThenTranslate) {
#endif
}
-TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithScale) {
+TEST_P(PaintPreviewRecorderRenderViewTest, CaptureWithScale) {
// URLs should be annotated correctly when a CSS transform is applied.
LoadHTML(
R"(
@@ -637,7 +660,7 @@ TEST_F(PaintPreviewRecorderRenderViewTest, CaptureWithScale) {
EXPECT_NEAR(out_response->links[0]->rect.height(), 20, 3);
}
-TEST_F(PaintPreviewRecorderRenderViewTest, CaptureSaveRestore) {
+TEST_P(PaintPreviewRecorderRenderViewTest, CaptureSaveRestore) {
// URLs should be annotated correctly when a CSS transform is applied.
LoadHTML(
R"(
@@ -694,4 +717,9 @@ TEST_F(PaintPreviewRecorderRenderViewTest, CaptureSaveRestore) {
EXPECT_NEAR(out_response->links[1]->rect.height(), 20, 3);
}
+INSTANTIATE_TEST_SUITE_P(All,
+ PaintPreviewRecorderRenderViewTest,
+ testing::Values(true, false),
+ CompositeAfterPaintToString);
+
} // namespace paint_preview
diff --git a/chromium/components/paint_preview/renderer/paint_preview_recorder_impl.cc b/chromium/components/paint_preview/renderer/paint_preview_recorder_impl.cc
index 75efd829b7b..e17aaa71e77 100644
--- a/chromium/components/paint_preview/renderer/paint_preview_recorder_impl.cc
+++ b/chromium/components/paint_preview/renderer/paint_preview_recorder_impl.cc
@@ -11,18 +11,19 @@
#include "base/bind.h"
#include "base/bind_post_task.h"
#include "base/metrics/histogram_functions.h"
-#include "base/optional.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/task_runner.h"
#include "base/time/time.h"
#include "base/trace_event/common/trace_event_common.h"
+#include "base/trace_event/trace_event.h"
#include "cc/paint/paint_record.h"
#include "cc/paint/paint_recorder.h"
#include "components/paint_preview/common/paint_preview_tracker.h"
#include "components/paint_preview/common/serialized_recording.h"
#include "components/paint_preview/renderer/paint_preview_recorder_utils.h"
#include "content/public/renderer/render_frame.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/web/web_local_frame.h"
@@ -58,7 +59,7 @@ void BuildAndSendResponse(std::unique_ptr<PaintPreviewTracker> tracker,
FinishedRecording out,
CapturePaintPreviewCallback callback) {
if (out.status == mojom::PaintPreviewStatus::kOk) {
- BuildResponse(tracker.get(), out.response.get(), /*log=*/true);
+ BuildResponse(tracker.get(), out.response.get());
}
std::move(callback).Run(out.status, std::move(out.response));
}
@@ -68,7 +69,7 @@ void BuildAndSendResponse(std::unique_ptr<PaintPreviewTracker> tracker,
void RecordToFileOnThreadPool(sk_sp<const SkPicture> skp,
base::File skp_file,
std::unique_ptr<PaintPreviewTracker> tracker,
- base::Optional<size_t> max_capture_size,
+ absl::optional<size_t> max_capture_size,
FinishedRecording out,
CapturePaintPreviewCallback callback) {
TRACE_EVENT0("paint_preview", "RecordToFileOnThreadPool");
@@ -87,7 +88,7 @@ void RecordToFileOnThreadPool(sk_sp<const SkPicture> skp,
void SerializeFileRecording(sk_sp<const SkPicture> skp,
base::File skp_file,
std::unique_ptr<PaintPreviewTracker> tracker,
- base::Optional<size_t> max_capture_size,
+ absl::optional<size_t> max_capture_size,
FinishedRecording out,
CapturePaintPreviewCallback callback) {
base::ThreadPool::PostTask(
@@ -104,12 +105,12 @@ void SerializeFileRecording(sk_sp<const SkPicture> skp,
void SerializeMemoryBufferRecording(
sk_sp<const SkPicture> skp,
std::unique_ptr<PaintPreviewTracker> tracker,
- base::Optional<size_t> max_capture_size,
+ absl::optional<size_t> max_capture_size,
FinishedRecording out,
CapturePaintPreviewCallback callback) {
TRACE_EVENT0("paint_preview", "SerializeMemoryBufferRecording");
size_t serialized_size = 0;
- base::Optional<mojo_base::BigBuffer> buffer =
+ absl::optional<mojo_base::BigBuffer> buffer =
RecordToBuffer(skp, tracker.get(), max_capture_size, &serialized_size);
out.status = buffer.has_value() ? mojom::PaintPreviewStatus::kOk
: mojom::PaintPreviewStatus::kCaptureFailed;
@@ -126,7 +127,7 @@ void FinishRecordingOnUIThread(sk_sp<const cc::PaintRecord> recording,
std::unique_ptr<PaintPreviewTracker> tracker,
RecordingPersistence persistence,
base::File skp_file,
- base::Optional<size_t> max_capture_size,
+ absl::optional<size_t> max_capture_size,
mojom::PaintPreviewCaptureResponsePtr response,
CapturePaintPreviewCallback callback) {
TRACE_EVENT0("paint_preview", "FinishRecordingOnUIThread");
@@ -137,9 +138,9 @@ void FinishRecordingOnUIThread(sk_sp<const cc::PaintRecord> recording,
return;
}
- TRACE_EVENT_BEGIN0("paint_preview", "ParseGlyphsAndLinks");
- ParseGlyphsAndLinks(recording.get(), tracker.get());
- TRACE_EVENT_END0("paint_preview", "ParseGlyphsAndLinks");
+ TRACE_EVENT_BEGIN0("paint_preview", "PreProcessPaintOpBuffer");
+ PreProcessPaintOpBuffer(recording.get(), tracker.get());
+ TRACE_EVENT_END0("paint_preview", "PreProcessPaintOpBuffer");
// This cannot be done async if the recording contains a GPU accelerated
// image.
@@ -297,7 +298,8 @@ void PaintPreviewRecorderImpl::CapturePaintPreviewInternal(
base::TimeTicks start_time = base::TimeTicks::Now();
TRACE_EVENT_BEGIN0("paint_preview", "WebLocalFrame::CapturePaintPreview");
bool success = frame->CapturePaintPreview(
- bounds, canvas, /*include_linked_destinations=*/params->capture_links);
+ bounds, canvas, /*include_linked_destinations=*/params->capture_links,
+ /*skip_accelerated_content=*/params->skip_accelerated_content);
TRACE_EVENT_END0("paint_preview", "WebLocalFrame::CapturePaintPreview");
canvas->restore();
base::TimeDelta capture_time = base::TimeTicks::Now() - start_time;
@@ -330,17 +332,20 @@ void PaintPreviewRecorderImpl::CapturePaintPreviewInternal(
return;
}
- // Convert the special value |0| to |base::nullopt|.
- base::Optional<size_t> max_capture_size;
+ // Convert the special value |0| to |absl::nullopt|.
+ absl::optional<size_t> max_capture_size;
if (params->max_capture_size == 0) {
- max_capture_size = base::nullopt;
+ max_capture_size = absl::nullopt;
} else {
max_capture_size = params->max_capture_size;
auto* image_ctx = tracker->GetImageSerializationContext();
image_ctx->remaining_image_size = params->max_capture_size;
- image_ctx->max_representation_size = params->max_capture_size;
}
+ auto* image_ctx = tracker->GetImageSerializationContext();
+ image_ctx->max_decoded_image_size_bytes =
+ params->max_decoded_image_size_bytes;
+
FinishRecordingOnUIThread(recorder.finishRecordingAsPicture(), bounds,
std::move(tracker), params->persistence,
std::move(params->file), max_capture_size,
diff --git a/chromium/components/paint_preview/renderer/paint_preview_recorder_utils.cc b/chromium/components/paint_preview/renderer/paint_preview_recorder_utils.cc
index b9f9fb794ac..e4ec8a5a186 100644
--- a/chromium/components/paint_preview/renderer/paint_preview_recorder_utils.cc
+++ b/chromium/components/paint_preview/renderer/paint_preview_recorder_utils.cc
@@ -9,9 +9,8 @@
#include "base/bind.h"
#include "base/trace_event/common/trace_event_common.h"
#include "base/trace_event/trace_event.h"
-#include "cc/paint/draw_image.h"
-#include "cc/paint/image_provider.h"
#include "cc/paint/paint_image.h"
+#include "cc/paint/paint_image_builder.h"
#include "components/paint_preview/common/file_stream.h"
#include "components/paint_preview/common/paint_preview_tracker.h"
#include "mojo/public/cpp/base/shared_memory_utils.h"
@@ -20,8 +19,37 @@
namespace paint_preview {
-void ParseGlyphsAndLinks(const cc::PaintOpBuffer* buffer,
- PaintPreviewTracker* tracker) {
+namespace {
+
+// Converts a texture backed paint image in the PaintOpBuffer to one that is not
+// texture backed.
+cc::PaintImage MakeUnaccelerated(cc::PaintImage& paint_image) {
+ DCHECK(paint_image.IsTextureBacked());
+ auto sk_image = paint_image.GetSwSkImage();
+ if (sk_image->isLazyGenerated()) {
+ // Texture backed images should always be returned as SkImage_Raster type
+ // (bitmap). This is just a catchall in the event a lazy image is somehow
+ // returned in which case we should just raster it.
+ SkBitmap bitmap;
+ bitmap.allocPixels(sk_image->imageInfo(),
+ sk_image->imageInfo().minRowBytes());
+ if (!sk_image->readPixels(bitmap.pixmap(), 0, 0)) {
+ return paint_image;
+ }
+ // Make immutable to skip an extra copy.
+ bitmap.setImmutable();
+ sk_image = SkImage::MakeFromBitmap(bitmap);
+ }
+ return cc::PaintImageBuilder::WithDefault()
+ .set_id(cc::PaintImage::GetNextId())
+ .set_image(sk_image, cc::PaintImage::GetNextContentId())
+ .TakePaintImage();
+}
+
+} // namespace
+
+void PreProcessPaintOpBuffer(const cc::PaintOpBuffer* buffer,
+ PaintPreviewTracker* tracker) {
for (cc::PaintOpBuffer::Iterator it(buffer); it; ++it) {
switch (it->GetType()) {
case cc::PaintOpType::DrawTextBlob: {
@@ -33,7 +61,7 @@ void ParseGlyphsAndLinks(const cc::PaintOpBuffer* buffer,
// Recurse into nested records if they contain text blobs (equivalent to
// nested SkPictures).
auto* record_op = static_cast<cc::DrawRecordOp*>(*it);
- ParseGlyphsAndLinks(record_op->record.get(), tracker);
+ PreProcessPaintOpBuffer(record_op->record.get(), tracker);
break;
}
case cc::PaintOpType::Annotate: {
@@ -92,33 +120,26 @@ void ParseGlyphsAndLinks(const cc::PaintOpBuffer* buffer,
tracker->Translate(translate_op->dx, translate_op->dy);
break;
}
+ case cc::PaintOpType::DrawImage: {
+ auto* image_op = static_cast<cc::DrawImageOp*>(*it);
+ if (image_op->image.IsTextureBacked()) {
+ image_op->image = MakeUnaccelerated(image_op->image);
+ }
+ break;
+ }
+ case cc::PaintOpType::DrawImageRect: {
+ auto* image_op = static_cast<cc::DrawImageRectOp*>(*it);
+ if (image_op->image.IsTextureBacked()) {
+ image_op->image = MakeUnaccelerated(image_op->image);
+ }
+ break;
+ }
default:
continue;
}
}
}
-class SkPictureImageProvider : public cc::ImageProvider {
- public:
- SkPictureImageProvider() = default;
- ~SkPictureImageProvider() override = default;
-
- SkPictureImageProvider& operator=(const SkPictureImageProvider&) = delete;
- SkPictureImageProvider& operator=(SkPictureImageProvider&& other);
-
- // Converts GPU accelerated content into software rastered content using
- // GetSwSkImage().
- cc::ImageProvider::ScopedResult GetRasterContent(
- const cc::DrawImage& draw_image) override {
- const cc::PaintImage& paint_image = draw_image.paint_image();
- return cc::ImageProvider::ScopedResult(cc::DecodedDrawImage(
- paint_image.GetSwSkImage(), /*dark_mode_color_filter=*/nullptr,
- /*src_rect_offset=*/SkSize::Make(0, 0),
- /*scale_adjustment=*/SkSize::Make(1.f, 1.f),
- draw_image.filter_quality(), /*is_budgeted=*/true));
- }
-};
-
sk_sp<const SkPicture> PaintRecordToSkPicture(
sk_sp<const cc::PaintRecord> recording,
PaintPreviewTracker* tracker,
@@ -129,10 +150,9 @@ sk_sp<const SkPicture> PaintRecordToSkPicture(
base::BindRepeating(&PaintPreviewTracker::CustomDataToSkPictureCallback,
base::Unretained(tracker));
- SkPictureImageProvider raster_accelerated_images;
auto skp =
ToSkPicture(recording, SkRect::MakeWH(bounds.width(), bounds.height()),
- &raster_accelerated_images, custom_callback);
+ nullptr, custom_callback);
if (!skp || skp->cullRect().width() == 0 || skp->cullRect().height() == 0)
return nullptr;
@@ -141,18 +161,11 @@ sk_sp<const SkPicture> PaintRecordToSkPicture(
}
void BuildResponse(PaintPreviewTracker* tracker,
- mojom::PaintPreviewCaptureResponse* response,
- bool log) {
+ mojom::PaintPreviewCaptureResponse* response) {
// Ensure these always exist.
DCHECK(tracker);
DCHECK(response);
- // paint_preview::BuildResponse has been showing in a large number of crashes
- // under stack scans. In order to determine if these entries are "real" we
- // should log the calls and check the log output.
- if (log)
- LOG(WARNING) << "paint_preview::BuildResponse() called";
-
response->embedding_token = tracker->EmbeddingToken();
tracker->MoveLinks(&response->links);
diff --git a/chromium/components/paint_preview/renderer/paint_preview_recorder_utils.h b/chromium/components/paint_preview/renderer/paint_preview_recorder_utils.h
index adfab3e0e99..47ddf3dff2a 100644
--- a/chromium/components/paint_preview/renderer/paint_preview_recorder_utils.h
+++ b/chromium/components/paint_preview/renderer/paint_preview_recorder_utils.h
@@ -21,10 +21,13 @@ namespace paint_preview {
class PaintPreviewTracker;
-// Walks |buffer| to extract all the glyphs from its text blobs and links. The
-// extracted data is written to to |tracker|.
-void ParseGlyphsAndLinks(const cc::PaintOpBuffer* buffer,
- PaintPreviewTracker* tracker);
+// Pre processes the PaintOpBuffer prior to conversion to SkPicture.
+// 1. Walks |buffer| to extract all the glyphs from its text blobs and links.
+// The extracted data is written to `tracker`.
+// 2. Tracks geometry changes for frames and saves them to `tracker`.
+// 3. Unaccelerates GPU accelerated PaintImages.
+void PreProcessPaintOpBuffer(const cc::PaintOpBuffer* buffer,
+ PaintPreviewTracker* tracker);
// Convert |recording| into an SkPicture, tracking embedded content. Will return
// |nullptr| if the resulting picture failed or zero sized.
@@ -35,8 +38,7 @@ sk_sp<const SkPicture> PaintRecordToSkPicture(
// NOTE: |tracker| is effectively const here despite being passed by pointer.
void BuildResponse(PaintPreviewTracker* tracker,
- mojom::PaintPreviewCaptureResponse* response,
- bool log = false);
+ mojom::PaintPreviewCaptureResponse* response);
} // namespace paint_preview
diff --git a/chromium/components/paint_preview/renderer/paint_preview_recorder_utils_unittest.cc b/chromium/components/paint_preview/renderer/paint_preview_recorder_utils_unittest.cc
index 19a10d21c71..532e18b3989 100644
--- a/chromium/components/paint_preview/renderer/paint_preview_recorder_utils_unittest.cc
+++ b/chromium/components/paint_preview/renderer/paint_preview_recorder_utils_unittest.cc
@@ -14,12 +14,14 @@
#include "base/memory/discardable_memory_allocator.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/test/test_discardable_memory_allocator.h"
#include "base/unguessable_token.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_flags.h"
+#include "cc/paint/paint_image.h"
+#include "cc/paint/paint_image_builder.h"
#include "cc/paint/paint_recorder.h"
+#include "cc/paint/paint_worklet_input.h"
#include "components/paint_preview/common/file_stream.h"
#include "components/paint_preview/common/mojom/paint_preview_recorder.mojom-shared.h"
#include "components/paint_preview/common/paint_preview_tracker.h"
@@ -28,6 +30,7 @@
#include "mojo/public/cpp/base/big_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkFont.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkTextBlob.h"
@@ -68,7 +71,7 @@ TEST(PaintPreviewRecorderUtilsTest, TestParseGlyphs) {
PaintPreviewTracker tracker(base::UnguessableToken::Create(),
base::UnguessableToken::Create(), true);
- ParseGlyphsAndLinks(record.get(), &tracker);
+ PreProcessPaintOpBuffer(record.get(), &tracker);
auto* usage_map = tracker.GetTypefaceUsageMap();
EXPECT_TRUE(usage_map->count(typeface->uniqueID()));
EXPECT_TRUE(
@@ -129,7 +132,7 @@ TEST(PaintPreviewRecorderUtilsTest, TestParseLinks) {
PaintPreviewTracker tracker(base::UnguessableToken::Create(),
base::UnguessableToken::Create(), true);
- ParseGlyphsAndLinks(record.get(), &tracker);
+ PreProcessPaintOpBuffer(record.get(), &tracker);
std::vector<mojom::LinkDataPtr> links;
tracker.MoveLinks(&links);
@@ -184,7 +187,7 @@ TEST(PaintPreviewRecorderUtilsTest, TestTransformSubframeRects) {
EXPECT_EQ(rect.width(), old_cull_rect.width());
EXPECT_EQ(rect.height(), old_cull_rect.height());
- ParseGlyphsAndLinks(record.get(), &tracker);
+ PreProcessPaintOpBuffer(record.get(), &tracker);
auto* picture_ctx = tracker.GetPictureSerializationContext();
ASSERT_EQ(picture_ctx->content_id_to_transformed_clip.size(), 1U);
@@ -218,26 +221,20 @@ class PaintPreviewRecorderUtilsSerializeAsSkPictureTest
cc::PaintFlags flags;
canvas->drawRect(SkRect::MakeWH(dimensions.width(), dimensions.height()),
flags);
- SkBitmap bitmap;
- bitmap.allocN32Pixels(dimensions.width(), dimensions.height());
- {
- SkCanvas sk_canvas(bitmap);
- sk_canvas.drawColor(SK_ColorRED);
- }
- canvas->drawImage(cc::PaintImage::CreateFromBitmap(bitmap), 0, 0);
}
void TearDown() override {
base::DiscardableMemoryAllocator::SetInstance(nullptr);
}
- base::Optional<SerializedRecording> SerializeAsSkPicture(
- base::Optional<size_t> max_capture_size,
+ absl::optional<SerializedRecording> SerializeAsSkPicture(
+ absl::optional<size_t> max_capture_size,
size_t* serialized_size) {
- auto skp = PaintRecordToSkPicture(recorder.finishRecordingAsPicture(),
- &tracker, dimensions);
+ auto recording = recorder.finishRecordingAsPicture();
+ PreProcessPaintOpBuffer(recording.get(), &tracker);
+ auto skp = PaintRecordToSkPicture(recording, &tracker, dimensions);
if (!skp)
- return base::nullopt;
+ return absl::nullopt;
canvas = nullptr;
@@ -245,30 +242,30 @@ class PaintPreviewRecorderUtilsSerializeAsSkPictureTest
case RecordingPersistence::kFileSystem: {
base::ScopedTempDir temp_dir;
if (!temp_dir.CreateUniqueTempDir())
- return base::nullopt;
+ return absl::nullopt;
base::FilePath file_path = temp_dir.GetPath().AppendASCII("test_file");
base::File write_file(
file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
if (!RecordToFile(std::move(write_file), skp, &tracker,
max_capture_size, serialized_size))
- return base::nullopt;
+ return absl::nullopt;
return {SerializedRecording(file_path)};
} break;
case RecordingPersistence::kMemoryBuffer: {
- base::Optional<mojo_base::BigBuffer> buffer =
+ absl::optional<mojo_base::BigBuffer> buffer =
RecordToBuffer(skp, &tracker, max_capture_size, serialized_size);
if (!buffer.has_value())
- return base::nullopt;
+ return absl::nullopt;
return {SerializedRecording(std::move(buffer.value()))};
} break;
}
NOTREACHED();
- return base::nullopt;
+ return absl::nullopt;
}
PaintPreviewTracker tracker;
@@ -298,16 +295,36 @@ TEST_P(PaintPreviewRecorderUtilsSerializeAsSkPictureTest, Roundtrip) {
ctx.insert(content_id);
size_t out_size = 0;
- auto recording = SerializeAsSkPicture(base::nullopt, &out_size);
+ auto recording = SerializeAsSkPicture(absl::nullopt, &out_size);
ASSERT_TRUE(recording.has_value());
- base::Optional<SkpResult> result = std::move(recording.value()).Deserialize();
+ absl::optional<SkpResult> result = std::move(recording.value()).Deserialize();
ASSERT_TRUE(result.has_value());
for (auto& content_id : ctx) {
EXPECT_TRUE(result->ctx.contains(content_id));
result->ctx.erase(content_id);
}
EXPECT_TRUE(result->ctx.empty());
+}
+
+TEST_P(PaintPreviewRecorderUtilsSerializeAsSkPictureTest, RoundtripWithImage) {
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(dimensions.width(), dimensions.height());
+ SkCanvas sk_canvas(bitmap);
+ sk_canvas.drawColor(SK_ColorRED);
+ cc::PaintImage paint_image = cc::PaintImage::CreateFromBitmap(bitmap);
+ ASSERT_FALSE(paint_image.IsLazyGenerated());
+ ASSERT_FALSE(paint_image.IsPaintWorklet());
+ canvas->drawImage(paint_image, 0U, 0U);
+ }
+
+ size_t out_size = 0;
+ auto recording = SerializeAsSkPicture(absl::nullopt, &out_size);
+ ASSERT_TRUE(recording.has_value());
+
+ absl::optional<SkpResult> result = std::move(recording.value()).Deserialize();
+ ASSERT_TRUE(result.has_value());
SkBitmap bitmap;
bitmap.allocN32Pixels(dimensions.width(), dimensions.height());
@@ -316,6 +333,179 @@ TEST_P(PaintPreviewRecorderUtilsSerializeAsSkPictureTest, Roundtrip) {
EXPECT_EQ(bitmap.getColor(10, 10), SK_ColorRED);
}
+class FakeTextureBacking : public cc::TextureBacking {
+ public:
+ explicit FakeTextureBacking(sk_sp<SkImage> image) : image_(image) {}
+
+ const SkImageInfo& GetSkImageInfo() override { return image_->imageInfo(); }
+ gpu::Mailbox GetMailbox() const override { return mailbox_; }
+ sk_sp<SkImage> GetAcceleratedSkImage() override { return nullptr; }
+ sk_sp<SkImage> GetSkImageViaReadback() override { return image_; }
+ bool readPixels(const SkImageInfo& dstInfo,
+ void* dstPixels,
+ size_t dstRowBytes,
+ int srcX,
+ int srcY) override {
+ return false;
+ }
+ void FlushPendingSkiaOps() override {}
+
+ private:
+ gpu::Mailbox mailbox_;
+ sk_sp<SkImage> image_;
+};
+
+TEST_P(PaintPreviewRecorderUtilsSerializeAsSkPictureTest,
+ RoundtripWithTexture) {
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(dimensions.width(), dimensions.height());
+ SkCanvas sk_canvas(bitmap);
+ sk_canvas.drawColor(SK_ColorRED);
+ cc::PaintImage paint_image =
+ cc::PaintImageBuilder::WithDefault()
+ .set_id(cc::PaintImage::GetNextId())
+ .set_texture_backing(
+ sk_sp<FakeTextureBacking>(
+ new FakeTextureBacking(SkImage::MakeFromBitmap(bitmap))),
+ cc::PaintImage::GetNextContentId())
+ .TakePaintImage();
+ canvas->drawImage(paint_image, 0U, 0U);
+ }
+
+ size_t out_size = 0;
+ auto recording = SerializeAsSkPicture(absl::nullopt, &out_size);
+ ASSERT_TRUE(recording.has_value());
+
+ absl::optional<SkpResult> result = std::move(recording.value()).Deserialize();
+ ASSERT_TRUE(result.has_value());
+
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(dimensions.width(), dimensions.height());
+ SkCanvas sk_canvas(bitmap);
+ sk_canvas.drawPicture(result->skp);
+ EXPECT_EQ(bitmap.getColor(10, 10), SK_ColorRED);
+}
+
+TEST_P(PaintPreviewRecorderUtilsSerializeAsSkPictureTest,
+ RoundtripWithLazyTexture) {
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(dimensions.width(), dimensions.height());
+ SkCanvas sk_canvas(bitmap);
+ sk_canvas.drawColor(SK_ColorRED);
+ auto sk_image = SkImage::MakeFromBitmap(bitmap);
+ auto data = sk_image->encodeToData();
+ auto lazy_sk_image = SkImage::MakeFromEncoded(data);
+ ASSERT_TRUE(lazy_sk_image->isLazyGenerated());
+ cc::PaintImage paint_image =
+ cc::PaintImageBuilder::WithDefault()
+ .set_id(cc::PaintImage::GetNextId())
+ .set_texture_backing(sk_sp<FakeTextureBacking>(
+ new FakeTextureBacking(lazy_sk_image)),
+ cc::PaintImage::GetNextContentId())
+ .TakePaintImage();
+ cc::PaintFlags paint;
+ paint.setBlendMode(SkBlendMode::kSrc);
+ auto rect = SkRect::MakeWH(dimensions.width(), dimensions.height());
+ canvas->drawImageRect(paint_image, rect, rect, SkSamplingOptions(), &paint,
+ SkCanvas::kStrict_SrcRectConstraint);
+ }
+
+ size_t out_size = 0;
+ auto recording = SerializeAsSkPicture(absl::nullopt, &out_size);
+ ASSERT_TRUE(recording.has_value());
+
+ absl::optional<SkpResult> result = std::move(recording.value()).Deserialize();
+ ASSERT_TRUE(result.has_value());
+
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(dimensions.width(), dimensions.height());
+ SkCanvas sk_canvas(bitmap);
+ sk_canvas.drawPicture(result->skp);
+ EXPECT_EQ(bitmap.getColor(10, 10), SK_ColorRED);
+}
+
+TEST_P(PaintPreviewRecorderUtilsSerializeAsSkPictureTest,
+ RoundtripWithLazyImage) {
+ {
+ cc::PaintRecorder inner_recorder;
+ cc::PaintCanvas* inner_canvas =
+ inner_recorder.beginRecording(dimensions.width(), dimensions.width());
+ inner_canvas->drawColor(SK_ColorRED);
+ cc::PaintImage paint_image =
+ cc::PaintImageBuilder::WithDefault()
+ .set_id(1)
+ .set_paint_record(inner_recorder.finishRecordingAsPicture(),
+ dimensions, cc::PaintImage::GetNextContentId())
+ .TakePaintImage();
+ ASSERT_TRUE(paint_image.IsLazyGenerated());
+ ASSERT_FALSE(paint_image.IsPaintWorklet());
+ canvas->drawImage(paint_image, 0U, 0U);
+ }
+
+ size_t out_size = 0;
+ auto recording = SerializeAsSkPicture(absl::nullopt, &out_size);
+ ASSERT_TRUE(recording.has_value());
+
+ absl::optional<SkpResult> result = std::move(recording.value()).Deserialize();
+ ASSERT_TRUE(result.has_value());
+
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(dimensions.width(), dimensions.height());
+ SkCanvas sk_canvas(bitmap);
+ sk_canvas.drawPicture(result->skp);
+ EXPECT_EQ(bitmap.getColor(10, 10), SK_ColorRED);
+}
+
+class TestPaintWorkletInput : public cc::PaintWorkletInput {
+ public:
+ explicit TestPaintWorkletInput(const gfx::SizeF& size)
+ : container_size_(size) {}
+
+ gfx::SizeF GetSize() const override { return container_size_; }
+ int WorkletId() const override { return 1U; }
+ const std::vector<PaintWorkletInput::PropertyKey>& GetPropertyKeys()
+ const override {
+ return property_keys_;
+ }
+
+ protected:
+ ~TestPaintWorkletInput() override = default;
+
+ private:
+ gfx::SizeF container_size_;
+ std::vector<PaintWorkletInput::PropertyKey> property_keys_;
+};
+
+TEST_P(PaintPreviewRecorderUtilsSerializeAsSkPictureTest,
+ RoundtripWithPaintWorklet) {
+ {
+ gfx::SizeF size(100, 50);
+ scoped_refptr<TestPaintWorkletInput> input =
+ base::MakeRefCounted<TestPaintWorkletInput>(size);
+ cc::PaintImage paint_image = cc::PaintImageBuilder::WithDefault()
+ .set_id(1)
+ .set_paint_worklet_input(std::move(input))
+ .TakePaintImage();
+ ASSERT_FALSE(paint_image.IsLazyGenerated());
+ ASSERT_TRUE(paint_image.IsPaintWorklet());
+ cc::PaintFlags paint;
+ paint.setBlendMode(SkBlendMode::kSrc);
+ auto rect = SkRect::MakeWH(dimensions.width(), dimensions.height());
+ canvas->drawImageRect(paint_image, rect, rect, SkSamplingOptions(), &paint,
+ SkCanvas::kStrict_SrcRectConstraint);
+ }
+
+ size_t out_size = 0;
+ auto recording = SerializeAsSkPicture(absl::nullopt, &out_size);
+ // The paint worklet needs to be skipped. Just make sure it doesn't crash.
+ ASSERT_TRUE(recording.has_value());
+
+ absl::optional<SkpResult> result = std::move(recording.value()).Deserialize();
+ ASSERT_TRUE(result.has_value());
+}
+
TEST_P(PaintPreviewRecorderUtilsSerializeAsSkPictureTest, FailIfExceedMaxSize) {
size_t out_size = 2;
auto recording = SerializeAsSkPicture({1}, &out_size);
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 4278a6a1b6d..61210300f16 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
@@ -261,7 +261,9 @@ void ContentPasswordManagerDriver::InformAboutUserInput(
// not used, such as on Android.
content::SiteInstance::StartIsolatingSite(
render_frame_host_->GetSiteInstance()->GetBrowserContext(),
- form_data.url);
+ form_data.url,
+ content::ChildProcessSecurityPolicy::IsolatedOriginSource::
+ USER_TRIGGERED);
}
}
diff --git a/chromium/components/password_manager/content/browser/password_requirements_service_factory.cc b/chromium/components/password_manager/content/browser/password_requirements_service_factory.cc
index 72f194508e0..45f185df938 100644
--- a/chromium/components/password_manager/content/browser/password_requirements_service_factory.cc
+++ b/chromium/components/password_manager/content/browser/password_requirements_service_factory.cc
@@ -45,7 +45,7 @@ KeyedService* PasswordRequirementsServiceFactory::BuildServiceInstanceFor(
return nullptr;
return CreatePasswordRequirementsService(
- content::BrowserContext::GetDefaultStoragePartition(context)
+ context->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess())
.release();
}
diff --git a/chromium/components/password_manager/content/common/credential_manager_mojom_traits.h b/chromium/components/password_manager/content/common/credential_manager_mojom_traits.h
index 66f6163bedf..4f83523f7ea 100644
--- a/chromium/components/password_manager/content/common/credential_manager_mojom_traits.h
+++ b/chromium/components/password_manager/content/common/credential_manager_mojom_traits.h
@@ -7,9 +7,9 @@
#include <string>
-#include "base/optional.h"
#include "components/password_manager/core/common/credential_manager_types.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/credentialmanager/credential_manager.mojom.h"
namespace mojo {
@@ -50,12 +50,12 @@ struct StructTraits<blink::mojom::CredentialInfoDataView,
return r.type;
}
- static const base::Optional<std::u16string>& id(
+ static const absl::optional<std::u16string>& id(
const password_manager::CredentialInfo& r) {
return r.id;
}
- static const base::Optional<std::u16string>& name(
+ static const absl::optional<std::u16string>& name(
const password_manager::CredentialInfo& r) {
return r.name;
}
@@ -64,7 +64,7 @@ struct StructTraits<blink::mojom::CredentialInfoDataView,
return r.icon;
}
- static const base::Optional<std::u16string>& password(
+ static const absl::optional<std::u16string>& password(
const password_manager::CredentialInfo& r) {
return r.password;
}
diff --git a/chromium/components/password_manager/core/browser/BUILD.gn b/chromium/components/password_manager/core/browser/BUILD.gn
index 21c3d258b8e..191727cca74 100644
--- a/chromium/components/password_manager/core/browser/BUILD.gn
+++ b/chromium/components/password_manager/core/browser/BUILD.gn
@@ -239,8 +239,6 @@ static_library("browser") {
"ui/post_save_compromised_helper.h",
"ui/saved_passwords_presenter.cc",
"ui/saved_passwords_presenter.h",
- "ui/weak_check_utility.cc",
- "ui/weak_check_utility.h",
"votes_uploader.cc",
"votes_uploader.h",
"well_known_change_password_state.cc",
@@ -290,6 +288,7 @@ static_library("browser") {
"//components/sync",
"//components/sync_preferences",
"//components/url_formatter",
+ "//components/variations/net",
"//components/webdata/common",
"//google_apis",
"//net",
@@ -300,7 +299,6 @@ static_library("browser") {
"//third_party/abseil-cpp:absl",
"//third_party/protobuf:protobuf_lite",
"//third_party/re2",
- "//third_party/zxcvbn-cpp",
"//ui/base",
"//ui/gfx",
"//ui/gfx/range",
@@ -322,6 +320,14 @@ static_library("browser") {
]
}
+ if (!is_android && !is_ios) {
+ sources += [
+ "ui/weak_check_utility.cc",
+ "ui/weak_check_utility.h",
+ ]
+ deps += [ "//third_party/zxcvbn-cpp" ]
+ }
+
if ((is_posix && !is_apple) || is_fuchsia) {
sources += [ "login_database_posix.cc" ]
}
@@ -486,6 +492,8 @@ static_library("test_support") {
"android_affiliation/mock_affiliation_fetcher_delegate.h",
"fake_form_fetcher.cc",
"fake_form_fetcher.h",
+ "mock_biometric_authenticator.cc",
+ "mock_biometric_authenticator.h",
"mock_bulk_leak_check_service.cc",
"mock_bulk_leak_check_service.h",
"mock_password_feature_manager.cc",
@@ -669,7 +677,6 @@ source_set("unit_tests") {
"ui/insecure_credentials_reader_unittest.cc",
"ui/post_save_compromised_helper_unittest.cc",
"ui/saved_passwords_presenter_unittest.cc",
- "ui/weak_check_utility_unittest.cc",
"vote_uploads_test_matchers.h",
"votes_uploader_unittest.cc",
"well_known_change_password_state_unittest.cc",
@@ -691,6 +698,10 @@ source_set("unit_tests") {
sources += [ "hash_password_manager_unittest.cc" ]
}
+ if (!is_android && !is_ios) {
+ sources += [ "ui/weak_check_utility_unittest.cc" ]
+ }
+
if (!is_chromeos_ash && !is_android) {
sources += [ "password_store_signin_notifier_impl_unittest.cc" ]
}
diff --git a/chromium/components/password_manager/core/browser/DEPS b/chromium/components/password_manager/core/browser/DEPS
index 3bf69fcbd09..d508df0eeea 100644
--- a/chromium/components/password_manager/core/browser/DEPS
+++ b/chromium/components/password_manager/core/browser/DEPS
@@ -17,6 +17,7 @@ include_rules = [
"+components/ukm",
"+components/url_formatter",
"+components/webdata/common",
+ "+components/variations/net",
"+crypto",
"+google_apis",
"+grit",
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/DIR_METADATA b/chromium/components/password_manager/core/browser/android_affiliation/DIR_METADATA
deleted file mode 100644
index 43d76b8a8a7..00000000000
--- a/chromium/components/password_manager/core/browser/android_affiliation/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "UI>Browser>Passwords"
-}
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 07f4b2a253e..56737cfd30a 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
@@ -120,8 +120,8 @@ const char kTestAndroidFacetURIGamma[] =
const char kTestAndroidRealmGamma[] =
"android://hash@com.example.gamma.android";
-const char kTestUsername[] = "JohnDoe";
-const char kTestPassword[] = "secret";
+const char16_t kTestUsername[] = u"JohnDoe";
+const char16_t kTestPassword[] = u"secret";
AffiliatedFacets GetTestEquivalenceClassAlpha() {
return {
@@ -149,8 +149,8 @@ PasswordForm GetTestAndroidCredentials(const char* signon_realm) {
PasswordForm form;
form.scheme = PasswordForm::Scheme::kHtml;
form.signon_realm = signon_realm;
- form.username_value = base::ASCIIToUTF16(kTestUsername);
- form.password_value = base::ASCIIToUTF16(kTestPassword);
+ form.username_value = kTestUsername;
+ form.password_value = kTestPassword;
return form;
}
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_database.h b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_database.h
index 84ea89d8f37..c41b283fba4 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_database.h
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_database.h
@@ -9,7 +9,6 @@
#include <vector>
#include "base/macros.h"
-#include "base/time/time.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
#include "components/password_manager/core/browser/sql_table_builder.h"
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_utils.cc b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_utils.cc
index cdc5735d8ab..aa2d429c6b4 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/affiliation_utils.cc
+++ b/chromium/components/password_manager/core/browser/android_affiliation/affiliation_utils.cc
@@ -246,14 +246,14 @@ bool FacetURI::IsValidAndroidFacetURI() const {
std::string FacetURI::scheme() const {
return is_valid()
- ? ComponentString(canonical_spec_, parsed_.scheme).as_string()
+ ? std::string(ComponentString(canonical_spec_, parsed_.scheme))
: "";
}
std::string FacetURI::android_package_name() const {
if (!IsValidAndroidFacetURI())
return "";
- return ComponentString(canonical_spec_, parsed_.host).as_string();
+ return std::string(ComponentString(canonical_spec_, parsed_.host));
}
FacetURI::FacetURI(const std::string& canonical_spec, bool is_valid)
diff --git a/chromium/components/password_manager/core/browser/android_affiliation/android_affiliation_service.h b/chromium/components/password_manager/core/browser/android_affiliation/android_affiliation_service.h
index ce201264510..1c28ef382ac 100644
--- a/chromium/components/password_manager/core/browser/android_affiliation/android_affiliation_service.h
+++ b/chromium/components/password_manager/core/browser/android_affiliation/android_affiliation_service.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_ANDROID_AFFILIATION_SERVICE_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ANDROID_AFFILIATION_ANDROID_AFFILIATION_SERVICE_H_
-#include <string>
-
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/components/password_manager/core/browser/biometric_authenticator.h b/chromium/components/password_manager/core/browser/biometric_authenticator.h
index 3b1038fb9d1..9cdb611d63f 100644
--- a/chromium/components/password_manager/core/browser/biometric_authenticator.h
+++ b/chromium/components/password_manager/core/browser/biometric_authenticator.h
@@ -6,41 +6,113 @@
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_BIOMETRIC_AUTHENTICATOR_H_
#include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
namespace password_manager {
-class UiCredential;
-
// Different states for biometric availability for a given device. Either no
// biometric hardware is available, hardware is available but the user has no
// biometrics enrolled, or hardware is available and the user makes use of it.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+//
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.password_manager
enum class BiometricsAvailability {
- kAvailable = 0,
- kNoHardware = 1,
- kNotEnrolled = 2,
+ kOtherError = 0,
+ kAvailable = 1,
+ kAvailableNoFallback = 2,
+ kNoHardware = 3,
+ kHwUnavailable = 4,
+ kNotEnrolled = 5,
+ kSecurityUpdateRequired = 6,
+ kAndroidVersionNotSupported = 7,
+
+ kMaxValue = kAndroidVersionNotSupported,
+};
+
+// The filling surface asking for biometric authentication.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class BiometricAuthRequester {
+ // The filling surface shown on the first tap on the field after page load.
+ // This surface has replaced autofilling on Android.
+ kTouchToFill = 0,
+
+ // The suggestion presented in the keyboard accessory or autofill popup.
+ kAutofillSuggestion = 1,
+
+ // The keyboard accessory sheet displaying suggestions for manual filling.
+ kFallbackSheet = 2,
+
+ // The list displaying all saved passwords. Can be used for filling on
+ // Android.
+ kAllPasswordsList = 3,
+
+ // The dialog displayed via the Credential Management API.
+ kAccountChooserDialog = 4,
+
+ kMaxValue = kAccountChooserDialog,
+};
+
+// The result of the biometric authentication.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class BiometricAuthFinalResult {
+ // This value is used for when we don't know the exact auth method used. This
+ // can be the case on Android versions under 11.
+ kSuccessWithUnknownMethod = 0,
+ kSuccessWithBiometrics = 1,
+ kSuccessWithDeviceLock = 2,
+ kCanceledByUser = 3,
+ kFailed = 4,
+
+ // Recorded when the auth succeeds after Chrome cancelled it.
+ kSuccessButCanceled = 5,
+
+ // Recorded when the auth fails after Chrome cancelled it.
+ kFailedAndCanceled = 6,
+
+ // Recorded if an authentication was requested within 60s of the previous
+ // successful authentication.
+ kAuthStillValid = 7,
+
+ kMaxValue = kAuthStillValid,
};
// This interface encapsulates operations related to biometric authentication.
// It's intended to be used prior to sharing the user's credentials with a
// website, either via form filling or the Credential Management API.
-class BiometricAuthenticator {
+class BiometricAuthenticator : public base::RefCounted<BiometricAuthenticator> {
public:
using AuthenticateCallback = base::OnceCallback<void(bool)>;
BiometricAuthenticator() = default;
BiometricAuthenticator(const BiometricAuthenticator&) = delete;
BiometricAuthenticator& operator=(const BiometricAuthenticator&) = delete;
- virtual ~BiometricAuthenticator() = default;
// Returns whether biometrics are available for a given device. Only if this
// returns kAvailable, callers can expect Authenticate() to succeed.
virtual BiometricsAvailability CanAuthenticate() = 0;
- // Asks the user to authenticate for the given |credential|. Invokes
- // |callback| asynchronously on the main thread with the result.
- virtual void Authenticate(const UiCredential& credential,
+ // Asks the user to authenticate. Invokes |callback| asynchronously when
+ // the auth flow returns with the result.
+ // |requester| is the filling surface that is asking for authentication.
+ virtual void Authenticate(BiometricAuthRequester requester,
AuthenticateCallback callback) = 0;
+
+ // Cancels an in-progress authentication if the filling surface requesting
+ // the cancelation corresponds to the one for which the ongoing auth was
+ // triggered.
+ virtual void Cancel(BiometricAuthRequester requester) = 0;
+
+ protected:
+ virtual ~BiometricAuthenticator() = default;
+
+ private:
+ friend class base::RefCounted<BiometricAuthenticator>;
};
} // namespace password_manager
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 5af2b6915d7..6aa946ce043 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
@@ -157,7 +157,7 @@ void BrowserSavePasswordProgressLogger::LogSuccessiveOrigins(
std::string
BrowserSavePasswordProgressLogger::FormStructurePasswordAttributesLogString(
const FormStructure& form) {
- const base::Optional<std::pair<PasswordAttribute, bool>> attribute_vote =
+ const absl::optional<std::pair<PasswordAttribute, bool>> attribute_vote =
form.get_password_attributes_vote();
if (!attribute_vote.has_value())
return std::string();
diff --git a/chromium/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc b/chromium/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc
index cfa4ee025c5..48bbedc6461 100644
--- a/chromium/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc
+++ b/chromium/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc
@@ -29,8 +29,8 @@ using ::testing::WithArg;
const int64_t kMockElapsedTime =
base::ScopedMockElapsedTimersForTest::kMockElapsedTime.InMilliseconds();
-constexpr char kUsername[] = "user";
-constexpr char kPassword[] = "password123";
+constexpr char16_t kUsername[] = u"user";
+constexpr char16_t kPassword[] = u"password123";
MATCHER_P(CredentialsAre, credentials, "") {
return std::equal(arg.begin(), arg.end(), credentials.get().begin(),
@@ -48,8 +48,7 @@ MATCHER_P(CredentialIs, credential, "") {
}
LeakCheckCredential TestCredential() {
- return LeakCheckCredential(base::ASCIIToUTF16(kUsername),
- base::ASCIIToUTF16(kPassword));
+ return LeakCheckCredential(kUsername, kPassword);
}
std::vector<LeakCheckCredential> TestCredentials() {
diff --git a/chromium/components/password_manager/core/browser/change_password_url_service_impl.cc b/chromium/components/password_manager/core/browser/change_password_url_service_impl.cc
index 8f03061fc9c..55fbcf1816a 100644
--- a/chromium/components/password_manager/core/browser/change_password_url_service_impl.cc
+++ b/chromium/components/password_manager/core/browser/change_password_url_service_impl.cc
@@ -152,7 +152,7 @@ void ChangePasswordUrlServiceImpl::OnFetchComplete(
base::UmaHistogramTimes(kGstaticFetchTimeMetricName, fetch_timer_.Elapsed());
// TODO(crbug.com/1086141): Log error codes in histograms.
if (response_body) {
- base::Optional<base::Value> data = base::JSONReader::Read(*response_body);
+ absl::optional<base::Value> data = base::JSONReader::Read(*response_body);
if (data && data->is_dict()) {
state_ = FetchState::kFetchSucceeded;
base::UmaHistogramEnumeration(
diff --git a/chromium/components/password_manager/core/browser/credential_cache.h b/chromium/components/password_manager/core/browser/credential_cache.h
index cbb13ad811b..832d7c854f9 100644
--- a/chromium/components/password_manager/core/browser/credential_cache.h
+++ b/chromium/components/password_manager/core/browser/credential_cache.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CREDENTIAL_CACHE_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_CREDENTIAL_CACHE_H_
-#include <string>
#include <vector>
#include "base/types/strong_alias.h"
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 f755962375e..c9734a6cb2c 100644
--- a/chromium/components/password_manager/core/browser/credential_manager_impl.cc
+++ b/chromium/components/password_manager/core/browser/credential_manager_impl.cc
@@ -109,7 +109,7 @@ void CredentialManagerImpl::Get(CredentialMediationRequirement mediation,
std::move(callback).Run(
pending_request_ ? CredentialManagerError::PENDING_REQUEST
: CredentialManagerError::PASSWORDSTOREUNAVAILABLE,
- base::nullopt);
+ absl::nullopt);
LogCredentialManagerGetResult(
metrics_util::CredentialManagerGetResult::kRejected, mediation);
return;
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 c9de1a1a5db..83e7e91bc22 100644
--- a/chromium/components/password_manager/core/browser/credential_manager_impl.h
+++ b/chromium/components/password_manager/core/browser/credential_manager_impl.h
@@ -23,7 +23,7 @@ using StoreCallback = base::OnceCallback<void()>;
using PreventSilentAccessCallback = base::OnceCallback<void()>;
using GetCallback =
base::OnceCallback<void(CredentialManagerError,
- const base::Optional<CredentialInfo>&)>;
+ const absl::optional<CredentialInfo>&)>;
// Class implementing Credential Manager methods Store, PreventSilentAccess
// and Get in a platform independent way. Each method takes a callback as an
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 ded5b222c92..bffeeb22c7c 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
@@ -188,9 +188,9 @@ void RespondCallback(bool* called) {
void GetCredentialCallback(bool* called,
CredentialManagerError* out_error,
- base::Optional<CredentialInfo>* out_info,
+ absl::optional<CredentialInfo>* out_info,
CredentialManagerError error,
- const base::Optional<CredentialInfo>& info) {
+ const absl::optional<CredentialInfo>& info) {
*called = true;
*out_error = error;
*out_info = info;
@@ -304,7 +304,7 @@ class CredentialManagerImplTest : public testing::Test,
const std::vector<GURL>& federations) {
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _))
.Times(testing::Exactly(0));
EXPECT_CALL(*client_, NotifyUserAutoSigninPtr()).Times(testing::Exactly(0));
@@ -325,7 +325,7 @@ class CredentialManagerImplTest : public testing::Test,
CredentialType type) {
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _))
.Times(testing::Exactly(0));
EXPECT_CALL(*client_, NotifyUserAutoSigninPtr()).Times(testing::Exactly(1));
@@ -346,7 +346,7 @@ class CredentialManagerImplTest : public testing::Test,
CredentialType type) {
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
CallGet(
mediation, include_passwords, federations,
base::BindOnce(&GetCredentialCallback, &called, &error, &credential));
@@ -699,7 +699,7 @@ TEST_P(CredentialManagerImplTest, CredentialManagerGetOverwriteZeroClick) {
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
CallGet(CredentialMediationRequirement::kOptional, true, federations,
base::BindOnce(&GetCredentialCallback, &called, &error, &credential));
@@ -802,7 +802,7 @@ TEST_P(CredentialManagerImplTest,
bool called = false;
CredentialManagerError error;
std::vector<GURL> federations;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
CallGet(CredentialMediationRequirement::kOptional, true, federations,
base::BindOnce(&GetCredentialCallback, &called, &error, &credential));
RunAllPendingTasks();
@@ -960,7 +960,7 @@ TEST_P(CredentialManagerImplTest,
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
std::vector<GURL> federations;
federations.emplace_back("https://google.com/");
CallGet(CredentialMediationRequirement::kOptional, true, federations,
@@ -996,7 +996,7 @@ TEST_P(CredentialManagerImplTest,
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
CallGet(CredentialMediationRequirement::kOptional, true, federations,
base::BindOnce(&GetCredentialCallback, &called, &error, &credential));
@@ -1270,14 +1270,14 @@ TEST_P(CredentialManagerImplTest,
// 1st request.
bool called_1 = false;
CredentialManagerError error_1;
- base::Optional<CredentialInfo> credential_1;
+ absl::optional<CredentialInfo> credential_1;
CallGet(CredentialMediationRequirement::kOptional, true, federations,
base::BindOnce(&GetCredentialCallback, &called_1, &error_1,
&credential_1));
// 2nd request.
bool called_2 = false;
CredentialManagerError error_2;
- base::Optional<CredentialInfo> credential_2;
+ absl::optional<CredentialInfo> credential_2;
CallGet(CredentialMediationRequirement::kOptional, true, federations,
base::BindOnce(&GetCredentialCallback, &called_2, &error_2,
&credential_2));
@@ -1335,7 +1335,7 @@ TEST_P(CredentialManagerImplTest, ResetSkipZeroClickInProfileStoreAfterPrompt) {
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
CallGet(CredentialMediationRequirement::kOptional, true, federations,
base::BindOnce(&GetCredentialCallback, &called, &error, &credential));
@@ -1375,7 +1375,7 @@ TEST_P(CredentialManagerImplTest, ResetSkipZeroClickInAccountStoreAfterPrompt) {
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
CallGet(CredentialMediationRequirement::kOptional, true, /*federations=*/{},
base::BindOnce(&GetCredentialCallback, &called, &error, &credential));
@@ -1417,7 +1417,7 @@ TEST_P(CredentialManagerImplTest,
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
CallGet(CredentialMediationRequirement::kOptional, true, /*federations=*/{},
base::BindOnce(&GetCredentialCallback, &called, &error, &credential));
@@ -1609,7 +1609,7 @@ TEST_P(CredentialManagerImplTest, MediationRequiredPreventsAutoSignIn) {
std::vector<GURL> federations;
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
EXPECT_CALL(*client_, PromptUserToChooseCredentialsPtr(_, _, _))
.Times(testing::Exactly(1));
@@ -1764,7 +1764,7 @@ TEST_P(CredentialManagerImplTest,
bool called = false;
CredentialManagerError error;
- base::Optional<CredentialInfo> credential;
+ absl::optional<CredentialInfo> credential;
std::vector<GURL> federations;
federations.emplace_back("https://google.com/");
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 fd8ecd933a3..919986d83d0 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
@@ -327,20 +327,20 @@ void CredentialManagerPendingRequestTask::ProcessForms(
return;
}
- auto repeating_send_callback =
- base::AdaptCallbackForRepeating(std::move(send_callback_));
+ auto split_send_callback = base::SplitOnceCallback(std::move(send_callback_));
if (!delegate_->client()->PromptUserToChooseCredentials(
std::move(local_results), origin_,
base::BindOnce(
&CredentialManagerPendingRequestTaskDelegate::SendPasswordForm,
- base::Unretained(delegate_), repeating_send_callback,
+ base::Unretained(delegate_), std::move(split_send_callback.first),
mediation_))) {
// Since PromptUserToChooseCredentials() does not invoke the callback when
// returning false, `repeating_send_callback` has not been run in this
// branch yet.
LogCredentialManagerGetResult(
metrics_util::CredentialManagerGetResult::kNone, mediation_);
- delegate_->SendCredential(repeating_send_callback, CredentialInfo());
+ delegate_->SendCredential(std::move(split_send_callback.second),
+ CredentialInfo());
}
}
diff --git a/chromium/components/password_manager/core/browser/credential_manager_utils.cc b/chromium/components/password_manager/core/browser/credential_manager_utils.cc
index ff4fa7b4363..6b256f40a38 100644
--- a/chromium/components/password_manager/core/browser/credential_manager_utils.cc
+++ b/chromium/components/password_manager/core/browser/credential_manager_utils.cc
@@ -7,9 +7,9 @@
#include <memory>
#include <string>
-#include "base/optional.h"
#include "components/password_manager/core/browser/password_form.h"
#include "components/password_manager/core/common/credential_manager_types.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
diff --git a/chromium/components/password_manager/core/browser/export/DIR_METADATA b/chromium/components/password_manager/core/browser/export/DIR_METADATA
deleted file mode 100644
index 14f1f467986..00000000000
--- a/chromium/components/password_manager/core/browser/export/DIR_METADATA
+++ /dev/null
@@ -1,4 +0,0 @@
-monorail {
- component: "UI>Browser>Passwords"
-}
-team_email: "chromium-dev@chromium.org"
diff --git a/chromium/components/password_manager/core/browser/export/password_manager_exporter.h b/chromium/components/password_manager/core/browser/export/password_manager_exporter.h
index 81087849afe..6aca84094aa 100644
--- a/chromium/components/password_manager/core/browser/export/password_manager_exporter.h
+++ b/chromium/components/password_manager/core/browser/export/password_manager_exporter.h
@@ -14,7 +14,6 @@
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_piece.h"
-#include "base/time/time.h"
#include "components/password_manager/core/browser/ui/export_progress_status.h"
namespace password_manager {
diff --git a/chromium/components/password_manager/core/browser/field_info_manager.cc b/chromium/components/password_manager/core/browser/field_info_manager.cc
index 5fd38520206..48df3dec54d 100644
--- a/chromium/components/password_manager/core/browser/field_info_manager.cc
+++ b/chromium/components/password_manager/core/browser/field_info_manager.cc
@@ -47,8 +47,6 @@ void FieldInfoManagerImpl::OnGetPasswordStoreResults(
void FieldInfoManagerImpl::OnGetAllFieldInfo(
std::vector<FieldInfo> field_infos) {
- base::UmaHistogramCounts100("PasswordManager.FieldInfoTableRows",
- field_infos.size());
for (const auto& field : field_infos) {
field_types_[std::make_pair(field.form_signature, field.field_signature)] =
field.field_type;
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 f6f9f2f5b5b..d2bb6268caa 100644
--- a/chromium/components/password_manager/core/browser/form_fetcher_impl.cc
+++ b/chromium/components/password_manager/core/browser/form_fetcher_impl.cc
@@ -126,6 +126,12 @@ void FormFetcherImpl::Fetch() {
// The desktop bubble needs this information.
password_store->GetMatchingInsecureCredentials(form_digest_.signon_realm,
this);
+#else
+ if (base::FeatureList::IsEnabled(features::kMutingCompromisedCredentials)) {
+ // We need this information to mute leak detection warming.
+ password_store->GetMatchingInsecureCredentials(form_digest_.signon_realm,
+ this);
+ }
#endif
}
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 2dcf7d8a67d..7afd3412c0d 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
@@ -536,10 +536,30 @@ TEST_P(FormFetcherImplTest, DontFetchStatistics) {
}
TEST_P(FormFetcherImplTest, DontFetchInsecure) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(features::kMutingCompromisedCredentials,
+ false);
EXPECT_CALL(*mock_store_, GetMatchingInsecureCredentialsImpl).Times(0);
form_fetcher_->Fetch();
task_environment_.RunUntilIdle();
}
+
+TEST_P(FormFetcherImplTest, FetchInsecure) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(features::kMutingCompromisedCredentials,
+ true);
+ std::vector<InsecureCredential> list = {InsecureCredential(
+ form_digest_.signon_realm, u"username_value", base::Time::FromTimeT(1),
+ InsecureType::kLeaked, IsMuted(false))};
+ EXPECT_CALL(*mock_store_,
+ GetMatchingInsecureCredentialsImpl(form_digest_.signon_realm))
+ .WillOnce(Return(list));
+ form_fetcher_->Fetch();
+ task_environment_.RunUntilIdle();
+
+ EXPECT_THAT(form_fetcher_->GetInsecureCredentials(),
+ UnorderedElementsAreArray(list));
+}
#endif
// Test that ensures HTTP passwords are not migrated on HTTP sites.
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 eb8a7349931..57c80cc0a2a 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
@@ -427,8 +427,11 @@ void ParseUsingPredictions(std::vector<ProcessedField>* processed_fields,
// fields have the "username" attribute.
// If any assumption is violated, the autocomplete attribute is ignored.
void ParseUsingAutocomplete(const std::vector<ProcessedField>& processed_fields,
+ FormDataParser::Mode mode,
SignificantFields* result) {
bool new_password_found_by_server = result->new_password;
+ bool new_password_found_by_autocomplete = false;
+ bool should_ignore_new_password_autocomplete = false;
const FormFieldData* field_marked_as_username = nullptr;
int username_fields_found = 0;
for (const ProcessedField& processed_field : processed_fields) {
@@ -452,14 +455,27 @@ void ParseUsingAutocomplete(const std::vector<ProcessedField>& processed_fields,
break;
case AutocompleteFlag::kNewPassword:
if (!processed_field.is_password || new_password_found_by_server ||
- processed_field.server_hints_not_password)
+ processed_field.server_hints_not_password ||
+ should_ignore_new_password_autocomplete)
continue;
// The first field with autocomplete=new-password is considered to be
// new_password and the second is confirmation_password.
- if (!result->new_password)
+ if (!result->new_password) {
result->new_password = processed_field.field;
- else if (!result->confirmation_password)
+ new_password_found_by_autocomplete = true;
+ } else if (!result->confirmation_password) {
+ // Ignore kNewPassword autocomplete feature if fields that have it
+ // have different values in saving mode.
+ if (mode == FormDataParser::Mode::kSaving &&
+ new_password_found_by_autocomplete &&
+ GetFieldValue(*result->new_password) !=
+ GetFieldValue(*processed_field.field)) {
+ should_ignore_new_password_autocomplete = true;
+ result->new_password = nullptr;
+ continue;
+ }
result->confirmation_password = processed_field.field;
+ }
break;
case AutocompleteFlag::kNonPassword:
case AutocompleteFlag::kNone:
@@ -665,7 +681,7 @@ const FormFieldData* FindUsernameFieldBaseHeuristics(
continue;
if (!MatchesInteractability(*it, best_interactability))
continue;
- if (is_saving && IsProbablyNotUsername(it->field->value))
+ if (is_saving && IsProbablyNotUsername(GetFieldValue(*it->field)))
continue;
if (!is_fallback && IsNotPasswordField(*it))
continue;
@@ -895,7 +911,7 @@ std::vector<ProcessedField> ProcessFields(
// |form_predictions| has |may_use_prefilled_placeholder| == true for the
// username field.
bool GetMayUsePrefilledPlaceholder(
- const base::Optional<FormPredictions>& form_predictions,
+ const absl::optional<FormPredictions>& form_predictions,
const SignificantFields& significant_fields) {
if (!form_predictions || !significant_fields.username)
return false;
@@ -922,7 +938,7 @@ std::unique_ptr<PasswordForm> AssemblePasswordForm(
const SignificantFields& significant_fields,
ValueElementVector all_possible_passwords,
ValueElementVector all_possible_usernames,
- const base::Optional<FormPredictions>& form_predictions) {
+ const absl::optional<FormPredictions>& form_predictions) {
if (!significant_fields.HasPasswords() &&
!significant_fields.is_single_username) {
return nullptr;
@@ -995,7 +1011,7 @@ std::unique_ptr<PasswordForm> FormDataParser::Parse(const FormData& form_data,
// (2) If that failed, try to parse with autocomplete attributes.
if (!significant_fields.is_single_username) {
- ParseUsingAutocomplete(processed_fields, &significant_fields);
+ ParseUsingAutocomplete(processed_fields, mode, &significant_fields);
if (method == UsernameDetectionMethod::kNoUsernameDetected &&
significant_fields.username) {
method = UsernameDetectionMethod::kAutocompleteAttribute;
diff --git a/chromium/components/password_manager/core/browser/form_parsing/form_parser.h b/chromium/components/password_manager/core/browser/form_parsing/form_parser.h
index 40f900d0870..e14d8c2f046 100644
--- a/chromium/components/password_manager/core/browser/form_parsing/form_parser.h
+++ b/chromium/components/password_manager/core/browser/form_parsing/form_parser.h
@@ -10,8 +10,8 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace autofill {
@@ -126,7 +126,7 @@ class FormDataParser {
void reset_predictions() { predictions_.reset(); }
- const base::Optional<FormPredictions>& predictions() { return predictions_; }
+ const absl::optional<FormPredictions>& predictions() { return predictions_; }
ReadonlyPasswordFields readonly_status() { return readonly_status_; }
@@ -138,7 +138,7 @@ class FormDataParser {
private:
// Predictions are an optional source of server-side information about field
// types.
- base::Optional<FormPredictions> predictions_;
+ absl::optional<FormPredictions> predictions_;
// Records whether readonly password fields were seen during the last call to
// Parse().
@@ -162,4 +162,4 @@ const autofill::FormFieldData* FindUsernameInPredictions(
} // namespace password_manager
-#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_IOS_FORM_PARSER_H_
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_FORM_PARSING_FORM_PARSER_H_
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 a1f23576655..3a1ffad1215 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
@@ -12,7 +12,6 @@
#include <utility>
#include "base/feature_list.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
@@ -26,13 +25,13 @@
#include "components/password_manager/core/common/password_manager_features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
using autofill::FieldPropertiesFlags;
using autofill::FormData;
using autofill::FormFieldData;
using autofill::mojom::SubmissionIndicatorEvent;
-using base::ASCIIToUTF16;
namespace password_manager {
@@ -42,7 +41,7 @@ using UsernameDetectionMethod = FormDataParser::UsernameDetectionMethod;
// Use this value in FieldDataDescription.value to get an arbitrary unique value
// generated in GetFormDataAndExpectation().
-constexpr char kNonimportantValue[] = "non-important unique";
+constexpr char16_t kNonimportantValue[] = u"non-important unique";
// Use this in FieldDataDescription below to mark the expected username and
// password fields.
@@ -70,9 +69,9 @@ struct FieldDataDescription {
autofill::FieldPropertiesMask properties_mask =
FieldPropertiesFlags::kNoFlags;
const char* autocomplete_attribute = nullptr;
- const std::u16string value = ASCIIToUTF16(kNonimportantValue);
+ const std::u16string value = kNonimportantValue;
const std::u16string user_input = u"";
- const char* name = kNonimportantValue;
+ const base::StringPiece16 name = kNonimportantValue;
const char* form_control_type = "text";
PasswordFieldPrediction prediction = {.type = autofill::MAX_VALID_FIELD_TYPE};
// If not -1, indicates on which rank among predicted usernames this should
@@ -92,15 +91,15 @@ struct FormParsingTestCase {
const ValueElementVector* all_possible_usernames = nullptr;
bool server_side_classification_successful = true;
bool username_may_use_prefilled_placeholder = false;
- base::Optional<FormDataParser::ReadonlyPasswordFields> readonly_status;
- base::Optional<FormDataParser::ReadonlyPasswordFields>
+ absl::optional<FormDataParser::ReadonlyPasswordFields> readonly_status;
+ absl::optional<FormDataParser::ReadonlyPasswordFields>
readonly_status_for_saving;
- base::Optional<FormDataParser::ReadonlyPasswordFields>
+ absl::optional<FormDataParser::ReadonlyPasswordFields>
readonly_status_for_filling;
// If the result should be marked as only useful for fallbacks.
bool fallback_only = false;
SubmissionIndicatorEvent submission_event = SubmissionIndicatorEvent::NONE;
- base::Optional<bool> is_new_password_reliable;
+ absl::optional<bool> is_new_password_reliable;
bool form_has_autofilled_value = false;
};
@@ -112,8 +111,8 @@ autofill::FieldRendererId GetUniqueId() {
}
// Use to add a number suffix which is unique in the scope of the test.
-std::u16string StampUniqueSuffix(const char* base_str) {
- return ASCIIToUTF16(base_str) + u"_" +
+std::u16string StampUniqueSuffix(const char16_t* base_str) {
+ return base_str + std::u16string(u"_") +
base::NumberToString16(GetUniqueId().value());
}
@@ -175,23 +174,23 @@ FormData GetFormDataAndExpectation(const FormParsingTestCase& test_case,
FormFieldData field;
const autofill::FieldRendererId renderer_id = GetUniqueId();
field.unique_renderer_id = renderer_id;
- field.id_attribute = StampUniqueSuffix("html_id");
+ field.id_attribute = StampUniqueSuffix(u"html_id");
if (field_description.name == kNonimportantValue) {
- field.name = StampUniqueSuffix("html_name");
+ field.name = StampUniqueSuffix(u"html_name");
} else {
- field.name = ASCIIToUTF16(field_description.name);
+ field.name = std::u16string(field_description.name);
}
field.name_attribute = field.name;
#if defined(OS_IOS)
- field.unique_id = StampUniqueSuffix("unique_id");
+ field.unique_id = StampUniqueSuffix(u"unique_id");
#endif
field.form_control_type = field_description.form_control_type;
field.is_focusable = field_description.is_focusable;
field.is_enabled = field_description.is_enabled;
field.is_readonly = field_description.is_readonly;
field.properties_mask = field_description.properties_mask;
- if (field_description.value == ASCIIToUTF16(kNonimportantValue)) {
- field.value = StampUniqueSuffix("value");
+ if (field_description.value == kNonimportantValue) {
+ field.value = StampUniqueSuffix(u"value");
} else {
field.value = field_description.value;
}
@@ -400,7 +399,7 @@ void CheckTestData(const std::vector<FormParsingTestCase>& test_cases) {
if (test_case.readonly_status) {
EXPECT_EQ(*test_case.readonly_status, parser.readonly_status());
} else {
- const base::Optional<FormDataParser::ReadonlyPasswordFields>*
+ const absl::optional<FormDataParser::ReadonlyPasswordFields>*
expected_readonly_status =
mode == FormDataParser::Mode::kSaving
? &test_case.readonly_status_for_saving
@@ -1088,14 +1087,17 @@ TEST(FormParserTest, ReadonlyFields) {
{.role = ElementRole::NEW_PASSWORD,
.is_readonly = true,
.autocomplete_attribute = "new-password",
+ .value = u"newpass",
.form_control_type = "password"},
{.role = ElementRole::CONFIRMATION_PASSWORD,
.is_readonly = true,
.autocomplete_attribute = "new-password",
+ .value = u"newpass",
.form_control_type = "password"},
{.role = ElementRole::CURRENT_PASSWORD,
.is_readonly = true,
.autocomplete_attribute = "current-password",
+ .value = u"oldpass",
.form_control_type = "password"},
},
.is_new_password_reliable = true,
@@ -1531,21 +1533,23 @@ TEST(FormParserTest, AllPossiblePasswords) {
.fields =
{
{.value = u"a",
- .name = "p1",
+ .name = u"p1",
.form_control_type = "password"},
{.role = ElementRole::USERNAME,
.autocomplete_attribute = "username",
.value = u"b",
- .name = "chosen",
+ .name = u"chosen",
.form_control_type = "text"},
{.role = ElementRole::CURRENT_PASSWORD,
.autocomplete_attribute = "current-password",
.value = u"a",
.form_control_type = "password"},
- {.value = u"a", .name = "first", .form_control_type = "text"},
+ {.value = u"a",
+ .name = u"first",
+ .form_control_type = "text"},
{.value = u"a", .form_control_type = "text"},
{.value = u"b",
- .name = "p3",
+ .name = u"p3",
.form_control_type = "password"},
{.value = u"b", .form_control_type = "password"},
},
@@ -1799,7 +1803,7 @@ TEST(FormParserTest, CVC) {
.fields =
{
{.role = ElementRole::USERNAME, .form_control_type = "text"},
- {.name = "verification_type",
+ {.name = u"verification_type",
.form_control_type = "password"},
{.role = ElementRole::CURRENT_PASSWORD,
.form_control_type = "password"},
@@ -1815,7 +1819,7 @@ TEST(FormParserTest, CVC) {
{
{.role = ElementRole::USERNAME, .form_control_type = "text"},
{.role = ElementRole::CURRENT_PASSWORD,
- .name = "verification_type",
+ .name = u"verification_type",
.form_control_type = "password"},
},
.fallback_only = true,
@@ -1826,8 +1830,8 @@ TEST(FormParserTest, CVC) {
// The parser should avoid identifying Social Security number and
// one time password fields as passwords.
TEST(FormParserTest, SSN_and_OTP) {
- for (const char* field_name :
- {"SocialSecurityNumber", "OneTimePassword", "SMS-token"}) {
+ for (const char16_t* field_name :
+ {u"SocialSecurityNumber", u"OneTimePassword", u"SMS-token"}) {
CheckTestData({
{
.description_for_logging = "Field name matches the SSN/OTP pattern,"
@@ -2540,6 +2544,28 @@ TEST(FormParserTest, TypedValues) {
.form_control_type = "password"},
},
},
+ {
+ .description_for_logging = "Form autocomplete with cleared by JavaScript values",
+ // Username autocomplete tests that typed values are taken as username, password and
+ // new password instead of values that are cleared by JavaScript.
+ .fields =
+ {
+ {.role = ElementRole::USERNAME,
+ .value = u"",
+ .user_input = u"typed_username",
+ .form_control_type = "text"},
+ {.role = ElementRole::CURRENT_PASSWORD,
+ .autocomplete_attribute = "current-password",
+ .value = u"",
+ .user_input = u"typed_password",
+ .form_control_type = "password"},
+ {.role = ElementRole::NEW_PASSWORD,
+ .autocomplete_attribute = "new-password",
+ .value = u"",
+ .user_input = u"typed_new_password",
+ .form_control_type = "password"},
+ },
+ },
});
}
@@ -2617,11 +2643,11 @@ TEST(FormParserTest, FindUsernameInPredictions_SkipPrediction) {
// Create a form containing username, email, id, password, submit.
const FormParsingTestCase form_desc = {
.fields = {
- {.name = "username", .form_control_type = "text"},
- {.name = "email", .form_control_type = "text"},
- {.name = "id", .form_control_type = "text"},
- {.name = "password", .form_control_type = "password"},
- {.name = "submit", .form_control_type = "submit"},
+ {.name = u"username", .form_control_type = "text"},
+ {.name = u"email", .form_control_type = "text"},
+ {.name = u"id", .form_control_type = "text"},
+ {.name = u"password", .form_control_type = "password"},
+ {.name = u"submit", .form_control_type = "submit"},
}};
FormPredictions no_predictions;
@@ -2663,10 +2689,10 @@ TEST(FormParserTest, SkipHiddenValueField) {
.fields =
{
{.value = u"foo",
- .name = "username",
+ .name = u"username",
.form_control_type = "text"},
{.value = u"***********",
- .name = "password",
+ .name = u"password",
.form_control_type = "password"},
},
},
@@ -2674,10 +2700,10 @@ TEST(FormParserTest, SkipHiddenValueField) {
.fields =
{
{.value = u"foo",
- .name = "username",
+ .name = u"username",
.form_control_type = "text"},
{.value = u"**",
- .name = "password",
+ .name = u"password",
.form_control_type = "password"},
},
},
@@ -2685,10 +2711,10 @@ TEST(FormParserTest, SkipHiddenValueField) {
.fields =
{
{.value = u"foo",
- .name = "username",
+ .name = u"username",
.form_control_type = "text"},
{.value = u"••••••••",
- .name = "password",
+ .name = u"password",
.form_control_type = "password"},
},
}};
@@ -2711,10 +2737,10 @@ TEST(FormParserTest, DontSkipNotHiddenValues) {
.fields =
{
{.value = u"foo",
- .name = "username",
+ .name = u"username",
.form_control_type = "text"},
{.value = u"a*******a",
- .name = "password",
+ .name = u"password",
.form_control_type = "password"},
},
},
@@ -2722,10 +2748,10 @@ TEST(FormParserTest, DontSkipNotHiddenValues) {
.fields =
{
{.value = u"foo",
- .name = "username",
+ .name = u"username",
.form_control_type = "text"},
{.value = u".....*****",
- .name = "password",
+ .name = u"password",
.form_control_type = "password"},
},
},
@@ -2733,10 +2759,10 @@ TEST(FormParserTest, DontSkipNotHiddenValues) {
.fields =
{
{.value = u"foo",
- .name = "username",
+ .name = u"username",
.form_control_type = "text"},
{.value = u"0 0 0 0 0",
- .name = "password",
+ .name = u"password",
.form_control_type = "password"},
},
}};
@@ -2752,6 +2778,55 @@ TEST(FormParserTest, DontSkipNotHiddenValues) {
}
}
+// Tests that 'new-password' autocomplete attribute is ignored when two
+// or more fields that have it have different values.
+TEST(FormParserTest, AutocompleteAttributesError) {
+ CheckTestData(
+ {{
+ .description_for_logging =
+ "Wrong autocomplete attributes, 2 fields.",
+ .fields =
+ {
+ {.role_filling = ElementRole::NEW_PASSWORD,
+ .role_saving = ElementRole::CURRENT_PASSWORD,
+ .autocomplete_attribute = "new-password",
+ .value = u"oldpass",
+ .name = u"password1",
+ .form_control_type = "password"},
+ {.role_filling = ElementRole::CONFIRMATION_PASSWORD,
+ .role_saving = ElementRole::NEW_PASSWORD,
+ .autocomplete_attribute = "new-password",
+ .value = u"newpass",
+ .name = u"password2",
+ .form_control_type = "password"},
+ },
+ },
+ {
+ .description_for_logging =
+ "Wrong autocomplete attributes, 3 fields.",
+ .fields =
+ {
+ {.role_filling = ElementRole::NEW_PASSWORD,
+ .role_saving = ElementRole::CURRENT_PASSWORD,
+ .autocomplete_attribute = "new-password",
+ .value = u"oldpass",
+ .name = u"password1",
+ .form_control_type = "password"},
+ {.role_filling = ElementRole::CONFIRMATION_PASSWORD,
+ .role_saving = ElementRole::NEW_PASSWORD,
+ .autocomplete_attribute = "new-password",
+ .value = u"newpass",
+ .name = u"password2",
+ .form_control_type = "password"},
+ {.role_saving = ElementRole::CONFIRMATION_PASSWORD,
+ .autocomplete_attribute = "new-password",
+ .value = u"newpass",
+ .name = u"password3",
+ .form_control_type = "password"},
+ },
+ }});
+}
+
} // namespace
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/form_saver.h b/chromium/components/password_manager/core/browser/form_saver.h
index 0d91baa77e5..5154ee03100 100644
--- a/chromium/components/password_manager/core/browser/form_saver.h
+++ b/chromium/components/password_manager/core/browser/form_saver.h
@@ -11,8 +11,8 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/password_manager/core/browser/password_store.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
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 94907144677..124a9e70f1b 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
@@ -22,8 +22,6 @@
#include "url/gurl.h"
using autofill::FormFieldData;
-using base::ASCIIToUTF16;
-using base::StringPiece;
using testing::_;
using testing::DoAll;
using testing::SaveArg;
@@ -44,10 +42,11 @@ PasswordForm CreateObserved() {
// Creates a dummy pending (for saving) form with some basic arbitrary values
// and |username| and |password| values as specified.
-PasswordForm CreatePending(StringPiece username, StringPiece password) {
+PasswordForm CreatePending(base::StringPiece16 username,
+ base::StringPiece16 password) {
PasswordForm form = CreateObserved();
- form.username_value = ASCIIToUTF16(username);
- form.password_value = ASCIIToUTF16(password);
+ form.username_value = std::u16string(username);
+ form.password_value = std::u16string(password);
return form;
}
@@ -105,7 +104,7 @@ void FormSaverImplSaveTest::SaveCredential(
EXPECT_CALL(*mock_store_, UpdateLogin(pending));
return form_saver_.Update(std::move(pending), matches, old_password);
case SaveOperation::kReplaceUpdate: {
- PasswordForm old_key = CreatePending("some_other_username", "1234");
+ PasswordForm old_key = CreatePending(u"some_other_username", u"1234");
EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(pending, old_key));
return form_saver_.UpdateReplace(std::move(pending), matches,
old_password, old_key);
@@ -115,7 +114,7 @@ void FormSaverImplSaveTest::SaveCredential(
// Pushes the credential to the store without any matches.
TEST_P(FormSaverImplSaveTest, Write_EmptyStore) {
- PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm pending = CreatePending(u"nameofuser", u"wordToP4a55");
SaveCredential(pending, {} /* matches */,
std::u16string() /* old_password */);
@@ -124,7 +123,7 @@ TEST_P(FormSaverImplSaveTest, Write_EmptyStore) {
// Pushes the credential to the store with |matches| containing the pending
// credential.
TEST_P(FormSaverImplSaveTest, Write_EmptyStoreWithPending) {
- PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm pending = CreatePending(u"nameofuser", u"wordToP4a55");
SaveCredential(pending, {&pending} /* matches */, pending.password_value);
}
@@ -132,16 +131,16 @@ TEST_P(FormSaverImplSaveTest, Write_EmptyStoreWithPending) {
// Pushes the credential to the store with |matches| containing the pending
// credential with an old password.
TEST_P(FormSaverImplSaveTest, Write_EmptyStoreWithPendingOldPassword) {
- PasswordForm pending = CreatePending("nameofuser", "old_password");
+ PasswordForm pending = CreatePending(u"nameofuser", u"old_password");
- SaveCredential(CreatePending("nameofuser", "new_password"),
+ SaveCredential(CreatePending(u"nameofuser", u"new_password"),
{&pending} /* matches */, pending.password_value);
}
// Check that storing credentials with a non-empty username results in deleting
// credentials with the same password but empty username, if present in matches.
TEST_P(FormSaverImplSaveTest, Write_AndDeleteEmptyUsernameCredentials) {
- PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm pending = CreatePending(u"nameofuser", u"wordToP4a55");
PasswordForm non_empty_username = pending;
non_empty_username.username_value = u"othername";
@@ -160,7 +159,7 @@ TEST_P(FormSaverImplSaveTest, Write_AndDeleteEmptyUsernameCredentials) {
// username.
TEST_P(FormSaverImplSaveTest,
Write_AndDoNotDeleteEmptyUsernameCredentialsWithDifferentPassword) {
- PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm pending = CreatePending(u"nameofuser", u"wordToP4a55");
PasswordForm no_username = pending;
no_username.username_value.clear();
@@ -174,7 +173,7 @@ TEST_P(FormSaverImplSaveTest,
// with the same password (and a non-empty username) is present in best matches,
// nothing is deleted.
TEST_P(FormSaverImplSaveTest, Write_EmptyUsernameWillNotCauseDeletion) {
- PasswordForm pending = CreatePending("", "wordToP4a55");
+ PasswordForm pending = CreatePending(u"", u"wordToP4a55");
PasswordForm with_username = pending;
with_username.username_value = u"nameofuser";
@@ -187,7 +186,7 @@ TEST_P(FormSaverImplSaveTest, Write_EmptyUsernameWillNotCauseDeletion) {
// even if they have an empty username and the same password as the pending
// credential.
TEST_P(FormSaverImplSaveTest, Write_AndDoNotDeleteEmptyUsernamePSLCredentials) {
- PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm pending = CreatePending(u"nameofuser", u"wordToP4a55");
PasswordForm stored = pending;
PasswordForm no_username_psl = pending;
@@ -202,7 +201,7 @@ TEST_P(FormSaverImplSaveTest, Write_AndDoNotDeleteEmptyUsernamePSLCredentials) {
// Check that on storing a credential, other credentials with the same password
// are not removed, as long as they have a non-empty username.
TEST_P(FormSaverImplSaveTest, Write_AndDoNotDeleteNonEmptyUsernameCredentials) {
- PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm pending = CreatePending(u"nameofuser", u"wordToP4a55");
PasswordForm other_username = pending;
other_username.username_value = u"other username";
@@ -213,42 +212,42 @@ TEST_P(FormSaverImplSaveTest, Write_AndDoNotDeleteNonEmptyUsernameCredentials) {
// Stores a credential and makes sure that its duplicate is updated.
TEST_P(FormSaverImplSaveTest, Write_AndUpdatePasswordValuesOnExactMatch) {
- constexpr char kOldPassword[] = "old_password";
- constexpr char kNewPassword[] = "new_password";
+ constexpr char16_t kOldPassword[] = u"old_password";
+ constexpr char16_t kNewPassword[] = u"new_password";
- PasswordForm duplicate = CreatePending("nameofuser", kOldPassword);
+ PasswordForm duplicate = CreatePending(u"nameofuser", kOldPassword);
duplicate.url = GURL("https://example.in/somePath");
PasswordForm expected_update = duplicate;
- expected_update.password_value = ASCIIToUTF16(kNewPassword);
+ expected_update.password_value = kNewPassword;
EXPECT_CALL(*mock_store_, UpdateLogin(expected_update));
- SaveCredential(CreatePending("nameofuser", kNewPassword), {&duplicate},
- ASCIIToUTF16(kOldPassword));
+ SaveCredential(CreatePending(u"nameofuser", kNewPassword), {&duplicate},
+ kOldPassword);
}
// Stores a credential and makes sure that its PSL duplicate is updated.
TEST_P(FormSaverImplSaveTest, Write_AndUpdatePasswordValuesOnPSLMatch) {
- constexpr char kOldPassword[] = "old_password";
- constexpr char kNewPassword[] = "new_password";
+ constexpr char16_t kOldPassword[] = u"old_password";
+ constexpr char16_t kNewPassword[] = u"new_password";
- PasswordForm duplicate = CreatePending("nameofuser", kOldPassword);
+ PasswordForm duplicate = CreatePending(u"nameofuser", kOldPassword);
duplicate.url = GURL("https://www.example.in");
duplicate.signon_realm = duplicate.url.spec();
duplicate.is_public_suffix_match = true;
PasswordForm expected_update = duplicate;
- expected_update.password_value = ASCIIToUTF16(kNewPassword);
+ expected_update.password_value = kNewPassword;
EXPECT_CALL(*mock_store_, UpdateLogin(expected_update));
- SaveCredential(CreatePending("nameofuser", kNewPassword), {&duplicate},
- ASCIIToUTF16(kOldPassword));
+ SaveCredential(CreatePending(u"nameofuser", kNewPassword), {&duplicate},
+ kOldPassword);
}
// Stores a credential and makes sure that not exact matches are not updated.
TEST_P(FormSaverImplSaveTest, Write_AndUpdatePasswordValues_IgnoreNonMatches) {
- constexpr char kOldPassword[] = "old_password";
- constexpr char kNewPassword[] = "new_password";
- PasswordForm pending = CreatePending("nameofuser", kOldPassword);
+ constexpr char16_t kOldPassword[] = u"old_password";
+ constexpr char16_t kNewPassword[] = u"new_password";
+ PasswordForm pending = CreatePending(u"nameofuser", kOldPassword);
PasswordForm different_username = pending;
different_username.username_value = u"someuser";
@@ -261,15 +260,15 @@ TEST_P(FormSaverImplSaveTest, Write_AndUpdatePasswordValues_IgnoreNonMatches) {
const std::vector<const PasswordForm*> matches = {
&different_username, &different_password, &empty_username};
- pending.password_value = ASCIIToUTF16(kNewPassword);
+ pending.password_value = kNewPassword;
EXPECT_CALL(*mock_store_, UpdateLogin(_)).Times(0);
EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, _)).Times(0);
- SaveCredential(pending, matches, ASCIIToUTF16(kOldPassword));
+ SaveCredential(pending, matches, kOldPassword);
}
// Check that on saving the pending form |form_data| is sanitized.
TEST_P(FormSaverImplSaveTest, FormDataSanitized) {
- PasswordForm pending = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm pending = CreatePending(u"nameofuser", u"wordToP4a55");
FormFieldData field;
field.name = u"name";
field.form_control_type = "password";
@@ -290,7 +289,7 @@ TEST_P(FormSaverImplSaveTest, FormDataSanitized) {
EXPECT_CALL(*mock_store_, UpdateLogin(_)).WillOnce(SaveArg<0>(&saved));
return form_saver_.Update(std::move(pending), {}, u"");
case SaveOperation::kReplaceUpdate: {
- PasswordForm old_key = CreatePending("some_other_username", "1234");
+ PasswordForm old_key = CreatePending(u"some_other_username", u"1234");
EXPECT_CALL(*mock_store_, UpdateLoginWithPrimaryKey(_, old_key))
.WillOnce(SaveArg<0>(&saved));
return form_saver_.UpdateReplace(std::move(pending), {}, u"", old_key);
@@ -339,7 +338,7 @@ TEST_F(FormSaverImplTest, Blocklist) {
// Check that Remove() method is relayed properly.
TEST_F(FormSaverImplTest, Remove) {
- PasswordForm form = CreatePending("nameofuser", "wordToP4a55");
+ PasswordForm form = CreatePending(u"nameofuser", u"wordToP4a55");
EXPECT_CALL(*mock_store_, RemoveLogin(form));
form_saver_.Remove(form);
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 34c3122b9b8..4f197f274e6 100644
--- a/chromium/components/password_manager/core/browser/hash_password_manager.cc
+++ b/chromium/components/password_manager/core/browser/hash_password_manager.cc
@@ -99,21 +99,21 @@ std::string BooleanToString(bool bool_value) {
}
// Helper function to convert a dictionary value to PasswordWordHashData.
-base::Optional<PasswordHashData> ConvertToPasswordHashData(
+absl::optional<PasswordHashData> ConvertToPasswordHashData(
const base::Value& dict) {
PasswordHashData result;
result.username = GetAndDecryptField(dict, kUsernameFieldKey);
if (result.username.empty())
- return base::nullopt;
+ return absl::nullopt;
if (!base::StringToUint64(GetAndDecryptField(dict, kHashFieldKey),
&result.hash)) {
- return base::nullopt;
+ return absl::nullopt;
}
if (!StringToLengthAndSalt(GetAndDecryptField(dict, kLengthAndSaltFieldKey),
&result.length, &result.salt)) {
- return base::nullopt;
+ return absl::nullopt;
}
result.is_gaia_password = GetAndDecryptField(dict, kIsGaiaFieldKey) == "true";
@@ -141,7 +141,7 @@ bool HashPasswordManager::SavePasswordHash(const std::string username,
if (AreUsernamesSame(
GetAndDecryptField(password_hash_data, kUsernameFieldKey),
IsGaiaPassword(password_hash_data), username, is_gaia_password)) {
- base::Optional<PasswordHashData> existing_password_hash =
+ absl::optional<PasswordHashData> existing_password_hash =
ConvertToPasswordHashData(password_hash_data);
if (existing_password_hash && existing_password_hash->MatchesPassword(
username, password, is_gaia_password)) {
@@ -227,7 +227,7 @@ std::vector<PasswordHashData> HashPasswordManager::RetrieveAllPasswordHashes() {
prefs_->GetList(prefs::kPasswordHashDataList);
for (const base::Value& entry : hash_list->GetList()) {
- base::Optional<PasswordHashData> password_hash_data =
+ absl::optional<PasswordHashData> password_hash_data =
ConvertToPasswordHashData(entry);
if (password_hash_data)
result.push_back(std::move(*password_hash_data));
@@ -235,12 +235,12 @@ std::vector<PasswordHashData> HashPasswordManager::RetrieveAllPasswordHashes() {
return result;
}
-base::Optional<PasswordHashData> HashPasswordManager::RetrievePasswordHash(
+absl::optional<PasswordHashData> HashPasswordManager::RetrievePasswordHash(
const std::string& username,
bool is_gaia_password) {
if (!prefs_ || username.empty() ||
!prefs_->HasPrefPath(prefs::kPasswordHashDataList)) {
- return base::nullopt;
+ return absl::nullopt;
}
for (const base::Value& entry :
@@ -251,7 +251,7 @@ base::Optional<PasswordHashData> HashPasswordManager::RetrievePasswordHash(
}
}
- return base::nullopt;
+ return absl::nullopt;
}
bool HashPasswordManager::HasPasswordHash(const std::string& username,
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 ac5411d1c8f..c762c5a8c77 100644
--- a/chromium/components/password_manager/core/browser/hash_password_manager.h
+++ b/chromium/components/password_manager/core/browser/hash_password_manager.h
@@ -10,8 +10,8 @@
#include "base/callback.h"
#include "base/callback_list.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/password_manager/core/browser/password_hash_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
@@ -45,7 +45,7 @@ class HashPasswordManager {
// Returns empty if no hash matching |username| and |is_gaia_password| is
// available.
- base::Optional<PasswordHashData> RetrievePasswordHash(
+ absl::optional<PasswordHashData> RetrievePasswordHash(
const std::string& username,
bool is_gaia_password);
diff --git a/chromium/components/password_manager/core/browser/hash_password_manager_unittest.cc b/chromium/components/password_manager/core/browser/hash_password_manager_unittest.cc
index 8c22ef7f893..8c351e44f32 100644
--- a/chromium/components/password_manager/core/browser/hash_password_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/hash_password_manager_unittest.cc
@@ -52,12 +52,12 @@ TEST_F(HashPasswordManagerTest, SavingPasswordHashData) {
EXPECT_TRUE(prefs_.HasPrefPath(prefs::kPasswordHashDataList));
// Saves the same password again won't change password hash, length or salt.
- base::Optional<PasswordHashData> current_password_hash_data =
+ absl::optional<PasswordHashData> current_password_hash_data =
hash_password_manager.RetrievePasswordHash(username,
/*is_gaia_password=*/true);
hash_password_manager.SavePasswordHash(username, password,
/*is_gaia_password=*/true);
- base::Optional<PasswordHashData> existing_password_data =
+ absl::optional<PasswordHashData> existing_password_data =
hash_password_manager.RetrievePasswordHash(username,
/*is_gaia_password=*/true);
EXPECT_EQ(current_password_hash_data->hash, existing_password_data->hash);
@@ -99,12 +99,12 @@ TEST_F(HashPasswordManagerTest, SavingPasswordHashDataNotCanonicalized) {
// Saves the same password with not canonicalized username should not change
// password hash.
- base::Optional<PasswordHashData> current_password_hash_data =
+ absl::optional<PasswordHashData> current_password_hash_data =
hash_password_manager.RetrievePasswordHash(username,
/*is_gaia_password=*/true);
hash_password_manager.SavePasswordHash(username, password,
/*is_gaia_password=*/true);
- base::Optional<PasswordHashData> existing_password_data =
+ absl::optional<PasswordHashData> existing_password_data =
hash_password_manager.RetrievePasswordHash(username,
/*is_gaia_password=*/true);
EXPECT_EQ(current_password_hash_data->hash, existing_password_data->hash);
@@ -247,7 +247,7 @@ TEST_F(HashPasswordManagerTest, RetrievingPasswordHashData) {
/*is_gaia_password=*/true);
EXPECT_EQ(1u, hash_password_manager.RetrieveAllPasswordHashes().size());
- base::Optional<PasswordHashData> password_hash_data =
+ absl::optional<PasswordHashData> password_hash_data =
hash_password_manager.RetrievePasswordHash("username@gmail.com",
/*is_gaia_password=*/false);
ASSERT_FALSE(password_hash_data);
@@ -269,7 +269,7 @@ TEST_F(HashPasswordManagerTest, RetrievingPasswordHashData) {
hash_password_manager.RetrievePasswordHash("USER.NAME@gmail.com",
/*is_gaia_password=*/true));
- base::Optional<PasswordHashData> non_existing_data =
+ absl::optional<PasswordHashData> non_existing_data =
hash_password_manager.RetrievePasswordHash("non_existing_user", true);
ASSERT_FALSE(non_existing_data);
}
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 be88d5e76af..1bbb4ad11be 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
@@ -7,7 +7,6 @@
#include <map>
#include <memory>
-#include <string>
#include <vector>
#include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
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 2bce2b1bccd..382be18d4fd 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
@@ -8,7 +8,6 @@
#include "base/feature_list.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
@@ -29,8 +28,8 @@
#include "components/password_manager/core/common/password_manager_features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
-using base::ASCIIToUTF16;
using base::TestMockTimeTaskRunner;
using testing::_;
using testing::AnyNumber;
@@ -161,8 +160,8 @@ TEST_F(HttpAuthManagerTest, HttpAuthFilling) {
EXPECT_CALL(*store_, GetLogins(_, _)).WillOnce(SaveArg<1>(&consumer));
httpauth_manager()->SetObserverAndDeliverCredentials(&observer,
observed_form);
- EXPECT_CALL(observer, OnAutofillDataAvailable(ASCIIToUTF16("user"),
- ASCIIToUTF16("1234")))
+ EXPECT_CALL(observer, OnAutofillDataAvailable(std::u16string(u"user"),
+ std::u16string(u"1234")))
.Times(filling_enabled);
ASSERT_TRUE(consumer);
std::vector<std::unique_ptr<PasswordForm>> result;
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
index 75409b9612a..8671dfd9f0c 100644
--- a/chromium/components/password_manager/core/browser/import/csv_password_iterator.h
+++ b/chromium/components/password_manager/core/browser/import/csv_password_iterator.h
@@ -9,9 +9,9 @@
#include <iterator>
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "components/password_manager/core/browser/import/csv_password.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
@@ -63,7 +63,7 @@ class CSVPasswordIterator {
// |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_;
+ absl::optional<CSVPassword> password_;
};
// ConsumeCSVLine is a shared utility between CSVPasswordIterator (which uses
diff --git a/chromium/components/password_manager/core/browser/import/csv_reader.h b/chromium/components/password_manager/core/browser/import/csv_reader.h
index 0670bd86889..ae25c6b0418 100644
--- a/chromium/components/password_manager/core/browser/import/csv_reader.h
+++ b/chromium/components/password_manager/core/browser/import/csv_reader.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_PASSWORD_MANAGER_CORE_BROWSER_EXPORT_CSV_READER_H_
-#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_EXPORT_CSV_READER_H_
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_CSV_READER_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_CSV_READER_H_
#include <map>
#include <string>
@@ -54,4 +54,4 @@ class CSVTable {
} // namespace password_manager
-#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_EXPORT_CSV_READER_H_
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_CSV_READER_H_
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 258b47253f3..3eb05358279 100644
--- a/chromium/components/password_manager/core/browser/import/password_importer.cc
+++ b/chromium/components/password_manager/core/browser/import/password_importer.cc
@@ -9,11 +9,11 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/location.h"
-#include "base/optional.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "components/password_manager/core/browser/import/csv_password.h"
#include "components/password_manager/core/browser/import/csv_password_sequence.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
@@ -24,10 +24,10 @@ const base::FilePath::CharType kFileExtension[] = FILE_PATH_LITERAL("csv");
// Reads and returns the contents of the file at |path| as a string, or returns
// a null value on error.
-base::Optional<std::string> ReadFileToString(const base::FilePath& path) {
+absl::optional<std::string> ReadFileToString(const base::FilePath& path) {
std::string contents;
if (!base::ReadFileToString(path, &contents))
- return base::Optional<std::string>();
+ return absl::optional<std::string>();
return contents;
}
@@ -45,7 +45,7 @@ PasswordImporter::Result ToImporterError(CSVPassword::Status status) {
// Parses passwords from |input| using |password_reader| and synchronously calls
// |completion| with the results.
static void ParsePasswords(PasswordImporter::CompletionCallback completion,
- base::Optional<std::string> input) {
+ absl::optional<std::string> input) {
// Currently, CSV is the only supported format.
if (!input) {
std::move(completion)
diff --git a/chromium/components/password_manager/core/browser/import/password_importer.h b/chromium/components/password_manager/core/browser/import/password_importer.h
index 1517bef8190..a412ea8e4bc 100644
--- a/chromium/components/password_manager/core/browser/import/password_importer.h
+++ b/chromium/components/password_manager/core/browser/import/password_importer.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_PASSWORD_IMPORTER_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_IMPORT_PASSWORD_IMPORTER_H_
-#include <string>
#include <vector>
#include "base/callback.h"
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 7a3e9cf2671..43be8ba3669 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
@@ -19,8 +19,8 @@ namespace password_manager {
namespace {
const char kTestOriginURL[] = "http://accounts.google.com/a/LoginAuth";
const char kTestSignonRealm[] = "http://accounts.google.com/";
-const char kTestUsername[] = "test@gmail.com";
-const char kTestPassword[] = "test1";
+const char16_t kTestUsername[] = u"test@gmail.com";
+const char16_t kTestPassword[] = u"test1";
const char kTestFileName[] = "test_only.csv";
} // namespace
@@ -84,10 +84,8 @@ TEST_F(PasswordImporterTest, CSVImport) {
ASSERT_EQ(1u, imported_passwords().size());
EXPECT_EQ(GURL(kTestOriginURL), imported_passwords()[0].url);
EXPECT_EQ(kTestSignonRealm, imported_passwords()[0].signon_realm);
- EXPECT_EQ(base::ASCIIToUTF16(kTestUsername),
- imported_passwords()[0].username_value);
- EXPECT_EQ(base::ASCIIToUTF16(kTestPassword),
- imported_passwords()[0].password_value);
+ EXPECT_EQ(kTestUsername, imported_passwords()[0].username_value);
+ EXPECT_EQ(kTestPassword, imported_passwords()[0].password_value);
}
TEST_F(PasswordImporterTest, ImportIOErrorDueToUnreadableFile) {
diff --git a/chromium/components/password_manager/core/browser/insecure_credentials_table_unittest.cc b/chromium/components/password_manager/core/browser/insecure_credentials_table_unittest.cc
index 89855754e96..ab0dbe13e26 100644
--- a/chromium/components/password_manager/core/browser/insecure_credentials_table_unittest.cc
+++ b/chromium/components/password_manager/core/browser/insecure_credentials_table_unittest.cc
@@ -28,9 +28,9 @@ namespace {
constexpr char kTestDomain[] = "http://example.com/";
constexpr char kTestDomain2[] = "http://test.com/";
constexpr char kTestDomain3[] = "http://google.com/";
-constexpr char kUsername[] = "user";
-constexpr char kUsername2[] = "user2";
-constexpr char kUsername3[] = "user3";
+constexpr char16_t kUsername[] = u"user";
+constexpr char16_t kUsername2[] = u"user2";
+constexpr char16_t kUsername3[] = u"user3";
using testing::ElementsAre;
using testing::IsEmpty;
@@ -41,7 +41,7 @@ PasswordForm TestForm() {
PasswordForm form;
form.signon_realm = kTestDomain;
form.url = GURL(form.signon_realm);
- form.username_value = base::ASCIIToUTF16(kUsername);
+ form.username_value = kUsername;
form.password_value = u"1234";
return form;
}
@@ -86,7 +86,7 @@ class InsecureCredentialsTableTest : public testing::Test {
// Required for iOS.
base::test::TaskEnvironment task_environment_;
std::unique_ptr<LoginDatabase> login_db_;
- InsecureCredential test_data_{kTestDomain, base::ASCIIToUTF16(kUsername),
+ InsecureCredential test_data_{kTestDomain, kUsername,
base::Time::FromTimeT(1), InsecureType::kLeaked,
IsMuted(false)};
PasswordForm test_form_ = TestForm();
@@ -124,8 +124,7 @@ TEST_F(InsecureCredentialsTableTest, SameSignonRealmDifferentUsername) {
EXPECT_THAT(login_db()->AddLogin(test_form()), SizeIs(1));
InsecureCredential compromised_credentials1 = test_data();
InsecureCredential compromised_credentials2 = test_data();
- test_form().username_value = compromised_credentials2.username =
- base::ASCIIToUTF16(kUsername2);
+ test_form().username_value = compromised_credentials2.username = kUsername2;
EXPECT_THAT(login_db()->AddLogin(test_form()), SizeIs(1));
EXPECT_TRUE(db()->AddRow(compromised_credentials1));
@@ -208,14 +207,12 @@ TEST_F(InsecureCredentialsTableTest, ReportMetricsBeforeBulkCheck) {
EXPECT_TRUE(db()->AddRow(test_data()));
test_form().signon_realm = test_data().signon_realm = kTestDomain2;
test_form().url = GURL(test_form().signon_realm);
- test_form().username_value = test_data().username =
- base::ASCIIToUTF16(kUsername2);
+ test_form().username_value = test_data().username = kUsername2;
EXPECT_THAT(login_db()->AddLogin(test_form()), SizeIs(1));
EXPECT_TRUE(db()->AddRow(test_data()));
test_form().signon_realm = test_data().signon_realm = kTestDomain3;
test_form().url = GURL(test_form().signon_realm);
- test_form().username_value = test_data().username =
- base::ASCIIToUTF16(kUsername3);
+ test_form().username_value = test_data().username = kUsername3;
test_data().insecure_type = InsecureType::kPhished;
EXPECT_THAT(login_db()->AddLogin(test_form()), SizeIs(1));
EXPECT_TRUE(db()->AddRow(test_data()));
@@ -235,8 +232,7 @@ TEST_F(InsecureCredentialsTableTest, ReportMetricsAfterBulkCheck) {
EXPECT_TRUE(db()->AddRow(test_data()));
test_form().signon_realm = test_data().signon_realm = kTestDomain2;
test_form().url = GURL(test_form().signon_realm);
- test_form().username_value = test_data().username =
- base::ASCIIToUTF16(kUsername2);
+ test_form().username_value = test_data().username = kUsername2;
EXPECT_THAT(login_db()->AddLogin(test_form()), SizeIs(1));
EXPECT_TRUE(db()->AddRow(test_data()));
@@ -262,7 +258,7 @@ TEST_F(InsecureCredentialsTableTest, GetAllRowsWithId) {
UnorderedElementsAre(compromised_credentials1, compromised_credentials2));
EXPECT_THAT(GetParentIds(db()->GetAllRows()), ElementsAre(1, 1));
- test_form().username_value = base::ASCIIToUTF16(kUsername2);
+ test_form().username_value = kUsername2;
test_data().username = test_form().username_value;
EXPECT_THAT(login_db()->AddLogin(test_form()), SizeIs(1));
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
index 9848f28bf92..c8bacb10d7d 100644
--- 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
@@ -9,7 +9,6 @@
#include "base/callback.h"
#include "base/metrics/histogram_functions.h"
-#include "base/optional.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"
@@ -20,6 +19,7 @@
#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"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
namespace {
@@ -241,7 +241,7 @@ void AuthenticatedLeakCheck::DoLeakRequest(
void AuthenticatedLeakCheck::OnLookupSingleLeakResponse(
std::unique_ptr<SingleLookupResponse> response,
- base::Optional<LeakDetectionError> error) {
+ absl::optional<LeakDetectionError> error) {
request_.reset();
if (!response) {
delegate_->OnError(*error);
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
index 9b438cae395..825af7b49cc 100644
--- 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
@@ -10,10 +10,10 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/password_manager/core/browser/leak_detection/leak_detection_check.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 "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
class GoogleServiceAuthError;
@@ -82,7 +82,7 @@ class AuthenticatedLeakCheck : public LeakDetectionCheck {
// null.
void OnLookupSingleLeakResponse(
std::unique_ptr<SingleLookupResponse> response,
- base::Optional<LeakDetectionError> error);
+ absl::optional<LeakDetectionError> error);
// Called when the network response is analazyed on the background thread. The
// method is called on the main thread.
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
index 53e26275243..dc201d693dd 100644
--- 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
@@ -28,13 +28,16 @@ namespace {
using ::testing::_;
using ::testing::ByMove;
using ::testing::ElementsAre;
+using ::testing::Eq;
using ::testing::Field;
using ::testing::Return;
using ::testing::StrictMock;
constexpr char kTestEmail[] = "user@gmail.com";
constexpr char kUsername[] = "USERNAME@gmail.com";
+constexpr char16_t kUsername16[] = u"USERNAME@gmail.com";
constexpr char kPassword[] = "password123";
+constexpr char16_t kPassword16[] = u"password123";
constexpr char kExampleCom[] = "https://example.com";
const int64_t kMockElapsedTime =
@@ -104,8 +107,7 @@ PayloadAndCallback AuthenticatedLeakCheckTest::ImitateNetworkRequest() {
identity_env().SetCookieAccounts({{info.email, info.gaia}});
identity_env().SetRefreshTokenForAccount(info.account_id);
- leak_check().Start(GURL(kExampleCom), base::ASCIIToUTF16(kUsername),
- base::ASCIIToUTF16(kPassword));
+ leak_check().Start(GURL(kExampleCom), kUsername16, kPassword16);
// Crypto stuff is done here.
task_env().RunUntilIdle();
@@ -159,8 +161,7 @@ TEST_F(AuthenticatedLeakCheckTest, GetAccessTokenBeforeEncryption) {
identity_env().SetRefreshTokenForAccount(info.account_id);
const std::string access_token = "access_token";
- leak_check().Start(GURL(kExampleCom), base::ASCIIToUTF16(kUsername),
- base::ASCIIToUTF16(kPassword));
+ leak_check().Start(GURL(kExampleCom), kUsername16, kPassword16);
// Return the access token before the crypto stuff is done.
identity_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
access_token, base::Time::Max());
@@ -196,8 +197,7 @@ TEST_F(AuthenticatedLeakCheckTest, GetAccessTokenAfterEncryption) {
identity_env().SetCookieAccounts({{info.email, info.gaia}});
identity_env().SetRefreshTokenForAccount(info.account_id);
- leak_check().Start(GURL(kExampleCom), base::ASCIIToUTF16(kUsername),
- base::ASCIIToUTF16(kPassword));
+ leak_check().Start(GURL(kExampleCom), kUsername16, kPassword16);
// crypto stuff is done here.
task_env().RunUntilIdle();
@@ -235,8 +235,7 @@ TEST_F(AuthenticatedLeakCheckTest, GetAccessTokenFailure) {
identity_env().SetCookieAccounts({{info.email, info.gaia}});
identity_env().SetRefreshTokenForAccount(info.account_id);
- leak_check().Start(GURL(kExampleCom), base::ASCIIToUTF16(kUsername),
- base::ASCIIToUTF16(kPassword));
+ leak_check().Start(GURL(kExampleCom), kUsername16, kPassword16);
EXPECT_CALL(delegate(), OnError(LeakDetectionError::kTokenRequestFailure));
identity_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
@@ -270,11 +269,11 @@ TEST_F(AuthenticatedLeakCheckTest, ParseResponse_DecryptionError) {
*ScryptHashUsernameAndPassword("another_username", kPassword),
key_server)));
- EXPECT_CALL(delegate(), OnLeakDetectionDone(false, GURL(kExampleCom),
- base::ASCIIToUTF16(kUsername),
- base::ASCIIToUTF16(kPassword)));
+ EXPECT_CALL(delegate(),
+ OnLeakDetectionDone(false, GURL(kExampleCom), Eq(kUsername16),
+ Eq(kPassword16)));
std::move(payload_and_callback.callback)
- .Run(std::move(response), base::nullopt);
+ .Run(std::move(response), absl::nullopt);
task_env().RunUntilIdle();
histogram_tester().ExpectUniqueSample(
@@ -303,11 +302,11 @@ TEST_F(AuthenticatedLeakCheckTest, ParseResponse_NoLeak) {
*ScryptHashUsernameAndPassword("another_username", kPassword),
key_server)));
- EXPECT_CALL(delegate(), OnLeakDetectionDone(false, GURL(kExampleCom),
- base::ASCIIToUTF16(kUsername),
- base::ASCIIToUTF16(kPassword)));
+ EXPECT_CALL(delegate(),
+ OnLeakDetectionDone(false, GURL(kExampleCom), Eq(kUsername16),
+ Eq(kPassword16)));
std::move(payload_and_callback.callback)
- .Run(std::move(response), base::nullopt);
+ .Run(std::move(response), absl::nullopt);
task_env().RunUntilIdle();
histogram_tester().ExpectUniqueSample(
@@ -343,11 +342,11 @@ TEST_F(AuthenticatedLeakCheckTest, ParseResponse_Leak) {
*ScryptHashUsernameAndPassword(canonicalized_username, kPassword),
key_server)));
- EXPECT_CALL(delegate(), OnLeakDetectionDone(true, GURL(kExampleCom),
- base::ASCIIToUTF16(kUsername),
- base::ASCIIToUTF16(kPassword)));
+ EXPECT_CALL(delegate(),
+ OnLeakDetectionDone(true, GURL(kExampleCom), Eq(kUsername16),
+ Eq(kPassword16)));
std::move(payload_and_callback.callback)
- .Run(std::move(response), base::nullopt);
+ .Run(std::move(response), absl::nullopt);
task_env().RunUntilIdle();
histogram_tester().ExpectUniqueSample(
diff --git a/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc b/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc
index 54c0cd5690e..aa8e38e492d 100644
--- a/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc
+++ b/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/check.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
@@ -18,6 +17,7 @@
#include "components/signin/public/identity_manager/access_token_fetcher.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
namespace {
@@ -161,7 +161,7 @@ void BulkLeakCheckImpl::OnTokenReady(
void BulkLeakCheckImpl::OnLookupLeakResponse(
CredentialHolder* weak_holder,
std::unique_ptr<SingleLookupResponse> response,
- base::Optional<LeakDetectionError> error) {
+ absl::optional<LeakDetectionError> error) {
std::unique_ptr<CredentialHolder> holder =
RemoveFromQueue(weak_holder, &waiting_response_);
diff --git a/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h b/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h
index 1315546e362..c71a7b38a94 100644
--- a/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h
+++ b/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl.h
@@ -10,13 +10,13 @@
#include "base/containers/circular_deque.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/task/cancelable_task_tracker.h"
#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.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 "third_party/abseil-cpp/absl/types/optional.h"
namespace network {
class SharedURLLoaderFactory;
@@ -73,7 +73,7 @@ class BulkLeakCheckImpl : public BulkLeakCheck {
// Called when the server replied with something.
void OnLookupLeakResponse(CredentialHolder* weak_holder,
std::unique_ptr<SingleLookupResponse> response,
- base::Optional<LeakDetectionError> error);
+ absl::optional<LeakDetectionError> error);
// Called when the response was analyzed on the background thread.
void OnAnalyzedResponse(CredentialHolder* weak_holder,
diff --git a/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl_unittest.cc b/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl_unittest.cc
index b9f6f702446..9bb9e108cdc 100644
--- a/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl_unittest.cc
+++ b/chromium/components/password_manager/core/browser/leak_detection/bulk_leak_check_impl_unittest.cc
@@ -29,7 +29,9 @@ using ::testing::Return;
constexpr char kAccessToken[] = "access_token";
constexpr char kTestEmail[] = "user@gmail.com";
+constexpr char16_t kTestEmail16[] = u"user@gmail.com";
constexpr char kTestPassword[] = "password123";
+constexpr char16_t kTestPassword16[] = u"password123";
constexpr char kUniqueString[] = "unique";
MATCHER_P(CredentialIs, credential, "") {
@@ -68,9 +70,8 @@ struct PayloadAndCallback {
LeakDetectionRequestInterface::LookupSingleLeakCallback callback;
};
-LeakCheckCredential TestCredential(base::StringPiece username) {
- return LeakCheckCredential(base::ASCIIToUTF16(username),
- base::ASCIIToUTF16(kTestPassword));
+LeakCheckCredential TestCredential(base::StringPiece16 username) {
+ return LeakCheckCredential(std::u16string(username), kTestPassword16);
}
class BulkLeakCheckTest : public testing::Test {
@@ -137,8 +138,8 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAndDestroyImmediately) {
EXPECT_CALL(delegate(), OnError).Times(0);
std::vector<LeakCheckCredential> credentials;
- credentials.push_back(TestCredential("user1"));
- credentials.push_back(TestCredential("user2"));
+ credentials.push_back(TestCredential(u"user1"));
+ credentials.push_back(TestCredential(u"user2"));
bulk_check().CheckCredentials(std::move(credentials));
}
@@ -151,7 +152,7 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAndDestroyAfterPayload) {
EXPECT_CALL(delegate(), OnError).Times(0);
std::vector<LeakCheckCredential> credentials;
- credentials.push_back(TestCredential("user1"));
+ credentials.push_back(TestCredential(u"user1"));
bulk_check().CheckCredentials(std::move(credentials));
RunUntilIdle();
}
@@ -164,7 +165,7 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAccessTokenAuthError) {
EXPECT_CALL(delegate(), OnError(LeakDetectionError::kTokenRequestFailure));
std::vector<LeakCheckCredential> credentials;
- credentials.push_back(TestCredential("user1"));
+ credentials.push_back(TestCredential(u"user1"));
bulk_check().CheckCredentials(std::move(credentials));
identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
GoogleServiceAuthError::FromServiceError("error"));
@@ -178,7 +179,7 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAccessTokenNetError) {
EXPECT_CALL(delegate(), OnError(LeakDetectionError::kNetworkError));
std::vector<LeakCheckCredential> credentials;
- credentials.push_back(TestCredential("user1"));
+ credentials.push_back(TestCredential(u"user1"));
bulk_check().CheckCredentials(std::move(credentials));
identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
GoogleServiceAuthError::FromConnectionError(net::ERR_TIMED_OUT));
@@ -192,7 +193,7 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAccessTokenSignedOut) {
EXPECT_CALL(delegate(), OnError(LeakDetectionError::kNotSignIn));
std::vector<LeakCheckCredential> credentials;
- credentials.push_back(TestCredential("user1"));
+ credentials.push_back(TestCredential(u"user1"));
bulk_check().CheckCredentials(std::move(credentials));
identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
@@ -206,7 +207,7 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsAccessDoesNetworkRequest) {
identity_test_env().SetRefreshTokenForAccount(info.account_id);
std::vector<LeakCheckCredential> credentials;
- credentials.push_back(TestCredential("USERNAME@gmail.com"));
+ credentials.push_back(TestCredential(u"USERNAME@gmail.com"));
bulk_check().CheckCredentials(std::move(credentials));
auto network_request = std::make_unique<MockLeakDetectionRequest>();
@@ -231,8 +232,8 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsMultipleNetworkRequests) {
EXPECT_EQ(0u, bulk_check().GetPendingChecksCount());
std::vector<LeakCheckCredential> credentials;
- credentials.push_back(TestCredential("user1"));
- credentials.push_back(TestCredential("user2"));
+ credentials.push_back(TestCredential(u"user1"));
+ credentials.push_back(TestCredential(u"user2"));
bulk_check().CheckCredentials(std::move(credentials));
EXPECT_EQ(2u, bulk_check().GetPendingChecksCount());
RunUntilIdle();
@@ -256,7 +257,7 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsDecryptionError) {
identity_test_env().SetRefreshTokenForAccount(info.account_id);
PayloadAndCallback payload_and_callback =
- ImitateNetworkRequest(TestCredential(kTestEmail));
+ ImitateNetworkRequest(TestCredential(kTestEmail16));
ASSERT_TRUE(!payload_and_callback.payload.empty());
auto response = std::make_unique<SingleLookupResponse>();
@@ -272,7 +273,7 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsDecryptionError) {
EXPECT_CALL(delegate(), OnError(LeakDetectionError::kHashingFailure));
std::move(payload_and_callback.callback)
- .Run(std::move(response), base::nullopt);
+ .Run(std::move(response), absl::nullopt);
RunUntilIdle();
EXPECT_EQ(0u, bulk_check().GetPendingChecksCount());
}
@@ -282,7 +283,7 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsNotLeaked) {
identity_test_env().SetCookieAccounts({{info.email, info.gaia}});
identity_test_env().SetRefreshTokenForAccount(info.account_id);
- LeakCheckCredential leaked_credential = TestCredential(kTestEmail);
+ LeakCheckCredential leaked_credential = TestCredential(kTestEmail16);
leaked_credential.SetUserData(kUniqueString,
std::make_unique<CustomData>("custom"));
PayloadAndCallback payload_and_callback =
@@ -299,13 +300,13 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsNotLeaked) {
key_server)));
EXPECT_EQ(1u, bulk_check().GetPendingChecksCount());
- leaked_credential = TestCredential(kTestEmail);
+ leaked_credential = TestCredential(kTestEmail16);
EXPECT_CALL(delegate(), OnFinishedCredential(
AllOf(CredentialIs(std::cref(leaked_credential)),
CustomDataIs("custom")),
IsLeaked(false)));
std::move(payload_and_callback.callback)
- .Run(std::move(response), base::nullopt);
+ .Run(std::move(response), absl::nullopt);
RunUntilIdle();
EXPECT_EQ(0u, bulk_check().GetPendingChecksCount());
}
@@ -315,7 +316,7 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsLeaked) {
identity_test_env().SetCookieAccounts({{info.email, info.gaia}});
identity_test_env().SetRefreshTokenForAccount(info.account_id);
- LeakCheckCredential leaked_credential = TestCredential("abc");
+ LeakCheckCredential leaked_credential = TestCredential(u"abc");
leaked_credential.SetUserData(kUniqueString,
std::make_unique<CustomData>("custom"));
PayloadAndCallback payload_and_callback =
@@ -331,13 +332,13 @@ TEST_F(BulkLeakCheckTest, CheckCredentialsLeaked) {
*ScryptHashUsernameAndPassword("abc", kTestPassword), key_server)));
EXPECT_EQ(1u, bulk_check().GetPendingChecksCount());
- leaked_credential = TestCredential("abc");
+ leaked_credential = TestCredential(u"abc");
EXPECT_CALL(delegate(), OnFinishedCredential(
AllOf(CredentialIs(std::cref(leaked_credential)),
CustomDataIs("custom")),
IsLeaked(true)));
std::move(payload_and_callback.callback)
- .Run(std::move(response), base::nullopt);
+ .Run(std::move(response), absl::nullopt);
RunUntilIdle();
EXPECT_EQ(0u, bulk_check().GetPendingChecksCount());
}
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
index d8e0d3f5ccf..ec458fe7b54 100644
--- a/chromium/components/password_manager/core/browser/leak_detection/encryption_utils.cc
+++ b/chromium/components/password_manager/core/browser/leak_detection/encryption_utils.cc
@@ -7,7 +7,6 @@
#include <climits>
#include <utility>
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
@@ -15,6 +14,7 @@
#include "base/strings/utf_string_conversions.h"
#include "crypto/openssl_util.h"
#include "crypto/sha2.h"
+#include "third_party/abseil-cpp/absl/types/optional.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"
@@ -23,9 +23,8 @@ namespace password_manager {
namespace {
-template <typename CharT>
-std::basic_string<CharT> CanonicalizeUsernameT(
- base::BasicStringPiece<CharT> username) {
+template <typename T, typename CharT = typename T::value_type>
+std::basic_string<CharT> CanonicalizeUsernameT(T username) {
static constexpr CharT kPeriod = '.';
std::basic_string<CharT> email_lower = base::ToLowerASCII(username);
@@ -85,7 +84,7 @@ std::string BucketizeUsername(base::StringPiece canonicalized_username) {
return prefix;
}
-base::Optional<std::string> ScryptHashUsernameAndPassword(
+absl::optional<std::string> ScryptHashUsernameAndPassword(
base::StringPiece canonicalized_username,
base::StringPiece password) {
// Constant salt added to the password hash on top of canonicalized_username.
@@ -120,11 +119,11 @@ base::Optional<std::string> ScryptHashUsernameAndPassword(
reinterpret_cast<const uint8_t*>(salt.data()), salt.size(),
kScryptCost, kScryptBlockSize, kScryptParallelization,
kScryptMaxMemory, key_data, kHashKeyLength);
- return scrypt_ok == 1 ? base::make_optional(std::move(result))
- : base::nullopt;
+ return scrypt_ok == 1 ? absl::make_optional(std::move(result))
+ : absl::nullopt;
}
-base::Optional<std::string> CipherEncrypt(const std::string& plaintext,
+absl::optional<std::string> CipherEncrypt(const std::string& plaintext,
std::string* key) {
using ::private_join_and_compute::ECCommutativeCipher;
auto cipher = ECCommutativeCipher::CreateWithNewKey(
@@ -136,10 +135,10 @@ base::Optional<std::string> CipherEncrypt(const std::string& plaintext,
return std::move(result).ValueOrDie();
}
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<std::string> CipherEncryptWithKey(const std::string& plaintext,
+absl::optional<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,
@@ -149,10 +148,10 @@ base::Optional<std::string> CipherEncryptWithKey(const std::string& plaintext,
if (result.ok())
return std::move(result).ValueOrDie();
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<std::string> CipherReEncrypt(
+absl::optional<std::string> CipherReEncrypt(
const std::string& already_encrypted,
std::string* key) {
using ::private_join_and_compute::ECCommutativeCipher;
@@ -165,10 +164,10 @@ base::Optional<std::string> CipherReEncrypt(
return std::move(result).ValueOrDie();
}
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<std::string> CipherDecrypt(const std::string& ciphertext,
+absl::optional<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,
@@ -178,16 +177,16 @@ base::Optional<std::string> CipherDecrypt(const std::string& ciphertext,
if (result.ok())
return std::move(result).ValueOrDie();
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<std::string> CreateNewKey() {
+absl::optional<std::string> CreateNewKey() {
using ::private_join_and_compute::ECCommutativeCipher;
auto cipher = ECCommutativeCipher::CreateWithNewKey(
NID_X9_62_prime256v1, ECCommutativeCipher::SHA256);
if (cipher.ok())
return cipher.ValueOrDie()->GetPrivateKeyBytes();
- return base::nullopt;
+ return absl::nullopt;
}
} // 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
index baca9038a8b..9c497a4d73f 100644
--- a/chromium/components/password_manager/core/browser/leak_detection/encryption_utils.h
+++ b/chromium/components/password_manager/core/browser/leak_detection/encryption_utils.h
@@ -7,8 +7,8 @@
#include <string>
-#include "base/optional.h"
#include "base/strings/string_piece_forward.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
@@ -32,7 +32,7 @@ std::string BucketizeUsername(base::StringPiece canonicalized_username);
// Produces the username/password pair hash using scrypt algorithm.
// |canonicalized_username| and |password| are UTF-8 strings.
// Returns nullopt in case of encryption failure.
-base::Optional<std::string> ScryptHashUsernameAndPassword(
+absl::optional<std::string> ScryptHashUsernameAndPassword(
base::StringPiece canonicalized_username,
base::StringPiece password);
@@ -42,12 +42,12 @@ base::Optional<std::string> ScryptHashUsernameAndPassword(
// Internally the function does some hashing first and then encrypts the result.
// In case of an encryption failure this returns nullopt and does not modify
// |key|.
-base::Optional<std::string> CipherEncrypt(const std::string& plaintext,
+absl::optional<std::string> CipherEncrypt(const std::string& plaintext,
std::string* key);
// Encrypts |plaintext| with the existing key.
// Returns nullopt in case of encryption failure.
-base::Optional<std::string> CipherEncryptWithKey(const std::string& plaintext,
+absl::optional<std::string> CipherEncryptWithKey(const std::string& plaintext,
const std::string& key);
// |already_encrypted| is an already encrypted string (output of CipherEncrypt).
@@ -56,19 +56,19 @@ base::Optional<std::string> CipherEncryptWithKey(const std::string& plaintext,
// the input.
// In case of an encryption failure this returns nullopt and does not modify
// |key|.
-base::Optional<std::string> CipherReEncrypt(
+absl::optional<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.
// Returns nullopt in case of decryption failure.
-base::Optional<std::string> CipherDecrypt(const std::string& ciphertext,
+absl::optional<std::string> CipherDecrypt(const std::string& ciphertext,
const std::string& key);
// Returns a new key suitable for the encryption functions above, or nullopt if
// the operation failed.
-base::Optional<std::string> CreateNewKey();
+absl::optional<std::string> CreateNewKey();
} // 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
index f1f69a044de..65358611cd8 100644
--- 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
@@ -5,8 +5,6 @@
#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 <string>
-
#include "base/macros.h"
#include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory.h"
#include "url/gurl.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
index 750e35f5887..8a02f433412 100644
--- 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
@@ -150,9 +150,6 @@ void LeakDetectionRequest::OnLookupSingleLeakResponse(
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, error);
return;
@@ -183,7 +180,7 @@ void LeakDetectionRequest::OnLookupSingleLeakResponse(
base::UmaHistogramCounts100000(
"PasswordManager.LeakDetection.SingleLeakResponsePrefixes",
single_lookup_response->encrypted_leak_match_prefixes.size());
- std::move(callback).Run(std::move(single_lookup_response), base::nullopt);
+ std::move(callback).Run(std::move(single_lookup_response), absl::nullopt);
}
} // 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
index d90fbe4e9f5..ff722d7b713 100644
--- 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
@@ -9,7 +9,7 @@
#include <string>
#include "base/callback_forward.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace network {
namespace mojom {
@@ -28,7 +28,7 @@ class LeakDetectionRequestInterface {
public:
using LookupSingleLeakCallback =
base::OnceCallback<void(std::unique_ptr<SingleLookupResponse>,
- base::Optional<LeakDetectionError>)>;
+ absl::optional<LeakDetectionError>)>;
LeakDetectionRequestInterface() = default;
virtual ~LeakDetectionRequestInterface() = default;
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
index ff6c5710c46..007473e3129 100644
--- 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
@@ -60,9 +60,6 @@ TEST_F(LeakDetectionRequestTest, ServerError) {
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, QuotaLimit) {
@@ -83,9 +80,6 @@ TEST_F(LeakDetectionRequestTest, QuotaLimit) {
histogram_tester().ExpectUniqueSample(
"PasswordManager.LeakDetection.HttpResponseCode",
net::HTTP_TOO_MANY_REQUESTS, 1);
- histogram_tester().ExpectUniqueSample(
- "PasswordManager.LeakDetection.NetErrorCode",
- -net::ERR_HTTP_RESPONSE_CODE_FAILURE, 1);
}
TEST_F(LeakDetectionRequestTest, MalformedServerResponse) {
@@ -122,7 +116,7 @@ TEST_F(LeakDetectionRequestTest, WellformedServerResponse) {
{kUsernameHash, kEncryptedPayload},
callback.Get());
EXPECT_CALL(callback,
- Run(testing::Pointee(SingleLookupResponse()), Eq(base::nullopt)));
+ Run(testing::Pointee(SingleLookupResponse()), Eq(absl::nullopt)));
task_env().RunUntilIdle();
histogram_tester().ExpectUniqueSample(
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
index 5e9884822d6..80863ea4ddc 100644
--- 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
@@ -8,7 +8,6 @@
#include "base/containers/span.h"
#include "base/debug/dump_without_crashing.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece_forward.h"
#include "base/strings/string_util.h"
@@ -21,6 +20,7 @@
#include "components/signin/public/identity_manager/identity_manager.h"
#include "crypto/sha2.h"
#include "google_apis/gaia/core_account_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
namespace {
@@ -94,7 +94,7 @@ LookupSingleLeakPayload PrepareLookupSingleLeakDataWithKey(
AnalyzeResponseResult CheckIfCredentialWasLeaked(
std::unique_ptr<SingleLookupResponse> response,
const std::string& encryption_key) {
- base::Optional<std::string> decrypted_username_password =
+ absl::optional<std::string> decrypted_username_password =
CipherDecrypt(response->reencrypted_lookup_hash, encryption_key);
if (!decrypted_username_password) {
DLOG(ERROR) << "Can't decrypt data="
diff --git a/chromium/components/password_manager/core/browser/leak_detection_delegate.cc b/chromium/components/password_manager/core/browser/leak_detection_delegate.cc
index fbcf5f8f40d..6e866acb22e 100644
--- a/chromium/components/password_manager/core/browser/leak_detection_delegate.cc
+++ b/chromium/components/password_manager/core/browser/leak_detection_delegate.cc
@@ -127,8 +127,6 @@ void LeakDetectionDelegate::OnShowLeakDetectionNotification(
IsPasswordSaved(leak_type));
base::UmaHistogramBoolean("PasswordManager.LeakDetection.IsPasswordReused",
IsPasswordUsedOnOtherSites(leak_type));
- base::UmaHistogramBoolean("PasswordManager.LeakDetection.IsSyncing",
- IsSyncingPasswordsNormally(leak_type));
client_->NotifyUserCredentialsWereLeaked(leak_type, url, username);
}
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
index 00b2c0dbcc1..6404454626b 100644
--- 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
@@ -16,7 +16,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::ASCIIToUTF16;
using base::BindOnce;
using base::MockCallback;
using base::Unretained;
@@ -29,21 +28,22 @@ using testing::WithArg;
namespace password_manager {
namespace {
-constexpr char kLeakedPassword[] = "leaked_password";
-constexpr char kLeakedUsername[] = "leaked_username";
-constexpr char kLeakedUsernameNonCanonicalized[] = "Leaked_Username@gmail.com";
-constexpr char kOtherUsername[] = "other_username";
+constexpr char16_t kLeakedPassword[] = u"leaked_password";
+constexpr char16_t kLeakedUsername[] = u"leaked_username";
+constexpr char16_t kLeakedUsernameNonCanonicalized[] =
+ u"Leaked_Username@gmail.com";
+constexpr char16_t kOtherUsername[] = u"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|, |username|, |password|.
PasswordForm CreateForm(base::StringPiece origin,
- base::StringPiece username,
- base::StringPiece password = kLeakedPassword) {
+ base::StringPiece16 username,
+ base::StringPiece16 password = kLeakedPassword) {
PasswordForm form;
- form.url = GURL(ASCIIToUTF16(origin));
- form.username_value = ASCIIToUTF16(username);
- form.password_value = ASCIIToUTF16(password);
+ form.url = GURL(origin);
+ form.username_value = std::u16string(username);
+ form.password_value = std::u16string(password);
form.signon_realm = form.url.GetOrigin().spec();
return form;
}
@@ -72,8 +72,7 @@ class LeakDetectionDelegateHelperTest : public testing::Test {
// Initiates determining the credential leak type.
void InitiateGetCredentialLeakType() {
delegate_helper_->ProcessLeakedPassword(GURL(kLeakedOrigin),
- ASCIIToUTF16(kLeakedUsername),
- ASCIIToUTF16(kLeakedPassword));
+ kLeakedUsername, kLeakedPassword);
task_environment_.RunUntilIdle();
}
@@ -92,7 +91,7 @@ class LeakDetectionDelegateHelperTest : public testing::Test {
void SetOnShowLeakDetectionNotificationExpectation(IsSaved is_saved,
IsReused is_reused) {
EXPECT_CALL(callback_, Run(is_saved, is_reused, GURL(kLeakedOrigin),
- ASCIIToUTF16(kLeakedUsername)))
+ std::u16string(kLeakedUsername)))
.Times(1);
}
@@ -190,14 +189,14 @@ TEST_F(LeakDetectionDelegateHelperTest, SaveLeakedCredentials) {
CreateForm(kOtherOrigin, kLeakedUsername, kLeakedPassword),
CreateForm(kLeakedOrigin, kOtherUsername, kLeakedPassword)});
SetOnShowLeakDetectionNotificationExpectation(IsSaved(true), IsReused(true));
- EXPECT_CALL(*store_, AddInsecureCredentialImpl(InsecureCredential(
- GetSignonRealm(GURL(kLeakedOrigin)),
- ASCIIToUTF16(kLeakedUsername), base::Time::Now(),
- InsecureType::kLeaked, IsMuted(false))));
- EXPECT_CALL(*store_, AddInsecureCredentialImpl(InsecureCredential(
- GetSignonRealm(GURL(kOtherOrigin)),
- ASCIIToUTF16(kLeakedUsername), base::Time::Now(),
- InsecureType::kLeaked, IsMuted(false))));
+ EXPECT_CALL(*store_,
+ AddInsecureCredentialImpl(InsecureCredential(
+ GetSignonRealm(GURL(kLeakedOrigin)), kLeakedUsername,
+ base::Time::Now(), InsecureType::kLeaked, IsMuted(false))));
+ EXPECT_CALL(*store_,
+ AddInsecureCredentialImpl(InsecureCredential(
+ GetSignonRealm(GURL(kOtherOrigin)), kLeakedUsername,
+ base::Time::Now(), InsecureType::kLeaked, IsMuted(false))));
InitiateGetCredentialLeakType();
}
@@ -207,11 +206,10 @@ TEST_F(LeakDetectionDelegateHelperTest, SaveLeakedCredentialsCanonicalized) {
kOtherOrigin, kLeakedUsernameNonCanonicalized, kLeakedPassword)});
SetOnShowLeakDetectionNotificationExpectation(IsSaved(false), IsReused(true));
- EXPECT_CALL(*store_,
- AddInsecureCredentialImpl(InsecureCredential(
- GetSignonRealm(GURL(kOtherOrigin)),
- ASCIIToUTF16(kLeakedUsernameNonCanonicalized),
- base::Time::Now(), InsecureType::kLeaked, IsMuted(false))));
+ EXPECT_CALL(*store_, AddInsecureCredentialImpl(InsecureCredential(
+ GetSignonRealm(GURL(kOtherOrigin)),
+ kLeakedUsernameNonCanonicalized, base::Time::Now(),
+ InsecureType::kLeaked, IsMuted(false))));
InitiateGetCredentialLeakType();
}
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
index 54b4089810c..422057c6db3 100644
--- a/chromium/components/password_manager/core/browser/leak_detection_dialog_utils.cc
+++ b/chromium/components/password_manager/core/browser/leak_detection_dialog_utils.cc
@@ -74,8 +74,7 @@ std::u16string GetCancelButtonLabel() {
return l10n_util::GetStringUTF16(IDS_CLOSE);
}
-std::u16string GetDescription(CredentialLeakType leak_type,
- const GURL& /*origin*/) {
+std::u16string GetDescription(CredentialLeakType leak_type) {
if (!ShouldCheckPasswords(leak_type)) {
return l10n_util::GetStringUTF16(
IDS_CREDENTIAL_LEAK_CHANGE_PASSWORD_MESSAGE);
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
index ca6ca9ab5b5..3d4684b3a9c 100644
--- a/chromium/components/password_manager/core/browser/leak_detection_dialog_utils.h
+++ b/chromium/components/password_manager/core/browser/leak_detection_dialog_utils.h
@@ -54,34 +54,31 @@ bool IsPasswordUsedOnOtherSites(CredentialLeakType leak_type);
bool IsSyncingPasswordsNormally(CredentialLeakType leak_type);
// Returns the label for the leak dialog accept button.
-std::u16string GetAcceptButtonLabel(
- password_manager::CredentialLeakType leak_type);
+std::u16string GetAcceptButtonLabel(CredentialLeakType leak_type);
// Returns the label for the leak dialog cancel button.
std::u16string GetCancelButtonLabel();
// Returns the leak dialog message based on leak type.
-std::u16string GetDescription(password_manager::CredentialLeakType leak_type,
- const GURL& origin);
+std::u16string GetDescription(CredentialLeakType leak_type);
// Returns the leak dialog title based on leak type.
-std::u16string GetTitle(password_manager::CredentialLeakType leak_type);
+std::u16string GetTitle(CredentialLeakType leak_type);
// Returns the leak dialog tooltip shown on (?) click.
std::u16string GetLeakDetectionTooltip();
// Checks whether the leak dialog should prompt user to password checkup.
-bool ShouldCheckPasswords(password_manager::CredentialLeakType leak_type);
+bool ShouldCheckPasswords(CredentialLeakType leak_type);
// Checks whether the leak dialog should show change password button.
bool ShouldShowChangePasswordButton(CredentialLeakType leak_type);
// Checks whether the leak dialog should show cancel button.
-bool ShouldShowCancelButton(password_manager::CredentialLeakType leak_type);
+bool ShouldShowCancelButton(CredentialLeakType leak_type);
// Returns the LeakDialogType corresponding to |leak_type|.
-password_manager::metrics_util::LeakDialogType GetLeakDialogType(
- password_manager::CredentialLeakType leak_type);
+metrics_util::LeakDialogType GetLeakDialogType(CredentialLeakType leak_type);
// Returns the URL used to launch the password checkup.
GURL GetPasswordCheckupURL(PasswordCheckupReferrer referrer =
diff --git a/chromium/components/password_manager/core/browser/leak_detection_dialog_utils_unittest.cc b/chromium/components/password_manager/core/browser/leak_detection_dialog_utils_unittest.cc
index f21ea944bfc..fbb9958ef4c 100644
--- a/chromium/components/password_manager/core/browser/leak_detection_dialog_utils_unittest.cc
+++ b/chromium/components/password_manager/core/browser/leak_detection_dialog_utils_unittest.cc
@@ -90,7 +90,6 @@ TEST(CredentialLeakDialogUtilsTest, GetCancelButtonLabel) {
}
TEST(CredentialLeakDialogUtilsTest, GetCheckPasswordsDescription) {
- GURL origin("https://example.com");
for (size_t i = 0; i < base::size(kLeakTypesTestCases); ++i) {
if (kLeakTypesTestCases[i].leak_message_id ==
IDS_CREDENTIAL_LEAK_CHECK_PASSWORDS_MESSAGE) {
@@ -98,13 +97,12 @@ TEST(CredentialLeakDialogUtilsTest, GetCheckPasswordsDescription) {
std::u16string expected_message = l10n_util::GetStringUTF16(
IDS_CREDENTIAL_LEAK_CHECK_PASSWORDS_MESSAGE);
EXPECT_EQ(expected_message,
- GetDescription(kLeakTypesTestCases[i].leak_type, origin));
+ GetDescription(kLeakTypesTestCases[i].leak_type));
}
}
}
TEST(CredentialLeakDialogUtilsTest, GetChangeAndCheckPasswordsDescription) {
- GURL origin("https://example.com");
for (size_t i = 0; i < base::size(kLeakTypesTestCases); ++i) {
if (kLeakTypesTestCases[i].leak_message_id ==
IDS_CREDENTIAL_LEAK_CHANGE_AND_CHECK_PASSWORDS_MESSAGE) {
@@ -112,13 +110,12 @@ TEST(CredentialLeakDialogUtilsTest, GetChangeAndCheckPasswordsDescription) {
std::u16string expected_message = l10n_util::GetStringUTF16(
IDS_CREDENTIAL_LEAK_CHANGE_AND_CHECK_PASSWORDS_MESSAGE);
EXPECT_EQ(expected_message,
- GetDescription(kLeakTypesTestCases[i].leak_type, origin));
+ GetDescription(kLeakTypesTestCases[i].leak_type));
}
}
}
TEST(CredentialLeakDialogUtilsTest, GetChangePasswordDescription) {
- GURL origin("https://example.com");
for (size_t i = 0; i < base::size(kLeakTypesTestCases); ++i) {
if (kLeakTypesTestCases[i].leak_message_id ==
IDS_CREDENTIAL_LEAK_CHANGE_PASSWORD_MESSAGE) {
@@ -126,7 +123,7 @@ TEST(CredentialLeakDialogUtilsTest, GetChangePasswordDescription) {
std::u16string expected_message = l10n_util::GetStringUTF16(
IDS_CREDENTIAL_LEAK_CHANGE_PASSWORD_MESSAGE);
EXPECT_EQ(expected_message,
- GetDescription(kLeakTypesTestCases[i].leak_type, origin));
+ GetDescription(kLeakTypesTestCases[i].leak_type));
}
}
}
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 0c88721d7ac..53c7067c767 100644
--- a/chromium/components/password_manager/core/browser/login_database_unittest.cc
+++ b/chromium/components/password_manager/core/browser/login_database_unittest.cc
@@ -2026,8 +2026,11 @@ TEST_F(LoginDatabaseTest, EncryptionDisabled) {
// accessible (this doesn't work for any plain-text value).
TEST_F(LoginDatabaseTest, HandleObfuscationMix) {
const char k_obfuscated_pw[] = "v10pass1";
+ const char16_t k_obfuscated_pw16[] = u"v10pass1";
const char k_plain_text_pw1[] = "v10pass2";
+ const char16_t k_plain_text_pw116[] = u"v10pass2";
const char k_plain_text_pw2[] = "v11pass3";
+ const char16_t k_plain_text_pw216[] = u"v11pass3";
base::FilePath file = temp_dir_.GetPath().AppendASCII("TestUnencryptedDB");
{
@@ -2035,15 +2038,15 @@ TEST_F(LoginDatabaseTest, HandleObfuscationMix) {
ASSERT_TRUE(db.Init());
// Add obfuscated (new) entries.
PasswordForm password_form = GenerateExamplePasswordForm();
- password_form.password_value = ASCIIToUTF16(k_obfuscated_pw);
+ password_form.password_value = k_obfuscated_pw16;
EXPECT_EQ(AddChangeForForm(password_form), db.AddLogin(password_form));
// Add plain-text (old) entries.
db.disable_encryption();
password_form.username_value = u"other_username";
- password_form.password_value = ASCIIToUTF16(k_plain_text_pw1);
+ password_form.password_value = k_plain_text_pw116;
EXPECT_EQ(AddChangeForForm(password_form), db.AddLogin(password_form));
password_form.username_value = u"other_username2";
- password_form.password_value = ASCIIToUTF16(k_plain_text_pw2);
+ password_form.password_value = k_plain_text_pw216;
EXPECT_EQ(AddChangeForForm(password_form), db.AddLogin(password_form));
}
@@ -2061,9 +2064,9 @@ TEST_F(LoginDatabaseTest, HandleObfuscationMix) {
k_plain_text_pw2));
// LoginDatabase serves the original values.
ASSERT_THAT(forms, SizeIs(3));
- EXPECT_EQ(k_obfuscated_pw, UTF16ToASCII(forms[0]->password_value));
- EXPECT_EQ(k_plain_text_pw1, UTF16ToASCII(forms[1]->password_value));
- EXPECT_EQ(k_plain_text_pw2, UTF16ToASCII(forms[2]->password_value));
+ EXPECT_EQ(k_obfuscated_pw16, forms[0]->password_value);
+ EXPECT_EQ(k_plain_text_pw116, forms[1]->password_value);
+ EXPECT_EQ(k_plain_text_pw216, forms[2]->password_value);
}
#endif // defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chromium/components/password_manager/core/browser/mock_biometric_authenticator.cc b/chromium/components/password_manager/core/browser/mock_biometric_authenticator.cc
new file mode 100644
index 00000000000..50377d3cf7f
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/mock_biometric_authenticator.cc
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/password_manager/core/browser/mock_biometric_authenticator.h"
+
+namespace password_manager {
+
+MockBiometricAuthenticator::MockBiometricAuthenticator() = default;
+MockBiometricAuthenticator::~MockBiometricAuthenticator() = default;
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/mock_biometric_authenticator.h b/chromium/components/password_manager/core/browser/mock_biometric_authenticator.h
new file mode 100644
index 00000000000..a5c34cfc705
--- /dev/null
+++ b/chromium/components/password_manager/core/browser/mock_biometric_authenticator.h
@@ -0,0 +1,32 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_MOCK_BIOMETRIC_AUTHENTICATOR_H_
+#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_MOCK_BIOMETRIC_AUTHENTICATOR_H_
+
+#include "base/callback.h"
+#include "components/password_manager/core/browser/biometric_authenticator.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace password_manager {
+
+// Mocked BiometricAuthenticator used by unit tests.
+class MockBiometricAuthenticator : public BiometricAuthenticator {
+ public:
+ MockBiometricAuthenticator();
+
+ MOCK_METHOD(BiometricsAvailability, CanAuthenticate, (), (override));
+ MOCK_METHOD(void,
+ Authenticate,
+ (BiometricAuthRequester, AuthenticateCallback),
+ (override));
+ MOCK_METHOD(void, Cancel, (BiometricAuthRequester), (override));
+
+ private:
+ ~MockBiometricAuthenticator() override;
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_MOCK_BIOMETRIC_AUTHENTICATOR_H_ \ No newline at end of file
diff --git a/chromium/components/password_manager/core/browser/password_autofill_manager.cc b/chromium/components/password_manager/core/browser/password_autofill_manager.cc
index 977a30fc265..adc7362f428 100644
--- a/chromium/components/password_manager/core/browser/password_autofill_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_autofill_manager.cc
@@ -34,6 +34,7 @@
#include "components/autofill/core/common/password_generation_util.h"
#include "components/favicon/core/favicon_util.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
+#include "components/password_manager/core/browser/biometric_authenticator.h"
#include "components/password_manager/core/browser/password_feature_manager.h"
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_driver.h"
@@ -325,6 +326,8 @@ PasswordAutofillManager::PasswordAutofillManager(
password_client_(password_client) {}
PasswordAutofillManager::~PasswordAutofillManager() {
+ CancelBiometricReauthIfOngoing();
+
if (deletion_callback_)
std::move(deletion_callback_).Run();
}
@@ -417,13 +420,29 @@ void PasswordAutofillManager::DidAcceptSuggestion(const std::u16string& value,
: PasswordDropdownSelectedOption::kUnlockAccountStoreGeneration,
password_client_->IsIncognito());
} else {
- bool success = FillSuggestion(GetUsernameFromSuggestion(value), identifier);
metrics_util::LogPasswordDropdownItemSelected(
PasswordDropdownSelectedOption::kPassword,
password_client_->IsIncognito());
- DCHECK(success);
- }
+ scoped_refptr<BiometricAuthenticator> authenticator =
+ password_client_->GetBiometricAuthenticator();
+ // Note: this is currently only implemented on Android. For desktop,
+ // the `authenticator` will be null.
+ if (!authenticator || authenticator->CanAuthenticate() !=
+ BiometricsAvailability::kAvailable) {
+ bool success =
+ FillSuggestion(GetUsernameFromSuggestion(value), identifier);
+ DCHECK(success);
+ } else {
+ // `this` cancels the authentication when it is destructed, which
+ // invalidates the callback, so using base::Unretained here is safe.
+ authenticator_ = std::move(authenticator);
+ authenticator_->Authenticate(
+ BiometricAuthRequester::kAutofillSuggestion,
+ base::BindOnce(&PasswordAutofillManager::OnBiometricReauthCompleted,
+ base::Unretained(this), value, identifier));
+ }
+ }
autofill_client_->HideAutofillPopup(
autofill::PopupHidingReason::kAcceptSuggestion);
}
@@ -472,6 +491,10 @@ void PasswordAutofillManager::OnAddPasswordFillData(
if (!autofill::IsValidPasswordFormFillData(fill_data))
return;
+ // If the `fill_data_` changes, then it's likely that the filling context
+ // changed as well, so the biometric auth is now out of scope.
+ CancelBiometricReauthIfOngoing();
+
fill_data_ = std::make_unique<autofill::PasswordFormFillData>(fill_data);
RequestFavicon(fill_data.url);
@@ -507,6 +530,7 @@ void PasswordAutofillManager::DeleteFillData() {
autofill_client_->HideAutofillPopup(
autofill::PopupHidingReason::kStaleData);
}
+ CancelBiometricReauthIfOngoing();
}
void PasswordAutofillManager::OnShowPasswordSuggestions(
@@ -545,6 +569,7 @@ bool PasswordAutofillManager::MaybeShowPasswordSuggestionsWithGeneration(
void PasswordAutofillManager::DidNavigateMainFrame() {
fill_data_.reset();
+ CancelBiometricReauthIfOngoing();
favicon_tracker_.TryCancelAll();
page_favicon_ = gfx::Image();
}
@@ -768,4 +793,22 @@ void PasswordAutofillManager::OnUnlockReauthCompleted(
IsLoading(false)));
}
+void PasswordAutofillManager::OnBiometricReauthCompleted(
+ const std::u16string& value,
+ int identifier,
+ bool auth_succeeded) {
+ authenticator_.reset();
+ if (!auth_succeeded)
+ return;
+ bool success = FillSuggestion(GetUsernameFromSuggestion(value), identifier);
+ DCHECK(success);
+}
+
+void PasswordAutofillManager::CancelBiometricReauthIfOngoing() {
+ if (!authenticator_)
+ return;
+ authenticator_->Cancel(BiometricAuthRequester::kAutofillSuggestion);
+ authenticator_.reset();
+}
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/password_autofill_manager.h b/chromium/components/password_manager/core/browser/password_autofill_manager.h
index fad2ba53354..ccc28cd3ee0 100644
--- a/chromium/components/password_manager/core/browser/password_autofill_manager.h
+++ b/chromium/components/password_manager/core/browser/password_autofill_manager.h
@@ -181,6 +181,16 @@ class PasswordAutofillManager : public autofill::AutofillPopupDelegate {
autofill::AutofillClient::PopupOpenArgs reopen_args,
PasswordManagerClient::ReauthSucceeded reauth_succeeded);
+ // Called when the biometric reauth that guards password filling completes.
+ // |identifier| identifies the suggestion that was selected for filling.
+ void OnBiometricReauthCompleted(const std::u16string& username_value,
+ int identifier,
+ bool auth_succeded);
+
+ // Cancels an ongoing biometric re-authentication. Usually, because
+ // the filling scope has changed or because |this| is being destroyed.
+ void CancelBiometricReauthIfOngoing();
+
std::unique_ptr<autofill::PasswordFormFillData> fill_data_;
// Contains the favicon for the credentials offered on the current page.
@@ -199,6 +209,11 @@ class PasswordAutofillManager : public autofill::AutofillPopupDelegate {
// Used to track a requested favicon.
base::CancelableTaskTracker favicon_tracker_;
+ // Used to trigger a reauthentication prompt based on biometrics that needs
+ // to be cleared before the password is filled. Currently only used
+ // on Android.
+ scoped_refptr<BiometricAuthenticator> authenticator_;
+
base::WeakPtrFactory<PasswordAutofillManager> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PasswordAutofillManager);
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 524c440ed1a..c9f9c8b9564 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
@@ -11,8 +11,10 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
+#include "base/memory/scoped_refptr.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/gmock_callback_support.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
@@ -28,6 +30,8 @@
#include "components/autofill/core/common/password_form_fill_data.h"
#include "components/autofill/core/common/password_generation_util.h"
#include "components/favicon/core/test/mock_favicon_service.h"
+#include "components/password_manager/core/browser/biometric_authenticator.h"
+#include "components/password_manager/core/browser/mock_biometric_authenticator.h"
#include "components/password_manager/core/browser/mock_password_feature_manager.h"
#include "components/password_manager/core/browser/password_manager.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
@@ -51,13 +55,13 @@
#endif
// The name of the username/password element in the form.
-const char kUsernameName[] = "username";
-const char kInvalidUsername[] = "no-username";
-const char kPasswordName[] = "password";
+const char16_t kUsernameName[] = u"username";
+const char16_t kInvalidUsername[] = u"no-username";
+const char16_t kPasswordName[] = u"password";
-const char kAliceUsername[] = "alice";
-const char kAlicePassword[] = "password";
-const char kAliceAccountStoredPassword[] = "account-stored-password";
+const char16_t kAliceUsername[] = u"alice";
+const char16_t kAlicePassword[] = u"password";
+const char16_t kAliceAccountStoredPassword[] = u"account-stored-password";
using autofill::PopupType;
using autofill::Suggestion;
@@ -66,6 +70,7 @@ using autofill::SuggestionVectorIdsAre;
using autofill::SuggestionVectorLabelsAre;
using autofill::SuggestionVectorValuesAre;
using autofill::password_generation::PasswordGenerationType;
+using base::test::RunOnceCallback;
using favicon_base::FaviconImageCallback;
using gfx::test::AreImagesEqual;
using testing::_;
@@ -146,6 +151,15 @@ class TestPasswordManagerClient : public StubPasswordManagerClient {
.WillByDefault(Return(needs_signin));
}
+ void SetBiometricAuthenticator(
+ scoped_refptr<MockBiometricAuthenticator> biometric_authenticator) {
+ biometric_authenticator_ = std::move(biometric_authenticator);
+ }
+
+ scoped_refptr<BiometricAuthenticator> GetBiometricAuthenticator() override {
+ return biometric_authenticator_;
+ }
+
MOCK_METHOD(void, GeneratePassword, (PasswordGenerationType), (override));
MOCK_METHOD(void,
TriggerReauthForPrimaryAccount,
@@ -161,6 +175,7 @@ class TestPasswordManagerClient : public StubPasswordManagerClient {
private:
MockPasswordManagerDriver driver_;
+ scoped_refptr<MockBiometricAuthenticator> biometric_authenticator_ = nullptr;
signin::IdentityTestEnvironment identity_test_env_;
std::unique_ptr<MockPasswordFeatureManager> feature_manager_{
new NiceMock<MockPasswordFeatureManager>};
@@ -257,18 +272,17 @@ autofill::AutofillClient::PopupOpenArgs CreateReopenArgsWithTestSuggestions(
class PasswordAutofillManagerTest : public testing::Test {
protected:
PasswordAutofillManagerTest()
- : test_username_(base::ASCIIToUTF16(kAliceUsername)),
- test_password_(base::ASCIIToUTF16(kAlicePassword)) {}
+ : test_username_(kAliceUsername), test_password_(kAlicePassword) {}
void SetUp() override {
// Add a preferred login and an additional login to the FillData.
autofill::FormFieldData username_field;
- username_field.name = base::ASCIIToUTF16(kUsernameName);
+ username_field.name = kUsernameName;
username_field.value = test_username_;
fill_data_.username_field = username_field;
autofill::FormFieldData password_field;
- password_field.name = base::ASCIIToUTF16(kPasswordName);
+ password_field.name = kPasswordName;
password_field.value = test_password_;
fill_data_.password_field = password_field;
}
@@ -316,6 +330,9 @@ class PasswordAutofillManagerTest : public testing::Test {
std::unique_ptr<PasswordAutofillManager> password_autofill_manager_;
+ scoped_refptr<MockBiometricAuthenticator> authenticator_ =
+ base::MakeRefCounted<MockBiometricAuthenticator>();
+
std::u16string test_username_;
std::u16string test_password_;
@@ -338,8 +355,8 @@ TEST_F(PasswordAutofillManagerTest, FillSuggestion) {
testing::Mock::VerifyAndClearExpectations(client.mock_driver());
EXPECT_CALL(*client.mock_driver(), FillSuggestion(_, _)).Times(0);
- EXPECT_FALSE(password_autofill_manager_->FillSuggestionForTest(
- base::ASCIIToUTF16(kInvalidUsername)));
+ EXPECT_FALSE(
+ password_autofill_manager_->FillSuggestionForTest(kInvalidUsername));
password_autofill_manager_->DidNavigateMainFrame();
EXPECT_FALSE(
@@ -357,8 +374,8 @@ TEST_F(PasswordAutofillManagerTest, PreviewSuggestion) {
testing::Mock::VerifyAndClearExpectations(client.mock_driver());
EXPECT_CALL(*client.mock_driver(), PreviewSuggestion(_, _)).Times(0);
- EXPECT_FALSE(password_autofill_manager_->PreviewSuggestionForTest(
- base::ASCIIToUTF16(kInvalidUsername)));
+ EXPECT_FALSE(
+ password_autofill_manager_->PreviewSuggestionForTest(kInvalidUsername));
password_autofill_manager_->DidNavigateMainFrame();
EXPECT_FALSE(
@@ -437,7 +454,7 @@ TEST_F(PasswordAutofillManagerTest,
// Load filling data and account-stored duplicate with a different password.
autofill::PasswordFormFillData data = CreateTestFormFillData();
autofill::PasswordAndMetadata duplicate;
- duplicate.password = base::ASCIIToUTF16(kAliceAccountStoredPassword);
+ duplicate.password = kAliceAccountStoredPassword;
duplicate.realm = data.preferred_realm;
duplicate.uses_account_store = true;
duplicate.username = data.username_field.value;
@@ -1435,4 +1452,272 @@ TEST_F(PasswordAutofillManagerTest, DisplayAccountSuggestionsIndicatorIcon) {
EXPECT_EQ(open_args.popup_type, PopupType::kPasswords);
}
+TEST_F(PasswordAutofillManagerTest, FillsSuggestionIfAuthNotAvailable) {
+ TestPasswordManagerClient client;
+ NiceMock<MockAutofillClient> autofill_client;
+ client.SetBiometricAuthenticator(authenticator_);
+
+ InitializePasswordAutofillManager(&client, &autofill_client);
+
+ for (bool is_suggestion_on_password_field : {false, true}) {
+ SCOPED_TRACE(testing::Message() << "is_suggestion_on_password_field = "
+ << is_suggestion_on_password_field);
+ // Show the popup
+ autofill::AutofillClient::PopupOpenArgs open_args;
+ EXPECT_CALL(autofill_client, ShowAutofillPopup)
+ .WillOnce(testing::SaveArg<0>(&open_args));
+
+ int show_suggestion_options =
+ is_suggestion_on_password_field ? autofill::IS_PASSWORD_FIELD : 0;
+ password_autofill_manager_->OnShowPasswordSuggestions(
+ base::i18n::RIGHT_TO_LEFT, std::u16string(), show_suggestion_options,
+ gfx::RectF());
+ ASSERT_GE(open_args.suggestions.size(), 1u);
+ EXPECT_THAT(open_args.suggestions,
+ SuggestionVectorIdsAre(ElementsAre(
+ is_suggestion_on_password_field
+ ? autofill::POPUP_ITEM_ID_PASSWORD_ENTRY
+ : autofill::POPUP_ITEM_ID_USERNAME_ENTRY,
+ autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY)));
+
+ // Suggestions should always be filled if the authenticator is not available
+ // or it cannot be used.
+ EXPECT_CALL(*client.mock_driver(),
+ FillSuggestion(test_username_, test_password_));
+
+ // The authenticator exists, but cannot be used for authentication.
+ EXPECT_CALL(*authenticator_.get(), CanAuthenticate())
+ .WillOnce(
+ Return(password_manager::BiometricsAvailability::kNoHardware));
+
+ // Accept the suggestion to start the filing process which tries to
+ // reauthenticate the user if possible.
+ password_autofill_manager_->DidAcceptSuggestion(
+ test_username_, autofill::POPUP_ITEM_ID_PASSWORD_ENTRY, 1);
+ }
+}
+
+TEST_F(PasswordAutofillManagerTest, FillsSuggestionIfAuthSuccessful) {
+ TestPasswordManagerClient client;
+ NiceMock<MockAutofillClient> autofill_client;
+ client.SetBiometricAuthenticator(authenticator_);
+
+ InitializePasswordAutofillManager(&client, &autofill_client);
+
+ for (bool is_suggestion_on_password_field : {false, true}) {
+ SCOPED_TRACE(testing::Message() << "is_suggestion_on_password_field = "
+ << is_suggestion_on_password_field);
+ // Show the popup
+ autofill::AutofillClient::PopupOpenArgs open_args;
+ EXPECT_CALL(autofill_client, ShowAutofillPopup)
+ .WillOnce(testing::SaveArg<0>(&open_args));
+
+ int show_suggestion_options =
+ is_suggestion_on_password_field ? autofill::IS_PASSWORD_FIELD : 0;
+ password_autofill_manager_->OnShowPasswordSuggestions(
+ base::i18n::RIGHT_TO_LEFT, std::u16string(), show_suggestion_options,
+ gfx::RectF());
+ ASSERT_GE(open_args.suggestions.size(), 1u);
+ EXPECT_THAT(open_args.suggestions,
+ SuggestionVectorIdsAre(ElementsAre(
+ is_suggestion_on_password_field
+ ? autofill::POPUP_ITEM_ID_PASSWORD_ENTRY
+ : autofill::POPUP_ITEM_ID_USERNAME_ENTRY,
+ autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY)));
+
+ // The suggestion should be filled if the authentication is successful.
+ EXPECT_CALL(*client.mock_driver(),
+ FillSuggestion(test_username_, test_password_));
+
+ // Accepting a suggestion should trigger a call to hide the popup.
+ EXPECT_CALL(
+ autofill_client,
+ HideAutofillPopup(autofill::PopupHidingReason::kAcceptSuggestion));
+
+ // The authenticator exists and is available.
+ EXPECT_CALL(*authenticator_.get(), CanAuthenticate())
+ .WillOnce(Return(password_manager::BiometricsAvailability::kAvailable));
+ EXPECT_CALL(*authenticator_.get(),
+ Authenticate(BiometricAuthRequester::kAutofillSuggestion, _))
+ .WillOnce(RunOnceCallback<1>(/*auth_succeeded=*/true));
+
+ // Accept the suggestion to start the filing process which tries to
+ // reauthenticate the user if possible.
+ password_autofill_manager_->DidAcceptSuggestion(
+ test_username_, autofill::POPUP_ITEM_ID_PASSWORD_ENTRY, 1);
+ }
+}
+
+TEST_F(PasswordAutofillManagerTest, DoesntFillSuggestionIfAuthFailed) {
+ for (bool is_suggestion_on_password_field : {false, true}) {
+ TestPasswordManagerClient client;
+ NiceMock<MockAutofillClient> autofill_client;
+ client.SetBiometricAuthenticator(authenticator_);
+
+ InitializePasswordAutofillManager(&client, &autofill_client);
+
+ SCOPED_TRACE(testing::Message() << "is_suggestion_on_password_field = "
+ << is_suggestion_on_password_field);
+ // Show the popup
+ autofill::AutofillClient::PopupOpenArgs open_args;
+ EXPECT_CALL(autofill_client, ShowAutofillPopup)
+ .WillOnce(testing::SaveArg<0>(&open_args));
+
+ int show_suggestion_options =
+ is_suggestion_on_password_field ? autofill::IS_PASSWORD_FIELD : 0;
+ password_autofill_manager_->OnShowPasswordSuggestions(
+ base::i18n::RIGHT_TO_LEFT, std::u16string(), show_suggestion_options,
+ gfx::RectF());
+ ASSERT_GE(open_args.suggestions.size(), 1u);
+ EXPECT_THAT(open_args.suggestions,
+ SuggestionVectorIdsAre(ElementsAre(
+ is_suggestion_on_password_field
+ ? autofill::POPUP_ITEM_ID_PASSWORD_ENTRY
+ : autofill::POPUP_ITEM_ID_USERNAME_ENTRY,
+ autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY)));
+
+ // The suggestion should not be filled if the authentication fails.
+ EXPECT_CALL(*client.mock_driver(),
+ FillSuggestion(test_username_, test_password_))
+ .Times(0);
+ // Accepting a suggestion should trigger a call to hide the popup.
+ EXPECT_CALL(
+ autofill_client,
+ HideAutofillPopup(autofill::PopupHidingReason::kAcceptSuggestion));
+
+ // The authenticator exists and is available.
+ EXPECT_CALL(*authenticator_.get(), CanAuthenticate())
+ .WillOnce(Return(password_manager::BiometricsAvailability::kAvailable));
+ EXPECT_CALL(*authenticator_.get(),
+ Authenticate(BiometricAuthRequester::kAutofillSuggestion, _))
+ .WillOnce(RunOnceCallback<1>(/*auth_succeeded=*/false));
+
+ // Accept the suggestion to start the filing process which tries to
+ // reauthenticate the user if possible.
+ password_autofill_manager_->DidAcceptSuggestion(
+ test_username_, autofill::POPUP_ITEM_ID_PASSWORD_ENTRY, 1);
+ }
+}
+
+TEST_F(PasswordAutofillManagerTest, CancelsOngoingBiometricAuthOnDestroy) {
+ TestPasswordManagerClient client;
+ NiceMock<MockAutofillClient> autofill_client;
+ client.SetBiometricAuthenticator(authenticator_);
+
+ InitializePasswordAutofillManager(&client, &autofill_client);
+
+ // Show the popup
+ autofill::AutofillClient::PopupOpenArgs open_args;
+ EXPECT_CALL(autofill_client, ShowAutofillPopup)
+ .WillOnce(testing::SaveArg<0>(&open_args));
+
+ password_autofill_manager_->OnShowPasswordSuggestions(
+ base::i18n::RIGHT_TO_LEFT, std::u16string(), autofill::IS_PASSWORD_FIELD,
+ gfx::RectF());
+ ASSERT_GE(open_args.suggestions.size(), 1u);
+ EXPECT_THAT(open_args.suggestions,
+ SuggestionVectorIdsAre(ElementsAre(
+ autofill::POPUP_ITEM_ID_PASSWORD_ENTRY,
+ autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY)));
+ EXPECT_CALL(*client.mock_driver(),
+ FillSuggestion(test_username_, test_password_))
+ .Times(0);
+
+ // The authenticator exists and is available.
+ EXPECT_CALL(*authenticator_.get(), CanAuthenticate())
+ .WillOnce(Return(password_manager::BiometricsAvailability::kAvailable));
+ EXPECT_CALL(*authenticator_.get(),
+ Authenticate(BiometricAuthRequester::kAutofillSuggestion, _));
+
+ // Accept the suggestion to start the filing process which tries to
+ // reauthenticate the user if possible.
+ password_autofill_manager_->DidAcceptSuggestion(
+ test_username_, autofill::POPUP_ITEM_ID_PASSWORD_ENTRY, 1);
+
+ EXPECT_CALL(*authenticator_.get(),
+ Cancel(BiometricAuthRequester::kAutofillSuggestion));
+}
+
+TEST_F(PasswordAutofillManagerTest,
+ CancelsOngoingBiometricAuthOnDeleteFillData) {
+ TestPasswordManagerClient client;
+ NiceMock<MockAutofillClient> autofill_client;
+ client.SetBiometricAuthenticator(authenticator_);
+
+ InitializePasswordAutofillManager(&client, &autofill_client);
+
+ // Show the popup
+ autofill::AutofillClient::PopupOpenArgs open_args;
+ EXPECT_CALL(autofill_client, ShowAutofillPopup)
+ .WillOnce(testing::SaveArg<0>(&open_args));
+
+ password_autofill_manager_->OnShowPasswordSuggestions(
+ base::i18n::RIGHT_TO_LEFT, std::u16string(), autofill::IS_PASSWORD_FIELD,
+ gfx::RectF());
+ ASSERT_GE(open_args.suggestions.size(), 1u);
+ EXPECT_THAT(open_args.suggestions,
+ SuggestionVectorIdsAre(ElementsAre(
+ autofill::POPUP_ITEM_ID_PASSWORD_ENTRY,
+ autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY)));
+ EXPECT_CALL(*client.mock_driver(),
+ FillSuggestion(test_username_, test_password_))
+ .Times(0);
+
+ // The authenticator exists and is available.
+ EXPECT_CALL(*authenticator_.get(), CanAuthenticate())
+ .WillOnce(Return(password_manager::BiometricsAvailability::kAvailable));
+ EXPECT_CALL(*authenticator_.get(),
+ Authenticate(BiometricAuthRequester::kAutofillSuggestion, _));
+
+ // Accept the suggestion to start the filing process which tries to
+ // reauthenticate the user if possible.
+ password_autofill_manager_->DidAcceptSuggestion(
+ test_username_, autofill::POPUP_ITEM_ID_PASSWORD_ENTRY, 1);
+
+ EXPECT_CALL(*authenticator_.get(),
+ Cancel(BiometricAuthRequester::kAutofillSuggestion));
+ password_autofill_manager_->DeleteFillData();
+}
+
+TEST_F(PasswordAutofillManagerTest,
+ CancelsOngoingBiometricAuthOnFillDataChange) {
+ TestPasswordManagerClient client;
+ NiceMock<MockAutofillClient> autofill_client;
+ client.SetBiometricAuthenticator(authenticator_);
+
+ InitializePasswordAutofillManager(&client, &autofill_client);
+
+ // Show the popup
+ autofill::AutofillClient::PopupOpenArgs open_args;
+ EXPECT_CALL(autofill_client, ShowAutofillPopup)
+ .WillOnce(testing::SaveArg<0>(&open_args));
+
+ password_autofill_manager_->OnShowPasswordSuggestions(
+ base::i18n::RIGHT_TO_LEFT, std::u16string(), autofill::IS_PASSWORD_FIELD,
+ gfx::RectF());
+ ASSERT_GE(open_args.suggestions.size(), 1u);
+ EXPECT_THAT(open_args.suggestions,
+ SuggestionVectorIdsAre(ElementsAre(
+ autofill::POPUP_ITEM_ID_PASSWORD_ENTRY,
+ autofill::POPUP_ITEM_ID_ALL_SAVED_PASSWORDS_ENTRY)));
+ EXPECT_CALL(*client.mock_driver(),
+ FillSuggestion(test_username_, test_password_))
+ .Times(0);
+
+ // The authenticator exists and is available.
+ EXPECT_CALL(*authenticator_.get(), CanAuthenticate())
+ .WillOnce(Return(password_manager::BiometricsAvailability::kAvailable));
+ EXPECT_CALL(*authenticator_.get(),
+ Authenticate(BiometricAuthRequester::kAutofillSuggestion, _));
+
+ // Accept the suggestion to start the filing process which tries to
+ // reauthenticate the user if possible.
+ password_autofill_manager_->DidAcceptSuggestion(
+ test_username_, autofill::POPUP_ITEM_ID_PASSWORD_ENTRY, 1);
+
+ EXPECT_CALL(*authenticator_.get(),
+ Cancel(BiometricAuthRequester::kAutofillSuggestion));
+ password_autofill_manager_->OnAddPasswordFillData(CreateTestFormFillData());
+}
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/password_bubble_experiment.cc b/chromium/components/password_manager/core/browser/password_bubble_experiment.cc
index 7200bb6eddf..f0cf92aa2ba 100644
--- a/chromium/components/password_manager/core/browser/password_bubble_experiment.cc
+++ b/chromium/components/password_manager/core/browser/password_bubble_experiment.cc
@@ -17,6 +17,7 @@
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
+#include "components/signin/public/base/signin_buildflags.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/sync/driver/sync_service.h"
#include "components/sync/driver/sync_user_settings.h"
@@ -61,9 +62,7 @@ void TurnOffAutoSignin(PrefService* prefs) {
bool ShouldShowChromeSignInPasswordPromo(
PrefService* prefs,
const syncer::SyncService* sync_service) {
-#if BUILDFLAG(IS_CHROMEOS_ASH)
- return false;
-#else
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
// If the account-scoped storage for passwords is enabled, then the user
// doesn't need to enable the full Sync feature to get their account
// passwords, so suppress the promo in this case.
@@ -97,7 +96,9 @@ bool ShouldShowChromeSignInPasswordPromo(
prefs->GetInteger(
password_manager::prefs::kNumberSignInPasswordPromoShown) <
kThreshold;
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#else
+ return false;
+#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
}
} // namespace password_bubble_experiment
diff --git a/chromium/components/password_manager/core/browser/password_bubble_experiment_unittest.cc b/chromium/components/password_manager/core/browser/password_bubble_experiment_unittest.cc
index 793190396a0..ad0a40db333 100644
--- a/chromium/components/password_manager/core/browser/password_bubble_experiment_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_bubble_experiment_unittest.cc
@@ -46,8 +46,8 @@ class PasswordManagerPasswordBubbleExperimentTest : public testing::Test {
CustomPassphraseState passphrase_state) {
sync_service()->SetPreferredDataTypes({type});
sync_service()->SetActiveDataTypes({type});
- sync_service()->SetIsUsingSecondaryPassphrase(passphrase_state ==
- CustomPassphraseState::SET);
+ sync_service()->SetIsUsingExplicitPassphrase(passphrase_state ==
+ CustomPassphraseState::SET);
}
private:
@@ -99,16 +99,16 @@ TEST_F(PasswordManagerPasswordBubbleExperimentTest,
: syncer::SyncService::TransportState::
PENDING_DESIRED_CONFIGURATION);
prefs()->SetBoolean(prefs::kSigninAllowed, test_case.is_signin_allowed);
-#if BUILDFLAG(IS_CHROMEOS_ASH)
- EXPECT_FALSE(ShouldShowChromeSignInPasswordPromo(prefs(), sync_service()));
-#else
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
EXPECT_EQ(test_case.result,
ShouldShowChromeSignInPasswordPromo(prefs(), sync_service()));
+#else
+ EXPECT_FALSE(ShouldShowChromeSignInPasswordPromo(prefs(), sync_service()));
#endif
}
}
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
TEST_F(PasswordManagerPasswordBubbleExperimentTest, ReviveSignInPasswordPromo) {
// If kEnablePasswordsAccountStorage is enabled, then the password manager
// bubble never shows Sync promos, so this test doesn't apply.
diff --git a/chromium/components/password_manager/core/browser/password_form.cc b/chromium/components/password_manager/core/browser/password_form.cc
index 29ac5b13879..2d480710e8b 100644
--- a/chromium/components/password_manager/core/browser/password_form.cc
+++ b/chromium/components/password_manager/core/browser/password_form.cc
@@ -202,7 +202,11 @@ bool PasswordForm::IsSingleUsername() const {
}
bool PasswordForm::IsUsingAccountStore() const {
- return in_store == Store::kAccountStore;
+ return (in_store & Store::kAccountStore) != Store::kNotSet;
+}
+
+bool PasswordForm::IsUsingProfileStore() const {
+ return (in_store & Store::kProfileStore) != Store::kNotSet;
}
bool PasswordForm::HasNonEmptyPasswordValue() const {
@@ -285,7 +289,7 @@ std::ostream& operator<<(std::ostream& os, const PasswordForm& form) {
!it_default_key_values.IsAtEnd(); it_default_key_values.Advance()) {
const base::Value* actual_value;
if (form_json.Get(it_default_key_values.key(), &actual_value) &&
- it_default_key_values.value().Equals(actual_value)) {
+ it_default_key_values.value() == *actual_value) {
form_json.Remove(it_default_key_values.key(), nullptr);
}
}
diff --git a/chromium/components/password_manager/core/browser/password_form.h b/chromium/components/password_manager/core/browser/password_form.h
index f1aec6b956e..12a196e60a8 100644
--- a/chromium/components/password_manager/core/browser/password_form.h
+++ b/chromium/components/password_manager/core/browser/password_form.h
@@ -317,11 +317,15 @@ struct PasswordForm {
// Default value.
kNotSet = 0,
// Credential came from the profile (i.e. local) storage.
- kProfileStore = 1,
+ kProfileStore = 1 << 0,
// Credential came from the Gaia-account-scoped storage.
- kAccountStore = 2,
+ kAccountStore = 1 << 1,
kMaxValue = kAccountStore
};
+ // Please use IsUsingAccountStore and IsUsingProfileStore to check in which
+ // store the form is present.
+ // TODO(crbug.com/1201643): Rename to in_stores to reflect possibility of
+ // password presence in both stores.
Store in_store = Store::kNotSet;
// Vector of hashes of the gaia id for users who prefer not to move this
@@ -354,10 +358,12 @@ struct PasswordForm {
// not set.
bool IsSingleUsername() const;
- // Returns whether this form is stored in the account-scoped store, i.e.
- // whether |in_store == Store::kAccountStore|.
+ // Returns whether this form is stored in the account-scoped store.
bool IsUsingAccountStore() const;
+ // Returns whether this form is stored in the profile-scoped store.
+ bool IsUsingProfileStore() const;
+
// Returns true when |password_value| or |new_password_value| are non-empty.
bool HasNonEmptyPasswordValue() const;
@@ -387,6 +393,18 @@ std::ostream& operator<<(std::ostream& os, const PasswordForm& form);
std::ostream& operator<<(std::ostream& os, PasswordForm* form);
#endif
+constexpr PasswordForm::Store operator&(PasswordForm::Store lhs,
+ PasswordForm::Store rhs) {
+ return static_cast<PasswordForm::Store>(static_cast<int>(lhs) &
+ static_cast<int>(rhs));
+}
+
+constexpr PasswordForm::Store operator|(PasswordForm::Store lhs,
+ PasswordForm::Store rhs) {
+ return static_cast<PasswordForm::Store>(static_cast<int>(lhs) |
+ static_cast<int>(rhs));
+}
+
} // namespace password_manager
#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_FORM_H_
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 52d143d7e2f..2cb828c4a90 100644
--- a/chromium/components/password_manager/core/browser/password_form_filling.h
+++ b/chromium/components/password_manager/core/browser/password_form_filling.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_FORM_FILLING_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_FORM_FILLING_H_
-#include <string>
#include <vector>
#include "base/memory/weak_ptr.h"
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 2d5c01bfa60..7bc88c9b8a9 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
@@ -30,8 +30,6 @@ using autofill::FieldRendererId;
using autofill::FormData;
using autofill::FormRendererId;
using autofill::PasswordFormFillData;
-using base::ASCIIToUTF16;
-using base::UTF16ToASCII;
using testing::_;
using testing::Return;
using testing::SaveArg;
@@ -40,15 +38,15 @@ using Store = password_manager::PasswordForm::Store;
namespace password_manager {
namespace {
-constexpr char kPreferredUsername[] = "test@gmail.com";
-constexpr char kPreferredPassword[] = "password";
-constexpr char kPreferredAlternatePassword[] = "new_password";
+constexpr char16_t kPreferredUsername[] = u"test@gmail.com";
+constexpr char16_t kPreferredPassword[] = u"password";
+constexpr char16_t kPreferredAlternatePassword[] = u"new_password";
-constexpr char kDuplicateLocalUsername[] = "local@gmail.com";
-constexpr char kDuplicateLocalPassword[] = "local_password";
+constexpr char16_t kDuplicateLocalUsername[] = u"local@gmail.com";
+constexpr char16_t kDuplicateLocalPassword[] = u"local_password";
-constexpr char kSyncedUsername[] = "synced@gmail.com";
-constexpr char kSyncedPassword[] = "password";
+constexpr char16_t kSyncedUsername[] = u"synced@gmail.com";
+constexpr char16_t kSyncedPassword[] = u"password";
class MockPasswordManagerDriver : public StubPasswordManagerDriver {
public:
@@ -75,20 +73,19 @@ class MockPasswordManagerClient : public StubPasswordManagerClient {
MOCK_METHOD(bool, IsCommittedMainFrameSecure, (), (const, override));
};
-PasswordForm CreateForm(std::string username,
- std::string password,
+PasswordForm CreateForm(std::u16string username,
+ std::u16string password,
Store store) {
PasswordForm form;
- form.username_value = ASCIIToUTF16(username);
- form.password_value = ASCIIToUTF16(password);
+ form.username_value = username;
+ form.password_value = password;
form.in_store = store;
return form;
}
// Matcher for PasswordAndMetadata.
MATCHER_P3(IsLogin, username, password, uses_account_store, std::string()) {
- return UTF16ToASCII(arg.username) == username &&
- UTF16ToASCII(arg.password) == password &&
+ return arg.username == username && arg.password == password &&
arg.uses_account_store == uses_account_store;
}
@@ -456,9 +453,9 @@ TEST(PasswordFormFillDataTest, TestSinglePreferredMatch) {
form_on_page.url = GURL("https://foo.com/");
form_on_page.action = GURL("https://foo.com/login");
form_on_page.username_element = u"username";
- form_on_page.username_value = ASCIIToUTF16(kPreferredUsername);
+ form_on_page.username_value = kPreferredUsername;
form_on_page.password_element = u"password";
- form_on_page.password_value = ASCIIToUTF16(kPreferredPassword);
+ form_on_page.password_value = kPreferredPassword;
form_on_page.submit_element = u"";
form_on_page.signon_realm = "https://foo.com/";
form_on_page.scheme = PasswordForm::Scheme::kHtml;
@@ -468,9 +465,9 @@ TEST(PasswordFormFillDataTest, TestSinglePreferredMatch) {
preferred_match.url = GURL("https://foo.com/");
preferred_match.action = GURL("https://foo.com/login");
preferred_match.username_element = u"username";
- preferred_match.username_value = ASCIIToUTF16(kPreferredUsername);
+ preferred_match.username_value = kPreferredUsername;
preferred_match.password_element = u"password";
- preferred_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ preferred_match.password_value = kPreferredPassword;
preferred_match.submit_element = u"";
preferred_match.signon_realm = "https://foo.com/";
preferred_match.scheme = PasswordForm::Scheme::kHtml;
@@ -505,9 +502,9 @@ TEST(PasswordFormFillDataTest, TestPublicSuffixDomainMatching) {
form_on_page.url = GURL("https://foo.com/");
form_on_page.action = GURL("https://foo.com/login");
form_on_page.username_element = u"username";
- form_on_page.username_value = ASCIIToUTF16(kPreferredUsername);
+ form_on_page.username_value = kPreferredUsername;
form_on_page.password_element = u"password";
- form_on_page.password_value = ASCIIToUTF16(kPreferredPassword);
+ form_on_page.password_value = kPreferredPassword;
form_on_page.submit_element = u"";
form_on_page.signon_realm = "https://foo.com/";
form_on_page.scheme = PasswordForm::Scheme::kHtml;
@@ -517,9 +514,9 @@ TEST(PasswordFormFillDataTest, TestPublicSuffixDomainMatching) {
preferred_match.url = GURL("https://mobile.foo.com/");
preferred_match.action = GURL("https://mobile.foo.com/login");
preferred_match.username_element = u"username";
- preferred_match.username_value = ASCIIToUTF16(kPreferredUsername);
+ preferred_match.username_value = kPreferredUsername;
preferred_match.password_element = u"password";
- preferred_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ preferred_match.password_value = kPreferredPassword;
preferred_match.submit_element = u"";
preferred_match.signon_realm = "https://foo.com/";
preferred_match.is_public_suffix_match = true;
@@ -533,7 +530,7 @@ TEST(PasswordFormFillDataTest, TestPublicSuffixDomainMatching) {
exact_match.username_element = u"username";
exact_match.username_value = u"test1@gmail.com";
exact_match.password_element = u"password";
- exact_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ exact_match.password_value = kPreferredPassword;
exact_match.submit_element = u"";
exact_match.signon_realm = "https://foo.com/";
exact_match.scheme = PasswordForm::Scheme::kHtml;
@@ -546,7 +543,7 @@ TEST(PasswordFormFillDataTest, TestPublicSuffixDomainMatching) {
public_suffix_match.username_element = u"username";
public_suffix_match.username_value = u"test2@gmail.com";
public_suffix_match.password_element = u"password";
- public_suffix_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ public_suffix_match.password_value = kPreferredPassword;
public_suffix_match.submit_element = u"";
public_suffix_match.is_public_suffix_match = true;
public_suffix_match.signon_realm = "https://foo.com/";
@@ -586,9 +583,9 @@ TEST(PasswordFormFillDataTest, TestAffiliationMatch) {
form_on_page.url = GURL("https://foo.com/");
form_on_page.action = GURL("https://foo.com/login");
form_on_page.username_element = u"username";
- form_on_page.username_value = ASCIIToUTF16(kPreferredUsername);
+ form_on_page.username_value = kPreferredUsername;
form_on_page.password_element = u"password";
- form_on_page.password_value = ASCIIToUTF16(kPreferredPassword);
+ form_on_page.password_value = kPreferredPassword;
form_on_page.submit_element = u"";
form_on_page.signon_realm = "https://foo.com/";
form_on_page.scheme = PasswordForm::Scheme::kHtml;
@@ -596,8 +593,8 @@ TEST(PasswordFormFillDataTest, TestAffiliationMatch) {
// Create a match from the database that matches using affiliation.
PasswordForm preferred_match;
preferred_match.url = GURL("android://hash@foo.com/");
- preferred_match.username_value = ASCIIToUTF16(kPreferredUsername);
- preferred_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ preferred_match.username_value = kPreferredUsername;
+ preferred_match.password_value = kPreferredPassword;
preferred_match.signon_realm = "android://hash@foo.com/";
preferred_match.is_affiliation_based_match = true;
@@ -609,7 +606,7 @@ TEST(PasswordFormFillDataTest, TestAffiliationMatch) {
exact_match.username_element = u"username";
exact_match.username_value = u"test1@gmail.com";
exact_match.password_element = u"password";
- exact_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ exact_match.password_value = kPreferredPassword;
exact_match.submit_element = u"";
exact_match.signon_realm = "https://foo.com/";
exact_match.scheme = PasswordForm::Scheme::kHtml;
@@ -619,7 +616,7 @@ TEST(PasswordFormFillDataTest, TestAffiliationMatch) {
PasswordForm affiliated_match;
affiliated_match.url = GURL("android://hash@foo1.com/");
affiliated_match.username_value = u"test2@gmail.com";
- affiliated_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ affiliated_match.password_value = kPreferredPassword;
affiliated_match.is_affiliation_based_match = true;
affiliated_match.signon_realm = "https://foo1.com/";
affiliated_match.scheme = PasswordForm::Scheme::kHtml;
@@ -660,8 +657,8 @@ TEST(PasswordFormFillDataTest, RendererIDs) {
// Create an exact match in the database.
PasswordForm preferred_match = form_on_page;
- preferred_match.username_value = ASCIIToUTF16(kPreferredUsername);
- preferred_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ preferred_match.username_value = kPreferredUsername;
+ preferred_match.password_value = kPreferredPassword;
// Set renderer id related fields.
FormData form_data;
@@ -699,8 +696,8 @@ TEST(PasswordFormFillDataTest, NoPasswordElement) {
// Create an exact match in the database.
PasswordForm preferred_match = form_on_page;
- preferred_match.username_value = ASCIIToUTF16(kPreferredUsername);
- preferred_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ preferred_match.username_value = kPreferredUsername;
+ preferred_match.password_value = kPreferredPassword;
FormData form_data;
form_data.unique_renderer_id = FormRendererId(42);
@@ -724,8 +721,8 @@ TEST(PasswordFormFillDataTest, DeduplicatesFillData) {
// Create an exact match in the database.
PasswordForm preferred_match = form;
- preferred_match.username_value = ASCIIToUTF16(kPreferredUsername);
- preferred_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ preferred_match.username_value = kPreferredUsername;
+ preferred_match.password_value = kPreferredPassword;
preferred_match.in_store = Store::kProfileStore;
// Create two discarded and one retained duplicate.
@@ -774,9 +771,9 @@ TEST(PasswordFormFillDataTest, TestAffiliationWithAppName) {
form_on_page.url = GURL("https://foo.com/");
form_on_page.action = GURL("https://foo.com/login");
form_on_page.username_element = u"username";
- form_on_page.username_value = ASCIIToUTF16(kPreferredUsername);
+ form_on_page.username_value = kPreferredUsername;
form_on_page.password_element = u"password";
- form_on_page.password_value = ASCIIToUTF16(kPreferredPassword);
+ form_on_page.password_value = kPreferredPassword;
form_on_page.signon_realm = "https://foo.com/";
form_on_page.scheme = PasswordForm::Scheme::kHtml;
@@ -785,7 +782,7 @@ TEST(PasswordFormFillDataTest, TestAffiliationWithAppName) {
PasswordForm affiliated_match;
affiliated_match.url = GURL("android://hash@foo1.com/");
affiliated_match.username_value = u"test2@gmail.com";
- affiliated_match.password_value = ASCIIToUTF16(kPreferredPassword);
+ affiliated_match.password_value = kPreferredPassword;
affiliated_match.is_affiliation_based_match = true;
affiliated_match.app_display_name = "Foo";
affiliated_match.signon_realm = "https://foo1.com/";
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 0bdf8620d0a..662061df8d1 100644
--- a/chromium/components/password_manager/core/browser/password_form_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_form_manager.cc
@@ -114,7 +114,7 @@ bool IsUsernameFirstFlowFeatureEnabled() {
// Find a field in |predictions| with given renderer id.
const PasswordFieldPrediction* FindFieldPrediction(
- const base::Optional<FormPredictions>& predictions,
+ const absl::optional<FormPredictions>& predictions,
autofill::FieldRendererId field_renderer_id) {
if (!predictions)
return nullptr;
@@ -697,6 +697,7 @@ bool PasswordFormManager::ProvisionallySave(
const PasswordManagerDriver* driver,
const PossibleUsernameData* possible_username) {
DCHECK(DoesManage(submitted_form.unique_renderer_id, driver));
+ DCHECK(client_->IsSavingAndFillingEnabled(submitted_form.url));
std::unique_ptr<PasswordForm> parsed_submitted_form =
ParseFormAndMakeLogging(submitted_form, FormDataParser::Mode::kSaving);
RecordMetricOnReadonly(parser_.readonly_status(), !!parsed_submitted_form,
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 514bb573332..7cb533c4310 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
@@ -71,7 +71,6 @@ using autofill::ServerFieldTypeSet;
using autofill::SINGLE_USERNAME;
using autofill::UNKNOWN_TYPE;
using autofill::password_generation::PasswordGenerationType;
-using base::ASCIIToUTF16;
using testing::_;
using testing::AllOf;
using testing::Contains;
@@ -182,9 +181,9 @@ void CheckPendingCredentials(const PasswordForm& expected,
}
struct ExpectedGenerationUKM {
- base::Optional<int64_t> generation_popup_shown;
+ absl::optional<int64_t> generation_popup_shown;
int64_t has_generated_password;
- base::Optional<int64_t> generated_password_modified;
+ absl::optional<int64_t> generated_password_modified;
};
// Check that UKM |metric_name| in |entry| is equal to |expected|. |expected| ==
@@ -1458,7 +1457,7 @@ TEST_P(PasswordFormManagerTest, PresaveGeneratedPasswordEmptyStore) {
form_data.fields[kPasswordFieldIndex].value =
form_with_generated_password.password_value;
EXPECT_CALL(form_saver,
- UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
+ UpdateReplace(_, IsEmpty(), testing::Eq(u""),
FormHasUniqueKey(form_with_generated_password)))
.WillOnce(SaveArg<0>(&saved_form));
@@ -1477,9 +1476,9 @@ TEST_P(PasswordFormManagerTest, PresaveGeneratedPasswordEmptyStore) {
// Check UKM metrics.
form_manager_.reset();
ExpectedGenerationUKM expected_metrics = {
- base::make_optional(1u) /* shown automatically */,
+ absl::make_optional(1u) /* shown automatically */,
1 /* password generated */,
- base::make_optional(1u) /* password modified */};
+ absl::make_optional(1u) /* password modified */};
CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
}
@@ -1507,7 +1506,7 @@ TEST_P(PasswordFormManagerTest, PresaveGenerated_ModifiedUsername) {
form_data.fields[kUsernameFieldIndex].value =
form_with_generated_password.username_value;
- EXPECT_CALL(form_saver, UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
+ EXPECT_CALL(form_saver, UpdateReplace(_, IsEmpty(), testing::Eq(u""),
FormHasUniqueKey(saved_form)))
.WillOnce(SaveArg<0>(&saved_form));
form_manager_->PresaveGeneratedPassword(
@@ -1523,9 +1522,9 @@ TEST_P(PasswordFormManagerTest, PresaveGenerated_ModifiedUsername) {
// Check UKM metrics.
form_manager_.reset();
ExpectedGenerationUKM expected_metrics = {
- base::make_optional(1u) /* shown automatically */,
+ absl::make_optional(1u) /* shown automatically */,
1 /* password generated */,
- base::make_optional(0u) /* password modified */};
+ absl::make_optional(0u) /* password modified */};
CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
}
@@ -1555,7 +1554,7 @@ TEST_P(PasswordFormManagerTest, GeneratedPasswordWhichIsNotInFormData) {
EXPECT_TRUE(form_manager_->HasGeneratedPassword());
// Check that the generated password is saved.
- EXPECT_CALL(form_saver, UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
+ EXPECT_CALL(form_saver, UpdateReplace(_, IsEmpty(), testing::Eq(u""),
FormHasUniqueKey(saved_form)))
.WillOnce(SaveArg<0>(&saved_form));
EXPECT_CALL(client_, UpdateFormManagers());
@@ -1614,7 +1613,7 @@ TEST_P(PasswordFormManagerTest, PasswordNoLongerGenerated) {
// Check UKM metrics.
form_manager_.reset();
ExpectedGenerationUKM expected_metrics = {
- base::make_optional(2u) /* shown manually */,
+ absl::make_optional(2u) /* shown manually */,
0 /* password generated */,
{} /* generated password is not modified */};
@@ -2805,7 +2804,7 @@ TEST_F(PasswordFormManagerTestWithMockedSaver, PasswordNoLongerGenerated) {
// Check UKM metrics.
form_manager_.reset();
ExpectedGenerationUKM expected_metrics = {
- base::make_optional(2u) /* shown manually */,
+ absl::make_optional(2u) /* shown manually */,
0 /* password generated */,
{} /* generated password is not modified */};
CheckPasswordGenerationUKM(test_ukm_recorder, expected_metrics);
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 ec19271c0d8..93bd0415462 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
@@ -73,7 +73,7 @@ PasswordFormMetricsRecorder::BubbleDismissalReason GetBubbleDismissalReason(
}
bool HasGeneratedPassword(
- base::Optional<PasswordFormMetricsRecorder::GeneratedPasswordStatus>
+ absl::optional<PasswordFormMetricsRecorder::GeneratedPasswordStatus>
status) {
return status.has_value() &&
(status == PasswordFormMetricsRecorder::GeneratedPasswordStatus::
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 5261183f03a..87a820dc6fd 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
@@ -14,7 +14,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/time/clock.h"
#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/signatures.h"
@@ -22,6 +21,7 @@
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
class PrefService;
@@ -439,7 +439,7 @@ class PasswordFormMetricsRecorder
// Contains the generated password's status, which resulted from a user
// action.
- base::Optional<GeneratedPasswordStatus> generated_password_status_;
+ absl::optional<GeneratedPasswordStatus> generated_password_status_;
// Tracks which bubble is currently being displayed to the user.
CurrentBubbleOfInterest current_bubble_ = CurrentBubbleOfInterest::kNone;
@@ -482,9 +482,9 @@ class PasswordFormMetricsRecorder
// 1 = the fallback was shown.
// 2 = the password was generated.
// 4 = this was an update prompt.
- base::Optional<uint32_t> showed_manual_fallback_for_saving_;
+ absl::optional<uint32_t> showed_manual_fallback_for_saving_;
- base::Optional<uint32_t> form_changes_bitmask_;
+ absl::optional<uint32_t> form_changes_bitmask_;
bool recorded_first_filling_result_ = false;
@@ -493,15 +493,15 @@ class PasswordFormMetricsRecorder
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_;
- base::Optional<FillingSource> filling_source_;
- base::Optional<metrics_util::PasswordAccountStorageUsageLevel>
+ absl::optional<FillingAssistance> filling_assistance_;
+ absl::optional<FillingSource> filling_source_;
+ absl::optional<metrics_util::PasswordAccountStorageUsageLevel>
account_storage_usage_level_;
bool possible_username_used_ = false;
bool username_updated_in_bubble_ = false;
- base::Optional<JsOnlyInput> js_only_input_;
+ absl::optional<JsOnlyInput> js_only_input_;
bool is_mixed_content_form_ = false;
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 ae8a1b5a06e..53133cf8ae3 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
@@ -630,7 +630,7 @@ struct FillingAssistanceTestCase {
std::vector<std::string> saved_passwords;
std::vector<InteractionsStats> interactions_stats;
- base::Optional<PasswordFormMetricsRecorder::FillingAssistance> expectation;
+ absl::optional<PasswordFormMetricsRecorder::FillingAssistance> expectation;
};
FormData ConvertToFormData(const std::vector<TestCaseFieldInfo>& fields) {
@@ -1125,7 +1125,7 @@ struct FillingSourceTestCase {
std::vector<std::string> saved_account_usernames;
std::vector<std::string> saved_account_passwords;
- base::Optional<PasswordFormMetricsRecorder::FillingSource> expectation;
+ absl::optional<PasswordFormMetricsRecorder::FillingSource> expectation;
};
void CheckFillingSourceTestCase(const FillingSourceTestCase& test_case) {
diff --git a/chromium/components/password_manager/core/browser/password_generation_frame_helper.cc b/chromium/components/password_manager/core/browser/password_generation_frame_helper.cc
index 0960b65ff60..6845605e0e8 100644
--- a/chromium/components/password_manager/core/browser/password_generation_frame_helper.cc
+++ b/chromium/components/password_manager/core/browser/password_generation_frame_helper.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/optional.h"
#include "base/strings/string_util.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_structure.h"
@@ -20,6 +19,7 @@
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/browser/password_requirements_service.h"
#include "components/password_manager/core/common/password_manager_features.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using autofill::FieldSignature;
using autofill::FormSignature;
diff --git a/chromium/components/password_manager/core/browser/password_generation_manager.cc b/chromium/components/password_manager/core/browser/password_generation_manager.cc
index ed55a845a99..a765776bad4 100644
--- a/chromium/components/password_manager/core/browser/password_generation_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_generation_manager.cc
@@ -279,7 +279,9 @@ void PasswordGenerationManager::OnPresaveBubbleResult(
bool accepted,
const PasswordForm& pending) {
weak_factory_.InvalidateWeakPtrs();
- if (accepted) {
+ if (driver && accepted) {
+ // See https://crbug.com/1210341 for when `driver` might be null due to a
+ // compromised renderer.
driver->GeneratedPasswordAccepted(pending.password_value);
}
}
diff --git a/chromium/components/password_manager/core/browser/password_generation_manager.h b/chromium/components/password_manager/core/browser/password_generation_manager.h
index 1be4f2adbb5..6681cd6eb3b 100644
--- a/chromium/components/password_manager/core/browser/password_generation_manager.h
+++ b/chromium/components/password_manager/core/browser/password_generation_manager.h
@@ -9,9 +9,9 @@
#include <memory>
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/clock.h"
#include "components/password_manager/core/browser/password_form.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
@@ -82,7 +82,7 @@ class PasswordGenerationManager {
// The client for the password form.
PasswordManagerClient* const client_;
// Stores the pre-saved credential.
- base::Optional<PasswordForm> presaved_;
+ absl::optional<PasswordForm> presaved_;
// Interface to get current time.
std::unique_ptr<base::Clock> clock_;
// Used to produce callbacks.
diff --git a/chromium/components/password_manager/core/browser/password_manager.cc b/chromium/components/password_manager/core/browser/password_manager.cc
index 8828f86148c..a2ba8e1c0ad 100644
--- a/chromium/components/password_manager/core/browser/password_manager.cc
+++ b/chromium/components/password_manager/core/browser/password_manager.cc
@@ -192,6 +192,15 @@ FormData SimplifiedFormDataFromFormStructure(
return form_data;
}
+bool HasMutedCredentials(base::span<const InsecureCredential> credentials,
+ const std::u16string& username) {
+ return base::ranges::any_of(credentials, [&username](const auto& credential) {
+ return credential.username == username && credential.is_muted &&
+ (credential.insecure_type == InsecureType::kLeaked ||
+ credential.insecure_type == InsecureType::kPhished);
+ });
+}
+
} // namespace
// static
@@ -642,8 +651,7 @@ PasswordFormManager* PasswordManager::ProvisionallySaveForm(
}
if (!client_->IsSavingAndFillingEnabled(submitted_form.url)) {
RecordProvisionalSaveFailure(
- PasswordManagerMetricsRecorder::SAVING_DISABLED, submitted_form.url,
- logger.get());
+ PasswordManagerMetricsRecorder::SAVING_DISABLED, submitted_form.url);
return nullptr;
}
@@ -654,7 +662,7 @@ PasswordFormManager* PasswordManager::ProvisionallySaveForm(
if (ShouldBlockPasswordForSameOriginButDifferentScheme(submitted_url)) {
RecordProvisionalSaveFailure(
PasswordManagerMetricsRecorder::SAVING_ON_HTTP_AFTER_HTTPS,
- submitted_url, logger.get());
+ submitted_url);
return nullptr;
}
@@ -671,8 +679,7 @@ PasswordFormManager* PasswordManager::ProvisionallySaveForm(
if (!matched_manager) {
RecordProvisionalSaveFailure(
- PasswordManagerMetricsRecorder::NO_MATCHING_FORM, submitted_form.url,
- logger.get());
+ PasswordManagerMetricsRecorder::NO_MATCHING_FORM, submitted_form.url);
matched_manager = CreateFormManager(driver, submitted_form);
}
@@ -802,6 +809,11 @@ void PasswordManager::PropagateFieldDataManagerInfo(
const FieldDataManager& field_data_manager,
const PasswordManagerDriver* driver) {
for (auto& manager : form_managers_) {
+ if (!client_->IsSavingAndFillingEnabled(manager->GetURL())) {
+ RecordProvisionalSaveFailure(
+ PasswordManagerMetricsRecorder::SAVING_DISABLED, manager->GetURL());
+ continue;
+ }
manager->ProvisionallySaveFieldDataManagerInfo(field_data_manager, driver);
}
}
@@ -830,7 +842,7 @@ bool PasswordManager::IsAutomaticSavePromptAvailable() {
// We just give up.
RecordProvisionalSaveFailure(
PasswordManagerMetricsRecorder::MATCHING_NOT_COMPLETE,
- submitted_manager->GetURL(), logger.get());
+ submitted_manager->GetURL());
return false;
}
@@ -947,10 +959,19 @@ void PasswordManager::OnLoginSuccessful() {
PasswordFormManager* submitted_manager = GetSubmittedManager();
DCHECK(submitted_manager);
- DCHECK(submitted_manager->GetSubmittedForm());
+ const PasswordForm* submitted_form = submitted_manager->GetSubmittedForm();
+ DCHECK(submitted_form);
+ if (!client_->IsSavingAndFillingEnabled(submitted_form->url))
+ return;
client_->GetStoreResultFilter()->ReportFormLoginSuccess(*submitted_manager);
- leak_delegate_.StartLeakCheck(submitted_manager->GetPendingCredentials());
+ // Check for leaks only if there are no muted credentials.
+ if (!HasMutedCredentials(
+ submitted_manager->GetInsecureCredentials(),
+ submitted_manager->GetSubmittedForm()->username_value) ||
+ !base::FeatureList::IsEnabled(features::kMutingCompromisedCredentials)) {
+ leak_delegate_.StartLeakCheck(submitted_manager->GetPendingCredentials());
+ }
auto submission_event =
submitted_manager->GetSubmittedForm()->submission_event;
@@ -978,7 +999,7 @@ void PasswordManager::OnLoginSuccessful() {
*submitted_manager->GetSubmittedForm())) {
RecordProvisionalSaveFailure(
PasswordManagerMetricsRecorder::SYNC_CREDENTIAL,
- submitted_manager->GetURL(), logger.get());
+ submitted_manager->GetURL());
ResetSubmittedManager();
return;
}
@@ -1176,11 +1197,15 @@ PasswordManager::MoveOwnedSubmittedManager() {
void PasswordManager::RecordProvisionalSaveFailure(
PasswordManagerMetricsRecorder::ProvisionalSaveFailure failure,
- const GURL& form_origin,
- BrowserSavePasswordProgressLogger* logger) {
+ const GURL& form_origin) {
+ std::unique_ptr<BrowserSavePasswordProgressLogger> logger;
+ if (password_manager_util::IsLoggingActive(client_)) {
+ logger = std::make_unique<BrowserSavePasswordProgressLogger>(
+ client_->GetLogManager());
+ }
if (client_ && client_->GetMetricsRecorder()) {
client_->GetMetricsRecorder()->RecordProvisionalSaveFailure(
- failure, submitted_form_url_, form_origin, logger);
+ failure, submitted_form_url_, form_origin, logger.get());
}
}
@@ -1300,6 +1325,14 @@ bool PasswordManager::DetectPotentialSubmission(
PasswordFormManager* form_manager,
const FieldDataManager& field_data_manager,
PasswordManagerDriver* driver) {
+ // Do not attempt to detect submission if saving is disabled.
+ if (!client_->IsSavingAndFillingEnabled(form_manager->GetURL())) {
+ RecordProvisionalSaveFailure(
+ PasswordManagerMetricsRecorder::SAVING_DISABLED,
+ form_manager->GetURL());
+ return false;
+ }
+
// If the manager is not submitted, it still can have autofilled data.
if (!form_manager->is_submitted()) {
form_manager->ProvisionallySaveFieldDataManagerInfo(field_data_manager,
diff --git a/chromium/components/password_manager/core/browser/password_manager.h b/chromium/components/password_manager/core/browser/password_manager.h
index fc7f252efd3..87b67a476c9 100644
--- a/chromium/components/password_manager/core/browser/password_manager.h
+++ b/chromium/components/password_manager/core/browser/password_manager.h
@@ -45,7 +45,6 @@ class FormStructure;
namespace password_manager {
-class BrowserSavePasswordProgressLogger;
class PasswordManagerClient;
class PasswordManagerDriver;
class PasswordFormManagerForUI;
@@ -290,8 +289,7 @@ class PasswordManager : public PasswordManagerInterface {
// |main_frame_url_|.
void RecordProvisionalSaveFailure(
PasswordManagerMetricsRecorder::ProvisionalSaveFailure failure,
- const GURL& form_origin,
- BrowserSavePasswordProgressLogger* logger);
+ const GURL& form_origin);
// Returns the manager which manages |form_id|. |driver| is needed to
// determine the match. Returns nullptr when no matched manager is found.
@@ -375,7 +373,7 @@ class PasswordManager : public PasswordManagerInterface {
// Helper for making the requests on leak detection.
LeakDetectionDelegate leak_delegate_;
- base::Optional<PossibleUsernameData> possible_username_;
+ absl::optional<PossibleUsernameData> possible_username_;
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 dc07e71dbcd..c9dd25093f1 100644
--- a/chromium/components/password_manager/core/browser/password_manager_client.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_client.cc
@@ -6,6 +6,7 @@
#include "base/macros.h"
#include "components/autofill/core/common/password_generation_util.h"
+#include "components/password_manager/core/browser/biometric_authenticator.h"
#include "components/password_manager/core/browser/http_auth_manager.h"
#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
#include "components/password_manager/core/browser/password_manager_client.h"
@@ -34,7 +35,8 @@ void PasswordManagerClient::ShowTouchToFill(PasswordManagerDriver* driver) {}
void PasswordManagerClient::OnPasswordSelected(const std::u16string& text) {}
-BiometricAuthenticator* PasswordManagerClient::GetBiometricAuthenticator() {
+scoped_refptr<BiometricAuthenticator>
+PasswordManagerClient::GetBiometricAuthenticator() {
return nullptr;
}
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 7b2fa604646..e5d0849d472 100644
--- a/chromium/components/password_manager/core/browser/password_manager_client.h
+++ b/chromium/components/password_manager/core/browser/password_manager_client.h
@@ -182,7 +182,7 @@ class PasswordManagerClient {
// Returns a pointer to a BiometricAuthenticator. Might be null if
// BiometricAuthentication is not available for a given platform.
- virtual BiometricAuthenticator* GetBiometricAuthenticator();
+ virtual scoped_refptr<BiometricAuthenticator> GetBiometricAuthenticator();
// Informs the embedder that the user has requested to generate a
// password in the focused password field.
diff --git a/chromium/components/password_manager/core/browser/password_manager_driver.h b/chromium/components/password_manager/core/browser/password_manager_driver.h
index 3351d9f7fe0..82193dd4b6b 100644
--- a/chromium/components/password_manager/core/browser/password_manager_driver.h
+++ b/chromium/components/password_manager/core/browser/password_manager_driver.h
@@ -13,11 +13,14 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/types/strong_alias.h"
-#include "components/autofill/core/common/mojom/autofill_types.mojom.h"
#include "components/autofill/core/common/unique_ids.h"
+class GURL;
+
namespace autofill {
class AutofillDriver;
+struct FormData;
+struct ParsingResult;
struct PasswordFormGenerationData;
struct PasswordFormFillData;
} // namespace autofill
diff --git a/chromium/components/password_manager/core/browser/password_manager_features_util.cc b/chromium/components/password_manager/core/browser/password_manager_features_util.cc
index 7d436e5f189..abb0bb97cc5 100644
--- a/chromium/components/password_manager/core/browser/password_manager_features_util.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_features_util.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/containers/flat_set.h"
+#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/ranges/algorithm.h"
#include "base/values.h"
@@ -61,7 +62,7 @@ bool CanAccountStorageBeEnabled(const syncer::SyncService* sync_service) {
bool IsUserEligibleForAccountStorage(const syncer::SyncService* sync_service) {
return CanAccountStorageBeEnabled(sync_service) &&
sync_service->IsEngineInitialized() &&
- !sync_service->GetUserSettings()->IsUsingSecondaryPassphrase() &&
+ !sync_service->GetUserSettings()->IsUsingExplicitPassphrase() &&
!sync_service->IsSyncFeatureEnabled();
}
@@ -86,9 +87,8 @@ int GetNumberOfOptedInAccounts(const PrefService* pref_service) {
const base::DictionaryValue* global_pref =
pref_service->GetDictionary(prefs::kAccountStoragePerAccountSettings);
int count = 0;
- for (const std::pair<std::string, std::unique_ptr<base::Value>>& entry :
- *global_pref) {
- if (entry.second->FindBoolKey(kAccountStorageOptedInKey).value_or(false))
+ for (const auto& entry : global_pref->DictItems()) {
+ if (entry.second.FindBoolKey(kAccountStorageOptedInKey).value_or(false))
++count;
}
return count;
@@ -115,7 +115,7 @@ class AccountStorageSettingsReader {
PasswordForm::Store GetDefaultStore() const {
if (!account_settings_)
return PasswordForm::Store::kNotSet;
- base::Optional<int> value =
+ absl::optional<int> value =
account_settings_->FindIntKey(kAccountStorageDefaultStoreKey);
if (!value)
return PasswordForm::Store::kNotSet;
@@ -231,9 +231,10 @@ bool ShouldShowAccountStorageReSignin(const PrefService* pref_service,
// Show the opt-in if any known previous user opted into using the account
// storage before and might want to access it again.
return base::ranges::any_of(
- *pref_service->GetDictionary(prefs::kAccountStoragePerAccountSettings),
- [](const std::pair<std::string, std::unique_ptr<base::Value>>& p) {
- return p.second->FindBoolKey(kAccountStorageOptedInKey).value_or(false);
+ pref_service->GetDictionary(prefs::kAccountStoragePerAccountSettings)
+ ->DictItems(),
+ [](const std::pair<std::string, const base::Value&>& p) {
+ return p.second.FindBoolKey(kAccountStorageOptedInKey).value_or(false);
});
}
diff --git a/chromium/components/password_manager/core/browser/password_manager_interface.h b/chromium/components/password_manager/core/browser/password_manager_interface.h
index e600d87b460..f4ab7dbce7f 100644
--- a/chromium/components/password_manager/core/browser/password_manager_interface.h
+++ b/chromium/components/password_manager/core/browser/password_manager_interface.h
@@ -12,6 +12,7 @@
#include "build/build_config.h"
#include "components/autofill/core/common/field_data_manager.h"
#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/password_generation_util.h"
#include "components/autofill/core/common/unique_ids.h"
#include "components/password_manager/core/browser/form_submission_observer.h"
#include "components/password_manager/core/browser/password_manager_driver.h"
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 9fc6674d33f..a047b942ab1 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
@@ -60,7 +60,7 @@ void LogGeneralUIDismissalReason(UIDismissalReason reason) {
void LogSaveUIDismissalReason(
UIDismissalReason reason,
- base::Optional<PasswordAccountStorageUserState> user_state) {
+ absl::optional<PasswordAccountStorageUserState> user_state) {
base::UmaHistogramEnumeration("PasswordManager.SaveUIDismissalReason", reason,
NUM_UI_RESPONSES);
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 f4a5fbab59f..6400796d3a7 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
@@ -520,7 +520,7 @@ void LogGeneralUIDismissalReason(UIDismissalReason reason);
// user-state-specific histogram.
void LogSaveUIDismissalReason(
UIDismissalReason reason,
- base::Optional<PasswordAccountStorageUserState> user_state);
+ absl::optional<PasswordAccountStorageUserState> user_state);
// Log the |reason| a user dismissed the save password prompt after previously
// having unblocklisted the origin while on the page.
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 40b6938f374..de18ce6002f 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
@@ -127,16 +127,16 @@ MockPasswordReuseDetectorConsumer::~MockPasswordReuseDetectorConsumer() =
default;
PasswordHashDataMatcher::PasswordHashDataMatcher(
- base::Optional<PasswordHashData> expected)
+ absl::optional<PasswordHashData> expected)
: expected_(expected) {}
bool PasswordHashDataMatcher::MatchAndExplain(
- base::Optional<PasswordHashData> hash_data,
+ absl::optional<PasswordHashData> hash_data,
::testing::MatchResultListener* listener) const {
- if (expected_ == base::nullopt)
- return hash_data == base::nullopt;
+ if (expected_ == absl::nullopt)
+ return hash_data == absl::nullopt;
- if (hash_data == base::nullopt)
+ if (hash_data == absl::nullopt)
return false;
return expected_->username == hash_data->username &&
@@ -152,8 +152,8 @@ void PasswordHashDataMatcher::DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't match password hash data for " << expected_->username;
}
-::testing::Matcher<base::Optional<PasswordHashData>> Matches(
- base::Optional<PasswordHashData> expected) {
+::testing::Matcher<absl::optional<PasswordHashData>> Matches(
+ absl::optional<PasswordHashData> expected) {
return ::testing::MakeMatcher(new PasswordHashDataMatcher(expected));
}
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 72c88400b84..fac2c5f380a 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
@@ -115,32 +115,32 @@ class MockPasswordReuseDetectorConsumer : public PasswordReuseDetectorConsumer {
MOCK_METHOD5(OnReuseCheckDone,
void(bool,
size_t,
- base::Optional<PasswordHashData>,
+ absl::optional<PasswordHashData>,
const std::vector<MatchingReusedCredential>&,
int));
};
// Matcher class used to compare PasswordHashData in tests.
class PasswordHashDataMatcher
- : public ::testing::MatcherInterface<base::Optional<PasswordHashData>> {
+ : public ::testing::MatcherInterface<absl::optional<PasswordHashData>> {
public:
- explicit PasswordHashDataMatcher(base::Optional<PasswordHashData> expected);
+ explicit PasswordHashDataMatcher(absl::optional<PasswordHashData> expected);
~PasswordHashDataMatcher() override = default;
// ::testing::MatcherInterface overrides
- bool MatchAndExplain(base::Optional<PasswordHashData> hash_data,
+ bool MatchAndExplain(absl::optional<PasswordHashData> hash_data,
::testing::MatchResultListener* listener) const override;
void DescribeTo(::std::ostream* os) const override;
void DescribeNegationTo(::std::ostream* os) const override;
private:
- const base::Optional<PasswordHashData> expected_;
+ const absl::optional<PasswordHashData> expected_;
DISALLOW_COPY_AND_ASSIGN(PasswordHashDataMatcher);
};
-::testing::Matcher<base::Optional<PasswordHashData>> Matches(
- base::Optional<PasswordHashData> expected);
+::testing::Matcher<absl::optional<PasswordHashData>> Matches(
+ absl::optional<PasswordHashData> expected);
} // namespace password_manager
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 2e9e73f6b10..e3f3feebf5a 100644
--- a/chromium/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_unittest.cc
@@ -12,7 +12,6 @@
#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"
@@ -59,6 +58,7 @@
#include "services/network/test/test_network_context.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using autofill::FieldRendererId;
using autofill::FormData;
@@ -3071,8 +3071,8 @@ namespace {
// A convenience helper for type conversions.
template <typename T>
-base::Optional<int64_t> MetricValue(T value) {
- return base::Optional<int64_t>(static_cast<int64_t>(value));
+absl::optional<int64_t> MetricValue(T value) {
+ return absl::optional<int64_t>(static_cast<int64_t>(value));
}
struct MissingFormManagerTestCase {
@@ -3087,8 +3087,8 @@ struct MissingFormManagerTestCase {
// A list of forms to be processed for saving, one at a time.
std::vector<FormData> processed_form_data;
// The expected value of the PageWithPassword::kFormManagerAvailableName
- // metric, or base::nullopt if no value should be logged.
- base::Optional<int64_t> expected_metric_value;
+ // metric, or absl::nullopt if no value should be logged.
+ absl::optional<int64_t> expected_metric_value;
};
} // namespace
@@ -3157,7 +3157,7 @@ TEST_P(PasswordManagerTest, ReportMissingFormManager) {
.save_signal = MissingFormManagerTestCase::Signal::None,
.parsed_forms_data = {},
.processed_form_data = {},
- .expected_metric_value = base::nullopt,
+ .expected_metric_value = absl::nullopt,
},
{
.description = "Not enabled, no report.",
@@ -3165,7 +3165,7 @@ TEST_P(PasswordManagerTest, ReportMissingFormManager) {
.save_signal = MissingFormManagerTestCase::Signal::Automatic,
.parsed_forms_data = {form_data},
.processed_form_data = {form_data},
- .expected_metric_value = base::nullopt,
+ .expected_metric_value = absl::nullopt,
},
};
@@ -3558,6 +3558,7 @@ TEST_P(PasswordManagerTest, FormSubmittedOnMainFrame) {
// Simulate finish loading of some iframe. Check that the prompt is shown.
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_));
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled).WillRepeatedly(Return(true));
manager()->OnPasswordFormsRendered(&driver_, {} /* observed */,
true /* did stop loading */);
}
@@ -3588,6 +3589,7 @@ TEST_P(PasswordManagerTest, FormSubmittedOnIFrame) {
// Simulate finish loading of the submitted form iframe. Check that the prompt
// is shown.
EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_));
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled).WillRepeatedly(Return(true));
manager()->OnPasswordFormsRendered(&iframe_driver, {} /* observed */,
true /* did stop loading */);
}
@@ -4088,6 +4090,85 @@ TEST_P(PasswordManagerTest, SubmittedManagerClearingOnSuccessfulLogin) {
EXPECT_FALSE(manager()->GetSubmittedManagerForTest());
}
+// Check that on successful login the credentials are checked for leak depending
+// on mute state of insecure credential.
+TEST_P(PasswordManagerTest, DontStartLeakDetectionWhenMuted) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(features::kMutingCompromisedCredentials,
+ true);
+
+ auto mock_factory =
+ std::make_unique<testing::StrictMock<MockLeakDetectionCheckFactory>>();
+ manager()->set_leak_factory(std::move(mock_factory));
+
+ const PasswordForm form = MakeSimpleForm();
+ std::vector<FormData> observed = {form.form_data};
+ EXPECT_CALL(*store_, GetLogins)
+ .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms(store_.get())));
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
+
+ // Add muted insecure credentials.
+ std::vector<InsecureCredential> insecure_credentials = {InsecureCredential(
+ form.signon_realm, form.username_value, base::Time::FromTimeT(1),
+ InsecureType::kLeaked, IsMuted(true))};
+ EXPECT_CALL(*store_, GetMatchingInsecureCredentialsImpl(form.signon_realm))
+ .WillOnce(Return(insecure_credentials));
+ task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled).WillRepeatedly(Return(true));
+ OnPasswordFormSubmitted(form.form_data);
+
+ auto check_instance = std::make_unique<MockLeakDetectionCheck>();
+ EXPECT_CALL(*check_instance, Start).Times(0);
+
+ // Now the password manager waits for the navigation to complete.
+ observed.clear();
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
+}
+
+// Tests that check for leaks happens even if there are muted credentials for
+// the same domain, but with different username.
+TEST_P(PasswordManagerTest, StartLeakCheckWhenForUsernameNotMuted) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(features::kMutingCompromisedCredentials,
+ true);
+
+ auto mock_factory =
+ std::make_unique<testing::StrictMock<MockLeakDetectionCheckFactory>>();
+ MockLeakDetectionCheckFactory* weak_factory = mock_factory.get();
+ manager()->set_leak_factory(std::move(mock_factory));
+
+ const PasswordForm form = MakeSimpleForm();
+ std::vector<FormData> observed = {form.form_data};
+ EXPECT_CALL(*store_, GetLogins)
+ .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms(store_.get())));
+ manager()->OnPasswordFormsParsed(&driver_, observed);
+ manager()->OnPasswordFormsRendered(&driver_, observed, true);
+
+ // Add muted insecure credentials.
+ std::vector<InsecureCredential> insecure_credentials = {InsecureCredential(
+ form.signon_realm, u"different_username", base::Time::FromTimeT(1),
+ InsecureType::kLeaked, IsMuted(true))};
+ EXPECT_CALL(*store_, GetMatchingInsecureCredentialsImpl(form.signon_realm))
+ .WillOnce(Return(insecure_credentials));
+ task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(client_, IsSavingAndFillingEnabled).WillRepeatedly(Return(true));
+ OnPasswordFormSubmitted(form.form_data);
+
+ auto check_instance = std::make_unique<MockLeakDetectionCheck>();
+ EXPECT_CALL(*check_instance, Start);
+ 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);
+}
+
INSTANTIATE_TEST_SUITE_P(, PasswordManagerTest, testing::Bool());
} // 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 e953dc425e4..7ec2d0b5ccf 100644
--- a/chromium/components/password_manager/core/browser/password_manager_util.cc
+++ b/chromium/components/password_manager/core/browser/password_manager_util.cc
@@ -74,7 +74,7 @@ password_manager::SyncState GetPasswordSyncState(
}
if (sync_service->IsSyncFeatureActive()) {
- return sync_service->GetUserSettings()->IsUsingSecondaryPassphrase()
+ return sync_service->GetUserSettings()->IsUsingExplicitPassphrase()
? password_manager::SyncState::kSyncingWithCustomPassphrase
: password_manager::SyncState::kSyncingNormalEncryption;
}
@@ -87,11 +87,6 @@ password_manager::SyncState GetPasswordSyncState(
return password_manager::SyncState::kAccountPasswordsActiveNormalEncryption;
}
-bool IsSyncingWithNormalEncryption(const syncer::SyncService* sync_service) {
- return GetPasswordSyncState(sync_service) ==
- password_manager::SyncState::kSyncingNormalEncryption;
-}
-
void TrimUsernameOnlyCredentials(
std::vector<std::unique_ptr<PasswordForm>>* android_credentials) {
// Remove username-only credentials which are not federated.
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 f3273708be2..05546a23b4d 100644
--- a/chromium/components/password_manager/core/browser/password_manager_util.h
+++ b/chromium/components/password_manager/core/browser/password_manager_util.h
@@ -44,10 +44,6 @@ void UpdateMetadataForUsage(password_manager::PasswordForm* credential);
password_manager::SyncState GetPasswordSyncState(
const syncer::SyncService* sync_service);
-// Reports whether passwords are synced with normal encryption, i.e. without a
-// custom passphrase.
-bool IsSyncingWithNormalEncryption(const syncer::SyncService* sync_service);
-
// Removes Android username-only credentials from |android_credentials|.
// Transforms federated credentials into non zero-click ones.
void TrimUsernameOnlyCredentials(
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 2ec1002f3f3..3368615cee6 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
@@ -36,9 +36,9 @@ constexpr char kTestFederationURL[] = "https://google.com/";
constexpr char kTestProxyOrigin[] = "http://proxy.com/";
constexpr char kTestProxySignonRealm[] = "proxy.com/realm";
constexpr char kTestURL[] = "https://example.com/login/";
-constexpr char kTestUsername[] = "Username";
-constexpr char kTestUsername2[] = "Username2";
-constexpr char kTestPassword[] = "12345";
+constexpr char16_t kTestUsername[] = u"Username";
+constexpr char16_t kTestUsername2[] = u"Username2";
+constexpr char16_t kTestPassword[] = u"12345";
class MockPasswordManagerClient
: public password_manager::StubPasswordManagerClient {
@@ -60,8 +60,8 @@ PasswordForm GetTestAndroidCredential() {
form.scheme = PasswordForm::Scheme::kHtml;
form.url = GURL(kTestAndroidRealm);
form.signon_realm = kTestAndroidRealm;
- form.username_value = base::ASCIIToUTF16(kTestUsername);
- form.password_value = base::ASCIIToUTF16(kTestPassword);
+ form.username_value = kTestUsername;
+ form.password_value = kTestPassword;
return form;
}
@@ -70,8 +70,8 @@ PasswordForm GetTestCredential() {
form.scheme = PasswordForm::Scheme::kHtml;
form.url = GURL(kTestURL);
form.signon_realm = form.url.GetOrigin().spec();
- form.username_value = base::ASCIIToUTF16(kTestUsername);
- form.password_value = base::ASCIIToUTF16(kTestPassword);
+ form.username_value = kTestUsername;
+ form.password_value = kTestPassword;
return form;
}
@@ -80,8 +80,8 @@ PasswordForm GetTestProxyCredential() {
form.scheme = PasswordForm::Scheme::kBasic;
form.url = GURL(kTestProxyOrigin);
form.signon_realm = kTestProxySignonRealm;
- form.username_value = base::ASCIIToUTF16(kTestUsername);
- form.password_value = base::ASCIIToUTF16(kTestPassword);
+ form.username_value = kTestUsername;
+ form.password_value = kTestPassword;
return form;
}
@@ -102,7 +102,7 @@ TEST(PasswordManagerUtil, TrimUsernameOnlyCredentials) {
PasswordForm username_only;
username_only.scheme = PasswordForm::Scheme::kUsernameOnly;
username_only.signon_realm = kTestAndroidRealm;
- username_only.username_value = base::ASCIIToUTF16(kTestUsername2);
+ username_only.username_value = kTestUsername2;
forms.push_back(std::make_unique<PasswordForm>(username_only));
username_only.federation_origin =
@@ -144,7 +144,7 @@ TEST(PasswordManagerUtil, FindBestMatches) {
struct TestMatch {
bool is_psl_match;
base::Time date_last_used;
- std::string username;
+ std::u16string username;
};
struct TestCase {
const char* description;
@@ -154,39 +154,47 @@ TEST(PasswordManagerUtil, FindBestMatches) {
} test_cases[] = {
{"Empty matches", {}, kNotFound, {}},
{"1 non-psl match",
- {{.is_psl_match = false, .date_last_used = kNow, .username = "u"}},
+ {{.is_psl_match = false, .date_last_used = kNow, .username = u"u"}},
0,
{{"u", 0}}},
{"1 psl match",
- {{.is_psl_match = true, .date_last_used = kNow, .username = "u"}},
+ {{.is_psl_match = true, .date_last_used = kNow, .username = u"u"}},
0,
{{"u", 0}}},
{"2 matches with the same username",
- {{.is_psl_match = false, .date_last_used = kNow, .username = "u"},
- {.is_psl_match = false, .date_last_used = kYesterday, .username = "u"}},
+ {{.is_psl_match = false, .date_last_used = kNow, .username = u"u"},
+ {.is_psl_match = false,
+ .date_last_used = kYesterday,
+ .username = u"u"}},
0,
{{"u", 0}}},
{"2 matches with different usernames, most recently used taken",
- {{.is_psl_match = false, .date_last_used = kNow, .username = "u1"},
+ {{.is_psl_match = false, .date_last_used = kNow, .username = u"u1"},
{.is_psl_match = false,
.date_last_used = kYesterday,
- .username = "u2"}},
+ .username = u"u2"}},
0,
{{"u1", 0}, {"u2", 1}}},
{"2 matches with different usernames, non-psl much taken",
- {{.is_psl_match = false, .date_last_used = kYesterday, .username = "u1"},
- {.is_psl_match = true, .date_last_used = kNow, .username = "u2"}},
+ {{.is_psl_match = false,
+ .date_last_used = kYesterday,
+ .username = u"u1"},
+ {.is_psl_match = true, .date_last_used = kNow, .username = u"u2"}},
0,
{{"u1", 0}, {"u2", 1}}},
{"8 matches, 3 usernames",
- {{.is_psl_match = false, .date_last_used = kYesterday, .username = "u2"},
- {.is_psl_match = true, .date_last_used = kYesterday, .username = "u3"},
- {.is_psl_match = true, .date_last_used = kYesterday, .username = "u1"},
- {.is_psl_match = false, .date_last_used = k2DaysAgo, .username = "u3"},
- {.is_psl_match = true, .date_last_used = kNow, .username = "u1"},
- {.is_psl_match = false, .date_last_used = kNow, .username = "u2"},
- {.is_psl_match = true, .date_last_used = kYesterday, .username = "u3"},
- {.is_psl_match = false, .date_last_used = k2DaysAgo, .username = "u1"}},
+ {{.is_psl_match = false,
+ .date_last_used = kYesterday,
+ .username = u"u2"},
+ {.is_psl_match = true, .date_last_used = kYesterday, .username = u"u3"},
+ {.is_psl_match = true, .date_last_used = kYesterday, .username = u"u1"},
+ {.is_psl_match = false, .date_last_used = k2DaysAgo, .username = u"u3"},
+ {.is_psl_match = true, .date_last_used = kNow, .username = u"u1"},
+ {.is_psl_match = false, .date_last_used = kNow, .username = u"u2"},
+ {.is_psl_match = true, .date_last_used = kYesterday, .username = u"u3"},
+ {.is_psl_match = false,
+ .date_last_used = k2DaysAgo,
+ .username = u"u1"}},
5,
{{"u1", 7}, {"u2", 5}, {"u3", 3}}},
@@ -201,7 +209,7 @@ TEST(PasswordManagerUtil, FindBestMatches) {
PasswordForm form;
form.is_public_suffix_match = match.is_psl_match;
form.date_last_used = match.date_last_used;
- form.username_value = base::ASCIIToUTF16(match.username);
+ form.username_value = match.username;
owning_matches.push_back(form);
}
std::vector<const PasswordForm*> matches;
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 491cdacd13b..5ce0f8ddf4f 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
@@ -101,7 +101,7 @@ void PasswordReuseDetectionManager::OnPaste(const std::u16string text) {
void PasswordReuseDetectionManager::OnReuseCheckDone(
bool is_reuse_found,
size_t password_length,
- base::Optional<PasswordHashData> reused_protected_password_hash,
+ absl::optional<PasswordHashData> reused_protected_password_hash,
const std::vector<MatchingReusedCredential>& matching_reused_credentials,
int saved_passwords) {
// Cache the results.
@@ -183,7 +183,7 @@ void PasswordReuseDetectionManager::SetClockForTesting(base::Clock* clock) {
}
metrics_util::PasswordType PasswordReuseDetectionManager::GetReusedPasswordType(
- base::Optional<PasswordHashData> reused_protected_password_hash,
+ absl::optional<PasswordHashData> reused_protected_password_hash,
size_t matching_domain_count) {
if (!reused_protected_password_hash.has_value()) {
DCHECK_GT(matching_domain_count, 0u);
diff --git a/chromium/components/password_manager/core/browser/password_reuse_detection_manager.h b/chromium/components/password_manager/core/browser/password_reuse_detection_manager.h
index 606b6f922ef..ff0caa23057 100644
--- a/chromium/components/password_manager/core/browser/password_reuse_detection_manager.h
+++ b/chromium/components/password_manager/core/browser/password_reuse_detection_manager.h
@@ -42,7 +42,7 @@ class PasswordReuseDetectionManager : public PasswordReuseDetectorConsumer {
void OnReuseCheckDone(
bool is_reuse_found,
size_t password_length,
- base::Optional<PasswordHashData> reused_protected_password_hash,
+ absl::optional<PasswordHashData> reused_protected_password_hash,
const std::vector<MatchingReusedCredential>& matching_reused_credentials,
int saved_passwords) override;
@@ -52,7 +52,7 @@ class PasswordReuseDetectionManager : public PasswordReuseDetectorConsumer {
void OnKeyPressed(const std::u16string& text, const bool is_committed);
// Determines the type of password being reused.
metrics_util::PasswordType GetReusedPasswordType(
- base::Optional<PasswordHashData> reused_protected_password_hash,
+ absl::optional<PasswordHashData> reused_protected_password_hash,
size_t match_domain_count);
void CheckStoresForReuse(const std::u16string& input);
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 ccd3689e7c9..e0618c2c06e 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
@@ -17,7 +17,6 @@
#include "ui/events/keycodes/keyboard_codes_posix.h"
#include "url/gurl.h"
-using base::ASCIIToUTF16;
using testing::_;
using testing::AnyNumber;
@@ -73,8 +72,7 @@ TEST_F(PasswordReuseDetectionManagerTest, CheckReuseCalled) {
const GURL gurls[] = {GURL("https://www.example.com"),
GURL("https://www.otherexample.com")};
const std::u16string input[] = {
- base::ASCIIToUTF16(
- "1234567890abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ"),
+ u"1234567890abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ",
u"?<>:'{}ABCDEF"};
EXPECT_CALL(client_, GetProfilePasswordStore())
@@ -110,14 +108,14 @@ TEST_F(PasswordReuseDetectionManagerTest,
clock.SetNow(now);
manager.SetClockForTesting(&clock);
- EXPECT_CALL(*store_, CheckReuse(base::ASCIIToUTF16("1"), _, _));
- manager.OnKeyPressedCommitted(base::ASCIIToUTF16("1"));
+ EXPECT_CALL(*store_, CheckReuse(std::u16string(u"1"), _, _));
+ manager.OnKeyPressedCommitted(u"1");
// Simulate 10 seconds of inactivity.
clock.SetNow(now + base::TimeDelta::FromSeconds(10));
// Expect that a keystroke typed before inactivity is cleared.
- EXPECT_CALL(*store_, CheckReuse(base::ASCIIToUTF16("2"), _, _));
- manager.OnKeyPressedCommitted(base::ASCIIToUTF16("2"));
+ EXPECT_CALL(*store_, CheckReuse(std::u16string(u"2"), _, _));
+ manager.OnKeyPressedCommitted(u"2");
}
// Verify that the keystroke buffer is cleared after user presses enter.
@@ -126,16 +124,16 @@ TEST_F(PasswordReuseDetectionManagerTest, CheckThatBufferClearedAfterEnter) {
.WillRepeatedly(testing::Return(store_.get()));
PasswordReuseDetectionManager manager(&client_);
- EXPECT_CALL(*store_, CheckReuse(base::ASCIIToUTF16("1"), _, _));
- manager.OnKeyPressedCommitted(base::ASCIIToUTF16("1"));
+ EXPECT_CALL(*store_, CheckReuse(std::u16string(u"1"), _, _));
+ manager.OnKeyPressedCommitted(u"1");
std::u16string enter_text(1, ui::VKEY_RETURN);
EXPECT_CALL(*store_, CheckReuse(_, _, _)).Times(0);
manager.OnKeyPressedCommitted(enter_text);
// Expect only a keystroke typed after enter.
- EXPECT_CALL(*store_, CheckReuse(base::ASCIIToUTF16("2"), _, _));
- manager.OnKeyPressedCommitted(base::ASCIIToUTF16("2"));
+ EXPECT_CALL(*store_, CheckReuse(std::u16string(u"2"), _, _));
+ manager.OnKeyPressedCommitted(u"2");
}
// Verify that after reuse found, no reuse checking happens till next main frame
@@ -146,7 +144,7 @@ TEST_F(PasswordReuseDetectionManagerTest, NoReuseCheckingAfterReuseFound) {
PasswordReuseDetectionManager manager(&client_);
// Simulate that reuse found.
- manager.OnReuseCheckDone(true, 0ul, base::nullopt, {{"https://example.com"}},
+ manager.OnReuseCheckDone(true, 0ul, absl::nullopt, {{"https://example.com"}},
0);
// Expect no checking of reuse.
@@ -155,8 +153,8 @@ TEST_F(PasswordReuseDetectionManagerTest, NoReuseCheckingAfterReuseFound) {
// Expect that after main frame navigation checking is restored.
manager.DidNavigateMainFrame(GURL("https://www.example.com"));
- EXPECT_CALL(*store_, CheckReuse(base::ASCIIToUTF16("1"), _, _));
- manager.OnKeyPressedCommitted(base::ASCIIToUTF16("1"));
+ EXPECT_CALL(*store_, CheckReuse(std::u16string(u"1"), _, _));
+ manager.OnKeyPressedCommitted(u"1");
}
// Verify that keystroke buffer is cleared only on cross host navigation.
@@ -166,18 +164,18 @@ TEST_F(PasswordReuseDetectionManagerTest, DidNavigateMainFrame) {
PasswordReuseDetectionManager manager(&client_);
manager.DidNavigateMainFrame(GURL("https://www.example1.com/123"));
- EXPECT_CALL(*store_, CheckReuse(base::ASCIIToUTF16("1"), _, _));
- manager.OnKeyPressedCommitted(base::ASCIIToUTF16("1"));
+ EXPECT_CALL(*store_, CheckReuse(std::u16string(u"1"), _, _));
+ manager.OnKeyPressedCommitted(u"1");
// Check that the buffer is not cleared on the same host navigation.
manager.DidNavigateMainFrame(GURL("https://www.example1.com/456"));
- EXPECT_CALL(*store_, CheckReuse(base::ASCIIToUTF16("12"), _, _));
- manager.OnKeyPressedCommitted(base::ASCIIToUTF16("2"));
+ EXPECT_CALL(*store_, CheckReuse(std::u16string(u"12"), _, _));
+ manager.OnKeyPressedCommitted(u"2");
// Check that the buffer is cleared on the cross host navigation.
manager.DidNavigateMainFrame(GURL("https://www.example2.com/123"));
- EXPECT_CALL(*store_, CheckReuse(base::ASCIIToUTF16("3"), _, _));
- manager.OnKeyPressedCommitted(base::ASCIIToUTF16("3"));
+ EXPECT_CALL(*store_, CheckReuse(std::u16string(u"3"), _, _));
+ manager.OnKeyPressedCommitted(u"3");
}
// Verify that CheckReuse is called on a paste event.
@@ -185,8 +183,7 @@ TEST_F(PasswordReuseDetectionManagerTest, CheckReuseCalledOnPaste) {
const GURL gurls[] = {GURL("https://www.example.com"),
GURL("https://www.example.test")};
const std::u16string input[] = {
- base::ASCIIToUTF16(
- "1234567890abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ"),
+ u"1234567890abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ",
u"?<>:'{}ABCDEF"};
EXPECT_CALL(client_, GetProfilePasswordStore())
@@ -234,10 +231,10 @@ TEST_F(PasswordReuseDetectionManagerTest,
CheckProtectedPasswordEntry(_, _, reused_credentials, _));
// Simulate 2 responses from the store with the same reused credentials.
manager.OnReuseCheckDone(/*is_reuse_found=*/true, /*password_length=*/10,
- /*reused_protected_password_hash=*/base::nullopt,
+ /*reused_protected_password_hash=*/absl::nullopt,
reused_credentials, /*saved_passwords=*/1);
manager.OnReuseCheckDone(/*is_reuse_found=*/true, /*password_length=*/10,
- /*reused_protected_password_hash=*/base::nullopt,
+ /*reused_protected_password_hash=*/absl::nullopt,
reused_credentials, /*saved_passwords=*/1);
}
@@ -312,7 +309,7 @@ TEST_F(PasswordReuseDetectionManagerWithTwoStoresTest,
.in_store = PasswordForm::Store::kProfileStore}};
// Simulate response from the profile store.
manager.OnReuseCheckDone(/*is_reuse_found=*/true, /*password_length=*/10,
- /*reused_protected_password_hash=*/base::nullopt,
+ /*reused_protected_password_hash=*/absl::nullopt,
profile_reused_credentials, /*saved_passwords=*/1);
std::vector<MatchingReusedCredential> account_reused_credentials{
@@ -329,7 +326,7 @@ TEST_F(PasswordReuseDetectionManagerWithTwoStoresTest,
_));
// Simulate response from the account store.
manager.OnReuseCheckDone(/*is_reuse_found=*/true, /*password_length=*/10,
- /*reused_protected_password_hash=*/base::nullopt,
+ /*reused_protected_password_hash=*/absl::nullopt,
account_reused_credentials, /*saved_passwords=*/1);
}
@@ -359,7 +356,7 @@ TEST_F(PasswordReuseDetectionManagerWithTwoStoresTest,
.in_store = PasswordForm::Store::kProfileStore}};
// Simulate response from the profile store.
manager.OnReuseCheckDone(/*is_reuse_found=*/true, /*password_length=*/10,
- /*reused_protected_password_hash=*/base::nullopt,
+ /*reused_protected_password_hash=*/absl::nullopt,
profile_reused_credentials, /*saved_passwords=*/1);
// The callback is run only after both stores respond.
@@ -367,7 +364,7 @@ TEST_F(PasswordReuseDetectionManagerWithTwoStoresTest,
CheckProtectedPasswordEntry(_, _, profile_reused_credentials, _));
// Simulate response from the account store with no reuse found.
manager.OnReuseCheckDone(/*is_reuse_found=*/false, /*password_length=*/0,
- /*reused_protected_password_hash=*/base::nullopt, {},
+ /*reused_protected_password_hash=*/absl::nullopt, {},
/*saved_passwords=*/0);
}
@@ -393,7 +390,7 @@ TEST_F(PasswordReuseDetectionManagerWithTwoStoresTest,
// Simulate response from the account store with no reuse found.
manager.OnReuseCheckDone(/*is_reuse_found=*/false, /*password_length=*/0,
- /*reused_protected_password_hash=*/base::nullopt, {},
+ /*reused_protected_password_hash=*/absl::nullopt, {},
/*saved_passwords=*/0);
std::vector<MatchingReusedCredential> profile_reused_credentials = {
@@ -406,7 +403,7 @@ TEST_F(PasswordReuseDetectionManagerWithTwoStoresTest,
CheckProtectedPasswordEntry(_, _, profile_reused_credentials, _));
// Simulate response from the profile store.
manager.OnReuseCheckDone(/*is_reuse_found=*/true, /*password_length=*/10,
- /*reused_protected_password_hash=*/base::nullopt,
+ /*reused_protected_password_hash=*/absl::nullopt,
profile_reused_credentials, /*saved_passwords=*/1);
}
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 439a3fc31b2..35291c9b578 100644
--- a/chromium/components/password_manager/core/browser/password_reuse_detector.cc
+++ b/chromium/components/password_manager/core/browser/password_reuse_detector.cc
@@ -40,10 +40,10 @@ bool IsSuffix(const std::u16string& str,
// Helper function to returns matching PasswordHashData from a list that has
// the longest password length.
-base::Optional<PasswordHashData> FindPasswordReuse(
+absl::optional<PasswordHashData> FindPasswordReuse(
const std::u16string& input,
const std::vector<PasswordHashData>& password_hash_list) {
- base::Optional<PasswordHashData> longest_match = base::nullopt;
+ absl::optional<PasswordHashData> longest_match = absl::nullopt;
size_t longest_match_size = 0;
for (const PasswordHashData& hash_data : password_hash_list) {
if (input.size() < hash_data.length)
@@ -98,6 +98,8 @@ void PasswordReuseDetector::OnLoginsChanged(
if (change.type() == PasswordStoreChange::ADD ||
change.type() == PasswordStoreChange::UPDATE)
AddPassword(change.form());
+ if (change.type() == PasswordStoreChange::REMOVE)
+ RemovePassword(change.form());
}
}
@@ -107,17 +109,17 @@ void PasswordReuseDetector::CheckReuse(
PasswordReuseDetectorConsumer* consumer) {
DCHECK(consumer);
if (input.size() < kMinPasswordLengthToCheck) {
- consumer->OnReuseCheckDone(false, 0, base::nullopt, {}, saved_passwords_);
+ consumer->OnReuseCheckDone(false, 0, absl::nullopt, {}, saved_passwords_);
return;
}
- base::Optional<PasswordHashData> reused_gaia_password_hash =
+ absl::optional<PasswordHashData> reused_gaia_password_hash =
CheckGaiaPasswordReuse(input, domain);
size_t gaia_reused_password_length = reused_gaia_password_hash.has_value()
? reused_gaia_password_hash->length
: 0;
- base::Optional<PasswordHashData> reused_enterprise_password_hash =
+ absl::optional<PasswordHashData> reused_enterprise_password_hash =
CheckNonGaiaEnterprisePasswordReuse(input, domain);
size_t enterprise_reused_password_length =
reused_enterprise_password_hash.has_value()
@@ -133,12 +135,12 @@ void PasswordReuseDetector::CheckReuse(
enterprise_reused_password_length});
if (max_reused_password_length == 0) {
- consumer->OnReuseCheckDone(false, 0, base::nullopt, {}, saved_passwords_);
+ consumer->OnReuseCheckDone(false, 0, absl::nullopt, {}, saved_passwords_);
return;
}
- base::Optional<PasswordHashData> reused_protected_password_hash =
- base::nullopt;
+ absl::optional<PasswordHashData> reused_protected_password_hash =
+ absl::nullopt;
if (gaia_reused_password_length > enterprise_reused_password_length) {
reused_protected_password_hash = std::move(reused_gaia_password_hash);
} else if (enterprise_reused_password_length != 0) {
@@ -149,30 +151,30 @@ void PasswordReuseDetector::CheckReuse(
matching_reused_credentials, saved_passwords_);
}
-base::Optional<PasswordHashData> PasswordReuseDetector::CheckGaiaPasswordReuse(
+absl::optional<PasswordHashData> PasswordReuseDetector::CheckGaiaPasswordReuse(
const std::u16string& input,
const std::string& domain) {
if (!gaia_password_hash_data_list_.has_value() ||
gaia_password_hash_data_list_->empty()) {
- return base::nullopt;
+ return absl::nullopt;
}
// Skips password reuse check if |domain| matches Gaia origin.
const Origin gaia_origin =
Origin::Create(GaiaUrls::GetInstance()->gaia_url().GetOrigin());
if (Origin::Create(GURL(domain)).IsSameOriginWith(gaia_origin))
- return base::nullopt;
+ return absl::nullopt;
return FindPasswordReuse(input, gaia_password_hash_data_list_.value());
}
-base::Optional<PasswordHashData>
+absl::optional<PasswordHashData>
PasswordReuseDetector::CheckNonGaiaEnterprisePasswordReuse(
const std::u16string& input,
const std::string& domain) {
if (!enterprise_password_hash_data_list_.has_value() ||
enterprise_password_hash_data_list_->empty()) {
- return base::nullopt;
+ return absl::nullopt;
}
// Skips password reuse check if |domain| matches enterprise login URL or
@@ -181,7 +183,7 @@ PasswordReuseDetector::CheckNonGaiaEnterprisePasswordReuse(
if (enterprise_password_urls_.has_value() &&
safe_browsing::MatchesURLList(page_url,
enterprise_password_urls_.value())) {
- return base::nullopt;
+ return absl::nullopt;
}
return FindPasswordReuse(input, enterprise_password_hash_data_list_.value());
@@ -233,18 +235,18 @@ size_t PasswordReuseDetector::CheckSavedPasswordReuse(
}
void PasswordReuseDetector::UseGaiaPasswordHash(
- base::Optional<std::vector<PasswordHashData>> password_hash_data_list) {
+ absl::optional<std::vector<PasswordHashData>> password_hash_data_list) {
gaia_password_hash_data_list_ = std::move(password_hash_data_list);
}
void PasswordReuseDetector::UseNonGaiaEnterprisePasswordHash(
- base::Optional<std::vector<PasswordHashData>> password_hash_data_list) {
+ absl::optional<std::vector<PasswordHashData>> password_hash_data_list) {
enterprise_password_hash_data_list_ = std::move(password_hash_data_list);
}
void PasswordReuseDetector::UseEnterprisePasswordURLs(
- base::Optional<std::vector<GURL>> enterprise_login_urls,
- base::Optional<GURL> enterprise_change_password_url) {
+ absl::optional<std::vector<GURL>> enterprise_login_urls,
+ absl::optional<GURL> enterprise_change_password_url) {
enterprise_password_urls_ = std::move(enterprise_login_urls);
if (!enterprise_change_password_url.has_value() ||
!enterprise_change_password_url->is_valid()) {
@@ -252,7 +254,7 @@ void PasswordReuseDetector::UseEnterprisePasswordURLs(
}
if (!enterprise_password_urls_)
- enterprise_password_urls_ = base::make_optional<std::vector<GURL>>();
+ enterprise_password_urls_ = absl::make_optional<std::vector<GURL>>();
enterprise_password_urls_->push_back(enterprise_change_password_url.value());
}
@@ -298,6 +300,19 @@ void PasswordReuseDetector::AddPassword(const PasswordForm& form) {
}
}
+void PasswordReuseDetector::RemovePassword(const PasswordForm& form) {
+ if (form.password_value.size() < kMinPasswordLengthToCheck)
+ return;
+
+ const auto result =
+ passwords_with_matching_reused_credentials_.find(form.password_value);
+ if (!(result == passwords_with_matching_reused_credentials_.end()) ||
+ !result->second.empty()) {
+ passwords_with_matching_reused_credentials_.erase(form.password_value);
+ saved_passwords_--;
+ }
+}
+
PasswordReuseDetector::passwords_iterator
PasswordReuseDetector::FindFirstSavedPassword(const std::u16string& input) {
// Keys in |passwords_with_matching_reused_credentials_| are ordered by
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 c271449cd22..8ea93d9e0b8 100644
--- a/chromium/components/password_manager/core/browser/password_reuse_detector.h
+++ b/chromium/components/password_manager/core/browser/password_reuse_detector.h
@@ -13,11 +13,11 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/password_manager/core/browser/hash_password_manager.h"
#include "components/password_manager/core/browser/password_form.h"
#include "components/password_manager/core/browser/password_store_change.h"
#include "components/password_manager/core/browser/password_store_consumer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
@@ -68,17 +68,17 @@ class PasswordReuseDetector : public PasswordStoreConsumer {
// Stores a vector of PasswordHashData for Gaia password reuse checking.
void UseGaiaPasswordHash(
- base::Optional<std::vector<PasswordHashData>> password_hash_data_list);
+ absl::optional<std::vector<PasswordHashData>> password_hash_data_list);
// Stores a vector of PasswordHashData for enterprise password reuse checking.
void UseNonGaiaEnterprisePasswordHash(
- base::Optional<std::vector<PasswordHashData>> password_hash_data_list);
+ absl::optional<std::vector<PasswordHashData>> password_hash_data_list);
// Stores enterprise login URLs and change password URL.
// These URLs should be skipped in enterprise password reuse checking.
void UseEnterprisePasswordURLs(
- base::Optional<std::vector<GURL>> enterprise_login_urls,
- base::Optional<GURL> enterprise_change_password_url);
+ absl::optional<std::vector<GURL>> enterprise_login_urls,
+ absl::optional<GURL> enterprise_change_password_url);
void ClearGaiaPasswordHash(const std::string& username);
@@ -100,15 +100,20 @@ class PasswordReuseDetector : public PasswordStoreConsumer {
// |passwords_with_matching_reused_credentials_|.
void AddPassword(const PasswordForm& form);
+ // Remove password of |form| from
+ // |passwords_with_matching_reused_credentials_| and lower the counter of
+ // |saved_passwords_|.
+ void RemovePassword(const PasswordForm& form);
+
// If Gaia password reuse is found, return the PasswordHashData of the reused
- // password. If no reuse is found, return |base::nullopt|.
- base::Optional<PasswordHashData> CheckGaiaPasswordReuse(
+ // password. If no reuse is found, return |absl::nullopt|.
+ absl::optional<PasswordHashData> CheckGaiaPasswordReuse(
const std::u16string& input,
const std::string& domain);
// If Non-Gaia enterprise password reuse is found, return the PasswordHashData
- // of the the reused password. If no reuse is found, return |base::nullopt|.
- base::Optional<PasswordHashData> CheckNonGaiaEnterprisePasswordReuse(
+ // of the the reused password. If no reuse is found, return |absl::nullopt|.
+ absl::optional<PasswordHashData> CheckNonGaiaEnterprisePasswordReuse(
const std::u16string& input,
const std::string& domain);
@@ -151,12 +156,12 @@ class PasswordReuseDetector : public PasswordStoreConsumer {
// of times how many different sites it's saved on.
int saved_passwords_ = 0;
- base::Optional<std::vector<PasswordHashData>> gaia_password_hash_data_list_;
+ absl::optional<std::vector<PasswordHashData>> gaia_password_hash_data_list_;
- base::Optional<std::vector<PasswordHashData>>
+ absl::optional<std::vector<PasswordHashData>>
enterprise_password_hash_data_list_;
- base::Optional<std::vector<GURL>> enterprise_password_urls_;
+ absl::optional<std::vector<GURL>> enterprise_password_urls_;
DISALLOW_COPY_AND_ASSIGN(PasswordReuseDetector);
};
diff --git a/chromium/components/password_manager/core/browser/password_reuse_detector_consumer.h b/chromium/components/password_manager/core/browser/password_reuse_detector_consumer.h
index 0e01ea916a1..76b4dc50fdf 100644
--- a/chromium/components/password_manager/core/browser/password_reuse_detector_consumer.h
+++ b/chromium/components/password_manager/core/browser/password_reuse_detector_consumer.h
@@ -5,14 +5,13 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_REUSE_DETECTOR_CONSUMER_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_REUSE_DETECTOR_CONSUMER_H_
-#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/password_manager/core/browser/hash_password_manager.h"
#include "components/password_manager/core/browser/password_reuse_detector.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
@@ -37,7 +36,7 @@ class PasswordReuseDetectorConsumer
virtual void OnReuseCheckDone(
bool is_reuse_found,
size_t password_length,
- base::Optional<PasswordHashData> reused_protected_password_hash,
+ absl::optional<PasswordHashData> reused_protected_password_hash,
const std::vector<MatchingReusedCredential>& matching_reused_credentials,
int saved_passwords) = 0;
};
diff --git a/chromium/components/password_manager/core/browser/password_reuse_detector_unittest.cc b/chromium/components/password_manager/core/browser/password_reuse_detector_unittest.cc
index 5981500cb10..a8487cf8fc6 100644
--- a/chromium/components/password_manager/core/browser/password_reuse_detector_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_reuse_detector_unittest.cc
@@ -28,8 +28,8 @@ namespace {
using StringVector = std::vector<std::string>;
// Constants to make the tests more readable.
-const base::Optional<PasswordHashData> NO_GAIA_OR_ENTERPRISE_REUSE =
- base::nullopt;
+const absl::optional<PasswordHashData> NO_GAIA_OR_ENTERPRISE_REUSE =
+ absl::nullopt;
struct TestData {
// Comma separated list of domains.
@@ -109,8 +109,8 @@ std::vector<PasswordHashData> PrepareEnterprisePasswordData(
void ConfigureEnterprisePasswordProtection(
PasswordReuseDetector* reuse_detector) {
- base::Optional<std::vector<GURL>> login_urls =
- base::make_optional<std::vector<GURL>>();
+ absl::optional<std::vector<GURL>> login_urls =
+ absl::make_optional<std::vector<GURL>>();
login_urls->push_back(GURL("https://login.example.com"));
reuse_detector->UseEnterprisePasswordURLs(
login_urls, GURL("https://changepassword.example.com/"));
@@ -231,6 +231,47 @@ TEST(PasswordReuseDetectorTest, OnLoginsChanged) {
}
}
+TEST(PasswordReuseDetectorTest, AddAndRemoveSameLogin) {
+ PasswordReuseDetector reuse_detector;
+ std::vector<std::unique_ptr<PasswordForm>> login_credentials =
+ GetForms(GetTestDomainsPasswords());
+ // Add the test domain passwords into the saved passwords map.
+ PasswordStoreChangeList add_changes =
+ GetChangeList(PasswordStoreChange::ADD, login_credentials);
+ reuse_detector.OnLoginsChanged(add_changes);
+
+ const std::vector<MatchingReusedCredential>
+ expected_matching_reused_credentials = {
+ {"https://accounts.google.com", u"gUsername"}};
+ MockPasswordReuseDetectorConsumer mockConsumer;
+ // One of the passwords in |login_credentials| has less than the minimum
+ // requirement of characters in a password so it will not be stored.
+ int valid_passwords = login_credentials.size() - 1;
+ EXPECT_CALL(
+ mockConsumer,
+ OnReuseCheckDone(
+ /*is_reuse_found=*/true, strlen("saved_password"),
+ Matches(NO_GAIA_OR_ENTERPRISE_REUSE),
+ UnorderedElementsAreArray(expected_matching_reused_credentials),
+ valid_passwords));
+
+ // "saved_password" is a substring of "123saved_password" so it should trigger
+ // a reuse and get the matching credentials.
+ reuse_detector.CheckReuse(u"123saved_password", "https://evil.com",
+ &mockConsumer);
+ testing::Mock::VerifyAndClearExpectations(&mockConsumer);
+
+ // Remove the test domain passwords from the saved passwords map.
+ PasswordStoreChangeList remove_changes =
+ GetChangeList(PasswordStoreChange::REMOVE, login_credentials);
+ reuse_detector.OnLoginsChanged(remove_changes);
+ EXPECT_CALL(mockConsumer,
+ OnReuseCheckDone(/*is_reuse_found=*/false, _, _, _, _));
+ // The stored credentials were removed so no reuse should be found.
+ reuse_detector.CheckReuse(u"123saved_password", "https://evil.com",
+ &mockConsumer);
+}
+
TEST(PasswordReuseDetectorTest, MatchMultiplePasswords) {
// These all have different length passwods so we can check the
// returned length.
@@ -306,7 +347,7 @@ TEST(PasswordReuseDetectorTest, GaiaPasswordReuseFound) {
std::vector<PasswordHashData> gaia_password_hashes =
PrepareGaiaPasswordData({"gaia_pw1", "gaia_pw2"});
- base::Optional<PasswordHashData> expected_reused_password_hash(
+ absl::optional<PasswordHashData> expected_reused_password_hash(
gaia_password_hashes[0]);
reuse_detector.UseGaiaPasswordHash(gaia_password_hashes);
@@ -327,7 +368,7 @@ TEST(PasswordReuseDetectorTest, EnterprisePasswordNoReuse) {
std::vector<PasswordHashData> enterprise_password_hashes =
PrepareEnterprisePasswordData({"enterprise_pw1", "enterprise_pw2"});
- base::Optional<PasswordHashData> expected_reused_password_hash(
+ absl::optional<PasswordHashData> expected_reused_password_hash(
enterprise_password_hashes[1]);
reuse_detector.UseNonGaiaEnterprisePasswordHash(enterprise_password_hashes);
@@ -355,7 +396,7 @@ TEST(PasswordReuseDetectorTest, EnterprisePasswordReuseFound) {
std::vector<PasswordHashData> enterprise_password_hashes =
PrepareEnterprisePasswordData({"enterprise_pw1", "enterprise_pw2"});
- base::Optional<PasswordHashData> expected_reused_password_hash(
+ absl::optional<PasswordHashData> expected_reused_password_hash(
enterprise_password_hashes[1]);
reuse_detector.UseNonGaiaEnterprisePasswordHash(enterprise_password_hashes);
@@ -379,7 +420,7 @@ TEST(PasswordReuseDetectorTest, MatchGaiaAndMultipleSavedPasswords) {
std::vector<PasswordHashData> gaia_password_hashes =
PrepareGaiaPasswordData({gaia_password});
ASSERT_EQ(1u, gaia_password_hashes.size());
- base::Optional<PasswordHashData> expected_reused_password_hash(
+ absl::optional<PasswordHashData> expected_reused_password_hash(
gaia_password_hashes[0]);
reuse_detector.UseGaiaPasswordHash(gaia_password_hashes);
@@ -468,7 +509,7 @@ TEST(PasswordReuseDetectorTest, MatchEnterpriseAndMultipleSavedPasswords) {
std::vector<PasswordHashData> enterprise_password_hashes =
PrepareEnterprisePasswordData({enterprise_password});
ASSERT_EQ(1u, enterprise_password_hashes.size());
- base::Optional<PasswordHashData> expected_reused_password_hash(
+ absl::optional<PasswordHashData> expected_reused_password_hash(
enterprise_password_hashes[0]);
reuse_detector.UseNonGaiaEnterprisePasswordHash(enterprise_password_hashes);
@@ -532,7 +573,7 @@ TEST(PasswordReuseDetectorTest, MatchGaiaEnterpriseAndSavedPassword) {
std::vector<PasswordHashData> enterprise_password_hashes =
PrepareEnterprisePasswordData({enterprise_password});
ASSERT_EQ(1u, enterprise_password_hashes.size());
- base::Optional<PasswordHashData> expected_reused_password_hash(
+ absl::optional<PasswordHashData> expected_reused_password_hash(
enterprise_password_hashes[0]);
reuse_detector.UseNonGaiaEnterprisePasswordHash(enterprise_password_hashes);
diff --git a/chromium/components/password_manager/core/browser/password_save_manager_impl.cc b/chromium/components/password_manager/core/browser/password_save_manager_impl.cc
index 795080e1c76..da27d86f77e 100644
--- a/chromium/components/password_manager/core/browser/password_save_manager_impl.cc
+++ b/chromium/components/password_manager/core/browser/password_save_manager_impl.cc
@@ -163,7 +163,7 @@ void PasswordSaveManagerImpl::CreatePendingCredentials(
std::tie(similar_saved_form, pending_credentials_state_) =
FindSimilarSavedFormAndComputeState(parsed_submitted_form);
- base::Optional<std::u16string> generated_password;
+ absl::optional<std::u16string> generated_password;
if (HasGeneratedPassword())
generated_password = generation_manager_->generated_password();
@@ -374,7 +374,7 @@ PasswordForm PasswordSaveManagerImpl::BuildPendingCredentials(
const PasswordForm& parsed_submitted_form,
const FormData* observed_form,
const FormData& submitted_form,
- const base::Optional<std::u16string>& generated_password,
+ const absl::optional<std::u16string>& generated_password,
bool is_http_auth,
bool is_credential_api_save,
const PasswordForm* similar_saved_form) {
diff --git a/chromium/components/password_manager/core/browser/password_save_manager_impl.h b/chromium/components/password_manager/core/browser/password_save_manager_impl.h
index 562491b9ff8..f482c645e26 100644
--- a/chromium/components/password_manager/core/browser/password_save_manager_impl.h
+++ b/chromium/components/password_manager/core/browser/password_save_manager_impl.h
@@ -95,7 +95,7 @@ class PasswordSaveManagerImpl : public PasswordSaveManager {
const PasswordForm& parsed_submitted_form,
const autofill::FormData* observed_form,
const autofill::FormData& submitted_form,
- const base::Optional<std::u16string>& generated_password,
+ const absl::optional<std::u16string>& generated_password,
bool is_http_auth,
bool is_credential_api_save,
const PasswordForm* similar_saved_form);
diff --git a/chromium/components/password_manager/core/browser/password_save_manager_impl_unittest.cc b/chromium/components/password_manager/core/browser/password_save_manager_impl_unittest.cc
index e82d212dfe0..c3802e0cf88 100644
--- a/chromium/components/password_manager/core/browser/password_save_manager_impl_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_save_manager_impl_unittest.cc
@@ -29,7 +29,6 @@ using autofill::FormFieldData;
using autofill::FormStructure;
using autofill::PasswordFormFillData;
using autofill::mojom::SubmissionIndicatorEvent;
-using base::ASCIIToUTF16;
using base::TestMockTimeTaskRunner;
using testing::_;
using testing::AllOf;
@@ -71,9 +70,9 @@ void CheckPendingCredentials(const PasswordForm& expected,
}
struct ExpectedGenerationUKM {
- base::Optional<int64_t> generation_popup_shown;
+ absl::optional<int64_t> generation_popup_shown;
int64_t has_generated_password;
- base::Optional<int64_t> generated_password_modified;
+ absl::optional<int64_t> generated_password_modified;
};
// Check that UKM |metric_name| in |entry| is equal to |expected|. |expected| ==
@@ -953,7 +952,7 @@ TEST_P(PasswordSaveManagerImplTest, PresaveGeneratedPasswordEmptyStore) {
// Check that when the generated password is edited, then it's presaved.
form_with_generated_password.password_value += u"1";
EXPECT_CALL(*mock_form_saver(),
- UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
+ UpdateReplace(_, IsEmpty(), testing::Eq(u""),
FormHasUniqueKey(form_with_generated_password)))
.WillOnce(SaveArg<0>(&saved_form));
@@ -986,7 +985,7 @@ TEST_P(PasswordSaveManagerImplTest, PresaveGenerated_ModifiedUsername) {
// Check that when the username is edited, then it's presaved.
form_with_generated_password.username_value += u"1";
- EXPECT_CALL(*mock_form_saver(), UpdateReplace(_, IsEmpty(), ASCIIToUTF16(""),
+ EXPECT_CALL(*mock_form_saver(), UpdateReplace(_, IsEmpty(), testing::Eq(u""),
FormHasUniqueKey(saved_form)))
.WillOnce(SaveArg<0>(&saved_form));
diff --git a/chromium/components/password_manager/core/browser/password_scripts_fetcher_impl.cc b/chromium/components/password_manager/core/browser/password_scripts_fetcher_impl.cc
index 08b50bca1ad..bd8acc807a8 100644
--- a/chromium/components/password_manager/core/browser/password_scripts_fetcher_impl.cc
+++ b/chromium/components/password_manager/core/browser/password_scripts_fetcher_impl.cc
@@ -21,7 +21,7 @@ namespace {
constexpr int kCacheTimeoutInMinutes = 5;
constexpr int kFetchTimeoutInSeconds = 3;
-constexpr int kMaxDownloadSizeInBytes = 10 * 1024;
+constexpr int kMaxDownloadSizeInBytes = 512 * 1024;
using ParsingResult =
password_manager::PasswordScriptsFetcherImpl::ParsingResult;
@@ -247,7 +247,7 @@ base::flat_set<ParsingResult> PasswordScriptsFetcherImpl::ParseResponse(
base::JSONReader::ValueWithError data =
base::JSONReader::ReadAndReturnValueWithError(*response_body);
- if (data.value == base::nullopt) {
+ if (data.value == absl::nullopt) {
DVLOG(1) << "Parse error: " << data.error_message;
return {ParsingResult::kInvalidJson};
}
diff --git a/chromium/components/password_manager/core/browser/password_store.cc b/chromium/components/password_manager/core/browser/password_store.cc
index e090bf7ed62..ffa72a0c752 100644
--- a/chromium/components/password_manager/core/browser/password_store.cc
+++ b/chromium/components/password_manager/core/browser/password_store.cc
@@ -123,7 +123,7 @@ PasswordStore::CheckReuseRequest::~CheckReuseRequest() = default;
void PasswordStore::CheckReuseRequest::OnReuseCheckDone(
bool is_reuse_found,
size_t password_length,
- base::Optional<PasswordHashData> reused_protected_password_hash,
+ absl::optional<PasswordHashData> reused_protected_password_hash,
const std::vector<MatchingReusedCredential>& matching_reused_credentials,
int saved_passwords) {
origin_task_runner_->PostTask(
@@ -834,7 +834,7 @@ void PasswordStore::CheckReuseImpl(std::unique_ptr<CheckReuseRequest> request,
if (reuse_detector_) {
reuse_detector_->CheckReuse(input, domain, request.get());
} else {
- request->OnReuseCheckDone(false, 0, base::nullopt, {}, 0);
+ request->OnReuseCheckDone(false, 0, absl::nullopt, {}, 0);
}
}
diff --git a/chromium/components/password_manager/core/browser/password_store.h b/chromium/components/password_manager/core/browser/password_store.h
index 531ec2271f4..421ee1b0799 100644
--- a/chromium/components/password_manager/core/browser/password_store.h
+++ b/chromium/components/password_manager/core/browser/password_store.h
@@ -58,7 +58,7 @@ class PasswordSyncBridge;
struct FieldInfo;
struct InteractionsStats;
-using PasswordHashDataList = base::Optional<std::vector<PasswordHashData>>;
+using PasswordHashDataList = absl::optional<std::vector<PasswordHashData>>;
// Interface for storing form passwords in a platform-specific secure way.
// The login request/manipulation API is not threadsafe and must be used
@@ -432,7 +432,7 @@ class PasswordStore : protected PasswordStoreSync,
void OnReuseCheckDone(
bool is_reuse_found,
size_t password_length,
- base::Optional<PasswordHashData> reused_protected_password_hash,
+ absl::optional<PasswordHashData> reused_protected_password_hash,
const std::vector<MatchingReusedCredential>&
matching_reused_credentials,
int saved_passwords) override;
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 df8e86aa11d..35c0a8e438f 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
@@ -119,7 +119,7 @@ bool ShouldAffiliationBasedMatchingBeActive(syncer::SyncService* sync_service) {
return sync_service && sync_service->IsSyncFeatureActive() &&
sync_service->GetUserSettings()->GetSelectedTypes().Has(
syncer::UserSelectableType::kPasswords) &&
- !sync_service->GetUserSettings()->IsUsingSecondaryPassphrase();
+ !sync_service->GetUserSettings()->IsUsingExplicitPassphrase();
}
} // 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 b5423096645..e97d1d4d1b9 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
@@ -54,7 +54,7 @@ base::FilePath GetLoginDatabaseForAccountStoragePathForTesting(
// It checks whether the user
// 1) has password syncing across multiple devices enabled
// (first setup must be completed)
-// 2) does not have secondary passphrase set.
+// 2) does not have explicit passphrase set.
// Failure to meet both of those requirements results in preventing Chrome from
// sending requests to Google Affiliation Service API.
bool ShouldAffiliationBasedMatchingBeActive(syncer::SyncService* sync_service);
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 19766c8e978..75947b393cb 100644
--- a/chromium/components/password_manager/core/browser/password_store_unittest.cc
+++ b/chromium/components/password_manager/core/browser/password_store_unittest.cc
@@ -244,7 +244,7 @@ class PasswordStoreTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(PasswordStoreTest);
};
-base::Optional<PasswordHashData> GetPasswordFromPref(
+absl::optional<PasswordHashData> GetPasswordFromPref(
const std::string& username,
bool is_gaia_password,
PrefService* prefs) {
@@ -1280,7 +1280,7 @@ TEST_F(PasswordStoreTest, CheckPasswordReuse) {
PasswordForm::Store::kProfileStore}};
EXPECT_CALL(mock_consumer,
OnReuseCheckDone(true, test_data.reused_password_len,
- Matches(base::nullopt),
+ Matches(absl::nullopt),
ElementsAreArray(credentials), 2));
} else {
EXPECT_CALL(mock_consumer, OnReuseCheckDone(false, _, _, _, _));
@@ -1314,7 +1314,7 @@ TEST_F(PasswordStoreTest, SavingClearingProtectedPassword) {
metrics_util::GaiaPasswordHashChange::SAVED_ON_CHROME_SIGNIN);
WaitForPasswordStore();
EXPECT_TRUE(prefs.HasPrefPath(prefs::kPasswordHashDataList));
- base::Optional<PasswordHashData> sync_password_hash =
+ absl::optional<PasswordHashData> sync_password_hash =
GetPasswordFromPref("sync_username", /*is_gaia_password=*/true, &prefs);
ASSERT_TRUE(sync_password_hash.has_value());
@@ -1332,7 +1332,7 @@ TEST_F(PasswordStoreTest, SavingClearingProtectedPassword) {
store->SaveGaiaPasswordHash("other_gaia_username", gaia_password,
/*is_primary_account=*/false,
GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE);
- base::Optional<PasswordHashData> gaia_password_hash = GetPasswordFromPref(
+ absl::optional<PasswordHashData> gaia_password_hash = GetPasswordFromPref(
"other_gaia_username", /*is_gaia_password=*/true, &prefs);
ASSERT_TRUE(gaia_password_hash.has_value());
@@ -1365,7 +1365,7 @@ TEST_F(PasswordStoreTest, SavingClearingProtectedPassword) {
// Save a enterprise password this time.
const std::u16string enterprise_password = u"23password";
store->SaveEnterprisePasswordHash("enterprise_username", enterprise_password);
- base::Optional<PasswordHashData> enterprise_password_hash =
+ absl::optional<PasswordHashData> enterprise_password_hash =
GetPasswordFromPref("enterprise_username", /*is_gaia_password=*/false,
&prefs);
ASSERT_TRUE(enterprise_password_hash.has_value());
@@ -1394,7 +1394,7 @@ TEST_F(PasswordStoreTest, SavingClearingProtectedPassword) {
GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE);
WaitForPasswordStore();
EXPECT_TRUE(prefs.HasPrefPath(prefs::kPasswordHashDataList));
- base::Optional<PasswordHashData> gmail_password_hash = GetPasswordFromPref(
+ absl::optional<PasswordHashData> gmail_password_hash = GetPasswordFromPref(
"username@gmail.com", /*is_gaia_password=*/true, &prefs);
ASSERT_TRUE(gmail_password_hash.has_value());
@@ -1412,7 +1412,7 @@ TEST_F(PasswordStoreTest, SavingClearingProtectedPassword) {
non_sync_gaia_password,
/*is_primary_account=*/false,
GaiaPasswordHashChange::NOT_SYNC_PASSWORD_CHANGE);
- base::Optional<PasswordHashData> non_sync_gaia_password_hash =
+ absl::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());
diff --git a/chromium/components/password_manager/core/browser/password_ui_utils.cc b/chromium/components/password_manager/core/browser/password_ui_utils.cc
index d711aab3720..465d89659a0 100644
--- a/chromium/components/password_manager/core/browser/password_ui_utils.cc
+++ b/chromium/components/password_manager/core/browser/password_ui_utils.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -70,7 +71,7 @@ std::string GetShownOrigin(const url::Origin& origin) {
}
}
- return result.find('.') != base::StringPiece::npos ? result.as_string()
+ return result.find('.') != base::StringPiece::npos ? std::string(result)
: original;
}
diff --git a/chromium/components/password_manager/core/browser/possible_username_data.h b/chromium/components/password_manager/core/browser/possible_username_data.h
index 1be16551c39..a4fa5aec71b 100644
--- a/chromium/components/password_manager/core/browser/possible_username_data.h
+++ b/chromium/components/password_manager/core/browser/possible_username_data.h
@@ -8,10 +8,10 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/autofill/core/common/unique_ids.h"
#include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
@@ -42,7 +42,7 @@ struct PossibleUsernameData {
int driver_id;
// Predictions for the form which contains a field with |renderer_id|.
- base::Optional<FormPredictions> form_predictions;
+ absl::optional<FormPredictions> form_predictions;
};
// Checks that |possible_username| might represent an username:
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 2273aafe781..5808a27dfec 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
@@ -10,7 +10,6 @@
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "components/password_manager/core/browser/password_form.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
diff --git a/chromium/components/password_manager/core/browser/site_affiliation/affiliation_fetcher_base.cc b/chromium/components/password_manager/core/browser/site_affiliation/affiliation_fetcher_base.cc
index dca028ee55e..d2e731c86b3 100644
--- a/chromium/components/password_manager/core/browser/site_affiliation/affiliation_fetcher_base.cc
+++ b/chromium/components/password_manager/core/browser/site_affiliation/affiliation_fetcher_base.cc
@@ -7,6 +7,7 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "components/password_manager/core/browser/android_affiliation/lookup_affiliation_response_parser.h"
+#include "components/variations/net/variations_http_headers.h"
#include "net/base/load_flags.h"
#include "net/base/url_util.h"
#include "services/network/public/cpp/resource_request.h"
@@ -70,6 +71,9 @@ void AffiliationFetcherBase::FinalizeRequest(
resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
resource_request->method = "POST";
+ variations::AppendVariationsHeaderUnknownSignedIn(
+ query_url, variations::InIncognito::kNo, resource_request.get());
+
DCHECK(!simple_url_loader_);
simple_url_loader_ = network::SimpleURLLoader::Create(
std::move(resource_request), traffic_annotation);
diff --git a/chromium/components/password_manager/core/browser/site_affiliation/affiliation_service_impl_unittest.cc b/chromium/components/password_manager/core/browser/site_affiliation/affiliation_service_impl_unittest.cc
index 2e8a7b1c2dc..9f4968fd360 100644
--- a/chromium/components/password_manager/core/browser/site_affiliation/affiliation_service_impl_unittest.cc
+++ b/chromium/components/password_manager/core/browser/site_affiliation/affiliation_service_impl_unittest.cc
@@ -74,7 +74,7 @@ class AffiliationServiceImplTest : public testing::Test {
// Sets TestSyncService flags.
void SetSyncServiceStates(bool is_setup_completed, bool is_passphrase_set) {
sync_service()->SetFirstSetupComplete(is_setup_completed);
- sync_service()->SetIsUsingSecondaryPassphrase(is_passphrase_set);
+ sync_service()->SetIsUsingExplicitPassphrase(is_passphrase_set);
}
private:
@@ -268,7 +268,7 @@ TEST_F(AffiliationServiceImplTest,
TEST_F(AffiliationServiceImplTest,
FetchRequiresCompleteSetupAndPassphraseDisabled) {
// The only scenario when the StartRequest() should be called.
- // Setup is completed and secondary passphrase feature is disabled.
+ // Setup is completed and explicit passphrase feature is disabled.
SetSyncServiceStates(/*is_setup_completed=*/true,
/*is_passphrase_set=*/false);
@@ -285,7 +285,7 @@ TEST_F(AffiliationServiceImplTest,
service()->PrefetchChangePasswordURLs(origins, base::DoNothing());
}
-TEST_F(AffiliationServiceImplTest, SecondaryPassphraseSetPreventsFetch) {
+TEST_F(AffiliationServiceImplTest, ExplicitPassphraseSetPreventsFetch) {
SetSyncServiceStates(/*is_setup_completed=*/true, /*is_passphrase_set=*/true);
EXPECT_CALL(mock_fetcher_factory(), CreateInstance).Times(0);
diff --git a/chromium/components/password_manager/core/browser/sql_table_builder.cc b/chromium/components/password_manager/core/browser/sql_table_builder.cc
index 4b3839b957e..d88ad716238 100644
--- a/chromium/components/password_manager/core/browser/sql_table_builder.cc
+++ b/chromium/components/password_manager/core/browser/sql_table_builder.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "base/containers/contains.h"
+#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/ranges/algorithm.h"
#include "base/strings/strcat.h"
diff --git a/chromium/components/password_manager/core/browser/statistics_table_unittest.cc b/chromium/components/password_manager/core/browser/statistics_table_unittest.cc
index edf8d9ad9a6..21497327067 100644
--- a/chromium/components/password_manager/core/browser/statistics_table_unittest.cc
+++ b/chromium/components/password_manager/core/browser/statistics_table_unittest.cc
@@ -23,9 +23,9 @@ const char kTestDomain[] = "http://google.com";
const char kTestDomain2[] = "http://example.com";
const char kTestDomain3[] = "https://example.org";
const char kTestDomain4[] = "http://localhost";
-const char kUsername1[] = "user1";
-const char kUsername2[] = "user2";
-const char kUsername3[] = "user3";
+const char16_t kUsername1[] = u"user1";
+const char16_t kUsername2[] = u"user2";
+const char16_t kUsername3[] = u"user3";
using ::testing::ElementsAre;
using ::testing::IsEmpty;
@@ -39,7 +39,7 @@ class StatisticsTableTest : public testing::Test {
ReloadDatabase();
test_data_.origin_domain = GURL(kTestDomain);
- test_data_.username_value = base::ASCIIToUTF16(kUsername1);
+ test_data_.username_value = kUsername1;
test_data_.dismissal_count = 10;
test_data_.update_time = base::Time::FromTimeT(1);
}
@@ -102,7 +102,7 @@ TEST_F(StatisticsTableTest, DoubleOperation) {
TEST_F(StatisticsTableTest, DifferentUsernames) {
InteractionsStats stats1 = test_data();
InteractionsStats stats2 = test_data();
- stats2.username_value = base::ASCIIToUTF16(kUsername2);
+ stats2.username_value = kUsername2;
EXPECT_TRUE(db()->AddRow(stats1));
EXPECT_TRUE(db()->AddRow(stats2));
@@ -191,7 +191,7 @@ TEST_F(StatisticsTableTest, EmptyURL) {
TEST_F(StatisticsTableTest, GetDomainsAndAccountsDomainsWithNDismissals) {
struct {
const char* origin;
- const char* username;
+ const char16_t* username;
int dismissal_count;
} const stats_database_entries[] = {
{kTestDomain, kUsername1, 10}, // A
@@ -203,7 +203,7 @@ TEST_F(StatisticsTableTest, GetDomainsAndAccountsDomainsWithNDismissals) {
for (const auto& entry : stats_database_entries) {
EXPECT_TRUE(db()->AddRow({
.origin_domain = GURL(entry.origin),
- .username_value = base::ASCIIToUTF16(entry.username),
+ .username_value = entry.username,
.dismissal_count = entry.dismissal_count,
.update_time = base::Time::FromTimeT(1),
}));
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 6a39adf0fd3..29b7f086c2e 100644
--- a/chromium/components/password_manager/core/browser/store_metrics_reporter.cc
+++ b/chromium/components/password_manager/core/browser/store_metrics_reporter.cc
@@ -197,10 +197,6 @@ StoreMetricsReporter::StoreMetricsReporter(
base::UmaHistogramBoolean(
"PasswordManager.Enabled",
prefs->GetBoolean(password_manager::prefs::kCredentialsEnableService));
- base::UmaHistogramBoolean(
- "PasswordManager.LeakDetection.Enabled",
- prefs->GetBoolean(
- password_manager::prefs::kPasswordLeakDetectionEnabled));
// If both stores exist, kick off the MultiStoreMetricsReporter.
PasswordStore* profile_store = client->GetProfilePasswordStore();
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 3444f6c1127..a6d8dc5ab2a 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
@@ -49,8 +49,6 @@ class StoreMetricsReporterTest : public SyncUsernameTestBase {
StoreMetricsReporterTest() {
prefs_.registry()->RegisterBooleanPref(prefs::kCredentialsEnableService,
false);
- prefs_.registry()->RegisterBooleanPref(prefs::kPasswordLeakDetectionEnabled,
- false);
prefs_.registry()->RegisterBooleanPref(
password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, false);
}
@@ -74,12 +72,9 @@ class StoreMetricsReporterTestWithParams
// Test that store-independent metrics are reported correctly.
TEST_P(StoreMetricsReporterTestWithParams, StoreIndependentMetrics) {
const bool password_manager_enabled = std::get<0>(GetParam());
- const bool leak_detection_enabled = std::get<1>(GetParam());
prefs_.SetBoolean(password_manager::prefs::kCredentialsEnableService,
password_manager_enabled);
- prefs_.SetBoolean(password_manager::prefs::kPasswordLeakDetectionEnabled,
- leak_detection_enabled);
base::HistogramTester histogram_tester;
EXPECT_CALL(client_, GetProfilePasswordStore())
.WillRepeatedly(Return(nullptr));
@@ -88,8 +83,6 @@ TEST_P(StoreMetricsReporterTestWithParams, StoreIndependentMetrics) {
histogram_tester.ExpectUniqueSample("PasswordManager.Enabled",
password_manager_enabled, 1);
- histogram_tester.ExpectUniqueSample("PasswordManager.LeakDetection.Enabled",
- leak_detection_enabled, 1);
}
// Test that sync username and syncing state are passed correctly to the
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 62572bb1a01..366d40adec4 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
@@ -6,7 +6,6 @@
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_STUB_PASSWORD_MANAGER_CLIENT_H_
#include "base/macros.h"
-#include "base/optional.h"
#include "components/autofill/core/browser/logging/stub_log_manager.h"
#include "components/password_manager/core/browser/mock_password_feature_manager.h"
#include "components/password_manager/core/browser/password_manager_client.h"
@@ -15,6 +14,7 @@
#include "components/password_manager/core/browser/password_reuse_detector.h"
#include "components/password_manager/core/browser/stub_credentials_filter.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace password_manager {
@@ -95,7 +95,7 @@ class StubPasswordManagerClient : public PasswordManagerClient {
testing::NiceMock<MockPasswordFeatureManager> password_feature_manager_;
autofill::StubLogManager log_manager_;
ukm::SourceId ukm_source_id_;
- base::Optional<PasswordManagerMetricsRecorder> metrics_recorder_;
+ absl::optional<PasswordManagerMetricsRecorder> metrics_recorder_;
DISALLOW_COPY_AND_ASSIGN(StubPasswordManagerClient);
};
diff --git a/chromium/components/password_manager/core/browser/stub_password_manager_driver.cc b/chromium/components/password_manager/core/browser/stub_password_manager_driver.cc
index bb75f9b0d9e..c6c9b88d2a3 100644
--- a/chromium/components/password_manager/core/browser/stub_password_manager_driver.cc
+++ b/chromium/components/password_manager/core/browser/stub_password_manager_driver.cc
@@ -4,6 +4,8 @@
#include "components/password_manager/core/browser/stub_password_manager_driver.h"
+#include "url/gurl.h"
+
namespace password_manager {
StubPasswordManagerDriver::StubPasswordManagerDriver() = default;
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 cf3ff871d30..099e571a26c 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
@@ -144,7 +144,7 @@ bool PasswordModelTypeController::ShouldRunInTransportOnlyMode() const {
if (!base::FeatureList::IsEnabled(features::kEnablePasswordsAccountStorage)) {
return false;
}
- if (sync_service_->GetUserSettings()->IsUsingSecondaryPassphrase()) {
+ if (sync_service_->GetUserSettings()->IsUsingExplicitPassphrase()) {
return false;
}
return true;
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 403646acabf..c0e6d8c6c16 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
@@ -413,7 +413,7 @@ PasswordSyncBridge::CreateMetadataChangeList() {
return std::make_unique<syncer::InMemoryMetadataChangeList>();
}
-base::Optional<syncer::ModelError> PasswordSyncBridge::MergeSyncData(
+absl::optional<syncer::ModelError> PasswordSyncBridge::MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
// This method merges the local and remote passwords based on their client
@@ -447,7 +447,7 @@ base::Optional<syncer::ModelError> PasswordSyncBridge::MergeSyncData(
"Failed to load entries from password store. "
"Encryption service failure.");
}
- base::Optional<syncer::ModelError> cleanup_result_error =
+ absl::optional<syncer::ModelError> cleanup_result_error =
CleanupPasswordStore();
if (cleanup_result_error) {
metrics_util::LogPasswordSyncState(
@@ -674,7 +674,7 @@ base::Optional<syncer::ModelError> PasswordSyncBridge::MergeSyncData(
// CreateMetadataChangeList() so downcasting is safe.
static_cast<syncer::InMemoryMetadataChangeList*>(metadata_change_list.get())
->TransferChangesTo(&sync_metadata_store_change_list);
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
sync_metadata_store_change_list.TakeError();
if (error) {
metrics_util::LogPasswordSyncState(
@@ -713,10 +713,10 @@ base::Optional<syncer::ModelError> PasswordSyncBridge::MergeSyncData(
}
sync_enabled_or_disabled_cb_.Run();
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<syncer::ModelError> PasswordSyncBridge::ApplySyncChanges(
+absl::optional<syncer::ModelError> PasswordSyncBridge::ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) {
base::AutoReset<bool> processing_changes(&is_processing_remote_sync_changes_,
@@ -879,7 +879,7 @@ base::Optional<syncer::ModelError> PasswordSyncBridge::ApplySyncChanges(
// CreateMetadataChangeList() so downcasting is safe.
static_cast<syncer::InMemoryMetadataChangeList*>(metadata_change_list.get())
->TransferChangesTo(&sync_metadata_store_change_list);
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
sync_metadata_store_change_list.TakeError();
if (error) {
metrics_util::LogApplySyncChangesState(
@@ -900,7 +900,7 @@ base::Optional<syncer::ModelError> PasswordSyncBridge::ApplySyncChanges(
}
metrics_util::LogApplySyncChangesState(
metrics_util::ApplySyncChangesState::kApplyOK);
- return base::nullopt;
+ return absl::nullopt;
}
void PasswordSyncBridge::GetData(StorageKeyList storage_keys,
@@ -1053,7 +1053,7 @@ std::string PasswordSyncBridge::ComputeClientTagForTesting(
return ComputeClientTag(password_data);
}
-base::Optional<syncer::ModelError> PasswordSyncBridge::CleanupPasswordStore() {
+absl::optional<syncer::ModelError> PasswordSyncBridge::CleanupPasswordStore() {
DatabaseCleanupResult cleanup_result =
password_store_sync_->DeleteUndecryptableLogins();
switch (cleanup_result) {
@@ -1070,7 +1070,7 @@ base::Optional<syncer::ModelError> PasswordSyncBridge::CleanupPasswordStore() {
metrics_util::NOT_SYNCING_FAILED_CLEANUP);
return syncer::ModelError(FROM_HERE, "Failed to cleanup database.");
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/sync/password_sync_bridge.h b/chromium/components/password_manager/core/browser/sync/password_sync_bridge.h
index 4f5b2483b90..e0986e13238 100644
--- a/chromium/components/password_manager/core/browser/sync/password_sync_bridge.h
+++ b/chromium/components/password_manager/core/browser/sync/password_sync_bridge.h
@@ -47,10 +47,10 @@ class PasswordSyncBridge : public syncer::ModelTypeSyncBridge {
// ModelTypeSyncBridge implementation.
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
@@ -70,7 +70,7 @@ class PasswordSyncBridge : public syncer::ModelTypeSyncBridge {
// method deletes those logins from the store. So during merge, the data in
// sync will be added to the password store. This should be called during
// MergeSyncData().
- base::Optional<syncer::ModelError> CleanupPasswordStore();
+ absl::optional<syncer::ModelError> CleanupPasswordStore();
// Retrieves the storage keys of all unsynced passwords in the store.
std::set<FormPrimaryKey> GetUnsyncedPasswordsStorageKeys();
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 84015857ec4..511dd058249 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
@@ -456,7 +456,7 @@ class PasswordSyncBridgeTest : public testing::Test,
return data;
}
- base::Optional<sync_pb::PasswordSpecifics> GetDataFromBridge(
+ absl::optional<sync_pb::PasswordSpecifics> GetDataFromBridge(
const std::string& storage_key) {
std::unique_ptr<syncer::DataBatch> batch;
bridge_->GetData({storage_key},
@@ -466,7 +466,7 @@ class PasswordSyncBridgeTest : public testing::Test,
}));
EXPECT_THAT(batch, NotNull());
if (!batch || !batch->HasNext()) {
- return base::nullopt;
+ return absl::nullopt;
}
const syncer::KeyAndData& data_pair = batch->Next();
EXPECT_THAT(data_pair.first, Eq(storage_key));
@@ -565,7 +565,7 @@ TEST_P(PasswordSyncBridgeTest,
}
TEST_P(PasswordSyncBridgeTest, ShouldApplyEmptySyncChangesWithoutError) {
- base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), syncer::EntityChangeList());
EXPECT_FALSE(error);
}
@@ -586,7 +586,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldApplyMetadataWithEmptySyncChanges) {
EXPECT_CALL(*mock_sync_metadata_store_sync(),
UpdateSyncMetadata(syncer::PASSWORDS, kStorageKey, _));
- base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
std::move(metadata_change_list), syncer::EntityChangeList());
EXPECT_FALSE(error);
}
@@ -618,7 +618,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldApplyRemoteCreation) {
syncer::EntityChangeList entity_change_list;
entity_change_list.push_back(syncer::EntityChange::CreateAdd(
/*storage_key=*/"", SpecificsToEntity(specifics)));
- base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -638,7 +638,7 @@ TEST_P(PasswordSyncBridgeTest,
syncer::EntityChangeList entity_change_list;
entity_change_list.push_back(syncer::EntityChange::CreateAdd(
/*storage_key=*/"", SpecificsToEntity(specifics)));
- base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -671,7 +671,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldApplyRemoteUpdate) {
syncer::EntityChangeList entity_change_list;
entity_change_list.push_back(syncer::EntityChange::CreateUpdate(
kStorageKey, SpecificsToEntity(specifics)));
- base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -699,7 +699,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldApplyRemoteDeletion) {
syncer::EntityChangeList entity_change_list;
entity_change_list.push_back(syncer::EntityChange::CreateDelete(kStorageKey));
- base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -715,7 +715,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldGetDataForStorageKey) {
fake_db()->AddLoginForPrimaryKey(kPrimaryKey1, form1);
fake_db()->AddLoginForPrimaryKey(kPrimaryKey2, form2);
- base::Optional<sync_pb::PasswordSpecifics> optional_specifics =
+ absl::optional<sync_pb::PasswordSpecifics> optional_specifics =
GetDataFromBridge(/*storage_key=*/kPrimaryKeyStr1);
ASSERT_TRUE(optional_specifics.has_value());
EXPECT_EQ(
@@ -731,7 +731,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldGetDataForStorageKey) {
TEST_P(PasswordSyncBridgeTest, ShouldNotGetDataForNonExistingStorageKey) {
const std::string kPrimaryKeyStr = "1";
- base::Optional<sync_pb::PasswordSpecifics> optional_specifics =
+ absl::optional<sync_pb::PasswordSpecifics> optional_specifics =
GetDataFromBridge(/*storage_key=*/kPrimaryKeyStr);
EXPECT_FALSE(optional_specifics.has_value());
}
@@ -821,7 +821,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldMergeSyncRemoteAndLocalPasswords) {
entity_change_list.push_back(syncer::EntityChange::CreateAdd(
/*storage_key=*/"", SpecificsToEntity(specifics3)));
- base::Optional<syncer::ModelError> error = bridge()->MergeSyncData(
+ absl::optional<syncer::ModelError> error = bridge()->MergeSyncData(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -875,7 +875,7 @@ TEST_P(PasswordSyncBridgeTest,
/*storage_key=*/"", SpecificsToEntity(specifics1)));
entity_change_list.push_back(syncer::EntityChange::CreateAdd(
/*storage_key=*/"", SpecificsToEntity(specifics2)));
- base::Optional<syncer::ModelError> error = bridge()->MergeSyncData(
+ absl::optional<syncer::ModelError> error = bridge()->MergeSyncData(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -905,7 +905,7 @@ TEST_P(PasswordSyncBridgeTest,
// Simulate a failed ReadAllLogins() by returning a kDbError.
ON_CALL(*mock_password_store_sync(), ReadAllLogins)
.WillByDefault(testing::Return(FormRetrievalResult::kDbError));
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
bridge()->MergeSyncData(bridge()->CreateMetadataChangeList(), {});
EXPECT_TRUE(error);
}
@@ -922,7 +922,7 @@ TEST_P(PasswordSyncBridgeTest,
SpecificsToEntity(CreateSpecificsWithSignonRealm(kSignonRealm1))));
EXPECT_CALL(*mock_password_store_sync(), RollbackTransaction());
- base::Optional<syncer::ModelError> error = bridge()->MergeSyncData(
+ absl::optional<syncer::ModelError> error = bridge()->MergeSyncData(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_TRUE(error);
}
@@ -944,7 +944,7 @@ TEST_P(
metadata_changes->UpdateModelTypeState(model_type_state);
EXPECT_CALL(*mock_password_store_sync(), RollbackTransaction());
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
bridge()->MergeSyncData(std::move(metadata_changes), {});
EXPECT_TRUE(error);
}
@@ -963,7 +963,7 @@ TEST_P(PasswordSyncBridgeTest,
syncer::EntityChangeList entity_change_list;
entity_change_list.push_back(syncer::EntityChange::CreateAdd(
/*storage_key=*/"", SpecificsToEntity(specifics)));
- base::Optional<syncer::ModelError> error = bridge()->MergeSyncData(
+ absl::optional<syncer::ModelError> error = bridge()->MergeSyncData(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -1030,7 +1030,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldDeleteUndecryptableLoginsDuringMerge) {
.WillOnce(Return(FormRetrievalResult::kSuccess));
EXPECT_CALL(*mock_password_store_sync(), DeleteUndecryptableLogins());
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
bridge()->MergeSyncData(bridge()->CreateMetadataChangeList(), {});
EXPECT_FALSE(error);
}
@@ -1055,7 +1055,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldNotifyOnSyncEnable) {
/*storage_key=*/"",
SpecificsToEntity(CreateSpecificsWithSignonRealm(kSignonRealm1))));
- base::Optional<syncer::ModelError> error = bridge()->MergeSyncData(
+ absl::optional<syncer::ModelError> error = bridge()->MergeSyncData(
bridge()->CreateMetadataChangeList(), std::move(initial_entity_data));
ASSERT_FALSE(error);
}
@@ -1075,7 +1075,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldNotNotifyOnSyncChange) {
/*storage_key=*/"",
SpecificsToEntity(CreateSpecificsWithSignonRealm(kSignonRealm1))));
- base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), std::move(entity_changes));
ASSERT_FALSE(error);
}
@@ -1232,7 +1232,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldReportDownloadedPasswordsIfAccountStore) {
/*storage_key=*/"", SpecificsToEntity(blocklisted_specifics)));
base::HistogramTester histogram_tester;
- base::Optional<syncer::ModelError> error = bridge()->MergeSyncData(
+ absl::optional<syncer::ModelError> error = bridge()->MergeSyncData(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
histogram_tester.ExpectUniqueSample(
@@ -1270,7 +1270,7 @@ TEST_P(PasswordSyncBridgeTest,
syncer::EntityChangeList entity_change_list;
entity_change_list.push_back(syncer::EntityChange::CreateAdd(
/*storage_key=*/"", SpecificsToEntity(specifics)));
- base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -1307,9 +1307,9 @@ TEST_P(PasswordSyncBridgeTest,
entity_change_list.push_back(syncer::EntityChange::CreateAdd(
/*storage_key=*/"", SpecificsToEntity(specifics)));
- base::Optional<syncer::ModelError> error = bridge()->MergeSyncData(
+ absl::optional<syncer::ModelError> error = bridge()->MergeSyncData(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
- EXPECT_EQ(error, base::nullopt);
+ EXPECT_EQ(error, absl::nullopt);
}
TEST_P(PasswordSyncBridgeTest, ShouldPutSecurityIssuesOnLoginChange) {
@@ -1358,7 +1358,7 @@ TEST_P(PasswordSyncBridgeTest, ShouldAddLocalSecurityIssuesDuringInitialMerge) {
mock_processor(),
Put(kPrimaryKeyStr1, EntityDataHasSecurityIssueTypes(kIssuesTypes), _));
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
bridge()->MergeSyncData(bridge()->CreateMetadataChangeList(), {});
EXPECT_FALSE(error);
}
@@ -1376,7 +1376,7 @@ TEST_P(PasswordSyncBridgeTest, GetDataWithIssuesForStorageKey) {
fake_db()->AddInsecureCredentials(
MakeInsecureCredentials(kForm, kIssuesTypes));
- base::Optional<sync_pb::PasswordSpecifics> optional_specifics =
+ absl::optional<sync_pb::PasswordSpecifics> optional_specifics =
GetDataFromBridge(/*storage_key=*/kPrimaryKeyStr1);
ASSERT_TRUE(optional_specifics.has_value());
ASSERT_TRUE(SpecificsHasExpectedInsecureTypes(
@@ -1410,7 +1410,7 @@ TEST_P(PasswordSyncBridgeTest,
syncer::EntityChangeList entity_change_list;
entity_change_list.push_back(syncer::EntityChange::CreateUpdate(
kStorageKey, SpecificsToEntity(specifics)));
- base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -1455,7 +1455,7 @@ TEST_P(PasswordSyncBridgeTest,
syncer::EntityChangeList entity_change_list;
entity_change_list.push_back(syncer::EntityChange::CreateUpdate(
kStorageKey, SpecificsToEntity(specifics)));
- base::Optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
+ absl::optional<syncer::ModelError> error = bridge()->ApplySyncChanges(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -1501,7 +1501,7 @@ TEST_P(PasswordSyncBridgeTest,
syncer::EntityChangeList entity_change_list;
entity_change_list.push_back(syncer::EntityChange::CreateAdd(
kStorageKey, SpecificsToEntity(specifics)));
- base::Optional<syncer::ModelError> error = bridge()->MergeSyncData(
+ absl::optional<syncer::ModelError> error = bridge()->MergeSyncData(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
@@ -1540,7 +1540,7 @@ TEST_P(PasswordSyncBridgeTest,
syncer::EntityChangeList entity_change_list;
entity_change_list.push_back(syncer::EntityChange::CreateAdd(
kStorageKey, SpecificsToEntity(specifics)));
- base::Optional<syncer::ModelError> error = bridge()->MergeSyncData(
+ absl::optional<syncer::ModelError> error = bridge()->MergeSyncData(
bridge()->CreateMetadataChangeList(), std::move(entity_change_list));
EXPECT_FALSE(error);
}
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 a3d6c028f5a..9dacb2ab1d0 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
@@ -178,8 +178,9 @@ TEST_P(CredentialsFilterTest, ReportFormLoginSuccess_NewSyncCredentials) {
TEST_P(CredentialsFilterTest, ReportFormLoginSuccess_GAIANotSyncCredentials) {
const char kOtherUsername[] = "other_user@gmail.com";
+ const char16_t kOtherUsername16[] = u"other_user@gmail.com";
FakeSigninAs(kOtherUsername);
- ASSERT_NE(pending_.username_value, base::ASCIIToUTF16(kOtherUsername));
+ ASSERT_NE(pending_.username_value, kOtherUsername16);
SetSyncingPasswords(true);
base::UserActionTester tester;
diff --git a/chromium/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter_unittest.cc b/chromium/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter_unittest.cc
index bdf628e2088..470f9df70e7 100644
--- a/chromium/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter_unittest.cc
+++ b/chromium/components/password_manager/core/browser/ui/bulk_leak_check_service_adapter_unittest.cc
@@ -36,11 +36,11 @@ namespace {
constexpr char kExampleCom[] = "https://example.com";
constexpr char kExampleOrg[] = "https://example.org";
-constexpr char kUsername1[] = "alice";
-constexpr char kUsername2[] = "bob";
+constexpr char16_t kUsername1[] = u"alice";
+constexpr char16_t kUsername2[] = u"bob";
-constexpr char kPassword1[] = "f00b4r";
-constexpr char kPassword2[] = "s3cr3t";
+constexpr char16_t kPassword1[] = u"f00b4r";
+constexpr char16_t kPassword2[] = u"s3cr3t";
using ::testing::ByMove;
using ::testing::NiceMock;
@@ -65,19 +65,19 @@ MATCHER_P(SavedPasswordsAre, passwords, "") {
}
PasswordForm MakeSavedPassword(base::StringPiece signon_realm,
- base::StringPiece username,
- base::StringPiece password) {
+ base::StringPiece16 username,
+ base::StringPiece16 password) {
PasswordForm form;
form.signon_realm = std::string(signon_realm);
- form.username_value = base::ASCIIToUTF16(username);
- form.password_value = base::ASCIIToUTF16(password);
+ form.username_value = std::u16string(username);
+ form.password_value = std::u16string(password);
return form;
}
-LeakCheckCredential MakeLeakCheckCredential(base::StringPiece username,
- base::StringPiece password) {
- return LeakCheckCredential(base::ASCIIToUTF16(username),
- base::ASCIIToUTF16(password));
+LeakCheckCredential MakeLeakCheckCredential(base::StringPiece16 username,
+ base::StringPiece16 password) {
+ return LeakCheckCredential(std::u16string(username),
+ std::u16string(password));
}
struct MockBulkLeakCheck : BulkLeakCheck {
@@ -189,9 +189,9 @@ TEST_F(BulkLeakCheckServiceAdapterTest, StartBulkLeakCheckAttachesData) {
// correctly deduped before starting the leak check.
TEST_F(BulkLeakCheckServiceAdapterTest, StartBulkLeakCheckDedupes) {
std::vector<PasswordForm> passwords = {
- MakeSavedPassword(kExampleCom, "alice", kPassword1),
- MakeSavedPassword(kExampleCom, "ALICE", kPassword1),
- MakeSavedPassword(kExampleCom, "Alice@example.com", kPassword1)};
+ MakeSavedPassword(kExampleCom, u"alice", kPassword1),
+ MakeSavedPassword(kExampleCom, u"ALICE", kPassword1),
+ MakeSavedPassword(kExampleCom, u"Alice@example.com", kPassword1)};
store().AddLogin(passwords[0]);
store().AddLogin(passwords[1]);
@@ -206,14 +206,14 @@ TEST_F(BulkLeakCheckServiceAdapterTest, StartBulkLeakCheckDedupes) {
adapter().StartBulkLeakCheck();
std::vector<LeakCheckCredential> expected;
- expected.push_back(MakeLeakCheckCredential("alice", kPassword1));
+ expected.push_back(MakeLeakCheckCredential(u"alice", kPassword1));
EXPECT_THAT(credentials, CredentialsAre(std::cref(expected)));
}
// Checks that trying to start a leak check when another check is already
// running does nothing and returns false to the caller.
TEST_F(BulkLeakCheckServiceAdapterTest, MultipleStarts) {
- store().AddLogin(MakeSavedPassword(kExampleCom, "alice", kPassword1));
+ store().AddLogin(MakeSavedPassword(kExampleCom, u"alice", kPassword1));
RunUntilIdle();
auto leak_check = std::make_unique<NiceMockBulkLeakCheck>();
@@ -230,7 +230,7 @@ TEST_F(BulkLeakCheckServiceAdapterTest, MultipleStarts) {
// Checks that stopping the leak check correctly resets the state of the bulk
// leak check.
TEST_F(BulkLeakCheckServiceAdapterTest, StopBulkLeakCheck) {
- store().AddLogin(MakeSavedPassword(kExampleCom, "alice", kPassword1));
+ store().AddLogin(MakeSavedPassword(kExampleCom, u"alice", kPassword1));
RunUntilIdle();
auto leak_check = std::make_unique<NiceMockBulkLeakCheck>();
@@ -263,7 +263,7 @@ TEST_F(BulkLeakCheckServiceAdapterTest, OnEditedNoPrefs) {
RunUntilIdle();
EXPECT_CALL(factory(), TryCreateBulkLeakCheck).Times(0);
- presenter().EditPassword(password, base::ASCIIToUTF16(kPassword2));
+ presenter().EditPassword(password, kPassword2);
}
// Tests that editing a password through the presenter will result in another
@@ -287,7 +287,7 @@ TEST_F(BulkLeakCheckServiceAdapterTest, OnEditedWithPrefs) {
CheckCredentials(CredentialsAre(std::cref(expected))));
EXPECT_CALL(factory(), TryCreateBulkLeakCheck)
.WillOnce(Return(ByMove(std::move(leak_check))));
- presenter().EditPassword(password, base::ASCIIToUTF16(kPassword2));
+ presenter().EditPassword(password, kPassword2);
}
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager.cc b/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
index 916d9b6057a..8a1150077ad 100644
--- a/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
+++ b/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/containers/flat_set.h"
+#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/ranges/algorithm.h"
#include "base/strings/utf_string_conversions.h"
@@ -23,9 +24,12 @@
#include "components/password_manager/core/browser/password_list_sorter.h"
#include "components/password_manager/core/browser/ui/credential_utils.h"
#include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
-#include "components/password_manager/core/browser/ui/weak_check_utility.h"
#include "components/password_manager/core/common/password_manager_features.h"
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#include "components/password_manager/core/browser/ui/weak_check_utility.h"
+#endif
+
namespace password_manager {
// Extra information about InsecureCredential which is required by UI.
@@ -163,6 +167,8 @@ std::vector<CredentialWithPassword> ExtractInsecureCredentials(
return credentials;
}
+// The function is only used by the weak check.
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
base::flat_set<std::u16string> ExtractPasswords(
SavedPasswordsPresenter::SavedPasswordsView password_forms) {
std::vector<std::u16string> passwords;
@@ -172,6 +178,7 @@ base::flat_set<std::u16string> ExtractPasswords(
}
return base::flat_set<std::u16string>(std::move(passwords));
}
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
} // namespace
@@ -238,6 +245,7 @@ void InsecureCredentialsManager::Init() {
insecure_credentials_reader_.Init();
}
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
void InsecureCredentialsManager::StartWeakCheck(
base::OnceClosure on_check_done) {
base::ThreadPool::PostTaskAndReplyWithResult(
@@ -248,6 +256,7 @@ void InsecureCredentialsManager::StartWeakCheck(
weak_ptr_factory_.GetWeakPtr(), base::ElapsedTimer())
.Then(std::move(on_check_done)));
}
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
void InsecureCredentialsManager::SaveInsecureCredential(
const LeakCheckCredential& credential) {
diff --git a/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager.h b/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager.h
index 0708260b152..31682b3f11f 100644
--- a/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager.h
+++ b/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager.h
@@ -18,6 +18,7 @@
#include "base/scoped_observation.h"
#include "base/timer/elapsed_timer.h"
#include "base/types/strong_alias.h"
+#include "build/build_config.h"
#include "components/password_manager/core/browser/insecure_credentials_table.h"
#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
#include "components/password_manager/core/browser/password_store.h"
@@ -163,9 +164,11 @@ class InsecureCredentialsManager : public InsecureCredentialsReader::Observer,
void Init();
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
// Computes weak credentials in a separate thread and then passes the result
// to OnWeakCheckDone.
void StartWeakCheck(base::OnceClosure on_check_done = base::DoNothing());
+#endif
// Marks all saved credentials which have same username & password as
// insecure.
diff --git a/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc b/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
index 15848185f0f..bf32c3e92e5 100644
--- a/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
+++ b/chromium/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
@@ -26,25 +26,31 @@ namespace {
constexpr char kExampleCom[] = "https://example.com";
constexpr char kExampleOrg[] = "https://example.org";
-constexpr char kUsername1[] = "alice";
-constexpr char kUsername2[] = "bob";
+constexpr char16_t kUsername1[] = u"alice";
+constexpr char16_t kUsername2[] = u"bob";
-constexpr char kPassword1[] = "f00b4r";
+constexpr char16_t kPassword1[] = u"f00b4r";
constexpr char kPassword2[] = "s3cr3t";
-constexpr char kPassword3[] = "484her";
+constexpr char16_t kPassword216[] = u"s3cr3t";
+constexpr char16_t kPassword3[] = u"484her";
-constexpr char kWeakPassword1[] = "123456";
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
+constexpr char16_t kWeakPassword1[] = u"123456";
constexpr char kWeakPassword2[] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcda";
+constexpr char16_t kWeakPassword216[] =
+ u"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcda";
constexpr char kStrongPassword1[] = "fnlsr4@cm^mdls@fkspnsg3d";
-constexpr char kStrongPassword2[] = "pmsFlsnoab4nsl#losb@skpfnsbkjb^klsnbs!cns";
+constexpr char16_t kStrongPassword116[] = u"fnlsr4@cm^mdls@fkspnsg3d";
+constexpr char16_t kStrongPassword2[] =
+ u"pmsFlsnoab4nsl#losb@skpfnsbkjb^klsnbs!cns";
+// Delay in milliseconds.
+constexpr int kDelay = 2;
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
using ::testing::ElementsAre;
using ::testing::ElementsAreArray;
using ::testing::IsEmpty;
-// Delay in milliseconds.
-const int kDelay = 2;
-
struct MockInsecureCredentialsManagerObserver
: InsecureCredentialsManager::Observer {
MOCK_METHOD(void,
@@ -59,30 +65,29 @@ using StrictMockInsecureCredentialsManagerObserver =
InsecureCredential MakeInsecureCredential(
std::string signon_realm,
- base::StringPiece username,
+ base::StringPiece16 username,
InsecureType type = InsecureType::kLeaked) {
- return InsecureCredential(std::move(signon_realm),
- base::ASCIIToUTF16(username), base::Time(), type,
- IsMuted(false));
+ return InsecureCredential(std::move(signon_realm), std::u16string(username),
+ base::Time(), type, IsMuted(false));
}
PasswordForm MakeSavedPassword(base::StringPiece signon_realm,
- base::StringPiece username,
- base::StringPiece password,
- base::StringPiece username_element = "") {
+ base::StringPiece16 username,
+ base::StringPiece16 password,
+ base::StringPiece16 username_element = u"") {
PasswordForm form;
form.signon_realm = std::string(signon_realm);
form.url = GURL(signon_realm);
- form.username_value = base::ASCIIToUTF16(username);
- form.password_value = base::ASCIIToUTF16(password);
- form.username_element = base::ASCIIToUTF16(username_element);
+ form.username_value = std::u16string(username);
+ form.password_value = std::u16string(password);
+ form.username_element = std::u16string(username_element);
return form;
}
-LeakCheckCredential MakeLeakCredential(base::StringPiece username,
- base::StringPiece password) {
- return LeakCheckCredential(base::ASCIIToUTF16(username),
- base::ASCIIToUTF16(password));
+LeakCheckCredential MakeLeakCredential(base::StringPiece16 username,
+ base::StringPiece16 password) {
+ return LeakCheckCredential(std::u16string(username),
+ std::u16string(password));
}
CredentialWithPassword MakeCompromisedCredential(
@@ -97,6 +102,7 @@ CredentialWithPassword MakeCompromisedCredential(
return credential_with_password;
}
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
CredentialWithPassword MakeWeakCredential(const PasswordForm& form) {
CredentialWithPassword weak_credential{CredentialView(form)};
weak_credential.insecure_type = InsecureCredentialTypeFlags::kWeakCredential;
@@ -112,6 +118,7 @@ CredentialWithPassword MakeWeakAndCompromisedCredential(
InsecureCredentialTypeFlags::kWeakCredential;
return credential_with_password;
}
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
class InsecureCredentialsManagerTest : public ::testing::Test {
protected:
@@ -130,17 +137,17 @@ class InsecureCredentialsManagerTest : public ::testing::Test {
// Returns saved password if it matches with |signon_realm| and |username|.
// Otherwise, returns an empty string, because the saved password should never
// be empty, unless it's a federated credential or "Never save" entry.
- std::string GetSavedPasswordForUsername(const std::string& signon_realm,
- const std::string& username) {
+ std::u16string GetSavedPasswordForUsername(const std::string& signon_realm,
+ const std::u16string& username) {
SavedPasswordsPresenter::SavedPasswordsView saved_passwords =
presenter_.GetSavedPasswords();
for (const auto& form : saved_passwords) {
if (form.signon_realm == signon_realm &&
- form.username_value == base::UTF8ToUTF16(username)) {
- return base::UTF16ToUTF8(form.password_value);
+ form.username_value == username) {
+ return form.password_value;
}
}
- return std::string();
+ return std::u16string();
}
base::HistogramTester& histogram_tester() { return histogram_tester_; }
@@ -239,7 +246,7 @@ TEST_F(InsecureCredentialsManagerTest,
RunUntilIdle();
// Updating a saved password should notify observers.
- saved_password.password_value = base::ASCIIToUTF16(kPassword2);
+ saved_password.password_value = kPassword216;
EXPECT_CALL(observer, OnInsecureCredentialsChanged);
EXPECT_CALL(observer, OnWeakCredentialsChanged);
store().UpdateLogin(saved_password);
@@ -305,7 +312,7 @@ TEST_F(InsecureCredentialsManagerTest, JoinPhishedAndLeaked) {
TEST_F(InsecureCredentialsManagerTest, ReactToChangesInBothTables) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kPassword1),
- MakeSavedPassword(kExampleCom, kUsername2, kPassword2)};
+ MakeSavedPassword(kExampleCom, kUsername2, kPassword216)};
std::vector<InsecureCredential> credentials = {
MakeInsecureCredential(kExampleCom, kUsername1),
@@ -345,7 +352,7 @@ TEST_F(InsecureCredentialsManagerTest, ReactToChangesInBothTables) {
TEST_F(InsecureCredentialsManagerTest, JoinMultipleCredentials) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kPassword1),
- MakeSavedPassword(kExampleCom, kUsername2, kPassword2)};
+ MakeSavedPassword(kExampleCom, kUsername2, kPassword216)};
std::vector<InsecureCredential> credentials = {
MakeInsecureCredential(kExampleCom, kUsername1),
@@ -371,7 +378,7 @@ TEST_F(InsecureCredentialsManagerTest, JoinMultipleCredentials) {
TEST_F(InsecureCredentialsManagerTest, JoinWitDifferentUsername) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername2, kPassword1),
- MakeSavedPassword(kExampleCom, kUsername2, kPassword2)};
+ MakeSavedPassword(kExampleCom, kUsername2, kPassword216)};
InsecureCredential credential =
MakeInsecureCredential(kExampleCom, kUsername1);
@@ -389,7 +396,7 @@ TEST_F(InsecureCredentialsManagerTest, JoinWitDifferentUsername) {
TEST_F(InsecureCredentialsManagerTest, JoinWitDifferentSignonRealm) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleOrg, kUsername1, kPassword1),
- MakeSavedPassword(kExampleOrg, kUsername1, kPassword2)};
+ MakeSavedPassword(kExampleOrg, kUsername1, kPassword216)};
InsecureCredential credential =
MakeInsecureCredential(kExampleCom, kUsername1);
@@ -407,8 +414,8 @@ TEST_F(InsecureCredentialsManagerTest, JoinWitDifferentSignonRealm) {
// when the passwords are distinct.
TEST_F(InsecureCredentialsManagerTest, JoinWithMultipleDistinctPasswords) {
std::vector<PasswordForm> passwords = {
- MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"),
- MakeSavedPassword(kExampleCom, kUsername1, kPassword2, "element_2")};
+ MakeSavedPassword(kExampleCom, kUsername1, kPassword1, u"element_1"),
+ MakeSavedPassword(kExampleCom, kUsername1, kPassword216, u"element_2")};
InsecureCredential credential =
MakeInsecureCredential(kExampleCom, kUsername1);
@@ -434,8 +441,8 @@ TEST_F(InsecureCredentialsManagerTest, JoinWithMultipleRepeatedPasswords) {
InsecureCredential credential =
MakeInsecureCredential(kExampleCom, kUsername1);
std::vector<PasswordForm> passwords = {
- MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"),
- MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_2")};
+ MakeSavedPassword(kExampleCom, kUsername1, kPassword1, u"element_1"),
+ MakeSavedPassword(kExampleCom, kUsername1, kPassword1, u"element_2")};
store().AddLogin(passwords[0]);
store().AddLogin(passwords[1]);
@@ -452,9 +459,9 @@ TEST_F(InsecureCredentialsManagerTest, JoinWithMultipleRepeatedPasswords) {
// correctly.
TEST_F(InsecureCredentialsManagerTest, MapCompromisedPasswordsToPasswords) {
std::vector<PasswordForm> passwords = {
- MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"),
- MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_2"),
- MakeSavedPassword(kExampleOrg, kUsername2, kPassword2)};
+ MakeSavedPassword(kExampleCom, kUsername1, kPassword1, u"element_1"),
+ MakeSavedPassword(kExampleCom, kUsername1, kPassword1, u"element_2"),
+ MakeSavedPassword(kExampleOrg, kUsername2, kPassword216)};
std::vector<InsecureCredential> credentials = {
MakeInsecureCredential(kExampleCom, kUsername1),
@@ -482,6 +489,7 @@ TEST_F(InsecureCredentialsManagerTest, MapCompromisedPasswordsToPasswords) {
ElementsAreArray(store().stored_passwords().at(kExampleOrg)));
}
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
TEST_F(InsecureCredentialsManagerTest, StartWeakCheckNotifiesOnCompletion) {
base::MockOnceClosure closure;
provider().StartWeakCheck(closure.Get());
@@ -511,7 +519,7 @@ TEST_F(InsecureCredentialsManagerTest, StartWeakCheckOnEmptyPasswordsList) {
TEST_F(InsecureCredentialsManagerTest, WeakCredentialsNotFound) {
std::vector<PasswordForm> passwords = {
- MakeSavedPassword(kExampleCom, kUsername1, kStrongPassword1),
+ MakeSavedPassword(kExampleCom, kUsername1, kStrongPassword116),
MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword2)};
store().AddLogin(passwords[0]);
@@ -540,7 +548,7 @@ TEST_F(InsecureCredentialsManagerTest, WeakCredentialsNotFound) {
TEST_F(InsecureCredentialsManagerTest, DetectedWeakCredential) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1),
- MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword1)};
+ MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword116)};
store().AddLogin(passwords[0]);
store().AddLogin(passwords[1]);
@@ -557,7 +565,7 @@ TEST_F(InsecureCredentialsManagerTest, DetectedWeakCredential) {
provider().GetWeakCredentials();
ASSERT_EQ(weak_credentials.size(), 1u);
- EXPECT_EQ(base::UTF16ToUTF8(weak_credentials[0].password), kWeakPassword1);
+ EXPECT_EQ(weak_credentials[0].password, kWeakPassword1);
EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type));
histogram_tester().ExpectUniqueSample(
@@ -575,8 +583,9 @@ TEST_F(InsecureCredentialsManagerTest, DetectedWeakCredential) {
TEST_F(InsecureCredentialsManagerTest,
FindBothWeakCredentialsWithDifferentPasswords) {
std::vector<PasswordForm> passwords = {
- MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_1"),
- MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword2, "element_2")};
+ MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, u"element_1"),
+ MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword216,
+ u"element_2")};
store().AddLogin(passwords[0]);
store().AddLogin(passwords[1]);
@@ -608,8 +617,8 @@ TEST_F(InsecureCredentialsManagerTest,
TEST_F(InsecureCredentialsManagerTest,
JoinWeakCredentialsWithTheSamePasswords) {
std::vector<PasswordForm> passwords = {
- MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_1"),
- MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_2")};
+ MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, u"element_1"),
+ MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, u"element_2")};
store().AddLogin(passwords[0]);
store().AddLogin(passwords[1]);
@@ -623,7 +632,7 @@ TEST_F(InsecureCredentialsManagerTest,
provider().GetWeakCredentials();
ASSERT_EQ(weak_credentials.size(), 1u);
- EXPECT_EQ(base::UTF16ToUTF8(weak_credentials[0].password), kWeakPassword1);
+ EXPECT_EQ(weak_credentials[0].password, kWeakPassword1);
EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type));
histogram_tester().ExpectUniqueSample(
@@ -639,7 +648,7 @@ TEST_F(InsecureCredentialsManagerTest,
TEST_F(InsecureCredentialsManagerTest, BothWeakAndCompromisedCredentialsExist) {
std::vector<PasswordForm> passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1),
- MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword1)};
+ MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword116)};
std::vector<InsecureCredential> compromised_credentials = {
MakeInsecureCredential(kExampleCom, kUsername1),
MakeInsecureCredential(kExampleCom, kUsername2)};
@@ -660,8 +669,7 @@ TEST_F(InsecureCredentialsManagerTest, BothWeakAndCompromisedCredentialsExist) {
provider().GetInsecureCredentials();
ASSERT_EQ(returned_weak_credentials.size(), 1u);
- EXPECT_EQ(base::UTF16ToUTF8(returned_weak_credentials[0].password),
- kWeakPassword1);
+ EXPECT_EQ(returned_weak_credentials[0].password, kWeakPassword1);
EXPECT_TRUE(IsWeak(returned_weak_credentials[0].insecure_type));
ASSERT_EQ(returned_compromised_credentials.size(), 2u);
@@ -704,14 +712,12 @@ TEST_F(InsecureCredentialsManagerTest, SingleCredentialIsWeakAndCompromised) {
// weak and compromised for elements from |returned_weak_credentials| and
// |returned_compromised_credentials|.
ASSERT_EQ(returned_weak_credentials.size(), 1u);
- EXPECT_EQ(base::UTF16ToUTF8(returned_weak_credentials[0].password),
- kWeakPassword1);
+ EXPECT_EQ(returned_weak_credentials[0].password, kWeakPassword1);
EXPECT_TRUE(IsWeak(returned_weak_credentials[0].insecure_type));
EXPECT_TRUE(IsInsecure(returned_weak_credentials[0].insecure_type));
ASSERT_EQ(returned_compromised_credentials.size(), 1u);
- EXPECT_EQ(base::UTF16ToUTF8(returned_compromised_credentials[0].password),
- kWeakPassword1);
+ EXPECT_EQ(returned_compromised_credentials[0].password, kWeakPassword1);
EXPECT_TRUE(IsWeak(returned_compromised_credentials[0].insecure_type));
EXPECT_TRUE(IsInsecure(returned_compromised_credentials[0].insecure_type));
@@ -724,6 +730,7 @@ TEST_F(InsecureCredentialsManagerTest, SingleCredentialIsWeakAndCompromised) {
histogram_tester().ExpectUniqueSample(
"PasswordManager.WeakCheck.PasswordScore", 0, 1);
}
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
// Test verifies that saving LeakCheckCredential via provider adds expected
// compromised credential.
@@ -768,11 +775,12 @@ TEST_F(InsecureCredentialsManagerTest, UpdateCompromisedPassword) {
EXPECT_TRUE(provider().UpdateCredential(expected, kPassword2));
RunUntilIdle();
- expected.password = base::UTF8ToUTF16(kPassword2);
+ expected.password = kPassword216;
EXPECT_THAT(provider().GetInsecureCredentials(), ElementsAre(expected));
}
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
// Test verifies that editing weak credential via provider has affect on weak
// credentials and updates password in the store.
TEST_F(InsecureCredentialsManagerTest, UpdateWeakPassword) {
@@ -791,10 +799,9 @@ TEST_F(InsecureCredentialsManagerTest, UpdateWeakPassword) {
EXPECT_THAT(provider().GetWeakCredentials(), IsEmpty());
EXPECT_EQ(GetSavedPasswordForUsername(kExampleCom, kUsername1),
- kStrongPassword1);
+ kStrongPassword116);
}
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
// Test verifies that editing a weak credential to another weak credential
// continues to be treated weak.
TEST_F(InsecureCredentialsManagerTest, UpdatedWeakPasswordRemainsWeak) {
@@ -813,10 +820,9 @@ TEST_F(InsecureCredentialsManagerTest, UpdatedWeakPasswordRemainsWeak) {
EXPECT_TRUE(provider().UpdateCredential(expected, kWeakPassword2));
RunUntilIdle();
- expected.password = base::ASCIIToUTF16(kWeakPassword2);
+ expected.password = kWeakPassword216;
EXPECT_THAT(provider().GetWeakCredentials(), ElementsAre(expected));
}
-#endif
// Test verifies that editing credential that is weak and compromised via
// provider change the saved password.
@@ -841,8 +847,9 @@ TEST_F(InsecureCredentialsManagerTest, UpdateInsecurePassword) {
RunUntilIdle();
EXPECT_EQ(GetSavedPasswordForUsername(kExampleCom, kUsername1),
- kStrongPassword1);
+ kStrongPassword116);
}
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
TEST_F(InsecureCredentialsManagerTest, RemoveCompromisedCredential) {
InsecureCredential credential =
@@ -865,6 +872,7 @@ TEST_F(InsecureCredentialsManagerTest, RemoveCompromisedCredential) {
EXPECT_THAT(provider().GetInsecureCredentials(), IsEmpty());
}
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
TEST_F(InsecureCredentialsManagerTest, RemoveWeakCredential) {
PasswordForm password =
MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1);
@@ -906,10 +914,10 @@ TEST_F(InsecureCredentialsManagerTest, RemoveInsecureCredential) {
// CreateSortKey.
TEST_F(InsecureCredentialsManagerTest, GetWeakCredentialsReturnsSortedData) {
const std::vector<PasswordForm> password_forms = {
- MakeSavedPassword("http://example-a.com", "user_a1", "pwd"),
- MakeSavedPassword("http://example-a.com", "user_a2", "pwd"),
- MakeSavedPassword("http://example-b.com", "user_a", "pwd"),
- MakeSavedPassword("http://example-c.com", "user_a", "pwd")};
+ MakeSavedPassword("http://example-a.com", u"user_a1", u"pwd"),
+ MakeSavedPassword("http://example-a.com", u"user_a2", u"pwd"),
+ MakeSavedPassword("http://example-b.com", u"user_a", u"pwd"),
+ MakeSavedPassword("http://example-c.com", u"user_a", u"pwd")};
store().AddLogin(password_forms[0]);
store().AddLogin(password_forms[1]);
store().AddLogin(password_forms[2]);
@@ -925,6 +933,7 @@ TEST_F(InsecureCredentialsManagerTest, GetWeakCredentialsReturnsSortedData) {
MakeWeakCredential(password_forms[2]),
MakeWeakCredential(password_forms[3])));
}
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
namespace {
class InsecureCredentialsManagerWithTwoStoresTest : public ::testing::Test {
@@ -974,7 +983,7 @@ TEST_F(InsecureCredentialsManagerWithTwoStoresTest,
std::vector<PasswordForm> account_store_passwords = {
MakeSavedPassword(kExampleCom, kUsername1, kPassword3),
- MakeSavedPassword(kExampleOrg, kUsername1, kPassword2)};
+ MakeSavedPassword(kExampleOrg, kUsername1, kPassword216)};
for (const PasswordForm& account_password : account_store_passwords)
account_store().AddLogin(account_password);
@@ -991,24 +1000,20 @@ TEST_F(InsecureCredentialsManagerWithTwoStoresTest,
// their store.
EXPECT_THAT(
provider().GetSavedPasswordsFor(
- CredentialView(kExampleCom, GURL(), base::ASCIIToUTF16(kUsername1),
- base::ASCIIToUTF16(kPassword1))),
+ CredentialView(kExampleCom, GURL(), kUsername1, kPassword1)),
ElementsAreArray(profile_store().stored_passwords().at(kExampleCom)));
- EXPECT_THAT(provider().GetSavedPasswordsFor(CredentialView(
- kExampleOrg, GURL(), base::ASCIIToUTF16(kUsername1),
- base::ASCIIToUTF16(kPassword3))),
+ EXPECT_THAT(provider().GetSavedPasswordsFor(
+ CredentialView(kExampleOrg, GURL(), kUsername1, kPassword3)),
IsEmpty());
- EXPECT_THAT(provider().GetSavedPasswordsFor(CredentialView(
- kExampleCom, GURL(), base::ASCIIToUTF16(kUsername1),
- base::ASCIIToUTF16(kPassword3))),
+ EXPECT_THAT(provider().GetSavedPasswordsFor(
+ CredentialView(kExampleCom, GURL(), kUsername1, kPassword3)),
IsEmpty());
EXPECT_THAT(
provider().GetSavedPasswordsFor(
- CredentialView(kExampleOrg, GURL(), base::ASCIIToUTF16(kUsername1),
- base::ASCIIToUTF16(kPassword2))),
+ CredentialView(kExampleOrg, GURL(), kUsername1, kPassword216)),
ElementsAreArray(account_store().stored_passwords().at(kExampleOrg)));
}
@@ -1025,7 +1030,7 @@ TEST_F(InsecureCredentialsManagerWithTwoStoresTest, SaveCompromisedPassword) {
account_store().AddLogin(
MakeSavedPassword(kExampleOrg, kUsername1, kPassword1));
account_store().AddLogin(
- MakeSavedPassword(kExampleCom, kUsername1, kPassword2));
+ MakeSavedPassword(kExampleCom, kUsername1, kPassword216));
RunUntilIdle();
@@ -1039,7 +1044,8 @@ TEST_F(InsecureCredentialsManagerWithTwoStoresTest, SaveCompromisedPassword) {
// Now, mark `kUsername1`, `kPassword2` as compromised, a new entry should be
// added only to the account store.
- provider().SaveInsecureCredential(MakeLeakCredential(kUsername1, kPassword2));
+ provider().SaveInsecureCredential(
+ MakeLeakCredential(kUsername1, kPassword216));
RunUntilIdle();
EXPECT_EQ(1U, profile_store().insecure_credentials().size());
@@ -1063,8 +1069,7 @@ TEST_F(InsecureCredentialsManagerWithTwoStoresTest,
// Now remove the compromised credentials
EXPECT_TRUE(provider().RemoveCredential(
- CredentialView(kExampleCom, GURL(), base::ASCIIToUTF16(kUsername1),
- base::ASCIIToUTF16(kPassword1))));
+ CredentialView(kExampleCom, GURL(), kUsername1, kPassword1)));
RunUntilIdle();
// It should have been removed from both stores.
@@ -1072,6 +1077,7 @@ TEST_F(InsecureCredentialsManagerWithTwoStoresTest,
EXPECT_TRUE(account_store().stored_passwords().at(kExampleCom).empty());
}
+#if !defined(OS_ANDROID) && !defined(OS_IOS)
TEST_F(InsecureCredentialsManagerWithTwoStoresTest, RemoveWeakCredential) {
// Add `kUsername1`,`kPassword1` to both stores.
profile_store().AddLogin(
@@ -1084,13 +1090,13 @@ TEST_F(InsecureCredentialsManagerWithTwoStoresTest, RemoveWeakCredential) {
// Now remove the weak credential
EXPECT_TRUE(provider().RemoveCredential(
- CredentialView(kExampleCom, GURL(), base::ASCIIToUTF16(kUsername1),
- base::ASCIIToUTF16(kWeakPassword1))));
+ CredentialView(kExampleCom, GURL(), kUsername1, kWeakPassword1)));
RunUntilIdle();
// It should have been removed from both stores.
EXPECT_THAT(profile_store().stored_passwords().at(kExampleCom), IsEmpty());
EXPECT_THAT(account_store().stored_passwords().at(kExampleCom), IsEmpty());
}
+#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper.cc b/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper.cc
index a3ff3f77934..d575039b6ec 100644
--- a/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper.cc
+++ b/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper.cc
@@ -5,7 +5,9 @@
#include "components/password_manager/core/browser/ui/post_save_compromised_helper.h"
#include "base/containers/contains.h"
+#include "base/feature_list.h"
#include "components/password_manager/core/browser/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_service.h"
@@ -61,6 +63,13 @@ void PostSaveCompromisedHelper::OnGetAllInsecureCredentials(
std::vector<InsecureCredential> insecure_credentials) {
const bool compromised_password_changed =
current_leak_ && !base::Contains(insecure_credentials, *current_leak_);
+ if (base::FeatureList::IsEnabled(features::kMutingCompromisedCredentials)) {
+ // We want to show bubble even if updated insecure credentials was muted,
+ // this is why muted credentials are erased after computing
+ // 'compromised_password_changed';
+ base::EraseIf(insecure_credentials,
+ [](const auto& credential) { return credential.is_muted; });
+ }
if (compromised_password_changed) {
bubble_type_ = insecure_credentials.empty()
? BubbleType::kPasswordUpdatedSafeState
diff --git a/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper.h b/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper.h
index 008081b7e42..161e47b9926 100644
--- a/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper.h
+++ b/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper.h
@@ -9,10 +9,9 @@
#include "base/callback.h"
#include "base/containers/span.h"
-#include "base/optional.h"
-#include "base/time/time.h"
#include "components/password_manager/core/browser/insecure_credentials_table.h"
#include "components/password_manager/core/browser/ui/insecure_credentials_reader.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
@@ -62,7 +61,7 @@ class PostSaveCompromisedHelper {
std::vector<InsecureCredential> insecure_credentials);
// Contains the entry for the currently leaked credentials if it was leaked.
- base::Optional<InsecureCredential> current_leak_;
+ absl::optional<InsecureCredential> current_leak_;
// Callback to notify the caller about the bubble type.
BubbleCallback callback_;
// BubbleType after the callback was executed.
diff --git a/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper_unittest.cc b/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper_unittest.cc
index 36c2b5e7983..e03268df721 100644
--- a/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper_unittest.cc
+++ b/chromium/components/password_manager/core/browser/ui/post_save_compromised_helper_unittest.cc
@@ -4,11 +4,14 @@
#include "components/password_manager/core/browser/ui/post_save_compromised_helper.h"
+#include "base/feature_list.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "components/password_manager/core/browser/mock_password_store.h"
#include "components/password_manager/core/browser/password_form.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"
@@ -24,15 +27,16 @@ using testing::_;
using testing::Return;
constexpr char kSignonRealm[] = "https://example.com/";
-constexpr char kUsername[] = "user";
-constexpr char kUsername2[] = "user2";
+constexpr char16_t kUsername[] = u"user";
+constexpr char16_t kUsername2[] = u"user2";
+constexpr char16_t kUsername3[] = u"user3";
InsecureCredential CreateInsecureCredential(
- base::StringPiece username,
- PasswordForm::Store store = PasswordForm::Store::kProfileStore) {
- InsecureCredential compromised(kSignonRealm, base::ASCIIToUTF16(username),
- base::Time(), InsecureType::kLeaked,
- IsMuted(false));
+ base::StringPiece16 username,
+ PasswordForm::Store store = PasswordForm::Store::kProfileStore,
+ IsMuted muted = IsMuted(false)) {
+ InsecureCredential compromised(kSignonRealm, std::u16string(username),
+ base::Time(), InsecureType::kLeaked, muted);
compromised.in_store = store;
return compromised;
}
@@ -67,7 +71,7 @@ class PostSaveCompromisedHelperTest : public testing::Test {
};
TEST_F(PostSaveCompromisedHelperTest, DefaultState) {
- PostSaveCompromisedHelper helper({}, base::ASCIIToUTF16(kUsername));
+ PostSaveCompromisedHelper helper({}, kUsername);
EXPECT_EQ(BubbleType::kNoBubble, helper.bubble_type());
EXPECT_EQ(0u, helper.compromised_count());
}
@@ -76,7 +80,7 @@ TEST_F(PostSaveCompromisedHelperTest, EmptyStore) {
prefs()->SetDouble(
kLastTimePasswordCheckCompleted,
(base::Time::Now() - base::TimeDelta::FromMinutes(1)).ToDoubleT());
- PostSaveCompromisedHelper helper({}, base::ASCIIToUTF16(kUsername));
+ PostSaveCompromisedHelper helper({}, kUsername);
base::MockCallback<PostSaveCompromisedHelper::BubbleCallback> callback;
EXPECT_CALL(callback, Run(BubbleType::kNoBubble, 0));
EXPECT_CALL(*profile_store(), GetAllInsecureCredentialsImpl);
@@ -91,7 +95,7 @@ TEST_F(PostSaveCompromisedHelperTest, RandomSite_FullStore) {
prefs()->SetDouble(
kLastTimePasswordCheckCompleted,
(base::Time::Now() - base::TimeDelta::FromMinutes(1)).ToDoubleT());
- PostSaveCompromisedHelper helper({}, base::ASCIIToUTF16(kUsername));
+ PostSaveCompromisedHelper helper({}, kUsername);
base::MockCallback<PostSaveCompromisedHelper::BubbleCallback> callback;
EXPECT_CALL(callback, Run(BubbleType::kNoBubble, _));
std::vector<InsecureCredential> saved = {
@@ -111,7 +115,7 @@ TEST_F(PostSaveCompromisedHelperTest, CompromisedSite_ItemStayed) {
std::vector<InsecureCredential> saved = {
CreateInsecureCredential(kUsername),
CreateInsecureCredential(kUsername2)};
- PostSaveCompromisedHelper helper({saved}, base::ASCIIToUTF16(kUsername));
+ PostSaveCompromisedHelper helper({saved}, kUsername);
base::MockCallback<PostSaveCompromisedHelper::BubbleCallback> callback;
EXPECT_CALL(callback, Run(BubbleType::kNoBubble, _));
EXPECT_CALL(*profile_store(), GetAllInsecureCredentialsImpl)
@@ -129,7 +133,7 @@ TEST_F(PostSaveCompromisedHelperTest, CompromisedSite_ItemGone) {
std::vector<InsecureCredential> saved = {
CreateInsecureCredential(kUsername),
CreateInsecureCredential(kUsername2)};
- PostSaveCompromisedHelper helper({saved}, base::ASCIIToUTF16(kUsername));
+ PostSaveCompromisedHelper helper({saved}, kUsername);
base::MockCallback<PostSaveCompromisedHelper::BubbleCallback> callback;
EXPECT_CALL(callback, Run(BubbleType::kPasswordUpdatedWithMoreToFix, 1));
saved = {CreateInsecureCredential(kUsername2)};
@@ -144,7 +148,7 @@ TEST_F(PostSaveCompromisedHelperTest, CompromisedSite_ItemGone) {
TEST_F(PostSaveCompromisedHelperTest, FixedLast_BulkCheckNeverDone) {
std::vector<InsecureCredential> saved = {CreateInsecureCredential(kUsername)};
- PostSaveCompromisedHelper helper({saved}, base::ASCIIToUTF16(kUsername));
+ PostSaveCompromisedHelper helper({saved}, kUsername);
base::MockCallback<PostSaveCompromisedHelper::BubbleCallback> callback;
EXPECT_CALL(callback, Run(BubbleType::kNoBubble, 0));
EXPECT_CALL(*profile_store(), GetAllInsecureCredentialsImpl).Times(0);
@@ -160,7 +164,7 @@ TEST_F(PostSaveCompromisedHelperTest, FixedLast_BulkCheckDoneLongAgo) {
kLastTimePasswordCheckCompleted,
(base::Time::Now() - base::TimeDelta::FromDays(5)).ToDoubleT());
std::vector<InsecureCredential> saved = {CreateInsecureCredential(kUsername)};
- PostSaveCompromisedHelper helper({saved}, base::ASCIIToUTF16(kUsername));
+ PostSaveCompromisedHelper helper({saved}, kUsername);
base::MockCallback<PostSaveCompromisedHelper::BubbleCallback> callback;
EXPECT_CALL(callback, Run(BubbleType::kNoBubble, 0));
EXPECT_CALL(*profile_store(), GetAllInsecureCredentialsImpl).Times(0);
@@ -176,7 +180,7 @@ TEST_F(PostSaveCompromisedHelperTest, FixedLast_BulkCheckDoneRecently) {
kLastTimePasswordCheckCompleted,
(base::Time::Now() - base::TimeDelta::FromMinutes(1)).ToDoubleT());
std::vector<InsecureCredential> saved = {CreateInsecureCredential(kUsername)};
- PostSaveCompromisedHelper helper({saved}, base::ASCIIToUTF16(kUsername));
+ PostSaveCompromisedHelper helper({saved}, kUsername);
base::MockCallback<PostSaveCompromisedHelper::BubbleCallback> callback;
EXPECT_CALL(callback, Run(BubbleType::kPasswordUpdatedSafeState, 0));
saved = {};
@@ -189,6 +193,55 @@ TEST_F(PostSaveCompromisedHelperTest, FixedLast_BulkCheckDoneRecently) {
EXPECT_EQ(0u, helper.compromised_count());
}
+TEST_F(PostSaveCompromisedHelperTest, BubbleShownEvenIfIssueIsMuted) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(features::kMutingCompromisedCredentials,
+ true);
+
+ prefs()->SetDouble(
+ kLastTimePasswordCheckCompleted,
+ (base::Time::Now() - base::TimeDelta::FromMinutes(1)).ToDoubleT());
+ std::vector<InsecureCredential> saved = {CreateInsecureCredential(
+ kUsername, PasswordForm::Store::kProfileStore, IsMuted(true))};
+ PostSaveCompromisedHelper helper({saved}, kUsername);
+ base::MockCallback<PostSaveCompromisedHelper::BubbleCallback> callback;
+ EXPECT_CALL(callback, Run(BubbleType::kPasswordUpdatedSafeState, 0));
+ saved = {};
+ EXPECT_CALL(*profile_store(), GetAllInsecureCredentialsImpl)
+ .WillOnce(Return(saved));
+ helper.AnalyzeLeakedCredentials(profile_store(), account_store(), prefs(),
+ callback.Get());
+ WaitForPasswordStore();
+ EXPECT_EQ(BubbleType::kPasswordUpdatedSafeState, helper.bubble_type());
+ EXPECT_EQ(0u, helper.compromised_count());
+}
+
+TEST_F(PostSaveCompromisedHelperTest, MutedIssuesNotIncludedToCount) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(features::kMutingCompromisedCredentials,
+ true);
+
+ prefs()->SetDouble(
+ kLastTimePasswordCheckCompleted,
+ (base::Time::Now() - base::TimeDelta::FromMinutes(1)).ToDoubleT());
+ std::vector<InsecureCredential> saved = {CreateInsecureCredential(kUsername)};
+ PostSaveCompromisedHelper helper({saved}, kUsername);
+ base::MockCallback<PostSaveCompromisedHelper::BubbleCallback> callback;
+ EXPECT_CALL(callback, Run(BubbleType::kPasswordUpdatedWithMoreToFix, 1));
+ saved = {
+ CreateInsecureCredential(kUsername2),
+ CreateInsecureCredential(kUsername3, PasswordForm::Store::kProfileStore,
+ IsMuted(true)),
+ };
+ EXPECT_CALL(*profile_store(), GetAllInsecureCredentialsImpl)
+ .WillOnce(Return(saved));
+ helper.AnalyzeLeakedCredentials(profile_store(), account_store(), prefs(),
+ callback.Get());
+ WaitForPasswordStore();
+ EXPECT_EQ(BubbleType::kPasswordUpdatedWithMoreToFix, helper.bubble_type());
+ EXPECT_EQ(1u, helper.compromised_count());
+}
+
namespace {
class PostSaveCompromisedHelperWithTwoStoreTest
: public PostSaveCompromisedHelperTest {
@@ -226,8 +279,7 @@ TEST_F(PostSaveCompromisedHelperWithTwoStoreTest,
profile_store_compromised_credential,
account_store_compromised_credential};
- PostSaveCompromisedHelper helper({compromised_credentials},
- base::ASCIIToUTF16(kUsername));
+ PostSaveCompromisedHelper helper({compromised_credentials}, kUsername);
EXPECT_CALL(*profile_store(), GetAllInsecureCredentialsImpl)
.WillOnce(Return(std::vector<InsecureCredential>{
profile_store_compromised_credential}));
diff --git a/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter.cc b/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
index 493ef8fbffb..1a45808de08 100644
--- a/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
+++ b/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
@@ -19,6 +19,7 @@
namespace {
using password_manager::metrics_util::IsPasswordChanged;
using password_manager::metrics_util::IsUsernameChanged;
+using Store = password_manager::PasswordForm::Store;
using SavedPasswordsView =
password_manager::SavedPasswordsPresenter::SavedPasswordsView;
@@ -39,6 +40,13 @@ bool IsUsernameAlreadyUsed(SavedPasswordsView all_forms,
return base::ranges::any_of(all_forms, has_conflicting_username);
}
+// Returns trues if there is at least one password store that contains both
+// passwords.
+constexpr bool ShareSameStore(const password_manager::PasswordForm& lhs,
+ const password_manager::PasswordForm& rhs) {
+ return (lhs.in_store & rhs.in_store) != Store::kNotSet;
+}
+
} // namespace
namespace password_manager {
@@ -67,14 +75,19 @@ void SavedPasswordsPresenter::Init() {
}
void SavedPasswordsPresenter::RemovePassword(const PasswordForm& form) {
- std::string current_form_key = CreateSortKey(form);
- for (const auto& saved_form : passwords_) {
- if (CreateSortKey(saved_form) == current_form_key) {
- PasswordStore& store =
- saved_form.IsUsingAccountStore() ? *account_store_ : *profile_store_;
- store.RemoveLogin(saved_form);
+ std::string current_form_key = CreateSortKey(form, IgnoreStore(true));
+ const auto range = sort_key_to_password_forms.equal_range(current_form_key);
+
+ std::for_each(range.first, range.second, [&](const auto& pair) {
+ const auto& current_form = pair.second;
+ // Make sure |form| and |current_form| share the same store.
+ if (ShareSameStore(form, current_form)) {
+ // |current_form| is unchanged result obtained from
+ // 'OnGetPasswordStoreResultsFrom'. So it can be present only in one store
+ // at a time..
+ GetStoreFor(current_form).RemoveLogin(current_form);
}
- }
+ });
}
bool SavedPasswordsPresenter::EditPassword(const PasswordForm& form,
@@ -98,15 +111,16 @@ bool SavedPasswordsPresenter::EditSavedPasswords(
const PasswordForm& form,
const std::u16string& new_username,
const std::u16string& new_password) {
- // TODO(crbug.com/1184691): Adapt this code to support credentials
- // coming from both account and profile store, then change desktop
- // settings and maybe iOS to use this presenter for updating the duplicates.
+ // TODO(crbug.com/1184691): Change desktop settings and maybe iOS to use this
+ // presenter for updating the duplicates.
std::vector<PasswordForm> forms_to_change;
- std::string current_form_key = CreateSortKey(form);
- for (const auto& saved_form : passwords_) {
- if (CreateSortKey(saved_form) == current_form_key)
- forms_to_change.push_back(saved_form);
- }
+
+ std::string current_form_key = CreateSortKey(form, IgnoreStore(true));
+ const auto range = sort_key_to_password_forms.equal_range(current_form_key);
+
+ base::ranges::transform(range.first, range.second,
+ std::back_inserter(forms_to_change),
+ [](const auto& pair) { return pair.second; });
return EditSavedPasswords(forms_to_change, new_username, new_password);
}
@@ -128,9 +142,7 @@ bool SavedPasswordsPresenter::EditSavedPasswords(
// class.
if (username_changed || password_changed) {
for (const auto& old_form : forms) {
- PasswordStore& store =
- old_form.IsUsingAccountStore() ? *account_store_ : *profile_store_;
-
+ PasswordStore& store = GetStoreFor(old_form);
PasswordForm new_form = old_form;
new_form.username_value = new_username;
new_form.password_value = new_password;
@@ -156,6 +168,26 @@ SavedPasswordsPresenter::GetSavedPasswords() const {
return passwords_;
}
+std::vector<PasswordForm> SavedPasswordsPresenter::GetUniquePasswordForms()
+ const {
+ std::vector<PasswordForm> forms;
+
+ auto it = sort_key_to_password_forms.begin();
+ std::string current_key;
+
+ while (it != sort_key_to_password_forms.end()) {
+ if (current_key != it->first) {
+ current_key = it->first;
+ forms.push_back(it->second);
+ } else {
+ forms.back().in_store = forms.back().in_store | it->second.in_store;
+ }
+ ++it;
+ }
+
+ return forms;
+}
+
std::vector<std::u16string> SavedPasswordsPresenter::GetUsernamesForRealm(
const std::string& signon_realm,
bool is_using_account_store) {
@@ -212,11 +244,6 @@ void SavedPasswordsPresenter::OnGetPasswordStoreResults(
void SavedPasswordsPresenter::OnGetPasswordStoreResultsFrom(
PasswordStore* store,
std::vector<std::unique_ptr<PasswordForm>> results) {
- // Ignore blocked or federated credentials.
- base::EraseIf(results, [](const auto& form) {
- return form->blocked_by_user || form->IsFederatedCredential();
- });
-
// Profile store passwords are always stored first in `passwords_`.
auto account_passwords_it = base::ranges::partition_point(
passwords_,
@@ -242,7 +269,24 @@ void SavedPasswordsPresenter::OnGetPasswordStoreResultsFrom(
base::ranges::transform(results, std::back_inserter(passwords_),
[](auto& result) { return std::move(*result); });
}
+
+ sort_key_to_password_forms.clear();
+ base::ranges::for_each(passwords_, [&](const auto& result) {
+ sort_key_to_password_forms.insert(
+ std::make_pair(CreateSortKey(result, IgnoreStore(true)), result));
+ });
+
+ // Remove blocked or federated credentials.
+ base::EraseIf(passwords_, [](const auto& form) {
+ return form.blocked_by_user || form.IsFederatedCredential();
+ });
+
NotifySavedPasswordsChanged();
}
+PasswordStore& SavedPasswordsPresenter::GetStoreFor(const PasswordForm& form) {
+ DCHECK_NE(form.IsUsingAccountStore(), form.IsUsingProfileStore());
+ return form.IsUsingAccountStore() ? *account_store_ : *profile_store_;
+}
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter.h b/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter.h
index 63fd415a773..b0261b4a4c4 100644
--- a/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter.h
+++ b/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter.h
@@ -77,8 +77,7 @@ class SavedPasswordsPresenter : public PasswordStore::Observer,
// Modifies the provided password form and its duplicates
// with `new_username` and `new_password`.
//
- // Note: this will only change credentials in the store that `form` comes
- // from.
+ // Note: this will also change duplicates of 'form' in all stores.
bool EditSavedPasswords(const PasswordForm& form,
const std::u16string& new_username,
const std::u16string& new_password);
@@ -93,6 +92,14 @@ class SavedPasswordsPresenter : public PasswordStore::Observer,
// Returns a list of the currently saved credentials.
SavedPasswordsView GetSavedPasswords() const;
+ // Returns a list of unique password forms which includes normal credentials,
+ // federated credentials and blocked forms. If a same form is present both on
+ // account and profile stores it will be represented as a single entity.
+ // Uniqueness is determined using site name, username, password. For Android
+ // credentials package name is also taken into account and for Federated
+ // credentials federation origin.
+ std::vector<PasswordForm> GetUniquePasswordForms() const;
+
// Returns all the usernames for credentials saved for `signon_realm`. If
// `is_using_account_store` is true, this method will only consider
// credentials saved in the account store. Otherwiser it will only consider
@@ -106,6 +113,7 @@ class SavedPasswordsPresenter : public PasswordStore::Observer,
void RemoveObserver(Observer* observer);
private:
+ using DuplicatePasswordsMap = std::multimap<std::string, PasswordForm>;
// PasswordStore::Observer
void OnLoginsChanged(const PasswordStoreChangeList& changes) override;
void OnLoginsChangedIn(PasswordStore* store,
@@ -122,6 +130,11 @@ class SavedPasswordsPresenter : public PasswordStore::Observer,
void NotifyEdited(const PasswordForm& password);
void NotifySavedPasswordsChanged();
+ // Returns the `profile_store_` or `account_store_` if `form` is stored in the
+ // profile store or the account store accordingly. This function should be
+ // used only for credential stored in a single store.
+ PasswordStore& GetStoreFor(const PasswordForm& form);
+
// The password stores containing the saved passwords.
scoped_refptr<PasswordStore> profile_store_;
scoped_refptr<PasswordStore> account_store_;
@@ -130,6 +143,9 @@ class SavedPasswordsPresenter : public PasswordStore::Observer,
// passwords are always stored first, and then account store passwords if any.
std::vector<PasswordForm> passwords_;
+ // Structure used to deduplicate list of passwords.
+ DuplicatePasswordsMap sort_key_to_password_forms;
+
base::ObserverList<Observer, /*check_empty=*/true> observers_;
};
diff --git a/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc b/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
index 685139fbcdb..25d9ee541f8 100644
--- a/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
+++ b/chromium/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
@@ -386,6 +386,41 @@ TEST_F(SavedPasswordsPresenterTest, EditUpdatesDuplicates) {
presenter().RemoveObserver(&observer);
}
+TEST_F(SavedPasswordsPresenterTest,
+ GetUniquePasswordFormsShouldReturnBlockedAndFederatedForms) {
+ PasswordForm form;
+ form.signon_realm = "https://example.com";
+ form.username_value = u"example@gmail.com";
+ form.password_value = u"password";
+ form.in_store = PasswordForm::Store::kProfileStore;
+
+ PasswordForm blocked_form;
+ blocked_form.signon_realm = "https://example.com";
+ blocked_form.blocked_by_user = true;
+ blocked_form.in_store = PasswordForm::Store::kProfileStore;
+
+ PasswordForm federated_form;
+ federated_form.signon_realm = "https://federated.com";
+ federated_form.username_value = u"example@gmail.com";
+ federated_form.federation_origin =
+ url::Origin::Create(GURL(u"federatedOrigin.com"));
+ federated_form.in_store = PasswordForm::Store::kProfileStore;
+
+ store().AddLogin(form);
+ store().AddLogin(blocked_form);
+ store().AddLogin(federated_form);
+ RunUntilIdle();
+
+ ASSERT_THAT(
+ store().stored_passwords(),
+ UnorderedElementsAre(
+ Pair(form.signon_realm, UnorderedElementsAre(form, blocked_form)),
+ Pair(federated_form.signon_realm, ElementsAre(federated_form))));
+
+ EXPECT_THAT(presenter().GetUniquePasswordForms(),
+ UnorderedElementsAre(form, blocked_form, federated_form));
+}
+
namespace {
class SavedPasswordsPresenterWithTwoStoresTest : public ::testing::Test {
@@ -580,6 +615,46 @@ TEST_F(SavedPasswordsPresenterWithTwoStoresTest, DeleteCredentialAccountStore) {
EXPECT_TRUE(account_store().IsEmpty());
}
+TEST_F(SavedPasswordsPresenterWithTwoStoresTest, DeleteCredentialBothStores) {
+ PasswordForm profile_store_form;
+ profile_store_form.signon_realm = "https://example.com";
+ profile_store_form.username_value = u"example@gmail.com";
+ profile_store_form.password_value = u"password";
+ profile_store_form.in_store = PasswordForm::Store::kProfileStore;
+
+ PasswordForm account_store_form = profile_store_form;
+ account_store_form.in_store = PasswordForm::Store::kAccountStore;
+
+ PasswordForm mobile_account_store_form = account_store_form;
+ mobile_account_store_form.signon_realm = "https://mobile.example.com";
+
+ profile_store().AddLogin(profile_store_form);
+ account_store().AddLogin(account_store_form);
+ account_store().AddLogin(mobile_account_store_form);
+ RunUntilIdle();
+
+ ASSERT_THAT(profile_store().stored_passwords(),
+ ElementsAre(Pair(profile_store_form.signon_realm,
+ ElementsAre(profile_store_form))));
+ ASSERT_THAT(account_store().stored_passwords(),
+ ElementsAre(Pair(account_store_form.signon_realm,
+ ElementsAre(account_store_form)),
+ Pair(mobile_account_store_form.signon_realm,
+ ElementsAre(mobile_account_store_form))));
+
+ PasswordForm form_to_delete = profile_store_form;
+ form_to_delete.in_store =
+ PasswordForm::Store::kProfileStore | PasswordForm::Store::kAccountStore;
+
+ presenter().RemovePassword(form_to_delete);
+ RunUntilIdle();
+
+ // All credentials which are considered duplicates of a 'form_to_delete'
+ // should have been deleted from both stores.
+ EXPECT_TRUE(profile_store().IsEmpty());
+ EXPECT_TRUE(account_store().IsEmpty());
+}
+
TEST_F(SavedPasswordsPresenterWithTwoStoresTest,
ReturnsUsernamesForRealmFromSameStore) {
PasswordForm form;
@@ -603,21 +678,128 @@ TEST_F(SavedPasswordsPresenterWithTwoStoresTest,
RunUntilIdle();
- ASSERT_THAT(
- profile_store().stored_passwords(),
- ElementsAre(Pair(form.signon_realm, ElementsAre(form, other_form))));
+ ASSERT_THAT(profile_store().stored_passwords(),
+ ElementsAre(Pair(form.signon_realm,
+ UnorderedElementsAre(form, other_form))));
ASSERT_THAT(account_store().stored_passwords(),
ElementsAre(Pair(account_store_form.signon_realm,
ElementsAre(account_store_form))));
- EXPECT_THAT(presenter().GetUsernamesForRealm(
- form.signon_realm, /*is_using_account_store=*/false),
- ElementsAre(form.username_value, other_form.username_value));
+ EXPECT_THAT(
+ presenter().GetUsernamesForRealm(form.signon_realm,
+ /*is_using_account_store=*/false),
+ UnorderedElementsAre(form.username_value, other_form.username_value));
EXPECT_THAT(presenter().GetUsernamesForRealm(account_store_form.signon_realm,
/*is_using_account_store=*/true),
ElementsAre(account_store_form.username_value));
}
+TEST_F(SavedPasswordsPresenterWithTwoStoresTest, GetUniquePasswords) {
+ PasswordForm profile_store_form;
+ profile_store_form.signon_realm = "https://example.com";
+ profile_store_form.username_value = u"example@gmail.com";
+ profile_store_form.password_value = u"password";
+ profile_store_form.in_store = PasswordForm::Store::kProfileStore;
+
+ PasswordForm account_store_form = profile_store_form;
+ account_store_form.in_store = PasswordForm::Store::kAccountStore;
+
+ profile_store().AddLogin(profile_store_form);
+ account_store().AddLogin(account_store_form);
+ RunUntilIdle();
+
+ ASSERT_THAT(profile_store().stored_passwords(),
+ ElementsAre(Pair(profile_store_form.signon_realm,
+ ElementsAre(profile_store_form))));
+ ASSERT_THAT(account_store().stored_passwords(),
+ ElementsAre(Pair(account_store_form.signon_realm,
+ ElementsAre(account_store_form))));
+
+ PasswordForm expected_form = profile_store_form;
+ expected_form.in_store =
+ PasswordForm::Store::kProfileStore | PasswordForm::Store::kAccountStore;
+
+ EXPECT_THAT(presenter().GetUniquePasswordForms(), ElementsAre(expected_form));
+}
+
+// Prefixes like [m, mobile, www] are considered as "same-site".
+TEST_F(SavedPasswordsPresenterWithTwoStoresTest, GetUniquePasswords2) {
+ PasswordForm profile_store_form;
+ profile_store_form.signon_realm = "https://example.com";
+ profile_store_form.username_value = u"example@gmail.com";
+ profile_store_form.password_value = u"password";
+ profile_store_form.in_store = PasswordForm::Store::kProfileStore;
+
+ PasswordForm mobile_profile_store_form = profile_store_form;
+ mobile_profile_store_form.signon_realm = "https://m.example.com";
+
+ PasswordForm account_form_with_www = profile_store_form;
+ account_form_with_www.signon_realm = "https://www.example.com";
+ account_form_with_www.in_store = PasswordForm::Store::kAccountStore;
+
+ profile_store().AddLogin(mobile_profile_store_form);
+ profile_store().AddLogin(profile_store_form);
+ account_store().AddLogin(account_form_with_www);
+
+ RunUntilIdle();
+
+ ASSERT_THAT(
+ profile_store().stored_passwords(),
+ UnorderedElementsAre(Pair(profile_store_form.signon_realm,
+ ElementsAre(profile_store_form)),
+ Pair(mobile_profile_store_form.signon_realm,
+ ElementsAre(mobile_profile_store_form))));
+ ASSERT_THAT(account_store().stored_passwords(),
+ ElementsAre(Pair(account_form_with_www.signon_realm,
+ ElementsAre(account_form_with_www))));
+
+ PasswordForm expected_form = profile_store_form;
+ expected_form.in_store =
+ PasswordForm::Store::kProfileStore | PasswordForm::Store::kAccountStore;
+
+ EXPECT_THAT(presenter().GetUniquePasswordForms(), ElementsAre(expected_form));
+}
+
+TEST_F(SavedPasswordsPresenterWithTwoStoresTest, EditPasswordBothStores) {
+ PasswordForm profile_store_form;
+ profile_store_form.username_value = u"test@gmail.com";
+ profile_store_form.password_value = u"pass";
+ profile_store_form.in_store = PasswordForm::Store::kProfileStore;
+
+ PasswordForm account_store_form = profile_store_form;
+ account_store_form.in_store = PasswordForm::Store::kAccountStore;
+
+ profile_store().AddLogin(profile_store_form);
+ account_store().AddLogin(account_store_form);
+ RunUntilIdle();
+
+ EXPECT_THAT(profile_store().stored_passwords(),
+ ElementsAre(Pair(profile_store_form.signon_realm,
+ ElementsAre(profile_store_form))));
+
+ std::u16string new_username = u"new_test@gmail.com";
+ std::u16string new_password = u"new_password";
+
+ EXPECT_TRUE(presenter().EditSavedPasswords(profile_store_form, new_username,
+ new_password));
+
+ RunUntilIdle();
+
+ PasswordForm expected_profile_store_form = profile_store_form;
+ expected_profile_store_form.username_value = new_username;
+ expected_profile_store_form.password_value = new_password;
+ expected_profile_store_form.in_store = PasswordForm::Store::kProfileStore;
+ PasswordForm expected_account_store_form = expected_profile_store_form;
+ expected_account_store_form.in_store = PasswordForm::Store::kAccountStore;
+
+ EXPECT_THAT(profile_store().stored_passwords(),
+ ElementsAre(Pair(profile_store_form.signon_realm,
+ ElementsAre(expected_profile_store_form))));
+ EXPECT_THAT(account_store().stored_passwords(),
+ ElementsAre(Pair(account_store_form.signon_realm,
+ ElementsAre(expected_account_store_form))));
+}
+
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/ui/weak_check_utility_unittest.cc b/chromium/components/password_manager/core/browser/ui/weak_check_utility_unittest.cc
index c006f42f7f0..62664960115 100644
--- a/chromium/components/password_manager/core/browser/ui/weak_check_utility_unittest.cc
+++ b/chromium/components/password_manager/core/browser/ui/weak_check_utility_unittest.cc
@@ -12,44 +12,40 @@ namespace password_manager {
namespace {
-constexpr char kWeakShortPassword[] = "123456";
-constexpr char kWeakLongPassword[] =
- "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcda";
-constexpr char kStrongShortPassword[] = "fnlsr4@cm^mdls@fkspnsg3d";
-constexpr char kStrongLongPassword[] =
- "pmsFlsnoab4nsl#losb@skpfnsbkjb^klsnbs!cns";
+constexpr char16_t kWeakShortPassword[] = u"123456";
+constexpr char16_t kWeakLongPassword[] =
+ u"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcda";
+constexpr char16_t kStrongShortPassword[] = u"fnlsr4@cm^mdls@fkspnsg3d";
+constexpr char16_t kStrongLongPassword[] =
+ u"pmsFlsnoab4nsl#losb@skpfnsbkjb^klsnbs!cns";
using ::testing::ElementsAre;
} // namespace
TEST(WeakCheckUtilityTest, IsWeak) {
- EXPECT_TRUE(IsWeak(base::ASCIIToUTF16(kWeakShortPassword)));
- EXPECT_TRUE(IsWeak(base::ASCIIToUTF16(kWeakLongPassword)));
- EXPECT_FALSE(IsWeak(base::ASCIIToUTF16(kStrongShortPassword)));
- EXPECT_FALSE(IsWeak(base::ASCIIToUTF16(kStrongLongPassword)));
+ EXPECT_TRUE(IsWeak(kWeakShortPassword));
+ EXPECT_TRUE(IsWeak(kWeakLongPassword));
+ EXPECT_FALSE(IsWeak(kStrongShortPassword));
+ EXPECT_FALSE(IsWeak(kStrongLongPassword));
}
TEST(WeakCheckUtilityTest, WeakPasswordsNotFound) {
- base::flat_set<std::u16string> passwords = {
- base::ASCIIToUTF16(kStrongShortPassword),
- base::ASCIIToUTF16(kStrongLongPassword)};
+ base::flat_set<std::u16string> passwords = {kStrongShortPassword,
+ kStrongLongPassword};
EXPECT_THAT(BulkWeakCheck(passwords), testing::IsEmpty());
}
TEST(WeakCheckUtilityTest, DetectedShortAndLongWeakPasswords) {
base::flat_set<std::u16string> passwords = {
- base::ASCIIToUTF16(kStrongLongPassword),
- base::ASCIIToUTF16(kWeakShortPassword),
- base::ASCIIToUTF16(kStrongShortPassword),
- base::ASCIIToUTF16(kWeakLongPassword)};
+ kStrongLongPassword, kWeakShortPassword, kStrongShortPassword,
+ kWeakLongPassword};
base::flat_set<std::u16string> weak_passwords = BulkWeakCheck(passwords);
EXPECT_THAT(weak_passwords,
- ElementsAre(base::ASCIIToUTF16(kWeakShortPassword),
- base::ASCIIToUTF16(kWeakLongPassword)));
+ ElementsAre(kWeakShortPassword, kWeakLongPassword));
}
} // namespace password_manager
diff --git a/chromium/components/password_manager/core/browser/votes_uploader.cc b/chromium/components/password_manager/core/browser/votes_uploader.cc
index fd8a10be661..9319c5facc9 100644
--- a/chromium/components/password_manager/core/browser/votes_uploader.cc
+++ b/chromium/components/password_manager/core/browser/votes_uploader.cc
@@ -12,7 +12,6 @@
#include "base/check_op.h"
#include "base/hash/hash.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/rand_util.h"
#include "base/ranges/algorithm.h"
#include "base/strings/utf_string_conversions.h"
@@ -27,6 +26,7 @@
#include "components/password_manager/core/browser/field_info_manager.h"
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using autofill::AutofillDownloadManager;
using autofill::AutofillField;
diff --git a/chromium/components/password_manager/core/browser/votes_uploader.h b/chromium/components/password_manager/core/browser/votes_uploader.h
index dd21c3deffd..dcbb3fa30ed 100644
--- a/chromium/components/password_manager/core/browser/votes_uploader.h
+++ b/chromium/components/password_manager/core/browser/votes_uploader.h
@@ -9,13 +9,13 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/proto/server.pb.h"
#include "components/autofill/core/common/signatures.h"
#include "components/autofill/core/common/unique_ids.h"
#include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
#include "components/password_manager/core/browser/password_form.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace autofill {
struct FormData;
@@ -235,7 +235,7 @@ class VotesUploader {
// The matched credential is copied to |username_correction_vote_|, but
// |username_correction_vote_.username_element| is set to the name of the
// field where the matched username was found.
- base::Optional<PasswordForm> username_correction_vote_;
+ absl::optional<PasswordForm> username_correction_vote_;
// Whether the password values have been shown to the user on the save prompt.
bool has_passwords_revealed_vote_ = false;
@@ -257,7 +257,7 @@ class VotesUploader {
// observed form.
std::map<autofill::FieldRendererId, std::u16string> initial_values_;
- base::Optional<SingleUsernameVoteData> single_username_vote_data_;
+ absl::optional<SingleUsernameVoteData> single_username_vote_data_;
};
} // namespace password_manager
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 3b29f72c24e..b1305053f4a 100644
--- a/chromium/components/password_manager/core/browser/votes_uploader_unittest.cc
+++ b/chromium/components/password_manager/core/browser/votes_uploader_unittest.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/hash/hash.h"
-#include "base/optional.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
@@ -28,6 +27,7 @@
#include "components/prefs/testing_pref_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using autofill::AutofillDownloadManager;
using autofill::CONFIRMATION_PASSWORD;
@@ -275,7 +275,7 @@ TEST_F(VotesUploaderTest, GeneratePasswordAttributesVote) {
for (int i = 0; i < kNumberOfRuns; ++i) {
votes_uploader.GeneratePasswordAttributesVote(password_value,
&form_structure);
- base::Optional<std::pair<PasswordAttribute, bool>> vote =
+ absl::optional<std::pair<PasswordAttribute, bool>> vote =
form_structure.get_password_attributes_vote();
int attribute_index = static_cast<int>(vote->first);
if (vote->second)
@@ -332,7 +332,7 @@ TEST_F(VotesUploaderTest, GeneratePasswordSpecialSymbolVote) {
votes_uploader.GeneratePasswordAttributesVote(password_value,
&form_structure);
- base::Optional<std::pair<PasswordAttribute, bool>> vote =
+ absl::optional<std::pair<PasswordAttribute, bool>> vote =
form_structure.get_password_attributes_vote();
// Continue if the vote is not about special symbols or implies that no
@@ -362,7 +362,7 @@ TEST_F(VotesUploaderTest, GeneratePasswordAttributesVote_OneCharacterPassword) {
FormStructure form_structure(form);
VotesUploader votes_uploader(&client_, true);
votes_uploader.GeneratePasswordAttributesVote(u"1", &form_structure);
- base::Optional<std::pair<PasswordAttribute, bool>> vote =
+ absl::optional<std::pair<PasswordAttribute, bool>> vote =
form_structure.get_password_attributes_vote();
EXPECT_TRUE(vote.has_value());
size_t reported_length = form_structure.get_password_length_vote();
@@ -374,10 +374,10 @@ TEST_F(VotesUploaderTest, GeneratePasswordAttributesVote_AllAsciiCharacters) {
FormStructure form_structure(form);
VotesUploader votes_uploader(&client_, true);
votes_uploader.GeneratePasswordAttributesVote(
- base::UTF8ToUTF16("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr"
- "stuvwxyz!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"),
+ u"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr"
+ u"stuvwxyz!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
&form_structure);
- base::Optional<std::pair<PasswordAttribute, bool>> vote =
+ absl::optional<std::pair<PasswordAttribute, bool>> vote =
form_structure.get_password_attributes_vote();
EXPECT_TRUE(vote.has_value());
}
@@ -386,15 +386,14 @@ TEST_F(VotesUploaderTest, GeneratePasswordAttributesVote_NonAsciiPassword) {
// Checks that password attributes vote is not generated if the password has
// non-ascii characters.
for (const auto* password :
- {"пароль1", "パスワード", "münchen", "סיסמה-A", "Σ-12345",
- "գաղտնաբառըTTT", "Slaptažodis", "密碼", "كلمهالسر", "mậtkhẩu!",
- "ລະຫັດຜ່ານ-l", "စကားá€á€¾á€€á€ºá€€á€­á€¯3", "პáƒáƒ áƒáƒšáƒ˜", "पारण शबà¥à¤¦"}) {
+ {u"пароль1", u"パスワード", u"münchen", u"סיסמה-A", u"Σ-12345",
+ u"գաղտնաբառըTTT", u"Slaptažodis", u"密碼", u"كلمهالسر", u"mậtkhẩu!",
+ u"ລະຫັດຜ່ານ-l", u"စကားá€á€¾á€€á€ºá€€á€­á€¯3", u"პáƒáƒ áƒáƒšáƒ˜", u"पारण शबà¥à¤¦"}) {
FormData form;
FormStructure form_structure(form);
VotesUploader votes_uploader(&client_, true);
- votes_uploader.GeneratePasswordAttributesVote(base::UTF8ToUTF16(password),
- &form_structure);
- base::Optional<std::pair<PasswordAttribute, bool>> vote =
+ votes_uploader.GeneratePasswordAttributesVote(password, &form_structure);
+ absl::optional<std::pair<PasswordAttribute, bool>> vote =
form_structure.get_password_attributes_vote();
EXPECT_FALSE(vote.has_value()) << password;
diff --git a/chromium/components/password_manager/core/browser/well_known_change_password_state.cc b/chromium/components/password_manager/core/browser/well_known_change_password_state.cc
index b4f37a2cc49..e28c6a42d9c 100644
--- a/chromium/components/password_manager/core/browser/well_known_change_password_state.cc
+++ b/chromium/components/password_manager/core/browser/well_known_change_password_state.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "base/optional.h"
#include "components/password_manager/core/browser/site_affiliation/affiliation_service.h"
#include "components/password_manager/core/browser/well_known_change_password_util.h"
#include "components/password_manager/core/common/password_manager_features.h"
@@ -16,6 +15,7 @@
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
using password_manager::WellKnownChangePasswordState;
@@ -29,8 +29,8 @@ namespace {
std::unique_ptr<network::SimpleURLLoader>
CreateResourceRequestToWellKnownNonExistingResourceFor(
const GURL& url,
- base::Optional<url::Origin> request_initiator,
- base::Optional<network::ResourceRequest::TrustedParams> trusted_params) {
+ absl::optional<url::Origin> request_initiator,
+ absl::optional<network::ResourceRequest::TrustedParams> trusted_params) {
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = CreateWellKnownNonExistingResourceURL(url);
resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
@@ -81,8 +81,8 @@ WellKnownChangePasswordState::~WellKnownChangePasswordState() = default;
void WellKnownChangePasswordState::FetchNonExistingResource(
network::SharedURLLoaderFactory* url_loader_factory,
const GURL& url,
- base::Optional<url::Origin> request_initiator,
- base::Optional<network::ResourceRequest::TrustedParams> trusted_params) {
+ absl::optional<url::Origin> request_initiator,
+ absl::optional<network::ResourceRequest::TrustedParams> trusted_params) {
url_loader_ = CreateResourceRequestToWellKnownNonExistingResourceFor(
url, std::move(request_initiator), std::move(trusted_params));
// Binding the callback to |this| is safe, because the State exists until
diff --git a/chromium/components/password_manager/core/browser/well_known_change_password_state.h b/chromium/components/password_manager/core/browser/well_known_change_password_state.h
index 6f5407f8c5a..4fae0f41ba9 100644
--- a/chromium/components/password_manager/core/browser/well_known_change_password_state.h
+++ b/chromium/components/password_manager/core/browser/well_known_change_password_state.h
@@ -9,10 +9,10 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/timer/timer.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -49,9 +49,9 @@ class WellKnownChangePasswordState {
void FetchNonExistingResource(
network::SharedURLLoaderFactory* url_loader_factory,
const GURL& origin,
- base::Optional<url::Origin> request_initiator = base::nullopt,
- base::Optional<network::ResourceRequest::TrustedParams> trusted_params =
- base::nullopt);
+ absl::optional<url::Origin> request_initiator = absl::nullopt,
+ absl::optional<network::ResourceRequest::TrustedParams> trusted_params =
+ absl::nullopt);
// Prefetch change password URLs from |affiliation_service|.
void PrefetchChangePasswordURLs(AffiliationService* affiliation_service,
const std::vector<GURL>& urls);
diff --git a/chromium/components/password_manager/core/browser/well_known_change_password_state_unittest.cc b/chromium/components/password_manager/core/browser/well_known_change_password_state_unittest.cc
index c2622d8ed61..1ee8483e101 100644
--- a/chromium/components/password_manager/core/browser/well_known_change_password_state_unittest.cc
+++ b/chromium/components/password_manager/core/browser/well_known_change_password_state_unittest.cc
@@ -239,7 +239,7 @@ TEST_P(WellKnownChangePasswordStateTest,
syncer::TestSyncService test_sync_service;
test_sync_service.SetFirstSetupComplete(true);
- test_sync_service.SetIsUsingSecondaryPassphrase(false);
+ test_sync_service.SetIsUsingExplicitPassphrase(false);
AffiliationServiceImpl affiliation_service(&test_sync_service,
test_shared_loader_factory());
affiliation_service.SetFetcherFactoryForTesting(
diff --git a/chromium/components/password_manager/core/browser/well_known_change_password_util.h b/chromium/components/password_manager/core/browser/well_known_change_password_util.h
index fd296a8e449..e5010f86232 100644
--- a/chromium/components/password_manager/core/browser/well_known_change_password_util.h
+++ b/chromium/components/password_manager/core/browser/well_known_change_password_util.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_WELL_KNOWN_CHANGE_PASSWORD_UTIL_H_
#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_WELL_KNOWN_CHANGE_PASSWORD_UTIL_H_
-#include <memory>
-
class GURL;
namespace password_manager {
diff --git a/chromium/components/password_manager/core/common/credential_manager_types.cc b/chromium/components/password_manager/core/common/credential_manager_types.cc
index f7ffa284eb2..f12847948a2 100644
--- a/chromium/components/password_manager/core/common/credential_manager_types.cc
+++ b/chromium/components/password_manager/core/common/credential_manager_types.cc
@@ -30,10 +30,10 @@ std::ostream& operator<<(std::ostream& os, CredentialType value) {
CredentialInfo::CredentialInfo() = default;
CredentialInfo::CredentialInfo(CredentialType type,
- base::Optional<std::u16string> id,
- base::Optional<std::u16string> name,
+ absl::optional<std::u16string> id,
+ absl::optional<std::u16string> name,
GURL icon,
- base::Optional<std::u16string> password,
+ absl::optional<std::u16string> password,
url::Origin federation)
: type(type),
id(std::move(id)),
diff --git a/chromium/components/password_manager/core/common/credential_manager_types.h b/chromium/components/password_manager/core/common/credential_manager_types.h
index c62f1889354..999df894c8d 100644
--- a/chromium/components/password_manager/core/common/credential_manager_types.h
+++ b/chromium/components/password_manager/core/common/credential_manager_types.h
@@ -12,7 +12,7 @@
#include <string>
#include "base/compiler_specific.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -44,10 +44,10 @@ std::ostream& operator<<(std::ostream& os, CredentialType value);
struct CredentialInfo {
CredentialInfo();
CredentialInfo(CredentialType type,
- base::Optional<std::u16string> id,
- base::Optional<std::u16string> name,
+ absl::optional<std::u16string> id,
+ absl::optional<std::u16string> name,
GURL icon,
- base::Optional<std::u16string> password,
+ absl::optional<std::u16string> password,
url::Origin federation);
CredentialInfo(const CredentialInfo& other);
@@ -59,18 +59,18 @@ struct CredentialInfo {
// An identifier (username, email address, etc). Corresponds to
// WebCredential's id property.
- base::Optional<std::u16string> id;
+ absl::optional<std::u16string> id;
// An user-friendly name ("Jane Doe"). Corresponds to WebCredential's name
// property.
- base::Optional<std::u16string> name;
+ absl::optional<std::u16string> name;
// The address of this credential's icon (e.g. the user's avatar).
// Corresponds to WebCredential's icon property.
GURL icon;
// Corresponds to WebPasswordCredential's password property.
- base::Optional<std::u16string> password;
+ absl::optional<std::u16string> password;
// Corresponds to WebFederatedCredential's provider property.
url::Origin federation;
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 cf8b0a7fac7..3cd6d0d10d2 100644
--- a/chromium/components/password_manager/core/common/password_manager_features.cc
+++ b/chromium/components/password_manager/core/common/password_manager_features.cc
@@ -60,7 +60,13 @@ const base::Feature kEnableOverwritingPlaceholderUsernames{
// 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};
+ "EnablePasswordsAccountStorage",
+#if defined(OS_ANDROID) || defined(OS_IOS)
+ base::FEATURE_DISABLED_BY_DEFAULT
+#else
+ base::FEATURE_ENABLED_BY_DEFAULT
+#endif
+};
const base::Feature KEnablePasswordGenerationForClearTextFields = {
"EnablePasswordGenerationForClearTextFields",
@@ -88,6 +94,10 @@ const base::Feature kFillOnAccountSelect = {"fill-on-account-select",
const base::Feature kInferConfirmationPasswordField = {
"InferConfirmationPasswordField", base::FEATURE_ENABLED_BY_DEFAULT};
+// Enables respecting of insecure credential muting state.
+const base::Feature kMutingCompromisedCredentials{
+ "MutingCompromisedCredentials", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables password change flow from leaked password dialog.
const base::Feature kPasswordChange = {"PasswordChange",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -138,6 +148,18 @@ const base::Feature kSyncingCompromisedCredentials = {
const base::Feature kTreatNewPasswordHeuristicsAsReliable = {
"TreatNewPasswordHeuristicsAsReliable", base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether we should use the new header images for the legacy save
+// password bubble.
+const base::Feature kUseNewHeaderForLegacySavePasswordBubble{
+ "UseNewHeaderForLegacySavePasswordBubble",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Controls whether we should use the new header images for the save
+// password bubble with account store.
+const base::Feature kUseNewHeaderForSavePasswordWithAccountStoreBubble{
+ "UseNewHeaderForSavePasswordWithAccountStoreBubble",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
// Enables use of Hash Affiliation fetcher for all requests.
const base::Feature kUseOfHashAffiliationFetcher = {
"UseOfHashAffiliationFetcher", base::FEATURE_DISABLED_BY_DEFAULT};
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 1c47927dcd6..85ace62759d 100644
--- a/chromium/components/password_manager/core/common/password_manager_features.h
+++ b/chromium/components/password_manager/core/common/password_manager_features.h
@@ -30,6 +30,7 @@ extern const base::Feature kFillingAcrossAffiliatedWebsites;
extern const base::Feature kFillingPasswordsFromAnyOrigin;
extern const base::Feature kFillOnAccountSelect;
extern const base::Feature kInferConfirmationPasswordField;
+extern const base::Feature kMutingCompromisedCredentials;
extern const base::Feature kPasswordChange;
extern const base::Feature kPasswordChangeInSettings;
extern const base::Feature kPasswordImport;
@@ -40,6 +41,8 @@ extern const base::Feature kReparseServerPredictionsFollowingFormChange;
extern const base::Feature kSecondaryServerFieldPredictions;
extern const base::Feature kSyncingCompromisedCredentials;
extern const base::Feature kTreatNewPasswordHeuristicsAsReliable;
+extern const base::Feature kUseNewHeaderForLegacySavePasswordBubble;
+extern const base::Feature kUseNewHeaderForSavePasswordWithAccountStoreBubble;
extern const base::Feature kUseOfHashAffiliationFetcher;
extern const base::Feature kUsernameFirstFlow;
diff --git a/chromium/components/password_manager/ios/BUILD.gn b/chromium/components/password_manager/ios/BUILD.gn
index 9cdd83f9d74..c86ece98c3f 100644
--- a/chromium/components/password_manager/ios/BUILD.gn
+++ b/chromium/components/password_manager/ios/BUILD.gn
@@ -8,11 +8,15 @@ component("ios") {
configs += [ "//build/config/compiler:enable_arc" ]
deps = [
+ ":account_select_fill_data",
+ ":password_manager_feature",
"//base",
"//components/autofill/core/browser",
"//components/autofill/core/common",
"//components/autofill/ios/browser",
+ "//components/autofill/ios/browser:util",
"//components/autofill/ios/form_util",
+ "//components/autofill/ios/form_util:form_util_feature",
"//components/password_manager/core/browser",
"//components/password_manager/core/browser/form_parsing",
"//components/password_manager/core/common",
@@ -26,10 +30,6 @@ component("ios") {
]
sources = [
- "account_select_fill_data.cc",
- "account_select_fill_data.h",
- "js_password_manager.h",
- "js_password_manager.mm",
"password_form_helper.h",
"password_form_helper.mm",
"password_generation_provider.h",
@@ -44,6 +44,44 @@ component("ios") {
]
}
+source_set("password_manager_feature") {
+ configs += [ "//build/config/compiler:enable_arc" ]
+
+ deps = [
+ ":account_select_fill_data",
+ ":password_controller_js",
+ "//base",
+ "//components/autofill/core/common",
+ "//components/autofill/ios/browser:util",
+ "//components/autofill/ios/form_util:form_util_feature",
+ "//ios/web/public/js_messaging",
+ ]
+
+ sources = [
+ "password_manager_java_script_feature.h",
+ "password_manager_java_script_feature.mm",
+ ]
+}
+
+source_set("account_select_fill_data") {
+ deps = [
+ "//base",
+ "//components/autofill/core/common",
+ "//components/autofill/ios/browser:util",
+ "//url",
+ ]
+
+ sources = [
+ "account_select_fill_data.cc",
+ "account_select_fill_data.h",
+ ]
+}
+
+js_compile_bundle("password_controller_js") {
+ closure_entry_point = "__crWeb.passwords"
+ sources = [ "resources/password_controller.js" ]
+}
+
static_library("test_support") {
testonly = true
sources = [
@@ -52,6 +90,7 @@ static_library("test_support") {
]
deps = [
+ ":account_select_fill_data",
":ios",
"//base",
"//components/autofill/core/common",
@@ -68,16 +107,19 @@ source_set("unit_tests") {
"shared_password_controller_unittest.mm",
]
deps = [
+ ":account_select_fill_data",
":ios",
- ":test_bundle",
":test_support",
"//base",
"//base/test:test_support",
"//components/autofill/core/common",
"//components/autofill/ios/browser",
"//components/autofill/ios/form_util",
+ "//components/autofill/ios/form_util:form_util_feature",
"//components/password_manager/core/browser",
"//components/password_manager/core/browser:test_support",
+ "//components/password_manager/ios:password_manager_feature",
+ "//ios/web/public/js_messaging",
"//ios/web/public/test",
"//ios/web/public/test/fakes",
"//testing/gmock",
@@ -85,14 +127,3 @@ source_set("unit_tests") {
"//third_party/ocmock",
]
}
-
-js_compile_bundle("test_bundle") {
- closure_entry_point = "__crWeb.testBundle"
- testonly = true
- sources = [
- "//components/autofill/ios/form_util/resources/fill.js",
- "//components/autofill/ios/form_util/resources/form.js",
- "resources/password_controller.js",
- "resources/test_bundle.js",
- ]
-}
diff --git a/chromium/components/password_manager/ios/js_password_manager.h b/chromium/components/password_manager/ios/js_password_manager.h
deleted file mode 100644
index ee62f3a0f83..00000000000
--- a/chromium/components/password_manager/ios/js_password_manager.h
+++ /dev/null
@@ -1,91 +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_IOS_JS_PASSWORD_MANAGER_H_
-#define COMPONENTS_PASSWORD_MANAGER_IOS_JS_PASSWORD_MANAGER_H_
-
-#include "base/ios/block_types.h"
-#include "components/autofill/core/common/unique_ids.h"
-#include "ios/web/public/js_messaging/web_frame.h"
-
-namespace autofill {
-struct PasswordFormFillData;
-} // namespace autofill
-
-namespace password_manager {
-
-struct FillData;
-
-// Serializes |fillData| so it can be used by the JS side of PasswordController.
-// Includes both username and password data if |fillUsername|, and only password
-// data otherwise.
-std::unique_ptr<base::Value> SerializeFillData(
- const password_manager::FillData& fillData,
- BOOL fillUsername);
-
-// Serializes |formData| so it can be used by the JS side of PasswordController.
-std::unique_ptr<base::Value> SerializePasswordFormFillData(
- const autofill::PasswordFormFillData& formData);
-
-} // namespace password_manager
-
-// Loads the JavaScript file, password_controller.js, which contains password
-// form parsing and autofill functions. It will be evaluated on a page that
-// is known to have at least one password form (see hasPasswordField_ in
-// password_controller.js) It returns contents of those password forms and also
-// registers functions that are later used to autofill them.
-@interface JsPasswordManager : NSObject
-
-// Finds any password forms on the web page.
-// |completionHandler| is then called with the JSON string result (which can
-// be a zero-length string if there was an error). |completionHandler| cannot be
-// nil.
-// For example the JSON string for a form with a single password field is:
-// [{"action":null,"method":null,"usernameElement":"","usernameValue":"","
-// passwords":[{"element":"","value":"asd"}]}]
-- (void)findPasswordFormsInFrame:(web::WebFrame*)frame
- completionHandler:(void (^)(NSString*))completionHandler;
-
-// Extracts the password form with the given name from a web page.
-// |completionHandler| is called with the JSON string containing the info about
-// submitted password forms from a web page (it can be zero-length if there was
-// an error). |completionHandler| cannot be nil.
-// For example. the JSON string for a form with a single password field is:
-// {"action":null,"method":null,"usernameElement":"","usernameValue":"",
-// "passwords":[{"element":"","value":"asd"}]}
-- (void)extractForm:(autofill::FormRendererId)formIdentifier
- inFrame:(web::WebFrame*)frame
- completionHandler:(void (^)(NSString*))completionHandler;
-
-// Fills in the password form specified by |JSONString| with the given
-// |username| and |password|. Assumes JavaScript has been injected previously
-// by calling |findPasswordFormsWithCompletionHandle| or
-// |extractSubmittedFormWithCompletionHandler|. Calls |completionHandler| with
-// YES if the filling of the password was successful, NO otherwise.
-// |completionHandler| cannot be nil.
-- (void)fillPasswordForm:(std::unique_ptr<base::Value>)form
- inFrame:(web::WebFrame*)frame
- withUsername:(std::string)username
- password:(std::string)password
- completionHandler:(void (^)(BOOL))completionHandler;
-
-// Fills new password field for (optional) |newPasswordIdentifier| and for
-// (optional) confirm password field |confirmPasswordIdentifier| in the form
-// identified by |formData|. Invokes |completionHandler| with true if any fields
-// were filled, false otherwise.
-- (void)fillPasswordForm:(autofill::FormRendererId)formIdentifier
- inFrame:(web::WebFrame*)frame
- newPasswordIdentifier:(autofill::FieldRendererId)newPasswordIdentifier
- confirmPasswordIdentifier:
- (autofill::FieldRendererId)confirmPasswordIdentifier
- generatedPassword:(NSString*)generatedPassword
- completionHandler:(void (^)(BOOL))completionHandler;
-
-// Sets up the next available unique ID value in a document.
-- (void)setUpForUniqueIDsWithInitialState:(uint32_t)nextAvailableID
- inFrame:(web::WebFrame*)frame;
-
-@end
-
-#endif // COMPONENTS_PASSWORD_MANAGER_IOS_JS_PASSWORD_MANAGER_H_
diff --git a/chromium/components/password_manager/ios/js_password_manager.mm b/chromium/components/password_manager/ios/js_password_manager.mm
deleted file mode 100644
index ab8ad38adbf..00000000000
--- a/chromium/components/password_manager/ios/js_password_manager.mm
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "components/password_manager/ios/js_password_manager.h"
-
-#include "base/check.h"
-#include "base/mac/foundation_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/values.h"
-#include "components/autofill/core/common/password_form_fill_data.h"
-#include "components/autofill/ios/browser/autofill_util.h"
-#include "components/password_manager/ios/account_select_fill_data.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-using autofill::CreateBoolCallback;
-using autofill::CreateStringCallback;
-using autofill::FormRendererId;
-using autofill::FieldRendererId;
-using base::SysNSStringToUTF8;
-
-// Converts FormRendererId to int value that can be used in Javascript methods.
-int FormRendererIdToJsParameter(FormRendererId formID) {
- return formID.value();
-}
-
-// Converts FieldRendererId to int value that can be used in Javascript methods.
-int FieldRendererIdToJsParameter(FieldRendererId fieldID) {
- return fieldID.value();
-}
-
-namespace password_manager {
-
-std::unique_ptr<base::Value> SerializeFillData(
- const GURL& origin,
- FormRendererId form_renderer_id,
- FieldRendererId username_element,
- const std::u16string& username_value,
- FieldRendererId password_element,
- const std::u16string& password_value) {
- auto rootDict = std::make_unique<base::DictionaryValue>();
- rootDict->SetString("origin", origin.spec());
- rootDict->SetInteger("unique_renderer_id",
- FormRendererIdToJsParameter(form_renderer_id));
-
- auto fieldList = std::make_unique<base::ListValue>();
-
- auto usernameField = std::make_unique<base::DictionaryValue>();
- usernameField->SetInteger("unique_renderer_id",
- FieldRendererIdToJsParameter(username_element));
- usernameField->SetString("value", username_value);
- fieldList->Append(std::move(usernameField));
-
- auto passwordField = std::make_unique<base::DictionaryValue>();
- passwordField->SetInteger("unique_renderer_id", password_element.value());
- passwordField->SetString("value", password_value);
- fieldList->Append(std::move(passwordField));
-
- rootDict->Set("fields", std::move(fieldList));
-
- return rootDict;
-}
-
-std::unique_ptr<base::Value> SerializePasswordFormFillData(
- const autofill::PasswordFormFillData& formData) {
- return SerializeFillData(formData.url, formData.form_renderer_id,
- formData.username_field.unique_renderer_id,
- formData.username_field.value,
- formData.password_field.unique_renderer_id,
- formData.password_field.value);
-}
-
-std::unique_ptr<base::Value> SerializeFillData(
- const password_manager::FillData& fillData,
- BOOL fillUsername) {
- return SerializeFillData(
- fillData.origin, fillData.form_id,
- fillUsername ? fillData.username_element_id : FieldRendererId(),
- fillData.username_value, fillData.password_element_id,
- fillData.password_value);
-}
-
-} // namespace password_manager
-
-@implementation JsPasswordManager
-
-- (void)findPasswordFormsInFrame:(web::WebFrame*)frame
- completionHandler:(void (^)(NSString*))completionHandler {
- DCHECK(completionHandler);
- std::vector<base::Value> parameters;
- autofill::ExecuteJavaScriptFunction("passwords.findPasswordForms", parameters,
- frame,
- CreateStringCallback(completionHandler));
-}
-
-- (void)extractForm:(FormRendererId)formIdentifier
- inFrame:(web::WebFrame*)frame
- completionHandler:(void (^)(NSString*))completionHandler {
- DCHECK(completionHandler);
- std::vector<base::Value> parameters;
- parameters.emplace_back(FormRendererIdToJsParameter(formIdentifier));
- autofill::ExecuteJavaScriptFunction("passwords.getPasswordFormDataAsString",
- parameters, frame,
- CreateStringCallback(completionHandler));
-}
-
-- (void)fillPasswordForm:(std::unique_ptr<base::Value>)form
- inFrame:(web::WebFrame*)frame
- withUsername:(std::string)username
- password:(std::string)password
- completionHandler:(void (^)(BOOL))completionHandler {
- DCHECK(completionHandler);
- std::vector<base::Value> parameters;
- parameters.push_back(std::move(*form));
- parameters.emplace_back(std::move(username));
- parameters.emplace_back(std::move(password));
- autofill::ExecuteJavaScriptFunction("passwords.fillPasswordForm", parameters,
- frame,
- CreateBoolCallback(completionHandler));
-}
-
-- (void)fillPasswordForm:(FormRendererId)formIdentifier
- inFrame:(web::WebFrame*)frame
- newPasswordIdentifier:(FieldRendererId)newPasswordIdentifier
- confirmPasswordIdentifier:(FieldRendererId)confirmPasswordIdentifier
- generatedPassword:(NSString*)generatedPassword
- completionHandler:(void (^)(BOOL))completionHandler {
- DCHECK(completionHandler);
- std::vector<base::Value> parameters;
- parameters.emplace_back(FormRendererIdToJsParameter(formIdentifier));
- parameters.emplace_back(FieldRendererIdToJsParameter(newPasswordIdentifier));
- parameters.emplace_back(
- FieldRendererIdToJsParameter(confirmPasswordIdentifier));
- parameters.push_back(base::Value(SysNSStringToUTF8(generatedPassword)));
- autofill::ExecuteJavaScriptFunction(
- "passwords.fillPasswordFormWithGeneratedPassword", parameters, frame,
- CreateBoolCallback(completionHandler));
-}
-
-- (void)setUpForUniqueIDsWithInitialState:(uint32_t)nextAvailableID
- inFrame:(web::WebFrame*)frame {
- std::vector<base::Value> parameters;
- parameters.emplace_back(static_cast<int>(nextAvailableID));
- autofill::ExecuteJavaScriptFunction("fill.setUpForUniqueIDs", parameters,
- frame,
- autofill::JavaScriptResultCallback());
-}
-
-@end
diff --git a/chromium/components/password_manager/ios/password_form_helper.h b/chromium/components/password_manager/ios/password_form_helper.h
index 5f3c87954bc..cc4d8f7fed6 100644
--- a/chromium/components/password_manager/ios/password_form_helper.h
+++ b/chromium/components/password_manager/ios/password_form_helper.h
@@ -15,7 +15,6 @@
NS_ASSUME_NONNULL_BEGIN
-@class JsPasswordManager;
@class PasswordFormHelper;
namespace autofill {
@@ -51,9 +50,6 @@ class WebState;
@interface PasswordFormHelper
: NSObject<FormActivityObserver, CRWWebStateObserver>
-// The JsPasswordManager processing password form via javascript.
-@property(nonatomic, readonly) JsPasswordManager* jsPasswordManager;
-
// Last committed URL of current web state.
// Returns empty URL if current web state is not available.
@property(nonatomic, readonly) const GURL& lastCommittedURL;
diff --git a/chromium/components/password_manager/ios/password_form_helper.mm b/chromium/components/password_manager/ios/password_form_helper.mm
index 8dbfafe7231..1f174f7150f 100644
--- a/chromium/components/password_manager/ios/password_form_helper.mm
+++ b/chromium/components/password_manager/ios/password_form_helper.mm
@@ -15,10 +15,11 @@
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/password_form_fill_data.h"
#include "components/autofill/ios/browser/autofill_util.h"
+#import "components/autofill/ios/form_util/form_util_java_script_feature.h"
#include "components/autofill/ios/form_util/unique_id_data_tab_helper.h"
#include "components/password_manager/ios/account_select_fill_data.h"
-#include "components/password_manager/ios/js_password_manager.h"
#include "components/password_manager/ios/password_manager_ios_util.h"
+#import "components/password_manager/ios/password_manager_java_script_feature.h"
#import "ios/web/public/js_messaging/web_frame.h"
#import "ios/web/public/js_messaging/web_frame_util.h"
#import "ios/web/public/web_state.h"
@@ -37,7 +38,6 @@ using base::UTF16ToUTF8;
using password_manager::FillData;
using password_manager::GetPageURLAndCheckTrustLevel;
using password_manager::JsonStringToFormData;
-using password_manager::SerializePasswordFormFillData;
namespace password_manager {
bool GetPageURLAndCheckTrustLevel(web::WebState* web_state,
@@ -71,14 +71,6 @@ constexpr char kCommandPrefix[] = "passwordForm";
@end
-// Category for test only.
-@interface PasswordFormHelper (Testing)
-
-// Replaces JsPasswordManager for test.
-- (void)setJsPasswordManager:(JsPasswordManager*)jsPasswordManager;
-
-@end
-
@implementation PasswordFormHelper {
// The WebState this instance is observing. Will be null after
// -webStateDestroyed: has been called.
@@ -97,7 +89,6 @@ constexpr char kCommandPrefix[] = "passwordForm";
#pragma mark - Properties
-@synthesize jsPasswordManager = _jsPasswordManager;
@synthesize fieldDataManager = _fieldDataManager;
- (const GURL&)lastCommittedURL {
@@ -116,7 +107,6 @@ constexpr char kCommandPrefix[] = "passwordForm";
_webState->AddObserver(_webStateObserverBridge.get());
_formActivityObserverBridge =
std::make_unique<autofill::FormActivityObserverBridge>(_webState, self);
- _jsPasswordManager = [[JsPasswordManager alloc] init];
UniqueIDDataTabHelper* uniqueIDDataTabHelper =
UniqueIDDataTabHelper::FromWebState(_webState);
@@ -253,12 +243,6 @@ constexpr char kCommandPrefix[] = "passwordForm";
}
}
-#pragma mark - Private methods for test only
-
-- (void)setJsPasswordManager:(JsPasswordManager*)jsPasswordManager {
- _jsPasswordManager = jsPasswordManager;
-}
-
#pragma mark - Public methods
- (void)findPasswordFormsWithCompletionHandler:
@@ -267,37 +251,47 @@ constexpr char kCommandPrefix[] = "passwordForm";
return;
}
+ web::WebFrame* mainFrame = web::GetMainFrame(_webState);
+ if (!mainFrame) {
+ return;
+ }
+
GURL pageURL;
if (!GetPageURLAndCheckTrustLevel(_webState, &pageURL)) {
return;
}
__weak PasswordFormHelper* weakSelf = self;
- [self.jsPasswordManager
- findPasswordFormsInFrame:GetMainFrame(_webState)
- completionHandler:^(NSString* JSONString) {
- std::vector<FormData> forms;
- [weakSelf getPasswordForms:&forms
- fromJSON:JSONString
- pageURL:pageURL];
- // Find the maximum extracted value.
- uint32_t maxID = 0;
- for (const auto& form : forms) {
- if (form.unique_renderer_id) {
- maxID = std::max(maxID, form.unique_renderer_id.value());
- }
- for (const auto& field : form.fields) {
- if (field.unique_renderer_id) {
- maxID = std::max(maxID, field.unique_renderer_id.value());
- }
- }
- }
- completionHandler(forms, maxID);
- }];
+ password_manager::PasswordManagerJavaScriptFeature::GetInstance()
+ ->FindPasswordFormsInFrame(
+ mainFrame, base::BindOnce(^(NSString* JSONString) {
+ std::vector<FormData> forms;
+ [weakSelf getPasswordForms:&forms
+ fromJSON:JSONString
+ pageURL:pageURL];
+ // Find the maximum extracted value.
+ uint32_t maxID = 0;
+ for (const auto& form : forms) {
+ if (form.unique_renderer_id) {
+ maxID = std::max(maxID, form.unique_renderer_id.value());
+ }
+ for (const auto& field : form.fields) {
+ if (field.unique_renderer_id) {
+ maxID = std::max(maxID, field.unique_renderer_id.value());
+ }
+ }
+ }
+ completionHandler(forms, maxID);
+ }));
}
- (void)fillPasswordForm:(const autofill::PasswordFormFillData&)formData
completionHandler:(nullable void (^)(BOOL))completionHandler {
+ web::WebFrame* mainFrame = web::GetMainFrame(_webState);
+ if (!mainFrame) {
+ return;
+ }
+
// Necessary copy so the values can be used inside a block.
FieldRendererId usernameID = formData.username_field.unique_renderer_id;
FieldRendererId passwordID = formData.password_field.unique_renderer_id;
@@ -320,24 +314,22 @@ constexpr char kCommandPrefix[] = "passwordForm";
// Send JSON over to the web view.
__weak PasswordFormHelper* weakSelf = self;
- [self.jsPasswordManager
- fillPasswordForm:SerializePasswordFormFillData(formData)
- inFrame:GetMainFrame(_webState)
- withUsername:UTF16ToUTF8(usernameValue)
- password:UTF16ToUTF8(passwordValue)
- completionHandler:^(BOOL success) {
- if (success) {
- weakSelf.fieldDataManager->UpdateFieldDataMap(
- usernameID, usernameValue,
- FieldPropertiesFlags::kAutofilledOnPageLoad);
- weakSelf.fieldDataManager->UpdateFieldDataMap(
- passwordID, passwordValue,
- FieldPropertiesFlags::kAutofilledOnPageLoad);
- }
- if (completionHandler) {
- completionHandler(success);
- }
- }];
+ password_manager::PasswordManagerJavaScriptFeature::GetInstance()
+ ->FillPasswordForm(mainFrame, formData, UTF16ToUTF8(usernameValue),
+ UTF16ToUTF8(passwordValue),
+ base::BindOnce(^(BOOL success) {
+ if (success) {
+ weakSelf.fieldDataManager->UpdateFieldDataMap(
+ usernameID, usernameValue,
+ FieldPropertiesFlags::kAutofilledOnPageLoad);
+ weakSelf.fieldDataManager->UpdateFieldDataMap(
+ passwordID, passwordValue,
+ FieldPropertiesFlags::kAutofilledOnPageLoad);
+ }
+ if (completionHandler) {
+ completionHandler(success);
+ }
+ }));
}
- (void)fillPasswordForm:(FormRendererId)formIdentifier
@@ -345,15 +337,19 @@ constexpr char kCommandPrefix[] = "passwordForm";
confirmPasswordIdentifier:(FieldRendererId)confirmPasswordIdentifier
generatedPassword:(NSString*)generatedPassword
completionHandler:(nullable void (^)(BOOL))completionHandler {
+ web::WebFrame* mainFrame = web::GetMainFrame(_webState);
+ if (!mainFrame) {
+ return;
+ }
+
// Send JSON over to the web view.
__weak PasswordFormHelper* weakSelf = self;
- [self.jsPasswordManager
- fillPasswordForm:formIdentifier
- inFrame:GetMainFrame(_webState)
- newPasswordIdentifier:newPasswordIdentifier
- confirmPasswordIdentifier:confirmPasswordIdentifier
- generatedPassword:generatedPassword
- completionHandler:^(BOOL success) {
+ password_manager::PasswordManagerJavaScriptFeature::GetInstance()
+ ->FillPasswordForm(
+ mainFrame, formIdentifier, newPasswordIdentifier,
+ confirmPasswordIdentifier, generatedPassword,
+ base::BindOnce(
+ ^(BOOL success) {
if (success) {
weakSelf.fieldDataManager->UpdateFieldDataMap(
newPasswordIdentifier,
@@ -367,13 +363,18 @@ constexpr char kCommandPrefix[] = "passwordForm";
if (completionHandler) {
completionHandler(success);
}
- }];
+ }));
}
- (void)fillPasswordFormWithFillData:(const password_manager::FillData&)fillData
triggeredOnField:(FieldRendererId)uniqueFieldID
completionHandler:
(nullable void (^)(BOOL))completionHandler {
+ web::WebFrame* mainFrame = web::GetMainFrame(_webState);
+ if (!mainFrame) {
+ return;
+ }
+
// Necessary copy so the values can be used inside a block.
FieldRendererId usernameID = fillData.username_element_id;
FieldRendererId passwordID = fillData.password_element_id;
@@ -385,24 +386,22 @@ constexpr char kCommandPrefix[] = "passwordForm";
BOOL fillUsername = uniqueFieldID == usernameID ||
!_fieldDataManager->DidUserType(usernameID);
__weak PasswordFormHelper* weakSelf = self;
- [self.jsPasswordManager
- fillPasswordForm:SerializeFillData(fillData, fillUsername)
- inFrame:GetMainFrame(_webState)
- withUsername:UTF16ToUTF8(usernameValue)
- password:UTF16ToUTF8(passwordValue)
- completionHandler:^(BOOL success) {
- if (success) {
- weakSelf.fieldDataManager->UpdateFieldDataMap(
- usernameID, usernameValue,
- FieldPropertiesFlags::kAutofilledOnUserTrigger);
- weakSelf.fieldDataManager->UpdateFieldDataMap(
- passwordID, passwordValue,
- FieldPropertiesFlags::kAutofilledOnUserTrigger);
- }
- if (completionHandler) {
- completionHandler(success);
- }
- }];
+ password_manager::PasswordManagerJavaScriptFeature::GetInstance()
+ ->FillPasswordForm(
+ mainFrame, fillData, fillUsername, UTF16ToUTF8(usernameValue),
+ UTF16ToUTF8(passwordValue), base::BindOnce(^(BOOL success) {
+ if (success) {
+ weakSelf.fieldDataManager->UpdateFieldDataMap(
+ usernameID, usernameValue,
+ FieldPropertiesFlags::kAutofilledOnUserTrigger);
+ weakSelf.fieldDataManager->UpdateFieldDataMap(
+ passwordID, passwordValue,
+ FieldPropertiesFlags::kAutofilledOnUserTrigger);
+ }
+ if (completionHandler) {
+ completionHandler(success);
+ }
+ }));
}
// Finds the password form named |formName| and calls
@@ -417,31 +416,34 @@ constexpr char kCommandPrefix[] = "passwordForm";
return;
}
+ web::WebFrame* mainFrame = web::GetMainFrame(_webState);
+ if (!mainFrame) {
+ return;
+ }
+
GURL pageURL;
if (!GetPageURLAndCheckTrustLevel(_webState, &pageURL)) {
completionHandler(NO, FormData());
return;
}
- id extractFormDataCompletionHandler = ^(NSString* jsonString) {
- FormData formData;
- if (!JsonStringToFormData(jsonString, &formData, pageURL)) {
- completionHandler(NO, FormData());
- return;
- }
-
- completionHandler(YES, formData);
- };
-
- [self.jsPasswordManager extractForm:formIdentifier
- inFrame:GetMainFrame(_webState)
- completionHandler:extractFormDataCompletionHandler];
+ password_manager::PasswordManagerJavaScriptFeature::GetInstance()
+ ->ExtractForm(
+ mainFrame, formIdentifier, base::BindOnce(^(NSString* jsonString) {
+ FormData formData;
+ if (!JsonStringToFormData(jsonString, &formData, pageURL)) {
+ completionHandler(NO, FormData());
+ return;
+ }
+
+ completionHandler(YES, formData);
+ }));
}
- (void)setUpForUniqueIDsWithInitialState:(uint32_t)nextAvailableID
inFrame:(web::WebFrame*)frame {
- [self.jsPasswordManager setUpForUniqueIDsWithInitialState:nextAvailableID
- inFrame:frame];
+ autofill::FormUtilJavaScriptFeature::GetInstance()
+ ->SetUpForUniqueIDsWithInitialState(frame, nextAvailableID);
}
- (void)updateFieldDataOnUserInput:(autofill::FieldRendererId)field_id
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 0d3f99dd6e5..73bcb95fafb 100644
--- a/chromium/components/password_manager/ios/password_form_helper_unittest.mm
+++ b/chromium/components/password_manager/ios/password_form_helper_unittest.mm
@@ -13,12 +13,17 @@
#include "components/autofill/core/browser/logging/log_manager.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/password_form_fill_data.h"
+#import "components/autofill/ios/form_util/form_util_java_script_feature.h"
#include "components/autofill/ios/form_util/unique_id_data_tab_helper.h"
#include "components/password_manager/ios/account_select_fill_data.h"
+#include "components/password_manager/ios/password_manager_java_script_feature.h"
#include "components/password_manager/ios/test_helpers.h"
+#include "ios/web/public/js_messaging/web_frame_util.h"
+#import "ios/web/public/js_messaging/web_frames_manager.h"
#import "ios/web/public/test/fakes/fake_navigation_context.h"
#include "ios/web/public/test/fakes/fake_web_client.h"
#import "ios/web/public/test/web_test_with_web_state.h"
+#import "ios/web/public/web_client.h"
#import "ios/web/public/web_state.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
@@ -41,35 +46,16 @@ using test_helpers::SetFillData;
using test_helpers::SetFormData;
namespace {
-// Returns a string containing the JavaScript loaded from a
-// bundled resource file with the given name (excluding extension).
-NSString* GetPageScript(NSString* script_file_name) {
- EXPECT_NE(nil, script_file_name);
- NSString* path =
- [base::mac::FrameworkBundle() pathForResource:script_file_name
- ofType:@"js"];
- EXPECT_NE(nil, path);
- NSError* error = nil;
- NSString* content = [NSString stringWithContentsOfFile:path
- encoding:NSUTF8StringEncoding
- error:&error];
- EXPECT_EQ(nil, error);
- EXPECT_NE(nil, content);
- return content;
-}
-
-class FakeWebClientWithScript : public web::FakeWebClient {
- public:
- NSString* GetDocumentStartScriptForMainFrame(
- web::BrowserState* browser_state) const override {
- return GetPageScript(@"test_bundle");
- }
-};
-
class PasswordFormHelperTest : public web::WebTestWithWebState {
public:
PasswordFormHelperTest()
- : web::WebTestWithWebState(std::make_unique<FakeWebClientWithScript>()) {}
+ : web::WebTestWithWebState(std::make_unique<web::FakeWebClient>()) {
+ web::FakeWebClient* web_client =
+ static_cast<web::FakeWebClient*>(GetWebClient());
+ web_client->SetJavaScriptFeatures(
+ {autofill::FormUtilJavaScriptFeature::GetInstance(),
+ password_manager::PasswordManagerJavaScriptFeature::GetInstance()});
+ }
~PasswordFormHelperTest() override = default;
@@ -85,6 +71,45 @@ class PasswordFormHelperTest : public web::WebTestWithWebState {
web::WebTestWithWebState::TearDown();
}
+ // Sets up unique form ids and returns true if successful.
+ bool SetUpUniqueIDs() {
+ __block web::WebFrame* main_frame = nullptr;
+ bool success =
+ WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+ main_frame = web_state()->GetWebFramesManager()->GetMainWebFrame();
+ return main_frame != nullptr;
+ });
+ if (!success) {
+ return false;
+ }
+ DCHECK(main_frame);
+
+ constexpr uint32_t next_available_id = 1;
+ autofill::FormUtilJavaScriptFeature::GetInstance()
+ ->SetUpForUniqueIDsWithInitialState(main_frame, next_available_id);
+
+ // Wait for |SetUpForUniqueIDsWithInitialState| to complete.
+ success = WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+ return [ExecuteJavaScript(@"document[__gCrWeb.fill.ID_SYMBOL]")
+ intValue] == int{next_available_id};
+ });
+ if (!success) {
+ return false;
+ }
+
+ // Run password forms search to set up unique IDs.
+ __block bool complete = false;
+ password_manager::PasswordManagerJavaScriptFeature::GetInstance()
+ ->FindPasswordFormsInFrame(web::GetMainFrame(web_state()),
+ base::BindOnce(^(NSString* forms) {
+ complete = true;
+ }));
+
+ return WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool {
+ return complete;
+ });
+ }
+
protected:
// PasswordFormHelper for testing.
PasswordFormHelper* helper_;
@@ -221,9 +246,8 @@ TEST_F(PasswordFormHelperTest, FillPasswordFormWithFillData) {
LoadHtml(
@"<form><input id='u1' type='text' name='un1'>"
"<input id='p1' type='password' name='pw1'></form>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);");
- // Run password forms search to set up unique IDs.
- EXPECT_TRUE(ExecuteJavaScript(@"__gCrWeb.passwords.findPasswordForms();"));
+
+ ASSERT_TRUE(SetUpUniqueIDs());
const std::string base_url = BaseUrl();
FieldRendererId username_field_id(2);
FieldRendererId password_field_id(3);
@@ -251,9 +275,8 @@ TEST_F(PasswordFormHelperTest, FindAndFillOnePasswordForm) {
LoadHtml(
@"<form><input id='u1' type='text' name='un1'>"
"<input id='p1' type='password' name='pw1'></form>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);");
- // Run password forms search to set up unique IDs.
- EXPECT_TRUE(ExecuteJavaScript(@"__gCrWeb.passwords.findPasswordForms();"));
+
+ ASSERT_TRUE(SetUpUniqueIDs());
PasswordFormFillData form_data;
SetPasswordFormFillData(BaseUrl(), "gChrome~form~0", 1, "u1", 2,
@@ -286,9 +309,9 @@ TEST_F(PasswordFormHelperTest, ExtractPasswordFormData) {
"<input id='p2' type='password' name='pw2'></form>"
"<form><input id='u3' type='text' name='un3'>"
"<input id='p3' type='password' name='pw3'></form>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);");
- // Run password forms search to set up unique IDs.
- EXPECT_TRUE(ExecuteJavaScript(@"__gCrWeb.passwords.findPasswordForms();"));
+
+ ASSERT_TRUE(SetUpUniqueIDs());
+
__block int call_counter = 0;
__block int success_counter = 0;
__block FormData result = FormData();
@@ -329,9 +352,8 @@ TEST_F(PasswordFormHelperTest, ExtractPasswordFormData) {
TEST_F(PasswordFormHelperTest, RefillFormFilledOnUserTrigger) {
LoadHtml(@"<form><input id='u1' type='text' name='un1'>"
"<input id='p1' type='password' name='pw1'></form>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);");
- // Run password forms search to set up unique IDs.
- EXPECT_TRUE(ExecuteJavaScript(@"__gCrWeb.passwords.findPasswordForms();"));
+
+ ASSERT_TRUE(SetUpUniqueIDs());
// Fill the form on user trigger.
const std::string base_url = BaseUrl();
@@ -375,9 +397,8 @@ TEST_F(PasswordFormHelperTest, RefillFormFilledOnUserTrigger) {
TEST_F(PasswordFormHelperTest, RefillFormWithUserTypedInput) {
LoadHtml(@"<form><input id='u1' type='text' name='un1'>"
"<input id='p1' type='password' name='pw1'></form>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);");
- // Run password forms search to set up unique IDs.
- EXPECT_TRUE(ExecuteJavaScript(@"__gCrWeb.passwords.findPasswordForms();"));
+
+ ASSERT_TRUE(SetUpUniqueIDs());
ExecuteJavaScript(
@"document.getElementById('u1').value = 'john.doe@gmail.com';");
@@ -424,9 +445,8 @@ TEST_F(PasswordFormHelperTest, RefillFormWithUserTypedInput) {
TEST_F(PasswordFormHelperTest, FillPasswordIntoFormWithUserTypedUsername) {
LoadHtml(@"<form><input id='u1' type='text' name='un1'>"
"<input id='p1' type='password' name='pw1'></form>");
- ExecuteJavaScript(@"__gCrWeb.fill.setUpForUniqueIDs(1);");
- // Run password forms search to set up unique IDs.
- EXPECT_TRUE(ExecuteJavaScript(@"__gCrWeb.passwords.findPasswordForms();"));
+
+ ASSERT_TRUE(SetUpUniqueIDs());
FieldRendererId username_field_id(2);
FieldRendererId password_field_id(3);
diff --git a/chromium/components/password_manager/ios/password_manager_java_script_feature.h b/chromium/components/password_manager/ios/password_manager_java_script_feature.h
new file mode 100644
index 00000000000..d6084a3b9c5
--- /dev/null
+++ b/chromium/components/password_manager/ios/password_manager_java_script_feature.h
@@ -0,0 +1,110 @@
+// Copyright 2021 The Chromium Authors. 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_IOS_PASSWORD_MANAGER_JAVA_SCRIPT_FEATURE_H_
+#define COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_MANAGER_JAVA_SCRIPT_FEATURE_H_
+
+#include "base/callback.h"
+#include "base/no_destructor.h"
+#include "components/autofill/core/common/unique_ids.h"
+#import "ios/web/public/js_messaging/java_script_feature.h"
+
+namespace autofill {
+struct PasswordFormFillData;
+} // namespace autofill
+
+namespace web {
+class WebFrame;
+} // namespace web
+
+namespace password_manager {
+
+struct FillData;
+
+// Communicates with the JavaScript file password_controller.js, which
+// contains password form parsing and autofill functions.
+class PasswordManagerJavaScriptFeature : public web::JavaScriptFeature {
+ public:
+ // This feature holds no state, so only a single static instance is ever
+ // needed.
+ static PasswordManagerJavaScriptFeature* GetInstance();
+
+ // Finds any password forms on the web page.
+ // |callback| is then called with the JSON string result (which can
+ // be a zero-length string if there was an error). |callback| cannot be null.
+ // For example the JSON string for a form with a single password field is:
+ // [{"action":null,"method":null,"usernameElement":"","usernameValue":"","
+ // passwords":[{"element":"","value":"asd"}]}]
+ void FindPasswordFormsInFrame(web::WebFrame* frame,
+ base::OnceCallback<void(NSString*)> callback);
+
+ // Extracts the password form with the given |form_identifier| from a web
+ // page. |callback| is called with the JSON string containing the info about
+ // submitted password forms from a web page (it can be zero-length if there
+ // was an error). |callback| cannot be null. For example. the JSON string for
+ // a form with a single password field is:
+ // {"action":null,"method":null,"usernameElement":"","usernameValue":"",
+ // "passwords":[{"element":"","value":"asd"}]}
+ void ExtractForm(web::WebFrame* frame,
+ autofill::FormRendererId form_identifier,
+ base::OnceCallback<void(NSString*)> callback);
+
+ // Fills in the form specified by |form| with the given |password|.
+ // |username| will be filled in if and only if |fill_username| is true.
+ // Assumes JavaScript has been injected previously by calling
+ // |FindPasswordFormsInFrame| or |ExtractForm|. Calls |callback|
+ // with YES if the filling of the password was successful, NO otherwise.
+ // |callback| cannot be null.
+ void FillPasswordForm(web::WebFrame* frame,
+ const password_manager::FillData& form,
+ BOOL fill_username,
+ const std::string& username,
+ const std::string& password,
+ base::OnceCallback<void(BOOL)> callback);
+
+ // Fills in the form specified by |fill_data| with the given |username| and
+ // |password|. Assumes JavaScript has been injected previously by calling
+ // |FindPasswordFormsInFrame| or |ExtractForm|. Calls |callback|
+ // with YES if the filling of the password was successful, NO otherwise.
+ // |callback| cannot be null.
+ void FillPasswordForm(web::WebFrame* frame,
+ const autofill::PasswordFormFillData& fill_data,
+ const std::string& username,
+ const std::string& password,
+ base::OnceCallback<void(BOOL)> callback);
+
+ // Fills new password field for (optional) |new_password_identifier| and for
+ // (optional) confirm password field |confirm_password_identifier| in the form
+ // identified by |form_identifier|. Invokes |callback| with YES if any fields
+ // were filled, false otherwise.
+ void FillPasswordForm(web::WebFrame* frame,
+ autofill::FormRendererId form_identifier,
+ autofill::FieldRendererId new_password_identifier,
+ autofill::FieldRendererId confirm_password_identifier,
+ NSString* generated_password,
+ base::OnceCallback<void(BOOL)> callback);
+
+ private:
+ friend class base::NoDestructor<PasswordManagerJavaScriptFeature>;
+
+ PasswordManagerJavaScriptFeature();
+ ~PasswordManagerJavaScriptFeature() override;
+
+ PasswordManagerJavaScriptFeature(const PasswordManagerJavaScriptFeature&) =
+ delete;
+ PasswordManagerJavaScriptFeature& operator=(
+ const PasswordManagerJavaScriptFeature&) = delete;
+
+ // Calls the "passwords.fillPasswordForm" JavaScript function to fill the form
+ // described by |form_value| with |username| and |password|.
+ void FillPasswordForm(web::WebFrame* frame,
+ std::unique_ptr<base::Value> form_value,
+ const std::string& username,
+ const std::string& password,
+ base::OnceCallback<void(BOOL)> callback);
+};
+
+} // namespace password_manager
+
+#endif // COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_MANAGER_JAVA_SCRIPT_FEATURE_H_
diff --git a/chromium/components/password_manager/ios/password_manager_java_script_feature.mm b/chromium/components/password_manager/ios/password_manager_java_script_feature.mm
new file mode 100644
index 00000000000..6b2f5e61b06
--- /dev/null
+++ b/chromium/components/password_manager/ios/password_manager_java_script_feature.mm
@@ -0,0 +1,213 @@
+// Copyright 2021 The Chromium 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 "components/password_manager/ios/password_manager_java_script_feature.h"
+
+#include "base/strings/sys_string_conversions.h"
+#include "base/values.h"
+#include "components/autofill/core/common/password_form_fill_data.h"
+#include "components/autofill/ios/browser/autofill_util.h"
+#import "components/autofill/ios/form_util/form_util_java_script_feature.h"
+#include "components/password_manager/ios/account_select_fill_data.h"
+#import "ios/web/public/js_messaging/java_script_feature_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+using autofill::CreateBoolCallback;
+using autofill::CreateStringCallback;
+
+namespace password_manager {
+
+namespace {
+constexpr char kScriptName[] = "password_controller_js";
+
+// The timeout for any JavaScript call in this file.
+constexpr int64_t kJavaScriptExecutionTimeoutInSeconds = 5;
+
+// Converts FormRendererId to int value that can be used in Javascript methods.
+int FormRendererIdToJsParameter(autofill::FormRendererId form_id) {
+ return form_id.value();
+}
+
+// Converts FieldRendererId to int value that can be used in Javascript methods.
+int FieldRendererIdToJsParameter(autofill::FieldRendererId field_id) {
+ return field_id.value();
+}
+
+std::unique_ptr<base::Value> SerializeFillData(
+ const GURL& origin,
+ autofill::FormRendererId form_renderer_id,
+ autofill::FieldRendererId username_element,
+ const std::u16string& username_value,
+ autofill::FieldRendererId password_element,
+ const std::u16string& password_value) {
+ auto root_dict = std::make_unique<base::DictionaryValue>();
+ root_dict->SetString("origin", origin.spec());
+ root_dict->SetInteger("unique_renderer_id",
+ FormRendererIdToJsParameter(form_renderer_id));
+
+ auto fieldList = std::make_unique<base::ListValue>();
+
+ auto usernameField = std::make_unique<base::DictionaryValue>();
+ usernameField->SetInteger("unique_renderer_id",
+ FieldRendererIdToJsParameter(username_element));
+ usernameField->SetString("value", username_value);
+ fieldList->Append(std::move(usernameField));
+
+ auto passwordField = std::make_unique<base::DictionaryValue>();
+ passwordField->SetInteger("unique_renderer_id", password_element.value());
+ passwordField->SetString("value", password_value);
+ fieldList->Append(std::move(passwordField));
+
+ root_dict->Set("fields", std::move(fieldList));
+
+ return root_dict;
+}
+
+// Serializes |fill_data| so it can be used by the JS side of
+// PasswordController. Includes both username and password data if
+// |fill_username|, and only password data otherwise.
+std::unique_ptr<base::Value> SerializeFillData(
+ const password_manager::FillData& fill_data,
+ BOOL fill_username) {
+ return SerializeFillData(fill_data.origin, fill_data.form_id,
+ fill_username ? fill_data.username_element_id
+ : autofill::FieldRendererId(),
+ fill_data.username_value,
+ fill_data.password_element_id,
+ fill_data.password_value);
+}
+
+// Serializes |fill_data| so it can be used by the JS side of
+// PasswordController.
+std::unique_ptr<base::Value> SerializePasswordFormFillData(
+ const autofill::PasswordFormFillData& fill_data) {
+ return SerializeFillData(fill_data.url, fill_data.form_renderer_id,
+ fill_data.username_field.unique_renderer_id,
+ fill_data.username_field.value,
+ fill_data.password_field.unique_renderer_id,
+ fill_data.password_field.value);
+}
+
+} // namespace
+
+// static
+PasswordManagerJavaScriptFeature*
+PasswordManagerJavaScriptFeature::GetInstance() {
+ static base::NoDestructor<PasswordManagerJavaScriptFeature> instance;
+ return instance.get();
+}
+
+PasswordManagerJavaScriptFeature::PasswordManagerJavaScriptFeature()
+ : web::JavaScriptFeature(
+ // TODO(crbug.com/1175793): Move autofill code to kAnyContentWorld
+ // once all scripts are converted to JavaScriptFeatures.
+ ContentWorld::kPageContentWorld,
+ {FeatureScript::CreateWithFilename(
+ kScriptName,
+ FeatureScript::InjectionTime::kDocumentStart,
+ FeatureScript::TargetFrames::kMainFrame,
+ FeatureScript::ReinjectionBehavior::kInjectOncePerWindow)},
+ {web::java_script_features::GetCommonJavaScriptFeature(),
+ web::java_script_features::GetMessageJavaScriptFeature(),
+ autofill::FormUtilJavaScriptFeature::GetInstance()}) {}
+
+PasswordManagerJavaScriptFeature::~PasswordManagerJavaScriptFeature() = default;
+
+void PasswordManagerJavaScriptFeature::FindPasswordFormsInFrame(
+ web::WebFrame* frame,
+ base::OnceCallback<void(NSString*)> callback) {
+ DCHECK(frame->IsMainFrame());
+ DCHECK(!callback.is_null());
+ CallJavaScriptFunction(
+ frame, "passwords.findPasswordForms", {},
+ CreateStringCallback(std::move(callback)),
+ base::TimeDelta::FromSeconds(kJavaScriptExecutionTimeoutInSeconds));
+}
+
+void PasswordManagerJavaScriptFeature::ExtractForm(
+ web::WebFrame* frame,
+ autofill::FormRendererId form_identifier,
+ base::OnceCallback<void(NSString*)> callback) {
+ DCHECK(frame->IsMainFrame());
+ DCHECK(!callback.is_null());
+ std::vector<base::Value> parameters;
+ parameters.emplace_back(FormRendererIdToJsParameter(form_identifier));
+ CallJavaScriptFunction(
+ frame, "passwords.getPasswordFormDataAsString", parameters,
+ CreateStringCallback(std::move(callback)),
+ base::TimeDelta::FromSeconds(kJavaScriptExecutionTimeoutInSeconds));
+}
+
+void PasswordManagerJavaScriptFeature::FillPasswordForm(
+ web::WebFrame* frame,
+ const password_manager::FillData& fill_data,
+ BOOL fill_username,
+ const std::string& username,
+ const std::string& password,
+ base::OnceCallback<void(BOOL)> callback) {
+ DCHECK(frame->IsMainFrame());
+ std::unique_ptr<base::Value> form_value =
+ SerializeFillData(fill_data, fill_username);
+ FillPasswordForm(frame, std::move(form_value), username, password,
+ std::move(callback));
+}
+
+void PasswordManagerJavaScriptFeature::FillPasswordForm(
+ web::WebFrame* frame,
+ const autofill::PasswordFormFillData& fill_data,
+ const std::string& username,
+ const std::string& password,
+ base::OnceCallback<void(BOOL)> callback) {
+ DCHECK(frame->IsMainFrame());
+ std::unique_ptr<base::Value> form_value =
+ SerializePasswordFormFillData(fill_data);
+ FillPasswordForm(frame, std::move(form_value), username, password,
+ std::move(callback));
+}
+
+void PasswordManagerJavaScriptFeature::FillPasswordForm(
+ web::WebFrame* frame,
+ std::unique_ptr<base::Value> form_value,
+ const std::string& username,
+ const std::string& password,
+ base::OnceCallback<void(BOOL)> callback) {
+ DCHECK(frame->IsMainFrame());
+ DCHECK(!callback.is_null());
+ std::vector<base::Value> parameters;
+ parameters.push_back(std::move(*form_value));
+ parameters.emplace_back(std::move(username));
+ parameters.emplace_back(std::move(password));
+ CallJavaScriptFunction(
+ frame, "passwords.fillPasswordForm", parameters,
+ CreateBoolCallback(std::move(callback)),
+ base::TimeDelta::FromSeconds(kJavaScriptExecutionTimeoutInSeconds));
+}
+
+void PasswordManagerJavaScriptFeature::FillPasswordForm(
+ web::WebFrame* frame,
+ autofill::FormRendererId form_identifier,
+ autofill::FieldRendererId new_password_identifier,
+ autofill::FieldRendererId confirm_password_identifier,
+ NSString* generated_password,
+ base::OnceCallback<void(BOOL)> callback) {
+ DCHECK(frame->IsMainFrame());
+ DCHECK(!callback.is_null());
+ std::vector<base::Value> parameters;
+ parameters.emplace_back(FormRendererIdToJsParameter(form_identifier));
+ parameters.emplace_back(
+ FieldRendererIdToJsParameter(new_password_identifier));
+ parameters.emplace_back(
+ FieldRendererIdToJsParameter(confirm_password_identifier));
+ parameters.push_back(
+ base::Value(base::SysNSStringToUTF8(generated_password)));
+ CallJavaScriptFunction(
+ frame, "passwords.fillPasswordFormWithGeneratedPassword", parameters,
+ CreateBoolCallback(std::move(callback)),
+ base::TimeDelta::FromSeconds(kJavaScriptExecutionTimeoutInSeconds));
+}
+
+} // namespace password_manager
diff --git a/chromium/components/password_manager/ios/resources/test_bundle.js b/chromium/components/password_manager/ios/resources/test_bundle.js
deleted file mode 100644
index 8cdf86d819b..00000000000
--- a/chromium/components/password_manager/ios/resources/test_bundle.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// The set of scripts to be injected into the test web view as early
-// as possible.
-goog.provide('__crWeb.testBundle');
-
-goog.require('__crWeb.fill');
-goog.require('__crWeb.form');
-goog.require('__crWeb.passwords');
diff --git a/chromium/components/password_manager/ios/shared_password_controller.h b/chromium/components/password_manager/ios/shared_password_controller.h
index eed7c63f62d..cc17c4523cc 100644
--- a/chromium/components/password_manager/ios/shared_password_controller.h
+++ b/chromium/components/password_manager/ios/shared_password_controller.h
@@ -6,7 +6,6 @@
#define COMPONENTS_PASSWORD_MANAGER_IOS_SHARED_PASSWORD_CONTROLLER_H_
#import <Foundation/Foundation.h>
-#include <memory>
#import "components/autofill/ios/browser/form_suggestion_provider.h"
#import "components/autofill/ios/form_util/form_activity_observer.h"
diff --git a/chromium/components/password_manager/ios/shared_password_controller.mm b/chromium/components/password_manager/ios/shared_password_controller.mm
index 7c5ea1f6384..fbb1302cec7 100644
--- a/chromium/components/password_manager/ios/shared_password_controller.mm
+++ b/chromium/components/password_manager/ios/shared_password_controller.mm
@@ -37,7 +37,6 @@
#include "components/password_manager/core/browser/password_manager_client.h"
#include "components/password_manager/core/browser/password_manager_driver.h"
#include "components/password_manager/ios/account_select_fill_data.h"
-#import "components/password_manager/ios/js_password_manager.h"
#include "components/password_manager/ios/password_manager_ios_util.h"
#include "components/strings/grit/components_strings.h"
#include "ios/web/common/url_scheme_util.h"
@@ -77,7 +76,6 @@ using password_manager::PasswordGenerationFrameHelper;
using password_manager::PasswordManagerClient;
using password_manager::PasswordManagerDriver;
using password_manager::PasswordManagerInterface;
-using password_manager::SerializePasswordFormFillData;
namespace {
@@ -226,9 +224,7 @@ NSString* const kSuggestionSuffix = @" ••••••••";
return;
}
- if (webState->ContentIsHTML()) {
- [self findPasswordFormsAndSendThemToPasswordStore];
- } else {
+ if (!webState->ContentIsHTML()) {
// If the current page is not HTML, it does not contain any HTML forms.
UniqueIDDataTabHelper* uniqueIDDataTabHelper =
UniqueIDDataTabHelper::FromWebState(_webState);
@@ -251,6 +247,10 @@ NSString* const kSuggestionSuffix = @" ••••••••";
uniqueIDDataTabHelper->GetNextAvailableRendererID();
[self.formHelper setUpForUniqueIDsWithInitialState:nextAvailableRendererID
inFrame:web_frame];
+ // Form parsing is run via the main frame for all same origin iframes.
+ if (web_frame->IsMainFrame() && webState->ContentIsHTML()) {
+ [self findPasswordFormsAndSendThemToPasswordStore];
+ }
}
// Track detaching iframes.
@@ -282,6 +282,7 @@ NSString* const kSuggestionSuffix = @" ••••••••";
_lastTypedValue = nil;
_lastFocusedFormIdentifier = FormRendererId();
_lastFocusedFieldIdentifier = FieldRendererId();
+ _passwordManager = nullptr;
}
#pragma mark - FormSuggestionProvider
@@ -387,7 +388,7 @@ NSString* const kSuggestionSuffix = @" ••••••••";
requiresReauth:requiresReauth];
[suggestions addObject:suggestion];
}
- base::Optional<PasswordDropdownState> suggestionState;
+ absl::optional<PasswordDropdownState> suggestionState;
if (suggestions.count) {
suggestionState = PasswordDropdownState::kStandard;
}
@@ -674,21 +675,12 @@ NSString* const kSuggestionSuffix = @" ••••••••";
FieldRendererId confirmPasswordUniqueId =
generationData->confirmation_password_renderer_id;
+ __weak SharedPasswordController* weakSelf = self;
auto generatedPasswordInjected = ^(BOOL success) {
- auto passwordPresaved = ^(BOOL found, const autofill::FormData& form) {
- if (found) {
- _passwordManager->PresaveGeneratedPassword(
- _delegate.passwordManagerDriver, form,
- SysNSStringToUTF16(generatedPassword), newPasswordUniqueId);
- }
- // If the form isn't found, it disappeared between fillPasswordForm below
- // and here. There isn't much that can be done.
- };
if (success) {
- [self.formHelper extractPasswordFormData:formIdentifier
- completionHandler:passwordPresaved];
- self.isPasswordGenerated = YES;
- self.passwordGeneratedIdentifier = newPasswordUniqueId;
+ [weakSelf onFilledPasswordForm:formIdentifier
+ withGeneratedPassword:generatedPassword
+ passwordUniqueId:newPasswordUniqueId];
}
if (completionHandler) {
completionHandler();
@@ -702,6 +694,39 @@ NSString* const kSuggestionSuffix = @" ••••••••";
completionHandler:generatedPasswordInjected];
}
+- (void)onFilledPasswordForm:(FormRendererId)formIdentifier
+ withGeneratedPassword:(NSString*)generatedPassword
+ passwordUniqueId:(FieldRendererId)newPasswordUniqueId {
+ __weak SharedPasswordController* weakSelf = self;
+ auto passwordPresaved = ^(BOOL found, const autofill::FormData& form) {
+ // If the form isn't found, it disappeared between the call to
+ // [self.formHelper fillPasswordForm:newPasswordIdentifier:...]
+ // and here. There isn't much that can be done.
+ if (!found)
+ return;
+
+ [weakSelf presaveGeneratedPassword:generatedPassword
+ passwordUniqueId:newPasswordUniqueId
+ formData:form];
+ };
+
+ [self.formHelper extractPasswordFormData:formIdentifier
+ completionHandler:passwordPresaved];
+ self.isPasswordGenerated = YES;
+ self.passwordGeneratedIdentifier = newPasswordUniqueId;
+}
+
+- (void)presaveGeneratedPassword:(NSString*)generatedPassword
+ passwordUniqueId:(FieldRendererId)newPasswordUniqueId
+ formData:(const autofill::FormData&)formData {
+ if (!_passwordManager)
+ return;
+
+ _passwordManager->PresaveGeneratedPassword(
+ _delegate.passwordManagerDriver, formData,
+ SysNSStringToUTF16(generatedPassword), newPasswordUniqueId);
+}
+
#pragma mark - FormActivityObserver
- (void)webState:(web::WebState*)webState
diff --git a/chromium/components/password_manager/ios/shared_password_controller_unittest.mm b/chromium/components/password_manager/ios/shared_password_controller_unittest.mm
index d6e8e6088c7..8dd3cf0f074 100644
--- a/chromium/components/password_manager/ios/shared_password_controller_unittest.mm
+++ b/chromium/components/password_manager/ios/shared_password_controller_unittest.mm
@@ -162,6 +162,12 @@ TEST_F(SharedPasswordControllerTest, FormsArePropagatedOnHTMLPageLoad) {
OCMExpect([suggestion_helper_ resetForNewPage]);
+ auto web_frame = web::FakeWebFrame::Create("dummy-frame-id",
+ /*is_main_frame=*/true, GURL());
+ [[[form_helper_ expect] ignoringNonObjectArgs]
+ setUpForUniqueIDsWithInitialState:1
+ inFrame:web_frame.get()];
+
id mock_completion_handler =
[OCMArg checkWithBlock:^(void (^completionHandler)(
const std::vector<autofill::FormData>& forms, uint32_t maxID)) {
@@ -174,7 +180,9 @@ TEST_F(SharedPasswordControllerTest, FormsArePropagatedOnHTMLPageLoad) {
}];
OCMExpect([form_helper_
findPasswordFormsWithCompletionHandler:mock_completion_handler]);
+
web_state_.OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS);
+ web_state_.OnWebFrameDidBecomeAvailable(web_frame.get());
[suggestion_helper_ verify];
[form_helper_ verify];
@@ -198,12 +206,12 @@ TEST_F(SharedPasswordControllerTest, NoFormsArePropagatedOnNonHTMLPageLoad) {
// Tests that new frames will trigger PasswordFormHelper to set up unique IDs.
TEST_F(SharedPasswordControllerTest, FormHelperSetsUpUniqueIDsForNewFrame) {
- [[[form_helper_ expect] ignoringNonObjectArgs]
- setUpForUniqueIDsWithInitialState:1
- inFrame:static_cast<web::WebFrame*>(
- [OCMArg anyPointer])];
auto web_frame = web::FakeWebFrame::Create("dummy-frame-id",
/*is_main_frame=*/true, GURL());
+ [[[form_helper_ expect] ignoringNonObjectArgs]
+ setUpForUniqueIDsWithInitialState:1
+ inFrame:web_frame.get()];
+ OCMExpect([form_helper_ findPasswordFormsWithCompletionHandler:[OCMArg any]]);
web_state_.OnWebFrameDidBecomeAvailable(web_frame.get());
}
diff --git a/chromium/components/payments/OWNERS b/chromium/components/payments/OWNERS
index 1dbaa6ad5c4..d04e41dd925 100644
--- a/chromium/components/payments/OWNERS
+++ b/chromium/components/payments/OWNERS
@@ -1,9 +1,7 @@
rouslan@chromium.org
-danyao@chromium.org
maxlg@chromium.org
-sahel@chromium.org
nburris@chromium.org
# Emeritus
-gogerald@chromium.org \ No newline at end of file
+gogerald@chromium.org
diff --git a/chromium/components/payments/content/android/BUILD.gn b/chromium/components/payments/content/android/BUILD.gn
index 06ec330c480..2696c12541f 100644
--- a/chromium/components/payments/content/android/BUILD.gn
+++ b/chromium/components/payments/content/android/BUILD.gn
@@ -29,6 +29,8 @@ static_library("android") {
"payment_manifest_downloader_android.h",
"payment_manifest_parser_android.cc",
"payment_manifest_parser_android.h",
+ "payment_manifest_web_data_service_android.cc",
+ "payment_manifest_web_data_service_android.h",
"payment_request_spec.cc",
"payment_request_spec.h",
"payment_request_update_event_listener.cc",
@@ -41,11 +43,14 @@ static_library("android") {
deps = [
":jni_headers",
"//base",
+ "//components/keyed_service/core",
"//components/payments/content",
"//components/payments/content:utils",
"//components/payments/content/utility",
"//components/payments/core",
"//components/ukm/content:content",
+ "//components/webdata/common",
+ "//components/webdata_services",
"//content/public/browser",
"//net",
"//url:gurl_android",
@@ -66,6 +71,7 @@ generate_jni("jni_headers") {
"java/src/org/chromium/components/payments/PaymentHandlerNavigationThrottle.java",
"java/src/org/chromium/components/payments/PaymentManifestDownloader.java",
"java/src/org/chromium/components/payments/PaymentManifestParser.java",
+ "java/src/org/chromium/components/payments/PaymentManifestWebDataService.java",
"java/src/org/chromium/components/payments/PaymentRequestSpec.java",
"java/src/org/chromium/components/payments/PaymentRequestUpdateEventListener.java",
"java/src/org/chromium/components/payments/PaymentValidator.java",
@@ -131,6 +137,8 @@ android_library("full_java") {
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
sources = [
"java/src/org/chromium/components/payments/AndroidPaymentApp.java",
+ "java/src/org/chromium/components/payments/AndroidPaymentAppFactory.java",
+ "java/src/org/chromium/components/payments/AndroidPaymentAppFinder.java",
"java/src/org/chromium/components/payments/BasicCardUtils.java",
"java/src/org/chromium/components/payments/BrowserPaymentRequest.java",
"java/src/org/chromium/components/payments/CanMakePaymentQuery.java",
@@ -145,6 +153,8 @@ android_library("full_java") {
"java/src/org/chromium/components/payments/PaymentHandlerNavigationThrottle.java",
"java/src/org/chromium/components/payments/PaymentManifestDownloader.java",
"java/src/org/chromium/components/payments/PaymentManifestParser.java",
+ "java/src/org/chromium/components/payments/PaymentManifestVerifier.java",
+ "java/src/org/chromium/components/payments/PaymentManifestWebDataService.java",
"java/src/org/chromium/components/payments/PaymentNotShownError.java",
"java/src/org/chromium/components/payments/PaymentOptionsUtils.java",
"java/src/org/chromium/components/payments/PaymentRequestService.java",
diff --git a/chromium/components/payments/content/android/DEPS b/chromium/components/payments/content/android/DEPS
index 08e0116bf47..e51550b371a 100644
--- a/chromium/components/payments/content/android/DEPS
+++ b/chromium/components/payments/content/android/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+components/embedder_support/android",
"+components/payments/content/android/jni_headers",
+ "+components/webdata_services",
"+mojo/public/java",
"+services/network/public/cpp",
"+ui/android/java/src/org/chromium/ui"
diff --git a/chromium/components/payments/content/android/currency_formatter_android.cc b/chromium/components/payments/content/android/currency_formatter_android.cc
index 4c43f699022..b4be4338b07 100644
--- a/chromium/components/payments/content/android/currency_formatter_android.cc
+++ b/chromium/components/payments/content/android/currency_formatter_android.cc
@@ -4,6 +4,7 @@
#include "components/payments/content/android/currency_formatter_android.h"
+#include <memory>
#include <string>
#include "base/android/jni_string.h"
@@ -23,9 +24,9 @@ CurrencyFormatterAndroid::CurrencyFormatterAndroid(
jobject jcaller,
const JavaParamRef<jstring>& currency_code,
const JavaParamRef<jstring>& locale_name) {
- currency_formatter_.reset(
- new CurrencyFormatter(ConvertJavaStringToUTF8(env, currency_code),
- ConvertJavaStringToUTF8(env, locale_name)));
+ currency_formatter_ = std::make_unique<CurrencyFormatter>(
+ ConvertJavaStringToUTF8(env, currency_code),
+ ConvertJavaStringToUTF8(env, locale_name));
}
CurrencyFormatterAndroid::~CurrencyFormatterAndroid() {}
diff --git a/chromium/components/payments/content/android/payment_feature_list.cc b/chromium/components/payments/content/android/payment_feature_list.cc
index c1bff3655a6..a1fc98f0198 100644
--- a/chromium/components/payments/content/android/payment_feature_list.cc
+++ b/chromium/components/payments/content/android/payment_feature_list.cc
@@ -19,7 +19,7 @@ namespace {
// Entries in this array refer to features defined in
// components/payments/core/features.h, content/public/common/content_features.h
// or the .h file (for Android only features).
-const base::Feature* kFeaturesExposedToJava[] = {
+const base::Feature* const kFeaturesExposedToJava[] = {
&::features::kServiceWorkerPaymentApps,
&::features::kWebPayments,
&::features::kWebPaymentsMinimalUI,
@@ -41,9 +41,9 @@ const base::Feature* kFeaturesExposedToJava[] = {
};
const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
- for (size_t i = 0; i < base::size(kFeaturesExposedToJava); ++i) {
- if (kFeaturesExposedToJava[i]->name == feature_name)
- return kFeaturesExposedToJava[i];
+ for (const base::Feature* feature : kFeaturesExposedToJava) {
+ if (feature->name == feature_name)
+ return feature;
}
NOTREACHED() << "Queried feature cannot be found in PaymentsFeatureList: "
<< feature_name;
diff --git a/chromium/components/payments/content/android/payment_manifest_downloader_android.cc b/chromium/components/payments/content/android/payment_manifest_downloader_android.cc
index de19bd3aff6..73517cd4425 100644
--- a/chromium/components/payments/content/android/payment_manifest_downloader_android.cc
+++ b/chromium/components/payments/content/android/payment_manifest_downloader_android.cc
@@ -123,8 +123,8 @@ static jlong JNI_PaymentManifestDownloader_Init(
return reinterpret_cast<jlong>(new PaymentManifestDownloaderAndroid(
std::make_unique<DeveloperConsoleLogger>(web_contents),
- content::BrowserContext::GetDefaultStoragePartition(
- web_contents->GetBrowserContext())
+ web_contents->GetBrowserContext()
+ ->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess()));
}
diff --git a/chromium/components/payments/content/android/payment_manifest_web_data_service_android.cc b/chromium/components/payments/content/android/payment_manifest_web_data_service_android.cc
new file mode 100644
index 00000000000..49acda015e7
--- /dev/null
+++ b/chromium/components/payments/content/android/payment_manifest_web_data_service_android.cc
@@ -0,0 +1,234 @@
+// 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/payments/content/android/payment_manifest_web_data_service_android.h"
+
+#include <string>
+
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/check_op.h"
+#include "base/notreached.h"
+#include "base/numerics/safe_conversions.h"
+#include "components/keyed_service/core/service_access_type.h"
+#include "components/payments/content/android/jni_headers/PaymentManifestWebDataService_jni.h"
+#include "components/webdata/common/web_data_results.h"
+#include "components/webdata_services/web_data_service_wrapper_factory.h"
+#include "content/public/browser/web_contents.h"
+
+namespace payments {
+
+PaymentManifestWebDataServiceAndroid::PaymentManifestWebDataServiceAndroid(
+ JNIEnv* env,
+ jobject obj,
+ content::WebContents* web_contents)
+ : content::WebContentsObserver(web_contents), weak_java_obj_(env, obj) {}
+
+PaymentManifestWebDataServiceAndroid::~PaymentManifestWebDataServiceAndroid() =
+ default;
+
+void PaymentManifestWebDataServiceAndroid::OnWebDataServiceRequestDone(
+ WebDataServiceBase::Handle h,
+ std::unique_ptr<WDTypedResult> result) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ if (weak_java_obj_.get(env).is_null())
+ return;
+
+ if (web_data_service_requests_.find(h) == web_data_service_requests_.end())
+ return;
+
+ switch (result->GetType()) {
+ case PAYMENT_WEB_APP_MANIFEST:
+ OnWebAppManifestRequestDone(env, h, result.get());
+ break;
+ case PAYMENT_METHOD_MANIFEST:
+ OnPaymentMethodManifestRequestDone(env, h, result.get());
+ break;
+ default:
+ NOTREACHED() << "unsupported data type";
+ }
+}
+
+void PaymentManifestWebDataServiceAndroid::OnWebAppManifestRequestDone(
+ JNIEnv* env,
+ WebDataServiceBase::Handle h,
+ WDTypedResult* result) {
+ const WDResult<std::vector<WebAppManifestSection>>* typed_result =
+ static_cast<const WDResult<std::vector<WebAppManifestSection>>*>(result);
+ const std::vector<WebAppManifestSection>* manifest =
+ &(typed_result->GetValue());
+
+ base::android::ScopedJavaLocalRef<jobjectArray> jmanifest =
+ Java_PaymentManifestWebDataService_createManifest(env, manifest->size());
+
+ for (size_t i = 0; i < manifest->size(); ++i) {
+ const WebAppManifestSection& section = manifest->at(i);
+ DCHECK_GE(100U, section.fingerprints.size());
+
+ Java_PaymentManifestWebDataService_addSectionToManifest(
+ env, jmanifest, base::checked_cast<int>(i),
+ base::android::ConvertUTF8ToJavaString(env, section.id),
+ section.min_version,
+ base::checked_cast<int>(section.fingerprints.size()));
+
+ for (size_t j = 0; j < section.fingerprints.size(); ++j) {
+ const std::vector<uint8_t>& fingerprint = section.fingerprints[j];
+ Java_PaymentManifestWebDataService_addFingerprintToSection(
+ env, jmanifest, base::checked_cast<int>(i),
+ base::checked_cast<int>(j),
+ base::android::ToJavaByteArray(env, fingerprint));
+ }
+ }
+
+ Java_PaymentManifestWebDataServiceCallback_onPaymentWebAppManifestFetched(
+ env, *web_data_service_requests_[h], jmanifest);
+ web_data_service_requests_.erase(h);
+}
+
+void PaymentManifestWebDataServiceAndroid::OnPaymentMethodManifestRequestDone(
+ JNIEnv* env,
+ WebDataServiceBase::Handle h,
+ WDTypedResult* result) {
+ const WDResult<std::vector<std::string>>* typed_result =
+ static_cast<const WDResult<std::vector<std::string>>*>(result);
+ const std::vector<std::string>* web_apps_ids = &(typed_result->GetValue());
+
+ Java_PaymentManifestWebDataServiceCallback_onPaymentMethodManifestFetched(
+ env, *web_data_service_requests_[h],
+ base::android::ToJavaArrayOfStrings(env, *web_apps_ids));
+ web_data_service_requests_.erase(h);
+}
+
+void PaymentManifestWebDataServiceAndroid::Destroy(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj) {
+ scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
+ GetPaymentManifestWebDataService();
+ if (web_data_service) {
+ for (const auto& request : web_data_service_requests_) {
+ web_data_service->CancelRequest(request.first);
+ }
+ web_data_service_requests_.clear();
+ }
+
+ delete this;
+}
+
+void PaymentManifestWebDataServiceAndroid::AddPaymentMethodManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& jmethod_name,
+ const base::android::JavaParamRef<jobjectArray>& japps_package_names) {
+ std::vector<std::string> apps_package_names;
+ base::android::AppendJavaStringArrayToStringVector(env, japps_package_names,
+ &apps_package_names);
+
+ scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
+ GetPaymentManifestWebDataService();
+ if (web_data_service == nullptr)
+ return;
+
+ web_data_service->AddPaymentMethodManifest(
+ base::android::ConvertJavaStringToUTF8(jmethod_name),
+ std::move(apps_package_names));
+}
+
+void PaymentManifestWebDataServiceAndroid::AddPaymentWebAppManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jobjectArray>& jmanifest_sections) {
+ scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
+ GetPaymentManifestWebDataService();
+ if (web_data_service == nullptr)
+ return;
+
+ std::vector<WebAppManifestSection> manifest;
+
+ for (auto jsection : jmanifest_sections.ReadElements<jobject>()) {
+ WebAppManifestSection section;
+
+ section.id = base::android::ConvertJavaStringToUTF8(
+ Java_PaymentManifestWebDataService_getIdFromSection(env, jsection));
+ section.min_version = static_cast<int64_t>(
+ Java_PaymentManifestWebDataService_getMinVersionFromSection(env,
+ jsection));
+
+ base::android::ScopedJavaLocalRef<jobjectArray> jsection_fingerprints(
+ Java_PaymentManifestWebDataService_getFingerprintsFromSection(
+ env, jsection));
+ for (auto jfingerprint : jsection_fingerprints.ReadElements<jbyteArray>()) {
+ std::vector<uint8_t> fingerprint;
+ base::android::JavaByteArrayToByteVector(env, jfingerprint, &fingerprint);
+ section.fingerprints.emplace_back(fingerprint);
+ }
+
+ manifest.emplace_back(std::move(section));
+ }
+
+ web_data_service->AddPaymentWebAppManifest(std::move(manifest));
+}
+
+bool PaymentManifestWebDataServiceAndroid::GetPaymentMethodManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& jmethod_name,
+ const base::android::JavaParamRef<jobject>& jcallback) {
+ scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
+ GetPaymentManifestWebDataService();
+ if (web_data_service == nullptr)
+ return false;
+
+ WebDataServiceBase::Handle handle =
+ web_data_service->GetPaymentMethodManifest(
+ base::android::ConvertJavaStringToUTF8(env, jmethod_name), this);
+ web_data_service_requests_[handle] =
+ std::make_unique<base::android::ScopedJavaGlobalRef<jobject>>(jcallback);
+
+ return true;
+}
+
+bool PaymentManifestWebDataServiceAndroid::GetPaymentWebAppManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& japp_package_name,
+ const base::android::JavaParamRef<jobject>& jcallback) {
+ scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
+ GetPaymentManifestWebDataService();
+ if (web_data_service == nullptr)
+ return false;
+
+ WebDataServiceBase::Handle handle =
+ web_data_service->GetPaymentWebAppManifest(
+ base::android::ConvertJavaStringToUTF8(env, japp_package_name), this);
+ web_data_service_requests_[handle] =
+ std::make_unique<base::android::ScopedJavaGlobalRef<jobject>>(jcallback);
+
+ return true;
+}
+
+static jlong JNI_PaymentManifestWebDataService_Init(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ const base::android::JavaParamRef<jobject>& jweb_contents) {
+ auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents);
+ if (!web_contents)
+ return 0;
+
+ PaymentManifestWebDataServiceAndroid* manifest_web_data_service_android =
+ new PaymentManifestWebDataServiceAndroid(env, obj, web_contents);
+ return reinterpret_cast<intptr_t>(manifest_web_data_service_android);
+}
+
+scoped_refptr<PaymentManifestWebDataService>
+PaymentManifestWebDataServiceAndroid::GetPaymentManifestWebDataService() {
+ if (!web_contents() || !web_contents()->GetBrowserContext())
+ return nullptr;
+
+ return webdata_services::WebDataServiceWrapperFactory::
+ GetPaymentManifestWebDataServiceForBrowserContext(
+ web_contents()->GetBrowserContext(),
+ ServiceAccessType::EXPLICIT_ACCESS);
+}
+
+} // namespace payments
diff --git a/chromium/components/payments/content/android/payment_manifest_web_data_service_android.h b/chromium/components/payments/content/android/payment_manifest_web_data_service_android.h
new file mode 100644
index 00000000000..02a6864dc82
--- /dev/null
+++ b/chromium/components/payments/content/android/payment_manifest_web_data_service_android.h
@@ -0,0 +1,97 @@
+// 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_PAYMENTS_CONTENT_ANDROID_PAYMENT_MANIFEST_WEB_DATA_SERVICE_ANDROID_H_
+#define COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_MANIFEST_WEB_DATA_SERVICE_ANDROID_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/scoped_refptr.h"
+#include "components/payments/content/payment_manifest_web_data_service.h"
+#include "components/webdata/common/web_data_results.h"
+#include "components/webdata/common/web_data_service_base.h"
+#include "components/webdata/common/web_data_service_consumer.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace payments {
+
+// Android wrapper of the PaymentManifestWebDataService which provides access
+// from the Java layer.
+class PaymentManifestWebDataServiceAndroid
+ : public WebDataServiceConsumer,
+ public content::WebContentsObserver {
+ public:
+ PaymentManifestWebDataServiceAndroid(JNIEnv* env,
+ jobject obj,
+ content::WebContents* web_contents);
+ ~PaymentManifestWebDataServiceAndroid() override;
+
+ // Override WebDataServiceConsumer interface.
+ void OnWebDataServiceRequestDone(
+ WebDataServiceBase::Handle h,
+ std::unique_ptr<WDTypedResult> result) override;
+
+ // Destroys this object.
+ void Destroy(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj);
+
+ // Adds the supported |japp_package_names| of the |jmethod_name| to the
+ // cache.
+ void AddPaymentMethodManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& jmethod_name,
+ const base::android::JavaParamRef<jobjectArray>& japp_package_names);
+
+ // Adds the web app |jmanifest_sections|.
+ void AddPaymentWebAppManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jobjectArray>& jmanifest_sections);
+
+ // Gets the payment |jmethod_name|'s manifest asynchronously from the web data
+ // service. Return true if the result will be returned through |jcallback|.
+ bool GetPaymentMethodManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& jmethod_name,
+ const base::android::JavaParamRef<jobject>& jcallback);
+
+ // Gets the payment |japp_package_name|'s manifest asynchronously from the web
+ // data service. Return true if the result will be returned through
+ // |jcallback|.
+ bool GetPaymentWebAppManifest(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& unused_obj,
+ const base::android::JavaParamRef<jstring>& japp_package_name,
+ const base::android::JavaParamRef<jobject>& jcallback);
+
+ private:
+ void OnWebAppManifestRequestDone(JNIEnv* env,
+ WebDataServiceBase::Handle h,
+ WDTypedResult* result);
+ void OnPaymentMethodManifestRequestDone(JNIEnv* env,
+ WebDataServiceBase::Handle h,
+ WDTypedResult* result);
+ scoped_refptr<PaymentManifestWebDataService>
+ GetPaymentManifestWebDataService();
+
+ // Pointer to the java counterpart.
+ JavaObjectWeakGlobalRef weak_java_obj_;
+
+ // Map of request handle and its correspond callback.
+ std::map<WebDataServiceBase::Handle,
+ std::unique_ptr<base::android::ScopedJavaGlobalRef<jobject>>>
+ web_data_service_requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(PaymentManifestWebDataServiceAndroid);
+};
+
+} // namespace payments
+
+#endif // COMPONENTS_PAYMENTS_CONTENT_ANDROID_PAYMENT_MANIFEST_WEB_DATA_SERVICE_ANDROID_H_
diff --git a/chromium/components/payments/content/android/url_util.cc b/chromium/components/payments/content/android/url_util.cc
index 66dc734026e..69cbbe11a3a 100644
--- a/chromium/components/payments/content/android/url_util.cc
+++ b/chromium/components/payments/content/android/url_util.cc
@@ -17,7 +17,15 @@ jboolean JNI_UrlUtil_IsOriginAllowedToUseWebPaymentApis(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& j_url) {
std::unique_ptr<GURL> url = url::GURLAndroid::ToNativeGURL(env, j_url);
- return UrlUtil::IsOriginAllowedToUseWebPaymentApis(*url);
+ return url && UrlUtil::IsOriginAllowedToUseWebPaymentApis(*url);
+}
+
+// static
+jboolean JNI_UrlUtil_IsValidUrlBasedPaymentMethodIdentifier(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_url) {
+ std::unique_ptr<GURL> url = url::GURLAndroid::ToNativeGURL(env, j_url);
+ return url && UrlUtil::IsValidUrlBasedPaymentMethodIdentifier(*url);
}
// static
@@ -25,7 +33,7 @@ jboolean JNI_UrlUtil_IsLocalDevelopmentUrl(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& j_url) {
std::unique_ptr<GURL> url = url::GURLAndroid::ToNativeGURL(env, j_url);
- return UrlUtil::IsLocalDevelopmentUrl(*url);
+ return url && UrlUtil::IsLocalDevelopmentUrl(*url);
}
} // namespace android
diff --git a/chromium/components/payments/content/android_app_communication.h b/chromium/components/payments/content/android_app_communication.h
index e85cee933f6..af99e9b7fc2 100644
--- a/chromium/components/payments/content/android_app_communication.h
+++ b/chromium/components/payments/content/android_app_communication.h
@@ -13,9 +13,10 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/supports_user_data.h"
+#include "base/unguessable_token.h"
#include "components/payments/core/android_app_description.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -31,19 +32,21 @@ namespace payments {
class AndroidAppCommunication : public base::SupportsUserData::Data {
public:
using GetAppDescriptionsCallback = base::OnceCallback<void(
- const base::Optional<std::string>& error_message,
+ const absl::optional<std::string>& error_message,
std::vector<std::unique_ptr<AndroidAppDescription>> app_descriptions)>;
using IsReadyToPayCallback =
- base::OnceCallback<void(const base::Optional<std::string>& error_message,
+ base::OnceCallback<void(const absl::optional<std::string>& error_message,
bool is_ready_to_pay)>;
using InvokePaymentAppCallback =
- base::OnceCallback<void(const base::Optional<std::string>& error_message,
+ base::OnceCallback<void(const absl::optional<std::string>& error_message,
bool is_activity_result_ok,
const std::string& payment_method_identifier,
const std::string& stringified_details)>;
+ using AbortPaymentAppCallback = base::OnceCallback<void(bool)>;
+
// Returns a weak pointer to the instance of AndroidAppCommunication that is
// owned by the given |context|, which should not be null.
static base::WeakPtr<AndroidAppCommunication> GetForBrowserContext(
@@ -82,9 +85,14 @@ class AndroidAppCommunication : public base::SupportsUserData::Data {
const GURL& top_level_origin,
const GURL& payment_request_origin,
const std::string& payment_request_id,
+ const base::UnguessableToken& request_token,
content::WebContents* web_contents,
InvokePaymentAppCallback callback) = 0;
+ // Aborts a payment flow which was previously started with InvokePaymentApp().
+ virtual void AbortPaymentApp(const base::UnguessableToken& request_token,
+ AbortPaymentAppCallback callback) = 0;
+
// Allows usage of a test browser context.
virtual void SetForTesting() = 0;
diff --git a/chromium/components/payments/content/android_app_communication_chrome_os.cc b/chromium/components/payments/content/android_app_communication_chrome_os.cc
index 6f2b561ce25..34e1aa19ddd 100644
--- a/chromium/components/payments/content/android_app_communication_chrome_os.cc
+++ b/chromium/components/payments/content/android_app_communication_chrome_os.cc
@@ -48,7 +48,7 @@ void OnIsImplemented(
if (response->get_valid()->activity_names.empty()) {
// If a TWA does not implement PAY intent in any of its activities, then
// |activity_names| is empty, which is not an error.
- std::move(callback).Run(/*error_message=*/base::nullopt,
+ std::move(callback).Run(/*error_message=*/absl::nullopt,
/*app_descriptions=*/{});
return;
}
@@ -74,7 +74,7 @@ void OnIsImplemented(
std::vector<std::unique_ptr<AndroidAppDescription>> app_descriptions;
app_descriptions.emplace_back(std::move(app));
- std::move(callback).Run(/*error_message=*/base::nullopt,
+ std::move(callback).Run(/*error_message=*/absl::nullopt,
std::move(app_descriptions));
}
@@ -97,7 +97,7 @@ void OnIsReadyToPay(AndroidAppCommunication::IsReadyToPayCallback callback,
return;
}
- std::move(callback).Run(/*error_message=*/base::nullopt,
+ std::move(callback).Run(/*error_message=*/absl::nullopt,
response->get_response());
}
@@ -137,7 +137,7 @@ void OnPaymentAppResponse(
// Chrome OS TWA currently supports only methods::kGooglePlayBilling payment
// method identifier.
std::move(callback).Run(
- /*error_message=*/base::nullopt,
+ /*error_message=*/absl::nullopt,
response->get_valid()->is_activity_result_ok,
/*payment_method_identifier=*/methods::kGooglePlayBilling,
response->get_valid()->stringified_details);
@@ -150,7 +150,7 @@ arc::mojom::PaymentParametersPtr CreatePaymentParameters(
const GURL& top_level_origin,
const GURL& payment_request_origin,
const std::string& payment_request_id,
- base::Optional<std::string>* error_message) {
+ absl::optional<std::string>* error_message) {
// Chrome OS TWA supports only kGooglePlayBilling payment method identifier
// at this time.
auto supported_method_iterator =
@@ -216,14 +216,14 @@ class AndroidAppCommunicationChromeOS : public AndroidAppCommunication {
// Chrome OS supports Android app payment only through a TWA. An empty
// |twa_package_name| indicates that Chrome was not launched from a TWA,
// so there're no payment apps available.
- std::move(callback).Run(/*error_message=*/base::nullopt,
+ std::move(callback).Run(/*error_message=*/absl::nullopt,
/*app_descriptions=*/{});
return;
}
if (!package_name_for_testing_.empty()) {
std::move(callback).Run(
- /*error_message=*/base::nullopt,
+ /*error_message=*/absl::nullopt,
CreateAppForTesting(package_name_for_testing_, method_for_testing_));
return;
}
@@ -257,7 +257,7 @@ class AndroidAppCommunicationChromeOS : public AndroidAppCommunication {
return;
}
- base::Optional<std::string> error_message;
+ absl::optional<std::string> error_message;
auto parameters = CreatePaymentParameters(
package_name, service_name, stringified_method_data, top_level_origin,
payment_request_origin, payment_request_id, &error_message);
@@ -279,6 +279,7 @@ class AndroidAppCommunicationChromeOS : public AndroidAppCommunication {
const GURL& top_level_origin,
const GURL& payment_request_origin,
const std::string& payment_request_id,
+ const base::UnguessableToken& request_token,
content::WebContents* web_contents,
InvokePaymentAppCallback callback) override {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -286,8 +287,8 @@ class AndroidAppCommunicationChromeOS : public AndroidAppCommunication {
// Create and register a token with ArcOverlayManager for the
// browser window. Doing so is required to allow the Android Play Billing
// interface to be overlaid on top of the browser window.
- // TODO(b/172592701): Use base::UnguessableToken::Create().ToString() and
- // send the same value to the Android service.
+ // TODO(crbug.com/1209716): Reuse the request_token for coordinating the
+ // overlay.
std::string billing_token =
payment_request_origin.spec() + "#" + payment_request_id;
ash::ArcOverlayManager* const overlay_manager =
@@ -296,7 +297,7 @@ class AndroidAppCommunicationChromeOS : public AndroidAppCommunication {
overlay_manager->RegisterHostWindow(std::move(billing_token),
web_contents->GetNativeView());
- base::Optional<std::string> error_message;
+ absl::optional<std::string> error_message;
if (package_name_for_testing_ == package_name) {
std::move(callback).Run(error_message,
/*is_activity_result_ok=*/true,
@@ -323,6 +324,7 @@ class AndroidAppCommunicationChromeOS : public AndroidAppCommunication {
/*stringified_details=*/kEmptyDictionaryJson);
return;
}
+ parameters->request_token = request_token.ToString();
payment_app_service->InvokePaymentApp(
std::move(parameters),
@@ -330,6 +332,17 @@ class AndroidAppCommunicationChromeOS : public AndroidAppCommunication {
std::move(overlay_state)));
}
+ void AbortPaymentApp(const base::UnguessableToken& token,
+ AbortPaymentAppCallback callback) override {
+ auto* payment_app_service = get_app_service_.Run(context());
+ if (!payment_app_service) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ payment_app_service->AbortPaymentApp(token.ToString(), std::move(callback));
+ }
+
// AndroidAppCommunication implementation.
void SetForTesting() override {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/chromium/components/payments/content/android_app_communication_stub.cc b/chromium/components/payments/content/android_app_communication_stub.cc
index ab159c94068..cb695366882 100644
--- a/chromium/components/payments/content/android_app_communication_stub.cc
+++ b/chromium/components/payments/content/android_app_communication_stub.cc
@@ -7,8 +7,8 @@
#include <utility>
#include "base/callback.h"
-#include "base/optional.h"
#include "components/payments/core/native_error_strings.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace payments {
namespace {
@@ -23,7 +23,7 @@ class AndroidAppCommunicationStub : public AndroidAppCommunication {
// AndroidAppCommunication implementation.
void GetAppDescriptions(const std::string& twa_package_name,
GetAppDescriptionsCallback callback) override {
- std::move(callback).Run(/*error_message=*/base::nullopt,
+ std::move(callback).Run(/*error_message=*/absl::nullopt,
/*app_descriptions=*/{});
}
@@ -48,6 +48,7 @@ class AndroidAppCommunicationStub : public AndroidAppCommunication {
const GURL& top_level_origin,
const GURL& payment_request_origin,
const std::string& payment_request_id,
+ const base::UnguessableToken& request_token,
content::WebContents* web_contents,
InvokePaymentAppCallback callback) override {
std::move(callback).Run(errors::kUnableToInvokeAndroidPaymentApps,
@@ -56,6 +57,11 @@ class AndroidAppCommunicationStub : public AndroidAppCommunication {
/*stringified_details=*/"{}");
}
+ void AbortPaymentApp(const base::UnguessableToken& request_token,
+ AbortPaymentAppCallback callback) override {
+ std::move(callback).Run(false);
+ }
+
// AndroidAppCommunication implementation.
void SetForTesting() override {}
diff --git a/chromium/components/payments/content/android_app_communication_test_support.h b/chromium/components/payments/content/android_app_communication_test_support.h
index 22617d8960b..1b9794f6040 100644
--- a/chromium/components/payments/content/android_app_communication_test_support.h
+++ b/chromium/components/payments/content/android_app_communication_test_support.h
@@ -90,6 +90,16 @@ class AndroidAppCommunicationTestSupport {
const std::string& payment_method_identifier,
const std::string& stringified_details) = 0;
+ // Sets up the expectation that the test case will invoke a PAY activity, and
+ // then subsequently abort that payment. The invoke callback will be called
+ // when the payment is aborted with an error result, and then the abort will
+ // be reported as successful.
+ virtual void ExpectInvokeAndAbortPaymentApp() = 0;
+
+ // Sets up the expectation that the test case will not abort any payment
+ // flows.
+ virtual void ExpectNoAbortPaymentApp() = 0;
+
// Returns the browser context to use.
virtual content::BrowserContext* context() = 0;
diff --git a/chromium/components/payments/content/android_app_communication_test_support_chrome_os.cc b/chromium/components/payments/content/android_app_communication_test_support_chrome_os.cc
index 43777527f93..341a7f35465 100644
--- a/chromium/components/payments/content/android_app_communication_test_support_chrome_os.cc
+++ b/chromium/components/payments/content/android_app_communication_test_support_chrome_os.cc
@@ -116,6 +116,33 @@ class AndroidAppCommunicationTestSupportChromeOS
}));
}
+ void ExpectInvokeAndAbortPaymentApp() override {
+ EXPECT_CALL(*support_.instance(), InvokePaymentApp(testing::_, testing::_))
+ .WillOnce(testing::Invoke(
+ [this](
+ arc::mojom::PaymentParametersPtr parameters,
+ arc::ArcPaymentAppBridge::InvokePaymentAppCallback callback) {
+ pending_invoke_callback_ = std::move(callback);
+ }));
+
+ EXPECT_CALL(*support_.instance(), AbortPaymentApp(testing::_, testing::_))
+ .WillOnce(testing::Invoke(
+ [this](const std::string& request_token,
+ arc::ArcPaymentAppBridge::AbortPaymentAppCallback callback) {
+ if (!pending_invoke_callback_.is_null()) {
+ std::move(pending_invoke_callback_)
+ .Run(arc::mojom::InvokePaymentAppResult::NewError(
+ "Payment was aborted."));
+ }
+ std::move(callback).Run(true);
+ }));
+ }
+
+ void ExpectNoAbortPaymentApp() override {
+ EXPECT_CALL(*support_.instance(), AbortPaymentApp(testing::_, testing::_))
+ .Times(0);
+ }
+
content::BrowserContext* context() override { return support_.context(); }
private:
@@ -147,6 +174,8 @@ class AndroidAppCommunicationTestSupportChromeOS
arc::ArcPaymentAppBridgeTestSupport support_;
std::vector<std::unique_ptr<AndroidAppDescription>> apps_;
ash::TestArcOverlayManager overlay_manager_;
+
+ arc::ArcPaymentAppBridge::InvokePaymentAppCallback pending_invoke_callback_;
};
} // namespace
diff --git a/chromium/components/payments/content/android_app_communication_test_support_stub.cc b/chromium/components/payments/content/android_app_communication_test_support_stub.cc
index 93df4287e60..bf7d33f9df9 100644
--- a/chromium/components/payments/content/android_app_communication_test_support_stub.cc
+++ b/chromium/components/payments/content/android_app_communication_test_support_stub.cc
@@ -45,6 +45,10 @@ class AndroidAppCommunicationTestSupportStub
const std::string& payment_method_identifier,
const std::string& stringified_details) override {}
+ void ExpectInvokeAndAbortPaymentApp() override {}
+
+ void ExpectNoAbortPaymentApp() override {}
+
content::BrowserContext* context() override { return &context_; }
private:
diff --git a/chromium/components/payments/content/android_app_communication_unittest.cc b/chromium/components/payments/content/android_app_communication_unittest.cc
index ba3ad57dc0f..c707599868a 100644
--- a/chromium/components/payments/content/android_app_communication_unittest.cc
+++ b/chromium/components/payments/content/android_app_communication_unittest.cc
@@ -11,12 +11,13 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/optional.h"
+#include "base/unguessable_token.h"
#include "components/payments/content/android_app_communication_test_support.h"
#include "components/payments/core/android_app_description.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_web_contents_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace payments {
@@ -58,19 +59,19 @@ class AndroidAppCommunicationTest : public testing::Test {
const AndroidAppCommunicationTest& other) = delete;
void OnGetAppDescriptionsResponse(
- const base::Optional<std::string>& error,
+ const absl::optional<std::string>& error,
std::vector<std::unique_ptr<AndroidAppDescription>> apps) {
error_ = error;
apps_ = std::move(apps);
}
- void OnIsReadyToPayResponse(const base::Optional<std::string>& error,
+ void OnIsReadyToPayResponse(const absl::optional<std::string>& error,
bool is_ready_to_pay) {
error_ = error;
is_ready_to_pay_ = is_ready_to_pay;
}
- void OnPaymentAppResponse(const base::Optional<std::string>& error,
+ void OnPaymentAppResponse(const absl::optional<std::string>& error,
bool is_activity_result_ok,
const std::string& payment_method_identifier,
const std::string& stringified_details) {
@@ -83,7 +84,7 @@ class AndroidAppCommunicationTest : public testing::Test {
std::unique_ptr<AndroidAppCommunicationTestSupport> support_;
content::TestWebContentsFactory web_contents_factory_;
content::WebContents* web_contents_;
- base::Optional<std::string> error_;
+ absl::optional<std::string> error_;
std::vector<std::unique_ptr<AndroidAppDescription>> apps_;
bool is_ready_to_pay_ = false;
bool is_activity_result_ok_ = false;
@@ -472,7 +473,7 @@ TEST_F(AndroidAppCommunicationTest, NoArcForInvokePaymentApp) {
"com.example.app", "com.example.app.Activity", stringified_method_data,
GURL("https://top-level-origin.com"),
GURL("https://payment-request-origin.com"), "payment-request-id",
- web_contents_,
+ base::UnguessableToken::Create(), web_contents_,
base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
base::Unretained(this)));
@@ -497,7 +498,7 @@ TEST_F(AndroidAppCommunicationTest, TwaPaymentOnlyWithPlayBilling) {
"com.example.app", "com.example.app.Activity", stringified_method_data,
GURL("https://top-level-origin.com"),
GURL("https://payment-request-origin.com"), "payment-request-id",
- web_contents_,
+ base::UnguessableToken::Create(), web_contents_,
base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
base::Unretained(this)));
@@ -530,7 +531,7 @@ TEST_F(AndroidAppCommunicationTest, NoPaymentWithMoreThanOnePaymentMethodData) {
"com.example.app", "com.example.app.Activity", stringified_method_data,
GURL("https://top-level-origin.com"),
GURL("https://payment-request-origin.com"), "payment-request-id",
- web_contents_,
+ base::UnguessableToken::Create(), web_contents_,
base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
base::Unretained(this)));
@@ -566,7 +567,7 @@ TEST_F(AndroidAppCommunicationTest, PaymentWithEmptyMethodData) {
"com.example.app", "com.example.app.Activity", stringified_method_data,
GURL("https://top-level-origin.com"),
GURL("https://payment-request-origin.com"), "payment-request-id",
- web_contents_,
+ base::UnguessableToken::Create(), web_contents_,
base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
base::Unretained(this)));
@@ -599,7 +600,7 @@ TEST_F(AndroidAppCommunicationTest, UserCancelInvokePaymentApp) {
"com.example.app", "com.example.app.Activity", stringified_method_data,
GURL("https://top-level-origin.com"),
GURL("https://payment-request-origin.com"), "payment-request-id",
- web_contents_,
+ base::UnguessableToken::Create(), web_contents_,
base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
base::Unretained(this)));
@@ -632,7 +633,7 @@ TEST_F(AndroidAppCommunicationTest, UserConfirmInvokePaymentApp) {
"com.example.app", "com.example.app.Activity", stringified_method_data,
GURL("https://top-level-origin.com"),
GURL("https://payment-request-origin.com"), "payment-request-id",
- web_contents_,
+ base::UnguessableToken::Create(), web_contents_,
base::BindOnce(&AndroidAppCommunicationTest::OnPaymentAppResponse,
base::Unretained(this)));
diff --git a/chromium/components/payments/content/android_payment_app.cc b/chromium/components/payments/content/android_payment_app.cc
index f0222582714..60456849845 100644
--- a/chromium/components/payments/content/android_payment_app.cc
+++ b/chromium/components/payments/content/android_payment_app.cc
@@ -32,7 +32,9 @@ AndroidPaymentApp::AndroidPaymentApp(
payment_request_id_(payment_request_id),
description_(std::move(description)),
communication_(communication),
- frame_routing_id_(frame_routing_id) {
+ frame_routing_id_(frame_routing_id),
+ payment_app_token_(base::UnguessableToken::Create()),
+ payment_app_open_(false) {
DCHECK(!payment_method_names.empty());
DCHECK_EQ(payment_method_names.size(), stringified_method_data_->size());
DCHECK_EQ(*payment_method_names.begin(),
@@ -45,7 +47,11 @@ AndroidPaymentApp::AndroidPaymentApp(
app_method_names_ = payment_method_names;
}
-AndroidPaymentApp::~AndroidPaymentApp() = default;
+AndroidPaymentApp::~AndroidPaymentApp() {
+ if (payment_app_open_) {
+ AbortPaymentApp(base::DoNothing());
+ }
+}
void AndroidPaymentApp::InvokePaymentApp(base::WeakPtr<Delegate> delegate) {
// Browser is closing, so no need to invoke a callback.
@@ -61,10 +67,11 @@ void AndroidPaymentApp::InvokePaymentApp(base::WeakPtr<Delegate> delegate) {
if (!web_contents)
return;
+ payment_app_open_ = true;
communication_->InvokePaymentApp(
description_->package, description_->activities.front()->name,
*stringified_method_data_, top_level_origin_, payment_request_origin_,
- payment_request_id_, web_contents,
+ payment_request_id_, payment_app_token_, web_contents,
base::BindOnce(&AndroidPaymentApp::OnPaymentAppResponse,
weak_ptr_factory_.GetWeakPtr(), delegate));
}
@@ -155,6 +162,19 @@ void AndroidPaymentApp::UpdateWith(
void AndroidPaymentApp::OnPaymentDetailsNotUpdated() {}
+void AndroidPaymentApp::AbortPaymentApp(
+ base::OnceCallback<void(bool)> abort_callback) {
+ // Browser is closing or no payment app active, so no need to invoke a
+ // callback.
+ if (!communication_ || !payment_app_open_)
+ return;
+
+ payment_app_open_ = false;
+
+ communication_->AbortPaymentApp(payment_app_token_,
+ std::move(abort_callback));
+}
+
bool AndroidPaymentApp::IsPreferred() const {
// This class used only on Chrome OS, where the only Android payment app
// available is the trusted web application (TWA) that launched this instance
@@ -170,10 +190,11 @@ bool AndroidPaymentApp::IsPreferred() const {
void AndroidPaymentApp::OnPaymentAppResponse(
base::WeakPtr<Delegate> delegate,
- const base::Optional<std::string>& error_message,
+ const absl::optional<std::string>& error_message,
bool is_activity_result_ok,
const std::string& payment_method_identifier,
const std::string& stringified_details) {
+ payment_app_open_ = false;
if (!delegate)
return;
diff --git a/chromium/components/payments/content/android_payment_app.h b/chromium/components/payments/content/android_payment_app.h
index c3e3b90deba..21f3111612e 100644
--- a/chromium/components/payments/content/android_payment_app.h
+++ b/chromium/components/payments/content/android_payment_app.h
@@ -10,11 +10,12 @@
#include <string>
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
+#include "base/unguessable_token.h"
#include "components/payments/content/android_app_communication.h"
#include "components/payments/content/payment_app.h"
#include "components/payments/core/android_app_description.h"
#include "content/public/browser/global_routing_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace payments {
@@ -74,11 +75,12 @@ class AndroidPaymentApp : public PaymentApp {
void UpdateWith(
mojom::PaymentRequestDetailsUpdatePtr details_update) override;
void OnPaymentDetailsNotUpdated() override;
+ void AbortPaymentApp(base::OnceCallback<void(bool)> abort_callback) override;
bool IsPreferred() const override;
private:
void OnPaymentAppResponse(base::WeakPtr<Delegate> delegate,
- const base::Optional<std::string>& error_message,
+ const absl::optional<std::string>& error_message,
bool is_activity_result_ok,
const std::string& payment_method_identifier,
const std::string& stringified_details);
@@ -92,6 +94,13 @@ class AndroidPaymentApp : public PaymentApp {
base::WeakPtr<AndroidAppCommunication> communication_;
content::GlobalFrameRoutingId frame_routing_id_;
+ // Token used to uniquely identify a particular payment app instance between
+ // Android and Chrome.
+ base::UnguessableToken payment_app_token_;
+ // True when InvokePaymentApp() has been called but no response has been
+ // received yet.
+ bool payment_app_open_;
+
base::WeakPtrFactory<AndroidPaymentApp> weak_ptr_factory_{this};
};
diff --git a/chromium/components/payments/content/android_payment_app_factory.cc b/chromium/components/payments/content/android_payment_app_factory.cc
index b31f12854b1..1bbd32dcc78 100644
--- a/chromium/components/payments/content/android_payment_app_factory.cc
+++ b/chromium/components/payments/content/android_payment_app_factory.cc
@@ -84,7 +84,7 @@ class AppFinder : public base::SupportsUserData::Data {
private:
void OnGetAppDescriptions(
- const base::Optional<std::string>& error_message,
+ const absl::optional<std::string>& error_message,
std::vector<std::unique_ptr<AndroidAppDescription>> app_descriptions) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// The browser could be shutting down.
@@ -147,7 +147,7 @@ class AppFinder : public base::SupportsUserData::Data {
single_activity_app->service_names.empty()) {
OnIsReadyToPay(std::move(single_activity_app), payment_method_names,
std::move(stringified_method_data),
- /*error_message=*/base::nullopt,
+ /*error_message=*/absl::nullopt,
/*is_ready_to_pay=*/true);
continue;
}
@@ -173,7 +173,7 @@ class AppFinder : public base::SupportsUserData::Data {
const std::set<std::string>& payment_method_names,
std::unique_ptr<std::map<std::string, std::set<std::string>>>
stringified_method_data,
- const base::Optional<std::string>& error_message,
+ const absl::optional<std::string>& error_message,
bool is_ready_to_pay) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK_LT(0U, number_of_pending_is_ready_to_pay_queries_);
diff --git a/chromium/components/payments/content/android_payment_app_unittest.cc b/chromium/components/payments/content/android_payment_app_unittest.cc
index 56a0f1ddde2..21978b8561d 100644
--- a/chromium/components/payments/content/android_payment_app_unittest.cc
+++ b/chromium/components/payments/content/android_payment_app_unittest.cc
@@ -13,7 +13,7 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/optional.h"
+#include "base/test/bind.h"
#include "components/payments/content/android_app_communication.h"
#include "components/payments/content/android_app_communication_test_support.h"
#include "components/payments/core/android_app_description.h"
@@ -22,6 +22,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_web_contents_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace payments {
@@ -171,5 +172,58 @@ TEST_F(AndroidPaymentAppTest, OnInstrumentDetailsReady) {
}
}
+TEST_F(AndroidPaymentAppTest, AbortWithPaymentAppOpen) {
+ communication_ =
+ AndroidAppCommunication::GetForBrowserContext(support_->context());
+ communication_->SetForTesting();
+ scoped_initialization_ = support_->CreateScopedInitialization();
+
+ support_->ExpectInvokeAndAbortPaymentApp();
+
+ auto app = CreateAndroidPaymentApp(communication_, web_contents_);
+ app->InvokePaymentApp(/*delegate=*/weak_ptr_factory_.GetWeakPtr());
+
+ bool aborted = false;
+ app->AbortPaymentApp(base::BindLambdaForTesting(
+ [&aborted](bool abort_success) { aborted = abort_success; }));
+
+ if (support_->AreAndroidAppsSupportedOnThisPlatform()) {
+ EXPECT_EQ("Payment was aborted.", error_message_);
+ EXPECT_TRUE(aborted);
+ } else {
+ EXPECT_EQ("Unable to invoke Android apps.", error_message_);
+ }
+}
+
+TEST_F(AndroidPaymentAppTest, AbortWhenAppDestroyed) {
+ communication_ =
+ AndroidAppCommunication::GetForBrowserContext(support_->context());
+ communication_->SetForTesting();
+ scoped_initialization_ = support_->CreateScopedInitialization();
+
+ support_->ExpectInvokeAndAbortPaymentApp();
+
+ auto app = CreateAndroidPaymentApp(communication_, web_contents_);
+ app->InvokePaymentApp(/*delegate=*/weak_ptr_factory_.GetWeakPtr());
+ // Payment app will be aborted when |app| is destroyed.
+}
+
+TEST_F(AndroidPaymentAppTest, NoAbortWhenDestroyedWithCompletedFlow) {
+ communication_ =
+ AndroidAppCommunication::GetForBrowserContext(support_->context());
+ communication_->SetForTesting();
+ scoped_initialization_ = support_->CreateScopedInitialization();
+
+ support_->ExpectInvokePaymentAppAndRespond(
+ /*is_activity_result_ok=*/false,
+ /*payment_method_identifier=*/methods::kGooglePlayBilling,
+ /*stringified_details=*/"{}");
+ support_->ExpectNoAbortPaymentApp();
+
+ auto app = CreateAndroidPaymentApp(communication_, web_contents_);
+ app->InvokePaymentApp(/*delegate=*/weak_ptr_factory_.GetWeakPtr());
+ // Payment app will not be aborted when |app| is destroyed.
+}
+
} // namespace
} // namespace payments
diff --git a/chromium/components/payments/content/installable_payment_app_crawler.cc b/chromium/components/payments/content/installable_payment_app_crawler.cc
index d84e79de576..9b391fc24bf 100644
--- a/chromium/components/payments/content/installable_payment_app_crawler.cc
+++ b/chromium/components/payments/content/installable_payment_app_crawler.cc
@@ -166,8 +166,7 @@ void InstallablePaymentAppCrawler::OnPaymentMethodManifestParsed(
return;
content::PermissionController* permission_controller =
- content::BrowserContext::GetPermissionController(
- rfh->GetBrowserContext());
+ rfh->GetBrowserContext()->GetPermissionController();
DCHECK(permission_controller);
for (const auto& web_app_manifest_url : default_applications) {
diff --git a/chromium/components/payments/content/manifest_verifier.cc b/chromium/components/payments/content/manifest_verifier.cc
index e07e8eb4ac5..ab80efa0190 100644
--- a/chromium/components/payments/content/manifest_verifier.cc
+++ b/chromium/components/payments/content/manifest_verifier.cc
@@ -84,16 +84,6 @@ void ManifestVerifier::Verify(
for (auto& app : apps_) {
std::vector<std::string> verified_method_names;
for (const auto& method : app.second->enabled_methods) {
- // For non-URL payment method names, only names published by W3C should be
- // supported. Keep this in sync with AndroidPaymentAppFinder.java.
- if (method == methods::kBasicCard || method == methods::kInterledger ||
- method == methods::kPayeeCreditTransfer ||
- method == methods::kPayerCreditTransfer ||
- method == methods::kTokenizedCard) {
- verified_method_names.emplace_back(method);
- continue;
- }
-
// GURL constructor may crash with some invalid unicode strings.
if (!base::IsStringUTF8(method)) {
log_.Warn("Payment method name \"" + method +
@@ -102,6 +92,7 @@ void ManifestVerifier::Verify(
continue;
}
+ // Only URL payment method names are supported.
GURL method_manifest_url = GURL(method);
if (!UrlUtil::IsValidUrlBasedPaymentMethodIdentifier(
method_manifest_url)) {
diff --git a/chromium/components/payments/content/payment_app.h b/chromium/components/payments/content/payment_app.h
index d47b70601d1..9836d0e0a92 100644
--- a/chromium/components/payments/content/payment_app.h
+++ b/chromium/components/payments/content/payment_app.h
@@ -17,6 +17,7 @@
#include "components/payments/core/payer_data.h"
#include "services/metrics/public/cpp/ukm_source_id.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/skia/include/core/SkBitmap.h"
namespace payments {
diff --git a/chromium/components/payments/content/payment_app_factory.h b/chromium/components/payments/content/payment_app_factory.h
index e615a1783cc..3e33dc1e243 100644
--- a/chromium/components/payments/content/payment_app_factory.h
+++ b/chromium/components/payments/content/payment_app_factory.h
@@ -8,7 +8,6 @@
#include <memory>
#include <vector>
-#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/payments/content/payment_app.h"
diff --git a/chromium/components/payments/content/payment_credential.h b/chromium/components/payments/content/payment_credential.h
index 668159b140f..7665f8ef839 100644
--- a/chromium/components/payments/content/payment_credential.h
+++ b/chromium/components/payments/content/payment_credential.h
@@ -123,11 +123,11 @@ class PaymentCredential : public mojom::PaymentCredential,
State state_ = State::kIdle;
const content::GlobalFrameRoutingId initiator_frame_routing_id_;
scoped_refptr<PaymentManifestWebDataService> web_data_service_;
- base::Optional<WebDataServiceBase::Handle> data_service_request_handle_;
+ absl::optional<WebDataServiceBase::Handle> data_service_request_handle_;
DownloadIconAndShowUserPromptCallback prompt_callback_;
StorePaymentCredentialAndHideUserPromptCallback storage_callback_;
mojo::Receiver<mojom::PaymentCredential> receiver_{this};
- base::Optional<int> pending_icon_download_request_id_;
+ absl::optional<int> pending_icon_download_request_id_;
std::vector<uint8_t> encoded_icon_;
std::unique_ptr<PaymentCredentialEnrollmentController::ScopedToken>
ui_controller_token_;
diff --git a/chromium/components/payments/content/payment_credential_enrollment_model_unittest.cc b/chromium/components/payments/content/payment_credential_enrollment_model_unittest.cc
index 1a56b4c4320..d1132854e57 100644
--- a/chromium/components/payments/content/payment_credential_enrollment_model_unittest.cc
+++ b/chromium/components/payments/content/payment_credential_enrollment_model_unittest.cc
@@ -15,9 +15,10 @@ TEST(PaymentCredentialEnrollmentModelTest, SmokeTest) {
PaymentCredentialEnrollmentModel model;
std::u16string title(u"Use Touch ID to verify and complete your purchase?");
- std::u16string description(base::UTF8ToUTF16(
- "Save payment information to this device and skip bank verification next "
- "time when you use Touch ID to verify your payment with Visa ••••4444."));
+ std::u16string description(
+ u"Save payment information to this device and skip bank verification "
+ u"next "
+ u"time when you use Touch ID to verify your payment with Visa ••••4444.");
std::u16string accept_button_label(u"Use Touch ID");
std::u16string cancel_button_label(u"No thanks");
diff --git a/chromium/components/payments/content/payment_handler_host.cc b/chromium/components/payments/content/payment_handler_host.cc
index 2d98f733561..9bc3cc664c5 100644
--- a/chromium/components/payments/content/payment_handler_host.cc
+++ b/chromium/components/payments/content/payment_handler_host.cc
@@ -29,9 +29,9 @@ content::DevToolsBackgroundServicesContext* GetDevTools(
if (!web_contents)
return nullptr;
- auto* storage_partition = content::BrowserContext::GetStoragePartitionForUrl(
- web_contents->GetBrowserContext(), sw_origin.GetURL(),
- /*can_create=*/true);
+ auto* storage_partition =
+ web_contents->GetBrowserContext()->GetStoragePartitionForUrl(
+ sw_origin.GetURL(), /*can_create=*/true);
if (!storage_partition)
return nullptr;
diff --git a/chromium/components/payments/content/payment_handler_navigation_throttle.cc b/chromium/components/payments/content/payment_handler_navigation_throttle.cc
index 7c463b61b33..8c06a17d518 100644
--- a/chromium/components/payments/content/payment_handler_navigation_throttle.cc
+++ b/chromium/components/payments/content/payment_handler_navigation_throttle.cc
@@ -40,7 +40,8 @@ void PaymentHandlerNavigationThrottle::MarkPaymentHandlerWebContents(
std::unique_ptr<PaymentHandlerNavigationThrottle>
PaymentHandlerNavigationThrottle::MaybeCreateThrottleFor(
content::NavigationHandle* handle) {
- if (!handle->GetWebContents()->GetUserData(
+ if (!handle || !handle->GetWebContents() ||
+ !handle->GetWebContents()->GetUserData(
kPaymentHandlerWebContentsUserDataKey)) {
return nullptr;
}
@@ -49,6 +50,8 @@ PaymentHandlerNavigationThrottle::MaybeCreateThrottleFor(
content::NavigationThrottle::ThrottleCheckResult
PaymentHandlerNavigationThrottle::WillProcessResponse() {
+ if (!navigation_handle())
+ return PROCEED;
const net::HttpResponseHeaders* response_headers =
navigation_handle()->GetResponseHeaders();
if (!response_headers)
diff --git a/chromium/components/payments/content/payment_request_display_manager.cc b/chromium/components/payments/content/payment_request_display_manager.cc
index 92a2166e4de..97f8c69a126 100644
--- a/chromium/components/payments/content/payment_request_display_manager.cc
+++ b/chromium/components/payments/content/payment_request_display_manager.cc
@@ -49,7 +49,7 @@ PaymentRequestDisplayManager::~PaymentRequestDisplayManager() {}
std::unique_ptr<PaymentRequestDisplayManager::DisplayHandle>
PaymentRequestDisplayManager::TryShow(ContentPaymentRequestDelegate* delegate) {
- std::unique_ptr<PaymentRequestDisplayManager::DisplayHandle> handle = nullptr;
+ std::unique_ptr<PaymentRequestDisplayManager::DisplayHandle> handle;
if (!current_handle_) {
handle = std::make_unique<PaymentRequestDisplayManager::DisplayHandle>(
this, delegate);
diff --git a/chromium/components/payments/content/payment_request_web_contents_manager.h b/chromium/components/payments/content/payment_request_web_contents_manager.h
index cb9dad7cf38..a4b6331681c 100644
--- a/chromium/components/payments/content/payment_request_web_contents_manager.h
+++ b/chromium/components/payments/content/payment_request_web_contents_manager.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_PAYMENTS_PAYMENT_REQUEST_WEB_CONTENTS_MANAGER_H_
-#define COMPONENTS_PAYMENTS_PAYMENT_REQUEST_WEB_CONTENTS_MANAGER_H_
+#ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_WEB_CONTENTS_MANAGER_H_
+#define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_WEB_CONTENTS_MANAGER_H_
#include <map>
#include <memory>
@@ -92,4 +92,4 @@ class PaymentRequestWebContentsManager
} // namespace payments
-#endif // COMPONENTS_PAYMENTS_PAYMENT_REQUEST_WEB_CONTENTS_MANAGER_H_
+#endif // COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_WEB_CONTENTS_MANAGER_H_
diff --git a/chromium/components/payments/content/payment_response_helper_unittest.cc b/chromium/components/payments/content/payment_response_helper_unittest.cc
index 1ddd77676e0..5fe19f39134 100644
--- a/chromium/components/payments/content/payment_response_helper_unittest.cc
+++ b/chromium/components/payments/content/payment_response_helper_unittest.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/memory/weak_ptr.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_executor.h"
#include "components/autofill/core/browser/autofill_test_utils.h"
diff --git a/chromium/components/payments/content/secure_payment_confirmation_app.cc b/chromium/components/payments/content/secure_payment_confirmation_app.cc
index a63fe775877..f3390baf73b 100644
--- a/chromium/components/payments/content/secure_payment_confirmation_app.cc
+++ b/chromium/components/payments/content/secure_payment_confirmation_app.cc
@@ -28,6 +28,7 @@
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/fido_types.h"
#include "device/fido/public_key_credential_descriptor.h"
+#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
#include "url/url_constants.h"
namespace payments {
diff --git a/chromium/components/payments/content/secure_payment_confirmation_app.h b/chromium/components/payments/content/secure_payment_confirmation_app.h
index 1112b2a1df2..71c5ebff06e 100644
--- a/chromium/components/payments/content/secure_payment_confirmation_app.h
+++ b/chromium/components/payments/content/secure_payment_confirmation_app.h
@@ -17,7 +17,7 @@
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/web_contents_observer.h"
#include "third_party/blink/public/mojom/payments/payment_request.mojom.h"
-#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
+#include "third_party/blink/public/mojom/webauthn/authenticator.mojom-forward.h"
#include "url/origin.h"
class SkBitmap;
diff --git a/chromium/components/payments/content/service_worker_payment_app_finder.cc b/chromium/components/payments/content/service_worker_payment_app_finder.cc
index 53a0cf5b962..ff4391838f5 100644
--- a/chromium/components/payments/content/service_worker_payment_app_finder.cc
+++ b/chromium/components/payments/content/service_worker_payment_app_finder.cc
@@ -437,8 +437,8 @@ void ServiceWorkerPaymentAppFinder::GetAllPaymentApps(
} else {
downloader = std::make_unique<payments::PaymentManifestDownloader>(
std::make_unique<DeveloperConsoleLogger>(web_contents),
- content::BrowserContext::GetDefaultStoragePartition(
- rfh->GetBrowserContext())
+ rfh->GetBrowserContext()
+ ->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess());
}
diff --git a/chromium/components/payments/content/service_worker_payment_app_unittest.cc b/chromium/components/payments/content/service_worker_payment_app_unittest.cc
index 6c55c31c4e1..775f67ec296 100644
--- a/chromium/components/payments/content/service_worker_payment_app_unittest.cc
+++ b/chromium/components/payments/content/service_worker_payment_app_unittest.cc
@@ -41,7 +41,7 @@ class ServiceWorkerPaymentAppTest : public testing::Test,
amount->currency = "USD";
total->amount = std::move(amount);
details->total = std::move(total);
- details->id = base::Optional<std::string>("123456");
+ details->id = absl::optional<std::string>("123456");
details->modifiers = std::vector<mojom::PaymentDetailsModifierPtr>();
mojom::PaymentDetailsModifierPtr modifier_1 =
diff --git a/chromium/components/payments/content/ssl_validity_checker.cc b/chromium/components/payments/content/ssl_validity_checker.cc
index c56f54cfd85..83608770dea 100644
--- a/chromium/components/payments/content/ssl_validity_checker.cc
+++ b/chromium/components/payments/content/ssl_validity_checker.cc
@@ -66,11 +66,11 @@ bool SslValidityChecker::IsValidPageInPaymentHandlerWindow(
if (!web_contents)
return false;
- GURL url = web_contents->GetLastCommittedURL();
- if (!UrlUtil::IsValidUrlInPaymentHandlerWindow(url))
+ GURL main_frame_url = web_contents->GetVisibleURL();
+ if (!UrlUtil::IsValidUrlInPaymentHandlerWindow(main_frame_url))
return false;
- if (url.SchemeIsCryptographic()) {
+ if (main_frame_url.SchemeIsCryptographic()) {
security_state::SecurityLevel security_level =
GetSecurityLevel(web_contents);
return security_level == security_state::SECURE ||
diff --git a/chromium/components/payments/content/utility/payment_manifest_parser.cc b/chromium/components/payments/content/utility/payment_manifest_parser.cc
index 5f874952567..65aefcbaef9 100644
--- a/chromium/components/payments/content/utility/payment_manifest_parser.cc
+++ b/chromium/components/payments/content/utility/payment_manifest_parser.cc
@@ -193,7 +193,7 @@ void ParseIcons(const base::DictionaryValue& dict,
return;
}
- for (const auto& icon : *icons_list) {
+ for (const auto& icon : icons_list->GetList()) {
if (!icon.is_dict()) {
log.Warn(base::StringPrintf(
"Each item in the list \"%s\" should be a dictionary.",
@@ -471,7 +471,7 @@ bool PaymentManifestParser::ParseWebAppManifestIntoVector(
base::ListValue* fingerprints_list = nullptr;
if (!related_application->GetList(kFingerprints, &fingerprints_list) ||
- fingerprints_list->empty() ||
+ fingerprints_list->GetList().empty() ||
fingerprints_list->GetSize() > kMaximumNumberOfItems) {
log.Error(base::StringPrintf(
"\"%s\" must be a non-empty list of at most %zu items.",
@@ -574,7 +574,7 @@ bool PaymentManifestParser::ParseWebAppInstallationInfoIntoStructs(
if (dict->GetDictionary(kPayment, &payment_dict)) {
const base::ListValue* delegation_list = nullptr;
if (payment_dict->GetList(kSupportedDelegations, &delegation_list)) {
- if (delegation_list->empty() ||
+ if (delegation_list->GetList().empty() ||
delegation_list->GetSize() > kMaximumNumberOfSupportedDelegations) {
log.Error(base::StringPrintf(
"\"%s.%s\" must be a non-empty list of at most %zu entries.",
@@ -582,7 +582,7 @@ bool PaymentManifestParser::ParseWebAppInstallationInfoIntoStructs(
kMaximumNumberOfSupportedDelegations));
return false;
}
- for (const auto& delegation_item : *delegation_list) {
+ for (const auto& delegation_item : delegation_list->GetList()) {
std::string delegation_name = delegation_item.GetString();
if (delegation_name == "shippingAddress") {
installation_info->supported_delegations.shipping_address = true;
diff --git a/chromium/components/payments/core/BUILD.gn b/chromium/components/payments/core/BUILD.gn
index f4e1b4581bf..b53b94aec9a 100644
--- a/chromium/components/payments/core/BUILD.gn
+++ b/chromium/components/payments/core/BUILD.gn
@@ -76,8 +76,6 @@ static_library("core") {
"payments_profile_comparator.h",
"strings_util.cc",
"strings_util.h",
- "web_payment_request.cc",
- "web_payment_request.h",
]
}
@@ -184,7 +182,6 @@ source_set("unit_tests") {
"payment_request_data_util_unittest.cc",
"payment_response_unittest.cc",
"payments_profile_comparator_unittest.cc",
- "web_payment_request_unittest.cc",
]
}
diff --git a/chromium/components/payments/core/can_make_payment_query.cc b/chromium/components/payments/core/can_make_payment_query.cc
index 8e379265716..567395bfbe6 100644
--- a/chromium/components/payments/core/can_make_payment_query.cc
+++ b/chromium/components/payments/core/can_make_payment_query.cc
@@ -10,7 +10,6 @@
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "components/payments/core/features.h"
#include "url/gurl.h"
diff --git a/chromium/components/payments/core/currency_formatter_unittest.cc b/chromium/components/payments/core/currency_formatter_unittest.cc
index 29465e92ed7..5341da69d9a 100644
--- a/chromium/components/payments/core/currency_formatter_unittest.cc
+++ b/chromium/components/payments/core/currency_formatter_unittest.cc
@@ -40,8 +40,8 @@ TEST_P(PaymentsCurrencyFormatterTest, IsValidCurrencyFormat) {
// Convenience so the test cases can use regular spaces.
const std::u16string kSpace(u" ");
- const std::u16string kNonBreakingSpace(base::UTF8ToUTF16(u8"\u00a0"));
- const std::u16string kNarrowNonBreakingSpace(base::UTF8ToUTF16(u8"\u202f"));
+ const std::u16string kNonBreakingSpace(u"\u00a0");
+ const std::u16string kNarrowNonBreakingSpace(u"\u202f");
base::ReplaceChars(actual_output, kNonBreakingSpace, kSpace, &actual_output);
base::ReplaceChars(actual_output, kNarrowNonBreakingSpace, kSpace,
&actual_output);
diff --git a/chromium/components/payments/core/features.cc b/chromium/components/payments/core/features.cc
index f30a29a89bf..4178e3798a8 100644
--- a/chromium/components/payments/core/features.cc
+++ b/chromium/components/payments/core/features.cc
@@ -81,7 +81,7 @@ const base::Feature kEnforceFullDelegation{"EnforceFullDelegation",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kGPayAppDynamicUpdate{"GPayAppDynamicUpdate",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
} // namespace features
} // namespace payments
diff --git a/chromium/components/payments/core/journey_logger.cc b/chromium/components/payments/core/journey_logger.cc
index ab8633a66da..e0ac44c3295 100644
--- a/chromium/components/payments/core/journey_logger.cc
+++ b/chromium/components/payments/core/journey_logger.cc
@@ -11,7 +11,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/re2/src/re2/re2.h"
@@ -307,11 +306,12 @@ void JourneyLogger::RecordTransactionAmount(std::string currency,
// A dictionary of 3-letter recorded currency codes and their approximated USD
// conversion rates. Transaction currencies in currency_conversion_rates are
// recorded after conversion.
+ // Conversion rates last updated on April 9, 2021
const std::unordered_map<std::string, float> currency_conversion_rates = {
- {"USD", 1.0}, {"EUR", 1.14}, {"GBP", 1.27}, {"JPY", 0.0093},
- {"INR", 0.014}, {"CNY", 0.15}, {"CAD", 0.77}, {"RUB", 0.016},
- {"PLN", 0.27}, {"AUD", 0.70}, {"BRL", 0.26}, {"UAH", 0.038},
- {"TWD", 0.032}, {"CZK", 0.045}, {"MXN", 0.052}};
+ {"USD", 1.0}, {"EUR", 1.19}, {"GBP", 1.37}, {"JPY", 0.0091},
+ {"INR", 0.013}, {"CNY", 0.15}, {"CAD", 0.80}, {"RUB", 0.013},
+ {"PLN", 0.26}, {"AUD", 0.76}, {"BRL", 0.18}, {"UAH", 0.036},
+ {"TWD", 0.035}, {"CZK", 0.046}, {"MXN", 0.050}, {"SGD", 0.75}};
std::unordered_map<std::string, float>::const_iterator it =
currency_conversion_rates.find(currency);
// transactions with currencies not included in the conversion dictionary are
diff --git a/chromium/components/payments/core/journey_logger.h b/chromium/components/payments/core/journey_logger.h
index d5cfb38c7d2..026b38e7e83 100644
--- a/chromium/components/payments/core/journey_logger.h
+++ b/chromium/components/payments/core/journey_logger.h
@@ -6,7 +6,6 @@
#define COMPONENTS_PAYMENTS_CORE_JOURNEY_LOGGER_H_
#include <string>
-#include <unordered_map>
#include "base/macros.h"
#include "base/time/time.h"
diff --git a/chromium/components/payments/core/method_strings.cc b/chromium/components/payments/core/method_strings.cc
index bcd0248dbcd..818f4d79c36 100644
--- a/chromium/components/payments/core/method_strings.cc
+++ b/chromium/components/payments/core/method_strings.cc
@@ -8,18 +8,12 @@ namespace payments {
namespace methods {
// Please keep the list alphabetized.
-// Each string must be on a single line to correctly generate
-// MethodStrings.java.
const char kAndroidPay[] = "https://android.com/pay";
const char kBasicCard[] = "basic-card";
const char kGooglePay[] = "https://google.com/pay";
const char kGooglePlayBilling[] = "https://play.google.com/billing";
-const char kInterledger[] = "interledger";
-const char kPayeeCreditTransfer[] = "payee-credit-transfer";
-const char kPayerCreditTransfer[] = "payer-credit-transfer";
const char kSecurePaymentConfirmation[] = "secure-payment-confirmation";
-const char kTokenizedCard[] = "tokenized-card";
} // namespace methods
} // namespace payments
diff --git a/chromium/components/payments/core/method_strings.h b/chromium/components/payments/core/method_strings.h
index 90a199f5bc5..6558a05b684 100644
--- a/chromium/components/payments/core/method_strings.h
+++ b/chromium/components/payments/core/method_strings.h
@@ -28,26 +28,10 @@ extern const char kGooglePay[];
// Google Play Billing method name.
extern const char kGooglePlayBilling[];
-// Interledger method name.
-// https://w3c.github.io/webpayments/proposals/interledger/
-extern const char kInterledger[];
-
-// Credit Transfer method name.
-// https://w3c.github.io/payment-method-credit-transfer/
-extern const char kPayeeCreditTransfer[];
-
-// Credit Transfer method name.
-// https://w3c.github.io/payment-method-credit-transfer/
-extern const char kPayerCreditTransfer[];
-
// Secure Payment Confirmation method name.
// https://github.com/rsolomakhin/secure-payment-confirmation/
extern const char kSecurePaymentConfirmation[];
-// Tokenized Card method name.
-// https://w3c.github.io/webpayments-methods-tokenization/
-extern const char kTokenizedCard[];
-
} // namespace methods
} // namespace payments
diff --git a/chromium/components/payments/core/payment_address.h b/chromium/components/payments/core/payment_address.h
index b29b7d4d43e..26e39ec8d5d 100644
--- a/chromium/components/payments/core/payment_address.h
+++ b/chromium/components/payments/core/payment_address.h
@@ -6,7 +6,6 @@
#define COMPONENTS_PAYMENTS_CORE_PAYMENT_ADDRESS_H_
#include <memory>
-#include <string>
#include <vector>
#include "components/payments/mojom/payment_request_data.mojom.h"
diff --git a/chromium/components/payments/core/payment_currency_amount.h b/chromium/components/payments/core/payment_currency_amount.h
index 48919c2f246..5f72d65698d 100644
--- a/chromium/components/payments/core/payment_currency_amount.h
+++ b/chromium/components/payments/core/payment_currency_amount.h
@@ -6,7 +6,6 @@
#define COMPONENTS_PAYMENTS_CORE_PAYMENT_CURRENCY_AMOUNT_H_
#include <memory>
-#include <string>
#include "components/payments/mojom/payment_request_data.mojom.h"
diff --git a/chromium/components/payments/core/payment_details_modifier.h b/chromium/components/payments/core/payment_details_modifier.h
index d749236ebb8..8e8132da5e0 100644
--- a/chromium/components/payments/core/payment_details_modifier.h
+++ b/chromium/components/payments/core/payment_details_modifier.h
@@ -6,7 +6,6 @@
#define COMPONENTS_PAYMENTS_CORE_PAYMENT_DETAILS_MODIFIER_H_
#include <memory>
-#include <string>
#include <vector>
#include "components/payments/core/payment_item.h"
diff --git a/chromium/components/payments/core/payment_manifest_downloader.cc b/chromium/components/payments/core/payment_manifest_downloader.cc
index ab310ec338d..b5a61b8939e 100644
--- a/chromium/components/payments/core/payment_manifest_downloader.cc
+++ b/chromium/components/payments/core/payment_manifest_downloader.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/check_op.h"
#include "base/containers/contains.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
@@ -30,6 +29,7 @@
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/url_constants.h"
namespace payments {
@@ -256,7 +256,7 @@ void PaymentManifestDownloader::OnURLLoaderCompleteInternal(
for (const auto& value : link_header_util::SplitLinkHeader(link_header)) {
std::string link_url;
- std::unordered_map<std::string, base::Optional<std::string>> params;
+ std::unordered_map<std::string, absl::optional<std::string>> params;
if (!link_header_util::ParseLinkHeaderValue(value.first, value.second,
&link_url, &params)) {
continue;
diff --git a/chromium/components/payments/core/payment_manifest_downloader_unittest.cc b/chromium/components/payments/core/payment_manifest_downloader_unittest.cc
index 81afb2a00b5..af44b2e09ef 100644
--- a/chromium/components/payments/core/payment_manifest_downloader_unittest.cc
+++ b/chromium/components/payments/core/payment_manifest_downloader_unittest.cc
@@ -5,7 +5,6 @@
#include "components/payments/core/payment_manifest_downloader.h"
#include "base/bind.h"
-#include "base/optional.h"
#include "base/strings/stringprintf.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -17,6 +16,7 @@
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace payments {
namespace {
@@ -25,7 +25,7 @@ using testing::_;
static constexpr char kNoContent[] = "";
static constexpr char kNoError[] = "";
-static constexpr base::nullopt_t kNoLinkHeader = base::nullopt;
+static constexpr absl::nullopt_t kNoLinkHeader = absl::nullopt;
static constexpr char kEmptyLinkHeader[] = "";
static constexpr char kNoResponseBody[] = "";
@@ -58,7 +58,7 @@ class PaymentMethodManifestDownloaderTest : public testing::Test {
void ServerResponse(int response_code,
Headers send_headers,
- base::Optional<std::string> link_header,
+ absl::optional<std::string> link_header,
const std::string& response_body,
int net_error) {
scoped_refptr<net::HttpResponseHeaders> headers;
diff --git a/chromium/components/payments/core/web_payment_request.cc b/chromium/components/payments/core/web_payment_request.cc
deleted file mode 100644
index 26e68200c7e..00000000000
--- a/chromium/components/payments/core/web_payment_request.cc
+++ /dev/null
@@ -1,97 +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/payments/core/web_payment_request.h"
-
-#include "base/values.h"
-
-namespace payments {
-
-namespace {
-
-// These are defined as part of the spec at:
-// https://w3c.github.io/payment-request/#paymentrequest-interface
-static const char kPaymentRequestDetails[] = "details";
-static const char kPaymentRequestId[] = "id";
-static const char kPaymentRequestMethodData[] = "methodData";
-static const char kPaymentRequestOptions[] = "options";
-
-} // namespace
-
-WebPaymentRequest::WebPaymentRequest() {}
-WebPaymentRequest::~WebPaymentRequest() = default;
-
-bool WebPaymentRequest::operator==(const WebPaymentRequest& other) const {
- return payment_request_id == other.payment_request_id &&
- shipping_address.Equals(other.shipping_address) &&
- shipping_option == other.shipping_option &&
- method_data == other.method_data && details == other.details &&
- options == other.options;
-}
-
-bool WebPaymentRequest::operator!=(const WebPaymentRequest& other) const {
- return !(*this == other);
-}
-
-WebPaymentRequest::WebPaymentRequest(const WebPaymentRequest& other) {
- *this = other;
-}
-
-WebPaymentRequest& WebPaymentRequest::operator=(
- const WebPaymentRequest& other) {
- payment_request_id = other.payment_request_id;
- shipping_address = other.shipping_address ? other.shipping_address->Clone()
- : mojom::PaymentAddress::New();
- shipping_option = other.shipping_option;
- method_data = other.method_data;
- details = other.details;
- options = other.options;
- return *this;
-}
-
-bool WebPaymentRequest::FromDictionaryValue(
- const base::DictionaryValue& value) {
- method_data.clear();
-
- if (!value.GetString(kPaymentRequestId, &payment_request_id)) {
- return false;
- }
-
- // Parse the payment method data.
- const base::ListValue* method_data_list = nullptr;
- // At least one method is required.
- if (!value.GetList(kPaymentRequestMethodData, &method_data_list) ||
- method_data_list->GetSize() == 0) {
- return false;
- }
- for (size_t i = 0; i < method_data_list->GetSize(); ++i) {
- const base::DictionaryValue* method_data_dict;
- if (!method_data_list->GetDictionary(i, &method_data_dict))
- return false;
-
- payments::PaymentMethodData method_datum;
- if (!method_datum.FromDictionaryValue(*method_data_dict))
- return false;
- method_data.push_back(method_datum);
- }
-
- // Parse the payment details.
- const base::DictionaryValue* payment_details_dict = nullptr;
- if (!value.GetDictionary(kPaymentRequestDetails, &payment_details_dict) ||
- !details.FromDictionaryValue(*payment_details_dict,
- /*requires_total=*/true)) {
- return false;
- }
-
- // Parse the payment options.
- const base::DictionaryValue* payment_options = nullptr;
- // Options field is optional.
- if (value.GetDictionary(kPaymentRequestOptions, &payment_options))
- if (!options.FromDictionaryValue(*payment_options))
- return false;
-
- return true;
-}
-
-} // namespace payments
diff --git a/chromium/components/payments/core/web_payment_request.h b/chromium/components/payments/core/web_payment_request.h
deleted file mode 100644
index 0ca6bdde506..00000000000
--- a/chromium/components/payments/core/web_payment_request.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PAYMENTS_CORE_WEB_PAYMENT_REQUEST_H_
-#define COMPONENTS_PAYMENTS_CORE_WEB_PAYMENT_REQUEST_H_
-
-#include <string>
-#include <vector>
-
-#include "components/payments/core/payment_address.h"
-#include "components/payments/core/payment_details.h"
-#include "components/payments/core/payment_method_data.h"
-#include "components/payments/core/payment_options.h"
-
-// C++ bindings for the PaymentRequest API PaymentRequest. Conforms to the
-// following spec:
-// https://w3c.github.io/payment-request/#paymentrequest-interface
-
-namespace base {
-class DictionaryValue;
-}
-
-namespace payments {
-
-// All of the information provided by a page making a request for payment.
-class WebPaymentRequest {
- public:
- WebPaymentRequest();
- ~WebPaymentRequest();
-
- bool operator==(const WebPaymentRequest& other) const;
- bool operator!=(const WebPaymentRequest& other) const;
- WebPaymentRequest(const WebPaymentRequest& other);
- WebPaymentRequest& operator=(const WebPaymentRequest& other);
-
- // Populates the properties of this WebPaymentRequest from |value|. Returns
- // true if the required values are present.
- bool FromDictionaryValue(const base::DictionaryValue& value);
-
- // The unique ID for this WebPaymentRequest. If it is not provided during
- // construction, one is generated.
- std::string payment_request_id;
-
- // Properties set in order to communicate user choices back to the page.
- mojom::PaymentAddressPtr shipping_address;
- std::string shipping_option;
-
- // Properties set via the constructor for communicating from the page to the
- // browser UI.
- std::vector<PaymentMethodData> method_data;
- PaymentDetails details;
- PaymentOptions options;
-};
-
-} // namespace payments
-
-#endif // COMPONENTS_PAYMENTS_CORE_WEB_PAYMENT_REQUEST_H_
diff --git a/chromium/components/payments/core/web_payment_request_unittest.cc b/chromium/components/payments/core/web_payment_request_unittest.cc
deleted file mode 100644
index 1c5240c8fac..00000000000
--- a/chromium/components/payments/core/web_payment_request_unittest.cc
+++ /dev/null
@@ -1,182 +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/payments/core/web_payment_request.h"
-
-#include <memory>
-
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace payments {
-
-// Tests that populating a WebPaymentRequest from an empty dictionary fails.
-TEST(PaymentRequestTest, ParsingEmptyRequestDictionaryFails) {
- WebPaymentRequest output_request;
- base::DictionaryValue request_dict;
- EXPECT_FALSE(output_request.FromDictionaryValue(request_dict));
-}
-
-// Tests that populating a WebPaymentRequest from a dictionary without all
-// required values fails.
-TEST(PaymentRequestTest, ParsingPartiallyPopulatedRequestDictionaryFails) {
- WebPaymentRequest expected_request;
- WebPaymentRequest output_request;
- base::DictionaryValue request_dict;
-
- // An empty methodData list alone is insufficient.
- auto method_data_list = std::make_unique<base::ListValue>();
- request_dict.Set("methodData", std::move(method_data_list));
-
- EXPECT_FALSE(output_request.FromDictionaryValue(request_dict));
- EXPECT_EQ(expected_request, output_request);
-
- // A non-dictionary value in the methodData list is incorrect.
- method_data_list = std::make_unique<base::ListValue>();
- method_data_list->AppendString("fake method data dictionary");
- request_dict.Set("methodData", std::move(method_data_list));
-
- EXPECT_FALSE(output_request.FromDictionaryValue(request_dict));
- EXPECT_EQ(expected_request, output_request);
-
- // An empty dictionary in the methodData list is still insufficient.
- method_data_list = std::make_unique<base::ListValue>();
- auto method_data_dict = std::make_unique<base::DictionaryValue>();
- method_data_list->Append(std::move(method_data_dict));
- request_dict.Set("methodData", std::move(method_data_list));
-
- EXPECT_FALSE(output_request.FromDictionaryValue(request_dict));
- EXPECT_EQ(expected_request, output_request);
-}
-
-// Tests that populating a WebPaymentRequest from a dictionary with all required
-// elements succeeds and produces the expected result.
-TEST(PaymentRequestTest, ParsingFullyPopulatedRequestDictionarySucceeds) {
- WebPaymentRequest expected_request;
- WebPaymentRequest output_request;
- base::DictionaryValue request_dict;
-
- // Add the expected values to expected_request.
- expected_request.payment_request_id = "123456789";
- expected_request.details.id = "12345";
- expected_request.details.total = std::make_unique<PaymentItem>();
- expected_request.details.total->label = "TOTAL";
- expected_request.details.total->amount->currency = "GBP";
- expected_request.details.total->amount->value = "6.66";
- expected_request.details.error = "Error in details";
-
- PaymentMethodData method_data;
- method_data.supported_method = "Visa";
- expected_request.method_data.push_back(method_data);
-
- // Add the same values to the dictionary to be parsed.
- auto details_dict = std::make_unique<base::DictionaryValue>();
- auto total_dict = std::make_unique<base::DictionaryValue>();
- total_dict->SetString("label", "TOTAL");
- auto amount_dict = std::make_unique<base::DictionaryValue>();
- amount_dict->SetString("currency", "GBP");
- amount_dict->SetString("value", "6.66");
- total_dict->Set("amount", std::move(amount_dict));
- details_dict->Set("total", std::move(total_dict));
- details_dict->SetString("id", "12345");
- details_dict->SetString("error", "Error in details");
- request_dict.Set("details", std::move(details_dict));
-
- auto method_data_list = std::make_unique<base::ListValue>();
- auto method_data_dict = std::make_unique<base::DictionaryValue>();
- method_data_dict->SetString("supportedMethods", "Visa");
- method_data_list->Append(std::move(method_data_dict));
- request_dict.Set("methodData", std::move(method_data_list));
- request_dict.SetString("id", "123456789");
-
- // With the required values present, parsing should succeed.
- EXPECT_TRUE(output_request.FromDictionaryValue(request_dict));
- EXPECT_EQ(expected_request, output_request);
-
- // If payment options are present, parse those as well.
- auto options_dict = std::make_unique<base::DictionaryValue>();
- options_dict->SetBoolean("requestPayerPhone", true);
- options_dict->SetBoolean("requestShipping", true);
- options_dict->SetString("shippingType", "delivery");
- request_dict.Set("options", std::move(options_dict));
-
- PaymentOptions payment_options;
- payment_options.request_payer_phone = true;
- payment_options.request_shipping = true;
- payment_options.shipping_type = PaymentShippingType::DELIVERY;
- expected_request.options = payment_options;
-
- EXPECT_TRUE(output_request.FromDictionaryValue(request_dict));
- EXPECT_EQ(expected_request, output_request);
-}
-
-// Tests that two payment request objects are not equal if their property values
-// differ or one is missing a value present in the other, and equal otherwise.
-// Doesn't test all properties of child objects, relying instead on their
-// respective tests.
-TEST(PaymentRequestTest, WebPaymentRequestEquality) {
- WebPaymentRequest request1;
- WebPaymentRequest request2;
- EXPECT_EQ(request1, request2);
-
- request1.payment_request_id = "12345";
- EXPECT_NE(request1, request2);
- request2.payment_request_id = "54321";
- EXPECT_NE(request1, request2);
- request2.payment_request_id = request1.payment_request_id;
- EXPECT_EQ(request1, request2);
-
- mojom::PaymentAddressPtr address1 = mojom::PaymentAddress::New();
- address1->recipient = "Jessica Jones";
- request1.shipping_address = address1.Clone();
- EXPECT_NE(request1, request2);
- mojom::PaymentAddressPtr address2 = mojom::PaymentAddress::New();
- address2->recipient = "Luke Cage";
- request2.shipping_address = address2.Clone();
- EXPECT_NE(request1, request2);
- request2.shipping_address = address1.Clone();
- EXPECT_EQ(request1, request2);
-
- request1.shipping_option = "2-Day";
- EXPECT_NE(request1, request2);
- request2.shipping_option = "3-Day";
- EXPECT_NE(request1, request2);
- request2.shipping_option = "2-Day";
- EXPECT_EQ(request1, request2);
-
- PaymentMethodData method_datum;
- method_datum.data = "{merchantId: '123456'}";
- std::vector<PaymentMethodData> method_data1;
- method_data1.push_back(method_datum);
- request1.method_data = method_data1;
- EXPECT_NE(request1, request2);
- std::vector<PaymentMethodData> method_data2;
- request2.method_data = method_data2;
- EXPECT_NE(request1, request2);
- request2.method_data = method_data1;
- EXPECT_EQ(request1, request2);
-
- PaymentDetails details1;
- details1.total = std::make_unique<PaymentItem>();
- details1.total->label = "Total";
- request1.details = details1;
- EXPECT_NE(request1, request2);
- PaymentDetails details2;
- details2.total = std::make_unique<PaymentItem>();
- details2.total->amount->value = "0.01";
- request2.details = details2;
- EXPECT_NE(request1, request2);
- request2.details = details1;
- EXPECT_EQ(request1, request2);
-
- PaymentOptions options;
- options.request_shipping = true;
- request1.options = options;
- EXPECT_NE(request1, request2);
- request2.options = options;
- EXPECT_EQ(request1, request2);
-}
-
-} // namespace payments
diff --git a/chromium/components/payments_strings.grdp b/chromium/components/payments_strings.grdp
index 558ce46093c..929f122d52d 100644
--- a/chromium/components/payments_strings.grdp
+++ b/chromium/components/payments_strings.grdp
@@ -257,13 +257,13 @@
<!-- Fields & Editors, sentence-cased -->
<if expr="not use_titlecase">
- <message name="IDS_PAYMENTS_NAME_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing the full name of a person. Sentence-cased. [CHAR-LIMIT=32]" formatter_data="android_java">
+ <message name="IDS_PAYMENTS_NAME_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing the full name of a person. Sentence-cased. [CHAR_LIMIT=32]" formatter_data="android_java">
Name
</message>
- <message name="IDS_PAYMENTS_PHONE_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing a phone number. Sentence-cased. [CHAR-LIMIT=32]">
+ <message name="IDS_PAYMENTS_PHONE_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing a phone number. Sentence-cased. [CHAR_LIMIT=32]">
Phone number
</message>
- <message name="IDS_PAYMENTS_EMAIL_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing an email address. Sentence-cased. [CHAR-LIMIT=32]">
+ <message name="IDS_PAYMENTS_EMAIL_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing an email address. Sentence-cased. [CHAR_LIMIT=32]">
Email
</message>
<message name="IDS_PAYMENTS_SAVE_CARD_TO_DEVICE_CHECKBOX" desc="The label for the checkbox that enables the user to save a credit card to their device, for example, on their phone. Sentence-cased." formatter_data="android_java">
@@ -272,7 +272,7 @@
<message name="IDS_PAYMENTS_ACCEPTED_CARDS_LABEL" desc="The title for the section that displays the card networks that the merchant accepts. Below the title, we show a row of icons indicating the accepted networks (Visa icon, Mastercard icon, etc.). Sentence-cased." formatter_data="android_java">
Accepted cards
</message>
- <message name="IDS_PAYMENTS_CREDIT_CARD_EXPIRATION_DATE_ABBR" desc="Abbreviated label for credit card expiration date. Sentence-cased. [CHAR-LIMIT=32]" formatter_data="android_java">
+ <message name="IDS_PAYMENTS_CREDIT_CARD_EXPIRATION_DATE_ABBR" desc="Abbreviated label for credit card expiration date. Sentence-cased. [CHAR_LIMIT=32]" formatter_data="android_java">
Expires <ph name="EXPIRATION_MONTH">%1$s<ex>06</ex></ph>/<ph name="EXPIRATION_YEAR">%2$s<ex>17</ex></ph>
</message>
<message name="IDS_PAYMENTS_LOADING_MESSAGE" desc="The text that informs the user that payment information is being loaded up. Sentence-cased." formatter_data="android_java">
@@ -293,13 +293,13 @@
</if> <!-- not use_titlecase -->
<!-- Fields & Editors, Title-cased -->
<if expr="use_titlecase">
- <message name="IDS_PAYMENTS_NAME_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing the full name of a person. Title-Cased. [CHAR-LIMIT=32]" formatter_data="android_java">
+ <message name="IDS_PAYMENTS_NAME_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing the full name of a person. Title-Cased. [CHAR_LIMIT=32]" formatter_data="android_java">
Name
</message>
- <message name="IDS_PAYMENTS_PHONE_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing a phone number. Title-Cased. [CHAR-LIMIT=32]">
+ <message name="IDS_PAYMENTS_PHONE_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing a phone number. Title-Cased. [CHAR_LIMIT=32]">
Phone Number
</message>
- <message name="IDS_PAYMENTS_EMAIL_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing an email address. Title-Cased. [CHAR-LIMIT=32]">
+ <message name="IDS_PAYMENTS_EMAIL_FIELD_IN_CONTACT_DETAILS" desc="The label for text input field containing an email address. Title-Cased. [CHAR_LIMIT=32]">
Email
</message>
<message name="IDS_PAYMENTS_SAVE_CARD_TO_DEVICE_CHECKBOX" desc="The label for the checkbox that enables the user to save a credit card to their device, for example, on their phone. Title-Cased.">
@@ -311,7 +311,7 @@
<message name="IDS_PAYMENTS_ACCEPTED_CREDIT_CARDS_LABEL" desc="The title for the section that displays the credit card networks that the merchant accepts. Below the title, we show a row of icons indicating the accepted credit card networks (Visa icon, Mastercard icon, etc.). Title-Cased.">
Accepted Credit Cards
</message>
- <message name="IDS_PAYMENTS_CREDIT_CARD_EXPIRATION_DATE_ABBR" desc="Abbreviated label for credit card expiration date. Title-Cased. [CHAR-LIMIT=32]" formatter_data="android_java">
+ <message name="IDS_PAYMENTS_CREDIT_CARD_EXPIRATION_DATE_ABBR" desc="Abbreviated label for credit card expiration date. Title-Cased. [CHAR_LIMIT=32]" formatter_data="android_java">
Expires <ph name="EXPIRATION_MONTH">%1$s<ex>06</ex></ph>/<ph name="EXPIRATION_YEAR">%2$s<ex>17</ex></ph>
</message>
<message name="IDS_PAYMENTS_LOADING_MESSAGE" desc="The text that informs the user that payment information is being loaded up. Title-Cased.">
@@ -552,8 +552,8 @@
Payment Manifest Parser
</message>
<if expr="is_android">
- <message name="IDS_EXTERNAL_PAYMENT_APP_LEAVE_INCOGNITO_WARNING" desc="Alert dialog text warning the user that incognito mode does not continue into external payment apps." formatter_data="android_java">
- Leaving incognito mode to pay via an external application. Continue?
+ <message name="IDS_EXTERNAL_PAYMENT_APP_LEAVE_INCOGNITO_WARNING" desc="Alert dialog text warning the user that Incognito mode does not continue into external payment apps." formatter_data="android_java">
+ Leaving Incognito mode to pay via an external application. Continue?
</message>
</if>
@@ -658,7 +658,7 @@
Check out faster next time
</message>
<message name="IDS_PAYMENT_CREDENTIAL_ENROLLMENT_OFF_THE_RECORD_DESCRIPTION" desc="Extra description at the bottom of a dialog that asks for the user's permission to set up device-based sign-in (i.e., using their computer's biometric sensor or screen unlock/PIN) to verify card payments. This is shown only in Incognito mode and explains that the sign-in data will be stored to the device.">
- Sign-in data will be stored on this device after you exit incognito mode.
+ Sign-in data will be stored on this device after you exit Incognito mode.
</message>
<message name="IDS_PAYMENT_CREDENTIAL_ENROLLMENT_CANCEL_BUTTON_LABEL" desc="Cancel button label on a dialog that asks for the user's permission to set up device-based sign-in (i.e., using their computer's biometric sensor or screen unlock/PIN) to verify card payments.">
No thanks
diff --git a/chromium/components/pdf/browser/pdf_web_contents_helper.cc b/chromium/components/pdf/browser/pdf_web_contents_helper.cc
index d35474a8381..1a411694513 100644
--- a/chromium/components/pdf/browser/pdf_web_contents_helper.cc
+++ b/chromium/components/pdf/browser/pdf_web_contents_helper.cc
@@ -166,7 +166,7 @@ void PDFWebContentsHelper::OnDragUpdate(
std::unique_ptr<ui::TouchHandleDrawable>
PDFWebContentsHelper::CreateDrawable() {
// We can return null here, as the manager will look after this.
- return std::unique_ptr<ui::TouchHandleDrawable>();
+ return nullptr;
}
void PDFWebContentsHelper::OnManagerWillDestroy(
diff --git a/chromium/components/pdf/renderer/BUILD.gn b/chromium/components/pdf/renderer/BUILD.gn
index 49fa2d308c8..48d09ca8585 100644
--- a/chromium/components/pdf/renderer/BUILD.gn
+++ b/chromium/components/pdf/renderer/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//build/config/features.gni")
+import("//pdf/features.gni")
+
+assert(enable_pdf)
static_library("renderer") {
sources = [
diff --git a/chromium/components/pdf/renderer/DIR_METADATA b/chromium/components/pdf/renderer/DIR_METADATA
deleted file mode 100644
index 507a6cad69c..00000000000
--- a/chromium/components/pdf/renderer/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Internals>Plugins>PDF"
-}
diff --git a/chromium/components/pdf/renderer/pdf_accessibility_tree.cc b/chromium/components/pdf/renderer/pdf_accessibility_tree.cc
index 75c7a4f4d67..1256cb377af 100644
--- a/chromium/components/pdf/renderer/pdf_accessibility_tree.cc
+++ b/chromium/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -10,7 +10,6 @@
#include "base/i18n/break_iterator.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversion_utils.h"
#include "components/pdf/renderer/pdf_ax_action_target.h"
#include "components/strings/grit/components_strings.h"
@@ -1606,11 +1605,11 @@ void PdfAccessibilityTree::HandleAction(
}
}
-base::Optional<PdfAccessibilityTree::AnnotationInfo>
+absl::optional<PdfAccessibilityTree::AnnotationInfo>
PdfAccessibilityTree::GetPdfAnnotationInfoFromAXNode(int32_t ax_node_id) const {
auto iter = node_id_to_annotation_info_.find(ax_node_id);
if (iter == node_id_to_annotation_info_.end())
- return base::nullopt;
+ return absl::nullopt;
return AnnotationInfo(iter->second.page_index, iter->second.annotation_index);
}
diff --git a/chromium/components/pdf/renderer/pdf_accessibility_tree.h b/chromium/components/pdf/renderer/pdf_accessibility_tree.h
index d51e5baff2d..710f2432811 100644
--- a/chromium/components/pdf/renderer/pdf_accessibility_tree.h
+++ b/chromium/components/pdf/renderer/pdf_accessibility_tree.h
@@ -7,15 +7,14 @@
#include <map>
#include <memory>
-#include <string>
#include <vector>
-#include "base/optional.h"
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_source.h"
@@ -64,7 +63,7 @@ class PdfAccessibilityTree : public content::PluginAXTreeSource {
const std::vector<PP_PrivateAccessibilityCharInfo>& chars,
const ppapi::PdfAccessibilityPageObjects& page_objects);
void HandleAction(const PP_PdfAccessibilityActionData& action_data);
- base::Optional<AnnotationInfo> GetPdfAnnotationInfoFromAXNode(
+ absl::optional<AnnotationInfo> GetPdfAnnotationInfoFromAXNode(
int32_t ax_node_id) const;
// Given the AXNode and the character offset within the AXNode, finds the
diff --git a/chromium/components/pdf/renderer/pdf_ax_action_target.cc b/chromium/components/pdf/renderer/pdf_ax_action_target.cc
index 8692548d751..597349587e9 100644
--- a/chromium/components/pdf/renderer/pdf_ax_action_target.cc
+++ b/chromium/components/pdf/renderer/pdf_ax_action_target.cc
@@ -80,7 +80,7 @@ bool PdfAXActionTarget::Click() const {
if (target_plugin_node_.data().role != ax::mojom::Role::kLink)
return false;
- base::Optional<PdfAccessibilityTree::AnnotationInfo> annotation_info_result =
+ absl::optional<PdfAccessibilityTree::AnnotationInfo> annotation_info_result =
pdf_accessibility_tree_source_->GetPdfAnnotationInfoFromAXNode(
target_plugin_node_.data().id);
if (!annotation_info_result.has_value())
diff --git a/chromium/components/pdf_strings.grdp b/chromium/components/pdf_strings.grdp
index fba90b240f5..0f1ef6784a4 100644
--- a/chromium/components/pdf_strings.grdp
+++ b/chromium/components/pdf_strings.grdp
@@ -166,18 +166,6 @@
Thumbnail for page <ph name="THUMBNAIL_PAGE"><ex>1</ex>$1</ph>
</message>
<if expr="chromeos">
- <message name="IDS_PDF_DISCARD_FORM_CHANGES" desc="Title for a dialog that informs the user that the changes they have made to a form will be lost if they continue">
- Discard changes?
- </message>
- <message name="IDS_PDF_DISCARD_FORM_CHANGES_DETAIL" desc="Warning message in dialog that informs the user that the changes they have made to a form will be lost if they continue">
- Form changes will be lost. Are you sure you want to continue?
- </message>
- <message name="IDS_PDF_KEEP_EDITING" desc="Button label for the button that lets the user return and keep editing the changes they made">
- Keep editing
- </message>
- <message name="IDS_PDF_DISCARD" desc="Button label for the button that lets the user discard their unneeded changes">
- Discard
- </message>
<message name="IDS_PDF_ANNOTATION_ANNOTATE" desc="Button tooltip for entering the 'Annotation mode' which allows writing, drawing and highlighting of the PDF document">
Annotate
</message>
diff --git a/chromium/components/performance_manager/BUILD.gn b/chromium/components/performance_manager/BUILD.gn
index eba36a7aea8..a13b9c75472 100644
--- a/chromium/components/performance_manager/BUILD.gn
+++ b/chromium/components/performance_manager/BUILD.gn
@@ -19,6 +19,7 @@ static_library("performance_manager") {
"decorators/page_load_tracker_decorator.cc",
"decorators/page_load_tracker_decorator.h",
"decorators/page_load_tracker_decorator_helper.cc",
+ "decorators/process_metrics_decorator.cc",
"decorators/tab_properties_decorator.cc",
"embedder/binders.h",
"embedder/graph_features_helper.h",
@@ -112,6 +113,7 @@ static_library("performance_manager") {
"process_node_source.h",
"public/decorators/page_live_state_decorator.h",
"public/decorators/page_load_tracker_decorator_helper.h",
+ "public/decorators/process_metrics_decorator.h",
"public/decorators/tab_properties_decorator.h",
"public/execution_context/execution_context.h",
"public/execution_context/execution_context_attached_data.h",
@@ -299,6 +301,7 @@ source_set("unit_tests") {
"test_support:test_support_common",
"//base/test:test_support",
"//base/util/memory_pressure:test_support",
+ "//components/services/storage/public/cpp",
"//content/test:test_support",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/components/performance_manager/DEPS b/chromium/components/performance_manager/DEPS
index ae079ef1ff9..f502731506d 100644
--- a/chromium/components/performance_manager/DEPS
+++ b/chromium/components/performance_manager/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/services/storage/public/cpp",
"+content/public/common",
"+content/public/browser",
"+content/public/test",
@@ -7,6 +8,7 @@ include_rules = [
"+net/base",
"+net/test",
"+services/metrics/public/cpp",
+ "+services/resource_coordinator/public/cpp/memory_instrumentation",
"+services/service_manager/public/cpp",
"+third_party/blink/public/common/features.h",
"+third_party/blink/public/common/tokens",
diff --git a/chromium/components/performance_manager/decorators/freezing_vote_decorator.cc b/chromium/components/performance_manager/decorators/freezing_vote_decorator.cc
index 5ef52cbf91d..d6c72ac859c 100644
--- a/chromium/components/performance_manager/decorators/freezing_vote_decorator.cc
+++ b/chromium/components/performance_manager/decorators/freezing_vote_decorator.cc
@@ -4,8 +4,8 @@
#include "components/performance_manager/decorators/freezing_vote_decorator.h"
-#include "base/optional.h"
#include "components/performance_manager/graph/page_node_impl.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace performance_manager {
@@ -49,7 +49,7 @@ void FreezingVoteDecorator::OnVoteInvalidated(
// causes recursive notifications and useless policy dispatches.
if (page_node->GetNodeState() == NodeState::kLeavingGraph)
return;
- PageNodeImpl::FromNode(page_node)->set_freezing_vote(base::nullopt);
+ PageNodeImpl::FromNode(page_node)->set_freezing_vote(absl::nullopt);
}
} // namespace performance_manager
diff --git a/chromium/components/performance_manager/decorators/freezing_vote_decorator.h b/chromium/components/performance_manager/decorators/freezing_vote_decorator.h
index bb89cfbd1fa..f3c076d55f9 100644
--- a/chromium/components/performance_manager/decorators/freezing_vote_decorator.h
+++ b/chromium/components/performance_manager/decorators/freezing_vote_decorator.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_FREEZING_VOTE_DECORATOR_H_
#define COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_FREEZING_VOTE_DECORATOR_H_
-#include <memory>
-
#include "components/performance_manager/freezing/freezing_vote_aggregator.h"
#include "components/performance_manager/public/freezing/freezing.h"
#include "components/performance_manager/public/graph/graph.h"
diff --git a/chromium/components/performance_manager/decorators/page_live_state_decorator_unittest.cc b/chromium/components/performance_manager/decorators/page_live_state_decorator_unittest.cc
index b1bbfe70b71..510bf1cf99a 100644
--- a/chromium/components/performance_manager/decorators/page_live_state_decorator_unittest.cc
+++ b/chromium/components/performance_manager/decorators/page_live_state_decorator_unittest.cc
@@ -5,7 +5,6 @@
#include "components/performance_manager/public/decorators/page_live_state_decorator.h"
#include "base/bind.h"
-#include "base/callback_forward.h"
#include "base/run_loop.h"
#include "components/performance_manager/test_support/decorators_utils.h"
#include "components/performance_manager/test_support/performance_manager_test_harness.h"
@@ -255,4 +254,4 @@ TEST_F(PageLiveStateDecoratorTest, OnWasDiscardedChanged) {
TestPageLiveStateObserver::ObserverFunction::kOnWasDiscardedChanged);
}
-} // namespace performance_manager \ No newline at end of file
+} // namespace performance_manager
diff --git a/chromium/components/performance_manager/decorators/page_load_tracker_decorator.h b/chromium/components/performance_manager/decorators/page_load_tracker_decorator.h
index b0eae5bf206..6a65bb1a6b7 100644
--- a/chromium/components/performance_manager/decorators/page_load_tracker_decorator.h
+++ b/chromium/components/performance_manager/decorators/page_load_tracker_decorator.h
@@ -187,4 +187,4 @@ class PageLoadTrackerDecorator::Data {
} // namespace performance_manager
-#endif // COMPONENTS_BROWSER_PERFORMANCE_MANAGER_DECORATORS_PAGE_LOAD_TRACKER_DECORATOR_H_
+#endif // COMPONENTS_PERFORMANCE_MANAGER_DECORATORS_PAGE_LOAD_TRACKER_DECORATOR_H_
diff --git a/chromium/components/performance_manager/decorators/process_metrics_decorator.cc b/chromium/components/performance_manager/decorators/process_metrics_decorator.cc
new file mode 100644
index 00000000000..1b96b9c6174
--- /dev/null
+++ b/chromium/components/performance_manager/decorators/process_metrics_decorator.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/performance_manager/public/decorators/process_metrics_decorator.h"
+
+#include <memory>
+
+#include "base/feature_list.h"
+#include "build/build_config.h"
+#include "components/performance_manager/graph/graph_impl.h"
+#include "components/performance_manager/graph/node_attached_data_impl.h"
+#include "components/performance_manager/graph/process_node_impl.h"
+#include "components/performance_manager/graph/system_node_impl.h"
+#include "components/performance_manager/public/features.h"
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h"
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
+
+namespace performance_manager {
+
+namespace {
+
+// The default process metrics refresh interval.
+constexpr base::TimeDelta kDefaultRefreshTimerPeriod =
+ base::TimeDelta::FromMinutes(2);
+
+#if !defined(OS_ANDROID)
+// The fast process metrics refresh interval. Used in certain situations, see
+// the comment in ProcessMetricsDecorator::StartTimer for more details.
+constexpr base::TimeDelta kFastRefreshTimerPeriod =
+ base::TimeDelta::FromSeconds(20);
+#endif
+
+} // namespace
+
+ProcessMetricsDecorator::ProcessMetricsDecorator() {
+ DETACH_FROM_SEQUENCE(sequence_checker_);
+}
+ProcessMetricsDecorator::~ProcessMetricsDecorator() = default;
+
+// Concrete implementation of a
+// ProcessMetricsDecorator::ScopedMetricsInterestToken
+class ProcessMetricsDecorator::ScopedMetricsInterestTokenImpl
+ : public ProcessMetricsDecorator::ScopedMetricsInterestToken {
+ public:
+ explicit ScopedMetricsInterestTokenImpl(Graph* graph);
+ ScopedMetricsInterestTokenImpl(const ScopedMetricsInterestTokenImpl& other) =
+ delete;
+ ScopedMetricsInterestTokenImpl& operator=(
+ const ScopedMetricsInterestTokenImpl&) = delete;
+ ~ScopedMetricsInterestTokenImpl() override;
+
+ protected:
+ Graph* graph_;
+};
+
+ProcessMetricsDecorator::ScopedMetricsInterestTokenImpl::
+ ScopedMetricsInterestTokenImpl(Graph* graph)
+ : graph_(graph) {
+ auto* decorator = graph->GetRegisteredObjectAs<ProcessMetricsDecorator>();
+ DCHECK(decorator);
+ decorator->OnMetricsInterestTokenCreated();
+}
+
+ProcessMetricsDecorator::ScopedMetricsInterestTokenImpl::
+ ~ScopedMetricsInterestTokenImpl() {
+ auto* decorator = graph_->GetRegisteredObjectAs<ProcessMetricsDecorator>();
+ // This could be destroyed after removing the decorator from the graph.
+ if (decorator)
+ decorator->OnMetricsInterestTokenReleased();
+}
+
+// static
+std::unique_ptr<ProcessMetricsDecorator::ScopedMetricsInterestToken>
+ProcessMetricsDecorator::RegisterInterestForProcessMetrics(Graph* graph) {
+ return std::make_unique<ScopedMetricsInterestTokenImpl>(graph);
+}
+
+void ProcessMetricsDecorator::OnPassedToGraph(Graph* graph) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ graph_ = graph;
+ graph_->RegisterObject(this);
+}
+
+void ProcessMetricsDecorator::OnTakenFromGraph(Graph* graph) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ StopTimer();
+ graph_->UnregisterObject(this);
+ graph_ = nullptr;
+}
+
+void ProcessMetricsDecorator::OnMetricsInterestTokenCreated() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ ++metrics_interest_token_count_;
+ if (metrics_interest_token_count_ == 1)
+ StartTimer();
+}
+
+void ProcessMetricsDecorator::OnMetricsInterestTokenReleased() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_GT(metrics_interest_token_count_, 0U);
+ --metrics_interest_token_count_;
+ if (metrics_interest_token_count_ == 0)
+ StopTimer();
+}
+
+void ProcessMetricsDecorator::StartTimer() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ base::TimeDelta refresh_period = kDefaultRefreshTimerPeriod;
+
+#if !defined(OS_ANDROID)
+ // Bump the refresh frequency when urgent discarding is done from the graph or
+ // when discarding tabs on high PMF as these features relies on relatively
+ // fresh data.
+ // TODO(sebmarchand): Measure the performance impact of this.
+ if (base::FeatureList::IsEnabled(
+ features::kUrgentDiscardingFromPerformanceManager) ||
+ base::FeatureList::IsEnabled(features::kHighPMFDiscardPolicy)) {
+ refresh_period = kFastRefreshTimerPeriod;
+ }
+#endif
+
+ refresh_timer_.Start(
+ FROM_HERE, refresh_period,
+ base::BindRepeating(&ProcessMetricsDecorator::RefreshMetrics,
+ base::Unretained(this)));
+}
+
+void ProcessMetricsDecorator::StopTimer() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ refresh_timer_.Stop();
+}
+
+void ProcessMetricsDecorator::RefreshMetrics() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ RequestProcessesMemoryMetrics(base::BindOnce(
+ &ProcessMetricsDecorator::DidGetMemoryUsage, weak_factory_.GetWeakPtr()));
+}
+
+void ProcessMetricsDecorator::RequestProcessesMemoryMetrics(
+ memory_instrumentation::MemoryInstrumentation::RequestGlobalDumpCallback
+ callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(sebmarchand): Use the synchronous calls once they are available.
+ auto* mem_instrumentation =
+ memory_instrumentation::MemoryInstrumentation::GetInstance();
+ // The memory instrumentation service is not available in unit tests unless
+ // explicitly created.
+ if (mem_instrumentation) {
+ mem_instrumentation->RequestPrivateMemoryFootprint(base::kNullProcessId,
+ std::move(callback));
+ }
+}
+
+void ProcessMetricsDecorator::DidGetMemoryUsage(
+ bool success,
+ std::unique_ptr<memory_instrumentation::GlobalMemoryDump> process_dumps) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!success)
+ return;
+
+ auto* graph_impl = GraphImpl::FromGraph(graph_);
+
+ // Refresh the process nodes with the data contained in |process_dumps|.
+ // Processes for which we don't receive any data will retain the previously
+ // set value.
+ // TODO(sebmarchand): Check if we should set the data to 0 instead, or add a
+ // timestamp to the data.
+ for (const auto& process_dump_iter : process_dumps->process_dumps()) {
+ // Check if there's a process node associated with this PID.
+ auto* node = graph_impl->GetProcessNodeByPid(process_dump_iter.pid());
+ if (!node)
+ continue;
+
+ node->set_private_footprint_kb(
+ process_dump_iter.os_dump().private_footprint_kb);
+ node->set_resident_set_kb(process_dump_iter.os_dump().resident_set_kb);
+ }
+
+ GraphImpl::FromGraph(graph_)
+ ->FindOrCreateSystemNodeImpl()
+ ->OnProcessMemoryMetricsAvailable();
+ refresh_timer_.Reset();
+}
+
+} // namespace performance_manager
diff --git a/chromium/components/performance_manager/decorators/site_data_recorder_unittest.cc b/chromium/components/performance_manager/decorators/site_data_recorder_unittest.cc
index 003bea3d06c..d3cfe2e66ec 100644
--- a/chromium/components/performance_manager/decorators/site_data_recorder_unittest.cc
+++ b/chromium/components/performance_manager/decorators/site_data_recorder_unittest.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/callback_forward.h"
#include "base/location.h"
#include "base/run_loop.h"
#include "base/task/post_task.h"
diff --git a/chromium/components/performance_manager/embedder/performance_manager_lifetime.h b/chromium/components/performance_manager/embedder/performance_manager_lifetime.h
index ebf8b882e20..9d7fca3e965 100644
--- a/chromium/components/performance_manager/embedder/performance_manager_lifetime.h
+++ b/chromium/components/performance_manager/embedder/performance_manager_lifetime.h
@@ -44,7 +44,7 @@ class PerformanceManagerLifetime {
// used in tests. This needs to be set before PerformanceManagerLifetime is
// created. In browser tests this occurs as part of Chrome browser main parts.
static void SetDecoratorsOverrideForTesting(
- base::Optional<Decorators> decorators_override);
+ absl::optional<Decorators> decorators_override);
private:
std::unique_ptr<PerformanceManager> performance_manager_;
diff --git a/chromium/components/performance_manager/execution_context/execution_context_registry_impl.h b/chromium/components/performance_manager/execution_context/execution_context_registry_impl.h
index a551337bf0d..d81047d5ca3 100644
--- a/chromium/components/performance_manager/execution_context/execution_context_registry_impl.h
+++ b/chromium/components/performance_manager/execution_context/execution_context_registry_impl.h
@@ -103,4 +103,4 @@ class ExecutionContextRegistryImpl
} // namespace execution_context
} // namespace performance_manager
-#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_EXECUTION_CONTEXT_EXECUTION_CONTEXT_REGISTRY_H_
+#endif // COMPONENTS_PERFORMANCE_MANAGER_EXECUTION_CONTEXT_EXECUTION_CONTEXT_REGISTRY_IMPL_H_
diff --git a/chromium/components/performance_manager/execution_context_priority/boosting_vote_aggregator.h b/chromium/components/performance_manager/execution_context_priority/boosting_vote_aggregator.h
index 41578ab28b4..fc8e2a05fe7 100644
--- a/chromium/components/performance_manager/execution_context_priority/boosting_vote_aggregator.h
+++ b/chromium/components/performance_manager/execution_context_priority/boosting_vote_aggregator.h
@@ -9,10 +9,9 @@
#include <set>
#include "base/containers/flat_map.h"
-#include "base/macros.h"
-#include "base/optional.h"
#include "base/task/task_traits.h"
#include "components/performance_manager/public/execution_context_priority/execution_context_priority.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace performance_manager {
namespace execution_context_priority {
@@ -74,6 +73,8 @@ class BoostingVote {
class BoostingVoteAggregator : public VoteObserver {
public:
BoostingVoteAggregator();
+ BoostingVoteAggregator(const BoostingVoteAggregator&) = delete;
+ BoostingVoteAggregator& operator=(const BoostingVoteAggregator&) = delete;
~BoostingVoteAggregator() override;
// Both of these must be called in order for the aggregator to be setup
@@ -137,7 +138,7 @@ class BoostingVoteAggregator : public VoteObserver {
}
void RemoveIncomingVote() {
DCHECK(incoming_vote_.has_value());
- incoming_vote_ = base::nullopt;
+ incoming_vote_ = absl::nullopt;
}
// Updates the incoming vote.
void UpdateIncomingVote(const Vote& incoming_vote) {
@@ -152,7 +153,7 @@ class BoostingVoteAggregator : public VoteObserver {
}
void CancelOutgoingVote() {
DCHECK(outgoing_vote_.has_value());
- outgoing_vote_ = base::nullopt;
+ outgoing_vote_ = absl::nullopt;
}
// Updates the outgoing vote. Returns true if it changed.
bool UpdateOutgoingVote(const Vote& outgoing_vote) {
@@ -192,10 +193,10 @@ class BoostingVoteAggregator : public VoteObserver {
size_t edge_count_ = 0;
// The input vote we've received, if any.
- base::Optional<Vote> incoming_vote_;
+ absl::optional<Vote> incoming_vote_;
// The output vote we're emitted, if any.
- base::Optional<Vote> outgoing_vote_;
+ absl::optional<Vote> outgoing_vote_;
};
// NOTE: It is important that NodeDataMap preserve pointers to NodeData
@@ -397,8 +398,6 @@ class BoostingVoteAggregator : public VoteObserver {
// NodeData.
ForwardEdges forward_edges_;
ReverseEdges reverse_edges_;
-
- DISALLOW_COPY_AND_ASSIGN(BoostingVoteAggregator);
};
} // namespace execution_context_priority
diff --git a/chromium/components/performance_manager/execution_context_priority/inherit_client_priority_voter.h b/chromium/components/performance_manager/execution_context_priority/inherit_client_priority_voter.h
index 01b8384e79d..6d0ab1c93ac 100644
--- a/chromium/components/performance_manager/execution_context_priority/inherit_client_priority_voter.h
+++ b/chromium/components/performance_manager/execution_context_priority/inherit_client_priority_voter.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_PERFORMANCE_MANAGER_EXECUTION_CONTEXT_PRIORITY_INHERIT_CLIENT_PRIORITY_VOTER_H_
#define COMPONENTS_PERFORMANCE_MANAGER_EXECUTION_CONTEXT_PRIORITY_INHERIT_CLIENT_PRIORITY_VOTER_H_
-#include <map>
-
#include "components/performance_manager/execution_context_priority/max_vote_aggregator.h"
#include "components/performance_manager/public/execution_context_priority/execution_context_priority.h"
#include "components/performance_manager/public/graph/frame_node.h"
diff --git a/chromium/components/performance_manager/execution_context_priority/max_vote_aggregator.cc b/chromium/components/performance_manager/execution_context_priority/max_vote_aggregator.cc
index 15b03a5c35f..980faceecf2 100644
--- a/chromium/components/performance_manager/execution_context_priority/max_vote_aggregator.cc
+++ b/chromium/components/performance_manager/execution_context_priority/max_vote_aggregator.cc
@@ -33,7 +33,7 @@ void MaxVoteAggregator::OnVoteSubmitted(
// Remember the previous top vote before adding the new vote. There could be
// none if this is the first vote submitted for |execution_context|.
- base::Optional<Vote> old_top_vote;
+ absl::optional<Vote> old_top_vote;
if (!vote_data.IsEmpty())
old_top_vote = vote_data.GetTopVote();
diff --git a/chromium/components/performance_manager/execution_context_priority/max_vote_aggregator.h b/chromium/components/performance_manager/execution_context_priority/max_vote_aggregator.h
index 5ab89fb0efe..6e05f0772a8 100644
--- a/chromium/components/performance_manager/execution_context_priority/max_vote_aggregator.h
+++ b/chromium/components/performance_manager/execution_context_priority/max_vote_aggregator.h
@@ -21,6 +21,8 @@ namespace execution_context_priority {
class MaxVoteAggregator : public VoteObserver {
public:
MaxVoteAggregator();
+ MaxVoteAggregator(const MaxVoteAggregator&) = delete;
+ MaxVoteAggregator& operator=(const MaxVoteAggregator&) = delete;
~MaxVoteAggregator() override;
// Issues a voting channel (effectively registered a voter).
@@ -127,8 +129,6 @@ class MaxVoteAggregator : public VoteObserver {
// Received votes, plus all of the upstreamed votes.
VoteDataMap vote_data_map_;
-
- DISALLOW_COPY_AND_ASSIGN(MaxVoteAggregator);
};
} // namespace execution_context_priority
diff --git a/chromium/components/performance_manager/execution_context_priority/override_vote_aggregator.cc b/chromium/components/performance_manager/execution_context_priority/override_vote_aggregator.cc
index 672340889dc..1d5edce7f51 100644
--- a/chromium/components/performance_manager/execution_context_priority/override_vote_aggregator.cc
+++ b/chromium/components/performance_manager/execution_context_priority/override_vote_aggregator.cc
@@ -47,7 +47,7 @@ void OverrideVoteAggregator::OnVoteSubmitted(
// Remember the previous chosen vote before adding the new vote. There could
// be none if the this the first vote submitted for |execution_context|.
- base::Optional<Vote> old_chosen_vote;
+ absl::optional<Vote> old_chosen_vote;
if (vote_data.HasChosenVote())
old_chosen_vote = vote_data.GetChosenVote();
@@ -150,11 +150,11 @@ void OverrideVoteAggregator::VoteData::RemoveVote(VoterType voter_type) {
switch (voter_type) {
case VoterType::kDefault:
DCHECK(default_vote_.has_value());
- default_vote_ = base::nullopt;
+ default_vote_ = absl::nullopt;
break;
case VoterType::kOverride:
DCHECK(override_vote_.has_value());
- override_vote_ = base::nullopt;
+ override_vote_ = absl::nullopt;
break;
}
}
diff --git a/chromium/components/performance_manager/execution_context_priority/override_vote_aggregator.h b/chromium/components/performance_manager/execution_context_priority/override_vote_aggregator.h
index e2c9f449e37..b631c896677 100644
--- a/chromium/components/performance_manager/execution_context_priority/override_vote_aggregator.h
+++ b/chromium/components/performance_manager/execution_context_priority/override_vote_aggregator.h
@@ -7,8 +7,8 @@
#include <map>
-#include "base/optional.h"
#include "components/performance_manager/public/execution_context_priority/execution_context_priority.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace performance_manager {
namespace execution_context_priority {
@@ -72,8 +72,8 @@ class OverrideVoteAggregator : public VoteObserver {
private:
// At least one of these is not null if a vote has been emitted for this
// execution context.
- base::Optional<Vote> default_vote_;
- base::Optional<Vote> override_vote_;
+ absl::optional<Vote> default_vote_;
+ absl::optional<Vote> override_vote_;
};
using VoteDataMap = std::map<const ExecutionContext*, VoteData>;
diff --git a/chromium/components/performance_manager/execution_context_priority/root_vote_observer_unittest.cc b/chromium/components/performance_manager/execution_context_priority/root_vote_observer_unittest.cc
index 8abb21905b1..6cd892e203d 100644
--- a/chromium/components/performance_manager/execution_context_priority/root_vote_observer_unittest.cc
+++ b/chromium/components/performance_manager/execution_context_priority/root_vote_observer_unittest.cc
@@ -24,13 +24,13 @@ static const char kReason[] = "test reason";
class LenientMockFrameNodeObserver : public FrameNode::ObserverDefaultImpl {
public:
LenientMockFrameNodeObserver() = default;
+ LenientMockFrameNodeObserver(const LenientMockFrameNodeObserver&) = delete;
+ LenientMockFrameNodeObserver& operator=(const LenientMockFrameNodeObserver&) =
+ delete;
~LenientMockFrameNodeObserver() override = default;
MOCK_METHOD2(OnPriorityAndReasonChanged,
void(const FrameNode*, const PriorityAndReason&));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(LenientMockFrameNodeObserver);
};
using MockFrameNodeObserver =
diff --git a/chromium/components/performance_manager/features.cc b/chromium/components/performance_manager/features.cc
index 12d6f07902f..5508faa2f2b 100644
--- a/chromium/components/performance_manager/features.cc
+++ b/chromium/components/performance_manager/features.cc
@@ -9,6 +9,7 @@
#include "base/dcheck_is_on.h"
#include "base/metrics/field_trial_params.h"
+#include "build/build_config.h"
namespace performance_manager {
namespace features {
@@ -50,5 +51,38 @@ TabLoadingFrameNavigationThrottlesParams::GetParams() {
const base::Feature kRunOnMainThread{"RunOnMainThread",
base::FEATURE_DISABLED_BY_DEFAULT};
+#if !defined(OS_ANDROID)
+const base::Feature kUrgentDiscardingFromPerformanceManager {
+ "UrgentDiscardingFromPerformanceManager",
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_LINUX)
+ base::FEATURE_DISABLED_BY_DEFAULT
+#else
+ base::FEATURE_ENABLED_BY_DEFAULT
+#endif
+};
+
+UrgentDiscardingParams::UrgentDiscardingParams() = default;
+UrgentDiscardingParams::UrgentDiscardingParams(
+ const UrgentDiscardingParams& rhs) = default;
+UrgentDiscardingParams::~UrgentDiscardingParams() = default;
+
+constexpr base::FeatureParam<int> UrgentDiscardingParams::kDiscardStrategy;
+
+// static
+UrgentDiscardingParams UrgentDiscardingParams::GetParams() {
+ UrgentDiscardingParams params = {};
+ params.discard_strategy_ = static_cast<DiscardStrategy>(
+ UrgentDiscardingParams::kDiscardStrategy.Get());
+ return params;
+}
+
+const base::Feature kBackgroundTabLoadingFromPerformanceManager{
+ "BackgroundTabLoadingFromPerformanceManager",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kHighPMFDiscardPolicy{"HighPMFDiscardPolicy",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
+
} // namespace features
} // namespace performance_manager
diff --git a/chromium/components/performance_manager/freezing/freezing_unittest.cc b/chromium/components/performance_manager/freezing/freezing_unittest.cc
index 751efb52d7a..8fe25dc3756 100644
--- a/chromium/components/performance_manager/freezing/freezing_unittest.cc
+++ b/chromium/components/performance_manager/freezing/freezing_unittest.cc
@@ -4,7 +4,6 @@
#include "components/performance_manager/public/freezing/freezing.h"
-#include "base/optional.h"
#include "components/performance_manager/public/graph/page_node.h"
#include "components/performance_manager/public/performance_manager.h"
#include "components/performance_manager/test_support/performance_manager_test_harness.h"
@@ -12,6 +11,7 @@
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace performance_manager {
namespace freezing {
@@ -22,15 +22,15 @@ constexpr char kCanFreeze[] = "Can freeze";
constexpr char kCannotFreeze[] = "Cannot freeze";
// Get the aggregated freezing vote associated with |contents|.
-base::Optional<FreezingVote> GetFreezingVote(content::WebContents* contents) {
+absl::optional<FreezingVote> GetFreezingVote(content::WebContents* contents) {
base::RunLoop run_loop;
- base::Optional<FreezingVote> ret;
+ absl::optional<FreezingVote> ret;
auto quit_closure = run_loop.QuitClosure();
PerformanceManager::CallOnGraph(
FROM_HERE,
base::BindOnce(
[](base::WeakPtr<PageNode> page_node, base::OnceClosure quit_closure,
- base::Optional<FreezingVote>* expected_vote) {
+ absl::optional<FreezingVote>* expected_vote) {
EXPECT_TRUE(page_node);
auto vote = page_node->GetFreezingVote();
*expected_vote = vote;
@@ -106,7 +106,7 @@ TEST_F(FreezingTest, FreezingToken) {
FreezingVote(FreezingVoteValue::kCanFreeze, kCanFreeze));
}
// Once the freezing vote token is destroyed the vote should be invalidated.
- EXPECT_EQ(GetFreezingVote(web_contents()), base::nullopt);
+ EXPECT_EQ(GetFreezingVote(web_contents()), absl::nullopt);
EXPECT_EQ(0U, GetVoteCount(web_contents()));
EXPECT_EQ(0U, GetTotalVoteCount());
@@ -119,7 +119,7 @@ TEST_F(FreezingTest, FreezingToken) {
EXPECT_EQ(GetFreezingVote(web_contents()),
FreezingVote(FreezingVoteValue::kCannotFreeze, kCannotFreeze));
}
- EXPECT_EQ(GetFreezingVote(web_contents()), base::nullopt);
+ EXPECT_EQ(GetFreezingVote(web_contents()), absl::nullopt);
EXPECT_EQ(0U, GetTotalVoteCount());
// Emit multiple positive token for the same page.
@@ -151,7 +151,7 @@ TEST_F(FreezingTest, FreezingToken) {
token1.reset();
EXPECT_EQ(0U, GetVoteCount(web_contents()));
EXPECT_EQ(0U, GetTotalVoteCount());
- EXPECT_EQ(GetFreezingVote(web_contents()), base::nullopt);
+ EXPECT_EQ(GetFreezingVote(web_contents()), absl::nullopt);
}
}
@@ -176,8 +176,8 @@ TEST_F(FreezingTest, FreezingTokenMultiplePages) {
web_contents(), FreezingVoteValue::kCanFreeze, kCanFreeze);
EXPECT_EQ(GetFreezingVote(web_contents()),
FreezingVote(FreezingVoteValue::kCanFreeze, kCanFreeze));
- EXPECT_EQ(GetFreezingVote(contents2.get()), base::nullopt);
- EXPECT_EQ(GetFreezingVote(contents3.get()), base::nullopt);
+ EXPECT_EQ(GetFreezingVote(contents2.get()), absl::nullopt);
+ EXPECT_EQ(GetFreezingVote(contents3.get()), absl::nullopt);
EXPECT_EQ(1U, GetVoteCount(web_contents()));
EXPECT_EQ(0U, GetVoteCount(contents2.get()));
EXPECT_EQ(0U, GetVoteCount(contents3.get()));
@@ -187,8 +187,8 @@ TEST_F(FreezingTest, FreezingTokenMultiplePages) {
web_contents(), FreezingVoteValue::kCanFreeze, kCanFreeze);
EXPECT_EQ(GetFreezingVote(web_contents()),
FreezingVote(FreezingVoteValue::kCanFreeze, kCanFreeze));
- EXPECT_EQ(GetFreezingVote(contents2.get()), base::nullopt);
- EXPECT_EQ(GetFreezingVote(contents3.get()), base::nullopt);
+ EXPECT_EQ(GetFreezingVote(contents2.get()), absl::nullopt);
+ EXPECT_EQ(GetFreezingVote(contents3.get()), absl::nullopt);
EXPECT_EQ(2U, GetVoteCount(web_contents()));
EXPECT_EQ(0U, GetVoteCount(contents2.get()));
EXPECT_EQ(0U, GetVoteCount(contents3.get()));
@@ -200,7 +200,7 @@ TEST_F(FreezingTest, FreezingTokenMultiplePages) {
FreezingVote(FreezingVoteValue::kCanFreeze, kCanFreeze));
EXPECT_EQ(GetFreezingVote(contents2.get()),
FreezingVote(FreezingVoteValue::kCanFreeze, kCanFreeze));
- EXPECT_EQ(GetFreezingVote(contents3.get()), base::nullopt);
+ EXPECT_EQ(GetFreezingVote(contents3.get()), absl::nullopt);
EXPECT_EQ(2U, GetVoteCount(web_contents()));
EXPECT_EQ(1U, GetVoteCount(contents2.get()));
EXPECT_EQ(0U, GetVoteCount(contents3.get()));
@@ -232,7 +232,7 @@ TEST_F(FreezingTest, FreezingTokenMultiplePages) {
EXPECT_EQ(3U, GetTotalVoteCount());
contents1_token2.reset();
- EXPECT_EQ(GetFreezingVote(web_contents()), base::nullopt);
+ EXPECT_EQ(GetFreezingVote(web_contents()), absl::nullopt);
EXPECT_EQ(GetFreezingVote(contents2.get()),
FreezingVote(FreezingVoteValue::kCanFreeze, kCanFreeze));
EXPECT_EQ(GetFreezingVote(contents3.get()),
@@ -243,8 +243,8 @@ TEST_F(FreezingTest, FreezingTokenMultiplePages) {
EXPECT_EQ(2U, GetTotalVoteCount());
contents2_token.reset();
- EXPECT_EQ(GetFreezingVote(web_contents()), base::nullopt);
- EXPECT_EQ(GetFreezingVote(contents2.get()), base::nullopt);
+ EXPECT_EQ(GetFreezingVote(web_contents()), absl::nullopt);
+ EXPECT_EQ(GetFreezingVote(contents2.get()), absl::nullopt);
EXPECT_EQ(GetFreezingVote(contents3.get()),
FreezingVote(FreezingVoteValue::kCanFreeze, kCanFreeze));
EXPECT_EQ(0U, GetVoteCount(web_contents()));
@@ -253,9 +253,9 @@ TEST_F(FreezingTest, FreezingTokenMultiplePages) {
EXPECT_EQ(1U, GetTotalVoteCount());
contents3_token.reset();
- EXPECT_EQ(GetFreezingVote(web_contents()), base::nullopt);
- EXPECT_EQ(GetFreezingVote(contents2.get()), base::nullopt);
- EXPECT_EQ(GetFreezingVote(contents3.get()), base::nullopt);
+ EXPECT_EQ(GetFreezingVote(web_contents()), absl::nullopt);
+ EXPECT_EQ(GetFreezingVote(contents2.get()), absl::nullopt);
+ EXPECT_EQ(GetFreezingVote(contents3.get()), absl::nullopt);
EXPECT_EQ(0U, GetVoteCount(web_contents()));
EXPECT_EQ(0U, GetVoteCount(contents2.get()));
EXPECT_EQ(0U, GetVoteCount(contents3.get()));
diff --git a/chromium/components/performance_manager/freezing/freezing_vote_aggregator.cc b/chromium/components/performance_manager/freezing/freezing_vote_aggregator.cc
index c3f4fd163a9..c24a9aabfd6 100644
--- a/chromium/components/performance_manager/freezing/freezing_vote_aggregator.cc
+++ b/chromium/components/performance_manager/freezing/freezing_vote_aggregator.cc
@@ -41,7 +41,7 @@ void FreezingVoteAggregator::OnVoteSubmitted(FreezingVoterId voter_id,
// Remember the previous chosen vote before adding the new vote. There
// could be none if this is the first vote submitted for |page_node|.
- base::Optional<FreezingVoteValue> old_chosen_vote_value;
+ absl::optional<FreezingVoteValue> old_chosen_vote_value;
if (!vote_data.IsEmpty())
old_chosen_vote_value = vote_data.GetChosenVote().value();
diff --git a/chromium/components/performance_manager/graph/frame_node_impl.cc b/chromium/components/performance_manager/graph/frame_node_impl.cc
index 8ff28c4207d..f7043c542bd 100644
--- a/chromium/components/performance_manager/graph/frame_node_impl.cc
+++ b/chromium/components/performance_manager/graph/frame_node_impl.cc
@@ -54,6 +54,7 @@ FrameNodeImpl::~FrameNodeImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(child_worker_nodes_.empty());
DCHECK(opened_page_nodes_.empty());
+ DCHECK(embedded_page_nodes_.empty());
DCHECK(!execution_context_);
}
@@ -171,6 +172,12 @@ const base::flat_set<PageNodeImpl*>& FrameNodeImpl::opened_page_nodes() const {
return opened_page_nodes_;
}
+const base::flat_set<PageNodeImpl*>& FrameNodeImpl::embedded_page_nodes()
+ const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return embedded_page_nodes_;
+}
+
mojom::LifecycleState FrameNodeImpl::lifecycle_state() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return lifecycle_state_.value();
@@ -232,7 +239,7 @@ bool FrameNodeImpl::is_audible() const {
return is_audible_.value();
}
-const base::Optional<gfx::Rect>& FrameNodeImpl::viewport_intersection() const {
+const absl::optional<gfx::Rect>& FrameNodeImpl::viewport_intersection() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// The viewport intersection of the main frame is not tracked.
DCHECK(!IsMainFrame());
@@ -388,6 +395,28 @@ void FrameNodeImpl::RemoveOpenedPage(base::PassKey<PageNodeImpl>,
DCHECK_EQ(1u, removed);
}
+void FrameNodeImpl::AddEmbeddedPage(base::PassKey<PageNodeImpl>,
+ PageNodeImpl* page_node) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(page_node);
+ DCHECK_NE(page_node_, page_node);
+ DCHECK(graph()->NodeInGraph(page_node));
+ DCHECK_EQ(this, page_node->embedder_frame_node());
+ bool inserted = embedded_page_nodes_.insert(page_node).second;
+ DCHECK(inserted);
+}
+
+void FrameNodeImpl::RemoveEmbeddedPage(base::PassKey<PageNodeImpl>,
+ PageNodeImpl* page_node) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(page_node);
+ DCHECK_NE(page_node_, page_node);
+ DCHECK(graph()->NodeInGraph(page_node));
+ DCHECK_EQ(this, page_node->embedder_frame_node());
+ size_t removed = embedded_page_nodes_.erase(page_node);
+ DCHECK_EQ(1u, removed);
+}
+
const FrameNode* FrameNodeImpl::GetParentFrameNode() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return parent_frame_node();
@@ -457,6 +486,23 @@ const base::flat_set<const PageNode*> FrameNodeImpl::GetOpenedPageNodes()
return UpcastNodeSet<PageNode>(opened_page_nodes());
}
+bool FrameNodeImpl::VisitEmbeddedPageNodes(
+ const PageNodeVisitor& visitor) const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ for (auto* page_impl : embedded_page_nodes()) {
+ const PageNode* page = page_impl;
+ if (!visitor.Run(page))
+ return false;
+ }
+ return true;
+}
+
+const base::flat_set<const PageNode*> FrameNodeImpl::GetEmbeddedPageNodes()
+ const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return UpcastNodeSet<PageNode>(embedded_page_nodes());
+}
+
FrameNodeImpl::LifecycleState FrameNodeImpl::GetLifecycleState() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return lifecycle_state();
@@ -530,7 +576,7 @@ bool FrameNodeImpl::IsAudible() const {
return is_audible();
}
-const base::Optional<gfx::Rect>& FrameNodeImpl::GetViewportIntersection()
+const absl::optional<gfx::Rect>& FrameNodeImpl::GetViewportIntersection()
const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return viewport_intersection();
@@ -590,8 +636,7 @@ void FrameNodeImpl::OnBeforeLeavingGraph() {
DCHECK(child_frame_nodes_.empty());
- // Sever opener relationships.
- SeverOpenedPagesAndMaybeReparent();
+ SeverPageRelationshipsAndMaybeReparent();
// Leave the page.
DCHECK(graph()->NodeInGraph(page_node_));
@@ -617,32 +662,45 @@ void FrameNodeImpl::RemoveNodeAttachedData() {
execution_context_.reset();
}
-void FrameNodeImpl::SeverOpenedPagesAndMaybeReparent() {
+void FrameNodeImpl::SeverPageRelationshipsAndMaybeReparent() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Copy |opened_page_nodes_| as we'll be modifying it in this loop: when we
- // call PageNodeImpl::(Set|Clear)OpenerFrameNodeAndOpenedType() this will call
- // back into this frame node and call RemoveOpenedPage().
- base::flat_set<PageNodeImpl*> opened_nodes = opened_page_nodes_;
- for (auto* opened_node : opened_nodes) {
- auto opened_type = opened_node->opened_type();
+ // Be careful when iterating: when we call
+ // PageNodeImpl::(Set|Clear)(Opener|Embedder)FrameNode() this will call
+ // back into this frame node and call Remove(Opened|Embedded)Page(), which
+ // modifies |opened_page_nodes_| and |embedded_page_nodes_|.
+ //
+ // We also reparent related pages to this frame's parent to maintain the
+ // relationship between the distinct frame trees for bookkeeping. For the
+ // relationship to be finally severed one of the frame trees must completely
+ // disappear, or it must be explicitly severed (this can happen with
+ // portals).
+ while (!opened_page_nodes_.empty()) {
+ auto* opened_node = *opened_page_nodes_.begin();
+ if (parent_frame_node_) {
+ opened_node->SetOpenerFrameNode(parent_frame_node_);
+ } else {
+ opened_node->ClearOpenerFrameNode();
+ }
+ DCHECK(!base::Contains(opened_page_nodes_, opened_node));
+ }
- // Reparent opened pages to this frame's parent to maintain the relationship
- // between the frame trees for bookkeeping. For the relationship to be
- // finally severed one of the frame trees must completely disappear, or it
- // must be explicitly severed (this can happen with portals).
+ while (!embedded_page_nodes_.empty()) {
+ auto* embedded_node = *embedded_page_nodes_.begin();
+ auto embedding_type = embedded_node->embedding_type();
if (parent_frame_node_) {
- opened_node->SetOpenerFrameNodeAndOpenedType(parent_frame_node_,
- opened_type);
+ embedded_node->SetEmbedderFrameNodeAndEmbeddingType(parent_frame_node_,
+ embedding_type);
} else {
- // There's no new parent, so simply clear the opener.
- opened_node->ClearOpenerFrameNodeAndOpenedType();
+ embedded_node->ClearEmbedderFrameNodeAndEmbeddingType();
}
+ DCHECK(!base::Contains(embedded_page_nodes_, embedded_node));
}
- // Expect each page node to have called RemoveOpenedPage(), and for this to
+ // Expect each page node to have called RemoveEmbeddedPage(), and for this to
// now be empty.
DCHECK(opened_page_nodes_.empty());
+ DCHECK(embedded_page_nodes_.empty());
}
FrameNodeImpl* FrameNodeImpl::GetFrameTreeRoot() const {
diff --git a/chromium/components/performance_manager/graph/frame_node_impl.h b/chromium/components/performance_manager/graph/frame_node_impl.h
index 717fcae7a4e..3404cd27fe3 100644
--- a/chromium/components/performance_manager/graph/frame_node_impl.h
+++ b/chromium/components/performance_manager/graph/frame_node_impl.h
@@ -109,6 +109,7 @@ class FrameNodeImpl
// Getters for non-const properties. These are not thread safe.
const base::flat_set<FrameNodeImpl*>& child_frame_nodes() const;
const base::flat_set<PageNodeImpl*>& opened_page_nodes() const;
+ const base::flat_set<PageNodeImpl*>& embedded_page_nodes() const;
LifecycleState lifecycle_state() const;
bool has_nonempty_beforeunload() const;
const GURL& url() const;
@@ -121,7 +122,7 @@ class FrameNodeImpl
const PriorityAndReason& priority_and_reason() const;
bool had_form_interaction() const;
bool is_audible() const;
- const base::Optional<gfx::Rect>& viewport_intersection() const;
+ const absl::optional<gfx::Rect>& viewport_intersection() const;
Visibility visibility() const;
// Setters are not thread safe.
@@ -145,18 +146,25 @@ class FrameNodeImpl
base::WeakPtr<FrameNodeImpl> GetWeakPtrOnUIThread();
base::WeakPtr<FrameNodeImpl> GetWeakPtr();
- void SeverOpenedPagesAndMaybeReparentForTesting() {
- SeverOpenedPagesAndMaybeReparent();
+ void SeverPageRelationshipsAndMaybeReparentForTesting() {
+ SeverPageRelationshipsAndMaybeReparent();
}
// Implementation details below this point.
// Invoked by opened pages when this frame is set/cleared as their opener.
- // See PageNodeImpl::(Set|Clear)OpenerFrameNodeAndOpenedType.
+ // See PageNodeImpl::(Set|Clear)OpenerFrameNode.
void AddOpenedPage(base::PassKey<PageNodeImpl> key, PageNodeImpl* page_node);
void RemoveOpenedPage(base::PassKey<PageNodeImpl> key,
PageNodeImpl* page_node);
+ // Invoked by embedded pages when this frame is set/cleared as their embedder.
+ // See PageNodeImpl::(Set|Clear)EmbedderFrameNodeAndEmbeddingType.
+ void AddEmbeddedPage(base::PassKey<PageNodeImpl> key,
+ PageNodeImpl* page_node);
+ void RemoveEmbeddedPage(base::PassKey<PageNodeImpl> key,
+ PageNodeImpl* page_node);
+
// Used by the ExecutionContextRegistry mechanism.
std::unique_ptr<NodeAttachedData>* GetExecutionContextStorage(
base::PassKey<execution_context::ExecutionContextAccess> key) {
@@ -181,6 +189,8 @@ class FrameNodeImpl
const base::flat_set<const FrameNode*> GetChildFrameNodes() const override;
bool VisitOpenedPageNodes(const PageNodeVisitor& visitor) const override;
const base::flat_set<const PageNode*> GetOpenedPageNodes() const override;
+ bool VisitEmbeddedPageNodes(const PageNodeVisitor& visitor) const override;
+ const base::flat_set<const PageNode*> GetEmbeddedPageNodes() const override;
LifecycleState GetLifecycleState() const override;
bool HasNonemptyBeforeUnload() const override;
const GURL& GetURL() const override;
@@ -195,7 +205,7 @@ class FrameNodeImpl
const PriorityAndReason& GetPriorityAndReason() const override;
bool HadFormInteraction() const override;
bool IsAudible() const override;
- const base::Optional<gfx::Rect>& GetViewportIntersection() const override;
+ const absl::optional<gfx::Rect>& GetViewportIntersection() const override;
Visibility GetVisibility() const override;
// Properties associated with a Document, which are reset when a
@@ -236,11 +246,11 @@ class FrameNodeImpl
void OnBeforeLeavingGraph() override;
void RemoveNodeAttachedData() override;
- // Helper function to sever all opened page relationships. This is called
- // before destroying the frame node in "OnBeforeLeavingGraph". Note that this
- // will reparent opened pages to this frame's parent so that tracking is
- // maintained.
- void SeverOpenedPagesAndMaybeReparent();
+ // Helper function to sever all opened/embedded page relationships. This is
+ // called before destroying the frame node in "OnBeforeLeavingGraph". Note
+ // that this will reparent embedded pages to this frame's parent so that
+ // tracking is maintained.
+ void SeverPageRelationshipsAndMaybeReparent();
// This is not quite the same as GetMainFrame, because there can be multiple
// main frames while the main frame is navigating. This explicitly walks up
@@ -289,6 +299,9 @@ class FrameNodeImpl
// The set of pages that have been opened by this frame.
base::flat_set<PageNodeImpl*> opened_page_nodes_;
+ // The set of pages that have been embedded by this frame.
+ base::flat_set<PageNodeImpl*> embedded_page_nodes_;
+
// Does *not* change when a navigation is committed.
ObservedProperty::NotifiesOnlyOnChanges<
LifecycleState,
@@ -347,7 +360,7 @@ class FrameNodeImpl
// so there is no point in tracking it. To avoid programming mistakes, it is
// forbidden to query this property for the main frame.
ObservedProperty::NotifiesOnlyOnChanges<
- base::Optional<gfx::Rect>,
+ absl::optional<gfx::Rect>,
&FrameNodeObserver::OnViewportIntersectionChanged>
viewport_intersection_;
diff --git a/chromium/components/performance_manager/graph/frame_node_impl_describer.cc b/chromium/components/performance_manager/graph/frame_node_impl_describer.cc
index 69e247c2bde..161aaea181c 100644
--- a/chromium/components/performance_manager/graph/frame_node_impl_describer.cc
+++ b/chromium/components/performance_manager/graph/frame_node_impl_describer.cc
@@ -20,7 +20,7 @@ namespace {
const char kDescriberName[] = "FrameNodeImpl";
std::string ViewportIntersectionToString(
- const base::Optional<gfx::Rect>& viewport_intersection) {
+ const absl::optional<gfx::Rect>& viewport_intersection) {
if (!viewport_intersection.has_value())
return "Nullopt";
diff --git a/chromium/components/performance_manager/graph/frame_node_impl_unittest.cc b/chromium/components/performance_manager/graph/frame_node_impl_unittest.cc
index 04534501944..0aad9309632 100644
--- a/chromium/components/performance_manager/graph/frame_node_impl_unittest.cc
+++ b/chromium/components/performance_manager/graph/frame_node_impl_unittest.cc
@@ -571,18 +571,20 @@ class LenientMockPageObserver : public PageNode::ObserverDefaultImpl {
MOCK_METHOD1(OnBeforePageNodeRemoved, void(const PageNode* page_node));
- // Note that opener functionality is actually tested in the
+ // Note that embedder functionality is actually tested in the
// performance_manager_browsertest.
- MOCK_METHOD3(OnOpenerFrameNodeChanged,
- void(const PageNode*, const FrameNode*, OpenedType));
+ MOCK_METHOD2(OnOpenerFrameNodeChanged,
+ void(const PageNode*, const FrameNode*));
+ MOCK_METHOD3(OnEmbedderFrameNodeChanged,
+ void(const PageNode*, const FrameNode*, EmbeddingType));
};
using MockPageObserver = ::testing::StrictMock<LenientMockPageObserver>;
} // namespace
-TEST_F(FrameNodeImplTest, OpenerRelationships) {
- using OpenedType = PageNode::OpenedType;
+TEST_F(FrameNodeImplTest, PageRelationships) {
+ using EmbeddingType = PageNode::EmbeddingType;
auto process = CreateNode<ProcessNodeImpl>();
auto pageA = CreateNode<PageNodeImpl>();
@@ -601,72 +603,83 @@ TEST_F(FrameNodeImplTest, OpenerRelationships) {
MockPageObserver obs;
graph()->AddPageNodeObserver(&obs);
- // You can always call the pre-delete opener clearing helper, even if you
+ // You can always call the pre-delete embedder clearing helper, even if you
// have no such relationships.
- frameB1->SeverOpenedPagesAndMaybeReparentForTesting();
-
- // You can't clear an opener if you don't already have one.
- EXPECT_DCHECK_DEATH(pageB->ClearOpenerFrameNodeAndOpenedType());
-
- // You can't be an opener for your own frame tree.
- EXPECT_DCHECK_DEATH(pageA->SetOpenerFrameNodeAndOpenedType(
- frameA1.get(), OpenedType::kPopup));
-
- // You can't set a null opener or an invalid opened type.
- EXPECT_DCHECK_DEATH(
- pageB->SetOpenerFrameNodeAndOpenedType(nullptr, OpenedType::kInvalid));
- EXPECT_DCHECK_DEATH(pageB->SetOpenerFrameNodeAndOpenedType(
- frameA1.get(), OpenedType::kInvalid));
-
- EXPECT_EQ(nullptr, pageB->opener_frame_node());
- EXPECT_EQ(nullptr, ppageB->GetOpenerFrameNode());
- EXPECT_EQ(OpenedType::kInvalid, pageB->opened_type());
- EXPECT_EQ(OpenedType::kInvalid, ppageB->GetOpenedType());
- EXPECT_TRUE(frameA1->opened_page_nodes().empty());
- EXPECT_TRUE(pframeA1->GetOpenedPageNodes().empty());
-
- // Set an opener relationship.
- EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), nullptr,
- OpenedType::kInvalid));
- pageB->SetOpenerFrameNodeAndOpenedType(frameA1.get(), OpenedType::kGuestView);
- EXPECT_EQ(frameA1.get(), pageB->opener_frame_node());
- EXPECT_EQ(frameA1.get(), ppageB->GetOpenerFrameNode());
- EXPECT_EQ(OpenedType::kGuestView, pageB->opened_type());
- EXPECT_EQ(OpenedType::kGuestView, ppageB->GetOpenedType());
- EXPECT_EQ(1u, frameA1->opened_page_nodes().size());
- EXPECT_EQ(1u, pframeA1->GetOpenedPageNodes().size());
- EXPECT_EQ(1u, frameA1->opened_page_nodes().count(pageB.get()));
- EXPECT_EQ(1u, pframeA1->GetOpenedPageNodes().count(pageB.get()));
+ frameB1->SeverPageRelationshipsAndMaybeReparentForTesting();
+
+ // You can't clear an embedder if you don't already have one.
+ EXPECT_DCHECK_DEATH(pageB->ClearEmbedderFrameNodeAndEmbeddingType());
+
+ // You can't be an embedder for your own frame tree.
+ EXPECT_DCHECK_DEATH(pageA->SetEmbedderFrameNodeAndEmbeddingType(
+ frameA1.get(), EmbeddingType::kPortal));
+
+ // You can't set a null embedder or an invalid embedded type.
+ EXPECT_DCHECK_DEATH(pageB->SetEmbedderFrameNodeAndEmbeddingType(
+ nullptr, EmbeddingType::kInvalid));
+ EXPECT_DCHECK_DEATH(pageB->SetEmbedderFrameNodeAndEmbeddingType(
+ frameA1.get(), EmbeddingType::kInvalid));
+
+ EXPECT_EQ(nullptr, pageB->embedder_frame_node());
+ EXPECT_EQ(nullptr, ppageB->GetEmbedderFrameNode());
+ EXPECT_EQ(EmbeddingType::kInvalid, pageB->embedding_type());
+ EXPECT_EQ(EmbeddingType::kInvalid, ppageB->GetEmbeddingType());
+ EXPECT_TRUE(frameA1->embedded_page_nodes().empty());
+ EXPECT_TRUE(pframeA1->GetEmbeddedPageNodes().empty());
+
+ // Set an embedder relationship.
+ EXPECT_CALL(obs, OnEmbedderFrameNodeChanged(pageB.get(), nullptr,
+ EmbeddingType::kInvalid));
+ pageB->SetEmbedderFrameNodeAndEmbeddingType(frameA1.get(),
+ EmbeddingType::kGuestView);
+ EXPECT_EQ(frameA1.get(), pageB->embedder_frame_node());
+ EXPECT_EQ(frameA1.get(), ppageB->GetEmbedderFrameNode());
+ EXPECT_EQ(EmbeddingType::kGuestView, pageB->embedding_type());
+ EXPECT_EQ(EmbeddingType::kGuestView, ppageB->GetEmbeddingType());
+ EXPECT_EQ(1u, frameA1->embedded_page_nodes().size());
+ EXPECT_EQ(1u, pframeA1->GetEmbeddedPageNodes().size());
+ EXPECT_EQ(1u, frameA1->embedded_page_nodes().count(pageB.get()));
+ EXPECT_EQ(1u, pframeA1->GetEmbeddedPageNodes().count(pageB.get()));
testing::Mock::VerifyAndClear(&obs);
- // Set another opener relationship.
- EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageC.get(), nullptr,
- OpenedType::kInvalid));
- pageC->SetOpenerFrameNodeAndOpenedType(frameA1.get(), OpenedType::kPopup);
+ // Set an opener relationship.
+ EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageC.get(), nullptr));
+ pageC->SetOpenerFrameNode(frameA1.get());
EXPECT_EQ(frameA1.get(), pageC->opener_frame_node());
- EXPECT_EQ(OpenedType::kPopup, pageC->opened_type());
- EXPECT_EQ(2u, frameA1->opened_page_nodes().size());
- EXPECT_EQ(1u, frameA1->opened_page_nodes().count(pageB.get()));
+ EXPECT_EQ(1u, frameA1->embedded_page_nodes().size());
+ EXPECT_EQ(1u, frameA1->opened_page_nodes().size());
+ EXPECT_EQ(1u, frameA1->embedded_page_nodes().count(pageB.get()));
testing::Mock::VerifyAndClear(&obs);
- // Do a traversal.
+ // Do an embedded page traversal.
std::set<const PageNode*> visited;
EXPECT_TRUE(
ToPublic(frameA1.get())
+ ->VisitEmbeddedPageNodes(base::BindRepeating(
+ [](std::set<const PageNode*>* visited, const PageNode* page) {
+ EXPECT_TRUE(visited->insert(page).second);
+ return true;
+ },
+ base::Unretained(&visited))));
+ EXPECT_THAT(visited, testing::UnorderedElementsAre(ToPublic(pageB.get())));
+
+ // Do an opened page traversal.
+ visited.clear();
+ EXPECT_TRUE(
+ ToPublic(frameA1.get())
->VisitOpenedPageNodes(base::BindRepeating(
[](std::set<const PageNode*>* visited, const PageNode* page) {
EXPECT_TRUE(visited->insert(page).second);
return true;
},
base::Unretained(&visited))));
- EXPECT_THAT(visited, testing::UnorderedElementsAre(ToPublic(pageB.get()),
- ToPublic(pageC.get())));
+ EXPECT_THAT(visited, testing::UnorderedElementsAre(ToPublic(pageC.get())));
// Do an aborted visit.
visited.clear();
EXPECT_FALSE(
ToPublic(frameA1.get())
- ->VisitOpenedPageNodes(base::BindRepeating(
+ ->VisitEmbeddedPageNodes(base::BindRepeating(
[](std::set<const PageNode*>* visited, const PageNode* page) {
EXPECT_TRUE(visited->insert(page).second);
return false;
@@ -674,44 +687,40 @@ TEST_F(FrameNodeImplTest, OpenerRelationships) {
base::Unretained(&visited))));
EXPECT_EQ(1u, visited.size());
- // Manually clear the first relationship (initiated from the page).
- EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), frameA1.get(),
- OpenedType::kGuestView));
- pageB->ClearOpenerFrameNodeAndOpenedType();
- EXPECT_EQ(nullptr, pageB->opener_frame_node());
- EXPECT_EQ(OpenedType::kInvalid, pageB->opened_type());
+ // Manually clear the embedder relationship (initiated from the page).
+ EXPECT_CALL(obs, OnEmbedderFrameNodeChanged(pageB.get(), frameA1.get(),
+ EmbeddingType::kGuestView));
+ pageB->ClearEmbedderFrameNodeAndEmbeddingType();
+ EXPECT_EQ(nullptr, pageB->embedder_frame_node());
+ EXPECT_EQ(EmbeddingType::kInvalid, pageB->embedding_type());
EXPECT_EQ(frameA1.get(), pageC->opener_frame_node());
- EXPECT_EQ(OpenedType::kPopup, pageC->opened_type());
- EXPECT_EQ(1u, frameA1->opened_page_nodes().size());
- EXPECT_EQ(0u, frameA1->opened_page_nodes().count(pageB.get()));
+ EXPECT_TRUE(frameA1->embedded_page_nodes().empty());
testing::Mock::VerifyAndClear(&obs);
- // Clear the second relationship (initiated from the frame).
- EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageC.get(), frameA1.get(),
- OpenedType::kPopup));
- frameA1->SeverOpenedPagesAndMaybeReparentForTesting();
- EXPECT_EQ(nullptr, pageC->opener_frame_node());
- EXPECT_EQ(OpenedType::kInvalid, pageC->opened_type());
+ // Clear the opener relationship.
+ EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageC.get(), frameA1.get()));
+ frameA1->SeverPageRelationshipsAndMaybeReparentForTesting();
+ EXPECT_EQ(nullptr, pageC->embedder_frame_node());
+ EXPECT_EQ(EmbeddingType::kInvalid, pageC->embedding_type());
EXPECT_TRUE(frameA1->opened_page_nodes().empty());
+ EXPECT_TRUE(frameA1->embedded_page_nodes().empty());
testing::Mock::VerifyAndClear(&obs);
- // Set a popup opener relationship on node A2.
- EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), nullptr,
- OpenedType::kInvalid));
- pageB->SetOpenerFrameNodeAndOpenedType(frameA2.get(), OpenedType::kPopup);
+ // Set a popup relationship on node A2.
+ EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), nullptr));
+ pageB->SetOpenerFrameNode(frameA2.get());
EXPECT_EQ(frameA2.get(), pageB->opener_frame_node());
- EXPECT_EQ(OpenedType::kPopup, pageB->opened_type());
EXPECT_TRUE(frameA1->opened_page_nodes().empty());
+ EXPECT_TRUE(frameA1->embedded_page_nodes().empty());
EXPECT_EQ(1u, frameA2->opened_page_nodes().size());
+ EXPECT_TRUE(frameA2->embedded_page_nodes().empty());
EXPECT_EQ(1u, frameA2->opened_page_nodes().count(pageB.get()));
testing::Mock::VerifyAndClear(&obs);
// Clear it with the helper, and expect it to be reparented to node A1.
- EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), frameA2.get(),
- OpenedType::kPopup));
- frameA2->SeverOpenedPagesAndMaybeReparentForTesting();
+ EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), frameA2.get()));
+ frameA2->SeverPageRelationshipsAndMaybeReparentForTesting();
EXPECT_EQ(frameA1.get(), pageB->opener_frame_node());
- EXPECT_EQ(OpenedType::kPopup, pageB->opened_type());
EXPECT_EQ(1u, frameA1->opened_page_nodes().size());
EXPECT_EQ(1u, frameA1->opened_page_nodes().count(pageB.get()));
EXPECT_TRUE(frameA2->opened_page_nodes().empty());
@@ -719,22 +728,18 @@ TEST_F(FrameNodeImplTest, OpenerRelationships) {
// Clear it again with the helper. This time reparenting can't happen, as it
// was already parented to the root.
- EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), frameA1.get(),
- OpenedType::kPopup));
- frameA1->SeverOpenedPagesAndMaybeReparentForTesting();
+ EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), frameA1.get()));
+ frameA1->SeverPageRelationshipsAndMaybeReparentForTesting();
EXPECT_EQ(nullptr, pageB->opener_frame_node());
- EXPECT_EQ(OpenedType::kInvalid, pageB->opened_type());
EXPECT_TRUE(frameA1->opened_page_nodes().empty());
EXPECT_TRUE(frameA2->opened_page_nodes().empty());
testing::Mock::VerifyAndClear(&obs);
- // verify that the opener relationship is torn down before any node removal
+ // verify that the embedder relationship is torn down before any node removal
// notification arrives.
- EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), nullptr,
- OpenedType::kInvalid));
- pageB->SetOpenerFrameNodeAndOpenedType(frameA2.get(), OpenedType::kPopup);
+ EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), nullptr));
+ pageB->SetOpenerFrameNode(frameA2.get());
EXPECT_EQ(frameA2.get(), pageB->opener_frame_node());
- EXPECT_EQ(OpenedType::kPopup, pageB->opened_type());
EXPECT_TRUE(frameA1->opened_page_nodes().empty());
EXPECT_EQ(1u, frameA2->opened_page_nodes().size());
EXPECT_EQ(1u, frameA2->opened_page_nodes().count(pageB.get()));
@@ -744,8 +749,7 @@ TEST_F(FrameNodeImplTest, OpenerRelationships) {
::testing::InSequence seq;
// These must occur in sequence.
- EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), frameA2.get(),
- OpenedType::kPopup));
+ EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), frameA2.get()));
EXPECT_CALL(obs, OnBeforePageNodeRemoved(pageB.get()));
}
frameB1.reset();
diff --git a/chromium/components/performance_manager/graph/graph_impl.cc b/chromium/components/performance_manager/graph/graph_impl.cc
index ca99daf5a0d..f9fed62886a 100644
--- a/chromium/components/performance_manager/graph/graph_impl.cc
+++ b/chromium/components/performance_manager/graph/graph_impl.cc
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/notreached.h"
#include "base/stl_util.h"
+#include "base/strings/string_piece.h"
#include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/graph/node_base.h"
#include "components/performance_manager/graph/page_node_impl.h"
@@ -117,7 +118,7 @@ void NodeDataDescriberRegistryImpl::RegisterDescriber(
}
#endif
bool inserted =
- describers_.insert(std::make_pair(describer, name.as_string())).second;
+ describers_.insert(std::make_pair(describer, std::string(name))).second;
DCHECK(inserted);
}
diff --git a/chromium/components/performance_manager/graph/graph_impl.h b/chromium/components/performance_manager/graph/graph_impl.h
index ea7be7e2a91..d9869b59436 100644
--- a/chromium/components/performance_manager/graph/graph_impl.h
+++ b/chromium/components/performance_manager/graph/graph_impl.h
@@ -9,7 +9,6 @@
#include <map>
#include <memory>
-#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
diff --git a/chromium/components/performance_manager/graph/graph_impl_operations.h b/chromium/components/performance_manager/graph/graph_impl_operations.h
index c7807f7b4df..813ea932361 100644
--- a/chromium/components/performance_manager/graph/graph_impl_operations.h
+++ b/chromium/components/performance_manager/graph/graph_impl_operations.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_PERFORMANCE_MANAGER_GRAPH_GRAPH_IMPL_OPERATIONS_H_
#define COMPONENTS_PERFORMANCE_MANAGER_GRAPH_GRAPH_IMPL_OPERATIONS_H_
-#include "base/callback_forward.h"
#include "base/containers/flat_set.h"
#include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/graph/page_node_impl.h"
diff --git a/chromium/components/performance_manager/graph/graph_impl_unittest.cc b/chromium/components/performance_manager/graph/graph_impl_unittest.cc
index 05d5de1f915..4493444a541 100644
--- a/chromium/components/performance_manager/graph/graph_impl_unittest.cc
+++ b/chromium/components/performance_manager/graph/graph_impl_unittest.cc
@@ -322,7 +322,7 @@ TEST_F(GraphImplTest, NodeDataDescribers) {
EXPECT_EQ(0u, descr.DictSize());
}
-TEST_F(GraphImplTest, OpenersClearedOnTeardown) {
+TEST_F(GraphImplTest, OpenersAndEmbeddersClearedOnTeardown) {
auto process = CreateNode<ProcessNodeImpl>();
auto pageA = CreateNode<PageNodeImpl>();
auto frameA1 = CreateFrameNodeAutoId(process.get(), pageA.get());
@@ -333,13 +333,12 @@ TEST_F(GraphImplTest, OpenersClearedOnTeardown) {
auto pageC = CreateNode<PageNodeImpl>();
auto frameC1 = CreateFrameNodeAutoId(process.get(), pageC.get());
- // Set up some opener relationships. These should be gracefully torn down as
+ // Set up some embedder relationships. These should be gracefully torn down as
// the graph cleans up nodes, otherwise the frame and page node destructors
// will explode.
- pageB->SetOpenerFrameNodeAndOpenedType(frameA1.get(),
- PageNode::OpenedType::kGuestView);
- pageC->SetOpenerFrameNodeAndOpenedType(frameA2.get(),
- PageNode::OpenedType::kPopup);
+ pageB->SetEmbedderFrameNodeAndEmbeddingType(
+ frameA1.get(), PageNode::EmbeddingType::kGuestView);
+ pageC->SetOpenerFrameNode(frameA2.get());
}
} // namespace performance_manager
diff --git a/chromium/components/performance_manager/graph/node_attached_data.h b/chromium/components/performance_manager/graph/node_attached_data.h
index aa8e803b3c4..9a7f1fa3619 100644
--- a/chromium/components/performance_manager/graph/node_attached_data.h
+++ b/chromium/components/performance_manager/graph/node_attached_data.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_PERFORMANCE_MANAGER_GRAPH_NODE_ATTACHED_DATA_H_
#define COMPONENTS_PERFORMANCE_MANAGER_GRAPH_NODE_ATTACHED_DATA_H_
-#include <memory>
-
#include "base/check_op.h"
#include "base/macros.h"
#include "components/performance_manager/graph/node_base.h"
diff --git a/chromium/components/performance_manager/graph/page_node.cc b/chromium/components/performance_manager/graph/page_node.cc
index 1ae4e7fc924..76a97e82e8f 100644
--- a/chromium/components/performance_manager/graph/page_node.cc
+++ b/chromium/components/performance_manager/graph/page_node.cc
@@ -9,15 +9,13 @@
namespace performance_manager {
// static
-const char* PageNode::ToString(PageNode::OpenedType opened_type) {
- switch (opened_type) {
- case PageNode::OpenedType::kInvalid:
+const char* PageNode::ToString(PageNode::EmbeddingType embedding_type) {
+ switch (embedding_type) {
+ case PageNode::EmbeddingType::kInvalid:
return "kInvalid";
- case PageNode::OpenedType::kPopup:
- return "kPopup";
- case PageNode::OpenedType::kGuestView:
+ case PageNode::EmbeddingType::kGuestView:
return "kGuestView";
- case PageNode::OpenedType::kPortal:
+ case PageNode::EmbeddingType::kPortal:
return "kPortal";
}
NOTREACHED();
@@ -51,8 +49,8 @@ PageNode::ObserverDefaultImpl::~ObserverDefaultImpl() = default;
std::ostream& operator<<(
std::ostream& os,
- performance_manager::PageNode::OpenedType opened_type) {
- os << performance_manager::PageNode::ToString(opened_type);
+ performance_manager::PageNode::EmbeddingType embedding_type) {
+ os << performance_manager::PageNode::ToString(embedding_type);
return os;
}
diff --git a/chromium/components/performance_manager/graph/page_node_impl.cc b/chromium/components/performance_manager/graph/page_node_impl.cc
index 66cb6d80b6c..5c279f27134 100644
--- a/chromium/components/performance_manager/graph/page_node_impl.cc
+++ b/chromium/components/performance_manager/graph/page_node_impl.cc
@@ -37,7 +37,8 @@ PageNodeImpl::PageNodeImpl(const WebContentsProxy& contents_proxy,
PageNodeImpl::~PageNodeImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(nullptr, opener_frame_node_);
- DCHECK_EQ(OpenedType::kInvalid, opened_type_);
+ DCHECK_EQ(nullptr, embedder_frame_node_);
+ DCHECK_EQ(EmbeddingType::kInvalid, embedding_type_);
DCHECK(!page_load_tracker_data_);
DCHECK(!site_data_);
DCHECK(!frozen_frame_data_);
@@ -166,14 +167,19 @@ FrameNodeImpl* PageNodeImpl::GetMainFrameNodeImpl() const {
FrameNodeImpl* PageNodeImpl::opener_frame_node() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(opener_frame_node_ || opened_type_ == OpenedType::kInvalid);
return opener_frame_node_;
}
-PageNodeImpl::OpenedType PageNodeImpl::opened_type() const {
+FrameNodeImpl* PageNodeImpl::embedder_frame_node() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(opener_frame_node_ || opened_type_ == OpenedType::kInvalid);
- return opened_type_;
+ DCHECK(embedder_frame_node_ || embedding_type_ == EmbeddingType::kInvalid);
+ return embedder_frame_node_;
+}
+
+PageNodeImpl::EmbeddingType PageNodeImpl::embedding_type() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(embedder_frame_node_ || embedding_type_ == EmbeddingType::kInvalid);
+ return embedding_type_;
}
bool PageNodeImpl::is_visible() const {
@@ -251,47 +257,79 @@ bool PageNodeImpl::had_form_interaction() const {
return had_form_interaction_.value();
}
-const base::Optional<freezing::FreezingVote>& PageNodeImpl::freezing_vote()
+const absl::optional<freezing::FreezingVote>& PageNodeImpl::freezing_vote()
const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return freezing_vote_.value();
}
-void PageNodeImpl::SetOpenerFrameNodeAndOpenedType(FrameNodeImpl* opener,
- OpenedType opened_type) {
+void PageNodeImpl::SetOpenerFrameNode(FrameNodeImpl* opener) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(opener);
DCHECK(graph()->NodeInGraph(opener));
DCHECK_NE(this, opener->page_node());
- DCHECK_NE(OpenedType::kInvalid, opened_type);
auto* previous_opener = opener_frame_node_;
- auto previous_type = opened_type_;
-
if (previous_opener)
previous_opener->RemoveOpenedPage(PassKey(), this);
opener_frame_node_ = opener;
- opened_type_ = opened_type;
opener->AddOpenedPage(PassKey(), this);
for (auto* observer : GetObservers())
- observer->OnOpenerFrameNodeChanged(this, previous_opener, previous_type);
+ observer->OnOpenerFrameNodeChanged(this, previous_opener);
}
-void PageNodeImpl::ClearOpenerFrameNodeAndOpenedType() {
+void PageNodeImpl::ClearOpenerFrameNode() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_NE(nullptr, opener_frame_node_);
- DCHECK_NE(OpenedType::kInvalid, opened_type_);
auto* previous_opener = opener_frame_node_;
- auto previous_type = opened_type_;
opener_frame_node_->RemoveOpenedPage(PassKey(), this);
opener_frame_node_ = nullptr;
- opened_type_ = OpenedType::kInvalid;
for (auto* observer : GetObservers())
- observer->OnOpenerFrameNodeChanged(this, previous_opener, previous_type);
+ observer->OnOpenerFrameNodeChanged(this, previous_opener);
+}
+
+void PageNodeImpl::SetEmbedderFrameNodeAndEmbeddingType(
+ FrameNodeImpl* embedder,
+ EmbeddingType embedding_type) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(embedder);
+ DCHECK(graph()->NodeInGraph(embedder));
+ DCHECK_NE(this, embedder->page_node());
+ DCHECK_NE(EmbeddingType::kInvalid, embedding_type);
+
+ auto* previous_embedder = embedder_frame_node_;
+ auto previous_type = embedding_type_;
+
+ if (previous_embedder)
+ previous_embedder->RemoveEmbeddedPage(PassKey(), this);
+ embedder_frame_node_ = embedder;
+ embedding_type_ = embedding_type;
+ embedder->AddEmbeddedPage(PassKey(), this);
+
+ for (auto* observer : GetObservers())
+ observer->OnEmbedderFrameNodeChanged(this, previous_embedder,
+ previous_type);
+}
+
+void PageNodeImpl::ClearEmbedderFrameNodeAndEmbeddingType() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_NE(nullptr, embedder_frame_node_);
+ DCHECK_NE(EmbeddingType::kInvalid, embedding_type_);
+
+ auto* previous_embedder = embedder_frame_node_;
+ auto previous_type = embedding_type_;
+
+ embedder_frame_node_->RemoveEmbeddedPage(PassKey(), this);
+ embedder_frame_node_ = nullptr;
+ embedding_type_ = EmbeddingType::kInvalid;
+
+ for (auto* observer : GetObservers())
+ observer->OnEmbedderFrameNodeChanged(this, previous_embedder,
+ previous_type);
}
void PageNodeImpl::set_usage_estimate_time(
@@ -313,7 +351,7 @@ void PageNodeImpl::set_has_nonempty_beforeunload(
}
void PageNodeImpl::set_freezing_vote(
- base::Optional<freezing::FreezingVote> freezing_vote) {
+ absl::optional<freezing::FreezingVote> freezing_vote) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
freezing_vote_.SetAndMaybeNotify(this, freezing_vote);
}
@@ -333,7 +371,11 @@ void PageNodeImpl::OnBeforeLeavingGraph() {
// Sever opener relationships.
if (opener_frame_node_)
- ClearOpenerFrameNodeAndOpenedType();
+ ClearOpenerFrameNode();
+
+ // Sever embedder relationships.
+ if (embedder_frame_node_)
+ ClearEmbedderFrameNodeAndEmbeddingType();
DCHECK_EQ(0u, frame_node_count_);
}
@@ -356,9 +398,14 @@ const FrameNode* PageNodeImpl::GetOpenerFrameNode() const {
return opener_frame_node();
}
-PageNodeImpl::OpenedType PageNodeImpl::GetOpenedType() const {
+const FrameNode* PageNodeImpl::GetEmbedderFrameNode() const {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return embedder_frame_node();
+}
+
+PageNodeImpl::EmbeddingType PageNodeImpl::GetEmbeddingType() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return opened_type();
+ return embedding_type();
}
bool PageNodeImpl::IsVisible() const {
@@ -451,7 +498,7 @@ const WebContentsProxy& PageNodeImpl::GetContentsProxy() const {
return contents_proxy();
}
-const base::Optional<freezing::FreezingVote>& PageNodeImpl::GetFreezingVote()
+const absl::optional<freezing::FreezingVote>& PageNodeImpl::GetFreezingVote()
const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return freezing_vote();
diff --git a/chromium/components/performance_manager/graph/page_node_impl.h b/chromium/components/performance_manager/graph/page_node_impl.h
index b26d17c8357..7d2b4387cf8 100644
--- a/chromium/components/performance_manager/graph/page_node_impl.h
+++ b/chromium/components/performance_manager/graph/page_node_impl.h
@@ -12,7 +12,6 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/types/pass_key.h"
#include "components/performance_manager/graph/node_attached_data.h"
@@ -20,6 +19,7 @@
#include "components/performance_manager/public/freezing/freezing.h"
#include "components/performance_manager/public/graph/page_node.h"
#include "components/performance_manager/public/web_contents_proxy.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace performance_manager {
@@ -84,7 +84,8 @@ class PageNodeImpl
// Accessors.
const std::string& browser_context_id() const;
FrameNodeImpl* opener_frame_node() const;
- OpenedType opened_type() const;
+ FrameNodeImpl* embedder_frame_node() const;
+ EmbeddingType embedding_type() const;
bool is_visible() const;
bool is_audible() const;
LoadingState loading_state() const;
@@ -99,18 +100,22 @@ class PageNodeImpl
int64_t navigation_id() const;
const std::string& contents_mime_type() const;
bool had_form_interaction() const;
- const base::Optional<freezing::FreezingVote>& freezing_vote() const;
+ const absl::optional<freezing::FreezingVote>& freezing_vote() const;
// Invoked to set/clear the opener of this page.
- void SetOpenerFrameNodeAndOpenedType(FrameNodeImpl* opener,
- OpenedType opened_type);
- void ClearOpenerFrameNodeAndOpenedType();
+ void SetOpenerFrameNode(FrameNodeImpl* opener);
+ void ClearOpenerFrameNode();
+
+ // Invoked to set/clear the embedder of this page.
+ void SetEmbedderFrameNodeAndEmbeddingType(FrameNodeImpl* embedder,
+ EmbeddingType embedder_type);
+ void ClearEmbedderFrameNodeAndEmbeddingType();
void set_usage_estimate_time(base::TimeTicks usage_estimate_time);
void set_private_footprint_kb_estimate(
uint64_t private_footprint_kb_estimate);
void set_has_nonempty_beforeunload(bool has_nonempty_beforeunload);
- void set_freezing_vote(base::Optional<freezing::FreezingVote> freezing_vote);
+ void set_freezing_vote(absl::optional<freezing::FreezingVote> freezing_vote);
void SetLifecycleStateForTesting(LifecycleState lifecycle_state) {
SetLifecycleState(lifecycle_state);
@@ -186,7 +191,8 @@ class PageNodeImpl
// PageNode implementation.
const std::string& GetBrowserContextID() const override;
const FrameNode* GetOpenerFrameNode() const override;
- OpenedType GetOpenedType() const override;
+ const FrameNode* GetEmbedderFrameNode() const override;
+ EmbeddingType GetEmbeddingType() const override;
bool IsVisible() const override;
base::TimeDelta GetTimeSinceLastVisibilityChange() const override;
bool IsAudible() const override;
@@ -204,7 +210,7 @@ class PageNodeImpl
const GURL& GetMainFrameUrl() const override;
bool HadFormInteraction() const override;
const WebContentsProxy& GetContentsProxy() const override;
- const base::Optional<freezing::FreezingVote>& GetFreezingVote()
+ const absl::optional<freezing::FreezingVote>& GetFreezingVote()
const override;
// NodeBase:
@@ -272,9 +278,13 @@ class PageNodeImpl
FrameNodeImpl* opener_frame_node_ GUARDED_BY_CONTEXT(sequence_checker_) =
nullptr;
- // The way in which this page was opened, if it was opened.
- OpenedType opened_type_ GUARDED_BY_CONTEXT(sequence_checker_) =
- OpenedType::kInvalid;
+ // The embedder of this page, if there is one.
+ FrameNodeImpl* embedder_frame_node_ GUARDED_BY_CONTEXT(sequence_checker_) =
+ nullptr;
+
+ // The way in which this page was embedded, if it was embedded.
+ EmbeddingType embedding_type_ GUARDED_BY_CONTEXT(sequence_checker_) =
+ EmbeddingType::kInvalid;
// Whether or not the page is visible. Driven by browser instrumentation.
// Initialized on construction.
@@ -327,8 +337,8 @@ class PageNodeImpl
// Page::GetFreezingVote for a description of the different values this can
// take.
ObservedProperty::NotifiesOnlyOnChangesWithPreviousValue<
- base::Optional<freezing::FreezingVote>,
- base::Optional<freezing::FreezingVote>,
+ absl::optional<freezing::FreezingVote>,
+ absl::optional<freezing::FreezingVote>,
&PageNodeObserver::OnFreezingVoteChanged>
freezing_vote_ GUARDED_BY_CONTEXT(sequence_checker_);
diff --git a/chromium/components/performance_manager/graph/page_node_impl_describer.cc b/chromium/components/performance_manager/graph/page_node_impl_describer.cc
index 6672ab4731e..10a4a226a88 100644
--- a/chromium/components/performance_manager/graph/page_node_impl_describer.cc
+++ b/chromium/components/performance_manager/graph/page_node_impl_describer.cc
@@ -4,12 +4,12 @@
#include "components/performance_manager/graph/page_node_impl_describer.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "components/performance_manager/graph/page_node_impl.h"
#include "components/performance_manager/public/freezing/freezing.h"
#include "components/performance_manager/public/graph/node_data_describer_registry.h"
#include "components/performance_manager/public/graph/node_data_describer_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace performance_manager {
@@ -18,7 +18,7 @@ namespace {
const char kDescriberName[] = "PageNodeImpl";
const char* FreezingVoteToString(
- base::Optional<freezing::FreezingVote> freezing_vote) {
+ absl::optional<freezing::FreezingVote> freezing_vote) {
if (!freezing_vote)
return "None";
@@ -86,9 +86,9 @@ base::Value PageNodeImplDescriber::DescribePageNodeData(
page_node_impl->is_holding_indexeddb_lock_.value());
result.SetBoolKey("had_form_interaction",
page_node_impl->had_form_interaction_.value());
- if (page_node_impl->opened_type_ != PageNode::OpenedType::kInvalid) {
- result.SetStringKey("opened_type",
- PageNode::ToString(page_node_impl->opened_type_));
+ if (page_node_impl->embedding_type_ != PageNode::EmbeddingType::kInvalid) {
+ result.SetStringKey("embedding_type",
+ PageNode::ToString(page_node_impl->embedding_type_));
}
result.SetStringKey("freezing_vote",
FreezingVoteToString(page_node_impl->freezing_vote()));
diff --git a/chromium/components/performance_manager/graph/page_node_impl_unittest.cc b/chromium/components/performance_manager/graph/page_node_impl_unittest.cc
index 97a2c8871d1..cd9340451da 100644
--- a/chromium/components/performance_manager/graph/page_node_impl_unittest.cc
+++ b/chromium/components/performance_manager/graph/page_node_impl_unittest.cc
@@ -5,7 +5,6 @@
#include "components/performance_manager/graph/page_node_impl.h"
#include "base/containers/contains.h"
-#include "base/optional.h"
#include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/graph/graph_impl_operations.h"
#include "components/performance_manager/graph/process_node_impl.h"
@@ -15,6 +14,7 @@
#include "components/performance_manager/test_support/mock_graphs.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace performance_manager {
@@ -204,14 +204,14 @@ TEST_F(PageNodeImplTest, GetFreezingVote) {
MockSinglePageInSingleProcessGraph mock_graph(graph());
auto* page_node = mock_graph.page.get();
- // This should be initialized to base::nullopt.
+ // This should be initialized to absl::nullopt.
EXPECT_FALSE(page_node->freezing_vote());
page_node->set_freezing_vote(kFreezingVote);
ASSERT_TRUE(page_node->freezing_vote().has_value());
EXPECT_EQ(kFreezingVote, page_node->freezing_vote().value());
- page_node->set_freezing_vote(base::nullopt);
+ page_node->set_freezing_vote(absl::nullopt);
EXPECT_FALSE(page_node->freezing_vote());
}
@@ -224,10 +224,12 @@ class LenientMockObserver : public PageNodeImpl::Observer {
MOCK_METHOD1(OnPageNodeAdded, void(const PageNode*));
MOCK_METHOD1(OnBeforePageNodeRemoved, void(const PageNode*));
- // Note that opener functionality is actually tested in the FrameNodeImpl
- // and GraphImpl unittests.
- MOCK_METHOD3(OnOpenerFrameNodeChanged,
- void(const PageNode*, const FrameNode*, OpenedType));
+ // Note that opener/embedder functionality is actually tested in the
+ // FrameNodeImpl and GraphImpl unittests.
+ MOCK_METHOD2(OnOpenerFrameNodeChanged,
+ void(const PageNode*, const FrameNode*));
+ MOCK_METHOD3(OnEmbedderFrameNodeChanged,
+ void(const PageNode*, const FrameNode*, EmbeddingType));
MOCK_METHOD1(OnIsVisibleChanged, void(const PageNode*));
MOCK_METHOD1(OnIsAudibleChanged, void(const PageNode*));
MOCK_METHOD1(OnLoadingStateChanged, void(const PageNode*));
@@ -241,7 +243,7 @@ class LenientMockObserver : public PageNodeImpl::Observer {
MOCK_METHOD1(OnFaviconUpdated, void(const PageNode*));
MOCK_METHOD1(OnHadFormInteractionChanged, void(const PageNode*));
MOCK_METHOD2(OnFreezingVoteChanged,
- void(const PageNode*, base::Optional<freezing::FreezingVote>));
+ void(const PageNode*, absl::optional<freezing::FreezingVote>));
void SetNotifiedPageNode(const PageNode* page_node) {
notified_page_node_ = page_node;
@@ -327,7 +329,7 @@ TEST_F(PageNodeImplTest, ObserverWorks) {
page_node->OnFaviconUpdated();
EXPECT_EQ(raw_page_node, obs.TakeNotifiedPageNode());
- EXPECT_CALL(obs, OnFreezingVoteChanged(_, testing::Eq(base::nullopt)))
+ EXPECT_CALL(obs, OnFreezingVoteChanged(_, testing::Eq(absl::nullopt)))
.WillOnce(testing::WithArg<0>(
Invoke(&obs, &MockObserver::SetNotifiedPageNode)));
page_node->set_freezing_vote(kFreezingVote);
diff --git a/chromium/components/performance_manager/graph/process_node_impl.cc b/chromium/components/performance_manager/graph/process_node_impl.cc
index 8376621ac58..923e7e6849f 100644
--- a/chromium/components/performance_manager/graph/process_node_impl.cc
+++ b/chromium/components/performance_manager/graph/process_node_impl.cc
@@ -292,7 +292,7 @@ base::Time ProcessNodeImpl::GetLaunchTime() const {
return launch_time();
}
-base::Optional<int32_t> ProcessNodeImpl::GetExitStatus() const {
+absl::optional<int32_t> ProcessNodeImpl::GetExitStatus() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return exit_status();
}
diff --git a/chromium/components/performance_manager/graph/process_node_impl.h b/chromium/components/performance_manager/graph/process_node_impl.h
index e2fd2d7225e..6da4bae9886 100644
--- a/chromium/components/performance_manager/graph/process_node_impl.h
+++ b/chromium/components/performance_manager/graph/process_node_impl.h
@@ -11,7 +11,6 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/time/time.h"
@@ -25,6 +24,7 @@
#include "components/performance_manager/public/render_process_host_proxy.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/tokens/tokens.h"
namespace content {
@@ -132,7 +132,7 @@ class ProcessNodeImpl
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return launch_time_;
}
- base::Optional<int32_t> exit_status() const {
+ absl::optional<int32_t> exit_status() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return exit_status_;
}
@@ -191,7 +191,7 @@ class ProcessNodeImpl
base::ProcessId GetProcessId() const override;
const base::Process& GetProcess() const override;
base::Time GetLaunchTime() const override;
- base::Optional<int32_t> GetExitStatus() const override;
+ absl::optional<int32_t> GetExitStatus() const override;
bool VisitFrameNodes(const FrameNodeVisitor& visitor) const override;
base::flat_set<const FrameNode*> GetFrameNodes() const override;
base::flat_set<const WorkerNode*> GetWorkerNodes() const override;
@@ -222,7 +222,7 @@ class ProcessNodeImpl
process_ GUARDED_BY_CONTEXT(sequence_checker_);
base::Time launch_time_ GUARDED_BY_CONTEXT(sequence_checker_);
- base::Optional<int32_t> exit_status_ GUARDED_BY_CONTEXT(sequence_checker_);
+ absl::optional<int32_t> exit_status_ GUARDED_BY_CONTEXT(sequence_checker_);
const content::ProcessType process_type_
GUARDED_BY_CONTEXT(sequence_checker_);
diff --git a/chromium/components/performance_manager/graph/process_node_impl_unittest.cc b/chromium/components/performance_manager/graph/process_node_impl_unittest.cc
index 59f8f97ab10..e7f291f097f 100644
--- a/chromium/components/performance_manager/graph/process_node_impl_unittest.cc
+++ b/chromium/components/performance_manager/graph/process_node_impl_unittest.cc
@@ -308,7 +308,7 @@ class LenientFakeBackgroundTracingManager
}
std::unique_ptr<content::BackgroundTracingConfig> GetBackgroundTracingConfig(
const std::string& trial_name) override {
- return std::unique_ptr<content::BackgroundTracingConfig>();
+ return nullptr;
}
void AbortScenarioForTesting() override {}
void SetTraceToUploadForTesting(
diff --git a/chromium/components/performance_manager/graph/system_node_impl.h b/chromium/components/performance_manager/graph/system_node_impl.h
index 6ed64397da1..79dfc1ba239 100644
--- a/chromium/components/performance_manager/graph/system_node_impl.h
+++ b/chromium/components/performance_manager/graph/system_node_impl.h
@@ -13,7 +13,6 @@
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process_handle.h"
-#include "base/time/time.h"
#include "components/performance_manager/graph/node_base.h"
#include "components/performance_manager/graph/properties.h"
#include "components/performance_manager/public/graph/system_node.h"
diff --git a/chromium/components/performance_manager/performance_manager_browsertest.cc b/chromium/components/performance_manager/performance_manager_browsertest.cc
index 2c8fcc06ea4..fd539cf376d 100644
--- a/chromium/components/performance_manager/performance_manager_browsertest.cc
+++ b/chromium/components/performance_manager/performance_manager_browsertest.cc
@@ -85,8 +85,7 @@ IN_PROC_BROWSER_TEST_F(PerformanceManagerBrowserTest,
run_loop_after_contents_reset.Run();
}
-IN_PROC_BROWSER_TEST_F(PerformanceManagerBrowserTest,
- PopupOpenerTrackingWorks) {
+IN_PROC_BROWSER_TEST_F(PerformanceManagerBrowserTest, OpenerTrackingWorks) {
// Load a page that will load a popup.
GURL url(embedded_test_server()->GetURL("a.com", "/a_popup_a.html"));
content::ShellAddedObserver shell_added_observer;
@@ -107,9 +106,8 @@ IN_PROC_BROWSER_TEST_F(PerformanceManagerBrowserTest,
EXPECT_TRUE(page);
auto* frame = page->GetMainFrameNode();
EXPECT_EQ(1u, frame->GetOpenedPageNodes().size());
- auto* opened_page = *(frame->GetOpenedPageNodes().begin());
- EXPECT_EQ(PageNode::OpenedType::kPopup, opened_page->GetOpenedType());
- EXPECT_EQ(frame, opened_page->GetOpenerFrameNode());
+ auto* embedded_page = *(frame->GetOpenedPageNodes().begin());
+ EXPECT_EQ(frame, embedded_page->GetOpenerFrameNode());
run_loop.Quit();
}));
run_loop.Run();
diff --git a/chromium/components/performance_manager/performance_manager_lifetime.cc b/chromium/components/performance_manager/performance_manager_lifetime.cc
index 9a4af3057ba..f0517f59901 100644
--- a/chromium/components/performance_manager/performance_manager_lifetime.cc
+++ b/chromium/components/performance_manager/performance_manager_lifetime.cc
@@ -31,8 +31,8 @@ GraphCreatedCallback* GetAdditionalGraphCreatedCallback() {
return additional_graph_created_callback.get();
}
-base::Optional<Decorators>* GetDecoratorsOverride() {
- static base::NoDestructor<base::Optional<Decorators>> decorators_override;
+absl::optional<Decorators>* GetDecoratorsOverride() {
+ static base::NoDestructor<absl::optional<Decorators>> decorators_override;
return decorators_override.get();
}
@@ -92,7 +92,7 @@ void PerformanceManagerLifetime::SetAdditionalGraphCreatedCallbackForTesting(
// static
void PerformanceManagerLifetime::SetDecoratorsOverrideForTesting(
- base::Optional<Decorators> decorators_override) {
+ absl::optional<Decorators> decorators_override) {
*GetDecoratorsOverride() = decorators_override;
}
diff --git a/chromium/components/performance_manager/performance_manager_registry_impl.cc b/chromium/components/performance_manager/performance_manager_registry_impl.cc
index dd3c4c5c5b1..9f797a123dc 100644
--- a/chromium/components/performance_manager/performance_manager_registry_impl.cc
+++ b/chromium/components/performance_manager/performance_manager_registry_impl.cc
@@ -154,7 +154,7 @@ void PerformanceManagerRegistryImpl::NotifyBrowserContextAdded(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
content::StoragePartition* storage_partition =
- content::BrowserContext::GetDefaultStoragePartition(browser_context);
+ browser_context->GetDefaultStoragePartition();
// Create an adapter for the service worker context.
auto insertion_result = service_worker_context_adapters_.emplace(
diff --git a/chromium/components/performance_manager/performance_manager_registry_impl.h b/chromium/components/performance_manager/performance_manager_registry_impl.h
index 290d19d70ba..309c702f27f 100644
--- a/chromium/components/performance_manager/performance_manager_registry_impl.h
+++ b/chromium/components/performance_manager/performance_manager_registry_impl.h
@@ -6,7 +6,6 @@
#define COMPONENTS_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_REGISTRY_IMPL_H_
#include <memory>
-#include <string>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
diff --git a/chromium/components/performance_manager/performance_manager_tab_helper.cc b/chromium/components/performance_manager/performance_manager_tab_helper.cc
index 7b2672713e7..88801cb44ce 100644
--- a/chromium/components/performance_manager/performance_manager_tab_helper.cc
+++ b/chromium/components/performance_manager/performance_manager_tab_helper.cc
@@ -64,10 +64,9 @@ bool ConnectWindowOpenRelationshipIfExists(PerformanceManagerTabHelper* helper,
return false;
PerformanceManagerImpl::CallOnGraphImpl(
- FROM_HERE, base::BindOnce(&PageNodeImpl::SetOpenerFrameNodeAndOpenedType,
+ FROM_HERE, base::BindOnce(&PageNodeImpl::SetOpenerFrameNode,
base::Unretained(helper->page_node()),
- base::Unretained(opener_frame_node),
- PageNode::OpenedType::kPopup));
+ base::Unretained(opener_frame_node)));
return true;
}
@@ -372,10 +371,10 @@ void PerformanceManagerTabHelper::InnerWebContentsAttached(
DCHECK(page);
auto* frame = GetFrameNode(render_frame_host);
- // Determine the opened type.
- auto opened_type = PageNode::OpenedType::kInvalid;
+ // Determine the embedded type.
+ auto embedding_type = PageNode::EmbeddingType::kInvalid;
if (inner_web_contents->IsPortal()) {
- opened_type = PageNode::OpenedType::kPortal;
+ embedding_type = PageNode::EmbeddingType::kPortal;
// In the case of portals there can be a temporary RFH that is created that
// will never actually be committed to the frame tree (for which we'll never
@@ -385,15 +384,11 @@ void PerformanceManagerTabHelper::InnerWebContentsAttached(
if (!frame)
frame = GetFrameNode(render_frame_host->GetParent());
} else {
- opened_type = PageNode::OpenedType::kGuestView;
+ embedding_type = PageNode::EmbeddingType::kGuestView;
// For a guest view, the RFH should already have been seen.
-
// Note that guest views can simultaneously have openers *and* be embedded.
- // The embedded relationship has higher priority, but we'll fall back to
- // using the window.open relationship if the embedded relationship is
- // severed.
}
- DCHECK_NE(PageNode::OpenedType::kInvalid, opened_type);
+ DCHECK_NE(PageNode::EmbeddingType::kInvalid, embedding_type);
if (!frame) {
DCHECK(!render_frame_host->IsRenderFrameCreated());
DCHECK(!inner_web_contents->IsPortal());
@@ -406,24 +401,20 @@ void PerformanceManagerTabHelper::InnerWebContentsAttached(
}
PerformanceManagerImpl::CallOnGraphImpl(
- FROM_HERE, base::BindOnce(&PageNodeImpl::SetOpenerFrameNodeAndOpenedType,
- base::Unretained(page), base::Unretained(frame),
- opened_type));
+ FROM_HERE,
+ base::BindOnce(&PageNodeImpl::SetEmbedderFrameNodeAndEmbeddingType,
+ base::Unretained(page), base::Unretained(frame),
+ embedding_type));
}
void PerformanceManagerTabHelper::InnerWebContentsDetached(
content::WebContents* inner_web_contents) {
auto* helper = FromWebContents(inner_web_contents);
DCHECK(helper);
-
- // Fall back to using the window.open opener if it exists. If not, simply
- // clear the opener relationship entirely.
- if (!ConnectWindowOpenRelationshipIfExists(helper, inner_web_contents)) {
- PerformanceManagerImpl::CallOnGraphImpl(
- FROM_HERE,
- base::BindOnce(&PageNodeImpl::ClearOpenerFrameNodeAndOpenedType,
- base::Unretained(helper->page_node())));
- }
+ PerformanceManagerImpl::CallOnGraphImpl(
+ FROM_HERE,
+ base::BindOnce(&PageNodeImpl::ClearEmbedderFrameNodeAndEmbeddingType,
+ base::Unretained(helper->page_node())));
}
void PerformanceManagerTabHelper::WebContentsDestroyed() {
diff --git a/chromium/components/performance_manager/performance_manager_tab_helper.h b/chromium/components/performance_manager/performance_manager_tab_helper.h
index 8ffb2c7e9ae..6ded9dfde1d 100644
--- a/chromium/components/performance_manager/performance_manager_tab_helper.h
+++ b/chromium/components/performance_manager/performance_manager_tab_helper.h
@@ -7,7 +7,6 @@
#include <map>
#include <memory>
-#include <string>
#include <vector>
#include "base/macros.h"
diff --git a/chromium/components/performance_manager/persistence/site_data/leveldb_site_data_store.cc b/chromium/components/performance_manager/persistence/site_data/leveldb_site_data_store.cc
index 6871af73a79..d1a1668ed60 100644
--- a/chromium/components/performance_manager/persistence/site_data/leveldb_site_data_store.cc
+++ b/chromium/components/performance_manager/persistence/site_data/leveldb_site_data_store.cc
@@ -10,7 +10,6 @@
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/callback.h"
-#include "base/callback_forward.h"
#include "base/files/file_util.h"
#include "base/hash/md5.h"
#include "base/logging.h"
@@ -102,8 +101,8 @@ bool ShouldAttemptDbRepair(const leveldb::Status& status) {
}
struct DatabaseSizeResult {
- base::Optional<int64_t> num_rows;
- base::Optional<int64_t> on_disk_size_kb;
+ absl::optional<int64_t> num_rows;
+ absl::optional<int64_t> on_disk_size_kb;
};
std::string SerializeOriginIntoDatabaseKey(const url::Origin& origin) {
@@ -152,7 +151,7 @@ class LevelDBSiteDataStore::AsyncHelper {
// Implementations of the DB manipulation functions of
// LevelDBSiteDataStore that run on a blocking sequence.
- base::Optional<SiteDataProto> ReadSiteDataFromDB(const url::Origin& origin);
+ absl::optional<SiteDataProto> ReadSiteDataFromDB(const url::Origin& origin);
void WriteSiteDataIntoDB(const url::Origin& origin,
const SiteDataProto& site_characteristic_proto);
void RemoveSiteDataFromDB(const std::vector<url::Origin>& site_origin);
@@ -253,13 +252,13 @@ void LevelDBSiteDataStore::AsyncHelper::OpenOrCreateDatabase() {
}
}
-base::Optional<SiteDataProto>
+absl::optional<SiteDataProto>
LevelDBSiteDataStore::AsyncHelper::ReadSiteDataFromDB(
const url::Origin& origin) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!db_)
- return base::nullopt;
+ return absl::nullopt;
leveldb::Status s;
std::string protobuf_value;
@@ -269,11 +268,11 @@ LevelDBSiteDataStore::AsyncHelper::ReadSiteDataFromDB(
s = db_->Get(read_options_, SerializeOriginIntoDatabaseKey(origin),
&protobuf_value);
}
- base::Optional<SiteDataProto> site_characteristic_proto;
+ absl::optional<SiteDataProto> site_characteristic_proto;
if (s.ok()) {
site_characteristic_proto = SiteDataProto();
if (!site_characteristic_proto->ParseFromString(protobuf_value)) {
- site_characteristic_proto = base::nullopt;
+ site_characteristic_proto = absl::nullopt;
DLOG(ERROR) << "Error while trying to parse a SiteDataProto "
<< "protobuf.";
}
diff --git a/chromium/components/performance_manager/persistence/site_data/leveldb_site_data_store_unittest.cc b/chromium/components/performance_manager/persistence/site_data/leveldb_site_data_store_unittest.cc
index 1cf418fb053..df283fb9628 100644
--- a/chromium/components/performance_manager/persistence/site_data/leveldb_site_data_store_unittest.cc
+++ b/chromium/components/performance_manager/persistence/site_data/leveldb_site_data_store_unittest.cc
@@ -124,7 +124,7 @@ class LevelDBSiteDataStoreTest : public ::testing::Test {
bool success = false;
auto init_callback = base::BindOnce(
[](SiteDataProto* receiving_proto, bool* success,
- base::Optional<SiteDataProto> proto_opt) {
+ absl::optional<SiteDataProto> proto_opt) {
*success = proto_opt.has_value();
if (proto_opt)
receiving_proto->CopyFrom(proto_opt.value());
@@ -211,8 +211,8 @@ TEST_F(LevelDBSiteDataStoreTest, GetDatabaseSize) {
std::vector<url::Origin> site_origins = AddDummyEntriesToDB(200);
auto size_callback =
- base::BindLambdaForTesting([&](base::Optional<int64_t> num_rows,
- base::Optional<int64_t> on_disk_size_kb) {
+ base::BindLambdaForTesting([&](absl::optional<int64_t> num_rows,
+ absl::optional<int64_t> on_disk_size_kb) {
EXPECT_TRUE(num_rows);
// The DB contains an extra row for metadata.
int64_t expected_rows = site_origins.size() + 1;
diff --git a/chromium/components/performance_manager/persistence/site_data/non_recording_site_data_cache.cc b/chromium/components/performance_manager/persistence/site_data/non_recording_site_data_cache.cc
index b1e627a2c1e..ce141a96a12 100644
--- a/chromium/components/performance_manager/persistence/site_data/non_recording_site_data_cache.cc
+++ b/chromium/components/performance_manager/persistence/site_data/non_recording_site_data_cache.cc
@@ -64,7 +64,7 @@ std::vector<url::Origin> NonRecordingSiteDataCache::GetAllInMemoryOrigins() {
void NonRecordingSiteDataCache::GetDataStoreSize(
DataStoreSizeCallback on_have_data) {
if (!data_cache_inspector_) {
- std::move(on_have_data).Run(base::nullopt, base::nullopt);
+ std::move(on_have_data).Run(absl::nullopt, absl::nullopt);
return;
}
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory.cc b/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory.cc
index 460ce124009..440aa963704 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory.cc
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory.cc
@@ -104,7 +104,7 @@ void SiteDataCacheFactory::SetCacheInspectorForTesting(
void SiteDataCacheFactory::OnBrowserContextCreated(
const std::string& browser_context_id,
const base::FilePath& context_path,
- base::Optional<std::string> parent_context_id) {
+ absl::optional<std::string> parent_context_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!base::Contains(data_cache_map_, browser_context_id));
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory.h b/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory.h
index 2d7336ec0cf..f77d3d36eb0 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory.h
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory.h
@@ -13,11 +13,11 @@
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "components/performance_manager/persistence/site_data/site_data_cache.h"
#include "content/public/browser/browser_context.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class BrowserContext;
@@ -75,7 +75,7 @@ class SiteDataCacheFactory {
// that runs on this object's task runner.
void OnBrowserContextCreated(const std::string& browser_context_id,
const base::FilePath& context_path,
- base::Optional<std::string> parent_context_id);
+ absl::optional<std::string> parent_context_id);
void OnBrowserContextDestroyed(const std::string& browser_context_id);
private:
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc b/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc
index a1f74ed88d3..1cfa8d6cb2b 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc
@@ -10,7 +10,6 @@
#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
@@ -20,6 +19,7 @@
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace performance_manager {
@@ -32,7 +32,7 @@ TEST(SiteDataCacheFactoryTest, EndToEnd) {
content::TestBrowserContext browser_context;
cache_factory.AsyncCall(&SiteDataCacheFactory::OnBrowserContextCreated)
.WithArgs(browser_context.UniqueId(), browser_context.GetPath(),
- base::nullopt);
+ absl::nullopt);
{
base::RunLoop run_loop;
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_cache_impl_unittest.cc b/chromium/components/performance_manager/persistence/site_data/site_data_cache_impl_unittest.cc
index 54c692ef96a..b6f7f38395a 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_cache_impl_unittest.cc
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_cache_impl_unittest.cc
@@ -25,15 +25,6 @@ namespace {
constexpr base::TimeDelta kDelay = base::TimeDelta::FromMinutes(1);
-// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
-// function.
-url::Origin TestOrigin1() {
- return url::Origin::Create(GURL("http://www.foo.com"));
-}
-url::Origin TestOrigin2() {
- return url::Origin::Create(GURL("http://www.bar.com"));
-}
-
class MockSiteCache : public testing::NoopSiteDataStore {
public:
MockSiteCache() = default;
@@ -68,22 +59,21 @@ class SiteDataCacheImplTest : public ::testing::Test {
void WaitForAsyncOperationsToComplete() { task_environment_.RunUntilIdle(); }
// Populates |writer_|, |reader_| and |data_| to refer to a tab navigated to
- // |TestOrigin1()| that updated its title in background. Populates |writer2_|,
- // |reader2_| and |data2_| to refer to a tab navigated to |TestOrigin2()| that
+ // |origin_| that updated its title in background. Populates |writer2_|,
+ // |reader2_| and |data2_| to refer to a tab navigated to |origin2_| that
// updates its favicon in background.
void SetupTwoSitesUsingFeaturesInBackground() {
// Load a first origin, and then make use of a feature on it.
ASSERT_FALSE(reader_);
- reader_ = data_cache_->GetReaderForOrigin(TestOrigin1());
+ reader_ = data_cache_->GetReaderForOrigin(origin_);
EXPECT_TRUE(reader_);
ASSERT_FALSE(writer_);
- writer_ = data_cache_->GetWriterForOrigin(TestOrigin1());
+ writer_ = data_cache_->GetWriterForOrigin(origin_);
EXPECT_TRUE(writer_);
ASSERT_FALSE(data_);
- data_ =
- data_cache_->origin_data_map_for_testing().find(TestOrigin1())->second;
+ data_ = data_cache_->origin_data_map_for_testing().find(origin_)->second;
EXPECT_TRUE(data_);
EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown,
@@ -96,16 +86,15 @@ class SiteDataCacheImplTest : public ::testing::Test {
// Load a second origin, make use of a feature on it too.
ASSERT_FALSE(reader2_);
- reader2_ = data_cache_->GetReaderForOrigin(TestOrigin2());
+ reader2_ = data_cache_->GetReaderForOrigin(origin2_);
EXPECT_TRUE(reader2_);
ASSERT_FALSE(writer2_);
- writer2_ = data_cache_->GetWriterForOrigin(TestOrigin2());
+ writer2_ = data_cache_->GetWriterForOrigin(origin2_);
EXPECT_TRUE(writer2_);
ASSERT_FALSE(data2_);
- data2_ =
- data_cache_->origin_data_map_for_testing().find(TestOrigin2())->second;
+ data2_ = data_cache_->origin_data_map_for_testing().find(origin2_)->second;
EXPECT_TRUE(data2_);
EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureUsageUnknown,
@@ -130,16 +119,18 @@ class SiteDataCacheImplTest : public ::testing::Test {
std::unique_ptr<SiteDataReader> reader_;
std::unique_ptr<SiteDataWriter> writer_;
internal::SiteDataImpl* data_ = nullptr;
+ url::Origin origin_ = url::Origin::Create(GURL("http://www.foo.com"));
std::unique_ptr<SiteDataReader> reader2_;
std::unique_ptr<SiteDataWriter> writer2_;
internal::SiteDataImpl* data2_ = nullptr;
+ url::Origin origin2_ = url::Origin::Create(GURL("http://www.bar.com"));
};
TEST_F(SiteDataCacheImplTest, EndToEnd) {
- auto reader = data_cache_->GetReaderForOrigin(TestOrigin1());
+ auto reader = data_cache_->GetReaderForOrigin(origin_);
EXPECT_TRUE(reader);
- auto writer = data_cache_->GetWriterForOrigin(TestOrigin1());
+ auto writer = data_cache_->GetWriterForOrigin(origin_);
EXPECT_TRUE(writer);
EXPECT_EQ(1U, data_cache_->origin_data_map_for_testing().size());
@@ -154,9 +145,9 @@ TEST_F(SiteDataCacheImplTest, EndToEnd) {
EXPECT_EQ(performance_manager::SiteFeatureUsage::kSiteFeatureInUse,
reader->UpdatesTitleInBackground());
- auto reader_copy = data_cache_->GetReaderForOrigin(TestOrigin1());
+ auto reader_copy = data_cache_->GetReaderForOrigin(origin_);
EXPECT_EQ(1U, data_cache_->origin_data_map_for_testing().size());
- auto reader2 = data_cache_->GetReaderForOrigin(TestOrigin2());
+ auto reader2 = data_cache_->GetReaderForOrigin(origin2_);
EXPECT_EQ(2U, data_cache_->origin_data_map_for_testing().size());
reader2.reset();
@@ -183,10 +174,10 @@ TEST_F(SiteDataCacheImplTest, ClearSiteDataForOrigins) {
// cache.
const url::Origin kOriginNotInMap =
url::Origin::Create(GURL("http://www.url-not-in-map.com"));
- std::vector<url::Origin> origins_to_remove = {TestOrigin1(), kOriginNotInMap};
+ std::vector<url::Origin> origins_to_remove = {origin_, kOriginNotInMap};
EXPECT_CALL(*mock_db_,
RemoveSiteDataFromStore(::testing::WhenSorted(
- ::testing::ElementsAre(TestOrigin1(), kOriginNotInMap))));
+ ::testing::ElementsAre(origin_, kOriginNotInMap))));
data_cache_->ClearSiteDataForOrigins(origins_to_remove);
::testing::Mock::VerifyAndClear(mock_db_);
@@ -241,22 +232,22 @@ TEST_F(SiteDataCacheImplTest, InspectorWorks) {
EXPECT_EQ(0U, inspector->GetAllInMemoryOrigins().size());
std::unique_ptr<SiteDataProto> data;
bool is_dirty = false;
- EXPECT_FALSE(inspector->GetDataForOrigin(TestOrigin1(), &is_dirty, &data));
+ EXPECT_FALSE(inspector->GetDataForOrigin(origin_, &is_dirty, &data));
EXPECT_FALSE(is_dirty);
EXPECT_EQ(nullptr, data.get());
{
// Add an entry, see that it's reflected in the inspector interface.
- auto writer = data_cache_->GetWriterForOrigin(TestOrigin1());
+ auto writer = data_cache_->GetWriterForOrigin(origin_);
EXPECT_EQ(1U, inspector->GetAllInMemoryOrigins().size());
- EXPECT_TRUE(inspector->GetDataForOrigin(TestOrigin1(), &is_dirty, &data));
+ EXPECT_TRUE(inspector->GetDataForOrigin(origin_, &is_dirty, &data));
EXPECT_FALSE(is_dirty);
ASSERT_NE(nullptr, data.get());
// Touch the underlying data, see that the dirty bit updates.
writer->NotifySiteLoaded(TabVisibility::kBackground);
- EXPECT_TRUE(inspector->GetDataForOrigin(TestOrigin1(), &is_dirty, &data));
+ EXPECT_TRUE(inspector->GetDataForOrigin(origin_, &is_dirty, &data));
EXPECT_TRUE(is_dirty);
writer->NotifySiteUnloaded(TabVisibility::kBackground);
}
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_cache_inspector.h b/chromium/components/performance_manager/persistence/site_data/site_data_cache_inspector.h
index 84d5207a716..c4294a61f30 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_cache_inspector.h
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_cache_inspector.h
@@ -7,13 +7,12 @@
#include <cstdint>
#include <memory>
-#include <string>
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
#include "base/supports_user_data.h"
#include "components/performance_manager/persistence/site_data/site_data.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
namespace performance_manager {
@@ -39,8 +38,8 @@ class SiteDataCacheInspector {
// the number can't be determined. |on_disk_size_kb| is the on-disk size of
// the database, or -1 if the on-disk size can't be determined.
using DataStoreSizeCallback =
- base::OnceCallback<void(base::Optional<int64_t> num_rows,
- base::Optional<int64_t> on_disk_size_kb)>;
+ base::OnceCallback<void(absl::optional<int64_t> num_rows,
+ absl::optional<int64_t> on_disk_size_kb)>;
virtual void GetDataStoreSize(DataStoreSizeCallback on_have_data) = 0;
// Retrieves the in-memory data for a given origin.
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_impl.cc b/chromium/components/performance_manager/persistence/site_data/site_data_impl.cc
index eeb4a5da4c1..624f44b0009 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_impl.cc
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_impl.cc
@@ -315,7 +315,7 @@ void SiteDataImpl::NotifyFeatureUsage(SiteDataFeatureProto* feature_proto,
}
void SiteDataImpl::OnInitCallback(
- base::Optional<SiteDataProto> db_site_characteristics) {
+ absl::optional<SiteDataProto> db_site_characteristics) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Check if the initialization has succeeded.
if (db_site_characteristics) {
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_impl.h b/chromium/components/performance_manager/persistence/site_data/site_data_impl.h
index f48c7dd1a7d..12db6045374 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_impl.h
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_impl.h
@@ -232,7 +232,7 @@ class SiteDataImpl : public base::RefCounted<SiteDataImpl> {
// Callback that needs to be called by the data store once it has finished
// trying to read the protobuf.
- void OnInitCallback(base::Optional<SiteDataProto> site_characteristic_proto);
+ void OnInitCallback(absl::optional<SiteDataProto> site_characteristic_proto);
// Decrement the |loaded_tabs_in_background_count_| counter and update the
// local feature observation durations if necessary.
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_impl_unittest.cc b/chromium/components/performance_manager/persistence/site_data/site_data_impl_unittest.cc
index 59ca53b9ed0..36e7bdf4709 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_impl_unittest.cc
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_impl_unittest.cc
@@ -415,7 +415,7 @@ TEST_F(SiteDataImplTest, OnInitCallbackMergePreviousObservations) {
// Initialize a fake protobuf that indicates that this site updates its title
// while in background and set a fake last loaded time (this should be
// overridden once the callback runs).
- base::Optional<SiteDataProto> test_proto = SiteDataProto();
+ absl::optional<SiteDataProto> test_proto = SiteDataProto();
SiteDataFeatureProto unused_feature_proto = GetUnusedFeatureProto();
test_proto->mutable_updates_title_in_background()->CopyFrom(
GetUsedFeatureProto());
@@ -590,7 +590,7 @@ TEST_F(SiteDataImplTest, OptionalFieldsNotPopulatedWhenClean) {
EXPECT_EQ(0u, local_site_data->cpu_usage_estimate().num_datums());
EXPECT_EQ(0u, local_site_data->private_footprint_kb_estimate().num_datums());
- base::Optional<SiteDataProto> test_proto = SiteDataProto();
+ absl::optional<SiteDataProto> test_proto = SiteDataProto();
// Run the callback to indicate that the initialization has completed.
std::move(read_cb).Run(test_proto);
@@ -672,7 +672,7 @@ TEST_F(SiteDataImplTest, DataLoadedCallbackInvoked) {
base::BindLambdaForTesting([&]() { callback_invoked = true; }));
// Run the callback to indicate that the initialization has completed.
- base::Optional<SiteDataProto> test_proto = SiteDataProto();
+ absl::optional<SiteDataProto> test_proto = SiteDataProto();
std::move(read_cb).Run(test_proto);
EXPECT_TRUE(callback_invoked);
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc b/chromium/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc
index 7145a122c99..dfde1d12f7a 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc
@@ -144,7 +144,7 @@ TEST_F(SiteDataReaderTest, FreeingReaderDoesntCauseWriteOperation) {
auto read_from_store_mock_impl =
[&](const url::Origin& origin,
SiteDataStore::ReadSiteDataFromStoreCallback& callback) {
- std::move(callback).Run(base::Optional<SiteDataProto>(proto));
+ std::move(callback).Run(absl::optional<SiteDataProto>(proto));
};
EXPECT_CALL(data_store, OnReadSiteDataFromStore(
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_store.h b/chromium/components/performance_manager/persistence/site_data/site_data_store.h
index 9301661e4c0..3a6e4aa2449 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_store.h
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_store.h
@@ -9,8 +9,8 @@
#include "base/callback_forward.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/performance_manager/persistence/site_data/site_data.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
class SiteDataProto;
@@ -21,13 +21,13 @@ namespace performance_manager {
class SiteDataStore {
public:
// Callback to call once the initialization from the store has completed,
- // |site_data_proto| should be equal to base::nullopt if the initialization
+ // |site_data_proto| should be equal to absl::nullopt if the initialization
// has failed.
using ReadSiteDataFromStoreCallback =
- base::OnceCallback<void(base::Optional<SiteDataProto> site_data_proto)>;
+ base::OnceCallback<void(absl::optional<SiteDataProto> site_data_proto)>;
using GetStoreSizeCallback =
- base::OnceCallback<void(base::Optional<int64_t> num_rows,
- base::Optional<int64_t> on_disk_size_kb)>;
+ base::OnceCallback<void(absl::optional<int64_t> num_rows,
+ absl::optional<int64_t> on_disk_size_kb)>;
SiteDataStore() = default;
virtual ~SiteDataStore() {}
diff --git a/chromium/components/performance_manager/persistence/site_data/site_data_writer.h b/chromium/components/performance_manager/persistence/site_data/site_data_writer.h
index f21ac3f494a..10fb400ab12 100644
--- a/chromium/components/performance_manager/persistence/site_data/site_data_writer.h
+++ b/chromium/components/performance_manager/persistence/site_data/site_data_writer.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_PERFORMANCE_MANAGER_PERSISTENCE_SITE_DATA_SITE_DATA_WRITER_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PERSISTENCE_SITE_DATA_SITE_DATA_WRITER_H_
-#include <memory>
-
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "components/performance_manager/persistence/site_data/site_data_impl.h"
diff --git a/chromium/components/performance_manager/persistence/site_data/unittest_utils.cc b/chromium/components/performance_manager/persistence/site_data/unittest_utils.cc
index f60b57222b9..4eeefafa4c8 100644
--- a/chromium/components/performance_manager/persistence/site_data/unittest_utils.cc
+++ b/chromium/components/performance_manager/persistence/site_data/unittest_utils.cc
@@ -24,7 +24,7 @@ NoopSiteDataStore::~NoopSiteDataStore() = default;
void NoopSiteDataStore::ReadSiteDataFromStore(
const url::Origin& origin,
ReadSiteDataFromStoreCallback callback) {
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
}
void NoopSiteDataStore::WriteSiteDataIntoStore(
@@ -37,7 +37,7 @@ void NoopSiteDataStore::RemoveSiteDataFromStore(
void NoopSiteDataStore::ClearStore() {}
void NoopSiteDataStore::GetStoreSize(GetStoreSizeCallback callback) {
- std::move(callback).Run(base::nullopt, base::nullopt);
+ std::move(callback).Run(absl::nullopt, absl::nullopt);
}
void NoopSiteDataStore::SetInitializationCallbackForTesting(
diff --git a/chromium/components/performance_manager/public/decorators/process_metrics_decorator.h b/chromium/components/performance_manager/public/decorators/process_metrics_decorator.h
new file mode 100644
index 00000000000..ad464922cb5
--- /dev/null
+++ b/chromium/components/performance_manager/public/decorators/process_metrics_decorator.h
@@ -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.
+
+#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_PROCESS_METRICS_DECORATOR_H_
+#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_PROCESS_METRICS_DECORATOR_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "components/performance_manager/public/graph/graph.h"
+#include "components/performance_manager/public/graph/graph_registered.h"
+
+namespace memory_instrumentation {
+class GlobalMemoryDump;
+}
+
+namespace performance_manager {
+
+// The ProcessMetricsDecorator is responsible for adorning process nodes with
+// performance metrics.
+class ProcessMetricsDecorator
+ : public GraphOwned,
+ public GraphRegisteredImpl<ProcessMetricsDecorator> {
+ public:
+ ProcessMetricsDecorator();
+ ~ProcessMetricsDecorator() override;
+
+ // A token used to express an interest for process metrics. Process metrics
+ // will only be updated as long as there's at least one token in existence.
+ //
+ // These objects shouldn't be created directly, they should be acquired by
+ // calling RegisterInterestForProcessMetrics.
+ class ScopedMetricsInterestToken {
+ public:
+ ScopedMetricsInterestToken(const ScopedMetricsInterestToken& other) =
+ delete;
+ ScopedMetricsInterestToken& operator=(const ScopedMetricsInterestToken&) =
+ delete;
+ virtual ~ScopedMetricsInterestToken() = default;
+
+ protected:
+ ScopedMetricsInterestToken() = default;
+ };
+
+ // Allows a process to register an interest for process metrics. Metrics are
+ // only guaranteed to be refreshed for the lifetime of the returned token.
+ static std::unique_ptr<ScopedMetricsInterestToken>
+ RegisterInterestForProcessMetrics(Graph* graph);
+
+ // GraphOwned:
+ void OnPassedToGraph(Graph* graph) override;
+ void OnTakenFromGraph(Graph* graph) override;
+
+ void SetGraphForTesting(Graph* graph) { graph_ = graph; }
+ bool IsTimerRunningForTesting() const { return refresh_timer_.IsRunning(); }
+
+ base::TimeDelta GetTimerDelayForTesting() const {
+ return refresh_timer_.GetCurrentDelay();
+ }
+
+ protected:
+ class ScopedMetricsInterestTokenImpl;
+
+ // Starts/Stop the timer responsible for refreshing the process nodes metrics.
+ void StartTimer();
+ void StopTimer();
+
+ // Schedule a refresh of the metrics for all the process nodes.
+ void RefreshMetrics();
+
+ // Query the MemoryInstrumentation service to get the memory metrics for all
+ // processes and run |callback| with the result. Virtual to make a test seam.
+ virtual void RequestProcessesMemoryMetrics(
+ base::OnceCallback<
+ void(bool success,
+ std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump)>
+ callback);
+
+ // Function that should be used as a callback to
+ // MemoryInstrumentation::RequestPrivateMemoryFootprint. |success| will
+ // indicate if the data has been retrieved successfully and |process_dumps|
+ // will contain the data for all the Chrome processes for which this data was
+ // available.
+ void DidGetMemoryUsage(
+ bool success,
+ std::unique_ptr<memory_instrumentation::GlobalMemoryDump> process_dumps);
+
+ // Called whenever a ScopedMetricsInterestToken is created/released.
+ void OnMetricsInterestTokenCreated();
+ void OnMetricsInterestTokenReleased();
+
+ private:
+ // The timer responsible for refreshing the metrics.
+ base::RetainingOneShotTimer refresh_timer_;
+
+ // The Graph instance owning this decorator.
+ Graph* graph_;
+
+ // The number of clients currently interested by the metrics tracked by this
+ // class.
+ size_t metrics_interest_token_count_ = 0;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ base::WeakPtrFactory<ProcessMetricsDecorator> weak_factory_{this};
+ DISALLOW_COPY_AND_ASSIGN(ProcessMetricsDecorator);
+};
+
+} // namespace performance_manager
+
+#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_DECORATORS_PROCESS_METRICS_DECORATOR_H_
diff --git a/chromium/components/performance_manager/public/features.h b/chromium/components/performance_manager/public/features.h
index 98d11af50c5..ca66e1a2aeb 100644
--- a/chromium/components/performance_manager/public/features.h
+++ b/chromium/components/performance_manager/public/features.h
@@ -5,12 +5,14 @@
// This header contains field trial and variations definitions for policies,
// mechanisms and features in the performance_manager component.
-#include "base/feature_list.h"
-#include "base/time/time.h"
-
#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_FEATURES_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_FEATURES_H_
+#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+
namespace performance_manager {
namespace features {
@@ -39,6 +41,50 @@ struct TabLoadingFrameNavigationThrottlesParams {
// The feature that gates whether or not the PM runs on the main (UI) thread.
extern const base::Feature kRunOnMainThread;
+#if !defined(OS_ANDROID)
+// Enables urgent discarding of pages directly from PerformanceManager rather
+// than via TabManager.
+extern const base::Feature kUrgentDiscardingFromPerformanceManager;
+
+// The discard strategy to use.
+// Integer values are specified to allow conversion from the integer value in
+// the DiscardStrategy feature param.
+enum class DiscardStrategy : int {
+ // Discards the least recently used tab among the eligible ones. This is the
+ // default strategy.
+ LRU = 0,
+ // Discard the tab with the biggest resident set among the eligible ones.
+ BIGGEST_RSS = 1,
+};
+
+class UrgentDiscardingParams {
+ public:
+ ~UrgentDiscardingParams();
+
+ static UrgentDiscardingParams GetParams();
+
+ DiscardStrategy discard_strategy() const { return discard_strategy_; }
+
+ static constexpr base::FeatureParam<int> kDiscardStrategy{
+ &features::kUrgentDiscardingFromPerformanceManager, "DiscardStrategy",
+ static_cast<int>(DiscardStrategy::LRU)};
+
+ private:
+ UrgentDiscardingParams();
+ UrgentDiscardingParams(const UrgentDiscardingParams& rhs);
+
+ DiscardStrategy discard_strategy_;
+};
+
+// Feature that controls whether or not tabs should be automatically discarded
+// when the total PMF is too high.
+extern const base::Feature kHighPMFDiscardPolicy;
+
+// Enable background tab loading of pages (restored via session restore)
+// directly from Performance Manager rather than via TabLoader.
+extern const base::Feature kBackgroundTabLoadingFromPerformanceManager;
+#endif
+
} // namespace features
} // namespace performance_manager
diff --git a/chromium/components/performance_manager/public/graph/frame_node.h b/chromium/components/performance_manager/public/graph/frame_node.h
index 89532573389..1d60dbf0a13 100644
--- a/chromium/components/performance_manager/public/graph/frame_node.h
+++ b/chromium/components/performance_manager/public/graph/frame_node.h
@@ -8,12 +8,12 @@
#include "base/callback_forward.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/types/strong_alias.h"
#include "components/performance_manager/public/execution_context_priority/execution_context_priority.h"
#include "components/performance_manager/public/graph/node.h"
#include "components/performance_manager/public/mojom/coordination_unit.mojom.h"
#include "components/performance_manager/public/mojom/lifecycle.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "ui/gfx/geometry/rect.h"
@@ -130,6 +130,18 @@ class FrameNode : public Node {
// lifetime of the frame.
virtual const base::flat_set<const PageNode*> GetOpenedPageNodes() const = 0;
+ // Visits the page nodes that have been embedded by this frame. The iteration
+ // is halted if the visitor returns false. Returns true if every call to the
+ // visitor returned true, false otherwise.
+ virtual bool VisitEmbeddedPageNodes(const PageNodeVisitor& visitor) const = 0;
+
+ // Returns the set of embedded pages associatted with this frame. Note that
+ // this incurs a full container copy all the embedded nodes. Please use
+ // VisitEmbeddedPageNodes when that makes sense. This can change over the
+ // lifetime of the frame.
+ virtual const base::flat_set<const PageNode*> GetEmbeddedPageNodes()
+ const = 0;
+
// Returns the current lifecycle state of this frame. See
// FrameNodeObserver::OnFrameLifecycleStateChanged.
virtual LifecycleState GetLifecycleState() const = 0;
@@ -192,7 +204,7 @@ class FrameNode : public Node {
// Returns the intersection of this frame with the viewport. This is initially
// null on node creation and is initialized during layout when the viewport
// intersection is first calculated. May only be called for a child frame.
- virtual const base::Optional<gfx::Rect>& GetViewportIntersection() const = 0;
+ virtual const absl::optional<gfx::Rect>& GetViewportIntersection() const = 0;
// Returns true if the frame is visible. This value is based on the viewport
// intersection of the frame, and the visibility of the page.
diff --git a/chromium/components/performance_manager/public/graph/node_data_describer_registry.h b/chromium/components/performance_manager/public/graph/node_data_describer_registry.h
index 2bd142fcb4c..2ee055db01a 100644
--- a/chromium/components/performance_manager/public/graph/node_data_describer_registry.h
+++ b/chromium/components/performance_manager/public/graph/node_data_describer_registry.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_DATA_DESCRIBER_REGISTRY_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_DATA_DESCRIBER_REGISTRY_H_
-#include <map>
-
#include "base/strings/string_piece.h"
#include "base/values.h"
diff --git a/chromium/components/performance_manager/public/graph/page_node.h b/chromium/components/performance_manager/public/graph/page_node.h
index 2f0672a7543..cc3aab4e0cc 100644
--- a/chromium/components/performance_manager/public/graph/page_node.h
+++ b/chromium/components/performance_manager/public/graph/page_node.h
@@ -11,13 +11,13 @@
#include "base/callback_forward.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/performance_manager/public/freezing/freezing.h"
#include "components/performance_manager/public/graph/node.h"
#include "components/performance_manager/public/mojom/coordination_unit.mojom.h"
#include "components/performance_manager/public/mojom/lifecycle.mojom.h"
#include "components/performance_manager/public/web_contents_proxy.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -36,12 +36,10 @@ class PageNode : public Node {
using Observer = PageNodeObserver;
class ObserverDefaultImpl;
- // Reasons for which a frame can become the opener of a page.
- enum class OpenedType {
- // Returned if this node doesn't have an opener.
+ // Reasons for which a frame can become the embedder of a page.
+ enum class EmbeddingType {
+ // Returned if this node doesn't have an embedder.
kInvalid,
- // This page is a popup (the opener created it via window.open).
- kPopup,
// This page is a guest view. This can be many things (<webview>, <appview>,
// etc) but is backed by the same inner/outer WebContents mechanism.
kGuestView,
@@ -49,8 +47,8 @@ class PageNode : public Node {
kPortal,
};
- // Returns a string for a PageNode::OpenedType enumeration.
- static const char* ToString(PageNode::OpenedType opened_type);
+ // Returns a string for a PageNode::EmbeddingType enumeration.
+ static const char* ToString(PageNode::EmbeddingType embedding_type);
// Loading state of a page.
enum class LoadingState {
@@ -86,9 +84,13 @@ class PageNode : public Node {
// lifetime of this page. See "OnOpenerFrameNodeChanged".
virtual const FrameNode* GetOpenerFrameNode() const = 0;
- // Returns the type of relationship this node has with its opener, if it has
- // an opener.
- virtual OpenedType GetOpenedType() const = 0;
+ // Returns the embedder frame node, if there is one. This may change over the
+ // lifetime of this page. See "OnEmbedderFrameNodeChanged".
+ virtual const FrameNode* GetEmbedderFrameNode() const = 0;
+
+ // Returns the type of relationship this node has with its embedder, if it has
+ // an embedder.
+ virtual EmbeddingType GetEmbeddingType() const = 0;
// Returns true if this page is currently visible, false otherwise.
// See PageNodeObserver::OnIsVisibleChanged.
@@ -169,12 +171,12 @@ class PageNode : public Node {
// Indicates if there's a freezing vote for this page node. This has 3
// possible values:
- // - base::nullopt: There's no active freezing vote for this page.
+ // - absl::nullopt: There's no active freezing vote for this page.
// - freezing::FreezingVoteValue::kCanFreeze: There's one or more positive
// freezing vote for this page and no negative vote.
// - freezing::FreezingVoteValue::kCannotFreeze: There's at least one
// negative freezing vote for this page.
- virtual const base::Optional<freezing::FreezingVote>& GetFreezingVote()
+ virtual const absl::optional<freezing::FreezingVote>& GetFreezingVote()
const = 0;
private:
@@ -185,7 +187,7 @@ class PageNode : public Node {
// implement the entire interface.
class PageNodeObserver {
public:
- using OpenedType = PageNode::OpenedType;
+ using EmbeddingType = PageNode::EmbeddingType;
PageNodeObserver();
virtual ~PageNodeObserver();
@@ -204,13 +206,21 @@ class PageNodeObserver {
// Notifications of property changes.
- // Invoked when this page has been assigned an opener, had the opener change,
- // or had the opener removed. This can happen if a page is opened via
- // window.open, webviews, portals, etc, or when that relationship is
- // subsequently severed or reparented.
+ // Invoked when this page has been assigned an opener, had the opener
+ // change, or had the opener removed. This happens when a page is opened
+ // via window.open, or when that relationship is subsequently severed or
+ // reparented.
virtual void OnOpenerFrameNodeChanged(const PageNode* page_node,
- const FrameNode* previous_opener,
- OpenedType previous_opened_type) = 0;
+ const FrameNode* previous_opener) = 0;
+
+ // Invoked when this page has been assigned an embedder, had the embedder
+ // change, or had the embedder removed. This can happen if a page is opened
+ // via webviews, guestviews, portals, etc, or when that relationship is
+ // subsequently severed or reparented.
+ virtual void OnEmbedderFrameNodeChanged(
+ const PageNode* page_node,
+ const FrameNode* previous_embedder,
+ EmbeddingType previous_embedder_type) = 0;
// Invoked when the IsVisible property changes.
virtual void OnIsVisibleChanged(const PageNode* page_node) = 0;
@@ -258,7 +268,7 @@ class PageNodeObserver {
// Called every time the aggregated freezing vote changes or gets invalidated.
virtual void OnFreezingVoteChanged(
const PageNode* page_node,
- base::Optional<freezing::FreezingVote> previous_vote) = 0;
+ absl::optional<freezing::FreezingVote> previous_vote) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(PageNodeObserver);
@@ -276,8 +286,11 @@ class PageNode::ObserverDefaultImpl : public PageNodeObserver {
void OnPageNodeAdded(const PageNode* page_node) override {}
void OnBeforePageNodeRemoved(const PageNode* page_node) override {}
void OnOpenerFrameNodeChanged(const PageNode* page_node,
- const FrameNode* previous_opener,
- OpenedType previous_opened_type) override {}
+ const FrameNode* previous_opener) override {}
+ void OnEmbedderFrameNodeChanged(
+ const PageNode* page_node,
+ const FrameNode* previous_embedder,
+ EmbeddingType previous_embedding_type) override {}
void OnIsVisibleChanged(const PageNode* page_node) override {}
void OnIsAudibleChanged(const PageNode* page_node) override {}
void OnLoadingStateChanged(const PageNode* page_node) override {}
@@ -293,15 +306,16 @@ class PageNode::ObserverDefaultImpl : public PageNodeObserver {
void OnFaviconUpdated(const PageNode* page_node) override {}
void OnFreezingVoteChanged(
const PageNode* page_node,
- base::Optional<freezing::FreezingVote> previous_vote) override {}
+ absl::optional<freezing::FreezingVote> previous_vote) override {}
private:
DISALLOW_COPY_AND_ASSIGN(ObserverDefaultImpl);
};
-// std::ostream support for PageNode::OpenedType.
-std::ostream& operator<<(std::ostream& os,
- performance_manager::PageNode::OpenedType opened_type);
+// std::ostream support for PageNode::EmbeddingType.
+std::ostream& operator<<(
+ std::ostream& os,
+ performance_manager::PageNode::EmbeddingType embedding_type);
} // namespace performance_manager
diff --git a/chromium/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h b/chromium/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h
index 5c37649835c..e19fc1ac6f8 100644
--- a/chromium/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h
+++ b/chromium/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h
@@ -217,4 +217,4 @@ class TabLoadingFrameNavigationPolicy::MechanismDelegate {
} // namespace policies
} // namespace performance_manager
-#endif // COMPONENTS_PERFORMANCE_MANAGER_GRAPH_POLICIES_TAB_LOADING_FRAME_NAVIGATION_POLICY_H_
+#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_POLICIES_TAB_LOADING_FRAME_NAVIGATION_POLICY_H_
diff --git a/chromium/components/performance_manager/public/graph/process_node.h b/chromium/components/performance_manager/public/graph/process_node.h
index 66ab140fcd3..0f52add905d 100644
--- a/chromium/components/performance_manager/public/graph/process_node.h
+++ b/chromium/components/performance_manager/public/graph/process_node.h
@@ -69,7 +69,7 @@ class ProcessNode : public Node {
// Returns the exit status of this process. This will be empty if the process
// has not yet exited.
- virtual base::Optional<int32_t> GetExitStatus() const = 0;
+ virtual absl::optional<int32_t> GetExitStatus() const = 0;
// Visits the frame nodes that are hosted in this process. The iteration is
// halted if the visitor returns false. Returns true if every call to the
@@ -91,6 +91,10 @@ class ProcessNode : public Node {
// Returns the most recently measured private memory footprint of the process.
// This is roughly private, anonymous, non-discardable, resident or swapped
// memory in kilobytes. For more details, see https://goo.gl/3kPb9S.
+ //
+ // Note: This is only valid if at least one component has expressed interest
+ // for process memory metrics by calling
+ // ProcessMetricsDecorator::RegisterInterestForProcessMetrics.
virtual uint64_t GetPrivateFootprintKb() const = 0;
// Returns the most recently measured resident set of the process, in
diff --git a/chromium/components/performance_manager/public/graph/system_node.h b/chromium/components/performance_manager/public/graph/system_node.h
index 5b748b32cec..624401e027f 100644
--- a/chromium/components/performance_manager/public/graph/system_node.h
+++ b/chromium/components/performance_manager/public/graph/system_node.h
@@ -49,6 +49,10 @@ class SystemNodeObserver {
virtual void OnBeforeSystemNodeRemoved(const SystemNode* system_node) = 0;
// Called when a new set of process memory metrics is available.
+ //
+ // Note: This is only valid if at least one component has expressed interest
+ // for process memory metrics by calling
+ // ProcessMetricsDecorator::RegisterInterestForProcessMetrics.
virtual void OnProcessMemoryMetricsAvailable(
const SystemNode* system_node) = 0;
diff --git a/chromium/components/performance_manager/public/mojom/web_memory.mojom b/chromium/components/performance_manager/public/mojom/web_memory.mojom
index a86176c353e..3652077ca09 100644
--- a/chromium/components/performance_manager/public/mojom/web_memory.mojom
+++ b/chromium/components/performance_manager/public/mojom/web_memory.mojom
@@ -30,9 +30,10 @@ struct WebMemoryAttribution {
// Specifies the scope (or type) of the context.
enum Scope {
kCrossOriginAggregated, // Dummy scope for cross-origin iframes.
- kDedicatedWorker,
kWindow,
- // TODO(1085129): Add worker scopes once they are implemented.
+ kDedicatedWorker,
+ kServiceWorker,
+ kSharedWorker
};
Scope scope;
// The current URL of the context. It is null for cross-origin contexts.
diff --git a/chromium/components/performance_manager/public/performance_manager_main_thread_mechanism.h b/chromium/components/performance_manager/public/performance_manager_main_thread_mechanism.h
index a139a1bbb47..11a2b229191 100644
--- a/chromium/components/performance_manager/public/performance_manager_main_thread_mechanism.h
+++ b/chromium/components/performance_manager/public/performance_manager_main_thread_mechanism.h
@@ -41,4 +41,4 @@ class PerformanceManagerMainThreadMechanism : public base::CheckedObserver {
} // namespace performance_manager
-#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_MAIN_THREAD_OBSERVER_H_
+#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_MAIN_THREAD_MECHANISM_H_
diff --git a/chromium/components/performance_manager/public/render_frame_host_proxy.h b/chromium/components/performance_manager/public/render_frame_host_proxy.h
index 30815c385a4..387fde065c0 100644
--- a/chromium/components/performance_manager/public/render_frame_host_proxy.h
+++ b/chromium/components/performance_manager/public/render_frame_host_proxy.h
@@ -18,7 +18,7 @@ class FrameNodeImpl;
// A RenderFrameHostProxy is used to post messages out of the performance
// manager sequence that are bound for a RenderFrameHostProxy running on the UI
// thread. The object is bound to the UI thread. A RenderFrameHostProxy is
-// conceptually equivalent to a WeakPtr<RenderProcessHost>. Copy and assignment
+// conceptually equivalent to a WeakPtr<RenderFrameHost>. Copy and assignment
// are explicitly allowed for this object.
class RenderFrameHostProxy {
public:
diff --git a/chromium/components/performance_manager/public/v8_memory/v8_detailed_memory.h b/chromium/components/performance_manager/public/v8_memory/v8_detailed_memory.h
index bd37a8002a4..58bef354f77 100644
--- a/chromium/components/performance_manager/public/v8_memory/v8_detailed_memory.h
+++ b/chromium/components/performance_manager/public/v8_memory/v8_detailed_memory.h
@@ -10,11 +10,11 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/types/pass_key.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace performance_manager {
@@ -152,9 +152,9 @@ class V8DetailedMemoryExecutionContextData {
// TODO(906991): Remove this once PlzDedicatedWorker ships. Until then
// the browser does not know URLs of dedicated workers, so we pass them
// together with the measurement result and store in ExecutionContext data.
- base::Optional<std::string> url() const { return url_; }
+ absl::optional<std::string> url() const { return url_; }
- void set_url(base::Optional<std::string> url) { url_ = std::move(url); }
+ void set_url(absl::optional<std::string> url) { url_ = std::move(url); }
// Returns frame data for the given node, or nullptr if no measurement has
// been taken. The returned pointer must only be accessed on the graph
@@ -175,7 +175,7 @@ class V8DetailedMemoryExecutionContextData {
const WorkerNode* node);
uint64_t v8_bytes_used_ = 0;
- base::Optional<std::string> url_;
+ absl::optional<std::string> url_;
};
class V8DetailedMemoryProcessData {
@@ -334,7 +334,7 @@ class V8DetailedMemoryRequest {
base::PassKey<V8DetailedMemoryRequestAnySeq>,
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode,
- base::Optional<base::WeakPtr<ProcessNode>> process_to_measure,
+ absl::optional<base::WeakPtr<ProcessNode>> process_to_measure,
base::WeakPtr<V8DetailedMemoryRequestAnySeq> off_sequence_request);
// Private constructor for V8DetailedMemoryRequestOneShot. Sets
@@ -358,7 +358,7 @@ class V8DetailedMemoryRequest {
private:
void StartMeasurementFromOffSequence(
- base::Optional<base::WeakPtr<ProcessNode>> process_to_measure,
+ absl::optional<base::WeakPtr<ProcessNode>> process_to_measure,
Graph* graph);
void StartMeasurementImpl(Graph* graph, const ProcessNode* process_node);
diff --git a/chromium/components/performance_manager/public/v8_memory/v8_detailed_memory_any_seq.h b/chromium/components/performance_manager/public/v8_memory/v8_detailed_memory_any_seq.h
index 47337172f8d..0244edae1bd 100644
--- a/chromium/components/performance_manager/public/v8_memory/v8_detailed_memory_any_seq.h
+++ b/chromium/components/performance_manager/public/v8_memory/v8_detailed_memory_any_seq.h
@@ -10,7 +10,6 @@
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/threading/sequence_bound.h"
#include "base/time/time.h"
@@ -18,6 +17,7 @@
#include "components/performance_manager/public/render_process_host_id.h"
#include "components/performance_manager/public/v8_memory/v8_detailed_memory.h"
#include "content/public/browser/global_routing_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace performance_manager {
@@ -153,7 +153,7 @@ class V8DetailedMemoryRequestAnySeq {
explicit V8DetailedMemoryRequestAnySeq(
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode = MeasurementMode::kDefault,
- base::Optional<RenderProcessHostId> process_to_measure = base::nullopt);
+ absl::optional<RenderProcessHostId> process_to_measure = absl::nullopt);
~V8DetailedMemoryRequestAnySeq();
V8DetailedMemoryRequestAnySeq(const V8DetailedMemoryRequestAnySeq&) = delete;
@@ -184,7 +184,7 @@ class V8DetailedMemoryRequestAnySeq {
void InitializeWrappedRequest(
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode,
- base::Optional<base::WeakPtr<ProcessNode>> process_to_measure);
+ absl::optional<base::WeakPtr<ProcessNode>> process_to_measure);
std::unique_ptr<V8DetailedMemoryRequest> request_
GUARDED_BY_CONTEXT(sequence_checker_);
diff --git a/chromium/components/performance_manager/test_support/voting.h b/chromium/components/performance_manager/test_support/voting.h
index 2059142c96a..db277413e6c 100644
--- a/chromium/components/performance_manager/test_support/voting.h
+++ b/chromium/components/performance_manager/test_support/voting.h
@@ -7,9 +7,6 @@
#include "components/performance_manager/public/voting/voting.h"
-#include <map>
-#include <vector>
-
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/performance_manager/v8_memory/v8_context_tracker.cc b/chromium/components/performance_manager/v8_memory/v8_context_tracker.cc
index 7e7afcb9b17..f15c50947bb 100644
--- a/chromium/components/performance_manager/v8_memory/v8_context_tracker.cc
+++ b/chromium/components/performance_manager/v8_memory/v8_context_tracker.cc
@@ -105,7 +105,7 @@ void V8ContextTracker::OnV8ContextCreated(
// Validate the |iframe_attribution_data|.
{
- base::Optional<bool> result =
+ absl::optional<bool> result =
ExpectIframeAttributionDataForV8ContextDescription(
description, process_node->graph());
if (result) {
@@ -507,14 +507,26 @@ void V8ContextTracker::OnRemoteIframeAttachedImpl(
raw_ec_data = ec_data.get();
}
- if (raw_ec_data->remote_frame_data() ||
- raw_ec_data->iframe_attribution_data) {
+ if (raw_ec_data->remote_frame_data()) {
std::move(bad_message_callback).Run("unexpected OnRemoteIframeAttached");
return;
}
- // Attach the iframe data to the ExecutionContextData.
- raw_ec_data->iframe_attribution_data = std::move(iframe_attribution_data);
+ // This used to assert that `raw_ec_data` had no `iframe_attribution_data`
+ // already attached. In general, the renderer should not send multiple updates
+ // for a given RenderFrameHost parent <-> RenderFrameProxyHost child pairing.
+ // However, when //content needs to undo a `CommitNavigation()` sent to a
+ // speculative RenderFrameHost, the renderer ends up swapping in a
+ // RenderFrameProxy with the same RemoteFrameToken back in. Allow it as an
+ // unfortunate exception--but ignore the update to retain the previous
+ // behavior. See https://crbug.com/1221955 for more background.
+ if (!raw_ec_data->iframe_attribution_data) {
+ // Attach the iframe data to the ExecutionContextData.
+ // If there was already iframe data, keep the original data, to be
+ // consistent with the behaviour of all other paths that ignore changes to
+ // the `src` and `id` attributes.
+ raw_ec_data->iframe_attribution_data = std::move(iframe_attribution_data);
+ }
// Create the RemoteFrameData reference to this context.
auto* parent_process_data =
diff --git a/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers.cc b/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers.cc
index 5406a7eed93..d9c7daa9bb7 100644
--- a/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers.cc
+++ b/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers.cc
@@ -162,7 +162,7 @@ V8ContextDescriptionStatus ValidateV8ContextDescription(
return V8ContextDescriptionStatus::kValid;
}
-base::Optional<bool> ExpectIframeAttributionDataForV8ContextDescription(
+absl::optional<bool> ExpectIframeAttributionDataForV8ContextDescription(
const mojom::V8ContextDescription& description,
Graph* graph) {
switch (description.world_type) {
@@ -176,7 +176,7 @@ base::Optional<bool> ExpectIframeAttributionDataForV8ContextDescription(
return IsSynchronousIframeAttributionDataExpected(ec);
} else {
// Unable to be determined.
- return base::nullopt;
+ return absl::nullopt;
}
} break;
diff --git a/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers.h b/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers.h
index 60d25a1d2c3..cab1e8915be 100644
--- a/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers.h
+++ b/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/compiler_specific.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/tokens/tokens.h"
namespace performance_manager {
@@ -78,9 +78,9 @@ V8ContextDescriptionStatus ValidateV8ContextDescription(
// Determines whether or not IframeAttributionData is expected to accompany the
// provided V8ContextDescription. This is not always able to be determined, in
-// which case base::nullopt will be returned. It is assumed that the
+// which case absl::nullopt will be returned. It is assumed that the
// |description| has previously been validated.
-base::Optional<bool> ExpectIframeAttributionDataForV8ContextDescription(
+absl::optional<bool> ExpectIframeAttributionDataForV8ContextDescription(
const mojom::V8ContextDescription& description,
Graph* graph) WARN_UNUSED_RESULT;
diff --git a/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers_unittest.cc b/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers_unittest.cc
index 429ffd11824..98c75bbbee9 100644
--- a/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers_unittest.cc
+++ b/chromium/components/performance_manager/v8_memory/v8_context_tracker_helpers_unittest.cc
@@ -109,7 +109,7 @@ TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionMainWorld) {
// A valid description of a main frame.
auto desc = mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt, mock_graph.frame->frame_token());
+ /* world_name */ absl::nullopt, mock_graph.frame->frame_token());
EXPECT_EQ(V8ContextDescriptionStatus::kValid,
ValidateV8ContextDescription(desc));
EXPECT_EQ(false,
@@ -118,7 +118,7 @@ TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionMainWorld) {
// A valid description of a cross-process child frame.
desc = mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt, mock_graph.child_frame->frame_token());
+ /* world_name */ absl::nullopt, mock_graph.child_frame->frame_token());
EXPECT_EQ(V8ContextDescriptionStatus::kValid,
ValidateV8ContextDescription(desc));
EXPECT_EQ(false,
@@ -127,7 +127,7 @@ TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionMainWorld) {
// A valid description of a same-process child frame.
desc = mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt, child_frame->frame_token());
+ /* world_name */ absl::nullopt, child_frame->frame_token());
EXPECT_EQ(V8ContextDescriptionStatus::kValid,
ValidateV8ContextDescription(desc));
EXPECT_EQ(true,
@@ -138,8 +138,8 @@ TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionMainWorld) {
// IframeAttributionData should accompany the V8ContextDescription.
desc = mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt, blink::LocalFrameToken());
- EXPECT_EQ(base::nullopt,
+ /* world_name */ absl::nullopt, blink::LocalFrameToken());
+ EXPECT_EQ(absl::nullopt,
ExpectIframeAttributionDataForV8ContextDescription(desc, graph()));
// A main-world should not have a world name.
@@ -152,15 +152,15 @@ TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionMainWorld) {
EXPECT_EQ(V8ContextDescriptionStatus::kMissingExecutionContextToken,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
- /* execution_context_token */ base::nullopt)));
+ /* world_name */ absl::nullopt,
+ /* execution_context_token */ absl::nullopt)));
// A main world must have an blink::LocalFrameToken.
blink::ExecutionContextToken worker_token((blink::SharedWorkerToken()));
EXPECT_EQ(V8ContextDescriptionStatus::kMissingLocalFrameToken,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt, worker_token)));
+ /* world_name */ absl::nullopt, worker_token)));
}
TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionWorkerWorld) {
@@ -172,7 +172,7 @@ TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionWorkerWorld) {
// A valid worker description.
auto desc = mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kWorkerOrWorklet,
- /* world_name */ base::nullopt, worker_token);
+ /* world_name */ absl::nullopt, worker_token);
EXPECT_EQ(V8ContextDescriptionStatus::kValid,
ValidateV8ContextDescription(desc));
EXPECT_EQ(false,
@@ -190,15 +190,15 @@ TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionWorkerWorld) {
V8ContextDescriptionStatus::kMissingExecutionContextToken,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kWorkerOrWorklet,
- /* world_name */ base::nullopt,
- /* execution_context_token */ base::nullopt)));
+ /* world_name */ absl::nullopt,
+ /* execution_context_token */ absl::nullopt)));
// A worker must have a valid worker token, not a LocalFrameToken.
EXPECT_EQ(
V8ContextDescriptionStatus::kUnexpectedLocalFrameToken,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kWorkerOrWorklet,
- /* world_name */ base::nullopt, blink::LocalFrameToken())));
+ /* world_name */ absl::nullopt, blink::LocalFrameToken())));
}
TEST_F(V8ContextTrackerHelpersTest,
@@ -217,7 +217,7 @@ TEST_F(V8ContextTrackerHelpersTest,
V8ContextDescriptionStatus::kMissingWorldName,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kExtension,
- /* world_name */ base::nullopt, mock_graph.frame->frame_token())));
+ /* world_name */ absl::nullopt, mock_graph.frame->frame_token())));
// An invalid extension name should fail.
EXPECT_EQ(V8ContextDescriptionStatus::kInvalidExtensionWorldName,
@@ -230,7 +230,7 @@ TEST_F(V8ContextTrackerHelpersTest,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kExtension,
kValidExtensionWorldName,
- /* execution_context_token */ base::nullopt)));
+ /* execution_context_token */ absl::nullopt)));
// An extension can't inject into a worklet.
EXPECT_EQ(V8ContextDescriptionStatus::kUnexpectedWorkletToken,
@@ -243,7 +243,7 @@ TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionIsolatedWorld) {
// An isolated world may or may not have a |world_name|.
auto desc = mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kIsolated,
- /* world_name */ base::nullopt, mock_graph.frame->frame_token());
+ /* world_name */ absl::nullopt, mock_graph.frame->frame_token());
EXPECT_EQ(V8ContextDescriptionStatus::kValid,
ValidateV8ContextDescription(desc));
EXPECT_EQ(false,
@@ -261,14 +261,14 @@ TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionIsolatedWorld) {
EXPECT_EQ(V8ContextDescriptionStatus::kMissingExecutionContextToken,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kIsolated,
- /* world_name */ base::nullopt,
- /* execution_context_token */ base::nullopt)));
+ /* world_name */ absl::nullopt,
+ /* execution_context_token */ absl::nullopt)));
// An isolated world can not inject into a worklet.
EXPECT_EQ(V8ContextDescriptionStatus::kUnexpectedWorkletToken,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kIsolated,
- /* world_name */ base::nullopt, blink::AudioWorkletToken())));
+ /* world_name */ absl::nullopt, blink::AudioWorkletToken())));
}
TEST_F(V8ContextTrackerHelpersTest,
@@ -276,7 +276,7 @@ TEST_F(V8ContextTrackerHelpersTest,
// A valid inspector world.
auto desc = mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kInspector,
- /* world_name */ base::nullopt, mock_graph.frame->frame_token());
+ /* world_name */ absl::nullopt, mock_graph.frame->frame_token());
EXPECT_EQ(V8ContextDescriptionStatus::kValid,
ValidateV8ContextDescription(desc));
EXPECT_EQ(false,
@@ -286,22 +286,22 @@ TEST_F(V8ContextTrackerHelpersTest,
EXPECT_EQ(V8ContextDescriptionStatus::kMissingExecutionContextToken,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kInspector,
- /* world_name */ base::nullopt,
- /* execution_context_token */ base::nullopt)));
+ /* world_name */ absl::nullopt,
+ /* execution_context_token */ absl::nullopt)));
// An inspector world can not inject into a worklet.
EXPECT_EQ(V8ContextDescriptionStatus::kUnexpectedWorkletToken,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kInspector,
- /* world_name */ base::nullopt, blink::AudioWorkletToken())));
+ /* world_name */ absl::nullopt, blink::AudioWorkletToken())));
}
TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionRegExpWorld) {
// A valid regexp world.
auto desc = mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kRegExp,
- /* world_name */ base::nullopt,
- /* execution_context_token */ base::nullopt);
+ /* world_name */ absl::nullopt,
+ /* execution_context_token */ absl::nullopt);
EXPECT_EQ(V8ContextDescriptionStatus::kValid,
ValidateV8ContextDescription(desc));
EXPECT_EQ(false,
@@ -312,14 +312,14 @@ TEST_F(V8ContextTrackerHelpersTest, ValidateV8ContextDescriptionRegExpWorld) {
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kRegExp,
kWorldName,
- /* execution_context_token */ base::nullopt)));
+ /* execution_context_token */ absl::nullopt)));
// A regexp world must not have an |execution_context_token|.
EXPECT_EQ(
V8ContextDescriptionStatus::kUnexpectedExecutionContextToken,
ValidateV8ContextDescription(mojom::V8ContextDescription(
blink::V8ContextToken(), mojom::V8ContextWorldType::kRegExp,
- /* world_name */ base::nullopt, mock_graph.frame->frame_token())));
+ /* world_name */ absl::nullopt, mock_graph.frame->frame_token())));
}
} // namespace v8_memory
diff --git a/chromium/components/performance_manager/v8_memory/v8_context_tracker_unittest.cc b/chromium/components/performance_manager/v8_memory/v8_context_tracker_unittest.cc
index 7b681439eb0..bfcfb8a3169 100644
--- a/chromium/components/performance_manager/v8_memory/v8_context_tracker_unittest.cc
+++ b/chromium/components/performance_manager/v8_memory/v8_context_tracker_unittest.cc
@@ -8,7 +8,6 @@
#include <string>
#include <utility>
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/test/gtest_util.h"
#include "components/performance_manager/execution_context/execution_context_registry_impl.h"
@@ -20,6 +19,7 @@
#include "components/performance_manager/test_support/mock_graphs.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/tokens/tokens.h"
namespace performance_manager {
@@ -97,8 +97,8 @@ TEST_F(V8ContextTrackerDeathTest, MissingExecutionContextForMainFrameExplodes) {
mojom::V8ContextDescription(
/* token */ kFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
- /* execution_context_token */ base::nullopt),
+ /* world_name */ absl::nullopt,
+ /* execution_context_token */ absl::nullopt),
/* iframe_attribution_data */ nullptr));
}
@@ -106,7 +106,7 @@ TEST_F(V8ContextTrackerDeathTest, DoubleCreationExplodes) {
auto v8_desc = mojom::V8ContextDescription(
/* token */ kFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */ mock_graph.frame->frame_token());
tracker->OnV8ContextCreated(ProcessNodeImpl::CreatePassKeyForTesting(),
@@ -153,7 +153,7 @@ TEST_F(V8ContextTrackerDeathTest, IframeAttributionDataForMainFrameExplodes) {
mojom::V8ContextDescription(
/* token */ kFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */ mock_graph.frame->frame_token()),
GetFakeIframeAttributionDataPtr()));
}
@@ -171,7 +171,7 @@ TEST_F(V8ContextTrackerDeathTest,
mojom::V8ContextDescription(
/* token */ kChildFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */ child2_frame->frame_token()),
/* iframe_attribution_data */ nullptr));
}
@@ -183,7 +183,7 @@ TEST_F(V8ContextTrackerDeathTest, MultipleMainContextsForExecutionContext) {
mojom::V8ContextDescription(
/* token */ kFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */ mock_graph.frame->frame_token()),
/* iframe_attribution_data */ nullptr);
@@ -192,7 +192,7 @@ TEST_F(V8ContextTrackerDeathTest, MultipleMainContextsForExecutionContext) {
mojom::V8ContextDescription(
/* token */ blink::V8ContextToken(),
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */ mock_graph.frame->frame_token()),
/* iframe_attribution_data */ nullptr));
}
@@ -206,7 +206,7 @@ TEST_F(V8ContextTrackerTest, NormalV8ContextLifecycleWithExecutionContext) {
mojom::V8ContextDescription(
/* token */ kFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */ mock_graph.frame->frame_token()),
/* iframe_attribution_data */ nullptr);
EXPECT_THAT(tracker, CountsMatch(1, 1));
@@ -232,8 +232,8 @@ TEST_F(V8ContextTrackerTest, NormalV8ContextLifecycleNoExecutionContext) {
mojom::V8ContextDescription(
/* token */ kFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kRegExp,
- /* world_name */ base::nullopt,
- /* execution_context_token */ base::nullopt),
+ /* world_name */ absl::nullopt,
+ /* execution_context_token */ absl::nullopt),
/* iframe_attribution_data */ nullptr);
EXPECT_THAT(tracker, CountsMatch(1, 0));
EXPECT_THAT(tracker, DetachedCountsMatch(0, 0));
@@ -261,7 +261,7 @@ TEST_F(V8ContextTrackerTest, MultipleV8ContextsForExecutionContext) {
mojom::V8ContextDescription(
/* token */ kFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */ mock_graph.frame->frame_token()),
/* iframe_attribution_data */ nullptr);
EXPECT_THAT(tracker, CountsMatch(1, 1));
@@ -291,7 +291,7 @@ TEST_F(V8ContextTrackerTest, MultipleV8ContextsForExecutionContext) {
mojom::V8ContextDescription(
/* token */ kChildFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */
mock_graph.child_frame->frame_token()),
/* iframe_attribution_data */ nullptr);
@@ -410,7 +410,7 @@ TEST_F(V8ContextTrackerTest, AllEventOrders) {
mojom::V8ContextDescription(
/* token */ kFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */ mock_graph.frame->frame_token()),
/* iframe_attribution_data */ nullptr);
EXPECT_THAT(tracker, CountsMatch(1, 1));
@@ -428,7 +428,7 @@ TEST_F(V8ContextTrackerTest, AllEventOrders) {
mojom::V8ContextDescription(
/* token */ kChildFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */
self->mock_graph.child_frame->frame_token()),
/* iframe_attribution_data */ nullptr);
@@ -678,7 +678,7 @@ TEST_F(V8ContextTrackerTest, PublicApi) {
mojom::V8ContextDescription(
/* token */ kFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */ mock_graph.frame->frame_token()),
/* iframe_attribution_data */ nullptr);
EXPECT_THAT(tracker, CountsMatch(1, 1));
@@ -710,7 +710,7 @@ TEST_F(V8ContextTrackerTest, PublicApi) {
mojom::V8ContextDescription(
/* token */ kChildFrameMainWorld,
/* world_type */ mojom::V8ContextWorldType::kMain,
- /* world_name */ base::nullopt,
+ /* world_name */ absl::nullopt,
/* execution_context_token */
mock_graph.child_frame->frame_token()),
/* iframe_attribution_data */ nullptr);
diff --git a/chromium/components/performance_manager/v8_memory/v8_detailed_memory.cc b/chromium/components/performance_manager/v8_memory/v8_detailed_memory.cc
index f46af3d41b3..4a3de9df89f 100644
--- a/chromium/components/performance_manager/v8_memory/v8_detailed_memory.cc
+++ b/chromium/components/performance_manager/v8_memory/v8_detailed_memory.cc
@@ -83,7 +83,7 @@ V8DetailedMemoryRequest::V8DetailedMemoryRequest(
base::PassKey<V8DetailedMemoryRequestAnySeq>,
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode,
- base::Optional<base::WeakPtr<ProcessNode>> process_to_measure,
+ absl::optional<base::WeakPtr<ProcessNode>> process_to_measure,
base::WeakPtr<V8DetailedMemoryRequestAnySeq> off_sequence_request)
: V8DetailedMemoryRequest(min_time_between_requests, mode) {
DETACH_FROM_SEQUENCE(sequence_checker_);
@@ -196,7 +196,7 @@ void V8DetailedMemoryRequest::NotifyObserversOnMeasurementAvailable(
}
void V8DetailedMemoryRequest::StartMeasurementFromOffSequence(
- base::Optional<base::WeakPtr<ProcessNode>> process_to_measure,
+ absl::optional<base::WeakPtr<ProcessNode>> process_to_measure,
Graph* graph) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!process_to_measure) {
diff --git a/chromium/components/performance_manager/v8_memory/v8_detailed_memory_any_seq.cc b/chromium/components/performance_manager/v8_memory/v8_detailed_memory_any_seq.cc
index 659ce325186..f93c2bf0e1c 100644
--- a/chromium/components/performance_manager/v8_memory/v8_detailed_memory_any_seq.cc
+++ b/chromium/components/performance_manager/v8_memory/v8_detailed_memory_any_seq.cc
@@ -29,8 +29,8 @@ namespace v8_memory {
V8DetailedMemoryRequestAnySeq::V8DetailedMemoryRequestAnySeq(
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode,
- base::Optional<RenderProcessHostId> process_to_measure) {
- base::Optional<base::WeakPtr<ProcessNode>> process_node;
+ absl::optional<RenderProcessHostId> process_to_measure) {
+ absl::optional<base::WeakPtr<ProcessNode>> process_node;
if (process_to_measure) {
// GetProcessNodeForRenderProcessHostId must be called from the UI thread.
auto ui_task_runner = content::GetUIThreadTaskRunner({});
@@ -95,7 +95,7 @@ void V8DetailedMemoryRequestAnySeq::NotifyObserversOnMeasurementAvailable(
void V8DetailedMemoryRequestAnySeq::InitializeWrappedRequest(
const base::TimeDelta& min_time_between_requests,
MeasurementMode mode,
- base::Optional<base::WeakPtr<ProcessNode>> process_to_measure) {
+ absl::optional<base::WeakPtr<ProcessNode>> process_to_measure) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Can't use make_unique since this calls the private any-sequence
// constructor. After construction the V8DetailedMemoryRequest must only be
diff --git a/chromium/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc b/chromium/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc
index 1e19d7dd8d2..abe7b8fd7bd 100644
--- a/chromium/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc
+++ b/chromium/components/performance_manager/v8_memory/v8_detailed_memory_unittest.cc
@@ -20,7 +20,10 @@
#include "base/test/bind.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/gtest_util.h"
+#include "base/test/test_timeouts.h"
#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "build/build_config.h"
#include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/graph/page_node_impl.h"
#include "components/performance_manager/graph/process_node_impl.h"
@@ -1343,7 +1346,13 @@ TEST_F(V8DetailedMemoryDecoratorTest, ObserverOutlivesDecorator) {
memory_request.RemoveObserver(&observer);
}
-TEST_F(V8DetailedMemoryDecoratorTest, SingleProcessRequest) {
+// TODO(crbug.com/1203439) Sometimes timing out on Windows.
+#if defined(OS_WIN)
+#define MAYBE_SingleProcessRequest DISABLED_SingleProcessRequest
+#else
+#define MAYBE_SingleProcessRequest SingleProcessRequest
+#endif
+TEST_F(V8DetailedMemoryDecoratorTest, MAYBE_SingleProcessRequest) {
// Create 2 renderer processes. Create one request that measures both of
// them, and one request that measures only one.
constexpr RenderProcessHostId kProcessId1 = RenderProcessHostId(0xFAB);
@@ -1747,6 +1756,13 @@ TEST_F(V8DetailedMemoryRequestAnySeqTest, SingleProcessRequest) {
expected_process_data1, _))
.WillOnce(base::test::RunClosure(barrier));
+ // If all measurements don't arrive in a reasonable period, cancel the
+ // run loop. This ensures the test will fail with errors from the unfulfilled
+ // EXPECT_CALL statements, as expected, instead of timing out.
+ base::OneShotTimer timeout;
+ timeout.Start(FROM_HERE, TestTimeouts::action_timeout(),
+ run_loop.QuitClosure());
+
// Now execute all the above tasks.
run_loop.Run();
Mock::VerifyAndClearExpectations(&mock_reporter1);
diff --git a/chromium/components/performance_manager/v8_memory/v8_memory_test_helpers.cc b/chromium/components/performance_manager/v8_memory/v8_memory_test_helpers.cc
index 1ce5753c4c2..a9e7b85868f 100644
--- a/chromium/components/performance_manager/v8_memory/v8_memory_test_helpers.cc
+++ b/chromium/components/performance_manager/v8_memory/v8_memory_test_helpers.cc
@@ -241,20 +241,20 @@ int WebMemoryTestHarness::GetNextUniqueId() {
}
FrameNodeImpl* WebMemoryTestHarness::AddFrameNodeImpl(
- base::Optional<std::string> url,
+ absl::optional<std::string> url,
int browsing_instance_id,
Bytes memory_usage,
FrameNodeImpl* parent,
FrameNodeImpl* opener,
ProcessNodeImpl* process,
- base::Optional<std::string> id_attribute,
- base::Optional<std::string> src_attribute) {
+ absl::optional<std::string> id_attribute,
+ absl::optional<std::string> src_attribute) {
// If there's an opener, the new frame is also a new page.
auto* page = pages_.front().get();
if (opener) {
pages_.push_back(CreateNode<PageNodeImpl>());
page = pages_.back().get();
- page->SetOpenerFrameNodeAndOpenedType(opener, PageNode::OpenedType::kPopup);
+ page->SetOpenerFrameNode(opener);
}
int frame_tree_node_id = GetNextUniqueId();
diff --git a/chromium/components/performance_manager/v8_memory/v8_memory_test_helpers.h b/chromium/components/performance_manager/v8_memory/v8_memory_test_helpers.h
index 1a967c17d15..a38b7af18c0 100644
--- a/chromium/components/performance_manager/v8_memory/v8_memory_test_helpers.h
+++ b/chromium/components/performance_manager/v8_memory/v8_memory_test_helpers.h
@@ -13,7 +13,6 @@
#include "base/callback_forward.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "components/performance_manager/public/render_process_host_id.h"
@@ -24,6 +23,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/performance_manager/v8_detailed_memory_reporter.mojom.h"
@@ -226,7 +226,7 @@ class WebMemoryTestHarness : public GraphTestHarness {
using Super = GraphTestHarness;
// Wrapper for memory usage bytes to improve test readability.
- using Bytes = base::Optional<uint64_t>;
+ using Bytes = absl::optional<uint64_t>;
WebMemoryTestHarness();
~WebMemoryTestHarness() override;
@@ -238,21 +238,21 @@ class WebMemoryTestHarness : public GraphTestHarness {
std::string url,
Bytes bytes,
FrameNodeImpl* parent = nullptr,
- base::Optional<std::string> id_attribute = base::nullopt,
- base::Optional<std::string> src_attribute = base::nullopt) {
+ absl::optional<std::string> id_attribute = absl::nullopt,
+ absl::optional<std::string> src_attribute = absl::nullopt) {
return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId, bytes, parent,
/*opener=*/nullptr, process_.get(), id_attribute,
src_attribute);
}
// Creates a frame node as if from window.open and adds it to the graph.
- FrameNodeImpl* AddFrameNodeFromOpener(base::Optional<std::string> url,
+ FrameNodeImpl* AddFrameNodeFromOpener(absl::optional<std::string> url,
Bytes bytes,
FrameNodeImpl* opener) {
return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId, bytes,
/*parent=*/nullptr, opener, process_.get(),
- /*id_attribute=*/base::nullopt,
- /*src_attribute=*/base::nullopt);
+ /*id_attribute=*/absl::nullopt,
+ /*src_attribute=*/absl::nullopt);
}
// Creates a frame node in a different browsing instance and adds it to the
@@ -261,8 +261,8 @@ class WebMemoryTestHarness : public GraphTestHarness {
std::string url,
Bytes bytes,
FrameNodeImpl* parent = nullptr,
- base::Optional<std::string> id_attribute = base::nullopt,
- base::Optional<std::string> src_attribute = base::nullopt) {
+ absl::optional<std::string> id_attribute = absl::nullopt,
+ absl::optional<std::string> src_attribute = absl::nullopt) {
return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId + 1, bytes, parent,
/*opener=*/nullptr, process_.get(), id_attribute,
src_attribute);
@@ -276,8 +276,8 @@ class WebMemoryTestHarness : public GraphTestHarness {
FrameNodeImpl* opener) {
return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId + 1, bytes,
/*parent=*/nullptr, opener, process_.get(),
- /*id_attribute=*/base::nullopt,
- /*src_attribute=*/base::nullopt);
+ /*id_attribute=*/absl::nullopt,
+ /*src_attribute=*/absl::nullopt);
}
// Creates a frame node in a different process and adds it to the graph.
@@ -285,8 +285,8 @@ class WebMemoryTestHarness : public GraphTestHarness {
std::string url,
Bytes bytes,
FrameNodeImpl* parent,
- base::Optional<std::string> id_attribute = base::nullopt,
- base::Optional<std::string> src_attribute = base::nullopt) {
+ absl::optional<std::string> id_attribute = absl::nullopt,
+ absl::optional<std::string> src_attribute = absl::nullopt) {
return AddFrameNodeImpl(url, kDefaultBrowsingInstanceId, bytes, parent,
/*opener=*/nullptr, other_process_.get(),
id_attribute, src_attribute);
@@ -313,14 +313,14 @@ class WebMemoryTestHarness : public GraphTestHarness {
static constexpr int kDefaultBrowsingInstanceId = 0;
// Creates and adds a new frame node to the graph.
- FrameNodeImpl* AddFrameNodeImpl(base::Optional<std::string> url,
+ FrameNodeImpl* AddFrameNodeImpl(absl::optional<std::string> url,
int browsing_instance_id,
Bytes bytes,
FrameNodeImpl* parent,
FrameNodeImpl* opener,
ProcessNodeImpl* process,
- base::Optional<std::string> id_attribute,
- base::Optional<std::string> src_attribute);
+ absl::optional<std::string> id_attribute,
+ absl::optional<std::string> src_attribute);
WorkerNodeImpl* AddWorkerNodeImpl(WorkerNode::WorkerType worker_type,
std::string url,
Bytes bytes);
diff --git a/chromium/components/performance_manager/v8_memory/web_memory_aggregator.cc b/chromium/components/performance_manager/v8_memory/web_memory_aggregator.cc
index 665ef993f8b..522c9fa205f 100644
--- a/chromium/components/performance_manager/v8_memory/web_memory_aggregator.cc
+++ b/chromium/components/performance_manager/v8_memory/web_memory_aggregator.cc
@@ -290,7 +290,7 @@ void AggregationPointVisitor::OnFrameEntered(const FrameNode* frame_node) {
// Since this node is NOT same-origin to the start node, the start node
// CANNOT view its current url.
aggregation_point = WebMemoryAggregator::CreateBreakdownEntry(
- AttributionScope::kCrossOriginAggregated, base::nullopt,
+ AttributionScope::kCrossOriginAggregated, absl::nullopt,
aggregation_result_.get());
// This is cross-origin but not being aggregated into another
// aggregation point, so its parent or opener must be same-origin to the
@@ -425,7 +425,7 @@ double GetBrowsingInstanceV8BytesFraction(const ProcessNode* process_node,
uint64_t bytes_used = 0;
uint64_t total_bytes_used = 0;
process_node->VisitFrameNodes(base::BindRepeating(
- [](base::Optional<int32_t> browsing_instance_id, uint64_t* bytes_used,
+ [](absl::optional<int32_t> browsing_instance_id, uint64_t* bytes_used,
uint64_t* total_bytes_used, const FrameNode* frame_node) {
const auto* data =
V8DetailedMemoryExecutionContextData::ForFrameNode(frame_node);
@@ -438,7 +438,10 @@ double GetBrowsingInstanceV8BytesFraction(const ProcessNode* process_node,
return true;
},
browsing_instance_id, &bytes_used, &total_bytes_used));
- return static_cast<double>(bytes_used) / total_bytes_used;
+ DCHECK_LE(bytes_used, total_bytes_used);
+ return total_bytes_used == 0
+ ? 1
+ : static_cast<double>(bytes_used) / total_bytes_used;
}
} // anonymous namespace
@@ -537,7 +540,7 @@ bool WebMemoryAggregator::VisitWorker(AggregationPointVisitor* ap_visitor,
// static
mojom::WebMemoryBreakdownEntry* WebMemoryAggregator::CreateBreakdownEntry(
AttributionScope scope,
- base::Optional<std::string> url,
+ absl::optional<std::string> url,
mojom::WebMemoryMeasurement* measurement) {
auto breakdown = mojom::WebMemoryBreakdownEntry::New();
auto attribution = mojom::WebMemoryAttribution::New();
diff --git a/chromium/components/performance_manager/v8_memory/web_memory_aggregator.h b/chromium/components/performance_manager/v8_memory/web_memory_aggregator.h
index 1c93376f031..3b05274426f 100644
--- a/chromium/components/performance_manager/v8_memory/web_memory_aggregator.h
+++ b/chromium/components/performance_manager/v8_memory/web_memory_aggregator.h
@@ -7,9 +7,9 @@
#include <string>
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "components/performance_manager/public/mojom/web_memory.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
namespace performance_manager {
@@ -64,7 +64,7 @@ class WebMemoryAggregator {
// to the list in |measurement|. Returns a pointer to the newly created entry.
static mojom::WebMemoryBreakdownEntry* CreateBreakdownEntry(
mojom::WebMemoryAttribution::Scope scope,
- base::Optional<std::string> url,
+ absl::optional<std::string> url,
mojom::WebMemoryMeasurement* measurement);
// Sets the id and src attributes of |breakdown| using those stored in the
diff --git a/chromium/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc b/chromium/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc
index 0edbb16887a..a8aad6a1bb7 100644
--- a/chromium/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc
+++ b/chromium/components/performance_manager/v8_memory/web_memory_aggregator_unittest.cc
@@ -9,12 +9,12 @@
#include <utility>
#include <vector>
-#include "base/optional.h"
#include "base/trace_event/traced_value.h"
#include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/public/v8_memory/web_memory.h"
#include "components/performance_manager/v8_memory/v8_memory_test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -29,17 +29,17 @@ using AttributionScope = mojom::WebMemoryAttribution::Scope;
struct ExpectedMemoryBreakdown {
WebMemoryTestHarness::Bytes bytes;
AttributionScope scope = AttributionScope::kWindow;
- base::Optional<std::string> url;
- base::Optional<std::string> id;
- base::Optional<std::string> src;
+ absl::optional<std::string> url;
+ absl::optional<std::string> id;
+ absl::optional<std::string> src;
ExpectedMemoryBreakdown() = default;
ExpectedMemoryBreakdown(
WebMemoryTestHarness::Bytes expected_bytes,
AttributionScope expected_scope,
- base::Optional<std::string> expected_url = base::nullopt,
- base::Optional<std::string> expected_id = base::nullopt,
- base::Optional<std::string> expected_src = base::nullopt)
+ absl::optional<std::string> expected_url = absl::nullopt,
+ absl::optional<std::string> expected_id = absl::nullopt,
+ absl::optional<std::string> expected_src = absl::nullopt)
: bytes(expected_bytes),
scope(expected_scope),
url(std::move(expected_url)),
@@ -96,7 +96,7 @@ class WebMemoryAggregatorTest : public WebMemoryTestHarness {
// WebMemoryAggregator.
static mojom::WebMemoryBreakdownEntry* CreateBreakdownEntry(
mojom::WebMemoryAttribution::Scope scope,
- base::Optional<std::string> url,
+ absl::optional<std::string> url,
mojom::WebMemoryMeasurement* measurement) {
return WebMemoryAggregator::CreateBreakdownEntry(scope, url, measurement);
}
@@ -119,7 +119,7 @@ TEST_F(WebMemoryAggregatorTest, CreateBreakdownEntry) {
auto measurement = mojom::WebMemoryMeasurement::New();
auto* breakdown_with_no_url =
CreateBreakdownEntry(AttributionScope::kCrossOriginAggregated,
- base::nullopt, measurement.get());
+ absl::nullopt, measurement.get());
auto* breakdown_with_url = CreateBreakdownEntry(
AttributionScope::kWindow, "https://example.com", measurement.get());
auto* breakdown_with_empty_url =
@@ -132,11 +132,11 @@ TEST_F(WebMemoryAggregatorTest, CreateBreakdownEntry) {
EXPECT_EQ(measurement->breakdown[2].get(), breakdown_with_empty_url);
// Can't use an initializer list because nullopt_t and
- // base::Optional<std::string> are different types.
- std::vector<base::Optional<std::string>> attributes;
- attributes.push_back(base::nullopt);
- attributes.push_back(base::make_optional("example_attr"));
- attributes.push_back(base::make_optional(""));
+ // absl::optional<std::string> are different types.
+ std::vector<absl::optional<std::string>> attributes;
+ attributes.push_back(absl::nullopt);
+ attributes.push_back(absl::make_optional("example_attr"));
+ attributes.push_back(absl::make_optional(""));
for (const auto& attribute : attributes) {
SCOPED_TRACE(attribute.value_or("nullopt"));
@@ -151,15 +151,15 @@ TEST_F(WebMemoryAggregatorTest, CreateBreakdownEntry) {
// All measurements should be created without measurement results.
auto expected_result = CreateExpectedMemoryMeasurement({
- ExpectedMemoryBreakdown(/*bytes=*/base::nullopt,
+ ExpectedMemoryBreakdown(/*bytes=*/absl::nullopt,
AttributionScope::kCrossOriginAggregated,
- /*expected_url=*/base::nullopt,
- /*expected_id=*/base::nullopt,
- /*expected_src=*/base::nullopt),
- ExpectedMemoryBreakdown(/*bytes=*/base::nullopt,
+ /*expected_url=*/absl::nullopt,
+ /*expected_id=*/absl::nullopt,
+ /*expected_src=*/absl::nullopt),
+ ExpectedMemoryBreakdown(/*bytes=*/absl::nullopt,
AttributionScope::kWindow,
"https://example.com", attribute, attribute),
- ExpectedMemoryBreakdown(/*bytes=*/base::nullopt,
+ ExpectedMemoryBreakdown(/*bytes=*/absl::nullopt,
AttributionScope::kWindow,
/*expected_url=*/"", attribute, attribute),
});
@@ -233,7 +233,7 @@ TEST_F(WebMemoryAggregatorTest, AggregateCrossOrigin) {
ExpectedMemoryBreakdown(10, AttributionScope::kWindow,
"https://example.com/"),
ExpectedMemoryBreakdown(14, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "example-id",
+ absl::nullopt, "example-id",
"https://foo.com/iframe1"),
});
auto result = aggregator.AggregateMeasureMemoryResult();
@@ -290,7 +290,7 @@ TEST_F(WebMemoryAggregatorTest, AggregateNestedCrossOrigin) {
// A frame without a memory measurement (eg. a frame that's added to the frame
// tree during the measurement) should not have a memory entry in the result.
- AddFrameNode("https://example.com/empty_frame", base::nullopt, subframe3);
+ AddFrameNode("https://example.com/empty_frame", absl::nullopt, subframe3);
WebMemoryAggregator aggregator(main_frame);
@@ -298,13 +298,13 @@ TEST_F(WebMemoryAggregatorTest, AggregateNestedCrossOrigin) {
ExpectedMemoryBreakdown(10, AttributionScope::kWindow,
"https://example.com/"),
ExpectedMemoryBreakdown(9, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "example-id",
+ absl::nullopt, "example-id",
"https://foo.com/iframe1"),
ExpectedMemoryBreakdown(3, AttributionScope::kWindow,
"https://example.com/iframe1", "example-id",
"https://foo.com/iframe1"),
ExpectedMemoryBreakdown(2, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "example-id4",
+ absl::nullopt, "example-id4",
"https://foo.com/iframe2"),
ExpectedMemoryBreakdown(1, AttributionScope::kWindow,
"https://example.com/iframe2", "example-id4",
@@ -316,8 +316,8 @@ TEST_F(WebMemoryAggregatorTest, AggregateNestedCrossOrigin) {
"https://example.com/cross_process",
"cross-process-id1"),
ExpectedMemoryBreakdown(0, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "cross-process-id2"),
- ExpectedMemoryBreakdown(base::nullopt, AttributionScope::kWindow,
+ absl::nullopt, "cross-process-id2"),
+ ExpectedMemoryBreakdown(absl::nullopt, AttributionScope::kWindow,
"https://example.com/empty_frame"),
});
auto result = aggregator.AggregateMeasureMemoryResult();
@@ -350,7 +350,7 @@ TEST_F(WebMemoryAggregatorTest, SkipCrossOriginAboutBlank) {
ExpectedMemoryBreakdown(10, AttributionScope::kWindow,
"https://example.com/"),
ExpectedMemoryBreakdown(50, AttributionScope::kCrossOriginAggregated,
- base::nullopt),
+ absl::nullopt),
});
WebMemoryAggregator aggregator(main_frame);
auto result = aggregator.AggregateMeasureMemoryResult();
@@ -388,7 +388,7 @@ TEST_F(WebMemoryAggregatorTest, AggregateWindowOpener) {
"https://example.com/window-iframe.html",
"example-id2"),
ExpectedMemoryBreakdown(2, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "example-id3"),
+ absl::nullopt, "example-id3"),
});
auto result = aggregator.AggregateMeasureMemoryResult();
EXPECT_EQ(NormalizeMeasurement(result),
@@ -401,8 +401,8 @@ TEST_F(WebMemoryAggregatorTest, AggregateWindowOpener) {
ExpectedMemoryBreakdown(22, AttributionScope::kCrossOriginAggregated),
ExpectedMemoryBreakdown(
2, AttributionScope::kWindow,
- "https://cross-site-example.com/window-iframe.html", base::nullopt,
- base::nullopt),
+ "https://cross-site-example.com/window-iframe.html", absl::nullopt,
+ absl::nullopt),
});
auto cross_site_result = aggregator.AggregateMeasureMemoryResult();
EXPECT_EQ(NormalizeMeasurement(cross_site_result),
@@ -415,7 +415,7 @@ TEST_F(WebMemoryAggregatorTest, AggregateWindowOpener) {
auto expected_cross_site_result = CreateExpectedMemoryMeasurement({
ExpectedMemoryBreakdown(2, AttributionScope::kWindow,
"https://cross-site-example.com/",
- base::nullopt, base::nullopt),
+ absl::nullopt, absl::nullopt),
});
auto cross_site_result = aggregator.AggregateMeasureMemoryResult();
EXPECT_EQ(NormalizeMeasurement(cross_site_result),
@@ -429,7 +429,7 @@ TEST_F(WebMemoryAggregatorTest, AggregateProvisionalWindowOpener) {
// This creates an openee window with pending navigation which should be
// skipped because it may get its own browsing context group once the
// navigation completes.
- AddFrameNodeFromOpener(base::nullopt, Bytes{4}, main_frame);
+ AddFrameNodeFromOpener(absl::nullopt, Bytes{4}, main_frame);
WebMemoryAggregator aggregator(main_frame);
@@ -489,7 +489,7 @@ TEST_F(WebMemoryAggregatorTest, AggregateCrossOriginWorker) {
ExpectedMemoryBreakdown(10, AttributionScope::kWindow,
"https://example.com/"),
ExpectedMemoryBreakdown(65, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "example-id"),
+ absl::nullopt, "example-id"),
});
auto result = aggregator.AggregateMeasureMemoryResult();
EXPECT_EQ(NormalizeMeasurement(result),
@@ -524,13 +524,13 @@ TEST_F(WebMemoryAggregatorTest, AggregateCrossOriginCallers) {
ExpectedMemoryBreakdown(20, AttributionScope::kWindow,
"https://a.com/iframe", "a_com_iframe"),
ExpectedMemoryBreakdown(40, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "b_com_iframe2"),
+ absl::nullopt, "b_com_iframe2"),
ExpectedMemoryBreakdown(80, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "b_com_iframe1"),
+ absl::nullopt, "b_com_iframe1"),
ExpectedMemoryBreakdown(60, AttributionScope::kWindow,
"https://a.com/popup1"),
ExpectedMemoryBreakdown(150, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "b_com_iframe3"),
+ absl::nullopt, "b_com_iframe3"),
ExpectedMemoryBreakdown(90, AttributionScope::kWindow,
"https://a.com/popup2"),
});
@@ -543,17 +543,17 @@ TEST_F(WebMemoryAggregatorTest, AggregateCrossOriginCallers) {
WebMemoryAggregator aggregator(b_com_iframe3);
auto expected_result = CreateExpectedMemoryMeasurement({
ExpectedMemoryBreakdown(180, AttributionScope::kCrossOriginAggregated,
- base::nullopt),
+ absl::nullopt),
ExpectedMemoryBreakdown(40, AttributionScope::kWindow,
"https://b.com/iframe2"),
ExpectedMemoryBreakdown(30, AttributionScope::kWindow,
"https://b.com/iframe1"),
ExpectedMemoryBreakdown(50, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "c_com_iframe1"),
+ absl::nullopt, "c_com_iframe1"),
ExpectedMemoryBreakdown(70, AttributionScope::kWindow,
"https://b.com/iframe3"),
ExpectedMemoryBreakdown(80, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "c_com_iframe2"),
+ absl::nullopt, "c_com_iframe2"),
});
auto result = aggregator.AggregateMeasureMemoryResult();
EXPECT_EQ(NormalizeMeasurement(result),
@@ -564,7 +564,7 @@ TEST_F(WebMemoryAggregatorTest, AggregateCrossOriginCallers) {
WebMemoryAggregator aggregator(c_com_iframe1);
auto expected_result = CreateExpectedMemoryMeasurement({
ExpectedMemoryBreakdown(320, AttributionScope::kCrossOriginAggregated,
- base::nullopt),
+ absl::nullopt),
ExpectedMemoryBreakdown(50, AttributionScope::kWindow,
"https://c.com/iframe1"),
ExpectedMemoryBreakdown(80, AttributionScope::kWindow,
@@ -586,7 +586,7 @@ TEST_F(WebMemoryAggregatorTest, AggregateCrossProcessCallers) {
ExpectedMemoryBreakdown(10, AttributionScope::kWindow,
"https://a.com/"),
ExpectedMemoryBreakdown(0, AttributionScope::kCrossOriginAggregated,
- base::nullopt, "b_com_iframe"),
+ absl::nullopt, "b_com_iframe"),
});
auto result = aggregator.AggregateMeasureMemoryResult();
EXPECT_EQ(NormalizeMeasurement(result),
@@ -597,7 +597,7 @@ TEST_F(WebMemoryAggregatorTest, AggregateCrossProcessCallers) {
WebMemoryAggregator aggregator(b_com_iframe);
auto expected_result = CreateExpectedMemoryMeasurement({
ExpectedMemoryBreakdown(0, AttributionScope::kCrossOriginAggregated,
- base::nullopt),
+ absl::nullopt),
ExpectedMemoryBreakdown(30, AttributionScope::kWindow,
"https://b.com/iframe"),
});
@@ -627,6 +627,26 @@ TEST_F(WebMemoryAggregatorTest, BlinkMemory) {
}
}
+TEST_F(WebMemoryAggregatorTest, BlinkMemoryWithoutFrameBytes) {
+ FrameNodeImpl* a_com = AddFrameNode("https://a.com/", absl::nullopt);
+ SetBlinkMemory(Bytes{1000});
+ {
+ WebMemoryAggregator aggregator(a_com);
+ auto expected_result =
+ CreateExpectedMemoryMeasurement({ExpectedMemoryBreakdown(
+ absl::nullopt, AttributionScope::kWindow, "https://a.com/")});
+ expected_result->blink_memory = mojom::WebMemoryUsage::New();
+ expected_result->blink_memory->bytes = 1000;
+ expected_result->shared_memory = mojom::WebMemoryUsage::New();
+ expected_result->shared_memory->bytes = 0;
+ expected_result->detached_memory = mojom::WebMemoryUsage::New();
+ expected_result->detached_memory->bytes = 0;
+ auto result = aggregator.AggregateMeasureMemoryResult();
+ EXPECT_EQ(NormalizeMeasurement(result),
+ NormalizeMeasurement(expected_result));
+ }
+}
+
TEST_F(WebMemoryAggregatorTest, BlinkMemoryMultipleBrowsingInstances) {
FrameNodeImpl* a_com = AddFrameNode("https://a.com/", Bytes{10});
AddCrossBrowsingInstanceFrameNode("https://b.com/", Bytes{30});
@@ -661,7 +681,7 @@ TEST_F(WebMemoryAggregatorTest, WorkerWithoutData) {
auto expected_result = CreateExpectedMemoryMeasurement({
ExpectedMemoryBreakdown(10, AttributionScope::kWindow,
"https://example.com/"),
- ExpectedMemoryBreakdown(base::nullopt, AttributionScope::kDedicatedWorker,
+ ExpectedMemoryBreakdown(absl::nullopt, AttributionScope::kDedicatedWorker,
""),
});
auto result = aggregator.AggregateMeasureMemoryResult();
diff --git a/chromium/components/performance_manager/v8_memory/web_memory_impl.cc b/chromium/components/performance_manager/v8_memory/web_memory_impl.cc
index 44e3d379c95..07a4d31561d 100644
--- a/chromium/components/performance_manager/v8_memory/web_memory_impl.cc
+++ b/chromium/components/performance_manager/v8_memory/web_memory_impl.cc
@@ -78,8 +78,8 @@ void CheckIsCrossOriginIsolatedOnUISeq(
// Frame was deleted before the task ran.
return;
}
- if (rfh->GetCrossOriginIsolationStatus() ==
- content::RenderFrameHost::CrossOriginIsolationStatus::kNotIsolated &&
+ if (rfh->GetWebExposedIsolationLevel() ==
+ content::RenderFrameHost::WebExposedIsolationLevel::kNotIsolated &&
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableWebSecurity)) {
std::move(bad_message_callback)
diff --git a/chromium/components/performance_manager/v8_memory/web_memory_impl_unittest.cc b/chromium/components/performance_manager/v8_memory/web_memory_impl_unittest.cc
index a9718ace47f..5e0df59644d 100644
--- a/chromium/components/performance_manager/v8_memory/web_memory_impl_unittest.cc
+++ b/chromium/components/performance_manager/v8_memory/web_memory_impl_unittest.cc
@@ -76,7 +76,7 @@ void WebMemoryImplTest::MeasureAndVerify(
? *entry->attribution[0]->url
: *entry->attribution[0]->src;
actual[attribution_tag] =
- entry->memory ? Bytes{entry->memory->bytes} : base::nullopt;
+ entry->memory ? Bytes{entry->memory->bytes} : absl::nullopt;
}
EXPECT_EQ(expected, actual);
measurement_done = true;
diff --git a/chromium/components/performance_manager/worker_watcher_unittest.cc b/chromium/components/performance_manager/worker_watcher_unittest.cc
index 9fe832341dd..1fa3bca97fb 100644
--- a/chromium/components/performance_manager/worker_watcher_unittest.cc
+++ b/chromium/components/performance_manager/worker_watcher_unittest.cc
@@ -25,6 +25,7 @@
#include "components/performance_manager/performance_manager_impl.h"
#include "components/performance_manager/process_node_source.h"
#include "components/performance_manager/public/features.h"
+#include "components/services/storage/public/cpp/storage_key.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/shared_worker_service.h"
#include "content/public/test/browser_task_environment.h"
@@ -161,7 +162,7 @@ class TestSharedWorkerService : public content::SharedWorkerService {
void EnumerateSharedWorkers(Observer* observer) override;
bool TerminateWorker(const GURL& url,
const std::string& name,
- const url::Origin& constructor_origin) override;
+ const storage::StorageKey& storage_key) override;
void Shutdown() override;
// Creates a new shared worker and returns its token.
@@ -209,7 +210,7 @@ void TestSharedWorkerService::EnumerateSharedWorkers(Observer* observer) {
bool TestSharedWorkerService::TerminateWorker(
const GURL& url,
const std::string& name,
- const url::Origin& constructor_origin) {
+ const storage::StorageKey& storage_key) {
// Not implemented.
ADD_FAILURE();
return false;
diff --git a/chromium/components/permissions/BUILD.gn b/chromium/components/permissions/BUILD.gn
index 2faa3caadfe..1f6a354712d 100644
--- a/chromium/components/permissions/BUILD.gn
+++ b/chromium/components/permissions/BUILD.gn
@@ -17,26 +17,30 @@ source_set("permissions_common") {
source_set("permissions") {
sources = [
- "chooser_context_base.cc",
- "chooser_context_base.h",
+ "chooser_controller.cc",
+ "chooser_controller.h",
+ "contexts/bluetooth_chooser_context.cc",
+ "contexts/bluetooth_chooser_context.h",
"contexts/clipboard_read_write_permission_context.cc",
"contexts/clipboard_read_write_permission_context.h",
"contexts/clipboard_sanitized_write_permission_context.cc",
"contexts/clipboard_sanitized_write_permission_context.h",
- "contexts/file_handling_permission_context.cc",
- "contexts/file_handling_permission_context.h",
"contexts/font_access_permission_context.cc",
"contexts/font_access_permission_context.h",
"contexts/geolocation_permission_context.cc",
"contexts/geolocation_permission_context.h",
+ "contexts/midi_permission_context.cc",
+ "contexts/midi_permission_context.h",
+ "contexts/midi_sysex_permission_context.cc",
+ "contexts/midi_sysex_permission_context.h",
"contexts/nfc_permission_context.cc",
"contexts/nfc_permission_context.h",
"contexts/payment_handler_permission_context.cc",
"contexts/payment_handler_permission_context.h",
"contexts/webxr_permission_context.cc",
"contexts/webxr_permission_context.h",
- "notification_permission_ui_selector.cc",
- "notification_permission_ui_selector.h",
+ "object_permission_context_base.cc",
+ "object_permission_context_base.h",
"permission_auditing_database.cc",
"permission_auditing_database.h",
"permission_auditing_service.cc",
@@ -58,6 +62,8 @@ source_set("permissions") {
"permission_request_manager.h",
"permission_result.cc",
"permission_result.h",
+ "permission_ui_selector.cc",
+ "permission_ui_selector.h",
"permission_uma_util.cc",
"permission_uma_util.h",
"permission_usage_session.cc",
@@ -91,6 +97,8 @@ source_set("permissions") {
"//components/variations",
"//components/vector_icons",
"//content/public/browser",
+ "//device/bluetooth",
+ "//device/bluetooth/public/cpp",
"//services/metrics/public/cpp:ukm_builders",
"//sql",
"//third_party/blink/public/common",
@@ -106,6 +114,8 @@ source_set("permissions") {
"android/permission_dialog_delegate.h",
"android/permission_prompt_android.cc",
"android/permission_prompt_android.h",
+ "android/permissions_android_feature_list.cc",
+ "android/permissions_android_feature_list.h",
"contexts/geolocation_permission_context_android.cc",
"contexts/geolocation_permission_context_android.h",
"contexts/nfc_permission_context_android.cc",
@@ -130,23 +140,35 @@ source_set("permissions") {
source_set("test_support") {
testonly = true
sources = [
- "test/chooser_context_base_mock_permission_observer.cc",
- "test/chooser_context_base_mock_permission_observer.h",
"test/mock_permission_prompt.cc",
"test/mock_permission_prompt.h",
"test/mock_permission_prompt_factory.cc",
"test/mock_permission_prompt_factory.h",
"test/mock_permission_request.cc",
"test/mock_permission_request.h",
+ "test/object_permission_context_base_mock_permission_observer.cc",
+ "test/object_permission_context_base_mock_permission_observer.h",
"test/permission_request_observer.cc",
"test/permission_request_observer.h",
"test/test_permissions_client.cc",
"test/test_permissions_client.h",
]
+ if (!is_android) {
+ sources += [
+ "fake_bluetooth_chooser_controller.cc",
+ "fake_bluetooth_chooser_controller.h",
+ "fake_usb_chooser_controller.cc",
+ "fake_usb_chooser_controller.h",
+ "mock_chooser_controller_view.cc",
+ "mock_chooser_controller_view.h",
+ ]
+ }
+
deps = [
":permissions",
"//base",
"//components/content_settings/core/browser",
+ "//components/strings:components_strings_grit",
"//components/sync_preferences:test_support",
"//components/ukm/content",
"//components/vector_icons",
@@ -164,9 +186,11 @@ source_set("test_support") {
source_set("unit_tests") {
testonly = true
sources = [
- "chooser_context_base_unittest.cc",
"contexts/geolocation_permission_context_unittest.cc",
+ "contexts/midi_permission_context_unittest.cc",
+ "contexts/midi_sysex_permission_context_unittest.cc",
"contexts/nfc_permission_context_unittest.cc",
+ "object_permission_context_base_unittest.cc",
"permission_auditing_database_unittest.cc",
"permission_auditing_service_unittest.cc",
"permission_context_base_unittest.cc",
diff --git a/chromium/components/permissions/android/BUILD.gn b/chromium/components/permissions/android/BUILD.gn
index 94886c4e9f6..3ff25d2e2d3 100644
--- a/chromium/components/permissions/android/BUILD.gn
+++ b/chromium/components/permissions/android/BUILD.gn
@@ -8,10 +8,12 @@ import("//tools/grit/grit_rule.gni")
generate_jni("jni_headers") {
sources = [
+ "java/src/org/chromium/components/permissions/AndroidPermissionRequester.java",
"java/src/org/chromium/components/permissions/PermissionDialogController.java",
"java/src/org/chromium/components/permissions/PermissionDialogDelegate.java",
"java/src/org/chromium/components/permissions/PermissionUmaUtil.java",
"java/src/org/chromium/components/permissions/PermissionUtil.java",
+ "java/src/org/chromium/components/permissions/PermissionsAndroidFeatureList.java",
"java/src/org/chromium/components/permissions/nfc/NfcSystemLevelSetting.java",
]
}
@@ -96,11 +98,11 @@ android_library("java") {
"java/src/org/chromium/components/permissions/PermissionDialogDelegate.java",
"java/src/org/chromium/components/permissions/PermissionDialogModel.java",
"java/src/org/chromium/components/permissions/PermissionUmaUtil.java",
- "java/src/org/chromium/components/permissions/PermissionUtil.java",
"java/src/org/chromium/components/permissions/nfc/NfcSystemLevelPrompt.java",
"java/src/org/chromium/components/permissions/nfc/NfcSystemLevelSetting.java",
]
deps = [
+ ":core_java",
":java_resources",
"//base:base_java",
"//components/browser_ui/modaldialog/android:java",
@@ -114,6 +116,21 @@ android_library("java") {
resources_package = "org.chromium.components.permissions"
}
+# Contains sources that do no depend on //content.
+android_library("core_java") {
+ sources = [
+ "java/src/org/chromium/components/permissions/PermissionUtil.java",
+ "java/src/org/chromium/components/permissions/PermissionsAndroidFeatureList.java",
+ ]
+ deps = [
+ "//base:base_java",
+ "//components/content_settings/android:content_settings_enums_java",
+ "//third_party/androidx:androidx_annotation_annotation_java",
+ "//third_party/androidx:androidx_core_core_java",
+ ]
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+}
+
java_library("components_permissions_junit_tests") {
# Platform checks are broken for Robolectric. See https://crbug.com/1071638.
bypass_platform_checks = true
diff --git a/chromium/components/permissions/android/android_permission_util.cc b/chromium/components/permissions/android/android_permission_util.cc
index 959ed6958c1..570d97568a4 100644
--- a/chromium/components/permissions/android/android_permission_util.cc
+++ b/chromium/components/permissions/android/android_permission_util.cc
@@ -5,6 +5,7 @@
#include "components/permissions/android/android_permission_util.h"
#include "base/android/jni_array.h"
+#include "components/permissions/android/jni_headers/AndroidPermissionRequester_jni.h"
#include "components/permissions/android/jni_headers/PermissionUtil_jni.h"
#include "components/permissions/permission_uma_util.h"
#include "content/public/browser/web_contents.h"
@@ -12,17 +13,37 @@
namespace permissions {
-void GetAndroidPermissionsForContentSetting(
+void AppendRequiredAndroidPermissionsForContentSetting(
ContentSettingsType content_settings_type,
std::vector<std::string>* out) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::AppendJavaStringArrayToStringVector(
env,
- Java_PermissionUtil_getAndroidPermissionsForContentSetting(
+ Java_PermissionUtil_getRequiredAndroidPermissionsForContentSetting(
env, static_cast<int>(content_settings_type)),
out);
}
+void AppendOptionalAndroidPermissionsForContentSetting(
+ ContentSettingsType content_settings_type,
+ std::vector<std::string>* out) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::AppendJavaStringArrayToStringVector(
+ env,
+ Java_PermissionUtil_getOptionalAndroidPermissionsForContentSetting(
+ env, static_cast<int>(content_settings_type)),
+ out);
+}
+
+bool HasRequiredAndroidPermissionsForContentSetting(
+ ui::WindowAndroid* window_android,
+ ContentSettingsType content_settings_type) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ return Java_AndroidPermissionRequester_hasRequiredAndroidPermissionsForContentSetting(
+ env, window_android->GetJavaObject(),
+ static_cast<int>(content_settings_type));
+}
+
PermissionRepromptState ShouldRepromptUserForPermissions(
content::WebContents* web_contents,
const std::vector<ContentSettingsType>& content_settings_types) {
@@ -34,16 +55,11 @@ PermissionRepromptState ShouldRepromptUserForPermissions(
return PermissionRepromptState::kCannotShow;
for (ContentSettingsType content_settings_type : content_settings_types) {
- std::vector<std::string> android_permissions;
- GetAndroidPermissionsForContentSetting(content_settings_type,
- &android_permissions);
-
- for (const auto& android_permission : android_permissions) {
- if (!window_android->HasPermission(android_permission)) {
- PermissionUmaUtil::RecordMissingPermissionInfobarShouldShow(
- true, content_settings_types);
- return PermissionRepromptState::kShow;
- }
+ if (!HasRequiredAndroidPermissionsForContentSetting(
+ window_android, content_settings_type)) {
+ PermissionUmaUtil::RecordMissingPermissionInfobarShouldShow(
+ true, content_settings_types);
+ return PermissionRepromptState::kShow;
}
}
diff --git a/chromium/components/permissions/android/android_permission_util.h b/chromium/components/permissions/android/android_permission_util.h
index c6367078e43..9792b649b84 100644
--- a/chromium/components/permissions/android/android_permission_util.h
+++ b/chromium/components/permissions/android/android_permission_util.h
@@ -14,12 +14,29 @@ namespace content {
class WebContents;
}
+namespace ui {
+class WindowAndroid;
+}
+
namespace permissions {
-// Populate the list of corresponding Android permissions associated with the
-// ContentSettingsType specified.
-void GetAndroidPermissionsForContentSetting(ContentSettingsType content_type,
- std::vector<std::string>* out);
+// Appends to `out` the required Android permissions associated with
+// `content_settings_type`.
+void AppendRequiredAndroidPermissionsForContentSetting(
+ ContentSettingsType content_settings_type,
+ std::vector<std::string>* out);
+
+// Appends to `out` the optional Android permissions associated with
+// `content_settings_type`.
+void AppendOptionalAndroidPermissionsForContentSetting(
+ ContentSettingsType content_settings_type,
+ std::vector<std::string>* out);
+
+// Returns whether the required Android permission for `content_settings_type`
+// are granted.
+bool HasRequiredAndroidPermissionsForContentSetting(
+ ui::WindowAndroid* window_android,
+ ContentSettingsType content_settings_type);
// The states that indicate if the user should/can be re-nudged to accept
// permissions. In Chrome this correlates to the PermissionUpdateInfoBar.
diff --git a/chromium/components/permissions/android/nfc/nfc_system_level_setting_impl.h b/chromium/components/permissions/android/nfc/nfc_system_level_setting_impl.h
index b285012daf4..59bdb3e05ab 100644
--- a/chromium/components/permissions/android/nfc/nfc_system_level_setting_impl.h
+++ b/chromium/components/permissions/android/nfc/nfc_system_level_setting_impl.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_PERMISSIONS_ANDROID_NFC_NFC_SYSTEM_LEVEL_SETTING_IMPL_H_
#define COMPONENTS_PERMISSIONS_ANDROID_NFC_NFC_SYSTEM_LEVEL_SETTING_IMPL_H_
-#include <memory>
-
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
diff --git a/chromium/components/permissions/android/permission_dialog_delegate.cc b/chromium/components/permissions/android/permission_dialog_delegate.cc
index 19905a0a9f2..4de29c5376b 100644
--- a/chromium/components/permissions/android/permission_dialog_delegate.cc
+++ b/chromium/components/permissions/android/permission_dialog_delegate.cc
@@ -124,4 +124,8 @@ void PermissionDialogDelegate::WebContentsDestroyed() {
DismissDialog();
}
+static jint JNI_PermissionDialogDelegate_GetRequestTypeEnumSize(JNIEnv* env) {
+ return static_cast<int>(RequestType::kMaxValue) + 1;
+}
+
} // namespace permissions
diff --git a/chromium/components/permissions/android/permission_dialog_delegate.h b/chromium/components/permissions/android/permission_dialog_delegate.h
index 5b4ff0e8a4d..c91cf444d9a 100644
--- a/chromium/components/permissions/android/permission_dialog_delegate.h
+++ b/chromium/components/permissions/android/permission_dialog_delegate.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_PERMISSIONS_ANDROID_PERMISSION_DIALOG_DELEGATE_H_
#define COMPONENTS_PERMISSIONS_ANDROID_PERMISSION_DIALOG_DELEGATE_H_
-#include <memory>
-
#include "base/android/scoped_java_ref.h"
#include "base/callback.h"
#include "base/macros.h"
diff --git a/chromium/components/page_info/android/page_info_feature_list.cc b/chromium/components/permissions/android/permissions_android_feature_list.cc
index a804b82b0b2..e6402a0c753 100644
--- a/chromium/components/page_info/android/page_info_feature_list.cc
+++ b/chromium/components/permissions/android/permissions_android_feature_list.cc
@@ -1,18 +1,16 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
+// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/permissions/android/permissions_android_feature_list.h"
#include "base/android/jni_string.h"
-#include "base/feature_list.h"
-#include "base/notreached.h"
#include "base/stl_util.h"
-#include "components/page_info/android/jni_headers/PageInfoFeatureList_jni.h"
-#include "components/page_info/features.h"
+#include "components/permissions/android/jni_headers/PermissionsAndroidFeatureList_jni.h"
using base::android::ConvertJavaStringToUTF8;
using base::android::JavaParamRef;
-namespace page_info {
+namespace permissions {
namespace {
@@ -20,25 +18,30 @@ namespace {
// this array may either refer to features defined in the header of this file or
// in other locations in the code base (e.g. content_features.h).
const base::Feature* kFeaturesExposedToJava[] = {
- &kPageInfoDiscoverability,
- &kPageInfoHistory,
- &kPageInfoV2,
+ &kAndroidApproximateLocationPermissionSupport,
};
-// TODO(crbug.com/1060097): Remove this once a generalized FeatureList exists.
const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
- for (size_t i = 0; i < base::size(kFeaturesExposedToJava); ++i) {
- if (kFeaturesExposedToJava[i]->name == feature_name)
- return kFeaturesExposedToJava[i];
+ for (const base::Feature* feature : kFeaturesExposedToJava) {
+ if (feature->name == feature_name)
+ return feature;
}
- NOTREACHED() << "Queried feature not found in PageInfoFeatureList: "
+ NOTREACHED() << "Queried feature not found in PermissionsAndroidFeatureList: "
<< feature_name;
return nullptr;
}
} // namespace
-static jboolean JNI_PageInfoFeatureList_IsEnabled(
+const base::Feature kAndroidApproximateLocationPermissionSupport{
+ "AndroidApproximateLocationPermissionSupport",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+static jboolean JNI_PermissionsAndroidFeatureList_IsInitialized(JNIEnv* env) {
+ return !!base::FeatureList::GetInstance();
+}
+
+static jboolean JNI_PermissionsAndroidFeatureList_IsEnabled(
JNIEnv* env,
const JavaParamRef<jstring>& jfeature_name) {
const base::Feature* feature =
@@ -46,4 +49,4 @@ static jboolean JNI_PageInfoFeatureList_IsEnabled(
return base::FeatureList::IsEnabled(*feature);
}
-} // namespace page_info
+} // namespace permissions
diff --git a/chromium/components/permissions/android/permissions_android_feature_list.h b/chromium/components/permissions/android/permissions_android_feature_list.h
new file mode 100644
index 00000000000..cf137a3ed6d
--- /dev/null
+++ b/chromium/components/permissions/android/permissions_android_feature_list.h
@@ -0,0 +1,15 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERMISSIONS_ANDROID_PERMISSIONS_ANDROID_FEATURE_LIST_H_
+#define COMPONENTS_PERMISSIONS_ANDROID_PERMISSIONS_ANDROID_FEATURE_LIST_H_
+
+#include "base/feature_list.h"
+
+namespace permissions {
+// Alphabetical:
+extern const base::Feature kAndroidApproximateLocationPermissionSupport;
+} // namespace permissions
+
+#endif // COMPONENTS_PERMISSIONS_ANDROID_PERMISSIONS_ANDROID_FEATURE_LIST_H_
diff --git a/chromium/components/permissions/android/translations/permissions_android_strings_fr-CA.xtb b/chromium/components/permissions/android/translations/permissions_android_strings_fr-CA.xtb
index 8bdac3e6fa2..593f0e68de5 100644
--- a/chromium/components/permissions/android/translations/permissions_android_strings_fr-CA.xtb
+++ b/chromium/components/permissions/android/translations/permissions_android_strings_fr-CA.xtb
@@ -7,7 +7,7 @@
<translation id="2987449669841041897">Ce site ne peut pas demander votre autorisation</translation>
<translation id="557283862590186398">Google Chrome a besoin de votre autorisation pour accéder à votre micro pour ce site.</translation>
<translation id="5860491529813859533">Activer</translation>
-<translation id="6092062101542170135">Pour continuer, activez la NFC dans les paramètres d'Android</translation>
+<translation id="6092062101542170135">Pour continuer, activez la CCP dans les paramètres d'Android</translation>
<translation id="6393863479814692971">Google Chrome a besoin de votre autorisation pour accéder à votre caméra et à votre micro pour ce site.</translation>
<translation id="6697947395630195233">Chrome a besoin d'accéder à votre position afin de la partager avec ce site.</translation>
<translation id="7134415045456331657">Chrome a besoin de votre autorisation pour accéder à votre appareil photo afin de créer une carte 3D de votre environnement.</translation>
diff --git a/chromium/components/permissions/chooser_controller.cc b/chromium/components/permissions/chooser_controller.cc
new file mode 100644
index 00000000000..6222d3a88c4
--- /dev/null
+++ b/chromium/components/permissions/chooser_controller.cc
@@ -0,0 +1,86 @@
+// 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/permissions/chooser_controller.h"
+
+#include "base/notreached.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace permissions {
+
+ChooserController::ChooserController(std::u16string title) : title_(title) {}
+
+ChooserController::~ChooserController() = default;
+
+std::u16string ChooserController::GetTitle() const {
+ return title_;
+}
+
+void ChooserController::View::OnAdapterAuthorizationChanged(bool authorized) {
+ NOTREACHED();
+}
+
+bool ChooserController::ShouldShowIconBeforeText() const {
+ return false;
+}
+
+bool ChooserController::ShouldShowHelpButton() const {
+ return true;
+}
+
+bool ChooserController::ShouldShowReScanButton() const {
+ return false;
+}
+
+bool ChooserController::AllowMultipleSelection() const {
+ return false;
+}
+
+bool ChooserController::ShouldShowSelectAllCheckbox() const {
+ return false;
+}
+
+std::u16string ChooserController::GetCancelButtonLabel() const {
+ return l10n_util::GetStringUTF16(IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT);
+}
+
+std::u16string ChooserController::GetSelectAllCheckboxLabel() const {
+ return std::u16string();
+}
+
+bool ChooserController::BothButtonsAlwaysEnabled() const {
+ return false;
+}
+
+bool ChooserController::TableViewAlwaysDisabled() const {
+ return false;
+}
+
+int ChooserController::GetSignalStrengthLevel(size_t index) const {
+ return -1;
+}
+
+bool ChooserController::IsConnected(size_t index) const {
+ return false;
+}
+
+bool ChooserController::IsPaired(size_t index) const {
+ return false;
+}
+
+void ChooserController::RefreshOptions() {
+ NOTREACHED();
+}
+
+void ChooserController::OpenAdapterOffHelpUrl() const {
+ NOTREACHED();
+}
+
+void ChooserController::OpenPermissionPreferences() const {
+ NOTREACHED();
+}
+
+} // namespace permissions \ No newline at end of file
diff --git a/chromium/components/permissions/chooser_controller.h b/chromium/components/permissions/chooser_controller.h
new file mode 100644
index 00000000000..3e90236dc7e
--- /dev/null
+++ b/chromium/components/permissions/chooser_controller.h
@@ -0,0 +1,183 @@
+// 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_PERMISSIONS_CHOOSER_CONTROLLER_H_
+#define COMPONENTS_PERMISSIONS_CHOOSER_CONTROLLER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+
+namespace permissions {
+
+// Subclass ChooserController to implement a chooser, which has some
+// introductory text and a list of options that users can pick one of.
+// Your subclass must define the set of options users can pick from;
+// the actions taken after users select an item or press the 'Cancel'
+// button or the chooser is closed.
+// After Select/Cancel/Close is called, this object is destroyed and
+// calls back into it are not allowed.
+class ChooserController {
+ public:
+ explicit ChooserController(std::u16string title);
+ virtual ~ChooserController();
+
+ // Since the set of options can change while the UI is visible an
+ // implementation should register a view to observe changes.
+ class View {
+ public:
+ // Called after the options list is initialized for the first time.
+ // OnOptionsInitialized should only be called once.
+ virtual void OnOptionsInitialized() = 0;
+
+ // Called after GetOption(index) has been added to the options and the
+ // newly added option is the last element in the options list. Calling
+ // GetOption(index) from inside a call to OnOptionAdded will see the
+ // added string since the options have already been updated.
+ virtual void OnOptionAdded(size_t index) = 0;
+
+ // Called when GetOption(index) is no longer present, and all later
+ // options have been moved earlier by 1 slot. Calling GetOption(index)
+ // from inside a call to OnOptionRemoved will NOT see the removed string
+ // since the options have already been updated.
+ virtual void OnOptionRemoved(size_t index) = 0;
+
+ // Called when the option at |index| has been updated.
+ virtual void OnOptionUpdated(size_t index) = 0;
+
+ // Called when the device adapter is turned on or off.
+ virtual void OnAdapterEnabledChanged(bool enabled) = 0;
+
+ // Called when the platform level device permission is changed.
+ // Currently only needed on macOS.
+ virtual void OnAdapterAuthorizationChanged(bool authorized);
+
+ // Called when refreshing options is in progress or complete.
+ virtual void OnRefreshStateChanged(bool refreshing) = 0;
+
+ protected:
+ virtual ~View() {}
+ };
+
+ // Returns the text to be displayed in the chooser title.
+ // Note that this is only called once, and there is no way to update the title
+ // for a given instance of ChooserController.
+ std::u16string GetTitle() const;
+
+ // Returns whether the chooser needs to show an icon before the text.
+ // For WebBluetooth, it is a signal strength icon.
+ virtual bool ShouldShowIconBeforeText() const;
+
+ // Returns whether the chooser needs to show a help button.
+ virtual bool ShouldShowHelpButton() const;
+
+ // Returns whether the chooser needs to show a button to re-scan for devices.
+ virtual bool ShouldShowReScanButton() const;
+
+ // Returns whether the chooser allows multiple items to be selected.
+ virtual bool AllowMultipleSelection() const;
+
+ // Returns whether the chooser needs to show a select-all checkbox.
+ virtual bool ShouldShowSelectAllCheckbox() const;
+
+ // Returns the text to be displayed in the chooser when there are no options.
+ virtual std::u16string GetNoOptionsText() const = 0;
+
+ // Returns the label for OK button.
+ virtual std::u16string GetOkButtonLabel() const = 0;
+
+ // Returns the label for Cancel button.
+ virtual std::u16string GetCancelButtonLabel() const;
+
+ // Returns the label for SelectAll checkbox.
+ virtual std::u16string GetSelectAllCheckboxLabel() const;
+
+ // Returns the label for the throbber shown while options are initializing or
+ // a re-scan is in progress.
+ virtual std::pair<std::u16string, std::u16string> GetThrobberLabelAndTooltip()
+ const = 0;
+
+ // Returns whether both OK and Cancel buttons are enabled.
+ //
+ // For chooser used in Web APIs such as WebBluetooth, WebUSB,
+ // WebSerial, etc., the OK button is only enabled when there is at least
+ // one device listed in the chooser, because user needs to be able to select
+ // a device to grant access permission in these APIs.
+ //
+ // For permission prompt used in Bluetooth scanning Web API, the two buttons
+ // represent Allow and Block, and should always be enabled so that user can
+ // make their permission decision.
+ virtual bool BothButtonsAlwaysEnabled() const;
+
+ // Returns whether table view should always be disabled.
+ //
+ // For permission prompt used in Bluetooth scanning Web API, the table is
+ // used for displaying device names, and user doesn't need to select a device
+ // from the table, so it should always be disabled.
+ virtual bool TableViewAlwaysDisabled() const;
+
+ // The number of options users can pick from. For example, it can be
+ // the number of USB/Bluetooth device names which are listed in the
+ // chooser so that users can grant permission.
+ virtual size_t NumOptions() const = 0;
+
+ // The signal strength level (0-4 inclusive) of the device at |index|, which
+ // is used to retrieve the corresponding icon to be displayed before the
+ // text. Returns -1 if no icon should be shown.
+ virtual int GetSignalStrengthLevel(size_t index) const;
+
+ // The |index|th option string which is listed in the chooser.
+ virtual std::u16string GetOption(size_t index) const = 0;
+
+ // Returns if the |index|th option is connected.
+ // This function returns false by default.
+ virtual bool IsConnected(size_t index) const;
+
+ // Returns if the |index|th option is paired.
+ // This function returns false by default.
+ virtual bool IsPaired(size_t index) const;
+
+ // Refresh the list of options.
+ virtual void RefreshOptions();
+
+ // These three functions are called just before this object is destroyed:
+
+ // Called when the user selects elements from the dialog. |indices| contains
+ // the indices of the selected elements.
+ virtual void Select(const std::vector<size_t>& indices) = 0;
+
+ // Called when the user presses the 'Cancel' button in the dialog.
+ virtual void Cancel() = 0;
+
+ // Called when the user clicks outside the dialog or the dialog otherwise
+ // closes without the user taking an explicit action.
+ virtual void Close() = 0;
+
+ // Open help center URL.
+ virtual void OpenHelpCenterUrl() const = 0;
+
+ // Provide help information when the adapter is off.
+ virtual void OpenAdapterOffHelpUrl() const;
+
+ // Navigate user to preferences in order to acquire Bluetooth permission.
+ virtual void OpenPermissionPreferences() const;
+
+ // Only one view may be registered at a time.
+ void set_view(View* view) { view_ = view; }
+ View* view() const { return view_; }
+
+ protected:
+ void set_title_for_testing(const std::u16string& title) { title_ = title; }
+
+ private:
+ std::u16string title_;
+ View* view_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ChooserController);
+};
+
+} // namespace permissions
+
+#endif // COMPONENTS_PERMISSIONS_CHOOSER_CONTROLLER_H_
diff --git a/chromium/components/permissions/contexts/DEPS b/chromium/components/permissions/contexts/DEPS
index d29516628c9..74dd14d9dee 100644
--- a/chromium/components/permissions/contexts/DEPS
+++ b/chromium/components/permissions/contexts/DEPS
@@ -2,6 +2,9 @@ include_rules = [
"+components/content_settings/browser",
"+components/location",
"+components/prefs",
+ "+device/bluetooth",
"+mojo/public",
"+services/device/public",
+ "+third_party/blink/public/common",
+ "+third_party/blink/public/mojom",
]
diff --git a/chromium/components/permissions/contexts/DIR_METADATA b/chromium/components/permissions/contexts/DIR_METADATA
deleted file mode 100644
index b1e8e6f3dbb..00000000000
--- a/chromium/components/permissions/contexts/DIR_METADATA
+++ /dev/null
@@ -1,5 +0,0 @@
-monorail {
- component: "Internals>Permissions"
-}
-
-team_email: "permissions-dev@chromium.org"
diff --git a/chromium/components/permissions/contexts/OWNERS b/chromium/components/permissions/contexts/OWNERS
deleted file mode 100644
index 399f2b60aaf..00000000000
--- a/chromium/components/permissions/contexts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-file://components/permissions/PERMISSIONS_OWNERS
-
-per-file *webxr_permission_context*=file://content/browser/xr/OWNERS
diff --git a/chromium/components/permissions/contexts/bluetooth_chooser_context.cc b/chromium/components/permissions/contexts/bluetooth_chooser_context.cc
new file mode 100644
index 00000000000..d9018eec79b
--- /dev/null
+++ b/chromium/components/permissions/contexts/bluetooth_chooser_context.cc
@@ -0,0 +1,337 @@
+// Copyright 2019 The Chromium Authors. 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/permissions/contexts/bluetooth_chooser_context.h"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/permissions/permissions_client.h"
+#include "content/public/browser/browser_context.h"
+#include "device/bluetooth/bluetooth_device.h"
+#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
+#include "url/origin.h"
+
+using blink::WebBluetoothDeviceId;
+using device::BluetoothUUID;
+
+namespace permissions {
+
+namespace {
+
+// The Bluetooth device permission objects are dictionary type base::Values. The
+// object contains keys for the device address, device name, services that can
+// be accessed, and the generated web bluetooth device ID. Since base::Value
+// does not have a set type, the services key contains another dictionary type
+// base::Value object where each key is a UUID for a service and the value is a
+// boolean that is never used. This allows for service permissions to be queried
+// quickly and for new service permissions to added without duplicating existing
+// service permissions. The following is an example of how a device permission
+// is formatted using JSON notation:
+// {
+// "device-address": "00:00:00:00:00:00",
+// "name": "Wireless Device",
+// "services": {
+// "0xabcd": "true",
+// "0x1234": "true",
+// },
+// "web-bluetooth-device-id": "4ik7W0WVaGFY6zXxJqdAKw==",
+// }
+constexpr char kDeviceAddressKey[] = "device-address";
+constexpr char kDeviceNameKey[] = "name";
+constexpr char kManufacturerDataKey[] = "manufacturer-data";
+constexpr char kServicesKey[] = "services";
+constexpr char kWebBluetoothDeviceIdKey[] = "web-bluetooth-device-id";
+
+// The Web Bluetooth API spec states that when the user selects a device to
+// pair with the origin, the origin is allowed to access any service listed in
+// |options->filters| and |options->optional_services|.
+// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth
+void AddUnionOfServicesTo(
+ const blink::mojom::WebBluetoothRequestDeviceOptions* options,
+ base::Value* permission_object) {
+ if (!options)
+ return;
+
+ DCHECK(!!permission_object->FindDictKey(kServicesKey));
+ auto& services_dict = *permission_object->FindDictKey(kServicesKey);
+ if (options->filters) {
+ for (const blink::mojom::WebBluetoothLeScanFilterPtr& filter :
+ options->filters.value()) {
+ if (!filter->services)
+ continue;
+
+ for (const BluetoothUUID& uuid : filter->services.value())
+ services_dict.SetBoolKey(uuid.canonical_value(), /*val=*/true);
+ }
+ }
+
+ for (const BluetoothUUID& uuid : options->optional_services)
+ services_dict.SetBoolKey(uuid.canonical_value(), /*val=*/true);
+}
+
+void AddManufacturerDataTo(
+ const blink::mojom::WebBluetoothRequestDeviceOptions* options,
+ base::Value* permission_object) {
+ if (!options || options->optional_manufacturer_data.empty())
+ return;
+
+ base::flat_set<uint16_t> manufacturer_data_set(
+ options->optional_manufacturer_data);
+
+ if (!permission_object->FindListKey(kManufacturerDataKey)) {
+ base::Value manufacturer_data_value(base::Value::Type::LIST);
+ permission_object->SetKey(kManufacturerDataKey,
+ std::move(manufacturer_data_value));
+ }
+
+ auto& manufacturer_data_list =
+ *permission_object->FindListKey(kManufacturerDataKey);
+ for (const auto& manufacturer_data_permission :
+ manufacturer_data_list.GetList()) {
+ manufacturer_data_set.insert(
+ static_cast<uint16_t>(manufacturer_data_permission.GetInt()));
+ }
+
+ manufacturer_data_list.ClearList();
+ for (const uint16_t manufacturer_code : manufacturer_data_set)
+ manufacturer_data_list.Append(manufacturer_code);
+}
+
+base::Value DeviceInfoToDeviceObject(
+ const device::BluetoothDevice* device,
+ const blink::mojom::WebBluetoothRequestDeviceOptions* options,
+ const WebBluetoothDeviceId& device_id) {
+ base::Value device_value(base::Value::Type::DICTIONARY);
+ device_value.SetStringKey(kDeviceAddressKey, device->GetAddress());
+ device_value.SetStringKey(kWebBluetoothDeviceIdKey, device_id.str());
+ device_value.SetStringKey(kDeviceNameKey, device->GetNameForDisplay());
+
+ base::Value services_value(base::Value::Type::DICTIONARY);
+ device_value.SetKey(kServicesKey, std::move(services_value));
+ AddUnionOfServicesTo(options, &device_value);
+
+ base::Value manufacturer_data_value(base::Value::Type::LIST);
+ device_value.SetKey(kManufacturerDataKey, std::move(manufacturer_data_value));
+ AddManufacturerDataTo(options, &device_value);
+
+ return device_value;
+}
+
+} // namespace
+
+BluetoothChooserContext::BluetoothChooserContext(
+ content::BrowserContext* browser_context)
+ : ObjectPermissionContextBase(
+ ContentSettingsType::BLUETOOTH_GUARD,
+ ContentSettingsType::BLUETOOTH_CHOOSER_DATA,
+ PermissionsClient::Get()->GetSettingsMap(browser_context)) {}
+
+BluetoothChooserContext::~BluetoothChooserContext() = default;
+
+WebBluetoothDeviceId BluetoothChooserContext::GetWebBluetoothDeviceId(
+ const url::Origin& origin,
+ const std::string& device_address) {
+ const std::vector<std::unique_ptr<Object>> object_list =
+ GetGrantedObjects(origin);
+ for (const auto& object : object_list) {
+ const base::Value& device = object->value;
+ DCHECK(IsValidObject(device));
+
+ if (device_address == *device.FindStringKey(kDeviceAddressKey)) {
+ return WebBluetoothDeviceId(
+ *device.FindStringKey(kWebBluetoothDeviceIdKey));
+ }
+ }
+
+ // Check if the device has been assigned an ID through an LE scan.
+ auto scanned_devices_it = scanned_devices_.find(origin);
+ if (scanned_devices_it == scanned_devices_.end())
+ return {};
+
+ auto address_to_id_it = scanned_devices_it->second.find(device_address);
+ if (address_to_id_it != scanned_devices_it->second.end())
+ return address_to_id_it->second;
+ return {};
+}
+
+std::string BluetoothChooserContext::GetDeviceAddress(
+ const url::Origin& origin,
+ const WebBluetoothDeviceId& device_id) {
+ base::Value device = FindDeviceObject(origin, device_id);
+ if (!device.is_none())
+ return *device.FindStringKey(kDeviceAddressKey);
+
+ // Check if the device ID corresponds to a device detected via an LE scan.
+ auto scanned_devices_it = scanned_devices_.find(origin);
+ if (scanned_devices_it == scanned_devices_.end())
+ return std::string();
+
+ for (const auto& entry : scanned_devices_it->second) {
+ if (entry.second == device_id)
+ return entry.first;
+ }
+ return std::string();
+}
+
+WebBluetoothDeviceId BluetoothChooserContext::AddScannedDevice(
+ const url::Origin& origin,
+ const std::string& device_address) {
+ // Check if a WebBluetoothDeviceId already exists for the device with
+ // |device_address| for the current origin.
+ const auto granted_id = GetWebBluetoothDeviceId(origin, device_address);
+ if (granted_id.IsValid())
+ return granted_id;
+
+ DeviceAddressToIdMap& address_to_id_map = scanned_devices_[origin];
+ auto scanned_id = WebBluetoothDeviceId::Create();
+ address_to_id_map.emplace(device_address, scanned_id);
+ return scanned_id;
+}
+
+WebBluetoothDeviceId BluetoothChooserContext::GrantServiceAccessPermission(
+ const url::Origin& origin,
+ const device::BluetoothDevice* device,
+ const blink::mojom::WebBluetoothRequestDeviceOptions* options) {
+ // If |origin| already has permission to access the device with
+ // |device_address|, update the allowed GATT services by performing a union of
+ // |services|.
+ const std::vector<std::unique_ptr<Object>> object_list =
+ GetGrantedObjects(origin);
+ const std::string& device_address = device->GetAddress();
+ for (const auto& object : object_list) {
+ base::Value& device_object = object->value;
+ DCHECK(IsValidObject(device_object));
+ if (device_address == *device_object.FindStringKey(kDeviceAddressKey)) {
+ auto new_device_object = device_object.Clone();
+ WebBluetoothDeviceId device_id(
+ *new_device_object.FindStringKey(kWebBluetoothDeviceIdKey));
+
+ AddUnionOfServicesTo(options, &new_device_object);
+ AddManufacturerDataTo(options, &new_device_object);
+ UpdateObjectPermission(origin, device_object,
+ std::move(new_device_object));
+ return device_id;
+ }
+ }
+
+ // If the device has been detected through the Web Bluetooth Scanning API,
+ // grant permission using the WebBluetoothDeviceId generated through that API.
+ // Remove the ID from the temporary |scanned_devices_| map to avoid
+ // duplication, since the ID will now be stored in HostContentSettingsMap.
+ WebBluetoothDeviceId device_id;
+ auto scanned_devices_it = scanned_devices_.find(origin);
+ if (scanned_devices_it != scanned_devices_.end()) {
+ auto& address_to_id_map = scanned_devices_it->second;
+ auto address_to_id_it = address_to_id_map.find(device_address);
+
+ if (address_to_id_it != address_to_id_map.end()) {
+ device_id = address_to_id_it->second;
+ address_to_id_map.erase(address_to_id_it);
+
+ if (scanned_devices_it->second.empty())
+ scanned_devices_.erase(scanned_devices_it);
+ }
+ }
+
+ if (!device_id.IsValid())
+ device_id = WebBluetoothDeviceId::Create();
+
+ base::Value permission_object =
+ DeviceInfoToDeviceObject(device, options, device_id);
+ GrantObjectPermission(origin, std::move(permission_object));
+ return device_id;
+}
+
+bool BluetoothChooserContext::HasDevicePermission(
+ const url::Origin& origin,
+ const WebBluetoothDeviceId& device_id) {
+ base::Value device = FindDeviceObject(origin, device_id);
+ return !device.is_none();
+}
+
+bool BluetoothChooserContext::IsAllowedToAccessAtLeastOneService(
+ const url::Origin& origin,
+ const WebBluetoothDeviceId& device_id) {
+ base::Value device = FindDeviceObject(origin, device_id);
+ if (device.is_none())
+ return false;
+ return !device.FindDictKey(kServicesKey)->DictEmpty();
+}
+
+bool BluetoothChooserContext::IsAllowedToAccessService(
+ const url::Origin& origin,
+ const WebBluetoothDeviceId& device_id,
+ const BluetoothUUID& service) {
+ base::Value device = FindDeviceObject(origin, device_id);
+ if (device.is_none())
+ return false;
+
+ const auto& services_dict = *device.FindDictKey(kServicesKey);
+ return !!services_dict.FindKey(service.canonical_value());
+}
+
+bool BluetoothChooserContext::IsAllowedToAccessManufacturerData(
+ const url::Origin& origin,
+ const WebBluetoothDeviceId& device_id,
+ uint16_t manufacturer_code) {
+ base::Value device = FindDeviceObject(origin, device_id);
+ if (device.is_none())
+ return false;
+
+ const auto* manufacturer_data_list = device.FindListKey(kManufacturerDataKey);
+ if (!manufacturer_data_list)
+ return false;
+
+ for (const auto& manufacturer_data : manufacturer_data_list->GetList()) {
+ if (manufacturer_code == manufacturer_data.GetInt())
+ return true;
+ }
+ return false;
+}
+
+// static
+WebBluetoothDeviceId BluetoothChooserContext::GetObjectDeviceId(
+ const base::Value& object) {
+ std::string device_id_str = *object.FindStringKey(kWebBluetoothDeviceIdKey);
+ return WebBluetoothDeviceId(device_id_str);
+}
+
+bool BluetoothChooserContext::IsValidObject(const base::Value& object) {
+ return object.FindStringKey(kDeviceAddressKey) &&
+ object.FindStringKey(kDeviceNameKey) &&
+ object.FindStringKey(kWebBluetoothDeviceIdKey) &&
+ WebBluetoothDeviceId::IsValid(
+ *object.FindStringKey(kWebBluetoothDeviceIdKey)) &&
+ object.FindDictKey(kServicesKey);
+}
+
+std::u16string BluetoothChooserContext::GetObjectDisplayName(
+ const base::Value& object) {
+ return base::UTF8ToUTF16(*object.FindStringKey(kDeviceNameKey));
+}
+
+base::Value BluetoothChooserContext::FindDeviceObject(
+ const url::Origin& origin,
+ const blink::WebBluetoothDeviceId& device_id) {
+ const std::vector<std::unique_ptr<Object>> object_list =
+ GetGrantedObjects(origin);
+ for (const auto& object : object_list) {
+ base::Value device = std::move(object->value);
+ DCHECK(IsValidObject(device));
+
+ const WebBluetoothDeviceId web_bluetooth_device_id(
+ *device.FindStringKey(kWebBluetoothDeviceIdKey));
+ if (device_id == web_bluetooth_device_id)
+ return device;
+ }
+ return base::Value(base::Value::Type::NONE);
+}
+
+} // namespace permissions
diff --git a/chromium/components/permissions/contexts/bluetooth_chooser_context.h b/chromium/components/permissions/contexts/bluetooth_chooser_context.h
new file mode 100644
index 00000000000..a6a14d1a614
--- /dev/null
+++ b/chromium/components/permissions/contexts/bluetooth_chooser_context.h
@@ -0,0 +1,104 @@
+// Copyright 2019 The Chromium Authors. 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_PERMISSIONS_CONTEXTS_BLUETOOTH_CHOOSER_CONTEXT_H_
+#define COMPONENTS_PERMISSIONS_CONTEXTS_BLUETOOTH_CHOOSER_CONTEXT_H_
+
+#include <map>
+#include <string>
+#include <utility>
+
+#include "base/containers/flat_set.h"
+#include "components/permissions/object_permission_context_base.h"
+#include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-forward.h"
+
+namespace base {
+class Value;
+} // namespace base
+
+namespace content {
+class BrowserContext;
+} // namespace content
+
+namespace device {
+class BluetoothDevice;
+class BluetoothUUID;
+} // namespace device
+
+namespace url {
+class Origin;
+} // namespace url
+
+namespace permissions {
+
+// Manages the permissions for Web Bluetooth device objects. A Web Bluetooth
+// permission object consists of its WebBluetoothDeviceId and set of Bluetooth
+// service UUIDs. The WebBluetoothDeviceId is generated randomly by this class
+// and is unique for a given Bluetooth device address and origin pair, so this
+// class stores this mapping and provides utility methods to convert between
+// the WebBluetoothDeviceId and Bluetooth device address.
+class BluetoothChooserContext : public ObjectPermissionContextBase {
+ public:
+ explicit BluetoothChooserContext(content::BrowserContext* browser_context);
+ ~BluetoothChooserContext() override;
+
+ // Set class as move-only.
+ BluetoothChooserContext(const BluetoothChooserContext&) = delete;
+ BluetoothChooserContext& operator=(const BluetoothChooserContext&) = delete;
+
+ // Helper methods for converting between a WebBluetoothDeviceId and a
+ // Bluetooth device address string for a given origin pair.
+ blink::WebBluetoothDeviceId GetWebBluetoothDeviceId(
+ const url::Origin& origin,
+ const std::string& device_address);
+ std::string GetDeviceAddress(const url::Origin& origin,
+ const blink::WebBluetoothDeviceId& device_id);
+
+ // Bluetooth scanning specific interface for generating WebBluetoothDeviceIds
+ // for scanned devices.
+ blink::WebBluetoothDeviceId AddScannedDevice(
+ const url::Origin& origin,
+ const std::string& device_address);
+
+ // Bluetooth-specific interface for granting and checking permissions.
+ blink::WebBluetoothDeviceId GrantServiceAccessPermission(
+ const url::Origin& origin,
+ const device::BluetoothDevice* device,
+ const blink::mojom::WebBluetoothRequestDeviceOptions* options);
+ bool HasDevicePermission(const url::Origin& origin,
+ const blink::WebBluetoothDeviceId& device_id);
+ bool IsAllowedToAccessAtLeastOneService(
+ const url::Origin& origin,
+ const blink::WebBluetoothDeviceId& device_id);
+ bool IsAllowedToAccessService(const url::Origin& origin,
+ const blink::WebBluetoothDeviceId& device_id,
+ const device::BluetoothUUID& service);
+ bool IsAllowedToAccessManufacturerData(
+ const url::Origin& origin,
+ const blink::WebBluetoothDeviceId& device_id,
+ uint16_t manufacturer_code);
+
+ static blink::WebBluetoothDeviceId GetObjectDeviceId(
+ const base::Value& object);
+
+ // ObjectPermissionContextBase;
+ bool IsValidObject(const base::Value& object) override;
+ std::u16string GetObjectDisplayName(const base::Value& object) override;
+
+ private:
+ base::Value FindDeviceObject(const url::Origin& origin,
+ const blink::WebBluetoothDeviceId& device_id);
+
+ // This map records the generated Web Bluetooth IDs for devices discovered via
+ // the Scanning API. Each requesting/embedding origin pair has its own version
+ // of this map so that IDs cannot be correlated between cross-origin sites.
+ using DeviceAddressToIdMap =
+ std::map<std::string, blink::WebBluetoothDeviceId>;
+ std::map<url::Origin, DeviceAddressToIdMap> scanned_devices_;
+};
+
+} // namespace permissions
+
+#endif // COMPONENTS_PERMISSIONS_CONTEXTS_BLUETOOTH_CHOOSER_CONTEXT_H_
diff --git a/chromium/components/permissions/contexts/file_handling_permission_context.cc b/chromium/components/permissions/contexts/file_handling_permission_context.cc
deleted file mode 100644
index c1f7d2bac79..00000000000
--- a/chromium/components/permissions/contexts/file_handling_permission_context.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/permissions/contexts/file_handling_permission_context.h"
-
-#include "components/content_settings/core/common/content_settings_types.h"
-#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h"
-
-FileHandlingPermissionContext::FileHandlingPermissionContext(
- content::BrowserContext* browser_context)
- : PermissionContextBase(browser_context,
- ContentSettingsType::FILE_HANDLING,
- blink::mojom::PermissionsPolicyFeature::kNotFound) {
-}
-
-FileHandlingPermissionContext::~FileHandlingPermissionContext() = default;
-
-bool FileHandlingPermissionContext::IsRestrictedToSecureOrigins() const {
- return true;
-}
diff --git a/chromium/components/permissions/contexts/file_handling_permission_context.h b/chromium/components/permissions/contexts/file_handling_permission_context.h
deleted file mode 100644
index 16442e79031..00000000000
--- a/chromium/components/permissions/contexts/file_handling_permission_context.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_PERMISSIONS_CONTEXTS_FILE_HANDLING_PERMISSION_CONTEXT_H_
-#define COMPONENTS_PERMISSIONS_CONTEXTS_FILE_HANDLING_PERMISSION_CONTEXT_H_
-
-#include "components/permissions/permission_context_base.h"
-
-class FileHandlingPermissionContext
- : public permissions::PermissionContextBase {
- public:
- explicit FileHandlingPermissionContext(
- content::BrowserContext* browser_context);
- ~FileHandlingPermissionContext() override;
-
- FileHandlingPermissionContext(const FileHandlingPermissionContext&) = delete;
- FileHandlingPermissionContext& operator=(
- const FileHandlingPermissionContext&) = delete;
-
- protected:
- // PermissionContextBase:
- bool IsRestrictedToSecureOrigins() const override;
-};
-
-#endif // COMPONENTS_PERMISSIONS_CONTEXTS_FILE_HANDLING_PERMISSION_CONTEXT_H_
diff --git a/chromium/components/permissions/contexts/geolocation_permission_context_android.h b/chromium/components/permissions/contexts/geolocation_permission_context_android.h
index 5b18bfa9241..e793c5e23cd 100644
--- a/chromium/components/permissions/contexts/geolocation_permission_context_android.h
+++ b/chromium/components/permissions/contexts/geolocation_permission_context_android.h
@@ -24,11 +24,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
#include "components/location/android/location_settings.h"
#include "components/location/android/location_settings_dialog_context.h"
#include "components/location/android/location_settings_dialog_outcome.h"
-#include "components/permissions/contexts//geolocation_permission_context.h"
+#include "components/permissions/contexts/geolocation_permission_context.h"
#include "components/permissions/permission_request_id.h"
namespace content {
diff --git a/chromium/components/permissions/contexts/geolocation_permission_context_unittest.cc b/chromium/components/permissions/contexts/geolocation_permission_context_unittest.cc
index c82e785c39d..b15391a8a23 100644
--- a/chromium/components/permissions/contexts/geolocation_permission_context_unittest.cc
+++ b/chromium/components/permissions/contexts/geolocation_permission_context_unittest.cc
@@ -112,7 +112,7 @@ class TestGeolocationPermissionContextDelegate
private:
TestingPrefServiceSimple prefs_;
- base::Optional<url::Origin> dse_origin_;
+ absl::optional<url::Origin> dse_origin_;
};
} // namespace
@@ -424,8 +424,12 @@ std::u16string GeolocationPermissionContextTests::GetPromptText() {
PermissionRequestManager* manager =
PermissionRequestManager::FromWebContents(web_contents());
PermissionRequest* request = manager->Requests().front();
+#if defined(OS_ANDROID)
+ return request->GetMessageText();
+#else
return base::ASCIIToUTF16(request->GetOrigin().spec()) +
request->GetMessageTextFragment();
+#endif
}
// Tests ----------------------------------------------------------------------
diff --git a/chromium/components/permissions/contexts/midi_permission_context.cc b/chromium/components/permissions/contexts/midi_permission_context.cc
new file mode 100644
index 00000000000..ad30cba6540
--- /dev/null
+++ b/chromium/components/permissions/contexts/midi_permission_context.cc
@@ -0,0 +1,33 @@
+// 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/permissions/contexts/midi_permission_context.h"
+
+#include "components/content_settings/core/common/content_settings.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom.h"
+
+namespace permissions {
+
+MidiPermissionContext::MidiPermissionContext(
+ content::BrowserContext* browser_context)
+ : PermissionContextBase(
+ browser_context,
+ ContentSettingsType::MIDI,
+ blink::mojom::PermissionsPolicyFeature::kMidiFeature) {}
+
+MidiPermissionContext::~MidiPermissionContext() = default;
+
+ContentSetting MidiPermissionContext::GetPermissionStatusInternal(
+ content::RenderFrameHost* render_frame_host,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) const {
+ return CONTENT_SETTING_ALLOW;
+}
+
+bool MidiPermissionContext::IsRestrictedToSecureOrigins() const {
+ return true;
+}
+
+} // namespace permissions
diff --git a/chromium/components/permissions/contexts/midi_permission_context.h b/chromium/components/permissions/contexts/midi_permission_context.h
new file mode 100644
index 00000000000..d677403c583
--- /dev/null
+++ b/chromium/components/permissions/contexts/midi_permission_context.h
@@ -0,0 +1,34 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERMISSIONS_CONTEXTS_MIDI_PERMISSION_CONTEXT_H_
+#define COMPONENTS_PERMISSIONS_CONTEXTS_MIDI_PERMISSION_CONTEXT_H_
+
+#include "components/permissions/permission_context_base.h"
+
+namespace content {
+class BrowserContext;
+} // namespace content
+
+namespace permissions {
+
+class MidiPermissionContext : public PermissionContextBase {
+ public:
+ explicit MidiPermissionContext(content::BrowserContext* browser_context);
+ MidiPermissionContext(const MidiPermissionContext&) = delete;
+ MidiPermissionContext& operator=(const MidiPermissionContext&) = delete;
+ ~MidiPermissionContext() override;
+
+ private:
+ // PermissionContextBase:
+ ContentSetting GetPermissionStatusInternal(
+ content::RenderFrameHost* render_frame_host,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin) const override;
+ bool IsRestrictedToSecureOrigins() const override;
+};
+
+} // namespace permissions
+
+#endif // COMPONENTS_PERMISSIONS_CONTEXTS_MIDI_PERMISSION_CONTEXT_H_
diff --git a/chromium/components/permissions/contexts/midi_permission_context_unittest.cc b/chromium/components/permissions/contexts/midi_permission_context_unittest.cc
new file mode 100644
index 00000000000..707fe5af9cf
--- /dev/null
+++ b/chromium/components/permissions/contexts/midi_permission_context_unittest.cc
@@ -0,0 +1,50 @@
+// 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/permissions/contexts/midi_permission_context.h"
+
+#include "components/content_settings/core/common/content_settings.h"
+#include "components/permissions/test/test_permissions_client.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_browser_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace permissions {
+
+class MidiPermissionContextTests : public testing::Test {
+ public:
+ content::TestBrowserContext* browser_context() { return &browser_context_; }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ content::TestBrowserContext browser_context_;
+ TestPermissionsClient client_;
+};
+
+// Web MIDI permission status should be allowed only for secure origins.
+TEST_F(MidiPermissionContextTests, TestNoSysexAllowedAllOrigins) {
+ MidiPermissionContext permission_context(browser_context());
+ GURL insecure_url("http://www.example.com");
+ GURL secure_url("https://www.example.com");
+
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ permission_context
+ .GetPermissionStatus(nullptr /* render_frame_host */,
+ insecure_url, insecure_url)
+ .content_setting);
+
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ permission_context
+ .GetPermissionStatus(nullptr /* render_frame_host */,
+ insecure_url, secure_url)
+ .content_setting);
+
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ permission_context
+ .GetPermissionStatus(nullptr /* render_frame_host */,
+ secure_url, secure_url)
+ .content_setting);
+}
+
+} // namespace permissions
diff --git a/chromium/components/permissions/contexts/midi_sysex_permission_context.cc b/chromium/components/permissions/contexts/midi_sysex_permission_context.cc
new file mode 100644
index 00000000000..166a2306c02
--- /dev/null
+++ b/chromium/components/permissions/contexts/midi_sysex_permission_context.cc
@@ -0,0 +1,49 @@
+// 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/permissions/contexts/midi_sysex_permission_context.h"
+
+#include "components/content_settings/browser/page_specific_content_settings.h"
+#include "components/content_settings/core/common/content_settings.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/permissions/permission_request_id.h"
+#include "content/public/browser/child_process_security_policy.h"
+#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom.h"
+#include "url/gurl.h"
+
+namespace permissions {
+
+MidiSysexPermissionContext::MidiSysexPermissionContext(
+ content::BrowserContext* browser_context)
+ : PermissionContextBase(
+ browser_context,
+ ContentSettingsType::MIDI_SYSEX,
+ blink::mojom::PermissionsPolicyFeature::kMidiFeature) {}
+
+MidiSysexPermissionContext::~MidiSysexPermissionContext() = default;
+
+void MidiSysexPermissionContext::UpdateTabContext(const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ bool allowed) {
+ content_settings::PageSpecificContentSettings* content_settings =
+ content_settings::PageSpecificContentSettings::GetForFrame(
+ id.render_process_id(), id.render_frame_id());
+ if (!content_settings)
+ return;
+
+ if (allowed) {
+ content_settings->OnContentAllowed(ContentSettingsType::MIDI_SYSEX);
+
+ content::ChildProcessSecurityPolicy::GetInstance()
+ ->GrantSendMidiSysExMessage(id.render_process_id());
+ } else {
+ content_settings->OnContentBlocked(ContentSettingsType::MIDI_SYSEX);
+ }
+}
+
+bool MidiSysexPermissionContext::IsRestrictedToSecureOrigins() const {
+ return true;
+}
+
+} // namespace permissions
diff --git a/chromium/components/permissions/contexts/midi_sysex_permission_context.h b/chromium/components/permissions/contexts/midi_sysex_permission_context.h
new file mode 100644
index 00000000000..c5ac9b68120
--- /dev/null
+++ b/chromium/components/permissions/contexts/midi_sysex_permission_context.h
@@ -0,0 +1,34 @@
+// 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_PERMISSIONS_CONTEXTS_MIDI_SYSEX_PERMISSION_CONTEXT_H_
+#define COMPONENTS_PERMISSIONS_CONTEXTS_MIDI_SYSEX_PERMISSION_CONTEXT_H_
+
+#include "components/permissions/permission_context_base.h"
+
+namespace content {
+class BrowserContext;
+} // namespace content
+
+namespace permissions {
+
+class MidiSysexPermissionContext : public PermissionContextBase {
+ public:
+ explicit MidiSysexPermissionContext(content::BrowserContext* browser_context);
+ MidiSysexPermissionContext(const MidiSysexPermissionContext&) = delete;
+ MidiSysexPermissionContext& operator=(const MidiSysexPermissionContext&) =
+ delete;
+ ~MidiSysexPermissionContext() override;
+
+ private:
+ // PermissionContextBase:
+ void UpdateTabContext(const PermissionRequestID& id,
+ const GURL& requesting_frame,
+ bool allowed) override;
+ bool IsRestrictedToSecureOrigins() const override;
+};
+
+} // namespace permissions
+
+#endif // COMPONENTS_PERMISSIONS_CONTEXTS_MIDI_SYSEX_PERMISSION_CONTEXT_H_
diff --git a/chromium/components/permissions/contexts/midi_sysex_permission_context_unittest.cc b/chromium/components/permissions/contexts/midi_sysex_permission_context_unittest.cc
new file mode 100644
index 00000000000..19efad6e644
--- /dev/null
+++ b/chromium/components/permissions/contexts/midi_sysex_permission_context_unittest.cc
@@ -0,0 +1,138 @@
+// 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/permissions/contexts/midi_sysex_permission_context.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/common/content_settings.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/permissions/permission_request_id.h"
+#include "components/permissions/test/test_permissions_client.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_renderer_host.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace permissions {
+
+namespace {
+
+class TestPermissionContext : public MidiSysexPermissionContext {
+ public:
+ explicit TestPermissionContext(content::BrowserContext* browser_context)
+ : MidiSysexPermissionContext(browser_context),
+ permission_set_(false),
+ permission_granted_(false),
+ tab_context_updated_(false) {}
+
+ ~TestPermissionContext() override = default;
+
+ bool permission_granted() { return permission_granted_; }
+
+ bool permission_set() { return permission_set_; }
+
+ bool tab_context_updated() { return tab_context_updated_; }
+
+ void TrackPermissionDecision(ContentSetting content_setting) {
+ permission_set_ = true;
+ permission_granted_ = content_setting == CONTENT_SETTING_ALLOW;
+ }
+
+ protected:
+ void UpdateTabContext(const PermissionRequestID& id,
+ const GURL& requesting_origin,
+ bool allowed) override {
+ tab_context_updated_ = true;
+ }
+
+ private:
+ bool permission_set_;
+ bool permission_granted_;
+ bool tab_context_updated_;
+};
+
+} // namespace
+
+class MidiSysexPermissionContextTests
+ : public content::RenderViewHostTestHarness {
+ protected:
+ MidiSysexPermissionContextTests() = default;
+ ~MidiSysexPermissionContextTests() override = default;
+
+ private:
+ TestPermissionsClient client_;
+};
+
+// Web MIDI sysex permission should be denied for insecure origin.
+TEST_F(MidiSysexPermissionContextTests, TestInsecureRequestingUrl) {
+ TestPermissionContext permission_context(browser_context());
+ GURL url("http://www.example.com");
+ content::WebContentsTester::For(web_contents())->NavigateAndCommit(url);
+
+ const PermissionRequestID id(
+ web_contents()->GetMainFrame()->GetProcess()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(),
+ permissions::PermissionRequestID::RequestLocalId());
+ permission_context.RequestPermission(
+ web_contents(), id, url, true,
+ base::BindOnce(&TestPermissionContext::TrackPermissionDecision,
+ base::Unretained(&permission_context)));
+
+ EXPECT_TRUE(permission_context.permission_set());
+ EXPECT_FALSE(permission_context.permission_granted());
+ EXPECT_TRUE(permission_context.tab_context_updated());
+
+ ContentSetting setting =
+ PermissionsClient::Get()
+ ->GetSettingsMap(browser_context())
+ ->GetContentSetting(url.GetOrigin(), url.GetOrigin(),
+ ContentSettingsType::MIDI_SYSEX);
+ EXPECT_EQ(CONTENT_SETTING_ASK, setting);
+}
+
+// Web MIDI sysex permission status should be denied for insecure origin.
+TEST_F(MidiSysexPermissionContextTests, TestInsecureQueryingUrl) {
+ TestPermissionContext permission_context(browser_context());
+ GURL insecure_url("http://www.example.com");
+ GURL secure_url("https://www.example.com");
+
+ // Check that there is no saved content settings.
+ EXPECT_EQ(CONTENT_SETTING_ASK,
+ PermissionsClient::Get()
+ ->GetSettingsMap(browser_context())
+ ->GetContentSetting(insecure_url.GetOrigin(),
+ insecure_url.GetOrigin(),
+ ContentSettingsType::MIDI_SYSEX));
+ EXPECT_EQ(
+ CONTENT_SETTING_ASK,
+ PermissionsClient::Get()
+ ->GetSettingsMap(browser_context())
+ ->GetContentSetting(secure_url.GetOrigin(), insecure_url.GetOrigin(),
+ ContentSettingsType::MIDI_SYSEX));
+ EXPECT_EQ(
+ CONTENT_SETTING_ASK,
+ PermissionsClient::Get()
+ ->GetSettingsMap(browser_context())
+ ->GetContentSetting(insecure_url.GetOrigin(), secure_url.GetOrigin(),
+ ContentSettingsType::MIDI_SYSEX));
+
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ permission_context
+ .GetPermissionStatus(nullptr /* render_frame_host */,
+ insecure_url, insecure_url)
+ .content_setting);
+
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ permission_context
+ .GetPermissionStatus(nullptr /* render_frame_host */,
+ insecure_url, secure_url)
+ .content_setting);
+}
+
+} // namespace permissions
diff --git a/chromium/components/permissions/fake_bluetooth_chooser_controller.cc b/chromium/components/permissions/fake_bluetooth_chooser_controller.cc
new file mode 100644
index 00000000000..3e7976d14f6
--- /dev/null
+++ b/chromium/components/permissions/fake_bluetooth_chooser_controller.cc
@@ -0,0 +1,105 @@
+// 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/permissions/fake_bluetooth_chooser_controller.h"
+
+#include "base/check_op.h"
+#include "base/notreached.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace permissions {
+
+FakeBluetoothChooserController::FakeBluetoothChooserController(
+ std::vector<FakeDevice> devices)
+ : ChooserController(
+ l10n_util::GetStringFUTF16(IDS_BLUETOOTH_DEVICE_CHOOSER_PROMPT_ORIGIN,
+ u"example.com")),
+ devices_(std::move(devices)) {}
+
+FakeBluetoothChooserController::~FakeBluetoothChooserController() {}
+
+bool FakeBluetoothChooserController::ShouldShowIconBeforeText() const {
+ return true;
+}
+
+bool FakeBluetoothChooserController::ShouldShowReScanButton() const {
+ return true;
+}
+
+std::u16string FakeBluetoothChooserController::GetNoOptionsText() const {
+ return l10n_util::GetStringUTF16(
+ IDS_BLUETOOTH_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT);
+}
+
+std::u16string FakeBluetoothChooserController::GetOkButtonLabel() const {
+ return l10n_util::GetStringUTF16(
+ IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT);
+}
+
+std::pair<std::u16string, std::u16string>
+FakeBluetoothChooserController::GetThrobberLabelAndTooltip() const {
+ return {
+ l10n_util::GetStringUTF16(IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL),
+ l10n_util::GetStringUTF16(
+ IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL_TOOLTIP)};
+}
+
+bool FakeBluetoothChooserController::TableViewAlwaysDisabled() const {
+ return table_view_always_disabled_;
+}
+
+size_t FakeBluetoothChooserController::NumOptions() const {
+ return devices_.size();
+}
+
+int FakeBluetoothChooserController::GetSignalStrengthLevel(size_t index) const {
+ return devices_.at(index).signal_strength;
+}
+
+std::u16string FakeBluetoothChooserController::GetOption(size_t index) const {
+ return base::ASCIIToUTF16(devices_.at(index).name);
+}
+
+bool FakeBluetoothChooserController::IsConnected(size_t index) const {
+ return devices_.at(index).connected;
+}
+
+bool FakeBluetoothChooserController::IsPaired(size_t index) const {
+ return devices_.at(index).paired;
+}
+
+void FakeBluetoothChooserController::SetBluetoothStatus(
+ BluetoothStatus status) {
+ const bool available = status != BluetoothStatus::UNAVAILABLE;
+ view()->OnAdapterEnabledChanged(available);
+ if (available)
+ view()->OnRefreshStateChanged(status == BluetoothStatus::SCANNING);
+}
+
+void FakeBluetoothChooserController::SetBluetoothPermission(
+ bool has_permission) {
+ view()->OnAdapterAuthorizationChanged(has_permission);
+}
+
+void FakeBluetoothChooserController::AddDevice(FakeDevice device) {
+ devices_.push_back(device);
+ view()->OnOptionAdded(devices_.size() - 1);
+}
+
+void FakeBluetoothChooserController::RemoveDevice(size_t index) {
+ DCHECK_GT(devices_.size(), index);
+ devices_.erase(devices_.begin() + index);
+ view()->OnOptionRemoved(index);
+}
+
+void FakeBluetoothChooserController::UpdateDevice(size_t index,
+ FakeDevice new_device) {
+ DCHECK_GT(devices_.size(), index);
+ devices_[index] = new_device;
+ view()->OnOptionUpdated(index);
+}
+
+} // namespace permissions
diff --git a/chromium/components/permissions/fake_bluetooth_chooser_controller.h b/chromium/components/permissions/fake_bluetooth_chooser_controller.h
new file mode 100644
index 00000000000..c548595d1d7
--- /dev/null
+++ b/chromium/components/permissions/fake_bluetooth_chooser_controller.h
@@ -0,0 +1,92 @@
+// 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_PERMISSIONS_FAKE_BLUETOOTH_CHOOSER_CONTROLLER_H_
+#define COMPONENTS_PERMISSIONS_FAKE_BLUETOOTH_CHOOSER_CONTROLLER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "components/permissions/chooser_controller.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace permissions {
+
+// A subclass of ChooserController that pretends to be a Bluetooth device
+// chooser for testing. The result should be visually similar to the real
+// version of the dialog for interactive tests.
+class FakeBluetoothChooserController : public ChooserController {
+ public:
+ enum class BluetoothStatus {
+ UNAVAILABLE,
+ IDLE,
+ SCANNING,
+ };
+
+ enum ConnectionStatus {
+ NOT_CONNECTED = false,
+ CONNECTED = true,
+ };
+
+ enum PairStatus {
+ NOT_PAIRED = false,
+ PAIRED = true,
+ };
+
+ static constexpr int kSignalStrengthUnknown = -1;
+ static constexpr int kSignalStrengthLevel0 = 0;
+ static constexpr int kSignalStrengthLevel1 = 1;
+ static constexpr int kSignalStrengthLevel2 = 2;
+ static constexpr int kSignalStrengthLevel3 = 3;
+ static constexpr int kSignalStrengthLevel4 = 4;
+
+ struct FakeDevice {
+ std::string name;
+ bool connected;
+ bool paired;
+ int signal_strength;
+ };
+
+ explicit FakeBluetoothChooserController(std::vector<FakeDevice> devices = {});
+ ~FakeBluetoothChooserController() override;
+
+ // ChooserController:
+ bool ShouldShowIconBeforeText() const override;
+ bool ShouldShowReScanButton() const override;
+ std::u16string GetNoOptionsText() const override;
+ std::u16string GetOkButtonLabel() const override;
+ std::pair<std::u16string, std::u16string> GetThrobberLabelAndTooltip()
+ const override;
+ bool TableViewAlwaysDisabled() const override;
+ size_t NumOptions() const override;
+ int GetSignalStrengthLevel(size_t index) const override;
+ std::u16string GetOption(size_t index) const override;
+ bool IsConnected(size_t index) const override;
+ bool IsPaired(size_t index) const override;
+ MOCK_METHOD0(RefreshOptions, void());
+ MOCK_METHOD1(Select, void(const std::vector<size_t>& indices));
+ MOCK_METHOD0(Cancel, void());
+ MOCK_METHOD0(Close, void());
+ MOCK_CONST_METHOD0(OpenHelpCenterUrl, void());
+ MOCK_CONST_METHOD0(OpenAdapterOffHelpUrl, void());
+
+ void SetBluetoothStatus(BluetoothStatus status);
+ void SetBluetoothPermission(bool has_permission);
+ void AddDevice(FakeDevice device);
+ void RemoveDevice(size_t index);
+ void UpdateDevice(size_t index, FakeDevice new_device);
+ void set_table_view_always_disabled(bool table_view_always_disabled) {
+ table_view_always_disabled_ = table_view_always_disabled;
+ }
+
+ private:
+ std::vector<FakeDevice> devices_;
+ bool table_view_always_disabled_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeBluetoothChooserController);
+};
+
+} // namespace permissions
+
+#endif // COMPONENTS_PERMISSIONS_FAKE_BLUETOOTH_CHOOSER_CONTROLLER_H_
diff --git a/chromium/components/permissions/fake_usb_chooser_controller.cc b/chromium/components/permissions/fake_usb_chooser_controller.cc
new file mode 100644
index 00000000000..1eae4ea1138
--- /dev/null
+++ b/chromium/components/permissions/fake_usb_chooser_controller.cc
@@ -0,0 +1,39 @@
+// 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/permissions/fake_usb_chooser_controller.h"
+
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+FakeUsbChooserController::FakeUsbChooserController(int device_count)
+ : ChooserController(u""), device_count_(device_count) {
+ set_title_for_testing(l10n_util::GetStringFUTF16(
+ IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN, u"example.com"));
+}
+
+std::u16string FakeUsbChooserController::GetNoOptionsText() const {
+ return l10n_util::GetStringUTF16(IDS_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT);
+}
+
+std::u16string FakeUsbChooserController::GetOkButtonLabel() const {
+ return l10n_util::GetStringUTF16(IDS_USB_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT);
+}
+
+std::pair<std::u16string, std::u16string>
+FakeUsbChooserController::GetThrobberLabelAndTooltip() const {
+ return {
+ l10n_util::GetStringUTF16(IDS_USB_DEVICE_CHOOSER_LOADING_LABEL),
+ l10n_util::GetStringUTF16(IDS_USB_DEVICE_CHOOSER_LOADING_LABEL_TOOLTIP)};
+}
+
+size_t FakeUsbChooserController::NumOptions() const {
+ return device_count_;
+}
+
+std::u16string FakeUsbChooserController::GetOption(size_t index) const {
+ return base::ASCIIToUTF16(base::StringPrintf("Device #%zu", index));
+}
diff --git a/chromium/components/permissions/fake_usb_chooser_controller.h b/chromium/components/permissions/fake_usb_chooser_controller.h
new file mode 100644
index 00000000000..214541d3c4b
--- /dev/null
+++ b/chromium/components/permissions/fake_usb_chooser_controller.h
@@ -0,0 +1,42 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERMISSIONS_FAKE_USB_CHOOSER_CONTROLLER_H_
+#define COMPONENTS_PERMISSIONS_FAKE_USB_CHOOSER_CONTROLLER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "components/permissions/chooser_controller.h"
+
+// A subclass of permissions::ChooserController that pretends to be a USB device
+// chooser for testing. The result should be visually similar to the real
+// version of the dialog for interactive tests.
+class FakeUsbChooserController : public permissions::ChooserController {
+ public:
+ explicit FakeUsbChooserController(int device_count);
+
+ // permissions::ChooserController:
+ std::u16string GetNoOptionsText() const override;
+ std::u16string GetOkButtonLabel() const override;
+ std::pair<std::u16string, std::u16string> GetThrobberLabelAndTooltip()
+ const override;
+ size_t NumOptions() const override;
+ std::u16string GetOption(size_t index) const override;
+ void Select(const std::vector<size_t>& indices) override {}
+ void Cancel() override {}
+ void Close() override {}
+ void OpenHelpCenterUrl() const override {}
+
+ void set_device_count(size_t device_count) { device_count_ = device_count; }
+
+ private:
+ // The number of fake devices to include in the chooser. Names are generated
+ // for them.
+ size_t device_count_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeUsbChooserController);
+};
+
+#endif // COMPONENTS_PERMISSIONS_FAKE_USB_CHOOSER_CONTROLLER_H_
diff --git a/chromium/components/permissions/features.cc b/chromium/components/permissions/features.cc
index d48e35a77ec..744b7645af8 100644
--- a/chromium/components/permissions/features.cc
+++ b/chromium/components/permissions/features.cc
@@ -50,6 +50,13 @@ const base::Feature kPermissionPredictionServiceUseUrlOverride{
"kPermissionPredictionServiceUseUrlOverride",
base::FEATURE_DISABLED_BY_DEFAULT};
+#if defined(OS_ANDROID)
+// When enabled, the Default Search Engine does not automatically receive the
+// "geolocation" and "notifications" permissions. DSE only applies to Android.
+const base::Feature kRevertDSEAutomaticPermissions{
+ "RevertDSEAutomaticPermissions", base::FEATURE_DISABLED_BY_DEFAULT};
+#endif // defined(OS_ANDROID)
+
} // namespace features
namespace feature_params {
diff --git a/chromium/components/permissions/features.h b/chromium/components/permissions/features.h
index e0a40747c9f..3b4485c0ae3 100644
--- a/chromium/components/permissions/features.h
+++ b/chromium/components/permissions/features.h
@@ -5,7 +5,10 @@
#ifndef COMPONENTS_PERMISSIONS_FEATURES_H_
#define COMPONENTS_PERMISSIONS_FEATURES_H_
+#include "base/component_export.h"
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
+#include "build/build_config.h"
namespace permissions {
namespace features {
@@ -19,6 +22,11 @@ extern const base::Feature kPermissionChipGestureSensitive;
extern const base::Feature kPermissionChipRequestTypeSensitive;
extern const base::Feature kPermissionPredictionServiceUseUrlOverride;
+#if defined(OS_ANDROID)
+COMPONENT_EXPORT(PERMISSIONS_COMMON)
+extern const base::Feature kRevertDSEAutomaticPermissions;
+#endif // defined(OS_ANDROID)
+
} // namespace features
namespace feature_params {
diff --git a/chromium/components/permissions/mock_chooser_controller_view.cc b/chromium/components/permissions/mock_chooser_controller_view.cc
new file mode 100644
index 00000000000..83cca97abb3
--- /dev/null
+++ b/chromium/components/permissions/mock_chooser_controller_view.cc
@@ -0,0 +1,13 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/permissions/mock_chooser_controller_view.h"
+
+namespace permissions {
+
+MockChooserControllerView::MockChooserControllerView() = default;
+
+MockChooserControllerView::~MockChooserControllerView() = default;
+
+} // namespace permissions
diff --git a/chromium/components/permissions/mock_chooser_controller_view.h b/chromium/components/permissions/mock_chooser_controller_view.h
new file mode 100644
index 00000000000..d1770ccad21
--- /dev/null
+++ b/chromium/components/permissions/mock_chooser_controller_view.h
@@ -0,0 +1,32 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERMISSIONS_MOCK_CHOOSER_CONTROLLER_VIEW_H_
+#define COMPONENTS_PERMISSIONS_MOCK_CHOOSER_CONTROLLER_VIEW_H_
+
+#include "components/permissions/chooser_controller.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace permissions {
+
+class MockChooserControllerView : public ChooserController::View {
+ public:
+ MockChooserControllerView();
+ MockChooserControllerView(MockChooserControllerView&) = delete;
+ MockChooserControllerView& operator=(MockChooserControllerView&) = delete;
+ ~MockChooserControllerView() override;
+
+ // ChooserController::View
+ MOCK_METHOD0(OnOptionsInitialized, void());
+ MOCK_METHOD1(OnOptionAdded, void(size_t index));
+ MOCK_METHOD1(OnOptionRemoved, void(size_t index));
+ MOCK_METHOD1(OnOptionUpdated, void(size_t index));
+ MOCK_METHOD1(OnAdapterEnabledChanged, void(bool enabled));
+ MOCK_METHOD1(OnRefreshStateChanged, void(bool enabled));
+};
+
+} // namespace permissions
+
+#endif // COMPONENTS_PERMISSIONS_MOCK_CHOOSER_CONTROLLER_VIEW_H_
diff --git a/chromium/components/permissions/notification_permission_ui_selector.cc b/chromium/components/permissions/notification_permission_ui_selector.cc
deleted file mode 100644
index f1764c9614f..00000000000
--- a/chromium/components/permissions/notification_permission_ui_selector.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/permissions/notification_permission_ui_selector.h"
-#include "base/optional.h"
-
-namespace permissions {
-
-// static
-bool NotificationPermissionUiSelector::ShouldSuppressAnimation(
- base::Optional<QuietUiReason> reason) {
- if (!reason)
- return true;
-
- switch (*reason) {
- case QuietUiReason::kEnabledInPrefs:
- case QuietUiReason::kPredictedVeryUnlikelyGrant:
- return false;
- case QuietUiReason::kTriggeredByCrowdDeny:
- case QuietUiReason::kTriggeredDueToAbusiveRequests:
- case QuietUiReason::kTriggeredDueToAbusiveContent:
- return true;
- }
-}
-
-NotificationPermissionUiSelector::Decision::Decision(
- base::Optional<QuietUiReason> quiet_ui_reason,
- base::Optional<WarningReason> warning_reason)
- : quiet_ui_reason(quiet_ui_reason), warning_reason(warning_reason) {}
-NotificationPermissionUiSelector::Decision::~Decision() = default;
-
-NotificationPermissionUiSelector::Decision::Decision(const Decision&) = default;
-NotificationPermissionUiSelector::Decision&
-NotificationPermissionUiSelector::Decision::operator=(const Decision&) =
- default;
-
-// static
-NotificationPermissionUiSelector::Decision
-NotificationPermissionUiSelector::Decision::UseNormalUiAndShowNoWarning() {
- return Decision(UseNormalUi(), ShowNoWarning());
-}
-
-base::Optional<PermissionUmaUtil::PredictionGrantLikelihood>
-NotificationPermissionUiSelector::PredictedGrantLikelihoodForUKM() {
- return base::nullopt;
-}
-
-} // namespace permissions
diff --git a/chromium/components/permissions/chooser_context_base.cc b/chromium/components/permissions/object_permission_context_base.cc
index bf6c91f92e3..f033da9ef9b 100644
--- a/chromium/components/permissions/chooser_context_base.cc
+++ b/chromium/components/permissions/object_permission_context_base.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/permissions/chooser_context_base.h"
+#include "components/permissions/object_permission_context_base.h"
#include <utility>
@@ -16,9 +16,9 @@ namespace permissions {
const char kObjectListKey[] = "chosen-objects";
-ChooserContextBase::ChooserContextBase(
- const ContentSettingsType guard_content_settings_type,
- const ContentSettingsType data_content_settings_type,
+ObjectPermissionContextBase::ObjectPermissionContextBase(
+ ContentSettingsType guard_content_settings_type,
+ ContentSettingsType data_content_settings_type,
HostContentSettingsMap* host_content_settings_map)
: guard_content_settings_type_(guard_content_settings_type),
data_content_settings_type_(data_content_settings_type),
@@ -26,46 +26,60 @@ ChooserContextBase::ChooserContextBase(
DCHECK(host_content_settings_map_);
}
-ChooserContextBase::~ChooserContextBase() = default;
+ObjectPermissionContextBase::ObjectPermissionContextBase(
+ ContentSettingsType data_content_settings_type,
+ HostContentSettingsMap* host_content_settings_map)
+ : guard_content_settings_type_(absl::nullopt),
+ data_content_settings_type_(data_content_settings_type),
+ host_content_settings_map_(host_content_settings_map) {
+ DCHECK(host_content_settings_map_);
+}
+
+ObjectPermissionContextBase::~ObjectPermissionContextBase() = default;
-ChooserContextBase::Object::Object(const url::Origin& origin,
- base::Value value,
- content_settings::SettingSource source,
- bool incognito)
+ObjectPermissionContextBase::Object::Object(
+ const url::Origin& origin,
+ base::Value value,
+ content_settings::SettingSource source,
+ bool incognito)
: origin(origin.GetURL()),
value(std::move(value)),
source(source),
incognito(incognito) {}
-ChooserContextBase::Object::~Object() = default;
+ObjectPermissionContextBase::Object::~Object() = default;
-void ChooserContextBase::PermissionObserver::OnChooserObjectPermissionChanged(
- ContentSettingsType data_content_settings_type,
- ContentSettingsType guard_content_settings_type) {}
+void ObjectPermissionContextBase::PermissionObserver::OnObjectPermissionChanged(
+ absl::optional<ContentSettingsType> guard_content_settings_type,
+ ContentSettingsType data_content_settings_type) {}
-void ChooserContextBase::PermissionObserver::OnPermissionRevoked(
+void ObjectPermissionContextBase::PermissionObserver::OnPermissionRevoked(
const url::Origin& origin) {}
-void ChooserContextBase::AddObserver(PermissionObserver* observer) {
+void ObjectPermissionContextBase::AddObserver(PermissionObserver* observer) {
permission_observer_list_.AddObserver(observer);
}
-void ChooserContextBase::RemoveObserver(PermissionObserver* observer) {
+void ObjectPermissionContextBase::RemoveObserver(PermissionObserver* observer) {
permission_observer_list_.RemoveObserver(observer);
}
-bool ChooserContextBase::CanRequestObjectPermission(const url::Origin& origin) {
+bool ObjectPermissionContextBase::CanRequestObjectPermission(
+ const url::Origin& origin) {
+ if (!guard_content_settings_type_)
+ return true;
+
ContentSetting content_setting =
host_content_settings_map_->GetContentSetting(
- origin.GetURL(), GURL(), guard_content_settings_type_);
+ origin.GetURL(), GURL(), *guard_content_settings_type_);
DCHECK(content_setting == CONTENT_SETTING_ASK ||
content_setting == CONTENT_SETTING_BLOCK);
return content_setting == CONTENT_SETTING_ASK;
}
-std::unique_ptr<ChooserContextBase::Object>
-ChooserContextBase::GetGrantedObject(const url::Origin& origin,
- const base::StringPiece key) {
+std::unique_ptr<ObjectPermissionContextBase::Object>
+ObjectPermissionContextBase::GetGrantedObject(const url::Origin& origin,
+ const base::StringPiece key) {
if (!CanRequestObjectPermission(origin))
return nullptr;
@@ -86,8 +100,8 @@ ChooserContextBase::GetGrantedObject(const url::Origin& origin,
return nullptr;
}
-std::vector<std::unique_ptr<ChooserContextBase::Object>>
-ChooserContextBase::GetGrantedObjects(const url::Origin& origin) {
+std::vector<std::unique_ptr<ObjectPermissionContextBase::Object>>
+ObjectPermissionContextBase::GetGrantedObjects(const url::Origin& origin) {
if (!CanRequestObjectPermission(origin))
return {};
@@ -109,8 +123,8 @@ ChooserContextBase::GetGrantedObjects(const url::Origin& origin) {
return results;
}
-std::vector<std::unique_ptr<ChooserContextBase::Object>>
-ChooserContextBase::GetAllGrantedObjects() {
+std::vector<std::unique_ptr<ObjectPermissionContextBase::Object>>
+ObjectPermissionContextBase::GetAllGrantedObjects() {
ContentSettingsForOneType content_settings;
host_content_settings_map_->GetSettingsForOneType(data_content_settings_type_,
&content_settings);
@@ -150,8 +164,9 @@ ChooserContextBase::GetAllGrantedObjects() {
return results;
}
-void ChooserContextBase::GrantObjectPermission(const url::Origin& origin,
- base::Value object) {
+void ObjectPermissionContextBase::GrantObjectPermission(
+ const url::Origin& origin,
+ base::Value object) {
DCHECK(IsValidObject(object));
base::Value setting = GetWebsiteSetting(origin, /*info=*/nullptr);
@@ -185,9 +200,10 @@ void ChooserContextBase::GrantObjectPermission(const url::Origin& origin,
NotifyPermissionChanged();
}
-void ChooserContextBase::UpdateObjectPermission(const url::Origin& origin,
- const base::Value& old_object,
- base::Value new_object) {
+void ObjectPermissionContextBase::UpdateObjectPermission(
+ const url::Origin& origin,
+ const base::Value& old_object,
+ base::Value new_object) {
base::Value setting = GetWebsiteSetting(origin, /*info=*/nullptr);
base::Value* objects = setting.FindListKey(kObjectListKey);
if (!objects)
@@ -203,8 +219,9 @@ void ChooserContextBase::UpdateObjectPermission(const url::Origin& origin,
NotifyPermissionChanged();
}
-void ChooserContextBase::RevokeObjectPermission(const url::Origin& origin,
- const base::Value& object) {
+void ObjectPermissionContextBase::RevokeObjectPermission(
+ const url::Origin& origin,
+ const base::Value& object) {
DCHECK(IsValidObject(object));
base::Value setting = GetWebsiteSetting(origin, /*info=*/nullptr);
@@ -221,8 +238,9 @@ void ChooserContextBase::RevokeObjectPermission(const url::Origin& origin,
NotifyPermissionRevoked(origin);
}
-void ChooserContextBase::RevokeObjectPermission(const url::Origin& origin,
- const base::StringPiece key) {
+void ObjectPermissionContextBase::RevokeObjectPermission(
+ const url::Origin& origin,
+ const base::StringPiece key) {
base::Value setting = GetWebsiteSetting(origin, /*info=*/nullptr);
base::Value* objects = setting.FindListKey(kObjectListKey);
if (!objects)
@@ -239,37 +257,39 @@ void ChooserContextBase::RevokeObjectPermission(const url::Origin& origin,
NotifyPermissionRevoked(origin);
}
-bool ChooserContextBase::HasGrantedObjects(const url::Origin& origin) {
+bool ObjectPermissionContextBase::HasGrantedObjects(const url::Origin& origin) {
base::Value setting = GetWebsiteSetting(origin, /*info=*/nullptr);
base::Value* objects = setting.FindListKey(kObjectListKey);
return objects && !objects->GetList().empty();
}
-std::string ChooserContextBase::GetKeyForObject(const base::Value& object) {
+std::string ObjectPermissionContextBase::GetKeyForObject(
+ const base::Value& object) {
return std::string();
}
-bool ChooserContextBase::IsOffTheRecord() {
+bool ObjectPermissionContextBase::IsOffTheRecord() {
return host_content_settings_map_->IsOffTheRecord();
}
-void ChooserContextBase::NotifyPermissionChanged() {
+void ObjectPermissionContextBase::NotifyPermissionChanged() {
for (auto& observer : permission_observer_list_) {
- observer.OnChooserObjectPermissionChanged(guard_content_settings_type_,
- data_content_settings_type_);
+ observer.OnObjectPermissionChanged(guard_content_settings_type_,
+ data_content_settings_type_);
}
}
-void ChooserContextBase::NotifyPermissionRevoked(const url::Origin& origin) {
+void ObjectPermissionContextBase::NotifyPermissionRevoked(
+ const url::Origin& origin) {
for (auto& observer : permission_observer_list_) {
- observer.OnChooserObjectPermissionChanged(guard_content_settings_type_,
- data_content_settings_type_);
+ observer.OnObjectPermissionChanged(guard_content_settings_type_,
+ data_content_settings_type_);
observer.OnPermissionRevoked(origin);
}
}
-base::Value ChooserContextBase::GetWebsiteSetting(
+base::Value ObjectPermissionContextBase::GetWebsiteSetting(
const url::Origin& origin,
content_settings::SettingInfo* info) {
std::unique_ptr<base::Value> value =
@@ -280,8 +300,8 @@ base::Value ChooserContextBase::GetWebsiteSetting(
return base::Value(base::Value::Type::DICTIONARY);
}
-void ChooserContextBase::SetWebsiteSetting(const url::Origin& origin,
- base::Value value) {
+void ObjectPermissionContextBase::SetWebsiteSetting(const url::Origin& origin,
+ base::Value value) {
host_content_settings_map_->SetWebsiteSettingDefaultScope(
origin.GetURL(), GURL(), data_content_settings_type_,
base::Value::ToUniquePtrValue(std::move(value)));
diff --git a/chromium/components/permissions/chooser_context_base.h b/chromium/components/permissions/object_permission_context_base.h
index 35259de983e..154ecf65a7d 100644
--- a/chromium/components/permissions/chooser_context_base.h
+++ b/chromium/components/permissions/object_permission_context_base.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_PERMISSIONS_CHOOSER_CONTEXT_BASE_H_
-#define COMPONENTS_PERMISSIONS_CHOOSER_CONTEXT_BASE_H_
+#ifndef COMPONENTS_PERMISSIONS_OBJECT_PERMISSION_CONTEXT_BASE_H_
+#define COMPONENTS_PERMISSIONS_OBJECT_PERMISSION_CONTEXT_BASE_H_
#include <memory>
#include <string>
@@ -11,11 +11,11 @@
#include "base/observer_list.h"
#include "base/observer_list_types.h"
-#include "base/optional.h"
#include "base/values.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
class HostContentSettingsMap;
@@ -27,9 +27,10 @@ class Origin;
namespace permissions {
// This is the base class for services that manage any type of permission that
-// is granted through a chooser-style UI instead of a simple allow/deny prompt.
+// is associated with a more complicated grant than simple allow/deny. This is
+// typically granted through a chooser-style UI.
// Subclasses must define the structure of the objects that are stored.
-class ChooserContextBase : public KeyedService {
+class ObjectPermissionContextBase : public KeyedService {
public:
struct Object {
Object(const url::Origin& origin,
@@ -44,27 +45,31 @@ class ChooserContextBase : public KeyedService {
bool incognito;
};
- // This observer can be used to be notified of changes to the permission of a
- // chooser object.
+ // This observer can be used to be notified of changes to the permission of
+ // an object.
class PermissionObserver : public base::CheckedObserver {
public:
- // Notify observers that an object permission changed for the chooser
- // context represented by |guard_content_settings_type| and
+ // Notify observer that an object permission changed for the permission
+ // context represented by |guard_content_settings_type|, if applicable, and
// |data_content_settings_type|.
- virtual void OnChooserObjectPermissionChanged(
- ContentSettingsType guard_content_settings_type,
+ virtual void OnObjectPermissionChanged(
+ absl::optional<ContentSettingsType> guard_content_settings_type,
ContentSettingsType data_content_settings_type);
- // Notify obsever that an object permission was revoked for |origin|.
+ // Notify observer that an object permission was revoked for |origin|.
virtual void OnPermissionRevoked(const url::Origin& origin);
};
void AddObserver(PermissionObserver* observer);
void RemoveObserver(PermissionObserver* observer);
- ChooserContextBase(ContentSettingsType guard_content_settings_type,
- ContentSettingsType data_content_settings_type,
- HostContentSettingsMap* host_content_settings_map);
- ~ChooserContextBase() override;
+ ObjectPermissionContextBase(
+ ContentSettingsType guard_content_settings_type,
+ ContentSettingsType data_content_settings_type,
+ HostContentSettingsMap* host_content_settings_map);
+ ObjectPermissionContextBase(
+ ContentSettingsType data_content_settings_type,
+ HostContentSettingsMap* host_content_settings_map);
+ ~ObjectPermissionContextBase() override;
// Checks whether |origin| can request permission to access objects. This is
// done by checking |guard_content_settings_type_| which will usually be "ask"
@@ -155,7 +160,7 @@ class ChooserContextBase : public KeyedService {
void NotifyPermissionChanged();
void NotifyPermissionRevoked(const url::Origin& origin);
- const ContentSettingsType guard_content_settings_type_;
+ const absl::optional<ContentSettingsType> guard_content_settings_type_;
const ContentSettingsType data_content_settings_type_;
base::ObserverList<PermissionObserver> permission_observer_list_;
@@ -169,4 +174,4 @@ class ChooserContextBase : public KeyedService {
} // namespace permissions
-#endif // COMPONENTS_PERMISSIONS_CHOOSER_CONTEXT_BASE_H_
+#endif // COMPONENTS_PERMISSIONS_OBJECT_PERMISSION_CONTEXT_BASE_H_
diff --git a/chromium/components/permissions/chooser_context_base_unittest.cc b/chromium/components/permissions/object_permission_context_base_unittest.cc
index 819a079af17..94c5750aa68 100644
--- a/chromium/components/permissions/chooser_context_base_unittest.cc
+++ b/chromium/components/permissions/object_permission_context_base_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/permissions/chooser_context_base.h"
+#include "components/permissions/object_permission_context_base.h"
#include "base/strings/strcat.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
-#include "components/permissions/test/chooser_context_base_mock_permission_observer.h"
+#include "components/permissions/test/object_permission_context_base_mock_permission_observer.h"
#include "components/permissions/test/test_permissions_client.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
@@ -26,18 +26,20 @@ const char* kRequiredKey2 = "key-2";
// will be a bit complicated.
// Currently:
// - object-based methods are TYPED_TESTs (GetKeyForObject extended/not)
-// - key-based methods are TEST_Fs which only use TestKeyedChooserContext
+// - key-based methods are TEST_Fs which only use
+// TestKeyedObjectPermissionContext
// Once object-based methods are removed, typed tests will no longer be needed.
-class TestNoKeyChooserContext : public ChooserContextBase {
+class TestNoKeyObjectPermissionContext : public ObjectPermissionContextBase {
public:
// This class uses the USB content settings type for testing purposes only.
- explicit TestNoKeyChooserContext(content::BrowserContext* browser_context)
- : ChooserContextBase(
+ explicit TestNoKeyObjectPermissionContext(
+ content::BrowserContext* browser_context)
+ : ObjectPermissionContextBase(
ContentSettingsType::USB_GUARD,
ContentSettingsType::USB_CHOOSER_DATA,
PermissionsClient::Get()->GetSettingsMap(browser_context)) {}
- ~TestNoKeyChooserContext() override = default;
+ ~TestNoKeyObjectPermissionContext() override = default;
bool IsValidObject(const base::Value& object) override {
return object.DictSize() == 2 && object.FindKey(kRequiredKey1) &&
@@ -49,15 +51,16 @@ class TestNoKeyChooserContext : public ChooserContextBase {
}
};
-class TestKeyedChooserContext : public ChooserContextBase {
+class TestKeyedObjectPermissionContext : public ObjectPermissionContextBase {
public:
// This class uses the USB content settings type for testing purposes only.
- explicit TestKeyedChooserContext(content::BrowserContext* browser_context)
- : ChooserContextBase(
+ explicit TestKeyedObjectPermissionContext(
+ content::BrowserContext* browser_context)
+ : ObjectPermissionContextBase(
ContentSettingsType::USB_GUARD,
ContentSettingsType::USB_CHOOSER_DATA,
PermissionsClient::Get()->GetSettingsMap(browser_context)) {}
- ~TestKeyedChooserContext() override = default;
+ ~TestKeyedObjectPermissionContext() override = default;
bool IsValidObject(const base::Value& object) override {
return object.DictSize() == 2 && object.FindKey(kRequiredKey1) &&
@@ -75,9 +78,9 @@ class TestKeyedChooserContext : public ChooserContextBase {
} // namespace
-class ChooserContextBaseTest : public testing::Test {
+class ObjectPermissionContextBaseTest : public testing::Test {
public:
- ChooserContextBaseTest()
+ ObjectPermissionContextBaseTest()
: url1_("https://google.com"),
url2_("https://chromium.org"),
origin1_(url::Origin::Create(url1_)),
@@ -90,7 +93,7 @@ class ChooserContextBaseTest : public testing::Test {
object2_.SetStringKey(kRequiredKey2, "value4");
}
- ~ChooserContextBaseTest() override = default;
+ ~ObjectPermissionContextBaseTest() override = default;
content::BrowserContext* browser_context() { return &browser_context_; }
@@ -109,181 +112,198 @@ class ChooserContextBaseTest : public testing::Test {
};
template <typename T>
-class ChooserContextBaseTypedTest : public ChooserContextBaseTest {
+class ObjectPermissionContextBaseTypedTest
+ : public ObjectPermissionContextBaseTest {
public:
- ChooserContextBaseTypedTest()
- : ChooserContextBaseTest(), chooser_context_(browser_context()) {}
+ ObjectPermissionContextBaseTypedTest()
+ : ObjectPermissionContextBaseTest(),
+ object_permission_context_(browser_context()) {}
- ~ChooserContextBaseTypedTest() override = default;
+ ~ObjectPermissionContextBaseTypedTest() override = default;
protected:
- T chooser_context_;
+ T object_permission_context_;
};
-using TestChooserContext =
- testing::Types<TestNoKeyChooserContext, TestKeyedChooserContext>;
+using TestObjectPermissionContext =
+ testing::Types<TestNoKeyObjectPermissionContext,
+ TestKeyedObjectPermissionContext>;
-TYPED_TEST_SUITE(ChooserContextBaseTypedTest, TestChooserContext);
+TYPED_TEST_SUITE(ObjectPermissionContextBaseTypedTest,
+ TestObjectPermissionContext);
// ----------------------------OBJECT-BASED METHODS-----------------------------
-TYPED_TEST(ChooserContextBaseTypedTest, GrantAndRevokeObjectPermissions) {
+TYPED_TEST(ObjectPermissionContextBaseTypedTest,
+ GrantAndRevokeObjectPermissions) {
MockPermissionObserver mock_observer;
- this->chooser_context_.AddObserver(&mock_observer);
+ this->object_permission_context_.AddObserver(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(2);
- this->chooser_context_.GrantObjectPermission(this->origin1_,
- this->object1_.Clone());
- this->chooser_context_.GrantObjectPermission(this->origin1_,
- this->object2_.Clone());
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin1_, this->object1_.Clone());
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin1_, this->object2_.Clone());
- auto objects = this->chooser_context_.GetGrantedObjects(this->origin1_);
+ auto objects =
+ this->object_permission_context_.GetGrantedObjects(this->origin1_);
EXPECT_EQ(2u, objects.size());
EXPECT_EQ(this->object1_, objects[0]->value);
EXPECT_EQ(this->object2_, objects[1]->value);
// Granting permission to one origin should not grant them to another.
- objects = this->chooser_context_.GetGrantedObjects(this->origin2_);
+ objects = this->object_permission_context_.GetGrantedObjects(this->origin2_);
EXPECT_EQ(0u, objects.size());
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(2);
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
EXPECT_CALL(mock_observer, OnPermissionRevoked(this->origin1_)).Times(2);
- this->chooser_context_.RevokeObjectPermission(this->origin1_, this->object1_);
- this->chooser_context_.RevokeObjectPermission(this->origin1_, this->object2_);
- objects = this->chooser_context_.GetGrantedObjects(this->origin1_);
+ this->object_permission_context_.RevokeObjectPermission(this->origin1_,
+ this->object1_);
+ this->object_permission_context_.RevokeObjectPermission(this->origin1_,
+ this->object2_);
+ objects = this->object_permission_context_.GetGrantedObjects(this->origin1_);
EXPECT_EQ(0u, objects.size());
}
-TYPED_TEST(ChooserContextBaseTypedTest, GrantObjectPermissionTwice) {
+TYPED_TEST(ObjectPermissionContextBaseTypedTest, GrantObjectPermissionTwice) {
MockPermissionObserver mock_observer;
- this->chooser_context_.AddObserver(&mock_observer);
+ this->object_permission_context_.AddObserver(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(2);
- this->chooser_context_.GrantObjectPermission(this->origin1_,
- this->object1_.Clone());
- this->chooser_context_.GrantObjectPermission(this->origin1_,
- this->object1_.Clone());
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin1_, this->object1_.Clone());
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin1_, this->object1_.Clone());
- auto objects = this->chooser_context_.GetGrantedObjects(this->origin1_);
+ auto objects =
+ this->object_permission_context_.GetGrantedObjects(this->origin1_);
EXPECT_EQ(1u, objects.size());
EXPECT_EQ(this->object1_, objects[0]->value);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _));
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
EXPECT_CALL(mock_observer, OnPermissionRevoked(this->origin1_));
- this->chooser_context_.RevokeObjectPermission(this->origin1_, this->object1_);
- objects = this->chooser_context_.GetGrantedObjects(this->origin1_);
+ this->object_permission_context_.RevokeObjectPermission(this->origin1_,
+ this->object1_);
+ objects = this->object_permission_context_.GetGrantedObjects(this->origin1_);
EXPECT_EQ(0u, objects.size());
}
-TYPED_TEST(ChooserContextBaseTypedTest, GrantAndUpdateObjectPermission) {
+TYPED_TEST(ObjectPermissionContextBaseTypedTest,
+ GrantAndUpdateObjectPermission) {
MockPermissionObserver mock_observer;
- this->chooser_context_.AddObserver(&mock_observer);
+ this->object_permission_context_.AddObserver(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _));
- this->chooser_context_.GrantObjectPermission(this->origin1_,
- this->object1_.Clone());
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin1_, this->object1_.Clone());
- auto objects = this->chooser_context_.GetGrantedObjects(this->origin1_);
+ auto objects =
+ this->object_permission_context_.GetGrantedObjects(this->origin1_);
EXPECT_EQ(1u, objects.size());
EXPECT_EQ(this->object1_, objects[0]->value);
testing::Mock::VerifyAndClearExpectations(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _));
- this->chooser_context_.UpdateObjectPermission(
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
+ this->object_permission_context_.UpdateObjectPermission(
this->origin1_, objects[0]->value, this->object2_.Clone());
- objects = this->chooser_context_.GetGrantedObjects(this->origin1_);
+ objects = this->object_permission_context_.GetGrantedObjects(this->origin1_);
EXPECT_EQ(1u, objects.size());
EXPECT_EQ(this->object2_, objects[0]->value);
}
// UpdateObjectPermission() should not grant new permissions.
-TYPED_TEST(ChooserContextBaseTypedTest,
+TYPED_TEST(ObjectPermissionContextBaseTypedTest,
UpdateObjectPermissionWithNonExistentPermission) {
MockPermissionObserver mock_observer;
- this->chooser_context_.AddObserver(&mock_observer);
+ this->object_permission_context_.AddObserver(&mock_observer);
// Attempt to update permission for non-existent |this->object1_| permission.
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(0);
- this->chooser_context_.UpdateObjectPermission(this->origin1_, this->object1_,
- this->object2_.Clone());
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(0);
+ this->object_permission_context_.UpdateObjectPermission(
+ this->origin1_, this->object1_, this->object2_.Clone());
testing::Mock::VerifyAndClearExpectations(&mock_observer);
- auto objects = this->chooser_context_.GetGrantedObjects(this->origin1_);
+ auto objects =
+ this->object_permission_context_.GetGrantedObjects(this->origin1_);
EXPECT_TRUE(objects.empty());
// Grant permission for |this->object2_| but attempt to update permission for
// non-existent |this->object1_| permission again.
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _));
- this->chooser_context_.GrantObjectPermission(this->origin1_,
- this->object2_.Clone());
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin1_, this->object2_.Clone());
testing::Mock::VerifyAndClearExpectations(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(0);
- this->chooser_context_.UpdateObjectPermission(this->origin1_, this->object1_,
- this->object2_.Clone());
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(0);
+ this->object_permission_context_.UpdateObjectPermission(
+ this->origin1_, this->object1_, this->object2_.Clone());
testing::Mock::VerifyAndClearExpectations(&mock_observer);
- objects = this->chooser_context_.GetGrantedObjects(this->origin1_);
+ objects = this->object_permission_context_.GetGrantedObjects(this->origin1_);
EXPECT_EQ(1u, objects.size());
EXPECT_EQ(this->object2_, objects[0]->value);
}
-TYPED_TEST(ChooserContextBaseTypedTest, GetAllGrantedObjects) {
+TYPED_TEST(ObjectPermissionContextBaseTypedTest, GetAllGrantedObjects) {
MockPermissionObserver mock_observer;
- this->chooser_context_.AddObserver(&mock_observer);
+ this->object_permission_context_.AddObserver(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(2);
- this->chooser_context_.GrantObjectPermission(this->origin1_,
- this->object1_.Clone());
- this->chooser_context_.GrantObjectPermission(this->origin2_,
- this->object2_.Clone());
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin1_, this->object1_.Clone());
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin2_, this->object2_.Clone());
- auto objects = this->chooser_context_.GetAllGrantedObjects();
+ auto objects = this->object_permission_context_.GetAllGrantedObjects();
EXPECT_EQ(2u, objects.size());
EXPECT_EQ(this->object1_, objects[0]->value);
EXPECT_EQ(this->object2_, objects[1]->value);
}
-TYPED_TEST(ChooserContextBaseTypedTest, GetGrantedObjectsWithGuardBlocked) {
+TYPED_TEST(ObjectPermissionContextBaseTypedTest,
+ GetGrantedObjectsWithGuardBlocked) {
auto* map = PermissionsClient::Get()->GetSettingsMap(this->browser_context());
map->SetContentSettingDefaultScope(this->url1_, this->url1_,
ContentSettingsType::USB_GUARD,
CONTENT_SETTING_BLOCK);
MockPermissionObserver mock_observer;
- this->chooser_context_.AddObserver(&mock_observer);
+ this->object_permission_context_.AddObserver(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(2);
- this->chooser_context_.GrantObjectPermission(this->origin1_,
- this->object1_.Clone());
- this->chooser_context_.GrantObjectPermission(this->origin2_,
- this->object2_.Clone());
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin1_, this->object1_.Clone());
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin2_, this->object2_.Clone());
- auto objects1 = this->chooser_context_.GetGrantedObjects(this->origin1_);
+ auto objects1 =
+ this->object_permission_context_.GetGrantedObjects(this->origin1_);
EXPECT_EQ(0u, objects1.size());
- auto objects2 = this->chooser_context_.GetGrantedObjects(this->origin2_);
+ auto objects2 =
+ this->object_permission_context_.GetGrantedObjects(this->origin2_);
ASSERT_EQ(1u, objects2.size());
EXPECT_EQ(this->object2_, objects2[0]->value);
}
-TYPED_TEST(ChooserContextBaseTypedTest, GetAllGrantedObjectsWithGuardBlocked) {
+TYPED_TEST(ObjectPermissionContextBaseTypedTest,
+ GetAllGrantedObjectsWithGuardBlocked) {
auto* map = PermissionsClient::Get()->GetSettingsMap(this->browser_context());
map->SetContentSettingDefaultScope(this->url1_, this->url1_,
ContentSettingsType::USB_GUARD,
CONTENT_SETTING_BLOCK);
MockPermissionObserver mock_observer;
- this->chooser_context_.AddObserver(&mock_observer);
+ this->object_permission_context_.AddObserver(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(2);
- this->chooser_context_.GrantObjectPermission(this->origin1_,
- this->object1_.Clone());
- this->chooser_context_.GrantObjectPermission(this->origin2_,
- this->object2_.Clone());
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin1_, this->object1_.Clone());
+ this->object_permission_context_.GrantObjectPermission(
+ this->origin2_, this->object2_.Clone());
- auto objects = this->chooser_context_.GetAllGrantedObjects();
+ auto objects = this->object_permission_context_.GetAllGrantedObjects();
ASSERT_EQ(1u, objects.size());
EXPECT_EQ(this->url2_, objects[0]->origin);
EXPECT_EQ(this->object2_, objects[0]->value);
@@ -291,15 +311,15 @@ TYPED_TEST(ChooserContextBaseTypedTest, GetAllGrantedObjectsWithGuardBlocked) {
// ------------------------------KEY-BASED METHODS------------------------------
-TEST_F(ChooserContextBaseTest, GrantAndRevokeObjectPermissions_Keyed) {
- TestKeyedChooserContext context(browser_context());
+TEST_F(ObjectPermissionContextBaseTest, GrantAndRevokeObjectPermissions_Keyed) {
+ TestKeyedObjectPermissionContext context(browser_context());
MockPermissionObserver mock_observer;
context.AddObserver(&mock_observer);
auto object1_key = context.GetKeyForObject(object1_);
auto object2_key = context.GetKeyForObject(object2_);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(2);
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
context.GrantObjectPermission(origin1_, object1_.Clone());
context.GrantObjectPermission(origin1_, object2_.Clone());
@@ -316,7 +336,7 @@ TEST_F(ChooserContextBaseTest, GrantAndRevokeObjectPermissions_Keyed) {
EXPECT_EQ(object1_, context.GetGrantedObject(origin1_, object1_key)->value);
EXPECT_EQ(object2_, context.GetGrantedObject(origin1_, object2_key)->value);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(2);
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
EXPECT_CALL(mock_observer, OnPermissionRevoked(origin1_)).Times(2);
context.RevokeObjectPermission(origin1_, object1_key);
context.RevokeObjectPermission(origin1_, object2_key);
@@ -326,12 +346,12 @@ TEST_F(ChooserContextBaseTest, GrantAndRevokeObjectPermissions_Keyed) {
EXPECT_EQ(0u, objects.size());
}
-TEST_F(ChooserContextBaseTest, GrantObjectPermissionTwice_Keyed) {
- TestKeyedChooserContext context(browser_context());
+TEST_F(ObjectPermissionContextBaseTest, GrantObjectPermissionTwice_Keyed) {
+ TestKeyedObjectPermissionContext context(browser_context());
MockPermissionObserver mock_observer;
context.AddObserver(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _)).Times(2);
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _)).Times(2);
context.GrantObjectPermission(origin1_, object1_.Clone());
context.GrantObjectPermission(origin1_, object1_.Clone());
@@ -339,19 +359,19 @@ TEST_F(ChooserContextBaseTest, GrantObjectPermissionTwice_Keyed) {
EXPECT_EQ(1u, objects.size());
EXPECT_EQ(object1_, objects[0]->value);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _));
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
EXPECT_CALL(mock_observer, OnPermissionRevoked(origin1_));
context.RevokeObjectPermission(origin1_, context.GetKeyForObject(object1_));
objects = context.GetGrantedObjects(origin1_);
EXPECT_EQ(0u, objects.size());
}
-TEST_F(ChooserContextBaseTest, GrantAndUpdateObjectPermission_Keyed) {
- TestKeyedChooserContext context(browser_context());
+TEST_F(ObjectPermissionContextBaseTest, GrantAndUpdateObjectPermission_Keyed) {
+ TestKeyedObjectPermissionContext context(browser_context());
MockPermissionObserver mock_observer;
context.AddObserver(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _));
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
context.GrantObjectPermission(origin1_, object1_.Clone());
auto objects = context.GetGrantedObjects(origin1_);
@@ -365,7 +385,7 @@ TEST_F(ChooserContextBaseTest, GrantAndUpdateObjectPermission_Keyed) {
EXPECT_NE(new_object, objects[0]->value);
testing::Mock::VerifyAndClearExpectations(&mock_observer);
- EXPECT_CALL(mock_observer, OnChooserObjectPermissionChanged(_, _));
+ EXPECT_CALL(mock_observer, OnObjectPermissionChanged(_, _));
// GrantObjectPermission will update an object if an object with the same key
// already exists.
context.GrantObjectPermission(origin1_, new_object.Clone());
diff --git a/chromium/components/permissions/permission_auditing_database.cc b/chromium/components/permissions/permission_auditing_database.cc
index ea3cab9e5e9..7f70722bb33 100644
--- a/chromium/components/permissions/permission_auditing_database.cc
+++ b/chromium/components/permissions/permission_auditing_database.cc
@@ -13,12 +13,11 @@
#include "base/check.h"
#include "base/files/file_path.h"
-#include "base/optional.h"
-#include "base/strings/stringprintf.h"
#include "sql/database.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
#include "sql/transaction.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace permissions {
@@ -172,7 +171,7 @@ PermissionAuditingDatabase::GetPermissionUsageHistory(ContentSettingsType type,
return sessions;
}
-base::Optional<base::Time>
+absl::optional<base::Time>
PermissionAuditingDatabase::GetLastPermissionUsageTime(
ContentSettingsType type,
const url::Origin& origin) {
@@ -186,7 +185,7 @@ PermissionAuditingDatabase::GetLastPermissionUsageTime(
"LIMIT 1"));
statement.BindString(0, origin.Serialize());
statement.BindInt(1, static_cast<int32_t>(type));
- base::Optional<base::Time> last_usage;
+ absl::optional<base::Time> last_usage;
if (statement.Step()) {
last_usage = Int64ToTime(statement.ColumnInt64(0));
}
diff --git a/chromium/components/permissions/permission_auditing_database.h b/chromium/components/permissions/permission_auditing_database.h
index 113f20b5c83..fbd1050d270 100644
--- a/chromium/components/permissions/permission_auditing_database.h
+++ b/chromium/components/permissions/permission_auditing_database.h
@@ -8,11 +8,11 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/permissions/permission_usage_session.h"
#include "sql/database.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
namespace base {
@@ -62,7 +62,7 @@ class PermissionAuditingDatabase {
// Returns when the given permission `type` was last used on a given `origin`.
// Returns nullopt if no permission usages match the given constraints. The
// `origin` must not be opaque.
- base::Optional<base::Time> GetLastPermissionUsageTime(
+ absl::optional<base::Time> GetLastPermissionUsageTime(
ContentSettingsType type,
const url::Origin& origin);
diff --git a/chromium/components/permissions/permission_auditing_database_unittest.cc b/chromium/components/permissions/permission_auditing_database_unittest.cc
index 3d3b2d08183..910e6cc5aa4 100644
--- a/chromium/components/permissions/permission_auditing_database_unittest.cc
+++ b/chromium/components/permissions/permission_auditing_database_unittest.cc
@@ -80,7 +80,7 @@ class PermissionAuditingDatabaseTest : public testing::Test {
return db_.GetPermissionUsageHistory(type, GetOrigin(url), starting_from);
}
- base::Optional<base::Time> GetLastUsageTime(ContentSettingsType type,
+ absl::optional<base::Time> GetLastUsageTime(ContentSettingsType type,
const char* url) {
return db_.GetLastPermissionUsageTime(type, GetOrigin(url));
}
diff --git a/chromium/components/permissions/permission_auditing_service.h b/chromium/components/permissions/permission_auditing_service.h
index 71934c45276..cd1b9c4b2f9 100644
--- a/chromium/components/permissions/permission_auditing_service.h
+++ b/chromium/components/permissions/permission_auditing_service.h
@@ -38,7 +38,7 @@ class PermissionAuditingService
typedef base::OnceCallback<void(std::vector<PermissionUsageSession>)>
PermissionUsageHistoryCallback;
- typedef base::OnceCallback<void(base::Optional<base::Time>)>
+ typedef base::OnceCallback<void(absl::optional<base::Time>)>
LastPermissionUsageTimeCallback;
explicit PermissionAuditingService(
diff --git a/chromium/components/permissions/permission_auditing_service_unittest.cc b/chromium/components/permissions/permission_auditing_service_unittest.cc
index 96af4bb3792..b084e1ef26b 100644
--- a/chromium/components/permissions/permission_auditing_service_unittest.cc
+++ b/chromium/components/permissions/permission_auditing_service_unittest.cc
@@ -11,7 +11,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/test/bind.h"
@@ -118,7 +117,7 @@ class PermissionAuditingServiceTest : public testing::Test {
base::Time last_usage_time;
service().GetLastPermissionUsageTime(
type, origin,
- base::BindLambdaForTesting([&](base::Optional<base::Time> time) {
+ base::BindLambdaForTesting([&](absl::optional<base::Time> time) {
last_usage_time = time.value_or(base::Time());
run_loop.QuitWhenIdle();
}));
diff --git a/chromium/components/permissions/permission_context_base.cc b/chromium/components/permissions/permission_context_base.cc
index 8a762896902..d98bac37cb4 100644
--- a/chromium/components/permissions/permission_context_base.cc
+++ b/chromium/components/permissions/permission_context_base.cc
@@ -109,6 +109,7 @@ PermissionContextBase::PermissionContextBase(
}
PermissionContextBase::~PermissionContextBase() {
+ DCHECK(permission_observers_.empty());
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
@@ -218,6 +219,20 @@ void PermissionContextBase::UserMadePermissionDecision(
const GURL& embedding_origin,
ContentSetting content_setting) {}
+std::unique_ptr<PermissionRequest>
+PermissionContextBase::CreatePermissionRequest(
+ const GURL& request_origin,
+ ContentSettingsType content_settings_type,
+ bool has_gesture,
+ content::WebContents* web_contents,
+ PermissionRequestImpl::PermissionDecidedCallback
+ permission_decided_callback,
+ base::OnceClosure delete_callback) const {
+ return std::make_unique<PermissionRequestImpl>(
+ request_origin, content_settings_type, has_gesture,
+ std::move(permission_decided_callback), std::move(delete_callback));
+}
+
PermissionResult PermissionContextBase::GetPermissionStatus(
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
@@ -372,14 +387,13 @@ void PermissionContextBase::DecidePermission(
if (!permission_request_manager)
return;
- std::unique_ptr<PermissionRequest> request_ptr =
- std::make_unique<PermissionRequestImpl>(
- requesting_origin, content_settings_type_, user_gesture,
- base::BindOnce(&PermissionContextBase::PermissionDecided,
- weak_factory_.GetWeakPtr(), id, requesting_origin,
- embedding_origin, std::move(callback)),
- base::BindOnce(&PermissionContextBase::CleanUpRequest,
- weak_factory_.GetWeakPtr(), id));
+ std::unique_ptr<PermissionRequest> request_ptr = CreatePermissionRequest(
+ requesting_origin, content_settings_type_, user_gesture, web_contents,
+ base::BindOnce(&PermissionContextBase::PermissionDecided,
+ weak_factory_.GetWeakPtr(), id, requesting_origin,
+ embedding_origin, std::move(callback)),
+ base::BindOnce(&PermissionContextBase::CleanUpRequest,
+ weak_factory_.GetWeakPtr(), id));
PermissionRequest* request = request_ptr.get();
bool inserted =
@@ -423,6 +437,39 @@ content::BrowserContext* PermissionContextBase::browser_context() const {
return browser_context_;
}
+void PermissionContextBase::OnContentSettingChanged(
+ const ContentSettingsPattern& primary_pattern,
+ const ContentSettingsPattern& secondary_pattern,
+ ContentSettingsType content_type) {
+ if (content_type != content_settings_type_)
+ return;
+
+ for (permissions::Observer& obs : permission_observers_)
+ obs.OnPermissionChanged(primary_pattern, secondary_pattern, content_type);
+}
+
+void PermissionContextBase::AddObserver(
+ permissions::Observer* permission_observer) {
+ if (permission_observers_.empty() &&
+ !content_setting_observer_registered_by_subclass_) {
+ PermissionsClient::Get()
+ ->GetSettingsMap(browser_context_)
+ ->AddObserver(this);
+ }
+ permission_observers_.AddObserver(permission_observer);
+}
+
+void PermissionContextBase::RemoveObserver(
+ permissions::Observer* permission_observer) {
+ permission_observers_.RemoveObserver(permission_observer);
+ if (permission_observers_.empty() &&
+ !content_setting_observer_registered_by_subclass_) {
+ PermissionsClient::Get()
+ ->GetSettingsMap(browser_context_)
+ ->RemoveObserver(this);
+ }
+}
+
void PermissionContextBase::NotifyPermissionSet(
const PermissionRequestID& id,
const GURL& requesting_origin,
diff --git a/chromium/components/permissions/permission_context_base.h b/chromium/components/permissions/permission_context_base.h
index f53b71206a0..93b981d2c38 100644
--- a/chromium/components/permissions/permission_context_base.h
+++ b/chromium/components/permissions/permission_context_base.h
@@ -10,11 +10,14 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
#include "build/build_config.h"
+#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/permissions/permission_request.h"
+#include "components/permissions/permission_request_impl.h"
#include "components/permissions/permission_result.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-forward.h"
@@ -32,6 +35,14 @@ class WebContents;
namespace permissions {
+class Observer : public base::CheckedObserver {
+ public:
+ virtual void OnPermissionChanged(
+ const ContentSettingsPattern& primary_pattern,
+ const ContentSettingsPattern& secondary_pattern,
+ ContentSettingsType content_type) = 0;
+};
+
using BrowserPermissionCallback = base::OnceCallback<void(ContentSetting)>;
// This base class contains common operations for granting permissions.
@@ -56,7 +67,8 @@ using BrowserPermissionCallback = base::OnceCallback<void(ContentSetting)>;
// See midi_permission_context.h/cc or push_permission_context.cc/h for some
// examples.
-class PermissionContextBase : public KeyedService {
+class PermissionContextBase : public KeyedService,
+ public content_settings::Observer {
public:
PermissionContextBase(
content::BrowserContext* browser_context,
@@ -111,6 +123,9 @@ class PermissionContextBase : public KeyedService {
// camera and microphone, and for testing.
bool IsPermissionKillSwitchOn() const;
+ void AddObserver(permissions::Observer* permission_observer);
+ void RemoveObserver(permissions::Observer* permission_observer);
+
protected:
virtual ContentSetting GetPermissionStatusInternal(
content::RenderFrameHost* render_frame_host,
@@ -164,10 +179,32 @@ class PermissionContextBase : public KeyedService {
const GURL& embedding_origin,
ContentSetting content_setting);
+ // content_settings::Observer:
+ void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
+ const ContentSettingsPattern& secondary_pattern,
+ ContentSettingsType content_type) override;
+
+ // Implementors can override this method to use a different PermissionRequest
+ // implementation.
+ virtual std::unique_ptr<PermissionRequest> CreatePermissionRequest(
+ const GURL& request_origin,
+ ContentSettingsType content_settings_type,
+ bool has_gesture,
+ content::WebContents* web_contents,
+ PermissionRequestImpl::PermissionDecidedCallback
+ permission_decided_callback,
+ base::OnceClosure delete_callback) const;
+
ContentSettingsType content_settings_type() const {
return content_settings_type_;
}
+ base::ObserverList<permissions::Observer> permission_observers_;
+
+ // Set by subclasses to inform the base class that they will handle adding
+ // and removing themselves as observers to the HostContentSettingsMap.
+ bool content_setting_observer_registered_by_subclass_ = false;
+
private:
friend class PermissionContextBaseTests;
diff --git a/chromium/components/permissions/permission_context_base_unittest.cc b/chromium/components/permissions/permission_context_base_unittest.cc
index c39b2061024..b926cc62d6b 100644
--- a/chromium/components/permissions/permission_context_base_unittest.cc
+++ b/chromium/components/permissions/permission_context_base_unittest.cc
@@ -234,7 +234,7 @@ class PermissionContextBaseTests : public content::RenderViewHostTestHarness {
EXPECT_TRUE(permission_context.tab_context_updated());
std::string decision_string;
- base::Optional<PermissionAction> action;
+ absl::optional<PermissionAction> action;
if (decision == CONTENT_SETTING_ALLOW) {
decision_string = "Accepted";
action = PermissionAction::GRANTED;
@@ -774,10 +774,6 @@ TEST_F(PermissionContextBaseTests, TestNonValidRequestingUrl) {
TestRequestPermissionInvalidUrl(ContentSettingsType::GEOLOCATION);
TestRequestPermissionInvalidUrl(ContentSettingsType::NOTIFICATIONS);
TestRequestPermissionInvalidUrl(ContentSettingsType::MIDI_SYSEX);
-#if BUILDFLAG(IS_CHROMEOS_ASH)
- TestRequestPermissionInvalidUrl(
- ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER);
-#endif
}
// Simulates granting and revoking of permissions.
diff --git a/chromium/components/permissions/permission_manager.cc b/chromium/components/permissions/permission_manager.cc
index 3a2f82f863b..a02b65f9f95 100644
--- a/chromium/components/permissions/permission_manager.cc
+++ b/chromium/components/permissions/permission_manager.cc
@@ -82,7 +82,7 @@ ContentSettingsType PermissionTypeToContentSettingSafe(
case PermissionType::GEOLOCATION:
return ContentSettingsType::GEOLOCATION;
case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
return ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER;
#else
break;
@@ -276,10 +276,15 @@ void PermissionManager::Shutdown() {
is_shutting_down_ = true;
if (!subscriptions_.IsEmpty()) {
- PermissionsClient::Get()
- ->GetSettingsMap(browser_context_)
- ->RemoveObserver(this);
subscriptions_.Clear();
+ for (const auto& type_to_count : subscription_type_counts_) {
+ if (type_to_count.second > 0) {
+ PermissionContextBase* context =
+ GetPermissionContext(type_to_count.first);
+ context->RemoveObserver(this);
+ }
+ }
+ subscription_type_counts_.clear();
}
}
@@ -302,7 +307,7 @@ PermissionContextBase* PermissionManager::GetPermissionContextForTesting(
GURL PermissionManager::GetCanonicalOrigin(ContentSettingsType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) const {
- base::Optional<GURL> override_origin =
+ absl::optional<GURL> override_origin =
PermissionsClient::Get()->OverrideCanonicalOrigin(requesting_origin,
embedding_origin);
if (override_origin)
@@ -524,7 +529,7 @@ PermissionStatus PermissionManager::GetPermissionStatusForFrame(
bool PermissionManager::IsPermissionOverridableByDevTools(
content::PermissionType permission,
- const base::Optional<url::Origin>& origin) {
+ const absl::optional<url::Origin>& origin) {
ContentSettingsType type = PermissionTypeToContentSettingSafe(permission);
PermissionContextBase* context = GetPermissionContext(type);
@@ -545,12 +550,14 @@ PermissionManager::SubscribePermissionStatusChange(
if (is_shutting_down_)
return SubscriptionId();
- if (subscriptions_.IsEmpty())
- PermissionsClient::Get()
- ->GetSettingsMap(browser_context_)
- ->AddObserver(this);
-
ContentSettingsType content_type = PermissionTypeToContentSetting(permission);
+ auto& type_count = subscription_type_counts_[content_type];
+ if (type_count == 0) {
+ PermissionContextBase* context = GetPermissionContext(content_type);
+ context->AddObserver(this);
+ }
+ ++type_count;
+
auto subscription = std::make_unique<Subscription>();
// The RFH may be null if the request is for a worker.
@@ -591,14 +598,19 @@ void PermissionManager::UnsubscribePermissionStatusChange(
if (is_shutting_down_)
return;
- if (subscriptions_.Lookup(subscription_id)) {
- subscriptions_.Remove(subscription_id);
- }
+ Subscription* subscription = subscriptions_.Lookup(subscription_id);
+ if (!subscription)
+ return;
- if (subscriptions_.IsEmpty()) {
- PermissionsClient::Get()
- ->GetSettingsMap(browser_context_)
- ->RemoveObserver(this);
+ ContentSettingsType type = subscription->permission;
+ subscriptions_.Remove(subscription_id);
+ auto type_count = subscription_type_counts_.find(type);
+ CHECK(type_count != subscription_type_counts_.end());
+ CHECK_GT(type_count->second, size_t(0));
+ type_count->second--;
+ if (type_count->second == 0) {
+ PermissionContextBase* context = GetPermissionContext(type);
+ context->RemoveObserver(this);
}
}
@@ -608,7 +620,7 @@ bool PermissionManager::IsPermissionKillSwitchOn(
return GetPermissionContext(permission)->IsPermissionKillSwitchOn();
}
-void PermissionManager::OnContentSettingChanged(
+void PermissionManager::OnPermissionChanged(
const ContentSettingsPattern& primary_pattern,
const ContentSettingsPattern& secondary_pattern,
ContentSettingsType content_type) {
@@ -689,7 +701,7 @@ PermissionResult PermissionManager::GetPermissionStatusHelper(
}
void PermissionManager::SetPermissionOverridesForDevTools(
- const base::Optional<url::Origin>& optional_origin,
+ const absl::optional<url::Origin>& optional_origin,
const PermissionOverrides& overrides) {
ContentSettingsTypeOverrides result;
for (const auto& item : overrides) {
diff --git a/chromium/components/permissions/permission_manager.h b/chromium/components/permissions/permission_manager.h
index 6b107641eec..e21fc1c1e61 100644
--- a/chromium/components/permissions/permission_manager.h
+++ b/chromium/components/permissions/permission_manager.h
@@ -8,11 +8,13 @@
#include <unordered_map>
#include "base/callback_forward.h"
+#include "base/containers/flat_map.h"
#include "base/containers/id_map.h"
#include "base/macros.h"
#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "components/permissions/permission_context_base.h"
#include "components/permissions/permission_request_id.h"
#include "components/permissions/permission_util.h"
#include "content/public/browser/permission_controller_delegate.h"
@@ -29,7 +31,7 @@ struct PermissionResult;
class PermissionManager : public KeyedService,
public content::PermissionControllerDelegate,
- public content_settings::Observer {
+ public permissions::Observer {
public:
using PermissionContextMap =
std::unordered_map<ContentSettingsType,
@@ -115,7 +117,7 @@ class PermissionManager : public KeyedService,
const GURL& requesting_origin) override;
bool IsPermissionOverridableByDevTools(
content::PermissionType permission,
- const base::Optional<url::Origin>& origin) override;
+ const absl::optional<url::Origin>& origin) override;
SubscriptionId SubscribePermissionStatusChange(
content::PermissionType permission,
content::RenderFrameHost* render_frame_host,
@@ -133,7 +135,7 @@ class PermissionManager : public KeyedService,
// For the given |origin|, overrides permissions that belong to |overrides|.
// These permissions are in-sync with the PermissionController.
void SetPermissionOverridesForDevTools(
- const base::Optional<url::Origin>& origin,
+ const absl::optional<url::Origin>& origin,
const PermissionOverrides& overrides) override;
void ResetPermissionOverridesForDevTools() override;
@@ -164,6 +166,7 @@ class PermissionManager : public KeyedService,
struct Subscription;
using SubscriptionsMap =
base::IDMap<std::unique_ptr<Subscription>, SubscriptionId>;
+ using SubscriptionTypeCounts = base::flat_map<ContentSettingsType, size_t>;
PermissionContextBase* GetPermissionContext(ContentSettingsType type);
@@ -178,10 +181,10 @@ class PermissionManager : public KeyedService,
int permission_id,
ContentSetting status);
- // content_settings::Observer implementation.
- void OnContentSettingChanged(const ContentSettingsPattern& primary_pattern,
- const ContentSettingsPattern& secondary_pattern,
- ContentSettingsType content_type) override;
+ // permissions::Observer:
+ void OnPermissionChanged(const ContentSettingsPattern& primary_pattern,
+ const ContentSettingsPattern& secondary_pattern,
+ ContentSettingsType content_type) override;
PermissionResult GetPermissionStatusHelper(
ContentSettingsType permission,
@@ -201,6 +204,13 @@ class PermissionManager : public KeyedService,
SubscriptionsMap subscriptions_;
SubscriptionId::Generator subscription_id_generator_;
+ // Tracks the number of Subscriptions in |subscriptions_| which have a
+ // certain ContentSettingsType. An entry for a given ContentSettingsType key
+ // is added on first use and never removed. This is done to utilize the
+ // flat_map's efficiency in accessing/editing items and minimize the use of
+ // the unefficient addition/removal of items.
+ SubscriptionTypeCounts subscription_type_counts_;
+
PermissionContextMap permission_contexts_;
using ContentSettingsTypeOverrides =
base::flat_map<ContentSettingsType, ContentSetting>;
diff --git a/chromium/components/permissions/permission_manager_unittest.cc b/chromium/components/permissions/permission_manager_unittest.cc
index efa4abefa97..ddeb49e019a 100644
--- a/chromium/components/permissions/permission_manager_unittest.cc
+++ b/chromium/components/permissions/permission_manager_unittest.cc
@@ -127,15 +127,13 @@ class PermissionManagerTest : public content::RenderViewHostTestHarness {
if (!quit_closure_.is_null())
std::move(quit_closure_).Run();
callback_called_ = true;
+ callback_count_++;
callback_result_ = permission;
}
protected:
PermissionManagerTest()
- : url_("https://example.com"),
- other_url_("https://foo.com"),
- callback_called_(false),
- callback_result_(PermissionStatus::ASK) {}
+ : url_("https://example.com"), other_url_("https://foo.com") {}
PermissionManager* GetPermissionControllerDelegate() {
return static_cast<PermissionManager*>(
@@ -184,10 +182,13 @@ class PermissionManagerTest : public content::RenderViewHostTestHarness {
bool callback_called() const { return callback_called_; }
+ int callback_count() const { return callback_count_; }
+
PermissionStatus callback_result() const { return callback_result_; }
void Reset() {
callback_called_ = false;
+ callback_count_ = 0;
callback_result_ = PermissionStatus::ASK;
}
@@ -259,8 +260,9 @@ class PermissionManagerTest : public content::RenderViewHostTestHarness {
const GURL url_;
const GURL other_url_;
- bool callback_called_;
- PermissionStatus callback_result_;
+ bool callback_called_ = false;
+ int callback_count_ = 0;
+ PermissionStatus callback_result_ = PermissionStatus::ASK;
base::OnceClosure quit_closure_;
std::unique_ptr<content::TestBrowserContext> browser_context_;
TestPermissionsClient client_;
@@ -416,6 +418,28 @@ TEST_F(PermissionManagerTest, ChangeAfterUnsubscribeDoesNotNotify) {
EXPECT_FALSE(callback_called());
}
+TEST_F(PermissionManagerTest,
+ ChangeAfterUnsubscribeOnlyNotifiesActiveSubscribers) {
+ content::PermissionControllerDelegate::SubscriptionId subscription_id =
+ GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+ PermissionType::GEOLOCATION, main_rfh(), url(),
+ base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
+ base::Unretained(this)));
+
+ GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+ PermissionType::GEOLOCATION, main_rfh(), url(),
+ base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
+ base::Unretained(this)));
+
+ GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
+ subscription_id);
+
+ GetHostContentSettingsMap()->SetContentSettingDefaultScope(
+ url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW);
+
+ EXPECT_EQ(callback_count(), 1);
+}
+
TEST_F(PermissionManagerTest, DifferentPrimaryUrlDoesNotNotify) {
content::PermissionControllerDelegate::SubscriptionId subscription_id =
GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
@@ -854,4 +878,49 @@ TEST_F(PermissionManagerTest, SubscribeWithPermissionDelegation) {
subscription_id);
}
+TEST_F(PermissionManagerTest, SubscribeUnsubscribeAndResubscribe) {
+ const char* kOrigin1 = "https://example.com";
+ NavigateAndCommit(GURL(kOrigin1));
+
+ content::PermissionControllerDelegate::SubscriptionId subscription_id =
+ GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+ PermissionType::GEOLOCATION, main_rfh(), GURL(kOrigin1),
+ base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
+ base::Unretained(this)));
+ EXPECT_EQ(callback_count(), 0);
+
+ GetHostContentSettingsMap()->SetContentSettingDefaultScope(
+ url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW);
+
+ EXPECT_EQ(callback_count(), 1);
+ EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
+
+ GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
+ subscription_id);
+
+ // ensure no callbacks are received when unsubscribed.
+ GetHostContentSettingsMap()->SetContentSettingDefaultScope(
+ url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_BLOCK);
+ GetHostContentSettingsMap()->SetContentSettingDefaultScope(
+ url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW);
+
+ EXPECT_EQ(callback_count(), 1);
+
+ content::PermissionControllerDelegate::SubscriptionId subscription_id_2 =
+ GetPermissionControllerDelegate()->SubscribePermissionStatusChange(
+ PermissionType::GEOLOCATION, main_rfh(), GURL(kOrigin1),
+ base::BindRepeating(&PermissionManagerTest::OnPermissionChange,
+ base::Unretained(this)));
+ EXPECT_EQ(callback_count(), 1);
+
+ GetHostContentSettingsMap()->SetContentSettingDefaultScope(
+ url(), url(), ContentSettingsType::GEOLOCATION, CONTENT_SETTING_BLOCK);
+
+ EXPECT_EQ(callback_count(), 2);
+ EXPECT_EQ(PermissionStatus::DENIED, callback_result());
+
+ GetPermissionControllerDelegate()->UnsubscribePermissionStatusChange(
+ subscription_id_2);
+}
+
} // namespace permissions
diff --git a/chromium/components/permissions/permission_prompt.h b/chromium/components/permissions/permission_prompt.h
index a1e3dec7d5f..d6718764adf 100644
--- a/chromium/components/permissions/permission_prompt.h
+++ b/chromium/components/permissions/permission_prompt.h
@@ -6,7 +6,6 @@
#define COMPONENTS_PERMISSIONS_PERMISSION_PROMPT_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/components/permissions/permission_request.cc b/chromium/components/permissions/permission_request.cc
index c3766a16d61..760ecab0484 100644
--- a/chromium/components/permissions/permission_request.cc
+++ b/chromium/components/permissions/permission_request.cc
@@ -10,6 +10,11 @@ namespace permissions {
PermissionRequest::PermissionRequest() {}
+bool PermissionRequest::IsDuplicateOf(PermissionRequest* other_request) const {
+ return GetRequestType() == other_request->GetRequestType() &&
+ GetOrigin() == other_request->GetOrigin();
+}
+
PermissionRequestGestureType PermissionRequest::GetGestureType() const {
return PermissionRequestGestureType::UNKNOWN;
}
@@ -19,18 +24,8 @@ ContentSettingsType PermissionRequest::GetContentSettingsType() const {
}
#if !defined(OS_ANDROID)
-base::Optional<std::u16string> PermissionRequest::GetChipText() const {
- return base::nullopt;
-}
-#endif
-
-#if defined(OS_ANDROID)
-std::u16string PermissionRequest::GetQuietTitleText() const {
- return std::u16string();
-}
-
-std::u16string PermissionRequest::GetQuietMessageText() const {
- return GetMessageText();
+absl::optional<std::u16string> PermissionRequest::GetChipText() const {
+ return absl::nullopt;
}
#endif
diff --git a/chromium/components/permissions/permission_request.h b/chromium/components/permissions/permission_request.h
index 65523f9b071..5b5d0ad18d7 100644
--- a/chromium/components/permissions/permission_request.h
+++ b/chromium/components/permissions/permission_request.h
@@ -8,10 +8,10 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/permissions/permission_request_enums.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace permissions {
@@ -33,31 +33,25 @@ class PermissionRequest {
// The type of this request.
virtual RequestType GetRequestType() const = 0;
+ // Whether |this| and |other_request| are duplicates and therefore don't both
+ // need to be shown in the UI.
+ virtual bool IsDuplicateOf(PermissionRequest* other_request) const;
+
#if defined(OS_ANDROID)
// Returns the full prompt text for this permission. This is currently only
// used on Android.
virtual std::u16string GetMessageText() const = 0;
-
- // Returns the title of this permission as text when the permission request is
- // displayed as a quiet prompt. Only used on Android. By default it returns
- // the same value as |GetTitleText| unless overridden.
- virtual std::u16string GetQuietTitleText() const;
-
- // Returns the full prompt text for this permission as text when the
- // permission request is displayed as a quiet prompt. Only used on Android. By
- // default it returns the same value as |GetMessageText| unless overridden.
- virtual std::u16string GetQuietMessageText() const;
#endif
#if !defined(OS_ANDROID)
// Returns the short text for the chip button related to this permission.
- virtual base::Optional<std::u16string> GetChipText() const;
-#endif
+ virtual absl::optional<std::u16string> GetChipText() const;
// Returns the shortened prompt text for this permission. The permission
// bubble may coalesce different requests, and if it does, this text will
// be displayed next to an image and indicate the user grants the permission.
virtual std::u16string GetMessageTextFragment() const = 0;
+#endif
// Get the origin on whose behalf this permission request is being made.
virtual GURL GetOrigin() const = 0;
diff --git a/chromium/components/permissions/permission_request_id.cc b/chromium/components/permissions/permission_request_id.cc
index cc9a91e0592..fee82df27b2 100644
--- a/chromium/components/permissions/permission_request_id.cc
+++ b/chromium/components/permissions/permission_request_id.cc
@@ -4,6 +4,7 @@
#include "components/permissions/permission_request_id.h"
+#include <inttypes.h>
#include <stdint.h>
#include "base/strings/stringprintf.h"
diff --git a/chromium/components/permissions/permission_request_impl.cc b/chromium/components/permissions/permission_request_impl.cc
index c670f1be7b0..40f912bb3ba 100644
--- a/chromium/components/permissions/permission_request_impl.cc
+++ b/chromium/components/permissions/permission_request_impl.cc
@@ -91,29 +91,47 @@ std::u16string PermissionRequestImpl::GetMessageText() const {
url_formatter::FormatUrlForSecurityDisplay(
GetOrigin(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
}
+#endif // defined(OS_ANDROID)
-std::u16string PermissionRequestImpl::GetQuietTitleText() const {
- if (content_settings_type_ == ContentSettingsType::NOTIFICATIONS) {
- return l10n_util::GetStringFUTF16(
- IDS_NOTIFICATION_QUIET_PERMISSION_PROMPT_TITLE,
- url_formatter::FormatUrlForSecurityDisplay(
- GetOrigin(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
- }
-
- NOTREACHED();
- return std::u16string();
-}
-
-std::u16string PermissionRequestImpl::GetQuietMessageText() const {
- if (content_settings_type_ == ContentSettingsType::NOTIFICATIONS) {
- return l10n_util::GetStringUTF16(
- IDS_NOTIFICATION_QUIET_PERMISSION_PROMPT_MESSAGE);
+#if !defined(OS_ANDROID)
+absl::optional<std::u16string> PermissionRequestImpl::GetChipText() const {
+ int message_id;
+ switch (content_settings_type_) {
+ case ContentSettingsType::GEOLOCATION:
+ message_id = IDS_GEOLOCATION_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::NOTIFICATIONS:
+ message_id = IDS_NOTIFICATION_PERMISSIONS_CHIP;
+ break;
+ case ContentSettingsType::MIDI_SYSEX:
+ message_id = IDS_MIDI_SYSEX_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::MEDIASTREAM_MIC:
+ message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::MEDIASTREAM_CAMERA:
+ message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::CLIPBOARD_READ_WRITE:
+ message_id = IDS_CLIPBOARD_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::VR:
+ message_id = IDS_VR_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::AR:
+ message_id = IDS_AR_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::IDLE_DETECTION:
+ message_id = IDS_IDLE_DETECTION_PERMISSION_CHIP;
+ break;
+ default:
+ // TODO(bsep): We don't actually want to support having no string in the
+ // long term, but writing them takes time. In the meantime, we fall back
+ // to the existing UI when the string is missing.
+ return absl::nullopt;
}
-
- NOTREACHED();
- return GetMessageText();
+ return l10n_util::GetStringUTF16(message_id);
}
-#endif
std::u16string PermissionRequestImpl::GetMessageTextFragment() const {
int message_id;
@@ -127,7 +145,7 @@ std::u16string PermissionRequestImpl::GetMessageTextFragment() const {
case ContentSettingsType::MIDI_SYSEX:
message_id = IDS_MIDI_SYSEX_PERMISSION_FRAGMENT;
break;
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER:
message_id = IDS_PROTECTED_MEDIA_IDENTIFIER_PERMISSION_FRAGMENT;
break;
@@ -168,56 +186,13 @@ std::u16string PermissionRequestImpl::GetMessageTextFragment() const {
case ContentSettingsType::IDLE_DETECTION:
message_id = IDS_IDLE_DETECTION_PERMISSION_FRAGMENT;
break;
- case ContentSettingsType::FILE_HANDLING:
- message_id = IDS_FILE_HANDLING_PERMISSION_FRAGMENT;
- break;
default:
NOTREACHED();
return std::u16string();
}
return l10n_util::GetStringUTF16(message_id);
}
-
-#if !defined(OS_ANDROID)
-base::Optional<std::u16string> PermissionRequestImpl::GetChipText() const {
- int message_id;
- switch (content_settings_type_) {
- case ContentSettingsType::GEOLOCATION:
- message_id = IDS_GEOLOCATION_PERMISSION_CHIP;
- break;
- case ContentSettingsType::NOTIFICATIONS:
- message_id = IDS_NOTIFICATION_PERMISSIONS_CHIP;
- break;
- case ContentSettingsType::MIDI_SYSEX:
- message_id = IDS_MIDI_SYSEX_PERMISSION_CHIP;
- break;
- case ContentSettingsType::MEDIASTREAM_MIC:
- message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_CHIP;
- break;
- case ContentSettingsType::MEDIASTREAM_CAMERA:
- message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_CHIP;
- break;
- case ContentSettingsType::CLIPBOARD_READ_WRITE:
- message_id = IDS_CLIPBOARD_PERMISSION_CHIP;
- break;
- case ContentSettingsType::VR:
- message_id = IDS_VR_PERMISSION_CHIP;
- break;
- case ContentSettingsType::AR:
- message_id = IDS_AR_PERMISSION_CHIP;
- break;
- case ContentSettingsType::IDLE_DETECTION:
- message_id = IDS_IDLE_DETECTION_PERMISSION_CHIP;
- break;
- default:
- // TODO(bsep): We don't actually want to support having no string in the
- // long term, but writing them takes time. In the meantime, we fall back
- // to the existing UI when the string is missing.
- return base::nullopt;
- }
- return l10n_util::GetStringUTF16(message_id);
-}
-#endif
+#endif // !defined(OS_ANDROID)
GURL PermissionRequestImpl::GetOrigin() const {
return request_origin_;
diff --git a/chromium/components/permissions/permission_request_impl.h b/chromium/components/permissions/permission_request_impl.h
index 6695a451c6a..4608b0cb03d 100644
--- a/chromium/components/permissions/permission_request_impl.h
+++ b/chromium/components/permissions/permission_request_impl.h
@@ -7,12 +7,12 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/permissions/permission_request.h"
#include "components/permissions/permission_request_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -35,18 +35,19 @@ class PermissionRequestImpl : public PermissionRequest {
~PermissionRequestImpl() override;
+// PermissionRequest:
+#if !defined(OS_ANDROID)
+ // Implementors can override this method to customize the message text.
+ std::u16string GetMessageTextFragment() const override;
+#endif
+
private:
- // PermissionRequest:
RequestType GetRequestType() const override;
#if defined(OS_ANDROID)
std::u16string GetMessageText() const override;
- std::u16string GetQuietTitleText() const override;
- std::u16string GetQuietMessageText() const override;
+#else
+ absl::optional<std::u16string> GetChipText() const override;
#endif
-#if !defined(OS_ANDROID)
- base::Optional<std::u16string> GetChipText() const override;
-#endif
- std::u16string GetMessageTextFragment() const override;
GURL GetOrigin() const override;
void PermissionGranted(bool is_one_time) override;
void PermissionDenied() override;
diff --git a/chromium/components/permissions/permission_request_manager.cc b/chromium/components/permissions/permission_request_manager.cc
index c4c308f0349..fbf3992d6b6 100644
--- a/chromium/components/permissions/permission_request_manager.cc
+++ b/chromium/components/permissions/permission_request_manager.cc
@@ -69,16 +69,6 @@ constexpr char kAbusiveNotificationContentWarningMessage[] =
namespace {
-bool IsMessageTextEqual(PermissionRequest* a, PermissionRequest* b) {
- if (a == b)
- return true;
- if (a->GetMessageTextFragment() == b->GetMessageTextFragment() &&
- a->GetOrigin() == b->GetOrigin()) {
- return true;
- }
- return false;
-}
-
bool IsMediaRequest(RequestType type) {
#if !defined(OS_ANDROID)
if (type == RequestType::kCameraPanTiltZoom)
@@ -141,6 +131,12 @@ void PermissionRequestManager::AddRequest(
return;
}
+ if (source_frame->IsInactiveAndDisallowActivation()) {
+ request->Cancelled();
+ request->RequestFinished();
+ return;
+ }
+
if (is_notification_prompt_cooldown_active_ &&
request->GetContentSettingsType() == ContentSettingsType::NOTIFICATIONS) {
// Short-circuit by canceling rather than denying to avoid creating a large
@@ -166,12 +162,13 @@ void PermissionRequestManager::AddRequest(
// any other renderer-side nav initiations?). Double-check this for
// correct behavior on interstitials -- we probably want to basically queue
// any request for which GetVisibleURL != GetLastCommittedURL.
- const GURL& main_frame_url_ = web_contents()->GetLastCommittedURL();
+ CHECK_EQ(source_frame->GetMainFrame(), web_contents()->GetMainFrame());
+ const GURL& main_frame_url = web_contents()->GetLastCommittedURL();
bool is_main_frame =
- url::Origin::Create(main_frame_url_)
+ url::Origin::Create(main_frame_url)
.IsSameOriginWith(url::Origin::Create(request->GetOrigin()));
- base::Optional<url::Origin> auto_approval_origin =
+ absl::optional<url::Origin> auto_approval_origin =
PermissionsClient::Get()->GetAutoApprovalOrigin();
if (auto_approval_origin) {
if (url::Origin::Create(request->GetOrigin()) ==
@@ -255,7 +252,7 @@ void PermissionRequestManager::UpdateAnchor() {
void PermissionRequestManager::DidStartNavigation(
content::NavigationHandle* navigation_handle) {
- if (!navigation_handle->IsInMainFrame() ||
+ if (!navigation_handle->IsInPrimaryMainFrame() ||
navigation_handle->IsSameDocument()) {
return;
}
@@ -274,7 +271,7 @@ void PermissionRequestManager::DidStartNavigation(
void PermissionRequestManager::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
- if (!navigation_handle->IsInMainFrame() ||
+ if (!navigation_handle->IsInPrimaryMainFrame() ||
!navigation_handle->HasCommitted() ||
navigation_handle->IsSameDocument()) {
return;
@@ -457,8 +454,8 @@ PermissionRequestManager::PermissionRequestManager(
tab_is_hidden_(web_contents->GetVisibility() ==
content::Visibility::HIDDEN),
auto_response_for_test_(NONE),
- notification_permission_ui_selectors_(
- PermissionsClient::Get()->CreateNotificationPermissionUiSelectors(
+ permission_ui_selectors_(
+ PermissionsClient::Get()->CreatePermissionUiSelectors(
web_contents->GetBrowserContext())) {}
void PermissionRequestManager::ScheduleShowBubble() {
@@ -513,21 +510,27 @@ void PermissionRequestManager::DequeueRequestIfNeeded() {
}
}
- if (!notification_permission_ui_selectors_.empty() &&
- requests_.front()->GetRequestType() == RequestType::kNotifications) {
+ if (!permission_ui_selectors_.empty()) {
DCHECK(!current_request_ui_to_use_.has_value());
// Initialize the selector decisions vector.
DCHECK(selector_decisions_.empty());
- selector_decisions_.resize(notification_permission_ui_selectors_.size());
+ selector_decisions_.resize(permission_ui_selectors_.size());
for (size_t selector_index = 0;
- selector_index < notification_permission_ui_selectors_.size();
- ++selector_index) {
- notification_permission_ui_selectors_[selector_index]->SelectUiToUse(
- requests_.front(),
- base::BindOnce(
- &PermissionRequestManager::OnNotificationPermissionUiSelectorDone,
- weak_factory_.GetWeakPtr(), selector_index));
+ selector_index < permission_ui_selectors_.size(); ++selector_index) {
+ if (permission_ui_selectors_[selector_index]
+ ->IsPermissionRequestSupported(
+ requests_.front()->GetRequestType())) {
+ permission_ui_selectors_[selector_index]->SelectUiToUse(
+ requests_.front(),
+ base::BindOnce(
+ &PermissionRequestManager::OnPermissionUiSelectorDone,
+ weak_factory_.GetWeakPtr(), selector_index));
+ } else {
+ OnPermissionUiSelectorDone(
+ selector_index,
+ PermissionUiSelector::Decision::UseNormalUiAndShowNoWarning());
+ }
}
} else {
current_request_ui_to_use_ =
@@ -602,7 +605,7 @@ void PermissionRequestManager::DeleteBubble() {
}
void PermissionRequestManager::ResetViewStateForCurrentRequest() {
- for (const auto& selector : notification_permission_ui_selectors_)
+ for (const auto& selector : permission_ui_selectors_)
selector->Cancel();
current_request_already_displayed_ = false;
@@ -636,7 +639,7 @@ void PermissionRequestManager::FinalizeCurrentRequests(
PermissionsClient::Get()->GetPermissionDecisionAutoBlocker(
browser_context);
- base::Optional<QuietUiReason> quiet_ui_reason;
+ absl::optional<QuietUiReason> quiet_ui_reason;
if (ShouldCurrentRequestUseQuietUI())
quiet_ui_reason = ReasonForUsingQuietUi();
@@ -704,11 +707,11 @@ void PermissionRequestManager::CleanUpRequests() {
PermissionRequest* PermissionRequestManager::GetExistingRequest(
PermissionRequest* request) {
for (PermissionRequest* existing_request : requests_) {
- if (IsMessageTextEqual(existing_request, request))
+ if (request->IsDuplicateOf(existing_request))
return existing_request;
}
for (PermissionRequest* queued_request : queued_requests_) {
- if (IsMessageTextEqual(queued_request, request))
+ if (request->IsDuplicateOf(queued_request))
return queued_request;
}
return nullptr;
@@ -773,14 +776,14 @@ void PermissionRequestManager::RemoveObserver(Observer* observer) {
bool PermissionRequestManager::ShouldCurrentRequestUseQuietUI() const {
// ContentSettingImageModel might call into this method if the user switches
// between tabs while the |notification_permission_ui_selectors_| are pending.
- return ReasonForUsingQuietUi() != base::nullopt;
+ return ReasonForUsingQuietUi() != absl::nullopt;
}
-base::Optional<PermissionRequestManager::QuietUiReason>
+absl::optional<PermissionRequestManager::QuietUiReason>
PermissionRequestManager::ReasonForUsingQuietUi() const {
if (!IsRequestInProgress() || !current_request_ui_to_use_ ||
!current_request_ui_to_use_->quiet_ui_reason)
- return base::nullopt;
+ return absl::nullopt;
return *(current_request_ui_to_use_->quiet_ui_reason);
}
@@ -799,7 +802,7 @@ void PermissionRequestManager::NotifyBubbleRemoved() {
observer.OnBubbleRemoved();
}
-void PermissionRequestManager::OnNotificationPermissionUiSelectorDone(
+void PermissionRequestManager::OnPermissionUiSelectorDone(
size_t selector_index,
const UiDecision& decision) {
if (decision.warning_reason) {
@@ -828,9 +831,8 @@ void PermissionRequestManager::OnNotificationPermissionUiSelectorDone(
selector_decisions_[decision_index].value();
if (!prediction_grant_likelihood_.has_value()) {
- prediction_grant_likelihood_ =
- notification_permission_ui_selectors_[decision_index]
- ->PredictedGrantLikelihoodForUKM();
+ prediction_grant_likelihood_ = permission_ui_selectors_[decision_index]
+ ->PredictedGrantLikelihoodForUKM();
}
if (current_decision.quiet_ui_reason.has_value()) {
diff --git a/chromium/components/permissions/permission_request_manager.h b/chromium/components/permissions/permission_request_manager.h
index ec2dab58f7d..4442cb80216 100644
--- a/chromium/components/permissions/permission_request_manager.h
+++ b/chromium/components/permissions/permission_request_manager.h
@@ -15,8 +15,8 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
-#include "components/permissions/notification_permission_ui_selector.h"
#include "components/permissions/permission_prompt.h"
+#include "components/permissions/permission_ui_selector.h"
#include "components/permissions/permission_uma_util.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
@@ -88,9 +88,9 @@ class PermissionRequestManager
enum AutoResponseType { NONE, ACCEPT_ONCE, ACCEPT_ALL, DENY_ALL, DISMISS };
- using UiDecision = NotificationPermissionUiSelector::Decision;
- using QuietUiReason = NotificationPermissionUiSelector::QuietUiReason;
- using WarningReason = NotificationPermissionUiSelector::WarningReason;
+ using UiDecision = PermissionUiSelector::Decision;
+ using QuietUiReason = PermissionUiSelector::QuietUiReason;
+ using WarningReason = PermissionUiSelector::WarningReason;
~PermissionRequestManager() override;
@@ -118,8 +118,8 @@ class PermissionRequestManager
bool ShouldCurrentRequestUseQuietUI() const;
// If |ShouldCurrentRequestUseQuietUI| return true, this will provide a reason
- // as to why the quiet UI needs to be used. Returns `base::nullopt` otherwise.
- base::Optional<QuietUiReason> ReasonForUsingQuietUi() const;
+ // as to why the quiet UI needs to be used. Returns `absl::nullopt` otherwise.
+ absl::optional<QuietUiReason> ReasonForUsingQuietUi() const;
bool IsRequestInProgress() const;
@@ -160,22 +160,22 @@ class PermissionRequestManager
// For testing only, used to override the default UI selectors and instead use
// a new one.
- void set_notification_permission_ui_selector_for_testing(
- std::unique_ptr<NotificationPermissionUiSelector> selector) {
- clear_notification_permission_ui_selector_for_testing();
- add_notification_permission_ui_selector_for_testing(std::move(selector));
+ void set_permission_ui_selector_for_testing(
+ std::unique_ptr<PermissionUiSelector> selector) {
+ clear_permission_ui_selector_for_testing();
+ add_permission_ui_selector_for_testing(std::move(selector));
}
// For testing only, used to add a new selector without overriding the
// existing ones.
- void add_notification_permission_ui_selector_for_testing(
- std::unique_ptr<NotificationPermissionUiSelector> selector) {
- notification_permission_ui_selectors_.emplace_back(std::move(selector));
+ void add_permission_ui_selector_for_testing(
+ std::unique_ptr<PermissionUiSelector> selector) {
+ permission_ui_selectors_.emplace_back(std::move(selector));
}
// For testing only, clear the existing ui selectors.
- void clear_notification_permission_ui_selector_for_testing() {
- notification_permission_ui_selectors_.clear();
+ void clear_permission_ui_selector_for_testing() {
+ permission_ui_selectors_.clear();
}
void set_view_factory_for_testing(PermissionPrompt::Factory view_factory) {
@@ -184,12 +184,12 @@ class PermissionRequestManager
PermissionPrompt* view_for_testing() { return view_.get(); }
- base::Optional<PermissionUmaUtil::PredictionGrantLikelihood>
+ absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
prediction_grant_likelihood_for_testing() {
return prediction_grant_likelihood_;
}
- base::Optional<permissions::PermissionPromptDisposition>
+ absl::optional<permissions::PermissionPromptDisposition>
current_request_prompt_disposition_for_testing() {
return current_request_prompt_disposition_;
}
@@ -252,8 +252,8 @@ class PermissionRequestManager
void NotifyBubbleAdded();
void NotifyBubbleRemoved();
- void OnNotificationPermissionUiSelectorDone(size_t selector_index,
- const UiDecision& decision);
+ void OnPermissionUiSelectorDone(size_t selector_index,
+ const UiDecision& decision);
PermissionPromptDisposition DetermineCurrentRequestUIDispositionForUMA();
PermissionPromptDispositionReason
@@ -275,7 +275,7 @@ class PermissionRequestManager
// The disposition for the currently active permission prompt, if any.
// Recorded separately because the `view_` might not be available at prompt
// resolution in order to determine the disposition.
- base::Optional<permissions::PermissionPromptDisposition>
+ absl::optional<permissions::PermissionPromptDisposition>
current_request_prompt_disposition_;
// We only show new prompts when |tab_is_hidden_| is false.
@@ -317,15 +317,14 @@ class PermissionRequestManager
bool is_notification_prompt_cooldown_active_ = false;
// A vector of selectors which decide if the quiet prompt UI should be used
- // to display notification permission requests. Sorted from the highest
- // priority to the lowest priority selector.
- std::vector<std::unique_ptr<NotificationPermissionUiSelector>>
- notification_permission_ui_selectors_;
+ // to display permission requests. Sorted from the highest priority to the
+ // lowest priority selector.
+ std::vector<std::unique_ptr<PermissionUiSelector>> permission_ui_selectors_;
// Holds the decisions returned by selectors. Needed in case a lower priority
// selector returns a decision first and we need to wait for the decisions of
// higher priority selectors before making use of it.
- std::vector<base::Optional<NotificationPermissionUiSelector::Decision>>
+ std::vector<absl::optional<PermissionUiSelector::Decision>>
selector_decisions_;
// Whether the view for the current |requests_| has been shown to the user at
@@ -338,12 +337,12 @@ class PermissionRequestManager
// Whether to use the normal or quiet UI to display the current permission
// |requests_|, and whether to show warnings. This will be nullopt if we are
- // still waiting on the result from |notification_permission_ui_selectors_|.
- base::Optional<UiDecision> current_request_ui_to_use_;
+ // still waiting on the result from |permission_ui_selectors_|.
+ absl::optional<UiDecision> current_request_ui_to_use_;
// The likelihood value returned by the Web Permission Predictions Service,
// to be recoreded in UKM.
- base::Optional<PermissionUmaUtil::PredictionGrantLikelihood>
+ absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
prediction_grant_likelihood_;
// True when the prompt is being temporary destroyed to be recreated for the
diff --git a/chromium/components/permissions/permission_request_manager_unittest.cc b/chromium/components/permissions/permission_request_manager_unittest.cc
index 8a36803c39b..71e9e462a85 100644
--- a/chromium/components/permissions/permission_request_manager_unittest.cc
+++ b/chromium/components/permissions/permission_request_manager_unittest.cc
@@ -8,16 +8,15 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "build/build_config.h"
#include "components/permissions/features.h"
-#include "components/permissions/notification_permission_ui_selector.h"
#include "components/permissions/permission_request.h"
#include "components/permissions/permission_request_manager.h"
+#include "components/permissions/permission_ui_selector.h"
#include "components/permissions/permission_uma_util.h"
#include "components/permissions/request_type.h"
#include "components/permissions/test/mock_permission_prompt_factory.h"
@@ -25,11 +24,12 @@
#include "components/permissions/test/test_permissions_client.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace permissions {
namespace {
-using QuietUiReason = NotificationPermissionUiSelector::QuietUiReason;
+using QuietUiReason = PermissionUiSelector::QuietUiReason;
}
class PermissionRequestManagerTest
@@ -37,34 +37,33 @@ class PermissionRequestManagerTest
public ::testing::WithParamInterface<bool> {
public:
PermissionRequestManagerTest()
- : content::RenderViewHostTestHarness(),
- request1_("test1",
+ : request1_(u"test1",
RequestType::kDiskQuota,
PermissionRequestGestureType::GESTURE),
- request2_("test2",
+ request2_(u"test2",
RequestType::kMultipleDownloads,
PermissionRequestGestureType::NO_GESTURE),
- request_mic_("mic",
+ request_mic_(u"mic",
RequestType::kMicStream,
PermissionRequestGestureType::NO_GESTURE),
- request_camera_("cam",
+ request_camera_(u"cam",
RequestType::kCameraStream,
PermissionRequestGestureType::NO_GESTURE),
#if !defined(OS_ANDROID)
- request_ptz_("ptz",
+ request_ptz_(u"ptz",
RequestType::kCameraPanTiltZoom,
PermissionRequestGestureType::NO_GESTURE),
#endif
- iframe_request_same_domain_("iframe",
+ iframe_request_same_domain_(u"iframe",
RequestType::kNotifications,
GURL("http://www.google.com/some/url")),
- iframe_request_other_domain_("iframe",
+ iframe_request_other_domain_(u"iframe",
RequestType::kGeolocation,
GURL("http://www.youtube.com")),
- iframe_request_camera_other_domain_("iframe",
+ iframe_request_camera_other_domain_(u"iframe",
RequestType::kCameraStream,
GURL("http://www.youtube.com")),
- iframe_request_mic_other_domain_("iframe",
+ iframe_request_mic_other_domain_(u"iframe",
RequestType::kMicStream,
GURL("http://www.youtube.com")) {
feature_list_.InitWithFeatureState(permissions::features::kPermissionChip,
@@ -483,33 +482,33 @@ TEST_P(PermissionRequestManagerTest, DuplicateRequest) {
WaitForBubbleToBeShown();
manager_->AddRequest(web_contents()->GetMainFrame(), &request2_);
- MockPermissionRequest dupe_request("test1");
- manager_->AddRequest(web_contents()->GetMainFrame(), &dupe_request);
- EXPECT_FALSE(dupe_request.finished());
+ auto dupe_request = request1_.CreateDuplicateRequest();
+ manager_->AddRequest(web_contents()->GetMainFrame(), dupe_request.get());
+ EXPECT_FALSE(dupe_request->finished());
EXPECT_FALSE(request1_.finished());
- MockPermissionRequest dupe_request2("test2");
- manager_->AddRequest(web_contents()->GetMainFrame(), &dupe_request2);
- EXPECT_FALSE(dupe_request2.finished());
+ auto dupe_request2 = request2_.CreateDuplicateRequest();
+ manager_->AddRequest(web_contents()->GetMainFrame(), dupe_request2.get());
+ EXPECT_FALSE(dupe_request2->finished());
EXPECT_FALSE(request2_.finished());
WaitForBubbleToBeShown();
Accept();
if (GetParam()) {
- EXPECT_TRUE(dupe_request2.finished());
+ EXPECT_TRUE(dupe_request2->finished());
EXPECT_TRUE(request2_.finished());
} else {
- EXPECT_TRUE(dupe_request.finished());
+ EXPECT_TRUE(dupe_request->finished());
EXPECT_TRUE(request1_.finished());
}
WaitForBubbleToBeShown();
Accept();
if (GetParam()) {
- EXPECT_TRUE(dupe_request.finished());
+ EXPECT_TRUE(dupe_request->finished());
EXPECT_TRUE(request1_.finished());
} else {
- EXPECT_TRUE(dupe_request2.finished());
+ EXPECT_TRUE(dupe_request2->finished());
EXPECT_TRUE(request2_.finished());
}
}
@@ -680,14 +679,13 @@ TEST_P(PermissionRequestManagerTest, UMAForTabSwitching) {
// UI selectors
////////////////////////////////////////////////////////////////////////////////
-// Simulate a NotificationPermissionUiSelector that simply returns a
-// predefined |ui_to_use| every time.
-class MockNotificationPermissionUiSelector
- : public NotificationPermissionUiSelector {
+// Simulate a PermissionUiSelector that simply returns a predefined |ui_to_use|
+// every time.
+class MockNotificationPermissionUiSelector : public PermissionUiSelector {
public:
explicit MockNotificationPermissionUiSelector(
- base::Optional<QuietUiReason> quiet_ui_reason,
- base::Optional<PermissionUmaUtil::PredictionGrantLikelihood>
+ absl::optional<QuietUiReason> quiet_ui_reason,
+ absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
prediction_likelihood,
bool async)
: quiet_ui_reason_(quiet_ui_reason),
@@ -705,35 +703,69 @@ class MockNotificationPermissionUiSelector
}
}
- base::Optional<PermissionUmaUtil::PredictionGrantLikelihood>
+ bool IsPermissionRequestSupported(RequestType request_type) override {
+ return request_type == RequestType::kNotifications ||
+ request_type == RequestType::kGeolocation;
+ }
+
+ absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
PredictedGrantLikelihoodForUKM() override {
return prediction_likelihood_;
}
static void CreateForManager(
PermissionRequestManager* manager,
- base::Optional<QuietUiReason> quiet_ui_reason,
+ absl::optional<QuietUiReason> quiet_ui_reason,
bool async,
- base::Optional<PermissionUmaUtil::PredictionGrantLikelihood>
- prediction_likelihood = base::nullopt) {
- manager->add_notification_permission_ui_selector_for_testing(
+ absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
+ prediction_likelihood = absl::nullopt) {
+ manager->add_permission_ui_selector_for_testing(
std::make_unique<MockNotificationPermissionUiSelector>(
quiet_ui_reason, prediction_likelihood, async));
}
private:
- base::Optional<QuietUiReason> quiet_ui_reason_;
- base::Optional<PermissionUmaUtil::PredictionGrantLikelihood>
+ absl::optional<QuietUiReason> quiet_ui_reason_;
+ absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
prediction_likelihood_;
bool async_;
};
+// Same as the MockNotificationPermissionUiSelector but handling only the
+// Camera stream request type
+class MockCameraStreamPermissionUiSelector
+ : public MockNotificationPermissionUiSelector {
+ public:
+ explicit MockCameraStreamPermissionUiSelector(
+ absl::optional<QuietUiReason> quiet_ui_reason,
+ absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
+ prediction_likelihood,
+ bool async)
+ : MockNotificationPermissionUiSelector(quiet_ui_reason,
+ prediction_likelihood,
+ async) {}
+
+ bool IsPermissionRequestSupported(RequestType request_type) override {
+ return request_type == RequestType::kCameraStream;
+ }
+
+ static void CreateForManager(
+ PermissionRequestManager* manager,
+ absl::optional<QuietUiReason> quiet_ui_reason,
+ bool async,
+ absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
+ prediction_likelihood = absl::nullopt) {
+ manager->add_permission_ui_selector_for_testing(
+ std::make_unique<MockCameraStreamPermissionUiSelector>(
+ quiet_ui_reason, prediction_likelihood, async));
+ }
+};
+
TEST_P(PermissionRequestManagerTest,
UiSelectorNotUsedForPermissionsOtherThanNotification) {
- manager_->clear_notification_permission_ui_selector_for_testing();
+ manager_->clear_permission_ui_selector_for_testing();
MockNotificationPermissionUiSelector::CreateForManager(
- manager_,
- NotificationPermissionUiSelector::QuietUiReason::kEnabledInPrefs,
+ manager_, PermissionUiSelector::QuietUiReason::kEnabledInPrefs,
false /* async */);
manager_->AddRequest(web_contents()->GetMainFrame(), &request_camera_);
@@ -750,22 +782,21 @@ TEST_P(PermissionRequestManagerTest,
TEST_P(PermissionRequestManagerTest, UiSelectorUsedForNotifications) {
const struct {
- base::Optional<NotificationPermissionUiSelector::QuietUiReason>
- quiet_ui_reason;
+ absl::optional<PermissionUiSelector::QuietUiReason> quiet_ui_reason;
bool async;
} kTests[] = {
{QuietUiReason::kEnabledInPrefs, true},
- {NotificationPermissionUiSelector::Decision::UseNormalUi(), true},
+ {PermissionUiSelector::Decision::UseNormalUi(), true},
{QuietUiReason::kEnabledInPrefs, false},
- {NotificationPermissionUiSelector::Decision::UseNormalUi(), false},
+ {PermissionUiSelector::Decision::UseNormalUi(), false},
};
for (const auto& test : kTests) {
- manager_->clear_notification_permission_ui_selector_for_testing();
+ manager_->clear_permission_ui_selector_for_testing();
MockNotificationPermissionUiSelector::CreateForManager(
manager_, test.quiet_ui_reason, test.async);
- MockPermissionRequest request("foo", RequestType::kNotifications,
+ MockPermissionRequest request(u"foo", RequestType::kNotifications,
PermissionRequestGestureType::GESTURE);
manager_->AddRequest(web_contents()->GetMainFrame(), &request);
@@ -783,23 +814,21 @@ TEST_P(PermissionRequestManagerTest, UiSelectorUsedForNotifications) {
TEST_P(PermissionRequestManagerTest,
UiSelectionHappensSeparatelyForEachRequest) {
- using QuietUiReason = NotificationPermissionUiSelector::QuietUiReason;
- manager_->clear_notification_permission_ui_selector_for_testing();
+ manager_->clear_permission_ui_selector_for_testing();
MockNotificationPermissionUiSelector::CreateForManager(
manager_, QuietUiReason::kEnabledInPrefs, true);
- MockPermissionRequest request1("request1", RequestType::kNotifications,
+ MockPermissionRequest request1(u"request1", RequestType::kNotifications,
PermissionRequestGestureType::GESTURE);
manager_->AddRequest(web_contents()->GetMainFrame(), &request1);
WaitForBubbleToBeShown();
EXPECT_TRUE(manager_->ShouldCurrentRequestUseQuietUI());
Accept();
- MockPermissionRequest request2("request2", RequestType::kNotifications,
+ MockPermissionRequest request2(u"request2", RequestType::kNotifications,
PermissionRequestGestureType::GESTURE);
- manager_->clear_notification_permission_ui_selector_for_testing();
+ manager_->clear_permission_ui_selector_for_testing();
MockNotificationPermissionUiSelector::CreateForManager(
- manager_, NotificationPermissionUiSelector::Decision::UseNormalUi(),
- true);
+ manager_, PermissionUiSelector::Decision::UseNormalUi(), true);
manager_->AddRequest(web_contents()->GetMainFrame(), &request2);
WaitForBubbleToBeShown();
EXPECT_FALSE(manager_->ShouldCurrentRequestUseQuietUI());
@@ -807,12 +836,11 @@ TEST_P(PermissionRequestManagerTest,
}
TEST_P(PermissionRequestManagerTest, MultipleUiSelectors) {
- using QuietUiReason = NotificationPermissionUiSelector::QuietUiReason;
const struct {
- std::vector<base::Optional<QuietUiReason>> quiet_ui_reasons;
+ std::vector<absl::optional<QuietUiReason>> quiet_ui_reasons;
std::vector<bool> simulate_delayed_decision;
- base::Optional<QuietUiReason> expected_reason;
+ absl::optional<QuietUiReason> expected_reason;
} kTests[] = {
// Simple sync selectors, first one should take priority.
{{QuietUiReason::kTriggeredByCrowdDeny, QuietUiReason::kEnabledInPrefs},
@@ -824,43 +852,43 @@ TEST_P(PermissionRequestManagerTest, MultipleUiSelectors) {
{true, false},
QuietUiReason::kTriggeredByCrowdDeny},
// The first selector that has a quiet ui decision should be used.
- {{base::nullopt, base::nullopt,
+ {{absl::nullopt, absl::nullopt,
QuietUiReason::kTriggeredDueToAbusiveContent,
QuietUiReason::kEnabledInPrefs},
{false, true, true, false},
QuietUiReason::kTriggeredDueToAbusiveContent},
// If all selectors return a normal ui, it should use a normal ui.
- {{base::nullopt, base::nullopt}, {false, true}, base::nullopt},
+ {{absl::nullopt, absl::nullopt}, {false, true}, absl::nullopt},
// Use a bunch of selectors both async and sync.
- {{base::nullopt, base::nullopt, base::nullopt, base::nullopt,
- base::nullopt, QuietUiReason::kTriggeredDueToAbusiveRequests,
- base::nullopt, QuietUiReason::kEnabledInPrefs},
+ {{absl::nullopt, absl::nullopt, absl::nullopt, absl::nullopt,
+ absl::nullopt, QuietUiReason::kTriggeredDueToAbusiveRequests,
+ absl::nullopt, QuietUiReason::kEnabledInPrefs},
{false, true, false, true, true, true, false, false},
QuietUiReason::kTriggeredDueToAbusiveRequests},
// Use a bunch of selectors all sync.
- {{base::nullopt, base::nullopt, base::nullopt, base::nullopt,
- base::nullopt, QuietUiReason::kTriggeredDueToAbusiveRequests,
- base::nullopt, QuietUiReason::kEnabledInPrefs},
+ {{absl::nullopt, absl::nullopt, absl::nullopt, absl::nullopt,
+ absl::nullopt, QuietUiReason::kTriggeredDueToAbusiveRequests,
+ absl::nullopt, QuietUiReason::kEnabledInPrefs},
{false, false, false, false, false, false, false, false},
QuietUiReason::kTriggeredDueToAbusiveRequests},
// Use a bunch of selectors all async.
- {{base::nullopt, base::nullopt, base::nullopt, base::nullopt,
- base::nullopt, QuietUiReason::kTriggeredDueToAbusiveRequests,
- base::nullopt, QuietUiReason::kEnabledInPrefs},
+ {{absl::nullopt, absl::nullopt, absl::nullopt, absl::nullopt,
+ absl::nullopt, QuietUiReason::kTriggeredDueToAbusiveRequests,
+ absl::nullopt, QuietUiReason::kEnabledInPrefs},
{true, true, true, true, true, true, true, true},
QuietUiReason::kTriggeredDueToAbusiveRequests},
};
for (const auto& test : kTests) {
- manager_->clear_notification_permission_ui_selector_for_testing();
+ manager_->clear_permission_ui_selector_for_testing();
for (size_t i = 0; i < test.quiet_ui_reasons.size(); ++i) {
MockNotificationPermissionUiSelector::CreateForManager(
manager_, test.quiet_ui_reasons[i],
test.simulate_delayed_decision[i]);
}
- MockPermissionRequest request("foo", RequestType::kNotifications,
+ MockPermissionRequest request(u"foo", RequestType::kNotifications,
PermissionRequestGestureType::GESTURE);
manager_->AddRequest(web_contents()->GetMainFrame(), &request);
@@ -880,7 +908,6 @@ TEST_P(PermissionRequestManagerTest, MultipleUiSelectors) {
}
TEST_P(PermissionRequestManagerTest, SelectorsPredictionLikelihood) {
- using QuietUiReason = NotificationPermissionUiSelector::QuietUiReason;
using PredictionLikelihood = PermissionUmaUtil::PredictionGrantLikelihood;
const auto VeryLikely = PredictionLikelihood::
PermissionPrediction_Likelihood_DiscretizedLikelihood_VERY_LIKELY;
@@ -889,17 +916,17 @@ TEST_P(PermissionRequestManagerTest, SelectorsPredictionLikelihood) {
const struct {
std::vector<bool> enable_quiet_uis;
- std::vector<base::Optional<PredictionLikelihood>> prediction_likelihoods;
- base::Optional<PredictionLikelihood> expected_prediction_likelihood;
+ std::vector<absl::optional<PredictionLikelihood>> prediction_likelihoods;
+ absl::optional<PredictionLikelihood> expected_prediction_likelihood;
} kTests[] = {
// Sanity check: prediction likelihood is populated correctly.
{{true}, {VeryLikely}, VeryLikely},
{{false}, {Neutral}, Neutral},
// Prediction likelihood is populated only if the selector was considered.
- {{true, true}, {base::nullopt, VeryLikely}, base::nullopt},
- {{false, true}, {base::nullopt, VeryLikely}, VeryLikely},
- {{false, false}, {base::nullopt, VeryLikely}, VeryLikely},
+ {{true, true}, {absl::nullopt, VeryLikely}, absl::nullopt},
+ {{false, true}, {absl::nullopt, VeryLikely}, VeryLikely},
+ {{false, false}, {absl::nullopt, VeryLikely}, VeryLikely},
// First considered selector is preserved.
{{true, true}, {Neutral, VeryLikely}, Neutral},
@@ -908,17 +935,17 @@ TEST_P(PermissionRequestManagerTest, SelectorsPredictionLikelihood) {
};
for (const auto& test : kTests) {
- manager_->clear_notification_permission_ui_selector_for_testing();
+ manager_->clear_permission_ui_selector_for_testing();
for (size_t i = 0; i < test.enable_quiet_uis.size(); ++i) {
MockNotificationPermissionUiSelector::CreateForManager(
manager_,
test.enable_quiet_uis[i]
- ? base::Optional<QuietUiReason>(QuietUiReason::kEnabledInPrefs)
- : base::nullopt,
+ ? absl::optional<QuietUiReason>(QuietUiReason::kEnabledInPrefs)
+ : absl::nullopt,
false /* async */, test.prediction_likelihoods[i]);
}
- MockPermissionRequest request("foo", RequestType::kNotifications,
+ MockPermissionRequest request(u"foo", RequestType::kNotifications,
PermissionRequestGestureType::GESTURE);
manager_->AddRequest(web_contents()->GetMainFrame(), &request);
@@ -934,6 +961,39 @@ TEST_P(PermissionRequestManagerTest, SelectorsPredictionLikelihood) {
}
}
+TEST_P(PermissionRequestManagerTest, SelectorRequestTypes) {
+ const struct {
+ RequestType request_type;
+ bool should_request_use_quiet_ui;
+ } kTests[] = {
+ {RequestType::kNotifications, true},
+ {RequestType::kGeolocation, true},
+ {RequestType::kCameraStream, false},
+ };
+ manager_->clear_permission_ui_selector_for_testing();
+ MockNotificationPermissionUiSelector::CreateForManager(
+ manager_, QuietUiReason::kEnabledInPrefs, true);
+ for (const auto& test : kTests) {
+ MockPermissionRequest request(u"request", test.request_type,
+ PermissionRequestGestureType::GESTURE);
+ manager_->AddRequest(web_contents()->GetMainFrame(), &request);
+ WaitForBubbleToBeShown();
+ EXPECT_EQ(test.should_request_use_quiet_ui,
+ manager_->ShouldCurrentRequestUseQuietUI());
+ Accept();
+ }
+ // Adding a mock PermissionUiSelector that handles Camera stream.
+ MockCameraStreamPermissionUiSelector::CreateForManager(
+ manager_, QuietUiReason::kEnabledInPrefs, true);
+ // Now the RequestType::kCameraStream should show a quiet UI as well
+ MockPermissionRequest request2(u"request2", RequestType::kCameraStream,
+ PermissionRequestGestureType::GESTURE);
+ manager_->AddRequest(web_contents()->GetMainFrame(), &request2);
+ WaitForBubbleToBeShown();
+ EXPECT_TRUE(manager_->ShouldCurrentRequestUseQuietUI());
+ Accept();
+}
+
INSTANTIATE_TEST_SUITE_P(All,
PermissionRequestManagerTest,
::testing::Values(false, true));
diff --git a/chromium/components/permissions/permission_ui_selector.cc b/chromium/components/permissions/permission_ui_selector.cc
new file mode 100644
index 00000000000..b264e9fd3d4
--- /dev/null
+++ b/chromium/components/permissions/permission_ui_selector.cc
@@ -0,0 +1,48 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/permissions/permission_ui_selector.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace permissions {
+
+// static
+bool PermissionUiSelector::ShouldSuppressAnimation(
+ absl::optional<QuietUiReason> reason) {
+ if (!reason)
+ return true;
+
+ switch (*reason) {
+ case QuietUiReason::kEnabledInPrefs:
+ case QuietUiReason::kPredictedVeryUnlikelyGrant:
+ return false;
+ case QuietUiReason::kTriggeredByCrowdDeny:
+ case QuietUiReason::kTriggeredDueToAbusiveRequests:
+ case QuietUiReason::kTriggeredDueToAbusiveContent:
+ return true;
+ }
+}
+
+PermissionUiSelector::Decision::Decision(
+ absl::optional<QuietUiReason> quiet_ui_reason,
+ absl::optional<WarningReason> warning_reason)
+ : quiet_ui_reason(quiet_ui_reason), warning_reason(warning_reason) {}
+PermissionUiSelector::Decision::~Decision() = default;
+
+PermissionUiSelector::Decision::Decision(const Decision&) = default;
+PermissionUiSelector::Decision& PermissionUiSelector::Decision::operator=(
+ const Decision&) = default;
+
+// static
+PermissionUiSelector::Decision
+PermissionUiSelector::Decision::UseNormalUiAndShowNoWarning() {
+ return Decision(UseNormalUi(), ShowNoWarning());
+}
+
+absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
+PermissionUiSelector::PredictedGrantLikelihoodForUKM() {
+ return absl::nullopt;
+}
+
+} // namespace permissions
diff --git a/chromium/components/permissions/notification_permission_ui_selector.h b/chromium/components/permissions/permission_ui_selector.h
index ca4ff54cf23..0220513d96c 100644
--- a/chromium/components/permissions/notification_permission_ui_selector.h
+++ b/chromium/components/permissions/permission_ui_selector.h
@@ -2,23 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_PERMISSIONS_NOTIFICATION_PERMISSION_UI_SELECTOR_H_
-#define COMPONENTS_PERMISSIONS_NOTIFICATION_PERMISSION_UI_SELECTOR_H_
+#ifndef COMPONENTS_PERMISSIONS_PERMISSION_UI_SELECTOR_H_
+#define COMPONENTS_PERMISSIONS_PERMISSION_UI_SELECTOR_H_
#include "base/callback_forward.h"
-#include "base/optional.h"
#include "components/permissions/permission_request.h"
#include "components/permissions/permission_uma_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace permissions {
// The interface for implementations that decide if the quiet prompt UI should
-// be used to display a notification permission |request|, whether a warning
-// should be printed to the Dev Tools console, and the reasons for both.
+// be used to display a permission |request|, whether a warning should be
+// printed to the Dev Tools console, and the reasons for both.
//
// Implementations of interface are expected to have long-lived instances that
// can support multiple requests, but only one at a time.
-class NotificationPermissionUiSelector {
+class PermissionUiSelector {
public:
enum class QuietUiReason {
kEnabledInPrefs,
@@ -34,39 +34,39 @@ class NotificationPermissionUiSelector {
};
struct Decision {
- Decision(base::Optional<QuietUiReason> quiet_ui_reason,
- base::Optional<WarningReason> warning_reason);
+ Decision(absl::optional<QuietUiReason> quiet_ui_reason,
+ absl::optional<WarningReason> warning_reason);
~Decision();
Decision(const Decision&);
Decision& operator=(const Decision&);
- static constexpr base::Optional<QuietUiReason> UseNormalUi() {
- return base::nullopt;
+ static constexpr absl::optional<QuietUiReason> UseNormalUi() {
+ return absl::nullopt;
}
- static constexpr base::Optional<WarningReason> ShowNoWarning() {
- return base::nullopt;
+ static constexpr absl::optional<WarningReason> ShowNoWarning() {
+ return absl::nullopt;
}
static Decision UseNormalUiAndShowNoWarning();
- // The reason for showing the quiet UI, or `base::nullopt` if the normal UI
+ // The reason for showing the quiet UI, or `absl::nullopt` if the normal UI
// should be used.
- base::Optional<QuietUiReason> quiet_ui_reason;
+ absl::optional<QuietUiReason> quiet_ui_reason;
- // The reason for printing a warning to the console, or `base::nullopt` if
+ // The reason for printing a warning to the console, or `absl::nullopt` if
// no warning should be printed.
- base::Optional<WarningReason> warning_reason;
+ absl::optional<WarningReason> warning_reason;
};
using DecisionMadeCallback = base::OnceCallback<void(const Decision&)>;
- virtual ~NotificationPermissionUiSelector() {}
+ virtual ~PermissionUiSelector() {}
// Determines whether animations should be suppressed because we're very
// confident the user does not want notifications (e.g. they're abusive).
- static bool ShouldSuppressAnimation(base::Optional<QuietUiReason> reason);
+ static bool ShouldSuppressAnimation(absl::optional<QuietUiReason> reason);
// Determines the UI to use for the given |request|, and invokes |callback|
// when done, either synchronously or asynchronously. The |callback| is
@@ -81,13 +81,15 @@ class NotificationPermissionUiSelector {
// simply be a no-op.
virtual void Cancel() {}
+ virtual bool IsPermissionRequestSupported(RequestType request_type) = 0;
+
// Will return the selector's discretized prediction value, if any is
// applicable to be recorded in UKMs. This is specific only to a selector that
// makes use of the Web Permission Predictions Service to make decisions.
- virtual base::Optional<PermissionUmaUtil::PredictionGrantLikelihood>
+ virtual absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
PredictedGrantLikelihoodForUKM();
};
} // namespace permissions
-#endif // COMPONENTS_PERMISSIONS_NOTIFICATION_PERMISSION_UI_SELECTOR_H_
+#endif // COMPONENTS_PERMISSIONS_PERMISSION_UI_SELECTOR_H_
diff --git a/chromium/components/permissions/permission_uma_util.cc b/chromium/components/permissions/permission_uma_util.cc
index e7f4572d299..f8d4e6c5297 100644
--- a/chromium/components/permissions/permission_uma_util.cc
+++ b/chromium/components/permissions/permission_uma_util.cc
@@ -89,7 +89,7 @@ RequestTypeForUma GetUmaValueForRequestType(RequestType request_type) {
#endif
case RequestType::kNotifications:
return RequestTypeForUma::PERMISSION_NOTIFICATIONS;
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
case RequestType::kProtectedMediaIdentifier:
return RequestTypeForUma::PERMISSION_PROTECTED_MEDIA_IDENTIFIER;
#endif
@@ -182,6 +182,20 @@ void RecordEngagementMetric(const std::vector<PermissionRequest*>& requests,
base::UmaHistogramPercentageObsoleteDoNotUse(name, engagement_score);
}
+void RecordPermissionUsageUkm(ContentSettingsType permission_type,
+ absl::optional<ukm::SourceId> source_id) {
+ if (!source_id.has_value())
+ return;
+
+ size_t num_values = 0;
+
+ ukm::builders::PermissionUsage builder(source_id.value());
+ builder.SetPermissionType(static_cast<int64_t>(
+ ContentSettingTypeToHistogramValue(permission_type, &num_values)));
+
+ builder.Record(ukm::UkmRecorder::Get());
+}
+
void RecordPermissionActionUkm(
PermissionAction action,
PermissionRequestGestureType gesture_type,
@@ -191,12 +205,12 @@ void RecordPermissionActionUkm(
PermissionSourceUI source_ui,
base::TimeDelta time_to_decision,
PermissionPromptDisposition ui_disposition,
- base::Optional<PermissionPromptDispositionReason> ui_reason,
- base::Optional<bool> has_three_consecutive_denies,
- base::Optional<bool> has_previously_revoked_permission,
- base::Optional<PermissionUmaUtil::PredictionGrantLikelihood>
+ absl::optional<PermissionPromptDispositionReason> ui_reason,
+ absl::optional<bool> has_three_consecutive_denies,
+ absl::optional<bool> has_previously_revoked_permission,
+ absl::optional<PermissionUmaUtil::PredictionGrantLikelihood>
predicted_grant_likelihood,
- base::Optional<ukm::SourceId> source_id) {
+ absl::optional<ukm::SourceId> source_id) {
// Only record the permission change if the origin is in the history.
if (!source_id.has_value())
return;
@@ -278,7 +292,7 @@ std::string GetPromptDispositionString(
// CrowdDeny versions published before 2020 will be reported as 1.
// Returns 0 if no version available.
// Returns 1 if a version has invalid format.
-int ConvertCrowdDenyVersionToInt(const base::Optional<base::Version>& version) {
+int ConvertCrowdDenyVersionToInt(const absl::optional<base::Version>& version) {
if (!version.has_value() || !version.value().IsValid())
return 0;
@@ -304,6 +318,39 @@ int ConvertCrowdDenyVersionToInt(const base::Optional<base::Version>& version) {
return short_version;
}
+AutoDSEPermissionRevertTransition GetAutoDSEPermissionRevertedTransition(
+ ContentSetting backed_up_setting,
+ ContentSetting effective_setting,
+ ContentSetting end_state_setting) {
+ if (backed_up_setting == CONTENT_SETTING_ASK &&
+ effective_setting == CONTENT_SETTING_ALLOW &&
+ end_state_setting == CONTENT_SETTING_ASK) {
+ return AutoDSEPermissionRevertTransition::NO_DECISION_ASK;
+ } else if (backed_up_setting == CONTENT_SETTING_ALLOW &&
+ effective_setting == CONTENT_SETTING_ALLOW &&
+ end_state_setting == CONTENT_SETTING_ALLOW) {
+ return AutoDSEPermissionRevertTransition::PRESERVE_ALLOW;
+ } else if (backed_up_setting == CONTENT_SETTING_BLOCK &&
+ effective_setting == CONTENT_SETTING_ALLOW &&
+ end_state_setting == CONTENT_SETTING_ASK) {
+ return AutoDSEPermissionRevertTransition::CONFLICT_ASK;
+ } else if (backed_up_setting == CONTENT_SETTING_ASK &&
+ effective_setting == CONTENT_SETTING_BLOCK &&
+ end_state_setting == CONTENT_SETTING_BLOCK) {
+ return AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_ASK;
+ } else if (backed_up_setting == CONTENT_SETTING_ALLOW &&
+ effective_setting == CONTENT_SETTING_BLOCK &&
+ end_state_setting == CONTENT_SETTING_BLOCK) {
+ return AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_ALLOW;
+ } else if (backed_up_setting == CONTENT_SETTING_BLOCK &&
+ effective_setting == CONTENT_SETTING_BLOCK &&
+ end_state_setting == CONTENT_SETTING_BLOCK) {
+ return AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_BLOCK;
+ } else {
+ return AutoDSEPermissionRevertTransition::INVALID_END_STATE;
+ }
+}
+
} // anonymous namespace
// PermissionUmaUtil ----------------------------------------------------------
@@ -367,9 +414,9 @@ void PermissionUmaUtil::PermissionRevoked(
PermissionRequestGestureType::UNKNOWN,
/*time_to_decision=*/base::TimeDelta(),
PermissionPromptDisposition::NOT_APPLICABLE,
- /*ui_reason=*/base::nullopt, revoked_origin,
+ /*ui_reason=*/absl::nullopt, revoked_origin,
/*web_contents=*/nullptr, browser_context,
- /*predicted_grant_likelihood=*/base::nullopt);
+ /*predicted_grant_likelihood=*/absl::nullopt);
}
void PermissionUmaUtil::RecordEmbargoPromptSuppression(
@@ -434,8 +481,8 @@ void PermissionUmaUtil::PermissionPromptResolved(
PermissionAction permission_action,
base::TimeDelta time_to_decision,
PermissionPromptDisposition ui_disposition,
- base::Optional<PermissionPromptDispositionReason> ui_reason,
- base::Optional<PredictionGrantLikelihood> predicted_grant_likelihood) {
+ absl::optional<PermissionPromptDispositionReason> ui_reason,
+ absl::optional<PredictionGrantLikelihood> predicted_grant_likelihood) {
switch (permission_action) {
case PermissionAction::GRANTED:
RecordPromptDecided(requests, /*accepted=*/true, /*is_one_time=*/false);
@@ -538,7 +585,7 @@ void PermissionUmaUtil::RecordCrowdDenyDelayedPushNotification(
}
void PermissionUmaUtil::RecordCrowdDenyVersionAtAbuseCheckTime(
- const base::Optional<base::Version>& version) {
+ const absl::optional<base::Version>& version) {
base::UmaHistogramSparse(
"Permissions.CrowdDeny.PreloadData.VersionAtAbuseCheckTime",
ConvertCrowdDenyVersionToInt(version));
@@ -634,6 +681,16 @@ PermissionUmaUtil::ScopedRevocationReporter::~ScopedRevocationReporter() {
}
}
+void PermissionUmaUtil::RecordPermissionUsage(
+ ContentSettingsType permission_type,
+ content::BrowserContext* browser_context,
+ const content::WebContents* web_contents,
+ const GURL& requesting_origin) {
+ PermissionsClient::Get()->GetUkmSourceId(
+ browser_context, web_contents, requesting_origin,
+ base::BindOnce(&RecordPermissionUsageUkm, permission_type));
+}
+
void PermissionUmaUtil::RecordPermissionAction(
ContentSettingsType permission,
PermissionAction action,
@@ -641,11 +698,11 @@ void PermissionUmaUtil::RecordPermissionAction(
PermissionRequestGestureType gesture_type,
base::TimeDelta time_to_decision,
PermissionPromptDisposition ui_disposition,
- base::Optional<PermissionPromptDispositionReason> ui_reason,
+ absl::optional<PermissionPromptDispositionReason> ui_reason,
const GURL& requesting_origin,
const content::WebContents* web_contents,
content::BrowserContext* browser_context,
- base::Optional<PredictionGrantLikelihood> predicted_grant_likelihood) {
+ absl::optional<PredictionGrantLikelihood> predicted_grant_likelihood) {
DCHECK(PermissionUtil::IsPermission(permission));
PermissionDecisionAutoBlocker* autoblocker =
PermissionsClient::Get()->GetPermissionDecisionAutoBlocker(
@@ -664,7 +721,7 @@ void PermissionUmaUtil::RecordPermissionAction(
? PermissionsClient::Get()
->HadThreeConsecutiveNotificationPermissionDenies(
browser_context)
- : base::nullopt,
+ : absl::nullopt,
PermissionsClient::Get()->HasPreviouslyAutoRevokedPermission(
browser_context, requesting_origin, permission),
predicted_grant_likelihood));
@@ -800,6 +857,33 @@ void PermissionUmaUtil::RecordTimeElapsedBetweenGrantAndRevoke(
delta.InSeconds(), 1, base::TimeDelta::FromDays(365).InSeconds(), 100);
}
+// static
+void PermissionUmaUtil::RecordAutoDSEPermissionReverted(
+ ContentSettingsType permission_type,
+ ContentSetting backed_up_setting,
+ ContentSetting effective_setting,
+ ContentSetting end_state_setting) {
+ std::string permission_string =
+ GetPermissionRequestString(GetUmaValueForRequestType(
+ ContentSettingsTypeToRequestType(permission_type)));
+ base::UmaHistogramEnumeration(
+ "Permissions.DSE.AutoPermissionRevertTransition." + permission_string,
+ GetAutoDSEPermissionRevertedTransition(
+ backed_up_setting, effective_setting, end_state_setting));
+}
+
+// static
+void PermissionUmaUtil::RecordDSEEffectiveSetting(
+ ContentSettingsType permission_type,
+ ContentSetting setting) {
+ std::string permission_string =
+ GetPermissionRequestString(GetUmaValueForRequestType(
+ ContentSettingsTypeToRequestType(permission_type)));
+ base::UmaHistogramEnumeration(
+ "Permissions.DSE.EffectiveSetting." + permission_string, setting,
+ CONTENT_SETTING_NUM_SETTINGS);
+}
+
std::string PermissionUmaUtil::GetPermissionActionString(
PermissionAction permission_action) {
switch (permission_action) {
diff --git a/chromium/components/permissions/permission_uma_util.h b/chromium/components/permissions/permission_uma_util.h
index 7a40b54a01b..55f1e2033b4 100644
--- a/chromium/components/permissions/permission_uma_util.h
+++ b/chromium/components/permissions/permission_uma_util.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/time/time.h"
#include "base/version.h"
+#include "components/content_settings/core/common/content_settings_types.h"
#include "components/permissions/permission_request.h"
#include "components/permissions/permission_result.h"
#include "components/permissions/permission_util.h"
@@ -191,6 +192,37 @@ enum class PermissionAutoRevocationHistory {
PREVIOUSLY_AUTO_REVOKED = 0x01,
};
+// This enum backs up the `AutoDSEPermissionRevertTransition` histogram enum.
+// Never reuse values and mirror any updates to it.
+// Describes the transition that has occured for the setting of a DSE origin
+// when DSE autogrant becomes disabled.
+enum class AutoDSEPermissionRevertTransition {
+ // The user has not previously made any decision so it results in an `ASK` end
+ // state.
+ NO_DECISION_ASK = 0,
+ // The user has decided to `ALLOW` the origin before it was the DSE origin and
+ // has not reverted this decision.
+ PRESERVE_ALLOW = 1,
+ // The user has previously `BLOCKED` the origin but has allowed it after it
+ // became the DSE origin. Resolve the conflict by setting it to `ASK` so the
+ // user will make a decision again.
+ CONFLICT_ASK = 2,
+ // The user has blocked the DSE origin and has not made a previous decision
+ // before the origin became the DSE origin.
+ PRESERVE_BLOCK_ASK = 3,
+ // The user has blocked the DSE origin and has `ALLOWED` it before it became
+ // the DSE origin, preserve the latest decision.
+ PRESERVE_BLOCK_ALLOW = 4,
+ // The user has blocked the DSE origin and has `BLOCKED` it before it became
+ // the DSE origin as well.
+ PRESERVE_BLOCK_BLOCK = 5,
+ // There has been an invalid transition.
+ INVALID_END_STATE = 6,
+
+ // Always keep at the end.
+ kMaxValue = INVALID_END_STATE,
+};
+
// Provides a convenient way of logging UMA for permission related operations.
class PermissionUmaUtil {
public:
@@ -247,8 +279,8 @@ class PermissionUmaUtil {
PermissionAction permission_action,
base::TimeDelta time_to_decision,
PermissionPromptDisposition ui_disposition,
- base::Optional<PermissionPromptDispositionReason> ui_reason,
- base::Optional<PredictionGrantLikelihood> predicted_grant_likelihood);
+ absl::optional<PermissionPromptDispositionReason> ui_reason,
+ absl::optional<PredictionGrantLikelihood> predicted_grant_likelihood);
static void RecordWithBatteryBucket(const std::string& histogram);
@@ -257,7 +289,7 @@ class PermissionUmaUtil {
static void RecordCrowdDenyDelayedPushNotification(base::TimeDelta delay);
static void RecordCrowdDenyVersionAtAbuseCheckTime(
- const base::Optional<base::Version>& version);
+ const absl::optional<base::Version>& version);
// Record UMAs related to the Android "Missing permissions" infobar.
static void RecordMissingPermissionInfobarShouldShow(
@@ -267,12 +299,26 @@ class PermissionUmaUtil {
PermissionAction action,
const std::vector<ContentSettingsType>& content_settings_types);
+ static void RecordPermissionUsage(ContentSettingsType permission_type,
+ content::BrowserContext* browser_context,
+ const content::WebContents* web_contents,
+ const GURL& requesting_origin);
+
static void RecordTimeElapsedBetweenGrantAndUse(ContentSettingsType type,
base::TimeDelta delta);
static void RecordTimeElapsedBetweenGrantAndRevoke(ContentSettingsType type,
base::TimeDelta delta);
+ static void RecordAutoDSEPermissionReverted(
+ ContentSettingsType permission_type,
+ ContentSetting backed_up_setting,
+ ContentSetting effective_setting,
+ ContentSetting end_state_setting);
+
+ static void RecordDSEEffectiveSetting(ContentSettingsType permission_type,
+ ContentSetting setting);
+
static std::string GetPermissionActionString(
PermissionAction permission_action);
@@ -318,11 +364,11 @@ class PermissionUmaUtil {
PermissionRequestGestureType gesture_type,
base::TimeDelta time_to_decision,
PermissionPromptDisposition ui_disposition,
- base::Optional<PermissionPromptDispositionReason> ui_reason,
+ absl::optional<PermissionPromptDispositionReason> ui_reason,
const GURL& requesting_origin,
const content::WebContents* web_contents,
content::BrowserContext* browser_context,
- base::Optional<PredictionGrantLikelihood> predicted_grant_likelihood);
+ absl::optional<PredictionGrantLikelihood> predicted_grant_likelihood);
// Records |count| total prior actions for a prompt of type |permission|
// for a single origin using |prefix| for the metric.
diff --git a/chromium/components/permissions/permission_uma_util_unittest.cc b/chromium/components/permissions/permission_uma_util_unittest.cc
index 1a13e706167..f8ed456d288 100644
--- a/chromium/components/permissions/permission_uma_util_unittest.cc
+++ b/chromium/components/permissions/permission_uma_util_unittest.cc
@@ -106,35 +106,101 @@ TEST_F(PermissionUmaUtilTest, ScopedRevocationReporter) {
TEST_F(PermissionUmaUtilTest, CrowdDenyVersionTest) {
base::HistogramTester histograms;
- const base::Optional<base::Version> empty_version;
+ const absl::optional<base::Version> empty_version;
PermissionUmaUtil::RecordCrowdDenyVersionAtAbuseCheckTime(empty_version);
histograms.ExpectBucketCount(
"Permissions.CrowdDeny.PreloadData.VersionAtAbuseCheckTime", 0, 1);
- const base::Optional<base::Version> valid_version =
+ const absl::optional<base::Version> valid_version =
base::Version({2020, 10, 11, 1234});
PermissionUmaUtil::RecordCrowdDenyVersionAtAbuseCheckTime(valid_version);
histograms.ExpectBucketCount(
"Permissions.CrowdDeny.PreloadData.VersionAtAbuseCheckTime", 20201011, 1);
- const base::Optional<base::Version> valid_old_version =
+ const absl::optional<base::Version> valid_old_version =
base::Version({2019, 10, 10, 1234});
PermissionUmaUtil::RecordCrowdDenyVersionAtAbuseCheckTime(valid_old_version);
histograms.ExpectBucketCount(
"Permissions.CrowdDeny.PreloadData.VersionAtAbuseCheckTime", 1, 1);
- const base::Optional<base::Version> valid_future_version =
+ const absl::optional<base::Version> valid_future_version =
base::Version({2021, 1, 1, 1234});
PermissionUmaUtil::RecordCrowdDenyVersionAtAbuseCheckTime(
valid_future_version);
histograms.ExpectBucketCount(
"Permissions.CrowdDeny.PreloadData.VersionAtAbuseCheckTime", 20210101, 1);
- const base::Optional<base::Version> invalid_version =
+ const absl::optional<base::Version> invalid_version =
base::Version({2020, 10, 11});
PermissionUmaUtil::RecordCrowdDenyVersionAtAbuseCheckTime(valid_version);
histograms.ExpectBucketCount(
"Permissions.CrowdDeny.PreloadData.VersionAtAbuseCheckTime", 1, 1);
}
+// Test that the appropriate UMA metrics have been recorded when the DSE is
+// disabled.
+TEST_F(PermissionUmaUtilTest, MetricsAreRecordedWhenAutoDSEPermissionReverted) {
+ constexpr char kNotificationsHistogram[] =
+ "Permissions.DSE.AutoPermissionRevertTransition.Notifications";
+ constexpr char kGeolocationHistogram[] =
+ "Permissions.DSE.AutoPermissionRevertTransition.Geolocation";
+
+ constexpr struct {
+ ContentSetting backed_up_setting;
+ ContentSetting effective_setting;
+ ContentSetting end_state_setting;
+ permissions::AutoDSEPermissionRevertTransition expected_transition;
+ } kTests[] = {
+ // Expected valid combinations.
+ {CONTENT_SETTING_ASK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK,
+ permissions::AutoDSEPermissionRevertTransition::NO_DECISION_ASK},
+ {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ALLOW,
+ permissions::AutoDSEPermissionRevertTransition::PRESERVE_ALLOW},
+ {CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK,
+ permissions::AutoDSEPermissionRevertTransition::CONFLICT_ASK},
+ {CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK, CONTENT_SETTING_BLOCK,
+ permissions::AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_ASK},
+ {CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, CONTENT_SETTING_BLOCK,
+ permissions::AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_ALLOW},
+ {CONTENT_SETTING_BLOCK, CONTENT_SETTING_BLOCK, CONTENT_SETTING_BLOCK,
+ permissions::AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_BLOCK},
+
+ // Invalid combinations.
+ {CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ASK,
+ permissions::AutoDSEPermissionRevertTransition::INVALID_END_STATE},
+ {CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW,
+ permissions::AutoDSEPermissionRevertTransition::INVALID_END_STATE},
+ {CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK,
+ permissions::AutoDSEPermissionRevertTransition::INVALID_END_STATE},
+ {CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ALLOW,
+ permissions::AutoDSEPermissionRevertTransition::INVALID_END_STATE},
+ };
+
+ // We test every combination of test case for notifications and geolocation to
+ // basically test the entire possible transition space.
+ for (const auto& test : kTests) {
+ for (const auto type : {ContentSettingsType::NOTIFICATIONS,
+ ContentSettingsType::GEOLOCATION}) {
+ base::HistogramTester histograms;
+ PermissionUmaUtil::RecordAutoDSEPermissionReverted(
+ type, test.backed_up_setting, test.effective_setting,
+ test.end_state_setting);
+
+ // Test that the expected samples are recorded in histograms.
+ for (auto sample = static_cast<int>(
+ permissions::AutoDSEPermissionRevertTransition::NO_DECISION_ASK);
+ sample <
+ static_cast<int>(
+ permissions::AutoDSEPermissionRevertTransition::kMaxValue);
+ ++sample) {
+ histograms.ExpectBucketCount(
+ type == ContentSettingsType::NOTIFICATIONS ? kNotificationsHistogram
+ : kGeolocationHistogram,
+ sample,
+ static_cast<int>(test.expected_transition) == sample ? 1 : 0);
+ }
+ }
+ }
+}
+
} // namespace permissions
diff --git a/chromium/components/permissions/permission_util.cc b/chromium/components/permissions/permission_util.cc
index 0b08ab45509..8ed4ca0311a 100644
--- a/chromium/components/permissions/permission_util.cc
+++ b/chromium/components/permissions/permission_util.cc
@@ -104,7 +104,7 @@ bool PermissionUtil::GetPermissionType(ContentSettingsType type,
*out = PermissionType::AUDIO_CAPTURE;
} else if (type == ContentSettingsType::BACKGROUND_SYNC) {
*out = PermissionType::BACKGROUND_SYNC;
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OW_WIN)
} else if (type == ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER) {
*out = PermissionType::PROTECTED_MEDIA_IDENTIFIER;
#endif
@@ -160,7 +160,7 @@ bool PermissionUtil::IsPermission(ContentSettingsType type) {
case ContentSettingsType::MEDIASTREAM_CAMERA:
case ContentSettingsType::MEDIASTREAM_MIC:
case ContentSettingsType::BACKGROUND_SYNC:
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OW_WIN)
case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER:
#endif
case ContentSettingsType::SENSORS:
diff --git a/chromium/components/permissions/permissions_client.cc b/chromium/components/permissions/permissions_client.cc
index 544bfab1e8a..cdcef15cc83 100644
--- a/chromium/components/permissions/permissions_client.cc
+++ b/chromium/components/permissions/permissions_client.cc
@@ -6,7 +6,6 @@
#include "base/callback.h"
#include "build/chromeos_buildflags.h"
-#include "components/permissions/notification_permission_ui_selector.h"
#if !defined(OS_ANDROID)
#include "ui/gfx/paint_vector_icon.h"
@@ -57,7 +56,7 @@ void PermissionsClient::GetUkmSourceId(content::BrowserContext* browser_context,
const content::WebContents* web_contents,
const GURL& requesting_origin,
GetUkmSourceIdCallback callback) {
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
}
IconId PermissionsClient::GetOverrideIconId(RequestType request_type) {
@@ -68,10 +67,10 @@ IconId PermissionsClient::GetOverrideIconId(RequestType request_type) {
#endif
}
-std::vector<std::unique_ptr<NotificationPermissionUiSelector>>
-PermissionsClient::CreateNotificationPermissionUiSelectors(
+std::vector<std::unique_ptr<PermissionUiSelector>>
+PermissionsClient::CreatePermissionUiSelectors(
content::BrowserContext* browser_context) {
- return std::vector<std::unique_ptr<NotificationPermissionUiSelector>>();
+ return std::vector<std::unique_ptr<PermissionUiSelector>>();
}
void PermissionsClient::OnPromptResolved(
@@ -79,23 +78,23 @@ void PermissionsClient::OnPromptResolved(
RequestType request_type,
PermissionAction action,
const GURL& origin,
- base::Optional<QuietUiReason> quiet_ui_reason) {}
+ absl::optional<QuietUiReason> quiet_ui_reason) {}
-base::Optional<bool>
+absl::optional<bool>
PermissionsClient::HadThreeConsecutiveNotificationPermissionDenies(
content::BrowserContext* browser_context) {
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<url::Origin> PermissionsClient::GetAutoApprovalOrigin() {
- return base::nullopt;
+absl::optional<url::Origin> PermissionsClient::GetAutoApprovalOrigin() {
+ return absl::nullopt;
}
-base::Optional<bool> PermissionsClient::HasPreviouslyAutoRevokedPermission(
+absl::optional<bool> PermissionsClient::HasPreviouslyAutoRevokedPermission(
content::BrowserContext* browser_context,
const GURL& origin,
ContentSettingsType permission) {
- return base::nullopt;
+ return absl::nullopt;
}
bool PermissionsClient::CanBypassEmbeddingOriginCheck(
@@ -104,10 +103,10 @@ bool PermissionsClient::CanBypassEmbeddingOriginCheck(
return false;
}
-base::Optional<GURL> PermissionsClient::OverrideCanonicalOrigin(
+absl::optional<GURL> PermissionsClient::OverrideCanonicalOrigin(
const GURL& requesting_origin,
const GURL& embedding_origin) {
- return base::nullopt;
+ return absl::nullopt;
}
#if defined(OS_ANDROID)
@@ -118,6 +117,11 @@ bool PermissionsClient::IsPermissionControlledByDse(
return false;
}
+bool PermissionsClient::IsDseOrigin(content::BrowserContext* browser_context,
+ const url::Origin& origin) {
+ return false;
+}
+
bool PermissionsClient::ResetPermissionIfControlledByDse(
content::BrowserContext* browser_context,
ContentSettingsType type,
diff --git a/chromium/components/permissions/permissions_client.h b/chromium/components/permissions/permissions_client.h
index 0cc6da8ec57..d2453585ad9 100644
--- a/chromium/components/permissions/permissions_client.h
+++ b/chromium/components/permissions/permissions_client.h
@@ -7,15 +7,15 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/content_settings/core/common/content_settings_types.h"
-#include "components/permissions/notification_permission_ui_selector.h"
#include "components/permissions/permission_prompt.h"
+#include "components/permissions/permission_ui_selector.h"
#include "components/permissions/permission_util.h"
#include "components/permissions/request_type.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
class GURL;
@@ -36,7 +36,7 @@ class InfoBarManager;
} // namespace infobars
namespace permissions {
-class ChooserContextBase;
+class ObjectPermissionContextBase;
class PermissionDecisionAutoBlocker;
class PermissionManager;
class PermissionPromptAndroid;
@@ -78,9 +78,10 @@ class PermissionsClient {
virtual PermissionManager* GetPermissionManager(
content::BrowserContext* browser_context) = 0;
- // Gets the ChooserContextBase for the given type and context, which must be a
+ // Gets the ObjectPermissionContextBase for the given type and context, which
+ // must be a
// *_CHOOSER_DATA value. May return null if the context does not exist.
- virtual ChooserContextBase* GetChooserContext(
+ virtual ObjectPermissionContextBase* GetChooserContext(
content::BrowserContext* browser_context,
ContentSettingsType type) = 0;
@@ -112,7 +113,7 @@ class PermissionsClient {
// with the result, and may be run synchronously if the result is available
// immediately.
using GetUkmSourceIdCallback =
- base::OnceCallback<void(base::Optional<ukm::SourceId>)>;
+ base::OnceCallback<void(absl::optional<ukm::SourceId>)>;
virtual void GetUkmSourceId(content::BrowserContext* browser_context,
const content::WebContents* web_contents,
const GURL& requesting_origin,
@@ -124,34 +125,33 @@ class PermissionsClient {
virtual IconId GetOverrideIconId(RequestType request_type);
// Allows the embedder to provide a list of selectors for choosing the UI to
- // use for notification permission requests. If the embedder returns an empty
- // list, the normal UI will be used always. Then for each request, if none of
- // the returned selectors prescribe the quiet UI, the normal UI will be used.
+ // use for permission requests. If the embedder returns an empty list, the
+ // normal UI will be used always. Then for each request, if none of the
+ // returned selectors prescribe the quiet UI, the normal UI will be used.
// Otherwise the quiet UI will be used. Selectors at lower indices have higher
// priority when determining the quiet UI flavor.
- virtual std::vector<std::unique_ptr<NotificationPermissionUiSelector>>
- CreateNotificationPermissionUiSelectors(
- content::BrowserContext* browser_context);
+ virtual std::vector<std::unique_ptr<PermissionUiSelector>>
+ CreatePermissionUiSelectors(content::BrowserContext* browser_context);
- using QuietUiReason = NotificationPermissionUiSelector::QuietUiReason;
+ using QuietUiReason = PermissionUiSelector::QuietUiReason;
// Called for each request type when a permission prompt is resolved.
virtual void OnPromptResolved(content::BrowserContext* browser_context,
RequestType request_type,
PermissionAction action,
const GURL& origin,
- base::Optional<QuietUiReason> quiet_ui_reason);
+ absl::optional<QuietUiReason> quiet_ui_reason);
// Returns true if user has 3 consecutive notifications permission denies,
// returns false otherwise.
- // Returns base::nullopt if the user is not in the adoptive activation quiet
+ // Returns absl::nullopt if the user is not in the adoptive activation quiet
// ui dry run experiment group.
- virtual base::Optional<bool> HadThreeConsecutiveNotificationPermissionDenies(
+ virtual absl::optional<bool> HadThreeConsecutiveNotificationPermissionDenies(
content::BrowserContext* browser_context);
// Returns whether the |permission| has already been auto-revoked due to abuse
// at least once for the given |origin|. Returns `nullopt` if permission
// auto-revocation is not supported for a given permission type.
- virtual base::Optional<bool> HasPreviouslyAutoRevokedPermission(
+ virtual absl::optional<bool> HasPreviouslyAutoRevokedPermission(
content::BrowserContext* browser_context,
const GURL& origin,
ContentSettingsType permission);
@@ -159,7 +159,7 @@ class PermissionsClient {
// If the embedder returns an origin here, any requests matching that origin
// will be approved. Requests that do not match the returned origin will
// immediately be finished without granting/denying the permission.
- virtual base::Optional<url::Origin> GetAutoApprovalOrigin();
+ virtual absl::optional<url::Origin> GetAutoApprovalOrigin();
// Allows the embedder to bypass checking the embedding origin when performing
// permission availability checks. This is used for example when a permission
@@ -171,7 +171,7 @@ class PermissionsClient {
// Allows embedder to override the canonical origin for a permission request.
// This is the origin that will be used for requesting/storing/displaying
// permissions.
- virtual base::Optional<GURL> OverrideCanonicalOrigin(
+ virtual absl::optional<GURL> OverrideCanonicalOrigin(
const GURL& requesting_origin,
const GURL& embedding_origin);
@@ -184,6 +184,11 @@ class PermissionsClient {
ContentSettingsType type,
const url::Origin& origin);
+ // Returns whether the given origin matches the default search engine (DSE)
+ // origin.
+ virtual bool IsDseOrigin(content::BrowserContext* browser_context,
+ const url::Origin& origin);
+
// Resets the permission if it's controlled by the default search
// engine (DSE). The return value is true if the permission was reset.
virtual bool ResetPermissionIfControlledByDse(
diff --git a/chromium/components/permissions/prediction_service/prediction_service.cc b/chromium/components/permissions/prediction_service/prediction_service.cc
index 4f547fd93e1..dd3f3e3bcda 100644
--- a/chromium/components/permissions/prediction_service/prediction_service.cc
+++ b/chromium/components/permissions/prediction_service/prediction_service.cc
@@ -282,8 +282,7 @@ PredictionService::CreatePredictionsResponse(network::SimpleURLLoader* loader,
return GeneratePredictionsResponseJsonToMessage(*response_body);
}
- std::unique_ptr<GeneratePredictionsResponse> predictions_response;
- predictions_response = std::make_unique<GeneratePredictionsResponse>();
+ auto predictions_response = std::make_unique<GeneratePredictionsResponse>();
if (!predictions_response->ParseFromString(*response_body)) {
return nullptr;
}
diff --git a/chromium/components/permissions/prediction_service/prediction_service_unittest.cc b/chromium/components/permissions/prediction_service/prediction_service_unittest.cc
index 992c5e290e5..e6973359c2b 100644
--- a/chromium/components/permissions/prediction_service/prediction_service_unittest.cc
+++ b/chromium/components/permissions/prediction_service/prediction_service_unittest.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
@@ -28,6 +27,7 @@
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "services/network/test/test_url_loader_factory.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
namespace {
@@ -349,24 +349,24 @@ TEST_F(PredictionServiceTest, BuiltProtoRequestIsCorrect) {
TEST_F(PredictionServiceTest, ResponsesAreCorrect) {
struct {
GURL url;
- base::Optional<GeneratePredictionsResponse> expected_response;
+ absl::optional<GeneratePredictionsResponse> expected_response;
double delay_in_seconds;
int err_code;
} kTests[] = {
// Test different responses.
{kUrl_Likely,
- base::Optional<GeneratePredictionsResponse>(kResponseLikely)},
+ absl::optional<GeneratePredictionsResponse>(kResponseLikely)},
{kUrl_Unlikely,
- base::Optional<GeneratePredictionsResponse>(kResponseUnlikely)},
+ absl::optional<GeneratePredictionsResponse>(kResponseUnlikely)},
// Test the response's timeout.
{kUrl_Likely,
- base::Optional<GeneratePredictionsResponse>(kResponseLikely), 0.5},
- {kUrl_Likely, base::nullopt, 2},
+ absl::optional<GeneratePredictionsResponse>(kResponseLikely), 0.5},
+ {kUrl_Likely, absl::nullopt, 2},
// Test error code responses.
- {kUrl_Likely, base::nullopt, 0, net::ERR_SSL_PROTOCOL_ERROR},
- {kUrl_Likely, base::nullopt, 0, net::ERR_CONNECTION_FAILED},
+ {kUrl_Likely, absl::nullopt, 0, net::ERR_SSL_PROTOCOL_ERROR},
+ {kUrl_Likely, absl::nullopt, 0, net::ERR_CONNECTION_FAILED},
};
for (const auto& kTest : kTests) {
@@ -393,26 +393,26 @@ TEST_F(PredictionServiceTest, ResponsesAreCorrect) {
// valid.
TEST_F(PredictionServiceTest, FeatureParamAndCommandLineCanOverrideDefaultUrl) {
struct {
- base::Optional<std::string> command_line_switch_value;
- base::Optional<std::string> url_override_param_value;
+ absl::optional<std::string> command_line_switch_value;
+ absl::optional<std::string> url_override_param_value;
GURL expected_request_url;
permissions::GeneratePredictionsResponse expected_response;
} kTests[] = {
// Test without any overrides.
- {base::nullopt, base::nullopt, GURL(kDefaultPredictionServiceUrl),
+ {absl::nullopt, absl::nullopt, GURL(kDefaultPredictionServiceUrl),
kResponseLikely},
// Test only the FeatureParam override.
- {base::nullopt, kUrl_Unlikely.spec(), kUrl_Unlikely, kResponseUnlikely},
- {base::nullopt, "this is not a url", GURL(kDefaultPredictionServiceUrl),
+ {absl::nullopt, kUrl_Unlikely.spec(), kUrl_Unlikely, kResponseUnlikely},
+ {absl::nullopt, "this is not a url", GURL(kDefaultPredictionServiceUrl),
kResponseLikely},
- {base::nullopt, "", GURL(kDefaultPredictionServiceUrl), kResponseLikely},
+ {absl::nullopt, "", GURL(kDefaultPredictionServiceUrl), kResponseLikely},
// Test only the command line override.
- {kUrl_Unlikely.spec(), base::nullopt, kUrl_Unlikely, kResponseUnlikely},
- {"this is not a url", base::nullopt, GURL(kDefaultPredictionServiceUrl),
+ {kUrl_Unlikely.spec(), absl::nullopt, kUrl_Unlikely, kResponseUnlikely},
+ {"this is not a url", absl::nullopt, GURL(kDefaultPredictionServiceUrl),
kResponseLikely},
- {"", base::nullopt, GURL(kDefaultPredictionServiceUrl), kResponseLikely},
+ {"", absl::nullopt, GURL(kDefaultPredictionServiceUrl), kResponseLikely},
// Command line takes precedence over FeatureParam, if valid.
{kUrl_Likely.spec(), kUrl_Unlikely.spec(), kUrl_Likely, kResponseLikely},
diff --git a/chromium/components/permissions/pref_names.h b/chromium/components/permissions/pref_names.h
index 623c68c7ab0..21fe0cb9a4b 100644
--- a/chromium/components/permissions/pref_names.h
+++ b/chromium/components/permissions/pref_names.h
@@ -20,4 +20,4 @@ extern const char kLocationSettingsNextShowDefault[];
} // namespace prefs
} // namespace permissions
-#endif // COMPONENTS_PROXIMITY_AUTH_BLE_PREF_NAMES_H
+#endif // COMPONENTS_PERMISSIONS_PREF_NAMES_H_
diff --git a/chromium/components/permissions/quota_permission_context_impl.cc b/chromium/components/permissions/quota_permission_context_impl.cc
index eb1b6447aca..d2acc7ebf0e 100644
--- a/chromium/components/permissions/quota_permission_context_impl.cc
+++ b/chromium/components/permissions/quota_permission_context_impl.cc
@@ -54,10 +54,12 @@ class QuotaPermissionRequest : public PermissionRequest {
private:
// PermissionRequest:
RequestType GetRequestType() const override;
+ bool IsDuplicateOf(PermissionRequest* other_request) const override;
#if defined(OS_ANDROID)
std::u16string GetMessageText() const override;
-#endif
+#else
std::u16string GetMessageTextFragment() const override;
+#endif
GURL GetOrigin() const override;
void PermissionGranted(bool is_one_time) override;
void PermissionDenied() override;
@@ -91,6 +93,16 @@ RequestType QuotaPermissionRequest::GetRequestType() const {
return RequestType::kDiskQuota;
}
+bool QuotaPermissionRequest::IsDuplicateOf(
+ PermissionRequest* other_request) const {
+ // The downcast here is safe because PermissionRequest::IsDuplicateOf ensures
+ // that both requests are of type kDiskQuota.
+ return permissions::PermissionRequest::IsDuplicateOf(other_request) &&
+ is_large_quota_request_ ==
+ static_cast<QuotaPermissionRequest*>(other_request)
+ ->is_large_quota_request_;
+}
+
#if defined(OS_ANDROID)
std::u16string QuotaPermissionRequest::GetMessageText() const {
// If the site requested larger quota than this threshold, show a different
@@ -100,11 +112,11 @@ std::u16string QuotaPermissionRequest::GetMessageText() const {
: IDS_REQUEST_QUOTA_INFOBAR_TEXT),
url_formatter::FormatUrlForSecurityDisplay(origin_url_));
}
-#endif
-
+#else
std::u16string QuotaPermissionRequest::GetMessageTextFragment() const {
return l10n_util::GetStringUTF16(IDS_REQUEST_QUOTA_PERMISSION_FRAGMENT);
}
+#endif // !defined(OS_ANDROID)
GURL QuotaPermissionRequest::GetOrigin() const {
return origin_url_;
diff --git a/chromium/components/permissions/request_type.cc b/chromium/components/permissions/request_type.cc
index 9b5a4c3d03f..7e70c3b195e 100644
--- a/chromium/components/permissions/request_type.cc
+++ b/chromium/components/permissions/request_type.cc
@@ -91,7 +91,7 @@ const gfx::VectorIcon& GetIconIdDesktop(RequestType type) {
return vector_icons::kFileDownloadIcon;
case RequestType::kNotifications:
return vector_icons::kNotificationsIcon;
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
case RequestType::kProtectedMediaIdentifier:
// This icon is provided by ChromePermissionsClient::GetOverrideIconId.
NOTREACHED();
@@ -144,7 +144,7 @@ RequestType ContentSettingsTypeToRequestType(
return RequestType::kMidiSysex;
case ContentSettingsType::NOTIFICATIONS:
return RequestType::kNotifications;
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER:
return RequestType::kProtectedMediaIdentifier;
#endif
@@ -217,7 +217,7 @@ const char* PermissionKeyForRequestType(permissions::RequestType request_type) {
#endif
case permissions::RequestType::kNotifications:
return "notifications";
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
case permissions::RequestType::kProtectedMediaIdentifier:
return "protected_media_identifier";
#endif
diff --git a/chromium/components/permissions/request_type.h b/chromium/components/permissions/request_type.h
index a2519ae4340..d219ccbc3cb 100644
--- a/chromium/components/permissions/request_type.h
+++ b/chromium/components/permissions/request_type.h
@@ -5,9 +5,9 @@
#ifndef COMPONENTS_PERMISSIONS_REQUEST_TYPE_H_
#define COMPONENTS_PERMISSIONS_REQUEST_TYPE_H_
-#include "base/optional.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
enum class ContentSettingsType;
@@ -41,7 +41,7 @@ enum class RequestType {
kNfcDevice,
#endif
kNotifications,
-#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN)
kProtectedMediaIdentifier,
#endif
#if !defined(OS_ANDROID)
@@ -52,6 +52,9 @@ enum class RequestType {
kVrSession,
#if !defined(OS_ANDROID)
kWindowPlacement,
+ kMaxValue = kWindowPlacement
+#else
+ kMaxValue = kVrSession
#endif
};
diff --git a/chromium/components/permissions_strings.grdp b/chromium/components/permissions_strings.grdp
index c3d43fe4a04..7758f36f7b5 100644
--- a/chromium/components/permissions_strings.grdp
+++ b/chromium/components/permissions_strings.grdp
@@ -140,8 +140,41 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<message name="IDS_PERMISSIONS_BUBBLE_PROMPT_ONE_TIME" desc="The label that is used to introduce permission request details to the user in a popup.">
Allow <ph name="SITE_NAME">$1<ex>google.com</ex></ph> to:
</message>
- <message name="IDS_FILE_HANDLING_PERMISSION_FRAGMENT" desc="Permission request shown if the user is opening a file using a PWA with a registered file handler. Follows a prompt: 'This site would like to:'">
- Open files with file type associations.
+ <!-- Device Chooser -->
+ <if expr="not is_android">
+ <message name="IDS_BLUETOOTH_DEVICE_CHOOSER_PROMPT_ORIGIN" desc="The label that is used to introduce Bluetooth chooser details to the user in a popup when it is from a website.">
+ <ph name="Origin">$1<ex>www.google.com</ex></ph> wants to pair
+ </message>
+ <message name="IDS_BLUETOOTH_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT" desc="The label shown to the user to inform them that no Bluetooth devices were found matching the requirements that the application provided.">
+ No compatible devices found.
+ </message>
+ <message name="IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT" desc="Label on the button that closes the Bluetooth chooser popup and pairs the selected device.">
+ Pair
+ </message>
+ <message name="IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL" desc="Text on label that indicates a scan for Bluetooth devices is in progress.">
+ Scanning...
+ </message>
+ <message name="IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL_TOOLTIP" desc="Tooltip for the label that shows while scanning for Bluetooth devices.">
+ Scanning for Bluetooth devices...
+ </message>
+ </if>
+ <message name="IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT" desc="Label on the button that closes the chooser popup without selecting an option.">
+ Cancel
+ </message>
+ <message name="IDS_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT" desc="The label shown to the user to inform them that no USB devices were found matching the requirements that the application provided.">
+ No compatible devices found.
+ </message>
+ <message name="IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN" desc="The label that is used to introduce USB chooser details to the user in a popup when it is from a website.">
+ <ph name="Origin">$1<ex>www.google.com</ex></ph> wants to connect
+ </message>
+ <message name="IDS_USB_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT" desc="Label on the button that closes the USB chooser popup and connects the selected device.">
+ Connect
+ </message>
+ <message name="IDS_USB_DEVICE_CHOOSER_LOADING_LABEL" desc="Text on label that the browser is loading the list of USB devices.">
+ Finding devices...
+ </message>
+ <message name="IDS_USB_DEVICE_CHOOSER_LOADING_LABEL_TOOLTIP" desc="Tooltip for the label that the browser is loading the list of USB devices.">
+ Finding USB devices...
</message>
<if expr="not is_android">
diff --git a/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT.png.sha1 b/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT.png.sha1
new file mode 100644
index 00000000000..3559d64802e
--- /dev/null
+++ b/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@
+bb7f1a2da4dcdcbff033f665b97d90eedffb8857 \ No newline at end of file
diff --git a/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_PROMPT_ORIGIN.png.sha1 b/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_PROMPT_ORIGIN.png.sha1
new file mode 100644
index 00000000000..d589d2e082e
--- /dev/null
+++ b/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_PROMPT_ORIGIN.png.sha1
@@ -0,0 +1 @@
+57488cb0c2791f76f45fd6108861861284b70052 \ No newline at end of file
diff --git a/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL.png.sha1 b/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL.png.sha1
new file mode 100644
index 00000000000..d589d2e082e
--- /dev/null
+++ b/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL.png.sha1
@@ -0,0 +1 @@
+57488cb0c2791f76f45fd6108861861284b70052 \ No newline at end of file
diff --git a/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL_TOOLTIP.png.sha1 b/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL_TOOLTIP.png.sha1
new file mode 100644
index 00000000000..fd011760054
--- /dev/null
+++ b/chromium/components/permissions_strings_grdp/IDS_BLUETOOTH_DEVICE_CHOOSER_SCANNING_LABEL_TOOLTIP.png.sha1
@@ -0,0 +1 @@
+170bd960f4641014af57bb9d1fc9715817bdc167 \ No newline at end of file
diff --git a/chromium/components/permissions_strings_grdp/IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT.png.sha1 b/chromium/components/permissions_strings_grdp/IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT.png.sha1
new file mode 100644
index 00000000000..d589d2e082e
--- /dev/null
+++ b/chromium/components/permissions_strings_grdp/IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@
+57488cb0c2791f76f45fd6108861861284b70052 \ No newline at end of file
diff --git a/chromium/components/permissions_strings_grdp/IDS_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT.png.sha1 b/chromium/components/permissions_strings_grdp/IDS_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT.png.sha1
new file mode 100644
index 00000000000..b98f7ab06a0
--- /dev/null
+++ b/chromium/components/permissions_strings_grdp/IDS_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT.png.sha1
@@ -0,0 +1 @@
+da4b775e56898a0bf921951d5196ed976eb14567 \ No newline at end of file
diff --git a/chromium/components/permissions_strings_grdp/IDS_FILE_HANDLING_PERMISSION_FRAGMENT.png.sha1 b/chromium/components/permissions_strings_grdp/IDS_FILE_HANDLING_PERMISSION_FRAGMENT.png.sha1
deleted file mode 100644
index 72ab8b24a86..00000000000
--- a/chromium/components/permissions_strings_grdp/IDS_FILE_HANDLING_PERMISSION_FRAGMENT.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-55ddb345d69ee2187e402f22579fc4459b9563d1 \ No newline at end of file
diff --git a/chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_LOADING_LABEL.png.sha1 b/chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_LOADING_LABEL.png.sha1
new file mode 100644
index 00000000000..32028d335b3
--- /dev/null
+++ b/chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_LOADING_LABEL.png.sha1
@@ -0,0 +1 @@
+690f00b44b20541cc37c8a9e23d399af12a1f281 \ No newline at end of file
diff --git a/chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_LOADING_LABEL_TOOLTIP.png.sha1 b/chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_LOADING_LABEL_TOOLTIP.png.sha1
new file mode 100644
index 00000000000..66902ee9183
--- /dev/null
+++ b/chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_LOADING_LABEL_TOOLTIP.png.sha1
@@ -0,0 +1 @@
+71fb28900b917966c9adba6e377274062df6b2a4 \ No newline at end of file
diff --git a/chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN.png.sha1 b/chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN.png.sha1
new file mode 100644
index 00000000000..b98f7ab06a0
--- /dev/null
+++ b/chromium/components/permissions_strings_grdp/IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN.png.sha1
@@ -0,0 +1 @@
+da4b775e56898a0bf921951d5196ed976eb14567 \ No newline at end of file
diff --git a/chromium/components/plugins/OWNERS b/chromium/components/plugins/OWNERS
index 94de159b9e4..c5978ea20f1 100644
--- a/chromium/components/plugins/OWNERS
+++ b/chromium/components/plugins/OWNERS
@@ -1 +1,2 @@
tommycli@chromium.org
+dtapuska@chromium.org
diff --git a/chromium/components/plugins/renderer/loadable_plugin_placeholder.cc b/chromium/components/plugins/renderer/loadable_plugin_placeholder.cc
index 136d20e2964..dc6ff6bc92f 100644
--- a/chromium/components/plugins/renderer/loadable_plugin_placeholder.cc
+++ b/chromium/components/plugins/renderer/loadable_plugin_placeholder.cc
@@ -10,7 +10,6 @@
#include "base/callback_helpers.h"
#include "base/json/string_escape.h"
#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
diff --git a/chromium/components/plugins/renderer/webview_plugin.cc b/chromium/components/plugins/renderer/webview_plugin.cc
index f219ad4ed7a..330c99f88fa 100644
--- a/chromium/components/plugins/renderer/webview_plugin.cc
+++ b/chromium/components/plugins/renderer/webview_plugin.cc
@@ -60,7 +60,7 @@ WebViewPlugin::WebViewPlugin(WebView* web_view,
focused_(false),
is_painting_(false),
is_resizing_(false),
- web_view_helper_(this, preferences) {}
+ web_view_helper_(this, preferences, web_view->GetRendererPreferences()) {}
// static
WebViewPlugin* WebViewPlugin::Create(WebView* web_view,
@@ -258,8 +258,10 @@ void WebViewPlugin::DidFailLoading(const WebURLError& error) {
error_ = std::make_unique<WebURLError>(error);
}
-WebViewPlugin::WebViewHelper::WebViewHelper(WebViewPlugin* plugin,
- const WebPreferences& preferences)
+WebViewPlugin::WebViewHelper::WebViewHelper(
+ WebViewPlugin* plugin,
+ const WebPreferences& parent_web_preferences,
+ const blink::RendererPreferences& parent_renderer_preferences)
: plugin_(plugin),
agent_group_scheduler_(
blink::scheduler::WebThreadScheduler::MainThreadScheduler()
@@ -269,12 +271,19 @@ WebViewPlugin::WebViewHelper::WebViewHelper(WebViewPlugin* plugin,
/*is_hidden=*/false,
/*is_inside_portal=*/false,
/*compositing_enabled=*/false,
+ /*widgets_never_composited=*/false,
/*opener=*/nullptr, mojo::NullAssociatedReceiver(),
*agent_group_scheduler_,
/*session_storage_namespace_id=*/base::EmptyString());
// ApplyWebPreferences before making a WebLocalFrame so that the frame sees a
// consistent view of our preferences.
- blink::WebView::ApplyWebPreferences(preferences, web_view_);
+ blink::WebView::ApplyWebPreferences(parent_web_preferences, web_view_);
+
+ // Turn off AcceptLoadDrops for this plugin webview.
+ blink::RendererPreferences renderer_preferences = parent_renderer_preferences;
+ renderer_preferences.can_accept_load_drops = false;
+ web_view_->SetRendererPreferences(renderer_preferences);
+
WebLocalFrame* web_frame = WebLocalFrame::CreateMainFrame(
web_view_, this, nullptr, blink::LocalFrameToken(), nullptr);
blink::WebFrameWidget* frame_widget = web_frame->InitializeFrameWidget(
@@ -298,15 +307,7 @@ WebViewPlugin::WebViewHelper::~WebViewHelper() {
web_view_->Close();
}
-bool WebViewPlugin::WebViewHelper::AcceptsLoadDrops() {
- return false;
-}
-
-bool WebViewPlugin::WebViewHelper::CanUpdateLayout() {
- return true;
-}
-
-void WebViewPlugin::WebViewHelper::SetToolTipText(
+void WebViewPlugin::WebViewHelper::UpdateTooltipUnderCursor(
const std::u16string& tooltip_text,
base::i18n::TextDirection hint) {
if (plugin_->container_) {
@@ -315,9 +316,9 @@ void WebViewPlugin::WebViewHelper::SetToolTipText(
}
}
-void WebViewPlugin::WebViewHelper::DidInvalidateRect(const gfx::Rect& rect) {
+void WebViewPlugin::WebViewHelper::InvalidateContainer() {
if (plugin_->container_)
- plugin_->container_->InvalidateRect(rect);
+ plugin_->container_->Invalidate();
}
void WebViewPlugin::WebViewHelper::SetCursor(const ui::Cursor& cursor) {
@@ -361,6 +362,8 @@ void WebViewPlugin::WebViewHelper::DidClearWindowObject() {
v8::Isolate* isolate = blink::MainThreadIsolate();
v8::HandleScope handle_scope(isolate);
+ v8::MicrotasksScope microtasks_scope(
+ isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
v8::Local<v8::Context> context = frame_->MainWorldScriptContext();
DCHECK(!context.IsEmpty());
diff --git a/chromium/components/plugins/renderer/webview_plugin.h b/chromium/components/plugins/renderer/webview_plugin.h
index e70fe562922..6607978d2f4 100644
--- a/chromium/components/plugins/renderer/webview_plugin.h
+++ b/chromium/components/plugins/renderer/webview_plugin.h
@@ -160,17 +160,17 @@ class WebViewPlugin : public blink::WebPlugin, public blink::WebViewObserver {
public blink::WebLocalFrameClient,
public blink::mojom::WidgetHost {
public:
- WebViewHelper(WebViewPlugin* plugin,
- const blink::web_pref::WebPreferences& preferences);
+ WebViewHelper(
+ WebViewPlugin* plugin,
+ const blink::web_pref::WebPreferences& parent_web_preferences,
+ const blink::RendererPreferences& parent_renderer_preferences);
~WebViewHelper() override;
blink::WebView* web_view() { return web_view_; }
blink::WebNavigationControl* main_frame() { return frame_; }
// WebViewClient methods:
- bool AcceptsLoadDrops() override;
- bool CanUpdateLayout() override;
- void DidInvalidateRect(const gfx::Rect&) override;
+ void InvalidateContainer() override;
// WebNonCompositedWidgetClient overrides.
void ScheduleNonCompositedAnimation() override;
@@ -184,8 +184,8 @@ class WebViewPlugin : public blink::WebPlugin, public blink::WebViewObserver {
// blink::mojom::WidgetHost implementation.
void SetCursor(const ui::Cursor& cursor) override;
- void SetToolTipText(const std::u16string& tooltip_text,
- base::i18n::TextDirection hint) override;
+ void UpdateTooltipUnderCursor(const std::u16string& tooltip_text,
+ base::i18n::TextDirection hint) override;
void TextInputStateChanged(ui::mojom::TextInputStatePtr state) override {}
void SelectionBoundsChanged(const gfx::Rect& anchor_rect,
base::i18n::TextDirection anchor_dir,
diff --git a/chromium/components/policy/BUILD.gn b/chromium/components/policy/BUILD.gn
index cff52433015..3de9099d1c8 100644
--- a/chromium/components/policy/BUILD.gn
+++ b/chromium/components/policy/BUILD.gn
@@ -7,6 +7,7 @@ import("//build/config/chrome_build.gni")
import("//build/config/chromeos/ui_mode.gni")
import("//build/config/features.gni")
import("//build/config/python.gni")
+import("//build/timestamp.gni")
import("//build/toolchain/toolchain.gni")
import("//components/policy/resources/policy_templates.gni")
import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
@@ -457,6 +458,8 @@ if (gen_policy_templates_zip) {
args = [
"--output",
rebase_path(output_zip_file, root_build_dir),
+ "--timestamp",
+ build_timestamp,
"--base_dir",
rebase_path(policy_templates_base_dir, root_build_dir),
"--languages",
diff --git a/chromium/components/policy/core/browser/BUILD.gn b/chromium/components/policy/core/browser/BUILD.gn
index 58fd373e762..0e8afdd3711 100644
--- a/chromium/components/policy/core/browser/BUILD.gn
+++ b/chromium/components/policy/core/browser/BUILD.gn
@@ -41,6 +41,10 @@ source_set("internal") {
"url_blocklist_policy_handler.h",
"url_util.cc",
"url_util.h",
+ "webui/machine_level_user_cloud_policy_status_provider.cc",
+ "webui/machine_level_user_cloud_policy_status_provider.h",
+ "webui/policy_status_provider.cc",
+ "webui/policy_status_provider.h",
]
configs += [ "//components/policy:component_implementation" ]
diff --git a/chromium/components/policy/core/common/BUILD.gn b/chromium/components/policy/core/common/BUILD.gn
index 1e65636901b..10290f8679e 100644
--- a/chromium/components/policy/core/common/BUILD.gn
+++ b/chromium/components/policy/core/common/BUILD.gn
@@ -27,6 +27,8 @@ source_set("internal") {
"async_policy_provider.h",
"chrome_schema.cc",
"chrome_schema.h",
+ "cloud/affiliation.cc",
+ "cloud/affiliation.h",
"cloud/chrome_browser_cloud_management_metrics.h",
"cloud/cloud_external_data_manager.cc",
"cloud/cloud_external_data_manager.h",
@@ -420,6 +422,7 @@ source_set("common_constants") {
source_set("unit_tests") {
testonly = true
sources = [
+ "cloud/affiliation_unittest.cc",
"cloud/cloud_policy_client_unittest.cc",
"cloud/cloud_policy_core_unittest.cc",
"cloud/cloud_policy_manager_unittest.cc",
@@ -551,6 +554,7 @@ source_set("unit_tests") {
"//chrome/browser",
"//chromeos/crosapi/mojom",
"//chromeos/lacros",
+ "//chromeos/lacros:test_support",
"//chromeos/startup:startup",
]
}
diff --git a/chromium/components/policy_strings.grdp b/chromium/components/policy_strings.grdp
index d4876061ade..f51ebe777fc 100644
--- a/chromium/components/policy_strings.grdp
+++ b/chromium/components/policy_strings.grdp
@@ -244,6 +244,9 @@
<message name="IDS_POLICY_VALUE_DEPRECATED" desc="The text displayed in the status column when a specific value for a policy is deprecated.">
This value is deprecated for this policy.
</message>
+ <message name="IDS_POLICY_DEPENDENCY_ERROR" desc="The text displayed in the status column when a policy is ignored as another policies is not set properly.">
+ Ignored because <ph name="POLICY_NAME">$1<ex>CloudReportingEnabled</ex></ph> is not set to <ph name="VALUE">$2<ex>Enabled</ex></ph>.
+ </message>
<if expr="chromeos">
<message name="IDS_POLICY_NETWORK_CONFIG_PARSE_FAILED" desc="The text displayed in the status column when the corresponding network configuration policy failed to parse.">
Network configuration failed to be parsed (invalid JSON).
@@ -317,9 +320,6 @@ Additional details:
Google Update
</message>
</if>
- <message name="IDS_POLICY_LABEL_ENTERPRISE_ENROLLMENT_DOMAIN" desc="Label for the enrollment domain in the device policy status box.">
- Enrollment domain:
- </message>
<message name="IDS_POLICY_LABEL_MACHINE_ENROLLMENT_DOMAIN" desc="Label for the enrollment domain in the machine policy status box.">
Enrollment domain:
</message>
@@ -356,6 +356,9 @@ Additional details:
<message name="IDS_POLICY_LABEL_TIME_SINCE_LAST_REFRESH" desc="Label for the time since the last refresh in the policy status boxes.">
Last fetched:
</message>
+ <message name="IDS_POLICY_LABEL_LAST_CLOUD_REPORT_SENT_TIMESTAMP" desc="Label for the time when the last cloud report is sent successfully.">
+ Report sent:
+ </message>
<message name="IDS_POLICY_NOT_SPECIFIED" desc="Indicates if that device attribute has not specified yet.">
Not Specified
</message>
@@ -480,6 +483,9 @@ Additional details:
<message name="IDS_POLICY_SOURCE_MERGED" desc="Indicates that the policy is a merged values from multiple sources.">
Merged
</message>
+ <message name="IDS_POLICY_SOURCE_CLOUD_FROM_ASH" desc="Indicates that the policy originates from the cloud in Ash and piped to Lacros.">
+ Cloud (system-wide)
+ </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>
</message>
diff --git a/chromium/components/policy_strings_grdp/DIR_METADATA b/chromium/components/policy_strings_grdp/DIR_METADATA
index ccb8f65d40b..04f18043fb9 100644
--- a/chromium/components/policy_strings_grdp/DIR_METADATA
+++ b/chromium/components/policy_strings_grdp/DIR_METADATA
@@ -1,5 +1,5 @@
monorail {
- component: "Enterprise>CloudPolicy"
+ component: "Enterprise"
}
-team_email: "chromium-reviews@chromium.org"
+team_email: "chromium-enterprise@chromium.org"
diff --git a/chromium/components/policy_strings_grdp/IDS_POLICY_DEPENDENCY_ERROR.png.sha1 b/chromium/components/policy_strings_grdp/IDS_POLICY_DEPENDENCY_ERROR.png.sha1
new file mode 100644
index 00000000000..b4e0267ac58
--- /dev/null
+++ b/chromium/components/policy_strings_grdp/IDS_POLICY_DEPENDENCY_ERROR.png.sha1
@@ -0,0 +1 @@
+1271390ebc1e665f8561ceee384ceb876541407f \ No newline at end of file
diff --git a/chromium/components/policy_strings_grdp/IDS_POLICY_LABEL_LAST_CLOUD_REPORT_SENT_TIMESTAMP.png.sha1 b/chromium/components/policy_strings_grdp/IDS_POLICY_LABEL_LAST_CLOUD_REPORT_SENT_TIMESTAMP.png.sha1
new file mode 100644
index 00000000000..020a3dbe41c
--- /dev/null
+++ b/chromium/components/policy_strings_grdp/IDS_POLICY_LABEL_LAST_CLOUD_REPORT_SENT_TIMESTAMP.png.sha1
@@ -0,0 +1 @@
+d2d18086f6ff06ae6750195cc5c18e2a6a95480a \ No newline at end of file
diff --git a/chromium/components/policy_strings_grdp/IDS_POLICY_SOURCE_CLOUD_FROM_ASH.png.sha1 b/chromium/components/policy_strings_grdp/IDS_POLICY_SOURCE_CLOUD_FROM_ASH.png.sha1
new file mode 100644
index 00000000000..0cae259a120
--- /dev/null
+++ b/chromium/components/policy_strings_grdp/IDS_POLICY_SOURCE_CLOUD_FROM_ASH.png.sha1
@@ -0,0 +1 @@
+2d09468764de0e5a129450d92e8c4f8db54067ed \ No newline at end of file
diff --git a/chromium/components/policy_strings_grdp/IDS_POLICY_SYNC_DISABLED_PREREQUISITE_MISSING.png.sha1 b/chromium/components/policy_strings_grdp/IDS_POLICY_SYNC_DISABLED_PREREQUISITE_MISSING.png.sha1
new file mode 100644
index 00000000000..c8616db963c
--- /dev/null
+++ b/chromium/components/policy_strings_grdp/IDS_POLICY_SYNC_DISABLED_PREREQUISITE_MISSING.png.sha1
@@ -0,0 +1 @@
+917a3f04e8d9b4769520f11d91ef9bd4c9f4b6da \ No newline at end of file
diff --git a/chromium/components/power_scheduler/power_mode.cc b/chromium/components/power_scheduler/power_mode.cc
index 27be01d5074..f15c1ca26cd 100644
--- a/chromium/components/power_scheduler/power_mode.cc
+++ b/chromium/components/power_scheduler/power_mode.cc
@@ -12,12 +12,20 @@ const char* PowerModeToString(PowerMode mode) {
switch (mode) {
case PowerMode::kIdle:
return "Idle";
+ case PowerMode::kNopAnimation:
+ return "NopAnimation";
case PowerMode::kAudible:
return "Audible";
+ case PowerMode::kVideoPlayback:
+ return "VideoPlayback";
+ case PowerMode::kMainThreadAnimation:
+ return "MainThreadAnimation";
case PowerMode::kLoading:
return "Loading";
case PowerMode::kAnimation:
return "Animation";
+ case PowerMode::kLoadingAnimation:
+ return "LoadingAnimation";
case PowerMode::kResponse:
return "Response";
case PowerMode::kNonWebActivity:
diff --git a/chromium/components/power_scheduler/power_mode.h b/chromium/components/power_scheduler/power_mode.h
index fbcff124234..894b0b76eb6 100644
--- a/chromium/components/power_scheduler/power_mode.h
+++ b/chromium/components/power_scheduler/power_mode.h
@@ -19,15 +19,29 @@ enum class PowerMode {
// Default mode: none of the other use cases were detected.
kIdle,
+ // The vsync signal is observed, but no frames are produced/submitted.
+ kNopAnimation,
+
// The process is playing audio.
kAudible,
+ // A video is playing in the process and producing frames.
+ kVideoPlayback,
+
+ // The main thread is producing frames. This is broken out into a separate
+ // PowerMode to override kNopAnimation votes in cases where the main thread
+ // takes a long time to produce a new frame.
+ kMainThreadAnimation,
+
// A page or tab associated with the process is loading.
kLoading,
- // A surface rendered by the process is animating.
+ // A surface rendered by the process is animating and producing frames.
kAnimation,
+ // Both kLoading + kAnimation modes are active.
+ kLoadingAnimation,
+
// The process is responding to user input.
kResponse,
diff --git a/chromium/components/power_scheduler/power_mode_arbiter.cc b/chromium/components/power_scheduler/power_mode_arbiter.cc
index cb9b5915689..360d5552feb 100644
--- a/chromium/components/power_scheduler/power_mode_arbiter.cc
+++ b/chromium/components/power_scheduler/power_mode_arbiter.cc
@@ -15,6 +15,7 @@
#include "base/task/thread_pool.h"
#include "base/task_runner.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_log.h"
#include "components/power_scheduler/power_mode.h"
#include "components/power_scheduler/power_mode_voter.h"
@@ -22,22 +23,46 @@
namespace power_scheduler {
+using ObserverList = base::ObserverListThreadSafe<PowerModeArbiter::Observer>;
+
+namespace {
+class TraceObserver : public PowerModeArbiter::Observer {
+ public:
+ ~TraceObserver() override = default;
+ void OnPowerModeChanged(PowerMode old_mode, PowerMode new_mode) override {}
+};
+} // namespace
+
// Created and owned by the arbiter on thread pool initialization because there
// has to be exactly one per process, and //base can't depend on the
// power_scheduler component.
class PowerModeArbiter::ChargingPowerModeVoter : base::PowerStateObserver {
public:
- ChargingPowerModeVoter()
- : charging_voter_(PowerModeArbiter::GetInstance()->NewVoter(
- "PowerModeVoter.Charging")) {
+ explicit ChargingPowerModeVoter(PowerModeArbiter* arbiter)
+ : charging_voter_(arbiter->NewVoter("PowerModeVoter.Charging")) {
+ // Start out in charging mode until we can register the observer with
+ // PowerMonitor, which itself also starts out in charging mode.
+ charging_voter_->VoteFor(PowerMode::kCharging);
+ }
+
+ ~ChargingPowerModeVoter() override {
+ if (was_setup_)
+ base::PowerMonitor::RemovePowerStateObserver(this);
+ }
+
+ void Setup() {
+ if (was_setup_)
+ return;
+ was_setup_ = true;
+
const bool on_battery =
base::PowerMonitor::AddPowerStateObserverAndReturnOnBatteryState(this);
- if (base::PowerMonitor::IsInitialized())
- OnPowerStateChange(on_battery);
+ OnPowerStateChange(on_battery);
}
- ~ChargingPowerModeVoter() override {
- base::PowerMonitor::RemovePowerStateObserver(this);
+ void SetOnBatteryPowerForTesting(bool on_battery_power) {
+ OnPowerStateChange(on_battery_power);
+ was_setup_ = true; // Prevent real setup in the test.
}
void OnPowerStateChange(bool on_battery_power) override {
@@ -47,10 +72,13 @@ class PowerModeArbiter::ChargingPowerModeVoter : base::PowerStateObserver {
private:
std::unique_ptr<PowerModeVoter> charging_voter_;
+ bool was_setup_ = false;
};
PowerModeArbiter::Observer::~Observer() = default;
+constexpr base::TimeDelta PowerModeArbiter::kResetVoteTimeResolution;
+
// static
PowerModeArbiter* PowerModeArbiter::GetInstance() {
static base::NoDestructor<PowerModeArbiter> arbiter;
@@ -58,8 +86,11 @@ PowerModeArbiter* PowerModeArbiter::GetInstance() {
}
PowerModeArbiter::PowerModeArbiter()
- : observers_(new base::ObserverListThreadSafe<Observer>()),
- active_mode_("PowerModeArbiter", this) {
+ : trace_observer_(std::make_unique<TraceObserver>()),
+ active_mode_("PowerModeArbiter", this),
+ observers_(
+ base::MakeRefCounted<base::ObserverListThreadSafe<Observer>>()),
+ charging_voter_(std::make_unique<ChargingPowerModeVoter>(this)) {
base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
}
@@ -68,46 +99,59 @@ PowerModeArbiter::~PowerModeArbiter() {
}
void PowerModeArbiter::OnThreadPoolAvailable() {
- // May be called multiple times in single-process mode.
- if (task_runner_)
- return;
+ int sequence_number = 0;
+ scoped_refptr<base::SequencedTaskRunner> task_runner;
+ {
+ base::AutoLock lock(lock_);
- // Currently only used for the delayed votes.
- task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
- {base::TaskPriority::USER_VISIBLE,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+ // May be called multiple times in single-process mode.
+ if (task_runner_)
+ return;
- // Create the charging voter on the task runner sequence, so that charging
- // state notifications are received there.
- task_runner_->PostTask(FROM_HERE, base::BindOnce([] {
- PowerModeArbiter::GetInstance()->charging_voter_ =
- std::make_unique<ChargingPowerModeVoter>();
- }));
+ // Set task_runner_ under lock to avoid a race with AddObserver().
+ task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
+ {base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
+ task_runner = task_runner_;
+
+ // Acquire the current sequence number in case it was previously incremented
+ // by RemoveObserver(). It will be incremented by UpdatePendingResets()
+ // in OnTaskRunnerAvailable().
+ sequence_number = update_task_sequence_number_;
+ }
+
+ OnTaskRunnerAvailable(task_runner, sequence_number);
+}
- // Check if we need to post a task to update pending votes.
- base::TimeTicks next_effective_time;
+void PowerModeArbiter::SetTaskRunnerForTesting(
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ int sequence_number = 0;
{
base::AutoLock lock(lock_);
- for (const auto& entry : pending_resets_) {
- base::TimeTicks effective_time = entry.second;
- if (next_effective_time.is_null() ||
- effective_time < next_effective_time) {
- next_effective_time = effective_time;
- }
- }
- next_pending_vote_update_time_ = next_effective_time;
- }
- if (!next_effective_time.is_null()) {
- base::TimeTicks now = base::TimeTicks::Now();
- if (next_effective_time < now)
- next_effective_time = now;
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&PowerModeArbiter::UpdatePendingResets,
- base::Unretained(this)),
- next_effective_time - now);
+ DCHECK(!task_runner_);
+ task_runner_ = task_runner;
+ sequence_number = update_task_sequence_number_;
}
+
+ OnTaskRunnerAvailable(task_runner, sequence_number);
+}
+
+void PowerModeArbiter::OnTaskRunnerAvailable(
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ int sequence_number) {
+ // Check if there are any actionable resets and post another task to handle
+ // future ones if necessary. If sequence_number is changed concurrently by
+ // RemoveObserver() or ResetVoteAfterTimeout(), this has call has no effect,
+ // but a future call to UpdatePendingResets() will take its place.
+ UpdatePendingResets(sequence_number);
+
+ // Create the charging voter on the task runner sequence, so that charging
+ // state notifications are received there.
+ task_runner->PostTask(
+ FROM_HERE, base::BindOnce([] {
+ PowerModeArbiter::GetInstance()->charging_voter_->Setup();
+ }));
}
std::unique_ptr<PowerModeVoter> PowerModeArbiter::NewVoter(const char* name) {
@@ -120,13 +164,41 @@ std::unique_ptr<PowerModeVoter> PowerModeArbiter::NewVoter(const char* name) {
}
void PowerModeArbiter::AddObserver(Observer* observer) {
- base::AutoLock lock(lock_);
- observer->OnPowerModeChanged(PowerMode::kIdle, active_mode_.mode());
- observers_->AddObserver(observer);
+ DCHECK(observer);
+ bool should_update_pending_resets = false;
+ int sequence_number = 0;
+
+ {
+ base::AutoLock lock(lock_);
+ observer->OnPowerModeChanged(PowerMode::kIdle, active_mode_.mode());
+ should_update_pending_resets = task_runner_ && !has_observers_;
+ // Acquire the current sequence number in case it was previously incremented
+ // by RemoveObserver(). If necessary, it will be incremented by
+ // UpdatePendingResets() below.
+ sequence_number = update_task_sequence_number_;
+ observers_->AddObserver(observer);
+ has_observers_ = true;
+ }
+
+ // Reset tasks are disabled until the first observer is registered. If
+ // sequence_number is changed concurrently by RemoveObserver() or
+ // ResetVoteAfterTimeout(), this has call has no effect, but a future call to
+ // UpdatePendingResets() will take its place.
+ if (should_update_pending_resets)
+ UpdatePendingResets(sequence_number);
}
void PowerModeArbiter::RemoveObserver(Observer* observer) {
- observers_->RemoveObserver(observer);
+ base::AutoLock lock(lock_);
+ ObserverList::RemoveObserverResult result =
+ observers_->RemoveObserver(observer);
+ has_observers_ =
+ result == ObserverList::RemoveObserverResult::kRemainsNonEmpty;
+
+ // Increment update_task_sequence_number_ so that any scheduled update tasks
+ // are skipped and only restarted if another observer registers.
+ if (!has_observers_)
+ ++update_task_sequence_number_;
}
void PowerModeArbiter::OnVoterDestroyed(PowerModeVoter* voter) {
@@ -156,38 +228,57 @@ void PowerModeArbiter::SetVote(PowerModeVoter* voter, PowerMode mode) {
void PowerModeArbiter::ResetVoteAfterTimeout(PowerModeVoter* voter,
base::TimeDelta timeout) {
bool should_post_update_task = false;
+ int sequence_number = 0;
+ scoped_refptr<base::TaskRunner> task_runner;
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks scheduled_time = now + timeout;
+ // Align to the reset task's resolution.
+ scheduled_time = scheduled_time.SnappedToNextTick(base::TimeTicks(),
+ kResetVoteTimeResolution);
+
{
base::AutoLock lock(lock_);
- base::TimeTicks scheduled_time = base::TimeTicks::Now() + timeout;
pending_resets_[voter] = scheduled_time;
// Only post a new task if there isn't one scheduled to run earlier yet.
// This reduces the number of posted callbacks in situations where the
// pending vote is cleared soon after UpdateVoteAfterTimeout() by SetVote().
- if (task_runner_ && (next_pending_vote_update_time_.is_null() ||
- scheduled_time < next_pending_vote_update_time_)) {
+ if (task_runner_ && has_observers_ &&
+ (next_pending_vote_update_time_.is_null() ||
+ scheduled_time < next_pending_vote_update_time_)) {
next_pending_vote_update_time_ = scheduled_time;
should_post_update_task = true;
+ ++update_task_sequence_number_;
+ sequence_number = update_task_sequence_number_;
+ task_runner = task_runner_;
}
}
if (should_post_update_task) {
- task_runner_->PostDelayedTask(
+ task_runner->PostDelayedTask(
FROM_HERE,
base::BindOnce(&PowerModeArbiter::UpdatePendingResets,
- base::Unretained(this)),
- timeout);
+ base::Unretained(this), sequence_number),
+ scheduled_time - now);
}
}
-void PowerModeArbiter::UpdatePendingResets() {
- // Note: This method may run at any point. Do not assume that there are any
- // resets that have expired, or that any other UpdatePendingResets() task is
- // scheduled.
+void PowerModeArbiter::UpdatePendingResets(int sequence_number) {
+ // Note: This method may run at any point and on any thread. Do not assume
+ // that there are any resets that have expired, or that any other
+ // UpdatePendingResets() task is scheduled.
bool did_change = false;
base::TimeTicks now = base::TimeTicks::Now();
base::TimeTicks next_task_time;
+ int next_sequence_number = 0;
+ scoped_refptr<base::TaskRunner> task_runner;
{
base::AutoLock lock(lock_);
+
+ // Check if this task was cancelled and replaced by another one.
+ if (update_task_sequence_number_ != sequence_number)
+ return;
+
+ now = base::TimeTicks::Now();
for (auto it = pending_resets_.begin(); it != pending_resets_.end();) {
base::TimeTicks task_time = it->second;
if (task_time <= now) {
@@ -204,13 +295,19 @@ void PowerModeArbiter::UpdatePendingResets() {
++it;
}
}
+
next_pending_vote_update_time_ = next_task_time;
+ if (!next_task_time.is_null()) {
+ task_runner = task_runner_;
+ ++update_task_sequence_number_;
+ next_sequence_number = update_task_sequence_number_;
+ }
}
if (!next_task_time.is_null()) {
- task_runner_->PostDelayedTask(
+ task_runner->PostDelayedTask(
FROM_HERE,
base::BindOnce(&PowerModeArbiter::UpdatePendingResets,
- base::Unretained(this)),
+ base::Unretained(this), next_sequence_number),
next_task_time - now);
}
if (did_change)
@@ -234,6 +331,7 @@ void PowerModeArbiter::OnVotesUpdated() {
PowerMode PowerModeArbiter::ComputeActiveModeLocked() {
PowerMode mode = PowerMode::kIdle;
bool is_audible = false;
+ bool is_loading = false;
for (const auto& voter_and_vote : votes_) {
PowerMode vote = voter_and_vote.second.mode();
@@ -241,12 +339,18 @@ PowerMode PowerModeArbiter::ComputeActiveModeLocked() {
mode = vote;
if (vote == PowerMode::kAudible)
is_audible = true;
+ if (vote == PowerMode::kLoading)
+ is_loading = true;
}
// In background, audible overrides.
if (mode == PowerMode::kBackground && is_audible)
return PowerMode::kAudible;
+ // Break out loading while concurrently animating into a separate mode.
+ if (mode == PowerMode::kAnimation && is_loading)
+ return PowerMode::kLoadingAnimation;
+
return mode;
}
@@ -255,13 +359,29 @@ PowerMode PowerModeArbiter::GetActiveModeForTesting() {
return active_mode_.mode();
}
+void PowerModeArbiter::SetOnBatteryPowerForTesting(bool on_battery_power) {
+ charging_voter_->SetOnBatteryPowerForTesting(on_battery_power); // IN-TEST
+}
+
void PowerModeArbiter::OnTraceLogEnabled() {
- base::AutoLock lock(lock_);
- for (const auto& voter_and_vote : votes_)
- voter_and_vote.second.OnTraceLogEnabled();
- active_mode_.OnTraceLogEnabled();
+ {
+ base::AutoLock lock(lock_);
+ for (const auto& voter_and_vote : votes_)
+ voter_and_vote.second.OnTraceLogEnabled();
+ active_mode_.OnTraceLogEnabled();
+ }
+
+ const auto* power_tracing_enabled =
+ TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("power");
+ if (*power_tracing_enabled) {
+ // Add a no-op observer which ensures that reset tasks are executing while
+ // tracing is enabled.
+ AddObserver(trace_observer_.get());
+ }
}
-void PowerModeArbiter::OnTraceLogDisabled() {}
+void PowerModeArbiter::OnTraceLogDisabled() {
+ RemoveObserver(trace_observer_.get());
+}
} // namespace power_scheduler
diff --git a/chromium/components/power_scheduler/power_mode_arbiter.h b/chromium/components/power_scheduler/power_mode_arbiter.h
index 69cefe4ed1a..7f5f559754f 100644
--- a/chromium/components/power_scheduler/power_mode_arbiter.h
+++ b/chromium/components/power_scheduler/power_mode_arbiter.h
@@ -9,6 +9,7 @@
#include <memory>
#include "base/component_export.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "base/observer_list_threadsafe.h"
@@ -42,6 +43,11 @@ class COMPONENT_EXPORT(POWER_SCHEDULER) PowerModeArbiter
virtual void OnPowerModeChanged(PowerMode old_mode, PowerMode new_mode) = 0;
};
+ // Limits the frequency at which we can run the UpdatePendingResets() task.
+ // All pending resets are aligned to this time resolution. Public for testing.
+ static constexpr base::TimeDelta kResetVoteTimeResolution =
+ base::TimeDelta::FromMilliseconds(100);
+
static PowerModeArbiter* GetInstance();
// Public for testing.
@@ -65,10 +71,16 @@ class COMPONENT_EXPORT(POWER_SCHEDULER) PowerModeArbiter
// pool is available.
void OnThreadPoolAvailable();
- // Returns the currently active PowerMode. Public for testing.
+ // Provide a custom task runner for unit tests. Replaces a call to
+ // OnThreadPoolAvailable().
+ void SetTaskRunnerForTesting(scoped_refptr<base::SequencedTaskRunner>);
+
PowerMode GetActiveModeForTesting();
+ void SetOnBatteryPowerForTesting(bool on_battery_power);
private:
+ FRIEND_TEST_ALL_PREFIXES(PowerModeArbiterTest, ObserverEnablesResetTasks);
+
class ChargingPowerModeVoter;
// PowerModeVoter::Delegate implementation:
@@ -76,24 +88,33 @@ class COMPONENT_EXPORT(POWER_SCHEDULER) PowerModeArbiter
void SetVote(PowerModeVoter*, PowerMode) override;
void ResetVoteAfterTimeout(PowerModeVoter*, base::TimeDelta timeout) override;
- void UpdatePendingResets();
+ void OnTaskRunnerAvailable(scoped_refptr<base::SequencedTaskRunner>,
+ int sequence_number);
+
+ void UpdatePendingResets(int sequence_number);
void OnVotesUpdated();
+ void ServicePendingResetsLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
+
PowerMode ComputeActiveModeLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_);
// trace_event::TraceLog::EnabledStateObserver implementation:
void OnTraceLogEnabled() override;
void OnTraceLogDisabled() override;
- scoped_refptr<base::TaskRunner> task_runner_;
- scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_;
+ std::unique_ptr<Observer> trace_observer_;
- base::Lock lock_;
+ base::Lock lock_; // Protects subsequent members.
+ scoped_refptr<base::SequencedTaskRunner> task_runner_ GUARDED_BY(lock_);
std::map<PowerModeVoter*, TracedPowerMode> votes_ GUARDED_BY(lock_);
std::map<PowerModeVoter*, base::TimeTicks /*effective_time*/> pending_resets_
GUARDED_BY(lock_);
base::TimeTicks next_pending_vote_update_time_ GUARDED_BY(lock_);
TracedPowerMode active_mode_ GUARDED_BY(lock_);
+ int update_task_sequence_number_ GUARDED_BY(lock_) = 0;
+ scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_
+ GUARDED_BY(lock_);
+ bool has_observers_ GUARDED_BY(lock_) = false;
// Owned by the arbiter but otherwise behaves like a regular voter.
std::unique_ptr<ChargingPowerModeVoter> charging_voter_;
diff --git a/chromium/components/power_scheduler/power_mode_arbiter_unittest.cc b/chromium/components/power_scheduler/power_mode_arbiter_unittest.cc
index eb394e77f63..c2a5b887532 100644
--- a/chromium/components/power_scheduler/power_mode_arbiter_unittest.cc
+++ b/chromium/components/power_scheduler/power_mode_arbiter_unittest.cc
@@ -12,6 +12,10 @@ namespace power_scheduler {
TEST(PowerModeArbiterTest, SingleVote) {
PowerModeArbiter arbiter;
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kCharging);
+
+ // Clear the initial kCharging vote.
+ arbiter.SetOnBatteryPowerForTesting(/*on_battery_power=*/true);
EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kIdle);
std::unique_ptr<PowerModeVoter> voter1 = arbiter.NewVoter("voter1");
@@ -29,6 +33,12 @@ TEST(PowerModeArbiterTest, SingleVote) {
TEST(PowerModeArbiterTest, MultipleVotes) {
PowerModeArbiter arbiter;
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kCharging);
+
+ // Clear the initial kCharging vote.
+ arbiter.SetOnBatteryPowerForTesting(/*on_battery_power=*/true);
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kIdle);
+
EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kIdle);
std::unique_ptr<PowerModeVoter> voter1 = arbiter.NewVoter("voter1");
@@ -54,53 +64,154 @@ TEST(PowerModeArbiterTest, MultipleVotes) {
// Charging trumps anything.
vote_and_expect(PowerMode::kCharging, PowerMode::kIdle, PowerMode::kCharging);
+ vote_and_expect(PowerMode::kCharging, PowerMode::kNopAnimation,
+ PowerMode::kCharging);
vote_and_expect(PowerMode::kCharging, PowerMode::kAudible,
PowerMode::kCharging);
+ vote_and_expect(PowerMode::kCharging, PowerMode::kVideoPlayback,
+ PowerMode::kCharging);
+ vote_and_expect(PowerMode::kCharging, PowerMode::kMainThreadAnimation,
+ PowerMode::kCharging);
vote_and_expect(PowerMode::kCharging, PowerMode::kLoading,
PowerMode::kCharging);
vote_and_expect(PowerMode::kCharging, PowerMode::kAnimation,
PowerMode::kCharging);
+ vote_and_expect(PowerMode::kCharging, PowerMode::kLoadingAnimation,
+ PowerMode::kCharging);
vote_and_expect(PowerMode::kCharging, PowerMode::kResponse,
PowerMode::kCharging);
+ vote_and_expect(PowerMode::kCharging, PowerMode::kNonWebActivity,
+ PowerMode::kCharging);
vote_and_expect(PowerMode::kCharging, PowerMode::kBackground,
PowerMode::kCharging);
// Background trumps remaining modes, but not audible.
vote_and_expect(PowerMode::kBackground, PowerMode::kIdle,
PowerMode::kBackground);
+ vote_and_expect(PowerMode::kBackground, PowerMode::kNopAnimation,
+ PowerMode::kBackground);
vote_and_expect(PowerMode::kBackground, PowerMode::kAudible,
PowerMode::kAudible);
+ vote_and_expect(PowerMode::kBackground, PowerMode::kVideoPlayback,
+ PowerMode::kBackground);
+ vote_and_expect(PowerMode::kBackground, PowerMode::kMainThreadAnimation,
+ PowerMode::kBackground);
vote_and_expect(PowerMode::kBackground, PowerMode::kLoading,
PowerMode::kBackground);
vote_and_expect(PowerMode::kBackground, PowerMode::kAnimation,
PowerMode::kBackground);
+ vote_and_expect(PowerMode::kBackground, PowerMode::kLoadingAnimation,
+ PowerMode::kBackground);
vote_and_expect(PowerMode::kBackground, PowerMode::kResponse,
PowerMode::kBackground);
+ vote_and_expect(PowerMode::kBackground, PowerMode::kNonWebActivity,
+ PowerMode::kBackground);
+
+ // NonWebActivity trumps remaining modes.
+ vote_and_expect(PowerMode::kNonWebActivity, PowerMode::kIdle,
+ PowerMode::kNonWebActivity);
+ vote_and_expect(PowerMode::kNonWebActivity, PowerMode::kNopAnimation,
+ PowerMode::kNonWebActivity);
+ vote_and_expect(PowerMode::kNonWebActivity, PowerMode::kAudible,
+ PowerMode::kNonWebActivity);
+ vote_and_expect(PowerMode::kNonWebActivity, PowerMode::kVideoPlayback,
+ PowerMode::kNonWebActivity);
+ vote_and_expect(PowerMode::kNonWebActivity, PowerMode::kMainThreadAnimation,
+ PowerMode::kNonWebActivity);
+ vote_and_expect(PowerMode::kNonWebActivity, PowerMode::kLoading,
+ PowerMode::kNonWebActivity);
+ vote_and_expect(PowerMode::kNonWebActivity, PowerMode::kAnimation,
+ PowerMode::kNonWebActivity);
+ vote_and_expect(PowerMode::kNonWebActivity, PowerMode::kLoadingAnimation,
+ PowerMode::kNonWebActivity);
+ vote_and_expect(PowerMode::kNonWebActivity, PowerMode::kResponse,
+ PowerMode::kNonWebActivity);
// Response trumps remaining modes.
vote_and_expect(PowerMode::kResponse, PowerMode::kIdle, PowerMode::kResponse);
+ vote_and_expect(PowerMode::kResponse, PowerMode::kNopAnimation,
+ PowerMode::kResponse);
vote_and_expect(PowerMode::kResponse, PowerMode::kAudible,
PowerMode::kResponse);
+ vote_and_expect(PowerMode::kResponse, PowerMode::kVideoPlayback,
+ PowerMode::kResponse);
+ vote_and_expect(PowerMode::kResponse, PowerMode::kMainThreadAnimation,
+ PowerMode::kResponse);
vote_and_expect(PowerMode::kResponse, PowerMode::kLoading,
PowerMode::kResponse);
vote_and_expect(PowerMode::kResponse, PowerMode::kAnimation,
PowerMode::kResponse);
+ vote_and_expect(PowerMode::kResponse, PowerMode::kLoadingAnimation,
+ PowerMode::kResponse);
+
+ // LoadingAnimation trumps remaining modes.
+ vote_and_expect(PowerMode::kLoadingAnimation, PowerMode::kIdle,
+ PowerMode::kLoadingAnimation);
+ vote_and_expect(PowerMode::kLoadingAnimation, PowerMode::kNopAnimation,
+ PowerMode::kLoadingAnimation);
+ vote_and_expect(PowerMode::kLoadingAnimation, PowerMode::kAudible,
+ PowerMode::kLoadingAnimation);
+ vote_and_expect(PowerMode::kLoadingAnimation, PowerMode::kVideoPlayback,
+ PowerMode::kLoadingAnimation);
+ vote_and_expect(PowerMode::kLoadingAnimation, PowerMode::kMainThreadAnimation,
+ PowerMode::kLoadingAnimation);
+ vote_and_expect(PowerMode::kLoadingAnimation, PowerMode::kLoading,
+ PowerMode::kLoadingAnimation);
+ vote_and_expect(PowerMode::kLoadingAnimation, PowerMode::kAnimation,
+ PowerMode::kLoadingAnimation);
// Animation trumps remaining modes.
vote_and_expect(PowerMode::kAnimation, PowerMode::kIdle,
PowerMode::kAnimation);
+ vote_and_expect(PowerMode::kAnimation, PowerMode::kNopAnimation,
+ PowerMode::kAnimation);
vote_and_expect(PowerMode::kAnimation, PowerMode::kAudible,
PowerMode::kAnimation);
- vote_and_expect(PowerMode::kAnimation, PowerMode::kLoading,
+ vote_and_expect(PowerMode::kAnimation, PowerMode::kVideoPlayback,
+ PowerMode::kAnimation);
+ vote_and_expect(PowerMode::kAnimation, PowerMode::kMainThreadAnimation,
PowerMode::kAnimation);
+ // Animation while loading breaks out into a separate mode.
+ vote_and_expect(PowerMode::kAnimation, PowerMode::kLoading,
+ PowerMode::kLoadingAnimation);
// Loading trumps remaining modes.
vote_and_expect(PowerMode::kLoading, PowerMode::kIdle, PowerMode::kLoading);
+ vote_and_expect(PowerMode::kLoading, PowerMode::kNopAnimation,
+ PowerMode::kLoading);
vote_and_expect(PowerMode::kLoading, PowerMode::kAudible,
PowerMode::kLoading);
+ vote_and_expect(PowerMode::kLoading, PowerMode::kVideoPlayback,
+ PowerMode::kLoading);
+ vote_and_expect(PowerMode::kLoading, PowerMode::kMainThreadAnimation,
+ PowerMode::kLoading);
- // Audible trumps idle.
+ // MainThreadAnimation trumps remaining modes.
+ vote_and_expect(PowerMode::kMainThreadAnimation, PowerMode::kIdle,
+ PowerMode::kMainThreadAnimation);
+ vote_and_expect(PowerMode::kMainThreadAnimation, PowerMode::kNopAnimation,
+ PowerMode::kMainThreadAnimation);
+ vote_and_expect(PowerMode::kMainThreadAnimation, PowerMode::kAudible,
+ PowerMode::kMainThreadAnimation);
+ vote_and_expect(PowerMode::kMainThreadAnimation, PowerMode::kVideoPlayback,
+ PowerMode::kMainThreadAnimation);
+
+ // VideoPlayback trumps remaining modes.
+ vote_and_expect(PowerMode::kVideoPlayback, PowerMode::kIdle,
+ PowerMode::kVideoPlayback);
+ vote_and_expect(PowerMode::kVideoPlayback, PowerMode::kNopAnimation,
+ PowerMode::kVideoPlayback);
+ vote_and_expect(PowerMode::kVideoPlayback, PowerMode::kAudible,
+ PowerMode::kVideoPlayback);
+
+ // Audible trumps idle and no-op animation.
vote_and_expect(PowerMode::kAudible, PowerMode::kIdle, PowerMode::kAudible);
+ vote_and_expect(PowerMode::kAudible, PowerMode::kNopAnimation,
+ PowerMode::kAudible);
+
+ // NopAnimation trumps idle.
+ vote_and_expect(PowerMode::kNopAnimation, PowerMode::kIdle,
+ PowerMode::kNopAnimation);
}
namespace {
@@ -119,6 +230,9 @@ TEST(PowerModeArbiterTest, Observer) {
PowerModeArbiter arbiter;
MockObserver observer;
+ // Clear the initial kCharging vote.
+ arbiter.SetOnBatteryPowerForTesting(/*on_battery_power=*/true);
+
// Observer is notified of initial mode right away.
EXPECT_CALL(observer, OnPowerModeChanged(PowerMode::kIdle, PowerMode::kIdle));
@@ -145,10 +259,33 @@ TEST(PowerModeArbiterTest, Observer) {
arbiter.RemoveObserver(&observer);
}
+namespace {
+class FakeObserver : public PowerModeArbiter::Observer {
+ public:
+ ~FakeObserver() override = default;
+ void OnPowerModeChanged(PowerMode old_mode, PowerMode new_mode) override {}
+};
+} // namespace
+
TEST(PowerModeArbiterTest, ResetVoteAfterTimeout) {
base::test::TaskEnvironment env(
base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+
+ // Align the mock clock with the phase of the reset tasks.
+ base::TimeTicks target_time = env.NowTicks().SnappedToNextTick(
+ base::TimeTicks(), PowerModeArbiter::kResetVoteTimeResolution);
+ env.AdvanceClock(target_time - env.NowTicks());
+
PowerModeArbiter arbiter;
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kCharging);
+
+ // Clear the initial kCharging vote.
+ arbiter.SetOnBatteryPowerForTesting(/*on_battery_power=*/true);
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kIdle);
+
+ // Add a fake observer to enable reset tasks.
+ FakeObserver observer;
+ arbiter.AddObserver(&observer);
base::TimeDelta delta1s = base::TimeDelta::FromSeconds(1);
base::TimeDelta delta2s = base::TimeDelta::FromSeconds(2);
@@ -211,11 +348,82 @@ TEST(PowerModeArbiterTest, ResetVoteAfterTimeout) {
env.FastForwardBy(delta1s); // Execute the second reset task.
EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kIdle);
+ // Unaligned reset timeouts get aligned to the resolution.
+ voter1->VoteFor(PowerMode::kAnimation);
+ voter2->VoteFor(PowerMode::kCharging);
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kCharging);
+ voter2->ResetVoteAfterTimeout(PowerModeArbiter::kResetVoteTimeResolution / 3);
+ voter1->ResetVoteAfterTimeout(PowerModeArbiter::kResetVoteTimeResolution / 2);
+ base::TimeDelta first_half = PowerModeArbiter::kResetVoteTimeResolution / 2;
+ env.FastForwardBy(first_half);
+ // No change, since the timeouts were aligned to kResetVoteTimeResolution.
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kCharging);
+ // Executes the resets.
+ env.FastForwardBy(PowerModeArbiter::kResetVoteTimeResolution - first_half);
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kIdle);
+
// If the voter is destroyed, the task doesn't cause crashes.
voter1->VoteFor(PowerMode::kAnimation);
voter1->ResetVoteAfterTimeout(delta1s);
voter1.reset();
env.FastForwardBy(delta1s); // Execute the reset task.
+
+ arbiter.RemoveObserver(&observer);
+}
+
+TEST(PowerModeArbiterTest, ObserverEnablesResetTasks) {
+ base::test::TaskEnvironment env(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+
+ // Align the mock clock with the phase of the reset tasks.
+ base::TimeTicks target_time = env.NowTicks().SnappedToNextTick(
+ base::TimeTicks(), PowerModeArbiter::kResetVoteTimeResolution);
+ env.AdvanceClock(target_time - env.NowTicks());
+
+ PowerModeArbiter arbiter;
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kCharging);
+
+ // Clear the initial kCharging vote.
+ arbiter.SetOnBatteryPowerForTesting(/*on_battery_power=*/true);
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kIdle);
+
+ FakeObserver observer;
+ base::TimeDelta delta1s = base::TimeDelta::FromSeconds(1);
+
+ arbiter.OnThreadPoolAvailable();
+
+ std::unique_ptr<PowerModeVoter> voter1 = arbiter.NewVoter("voter1");
+
+ for (int i = 0; i < 2; i++) {
+ // Without observer, reset tasks are not executed and resets not serviced.
+ voter1->VoteFor(PowerMode::kAnimation);
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kAnimation);
+ voter1->ResetVoteAfterTimeout(delta1s);
+ {
+ base::AutoLock lock(arbiter.lock_);
+ EXPECT_EQ(arbiter.next_pending_vote_update_time_, base::TimeTicks());
+ }
+ env.FastForwardBy(delta1s);
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kAnimation);
+
+ // Adding the observer services the reset.
+ arbiter.AddObserver(&observer);
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kIdle);
+
+ // While observer is registered, resets are serviced.
+ voter1->VoteFor(PowerMode::kAnimation);
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kAnimation);
+ voter1->ResetVoteAfterTimeout(delta1s);
+ {
+ base::AutoLock lock(arbiter.lock_);
+ EXPECT_NE(arbiter.next_pending_vote_update_time_, base::TimeTicks());
+ }
+ env.FastForwardBy(delta1s);
+ EXPECT_EQ(arbiter.GetActiveModeForTesting(), PowerMode::kIdle);
+
+ // After removing the observer, resets are no longer serviced.
+ arbiter.RemoveObserver(&observer);
+ }
}
} // namespace power_scheduler \ No newline at end of file
diff --git a/chromium/components/power_scheduler/power_mode_voter.cc b/chromium/components/power_scheduler/power_mode_voter.cc
index cb9a164474a..fcf254173b7 100644
--- a/chromium/components/power_scheduler/power_mode_voter.cc
+++ b/chromium/components/power_scheduler/power_mode_voter.cc
@@ -4,6 +4,8 @@
#include "components/power_scheduler/power_mode_voter.h"
+#include "components/power_scheduler/power_mode_arbiter.h"
+
namespace power_scheduler {
PowerModeVoter::Delegate::~Delegate() = default;
@@ -15,7 +17,13 @@ constexpr base::TimeDelta PowerModeVoter::kResponseTimeout;
// static
constexpr base::TimeDelta PowerModeVoter::kAnimationTimeout;
// static
+constexpr base::TimeDelta PowerModeVoter::kVideoTimeout;
+// static
+constexpr base::TimeDelta PowerModeVoter::kSoftwareDrawTimeout;
+// static
constexpr base::TimeDelta PowerModeVoter::kLoadingTimeout;
+// static
+constexpr base::TimeDelta PowerModeVoter::kStuckLoadingTimeout;
PowerModeVoter::~PowerModeVoter() {
delegate_->OnVoterDestroyed(this);
@@ -29,4 +37,91 @@ void PowerModeVoter::ResetVoteAfterTimeout(base::TimeDelta timeout) {
delegate_->ResetVoteAfterTimeout(this, timeout);
}
+// static
+constexpr int FrameProductionPowerModeVoter::kMinFramesSkippedForIdleAnimation;
+
+FrameProductionPowerModeVoter::FrameProductionPowerModeVoter(const char* name)
+ : voter_(PowerModeArbiter::GetInstance()->NewVoter(name)) {}
+
+FrameProductionPowerModeVoter::~FrameProductionPowerModeVoter() = default;
+
+void FrameProductionPowerModeVoter::OnNeedsBeginFramesChanged(
+ bool needs_begin_frames) {
+ needs_begin_frames_ = needs_begin_frames;
+ if (needs_begin_frames) {
+ consecutive_frames_skipped_ = 0;
+ voter_->VoteFor(PowerMode::kAnimation);
+ } else {
+ voter_->ResetVoteAfterTimeout(PowerModeVoter::kAnimationTimeout);
+ }
+}
+
+void FrameProductionPowerModeVoter::OnFrameProduced() {
+ consecutive_frames_skipped_ = 0;
+
+ // If we were in no-op mode, only go back into animation mode if there were at
+ // least two frames produced within kAnimationTimeout.
+ base::TimeTicks now = base::TimeTicks::Now();
+ if (last_frame_produced_timestamp_ + PowerModeVoter::kAnimationTimeout <
+ now) {
+ last_frame_produced_timestamp_ = now;
+ return;
+ }
+
+ last_frame_produced_timestamp_ = now;
+ voter_->VoteFor(PowerMode::kAnimation);
+
+ if (!needs_begin_frames_)
+ voter_->ResetVoteAfterTimeout(PowerModeVoter::kAnimationTimeout);
+}
+
+void FrameProductionPowerModeVoter::OnFrameSkipped(bool frame_completed,
+ bool waiting_on_main) {
+ // Only consider skipped frames when we still need BeginFrames.
+ if (!needs_begin_frames_)
+ return;
+
+ // Ignore frames that are skipped in an incomplete state, e.g. because frame
+ // production took too long and the deadline was missed. Such frames should
+ // not count as "no-op", because frame production may still be in progress.
+ // However, if we were only waiting on the main thread, we will treat this as
+ // no-op here, because we cannot distinguish aborted BeginMainFrame sequences
+ // from "long" content-producing BeginMainFrames here. Instead, a separate
+ // PowerModeVoter tracks BeginMainFrame production in cc::Scheduler.
+ if (!frame_completed && !waiting_on_main)
+ return;
+
+ if (consecutive_frames_skipped_ < kMinFramesSkippedForIdleAnimation) {
+ consecutive_frames_skipped_++;
+ return;
+ }
+
+ voter_->VoteFor(PowerMode::kNopAnimation);
+}
+
+void FrameProductionPowerModeVoter::OnFrameTimeout() {
+ voter_->VoteFor(PowerMode::kNopAnimation);
+}
+
+DebouncedPowerModeVoter::DebouncedPowerModeVoter(const char* name,
+ base::TimeDelta timeout)
+ : voter_(PowerModeArbiter::GetInstance()->NewVoter(name)),
+ timeout_(timeout) {}
+
+DebouncedPowerModeVoter::~DebouncedPowerModeVoter() = default;
+
+void DebouncedPowerModeVoter::VoteFor(PowerMode vote) {
+ base::TimeTicks now = base::TimeTicks::Now();
+ if (!last_vote_ || vote != *last_vote_ ||
+ last_vote_timestamp_ + timeout_ < now) {
+ last_vote_ = vote;
+ last_vote_timestamp_ = now;
+ return;
+ }
+
+ DCHECK_EQ(*last_vote_, vote);
+ last_vote_timestamp_ = now;
+ voter_->VoteFor(vote);
+}
+
} // namespace power_scheduler
diff --git a/chromium/components/power_scheduler/power_mode_voter.h b/chromium/components/power_scheduler/power_mode_voter.h
index f6c8792ce1d..c58b216a388 100644
--- a/chromium/components/power_scheduler/power_mode_voter.h
+++ b/chromium/components/power_scheduler/power_mode_voter.h
@@ -5,9 +5,12 @@
#ifndef COMPONENTS_POWER_SCHEDULER_POWER_MODE_VOTER_H_
#define COMPONENTS_POWER_SCHEDULER_POWER_MODE_VOTER_H_
+#include <memory>
+
#include "base/component_export.h"
#include "base/time/time.h"
#include "components/power_scheduler/power_mode.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace power_scheduler {
@@ -35,11 +38,20 @@ class COMPONENT_EXPORT(POWER_SCHEDULER) PowerModeVoter {
// timeout is applied before resetting animation votes to avoid frequent vote
// reversals.
static constexpr base::TimeDelta kAnimationTimeout =
- base::TimeDelta::FromMilliseconds(50);
+ base::TimeDelta::FromMilliseconds(100);
+ static constexpr base::TimeDelta kVideoTimeout = kAnimationTimeout;
+ // Software draws can take longer than the rest of animations. We use a
+ // different timeout constant for them to allow individual tweaking.
+ static constexpr base::TimeDelta kSoftwareDrawTimeout =
+ base::TimeDelta::FromMilliseconds(100);
+
+ // Give frames an extra second to draw & settle after load completion.
+ static constexpr base::TimeDelta kLoadingTimeout =
+ base::TimeDelta::FromSeconds(1);
// Avoid getting stuck in loading stage forever. More than 99.9% of
// navigations load (to largest contentful paint) in less than a minute.
- static constexpr base::TimeDelta kLoadingTimeout =
+ static constexpr base::TimeDelta kStuckLoadingTimeout =
base::TimeDelta::FromSeconds(60);
~PowerModeVoter();
@@ -62,6 +74,63 @@ class COMPONENT_EXPORT(POWER_SCHEDULER) PowerModeVoter {
Delegate* delegate_;
};
+// Tracks the BeginFrame signal as well as produced and skipped frames to vote
+// either for the kAnimation, kNopAnimation, or kIdle modes.
+class COMPONENT_EXPORT(POWER_SCHEDULER) FrameProductionPowerModeVoter {
+ public:
+ explicit FrameProductionPowerModeVoter(const char* name);
+ ~FrameProductionPowerModeVoter();
+
+ FrameProductionPowerModeVoter(const FrameProductionPowerModeVoter&) = delete;
+ FrameProductionPowerModeVoter& operator=(
+ const FrameProductionPowerModeVoter&) = delete;
+
+ // Should be called when starting or stoping observing BeginFrames.
+ void OnNeedsBeginFramesChanged(bool needs_begin_frames);
+ // Should be called when a frame is produced.
+ void OnFrameProduced();
+ // Should be called when a frame is skipped. |frame_completed| should be true
+ // if the frame production resulted in no visible updates and was completed on
+ // time. In other cases (e.g. if the deadline was missed and frame production
+ // continues for the next vsync), it should be false. |waiting_on_main| should
+ // be true if the frame was not completed because the main thread's frame
+ // production was not finished on time for the deadline.
+ void OnFrameSkipped(bool frame_completed, bool waiting_on_main);
+ // Should be called when BeginFrame was not followed by a draw within a set
+ // timeframe.
+ void OnFrameTimeout();
+
+ private:
+ // 10 Frames: 166ms on 60fps, 111ms on 90fps, 83ms on 120fps. This should be a
+ // reasonable compromise to avoid frequent flip-flopping between different
+ // animation modes.
+ static constexpr int kMinFramesSkippedForIdleAnimation = 10;
+
+ std::unique_ptr<PowerModeVoter> voter_;
+ int consecutive_frames_skipped_ = 0;
+ base::TimeTicks last_frame_produced_timestamp_;
+ bool needs_begin_frames_ = false;
+};
+
+// PowerModeVoter that requires two consecutive votes for the same PowerMode
+// within a given timeout to move out of idle.
+class COMPONENT_EXPORT(POWER_SCHEDULER) DebouncedPowerModeVoter {
+ public:
+ DebouncedPowerModeVoter(const char* name, base::TimeDelta timeout);
+ ~DebouncedPowerModeVoter();
+
+ void VoteFor(PowerMode vote);
+
+ void ResetVoteAfterTimeout() { voter_->ResetVoteAfterTimeout(timeout_); }
+
+ private:
+ std::unique_ptr<PowerModeVoter> voter_;
+ const base::TimeDelta timeout_;
+
+ absl::optional<PowerMode> last_vote_;
+ base::TimeTicks last_vote_timestamp_;
+};
+
} // namespace power_scheduler
#endif // COMPONENTS_POWER_SCHEDULER_POWER_MODE_VOTER_H_
diff --git a/chromium/components/power_scheduler/power_scheduler.cc b/chromium/components/power_scheduler/power_scheduler.cc
index 527cf6313ea..4ef10efd757 100644
--- a/chromium/components/power_scheduler/power_scheduler.cc
+++ b/chromium/components/power_scheduler/power_scheduler.cc
@@ -8,10 +8,13 @@
#include "base/cpu.h"
#include "base/cpu_affinity_posix.h"
#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/process/process_handle.h"
#include "base/task/current_thread.h"
+#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
#include "base/trace_event/typed_macros.h"
namespace {
@@ -36,12 +39,12 @@ CpuAffinityModeForUma GetCpuAffinityModeForUma(base::CpuAffinityMode affinity) {
perfetto::StaticString TraceEventNameForAffinityMode(
base::CpuAffinityMode affinity) {
- if (affinity == base::CpuAffinityMode::kDefault) {
- return "ApplyCpuAffinityModeDefault";
- } else if (affinity == base::CpuAffinityMode::kLittleCoresOnly) {
- return "ApplyCpuAffinityModeLittleCoresOnly";
+ switch (affinity) {
+ case base::CpuAffinityMode::kDefault:
+ return "ApplyCpuAffinityModeDefault";
+ case base::CpuAffinityMode::kLittleCoresOnly:
+ return "ApplyCpuAffinityModeLittleCoresOnly";
}
- return "ApplyCpuAffinityModeUnknown";
}
void ApplyProcessCpuAffinityMode(base::CpuAffinityMode affinity) {
@@ -73,7 +76,10 @@ bool CpuAffinityApplicable() {
namespace power_scheduler {
-PowerScheduler::PowerScheduler() = default;
+PowerScheduler::PowerScheduler() {
+ DETACH_FROM_SEQUENCE(thread_pool_checker_);
+}
+
PowerScheduler::~PowerScheduler() = default;
// static
@@ -86,101 +92,170 @@ void PowerScheduler::WillProcessTask(const base::PendingTask& pending_task,
bool was_blocked_or_low_priority) {}
void PowerScheduler::DidProcessTask(const base::PendingTask& pending_task) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(main_thread_checker_);
++task_counter_;
if (task_counter_ == kUpdateAfterEveryNTasks) {
- EnforceCpuAffinity();
+ thread_pool_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&PowerScheduler::EnforceCpuAffinityOnSequence,
+ base::Unretained(this) // never destroyed.
+ ));
task_counter_ = 0;
}
}
void PowerScheduler::OnPowerModeChanged(power_scheduler::PowerMode old_mode,
power_scheduler::PowerMode new_mode) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- current_power_mode_ = new_mode;
+ TRACE_EVENT2("power", "PowerScheduler::OnPowerModeChanged", "old_mode",
+ power_scheduler::PowerModeToString(old_mode), "new_mode",
+ power_scheduler::PowerModeToString(new_mode));
- ApplyPolicy();
+ OnPowerModeChangedOnSequence(old_mode, new_mode);
}
void PowerScheduler::Setup() {
- // The setup should be called once from the main thread. Subsequent calls
- // from other threads should be ignored.
+ // The setup should be called once from the main thread. In single-process
+ // mode, it may later be called on other threads (which should be ignored).
if (did_call_setup_)
return;
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(main_thread_checker_);
- SetupPolicy();
+ main_thread_task_runner_ = base::SequencedTaskRunnerHandle::Get();
+ thread_pool_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
+ {base::TaskPriority::USER_BLOCKING,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
did_call_setup_ = true;
+
+ if (pending_policy_ == SchedulingPolicy::kNone)
+ return;
+
+ thread_pool_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&PowerScheduler::SetupPolicyOnSequence,
+ base::Unretained(this), // never destroyed.
+ pending_policy_));
+ pending_policy_ = SchedulingPolicy::kNone;
}
void PowerScheduler::SetPolicy(SchedulingPolicy policy) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(main_thread_checker_);
if (!CpuAffinityApplicable())
return;
- current_policy_ = policy;
-
// Set up the power affinity observer and apply the policy if it's already
// possible. Otherwise it will be set up after thread initialization via
// Setup() (see app/content_main_runner_impl.cc and child/child_process.cc).
- if (base::CurrentThread::IsSet()) {
- SetupPolicy();
+ if (thread_pool_task_runner_) {
+ thread_pool_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&PowerScheduler::SetupPolicyOnSequence,
+ base::Unretained(this), // never destroyed.
+ policy));
+ } else {
+ pending_policy_ = policy;
}
}
-void PowerScheduler::SetupPolicy() {
+void PowerScheduler::SetupPolicyOnSequence(SchedulingPolicy policy) {
DCHECK(power_scheduler::PowerModeArbiter::GetInstance());
- DCHECK(base::CurrentThread::IsSet());
+ DCHECK_CALLED_ON_VALID_SEQUENCE(thread_pool_checker_);
// Reset the power mode in case it contains an obsolete value.
current_power_mode_ = power_scheduler::PowerMode::kMaxValue;
+ current_policy_ = policy;
- if (current_policy_ == SchedulingPolicy::kThrottleIdle &&
- !power_observer_registered_) {
+ bool needs_power_observer =
+ current_policy_ == SchedulingPolicy::kThrottleIdle ||
+ current_policy_ == SchedulingPolicy::kThrottleIdleAndNopAnimation;
+
+ if (needs_power_observer && !power_observer_registered_) {
power_scheduler::PowerModeArbiter::GetInstance()->AddObserver(this);
power_observer_registered_ = true;
- } else if (current_policy_ != SchedulingPolicy::kThrottleIdle &&
- power_observer_registered_) {
+ } else if (!needs_power_observer && power_observer_registered_) {
power_scheduler::PowerModeArbiter::GetInstance()->RemoveObserver(this);
power_observer_registered_ = false;
}
- ApplyPolicy();
+ ApplyPolicyOnSequence();
}
-void PowerScheduler::ApplyPolicy() {
- auto new_affinity = base::CpuAffinityMode::kDefault;
- if (current_policy_ == SchedulingPolicy::kLittleCoresOnly ||
- (current_policy_ == SchedulingPolicy::kThrottleIdle &&
- (current_power_mode_ == power_scheduler::PowerMode::kIdle ||
- current_power_mode_ == power_scheduler::PowerMode::kBackground))) {
- new_affinity = base::CpuAffinityMode::kLittleCoresOnly;
+void PowerScheduler::OnPowerModeChangedOnSequence(
+ power_scheduler::PowerMode old_mode,
+ power_scheduler::PowerMode new_mode) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(thread_pool_checker_);
+
+ current_power_mode_ = new_mode;
+ ApplyPolicyOnSequence();
+}
+
+void PowerScheduler::ApplyPolicyOnSequence() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(thread_pool_checker_);
+
+ bool should_throttle = false;
+ switch (current_policy_) {
+ case SchedulingPolicy::kNone:
+ break;
+ case SchedulingPolicy::kLittleCoresOnly:
+ should_throttle = true;
+ break;
+ case SchedulingPolicy::kThrottleIdle:
+ should_throttle =
+ current_power_mode_ == power_scheduler::PowerMode::kIdle ||
+ current_power_mode_ == power_scheduler::PowerMode::kBackground;
+ break;
+ case SchedulingPolicy::kThrottleIdleAndNopAnimation:
+ should_throttle =
+ current_power_mode_ == power_scheduler::PowerMode::kIdle ||
+ current_power_mode_ == power_scheduler::PowerMode::kBackground ||
+ current_power_mode_ == power_scheduler::PowerMode::kNopAnimation;
+ break;
}
+ auto new_affinity = should_throttle ? base::CpuAffinityMode::kLittleCoresOnly
+ : base::CpuAffinityMode::kDefault;
+
if (new_affinity != enforced_affinity_) {
+ base::TimeTicks now = base::TimeTicks::Now();
+ if (new_affinity == base::CpuAffinityMode::kDefault &&
+ !enforced_affinity_setup_time_.is_null()) {
+ UMA_HISTOGRAM_CUSTOM_TIMES("Power.PowerScheduler.ThrottlingDuration",
+ now - enforced_affinity_setup_time_,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10), 100);
+ }
+ enforced_affinity_setup_time_ = now;
enforced_affinity_ = new_affinity;
- EnforceCpuAffinity();
+ EnforceCpuAffinityOnSequence();
}
}
-void PowerScheduler::EnforceCpuAffinity() {
- if (enforced_affinity_ == base::CpuAffinityMode::kLittleCoresOnly &&
- !task_observer_registered_) {
- base::CurrentThread::Get()->AddTaskObserver(this);
- task_observer_registered_ = true;
- } else if (enforced_affinity_ == base::CpuAffinityMode::kDefault &&
- task_observer_registered_) {
- // We don't have to enforce the default affinity.
- base::CurrentThread::Get()->RemoveTaskObserver(this);
- task_observer_registered_ = false;
- }
+void PowerScheduler::EnforceCpuAffinityOnSequence() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(thread_pool_checker_);
if (enforced_affinity_ != base::CurrentThreadCpuAffinityMode())
ApplyProcessCpuAffinityMode(enforced_affinity_);
+
+ // Android system may reset a non-default affinity setting, so we need to
+ // check periodically if we need to re-apply it.
+ bool mode_needs_periodic_enforcement =
+ enforced_affinity_ != base::CpuAffinityMode::kDefault;
+
+ if (mode_needs_periodic_enforcement && !task_observer_registered_) {
+ main_thread_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce([] {
+ base::CurrentThread::Get()->AddTaskObserver(
+ PowerScheduler::GetInstance());
+ }));
+ task_observer_registered_ = true;
+ } else if (!mode_needs_periodic_enforcement && task_observer_registered_) {
+ main_thread_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce([] {
+ base::CurrentThread::Get()->RemoveTaskObserver(
+ PowerScheduler::GetInstance());
+ PowerScheduler::GetInstance()->task_counter_ = 0;
+ }));
+ task_observer_registered_ = false;
+ }
}
} // namespace power_scheduler
diff --git a/chromium/components/power_scheduler/power_scheduler.h b/chromium/components/power_scheduler/power_scheduler.h
index e94b81e33a9..b41019cf1c9 100644
--- a/chromium/components/power_scheduler/power_scheduler.h
+++ b/chromium/components/power_scheduler/power_scheduler.h
@@ -16,6 +16,7 @@ enum class SchedulingPolicy {
kNone,
kLittleCoresOnly,
kThrottleIdle,
+ kThrottleIdleAndNopAnimation,
};
class COMPONENT_EXPORT(POWER_SCHEDULER) PowerScheduler
@@ -31,9 +32,9 @@ class COMPONENT_EXPORT(POWER_SCHEDULER) PowerScheduler
PowerScheduler& operator=(const PowerScheduler&) = delete;
// base::TaskObserver implementation.
- void WillProcessTask(const base::PendingTask& pending_task,
+ void WillProcessTask(const base::PendingTask&,
bool was_blocked_or_low_priority) override;
- void DidProcessTask(const base::PendingTask& pending_task) override;
+ void DidProcessTask(const base::PendingTask&) override;
// power_scheduler::PowerModeArbiter::Observer implementation.
void OnPowerModeChanged(power_scheduler::PowerMode old_mode,
@@ -52,28 +53,40 @@ class COMPONENT_EXPORT(POWER_SCHEDULER) PowerScheduler
// The affinity might change at runtime (e.g. after Chrome goes back from
// background), so the power scheduler will set up a polling mechanism to
// enforce the given mode.
- void SetPolicy(SchedulingPolicy policy);
+ void SetPolicy(SchedulingPolicy);
private:
// Register the power mode observer and apply the current policy if necessary.
- void SetupPolicy();
+ void SetupPolicyOnSequence(SchedulingPolicy);
+
+ void OnPowerModeChangedOnSequence(power_scheduler::PowerMode old_mode,
+ power_scheduler::PowerMode new_mode);
// Apply CPU affinity settings according to current policy and power mode.
- void ApplyPolicy();
+ void ApplyPolicyOnSequence();
// Set the CPU affinity of the current process and set up the polling
// mechanism to enforce the affinity mode. The check is implemented as a
// TaskObserver that runs every 100th main thread task.
- void EnforceCpuAffinity();
+ void EnforceCpuAffinityOnSequence();
+
+ SEQUENCE_CHECKER(main_thread_checker_);
+ SEQUENCE_CHECKER(thread_pool_checker_);
- SEQUENCE_CHECKER(sequence_checker_);
+ scoped_refptr<base::TaskRunner> main_thread_task_runner_;
+ scoped_refptr<base::TaskRunner> thread_pool_task_runner_;
+ // Accessed only on the main thread.
static constexpr int kUpdateAfterEveryNTasks = 100;
int task_counter_ = 0;
bool did_call_setup_ = false;
+ SchedulingPolicy pending_policy_ = SchedulingPolicy::kNone;
+
+ // Accessed only on the |thread_pool_task_runner_| sequence.
bool power_observer_registered_ = false;
bool task_observer_registered_ = false;
base::CpuAffinityMode enforced_affinity_ = base::CpuAffinityMode::kDefault;
+ base::TimeTicks enforced_affinity_setup_time_;
power_scheduler::PowerMode current_power_mode_ =
power_scheduler::PowerMode::kMaxValue;
SchedulingPolicy current_policy_ = SchedulingPolicy::kNone;
diff --git a/chromium/components/power_scheduler/traced_power_mode.h b/chromium/components/power_scheduler/traced_power_mode.h
index 942c5c3dce8..976291b6f69 100644
--- a/chromium/components/power_scheduler/traced_power_mode.h
+++ b/chromium/components/power_scheduler/traced_power_mode.h
@@ -7,7 +7,6 @@
#include <atomic>
-#include "base/trace_event/trace_event.h"
#include "components/power_scheduler/power_mode.h"
namespace power_scheduler {
diff --git a/chromium/components/pref_registry/DIR_METADATA b/chromium/components/pref_registry/DIR_METADATA
index 1b859d641e2..e9153b069b8 100644
--- a/chromium/components/pref_registry/DIR_METADATA
+++ b/chromium/components/pref_registry/DIR_METADATA
@@ -1,5 +1,5 @@
monorail {
- component: "UI>Browser>Preferences"
+ component: "Internals>Preferences"
}
team_email: "chromium-dev@chromium.org"
diff --git a/chromium/components/prefs/BUILD.gn b/chromium/components/prefs/BUILD.gn
index 1017a2069cc..0df592dc08a 100644
--- a/chromium/components/prefs/BUILD.gn
+++ b/chromium/components/prefs/BUILD.gn
@@ -42,6 +42,8 @@ component("prefs") {
"prefs_export.h",
"scoped_user_pref_update.cc",
"scoped_user_pref_update.h",
+ "segregated_pref_store.cc",
+ "segregated_pref_store.h",
"value_map_pref_store.cc",
"value_map_pref_store.h",
"writeable_pref_store.cc",
@@ -103,6 +105,7 @@ source_set("unit_tests") {
"pref_value_map_unittest.cc",
"pref_value_store_unittest.cc",
"scoped_user_pref_update_unittest.cc",
+ "segregated_pref_store_unittest.cc",
]
deps = [
diff --git a/chromium/components/prefs/DIR_METADATA b/chromium/components/prefs/DIR_METADATA
index 1b859d641e2..e9153b069b8 100644
--- a/chromium/components/prefs/DIR_METADATA
+++ b/chromium/components/prefs/DIR_METADATA
@@ -1,5 +1,5 @@
monorail {
- component: "UI>Browser>Preferences"
+ component: "Internals>Preferences"
}
team_email: "chromium-dev@chromium.org"
diff --git a/chromium/components/prefs/android/DIR_METADATA b/chromium/components/prefs/android/DIR_METADATA
index 830f167d664..1744a1fc936 100644
--- a/chromium/components/prefs/android/DIR_METADATA
+++ b/chromium/components/prefs/android/DIR_METADATA
@@ -1,5 +1,2 @@
-monorail {
- component: "Internals>Preferences"
-}
os: ANDROID
diff --git a/chromium/components/prefs/command_line_pref_store.cc b/chromium/components/prefs/command_line_pref_store.cc
index 4a475f57695..35c74a4b62e 100644
--- a/chromium/components/prefs/command_line_pref_store.cc
+++ b/chromium/components/prefs/command_line_pref_store.cc
@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
+#include "base/values.h"
CommandLinePrefStore::CommandLinePrefStore(
const base::CommandLine* command_line)
diff --git a/chromium/components/prefs/command_line_pref_store.h b/chromium/components/prefs/command_line_pref_store.h
index 03d5da96958..bbc7b2bff1a 100644
--- a/chromium/components/prefs/command_line_pref_store.h
+++ b/chromium/components/prefs/command_line_pref_store.h
@@ -7,7 +7,6 @@
#include "base/command_line.h"
#include "base/macros.h"
-#include "base/values.h"
#include "components/prefs/value_map_pref_store.h"
// Base class for a PrefStore that maps command line switches to preferences.
diff --git a/chromium/components/prefs/json_pref_store.cc b/chromium/components/prefs/json_pref_store.cc
index c7017f0b61e..2f1f2c72fa9 100644
--- a/chromium/components/prefs/json_pref_store.cc
+++ b/chromium/components/prefs/json_pref_store.cc
@@ -220,7 +220,7 @@ void JsonPrefStore::SetValue(const std::string& key,
DCHECK(value);
base::Value* old_value = nullptr;
prefs_->Get(key, &old_value);
- if (!old_value || !value->Equals(old_value)) {
+ if (!old_value || *value != *old_value) {
prefs_->Set(key, std::move(value));
ReportValueChanged(key, flags);
}
@@ -234,7 +234,7 @@ void JsonPrefStore::SetValueSilently(const std::string& key,
DCHECK(value);
base::Value* old_value = nullptr;
prefs_->Get(key, &old_value);
- if (!old_value || !value->Equals(old_value)) {
+ if (!old_value || *value != *old_value) {
prefs_->Set(key, std::move(value));
ScheduleWrite(flags);
}
diff --git a/chromium/components/prefs/json_pref_store_unittest.cc b/chromium/components/prefs/json_pref_store_unittest.cc
index 024f36a0091..5eeeeeed12e 100644
--- a/chromium/components/prefs/json_pref_store_unittest.cc
+++ b/chromium/components/prefs/json_pref_store_unittest.cc
@@ -240,55 +240,51 @@ void RunBasicJsonPrefStoreTest(JsonPrefStore* pref_store,
const Value* actual;
EXPECT_TRUE(pref_store->GetValue(kHomePage, &actual));
- std::string string_value;
- EXPECT_TRUE(actual->GetAsString(&string_value));
- EXPECT_EQ(cnn, string_value);
+ EXPECT_TRUE(actual->is_string());
+ EXPECT_EQ(cnn, actual->GetString());
const char kSomeDirectory[] = "some_directory";
EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
- std::string path;
- EXPECT_TRUE(actual->GetAsString(&path));
- EXPECT_EQ("/usr/local/", path);
+ EXPECT_TRUE(actual->is_string());
+ EXPECT_EQ("/usr/local/", actual->GetString());
base::FilePath some_path(FILE_PATH_LITERAL("/usr/sbin/"));
pref_store->SetValue(kSomeDirectory,
std::make_unique<Value>(some_path.AsUTF8Unsafe()),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(pref_store->GetValue(kSomeDirectory, &actual));
- EXPECT_TRUE(actual->GetAsString(&path));
- EXPECT_EQ(some_path.AsUTF8Unsafe(), path);
+ EXPECT_TRUE(actual->is_string());
+ EXPECT_EQ(some_path.AsUTF8Unsafe(), actual->GetString());
// Test reading some other data types from sub-dictionaries.
EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
- bool boolean = false;
- EXPECT_TRUE(actual->GetAsBoolean(&boolean));
- EXPECT_TRUE(boolean);
+ EXPECT_TRUE(actual->is_bool());
+ EXPECT_TRUE(actual->GetBool());
pref_store->SetValue(kNewWindowsInTabs, std::make_unique<Value>(false),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(pref_store->GetValue(kNewWindowsInTabs, &actual));
- EXPECT_TRUE(actual->GetAsBoolean(&boolean));
- EXPECT_FALSE(boolean);
+ EXPECT_TRUE(actual->is_bool());
+ EXPECT_FALSE(actual->GetBool());
EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
- int integer = 0;
- EXPECT_TRUE(actual->GetAsInteger(&integer));
- EXPECT_EQ(20, integer);
+ ASSERT_TRUE(actual->is_int());
+ EXPECT_EQ(20, actual->GetInt());
pref_store->SetValue(kMaxTabs, std::make_unique<Value>(10),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(pref_store->GetValue(kMaxTabs, &actual));
- EXPECT_TRUE(actual->GetAsInteger(&integer));
- EXPECT_EQ(10, integer);
+ ASSERT_TRUE(actual->is_int());
+ EXPECT_EQ(10, actual->GetInt());
pref_store->SetValue(
kLongIntPref,
std::make_unique<Value>(base::NumberToString(214748364842LL)),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
EXPECT_TRUE(pref_store->GetValue(kLongIntPref, &actual));
- EXPECT_TRUE(actual->GetAsString(&string_value));
+ EXPECT_TRUE(actual->is_string());
int64_t value;
- base::StringToInt64(string_value, &value);
+ base::StringToInt64(actual->GetString(), &value);
EXPECT_EQ(214748364842LL, value);
// Serialize and compare to expected output.
diff --git a/chromium/components/prefs/mock_pref_change_callback.h b/chromium/components/prefs/mock_pref_change_callback.h
index 9c0aeecd9c3..6ba895c3d52 100644
--- a/chromium/components/prefs/mock_pref_change_callback.h
+++ b/chromium/components/prefs/mock_pref_change_callback.h
@@ -28,7 +28,7 @@ MATCHER_P3(PrefValueMatches, prefs, pref_name, value, "") {
return value == NULL;
if (!value)
return actual_value == NULL;
- return value->Equals(actual_value);
+ return *value == *actual_value;
}
// A mock for testing preference notifications and easy setup of expectations.
diff --git a/chromium/components/prefs/overlay_user_pref_store.cc b/chromium/components/prefs/overlay_user_pref_store.cc
index 5bb26b43e48..b3374930553 100644
--- a/chromium/components/prefs/overlay_user_pref_store.cc
+++ b/chromium/components/prefs/overlay_user_pref_store.cc
@@ -116,7 +116,7 @@ bool OverlayUserPrefStore::GetMutableValue(const std::string& key,
return false;
ephemeral_user_pref_store_->SetValue(
- key, persistent_value->CreateDeepCopy(),
+ key, base::Value::ToUniquePtrValue(persistent_value->Clone()),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
ephemeral_user_pref_store_->GetMutableValue(key, result);
return true;
diff --git a/chromium/components/prefs/overlay_user_pref_store_unittest.cc b/chromium/components/prefs/overlay_user_pref_store_unittest.cc
index 1c0c855b93c..d8be47e61b0 100644
--- a/chromium/components/prefs/overlay_user_pref_store_unittest.cc
+++ b/chromium/components/prefs/overlay_user_pref_store_unittest.cc
@@ -145,7 +145,7 @@ TEST_F(OverlayUserPrefStoreTest, ModifyDictionaries) {
EXPECT_TRUE(underlay_->GetMutableValue(regular_key, &original_in_underlay));
ASSERT_TRUE(original_in_underlay);
ASSERT_TRUE(original_in_underlay->is_dict());
- EXPECT_TRUE(static_cast<DictionaryValue*>(original_in_underlay)->empty());
+ EXPECT_TRUE(original_in_underlay->DictEmpty());
Value* modified = nullptr;
EXPECT_TRUE(overlay_->GetMutableValue(regular_key, &modified));
diff --git a/chromium/components/prefs/persistent_pref_store.h b/chromium/components/prefs/persistent_pref_store.h
index 967ccdaaec8..0da1423d159 100644
--- a/chromium/components/prefs/persistent_pref_store.h
+++ b/chromium/components/prefs/persistent_pref_store.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_PREFS_PERSISTENT_PREF_STORE_H_
#define COMPONENTS_PREFS_PERSISTENT_PREF_STORE_H_
-#include <string>
-
#include "base/callback.h"
#include "components/prefs/prefs_export.h"
#include "components/prefs/writeable_pref_store.h"
diff --git a/chromium/components/prefs/pref_member.cc b/chromium/components/prefs/pref_member.cc
index a53394f6ff8..e2087ab1bc7 100644
--- a/chromium/components/prefs/pref_member.cc
+++ b/chromium/components/prefs/pref_member.cc
@@ -11,6 +11,7 @@
#include "base/location.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/util/values/values_util.h"
+#include "base/values.h"
#include "components/prefs/pref_service.h"
using base::SequencedTaskRunner;
@@ -72,8 +73,9 @@ void PrefMemberBase::UpdateValueFromPref(base::OnceClosure callback) const {
DCHECK(pref);
if (!internal())
CreateInternal();
- internal()->UpdateValue(pref->GetValue()->DeepCopy(), pref->IsManaged(),
- pref->IsUserModifiable(), std::move(callback));
+ internal()->UpdateValue(
+ base::Value::ToUniquePtrValue(pref->GetValue()->Clone()).release(),
+ pref->IsManaged(), pref->IsUserModifiable(), std::move(callback));
}
void PrefMemberBase::VerifyPref() const {
@@ -129,15 +131,12 @@ bool PrefMemberVectorStringUpdate(const base::Value& value,
std::vector<std::string>* string_vector) {
if (!value.is_list())
return false;
- const base::ListValue* list = static_cast<const base::ListValue*>(&value);
std::vector<std::string> local_vector;
- for (auto it = list->begin(); it != list->end(); ++it) {
- std::string string_value;
- if (!it->GetAsString(&string_value))
+ for (const auto& item : value.GetList()) {
+ if (!item.is_string())
return false;
-
- local_vector.push_back(string_value);
+ local_vector.push_back(item.GetString());
}
string_vector->swap(local_vector);
@@ -154,7 +153,9 @@ void PrefMember<bool>::UpdatePref(const bool& value) {
template <>
bool PrefMember<bool>::Internal::UpdateValueInternal(
const base::Value& value) const {
- return value.GetAsBoolean(&value_);
+ if (value.is_bool())
+ value_ = value.GetBool();
+ return value.is_bool();
}
template <>
@@ -165,7 +166,9 @@ void PrefMember<int>::UpdatePref(const int& value) {
template <>
bool PrefMember<int>::Internal::UpdateValueInternal(
const base::Value& value) const {
- return value.GetAsInteger(&value_);
+ if (value.is_int())
+ value_ = value.GetInt();
+ return value.is_int();
}
template <>
@@ -176,7 +179,9 @@ void PrefMember<double>::UpdatePref(const double& value) {
template <>
bool PrefMember<double>::Internal::UpdateValueInternal(const base::Value& value)
const {
- return value.GetAsDouble(&value_);
+ if (value.is_double() || value.is_int())
+ value_ = value.GetDouble();
+ return value.is_double() || value.is_int();
}
template <>
@@ -188,7 +193,9 @@ template <>
bool PrefMember<std::string>::Internal::UpdateValueInternal(
const base::Value& value)
const {
- return value.GetAsString(&value_);
+ if (value.is_string())
+ value_ = value.GetString();
+ return value.is_string();
}
template <>
@@ -200,7 +207,7 @@ template <>
bool PrefMember<base::FilePath>::Internal::UpdateValueInternal(
const base::Value& value)
const {
- base::Optional<base::FilePath> path = util::ValueToFilePath(value);
+ absl::optional<base::FilePath> path = util::ValueToFilePath(value);
if (!path)
return false;
value_ = *path;
@@ -211,7 +218,9 @@ template <>
void PrefMember<std::vector<std::string> >::UpdatePref(
const std::vector<std::string>& value) {
base::ListValue list_value;
- list_value.AppendStrings(value);
+ for (const std::string& val : value)
+ list_value.Append(val);
+
prefs()->Set(pref_name(), list_value);
}
diff --git a/chromium/components/prefs/pref_service.cc b/chromium/components/prefs/pref_service.cc
index e15c2d5f723..3f1474a47e1 100644
--- a/chromium/components/prefs/pref_service.cc
+++ b/chromium/components/prefs/pref_service.cc
@@ -23,6 +23,7 @@
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/util/values/values_util.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "components/prefs/default_pref_store.h"
#include "components/prefs/pref_notifier_impl.h"
@@ -196,7 +197,7 @@ base::FilePath PrefService::GetFilePath(const std::string& path) const {
const base::Value* value = GetPreferenceValueChecked(path);
if (!value)
return base::FilePath();
- base::Optional<base::FilePath> result = util::ValueToFilePath(*value);
+ absl::optional<base::FilePath> result = util::ValueToFilePath(*value);
DCHECK(result);
return *result;
}
@@ -492,7 +493,7 @@ void PrefService::SetInt64(const std::string& path, int64_t value) {
int64_t PrefService::GetInt64(const std::string& path) const {
const base::Value* value = GetPreferenceValueChecked(path);
- base::Optional<int64_t> integer = util::ValueToInt64(value);
+ absl::optional<int64_t> integer = util::ValueToInt64(value);
DCHECK(integer);
return integer.value_or(0);
}
@@ -519,7 +520,7 @@ void PrefService::SetTime(const std::string& path, base::Time value) {
base::Time PrefService::GetTime(const std::string& path) const {
const base::Value* value = GetPreferenceValueChecked(path);
- base::Optional<base::Time> time = util::ValueToTime(value);
+ absl::optional<base::Time> time = util::ValueToTime(value);
DCHECK(time);
return time.value_or(base::Time());
}
@@ -530,7 +531,7 @@ void PrefService::SetTimeDelta(const std::string& path, base::TimeDelta value) {
base::TimeDelta PrefService::GetTimeDelta(const std::string& path) const {
const base::Value* value = GetPreferenceValueChecked(path);
- base::Optional<base::TimeDelta> time_delta = util::ValueToTimeDelta(value);
+ absl::optional<base::TimeDelta> time_delta = util::ValueToTimeDelta(value);
DCHECK(time_delta);
return time_delta.value_or(base::TimeDelta());
}
@@ -559,22 +560,13 @@ base::Value* PrefService::GetMutableUserPref(const std::string& path,
return value;
}
- // TODO(crbug.com/859477): Remove once root cause has been found.
- if (value && value->type() != type) {
- DEBUG_ALIAS_FOR_CSTR(path_copy, path.c_str(), 1024);
- base::debug::DumpWithoutCrashing();
- }
-
// If no user preference of the correct type exists, clone default value.
const base::Value* default_value = nullptr;
pref_registry_->defaults()->GetValue(path, &default_value);
- // TODO(crbug.com/859477): Revert to DCHECK once root cause has been found.
- if (default_value->type() != type) {
- DEBUG_ALIAS_FOR_CSTR(path_copy, path.c_str(), 1024);
- base::debug::DumpWithoutCrashing();
- }
- user_pref_store_->SetValueSilently(path, default_value->CreateDeepCopy(),
- GetWriteFlags(pref));
+ DCHECK_EQ(default_value->type(), type);
+ user_pref_store_->SetValueSilently(
+ path, base::Value::ToUniquePtrValue(default_value->Clone()),
+ GetWriteFlags(pref));
user_pref_store_->GetMutableValue(path, &value);
return value;
}
diff --git a/chromium/components/prefs/pref_service_unittest.cc b/chromium/components/prefs/pref_service_unittest.cc
index 392cd6816c8..fd83ccf6955 100644
--- a/chromium/components/prefs/pref_service_unittest.cc
+++ b/chromium/components/prefs/pref_service_unittest.cc
@@ -158,9 +158,8 @@ TEST(PrefServiceTest, GetValueChangedType) {
const base::Value* value = pref->GetValue();
ASSERT_TRUE(value);
EXPECT_EQ(base::Value::Type::INTEGER, value->type());
- int actual_int_value = -1;
- EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
- EXPECT_EQ(kTestValue, actual_int_value);
+ ASSERT_TRUE(value->is_int());
+ EXPECT_EQ(kTestValue, value->GetInt());
}
TEST(PrefServiceTest, GetValueAndGetRecommendedValue) {
@@ -178,9 +177,8 @@ TEST(PrefServiceTest, GetValueAndGetRecommendedValue) {
const base::Value* value = pref->GetValue();
ASSERT_TRUE(value);
EXPECT_EQ(base::Value::Type::INTEGER, value->type());
- int actual_int_value = -1;
- EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
- EXPECT_EQ(kDefaultValue, actual_int_value);
+ ASSERT_TRUE(value->is_int());
+ EXPECT_EQ(kDefaultValue, value->GetInt());
// Check that GetRecommendedValue() returns no value.
value = pref->GetRecommendedValue();
@@ -193,9 +191,8 @@ TEST(PrefServiceTest, GetValueAndGetRecommendedValue) {
value = pref->GetValue();
ASSERT_TRUE(value);
EXPECT_EQ(base::Value::Type::INTEGER, value->type());
- actual_int_value = -1;
- EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
- EXPECT_EQ(kUserValue, actual_int_value);
+ ASSERT_TRUE(value->is_int());
+ EXPECT_EQ(kUserValue, value->GetInt());
// Check that GetRecommendedValue() returns no value.
value = pref->GetRecommendedValue();
@@ -209,17 +206,15 @@ TEST(PrefServiceTest, GetValueAndGetRecommendedValue) {
value = pref->GetValue();
ASSERT_TRUE(value);
EXPECT_EQ(base::Value::Type::INTEGER, value->type());
- actual_int_value = -1;
- EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
- EXPECT_EQ(kUserValue, actual_int_value);
+ ASSERT_TRUE(value->is_int());
+ EXPECT_EQ(kUserValue, value->GetInt());
// Check that GetRecommendedValue() returns the recommended value.
value = pref->GetRecommendedValue();
ASSERT_TRUE(value);
EXPECT_EQ(base::Value::Type::INTEGER, value->type());
- actual_int_value = -1;
- EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
- EXPECT_EQ(kRecommendedValue, actual_int_value);
+ ASSERT_TRUE(value->is_int());
+ EXPECT_EQ(kRecommendedValue, value->GetInt());
// Remove the user-set value.
prefs.RemoveUserPref(kPrefName);
@@ -228,17 +223,15 @@ TEST(PrefServiceTest, GetValueAndGetRecommendedValue) {
value = pref->GetValue();
ASSERT_TRUE(value);
EXPECT_EQ(base::Value::Type::INTEGER, value->type());
- actual_int_value = -1;
- EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
- EXPECT_EQ(kRecommendedValue, actual_int_value);
+ ASSERT_TRUE(value->is_int());
+ EXPECT_EQ(kRecommendedValue, value->GetInt());
// Check that GetRecommendedValue() returns the recommended value.
value = pref->GetRecommendedValue();
ASSERT_TRUE(value);
EXPECT_EQ(base::Value::Type::INTEGER, value->type());
- actual_int_value = -1;
- EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
- EXPECT_EQ(kRecommendedValue, actual_int_value);
+ ASSERT_TRUE(value->is_int());
+ EXPECT_EQ(kRecommendedValue, value->GetInt());
}
TEST(PrefServiceTest, SetTimeValue_RegularTime) {
diff --git a/chromium/components/prefs/pref_value_map.cc b/chromium/components/prefs/pref_value_map.cc
index 559f827bcec..78adef8fc75 100644
--- a/chromium/components/prefs/pref_value_map.cc
+++ b/chromium/components/prefs/pref_value_map.cc
@@ -89,7 +89,11 @@ bool PrefValueMap::empty() const {
bool PrefValueMap::GetBoolean(const std::string& key, bool* value) const {
const base::Value* stored_value = nullptr;
- return GetValue(key, &stored_value) && stored_value->GetAsBoolean(value);
+ if (GetValue(key, &stored_value) && stored_value->is_bool()) {
+ *value = stored_value->GetBool();
+ return true;
+ }
+ return false;
}
void PrefValueMap::SetBoolean(const std::string& key, bool value) {
@@ -98,7 +102,11 @@ void PrefValueMap::SetBoolean(const std::string& key, bool value) {
bool PrefValueMap::GetString(const std::string& key, std::string* value) const {
const base::Value* stored_value = nullptr;
- return GetValue(key, &stored_value) && stored_value->GetAsString(value);
+ if (GetValue(key, &stored_value) && stored_value->is_string()) {
+ *value = stored_value->GetString();
+ return true;
+ }
+ return false;
}
void PrefValueMap::SetString(const std::string& key, const std::string& value) {
@@ -107,7 +115,11 @@ void PrefValueMap::SetString(const std::string& key, const std::string& value) {
bool PrefValueMap::GetInteger(const std::string& key, int* value) const {
const base::Value* stored_value = nullptr;
- return GetValue(key, &stored_value) && stored_value->GetAsInteger(value);
+ if (GetValue(key, &stored_value) && stored_value->is_int()) {
+ *value = stored_value->GetInt();
+ return true;
+ }
+ return false;
}
void PrefValueMap::SetInteger(const std::string& key, const int value) {
@@ -137,7 +149,7 @@ void PrefValueMap::GetDifferingKeys(
while (this_pref != this_prefs.end() && other_pref != other_prefs.end()) {
const int diff = this_pref->first.compare(other_pref->first);
if (diff == 0) {
- if (!this_pref->second->Equals(other_pref->second))
+ if (*this_pref->second != *other_pref->second)
differing_keys->push_back(this_pref->first);
++this_pref;
++other_pref;
@@ -160,7 +172,8 @@ void PrefValueMap::GetDifferingKeys(
std::unique_ptr<base::DictionaryValue> PrefValueMap::AsDictionaryValue() const {
auto dictionary = std::make_unique<base::DictionaryValue>();
for (const auto& value : prefs_)
- dictionary->Set(value.first, value.second.CreateDeepCopy());
+ dictionary->Set(value.first,
+ base::Value::ToUniquePtrValue(value.second.Clone()));
return dictionary;
}
diff --git a/chromium/components/prefs/prefs_export.h b/chromium/components/prefs/prefs_export.h
index e047ad99ab2..b5c8366b955 100644
--- a/chromium/components/prefs/prefs_export.h
+++ b/chromium/components/prefs/prefs_export.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_PREFS_COMPONENTS_PREFS_EXPORT_H_
-#define COMPONENTS_PREFS_COMPONENTS_PREFS_EXPORT_H_
+#ifndef COMPONENTS_PREFS_PREFS_EXPORT_H_
+#define COMPONENTS_PREFS_PREFS_EXPORT_H_
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
@@ -26,4 +26,4 @@
#define COMPONENTS_PREFS_EXPORT
#endif
-#endif // COMPONENTS_PREFS_COMPONENTS_PREFS_EXPORT_H_
+#endif // COMPONENTS_PREFS_PREFS_EXPORT_H_
diff --git a/chromium/components/prefs/scoped_user_pref_update_unittest.cc b/chromium/components/prefs/scoped_user_pref_update_unittest.cc
index fa1dc71ae45..431fad1b0f1 100644
--- a/chromium/components/prefs/scoped_user_pref_update_unittest.cc
+++ b/chromium/components/prefs/scoped_user_pref_update_unittest.cc
@@ -102,9 +102,9 @@ TEST_F(ScopedUserPrefUpdateTest, UpdatingDictionaryPrefWithDefaults) {
std::string pref_name = "mypref";
prefs_.registry()->RegisterDictionaryPref(pref_name, std::move(defaults));
- EXPECT_EQ(2u, prefs_.GetDictionary(pref_name)->size());
+ EXPECT_EQ(2u, prefs_.GetDictionary(pref_name)->DictSize());
DictionaryPrefUpdate update(&prefs_, pref_name);
update->SetKey("thirdkey", base::Value("value"));
- EXPECT_EQ(3u, prefs_.GetDictionary(pref_name)->size());
+ EXPECT_EQ(3u, prefs_.GetDictionary(pref_name)->DictSize());
}
diff --git a/chromium/components/prefs/segregated_pref_store.cc b/chromium/components/prefs/segregated_pref_store.cc
new file mode 100644
index 00000000000..65f2c8052db
--- /dev/null
+++ b/chromium/components/prefs/segregated_pref_store.cc
@@ -0,0 +1,224 @@
+// 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/prefs/segregated_pref_store.h"
+
+#include <utility>
+
+#include "base/barrier_closure.h"
+#include "base/check_op.h"
+#include "base/containers/contains.h"
+#include "base/notreached.h"
+#include "base/values.h"
+
+SegregatedPrefStore::AggregatingObserver::AggregatingObserver(
+ SegregatedPrefStore* outer)
+ : outer_(outer),
+ failed_sub_initializations_(0),
+ successful_sub_initializations_(0) {}
+
+void SegregatedPrefStore::AggregatingObserver::OnPrefValueChanged(
+ const std::string& key) {
+ // There is no need to tell clients about changes if they have not yet been
+ // told about initialization.
+ if (failed_sub_initializations_ + successful_sub_initializations_ < 2)
+ return;
+
+ for (auto& observer : outer_->observers_)
+ observer.OnPrefValueChanged(key);
+}
+
+void SegregatedPrefStore::AggregatingObserver::OnInitializationCompleted(
+ bool succeeded) {
+ if (succeeded)
+ ++successful_sub_initializations_;
+ else
+ ++failed_sub_initializations_;
+
+ DCHECK_LE(failed_sub_initializations_ + successful_sub_initializations_, 2);
+
+ if (failed_sub_initializations_ + successful_sub_initializations_ == 2) {
+ if (successful_sub_initializations_ == 2 && outer_->read_error_delegate_) {
+ PersistentPrefStore::PrefReadError read_error = outer_->GetReadError();
+ if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE)
+ outer_->read_error_delegate_->OnError(read_error);
+ }
+
+ for (auto& observer : outer_->observers_)
+ observer.OnInitializationCompleted(successful_sub_initializations_ == 2);
+ }
+}
+
+SegregatedPrefStore::SegregatedPrefStore(
+ scoped_refptr<PersistentPrefStore> default_pref_store,
+ scoped_refptr<PersistentPrefStore> selected_pref_store,
+ std::set<std::string> selected_pref_names)
+ : default_pref_store_(std::move(default_pref_store)),
+ selected_pref_store_(std::move(selected_pref_store)),
+ selected_preference_names_(std::move(selected_pref_names)),
+ aggregating_observer_(this) {
+ default_pref_store_->AddObserver(&aggregating_observer_);
+ selected_pref_store_->AddObserver(&aggregating_observer_);
+}
+
+void SegregatedPrefStore::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void SegregatedPrefStore::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+bool SegregatedPrefStore::HasObservers() const {
+ return !observers_.empty();
+}
+
+bool SegregatedPrefStore::IsInitializationComplete() const {
+ return default_pref_store_->IsInitializationComplete() &&
+ selected_pref_store_->IsInitializationComplete();
+}
+
+bool SegregatedPrefStore::GetValue(const std::string& key,
+ const base::Value** result) const {
+ return StoreForKey(key)->GetValue(key, result);
+}
+
+std::unique_ptr<base::DictionaryValue> SegregatedPrefStore::GetValues() const {
+ auto values = default_pref_store_->GetValues();
+ auto selected_pref_store_values = selected_pref_store_->GetValues();
+ for (const auto& key : selected_preference_names_) {
+ const base::Value* value = nullptr;
+ if (selected_pref_store_values->Get(key, &value)) {
+ values->Set(key, base::Value::ToUniquePtrValue(value->Clone()));
+ } else {
+ values->Remove(key, nullptr);
+ }
+ }
+ return values;
+}
+
+void SegregatedPrefStore::SetValue(const std::string& key,
+ std::unique_ptr<base::Value> value,
+ uint32_t flags) {
+ StoreForKey(key)->SetValue(key, std::move(value), flags);
+}
+
+void SegregatedPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
+ StoreForKey(key)->RemoveValue(key, flags);
+}
+
+void SegregatedPrefStore::RemoveValuesByPrefixSilently(
+ const std::string& prefix) {
+ // Since we can't guarantee to have all the prefs in one the pref stores, we
+ // have to push the removal command down to both of them.
+ default_pref_store_->RemoveValuesByPrefixSilently(prefix);
+ selected_pref_store_->RemoveValuesByPrefixSilently(prefix);
+}
+
+bool SegregatedPrefStore::GetMutableValue(const std::string& key,
+ base::Value** result) {
+ return StoreForKey(key)->GetMutableValue(key, result);
+}
+
+void SegregatedPrefStore::ReportValueChanged(const std::string& key,
+ uint32_t flags) {
+ StoreForKey(key)->ReportValueChanged(key, flags);
+}
+
+void SegregatedPrefStore::SetValueSilently(const std::string& key,
+ std::unique_ptr<base::Value> value,
+ uint32_t flags) {
+ StoreForKey(key)->SetValueSilently(key, std::move(value), flags);
+}
+
+bool SegregatedPrefStore::ReadOnly() const {
+ return selected_pref_store_->ReadOnly() || default_pref_store_->ReadOnly();
+}
+
+PersistentPrefStore::PrefReadError SegregatedPrefStore::GetReadError() const {
+ PersistentPrefStore::PrefReadError read_error =
+ default_pref_store_->GetReadError();
+ if (read_error == PersistentPrefStore::PREF_READ_ERROR_NONE) {
+ read_error = selected_pref_store_->GetReadError();
+ // Ignore NO_FILE from selected_pref_store_.
+ if (read_error == PersistentPrefStore::PREF_READ_ERROR_NO_FILE)
+ read_error = PersistentPrefStore::PREF_READ_ERROR_NONE;
+ }
+ return read_error;
+}
+
+PersistentPrefStore::PrefReadError SegregatedPrefStore::ReadPrefs() {
+ // Note: Both of these stores own PrefFilters which makes ReadPrefs
+ // asynchronous. This is okay in this case as only the first call will be
+ // truly asynchronous, the second call will then unblock the migration in
+ // TrackedPreferencesMigrator and complete synchronously.
+ default_pref_store_->ReadPrefs();
+ PersistentPrefStore::PrefReadError selected_store_read_error =
+ selected_pref_store_->ReadPrefs();
+ DCHECK_NE(PersistentPrefStore::PREF_READ_ERROR_ASYNCHRONOUS_TASK_INCOMPLETE,
+ selected_store_read_error);
+
+ return GetReadError();
+}
+
+void SegregatedPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
+ read_error_delegate_.reset(error_delegate);
+ default_pref_store_->ReadPrefsAsync(NULL);
+ selected_pref_store_->ReadPrefsAsync(NULL);
+}
+
+void SegregatedPrefStore::CommitPendingWrite(
+ base::OnceClosure reply_callback,
+ base::OnceClosure synchronous_done_callback) {
+ // A BarrierClosure will run its callback wherever the last instance of the
+ // returned wrapper is invoked. As such it is guaranteed to respect the reply
+ // vs synchronous semantics assuming |default_pref_store_| and
+ // |selected_pref_store_| honor it.
+
+ base::RepeatingClosure reply_callback_wrapper =
+ reply_callback ? base::BarrierClosure(2, std::move(reply_callback))
+ : base::RepeatingClosure();
+
+ base::RepeatingClosure synchronous_callback_wrapper =
+ synchronous_done_callback
+ ? base::BarrierClosure(2, std::move(synchronous_done_callback))
+ : base::RepeatingClosure();
+
+ default_pref_store_->CommitPendingWrite(reply_callback_wrapper,
+ synchronous_callback_wrapper);
+ selected_pref_store_->CommitPendingWrite(reply_callback_wrapper,
+ synchronous_callback_wrapper);
+}
+
+void SegregatedPrefStore::SchedulePendingLossyWrites() {
+ default_pref_store_->SchedulePendingLossyWrites();
+ selected_pref_store_->SchedulePendingLossyWrites();
+}
+
+void SegregatedPrefStore::ClearMutableValues() {
+ NOTIMPLEMENTED();
+}
+
+void SegregatedPrefStore::OnStoreDeletionFromDisk() {
+ default_pref_store_->OnStoreDeletionFromDisk();
+ selected_pref_store_->OnStoreDeletionFromDisk();
+}
+
+SegregatedPrefStore::~SegregatedPrefStore() {
+ default_pref_store_->RemoveObserver(&aggregating_observer_);
+ selected_pref_store_->RemoveObserver(&aggregating_observer_);
+}
+
+PersistentPrefStore* SegregatedPrefStore::StoreForKey(const std::string& key) {
+ return (base::Contains(selected_preference_names_, key) ? selected_pref_store_
+ : default_pref_store_)
+ .get();
+}
+
+const PersistentPrefStore* SegregatedPrefStore::StoreForKey(
+ const std::string& key) const {
+ return (base::Contains(selected_preference_names_, key) ? selected_pref_store_
+ : default_pref_store_)
+ .get();
+}
diff --git a/chromium/components/prefs/segregated_pref_store.h b/chromium/components/prefs/segregated_pref_store.h
new file mode 100644
index 00000000000..9d9b6811c1f
--- /dev/null
+++ b/chromium/components/prefs/segregated_pref_store.h
@@ -0,0 +1,118 @@
+// 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_PREFS_SEGREGATED_PREF_STORE_H_
+#define COMPONENTS_PREFS_SEGREGATED_PREF_STORE_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <set>
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
+#include "components/prefs/persistent_pref_store.h"
+#include "components/prefs/prefs_export.h"
+
+// Provides a unified PersistentPrefStore implementation that splits its storage
+// and retrieval between two underlying PersistentPrefStore instances: a set of
+// preference names is used to partition the preferences.
+//
+// Combines properties of the two stores as follows:
+// * The unified read error will be:
+// Selected Store Error
+// Default Store Error | NO_ERROR | NO_FILE | other selected |
+// NO_ERROR | NO_ERROR | NO_ERROR | other selected |
+// NO_FILE | NO_FILE | NO_FILE | NO_FILE |
+// other default | other default | other default | other default |
+// * The unified initialization success, initialization completion, and
+// read-only state are the boolean OR of the underlying stores' properties.
+class COMPONENTS_PREFS_EXPORT SegregatedPrefStore : public PersistentPrefStore {
+ public:
+ // Creates an instance that delegates to |selected_pref_store| for the
+ // preferences named in |selected_pref_names| and to |default_pref_store|
+ // for all others. If an unselected preference is present in
+ // |selected_pref_store| (i.e. because it was previously selected) it will
+ // be migrated back to |default_pref_store| upon access via a non-const
+ // method.
+ SegregatedPrefStore(scoped_refptr<PersistentPrefStore> default_pref_store,
+ scoped_refptr<PersistentPrefStore> selected_pref_store,
+ std::set<std::string> selected_pref_names);
+
+ // PrefStore implementation
+ void AddObserver(Observer* observer) override;
+ void RemoveObserver(Observer* observer) override;
+ bool HasObservers() const override;
+ bool IsInitializationComplete() const override;
+ bool GetValue(const std::string& key,
+ const base::Value** result) const override;
+ std::unique_ptr<base::DictionaryValue> GetValues() const override;
+
+ // WriteablePrefStore implementation
+ void SetValue(const std::string& key,
+ std::unique_ptr<base::Value> value,
+ uint32_t flags) override;
+ void RemoveValue(const std::string& key, uint32_t flags) override;
+ void RemoveValuesByPrefixSilently(const std::string& prefix) override;
+
+ // PersistentPrefStore implementation
+ bool GetMutableValue(const std::string& key, base::Value** result) override;
+ void ReportValueChanged(const std::string& key, uint32_t flags) override;
+ void SetValueSilently(const std::string& key,
+ std::unique_ptr<base::Value> value,
+ uint32_t flags) override;
+ bool ReadOnly() const override;
+ PrefReadError GetReadError() const override;
+ PrefReadError ReadPrefs() override;
+ void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override;
+ void CommitPendingWrite(
+ base::OnceClosure reply_callback = base::OnceClosure(),
+ base::OnceClosure synchronous_done_callback =
+ base::OnceClosure()) override;
+ void SchedulePendingLossyWrites() override;
+ void ClearMutableValues() override;
+ void OnStoreDeletionFromDisk() override;
+
+ protected:
+ ~SegregatedPrefStore() override;
+
+ private:
+ // Aggregates events from the underlying stores and synthesizes external
+ // events via |on_initialization|, |read_error_delegate_|, and |observers_|.
+ class AggregatingObserver : public PrefStore::Observer {
+ public:
+ explicit AggregatingObserver(SegregatedPrefStore* outer);
+
+ // PrefStore::Observer implementation
+ void OnPrefValueChanged(const std::string& key) override;
+ void OnInitializationCompleted(bool succeeded) override;
+
+ private:
+ SegregatedPrefStore* outer_;
+ int failed_sub_initializations_;
+ int successful_sub_initializations_;
+
+ DISALLOW_COPY_AND_ASSIGN(AggregatingObserver);
+ };
+
+ // Returns |selected_pref_store| if |key| is selected and |default_pref_store|
+ // otherwise.
+ PersistentPrefStore* StoreForKey(const std::string& key);
+ const PersistentPrefStore* StoreForKey(const std::string& key) const;
+
+ const scoped_refptr<PersistentPrefStore> default_pref_store_;
+ const scoped_refptr<PersistentPrefStore> selected_pref_store_;
+ const std::set<std::string> selected_preference_names_;
+
+ std::unique_ptr<PersistentPrefStore::ReadErrorDelegate> read_error_delegate_;
+ base::ObserverList<PrefStore::Observer, true>::Unchecked observers_;
+ AggregatingObserver aggregating_observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(SegregatedPrefStore);
+};
+
+#endif // COMPONENTS_PREFS_SEGREGATED_PREF_STORE_H_
diff --git a/chromium/components/prefs/segregated_pref_store_unittest.cc b/chromium/components/prefs/segregated_pref_store_unittest.cc
new file mode 100644
index 00000000000..4e90ea8c8b1
--- /dev/null
+++ b/chromium/components/prefs/segregated_pref_store_unittest.cc
@@ -0,0 +1,380 @@
+// 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/prefs/segregated_pref_store.h"
+
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/task_environment.h"
+#include "base/values.h"
+#include "components/prefs/persistent_pref_store.h"
+#include "components/prefs/pref_store_observer_mock.h"
+#include "components/prefs/testing_pref_store.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kSelectedPref[] = "selected_pref";
+const char kUnselectedPref[] = "unselected_pref";
+const char kSharedPref[] = "shared_pref";
+
+const char kValue1[] = "value1";
+const char kValue2[] = "value2";
+
+class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
+ public:
+ struct Data {
+ Data(bool invoked_in, PersistentPrefStore::PrefReadError read_error_in)
+ : invoked(invoked_in), read_error(read_error_in) {}
+
+ bool invoked;
+ PersistentPrefStore::PrefReadError read_error;
+ };
+
+ explicit MockReadErrorDelegate(Data* data) : data_(data) {
+ DCHECK(data_);
+ EXPECT_FALSE(data_->invoked);
+ }
+
+ // PersistentPrefStore::ReadErrorDelegate implementation
+ void OnError(PersistentPrefStore::PrefReadError read_error) override {
+ EXPECT_FALSE(data_->invoked);
+ data_->invoked = true;
+ data_->read_error = read_error;
+ }
+
+ private:
+ Data* data_;
+};
+
+enum class CommitPendingWriteMode {
+ // Basic mode.
+ WITHOUT_CALLBACK,
+ // With reply callback.
+ WITH_CALLBACK,
+ // With synchronous notify callback (synchronous after the write -- shouldn't
+ // require pumping messages to observe).
+ WITH_SYNCHRONOUS_CALLBACK,
+};
+
+class SegregatedPrefStoreTest
+ : public testing::TestWithParam<CommitPendingWriteMode> {
+ public:
+ SegregatedPrefStoreTest()
+ : read_error_delegate_data_(false,
+ PersistentPrefStore::PREF_READ_ERROR_NONE),
+ read_error_delegate_(
+ new MockReadErrorDelegate(&read_error_delegate_data_)) {}
+
+ void SetUp() override {
+ selected_store_ = new TestingPrefStore;
+ default_store_ = new TestingPrefStore;
+
+ std::set<std::string> selected_pref_names;
+ selected_pref_names.insert(kSelectedPref);
+ selected_pref_names.insert(kSharedPref);
+
+ segregated_store_ = new SegregatedPrefStore(default_store_, selected_store_,
+ selected_pref_names);
+
+ segregated_store_->AddObserver(&observer_);
+ }
+
+ void TearDown() override { segregated_store_->RemoveObserver(&observer_); }
+
+ protected:
+ std::unique_ptr<PersistentPrefStore::ReadErrorDelegate>
+ GetReadErrorDelegate() {
+ EXPECT_TRUE(read_error_delegate_);
+ return std::move(read_error_delegate_);
+ }
+
+ base::test::TaskEnvironment task_environment_;
+
+ PrefStoreObserverMock observer_;
+
+ scoped_refptr<TestingPrefStore> default_store_;
+ scoped_refptr<TestingPrefStore> selected_store_;
+ scoped_refptr<SegregatedPrefStore> segregated_store_;
+
+ MockReadErrorDelegate::Data read_error_delegate_data_;
+
+ private:
+ std::unique_ptr<MockReadErrorDelegate> read_error_delegate_;
+};
+
+} // namespace
+
+TEST_P(SegregatedPrefStoreTest, StoreValues) {
+ ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+ segregated_store_->ReadPrefs());
+
+ // Properly stores new values.
+ segregated_store_->SetValue(kSelectedPref,
+ std::make_unique<base::Value>(kValue1),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ segregated_store_->SetValue(kUnselectedPref,
+ std::make_unique<base::Value>(kValue2),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+
+ ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
+ ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
+ ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
+ ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
+
+ ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
+ ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
+
+ ASSERT_FALSE(selected_store_->committed());
+ ASSERT_FALSE(default_store_->committed());
+
+ switch (GetParam()) {
+ case CommitPendingWriteMode::WITHOUT_CALLBACK: {
+ segregated_store_->CommitPendingWrite();
+ base::RunLoop().RunUntilIdle();
+ break;
+ }
+
+ case CommitPendingWriteMode::WITH_CALLBACK: {
+ base::RunLoop run_loop;
+ segregated_store_->CommitPendingWrite(run_loop.QuitClosure());
+ run_loop.Run();
+ break;
+ }
+
+ case CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK: {
+ base::WaitableEvent written;
+ segregated_store_->CommitPendingWrite(
+ base::OnceClosure(),
+ base::BindOnce(&base::WaitableEvent::Signal, Unretained(&written)));
+ written.Wait();
+ break;
+ }
+ }
+
+ ASSERT_TRUE(selected_store_->committed());
+ ASSERT_TRUE(default_store_->committed());
+}
+
+TEST_F(SegregatedPrefStoreTest, ReadValues) {
+ selected_store_->SetValue(kSelectedPref,
+ std::make_unique<base::Value>(kValue1),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ default_store_->SetValue(kUnselectedPref,
+ std::make_unique<base::Value>(kValue2),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+
+ // Works properly with values that are already there.
+ ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+ segregated_store_->ReadPrefs());
+ ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+ segregated_store_->GetReadError());
+
+ ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
+ ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
+ ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
+ ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
+
+ ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
+ ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
+}
+
+TEST_F(SegregatedPrefStoreTest, RemoveValuesByPrefix) {
+ const std::string subpref_name1 = kSelectedPref;
+ const std::string subpref_name2 = std::string(kSelectedPref) + "b";
+ const std::string other_name = kUnselectedPref;
+ const std::string prefix = kSelectedPref;
+
+ selected_store_->SetValue(subpref_name1,
+ std::make_unique<base::Value>(kValue1),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ default_store_->SetValue(subpref_name2,
+ std::make_unique<base::Value>(kValue2),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ default_store_->SetValue(other_name, std::make_unique<base::Value>(kValue2),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+
+ ASSERT_TRUE(selected_store_->GetValue(subpref_name1, nullptr));
+ ASSERT_TRUE(default_store_->GetValue(subpref_name2, nullptr));
+ ASSERT_TRUE(default_store_->GetValue(other_name, nullptr));
+
+ segregated_store_->RemoveValuesByPrefixSilently(kSelectedPref);
+
+ ASSERT_FALSE(selected_store_->GetValue(subpref_name1, nullptr));
+ ASSERT_FALSE(default_store_->GetValue(subpref_name2, nullptr));
+ ASSERT_TRUE(default_store_->GetValue(other_name, nullptr));
+}
+
+TEST_F(SegregatedPrefStoreTest, Observer) {
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+ segregated_store_->ReadPrefs());
+ EXPECT_TRUE(observer_.initialized);
+ EXPECT_TRUE(observer_.initialization_success);
+ EXPECT_TRUE(observer_.changed_keys.empty());
+ segregated_store_->SetValue(kSelectedPref,
+ std::make_unique<base::Value>(kValue1),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ observer_.VerifyAndResetChangedKey(kSelectedPref);
+ segregated_store_->SetValue(kUnselectedPref,
+ std::make_unique<base::Value>(kValue2),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ observer_.VerifyAndResetChangedKey(kUnselectedPref);
+}
+
+TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileError) {
+ // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
+ // to PREF_READ_ERROR_NONE.
+ selected_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+ segregated_store_->ReadPrefs());
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+ segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, SelectedPrefReadError) {
+ selected_store_->set_read_error(
+ PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
+ segregated_store_->ReadPrefs());
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
+ segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, SelectedPrefReadNoFileErrorAsync) {
+ // PREF_READ_ERROR_NO_FILE for the selected prefs file is silently converted
+ // to PREF_READ_ERROR_NONE.
+ selected_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
+
+ default_store_->SetBlockAsyncRead(true);
+
+ EXPECT_FALSE(read_error_delegate_data_.invoked);
+
+ segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
+
+ EXPECT_FALSE(read_error_delegate_data_.invoked);
+
+ default_store_->SetBlockAsyncRead(false);
+
+ // ReadErrorDelegate is not invoked for ERROR_NONE.
+ EXPECT_FALSE(read_error_delegate_data_.invoked);
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+ segregated_store_->GetReadError());
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+ segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadNoFileError) {
+ default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+ segregated_store_->ReadPrefs());
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+ segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadError) {
+ default_store_->set_read_error(
+ PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
+ segregated_store_->ReadPrefs());
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED,
+ segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, BothPrefReadError) {
+ default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
+ selected_store_->set_read_error(
+ PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+ segregated_store_->ReadPrefs());
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+ segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, BothPrefReadErrorAsync) {
+ default_store_->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
+ selected_store_->set_read_error(
+ PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
+
+ selected_store_->SetBlockAsyncRead(true);
+
+ EXPECT_FALSE(read_error_delegate_data_.invoked);
+
+ segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
+
+ EXPECT_FALSE(read_error_delegate_data_.invoked);
+
+ selected_store_->SetBlockAsyncRead(false);
+
+ EXPECT_TRUE(read_error_delegate_data_.invoked);
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+ segregated_store_->GetReadError());
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+ segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, IsInitializationComplete) {
+ EXPECT_FALSE(segregated_store_->IsInitializationComplete());
+ segregated_store_->ReadPrefs();
+ EXPECT_TRUE(segregated_store_->IsInitializationComplete());
+}
+
+TEST_F(SegregatedPrefStoreTest, IsInitializationCompleteAsync) {
+ selected_store_->SetBlockAsyncRead(true);
+ default_store_->SetBlockAsyncRead(true);
+ EXPECT_FALSE(segregated_store_->IsInitializationComplete());
+ segregated_store_->ReadPrefsAsync(NULL);
+ EXPECT_FALSE(segregated_store_->IsInitializationComplete());
+ selected_store_->SetBlockAsyncRead(false);
+ EXPECT_FALSE(segregated_store_->IsInitializationComplete());
+ default_store_->SetBlockAsyncRead(false);
+ EXPECT_TRUE(segregated_store_->IsInitializationComplete());
+}
+
+TEST_F(SegregatedPrefStoreTest, GetValues) {
+ // To check merge behavior, create selected and default stores so each has a
+ // key the other doesn't have and they have one key in common.
+ selected_store_->SetValue(kSelectedPref,
+ std::make_unique<base::Value>(kValue1),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ default_store_->SetValue(kUnselectedPref,
+ std::make_unique<base::Value>(kValue2),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ selected_store_->SetValue(kSharedPref, std::make_unique<base::Value>(kValue1),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+
+ auto values = segregated_store_->GetValues();
+ const base::Value* value = nullptr;
+ // Check that a selected preference is returned.
+ ASSERT_TRUE(values->Get(kSelectedPref, &value));
+ EXPECT_TRUE(base::Value(kValue1).Equals(value));
+
+ // Check that a a default preference is returned.
+ ASSERT_TRUE(values->Get(kUnselectedPref, &value));
+ EXPECT_TRUE(base::Value(kValue2).Equals(value));
+
+ // Check that the selected preference is preferred.
+ ASSERT_TRUE(values->Get(kSharedPref, &value));
+ EXPECT_TRUE(base::Value(kValue1).Equals(value));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ WithoutCallback,
+ SegregatedPrefStoreTest,
+ ::testing::Values(CommitPendingWriteMode::WITHOUT_CALLBACK));
+INSTANTIATE_TEST_SUITE_P(
+ WithCallback,
+ SegregatedPrefStoreTest,
+ ::testing::Values(CommitPendingWriteMode::WITH_CALLBACK));
+INSTANTIATE_TEST_SUITE_P(
+ WithSynchronousCallback,
+ SegregatedPrefStoreTest,
+ ::testing::Values(CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK));
diff --git a/chromium/components/prefs/testing_pref_store.cc b/chromium/components/prefs/testing_pref_store.cc
index f81946d8ae3..5d3d1ec0b5c 100644
--- a/chromium/components/prefs/testing_pref_store.cc
+++ b/chromium/components/prefs/testing_pref_store.cc
@@ -160,7 +160,11 @@ bool TestingPrefStore::GetString(const std::string& key,
if (!prefs_.GetValue(key, &stored_value) || !stored_value)
return false;
- return stored_value->GetAsString(value);
+ if (value && stored_value->is_string()) {
+ *value = stored_value->GetString();
+ return true;
+ }
+ return stored_value->is_string();
}
bool TestingPrefStore::GetInteger(const std::string& key, int* value) const {
@@ -168,7 +172,11 @@ bool TestingPrefStore::GetInteger(const std::string& key, int* value) const {
if (!prefs_.GetValue(key, &stored_value) || !stored_value)
return false;
- return stored_value->GetAsInteger(value);
+ if (value && stored_value->is_int()) {
+ *value = stored_value->GetInt();
+ return true;
+ }
+ return stored_value->is_int();
}
bool TestingPrefStore::GetBoolean(const std::string& key, bool* value) const {
@@ -176,7 +184,11 @@ bool TestingPrefStore::GetBoolean(const std::string& key, bool* value) const {
if (!prefs_.GetValue(key, &stored_value) || !stored_value)
return false;
- return stored_value->GetAsBoolean(value);
+ if (value && stored_value->is_bool()) {
+ *value = stored_value->GetBool();
+ return true;
+ }
+ return stored_value->is_bool();
}
void TestingPrefStore::SetBlockAsyncRead(bool block_async_read) {
diff --git a/chromium/components/printing/browser/BUILD.gn b/chromium/components/printing/browser/BUILD.gn
index c8518f3ea3e..8ec335074c1 100644
--- a/chromium/components/printing/browser/BUILD.gn
+++ b/chromium/components/printing/browser/BUILD.gn
@@ -4,6 +4,8 @@
static_library("browser") {
sources = [
+ "prefs_util.cc",
+ "prefs_util.h",
"print_composite_client.cc",
"print_composite_client.h",
"print_manager.cc",
@@ -20,6 +22,7 @@ static_library("browser") {
"//build:chromeos_buildflags",
"//components/crash/core/common",
"//components/discardable_memory/service",
+ "//components/prefs",
"//components/printing/common",
"//components/printing/common:mojo_interfaces",
"//components/services/print_compositor/public/cpp",
diff --git a/chromium/components/printing/browser/DEPS b/chromium/components/printing/browser/DEPS
index 1b04a6a4406..f1c82e269fb 100644
--- a/chromium/components/printing/browser/DEPS
+++ b/chromium/components/printing/browser/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+components/crash/core/common",
"+components/discardable_memory/service",
+ "+components/prefs",
"+components/services/print_compositor/public",
"+components/site_isolation",
"+components/strings/grit",
diff --git a/chromium/components/printing/browser/DIR_METADATA b/chromium/components/printing/browser/DIR_METADATA
deleted file mode 100644
index c6bf1f00c00..00000000000
--- a/chromium/components/printing/browser/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Internals>Printing"
-}
diff --git a/chromium/components/printing/browser/prefs_util.cc b/chromium/components/printing/browser/prefs_util.cc
new file mode 100644
index 00000000000..689e8adad3b
--- /dev/null
+++ b/chromium/components/printing/browser/prefs_util.cc
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/printing/browser/prefs_util.h"
+
+#include <string>
+
+#include "base/values.h"
+#include "components/prefs/pref_service.h"
+#include "printing/backend/print_backend_utils.h"
+#include "printing/backend/printing_restrictions.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace {
+
+constexpr char kPrintingPaperSizeDefault[] = "printing.paper_size_default";
+
+} // namespace
+
+namespace printing {
+
+absl::optional<gfx::Size> ParsePaperSizeDefault(const PrefService& prefs) {
+ if (!prefs.HasPrefPath(kPrintingPaperSizeDefault))
+ return absl::nullopt;
+
+ const base::Value* paper_size_value = prefs.Get(kPrintingPaperSizeDefault);
+ if (!paper_size_value || paper_size_value->DictEmpty())
+ return absl::nullopt;
+
+ const base::Value* custom_size =
+ paper_size_value->FindKey(kPaperSizeCustomSize);
+ if (custom_size) {
+ return gfx::Size(*custom_size->FindIntKey(kPaperSizeWidth),
+ *custom_size->FindIntKey(kPaperSizeHeight));
+ }
+
+ const std::string* name = paper_size_value->FindStringKey(kPaperSizeName);
+ DCHECK(name);
+ return ParsePaper(*name).size_um;
+}
+
+} // namespace printing
diff --git a/chromium/components/printing/browser/prefs_util.h b/chromium/components/printing/browser/prefs_util.h
new file mode 100644
index 00000000000..12d1f9bc78e
--- /dev/null
+++ b/chromium/components/printing/browser/prefs_util.h
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PRINTING_BROWSER_PREFS_UTIL_H_
+#define COMPONENTS_PRINTING_BROWSER_PREFS_UTIL_H_
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/geometry/size.h"
+
+class PrefService;
+
+namespace printing {
+
+// Parse the printing.paper_size_default preference.
+absl::optional<gfx::Size> ParsePaperSizeDefault(const PrefService& prefs);
+
+} // namespace printing
+
+#endif // COMPONENTS_PRINTING_BROWSER_PREFS_UTIL_H_
diff --git a/chromium/components/printing/browser/print_manager.cc b/chromium/components/printing/browser/print_manager.cc
index 8616a7d30ba..cface58d6fb 100644
--- a/chromium/components/printing/browser/print_manager.cc
+++ b/chromium/components/printing/browser/print_manager.cc
@@ -29,24 +29,6 @@ void PrintManager::DidGetPrintedPagesCount(int32_t cookie,
number_pages_ = number_pages;
}
-void PrintManager::DidGetDocumentCookie(int32_t cookie) {
- cookie_ = cookie;
-}
-
-#if BUILDFLAG(ENABLE_TAGGED_PDF)
-void PrintManager::SetAccessibilityTree(
- int32_t cookie,
- const ui::AXTreeUpdate& accessibility_tree) {}
-#endif
-
-void PrintManager::UpdatePrintSettings(int32_t cookie,
- base::Value job_settings,
- UpdatePrintSettingsCallback callback) {
- auto params = mojom::PrintPagesParams::New();
- params->params = mojom::PrintParams::New();
- std::move(callback).Run(std::move(params), false);
-}
-
void PrintManager::DidShowPrintDialog() {}
void PrintManager::DidPrintDocument(mojom::DidPrintDocumentParamsPtr params,
@@ -57,31 +39,16 @@ void PrintManager::DidPrintDocument(mojom::DidPrintDocumentParamsPtr params,
void PrintManager::ShowInvalidPrinterSettingsError() {}
void PrintManager::PrintingFailed(int32_t cookie) {
- if (cookie != cookie_) {
- NOTREACHED();
+ // Note: Not redundant with cookie checks in the same method in other parts of
+ // the class hierarchy.
+ if (!IsValidCookie(cookie))
return;
- }
+
#if defined(OS_ANDROID)
PdfWritingDone(0);
#endif
}
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
-void PrintManager::SetupScriptedPrintPreview(
- SetupScriptedPrintPreviewCallback callback) {
- std::move(callback).Run();
-}
-
-void PrintManager::ShowScriptedPrintPreview(bool source_is_modifiable) {}
-
-void PrintManager::RequestPrintPreview(
- mojom::RequestPrintPreviewParamsPtr params) {}
-
-void PrintManager::CheckForCancel(int32_t preview_ui_id,
- int32_t request_id,
- CheckForCancelCallback callback) {}
-#endif
-
bool PrintManager::IsPrintRenderFrameConnected(
content::RenderFrameHost* rfh) const {
auto it = print_render_frames_.find(rfh);
@@ -106,10 +73,18 @@ PrintManager::GetPrintRenderFrame(content::RenderFrameHost* rfh) {
return it->second;
}
+content::RenderFrameHost* PrintManager::GetCurrentTargetFrame() {
+ return print_manager_host_receivers_.GetCurrentTargetFrame();
+}
+
void PrintManager::PrintingRenderFrameDeleted() {
#if defined(OS_ANDROID)
PdfWritingDone(0);
#endif
}
+bool PrintManager::IsValidCookie(int cookie) const {
+ return cookie > 0 && cookie == cookie_;
+}
+
} // namespace printing
diff --git a/chromium/components/printing/browser/print_manager.h b/chromium/components/printing/browser/print_manager.h
index 8658f417cb6..7e2881e3212 100644
--- a/chromium/components/printing/browser/print_manager.h
+++ b/chromium/components/printing/browser/print_manager.h
@@ -16,11 +16,9 @@
#include "printing/buildflags/buildflags.h"
#if defined(OS_ANDROID)
-#include "base/callback.h"
-#endif
+#include <utility>
-#if BUILDFLAG(ENABLE_TAGGED_PDF)
-#include "ui/accessibility/ax_tree_update_forward.h"
+#include "base/callback.h"
#endif
namespace printing {
@@ -42,29 +40,11 @@ class PrintManager : public content::WebContentsObserver,
// printing::mojom::PrintManagerHost:
void DidGetPrintedPagesCount(int32_t cookie, uint32_t number_pages) override;
- void DidGetDocumentCookie(int32_t cookie) override;
void DidPrintDocument(mojom::DidPrintDocumentParamsPtr params,
DidPrintDocumentCallback callback) override;
-#if BUILDFLAG(ENABLE_TAGGED_PDF)
- void SetAccessibilityTree(
- int32_t cookie,
- const ui::AXTreeUpdate& accessibility_tree) override;
-#endif
- void UpdatePrintSettings(int32_t cookie,
- base::Value job_settings,
- UpdatePrintSettingsCallback callback) override;
void DidShowPrintDialog() override;
void ShowInvalidPrinterSettingsError() override;
void PrintingFailed(int32_t cookie) override;
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
- void SetupScriptedPrintPreview(
- SetupScriptedPrintPreviewCallback callback) override;
- void ShowScriptedPrintPreview(bool source_is_modifiable) override;
- void RequestPrintPreview(mojom::RequestPrintPreviewParamsPtr params) override;
- void CheckForCancel(int32_t preview_ui_id,
- int32_t request_id,
- CheckForCancelCallback callback) override;
-#endif
protected:
explicit PrintManager(content::WebContents* contents);
@@ -78,14 +58,34 @@ class PrintManager : public content::WebContentsObserver,
const mojo::AssociatedRemote<printing::mojom::PrintRenderFrame>&
GetPrintRenderFrame(content::RenderFrameHost* rfh);
+ // Returns the RenderFrameHost currently targeted by message dispatch.
+ content::RenderFrameHost* GetCurrentTargetFrame();
+
// Terminates or cancels the print job if one was pending.
void PrintingRenderFrameDeleted();
- // content::WebContentsObserver
+ bool IsValidCookie(int cookie) const;
+
+ // content::WebContentsObserver:
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
+ uint32_t number_pages() const { return number_pages_; }
+ int cookie() const { return cookie_; }
+ void set_cookie(int cookie) { cookie_ = cookie; }
+
+#if defined(OS_ANDROID)
+ PdfWritingDoneCallback pdf_writing_done_callback() const {
+ return pdf_writing_done_callback_;
+ }
+ void set_pdf_writing_done_callback(PdfWritingDoneCallback callback) {
+ pdf_writing_done_callback_ = std::move(callback);
+ }
+#endif
+
+ private:
uint32_t number_pages_ = 0; // Number of pages to print in the print job.
int cookie_ = 0; // The current document cookie.
+
// Holds WebContents associated mojo receivers.
content::WebContentsFrameReceiverSet<printing::mojom::PrintManagerHost>
print_manager_host_receivers_;
@@ -95,7 +95,6 @@ class PrintManager : public content::WebContentsObserver,
PdfWritingDoneCallback pdf_writing_done_callback_;
#endif
- private:
// Stores a PrintRenderFrame associated remote with the RenderFrameHost used
// to bind it. The PrintRenderFrame is used to transmit mojo interface method
// calls to the associated receiver.
diff --git a/chromium/components/printing/common/BUILD.gn b/chromium/components/printing/common/BUILD.gn
index d1fd46d1765..f3094ed398b 100644
--- a/chromium/components/printing/common/BUILD.gn
+++ b/chromium/components/printing/common/BUILD.gn
@@ -36,6 +36,7 @@ mojom("mojo_interfaces") {
enabled_features += [ "enable_print_preview" ]
}
if (enable_tagged_pdf) {
+ assert(enable_print_preview)
public_deps += [ "//ui/accessibility/mojom" ]
enabled_features += [ "enable_tagged_pdf" ]
}
diff --git a/chromium/components/printing/common/DIR_METADATA b/chromium/components/printing/common/DIR_METADATA
deleted file mode 100644
index c6bf1f00c00..00000000000
--- a/chromium/components/printing/common/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Internals>Printing"
-}
diff --git a/chromium/components/printing/common/cloud_print_cdd_conversion.cc b/chromium/components/printing/common/cloud_print_cdd_conversion.cc
index f5c17bbdebd..0b7a9bd95fb 100644
--- a/chromium/components/printing/common/cloud_print_cdd_conversion.cc
+++ b/chromium/components/printing/common/cloud_print_cdd_conversion.cc
@@ -38,7 +38,7 @@ printer::DuplexType ToCloudDuplexType(printing::mojom::DuplexMode mode) {
return printer::DuplexType::NO_DUPLEX;
}
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
printer::TypedValueVendorCapability::ValueType ToCloudValueType(
printing::AdvancedCapability::Type type) {
switch (type) {
@@ -55,7 +55,7 @@ printer::TypedValueVendorCapability::ValueType ToCloudValueType(
}
return printer::TypedValueVendorCapability::ValueType::STRING;
}
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif // defined(OS_CHROMEOS)
printer::Media ConvertPaperToMedia(
const printing::PrinterSemanticCapsAndDefaults::Paper& paper) {
@@ -134,7 +134,7 @@ printer::DpiCapability GetDpiCapabilities(
return dpi_capabilities;
}
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
printer::VendorCapabilities GetVendorCapabilities(
const printing::PrinterSemanticCapsAndDefaults& semantic_info) {
printer::VendorCapabilities vendor_capabilities;
@@ -164,7 +164,7 @@ printer::VendorCapabilities GetVendorCapabilities(
return vendor_capabilities;
}
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif // defined(OS_CHROMEOS)
} // namespace
@@ -231,7 +231,7 @@ base::Value PrinterSemanticCapsAndDefaultsToCdd(
orientation.AddOption(printer::OrientationType::AUTO_ORIENTATION);
orientation.SaveTo(&description);
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
printer::PinCapability pin;
pin.set_value(semantic_info.pin_supported);
pin.SaveTo(&description);
@@ -241,7 +241,7 @@ base::Value PrinterSemanticCapsAndDefaultsToCdd(
GetVendorCapabilities(semantic_info);
vendor_capabilities.SaveTo(&description);
}
-#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif // defined(OS_CHROMEOS)
return std::move(description).ToValue();
}
diff --git a/chromium/components/printing/common/cloud_print_cdd_conversion.h b/chromium/components/printing/common/cloud_print_cdd_conversion.h
index 09aa62bb4ae..d63129ea6bb 100644
--- a/chromium/components/printing/common/cloud_print_cdd_conversion.h
+++ b/chromium/components/printing/common/cloud_print_cdd_conversion.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_PRINTING_COMMON_CLOUD_PRINT_CDD_CONVERSION_H_
#define COMPONENTS_PRINTING_COMMON_CLOUD_PRINT_CDD_CONVERSION_H_
-#include <memory>
-#include <string>
-
#include "base/values.h"
namespace printing {
diff --git a/chromium/components/printing/common/print.mojom b/chromium/components/printing/common/print.mojom
index 4fde003f2a1..bfca294bd94 100644
--- a/chromium/components/printing/common/print.mojom
+++ b/chromium/components/printing/common/print.mojom
@@ -276,6 +276,7 @@ interface PrintRenderFrame {
// Tells the RenderFrame to switch the CSS to print media type, render every
// requested page using the print preview document's frame/node, and then
// switch the CSS back to display media type.
+ [EnableIf=enable_print_preview]
PrintForSystemDialog();
// Tells the RenderFrame to initiate print preview for the entire document.
@@ -321,25 +322,10 @@ interface PrintManagerHost {
// rendered pages according to the specified settings.
DidGetPrintedPagesCount(int32 cookie, uint32 number_pages);
- // Sends the document cookie of the current printer query to the browser.
- DidGetDocumentCookie(int32 cookie);
-
- // Sends the accessibility tree corresponding to a document being
- // printed, needed for a tagged (accessible) PDF.
- [EnableIf=enable_tagged_pdf]
- SetAccessibilityTree(int32 cookie, ax.mojom.AXTreeUpdate accessibility_tree);
-
// Request the default print settings.
[Sync]
GetDefaultPrintSettings() => (PrintParams default_settings);
- // Update the current print settings with new |job_settings|.
- [Sync]
- UpdatePrintSettings(
- int32 cookie,
- mojo_base.mojom.DictionaryValue job_settings)
- => (PrintPagesParams current_settings, bool canceled);
-
// Tells the browser that the print dialog has been shown.
DidShowPrintDialog();
@@ -360,6 +346,13 @@ interface PrintManagerHost {
// Tells the browser printing failed.
PrintingFailed(int32 cookie);
+ // Update the current print settings with new |job_settings|.
+ [EnableIf=enable_print_preview, Sync]
+ UpdatePrintSettings(
+ int32 cookie,
+ mojo_base.mojom.DictionaryValue job_settings)
+ => (PrintPagesParams current_settings, bool canceled);
+
// Tells the browser to set up the print preview requested by the script. It
// runs a nested run loop in the renderer until print preview for
// window.print() finishes.
@@ -381,4 +374,11 @@ interface PrintManagerHost {
// has been cancelled.
[EnableIf=enable_print_preview, Sync]
CheckForCancel(int32 preview_ui_id, int32 request_id) => (bool cancel);
+
+ // Sends the accessibility tree corresponding to a document being
+ // printed, needed for a tagged (accessible) PDF. Note that
+ // enable_print_preview must be set to true as well, but Mojo cannot express
+ // that. Instead, this dependency is enforced by GN.
+ [EnableIf=enable_tagged_pdf]
+ SetAccessibilityTree(int32 cookie, ax.mojom.AXTreeUpdate accessibility_tree);
};
diff --git a/chromium/components/printing/renderer/print_render_frame_helper.cc b/chromium/components/printing/renderer/print_render_frame_helper.cc
index b2f6053c94a..8f9e14c5be9 100644
--- a/chromium/components/printing/renderer/print_render_frame_helper.cc
+++ b/chromium/components/printing/renderer/print_render_frame_helper.cc
@@ -114,6 +114,8 @@ const char kPageLoadScriptFormat[] =
const char kPageSetupScriptFormat[] = "setupHeaderFooterTemplate(%s);";
+constexpr int kAllowedIpcDepthForPrint = 1;
+
void ExecuteScript(blink::WebLocalFrame* frame,
const char* script_format,
const base::Value& parameters) {
@@ -637,6 +639,43 @@ blink::WebView* FrameReference::view() {
return view_;
}
+ClosuresForMojoResponse::ClosuresForMojoResponse() = default;
+
+ClosuresForMojoResponse::~ClosuresForMojoResponse() {
+ RunScriptedPrintPreviewQuitClosure();
+ RunPrintSettingFromUserQuitClosure();
+}
+
+void ClosuresForMojoResponse::SetScriptedPrintPreviewQuitClosure(
+ base::OnceClosure quit_print_preview) {
+ DCHECK(!scripted_print_preview_quit_closure_);
+ scripted_print_preview_quit_closure_ = std::move(quit_print_preview);
+}
+
+bool ClosuresForMojoResponse::HasScriptedPrintPreviewQuitClosure() const {
+ return !scripted_print_preview_quit_closure_.is_null();
+}
+
+void ClosuresForMojoResponse::RunScriptedPrintPreviewQuitClosure() {
+ if (!scripted_print_preview_quit_closure_)
+ return;
+
+ std::move(scripted_print_preview_quit_closure_).Run();
+}
+
+void ClosuresForMojoResponse::SetPrintSettingFromUserQuitClosure(
+ base::OnceClosure quit_print_setting) {
+ DCHECK(!get_print_settings_from_user_quit_closure_);
+ get_print_settings_from_user_quit_closure_ = std::move(quit_print_setting);
+}
+
+void ClosuresForMojoResponse::RunPrintSettingFromUserQuitClosure() {
+ if (!get_print_settings_from_user_quit_closure_)
+ return;
+
+ std::move(get_print_settings_from_user_quit_closure_).Run();
+}
+
// static
double PrintRenderFrameHelper::GetScaleFactor(double input_scale_factor,
bool is_pdf) {
@@ -669,8 +708,9 @@ void PrintRenderFrameHelper::PrintHeaderAndFooter(
blink::WebView* web_view = blink::WebView::Create(
/*client=*/nullptr,
/*is_hidden=*/false, /*is_inside_portal=*/false,
- /*compositing_enabled=*/false, /*opener=*/nullptr,
- mojo::NullAssociatedReceiver(), *source_frame.GetAgentGroupScheduler(),
+ /*compositing_enabled=*/false, /*widgets_never_composited=*/false,
+ /*opener=*/nullptr, mojo::NullAssociatedReceiver(),
+ *source_frame.GetAgentGroupScheduler(),
/*session_storage_namespace_id=*/base::EmptyString());
web_view->GetSettings()->SetJavaScriptEnabled(true);
@@ -908,9 +948,9 @@ void PrepareFrameAndViewForPrint::ResizeForPrinting() {
}
void PrepareFrameAndViewForPrint::StartPrinting() {
- ResizeForPrinting();
blink::WebView* web_view = frame_.view();
web_view->GetSettings()->SetShouldPrintBackgrounds(should_print_backgrounds_);
+ ResizeForPrinting();
expected_pages_count_ =
frame()->PrintBegin(web_print_params_, node_to_print_);
is_printing_started_ = true;
@@ -947,6 +987,7 @@ void PrepareFrameAndViewForPrint::CopySelection(
/*is_hidden=*/false,
/*is_inside_portal=*/false,
/*compositing_enabled=*/false,
+ /*widgets_never_composited=*/false,
/*opener=*/nullptr, mojo::NullAssociatedReceiver(),
agent_group_scheduler_,
/*session_storage_namespace_id=*/base::EmptyString());
@@ -1089,7 +1130,9 @@ PrintRenderFrameHelper::PrintRenderFrameHelper(
std::unique_ptr<Delegate> delegate)
: content::RenderFrameObserver(render_frame),
content::RenderFrameObserverTracker<PrintRenderFrameHelper>(render_frame),
- delegate_(std::move(delegate)) {
+ delegate_(std::move(delegate)),
+ closures_for_mojo_responses_(
+ base::MakeRefCounted<ClosuresForMojoResponse>()) {
if (!delegate_->IsPrintPreviewEnabled())
DisablePreview();
@@ -1135,7 +1178,7 @@ bool PrintRenderFrameHelper::IsScriptInitiatedPrintAllowed(
void PrintRenderFrameHelper::DidStartNavigation(
const GURL& url,
- base::Optional<blink::WebNavigationType> navigation_type) {
+ absl::optional<blink::WebNavigationType> navigation_type) {
is_loading_ = true;
}
@@ -1209,7 +1252,7 @@ void PrintRenderFrameHelper::BindPrintRenderFrameReceiver(
void PrintRenderFrameHelper::PrintRequestedPages() {
ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
- if (ipc_nesting_level_ > 1)
+ if (ipc_nesting_level_ > kAllowedIpcDepthForPrint)
return;
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
@@ -1230,18 +1273,19 @@ void PrintRenderFrameHelper::PrintRequestedPages() {
// just return.
}
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
void PrintRenderFrameHelper::PrintForSystemDialog() {
ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
- if (ipc_nesting_level_ > 1)
+ if (ipc_nesting_level_ > kAllowedIpcDepthForPrint)
return;
- if (scripted_print_preview_quit_closure_) {
+ if (closures_for_mojo_responses_->HasScriptedPrintPreviewQuitClosure()) {
// If an in-progress print preview already created a nested loop, avoid
// creating yet another nested loop. Instead, quit the current nested loop,
// and call this method again.
DCHECK(!do_deferred_print_for_system_dialog_);
do_deferred_print_for_system_dialog_ = true;
- std::move(scripted_print_preview_quit_closure_).Run();
+ closures_for_mojo_responses_->RunScriptedPrintPreviewQuitClosure();
return;
}
@@ -1259,7 +1303,6 @@ void PrintRenderFrameHelper::PrintForSystemDialog() {
// just return.
}
-#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
void PrintRenderFrameHelper::SetPrintPreviewUI(
mojo::PendingAssociatedRemote<mojom::PrintPreviewUI> preview) {
preview_ui_.Bind(std::move(preview));
@@ -1272,7 +1315,7 @@ void PrintRenderFrameHelper::InitiatePrintPreview(
mojo::PendingAssociatedRemote<mojom::PrintRenderer> print_renderer,
bool has_selection) {
ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
- if (ipc_nesting_level_ > 1)
+ if (ipc_nesting_level_ > kAllowedIpcDepthForPrint)
return;
if (print_renderer) {
@@ -1297,7 +1340,7 @@ void PrintRenderFrameHelper::InitiatePrintPreview(
void PrintRenderFrameHelper::PrintPreview(base::Value settings) {
ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
- if (ipc_nesting_level_ > 1)
+ if (ipc_nesting_level_ > kAllowedIpcDepthForPrint)
return;
print_preview_context_.OnPrintPreview();
@@ -1357,7 +1400,7 @@ void PrintRenderFrameHelper::PrintFrameContent(
mojom::PrintFrameContentParamsPtr params,
PrintFrameContentCallback callback) {
ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
- if (ipc_nesting_level_ > 1)
+ if (ipc_nesting_level_ > kAllowedIpcDepthForPrint)
return;
// If the last request is not finished yet, do not proceed.
@@ -1430,7 +1473,7 @@ void PrintRenderFrameHelper::PrintFrameContent(
void PrintRenderFrameHelper::PrintingDone(bool success) {
ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
- if (ipc_nesting_level_ > 1)
+ if (ipc_nesting_level_ > kAllowedIpcDepthForPrint)
return;
notify_browser_of_print_failure_ = false;
DidFinishPrinting(success ? OK : FAIL_PRINT);
@@ -1463,7 +1506,7 @@ void PrintRenderFrameHelper::GetPageSizeAndContentAreaFromPageLayout(
void PrintRenderFrameHelper::UpdateFrameMarginsCssInfo(
const base::DictionaryValue& settings) {
- base::Optional<int> margins_type = settings.FindIntKey(kSettingMarginsType);
+ absl::optional<int> margins_type = settings.FindIntKey(kSettingMarginsType);
ignore_css_margins_ = margins_type.value_or(static_cast<int>(
mojom::MarginType::kDefaultMargins)) !=
static_cast<int>(mojom::MarginType::kDefaultMargins);
@@ -2192,7 +2235,7 @@ bool PrintRenderFrameHelper::UpdatePrintSettings(
blink::WebLocalFrame* frame,
const blink::WebNode& node,
const base::DictionaryValue& passed_job_settings) {
- if (passed_job_settings.empty()) {
+ if (passed_job_settings.DictEmpty()) {
// TODO(thestig): Remove this block in the future, when we are certain this
// is not reachable.
NOTREACHED();
@@ -2292,7 +2335,8 @@ mojom::PrintPagesParamsPtr PrintRenderFrameHelper::GetPrintSettingsFromUser(
mojom::PrintPagesParamsPtr print_settings;
base::RunLoop loop{base::RunLoop::Type::kNestableTasksAllowed};
- get_print_settings_from_user_quit_closure_ = loop.QuitClosure();
+ closures_for_mojo_responses_->SetPrintSettingFromUserQuitClosure(
+ loop.QuitClosure());
GetPrintManagerHost()->ScriptedPrint(
std::move(params),
base::BindOnce(
@@ -2462,10 +2506,11 @@ void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type) {
weak_ptr_factory_.GetWeakPtr()));
}
base::RunLoop loop{base::RunLoop::Type::kNestableTasksAllowed};
- scripted_print_preview_quit_closure_ = loop.QuitClosure();
+ closures_for_mojo_responses_->SetScriptedPrintPreviewQuitClosure(
+ loop.QuitClosure());
GetPrintManagerHost()->SetupScriptedPrintPreview(base::BindOnce(
- &PrintRenderFrameHelper::QuitScriptedPrintPreviewRunLoop,
- weak_ptr_factory_.GetWeakPtr()));
+ &ClosuresForMojoResponse::RunScriptedPrintPreviewQuitClosure,
+ closures_for_mojo_responses_));
loop.Run();
// Check if |this| is still valid.
@@ -2728,17 +2773,12 @@ void PrintRenderFrameHelper::PrintPreviewContext::FinalizePrintReadyDocument() {
(base::TimeTicks::Now() - begin_time) + document_render_time_;
base::TimeDelta avg_time_per_page = total_time / pages_to_render_.size();
- base::UmaHistogramMediumTimes(is_for_arc_ ? "Arc.PrintPreview.RenderToPDFTime"
- : "PrintPreview.RenderToPDFTime",
+ base::UmaHistogramMediumTimes("PrintPreview.RenderToPDFTime",
document_render_time_);
+ base::UmaHistogramMediumTimes("PrintPreview.RenderAndGeneratePDFTime",
+ total_time);
base::UmaHistogramMediumTimes(
- is_for_arc_ ? "Arc.PrintPreview.RenderAndGeneratePDFTime"
- : "PrintPreview.RenderAndGeneratePDFTime",
- total_time);
- base::UmaHistogramMediumTimes(
- is_for_arc_ ? "Arc.PrintPreview.RenderAndGeneratePDFTimeAvgPerPage"
- : "PrintPreview.RenderAndGeneratePDFTimeAvgPerPage",
- avg_time_per_page);
+ "PrintPreview.RenderAndGeneratePDFTimeAvgPerPage", avg_time_per_page);
}
void PrintRenderFrameHelper::PrintPreviewContext::Finished() {
@@ -2887,7 +2927,6 @@ void PrintRenderFrameHelper::PrintPreviewContext::CalculatePluginAttributes() {
void PrintRenderFrameHelper::SetPrintPagesParams(
const mojom::PrintPagesParams& settings) {
print_pages_params_ = settings.Clone();
- GetPrintManagerHost()->DidGetDocumentCookie(settings.params->document_cookie);
}
void PrintRenderFrameHelper::QuitActiveRunLoops() {
@@ -2896,13 +2935,11 @@ void PrintRenderFrameHelper::QuitActiveRunLoops() {
}
void PrintRenderFrameHelper::QuitScriptedPrintPreviewRunLoop() {
- if (scripted_print_preview_quit_closure_)
- std::move(scripted_print_preview_quit_closure_).Run();
+ closures_for_mojo_responses_->RunScriptedPrintPreviewQuitClosure();
}
void PrintRenderFrameHelper::QuitGetPrintSettingsFromUserRunLoop() {
- if (get_print_settings_from_user_quit_closure_)
- std::move(get_print_settings_from_user_quit_closure_).Run();
+ closures_for_mojo_responses_->RunPrintSettingFromUserQuitClosure();
}
PrintRenderFrameHelper::ScopedIPC::ScopedIPC(
diff --git a/chromium/components/printing/renderer/print_render_frame_helper.h b/chromium/components/printing/renderer/print_render_frame_helper.h
index ae14b4e5da6..32885b25971 100644
--- a/chromium/components/printing/renderer/print_render_frame_helper.h
+++ b/chromium/components/printing/renderer/print_render_frame_helper.h
@@ -11,6 +11,8 @@
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/read_only_shared_memory_region.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -84,6 +86,29 @@ class FrameReference {
blink::WebLocalFrame* frame_;
};
+// Helper to ensure that quit closures for Mojo response are called.
+class ClosuresForMojoResponse
+ : public base::RefCounted<ClosuresForMojoResponse> {
+ public:
+ ClosuresForMojoResponse();
+ ClosuresForMojoResponse(const ClosuresForMojoResponse&) = delete;
+ ClosuresForMojoResponse& operator=(const ClosuresForMojoResponse&) = delete;
+
+ void SetScriptedPrintPreviewQuitClosure(base::OnceClosure quit_print_preview);
+ bool HasScriptedPrintPreviewQuitClosure() const;
+ void RunScriptedPrintPreviewQuitClosure();
+ void SetPrintSettingFromUserQuitClosure(base::OnceClosure quit_print_setting);
+ void RunPrintSettingFromUserQuitClosure();
+
+ private:
+ friend class base::RefCounted<ClosuresForMojoResponse>;
+ ~ClosuresForMojoResponse();
+
+ // Stores quit closures for the runloops that are waiting for Mojo replies.
+ base::OnceClosure scripted_print_preview_quit_closure_;
+ base::OnceClosure get_print_settings_from_user_quit_closure_;
+};
+
// PrintRenderFrameHelper handles most of the printing grunt work for
// RenderView. We plan on making print asynchronous and that will require
// copying the DOM of the document and creating a new WebView with the contents.
@@ -222,7 +247,7 @@ class PrintRenderFrameHelper
void OnDestruct() override;
void DidStartNavigation(
const GURL& url,
- base::Optional<blink::WebNavigationType> navigation_type) override;
+ absl::optional<blink::WebNavigationType> navigation_type) override;
void DidFailProvisionalLoad() override;
void DidFinishLoad() override;
void ScriptedPrint(bool user_initiated) override;
@@ -232,8 +257,8 @@ class PrintRenderFrameHelper
// printing::mojom::PrintRenderFrame:
void PrintRequestedPages() override;
- void PrintForSystemDialog() override;
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
+ void PrintForSystemDialog() override;
void SetPrintPreviewUI(
mojo::PendingAssociatedRemote<mojom::PrintPreviewUI> preview) override;
void InitiatePrintPreview(
@@ -662,9 +687,8 @@ class PrintRenderFrameHelper
// parameters so that it can be invoked after DidStopLoading.
base::OnceClosure on_stop_loading_closure_;
- // Stores quit closures for the runloops that are waiting for Mojo replies.
- base::OnceClosure scripted_print_preview_quit_closure_;
- base::OnceClosure get_print_settings_from_user_quit_closure_;
+ // Stores the quit closures of Mojo responses.
+ scoped_refptr<ClosuresForMojoResponse> closures_for_mojo_responses_;
bool do_deferred_print_for_system_dialog_ = false;
diff --git a/chromium/components/printing/resources/DIR_METADATA b/chromium/components/printing/resources/DIR_METADATA
deleted file mode 100644
index c6bf1f00c00..00000000000
--- a/chromium/components/printing/resources/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Internals>Printing"
-}
diff --git a/chromium/components/printing_component_strings.grdp b/chromium/components/printing_component_strings.grdp
index da952350895..d44b0eb70d0 100644
--- a/chromium/components/printing_component_strings.grdp
+++ b/chromium/components/printing_component_strings.grdp
@@ -12,7 +12,7 @@
Print Compositor Service
</message>
- <if expr="chromeos">
+ <if expr="chromeos or lacros">
<message name="IDS_PRINT_CHAMBER_HUMIDITY" desc="PWG5100.21 (8.1.1) chamber-humidity">
Chamber humidity
</message>
diff --git a/chromium/components/privacy_sandbox/privacy_sandbox_prefs.cc b/chromium/components/privacy_sandbox/privacy_sandbox_prefs.cc
index 3bf14f00369..f6094c3d700 100644
--- a/chromium/components/privacy_sandbox/privacy_sandbox_prefs.cc
+++ b/chromium/components/privacy_sandbox/privacy_sandbox_prefs.cc
@@ -23,6 +23,8 @@ const char kPrivacySandboxPageViewed[] = "privacy_sandbox.page_viewed";
const char kPrivacySandboxFlocDataAccessibleSince[] =
"privacy_sandbox.floc_data_accessible_since";
+extern const char kPrivacySandboxFlocEnabled[] = "privacy_sandbox.floc_enabled";
+
} // namespace prefs
namespace privacy_sandbox {
@@ -39,6 +41,9 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kPrivacySandboxPageViewed, false);
registry->RegisterTimePref(prefs::kPrivacySandboxFlocDataAccessibleSince,
base::Time());
+ registry->RegisterBooleanPref(
+ prefs::kPrivacySandboxFlocEnabled, true,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
}
} // namespace privacy_sandbox
diff --git a/chromium/components/privacy_sandbox/privacy_sandbox_prefs.h b/chromium/components/privacy_sandbox/privacy_sandbox_prefs.h
index 0dcd5767d6f..22f6bf7e4e1 100644
--- a/chromium/components/privacy_sandbox/privacy_sandbox_prefs.h
+++ b/chromium/components/privacy_sandbox/privacy_sandbox_prefs.h
@@ -9,10 +9,9 @@ class PrefRegistrySimple;
namespace prefs {
-// Synced boolean that is true when Privacy Sandbox APIs are enabled. If the
-// PrivacySandboxSettings feature is enabled, this Boolean is controlled by the
-// associated UI; if it is disabled, it is controlled by third party cookie
-// blocking settings.
+// Synced boolean pref. Privacy Sandbox APIs may only be enabled when this is
+// enabled, but each API will respect its own enabling logic if this pref is
+// true. When this pref is false ALL Privacy Sandbox APIs are disabled.
extern const char kPrivacySandboxApisEnabled[];
// Synced boolean that indicates if a user has manually toggled the settings
@@ -32,6 +31,10 @@ extern const char kPrivacySandboxPageViewed[];
// a user's FLoC ID.
extern const char kPrivacySandboxFlocDataAccessibleSince[];
+// Synced boolean that controls whether FLoC is enabled. Requires that the
+// kPrivacySandboxApisEnabled preference be enabled to take effect.
+extern const char kPrivacySandboxFlocEnabled[];
+
} // namespace prefs
namespace privacy_sandbox {
diff --git a/chromium/components/privacy_sandbox_strings.grdp b/chromium/components/privacy_sandbox_strings.grdp
new file mode 100644
index 00000000000..4953b15aa84
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings.grdp
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <message name="IDS_PRIVACY_SANDBOX_FLOC_INVALID" desc="A message shown in place of the user's FLoC ID if the ID is invalid and will not be recomputed">
+ None
+ </message>
+ <message name="IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION" desc="Description of how FLoC works displayed to the user.">
+ {NUM_DAYS, plural,
+ =0 {When this control is on and the status is active, Chrome determines which large group of people, or "cohort," your recent browsing activity is most similar to. Advertisers can select ads for the group and your browsing activity is kept private on your device. Your group is updated every day.}
+ =1 {When this control is on and the status is active, Chrome determines which large group of people, or "cohort," your recent browsing activity is most similar to. Advertisers can select ads for the group and your browsing activity is kept private on your device. Your group is updated every day.}
+ other {When this control is on and the status is active, Chrome determines which large group of people, or "cohort," your recent browsing activity is most similar to. Advertisers can select ads for the group and your browsing activity is kept private on your device. Your group is updated every {NUM_DAYS} days.}}
+ </message>
+ <message name="IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE" desc="Description of how long until the user's FLoC ID is recomputed, in days.">
+ {NUM_DAYS, plural,
+ =0 {In less than a day}
+ =1 {In a day}
+ other {In {NUM_DAYS} days}}
+ </message>
+ <message name="IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE_INVALID" desc="A message shown in place of when the user's FLoC ID will be next computed if the user's ID will not be recomputed for any reason, such as having FLoC disabled">
+ Not applicable
+ </message>
+ <message name="IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION" desc="Description of what happens when a user chooses to reset their Federated Learning of Cohorts (FLoC) identifier">
+ {NUM_DAYS, plural,
+ =0 {You can reset your group at any time. It takes about a day to join a new group.}
+ =1 {You can reset your group at any time. It takes about a day to join a new group.}
+ other {You can reset your group at any time. It takes {NUM_DAYS} days to join a new group.}}
+ </message>
+ <message name="IDS_PRIVACY_SANDBOX_FLOC_STATUS_ACTIVE" desc="Description of the user's FLoC status when they have the FLoC setting enabled, and the Origin Trial feature enabled, and so FLoC is fully active.">
+ Trial is active
+ </message>
+ <message name="IDS_PRIVACY_SANDBOX_FLOC_STATUS_ELIGIBLE_NOT_ACTIVE" desc="Description of the user's FLoC status when FLoC is not operational because the user was not placed in the origin trial. When the user is placed in the trial, because their FLoC setting is enabled, FLoC will become operational">
+ Eligible for trial but not active
+ </message>
+ <message name="IDS_PRIVACY_SANDBOX_FLOC_STATUS_NOT_ACTIVE" desc="Description of the user's FLoC status when FLoC is not operational, either because the user does not have the FLoC setting enabled, or the user was not placed in the origin trial, or both.">
+ Off
+ </message>
+</grit-part>
diff --git a/chromium/components/privacy_sandbox_strings_grdp/DIR_METADATA b/chromium/components/privacy_sandbox_strings_grdp/DIR_METADATA
new file mode 100644
index 00000000000..669e5c9c9d1
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+ component: "UI>Settings>Privacy"
+}
+
+team_email: "chrome-friendly-settings@google.com"
diff --git a/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION.png.sha1 b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION.png.sha1
new file mode 100644
index 00000000000..9da6afd8821
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+b7fd0dcb9fea54451d02f3ceeef41ea39dad98f1 \ No newline at end of file
diff --git a/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_INVALID.png.sha1 b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_INVALID.png.sha1
new file mode 100644
index 00000000000..bbb43d4867c
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_INVALID.png.sha1
@@ -0,0 +1 @@
+62051f974110afa57d03943f60f43ee68d7229bb \ No newline at end of file
diff --git a/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION.png.sha1 b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION.png.sha1
new file mode 100644
index 00000000000..c234ffffc8b
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_RESET_EXPLANATION.png.sha1
@@ -0,0 +1 @@
+7b4c64079a5687478ebd04d5debdbf23f7be580e \ No newline at end of file
diff --git a/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_ACTIVE.png.sha1 b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_ACTIVE.png.sha1
new file mode 100644
index 00000000000..d4aed4d5ed4
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_ACTIVE.png.sha1
@@ -0,0 +1 @@
+1e5dfe1174e1a2c3019c4cd948b8982ac6b3fb7a \ No newline at end of file
diff --git a/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_ELIGIBLE_NOT_ACTIVE.png.sha1 b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_ELIGIBLE_NOT_ACTIVE.png.sha1
new file mode 100644
index 00000000000..e8cb55c66e8
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_ELIGIBLE_NOT_ACTIVE.png.sha1
@@ -0,0 +1 @@
+235572bf892a3558861dc6d9ac736f27d8acc645 \ No newline at end of file
diff --git a/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_NOT_ACTIVE.png.sha1 b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_NOT_ACTIVE.png.sha1
new file mode 100644
index 00000000000..1ddf33ffcc6
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_STATUS_NOT_ACTIVE.png.sha1
@@ -0,0 +1 @@
+dc3df7a7eb31c3c09aa9480946aeb873b9c3d0fc \ No newline at end of file
diff --git a/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE.png.sha1 b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE.png.sha1
new file mode 100644
index 00000000000..aa6d6f7b331
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE.png.sha1
@@ -0,0 +1 @@
+26eb02bf641228865c1090d21689f8345b78730e \ No newline at end of file
diff --git a/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE_INVALID.png.sha1 b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE_INVALID.png.sha1
new file mode 100644
index 00000000000..653922e68e2
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/IDS_PRIVACY_SANDBOX_FLOC_TIME_TO_NEXT_COMPUTE_INVALID.png.sha1
@@ -0,0 +1 @@
+49f9f1b55c58eeb7a18da389f1d08eb4d6ae955c \ No newline at end of file
diff --git a/chromium/components/privacy_sandbox_strings_grdp/OWNERS b/chromium/components/privacy_sandbox_strings_grdp/OWNERS
new file mode 100644
index 00000000000..230e9a1decd
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/OWNERS
@@ -0,0 +1 @@
+file://components/privacy_sandbox/OWNERS
diff --git a/chromium/components/privacy_sandbox_strings_grdp/README.md b/chromium/components/privacy_sandbox_strings_grdp/README.md
new file mode 100644
index 00000000000..119d8b9bff7
--- /dev/null
+++ b/chromium/components/privacy_sandbox_strings_grdp/README.md
@@ -0,0 +1,5 @@
+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/profile_metrics/BUILD.gn b/chromium/components/profile_metrics/BUILD.gn
index f45590f0ef9..b303193dc00 100644
--- a/chromium/components/profile_metrics/BUILD.gn
+++ b/chromium/components/profile_metrics/BUILD.gn
@@ -4,6 +4,7 @@
static_library("profile_metrics") {
sources = [
+ "browser_profile_type.cc",
"browser_profile_type.h",
"counts.cc",
"counts.h",
@@ -11,13 +12,20 @@ static_library("profile_metrics") {
"state.h",
]
- if (!is_ios) {
- sources += [ "browser_profile_type.cc" ]
- }
-
deps = [ "//base" ]
}
+source_set("unit_tests") {
+ testonly = true
+ sources = [ "browser_profile_type_unittest.cc" ]
+
+ deps = [
+ ":profile_metrics",
+ "//base",
+ "//testing/gtest",
+ ]
+}
+
if (is_android) {
import("//build/config/android/rules.gni")
diff --git a/chromium/components/profile_metrics/browser_profile_type.cc b/chromium/components/profile_metrics/browser_profile_type.cc
index 22a4a2bd6d0..77b08d13f0f 100644
--- a/chromium/components/profile_metrics/browser_profile_type.cc
+++ b/chromium/components/profile_metrics/browser_profile_type.cc
@@ -31,13 +31,13 @@ const void* const ProfileTypeUserData::kKey = &ProfileTypeUserData::kKey;
namespace profile_metrics {
-void SetBrowserContextType(base::SupportsUserData* browser_context,
+void SetBrowserProfileType(base::SupportsUserData* browser_context,
BrowserProfileType type) {
browser_context->SetUserData(ProfileTypeUserData::kKey,
std::make_unique<ProfileTypeUserData>(type));
}
-BrowserProfileType GetBrowserContextType(
+BrowserProfileType GetBrowserProfileType(
const base::SupportsUserData* browser_context) {
base::SupportsUserData::Data* data =
browser_context->GetUserData(ProfileTypeUserData::kKey);
diff --git a/chromium/components/profile_metrics/browser_profile_type.h b/chromium/components/profile_metrics/browser_profile_type.h
index eed437c1b79..e4afed1ea7e 100644
--- a/chromium/components/profile_metrics/browser_profile_type.h
+++ b/chromium/components/profile_metrics/browser_profile_type.h
@@ -6,18 +6,13 @@
#define COMPONENTS_PROFILE_METRICS_BROWSER_PROFILE_TYPE_H_
#include "base/supports_user_data.h"
-#include "build/build_config.h"
-// TODO(https://crbug.com/1169142): Rename to browser_context_metrics to remove
-// the profile concept from /components.
namespace profile_metrics {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.profile_metrics
-// TODO(https://crbug.com/1169142): Rename to BrowserContextType to remove the
-// profile concept from /components.
enum class BrowserProfileType {
kRegular = 0,
kIncognito = 1,
@@ -28,13 +23,17 @@ enum class BrowserProfileType {
kMaxValue = kEphemeralGuest,
};
-// TODO(https://crbug.com/1169142): Expand to iOS.
-#if !defined(OS_IOS)
-BrowserProfileType GetBrowserContextType(
+// Returns the BrowserProfileType value associated with |browser_context|.
+// Note that the browser profile type should be set for all BrowserContext (or
+// equivalent) objects during creation or initialization of the object. This
+// function will result in a crash if |SetBrowserProfileType| is not called
+// before to associate the browser profile type.
+BrowserProfileType GetBrowserProfileType(
const base::SupportsUserData* browser_context);
-void SetBrowserContextType(base::SupportsUserData* browser_context,
+
+// Associates |type| as the BrowserProfileType value for |browser_context|.
+void SetBrowserProfileType(base::SupportsUserData* browser_context,
BrowserProfileType type);
-#endif
} // namespace profile_metrics
#endif // COMPONENTS_PROFILE_METRICS_BROWSER_PROFILE_TYPE_H_ \ No newline at end of file
diff --git a/chromium/components/profile_metrics/browser_profile_type_unittest.cc b/chromium/components/profile_metrics/browser_profile_type_unittest.cc
new file mode 100644
index 00000000000..421906f671d
--- /dev/null
+++ b/chromium/components/profile_metrics/browser_profile_type_unittest.cc
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/profile_metrics/browser_profile_type.h"
+#include "base/supports_user_data.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class FakeBrowserContext : public base::SupportsUserData {
+ public:
+ FakeBrowserContext() = default;
+ ~FakeBrowserContext() override = default;
+};
+
+} // namespace
+
+namespace profile_metrics {
+
+class BrowserProfileTypeUnitTest : public testing::Test {
+ public:
+ BrowserProfileTypeUnitTest() = default;
+ ~BrowserProfileTypeUnitTest() override = default;
+};
+
+TEST_F(BrowserProfileTypeUnitTest, AssignmentAndRetrieval) {
+ for (int i = 0; i <= static_cast<int>(BrowserProfileType::kMaxValue); i++) {
+ BrowserProfileType pt = static_cast<BrowserProfileType>(i);
+
+ FakeBrowserContext browser_context;
+
+ SetBrowserProfileType(&browser_context, pt);
+ EXPECT_EQ(pt, GetBrowserProfileType(&browser_context));
+ }
+}
+
+#if defined(GTEST_HAS_DEATH_TEST)
+TEST_F(BrowserProfileTypeUnitTest, UnassignedType) {
+ FakeBrowserContext browser_context;
+
+ EXPECT_DEATH(GetBrowserProfileType(&browser_context), "");
+}
+#endif
+
+} // namespace profile_metrics
diff --git a/chromium/components/qr_code_generator/qr_code_generator.cc b/chromium/components/qr_code_generator/qr_code_generator.cc
index f12ea11d327..815612ff79a 100644
--- a/chromium/components/qr_code_generator/qr_code_generator.cc
+++ b/chromium/components/qr_code_generator/qr_code_generator.cc
@@ -263,7 +263,7 @@ constexpr QRVersionInfo version_infos[] = {
};
const QRVersionInfo* GetVersionForDataSize(size_t num_data_bytes,
- base::Optional<int> min_version) {
+ absl::optional<int> min_version) {
for (const auto& version : version_infos) {
if (version.input_bytes() >= num_data_bytes &&
(!min_version || *min_version <= version.version)) {
@@ -404,10 +404,10 @@ QRCodeGenerator::GeneratedCode::GeneratedCode(
QRCodeGenerator::GeneratedCode&&) = default;
QRCodeGenerator::GeneratedCode::~GeneratedCode() = default;
-base::Optional<QRCodeGenerator::GeneratedCode> QRCodeGenerator::Generate(
+absl::optional<QRCodeGenerator::GeneratedCode> QRCodeGenerator::Generate(
base::span<const uint8_t> in,
- base::Optional<int> min_version,
- base::Optional<uint8_t> mask) {
+ absl::optional<int> min_version,
+ absl::optional<uint8_t> mask) {
CHECK(!mask || *mask <= kMaxMask);
const bool is_alphanum =
@@ -446,7 +446,7 @@ base::Optional<QRCodeGenerator::GeneratedCode> QRCodeGenerator::Generate(
const QRVersionInfo* version_info =
GetVersionForDataSize(small_length_bytes, min_version);
if (!version_info) {
- return base::nullopt;
+ return absl::nullopt;
}
if (version_info->version > kMaxVersionWithSmallLengths) {
@@ -454,7 +454,7 @@ base::Optional<QRCodeGenerator::GeneratedCode> QRCodeGenerator::Generate(
// now needed may change the selected version.
version_info = GetVersionForDataSize(large_length_bytes, min_version);
if (!version_info) {
- return base::nullopt;
+ return absl::nullopt;
}
}
@@ -636,7 +636,7 @@ base::Optional<QRCodeGenerator::GeneratedCode> QRCodeGenerator::Generate(
DCHECK_EQ(k, total_bytes);
uint8_t best_mask = mask.value_or(0);
- base::Optional<unsigned> lowest_penalty;
+ absl::optional<unsigned> lowest_penalty;
// If |mask| was not specified, then evaluate each masking function to find
// the one with the lowest penalty score.
diff --git a/chromium/components/qr_code_generator/qr_code_generator.h b/chromium/components/qr_code_generator/qr_code_generator.h
index 50a0b4a55eb..d264e93c869 100644
--- a/chromium/components/qr_code_generator/qr_code_generator.h
+++ b/chromium/components/qr_code_generator/qr_code_generator.h
@@ -11,7 +11,7 @@
#include <vector>
#include "base/containers/span.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
struct QRVersionInfo;
@@ -60,10 +60,10 @@ class QRCodeGenerator {
// input-dependent and not known at compile-time. The optional |mask| argument
// specifies the QR mask value to use (from 0 to 7). If not specified, the
// optimal mask is calculated per the algorithm specified in the QR standard.
- base::Optional<GeneratedCode> Generate(
+ absl::optional<GeneratedCode> Generate(
base::span<const uint8_t> in,
- base::Optional<int> min_version = base::nullopt,
- base::Optional<uint8_t> mask = base::nullopt);
+ absl::optional<int> min_version = absl::nullopt,
+ absl::optional<uint8_t> mask = absl::nullopt);
private:
// PutFinder paints a finder symbol at the given coordinates.
diff --git a/chromium/components/qr_code_generator/qr_code_generator_unittest.cc b/chromium/components/qr_code_generator/qr_code_generator_unittest.cc
index ce6344a4b0b..dff3e6ec0d7 100644
--- a/chromium/components/qr_code_generator/qr_code_generator_unittest.cc
+++ b/chromium/components/qr_code_generator/qr_code_generator_unittest.cc
@@ -16,8 +16,8 @@ TEST(QRCodeGenerator, Generate) {
constexpr size_t kMaxInputLen = 210;
uint8_t input[kMaxInputLen];
QRCodeGenerator qr;
- base::Optional<int> smallest_size;
- base::Optional<int> largest_size;
+ absl::optional<int> smallest_size;
+ absl::optional<int> largest_size;
for (const bool use_alphanum : {false, true}) {
SCOPED_TRACE(use_alphanum);
@@ -27,9 +27,9 @@ TEST(QRCodeGenerator, Generate) {
for (size_t input_len = 30; input_len < kMaxInputLen; input_len += 10) {
SCOPED_TRACE(input_len);
- base::Optional<QRCodeGenerator::GeneratedCode> qr_code =
+ absl::optional<QRCodeGenerator::GeneratedCode> qr_code =
qr.Generate(base::span<const uint8_t>(input, input_len));
- ASSERT_NE(qr_code, base::nullopt);
+ ASSERT_NE(qr_code, absl::nullopt);
auto& qr_data = qr_code->data;
if (!smallest_size || qr_code->qr_size < *smallest_size) {
diff --git a/chromium/components/qr_code_generator/qr_print.cc b/chromium/components/qr_code_generator/qr_print.cc
index 277f3890278..e2eee7b8db2 100644
--- a/chromium/components/qr_code_generator/qr_print.cc
+++ b/chromium/components/qr_code_generator/qr_print.cc
@@ -12,9 +12,9 @@
#include <utility>
#include "base/containers/span.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "components/qr_code_generator/qr_code_generator.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
// kTerminalBackgroundIsBright controls the output polarity. Many QR scanners
// will cope with inverted bright / dark but, if you have a bright terminal
@@ -44,7 +44,7 @@ int main(int argc, char** argv) {
const uint8_t* const input = reinterpret_cast<const uint8_t*>(argv[1]);
const size_t input_len = strlen(argv[1]);
- base::Optional<uint8_t> mask;
+ absl::optional<uint8_t> mask;
if (argc == 3) {
unsigned mask_unsigned;
if (!base::StringToUint(argv[2], &mask_unsigned) || mask_unsigned > 7) {
@@ -61,7 +61,7 @@ int main(int argc, char** argv) {
}
QRCodeGenerator generator;
- base::Optional<QRCodeGenerator::GeneratedCode> code =
+ absl::optional<QRCodeGenerator::GeneratedCode> code =
generator.Generate(base::span<const uint8_t>(input, input_len), mask);
if (!code) {
fprintf(STDERR, "Input too long to be encoded.\n");
diff --git a/chromium/components/query_parser/query_parser.cc b/chromium/components/query_parser/query_parser.cc
index 42c1a773ad2..5be2cd74d0f 100644
--- a/chromium/components/query_parser/query_parser.cc
+++ b/chromium/components/query_parser/query_parser.cc
@@ -457,6 +457,9 @@ bool QueryParser::ParseQueryImpl(const std::u16string& query,
// static
void QueryParser::ExtractQueryWords(const std::u16string& text,
QueryWordVector* words) {
+ DCHECK(text == base::i18n::ToLower(text))
+ << "The caller must have already lowercased `text`. Value = "
+ << base::UTF16ToUTF8(text);
base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD);
// TODO(evanm): support a locale here
if (!iter.Init())
diff --git a/chromium/components/query_parser/query_parser.h b/chromium/components/query_parser/query_parser.h
index c1c22fcddb3..f28ed65097d 100644
--- a/chromium/components/query_parser/query_parser.h
+++ b/chromium/components/query_parser/query_parser.h
@@ -124,6 +124,8 @@ class QueryParser {
const QueryNodeVector& find_nodes);
// Extracts the words from |text|, placing each word into |words|.
+ // |text| must already be lowercased by the caller, as otherwise the output
+ // will NEVER match anything.
static void ExtractQueryWords(const std::u16string& text,
QueryWordVector* words);
diff --git a/chromium/components/query_tiles/android/tile_provider_bridge.cc b/chromium/components/query_tiles/android/tile_provider_bridge.cc
index 6b08892d597..c04e4bd701a 100644
--- a/chromium/components/query_tiles/android/tile_provider_bridge.cc
+++ b/chromium/components/query_tiles/android/tile_provider_bridge.cc
@@ -31,7 +31,7 @@ void RunGetTilesCallback(const JavaRef<jobject>& j_callback,
}
void RunGetTileCallback(const JavaRef<jobject>& j_callback,
- base::Optional<Tile> tile) {
+ absl::optional<Tile> tile) {
JNIEnv* env = AttachCurrentThread();
RunObjectCallbackAndroid(
j_callback,
diff --git a/chromium/components/query_tiles/internal/cached_image_loader.h b/chromium/components/query_tiles/internal/cached_image_loader.h
index e2df62aaf6f..6033678eea5 100644
--- a/chromium/components/query_tiles/internal/cached_image_loader.h
+++ b/chromium/components/query_tiles/internal/cached_image_loader.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_QUERY_TILES_INTERNAL_CACHED_IMAGE_LOADER_H_
#define COMPONENTS_QUERY_TILES_INTERNAL_CACHED_IMAGE_LOADER_H_
-#include <memory>
-
#include "components/image_fetcher/core/image_fetcher.h"
#include "components/query_tiles/internal/image_loader.h"
diff --git a/chromium/components/query_tiles/internal/image_loader.h b/chromium/components/query_tiles/internal/image_loader.h
index 6cae48684c7..fe8d53a08a4 100644
--- a/chromium/components/query_tiles/internal/image_loader.h
+++ b/chromium/components/query_tiles/internal/image_loader.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_QUERY_TILES_INTERNAL_IMAGE_LOADER_H_
#define COMPONENTS_QUERY_TILES_INTERNAL_IMAGE_LOADER_H_
-#include <memory>
-#include <string>
-
#include "base/callback.h"
#include "base/macros.h"
#include "url/gurl.h"
diff --git a/chromium/components/query_tiles/internal/init_aware_tile_service.cc b/chromium/components/query_tiles/internal/init_aware_tile_service.cc
index 2743462489c..3c0b4743c5b 100644
--- a/chromium/components/query_tiles/internal/init_aware_tile_service.cc
+++ b/chromium/components/query_tiles/internal/init_aware_tile_service.cc
@@ -56,7 +56,7 @@ void InitAwareTileService::GetTile(const std::string& tile_id,
if (IsFailed()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
+ FROM_HERE, base::BindOnce(std::move(callback), absl::nullopt));
return;
}
@@ -123,7 +123,7 @@ void InitAwareTileService::OnTileClicked(const std::string& tile_id) {
}
void InitAwareTileService::OnQuerySelected(
- const base::Optional<std::string>& parent_tile_id,
+ const absl::optional<std::string>& parent_tile_id,
const std::u16string& query_text) {
if (IsReady()) {
tile_service_->OnQuerySelected(std::move(parent_tile_id), query_text);
diff --git a/chromium/components/query_tiles/internal/init_aware_tile_service.h b/chromium/components/query_tiles/internal/init_aware_tile_service.h
index 07e904b36c9..400845f1d23 100644
--- a/chromium/components/query_tiles/internal/init_aware_tile_service.h
+++ b/chromium/components/query_tiles/internal/init_aware_tile_service.h
@@ -9,9 +9,9 @@
#include <memory>
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/query_tiles/internal/tile_service_impl.h"
#include "components/query_tiles/tile_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace query_tiles {
@@ -35,7 +35,7 @@ class InitAwareTileService : public TileService {
void PurgeDb() override;
void SetServerUrl(const std::string& base_url) override;
void OnTileClicked(const std::string& tile_id) override;
- void OnQuerySelected(const base::Optional<std::string>& parent_tile_id,
+ void OnQuerySelected(const absl::optional<std::string>& parent_tile_id,
const std::u16string& query_text) override;
Logger* GetLogger() override;
@@ -52,7 +52,7 @@ class InitAwareTileService : public TileService {
std::deque<base::OnceClosure> cached_api_calls_;
// The initialization result of |tile_service_|.
- base::Optional<bool> init_success_;
+ absl::optional<bool> init_success_;
base::WeakPtrFactory<InitAwareTileService> weak_ptr_factory_{this};
};
diff --git a/chromium/components/query_tiles/internal/init_aware_tile_service_unittest.cc b/chromium/components/query_tiles/internal/init_aware_tile_service_unittest.cc
index 661cb589461..79af4a38bbe 100644
--- a/chromium/components/query_tiles/internal/init_aware_tile_service_unittest.cc
+++ b/chromium/components/query_tiles/internal/init_aware_tile_service_unittest.cc
@@ -7,11 +7,11 @@
#include <memory>
#include "base/callback_helpers.h"
-#include "base/optional.h"
#include "base/test/task_environment.h"
#include "components/query_tiles/internal/tile_service_impl.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using testing::_;
using testing::InSequence;
@@ -49,12 +49,12 @@ class MockInitializableTileService : public InitializableTileService {
MOCK_METHOD(void, OnTileClicked, (const std::string&), (override));
MOCK_METHOD(void,
OnQuerySelected,
- (const base::Optional<std::string>&, const std::u16string&),
+ (const absl::optional<std::string>&, const std::u16string&),
(override));
// Callback stubs.
MOCK_METHOD(void, GetTilesCallbackStub, (TileList), ());
- MOCK_METHOD(void, TileCallbackStub, (base::Optional<Tile>), ());
+ MOCK_METHOD(void, TileCallbackStub, (absl::optional<Tile>), ());
MOCK_METHOD(void, BackgroundTaskFinishedCallbackStub, (bool), ());
private:
@@ -145,7 +145,7 @@ TEST_F(InitAwareTileServiceTest, AfterInitSuccessPassThrough) {
}
EXPECT_CALL(*mock_service(), GetTilesCallbackStub(TileList({Tile()})));
- EXPECT_CALL(*mock_service(), TileCallbackStub(base::make_optional<Tile>()));
+ EXPECT_CALL(*mock_service(), TileCallbackStub(absl::make_optional<Tile>()));
EXPECT_CALL(*mock_service(), BackgroundTaskFinishedCallbackStub(true));
GetQueryTiles();
@@ -165,7 +165,7 @@ TEST_F(InitAwareTileServiceTest, AfterInitFailureNotPassThrough) {
}
EXPECT_CALL(*mock_service(), GetTilesCallbackStub(TileList()));
- EXPECT_CALL(*mock_service(), TileCallbackStub(base::Optional<Tile>()));
+ EXPECT_CALL(*mock_service(), TileCallbackStub(absl::optional<Tile>()));
EXPECT_CALL(*mock_service(), BackgroundTaskFinishedCallbackStub(false));
GetQueryTiles();
@@ -184,7 +184,7 @@ TEST_F(InitAwareTileServiceTest, BeforeInitSuccessFlushedThrough) {
}
EXPECT_CALL(*mock_service(), GetTilesCallbackStub(TileList({Tile()})));
- EXPECT_CALL(*mock_service(), TileCallbackStub(base::make_optional<Tile>()));
+ EXPECT_CALL(*mock_service(), TileCallbackStub(absl::make_optional<Tile>()));
EXPECT_CALL(*mock_service(), BackgroundTaskFinishedCallbackStub(true));
GetQueryTiles();
@@ -204,7 +204,7 @@ TEST_F(InitAwareTileServiceTest, BeforeInitFailureNotFlushedThrough) {
}
EXPECT_CALL(*mock_service(), GetTilesCallbackStub(TileList()));
- EXPECT_CALL(*mock_service(), TileCallbackStub(base::Optional<Tile>()));
+ EXPECT_CALL(*mock_service(), TileCallbackStub(absl::optional<Tile>()));
EXPECT_CALL(*mock_service(), BackgroundTaskFinishedCallbackStub(false));
GetQueryTiles();
diff --git a/chromium/components/query_tiles/internal/log_source.h b/chromium/components/query_tiles/internal/log_source.h
index 56ab92e4ba1..ac3b66f4f29 100644
--- a/chromium/components/query_tiles/internal/log_source.h
+++ b/chromium/components/query_tiles/internal/log_source.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_QUERY_TILES_INTERNAL_LOG_SOURCE_H_
#define COMPONENTS_QUERY_TILES_INTERNAL_LOG_SOURCE_H_
-#include <string>
-
#include "base/observer_list.h"
#include "components/query_tiles/internal/log_sink.h"
#include "components/query_tiles/internal/tile_group.h"
diff --git a/chromium/components/query_tiles/internal/tile_manager.cc b/chromium/components/query_tiles/internal/tile_manager.cc
index eaef1798dab..c24ff33011a 100644
--- a/chromium/components/query_tiles/internal/tile_manager.cc
+++ b/chromium/components/query_tiles/internal/tile_manager.cc
@@ -96,7 +96,7 @@ class TileManagerImpl : public TileManager {
}
}
}
- auto result_tile = result ? base::make_optional(*result) : base::nullopt;
+ auto result_tile = result ? absl::make_optional(*result) : absl::nullopt;
if (result_tile.has_value()) {
// Get the tiles to display, and convert the result vector.
// TODO(qinmin): make GetTile() return a vector of sub tiles, rather than
@@ -275,7 +275,7 @@ class TileManagerImpl : public TileManager {
trending_tile_handler_.OnTileClicked(tile_id);
}
- void OnQuerySelected(const base::Optional<std::string>& parent_tile_id,
+ void OnQuerySelected(const absl::optional<std::string>& parent_tile_id,
const std::u16string& query_text) override {
if (!tile_group_)
return;
diff --git a/chromium/components/query_tiles/internal/tile_manager.h b/chromium/components/query_tiles/internal/tile_manager.h
index 6fea43f17bb..a37a97cd77d 100644
--- a/chromium/components/query_tiles/internal/tile_manager.h
+++ b/chromium/components/query_tiles/internal/tile_manager.h
@@ -10,12 +10,12 @@
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
#include "base/time/clock.h"
#include "components/query_tiles/internal/store.h"
#include "components/query_tiles/internal/tile_group.h"
#include "components/query_tiles/internal/tile_types.h"
#include "components/query_tiles/tile.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace query_tiles {
@@ -25,7 +25,7 @@ class TileManager {
using TileStore = Store<TileGroup>;
using TileGroupStatusCallback = base::OnceCallback<void(TileGroupStatus)>;
using GetTilesCallback = base::OnceCallback<void(std::vector<Tile>)>;
- using TileCallback = base::OnceCallback<void(base::Optional<Tile>)>;
+ using TileCallback = base::OnceCallback<void(absl::optional<Tile>)>;
// Creates the instance.
static std::unique_ptr<TileManager> Create(
@@ -59,7 +59,7 @@ class TileManager {
// Called when the final query is formed. |parent_tile_id| is the parent
// Id of the last tile, if it exists.
virtual void OnQuerySelected(
- const base::Optional<std::string>& parent_tile_id,
+ const absl::optional<std::string>& parent_tile_id,
const std::u16string& query_text) = 0;
TileManager();
diff --git a/chromium/components/query_tiles/internal/tile_manager_unittest.cc b/chromium/components/query_tiles/internal/tile_manager_unittest.cc
index f3d921f0864..8e38cb739af 100644
--- a/chromium/components/query_tiles/internal/tile_manager_unittest.cc
+++ b/chromium/components/query_tiles/internal/tile_manager_unittest.cc
@@ -152,7 +152,7 @@ class TileManagerTest : public testing::Test {
std::move(closure).Run();
}
- void GetSingleTile(const std::string& id, base::Optional<Tile> expected) {
+ void GetSingleTile(const std::string& id, absl::optional<Tile> expected) {
base::RunLoop loop;
manager()->GetTile(
id, base::BindOnce(&TileManagerTest::OnGetTile, base::Unretained(this),
@@ -161,8 +161,8 @@ class TileManagerTest : public testing::Test {
}
void OnGetTile(base::RepeatingClosure closure,
- base::Optional<Tile> expected,
- base::Optional<Tile> actual) {
+ absl::optional<Tile> expected,
+ absl::optional<Tile> actual) {
ASSERT_EQ(expected.has_value(), actual.has_value());
if (expected.has_value())
EXPECT_TRUE(test::AreTilesIdentical(expected.value(), actual.value()));
@@ -314,7 +314,7 @@ TEST_F(TileManagerTest, GetTileById) {
test::ResetTestGroup(&group);
InitWithData(TileGroupStatus::kSuccess, {group});
GetSingleTile("guid-1-1", *group.tiles[0]);
- GetSingleTile("id_not_exist", base::nullopt);
+ GetSingleTile("id_not_exist", absl::nullopt);
}
// Verify that GetTiles will return empty result if no matching AcceptLanguages
@@ -419,7 +419,7 @@ TEST_F(TileManagerTest, GetSingleTileWithTrendingSubTiles) {
parent_tile->sub_tiles = test::GetTestTrendingTileList();
- base::Optional<Tile> parent_tile2 = base::make_optional(*parent_tile.get());
+ absl::optional<Tile> parent_tile2 = absl::make_optional(*parent_tile.get());
parent_tile2->sub_tiles.pop_back();
std::vector<std::unique_ptr<Tile>> tiles_to_save;
@@ -538,8 +538,8 @@ TEST_F(TileManagerTest, GetSingleTileAfterOnTileClicked) {
expected.emplace_back(*parent_tile.get());
Tile trending_3 = *(expected[0].sub_tiles[2]).get();
- base::Optional<Tile> get_single_tile_expected =
- base::make_optional(*parent_tile.get());
+ absl::optional<Tile> get_single_tile_expected =
+ absl::make_optional(*parent_tile.get());
get_single_tile_expected->sub_tiles.pop_back();
std::vector<std::unique_ptr<Tile>> tiles_to_save;
diff --git a/chromium/components/query_tiles/internal/tile_service_impl.cc b/chromium/components/query_tiles/internal/tile_service_impl.cc
index 587d1b75133..bb68d71da72 100644
--- a/chromium/components/query_tiles/internal/tile_service_impl.cc
+++ b/chromium/components/query_tiles/internal/tile_service_impl.cc
@@ -147,7 +147,7 @@ void TileServiceImpl::OnTileClicked(const std::string& tile_id) {
}
void TileServiceImpl::OnQuerySelected(
- const base::Optional<std::string>& parent_tile_id,
+ const absl::optional<std::string>& parent_tile_id,
const std::u16string& query_text) {
tile_manager_->OnQuerySelected(std::move(parent_tile_id), query_text);
}
diff --git a/chromium/components/query_tiles/internal/tile_service_impl.h b/chromium/components/query_tiles/internal/tile_service_impl.h
index 13468f9f6c6..fcc211155ad 100644
--- a/chromium/components/query_tiles/internal/tile_service_impl.h
+++ b/chromium/components/query_tiles/internal/tile_service_impl.h
@@ -57,7 +57,7 @@ class TileServiceImpl : public InitializableTileService,
void PurgeDb() override;
void SetServerUrl(const std::string& base_url) override;
void OnTileClicked(const std::string& tile_id) override;
- void OnQuerySelected(const base::Optional<std::string>& parent_tile_id,
+ void OnQuerySelected(const absl::optional<std::string>& parent_tile_id,
const std::u16string& query_text) override;
Logger* GetLogger() override;
diff --git a/chromium/components/query_tiles/internal/tile_service_impl_unittest.cc b/chromium/components/query_tiles/internal/tile_service_impl_unittest.cc
index 8735a4ee296..ea532d4f726 100644
--- a/chromium/components/query_tiles/internal/tile_service_impl_unittest.cc
+++ b/chromium/components/query_tiles/internal/tile_service_impl_unittest.cc
@@ -45,7 +45,7 @@ class MockTileManager : public TileManager {
MOCK_METHOD(void, OnTileClicked, (const std::string&));
MOCK_METHOD(void,
OnQuerySelected,
- (const base::Optional<std::string>&, const std::u16string&));
+ (const absl::optional<std::string>&, const std::u16string&));
};
class MockTileServiceScheduler : public TileServiceScheduler {
@@ -121,7 +121,7 @@ class TileServiceImplTest : public testing::Test {
}
void OnGetTileDone(const std::string& expected_id,
- base::Optional<Tile> actual_tile) {
+ absl::optional<Tile> actual_tile) {
EXPECT_EQ(expected_id, actual_tile->id);
}
diff --git a/chromium/components/query_tiles/internal/tile_service_scheduler.h b/chromium/components/query_tiles/internal/tile_service_scheduler.h
index e5caf2901ae..27c659e5c52 100644
--- a/chromium/components/query_tiles/internal/tile_service_scheduler.h
+++ b/chromium/components/query_tiles/internal/tile_service_scheduler.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_QUERY_TILES_INTERNAL_TILE_SERVICE_SCHEDULER_H_
#define COMPONENTS_QUERY_TILES_INTERNAL_TILE_SERVICE_SCHEDULER_H_
-#include <memory>
-#include <string>
-
#include "components/background_task_scheduler/background_task_scheduler.h"
#include "components/query_tiles/internal/tile_types.h"
diff --git a/chromium/components/query_tiles/internal/tile_service_scheduler_impl.cc b/chromium/components/query_tiles/internal/tile_service_scheduler_impl.cc
index c1aa465caaa..badee9aae30 100644
--- a/chromium/components/query_tiles/internal/tile_service_scheduler_impl.cc
+++ b/chromium/components/query_tiles/internal/tile_service_scheduler_impl.cc
@@ -67,6 +67,7 @@ void TileServiceSchedulerImpl::OnFetchStarted() {
}
void TileServiceSchedulerImpl::OnFetchCompleted(TileInfoRequestStatus status) {
+ auto first_schedule_time = prefs_->GetTime(kFirstScheduleTimeKey);
MarkFirstRunFinished();
fetcher_status_ = status;
@@ -75,8 +76,7 @@ void TileServiceSchedulerImpl::OnFetchCompleted(TileInfoRequestStatus status) {
// If this task was marked at first attempting flow, record the duration, and
// mark the flow is finished now.
- if (IsDuringFirstFlow()) {
- auto first_schedule_time = prefs_->GetTime(kFirstScheduleTimeKey);
+ if (first_schedule_time != base::Time()) {
auto hours_past = (clock_->Now() - first_schedule_time).InHours();
if (hours_past >= 0) {
stats::RecordFirstFetchFlowDuration(hours_past);
@@ -84,8 +84,7 @@ void TileServiceSchedulerImpl::OnFetchCompleted(TileInfoRequestStatus status) {
}
if (status == TileInfoRequestStatus::kShouldSuspend) {
- MaximizeBackoff();
- ScheduleTask(false);
+ ResetBackoff();
is_suspend_ = true;
} else if (status == TileInfoRequestStatus::kFailure) {
AddBackoff();
@@ -125,8 +124,7 @@ void TileServiceSchedulerImpl::OnTileManagerInitialized(
ScheduleTask(true);
MarkFirstRunScheduled();
} else if (status == TileGroupStatus::kFailureDbOperation) {
- MaximizeBackoff();
- ScheduleTask(false);
+ ResetBackoff();
is_suspend_ = true;
}
stats::RecordTileGroupStatus(status);
@@ -193,15 +191,6 @@ void TileServiceSchedulerImpl::ResetBackoff() {
UpdateBackoff(current.get());
}
-void TileServiceSchedulerImpl::MaximizeBackoff() {
- std::unique_ptr<net::BackoffEntry> current = GetBackoff();
- current->Reset();
- current->SetCustomReleaseTime(
- tick_clock_->NowTicks() +
- base::TimeDelta::FromMilliseconds(backoff_policy_->maximum_backoff_ms));
- UpdateBackoff(current.get());
-}
-
int64_t TileServiceSchedulerImpl::GetDelaysFromBackoff() {
return GetBackoff()->GetTimeUntilRelease().InMilliseconds();
}
@@ -231,9 +220,9 @@ void TileServiceSchedulerImpl::GetTaskWindow(int64_t* start_time_ms,
}
void TileServiceSchedulerImpl::UpdateBackoff(net::BackoffEntry* backoff) {
- std::unique_ptr<base::Value> value =
+ base::Value value =
net::BackoffEntrySerializer::SerializeToValue(*backoff, clock_->Now());
- prefs_->Set(kBackoffEntryKey, *value);
+ prefs_->Set(kBackoffEntryKey, value);
}
void TileServiceSchedulerImpl::MarkFirstRunScheduled() {
diff --git a/chromium/components/query_tiles/internal/tile_service_scheduler_impl.h b/chromium/components/query_tiles/internal/tile_service_scheduler_impl.h
index 10b86c63b07..16bfbabb9f2 100644
--- a/chromium/components/query_tiles/internal/tile_service_scheduler_impl.h
+++ b/chromium/components/query_tiles/internal/tile_service_scheduler_impl.h
@@ -49,7 +49,6 @@ class TileServiceSchedulerImpl : public TileServiceScheduler, public LogSource {
std::unique_ptr<net::BackoffEntry> GetBackoff();
void AddBackoff();
void ResetBackoff();
- void MaximizeBackoff();
int64_t GetDelaysFromBackoff();
void GetInstantTaskWindow(int64_t* start_time_ms,
int64_t* end_time_ms,
@@ -103,4 +102,4 @@ class TileServiceSchedulerImpl : public TileServiceScheduler, public LogSource {
} // namespace query_tiles
-#endif // COMPONENTS_QUERY_TILES_INTERNAL_TILE_SERVICE_SCHEDULER_H_
+#endif // COMPONENTS_QUERY_TILES_INTERNAL_TILE_SERVICE_SCHEDULER_IMPL_H_
diff --git a/chromium/components/query_tiles/internal/tile_service_scheduler_unittest.cc b/chromium/components/query_tiles/internal/tile_service_scheduler_unittest.cc
index 31d748da71c..f3201ceb117 100644
--- a/chromium/components/query_tiles/internal/tile_service_scheduler_unittest.cc
+++ b/chromium/components/query_tiles/internal/tile_service_scheduler_unittest.cc
@@ -96,6 +96,13 @@ class TileServiceSchedulerTest : public testing::Test {
return result;
}
+ void ResetTileServiceScheduler() {
+ auto policy = std::make_unique<net::BackoffEntry::Policy>(kTestPolicy);
+ tile_service_scheduler_ = std::make_unique<TileServiceSchedulerImpl>(
+ &mocked_native_scheduler_, &prefs_, &clock_, &tick_clock_,
+ std::move(policy), log_sink_.get());
+ }
+
private:
base::test::TaskEnvironment task_environment_;
@@ -154,11 +161,24 @@ TEST_F(TileServiceSchedulerTest, OnFetchCompletedSuccessInstantFetchOn) {
}
TEST_F(TileServiceSchedulerTest, OnFetchCompletedSuspend) {
- EXPECT_CALL(*native_scheduler(), Schedule(TaskInfoEq(4000, 4000)));
+ EXPECT_CALL(*native_scheduler(), Schedule(_)).Times(0);
tile_service_scheduler()->OnFetchCompleted(
TileInfoRequestStatus::kShouldSuspend);
auto backoff = GetBackoffPolicy();
- EXPECT_EQ(backoff->GetTimeUntilRelease().InMilliseconds(), 4000);
+ EXPECT_EQ(backoff->GetTimeUntilRelease().InMilliseconds(), 0);
+
+ // Scheduler is in a suspended state, initializing the tile manager will not
+ // schedule any tasks.
+ tile_service_scheduler()->OnTileManagerInitialized(TileGroupStatus::kNoTiles);
+
+ ResetTileServiceScheduler();
+ // A task is rescheduled when scheduler is recreated.
+ auto expected_range_start = TileConfig::GetScheduleIntervalInMs();
+ auto expected_range_end =
+ expected_range_start + TileConfig::GetMaxRandomWindowInMs();
+ EXPECT_CALL(*native_scheduler(),
+ Schedule(TaskInfoEq(expected_range_start, expected_range_end)));
+ tile_service_scheduler()->OnTileManagerInitialized(TileGroupStatus::kNoTiles);
}
// Verify the failure will add delay that using test backoff policy.
@@ -200,9 +220,18 @@ TEST_F(TileServiceSchedulerTest, OnTileGroupLoadedInstantFetchOn) {
}
TEST_F(TileServiceSchedulerTest, OnTileGroupLoadedWithFailure) {
- EXPECT_CALL(*native_scheduler(), Schedule(TaskInfoEq(4000, 4000)));
+ EXPECT_CALL(*native_scheduler(), Schedule(_)).Times(0);
tile_service_scheduler()->OnTileManagerInitialized(
TileGroupStatus::kFailureDbOperation);
+
+ // A task is rescheduled when scheduler is recreated.
+ ResetTileServiceScheduler();
+ auto expected_range_start = TileConfig::GetScheduleIntervalInMs();
+ auto expected_range_end =
+ expected_range_start + TileConfig::GetMaxRandomWindowInMs();
+ EXPECT_CALL(*native_scheduler(),
+ Schedule(TaskInfoEq(expected_range_start, expected_range_end)));
+ tile_service_scheduler()->OnTileManagerInitialized(TileGroupStatus::kNoTiles);
}
TEST_F(TileServiceSchedulerTest, OnTileGroupLoadedWithOtherStatus) {
diff --git a/chromium/components/query_tiles/tile_service.h b/chromium/components/query_tiles/tile_service.h
index e3c75b27b30..6aa7d4e6066 100644
--- a/chromium/components/query_tiles/tile_service.h
+++ b/chromium/components/query_tiles/tile_service.h
@@ -9,11 +9,11 @@
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
#include "base/supports_user_data.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/query_tiles/logger.h"
#include "components/query_tiles/tile.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace gfx {
class Image;
@@ -23,7 +23,7 @@ namespace query_tiles {
using TileList = std::vector<Tile>;
using GetTilesCallback = base::OnceCallback<void(TileList)>;
-using TileCallback = base::OnceCallback<void(base::Optional<Tile>)>;
+using TileCallback = base::OnceCallback<void(absl::optional<Tile>)>;
using VisualsCallback = base::OnceCallback<void(const gfx::Image&)>;
using BackgroundTaskFinishedCallback = base::OnceCallback<void(bool)>;
@@ -56,7 +56,7 @@ class TileService : public KeyedService, public base::SupportsUserData {
// Called when the final level of tile is selected. |parent_tile_id| is
// the Id of the parent tile, if it exists.
virtual void OnQuerySelected(
- const base::Optional<std::string>& parent_tile_id,
+ const absl::optional<std::string>& parent_tile_id,
const std::u16string& query_text) = 0;
// Returns a Logger instance that is meant to be used by logging and debug UI
diff --git a/chromium/components/quirks/pref_names.h b/chromium/components/quirks/pref_names.h
index a73065b678c..44777c04a97 100644
--- a/chromium/components/quirks/pref_names.h
+++ b/chromium/components/quirks/pref_names.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_QUIRKS_PREF_NAMES_H
-#define COMPONENTS_QUIRKS_PREF_NAMES_H
+#ifndef COMPONENTS_QUIRKS_PREF_NAMES_H_
+#define COMPONENTS_QUIRKS_PREF_NAMES_H_
namespace quirks {
namespace prefs {
@@ -13,4 +13,4 @@ extern const char kQuirksClientLastServerCheck[];
} // namespace prefs
} // namespace quirks
-#endif // COMPONENTS_PROXIMITY_AUTH_BLE_PREF_NAMES_H
+#endif // COMPONENTS_QUIRKS_PREF_NAMES_H_
diff --git a/chromium/components/reading_list/core/offline_url_utils.cc b/chromium/components/reading_list/core/offline_url_utils.cc
index c8c08937108..a1d31f2ccbb 100644
--- a/chromium/components/reading_list/core/offline_url_utils.cc
+++ b/chromium/components/reading_list/core/offline_url_utils.cc
@@ -6,7 +6,6 @@
#include "base/hash/md5.h"
#include "base/notreached.h"
-#include "base/strings/stringprintf.h"
namespace {
const base::FilePath::CharType kOfflineDirectory[] =
diff --git a/chromium/components/reading_list/core/reading_list_entry.cc b/chromium/components/reading_list/core/reading_list_entry.cc
index e346848a103..42cfdeb4eb1 100644
--- a/chromium/components/reading_list/core/reading_list_entry.cc
+++ b/chromium/components/reading_list/core/reading_list_entry.cc
@@ -597,12 +597,12 @@ ReadingListEntry::AsReadingListLocal(const base::Time& now) const {
pb_entry->set_failed_download_counter(failed_download_counter_);
if (backoff_) {
- std::unique_ptr<base::Value> backoff =
+ base::Value backoff =
net::BackoffEntrySerializer::SerializeToValue(*backoff_, now);
std::string output;
JSONStringValueSerializer serializer(&output);
- serializer.Serialize(*backoff);
+ serializer.Serialize(backoff);
pb_entry->set_backoff(output);
}
diff --git a/chromium/components/reading_list/core/reading_list_model_impl.cc b/chromium/components/reading_list/core/reading_list_model_impl.cc
index 2c6f9e5dde9..4bce004cbf4 100644
--- a/chromium/components/reading_list/core/reading_list_model_impl.cc
+++ b/chromium/components/reading_list/core/reading_list_model_impl.cc
@@ -337,7 +337,7 @@ const ReadingListEntry& ReadingListModelImpl::AddEntry(
DCHECK(loaded());
DCHECK(IsUrlSupported(url));
std::unique_ptr<ReadingListModel::ScopedReadingListBatchUpdate>
- scoped_model_batch_updates = nullptr;
+ scoped_model_batch_updates;
if (GetEntryByURL(url)) {
scoped_model_batch_updates = BeginBatchUpdates();
RemoveEntryByURL(url);
diff --git a/chromium/components/reading_list/core/reading_list_model_observer.h b/chromium/components/reading_list/core/reading_list_model_observer.h
index a0ad2bf3951..3884fbadc39 100644
--- a/chromium/components/reading_list/core/reading_list_model_observer.h
+++ b/chromium/components/reading_list/core/reading_list_model_observer.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_READING_LIST_CORE_READING_LIST_MODEL_OBSERVER_H_
#define COMPONENTS_READING_LIST_CORE_READING_LIST_MODEL_OBSERVER_H_
-#include <set>
-#include <vector>
-
#include "components/reading_list/core/reading_list_entry.h"
class GURL;
diff --git a/chromium/components/reading_list/core/reading_list_model_unittest.cc b/chromium/components/reading_list/core/reading_list_model_unittest.cc
index 2d32acd339e..4cdcb3c7629 100644
--- a/chromium/components/reading_list/core/reading_list_model_unittest.cc
+++ b/chromium/components/reading_list/core/reading_list_model_unittest.cc
@@ -107,24 +107,24 @@ class TestReadingListStorage : public ReadingListModelStorage {
}
std::unique_ptr<ScopedBatchUpdate> EnsureBatchCreated() override {
- return std::unique_ptr<ScopedBatchUpdate>();
+ return nullptr;
}
// Syncing is not used in this test class.
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override {
NOTREACHED();
- return std::unique_ptr<syncer::MetadataChangeList>();
+ return nullptr;
}
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override {
NOTREACHED();
return {};
}
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override {
NOTREACHED();
diff --git a/chromium/components/reading_list/core/reading_list_store.cc b/chromium/components/reading_list/core/reading_list_store.cc
index 20a9cd93e75..d165103b213 100644
--- a/chromium/components/reading_list/core/reading_list_store.cc
+++ b/chromium/components/reading_list/core/reading_list_store.cc
@@ -113,7 +113,7 @@ void ReadingListStore::RemoveEntry(const ReadingListEntry& entry) {
}
void ReadingListStore::OnDatabaseLoad(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore::RecordList> entries) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (error) {
@@ -148,7 +148,7 @@ void ReadingListStore::OnDatabaseLoad(
}
void ReadingListStore::OnReadAllMetadata(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (error) {
@@ -159,12 +159,12 @@ void ReadingListStore::OnReadAllMetadata(
}
void ReadingListStore::OnDatabaseSave(
- const base::Optional<syncer::ModelError>& error) {
+ const absl::optional<syncer::ModelError>& error) {
return;
}
void ReadingListStore::OnStoreCreated(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore> store) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (error) {
@@ -196,7 +196,7 @@ ReadingListStore::CreateMetadataChangeList() {
// Durable storage writes, if not able to combine all change atomically, should
// save the metadata after the data changes, so that this merge will be re-
// driven by sync if is not completely saved during the current run.
-base::Optional<syncer::ModelError> ReadingListStore::MergeSyncData(
+absl::optional<syncer::ModelError> ReadingListStore::MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -282,7 +282,7 @@ base::Optional<syncer::ModelError> ReadingListStore::MergeSyncData(
// |metadata_change_list| in case when some of the data changes are filtered
// out, or even be empty in case when a commit confirmation is processed and
// only the metadata needs to persisted.
-base::Optional<syncer::ModelError> ReadingListStore::ApplySyncChanges(
+absl::optional<syncer::ModelError> ReadingListStore::ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chromium/components/reading_list/core/reading_list_store.h b/chromium/components/reading_list/core/reading_list_store.h
index c01984743ea..f9e4471da34 100644
--- a/chromium/components/reading_list/core/reading_list_store.h
+++ b/chromium/components/reading_list/core/reading_list_store.h
@@ -57,7 +57,7 @@ class ReadingListStore : public ReadingListModelStorage {
// atomically, should save the metadata after the data changes, so that this
// merge will be re-driven by sync if is not completely saved during the
// current run.
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
@@ -66,7 +66,7 @@ class ReadingListStore : public ReadingListModelStorage {
// |metadata_change_list| in case when some of the data changes are filtered
// out, or even be empty in case when a commit confirmation is processed and
// only the metadata needs to persisted.
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
@@ -127,7 +127,7 @@ class ReadingListStore : public ReadingListModelStorage {
std::string GetStorageKey(const syncer::EntityData& entity_data) override;
// Methods used as callbacks given to DataTypeStore.
- void OnStoreCreated(const base::Optional<syncer::ModelError>& error,
+ void OnStoreCreated(const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore> store);
class ScopedBatchUpdate : public ReadingListModelStorage::ScopedBatchUpdate {
@@ -147,10 +147,10 @@ class ReadingListStore : public ReadingListModelStorage {
void CommitTransaction();
// Callbacks needed for the database handling.
void OnDatabaseLoad(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore::RecordList> entries);
- void OnDatabaseSave(const base::Optional<syncer::ModelError>& error);
- void OnReadAllMetadata(const base::Optional<syncer::ModelError>& error,
+ void OnDatabaseSave(const absl::optional<syncer::ModelError>& error);
+ void OnReadAllMetadata(const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch);
void AddEntryToBatch(syncer::MutableDataBatch* batch,
diff --git a/chromium/components/remote_cocoa/app_shim/BUILD.gn b/chromium/components/remote_cocoa/app_shim/BUILD.gn
index ecdbb7e50c8..7f009340014 100644
--- a/chromium/components/remote_cocoa/app_shim/BUILD.gn
+++ b/chromium/components/remote_cocoa/app_shim/BUILD.gn
@@ -50,6 +50,8 @@ component("app_shim") {
"views_nswindow_delegate.mm",
"views_scrollbar_bridge.h",
"views_scrollbar_bridge.mm",
+ "window_controls_overlay_nsview.h",
+ "window_controls_overlay_nsview.mm",
"window_move_loop.h",
"window_move_loop.mm",
"window_touch_bar_delegate.h",
diff --git a/chromium/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm b/chromium/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
index 69580888047..cf88f696a46 100644
--- a/chromium/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
+++ b/chromium/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
@@ -65,23 +65,6 @@
@implementation BrowserNativeWidgetWindow
-// Prevent detached tabs from glitching when the window is partially offscreen.
-// See https://crbug.com/1095717 for details.
-// This is easy to get wrong so scope very tightly to only disallow large
-// vertical jumps.
-- (NSRect)constrainFrameRect:(NSRect)rect toScreen:(NSScreen*)screen {
- NSRect proposed = [super constrainFrameRect:rect toScreen:screen];
- // This boils down to: use the small threshold when we're not avoiding a
- // Dock on the bottom, and the big threshold otherwise.
- static constexpr CGFloat kBigThreshold = 200;
- static constexpr CGFloat kSmallThreshold = 50;
- const CGFloat yDelta = NSMaxY(proposed) - NSMaxY(rect);
- if (yDelta > kBigThreshold ||
- (yDelta > kSmallThreshold && NSMinY(proposed) == 0))
- return rect;
- return proposed;
-}
-
// NSWindow (PrivateAPI) overrides.
+ (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle {
diff --git a/chromium/components/remote_cocoa/app_shim/color_panel_bridge.mm b/chromium/components/remote_cocoa/app_shim/color_panel_bridge.mm
index c4f51e955c2..1ad75ab1c8c 100644
--- a/chromium/components/remote_cocoa/app_shim/color_panel_bridge.mm
+++ b/chromium/components/remote_cocoa/app_shim/color_panel_bridge.mm
@@ -39,7 +39,7 @@ remote_cocoa::ColorPanelBridge* g_current_panel_bridge = nullptr;
@end
@implementation ColorPanelListener
-- (id)init {
+- (instancetype)init {
if ((self = [super init])) {
NSColorPanel* panel = [NSColorPanel sharedColorPanel];
[[NSNotificationCenter defaultCenter]
diff --git a/chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h b/chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
index e03bbc724cf..5a23ea75588 100644
--- a/chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
+++ b/chromium/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
@@ -52,6 +52,11 @@ REMOTE_COCOA_APP_SHIM_EXPORT
// create one.
- (void)setWindowTouchBarDelegate:(id<WindowTouchBarDelegate>)delegate;
+// Enforce that this window never be made visible. In the event that it is made
+// visible, it will log a crash report.
+// https://crbug.com/960904
+- (void)enforceNeverMadeVisible;
+
// Identifier for the NativeWidgetMac from which this window was created. This
// may be used to look up the NativeWidgetMacNSWindowHost in the browser process
// or the NativeWidgetNSWindowBridge in a display process.
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 44a574ee1a1..f4104fe938b 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
@@ -4,6 +4,7 @@
#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
+#include "base/debug/dump_without_crashing.h"
#include "base/mac/foundation_util.h"
#include "base/trace_event/trace_event.h"
#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
@@ -81,6 +82,7 @@
uint64_t _bridgedNativeWidgetId;
remote_cocoa::NativeWidgetNSWindowBridge* _bridge;
BOOL _willUpdateRestorableState;
+ BOOL _isEnforcingNeverMadeVisible;
}
@synthesize bridgedNativeWidgetId = _bridgedNativeWidgetId;
@synthesize bridge = _bridge;
@@ -103,11 +105,41 @@
// inserting a symbol on NativeWidgetMacNSWindow and should be kept even if it
// does nothing.
- (void)dealloc {
+ if (_isEnforcingNeverMadeVisible) {
+ [self removeObserver:self forKeyPath:@"visible"];
+ }
_willUpdateRestorableState = YES;
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[super dealloc];
}
+- (void)enforceNeverMadeVisible {
+ if (_isEnforcingNeverMadeVisible)
+ return;
+ _isEnforcingNeverMadeVisible = YES;
+ [self addObserver:self
+ forKeyPath:@"visible"
+ options:NSKeyValueObservingOptionNew
+ context:nil];
+}
+
+- (void)observeValueForKeyPath:(NSString*)keyPath
+ ofObject:(id)object
+ change:(NSDictionary*)change
+ context:(void*)context {
+ if ([keyPath isEqual:@"visible"]) {
+ DCHECK(_isEnforcingNeverMadeVisible);
+ DCHECK_EQ(object, self);
+ DCHECK_EQ(context, nil);
+ if ([change[NSKeyValueChangeNewKey] boolValue])
+ base::debug::DumpWithoutCrashing();
+ }
+ [super observeValueForKeyPath:keyPath
+ ofObject:object
+ change:change
+ context:context];
+}
+
// Public methods.
- (void)setCommandDispatcherDelegate:(id<CommandDispatcherDelegate>)delegate {
@@ -327,6 +359,7 @@
return;
if (![self _isConsideredOpenForPersistentState])
return;
+
base::scoped_nsobject<NSMutableData> restorableStateData(
[[NSMutableData alloc] init]);
base::scoped_nsobject<NSKeyedArchiver> encoder([[NSKeyedArchiver alloc]
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 624af21b7f6..b4655c1c2b3 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
@@ -30,6 +30,7 @@
@class ModalShowAnimationWithLayer;
@class NativeWidgetMacNSWindow;
@class ViewsNSWindowDelegate;
+@class WindowControlsOverlayNSView;
namespace views {
namespace test {
@@ -248,6 +249,11 @@ class REMOTE_COCOA_APP_SHIM_EXPORT NativeWidgetNSWindowBridge
void ReleaseCapture() override;
void RedispatchKeyEvent(
const std::vector<uint8_t>& native_event_data) override;
+ void CreateWindowControlsOverlayNSView(
+ const mojom::WindowControlsOverlayNSViewType overlay_type) override;
+ void UpdateWindowControlsOverlayNSView(
+ const gfx::Rect& bounds,
+ const mojom::WindowControlsOverlayNSViewType overlay_type) override;
// Return true if [NSApp updateWindows] needs to be called after updating the
// TextInputClient.
@@ -287,6 +293,9 @@ class REMOTE_COCOA_APP_SHIM_EXPORT NativeWidgetNSWindowBridge
// Returns true if capture exists and is currently active.
bool HasCapture();
+ // Returns true if window restoration data exists from session restore.
+ bool HasWindowRestorationData();
+
// CocoaMouseCaptureDelegate:
void PostCapturedEvent(NSEvent* event) override;
void OnMouseCaptureLost() override;
@@ -312,6 +321,14 @@ class REMOTE_COCOA_APP_SHIM_EXPORT NativeWidgetNSWindowBridge
ui::ModalType modal_type_ = ui::MODAL_TYPE_NONE;
bool is_translucent_window_ = false;
+ // Intended for PWAs with window controls overlay display override. These two
+ // NSViews are added on top of the non client area to route events to the
+ // BridgedContentView instead of the RenderWidgetHostView.
+ base::scoped_nsobject<WindowControlsOverlayNSView>
+ caption_buttons_overlay_nsview_;
+ base::scoped_nsobject<WindowControlsOverlayNSView>
+ web_app_frame_toolbar_overlay_nsview_;
+
NativeWidgetNSWindowBridge* parent_ =
nullptr; // Weak. If non-null, owns this.
std::vector<NativeWidgetNSWindowBridge*> child_windows_;
@@ -369,7 +386,7 @@ class REMOTE_COCOA_APP_SHIM_EXPORT NativeWidgetNSWindowBridge
bool invalidate_shadow_on_frame_swap_ = false;
// A blob representing the window's saved state, which is applied and cleared
- // the first time it's shown.
+ // on the first call to SetVisibilityState().
std::vector<uint8_t> pending_restoration_data_;
mojo::AssociatedReceiver<remote_cocoa::mojom::NativeWidgetNSWindow>
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 fedf4e36b6d..def66d5040d 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
@@ -28,6 +28,7 @@
#import "components/remote_cocoa/app_shim/native_widget_ns_window_host_helper.h"
#include "components/remote_cocoa/app_shim/select_file_dialog_bridge.h"
#import "components/remote_cocoa/app_shim/views_nswindow_delegate.h"
+#import "components/remote_cocoa/app_shim/window_controls_overlay_nsview.h"
#import "components/remote_cocoa/app_shim/window_move_loop.h"
#include "components/remote_cocoa/common/native_widget_ns_window_host.mojom.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
@@ -653,6 +654,33 @@ void NativeWidgetNSWindowBridge::CloseWindowNow() {
void NativeWidgetNSWindowBridge::SetVisibilityState(
WindowVisibilityState new_state) {
+ // During session restore this method gets called from RestoreTabsToBrowser()
+ // with new_state = kShowAndActivateWindow. We consume restoration data on our
+ // first time through this method so we can use its existence as an
+ // indication that session restoration is underway. We'll use this later to
+ // decide whether or not to actually honor the WindowVisibilityState change
+ // request. This window may live in the dock, for example, in which case we
+ // don't really want to kShowAndActivateWindow. Even if the window is on the
+ // desktop we still won't want to kShowAndActivateWindow because doing so
+ // might trigger a transition to a different space (and we don't want to
+ // switch spaces on start-up). When session restore determines the Active
+ // window it will also call SetVisibilityState(), on that pass the window
+ // can/will be activated.
+ bool session_restore_in_progress = false;
+
+ // Restore Cocoa window state.
+ if (HasWindowRestorationData()) {
+ NSData* restore_ns_data =
+ [NSData dataWithBytes:pending_restoration_data_.data()
+ length:pending_restoration_data_.size()];
+ base::scoped_nsobject<NSKeyedUnarchiver> decoder(
+ [[NSKeyedUnarchiver alloc] initForReadingWithData:restore_ns_data]);
+ [window_ restoreStateWithCoder:decoder];
+ pending_restoration_data_.clear();
+
+ session_restore_in_progress = true;
+ }
+
// Ensure that:
// - A window with an invisible parent is not made visible.
// - A parent changing visibility updates child window visibility.
@@ -694,20 +722,11 @@ void NativeWidgetNSWindowBridge::SetVisibilityState(
return;
}
- if (!pending_restoration_data_.empty()) {
- NSData* restore_ns_data =
- [NSData dataWithBytes:pending_restoration_data_.data()
- length:pending_restoration_data_.size()];
- base::scoped_nsobject<NSKeyedUnarchiver> decoder(
- [[NSKeyedUnarchiver alloc] initForReadingWithData:restore_ns_data]);
- [window_ restoreStateWithCoder:decoder];
- pending_restoration_data_.clear();
-
- // When first showing a window with restoration data, don't activate it.
- // This avoids switching spaces or un-miniaturizing it right away.
- // Additional activations act normally.
- if (new_state == WindowVisibilityState::kShowAndActivateWindow)
- new_state = WindowVisibilityState::kShowInactive;
+ // Don't activate a window during session restore, to avoid switching spaces
+ // (or pulling it out of the dock) during startup.
+ if (session_restore_in_progress &&
+ new_state == WindowVisibilityState::kShowAndActivateWindow) {
+ new_state = WindowVisibilityState::kShowInactive;
}
if (IsWindowModalSheet()) {
@@ -779,6 +798,10 @@ bool NativeWidgetNSWindowBridge::HasCapture() {
return mouse_capture_ && mouse_capture_->IsActive();
}
+bool NativeWidgetNSWindowBridge::HasWindowRestorationData() {
+ return !pending_restoration_data_.empty();
+}
+
bool NativeWidgetNSWindowBridge::RunMoveLoop(const gfx::Vector2d& drag_offset) {
// https://crbug.com/876493
CHECK(!HasCapture());
@@ -1121,6 +1144,35 @@ bool NativeWidgetNSWindowBridge::RedispatchKeyEvent(NSEvent* event) {
return [[window_ commandDispatcher] redispatchKeyEvent:event];
}
+void NativeWidgetNSWindowBridge::CreateWindowControlsOverlayNSView(
+ const mojom::WindowControlsOverlayNSViewType overlay_type) {
+ switch (overlay_type) {
+ case mojom::WindowControlsOverlayNSViewType::kCaptionButtonContainer:
+ caption_buttons_overlay_nsview_.reset(
+ [[WindowControlsOverlayNSView alloc] initWithBridge:this]);
+ [bridged_view_ addSubview:caption_buttons_overlay_nsview_];
+ break;
+ case mojom::WindowControlsOverlayNSViewType::kWebAppFrameToolbar:
+ web_app_frame_toolbar_overlay_nsview_.reset(
+ [[WindowControlsOverlayNSView alloc] initWithBridge:this]);
+ [bridged_view_ addSubview:web_app_frame_toolbar_overlay_nsview_];
+ break;
+ }
+}
+
+void NativeWidgetNSWindowBridge::UpdateWindowControlsOverlayNSView(
+ const gfx::Rect& bounds,
+ const mojom::WindowControlsOverlayNSViewType overlay_type) {
+ switch (overlay_type) {
+ case mojom::WindowControlsOverlayNSViewType::kCaptionButtonContainer:
+ [caption_buttons_overlay_nsview_ updateBounds:bounds];
+ break;
+ case mojom::WindowControlsOverlayNSViewType::kWebAppFrameToolbar:
+ [web_app_frame_toolbar_overlay_nsview_ updateBounds:bounds];
+ break;
+ }
+}
+
NSWindow* NativeWidgetNSWindowBridge::ns_window() {
return window_.get();
}
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 29cbf996c43..d62ec1081f6 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
@@ -101,7 +101,8 @@ NSSavePanel* g_last_created_panel_for_testing = nil;
base::scoped_nsobject<NSArray> _fileTypeLists;
}
-- (id)initWithDialog:(NSSavePanel*)dialog fileTypeLists:(NSArray*)fileTypeLists;
+- (instancetype)initWithDialog:(NSSavePanel*)dialog
+ fileTypeLists:(NSArray*)fileTypeLists;
- (void)popupAction:(id)sender;
@end
@@ -128,8 +129,8 @@ NSSavePanel* g_last_created_panel_for_testing = nil;
@implementation ExtensionDropdownHandler
-- (id)initWithDialog:(NSSavePanel*)dialog
- fileTypeLists:(NSArray*)fileTypeLists {
+- (instancetype)initWithDialog:(NSSavePanel*)dialog
+ fileTypeLists:(NSArray*)fileTypeLists {
if ((self = [super init])) {
_dialog = dialog;
_fileTypeLists.reset([fileTypeLists retain]);
diff --git a/chromium/components/remote_cocoa/app_shim/views_nswindow_delegate.h b/chromium/components/remote_cocoa/app_shim/views_nswindow_delegate.h
index 93fefce9db7..291913e5046 100644
--- a/chromium/components/remote_cocoa/app_shim/views_nswindow_delegate.h
+++ b/chromium/components/remote_cocoa/app_shim/views_nswindow_delegate.h
@@ -8,8 +8,8 @@
#import <Cocoa/Cocoa.h>
#import "base/mac/scoped_nsobject.h"
-#include "base/optional.h"
#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace remote_cocoa {
class NativeWidgetNSWindowBridge;
@@ -22,7 +22,7 @@ REMOTE_COCOA_APP_SHIM_EXPORT
@private
remote_cocoa::NativeWidgetNSWindowBridge* _parent; // Weak. Owns this.
base::scoped_nsobject<NSCursor> _cursor;
- base::Optional<float> _aspectRatio;
+ absl::optional<float> _aspectRatio;
// Only valid during a live resize.
// Used to keep track of whether a resize is happening horizontally or
@@ -34,7 +34,7 @@ REMOTE_COCOA_APP_SHIM_EXPORT
// stick to it. This is necessary to achieve stable results, because in order
// to keep the aspect ratio fixed we override one window dimension with a
// value computed from the other dimension.
- base::Optional<bool> _resizingHorizontally;
+ absl::optional<bool> _resizingHorizontally;
}
// If set, the cursor set in -[NSResponder updateCursor:] when the window is
diff --git a/chromium/components/remote_cocoa/app_shim/views_scrollbar_bridge.h b/chromium/components/remote_cocoa/app_shim/views_scrollbar_bridge.h
index 9b7fca269bb..8e52bcc7d6c 100644
--- a/chromium/components/remote_cocoa/app_shim/views_scrollbar_bridge.h
+++ b/chromium/components/remote_cocoa/app_shim/views_scrollbar_bridge.h
@@ -38,4 +38,4 @@ REMOTE_COCOA_APP_SHIM_EXPORT
@end
-#endif
+#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_VIEWS_SCROLLBAR_BRIDGE_H_
diff --git a/chromium/components/remote_cocoa/app_shim/window_controls_overlay_nsview.h b/chromium/components/remote_cocoa/app_shim/window_controls_overlay_nsview.h
new file mode 100644
index 00000000000..86b3e82a50c
--- /dev/null
+++ b/chromium/components/remote_cocoa/app_shim/window_controls_overlay_nsview.h
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_CONTROLS_OVERLAY_NSVIEW_H_
+#define COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_CONTROLS_OVERLAY_NSVIEW_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace remote_cocoa {
+class NativeWidgetNSWindowBridge;
+} // namespace remote_cocoa
+
+REMOTE_COCOA_APP_SHIM_EXPORT
+@interface WindowControlsOverlayNSView : NSView {
+ @private
+ // Weak.
+ remote_cocoa::NativeWidgetNSWindowBridge* _bridge;
+}
+@property(readonly, nonatomic) remote_cocoa::NativeWidgetNSWindowBridge* bridge;
+
+- (instancetype)initWithBridge:
+ (remote_cocoa::NativeWidgetNSWindowBridge*)bridge;
+
+- (void)updateBounds:(gfx::Rect)bounds;
+@end
+
+#endif // COMPONENTS_REMOTE_COCOA_APP_SHIM_WINDOW_CONTROLS_OVERLAY_NSVIEW_H_
diff --git a/chromium/components/remote_cocoa/app_shim/window_controls_overlay_nsview.mm b/chromium/components/remote_cocoa/app_shim/window_controls_overlay_nsview.mm
new file mode 100644
index 00000000000..24afac6904b
--- /dev/null
+++ b/chromium/components/remote_cocoa/app_shim/window_controls_overlay_nsview.mm
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "components/remote_cocoa/app_shim/window_controls_overlay_nsview.h"
+
+@implementation WindowControlsOverlayNSView
+
+@synthesize bridge = _bridge;
+
+- (instancetype)initWithBridge:
+ (remote_cocoa::NativeWidgetNSWindowBridge*)bridge {
+ if ((self = [super initWithFrame:NSZeroRect])) {
+ _bridge = bridge;
+ }
+ return self;
+}
+
+- (NSView*)hitTest:(NSPoint)point {
+ NSPoint pointInView = [self convertPoint:point fromView:self.superview];
+ // This NSView is directly above NonClientView. We want to route events
+ // to BridgedContentView so the right view in NonClientArea can consume them
+ // instead of going to RenderWidgetHostView.
+ if (NSPointInRect(pointInView, self.visibleRect))
+ return self.superview;
+ return [super hitTest:point];
+}
+
+- (void)updateBounds:(gfx::Rect)bounds {
+ NSRect frameRect = bounds.ToCGRect();
+ frameRect.origin.y = NSHeight(self.superview.bounds) - frameRect.origin.y -
+ NSHeight(frameRect);
+ [self setFrame:frameRect];
+}
+
+@end
diff --git a/chromium/components/remote_cocoa/app_shim/window_move_loop.h b/chromium/components/remote_cocoa/app_shim/window_move_loop.h
index 1a3f6c6b001..cb92808c203 100644
--- a/chromium/components/remote_cocoa/app_shim/window_move_loop.h
+++ b/chromium/components/remote_cocoa/app_shim/window_move_loop.h
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
+#include "ui/gfx/mac/scoped_cocoa_disable_screen_updates.h"
namespace remote_cocoa {
class NativeWidgetNSWindowBridge;
@@ -42,6 +43,8 @@ class CocoaWindowMoveLoop {
LoopExitReason* exit_reason_ref_ = nullptr;
base::OnceClosure quit_closure_;
+ std::unique_ptr<gfx::ScopedCocoaDisableScreenUpdates> screen_disabler_;
+
// WeakPtrFactory for event monitor safety.
base::WeakPtrFactory<CocoaWindowMoveLoop> weak_factory_;
diff --git a/chromium/components/remote_cocoa/app_shim/window_move_loop.mm b/chromium/components/remote_cocoa/app_shim/window_move_loop.mm
index dea9ab6b9f4..66dc541768c 100644
--- a/chromium/components/remote_cocoa/app_shim/window_move_loop.mm
+++ b/chromium/components/remote_cocoa/app_shim/window_move_loop.mm
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "components/remote_cocoa/app_shim/window_move_loop.h"
+#include <memory>
#include "base/debug/stack_trace.h"
#include "base/run_loop.h"
@@ -80,6 +81,9 @@ bool CocoaWindowMoveLoop::Run() {
[[[WeakCocoaWindowMoveLoop alloc]
initWithWeakPtr:weak_factory_.GetWeakPtr()] autorelease];
+ __block BOOL has_moved = NO;
+ screen_disabler_ = std::make_unique<gfx::ScopedCocoaDisableScreenUpdates>();
+
// Esc keypress is handled by EscapeTracker, which is installed by
// TabDragController.
NSEventMask mask =
@@ -104,8 +108,13 @@ bool CocoaWindowMoveLoop::Run() {
NSRect ns_frame = NSOffsetRect(
initial_frame, mouse_in_screen.x - initial_mouse_in_screen_.x,
mouse_in_screen.y - initial_mouse_in_screen_.y);
- ns_frame = [window constrainFrameRect:ns_frame toScreen:window.screen];
[window setFrame:ns_frame display:NO animate:NO];
+ // `setFrame:...` may have destroyed `this`, so do the weak check again.
+ bool is_valid = [weak_cocoa_window_move_loop weak].get() == strong;
+ if (is_valid && !has_moved) {
+ has_moved = YES;
+ strong->screen_disabler_.reset();
+ }
return event;
}
@@ -136,6 +145,7 @@ bool CocoaWindowMoveLoop::Run() {
}
void CocoaWindowMoveLoop::End() {
+ screen_disabler_.reset();
if (exit_reason_ref_) {
DCHECK_EQ(*exit_reason_ref_, ENDED_EXTERNALLY);
// Ensure the destructor doesn't replace the reason.
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 1a8b77dab65..8456bffc87c 100644
--- a/chromium/components/remote_cocoa/common/native_widget_ns_window.mojom
+++ b/chromium/components/remote_cocoa/common/native_widget_ns_window.mojom
@@ -79,6 +79,11 @@ struct NativeWidgetNSWindowInitParams {
array<uint8> state_restoration_data;
};
+enum WindowControlsOverlayNSViewType {
+ kCaptionButtonContainer,
+ kWebAppFrameToolbar,
+};
+
// The interface through which a NativeWidgetMac may interact with an NSWindow
// (possibly in a process separate from the browser process).
interface NativeWidgetNSWindow {
@@ -220,4 +225,14 @@ interface NativeWidgetNSWindow {
// Redispatch a keyboard event using the widget's window's CommandDispatcher.
RedispatchKeyEvent(array<uint8> native_event_data);
+
+ // Add the overlay NSView for a PWA with window controls overlay
+ // display override given a |overlay_type|.
+ CreateWindowControlsOverlayNSView(
+ WindowControlsOverlayNSViewType overlay_type);
+
+ // Update the overlay NSView with |bounds| for a PWA with window controls
+ // overlay display override for a |overlay_type|.
+ UpdateWindowControlsOverlayNSView(
+ gfx.mojom.Rect bounds, WindowControlsOverlayNSViewType overlay_type);
};
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 62100403d27..6585ac1d019 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
@@ -169,6 +169,7 @@ RenderViewContextMenuBase::RenderViewContextMenuBase(
render_frame_id_(render_frame_host->GetRoutingID()),
render_frame_token_(render_frame_host->GetFrameToken()),
render_process_id_(render_frame_host->GetProcess()->GetID()),
+ site_instance_(render_frame_host->GetSiteInstance()),
command_executed_(false) {}
RenderViewContextMenuBase::~RenderViewContextMenuBase() {
@@ -476,6 +477,8 @@ void RenderViewContextMenuBase::OpenURLWithExtraHeaders(
open_url_params.initiator_process_id = render_process_id_;
open_url_params.initiator_origin = url::Origin::Create(referring_url);
+ open_url_params.source_site_instance = site_instance_;
+
if (disposition != WindowOpenDisposition::OFF_THE_RECORD)
open_url_params.impression = params_.impression;
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 52002b190fd..051953091fd 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
@@ -19,6 +19,7 @@
#include "components/renderer_context_menu/render_view_context_menu_observer.h"
#include "components/renderer_context_menu/render_view_context_menu_proxy.h"
#include "content/public/browser/context_menu_params.h"
+#include "content/public/browser/site_instance.h"
#include "ppapi/buildflags/buildflags.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "ui/base/models/simple_menu_model.h"
@@ -191,6 +192,9 @@ class RenderViewContextMenuBase : public ui::SimpleMenuModel::Delegate,
// The RenderFrameHost's IDs.
const int render_process_id_;
+ // Renderer's frame SiteInstance.
+ scoped_refptr<content::SiteInstance> site_instance_;
+
// Our observers.
mutable base::ObserverList<RenderViewContextMenuObserver>::Unchecked
observers_;
diff --git a/chromium/components/reporting/client/mock_report_queue.h b/chromium/components/reporting/client/mock_report_queue.h
index 27c79d1c311..15340bdbdb7 100644
--- a/chromium/components/reporting/client/mock_report_queue.h
+++ b/chromium/components/reporting/client/mock_report_queue.h
@@ -6,8 +6,6 @@
#define COMPONENTS_REPORTING_CLIENT_MOCK_REPORT_QUEUE_H_
#include "base/callback.h"
-#include "base/values.h"
-#include "components/reporting/client/mock_report_queue.h"
#include "components/reporting/client/report_queue.h"
#include "components/reporting/proto/record.pb.h"
#include "components/reporting/proto/record_constants.pb.h"
diff --git a/chromium/components/reporting/client/report_queue_provider.cc b/chromium/components/reporting/client/report_queue_provider.cc
index ff2ddf662ac..f6c1e20c133 100644
--- a/chromium/components/reporting/client/report_queue_provider.cc
+++ b/chromium/components/reporting/client/report_queue_provider.cc
@@ -30,7 +30,7 @@ bool ReportQueueProvider::IsEncryptedReportingPipelineEnabled() {
// static
const base::Feature ReportQueueProvider::kEncryptedReportingPipeline{
- "EncryptedReportingPipeline", base::FEATURE_DISABLED_BY_DEFAULT};
+ "EncryptedReportingPipeline", base::FEATURE_ENABLED_BY_DEFAULT};
ReportQueueProvider::ReportQueueProvider()
: create_request_queue_(SharedQueue<CreateReportQueueRequest>::Create()),
@@ -67,8 +67,6 @@ void ReportQueueProvider::OnInitState(bool provider_configured) {
if (!provider_configured) {
// Schedule an InitializingContext to take care of initialization.
InitializingContext* const context = InstantiateInitializingContext(
- base::BindOnce(&ReportQueueProvider::OnConfigResult,
- base::Unretained(this)),
base::BindOnce(&ReportQueueProvider::OnInitializationComplete,
base::Unretained(this)),
init_state_tracker_);
@@ -83,11 +81,6 @@ void ReportQueueProvider::OnInitState(bool provider_configured) {
&ReportQueueProvider::BuildRequestQueue, base::Unretained(this)));
}
-void ReportQueueProvider::OnConfigResult(
- base::OnceCallback<void(Status)> continue_init_cb) {
- std::move(continue_init_cb).Run(Status::StatusOK());
-}
-
void ReportQueueProvider::OnInitializationComplete(Status init_status) {
if (init_status.error_code() == error::RESOURCE_EXHAUSTED) {
// This happens when a new request comes in while the ReportQueueProvider is
@@ -177,12 +170,10 @@ ReportQueueProvider::CreateReportQueueRequest::create_cb() {
// InitializingContext implementation.
ReportQueueProvider::InitializingContext::InitializingContext(
- UpdateConfigurationCallback update_config_cb,
InitCompleteCallback init_complete_cb,
scoped_refptr<ReportQueueProvider::InitializationStateTracker>
init_state_tracker)
- : update_config_cb_(std::move(update_config_cb)),
- init_state_tracker_(init_state_tracker),
+ : init_state_tracker_(init_state_tracker),
init_complete_cb_(std::move(init_complete_cb)) {}
ReportQueueProvider::InitializingContext::~InitializingContext() = default;
@@ -210,13 +201,14 @@ void ReportQueueProvider::InitializingContext::OnLeaderPromotionResult(
base::Unretained(this)));
}
-void ReportQueueProvider::InitializingContext::OnCompleted() {
- std::move(update_config_cb_)
- .Run(base::BindOnce(&InitializingContext::Complete,
- base::Unretained(this)));
-}
-
void ReportQueueProvider::InitializingContext::Complete(Status status) {
+ if (status.error_code() == error::RESOURCE_EXHAUSTED) {
+ // There is already a leader initializing the ReportQueueProvider.
+ std::move(init_complete_cb_).Run(status);
+ delete this;
+ return;
+ }
+
if (status.ok()) {
// Export the results to the provider.
OnCompleted();
@@ -226,6 +218,7 @@ void ReportQueueProvider::InitializingContext::Complete(Status status) {
// update the provider.
status = Status::StatusOK();
}
+
std::move(release_leader_cb_).Run(/*initialization_successful=*/status.ok());
std::move(init_complete_cb_).Run(status);
delete this;
@@ -289,6 +282,7 @@ void ReportQueueProvider::InitializationStateTracker::OnLeaderPromotionRequest(
result = Status(error::RESOURCE_EXHAUSTED,
"ReportClient already has a lead initializing context.");
} else {
+ has_promoted_initializing_context_ = true;
result = base::BindOnce(
&ReportQueueProvider::InitializationStateTracker::ReleaseLeader, this);
}
@@ -320,4 +314,4 @@ void ReportQueueProvider::InitializationStateTracker::OnLeaderRelease(
has_promoted_initializing_context_ = false;
}
-} // namespace reporting \ No newline at end of file
+} // namespace reporting
diff --git a/chromium/components/reporting/client/report_queue_provider.h b/chromium/components/reporting/client/report_queue_provider.h
index ea7d6040c11..5d961f66f2f 100644
--- a/chromium/components/reporting/client/report_queue_provider.h
+++ b/chromium/components/reporting/client/report_queue_provider.h
@@ -6,7 +6,6 @@
#define COMPONENTS_REPORTING_CLIENT_REPORT_QUEUE_PROVIDER_H_
#include <memory>
-#include <string>
#include <utility>
#include "base/callback.h"
@@ -166,7 +165,7 @@ class ReportQueueProvider {
// (for non-trivial initialization needs to be subclassed).
// Once Start is called, it can post an arbitrary set of callbacks
// to appropriate threads, and then collects the result back.
- // Once the result is collected, needs to makes a call to |Complete|
+ // Once the result is collected, needs to make a call to |Complete|
// passing resulting status (if status is OK, |OnCompleted| will be
// called, and it may update the |ReportQueueProvider|).
// In order to substitute the context, override
@@ -174,12 +173,10 @@ class ReportQueueProvider {
//
// Example:
// InitializingContext* InstantiateInitializingContext(
- // InitializingContext::UpdateConfigurationCallback update_config_cb,
// InitCompleteCallback init_complete_cb,
// scoped_refptr<InitializationStateTracker> init_state_tracker,
// ...more parameters as needed...) override {
- // return new InitializingContextImpl(std::move(update_config_cb),
- // std::move(init_complete_cb),
+ // return new InitializingContextImpl(std::move(init_complete_cb),
// init_state_tracker,
// ...more parameters as needed...,
// this);
@@ -188,13 +185,11 @@ class ReportQueueProvider {
// : public ReportQueueProvider::InitializingContext {
// public:
// InitializingContextImpl(
- // UpdateConfigurationCallback update_config_cb,
// InitCompleteCallback init_complete_cb,
// scoped_refptr<InitializationStateTracker> init_state_tracker,
// ...more parameters as needed...,
// ReportQueueProviderImpl* provider)
- // : InitializingContext(std::move(update_config_cb),
- // std::move(init_complete_cb),
+ // : InitializingContext(std::move(init_complete_cb),
// init_state_tracker),
// ...saving parameters to the context,
// provider_(provider) {
@@ -247,11 +242,7 @@ class ReportQueueProvider {
using InitCompleteCallback = base::OnceCallback<void(Status)>;
class InitializingContext {
public:
- using UpdateConfigurationCallback =
- base::OnceCallback<void(base::OnceCallback<void(Status)>)>;
-
InitializingContext(
- UpdateConfigurationCallback update_config_cb,
InitCompleteCallback init_complete_cb,
scoped_refptr<InitializationStateTracker> init_state_tracker);
@@ -270,7 +261,7 @@ class ReportQueueProvider {
// Called if |Complete| got a success.
// Needs to be overridden to update the provider.
- virtual void OnCompleted();
+ virtual void OnCompleted() = 0;
private:
// Called Upon leader promotion: OK means we are a leader and initialization
@@ -285,7 +276,6 @@ class ReportQueueProvider {
// initialization.
virtual void OnStart() = 0;
- UpdateConfigurationCallback update_config_cb_;
InitializationStateTracker::ReleaseLeaderCallback release_leader_cb_;
scoped_refptr<InitializationStateTracker> init_state_tracker_;
@@ -313,13 +303,9 @@ class ReportQueueProvider {
// Result owned by itself (passed to InitializingContext::Start and
// self-destructs upon InitializingContext::Complete call).
virtual InitializingContext* InstantiateInitializingContext(
- InitializingContext::UpdateConfigurationCallback update_config_cb,
InitCompleteCallback init_complete_cb,
scoped_refptr<InitializationStateTracker> init_state_tracker) = 0;
- virtual void OnConfigResult(
- base::OnceCallback<void(Status)> continue_init_cb);
-
// Creates and initializes queue implementation. Returns status in case of
// error.
virtual CreateReportQueueResponse CreateNewQueue(
diff --git a/chromium/components/reporting/client/report_queue_provider_unttest.cc b/chromium/components/reporting/client/report_queue_provider_unttest.cc
index 16cefc2b967..98445e21062 100644
--- a/chromium/components/reporting/client/report_queue_provider_unttest.cc
+++ b/chromium/components/reporting/client/report_queue_provider_unttest.cc
@@ -35,11 +35,9 @@ namespace {
class MockReportQueueProvider : public ReportQueueProvider {
public:
InitializingContext* InstantiateInitializingContext(
- InitializingContext::UpdateConfigurationCallback update_config_cb,
InitCompleteCallback init_complete_cb,
scoped_refptr<InitializationStateTracker> init_state_tracker) override {
- return new MockInitializingContext(std::move(update_config_cb),
- std::move(init_complete_cb),
+ return new MockInitializingContext(std::move(init_complete_cb),
init_state_tracker, this);
}
@@ -56,13 +54,10 @@ class MockReportQueueProvider : public ReportQueueProvider {
: public ReportQueueProvider::InitializingContext {
public:
MockInitializingContext(
- UpdateConfigurationCallback update_config_cb,
InitCompleteCallback init_complete_cb,
scoped_refptr<InitializationStateTracker> init_state_tracker,
MockReportQueueProvider* provider)
- : InitializingContext(std::move(update_config_cb),
- std::move(init_complete_cb),
- init_state_tracker),
+ : InitializingContext(std::move(init_complete_cb), init_state_tracker),
provider_(provider) {
DCHECK(provider_ != nullptr);
}
@@ -91,12 +86,6 @@ class MockReportQueueProvider : public ReportQueueProvider {
class ReportQueueProviderTest : public ::testing::Test {
protected:
- void SetUp() override {
- // Enable reporting.
- scoped_feature_list_.InitAndEnableFeature(
- reporting::ReportQueueProvider::kEncryptedReportingPipeline);
- }
-
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
diff --git a/chromium/components/reporting/encryption/decryption.h b/chromium/components/reporting/encryption/decryption.h
index cf9eddae943..839a6ef9bad 100644
--- a/chromium/components/reporting/encryption/decryption.h
+++ b/chromium/components/reporting/encryption/decryption.h
@@ -11,13 +11,13 @@
#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/reporting/encryption/encryption.h"
#include "components/reporting/util/status.h"
#include "components/reporting/util/statusor.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace reporting {
namespace test {
diff --git a/chromium/components/reporting/encryption/encryption.h b/chromium/components/reporting/encryption/encryption.h
index eea82c3cdda..5e6608bddbb 100644
--- a/chromium/components/reporting/encryption/encryption.h
+++ b/chromium/components/reporting/encryption/encryption.h
@@ -11,11 +11,11 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "components/reporting/proto/record.pb.h"
#include "components/reporting/util/status.h"
#include "components/reporting/util/statusor.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace reporting {
@@ -103,7 +103,7 @@ class Encryptor : public base::RefCountedThreadSafe<Encryptor> {
~Encryptor();
// Public key used for asymmetric encryption of symmetric key and its id.
- base::Optional<std::pair<std::string, PublicKeyId>> asymmetric_key_;
+ absl::optional<std::pair<std::string, PublicKeyId>> asymmetric_key_;
// Sequential task runner for all asymmetric_key_ activities: update, read.
scoped_refptr<base::SequencedTaskRunner>
diff --git a/chromium/components/reporting/encryption/encryption_module_interface.h b/chromium/components/reporting/encryption/encryption_module_interface.h
index 4a752ff07dc..5154f9ab79c 100644
--- a/chromium/components/reporting/encryption/encryption_module_interface.h
+++ b/chromium/components/reporting/encryption/encryption_module_interface.h
@@ -24,7 +24,7 @@ class EncryptionModuleInterface
using PublicKeyId = int32_t;
// Feature to enable/disable encryption.
- // By default encryption is disabled, until server can support decryption.
+ // By default encryption is disabled.
static const char kEncryptedReporting[];
explicit EncryptionModuleInterface(
@@ -58,7 +58,6 @@ class EncryptionModuleInterface
bool need_encryption_key() const;
// Returns 'true' if |kEncryptedReporting| feature is enabled.
- // To be removed once encryption becomes mandatory.
static bool is_enabled();
protected:
diff --git a/chromium/components/reporting/encryption/encryption_module_unittest.cc b/chromium/components/reporting/encryption/encryption_module_unittest.cc
index a036ab79d19..f2f69d4a038 100644
--- a/chromium/components/reporting/encryption/encryption_module_unittest.cc
+++ b/chromium/components/reporting/encryption/encryption_module_unittest.cc
@@ -165,7 +165,7 @@ TEST_F(EncryptionModuleTest, EncryptAndDecrypt) {
TEST_F(EncryptionModuleTest, EncryptionDisabled) {
constexpr char kTestString[] = "ABCDEF";
- // Disable encryption.
+ // Disable encryption for this test.
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitFromCommandLine(
{}, {EncryptionModuleInterface::kEncryptedReporting});
diff --git a/chromium/components/reporting/proto/record.proto b/chromium/components/reporting/proto/record.proto
index 1d20fc9591c..4afd91249d3 100644
--- a/chromium/components/reporting/proto/record.proto
+++ b/chromium/components/reporting/proto/record.proto
@@ -56,10 +56,10 @@ message WrappedRecord {
// Information about how the record was encrypted.
message EncryptionInfo {
// Encryption key (optional).
- // Represents a symmetric key used for |encrypted_wrapped_record|
- // encryption; itself encrypted with asymmetric encryption by a public key.
- // The private portion of the key is known to the receiver only, and
- // identified with the |public_key_id|.
+ // Represents the client's X25519 public key used along with the server's
+ // private key (identified by |public_key_id|) for shared secret recreation
+ // by the server to get the symmetric key used for |encrypted_wrapped_record|
+ // encryption.
optional bytes encryption_key = 1;
// Public key id (optional)
diff --git a/chromium/components/reporting/proto/record_constants.proto b/chromium/components/reporting/proto/record_constants.proto
index 618fe9b36af..eab5c904201 100644
--- a/chromium/components/reporting/proto/record_constants.proto
+++ b/chromium/components/reporting/proto/record_constants.proto
@@ -45,6 +45,9 @@ enum Destination {
// |EXTENSIONS_WORKFLOW| handler is for sending extension requests events,
// sent for Chrome Browser Cloud Management (CBCM).
EXTENSIONS_WORKFLOW = 10;
+
+ // |DLP_EVENTS| events send from data leakage protection for Chrome OS
+ DLP_EVENTS = 11;
}
// |Priority| is used to determine when items from the queue should be rate
diff --git a/chromium/components/reporting/storage/resources/resource_interface.h b/chromium/components/reporting/storage/resources/resource_interface.h
index a2b30299fbe..9da9cf2dc7c 100644
--- a/chromium/components/reporting/storage/resources/resource_interface.h
+++ b/chromium/components/reporting/storage/resources/resource_interface.h
@@ -7,7 +7,7 @@
#include <cstdint>
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace reporting {
@@ -67,7 +67,7 @@ class ScopedReservation {
private:
ResourceInterface* const resource_interface_;
- base::Optional<uint64_t> size_;
+ absl::optional<uint64_t> size_;
};
ResourceInterface* GetMemoryResource();
diff --git a/chromium/components/reporting/storage/storage.cc b/chromium/components/reporting/storage/storage.cc
index 83640c76d79..c8100a2b5d8 100644
--- a/chromium/components/reporting/storage/storage.cc
+++ b/chromium/components/reporting/storage/storage.cc
@@ -122,7 +122,7 @@ class Storage::QueueUploaderInterface : public UploaderInterface {
static void AsyncProvideUploader(
Priority priority,
Storage* storage,
- UploaderInterface::UploaderInterfaceResultCb start_uploader_cb) {
+ UploaderInterfaceResultCb start_uploader_cb) {
storage->async_start_upload_cb_.Run(
priority,
/*need_encryption_key=*/EncryptionModuleInterface::is_enabled() &&
@@ -157,7 +157,7 @@ class Storage::QueueUploaderInterface : public UploaderInterface {
private:
static void WrapInstantiatedUploader(
Priority priority,
- UploaderInterface::UploaderInterfaceResultCb start_uploader_cb,
+ UploaderInterfaceResultCb start_uploader_cb,
StatusOr<std::unique_ptr<UploaderInterface>> uploader_result) {
if (!uploader_result.ok()) {
std::move(start_uploader_cb).Run(uploader_result.status());
@@ -375,7 +375,7 @@ class Storage::KeyInStorage {
// Enumerates found key files and locates one with the highest index and
// valid key. Returns pair of file name and loaded signed key proto.
// Called once, during initialization.
- base::Optional<std::pair<base::FilePath, SignedEncryptionInfo>>
+ absl::optional<std::pair<base::FilePath, SignedEncryptionInfo>>
LocateValidKeyAndParse(
const base::flat_map<uint64_t, base::FilePath>& found_key_files) {
// Try to unserialize the key from each found file (latest first).
@@ -426,7 +426,7 @@ class Storage::KeyInStorage {
}
// Not found, return error.
- return base::nullopt;
+ return absl::nullopt;
}
// Index of the file to serialize the signed key to.
@@ -500,11 +500,14 @@ void Storage::Create(
} else {
if (EncryptionModuleInterface::is_enabled()) {
// Initiate upload with need_encryption_key flag and no records.
+ UploaderInterface::UploaderInterfaceResultCb start_uploader_cb =
+ base::BindOnce(&StorageInitContext::EncryptionKeyReceiverReady);
storage_->async_start_upload_cb_.Run(
/*priority=*/MANUAL_BATCH, // Any priority would do.
/*need_encryption_key=*/true,
- base::BindOnce(&StorageInitContext::EncryptionKeyReceiverReady,
- base::Unretained(this)));
+ base::BindOnce(&StorageInitContext::WrapInstantiatedKeyUploader,
+ /*priority=*/MANUAL_BATCH,
+ std::move(start_uploader_cb)));
// Continue initialization without waiting for it to respond.
// Until the response arrives, we will reject Enqueues.
}
@@ -527,7 +530,20 @@ void Storage::Create(
}
}
- void EncryptionKeyReceiverReady(
+ static void WrapInstantiatedKeyUploader(
+ Priority priority,
+ UploaderInterface::UploaderInterfaceResultCb start_uploader_cb,
+ StatusOr<std::unique_ptr<UploaderInterface>> uploader_result) {
+ if (!uploader_result.ok()) {
+ std::move(start_uploader_cb).Run(uploader_result.status());
+ return;
+ }
+ std::move(start_uploader_cb)
+ .Run(std::make_unique<QueueUploaderInterface>(
+ priority, std::move(uploader_result.ValueOrDie())));
+ }
+
+ static void EncryptionKeyReceiverReady(
StatusOr<std::unique_ptr<UploaderInterface>> uploader_result) {
if (uploader_result.ok()) {
uploader_result.ValueOrDie()->Completed(Status::StatusOK());
@@ -605,7 +621,7 @@ void Storage::Write(Priority priority,
}
void Storage::Confirm(Priority priority,
- base::Optional<int64_t> seq_number,
+ absl::optional<int64_t> seq_number,
bool force,
base::OnceCallback<void(Status)> completion_cb) {
// Note: queues_ never change after initialization is finished, so there is
@@ -645,9 +661,18 @@ void Storage::UpdateEncryptionKey(SignedEncryptionInfo signed_encryption_key) {
}));
// Serialize whole signed_encryption_key to a new file, discard the old
- // one(s).
- const Status status = key_in_storage_->UploadKeyFile(signed_encryption_key);
- LOG_IF(ERROR, !status.ok()) << "Failed to upload the new encription key.";
+ // one(s). Do it on a thread which may block doing file operations.
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
+ base::BindOnce(
+ [](SignedEncryptionInfo signed_encryption_key,
+ KeyInStorage* key_in_storage) {
+ const Status status =
+ key_in_storage->UploadKeyFile(signed_encryption_key);
+ LOG_IF(ERROR, !status.ok())
+ << "Failed to upload the new encription key.";
+ },
+ std::move(signed_encryption_key), key_in_storage_.get()));
}
StatusOr<scoped_refptr<StorageQueue>> Storage::GetQueue(Priority priority) {
diff --git a/chromium/components/reporting/storage/storage.h b/chromium/components/reporting/storage/storage.h
index cf0bffcd1c5..6578d5d75f5 100644
--- a/chromium/components/reporting/storage/storage.h
+++ b/chromium/components/reporting/storage/storage.h
@@ -7,12 +7,10 @@
#include <map>
#include <memory>
-#include <string>
#include <utility>
#include "base/callback.h"
#include "base/containers/flat_map.h"
-#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/string_piece.h"
@@ -53,7 +51,7 @@ class Storage : public base::RefCountedThreadSafe<Storage> {
// only accepted if no higher ids were confirmed before; otherwise it is
// accepted unconditionally.
void Confirm(Priority priority,
- base::Optional<int64_t> sequencing_id,
+ absl::optional<int64_t> sequencing_id,
bool force,
base::OnceCallback<void(Status)> completion_cb);
diff --git a/chromium/components/reporting/storage/storage_module.h b/chromium/components/reporting/storage/storage_module.h
index 31c5a21f035..a4f3af5739a 100644
--- a/chromium/components/reporting/storage/storage_module.h
+++ b/chromium/components/reporting/storage/storage_module.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_REPORTING_STORAGE_STORAGE_MODULE_H_
#define COMPONENTS_REPORTING_STORAGE_STORAGE_MODULE_H_
-#include <utility>
-
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
diff --git a/chromium/components/reporting/storage/storage_module_interface.h b/chromium/components/reporting/storage/storage_module_interface.h
index ed5ff52eecb..f4b301de1ea 100644
--- a/chromium/components/reporting/storage/storage_module_interface.h
+++ b/chromium/components/reporting/storage/storage_module_interface.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_REPORTING_STORAGE_STORAGE_MODULE_INTERFACE_H_
#define COMPONENTS_REPORTING_STORAGE_STORAGE_MODULE_INTERFACE_H_
-#include <utility>
-
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
diff --git a/chromium/components/reporting/storage/storage_queue.cc b/chromium/components/reporting/storage/storage_queue.cc
index c0a6c37de79..988d5d910b9 100644
--- a/chromium/components/reporting/storage/storage_queue.cc
+++ b/chromium/components/reporting/storage/storage_queue.cc
@@ -24,7 +24,6 @@
#include "base/hash/hash.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/rand_util.h"
#include "base/sequence_checker.h"
#include "base/strings/strcat.h"
@@ -46,6 +45,7 @@
#include "components/reporting/util/task_runner_context.h"
#include "crypto/random.h"
#include "crypto/sha2.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h"
namespace reporting {
@@ -144,7 +144,7 @@ StorageQueue::~StorageQueue() {
DCHECK_CALLED_ON_VALID_SEQUENCE(storage_queue_sequence_checker_);
// Stop upload timer.
- upload_timer_.Stop();
+ upload_timer_.AbandonAndStop();
// Make sure no pending writes is present.
DCHECK(write_contexts_queue_.empty());
@@ -199,8 +199,8 @@ Status StorageQueue::Init() {
// Some of them might have been changed earlier.
next_sequencing_id_ = 0;
first_sequencing_id_ = 0;
- first_unconfirmed_sequencing_id_ = base::nullopt;
- last_record_digest_ = base::nullopt;
+ first_unconfirmed_sequencing_id_ = absl::nullopt;
+ last_record_digest_ = absl::nullopt;
ReleaseAllFileInstances();
used_files_set.clear();
}
@@ -215,7 +215,7 @@ Status StorageQueue::Init() {
return Status::StatusOK();
}
-base::Optional<std::string> StorageQueue::GetLastRecordDigest() const {
+absl::optional<std::string> StorageQueue::GetLastRecordDigest() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(storage_queue_sequence_checker_);
// Attach last record digest, if present.
return last_record_digest_;
@@ -255,7 +255,7 @@ Status StorageQueue::EnumerateDataFiles(
// We need to set first_sequencing_id_ to 0 if this is the initialization
// of an empty StorageQueue, and to the lowest sequencing id among all
// existing files, if it was already used.
- base::Optional<int64_t> first_sequencing_id;
+ absl::optional<int64_t> first_sequencing_id;
base::FileEnumerator dir_enum(
options_.directory(),
/*recursive=*/false, base::FileEnumerator::FILES,
@@ -664,6 +664,9 @@ class StorageQueue::ReadContext : public TaskRunnerContext<Status> {
base::Unretained(this)),
storage_queue->sequenced_task_runner_),
async_start_upload_cb_(storage_queue->async_start_upload_cb_),
+ must_invoke_upload_(
+ EncryptionModuleInterface::is_enabled() &&
+ storage_queue->encryption_module_->need_encryption_key()),
storage_queue_weakptr_factory_{storage_queue.get()} {
DCHECK(storage_queue.get());
DCHECK(async_start_upload_cb_);
@@ -682,26 +685,16 @@ class StorageQueue::ReadContext : public TaskRunnerContext<Status> {
Response(Status(error::UNAVAILABLE, "StorageQueue shut down"));
return;
}
- base::ThreadPool::PostTask(
- FROM_HERE, {base::TaskPriority::BEST_EFFORT},
- base::BindOnce(
- [](ReadContext* self) {
- self->async_start_upload_cb_.Run(
- base::BindOnce(&ReadContext::ScheduleOnUploaderInstantiated,
- base::Unretained(self)));
- },
- base::Unretained(this)));
- }
+ if (!must_invoke_upload_) {
+ PrepareDataFiles();
+ return;
+ }
- void ScheduleOnUploaderInstantiated(
- StatusOr<std::unique_ptr<UploaderInterface>> uploader_result) {
- Schedule(base::BindOnce(&ReadContext::OnUploaderInstantiated,
- base::Unretained(this),
- std::move(uploader_result)));
+ InstantiateUploader(
+ base::BindOnce(&ReadContext::PrepareDataFiles, base::Unretained(this)));
}
- void OnUploaderInstantiated(
- StatusOr<std::unique_ptr<UploaderInterface>> uploader_result) {
+ void PrepareDataFiles() {
DCHECK_CALLED_ON_VALID_SEQUENCE(read_sequence_checker_);
base::WeakPtr<StorageQueue> storage_queue =
storage_queue_weakptr_factory_.GetWeakPtr();
@@ -709,16 +702,6 @@ class StorageQueue::ReadContext : public TaskRunnerContext<Status> {
Response(Status(error::UNAVAILABLE, "StorageQueue shut down"));
return;
}
- if (!uploader_result.ok()) {
- Response(Status(error::FAILED_PRECONDITION,
- base::StrCat({"Failed to provide the Uploader, status=",
- uploader_result.status().ToString()})));
- return;
- }
- DCHECK(!uploader_)
- << "Uploader instantiated more than once for single upload";
- uploader_ = std::move(uploader_result.ValueOrDie());
-
// Fill in initial sequencing information to track progress:
// use minimum of first_sequencing_id_ and first_unconfirmed_sequencing_id_
// if the latter has been recorded.
@@ -760,6 +743,25 @@ class StorageQueue::ReadContext : public TaskRunnerContext<Status> {
// Register with storage_queue, to make sure selected files are not removed.
++(storage_queue->active_read_operations_);
+ if (uploader_) {
+ // Uploader already created.
+ BeginUploading();
+ return;
+ }
+
+ InstantiateUploader(
+ base::BindOnce(&ReadContext::BeginUploading, base::Unretained(this)));
+ }
+
+ void BeginUploading() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(read_sequence_checker_);
+ base::WeakPtr<StorageQueue> storage_queue =
+ storage_queue_weakptr_factory_.GetWeakPtr();
+ if (!storage_queue) {
+ Response(Status(error::UNAVAILABLE, "StorageQueue shut down"));
+ return;
+ }
+
// The first <seq.file> pair is the current file now, and we are at its
// start or ahead of it.
current_file_ = files_.begin();
@@ -1038,12 +1040,50 @@ class StorageQueue::ReadContext : public TaskRunnerContext<Status> {
// Resume at ScheduleNextRecord.
}
+ void InstantiateUploader(base::OnceCallback<void()> continuation) {
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(
+ [](base::OnceCallback<void()> continuation, ReadContext* self) {
+ self->async_start_upload_cb_.Run(base::BindOnce(
+ &ReadContext::ScheduleOnUploaderInstantiated,
+ base::Unretained(self), std::move(continuation)));
+ },
+ std::move(continuation), base::Unretained(this)));
+ }
+
+ void ScheduleOnUploaderInstantiated(
+ base::OnceCallback<void()> continuation,
+ StatusOr<std::unique_ptr<UploaderInterface>> uploader_result) {
+ Schedule(base::BindOnce(&ReadContext::OnUploaderInstantiated,
+ base::Unretained(this), std::move(continuation),
+ std::move(uploader_result)));
+ }
+
+ void OnUploaderInstantiated(
+ base::OnceCallback<void()> continuation,
+ StatusOr<std::unique_ptr<UploaderInterface>> uploader_result) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(read_sequence_checker_);
+ if (!uploader_result.ok()) {
+ Response(Status(error::FAILED_PRECONDITION,
+ base::StrCat({"Failed to provide the Uploader, status=",
+ uploader_result.status().ToString()})));
+ return;
+ }
+ DCHECK(!uploader_)
+ << "Uploader instantiated more than once for single upload";
+ uploader_ = std::move(uploader_result.ValueOrDie());
+
+ std::move(continuation).Run();
+ }
+
// Files that will be read (in order of sequencing ids).
std::map<int64_t, scoped_refptr<SingleFile>> files_;
SequencingInformation sequencing_info_;
uint32_t current_pos_;
std::map<int64_t, scoped_refptr<SingleFile>>::iterator current_file_;
const AsyncStartUploaderCb async_start_upload_cb_;
+ const bool must_invoke_upload_;
std::unique_ptr<UploaderInterface> uploader_;
base::WeakPtrFactory<StorageQueue> storage_queue_weakptr_factory_;
@@ -1331,7 +1371,7 @@ StorageQueue::CollectFilesForUpload(int64_t sequencing_id) const {
class StorageQueue::ConfirmContext : public TaskRunnerContext<Status> {
public:
- ConfirmContext(base::Optional<int64_t> sequencing_id,
+ ConfirmContext(absl::optional<int64_t> sequencing_id,
bool force,
base::OnceCallback<void(Status)> end_callback,
scoped_refptr<StorageQueue> storage_queue)
@@ -1362,7 +1402,7 @@ class StorageQueue::ConfirmContext : public TaskRunnerContext<Status> {
}
// Confirmed sequencing id.
- base::Optional<int64_t> sequencing_id_;
+ absl::optional<int64_t> sequencing_id_;
bool force_;
@@ -1371,7 +1411,7 @@ class StorageQueue::ConfirmContext : public TaskRunnerContext<Status> {
SEQUENCE_CHECKER(confirm_sequence_checker_);
};
-void StorageQueue::Confirm(base::Optional<int64_t> sequencing_id,
+void StorageQueue::Confirm(absl::optional<int64_t> sequencing_id,
bool force,
base::OnceCallback<void(Status)> completion_cb) {
Start<ConfirmContext>(sequencing_id, force, std::move(completion_cb), this);
@@ -1496,7 +1536,7 @@ void StorageQueue::SingleFile::Close() {
return;
}
handle_.reset();
- is_readonly_ = base::nullopt;
+ is_readonly_ = absl::nullopt;
if (buffer_) {
buffer_.reset();
GetMemoryResource()->Discard(buffer_size_);
diff --git a/chromium/components/reporting/storage/storage_queue.h b/chromium/components/reporting/storage/storage_queue.h
index 758b626a3ea..f68aab522e2 100644
--- a/chromium/components/reporting/storage/storage_queue.h
+++ b/chromium/components/reporting/storage/storage_queue.h
@@ -19,7 +19,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread.h"
@@ -31,6 +30,7 @@
#include "components/reporting/storage/storage_uploader_interface.h"
#include "components/reporting/util/status.h"
#include "components/reporting/util/statusor.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace reporting {
@@ -73,7 +73,7 @@ class StorageQueue : public base::RefCountedDeleteOnSequence<StorageQueue> {
// only accepted if no higher ids were confirmed before; otherwise it is
// accepted unconditionally.
// Helper methods: RemoveConfirmedData.
- void Confirm(base::Optional<int64_t> sequencing_id,
+ void Confirm(absl::optional<int64_t> sequencing_id,
bool force,
base::OnceCallback<void(Status)> completion_cb);
@@ -169,7 +169,7 @@ class StorageQueue : public base::RefCountedDeleteOnSequence<StorageQueue> {
// Flag (valid for opened file only): true if file was opened for reading
// only, false otherwise.
- base::Optional<bool> is_readonly_;
+ absl::optional<bool> is_readonly_;
const base::FilePath filename_; // relative to the StorageQueue directory
uint64_t size_ = 0; // tracked internally rather than by filesystem
@@ -203,7 +203,7 @@ class StorageQueue : public base::RefCountedDeleteOnSequence<StorageQueue> {
Status Init();
// Retrieves last record digest (does not exist at a generation start).
- base::Optional<std::string> GetLastRecordDigest() const;
+ absl::optional<std::string> GetLastRecordDigest() const;
// Helper method for Init(): process single data file.
// Return sequencing_id from <prefix>.<sequencing_id> file name, or Status
@@ -293,7 +293,7 @@ class StorageQueue : public base::RefCountedDeleteOnSequence<StorageQueue> {
// Digest of the last written record (loaded at queue initialization, absent
// if the new generation has just started, and no records where stored yet).
- base::Optional<std::string> last_record_digest_;
+ absl::optional<std::string> last_record_digest_;
// Queue of the write context instances in the order of creation, sequencing
// ids and record digests. Context is always removed from this queue before
@@ -315,7 +315,7 @@ class StorageQueue : public base::RefCountedDeleteOnSequence<StorageQueue> {
// If first_unconfirmed_sequencing_id_ < first_sequencing_id_,
// [first_unconfirmed_sequencing_id_, first_sequencing_id_) is a gap
// that cannot be filled in and is uploaded as such.
- base::Optional<int64_t> first_unconfirmed_sequencing_id_;
+ absl::optional<int64_t> first_unconfirmed_sequencing_id_;
// Latest metafile. May be null.
scoped_refptr<SingleFile> meta_file_;
diff --git a/chromium/components/reporting/storage/storage_queue_stress_test.cc b/chromium/components/reporting/storage/storage_queue_stress_test.cc
index fb06691e0ed..d7062e3bc87 100644
--- a/chromium/components/reporting/storage/storage_queue_stress_test.cc
+++ b/chromium/components/reporting/storage/storage_queue_stress_test.cc
@@ -13,7 +13,6 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/optional.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
@@ -30,6 +29,7 @@
#include "crypto/sha2.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using ::testing::_;
using ::testing::Between;
@@ -56,7 +56,7 @@ class TestUploadClient : public UploaderInterface {
// generation is uploaded without last record digest.
using LastRecordDigestMap = base::flat_map<
std::pair<int64_t /*generation id */, int64_t /*sequencing id*/>,
- base::Optional<std::string /*digest*/>>;
+ absl::optional<std::string /*digest*/>>;
explicit TestUploadClient(LastRecordDigestMap* last_record_digest_map)
: last_record_digest_map_(last_record_digest_map) {}
@@ -115,7 +115,7 @@ class TestUploadClient : public UploaderInterface {
void Completed(Status status) override { ASSERT_OK(status); }
private:
- base::Optional<int64_t> generation_id_;
+ absl::optional<int64_t> generation_id_;
LastRecordDigestMap* const last_record_digest_map_;
Sequence test_upload_sequence_;
@@ -135,7 +135,6 @@ class StorageQueueStressTest : public ::testing::TestWithParam<size_t> {
void TearDown() override {
ResetTestStorageQueue();
- task_environment_.RunUntilIdle();
// Make sure all memory is deallocated.
ASSERT_THAT(GetMemoryResource()->GetUsed(), Eq(0u));
// Make sure all disk is not reserved (files remain, but Storage is not
@@ -166,8 +165,12 @@ class StorageQueueStressTest : public ::testing::TestWithParam<size_t> {
}
void ResetTestStorageQueue() {
+ // Let everything ongoing to finish.
task_environment_.RunUntilIdle();
storage_queue_.reset();
+ // StorageQueue is destructed on a thread,
+ // so we need to wait for it to destruct.
+ task_environment_.RunUntilIdle();
}
QueueOptions BuildStorageQueueOptionsImmediate() const {
diff --git a/chromium/components/reporting/storage/storage_queue_unittest.cc b/chromium/components/reporting/storage/storage_queue_unittest.cc
index e30f55a308a..2f770d8fcac 100644
--- a/chromium/components/reporting/storage/storage_queue_unittest.cc
+++ b/chromium/components/reporting/storage/storage_queue_unittest.cc
@@ -12,11 +12,11 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/optional.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
+#include "build/build_config.h"
#include "components/reporting/encryption/test_encryption_module.h"
#include "components/reporting/proto/record.pb.h"
#include "components/reporting/storage/resources/resource_interface.h"
@@ -27,6 +27,7 @@
#include "crypto/sha2.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using ::testing::_;
using ::testing::Between;
@@ -37,6 +38,7 @@ using ::testing::Return;
using ::testing::Sequence;
using ::testing::StrEq;
using ::testing::WithArg;
+using ::testing::WithoutArgs;
namespace reporting {
namespace {
@@ -53,7 +55,7 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
// no-value if there was a gap record instead of a real one.
using LastRecordDigestMap =
std::map<std::pair<int64_t /*generation id */, int64_t /*sequencing id*/>,
- base::Optional<std::string /*digest*/>>;
+ absl::optional<std::string /*digest*/>>;
explicit MockUploadClient(LastRecordDigestMap* last_record_digest_map)
: last_record_digest_map_(last_record_digest_map) {}
@@ -151,7 +153,7 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
last_record_digest_map_->emplace(
std::make_pair(sequencing_information.sequencing_id(),
sequencing_information.generation_id()),
- base::nullopt);
+ absl::nullopt);
for (uint64_t c = 0; c < count; ++c) {
EncounterSeqId(sequencing_information.sequencing_id() +
@@ -173,7 +175,7 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
// completion.
class SetUp {
public:
- explicit SetUp(MockUploadClient* client, test::TestCallbackWaiter* waiter)
+ SetUp(MockUploadClient* client, test::TestCallbackWaiter* waiter)
: client_(client), waiter_(waiter) {}
~SetUp() {
test::TestCallbackWaiter* const waiter =
@@ -181,7 +183,8 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
EXPECT_CALL(*client_, UploadComplete(Eq(Status::StatusOK())))
.InSequence(client_->test_upload_sequence_,
client_->test_encounter_sequence_)
- .WillOnce(Invoke([waiter] { waiter->Signal(); }));
+ .WillOnce(
+ WithoutArgs(Invoke(waiter, &test::TestCallbackWaiter::Signal)));
}
SetUp& Required(int64_t sequence_number, base::StringPiece value) {
@@ -247,7 +250,7 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
};
private:
- base::Optional<int64_t> generation_id_;
+ absl::optional<int64_t> generation_id_;
LastRecordDigestMap* const last_record_digest_map_;
Sequence test_encounter_sequence_;
@@ -268,7 +271,6 @@ class StorageQueueTest : public ::testing::TestWithParam<size_t> {
void TearDown() override {
ResetTestStorageQueue();
- task_environment_.RunUntilIdle();
// Make sure all memory is deallocated.
ASSERT_THAT(GetMemoryResource()->GetUsed(), Eq(0u));
// Make sure all disk is not reserved (files remain, but Storage is not
@@ -299,8 +301,12 @@ class StorageQueueTest : public ::testing::TestWithParam<size_t> {
}
void ResetTestStorageQueue() {
+ // Let everything ongoing to finish.
task_environment_.RunUntilIdle();
storage_queue_.reset();
+ // StorageQueue is destructed on a thread,
+ // so we need to wait for it to destruct.
+ task_environment_.RunUntilIdle();
}
void InjectFailures(std::initializer_list<int64_t> sequencing_ids) {
@@ -346,7 +352,7 @@ class StorageQueueTest : public ::testing::TestWithParam<size_t> {
ASSERT_OK(write_result) << write_result;
}
- void ConfirmOrDie(base::Optional<std::int64_t> sequencing_id,
+ void ConfirmOrDie(absl::optional<std::int64_t> sequencing_id,
bool force = false) {
test::TestEvent<Status> c;
storage_queue_->Confirm(sequencing_id, force, c.cb());
@@ -1150,7 +1156,7 @@ TEST_P(StorageQueueTest, ForceConfirm) {
}
// Now force confirm the very beginning and forward time again.
- ConfirmOrDie(/*sequencing_id=*/base::nullopt, /*force=*/true);
+ ConfirmOrDie(/*sequencing_id=*/absl::nullopt, /*force=*/true);
{
// Set uploader expectations.
diff --git a/chromium/components/reporting/storage/storage_unittest.cc b/chromium/components/reporting/storage/storage_unittest.cc
index 4e612465426..bf3680974ef 100644
--- a/chromium/components/reporting/storage/storage_unittest.cc
+++ b/chromium/components/reporting/storage/storage_unittest.cc
@@ -10,7 +10,6 @@
#include <utility>
#include "base/files/scoped_temp_dir.h"
-#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
@@ -35,6 +34,7 @@
#include "crypto/sha2.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using ::testing::_;
using ::testing::Between;
@@ -49,6 +49,7 @@ using ::testing::Sequence;
using ::testing::StrEq;
using ::testing::WithArg;
using ::testing::WithArgs;
+using ::testing::WithoutArgs;
namespace reporting {
namespace {
@@ -181,7 +182,7 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
using LastRecordDigestMap = std::map<std::tuple<Priority,
int64_t /*generation id*/,
int64_t /*sequencing id*/>,
- base::Optional<std::string /*digest*/>>;
+ absl::optional<std::string /*digest*/>>;
explicit MockUploadClient(
LastRecordDigestMap* last_record_digest_map,
@@ -252,7 +253,7 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
std::make_tuple(sequencing_information.priority(),
sequencing_information.sequencing_id(),
sequencing_information.generation_id()),
- base::nullopt);
+ absl::nullopt);
for (uint64_t c = 0; c < count; ++c) {
EncounterSeqId(
@@ -279,9 +280,9 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
// completion.
class SetUp {
public:
- explicit SetUp(Priority priority,
- MockUploadClient* client,
- test::TestCallbackWaiter* waiter)
+ SetUp(Priority priority,
+ MockUploadClient* client,
+ test::TestCallbackWaiter* waiter)
: priority_(priority), client_(client), waiter_(waiter) {}
~SetUp() {
EXPECT_CALL(*client_, UploadRecordFailure(_, _, _))
@@ -292,7 +293,8 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
EXPECT_CALL(*client_, UploadComplete(Eq(Status::StatusOK())))
.InSequence(client_->test_upload_sequence_,
client_->test_encounter_sequence_)
- .WillOnce(Invoke([waiter] { waiter->Signal(); }));
+ .WillOnce(
+ WithoutArgs(Invoke(waiter, &test::TestCallbackWaiter::Signal)));
}
SetUp& Required(int64_t sequencing_id, base::StringPiece value) {
@@ -363,22 +365,16 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
// Helper class for setting up mock client expectations for key delivery.
class SetKeyDelivery {
public:
- explicit SetKeyDelivery(MockUploadClient* client,
- test::TestCallbackWaiter* waiter)
- : client_(client), waiter_(waiter) {}
+ explicit SetKeyDelivery(MockUploadClient* client) : client_(client) {}
~SetKeyDelivery() {
EXPECT_CALL(*client_, UploadRecord(_, _, _)).Times(0);
EXPECT_CALL(*client_, UploadRecordFailure(_, _, _)).Times(0);
- test::TestCallbackWaiter* const waiter =
- waiter_; // let pointer outlive SetUp
- EXPECT_CALL(*client_, UploadComplete(Eq(Status::StatusOK())))
- .WillOnce(Invoke([waiter] { waiter->Signal(); }));
+ EXPECT_CALL(*client_, UploadComplete(Eq(Status::StatusOK()))).Times(1);
}
private:
MockUploadClient* const client_;
- test::TestCallbackWaiter* const waiter_;
};
private:
@@ -479,7 +475,7 @@ class MockUploadClient : public ::testing::NiceMock<UploaderInterface> {
wrapped_record.record().data()));
}
- base::Optional<int64_t> generation_id_;
+ absl::optional<int64_t> generation_id_;
LastRecordDigestMap* const last_record_digest_map_;
scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
@@ -494,6 +490,12 @@ class StorageTest
protected:
void SetUp() override {
ASSERT_TRUE(location_.CreateUniqueTempDir());
+ // Disallow uploads unless other expectation is set (any later EXPECT_CALL
+ // will take precedence over this one).
+ EXPECT_CALL(set_mock_uploader_expectations_, Call(_, _, NotNull()))
+ .WillRepeatedly(WithoutArgs(Invoke([]() {
+ return Status(error::UNAVAILABLE, "Upload unavailable at this time");
+ })));
// Encryption is disabled by default.
ASSERT_FALSE(EncryptionModuleInterface::is_enabled());
if (is_encryption_enabled()) {
@@ -509,12 +511,15 @@ class StorageTest
decryptor_ = std::move(decryptor_result.ValueOrDie());
// First creation of Storage would need key delivered.
expect_to_need_key_ = true;
+ } else {
+ // Disable encryption.
+ scoped_feature_list_.InitFromCommandLine(
+ {}, {EncryptionModuleInterface::kEncryptedReporting});
}
}
void TearDown() override {
ResetTestStorage();
- task_environment_.RunUntilIdle();
// Make sure all memory is deallocated.
ASSERT_THAT(GetMemoryResource()->GetUsed(), Eq(0u));
// Make sure all disk is not reserved (files remain, but Storage is not
@@ -525,18 +530,15 @@ class StorageTest
StatusOr<scoped_refptr<Storage>> CreateTestStorage(
const StorageOptions& options,
scoped_refptr<EncryptionModuleInterface> encryption_module) {
- test::TestCallbackWaiter waiter;
if (expect_to_need_key_) {
// Set uploader expectations for any queue; expect no records and need
// key. Make sure no uploads happen, and key is requested.
- waiter.Attach();
EXPECT_CALL(set_mock_uploader_expectations_,
Call(_, /*need_encryption_key=*/Eq(true), NotNull()))
- .WillOnce(WithArg<2>(
- Invoke([&waiter](MockUploadClient* mock_upload_client) {
- MockUploadClient::SetKeyDelivery client(mock_upload_client,
- &waiter);
- })))
+ .WillOnce(WithArg<2>(Invoke([](MockUploadClient* mock_upload_client) {
+ MockUploadClient::SetKeyDelivery client(mock_upload_client);
+ return Status::StatusOK();
+ })))
.RetiresOnSaturation();
}
// Initialize Storage with no key.
@@ -546,7 +548,8 @@ class StorageTest
base::Unretained(this)),
encryption_module, e.cb());
ASSIGN_OR_RETURN(auto storage, e.result());
- waiter.Wait();
+ // Let asynchronous activity finish.
+ task_environment_.RunUntilIdle();
if (expect_to_need_key_) {
// Provision the storage with a key.
// Key delivery must have been requested above.
@@ -570,8 +573,12 @@ class StorageTest
}
void ResetTestStorage() {
+ // Let asynchronous activity finish.
task_environment_.RunUntilIdle();
storage_.reset();
+ // StorageQueue is destructed on a thread,
+ // so we need to wait for all queues to destruct.
+ task_environment_.RunUntilIdle();
expect_to_need_key_ = false;
}
@@ -612,8 +619,12 @@ class StorageTest
UploaderInterface::UploaderInterfaceResultCb start_uploader_cb) {
auto uploader = std::make_unique<MockUploadClient>(
&last_record_digest_map_, sequenced_task_runner_, decryptor_);
- set_mock_uploader_expectations_.Call(priority, need_encryption_key,
- uploader.get());
+ const auto status = set_mock_uploader_expectations_.Call(
+ priority, need_encryption_key, uploader.get());
+ if (!status.ok()) {
+ std::move(start_uploader_cb).Run(status);
+ return;
+ }
std::move(start_uploader_cb).Run(std::move(uploader));
}
@@ -648,7 +659,7 @@ class StorageTest
}
void ConfirmOrDie(Priority priority,
- base::Optional<std::int64_t> sequencing_id,
+ absl::optional<std::int64_t> sequencing_id,
bool force = false) {
test::TestEvent<Status> c;
storage_->Confirm(priority, sequencing_id, force, c.cb());
@@ -724,8 +735,8 @@ class StorageTest
scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_{
base::ThreadPool::CreateSequencedTaskRunner(base::TaskTraits())};
- ::testing::MockFunction<
- void(Priority, bool /*need_encryption_key*/, MockUploadClient*)>
+ ::testing::NiceMock<::testing::MockFunction<
+ Status(Priority, bool /*need_encryption_key*/, MockUploadClient*)>>
set_mock_uploader_expectations_;
};
@@ -735,7 +746,6 @@ constexpr std::array<const char*, 3> kMoreData = {"More1111", "More222",
TEST_P(StorageTest, WriteIntoNewStorageAndReopen) {
CreateTestStorageOrDie(BuildTestStorageOptions());
- EXPECT_CALL(set_mock_uploader_expectations_, Call(_, _, NotNull())).Times(0);
WriteStringOrDie(FAST_BATCH, kData[0]);
WriteStringOrDie(FAST_BATCH, kData[1]);
WriteStringOrDie(FAST_BATCH, kData[2]);
@@ -747,7 +757,6 @@ TEST_P(StorageTest, WriteIntoNewStorageAndReopen) {
TEST_P(StorageTest, WriteIntoNewStorageReopenAndWriteMore) {
CreateTestStorageOrDie(BuildTestStorageOptions());
- EXPECT_CALL(set_mock_uploader_expectations_, Call(_, _, NotNull())).Times(0);
WriteStringOrDie(FAST_BATCH, kData[0]);
WriteStringOrDie(FAST_BATCH, kData[1]);
WriteStringOrDie(FAST_BATCH, kData[2]);
@@ -777,6 +786,7 @@ TEST_P(StorageTest, WriteIntoNewStorageAndUpload) {
.Required(0, kData[0])
.Required(1, kData[1])
.Required(2, kData[2]);
+ return Status::StatusOK();
})));
// Trigger upload.
@@ -804,6 +814,7 @@ TEST_P(StorageTest, WriteIntoNewStorageAndUploadWithKeyUpdate) {
.WillRepeatedly(WithArgs<0, 2>(
Invoke([](Priority priority, MockUploadClient* mock_upload_client) {
MockUploadClient::SetEmpty client(mock_upload_client);
+ return Status::StatusOK();
})));
EXPECT_CALL(
set_mock_uploader_expectations_,
@@ -814,6 +825,7 @@ TEST_P(StorageTest, WriteIntoNewStorageAndUploadWithKeyUpdate) {
.Required(0, kData[0])
.Required(1, kData[1])
.Required(2, kData[2]);
+ return Status::StatusOK();
})));
// Trigger upload with no key update.
@@ -843,7 +855,9 @@ TEST_P(StorageTest, WriteIntoNewStorageAndUploadWithKeyUpdate) {
.Required(3, kMoreData[0])
.Required(4, kMoreData[1])
.Required(5, kMoreData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Trigger upload with key update after a long wait.
EXPECT_OK(storage_->Flush(MANUAL_BATCH));
@@ -876,7 +890,9 @@ TEST_P(StorageTest, WriteIntoNewStorageReopenWriteMoreAndUpload) {
.Required(3, kMoreData[0])
.Required(4, kMoreData[1])
.Required(5, kMoreData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Trigger upload.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
@@ -899,7 +915,9 @@ TEST_P(StorageTest, WriteIntoNewStorageAndFlush) {
.Required(0, kData[0])
.Required(1, kData[1])
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Trigger upload.
EXPECT_OK(storage_->Flush(MANUAL_BATCH));
@@ -932,7 +950,9 @@ TEST_P(StorageTest, WriteIntoNewStorageReopenWriteMoreAndFlush) {
.Required(3, kMoreData[0])
.Required(4, kMoreData[1])
.Required(5, kMoreData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Trigger upload.
EXPECT_OK(storage_->Flush(MANUAL_BATCH));
@@ -957,7 +977,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadWithConfirmations) {
.Required(0, kData[0])
.Required(1, kData[1])
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Forward time to trigger upload
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
@@ -976,7 +998,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadWithConfirmations) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Required(1, kData[1])
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Forward time to trigger upload
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
@@ -993,7 +1017,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadWithConfirmations) {
[&waiter](Priority priority, MockUploadClient* mock_upload_client) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Forward time to trigger upload
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
@@ -1016,7 +1042,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadWithConfirmations) {
.Required(3, kMoreData[0])
.Required(4, kMoreData[1])
.Required(5, kMoreData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
@@ -1034,7 +1062,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadWithConfirmations) {
.Required(3, kMoreData[0])
.Required(4, kMoreData[1])
.Required(5, kMoreData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
}
@@ -1054,7 +1084,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyImmediateUpload) {
[&waiter](Priority priority, MockUploadClient* mock_upload_client) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Required(0, kData[0]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE,
kData[0]); // Immediately uploads and verifies.
}
@@ -1069,7 +1101,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyImmediateUpload) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Required(0, kData[0])
.Required(1, kData[1]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE,
kData[1]); // Immediately uploads and verifies.
}
@@ -1085,7 +1119,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyImmediateUpload) {
.Required(0, kData[0])
.Required(1, kData[1])
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE,
kData[2]); // Immediately uploads and verifies.
}
@@ -1107,7 +1143,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyImmediateUploadWithConfirmations) {
[&waiter](Priority priority, MockUploadClient* mock_upload_client) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Required(0, kData[0]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE, kData[0]);
}
@@ -1121,7 +1159,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyImmediateUploadWithConfirmations) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Required(0, kData[0])
.Required(1, kData[1]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE, kData[1]);
}
@@ -1136,7 +1176,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyImmediateUploadWithConfirmations) {
.Required(0, kData[0])
.Required(1, kData[1])
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE, kData[2]);
}
@@ -1157,7 +1199,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyImmediateUploadWithConfirmations) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Required(2, kData[2])
.Required(3, kMoreData[0]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE, kMoreData[0]);
}
@@ -1172,7 +1216,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyImmediateUploadWithConfirmations) {
.Required(2, kData[2])
.Required(3, kMoreData[0])
.Required(4, kMoreData[1]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE, kMoreData[1]);
}
@@ -1188,7 +1234,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyImmediateUploadWithConfirmations) {
.Required(3, kMoreData[0])
.Required(4, kMoreData[1])
.Required(5, kMoreData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE, kMoreData[2]);
}
}
@@ -1205,7 +1253,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadMultipleQueues) {
[&waiter](Priority priority, MockUploadClient* mock_upload_client) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Required(0, kData[0]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE, kData[0]);
}
@@ -1221,7 +1271,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadMultipleQueues) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Required(0, kData[0])
.Required(1, kData[1]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE, kData[1]);
}
@@ -1236,6 +1288,7 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadMultipleQueues) {
.WillRepeatedly(WithArgs<0, 2>(
Invoke([](Priority priority, MockUploadClient* mock_upload_client) {
MockUploadClient::SetEmpty client(mock_upload_client);
+ return Status::StatusOK();
})));
EXPECT_CALL(
set_mock_uploader_expectations_,
@@ -1245,7 +1298,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadMultipleQueues) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Required(0, kMoreData[0])
.Required(1, kMoreData[1]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(20));
}
@@ -1266,7 +1321,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadMultipleQueues) {
MockUploadClient::SetUp(priority, mock_upload_client, &waiter)
.Possible(1, kData[1])
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
WriteStringOrDie(IMMEDIATE, kData[2]);
}
WriteStringOrDie(SLOW_BATCH, kMoreData[2]);
@@ -1280,6 +1337,7 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadMultipleQueues) {
.WillRepeatedly(WithArgs<0, 2>(
Invoke([](Priority priority, MockUploadClient* mock_upload_client) {
MockUploadClient::SetEmpty client(mock_upload_client);
+ return Status::StatusOK();
})));
EXPECT_CALL(
set_mock_uploader_expectations_,
@@ -1289,7 +1347,9 @@ TEST_P(StorageTest, WriteAndRepeatedlyUploadMultipleQueues) {
MockUploadClient::SetUp(SLOW_BATCH, mock_upload_client, &waiter)
.Required(1, kMoreData[1])
.Required(2, kMoreData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(20));
}
}
@@ -1309,7 +1369,9 @@ TEST_P(StorageTest, WriteEncryptFailure) {
.WillOnce(WithArg<1>(
Invoke([](base::OnceCallback<void(StatusOr<EncryptedRecord>)> cb) {
std::move(cb).Run(Status(error::UNKNOWN, "Failing for tests"));
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
const Status result = WriteString(FAST_BATCH, "TEST_MESSAGE");
EXPECT_FALSE(result.ok());
EXPECT_EQ(result.error_code(), error::UNKNOWN);
@@ -1334,7 +1396,9 @@ TEST_P(StorageTest, ForceConfirm) {
.Required(0, kData[0])
.Required(1, kData[1])
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Forward time to trigger upload
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
@@ -1351,13 +1415,15 @@ TEST_P(StorageTest, ForceConfirm) {
[&waiter](Priority priority, MockUploadClient* mock_upload_client) {
MockUploadClient::SetUp(FAST_BATCH, mock_upload_client, &waiter)
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Forward time to trigger upload
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
// Now force confirm #0 and forward time again.
- ConfirmOrDie(FAST_BATCH, /*sequencing_id=*/base::nullopt, /*force=*/true);
+ ConfirmOrDie(FAST_BATCH, /*sequencing_id=*/absl::nullopt, /*force=*/true);
// Set uploader expectations: #0 and #1 could be returned as Gaps
{
test::TestCallbackAutoWaiter waiter;
@@ -1377,7 +1443,9 @@ TEST_P(StorageTest, ForceConfirm) {
.PossibleGap(0, 2)
.Possible(1, kData[1])
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Forward time to trigger upload
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
@@ -1400,7 +1468,9 @@ TEST_P(StorageTest, ForceConfirm) {
.PossibleGap(1, 1)
.Possible(1, kData[1])
.Required(2, kData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Forward time to trigger upload
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
}
@@ -1437,20 +1507,19 @@ TEST_P(StorageTest, KayDeliveryFailureOnNewStorage) {
// This time key delivery is to succeed.
// Set uploader expectations for any queue; expect no records and need
// key. Make sure no uploads happen, and key is requested.
- {
- test::TestCallbackAutoWaiter waiter;
- EXPECT_CALL(set_mock_uploader_expectations_,
- Call(_, /*need_encryption_key=*/Eq(true), NotNull()))
- .WillOnce(
- WithArg<2>(Invoke([&waiter](MockUploadClient* mock_upload_client) {
- MockUploadClient::SetKeyDelivery client(mock_upload_client,
- &waiter);
- })))
- .RetiresOnSaturation();
+ EXPECT_CALL(set_mock_uploader_expectations_,
+ Call(_, /*need_encryption_key=*/Eq(true), NotNull()))
+ .WillOnce(WithArg<2>(Invoke([](MockUploadClient* mock_upload_client) {
+ MockUploadClient::SetKeyDelivery client(mock_upload_client);
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
+
+ // Forward time to trigger upload
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
- // Forward time to trigger upload
- task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
- }
+ // Let asynchronous activity finish.
+ task_environment_.RunUntilIdle();
// Provision the storage with a key.
// Key delivery must have been requested above.
@@ -1473,6 +1542,7 @@ TEST_P(StorageTest, KayDeliveryFailureOnNewStorage) {
.Required(0, kData[0])
.Required(1, kData[1])
.Required(2, kData[2]);
+ return Status::StatusOK();
})))
.RetiresOnSaturation();
@@ -1503,7 +1573,9 @@ TEST_P(StorageTest, KayDeliveryFailureOnNewStorage) {
.Required(3, kMoreData[0])
.Required(4, kMoreData[1])
.Required(5, kMoreData[2]);
- })));
+ return Status::StatusOK();
+ })))
+ .RetiresOnSaturation();
// Trigger upload.
task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
diff --git a/chromium/components/reporting/storage/test_storage_module.h b/chromium/components/reporting/storage/test_storage_module.h
index f7dfb55def9..437592f3570 100644
--- a/chromium/components/reporting/storage/test_storage_module.h
+++ b/chromium/components/reporting/storage/test_storage_module.h
@@ -5,15 +5,13 @@
#ifndef COMPONENTS_REPORTING_STORAGE_TEST_STORAGE_MODULE_H_
#define COMPONENTS_REPORTING_STORAGE_TEST_STORAGE_MODULE_H_
-#include <utility>
-
#include "base/callback.h"
-#include "base/optional.h"
#include "components/reporting/proto/record.pb.h"
#include "components/reporting/proto/record_constants.pb.h"
#include "components/reporting/storage/storage_module_interface.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace reporting {
namespace test {
@@ -57,8 +55,8 @@ class TestStorageModuleStrict : public StorageModuleInterface {
Record record,
base::OnceCallback<void(Status)> callback);
- base::Optional<Record> record_;
- base::Optional<Priority> priority_;
+ absl::optional<Record> record_;
+ absl::optional<Priority> priority_;
};
// Most of the time no need to log uninterested calls to |AddRecord|.
diff --git a/chromium/components/reporting/storage_selector/storage_selector.cc b/chromium/components/reporting/storage_selector/storage_selector.cc
index ef4994ac64a..b4d6137dcd6 100644
--- a/chromium/components/reporting/storage_selector/storage_selector.cc
+++ b/chromium/components/reporting/storage_selector/storage_selector.cc
@@ -14,7 +14,6 @@
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/reporting/encryption/encryption_module.h"
-#include "components/reporting/encryption/verification.h"
#include "components/reporting/storage/storage_module.h"
#include "components/reporting/storage/storage_module_interface.h"
#include "components/reporting/storage/storage_uploader_interface.h"
@@ -43,9 +42,9 @@ const base::Feature kProvideUploaderFeature{StorageSelector::kProvideUploader,
#if BUILDFLAG(IS_CHROMEOS_ASH)
// static
-const char StorageSelector::kUseMissiveDaemon[] = "connect_misive_daemon";
+const char StorageSelector::kUseMissiveDaemon[] = "ConnectMissiveDaemon";
// static
-const char StorageSelector::kProvideUploader[] = "provide_upload";
+const char StorageSelector::kProvideUploader[] = "ProvideUploader";
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
// static
@@ -60,6 +59,7 @@ bool StorageSelector::is_uploader_required() {
// static
void StorageSelector::CreateStorageModule(
const base::FilePath& local_reporting_path,
+ base::StringPiece verification_key,
UploaderInterface::AsyncStartUploaderCb async_start_upload_cb,
base::OnceCallback<void(StatusOr<scoped_refptr<StorageModuleInterface>>)>
cb) {
@@ -89,12 +89,12 @@ void StorageSelector::CreateStorageModule(
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
// Use Storage in a local file system.
- StorageModule::Create(StorageOptions()
- .set_directory(local_reporting_path)
- .set_signature_verification_public_key(
- SignatureVerifier::VerificationKey()),
- std::move(async_start_upload_cb),
- EncryptionModule::Create(), std::move(cb));
+ StorageModule::Create(
+ StorageOptions()
+ .set_directory(local_reporting_path)
+ .set_signature_verification_public_key(verification_key),
+ std::move(async_start_upload_cb), EncryptionModule::Create(),
+ std::move(cb));
}
} // namespace reporting
diff --git a/chromium/components/reporting/storage_selector/storage_selector.h b/chromium/components/reporting/storage_selector/storage_selector.h
index ef05e9fea00..1b4c40c5823 100644
--- a/chromium/components/reporting/storage_selector/storage_selector.h
+++ b/chromium/components/reporting/storage_selector/storage_selector.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_REPORTING_STORAGE_SELECTOR_STORAGE_SELECTOR_H_
#define COMPONENTS_REPORTING_STORAGE_SELECTOR_STORAGE_SELECTOR_H_
-#include <memory>
-#include <utility>
-
#include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
@@ -38,6 +35,7 @@ class StorageSelector {
static bool is_uploader_required();
static void CreateStorageModule(
const base::FilePath& local_reporting_path,
+ base::StringPiece verification_key,
UploaderInterface::AsyncStartUploaderCb async_start_upload_cb,
base::OnceCallback<void(StatusOr<scoped_refptr<StorageModuleInterface>>)>
cb);
diff --git a/chromium/components/reporting/util/shared_vector_unittest.cc b/chromium/components/reporting/util/shared_vector_unittest.cc
index 0e56e14302d..8b51e15a62d 100644
--- a/chromium/components/reporting/util/shared_vector_unittest.cc
+++ b/chromium/components/reporting/util/shared_vector_unittest.cc
@@ -7,11 +7,11 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
-#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/test/task_environment.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -39,7 +39,7 @@ class VectorTester {
const FindType& sought_item() const { return sought_item_; }
- const base::Optional<FindType>& found_result() const {
+ const absl::optional<FindType>& found_result() const {
return found_result_;
}
@@ -52,7 +52,7 @@ class VectorTester {
const FindType sought_item_;
std::unique_ptr<base::RunLoop> run_loop_;
- base::Optional<FindType> found_result_;
+ absl::optional<FindType> found_result_;
};
template <typename ExecuteType>
@@ -107,8 +107,8 @@ class VectorTester {
}
// Resets |insert_success| before returning its value.
- base::Optional<bool> GetPushBackSuccess() {
- base::Optional<bool> return_value;
+ absl::optional<bool> GetPushBackSuccess() {
+ absl::optional<bool> return_value;
return_value.swap(insert_success_);
return return_value;
}
@@ -129,8 +129,8 @@ class VectorTester {
base::Unretained(this)));
}
- base::Optional<uint64_t> GetEraseValue() {
- base::Optional<uint64_t> return_value;
+ absl::optional<uint64_t> GetEraseValue() {
+ absl::optional<uint64_t> return_value;
return_value.swap(number_deleted_);
return return_value;
}
@@ -187,8 +187,8 @@ class VectorTester {
scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
std::unique_ptr<base::RunLoop> run_loop_;
- base::Optional<bool> insert_success_;
- base::Optional<uint64_t> number_deleted_;
+ absl::optional<bool> insert_success_;
+ absl::optional<uint64_t> number_deleted_;
};
// Ensures that the vector accept values, and will erase inserted values.
diff --git a/chromium/components/reporting/util/status.h b/chromium/components/reporting/util/status.h
index c0a000d12d2..d13a41132f9 100644
--- a/chromium/components/reporting/util/status.h
+++ b/chromium/components/reporting/util/status.h
@@ -35,6 +35,8 @@ enum Code : int32_t {
INTERNAL = 13,
UNAVAILABLE = 14,
DATA_LOSS = 15,
+ // The value should always be kept last.
+ MAX_VALUE
};
} // namespace error
diff --git a/chromium/components/reporting/util/statusor.h b/chromium/components/reporting/util/statusor.h
index 5044da91d76..f287281f8be 100644
--- a/chromium/components/reporting/util/statusor.h
+++ b/chromium/components/reporting/util/statusor.h
@@ -57,14 +57,13 @@
#define COMPONENTS_REPORTING_UTIL_STATUSOR_H_
#include <new>
-#include <string>
#include <type_traits>
#include <utility>
#include "base/compiler_specific.h"
#include "base/logging.h"
-#include "base/optional.h"
#include "components/reporting/util/status.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace reporting {
@@ -299,7 +298,7 @@ class WARN_UNUSED_RESULT StatusOr {
}
Status status_;
- base::Optional<T> value_;
+ absl::optional<T> value_;
};
} // namespace reporting
diff --git a/chromium/components/reputation/core/safety_tip_test_utils.cc b/chromium/components/reputation/core/safety_tip_test_utils.cc
index 165e09c34f3..1b45d901a85 100644
--- a/chromium/components/reputation/core/safety_tip_test_utils.cc
+++ b/chromium/components/reputation/core/safety_tip_test_utils.cc
@@ -53,13 +53,16 @@ void SetSafetyTipBadRepPatterns(std::vector<std::string> patterns) {
}
void SetSafetyTipAllowlistPatterns(std::vector<std::string> patterns,
- std::vector<std::string> target_patterns) {
+ std::vector<std::string> target_patterns,
+ std::vector<std::string> common_words) {
auto config_proto = GetConfig();
config_proto->clear_allowed_pattern();
config_proto->clear_allowed_target_pattern();
+ config_proto->clear_common_word();
std::sort(patterns.begin(), patterns.end());
std::sort(target_patterns.begin(), target_patterns.end());
+ std::sort(common_words.begin(), common_words.end());
for (const auto& pattern : patterns) {
UrlPattern* page = config_proto->add_allowed_pattern();
@@ -69,11 +72,14 @@ void SetSafetyTipAllowlistPatterns(std::vector<std::string> patterns,
HostPattern* page = config_proto->add_allowed_target_pattern();
page->set_regex(pattern);
}
+ for (const auto& word : common_words) {
+ config_proto->add_common_word(word);
+ }
SetSafetyTipsRemoteConfigProto(std::move(config_proto));
}
void InitializeBlankLookalikeAllowlistForTesting() {
- SetSafetyTipAllowlistPatterns({}, {});
+ SetSafetyTipAllowlistPatterns({}, {}, {});
}
} // namespace reputation
diff --git a/chromium/components/reputation/core/safety_tip_test_utils.h b/chromium/components/reputation/core/safety_tip_test_utils.h
index 666f97f0ecb..58b8065aec4 100644
--- a/chromium/components/reputation/core/safety_tip_test_utils.h
+++ b/chromium/components/reputation/core/safety_tip_test_utils.h
@@ -31,7 +31,8 @@ void SetSafetyTipBadRepPatterns(std::vector<std::string> pattern);
// |target_patterns| is the list of hostname regexes allowed to be targets of
// lookalikes.
void SetSafetyTipAllowlistPatterns(std::vector<std::string> patterns,
- std::vector<std::string> target_patterns);
+ std::vector<std::string> target_patterns,
+ std::vector<std::string> common_words);
// Ensure that the allowlist has been initialized. This is important as some
// code (e.g. the elision policy) is fail-open (i.e. it won't elide without an
diff --git a/chromium/components/reputation/core/safety_tips.proto b/chromium/components/reputation/core/safety_tips.proto
index b14bfaa362e..44b5b5204d7 100644
--- a/chromium/components/reputation/core/safety_tips.proto
+++ b/chromium/components/reputation/core/safety_tips.proto
@@ -65,4 +65,9 @@ message SafetyTipsConfig {
// In these cases it's simpler to allowlist the target instead of the
// embedder.
repeated HostPattern allowed_target_pattern = 4;
+
+ // A *sorted* list of common words. These words are combined with the list at
+ // components/url_formatter/spoof_checks/common_words. The combined list is
+ // used in some lookalike heuristics to prevent common false positives.
+ repeated string common_word = 5;
}
diff --git a/chromium/components/reputation/core/safety_tips_config.cc b/chromium/components/reputation/core/safety_tips_config.cc
index e3cf98d9985..a3ef88661d5 100644
--- a/chromium/components/reputation/core/safety_tips_config.cc
+++ b/chromium/components/reputation/core/safety_tips_config.cc
@@ -5,6 +5,7 @@
#include "components/reputation/core/safety_tips_config.h"
#include "base/no_destructor.h"
+#include "base/ranges/algorithm.h"
#include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
#include "third_party/re2/src/re2/re2.h"
#include "url/gurl.h"
@@ -169,4 +170,20 @@ security_state::SafetyTipStatus GetSafetyTipUrlBlockType(const GURL& url) {
return security_state::SafetyTipStatus::kNone;
}
+bool IsCommonWordInConfigProto(const SafetyTipsConfig* proto,
+ const std::string& word) {
+ // proto is nullptr when running in non-Lookalike tests.
+ if (proto == nullptr) {
+ return false;
+ }
+
+ auto common_words = proto->common_word();
+ DCHECK(base::ranges::is_sorted(common_words.begin(), common_words.end()));
+ auto lower = std::lower_bound(
+ common_words.begin(), common_words.end(), word,
+ [](const std::string& a, const std::string& b) -> bool { return a < b; });
+
+ return lower != common_words.end() && word == *lower;
+}
+
} // namespace reputation
diff --git a/chromium/components/reputation/core/safety_tips_config.h b/chromium/components/reputation/core/safety_tips_config.h
index 532c0dcfd29..9d0d406bb5e 100644
--- a/chromium/components/reputation/core/safety_tips_config.h
+++ b/chromium/components/reputation/core/safety_tips_config.h
@@ -42,6 +42,10 @@ bool IsTargetHostAllowlistedBySafetyTipsComponent(const SafetyTipsConfig* proto,
// in sorted order.
security_state::SafetyTipStatus GetSafetyTipUrlBlockType(const GURL& url);
+// Returns whether |word| is included in the component updater common word list
+bool IsCommonWordInConfigProto(const SafetyTipsConfig* proto,
+ const std::string& word);
+
} // namespace reputation
#endif // COMPONENTS_REPUTATION_CORE_SAFETY_TIPS_CONFIG_H_
diff --git a/chromium/components/reputation/core/safety_tips_config_unittest.cc b/chromium/components/reputation/core/safety_tips_config_unittest.cc
index 792f54c37b8..4c7756e8f2d 100644
--- a/chromium/components/reputation/core/safety_tips_config_unittest.cc
+++ b/chromium/components/reputation/core/safety_tips_config_unittest.cc
@@ -13,7 +13,7 @@
namespace reputation {
TEST(SafetyTipsConfigTest, TestUrlAllowlist) {
- SetSafetyTipAllowlistPatterns({"example.com/"}, {});
+ SetSafetyTipAllowlistPatterns({"example.com/"}, {}, {});
auto* config = GetSafetyTipsRemoteConfigProto();
EXPECT_TRUE(IsUrlAllowlistedBySafetyTipsComponent(
config, GURL("http://example.com")));
@@ -22,7 +22,7 @@ TEST(SafetyTipsConfigTest, TestUrlAllowlist) {
}
TEST(SafetyTipsConfigTest, TestTargetUrlAllowlist) {
- SetSafetyTipAllowlistPatterns({}, {"exa.*\\.com"});
+ SetSafetyTipAllowlistPatterns({}, {"exa.*\\.com"}, {});
auto* config = GetSafetyTipsRemoteConfigProto();
EXPECT_TRUE(
IsTargetHostAllowlistedBySafetyTipsComponent(config, "example.com"));
@@ -30,4 +30,14 @@ TEST(SafetyTipsConfigTest, TestTargetUrlAllowlist) {
IsTargetHostAllowlistedBySafetyTipsComponent(config, "example.org"));
}
+TEST(SafetyTipsConfigTest, TestCommonWords) {
+ // IsCommonWordInConfigProto does a binary search of sorted common words.
+ SetSafetyTipAllowlistPatterns({}, {}, {"common3", "common1", "common2"});
+ auto* config = GetSafetyTipsRemoteConfigProto();
+ EXPECT_TRUE(IsCommonWordInConfigProto(config, "common1"));
+ EXPECT_TRUE(IsCommonWordInConfigProto(config, "common2"));
+ EXPECT_TRUE(IsCommonWordInConfigProto(config, "common3"));
+ EXPECT_FALSE(IsCommonWordInConfigProto(config, "uncommon"));
+}
+
} // namespace reputation
diff --git a/chromium/components/resources/android/page_info_resource_id.h b/chromium/components/resources/android/page_info_resource_id.h
index dd09006da97..7ec3a91108e 100644
--- a/chromium/components/resources/android/page_info_resource_id.h
+++ b/chromium/components/resources/android/page_info_resource_id.h
@@ -24,23 +24,9 @@
// PageInfoUI images, used in ConnectionInfoView
// Good:
-DECLARE_RESOURCE_ID(IDR_PAGEINFO_GOOD, R.drawable.pageinfo_good)
-DECLARE_RESOURCE_ID(IDR_PAGEINFO_GOOD_V2, R.drawable.omnibox_https_valid)
-// Warnings:
-DECLARE_RESOURCE_ID(IDR_PAGEINFO_WARNING_MINOR, R.drawable.pageinfo_warning)
+DECLARE_RESOURCE_ID(IDR_PAGEINFO_GOOD, R.drawable.omnibox_https_valid)
// Bad:
-DECLARE_RESOURCE_ID(IDR_PAGEINFO_BAD, R.drawable.pageinfo_bad)
-DECLARE_RESOURCE_ID(IDR_PAGEINFO_BAD_V2, R.drawable.omnibox_not_secure_warning)
-// Should never occur, use warning just in case:
-// Enterprise managed: ChromeOS only.
-DECLARE_RESOURCE_ID(IDR_PAGEINFO_ENTERPRISE_MANAGED,
- R.drawable.pageinfo_warning)
-// Info: Only shown on chrome:// urls, which don't show the connection info
-// popup.
-DECLARE_RESOURCE_ID(IDR_PAGEINFO_INFO, R.drawable.pageinfo_warning)
-// Major warning: Used on insecure pages, which don't show the connection info
-// popup.
-DECLARE_RESOURCE_ID(IDR_PAGEINFO_WARNING_MAJOR, R.drawable.pageinfo_warning)
+DECLARE_RESOURCE_ID(IDR_PAGEINFO_BAD, R.drawable.omnibox_not_secure_warning)
// PageInfoUI colors, used in ConnectionInfoView
// Good:
diff --git a/chromium/components/resources/components_scaled_resources.grd b/chromium/components/resources/components_scaled_resources.grd
index 940244ddd6f..b404cacd3ea 100644
--- a/chromium/components/resources/components_scaled_resources.grd
+++ b/chromium/components/resources/components_scaled_resources.grd
@@ -22,6 +22,7 @@
<!-- Generic resources -->
<if expr="not is_android">
<structure type="chrome_scaled_image" name="IDR_HISTORY_FAVICON" file="favicon_history.png" />
+ <structure type="chrome_scaled_image" name="IDR_INFO_FAVICON" file="favicon_info.png" />
</if>
<structure type="chrome_scaled_image" name="IDR_SAD_WEBVIEW" file="webview-crash.png" />
<structure type="chrome_scaled_image" name="IDR_SAD_PLUGIN" file="sadplugin.png" />
diff --git a/chromium/components/resources/default_100_percent/favicon_info.png b/chromium/components/resources/default_100_percent/favicon_info.png
new file mode 100644
index 00000000000..bdd03588057
--- /dev/null
+++ b/chromium/components/resources/default_100_percent/favicon_info.png
Binary files differ
diff --git a/chromium/components/resources/default_200_percent/favicon_info.png b/chromium/components/resources/default_200_percent/favicon_info.png
new file mode 100644
index 00000000000..07f97a61075
--- /dev/null
+++ b/chromium/components/resources/default_200_percent/favicon_info.png
Binary files differ
diff --git a/chromium/components/resources/default_300_percent/favicon_info.png b/chromium/components/resources/default_300_percent/favicon_info.png
new file mode 100644
index 00000000000..fc1108adbf4
--- /dev/null
+++ b/chromium/components/resources/default_300_percent/favicon_info.png
Binary files differ
diff --git a/chromium/components/resources/flags_ui_resources.grdp b/chromium/components/resources/flags_ui_resources.grdp
index 6dbb7003da1..1f46be7537d 100644
--- a/chromium/components/resources/flags_ui_resources.grdp
+++ b/chromium/components/resources/flags_ui_resources.grdp
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
<include name="IDR_FLAGS_UI_FLAGS_HTML" file="../flags_ui/resources/flags.html" preprocess="true" type="BINDATA" />
- <include name="IDR_FLAGS_UI_FLAGS_JS" file="../flags_ui/resources/flags.js" type="BINDATA" />
- <include name="IDR_FLAGS_UI_FLAGS_CSS" file="../flags_ui/resources/flags.css" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_FLAGS_UI_FLAGS_JS" file="../flags_ui/resources/flags.js" preprocess="true" type="BINDATA" />
+ <include name="IDR_FLAGS_UI_FLAGS_CSS" file="../flags_ui/resources/flags.css" preprocess="true" type="BINDATA" />
</grit-part>
diff --git a/chromium/components/resources/gcm_driver_resources.grdp b/chromium/components/resources/gcm_driver_resources.grdp
index 5ab55e32d69..99e2d019345 100644
--- a/chromium/components/resources/gcm_driver_resources.grdp
+++ b/chromium/components/resources/gcm_driver_resources.grdp
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <include name="IDR_GCM_DRIVER_GCM_INTERNALS_HTML" file="../gcm_driver/resources/gcm_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
+ <include name="IDR_GCM_DRIVER_GCM_INTERNALS_HTML" file="../gcm_driver/resources/gcm_internals.html" type="BINDATA" />
<include name="IDR_GCM_DRIVER_GCM_INTERNALS_CSS" file="../gcm_driver/resources/gcm_internals.css" type="BINDATA" />
- <include name="IDR_GCM_DRIVER_GCM_INTERNALS_JS" file="../gcm_driver/resources/gcm_internals.js" type="BINDATA" />
+ <include name="IDR_GCM_DRIVER_GCM_INTERNALS_JS" file="../gcm_driver/resources/gcm_internals.js" preprocess="true" type="BINDATA" />
</grit-part>
diff --git a/chromium/components/resources/net_log_resources.grdp b/chromium/components/resources/net_log_resources.grdp
index 4cf3ec96169..c023000d7ae 100644
--- a/chromium/components/resources/net_log_resources.grdp
+++ b/chromium/components/resources/net_log_resources.grdp
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
- <include name="IDR_NET_LOG_NET_EXPORT_HTML" file="../net_log/resources/net_export.html" flattenhtml="true" type="BINDATA" />
- <include name="IDR_NET_LOG_NET_EXPORT_JS" file="../net_log/resources/net_export.js" type="BINDATA" />
+ <include name="IDR_NET_LOG_NET_EXPORT_CSS" file="../net_log/resources/net_export.css" type="BINDATA" />
+ <include name="IDR_NET_LOG_NET_EXPORT_HTML" file="../net_log/resources/net_export.html" preprocess="true" type="BINDATA" />
+ <include name="IDR_NET_LOG_NET_EXPORT_JS" file="../net_log/resources/net_export.js" preprocess="true" type="BINDATA" />
</grit-part>
diff --git a/chromium/components/resources/ntp_tiles_dev_ui_resources.grdp b/chromium/components/resources/ntp_tiles_dev_ui_resources.grdp
index 03f106f608f..d82e1e73318 100644
--- a/chromium/components/resources/ntp_tiles_dev_ui_resources.grdp
+++ b/chromium/components/resources/ntp_tiles_dev_ui_resources.grdp
@@ -3,11 +3,10 @@
<grit-part>
<include name="IDR_NTP_TILES_INTERNALS_HTML"
file="../ntp_tiles/webui/resources/ntp_tiles_internals.html"
- flattenhtml="true"
- allowexternalscript="true"
type="BINDATA" />
<include name="IDR_NTP_TILES_INTERNALS_JS"
file="../ntp_tiles/webui/resources/ntp_tiles_internals.js"
+ preprocess="true"
type="BINDATA" />
<include name="IDR_NTP_TILES_INTERNALS_CSS"
file="../ntp_tiles/webui/resources/ntp_tiles_internals.css"
diff --git a/chromium/components/resources/ssl/ssl_error_assistant/BUILD.gn b/chromium/components/resources/ssl/ssl_error_assistant/BUILD.gn
index 9a90fd463f2..ca822984e16 100644
--- a/chromium/components/resources/ssl/ssl_error_assistant/BUILD.gn
+++ b/chromium/components/resources/ssl/ssl_error_assistant/BUILD.gn
@@ -5,8 +5,7 @@
import("//build/config/python.gni")
# Generate the binary proto form of "ssl_error_assistant" from the ascii proto.
-# TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
-python2_action("make_ssl_error_assistant_protobuf") {
+action("make_ssl_error_assistant_protobuf") {
script = "gen_ssl_error_assistant_proto.py"
# The output goes in $target_gen_dir since that's where
diff --git a/chromium/components/resources/ssl/ssl_error_assistant/PRESUBMIT.py b/chromium/components/resources/ssl/ssl_error_assistant/PRESUBMIT.py
index 16a0f328f8a..93b738b24c5 100644
--- a/chromium/components/resources/ssl/ssl_error_assistant/PRESUBMIT.py
+++ b/chromium/components/resources/ssl/ssl_error_assistant/PRESUBMIT.py
@@ -7,6 +7,8 @@
This is taken from chrome/browser/resources/safe_browsing/PRESUBMIT.py.
"""
+USE_PYTHON3 = True
+
# TODO(meacer): Refactor and reuse shared code with
# chrome/browser/resources/safe_browsing/PRESUBMIT.py
def CheckVersionUpdatedInSSLErrorAssistantProto(input_api, output_api):
diff --git a/chromium/components/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py b/chromium/components/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py
index bf37febd56e..9032c7307d0 100755
--- a/chromium/components/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py
+++ b/chromium/components/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# 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.
diff --git a/chromium/components/resources/ssl/ssl_error_assistant/push_proto.py b/chromium/components/resources/ssl/ssl_error_assistant/push_proto.py
index e313194671c..17ee45ac5d5 100755
--- a/chromium/components/resources/ssl/ssl_error_assistant/push_proto.py
+++ b/chromium/components/resources/ssl/ssl_error_assistant/push_proto.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -46,10 +46,10 @@ def main():
gn_command = ['ninja',
'-C', opts.dir,
RESOURCE_SUBDIR + ':make_ssl_error_assistant_protobuf']
- print "Running the following"
- print " " + (' '.join(gn_command))
+ print("Running the following")
+ print(" " + (' '.join(gn_command)))
if subprocess.call(gn_command):
- print "Ninja failed."
+ print("Ninja failed.")
return 1
# Use the versioned files under the copy directory to push to the GCS bucket.
@@ -68,19 +68,19 @@ def main():
version_dir = dirs[0]
command = ['gsutil', 'cp', '-Rn', version_dir, DEST_BUCKET]
- print '\nGoing to run the following command'
- print ' ', ' '.join(command)
- print '\nIn directory'
- print ' ', copy_dir
- print '\nWhich should push the following files'
+ print('\nGoing to run the following command')
+ print(' ', ' '.join(command))
+ print('\nIn directory')
+ print(' ', copy_dir)
+ print('\nWhich should push the following files')
expected_files = [os.path.join(dp, f) for dp, _, fn in
os.walk(version_dir) for f in fn]
for f in expected_files:
- print ' ', f
+ print(' ', f)
shall = raw_input('\nAre you sure (y/N) ').lower() == 'y'
if not shall:
- print 'aborting'
+ print('aborting')
return 1
return subprocess.call(command)
diff --git a/chromium/components/safe_browsing/DEPS b/chromium/components/safe_browsing/DEPS
index 09bc03f1d25..09fb3f119a0 100644
--- a/chromium/components/safe_browsing/DEPS
+++ b/chromium/components/safe_browsing/DEPS
@@ -31,6 +31,8 @@ include_rules = [
"+testing/gtest",
"+third_party/blink/public/common/loader/url_loader_throttle.h",
"+third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h",
+ "+third_party/tflite-support",
+ "+third_party/tflite",
"+third_party/protobuf",
"+ui/base/resource/resource_bundle.h",
"+ui/android/view_android.h",
diff --git a/chromium/components/safe_browsing/android/DIR_METADATA b/chromium/components/safe_browsing/android/DIR_METADATA
deleted file mode 100644
index 578f3dfc4ea..00000000000
--- a/chromium/components/safe_browsing/android/DIR_METADATA
+++ /dev/null
@@ -1,5 +0,0 @@
-monorail {
- component: "Services>Safebrowsing"
-}
-
-team_email: "safebrowsing@chromium.org"
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 361685599fe..5d718a9deba 100644
--- a/chromium/components/safe_browsing/android/remote_database_manager_unittest.cc
+++ b/chromium/components/safe_browsing/android/remote_database_manager_unittest.cc
@@ -9,7 +9,6 @@
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "components/safe_browsing/android/safe_browsing_api_handler.h"
#include "components/variations/variations_associated_data.h"
diff --git a/chromium/components/safe_browsing/android/safe_browsing_api_handler.h b/chromium/components/safe_browsing/android/safe_browsing_api_handler.h
index a343c4b1ea0..b4be21cb8a7 100644
--- a/chromium/components/safe_browsing/android/safe_browsing_api_handler.h
+++ b/chromium/components/safe_browsing/android/safe_browsing_api_handler.h
@@ -9,7 +9,6 @@
#define COMPONENTS_SAFE_BROWSING_ANDROID_SAFE_BROWSING_API_HANDLER_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.h b/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.h
index bcee335fe83..4ba4ebb846e 100644
--- a/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.h
+++ b/chromium/components/safe_browsing/android/safe_browsing_api_handler_bridge.h
@@ -9,7 +9,6 @@
#include <jni.h>
-#include <string>
#include <vector>
#include "base/android/jni_android.h"
diff --git a/chromium/components/safe_browsing/content/browser/BUILD.gn b/chromium/components/safe_browsing/content/browser/BUILD.gn
index 9d1098a61a9..07f1106c731 100644
--- a/chromium/components/safe_browsing/content/browser/BUILD.gn
+++ b/chromium/components/safe_browsing/content/browser/BUILD.gn
@@ -16,6 +16,8 @@ source_set("browser") {
"threat_details_cache.h",
"threat_details_history.cc",
"threat_details_history.h",
+ "web_api_handshake_checker.cc",
+ "web_api_handshake_checker.h",
]
deps = [
"//components/back_forward_cache",
@@ -64,18 +66,28 @@ source_set("client_side_model_loader") {
]
}
-source_set("client_side_model_loader_unittest") {
+source_set("unit_tests") {
testonly = true
- sources = [ "client_side_model_loader_unittest.cc" ]
+ sources = [
+ "client_side_model_loader_unittest.cc",
+ "client_side_phishing_model_unittest.cc",
+ "web_api_handshake_checker_unittest.cc",
+ ]
deps = [
+ ":client_side_detection",
":client_side_model_loader",
"//base:base",
"//base/test:test_support",
"//components/safe_browsing:buildflags",
+ "//components/safe_browsing/content/browser:browser",
"//components/safe_browsing/core:client_model_proto",
"//components/safe_browsing/core:csd_proto",
"//components/safe_browsing/core:features",
+ "//components/safe_browsing/core/browser:browser",
+ "//components/safe_browsing/core/db:test_database_manager",
+ "//components/safe_browsing/core/fbs:client_model",
+ "//components/security_interstitials/core:unsafe_resource",
"//components/variations",
"//content/test:test_support",
"//services/network:test_support",
@@ -90,6 +102,8 @@ source_set("client_side_detection") {
"client_side_detection_host.h",
"client_side_detection_service.cc",
"client_side_detection_service.h",
+ "client_side_phishing_model.cc",
+ "client_side_phishing_model.h",
]
deps = [
":client_side_model_loader",
@@ -109,6 +123,7 @@ source_set("client_side_detection") {
"//components/safe_browsing/core/db:allowlist_checker_client",
"//components/safe_browsing/core/db:database_manager",
"//components/safe_browsing/core/db:v4_protocol_manager_util",
+ "//components/safe_browsing/core/fbs:client_model",
"//components/security_interstitials/content:security_interstitial_page",
"//components/variations",
"//content/public/browser",
diff --git a/chromium/components/safe_browsing/content/browser/client_side_detection_host.cc b/chromium/components/safe_browsing/content/browser/client_side_detection_host.cc
index f55c0498ae4..7ada63d74e5 100644
--- a/chromium/components/safe_browsing/content/browser/client_side_detection_host.cc
+++ b/chromium/components/safe_browsing/content/browser/client_side_detection_host.cc
@@ -20,6 +20,7 @@
#include "base/time/tick_clock.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/content/browser/client_side_detection_service.h"
+#include "components/safe_browsing/content/browser/client_side_phishing_model.h"
#include "components/safe_browsing/content/common/safe_browsing.mojom-shared.h"
#include "components/safe_browsing/content/common/safe_browsing.mojom.h"
#include "components/safe_browsing/core/browser/sync/sync_utils.h"
@@ -368,6 +369,22 @@ void ClientSideDetectionHost::DidFinishNavigation(
classification_request_->Start();
}
+void ClientSideDetectionHost::SetPhishingModel() {
+ switch (csd_service_->GetModelType()) {
+ case CSDModelType::kNone:
+ case CSDModelType::kProtobuf:
+ phishing_detector_->SetPhishingModel(
+ csd_service_->GetModelStr(),
+ csd_service_->GetVisualTfLiteModel().Duplicate());
+ return;
+ case CSDModelType::kFlatbuffer:
+ phishing_detector_->SetPhishingFlatBufferModel(
+ csd_service_->GetModelSharedMemoryRegion(),
+ csd_service_->GetVisualTfLiteModel().Duplicate());
+ return;
+ }
+}
+
void ClientSideDetectionHost::SendModelToRenderFrame() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!web_contents() || web_contents() != tab_ || !csd_service_)
@@ -380,7 +397,7 @@ void ClientSideDetectionHost::SendModelToRenderFrame() {
phishing_detector_.reset();
frame->GetRemoteInterfaces()->GetInterface(
phishing_detector_.BindNewPipeAndPassReceiver());
- phishing_detector_->SetPhishingModel(csd_service_->GetModelStr());
+ SetPhishingModel();
}
}
@@ -399,7 +416,7 @@ void ClientSideDetectionHost::RenderFrameCreated(
phishing_detector_.reset();
render_frame_host->GetRemoteInterfaces()->GetInterface(
phishing_detector_.BindNewPipeAndPassReceiver());
- phishing_detector_->SetPhishingModel(csd_service_->GetModelStr());
+ SetPhishingModel();
}
void ClientSideDetectionHost::OnPhishingPreClassificationDone(
@@ -433,8 +450,9 @@ void ClientSideDetectionHost::PhishingDetectionDone(
base::UmaHistogramEnumeration("SBClientPhishing.PhishingDetectorResult",
result);
if (result == mojom::PhishingDetectorResult::CLASSIFIER_NOT_READY) {
- base::UmaHistogramEnumeration("SBClientPhishing.ClassifierNotReadyReason",
- csd_service_->GetLastModelStatus());
+ base::UmaHistogramBoolean(
+ "SBClientPhishing.BrowserReadyOnClassifierNotReady",
+ ClientSidePhishingModel::GetInstance()->IsEnabled());
}
if (result != mojom::PhishingDetectorResult::SUCCESS)
return;
diff --git a/chromium/components/safe_browsing/content/browser/client_side_detection_host.h b/chromium/components/safe_browsing/content/browser/client_side_detection_host.h
index f42f6a031cf..1da2130428b 100644
--- a/chromium/components/safe_browsing/content/browser/client_side_detection_host.h
+++ b/chromium/components/safe_browsing/content/browser/client_side_detection_host.h
@@ -160,6 +160,9 @@ class ClientSideDetectionHost : public content::WebContentsObserver {
// who are signed in and not in incognito mode.
bool CanGetAccessToken();
+ // Set phishing model in PhishingDetector in renderers.
+ void SetPhishingModel();
+
// Send the client report to CSD server.
void SendRequest(std::unique_ptr<ClientPhishingRequest> verdict,
const std::string& access_token);
diff --git a/chromium/components/safe_browsing/content/browser/client_side_detection_service.cc b/chromium/components/safe_browsing/content/browser/client_side_detection_service.cc
index b555813e63e..aa4a5f67ffc 100644
--- a/chromium/components/safe_browsing/content/browser/client_side_detection_service.cc
+++ b/chromium/components/safe_browsing/content/browser/client_side_detection_service.cc
@@ -22,9 +22,11 @@
#include "base/time/time.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/content/browser/client_side_detection_host.h"
+#include "components/safe_browsing/content/browser/client_side_phishing_model.h"
#include "components/safe_browsing/content/common/safe_browsing.mojom.h"
#include "components/safe_browsing/content/web_ui/safe_browsing_ui.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safebrowsing_constants.h"
#include "components/safe_browsing/core/common/utils.h"
#include "components/safe_browsing/core/features.h"
#include "components/safe_browsing/core/proto/client_model.pb.h"
@@ -52,7 +54,6 @@ using content::BrowserThread;
namespace safe_browsing {
-const int ClientSideDetectionService::kInitialClientModelFetchDelayMs = 10000;
const int ClientSideDetectionService::kReportsIntervalDays = 1;
const int ClientSideDetectionService::kMaxReportsPerInterval = 3;
const int ClientSideDetectionService::kNegativeCacheIntervalDays = 1;
@@ -61,8 +62,6 @@ const int ClientSideDetectionService::kPositiveCacheIntervalMinutes = 30;
const char ClientSideDetectionService::kClientReportPhishingUrl[] =
"https://sb-ssl.google.com/safebrowsing/clientreport/phishing";
-constexpr char kAuthHeaderBearer[] = "Bearer ";
-
struct ClientSideDetectionService::ClientPhishingReportInfo {
std::unique_ptr<network::SimpleURLLoader> loader;
ClientReportPhishingRequestCallback callback;
@@ -120,25 +119,12 @@ void ClientSideDetectionService::OnPrefsUpdated() {
extended_reporting_ = extended_reporting;
if (enabled_) {
- if (!model_factory_.is_null()) {
- model_loader_ = model_factory_.Run();
- } else {
- model_loader_ = std::make_unique<ModelLoader>(
- base::BindRepeating(&ClientSideDetectionService::SendModelToRenderers,
- base::Unretained(this)),
- delegate_->GetURLLoaderFactory(), extended_reporting_);
- }
- // Refresh the models when the service is enabled. This can happen when
- // either of the preferences are toggled, or early during startup if
- // safe browsing is already enabled. In a lot of cases the model will be
- // in the cache so it won't actually be fetched from the network.
- // We delay the first model fetches to avoid slowing down browser startup.
- model_loader_->ScheduleFetch(kInitialClientModelFetchDelayMs);
+ update_model_subscription_ =
+ ClientSidePhishingModel::GetInstance()->RegisterCallback(
+ base::BindRepeating(
+ &ClientSideDetectionService::SendModelToRenderers,
+ base::Unretained(this)));
} else {
- if (model_loader_) {
- // Cancel model loads in progress.
- model_loader_->CancelFetcher();
- }
// Invoke pending callbacks with a false verdict.
for (auto& client_phishing_report : client_phishing_reports_) {
ClientPhishingReportInfo* info = client_phishing_report.second.get();
@@ -223,7 +209,6 @@ void ClientSideDetectionService::StartClientReportPhishingRequest(
}
// Fill in metadata about which model we used.
- request->set_model_filename(model_loader_->name());
*request->mutable_population() = delegate_->GetUserPopulation();
std::string request_data;
@@ -427,7 +412,9 @@ void ClientSideDetectionService::LoadPhishingReportTimesFromPrefs() {
phishing_report_times_.clear();
for (const base::Value& timestamp :
- *delegate_->GetPrefs()->GetList(prefs::kSafeBrowsingCsdPingTimestamps)) {
+ delegate_->GetPrefs()
+ ->GetList(prefs::kSafeBrowsingCsdPingTimestamps)
+ ->GetList()) {
phishing_report_times_.push_back(
base::Time::FromDoubleT(timestamp.GetDouble()));
}
@@ -444,20 +431,21 @@ GURL ClientSideDetectionService::GetClientReportUrl(
return url;
}
-ModelLoader::ClientModelStatus
-ClientSideDetectionService::GetLastModelStatus() {
- // |model_loader_| can be null in tests
- return model_loader_ ? model_loader_->last_client_model_status()
- : ModelLoader::MODEL_NEVER_FETCHED;
+std::string ClientSideDetectionService::GetModelStr() {
+ return ClientSidePhishingModel::GetInstance()->GetModelStr();
}
-std::string ClientSideDetectionService::GetModelStr() {
- return model_loader_ ? model_loader_->model_str() : "";
+CSDModelType ClientSideDetectionService::GetModelType() {
+ return ClientSidePhishingModel::GetInstance()->GetModelType();
+}
+
+base::ReadOnlySharedMemoryRegion
+ClientSideDetectionService::GetModelSharedMemoryRegion() {
+ return ClientSidePhishingModel::GetInstance()->GetModelSharedMemoryRegion();
}
-void ClientSideDetectionService::SetModelLoaderFactoryForTesting(
- base::RepeatingCallback<std::unique_ptr<ModelLoader>()> factory) {
- model_factory_ = factory;
+const base::File& ClientSideDetectionService::GetVisualTfLiteModel() {
+ return ClientSidePhishingModel::GetInstance()->GetVisualTfLiteModel();
}
void ClientSideDetectionService::SetURLLoaderFactoryForTesting(
diff --git a/chromium/components/safe_browsing/content/browser/client_side_detection_service.h b/chromium/components/safe_browsing/content/browser/client_side_detection_service.h
index 3676f680645..6399e0fe1d0 100644
--- a/chromium/components/safe_browsing/content/browser/client_side_detection_service.h
+++ b/chromium/components/safe_browsing/content/browser/client_side_detection_service.h
@@ -24,12 +24,13 @@
#include "base/containers/queue.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
-#include "components/safe_browsing/content/browser/client_side_model_loader.h"
+#include "components/safe_browsing/content/browser/client_side_phishing_model.h"
#include "components/safe_browsing/core/proto/csd.pb.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_observer.h"
@@ -124,17 +125,21 @@ class ClientSideDetectionService : public KeyedService {
// Sends a model to each renderer.
virtual void SendModelToRenderers();
- // Get the model status for the given client-side model.
- ModelLoader::ClientModelStatus GetLastModelStatus();
-
- // Returns the model string. Virtual so that mock implementation can override
- // it.
+ // Returns the model string. Used only for protobuf model. Virtual so that
+ // mock implementation can override it.
virtual std::string GetModelStr();
- // Makes ModelLoaders be constructed by calling |factory| rather than the
- // default constructor.
- void SetModelLoaderFactoryForTesting(
- base::RepeatingCallback<std::unique_ptr<ModelLoader>()> factory);
+ // Returns the model type (protobuf or flatbuffer). Virtual so that mock
+ // implementation can override it.
+ virtual CSDModelType GetModelType();
+
+ // Returns the ReadOnlySharedMemoryRegion for the flatbuffer model. Virtual so
+ // that mock implementation can override it.
+ virtual base::ReadOnlySharedMemoryRegion GetModelSharedMemoryRegion();
+
+ // Returns the TfLite model file. Virtual so that mock implementation can
+ // override it.
+ virtual const base::File& GetVisualTfLiteModel();
// Overrides the SharedURLLoaderFactory
void SetURLLoaderFactoryForTesting(
@@ -163,7 +168,6 @@ class ClientSideDetectionService : public KeyedService {
static const char kClientReportPhishingUrl[];
static const int kMaxReportsPerInterval;
- static const int kInitialClientModelFetchDelayMs;
static const int kReportsIntervalDays;
static const int kNegativeCacheIntervalDays;
static const int kPositiveCacheIntervalMinutes;
@@ -215,8 +219,6 @@ class ClientSideDetectionService : public KeyedService {
// choice of model.
bool extended_reporting_ = false;
- std::unique_ptr<ModelLoader> model_loader_;
-
// Map of client report phishing request to the corresponding callback that
// has to be invoked when the request is done.
struct ClientPhishingReportInfo;
@@ -244,11 +246,10 @@ class ClientSideDetectionService : public KeyedService {
std::vector<ClientSideDetectionHost*> csd_hosts_;
- // Factory used for constructing ModelLoaders
- base::RepeatingCallback<std::unique_ptr<ModelLoader>()> model_factory_;
-
std::unique_ptr<Delegate> delegate_;
+ base::CallbackListSubscription update_model_subscription_;
+
// Used to asynchronously call the callbacks for
// SendClientReportPhishingRequest.
base::WeakPtrFactory<ClientSideDetectionService> weak_factory_{this};
diff --git a/chromium/components/safe_browsing/content/browser/client_side_model_loader.cc b/chromium/components/safe_browsing/content/browser/client_side_model_loader.cc
index 202dec71661..1f489b663fc 100644
--- a/chromium/components/safe_browsing/content/browser/client_side_model_loader.cc
+++ b/chromium/components/safe_browsing/content/browser/client_side_model_loader.cc
@@ -87,7 +87,7 @@ int ModelLoader::GetModelNumber() {
#endif
int model_number = 0;
if (!base::StringToInt(num_str, &model_number)) {
- model_number = 6; // Default model
+ model_number = 8; // Default model
}
return model_number;
}
@@ -129,7 +129,6 @@ ModelLoader::ModelLoader(
url_loader_factory_(url_loader_factory),
last_client_model_status_(ClientModelStatus::MODEL_NEVER_FETCHED) {
DCHECK(url_.is_valid());
- StartFetch(/*only_from_cache=*/true);
}
// For testing only
diff --git a/chromium/components/safe_browsing/content/browser/client_side_model_loader.h b/chromium/components/safe_browsing/content/browser/client_side_model_loader.h
index 1da09a936d3..9d3d2851901 100644
--- a/chromium/components/safe_browsing/content/browser/client_side_model_loader.h
+++ b/chromium/components/safe_browsing/content/browser/client_side_model_loader.h
@@ -78,11 +78,6 @@ class ModelLoader {
// sequence as ScheduleFetch.
virtual void CancelFetcher();
- // Only used in tests.
- void SetModelStrForTesting(const std::string& model_str) {
- model_str_ = model_str;
- }
-
const std::string& model_str() const { return model_str_; }
const std::string& name() const { return name_; }
diff --git a/chromium/components/safe_browsing/content/browser/client_side_model_loader_unittest.cc b/chromium/components/safe_browsing/content/browser/client_side_model_loader_unittest.cc
index 04c9998a452..fdf5afb8b7c 100644
--- a/chromium/components/safe_browsing/content/browser/client_side_model_loader_unittest.cc
+++ b/chromium/components/safe_browsing/content/browser/client_side_model_loader_unittest.cc
@@ -376,14 +376,14 @@ TEST_F(ModelLoaderTest, ModelNamesTest) {
EXPECT_EQ(ModelLoader::FillInModelName(false, 5),
"client_model_v5_variation_5.pb");
- // No Finch setup. Should default to 4.
+ // No Finch setup. Should default to 8.
std::unique_ptr<ModelLoader> loader;
loader = std::make_unique<ModelLoader>(base::RepeatingClosure(), nullptr,
false /* is_extended_reporting */);
- EXPECT_EQ(loader->name(), "client_model_v5_variation_6.pb");
+ EXPECT_EQ(loader->name(), "client_model_v5_variation_8.pb");
EXPECT_EQ(loader->url_.spec(),
"https://ssl.gstatic.com/safebrowsing/csd/"
- "client_model_v5_variation_6.pb");
+ "client_model_v5_variation_8.pb");
// Model 1, no extended reporting.
SetFinchModelNumber(1);
@@ -435,15 +435,4 @@ TEST_F(ModelLoaderTest, ModelHasValidHashIds) {
EXPECT_TRUE(ModelLoader::ModelHasValidHashIds(model));
}
-TEST_F(ModelLoaderTest, FetchesFromCacheAtStartup) {
- ModelLoader model_loader(base::DoNothing(), shared_loader_factory(),
- /*is_extended_reporting=*/false);
- ASSERT_NE(test_url_loader_factory()->GetPendingRequest(0), nullptr);
-
- // Check the request does not use the network
- int load_flags =
- test_url_loader_factory()->GetPendingRequest(0)->request.load_flags;
- EXPECT_NE((load_flags & net::LOAD_ONLY_FROM_CACHE), 0);
-}
-
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/content/browser/client_side_phishing_model.cc b/chromium/components/safe_browsing/content/browser/client_side_phishing_model.cc
new file mode 100644
index 00000000000..a0f81f7db1f
--- /dev/null
+++ b/chromium/components/safe_browsing/content/browser/client_side_phishing_model.cc
@@ -0,0 +1,281 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/safe_browsing/content/browser/client_side_phishing_model.h"
+
+#include <stdint.h>
+#include <memory>
+
+#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/logging.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/memory/shared_memory_mapping.h"
+#include "base/memory/singleton.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
+#include "build/build_config.h"
+#include "components/safe_browsing/core/fbs/client_model_generated.h"
+#include "components/safe_browsing/core/features.h"
+#include "components/safe_browsing/core/proto/client_model.pb.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace safe_browsing {
+
+namespace {
+
+// Command-line flag that can be used to override the current CSD model. Must be
+// provided with an absolute path.
+const char kOverrideCsdModelFlag[] = "csd-model-override-path";
+
+std::string ReadFileIntoString(base::FilePath path) {
+ if (path.empty())
+ return std::string();
+
+ base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+ if (!file.IsValid())
+ return std::string();
+
+ std::vector<char> model_data(file.GetLength());
+ if (file.ReadAtCurrentPos(model_data.data(), model_data.size()) == -1)
+ return std::string();
+
+ return std::string(model_data.begin(), model_data.end());
+}
+
+} // namespace
+
+using base::AutoLock;
+
+struct ClientSidePhishingModelSingletonTrait
+ : public base::DefaultSingletonTraits<ClientSidePhishingModel> {
+ static ClientSidePhishingModel* New() {
+ ClientSidePhishingModel* instance = new ClientSidePhishingModel();
+ return instance;
+ }
+};
+
+// --- ClientSidePhishingModel methods ---
+
+// static
+ClientSidePhishingModel* ClientSidePhishingModel::GetInstance() {
+ return base::Singleton<ClientSidePhishingModel,
+ ClientSidePhishingModelSingletonTrait>::get();
+}
+
+ClientSidePhishingModel::ClientSidePhishingModel() {
+ MaybeOverrideModel();
+}
+
+ClientSidePhishingModel::~ClientSidePhishingModel() {
+ AutoLock lock(lock_); // DCHECK fail if the lock is held.
+}
+
+base::CallbackListSubscription ClientSidePhishingModel::RegisterCallback(
+ base::RepeatingCallback<void()> callback) {
+ AutoLock lock(lock_);
+ return callbacks_.Add(std::move(callback));
+}
+
+bool ClientSidePhishingModel::IsEnabled() const {
+ return (model_type_ == CSDModelType::kFlatbuffer &&
+ mapped_region_.IsValid()) ||
+ (model_type_ == CSDModelType::kProtobuf && !model_str_.empty()) ||
+ visual_tflite_model_.IsValid();
+}
+
+std::string ClientSidePhishingModel::GetModelStr() const {
+ DCHECK(model_type_ != CSDModelType::kFlatbuffer);
+ return model_str_;
+}
+
+const base::File& ClientSidePhishingModel::GetVisualTfLiteModel() const {
+ return visual_tflite_model_;
+}
+
+CSDModelType ClientSidePhishingModel::GetModelType() const {
+ return model_type_;
+}
+
+base::ReadOnlySharedMemoryRegion
+ClientSidePhishingModel::GetModelSharedMemoryRegion() const {
+ return mapped_region_.region.Duplicate();
+}
+
+void ClientSidePhishingModel::PopulateFromDynamicUpdate(
+ const std::string& model_str,
+ base::File visual_tflite_model) {
+ AutoLock lock(lock_);
+
+ bool model_valid = false;
+ int model_version_field = 0;
+ model_type_ = CSDModelType::kNone;
+
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kOverrideCsdModelFlag) &&
+ !model_str.empty()) {
+ if (base::FeatureList::IsEnabled(kClientSideDetectionModelIsFlatBuffer)) {
+ flatbuffers::Verifier verifier(
+ reinterpret_cast<const uint8_t*>(model_str.data()),
+ model_str.length());
+ model_valid = flat::VerifyClientSideModelBuffer(verifier);
+ if (model_valid) {
+ mapped_region_ =
+ base::ReadOnlySharedMemoryRegion::Create(model_str.length());
+ if (mapped_region_.IsValid()) {
+ model_type_ = CSDModelType::kFlatbuffer;
+ model_version_field =
+ flat::GetClientSideModel(model_str.data())->version();
+ memcpy(mapped_region_.mapping.memory(), model_str.data(),
+ model_str.length());
+ } else {
+ model_valid = false;
+ }
+ base::UmaHistogramBoolean(
+ "SBClientPhishing.FlatBufferMappedRegionValid",
+ mapped_region_.IsValid());
+ }
+ } else {
+ ClientSideModel model_proto;
+ model_valid = model_proto.ParseFromString(model_str);
+ if (model_valid) {
+ model_type_ = CSDModelType::kProtobuf;
+ model_version_field = model_proto.version();
+ model_str_ = model_str;
+ }
+ }
+
+ base::UmaHistogramBoolean("SBClientPhishing.ModelDynamicUpdateSuccess",
+ model_valid);
+
+ if (model_valid) {
+ // At time of writing, versions go up to 25. We set a max version of 100
+ // to give some room.
+ const int kMaxVersion = 100;
+ base::UmaHistogramExactLinear(
+ "SBClientPhishing.ModelDynamicUpdateVersion", model_version_field,
+ kMaxVersion + 1);
+ }
+ }
+
+ bool tflite_valid = visual_tflite_model.IsValid();
+ if (tflite_valid) {
+ visual_tflite_model_ = std::move(visual_tflite_model);
+ }
+
+ if (model_valid || tflite_valid) {
+ // Unretained is safe because this is a singleton.
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&ClientSidePhishingModel::NotifyCallbacksOnUI,
+ base::Unretained(this)));
+ }
+}
+
+void ClientSidePhishingModel::NotifyCallbacksOnUI() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ callbacks_.Notify();
+}
+
+void ClientSidePhishingModel::SetModelStrForTesting(
+ const std::string& model_str) {
+ AutoLock lock(lock_);
+ model_str_ = model_str;
+}
+
+void ClientSidePhishingModel::SetVisualTfLiteModelForTesting(base::File file) {
+ AutoLock lock(lock_);
+ visual_tflite_model_ = std::move(file);
+}
+
+void ClientSidePhishingModel::SetModelTypeForTesting(CSDModelType model_type) {
+ AutoLock lock(lock_);
+ model_type_ = model_type;
+}
+
+void ClientSidePhishingModel::ClearMappedRegionForTesting() {
+ AutoLock lock(lock_);
+ mapped_region_.mapping = base::WritableSharedMemoryMapping();
+ mapped_region_.region = base::ReadOnlySharedMemoryRegion();
+}
+
+void* ClientSidePhishingModel::GetFlatBufferMemoryAddressForTesting() {
+ return mapped_region_.mapping.memory();
+}
+
+void ClientSidePhishingModel::MaybeOverrideModel() {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kOverrideCsdModelFlag)) {
+ base::FilePath overriden_model_path =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+ kOverrideCsdModelFlag);
+ CSDModelType model_type =
+ base::FeatureList::IsEnabled(kClientSideDetectionModelIsFlatBuffer)
+ ? CSDModelType::kFlatbuffer
+ : CSDModelType::kProtobuf;
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock()},
+ base::BindOnce(&ReadFileIntoString, overriden_model_path),
+ // base::Unretained is safe because this is a singleton.
+ base::BindOnce(&ClientSidePhishingModel::OnGetOverridenModelData,
+ base::Unretained(this), model_type));
+ }
+}
+
+void ClientSidePhishingModel::OnGetOverridenModelData(
+ CSDModelType model_type,
+ const std::string& model_data) {
+ if (model_data.empty()) {
+ VLOG(2) << "Overriden model data is empty";
+ return;
+ }
+
+ switch (model_type) {
+ case CSDModelType::kProtobuf: {
+ std::unique_ptr<ClientSideModel> model =
+ std::make_unique<ClientSideModel>();
+ if (!model->ParseFromArray(model_data.data(), model_data.size())) {
+ VLOG(2) << "Overriden model data is not a valid ClientSideModel proto";
+ return;
+ }
+ model_type_ = model_type;
+ model_str_ = model_data;
+ break;
+ }
+ case CSDModelType::kFlatbuffer: {
+ flatbuffers::Verifier verifier(
+ reinterpret_cast<const uint8_t*>(model_data.data()),
+ model_data.length());
+ if (!flat::VerifyClientSideModelBuffer(verifier)) {
+ VLOG(2)
+ << "Overriden model data is not a valid ClientSideModel flatbuffer";
+ return;
+ }
+ mapped_region_ =
+ base::ReadOnlySharedMemoryRegion::Create(model_data.length());
+ if (!mapped_region_.IsValid()) {
+ VLOG(2) << "Could not create shared memory region for flatbuffer";
+ return;
+ }
+ memcpy(mapped_region_.mapping.memory(), model_data.data(),
+ model_data.length());
+ model_type_ = model_type;
+ break;
+ }
+ case CSDModelType::kNone:
+ VLOG(2) << "Model type should have been either proto or flatbuffer";
+ return;
+ }
+
+ VLOG(2) << "Model overriden successfully";
+
+ // Unretained is safe because this is a singleton.
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&ClientSidePhishingModel::NotifyCallbacksOnUI,
+ base::Unretained(this)));
+}
+
+} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/content/browser/client_side_phishing_model.h b/chromium/components/safe_browsing/content/browser/client_side_phishing_model.h
new file mode 100644
index 00000000000..aee7f91d8c9
--- /dev/null
+++ b/chromium/components/safe_browsing/content/browser/client_side_phishing_model.h
@@ -0,0 +1,109 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SAFE_BROWSING_CONTENT_BROWSER_CLIENT_SIDE_PHISHING_MODEL_H_
+#define COMPONENTS_SAFE_BROWSING_CONTENT_BROWSER_CLIENT_SIDE_PHISHING_MODEL_H_
+
+#include <map>
+#include <memory>
+
+#include "base/callback_list.h"
+#include "base/files/file.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/synchronization/lock.h"
+#include "components/safe_browsing/content/browser/client_side_model_loader.h"
+
+namespace safe_browsing {
+
+struct ClientSidePhishingModelSingletonTrait;
+
+enum class CSDModelType { kNone = 0, kProtobuf = 1, kFlatbuffer = 2 };
+
+// This holds the currently active client side phishing detection model.
+//
+// The data to populate it is fetched periodically from Google to get the most
+// up-to-date model.
+//
+// This is thread safe. We assume it is updated at most every few hours.
+
+class ClientSidePhishingModel {
+ public:
+ virtual ~ClientSidePhishingModel();
+
+ static ClientSidePhishingModel* GetInstance(); // Singleton
+
+ // Register a callback to be notified whenever the model changes. All
+ // notifications will occur on the UI thread.
+ base::CallbackListSubscription RegisterCallback(
+ base::RepeatingCallback<void()> callback);
+
+ // Returns whether we currently have a model.
+ bool IsEnabled() const;
+
+ // Returns model type (protobuf or flatbuffer).
+ CSDModelType GetModelType() const;
+
+ // Returns the model string, as a serialized protobuf or flatbuffer.
+ std::string GetModelStr() const;
+
+ // Returns the shared memory region for the flatbuffer.
+ base::ReadOnlySharedMemoryRegion GetModelSharedMemoryRegion() const;
+
+ // Updates the internal model string, when one is received from a component
+ // update.
+ void PopulateFromDynamicUpdate(const std::string& model_str,
+ base::File visual_tflite_model);
+
+ const base::File& GetVisualTfLiteModel() const;
+
+ // Overrides the model string for use in tests.
+ void SetModelStrForTesting(const std::string& model_str);
+ void SetVisualTfLiteModelForTesting(base::File file);
+ // Overrides model type.
+ void SetModelTypeForTesting(CSDModelType model_type);
+ // Removes mapping.
+ void ClearMappedRegionForTesting();
+ // Get flatbuffer memory address.
+ void* GetFlatBufferMemoryAddressForTesting();
+
+ // Called to check the command line and maybe override the current model.
+ void MaybeOverrideModel();
+
+ private:
+ static const int kInitialClientModelFetchDelayMs;
+
+ ClientSidePhishingModel();
+
+ void NotifyCallbacksOnUI();
+
+ // Callback when the local file overriding the model has been read.
+ void OnGetOverridenModelData(CSDModelType model_type,
+ const std::string& model_data);
+
+ // The list of callbacks to notify when a new model is ready. Protected by
+ // lock_. Will always be notified on the UI thread.
+ base::RepeatingCallbackList<void()> callbacks_;
+
+ // Model protobuf string. Protected by lock_.
+ std::string model_str_;
+
+ // Visual TFLite model file. Protected by lock_.
+ base::File visual_tflite_model_;
+
+ // Model type as inferred by feature flag. Protected by lock_.
+ CSDModelType model_type_ = CSDModelType::kNone;
+
+ // MappedReadOnlyRegion where the flatbuffer has been copied to. Protected by
+ // lock_.
+ base::MappedReadOnlyRegion mapped_region_ = base::MappedReadOnlyRegion();
+
+ mutable base::Lock lock_;
+
+ friend struct ClientSidePhishingModelSingletonTrait;
+ FRIEND_TEST_ALL_PREFIXES(ClientSidePhishingModelTest, CanOverrideWithFlag);
+};
+
+} // namespace safe_browsing
+
+#endif // COMPONENTS_SAFE_BROWSING_CONTENT_BROWSER_CLIENT_SIDE_PHISHING_MODEL_H_
diff --git a/chromium/components/safe_browsing/content/browser/client_side_phishing_model_unittest.cc b/chromium/components/safe_browsing/content/browser/client_side_phishing_model_unittest.cc
new file mode 100644
index 00000000000..00879734bcd
--- /dev/null
+++ b/chromium/components/safe_browsing/content/browser/client_side_phishing_model_unittest.cc
@@ -0,0 +1,390 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/safe_browsing/content/browser/client_side_phishing_model.h"
+
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/files/file.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/memory/shared_memory_mapping.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_command_line.h"
+#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
+#include "components/safe_browsing/core/fbs/client_model_generated.h"
+#include "components/safe_browsing/core/features.h"
+#include "components/safe_browsing/core/proto/client_model.pb.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace safe_browsing {
+
+namespace {
+
+void ResetClientSidePhishingModel() {
+ ClientSidePhishingModel::GetInstance()->SetModelStrForTesting("");
+ ClientSidePhishingModel::GetInstance()->SetVisualTfLiteModelForTesting(
+ base::File());
+ ClientSidePhishingModel::GetInstance()->ClearMappedRegionForTesting();
+ ClientSidePhishingModel::GetInstance()->SetModelTypeForTesting(
+ CSDModelType::kNone);
+}
+
+std::string CreateFlatBufferString() {
+ flatbuffers::FlatBufferBuilder builder(1024);
+ flat::ClientSideModelBuilder csd_model_builder(builder);
+ builder.Finish(csd_model_builder.Finish());
+ return std::string(reinterpret_cast<char*>(builder.GetBufferPointer()),
+ builder.GetSize());
+}
+
+void GetFlatBufferStringFromMappedMemory(
+ base::ReadOnlySharedMemoryRegion region,
+ std::string* output) {
+ ASSERT_TRUE(region.IsValid());
+ base::ReadOnlySharedMemoryMapping mapping = region.Map();
+ ASSERT_TRUE(mapping.IsValid());
+ *output = std::string(reinterpret_cast<const char*>(mapping.memory()),
+ mapping.size());
+}
+
+} // namespace
+
+TEST(ClientSidePhishingModelTest, NotifiesOnUpdate) {
+ ResetClientSidePhishingModel();
+
+ content::BrowserTaskEnvironment task_environment;
+ base::RunLoop run_loop;
+ bool called = false;
+ base::CallbackListSubscription subscription =
+ ClientSidePhishingModel::GetInstance()->RegisterCallback(
+ base::BindRepeating(
+ [](base::RepeatingClosure quit_closure, bool* called) {
+ *called = true;
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &called));
+
+ ClientSideModel model;
+ model.set_max_words_per_term(0); // Required field.
+ ClientSidePhishingModel::GetInstance()->PopulateFromDynamicUpdate(
+ model.SerializeAsString(), base::File());
+
+ run_loop.Run();
+
+ EXPECT_TRUE(called);
+ EXPECT_EQ(model.SerializeAsString(),
+ ClientSidePhishingModel::GetInstance()->GetModelStr());
+ EXPECT_TRUE(ClientSidePhishingModel::GetInstance()->IsEnabled());
+}
+
+TEST(ClientSidePhishingModelTest, RejectsInvalidProto) {
+ ResetClientSidePhishingModel();
+ ClientSidePhishingModel::GetInstance()->PopulateFromDynamicUpdate(
+ "bad proto", base::File());
+ EXPECT_FALSE(ClientSidePhishingModel::GetInstance()->IsEnabled());
+}
+
+TEST(ClientSidePhishingModelTest, RejectsInvalidFlatbuffer) {
+ ResetClientSidePhishingModel();
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatures(
+ /*enabled_features=*/{kClientSideDetectionModelIsFlatBuffer},
+ /*disabled_features=*/{});
+ ClientSidePhishingModel::GetInstance()->PopulateFromDynamicUpdate(
+ "bad flatbuffer", base::File());
+ EXPECT_FALSE(ClientSidePhishingModel::GetInstance()->IsEnabled());
+}
+
+TEST(ClientSidePhishingModelTest, NotifiesForFile) {
+ ResetClientSidePhishingModel();
+
+ content::BrowserTaskEnvironment task_environment;
+ base::RunLoop run_loop;
+ bool called = false;
+ base::CallbackListSubscription subscription =
+ ClientSidePhishingModel::GetInstance()->RegisterCallback(
+ base::BindRepeating(
+ [](base::RepeatingClosure quit_closure, bool* called) {
+ *called = true;
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &called));
+
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ const base::FilePath file_path =
+ temp_dir.GetPath().AppendASCII("visual_model.tflite");
+ base::File file(file_path, base::File::FLAG_OPEN_ALWAYS |
+ base::File::FLAG_READ |
+ base::File::FLAG_WRITE);
+ const std::string file_contents = "visual model file";
+ file.WriteAtCurrentPos(file_contents.data(), file_contents.size());
+
+ ClientSidePhishingModel::GetInstance()->PopulateFromDynamicUpdate(
+ "", std::move(file));
+
+ run_loop.Run();
+
+ EXPECT_TRUE(called);
+ EXPECT_TRUE(ClientSidePhishingModel::GetInstance()->IsEnabled());
+}
+
+TEST(ClientSidePhishingModelTest, DoesNotNotifyOnBadInitialUpdate) {
+ ResetClientSidePhishingModel();
+
+ content::BrowserTaskEnvironment task_environment;
+ base::RunLoop run_loop;
+ bool called = false;
+ base::CallbackListSubscription subscription =
+ ClientSidePhishingModel::GetInstance()->RegisterCallback(
+ base::BindRepeating(
+ [](base::RepeatingClosure quit_closure, bool* called) {
+ *called = true;
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &called));
+
+ ClientSidePhishingModel::GetInstance()->PopulateFromDynamicUpdate(
+ "", base::File());
+
+ run_loop.RunUntilIdle();
+
+ EXPECT_FALSE(called);
+ EXPECT_FALSE(ClientSidePhishingModel::GetInstance()->IsEnabled());
+}
+
+TEST(ClientSidePhishingModelTest, DoesNotNotifyOnBadFollowingUpdate) {
+ ResetClientSidePhishingModel();
+
+ content::BrowserTaskEnvironment task_environment;
+ base::RunLoop run_loop;
+
+ // Perform a valid update.
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ const base::FilePath file_path =
+ temp_dir.GetPath().AppendASCII("visual_model.tflite");
+ base::File file(file_path, base::File::FLAG_OPEN_ALWAYS |
+ base::File::FLAG_READ |
+ base::File::FLAG_WRITE);
+ const std::string file_contents = "visual model file";
+ file.WriteAtCurrentPos(file_contents.data(), file_contents.size());
+
+ ClientSidePhishingModel::GetInstance()->PopulateFromDynamicUpdate(
+ "", std::move(file));
+
+ run_loop.RunUntilIdle();
+
+ // Perform an invalid update.
+ bool called = false;
+ base::CallbackListSubscription subscription =
+ ClientSidePhishingModel::GetInstance()->RegisterCallback(
+ base::BindRepeating(
+ [](base::RepeatingClosure quit_closure, bool* called) {
+ *called = true;
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &called));
+
+ ClientSidePhishingModel::GetInstance()->PopulateFromDynamicUpdate(
+ "", base::File());
+
+ run_loop.RunUntilIdle();
+
+ EXPECT_FALSE(called);
+ EXPECT_TRUE(ClientSidePhishingModel::GetInstance()->IsEnabled());
+}
+
+TEST(ClientSidePhishingModelTest, CanOverrideProtoWithFlag) {
+ ResetClientSidePhishingModel();
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ const base::FilePath file_path =
+ temp_dir.GetPath().AppendASCII("overridden_model.proto");
+ base::File file(file_path, base::File::FLAG_OPEN_ALWAYS |
+ base::File::FLAG_READ |
+ base::File::FLAG_WRITE);
+ ClientSideModel model_proto;
+ model_proto.set_version(123);
+ model_proto.set_max_words_per_term(0); // Required field
+ const std::string file_contents = model_proto.SerializeAsString();
+ file.WriteAtCurrentPos(file_contents.data(), file_contents.size());
+
+ base::test::ScopedCommandLine command_line;
+ command_line.GetProcessCommandLine()->AppendSwitchPath(
+ "--csd-model-override-path", file_path);
+
+ content::BrowserTaskEnvironment task_environment;
+ base::RunLoop run_loop;
+ bool called = false;
+ base::CallbackListSubscription subscription =
+ ClientSidePhishingModel::GetInstance()->RegisterCallback(
+ base::BindRepeating(
+ [](base::RepeatingClosure quit_closure, bool* called) {
+ *called = true;
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &called));
+
+ ClientSidePhishingModel::GetInstance()->MaybeOverrideModel();
+
+ run_loop.Run();
+
+ EXPECT_EQ(ClientSidePhishingModel::GetInstance()->GetModelStr(),
+ file_contents);
+ EXPECT_EQ(ClientSidePhishingModel::GetInstance()->GetModelType(),
+ CSDModelType::kProtobuf);
+ EXPECT_TRUE(called);
+}
+
+TEST(ClientSidePhishingModelTest, CanOverrideFlatBufferWithFlag) {
+ ResetClientSidePhishingModel();
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatures(
+ /*enabled_features=*/{kClientSideDetectionModelIsFlatBuffer},
+ /*disabled_features=*/{});
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ const base::FilePath file_path =
+ temp_dir.GetPath().AppendASCII("overridden_model.fb");
+ base::File file(file_path, base::File::FLAG_OPEN_ALWAYS |
+ base::File::FLAG_READ |
+ base::File::FLAG_WRITE);
+
+ const std::string file_contents = CreateFlatBufferString();
+ file.WriteAtCurrentPos(file_contents.data(), file_contents.size());
+
+ base::test::ScopedCommandLine command_line;
+ command_line.GetProcessCommandLine()->AppendSwitchPath(
+ "csd-model-override-path", file_path);
+
+ content::BrowserTaskEnvironment task_environment;
+ base::RunLoop run_loop;
+ bool called = false;
+ base::CallbackListSubscription subscription =
+ ClientSidePhishingModel::GetInstance()->RegisterCallback(
+ base::BindRepeating(
+ [](base::RepeatingClosure quit_closure, bool* called) {
+ *called = true;
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &called));
+
+ ClientSidePhishingModel::GetInstance()->MaybeOverrideModel();
+
+ run_loop.Run();
+
+ std::string model_str_from_shared_mem;
+ ASSERT_NO_FATAL_FAILURE(GetFlatBufferStringFromMappedMemory(
+ ClientSidePhishingModel::GetInstance()->GetModelSharedMemoryRegion(),
+ &model_str_from_shared_mem));
+ EXPECT_EQ(model_str_from_shared_mem, file_contents);
+ EXPECT_EQ(ClientSidePhishingModel::GetInstance()->GetModelType(),
+ CSDModelType::kFlatbuffer);
+ EXPECT_TRUE(called);
+}
+
+TEST(ClientSidePhishingModelTest, AcceptsValidFlatbufferIfFeatureEnabled) {
+ ResetClientSidePhishingModel();
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatures(
+ /*enabled_features=*/{kClientSideDetectionModelIsFlatBuffer},
+ /*disabled_features=*/{});
+ content::BrowserTaskEnvironment task_environment;
+ base::RunLoop run_loop;
+ bool called = false;
+ base::CallbackListSubscription subscription =
+ ClientSidePhishingModel::GetInstance()->RegisterCallback(
+ base::BindRepeating(
+ [](base::RepeatingClosure quit_closure, bool* called) {
+ *called = true;
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &called));
+
+ const std::string model_str = CreateFlatBufferString();
+ ClientSidePhishingModel::GetInstance()->PopulateFromDynamicUpdate(
+ model_str, base::File());
+ run_loop.Run();
+
+ EXPECT_TRUE(ClientSidePhishingModel::GetInstance()->IsEnabled());
+ std::string model_str_from_shared_mem;
+ ASSERT_NO_FATAL_FAILURE(GetFlatBufferStringFromMappedMemory(
+ ClientSidePhishingModel::GetInstance()->GetModelSharedMemoryRegion(),
+ &model_str_from_shared_mem));
+ EXPECT_EQ(model_str, model_str_from_shared_mem);
+ EXPECT_EQ(ClientSidePhishingModel::GetInstance()->GetModelType(),
+ CSDModelType::kFlatbuffer);
+ EXPECT_TRUE(called);
+}
+
+TEST(ClientSidePhishingModelTest, FlatbufferonFollowingUpdate) {
+ ResetClientSidePhishingModel();
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatures(
+ /*enabled_features=*/{kClientSideDetectionModelIsFlatBuffer},
+ /*disabled_features=*/{});
+ content::BrowserTaskEnvironment task_environment;
+ base::RunLoop run_loop;
+
+ const std::string model_str1 = CreateFlatBufferString();
+ ClientSidePhishingModel::GetInstance()->PopulateFromDynamicUpdate(
+ model_str1, base::File());
+
+ run_loop.RunUntilIdle();
+ EXPECT_TRUE(ClientSidePhishingModel::GetInstance()->IsEnabled());
+ std::string model_str_from_shared_mem1;
+ ASSERT_NO_FATAL_FAILURE(GetFlatBufferStringFromMappedMemory(
+ ClientSidePhishingModel::GetInstance()->GetModelSharedMemoryRegion(),
+ &model_str_from_shared_mem1));
+ EXPECT_EQ(model_str1, model_str_from_shared_mem1);
+ EXPECT_EQ(ClientSidePhishingModel::GetInstance()->GetModelType(),
+ CSDModelType::kFlatbuffer);
+
+ // Should be able to write to memory with WritableSharedMemoryMapping field.
+ void* memory_addr = ClientSidePhishingModel::GetInstance()
+ ->GetFlatBufferMemoryAddressForTesting();
+ EXPECT_EQ(memset(memory_addr, 'G', 1), memory_addr);
+
+ bool called = false;
+ base::CallbackListSubscription subscription =
+ ClientSidePhishingModel::GetInstance()->RegisterCallback(
+ base::BindRepeating(
+ [](base::RepeatingClosure quit_closure, bool* called) {
+ *called = true;
+ std::move(quit_closure).Run();
+ },
+ run_loop.QuitClosure(), &called));
+
+ const std::string model_str2 = CreateFlatBufferString();
+ ClientSidePhishingModel::GetInstance()->PopulateFromDynamicUpdate(
+ model_str2, base::File());
+
+ run_loop.RunUntilIdle();
+ EXPECT_TRUE(called);
+ EXPECT_TRUE(ClientSidePhishingModel::GetInstance()->IsEnabled());
+ std::string model_str_from_shared_mem2;
+ ASSERT_NO_FATAL_FAILURE(GetFlatBufferStringFromMappedMemory(
+ ClientSidePhishingModel::GetInstance()->GetModelSharedMemoryRegion(),
+ &model_str_from_shared_mem2));
+ EXPECT_EQ(model_str2, model_str_from_shared_mem2);
+ EXPECT_EQ(ClientSidePhishingModel::GetInstance()->GetModelType(),
+ CSDModelType::kFlatbuffer);
+
+ // Mapping should be undone automatically, even with a region copy lying
+ // around. Death tests misbehave on Android, or the memory may be re-mapped.
+ // See https://crbug.com/815537 and base/test/gtest_util.h.
+ // Can remove this if flaky.
+#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
+ EXPECT_DEATH_IF_SUPPORTED(memset(memory_addr, 'G', 1), "");
+#endif
+}
+
+} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/content/browser/threat_details.cc b/chromium/components/safe_browsing/content/browser/threat_details.cc
index 9114911f57a..5885be6ebc9 100644
--- a/chromium/components/safe_browsing/content/browser/threat_details.cc
+++ b/chromium/components/safe_browsing/content/browser/threat_details.cc
@@ -22,6 +22,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "components/back_forward_cache/back_forward_cache_disable.h"
#include "components/history/core/browser/history_service.h"
#include "components/safe_browsing/content/base_ui_manager.h"
diff --git a/chromium/components/safe_browsing/content/browser/threat_details_history.h b/chromium/components/safe_browsing/content/browser/threat_details_history.h
index 4f76efebd5c..15fef3f85cb 100644
--- a/chromium/components/safe_browsing/content/browser/threat_details_history.h
+++ b/chromium/components/safe_browsing/content/browser/threat_details_history.h
@@ -7,7 +7,6 @@
// This class gets redirect chain for urls from the history service.
-#include <string>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/components/safe_browsing/content/browser/web_api_handshake_checker.cc b/chromium/components/safe_browsing/content/browser/web_api_handshake_checker.cc
new file mode 100644
index 00000000000..c27d442c6c3
--- /dev/null
+++ b/chromium/components/safe_browsing/content/browser/web_api_handshake_checker.cc
@@ -0,0 +1,133 @@
+// Copyright 2021 The Chromium Authors. 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/content/browser/web_api_handshake_checker.h"
+
+#include "components/safe_browsing/core/browser/safe_browsing_url_checker_impl.h"
+#include "components/safe_browsing/core/browser/url_checker_delegate.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/http/http_request_headers.h"
+
+namespace safe_browsing {
+
+class WebApiHandshakeChecker::CheckerOnIO
+ : public base::SupportsWeakPtr<WebApiHandshakeChecker::CheckerOnIO> {
+ public:
+ CheckerOnIO(base::WeakPtr<WebApiHandshakeChecker> handshake_checker,
+ GetDelegateCallback delegate_getter,
+ const GetWebContentsCallback& web_contents_getter,
+ int frame_tree_node_id)
+ : handshake_checker_(std::move(handshake_checker)),
+ delegate_getter_(std::move(delegate_getter)),
+ web_contents_getter_(web_contents_getter),
+ frame_tree_node_id_(frame_tree_node_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(handshake_checker_);
+ DCHECK(delegate_getter_);
+ DCHECK(web_contents_getter_);
+ }
+
+ void Check(const GURL& url) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ DCHECK(delegate_getter_);
+ DCHECK(web_contents_getter_);
+
+ scoped_refptr<UrlCheckerDelegate> url_checker_delegate =
+ std::move(delegate_getter_).Run();
+ bool skip_checks =
+ !url_checker_delegate ||
+ !url_checker_delegate->GetDatabaseManager()->IsSupported() ||
+ url_checker_delegate->ShouldSkipRequestCheck(
+ url, frame_tree_node_id_, /*render_process_id=*/-1,
+ /*render_frame_id=*/-1, /*originated_from_service_worker=*/false);
+ if (skip_checks) {
+ OnCompleteCheck(/*slow_check=*/false, /*proceed=*/true,
+ /*showed_interstitial=*/false);
+ return;
+ }
+
+ url_checker_ = std::make_unique<SafeBrowsingUrlCheckerImpl>(
+ net::HttpRequestHeaders(), /*load_flags=*/0,
+ network::mojom::RequestDestination::kEmpty, /*has_user_gesture=*/false,
+ url_checker_delegate, web_contents_getter_,
+ /*real_time_lookup_enabled=*/false,
+ /*can_rt_check_subresource_url=*/false,
+ /*can_check_db=*/true, /*url_lookup_service=*/nullptr);
+ url_checker_->CheckUrl(
+ url, "GET",
+ base::BindOnce(&WebApiHandshakeChecker::CheckerOnIO::OnCheckUrlResult,
+ base::Unretained(this)));
+ }
+
+ private:
+ // See comments in BrowserUrlLoaderThrottle::OnCheckUrlResult().
+ void OnCheckUrlResult(
+ SafeBrowsingUrlCheckerImpl::NativeUrlCheckNotifier* slow_check_notifier,
+ bool proceed,
+ bool showed_interstitial) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ if (!slow_check_notifier) {
+ OnCompleteCheck(/*slow_check=*/false, proceed, showed_interstitial);
+ return;
+ }
+
+ *slow_check_notifier =
+ base::BindOnce(&WebApiHandshakeChecker::CheckerOnIO::OnCompleteCheck,
+ base::Unretained(this), /*slow_check=*/true);
+ }
+
+ void OnCompleteCheck(bool slow_check,
+ bool proceed,
+ bool showed_interstitial) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&WebApiHandshakeChecker::OnCompleteCheck,
+ handshake_checker_, slow_check, proceed,
+ showed_interstitial));
+ }
+
+ base::WeakPtr<WebApiHandshakeChecker> handshake_checker_;
+ GetDelegateCallback delegate_getter_;
+ GetWebContentsCallback web_contents_getter_;
+ const int frame_tree_node_id_;
+ std::unique_ptr<SafeBrowsingUrlCheckerImpl> url_checker_;
+};
+
+WebApiHandshakeChecker::WebApiHandshakeChecker(
+ GetDelegateCallback delegate_getter,
+ const GetWebContentsCallback& web_contents_getter,
+ int frame_tree_node_id) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ io_checker_ = std::make_unique<CheckerOnIO>(
+ weak_factory_.GetWeakPtr(), std::move(delegate_getter),
+ web_contents_getter, frame_tree_node_id);
+}
+
+WebApiHandshakeChecker::~WebApiHandshakeChecker() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ content::GetIOThreadTaskRunner({})->DeleteSoon(FROM_HERE,
+ std::move(io_checker_));
+}
+
+void WebApiHandshakeChecker::Check(const GURL& url, CheckCallback callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(!check_callback_);
+ check_callback_ = std::move(callback);
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&WebApiHandshakeChecker::CheckerOnIO::Check,
+ io_checker_->AsWeakPtr(), url));
+}
+
+void WebApiHandshakeChecker::OnCompleteCheck(bool slow_check,
+ bool proceed,
+ bool showed_interstitial) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(check_callback_);
+
+ CheckResult result = proceed ? CheckResult::kProceed : CheckResult::kBlocked;
+ std::move(check_callback_).Run(result);
+}
+
+} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/content/browser/web_api_handshake_checker.h b/chromium/components/safe_browsing/content/browser/web_api_handshake_checker.h
new file mode 100644
index 00000000000..381aa131bab
--- /dev/null
+++ b/chromium/components/safe_browsing/content/browser/web_api_handshake_checker.h
@@ -0,0 +1,64 @@
+// Copyright 2021 The Chromium Authors. 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_CONTENT_BROWSER_WEB_API_HANDSHAKE_CHECKER_H_
+#define COMPONENTS_SAFE_BROWSING_CONTENT_BROWSER_WEB_API_HANDSHAKE_CHECKER_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "url/gurl.h"
+
+namespace content {
+class WebContents;
+} // namespace content
+
+namespace safe_browsing {
+
+class UrlCheckerDelegate;
+
+// Performs SafeBrowsing checks for Web API handshakes such as WebTransport.
+class WebApiHandshakeChecker {
+ public:
+ using GetDelegateCallback =
+ base::OnceCallback<scoped_refptr<UrlCheckerDelegate>()>;
+ using GetWebContentsCallback =
+ base::RepeatingCallback<content::WebContents*()>;
+
+ enum class CheckResult {
+ kProceed,
+ kBlocked,
+ };
+ using CheckCallback = base::OnceCallback<void(CheckResult)>;
+
+ WebApiHandshakeChecker(GetDelegateCallback delegate_getter,
+ const GetWebContentsCallback& web_contents_getter,
+ int frame_tree_node_id);
+ ~WebApiHandshakeChecker();
+
+ WebApiHandshakeChecker(const WebApiHandshakeChecker&) = delete;
+ WebApiHandshakeChecker& operator=(const WebApiHandshakeChecker&) = delete;
+ WebApiHandshakeChecker(WebApiHandshakeChecker&&) = delete;
+ WebApiHandshakeChecker& operator=(WebApiHandshakeChecker&&) = delete;
+
+ void Check(const GURL& url, CheckCallback callback);
+
+ private:
+ // Performs checks on the IO thread by using SafeBrowsingUrlCheckerImpl, which
+ // must live on the IO thread.
+ class CheckerOnIO;
+
+ void OnCompleteCheck(bool slow_check, bool proceed, bool showed_interstitial);
+
+ std::unique_ptr<CheckerOnIO> io_checker_;
+ CheckCallback check_callback_;
+
+ base::WeakPtrFactory<WebApiHandshakeChecker> weak_factory_{this};
+};
+
+} // namespace safe_browsing
+
+#endif // COMPONENTS_SAFE_BROWSING_CONTENT_BROWSER_WEB_API_HANDSHAKE_CHECKER_H_
diff --git a/chromium/components/safe_browsing/content/browser/web_api_handshake_checker_unittest.cc b/chromium/components/safe_browsing/content/browser/web_api_handshake_checker_unittest.cc
new file mode 100644
index 00000000000..e261cc2a04b
--- /dev/null
+++ b/chromium/components/safe_browsing/content/browser/web_api_handshake_checker_unittest.cc
@@ -0,0 +1,129 @@
+// Copyright 2021 The Chromium Authors. 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/content/browser/web_api_handshake_checker.h"
+
+#include "base/memory/scoped_refptr.h"
+#include "base/test/bind.h"
+#include "components/safe_browsing/core/browser/url_checker_delegate.h"
+#include "components/safe_browsing/core/db/fake_database_manager.h"
+#include "components/security_interstitials/core/unsafe_resource.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace safe_browsing {
+
+class FakeUrlCheckerDelegate : public UrlCheckerDelegate {
+ public:
+ explicit FakeUrlCheckerDelegate(
+ scoped_refptr<SafeBrowsingDatabaseManager> database_manager)
+ : database_manager_(database_manager),
+ threat_types_(
+ SBThreatTypeSet({safe_browsing::SB_THREAT_TYPE_URL_PHISHING})) {}
+
+ // UrlCheckerDelegate overrides:
+ void MaybeDestroyNoStatePrefetchContents(
+ base::OnceCallback<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(/*proceed=*/false, /*showed_intersitial=*/false);
+ }
+
+ void StartObservingInteractionsForDelayedBlockingPageHelper(
+ const security_interstitials::UnsafeResource& resource,
+ bool is_main_frame) override {}
+
+ bool IsUrlAllowlisted(const GURL& url) override { return false; }
+
+ void SetPolicyAllowlistDomains(
+ const std::vector<std::string>& allowlist_domains) override {}
+
+ bool ShouldSkipRequestCheck(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; }
+
+ protected:
+ friend class base::RefCountedThreadSafe<FakeUrlCheckerDelegate>;
+ ~FakeUrlCheckerDelegate() override = default;
+
+ private:
+ scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
+ SBThreatTypeSet threat_types_;
+};
+
+class WebApiHandshakeCheckerTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ database_manager_ = base::MakeRefCounted<FakeSafeBrowsingDatabaseManager>();
+ delegate_ = base::MakeRefCounted<FakeUrlCheckerDelegate>(database_manager_);
+ handshake_checker_ = std::make_unique<WebApiHandshakeChecker>(
+ base::BindOnce(&WebApiHandshakeCheckerTest::GetDelegate,
+ base::Unretained(this)),
+ base::BindRepeating(&WebApiHandshakeCheckerTest::GetWebContents,
+ base::Unretained(this)),
+ /*frame_tree_node_id=*/-1);
+ }
+
+ FakeSafeBrowsingDatabaseManager* database_manager() {
+ return database_manager_.get();
+ }
+
+ WebApiHandshakeChecker::CheckResult Check(const GURL& url) {
+ WebApiHandshakeChecker::CheckResult out;
+ base::RunLoop loop;
+ handshake_checker_->Check(
+ url, base::BindLambdaForTesting(
+ [&](WebApiHandshakeChecker::CheckResult result) {
+ out = result;
+ loop.Quit();
+ }));
+ loop.Run();
+ return out;
+ }
+
+ private:
+ scoped_refptr<UrlCheckerDelegate> GetDelegate() { return delegate_; }
+
+ content::WebContents* GetWebContents() { return nullptr; }
+
+ content::BrowserTaskEnvironment task_environment_;
+ scoped_refptr<FakeSafeBrowsingDatabaseManager> database_manager_;
+ scoped_refptr<FakeUrlCheckerDelegate> delegate_;
+ std::unique_ptr<WebApiHandshakeChecker> handshake_checker_;
+};
+
+TEST_F(WebApiHandshakeCheckerTest, CheckSafeUrl) {
+ const GURL kUrl("https://example.test");
+ EXPECT_EQ(Check(kUrl), WebApiHandshakeChecker::CheckResult::kProceed);
+}
+
+TEST_F(WebApiHandshakeCheckerTest, CheckDangerousUrl) {
+ const GURL kUrl("https://example.test");
+ database_manager()->AddDangerousUrl(kUrl, SB_THREAT_TYPE_URL_PHISHING);
+ EXPECT_EQ(Check(kUrl), WebApiHandshakeChecker::CheckResult::kBlocked);
+}
+
+} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/content/common/safe_browsing.mojom b/chromium/components/safe_browsing/content/common/safe_browsing.mojom
index fc814aa58ca..1f9144fb17e 100644
--- a/chromium/components/safe_browsing/content/common/safe_browsing.mojom
+++ b/chromium/components/safe_browsing/content/common/safe_browsing.mojom
@@ -4,7 +4,10 @@
module safe_browsing.mojom;
+
import "components/safe_browsing/core/common/safe_browsing_url_checker.mojom";
+import "mojo/public/mojom/base/read_only_file.mojom";
+import "mojo/public/mojom/base/shared_memory.mojom";
import "services/network/public/mojom/http_request_headers.mojom";
import "services/network/public/mojom/fetch_api.mojom";
import "url/mojom/url.mojom";
@@ -122,8 +125,20 @@ enum PhishingDetectorResult {
interface PhishingDetector {
// A classification model for client-side phishing detection.
// The string is an encoded safe_browsing::ClientSideModel protocol buffer, or
- // empty to disable client-side phishing detection for this renderer.
- SetPhishingModel(string model);
+ // empty to disable client-side phishing detection for this renderer. The
+ // |tflite_model| is a file handle with contents a TfLite model, which is used
+ // to classify the appearance of pages.
+ SetPhishingModel(string model, mojo_base.mojom.ReadOnlyFile? tflite_model);
+
+ // A classification model for client-side phishing detection. This call sends
+ // the model from the browser process to the renderer process. The model is
+ // sent as a safe_browsing::ClientSideModel flatbuffer string in a
+ // ReadOnlySharedMemoryRegion to client-side phishing detection on the
+ // renderer process. An invalid region is used to disable classification. The
+ // |tflite_model| is a file handle with contents a TfLite model, which is used
+ // to classify the appearance of pages.
+ SetPhishingFlatBufferModel(mojo_base.mojom.ReadOnlySharedMemoryRegion region,
+ mojo_base.mojom.ReadOnlyFile? tflite_model);
// Tells the renderer to begin phishing detection for the given toplevel URL
// which it has started loading. Returns the serialized request proto and a
diff --git a/chromium/components/safe_browsing/content/password_protection/BUILD.gn b/chromium/components/safe_browsing/content/password_protection/BUILD.gn
index 01d6f8f85d7..ea72d77d49e 100644
--- a/chromium/components/safe_browsing/content/password_protection/BUILD.gn
+++ b/chromium/components/safe_browsing/content/password_protection/BUILD.gn
@@ -79,6 +79,7 @@ source_set("password_protection_unittest") {
"//components/safe_browsing/core:csd_proto",
"//components/safe_browsing/core:features",
"//components/safe_browsing/core:verdict_cache_manager",
+ "//components/safe_browsing/core/common:common",
"//components/safe_browsing/core/common:safe_browsing_prefs",
"//components/safe_browsing/core/db:test_database_manager",
"//components/safe_browsing/core/password_protection",
diff --git a/chromium/components/safe_browsing/content/password_protection/DIR_METADATA b/chromium/components/safe_browsing/content/password_protection/DIR_METADATA
deleted file mode 100644
index 578f3dfc4ea..00000000000
--- a/chromium/components/safe_browsing/content/password_protection/DIR_METADATA
+++ /dev/null
@@ -1,5 +0,0 @@
-monorail {
- component: "Services>Safebrowsing"
-}
-
-team_email: "safebrowsing@chromium.org"
diff --git a/chromium/components/safe_browsing/content/password_protection/password_protection_request_content.cc b/chromium/components/safe_browsing/content/password_protection/password_protection_request_content.cc
index 4bc565f31bc..4e3eeb1a1a6 100644
--- a/chromium/components/safe_browsing/content/password_protection/password_protection_request_content.cc
+++ b/chromium/components/safe_browsing/content/password_protection/password_protection_request_content.cc
@@ -4,6 +4,7 @@
#include "components/safe_browsing/content/password_protection/password_protection_request_content.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/task/thread_pool.h"
#include "components/safe_browsing/content/password_protection/password_protection_navigation_throttle.h"
@@ -54,6 +55,24 @@ std::unique_ptr<VisualFeatures> ExtractVisualFeatures(
}
#endif // BUILDFLAG(SAFE_BROWSING_AVAILABLE)
+int GetMinWidthForVisualFeatures() {
+ if (base::FeatureList::IsEnabled(kVisualFeaturesSizes)) {
+ return base::GetFieldTrialParamByFeatureAsInt(
+ kVisualFeaturesSizes, "min_width", kMinWidthForVisualFeatures);
+ }
+
+ return kMinWidthForVisualFeatures;
+}
+
+int GetMinHeightForVisualFeatures() {
+ if (base::FeatureList::IsEnabled(kVisualFeaturesSizes)) {
+ return base::GetFieldTrialParamByFeatureAsInt(
+ kVisualFeaturesSizes, "min_height", kMinHeightForVisualFeatures);
+ }
+
+ return kMinHeightForVisualFeatures;
+}
+
} // namespace
PasswordProtectionRequestContent::PasswordProtectionRequestContent(
@@ -117,9 +136,10 @@ void PasswordProtectionRequestContent::MaybeLogPasswordReuseLookupEvent(
password_type(), response);
}
-void PasswordProtectionRequestContent::MaybeAddPingToWebUI() {
- web_ui_token_ =
- WebUIInfoSingleton::GetInstance()->AddToPGPings(*request_proto_);
+void PasswordProtectionRequestContent::MaybeAddPingToWebUI(
+ const std::string& oauth_token) {
+ web_ui_token_ = WebUIInfoSingleton::GetInstance()->AddToPGPings(
+ *request_proto_, oauth_token);
}
void PasswordProtectionRequestContent::MaybeAddResponseToWebUI(
@@ -235,10 +255,23 @@ void PasswordProtectionRequestContent::MaybeCollectVisualFeatures() {
!password_protection_service()->IsIncognito()) {
content::RenderWidgetHostView* view =
web_contents_ ? web_contents_->GetRenderWidgetHostView() : nullptr;
+ base::UmaHistogramBoolean(
+ "PasswordProtection.AndroidVisualFeaturesViewNull", (view == nullptr));
+ if (view) {
+ base::UmaHistogramBoolean(
+ "PasswordProtection.AndroidVisualFeaturesNativeViewNull",
+ (view->GetNativeView() == nullptr));
+ }
if (view && view->GetNativeView()) {
gfx::SizeF content_area_size = view->GetNativeView()->viewport_size();
request_proto_->set_content_area_height(content_area_size.height());
request_proto_->set_content_area_width(content_area_size.width());
+ base::UmaHistogramCounts10000(
+ "PasswordProtection.AndroidVisualFeaturesNativeViewWidth",
+ content_area_size.width());
+ base::UmaHistogramCounts10000(
+ "PasswordProtection.AndroidVisualFeaturesNativeViewHeight",
+ content_area_size.height());
}
}
#endif
@@ -247,8 +280,8 @@ void PasswordProtectionRequestContent::MaybeCollectVisualFeatures() {
trigger_type() == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE &&
password_protection_service()->IsExtendedReporting() &&
!password_protection_service()->IsIncognito() &&
- request_proto_->content_area_width() >= kMinWidthForVisualFeatures &&
- request_proto_->content_area_height() >= kMinHeightForVisualFeatures;
+ request_proto_->content_area_width() >= GetMinWidthForVisualFeatures() &&
+ request_proto_->content_area_height() >= GetMinHeightForVisualFeatures();
#if !defined(OS_ANDROID)
can_collect_visual_features &=
zoom::ZoomController::GetZoomLevelForWebContents(web_contents_) <=
diff --git a/chromium/components/safe_browsing/content/password_protection/password_protection_request_content.h b/chromium/components/safe_browsing/content/password_protection/password_protection_request_content.h
index c0e13165297..da94d7927ef 100644
--- a/chromium/components/safe_browsing/content/password_protection/password_protection_request_content.h
+++ b/chromium/components/safe_browsing/content/password_protection/password_protection_request_content.h
@@ -86,7 +86,7 @@ class PasswordProtectionRequestContent : public PasswordProtectionRequest {
RequestOutcome outcome,
const LoginReputationClientResponse* response) override;
- void MaybeAddPingToWebUI() override;
+ void MaybeAddPingToWebUI(const std::string& oauth_token) override;
void MaybeAddResponseToWebUI(
const LoginReputationClientResponse& response) override;
diff --git a/chromium/components/safe_browsing/content/password_protection/password_protection_service_unittest.cc b/chromium/components/safe_browsing/content/password_protection/password_protection_service_unittest.cc
index 225b0363b8c..46937252027 100644
--- a/chromium/components/safe_browsing/content/password_protection/password_protection_service_unittest.cc
+++ b/chromium/components/safe_browsing/content/password_protection/password_protection_service_unittest.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
@@ -29,6 +30,7 @@
#include "components/safe_browsing/content/password_protection/password_protection_navigation_throttle.h"
#include "components/safe_browsing/content/password_protection/password_protection_request_content.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safebrowsing_constants.h"
#include "components/safe_browsing/core/db/test_database_manager.h"
#include "components/safe_browsing/core/features.h"
#include "components/safe_browsing/core/password_protection/metrics_util.h"
@@ -85,6 +87,7 @@ class MockSafeBrowsingTokenFetcher : public SafeBrowsingTokenFetcher {
~MockSafeBrowsingTokenFetcher() override = default;
MOCK_METHOD1(Start, void(Callback));
+ MOCK_METHOD1(OnInvalidAccessToken, void(const std::string&));
private:
DISALLOW_COPY_AND_ASSIGN(MockSafeBrowsingTokenFetcher);
@@ -116,7 +119,10 @@ class TestPhishingDetector : public mojom::PhishingDetector {
mojo::PendingReceiver<mojom::PhishingDetector>(std::move(handle)));
}
- void SetPhishingModel(const std::string& model) override {}
+ void SetPhishingModel(const std::string& model, base::File file) override {}
+
+ void SetPhishingFlatBufferModel(base::ReadOnlySharedMemoryRegion region,
+ base::File file) override {}
void StartPhishingDetection(
const GURL& url,
@@ -462,14 +468,16 @@ class PasswordProtectionServiceBaseTest
std::unique_ptr<base::DictionaryValue> invalid_cache_expression_entry =
std::make_unique<base::DictionaryValue>();
- invalid_cache_expression_entry->SetWithoutPathExpansion(
- "invalid_cache_expression", std::move(invalid_verdict_entry));
- verdict_dictionary->SetWithoutPathExpansion(
+ invalid_cache_expression_entry->SetKey(
+ "invalid_cache_expression",
+ base::Value::FromUniquePtrValue(std::move(invalid_verdict_entry)));
+ verdict_dictionary->SetKey(
base::NumberToString(static_cast<std::underlying_type_t<PasswordType>>(
password_protection_service_
->ConvertReusedPasswordAccountTypeToPasswordType(
password_type))),
- std::move(invalid_cache_expression_entry));
+ base::Value::FromUniquePtrValue(
+ std::move(invalid_cache_expression_entry)));
content_setting_map_->SetWebsiteSettingDefaultScope(
invalid_hostname, GURL(), ContentSettingsType::PASSWORD_PROTECTION,
std::move(verdict_dictionary));
@@ -1035,7 +1043,7 @@ TEST_P(PasswordProtectionServiceBaseTest,
std::string out;
EXPECT_TRUE(request.headers.GetHeader(
net::HttpRequestHeaders::kAuthorization, &out));
- EXPECT_EQ(out, "Bearer " + access_token);
+ EXPECT_EQ(out, kAuthHeaderBearer + access_token);
}));
// Set up mock call to token fetcher.
SafeBrowsingTokenFetcher::Callback cb;
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/BUILD.gn b/chromium/components/safe_browsing/content/renderer/phishing_classifier/BUILD.gn
index 77d460c7160..b60b96b64c5 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/BUILD.gn
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/BUILD.gn
@@ -4,12 +4,16 @@
import("//build/config/features.gni")
import("//components/safe_browsing/buildflags.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
+import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
source_set("phishing_classifier") {
if (safe_browsing_mode != 0) {
sources = [
"features.cc",
"features.h",
+ "flatbuffer_scorer.cc",
+ "flatbuffer_scorer.h",
"murmurhash3_util.cc",
"murmurhash3_util.h",
"phishing_classifier.cc",
@@ -22,10 +26,13 @@ source_set("phishing_classifier") {
"phishing_term_feature_extractor.h",
"phishing_url_feature_extractor.cc",
"phishing_url_feature_extractor.h",
+ "protobuf_scorer.cc",
+ "protobuf_scorer.h",
"scorer.cc",
"scorer.h",
]
deps = [
+ "//base",
"//cc/paint",
"//components/paint_preview/common",
"//components/safe_browsing:buildflags",
@@ -34,11 +41,16 @@ source_set("phishing_classifier") {
"//components/safe_browsing/core:client_model_proto",
"//components/safe_browsing/core:csd_proto",
"//components/safe_browsing/core/common",
+ "//components/safe_browsing/core/fbs:client_model",
"//content/public/renderer",
"//crypto",
"//skia",
"//third_party/blink/public:blink_headers",
"//third_party/smhasher:murmurhash3",
+ "//third_party/tflite",
+ "//third_party/tflite:tflite_public_headers",
+ "//third_party/tflite-support",
+ "//third_party/tflite-support:tflite-support-proto",
"//ui/base",
"//ui/gfx/geometry:geometry",
"//url",
@@ -63,6 +75,7 @@ source_set("unit_tests") {
"//components/safe_browsing/content/renderer/phishing_classifier:unit_tests_support",
"//components/safe_browsing/core:client_model_proto",
"//components/safe_browsing/core:csd_proto",
+ "//components/safe_browsing/core/fbs:client_model",
"//crypto",
"//skia",
"//testing/gmock",
@@ -82,3 +95,23 @@ source_set("unit_tests_support") {
"//testing/gmock",
]
}
+
+if (use_libfuzzer) {
+ fuzzer_test("client_side_phishing_fuzzer") {
+ sources = [ "client_side_phishing_fuzzer.cc" ]
+ deps = [
+ ":client_side_phishing_fuzzer_proto",
+ ":phishing_classifier",
+ "//base:base",
+ "//components/safe_browsing/core/fbs:client_model",
+ "//skia",
+ "//third_party/libprotobuf-mutator",
+ ]
+ }
+
+ fuzzable_proto_library("client_side_phishing_fuzzer_proto") {
+ proto_in_dir = "//"
+ sources = [ "client_side_phishing_fuzzer.proto" ]
+ deps = [ "//components/safe_browsing/core:csd_proto" ]
+ }
+}
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.cc
new file mode 100644
index 00000000000..d3a7b92543c
--- /dev/null
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.cc
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.pb.h"
+#include "components/safe_browsing/content/renderer/phishing_classifier/features.h"
+#include "components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h"
+#include "testing/libfuzzer/proto/lpm_interface.h"
+
+DEFINE_PROTO_FUZZER(
+ const safe_browsing::ClientSidePhishingFuzzerCase& fuzzing_case) {
+ std::string model_str;
+ if (!fuzzing_case.model().SerializeToString(&model_str))
+ return;
+ std::unique_ptr<safe_browsing::Scorer> scorer(
+ safe_browsing::ProtobufModelScorer::Create(model_str, base::File()));
+ if (!scorer)
+ return;
+
+ safe_browsing::FeatureMap features;
+ for (const std::string& boolean_feature : fuzzing_case.boolean_features()) {
+ if (!features.AddBooleanFeature(boolean_feature))
+ return;
+ }
+
+ for (const safe_browsing::ClientSidePhishingFuzzerCase::RealFeature&
+ real_feature : fuzzing_case.real_features()) {
+ if (!features.AddRealFeature(real_feature.name(), real_feature.value()))
+ return;
+ }
+
+ scorer->ComputeScore(features);
+}
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.proto b/chromium/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.proto
new file mode 100644
index 00000000000..8695ae41317
--- /dev/null
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.proto
@@ -0,0 +1,23 @@
+// Copyright 2021 The Chromium 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 = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package safe_browsing;
+
+import "components/safe_browsing/core/proto/client_model.proto";
+
+message ClientSidePhishingFuzzerCase {
+ optional ClientSideModel model = 1;
+
+ message RealFeature {
+ optional bytes name = 1;
+ optional float value = 2;
+ }
+
+ repeated RealFeature real_features = 2;
+ repeated bytes boolean_features = 3;
+}
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc
new file mode 100644
index 00000000000..85d1292802c
--- /dev/null
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc
@@ -0,0 +1,272 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h"
+
+#include <math.h>
+
+#include <memory>
+
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/memory/shared_memory_mapping.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "components/safe_browsing/content/renderer/phishing_classifier/features.h"
+#include "components/safe_browsing/core/common/visual_utils.h"
+#include "components/safe_browsing/core/proto/client_model.pb.h"
+#include "components/safe_browsing/core/proto/csd.pb.h"
+#include "content/public/renderer/render_thread.h"
+#include "crypto/sha2.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h"
+#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/vision/image_classifier.h"
+#include "third_party/tflite/src/tensorflow/lite/kernels/builtin_op_kernels.h"
+#include "third_party/tflite/src/tensorflow/lite/op_resolver.h"
+
+namespace safe_browsing {
+
+namespace {
+bool VerifyCSDFlatBufferIndicesAndFields(const flat::ClientSideModel* model) {
+ const flatbuffers::Vector<flatbuffers::Offset<flat::Hash>>* hashes =
+ model->hashes();
+ if (!hashes)
+ return false;
+
+ const flatbuffers::Vector<
+ flatbuffers::Offset<safe_browsing::flat::ClientSideModel_::Rule>>* rules =
+ model->rule();
+ if (!rules)
+ return false;
+ for (const flat::ClientSideModel_::Rule* rule : *model->rule()) {
+ if (!rule || !rule->feature())
+ return false;
+ for (int32_t feature : *rule->feature()) {
+ if (feature < 0 || feature >= static_cast<int32_t>(hashes->size())) {
+ return false;
+ }
+ }
+ }
+
+ const flatbuffers::Vector<int32_t>* page_terms = model->page_term();
+ if (!page_terms)
+ return false;
+ for (int32_t page_term_idx : *page_terms) {
+ if (page_term_idx < 0 ||
+ page_term_idx >= static_cast<int32_t>(hashes->size())) {
+ return false;
+ }
+ }
+
+ const flatbuffers::Vector<uint32_t>* page_words = model->page_word();
+ if (!page_words)
+ return false;
+
+ const flat::TfLiteModelMetadata* metadata = model->tflite_metadata();
+ if (!metadata)
+ return false;
+ const flatbuffers::Vector<
+ flatbuffers::Offset<flat::TfLiteModelMetadata_::Threshold>>* thresholds =
+ metadata->thresholds();
+ if (!thresholds)
+ return false;
+ for (const flat::TfLiteModelMetadata_::Threshold* threshold : *thresholds) {
+ if (!threshold || !threshold->label())
+ return false;
+ }
+
+ return true;
+}
+
+std::string HashToString(const flat::Hash* hash) {
+ return std::string(reinterpret_cast<const char*>(hash->data()->Data()),
+ hash->data()->size());
+}
+
+void RecordScorerCreationStatus(ScorerCreationStatus status) {
+ UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.FlatBufferScorer.CreationStatus",
+ status, SCORER_STATUS_MAX);
+}
+
+} // namespace
+
+FlatBufferModelScorer::FlatBufferModelScorer() = default;
+FlatBufferModelScorer::~FlatBufferModelScorer() = default;
+
+/* static */
+FlatBufferModelScorer* FlatBufferModelScorer::Create(
+ base::ReadOnlySharedMemoryRegion region,
+ base::File visual_tflite_model) {
+ std::unique_ptr<FlatBufferModelScorer> scorer(new FlatBufferModelScorer());
+
+ if (!region.IsValid()) {
+ RecordScorerCreationStatus(SCORER_FAIL_FLATBUFFER_INVALID_REGION);
+ return nullptr;
+ }
+
+ base::ReadOnlySharedMemoryMapping mapping = region.Map();
+ if (!mapping.IsValid()) {
+ RecordScorerCreationStatus(SCORER_FAIL_FLATBUFFER_INVALID_MAPPING);
+ return nullptr;
+ }
+
+ flatbuffers::Verifier verifier(
+ reinterpret_cast<const uint8_t*>(mapping.memory()), mapping.size());
+ if (!flat::VerifyClientSideModelBuffer(verifier)) {
+ RecordScorerCreationStatus(SCORER_FAIL_FLATBUFFER_FAILED_VERIFY);
+ return nullptr;
+ }
+ scorer->flatbuffer_model_ = flat::GetClientSideModel(mapping.memory());
+
+ if (!VerifyCSDFlatBufferIndicesAndFields(scorer->flatbuffer_model_)) {
+ RecordScorerCreationStatus(SCORER_FAIL_FLATBUFFER_BAD_INDICES_OR_FIELDS);
+ return nullptr;
+ }
+
+ // Only do this part if the visual model file exists
+ if (visual_tflite_model.IsValid()) {
+ if (!scorer->visual_tflite_model_.Initialize(
+ std::move(visual_tflite_model))) {
+ RecordScorerCreationStatus(SCORER_FAIL_MAP_VISUAL_TFLITE_MODEL);
+ return nullptr;
+ } else {
+ for (const flat::TfLiteModelMetadata_::Threshold* flat_threshold :
+ *(scorer->flatbuffer_model_->tflite_metadata()->thresholds())) {
+ TfLiteModelMetadata::Threshold* threshold = scorer->thresholds_.Add();
+ threshold->set_label(flat_threshold->label()->str());
+ threshold->set_threshold(flat_threshold->threshold());
+ }
+ }
+ }
+
+ RecordScorerCreationStatus(SCORER_SUCCESS);
+ scorer->flatbuffer_mapping_ = std::move(mapping);
+
+ return scorer.release();
+}
+
+double FlatBufferModelScorer::ComputeRuleScore(
+ const flat::ClientSideModel_::Rule* rule,
+ const FeatureMap& features) const {
+ const std::unordered_map<std::string, double>& feature_map =
+ features.features();
+ double rule_score = 1.0;
+ for (int32_t feature : *rule->feature()) {
+ const flat::Hash* hash = flatbuffer_model_->hashes()->Get(feature);
+ std::string hash_str(reinterpret_cast<const char*>(hash->data()->Data()),
+ hash->data()->size());
+ const auto it = feature_map.find(hash_str);
+ if (it == feature_map.end() || it->second == 0.0) {
+ // If the feature of the rule does not exist in the given feature map the
+ // feature weight is considered to be zero. If the feature weight is zero
+ // we leave early since we know that the rule score will be zero.
+ return 0.0;
+ }
+ rule_score *= it->second;
+ }
+ return rule_score * rule->weight();
+}
+
+double FlatBufferModelScorer::ComputeScore(const FeatureMap& features) const {
+ double logodds = 0.0;
+ for (const flat::ClientSideModel_::Rule* rule : *flatbuffer_model_->rule()) {
+ logodds += ComputeRuleScore(rule, features);
+ }
+ return LogOdds2Prob(logodds);
+}
+
+// Only DOM model implemented for FlatBuffer.
+void FlatBufferModelScorer::GetMatchingVisualTargets(
+ const SkBitmap& bitmap,
+ std::unique_ptr<ClientPhishingRequest> request,
+ base::OnceCallback<void(std::unique_ptr<ClientPhishingRequest>)> callback)
+ const {
+ NOTIMPLEMENTED();
+}
+
+void FlatBufferModelScorer::ApplyVisualTfLiteModel(
+ const SkBitmap& bitmap,
+ base::OnceCallback<void(std::vector<double>)> callback) const {
+ DCHECK(content::RenderThread::IsMainThread());
+ if (visual_tflite_model_.IsValid()) {
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&ApplyVisualTfLiteModelHelper, bitmap,
+ flatbuffer_model_->tflite_metadata()->input_width(),
+ flatbuffer_model_->tflite_metadata()->input_height(),
+ std::string(reinterpret_cast<const char*>(
+ visual_tflite_model_.data()),
+ visual_tflite_model_.length())),
+ std::move(callback));
+ } else {
+ std::move(callback).Run(std::vector<double>());
+ }
+}
+
+int FlatBufferModelScorer::model_version() const {
+ return flatbuffer_model_->version();
+}
+
+bool FlatBufferModelScorer::has_page_term(const std::string& str) const {
+ const flatbuffers::Vector<flatbuffers::Offset<flat::Hash>>* hashes =
+ flatbuffer_model_->hashes();
+ flatbuffers::Vector<flatbuffers::Offset<flat::Hash>>::const_iterator
+ hashes_iter =
+ std::lower_bound(hashes->begin(), hashes->end(), str,
+ [](const flat::Hash* hash, const std::string& str) {
+ std::string hash_str = HashToString(hash);
+ return hash_str.compare(str) < 0;
+ });
+ if (hashes_iter == hashes->end() || HashToString(*hashes_iter) != str)
+ return false;
+ int index = hashes_iter - hashes->begin();
+ const flatbuffers::Vector<int32_t>* page_terms =
+ flatbuffer_model_->page_term();
+ return std::binary_search(page_terms->begin(), page_terms->end(), index);
+}
+
+base::RepeatingCallback<bool(const std::string&)>
+FlatBufferModelScorer::find_page_term_callback() const {
+ return base::BindRepeating(&FlatBufferModelScorer::has_page_term,
+ base::Unretained(this));
+}
+
+bool FlatBufferModelScorer::has_page_word(uint32_t page_word_hash) const {
+ const flatbuffers::Vector<uint32_t>* page_words =
+ flatbuffer_model_->page_word();
+ return std::binary_search(page_words->begin(), page_words->end(),
+ page_word_hash);
+}
+
+base::RepeatingCallback<bool(uint32_t)>
+FlatBufferModelScorer::find_page_word_callback() const {
+ return base::BindRepeating(&FlatBufferModelScorer::has_page_word,
+ base::Unretained(this));
+}
+
+size_t FlatBufferModelScorer::max_words_per_term() const {
+ return flatbuffer_model_->max_words_per_term();
+}
+uint32_t FlatBufferModelScorer::murmurhash3_seed() const {
+ return flatbuffer_model_->murmur_hash_seed();
+}
+size_t FlatBufferModelScorer::max_shingles_per_page() const {
+ return flatbuffer_model_->max_shingles_per_page();
+}
+size_t FlatBufferModelScorer::shingle_size() const {
+ return flatbuffer_model_->shingle_size();
+}
+float FlatBufferModelScorer::threshold_probability() const {
+ return flatbuffer_model_->threshold_probability();
+}
+int FlatBufferModelScorer::tflite_model_version() const {
+ return flatbuffer_model_->tflite_metadata()->version();
+}
+const google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>&
+FlatBufferModelScorer::tflite_thresholds() const {
+ return thresholds_;
+}
+
+} // namespace safe_browsing \ No newline at end of file
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h b/chromium/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h
new file mode 100644
index 00000000000..7c9f9b843d0
--- /dev/null
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h
@@ -0,0 +1,96 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This class loads a client-side flatbuffer model from a
+// ReadOnlySharedMemoryRegion and lets you compute a phishing score
+// for a set of previously extracted features. The phishing score corresponds
+// to the probability that the features are indicative of a phishing site.
+//
+// For more details on how the score is actually computed for a given model
+// and a given set of features read the comments in client_model.fbs file.
+//
+// See features.h for a list of features that are currently used.
+
+#ifndef COMPONENTS_SAFE_BROWSING_CONTENT_RENDERER_PHISHING_CLASSIFIER_FLATBUFFER_SCORER_H_
+#define COMPONENTS_SAFE_BROWSING_CONTENT_RENDERER_PHISHING_CLASSIFIER_FLATBUFFER_SCORER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <unordered_set>
+
+#include "base/callback.h"
+#include "base/files/file.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/macros.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/strings/string_piece.h"
+#include "components/safe_browsing/content/renderer/phishing_classifier/scorer.h"
+#include "components/safe_browsing/core/fbs/client_model_generated.h"
+#include "components/safe_browsing/core/proto/client_model.pb.h"
+#include "components/safe_browsing/core/proto/csd.pb.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace safe_browsing {
+class FeatureMap;
+
+class FlatBufferModelScorer : public Scorer {
+ public:
+ ~FlatBufferModelScorer() override;
+
+ // Factory method which creates a new Scorer object by parsing the given
+ // flatbuffer or tflite model. If parsing fails this method returns NULL.
+ // Use this only if region is valid.
+ static FlatBufferModelScorer* Create(base::ReadOnlySharedMemoryRegion region,
+ base::File visual_tflite_model);
+
+ double ComputeScore(const FeatureMap& features) const override;
+
+ void GetMatchingVisualTargets(
+ const SkBitmap& bitmap,
+ std::unique_ptr<ClientPhishingRequest> request,
+ base::OnceCallback<void(std::unique_ptr<ClientPhishingRequest>)> callback)
+ const override;
+
+ void ApplyVisualTfLiteModel(
+ const SkBitmap& bitmap,
+ base::OnceCallback<void(std::vector<double>)> callback) const override;
+
+ int model_version() const override;
+ size_t max_words_per_term() const override;
+ uint32_t murmurhash3_seed() const override;
+ size_t max_shingles_per_page() const override;
+ size_t shingle_size() const override;
+ float threshold_probability() const override;
+ int tflite_model_version() const override;
+ const google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>&
+ tflite_thresholds() const override;
+ base::RepeatingCallback<bool(uint32_t)> find_page_word_callback()
+ const override;
+ base::RepeatingCallback<bool(const std::string&)> find_page_term_callback()
+ const override;
+
+ private:
+ friend class PhishingScorerTest;
+
+ bool has_page_term(const std::string& str) const;
+ bool has_page_word(uint32_t page_word_hash) const;
+ FlatBufferModelScorer();
+
+ double ComputeRuleScore(const flat::ClientSideModel_::Rule* rule,
+ const FeatureMap& features) const;
+
+ // Unowned. Points within flatbuffer_mapping_ and should not be free()d.
+ // It remains valid till flatbuffer_mapping_ is valid and should be reassigned
+ // if the mapping is updated.
+ const flat::ClientSideModel* flatbuffer_model_;
+ base::ReadOnlySharedMemoryMapping flatbuffer_mapping_;
+ google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>
+ thresholds_;
+};
+
+} // namespace safe_browsing
+
+#endif // COMPONENTS_SAFE_BROWSING_CONTENT_RENDERER_PHISHING_CLASSIFIER_FLATBUFFER_SCORER_H_ \ No newline at end of file
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
index bba21eab8e9..f3e7fb24555 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
@@ -19,6 +19,7 @@
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
#include "cc/paint/skia_paint_canvas.h"
#include "components/paint_preview/common/paint_preview_tracker.h"
#include "components/safe_browsing/buildflags.h"
@@ -66,7 +67,7 @@ void PhishingClassifier::set_phishing_scorer(const Scorer* scorer) {
url_extractor_ = std::make_unique<PhishingUrlFeatureExtractor>();
dom_extractor_ = std::make_unique<PhishingDOMFeatureExtractor>();
term_extractor_ = std::make_unique<PhishingTermFeatureExtractor>(
- &scorer_->page_terms(), &scorer_->page_words(),
+ scorer_->find_page_term_callback(), scorer_->find_page_word_callback(),
scorer_->max_words_per_term(), scorer_->murmurhash3_seed(),
scorer_->max_shingles_per_page(), scorer_->shingle_size());
} else {
@@ -84,6 +85,8 @@ bool PhishingClassifier::is_ready() const {
void PhishingClassifier::BeginClassification(const std::u16string* page_text,
DoneCallback done_callback) {
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("safe_browsing", "PhishingClassification",
+ this);
DCHECK(is_ready());
// The RenderView should have called CancelPendingClassification() before
@@ -166,7 +169,11 @@ void PhishingClassifier::TermExtractionFinished(bool success) {
#if BUILDFLAG(FULL_SAFE_BROWSING)
ExtractVisualFeatures();
#else
- VisualExtractionFinished(true);
+ if (scorer_->HasVisualTfLiteModel()) {
+ ExtractVisualFeatures();
+ } else {
+ VisualExtractionFinished(true);
+ }
#endif
} else {
RunFailureCallback();
@@ -176,6 +183,7 @@ void PhishingClassifier::TermExtractionFinished(bool success) {
void PhishingClassifier::ExtractVisualFeatures() {
DCHECK(content::RenderThread::IsMainThread());
base::TimeTicks start_time = base::TimeTicks::Now();
+ TRACE_EVENT0("safe_browsing", "ExtractVisualFeatures");
blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
gfx::SizeF viewport_size = frame->View()->VisualViewportSize();
@@ -186,7 +194,7 @@ void PhishingClassifier::ExtractVisualFeatures() {
{2.22222f, 0.909672f, 0.0903276f, 0.222222f, 0.0812429f, 0, 0},
SkNamedGamut::kRec2020);
SkImageInfo bitmap_info = SkImageInfo::Make(
- bounds.width(), bounds.height(), SkColorType::kRGBA_8888_SkColorType,
+ bounds.width(), bounds.height(), SkColorType::kN32_SkColorType,
SkAlphaType::kUnpremul_SkAlphaType, rec2020);
if (!bitmap_->tryAllocPixels(bitmap_info))
return VisualExtractionFinished(/*success=*/false);
@@ -197,7 +205,8 @@ void PhishingClassifier::ExtractVisualFeatures() {
/*is_main_frame=*/true);
cc_canvas.SetPaintPreviewTracker(tracker.get());
VisualExtractionFinished(frame->CapturePaintPreview(
- bounds, &cc_canvas, /*include_linked_destinations=*/false));
+ bounds, &cc_canvas, /*include_linked_destinations=*/false,
+ /*skip_accelerated_content=*/false));
base::UmaHistogramTimes("SBClientPhishing.VisualFeatureTime",
base::TimeTicks::Now() - start_time);
}
@@ -242,7 +251,9 @@ void PhishingClassifier::VisualExtractionFinished(bool success) {
base::BindOnce(&PhishingClassifier::OnVisualTargetsMatched,
weak_factory_.GetWeakPtr()));
#else
- RunCallback(*verdict);
+ scorer_->ApplyVisualTfLiteModel(
+ *bitmap_, base::BindOnce(&PhishingClassifier::OnVisualTfLiteModelDone,
+ weak_factory_.GetWeakPtr(), std::move(verdict)));
#endif
}
@@ -255,10 +266,39 @@ void PhishingClassifier::OnVisualTargetsMatched(
base::UmaHistogramTimes("SBClientPhishing.VisualComparisonTime",
base::TimeTicks::Now() - visual_matching_start_);
+ scorer_->ApplyVisualTfLiteModel(
+ *bitmap_, base::BindOnce(&PhishingClassifier::OnVisualTfLiteModelDone,
+ weak_factory_.GetWeakPtr(), std::move(verdict)));
+}
+
+void PhishingClassifier::OnVisualTfLiteModelDone(
+ std::unique_ptr<ClientPhishingRequest> verdict,
+ std::vector<double> result) {
+ if (static_cast<int>(result.size()) > scorer_->tflite_thresholds().size()) {
+ // Model is misconfigured, so bail out.
+ RunFailureCallback();
+ return;
+ }
+
+ verdict->set_tflite_model_version(scorer_->tflite_model_version());
+ for (size_t i = 0; i < result.size(); i++) {
+ ClientPhishingRequest::CategoryScore* category =
+ verdict->add_tflite_model_scores();
+ category->set_label(scorer_->tflite_thresholds().at(i).label());
+ category->set_value(result[i]);
+
+ if (result[i] >= scorer_->tflite_thresholds().at(i).threshold()) {
+ verdict->set_is_phishing(true);
+ verdict->set_is_tflite_match(true);
+ }
+ }
+
RunCallback(*verdict);
}
void PhishingClassifier::RunCallback(const ClientPhishingRequest& verdict) {
+ TRACE_EVENT_NESTABLE_ASYNC_END0("safe_browsing", "PhishingClassification",
+ this);
std::move(done_callback_).Run(verdict);
Clear();
}
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.h b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.h
index cd4e9434ce2..a15faa09b94 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.h
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.h
@@ -125,6 +125,11 @@ class PhishingClassifier {
// model.
void OnVisualTargetsMatched(std::unique_ptr<ClientPhishingRequest> verdict);
+ // Callback when the visual TFLite model has been applied, and returned a list
+ // of scores.
+ void OnVisualTfLiteModelDone(std::unique_ptr<ClientPhishingRequest> verdict,
+ std::vector<double> result);
+
// Helper method to run the DoneCallback and clear the state.
void RunCallback(const ClientPhishingRequest& verdict);
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.cc
index 9239ecdb6a2..92d4b88c551 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.cc
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.cc
@@ -16,8 +16,9 @@
#include "base/no_destructor.h"
#include "components/safe_browsing/content/common/safe_browsing.mojom-forward.h"
#include "components/safe_browsing/content/common/safe_browsing.mojom-shared.h"
+#include "components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h"
#include "components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.h"
-#include "components/safe_browsing/content/renderer/phishing_classifier/scorer.h"
+#include "components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h"
#include "components/safe_browsing/core/proto/csd.pb.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/render_frame.h"
@@ -79,12 +80,32 @@ PhishingClassifierDelegate::~PhishingClassifierDelegate() {
PhishingClassifierDelegates().erase(this);
}
-void PhishingClassifierDelegate::SetPhishingModel(const std::string& model) {
+void PhishingClassifierDelegate::SetPhishingModel(
+ const std::string& model,
+ base::File tflite_visual_model) {
safe_browsing::Scorer* scorer = nullptr;
- // An empty model string means we should disable client-side phishing
- // detection.
- if (!model.empty()) {
- scorer = safe_browsing::Scorer::Create(model);
+ // An empty model string and invalid model file means we should disable
+ // client-side phishing detection.
+ if (!model.empty() || tflite_visual_model.IsValid()) {
+ scorer = safe_browsing::ProtobufModelScorer::Create(
+ model, std::move(tflite_visual_model));
+ if (!scorer)
+ return;
+ }
+ for (auto* delegate : PhishingClassifierDelegates())
+ delegate->SetPhishingScorer(scorer);
+ g_phishing_scorer.Get().reset(scorer);
+}
+
+void PhishingClassifierDelegate::SetPhishingFlatBufferModel(
+ base::ReadOnlySharedMemoryRegion flatbuffer_region,
+ base::File tflite_visual_model) {
+ safe_browsing::Scorer* scorer = nullptr;
+ // An invalid region or invalid model file means we should disable
+ // client-side phishing detection.
+ if (flatbuffer_region.IsValid() || tflite_visual_model.IsValid()) {
+ scorer = safe_browsing::FlatBufferModelScorer::Create(
+ std::move(flatbuffer_region), std::move(tflite_visual_model));
if (!scorer)
return;
}
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.h b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.h
index c9df4cb9589..45e86b698eb 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.h
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier_delegate.h
@@ -11,6 +11,7 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/read_only_shared_memory_region.h"
#include "components/safe_browsing/content/common/safe_browsing.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_thread_observer.h"
@@ -49,7 +50,13 @@ class PhishingClassifierDelegate : public content::RenderFrameObserver,
~PhishingClassifierDelegate() override;
// mojom::PhishingDetector
- void SetPhishingModel(const std::string& model) override;
+ void SetPhishingModel(const std::string& model,
+ base::File tflite_visual_model) override;
+
+ // mojom::PhishingDetector
+ void SetPhishingFlatBufferModel(
+ base::ReadOnlySharedMemoryRegion flatbuffer_region,
+ base::File tflite_visual_model) override;
// Called by the RenderFrame once there is a phishing scorer available.
// The scorer is passed on to the classifier.
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_dom_feature_extractor.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_dom_feature_extractor.cc
index 3a156be84b9..a2fa8591ad1 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_dom_feature_extractor.cc
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_dom_feature_extractor.cc
@@ -16,6 +16,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "components/safe_browsing/content/renderer/phishing_classifier/features.h"
#include "content/public/renderer/render_view.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
@@ -130,6 +131,8 @@ void PhishingDOMFeatureExtractor::ExtractFeatures(blink::WebDocument document,
features_ = features;
done_callback_ = std::move(done_callback);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("safe_browsing", "ExtractDomFeatures",
+ this);
page_feature_state_ = std::make_unique<PageFeatureState>(clock_->NowTicks());
cur_document_ = document;
@@ -338,6 +341,7 @@ void PhishingDOMFeatureExtractor::RunCallback(bool success) {
clock_->NowTicks() - page_feature_state_->start_time);
DCHECK(!done_callback_.is_null());
+ TRACE_EVENT_NESTABLE_ASYNC_END0("safe_browsing", "ExtractDomFeatures", this);
std::move(done_callback_).Run(success);
Clear();
}
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.cc
index 21a779fa914..bb5b1885dfe 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.cc
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.cc
@@ -21,6 +21,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "components/safe_browsing/content/renderer/phishing_classifier/features.h"
#include "components/safe_browsing/content/renderer/phishing_classifier/murmurhash3_util.h"
#include "crypto/sha2.h"
@@ -78,14 +79,14 @@ struct PhishingTermFeatureExtractor::ExtractionState {
};
PhishingTermFeatureExtractor::PhishingTermFeatureExtractor(
- const std::unordered_set<std::string>* page_term_hashes,
- const std::unordered_set<uint32_t>* page_word_hashes,
+ base::RepeatingCallback<bool(const std::string&)> find_page_term_callback,
+ base::RepeatingCallback<bool(uint32_t)> find_page_word_callback,
size_t max_words_per_term,
uint32_t murmurhash3_seed,
size_t max_shingles_per_page,
size_t shingle_size)
- : page_term_hashes_(page_term_hashes),
- page_word_hashes_(page_word_hashes),
+ : find_page_term_callback_(find_page_term_callback),
+ find_page_word_callback_(find_page_word_callback),
max_words_per_term_(max_words_per_term),
murmurhash3_seed_(murmurhash3_seed),
max_shingles_per_page_(max_shingles_per_page),
@@ -114,6 +115,9 @@ void PhishingTermFeatureExtractor::ExtractFeatures(
// extraction so that we can start in a known state.
CancelPendingExtraction();
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("safe_browsing", "ExtractTermFeatures",
+ this);
+
page_text_ = page_text;
features_ = features;
shingle_hashes_ = shingle_hashes, done_callback_ = std::move(done_callback);
@@ -207,7 +211,7 @@ void PhishingTermFeatureExtractor::HandleWord(const base::StringPiece16& word) {
uint32_t word_hash = MurmurHash3String(word_lower, murmurhash3_seed_);
// Quick out if the word is not part of any term, which is the common case.
- if (page_word_hashes_->find(word_hash) == page_word_hashes_->end()) {
+ if (!find_page_word_callback_.Run(word_hash)) {
// Word doesn't exist in our terms so we can clear the n-gram state.
state_->previous_words.clear();
state_->previous_word_sizes.clear();
@@ -225,16 +229,15 @@ void PhishingTermFeatureExtractor::HandleWord(const base::StringPiece16& word) {
//
state_->previous_words.append(word_lower);
std::string current_term = state_->previous_words;
- for (auto it = state_->previous_word_sizes.begin();
- it != state_->previous_word_sizes.end(); ++it) {
+ for (const auto& previous_word_size : state_->previous_word_sizes) {
hashes_to_check[crypto::SHA256HashString(current_term)] = current_term;
- current_term.erase(0, *it);
+ current_term.erase(0, previous_word_size);
}
// Add features for any hashes that match page_term_hashes_.
- for (auto it = hashes_to_check.begin(); it != hashes_to_check.end(); ++it) {
- if (page_term_hashes_->find(it->first) != page_term_hashes_->end()) {
- features_->AddBooleanFeature(features::kPageTerm + it->second);
+ for (const auto& hash_to_check : hashes_to_check) {
+ if (find_page_term_callback_.Run(hash_to_check.first)) {
+ features_->AddBooleanFeature(features::kPageTerm + hash_to_check.second);
}
}
@@ -263,6 +266,7 @@ void PhishingTermFeatureExtractor::RunCallback(bool success) {
clock_->NowTicks() - state_->start_time);
DCHECK(!done_callback_.is_null());
+ TRACE_EVENT_NESTABLE_ASYNC_END0("safe_browsing", "ExtractTermFeatures", this);
std::move(done_callback_).Run(success);
Clear();
}
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.h b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.h
index 853789a28ba..5898385d2f8 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.h
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.h
@@ -57,8 +57,8 @@ class PhishingTermFeatureExtractor {
// |clock| is used for timing feature extractor operations, and may be mocked
// for testing. The caller keeps ownership of the clock.
PhishingTermFeatureExtractor(
- const std::unordered_set<std::string>* page_term_hashes,
- const std::unordered_set<uint32_t>* page_word_hashes,
+ base::RepeatingCallback<bool(const std::string&)> find_page_term_callback,
+ base::RepeatingCallback<bool(uint32_t)> find_page_word_callback,
size_t max_words_per_term,
uint32_t murmurhash3_seed,
size_t max_shingles_per_page,
@@ -121,15 +121,16 @@ class PhishingTermFeatureExtractor {
// Clears all internal feature extraction state.
void Clear();
- // All of the term hashes that we are looking for in the page.
- const std::unordered_set<std::string>* page_term_hashes_;
+ // Check if a term hash is in the CSD Model.
+ base::RepeatingCallback<bool(const std::string&)> find_page_term_callback_;
// Murmur3 hashes of all the individual words in page_term_hashes_. If
// page_term_hashes_ included (hashed) "one" and "one two", page_word_hashes_
// would contain (hashed) "one" and "two". We do this so that we can have a
// quick out in the common case that the current word we are processing
// doesn't contain any part of one of our terms.
- const std::unordered_set<uint32_t>* page_word_hashes_;
+ // Check if a murmur3 hash word is in the CSD Model.
+ base::RepeatingCallback<bool(uint32_t)> find_page_word_callback_;
// The maximum number of words in an n-gram.
const size_t max_words_per_term_;
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor_unittest.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor_unittest.cc
index 88f5ff494cf..88b3d98abf8 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor_unittest.cc
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor_unittest.cc
@@ -29,7 +29,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using base::ASCIIToUTF16;
using ::testing::Return;
using ::testing::StrictMock;
@@ -86,10 +85,22 @@ class PhishingTermFeatureExtractorTest : public ::testing::Test {
ResetExtractor(3 /* max shingles per page */);
}
+ bool has_page_term(const std::string& str) const {
+ return term_hashes_.find(str) != term_hashes_.end();
+ }
+
+ bool has_page_word(uint32_t page_word_hash) const {
+ return word_hashes_.find(page_word_hash) != word_hashes_.end();
+ }
+
void ResetExtractor(size_t max_shingles_per_page) {
extractor_ = std::make_unique<PhishingTermFeatureExtractor>(
- &term_hashes_, &word_hashes_, 3 /* max_words_per_term */,
- kMurmurHash3Seed, max_shingles_per_page, 4 /* shingle_size */);
+ base::BindRepeating(&PhishingTermFeatureExtractorTest::has_page_term,
+ base::Unretained(this)),
+ base::BindRepeating(&PhishingTermFeatureExtractorTest::has_page_word,
+ base::Unretained(this)),
+ 3 /* max_words_per_term */, kMurmurHash3Seed, max_shingles_per_page,
+ 4 /* shingle_size */);
}
// Runs the TermFeatureExtractor on |page_text|, waiting for the
@@ -202,9 +213,7 @@ TEST_F(PhishingTermFeatureExtractorTest, ExtractFeatures) {
EXPECT_THAT(expected_shingle_hashes, testing::ContainerEq(shingle_hashes));
// Test various separators.
- page_text = ASCIIToUTF16(
- "Capitalization plus non-space\n"
- "separator... punctuation!");
+ page_text = u"Capitalization plus non-space\nseparator... punctuation!";
expected_features.Clear();
expected_features.AddBooleanFeature(features::kPageTerm +
std::string("capitalization"));
@@ -266,19 +275,15 @@ TEST_F(PhishingTermFeatureExtractorTest, ExtractFeatures) {
// Chinese translation of the phrase "hello goodbye hello goodbye". This tests
// that we can correctly separate terms in languages that don't use spaces.
- page_text = base::UTF8ToUTF16(
- "\xe4\xbd\xa0\xe5\xa5\xbd\xe5\x86\x8d\xe8\xa7\x81"
- "\xe4\xbd\xa0\xe5\xa5\xbd\xe5\x86\x8d\xe8\xa7\x81");
+ page_text = u"你好å†è§ä½ å¥½å†è§";
expected_features.Clear();
expected_features.AddBooleanFeature(features::kPageTerm +
- std::string("\xe4\xbd\xa0\xe5\xa5\xbd"));
+ std::string("你好"));
expected_features.AddBooleanFeature(features::kPageTerm +
- std::string("\xe5\x86\x8d\xe8\xa7\x81"));
+ std::string("å†è§"));
expected_shingle_hashes.clear();
expected_shingle_hashes.insert(
- MurmurHash3String("\xe4\xbd\xa0\xe5\xa5\xbd \xe5\x86\x8d\xe8\xa7\x81 "
- "\xe4\xbd\xa0\xe5\xa5\xbd \xe5\x86\x8d\xe8\xa7\x81 ",
- kMurmurHash3Seed));
+ MurmurHash3String("你好 å†è§ 你好 å†è§ ", kMurmurHash3Seed));
features.Clear();
shingle_hashes.clear();
@@ -297,7 +302,7 @@ TEST_F(PhishingTermFeatureExtractorTest, Continuation) {
// correctly, the extractor has to process the entire string of text.
std::u16string page_text(u"one ");
for (int i = 0; i < 28; ++i) {
- page_text.append(ASCIIToUTF16(base::StringPrintf("%d ", i)));
+ page_text.append(base::ASCIIToUTF16(base::StringPrintf("%d ", i)));
}
page_text.append(u"two");
@@ -423,7 +428,7 @@ TEST_F(PhishingTermFeatureExtractorTest, Continuation) {
TEST_F(PhishingTermFeatureExtractorTest, PartialExtractionTest) {
std::unique_ptr<std::u16string> page_text(new std::u16string(u"one "));
for (int i = 0; i < 28; ++i) {
- page_text->append(ASCIIToUTF16(base::StringPrintf("%d ", i)));
+ page_text->append(base::ASCIIToUTF16(base::StringPrintf("%d ", i)));
}
base::TimeTicks now = base::TimeTicks::Now();
@@ -447,7 +452,7 @@ TEST_F(PhishingTermFeatureExtractorTest, PartialExtractionTest) {
page_text = std::make_unique<std::u16string>();
for (int i = 30; i < 58; ++i) {
- page_text->append(ASCIIToUTF16(base::StringPrintf("%d ", i)));
+ page_text->append(base::ASCIIToUTF16(base::StringPrintf("%d ", i)));
}
page_text->append(u"multi word test ");
features.Clear();
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_url_feature_extractor.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_url_feature_extractor.cc
index cbd60d19ddf..83b680ae5de 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_url_feature_extractor.cc
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/phishing_url_feature_extractor.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/timer/elapsed_timer.h"
@@ -109,7 +110,7 @@ void PhishingUrlFeatureExtractor::SplitStringIntoLongAlphanumTokens(
// Copy over only the splits that are 3 or more chars long.
// TODO(bryner): Determine a meaningful min size.
if (token.length() >= kMinPathComponentLength)
- tokens->push_back(token.as_string());
+ tokens->push_back(std::string(token));
}
}
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc
new file mode 100644
index 00000000000..3e68aa97c75
--- /dev/null
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc
@@ -0,0 +1,259 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h"
+
+#include <math.h>
+
+#include <memory>
+#include <unordered_map>
+#include <unordered_set>
+
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/trace_event/trace_event.h"
+#include "components/safe_browsing/content/renderer/phishing_classifier/features.h"
+#include "components/safe_browsing/core/common/visual_utils.h"
+#include "components/safe_browsing/core/proto/client_model.pb.h"
+#include "components/safe_browsing/core/proto/csd.pb.h"
+#include "content/public/renderer/render_thread.h"
+#include "crypto/sha2.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h"
+#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/vision/image_classifier.h"
+#include "third_party/tflite/src/tensorflow/lite/kernels/builtin_op_kernels.h"
+#include "third_party/tflite/src/tensorflow/lite/op_resolver.h"
+
+namespace safe_browsing {
+
+namespace {
+std::unique_ptr<ClientPhishingRequest> GetMatchingVisualTargetsHelper(
+ const SkBitmap& bitmap,
+ const ClientSideModel& model,
+ std::unique_ptr<ClientPhishingRequest> request) {
+ DCHECK(!content::RenderThread::IsMainThread());
+
+ TRACE_EVENT0("safe_browsing", "GetMatchingVisualTargets");
+
+ VisualFeatures::BlurredImage blurred_image;
+ // Obtaining a blurred image is essential for both adding a vision match or
+ // populating telemetry.
+ if (!visual_utils::GetBlurredImage(bitmap, &blurred_image)) {
+ return request;
+ }
+ const std::string blurred_image_hash =
+ visual_utils::GetHashFromBlurredImage(blurred_image);
+
+ VisualFeatures::ColorHistogram histogram;
+ if (visual_utils::GetHistogramForImage(bitmap, &histogram)) {
+ for (const VisualTarget& target : model.vision_model().targets()) {
+ absl::optional<VisionMatchResult> result = visual_utils::IsVisualMatch(
+ bitmap, blurred_image_hash, histogram, target);
+ if (result.has_value()) {
+ *request->add_vision_match() = result.value();
+ }
+ }
+ }
+
+ // Populate these fields for telemetry purposes. They will be filtered in
+ // the browser process if they are not needed.
+ std::string raw_digest = crypto::SHA256HashString(blurred_image.data());
+ request->set_screenshot_digest(
+ base::HexEncode(raw_digest.data(), raw_digest.size()));
+ request->set_screenshot_phash(blurred_image_hash);
+ request->set_phash_dimension_size(48);
+
+ return request;
+}
+
+void RecordScorerCreationStatus(ScorerCreationStatus status) {
+ UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.ProtobufScorer.CreationStatus",
+ status, SCORER_STATUS_MAX);
+}
+
+} // namespace
+
+ProtobufModelScorer::ProtobufModelScorer() = default;
+ProtobufModelScorer::~ProtobufModelScorer() = default;
+
+/* static */
+ProtobufModelScorer* ProtobufModelScorer::Create(
+ const base::StringPiece& model_str,
+ base::File visual_tflite_model) {
+ std::unique_ptr<ProtobufModelScorer> scorer(new ProtobufModelScorer());
+ ClientSideModel& model = scorer->model_;
+ // Parse the phishing model.
+ if (!model_str.empty() &&
+ !model.ParseFromArray(model_str.data(), model_str.size())) {
+ RecordScorerCreationStatus(SCORER_FAIL_MODEL_PARSE_ERROR);
+ return nullptr;
+ }
+
+ if (!model_str.empty() && !model.IsInitialized()) {
+ // The model may be missing some required fields.
+ RecordScorerCreationStatus(SCORER_FAIL_MODEL_MISSING_FIELDS);
+ return nullptr;
+ }
+
+ if (!model_str.empty()) {
+ for (int i = 0; i < model.page_term_size(); ++i) {
+ if (model.page_term(i) < 0 || model.page_term(i) >= model.hashes().size())
+ return nullptr;
+ scorer->page_terms_.insert(model.hashes(model.page_term(i)));
+ }
+ for (int i = 0; i < model.page_word_size(); ++i) {
+ scorer->page_words_.insert(model.page_word(i));
+ }
+
+ for (const ClientSideModel::Rule& rule : model.rule()) {
+ for (int feature_index : rule.feature()) {
+ if (feature_index < 0 || feature_index >= model.hashes().size()) {
+ return nullptr;
+ }
+ }
+ }
+ }
+
+ // Only do this part if the visual model file exists
+ if (visual_tflite_model.IsValid() && !scorer->visual_tflite_model_.Initialize(
+ std::move(visual_tflite_model))) {
+ RecordScorerCreationStatus(SCORER_FAIL_MAP_VISUAL_TFLITE_MODEL);
+ return nullptr;
+ }
+
+ RecordScorerCreationStatus(SCORER_SUCCESS);
+ return scorer.release();
+}
+
+double ProtobufModelScorer::ComputeScore(const FeatureMap& features) const {
+ double logodds = 0.0;
+ for (int i = 0; i < model_.rule_size(); ++i) {
+ logodds += ComputeRuleScore(model_.rule(i), features);
+ }
+ return LogOdds2Prob(logodds);
+}
+
+void ProtobufModelScorer::GetMatchingVisualTargets(
+ const SkBitmap& bitmap,
+ std::unique_ptr<ClientPhishingRequest> request,
+ base::OnceCallback<void(std::unique_ptr<ClientPhishingRequest>)> callback)
+ const {
+ DCHECK(content::RenderThread::IsMainThread());
+
+ // Perform scoring off the main thread to avoid blocking.
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::WithBaseSyncPrimitives()},
+ base::BindOnce(&GetMatchingVisualTargetsHelper, bitmap, model_,
+ std::move(request)),
+ std::move(callback));
+}
+
+void ProtobufModelScorer::ApplyVisualTfLiteModel(
+ const SkBitmap& bitmap,
+ base::OnceCallback<void(std::vector<double>)> callback) const {
+ DCHECK(content::RenderThread::IsMainThread());
+ if (visual_tflite_model_.IsValid()) {
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&ApplyVisualTfLiteModelHelper, bitmap,
+ model_.tflite_metadata().input_width(),
+ model_.tflite_metadata().input_height(),
+ std::string(reinterpret_cast<const char*>(
+ visual_tflite_model_.data()),
+ visual_tflite_model_.length())),
+ std::move(callback));
+ } else {
+ std::move(callback).Run(std::vector<double>());
+ }
+}
+
+int ProtobufModelScorer::model_version() const {
+ return model_.version();
+}
+
+bool Scorer::HasVisualTfLiteModel() const {
+ return visual_tflite_model_.IsValid();
+}
+
+const std::unordered_set<std::string>&
+ProtobufModelScorer::get_page_terms_for_test() const {
+ return page_terms_;
+}
+
+const std::unordered_set<uint32_t>&
+ProtobufModelScorer::get_page_words_for_test() const {
+ return page_words_;
+}
+
+bool ProtobufModelScorer::has_page_term(const std::string& str) const {
+ return page_terms_.find(str) != page_terms_.end();
+}
+
+base::RepeatingCallback<bool(const std::string&)>
+ProtobufModelScorer::find_page_term_callback() const {
+ return base::BindRepeating(&ProtobufModelScorer::has_page_term,
+ base::Unretained(this));
+}
+
+bool ProtobufModelScorer::has_page_word(uint32_t page_word_hash) const {
+ return page_words_.find(page_word_hash) != page_words_.end();
+}
+
+base::RepeatingCallback<bool(uint32_t)>
+ProtobufModelScorer::find_page_word_callback() const {
+ return base::BindRepeating(&ProtobufModelScorer::has_page_word,
+ base::Unretained(this));
+}
+
+size_t ProtobufModelScorer::max_words_per_term() const {
+ return model_.max_words_per_term();
+}
+
+uint32_t ProtobufModelScorer::murmurhash3_seed() const {
+ return model_.murmur_hash_seed();
+}
+
+size_t ProtobufModelScorer::max_shingles_per_page() const {
+ return model_.max_shingles_per_page();
+}
+
+size_t ProtobufModelScorer::shingle_size() const {
+ return model_.shingle_size();
+}
+
+float ProtobufModelScorer::threshold_probability() const {
+ return model_.threshold_probability();
+}
+
+int ProtobufModelScorer::tflite_model_version() const {
+ return model_.tflite_metadata().model_version();
+}
+
+const google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>&
+ProtobufModelScorer::tflite_thresholds() const {
+ return model_.tflite_metadata().thresholds();
+}
+
+double ProtobufModelScorer::ComputeRuleScore(const ClientSideModel::Rule& rule,
+ const FeatureMap& features) const {
+ const std::unordered_map<std::string, double>& feature_map =
+ features.features();
+ double rule_score = 1.0;
+ for (int i = 0; i < rule.feature_size(); ++i) {
+ const auto it = feature_map.find(model_.hashes(rule.feature(i)));
+ if (it == feature_map.end() || it->second == 0.0) {
+ // If the feature of the rule does not exist in the given feature map the
+ // feature weight is considered to be zero. If the feature weight is zero
+ // we leave early since we know that the rule score will be zero.
+ return 0.0;
+ }
+ rule_score *= it->second;
+ }
+ return rule_score * rule.weight();
+}
+
+} // namespace safe_browsing \ No newline at end of file
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h b/chromium/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h
new file mode 100644
index 00000000000..753f30190bb
--- /dev/null
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h
@@ -0,0 +1,100 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This class loads a client-side protobuf model from a
+// string and lets you compute a phishing score
+// for a set of previously extracted features. The phishing score corresponds
+// to the probability that the features are indicative of a phishing site.
+//
+// For more details on how the score is actually computed for a given model
+// and a given set of features read the comments in client_model.proto file.
+//
+// See features.h for a list of features that are currently used.
+
+#ifndef COMPONENTS_SAFE_BROWSING_CONTENT_RENDERER_PHISHING_CLASSIFIER_PROTOBUF_SCORER_H_
+#define COMPONENTS_SAFE_BROWSING_CONTENT_RENDERER_PHISHING_CLASSIFIER_PROTOBUF_SCORER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <unordered_set>
+
+#include "base/callback.h"
+#include "base/files/file.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "components/safe_browsing/content/renderer/phishing_classifier/scorer.h"
+#include "components/safe_browsing/core/proto/client_model.pb.h"
+#include "components/safe_browsing/core/proto/csd.pb.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace safe_browsing {
+class FeatureMap;
+
+class ProtobufModelScorer : public Scorer {
+ public:
+ ~ProtobufModelScorer() override;
+
+ // Factory method which creates a new Scorer object by parsing the given
+ // model. If parsing fails this method returns NULL.
+ // Can use this if model_str is empty.
+ static ProtobufModelScorer* Create(const base::StringPiece& model_str,
+ base::File visual_tflite_model);
+
+ double ComputeScore(const FeatureMap& features) const override;
+
+ void GetMatchingVisualTargets(
+ const SkBitmap& bitmap,
+ std::unique_ptr<ClientPhishingRequest> request,
+ base::OnceCallback<void(std::unique_ptr<ClientPhishingRequest>)> callback)
+ const override;
+
+ void ApplyVisualTfLiteModel(
+ const SkBitmap& bitmap,
+ base::OnceCallback<void(std::vector<double>)> callback) const override;
+
+ int model_version() const override;
+ base::RepeatingCallback<bool(uint32_t)> find_page_word_callback()
+ const override;
+ base::RepeatingCallback<bool(const std::string&)> find_page_term_callback()
+ const override;
+ size_t max_words_per_term() const override;
+ uint32_t murmurhash3_seed() const override;
+ size_t max_shingles_per_page() const override;
+ size_t shingle_size() const override;
+ float threshold_probability() const override;
+ int tflite_model_version() const override;
+ const google::protobuf::RepeatedPtrField<TfLiteModelMetadata::Threshold>&
+ tflite_thresholds() const override;
+
+ const std::unordered_set<std::string>& get_page_terms_for_test() const;
+ const std::unordered_set<uint32_t>& get_page_words_for_test() const;
+
+ private:
+ friend class PhishingScorerTest;
+ friend class Scorer;
+
+ bool has_page_term(const std::string& str) const;
+ bool has_page_word(uint32_t page_word_hash) const;
+
+ ProtobufModelScorer();
+
+ // Computes the score for a given rule and feature map. The score is computed
+ // by multiplying the rule weight with the product of feature weights for the
+ // given rule. The feature weights are stored in the feature map. If a
+ // particular feature does not exist in the feature map we set its weight to
+ // zero.
+ double ComputeRuleScore(const ClientSideModel::Rule& rule,
+ const FeatureMap& features) const;
+
+ ClientSideModel model_;
+ std::unordered_set<std::string> page_terms_;
+ std::unordered_set<uint32_t> page_words_;
+};
+
+} // namespace safe_browsing
+
+#endif // COMPONENTS_SAFE_BROWSING_CONTENT_RENDERER_PHISHING_CLASSIFIER_PROTOBUF_SCORER_H_ \ No newline at end of file
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
index d5c75a164f4..626bba8f05c 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
@@ -10,11 +10,13 @@
#include <unordered_map>
#include <unordered_set>
-#include "base/metrics/histogram_macros.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/memory/shared_memory_mapping.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
+#include "base/trace_event/trace_event.h"
#include "components/safe_browsing/content/renderer/phishing_classifier/features.h"
#include "components/safe_browsing/core/common/visual_utils.h"
#include "components/safe_browsing/core/proto/client_model.pb.h"
@@ -22,61 +24,119 @@
#include "content/public/renderer/render_thread.h"
#include "crypto/sha2.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h"
+#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/vision/image_classifier.h"
+#include "third_party/tflite/src/tensorflow/lite/kernels/builtin_op_kernels.h"
+#include "third_party/tflite/src/tensorflow/lite/op_resolver.h"
namespace safe_browsing {
namespace {
-// Enum used to keep stats about the status of the Scorer creation.
-enum ScorerCreationStatus {
- SCORER_SUCCESS,
- SCORER_FAIL_MODEL_OPEN_FAIL, // Not used anymore
- SCORER_FAIL_MODEL_FILE_EMPTY, // Not used anymore
- SCORER_FAIL_MODEL_FILE_TOO_LARGE, // Not used anymore
- SCORER_FAIL_MODEL_PARSE_ERROR,
- SCORER_FAIL_MODEL_MISSING_FIELDS,
- SCORER_STATUS_MAX // Always add new values before this one.
-};
-
-void RecordScorerCreationStatus(ScorerCreationStatus status) {
- UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.ScorerCreationStatus", status,
- SCORER_STATUS_MAX);
+
+std::unique_ptr<tflite::MutableOpResolver> CreateOpResolver() {
+ tflite::MutableOpResolver resolver;
+ // The minimal set of OPs required to run the visual model.
+ resolver.AddBuiltin(tflite::BuiltinOperator_ADD,
+ tflite::ops::builtin::Register_ADD());
+ resolver.AddBuiltin(tflite::BuiltinOperator_CONV_2D,
+ tflite::ops::builtin::Register_CONV_2D());
+ resolver.AddBuiltin(tflite::BuiltinOperator_DEPTHWISE_CONV_2D,
+ tflite::ops::builtin::Register_DEPTHWISE_CONV_2D());
+ resolver.AddBuiltin(tflite::BuiltinOperator_FULLY_CONNECTED,
+ tflite::ops::builtin::Register_FULLY_CONNECTED());
+ resolver.AddBuiltin(tflite::BuiltinOperator_MEAN,
+ tflite::ops::builtin::Register_MEAN());
+ resolver.AddBuiltin(tflite::BuiltinOperator_SOFTMAX,
+ tflite::ops::builtin::Register_SOFTMAX());
+ return std::make_unique<tflite::MutableOpResolver>(resolver);
}
-std::unique_ptr<ClientPhishingRequest> GetMatchingVisualTargetsHelper(
- const SkBitmap& bitmap,
- const ClientSideModel& model,
- std::unique_ptr<ClientPhishingRequest> request) {
- DCHECK(!content::RenderThread::IsMainThread());
- for (const VisualTarget& target : model.vision_model().targets()) {
- base::Optional<VisionMatchResult> result =
- visual_utils::IsVisualMatch(bitmap, target);
- if (result.has_value()) {
- *request->add_vision_match() = result.value();
- }
+std::unique_ptr<tflite::task::vision::ImageClassifier> CreateClassifier(
+ const std::string& model_data) {
+ TRACE_EVENT0("safe_browsing", "CreateTfLiteClassifier");
+ tflite::task::vision::ImageClassifierOptions options;
+ options.mutable_model_file_with_metadata()->set_file_content(model_data);
+ auto statusor_classifier =
+ tflite::task::vision::ImageClassifier::CreateFromOptions(
+ options, CreateOpResolver());
+ if (!statusor_classifier.ok()) {
+ VLOG(1) << statusor_classifier.status().ToString();
+ return nullptr;
}
- if (model.has_vision_model()) {
- // Populate these fields for telementry purposes. They will be filtered in
- // the browser process if they are not needed.
- VisualFeatures::BlurredImage blurred_image;
- if (visual_utils::GetBlurredImage(bitmap, &blurred_image)) {
- std::string raw_digest = crypto::SHA256HashString(blurred_image.data());
- request->set_screenshot_digest(
- base::HexEncode(raw_digest.data(), raw_digest.size()));
- request->set_screenshot_phash(
- visual_utils::GetHashFromBlurredImage(blurred_image));
- request->set_phash_dimension_size(48);
+ return std::move(*statusor_classifier);
+}
+
+std::string GetModelInput(const SkBitmap& bitmap, int width, int height) {
+ TRACE_EVENT0("safe_browsing", "GetTfLiteModelInput");
+ // Use the Rec. 2020 color space, in case the user input is wide-gamut.
+ sk_sp<SkColorSpace> rec2020 = SkColorSpace::MakeRGB(
+ {2.22222f, 0.909672f, 0.0903276f, 0.222222f, 0.0812429f, 0, 0},
+ SkNamedGamut::kRec2020);
+
+ SkImageInfo downsampled_info = SkImageInfo::MakeN32(
+ width, height, SkAlphaType::kUnpremul_SkAlphaType, rec2020);
+ SkBitmap downsampled;
+ if (!downsampled.tryAllocPixels(downsampled_info))
+ return std::string();
+ bitmap.pixmap().scalePixels(
+ downsampled.pixmap(),
+ SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest));
+
+ // Format as an RGB buffer for input into the model
+ std::string data;
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ SkColor color = downsampled.getColor(x, y);
+ data += static_cast<char>(SkColorGetR(color));
+ data += static_cast<char>(SkColorGetG(color));
+ data += static_cast<char>(SkColorGetB(color));
}
}
- return request;
+ return data;
}
} // namespace
-// Helper function which converts log odds to a probability in the range
-// [0.0,1.0].
-static double LogOdds2Prob(double log_odds) {
+std::vector<double> Scorer::ApplyVisualTfLiteModelHelper(
+ const SkBitmap& bitmap,
+ int input_width,
+ int input_height,
+ const std::string& model_data) {
+ TRACE_EVENT0("safe_browsing", "ApplyVisualTfLiteModel");
+ std::unique_ptr<tflite::task::vision::ImageClassifier> classifier =
+ CreateClassifier(model_data);
+ if (!classifier)
+ return std::vector<double>();
+
+ std::string model_input = GetModelInput(bitmap, input_width, input_height);
+ if (model_input.empty())
+ return std::vector<double>();
+
+ tflite::task::vision::FrameBuffer::Plane plane{
+ reinterpret_cast<const tflite::uint8*>(model_input.data()),
+ {3 * input_width, 3}};
+ auto frame_buffer = tflite::task::vision::FrameBuffer::Create(
+ {plane}, {input_width, input_height},
+ tflite::task::vision::FrameBuffer::Format::kRGB,
+ tflite::task::vision::FrameBuffer::Orientation::kTopLeft);
+ auto statusor_result = classifier->Classify(*frame_buffer);
+ if (!statusor_result.ok()) {
+ VLOG(1) << statusor_result.status().ToString();
+ return std::vector<double>();
+ } else {
+ std::vector<double> scores(
+ statusor_result->classifications(0).classes().size());
+ for (const tflite::task::vision::Class& clas :
+ statusor_result->classifications(0).classes()) {
+ scores[clas.index()] = clas.score();
+ }
+ return scores;
+ }
+}
+
+double Scorer::LogOdds2Prob(double log_odds) {
// 709 = floor(1023*ln(2)). 2**1023 is the largest finite double.
// Small log odds aren't a problem. as the odds will be 0. It's only
// when we get +infinity for the odds, that odds/(odds+1) would be NaN.
@@ -87,102 +147,7 @@ static double LogOdds2Prob(double log_odds) {
return odds / (odds + 1.0);
}
-Scorer::Scorer() {}
-Scorer::~Scorer() {}
-
-/* static */
-Scorer* Scorer::Create(const base::StringPiece& model_str) {
- std::unique_ptr<Scorer> scorer(new Scorer());
- ClientSideModel& model = scorer->model_;
- // Parse the phishing model.
- if (!model.ParseFromArray(model_str.data(), model_str.size())) {
- RecordScorerCreationStatus(SCORER_FAIL_MODEL_PARSE_ERROR);
- return NULL;
- } else if (!model.IsInitialized()) {
- // The model may be missing some required fields.
- RecordScorerCreationStatus(SCORER_FAIL_MODEL_MISSING_FIELDS);
- return NULL;
- }
- RecordScorerCreationStatus(SCORER_SUCCESS);
- for (int i = 0; i < model.page_term_size(); ++i) {
- scorer->page_terms_.insert(model.hashes(model.page_term(i)));
- }
- for (int i = 0; i < model.page_word_size(); ++i) {
- scorer->page_words_.insert(model.page_word(i));
- }
- return scorer.release();
-}
-
-double Scorer::ComputeScore(const FeatureMap& features) const {
- double logodds = 0.0;
- for (int i = 0; i < model_.rule_size(); ++i) {
- logodds += ComputeRuleScore(model_.rule(i), features);
- }
- return LogOdds2Prob(logodds);
-}
-
-void Scorer::GetMatchingVisualTargets(
- const SkBitmap& bitmap,
- std::unique_ptr<ClientPhishingRequest> request,
- base::OnceCallback<void(std::unique_ptr<ClientPhishingRequest>)> callback)
- const {
- DCHECK(content::RenderThread::IsMainThread());
-
- // Perform scoring off the main thread to avoid blocking.
- base::ThreadPool::PostTaskAndReplyWithResult(
- FROM_HERE, {base::WithBaseSyncPrimitives()},
- base::BindOnce(&GetMatchingVisualTargetsHelper, bitmap, model_,
- std::move(request)),
- std::move(callback));
-}
+Scorer::Scorer() = default;
+Scorer::~Scorer() = default;
-int Scorer::model_version() const {
- return model_.version();
-}
-
-const std::unordered_set<std::string>& Scorer::page_terms() const {
- return page_terms_;
-}
-
-const std::unordered_set<uint32_t>& Scorer::page_words() const {
- return page_words_;
-}
-
-size_t Scorer::max_words_per_term() const {
- return model_.max_words_per_term();
-}
-
-uint32_t Scorer::murmurhash3_seed() const {
- return model_.murmur_hash_seed();
-}
-
-size_t Scorer::max_shingles_per_page() const {
- return model_.max_shingles_per_page();
-}
-
-size_t Scorer::shingle_size() const {
- return model_.shingle_size();
-}
-
-float Scorer::threshold_probability() const {
- return model_.threshold_probability();
-}
-
-double Scorer::ComputeRuleScore(const ClientSideModel::Rule& rule,
- const FeatureMap& features) const {
- const std::unordered_map<std::string, double>& feature_map =
- features.features();
- double rule_score = 1.0;
- for (int i = 0; i < rule.feature_size(); ++i) {
- const auto it = feature_map.find(model_.hashes(rule.feature(i)));
- if (it == feature_map.end() || it->second == 0.0) {
- // If the feature of the rule does not exist in the given feature map the
- // feature weight is considered to be zero. If the feature weight is zero
- // we leave early since we know that the rule score will be zero.
- return 0.0;
- }
- rule_score *= it->second;
- }
- return rule_score * rule.weight();
-}
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer.h b/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
index cbfb4f68f04..3aea64422b3 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// This class loads a client-side model and lets you compute a phishing score
-// for a set of previously extracted features. The phishing score corresponds
-// to the probability that the features are indicative of a phishing site.
+// This abstract class loads a client-side model and lets you compute a phishing
+// score for a set of previously extracted features. The phishing score
+// corresponds to the probability that the features are indicative of a phishing
+// site.
//
-// For more details on how the score is actually computed for a given model
-// and a given set of features read the comments in client_model.proto file.
+// For more details on how the score is actually computed, consult the two
+// derived classes protobuf_scorer.h and flatbuffer_scorer.h
//
// See features.h for a list of features that are currently used.
@@ -21,8 +22,11 @@
#include <unordered_set>
#include "base/callback.h"
+#include "base/files/file.h"
+#include "base/files/memory_mapped_file.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/string_piece.h"
#include "components/safe_browsing/core/proto/client_model.pb.h"
#include "components/safe_browsing/core/proto/csd.pb.h"
@@ -31,19 +35,37 @@
namespace safe_browsing {
class FeatureMap;
-// Scorer methods are virtual to simplify mocking of this class.
+// Enum used to keep stats about the status of the Scorer creation.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum ScorerCreationStatus {
+ SCORER_SUCCESS = 0,
+ SCORER_FAIL_MODEL_OPEN_FAIL = 1, // Not used anymore
+ SCORER_FAIL_MODEL_FILE_EMPTY = 2, // Not used anymore
+ SCORER_FAIL_MODEL_FILE_TOO_LARGE = 3, // Not used anymore
+ SCORER_FAIL_MODEL_PARSE_ERROR = 4,
+ SCORER_FAIL_MODEL_MISSING_FIELDS = 5,
+ SCORER_FAIL_MAP_VISUAL_TFLITE_MODEL = 6,
+ SCORER_FAIL_FLATBUFFER_INVALID_REGION = 7,
+ SCORER_FAIL_FLATBUFFER_INVALID_MAPPING = 8,
+ SCORER_FAIL_FLATBUFFER_FAILED_VERIFY = 9,
+ SCORER_FAIL_FLATBUFFER_BAD_INDICES_OR_FIELDS = 10,
+ SCORER_STATUS_MAX // Always add new values before this one.
+};
+
+// Scorer methods are virtual to simplify mocking of this class,
+// and to allow inheritance.
class Scorer {
public:
virtual ~Scorer();
-
- // Factory method which creates a new Scorer object by parsing the given
- // model. If parsing fails this method returns NULL.
- static Scorer* Create(const base::StringPiece& model_str);
+ // Most clients should use the factory method. This constructor is public
+ // to allow for mock implementations.
+ Scorer();
// This method computes the probability that the given features are indicative
// of phishing. It returns a score value that falls in the range [0.0,1.0]
// (range is inclusive on both ends).
- virtual double ComputeScore(const FeatureMap& features) const;
+ virtual double ComputeScore(const FeatureMap& features) const = 0;
// This method matches the given |bitmap| against the visual model. It
// modifies |request| appropriately, and returns the new request. This expects
@@ -53,60 +75,76 @@ class Scorer {
const SkBitmap& bitmap,
std::unique_ptr<ClientPhishingRequest> request,
base::OnceCallback<void(std::unique_ptr<ClientPhishingRequest>)> callback)
- const;
+ const = 0;
+
+ // This method applies the TfLite visual model to the given bitmap. It
+ // asynchronously returns the list of scores for each category, in the same
+ // order as `tflite_thresholds()`.
+ virtual void ApplyVisualTfLiteModel(
+ const SkBitmap& bitmap,
+ base::OnceCallback<void(std::vector<double>)> callback) const = 0;
// Returns the version number of the loaded client model.
- int model_version() const;
+ virtual int model_version() const = 0;
+
+ bool HasVisualTfLiteModel() const;
// -- Accessors used by the page feature extractor ---------------------------
- // Returns a set of hashed page terms that appear in the model in binary
- // format.
- const std::unordered_set<std::string>& page_terms() const;
+ // Returns a callback to find if a page word is in the model.
+ virtual base::RepeatingCallback<bool(uint32_t)> find_page_word_callback()
+ const = 0;
- // Returns a set of hashed page words that appear in the model in binary
- // format.
- const std::unordered_set<uint32_t>& page_words() const;
+ // Returns a callback to find if a page term is in the model.
+ virtual base::RepeatingCallback<bool(const std::string&)>
+ find_page_term_callback() const = 0;
// Return the maximum number of words per term for the loaded model.
- size_t max_words_per_term() const;
+ virtual size_t max_words_per_term() const = 0;
// Returns the murmurhash3 seed for the loaded model.
- uint32_t murmurhash3_seed() const;
+ virtual uint32_t murmurhash3_seed() const = 0;
// Return the maximum number of unique shingle hashes per page.
- size_t max_shingles_per_page() const;
+ virtual size_t max_shingles_per_page() const = 0;
// Return the number of words in a shingle.
- size_t shingle_size() const;
+ virtual size_t shingle_size() const = 0;
// Returns the threshold probability above which we send a CSD ping.
- float threshold_probability() const;
+ virtual float threshold_probability() const = 0;
- protected:
- // Most clients should use the factory method. This constructor is public
- // to allow for mock implementations.
- Scorer();
+ // Returns the version of the visual TFLite model.
+ virtual int tflite_model_version() const = 0;
- private:
- friend class PhishingScorerTest;
+ // Returns the thresholds configured for the visual TFLite model categories.
+ virtual const google::protobuf::RepeatedPtrField<
+ TfLiteModelMetadata::Threshold>&
+ tflite_thresholds() const = 0;
+
+ // Disable copy and move.
+ Scorer(const Scorer&) = delete;
+ Scorer& operator=(const Scorer&) = delete;
- // Computes the score for a given rule and feature map. The score is computed
- // by multiplying the rule weight with the product of feature weights for the
- // given rule. The feature weights are stored in the feature map. If a
- // particular feature does not exist in the feature map we set its weight to
- // zero.
- double ComputeRuleScore(const ClientSideModel::Rule& rule,
- const FeatureMap& features) const;
+ protected:
+ // Helper function which converts log odds to a probability in the range
+ // [0.0,1.0].
+ static double LogOdds2Prob(double log_odds);
- ClientSideModel model_;
- std::unordered_set<std::string> page_terms_;
- std::unordered_set<uint32_t> page_words_;
+ // Apply the tflite model to the bitmap, and return scores.
+ static std::vector<double> ApplyVisualTfLiteModelHelper(
+ const SkBitmap& bitmap,
+ int input_width,
+ int input_height,
+ const std::string& model_data);
+ base::MemoryMappedFile visual_tflite_model_;
base::WeakPtrFactory<Scorer> weak_ptr_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(Scorer);
+ private:
+ friend class PhishingScorerTest;
};
+
} // namespace safe_browsing
#endif // COMPONENTS_SAFE_BROWSING_CONTENT_RENDERER_PHISHING_CLASSIFIER_SCORER_H_
diff --git a/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc b/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc
index 3b9ae0cd3c4..36bd7603df6 100644
--- a/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc
+++ b/chromium/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "components/safe_browsing/content/renderer/phishing_classifier/scorer.h"
+#include "components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h"
+#include "components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h"
#include <stdint.h>
@@ -12,12 +14,15 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
+#include "base/logging.h"
+#include "base/memory/read_only_shared_memory_region.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/test/test_discardable_memory_allocator.h"
#include "base/threading/thread.h"
#include "components/safe_browsing/content/renderer/phishing_classifier/features.h"
+#include "components/safe_browsing/core/fbs/client_model_generated.h"
#include "components/safe_browsing/core/proto/client_model.pb.h"
#include "components/safe_browsing/core/proto/csd.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -25,6 +30,76 @@
namespace safe_browsing {
+namespace {
+
+std::string GetFlatBufferString() {
+ flatbuffers::FlatBufferBuilder builder(1024);
+ std::vector<flatbuffers::Offset<flat::Hash>> hashes;
+ // Make sure this is sorted.
+ std::vector<std::string> hashes_vector = {"feature1", "feature2", "feature3",
+ "token one", "token two"};
+ for (std::string& feature : hashes_vector) {
+ std::vector<uint8_t> hash_data(feature.begin(), feature.end());
+ hashes.push_back(flat::CreateHashDirect(builder, &hash_data));
+ }
+ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flat::Hash>>>
+ hashes_flat = builder.CreateVector(hashes);
+
+ std::vector<flatbuffers::Offset<flat::ClientSideModel_::Rule>> rules;
+ std::vector<int32_t> rule_feature1 = {};
+ std::vector<int32_t> rule_feature2 = {0};
+ std::vector<int32_t> rule_feature3 = {0, 1};
+ rules.push_back(
+ flat::ClientSideModel_::CreateRuleDirect(builder, &rule_feature1, 0.5));
+ rules.push_back(
+ flat::ClientSideModel_::CreateRuleDirect(builder, &rule_feature2, 2));
+ rules.push_back(
+ flat::ClientSideModel_::CreateRuleDirect(builder, &rule_feature3, 3));
+ flatbuffers::Offset<
+ flatbuffers::Vector<flatbuffers::Offset<flat::ClientSideModel_::Rule>>>
+ rules_flat = builder.CreateVector(rules);
+
+ std::vector<int32_t> page_terms_vector = {3, 4};
+ flatbuffers::Offset<flatbuffers::Vector<int32_t>> page_term_flat =
+ builder.CreateVector(page_terms_vector);
+
+ std::vector<uint32_t> page_words_vector = {1000U, 2000U, 3000U};
+ flatbuffers::Offset<flatbuffers::Vector<uint32_t>> page_word_flat =
+ builder.CreateVector(page_words_vector);
+
+ std::vector<
+ flatbuffers::Offset<safe_browsing::flat::TfLiteModelMetadata_::Threshold>>
+ thresholds_vector = {};
+ flatbuffers::Offset<flat::TfLiteModelMetadata> tflite_metadata_flat =
+ flat::CreateTfLiteModelMetadataDirect(builder, 0, &thresholds_vector, 0,
+ 0);
+
+ flat::ClientSideModelBuilder csd_model_builder(builder);
+ csd_model_builder.add_hashes(hashes_flat);
+ csd_model_builder.add_rule(rules_flat);
+ csd_model_builder.add_page_term(page_term_flat);
+ csd_model_builder.add_page_word(page_word_flat);
+ csd_model_builder.add_max_words_per_term(2);
+ csd_model_builder.add_murmur_hash_seed(12345U);
+ csd_model_builder.add_max_shingles_per_page(10);
+ csd_model_builder.add_shingle_size(3);
+ csd_model_builder.add_tflite_metadata(tflite_metadata_flat);
+
+ builder.Finish(csd_model_builder.Finish());
+ return std::string(reinterpret_cast<char*>(builder.GetBufferPointer()),
+ builder.GetSize());
+}
+
+base::MappedReadOnlyRegion GetMappedReadOnlyRegionWithData(std::string data) {
+ base::MappedReadOnlyRegion mapped_region =
+ base::ReadOnlySharedMemoryRegion::Create(data.length());
+ EXPECT_TRUE(mapped_region.IsValid());
+ memcpy(mapped_region.mapping.memory(), data.data(), data.length());
+ return mapped_region;
+}
+
+} // namespace
+
class PhishingScorerTest : public ::testing::Test {
protected:
void SetUp() override {
@@ -91,7 +166,7 @@ class PhishingScorerTest : public ::testing::Test {
{2.22222f, 0.909672f, 0.0903276f, 0.222222f, 0.0812429f, 0, 0},
SkNamedGamut::kRec2020);
SkImageInfo bitmap_info =
- SkImageInfo::Make(1000, 1000, SkColorType::kRGBA_8888_SkColorType,
+ SkImageInfo::Make(1000, 1000, SkColorType::kN32_SkColorType,
SkAlphaType::kUnpremul_SkAlphaType, rec2020);
ASSERT_TRUE(bitmap_.tryAllocPixels(bitmap_info));
@@ -108,25 +183,58 @@ class PhishingScorerTest : public ::testing::Test {
base::TestDiscardableMemoryAllocator test_allocator_;
};
+TEST_F(PhishingScorerTest, HasValidFlatBufferModel) {
+ std::unique_ptr<Scorer> scorer;
+ std::string flatbuffer = GetFlatBufferString();
+ base::MappedReadOnlyRegion mapped_region =
+ GetMappedReadOnlyRegionWithData(flatbuffer);
+ scorer.reset(FlatBufferModelScorer::Create(mapped_region.region.Duplicate(),
+ base::File()));
+ EXPECT_TRUE(scorer.get() != nullptr);
+
+ // Invalid region.
+ scorer.reset(FlatBufferModelScorer::Create(base::ReadOnlySharedMemoryRegion(),
+ base::File()));
+ EXPECT_FALSE(scorer.get());
+
+ // Invalid buffer in region.
+ mapped_region = GetMappedReadOnlyRegionWithData("bogus string");
+ scorer.reset(FlatBufferModelScorer::Create(mapped_region.region.Duplicate(),
+ base::File()));
+ EXPECT_FALSE(scorer.get());
+}
+
TEST_F(PhishingScorerTest, HasValidModel) {
std::unique_ptr<Scorer> scorer;
- scorer.reset(Scorer::Create(model_.SerializeAsString()));
- EXPECT_TRUE(scorer.get() != NULL);
+ scorer.reset(
+ ProtobufModelScorer::Create(model_.SerializeAsString(), base::File()));
+ EXPECT_TRUE(scorer.get() != nullptr);
// Invalid model string.
- scorer.reset(Scorer::Create("bogus string"));
+ scorer.reset(ProtobufModelScorer::Create("bogus string", base::File()));
EXPECT_FALSE(scorer.get());
// Mode is missing a required field.
model_.clear_max_words_per_term();
- scorer.reset(Scorer::Create(model_.SerializePartialAsString()));
+ scorer.reset(ProtobufModelScorer::Create(model_.SerializePartialAsString(),
+ base::File()));
EXPECT_FALSE(scorer.get());
}
TEST_F(PhishingScorerTest, PageTerms) {
- std::unique_ptr<Scorer> scorer(Scorer::Create(model_.SerializeAsString()));
+ std::unique_ptr<ProtobufModelScorer> scorer(
+ ProtobufModelScorer::Create(model_.SerializeAsString(), base::File()));
ASSERT_TRUE(scorer.get());
+ base::RepeatingCallback<bool(const std::string&)> page_terms_callback(
+ scorer->find_page_term_callback());
+ EXPECT_FALSE(page_terms_callback.Run("a"));
+ EXPECT_FALSE(page_terms_callback.Run(""));
+ EXPECT_TRUE(page_terms_callback.Run("token one"));
+ EXPECT_FALSE(page_terms_callback.Run("token onetwo"));
+ EXPECT_TRUE(page_terms_callback.Run("token two"));
+ EXPECT_FALSE(page_terms_callback.Run("token ZZ"));
+
// Use std::vector instead of std::unordered_set for comparison.
// On Android, EXPECT_THAT(..., ContainerEq(...)) doesn't support
// std::hash_set, but std::vector works fine.
@@ -135,23 +243,53 @@ TEST_F(PhishingScorerTest, PageTerms) {
expected_page_terms.push_back("token two");
std::sort(expected_page_terms.begin(), expected_page_terms.end());
- std::unordered_set<std::string> page_terms = scorer->page_terms();
+ std::unordered_set<std::string> page_terms =
+ scorer->get_page_terms_for_test();
std::vector<std::string> page_terms_v(page_terms.begin(), page_terms.end());
std::sort(page_terms_v.begin(), page_terms_v.end());
EXPECT_THAT(page_terms_v, ::testing::ContainerEq(expected_page_terms));
}
+TEST_F(PhishingScorerTest, PageTermsFlat) {
+ std::unique_ptr<Scorer> scorer;
+ std::string flatbuffer = GetFlatBufferString();
+ base::MappedReadOnlyRegion mapped_region =
+ GetMappedReadOnlyRegionWithData(flatbuffer);
+ scorer.reset(FlatBufferModelScorer::Create(mapped_region.region.Duplicate(),
+ base::File()));
+ ASSERT_TRUE(scorer.get());
+ base::RepeatingCallback<bool(const std::string&)> page_terms_callback(
+ scorer->find_page_term_callback());
+ EXPECT_FALSE(page_terms_callback.Run("a"));
+ EXPECT_FALSE(page_terms_callback.Run(""));
+ EXPECT_TRUE(page_terms_callback.Run("token one"));
+ EXPECT_FALSE(page_terms_callback.Run("token onetwo"));
+ EXPECT_TRUE(page_terms_callback.Run("token two"));
+ EXPECT_FALSE(page_terms_callback.Run("token ZZ"));
+}
+
TEST_F(PhishingScorerTest, PageWords) {
- std::unique_ptr<Scorer> scorer(Scorer::Create(model_.SerializeAsString()));
+ std::unique_ptr<ProtobufModelScorer> scorer(
+ ProtobufModelScorer::Create(model_.SerializeAsString(), base::File()));
ASSERT_TRUE(scorer.get());
+
+ base::RepeatingCallback<bool(uint32_t)> page_words_callback(
+ scorer->find_page_word_callback());
+ EXPECT_FALSE(page_words_callback.Run(0U));
+ EXPECT_TRUE(page_words_callback.Run(1000U));
+ EXPECT_FALSE(page_words_callback.Run(1500U));
+ EXPECT_TRUE(page_words_callback.Run(2000U));
+ EXPECT_TRUE(page_words_callback.Run(3000U));
+ EXPECT_FALSE(page_words_callback.Run(4000U));
+
std::vector<uint32_t> expected_page_words;
expected_page_words.push_back(1000U);
expected_page_words.push_back(2000U);
expected_page_words.push_back(3000U);
std::sort(expected_page_words.begin(), expected_page_words.end());
- std::unordered_set<uint32_t> page_words = scorer->page_words();
+ std::unordered_set<uint32_t> page_words = scorer->get_page_words_for_test();
std::vector<uint32_t> page_words_v(page_words.begin(), page_words.end());
std::sort(page_words_v.begin(), page_words_v.end());
@@ -163,8 +301,31 @@ TEST_F(PhishingScorerTest, PageWords) {
EXPECT_EQ(3U, scorer->shingle_size());
}
+TEST_F(PhishingScorerTest, PageWordsFlat) {
+ std::unique_ptr<Scorer> scorer;
+ std::string flatbuffer = GetFlatBufferString();
+ base::MappedReadOnlyRegion mapped_region =
+ GetMappedReadOnlyRegionWithData(flatbuffer);
+ scorer.reset(FlatBufferModelScorer::Create(mapped_region.region.Duplicate(),
+ base::File()));
+ ASSERT_TRUE(scorer.get());
+ base::RepeatingCallback<bool(uint32_t)> page_words_callback(
+ scorer->find_page_word_callback());
+ EXPECT_FALSE(page_words_callback.Run(0U));
+ EXPECT_TRUE(page_words_callback.Run(1000U));
+ EXPECT_FALSE(page_words_callback.Run(1500U));
+ EXPECT_TRUE(page_words_callback.Run(2000U));
+ EXPECT_TRUE(page_words_callback.Run(3000U));
+ EXPECT_FALSE(page_words_callback.Run(4000U));
+ EXPECT_EQ(2U, scorer->max_words_per_term());
+ EXPECT_EQ(12345U, scorer->murmurhash3_seed());
+ EXPECT_EQ(10U, scorer->max_shingles_per_page());
+ EXPECT_EQ(3U, scorer->shingle_size());
+}
+
TEST_F(PhishingScorerTest, ComputeScore) {
- std::unique_ptr<Scorer> scorer(Scorer::Create(model_.SerializeAsString()));
+ std::unique_ptr<Scorer> scorer(
+ ProtobufModelScorer::Create(model_.SerializeAsString(), base::File()));
ASSERT_TRUE(scorer.get());
// An empty feature map should match the empty rule.
@@ -190,8 +351,41 @@ TEST_F(PhishingScorerTest, ComputeScore) {
EXPECT_DOUBLE_EQ(0.77729986117469119, scorer->ComputeScore(features));
}
+TEST_F(PhishingScorerTest, ComputeScoreFlat) {
+ std::unique_ptr<Scorer> scorer;
+ std::string flatbuffer = GetFlatBufferString();
+ base::MappedReadOnlyRegion mapped_region =
+ GetMappedReadOnlyRegionWithData(flatbuffer);
+ scorer.reset(FlatBufferModelScorer::Create(mapped_region.region.Duplicate(),
+ base::File()));
+ EXPECT_TRUE(scorer.get() != nullptr);
+
+ // An empty feature map should match the empty rule.
+ FeatureMap features;
+ // The expected logodds is 0.5 (empty rule) => p = exp(0.5) / (exp(0.5) + 1)
+ // => 0.62245933120185459
+ EXPECT_DOUBLE_EQ(0.62245933120185459, scorer->ComputeScore(features));
+ // Same if the feature does not match any rule.
+ EXPECT_TRUE(features.AddBooleanFeature("not existing feature"));
+ EXPECT_DOUBLE_EQ(0.62245933120185459, scorer->ComputeScore(features));
+
+ // Feature 1 matches which means that the logodds will be:
+ // 0.5 (empty rule) + 2.0 (rule weight) * 0.15 (feature weight) = 0.8
+ // => p = 0.6899744811276125
+ EXPECT_TRUE(features.AddRealFeature("feature1", 0.15));
+ EXPECT_DOUBLE_EQ(0.6899744811276125, scorer->ComputeScore(features));
+
+ // Now, both feature 1 and feature 2 match. Expected logodds:
+ // 0.5 (empty rule) + 2.0 (rule weight) * 0.15 (feature weight) +
+ // 3.0 (rule weight) * 0.15 (feature1 weight) * 1.0 (feature2) weight = 9.8
+ // => p = 0.99999627336071584
+ EXPECT_TRUE(features.AddBooleanFeature("feature2"));
+ EXPECT_DOUBLE_EQ(0.77729986117469119, scorer->ComputeScore(features));
+}
+
TEST_F(PhishingScorerTest, GetMatchingVisualTargetsMatchOne) {
- std::unique_ptr<Scorer> scorer(Scorer::Create(model_.SerializeAsString()));
+ std::unique_ptr<Scorer> scorer(
+ ProtobufModelScorer::Create(model_.SerializeAsString(), base::File()));
// Make the whole image white
for (int x = 0; x < 1000; x++)
@@ -220,7 +414,8 @@ TEST_F(PhishingScorerTest, GetMatchingVisualTargetsMatchOne) {
}
TEST_F(PhishingScorerTest, GetMatchingVisualTargetsMatchBoth) {
- std::unique_ptr<Scorer> scorer(Scorer::Create(model_.SerializeAsString()));
+ std::unique_ptr<Scorer> scorer(
+ ProtobufModelScorer::Create(model_.SerializeAsString(), base::File()));
// Make the whole image white
for (int x = 0; x < 1000; x++)
diff --git a/chromium/components/safe_browsing/content/renderer/threat_dom_details.cc b/chromium/components/safe_browsing/content/renderer/threat_dom_details.cc
index fd6879e0121..e4b04b40f02 100644
--- a/chromium/components/safe_browsing/content/renderer/threat_dom_details.cc
+++ b/chromium/components/safe_browsing/content/renderer/threat_dom_details.cc
@@ -15,7 +15,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
#include "components/safe_browsing/core/features.h"
#include "content/public/renderer/render_frame.h"
#include "third_party/blink/public/platform/web_string.h"
diff --git a/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle.cc b/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle.cc
index 908a37b405f..2879bf28018 100644
--- a/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle.cc
+++ b/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle.cc
@@ -56,7 +56,7 @@ void WebSocketSBHandshakeThrottle::OnCompleteCheck(bool proceed,
DCHECK_EQ(state_, State::kStarted);
if (proceed) {
state_ = State::kSafe;
- std::move(completion_callback_).Run(base::nullopt);
+ std::move(completion_callback_).Run(absl::nullopt);
} else {
// When the insterstitial is dismissed the page is navigated and this object
// is destroyed before reaching here.
@@ -94,7 +94,7 @@ void WebSocketSBHandshakeThrottle::OnMojoDisconnect() {
notifier_receiver_.reset();
state_ = State::kNotSupported;
- std::move(completion_callback_).Run(base::nullopt);
+ std::move(completion_callback_).Run(absl::nullopt);
// |this| is destroyed here.
}
diff --git a/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle.h b/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle.h
index c703942d2e0..583cc111633 100644
--- a/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle.h
+++ b/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle.h
@@ -12,7 +12,6 @@
#include <memory>
#include "base/macros.h"
-#include "base/time/time.h"
#include "components/safe_browsing/content/common/safe_browsing.mojom.h"
#include "components/safe_browsing/core/common/safe_browsing_url_checker.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
diff --git a/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle_unittest.cc b/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle_unittest.cc
index 595f32d5910..8a6b62281cc 100644
--- a/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle_unittest.cc
+++ b/chromium/components/safe_browsing/content/renderer/websocket_sb_handshake_throttle_unittest.cc
@@ -86,7 +86,7 @@ class FakeCallback {
FakeCallback() : result_(RESULT_NOT_CALLED) {}
- void OnCompletion(const base::Optional<blink::WebString>& message) {
+ void OnCompletion(const absl::optional<blink::WebString>& message) {
if (message) {
result_ = RESULT_ERROR;
message_ = *message;
diff --git a/chromium/components/safe_browsing/content/web_ui/safe_browsing_ui.cc b/chromium/components/safe_browsing/content/web_ui/safe_browsing_ui.cc
index 4f49fa095b0..17cfe583e67 100644
--- a/chromium/components/safe_browsing/content/web_ui/safe_browsing_ui.cc
+++ b/chromium/components/safe_browsing/content/web_ui/safe_browsing_ui.cc
@@ -190,14 +190,17 @@ void WebUIInfoSingleton::ClearSecurityEvents() {
}
int WebUIInfoSingleton::AddToPGPings(
- const LoginReputationClientRequest& request) {
+ const LoginReputationClientRequest& request,
+ const std::string oauth_token) {
if (!HasListener())
return -1;
+ LoginReputationClientRequestAndToken ping = {request, oauth_token};
+
for (auto* webui_listener : webui_instances_)
- webui_listener->NotifyPGPingJsListener(pg_pings_.size(), request);
+ webui_listener->NotifyPGPingJsListener(pg_pings_.size(), ping);
- pg_pings_.push_back(request);
+ pg_pings_.push_back(ping);
return pg_pings_.size() - 1;
}
@@ -215,7 +218,7 @@ void WebUIInfoSingleton::AddToPGResponses(
}
void WebUIInfoSingleton::ClearPGPings() {
- std::vector<LoginReputationClientRequest>().swap(pg_pings_);
+ std::vector<LoginReputationClientRequestAndToken>().swap(pg_pings_);
std::map<int, LoginReputationClientResponse>().swap(pg_responses_);
}
@@ -613,6 +616,15 @@ base::Value SerializeChromeUserPopulation(
population_dict.SetKey("is_incognito",
base::Value(population.is_incognito()));
+ population_dict.SetKey("user_agent", base::Value(population.user_agent()));
+
+ population_dict.SetKey("number_of_profiles",
+ base::Value(population.number_of_profiles()));
+ population_dict.SetKey("number_of_loaded_profiles",
+ base::Value(population.number_of_loaded_profiles()));
+ population_dict.SetKey("number_of_open_profiles",
+ base::Value(population.number_of_open_profiles()));
+
return std::move(population_dict);
}
@@ -763,28 +775,33 @@ std::string SerializeClientDownloadRequest(const ClientDownloadRequest& cdr) {
return request_serialized;
}
-std::string SerializeClientDownloadResponse(const ClientDownloadResponse& cdr) {
- base::DictionaryValue dict;
-
- switch (cdr.verdict()) {
+std::string ClientDownloadResponseVerdictToString(
+ const ClientDownloadResponse::Verdict& verdict) {
+ switch (verdict) {
case ClientDownloadResponse::SAFE:
- dict.SetKey("verdict", base::Value("SAFE"));
- break;
+ return "SAFE";
case ClientDownloadResponse::DANGEROUS:
- dict.SetKey("verdict", base::Value("DANGEROUS"));
- break;
+ return "DANGEROUS";
case ClientDownloadResponse::UNCOMMON:
- dict.SetKey("verdict", base::Value("UNCOMMON"));
- break;
+ return "UNCOMMON";
case ClientDownloadResponse::POTENTIALLY_UNWANTED:
- dict.SetKey("verdict", base::Value("POTENTIALLY_UNWANTED"));
- break;
+ return "POTENTIALLY_UNWANTED";
case ClientDownloadResponse::DANGEROUS_HOST:
- dict.SetKey("verdict", base::Value("DANGEROUS_HOST"));
- break;
+ return "DANGEROUS_HOST";
case ClientDownloadResponse::UNKNOWN:
- dict.SetKey("verdict", base::Value("UNKNOWN"));
- break;
+ return "UNKNOWN";
+ case ClientDownloadResponse::DANGEROUS_ACCOUNT_COMPROMISE:
+ return "DANGEROUS_ACCOUNT_COMPROMISE";
+ }
+}
+
+std::string SerializeClientDownloadResponse(const ClientDownloadResponse& cdr) {
+ base::DictionaryValue dict;
+
+ if (cdr.has_verdict()) {
+ dict.SetKey(
+ "verdict",
+ base::Value(ClientDownloadResponseVerdictToString(cdr.verdict())));
}
if (cdr.has_more_info()) {
@@ -846,7 +863,6 @@ std::string SerializeClientPhishingRequest(
}
dict.SetList("shingle_hashes", std::move(shingle_hashes));
- dict.SetString("model_filename", cpr.model_filename());
dict.SetKey("population", SerializeChromeUserPopulation(cpr.population()));
if (cpr.has_screenshot_digest()) {
dict.SetKey("screenshot_digest", base::Value(cpr.screenshot_digest()));
@@ -868,6 +884,17 @@ std::string SerializeClientPhishingRequest(
dict.SetList("vision_match", std::move(vision_matches));
dict.SetKey("scoped_oauth_token", base::Value(cprat.token));
+ if (cpr.has_tflite_model_version())
+ dict.SetInteger("tflite_model_version", cpr.tflite_model_version());
+ dict.SetBoolean("is_tflite_match", cpr.is_tflite_match());
+ auto tflite_scores = std::make_unique<base::ListValue>();
+ for (const auto& score : cpr.tflite_model_scores()) {
+ auto score_value = std::make_unique<base::DictionaryValue>();
+ score_value->SetStringKey("label", score.label());
+ score_value->SetDoubleKey("lvalue", score.value());
+ }
+ dict.SetList("tflite_model_scores", std::move(tflite_scores));
+
base::Value* request_tree = &dict;
std::string request_serialized;
JSONStringValueSerializer serializer(&request_serialized);
@@ -904,6 +931,21 @@ std::string SerializeCSBRR(const ClientSafeBrowsingReportRequest& report) {
if (report.has_did_proceed()) {
report_request.SetInteger("did_proceed", report.did_proceed());
}
+ if (report.has_download_verdict()) {
+ report_request.SetString(
+ "download_verdict",
+ ClientDownloadResponseVerdictToString(report.download_verdict()));
+ }
+ if (report.has_url()) {
+ report_request.SetString("url", report.url());
+ }
+ if (report.has_token()) {
+ report_request.SetString("token", report.token());
+ }
+ if (report.has_show_download_in_folder()) {
+ report_request.SetBoolean("show_download_in_folder",
+ report.show_download_in_folder());
+ }
std::string serialized;
if (report.SerializeToString(&serialized)) {
std::string base64_encoded;
@@ -1303,9 +1345,12 @@ base::Value SerializeReferringAppInfo(
return std::move(dict);
}
-std::string SerializePGPing(const LoginReputationClientRequest& request) {
+std::string SerializePGPing(
+ const LoginReputationClientRequestAndToken& request_and_token) {
base::DictionaryValue request_dict;
+ const LoginReputationClientRequest& request = request_and_token.request;
+
request_dict.SetKey("page_url", base::Value(request.page_url()));
std::string trigger_type;
@@ -1365,6 +1410,9 @@ std::string SerializePGPing(const LoginReputationClientRequest& request) {
SerializeReferringAppInfo(request.referring_app_info()));
}
+ request_dict.SetKey("scoped_oauth_token",
+ base::Value(request_and_token.token));
+
std::string request_serialized;
JSONStringValueSerializer serializer(&request_serialized);
serializer.set_pretty_print(true);
@@ -1955,7 +2003,7 @@ void SafeBrowsingUIHandler::GetSecurityEvents(const base::ListValue* args) {
}
void SafeBrowsingUIHandler::GetPGPings(const base::ListValue* args) {
- const std::vector<LoginReputationClientRequest> requests =
+ const std::vector<LoginReputationClientRequestAndToken> requests =
WebUIInfoSingleton::GetInstance()->pg_pings();
base::ListValue pings_sent;
@@ -2163,7 +2211,7 @@ void SafeBrowsingUIHandler::NotifySecurityEventJsListener(
void SafeBrowsingUIHandler::NotifyPGPingJsListener(
int token,
- const LoginReputationClientRequest& request) {
+ const LoginReputationClientRequestAndToken& request) {
base::ListValue request_list;
request_list.Append(base::Value(token));
request_list.Append(base::Value(SerializePGPing(request)));
diff --git a/chromium/components/safe_browsing/content/web_ui/safe_browsing_ui.h b/chromium/components/safe_browsing/content/web_ui/safe_browsing_ui.h
index 121c44fb25b..109d196e0b1 100644
--- a/chromium/components/safe_browsing/content/web_ui/safe_browsing_ui.h
+++ b/chromium/components/safe_browsing/content/web_ui/safe_browsing_ui.h
@@ -42,16 +42,25 @@ struct DeepScanDebugData {
~DeepScanDebugData();
base::Time request_time;
- base::Optional<enterprise_connectors::ContentAnalysisRequest> request;
+ absl::optional<enterprise_connectors::ContentAnalysisRequest> request;
GURL tab_url;
bool per_profile_request;
base::Time response_time;
std::string response_status;
- base::Optional<enterprise_connectors::ContentAnalysisResponse> response;
+ absl::optional<enterprise_connectors::ContentAnalysisResponse> response;
};
#endif
+// The struct to combine a PhishGuard request and the token associated
+// with it. The token is not part of the request proto because it is sent in the
+// header. The token will be displayed along with the request in the safe
+// browsing page.
+struct LoginReputationClientRequestAndToken {
+ LoginReputationClientRequest request;
+ std::string token;
+};
+
// The struct to combine a real time lookup request and the token associated
// with it. The token is not part of the request proto because it is sent in the
// header. The token will be displayed along with the request in the safe
@@ -199,8 +208,9 @@ class SafeBrowsingUIHandler : public content::WebUIMessageHandler {
// Called when any new PhishGuard pings are sent while one or more WebUI tabs
// are open.
- void NotifyPGPingJsListener(int token,
- const LoginReputationClientRequest& request);
+ void NotifyPGPingJsListener(
+ int token,
+ const LoginReputationClientRequestAndToken& request);
// Called when any new PhishGuard responses are received while one or more
// WebUI tabs are open.
@@ -321,10 +331,11 @@ class WebUIInfoSingleton {
// 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.
- int AddToPGPings(const LoginReputationClientRequest& request);
+ // Add the new ping (with oauth token) to |pg_pings_| and send it to all the
+ // open chrome://safe-browsing tabs. Returns a token that can be used in
+ // |AddToPGResponses| to correlate a ping and response.
+ int AddToPGPings(const LoginReputationClientRequest& request,
+ const std::string oauth_token);
// Add the new response to |pg_responses_| and send it to all the open
// chrome://safe-browsing tabs.
@@ -444,9 +455,9 @@ class WebUIInfoSingleton {
return security_event_log_;
}
- // Get the list of PhishGuard pings since the oldest currently open
+ // Get the list of PhishGuard pings and tokens since the oldest currently open
// chrome://safe-browsing tab was opened.
- const std::vector<LoginReputationClientRequest>& pg_pings() const {
+ const std::vector<LoginReputationClientRequestAndToken>& pg_pings() const {
return pg_pings_;
}
@@ -554,9 +565,9 @@ class WebUIInfoSingleton {
// chrome://safe-browsing tab was opened.
std::vector<sync_pb::GaiaPasswordReuse> security_event_log_;
- // List of PhishGuard pings sent since the oldest currently open
+ // List of PhishGuard pings and tokens sent since the oldest currently open
// chrome://safe-browsing tab was opened.
- std::vector<LoginReputationClientRequest> pg_pings_;
+ std::vector<LoginReputationClientRequestAndToken> pg_pings_;
// List of PhishGuard responses received since the oldest currently open
// chrome://safe-browsing tab was opened.
diff --git a/chromium/components/safe_browsing/core/BUILD.gn b/chromium/components/safe_browsing/core/BUILD.gn
index 41d572ddc02..c7824fcc9b5 100644
--- a/chromium/components/safe_browsing/core/BUILD.gn
+++ b/chromium/components/safe_browsing/core/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("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
import("//third_party/protobuf/proto_library.gni")
static_library("features") {
@@ -13,6 +14,18 @@ static_library("features") {
deps = [
"//base:base",
"//components/safe_browsing:buildflags",
+ "//components/variations",
+ ]
+}
+
+source_set("features_unittest") {
+ testonly = true
+ sources = [ "features_unittest.cc" ]
+
+ deps = [
+ ":features",
+ "//base/test:test_support",
+ "//testing/gtest:gtest",
]
}
@@ -25,7 +38,7 @@ static_library("features") {
# the protos in the same directory. Those protos also need to import csd.proto
# using a path from the source root, otherwise they won't compile.
-proto_library("csd_proto") {
+fuzzable_proto_library("csd_proto") {
proto_in_dir = "//"
sources = [ "proto/csd.proto" ]
}
@@ -40,7 +53,7 @@ proto_library("realtimeapi_proto") {
deps = [ ":csd_proto" ]
}
-proto_library("client_model_proto") {
+fuzzable_proto_library("client_model_proto") {
proto_in_dir = "//"
sources = [ "proto/client_model.proto" ]
deps = [ ":csd_proto" ]
@@ -91,6 +104,7 @@ source_set("verdict_cache_manager") {
"//components/history/core/browser",
"//components/keyed_service/core:core",
"//components/password_manager/core/browser:browser",
+ "//components/safe_browsing/core/common",
"//components/safe_browsing/core/common:thread_utils",
"//components/safe_browsing/core/db:v4_protocol_manager_util",
"//url",
@@ -149,10 +163,12 @@ if (!is_ios && !is_fuchsia) {
"file_type_policies.h",
]
- public_deps = [ ":download_file_types_proto" ]
+ public_deps = [
+ ":download_file_types_proto",
+ "//base",
+ ]
deps = [
- "//base",
"//components/resources:components_resources",
"//ui/base",
]
diff --git a/chromium/components/safe_browsing/core/browser/download/BUILD.gn b/chromium/components/safe_browsing/core/browser/download/BUILD.gn
new file mode 100644
index 00000000000..069a0329fe0
--- /dev/null
+++ b/chromium/components/safe_browsing/core/browser/download/BUILD.gn
@@ -0,0 +1,29 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+
+source_set("download_stats") {
+ sources = [
+ "download_stats.cc",
+ "download_stats.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/download/public/common:public",
+ "//components/safe_browsing/core:file_type_policies",
+ ]
+}
+
+source_set("unittests") {
+ testonly = true
+ sources = [ "download_stats_unittest.cc" ]
+
+ deps = [
+ ":download_stats",
+ "//base/test:test_support",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/safe_browsing/core/browser/download/DEPS b/chromium/components/safe_browsing/core/browser/download/DEPS
new file mode 100644
index 00000000000..88c4ec873a3
--- /dev/null
+++ b/chromium/components/safe_browsing/core/browser/download/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+components/download/public/common",
+]
diff --git a/chromium/components/safe_browsing/core/browser/download/download_stats.cc b/chromium/components/safe_browsing/core/browser/download/download_stats.cc
new file mode 100644
index 00000000000..a7ad96d31cd
--- /dev/null
+++ b/chromium/components/safe_browsing/core/browser/download/download_stats.cc
@@ -0,0 +1,121 @@
+// Copyright 2021 The Chromium Authors. 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/core/browser/download/download_stats.h"
+
+#include "base/files/file_path.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/time/time.h"
+#include "components/download/public/common/download_danger_type.h"
+#include "components/safe_browsing/core/file_type_policies.h"
+
+namespace {
+
+using safe_browsing::FileTypePolicies;
+
+constexpr char kShownMetricSuffix[] = ".Shown";
+constexpr char kBypassedMetricSuffix[] = ".Bypassed";
+
+std::string GetDangerTypeMetricSuffix(
+ download::DownloadDangerType danger_type) {
+ switch (danger_type) {
+ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE:
+ return ".DangerousFileType";
+ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL:
+ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT:
+ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST:
+ case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE:
+ case download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
+ case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS:
+ return ".Malicious";
+ case download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT:
+ return ".Uncommon";
+ case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING:
+ case download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING:
+ case download::DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED:
+ case download::DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE:
+ case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING:
+ case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK:
+ case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE:
+ case download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE:
+ case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
+ case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
+ case download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
+ case download::DOWNLOAD_DANGER_TYPE_ALLOWLISTED_BY_POLICY:
+ case download::DOWNLOAD_DANGER_TYPE_MAX:
+ return ".Others";
+ }
+}
+
+void RecordDangerousWarningFileType(download::DownloadDangerType danger_type,
+ const base::FilePath& file_path,
+ const std::string& metrics_suffix) {
+ base::UmaHistogramSparse(
+ "SBClientDownload.Warning.FileType" +
+ GetDangerTypeMetricSuffix(danger_type) + metrics_suffix,
+ FileTypePolicies::GetInstance()->UmaValueForFile(file_path));
+}
+
+void RecordDangerousWarningIsHttps(download::DownloadDangerType danger_type,
+ bool is_https,
+ const std::string& metrics_suffix) {
+ base::UmaHistogramBoolean("SBClientDownload.Warning.DownloadIsHttps" +
+ GetDangerTypeMetricSuffix(danger_type) +
+ metrics_suffix,
+ is_https);
+}
+
+void RecordDangerousWarningHasUserGesture(
+ download::DownloadDangerType danger_type,
+ bool has_user_gesture,
+ const std::string& metrics_suffix) {
+ base::UmaHistogramBoolean("SBClientDownload.Warning.DownloadHasUserGesture" +
+ GetDangerTypeMetricSuffix(danger_type) +
+ metrics_suffix,
+ has_user_gesture);
+}
+
+} // namespace
+
+namespace safe_browsing {
+
+void RecordDangerousDownloadWarningShown(
+ download::DownloadDangerType danger_type,
+ const base::FilePath& file_path,
+ bool is_https,
+ bool has_user_gesture) {
+ RecordDangerousWarningFileType(danger_type, file_path, kShownMetricSuffix);
+ RecordDangerousWarningIsHttps(danger_type, is_https, kShownMetricSuffix);
+ RecordDangerousWarningHasUserGesture(danger_type, has_user_gesture,
+ kShownMetricSuffix);
+}
+
+void RecordDangerousDownloadWarningBypassed(
+ download::DownloadDangerType danger_type,
+ const base::FilePath& file_path,
+ bool is_https,
+ bool has_user_gesture) {
+ RecordDangerousWarningFileType(danger_type, file_path, kBypassedMetricSuffix);
+ RecordDangerousWarningIsHttps(danger_type, is_https, kBypassedMetricSuffix);
+ RecordDangerousWarningHasUserGesture(danger_type, has_user_gesture,
+ kBypassedMetricSuffix);
+}
+
+void RecordDownloadOpened(download::DownloadDangerType danger_type,
+ base::Time download_opened_time,
+ base::Time download_end_time,
+ bool show_download_in_folder) {
+ if (danger_type != download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
+ return;
+ }
+ std::string metric_suffix =
+ show_download_in_folder ? ".ShowInFolder" : ".OpenDirectly";
+ base::UmaHistogramCustomTimes(
+ "SBClientDownload.SafeDownloadOpenedLatency" + metric_suffix,
+ /* sample */ download_opened_time - download_end_time,
+ /* min */ base::TimeDelta::FromSeconds(1),
+ /* max */ base::TimeDelta::FromDays(1), /* buckets */ 50);
+}
+
+} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/core/browser/download/download_stats.h b/chromium/components/safe_browsing/core/browser/download/download_stats.h
new file mode 100644
index 00000000000..aba7e29025a
--- /dev/null
+++ b/chromium/components/safe_browsing/core/browser/download/download_stats.h
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SAFE_BROWSING_CORE_BROWSER_DOWNLOAD_DOWNLOAD_STATS_H_
+#define COMPONENTS_SAFE_BROWSING_CORE_BROWSER_DOWNLOAD_DOWNLOAD_STATS_H_
+
+#include "components/download/public/common/download_danger_type.h"
+
+namespace base {
+class FilePath;
+class Time;
+} // namespace base
+
+// The functions in this file are for logging UMA metrics related to downloads.
+namespace safe_browsing {
+
+// Records that a download warning was shown on the download shelf.
+void RecordDangerousDownloadWarningShown(
+ download::DownloadDangerType danger_type,
+ const base::FilePath& file_path,
+ bool is_https,
+ bool has_user_gesture);
+
+// Records that a download warning was bypassed from the download shelf or the
+// chrome://downloads page.
+void RecordDangerousDownloadWarningBypassed(
+ download::DownloadDangerType danger_type,
+ const base::FilePath& file_path,
+ bool is_https,
+ bool has_user_gesture);
+
+// Records that a download was opened from the download shelf or the
+// chrome://downloads page.
+void RecordDownloadOpened(download::DownloadDangerType danger_type,
+ base::Time download_opened_time,
+ base::Time download_end_time,
+ bool show_download_in_folder);
+
+} // namespace safe_browsing
+
+#endif // COMPONENTS_SAFE_BROWSING_CORE_BROWSER_DOWNLOAD_DOWNLOAD_STATS_H_
diff --git a/chromium/components/safe_browsing/core/browser/download/download_stats_unittest.cc b/chromium/components/safe_browsing/core/browser/download/download_stats_unittest.cc
new file mode 100644
index 00000000000..288de6857a1
--- /dev/null
+++ b/chromium/components/safe_browsing/core/browser/download/download_stats_unittest.cc
@@ -0,0 +1,106 @@
+// Copyright 2021 The Chromium Authors. 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/core/browser/download/download_stats.h"
+
+#include "base/files/file_path.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// The below constants are based on download_file_types.asciipb.
+const int kExeFileTypeUmaValue = 0;
+const int kApkFileTypeUmaValue = 20;
+
+} // namespace
+
+namespace safe_browsing {
+
+TEST(SafeBrowsingDownloadStatsTest, RecordDangerousDownloadWarningShown) {
+ base::HistogramTester histogram_tester;
+
+ RecordDangerousDownloadWarningShown(
+ download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT,
+ base::FilePath(FILE_PATH_LITERAL("file.apk")),
+ /*is_https=*/true, /*has_user_gesture=*/true);
+ histogram_tester.ExpectUniqueSample(
+ "SBClientDownload.Warning.FileType.Malicious.Shown",
+ /*sample=*/kApkFileTypeUmaValue, /*expected_bucket_count=*/1);
+ histogram_tester.ExpectUniqueSample(
+ "SBClientDownload.Warning.DownloadIsHttps.Malicious.Shown",
+ /*sample=*/1, /*expected_bucket_count=*/1);
+ histogram_tester.ExpectUniqueSample(
+ "SBClientDownload.Warning.DownloadHasUserGesture.Malicious.Shown",
+ /*sample=*/1, /*expected_bucket_count=*/1);
+
+ RecordDangerousDownloadWarningShown(
+ download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT,
+ base::FilePath(FILE_PATH_LITERAL("file.exe")),
+ /*is_https=*/false, /*has_user_gesture=*/false);
+ histogram_tester.ExpectBucketCount(
+ "SBClientDownload.Warning.FileType.Uncommon.Shown",
+ /*sample=*/kExeFileTypeUmaValue,
+ /*expected_count=*/1);
+ histogram_tester.ExpectBucketCount(
+ "SBClientDownload.Warning.DownloadIsHttps.Uncommon.Shown",
+ /*sample=*/0,
+ /*expected_count=*/1);
+ histogram_tester.ExpectBucketCount(
+ "SBClientDownload.Warning.DownloadHasUserGesture.Uncommon.Shown",
+ /*sample=*/0,
+ /*expected_count=*/1);
+}
+
+TEST(SafeBrowsingDownloadStatsTest, RecordDangerousDownloadWarningBypassed) {
+ base::HistogramTester histogram_tester;
+
+ RecordDangerousDownloadWarningBypassed(
+ download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE,
+ base::FilePath(FILE_PATH_LITERAL("file.apk")),
+ /*is_https=*/true, /*has_user_gesture=*/false);
+ histogram_tester.ExpectUniqueSample(
+ "SBClientDownload.Warning.FileType.DangerousFileType.Bypassed",
+ /*sample=*/kApkFileTypeUmaValue, /*expected_bucket_count=*/1);
+ histogram_tester.ExpectUniqueSample(
+ "SBClientDownload.Warning.DownloadIsHttps.DangerousFileType.Bypassed",
+ /*sample=*/1, /*expected_bucket_count=*/1);
+ histogram_tester.ExpectUniqueSample(
+ "SBClientDownload.Warning.DownloadHasUserGesture.DangerousFileType."
+ "Bypassed",
+ /*sample=*/0, /*expected_bucket_count=*/1);
+}
+
+TEST(SafeBrowsingDownloadStatsTest, RecordDownloadOpened) {
+ base::HistogramTester histogram_tester;
+
+ base::Time download_end_time = base::Time::Now();
+ // Not logged for dangerous downloads.
+ RecordDownloadOpened(
+ download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT,
+ download_end_time + base::TimeDelta::FromDays(1), download_end_time,
+ /*show_download_in_folder=*/false);
+ histogram_tester.ExpectTotalCount(
+ "SBClientDownload.SafeDownloadOpenedLatency.OpenDirectly", 0);
+
+ RecordDownloadOpened(
+ download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ download_end_time + base::TimeDelta::FromDays(1), download_end_time,
+ /*show_download_in_folder=*/false);
+ histogram_tester.ExpectTimeBucketCount(
+ "SBClientDownload.SafeDownloadOpenedLatency.OpenDirectly",
+ /*sample=*/base::TimeDelta::FromDays(1),
+ /*count=*/1);
+
+ RecordDownloadOpened(
+ download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ download_end_time + base::TimeDelta::FromHours(5), download_end_time,
+ /*show_download_in_folder=*/true);
+ histogram_tester.ExpectTimeBucketCount(
+ "SBClientDownload.SafeDownloadOpenedLatency.ShowInFolder",
+ /*sample=*/base::TimeDelta::FromHours(5),
+ /*count=*/1);
+}
+
+} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/core/browser/safe_browsing_token_fetcher.h b/chromium/components/safe_browsing/core/browser/safe_browsing_token_fetcher.h
index 081e046e497..6b21b59d70d 100644
--- a/chromium/components/safe_browsing/core/browser/safe_browsing_token_fetcher.h
+++ b/chromium/components/safe_browsing/core/browser/safe_browsing_token_fetcher.h
@@ -26,6 +26,11 @@ class SafeBrowsingTokenFetcher {
// Begin fetching a token for the account. The
// result will be returned in |callback|. Must be called on the UI thread.
virtual void Start(Callback callback) = 0;
+
+ // Called when the access token is identified as invalid, so the embedders can
+ // perform extra actions on it. Must be called on the UI thread.
+ virtual void OnInvalidAccessToken(
+ const std::string& invalid_access_token) = 0;
};
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.cc b/chromium/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.cc
index 8bc7c0a4c42..60ffeba71a1 100644
--- a/chromium/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.cc
+++ b/chromium/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.cc
@@ -49,6 +49,14 @@ void SafeBrowsingPrimaryAccountTokenFetcher::Start(
signin::AccessTokenFetcher::Mode::kImmediate);
}
+void SafeBrowsingPrimaryAccountTokenFetcher::OnInvalidAccessToken(
+ const std::string& invalid_access_token) {
+ CoreAccountId account_id =
+ identity_manager_->GetPrimaryAccountId(signin::ConsentLevel::kSignin);
+ identity_manager_->RemoveAccessTokenFromCache(account_id, {kAPIScope},
+ invalid_access_token);
+}
+
void SafeBrowsingPrimaryAccountTokenFetcher::OnTokenFetched(
int request_id,
GoogleServiceAuthError error,
diff --git a/chromium/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h b/chromium/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h
index e6e75dbabc5..2ac03f5d76b 100644
--- a/chromium/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h
+++ b/chromium/components/safe_browsing/core/browser/sync/safe_browsing_primary_account_token_fetcher.h
@@ -35,6 +35,7 @@ class SafeBrowsingPrimaryAccountTokenFetcher : public SafeBrowsingTokenFetcher {
// SafeBrowsingTokenFetcher:
void Start(Callback callback) override;
+ void OnInvalidAccessToken(const std::string& invalid_access_token) override;
private:
void OnTokenFetched(int request_id,
diff --git a/chromium/components/safe_browsing/core/browser/sync/sync_utils.cc b/chromium/components/safe_browsing/core/browser/sync/sync_utils.cc
index 0e47cf5cb73..f761b314a44 100644
--- a/chromium/components/safe_browsing/core/browser/sync/sync_utils.cc
+++ b/chromium/components/safe_browsing/core/browser/sync/sync_utils.cc
@@ -43,7 +43,7 @@ bool SyncUtils::AreSigninAndSyncSetUpForSafeBrowsingTokenFetches(
(syncer::GetUploadToGoogleState(
sync_service, syncer::ModelType::HISTORY_DELETE_DIRECTIVES) ==
syncer::UploadState::ACTIVE) &&
- !sync_service->GetUserSettings()->IsUsingSecondaryPassphrase();
+ !sync_service->GetUserSettings()->IsUsingExplicitPassphrase();
}
// TODO(bdea): Migrate other SB classes that define this method to call the one
diff --git a/chromium/components/safe_browsing/core/browser/sync/sync_utils_unittest.cc b/chromium/components/safe_browsing/core/browser/sync/sync_utils_unittest.cc
index b2b43f0b0a6..cb5d3fc3d14 100644
--- a/chromium/components/safe_browsing/core/browser/sync/sync_utils_unittest.cc
+++ b/chromium/components/safe_browsing/core/browser/sync/sync_utils_unittest.cc
@@ -61,7 +61,7 @@ TEST_F(SyncUtilsTest, AreSigninAndSyncSetUpForSafeBrowsingTokenFetches_Sync) {
// Custom passphrase is enabled.
sync_service.GetUserSettings()->SetSelectedTypes(
false, {syncer::UserSelectableType::kHistory});
- sync_service.SetIsUsingSecondaryPassphrase(true);
+ sync_service.SetIsUsingExplicitPassphrase(true);
EXPECT_FALSE(SyncUtils::AreSigninAndSyncSetUpForSafeBrowsingTokenFetches(
&sync_service, identity_manager,
/* user_has_enabled_enhanced_protection=*/true));
diff --git a/chromium/components/safe_browsing/core/common/safe_browsing_policy_handler.cc b/chromium/components/safe_browsing/core/common/safe_browsing_policy_handler.cc
index 510fafd2540..567b40f90b1 100644
--- a/chromium/components/safe_browsing/core/common/safe_browsing_policy_handler.cc
+++ b/chromium/components/safe_browsing/core/common/safe_browsing_policy_handler.cc
@@ -4,7 +4,6 @@
#include "components/safe_browsing/core/common/safe_browsing_policy_handler.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "components/policy/core/browser/policy_error_map.h"
@@ -14,6 +13,7 @@
#include "components/prefs/pref_value_map.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/strings/grit/components_strings.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace safe_browsing {
@@ -53,14 +53,14 @@ PolicyCheckResult CheckSafeBrowsingEnabled(
// Returns the target value of the Safe Browsing Protection Level derived only
// from the legacy SafeBrowsingEnabled policy. If this policy is not set or
// does not have a valid value, returns |nullopt|.
-base::Optional<ProtectionLevel> GetValueFromSafeBrowsingEnabledPolicy(
+absl::optional<ProtectionLevel> GetValueFromSafeBrowsingEnabledPolicy(
const policy::PolicyMap& policies) {
const base::Value* safe_browsing_enabled =
policies.GetValue(policy::key::kSafeBrowsingEnabled);
if (CheckSafeBrowsingEnabled(safe_browsing_enabled, nullptr /*error*/) !=
PolicyCheckResult::kValid) {
- return base::nullopt;
+ return absl::nullopt;
}
return safe_browsing_enabled->GetBool() ? ProtectionLevel::kStandardProtection
@@ -105,7 +105,7 @@ PolicyCheckResult CheckSafeBrowsingProtectionLevel(
// Returns the target value of Safe Browsing protection level derived only
// from the SafeBrowsingProtectionLevel policy. If this policy is not set or
// does not have a valid value, returns |nullopt|.
-base::Optional<ProtectionLevel> GetValueFromSafeBrowsingProtectionLevelPolicy(
+absl::optional<ProtectionLevel> GetValueFromSafeBrowsingProtectionLevelPolicy(
const policy::PolicyMap& policies) {
const base::Value* safe_browsing_protection_level =
policies.GetValue(policy::key::kSafeBrowsingProtectionLevel);
@@ -113,7 +113,7 @@ base::Optional<ProtectionLevel> GetValueFromSafeBrowsingProtectionLevelPolicy(
if (CheckSafeBrowsingProtectionLevel(safe_browsing_protection_level,
nullptr /*error*/) !=
PolicyCheckResult::kValid) {
- return base::nullopt;
+ return absl::nullopt;
}
return static_cast<ProtectionLevel>(safe_browsing_protection_level->GetInt());
@@ -123,9 +123,9 @@ base::Optional<ProtectionLevel> GetValueFromSafeBrowsingProtectionLevelPolicy(
// both the SafeBrowsingEnabled policy and the
// SafeBrowsingProtectionLevel policy. If both policies are set,
// SafeBrowsingProtectionLevel wins.
-base::Optional<ProtectionLevel> GetValueFromBothPolicies(
+absl::optional<ProtectionLevel> GetValueFromBothPolicies(
const policy::PolicyMap& policies) {
- const base::Optional<ProtectionLevel> safe_browsing_protection_level =
+ const absl::optional<ProtectionLevel> safe_browsing_protection_level =
GetValueFromSafeBrowsingProtectionLevelPolicy(policies);
if (safe_browsing_protection_level.has_value()) {
@@ -167,7 +167,7 @@ bool SafeBrowsingPolicyHandler::CheckPolicySettings(
void SafeBrowsingPolicyHandler::ApplyPolicySettings(
const policy::PolicyMap& policies,
PrefValueMap* prefs) {
- const base::Optional<ProtectionLevel> value =
+ const absl::optional<ProtectionLevel> value =
GetValueFromBothPolicies(policies);
if (!value.has_value())
diff --git a/chromium/components/safe_browsing/core/common/safebrowsing_constants.cc b/chromium/components/safe_browsing/core/common/safebrowsing_constants.cc
index d4fea3610ce..d35332a3456 100644
--- a/chromium/components/safe_browsing/core/common/safebrowsing_constants.cc
+++ b/chromium/components/safe_browsing/core/common/safebrowsing_constants.cc
@@ -23,6 +23,8 @@ const char kSafeBrowsingEnabledHistogramName[] = "SafeBrowsing.Pref.General";
const char kArtificialCachedPhishGuardVerdictFlag[] =
"mark_as_phish_guard_phishing";
+const char kAuthHeaderBearer[] = "Bearer ";
+
const std::vector<std::string> GetExcludedCountries() {
// Safe Browsing endpoint doesn't exist.
return {"cn"};
diff --git a/chromium/components/safe_browsing/core/common/safebrowsing_constants.h b/chromium/components/safe_browsing/core/common/safebrowsing_constants.h
index bd7a0752e82..a0647922e62 100644
--- a/chromium/components/safe_browsing/core/common/safebrowsing_constants.h
+++ b/chromium/components/safe_browsing/core/common/safebrowsing_constants.h
@@ -31,6 +31,10 @@ extern const char kSafeBrowsingEnabledHistogramName[];
// Command-line flag for caching an artificial PhishGuard unsafe verdict.
extern const char kArtificialCachedPhishGuardVerdictFlag[];
+// The bearer token prefix in authorization header. Used when various Safe
+// Browsing requests are GAIA-keyed by attaching oauth2 tokens as bearer tokens.
+extern const char kAuthHeaderBearer[];
+
// Countries that has no endpoint for Safe Browsing.
const std::vector<std::string> GetExcludedCountries();
diff --git a/chromium/components/safe_browsing/core/common/visual_utils.cc b/chromium/components/safe_browsing/core/common/visual_utils.cc
index 42f5aa71ba4..6f8569b2405 100644
--- a/chromium/components/safe_browsing/core/common/visual_utils.cc
+++ b/chromium/components/safe_browsing/core/common/visual_utils.cc
@@ -2,17 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "components/safe_browsing/core/common/visual_utils.h"
+
#include <unordered_map>
#include <vector>
-#include "components/safe_browsing/core/common/visual_utils.h"
-
#include "base/check_op.h"
+#include "base/feature_list.h"
#include "base/numerics/checked_math.h"
+#include "base/optional.h"
+#include "base/trace_event/trace_event.h"
+#include "components/safe_browsing/core/features.h"
#include "components/safe_browsing/core/proto/client_model.pb.h"
#include "components/safe_browsing/core/proto/csd.pb.h"
#include "third_party/opencv/src/emd_wrapper.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColorPriv.h"
#include "third_party/skia/include/core/SkPixmap.h"
#include "ui/gfx/color_utils.h"
@@ -67,6 +72,7 @@ opencv::PointDistribution HistogramBinsToPointDistribution(
bins) {
opencv::PointDistribution distribution;
distribution.dimensions = 5;
+ distribution.positions.reserve(bins.size());
for (const VisualFeatures::ColorHistogramBin& bin : bins) {
distribution.weights.push_back(bin.weight());
std::vector<float> position(5);
@@ -99,12 +105,14 @@ bool ImageHasColorInRange(const SkBitmap& image,
bool ImageHasColorInRange(const SkBitmap& image,
const MatchRule::FloatColorRange& color_range) {
+ TRACE_EVENT0("safe_browsing", "ImageHasColorInRange");
for (int i = 0; i < image.width(); i++) {
for (int j = 0; j < image.height(); j++) {
SkScalar hsv[3];
SkColorToHSV(image.getColor(i, j), hsv);
- if (color_range.low() <= hsv[0] && hsv[0] <= color_range.high())
+ if (color_range.low() <= hsv[0] && hsv[0] <= color_range.high()) {
return true;
+ }
}
}
@@ -124,6 +132,24 @@ uint8_t GetMedian(const std::vector<uint8_t>& data) {
}
}
+int GetPHashDownsampleWidth() {
+ if (base::FeatureList::IsEnabled(kVisualFeaturesSizes)) {
+ return base::GetFieldTrialParamByFeatureAsInt(
+ kVisualFeaturesSizes, "phash_width", kPHashDownsampleWidth);
+ }
+
+ return kPHashDownsampleWidth;
+}
+
+int GetPHashDownsampleHeight() {
+ if (base::FeatureList::IsEnabled(kVisualFeaturesSizes)) {
+ return base::GetFieldTrialParamByFeatureAsInt(
+ kVisualFeaturesSizes, "phash_height", kPHashDownsampleHeight);
+ }
+
+ return kPHashDownsampleHeight;
+}
+
} // namespace
// A QuantizedColor takes the highest 3 bits of R, G, and B, and concatenates
@@ -145,36 +171,72 @@ int GetQuantizedB(QuantizedColor color) {
return color & 7;
}
+struct ColorStats {
+ int color_to_count = 0;
+ double color_to_total_x = 0.0;
+ double color_to_total_y = 0.0;
+
+ absl::optional<QuantizedColor> quantized_color;
+};
+
bool GetHistogramForImage(const SkBitmap& image,
VisualFeatures::ColorHistogram* histogram) {
+ TRACE_EVENT0("safe_browsing", "GetHistogramForImage");
if (image.drawsNothing())
return false;
- std::unordered_map<QuantizedColor, int> color_to_count;
- std::unordered_map<QuantizedColor, double> color_to_total_x;
- std::unordered_map<QuantizedColor, double> color_to_total_y;
+ int normalization_factor;
+ if (!base::CheckMul(image.width(), image.height())
+ .AssignIfValid(&normalization_factor))
+ return false;
+
+ // Indexed with colors in rgba order.
+ std::unordered_map<uint32_t, ColorStats> stats_map;
+ auto it = stats_map.end();
+
+ // This code uses the unsafe getAddr32 function which assumes 32bpp depth.
+ // Make sure the color type reflects that.
+ CHECK_EQ(image.colorType(), SkColorType::kN32_SkColorType);
for (int x = 0; x < image.width(); x++) {
for (int y = 0; y < image.height(); y++) {
- QuantizedColor color = SkColorToQuantizedColor(image.getColor(x, y));
- color_to_count[color]++;
- color_to_total_x[color] += static_cast<float>(x) / image.width();
- color_to_total_y[color] += static_cast<float>(y) / image.height();
+ // The conversions to QuantizedColor are avoided when possible to save
+ // cycles but colors still need to be grouped in the same way they would
+ // with the conversion. To achieve this mask out the bits that would be
+ // ignored in the conversion.
+ constexpr uint32_t kMask = 0xe0e0e000;
+ uint32_t rgba = *image.getAddr32(x, y) & kMask;
+
+ // If we're updating the same color as the last don't fetch uselessly
+ // in the map and reuse the iterator we have.
+ if (it == stats_map.end() || it->first != rgba) {
+ it = stats_map.insert({rgba, ColorStats{}}).first;
+ }
+
+ // Update the color stats with the information from the current pixel.
+ ColorStats& stats = it->second;
+ stats.color_to_count++;
+ stats.color_to_total_x += static_cast<float>(x);
+ stats.color_to_total_y += static_cast<float>(y);
+
+ // If we've never encountered this color before do the conversion. Avoid
+ // it otherwise to save the overhead.
+ if (!stats.quantized_color.has_value()) {
+ stats.quantized_color.emplace(
+ SkColorToQuantizedColor(image.getColor(x, y)));
+ }
}
}
- int normalization_factor;
- if (!base::CheckMul(image.width(), image.height())
- .AssignIfValid(&normalization_factor))
- return false;
+ for (const auto& entry : stats_map) {
+ QuantizedColor color = entry.second.quantized_color.value();
- for (const auto& entry : color_to_count) {
- const QuantizedColor& color = entry.first;
- int count = entry.second;
+ const ColorStats& stats = entry.second;
+ int count = entry.second.color_to_count;
VisualFeatures::ColorHistogramBin* bin = histogram->add_bins();
bin->set_weight(static_cast<float>(count) / normalization_factor);
- bin->set_centroid_x(color_to_total_x[color] / count);
- bin->set_centroid_y(color_to_total_y[color] / count);
+ bin->set_centroid_x(stats.color_to_total_x / count / image.width());
+ bin->set_centroid_y(stats.color_to_total_y / count / image.height());
bin->set_quantized_r(GetQuantizedR(color));
bin->set_quantized_g(GetQuantizedG(color));
bin->set_quantized_b(GetQuantizedB(color));
@@ -185,6 +247,7 @@ bool GetHistogramForImage(const SkBitmap& image,
bool GetBlurredImage(const SkBitmap& image,
VisualFeatures::BlurredImage* blurred_image) {
+ TRACE_EVENT0("safe_browsing", "GetBlurredImage");
if (image.drawsNothing())
return false;
@@ -197,10 +260,9 @@ bool GetBlurredImage(const SkBitmap& image,
// average to be consistent with the backend.
// TODO(drubery): Investigate whether this is necessary for performance or
// not.
- SkImageInfo downsampled_info =
- SkImageInfo::Make(kPHashDownsampleWidth, kPHashDownsampleHeight,
- SkColorType::kRGBA_8888_SkColorType,
- SkAlphaType::kUnpremul_SkAlphaType, rec2020);
+ SkImageInfo downsampled_info = SkImageInfo::MakeN32(
+ GetPHashDownsampleWidth(), GetPHashDownsampleHeight(),
+ SkAlphaType::kUnpremul_SkAlphaType, rec2020);
SkBitmap downsampled;
if (!downsampled.tryAllocPixels(downsampled_info))
return false;
@@ -213,14 +275,17 @@ bool GetBlurredImage(const SkBitmap& image,
blurred_image->set_width(blurred->width());
blurred_image->set_height(blurred->height());
- blurred_image->clear_data();
-
- const uint32_t* rgba = blurred->getAddr32(0, 0);
- for (int i = 0; i < blurred->width() * blurred->height(); i++) {
- // Data is stored in BGR order.
- *blurred_image->mutable_data() += static_cast<char>((rgba[i] >> 0) & 0xff);
- *blurred_image->mutable_data() += static_cast<char>((rgba[i] >> 8) & 0xff);
- *blurred_image->mutable_data() += static_cast<char>((rgba[i] >> 16) & 0xff);
+
+ const int data_size = blurred->width() * blurred->height();
+ blurred_image->mutable_data()->reserve(data_size);
+
+ for (int x = 0; x < blurred->width(); ++x) {
+ for (int y = 0; y < blurred->height(); ++y) {
+ SkColor color = blurred->getColor(y, x);
+ *blurred_image->mutable_data() += static_cast<char>(SkColorGetR(color));
+ *blurred_image->mutable_data() += static_cast<char>(SkColorGetG(color));
+ *blurred_image->mutable_data() += static_cast<char>(SkColorGetB(color));
+ }
}
return true;
@@ -235,9 +300,9 @@ std::unique_ptr<SkBitmap> BlockMeanAverage(const SkBitmap& image,
int num_blocks_wide =
std::ceil(static_cast<float>(image.width()) / block_size);
- SkImageInfo target_info = SkImageInfo::Make(
- num_blocks_wide, num_blocks_high, SkColorType::kRGBA_8888_SkColorType,
- SkAlphaType::kUnpremul_SkAlphaType, image.refColorSpace());
+ SkImageInfo target_info = SkImageInfo::MakeN32(
+ num_blocks_wide, num_blocks_high, SkAlphaType::kUnpremul_SkAlphaType,
+ image.refColorSpace());
auto target = std::make_unique<SkBitmap>();
if (!target->tryAllocPixels(target_info))
return target;
@@ -255,9 +320,10 @@ std::unique_ptr<SkBitmap> BlockMeanAverage(const SkBitmap& image,
int y_end = std::min(y_start + block_size, image.height());
for (int i = x_start; i < x_end; i++) {
for (int j = y_start; j < y_end; j++) {
- r_total += SkColorGetR(image.getColor(i, j));
- g_total += SkColorGetG(image.getColor(i, j));
- b_total += SkColorGetB(image.getColor(i, j));
+ const QuantizedColor color = image.getColor(i, j);
+ r_total += SkColorGetR(color);
+ g_total += SkColorGetG(color);
+ b_total += SkColorGetB(color);
sample_count++;
}
}
@@ -267,7 +333,7 @@ std::unique_ptr<SkBitmap> BlockMeanAverage(const SkBitmap& image,
int b_mean = b_total / sample_count;
*target->getAddr32(block_x, block_y) =
- (255 << 24) | (b_mean << 16) | (g_mean << 8) | (r_mean << 0);
+ SkPackARGB32(255, r_mean, g_mean, b_mean);
}
}
@@ -276,6 +342,7 @@ std::unique_ptr<SkBitmap> BlockMeanAverage(const SkBitmap& image,
std::string GetHashFromBlurredImage(
VisualFeatures::BlurredImage blurred_image) {
+ TRACE_EVENT0("safe_browsing", "GetHashFromBlurredImage");
DCHECK_EQ(blurred_image.data().size(),
3u * blurred_image.width() * blurred_image.height());
// Convert the blurred image to grayscale.
@@ -322,23 +389,25 @@ std::string GetHashFromBlurredImage(
return output;
}
-base::Optional<VisionMatchResult> IsVisualMatch(const SkBitmap& image,
- const VisualTarget& target) {
- VisualFeatures::BlurredImage blurred_image;
- if (!GetBlurredImage(image, &blurred_image))
- return base::nullopt;
- std::string hash = GetHashFromBlurredImage(blurred_image);
- size_t hash_distance;
- bool has_hash_distance = GetHashDistance(hash, target.hash(), &hash_distance);
+absl::optional<VisionMatchResult> IsVisualMatch(
+ const SkBitmap& image,
+ const std::string& blurred_image_hash,
+ const VisualFeatures::ColorHistogram& histogram,
+ const VisualTarget& target) {
+ TRACE_EVENT0("safe_browsing", "IsVisualMatch");
- VisualFeatures::ColorHistogram histogram;
- if (!GetHistogramForImage(image, &histogram))
- return base::nullopt;
+ TRACE_EVENT_BEGIN0("safe_browsing", "IsVisualMatch_ComputeHashDistance");
+ size_t hash_distance;
+ bool has_hash_distance =
+ GetHashDistance(blurred_image_hash, target.hash(), &hash_distance);
+ TRACE_EVENT_END0("safe_browsing", "IsVisualMatch_ComputeHashDistance");
+ TRACE_EVENT_BEGIN0("safe_browsing", "IsVisualMatch_ComputeEMD");
opencv::PointDistribution point_distribution =
HistogramBinsToPointDistribution(histogram.bins());
- base::Optional<double> color_distance = opencv::EMD(
+ absl::optional<double> color_distance = opencv::EMD(
point_distribution, HistogramBinsToPointDistribution(target.bins()));
+ TRACE_EVENT_END0("safe_browsing", "IsVisualMatch_ComputeEMD");
for (const MatchRule& match_rule : target.match_config().match_rule()) {
bool is_match = true;
@@ -372,7 +441,7 @@ base::Optional<VisionMatchResult> IsVisualMatch(const SkBitmap& image,
}
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace visual_utils
diff --git a/chromium/components/safe_browsing/core/common/visual_utils.h b/chromium/components/safe_browsing/core/common/visual_utils.h
index 7716ca7c9c6..069b6f240ff 100644
--- a/chromium/components/safe_browsing/core/common/visual_utils.h
+++ b/chromium/components/safe_browsing/core/common/visual_utils.h
@@ -7,9 +7,9 @@
#include <string>
-#include "base/optional.h"
#include "components/safe_browsing/core/proto/client_model.pb.h"
#include "components/safe_browsing/core/proto/csd.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace safe_browsing {
@@ -44,10 +44,16 @@ std::unique_ptr<SkBitmap> BlockMeanAverage(const SkBitmap& image,
// Returns the hash used to compare blurred images.
std::string GetHashFromBlurredImage(VisualFeatures::BlurredImage blurred_image);
-// Returns whether the given |image| is a match for the |target|. Returns
-// nullopt in the case of no match, and the VisionMatchResult if it is a match.
-base::Optional<VisionMatchResult> IsVisualMatch(const SkBitmap& image,
- const VisualTarget& target);
+// Returns whether the given |image| is a match for the |target|.
+// |blurred_image_hash| should be obtained by applying GetBlurredImage()
+// and then GetHashFromBlurredImage() to |image|. |histogram| should be obtained
+// by applying GetHistogramForImage() to |image|. Returns nullopt in the case of
+// no match, and the VisionMatchResult if it is a match.
+absl::optional<VisionMatchResult> IsVisualMatch(
+ const SkBitmap& image,
+ const std::string& blurred_image_hash,
+ const VisualFeatures::ColorHistogram& histogram,
+ const VisualTarget& target);
} // namespace visual_utils
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/core/common/visual_utils_unittest.cc b/chromium/components/safe_browsing/core/common/visual_utils_unittest.cc
index 04f985d8c73..7d56fca853b 100644
--- a/chromium/components/safe_browsing/core/common/visual_utils_unittest.cc
+++ b/chromium/components/safe_browsing/core/common/visual_utils_unittest.cc
@@ -7,40 +7,30 @@
#include "base/test/test_discardable_memory_allocator.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkColorPriv.h"
namespace safe_browsing {
namespace visual_utils {
namespace {
-// Pixel value constants, all in BGR order.
-const unsigned int kWhite = 0xffffffff;
-const unsigned int kBlack = 0xff000000;
-const unsigned int kRed = 0xff0000ff;
-const unsigned int kGreen = 0xff00ff00;
-const unsigned int kBlue = 0xffff0000;
+const SkPMColor kSkPMRed = SkPackARGB32(255, 255, 0, 0);
+const SkPMColor kSkPMGreen = SkPackARGB32(255, 0, 255, 0);
+const SkPMColor kSkPMBlue = SkPackARGB32(255, 0, 0, 255);
// Use to add noise to the 5 lower bits of each color component. Use to
-// diversify input in tests that cover function that will only look at the most
-// significant three bits of each component. |i| is used to get different noise
-// that changes in sequence. Any number can be provided. Noise applied can be
-// identical for two different values of |i|.
-unsigned int AddNoiseToLowerBits(unsigned int color, unsigned int i) {
+// introduce values directly into an N32 bitmap's memory. Use to diversify input
+// in tests that cover function that will only look at the most significant
+// three bits of each component. |i| is used to get different noise that changes
+// in sequence. Any number can be provided. Noise applied can be identical for
+// two different values of |i|.
+SkPMColor AddNoiseToLowerBits(SkColor color, unsigned int i) {
// Get a mask between 00000 and 11111 from index.
unsigned int mask = i % 0x1f;
// Apply noise to each color component separately.
- color &= 0xffffffe0;
- color |= mask << 0;
-
- color &= 0xffffe0ff;
- color |= mask << 8;
-
- color &= 0xffe0ffff;
- color |= mask << 16;
-
- color &= 0xe0ffffff;
- color |= mask << 24;
+ color = SkColorSetARGB(SkColorGetA(color) | mask, SkColorGetR(color) | mask,
+ SkColorGetG(color) | mask, SkColorGetB(color) | mask);
return color;
}
@@ -57,9 +47,8 @@ class VisualUtilsTest : public testing::Test {
sk_sp<SkColorSpace> rec2020 = SkColorSpace::MakeRGB(
{2.22222f, 0.909672f, 0.0903276f, 0.222222f, 0.0812429f, 0, 0},
SkNamedGamut::kRec2020);
- SkImageInfo bitmap_info =
- SkImageInfo::Make(1000, 1000, SkColorType::kRGBA_8888_SkColorType,
- SkAlphaType::kUnpremul_SkAlphaType, rec2020);
+ SkImageInfo bitmap_info = SkImageInfo::MakeN32(
+ 1000, 1000, SkAlphaType::kUnpremul_SkAlphaType, rec2020);
ASSERT_TRUE(bitmap_.tryAllocPixels(bitmap_info));
}
@@ -68,6 +57,20 @@ class VisualUtilsTest : public testing::Test {
base::DiscardableMemoryAllocator::SetInstance(nullptr);
}
+ std::string GetBlurredBitmapHash() {
+ VisualFeatures::BlurredImage blurred_image;
+ EXPECT_TRUE(visual_utils::GetBlurredImage(bitmap_, &blurred_image));
+ std::string blurred_image_hash =
+ visual_utils::GetHashFromBlurredImage(blurred_image);
+ return blurred_image_hash;
+ }
+
+ VisualFeatures::ColorHistogram GetBitmapHistogram() {
+ VisualFeatures::ColorHistogram histogram;
+ EXPECT_TRUE(GetHistogramForImage(bitmap_, &histogram));
+ return histogram;
+ }
+
// A test bitmap to work with. Initialized to be 1000x1000 in the Rec 2020
// color space.
SkBitmap bitmap_;
@@ -77,7 +80,7 @@ class VisualUtilsTest : public testing::Test {
base::TestDiscardableMemoryAllocator test_allocator_;
};
-TEST_F(VisualUtilsTest, TestSkColorToQuantizedColor) {
+TEST_F(VisualUtilsTest, TestkColorToQuantizedColor) {
// Test quantization
EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(0, 0, 31)), 0u);
EXPECT_EQ(SkColorToQuantizedColor(SkColorSetRGB(0, 0, 32)), 1u);
@@ -113,14 +116,13 @@ TEST_F(VisualUtilsTest, GetQuantizedB) {
TEST_F(VisualUtilsTest, GetHistogramForImageWhite) {
VisualFeatures::ColorHistogram histogram;
- SkBitmap bitmap;
// Draw white over half the image
for (int x = 0; x < 1000; x++)
for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = AddNoiseToLowerBits(kWhite, x + y);
-
- *bitmap_.getAddr32(10, 10) = 0xffe0ffff;
+ // NOTE: getAddr32 used since byte ordering does not matter for white and
+ // repeated erase() calls might make tests time out.
+ *bitmap_.getAddr32(x, y) = AddNoiseToLowerBits(SK_ColorWHITE, x + y);
ASSERT_TRUE(GetHistogramForImage(bitmap_, &histogram));
ASSERT_EQ(histogram.bins_size(), 1);
@@ -140,12 +142,16 @@ TEST_F(VisualUtilsTest, GetHistogramForImageHalfWhiteHalfBlack) {
// Draw white over half the image
for (int x = 0; x < 1000; x++)
for (int y = 0; y < 500; y++)
- *bitmap_.getAddr32(x, y) = AddNoiseToLowerBits(kWhite, x + y);
+ // NOTE: getAddr32 used since byte ordering does not matter for white and
+ // repeated erase() calls might make tests time out.
+ *bitmap_.getAddr32(x, y) = AddNoiseToLowerBits(SK_ColorWHITE, x + y);
// Draw black over half the image.
for (int x = 0; x < 1000; x++)
for (int y = 500; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = AddNoiseToLowerBits(kBlack, x + y);
+ // NOTE: getAddr32 used since byte ordering does not matter for black and
+ // repeated erase() calls might make tests time out.
+ *bitmap_.getAddr32(x, y) = AddNoiseToLowerBits(SK_ColorBLACK, x + y);
ASSERT_TRUE(GetHistogramForImage(bitmap_, &histogram));
ASSERT_EQ(histogram.bins_size(), 2);
@@ -169,9 +175,7 @@ TEST_F(VisualUtilsTest, BlurImageWhite) {
VisualFeatures::BlurredImage blurred;
// Draw white over the image
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kWhite;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1000, 1000));
ASSERT_TRUE(GetBlurredImage(bitmap_, &blurred));
ASSERT_EQ(48, blurred.width());
@@ -190,7 +194,7 @@ TEST_F(VisualUtilsTest, BlurImageRed) {
// Draw red over the image.
for (int x = 0; x < 1000; x++)
for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kRed;
+ *bitmap_.getAddr32(x, y) = kSkPMRed;
ASSERT_TRUE(GetBlurredImage(bitmap_, &blurred));
ASSERT_EQ(48, blurred.width());
@@ -207,14 +211,10 @@ TEST_F(VisualUtilsTest, BlurImageHalfWhiteHalfBlack) {
VisualFeatures::BlurredImage blurred;
// Draw black over half the image.
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 500; y++)
- *bitmap_.getAddr32(x, y) = kBlack;
+ bitmap_.erase(SK_ColorBLACK, SkIRect::MakeXYWH(0, 0, 1000, 500));
// Draw white over half the image
- for (int x = 0; x < 1000; x++)
- for (int y = 500; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kWhite;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 500, 1000, 1000));
ASSERT_TRUE(GetBlurredImage(bitmap_, &blurred));
ASSERT_EQ(48, blurred.width());
@@ -237,14 +237,10 @@ TEST_F(VisualUtilsTest, BlurImageHalfWhiteHalfBlack) {
TEST_F(VisualUtilsTest, BlockMeanAverageOneBlock) {
// Draw black over half the image.
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 500; y++)
- *bitmap_.getAddr32(x, y) = kBlack;
+ bitmap_.erase(SK_ColorBLACK, SkIRect::MakeXYWH(0, 0, 1000, 500));
// Draw white over half the image
- for (int x = 0; x < 1000; x++)
- for (int y = 500; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kWhite;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 500, 1000, 1000));
std::unique_ptr<SkBitmap> blocks = BlockMeanAverage(bitmap_, 1000);
ASSERT_EQ(1, blocks->width());
@@ -254,37 +250,34 @@ TEST_F(VisualUtilsTest, BlockMeanAverageOneBlock) {
TEST_F(VisualUtilsTest, BlockMeanAveragePartialBlocks) {
// Draw a white, red, green, and blue box with the expected block sizes.
- for (int x = 0; x < 600; x++)
- for (int y = 0; y < 600; y++)
- *bitmap_.getAddr32(x, y) = kWhite;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 600, 600));
for (int x = 600; x < 1000; x++)
for (int y = 0; y < 600; y++)
- *bitmap_.getAddr32(x, y) = kRed;
+ *bitmap_.getAddr32(x, y) = kSkPMRed;
for (int x = 0; x < 600; x++)
for (int y = 600; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kGreen;
+ *bitmap_.getAddr32(x, y) = kSkPMGreen;
for (int x = 600; x < 1000; x++)
for (int y = 600; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kBlue;
+ *bitmap_.getAddr32(x, y) = kSkPMBlue;
std::unique_ptr<SkBitmap> blocks = BlockMeanAverage(bitmap_, 600);
ASSERT_EQ(2, blocks->width());
ASSERT_EQ(2, blocks->height());
- EXPECT_EQ(*blocks->getAddr32(0, 0), kWhite);
- EXPECT_EQ(*blocks->getAddr32(1, 0), kRed);
- EXPECT_EQ(*blocks->getAddr32(0, 1), kGreen);
- EXPECT_EQ(*blocks->getAddr32(1, 1), kBlue);
+ EXPECT_EQ(blocks->getColor(0, 0), SK_ColorWHITE);
+
+ EXPECT_EQ(*blocks->getAddr32(1, 0), kSkPMRed);
+ EXPECT_EQ(*blocks->getAddr32(0, 1), kSkPMGreen);
+ EXPECT_EQ(*blocks->getAddr32(1, 1), kSkPMBlue);
}
TEST_F(VisualUtilsTest, IsVisualMatchHash) {
{
// An all-white image should hash to all 1-bits.
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kWhite;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1000, 1000));
std::vector<unsigned char> target_hash;
target_hash.push_back('\x30');
@@ -294,15 +287,15 @@ TEST_F(VisualUtilsTest, IsVisualMatchHash) {
VisualTarget target;
target.set_hash(target_hash.data(), target_hash.size());
target.mutable_match_config()->add_match_rule()->set_hash_distance(0.0);
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
{
// Make the top quarter black, and the corresponding bits of the hash should
// be 0.
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 250; y++)
- *bitmap_.getAddr32(x, y) = kBlack;
+ bitmap_.erase(SK_ColorBLACK, SkIRect::MakeXYWH(0, 0, 1000, 250));
std::vector<unsigned char> target_hash;
target_hash.push_back('\x30');
@@ -314,19 +307,17 @@ TEST_F(VisualUtilsTest, IsVisualMatchHash) {
target.set_hash(target_hash.data(), target_hash.size());
target.mutable_match_config()->add_match_rule()->set_hash_distance(0.0);
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
}
TEST_F(VisualUtilsTest, IsVisualMatchHashPartialMatch) {
// Make the top quarter black, and the corresponding bits of the hash should
// be 0.
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 250; y++)
- *bitmap_.getAddr32(x, y) = kBlack;
- for (int x = 0; x < 1000; x++)
- for (int y = 250; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kWhite;
+ bitmap_.erase(SK_ColorBLACK, SkIRect::MakeXYWH(0, 0, 1000, 250));
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 250, 1000, 1000));
std::vector<unsigned char> target_hash;
target_hash.push_back('\x30');
@@ -338,15 +329,17 @@ TEST_F(VisualUtilsTest, IsVisualMatchHashPartialMatch) {
VisualTarget target;
target.set_hash(target_hash.data(), target_hash.size());
target.mutable_match_config()->add_match_rule()->set_hash_distance(23.0);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
target.mutable_match_config()->add_match_rule()->set_hash_distance(24.0);
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
TEST_F(VisualUtilsTest, IsVisualMatchHashStrideComparison) {
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kWhite;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1000, 1000));
std::vector<unsigned char> target_hash;
target_hash.push_back('\x30');
@@ -356,17 +349,23 @@ TEST_F(VisualUtilsTest, IsVisualMatchHashStrideComparison) {
VisualTarget target;
target.set_hash(target_hash.data(), target_hash.size());
target.mutable_match_config()->add_match_rule()->set_hash_distance(0.0);
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
target_hash[0] = '\x00';
target.set_hash(target_hash.data(), target_hash.size());
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
TEST_F(VisualUtilsTest, IsVisualMatchHistogramOnly) {
for (int x = 0; x < 1000; x++)
for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = AddNoiseToLowerBits(kWhite, x + y);
+ // NOTE: getAddr32 used since byte ordering does not matter for white and
+ // repeated erase calls might make tests time out.
+ *bitmap_.getAddr32(x, y) = AddNoiseToLowerBits(SK_ColorWHITE, x + y);
{
VisualTarget target;
@@ -380,7 +379,9 @@ TEST_F(VisualUtilsTest, IsVisualMatchHistogramOnly) {
bin->set_quantized_b(7);
bin->set_weight(1.0);
target.mutable_match_config()->add_match_rule()->set_color_distance(0.0);
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
{
@@ -397,10 +398,14 @@ TEST_F(VisualUtilsTest, IsVisualMatchHistogramOnly) {
MatchRule* match_rule = target.mutable_match_config()->add_match_rule();
match_rule->set_color_distance(0.5);
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
match_rule->set_color_distance(0.4);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
{
@@ -417,18 +422,21 @@ TEST_F(VisualUtilsTest, IsVisualMatchHistogramOnly) {
MatchRule* match_rule = target.mutable_match_config()->add_match_rule();
match_rule->set_color_distance(0.2);
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
match_rule->set_color_distance(0.1);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
}
TEST_F(VisualUtilsTest, IsVisualMatchColorRange) {
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = AddNoiseToLowerBits(kWhite, x + y);
- *bitmap_.getAddr32(0, 0) = kBlue;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1000, 1000));
+
+ *bitmap_.getAddr32(0, 0) = kSkPMBlue;
SkScalar hsv[3];
SkColorToHSV(bitmap_.getColor(0, 0), hsv);
@@ -440,29 +448,36 @@ TEST_F(VisualUtilsTest, IsVisualMatchColorRange) {
color_range->set_high(target_hue);
// Blue hue present
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// Color range too high
color_range->set_low(target_hue + 1);
color_range->set_high(target_hue + 1);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// Color range too low
color_range->set_low(target_hue - 1);
color_range->set_high(target_hue - 1);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// No blue hue present
- *bitmap_.getAddr32(0, 0) = AddNoiseToLowerBits(kWhite, 1);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
TEST_F(VisualUtilsTest, IsVisualMatchMultipleColorRanges) {
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = AddNoiseToLowerBits(kWhite, x + y);
- *bitmap_.getAddr32(0, 0) = kBlue;
- *bitmap_.getAddr32(1, 0) = kGreen;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1000, 1000));
+
+ *bitmap_.getAddr32(0, 0) = kSkPMBlue;
+ *bitmap_.getAddr32(1, 0) = kSkPMGreen;
SkScalar hsv[3];
SkColorToHSV(bitmap_.getColor(0, 0), hsv);
@@ -480,28 +495,36 @@ TEST_F(VisualUtilsTest, IsVisualMatchMultipleColorRanges) {
color_range->set_high(green_hue);
// Both hues present
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// No blue hue present
- *bitmap_.getAddr32(0, 0) = AddNoiseToLowerBits(kWhite, 1);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// No green hue present
- *bitmap_.getAddr32(0, 0) = AddNoiseToLowerBits(kBlue, 1);
- *bitmap_.getAddr32(1, 0) = AddNoiseToLowerBits(kWhite, 1);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ *bitmap_.getAddr32(0, 0) = kSkPMBlue;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(1, 0, 1, 1));
+
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// Neither hue present
- *bitmap_.getAddr32(0, 0) = AddNoiseToLowerBits(kWhite, 1);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
TEST_F(VisualUtilsTest, IsVisualMatchMultipleMatchRules) {
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kWhite;
- *bitmap_.getAddr32(0, 0) = kBlue;
- *bitmap_.getAddr32(1, 0) = kGreen;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
+
+ *bitmap_.getAddr32(0, 0) = kSkPMBlue;
+ *bitmap_.getAddr32(1, 0) = kSkPMGreen;
// Create a target with two match rules, one matching blue pixels and one
// matching green.
@@ -522,30 +545,36 @@ TEST_F(VisualUtilsTest, IsVisualMatchMultipleMatchRules) {
color_range->set_high(green_hue);
// Both hues present
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// No blue hue present
- *bitmap_.getAddr32(0, 0) = kWhite;
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// No green hue present
- *bitmap_.getAddr32(0, 0) = kBlue;
- *bitmap_.getAddr32(1, 0) = kWhite;
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ *bitmap_.getAddr32(0, 0) = kSkPMBlue;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(1, 0, 1, 1));
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// Neither hue present
- *bitmap_.getAddr32(0, 0) = kWhite;
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
TEST_F(VisualUtilsTest, IsVisualMatchFloatColorRange) {
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kWhite;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
// Adding a little noise in the red component makes the target_hue not an
// integer. Testing for this color requires float ranges.
- *bitmap_.getAddr32(0, 0) = kBlue | 0x0f;
+ *bitmap_.getAddr32(0, 0) = kSkPMBlue | 0x0f;
SkScalar hsv[3];
SkColorToHSV(bitmap_.getColor(0, 0), hsv);
@@ -557,29 +586,36 @@ TEST_F(VisualUtilsTest, IsVisualMatchFloatColorRange) {
color_range->set_high(target_hue);
// Blue hue present
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// Color range too high
color_range->set_low(target_hue + 0.1);
color_range->set_high(target_hue + 0.1);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// Color range too low
color_range->set_low(target_hue - 0.1);
color_range->set_high(target_hue - 0.1);
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// No blue hue present
- *bitmap_.getAddr32(0, 0) = kWhite;
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
TEST_F(VisualUtilsTest, IsVisualMatchMultipleFloatColorRanges) {
- for (int x = 0; x < 1000; x++)
- for (int y = 0; y < 1000; y++)
- *bitmap_.getAddr32(x, y) = kWhite;
- *bitmap_.getAddr32(0, 0) = kBlue;
- *bitmap_.getAddr32(1, 0) = kGreen;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
+
+ *bitmap_.getAddr32(0, 0) = kSkPMBlue;
+ *bitmap_.getAddr32(1, 0) = kSkPMGreen;
SkScalar hsv[3];
SkColorToHSV(bitmap_.getColor(0, 0), hsv);
@@ -597,20 +633,28 @@ TEST_F(VisualUtilsTest, IsVisualMatchMultipleFloatColorRanges) {
color_range->set_high(green_hue);
// Both hues present
- EXPECT_TRUE(IsVisualMatch(bitmap_, target).has_value());
+ EXPECT_TRUE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// No blue hue present
- *bitmap_.getAddr32(0, 0) = kWhite;
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// No green hue present
- *bitmap_.getAddr32(0, 0) = kBlue;
- *bitmap_.getAddr32(1, 0) = kWhite;
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ *bitmap_.getAddr32(0, 0) = kSkPMBlue;
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(1, 0, 1, 1));
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
// Neither hue present
- *bitmap_.getAddr32(0, 0) = kWhite;
- EXPECT_FALSE(IsVisualMatch(bitmap_, target).has_value());
+ bitmap_.erase(SK_ColorWHITE, SkIRect::MakeXYWH(0, 0, 1, 1));
+ EXPECT_FALSE(IsVisualMatch(bitmap_, GetBlurredBitmapHash(),
+ GetBitmapHistogram(), target)
+ .has_value());
}
} // namespace visual_utils
diff --git a/chromium/components/safe_browsing/core/db/util.h b/chromium/components/safe_browsing/core/db/util.h
index fe28410ec24..2597ac6b5f6 100644
--- a/chromium/components/safe_browsing/core/db/util.h
+++ b/chromium/components/safe_browsing/core/db/util.h
@@ -16,7 +16,6 @@
#include "base/containers/flat_map.h"
#include "base/strings/string_piece.h"
-#include "base/time/time.h"
#include "base/trace_event/traced_value.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
diff --git a/chromium/components/safe_browsing/core/db/v4_get_hash_protocol_manager_unittest.cc b/chromium/components/safe_browsing/core/db/v4_get_hash_protocol_manager_unittest.cc
index ec88c1e3686..c6aa0c76c5b 100644
--- a/chromium/components/safe_browsing/core/db/v4_get_hash_protocol_manager_unittest.cc
+++ b/chromium/components/safe_browsing/core/db/v4_get_hash_protocol_manager_unittest.cc
@@ -11,7 +11,6 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
diff --git a/chromium/components/safe_browsing/core/db/v4_local_database_manager.cc b/chromium/components/safe_browsing/core/db/v4_local_database_manager.cc
index 3625b4e84a4..ce33fc58e7c 100644
--- a/chromium/components/safe_browsing/core/db/v4_local_database_manager.cc
+++ b/chromium/components/safe_browsing/core/db/v4_local_database_manager.cc
@@ -126,6 +126,7 @@ ListInfos GetListInfos() {
std::vector<CommandLineSwitchAndThreatType> GetSwitchAndThreatTypes() {
static const std::vector<CommandLineSwitchAndThreatType>
command_line_switch_and_threat_type = {
+ {"mark_as_allowlisted_for_phish_guard", CSD_WHITELIST},
{"mark_as_allowlisted_for_real_time", HIGH_CONFIDENCE_ALLOWLIST},
{"mark_as_phishing", SOCIAL_ENGINEERING},
{"mark_as_malware", MALWARE_THREAT},
@@ -541,7 +542,12 @@ AsyncMatch V4LocalDatabaseManager::CheckCsdAllowlistUrl(const GURL& url,
DCHECK(CurrentlyOnThread(ThreadID::IO));
StoresToCheck stores_to_check({GetUrlCsdAllowlistId()});
- if (!AreAllStoresAvailableNow(stores_to_check) || !CanCheckUrl(url)) {
+ // If any artificial matches are present, consider the allowlist as ready.
+ bool is_artificial_prefix_empty =
+ artificially_marked_store_and_hash_prefixes_.empty();
+ if ((!AreAllStoresAvailableNow(stores_to_check) &&
+ is_artificial_prefix_empty) ||
+ !CanCheckUrl(url)) {
// Fail open: Allowlist everything. Otherwise we may run the
// CSD phishing/malware detector on popular domains and generate
// undue load on the client and server, or send Password Reputation
@@ -866,7 +872,7 @@ void V4LocalDatabaseManager::PopulateArtificialDatabase() {
ListIdentifier artificial_list_id(GetCurrentPlatformType(), URL,
switch_and_threat_type.second);
FullHash full_hash =
- V4ProtocolManagerUtil::GetFullHash(GURL(tokenizer.token()));
+ V4ProtocolManagerUtil::GetFullHash(GURL(tokenizer.token_piece()));
artificially_marked_store_and_hash_prefixes_.emplace_back(
artificial_list_id, full_hash);
}
diff --git a/chromium/components/safe_browsing/core/db/v4_local_database_manager.h b/chromium/components/safe_browsing/core/db/v4_local_database_manager.h
index 3319707c87f..270b65079b0 100644
--- a/chromium/components/safe_browsing/core/db/v4_local_database_manager.h
+++ b/chromium/components/safe_browsing/core/db/v4_local_database_manager.h
@@ -394,4 +394,4 @@ class V4LocalDatabaseManager : public SafeBrowsingDatabaseManager {
} // namespace safe_browsing
-#endif // COMPONENTS_SAFE_BROWSING_DB_V4_LOCAL_DATABASE_MANAGER_H_
+#endif // COMPONENTS_SAFE_BROWSING_CORE_DB_V4_LOCAL_DATABASE_MANAGER_H_
diff --git a/chromium/components/safe_browsing/core/db/v4_protocol_manager_util.cc b/chromium/components/safe_browsing/core/db/v4_protocol_manager_util.cc
index 331dfec5e75..0d74cd6f051 100644
--- a/chromium/components/safe_browsing/core/db/v4_protocol_manager_util.cc
+++ b/chromium/components/safe_browsing/core/db/v4_protocol_manager_util.cc
@@ -120,7 +120,7 @@ PlatformType GetCurrentPlatformType() {
return LINUX_PLATFORM;
#elif defined(OS_IOS)
return IOS_PLATFORM;
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
return OSX_PLATFORM;
#else
// TODO(crbug.com/1030487): This file is, in fact, intended to be compiled on
@@ -317,8 +317,11 @@ void V4ProtocolManagerUtil::RecordHttpResponseOrErrorCode(
const char* metric_name,
int net_error,
int response_code) {
- base::UmaHistogramSparse(metric_name,
- net_error == net::OK ? response_code : net_error);
+ base::UmaHistogramSparse(
+ metric_name,
+ net_error == net::OK || net_error == net::ERR_HTTP_RESPONSE_CODE_FAILURE
+ ? response_code
+ : net_error);
}
// static
diff --git a/chromium/components/safe_browsing/core/db/v4_protocol_manager_util.h b/chromium/components/safe_browsing/core/db/v4_protocol_manager_util.h
index e2963304c72..72e0b7bb7ff 100644
--- a/chromium/components/safe_browsing/core/db/v4_protocol_manager_util.h
+++ b/chromium/components/safe_browsing/core/db/v4_protocol_manager_util.h
@@ -10,8 +10,8 @@
#include <functional>
#include <initializer_list>
+#include <iosfwd>
#include <memory>
-#include <ostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
diff --git a/chromium/components/safe_browsing/core/db/v4_store.cc b/chromium/components/safe_browsing/core/db/v4_store.cc
index ec7ed07f74a..398895f24e3 100644
--- a/chromium/components/safe_browsing/core/db/v4_store.cc
+++ b/chromium/components/safe_browsing/core/db/v4_store.cc
@@ -14,7 +14,9 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
+#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
+#include "base/timer/elapsed_timer.h"
#include "components/safe_browsing/core/db/prefix_iterator.h"
#include "components/safe_browsing/core/db/v4_rice.h"
#include "components/safe_browsing/core/db/v4_store.pb.h"
@@ -38,8 +40,11 @@ const char kReadFromDisk[] = "SafeBrowsing.V4ReadFromDisk";
const char kApplyUpdate[] = ".ApplyUpdate";
const char kDecodeAdditions[] = ".DecodeAdditions";
const char kDecodeRemovals[] = ".DecodeRemovals";
-const char kAdditionsHashesCount[] = ".AdditionsHashesCount";
+const char kAdditionsHashesCountPartialUpdate[] = ".AdditionsHashesCount";
+const char kAdditionsHashesCountFullUpdate[] = ".AdditionsHashesCount2";
const char kRemovalsHashesCount[] = ".RemovalsHashesCount";
+const char kApplyUpdateDuration[] = ".ApplyUpdateDuration";
+const char kVerifyChecksumDuration[] = ".VerifyChecksumDuration";
// Part 3: Represent the unit of value being measured and logged.
const char kResult[] = ".Result";
// Part 4 (optional): Represent the name of the list for which the metric is
@@ -57,7 +62,9 @@ const uint32_t kFileVersion = 9;
constexpr size_t kMaxStoreSizeBytes = 50 * 1000 * 1000;
// The maximum size of additions hashes in a single update response.
-const int32_t ADDITIONS_HASHES_COUNT_MAX = 10000;
+const int32_t ADDITIONS_HASHES_COUNT_PARTIAL_UPDATE_MAX = 10000;
+const int32_t ADDITIONS_HASHES_COUNT_FULL_UPDATE_MAX = 5000000;
+
// The maximum size of removals hashes in a single update response.
const int32_t REMOVALS_HASHES_COUNT_MAX = 10000;
@@ -89,6 +96,14 @@ void RecordCountWithAndWithoutSuffix(const std::string& metric,
/*buckets=*/50);
}
+void RecordTimeWithAndWithoutSuffix(const std::string& metric,
+ base::TimeDelta duration,
+ const base::FilePath& file_path) {
+ base::UmaHistogramTimes(metric, duration);
+ std::string suffix = GetUmaSuffixForStore(file_path);
+ base::UmaHistogramTimes(metric + suffix, duration);
+}
+
void RecordApplyUpdateResult(const std::string& base_metric,
ApplyUpdateResult result,
const base::FilePath& file_path) {
@@ -113,8 +128,15 @@ void RecordDecodeRemovalsResult(const std::string& base_metric,
void RecordAdditionsHashesCount(const std::string& base_metric,
int32_t count,
const base::FilePath& file_path) {
- RecordCountWithAndWithoutSuffix(base_metric + kAdditionsHashesCount, count,
- ADDITIONS_HASHES_COUNT_MAX, file_path);
+ if (base_metric == kProcessFullUpdate) {
+ RecordCountWithAndWithoutSuffix(
+ base_metric + kAdditionsHashesCountFullUpdate, count,
+ ADDITIONS_HASHES_COUNT_FULL_UPDATE_MAX, file_path);
+ } else {
+ RecordCountWithAndWithoutSuffix(
+ base_metric + kAdditionsHashesCountPartialUpdate, count,
+ ADDITIONS_HASHES_COUNT_PARTIAL_UPDATE_MAX, file_path);
+ }
}
void RecordRemovalsHashesCount(const std::string& base_metric,
@@ -124,6 +146,20 @@ void RecordRemovalsHashesCount(const std::string& base_metric,
REMOVALS_HASHES_COUNT_MAX, file_path);
}
+void RecordApplyUpdateDuration(const std::string& base_metric,
+ base::TimeDelta duration,
+ const base::FilePath& file_path) {
+ RecordTimeWithAndWithoutSuffix(base_metric + kApplyUpdateDuration, duration,
+ file_path);
+}
+
+void RecordVerifyChecksumDuration(const std::string& base_metric,
+ base::TimeDelta duration,
+ const base::FilePath& file_path) {
+ RecordTimeWithAndWithoutSuffix(base_metric + kVerifyChecksumDuration,
+ duration, file_path);
+}
+
void RecordStoreReadResult(StoreReadResult result) {
UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreRead.Result", result,
STORE_READ_RESULT_MAX);
@@ -328,6 +364,7 @@ void V4Store::ApplyUpdate(
std::unique_ptr<ListUpdateResponse> response,
const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner,
UpdatedStoreReadyCallback callback) {
+ base::ElapsedThreadTimer thread_timer;
std::unique_ptr<V4Store> new_store(
new V4Store(task_runner_, store_path_, file_size_));
ApplyUpdateResult apply_update_result;
@@ -361,6 +398,7 @@ void V4Store::ApplyUpdate(
last_apply_update_result_ = apply_update_result;
RecordApplyUpdateResult(metric, apply_update_result, store_path_);
+ RecordApplyUpdateDuration(metric, thread_timer.Elapsed(), store_path_);
// Posting the task should be the last thing to do in this function.
// Otherwise, the posted task can end up running in parallel. If that
@@ -747,7 +785,7 @@ HashPrefix V4Store::GetMatchingHashPrefix(base::StringPiece full_hash) {
const PrefixSize& prefix_size = pair.first;
base::StringPiece hash_prefix = full_hash.substr(0, prefix_size);
if (HashPrefixMatches(hash_prefix, pair.second, prefix_size))
- return hash_prefix.as_string();
+ return std::string(hash_prefix);
}
return HashPrefix();
}
@@ -761,6 +799,7 @@ bool V4Store::HashPrefixMatches(base::StringPiece prefix,
}
bool V4Store::VerifyChecksum() {
+ base::ElapsedThreadTimer thread_timer;
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (expected_checksum_.empty()) {
@@ -808,9 +847,14 @@ bool V4Store::VerifyChecksum() {
<< "; expected: " << expected_checksum_b64
<< "; store: " << *this;
#endif
+ RecordVerifyChecksumDuration(kReadFromDisk, thread_timer.Elapsed(),
+ store_path_);
return false;
}
}
+
+ RecordVerifyChecksumDuration(kReadFromDisk, thread_timer.Elapsed(),
+ store_path_);
return true;
}
diff --git a/chromium/components/safe_browsing/core/db/v4_update_protocol_manager.h b/chromium/components/safe_browsing/core/db/v4_update_protocol_manager.h
index 79c39d0996e..aa32e9107fa 100644
--- a/chromium/components/safe_browsing/core/db/v4_update_protocol_manager.h
+++ b/chromium/components/safe_browsing/core/db/v4_update_protocol_manager.h
@@ -18,7 +18,6 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -27,6 +26,7 @@
#include "components/safe_browsing/core/db/util.h"
#include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/core/proto/webui.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -181,7 +181,7 @@ class V4UpdateProtocolManager {
// The time when the next update is scheduled to be requested. This is valid
// only when |update_timer_| is running.
- base::Optional<base::Time> next_update_time_ = base::nullopt;
+ absl::optional<base::Time> next_update_time_ = absl::nullopt;
// The config of the client making Pver4 requests.
const V4ProtocolConfig config_;
diff --git a/chromium/components/safe_browsing/core/db/v4_update_protocol_manager_unittest.cc b/chromium/components/safe_browsing/core/db/v4_update_protocol_manager_unittest.cc
index 57be9993901..00e969c79d0 100644
--- a/chromium/components/safe_browsing/core/db/v4_update_protocol_manager_unittest.cc
+++ b/chromium/components/safe_browsing/core/db/v4_update_protocol_manager_unittest.cc
@@ -10,7 +10,6 @@
#include "base/base64.h"
#include "base/bind.h"
-#include "base/strings/stringprintf.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
diff --git a/chromium/components/safe_browsing/core/fbs/BUILD.gn b/chromium/components/safe_browsing/core/fbs/BUILD.gn
new file mode 100644
index 00000000000..6a99e969c53
--- /dev/null
+++ b/chromium/components/safe_browsing/core/fbs/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/flatbuffers/flatbuffer.gni")
+
+flatbuffer("csd") {
+ sources = [ "csd.fbs" ]
+ mutable = true
+}
+
+flatbuffer("client_model") {
+ sources = [ "client_model.fbs" ]
+ public_deps = [ ":csd" ]
+ mutable = true
+}
diff --git a/chromium/components/safe_browsing/core/fbs/client_model.fbs b/chromium/components/safe_browsing/core/fbs/client_model.fbs
new file mode 100644
index 00000000000..57802922964
--- /dev/null
+++ b/chromium/components/safe_browsing/core/fbs/client_model.fbs
@@ -0,0 +1,110 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This flatbuffer represents a machine learning model which is used to compute
+// the probability that a particular page visited by Chrome is phishing.
+//
+// Note: since the machine learning model is trained on the server-side and then
+// downloaded onto the client it is important that this flatbuffer file stays in
+// sync with the server-side copy. Otherwise, the client may not be able to
+// parse the server generated model anymore. If you want to change this
+// flatbuffer definition or you have questions regarding its format please contact
+// chrome-anti-phishing@googlegroups.com.
+
+include "components/safe_browsing/core/fbs/csd.fbs";
+
+namespace safe_browsing.flat;
+
+table Hash {
+ data:[ubyte];
+}
+
+table ClientSideModel {
+ hashes:[Hash];
+ rule:[safe_browsing.flat.ClientSideModel_.Rule];
+ page_term:[int];
+ page_word:[uint];
+ max_words_per_term:int;
+ version:int;
+ bad_subnet:[safe_browsing.flat.ClientSideModel_.IPSubnet];
+ murmur_hash_seed:uint;
+ max_shingles_per_page:int = 200;
+ shingle_size:int = 4;
+ threshold_probability:float = 0.5;
+ vision_model:safe_browsing.flat.VisionModel;
+ tflite_model_version:int (deprecated);
+ tflite_thresholds:[safe_browsing.flat.TfLiteModelMetadata_.Threshold]
+ (deprecated);
+ tflite_model_input_width: int (deprecated);
+ tflite_model_input_height: int (deprecated);
+ tflite_metadata:safe_browsing.flat.TfLiteModelMetadata;
+}
+
+root_type ClientSideModel;
+
+namespace safe_browsing.flat.ClientSideModel_;
+
+table Rule {
+ feature:[int];
+ weight:float;
+}
+
+table IPSubnet {
+ prefix:[ubyte] (required);
+ size:int = 128;
+}
+
+namespace safe_browsing.flat;
+
+table TfLiteModelMetadata {
+ version:int;
+ thresholds:[safe_browsing.flat.TfLiteModelMetadata_.Threshold];
+ input_width: int;
+ input_height: int;
+}
+
+namespace safe_browsing.flat.TfLiteModelMetadata_;
+
+table Threshold {
+ label:string;
+ threshold:float;
+}
+
+namespace safe_browsing.flat;
+
+table VisionModel {
+ targets:[safe_browsing.flat.VisualTarget];
+}
+
+table VisualTarget {
+ digest:[ubyte];
+ timestamp_usec:long;
+ hash:[ubyte];
+ dimension_size:int;
+ bins:[safe_browsing.flat.VisualFeatures_.ColorHistogramBin];
+ match_config:safe_browsing.flat.MatchConfig;
+}
+
+table MatchConfig {
+ match_rule:[safe_browsing.flat.MatchRule];
+}
+
+table MatchRule {
+ hash_distance:double;
+ color_distance:double;
+ color_range:[safe_browsing.flat.MatchRule_.ColorRange];
+ float_color_range:[safe_browsing.flat.MatchRule_.FloatColorRange];
+}
+
+namespace safe_browsing.flat.MatchRule_;
+
+table ColorRange {
+ low:int;
+ high:int;
+}
+
+table FloatColorRange {
+ low:float;
+ high:float;
+}
diff --git a/chromium/components/safe_browsing/core/fbs/csd.fbs b/chromium/components/safe_browsing/core/fbs/csd.fbs
new file mode 100644
index 00000000000..e25e4ae76a8
--- /dev/null
+++ b/chromium/components/safe_browsing/core/fbs/csd.fbs
@@ -0,0 +1,22 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// If you want to change this flatbuffer definition or you have questions
+// regarding its format please contact chrome-anti-phishing@googlegroups.com.
+
+namespace safe_browsing.flat;
+
+table VisualFeatures {
+}
+
+namespace safe_browsing.flat.VisualFeatures_;
+
+table ColorHistogramBin {
+ centroid_x:float;
+ centroid_y:float;
+ quantized_r:int;
+ quantized_g:int;
+ quantized_b:int;
+ weight:float;
+} \ No newline at end of file
diff --git a/chromium/components/safe_browsing/core/features.cc b/chromium/components/safe_browsing/core/features.cc
index 02e6948dd30..b43c72bbd88 100644
--- a/chromium/components/safe_browsing/core/features.cc
+++ b/chromium/components/safe_browsing/core/features.cc
@@ -10,8 +10,10 @@
#include <vector>
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
+#include "base/system/sys_info.h"
#include "build/build_config.h"
#include "components/safe_browsing/buildflags.h"
+#include "components/variations/variations_associated_data.h"
#include "base/macros.h"
#include "base/values.h"
@@ -30,15 +32,28 @@ const base::Feature kAdRedirectTriggerFeature{
const base::Feature kAdSamplerTriggerFeature{"SafeBrowsingAdSamplerTrigger",
base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kBetterTelemetryAcrossReports{
+ "SafeBrowsingBetterTelemetryAcrossReports",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kCaptureInlineJavascriptForGoogleAds{
"CaptureInlineJavascriptForGoogleAds", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kClientSideDetectionForAndroid{
"ClientSideDetectionModelOnAndroid", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kClientSideDetectionModelIsFlatBuffer{
+ "ClientSideDetectionModelIsFlatBuffer", base::FEATURE_DISABLED_BY_DEFAULT};
+
extern const base::Feature kClientSideDetectionModelVersion{
"ClientSideDetectionModel", base::FEATURE_ENABLED_BY_DEFAULT};
+extern const base::Feature kClientSideDetectionModelTag{
+ "ClientSideDetectionTag", base::FEATURE_DISABLED_BY_DEFAULT};
+
+extern const base::Feature kClientSideDetectionModelHighMemoryTag{
+ "ClientSideDetectionHighMemoryTag", base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kClientSideDetectionReferrerChain{
"ClientSideDetectionReferrerChain", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -64,10 +79,6 @@ const base::Feature kDownloadRequestWithToken{
const base::Feature kLimitedListSizeForIOS{"SafeBrowsingLimitedListSizeForIOS",
base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kPasswordProtectionReferringAppEnabledAndroid{
- "SafeBrowsingPasswordProtectionReferringAppEnabledAndroid",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
const base::Feature kPasswordProtectionForSignedInUsers {
"SafeBrowsingPasswordProtectionForSignedInUsers",
#if BUILDFLAG(FULL_SAFE_BROWSING)
@@ -84,6 +95,9 @@ const base::Feature kPasswordProtectionWithToken{
const base::Feature kPromptEsbForDeepScanning{
"SafeBrowsingPromptEsbForDeepScanning", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kSafeBrowsingCTDownloadWarning{
+ "SafeBrowsingCTDownloadWarning", base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kSafeBrowsingEnterpriseCsd{
"SafeBrowsingEnterpriseCsd", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -94,14 +108,6 @@ const base::Feature kSafeBrowsingDisableConsumerCsdForEnterprise{
const base::Feature kRealTimeUrlLookupEnabled{
"SafeBrowsingRealTimeUrlLookupEnabled", base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kRealTimeUrlLookupEnabledForEnterprise{
- "SafeBrowsingRealTimeUrlLookupEnabledForEnterprise",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
-const base::Feature kRealTimeUrlLookupEnterpriseGaEndpoint{
- "SafeBrowsingkRealTimeUrlLookupEnterpriseGaEndpoint",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
const base::Feature kRealTimeUrlLookupEnabledWithToken{
"SafeBrowsingRealTimeUrlLookupEnabledWithToken",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -133,7 +139,10 @@ const base::Feature kUseNewDownloadWarnings{"UseNewDownloadWarnings",
const base::Feature kVisualFeaturesInPasswordProtectionAndroid{
"VisualFeaturesInPasswordProtectionAndroid",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kVisualFeaturesSizes{"VisualFeaturesSizes",
+ base::FEATURE_DISABLED_BY_DEFAULT};
namespace {
// List of Safe Browsing features. Boolean value for each list member should be
@@ -147,17 +156,17 @@ constexpr struct {
{&kAdPopupTriggerFeature, true},
{&kAdRedirectTriggerFeature, true},
{&kAdSamplerTriggerFeature, false},
+ {&kBetterTelemetryAcrossReports, true},
{&kCaptureInlineJavascriptForGoogleAds, true},
{&kClientSideDetectionForAndroid, true},
{&kClientSideDetectionWithToken, true},
{&kDelayedWarnings, true},
{&kDownloadRequestWithToken, true},
{&kLimitedListSizeForIOS, true},
- {&kPasswordProtectionReferringAppEnabledAndroid, true},
{&kPasswordProtectionForSignedInUsers, true},
+ {&kPasswordProtectionWithToken, true},
+ {&kPromptEsbForDeepScanning, true},
{&kRealTimeUrlLookupEnabled, true},
- {&kRealTimeUrlLookupEnabledForEnterprise, true},
- {&kRealTimeUrlLookupEnterpriseGaEndpoint, true},
{&kRealTimeUrlLookupEnabledWithToken, true},
{&kRealTimeUrlLookupReferrerChain, true},
{&kSafeBrowsingSeparateNetworkContexts, true},
@@ -186,6 +195,17 @@ base::ListValue GetFeatureStatusList() {
if (feature_status.show_state)
AddFeatureAndAvailability(feature_status.feature, &param_list);
}
+
+ // Manually add experimental features that we want param values for.
+ param_list.Append(base::Value(variations::GetVariationParamValueByFeature(
+ safe_browsing::kClientSideDetectionModelTag,
+ kClientSideDetectionTagParamName)));
+ param_list.Append(base::Value(kClientSideDetectionModelTag.name));
+ param_list.Append(base::Value(variations::GetVariationParamValueByFeature(
+ safe_browsing::kClientSideDetectionModelHighMemoryTag,
+ kClientSideDetectionTagParamName)));
+ param_list.Append(base::Value(kClientSideDetectionModelHighMemoryTag.name));
+
return param_list;
}
@@ -193,4 +213,27 @@ bool GetShouldFillOldPhishGuardProto() {
return kShouldFillOldPhishGuardProto.Get();
}
+std::string GetClientSideDetectionTag() {
+ constexpr char kMemoryThresholdParamName[] = "memory_threshold_mb";
+ const int kDefaultMemoryThresholdMB = 4096;
+ if (base::FeatureList::IsEnabled(
+ safe_browsing::kClientSideDetectionModelTag)) {
+ return variations::GetVariationParamValueByFeature(
+ safe_browsing::kClientSideDetectionModelTag,
+ kClientSideDetectionTagParamName);
+ } else if (base::FeatureList::IsEnabled(
+ safe_browsing::kClientSideDetectionModelHighMemoryTag)) {
+ int memory_threshold_mb = base::GetFieldTrialParamByFeatureAsInt(
+ safe_browsing::kClientSideDetectionModelHighMemoryTag,
+ kMemoryThresholdParamName, kDefaultMemoryThresholdMB);
+ if (base::SysInfo::AmountOfPhysicalMemoryMB() >= memory_threshold_mb) {
+ return variations::GetVariationParamValueByFeature(
+ safe_browsing::kClientSideDetectionModelHighMemoryTag,
+ kClientSideDetectionTagParamName);
+ }
+ }
+
+ return "default";
+}
+
} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/core/features.h b/chromium/components/safe_browsing/core/features.h
index 8ee52e75f7c..1e3e2523ed4 100644
--- a/chromium/components/safe_browsing/core/features.h
+++ b/chromium/components/safe_browsing/core/features.h
@@ -6,13 +6,12 @@
#define COMPONENTS_SAFE_BROWSING_CORE_FEATURES_H_
#include <stddef.h>
-#include <algorithm>
-#include <utility>
-#include <vector>
#include "base/feature_list.h"
#include "base/macros.h"
+#include "base/metrics/field_trial_params.h"
#include "base/values.h"
+
namespace base {
class ListValue;
} // namespace base
@@ -30,6 +29,10 @@ extern const base::Feature kAdRedirectTriggerFeature;
extern const base::Feature kAdSamplerTriggerFeature;
+// Enables including some information in protection requests sent to Safe
+// Browsing.
+extern const base::Feature kBetterTelemetryAcrossReports;
+
// Controls whether we sample inline JavaScript for ads in RIND
// reports.
extern const base::Feature kCaptureInlineJavascriptForGoogleAds;
@@ -37,10 +40,26 @@ extern const base::Feature kCaptureInlineJavascriptForGoogleAds;
// Enables client side detection on Android.
extern const base::Feature kClientSideDetectionForAndroid;
+// The client side detection model is a flatbuffer.
+extern const base::Feature kClientSideDetectionModelIsFlatBuffer;
+
// Determines the experimental version of client side detection model, for
// Desktop.
extern const base::Feature kClientSideDetectionModelVersion;
+// Determines the tag to pass to Omaha to get a client side detection model.
+extern const base::Feature kClientSideDetectionModelTag;
+
+// Determines the tag to pass to Omaha to get a client side detection model.
+// This is used for high-memory devices, when `kClientSideDetectionModelTag` is
+// disabled.
+extern const base::Feature kClientSideDetectionModelHighMemoryTag;
+
+// The parameter name used for getting the tag values from client side detection
+// features, `kClientSideDetectionModelTag` and
+// `kClientSideDetectionModelHighMemoryTag`.
+const char kClientSideDetectionTagParamName[] = "reporter_omaha_tag";
+
// Enables client side detection referrer chain.
extern const base::Feature kClientSideDetectionReferrerChain;
@@ -56,9 +75,6 @@ extern const base::Feature kDownloadRequestWithToken;
// limits the number of entries stored in each Safe Browsing list.
extern const base::Feature kLimitedListSizeForIOS;
-// Include referring app info in password protection requests on Android.
-extern const base::Feature kPasswordProtectionReferringAppEnabledAndroid;
-
// Enable GAIA password protection for signed-in users.
extern const base::Feature kPasswordProtectionForSignedInUsers;
@@ -70,8 +86,12 @@ extern const base::Feature kPasswordProtectionWithToken;
// scanning.
extern const base::Feature kPromptEsbForDeepScanning;
-// Controls whether we are performing enterprise download checks for users with
-// the appropriate policies enabled.
+// Contros whether users will see an account compromise specific warning
+// when Safe Browsing determines a file is associated with stealing cookies.
+extern const base::Feature kSafeBrowsingCTDownloadWarning;
+
+// Controls whether we are performing enterprise download checks for users
+// with the appropriate policies enabled.
extern const base::Feature kSafeBrowsingEnterpriseCsd;
// Controls whether we are disabling consumer download checks for users using
@@ -92,15 +112,6 @@ extern const base::Feature kSuspiciousSiteTriggerQuotaFeature;
// Controls whether the real time URL lookup is enabled.
extern const base::Feature kRealTimeUrlLookupEnabled;
-// Controls whether to do real time URL lookup for enterprise users. If both
-// this feature and the enterprise policies are enabled, the enterprise real
-// time URL lookup will be enabled and the consumer real time URL lookup will be
-// disabled.
-extern const base::Feature kRealTimeUrlLookupEnabledForEnterprise;
-
-// Controls whether to use the GA endpoint for enterprise real time URL lookup.
-extern const base::Feature kRealTimeUrlLookupEnterpriseGaEndpoint;
-
// Controls whether the GAIA-keyed real time URL lookup is enabled.
extern const base::Feature kRealTimeUrlLookupEnabledWithToken;
@@ -132,6 +143,11 @@ extern const base::Feature kUseNewDownloadWarnings;
// Android.
extern const base::Feature kVisualFeaturesInPasswordProtectionAndroid;
+// Controls the behavior of visual features in CSD pings. This feature is
+// checked for the final size of the visual features and the minimum size of
+// the screen.
+extern const base::Feature kVisualFeaturesSizes;
+
// Controls whether the delayed warning experiment is enabled.
extern const base::Feature kDelayedWarnings;
// True if mouse clicks should undelay the warnings immediately when delayed
@@ -151,5 +167,9 @@ base::ListValue GetFeatureStatusList();
// |kPasswordProtectionForSignedInUsers| experiment.
bool GetShouldFillOldPhishGuardProto();
+// Returns the tag used for Client Side Phishing Detection models, as
+// computed from the current feature flags.
+std::string GetClientSideDetectionTag();
+
} // namespace safe_browsing
#endif // COMPONENTS_SAFE_BROWSING_CORE_FEATURES_H_
diff --git a/chromium/components/safe_browsing/core/features_unittest.cc b/chromium/components/safe_browsing/core/features_unittest.cc
new file mode 100644
index 00000000000..c87a5afa826
--- /dev/null
+++ b/chromium/components/safe_browsing/core/features_unittest.cc
@@ -0,0 +1,93 @@
+// Copyright 2021 The Chromium Authors. 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/core/features.h"
+
+#include "base/system/sys_info.h"
+#include "base/test/scoped_feature_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace safe_browsing {
+
+TEST(SafeBrowsingFeatures, ClientSideDetectionTagDefault) {
+ EXPECT_EQ(GetClientSideDetectionTag(), "default");
+}
+
+TEST(SafeBrowsingFeatures, ClientSideDetectionTagAllUsers) {
+ base::test::ScopedFeatureList feature_list;
+ base::test::ScopedFeatureList::FeatureAndParams all_users_feature(
+ kClientSideDetectionModelTag, {{"reporter_omaha_tag", "all_users_tag"}});
+ feature_list.InitWithFeaturesAndParameters({all_users_feature}, {});
+ EXPECT_EQ(GetClientSideDetectionTag(), "all_users_tag");
+}
+
+TEST(SafeBrowsingFeatures, ClientSideDetectionTagHighMemory) {
+ // One case where the user has enough memory
+ {
+ base::test::ScopedFeatureList::FeatureAndParams high_memory_feature(
+ kClientSideDetectionModelHighMemoryTag,
+ {{"reporter_omaha_tag", "high_memory_tag"},
+ {"memory_threshold_mb",
+ base::NumberToString(base::SysInfo::AmountOfPhysicalMemoryMB() -
+ 1)}});
+
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters({high_memory_feature}, {});
+ EXPECT_EQ(GetClientSideDetectionTag(), "high_memory_tag");
+ }
+
+ // One case where the user does not have enough memory
+ {
+ base::test::ScopedFeatureList::FeatureAndParams high_memory_feature(
+ kClientSideDetectionModelHighMemoryTag,
+ {{"reporter_omaha_tag", "high_memory_tag"},
+ {"memory_threshold_mb",
+ base::NumberToString(base::SysInfo::AmountOfPhysicalMemoryMB() +
+ 1)}});
+
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters({high_memory_feature}, {});
+ EXPECT_EQ(GetClientSideDetectionTag(), "default");
+ }
+}
+
+TEST(SafeBrowsingFeatures, ClientSideDetectionTagAllUsersAndHighMemory) {
+ // One case where the user has enough memory
+ {
+ base::test::ScopedFeatureList::FeatureAndParams all_users_feature(
+ kClientSideDetectionModelTag,
+ {{"reporter_omaha_tag", "all_users_tag"}});
+ base::test::ScopedFeatureList::FeatureAndParams high_memory_feature(
+ kClientSideDetectionModelHighMemoryTag,
+ {{"reporter_omaha_tag", "high_memory_tag"},
+ {"memory_threshold_mb",
+ base::NumberToString(base::SysInfo::AmountOfPhysicalMemoryMB() -
+ 1)}});
+
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters(
+ {all_users_feature, high_memory_feature}, {});
+ EXPECT_EQ(GetClientSideDetectionTag(), "all_users_tag");
+ }
+
+ // One case where the user does not have enough memory
+ {
+ base::test::ScopedFeatureList::FeatureAndParams all_users_feature(
+ kClientSideDetectionModelTag,
+ {{"reporter_omaha_tag", "all_users_tag"}});
+ base::test::ScopedFeatureList::FeatureAndParams high_memory_feature(
+ kClientSideDetectionModelHighMemoryTag,
+ {{"reporter_omaha_tag", "high_memory_tag"},
+ {"memory_threshold_mb",
+ base::NumberToString(base::SysInfo::AmountOfPhysicalMemoryMB() +
+ 1)}});
+
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters(
+ {all_users_feature, high_memory_feature}, {});
+ EXPECT_EQ(GetClientSideDetectionTag(), "all_users_tag");
+ }
+}
+
+} // namespace safe_browsing
diff --git a/chromium/components/safe_browsing/core/password_protection/DIR_METADATA b/chromium/components/safe_browsing/core/password_protection/DIR_METADATA
deleted file mode 100644
index ee2d9cf50ff..00000000000
--- a/chromium/components/safe_browsing/core/password_protection/DIR_METADATA
+++ /dev/null
@@ -1,4 +0,0 @@
-monorail: {
- component: "Services>Safebrowsing"
-}
-team_email: "safebrowsing@chromium.org"
diff --git a/chromium/components/safe_browsing/core/password_protection/password_protection_request.cc b/chromium/components/safe_browsing/core/password_protection/password_protection_request.cc
index 131c75df82b..54793f27bca 100644
--- a/chromium/components/safe_browsing/core/password_protection/password_protection_request.cc
+++ b/chromium/components/safe_browsing/core/password_protection/password_protection_request.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/safe_browsing/core/common/safebrowsing_constants.h"
#include "components/safe_browsing/core/common/thread_utils.h"
#include "components/safe_browsing/core/db/allowlist_checker_client.h"
#include "components/safe_browsing/core/db/database_manager.h"
@@ -29,8 +30,6 @@ namespace safe_browsing {
using ReusedPasswordAccountType =
LoginReputationClientRequest::PasswordReuseEvent::ReusedPasswordAccountType;
-constexpr char kAuthHeaderBearer[] = "Bearer ";
-
namespace {
// Cap on how many reused domains can be included in a report, to limit
@@ -232,10 +231,6 @@ void PasswordProtectionRequest::FillRequestProto(bool is_sampled_ping) {
SetReferringAppInfo();
#endif // defined(OS_ANDROID)
-#if defined(OS_ANDROID)
- SetReferringAppInfo();
-#endif // defined(OS_ANDROID)
-
switch (trigger_type_) {
case LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE: {
LoginReputationClientRequest::Frame::Form* password_form;
@@ -332,7 +327,7 @@ void PasswordProtectionRequest::SendRequestWithToken(
const std::string& access_token) {
DCHECK(CurrentlyOnThread(ThreadID::UI));
- MaybeAddPingToWebUI();
+ MaybeAddPingToWebUI(access_token);
std::string serialized_request;
// TODO(crbug.com/1158582): Return early if request serialization fails.
diff --git a/chromium/components/safe_browsing/core/password_protection/password_protection_request.h b/chromium/components/safe_browsing/core/password_protection/password_protection_request.h
index 52ea12a2aae..49ffe68e268 100644
--- a/chromium/components/safe_browsing/core/password_protection/password_protection_request.h
+++ b/chromium/components/safe_browsing/core/password_protection/password_protection_request.h
@@ -153,7 +153,7 @@ class PasswordProtectionRequest
const LoginReputationClientResponse* response) = 0;
// Subclasses may override this method to add pings to the WebUI.
- virtual void MaybeAddPingToWebUI() {}
+ virtual void MaybeAddPingToWebUI(const std::string& oauth_token) {}
// Subclasses may override this method to add responses to the WebUI.
virtual void MaybeAddResponseToWebUI(
diff --git a/chromium/components/safe_browsing/core/password_protection/password_protection_service_base.h b/chromium/components/safe_browsing/core/password_protection/password_protection_service_base.h
index c775a5cbc21..4f8222edb4d 100644
--- a/chromium/components/safe_browsing/core/password_protection/password_protection_service_base.h
+++ b/chromium/components/safe_browsing/core/password_protection/password_protection_service_base.h
@@ -14,7 +14,6 @@
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/task/cancelable_task_tracker.h"
-#include "base/values.h"
#include "build/build_config.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_service_observer.h"
diff --git a/chromium/components/safe_browsing/core/proto/client_model.proto b/chromium/components/safe_browsing/core/proto/client_model.proto
index f2e2bb6290d..a3587e0d038 100644
--- a/chromium/components/safe_browsing/core/proto/client_model.proto
+++ b/chromium/components/safe_browsing/core/proto/client_model.proto
@@ -102,6 +102,38 @@ message ClientSideModel {
// The vision model.
optional VisionModel vision_model = 12;
+
+ // Reserved tag numbers holding deprecated fields.
+ reserved 13;
+ reserved 14;
+ reserved 15;
+ reserved 16;
+
+ optional TfLiteModelMetadata tflite_metadata = 17;
+
+ // next available tag number: 18
+}
+
+message TfLiteModelMetadata {
+ // The version number of the visual TFLite model.
+ optional int32 model_version = 1;
+
+ message Threshold {
+ // The label for the category
+ optional string label = 1;
+
+ // The threshold value
+ optional float threshold = 2;
+ }
+
+ // The list of threshold values for each category in the TFLite model. Pages
+ // where the model score exceeds one of these thresholds will be sent to
+ // Safe Browsing for a more definitive classification.
+ repeated Threshold thresholds = 2;
+
+ // The width and height of the input tensor to the corresponding TFLite model.
+ optional int32 input_width = 3;
+ optional int32 input_height = 4;
}
// Wrapper of the vision model for the similarity check target images.
diff --git a/chromium/components/safe_browsing/core/proto/csd.proto b/chromium/components/safe_browsing/core/proto/csd.proto
index 8cd0721a974..7fcd43a2b8b 100644
--- a/chromium/components/safe_browsing/core/proto/csd.proto
+++ b/chromium/components/safe_browsing/core/proto/csd.proto
@@ -69,6 +69,22 @@ message ChromeUserPopulation {
// If the user is opted in to MBB.
optional bool is_mbb_enabled = 8;
+
+ // The simplified user agent string (e.g. Chrome/xy.0.abcd.e/Windows).
+ optional string user_agent = 9;
+
+ // The total number of profiles available on this machine. Some of these may
+ // not be fully initialized so can't be used.
+ optional int32 number_of_profiles = 10;
+
+ // The number of created and fully initialized profiles. Some of these
+ // profiles may be inactive.
+ optional int32 number_of_loaded_profiles = 11;
+
+ // The number of profiles that are currently open, i.e. have open browsers or
+ // were open the last time Chrome was running. Profiles that fail to
+ // initialize are skipped.
+ optional int32 number_of_open_profiles = 12;
}
message ClientPhishingRequest {
@@ -128,8 +144,8 @@ message ClientPhishingRequest {
// List of shingle hashes we extracted.
repeated uint32 shingle_hashes = 12 [packed = true];
- // The model filename (basename) that was used by the client.
- optional string model_filename = 13;
+ // The model filename (basename) that was used by the client. Deprecated.
+ optional string DEPRECATED_model_filename = 13 [deprecated = true];
// Population that the reporting user is part of.
optional ChromeUserPopulation population = 14;
@@ -160,7 +176,20 @@ message ClientPhishingRequest {
// events to this list. The type of these entries will be RECENT_NAVIGATION.
repeated ReferrerChainEntry referrer_chain = 22;
- // next available tag number: 23.
+ // The version of the TFLite model used for classification
+ optional int32 tflite_model_version = 23;
+
+ message CategoryScore {
+ optional string label = 1;
+ optional float value = 2;
+ }
+ // The resulting score from the TFLite model
+ repeated CategoryScore tflite_model_scores = 24;
+
+ // Whether the TFLite model believed the page was phishy.
+ optional bool is_tflite_match = 25;
+
+ // next available tag number: 26.
}
// Vision match result for one target image.
@@ -952,6 +981,9 @@ message ClientDownloadResponse {
// The backend doesn't have confidence in its verdict of this file.
// Chrome should show the default warning if configured for this file type.
UNKNOWN = 5;
+ // Download is associated with stealing cookies and account compromise.
+ // Chrome should show a severe warning.
+ DANGEROUS_ACCOUNT_COMPROMISE = 8;
}
optional Verdict verdict = 1 [default = SAFE];
diff --git a/chromium/components/safe_browsing/core/realtime/DIR_METADATA b/chromium/components/safe_browsing/core/realtime/DIR_METADATA
deleted file mode 100644
index 578f3dfc4ea..00000000000
--- a/chromium/components/safe_browsing/core/realtime/DIR_METADATA
+++ /dev/null
@@ -1,5 +0,0 @@
-monorail {
- component: "Services>Safebrowsing"
-}
-
-team_email: "safebrowsing@chromium.org"
diff --git a/chromium/components/safe_browsing/core/realtime/policy_engine.cc b/chromium/components/safe_browsing/core/realtime/policy_engine.cc
index 291be557577..2fbae581ef3 100644
--- a/chromium/components/safe_browsing/core/realtime/policy_engine.cc
+++ b/chromium/components/safe_browsing/core/realtime/policy_engine.cc
@@ -96,10 +96,6 @@ bool RealTimePolicyEngine::CanPerformEnterpriseFullURLLookup(
return false;
}
- if (!base::FeatureList::IsEnabled(kRealTimeUrlLookupEnabledForEnterprise)) {
- return false;
- }
-
if (!has_valid_dm_token) {
return false;
}
diff --git a/chromium/components/safe_browsing/core/realtime/policy_engine_unittest.cc b/chromium/components/safe_browsing/core/realtime/policy_engine_unittest.cc
index 40222668ae2..28105dd047b 100644
--- a/chromium/components/safe_browsing/core/realtime/policy_engine_unittest.cc
+++ b/chromium/components/safe_browsing/core/realtime/policy_engine_unittest.cc
@@ -178,29 +178,16 @@ TEST_F(
TEST_F(RealTimePolicyEngineTest, TestCanPerformEnterpriseFullURLLookup) {
// Is off the record profile.
{
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(kRealTimeUrlLookupEnabledForEnterprise);
EXPECT_FALSE(CanPerformEnterpriseFullURLLookup(/*has_valid_dm_token=*/true,
/*is_off_the_record=*/true));
}
- // Feature flag disabled.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(kRealTimeUrlLookupEnabledForEnterprise);
- EXPECT_FALSE(CanPerformEnterpriseFullURLLookup(
- /*has_valid_dm_token=*/true, /*is_off_the_record=*/false));
- }
// No valid DM token.
{
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(kRealTimeUrlLookupEnabledForEnterprise);
EXPECT_FALSE(CanPerformEnterpriseFullURLLookup(
/*has_valid_dm_token=*/false, /*is_off_the_record=*/false));
}
// Policy disabled.
{
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(kRealTimeUrlLookupEnabledForEnterprise);
pref_service_.SetUserPref(
prefs::kSafeBrowsingEnterpriseRealTimeUrlCheckMode,
std::make_unique<base::Value>(REAL_TIME_CHECK_DISABLED));
@@ -209,8 +196,6 @@ TEST_F(RealTimePolicyEngineTest, TestCanPerformEnterpriseFullURLLookup) {
}
// Policy enabled.
{
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(kRealTimeUrlLookupEnabledForEnterprise);
pref_service_.SetUserPref(
prefs::kSafeBrowsingEnterpriseRealTimeUrlCheckMode,
std::make_unique<base::Value>(REAL_TIME_CHECK_FOR_MAINFRAME_ENABLED));
diff --git a/chromium/components/safe_browsing/core/realtime/url_lookup_service.cc b/chromium/components/safe_browsing/core/realtime/url_lookup_service.cc
index 132a97f399c..96cec4693bc 100644
--- a/chromium/components/safe_browsing/core/realtime/url_lookup_service.cc
+++ b/chromium/components/safe_browsing/core/realtime/url_lookup_service.cc
@@ -85,7 +85,12 @@ void RealTimeUrlLookupService::OnGetAccessToken(
std::move(response_callback));
}
-RealTimeUrlLookupService::~RealTimeUrlLookupService() {}
+void RealTimeUrlLookupService::OnResponseUnauthorized(
+ const std::string& invalid_access_token) {
+ token_fetcher_->OnInvalidAccessToken(invalid_access_token);
+}
+
+RealTimeUrlLookupService::~RealTimeUrlLookupService() = default;
bool RealTimeUrlLookupService::CanPerformFullURLLookup() const {
return RealTimePolicyEngine::CanPerformFullURLLookup(
@@ -168,9 +173,9 @@ RealTimeUrlLookupService::GetTrafficAnnotationTag() const {
})");
}
-base::Optional<std::string> RealTimeUrlLookupService::GetDMTokenString() const {
+absl::optional<std::string> RealTimeUrlLookupService::GetDMTokenString() const {
// DM token should only be set for enterprise requests.
- return base::nullopt;
+ return absl::nullopt;
}
std::string RealTimeUrlLookupService::GetMetricSuffix() const {
diff --git a/chromium/components/safe_browsing/core/realtime/url_lookup_service.h b/chromium/components/safe_browsing/core/realtime/url_lookup_service.h
index d87e74a4245..ad2b3345921 100644
--- a/chromium/components/safe_browsing/core/realtime/url_lookup_service.h
+++ b/chromium/components/safe_browsing/core/realtime/url_lookup_service.h
@@ -11,13 +11,13 @@
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/core/proto/csd.pb.h"
#include "components/safe_browsing/core/proto/realtimeapi.pb.h"
#include "components/safe_browsing/core/realtime/url_lookup_service_base.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace net {
@@ -83,9 +83,10 @@ class RealTimeUrlLookupService : public RealTimeUrlLookupServiceBase {
void GetAccessToken(const GURL& url,
RTLookupRequestCallback request_callback,
RTLookupResponseCallback response_callback) override;
- base::Optional<std::string> GetDMTokenString() const override;
+ absl::optional<std::string> GetDMTokenString() const override;
std::string GetMetricSuffix() const override;
bool ShouldIncludeCredentials() const override;
+ void OnResponseUnauthorized(const std::string& invalid_access_token) override;
// Called when the access token is obtained from |token_fetcher_|.
void OnGetAccessToken(const GURL& url,
diff --git a/chromium/components/safe_browsing/core/realtime/url_lookup_service_base.cc b/chromium/components/safe_browsing/core/realtime/url_lookup_service_base.cc
index 60020eafe08..b4b3d236ec7 100644
--- a/chromium/components/safe_browsing/core/realtime/url_lookup_service_base.cc
+++ b/chromium/components/safe_browsing/core/realtime/url_lookup_service_base.cc
@@ -15,6 +15,7 @@
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/core/browser/referrer_chain_provider.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safebrowsing_constants.h"
#include "components/safe_browsing/core/common/thread_utils.h"
#include "components/safe_browsing/core/common/utils.h"
#include "components/safe_browsing/core/verdict_cache_manager.h"
@@ -38,8 +39,6 @@ const size_t kMaxBackOffResetDurationInSeconds = 30 * 60; // 30 minutes.
const size_t kURLLookupTimeoutDurationInSeconds = 3;
-constexpr char kAuthHeaderBearer[] = "Bearer ";
-
// Represents the value stored in the |version| field of |RTLookupRequest|.
const int kRTLookupRequestVersion = 2;
@@ -171,7 +170,6 @@ GURL RealTimeUrlLookupServiceBase::SanitizeURL(const GURL& url) {
void RealTimeUrlLookupServiceBase::SanitizeReferrerChainEntries(
ReferrerChain* referrer_chain) {
for (ReferrerChainEntry& entry : *referrer_chain) {
- // TODO(crbug.com/1161342): Also set the is_subframe_url_removed field after
// is_subframe_url_removed is added in the proto.
// If the entry sets main_frame_url, that means the url is triggered in a
// subframe. Thus replace the url with the main_frame_url and clear
@@ -330,14 +328,14 @@ void RealTimeUrlLookupServiceBase::StartLookup(
GetAccessToken(url, std::move(request_callback),
std::move(response_callback));
} else {
- SendRequest(url, /* access_token_string */ base::nullopt,
+ SendRequest(url, /* access_token_string */ absl::nullopt,
std::move(request_callback), std::move(response_callback));
}
}
void RealTimeUrlLookupServiceBase::SendRequest(
const GURL& url,
- base::Optional<std::string> access_token_string,
+ absl::optional<std::string> access_token_string,
RTLookupRequestCallback request_callback,
RTLookupResponseCallback response_callback) {
DCHECK(CurrentlyOnThread(ThreadID::UI));
@@ -362,7 +360,7 @@ void RealTimeUrlLookupServiceBase::SendRequest(
access_token_string.has_value());
SendRequestInternal(std::move(resource_request), req_data, url,
- std::move(response_callback));
+ access_token_string, std::move(response_callback));
GetTaskRunner(ThreadID::IO)
->PostTask(FROM_HERE,
@@ -376,6 +374,7 @@ void RealTimeUrlLookupServiceBase::SendRequestInternal(
std::unique_ptr<network::ResourceRequest> resource_request,
const std::string& req_data,
const GURL& url,
+ absl::optional<std::string> access_token_string,
RTLookupResponseCallback response_callback) {
std::unique_ptr<network::SimpleURLLoader> owned_loader =
network::SimpleURLLoader::Create(std::move(resource_request),
@@ -389,13 +388,15 @@ void RealTimeUrlLookupServiceBase::SendRequestInternal(
owned_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
url_loader_factory_.get(),
base::BindOnce(&RealTimeUrlLookupServiceBase::OnURLLoaderComplete,
- GetWeakPtr(), url, loader, base::TimeTicks::Now()));
+ GetWeakPtr(), url, access_token_string, loader,
+ base::TimeTicks::Now()));
pending_requests_[owned_loader.release()] = std::move(response_callback);
}
void RealTimeUrlLookupServiceBase::OnURLLoaderComplete(
const GURL& url,
+ absl::optional<std::string> access_token_string,
network::SimpleURLLoader* url_loader,
base::TimeTicks request_start_time,
std::unique_ptr<std::string> response_body) {
@@ -416,6 +417,11 @@ void RealTimeUrlLookupServiceBase::OnURLLoaderComplete(
GetMetricSuffix(), net_error,
response_code);
+ if (response_code == net::HTTP_UNAUTHORIZED &&
+ access_token_string.has_value()) {
+ OnResponseUnauthorized(access_token_string.value());
+ }
+
auto response = std::make_unique<RTLookupResponse>();
bool is_rt_lookup_successful = (net_error == net::OK) &&
(response_code == net::HTTP_OK) &&
@@ -458,7 +464,7 @@ std::unique_ptr<RTLookupRequest> RealTimeUrlLookupServiceBase::FillRequestProto(
request->set_lookup_type(RTLookupRequest::NAVIGATION);
request->set_version(kRTLookupRequestVersion);
request->set_os_type(GetRTLookupRequestOSType());
- base::Optional<std::string> dm_token_string = GetDMTokenString();
+ absl::optional<std::string> dm_token_string = GetDMTokenString();
if (dm_token_string.has_value()) {
request->set_dm_token(dm_token_string.value());
}
@@ -477,6 +483,9 @@ std::unique_ptr<RTLookupRequest> RealTimeUrlLookupServiceBase::FillRequestProto(
return request;
}
+void RealTimeUrlLookupServiceBase::OnResponseUnauthorized(
+ const std::string& invalid_access_token) {}
+
void RealTimeUrlLookupServiceBase::Shutdown() {
for (auto& pending : pending_requests_) {
// Pending requests are not posted back to the IO thread during shutdown,
diff --git a/chromium/components/safe_browsing/core/realtime/url_lookup_service_base.h b/chromium/components/safe_browsing/core/realtime/url_lookup_service_base.h
index 2b1d9b26f1d..15958bad168 100644
--- a/chromium/components/safe_browsing/core/realtime/url_lookup_service_base.h
+++ b/chromium/components/safe_browsing/core/realtime/url_lookup_service_base.h
@@ -11,13 +11,13 @@
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/core/proto/csd.pb.h"
#include "components/safe_browsing/core/proto/realtimeapi.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace net {
@@ -107,7 +107,7 @@ class RealTimeUrlLookupServiceBase : public KeyedService {
// Called to send the request to the Safe Browsing backend over the network.
// It also attached an auth header if |access_token_string| has a value.
void SendRequest(const GURL& url,
- base::Optional<std::string> access_token_string,
+ absl::optional<std::string> access_token_string,
RTLookupRequestCallback request_callback,
RTLookupResponseCallback response_callback);
@@ -140,8 +140,12 @@ class RealTimeUrlLookupServiceBase : public KeyedService {
RTLookupRequestCallback request_callback,
RTLookupResponseCallback response_callback) = 0;
+ // Called when the response from the server is unauthorized, so child classes
+ // can add extra handling when this happens.
+ virtual void OnResponseUnauthorized(const std::string& invalid_access_token);
+
// Gets a dm token string to be set in a request proto.
- virtual base::Optional<std::string> GetDMTokenString() const = 0;
+ virtual absl::optional<std::string> GetDMTokenString() const = 0;
// Suffix for logging metrics.
virtual std::string GetMetricSuffix() const = 0;
@@ -182,14 +186,17 @@ class RealTimeUrlLookupServiceBase : public KeyedService {
std::unique_ptr<network::ResourceRequest> resource_request,
const std::string& req_data,
const GURL& url,
+ absl::optional<std::string> access_token_string,
RTLookupResponseCallback response_callback);
// Called when the response from the real-time lookup remote endpoint is
// received. |url_loader| is the unowned loader that was used to send the
// request. |request_start_time| is the time when the request was sent.
// |response_body| is the response received. |url| is used for calling
- // |MayBeCacheRealTimeUrlVerdict|.
+ // |MayBeCacheRealTimeUrlVerdict|. |access_token_string| is used for calling
+ // |OnResponseUnauthorized| in case the response code is HTTP_UNAUTHORIZED.
void OnURLLoaderComplete(const GURL& url,
+ absl::optional<std::string> access_token_string,
network::SimpleURLLoader* url_loader,
base::TimeTicks request_start_time,
std::unique_ptr<std::string> response_body);
diff --git a/chromium/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc b/chromium/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc
index 4f380c195a1..dc237d944a3 100644
--- a/chromium/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc
+++ b/chromium/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc
@@ -21,6 +21,7 @@
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/unified_consent/pref_names.h"
#include "components/unified_consent/unified_consent_service.h"
+#include "net/http/http_status_code.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"
@@ -54,6 +55,8 @@ class TestSafeBrowsingTokenFetcher : public SafeBrowsingTokenFetcher {
std::move(callback_).Run(token);
}
+ MOCK_METHOD1(OnInvalidAccessToken, void(const std::string&));
+
private:
Callback callback_;
};
@@ -188,6 +191,10 @@ class RealTimeUrlLookupServiceTest : public PlatformTest {
expected_response_str);
}
+ void SetUpFailureResponse(net::HttpStatusCode status) {
+ test_url_loader_factory_.AddResponse(kRealTimeLookupUrlPrefix, "", status);
+ }
+
RealTimeUrlLookupService* rt_service() { return rt_service_.get(); }
void EnableMbb() {
@@ -222,6 +229,10 @@ class RealTimeUrlLookupServiceTest : public PlatformTest {
raw_token_fetcher_->RunAccessTokenCallback(token);
}
+ TestSafeBrowsingTokenFetcher* raw_token_fetcher() {
+ return raw_token_fetcher_;
+ }
+
bool AreTokenFetchesConfiguredInClient(
bool user_has_enabled_extended_protection) {
return token_fetches_configured_in_client_;
@@ -682,6 +693,7 @@ TEST_F(RealTimeUrlLookupServiceTest,
/* is_cached_response */ false, _));
FulfillAccessTokenRequest("access_token_string");
+ EXPECT_CALL(*raw_token_fetcher(), OnInvalidAccessToken(_)).Times(0);
task_environment_->RunUntilIdle();
// Check the response is cached.
@@ -758,6 +770,51 @@ TEST_F(RealTimeUrlLookupServiceTest,
EXPECT_NE(nullptr, cache_response);
}
+TEST_F(RealTimeUrlLookupServiceTest,
+ TestStartLookup_OnInvalidAccessTokenCalledResponseCodeUnauthorized) {
+ EnableRealTimeUrlLookup(
+ {kRealTimeUrlLookupEnabled, kRealTimeUrlLookupEnabledWithToken}, {});
+ EnableTokenFetchesInClient();
+ GURL url(kTestUrl);
+ SetUpFailureResponse(net::HTTP_UNAUTHORIZED);
+
+ base::MockCallback<RTLookupRequestCallback> request_callback;
+ base::MockCallback<RTLookupResponseCallback> response_callback;
+ rt_service()->StartLookup(url, request_callback.Get(),
+ response_callback.Get());
+
+ EXPECT_CALL(request_callback, Run(_, _)).Times(1);
+ EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false,
+ /* is_cached_response */ false, _));
+
+ FulfillAccessTokenRequest("invalid_token_string");
+ EXPECT_CALL(*raw_token_fetcher(),
+ OnInvalidAccessToken("invalid_token_string"))
+ .Times(1);
+ task_environment_->RunUntilIdle();
+}
+
+TEST_F(RealTimeUrlLookupServiceTest,
+ TestStartLookup_OnInvalidAccessTokenNotCalledResponseCodeForbidden) {
+ EnableRealTimeUrlLookup(
+ {kRealTimeUrlLookupEnabled, kRealTimeUrlLookupEnabledWithToken}, {});
+ EnableTokenFetchesInClient();
+ GURL url(kTestUrl);
+ SetUpFailureResponse(net::HTTP_FORBIDDEN);
+
+ base::MockCallback<RTLookupRequestCallback> request_callback;
+ base::MockCallback<RTLookupResponseCallback> response_callback;
+ rt_service()->StartLookup(url, request_callback.Get(),
+ response_callback.Get());
+
+ EXPECT_CALL(response_callback, Run(/* is_rt_lookup_successful */ false,
+ /* is_cached_response */ false, _));
+
+ FulfillAccessTokenRequest("invalid_token_string");
+ EXPECT_CALL(*raw_token_fetcher(), OnInvalidAccessToken(_)).Times(0);
+ task_environment_->RunUntilIdle();
+}
+
TEST_F(RealTimeUrlLookupServiceTest, TestReferrerChain_ReferrerChainAttached) {
EnableRealTimeUrlLookup({kRealTimeUrlLookupReferrerChain}, {});
GURL url(kTestUrl);
diff --git a/chromium/components/safe_browsing/core/resources/BUILD.gn b/chromium/components/safe_browsing/core/resources/BUILD.gn
index c0b0acc2d5f..21d9cee887a 100644
--- a/chromium/components/safe_browsing/core/resources/BUILD.gn
+++ b/chromium/components/safe_browsing/core/resources/BUILD.gn
@@ -3,13 +3,11 @@
# found in the LICENSE file.
import("//build/config/chromeos/ui_mode.gni")
-import("//build/config/python.gni")
# TODO(nparker): reduce the duplication between these two, somehow.
# Generate the binary proto form of "file_types" from the ascii proto.
-# TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
-python2_action("make_file_types_protobuf") {
+action("make_file_types_protobuf") {
script = "gen_file_type_proto.py"
# The output goes in $target_gen_dir since that's where
@@ -67,8 +65,7 @@ python2_action("make_file_types_protobuf") {
# Generate the binary proto for ALL platforms. This is only run manually
# when pushing the files to GCS for the component-updater to pick up.
-# TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
-python2_action("make_all_file_types_protobuf") {
+action("make_all_file_types_protobuf") {
script = "gen_file_type_proto.py"
input_filename = "download_file_types.asciipb"
diff --git a/chromium/components/safe_browsing/core/resources/gen_file_type_proto.py b/chromium/components/safe_browsing/core/resources/gen_file_type_proto.py
index 3974ba3dbd9..c2b3daa44d8 100755
--- a/chromium/components/safe_browsing/core/resources/gen_file_type_proto.py
+++ b/chromium/components/safe_browsing/core/resources/gen_file_type_proto.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# 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.
@@ -10,6 +10,8 @@
each which contains only the values that platform needs.
"""
+from __future__ import absolute_import
+from __future__ import print_function
import os
import re
import sys
@@ -154,7 +156,7 @@ class DownloadFileTypeProtoGenerator(BinaryProtoGenerator):
FilterForPlatformAndWrite(pb, platform_enum, outfile)
else:
# Make a separate file for each platform
- for platform_type, platform_enum in PlatformTypes().iteritems():
+ for platform_type, platform_enum in PlatformTypes().items():
# e.g. .../all/77/chromeos/download_file_types.pb
outfile = os.path.join(opts.outdir,
str(pb.version_id),
@@ -179,12 +181,12 @@ class DownloadFileTypeProtoGenerator(BinaryProtoGenerator):
def VerifyArgs(self, opts):
if (not opts.all and opts.type not in PlatformTypes()):
- print "ERROR: Unknown platform type '%s'" % opts.type
+ print("ERROR: Unknown platform type '%s'" % opts.type)
self.opt_parser.print_help()
return False
if (bool(opts.all) == bool(opts.type)):
- print "ERROR: Need exactly one of --type or --all"
+ print("ERROR: Need exactly one of --type or --all")
self.opt_parser.print_help()
return False
return True
diff --git a/chromium/components/safe_browsing/core/verdict_cache_manager.cc b/chromium/components/safe_browsing/core/verdict_cache_manager.cc
index ac96a9efadc..da5260c3f61 100644
--- a/chromium/components/safe_browsing/core/verdict_cache_manager.cc
+++ b/chromium/components/safe_browsing/core/verdict_cache_manager.cc
@@ -8,14 +8,15 @@
#include "base/command_line.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/time/time.h"
#include "components/history/core/browser/history_service_observer.h"
+#include "components/safe_browsing/core/common/safebrowsing_constants.h"
#include "components/safe_browsing/core/common/thread_utils.h"
#include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
#include "components/safe_browsing/core/proto/csd.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace safe_browsing {
@@ -282,7 +283,7 @@ typename T::VerdictType GetMostMatchingCachedVerdictWithPathMatching(
base::DictionaryValue::From(content_settings->GetWebsiteSetting(
hostname, GURL(), contents_setting_type, nullptr));
- if (!cache_dictionary || cache_dictionary->empty())
+ if (!cache_dictionary || cache_dictionary->DictEmpty())
return T::VERDICT_TYPE_UNSPECIFIED;
base::Value* verdict_dictionary =
@@ -377,9 +378,9 @@ typename T::VerdictType GetMostMatchingCachedVerdictWithHostAndPathMatching(
VerdictCacheManager::VerdictCacheManager(
history::HistoryService* history_service,
scoped_refptr<HostContentSettingsMap> content_settings)
- : stored_verdict_count_password_on_focus_(base::nullopt),
- stored_verdict_count_password_entry_(base::nullopt),
- stored_verdict_count_real_time_url_check_(base::nullopt),
+ : stored_verdict_count_password_on_focus_(absl::nullopt),
+ stored_verdict_count_password_entry_(absl::nullopt),
+ stored_verdict_count_real_time_url_check_(absl::nullopt),
content_settings_(content_settings) {
if (history_service)
history_service_observation_.Observe(history_service);
@@ -387,7 +388,8 @@ VerdictCacheManager::VerdictCacheManager(
ScheduleNextCleanUpAfterInterval(
base::TimeDelta::FromSeconds(kCleanUpIntervalInitSecond));
}
- CacheArtificialVerdict();
+ CacheArtificialRealTimeUrlVerdict();
+ CacheArtificialPhishGuardVerdict();
}
void VerdictCacheManager::Shutdown() {
@@ -432,7 +434,7 @@ void VerdictCacheManager::CachePhishGuardVerdict(
// Increases stored verdict count if we haven't seen this cache expression
// before.
if (!verdict_dictionary->FindKey(GetCacheExpression(verdict))) {
- base::Optional<size_t>* stored_verdict_count =
+ absl::optional<size_t>* stored_verdict_count =
trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE
? &stored_verdict_count_password_on_focus_
: &stored_verdict_count_password_entry_;
@@ -471,7 +473,7 @@ size_t VerdictCacheManager::GetStoredPhishGuardVerdictCount(
DCHECK(content_settings_);
DCHECK(trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE ||
trigger_type == LoginReputationClientRequest::PASSWORD_REUSE_EVENT);
- base::Optional<size_t>* stored_verdict_count =
+ absl::optional<size_t>* stored_verdict_count =
trigger_type == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE
? &stored_verdict_count_password_on_focus_
: &stored_verdict_count_password_entry_;
@@ -815,7 +817,7 @@ size_t VerdictCacheManager::GetPhishGuardVerdictCountForURL(
std::unique_ptr<base::DictionaryValue> cache_dictionary =
base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
url, GURL(), ContentSettingsType::PASSWORD_PROTECTION, nullptr));
- if (!cache_dictionary || cache_dictionary->empty())
+ if (!cache_dictionary || cache_dictionary->DictEmpty())
return 0;
int verdict_cnt = 0;
@@ -841,14 +843,14 @@ size_t VerdictCacheManager::GetRealTimeUrlCheckVerdictCountForURL(
base::DictionaryValue::From(content_settings_->GetWebsiteSetting(
url, GURL(), ContentSettingsType::SAFE_BROWSING_URL_CHECK_DATA,
nullptr));
- if (!cache_dictionary || cache_dictionary->empty())
+ if (!cache_dictionary || cache_dictionary->DictEmpty())
return 0;
base::Value* verdict_dictionary =
cache_dictionary->FindKey(kRealTimeUrlCacheKey);
return verdict_dictionary ? verdict_dictionary->DictSize() : 0;
}
-void VerdictCacheManager::CacheArtificialVerdict() {
+void VerdictCacheManager::CacheArtificialRealTimeUrlVerdict() {
std::string phishing_url_string =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
kUnsafeUrlFlag);
@@ -877,6 +879,32 @@ void VerdictCacheManager::CacheArtificialVerdict() {
/*store_old_cache=*/false);
}
+void VerdictCacheManager::CacheArtificialPhishGuardVerdict() {
+ std::string phishing_url_string =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ kArtificialCachedPhishGuardVerdictFlag);
+ if (phishing_url_string.empty())
+ return;
+
+ GURL artificial_unsafe_url(phishing_url_string);
+ if (!artificial_unsafe_url.is_valid())
+ return;
+
+ has_artificial_unsafe_url_ = true;
+
+ ReusedPasswordAccountType reused_password_account_type;
+ reused_password_account_type.set_account_type(
+ ReusedPasswordAccountType::SAVED_PASSWORD);
+
+ LoginReputationClientResponse verdict;
+ verdict.set_verdict_type(LoginReputationClientResponse::PHISHING);
+ verdict.set_cache_expression(artificial_unsafe_url.GetContent());
+ verdict.set_cache_duration_sec(3000);
+ CachePhishGuardVerdict(LoginReputationClientRequest::PASSWORD_REUSE_EVENT,
+ reused_password_account_type, verdict,
+ base::Time::Now());
+}
+
void VerdictCacheManager::StopCleanUpTimerForTesting() {
if (cleanup_timer_.IsRunning()) {
cleanup_timer_.AbandonAndStop();
diff --git a/chromium/components/safe_browsing/core/verdict_cache_manager.h b/chromium/components/safe_browsing/core/verdict_cache_manager.h
index f1dc5e1dfb5..284e9a1db22 100644
--- a/chromium/components/safe_browsing/core/verdict_cache_manager.h
+++ b/chromium/components/safe_browsing/core/verdict_cache_manager.h
@@ -97,8 +97,8 @@ class VerdictCacheManager : public history::HistoryServiceObserver,
void HistoryServiceBeingDeleted(
history::HistoryService* history_service) override;
- // Returns true if an artificial unsafe URL has been provided using the
- // command-line flag "mark_as_real_time_phishing".
+ // Returns true if an artificial unsafe URL has been provided using
+ // command-line flags.
static bool has_artificial_unsafe_url();
void StopCleanUpTimerForTesting();
@@ -146,17 +146,21 @@ class VerdictCacheManager : public history::HistoryServiceObserver,
// This adds a cached verdict for a URL that has artificially been marked as
// unsafe using the command line flag "mark_as_real_time_phishing".
- void CacheArtificialVerdict();
+ void CacheArtificialRealTimeUrlVerdict();
+
+ // This adds a cached verdict for a URL that has artificially been marked as
+ // unsafe using the command line flag "mark_as_phish_guard_phishing".
+ void CacheArtificialPhishGuardVerdict();
// Number of verdict stored for this profile for password on focus pings.
- base::Optional<size_t> stored_verdict_count_password_on_focus_;
+ absl::optional<size_t> stored_verdict_count_password_on_focus_;
// Number of verdict stored for this profile for protected password entry
// pings.
- base::Optional<size_t> stored_verdict_count_password_entry_;
+ absl::optional<size_t> stored_verdict_count_password_entry_;
// Number of verdict stored for this profile for real time url check pings.
- base::Optional<size_t> stored_verdict_count_real_time_url_check_;
+ absl::optional<size_t> stored_verdict_count_real_time_url_check_;
base::ScopedObservation<history::HistoryService,
history::HistoryServiceObserver>
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 a48bf3904b0..36bd061c916 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
@@ -9,7 +9,6 @@
#include "base/callback.h"
#include "base/json/json_reader.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
@@ -22,6 +21,7 @@
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "url/url_constants.h"
namespace safe_search_api {
@@ -42,7 +42,7 @@ std::string BuildRequestData(const std::string& api_key, const GURL& url) {
// Parses a SafeSearch API |response| and stores the result in |is_porn|,
// returns true on success. Otherwise, returns false and doesn't set |is_porn|.
bool ParseResponse(const std::string& response, bool* is_porn) {
- base::Optional<base::Value> optional_value = base::JSONReader::Read(response);
+ absl::optional<base::Value> optional_value = base::JSONReader::Read(response);
const base::DictionaryValue* dict = nullptr;
if (!optional_value || !optional_value.value().GetAsDictionary(&dict)) {
DLOG(WARNING) << "ParseResponse failed to parse global dictionary";
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 729650fae44..cd698b5fa7a 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
@@ -35,8 +35,8 @@ std::string BuildResponse(bool is_porn) {
classification_dict->SetBoolean("pornography", is_porn);
auto classifications_list = std::make_unique<base::ListValue>();
classifications_list->Append(std::move(classification_dict));
- dict.SetWithoutPathExpansion("classifications",
- std::move(classifications_list));
+ dict.SetKey("classifications",
+ base::Value::FromUniquePtrValue(std::move(classifications_list)));
std::string result;
base::JSONWriter::Write(dict, &result);
return result;
diff --git a/chromium/components/safe_search_api/stub_url_checker.cc b/chromium/components/safe_search_api/stub_url_checker.cc
index b32462da682..bdd2cc28ae8 100644
--- a/chromium/components/safe_search_api/stub_url_checker.cc
+++ b/chromium/components/safe_search_api/stub_url_checker.cc
@@ -29,8 +29,8 @@ std::string BuildResponse(bool is_porn) {
classification_dict->SetBoolean("pornography", is_porn);
auto classifications_list = std::make_unique<base::ListValue>();
classifications_list->Append(std::move(classification_dict));
- dict.SetWithoutPathExpansion("classifications",
- std::move(classifications_list));
+ dict.SetKey("classifications",
+ base::Value::FromUniquePtrValue(std::move(classifications_list)));
std::string result;
base::JSONWriter::Write(dict, &result);
return result;
diff --git a/chromium/components/safe_search_api/url_checker.cc b/chromium/components/safe_search_api/url_checker.cc
index 19ebcafcdcd..28af58c26d1 100644
--- a/chromium/components/safe_search_api/url_checker.cc
+++ b/chromium/components/safe_search_api/url_checker.cc
@@ -17,7 +17,6 @@
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/google/core/common/google_util.h"
diff --git a/chromium/components/safety_check/BUILD.gn b/chromium/components/safety_check/BUILD.gn
index a52d855282a..0b9b03e49e7 100644
--- a/chromium/components/safety_check/BUILD.gn
+++ b/chromium/components/safety_check/BUILD.gn
@@ -12,8 +12,9 @@ source_set("safety_check") {
"url_constants.h",
]
+ public_deps = [ "//base" ]
+
deps = [
- "//base",
"//components/prefs",
"//components/safe_browsing/core/common:safe_browsing_prefs",
"//net",
diff --git a/chromium/components/safety_check/safety_check.cc b/chromium/components/safety_check/safety_check.cc
index e09f9d7e7d4..ea801a28d94 100644
--- a/chromium/components/safety_check/safety_check.cc
+++ b/chromium/components/safety_check/safety_check.cc
@@ -8,34 +8,23 @@
namespace safety_check {
-SafetyCheck::SafetyCheck(SafetyCheckHandlerInterface* handler)
- : handler_(handler) {
- DCHECK(handler_);
-}
-
-SafetyCheck::~SafetyCheck() = default;
-
-void SafetyCheck::CheckSafeBrowsing(PrefService* pref_service) {
+SafeBrowsingStatus CheckSafeBrowsing(PrefService* pref_service) {
const PrefService::Preference* enabled_pref =
pref_service->FindPreference(prefs::kSafeBrowsingEnabled);
bool is_sb_enabled = pref_service->GetBoolean(prefs::kSafeBrowsingEnabled);
bool is_sb_managed = enabled_pref->IsManaged();
- SafeBrowsingStatus status;
- if (is_sb_enabled && pref_service->GetBoolean(prefs::kSafeBrowsingEnhanced)) {
- status = SafeBrowsingStatus::kEnabledEnhanced;
- } else if (is_sb_enabled && is_sb_managed) {
- status = SafeBrowsingStatus::kEnabledStandard;
- } else if (is_sb_enabled && !is_sb_managed) {
- status = SafeBrowsingStatus::kEnabledStandardAvailableEnhanced;
- } else if (is_sb_managed) {
- status = SafeBrowsingStatus::kDisabledByAdmin;
- } else if (enabled_pref->IsExtensionControlled()) {
- status = SafeBrowsingStatus::kDisabledByExtension;
- } else {
- status = SafeBrowsingStatus::kDisabled;
- }
- handler_->OnSafeBrowsingCheckResult(status);
+ if (is_sb_enabled && pref_service->GetBoolean(prefs::kSafeBrowsingEnhanced))
+ return SafeBrowsingStatus::kEnabledEnhanced;
+ if (is_sb_enabled && is_sb_managed)
+ return SafeBrowsingStatus::kEnabledStandard;
+ if (is_sb_enabled && !is_sb_managed)
+ return SafeBrowsingStatus::kEnabledStandardAvailableEnhanced;
+ if (is_sb_managed)
+ return SafeBrowsingStatus::kDisabledByAdmin;
+ if (enabled_pref->IsExtensionControlled())
+ return SafeBrowsingStatus::kDisabledByExtension;
+ return SafeBrowsingStatus::kDisabled;
}
} // namespace safety_check
diff --git a/chromium/components/safety_check/safety_check.h b/chromium/components/safety_check/safety_check.h
index 3aab1c1962b..6dcf7b3a49f 100644
--- a/chromium/components/safety_check/safety_check.h
+++ b/chromium/components/safety_check/safety_check.h
@@ -9,85 +9,71 @@
#include "base/observer_list_types.h"
#include "components/prefs/pref_service.h"
-namespace safety_check {
-
-// Class for performing browser safety checks common to desktop, Android, and
-// iOS. Platform-specific checks, such as updates and extensions, are
+// Utilities for performing browser safety checks common to desktop, Android,
+// and iOS. Platform-specific checks, such as updates and extensions, are
// implemented in handlers.
-class SafetyCheck {
- public:
- // The following enums represent the state of each component (common among
- // desktop, Android, and iOS) of the safety check and should be kept in sync
- // with the JS frontend (safety_check_browser_proxy.js) and |SafetyCheck*|
- // metrics enums in enums.xml.
- // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.safety_check
- enum class PasswordsStatus {
- kChecking = 0,
- kSafe = 1,
- // Indicates that at least one compromised password exists. Weak passwords
- // may exist as well.
- kCompromisedExist = 2,
- kOffline = 3,
- kNoPasswords = 4,
- kSignedOut = 5,
- kQuotaLimit = 6,
- kError = 7,
- kFeatureUnavailable = 8,
- // Indicates that no compromised passwords exist, but at least one weak
- // password.
- kWeakPasswordsExist = 9,
- // New enum values must go above here.
- kMaxValue = kWeakPasswordsExist,
- };
-
- // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.safety_check
- enum class SafeBrowsingStatus {
- kChecking = 0,
- kEnabled = 1,
- kDisabled = 2,
- kDisabledByAdmin = 3,
- kDisabledByExtension = 4,
- kEnabledStandard = 5,
- kEnabledEnhanced = 6,
- kEnabledStandardAvailableEnhanced = 7,
- // New enum values must go above here.
- kMaxValue = kEnabledStandardAvailableEnhanced,
- };
-
- // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.safety_check
- enum class UpdateStatus {
- kChecking = 0,
- kUpdated = 1,
- kUpdating = 2,
- kRelaunch = 3,
- kDisabledByAdmin = 4,
- kFailedOffline = 5,
- kFailed = 6,
- // Non-Google branded browsers cannot check for updates using
- // VersionUpdater.
- kUnknown = 7,
- // Only used in Android where the user is directed to the Play Store.
- kOutdated = 8,
- // New enum values must go above here.
- kMaxValue = kOutdated,
- };
-
- class SafetyCheckHandlerInterface {
- public:
- virtual void OnSafeBrowsingCheckResult(SafeBrowsingStatus status) = 0;
- };
+namespace safety_check {
- explicit SafetyCheck(SafetyCheckHandlerInterface* handler);
- ~SafetyCheck();
+// The following enums represent the state of each component (common among
+// desktop, Android, and iOS) of the safety check and should be kept in sync
+// with the JS frontend (safety_check_browser_proxy.js) and |SafetyCheck*|
+// metrics enums in enums.xml.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.safety_check
+enum class PasswordsStatus {
+ kChecking = 0,
+ kSafe = 1,
+ // Indicates that at least one compromised password exists. Weak passwords
+ // may exist as well.
+ kCompromisedExist = 2,
+ kOffline = 3,
+ kNoPasswords = 4,
+ kSignedOut = 5,
+ kQuotaLimit = 6,
+ kError = 7,
+ kFeatureUnavailable = 8,
+ // Indicates that no compromised passwords exist, but at least one weak
+ // password.
+ kWeakPasswordsExist = 9,
+ // New enum values must go above here.
+ kMaxValue = kWeakPasswordsExist,
+};
- // Gets the status of Safe Browsing from the PrefService and invokes
- // OnSafeBrowsingCheckResult on each Observer with results.
- void CheckSafeBrowsing(PrefService* pref_service);
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.safety_check
+enum class SafeBrowsingStatus {
+ kChecking = 0,
+ kEnabled = 1,
+ kDisabled = 2,
+ kDisabledByAdmin = 3,
+ kDisabledByExtension = 4,
+ kEnabledStandard = 5,
+ kEnabledEnhanced = 6,
+ kEnabledStandardAvailableEnhanced = 7,
+ // New enum values must go above here.
+ kMaxValue = kEnabledStandardAvailableEnhanced,
+};
- private:
- SafetyCheckHandlerInterface* handler_;
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.safety_check
+enum class UpdateStatus {
+ kChecking = 0,
+ kUpdated = 1,
+ kUpdating = 2,
+ kRelaunch = 3,
+ kDisabledByAdmin = 4,
+ kFailedOffline = 5,
+ kFailed = 6,
+ // Non-Google branded browsers cannot check for updates using
+ // VersionUpdater.
+ kUnknown = 7,
+ // Only used in Android where the user is directed to the Play Store.
+ kOutdated = 8,
+ // New enum values must go above here.
+ kMaxValue = kOutdated,
};
+// Gets the status of Safe Browsing from the PrefService and invokes
+// OnSafeBrowsingCheckResult on each Observer with results.
+SafeBrowsingStatus CheckSafeBrowsing(PrefService* pref_service);
+
} // namespace safety_check
#endif // COMPONENTS_SAFETY_CHECK_SAFETY_CHECK_H_
diff --git a/chromium/components/scheduling_metrics/thread_metrics.h b/chromium/components/scheduling_metrics/thread_metrics.h
index c5d0609dbbf..57ce8c97c18 100644
--- a/chromium/components/scheduling_metrics/thread_metrics.h
+++ b/chromium/components/scheduling_metrics/thread_metrics.h
@@ -6,12 +6,11 @@
#define COMPONENTS_SCHEDULING_METRICS_THREAD_METRICS_H_
#include "base/component_export.h"
-#include "base/optional.h"
#include "base/task/sequence_manager/task_queue.h"
-#include "base/time/time.h"
#include "components/scheduling_metrics/task_duration_metric_reporter.h"
#include "components/scheduling_metrics/thread_type.h"
#include "components/scheduling_metrics/total_duration_metric_reporter.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace scheduling_metrics {
diff --git a/chromium/components/scheduling_metrics/total_duration_metric_reporter.cc b/chromium/components/scheduling_metrics/total_duration_metric_reporter.cc
index 061c4d78edc..40b66d6e099 100644
--- a/chromium/components/scheduling_metrics/total_duration_metric_reporter.cc
+++ b/chromium/components/scheduling_metrics/total_duration_metric_reporter.cc
@@ -39,7 +39,7 @@ void TotalDurationMetricReporter::RecordAdditionalDuration(
}
void TotalDurationMetricReporter::Reset() {
- reported_value_ = base::nullopt;
+ reported_value_ = absl::nullopt;
}
} // namespace scheduling_metrics
diff --git a/chromium/components/scheduling_metrics/total_duration_metric_reporter.h b/chromium/components/scheduling_metrics/total_duration_metric_reporter.h
index 5ea43ed61c5..3014a06e40d 100644
--- a/chromium/components/scheduling_metrics/total_duration_metric_reporter.h
+++ b/chromium/components/scheduling_metrics/total_duration_metric_reporter.h
@@ -7,8 +7,8 @@
#include "base/component_export.h"
#include "base/metrics/histogram.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace scheduling_metrics {
@@ -30,7 +30,7 @@ class COMPONENT_EXPORT(SCHEDULING_METRICS) TotalDurationMetricReporter {
void Reset();
private:
- base::Optional<base::TimeDelta> reported_value_;
+ absl::optional<base::TimeDelta> reported_value_;
base::HistogramBase* positive_histogram_;
base::HistogramBase* negative_histogram_;
diff --git a/chromium/components/schema_org/common/time.cc b/chromium/components/schema_org/common/time.cc
index c3db09f4dca..0be877a926e 100644
--- a/chromium/components/schema_org/common/time.cc
+++ b/chromium/components/schema_org/common/time.cc
@@ -8,16 +8,16 @@
namespace schema_org {
-base::Optional<base::TimeDelta> ParseISO8601Duration(const std::string& str) {
+absl::optional<base::TimeDelta> ParseISO8601Duration(const std::string& str) {
if (str.empty() || str[0] != 'P')
- return base::nullopt;
+ return absl::nullopt;
base::TimeDelta duration;
std::string time = "";
int time_index = str.find("T");
if (time_index == -1)
- return base::nullopt;
+ return absl::nullopt;
time = str.substr(time_index + 1);
std::stringstream t(time);
@@ -37,7 +37,7 @@ base::Optional<base::TimeDelta> ParseISO8601Duration(const std::string& str) {
duration = duration + base::TimeDelta::FromSeconds(amount);
break;
default:
- return base::nullopt;
+ return absl::nullopt;
}
}
diff --git a/chromium/components/schema_org/common/time.h b/chromium/components/schema_org/common/time.h
index 040038193d2..62ba4294806 100644
--- a/chromium/components/schema_org/common/time.h
+++ b/chromium/components/schema_org/common/time.h
@@ -8,8 +8,8 @@
#include <string>
#include "base/component_export.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace schema_org {
@@ -18,7 +18,7 @@ namespace schema_org {
// particularly because there is no standard conversion from date units, such as
// a month to a time interval.
COMPONENT_EXPORT(SCHEMA_ORG_COMMON)
-base::Optional<base::TimeDelta> ParseISO8601Duration(const std::string& str);
+absl::optional<base::TimeDelta> ParseISO8601Duration(const std::string& str);
} // namespace schema_org
diff --git a/chromium/components/search/OWNERS b/chromium/components/search/OWNERS
index 81d20ebfd3b..e8105bb5841 100644
--- a/chromium/components/search/OWNERS
+++ b/chromium/components/search/OWNERS
@@ -1,5 +1,4 @@
# Incoming team
-aee@chromium.org
mahmadi@chromium.org
tiborg@chromium.org
@@ -7,10 +6,10 @@ tiborg@chromium.org
gayane@chromium.org
kmilka@chromium.org
kristipark@chromium.org
-ramyan@chromium.org
# Former team
mathp@chromium.org
+ramyan@chromium.org
# Original implementors of most of the code, but not active in Chromium anymore:
# - jered@chromium.org
diff --git a/chromium/components/search/ntp_features.cc b/chromium/components/search/ntp_features.cc
index 4037ed95c5f..5d5db1c0d95 100644
--- a/chromium/components/search/ntp_features.cc
+++ b/chromium/components/search/ntp_features.cc
@@ -5,6 +5,7 @@
#include "components/search/ntp_features.h"
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -25,20 +26,11 @@ const base::Feature kCacheOneGoogleBar{"CacheOneGoogleBar",
const base::Feature kDismissPromos{"DismissNtpPromos",
base::FEATURE_DISABLED_BY_DEFAULT};
-// If enabled, the OneGooleBar is loaded in an iframe. Otherwise, it is inlined.
-const base::Feature kIframeOneGoogleBar{"IframeOneGoogleBar",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// If enabled, queries that are frequently repeated by the user (and are
// expected to be issued again) are shown as most visited tiles.
const base::Feature kNtpRepeatableQueries{"NtpRepeatableQueries",
base::FEATURE_DISABLED_BY_DEFAULT};
-// If enabled, the iframed OneGooleBar shows the overlays modally with a
-// backdrop.
-const base::Feature kOneGoogleBarModalOverlays{
- "OneGoogleBarModalOverlays", base::FEATURE_DISABLED_BY_DEFAULT};
-
// Depends on kRealbox being enabled. If enabled, the NTP "realbox" will be
// themed like the omnibox (same background/text/selected/hover colors).
const base::Feature kRealboxMatchOmniboxTheme{
@@ -117,9 +109,15 @@ const char kNtpModulesLoadTimeoutMillisecondsParam[] =
const char kNtpStatefulTasksModuleDataParam[] =
"NtpStatefulTasksModuleDataParam";
const char kNtpChromeCartModuleDataParam[] = "NtpChromeCartModuleDataParam";
-
const char kNtpChromeCartModuleAbandonedCartDiscountParam[] =
"NtpChromeCartModuleAbandonedCartDiscountParam";
+const char NtpChromeCartModuleAbandonedCartDiscountUseUtmParam[] =
+ "NtpChromeCartModuleAbandonedCartDiscountUseUtmParam";
+const char kNtpChromeCartModuleHeuristicsImprovementParam[] =
+ "NtpChromeCartModuleHeuristicsImprovementParam";
+const char kNtpDriveModuleDataParam[] = "NtpDriveModuleDataParam";
+const char kNtpDriveModuleManagedUsersOnlyParam[] =
+ "NtpDriveModuleManagedUsersOnlyParam";
base::Time GetLocalHistoryRepeatableQueriesAgeThreshold() {
const base::TimeDelta kLocalHistoryRepeatableQueriesAgeThreshold =
diff --git a/chromium/components/search/ntp_features.h b/chromium/components/search/ntp_features.h
index 823eb1645b4..7bd99fd5bfc 100644
--- a/chromium/components/search/ntp_features.h
+++ b/chromium/components/search/ntp_features.h
@@ -68,6 +68,15 @@ extern const char kNtpStatefulTasksModuleDataParam[];
extern const char kNtpChromeCartModuleDataParam[];
// Parameter for enabling the abandoned cart discount.
extern const char kNtpChromeCartModuleAbandonedCartDiscountParam[];
+// Parameter for enabling the abandoned cart discount with utm_source tag to
+// indicate the feature state.
+extern const char NtpChromeCartModuleAbandonedCartDiscountUseUtmParam[];
+// Parameter for enabling the cart heuristics improvement.
+extern const char kNtpChromeCartModuleHeuristicsImprovementParam[];
+// Parameter determining the type of Drive data to render.
+extern const char kNtpDriveModuleDataParam[];
+// Parameter for enabling the Drive module for managed users only.
+extern const char kNtpDriveModuleManagedUsersOnlyParam[];
// Returns the age threshold for local history repeatable queries.
base::Time GetLocalHistoryRepeatableQueriesAgeThreshold();
diff --git a/chromium/components/search/repeatable_queries/repeatable_queries_service_unittest.cc b/chromium/components/search/repeatable_queries/repeatable_queries_service_unittest.cc
index ca745dfe51c..034f29d372e 100644
--- a/chromium/components/search/repeatable_queries/repeatable_queries_service_unittest.cc
+++ b/chromium/components/search/repeatable_queries/repeatable_queries_service_unittest.cc
@@ -11,7 +11,6 @@
#include "base/callback_helpers.h"
#include "base/cancelable_callback.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
@@ -33,6 +32,7 @@
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
using base::Time;
using base::TimeDelta;
diff --git a/chromium/components/search_engines/android/DIR_METADATA b/chromium/components/search_engines/android/DIR_METADATA
deleted file mode 100644
index 4bbdcaebcc8..00000000000
--- a/chromium/components/search_engines/android/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "UI>Browser>Search"
-}
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 4174566f3e5..928c3bd78b7 100644
--- a/chromium/components/search_engines/android/template_url_service_android.h
+++ b/chromium/components/search_engines/android/template_url_service_android.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SEARCH_ENGINES_ANDROID_TEMPLATE_URL_SERVICE_ANDROID_H_
#define COMPONENTS_SEARCH_ENGINES_ANDROID_TEMPLATE_URL_SERVICE_ANDROID_H_
-#include <memory>
-
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
#include "components/search_engines/template_url_service.h"
diff --git a/chromium/components/search_engines/default_search_manager.cc b/chromium/components/search_engines/default_search_manager.cc
index 4f89b1ca1c7..ce9d8859626 100644
--- a/chromium/components/search_engines/default_search_manager.cc
+++ b/chromium/components/search_engines/default_search_manager.cc
@@ -289,7 +289,7 @@ void DefaultSearchManager::LoadDefaultSearchEngineFromPrefs() {
const base::DictionaryValue* url_dict =
pref_service_->GetDictionary(kDefaultSearchProviderDataPrefName);
- if (url_dict->empty())
+ if (url_dict->DictEmpty())
return;
if (default_search_controlled_by_policy_) {
diff --git a/chromium/components/search_engines/keyword_table.cc b/chromium/components/search_engines/keyword_table.cc
index 38c308588a0..097582a2331 100644
--- a/chromium/components/search_engines/keyword_table.cc
+++ b/chromium/components/search_engines/keyword_table.cc
@@ -490,7 +490,7 @@ bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s,
data->sync_guid = s.ColumnString(14);
data->alternate_urls.clear();
- base::Optional<base::Value> value(base::JSONReader::Read(s.ColumnString(15)));
+ absl::optional<base::Value> value(base::JSONReader::Read(s.ColumnString(15)));
base::ListValue* alternate_urls_value;
if (value && value->GetAsList(&alternate_urls_value)) {
std::string alternate_url;
diff --git a/chromium/components/search_engines/template_url_data.cc b/chromium/components/search_engines/template_url_data.cc
index bd2c32c07e3..9e38747bf73 100644
--- a/chromium/components/search_engines/template_url_data.cc
+++ b/chromium/components/search_engines/template_url_data.cc
@@ -7,6 +7,7 @@
#include "base/check.h"
#include "base/guid.h"
#include "base/i18n/case_conversion.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"
@@ -89,8 +90,8 @@ TemplateURLData::TemplateURLData(const std::u16string& name,
sync_guid(GenerateGUID(prepopulate_id)) {
SetShortName(name);
SetKeyword(keyword);
- SetURL(search_url.as_string());
- input_encodings.push_back(encoding.as_string());
+ SetURL(std::string(search_url));
+ input_encodings.push_back(std::string(encoding));
for (size_t i = 0; i < alternate_urls_list.GetSize(); ++i) {
std::string alternate_url;
alternate_urls_list.GetString(i, &alternate_url);
diff --git a/chromium/components/search_engines/template_url_data_util.cc b/chromium/components/search_engines/template_url_data_util.cc
index c07cfa88a9c..1f4dd5d70cd 100644
--- a/chromium/components/search_engines/template_url_data_util.cc
+++ b/chromium/components/search_engines/template_url_data_util.cc
@@ -35,7 +35,7 @@ std::unique_ptr<TemplateURLData> TemplateURLDataFromDictionary(
dict.GetString(DefaultSearchManager::kShortName, &short_name);
// Check required TemplateURLData fields first.
if (search_url.empty() || keyword.empty() || short_name.empty())
- return std::unique_ptr<TemplateURLData>();
+ return nullptr;
auto result = std::make_unique<TemplateURLData>();
result->SetKeyword(keyword);
@@ -101,7 +101,7 @@ std::unique_ptr<TemplateURLData> TemplateURLDataFromDictionary(
const base::ListValue* alternate_urls = nullptr;
if (dict.GetList(DefaultSearchManager::kAlternateURLs, &alternate_urls)) {
- for (const auto& it : *alternate_urls) {
+ for (const auto& it : alternate_urls->GetList()) {
std::string alternate_url;
if (it.GetAsString(&alternate_url))
result->alternate_urls.push_back(std::move(alternate_url));
@@ -110,7 +110,7 @@ std::unique_ptr<TemplateURLData> TemplateURLDataFromDictionary(
const base::ListValue* encodings = nullptr;
if (dict.GetList(DefaultSearchManager::kInputEncodings, &encodings)) {
- for (const auto& it : *encodings) {
+ for (const auto& it : encodings->GetList()) {
std::string encoding;
if (it.GetAsString(&encoding))
result->input_encodings.push_back(std::move(encoding));
@@ -252,5 +252,5 @@ std::unique_ptr<TemplateURLData> TemplateURLDataFromOverrideDictionary(
suggest_url_post_params, image_url_post_params, favicon_url, encoding,
*alternate_urls, id);
}
- return std::unique_ptr<TemplateURLData>();
+ return nullptr;
}
diff --git a/chromium/components/search_engines/template_url_fetcher.h b/chromium/components/search_engines/template_url_fetcher.h
index 2f22398baa0..2a230aa4fcd 100644
--- a/chromium/components/search_engines/template_url_fetcher.h
+++ b/chromium/components/search_engines/template_url_fetcher.h
@@ -9,7 +9,6 @@
#include <string>
#include <vector>
-#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "components/keyed_service/core/keyed_service.h"
diff --git a/chromium/components/search_engines/template_url_service.cc b/chromium/components/search_engines/template_url_service.cc
index 933b8104c63..93866e85c6f 100644
--- a/chromium/components/search_engines/template_url_service.cc
+++ b/chromium/components/search_engines/template_url_service.cc
@@ -561,10 +561,6 @@ void TemplateURLService::RemoveExtensionControlledTURL(
Remove(url);
}
-void TemplateURLService::RemoveAutoGeneratedSince(base::Time created_after) {
- RemoveAutoGeneratedBetween(created_after, base::Time());
-}
-
void TemplateURLService::RemoveAutoGeneratedBetween(base::Time created_after,
base::Time created_before) {
RemoveAutoGeneratedForUrlsBetween(base::NullCallback(), created_after,
@@ -1005,7 +1001,7 @@ syncer::SyncDataList TemplateURLService::GetAllSyncData(
return current_data;
}
-base::Optional<syncer::ModelError> TemplateURLService::ProcessSyncChanges(
+absl::optional<syncer::ModelError> TemplateURLService::ProcessSyncChanges(
const base::Location& from_here,
const syncer::SyncChangeList& change_list) {
if (!models_associated_) {
@@ -1126,7 +1122,7 @@ base::Optional<syncer::ModelError> TemplateURLService::ProcessSyncChanges(
return sync_processor_->ProcessSyncChanges(from_here, new_changes);
}
-base::Optional<syncer::ModelError> TemplateURLService::MergeDataAndStartSyncing(
+absl::optional<syncer::ModelError> TemplateURLService::MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
@@ -1235,7 +1231,7 @@ base::Optional<syncer::ModelError> TemplateURLService::MergeDataAndStartSyncing(
PruneSyncChanges(&sync_data_map, &new_changes);
LogDuplicatesHistogram(GetTemplateURLs());
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
if (!error.has_value()) {
// The ACTION_DELETEs from this set are processed. Empty it so we don't try
diff --git a/chromium/components/search_engines/template_url_service.h b/chromium/components/search_engines/template_url_service.h
index af8de9a8801..7c4a49d74ab 100644
--- a/chromium/components/search_engines/template_url_service.h
+++ b/chromium/components/search_engines/template_url_service.h
@@ -213,10 +213,6 @@ class TemplateURLService : public WebDataServiceConsumer,
void RemoveExtensionControlledTURL(const std::string& extension_id,
TemplateURL::Type type);
- // Removes all auto-generated keywords that were created on or after the
- // date passed in.
- void RemoveAutoGeneratedSince(base::Time created_after);
-
// Removes all auto-generated keywords that were created in the specified
// range.
void RemoveAutoGeneratedBetween(base::Time created_after,
@@ -380,13 +376,13 @@ class TemplateURLService : public WebDataServiceConsumer,
// Process new search engine changes from Sync, merging them into our local
// data. This may send notifications if local search engines are added,
// updated or removed.
- base::Optional<syncer::ModelError> ProcessSyncChanges(
+ absl::optional<syncer::ModelError> ProcessSyncChanges(
const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
// Merge initial search engine data from Sync and push any local changes up
// to Sync. This may send notifications if local search engines are added,
// updated or removed.
- base::Optional<syncer::ModelError> MergeDataAndStartSyncing(
+ absl::optional<syncer::ModelError> MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
@@ -690,7 +686,7 @@ class TemplateURLService : public WebDataServiceConsumer,
// ---------- Dependencies on other components ------------------------------
// Service used to store entries.
- scoped_refptr<KeywordWebDataService> web_data_service_ = nullptr;
+ scoped_refptr<KeywordWebDataService> web_data_service_;
std::unique_ptr<TemplateURLServiceClient> client_;
diff --git a/chromium/components/search_engines/template_url_unittest.cc b/chromium/components/search_engines/template_url_unittest.cc
index 79ec26ec152..2cbb292a5bf 100644
--- a/chromium/components/search_engines/template_url_unittest.cc
+++ b/chromium/components/search_engines/template_url_unittest.cc
@@ -522,14 +522,14 @@ TEST_F(TemplateURLTest, ReplaceArbitrarySearchTerms) {
const std::string url;
const std::string expected_result;
} test_data[] = {
- {"BIG5", u"\x60BD", "http://foo/?{searchTerms}{inputEncoding}",
+ {"BIG5", u"悽", "http://foo/?{searchTerms}{inputEncoding}",
"http://foo/?%B1~BIG5"},
{"UTF-8", u"blah", "http://foo/?{searchTerms}{inputEncoding}",
"http://foo/?blahUTF-8"},
- {"Shift_JIS", base::UTF8ToUTF16("\xe3\x81\x82"),
- "http://foo/{searchTerms}/bar", "http://foo/%82%A0/bar"},
- {"Shift_JIS", base::UTF8ToUTF16("\xe3\x81\x82 \xe3\x81\x84"),
- "http://foo/{searchTerms}/bar", "http://foo/%82%A0%20%82%A2/bar"},
+ {"Shift_JIS", u"ã‚", "http://foo/{searchTerms}/bar",
+ "http://foo/%82%A0/bar"},
+ {"Shift_JIS", u"ã‚ ã„", "http://foo/{searchTerms}/bar",
+ "http://foo/%82%A0%20%82%A2/bar"},
};
TemplateURLData data;
for (size_t i = 0; i < base::size(test_data); ++i) {
@@ -558,27 +558,27 @@ TEST_F(TemplateURLTest, ReplaceSearchTermsMultipleEncodings) {
} test_data[] = {
// First and third encodings are valid. First is used.
{{"windows-1251", "cp-866", "UTF-8"},
- base::UTF8ToUTF16("\xD1\x8F"),
+ u"Ñ",
"http://foo/?{searchTerms}{inputEncoding}",
"http://foo/?%FFwindows-1251"},
// Second and third encodings are valid, second is used.
{{"cp-866", "GB2312", "UTF-8"},
- base::UTF8ToUTF16("\xE7\x8B\x97"),
+ u"ç‹—",
"http://foo/?{searchTerms}{inputEncoding}",
"http://foo/?%B9%B7GB2312"},
// Second and third encodings are valid in another order, second is used.
{{"cp-866", "UTF-8", "GB2312"},
- base::UTF8ToUTF16("\xE7\x8B\x97"),
+ u"ç‹—",
"http://foo/?{searchTerms}{inputEncoding}",
"http://foo/?%E7%8B%97UTF-8"},
// Both encodings are invalid, fallback to UTF-8.
{{"cp-866", "windows-1251"},
- base::UTF8ToUTF16("\xE7\x8B\x97"),
+ u"ç‹—",
"http://foo/?{searchTerms}{inputEncoding}",
"http://foo/?%E7%8B%97UTF-8"},
// No encodings are given, fallback to UTF-8.
{{},
- base::UTF8ToUTF16("\xE7\x8B\x97"),
+ u"ç‹—",
"http://foo/?{searchTerms}{inputEncoding}",
"http://foo/?%E7%8B%97UTF-8"},
};
@@ -1854,9 +1854,7 @@ TEST_F(TemplateURLTest, GenerateKeyword) {
ASSERT_EQ(u"blah", TemplateURL::GenerateKeyword(GURL("http://blah/")));
// Don't generate the empty string.
ASSERT_EQ(u"www.", TemplateURL::GenerateKeyword(GURL("http://www.")));
- ASSERT_EQ(
- base::UTF8ToUTF16("\xd0\xb0\xd0\xb1\xd0\xb2"),
- TemplateURL::GenerateKeyword(GURL("http://xn--80acd")));
+ ASSERT_EQ(u"абв", TemplateURL::GenerateKeyword(GURL("http://xn--80acd")));
// Generated keywords must always be in lowercase, because TemplateURLs always
// converts keywords to lowercase in its constructor and TemplateURLService
diff --git a/chromium/components/search_provider_logos/google_logo_api.cc b/chromium/components/search_provider_logos/google_logo_api.cc
index f76353119e2..84b8a8f5aa8 100644
--- a/chromium/components/search_provider_logos/google_logo_api.cc
+++ b/chromium/components/search_provider_logos/google_logo_api.cc
@@ -169,7 +169,7 @@ std::unique_ptr<EncodedLogo> ParseDoodleLogoResponse(
return nullptr;
// If there is no logo today, the "ddljson" dictionary will be empty.
- if (ddljson->empty()) {
+ if (ddljson->DictEmpty()) {
*parsing_failed = false;
return nullptr;
}
diff --git a/chromium/components/search_provider_logos/logo_common.h b/chromium/components/search_provider_logos/logo_common.h
index 4cf25a7fae5..ca32db0b0c1 100644
--- a/chromium/components/search_provider_logos/logo_common.h
+++ b/chromium/components/search_provider_logos/logo_common.h
@@ -13,8 +13,8 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"
@@ -178,7 +178,7 @@ struct EncodedLogo {
};
using EncodedLogoCallback =
base::OnceCallback<void(LogoCallbackReason type,
- const base::Optional<EncodedLogo>& logo)>;
+ const absl::optional<EncodedLogo>& logo)>;
struct Logo {
Logo();
@@ -192,7 +192,7 @@ struct Logo {
LogoMetadata metadata;
};
using LogoCallback = base::OnceCallback<void(LogoCallbackReason type,
- const base::Optional<Logo>& logo)>;
+ const absl::optional<Logo>& logo)>;
struct LogoCallbacks {
EncodedLogoCallback on_cached_encoded_logo_available;
diff --git a/chromium/components/search_provider_logos/logo_service.h b/chromium/components/search_provider_logos/logo_service.h
index 6dd7396f356..72fc032f152 100644
--- a/chromium/components/search_provider_logos/logo_service.h
+++ b/chromium/components/search_provider_logos/logo_service.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_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_H_
-#define COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_H_
+#ifndef COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_SERVICE_H_
+#define COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_SERVICE_H_
#include "components/keyed_service/core/keyed_service.h"
#include "components/search_provider_logos/logo_common.h"
@@ -54,4 +54,4 @@ class LogoService : public KeyedService {
} // namespace search_provider_logos
-#endif // COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_H_
+#endif // COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_SERVICE_H_
diff --git a/chromium/components/search_provider_logos/logo_service_impl.cc b/chromium/components/search_provider_logos/logo_service_impl.cc
index e3e7edbba03..3ec9034bd13 100644
--- a/chromium/components/search_provider_logos/logo_service_impl.cc
+++ b/chromium/components/search_provider_logos/logo_service_impl.cc
@@ -85,7 +85,7 @@ class ImageDecodedHandlerWithTimeout {
void ObserverOnLogoAvailable(LogoObserver* observer,
bool from_cache,
LogoCallbackReason type,
- const base::Optional<Logo>& logo) {
+ const absl::optional<Logo>& logo) {
switch (type) {
case LogoCallbackReason::DISABLED:
case LogoCallbackReason::CANCELED:
@@ -108,19 +108,19 @@ void ObserverOnLogoAvailable(LogoObserver* observer,
void RunCallbacksWithDisabled(LogoCallbacks callbacks) {
if (callbacks.on_cached_encoded_logo_available) {
std::move(callbacks.on_cached_encoded_logo_available)
- .Run(LogoCallbackReason::DISABLED, base::nullopt);
+ .Run(LogoCallbackReason::DISABLED, absl::nullopt);
}
if (callbacks.on_cached_decoded_logo_available) {
std::move(callbacks.on_cached_decoded_logo_available)
- .Run(LogoCallbackReason::DISABLED, base::nullopt);
+ .Run(LogoCallbackReason::DISABLED, absl::nullopt);
}
if (callbacks.on_fresh_encoded_logo_available) {
std::move(callbacks.on_fresh_encoded_logo_available)
- .Run(LogoCallbackReason::DISABLED, base::nullopt);
+ .Run(LogoCallbackReason::DISABLED, absl::nullopt);
}
if (callbacks.on_fresh_decoded_logo_available) {
std::move(callbacks.on_fresh_decoded_logo_available)
- .Run(LogoCallbackReason::DISABLED, base::nullopt);
+ .Run(LogoCallbackReason::DISABLED, absl::nullopt);
}
}
@@ -161,14 +161,14 @@ void NotifyAndClear(std::vector<EncodedLogoCallback>* encoded_callbacks,
const EncodedLogo* encoded_logo,
const Logo* decoded_logo) {
auto opt_encoded_logo =
- encoded_logo ? base::Optional<EncodedLogo>(*encoded_logo) : base::nullopt;
+ encoded_logo ? absl::optional<EncodedLogo>(*encoded_logo) : absl::nullopt;
for (EncodedLogoCallback& callback : *encoded_callbacks) {
std::move(callback).Run(type, opt_encoded_logo);
}
encoded_callbacks->clear();
auto opt_decoded_logo =
- decoded_logo ? base::Optional<Logo>(*decoded_logo) : base::nullopt;
+ decoded_logo ? absl::optional<Logo>(*decoded_logo) : absl::nullopt;
for (LogoCallback& callback : *decoded_callbacks) {
std::move(callback).Run(type, opt_decoded_logo);
}
diff --git a/chromium/components/search_provider_logos/logo_service_impl.h b/chromium/components/search_provider_logos/logo_service_impl.h
index 9555920ac2b..bc6e053d7df 100644
--- a/chromium/components/search_provider_logos/logo_service_impl.h
+++ b/chromium/components/search_provider_logos/logo_service_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_IMPL_H_
-#define COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_IMPL_H_
+#ifndef COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_SERVICE_IMPL_H_
+#define COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_SERVICE_IMPL_H_
#include <memory>
#include <string>
@@ -235,4 +235,4 @@ class LogoServiceImpl : public LogoService,
} // namespace search_provider_logos
-#endif // COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_IMPL_H_
+#endif // COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_SERVICE_IMPL_H_
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 fdcfce82722..06d6b044591 100644
--- a/chromium/components/search_provider_logos/logo_service_impl_unittest.cc
+++ b/chromium/components/search_provider_logos/logo_service_impl_unittest.cc
@@ -566,7 +566,7 @@ TEST_F(LogoServiceImplTest, DownloadAndCacheLogo) {
Logo logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
SetServerResponse(ServerResponse(logo));
logo_cache_->ExpectSetCachedLogo(&logo);
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -577,7 +577,7 @@ TEST_F(LogoServiceImplTest, DownloadAndCacheLogoWithoutDarkImage) {
Logo logo = GetSampleLogoWithoutDarkImage(DoodleURL(), test_clock_.Now());
SetServerResponse(ServerResponse(logo));
logo_cache_->ExpectSetCachedLogo(&logo);
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -589,7 +589,7 @@ TEST_F(LogoServiceImplTest, DownloadAndCacheEncodedLogo) {
EncodedLogo encoded_logo = EncodeLogo(logo);
SetServerResponse(ServerResponse(logo));
logo_cache_->ExpectSetCachedLogo(&logo);
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(encoded_logo)));
GetEncodedLogo(cached.Get(), fresh.Get());
}
@@ -601,7 +601,7 @@ TEST_F(LogoServiceImplTest, DownloadAndCacheEncodedLogoWithoutDarkImage) {
EncodedLogo encoded_logo = EncodeLogo(logo);
SetServerResponse(ServerResponse(logo));
logo_cache_->ExpectSetCachedLogo(&logo);
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(encoded_logo)));
GetEncodedLogo(cached.Get(), fresh.Get());
}
@@ -613,16 +613,16 @@ TEST_F(LogoServiceImplTest, ShouldReturnDisabledWhenDSEHasNoLogo) {
{
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
- EXPECT_CALL(cached, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DISABLED, Eq(absl::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::DISABLED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
{
StrictMock<MockEncodedLogoCallback> cached;
StrictMock<MockEncodedLogoCallback> fresh;
- EXPECT_CALL(cached, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::DISABLED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DISABLED, Eq(absl::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::DISABLED, Eq(absl::nullopt)));
GetEncodedLogo(cached.Get(), fresh.Get());
}
}
@@ -636,8 +636,8 @@ TEST_F(LogoServiceImplTest, EmptyCacheAndFailedDownload) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
SetServerResponse("server is borked");
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -645,8 +645,8 @@ TEST_F(LogoServiceImplTest, EmptyCacheAndFailedDownload) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
SetServerResponse("", net::ERR_FAILED, net::HTTP_OK);
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -654,8 +654,8 @@ TEST_F(LogoServiceImplTest, EmptyCacheAndFailedDownload) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
SetServerResponse("", net::OK, net::HTTP_BAD_GATEWAY);
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
}
@@ -676,7 +676,7 @@ TEST_F(LogoServiceImplTest, AcceptMinimalLogoResponse) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
GetDecodedLogo(cached.Get(), fresh.Get());
@@ -695,7 +695,7 @@ TEST_F(LogoServiceImplTest, ReturnCachedLogo) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -723,7 +723,7 @@ TEST_F(LogoServiceImplTest, ValidateCachedLogo) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -742,7 +742,7 @@ TEST_F(LogoServiceImplTest, ValidateCachedLogo) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
}
@@ -767,7 +767,7 @@ TEST_F(LogoServiceImplTest, UpdateCachedLogoMetadata) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -780,7 +780,7 @@ TEST_F(LogoServiceImplTest, UpdateCachedLogoMetadata) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(expected_logo)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(base::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::REVALIDATED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
}
@@ -819,7 +819,7 @@ TEST_F(LogoServiceImplTest, InvalidateCachedLogo) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -837,8 +837,8 @@ TEST_F(LogoServiceImplTest, DeleteCachedLogoFromOldUrl) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -850,7 +850,7 @@ TEST_F(LogoServiceImplTest, LogoWithTTLCannotBeShownAfterExpiration) {
SetServerResponse(ServerResponse(logo));
LogoCallbacks callbacks;
callbacks.on_fresh_decoded_logo_available = base::BindOnce(
- [](LogoCallbackReason type, const base::Optional<Logo>& logo) {});
+ [](LogoCallbackReason type, const absl::optional<Logo>& logo) {});
GetLogo(std::move(callbacks));
const LogoMetadata* cached_metadata = logo_cache_->GetCachedLogoMetadata();
@@ -865,7 +865,7 @@ TEST_F(LogoServiceImplTest, LogoWithoutTTLCanBeShownAfterExpiration) {
SetServerResponse(MakeServerResponse(logo, time_to_live));
LogoCallbacks callbacks;
callbacks.on_fresh_decoded_logo_available = base::BindOnce(
- [](LogoCallbackReason type, const base::Optional<Logo>& logo) {});
+ [](LogoCallbackReason type, const absl::optional<Logo>& logo) {});
GetLogo(std::move(callbacks));
const LogoMetadata* cached_metadata = logo_cache_->GetCachedLogoMetadata();
@@ -890,7 +890,7 @@ TEST_F(LogoServiceImplTest, UseSoftExpiredCachedLogo) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(cached_logo)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -932,8 +932,8 @@ TEST_F(LogoServiceImplTest, DeleteAncientCachedLogo) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -953,8 +953,8 @@ TEST_F(LogoServiceImplTest, DeleteExpiredCachedLogo) {
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
- EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
+ EXPECT_CALL(fresh, Run(LogoCallbackReason::FAILED, Eq(absl::nullopt)));
GetDecodedLogo(cached.Get(), fresh.Get());
}
@@ -971,7 +971,7 @@ TEST_F(LogoServiceImplTest, ClearLogoOnSignOut) {
logo_cache_->ExpectSetCachedLogo(&logo);
StrictMock<MockLogoCallback> cached;
StrictMock<MockLogoCallback> fresh;
- EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+ EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
EXPECT_CALL(fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
GetDecodedLogo(cached.Get(), fresh.Get());
@@ -1039,9 +1039,9 @@ TEST_F(LogoServiceImplTest, DeleteCallbacksWhenLogoURLChanged) {
StrictMock<MockLogoCallback> first_cached;
StrictMock<MockLogoCallback> first_fresh;
EXPECT_CALL(first_cached,
- Run(LogoCallbackReason::CANCELED, Eq(base::nullopt)));
+ Run(LogoCallbackReason::CANCELED, Eq(absl::nullopt)));
EXPECT_CALL(first_fresh,
- Run(LogoCallbackReason::CANCELED, Eq(base::nullopt)));
+ Run(LogoCallbackReason::CANCELED, Eq(absl::nullopt)));
LogoCallbacks first_callbacks;
first_callbacks.on_cached_decoded_logo_available = first_cached.Get();
first_callbacks.on_fresh_decoded_logo_available = first_fresh.Get();
@@ -1058,7 +1058,7 @@ TEST_F(LogoServiceImplTest, DeleteCallbacksWhenLogoURLChanged) {
StrictMock<MockLogoCallback> second_cached;
StrictMock<MockLogoCallback> second_fresh;
EXPECT_CALL(second_cached,
- Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
+ Run(LogoCallbackReason::DETERMINED, Eq(absl::nullopt)));
EXPECT_CALL(second_fresh, Run(LogoCallbackReason::DETERMINED, Eq(logo)));
LogoCallbacks second_callbacks;
second_callbacks.on_cached_decoded_logo_available = second_cached.Get();
diff --git a/chromium/components/security_interstitials/content/captive_portal_metrics_recorder.h b/chromium/components/security_interstitials/content/captive_portal_metrics_recorder.h
index 1b4ee913b4b..06e38b9fa5d 100644
--- a/chromium/components/security_interstitials/content/captive_portal_metrics_recorder.h
+++ b/chromium/components/security_interstitials/content/captive_portal_metrics_recorder.h
@@ -8,7 +8,6 @@
#include <string>
#include <vector>
-#include "base/time/time.h"
#include "components/captive_portal/content/captive_portal_service.h"
#include "net/cert/x509_certificate.h"
#include "url/gurl.h"
diff --git a/chromium/components/security_interstitials/content/cert_report_helper.cc b/chromium/components/security_interstitials/content/cert_report_helper.cc
index 448759d7a69..798e94ef953 100644
--- a/chromium/components/security_interstitials/content/cert_report_helper.cc
+++ b/chromium/components/security_interstitials/content/cert_report_helper.cc
@@ -10,7 +10,6 @@
#include "base/metrics/field_trial.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
diff --git a/chromium/components/security_interstitials/content/cert_report_helper.h b/chromium/components/security_interstitials/content/cert_report_helper.h
index 41a72e96a71..64527b7d607 100644
--- a/chromium/components/security_interstitials/content/cert_report_helper.h
+++ b/chromium/components/security_interstitials/content/cert_report_helper.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_CERT_REPORT_HELPER_H_
#define COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_CERT_REPORT_HELPER_H_
-#include <string>
-
#include "base/macros.h"
#include "components/security_interstitials/content/certificate_error_report.h"
#include "components/security_interstitials/core/controller_client.h"
diff --git a/chromium/components/security_interstitials/content/common_name_mismatch_handler.h b/chromium/components/security_interstitials/content/common_name_mismatch_handler.h
index 8ab131695e7..938cc73447d 100644
--- a/chromium/components/security_interstitials/content/common_name_mismatch_handler.h
+++ b/chromium/components/security_interstitials/content/common_name_mismatch_handler.h
@@ -14,7 +14,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
-#include "base/time/time.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
#include "url/gurl.h"
diff --git a/chromium/components/security_interstitials/content/content_metrics_helper.h b/chromium/components/security_interstitials/content/content_metrics_helper.h
index e073b96a467..e6e2352afc4 100644
--- a/chromium/components/security_interstitials/content/content_metrics_helper.h
+++ b/chromium/components/security_interstitials/content/content_metrics_helper.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_CONTENT_METRICS_HELPER_H_
#define COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_CONTENT_METRICS_HELPER_H_
-#include <string>
-
#include "base/macros.h"
#include "components/captive_portal/core/buildflags.h"
#include "components/security_interstitials/core/metrics_helper.h"
diff --git a/chromium/components/security_interstitials/content/origin_policy_ui.cc b/chromium/components/security_interstitials/content/origin_policy_ui.cc
index b537dd92974..a2fe6540f1c 100644
--- a/chromium/components/security_interstitials/content/origin_policy_ui.cc
+++ b/chromium/components/security_interstitials/content/origin_policy_ui.cc
@@ -8,13 +8,13 @@
#include <utility>
#include "base/check.h"
-#include "base/optional.h"
#include "components/security_interstitials/content/origin_policy_interstitial_page.h"
#include "components/security_interstitials/content/security_interstitial_tab_helper.h"
#include "components/security_interstitials/content/settings_page_helper.h"
#include "components/security_interstitials/core/metrics_helper.h"
#include "content/public/browser/navigation_handle.h"
#include "services/network/public/cpp/origin_policy.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace security_interstitials {
@@ -39,7 +39,7 @@ std::unique_ptr<SecurityInterstitialPage> GetErrorPageImpl(
} // namespace
-base::Optional<std::string> OriginPolicyUI::GetErrorPageAsHTML(
+absl::optional<std::string> OriginPolicyUI::GetErrorPageAsHTML(
network::OriginPolicyState error_reason,
content::NavigationHandle* handle) {
DCHECK(handle);
diff --git a/chromium/components/security_interstitials/content/origin_policy_ui.h b/chromium/components/security_interstitials/content/origin_policy_ui.h
index b3c26bee08d..e469bf535d8 100644
--- a/chromium/components/security_interstitials/content/origin_policy_ui.h
+++ b/chromium/components/security_interstitials/content/origin_policy_ui.h
@@ -10,7 +10,7 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -31,7 +31,7 @@ class OriginPolicyUI {
public:
// Create the error page for the given NavigationHandle.
// This is intended to implement the ContentBrowserClient interface.
- static base::Optional<std::string> GetErrorPageAsHTML(
+ static absl::optional<std::string> GetErrorPageAsHTML(
network::OriginPolicyState error_reason,
content::NavigationHandle* handle);
diff --git a/chromium/components/security_interstitials/content/renderer/security_interstitial_page_controller.cc b/chromium/components/security_interstitials/content/renderer/security_interstitial_page_controller.cc
index 75231ac2378..87821087147 100644
--- a/chromium/components/security_interstitials/content/renderer/security_interstitial_page_controller.cc
+++ b/chromium/components/security_interstitials/content/renderer/security_interstitial_page_controller.cc
@@ -4,6 +4,7 @@
#include "components/security_interstitials/content/renderer/security_interstitial_page_controller.h"
+#include "components/security_interstitials/core/common/mojom/interstitial_commands.mojom.h"
#include "components/security_interstitials/core/controller_client.h"
#include "content/public/renderer/render_frame.h"
#include "gin/converter.h"
@@ -22,6 +23,8 @@ void SecurityInterstitialPageController::Install(
content::RenderFrame* render_frame) {
v8::Isolate* isolate = blink::MainThreadIsolate();
v8::HandleScope handle_scope(isolate);
+ v8::MicrotasksScope microtasks_scope(
+ isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
v8::Local<v8::Context> context =
render_frame->GetWebFrame()->MainWorldScriptContext();
if (context.IsEmpty())
diff --git a/chromium/components/security_interstitials/content/renderer/security_interstitial_page_controller.h b/chromium/components/security_interstitials/content/renderer/security_interstitial_page_controller.h
index 0c31a9af935..e9bae064b06 100644
--- a/chromium/components/security_interstitials/content/renderer/security_interstitial_page_controller.h
+++ b/chromium/components/security_interstitials/content/renderer/security_interstitial_page_controller.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_RENDERER_SECURITY_INTERSTITIAL_PAGE_CONTROLLER_H_
#include "base/memory/weak_ptr.h"
-#include "components/security_interstitials/core/common/mojom/interstitial_commands.mojom.h"
#include "components/security_interstitials/core/controller_client.h"
#include "content/public/renderer/render_frame_observer.h"
#include "gin/wrappable.h"
diff --git a/chromium/components/security_interstitials/content/ssl_blocking_page_base.h b/chromium/components/security_interstitials/content/ssl_blocking_page_base.h
index 50be7b6322d..c9a8a14ec28 100644
--- a/chromium/components/security_interstitials/content/ssl_blocking_page_base.h
+++ b/chromium/components/security_interstitials/content/ssl_blocking_page_base.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_SSL_BLOCKING_PAGE_BASE_H_
#define COMPONENTS_SECURITY_INTERSTITIALS_CONTENT_SSL_BLOCKING_PAGE_BASE_H_
-#include "base/callback_forward.h"
#include "components/security_interstitials/content/cert_report_helper.h"
#include "components/security_interstitials/content/certificate_error_report.h"
#include "components/security_interstitials/content/security_interstitial_page.h"
diff --git a/chromium/components/security_interstitials/content/ssl_error_assistant.cc b/chromium/components/security_interstitials/content/ssl_error_assistant.cc
index 73f280819a7..0ae656e05c1 100644
--- a/chromium/components/security_interstitials/content/ssl_error_assistant.cc
+++ b/chromium/components/security_interstitials/content/ssl_error_assistant.cc
@@ -203,7 +203,7 @@ bool SSLErrorAssistant::IsKnownCaptivePortalCertificate(
return MatchSSLInfoWithHashes(ssl_info, *(captive_portal_spki_hashes_.get()));
}
-base::Optional<DynamicInterstitialInfo>
+absl::optional<DynamicInterstitialInfo>
SSLErrorAssistant::MatchDynamicInterstitial(const net::SSLInfo& ssl_info,
bool is_overridable) {
// Load the dynamic interstitial data from SSL error assistant proto if it's
@@ -248,7 +248,7 @@ SSLErrorAssistant::MatchDynamicInterstitial(const net::SSLInfo& ssl_info,
return data;
}
- return base::nullopt;
+ return absl::nullopt;
}
const std::string SSLErrorAssistant::MatchKnownMITMSoftware(
diff --git a/chromium/components/security_interstitials/content/ssl_error_assistant.h b/chromium/components/security_interstitials/content/ssl_error_assistant.h
index 7ccd8bb42ae..4e80c67fc12 100644
--- a/chromium/components/security_interstitials/content/ssl_error_assistant.h
+++ b/chromium/components/security_interstitials/content/ssl_error_assistant.h
@@ -9,9 +9,9 @@
#include <unordered_set>
#include <vector>
-#include "base/optional.h"
#include "components/security_interstitials/content/ssl_error_assistant.pb.h"
#include "net/ssl/ssl_info.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace net {
@@ -81,7 +81,7 @@ class SSLErrorAssistant {
// Returns a DynamicInterstitialInfo from |dynamic_interstitial_list_| that
// matches with |ssl_info|. If there is no match, returns null. Loads
// |dynamic_interstitial_list_| on the first use.
- base::Optional<DynamicInterstitialInfo> MatchDynamicInterstitial(
+ absl::optional<DynamicInterstitialInfo> MatchDynamicInterstitial(
const net::SSLInfo& ssl_info,
bool is_overridable = false);
diff --git a/chromium/components/security_interstitials/content/ssl_error_assistant_unittest.cc b/chromium/components/security_interstitials/content/ssl_error_assistant_unittest.cc
index 028ce008a30..fc08538f4de 100644
--- a/chromium/components/security_interstitials/content/ssl_error_assistant_unittest.cc
+++ b/chromium/components/security_interstitials/content/ssl_error_assistant_unittest.cc
@@ -252,7 +252,7 @@ TEST_F(SSLErrorAssistantTest, DynamicInterstitialListMatch) {
error_assistant()->SetErrorAssistantProto(std::move(config_proto));
- base::Optional<DynamicInterstitialInfo> dynamic_interstitial =
+ absl::optional<DynamicInterstitialInfo> dynamic_interstitial =
error_assistant()->MatchDynamicInterstitial(ssl_info());
ASSERT_TRUE(dynamic_interstitial);
EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL,
@@ -298,7 +298,7 @@ TEST_F(SSLErrorAssistantTest, DynamicInterstitialListComplexRegexMatch) {
error_assistant()->SetErrorAssistantProto(std::move(config_proto));
- base::Optional<DynamicInterstitialInfo> dynamic_interstitial =
+ absl::optional<DynamicInterstitialInfo> dynamic_interstitial =
error_assistant()->MatchDynamicInterstitial(ssl_info());
ASSERT_TRUE(dynamic_interstitial);
EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL,
@@ -342,7 +342,7 @@ TEST_F(SSLErrorAssistantTest, DynamicInterstitialListMatchUnknownCertError) {
error_assistant()->SetErrorAssistantProto(std::move(config_proto));
- base::Optional<DynamicInterstitialInfo> dynamic_interstitial =
+ absl::optional<DynamicInterstitialInfo> dynamic_interstitial =
error_assistant()->MatchDynamicInterstitial(ssl_info());
EXPECT_TRUE(dynamic_interstitial);
EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL,
@@ -387,7 +387,7 @@ TEST_F(SSLErrorAssistantTest, DynamicInterstitialListNoCommonName) {
error_assistant()->SetErrorAssistantProto(std::move(config_proto));
- base::Optional<DynamicInterstitialInfo> dynamic_interstitial =
+ absl::optional<DynamicInterstitialInfo> dynamic_interstitial =
error_assistant()->MatchDynamicInterstitial(ssl_info());
ASSERT_TRUE(dynamic_interstitial);
EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL,
@@ -432,7 +432,7 @@ TEST_F(SSLErrorAssistantTest, DynamicInterstitialListNoOrganizationRegex) {
error_assistant()->SetErrorAssistantProto(std::move(config_proto));
- base::Optional<DynamicInterstitialInfo> dynamic_interstitial =
+ absl::optional<DynamicInterstitialInfo> dynamic_interstitial =
error_assistant()->MatchDynamicInterstitial(ssl_info());
ASSERT_TRUE(dynamic_interstitial);
EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL,
@@ -473,7 +473,7 @@ TEST_F(SSLErrorAssistantTest, DynamicInterstitialListNoCertHashes) {
error_assistant()->SetErrorAssistantProto(std::move(config_proto));
- base::Optional<DynamicInterstitialInfo> dynamic_interstitial =
+ absl::optional<DynamicInterstitialInfo> dynamic_interstitial =
error_assistant()->MatchDynamicInterstitial(ssl_info());
ASSERT_TRUE(dynamic_interstitial);
EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL,
@@ -498,7 +498,7 @@ TEST_F(SSLErrorAssistantTest, DynamicInterstitialListMatchBlank) {
error_assistant()->SetErrorAssistantProto(std::move(config_proto));
- base::Optional<DynamicInterstitialInfo> dynamic_interstitial =
+ absl::optional<DynamicInterstitialInfo> dynamic_interstitial =
error_assistant()->MatchDynamicInterstitial(ssl_info());
ASSERT_TRUE(dynamic_interstitial);
EXPECT_EQ(chrome_browser_ssl::DynamicInterstitial::INTERSTITIAL_PAGE_SSL,
diff --git a/chromium/components/security_interstitials/content/ssl_error_handler.cc b/chromium/components/security_interstitials/content/ssl_error_handler.cc
index 0529f7710c9..9d685abb4c1 100644
--- a/chromium/components/security_interstitials/content/ssl_error_handler.cc
+++ b/chromium/components/security_interstitials/content/ssl_error_handler.cc
@@ -186,7 +186,7 @@ class ConfigSingleton {
// Returns a DynamicInterstitialInfo that matches with |ssl_info|. If is no
// match, return null.
- base::Optional<DynamicInterstitialInfo> MatchDynamicInterstitial(
+ absl::optional<DynamicInterstitialInfo> MatchDynamicInterstitial(
const net::SSLInfo& ssl_info,
bool is_overridable);
@@ -331,7 +331,7 @@ const std::string ConfigSingleton::MatchKnownMITMSoftware(
return ssl_error_assistant_->MatchKnownMITMSoftware(cert);
}
-base::Optional<DynamicInterstitialInfo>
+absl::optional<DynamicInterstitialInfo>
ConfigSingleton::MatchDynamicInterstitial(const net::SSLInfo& ssl_info,
bool is_overridable) {
return ssl_error_assistant_->MatchDynamicInterstitial(ssl_info,
@@ -450,7 +450,7 @@ void SSLErrorHandlerDelegateImpl::CheckSuggestedUrl(
const GURL& suggested_url,
CommonNameMismatchHandler::CheckUrlCallback callback) {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory(
- content::BrowserContext::GetDefaultStoragePartition(browser_context_)
+ browser_context_->GetDefaultStoragePartition()
->GetURLLoaderFactoryForBrowserProcess());
common_name_mismatch_handler_ = std::make_unique<CommonNameMismatchHandler>(
request_url_, url_loader_factory);
@@ -698,7 +698,7 @@ void SSLErrorHandler::StartHandlingError() {
return;
}
- base::Optional<DynamicInterstitialInfo> dynamic_interstitial =
+ absl::optional<DynamicInterstitialInfo> dynamic_interstitial =
g_config.Pointer()->MatchDynamicInterstitial(
ssl_info_, delegate_->IsErrorOverridable());
if (dynamic_interstitial) {
diff --git a/chromium/components/security_interstitials/content/stateful_ssl_host_state_delegate.cc b/chromium/components/security_interstitials/content/stateful_ssl_host_state_delegate.cc
index fdcd012e670..895823b474a 100644
--- a/chromium/components/security_interstitials/content/stateful_ssl_host_state_delegate.cc
+++ b/chromium/components/security_interstitials/content/stateful_ssl_host_state_delegate.cc
@@ -218,12 +218,11 @@ void StatefulSSLHostStateDelegate::AllowCert(
content::WebContents* web_contents) {
DCHECK(web_contents);
content::StoragePartition* storage_partition =
- content::BrowserContext::GetStoragePartition(
- browser_context_, web_contents->GetMainFrame()->GetSiteInstance(),
+ browser_context_->GetStoragePartition(
+ web_contents->GetMainFrame()->GetSiteInstance(),
false /* can_create */);
if (!storage_partition ||
- storage_partition != content::BrowserContext::GetDefaultStoragePartition(
- browser_context_)) {
+ storage_partition != browser_context_->GetDefaultStoragePartition()) {
// Decisions for non-default storage partitions are stored in memory only;
// see comment on declaration of
// |allowed_certs_for_non_default_storage_partitions_|.
@@ -297,12 +296,11 @@ StatefulSSLHostStateDelegate::QueryPolicy(const std::string& host,
return ALLOWED;
content::StoragePartition* storage_partition =
- content::BrowserContext::GetStoragePartition(
- browser_context_, web_contents->GetMainFrame()->GetSiteInstance(),
+ browser_context_->GetStoragePartition(
+ web_contents->GetMainFrame()->GetSiteInstance(),
false /* can_create */);
if (!storage_partition ||
- storage_partition != content::BrowserContext::GetDefaultStoragePartition(
- browser_context_)) {
+ storage_partition != browser_context_->GetDefaultStoragePartition()) {
if (allowed_certs_for_non_default_storage_partitions_.find(host) ==
allowed_certs_for_non_default_storage_partitions_.end()) {
return DENIED;
@@ -397,12 +395,11 @@ bool StatefulSSLHostStateDelegate::HasAllowException(
DCHECK(web_contents);
content::StoragePartition* storage_partition =
- content::BrowserContext::GetStoragePartition(
- browser_context_, web_contents->GetMainFrame()->GetSiteInstance(),
+ browser_context_->GetStoragePartition(
+ web_contents->GetMainFrame()->GetSiteInstance(),
false /* can_create */);
if (!storage_partition ||
- storage_partition != content::BrowserContext::GetDefaultStoragePartition(
- browser_context_)) {
+ storage_partition != browser_context_->GetDefaultStoragePartition()) {
return allowed_certs_for_non_default_storage_partitions_.find(host) !=
allowed_certs_for_non_default_storage_partitions_.end();
}
@@ -423,9 +420,8 @@ bool StatefulSSLHostStateDelegate::HasAllowException(
DCHECK(success);
for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
- int policy_decision; // Owned by dict
- success = it.value().GetAsInteger(&policy_decision);
- if (success && (static_cast<CertJudgment>(policy_decision) == ALLOWED))
+ if (it.value().is_int() &&
+ (static_cast<CertJudgment>(it.value().GetInt()) == ALLOWED))
return true;
}
@@ -452,8 +448,7 @@ void StatefulSSLHostStateDelegate::RevokeUserAllowExceptionsHard(
const std::string& host) {
RevokeUserAllowExceptions(host);
auto* network_context =
- content::BrowserContext::GetDefaultStoragePartition(browser_context_)
- ->GetNetworkContext();
+ browser_context_->GetDefaultStoragePartition()->GetNetworkContext();
network_context->CloseIdleConnections(base::NullCallback());
}
diff --git a/chromium/components/security_interstitials/content/stateful_ssl_host_state_delegate.h b/chromium/components/security_interstitials/content/stateful_ssl_host_state_delegate.h
index 6c74da020d7..f83b6f08950 100644
--- a/chromium/components/security_interstitials/content/stateful_ssl_host_state_delegate.h
+++ b/chromium/components/security_interstitials/content/stateful_ssl_host_state_delegate.h
@@ -10,7 +10,6 @@
#include "base/feature_list.h"
#include "base/macros.h"
-#include "base/time/time.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/ssl_host_state_delegate.h"
@@ -20,6 +19,7 @@ class PrefService;
namespace base {
class Clock;
class DictionaryValue;
+class FilePath;
} // namespace base
namespace content {
diff --git a/chromium/components/security_interstitials/core/metrics_helper.h b/chromium/components/security_interstitials/core/metrics_helper.h
index 4663f592041..58a9ee7ec9d 100644
--- a/chromium/components/security_interstitials/core/metrics_helper.h
+++ b/chromium/components/security_interstitials/core/metrics_helper.h
@@ -10,7 +10,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/task/cancelable_task_tracker.h"
-#include "base/time/time.h"
#include "url/gurl.h"
namespace history {
diff --git a/chromium/components/security_interstitials/core/mitm_software_ui.h b/chromium/components/security_interstitials/core/mitm_software_ui.h
index 973327b12e3..21017f7dcf2 100644
--- a/chromium/components/security_interstitials/core/mitm_software_ui.h
+++ b/chromium/components/security_interstitials/core/mitm_software_ui.h
@@ -46,4 +46,4 @@ class MITMSoftwareUI {
} // namespace security_interstitials
-#endif // COMPONENTS_SECURITY_INTERSTITIALS_CORE_MITM_SOFTWARE_UI_H
+#endif // COMPONENTS_SECURITY_INTERSTITIALS_CORE_MITM_SOFTWARE_UI_H_
diff --git a/chromium/components/security_interstitials/core/pref_names.h b/chromium/components/security_interstitials/core/pref_names.h
index 1a134edc1eb..9537d059c50 100644
--- a/chromium/components/security_interstitials/core/pref_names.h
+++ b/chromium/components/security_interstitials/core/pref_names.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SECURITY_INTERSTITIALS_CORE_PREF_NAMES_H_
#define COMPONENTS_SECURITY_INTERSTITIALS_CORE_PREF_NAMES_H_
-#include <string>
-
namespace prefs {
// Stores counts and timestamps of SSL certificate errors that have occurred.
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 c6042a10327..471afe3c8a4 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
@@ -6,7 +6,6 @@
#include "base/i18n/time_formatting.h"
#include "base/metrics/histogram_macros.h"
-#include "base/strings/stringprintf.h"
#include "components/google/core/common/google_util.h"
#include "components/grit/components_resources.h"
#include "components/security_interstitials/core/common_string_util.h"
diff --git a/chromium/components/security_state/OWNERS b/chromium/components/security_state/OWNERS
index 6aff2ec7088..167dbd0d950 100644
--- a/chromium/components/security_state/OWNERS
+++ b/chromium/components/security_state/OWNERS
@@ -1,3 +1,2 @@
cthomp@chromium.org
estark@chromium.org
-felt@chromium.org
diff --git a/chromium/components/security_state/ios/insecure_input_tab_helper.h b/chromium/components/security_state/ios/insecure_input_tab_helper.h
index a93495dd17a..d15354621d0 100644
--- a/chromium/components/security_state/ios/insecure_input_tab_helper.h
+++ b/chromium/components/security_state/ios/insecure_input_tab_helper.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SECURITY_STATE_IOS_INSECURE_INPUT_TAB_HELPER_H_
#define COMPONENTS_SECURITY_STATE_IOS_INSECURE_INPUT_TAB_HELPER_H_
-#include <string>
-
#include "base/macros.h"
#include "components/autofill/ios/form_util/form_activity_observer.h"
#include "ios/web/public/web_state_observer.h"
diff --git a/chromium/components/segmentation_platform/BUILD.gn b/chromium/components/segmentation_platform/BUILD.gn
new file mode 100644
index 00000000000..5b4a2ca5130
--- /dev/null
+++ b/chromium/components/segmentation_platform/BUILD.gn
@@ -0,0 +1,22 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/buildflag_header.gni")
+
+group("unit_tests") {
+ testonly = true
+
+ deps = [
+ "//components/segmentation_platform/internal:unit_tests",
+ "//components/segmentation_platform/public:unit_tests",
+ ]
+
+ data_deps = [ ":components_unittests_gtest_filter" ]
+}
+
+source_set("components_unittests_gtest_filter") {
+ testonly = true
+
+ data = [ "components_unittests.filter" ]
+}
diff --git a/chromium/components/segmentation_platform/DEPS b/chromium/components/segmentation_platform/DEPS
new file mode 100644
index 00000000000..38d895bafdc
--- /dev/null
+++ b/chromium/components/segmentation_platform/DEPS
@@ -0,0 +1,10 @@
+include_rules = [
+ "+components/keyed_service",
+ "+components/leveldb_proto",
+ "+components/optimization_guide",
+ "-components/optimization_guide/content",
+ "+components/prefs",
+ "+third_party/perfetto",
+ "+third_party/tflite",
+ "+third_party/tflite-support",
+]
diff --git a/chromium/components/segmentation_platform/DIR_METADATA b/chromium/components/segmentation_platform/DIR_METADATA
new file mode 100644
index 00000000000..e90fa62943c
--- /dev/null
+++ b/chromium/components/segmentation_platform/DIR_METADATA
@@ -0,0 +1,5 @@
+monorail {
+ component: "Internals>SegmentationPlatform"
+}
+
+team_email: "chrome-segmentation-platform@google.com"
diff --git a/chromium/components/segmentation_platform/OWNERS b/chromium/components/segmentation_platform/OWNERS
new file mode 100644
index 00000000000..ec92ff59d23
--- /dev/null
+++ b/chromium/components/segmentation_platform/OWNERS
@@ -0,0 +1,2 @@
+nyquist@chromium.org
+shaktisahu@chromium.org \ No newline at end of file
diff --git a/chromium/components/segmentation_platform/README.md b/chromium/components/segmentation_platform/README.md
new file mode 100644
index 00000000000..08415064a13
--- /dev/null
+++ b/chromium/components/segmentation_platform/README.md
@@ -0,0 +1,40 @@
+# Segmentation Platform
+
+## Introduction
+The segmentation platform is a platform that uses intelligence and machine learning to guide developers for building purpose-built user experience for specific segments of users.
+
+
+Segmentation Platform is a layered component
+(https://sites.google.com/a/chromium.org/dev/developers/design-documents/layered-components-design)
+to enable it to be easily used on all platforms.
+
+## Code structure
+
+[components/segmentation_platform/public](.)
+Public interfaces and data structure.
+
+[components/segmentation_platform/internal](./internal)
+Internal implementations.
+
+[chrome/browser/segmentation_platform](../../chrome/browser/segmentation_platform)
+Includes factories to instantiate the service.
+
+`SegmentationPlatformService` - Public interface for segmentation platform service.
+
+## Test models
+
+[components/test/data/segmentation_platform](../test/data/segmentation_platform)
+contains ML models used for testing.
+
+* `adder.tflite`: Takes two floats as input in a single tensor. Outputs a
+ single tensor with a single element which is the sum of the two floats given
+ as input.
+
+## Testing
+
+To run all the relevant C++ unit tests, you can run the `components_unittests`
+target and give the `segmentation_platform` filter file as an argument:
+
+```
+./out/Default/components_unittests --test-launcher-filter-file=components/segmentation_platform/components_unittests.filter
+```
diff --git a/chromium/components/segmentation_platform/components_unittests.filter b/chromium/components/segmentation_platform/components_unittests.filter
new file mode 100644
index 00000000000..f003586f216
--- /dev/null
+++ b/chromium/components/segmentation_platform/components_unittests.filter
@@ -0,0 +1,22 @@
+DatabaseMaintenanceImplTest.*
+DummyModelExecutionManagerTest.*
+DummySegmentationPlatformServiceTest.*
+FeatureAggregatorImplTest.*
+HistogramSignalHandlerTest.*
+MetadataUtilsTest.*
+ModelExecutionManagerFactoryTest.*
+ModelExecutionManagerTest.*
+ModelExecutionSchedulerTest.*
+SegmentationModelExecutorTest.*
+SegmentationPlatformFeaturesTest.*
+SegmentationPlatformServiceImplTest.*
+SegmentationResultPrefsTest.*
+SegmentInfoDatabaseTest.*
+SegmentSelectorTest.*
+SignalDatabaseImplTest.*
+SignalFilterProcessorTest.*
+SignalKeyInternalTest.*
+SignalKeyTest.*
+SignalStorageConfigTest.*
+StatsTest.*
+UserActionSignalHandlerTest.*
diff --git a/chromium/components/segmentation_platform/internal/BUILD.gn b/chromium/components/segmentation_platform/internal/BUILD.gn
new file mode 100644
index 00000000000..e9798201e63
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/BUILD.gn
@@ -0,0 +1,189 @@
+# Copyright 2021 The Chromium 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/config.gni")
+ import("//build/config/android/rules.gni")
+}
+import("//components/optimization_guide/features.gni")
+
+static_library("internal") {
+ visibility = [
+ ":*",
+ "//chrome/browser",
+ ]
+
+ sources = [
+ "constants.cc",
+ "constants.h",
+ "database/database_maintenance.h",
+ "database/database_maintenance_impl.cc",
+ "database/database_maintenance_impl.h",
+ "database/metadata_utils.cc",
+ "database/metadata_utils.h",
+ "database/segment_info_database.cc",
+ "database/segment_info_database.h",
+ "database/signal_database.h",
+ "database/signal_database_impl.cc",
+ "database/signal_database_impl.h",
+ "database/signal_key.cc",
+ "database/signal_key.h",
+ "database/signal_key_internal.cc",
+ "database/signal_key_internal.h",
+ "database/signal_storage_config.cc",
+ "database/signal_storage_config.h",
+ "dummy_segmentation_platform_service.cc",
+ "dummy_segmentation_platform_service.h",
+ "execution/dummy_model_execution_manager.cc",
+ "execution/dummy_model_execution_manager.h",
+ "execution/feature_aggregator.h",
+ "execution/feature_aggregator_impl.cc",
+ "execution/feature_aggregator_impl.h",
+ "execution/model_execution_manager.h",
+ "execution/model_execution_manager_factory.cc",
+ "execution/model_execution_manager_factory.h",
+ "execution/model_execution_status.h",
+ "scheduler/model_execution_scheduler.h",
+ "scheduler/model_execution_scheduler_impl.cc",
+ "scheduler/model_execution_scheduler_impl.h",
+ "segmentation_platform_service_impl.cc",
+ "segmentation_platform_service_impl.h",
+ "selection/segment_selector.h",
+ "selection/segment_selector_impl.cc",
+ "selection/segment_selector_impl.h",
+ "selection/segmentation_result_prefs.cc",
+ "selection/segmentation_result_prefs.h",
+ "signals/histogram_signal_handler.cc",
+ "signals/histogram_signal_handler.h",
+ "signals/signal_filter_processor.cc",
+ "signals/signal_filter_processor.h",
+ "signals/user_action_signal_handler.cc",
+ "signals/user_action_signal_handler.h",
+ "stats.cc",
+ "stats.h",
+ ]
+
+ deps = [
+ "//base",
+ "//base/util/values:values_util",
+ "//components/keyed_service/core",
+ "//components/leveldb_proto",
+ "//components/prefs",
+ "//components/segmentation_platform/internal/proto",
+ "//components/segmentation_platform/public",
+ ]
+
+ public_deps = [
+ "//components/optimization_guide/core",
+ "//components/optimization_guide/proto:optimization_guide_proto",
+ ]
+
+ if (build_with_tflite_lib) {
+ sources += [
+ "execution/model_execution_manager_impl.cc",
+ "execution/model_execution_manager_impl.h",
+ "execution/segmentation_model_executor.cc",
+ "execution/segmentation_model_executor.h",
+ "execution/segmentation_model_handler.cc",
+ "execution/segmentation_model_handler.h",
+ ]
+
+ deps += [
+ "//third_party/tflite:tflite_public_headers",
+ "//third_party/tflite-support",
+ ]
+ }
+
+ if (is_android) {
+ sources += [
+ "android/segmentation_platform_service_android.cc",
+ "android/segmentation_platform_service_android.h",
+ ]
+
+ deps += [ ":jni_headers" ]
+ }
+}
+
+source_set("unit_tests") {
+ testonly = true
+
+ visibility = [ "//components/segmentation_platform:unit_tests" ]
+
+ # IMPORTANT NOTE: When adding new tests, also remember to update the list of
+ # tests in //components/segmentation_platform/components_unittests.filter
+ sources = [
+ "database/database_maintenance_impl_unittest.cc",
+ "database/metadata_utils_unittest.cc",
+ "database/mock_signal_database.cc",
+ "database/mock_signal_database.h",
+ "database/mock_signal_storage_config.cc",
+ "database/mock_signal_storage_config.h",
+ "database/segment_info_database_unittest.cc",
+ "database/signal_database_impl_unittest.cc",
+ "database/signal_key_internal_unittest.cc",
+ "database/signal_key_unittest.cc",
+ "database/signal_storage_config_unittest.cc",
+ "database/test_segment_info_database.cc",
+ "database/test_segment_info_database.h",
+ "dummy_segmentation_platform_service_unittest.cc",
+ "execution/dummy_model_execution_manager_unittest.cc",
+ "execution/feature_aggregator_impl_unittest.cc",
+ "execution/model_execution_manager_factory_unittest.cc",
+ "scheduler/model_execution_scheduler_unittest.cc",
+ "segmentation_platform_service_impl_unittest.cc",
+ "selection/segment_selector_unittest.cc",
+ "selection/segmentation_result_prefs_unittest.cc",
+ "signals/histogram_signal_handler_unittest.cc",
+ "signals/signal_filter_processor_unittest.cc",
+ "signals/user_action_signal_handler_unittest.cc",
+ "stats_unittest.cc",
+ ]
+
+ deps = [
+ ":internal",
+ "//base",
+ "//base/test:test_support",
+ "//components/leveldb_proto:test_support",
+ "//components/optimization_guide/core:test_support",
+ "//components/prefs",
+ "//components/prefs:test_support",
+ "//components/segmentation_platform/internal/proto",
+ "//components/segmentation_platform/public",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+
+ if (build_with_tflite_lib) {
+ # IMPORTANT NOTE: When adding new tests, also remember to update the list of
+ # tests in //components/segmentation_platform/components_unittests.filter
+ sources += [
+ "execution/model_execution_manager_impl_unittest.cc",
+ "execution/segmentation_model_executor_unittest.cc",
+ ]
+ }
+}
+
+if (is_android) {
+ android_library("internal_java") {
+ visibility = [ "//chrome/android:chrome_all_java" ]
+ sources = [ "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformServiceImpl.java" ]
+
+ deps = [
+ "//base:base_java",
+ "//components/optimization_guide/proto:optimization_guide_proto_java",
+ "//components/segmentation_platform/public:public_java",
+ "//third_party/androidx:androidx_annotation_annotation_java",
+ ]
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+ }
+
+ generate_jni("jni_headers") {
+ visibility = [
+ ":*",
+ "//chrome/browser",
+ ]
+
+ sources = [ "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformServiceImpl.java" ]
+ }
+}
diff --git a/chromium/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc b/chromium/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc
new file mode 100644
index 00000000000..738d40fcecf
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc
@@ -0,0 +1,92 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/android/segmentation_platform_service_android.h"
+
+#include <memory>
+
+#include "base/android/callback_android.h"
+#include "base/android/jni_string.h"
+#include "base/bind.h"
+#include "components/segmentation_platform/internal/jni_headers/SegmentationPlatformServiceImpl_jni.h"
+#include "components/segmentation_platform/public/segment_selection_result.h"
+#include "components/segmentation_platform/public/segmentation_platform_service.h"
+
+using base::android::AttachCurrentThread;
+
+namespace segmentation_platform {
+namespace {
+
+const char kSegmentationPlatformServiceBridgeKey[] =
+ "segmentation_platform_service_bridge";
+
+ScopedJavaLocalRef<jobject> CreateJavaSegmentSelectionResult(
+ JNIEnv* env,
+ const SegmentSelectionResult& result) {
+ int selected_segment = result.segment.has_value()
+ ? result.segment.value()
+ : OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN;
+ return Java_SegmentationPlatformServiceImpl_createSegmentSelectionResult(
+ env, result.is_ready, selected_segment);
+}
+
+void RunGetSelectedSegmentCallback(const JavaRef<jobject>& j_callback,
+ const SegmentSelectionResult& result) {
+ JNIEnv* env = AttachCurrentThread();
+ RunObjectCallbackAndroid(j_callback,
+ CreateJavaSegmentSelectionResult(env, result));
+}
+
+} // namespace
+
+// This function is declared in segmentation_platform_service.h and
+// should be linked in to any binary using
+// SegmentationPlatformService::GetJavaObject. static
+ScopedJavaLocalRef<jobject> SegmentationPlatformService::GetJavaObject(
+ SegmentationPlatformService* service) {
+ if (!service->GetUserData(kSegmentationPlatformServiceBridgeKey)) {
+ service->SetUserData(
+ kSegmentationPlatformServiceBridgeKey,
+ std::make_unique<SegmentationPlatformServiceAndroid>(service));
+ }
+
+ SegmentationPlatformServiceAndroid* bridge =
+ static_cast<SegmentationPlatformServiceAndroid*>(
+ service->GetUserData(kSegmentationPlatformServiceBridgeKey));
+
+ return bridge->GetJavaObject();
+}
+
+SegmentationPlatformServiceAndroid::SegmentationPlatformServiceAndroid(
+ SegmentationPlatformService* segmentation_platform_service)
+ : segmentation_platform_service_(segmentation_platform_service) {
+ DCHECK(segmentation_platform_service_);
+ JNIEnv* env = base::android::AttachCurrentThread();
+ java_obj_.Reset(env, Java_SegmentationPlatformServiceImpl_create(
+ env, reinterpret_cast<int64_t>(this))
+ .obj());
+}
+
+SegmentationPlatformServiceAndroid::~SegmentationPlatformServiceAndroid() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_SegmentationPlatformServiceImpl_clearNativePtr(env, java_obj_);
+}
+
+void SegmentationPlatformServiceAndroid::GetSelectedSegment(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& jcaller,
+ const JavaParamRef<jstring>& j_segmentation_key,
+ const JavaParamRef<jobject>& jcallback) {
+ segmentation_platform_service_->GetSelectedSegment(
+ ConvertJavaStringToUTF8(env, j_segmentation_key),
+ base::BindOnce(&RunGetSelectedSegmentCallback,
+ ScopedJavaGlobalRef<jobject>(jcallback)));
+}
+
+ScopedJavaLocalRef<jobject>
+SegmentationPlatformServiceAndroid::GetJavaObject() {
+ return ScopedJavaLocalRef<jobject>(java_obj_);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/android/segmentation_platform_service_android.h b/chromium/components/segmentation_platform/internal/android/segmentation_platform_service_android.h
new file mode 100644
index 00000000000..69d1d55b361
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/android/segmentation_platform_service_android.h
@@ -0,0 +1,45 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_ANDROID_SEGMENTATION_PLATFORM_SERVICE_ANDROID_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_ANDROID_SEGMENTATION_PLATFORM_SERVICE_ANDROID_H_
+
+#include "base/android/jni_android.h"
+#include "base/supports_user_data.h"
+#include "components/segmentation_platform/public/segmentation_platform_service.h"
+
+using base::android::JavaParamRef;
+using base::android::JavaRef;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace segmentation_platform {
+
+// Helper class responsible for bridging the SegmentationPlatformService between
+// C++ and Java.
+class SegmentationPlatformServiceAndroid : public base::SupportsUserData::Data {
+ public:
+ explicit SegmentationPlatformServiceAndroid(
+ SegmentationPlatformService* service);
+ ~SegmentationPlatformServiceAndroid() override;
+
+ void GetSelectedSegment(JNIEnv* env,
+ const JavaParamRef<jobject>& j_caller,
+ const JavaParamRef<jstring>& j_segmentation_key,
+ const JavaParamRef<jobject>& j_callback);
+
+ ScopedJavaLocalRef<jobject> GetJavaObject();
+
+ private:
+ // A reference to the Java counterpart of this class. See
+ // SegmentationPlatformServiceImpl.java.
+ ScopedJavaGlobalRef<jobject> java_obj_;
+
+ // Not owned.
+ SegmentationPlatformService* segmentation_platform_service_;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_ANDROID_SEGMENTATION_PLATFORM_SERVICE_ANDROID_H_
diff --git a/chromium/components/segmentation_platform/internal/constants.cc b/chromium/components/segmentation_platform/internal/constants.cc
new file mode 100644
index 00000000000..4c9f4523a8f
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/constants.cc
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/constants.h"
+
+namespace segmentation_platform {
+
+const char kSegmentationResultPref[] =
+ "segmentation_platform.segmentation_result";
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/constants.h b/chromium/components/segmentation_platform/internal/constants.h
new file mode 100644
index 00000000000..a7b5d49d19c
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/constants.h
@@ -0,0 +1,15 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_CONSTANTS_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_CONSTANTS_H_
+
+namespace segmentation_platform {
+
+// The path to the pref storing the segmentation result.
+extern const char kSegmentationResultPref[];
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_CONSTANTS_H_
diff --git a/chromium/components/segmentation_platform/internal/database/database_maintenance.h b/chromium/components/segmentation_platform/internal/database/database_maintenance.h
new file mode 100644
index 00000000000..116e9261bb9
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/database_maintenance.h
@@ -0,0 +1,23 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_DATABASE_MAINTENANCE_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_DATABASE_MAINTENANCE_H_
+
+namespace segmentation_platform {
+
+// DatabaseMaintenance is responsible for running all relevant database
+// maintenance tasks such as purging old data and removing newly unnecessary
+// data.
+class DatabaseMaintenance {
+ public:
+ virtual ~DatabaseMaintenance() = default;
+
+ // Kicks of executing all maintenance tasks asynchronously.
+ virtual void ExecuteMaintenanceTasks() = 0;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_DATABASE_MAINTENANCE_H_
diff --git a/chromium/components/segmentation_platform/internal/database/database_maintenance_impl.cc b/chromium/components/segmentation_platform/internal/database/database_maintenance_impl.cc
new file mode 100644
index 00000000000..9ef9eb72296
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/database_maintenance_impl.cc
@@ -0,0 +1,227 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/database/database_maintenance_impl.h"
+
+#include <deque>
+#include <memory>
+#include <set>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_forward.h"
+#include "base/callback_helpers.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/clock.h"
+#include "base/time/time.h"
+#include "base/trace_event/typed_macros.h"
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/database/signal_storage_config.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "components/segmentation_platform/internal/stats.h"
+#include "components/segmentation_platform/public/config.h"
+
+namespace {
+constexpr uint64_t kFirstCompactionDay = 2;
+constexpr uint64_t kMaxSignalStorageDays = 60;
+} // namespace
+
+namespace segmentation_platform {
+using SignalIdentifier = DatabaseMaintenanceImpl::SignalIdentifier;
+using CleanupItem = DatabaseMaintenanceImpl::CleanupItem;
+
+namespace {
+std::set<SignalIdentifier> CollectAllSignalIdentifiers(
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ segment_infos) {
+ std::set<SignalIdentifier> signal_ids;
+ for (const auto& pair : segment_infos) {
+ const proto::SegmentInfo& segment_info = pair.second;
+ const auto& metadata = segment_info.model_metadata();
+ for (int i = 0; i < metadata.features_size(); i++) {
+ const auto& feature = metadata.features(i);
+ if (feature.name_hash() != 0 &&
+ feature.type() != proto::SignalType::UNKNOWN_SIGNAL_TYPE) {
+ signal_ids.insert(std::make_pair(feature.name_hash(), feature.type()));
+ }
+ }
+ }
+ return signal_ids;
+}
+
+// Takes in the list of tasks and creates a link between each of them, and
+// returns the first task which points to the next one, which points to the next
+// one, etc., until the last task points to base::DoNothing::Once().
+base::OnceClosure LinkTasks(
+ std::vector<base::OnceCallback<void(base::OnceClosure)>> tasks) {
+ // Iterate in reverse order over the list of tasks and put them into a type
+ // of linked list, where the last task refers to base::DoNothing::Once().
+ base::OnceClosure first_task = base::DoNothing::Once();
+ for (auto curr_task = tasks.rbegin(); curr_task != tasks.rend();
+ ++curr_task) {
+ // We need to first perform the current task, and then move on to the next
+ // task which was previously stored in first_task.
+ first_task = base::BindOnce(std::move(*curr_task), std::move(first_task));
+ }
+ // All tasks can now be found following from the first task.
+ return first_task;
+}
+} // namespace
+
+struct DatabaseMaintenanceImpl::CleanupState {
+ CleanupState() = default;
+ ~CleanupState() = default;
+
+ // Disallow copy and assign.
+ CleanupState(const CleanupState&) = delete;
+ CleanupState& operator=(const CleanupState&) = delete;
+
+ std::deque<CleanupItem> signals_to_cleanup_;
+ std::vector<CleanupItem> cleaned_up_signals_;
+};
+
+DatabaseMaintenanceImpl::DatabaseMaintenanceImpl(
+ Config* config,
+ base::Clock* clock,
+ SegmentInfoDatabase* segment_info_database,
+ SignalDatabase* signal_database,
+ SignalStorageConfig* signal_storage_config)
+ : config_(config),
+ clock_(clock),
+ segment_info_database_(segment_info_database),
+ signal_database_(signal_database),
+ signal_storage_config_(signal_storage_config) {}
+
+DatabaseMaintenanceImpl::~DatabaseMaintenanceImpl() = default;
+
+void DatabaseMaintenanceImpl::ExecuteMaintenanceTasks() {
+ segment_info_database_->GetSegmentInfoForSegments(
+ config_->segment_ids,
+ base::BindOnce(&DatabaseMaintenanceImpl::OnSegmentInfoCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DatabaseMaintenanceImpl::OnSegmentInfoCallback(
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ segment_infos) {
+ std::set<SignalIdentifier> signal_ids =
+ CollectAllSignalIdentifiers(segment_infos);
+ stats::RecordMaintenanceSignalIdentifierCount(signal_ids.size());
+
+ auto all_tasks = GetAllTasks(signal_ids);
+ auto first_task = LinkTasks(std::move(all_tasks));
+ std::move(first_task).Run();
+}
+
+std::vector<base::OnceCallback<void(base::OnceClosure)>>
+DatabaseMaintenanceImpl::GetAllTasks(std::set<SignalIdentifier> signal_ids) {
+ // Create an ordered vector of tasks. These are not yet OnceClosures, since
+ // they are missing their reference to the next task. This will be added later
+ // using LinkTasks(...).
+ std::vector<base::OnceCallback<void(base::OnceClosure)>> tasks;
+
+ // 1) Clean up unnecessary signals.
+ tasks.emplace_back(
+ base::BindOnce(&DatabaseMaintenanceImpl::CleanupSignalStorage,
+ weak_ptr_factory_.GetWeakPtr(), signal_ids));
+ // 2) Compact anything still left in the database.
+ tasks.emplace_back(base::BindOnce(&DatabaseMaintenanceImpl::CompactSamples,
+ weak_ptr_factory_.GetWeakPtr(),
+ signal_ids));
+
+ return tasks;
+}
+
+void DatabaseMaintenanceImpl::CleanupSignalStorage(
+ std::set<SignalIdentifier> signal_ids,
+ base::OnceClosure next_action) {
+ std::vector<CleanupItem> signals_to_cleanup;
+ signal_storage_config_->GetSignalsForCleanup(signal_ids, signals_to_cleanup);
+
+ auto cleanup_state = std::make_unique<CleanupState>();
+ // Convert the vector of cleanup items to a deque so we can easily handle
+ // the state by popping the first one until it is empty.
+ for (auto& item : signals_to_cleanup)
+ cleanup_state->signals_to_cleanup_.emplace_back(item);
+
+ CleanupSignalStorageProcessNext(
+ std::move(cleanup_state),
+ base::BindOnce(&DatabaseMaintenanceImpl::CleanupSignalStorageDone,
+ weak_ptr_factory_.GetWeakPtr(), std::move(next_action)),
+ CleanupItem(), false);
+}
+
+void DatabaseMaintenanceImpl::CleanupSignalStorageProcessNext(
+ std::unique_ptr<CleanupState> cleanup_state,
+ base::OnceCallback<void(std::vector<CleanupItem>)> on_done_callback,
+ CleanupItem previous_item,
+ bool previous_item_deleted) {
+ if (previous_item_deleted)
+ cleanup_state->cleaned_up_signals_.emplace_back(previous_item);
+
+ if (cleanup_state->signals_to_cleanup_.empty()) {
+ std::move(on_done_callback)
+ .Run(std::move(cleanup_state->cleaned_up_signals_));
+ return;
+ }
+
+ CleanupItem cleanup_item = cleanup_state->signals_to_cleanup_.front();
+ cleanup_state->signals_to_cleanup_.pop_front();
+
+ proto::SignalType signal_type = std::get<1>(cleanup_item);
+ uint64_t name_hash = std::get<0>(cleanup_item);
+ base::Time end_time = std::get<2>(cleanup_item);
+ signal_database_->DeleteSamples(
+ signal_type, name_hash, end_time,
+ base::BindOnce(&DatabaseMaintenanceImpl::CleanupSignalStorageProcessNext,
+ weak_ptr_factory_.GetWeakPtr(), std::move(cleanup_state),
+ std::move(on_done_callback), std::move(cleanup_item)));
+}
+
+void DatabaseMaintenanceImpl::CleanupSignalStorageDone(
+ base::OnceClosure next_action,
+ std::vector<CleanupItem> cleaned_up_signals) {
+ stats::RecordMaintenanceCleanupSignalSuccessCount(cleaned_up_signals.size());
+ signal_storage_config_->UpdateSignalsForCleanup(cleaned_up_signals);
+ std::move(next_action).Run();
+}
+
+void DatabaseMaintenanceImpl::CompactSamples(
+ std::set<SignalIdentifier> signal_ids,
+ base::OnceClosure next_action) {
+ for (uint64_t days_ago = kFirstCompactionDay;
+ days_ago <= kMaxSignalStorageDays; ++days_ago) {
+ base::Time compaction_day =
+ clock_->Now() - base::TimeDelta::FromDays(days_ago);
+ for (auto signal_id : signal_ids) {
+ signal_database_->CompactSamplesForDay(
+ signal_id.second, signal_id.first, compaction_day,
+ base::BindOnce(&DatabaseMaintenanceImpl::RecordCompactionResult,
+ weak_ptr_factory_.GetWeakPtr(), signal_id.second,
+ signal_id.first));
+ }
+ }
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&DatabaseMaintenanceImpl::CompactSamplesDone,
+ weak_ptr_factory_.GetWeakPtr(), std::move(next_action)));
+}
+
+void DatabaseMaintenanceImpl::RecordCompactionResult(
+ proto::SignalType signal_type,
+ uint64_t name_hash,
+ bool success) {
+ stats::RecordMaintenanceCompactionResult(signal_type, success);
+}
+
+void DatabaseMaintenanceImpl::CompactSamplesDone(
+ base::OnceClosure next_action) {
+ std::move(next_action).Run();
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/database_maintenance_impl.h b/chromium/components/segmentation_platform/internal/database/database_maintenance_impl.h
new file mode 100644
index 00000000000..618fbdfa4d1
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/database_maintenance_impl.h
@@ -0,0 +1,100 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_DATABASE_MAINTENANCE_IMPL_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_DATABASE_MAINTENANCE_IMPL_H_
+
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/memory/weak_ptr.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/database/database_maintenance.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+
+namespace base {
+class Clock;
+} // namespace base
+
+using optimization_guide::proto::OptimizationTarget;
+
+namespace segmentation_platform {
+namespace proto {
+class SegmentInfo;
+} // namespace proto
+struct Config;
+class SignalDatabase;
+class SegmentInfoDatabase;
+class SignalStorageConfig;
+
+// DatabaseMaintenanceImpl is the main implementation of the DatabaseMaintenance
+// functionality.
+class DatabaseMaintenanceImpl : public DatabaseMaintenance {
+ public:
+ using SignalIdentifier = std::pair<uint64_t, proto::SignalType>;
+ using CleanupItem = std::tuple<uint64_t, proto::SignalType, base::Time>;
+
+ explicit DatabaseMaintenanceImpl(Config* config,
+ base::Clock* clock,
+ SegmentInfoDatabase* segment_info_database,
+ SignalDatabase* signal_database,
+ SignalStorageConfig* signal_storage_config);
+ ~DatabaseMaintenanceImpl() override;
+
+ // DatabaseMaintenance overrides.
+ void ExecuteMaintenanceTasks() override;
+
+ private:
+ // Internal struct for tracking the remaining work when cleaning up the
+ // signal storage.
+ struct CleanupState;
+
+ // All tasks currently need information about various segments, so this is
+ // the callback after the initial database lookup for this data.
+ void OnSegmentInfoCallback(
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ segment_infos);
+
+ // Returns an ordered vector of all the tasks we are supposed to perform.
+ // These are unfinished and also need to be linked to the next task to be
+ // valid.
+ std::vector<base::OnceCallback<void(base::OnceClosure)>> GetAllTasks(
+ std::set<SignalIdentifier> signal_ids);
+
+ // Signal storage cleanup.
+ void CleanupSignalStorage(std::set<SignalIdentifier> signal_ids,
+ base::OnceClosure next_action);
+ void CleanupSignalStorageProcessNext(
+ std::unique_ptr<CleanupState> cleanup_state,
+ base::OnceCallback<void(std::vector<CleanupItem>)> on_done_callback,
+ CleanupItem previous_item,
+ bool previous_item_deleted);
+ void CleanupSignalStorageDone(base::OnceClosure next_action,
+ std::vector<CleanupItem> cleaned_up_signals);
+
+ // Sample compaction.
+ void CompactSamples(std::set<SignalIdentifier> signal_ids,
+ base::OnceClosure next_action);
+ void RecordCompactionResult(proto::SignalType signal_type,
+ uint64_t name_hash,
+ bool success);
+ void CompactSamplesDone(base::OnceClosure next_action);
+
+ // Input.
+ Config* config_;
+ base::Clock* clock_;
+
+ // Databases.
+ SegmentInfoDatabase* segment_info_database_;
+ SignalDatabase* signal_database_;
+ SignalStorageConfig* signal_storage_config_;
+
+ base::WeakPtrFactory<DatabaseMaintenanceImpl> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_DATABASE_MAINTENANCE_IMPL_H_
diff --git a/chromium/components/segmentation_platform/internal/database/database_maintenance_impl_unittest.cc b/chromium/components/segmentation_platform/internal/database/database_maintenance_impl_unittest.cc
new file mode 100644
index 00000000000..45ba1a05b2a
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/database_maintenance_impl_unittest.cc
@@ -0,0 +1,203 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/database/database_maintenance_impl.h"
+
+#include <cstdint>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/metrics/metrics_hashes.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/database/mock_signal_database.h"
+#include "components/segmentation_platform/internal/database/mock_signal_storage_config.h"
+#include "components/segmentation_platform/internal/database/signal_storage_config.h"
+#include "components/segmentation_platform/internal/database/test_segment_info_database.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "components/segmentation_platform/public/config.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::base::test::RunOnceCallback;
+using ::testing::_;
+using ::testing::SetArgReferee;
+
+using optimization_guide::proto::OptimizationTarget;
+
+namespace segmentation_platform {
+using SignalType = proto::SignalType;
+using Aggregation = proto::Aggregation;
+using SignalIdentifier = std::pair<uint64_t, SignalType>;
+using CleanupItem = std::tuple<uint64_t, SignalType, base::Time>;
+
+namespace {
+constexpr uint64_t kLatestCompactionDaysAgo = 2;
+constexpr uint64_t kEarliestCompactionDaysAgo = 60;
+
+std::string kTestSegmentationKey = "some_key";
+
+struct SignalData {
+ OptimizationTarget target;
+ proto::SignalType signal_type;
+ std::string name;
+ uint64_t name_hash;
+ uint64_t bucket_count;
+ uint64_t tensor_length;
+ Aggregation aggregation;
+ base::Time earliest_needed_timestamp;
+ bool success;
+};
+
+std::unique_ptr<Config> CreateTestConfig() {
+ auto config = std::make_unique<Config>();
+ config->segmentation_key = kTestSegmentationKey;
+ config->segment_selection_ttl = base::TimeDelta::FromDays(28);
+ config->segment_ids = {
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE};
+ return config;
+}
+} // namespace
+
+class DatabaseMaintenanceImplTest : public testing::Test {
+ public:
+ DatabaseMaintenanceImplTest() = default;
+ ~DatabaseMaintenanceImplTest() override = default;
+
+ void SetUp() override {
+ config_ = CreateTestConfig();
+ segment_info_database_ = std::make_unique<test::TestSegmentInfoDatabase>();
+ signal_database_ = std::make_unique<MockSignalDatabase>();
+ signal_storage_config_ = std::make_unique<MockSignalStorageConfig>();
+ database_maintenance_ = std::make_unique<DatabaseMaintenanceImpl>(
+ config_.get(), &clock_, segment_info_database_.get(),
+ signal_database_.get(), signal_storage_config_.get());
+
+ clock_.SetNow(base::Time::Now());
+ }
+
+ // Adds the provided features to the SegmentInfoDatabase.
+ void AddFeatures(std::vector<SignalData> signal_datas) {
+ for (auto& sd : signal_datas) {
+ switch (sd.signal_type) {
+ case SignalType::HISTOGRAM_VALUE: {
+ segment_info_database_->AddHistogramValueFeature(
+ sd.target, sd.name, sd.bucket_count, sd.tensor_length,
+ sd.aggregation);
+ break;
+ }
+ case SignalType::HISTOGRAM_ENUM: {
+ segment_info_database_->AddHistogramEnumFeature(
+ sd.target, sd.name, sd.bucket_count, sd.tensor_length,
+ sd.aggregation, {});
+ break;
+ }
+ case SignalType::USER_ACTION: {
+ segment_info_database_->AddUserActionFeature(
+ sd.target, sd.name, sd.bucket_count, sd.tensor_length,
+ sd.aggregation);
+ break;
+ }
+ default: {
+ CHECK(false) << "Incorrect SignalType";
+ break;
+ }
+ }
+ }
+ }
+
+ base::test::TaskEnvironment task_environment_;
+
+ std::unique_ptr<Config> config_;
+ base::SimpleTestClock clock_;
+ std::unique_ptr<test::TestSegmentInfoDatabase> segment_info_database_;
+ std::unique_ptr<MockSignalDatabase> signal_database_;
+ std::unique_ptr<MockSignalStorageConfig> signal_storage_config_;
+
+ std::unique_ptr<DatabaseMaintenanceImpl> database_maintenance_;
+};
+
+std::set<DatabaseMaintenanceImpl::SignalIdentifier> GetSignalIds(
+ std::vector<SignalData> signal_datas) {
+ std::set<DatabaseMaintenanceImpl::SignalIdentifier> signal_ids;
+ for (auto& sd : signal_datas)
+ signal_ids.emplace(std::make_pair(sd.name_hash, sd.signal_type));
+
+ return signal_ids;
+}
+
+std::vector<CleanupItem> GetCleanupItems(std::vector<SignalData> signal_datas) {
+ std::vector<CleanupItem> cleanup_items;
+ for (auto& sd : signal_datas) {
+ cleanup_items.emplace_back(std::make_tuple(sd.name_hash, sd.signal_type,
+ sd.earliest_needed_timestamp));
+ }
+ return cleanup_items;
+}
+
+TEST_F(DatabaseMaintenanceImplTest, ExecuteMaintenanceTasks) {
+ std::vector<SignalData> signal_datas = {
+ {OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ SignalType::HISTOGRAM_VALUE, "Foo", base::HashMetricName("Foo"), 44, 1,
+ Aggregation::COUNT, clock_.Now() - base::TimeDelta::FromDays(10), true},
+ {OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE,
+ SignalType::HISTOGRAM_ENUM, "Bar", base::HashMetricName("Bar"), 33, 1,
+ Aggregation::COUNT, clock_.Now() - base::TimeDelta::FromDays(5), true},
+ {OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE,
+ SignalType::USER_ACTION, "Failed", base::HashMetricName("Failed"), 22, 1,
+ Aggregation::COUNT, clock_.Now() - base::TimeDelta::FromDays(1), false},
+ };
+
+ // Prepare test setup.
+ AddFeatures(signal_datas);
+ std::set<DatabaseMaintenanceImpl::SignalIdentifier> signal_ids =
+ GetSignalIds(signal_datas);
+ std::vector<CleanupItem> cleanup_items = GetCleanupItems(signal_datas);
+
+ // Ensure we return the correct signals.
+ ON_CALL(*signal_storage_config_, GetSignalsForCleanup(_, _))
+ .WillByDefault(SetArgReferee<1>(cleanup_items));
+
+ // We should try to delete each signal.
+ for (auto& sd : signal_datas) {
+ EXPECT_CALL(*signal_database_,
+ DeleteSamples(sd.signal_type, sd.name_hash,
+ sd.earliest_needed_timestamp, _))
+ .WillOnce(RunOnceCallback<3>(sd.success));
+ }
+
+ // The Failed signal failed to clean up, so we should not be updating it, but
+ // the rest should be updated.
+ cleanup_items.erase(std::remove_if(cleanup_items.begin(), cleanup_items.end(),
+ [](CleanupItem item) {
+ return std::get<0>(item) ==
+ base::HashMetricName("Failed");
+ }),
+ cleanup_items.end());
+ EXPECT_CALL(*signal_storage_config_, UpdateSignalsForCleanup(cleanup_items));
+
+ // Verify that for each of the signal data, we get a compaction request for
+ // each day within the correct range.
+ for (auto& sd : signal_datas) {
+ for (uint64_t days_ago = kLatestCompactionDaysAgo;
+ days_ago <= kEarliestCompactionDaysAgo; ++days_ago) {
+ EXPECT_CALL(*signal_database_,
+ CompactSamplesForDay(
+ sd.signal_type, sd.name_hash,
+ clock_.Now() - base::TimeDelta::FromDays(days_ago), _))
+ .WillOnce(RunOnceCallback<3>(/*success=*/sd.success));
+ }
+ }
+
+ // Kick off all tasks.
+ database_maintenance_->ExecuteMaintenanceTasks();
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/metadata_utils.cc b/chromium/components/segmentation_platform/internal/database/metadata_utils.cc
new file mode 100644
index 00000000000..246fa8aeb75
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/metadata_utils.cc
@@ -0,0 +1,196 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/database/metadata_utils.h"
+
+#include "base/metrics/metrics_hashes.h"
+#include "base/notreached.h"
+#include "base/time/time.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+namespace metadata_utils {
+
+namespace {
+uint64_t GetExpectedTensorLength(const proto::Feature& feature) {
+ switch (feature.aggregation()) {
+ case proto::Aggregation::COUNT:
+ case proto::Aggregation::COUNT_BOOLEAN:
+ case proto::Aggregation::BUCKETED_COUNT_BOOLEAN_TRUE_COUNT:
+ case proto::Aggregation::SUM:
+ case proto::Aggregation::SUM_BOOLEAN:
+ case proto::Aggregation::BUCKETED_SUM_BOOLEAN_TRUE_COUNT:
+ return feature.bucket_count() == 0 ? 0 : 1;
+ case proto::Aggregation::BUCKETED_COUNT:
+ case proto::Aggregation::BUCKETED_COUNT_BOOLEAN:
+ case proto::Aggregation::BUCKETED_CUMULATIVE_COUNT:
+ case proto::Aggregation::BUCKETED_SUM:
+ case proto::Aggregation::BUCKETED_SUM_BOOLEAN:
+ case proto::Aggregation::BUCKETED_CUMULATIVE_SUM:
+ return feature.bucket_count();
+ case proto::Aggregation::UNKNOWN:
+ NOTREACHED();
+ return 0;
+ }
+}
+} // namespace
+
+ValidationResult ValidateSegmentInfo(const proto::SegmentInfo& segment_info) {
+ if (segment_info.segment_id() ==
+ optimization_guide::proto::OPTIMIZATION_TARGET_UNKNOWN) {
+ return ValidationResult::kSegmentIDNotFound;
+ }
+
+ if (!segment_info.has_model_metadata())
+ return ValidationResult::kMetadataNotFound;
+
+ return ValidateMetadata(segment_info.model_metadata());
+}
+
+ValidationResult ValidateMetadata(
+ const proto::SegmentationModelMetadata& model_metadata) {
+ if (model_metadata.time_unit() == proto::TimeUnit::UNKNOWN_TIME_UNIT)
+ return ValidationResult::kTimeUnitInvald;
+
+ return ValidationResult::kValidationSuccess;
+}
+
+ValidationResult ValidateMetadataFeature(const proto::Feature& feature) {
+ if (feature.type() == proto::SignalType::UNKNOWN_SIGNAL_TYPE)
+ return ValidationResult::kSignalTypeInvalid;
+
+ if ((feature.type() == proto::SignalType::HISTOGRAM_ENUM ||
+ feature.type() == proto::SignalType::HISTOGRAM_VALUE) &&
+ feature.name().empty()) {
+ return ValidationResult::kFeatureNameNotFound;
+ }
+
+ if (feature.name_hash() == 0)
+ return ValidationResult::kFeatureNameHashNotFound;
+
+ if (!feature.name().empty() &&
+ base::HashMetricName(feature.name()) != feature.name_hash()) {
+ return ValidationResult::kFeatureNameHashDoesNotMatchName;
+ }
+
+ if (feature.aggregation() == proto::Aggregation::UNKNOWN)
+ return ValidationResult::kFeatureAggregationNotFound;
+
+ if (GetExpectedTensorLength(feature) != feature.tensor_length())
+ return ValidationResult::kFeatureTensorLengthInvalid;
+
+ return ValidationResult::kValidationSuccess;
+}
+
+ValidationResult ValidateMetadataAndFeatures(
+ const proto::SegmentationModelMetadata& model_metadata) {
+ auto metadata_result = ValidateMetadata(model_metadata);
+ if (metadata_result != ValidationResult::kValidationSuccess)
+ return metadata_result;
+
+ for (int i = 0; i < model_metadata.features_size(); ++i) {
+ auto feature = model_metadata.features(i);
+ auto feature_result = ValidateMetadataFeature(feature);
+ if (feature_result != ValidationResult::kValidationSuccess)
+ return feature_result;
+ }
+
+ return ValidationResult::kValidationSuccess;
+}
+
+ValidationResult ValidateSegmentInfoMetadataAndFeatures(
+ const proto::SegmentInfo& segment_info) {
+ auto segment_info_result = ValidateSegmentInfo(segment_info);
+ if (segment_info_result != ValidationResult::kValidationSuccess)
+ return segment_info_result;
+
+ return ValidateMetadataAndFeatures(segment_info.model_metadata());
+}
+
+void SetFeatureNameHashesFromName(
+ proto::SegmentationModelMetadata* model_metadata) {
+ for (int i = 0; i < model_metadata->features_size(); ++i) {
+ proto::Feature* feature = model_metadata->mutable_features(i);
+ feature->set_name_hash(base::HashMetricName(feature->name()));
+ }
+}
+
+bool HasExpiredOrUnavailableResult(const proto::SegmentInfo& segment_info) {
+ if (!segment_info.has_prediction_result())
+ return true;
+
+ base::Time last_result_timestamp =
+ base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromMicroseconds(
+ segment_info.prediction_result().timestamp_us()));
+
+ base::TimeDelta result_ttl =
+ segment_info.model_metadata().result_time_to_live() *
+ GetTimeUnit(segment_info.model_metadata());
+
+ return last_result_timestamp + result_ttl < base::Time::Now();
+}
+
+bool HasFreshResults(const proto::SegmentInfo& segment_info) {
+ if (!segment_info.has_prediction_result())
+ return false;
+
+ const proto::SegmentationModelMetadata& metadata =
+ segment_info.model_metadata();
+
+ base::Time last_result_timestamp =
+ base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromMicroseconds(
+ segment_info.prediction_result().timestamp_us()));
+ base::TimeDelta result_ttl =
+ metadata.result_time_to_live() * GetTimeUnit(metadata);
+
+ return base::Time::Now() - last_result_timestamp < result_ttl;
+}
+
+base::TimeDelta GetTimeUnit(
+ const proto::SegmentationModelMetadata& model_metadata) {
+ proto::TimeUnit time_unit = model_metadata.time_unit();
+ switch (time_unit) {
+ case proto::TimeUnit::YEAR:
+ return base::TimeDelta::FromDays(365);
+ case proto::TimeUnit::MONTH:
+ return base::TimeDelta::FromDays(30);
+ case proto::TimeUnit::WEEK:
+ return base::TimeDelta::FromDays(7);
+ case proto::TimeUnit::DAY:
+ return base::TimeDelta::FromDays(1);
+ case proto::TimeUnit::HOUR:
+ return base::TimeDelta::FromHours(1);
+ case proto::TimeUnit::MINUTE:
+ return base::TimeDelta::FromMinutes(1);
+ case proto::TimeUnit::SECOND:
+ return base::TimeDelta::FromSeconds(1);
+ case proto::TimeUnit::UNKNOWN_TIME_UNIT:
+ FALLTHROUGH;
+ default:
+ NOTREACHED();
+ return base::TimeDelta();
+ }
+}
+
+SignalKey::Kind SignalTypeToSignalKind(proto::SignalType signal_type) {
+ switch (signal_type) {
+ case proto::SignalType::USER_ACTION:
+ return SignalKey::Kind::USER_ACTION;
+ case proto::SignalType::HISTOGRAM_ENUM:
+ return SignalKey::Kind::HISTOGRAM_ENUM;
+ case proto::SignalType::HISTOGRAM_VALUE:
+ return SignalKey::Kind::HISTOGRAM_VALUE;
+ case proto::SignalType::UNKNOWN_SIGNAL_TYPE:
+ return SignalKey::Kind::UNKNOWN;
+ }
+}
+
+} // namespace metadata_utils
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/metadata_utils.h b/chromium/components/segmentation_platform/internal/database/metadata_utils.h
new file mode 100644
index 00000000000..54982611995
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/metadata_utils.h
@@ -0,0 +1,80 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_METADATA_UTILS_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_METADATA_UTILS_H_
+
+#include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+namespace metadata_utils {
+
+// Keep up to date with SegmentationPlatformValidationResult in
+// //tools/metrics/histograms/enums.xml.
+enum class ValidationResult {
+ kValidationSuccess = 0,
+ kSegmentIDNotFound = 1,
+ kMetadataNotFound = 2,
+ kTimeUnitInvald = 3,
+ kSignalTypeInvalid = 4,
+ kFeatureNameNotFound = 5,
+ kFeatureNameHashNotFound = 6,
+ kFeatureAggregationNotFound = 7,
+ kFeatureTensorLengthInvalid = 8,
+ kFeatureNameHashDoesNotMatchName = 9,
+ kMaxValue = kFeatureNameHashDoesNotMatchName,
+};
+
+// Whether the given SegmentInfo and its metadata is valid to be used for the
+// current segmentation platform.
+ValidationResult ValidateSegmentInfo(const proto::SegmentInfo& segment_info);
+
+// Whether the given metadata is valid to be used for the current segmentation
+// platform.
+ValidationResult ValidateMetadata(
+ const proto::SegmentationModelMetadata& model_metadata);
+
+// Whether the given feature metadata is valid to be used for the current
+// segmentation platform.
+ValidationResult ValidateMetadataFeature(const proto::Feature& feature);
+
+// Whether the given metadata and feature metadata is valid to be used for the
+// current segmentation platform.
+ValidationResult ValidateMetadataAndFeatures(
+ const proto::SegmentationModelMetadata& model_metadata);
+
+// Whether the given SegmentInfo, metadata and feature metadata is valid to be
+// used for the current segmentation platform.
+ValidationResult ValidateSegmentInfoMetadataAndFeatures(
+ const proto::SegmentInfo& segment_info);
+
+// For all features in the given metadata, updates the feature name hash based
+// on the feature name. Note: This mutates the metadata that is passed in.
+void SetFeatureNameHashesFromName(
+ proto::SegmentationModelMetadata* model_metadata);
+
+// Whether a segment has expired results or no result. Called to determine
+// whether the model should be rerun.
+bool HasExpiredOrUnavailableResult(const proto::SegmentInfo& segment_info);
+
+// Whether the results were computed too recently for a given segment. If
+// true, the model execution should be skipped for the time being.
+bool HasFreshResults(const proto::SegmentInfo& segment_info);
+
+// Helper method to read the time unit from the proto.
+base::TimeDelta GetTimeUnit(
+ const proto::SegmentationModelMetadata& model_metadata);
+
+// Conversion methods between SignalKey::Kind and proto::SignalType.
+SignalKey::Kind SignalTypeToSignalKind(proto::SignalType signal_type);
+
+} // namespace metadata_utils
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_METADATA_UTILS_H_
diff --git a/chromium/components/segmentation_platform/internal/database/metadata_utils_unittest.cc b/chromium/components/segmentation_platform/internal/database/metadata_utils_unittest.cc
new file mode 100644
index 00000000000..9550c7af9d3
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/metadata_utils_unittest.cc
@@ -0,0 +1,419 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/database/metadata_utils.h"
+
+#include "base/metrics/metrics_hashes.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace segmentation_platform {
+
+class MetadataUtilsTest : public testing::Test {
+ public:
+ ~MetadataUtilsTest() override = default;
+};
+
+TEST_F(MetadataUtilsTest, SegmentInfoValidation) {
+ proto::SegmentInfo segment_info;
+ EXPECT_EQ(metadata_utils::ValidationResult::kSegmentIDNotFound,
+ metadata_utils::ValidateSegmentInfo(segment_info));
+
+ segment_info.set_segment_id(optimization_guide::proto::OptimizationTarget::
+ OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
+ EXPECT_EQ(metadata_utils::ValidationResult::kMetadataNotFound,
+ metadata_utils::ValidateSegmentInfo(segment_info));
+
+ // The rest of this test verifies that at least some metadata is verified.
+ segment_info.mutable_model_metadata()->set_time_unit(
+ proto::UNKNOWN_TIME_UNIT);
+ EXPECT_EQ(metadata_utils::ValidationResult::kTimeUnitInvald,
+ metadata_utils::ValidateSegmentInfo(segment_info));
+
+ segment_info.mutable_model_metadata()->set_time_unit(proto::DAY);
+ EXPECT_EQ(metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateSegmentInfo(segment_info));
+}
+
+TEST_F(MetadataUtilsTest, DefaultMetadataIsInvalid) {
+ proto::SegmentationModelMetadata empty;
+
+ EXPECT_EQ(metadata_utils::ValidationResult::kTimeUnitInvald,
+ metadata_utils::ValidateMetadata(empty));
+}
+
+TEST_F(MetadataUtilsTest, MetadataValidation) {
+ proto::SegmentationModelMetadata metadata;
+ metadata.set_time_unit(proto::UNKNOWN_TIME_UNIT);
+ EXPECT_EQ(metadata_utils::ValidationResult::kTimeUnitInvald,
+ metadata_utils::ValidateMetadata(metadata));
+
+ metadata.set_time_unit(proto::DAY);
+ EXPECT_EQ(metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateMetadata(metadata));
+}
+
+TEST_F(MetadataUtilsTest, MetadataFeatureValidation) {
+ proto::Feature feature;
+ EXPECT_EQ(metadata_utils::ValidationResult::kSignalTypeInvalid,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ feature.set_type(proto::SignalType::UNKNOWN_SIGNAL_TYPE);
+ EXPECT_EQ(metadata_utils::ValidationResult::kSignalTypeInvalid,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ // name not required for USER_ACTION.
+ feature.set_type(proto::SignalType::USER_ACTION);
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureNameHashNotFound,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ feature.set_type(proto::SignalType::HISTOGRAM_ENUM);
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureNameNotFound,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ feature.set_type(proto::SignalType::HISTOGRAM_VALUE);
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureNameNotFound,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ feature.set_name("test name");
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureNameHashNotFound,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ feature.set_name_hash(base::HashMetricName("not the correct name"));
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureNameHashDoesNotMatchName,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ feature.set_name_hash(base::HashMetricName("test name"));
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureAggregationNotFound,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ feature.set_aggregation(proto::Aggregation::COUNT);
+ // No bucket_count or tensor_length is valid.
+ EXPECT_EQ(metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ feature.set_bucket_count(456);
+ // Aggregation=COUNT requires tensor length = 1.
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureTensorLengthInvalid,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ std::vector<proto::Aggregation> tensor_length_1 = {
+ proto::Aggregation::COUNT,
+ proto::Aggregation::COUNT_BOOLEAN,
+ proto::Aggregation::BUCKETED_COUNT_BOOLEAN_TRUE_COUNT,
+ proto::Aggregation::SUM,
+ proto::Aggregation::SUM_BOOLEAN,
+ proto::Aggregation::BUCKETED_SUM_BOOLEAN_TRUE_COUNT,
+ };
+ std::vector<proto::Aggregation> tensor_length_bucket_count = {
+ proto::Aggregation::BUCKETED_COUNT,
+ proto::Aggregation::BUCKETED_COUNT_BOOLEAN,
+ proto::Aggregation::BUCKETED_CUMULATIVE_COUNT,
+ proto::Aggregation::BUCKETED_SUM,
+ proto::Aggregation::BUCKETED_SUM_BOOLEAN,
+ proto::Aggregation::BUCKETED_CUMULATIVE_SUM,
+ };
+
+ for (auto aggregation : tensor_length_1) {
+ feature.set_aggregation(aggregation);
+
+ // If bucket count is 0, do not use for output, i.e. tensor_length should be
+ // 0.
+ feature.set_bucket_count(0);
+ feature.set_tensor_length(1);
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureTensorLengthInvalid,
+ metadata_utils::ValidateMetadataFeature(feature));
+ feature.set_tensor_length(0);
+ EXPECT_EQ(metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ // Tensor length should otherwise always be 1 for this aggregation type.
+ feature.set_bucket_count(456);
+ feature.set_tensor_length(10);
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureTensorLengthInvalid,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ feature.set_bucket_count(456);
+ feature.set_tensor_length(1);
+ EXPECT_EQ(metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateMetadataFeature(feature));
+ }
+
+ for (auto aggregation : tensor_length_bucket_count) {
+ feature.set_aggregation(aggregation);
+
+ // If bucket count is 0, do not use for output, i.e. tensor_length should be
+ // 0.
+ feature.set_bucket_count(0);
+ feature.set_tensor_length(1);
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureTensorLengthInvalid,
+ metadata_utils::ValidateMetadataFeature(feature));
+ feature.set_tensor_length(0);
+ EXPECT_EQ(metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ // Tensor length should otherwise always be equal to bucket_count for this
+ // aggregation type.
+ feature.set_bucket_count(456);
+ feature.set_tensor_length(1);
+ EXPECT_EQ(metadata_utils::ValidationResult::kFeatureTensorLengthInvalid,
+ metadata_utils::ValidateMetadataFeature(feature));
+
+ feature.set_bucket_count(456);
+ feature.set_tensor_length(456);
+ EXPECT_EQ(metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateMetadataFeature(feature));
+ }
+}
+
+TEST_F(MetadataUtilsTest, ValidateMetadataAndFeatures) {
+ proto::SegmentationModelMetadata metadata;
+ metadata.set_time_unit(proto::UNKNOWN_TIME_UNIT);
+ EXPECT_EQ(metadata_utils::ValidationResult::kTimeUnitInvald,
+ metadata_utils::ValidateMetadataAndFeatures(metadata));
+
+ metadata.set_time_unit(proto::DAY);
+ EXPECT_EQ(metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateMetadataAndFeatures(metadata));
+
+ // Verify adding a single features adds new requirements.
+ auto* feature1 = metadata.add_features();
+ EXPECT_EQ(metadata_utils::ValidationResult::kSignalTypeInvalid,
+ metadata_utils::ValidateMetadataAndFeatures(metadata));
+
+ // Fully flesh out an example feature and verify validation starts working
+ // again.
+ feature1->set_type(proto::SignalType::USER_ACTION);
+ feature1->set_name_hash(base::HashMetricName("some user action"));
+ feature1->set_aggregation(proto::Aggregation::COUNT);
+ feature1->set_bucket_count(1);
+ feature1->set_tensor_length(1);
+ EXPECT_EQ(metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateMetadataAndFeatures(metadata));
+
+ // Verify adding another feature adds new requirements again.
+ auto* feature2 = metadata.add_features();
+ EXPECT_EQ(metadata_utils::ValidationResult::kSignalTypeInvalid,
+ metadata_utils::ValidateMetadataAndFeatures(metadata));
+
+ // Fully flesh out the second feature and verify validation starts working
+ // again.
+ feature2->set_type(proto::SignalType::HISTOGRAM_VALUE);
+ feature2->set_name("some histogram");
+ feature2->set_name_hash(base::HashMetricName("some histogram"));
+ feature2->set_aggregation(proto::Aggregation::BUCKETED_COUNT);
+ feature2->set_bucket_count(2);
+ feature2->set_tensor_length(2);
+ EXPECT_EQ(metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateMetadataAndFeatures(metadata));
+}
+
+TEST_F(MetadataUtilsTest, ValidateSegementInfoMetadataAndFeatures) {
+ proto::SegmentInfo segment_info;
+ EXPECT_EQ(
+ metadata_utils::ValidationResult::kSegmentIDNotFound,
+ metadata_utils::ValidateSegmentInfoMetadataAndFeatures(segment_info));
+
+ segment_info.set_segment_id(optimization_guide::proto::OptimizationTarget::
+ OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB);
+ EXPECT_EQ(
+ metadata_utils::ValidationResult::kMetadataNotFound,
+ metadata_utils::ValidateSegmentInfoMetadataAndFeatures(segment_info));
+
+ auto* metadata = segment_info.mutable_model_metadata();
+ metadata->set_time_unit(proto::DAY);
+ EXPECT_EQ(
+ metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateSegmentInfoMetadataAndFeatures(segment_info));
+
+ // Verify adding a single features adds new requirements.
+ auto* feature1 = metadata->add_features();
+ EXPECT_EQ(
+ metadata_utils::ValidationResult::kSignalTypeInvalid,
+ metadata_utils::ValidateSegmentInfoMetadataAndFeatures(segment_info));
+
+ // Fully flesh out an example feature and verify validation starts working
+ // again.
+ feature1->set_type(proto::SignalType::USER_ACTION);
+ feature1->set_name_hash(base::HashMetricName("some user action"));
+ feature1->set_aggregation(proto::Aggregation::COUNT);
+ feature1->set_bucket_count(1);
+ feature1->set_tensor_length(1);
+ EXPECT_EQ(
+ metadata_utils::ValidationResult::kValidationSuccess,
+ metadata_utils::ValidateSegmentInfoMetadataAndFeatures(segment_info));
+}
+
+TEST_F(MetadataUtilsTest, SetFeatureNameHashesFromName) {
+ // No crashes should happen if there are no features.
+ proto::SegmentationModelMetadata empty;
+ metadata_utils::SetFeatureNameHashesFromName(&empty);
+
+ // Ensure that the name hash is overwritten.
+ proto::SegmentationModelMetadata one_feature_both_set;
+ auto* feature1 = one_feature_both_set.add_features();
+ feature1->set_name("both set");
+ feature1->set_name_hash(base::HashMetricName("both set"));
+ metadata_utils::SetFeatureNameHashesFromName(&one_feature_both_set);
+ EXPECT_EQ(1, one_feature_both_set.features_size());
+ EXPECT_EQ("both set", one_feature_both_set.features(0).name());
+ EXPECT_EQ(base::HashMetricName("both set"),
+ one_feature_both_set.features(0).name_hash());
+
+ // Ensure that the name hash is overwritten if it is incorrect.
+ proto::SegmentationModelMetadata one_feature_both_set_hash_incorrect;
+ auto* feature2 = one_feature_both_set_hash_incorrect.add_features();
+ feature2->set_name("both set");
+ feature2->set_name_hash(base::HashMetricName("INCORRECT NAME HASH"));
+ metadata_utils::SetFeatureNameHashesFromName(
+ &one_feature_both_set_hash_incorrect);
+ EXPECT_EQ(1, one_feature_both_set_hash_incorrect.features_size());
+ EXPECT_EQ("both set", one_feature_both_set_hash_incorrect.features(0).name());
+ EXPECT_EQ(base::HashMetricName("both set"),
+ one_feature_both_set_hash_incorrect.features(0).name_hash());
+
+ // Ensure that the name hash is set from the name.
+ proto::SegmentationModelMetadata one_feature_name_set;
+ auto* feature3 = one_feature_name_set.add_features();
+ feature3->set_name("only name set");
+ metadata_utils::SetFeatureNameHashesFromName(&one_feature_name_set);
+ EXPECT_EQ(1, one_feature_name_set.features_size());
+ EXPECT_EQ("only name set", one_feature_name_set.features(0).name());
+ EXPECT_EQ(base::HashMetricName("only name set"),
+ one_feature_name_set.features(0).name_hash());
+
+ // Name hash should be overwritten with the hash of the empty string in the
+ // case of only the name hash having been set.
+ proto::SegmentationModelMetadata one_feature_name_hash_set;
+ auto* feature4 = one_feature_name_hash_set.add_features();
+ feature4->set_name_hash(base::HashMetricName("only name hash set"));
+ metadata_utils::SetFeatureNameHashesFromName(&one_feature_name_hash_set);
+ EXPECT_EQ(1, one_feature_name_hash_set.features_size());
+ EXPECT_EQ("", one_feature_name_hash_set.features(0).name());
+ EXPECT_EQ(base::HashMetricName(""),
+ one_feature_name_hash_set.features(0).name_hash());
+
+ // When neither name nor name hash is set, we should still overwrite the name
+ // hash with the hash of the empty string.
+ proto::SegmentationModelMetadata one_feature_nothing_set;
+ // Add feature and set a different field to ensure it is added.
+ auto* feature5 = one_feature_nothing_set.add_features();
+ feature5->set_type(proto::SignalType::USER_ACTION);
+ metadata_utils::SetFeatureNameHashesFromName(&one_feature_nothing_set);
+ EXPECT_EQ(1, one_feature_nothing_set.features_size());
+ EXPECT_EQ("", one_feature_nothing_set.features(0).name());
+ EXPECT_EQ(base::HashMetricName(""),
+ one_feature_nothing_set.features(0).name_hash());
+
+ // Ensure that the name hash is set for all features.
+ proto::SegmentationModelMetadata multiple_features;
+ auto* multifeature1 = multiple_features.add_features();
+ multifeature1->set_name("first multi");
+ auto* multifeature2 = multiple_features.add_features();
+ multifeature2->set_name("second multi");
+ metadata_utils::SetFeatureNameHashesFromName(&multiple_features);
+ EXPECT_EQ(2, multiple_features.features_size());
+ EXPECT_EQ("first multi", multiple_features.features(0).name());
+ EXPECT_EQ(base::HashMetricName("first multi"),
+ multiple_features.features(0).name_hash());
+ EXPECT_EQ("second multi", multiple_features.features(1).name());
+ EXPECT_EQ(base::HashMetricName("second multi"),
+ multiple_features.features(1).name_hash());
+}
+
+TEST_F(MetadataUtilsTest, HasFreshResults) {
+ proto::SegmentInfo segment_info;
+ // No result.
+ EXPECT_FALSE(metadata_utils::HasFreshResults(segment_info));
+
+ auto* metadata = segment_info.mutable_model_metadata();
+ metadata->set_result_time_to_live(1);
+ metadata->set_time_unit(proto::DAY);
+
+ // Stale results.
+ auto* prediction_result = segment_info.mutable_prediction_result();
+ base::Time result_time = base::Time::Now() - base::TimeDelta::FromDays(3);
+ prediction_result->set_timestamp_us(
+ result_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ EXPECT_FALSE(metadata_utils::HasFreshResults(segment_info));
+
+ // Fresh results.
+ result_time = base::Time::Now() - base::TimeDelta::FromHours(2);
+ prediction_result->set_timestamp_us(
+ result_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ EXPECT_TRUE(metadata_utils::HasFreshResults(segment_info));
+}
+
+TEST_F(MetadataUtilsTest, HasExpiredOrUnavailableResult) {
+ proto::SegmentInfo segment_info;
+ auto* metadata = segment_info.mutable_model_metadata();
+ metadata->set_result_time_to_live(7);
+ metadata->set_time_unit(proto::TimeUnit::DAY);
+
+ // No result.
+ EXPECT_TRUE(metadata_utils::HasExpiredOrUnavailableResult(segment_info));
+
+ // Unexpired result.
+ auto* prediction_result = segment_info.mutable_prediction_result();
+ base::Time result_time = base::Time::Now() - base::TimeDelta::FromDays(3);
+ prediction_result->set_timestamp_us(
+ result_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ EXPECT_FALSE(metadata_utils::HasExpiredOrUnavailableResult(segment_info));
+
+ // Expired result.
+ result_time = base::Time::Now() - base::TimeDelta::FromDays(30);
+ prediction_result->set_timestamp_us(
+ result_time.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ EXPECT_TRUE(metadata_utils::HasExpiredOrUnavailableResult(segment_info));
+}
+
+TEST_F(MetadataUtilsTest, GetTimeUnit) {
+ proto::SegmentationModelMetadata metadata;
+ metadata.set_time_unit(proto::TimeUnit::DAY);
+ EXPECT_EQ(base::TimeDelta::FromDays(1),
+ metadata_utils::GetTimeUnit(metadata));
+
+ metadata.set_time_unit(proto::TimeUnit::HOUR);
+ EXPECT_EQ(base::TimeDelta::FromHours(1),
+ metadata_utils::GetTimeUnit(metadata));
+
+ metadata.set_time_unit(proto::TimeUnit::MINUTE);
+ EXPECT_EQ(base::TimeDelta::FromMinutes(1),
+ metadata_utils::GetTimeUnit(metadata));
+
+ metadata.set_time_unit(proto::TimeUnit::SECOND);
+ EXPECT_EQ(base::TimeDelta::FromSeconds(1),
+ metadata_utils::GetTimeUnit(metadata));
+
+ metadata.set_time_unit(proto::TimeUnit::WEEK);
+ EXPECT_EQ(base::TimeDelta::FromDays(7),
+ metadata_utils::GetTimeUnit(metadata));
+
+ metadata.set_time_unit(proto::TimeUnit::MONTH);
+ EXPECT_EQ(base::TimeDelta::FromDays(30),
+ metadata_utils::GetTimeUnit(metadata));
+
+ metadata.set_time_unit(proto::TimeUnit::YEAR);
+ EXPECT_EQ(base::TimeDelta::FromDays(365),
+ metadata_utils::GetTimeUnit(metadata));
+}
+
+TEST_F(MetadataUtilsTest, SignalTypeToSignalKind) {
+ EXPECT_EQ(
+ SignalKey::Kind::USER_ACTION,
+ metadata_utils::SignalTypeToSignalKind(proto::SignalType::USER_ACTION));
+ EXPECT_EQ(SignalKey::Kind::HISTOGRAM_ENUM,
+ metadata_utils::SignalTypeToSignalKind(
+ proto::SignalType::HISTOGRAM_ENUM));
+ EXPECT_EQ(SignalKey::Kind::HISTOGRAM_VALUE,
+ metadata_utils::SignalTypeToSignalKind(
+ proto::SignalType::HISTOGRAM_VALUE));
+ EXPECT_EQ(SignalKey::Kind::UNKNOWN,
+ metadata_utils::SignalTypeToSignalKind(
+ proto::SignalType::UNKNOWN_SIGNAL_TYPE));
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/mock_signal_database.cc b/chromium/components/segmentation_platform/internal/database/mock_signal_database.cc
new file mode 100644
index 00000000000..d0091cf9f8f
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/mock_signal_database.cc
@@ -0,0 +1,13 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/database/mock_signal_database.h"
+
+namespace segmentation_platform {
+
+MockSignalDatabase::MockSignalDatabase() = default;
+
+MockSignalDatabase::~MockSignalDatabase() = default;
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/mock_signal_database.h b/chromium/components/segmentation_platform/internal/database/mock_signal_database.h
new file mode 100644
index 00000000000..31e3191989b
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/mock_signal_database.h
@@ -0,0 +1,57 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_MOCK_SIGNAL_DATABASE_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_MOCK_SIGNAL_DATABASE_H_
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+
+// A mock of the SignalDatabase.
+class MockSignalDatabase : public SignalDatabase {
+ public:
+ MockSignalDatabase();
+ ~MockSignalDatabase() override;
+
+ MOCK_METHOD(void, Initialize, (SignalDatabase::SuccessCallback), (override));
+ MOCK_METHOD(void,
+ WriteSample,
+ (proto::SignalType,
+ uint64_t,
+ absl::optional<int32_t>,
+ SignalDatabase::SuccessCallback),
+ (override));
+ MOCK_METHOD(void,
+ GetSamples,
+ (proto::SignalType,
+ uint64_t,
+ base::Time,
+ base::Time,
+ SignalDatabase::SamplesCallback),
+ (override));
+ MOCK_METHOD(void,
+ DeleteSamples,
+ (proto::SignalType,
+ uint64_t,
+ base::Time,
+ SignalDatabase::SuccessCallback),
+ (override));
+ MOCK_METHOD(void,
+ CompactSamplesForDay,
+ (proto::SignalType,
+ uint64_t,
+ base::Time,
+ SignalDatabase::SuccessCallback),
+ (override));
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_MOCK_SIGNAL_DATABASE_H_
diff --git a/chromium/components/segmentation_platform/internal/database/mock_signal_storage_config.cc b/chromium/components/segmentation_platform/internal/database/mock_signal_storage_config.cc
new file mode 100644
index 00000000000..25ce3ddb8ea
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/mock_signal_storage_config.cc
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/database/mock_signal_storage_config.h"
+
+#include "components/segmentation_platform/internal/database/signal_storage_config.h"
+
+namespace segmentation_platform {
+
+MockSignalStorageConfig::MockSignalStorageConfig()
+ : SignalStorageConfig(nullptr, nullptr) {}
+
+MockSignalStorageConfig::~MockSignalStorageConfig() = default;
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/mock_signal_storage_config.h b/chromium/components/segmentation_platform/internal/database/mock_signal_storage_config.h
new file mode 100644
index 00000000000..38f8ec6a85b
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/mock_signal_storage_config.h
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_MOCK_SIGNAL_STORAGE_CONFIG_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_MOCK_SIGNAL_STORAGE_CONFIG_H_
+
+#include <set>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "components/segmentation_platform/internal/database/signal_storage_config.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace segmentation_platform {
+
+// A mock of the SignalStorageConfig.
+class MockSignalStorageConfig : public SignalStorageConfig {
+ public:
+ using SignalType = proto::SignalType;
+ using SignalIdentifier = std::pair<uint64_t, SignalType>;
+ using CleanupItem = std::tuple<uint64_t, SignalType, base::Time>;
+
+ MockSignalStorageConfig();
+ ~MockSignalStorageConfig() override;
+
+ MOCK_METHOD(bool,
+ MeetsSignalCollectionRequirement,
+ (const proto::SegmentationModelMetadata& model_metadata),
+ (override));
+
+ MOCK_METHOD(void,
+ OnSignalCollectionStarted,
+ (const proto::SegmentationModelMetadata& model_metadata),
+ (override));
+
+ MOCK_METHOD(void,
+ GetSignalsForCleanup,
+ (const std::set<SignalIdentifier>& known_signals,
+ std::vector<CleanupItem>& result),
+ (const override));
+
+ MOCK_METHOD(void,
+ UpdateSignalsForCleanup,
+ (const std::vector<CleanupItem>& signals),
+ (override));
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_MOCK_SIGNAL_STORAGE_CONFIG_H_
diff --git a/chromium/components/segmentation_platform/internal/database/segment_info_database.cc b/chromium/components/segmentation_platform/internal/database/segment_info_database.cc
new file mode 100644
index 00000000000..f35e35cd87a
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/segment_info_database.cc
@@ -0,0 +1,149 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/database/segment_info_database.h"
+
+#include "base/callback_helpers.h"
+#include "base/containers/contains.h"
+#include "base/strings/string_number_conversions.h"
+
+namespace segmentation_platform {
+
+namespace {
+
+std::string ToString(OptimizationTarget segment_id) {
+ return base::NumberToString(static_cast<int>(segment_id));
+}
+
+} // namespace
+
+SegmentInfoDatabase::SegmentInfoDatabase(
+ std::unique_ptr<SegmentInfoProtoDb> database)
+ : database_(std::move(database)) {}
+
+SegmentInfoDatabase::~SegmentInfoDatabase() = default;
+
+void SegmentInfoDatabase::Initialize(SuccessCallback callback) {
+ database_->Init(
+ leveldb_proto::CreateSimpleOptions(),
+ base::BindOnce(&SegmentInfoDatabase::OnDatabaseInitialized,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void SegmentInfoDatabase::GetAllSegmentInfo(
+ MultipleSegmentInfoCallback callback) {
+ database_->LoadEntries(
+ base::BindOnce(&SegmentInfoDatabase::OnMultipleSegmentInfoLoaded,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void SegmentInfoDatabase::OnMultipleSegmentInfoLoaded(
+ MultipleSegmentInfoCallback callback,
+ bool success,
+ std::unique_ptr<std::vector<proto::SegmentInfo>> all_infos) {
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>> pairs;
+ if (success && all_infos) {
+ for (auto& info : *all_infos.get()) {
+ pairs.emplace_back(std::make_pair(info.segment_id(), std::move(info)));
+ }
+ }
+
+ std::move(callback).Run(pairs);
+}
+
+void SegmentInfoDatabase::GetSegmentInfoForSegments(
+ const std::vector<OptimizationTarget>& segment_ids,
+ MultipleSegmentInfoCallback callback) {
+ std::vector<std::string> keys;
+ for (OptimizationTarget target : segment_ids)
+ keys.emplace_back(ToString(target));
+
+ database_->LoadEntriesWithFilter(
+ base::BindRepeating(
+ [](const std::vector<std::string>& key_dict, const std::string& key) {
+ return base::Contains(key_dict, key);
+ },
+ keys),
+ base::BindOnce(&SegmentInfoDatabase::OnMultipleSegmentInfoLoaded,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void SegmentInfoDatabase::GetSegmentInfo(OptimizationTarget segment_id,
+ SegmentInfoCallback callback) {
+ database_->GetEntry(
+ ToString(segment_id),
+ base::BindOnce(&SegmentInfoDatabase::OnGetSegmentInfo,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void SegmentInfoDatabase::OnGetSegmentInfo(
+ SegmentInfoCallback callback,
+ bool success,
+ std::unique_ptr<proto::SegmentInfo> info) {
+ std::move(callback).Run(success && info ? absl::make_optional(*info)
+ : absl::nullopt);
+}
+
+void SegmentInfoDatabase::UpdateSegment(
+ OptimizationTarget segment_id,
+ absl::optional<proto::SegmentInfo> segment_info,
+ SuccessCallback callback) {
+ auto entries_to_save = std::make_unique<
+ std::vector<std::pair<std::string, proto::SegmentInfo>>>();
+ auto keys_to_delete = std::make_unique<std::vector<std::string>>();
+ if (segment_info.has_value()) {
+ entries_to_save->emplace_back(
+ std::make_pair(ToString(segment_id), segment_info.value()));
+ } else {
+ keys_to_delete->emplace_back(ToString(segment_id));
+ }
+
+ database_->UpdateEntries(std::move(entries_to_save),
+ std::move(keys_to_delete), std::move(callback));
+}
+
+void SegmentInfoDatabase::SaveSegmentResult(
+ OptimizationTarget segment_id,
+ absl::optional<proto::PredictionResult> result,
+ SuccessCallback callback) {
+ GetSegmentInfo(
+ segment_id,
+ base::BindOnce(&SegmentInfoDatabase::OnGetSegmentInfoForUpdatingResults,
+ weak_ptr_factory_.GetWeakPtr(), result,
+ std::move(callback)));
+}
+
+void SegmentInfoDatabase::OnGetSegmentInfoForUpdatingResults(
+ absl::optional<proto::PredictionResult> result,
+ SuccessCallback callback,
+ absl::optional<proto::SegmentInfo> segment_info) {
+ // Ignore results if the metadata no longer exists.
+ if (!segment_info.has_value()) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ // Update results.
+ if (result.has_value()) {
+ segment_info->mutable_prediction_result()->CopyFrom(*result);
+ } else {
+ segment_info->clear_prediction_result();
+ }
+
+ auto entries_to_save = std::make_unique<
+ std::vector<std::pair<std::string, proto::SegmentInfo>>>();
+ entries_to_save->emplace_back(std::make_pair(
+ ToString(segment_info->segment_id()), std::move(segment_info.value())));
+ database_->UpdateEntries(std::move(entries_to_save),
+ std::make_unique<std::vector<std::string>>(),
+ std::move(callback));
+}
+
+void SegmentInfoDatabase::OnDatabaseInitialized(
+ SuccessCallback callback,
+ leveldb_proto::Enums::InitStatus status) {
+ std::move(callback).Run(status == leveldb_proto::Enums::InitStatus::kOK);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/segment_info_database.h b/chromium/components/segmentation_platform/internal/database/segment_info_database.h
new file mode 100644
index 00000000000..9687c021895
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/segment_info_database.h
@@ -0,0 +1,95 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SEGMENT_INFO_DATABASE_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SEGMENT_INFO_DATABASE_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "components/leveldb_proto/public/proto_database.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+using optimization_guide::proto::OptimizationTarget;
+
+namespace segmentation_platform {
+
+namespace proto {
+class SegmentInfo;
+class PredictionResult;
+} // namespace proto
+
+// Represents a DB layer that stores model metadata and prediction results to
+// the disk.
+class SegmentInfoDatabase {
+ public:
+ using SuccessCallback = base::OnceCallback<void(bool)>;
+ using MultipleSegmentInfoCallback = base::OnceCallback<void(
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>)>;
+ using SegmentInfoCallback =
+ base::OnceCallback<void(absl::optional<proto::SegmentInfo>)>;
+ using SegmentInfoProtoDb = leveldb_proto::ProtoDatabase<proto::SegmentInfo>;
+
+ explicit SegmentInfoDatabase(std::unique_ptr<SegmentInfoProtoDb> database);
+ virtual ~SegmentInfoDatabase();
+
+ // Disallow copy/assign.
+ SegmentInfoDatabase(const SegmentInfoDatabase&) = delete;
+ SegmentInfoDatabase& operator=(const SegmentInfoDatabase&) = delete;
+
+ virtual void Initialize(SuccessCallback callback);
+
+ // Convenient method to return combined info for all the segments in the
+ // database.
+ virtual void GetAllSegmentInfo(MultipleSegmentInfoCallback callback);
+
+ // Called to get metadata for a given list of segments.
+ virtual void GetSegmentInfoForSegments(
+ const std::vector<OptimizationTarget>& segment_ids,
+ MultipleSegmentInfoCallback callback);
+
+ // Called to get the metadata for a given segment.
+ virtual void GetSegmentInfo(OptimizationTarget segment_id,
+ SegmentInfoCallback callback);
+
+ // Called to save or update metadata for a segment. The previous data is
+ // overwritten. If |segment_info| is empty, the segment will be deleted.
+ // TODO(shaktisahu): How does the client know if a segment is to be deleted?
+ virtual void UpdateSegment(OptimizationTarget segment_id,
+ absl::optional<proto::SegmentInfo> segment_info,
+ SuccessCallback callback);
+
+ // Called to write the model execution results for a given segment. It will
+ // first read the currently stored result, and then overwrite it with
+ // |result|. If |result| is null, the existing result will be deleted.
+ virtual void SaveSegmentResult(OptimizationTarget segment_id,
+ absl::optional<proto::PredictionResult> result,
+ SuccessCallback callback);
+
+ private:
+ void OnDatabaseInitialized(SuccessCallback callback,
+ leveldb_proto::Enums::InitStatus status);
+ void OnMultipleSegmentInfoLoaded(
+ MultipleSegmentInfoCallback callback,
+ bool success,
+ std::unique_ptr<std::vector<proto::SegmentInfo>> all_infos);
+ void OnGetSegmentInfo(SegmentInfoCallback callback,
+ bool success,
+ std::unique_ptr<proto::SegmentInfo> info);
+ void OnGetSegmentInfoForUpdatingResults(
+ absl::optional<proto::PredictionResult> result,
+ SuccessCallback callback,
+ absl::optional<proto::SegmentInfo> segment_info);
+
+ std::unique_ptr<SegmentInfoProtoDb> database_;
+
+ base::WeakPtrFactory<SegmentInfoDatabase> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SEGMENT_INFO_DATABASE_H_
diff --git a/chromium/components/segmentation_platform/internal/database/segment_info_database_unittest.cc b/chromium/components/segmentation_platform/internal/database/segment_info_database_unittest.cc
new file mode 100644
index 00000000000..bedc2c898d4
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/segment_info_database_unittest.cc
@@ -0,0 +1,238 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/database/segment_info_database.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "base/test/task_environment.h"
+#include "components/leveldb_proto/public/proto_database.h"
+#include "components/leveldb_proto/testing/fake_db.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using InitStatus = leveldb_proto::Enums::InitStatus;
+
+namespace segmentation_platform {
+
+namespace {
+
+// Test Ids.
+const OptimizationTarget kSegmentId =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+const OptimizationTarget kSegmentId2 =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE;
+
+std::string ToString(OptimizationTarget segment_id) {
+ return base::NumberToString(static_cast<int>(segment_id));
+}
+
+proto::SegmentInfo CreateSegment(OptimizationTarget segment_id,
+ absl::optional<int> result = absl::nullopt) {
+ proto::SegmentInfo info;
+ info.set_segment_id(segment_id);
+
+ if (result.has_value()) {
+ info.mutable_prediction_result()->set_result(result.value());
+ }
+ return info;
+}
+
+} // namespace
+
+class SegmentInfoDatabaseTest : public testing::Test {
+ public:
+ SegmentInfoDatabaseTest() = default;
+ ~SegmentInfoDatabaseTest() override = default;
+
+ void OnGetAllSegments(
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>> entries) {
+ get_all_segment_result_ = entries;
+ }
+
+ void OnGetSegment(absl::optional<proto::SegmentInfo> result) {
+ get_segment_result_ = result;
+ }
+
+ protected:
+ void SetUpDB() {
+ DCHECK(!db_);
+ DCHECK(!segment_db_);
+
+ auto db = std::make_unique<leveldb_proto::test::FakeDB<proto::SegmentInfo>>(
+ &db_entries_);
+ db_ = db.get();
+ segment_db_ = std::make_unique<SegmentInfoDatabase>(std::move(db));
+ }
+
+ void TearDown() override {
+ db_entries_.clear();
+ db_ = nullptr;
+ segment_db_.reset();
+ }
+
+ void VerifyDb(std::vector<OptimizationTarget> expected_ids) {
+ EXPECT_EQ(expected_ids.size(), db_entries_.size());
+ for (auto segment_id : expected_ids)
+ EXPECT_TRUE(db_entries_.find(ToString(segment_id)) != db_entries_.end());
+ }
+
+ void WriteResult(OptimizationTarget segment_id,
+ absl::optional<float> result) {
+ proto::PredictionResult prediction_result;
+ if (result.has_value())
+ prediction_result.set_result(result.value());
+
+ segment_db_->SaveSegmentResult(segment_id,
+ result.has_value()
+ ? absl::make_optional(prediction_result)
+ : absl::nullopt,
+ base::DoNothing());
+ db_->GetCallback(true);
+ db_->UpdateCallback(true);
+ }
+
+ void VerifyResult(OptimizationTarget segment_id,
+ absl::optional<float> result) {
+ segment_db_->GetSegmentInfo(
+ segment_id, base::BindOnce(&SegmentInfoDatabaseTest::OnGetSegment,
+ base::Unretained(this)));
+ db_->GetCallback(true);
+
+ EXPECT_EQ(segment_id, get_segment_result_->segment_id());
+ EXPECT_EQ(result.has_value(), get_segment_result_->has_prediction_result());
+ if (result.has_value()) {
+ EXPECT_EQ(result.value(),
+ get_segment_result_->prediction_result().result());
+ }
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ get_all_segment_result_;
+ absl::optional<proto::SegmentInfo> get_segment_result_;
+ std::map<std::string, proto::SegmentInfo> db_entries_;
+ leveldb_proto::test::FakeDB<proto::SegmentInfo>* db_{nullptr};
+ std::unique_ptr<SegmentInfoDatabase> segment_db_;
+};
+
+TEST_F(SegmentInfoDatabaseTest, Get) {
+ // Initialize DB with one entry.
+ db_entries_.insert(
+ std::make_pair(ToString(kSegmentId), CreateSegment(kSegmentId)));
+ SetUpDB();
+
+ segment_db_->Initialize(base::DoNothing());
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ VerifyDb({kSegmentId});
+
+ // Get all segments.
+ segment_db_->GetAllSegmentInfo(base::BindOnce(
+ &SegmentInfoDatabaseTest::OnGetAllSegments, base::Unretained(this)));
+ db_->LoadCallback(true);
+ EXPECT_EQ(1u, get_all_segment_result_.size());
+
+ // Get a single segment.
+ segment_db_->GetSegmentInfo(
+ kSegmentId, base::BindOnce(&SegmentInfoDatabaseTest::OnGetSegment,
+ base::Unretained(this)));
+ db_->GetCallback(true);
+ EXPECT_TRUE(get_segment_result_.has_value());
+ EXPECT_EQ(kSegmentId, get_segment_result_->segment_id());
+}
+
+TEST_F(SegmentInfoDatabaseTest, Update) {
+ // Initialize DB with one entry.
+ db_entries_.insert(
+ std::make_pair(ToString(kSegmentId), CreateSegment(kSegmentId)));
+ SetUpDB();
+
+ segment_db_->Initialize(base::DoNothing());
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+
+ // Delete a segment.
+ segment_db_->UpdateSegment(kSegmentId, absl::nullopt, base::DoNothing());
+ db_->UpdateCallback(true);
+ VerifyDb({});
+
+ // Insert a segment and verify.
+ segment_db_->UpdateSegment(kSegmentId, CreateSegment(kSegmentId),
+ base::DoNothing());
+ db_->UpdateCallback(true);
+ VerifyDb({kSegmentId});
+
+ // Insert another segment and verify.
+ segment_db_->UpdateSegment(kSegmentId2, CreateSegment(kSegmentId2),
+ base::DoNothing());
+ db_->UpdateCallback(true);
+ VerifyDb({kSegmentId, kSegmentId2});
+
+ // Verify GetSegmentInfoForSegments.
+ segment_db_->GetSegmentInfoForSegments(
+ {kSegmentId2}, base::BindOnce(&SegmentInfoDatabaseTest::OnGetAllSegments,
+ base::Unretained(this)));
+ db_->LoadCallback(true);
+ EXPECT_EQ(1u, get_all_segment_result_.size());
+ EXPECT_EQ(kSegmentId2, get_all_segment_result_[0].first);
+
+ segment_db_->GetSegmentInfoForSegments(
+ {kSegmentId}, base::BindOnce(&SegmentInfoDatabaseTest::OnGetAllSegments,
+ base::Unretained(this)));
+ db_->LoadCallback(true);
+ EXPECT_EQ(1u, get_all_segment_result_.size());
+ EXPECT_EQ(kSegmentId, get_all_segment_result_[0].first);
+
+ segment_db_->GetSegmentInfoForSegments(
+ {kSegmentId, kSegmentId2},
+ base::BindOnce(&SegmentInfoDatabaseTest::OnGetAllSegments,
+ base::Unretained(this)));
+ db_->LoadCallback(true);
+ EXPECT_EQ(2u, get_all_segment_result_.size());
+ EXPECT_EQ(kSegmentId, get_all_segment_result_[0].first);
+ EXPECT_EQ(kSegmentId2, get_all_segment_result_[1].first);
+}
+
+TEST_F(SegmentInfoDatabaseTest, WriteResult) {
+ // Initialize DB with one entry.
+ db_entries_.insert(
+ std::make_pair(ToString(kSegmentId), CreateSegment(kSegmentId)));
+ SetUpDB();
+
+ segment_db_->Initialize(base::DoNothing());
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+
+ // Update results and verify.
+ WriteResult(kSegmentId, 0.4f);
+ VerifyResult(kSegmentId, 0.4f);
+
+ // Overwrite results and verify.
+ WriteResult(kSegmentId, 0.9f);
+ VerifyResult(kSegmentId, 0.9f);
+
+ // Clear results and verify.
+ WriteResult(kSegmentId, absl::nullopt);
+ VerifyResult(kSegmentId, absl::nullopt);
+}
+
+TEST_F(SegmentInfoDatabaseTest, WriteResultForTwoSegments) {
+ // Initialize DB with two entries.
+ db_entries_.insert(
+ std::make_pair(ToString(kSegmentId), CreateSegment(kSegmentId)));
+ db_entries_.insert(
+ std::make_pair(ToString(kSegmentId2), CreateSegment(kSegmentId2)));
+ SetUpDB();
+
+ segment_db_->Initialize(base::DoNothing());
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+
+ // Update results for first segment.
+ WriteResult(kSegmentId, 0.4f);
+
+ // Update results for second segment.
+ WriteResult(kSegmentId2, 0.9f);
+
+ // Verify results for both segments.
+ VerifyResult(kSegmentId, 0.4f);
+ VerifyResult(kSegmentId2, 0.9f);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/signal_database.h b/chromium/components/segmentation_platform/internal/database/signal_database.h
new file mode 100644
index 00000000000..9cfd080b32a
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_database.h
@@ -0,0 +1,70 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_DATABASE_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_DATABASE_H_
+
+#include <cstdint>
+#include <utility>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+
+// Responsible for storing histogram signals and user action events in a
+// database. The signal samples are lazily bucketed into daily buckets for
+// efficient storage and retrieval. A periodic job is responsible for running
+// the compaction and deletion of old entries.
+class SignalDatabase {
+ public:
+ using SuccessCallback = base::OnceCallback<void(bool)>;
+ using Sample = std::pair<base::Time, int32_t>;
+ using SamplesCallback = base::OnceCallback<void(std::vector<Sample>)>;
+
+ virtual ~SignalDatabase() = default;
+
+ // Called to initialize the database. Must be called before other methods.
+ virtual void Initialize(SuccessCallback callback) = 0;
+
+ // Called to write UMA events to the database. Sample timestamps are converted
+ // to delta from UTC midnight for efficient storage.
+ virtual void WriteSample(proto::SignalType signal_type,
+ uint64_t name_hash,
+ absl::optional<int32_t> value,
+ SuccessCallback callback) = 0;
+
+ // Called to get signals collected between any two timestamps. The samples are
+ // returned in the |callback| as a list of pairs containing signal timestamp
+ // and and an optional value.
+ virtual void GetSamples(proto::SignalType signal_type,
+ uint64_t name_hash,
+ base::Time start_time,
+ base::Time end_time,
+ SamplesCallback callback) = 0;
+
+ // Called to delete database entries having end time earlier than |end_time|.
+ virtual void DeleteSamples(proto::SignalType signal_type,
+ uint64_t name_hash,
+ base::Time end_time,
+ SuccessCallback callback) = 0;
+
+ // Called to compact the signals collected for the given day. Do not run this
+ // for the current day as it might lead to read/write race condition. Meant to
+ // be used for compacting the entries for the previous day from a background
+ // job. Nevertheless, the database will work correctly without the need for
+ // any compaction. |time| is used for finding the associated day.
+ virtual void CompactSamplesForDay(proto::SignalType signal_type,
+ uint64_t name_hash,
+ base::Time time,
+ SuccessCallback callback) = 0;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_DATABASE_H_
diff --git a/chromium/components/segmentation_platform/internal/database/signal_database_impl.cc b/chromium/components/segmentation_platform/internal/database/signal_database_impl.cc
new file mode 100644
index 00000000000..d6582502034
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_database_impl.cc
@@ -0,0 +1,277 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/database/signal_database_impl.h"
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/clock.h"
+#include "base/time/time.h"
+#include "base/trace_event/typed_macros.h"
+#include "components/leveldb_proto/public/proto_database.h"
+#include "components/segmentation_platform/internal/database/metadata_utils.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
+#include "components/segmentation_platform/internal/proto/signal.pb.h"
+#include "components/segmentation_platform/internal/stats.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+namespace {
+
+// TODO(shaktisahu): May be make this a class member for ease of testing.
+bool FilterKeyBasedOnRange(proto::SignalType signal_type,
+ uint64_t name_hash,
+ base::Time end_time,
+ base::Time start_time,
+ const std::string& signal_key) {
+ DCHECK(start_time <= end_time);
+ SignalKey key;
+ SignalKey::FromBinary(signal_key, &key);
+ DCHECK(key.IsValid());
+ if (key.kind() != metadata_utils::SignalTypeToSignalKind(signal_type) ||
+ key.name_hash() != name_hash) {
+ return false;
+ }
+
+ // Check if the key range is contained within the given range.
+ return key.range_end() <= end_time && start_time <= key.range_start();
+}
+
+} // namespace
+
+SignalDatabaseImpl::SignalDatabaseImpl(std::unique_ptr<SignalProtoDb> database,
+ base::Clock* clock)
+ : database_(std::move(database)), clock_(clock) {}
+
+SignalDatabaseImpl::~SignalDatabaseImpl() = default;
+
+void SignalDatabaseImpl::Initialize(SuccessCallback callback) {
+ database_->Init(
+ leveldb_proto::CreateSimpleOptions(),
+ base::BindOnce(&SignalDatabaseImpl::OnDatabaseInitialized,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void SignalDatabaseImpl::WriteSample(proto::SignalType signal_type,
+ uint64_t name_hash,
+ absl::optional<int32_t> value,
+ SuccessCallback callback) {
+ DCHECK(initialized_);
+ base::Time timestamp = clock_->Now();
+ SignalKey key(metadata_utils::SignalTypeToSignalKind(signal_type), name_hash,
+ timestamp, timestamp);
+
+ proto::SignalData signal_data;
+ // If there is another sample with the same signal key, collate both into a
+ // single DB entry.
+ if (recently_added_signals_.find(key) != recently_added_signals_.end())
+ signal_data = recently_added_signals_[key];
+
+ proto::Sample* sample = signal_data.add_samples();
+ if (value.has_value())
+ sample->set_value(value.value());
+
+ // Convert to delta from UTC midnight. This results in smaller values thereby
+ // requiring less storage space in the DB.
+ base::TimeDelta midnight_delta = timestamp - timestamp.UTCMidnight();
+ sample->set_time_sec_delta(midnight_delta.InSeconds());
+
+ recently_added_signals_[key] = signal_data;
+
+ // Write as a new db entry.
+ auto entries_to_save = std::make_unique<
+ std::vector<std::pair<std::string, proto::SignalData>>>();
+ auto keys_to_delete = std::make_unique<std::vector<std::string>>();
+ entries_to_save->emplace_back(
+ std::make_pair(key.ToBinary(), std::move(signal_data)));
+ database_->UpdateEntries(std::move(entries_to_save),
+ std::move(keys_to_delete), std::move(callback));
+ CleanupStaleCachedEntries(timestamp);
+}
+
+void SignalDatabaseImpl::GetSamples(proto::SignalType signal_type,
+ uint64_t name_hash,
+ base::Time start_time,
+ base::Time end_time,
+ SamplesCallback callback) {
+ TRACE_EVENT("segmentation_platform", "SignalDatabaseImpl::GetSamples");
+ DCHECK(initialized_);
+ SignalKey dummy_key(metadata_utils::SignalTypeToSignalKind(signal_type),
+ name_hash, base::Time(), base::Time());
+ std::string key_prefix = dummy_key.GetPrefixInBinary();
+ database_->LoadKeysAndEntriesWithFilter(
+ base::BindRepeating(&FilterKeyBasedOnRange, signal_type, name_hash,
+ end_time, start_time),
+ leveldb::ReadOptions(), key_prefix,
+ base::BindOnce(&SignalDatabaseImpl::OnGetSamples,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+ start_time, end_time));
+}
+
+void SignalDatabaseImpl::OnGetSamples(
+ SamplesCallback callback,
+ base::Time start_time,
+ base::Time end_time,
+ bool success,
+ std::unique_ptr<std::map<std::string, proto::SignalData>> entries) {
+ TRACE_EVENT("segmentation_platform", "SignalDatabaseImpl::OnGetSamples");
+ std::vector<Sample> out;
+ if (!success || !entries) {
+ stats::RecordSignalDatabaseGetSamplesResult(/* success = */ false);
+ std::move(callback).Run(out);
+ return;
+ }
+ stats::RecordSignalDatabaseGetSamplesResult(/* success = */ true);
+
+ stats::RecordSignalDatabaseGetSamplesDatabaseEntryCount(
+ entries.get()->size());
+ for (const auto& pair : *entries.get()) {
+ SignalKey key;
+ SignalKey::FromBinary(pair.first, &key);
+ DCHECK(key.IsValid());
+ // TODO(shaktisahu): Remove DCHECK and collect UMA.
+ const auto& signal_data = pair.second;
+ base::Time midnight = key.range_start().UTCMidnight();
+ for (int i = 0; i < signal_data.samples_size(); ++i) {
+ const auto& sample = signal_data.samples(i);
+ base::Time timestamp =
+ midnight + base::TimeDelta::FromSeconds(sample.time_sec_delta());
+ if (timestamp < start_time || timestamp > end_time)
+ continue;
+
+ out.emplace_back(std::make_pair(timestamp, sample.value()));
+ }
+ }
+
+ stats::RecordSignalDatabaseGetSamplesSampleCount(out.size());
+ std::move(callback).Run(out);
+}
+
+void SignalDatabaseImpl::DeleteSamples(proto::SignalType signal_type,
+ uint64_t name_hash,
+ base::Time end_time,
+ SuccessCallback callback) {
+ TRACE_EVENT("segmentation_platform", "SignalDatabaseImpl::DeleteSamples");
+ DCHECK(initialized_);
+ SignalKey dummy_key(metadata_utils::SignalTypeToSignalKind(signal_type),
+ name_hash, base::Time(), base::Time());
+ std::string key_prefix = dummy_key.GetPrefixInBinary();
+ database_->LoadKeysAndEntriesWithFilter(
+ base::BindRepeating(&FilterKeyBasedOnRange, signal_type, name_hash,
+ end_time, base::Time()),
+ leveldb::ReadOptions(), key_prefix,
+ base::BindOnce(&SignalDatabaseImpl::OnGetSamplesForDeletion,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void SignalDatabaseImpl::OnGetSamplesForDeletion(
+ SuccessCallback callback,
+ bool success,
+ std::unique_ptr<std::map<std::string, proto::SignalData>> entries) {
+ TRACE_EVENT("segmentation_platform",
+ "SignalDatabaseImpl::OnGetSamplesForDeletion");
+ if (!success || !entries) {
+ std::move(callback).Run(success);
+ return;
+ }
+
+ auto entries_to_save = std::make_unique<
+ std::vector<std::pair<std::string, proto::SignalData>>>();
+ auto keys_to_delete = std::make_unique<std::vector<std::string>>();
+
+ // Collect the keys to be deleted.
+ for (const auto& pair : *entries.get()) {
+ keys_to_delete->emplace_back(pair.first);
+ }
+
+ // Write to DB.
+ database_->UpdateEntries(std::move(entries_to_save),
+ std::move(keys_to_delete), std::move(callback));
+}
+
+void SignalDatabaseImpl::CompactSamplesForDay(proto::SignalType signal_type,
+ uint64_t name_hash,
+ base::Time day_start_time,
+ SuccessCallback callback) {
+ TRACE_EVENT("segmentation_platform",
+ "SignalDatabaseImpl::CompactSamplesForDay");
+ DCHECK(initialized_);
+ // Compact the signals between 00:00:00AM to 23:59:59PM.
+ day_start_time = day_start_time.UTCMidnight();
+ base::Time day_end_time = day_start_time + base::TimeDelta::FromDays(1) -
+ base::TimeDelta::FromSeconds(1);
+ SignalKey compact_key(metadata_utils::SignalTypeToSignalKind(signal_type),
+ name_hash, day_end_time, day_start_time);
+ database_->LoadKeysAndEntriesWithFilter(
+ base::BindRepeating(&FilterKeyBasedOnRange, signal_type, name_hash,
+ day_end_time, day_start_time),
+ base::BindOnce(&SignalDatabaseImpl::OnGetSamplesForCompaction,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+ compact_key.ToBinary()));
+}
+
+void SignalDatabaseImpl::OnGetSamplesForCompaction(
+ SuccessCallback callback,
+ std::string compact_key,
+ bool success,
+ std::unique_ptr<std::map<std::string, proto::SignalData>> entries) {
+ TRACE_EVENT("segmentation_platform",
+ "SignalDatabaseImpl::OnGetSamplesForCompaction");
+ if (!success || !entries || entries->empty()) {
+ std::move(callback).Run(success);
+ return;
+ }
+
+ // We found one or more entries for the day. Let's compact them.
+ auto keys_to_delete = std::make_unique<std::vector<std::string>>();
+
+ // Aggregate samples under a new proto. Delete the old entries.
+ proto::SignalData compact;
+ for (const auto& pair : *entries.get()) {
+ const auto& signal_data = pair.second;
+ for (int i = 0; i < signal_data.samples_size(); i++) {
+ auto* new_sample = compact.add_samples();
+ new_sample->CopyFrom(signal_data.samples(i));
+ }
+
+ keys_to_delete->emplace_back(pair.first);
+ }
+
+ // Write to DB.
+ auto entries_to_save = std::make_unique<
+ std::vector<std::pair<std::string, proto::SignalData>>>();
+ entries_to_save->emplace_back(
+ std::make_pair(compact_key, std::move(compact)));
+ database_->UpdateEntries(std::move(entries_to_save),
+ std::move(keys_to_delete), std::move(callback));
+}
+
+void SignalDatabaseImpl::OnDatabaseInitialized(
+ SuccessCallback callback,
+ leveldb_proto::Enums::InitStatus status) {
+ initialized_ = status == leveldb_proto::Enums::InitStatus::kOK;
+ std::move(callback).Run(status == leveldb_proto::Enums::InitStatus::kOK);
+}
+
+void SignalDatabaseImpl::CleanupStaleCachedEntries(
+ base::Time current_timestamp) {
+ base::Time prev_second = current_timestamp - base::TimeDelta::FromSeconds(1);
+ std::vector<SignalKey> keys_to_delete;
+ for (const auto& entry : recently_added_signals_) {
+ if (entry.first.range_end() < prev_second)
+ keys_to_delete.emplace_back(entry.first);
+ }
+ for (const auto& cache_key : keys_to_delete)
+ recently_added_signals_.erase(cache_key);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/signal_database_impl.h b/chromium/components/segmentation_platform/internal/database/signal_database_impl.h
new file mode 100644
index 00000000000..da7c7ec44ed
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_database_impl.h
@@ -0,0 +1,113 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_DATABASE_IMPL_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_DATABASE_IMPL_H_
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "components/leveldb_proto/public/proto_database.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace base {
+class Clock;
+} // namespace base
+
+namespace segmentation_platform {
+namespace proto {
+class SignalData;
+} // namespace proto
+
+// Main implementation of SignalDatabase based on using a
+// leveldb_proto::ProtoDatabase<proto::SignalData> as storage.
+class SignalDatabaseImpl : public SignalDatabase {
+ public:
+ using SignalProtoDb = leveldb_proto::ProtoDatabase<proto::SignalData>;
+
+ SignalDatabaseImpl(std::unique_ptr<SignalProtoDb> database,
+ base::Clock* clock);
+ ~SignalDatabaseImpl() override;
+
+ // Disallow copy/assign.
+ SignalDatabaseImpl(const SignalDatabaseImpl&) = delete;
+ SignalDatabaseImpl& operator=(const SignalDatabaseImpl&) = delete;
+
+ // SignalDatabase overrides.
+ void Initialize(SuccessCallback callback) override;
+ void WriteSample(proto::SignalType signal_type,
+ uint64_t name_hash,
+ absl::optional<int32_t> value,
+ SuccessCallback callback) override;
+ void GetSamples(proto::SignalType signal_type,
+ uint64_t name_hash,
+ base::Time start_time,
+ base::Time end_time,
+ SamplesCallback callback) override;
+ void DeleteSamples(proto::SignalType signal_type,
+ uint64_t name_hash,
+ base::Time end_time,
+ SuccessCallback callback) override;
+ void CompactSamplesForDay(proto::SignalType signal_type,
+ uint64_t name_hash,
+ base::Time time,
+ SuccessCallback callback) override;
+
+ private:
+ void OnDatabaseInitialized(SuccessCallback callback,
+ leveldb_proto::Enums::InitStatus status);
+
+ void OnGetSamples(
+ SamplesCallback callback,
+ base::Time start_time,
+ base::Time end_time,
+ bool success,
+ std::unique_ptr<std::map<std::string, proto::SignalData>> entries);
+
+ void OnGetSamplesForCompaction(
+ SuccessCallback callback,
+ std::string compact_key,
+ bool success,
+ std::unique_ptr<std::map<std::string, proto::SignalData>> entries);
+
+ void OnGetSamplesForDeletion(
+ SuccessCallback callback,
+ bool success,
+ std::unique_ptr<std::map<std::string, proto::SignalData>> entries);
+
+ // Cleans up entries from |recently_added_signals_| cache that are more than 1
+ // second old.
+ void CleanupStaleCachedEntries(base::Time current_timestamp);
+
+ // The backing LevelDB proto database.
+ std::unique_ptr<SignalProtoDb> database_;
+
+ // Used for getting current time.
+ base::Clock* clock_;
+
+ // Whether or not initialization has been completed.
+ bool initialized_{false};
+
+ // A cache of recently added signals. Used for avoiding collisions between two
+ // signals if they end up generating the same signal key, which can happen if
+ // the two WriteSample() calls are less than 1 second apart. In that case, the
+ // samples will be appended and rewritten to the database. Any entries older
+ // than 1 second are cleaned up on the subsequent invocation to WriteSample().
+ std::map<SignalKey, proto::SignalData> recently_added_signals_;
+
+ base::WeakPtrFactory<SignalDatabaseImpl> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_DATABASE_IMPL_H_
diff --git a/chromium/components/segmentation_platform/internal/database/signal_database_impl_unittest.cc b/chromium/components/segmentation_platform/internal/database/signal_database_impl_unittest.cc
new file mode 100644
index 00000000000..0d5f5d1fa95
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_database_impl_unittest.cc
@@ -0,0 +1,258 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/database/signal_database_impl.h"
+
+#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
+#include "components/leveldb_proto/testing/fake_db.h"
+#include "components/segmentation_platform/internal/proto/signal.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace segmentation_platform {
+
+bool IsWithinOneSecond(base::Time t1, base::Time t2) {
+ return (t1 - t2).magnitude() < base::TimeDelta::FromSeconds(1);
+}
+
+void CheckVectorsEqual(const std::vector<SignalDatabase::Sample>& expected_list,
+ const std::vector<SignalDatabase::Sample>& actual_list) {
+ EXPECT_EQ(expected_list.size(), actual_list.size());
+ unsigned int equal_count = 0;
+ for (const auto& expected : expected_list) {
+ for (const auto& actual : actual_list) {
+ if (expected.second == actual.second &&
+ IsWithinOneSecond(expected.first, actual.first)) {
+ equal_count++;
+ }
+ }
+ }
+
+ EXPECT_EQ(equal_count, actual_list.size());
+}
+
+class SignalDatabaseImplTest : public testing::Test {
+ public:
+ SignalDatabaseImplTest() = default;
+ ~SignalDatabaseImplTest() override = default;
+
+ void OnGetSamples(std::vector<SignalDatabase::Sample> samples) {
+ get_samples_result_ = samples;
+ }
+
+ protected:
+ void SetUpDB() {
+ DCHECK(!db_);
+ DCHECK(!signal_db_);
+
+ auto db = std::make_unique<leveldb_proto::test::FakeDB<proto::SignalData>>(
+ &db_entries_);
+ db_ = db.get();
+ signal_db_ =
+ std::make_unique<SignalDatabaseImpl>(std::move(db), &test_clock_);
+
+ signal_db_->Initialize(base::DoNothing());
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+
+ test_clock_.SetNow(base::Time::Now().UTCMidnight() +
+ base::TimeDelta::FromHours(8));
+ }
+
+ void TearDown() override {
+ db_entries_.clear();
+ db_ = nullptr;
+ signal_db_.reset();
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ base::SimpleTestClock test_clock_;
+ std::vector<SignalDatabase::Sample> get_samples_result_;
+ std::map<std::string, proto::SignalData> db_entries_;
+ leveldb_proto::test::FakeDB<proto::SignalData>* db_{nullptr};
+ std::unique_ptr<SignalDatabaseImpl> signal_db_;
+};
+
+TEST_F(SignalDatabaseImplTest, WriteSampleAndRead) {
+ SetUpDB();
+ base::Time now =
+ base::Time::Now().UTCMidnight() + base::TimeDelta::FromHours(8);
+
+ uint64_t name_hash = 1234;
+ proto::SignalType signal_type = proto::SignalType::HISTOGRAM_VALUE;
+
+ // No entries to begin with.
+ signal_db_->GetSamples(signal_type, name_hash, now.UTCMidnight(), now,
+ base::BindOnce(&SignalDatabaseImplTest::OnGetSamples,
+ base::Unretained(this)));
+ db_->LoadCallback(true);
+ CheckVectorsEqual({}, get_samples_result_);
+
+ // Write a sample.
+ int32_t value = 10;
+ base::Time timestamp = now - base::TimeDelta::FromHours(1);
+ test_clock_.SetNow(timestamp);
+ signal_db_->WriteSample(signal_type, name_hash, value, base::DoNothing());
+ db_->UpdateCallback(true);
+
+ // Read back the sample and verify.
+ signal_db_->GetSamples(signal_type, name_hash, now.UTCMidnight(), now,
+ base::BindOnce(&SignalDatabaseImplTest::OnGetSamples,
+ base::Unretained(this)));
+ db_->LoadCallback(true);
+ CheckVectorsEqual({{timestamp, value}}, get_samples_result_);
+ EXPECT_EQ(1u, db_entries_.size());
+
+ // Write another sample right away. Both the values should be persisted
+ // correctly without being overwritten.
+ int32_t value2 = 20;
+ signal_db_->WriteSample(signal_type, name_hash, value2, base::DoNothing());
+ db_->UpdateCallback(true);
+
+ signal_db_->GetSamples(signal_type, name_hash, now.UTCMidnight(), now,
+ base::BindOnce(&SignalDatabaseImplTest::OnGetSamples,
+ base::Unretained(this)));
+ db_->LoadCallback(true);
+ CheckVectorsEqual({{timestamp, value}, {timestamp, value2}},
+ get_samples_result_);
+ EXPECT_EQ(1u, db_entries_.size());
+}
+
+TEST_F(SignalDatabaseImplTest, DeleteSamples) {
+ SetUpDB();
+
+ proto::SignalType signal_type = proto::SignalType::USER_ACTION;
+ uint64_t name_hash = 1234;
+ base::Time timestamp1 = test_clock_.Now() - base::TimeDelta::FromHours(3);
+ base::Time timestamp2 = timestamp1 + base::TimeDelta::FromHours(1);
+ base::Time timestamp3 = timestamp2 + base::TimeDelta::FromHours(1);
+
+ // Write two samples, at timestamp1 and timestamp3.
+ test_clock_.SetNow(timestamp1);
+ signal_db_->WriteSample(signal_type, name_hash, absl::nullopt,
+ base::DoNothing());
+ db_->UpdateCallback(true);
+ EXPECT_EQ(1u, db_entries_.size());
+
+ test_clock_.SetNow(timestamp3);
+ signal_db_->WriteSample(signal_type, name_hash, absl::nullopt,
+ base::DoNothing());
+ db_->UpdateCallback(true);
+ EXPECT_EQ(2u, db_entries_.size());
+
+ // Now delete samples till timestamp2 and verify.
+ signal_db_->DeleteSamples(signal_type, name_hash, timestamp2,
+ base::DoNothing());
+ db_->LoadCallback(true);
+ db_->UpdateCallback(true);
+ EXPECT_EQ(1u, db_entries_.size());
+
+ // Now delete samples till timestamp3 and verify.
+ signal_db_->DeleteSamples(signal_type, name_hash, timestamp3,
+ base::DoNothing());
+ db_->LoadCallback(true);
+ db_->UpdateCallback(true);
+ EXPECT_EQ(0u, db_entries_.size());
+
+ // Try deleting again for the same period.
+ signal_db_->DeleteSamples(signal_type, name_hash, timestamp3,
+ base::DoNothing());
+ db_->LoadCallback(true);
+ db_->UpdateCallback(true);
+ EXPECT_EQ(0u, db_entries_.size());
+}
+
+TEST_F(SignalDatabaseImplTest, WriteMultipleSamplesAndRunCompaction) {
+ // Set up three consecutive date timestamps, each at 8:00AM.
+ base::Time day1 = base::Time::Now().UTCMidnight() +
+ base::TimeDelta::FromHours(8) -
+ base::TimeDelta::FromDays(2);
+ base::Time day2 = day1 + base::TimeDelta::FromDays(1);
+ base::Time day3 = day2 + base::TimeDelta::FromDays(1);
+
+ SetUpDB();
+ EXPECT_EQ(0u, db_entries_.size());
+
+ proto::SignalType signal_type = proto::SignalType::USER_ACTION;
+ uint64_t name_hash = 1234;
+
+ // Collect two samples on day1, and one on day2.
+ base::Time timestamp_day1_1 = day1 + base::TimeDelta::FromHours(1);
+ base::Time timestamp_day1_2 = day1 + base::TimeDelta::FromHours(2);
+ base::Time timestamp_day2_1 = day2 + base::TimeDelta::FromHours(2);
+
+ test_clock_.SetNow(timestamp_day1_1);
+ signal_db_->WriteSample(signal_type, name_hash, absl::nullopt,
+ base::DoNothing());
+ db_->UpdateCallback(true);
+
+ test_clock_.SetNow(timestamp_day1_2);
+ signal_db_->WriteSample(signal_type, name_hash, absl::nullopt,
+ base::DoNothing());
+ db_->UpdateCallback(true);
+
+ test_clock_.SetNow(timestamp_day2_1);
+ signal_db_->WriteSample(signal_type, name_hash, absl::nullopt,
+ base::DoNothing());
+ db_->UpdateCallback(true);
+
+ EXPECT_EQ(3u, db_entries_.size());
+
+ // Verify samples for the day1. There should be two of them.
+ signal_db_->GetSamples(signal_type, name_hash, day1.UTCMidnight(),
+ day2.UTCMidnight(),
+ base::BindOnce(&SignalDatabaseImplTest::OnGetSamples,
+ base::Unretained(this)));
+ db_->LoadCallback(true);
+ CheckVectorsEqual({{timestamp_day1_1, 0}, {timestamp_day1_2, 0}},
+ get_samples_result_);
+
+ // Compact samples for the day1 and verify. We will have two samples, but one
+ // less entry.
+ signal_db_->CompactSamplesForDay(signal_type, name_hash, day1,
+ base::DoNothing());
+ db_->LoadCallback(true);
+ db_->UpdateCallback(true);
+
+ signal_db_->GetSamples(signal_type, name_hash, day1.UTCMidnight(),
+ day2.UTCMidnight(),
+ base::BindOnce(&SignalDatabaseImplTest::OnGetSamples,
+ base::Unretained(this)));
+ db_->LoadCallback(true);
+ CheckVectorsEqual({{timestamp_day1_1, 0}, {timestamp_day1_2, 0}},
+ get_samples_result_);
+
+ EXPECT_EQ(2u, db_entries_.size());
+
+ // Compact samples for the day2 and verify.
+ signal_db_->CompactSamplesForDay(signal_type, name_hash, day2,
+ base::DoNothing());
+ db_->LoadCallback(true);
+ db_->UpdateCallback(true);
+
+ signal_db_->GetSamples(signal_type, name_hash, day2.UTCMidnight(),
+ day3.UTCMidnight(),
+ base::BindOnce(&SignalDatabaseImplTest::OnGetSamples,
+ base::Unretained(this)));
+ db_->LoadCallback(true);
+ CheckVectorsEqual({{timestamp_day2_1, 0}}, get_samples_result_);
+
+ EXPECT_EQ(2u, db_entries_.size());
+
+ // Compact samples for the day3 and verify. There should be no change since
+ // there are no samples.
+ signal_db_->CompactSamplesForDay(signal_type, name_hash, day3,
+ base::DoNothing());
+ db_->LoadCallback(true);
+
+ signal_db_->GetSamples(signal_type, name_hash, day3.UTCMidnight(),
+ day3.UTCMidnight() + base::TimeDelta::FromDays(1),
+ base::BindOnce(&SignalDatabaseImplTest::OnGetSamples,
+ base::Unretained(this)));
+ db_->LoadCallback(true);
+ CheckVectorsEqual({}, get_samples_result_);
+
+ EXPECT_EQ(2u, db_entries_.size());
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/signal_key.cc b/chromium/components/segmentation_platform/internal/database/signal_key.cc
new file mode 100644
index 00000000000..b7dfe0fdb4c
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_key.cc
@@ -0,0 +1,120 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/database/signal_key.h"
+
+#include <ostream>
+#include <sstream>
+#include <string>
+
+#include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/signal_key_internal.h"
+
+namespace segmentation_platform {
+
+namespace {
+char ToInternalSignalKindRepresentation(SignalKey::Kind kind) {
+ switch (kind) {
+ case SignalKey::Kind::USER_ACTION:
+ return 'u';
+ case SignalKey::Kind::HISTOGRAM_VALUE:
+ return 'h';
+ case SignalKey::Kind::HISTOGRAM_ENUM:
+ return 'e';
+ default:
+ return '0';
+ }
+}
+
+SignalKey::Kind FromInternalSignalKindRepresentation(char kind) {
+ switch (kind) {
+ case 'u':
+ return SignalKey::Kind::USER_ACTION;
+ case 'h':
+ return SignalKey::Kind::HISTOGRAM_VALUE;
+ case 'e':
+ return SignalKey::Kind::HISTOGRAM_ENUM;
+ default:
+ return SignalKey::Kind::UNKNOWN;
+ }
+}
+
+base::Time StripResolutionSmallerThanSeconds(base::Time time) {
+ return base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromSeconds(
+ time.ToDeltaSinceWindowsEpoch().InSeconds()));
+}
+} // namespace
+
+SignalKey::SignalKey(Kind kind,
+ uint64_t name_hash,
+ base::Time range_start,
+ base::Time range_end)
+ : kind_(kind),
+ name_hash_(name_hash),
+ range_start_(StripResolutionSmallerThanSeconds(range_start)),
+ range_end_(StripResolutionSmallerThanSeconds(range_end)) {}
+
+SignalKey::SignalKey() : kind_(Kind::UNKNOWN), name_hash_(0) {}
+
+SignalKey::~SignalKey() = default;
+
+bool SignalKey::IsValid() const {
+ return kind_ != Kind::UNKNOWN && name_hash_ != 0 && !range_start_.is_null() &&
+ !range_end_.is_null();
+}
+
+std::string SignalKey::ToBinary() const {
+ SignalKeyInternal internal_key;
+ internal_key.prefix.kind = ToInternalSignalKindRepresentation(kind_);
+ internal_key.prefix.name_hash = name_hash_;
+ internal_key.time_range_end_sec =
+ range_end_.ToDeltaSinceWindowsEpoch().InSeconds();
+ internal_key.time_range_start_sec =
+ range_start_.ToDeltaSinceWindowsEpoch().InSeconds();
+ return SignalKeyInternalToBinary(internal_key);
+}
+
+std::string SignalKey::GetPrefixInBinary() const {
+ SignalKeyInternal::Prefix prefix;
+ prefix.kind = ToInternalSignalKindRepresentation(kind_);
+ prefix.name_hash = name_hash_;
+ return SignalKeyInternalPrefixToBinary(prefix);
+}
+
+// static
+void SignalKey::FromBinary(const std::string& input, SignalKey* output) {
+ SignalKeyInternal internal_key;
+ SignalKeyInternalFromBinary(input, &internal_key);
+ output->kind_ =
+ FromInternalSignalKindRepresentation(internal_key.prefix.kind);
+ output->name_hash_ = internal_key.prefix.name_hash;
+ output->range_start_ = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromSeconds(internal_key.time_range_start_sec));
+ output->range_end_ = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromSeconds(internal_key.time_range_end_sec));
+}
+
+std::string SignalKey::ToDebugString() const {
+ std::stringstream buffer;
+ buffer << *this;
+ return buffer.str();
+}
+
+bool SignalKey::operator<(const SignalKey& other) const {
+ if (kind_ != other.kind_)
+ return kind_ < other.kind_;
+ if (name_hash_ != other.name_hash_)
+ return name_hash_ < other.name_hash_;
+ if (range_end_ < other.range_end_)
+ return range_end_ < other.range_end_;
+ return range_start_ < other.range_start_;
+}
+
+std::ostream& operator<<(std::ostream& os, const SignalKey& key) {
+ return os << "{kind=" << key.kind() << ", name_hash=" << key.name_hash()
+ << ", range_start=" << key.range_start()
+ << ", range_end=" << key.range_end() << "}";
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/signal_key.h b/chromium/components/segmentation_platform/internal/database/signal_key.h
new file mode 100644
index 00000000000..72cda4a8962
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_key.h
@@ -0,0 +1,97 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_KEY_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_KEY_H_
+
+#include <cstdint>
+#include <ostream>
+#include <string>
+
+#include "base/time/time.h"
+
+namespace segmentation_platform {
+
+// The SignalKey is used for identifying a particular record in the
+// SignalDatabase. The format is defined in go/chrome-segmentation-storage-mvp.
+//
+// It provides functionality to convert to and from a binary format. The format
+// for this binary key must never change on a single device, so an internal
+// representation for this, SignalKeyInternal, is used.
+//
+// The SignalKey is not meant to be used by external clients in any way,
+// and should be considered as an internal implementation detail of the
+// SignalDatabase.
+//
+// The binary representation of the key does not store any resolution smaller
+// than seconds, so any constructed SignalKey is immediately stripped of
+// resolutions smaller than 1 second to ensure a SignalKey which has been
+// converted to a binary key and back again matches the original SignalKey.
+//
+// Since the binary representation is not human readable, the struct also
+// supports being streamed or by calling ToDebugString(), which will make it be
+// presented using this format:
+// {kind=..., name_hash=..., range_start=..., range_start=...} which is useful
+// for debugging.
+//
+// The binary representation of a key can be lexicographically compared. The
+// fields are in the following order: kind, name_hash, range_start, range_end.
+class SignalKey {
+ public:
+ enum Kind {
+ UNKNOWN = 0,
+ USER_ACTION = 1,
+ HISTOGRAM_VALUE = 2,
+ HISTOGRAM_ENUM = 3,
+ };
+
+ SignalKey(Kind kind,
+ uint64_t name_hash,
+ base::Time range_start,
+ base::Time range_end);
+ SignalKey();
+ ~SignalKey();
+
+ // Whether this object has been initialized and does not contain unknown data.
+ bool IsValid() const;
+
+ Kind kind() const { return kind_; }
+ uint64_t name_hash() const { return name_hash_; }
+ // The smallest resolution for range_start() and range_end() is 1 second, so
+ // any fraction of a second is dropped.
+ const base::Time& range_start() const { return range_start_; }
+ const base::Time& range_end() const { return range_end_; }
+
+ // A machine readable representation of the SignalKey.
+ // See ToDebugString and operator<< implementation for a human readable
+ // format.
+ std::string ToBinary() const;
+ // Parses a machine readable representation of a SignalKeyInternal into
+ // a SignalKey. Use IsValid() to check that the resulting SignalKey is valid.
+ static void FromBinary(const std::string& input, SignalKey* output);
+ // The SignalKey prefix in binary format.
+ std::string GetPrefixInBinary() const;
+ // Returns a human readable representation of the SignalKey.
+ std::string ToDebugString() const;
+
+ // Allow SignalKey to be a key in STL containers.
+ bool operator<(const SignalKey& other) const;
+
+ private:
+ // The type of record this key refers to.
+ Kind kind_;
+ // The name of the sample identifier, for example the hash of the histogram
+ // or user action.
+ uint64_t name_hash_;
+ // The first record timestamp this key refers to.
+ base::Time range_start_;
+ // The latest record timestamp this key refers to.
+ base::Time range_end_;
+};
+
+std::ostream& operator<<(std::ostream& os, const SignalKey& key);
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_KEY_H_
diff --git a/chromium/components/segmentation_platform/internal/database/signal_key_internal.cc b/chromium/components/segmentation_platform/internal/database/signal_key_internal.cc
new file mode 100644
index 00000000000..46ede2447dc
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_key_internal.cc
@@ -0,0 +1,92 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/database/signal_key_internal.h"
+
+#include <stdint.h>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "base/big_endian.h"
+#include "base/check.h"
+#include "base/logging.h"
+
+namespace segmentation_platform {
+
+std::string SignalKeyInternalToBinary(const SignalKeyInternal& input) {
+ char output[sizeof(SignalKeyInternal)];
+ base::BigEndianWriter writer(output, sizeof(output));
+ writer.WriteBytes(&input.prefix.kind, sizeof(input.prefix.kind));
+ writer.WriteBytes(&input.prefix.padding, sizeof(input.prefix.padding));
+ writer.WriteU64(input.prefix.name_hash);
+ base::WriteBigEndian(writer.ptr(), input.time_range_end_sec);
+ writer.Skip(sizeof(input.time_range_end_sec));
+ base::WriteBigEndian(writer.ptr(), input.time_range_start_sec);
+ writer.Skip(sizeof(input.time_range_start_sec));
+ CHECK_EQ(0UL, writer.remaining());
+ return std::string(output, sizeof(output));
+}
+
+void SignalKeyInternalFromBinary(const std::string& input,
+ SignalKeyInternal* output) {
+ CHECK_EQ(input.size(), sizeof(SignalKeyInternal));
+ base::BigEndianReader reader(input.data(), input.size());
+ reader.ReadBytes(&output->prefix.kind, sizeof(output->prefix.kind));
+ reader.Skip(sizeof(SignalKeyInternal::Prefix::padding));
+ reader.ReadU64(&output->prefix.name_hash);
+ base::ReadBigEndian(reader.ptr(), &output->time_range_end_sec);
+ reader.Skip(sizeof(SignalKeyInternal::time_range_end_sec));
+ base::ReadBigEndian(reader.ptr(), &output->time_range_start_sec);
+ reader.Skip(sizeof(SignalKeyInternal::time_range_start_sec));
+ CHECK_EQ(0UL, reader.remaining());
+}
+
+std::string SignalKeyInternalToDebugString(const SignalKeyInternal& input) {
+ std::stringstream buffer;
+ buffer << input;
+ return buffer.str();
+}
+
+std::string SignalKeyInternalPrefixToBinary(
+ const SignalKeyInternal::Prefix& input) {
+ char output[sizeof(SignalKeyInternal::Prefix)];
+ base::BigEndianWriter writer(output, sizeof(output));
+ writer.WriteBytes(&input.kind, sizeof(input.kind));
+ writer.WriteBytes(&input.padding, sizeof(input.padding));
+ writer.WriteU64(input.name_hash);
+ CHECK_EQ(0UL, writer.remaining());
+ std::string output_str = std::string(output, sizeof(output));
+ return output_str;
+}
+
+void SignalKeyInternalPrefixFromBinary(const std::string& input,
+ SignalKeyInternal::Prefix* output) {
+ CHECK_EQ(input.size(), sizeof(SignalKeyInternal::Prefix));
+ base::BigEndianReader reader(input.data(), input.size());
+ reader.ReadBytes(&output->kind, sizeof(output->kind));
+ reader.Skip(sizeof(SignalKeyInternal::Prefix::padding));
+ reader.ReadU64(&output->name_hash);
+ CHECK_EQ(0UL, reader.remaining());
+}
+
+std::string SignalKeyInternalPrefixToDebugString(
+ const SignalKeyInternal::Prefix& input) {
+ std::stringstream buffer;
+ buffer << input;
+ return buffer.str();
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const SignalKeyInternal::Prefix& prefix) {
+ return os << "{" << prefix.kind << ":" << prefix.name_hash << "}";
+}
+
+std::ostream& operator<<(std::ostream& os, const SignalKeyInternal& key) {
+ return os << "{" << key.prefix << ":" << key.time_range_end_sec << ":"
+ << key.time_range_start_sec << "}";
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/signal_key_internal.h b/chromium/components/segmentation_platform/internal/database/signal_key_internal.h
new file mode 100644
index 00000000000..17b63273070
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_key_internal.h
@@ -0,0 +1,128 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_KEY_INTERNAL_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_KEY_INTERNAL_H_
+
+#include <stdint.h>
+#include <ostream>
+#include <string>
+#include <type_traits>
+
+namespace segmentation_platform {
+
+// The SignalKeyInternal is used for identifying a particular record in the
+// SignalDatabase. The format is defined in go/chrome-segmentation-storage-mvp.
+// It is important that on a single device, this representation never changes,
+// so steps are taken to make sure it is safe to make assumptions about the
+// memory layout of the key.
+//
+// The SignalKeyInternal is not meant to be used by external clients in any way,
+// and should be considered as an internal implementation detail of the
+// SignalDatabase.
+//
+// Since the binary representation is not human readable, the struct also
+// supports being streamed or by calling SignalKeyInternalToDebugString(),
+// which will make it be presented using this format:
+// {{kind:name_hash}:time_range_end_sec:time_range_start_sec} which is useful
+// for debugging.
+//
+// The structure of the key is on the following format:
+// +----+---------------------------+
+// |kind| (PADDING) |
+// |char| char[7] |
+// +----+---------------------------+
+// | name_hash |
+// | uint64_t |
+// +--------------------------------+
+// | time_range_end_sec |
+// | int64_t |
+// +--------------------------------+
+// | time_range_start_sec |
+// | int64_t |
+// +--------------------------------+
+//
+// Even though SignalKeyInternal is serialized/deserialized using big endian
+// writer and reader respectively, it still cannot contain any implicit padding
+// since implicit padding bytes could contain any value and prevent two
+// otherwise equal binary keys from comparing as equal.
+//
+// The binary format is created using big endian, which means that the binary
+// key can be used to do lexicographical comparisons in its binary format
+// (represented as std::string). The same is true for prefix-based lookups using
+// the SignalKeyInternal::Prefix.
+// The fields are in the following order: kind, name_hash, range_start,
+// range_end (SignalKey::Prefix only contains the first two fields).
+struct SignalKeyInternal {
+ struct Prefix {
+ // The type of record this key refers to.
+ char kind{};
+
+ // This padding is required to be able to guarantee a standard layout.
+ const char padding[7]{};
+
+ // The name of the sample identifier, for example the hash of the histogram
+ // or user action.
+ uint64_t name_hash{};
+ };
+ Prefix prefix;
+
+ // The latest record timestamp this key refers to.
+ int64_t time_range_end_sec{};
+ // The first record timestamp this key refers to.
+ int64_t time_range_start_sec{};
+};
+
+// Verify that we can safely make assumptions about the memory layout.
+// It is important to recognize that if you change how the key is laid out,
+// old keys will no longer be usable, and since this key is persisted to disk,
+// this is something that should be avoided.
+// See https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
+static_assert(std::is_standard_layout<SignalKeyInternal>::value,
+ "SignalKeyInternal must have a standard layout.");
+
+// Ensure there is no implicit padding.
+// TODO(C++17): Use std::has_unique_object_representations instead.
+static_assert(sizeof(SignalKeyInternal) == 32, "Size must be 32");
+static_assert(sizeof(SignalKeyInternal) ==
+ sizeof(SignalKeyInternal::Prefix::kind) +
+ sizeof(SignalKeyInternal::Prefix::padding) +
+ sizeof(SignalKeyInternal::Prefix::name_hash) +
+ sizeof(SignalKeyInternal::time_range_end_sec) +
+ sizeof(SignalKeyInternal::time_range_start_sec),
+ "Sum of the size of all fields must be 32");
+
+// A machine readable representation of the SignalKeyInternal.
+// See ToDebugString and operator<< implementation for a human readable
+// format.
+std::string SignalKeyInternalToBinary(const SignalKeyInternal& input);
+// Parses a machine readable representation of a SignalKeyInternal into
+// a SignalKeyInternal.
+void SignalKeyInternalFromBinary(const std::string& input,
+ SignalKeyInternal* output);
+// Returns a human readable representation of the SignalKeyInternal.
+std::string SignalKeyInternalToDebugString(const SignalKeyInternal& input);
+
+// A machine readable representation of the SignalKeyInternal::Prefix.
+// See ToDebugString and operator<< implementation for a human readable
+// format.
+std::string SignalKeyInternalPrefixToBinary(
+ const SignalKeyInternal::Prefix& input);
+// Parses a machine readable representation of a SignalKeyInternal::Prefix into
+// a SignalKeyInternal::Prefix.
+void SignalKeyInternalPrefixFromBinary(const std::string& input,
+ SignalKeyInternal::Prefix* output);
+// Returns a human readable representation of the SignalKeyInternal::Prefix.
+std::string SignalKeyInternalPrefixToDebugString(
+ const SignalKeyInternal::Prefix& input);
+
+// The following streaming operators make it easy to get a human readable
+// version of the SignalKeyInternal and SignalKeyInternal::Prefix.
+std::ostream& operator<<(std::ostream& os, const SignalKeyInternal& key);
+std::ostream& operator<<(std::ostream& os,
+ const SignalKeyInternal::Prefix& prefix);
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_KEY_INTERNAL_H_
diff --git a/chromium/components/segmentation_platform/internal/database/signal_key_internal_unittest.cc b/chromium/components/segmentation_platform/internal/database/signal_key_internal_unittest.cc
new file mode 100644
index 00000000000..a2342834242
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_key_internal_unittest.cc
@@ -0,0 +1,330 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/database/signal_key_internal.h"
+
+#include <sstream>
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace segmentation_platform {
+
+namespace {
+void VerifyEqual(SignalKeyInternal a, SignalKeyInternal b) {
+ ASSERT_EQ(0, memcmp(&a, &b, sizeof(SignalKeyInternal)));
+}
+
+void VerifyNotEqual(SignalKeyInternal a, SignalKeyInternal b) {
+ ASSERT_NE(0, memcmp(&a, &b, sizeof(SignalKeyInternal)));
+}
+
+void VerifyEqual(SignalKeyInternal::Prefix a, SignalKeyInternal::Prefix b) {
+ ASSERT_EQ(0, memcmp(&a, &b, sizeof(SignalKeyInternal::Prefix)));
+}
+
+void VerifyNotEqual(SignalKeyInternal::Prefix a, SignalKeyInternal::Prefix b) {
+ ASSERT_NE(0, memcmp(&a, &b, sizeof(SignalKeyInternal::Prefix)));
+}
+
+TEST(SignalKeyInternalTest, TestKeyConversionToAndFromBinary) {
+ SignalKeyInternal key;
+ key.prefix.kind = 'u';
+ key.prefix.name_hash = 42;
+ key.time_range_end_sec = 1577836800000;
+ key.time_range_start_sec = 1609459200000;
+
+ std::string binary = SignalKeyInternalToBinary(key);
+ SignalKeyInternal result;
+ SignalKeyInternalFromBinary(binary, &result);
+ VerifyEqual(key, result);
+}
+
+TEST(SignalKeyInternalTest, TestPrefixConversionToAndFromBinary) {
+ SignalKeyInternal::Prefix prefix;
+ prefix.kind = 'u';
+ prefix.name_hash = 42;
+
+ std::string binary = SignalKeyInternalPrefixToBinary(prefix);
+ SignalKeyInternal::Prefix result;
+ SignalKeyInternalPrefixFromBinary(binary, &result);
+ VerifyEqual(prefix, result);
+}
+
+TEST(SignalKeyInternalTest, TestChangingAnyKeyFieldMakesNotEqual) {
+ SignalKeyInternal original;
+ original.prefix.kind = 'u';
+ original.prefix.name_hash = 42;
+ original.time_range_end_sec = 1577836800000;
+ original.time_range_start_sec = 1609459200000;
+
+ SignalKeyInternal copy = original;
+ SignalKeyInternal result;
+ SignalKeyInternalFromBinary(SignalKeyInternalToBinary(copy), &result);
+ VerifyEqual(original, result);
+
+ SignalKeyInternal different_kind = original;
+ different_kind.prefix.kind = 'r';
+ SignalKeyInternalFromBinary(SignalKeyInternalToBinary(different_kind),
+ &result);
+ VerifyNotEqual(original, result);
+
+ SignalKeyInternal different_name_hash = original;
+ different_name_hash.prefix.name_hash = 84;
+ SignalKeyInternalFromBinary(SignalKeyInternalToBinary(different_name_hash),
+ &result);
+ VerifyNotEqual(original, result);
+
+ SignalKeyInternal different_time_range_end_sec = original;
+ different_time_range_end_sec.time_range_end_sec = 1546300800000;
+ SignalKeyInternalFromBinary(
+ SignalKeyInternalToBinary(different_time_range_end_sec), &result);
+ VerifyNotEqual(original, result);
+
+ SignalKeyInternal different_time_range_start_sec = original;
+ different_time_range_start_sec.time_range_start_sec = 1546300800000;
+ SignalKeyInternalFromBinary(
+ SignalKeyInternalToBinary(different_time_range_start_sec), &result);
+ VerifyNotEqual(original, result);
+}
+
+TEST(SignalKeyInternalTest, TestChangingAnyPrefixFieldMakesNotEqual) {
+ SignalKeyInternal::Prefix original;
+ original.kind = 'u';
+ original.name_hash = 42;
+
+ SignalKeyInternal::Prefix copy = original;
+ SignalKeyInternal::Prefix result;
+ SignalKeyInternalPrefixFromBinary(SignalKeyInternalPrefixToBinary(copy),
+ &result);
+ VerifyEqual(original, result);
+
+ SignalKeyInternal::Prefix different_kind = original;
+ different_kind.kind = 'r';
+ SignalKeyInternalPrefixFromBinary(
+ SignalKeyInternalPrefixToBinary(different_kind), &result);
+ VerifyNotEqual(original, result);
+
+ SignalKeyInternal::Prefix different_name_hash = original;
+ different_name_hash.name_hash = 84;
+ SignalKeyInternalPrefixFromBinary(
+ SignalKeyInternalPrefixToBinary(different_name_hash), &result);
+ VerifyNotEqual(original, result);
+}
+
+TEST(SignalKeyInternalTest, TestKeyDebugStringRepresentation) {
+ SignalKeyInternal key1;
+ key1.prefix.kind = 'u';
+ key1.prefix.name_hash = 1;
+ key1.time_range_end_sec = 3;
+ key1.time_range_start_sec = 2;
+
+ EXPECT_EQ("{{u:1}:3:2}", SignalKeyInternalToDebugString(key1));
+ std::stringstream key1_buffer;
+ key1_buffer << key1;
+ EXPECT_EQ("{{u:1}:3:2}", key1_buffer.str());
+
+ SignalKeyInternal key2;
+ key2.prefix.kind = 'u';
+ key2.prefix.name_hash = 1;
+ key2.time_range_end_sec = -2;
+ key2.time_range_start_sec = -3;
+ EXPECT_EQ("{{u:1}:-2:-3}", SignalKeyInternalToDebugString(key2));
+ std::stringstream key2_buffer;
+ key2_buffer << key2;
+ EXPECT_EQ("{{u:1}:-2:-3}", key2_buffer.str());
+}
+
+TEST(SignalKeyInternalTest, TestPrefixDebugStringRepresentation) {
+ SignalKeyInternal::Prefix prefix;
+ prefix.kind = 'u';
+ prefix.name_hash = 1;
+ EXPECT_EQ("{u:1}", SignalKeyInternalPrefixToDebugString(prefix));
+ std::stringstream prefix_buffer;
+ prefix_buffer << prefix;
+ EXPECT_EQ("{u:1}", prefix_buffer.str());
+}
+
+TEST(SignalKeyInternalTest, TestBinaryKeyLexicographicalComparison) {
+ // The members prefix.name_hash, time_range_end_sec, and time_range_start_sec
+ // are not lexicographically comparable using their in-memory representation
+ // on little endian systems. Verify that the resulting binary key still is
+ // lexicographically comparable since big endian should be used.
+ // It is important to use multiple bytes when creating test scenarios, since
+ // both little endian and big endian store each individual byte the same way.
+ SignalKeyInternal original;
+ original.prefix.kind = 'u';
+ original.prefix.name_hash = 1 << 8;
+ original.time_range_end_sec = 1 << 24;
+ original.time_range_start_sec = 1 << 8;
+ std::string original_binary = SignalKeyInternalToBinary(original);
+
+ SignalKeyInternal other{{'u', {}, 1 << 8}, 1 << 24, 1 << 8};
+ std::string other_binary = SignalKeyInternalToBinary(other);
+ EXPECT_EQ(original_binary, other_binary);
+
+ SignalKeyInternal kind_smaller{{'a', {}, 1 << 8}, 1 << 24, 1 << 8};
+ std::string kind_smaller_binary = SignalKeyInternalToBinary(kind_smaller);
+ EXPECT_GT(original_binary, kind_smaller_binary);
+
+ SignalKeyInternal kind_larger{{'z', {}, 1 << 8}, 1 << 24, 1 << 8};
+ std::string kind_larger_binary = SignalKeyInternalToBinary(kind_larger);
+ EXPECT_LT(original_binary, kind_larger_binary);
+
+ SignalKeyInternal name_hash_smaller{{'u', {}, 1}, 1 << 24, 1 << 8};
+ std::string name_hash_smaller_binary =
+ SignalKeyInternalToBinary(name_hash_smaller);
+ EXPECT_GT(original_binary, name_hash_smaller_binary);
+
+ SignalKeyInternal name_hash_larger{{'u', {}, 1 << 16}, 1 << 24, 1 << 8};
+ std::string name_hash_larger_binary =
+ SignalKeyInternalToBinary(name_hash_larger);
+ EXPECT_LT(original_binary, name_hash_larger_binary);
+
+ SignalKeyInternal range_end_smaller{{'u', {}, 1 << 8}, 1 << 16, 1 << 8};
+ std::string range_end_smaller_binary =
+ SignalKeyInternalToBinary(range_end_smaller);
+ EXPECT_GT(original_binary, range_end_smaller_binary);
+
+ SignalKeyInternal range_end_larger{{'u', {}, 1 << 8}, 1LL << 32, 1 << 8};
+ std::string range_end_larger_binary =
+ SignalKeyInternalToBinary(range_end_larger);
+ EXPECT_LT(original_binary, range_end_larger_binary);
+
+ SignalKeyInternal range_start_smaller{{'u', {}, 1 << 8}, 1 << 24, 1};
+ std::string range_start_smaller_binary =
+ SignalKeyInternalToBinary(range_start_smaller);
+ EXPECT_GT(original_binary, range_start_smaller_binary);
+
+ SignalKeyInternal range_start_larger{{'u', {}, 1 << 8}, 1 << 24, 1 << 16};
+ std::string range_start_larger_binary =
+ SignalKeyInternalToBinary(range_start_larger);
+ EXPECT_LT(original_binary, range_start_larger_binary);
+}
+
+TEST(SignalKeyInternalTest, TestBinaryKeyFieldOrder) {
+ // This test changes one field at a time, and ensures that all fields expected
+ // to be later in the binary representation are set to values that would fail
+ // the comparison if they were in a different order.
+ SignalKeyInternal original;
+ original.prefix.kind = 'u';
+ original.prefix.name_hash = 1 << 8;
+ original.time_range_end_sec = 1 << 8;
+ original.time_range_start_sec = 1 << 8;
+ std::string original_binary = SignalKeyInternalToBinary(original);
+
+ // First value should be prefix.kind.
+ SignalKeyInternal kind_smaller{{'a', {}, 1 << 16}, 1 << 16, 1 << 16};
+ std::string kind_smaller_binary = SignalKeyInternalToBinary(kind_smaller);
+ EXPECT_GT(original_binary, kind_smaller_binary);
+
+ SignalKeyInternal kind_larger{{'z', {}, 1}, 1, 1};
+ std::string kind_larger_binary = SignalKeyInternalToBinary(kind_larger);
+ EXPECT_LT(original_binary, kind_larger_binary);
+
+ // Second value should be prefix.name_hash.
+ SignalKeyInternal name_hash_smaller{{'u', {}, 1}, 1 << 16, 1 << 16};
+ std::string name_hash_smaller_binary =
+ SignalKeyInternalToBinary(name_hash_smaller);
+ EXPECT_GT(original_binary, name_hash_smaller_binary);
+
+ SignalKeyInternal name_hash_larger{{'u', {}, 1 << 16}, 1, 1};
+ std::string name_hash_larger_binary =
+ SignalKeyInternalToBinary(name_hash_larger);
+ EXPECT_LT(original_binary, name_hash_larger_binary);
+
+ // Third value should be time_range_end_sec.
+ SignalKeyInternal time_range_end_sec_smaller{{'u', {}, 1 << 8}, 1, 1 << 16};
+ std::string time_range_end_sec_smaller_binary =
+ SignalKeyInternalToBinary(time_range_end_sec_smaller);
+ EXPECT_GT(original_binary, time_range_end_sec_smaller_binary);
+
+ SignalKeyInternal time_range_end_sec_larger{{'u', {}, 1 << 8}, 1 << 16, 1};
+ std::string time_range_end_sec_larger_binary =
+ SignalKeyInternalToBinary(time_range_end_sec_larger);
+ EXPECT_LT(original_binary, time_range_end_sec_larger_binary);
+
+ // Fourth value should be time_range_start_sec.
+ SignalKeyInternal time_range_start_sec_smaller{{'u', {}, 1 << 8}, 1 << 8, 1};
+ std::string time_range_start_sec_smaller_binary =
+ SignalKeyInternalToBinary(time_range_start_sec_smaller);
+ EXPECT_GT(original_binary, time_range_start_sec_smaller_binary);
+
+ SignalKeyInternal time_range_start_sec_larger{
+ {'u', {}, 1 << 8}, 1 << 8, 1 << 16};
+ std::string time_range_start_sec_larger_binary =
+ SignalKeyInternalToBinary(time_range_start_sec_larger);
+ EXPECT_LT(original_binary, time_range_start_sec_larger_binary);
+}
+
+TEST(SignalKeyInternalTest, TestBinaryPrefixLexicographicalComparison) {
+ // The members prefix.name_hash is not lexicographically comparable using
+ // their in-memory representation on little endian systems. Verify that the
+ // resulting binary prefix still is lexicographically comparable since big
+ // endian should be used.
+ // It is important to use multiple bytes when creating test scenarios, since
+ // both little endian and big endian store each individual byte the same way.
+ SignalKeyInternal::Prefix original;
+ original.kind = 'u';
+ original.name_hash = 1 << 8;
+ std::string original_binary = SignalKeyInternalPrefixToBinary(original);
+
+ SignalKeyInternal::Prefix other{'u', {}, 1 << 8};
+ std::string other_binary = SignalKeyInternalPrefixToBinary(other);
+ EXPECT_EQ(original_binary, other_binary);
+
+ SignalKeyInternal::Prefix kind_smaller{'a', {}, 1 << 8};
+ std::string kind_smaller_binary =
+ SignalKeyInternalPrefixToBinary(kind_smaller);
+ EXPECT_GT(original_binary, kind_smaller_binary);
+
+ SignalKeyInternal::Prefix kind_larger{'z', {}, 1 << 8};
+ std::string kind_larger_binary = SignalKeyInternalPrefixToBinary(kind_larger);
+ EXPECT_LT(original_binary, kind_larger_binary);
+
+ SignalKeyInternal::Prefix name_hash_smaller{'u', {}, 1};
+ std::string name_hash_smaller_binary =
+ SignalKeyInternalPrefixToBinary(name_hash_smaller);
+ EXPECT_GT(original_binary, name_hash_smaller_binary);
+
+ SignalKeyInternal::Prefix name_hash_larger{'u', {}, 1 << 16};
+ std::string name_hash_larger_binary =
+ SignalKeyInternalPrefixToBinary(name_hash_larger);
+ EXPECT_LT(original_binary, name_hash_larger_binary);
+}
+
+TEST(SignalKeyInternalTest, TestBinaryPrefixFieldOrder) {
+ // This test changes one field at a time, and ensures that all fields expected
+ // to be later in the binary representation are set to values that would fail
+ // the comparison if they were in a different order.
+ SignalKeyInternal::Prefix original;
+ original.kind = 'u';
+ original.name_hash = 1 << 8;
+ std::string original_binary = SignalKeyInternalPrefixToBinary(original);
+
+ // First value should be kind.
+ SignalKeyInternal::Prefix kind_smaller{'a', {}, 1 << 16};
+ std::string kind_smaller_binary =
+ SignalKeyInternalPrefixToBinary(kind_smaller);
+ EXPECT_GT(original_binary, kind_smaller_binary);
+
+ SignalKeyInternal::Prefix kind_larger{'z', {}, 1};
+ std::string kind_larger_binary = SignalKeyInternalPrefixToBinary(kind_larger);
+ EXPECT_LT(original_binary, kind_larger_binary);
+
+ // Second value should be name_hash.
+ SignalKeyInternal::Prefix name_hash_smaller{'u', {}, 1};
+ std::string name_hash_smaller_binary =
+ SignalKeyInternalPrefixToBinary(name_hash_smaller);
+ EXPECT_GT(original_binary, name_hash_smaller_binary);
+
+ SignalKeyInternal::Prefix name_hash_larger{'u', {}, 1 << 16};
+ std::string name_hash_larger_binary =
+ SignalKeyInternalPrefixToBinary(name_hash_larger);
+ EXPECT_LT(original_binary, name_hash_larger_binary);
+}
+
+} // namespace
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/signal_key_unittest.cc b/chromium/components/segmentation_platform/internal/database/signal_key_unittest.cc
new file mode 100644
index 00000000000..62268ffe0e3
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_key_unittest.cc
@@ -0,0 +1,195 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/database/signal_key.h"
+
+#include <cmath>
+#include <cstring>
+
+#include "base/logging.h"
+#include "base/test/simple_test_clock.h"
+#include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/signal_key_internal.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace segmentation_platform {
+
+namespace {
+int CompareBinaryKeys(const SignalKey& a, const SignalKey& b) {
+ std::string a_key = a.ToBinary();
+ std::string b_key = b.ToBinary();
+ CHECK_EQ(a_key.size(), b_key.size());
+ return std::memcmp(a_key.data(), b_key.data(), a_key.size());
+}
+
+bool Equal(const SignalKey& k1, const SignalKey& k2) {
+ // Log comparison debugging info for failing tests.
+ VLOG(0) << k1 << " ==? " << k2;
+ return k1.kind() == k2.kind() && k1.name_hash() == k2.name_hash() &&
+ k1.range_start() == k2.range_start() &&
+ k1.range_end() == k2.range_end() && CompareBinaryKeys(k1, k2) == 0;
+}
+} // namespace
+
+class SignalKeyTest : public testing::Test {
+ public:
+ SignalKeyTest() = default;
+ ~SignalKeyTest() override = default;
+
+ void VerifyConversion(const SignalKey& key) {
+ std::string binary_key = key.ToBinary();
+ SignalKey result;
+ SignalKey::FromBinary(binary_key, &result);
+ EXPECT_TRUE(Equal(key, result));
+ }
+
+ protected:
+ void SetUp() override {
+ test_clock_.SetNow(base::Time::UnixEpoch() + base::TimeDelta::FromHours(8));
+ }
+
+ base::SimpleTestClock test_clock_;
+};
+
+TEST_F(SignalKeyTest, TestConvertToAndFromBinary) {
+ VerifyConversion(
+ SignalKey(SignalKey::Kind::USER_ACTION, 1, test_clock_.Now(),
+ test_clock_.Now() + base::TimeDelta::FromSeconds(10)));
+ VerifyConversion(
+ SignalKey(SignalKey::Kind::HISTOGRAM_VALUE, 2, base::Time::Now(),
+ test_clock_.Now() + base::TimeDelta::FromSeconds(20)));
+ VerifyConversion(
+ SignalKey(SignalKey::Kind::HISTOGRAM_ENUM, 3, base::Time::Now(),
+ test_clock_.Now() + base::TimeDelta::FromSeconds(30)));
+}
+
+TEST_F(SignalKeyTest, TestValidity) {
+ SignalKey valid_key(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ test_clock_.Now() + base::TimeDelta::FromSeconds(10));
+ EXPECT_TRUE(valid_key.IsValid());
+
+ // A default constructed key should not be valid.
+ SignalKey default_constructed_key;
+ EXPECT_FALSE(default_constructed_key.IsValid());
+
+ // Verify that each individual field is tested for validity.
+ SignalKey invalid_key1(SignalKey::Kind::UNKNOWN, 42, test_clock_.Now(),
+ test_clock_.Now());
+ EXPECT_FALSE(invalid_key1.IsValid());
+
+ SignalKey invalid_key2(SignalKey::Kind::USER_ACTION, 0, test_clock_.Now(),
+ test_clock_.Now());
+ EXPECT_FALSE(invalid_key2.IsValid());
+
+ SignalKey invalid_key3(SignalKey::Kind::USER_ACTION, 42, base::Time(),
+ test_clock_.Now());
+ EXPECT_FALSE(invalid_key3.IsValid());
+
+ SignalKey invalid_key4(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ base::Time());
+ EXPECT_FALSE(invalid_key4.IsValid());
+}
+
+TEST_F(SignalKeyTest, TestUsesSafeBinaryFormat) {
+ // By testing that the underlying format is the binary version of
+ // SignalKeyInternal, we can ensure API guarantees based on SignalKeyInternal.
+ SignalKey key(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ test_clock_.Now() + base::TimeDelta::FromSeconds(10));
+
+ std::string binary_key = key.ToBinary();
+ SignalKeyInternal internal_key;
+ SignalKeyInternalFromBinary(binary_key, &internal_key);
+ EXPECT_EQ('u', internal_key.prefix.kind);
+ EXPECT_EQ(42UL, internal_key.prefix.name_hash);
+ EXPECT_EQ(11644502400, internal_key.time_range_start_sec);
+ EXPECT_EQ(11644502410, internal_key.time_range_end_sec);
+}
+
+TEST_F(SignalKeyTest, TestGetPrefixInBinary) {
+ SignalKey key(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ test_clock_.Now() + base::TimeDelta::FromSeconds(10));
+
+ std::string binary_prefix = key.GetPrefixInBinary();
+ SignalKeyInternal::Prefix prefix;
+ SignalKeyInternalPrefixFromBinary(binary_prefix, &prefix);
+ EXPECT_EQ('u', prefix.kind);
+ EXPECT_EQ(42UL, prefix.name_hash);
+}
+
+TEST_F(SignalKeyTest, EarliestEndTimeComesFirst) {
+ SignalKey early(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ test_clock_.Now());
+
+ SignalKey late(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ test_clock_.Now() + base::TimeDelta::FromSeconds(20));
+
+ EXPECT_LT(CompareBinaryKeys(early, late), 0);
+}
+
+TEST_F(SignalKeyTest, EqualKeysHaveEqualBinaryKeys) {
+ SignalKey a(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ test_clock_.Now());
+ SignalKey b(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ test_clock_.Now());
+
+ EXPECT_EQ(0, CompareBinaryKeys(a, b));
+}
+
+TEST_F(SignalKeyTest, EndTimeMoreSignificantThanStartTime) {
+ SignalKey early_end(SignalKey::Kind::USER_ACTION, 42,
+ test_clock_.Now() + base::TimeDelta::FromSeconds(20),
+ test_clock_.Now() + base::TimeDelta::FromSeconds(20));
+ SignalKey early_start(SignalKey::Kind::USER_ACTION, 42,
+ test_clock_.Now() + base::TimeDelta::FromSeconds(10),
+ test_clock_.Now() + base::TimeDelta::FromSeconds(30));
+
+ EXPECT_LT(CompareBinaryKeys(early_end, early_start), 0);
+}
+
+TEST_F(SignalKeyTest, OrderByStartTimeIfEverythingElseIsEqual) {
+ SignalKey early_start(SignalKey::Kind::USER_ACTION, 42,
+ test_clock_.Now() + base::TimeDelta::FromSeconds(10),
+ test_clock_.Now());
+ SignalKey late_start(SignalKey::Kind::USER_ACTION, 42,
+ test_clock_.Now() + base::TimeDelta::FromSeconds(20),
+ test_clock_.Now());
+
+ EXPECT_LT(CompareBinaryKeys(early_start, late_start), 0);
+}
+
+TEST_F(SignalKeyTest, DifferentNameHashGivesDifferentKey) {
+ SignalKey a(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ test_clock_.Now());
+ SignalKey b(SignalKey::Kind::USER_ACTION, 84, test_clock_.Now(),
+ test_clock_.Now());
+
+ EXPECT_NE(0, CompareBinaryKeys(a, b));
+}
+
+TEST_F(SignalKeyTest, DifferentKindGivesDifferentKey) {
+ SignalKey a(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ test_clock_.Now());
+ SignalKey b(SignalKey::Kind::HISTOGRAM_VALUE, 42, test_clock_.Now(),
+ test_clock_.Now());
+
+ EXPECT_NE(0, CompareBinaryKeys(a, b));
+}
+
+TEST_F(SignalKeyTest, TestKeyDebugStringRepresentation) {
+ SignalKey key(SignalKey::Kind::USER_ACTION, 42, test_clock_.Now(),
+ test_clock_.Now() + base::TimeDelta::FromSeconds(10));
+
+ EXPECT_EQ(
+ "{kind=1, name_hash=42, range_start=1970-01-01 08:00:00.000 UTC, "
+ "range_end=1970-01-01 08:00:10.000 UTC}",
+ key.ToDebugString());
+ std::stringstream key_buffer;
+ key_buffer << key;
+ EXPECT_EQ(
+ "{kind=1, name_hash=42, range_start=1970-01-01 08:00:00.000 UTC, "
+ "range_end=1970-01-01 08:00:10.000 UTC}",
+ key_buffer.str());
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/signal_storage_config.cc b/chromium/components/segmentation_platform/internal/database/signal_storage_config.cc
new file mode 100644
index 00000000000..7768fd2ddb5
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_storage_config.cc
@@ -0,0 +1,226 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/database/signal_storage_config.h"
+
+#include "base/callback_helpers.h"
+#include "base/containers/contains.h"
+#include "components/segmentation_platform/internal/database/metadata_utils.h"
+
+namespace segmentation_platform {
+namespace {
+// The key of the one and only entry in the database.
+const char kDatabaseKey[] = "config";
+} // namespace
+
+SignalStorageConfig::SignalStorageConfig(
+ std::unique_ptr<SignalStorageConfigProtoDb> database,
+ base::Clock* clock)
+ : database_(std::move(database)), clock_(clock) {}
+
+SignalStorageConfig::~SignalStorageConfig() = default;
+
+void SignalStorageConfig::InitAndLoad(SuccessCallback callback) {
+ database_->Init(
+ leveldb_proto::CreateSimpleOptions(),
+ base::BindOnce(&SignalStorageConfig::OnDatabaseInitialized,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void SignalStorageConfig::OnDatabaseInitialized(
+ SuccessCallback callback,
+ leveldb_proto::Enums::InitStatus status) {
+ if (status != leveldb_proto::Enums::InitStatus::kOK) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ database_->LoadEntries(base::BindOnce(&SignalStorageConfig::OnDataLoaded,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(callback)));
+}
+
+void SignalStorageConfig::OnDataLoaded(
+ SuccessCallback callback,
+ bool success,
+ std::unique_ptr<std::vector<proto::SignalStorageConfigs>> entries) {
+ if (!success || !entries) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ // We should only have one entry in the DB, or zero if it is the first time.
+ if (entries->empty()) {
+ std::move(callback).Run(true);
+ return;
+ }
+
+ DCHECK(entries->size() == 1);
+ config_ = std::move(entries->at(0));
+ std::move(callback).Run(true);
+}
+
+proto::SignalStorageConfig* SignalStorageConfig::FindSignal(
+ uint64_t signal_hash,
+ proto::SignalType signal_type) {
+ // TODO(shaktisahu): May be have an internal map of signals.
+ for (int i = 0; i < config_.signals().size(); ++i) {
+ auto* signal_config = config_.mutable_signals(i);
+ if (signal_config->name_hash() == signal_hash &&
+ signal_config->signal_type() == signal_type) {
+ return signal_config;
+ }
+ }
+ return nullptr;
+}
+
+bool SignalStorageConfig::MeetsSignalCollectionRequirement(
+ const proto::SegmentationModelMetadata& model_metadata) {
+ base::TimeDelta min_signal_collection_length =
+ model_metadata.min_signal_collection_length() *
+ metadata_utils::GetTimeUnit(model_metadata);
+
+ // Loop through all the signals specified in the model, and check if they have
+ // been collected long enough.
+ for (int i = 0; i < model_metadata.features_size(); ++i) {
+ const proto::Feature& feature = model_metadata.features(i);
+ // Skip the signals that has bucket_count set to 0. These ones are only for
+ // collection purposes and hence don't get used in model evaluation.
+ if (feature.bucket_count() == 0)
+ continue;
+
+ if (metadata_utils::ValidateMetadataFeature(feature) !=
+ metadata_utils::ValidationResult::kValidationSuccess) {
+ continue;
+ }
+
+ proto::SignalStorageConfig* config =
+ FindSignal(feature.name_hash(), feature.type());
+ if (!config || config->collection_start_time_s() == 0)
+ return false;
+
+ base::Time collection_start_time = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromSeconds(config->collection_start_time_s()));
+ if (clock_->Now() - collection_start_time < min_signal_collection_length)
+ return false;
+ }
+
+ return true;
+}
+
+void SignalStorageConfig::OnSignalCollectionStarted(
+ const proto::SegmentationModelMetadata& model_metadata) {
+ int signal_storage_length =
+ model_metadata.signal_storage_length() *
+ metadata_utils::GetTimeUnit(model_metadata).InSeconds();
+
+ // Run through the model and calculate for each signal.
+ bool is_dirty = false;
+ for (int i = 0; i < model_metadata.features_size(); ++i) {
+ const proto::Feature& feature = model_metadata.features(i);
+ if (metadata_utils::ValidateMetadataFeature(feature) !=
+ metadata_utils::ValidationResult::kValidationSuccess) {
+ continue;
+ }
+
+ proto::SignalStorageConfig* config =
+ FindSignal(feature.name_hash(), feature.type());
+ if (config) {
+ if (config->storage_length_s() < signal_storage_length) {
+ // We found a model that has a longer storage length requirement. Update
+ // it to DB.
+ config->set_storage_length_s(signal_storage_length);
+ is_dirty = true;
+ }
+ } else {
+ // This is the first time we have encountered this signal. Just create an
+ // entry in the DB, and set collection start time.
+ proto::SignalStorageConfig* signal_config = config_.add_signals();
+ signal_config->set_name_hash(feature.name_hash());
+ signal_config->set_signal_type(feature.type());
+ signal_config->set_storage_length_s(signal_storage_length);
+ signal_config->set_collection_start_time_s(
+ clock_->Now().ToDeltaSinceWindowsEpoch().InSeconds());
+ is_dirty = true;
+ }
+ }
+
+ if (is_dirty)
+ WriteToDB();
+}
+
+void SignalStorageConfig::GetSignalsForCleanup(
+ const std::set<std::pair<uint64_t, proto::SignalType>>& known_signals,
+ std::vector<std::tuple<uint64_t, proto::SignalType, base::Time>>& result)
+ const {
+ // Collect the signals that have longer than required data.
+ for (int i = 0; i < config_.signals_size(); ++i) {
+ const auto& signal_config = config_.signals(i);
+ base::Time collection_start_time = base::Time::FromDeltaSinceWindowsEpoch(
+ base::TimeDelta::FromSeconds(signal_config.collection_start_time_s()));
+ base::TimeDelta required_storage_length =
+ base::TimeDelta::FromSeconds(signal_config.storage_length_s());
+ base::Time earliest_needed_timestamp =
+ clock_->Now() - required_storage_length;
+
+ if (earliest_needed_timestamp < collection_start_time)
+ continue;
+
+ result.emplace_back(std::make_tuple(signal_config.name_hash(),
+ signal_config.signal_type(),
+ earliest_needed_timestamp));
+ }
+
+ // Now collect the signals that aren't used by any of the models.
+ if (known_signals.empty())
+ return;
+
+ for (int i = 0; i < config_.signals_size(); ++i) {
+ const auto& signal_config = config_.signals(i);
+ if (base::Contains(known_signals,
+ std::make_pair(signal_config.name_hash(),
+ signal_config.signal_type()))) {
+ continue;
+ }
+
+ result.emplace_back(std::make_tuple(
+ signal_config.name_hash(), signal_config.signal_type(), clock_->Now()));
+ }
+}
+
+void SignalStorageConfig::UpdateSignalsForCleanup(
+ const std::vector<std::tuple<uint64_t, proto::SignalType, base::Time>>&
+ signals) {
+ bool is_dirty = false;
+ for (auto& tuple : signals) {
+ uint64_t name_hash = std::get<0>(tuple);
+ proto::SignalType signal_type = std::get<1>(tuple);
+ base::Time timestamp = std::get<2>(tuple);
+
+ proto::SignalStorageConfig* signal_config =
+ FindSignal(name_hash, signal_type);
+ if (!signal_config)
+ continue;
+
+ signal_config->set_collection_start_time_s(
+ timestamp.ToDeltaSinceWindowsEpoch().InSeconds());
+ is_dirty = true;
+ }
+
+ if (is_dirty)
+ WriteToDB();
+}
+
+void SignalStorageConfig::WriteToDB() {
+ auto entries_to_save = std::make_unique<
+ std::vector<std::pair<std::string, proto::SignalStorageConfigs>>>();
+ auto keys_to_delete = std::make_unique<std::vector<std::string>>();
+
+ entries_to_save->emplace_back(std::make_pair(kDatabaseKey, config_));
+ database_->UpdateEntries(std::move(entries_to_save),
+ std::move(keys_to_delete),
+ std::move(base::DoNothing()));
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/signal_storage_config.h b/chromium/components/segmentation_platform/internal/database/signal_storage_config.h
new file mode 100644
index 00000000000..f44f30c2c07
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_storage_config.h
@@ -0,0 +1,105 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_STORAGE_CONFIG_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_STORAGE_CONFIG_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/time/clock.h"
+#include "components/leveldb_proto/public/proto_database.h"
+#include "components/segmentation_platform/internal/database/signal_key.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/signal_storage_config.pb.h"
+
+namespace segmentation_platform {
+
+// SignalStorageConfig is used to determine whether the signals for a model have
+// been captured long enough to be used for model evaluation. It is also used
+// for cleaning up the old entries for a signal in the signal database. It's
+// able to answer these two questions based on storing (1) The timestamp of the
+// first time we encountered the signal. (2) The longest storage requirement to
+// store the signal across models. The DB is read to memory on startup, so that
+// subsequent queries can be answered synchronously.
+class SignalStorageConfig {
+ public:
+ using SuccessCallback = base::OnceCallback<void(bool)>;
+ using SignalStorageConfigProtoDb =
+ leveldb_proto::ProtoDatabase<proto::SignalStorageConfigs>;
+ SignalStorageConfig(std::unique_ptr<SignalStorageConfigProtoDb> database,
+ base::Clock* clock);
+ virtual ~SignalStorageConfig();
+
+ // Disallow copy/assign.
+ SignalStorageConfig(const SignalStorageConfig& other) = delete;
+ SignalStorageConfig operator=(const SignalStorageConfig& other) = delete;
+
+ // Initializes the DB and loads it to memory. Only called at startup, and
+ // after that all client operations are synchronous.
+ virtual void InitAndLoad(SuccessCallback callback);
+
+ // Called to determine whether or not all the required signals in the given
+ // model have been collected long enough to be eligible for using in model
+ // evaluation. The model should be skipped if it hasn't been captured long
+ // enough.
+ virtual bool MeetsSignalCollectionRequirement(
+ const proto::SegmentationModelMetadata& model_metadata);
+
+ // Called whenever we find a model. Noop for existing models. Loops through
+ // all the signals and updates their storage requirements. Also sets their
+ // collection start time if not set already. This will be called for all the
+ // models and eventually will store the longest storage length requirement for
+ // every signal.
+ virtual void OnSignalCollectionStarted(
+ const proto::SegmentationModelMetadata& model_metadata);
+
+ // Called to get a list of signals that can be cleaned up along with the
+ // respective timestamp before which the signal can be cleaned up. The signals
+ // can be cleaned up in two situations.
+ // 1. If we have longer signal data than the maximum length required to store.
+ // 2. If the signal isn't needed by any model any more.
+ // (2) will be ignored if |known_signals| is passed as empty.
+ // The result of the operation will be stored in the |result|.
+ virtual void GetSignalsForCleanup(
+ const std::set<std::pair<uint64_t, proto::SignalType>>& known_signals,
+ std::vector<std::tuple<uint64_t, proto::SignalType, base::Time>>& result)
+ const;
+
+ // Called to notify that the SignalDatabase entries have been cleaned up. Now
+ // it should update the collection start timestamp in the SignalStorageConfig.
+ virtual void UpdateSignalsForCleanup(
+ const std::vector<std::tuple<uint64_t, proto::SignalType, base::Time>>&
+ signals);
+
+ private:
+ void OnDatabaseInitialized(SuccessCallback callback,
+ leveldb_proto::Enums::InitStatus status);
+
+ void OnDataLoaded(
+ SuccessCallback callback,
+ bool success,
+ std::unique_ptr<std::vector<proto::SignalStorageConfigs>> entries);
+
+ proto::SignalStorageConfig* FindSignal(uint64_t signal_hash,
+ proto::SignalType signal_type);
+
+ // Helper method to flush the cached data to the DB. Called whenever the cache
+ // is dirty.
+ void WriteToDB();
+
+ // Cached copy of the DB. Loaded at startup and used subsequently for faster
+ // read and write. Written back to DB whenever it is updated.
+ proto::SignalStorageConfigs config_;
+
+ std::unique_ptr<SignalStorageConfigProtoDb> database_;
+
+ base::Clock* clock_;
+
+ base::WeakPtrFactory<SignalStorageConfig> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_SIGNAL_STORAGE_CONFIG_H_
diff --git a/chromium/components/segmentation_platform/internal/database/signal_storage_config_unittest.cc b/chromium/components/segmentation_platform/internal/database/signal_storage_config_unittest.cc
new file mode 100644
index 00000000000..2c43e590381
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/signal_storage_config_unittest.cc
@@ -0,0 +1,254 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/database/signal_storage_config.h"
+
+#include "base/metrics/metrics_hashes.h"
+#include "base/test/mock_callback.h"
+#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
+#include "components/leveldb_proto/public/proto_database.h"
+#include "components/leveldb_proto/testing/fake_db.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using InitStatus = leveldb_proto::Enums::InitStatus;
+
+namespace segmentation_platform {
+
+namespace {
+const char kDatabaseKey[] = "config";
+
+} // namespace
+
+class SignalStorageConfigTest : public testing::Test {
+ public:
+ SignalStorageConfigTest() = default;
+ ~SignalStorageConfigTest() override = default;
+
+ protected:
+ void SetUpDB() {
+ DCHECK(!db_);
+ DCHECK(!signal_storage_config_);
+
+ auto db = std::make_unique<
+ leveldb_proto::test::FakeDB<proto::SignalStorageConfigs>>(&db_entries_);
+ db_ = db.get();
+ signal_storage_config_ =
+ std::make_unique<SignalStorageConfig>(std::move(db), &test_clock_);
+ test_clock_.SetNow(base::Time::Now());
+ }
+
+ void TearDown() override {
+ db_entries_.clear();
+ db_ = nullptr;
+ signal_storage_config_.reset();
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ base::SimpleTestClock test_clock_;
+ std::map<std::string, proto::SignalStorageConfigs> db_entries_;
+ leveldb_proto::test::FakeDB<proto::SignalStorageConfigs>* db_{nullptr};
+ std::unique_ptr<SignalStorageConfig> signal_storage_config_;
+};
+
+TEST_F(SignalStorageConfigTest,
+ CheckMeetsSignalCollectionRequirementWithMultipleModels) {
+ // Start with empty DB.
+ SetUpDB();
+ base::MockCallback<SignalStorageConfig::SuccessCallback> init_callback;
+ EXPECT_CALL(init_callback, Run(true)).Times(1);
+ signal_storage_config_->InitAndLoad(init_callback.Get());
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ db_->LoadCallback(true);
+ EXPECT_EQ(0u, db_entries_.size());
+
+ // Create a model metadata.
+ proto::SegmentationModelMetadata metadata;
+ metadata.set_time_unit(proto::TimeUnit::DAY);
+ metadata.set_signal_storage_length(2);
+ metadata.set_min_signal_collection_length(2);
+
+ // Create a second model metadata with longer requirement.
+ proto::SegmentationModelMetadata metadata2;
+ metadata2.set_time_unit(proto::TimeUnit::DAY);
+ metadata2.set_signal_storage_length(6);
+ metadata2.set_min_signal_collection_length(4);
+
+ // Add a user action feature to the both models.
+ proto::Feature* feature = metadata.add_features();
+ uint64_t name_hash = base::HashMetricName("some user action");
+ feature->set_type(proto::SignalType::USER_ACTION);
+ feature->set_name_hash(name_hash);
+ feature->set_bucket_count(1);
+ feature->set_tensor_length(1);
+ feature->set_aggregation(proto::Aggregation::COUNT);
+ proto::Feature* feature2 = metadata2.add_features();
+ feature2->set_type(proto::SignalType::USER_ACTION);
+ feature2->set_name_hash(name_hash);
+ feature2->set_bucket_count(1);
+ feature2->set_tensor_length(1);
+ feature2->set_aggregation(proto::Aggregation::COUNT);
+
+ // The DB should be empty before the model is added.
+ EXPECT_EQ(0u, db_entries_.size());
+
+ // Add the model.
+ EXPECT_FALSE(
+ signal_storage_config_->MeetsSignalCollectionRequirement(metadata));
+ signal_storage_config_->OnSignalCollectionStarted(metadata);
+ db_->UpdateCallback(true);
+
+ // Verify that the DB has now a top level entry.
+ EXPECT_EQ(1u, db_entries_.size());
+ const auto& config = db_entries_[kDatabaseKey];
+ EXPECT_EQ(1, config.signals_size());
+
+ // Verify that DB has a signal entry with correct storage and collection start
+ // time.
+ proto::SignalStorageConfig signal_config = config.signals(0);
+ EXPECT_EQ(name_hash, signal_config.name_hash());
+ EXPECT_EQ(proto::SignalType::USER_ACTION, signal_config.signal_type());
+ EXPECT_EQ(base::TimeDelta::FromDays(2).InSeconds(),
+ signal_config.storage_length_s());
+ EXPECT_NE(0, signal_config.collection_start_time_s());
+
+ // Add the second model. It should do a overwrite of previous value.
+ signal_storage_config_->OnSignalCollectionStarted(metadata2);
+ db_->UpdateCallback(true);
+
+ // Verify DB size.
+ EXPECT_EQ(1u, db_entries_.size());
+ EXPECT_EQ(1, config.signals_size());
+
+ // Verify that DB has a signal entry with correct storage and collection start
+ // time.
+ signal_config = config.signals(0);
+ EXPECT_EQ(name_hash, signal_config.name_hash());
+ EXPECT_EQ(proto::SignalType::USER_ACTION, signal_config.signal_type());
+ EXPECT_EQ(base::TimeDelta::FromDays(6).InSeconds(),
+ signal_config.storage_length_s());
+ EXPECT_NE(0, signal_config.collection_start_time_s());
+
+ // Signal collection shouldn't satisfy.
+ EXPECT_FALSE(
+ signal_storage_config_->MeetsSignalCollectionRequirement(metadata));
+
+ // Advance clock by 1 day. Start collection. Signal collection still won't
+ // satisfy.
+ test_clock_.Advance(base::TimeDelta::FromDays(1));
+ EXPECT_FALSE(
+ signal_storage_config_->MeetsSignalCollectionRequirement(metadata));
+ EXPECT_FALSE(
+ signal_storage_config_->MeetsSignalCollectionRequirement(metadata2));
+ EXPECT_NE(0, signal_config.collection_start_time_s());
+
+ // Advance clock by 2 days. Signal collection should be sufficient for the
+ // first model.
+ test_clock_.Advance(base::TimeDelta::FromDays(2));
+ EXPECT_TRUE(
+ signal_storage_config_->MeetsSignalCollectionRequirement(metadata));
+ EXPECT_NE(0, signal_config.collection_start_time_s());
+
+ // The second model shouldn't satisfy yet.
+ EXPECT_FALSE(
+ signal_storage_config_->MeetsSignalCollectionRequirement(metadata2));
+
+ // Advance clock by 3 days. Signal collection should be sufficient for second
+ // model as well.
+ test_clock_.Advance(base::TimeDelta::FromDays(3));
+ EXPECT_TRUE(
+ signal_storage_config_->MeetsSignalCollectionRequirement(metadata));
+ EXPECT_TRUE(
+ signal_storage_config_->MeetsSignalCollectionRequirement(metadata2));
+
+ // Add the model several times. DB shouldn't change.
+ signal_storage_config_->OnSignalCollectionStarted(metadata);
+ signal_config = config.signals(0);
+ EXPECT_EQ(name_hash, signal_config.name_hash());
+ EXPECT_EQ(proto::SignalType::USER_ACTION, signal_config.signal_type());
+ EXPECT_EQ(base::TimeDelta::FromDays(6).InSeconds(),
+ signal_config.storage_length_s());
+ EXPECT_NE(0, signal_config.collection_start_time_s());
+}
+
+TEST_F(SignalStorageConfigTest, CleanupSignals) {
+ SetUpDB();
+
+ // Set up DB with three signals. One expired, one unknown, and one valid.
+ proto::SignalStorageConfigs config;
+
+ // Expired.
+ proto::SignalStorageConfig* signal1 = config.add_signals();
+ signal1->set_name_hash(base::HashMetricName("1"));
+ signal1->set_signal_type(proto::SignalType::HISTOGRAM_VALUE);
+ signal1->set_collection_start_time_s(
+ (test_clock_.Now() - base::TimeDelta::FromDays(3))
+ .ToDeltaSinceWindowsEpoch()
+ .InSeconds());
+ signal1->set_storage_length_s(base::TimeDelta::FromDays(2).InSeconds());
+
+ // Unknown.
+ proto::SignalStorageConfig* signal2 = config.add_signals();
+ signal2->set_name_hash(base::HashMetricName("2"));
+ signal2->set_signal_type(proto::SignalType::HISTOGRAM_VALUE);
+ signal2->set_collection_start_time_s(
+ (test_clock_.Now() - base::TimeDelta::FromDays(3))
+ .ToDeltaSinceWindowsEpoch()
+ .InSeconds());
+ signal2->set_storage_length_s(base::TimeDelta::FromDays(5).InSeconds());
+
+ // Known.
+ proto::SignalStorageConfig* signal3 = config.add_signals();
+ signal3->set_name_hash(base::HashMetricName("3"));
+ signal3->set_signal_type(proto::SignalType::HISTOGRAM_VALUE);
+ signal3->set_collection_start_time_s(
+ (test_clock_.Now() - base::TimeDelta::FromDays(3))
+ .ToDeltaSinceWindowsEpoch()
+ .InSeconds());
+ signal3->set_storage_length_s(base::TimeDelta::FromDays(5).InSeconds());
+
+ // Initialize non-empty DB.
+ db_entries_.insert({kDatabaseKey, config});
+ base::MockCallback<SignalStorageConfig::SuccessCallback> init_callback;
+ EXPECT_CALL(init_callback, Run(true)).Times(1);
+ signal_storage_config_->InitAndLoad(init_callback.Get());
+ db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ db_->LoadCallback(true);
+ EXPECT_EQ(1u, db_entries_.size());
+
+ // Run cleanup to find expired signals
+ std::set<std::pair<uint64_t, proto::SignalType>> known_signals;
+ std::vector<std::tuple<uint64_t, proto::SignalType, base::Time>> result;
+ signal_storage_config_->GetSignalsForCleanup(known_signals, result);
+ EXPECT_EQ(1u, result.size());
+ // The first element in result tuple is the name hash.
+ EXPECT_EQ(base::HashMetricName("1"), std::get<0>(result[0]));
+ EXPECT_EQ(proto::SignalType::HISTOGRAM_VALUE, std::get<1>(result[0]));
+
+ // Run cleanup to find expired and unknown signals.
+ result.clear();
+ known_signals.insert(
+ {base::HashMetricName("1"), proto::SignalType::HISTOGRAM_VALUE});
+ known_signals.insert(
+ {base::HashMetricName("3"), proto::SignalType::HISTOGRAM_VALUE});
+ signal_storage_config_->GetSignalsForCleanup(known_signals, result);
+ EXPECT_EQ(2u, result.size());
+ // The first element in result tuple is the name hash.
+ EXPECT_EQ(base::HashMetricName("2"), std::get<0>(result[1]));
+ EXPECT_EQ(proto::SignalType::HISTOGRAM_VALUE, std::get<1>(result[1]));
+
+ // Cleanup the signals from this DB. The collection start time should be
+ // updated.
+ signal_storage_config_->UpdateSignalsForCleanup(result);
+ db_->UpdateCallback(true);
+ auto signal = db_entries_[kDatabaseKey].signals(0);
+ EXPECT_EQ((test_clock_.Now() - base::TimeDelta::FromDays(2))
+ .ToDeltaSinceWindowsEpoch()
+ .InSeconds(),
+ signal.collection_start_time_s());
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/test_segment_info_database.cc b/chromium/components/segmentation_platform/internal/database/test_segment_info_database.cc
new file mode 100644
index 00000000000..f460c110900
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/test_segment_info_database.cc
@@ -0,0 +1,208 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/database/test_segment_info_database.h"
+
+#include <algorithm>
+
+#include "base/containers/contains.h"
+#include "base/metrics/metrics_hashes.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/constants.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+
+namespace test {
+
+namespace {
+void AddFeature(proto::SegmentInfo* segment_info,
+ proto::SignalType signal_type,
+ const std::string& name,
+ uint64_t bucket_count,
+ uint64_t tensor_length,
+ proto::Aggregation aggregation,
+ const std::vector<int32_t>& accepted_enum_ids) {
+ proto::SegmentationModelMetadata* metadata =
+ segment_info->mutable_model_metadata();
+ proto::Feature* feature = metadata->add_features();
+ feature->set_type(signal_type);
+ feature->set_name(name);
+ feature->set_name_hash(base::HashMetricName(name));
+ feature->set_bucket_count(bucket_count);
+ feature->set_tensor_length(tensor_length);
+ feature->set_aggregation(aggregation);
+
+ for (int32_t accepted_enum_id : accepted_enum_ids)
+ feature->add_enum_ids(accepted_enum_id);
+}
+} // namespace
+
+TestSegmentInfoDatabase::TestSegmentInfoDatabase()
+ : SegmentInfoDatabase(nullptr) {}
+
+TestSegmentInfoDatabase::~TestSegmentInfoDatabase() = default;
+
+void TestSegmentInfoDatabase::Initialize(SuccessCallback callback) {
+ std::move(callback).Run(true);
+}
+
+void TestSegmentInfoDatabase::GetAllSegmentInfo(
+ MultipleSegmentInfoCallback callback) {
+ std::move(callback).Run(segment_infos_);
+}
+
+void TestSegmentInfoDatabase::GetSegmentInfoForSegments(
+ const std::vector<OptimizationTarget>& segment_ids,
+ MultipleSegmentInfoCallback callback) {
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>> result;
+ for (const auto& pair : segment_infos_) {
+ if (base::Contains(segment_ids, pair.first))
+ result.emplace_back(pair);
+ }
+ std::move(callback).Run(result);
+}
+
+void TestSegmentInfoDatabase::GetSegmentInfo(OptimizationTarget segment_id,
+ SegmentInfoCallback callback) {
+ auto result = std::find_if(
+ segment_infos_.begin(), segment_infos_.end(),
+ [segment_id](std::pair<OptimizationTarget, proto::SegmentInfo> pair) {
+ return pair.first == segment_id;
+ });
+
+ std::move(callback).Run(result == segment_infos_.end()
+ ? absl::nullopt
+ : absl::make_optional(result->second));
+}
+
+void TestSegmentInfoDatabase::UpdateSegment(
+ OptimizationTarget segment_id,
+ absl::optional<proto::SegmentInfo> segment_info,
+ SuccessCallback callback) {
+ if (segment_info.has_value()) {
+ proto::SegmentInfo* info = FindOrCreateSegment(segment_id);
+ info->CopyFrom(segment_info.value());
+ } else {
+ // Delete the segment.
+ auto new_end = std::remove_if(
+ segment_infos_.begin(), segment_infos_.end(),
+ [segment_id](
+ const std::pair<OptimizationTarget, proto::SegmentInfo>& pair) {
+ return pair.first == segment_id;
+ });
+ segment_infos_.erase(new_end, segment_infos_.end());
+ }
+ std::move(callback).Run(true);
+}
+
+void TestSegmentInfoDatabase::SaveSegmentResult(
+ OptimizationTarget segment_id,
+ absl::optional<proto::PredictionResult> result,
+ SuccessCallback callback) {
+ proto::SegmentInfo* info = FindOrCreateSegment(segment_id);
+ if (!result.has_value()) {
+ info->clear_prediction_result();
+ } else {
+ auto* mutable_result = info->mutable_prediction_result();
+ mutable_result->set_result(result->result());
+ mutable_result->set_timestamp_us(result->timestamp_us());
+ }
+ std::move(callback).Run(true);
+}
+
+void TestSegmentInfoDatabase::AddUserActionFeature(
+ OptimizationTarget segment_id,
+ const std::string& name,
+ uint64_t bucket_count,
+ uint64_t tensor_length,
+ proto::Aggregation aggregation) {
+ proto::SegmentInfo* info = FindOrCreateSegment(segment_id);
+ AddFeature(info, proto::SignalType::USER_ACTION, name, bucket_count,
+ tensor_length, aggregation, {});
+}
+
+void TestSegmentInfoDatabase::AddHistogramValueFeature(
+ OptimizationTarget segment_id,
+ const std::string& name,
+ uint64_t bucket_count,
+ uint64_t tensor_length,
+ proto::Aggregation aggregation) {
+ proto::SegmentInfo* info = FindOrCreateSegment(segment_id);
+ AddFeature(info, proto::SignalType::HISTOGRAM_VALUE, name, bucket_count,
+ tensor_length, aggregation, {});
+}
+
+void TestSegmentInfoDatabase::AddHistogramEnumFeature(
+ OptimizationTarget segment_id,
+ const std::string& name,
+ uint64_t bucket_count,
+ uint64_t tensor_length,
+ proto::Aggregation aggregation,
+ const std::vector<int32_t>& accepted_enum_ids) {
+ proto::SegmentInfo* info = FindOrCreateSegment(segment_id);
+ AddFeature(info, proto::SignalType::HISTOGRAM_ENUM, name, bucket_count,
+ tensor_length, aggregation, accepted_enum_ids);
+}
+
+void TestSegmentInfoDatabase::AddPredictionResult(OptimizationTarget segment_id,
+ float score,
+ base::Time timestamp) {
+ proto::SegmentInfo* info = FindOrCreateSegment(segment_id);
+ proto::PredictionResult* result = info->mutable_prediction_result();
+ result->set_result(score);
+ result->set_timestamp_us(
+ timestamp.ToDeltaSinceWindowsEpoch().InMicroseconds());
+}
+
+void TestSegmentInfoDatabase::AddDiscreteMapping(
+ OptimizationTarget segment_id,
+ float mappings[][2],
+ int num_pairs,
+ const std::string& discrete_mapping_key) {
+ proto::SegmentInfo* info = FindOrCreateSegment(segment_id);
+ auto* discrete_mappings_map =
+ info->mutable_model_metadata()->mutable_discrete_mappings();
+ auto& discrete_mappings = (*discrete_mappings_map)[discrete_mapping_key];
+ for (int i = 0; i < num_pairs; i++) {
+ auto* pair = mappings[i];
+ auto* entry = discrete_mappings.add_entries();
+ entry->set_min_result(pair[0]);
+ entry->set_rank(pair[1]);
+ }
+}
+
+void TestSegmentInfoDatabase::SetBucketDuration(OptimizationTarget segment_id,
+ uint64_t bucket_duration,
+ proto::TimeUnit time_unit) {
+ proto::SegmentInfo* info = FindOrCreateSegment(segment_id);
+ info->mutable_model_metadata()->set_bucket_duration(bucket_duration);
+ info->mutable_model_metadata()->set_time_unit(time_unit);
+}
+
+proto::SegmentInfo* TestSegmentInfoDatabase::FindOrCreateSegment(
+ OptimizationTarget segment_id) {
+ proto::SegmentInfo* info = nullptr;
+ for (auto& pair : segment_infos_) {
+ if (pair.first == segment_id) {
+ info = &pair.second;
+ break;
+ }
+ }
+
+ if (info == nullptr) {
+ segment_infos_.emplace_back(segment_id, proto::SegmentInfo());
+ info = &segment_infos_.back().second;
+ info->set_segment_id(segment_id);
+ }
+
+ return info;
+}
+
+} // namespace test
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/database/test_segment_info_database.h b/chromium/components/segmentation_platform/internal/database/test_segment_info_database.h
new file mode 100644
index 00000000000..82dab4e1dc7
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/database/test_segment_info_database.h
@@ -0,0 +1,80 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_TEST_SEGMENT_INFO_DATABASE_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_TEST_SEGMENT_INFO_DATABASE_H_
+
+#include <utility>
+#include <vector>
+
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+
+namespace segmentation_platform {
+
+namespace test {
+
+// A fake database with sample entries that can be used for tests.
+class TestSegmentInfoDatabase : public SegmentInfoDatabase {
+ public:
+ TestSegmentInfoDatabase();
+ ~TestSegmentInfoDatabase() override;
+
+ // SegmentInfoDatabase overrides.
+ void Initialize(SuccessCallback callback) override;
+ void GetAllSegmentInfo(MultipleSegmentInfoCallback callback) override;
+ void GetSegmentInfoForSegments(
+ const std::vector<OptimizationTarget>& segment_ids,
+ MultipleSegmentInfoCallback callback) override;
+ void GetSegmentInfo(OptimizationTarget segment_id,
+ SegmentInfoCallback callback) override;
+ void UpdateSegment(OptimizationTarget segment_id,
+ absl::optional<proto::SegmentInfo> segment_info,
+ SuccessCallback callback) override;
+ void SaveSegmentResult(OptimizationTarget segment_id,
+ absl::optional<proto::PredictionResult> result,
+ SuccessCallback callback) override;
+
+ // Test helper methods.
+ void AddUserActionFeature(OptimizationTarget segment_id,
+ const std::string& user_action,
+ uint64_t bucket_count,
+ uint64_t tensor_length,
+ proto::Aggregation aggregation);
+ void AddHistogramValueFeature(OptimizationTarget segment_id,
+ const std::string& histogram,
+ uint64_t bucket_count,
+ uint64_t tensor_length,
+ proto::Aggregation aggregation);
+ void AddHistogramEnumFeature(OptimizationTarget segment_id,
+ const std::string& histogram_name,
+ uint64_t bucket_count,
+ uint64_t tensor_length,
+ proto::Aggregation aggregation,
+ const std::vector<int32_t>& accepted_enum_ids);
+ void AddPredictionResult(OptimizationTarget segment_id,
+ float score,
+ base::Time timestamp);
+ void AddDiscreteMapping(OptimizationTarget segment_id,
+ float mappings[][2],
+ int num_pairs,
+ const std::string& discrete_mapping_key);
+ void SetBucketDuration(OptimizationTarget segment_id,
+ uint64_t bucket_duration,
+ proto::TimeUnit time_unit);
+
+ // Finds a segment with given |segment_id|. Creates one if it doesn't exist.
+ proto::SegmentInfo* FindOrCreateSegment(OptimizationTarget segment_id);
+
+ private:
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>> segment_infos_;
+};
+
+} // namespace test
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DATABASE_TEST_SEGMENT_INFO_DATABASE_H_
diff --git a/chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service.cc b/chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service.cc
new file mode 100644
index 00000000000..749f411a74f
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service.cc
@@ -0,0 +1,28 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/dummy_segmentation_platform_service.h"
+
+#include <string>
+
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/segmentation_platform/public/segment_selection_result.h"
+
+namespace segmentation_platform {
+
+DummySegmentationPlatformService::DummySegmentationPlatformService() = default;
+
+DummySegmentationPlatformService::~DummySegmentationPlatformService() = default;
+
+void DummySegmentationPlatformService::GetSelectedSegment(
+ const std::string& segmentation_key,
+ SegmentSelectionCallback callback) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), SegmentSelectionResult()));
+}
+
+void DummySegmentationPlatformService::EnableMetrics(
+ bool signal_collection_allowed) {}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service.h b/chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service.h
new file mode 100644
index 00000000000..0ceb1495295
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service.h
@@ -0,0 +1,35 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DUMMY_SEGMENTATION_PLATFORM_SERVICE_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DUMMY_SEGMENTATION_PLATFORM_SERVICE_H_
+
+#include "components/segmentation_platform/public/segmentation_platform_service.h"
+
+#include <string>
+
+namespace segmentation_platform {
+
+// A dummy implementation of the SegmentationPlatformService that can be
+// returned whenever the feature is not enabled.
+class DummySegmentationPlatformService : public SegmentationPlatformService {
+ public:
+ DummySegmentationPlatformService();
+ ~DummySegmentationPlatformService() override;
+
+ // Disallow copy/assign.
+ DummySegmentationPlatformService(const DummySegmentationPlatformService&) =
+ delete;
+ DummySegmentationPlatformService& operator=(
+ const DummySegmentationPlatformService&) = delete;
+
+ // SegmentationPlatformService overrides.
+ void GetSelectedSegment(const std::string& segmentation_key,
+ SegmentSelectionCallback callback) override;
+ void EnableMetrics(bool signal_collection_allowed) override;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_DUMMY_SEGMENTATION_PLATFORM_SERVICE_H_
diff --git a/chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service_unittest.cc b/chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service_unittest.cc
new file mode 100644
index 00000000000..accf532976c
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/dummy_segmentation_platform_service_unittest.cc
@@ -0,0 +1,52 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/dummy_segmentation_platform_service.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "components/segmentation_platform/internal/constants.h"
+#include "components/segmentation_platform/public/segment_selection_result.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace segmentation_platform {
+
+class DummySegmentationPlatformServiceTest : public testing::Test {
+ public:
+ DummySegmentationPlatformServiceTest() = default;
+ ~DummySegmentationPlatformServiceTest() override = default;
+
+ void SetUp() override {
+ segmentation_platform_service_ =
+ std::make_unique<DummySegmentationPlatformService>();
+ }
+
+ void OnGetSelectedSegment(base::RepeatingClosure closure,
+ const SegmentSelectionResult& expected,
+ const SegmentSelectionResult& actual) {
+ ASSERT_EQ(expected, actual);
+ std::move(closure).Run();
+ }
+
+ protected:
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<DummySegmentationPlatformService>
+ segmentation_platform_service_;
+};
+
+TEST_F(DummySegmentationPlatformServiceTest, GetSelectedSegment) {
+ SegmentSelectionResult expected;
+ base::RunLoop loop;
+ segmentation_platform_service_->GetSelectedSegment(
+ "some_key",
+ base::BindOnce(
+ &DummySegmentationPlatformServiceTest::OnGetSelectedSegment,
+ base::Unretained(this), loop.QuitClosure(), expected));
+ loop.Run();
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager.cc b/chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager.cc
new file mode 100644
index 00000000000..9263a569b50
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager.cc
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/execution/dummy_model_execution_manager.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+#include "components/segmentation_platform/internal/execution/model_execution_status.h"
+
+namespace optimization_guide {
+class OptimizationGuideModelProvider;
+using proto::OptimizationTarget;
+} // namespace optimization_guide
+
+namespace segmentation_platform {
+namespace {
+void RunModelExecutionCallback(
+ ModelExecutionManager::ModelExecutionCallback callback) {
+ std::move(callback).Run(
+ std::make_pair(0, ModelExecutionStatus::kExecutionError));
+}
+} // namespace
+
+DummyModelExecutionManager::DummyModelExecutionManager() = default;
+
+DummyModelExecutionManager::~DummyModelExecutionManager() = default;
+
+void DummyModelExecutionManager::ExecuteModel(
+ optimization_guide::proto::OptimizationTarget segment_id,
+ ModelExecutionCallback callback) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RunModelExecutionCallback, std::move(callback)));
+ return;
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager.h b/chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager.h
new file mode 100644
index 00000000000..9bf98353d8e
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager.h
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_DUMMY_MODEL_EXECUTION_MANAGER_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_DUMMY_MODEL_EXECUTION_MANAGER_H_
+
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+
+namespace segmentation_platform {
+
+// The DummyModelExecutionManager provides an implementation of the core
+// ModelExecutionManager that always posts a callback results with
+// ModelExecutionStatus::kExecutionError.
+//
+// It has no dependencies on TFLite, so it can be used even when
+// BUILDFLAG(BUILD_WITH_TFLITE_LIB) is not set.
+class DummyModelExecutionManager : public ModelExecutionManager {
+ public:
+ DummyModelExecutionManager();
+ ~DummyModelExecutionManager() override;
+
+ // Disallow copy/assign.
+ DummyModelExecutionManager(const DummyModelExecutionManager&) = delete;
+ DummyModelExecutionManager& operator=(const DummyModelExecutionManager&) =
+ delete;
+
+ // ModelExecutionManager overrides.
+ void ExecuteModel(optimization_guide::proto::OptimizationTarget segment_id,
+ ModelExecutionCallback callback) override;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_DUMMY_MODEL_EXECUTION_MANAGER_H_
diff --git a/chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager_unittest.cc b/chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager_unittest.cc
new file mode 100644
index 00000000000..feda5e8302d
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/dummy_model_execution_manager_unittest.cc
@@ -0,0 +1,61 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/execution/dummy_model_execution_manager.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/model_execution_status.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace segmentation_platform {
+class DummyModelExecutionManagerTest : public testing::Test {
+ public:
+ DummyModelExecutionManagerTest() = default;
+ ~DummyModelExecutionManagerTest() override = default;
+
+ void TearDown() override {
+ model_execution_manager_.reset();
+ // Allow for the background class to be destroyed.
+ RunUntilIdle();
+ }
+
+ void CreateModelExecutionManager() {
+ model_execution_manager_ = std::make_unique<DummyModelExecutionManager>();
+ }
+
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
+
+ void ExecuteModel() {
+ base::RunLoop loop;
+ model_execution_manager_->ExecuteModel(
+ optimization_guide::proto::OptimizationTarget::
+ OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ base::BindOnce(&DummyModelExecutionManagerTest::OnExecutionCallback,
+ base::Unretained(this), loop.QuitClosure()));
+ loop.Run();
+ }
+
+ void OnExecutionCallback(
+ base::RepeatingClosure closure,
+ const std::pair<float, ModelExecutionStatus>& actual) {
+ EXPECT_EQ(ModelExecutionStatus::kExecutionError, actual.second);
+ EXPECT_EQ(0, actual.first);
+ std::move(closure).Run();
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<DummyModelExecutionManager> model_execution_manager_;
+};
+
+TEST_F(DummyModelExecutionManagerTest, AlwaysSameResult) {
+ CreateModelExecutionManager();
+ ExecuteModel();
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/feature_aggregator.h b/chromium/components/segmentation_platform/internal/execution/feature_aggregator.h
new file mode 100644
index 00000000000..e009ecc842f
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/feature_aggregator.h
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_AGGREGATOR_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_AGGREGATOR_H_
+
+#include <cstdint>
+#include <utility>
+#include <vector>
+
+#include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+
+// The FeatureAggregator is able to convert metadata and a vector of samples
+// into a vector of resulting floats that the ML model accepts.
+class FeatureAggregator {
+ public:
+ virtual ~FeatureAggregator() = default;
+
+ // Calculate the aggregated result for the given feature metadata and samples.
+ // Assumes that the all the provided samples are valid within the required
+ // time frame.
+ virtual std::vector<float> Process(
+ proto::SignalType signal_type,
+ proto::Aggregation aggregation,
+ uint64_t length,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<SignalDatabase::Sample>& samples) const = 0;
+
+ // Removes all enum samples that are not accepted. If |accepted_enum_values|
+ // is empty, all values are accepted. Note: This modifies the input |samples|.
+ virtual void FilterEnumSamples(
+ const std::vector<int32_t>& accepted_enum_ids,
+ std::vector<SignalDatabase::Sample>& samples) const = 0;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_AGGREGATOR_H_
diff --git a/chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl.cc b/chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl.cc
new file mode 100644
index 00000000000..177cc5a33bc
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl.cc
@@ -0,0 +1,286 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/execution/feature_aggregator_impl.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <vector>
+
+#include "base/notreached.h"
+#include "base/numerics/clamped_math.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/execution/feature_aggregator.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+using Sample = SignalDatabase::Sample;
+
+namespace {
+std::vector<std::vector<Sample>> Bucketize(
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples) {
+ std::vector<std::vector<Sample>> bucketized_samples(bucket_count);
+ for (auto& sample : samples) {
+ const base::Time& timestamp = sample.first;
+ base::TimeDelta time_since_now = end_time - timestamp;
+ int bucket_index = time_since_now / bucket_duration;
+
+ // Ignore out-of-bounds samples.
+ if (bucket_index < 0 || base::saturated_cast<uint32_t>(bucket_index) >=
+ bucketized_samples.size()) {
+ continue;
+ }
+
+ bucketized_samples[bucket_index].emplace_back(sample);
+ }
+
+ return bucketized_samples;
+}
+
+int64_t SumValues(proto::SignalType signal_type,
+ const std::vector<Sample>& samples) {
+ if (signal_type == proto::SignalType::USER_ACTION)
+ return base::saturated_cast<int64_t>(samples.size());
+
+ int64_t sum = 0;
+ for (auto& sample : samples)
+ sum = base::ClampAdd(sum, sample.second);
+
+ return sum;
+}
+
+std::vector<float> CountAggregation(const std::vector<Sample>& samples) {
+ return {static_cast<float>(samples.size())};
+}
+
+std::vector<float> CountBooleanAggregation(const std::vector<Sample>& samples) {
+ return {static_cast<float>(samples.size() > 0 ? 1 : 0)};
+}
+
+std::vector<float> BucketedCountAggregation(
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples) {
+ auto bucketized_samples =
+ Bucketize(bucket_count, end_time, bucket_duration, samples);
+
+ std::vector<float> tensor_data;
+ for (auto& bucket : bucketized_samples)
+ tensor_data.emplace_back(static_cast<float>(bucket.size()));
+
+ return tensor_data;
+}
+
+std::vector<float> BucketedCountBooleanAggregation(
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples) {
+ auto bucketized_samples =
+ Bucketize(bucket_count, end_time, bucket_duration, samples);
+
+ std::vector<float> tensor_data;
+ for (auto& bucket : bucketized_samples)
+ tensor_data.emplace_back(static_cast<float>(bucket.size() > 0 ? 1 : 0));
+
+ return tensor_data;
+}
+
+std::vector<float> BucketedCountBooleanTrueCountAggregation(
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples) {
+ auto bucketized_samples =
+ Bucketize(bucket_count, end_time, bucket_duration, samples);
+
+ int64_t true_count = 0;
+ for (auto& bucket : bucketized_samples) {
+ if (bucket.size() > 0)
+ true_count = base::ClampAdd(true_count, 1);
+ }
+
+ return {static_cast<float>(true_count)};
+}
+
+std::vector<float> BucketedCumulativeCountAggregation(
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples) {
+ auto bucketized_samples =
+ Bucketize(bucket_count, end_time, bucket_duration, samples);
+
+ int64_t cumulative_count = 0;
+ std::vector<float> tensor_data;
+ for (auto& bucket : bucketized_samples) {
+ cumulative_count = base::ClampAdd(cumulative_count, bucket.size());
+ tensor_data.emplace_back(static_cast<float>(cumulative_count));
+ }
+
+ return tensor_data;
+}
+
+std::vector<float> SumAggregation(proto::SignalType signal_type,
+ const std::vector<Sample>& samples) {
+ return {static_cast<float>(SumValues(signal_type, samples))};
+}
+
+std::vector<float> SumBooleanAggregation(proto::SignalType signal_type,
+ const std::vector<Sample>& samples) {
+ return SumValues(signal_type, samples) > 0 ? std::vector<float>{1}
+ : std::vector<float>{0};
+}
+
+std::vector<float> BucketedSumAggregation(
+ proto::SignalType signal_type,
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples) {
+ auto bucketized_samples =
+ Bucketize(bucket_count, end_time, bucket_duration, samples);
+
+ std::vector<float> tensor_data;
+ for (auto& bucket : bucketized_samples) {
+ tensor_data.emplace_back(
+ static_cast<float>(SumValues(signal_type, bucket)));
+ }
+
+ return tensor_data;
+}
+
+std::vector<float> BucketedSumBooleanAggregation(
+ proto::SignalType signal_type,
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples) {
+ auto bucketized_samples =
+ Bucketize(bucket_count, end_time, bucket_duration, samples);
+
+ std::vector<float> tensor_data;
+ for (auto& bucket : bucketized_samples) {
+ tensor_data.emplace_back(
+ static_cast<float>(SumValues(signal_type, bucket) > 0 ? 1 : 0));
+ }
+
+ return tensor_data;
+}
+
+std::vector<float> BucketedSumBooleanTrueCountAggregation(
+ proto::SignalType signal_type,
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples) {
+ auto bucketized_samples =
+ Bucketize(bucket_count, end_time, bucket_duration, samples);
+
+ int64_t true_count = 0;
+ for (auto& bucket : bucketized_samples) {
+ if (SumValues(signal_type, bucket) > 0)
+ true_count = base::ClampAdd(true_count, 1);
+ }
+
+ return std::vector<float>{static_cast<float>(true_count)};
+}
+
+std::vector<float> BucketedCumulativeSumAggregation(
+ proto::SignalType signal_type,
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples) {
+ auto bucketized_samples =
+ Bucketize(bucket_count, end_time, bucket_duration, samples);
+
+ int64_t cumulative_sum = 0;
+ std::vector<float> tensor_data;
+ for (auto& bucket : bucketized_samples) {
+ cumulative_sum =
+ base::ClampAdd(cumulative_sum, SumValues(signal_type, bucket));
+ tensor_data.emplace_back(static_cast<float>(cumulative_sum));
+ }
+
+ return tensor_data;
+}
+
+} // namespace
+
+FeatureAggregatorImpl::FeatureAggregatorImpl() = default;
+
+FeatureAggregatorImpl::~FeatureAggregatorImpl() = default;
+
+std::vector<float> FeatureAggregatorImpl::Process(
+ proto::SignalType signal_type,
+ proto::Aggregation aggregation,
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples) const {
+ switch (aggregation) {
+ case proto::Aggregation::UNKNOWN:
+ NOTREACHED();
+ return std::vector<float>();
+ case proto::Aggregation::COUNT:
+ return CountAggregation(samples);
+ case proto::Aggregation::COUNT_BOOLEAN:
+ return CountBooleanAggregation(samples);
+ case proto::Aggregation::BUCKETED_COUNT:
+ return BucketedCountAggregation(bucket_count, end_time, bucket_duration,
+ samples);
+ case proto::Aggregation::BUCKETED_COUNT_BOOLEAN:
+ return BucketedCountBooleanAggregation(bucket_count, end_time,
+ bucket_duration, samples);
+ case proto::Aggregation::BUCKETED_COUNT_BOOLEAN_TRUE_COUNT:
+ return BucketedCountBooleanTrueCountAggregation(bucket_count, end_time,
+ bucket_duration, samples);
+ case proto::Aggregation::BUCKETED_CUMULATIVE_COUNT:
+ return BucketedCumulativeCountAggregation(bucket_count, end_time,
+ bucket_duration, samples);
+ case proto::Aggregation::SUM:
+ return SumAggregation(signal_type, samples);
+ case proto::Aggregation::SUM_BOOLEAN:
+ return SumBooleanAggregation(signal_type, samples);
+ case proto::Aggregation::BUCKETED_SUM:
+ return BucketedSumAggregation(signal_type, bucket_count, end_time,
+ bucket_duration, samples);
+ case proto::Aggregation::BUCKETED_SUM_BOOLEAN:
+ return BucketedSumBooleanAggregation(signal_type, bucket_count, end_time,
+ bucket_duration, samples);
+ case proto::Aggregation::BUCKETED_SUM_BOOLEAN_TRUE_COUNT:
+ return BucketedSumBooleanTrueCountAggregation(
+ signal_type, bucket_count, end_time, bucket_duration, samples);
+ case proto::Aggregation::BUCKETED_CUMULATIVE_SUM:
+ return BucketedCumulativeSumAggregation(
+ signal_type, bucket_count, end_time, bucket_duration, samples);
+ }
+}
+
+void FeatureAggregatorImpl::FilterEnumSamples(
+ const std::vector<int32_t>& accepted_enum_ids,
+ std::vector<Sample>& samples) const {
+ if (accepted_enum_ids.size() == 0)
+ return;
+
+ auto new_end = std::remove_if(
+ samples.begin(), samples.end(), [&accepted_enum_ids](Sample sample) {
+ auto found =
+ std::find(accepted_enum_ids.begin(), accepted_enum_ids.end(),
+ sample.second) != accepted_enum_ids.end();
+ return !found;
+ });
+ samples.erase(new_end, samples.end());
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl.h b/chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl.h
new file mode 100644
index 00000000000..f407e1c9f1e
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl.h
@@ -0,0 +1,46 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_AGGREGATOR_IMPL_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_AGGREGATOR_IMPL_H_
+
+#include <cstdint>
+#include <vector>
+
+#include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/execution/feature_aggregator.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+
+// Core implementation of the FeatureAggregator.
+class FeatureAggregatorImpl : public FeatureAggregator {
+ public:
+ FeatureAggregatorImpl();
+ ~FeatureAggregatorImpl() override;
+
+ // Disallow copy/assign.
+ FeatureAggregatorImpl(const FeatureAggregatorImpl&) = delete;
+ FeatureAggregatorImpl& operator=(const FeatureAggregatorImpl&) = delete;
+
+ // FeatureAggregator overrides.
+ std::vector<float> Process(
+ proto::SignalType signal_type,
+ proto::Aggregation aggregation,
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<SignalDatabase::Sample>& samples) const override;
+ void FilterEnumSamples(
+ const std::vector<int32_t>& accepted_enum_ids,
+ std::vector<SignalDatabase::Sample>& samples) const override;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_AGGREGATOR_IMPL_H_
diff --git a/chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl_unittest.cc b/chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl_unittest.cc
new file mode 100644
index 00000000000..cb8a70190ff
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/feature_aggregator_impl_unittest.cc
@@ -0,0 +1,320 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/execution/feature_aggregator_impl.h"
+
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "base/notreached.h"
+#include "base/test/simple_test_clock.h"
+#include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/execution/feature_aggregator.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+using Sample = SignalDatabase::Sample;
+using proto::Aggregation;
+using proto::SignalType;
+
+namespace {
+constexpr base::TimeDelta kDefaultBucketDuration =
+ base::TimeDelta::FromHours(3);
+constexpr base::TimeDelta kOneSecond = base::TimeDelta::FromSeconds(1);
+constexpr base::TimeDelta kTwoSeconds = base::TimeDelta::FromSeconds(2);
+constexpr base::TimeDelta kThreeSeconds = base::TimeDelta::FromSeconds(3);
+constexpr base::TimeDelta kFourSeconds = base::TimeDelta::FromSeconds(4);
+constexpr uint64_t kDefaultBucketCount = 6;
+} // namespace
+
+class FeatureAggregatorImplTest : public testing::Test {
+ public:
+ FeatureAggregatorImplTest() = default;
+ ~FeatureAggregatorImplTest() override = default;
+
+ void SetUp() override {
+ clock_.SetNow(base::Time::Now());
+ feature_aggregator_ = std::make_unique<FeatureAggregatorImpl>();
+ }
+
+ // Returns samples which when using kDefaultBucketDuration will end up in the
+ // following 6 buckets with their respective values:
+ // bucket[0] = {1, 2} (count=2, sum=3)
+ // bucket[1] = {3, 4, 5} (count=3, sum=12)
+ // bucket[2] = {6, 7, 8, 9} (count=4, sum=30)
+ // bucket[3] = {10} (count=1, sum=10)
+ // bucket[4] = {} (count=0, sum=0)
+ // bucket[5] = {11, 12, 13, 14, 15} (count=5, sum=65)
+ std::vector<Sample> value_samples() {
+ return {
+ // First bucket.
+ {clock_.Now(), 1},
+ {clock_.Now() - kOneSecond, 2},
+ // Second bucket.
+ {clock_.Now() - kDefaultBucketDuration, 3},
+ {clock_.Now() - kDefaultBucketDuration - kOneSecond, 4},
+ {clock_.Now() - kDefaultBucketDuration - kTwoSeconds, 5},
+ // Third bucket.
+ {clock_.Now() - kDefaultBucketDuration * 2, 6},
+ {clock_.Now() - kDefaultBucketDuration * 2 - kOneSecond, 7},
+ {clock_.Now() - kDefaultBucketDuration * 2 - kTwoSeconds, 8},
+ {clock_.Now() - kDefaultBucketDuration * 2 - kThreeSeconds, 9},
+ // Fourth bucket.
+ {clock_.Now() - kDefaultBucketDuration * 3, 10},
+ // Fifth bucket is empty.
+ // Sixth bucket.
+ {clock_.Now() - kDefaultBucketDuration * 5, 11},
+ {clock_.Now() - kDefaultBucketDuration * 5 - kOneSecond, 12},
+ {clock_.Now() - kDefaultBucketDuration * 5 - kTwoSeconds, 13},
+ {clock_.Now() - kDefaultBucketDuration * 5 - kThreeSeconds, 14},
+ {clock_.Now() - kDefaultBucketDuration * 5 - kFourSeconds, 15},
+ };
+ }
+
+ // Returns samples which when using kDefaultBucketDuration will end up in the
+ // following 6 buckets with their respective values:
+ // bucket[0] = {0, 0} (count=2, sum=0)
+ // bucket[1] = {0, 0, 0} (count=3, sum=0)
+ // bucket[2] = {0, 0, 0, 0} (count=4, sum=0)
+ // bucket[3] = {0} (count=1, sum=0)
+ // bucket[4] = {} (count=0, sum=0)
+ // bucket[5] = {0, 0, 0, 0, 0} (count=5, sum=0)
+ std::vector<Sample> zero_value_samples() {
+ std::vector<Sample> samples = value_samples();
+ for (auto& sample : samples)
+ sample.second = 0;
+
+ return samples;
+ }
+
+ // Verifies the result of a single invocation of Process(...), comparing to
+ // the expected output.
+ void Verify(SignalType signal_type,
+ Aggregation aggregation,
+ uint64_t bucket_count,
+ base::TimeDelta bucket_duration,
+ std::vector<Sample> samples,
+ std::vector<float> expected) {
+ std::vector<float> res =
+ feature_aggregator_->Process(signal_type, aggregation, bucket_count,
+ clock_.Now(), bucket_duration, samples);
+ EXPECT_EQ(expected, res);
+ }
+
+ // Verifies the result of a multiple invocations of Process(...), comparing to
+ // the expected output in the cases of using value samples, zero-value
+ // samples, no-value samples, and an empty input vector.
+ void VerifyAll(SignalType signal_type,
+ Aggregation aggregation,
+ std::vector<float> expected_value,
+ std::vector<float> expected_zero_value,
+ std::vector<float> expected_empty) {
+ // Value is always assumed to be 1 for USER_ACTION.
+ Verify(signal_type, aggregation, kDefaultBucketCount,
+ kDefaultBucketDuration, value_samples(), expected_value);
+
+ // Value is always assumed to be 1 for USER_ACTION.
+ Verify(signal_type, aggregation, kDefaultBucketCount,
+ kDefaultBucketDuration, zero_value_samples(), expected_zero_value);
+
+ Verify(signal_type, aggregation, kDefaultBucketCount,
+ kDefaultBucketDuration, {}, expected_empty);
+ }
+
+ base::SimpleTestClock clock_;
+ std::unique_ptr<FeatureAggregatorImpl> feature_aggregator_;
+};
+
+TEST_F(FeatureAggregatorImplTest, CountAggregation) {
+ VerifyAll(SignalType::USER_ACTION, Aggregation::COUNT, {15}, {15}, {0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM, Aggregation::COUNT, {15}, {15}, {0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE, Aggregation::COUNT, {15}, {15}, {0});
+}
+
+TEST_F(FeatureAggregatorImplTest, CountBooleanAggregation) {
+ VerifyAll(SignalType::USER_ACTION, Aggregation::COUNT_BOOLEAN, {1}, {1}, {0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM, Aggregation::COUNT_BOOLEAN, {1}, {1},
+ {0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE, Aggregation::COUNT_BOOLEAN, {1}, {1},
+ {0});
+}
+
+TEST_F(FeatureAggregatorImplTest, BucketedCountAggregation) {
+ VerifyAll(SignalType::USER_ACTION, Aggregation::BUCKETED_COUNT,
+ {2, 3, 4, 1, 0, 5}, {2, 3, 4, 1, 0, 5}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM, Aggregation::BUCKETED_COUNT,
+ {2, 3, 4, 1, 0, 5}, {2, 3, 4, 1, 0, 5}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE, Aggregation::BUCKETED_COUNT,
+ {2, 3, 4, 1, 0, 5}, {2, 3, 4, 1, 0, 5}, {0, 0, 0, 0, 0, 0});
+}
+
+TEST_F(FeatureAggregatorImplTest, BucketedCountBooleanAggregation) {
+ VerifyAll(SignalType::USER_ACTION, Aggregation::BUCKETED_COUNT_BOOLEAN,
+ {1, 1, 1, 1, 0, 1}, {1, 1, 1, 1, 0, 1}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM, Aggregation::BUCKETED_COUNT_BOOLEAN,
+ {1, 1, 1, 1, 0, 1}, {1, 1, 1, 1, 0, 1}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE, Aggregation::BUCKETED_COUNT_BOOLEAN,
+ {1, 1, 1, 1, 0, 1}, {1, 1, 1, 1, 0, 1}, {0, 0, 0, 0, 0, 0});
+}
+
+TEST_F(FeatureAggregatorImplTest, BucketedCountBooleanTrueCountAggregation) {
+ VerifyAll(SignalType::USER_ACTION,
+ Aggregation::BUCKETED_COUNT_BOOLEAN_TRUE_COUNT, {5}, {5}, {0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM,
+ Aggregation::BUCKETED_COUNT_BOOLEAN_TRUE_COUNT, {5}, {5}, {0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE,
+ Aggregation::BUCKETED_COUNT_BOOLEAN_TRUE_COUNT, {5}, {5}, {0});
+}
+
+TEST_F(FeatureAggregatorImplTest, BucketedCumulativeCountAggregation) {
+ VerifyAll(SignalType::USER_ACTION, Aggregation::BUCKETED_CUMULATIVE_COUNT,
+ {2, 5, 9, 10, 10, 15}, {2, 5, 9, 10, 10, 15}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM, Aggregation::BUCKETED_CUMULATIVE_COUNT,
+ {2, 5, 9, 10, 10, 15}, {2, 5, 9, 10, 10, 15}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE, Aggregation::BUCKETED_CUMULATIVE_COUNT,
+ {2, 5, 9, 10, 10, 15}, {2, 5, 9, 10, 10, 15}, {0, 0, 0, 0, 0, 0});
+}
+
+TEST_F(FeatureAggregatorImplTest, SumAggregation) {
+ VerifyAll(SignalType::USER_ACTION, Aggregation::SUM, {15}, {15}, {0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM, Aggregation::SUM, {120}, {0}, {0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE, Aggregation::SUM, {120}, {0}, {0});
+}
+
+TEST_F(FeatureAggregatorImplTest, SumBooleanAggregation) {
+ VerifyAll(SignalType::USER_ACTION, Aggregation::SUM_BOOLEAN, {1}, {1}, {0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM, Aggregation::SUM_BOOLEAN, {1}, {0},
+ {0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE, Aggregation::SUM_BOOLEAN, {1}, {0},
+ {0});
+}
+
+TEST_F(FeatureAggregatorImplTest, BucketedSumAggregation) {
+ VerifyAll(SignalType::USER_ACTION, Aggregation::BUCKETED_SUM,
+ {2, 3, 4, 1, 0, 5}, {2, 3, 4, 1, 0, 5}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM, Aggregation::BUCKETED_SUM,
+ {3, 12, 30, 10, 0, 65}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE, Aggregation::BUCKETED_SUM,
+ {3, 12, 30, 10, 0, 65}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0});
+}
+
+TEST_F(FeatureAggregatorImplTest, BucketedSumBooleanAggregation) {
+ VerifyAll(SignalType::USER_ACTION, Aggregation::BUCKETED_SUM_BOOLEAN,
+ {1, 1, 1, 1, 0, 1}, {1, 1, 1, 1, 0, 1}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM, Aggregation::BUCKETED_SUM_BOOLEAN,
+ {1, 1, 1, 1, 0, 1}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE, Aggregation::BUCKETED_SUM_BOOLEAN,
+ {1, 1, 1, 1, 0, 1}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0});
+}
+
+TEST_F(FeatureAggregatorImplTest, BucketedSumBooleanTrueCountAggregation) {
+ VerifyAll(SignalType::USER_ACTION,
+ Aggregation::BUCKETED_SUM_BOOLEAN_TRUE_COUNT, {5}, {5}, {0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM,
+ Aggregation::BUCKETED_SUM_BOOLEAN_TRUE_COUNT, {5}, {0}, {0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE,
+ Aggregation::BUCKETED_SUM_BOOLEAN_TRUE_COUNT, {5}, {0}, {0});
+}
+
+TEST_F(FeatureAggregatorImplTest, BucketedCumulativeSumAggregation) {
+ VerifyAll(SignalType::USER_ACTION, Aggregation::BUCKETED_CUMULATIVE_SUM,
+ {2, 5, 9, 10, 10, 15}, {2, 5, 9, 10, 10, 15}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_ENUM, Aggregation::BUCKETED_CUMULATIVE_SUM,
+ {3, 15, 45, 55, 55, 120}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0});
+
+ VerifyAll(SignalType::HISTOGRAM_VALUE, Aggregation::BUCKETED_CUMULATIVE_SUM,
+ {3, 15, 45, 55, 55, 120}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0});
+}
+
+TEST_F(FeatureAggregatorImplTest, BucketizationThresholds) {
+ std::vector<Sample> samples{
+ // First sample is exactly 1 day ago, part of second bucket.
+ {clock_.Now() - base::TimeDelta::FromDays(1), 1},
+ // Second sample is just over 1 day ago, part of second bucket.
+ {clock_.Now() - base::TimeDelta::FromDays(1) -
+ base::TimeDelta::FromSeconds(1),
+ 2},
+ // Second sample is just under 1 day ago, part of first bucket.
+ {clock_.Now() - base::TimeDelta::FromDays(1) +
+ base::TimeDelta::FromSeconds(1),
+ 3},
+ };
+
+ Verify(SignalType::USER_ACTION, Aggregation::BUCKETED_COUNT, 2,
+ base::TimeDelta::FromDays(1), samples, {1, 2});
+ Verify(SignalType::USER_ACTION, Aggregation::BUCKETED_SUM, 2,
+ base::TimeDelta::FromDays(1), samples, {1, 2});
+ Verify(SignalType::HISTOGRAM_ENUM, Aggregation::BUCKETED_COUNT, 2,
+ base::TimeDelta::FromDays(1), samples, {1, 2});
+ Verify(SignalType::HISTOGRAM_ENUM, Aggregation::BUCKETED_SUM, 2,
+ base::TimeDelta::FromDays(1), samples, {3, 3});
+ Verify(SignalType::HISTOGRAM_VALUE, Aggregation::BUCKETED_COUNT, 2,
+ base::TimeDelta::FromDays(1), samples, {1, 2});
+ Verify(SignalType::HISTOGRAM_VALUE, Aggregation::BUCKETED_SUM, 2,
+ base::TimeDelta::FromDays(1), samples, {3, 3});
+}
+
+TEST_F(FeatureAggregatorImplTest, BucketsOutOfBounds) {
+ std::vector<Sample> samples{
+ {clock_.Now() + base::TimeDelta::FromDays(1), 1}, // In the future.
+ {clock_.Now(), 2},
+ {clock_.Now() - base::TimeDelta::FromDays(1), 3},
+ {clock_.Now() - base::TimeDelta::FromDays(2), 4},
+ {clock_.Now() - base::TimeDelta::FromDays(3), 5}, // Too old.
+ };
+
+ // Using bucket count of 3, means the first sample is out of bounds for being
+ // in the future, and the last sample is out of bounds for being too old.
+ Verify(SignalType::HISTOGRAM_VALUE, Aggregation::BUCKETED_COUNT, 3,
+ base::TimeDelta::FromDays(1), samples, {1, 1, 1});
+ Verify(SignalType::HISTOGRAM_VALUE, Aggregation::BUCKETED_SUM, 3,
+ base::TimeDelta::FromDays(1), samples, {2, 3, 4});
+}
+
+TEST_F(FeatureAggregatorImplTest, FilterEnumSamples) {
+ std::vector<Sample> samples{
+ {clock_.Now(), 1}, {clock_.Now(), 2}, {clock_.Now(), 3},
+ {clock_.Now(), 4}, {clock_.Now(), 5},
+ };
+
+ // Empty accept list should keep all samples.
+ feature_aggregator_->FilterEnumSamples(std::vector<int32_t>(), samples);
+ EXPECT_EQ(5u, samples.size());
+
+ // Only accept 1 and 3 as enum values.
+ feature_aggregator_->FilterEnumSamples(std::vector<int32_t>{2, 4}, samples);
+ EXPECT_EQ(2u, samples.size());
+ EXPECT_EQ(2, samples[0].second);
+ EXPECT_EQ(4, samples[1].second);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/model_execution_manager.h b/chromium/components/segmentation_platform/internal/execution/model_execution_manager.h
new file mode 100644
index 00000000000..0b648e62019
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/model_execution_manager.h
@@ -0,0 +1,45 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_H_
+
+#include <utility>
+
+#include "base/callback_forward.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/model_execution_status.h"
+
+namespace segmentation_platform {
+namespace proto {
+class SegmentInfo;
+} // namespace proto
+
+// The ModelExecutionManager is the core class for interacting with the ML
+// framework. The only requirement is to pass in the segment ID to execute the
+// model for, and a callback will be posted with the result, once the
+// calculation has finished.
+class ModelExecutionManager {
+ public:
+ virtual ~ModelExecutionManager() = default;
+
+ // The float value is only valid when ModelExecutionStatus == kSuccess.
+ using ModelExecutionCallback =
+ base::OnceCallback<void(const std::pair<float, ModelExecutionStatus>&)>;
+
+ // Invoked whenever there are changes to the state of a segmentation model.
+ // Will not be invoked unless the proto::SegmentInfo is valid.
+ using SegmentationModelUpdatedCallback =
+ base::RepeatingCallback<void(proto::SegmentInfo)>;
+
+ // Called to execute a given model. This assumes that data has been collected
+ // for long enough for each of the individual ML features.
+ virtual void ExecuteModel(
+ optimization_guide::proto::OptimizationTarget segment_id,
+ ModelExecutionCallback callback) = 0;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_H_
diff --git a/chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory.cc b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory.cc
new file mode 100644
index 00000000000..1e19afca481
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory.cc
@@ -0,0 +1,74 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/execution/model_execution_manager_factory.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/sequenced_task_runner.h"
+#include "components/optimization_guide/machine_learning_tflite_buildflags.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/feature_aggregator.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+#include "components/segmentation_platform/internal/execution/model_execution_manager_impl.h"
+#include "components/segmentation_platform/internal/execution/segmentation_model_handler.h"
+#else
+#include "components/segmentation_platform/internal/execution/dummy_model_execution_manager.h"
+#endif // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+
+namespace base {
+class Clock;
+} // namespace base
+
+namespace optimization_guide {
+class OptimizationGuideModelProvider;
+} // namespace optimization_guide
+
+namespace segmentation_platform {
+class FeatureAggregator;
+class SegmentInfoDatabase;
+class SignalDatabase;
+
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+// CreateModelHandler makes it possible to pass in any creator of the
+// SegmentationModelHandler, which makes it possible to create mock versions.
+std::unique_ptr<SegmentationModelHandler> CreateModelHandler(
+ optimization_guide::OptimizationGuideModelProvider* model_provider,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ optimization_guide::proto::OptimizationTarget optimization_target,
+ const SegmentationModelHandler::ModelUpdatedCallback&
+ model_updated_callback) {
+ return std::make_unique<SegmentationModelHandler>(
+ model_provider, background_task_runner, optimization_target,
+ model_updated_callback);
+}
+#endif // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+
+std::unique_ptr<ModelExecutionManager> CreateModelExecutionManager(
+ optimization_guide::OptimizationGuideModelProvider* model_provider,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ std::vector<optimization_guide::proto::OptimizationTarget> segment_ids,
+ base::Clock* clock,
+ SegmentInfoDatabase* segment_database,
+ SignalDatabase* signal_database,
+ std::unique_ptr<FeatureAggregator> feature_aggregator,
+ const ModelExecutionManager::SegmentationModelUpdatedCallback&
+ model_updated_callback) {
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+ return std::make_unique<ModelExecutionManagerImpl>(
+ segment_ids,
+ base::BindRepeating(&CreateModelHandler, model_provider,
+ background_task_runner),
+ clock, segment_database, signal_database, std::move(feature_aggregator),
+ model_updated_callback);
+#else
+ return std::make_unique<DummyModelExecutionManager>();
+#endif // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory.h b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory.h
new file mode 100644
index 00000000000..d9cab7e1198
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory.h
@@ -0,0 +1,45 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_FACTORY_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_FACTORY_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/sequenced_task_runner.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+
+namespace base {
+class Clock;
+} // namespace base
+
+namespace optimization_guide {
+class OptimizationGuideModelProvider;
+} // namespace optimization_guide
+
+namespace segmentation_platform {
+class FeatureAggregator;
+class SegmentInfoDatabase;
+class SignalDatabase;
+
+// Creates a ModelExecutionManager that is appropriate for the current platform.
+// In particular, it creates a DummyModelExecutionManager in cases where
+// BUILDFLAG(BUILD_WITH_TFLITE_LIB) is not set, in case of the full
+// implementation provided by ModelExecutionManagerImpl.
+std::unique_ptr<ModelExecutionManager> CreateModelExecutionManager(
+ optimization_guide::OptimizationGuideModelProvider* model_provider,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ std::vector<optimization_guide::proto::OptimizationTarget> segment_ids,
+ base::Clock* clock,
+ SegmentInfoDatabase* segment_database,
+ SignalDatabase* signal_database,
+ std::unique_ptr<FeatureAggregator> feature_aggregator,
+ const ModelExecutionManager::SegmentationModelUpdatedCallback&
+ model_updated_callback);
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_FACTORY_H_
diff --git a/chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory_unittest.cc b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory_unittest.cc
new file mode 100644
index 00000000000..120486e14c6
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_factory_unittest.cc
@@ -0,0 +1,65 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/execution/model_execution_manager_factory.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/callback_helpers.h"
+#include "base/run_loop.h"
+#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/database/test_segment_info_database.h"
+#include "components/segmentation_platform/internal/execution/feature_aggregator_impl.h"
+#include "components/segmentation_platform/internal/execution/model_execution_status.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace segmentation_platform {
+class ModelExecutionManagerFactoryTest : public testing::Test {
+ public:
+ ModelExecutionManagerFactoryTest() = default;
+ ~ModelExecutionManagerFactoryTest() override = default;
+
+ void SetUp() override {
+ optimization_guide_model_provider_ = std::make_unique<
+ optimization_guide::TestOptimizationGuideModelProvider>();
+ segment_database_ = std::make_unique<test::TestSegmentInfoDatabase>();
+ feature_aggregator_ = std::make_unique<FeatureAggregatorImpl>();
+ test_clock_.SetNow(base::Time::Now());
+ }
+
+ void TearDown() override {
+ // Allow for the SegmentationModelExecutor owned by SegmentationModelHandler
+ // to be destroyed.
+ task_environment_.RunUntilIdle();
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<optimization_guide::TestOptimizationGuideModelProvider>
+ optimization_guide_model_provider_;
+ base::SimpleTestClock test_clock_;
+ std::unique_ptr<test::TestSegmentInfoDatabase> segment_database_;
+ std::unique_ptr<SignalDatabase> signal_database_;
+ std::unique_ptr<FeatureAggregatorImpl> feature_aggregator_;
+};
+
+TEST_F(ModelExecutionManagerFactoryTest, CreateModelExecutionManager) {
+ auto model_execution_manager = CreateModelExecutionManager(
+ optimization_guide_model_provider_.get(),
+ task_environment_.GetMainThreadTaskRunner(),
+ {OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB},
+ &test_clock_, segment_database_.get(), signal_database_.get(),
+ std::move(feature_aggregator_), base::DoNothing());
+ // This should work regardless of whether a DummyModelExecutionManager or
+ // ModelExecutionManagerImpl is returned.
+ CHECK(model_execution_manager);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc
new file mode 100644
index 00000000000..147228627b1
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc
@@ -0,0 +1,458 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/execution/model_execution_manager_impl.h"
+
+#include <deque>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/clock.h"
+#include "base/time/time.h"
+#include "base/trace_event/typed_macros.h"
+#include "components/optimization_guide/core/model_executor.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/database/metadata_utils.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/execution/feature_aggregator.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+#include "components/segmentation_platform/internal/execution/model_execution_status.h"
+#include "components/segmentation_platform/internal/execution/segmentation_model_handler.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "components/segmentation_platform/internal/stats.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/perfetto/include/perfetto/tracing/track.h"
+
+namespace optimization_guide {
+class OptimizationGuideModelProvider;
+using proto::OptimizationTarget;
+} // namespace optimization_guide
+
+namespace segmentation_platform {
+struct ModelExecutionManagerImpl::ModelExecutionTraceEvent {
+ ModelExecutionTraceEvent(
+ const char* event_name,
+ const ModelExecutionManagerImpl::ExecutionState& state);
+ ~ModelExecutionTraceEvent();
+
+ const ModelExecutionManagerImpl::ExecutionState& state;
+};
+
+struct ModelExecutionManagerImpl::ExecutionState {
+ ExecutionState()
+ : trace_event(std::make_unique<ModelExecutionTraceEvent>(
+ "ModelExecutionManagerImpl::ExecutionState",
+ *this)) {}
+ ~ExecutionState() {
+ trace_event.reset();
+ // Emit another event to ensure that the event emitted by resetting
+ // trace_event can be scraped by the tracing service (crbug.com/1021571).
+ TRACE_EVENT_INSTANT("segmentation_platform",
+ "ModelExecutionManagerImpl::~ExecutionState()");
+ }
+
+ // Disallow copy/assign.
+ ExecutionState(const ExecutionState&) = delete;
+ ExecutionState& operator=(const ExecutionState&) = delete;
+
+ // The top level event for all ExecuteModel calls is the ExecutionState
+ // trace event. This is std::unique_ptr to be able to easily reset it right
+ // before we emit an instant event at destruction time. If this is the last
+ // trace event for a thread, it will not be emitted. See
+ // https://crbug.com/1021571.
+ std::unique_ptr<ModelExecutionTraceEvent> trace_event;
+
+ OptimizationTarget segment_id;
+ SegmentationModelHandler* model_handler = nullptr;
+ ModelExecutionCallback callback;
+ base::TimeDelta bucket_duration;
+ std::deque<proto::Feature> features;
+ std::vector<float> input_tensor;
+ base::Time end_time;
+ base::Time total_execution_start_time;
+ base::Time model_execution_start_time;
+};
+
+ModelExecutionManagerImpl::ModelExecutionTraceEvent::ModelExecutionTraceEvent(
+ const char* event_name,
+ const ModelExecutionManagerImpl::ExecutionState& state)
+ : state(state) {
+ TRACE_EVENT_BEGIN("segmentation_platform", perfetto::StaticString(event_name),
+ perfetto::Track::FromPointer(&state));
+}
+
+ModelExecutionManagerImpl::ModelExecutionTraceEvent::
+ ~ModelExecutionTraceEvent() {
+ TRACE_EVENT_END("segmentation_platform",
+ perfetto::Track::FromPointer(&state));
+}
+
+struct ModelExecutionManagerImpl::FeatureState {
+ FeatureState() = default;
+ ~FeatureState() = default;
+
+ // Disallow copy/assign.
+ FeatureState(const FeatureState&) = delete;
+ FeatureState& operator=(const FeatureState&) = delete;
+
+ proto::SignalType signal_type;
+ proto::Aggregation aggregation;
+ absl::optional<std::vector<int32_t>> accepted_enum_ids;
+ uint64_t bucket_count;
+ uint64_t tensor_length;
+};
+
+ModelExecutionManagerImpl::ModelExecutionManagerImpl(
+ std::vector<OptimizationTarget> segment_ids,
+ ModelHandlerCreator model_handler_creator,
+ base::Clock* clock,
+ SegmentInfoDatabase* segment_database,
+ SignalDatabase* signal_database,
+ std::unique_ptr<FeatureAggregator> feature_aggregator,
+ const SegmentationModelUpdatedCallback& model_updated_callback)
+ : clock_(clock),
+ segment_database_(segment_database),
+ signal_database_(signal_database),
+ feature_aggregator_(std::move(feature_aggregator)),
+ model_updated_callback_(model_updated_callback) {
+ for (OptimizationTarget segment_id : segment_ids) {
+ model_handlers_.emplace(std::make_pair(
+ segment_id,
+ model_handler_creator.Run(
+ segment_id,
+ base::BindRepeating(
+ &ModelExecutionManagerImpl::OnSegmentationModelUpdated,
+ weak_ptr_factory_.GetWeakPtr()))));
+ }
+}
+
+ModelExecutionManagerImpl::~ModelExecutionManagerImpl() = default;
+
+void ModelExecutionManagerImpl::ExecuteModel(OptimizationTarget segment_id,
+ ModelExecutionCallback callback) {
+ auto model_handler_it = model_handlers_.find(segment_id);
+ DCHECK(model_handler_it != model_handlers_.end());
+
+ // Create an ExecutionState that will stay with this request until it has been
+ // fully processed.
+ auto state = std::make_unique<ExecutionState>();
+ state->segment_id = segment_id;
+ state->model_handler = (*model_handler_it).second.get();
+ state->callback = std::move(callback);
+ state->total_execution_start_time = clock_->Now();
+
+ ModelExecutionTraceEvent trace_event(
+ "ModelExecutionManagerImpl::ExecuteModel", *state);
+
+ // We first need to look up all relevant metadata for the related segment, as
+ // the metadata informs how we should process the data.
+ segment_database_->GetSegmentInfo(
+ segment_id,
+ base::BindOnce(
+ &ModelExecutionManagerImpl::OnSegmentInfoFetchedForExecution,
+ weak_ptr_factory_.GetWeakPtr(), std::move(state)));
+}
+
+void ModelExecutionManagerImpl::OnSegmentInfoFetchedForExecution(
+ std::unique_ptr<ExecutionState> state,
+ absl::optional<proto::SegmentInfo> segment_info) {
+ ModelExecutionTraceEvent trace_event(
+ "ModelExecutionManagerImpl::OnSegmentInfoFetchedForExecution", *state);
+ // It is required to have a valid and well formed segment info.
+ if (!segment_info ||
+ metadata_utils::ValidateSegmentInfo(*segment_info) !=
+ metadata_utils::ValidationResult::kValidationSuccess) {
+ RunModelExecutionCallback(std::move(state), 0,
+ ModelExecutionStatus::kInvalidMetadata);
+ return;
+ }
+
+ // The total bucket duration is defined by product of the bucket_duration
+ // value and the length of related time_unit field, e.g. 28 * length(DAY).
+ const auto& model_metadata = segment_info->model_metadata();
+ uint64_t bucket_duration = model_metadata.bucket_duration();
+ base::TimeDelta time_unit_len = metadata_utils::GetTimeUnit(model_metadata);
+ state->bucket_duration = bucket_duration * time_unit_len;
+
+ // Now that we have just fetched the metadata, set the end_time to be shared
+ // across all features, so we get a consistent picture.
+ state->end_time = clock_->Now();
+
+ // Grab the metadata for all the features, which will be processed one at a
+ // time, before executing the model.
+ for (int i = 0; i < model_metadata.features_size(); ++i)
+ state->features.emplace_back(model_metadata.features(i));
+
+ // Process all the features in-order, starting with the first feature.
+ ProcessFeatures(std::move(state));
+}
+
+void ModelExecutionManagerImpl::ProcessFeatures(
+ std::unique_ptr<ExecutionState> state) {
+ ModelExecutionTraceEvent trace_event(
+ "ModelExecutionManagerImpl::ProcessFeatures", *state);
+ // When there are no more features to process, we are done, so we execute the
+ // model.
+ if (state->features.empty()) {
+ ExecuteModel(std::move(state));
+ return;
+ }
+
+ proto::Feature feature;
+ do {
+ // Copy and pop the next feature.
+ feature = state->features.front();
+ state->features.pop_front();
+
+ // Validate the proto::Feature metadata.
+ if (metadata_utils::ValidateMetadataFeature(feature) !=
+ metadata_utils::ValidationResult::kValidationSuccess) {
+ RunModelExecutionCallback(std::move(state), 0,
+ ModelExecutionStatus::kInvalidMetadata);
+ return;
+ }
+ } while (feature.bucket_count() == 0); // Skip collection-only features.
+
+ // Capture all relevant metadata for the current proto::Feature into the
+ // FeatureState.
+ auto feature_state = std::make_unique<FeatureState>();
+ feature_state->signal_type = feature.type();
+ feature_state->aggregation = feature.aggregation();
+ feature_state->bucket_count = feature.bucket_count();
+ feature_state->tensor_length = feature.tensor_length();
+
+ auto name_hash = feature.name_hash();
+
+ // Enum histograms can optionally only accept some of the enum values.
+ // While the proto::Feature is available, capture a vector of the accepted
+ // enum values. An empty vector is ignored (all values are considered
+ // accepted).
+ if (feature_state->signal_type == proto::SignalType::HISTOGRAM_ENUM) {
+ std::vector<int32_t> accepted_enum_ids{};
+ for (int i = 0; i < feature.enum_ids_size(); ++i)
+ accepted_enum_ids.emplace_back(feature.enum_ids(i));
+
+ feature_state->accepted_enum_ids = absl::make_optional(accepted_enum_ids);
+ }
+
+ // Only fetch data that is relevant for the current proto::Feature, since
+ // the FeatureAggregator assumes that only relevant data is given to it.
+ base::TimeDelta duration =
+ state->bucket_duration * feature_state->bucket_count;
+ base::Time start_time = state->end_time - duration;
+
+ // Fetch the relevant samples for the current proto::Feature. Once the result
+ // has come back, it will be processed and inserted into the
+ // ExecutorState::input_tensor and will then invoke ProcessFeatures(...)
+ // again to ensure we continue until all features have been processed.
+ // Note: All parameters from the ExecutorState need to be captured locally
+ // before invoking GetSamples, because the state is moved with the callback,
+ // and the order of the move and accessing the members while invoking
+ // GetSamples is not guaranteed.
+ auto signal_type = feature_state->signal_type;
+ auto end_time = state->end_time;
+ signal_database_->GetSamples(
+ signal_type, name_hash, start_time, end_time,
+ base::BindOnce(&ModelExecutionManagerImpl::OnGetSamplesForFeature,
+ weak_ptr_factory_.GetWeakPtr(), std::move(state),
+ std::move(feature_state)));
+}
+
+void ModelExecutionManagerImpl::OnGetSamplesForFeature(
+ std::unique_ptr<ExecutionState> state,
+ std::unique_ptr<FeatureState> feature_state,
+ std::vector<SignalDatabase::Sample> samples) {
+ ModelExecutionTraceEvent trace_event(
+ "ModelExecutionManagerImpl::OnGetSamplesForFeature", *state);
+ base::Time process_start_time = clock_->Now();
+ // HISTOGRAM_ENUM features might require us to filter out the result to only
+ // keep enum values that match the accepted list. If the accepted list is'
+ // empty, all histogram enum values are kept.
+ // The SignalDatabase does not currently support this type of data filter,
+ // so instead we are doing this here.
+ if (feature_state->signal_type == proto::SignalType::HISTOGRAM_ENUM) {
+ DCHECK(feature_state->accepted_enum_ids.has_value());
+ feature_aggregator_->FilterEnumSamples(*feature_state->accepted_enum_ids,
+ samples);
+ }
+
+ // We now have all the data required to process a single feature, so we can
+ // process it synchronously, and insert it into the
+ // ExecutorState::input_tensor so we can later pass it to the ML model
+ // executor.
+ std::vector<float> feature_data = feature_aggregator_->Process(
+ feature_state->signal_type, feature_state->aggregation,
+ feature_state->bucket_count, state->end_time, state->bucket_duration,
+ samples);
+ DCHECK_EQ(feature_state->tensor_length, feature_data.size());
+ state->input_tensor.insert(state->input_tensor.end(), feature_data.begin(),
+ feature_data.end());
+
+ stats::RecordModelExecutionDurationFeatureProcessing(
+ state->segment_id, clock_->Now() - process_start_time);
+
+ // Continue with the rest of the features.
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ModelExecutionManagerImpl::ProcessFeatures,
+ weak_ptr_factory_.GetWeakPtr(), std::move(state)));
+}
+
+void ModelExecutionManagerImpl::ExecuteModel(
+ std::unique_ptr<ExecutionState> state) {
+ ModelExecutionTraceEvent trace_event(
+ "ModelExecutionManagerImpl::ExecuteModel", *state);
+ auto it = model_handlers_.find(state->segment_id);
+ DCHECK(it != model_handlers_.end());
+
+ SegmentationModelHandler* handler = (*it).second.get();
+ if (!handler->ModelAvailable()) {
+ RunModelExecutionCallback(std::move(state), 0,
+ ModelExecutionStatus::kExecutionError);
+ return;
+ }
+
+ const std::vector<float>& const_input_tensor = std::move(state->input_tensor);
+ stats::RecordModelExecutionZeroValuePercent(state->segment_id,
+ const_input_tensor);
+ state->model_execution_start_time = clock_->Now();
+ handler->ExecuteModelWithInput(
+ base::BindOnce(&ModelExecutionManagerImpl::OnModelExecutionComplete,
+ weak_ptr_factory_.GetWeakPtr(), std::move(state)),
+ const_input_tensor);
+}
+
+void ModelExecutionManagerImpl::OnModelExecutionComplete(
+ std::unique_ptr<ExecutionState> state,
+ const absl::optional<float>& result) {
+ ModelExecutionTraceEvent trace_event(
+ "ModelExecutionManagerImpl::OnModelExecutionComplete", *state);
+ stats::RecordModelExecutionDurationModel(
+ state->segment_id, result.has_value(),
+ clock_->Now() - state->model_execution_start_time);
+ if (result.has_value()) {
+ stats::RecordModelExecutionResult(state->segment_id, result.value());
+ RunModelExecutionCallback(std::move(state), *result,
+ ModelExecutionStatus::kSuccess);
+ } else {
+ RunModelExecutionCallback(std::move(state), 0,
+ ModelExecutionStatus::kExecutionError);
+ }
+}
+
+void ModelExecutionManagerImpl::RunModelExecutionCallback(
+ std::unique_ptr<ExecutionState> state,
+ float result,
+ ModelExecutionStatus status) {
+ stats::RecordModelExecutionDurationTotal(
+ state->segment_id, status,
+ clock_->Now() - state->total_execution_start_time);
+ stats::RecordModelExecutionStatus(state->segment_id, status);
+ std::move(state->callback).Run(std::make_pair(result, status));
+}
+
+void ModelExecutionManagerImpl::OnSegmentationModelUpdated(
+ optimization_guide::proto::OptimizationTarget segment_id,
+ proto::SegmentationModelMetadata metadata) {
+ TRACE_EVENT("segmentation_platform",
+ "ModelExecutionManagerImpl::OnSegmentationModelUpdated");
+ stats::RecordModelDeliveryReceived(segment_id);
+ if (segment_id == optimization_guide::proto::OptimizationTarget::
+ OPTIMIZATION_TARGET_UNKNOWN) {
+ return;
+ }
+
+ // Set or overwrite name hashes for metadata features based on the name field.
+ metadata_utils::SetFeatureNameHashesFromName(&metadata);
+
+ auto validation = metadata_utils::ValidateMetadataAndFeatures(metadata);
+ stats::RecordModelDeliveryMetadataValidation(
+ segment_id, /* processed = */ false, validation);
+ if (validation != metadata_utils::ValidationResult::kValidationSuccess)
+ return;
+
+ segment_database_->GetSegmentInfo(
+ segment_id,
+ base::BindOnce(
+ &ModelExecutionManagerImpl::OnSegmentInfoFetchedForModelUpdate,
+ weak_ptr_factory_.GetWeakPtr(), segment_id, std::move(metadata)));
+}
+
+void ModelExecutionManagerImpl::OnSegmentInfoFetchedForModelUpdate(
+ optimization_guide::proto::OptimizationTarget segment_id,
+ proto::SegmentationModelMetadata metadata,
+ absl::optional<proto::SegmentInfo> old_segment_info) {
+ TRACE_EVENT("segmentation_platform",
+ "ModelExecutionManagerImpl::OnSegmentInfoFetchedForModelUpdate");
+ proto::SegmentInfo new_segment_info;
+ new_segment_info.set_segment_id(segment_id);
+
+ // If we find an existing SegmentInfo in the database, we can verify that it
+ // is valid, and we can copy over the PredictionResult to the new version
+ // we are creating.
+ if (old_segment_info.has_value()) {
+ // The retrieved SegmentInfo's ID should match the one we looked up,
+ // otherwise the DB has not upheld its contract.
+ // If does not match, we should just overwrite the old entry with one
+ // that has a matching segment ID, otherwise we will keep ignoring it
+ // forever and never be able to clean it up.
+ stats::RecordModelDeliverySegmentIdMatches(
+ new_segment_info.segment_id(),
+ new_segment_info.segment_id() == old_segment_info->segment_id());
+
+ if (old_segment_info->has_prediction_result()) {
+ // If we have an old PredictionResult, we need to keep it around in the
+ // new version of the SegmentInfo.
+ auto* prediction_result = new_segment_info.mutable_prediction_result();
+ prediction_result->CopyFrom(old_segment_info->prediction_result());
+ }
+ }
+
+ // Inject the newly updated metadata into the new SegmentInfo.
+ auto* new_metadata = new_segment_info.mutable_model_metadata();
+ new_metadata->CopyFrom(metadata);
+
+ // We have a valid segment id, and the new metadata was valid, therefore the
+ // new metadata should be valid. We are not allowed to invoke the callback
+ // unless the metadata is valid.
+ auto validation =
+ metadata_utils::ValidateSegmentInfoMetadataAndFeatures(new_segment_info);
+ stats::RecordModelDeliveryMetadataValidation(
+ segment_id, /* processed = */ true, validation);
+ if (validation != metadata_utils::ValidationResult::kValidationSuccess)
+ return;
+
+ stats::RecordModelDeliveryMetadataFeatureCount(
+ segment_id, new_segment_info.model_metadata().features_size());
+ // Now that we've merged the old and the new SegmentInfo, we want to store the
+ // new version in the database.
+ segment_database_->UpdateSegment(
+ segment_id, absl::make_optional(new_segment_info),
+ base::BindOnce(&ModelExecutionManagerImpl::OnUpdatedSegmentInfoStored,
+ weak_ptr_factory_.GetWeakPtr(), new_segment_info));
+}
+
+void ModelExecutionManagerImpl::OnUpdatedSegmentInfoStored(
+ proto::SegmentInfo segment_info,
+ bool success) {
+ TRACE_EVENT("segmentation_platform",
+ "ModelExecutionManagerImpl::OnUpdatedSegmentInfoStored");
+ stats::RecordModelDeliverySaveResult(segment_info.segment_id(), success);
+ if (!success)
+ return;
+
+ // We are now ready to receive requests for execution, so invoke the callback.
+ model_updated_callback_.Run(std::move(segment_info));
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl.h b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl.h
new file mode 100644
index 00000000000..8d8d71b65df
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl.h
@@ -0,0 +1,163 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_IMPL_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_IMPL_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "components/optimization_guide/core/model_executor.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+#include "components/segmentation_platform/internal/execution/segmentation_model_handler.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace base {
+class Clock;
+} // namespace base
+
+namespace segmentation_platform {
+class FeatureAggregator;
+class SignalDatabase;
+
+namespace proto {
+class SegmentInfo;
+} // namespace proto
+
+// The ModelExecutionManagerImpl is the core implementation of the
+// ModelExecutionManager that hooks up the SegmentInfoDatabase (metadata) and
+// SignalDatabase (raw signals) databases, and uses a FeatureCalculator for each
+// feature to go from metadata and raw signals to create an input tensor to use
+// when executing the ML model. It then uses this input tensor to execute the
+// model and returns the result through a callback.
+// This class is implemented by having a long chain of callbacks and storing all
+// necessary state as part of an ExecutionState struct. This simplifies state
+// management, particularly in the case of executing multiple models
+// simultaneously, or the same model multiple times without waiting for the
+// requests to finish.
+// The vector of OptimizationTargets need to be passed in at construction time
+// so the SegmentationModelHandler instances can be created early.
+class ModelExecutionManagerImpl : public ModelExecutionManager {
+ public:
+ using ModelHandlerCreator =
+ base::RepeatingCallback<std::unique_ptr<SegmentationModelHandler>(
+ optimization_guide::proto::OptimizationTarget,
+ const SegmentationModelHandler::ModelUpdatedCallback&)>;
+
+ explicit ModelExecutionManagerImpl(
+ std::vector<OptimizationTarget> segment_ids,
+ ModelHandlerCreator model_handler_creator,
+ base::Clock* clock,
+ SegmentInfoDatabase* segment_database,
+ SignalDatabase* signal_database,
+ std::unique_ptr<FeatureAggregator> feature_aggregator,
+ const SegmentationModelUpdatedCallback& model_updated_callback);
+ ~ModelExecutionManagerImpl() override;
+
+ // Disallow copy/assign.
+ ModelExecutionManagerImpl(const ModelExecutionManagerImpl&) = delete;
+ ModelExecutionManagerImpl& operator=(const ModelExecutionManagerImpl&) =
+ delete;
+
+ // ModelExecutionManager overrides.
+ void ExecuteModel(optimization_guide::proto::OptimizationTarget segment_id,
+ ModelExecutionCallback callback) override;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(SegmentationPlatformServiceImplTest,
+ InitializationFlow);
+ struct ExecutionState;
+ struct FeatureState;
+ struct ModelExecutionTraceEvent;
+
+ // Callback method for when the SegmentInfo (segment metadata) has been
+ // loaded.
+ void OnSegmentInfoFetchedForExecution(
+ std::unique_ptr<ExecutionState> state,
+ absl::optional<proto::SegmentInfo> segment_info);
+
+ // ProcessFeatures is the core function for processing all the required ML
+ // features in the correct order. It fetches samples for one feature at a
+ // time, makes sure the data is processed, and then is invoked again to
+ // process the next feature.
+ void ProcessFeatures(std::unique_ptr<ExecutionState> state);
+
+ // Callback method for when all relevant samples for a particular feature has
+ // been loaded. Processes the samples, and inserts them into the input tensor
+ // that is later given to the ML execution.
+ void OnGetSamplesForFeature(std::unique_ptr<ExecutionState> state,
+ std::unique_ptr<FeatureState> feature_state,
+ std::vector<SignalDatabase::Sample> samples);
+
+ // ExecuteModel takes the current input tensor and passes it to the ML model
+ // for execution.
+ void ExecuteModel(std::unique_ptr<ExecutionState> state);
+
+ // Callback method for when the model execution has completed which gives the
+ // end result to the initial ModelExecutionCallback passed to
+ // ExecuteModel(...).
+ void OnModelExecutionComplete(std::unique_ptr<ExecutionState> state,
+ const absl::optional<float>& result);
+
+ // Helper function for synchronously invoking the callback with the given
+ // result and status.
+ void RunModelExecutionCallback(std::unique_ptr<ExecutionState> state,
+ float result,
+ ModelExecutionStatus status);
+
+ // Callback for whenever a SegmentationModelHandler is informed that the
+ // underlying ML model file has been updated. If there is an available
+ // model, this will be called at least once per session.
+ void OnSegmentationModelUpdated(
+ optimization_guide::proto::OptimizationTarget segment_id,
+ proto::SegmentationModelMetadata metadata);
+
+ // Callback after fetching the current SegmentInfo from the
+ // SegmentInfoDatabase. This is part of the flow for informing the
+ // SegmentationModelUpdatedCallback about a changed model.
+ // Merges the PredictionResult from the previously stored SegmentInfo with the
+ // newly updated one, and stores the new version in the DB.
+ void OnSegmentInfoFetchedForModelUpdate(
+ optimization_guide::proto::OptimizationTarget segment_id,
+ proto::SegmentationModelMetadata metadata,
+ absl::optional<proto::SegmentInfo> segment_info);
+
+ // Callback after storing the updated version of the SegmentInfo. Responsible
+ // for invoking the SegmentationModelUpdatedCallback.
+ void OnUpdatedSegmentInfoStored(proto::SegmentInfo segment_info,
+ bool success);
+
+ // All the relevant handlers for each of the segments.
+ std::map<OptimizationTarget, std::unique_ptr<SegmentationModelHandler>>
+ model_handlers_;
+
+ // Used to access the current time.
+ base::Clock* clock_;
+
+ // Database for segment information and metadata.
+ SegmentInfoDatabase* segment_database_;
+
+ // Main signal database for user actions and histograms.
+ SignalDatabase* signal_database_;
+
+ // The FeatureAggregator aggregates all the data based on metadata and input.
+ std::unique_ptr<FeatureAggregator> feature_aggregator_;
+
+ // Invoked whenever there is an update to any of the relevant ML models.
+ SegmentationModelUpdatedCallback model_updated_callback_;
+
+ base::WeakPtrFactory<ModelExecutionManagerImpl> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_MANAGER_IMPL_H_
diff --git a/chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc
new file mode 100644
index 00000000000..1a6ef85d5cd
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc
@@ -0,0 +1,722 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/execution/model_execution_manager_impl.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/callback_helpers.h"
+#include "base/metrics/metrics_hashes.h"
+#include "base/run_loop.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/gtest_util.h"
+#include "base/test/mock_callback.h"
+#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/database/metadata_utils.h"
+#include "components/segmentation_platform/internal/database/mock_signal_database.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/database/test_segment_info_database.h"
+#include "components/segmentation_platform/internal/execution/feature_aggregator.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+#include "components/segmentation_platform/internal/execution/model_execution_status.h"
+#include "components/segmentation_platform/internal/execution/segmentation_model_handler.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::base::test::RunOnceCallback;
+using testing::_;
+using testing::Return;
+using testing::SaveArg;
+using testing::SetArgReferee;
+
+namespace segmentation_platform {
+using Sample = SignalDatabase::Sample;
+
+namespace {
+constexpr base::TimeDelta kOneSecond = base::TimeDelta::FromSeconds(1);
+constexpr base::TimeDelta kTwoSeconds = base::TimeDelta::FromSeconds(2);
+} // namespace
+
+class MockSegmentInfoDatabase : public test::TestSegmentInfoDatabase {
+ public:
+ MOCK_METHOD(void, Initialize, (SuccessCallback callback), (override));
+ MOCK_METHOD(void,
+ GetAllSegmentInfo,
+ (MultipleSegmentInfoCallback callback),
+ (override));
+ MOCK_METHOD(void,
+ GetSegmentInfoForSegments,
+ (const std::vector<OptimizationTarget>& segment_ids,
+ MultipleSegmentInfoCallback callback),
+ (override));
+ MOCK_METHOD(void,
+ GetSegmentInfo,
+ (OptimizationTarget segment_id, SegmentInfoCallback callback),
+ (override));
+ MOCK_METHOD(void,
+ UpdateSegment,
+ (OptimizationTarget segment_id,
+ absl::optional<proto::SegmentInfo> segment_info,
+ SuccessCallback callback),
+ (override));
+ MOCK_METHOD(void,
+ SaveSegmentResult,
+ (OptimizationTarget segment_id,
+ absl::optional<proto::PredictionResult> result,
+ SuccessCallback callback),
+ (override));
+};
+
+class MockSegmentationModelHandler : public SegmentationModelHandler {
+ public:
+ MockSegmentationModelHandler(
+ optimization_guide::OptimizationGuideModelProvider* model_provider,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ optimization_guide::proto::OptimizationTarget optimization_target,
+ const SegmentationModelHandler::ModelUpdatedCallback&
+ model_updated_callback)
+ : SegmentationModelHandler(model_provider,
+ background_task_runner,
+ optimization_target,
+ model_updated_callback) {}
+
+ MOCK_METHOD(void,
+ ExecuteModelWithInput,
+ (base::OnceCallback<void(const absl::optional<float>&)> callback,
+ const std::vector<float>& input),
+ (override));
+
+ MOCK_METHOD(bool, ModelAvailable, (), (const override));
+};
+
+class MockFeatureAggregator : public FeatureAggregator {
+ public:
+ MockFeatureAggregator() = default;
+ MOCK_METHOD(std::vector<float>,
+ Process,
+ (proto::SignalType signal_type,
+ proto::Aggregation aggregation,
+ uint64_t bucket_count,
+ const base::Time& end_time,
+ const base::TimeDelta& bucket_duration,
+ const std::vector<Sample>& samples),
+ (const override));
+ MOCK_METHOD(void,
+ FilterEnumSamples,
+ (const std::vector<int32_t>& accepted_enum_ids,
+ std::vector<Sample>& samples),
+ (const override));
+};
+
+class ModelExecutionManagerTest : public testing::Test {
+ public:
+ ModelExecutionManagerTest() = default;
+ ~ModelExecutionManagerTest() override = default;
+
+ void SetUp() override {
+ optimization_guide_model_provider_ = std::make_unique<
+ optimization_guide::TestOptimizationGuideModelProvider>();
+ segment_database_ = std::make_unique<test::TestSegmentInfoDatabase>();
+ signal_database_ = std::make_unique<MockSignalDatabase>();
+ clock_.SetNow(base::Time::Now());
+ }
+
+ void TearDown() override {
+ model_execution_manager_.reset();
+ // Allow for the SegmentationModelExecutor owned by SegmentationModelHandler
+ // to be destroyed.
+ RunUntilIdle();
+ }
+
+ void CreateModelExecutionManager(
+ std::vector<OptimizationTarget> segment_ids,
+ const ModelExecutionManager::SegmentationModelUpdatedCallback& callback) {
+ auto feature_aggregator = std::make_unique<MockFeatureAggregator>();
+ feature_aggregator_ = feature_aggregator.get();
+
+ model_execution_manager_ = std::make_unique<ModelExecutionManagerImpl>(
+ segment_ids,
+ base::BindRepeating(&ModelExecutionManagerTest::CreateModelHandler,
+ base::Unretained(this)),
+ &clock_, segment_database_.get(), signal_database_.get(),
+ std::move(feature_aggregator), callback);
+ }
+
+ std::unique_ptr<SegmentationModelHandler> CreateModelHandler(
+ optimization_guide::proto::OptimizationTarget segment_id,
+ const SegmentationModelHandler::ModelUpdatedCallback&
+ model_updated_callback) {
+ auto handler = std::make_unique<MockSegmentationModelHandler>(
+ optimization_guide_model_provider_.get(),
+ task_environment_.GetMainThreadTaskRunner(), segment_id,
+ model_updated_callback);
+ model_handlers_.emplace(std::make_pair(segment_id, handler.get()));
+ model_handlers_callbacks_.emplace(
+ std::make_pair(segment_id, model_updated_callback));
+ return handler;
+ }
+
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
+
+ void ExecuteModel(const std::pair<float, ModelExecutionStatus>& expected) {
+ base::RunLoop loop;
+ model_execution_manager_->ExecuteModel(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ base::BindOnce(&ModelExecutionManagerTest::OnExecutionCallback,
+ base::Unretained(this), loop.QuitClosure(), expected));
+ loop.Run();
+ }
+
+ void OnExecutionCallback(
+ base::RepeatingClosure closure,
+ const std::pair<float, ModelExecutionStatus>& expected,
+ const std::pair<float, ModelExecutionStatus>& actual) {
+ EXPECT_EQ(expected.second, actual.second);
+ EXPECT_NEAR(expected.first, actual.first, 1e-5);
+ std::move(closure).Run();
+ }
+
+ MockSegmentationModelHandler& FindHandler(
+ optimization_guide::proto::OptimizationTarget segment_id) {
+ return *(*model_handlers_.find(segment_id)).second;
+ }
+
+ base::Time StartTime(base::TimeDelta bucket_duration, int64_t bucket_count) {
+ return clock_.Now() - bucket_duration * bucket_count;
+ }
+
+ base::test::TaskEnvironment task_environment_;
+
+ std::unique_ptr<optimization_guide::TestOptimizationGuideModelProvider>
+ optimization_guide_model_provider_;
+ std::map<OptimizationTarget, MockSegmentationModelHandler*> model_handlers_;
+ std::map<OptimizationTarget, SegmentationModelHandler::ModelUpdatedCallback>
+ model_handlers_callbacks_;
+ base::SimpleTestClock clock_;
+ std::unique_ptr<test::TestSegmentInfoDatabase> segment_database_;
+ std::unique_ptr<MockSignalDatabase> signal_database_;
+ MockFeatureAggregator* feature_aggregator_;
+
+ std::unique_ptr<ModelExecutionManagerImpl> model_execution_manager_;
+};
+
+TEST_F(ModelExecutionManagerTest, HandlerNotRegistered) {
+ CreateModelExecutionManager({}, base::DoNothing());
+ EXPECT_DCHECK_DEATH(
+ ExecuteModel(std::make_pair(0, ModelExecutionStatus::kExecutionError)));
+}
+
+TEST_F(ModelExecutionManagerTest, MetadataTests) {
+ auto segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ CreateModelExecutionManager({segment_id}, base::DoNothing());
+ ExecuteModel(std::make_pair(0, ModelExecutionStatus::kInvalidMetadata));
+
+ segment_database_->SetBucketDuration(segment_id, 14,
+ proto::TimeUnit::UNKNOWN_TIME_UNIT);
+ ExecuteModel(std::make_pair(0, ModelExecutionStatus::kInvalidMetadata));
+}
+
+TEST_F(ModelExecutionManagerTest, SingleUserAction) {
+ auto segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ auto unrelated_segment_id =
+ optimization_guide::proto::OPTIMIZATION_TARGET_SEGMENTATION_SHARE;
+ CreateModelExecutionManager({segment_id, unrelated_segment_id},
+ base::DoNothing());
+
+ // Initialize with required metadata.
+ segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR);
+ base::TimeDelta bucket_duration = base::TimeDelta::FromHours(3);
+
+ // Set up a single user action feature.
+ std::string user_action_name_1 = "some_action_1";
+ segment_database_->AddUserActionFeature(segment_id, user_action_name_1, 2, 1,
+ proto::Aggregation::COUNT);
+
+ // When the particular user action is looked up with the correct start time,
+ // end time, and aggregation type, return 3 samples.
+ std::vector<Sample> samples{
+ {clock_.Now(), 0},
+ {clock_.Now(), 0},
+ {clock_.Now(), 0},
+ };
+ EXPECT_CALL(*signal_database_,
+ GetSamples(proto::SignalType::USER_ACTION,
+ base::HashMetricName(user_action_name_1),
+ StartTime(bucket_duration, 2), clock_.Now(), _))
+ .WillOnce(RunOnceCallback<4>(samples));
+
+ // After retrieving the samples, they should be processed and aggregated.
+ EXPECT_CALL(*feature_aggregator_,
+ Process(proto::SignalType::USER_ACTION, proto::Aggregation::COUNT,
+ 2, clock_.Now(), bucket_duration, samples))
+ .WillOnce(Return(std::vector<float>{3}));
+
+ // The next step should be to execute the model.
+ EXPECT_CALL(FindHandler(segment_id), ModelAvailable())
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(FindHandler(segment_id),
+ ExecuteModelWithInput(_, std::vector<float>{3}))
+ .WillOnce(RunOnceCallback<0>(absl::make_optional(0.8)));
+
+ ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess));
+}
+
+TEST_F(ModelExecutionManagerTest, ModelNotReady) {
+ auto segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ CreateModelExecutionManager({segment_id}, base::DoNothing());
+
+ segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR);
+
+ // When the model is unavailable, the execution should fail.
+ EXPECT_CALL(FindHandler(segment_id), ModelAvailable())
+ .WillRepeatedly(Return(false));
+
+ ExecuteModel(std::make_pair(0, ModelExecutionStatus::kExecutionError));
+}
+
+TEST_F(ModelExecutionManagerTest, MultipleFeatures) {
+ auto segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ CreateModelExecutionManager({segment_id}, base::DoNothing());
+
+ // Initialize with required metadata.
+ segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR);
+ base::TimeDelta bucket_duration = base::TimeDelta::FromHours(3);
+
+ // Set up 3 metadata feature, one of each signal type.
+ std::string user_action_name = "some_user_action";
+ segment_database_->AddUserActionFeature(segment_id, user_action_name, 2, 1,
+ proto::Aggregation::COUNT);
+ std::string histogram_value_name = "some_histogram_value";
+ segment_database_->AddHistogramValueFeature(segment_id, histogram_value_name,
+ 3, 1, proto::Aggregation::SUM);
+ std::string histogram_enum_name = "some_histogram_enum";
+ segment_database_->AddHistogramEnumFeature(segment_id, histogram_enum_name, 4,
+ 1, proto::Aggregation::COUNT, {});
+
+ // First feature should be the user action.
+ std::vector<Sample> user_action_samples{
+ {clock_.Now(), 0},
+ {clock_.Now(), 0},
+ {clock_.Now(), 0},
+ };
+ EXPECT_CALL(*signal_database_,
+ GetSamples(proto::SignalType::USER_ACTION,
+ base::HashMetricName(user_action_name),
+ StartTime(bucket_duration, 2), clock_.Now(), _))
+ .WillOnce(RunOnceCallback<4>(user_action_samples));
+ EXPECT_CALL(*feature_aggregator_,
+ Process(proto::SignalType::USER_ACTION, proto::Aggregation::COUNT,
+ 2, clock_.Now(), bucket_duration, user_action_samples))
+ .WillOnce(Return(std::vector<float>{3}));
+
+ // Second feature should be the value histogram.
+ std::vector<Sample> histogram_value_samples{
+ {clock_.Now(), 1},
+ {clock_.Now(), 2},
+ {clock_.Now(), 3},
+ };
+ EXPECT_CALL(*signal_database_,
+ GetSamples(proto::SignalType::HISTOGRAM_VALUE,
+ base::HashMetricName(histogram_value_name),
+ StartTime(bucket_duration, 3), clock_.Now(), _))
+ .WillOnce(RunOnceCallback<4>(histogram_value_samples));
+ EXPECT_CALL(
+ *feature_aggregator_,
+ Process(proto::SignalType::HISTOGRAM_VALUE, proto::Aggregation::SUM, 3,
+ clock_.Now(), bucket_duration, histogram_value_samples))
+ .WillOnce(Return(std::vector<float>{6}));
+
+ // Third feature should be the value histogram.
+ std::vector<Sample> histogram_enum_samples{
+ {clock_.Now(), 1},
+ {clock_.Now(), 2},
+ {clock_.Now(), 3},
+ {clock_.Now(), 4},
+ };
+ EXPECT_CALL(*signal_database_,
+ GetSamples(proto::SignalType::HISTOGRAM_ENUM,
+ base::HashMetricName(histogram_enum_name),
+ StartTime(bucket_duration, 4), clock_.Now(), _))
+ .WillOnce(RunOnceCallback<4>(histogram_enum_samples));
+ EXPECT_CALL(
+ *feature_aggregator_,
+ Process(proto::SignalType::HISTOGRAM_ENUM, proto::Aggregation::COUNT, 4,
+ clock_.Now(), bucket_duration, histogram_enum_samples))
+ .WillOnce(Return(std::vector<float>{4}));
+
+ // The input tensor should contain all three values: 3, 6, and 4.
+ EXPECT_CALL(FindHandler(segment_id), ModelAvailable())
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(FindHandler(segment_id),
+ ExecuteModelWithInput(_, std::vector<float>{3, 6, 4}))
+ .WillOnce(RunOnceCallback<0>(absl::make_optional(0.8)));
+
+ ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess));
+}
+
+TEST_F(ModelExecutionManagerTest, SkipCollectionOnlyFeatures) {
+ auto segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ CreateModelExecutionManager({segment_id}, base::DoNothing());
+
+ // Initialize with required metadata.
+ segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR);
+ base::TimeDelta bucket_duration = base::TimeDelta::FromHours(3);
+
+ // Set up 3 metadata feature, one of each signal type.
+ std::string collected_user_action = "some_user_action";
+ segment_database_->AddUserActionFeature(segment_id, collected_user_action, 1,
+ 1, proto::Aggregation::COUNT);
+ std::string no_collection_user_action = "no_collection_user_action";
+ segment_database_->AddUserActionFeature(segment_id, no_collection_user_action,
+ 0, 0, proto::Aggregation::SUM);
+ std::string no_collection_histogram_value = "no_collection_histogram_value";
+ segment_database_->AddHistogramValueFeature(
+ segment_id, no_collection_histogram_value, 0, 0, proto::Aggregation::SUM);
+ std::string no_collection_histogram_enum = "no_collection_histogram_enum";
+ segment_database_->AddHistogramEnumFeature(segment_id,
+ no_collection_histogram_enum, 0, 0,
+ proto::Aggregation::SUM, {});
+ std::string collected_histogram_value = "collected_histogram_value";
+ segment_database_->AddHistogramValueFeature(
+ segment_id, collected_histogram_value, 1, 1, proto::Aggregation::SUM);
+
+ // The first feature in use should be the very first feature.
+ std::vector<Sample> user_action_samples{
+ {clock_.Now(), 0},
+ {clock_.Now(), 0},
+ {clock_.Now(), 0},
+ };
+ EXPECT_CALL(*signal_database_,
+ GetSamples(proto::SignalType::USER_ACTION,
+ base::HashMetricName(collected_user_action),
+ StartTime(bucket_duration, 1), clock_.Now(), _))
+ .WillOnce(RunOnceCallback<4>(user_action_samples));
+ EXPECT_CALL(*feature_aggregator_,
+ Process(proto::SignalType::USER_ACTION, proto::Aggregation::COUNT,
+ 1, clock_.Now(), bucket_duration, user_action_samples))
+ .WillOnce(Return(std::vector<float>{3}));
+
+ // The three features in the middle should all be ignored, so the next one
+ // should be the last feature.
+ std::vector<Sample> histogram_value_samples{
+ {clock_.Now(), 1},
+ {clock_.Now(), 2},
+ {clock_.Now(), 3},
+ };
+ EXPECT_CALL(*signal_database_,
+ GetSamples(proto::SignalType::HISTOGRAM_VALUE,
+ base::HashMetricName(collected_histogram_value),
+ StartTime(bucket_duration, 1), clock_.Now(), _))
+ .WillOnce(RunOnceCallback<4>(histogram_value_samples));
+ EXPECT_CALL(
+ *feature_aggregator_,
+ Process(proto::SignalType::HISTOGRAM_VALUE, proto::Aggregation::SUM, 1,
+ clock_.Now(), bucket_duration, histogram_value_samples))
+ .WillOnce(Return(std::vector<float>{6}));
+
+ // The input tensor should contain only the first and last feature.
+ EXPECT_CALL(FindHandler(segment_id), ModelAvailable())
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(FindHandler(segment_id),
+ ExecuteModelWithInput(_, std::vector<float>{3, 6}))
+ .WillOnce(RunOnceCallback<0>(absl::make_optional(0.8)));
+
+ ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess));
+}
+
+TEST_F(ModelExecutionManagerTest, FilteredEnumSamples) {
+ auto segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ CreateModelExecutionManager({segment_id}, base::DoNothing());
+
+ // Initialize with required metadata.
+ segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR);
+ base::TimeDelta bucket_duration = base::TimeDelta::FromHours(3);
+
+ // Set up a single enum histogram feature.
+ std::string histogram_enum_name = "some_histogram_enum";
+ std::vector<int32_t> accepted_enum_ids = {2, 4};
+ segment_database_->AddHistogramEnumFeature(segment_id, histogram_enum_name, 4,
+ 1, proto::Aggregation::COUNT,
+ accepted_enum_ids);
+
+ // When the particular enum histogram is looked up with the correct start
+ // time, end time, and aggregation type, return all 5 samples.
+ std::vector<Sample> histogram_enum_samples{
+ {clock_.Now(), 1}, {clock_.Now(), 2}, {clock_.Now(), 3},
+ {clock_.Now(), 4}, {clock_.Now(), 5},
+ };
+ EXPECT_CALL(*signal_database_,
+ GetSamples(proto::SignalType::HISTOGRAM_ENUM,
+ base::HashMetricName(histogram_enum_name),
+ StartTime(bucket_duration, 4), clock_.Now(), _))
+ .WillOnce(RunOnceCallback<4>(histogram_enum_samples));
+ // The executor must first filter the enum samples.
+ std::vector<Sample> filtered_enum_samples{
+ {clock_.Now(), 2},
+ {clock_.Now(), 4},
+ };
+ EXPECT_CALL(*feature_aggregator_,
+ FilterEnumSamples(accepted_enum_ids, histogram_enum_samples))
+ .WillOnce(SetArgReferee<1>(filtered_enum_samples));
+ // Only filtered_enum_samples should be processed.
+ EXPECT_CALL(
+ *feature_aggregator_,
+ Process(proto::SignalType::HISTOGRAM_ENUM, proto::Aggregation::COUNT, 4,
+ clock_.Now(), bucket_duration, filtered_enum_samples))
+ .WillOnce(Return(std::vector<float>{2}));
+
+ // The input tensor should contain a single value.
+ EXPECT_CALL(FindHandler(segment_id), ModelAvailable())
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(FindHandler(segment_id),
+ ExecuteModelWithInput(_, std::vector<float>{2}))
+ .WillOnce(RunOnceCallback<0>(absl::make_optional(0.8)));
+
+ ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess));
+}
+
+TEST_F(ModelExecutionManagerTest, MultipleFeaturesWithMultipleBuckets) {
+ auto segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ CreateModelExecutionManager({segment_id}, base::DoNothing());
+
+ // Initialize with required metadata.
+ segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR);
+ base::TimeDelta bucket_duration = base::TimeDelta::FromHours(3);
+
+ // Set up metadata features where bucket_count is not equal to 1.
+ std::string user_action_name = "some_user_action";
+ // 3 buckets
+ segment_database_->AddUserActionFeature(segment_id, user_action_name, 3, 3,
+ proto::Aggregation::BUCKETED_COUNT);
+ std::string histogram_value_name = "some_histogram_value";
+ // 4 buckets
+ segment_database_->AddHistogramValueFeature(
+ segment_id, histogram_value_name, 4, 4,
+ proto::Aggregation::BUCKETED_COUNT_BOOLEAN);
+
+ // First feature should be the user action. The timestamp is set to three
+ // different buckets.
+ std::vector<Sample> user_action_samples{
+ {clock_.Now(), 0},
+ {clock_.Now() - kOneSecond, 0},
+ {clock_.Now() - bucket_duration, 0},
+ {clock_.Now() - bucket_duration - kOneSecond, 0},
+ {clock_.Now() - bucket_duration - kTwoSeconds, 0},
+ {clock_.Now() - bucket_duration * 2, 0},
+ {clock_.Now() - bucket_duration * 2 - kOneSecond, 0},
+ {clock_.Now() - bucket_duration * 2 - kTwoSeconds, 0},
+ };
+ EXPECT_CALL(*signal_database_,
+ GetSamples(proto::SignalType::USER_ACTION,
+ base::HashMetricName(user_action_name),
+ StartTime(bucket_duration, 3), clock_.Now(), _))
+ .WillOnce(RunOnceCallback<4>(user_action_samples));
+ EXPECT_CALL(*feature_aggregator_,
+ Process(proto::SignalType::USER_ACTION,
+ proto::Aggregation::BUCKETED_COUNT, 3, clock_.Now(),
+ bucket_duration, user_action_samples))
+ .WillOnce(Return(std::vector<float>{1, 2, 3}));
+
+ // Second feature should be the value histogram. The timestamp is set to four
+ // different buckets.
+ std::vector<Sample> histogram_value_samples{
+ {clock_.Now(), 1},
+ {clock_.Now() - kOneSecond, 2},
+ {clock_.Now() - bucket_duration, 3},
+ {clock_.Now() - bucket_duration - kOneSecond, 4},
+ {clock_.Now() - bucket_duration - kTwoSeconds, 5},
+ {clock_.Now() - bucket_duration * 2, 6},
+ {clock_.Now() - bucket_duration * 2 - kOneSecond, 7},
+ {clock_.Now() - bucket_duration * 2 - kTwoSeconds, 8},
+ {clock_.Now() - bucket_duration * 3, 9},
+ {clock_.Now() - bucket_duration * 3 - kOneSecond, 10},
+ {clock_.Now() - bucket_duration * 3 - kTwoSeconds, 11},
+ };
+ EXPECT_CALL(*signal_database_,
+ GetSamples(proto::SignalType::HISTOGRAM_VALUE,
+ base::HashMetricName(histogram_value_name),
+ StartTime(bucket_duration, 4), clock_.Now(), _))
+ .WillOnce(RunOnceCallback<4>(histogram_value_samples));
+ EXPECT_CALL(*feature_aggregator_,
+ Process(proto::SignalType::HISTOGRAM_VALUE,
+ proto::Aggregation::BUCKETED_COUNT_BOOLEAN, 4,
+ clock_.Now(), bucket_duration, histogram_value_samples))
+ .WillOnce(Return(std::vector<float>{4, 5, 6, 7}));
+
+ // The input tensor should contain all values flattened to a single vector.
+ EXPECT_CALL(FindHandler(segment_id), ModelAvailable())
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(FindHandler(segment_id),
+ ExecuteModelWithInput(_, std::vector<float>{1, 2, 3, 4, 5, 6, 7}))
+ .WillOnce(RunOnceCallback<0>(absl::make_optional(0.8)));
+
+ ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess));
+}
+
+TEST_F(ModelExecutionManagerTest, OnSegmentationModelUpdatedInvalidMetadata) {
+ // Use a MockSegmentInfoDatabase for this test in particular, to verify that
+ // it is never used.
+ auto mock_segment_database = std::make_unique<MockSegmentInfoDatabase>();
+ auto* mock_segment_database_ptr = mock_segment_database.get();
+ segment_database_ = std::move(mock_segment_database);
+
+ // Construct the ModelExecutionManager.
+ base::MockCallback<ModelExecutionManager::SegmentationModelUpdatedCallback>
+ callback;
+ auto segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ CreateModelExecutionManager({segment_id}, callback.Get());
+
+ // Create invalid metadata, which should be ignored.
+ proto::SegmentInfo segment_info;
+ proto::SegmentationModelMetadata metadata;
+ metadata.set_time_unit(proto::UNKNOWN_TIME_UNIT);
+
+ // Verify that the ModelExecutionManager never invokes its
+ // SegmentInfoDatabase, nor invokes the callback.
+ EXPECT_CALL(*mock_segment_database_ptr, GetSegmentInfo(_, _)).Times(0);
+ EXPECT_CALL(callback, Run(_)).Times(0);
+ model_handlers_callbacks_[segment_id].Run(segment_id, metadata);
+}
+
+TEST_F(ModelExecutionManagerTest, OnSegmentationModelUpdatedNoOldMetadata) {
+ base::MockCallback<ModelExecutionManager::SegmentationModelUpdatedCallback>
+ callback;
+ auto segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ CreateModelExecutionManager({segment_id}, callback.Get());
+
+ proto::SegmentInfo segment_info;
+ proto::SegmentationModelMetadata metadata;
+ metadata.set_bucket_duration(42u);
+ metadata.set_time_unit(proto::TimeUnit::DAY);
+ EXPECT_CALL(callback, Run(_)).WillOnce(SaveArg<0>(&segment_info));
+ model_handlers_callbacks_[segment_id].Run(segment_id, metadata);
+
+ // Verify that the resulting callback was invoked correctly.
+ EXPECT_EQ(segment_id, segment_info.segment_id());
+ EXPECT_EQ(42u, segment_info.model_metadata().bucket_duration());
+
+ // Also verify that the database has been updated.
+ base::MockCallback<SegmentInfoDatabase::SegmentInfoCallback> db_callback;
+ absl::optional<proto::SegmentInfo> segment_info_from_db;
+ EXPECT_CALL(db_callback, Run(_)).WillOnce(SaveArg<0>(&segment_info_from_db));
+
+ // Fetch SegmentInfo from the database.
+ segment_database_->GetSegmentInfo(segment_id, db_callback.Get());
+ EXPECT_TRUE(segment_info_from_db.has_value());
+ EXPECT_EQ(segment_id, segment_info_from_db->segment_id());
+
+ // The metadata should have been stored.
+ EXPECT_EQ(42u, segment_info_from_db->model_metadata().bucket_duration());
+}
+
+TEST_F(ModelExecutionManagerTest,
+ OnSegmentationModelUpdatedWithPreviousMetadataAndPredictionResult) {
+ base::MockCallback<ModelExecutionManager::SegmentationModelUpdatedCallback>
+ callback;
+ auto segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ CreateModelExecutionManager({segment_id}, callback.Get());
+
+ // Fill in old data in the SegmentInfo database.
+ segment_database_->SetBucketDuration(segment_id, 456, proto::TimeUnit::MONTH);
+ segment_database_->AddUserActionFeature(segment_id, "hello", 2, 2,
+ proto::Aggregation::BUCKETED_COUNT);
+ segment_database_->AddPredictionResult(segment_id, 2, clock_.Now());
+
+ base::MockCallback<SegmentInfoDatabase::SegmentInfoCallback> db_callback_1;
+ absl::optional<proto::SegmentInfo> segment_info_from_db_1;
+ EXPECT_CALL(db_callback_1, Run(_))
+ .WillOnce(SaveArg<0>(&segment_info_from_db_1));
+ segment_database_->GetSegmentInfo(segment_id, db_callback_1.Get());
+ EXPECT_TRUE(segment_info_from_db_1.has_value());
+ EXPECT_EQ(segment_id, segment_info_from_db_1->segment_id());
+ // Verify the old metadata and prediction result has been stored correctly.
+ EXPECT_EQ(456u, segment_info_from_db_1->model_metadata().bucket_duration());
+ EXPECT_EQ(2, segment_info_from_db_1->prediction_result().result());
+ // Verify the metadata features have been stored correctly.
+ EXPECT_EQ(proto::SignalType::USER_ACTION,
+ segment_info_from_db_1->model_metadata().features(0).type());
+ EXPECT_EQ("hello",
+ segment_info_from_db_1->model_metadata().features(0).name());
+ EXPECT_EQ(proto::Aggregation::BUCKETED_COUNT,
+ segment_info_from_db_1->model_metadata().features(0).aggregation());
+
+ // Create segment info that does not match.
+ proto::SegmentInfo segment_info;
+ proto::SegmentationModelMetadata metadata;
+ metadata.set_bucket_duration(42u);
+ metadata.set_time_unit(proto::TimeUnit::HOUR);
+
+ // Create one feature that does not match the stored feature.
+ auto* feature = metadata.add_features();
+ feature->set_type(proto::SignalType::HISTOGRAM_VALUE);
+ feature->set_name("other");
+ // Intentionally not set the name hash, as it should be set automatically.
+ feature->set_aggregation(proto::Aggregation::BUCKETED_SUM);
+ feature->set_bucket_count(3);
+ feature->set_tensor_length(3);
+
+ // Invoke the callback and store the resulting invocation of the outer
+ // callback for verification.
+ EXPECT_CALL(callback, Run(_)).WillOnce(SaveArg<0>(&segment_info));
+ model_handlers_callbacks_[segment_id].Run(segment_id, metadata);
+
+ // Should now have the metadata from the new proto.
+ EXPECT_EQ(segment_id, segment_info.segment_id());
+ EXPECT_EQ(42u, segment_info.model_metadata().bucket_duration());
+ EXPECT_EQ(proto::SignalType::HISTOGRAM_VALUE,
+ segment_info.model_metadata().features(0).type());
+ EXPECT_EQ("other", segment_info.model_metadata().features(0).name());
+ // The name_hash should have been set automatically.
+ EXPECT_EQ(base::HashMetricName("other"),
+ segment_info.model_metadata().features(0).name_hash());
+ EXPECT_EQ(proto::Aggregation::BUCKETED_SUM,
+ segment_info.model_metadata().features(0).aggregation());
+ EXPECT_EQ(2, segment_info.prediction_result().result());
+ EXPECT_EQ(clock_.Now().ToDeltaSinceWindowsEpoch().InMicroseconds(),
+ segment_info.prediction_result().timestamp_us());
+
+ // Also verify that the database has been updated.
+ base::MockCallback<SegmentInfoDatabase::SegmentInfoCallback> db_callback_2;
+ absl::optional<proto::SegmentInfo> segment_info_from_db_2;
+ EXPECT_CALL(db_callback_2, Run(_))
+ .WillOnce(SaveArg<0>(&segment_info_from_db_2));
+ segment_database_->GetSegmentInfo(segment_id, db_callback_2.Get());
+ EXPECT_TRUE(segment_info_from_db_2.has_value());
+ EXPECT_EQ(segment_id, segment_info_from_db_2->segment_id());
+
+ // The metadata should have been updated.
+ EXPECT_EQ(42u, segment_info_from_db_2->model_metadata().bucket_duration());
+ // The metadata features should have been updated.
+ EXPECT_EQ(proto::SignalType::HISTOGRAM_VALUE,
+ segment_info_from_db_2->model_metadata().features(0).type());
+ EXPECT_EQ("other",
+ segment_info_from_db_2->model_metadata().features(0).name());
+ EXPECT_EQ(base::HashMetricName("other"),
+ segment_info_from_db_2->model_metadata().features(0).name_hash());
+ EXPECT_EQ(proto::Aggregation::BUCKETED_SUM,
+ segment_info_from_db_2->model_metadata().features(0).aggregation());
+ // We shuold have kept the prediction result.
+ EXPECT_EQ(2, segment_info_from_db_2->prediction_result().result());
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/model_execution_status.h b/chromium/components/segmentation_platform/internal/execution/model_execution_status.h
new file mode 100644
index 00000000000..fae5afd7968
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/model_execution_status.h
@@ -0,0 +1,22 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_STATUS_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_STATUS_H_
+
+namespace segmentation_platform {
+
+// Success or failure states resulting from the model execution.
+// Keep up to date with SegmentationPlatformModelExecutionStatus in
+// //tools/metrics/histograms/enums.xml.
+enum class ModelExecutionStatus {
+ kSuccess = 0,
+ kExecutionError = 1,
+ kInvalidMetadata = 2,
+ kMaxValue = kInvalidMetadata,
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MODEL_EXECUTION_STATUS_H_
diff --git a/chromium/components/segmentation_platform/internal/execution/segmentation_model_executor.cc b/chromium/components/segmentation_platform/internal/execution/segmentation_model_executor.cc
new file mode 100644
index 00000000000..e82e2c30959
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/segmentation_model_executor.cc
@@ -0,0 +1,51 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/execution/segmentation_model_executor.h"
+
+#include <vector>
+
+#include "base/check_op.h"
+#include "third_party/tflite-support/src/tensorflow_lite_support/cc/task/core/task_utils.h"
+#include "third_party/tflite/src/tensorflow/lite/c/common.h"
+
+namespace segmentation_platform {
+
+SegmentationModelExecutor::SegmentationModelExecutor() = default;
+
+SegmentationModelExecutor::~SegmentationModelExecutor() = default;
+
+absl::Status SegmentationModelExecutor::Preprocess(
+ const std::vector<TfLiteTensor*>& input_tensors,
+ const std::vector<float>& input) {
+ // The model must have a single float input tensor, and the length of the
+ // input data must match the length of the tensor.
+ if (input_tensors.size() != 1u)
+ return absl::InvalidArgumentError("input tensor size not 1");
+ if (kTfLiteFloat32 != input_tensors[0]->type)
+ return absl::InvalidArgumentError("input tensor type is not float");
+ if (input_tensors[0]->bytes / sizeof(input_tensors[0]->type) !=
+ input.size()) {
+ return absl::InvalidArgumentError(
+ "length of input data does not match length of tensor");
+ }
+
+ tflite::task::core::PopulateTensor<float>(input, input_tensors[0]);
+ return absl::OkStatus();
+}
+
+float SegmentationModelExecutor::Postprocess(
+ const std::vector<const TfLiteTensor*>& output_tensors) {
+ // The output must be a single tensor with a single float element.
+ DCHECK_EQ(1u, output_tensors.size());
+ DCHECK_EQ(kTfLiteFloat32, output_tensors[0]->type);
+ DCHECK_EQ(1u, output_tensors[0]->bytes / sizeof(output_tensors[0]->type));
+
+ std::vector<float> data;
+ tflite::task::core::PopulateVector<float>(output_tensors[0], &data);
+ DCHECK_EQ(1u, data.size());
+ return data[0];
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/segmentation_model_executor.h b/chromium/components/segmentation_platform/internal/execution/segmentation_model_executor.h
new file mode 100644
index 00000000000..fa578e95870
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/segmentation_model_executor.h
@@ -0,0 +1,48 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_SEGMENTATION_MODEL_EXECUTOR_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_SEGMENTATION_MODEL_EXECUTOR_H_
+
+#include <memory>
+#include <vector>
+
+#include "components/optimization_guide/core/base_model_executor.h"
+#include "components/optimization_guide/proto/models.pb.h"
+
+struct TfLiteTensor;
+
+namespace segmentation_platform {
+
+// Provides a framework for executing a particular segmentation model.
+// It requires the loaded TensorFlow Lite model to use a single one dimensional
+// tensor of floats as the input and a single output tensor with a single float.
+// The length of the vector of floats given as input to execution needs to
+// exactly match the length of the one-dimensional input tensor.
+// Since the shape of the inputs and outputs across all segmentation models are
+// the same, this class can be re-used across all the segmentation model
+// executors.
+class SegmentationModelExecutor
+ : public optimization_guide::BaseModelExecutor<float,
+ const std::vector<float>&> {
+ public:
+ SegmentationModelExecutor();
+ ~SegmentationModelExecutor() override;
+
+ // Disallow copy/assign.
+ SegmentationModelExecutor(const SegmentationModelExecutor&) = delete;
+ SegmentationModelExecutor& operator=(const SegmentationModelExecutor&) =
+ delete;
+
+ protected:
+ // optimization_guide::BaseModelExecutor overrides.
+ absl::Status Preprocess(const std::vector<TfLiteTensor*>& input_tensors,
+ const std::vector<float>& input) override;
+ float Postprocess(
+ const std::vector<const TfLiteTensor*>& output_tensors) override;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_SEGMENTATION_MODEL_EXECUTOR_H_
diff --git a/chromium/components/segmentation_platform/internal/execution/segmentation_model_executor_unittest.cc b/chromium/components/segmentation_platform/internal/execution/segmentation_model_executor_unittest.cc
new file mode 100644
index 00000000000..df8d92e1d96
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/segmentation_model_executor_unittest.cc
@@ -0,0 +1,183 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/execution/segmentation_model_executor.h"
+
+#include <memory>
+
+#include "base/base_paths.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/callback_helpers.h"
+#include "base/check.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/test/mock_callback.h"
+#include "base/test/task_environment.h"
+#include "components/optimization_guide/core/optimization_guide_model_provider.h"
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
+#include "components/optimization_guide/proto/common_types.pb.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/segmentation_model_handler.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+
+namespace {
+const auto kOptimizationTarget = optimization_guide::proto::OptimizationTarget::
+ OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+} // namespace
+
+namespace segmentation_platform {
+bool AreEqual(const proto::SegmentationModelMetadata& a,
+ const proto::SegmentationModelMetadata& b) {
+ // Serializing two protos and comparing them is unsafe, in particular if they
+ // contain a map because the wire format of a proto is not guaranteed to be
+ // constant. However, in practice this should work well for the simplistic
+ // test case we are running here.
+ std::string serialized_a = a.SerializeAsString();
+ std::string serialized_b = b.SerializeAsString();
+ return serialized_a == serialized_b;
+}
+
+class SegmentationModelExecutorTest : public testing::Test {
+ public:
+ SegmentationModelExecutorTest() = default;
+ ~SegmentationModelExecutorTest() override = default;
+
+ void SetUp() override {
+ base::FilePath source_root_dir;
+ base::PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir);
+ model_file_path_ = source_root_dir.AppendASCII("components")
+ .AppendASCII("test")
+ .AppendASCII("data")
+ .AppendASCII("segmentation_platform")
+ .AppendASCII("adder.tflite");
+
+ optimization_guide_model_provider_ = std::make_unique<
+ optimization_guide::TestOptimizationGuideModelProvider>();
+ }
+
+ void TearDown() override { ResetModelExecutor(); }
+
+ void CreateModelExecutor(
+ SegmentationModelHandler::ModelUpdatedCallback callback) {
+ if (model_executor_handle_)
+ model_executor_handle_.reset();
+
+ model_executor_handle_ = std::make_unique<SegmentationModelHandler>(
+ optimization_guide_model_provider_.get(),
+ task_environment_.GetMainThreadTaskRunner(), kOptimizationTarget,
+ callback);
+ }
+
+ void ResetModelExecutor() {
+ model_executor_handle_.reset();
+ // Allow for the SegmentationModelExecutor owned by SegmentationModelHandler
+ // to be destroyed.
+ RunUntilIdle();
+ }
+
+ void PushModelFileToModelExecutor(
+ absl::optional<proto::SegmentationModelMetadata> metadata) {
+ absl::optional<optimization_guide::proto::Any> any;
+
+ // Craft a correct Any proto in the case we passed in metadata.
+ if (metadata.has_value()) {
+ std::string serialized_metadata;
+ (*metadata).SerializeToString(&serialized_metadata);
+ optimization_guide::proto::Any any_proto;
+ any = absl::make_optional(any_proto);
+ any->set_value(serialized_metadata);
+ // Need to set the type URL for ParsedSupportedFeaturesForLoadedModel() to
+ // work correctly, since it's verifying the type name.
+ any->set_type_url(
+ "type.googleapis.com/"
+ "segmentation_platform.proto.SegmentationModelMetadata");
+ }
+ DCHECK(model_executor_handle_);
+ model_executor_handle_->OnModelFileUpdated(kOptimizationTarget, any,
+ model_file_path_);
+ RunUntilIdle();
+ }
+
+ SegmentationModelHandler* model_executor_handle() {
+ return model_executor_handle_.get();
+ }
+
+ void RunUntilIdle() { task_environment_.RunUntilIdle(); }
+
+ private:
+ base::test::TaskEnvironment task_environment_;
+
+ base::FilePath model_file_path_;
+ std::unique_ptr<optimization_guide::TestOptimizationGuideModelProvider>
+ optimization_guide_model_provider_;
+
+ std::unique_ptr<SegmentationModelHandler> model_executor_handle_;
+};
+
+TEST_F(SegmentationModelExecutorTest, ExecuteWithLoadedModel) {
+ proto::SegmentationModelMetadata metadata;
+ metadata.set_bucket_duration(42);
+
+ std::unique_ptr<base::RunLoop> model_update_runloop =
+ std::make_unique<base::RunLoop>();
+ CreateModelExecutor(base::BindRepeating(
+ [](base::RunLoop* run_loop,
+ proto::SegmentationModelMetadata original_metadata,
+ optimization_guide::proto::OptimizationTarget optimization_target,
+ proto::SegmentationModelMetadata actual_metadata) {
+ // Verify that the callback is invoked with the correct data.
+ EXPECT_EQ(kOptimizationTarget, optimization_target);
+ EXPECT_TRUE(AreEqual(original_metadata, actual_metadata));
+ run_loop->Quit();
+ },
+ model_update_runloop.get(), metadata));
+
+ // Provide metadata as part of the OnModelFileUpdated invocation, which will
+ // be passed along as a correctly crafted Any proto.
+ PushModelFileToModelExecutor(metadata);
+ model_update_runloop->Run();
+
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
+
+ std::vector<float> input = {4, 5};
+
+ std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
+ model_executor_handle()->ExecuteModelWithInput(
+ base::BindOnce(
+ [](base::RunLoop* run_loop, const absl::optional<float>& output) {
+ EXPECT_TRUE(output.has_value());
+ // 4 + 5 = 9
+ EXPECT_NEAR(9, output.value(), 1e-1);
+
+ run_loop->Quit();
+ },
+ run_loop.get()),
+ input);
+ run_loop->Run();
+
+ ResetModelExecutor();
+}
+
+TEST_F(SegmentationModelExecutorTest, FailToProvideMetadata) {
+ std::unique_ptr<base::RunLoop> model_update_runloop =
+ std::make_unique<base::RunLoop>();
+ base::MockCallback<SegmentationModelHandler::ModelUpdatedCallback> callback;
+ CreateModelExecutor(callback.Get());
+ EXPECT_CALL(callback, Run(_, _)).Times(0);
+
+ // Intentionally pass an empty metadata which will pass absl::nullopt as the
+ // Any proto.
+ PushModelFileToModelExecutor(absl::nullopt);
+ model_update_runloop->RunUntilIdle();
+
+ EXPECT_TRUE(model_executor_handle()->ModelAvailable());
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/segmentation_model_handler.cc b/chromium/components/segmentation_platform/internal/execution/segmentation_model_handler.cc
new file mode 100644
index 00000000000..d7e02df0570
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/segmentation_model_handler.cc
@@ -0,0 +1,65 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/execution/segmentation_model_handler.h"
+
+#include <memory>
+#include <vector>
+
+#include "components/optimization_guide/core/model_executor.h"
+#include "components/optimization_guide/proto/common_types.pb.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/segmentation_model_executor.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/stats.h"
+
+namespace segmentation_platform {
+
+SegmentationModelHandler::SegmentationModelHandler(
+ optimization_guide::OptimizationGuideModelProvider* model_provider,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ optimization_guide::proto::OptimizationTarget optimization_target,
+ const ModelUpdatedCallback& model_updated_callback)
+ : optimization_guide::ModelHandler<float, const std::vector<float>&>(
+ model_provider,
+ background_task_runner,
+ std::make_unique<SegmentationModelExecutor>(),
+ optimization_target,
+ /*model_metadata=*/absl::nullopt),
+ model_updated_callback_(model_updated_callback) {}
+
+SegmentationModelHandler::~SegmentationModelHandler() = default;
+
+void SegmentationModelHandler::OnModelFileUpdated(
+ optimization_guide::proto::OptimizationTarget optimization_target,
+ const absl::optional<optimization_guide::proto::Any>& model_metadata,
+ const base::FilePath& file_path) {
+ // First invoke parent to update internal status.
+ optimization_guide::ModelHandler<
+ float, const std::vector<float>&>::OnModelFileUpdated(optimization_target,
+ model_metadata,
+ file_path);
+ // The parent class should always set the model availability to true after
+ // having received an updated model.
+ DCHECK(ModelAvailable());
+
+ // Grab the segmentation specific metadata from the Any proto. If we are
+ // unable to find it, there is no point in informing the rest of the platform.
+ absl::optional<proto::SegmentationModelMetadata> segmentation_model_metadata =
+ ParsedSupportedFeaturesForLoadedModel<proto::SegmentationModelMetadata>();
+ stats::RecordModelDeliveryHasMetadata(
+ optimization_target, segmentation_model_metadata.has_value());
+ if (!segmentation_model_metadata.has_value()) {
+ // This is not expected to happen, since the optimization guide server is
+ // expected to pass this along. Either something failed horribly on the way,
+ // we failed to read the metadata, or the server side configuration is
+ // wrong.
+ return;
+ }
+
+ model_updated_callback_.Run(optimization_target,
+ std::move(*segmentation_model_metadata));
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/execution/segmentation_model_handler.h b/chromium/components/segmentation_platform/internal/execution/segmentation_model_handler.h
new file mode 100644
index 00000000000..c10521df45d
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/execution/segmentation_model_handler.h
@@ -0,0 +1,64 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_SEGMENTATION_MODEL_HANDLER_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_SEGMENTATION_MODEL_HANDLER_H_
+
+#include <memory>
+#include <vector>
+
+#include "components/optimization_guide/core/model_executor.h"
+#include "components/optimization_guide/proto/models.pb.h"
+
+namespace optimization_guide {
+namespace proto {
+class Any;
+} // namespace proto
+class OptimizationGuideModelProvider;
+} // namespace optimization_guide
+
+namespace segmentation_platform {
+namespace proto {
+class SegmentationModelMetadata;
+} // namespace proto
+
+// A simple wrapper around a ModelHandler which is usable for all segmentation
+// models. This class constructs and owns the SegmentationModelExecutor through
+// its parent class.
+// See documentation for SegmentationModelExecutor for details on the
+// requirements for the ML model and the inputs to execution.
+class SegmentationModelHandler
+ : public optimization_guide::ModelHandler<float,
+ const std::vector<float>&> {
+ public:
+ using ModelUpdatedCallback = base::RepeatingCallback<void(
+ optimization_guide::proto::OptimizationTarget,
+ proto::SegmentationModelMetadata)>;
+
+ explicit SegmentationModelHandler(
+ optimization_guide::OptimizationGuideModelProvider* model_provider,
+ scoped_refptr<base::SequencedTaskRunner> background_task_runner,
+ optimization_guide::proto::OptimizationTarget optimization_target,
+ const ModelUpdatedCallback& model_updated_callback);
+ ~SegmentationModelHandler() override;
+
+ // Disallow copy/assign.
+ SegmentationModelHandler(const SegmentationModelHandler&) = delete;
+ SegmentationModelHandler& operator=(const SegmentationModelHandler&) = delete;
+
+ // optimization_guide::ModelHandler overrides.
+ void OnModelFileUpdated(
+ optimization_guide::proto::OptimizationTarget optimization_target,
+ const absl::optional<optimization_guide::proto::Any>& model_metadata,
+ const base::FilePath& file_path) override;
+
+ private:
+ // Callback to invoke whenever the model file has been updated. If there is
+ // a model available, this will be invoked at least once per session.
+ ModelUpdatedCallback model_updated_callback_;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_SEGMENTATION_MODEL_HANDLER_H_
diff --git a/chromium/components/segmentation_platform/internal/proto/BUILD.gn b/chromium/components/segmentation_platform/internal/proto/BUILD.gn
new file mode 100644
index 00000000000..09c721d1b5a
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/proto/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/protobuf/proto_library.gni")
+
+proto_library("proto") {
+ proto_in_dir = "//"
+ sources = [
+ "aggregation.proto",
+ "model_metadata.proto",
+ "model_prediction.proto",
+ "signal.proto",
+ "signal_storage_config.proto",
+ "types.proto",
+ ]
+
+ link_deps =
+ [ "//components/optimization_guide/proto:optimization_guide_proto" ]
+}
diff --git a/chromium/components/segmentation_platform/internal/proto/aggregation.proto b/chromium/components/segmentation_platform/internal/proto/aggregation.proto
new file mode 100644
index 00000000000..a9b7851965c
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/proto/aggregation.proto
@@ -0,0 +1,79 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package segmentation_platform.proto;
+
+// Describes how a feature will be aggregated inside a timed bucket for
+// forming the input tensor to the model. |bucket_count| here refers to the
+// field Feature.bucket_count. Buckets are listed in reverse order, so the
+// first entry in the result will be the most recent.
+enum Aggregation {
+ UNKNOWN = 0;
+
+ // TENSOR RESULT: Data type: int, Length: 1
+ // The number of events.
+ COUNT = 1;
+
+ // TENSOR RESULT: Data type: int, Length: 1
+ // If a COUNT aggregation yields 0, then False, else True.
+ COUNT_BOOLEAN = 2;
+
+ // TENSOR RESULT: Data type: int, Length: |bucket_count|
+ // Each entry is the count of times the event happened within each bucket.
+ BUCKETED_COUNT = 3;
+
+ // TENSOR RESULT: Data type: bool, Length: |bucket_count|
+ // Each entry is True if BUCKETED_COUNT for that bucket would yield > 0, else
+ // False.
+ BUCKETED_COUNT_BOOLEAN = 4;
+
+ // TENSOR RESULT: Data type: int, Length: 1
+ // The count of BUCKETED_COUNT_BOOLEAN True values over the same
+ // |bucket_count|.
+ BUCKETED_COUNT_BOOLEAN_TRUE_COUNT = 5;
+
+ // TENSOR RESULT: Data type: int, Length: |bucket_count|
+ // First value is the count for the current bucket.
+ // Second value is the count for the current + previous bucket.
+ // Third value is the count for the current + previous + before previous
+ // bucket, etc. The last value is the same value as a COUNT aggregation
+ // for the same |bucket_count|.
+ BUCKETED_CUMULATIVE_COUNT = 6;
+
+ // TENSOR RESULT: Data type: int, Length: 1
+ // Value for each User Action is 1.
+ // Sum of all values from now back to |bucket_count| number of buckets.
+ SUM = 7;
+
+ // TENSOR RESULT: Data type: bool, Length: 1
+ // If a SUM aggregation yields 0, then False, else True.
+ SUM_BOOLEAN = 8;
+
+ // TENSOR RESULT: Data type: int, Length: |bucket_count|
+ // Value for each User Action is 1.
+ // Each entry is the sum for that event within each bucket.
+ BUCKETED_SUM = 9;
+
+ // TENSOR RESULT: Data type: int, Length: |bucket_count|
+ // Value for each User Action is 1.
+ // Each entry is True if BUCKETED_SUM for that bucket would yield > 0, else
+ // False.
+ BUCKETED_SUM_BOOLEAN = 10;
+
+ // TENSOR RESULT: Data type: int, Length: 1
+ // The count of BUCKETED_SUM_BOOLEAN True values over the same |bucket_count|.
+ BUCKETED_SUM_BOOLEAN_TRUE_COUNT = 11;
+
+ // TENSOR RESULT: Data type: int, Length: |bucket_count|
+ // Value for each User Action is 1.
+ // First value is the sum for the current bucket.
+ // Second value is the sum for the current + previous bucket.
+ // Third value is the sum for the current + previous + before previous bucket,
+ // etc. The last value is the same value as a SUM aggregation for the same
+ // |bucket_count|.
+ BUCKETED_CUMULATIVE_SUM = 12;
+}
diff --git a/chromium/components/segmentation_platform/internal/proto/model_metadata.proto b/chromium/components/segmentation_platform/internal/proto/model_metadata.proto
new file mode 100644
index 00000000000..1eb33de546e
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/proto/model_metadata.proto
@@ -0,0 +1,101 @@
+// Copyright 2021 The Chromium 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 = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package segmentation_platform.proto;
+
+import "components/segmentation_platform/internal/proto/aggregation.proto";
+import "components/segmentation_platform/internal/proto/types.proto";
+
+// Used as time unit for rest of this proto.
+enum TimeUnit {
+ UNKNOWN_TIME_UNIT = 0;
+ YEAR = 1;
+ MONTH = 2;
+ WEEK = 3;
+ DAY = 4;
+ HOUR = 5;
+ MINUTE = 6;
+ SECOND = 7;
+}
+
+message Feature {
+ // The type of signal this feature refers to.
+ optional SignalType type = 1;
+
+ // The human readable name of the histogram or user action.
+ optional string name = 2;
+
+ // The hash of the histogram name or user action. Must match the result of
+ // base::HashMetricName.
+ optional fixed64 name_hash = 3;
+
+ // Number of buckets to include in the result. If set to 0, no data will be
+ // collected. This can be used to start storing data before it should be used.
+ // See documentation for Aggregation for details.
+ optional uint64 bucket_count = 4;
+
+ // The required length of the calculated result. See documentation for
+ // Aggregation for details.
+ optional uint64 tensor_length = 5;
+
+ // The type of aggregation to use for this particular feature.
+ optional Aggregation aggregation = 6;
+
+ // Only set if type == HISTOGRAM_ENUM.
+ // Matches are only valid when the enum ID matches any of these.
+ // Works like an OR condition, e.g.: [url, search, …] or just [url].
+ repeated int32 enum_ids = 7;
+}
+
+// Metadata about a segmentation model for a given segment. Contains information
+// on how to use the model such as collecting signals, interpreting results etc.
+message SegmentationModelMetadata {
+ // An ordered list of required features.
+ repeated Feature features = 1;
+
+ // The time unit to be used for the rest of this proto.
+ optional TimeUnit time_unit = 2;
+
+ // The size of each interval the data should be aggregated over.
+ optional uint64 bucket_duration = 3;
+
+ // For how long should data be stored for this model.
+ optional int64 signal_storage_length = 4;
+
+ // For how long do we have to have captured data for this model. If the
+ // relevant signals have been captured for a shorter amount of time than this,
+ // this model can never be selected.
+ optional int64 min_signal_collection_length = 5;
+
+ // Describes how long after a valid result has been calculated for this model
+ // it is OK to cache the result without recalculating with updated data.
+ optional int64 result_time_to_live = 6;
+
+ message DiscreteMapping {
+ // A mapping result from the raw continuous result to a discrete and
+ // comparable value based on |rank|.
+ message Entry {
+ // The minimum result of the model to be allowed to choose this mapping.
+ optional float min_result = 1;
+
+ // A feature specific rank.
+ optional int64 rank = 2;
+ }
+
+ // An ordered (based on their |min_result|) list of discrete mappings.
+ // To map a model evaluation result to a DiscreteMapping, choose the highest
+ // |min_value| that the evaluation result is at or above.
+ // E.g. for these mappings: [(0.0, 0), (0.4, 1), (0.7, 2), (0.9, 3)], a
+ // result of 0.7 would yield (0.7, 2), and 0.69 would yield (0.4, 1).
+ repeated Entry entries = 1;
+ }
+ map<string, DiscreteMapping> discrete_mappings = 7;
+
+ // The default key to use during the mapping process if no key has been
+ // provided.
+ optional string default_discrete_mapping = 8;
+}
diff --git a/chromium/components/segmentation_platform/internal/proto/model_prediction.proto b/chromium/components/segmentation_platform/internal/proto/model_prediction.proto
new file mode 100644
index 00000000000..75342969c6c
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/proto/model_prediction.proto
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package segmentation_platform.proto;
+
+import "components/segmentation_platform/internal/proto/model_metadata.proto";
+import "components/optimization_guide/proto/models.proto";
+
+// Result from the model evaluation for a given segment.
+message PredictionResult {
+ // The result is the confidence rating from the model evaluation.
+ optional float result = 1;
+
+ // The time when the prediction was made, in terms of the number of
+ // microseconds since Windows epoch.
+ optional int64 timestamp_us = 2;
+}
+
+// Top level message for a segment. Contains both the model metadata and
+// prediction results.
+message SegmentInfo {
+ // Segment target.
+ optional optimization_guide.proto.OptimizationTarget segment_id = 1;
+
+ // Cached copy of the segment metadata which is important in case the metadata
+ // is temporarily not available in the future. It also contains the relevant
+ // information regarding things like the TTL for a prediction result.
+ optional SegmentationModelMetadata model_metadata = 2;
+
+ // The last prediction result for this segment.
+ optional PredictionResult prediction_result = 3;
+}
diff --git a/chromium/components/segmentation_platform/internal/proto/signal.proto b/chromium/components/segmentation_platform/internal/proto/signal.proto
new file mode 100644
index 00000000000..2273bbd685c
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/proto/signal.proto
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package segmentation_platform.proto;
+
+// Represents the signal data collected during a certain time range.
+message SignalData {
+ // The list of samples during the time range.
+ repeated Sample samples = 1;
+}
+
+// Represents the signal data sample for a single timestamp.
+message Sample {
+ // The value of the histogram sample. Not provided for user actions.
+ optional int32 value = 1;
+
+ // Timestamp relative to the start of the UTC day. This results in a smaller
+ // value which can be efficiently stored in the proto.
+ optional int32 time_sec_delta = 2;
+}
diff --git a/chromium/components/segmentation_platform/internal/proto/signal_storage_config.proto b/chromium/components/segmentation_platform/internal/proto/signal_storage_config.proto
new file mode 100644
index 00000000000..f3b1fa6745c
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/proto/signal_storage_config.proto
@@ -0,0 +1,34 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package segmentation_platform.proto;
+
+import "components/segmentation_platform/internal/proto/types.proto";
+
+// Contains storage related information about a particular signal useful for
+// determining eligibility for model evaluation and DB cleanups.
+message SignalStorageConfig {
+ // The name (hash) of the user action or histogram.
+ optional uint64 name_hash = 1;
+
+ // The type of the signal.
+ optional SignalType signal_type = 2;
+
+ // Number of seconds to store a particular signal.
+ optional int64 storage_length_s = 3;
+
+ // Set to the first time we received a model that required collecting this
+ // signal, in seconds from windows epoch.
+ optional int64 collection_start_time_s = 4;
+}
+
+// Top level message for the signal storage config containing all signals across
+// different models.
+message SignalStorageConfigs {
+ // The list of all signal configs.
+ repeated SignalStorageConfig signals = 1;
+}
diff --git a/chromium/components/segmentation_platform/internal/proto/types.proto b/chromium/components/segmentation_platform/internal/proto/types.proto
new file mode 100644
index 00000000000..9452ca3aefc
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/proto/types.proto
@@ -0,0 +1,16 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package segmentation_platform.proto;
+
+// Used to distinguish between different types of signals.
+enum SignalType {
+ UNKNOWN_SIGNAL_TYPE = 0;
+ USER_ACTION = 1;
+ HISTOGRAM_ENUM = 2;
+ HISTOGRAM_VALUE = 3;
+}
diff --git a/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler.h b/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler.h
new file mode 100644
index 00000000000..ad6a7db98c7
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler.h
@@ -0,0 +1,63 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SCHEDULER_MODEL_EXECUTION_SCHEDULER_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SCHEDULER_MODEL_EXECUTION_SCHEDULER_H_
+
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/model_execution_status.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+using optimization_guide::proto::OptimizationTarget;
+
+namespace segmentation_platform {
+namespace proto {
+class SegmentInfo;
+} // namespace proto
+
+// Central class responsible for scheduling model execution. Determines which
+// models are eligible for execution based on various criteria e.g. cached
+// results, TTL etc. Invoked from multiple classes such as segment
+// selector or periodic jobs.
+class ModelExecutionScheduler {
+ public:
+ // An observer to be notified about the model execution and results.
+ class Observer {
+ public:
+ // Called whenever a model execution completes.
+ virtual void OnModelExecutionCompleted(OptimizationTarget segment_id) = 0;
+ };
+
+ virtual ~ModelExecutionScheduler() = default;
+
+ // Called whenever a new or updated model is available. Must be a valid
+ // SegmentInfo with valid metadata and features.
+ virtual void OnNewModelInfoReady(const proto::SegmentInfo& segment_info) = 0;
+
+ // Central method to determine which all models to execute. Called in response
+ // to segmentation requests from clients, or periodic tasks. Can be called
+ // repeatedly. Loops through all the models and decides whether to execute a
+ // model or not. A segment is considered eligible to run based on
+ // - if it has no results, or
+ // - if the results have expired or
+ // - if the results weren't computed too recently, and |expired_only| is false
+ // - if all the required signals have been collected for sufficient duration.
+ virtual void RequestModelExecutionForEligibleSegments(bool expired_only) = 0;
+
+ // Runs model execution for a particular segment.
+ virtual void RequestModelExecution(OptimizationTarget segment_id) = 0;
+
+ // Called after model execution completes. If the execution was successful,
+ // saves the results to the DB, and notifies observers. If the execution was
+ // unsuccessful, deletes the result from the DB.
+ // TODO(shaktisahu): Do we want to store that failure reason in the DB
+ // instead? We might treat different failures differently next time.
+ virtual void OnModelExecutionCompleted(
+ OptimizationTarget segment_id,
+ const std::pair<float, ModelExecutionStatus>& result) = 0;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SCHEDULER_MODEL_EXECUTION_SCHEDULER_H_
diff --git a/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc b/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc
new file mode 100644
index 00000000000..0dfbb8fbdb7
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.cc
@@ -0,0 +1,143 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "components/segmentation_platform/internal/database/metadata_utils.h"
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/database/signal_storage_config.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+#include "components/segmentation_platform/internal/stats.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace segmentation_platform {
+
+ModelExecutionSchedulerImpl::ModelExecutionSchedulerImpl(
+ Observer* observer,
+ SegmentInfoDatabase* segment_database,
+ SignalStorageConfig* signal_storage_config,
+ ModelExecutionManager* model_execution_manager)
+ : observer_(observer),
+ segment_database_(segment_database),
+ signal_storage_config_(signal_storage_config),
+ model_execution_manager_(model_execution_manager) {}
+
+ModelExecutionSchedulerImpl::~ModelExecutionSchedulerImpl() = default;
+
+void ModelExecutionSchedulerImpl::OnNewModelInfoReady(
+ const proto::SegmentInfo& segment_info) {
+ DCHECK(metadata_utils::ValidateSegmentInfoMetadataAndFeatures(segment_info) ==
+ metadata_utils::ValidationResult::kValidationSuccess);
+
+ if (!ShouldExecuteSegment(/*expired_only=*/true, segment_info)) {
+ // We usually cancel any outstanding requests right before executing the
+ // model, but in this case we alreday know that 1) we got a new model, and
+ // b) the new model is not yet valid for execution. Therefore, we cancel
+ // the current execution and we will have to execute this model later.
+ CancelOutstandingExecutionRequests(segment_info.segment_id());
+ return;
+ }
+
+ RequestModelExecution(segment_info.segment_id());
+}
+
+void ModelExecutionSchedulerImpl::RequestModelExecutionForEligibleSegments(
+ bool expired_only) {
+ segment_database_->GetAllSegmentInfo(
+ base::BindOnce(&ModelExecutionSchedulerImpl::FilterEligibleSegments,
+ weak_ptr_factory_.GetWeakPtr(), expired_only));
+}
+
+void ModelExecutionSchedulerImpl::RequestModelExecution(
+ OptimizationTarget segment_id) {
+ CancelOutstandingExecutionRequests(segment_id);
+ outstanding_requests_.insert(std::make_pair(
+ segment_id,
+ base::BindOnce(&ModelExecutionSchedulerImpl::OnModelExecutionCompleted,
+ weak_ptr_factory_.GetWeakPtr(), segment_id)));
+ model_execution_manager_->ExecuteModel(
+ segment_id, outstanding_requests_[segment_id].callback());
+}
+
+void ModelExecutionSchedulerImpl::OnModelExecutionCompleted(
+ OptimizationTarget segment_id,
+ const std::pair<float, ModelExecutionStatus>& result) {
+ // TODO(shaktisahu): Check ModelExecutionStatus and handle failure cases.
+ // Should we save it to DB?
+ proto::PredictionResult segment_result;
+ bool success = result.second == ModelExecutionStatus::kSuccess;
+ if (success) {
+ segment_result.set_result(result.first);
+ segment_result.set_timestamp_us(
+ base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
+ stats::RecordModelScore(segment_id, result.first);
+ }
+
+ segment_database_->SaveSegmentResult(
+ segment_id, success ? absl::make_optional(segment_result) : absl::nullopt,
+ base::BindOnce(&ModelExecutionSchedulerImpl::OnResultSaved,
+ weak_ptr_factory_.GetWeakPtr(), segment_id));
+}
+
+void ModelExecutionSchedulerImpl::FilterEligibleSegments(
+ bool expired_only,
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ all_segments) {
+ std::vector<OptimizationTarget> models_to_run;
+ for (const auto& pair : all_segments) {
+ OptimizationTarget segment_id = pair.first;
+ const proto::SegmentInfo& segment_info = pair.second;
+ if (!ShouldExecuteSegment(expired_only, segment_info))
+ continue;
+
+ models_to_run.emplace_back(segment_id);
+ }
+
+ for (OptimizationTarget segment_id : models_to_run)
+ RequestModelExecution(segment_id);
+}
+
+bool ModelExecutionSchedulerImpl::ShouldExecuteSegment(
+ bool expired_only,
+ const proto::SegmentInfo& segment_info) {
+ // Filter out the segments computed recently.
+ if (metadata_utils::HasFreshResults(segment_info))
+ return false;
+
+ // Filter out the segments that aren't expired yet.
+ if (expired_only &&
+ !metadata_utils::HasExpiredOrUnavailableResult(segment_info)) {
+ return false;
+ }
+
+ // Filter out segments that don't match signal collection min length.
+ if (!signal_storage_config_->MeetsSignalCollectionRequirement(
+ segment_info.model_metadata())) {
+ return false;
+ }
+
+ return true;
+}
+
+void ModelExecutionSchedulerImpl::CancelOutstandingExecutionRequests(
+ OptimizationTarget segment_id) {
+ const auto& iter = outstanding_requests_.find(segment_id);
+ if (iter != outstanding_requests_.end()) {
+ iter->second.Cancel();
+ outstanding_requests_.erase(iter);
+ }
+}
+
+void ModelExecutionSchedulerImpl::OnResultSaved(OptimizationTarget segment_id,
+ bool success) {
+ stats::RecordModelExecutionSaveResult(segment_id, success);
+ if (!success)
+ return;
+
+ observer_->OnModelExecutionCompleted(segment_id);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.h b/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.h
new file mode 100644
index 00000000000..2fb13ae6cc6
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.h
@@ -0,0 +1,82 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_SCHEDULER_MODEL_EXECUTION_SCHEDULER_IMPL_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SCHEDULER_MODEL_EXECUTION_SCHEDULER_IMPL_H_
+
+#include "components/segmentation_platform/internal/scheduler/model_execution_scheduler.h"
+
+#include "base/cancelable_callback.h"
+#include "base/memory/weak_ptr.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+#include "components/segmentation_platform/internal/execution/model_execution_status.h"
+
+namespace segmentation_platform {
+
+namespace proto {
+class SegmentInfo;
+} // namespace proto
+
+class SegmentInfoDatabase;
+class SignalStorageConfig;
+
+class ModelExecutionSchedulerImpl : public ModelExecutionScheduler {
+ public:
+ ModelExecutionSchedulerImpl(Observer* observer,
+ SegmentInfoDatabase* segment_database,
+ SignalStorageConfig* signal_storage_config,
+ ModelExecutionManager* model_execution_manager);
+ ~ModelExecutionSchedulerImpl() override;
+
+ // Disallow copy/assign.
+ ModelExecutionSchedulerImpl(const ModelExecutionSchedulerImpl&) = delete;
+ ModelExecutionSchedulerImpl& operator=(const ModelExecutionSchedulerImpl&) =
+ delete;
+
+ // ModelExecutionScheduler overrides.
+ void OnNewModelInfoReady(const proto::SegmentInfo& segment_info) override;
+ void RequestModelExecutionForEligibleSegments(bool expired_only) override;
+ void RequestModelExecution(OptimizationTarget segment_id) override;
+ void OnModelExecutionCompleted(
+ OptimizationTarget segment_id,
+ const std::pair<float, ModelExecutionStatus>& score) override;
+
+ private:
+ void FilterEligibleSegments(
+ bool expired_only,
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ all_segments);
+ bool ShouldExecuteSegment(bool expired_only,
+ const proto::SegmentInfo& segment_info);
+ void CancelOutstandingExecutionRequests(OptimizationTarget segment_id);
+
+ void OnResultSaved(OptimizationTarget segment_id, bool success);
+
+ // Observer listening to model exeuction events. Required by the segment
+ // selection pipeline.
+ Observer* observer_;
+
+ // The database storing metadata and results.
+ SegmentInfoDatabase* segment_database_;
+
+ // Used for confirming if the signals have been collected long enough.
+ SignalStorageConfig* signal_storage_config_;
+
+ // The class that executes the models.
+ ModelExecutionManager* model_execution_manager_;
+
+ // In-flight model execution requests. Will be killed if we get a model
+ // update.
+ std::map<OptimizationTarget,
+ base::CancelableOnceCallback<
+ ModelExecutionManager::ModelExecutionCallback::RunType>>
+ outstanding_requests_;
+
+ base::WeakPtrFactory<ModelExecutionSchedulerImpl> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SCHEDULER_MODEL_EXECUTION_SCHEDULER_IMPL_H_
diff --git a/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_unittest.cc b/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_unittest.cc
new file mode 100644
index 00000000000..df6374e8583
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/scheduler/model_execution_scheduler_unittest.cc
@@ -0,0 +1,163 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.h"
+
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "components/segmentation_platform/internal/database/mock_signal_storage_config.h"
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/database/signal_storage_config.h"
+#include "components/segmentation_platform/internal/database/test_segment_info_database.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::Return;
+using testing::SaveArg;
+
+namespace segmentation_platform {
+using SignalType = proto::SignalType;
+using SignalIdentifier = std::pair<uint64_t, SignalType>;
+using CleanupItem = std::tuple<uint64_t, SignalType, base::Time>;
+
+namespace {
+constexpr auto kTestOptimizationTarget =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+} // namespace
+
+class MockModelExecutionObserver : public ModelExecutionScheduler::Observer {
+ public:
+ MockModelExecutionObserver() = default;
+ MOCK_METHOD(void, OnModelExecutionCompleted, (OptimizationTarget));
+};
+
+class MockModelExecutionManager : public ModelExecutionManager {
+ public:
+ MockModelExecutionManager() = default;
+ MOCK_METHOD(void, ExecuteModel, (OptimizationTarget, ModelExecutionCallback));
+};
+
+class ModelExecutionSchedulerTest : public testing::Test {
+ public:
+ ModelExecutionSchedulerTest() = default;
+ ~ModelExecutionSchedulerTest() override = default;
+
+ void SetUp() override {
+ segment_database_ = std::make_unique<test::TestSegmentInfoDatabase>();
+ model_execution_scheduler_ = std::make_unique<ModelExecutionSchedulerImpl>(
+ &observer_, segment_database_.get(), &signal_storage_config_,
+ &model_execution_manager_);
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ MockModelExecutionObserver observer_;
+ MockSignalStorageConfig signal_storage_config_;
+ MockModelExecutionManager model_execution_manager_;
+ std::unique_ptr<test::TestSegmentInfoDatabase> segment_database_;
+ std::unique_ptr<ModelExecutionScheduler> model_execution_scheduler_;
+};
+
+TEST_F(ModelExecutionSchedulerTest, OnNewModelInfoReady) {
+ auto* segment_info =
+ segment_database_->FindOrCreateSegment(kTestOptimizationTarget);
+ segment_info->set_segment_id(kTestOptimizationTarget);
+ auto* metadata = segment_info->mutable_model_metadata();
+ metadata->set_result_time_to_live(1);
+ metadata->set_time_unit(proto::TimeUnit::DAY);
+
+ // If the metadata DOES NOT meet the signal requirement, we SHOULD NOT try to
+ // execute the model.
+ EXPECT_CALL(model_execution_manager_,
+ ExecuteModel(kTestOptimizationTarget, _))
+ .Times(0);
+ EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_))
+ .WillOnce(Return(false));
+ model_execution_scheduler_->OnNewModelInfoReady(*segment_info);
+
+ // If the metadata DOES meet the signal requirement, and we have no old,
+ // PredictionResult we SHOULD try to execute the model.
+ EXPECT_CALL(model_execution_manager_,
+ ExecuteModel(kTestOptimizationTarget, _))
+ .Times(1);
+ EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_))
+ .WillOnce(Return(true));
+ model_execution_scheduler_->OnNewModelInfoReady(*segment_info);
+
+ // If we just got a new result, we SHOULD NOT try to execute the model.
+ auto* prediction_result = segment_info->mutable_prediction_result();
+ prediction_result->set_result(0.9);
+ prediction_result->set_timestamp_us(
+ base::Time::Now().ToDeltaSinceWindowsEpoch().InMicroseconds());
+ EXPECT_CALL(model_execution_manager_,
+ ExecuteModel(kTestOptimizationTarget, _))
+ .Times(0);
+ EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_))
+ .WillRepeatedly(Return(true)); // Ensure this part has positive result.
+ model_execution_scheduler_->OnNewModelInfoReady(*segment_info);
+
+ // If we have a non-fresh, but not expired result, we SHOULD NOT try to
+ // execute the model.
+ base::Time not_expired_timestamp = base::Time::Now() -
+ base::TimeDelta::FromDays(1) +
+ base::TimeDelta::FromHours(1);
+ prediction_result->set_result(0.9);
+ prediction_result->set_timestamp_us(
+ not_expired_timestamp.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ EXPECT_CALL(model_execution_manager_,
+ ExecuteModel(kTestOptimizationTarget, _))
+ .Times(0);
+ model_execution_scheduler_->OnNewModelInfoReady(*segment_info);
+
+ // If we have an expired result, we SHOULD try to execute the model.
+ base::Time just_expired_timestamp = base::Time::Now() -
+ base::TimeDelta::FromDays(1) -
+ base::TimeDelta::FromHours(1);
+ prediction_result->set_result(0.9);
+ prediction_result->set_timestamp_us(
+ just_expired_timestamp.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ EXPECT_CALL(model_execution_manager_,
+ ExecuteModel(kTestOptimizationTarget, _))
+ .Times(1);
+ model_execution_scheduler_->OnNewModelInfoReady(*segment_info);
+}
+
+TEST_F(ModelExecutionSchedulerTest, RequestModelExecutionForEligibleSegments) {
+ segment_database_->FindOrCreateSegment(kTestOptimizationTarget);
+
+ // TODO(shaktisahu): Add tests for expired segments, freshly computed segments
+ // etc.
+
+ EXPECT_CALL(model_execution_manager_,
+ ExecuteModel(kTestOptimizationTarget, _))
+ .Times(1);
+ EXPECT_CALL(signal_storage_config_, MeetsSignalCollectionRequirement(_))
+ .WillRepeatedly(Return(true));
+ // TODO(shaktisahu): Add test when the signal collection returns false.
+
+ model_execution_scheduler_->RequestModelExecutionForEligibleSegments(true);
+}
+
+TEST_F(ModelExecutionSchedulerTest, OnModelExecutionCompleted) {
+ proto::SegmentInfo* segment_info =
+ segment_database_->FindOrCreateSegment(kTestOptimizationTarget);
+
+ // TODO(shaktisahu): Add tests for model failure.
+ EXPECT_CALL(observer_, OnModelExecutionCompleted(kTestOptimizationTarget))
+ .Times(1);
+ float score = 0.4;
+ model_execution_scheduler_->OnModelExecutionCompleted(
+ kTestOptimizationTarget,
+ std::make_pair(score, ModelExecutionStatus::kSuccess));
+
+ // Verify that the results are written to the DB.
+ segment_info =
+ segment_database_->FindOrCreateSegment(kTestOptimizationTarget);
+ ASSERT_TRUE(segment_info->has_prediction_result());
+ ASSERT_EQ(score, segment_info->prediction_result().result());
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/segmentation_platform_service_impl.cc b/chromium/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
new file mode 100644
index 00000000000..52eab30ee51
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/segmentation_platform_service_impl.cc
@@ -0,0 +1,226 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/segmentation_platform_service_impl.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/clock.h"
+#include "components/leveldb_proto/public/proto_database_provider.h"
+#include "components/leveldb_proto/public/shared_proto_database_client_list.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/segmentation_platform/internal/constants.h"
+#include "components/segmentation_platform/internal/database/database_maintenance_impl.h"
+#include "components/segmentation_platform/internal/database/metadata_utils.h"
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/database/signal_database_impl.h"
+#include "components/segmentation_platform/internal/database/signal_storage_config.h"
+#include "components/segmentation_platform/internal/execution/feature_aggregator_impl.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager_factory.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "components/segmentation_platform/internal/proto/signal.pb.h"
+#include "components/segmentation_platform/internal/proto/signal_storage_config.pb.h"
+#include "components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.h"
+#include "components/segmentation_platform/internal/selection/segment_selector_impl.h"
+#include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h"
+#include "components/segmentation_platform/internal/signals/histogram_signal_handler.h"
+#include "components/segmentation_platform/internal/signals/signal_filter_processor.h"
+#include "components/segmentation_platform/internal/signals/user_action_signal_handler.h"
+#include "components/segmentation_platform/public/config.h"
+
+using optimization_guide::proto::OptimizationTarget;
+
+namespace segmentation_platform {
+namespace {
+const base::FilePath::CharType kSegmentInfoDBName[] =
+ FILE_PATH_LITERAL("SegmentInfoDB");
+const base::FilePath::CharType kSignalDBName[] = FILE_PATH_LITERAL("SignalDB");
+const base::FilePath::CharType kSignalStorageConfigDBName[] =
+ FILE_PATH_LITERAL("SignalStorageConfigDB");
+const base::TimeDelta kDatabaseMaintenanceDelay =
+ base::TimeDelta::FromSeconds(30);
+} // namespace
+
+SegmentationPlatformServiceImpl::SegmentationPlatformServiceImpl(
+ optimization_guide::OptimizationGuideModelProvider* model_provider,
+ leveldb_proto::ProtoDatabaseProvider* db_provider,
+ const base::FilePath& storage_dir,
+ PrefService* pref_service,
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
+ base::Clock* clock,
+ std::unique_ptr<Config> config)
+ : SegmentationPlatformServiceImpl(
+ db_provider->GetDB<proto::SegmentInfo>(
+ leveldb_proto::ProtoDbType::SEGMENT_INFO_DATABASE,
+ storage_dir.Append(kSegmentInfoDBName),
+ task_runner),
+ db_provider->GetDB<proto::SignalData>(
+ leveldb_proto::ProtoDbType::SIGNAL_DATABASE,
+ storage_dir.Append(kSignalDBName),
+ task_runner),
+ db_provider->GetDB<proto::SignalStorageConfigs>(
+ leveldb_proto::ProtoDbType::SIGNAL_STORAGE_CONFIG_DATABASE,
+ storage_dir.Append(kSignalStorageConfigDBName),
+ task_runner),
+ model_provider,
+ pref_service,
+ task_runner,
+ clock,
+ std::move(config)) {}
+
+SegmentationPlatformServiceImpl::SegmentationPlatformServiceImpl(
+ std::unique_ptr<leveldb_proto::ProtoDatabase<proto::SegmentInfo>>
+ segment_db,
+ std::unique_ptr<leveldb_proto::ProtoDatabase<proto::SignalData>> signal_db,
+ std::unique_ptr<leveldb_proto::ProtoDatabase<proto::SignalStorageConfigs>>
+ signal_storage_config_db,
+ optimization_guide::OptimizationGuideModelProvider* model_provider,
+ PrefService* pref_service,
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
+ base::Clock* clock,
+ std::unique_ptr<Config> config)
+ : model_provider_(model_provider),
+ task_runner_(task_runner),
+ clock_(clock),
+ config_(std::move(config)) {
+ // Construct databases.
+ segment_info_database_ =
+ std::make_unique<SegmentInfoDatabase>(std::move(segment_db));
+ signal_database_ =
+ std::make_unique<SignalDatabaseImpl>(std::move(signal_db), clock);
+ signal_storage_config_ = std::make_unique<SignalStorageConfig>(
+ std::move(signal_storage_config_db), clock);
+ segmentation_result_prefs_ =
+ std::make_unique<SegmentationResultPrefs>(pref_service);
+
+ // Construct signal processors.
+ user_action_signal_handler_ =
+ std::make_unique<UserActionSignalHandler>(signal_database_.get());
+ histogram_signal_handler_ =
+ std::make_unique<HistogramSignalHandler>(signal_database_.get());
+ signal_filter_processor_ = std::make_unique<SignalFilterProcessor>(
+ segment_info_database_.get(), user_action_signal_handler_.get(),
+ histogram_signal_handler_.get());
+
+ segment_selector_ = std::make_unique<SegmentSelectorImpl>(
+ segment_info_database_.get(), segmentation_result_prefs_.get(),
+ config_.get());
+
+ database_maintenance_ = std::make_unique<DatabaseMaintenanceImpl>(
+ config_.get(), clock, segment_info_database_.get(),
+ signal_database_.get(), signal_storage_config_.get());
+
+ // Kick off initialization of all databases. Internal operations will be
+ // delayed until they are all complete.
+ segment_info_database_->Initialize(base::BindOnce(
+ &SegmentationPlatformServiceImpl::OnSegmentInfoDatabaseInitialized,
+ weak_ptr_factory_.GetWeakPtr()));
+ signal_database_->Initialize(base::BindOnce(
+ &SegmentationPlatformServiceImpl::OnSignalDatabaseInitialized,
+ weak_ptr_factory_.GetWeakPtr()));
+ signal_storage_config_->InitAndLoad(base::BindOnce(
+ &SegmentationPlatformServiceImpl::OnSignalStorageConfigInitialized,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+SegmentationPlatformServiceImpl::~SegmentationPlatformServiceImpl() = default;
+
+void SegmentationPlatformServiceImpl::GetSelectedSegment(
+ const std::string& segmentation_key,
+ SegmentSelectionCallback callback) {
+ segment_selector_->GetSelectedSegment(std::move(callback));
+}
+
+void SegmentationPlatformServiceImpl::EnableMetrics(
+ bool signal_collection_allowed) {
+ signal_filter_processor_->EnableMetrics(signal_collection_allowed);
+}
+
+void SegmentationPlatformServiceImpl::OnSegmentInfoDatabaseInitialized(
+ bool success) {
+ segment_info_database_initialized_ = success;
+ MaybeRunPostInitializationRoutines();
+}
+
+void SegmentationPlatformServiceImpl::OnSignalDatabaseInitialized(
+ bool success) {
+ signal_database_initialized_ = success;
+ MaybeRunPostInitializationRoutines();
+}
+
+void SegmentationPlatformServiceImpl::OnSignalStorageConfigInitialized(
+ bool success) {
+ signal_storage_config_initialized_ = success;
+ MaybeRunPostInitializationRoutines();
+}
+
+bool SegmentationPlatformServiceImpl::IsInitializationFinished() const {
+ return segment_info_database_initialized_.has_value() &&
+ signal_database_initialized_.has_value() &&
+ signal_storage_config_initialized_.has_value();
+}
+
+void SegmentationPlatformServiceImpl::MaybeRunPostInitializationRoutines() {
+ if (!IsInitializationFinished())
+ return;
+
+ bool init_success = segment_info_database_initialized_ &&
+ signal_database_initialized_ &&
+ signal_storage_config_initialized_;
+ if (!init_success)
+ return;
+
+ model_execution_manager_ = CreateModelExecutionManager(
+ model_provider_, task_runner_, config_->segment_ids, clock_,
+ segment_info_database_.get(), signal_database_.get(),
+ std::make_unique<FeatureAggregatorImpl>(),
+ base::BindRepeating(
+ &SegmentationPlatformServiceImpl::OnSegmentationModelUpdated,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ model_execution_scheduler_ = std::make_unique<ModelExecutionSchedulerImpl>(
+ segment_selector_.get(), segment_info_database_.get(),
+ signal_storage_config_.get(), model_execution_manager_.get());
+
+ signal_filter_processor_->OnSignalListUpdated();
+ model_execution_scheduler_->RequestModelExecutionForEligibleSegments(
+ /*expired_only=*/true);
+
+ // Initiate database maintenance tasks with a small delay.
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(
+ &SegmentationPlatformServiceImpl::OnExecuteDatabaseMaintenanceTasks,
+ weak_ptr_factory_.GetWeakPtr()),
+ kDatabaseMaintenanceDelay);
+}
+
+void SegmentationPlatformServiceImpl::OnSegmentationModelUpdated(
+ proto::SegmentInfo segment_info) {
+ DCHECK(metadata_utils::ValidateSegmentInfoMetadataAndFeatures(segment_info) ==
+ metadata_utils::ValidationResult::kValidationSuccess);
+
+ signal_storage_config_->OnSignalCollectionStarted(
+ segment_info.model_metadata());
+ signal_filter_processor_->OnSignalListUpdated();
+
+ model_execution_scheduler_->OnNewModelInfoReady(segment_info);
+}
+
+void SegmentationPlatformServiceImpl::OnExecuteDatabaseMaintenanceTasks() {
+ database_maintenance_->ExecuteMaintenanceTasks();
+}
+
+// static
+void SegmentationPlatformService::RegisterProfilePrefs(
+ PrefRegistrySimple* registry) {
+ registry->RegisterDictionaryPref(kSegmentationResultPref);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/segmentation_platform_service_impl.h b/chromium/components/segmentation_platform/internal/segmentation_platform_service_impl.h
new file mode 100644
index 00000000000..b237d3876a5
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/segmentation_platform_service_impl.h
@@ -0,0 +1,151 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_SEGMENTATION_PLATFORM_SERVICE_IMPL_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SEGMENTATION_PLATFORM_SERVICE_IMPL_H_
+
+#include "components/segmentation_platform/public/segmentation_platform_service.h"
+
+#include <memory>
+#include <string>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "components/leveldb_proto/public/proto_database.h"
+
+namespace base {
+class Clock;
+class FilePath;
+class SequencedTaskRunner;
+} // namespace base
+
+namespace leveldb_proto {
+class ProtoDatabaseProvider;
+} // namespace leveldb_proto
+
+namespace optimization_guide {
+class OptimizationGuideModelProvider;
+} // namespace optimization_guide
+
+class PrefService;
+
+namespace segmentation_platform {
+
+namespace proto {
+class SegmentInfo;
+class SignalData;
+class SignalStorageConfigs;
+} // namespace proto
+
+struct Config;
+class DatabaseMaintenanceImpl;
+class HistogramSignalHandler;
+class ModelExecutionManager;
+class ModelExecutionSchedulerImpl;
+class SegmentationResultPrefs;
+class SegmentInfoDatabase;
+class SegmentSelectorImpl;
+class SignalDatabaseImpl;
+class SignalFilterProcessor;
+class SignalStorageConfig;
+class UserActionSignalHandler;
+
+// The internal implementation of the SegmentationPlatformService.
+class SegmentationPlatformServiceImpl : public SegmentationPlatformService {
+ public:
+ SegmentationPlatformServiceImpl(
+ optimization_guide::OptimizationGuideModelProvider* model_provider,
+ leveldb_proto::ProtoDatabaseProvider* db_provider,
+ const base::FilePath& storage_dir,
+ PrefService* pref_service,
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
+ base::Clock* clock,
+ std::unique_ptr<Config> config);
+
+ // For testing only.
+ SegmentationPlatformServiceImpl(
+ std::unique_ptr<leveldb_proto::ProtoDatabase<proto::SegmentInfo>>
+ segment_db,
+ std::unique_ptr<leveldb_proto::ProtoDatabase<proto::SignalData>>
+ signal_db,
+ std::unique_ptr<leveldb_proto::ProtoDatabase<proto::SignalStorageConfigs>>
+ signal_storage_config_db,
+ optimization_guide::OptimizationGuideModelProvider* model_provider,
+ PrefService* pref_service,
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
+ base::Clock* clock,
+ std::unique_ptr<Config> config);
+
+ ~SegmentationPlatformServiceImpl() override;
+
+ // Disallow copy/assign.
+ SegmentationPlatformServiceImpl(const SegmentationPlatformServiceImpl&) =
+ delete;
+ SegmentationPlatformServiceImpl& operator=(
+ const SegmentationPlatformServiceImpl&) = delete;
+
+ // SegmentationPlatformService overrides.
+ void GetSelectedSegment(const std::string& segmentation_key,
+ SegmentSelectionCallback callback) override;
+ void EnableMetrics(bool signal_collection_allowed) override;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(SegmentationPlatformServiceImplTest,
+ InitializationFlow);
+
+ void OnSegmentInfoDatabaseInitialized(bool success);
+ void OnSignalDatabaseInitialized(bool success);
+ void OnSignalStorageConfigInitialized(bool success);
+ bool IsInitializationFinished() const;
+ void MaybeRunPostInitializationRoutines();
+ // Must only be invoked with a valid SegmentInfo.
+ void OnSegmentationModelUpdated(proto::SegmentInfo segment_info);
+
+ // Executes all database maintenance tasks. This should be invoked after a
+ // short amount of time has passed since initialization happened.
+ void OnExecuteDatabaseMaintenanceTasks();
+
+ optimization_guide::OptimizationGuideModelProvider* model_provider_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ base::Clock* clock_;
+
+ // Config.
+ std::unique_ptr<Config> config_;
+
+ // Databases.
+ std::unique_ptr<SegmentInfoDatabase> segment_info_database_;
+ std::unique_ptr<SignalDatabaseImpl> signal_database_;
+ std::unique_ptr<SignalStorageConfig> signal_storage_config_;
+ std::unique_ptr<SegmentationResultPrefs> segmentation_result_prefs_;
+
+ // Signal processing.
+ std::unique_ptr<UserActionSignalHandler> user_action_signal_handler_;
+ std::unique_ptr<HistogramSignalHandler> histogram_signal_handler_;
+ std::unique_ptr<SignalFilterProcessor> signal_filter_processor_;
+
+ // Segment selection.
+ // TODO(shaktisahu): Determine safe destruction ordering between
+ // SegmentSelectorImpl and ModelExecutionSchedulerImpl.
+ std::unique_ptr<SegmentSelectorImpl> segment_selector_;
+
+ // Model execution scheduling logic.
+ std::unique_ptr<ModelExecutionSchedulerImpl> model_execution_scheduler_;
+
+ // Model execution.
+ std::unique_ptr<ModelExecutionManager> model_execution_manager_;
+
+ // Database maintenance.
+ std::unique_ptr<DatabaseMaintenanceImpl> database_maintenance_;
+
+ // Database initialization statuses.
+ absl::optional<bool> segment_info_database_initialized_;
+ absl::optional<bool> signal_database_initialized_;
+ absl::optional<bool> signal_storage_config_initialized_;
+
+ base::WeakPtrFactory<SegmentationPlatformServiceImpl> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SEGMENTATION_PLATFORM_SERVICE_IMPL_H_
diff --git a/chromium/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc b/chromium/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc
new file mode 100644
index 00000000000..3ca58955b0e
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc
@@ -0,0 +1,218 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/segmentation_platform_service_impl.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/metrics/metrics_hashes.h"
+#include "base/metrics/user_metrics.h"
+#include "base/run_loop.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/simple_test_clock.h"
+#include "base/test/task_environment.h"
+#include "base/test/test_simple_task_runner.h"
+#include "components/leveldb_proto/public/proto_database_provider.h"
+#include "components/leveldb_proto/public/shared_proto_database_client_list.h"
+#include "components/leveldb_proto/testing/fake_db.h"
+#include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
+#include "components/optimization_guide/machine_learning_tflite_buildflags.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/segmentation_platform/internal/constants.h"
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/database/signal_database_impl.h"
+#include "components/segmentation_platform/internal/database/signal_storage_config.h"
+#include "components/segmentation_platform/internal/execution/feature_aggregator_impl.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager.h"
+#include "components/segmentation_platform/internal/execution/model_execution_manager_factory.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "components/segmentation_platform/internal/proto/signal.pb.h"
+#include "components/segmentation_platform/internal/proto/signal_storage_config.pb.h"
+#include "components/segmentation_platform/internal/scheduler/model_execution_scheduler_impl.h"
+#include "components/segmentation_platform/internal/selection/segment_selector_impl.h"
+#include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h"
+#include "components/segmentation_platform/internal/signals/histogram_signal_handler.h"
+#include "components/segmentation_platform/internal/signals/signal_filter_processor.h"
+#include "components/segmentation_platform/internal/signals/user_action_signal_handler.h"
+#include "components/segmentation_platform/public/config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+#include "components/segmentation_platform/internal/execution/model_execution_manager_impl.h"
+#endif // BUILDFLAG(BUILD_WITH_TFLITE_LIB
+
+namespace segmentation_platform {
+namespace {
+
+std::string kTestSegmentationKey = "some_key";
+
+Config CreateTestConfig() {
+ Config config;
+ config.segmentation_key = kTestSegmentationKey;
+ config.segment_selection_ttl = base::TimeDelta::FromDays(28);
+ config.segment_ids = {
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE};
+ return config;
+}
+} // namespace
+
+class SegmentationPlatformServiceImplTest : public testing::Test {
+ public:
+ SegmentationPlatformServiceImplTest() = default;
+ ~SegmentationPlatformServiceImplTest() override = default;
+
+ void SetUp() override {
+ task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>();
+ base::SetRecordActionTaskRunner(
+ task_environment_.GetMainThreadTaskRunner());
+
+ auto segment_db =
+ std::make_unique<leveldb_proto::test::FakeDB<proto::SegmentInfo>>(
+ &segment_db_entries_);
+ auto signal_db =
+ std::make_unique<leveldb_proto::test::FakeDB<proto::SignalData>>(
+ &signal_db_entries_);
+ auto segment_storage_config_db = std::make_unique<
+ leveldb_proto::test::FakeDB<proto::SignalStorageConfigs>>(
+ &segment_storage_config_db_entries_);
+ segment_db_ = segment_db.get();
+ signal_db_ = signal_db.get();
+ segment_storage_config_db_ = segment_storage_config_db.get();
+
+ SegmentationPlatformService::RegisterProfilePrefs(pref_service_.registry());
+ SetUpPrefs(OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE);
+
+ auto config = std::make_unique<Config>(CreateTestConfig());
+ config_ = config.get();
+ segmentation_platform_service_impl_ =
+ std::make_unique<SegmentationPlatformServiceImpl>(
+ std::move(segment_db), std::move(signal_db),
+ std::move(segment_storage_config_db), &model_provider_,
+ &pref_service_, task_runner_, &test_clock_, std::move(config));
+ }
+
+ void TearDown() override {
+ segmentation_platform_service_impl_.reset();
+ // Allow for the SegmentationModelExecutor owned by SegmentationModelHandler
+ // to be destroyed.
+ task_runner_->RunUntilIdle();
+ }
+
+ void SetUpPrefs(OptimizationTarget segment_id) {
+ DictionaryPrefUpdate update(&pref_service_, kSegmentationResultPref);
+ base::DictionaryValue* dictionary = update.Get();
+
+ base::Value segmentation_result(base::Value::Type::DICTIONARY);
+ segmentation_result.SetIntKey("segment_id", segment_id);
+ dictionary->SetKey(kTestSegmentationKey, std::move(segmentation_result));
+ }
+
+ void OnGetSelectedSegment(base::RepeatingClosure closure,
+ const SegmentSelectionResult& expected,
+ const SegmentSelectionResult& actual) {
+ ASSERT_EQ(expected, actual);
+ std::move(closure).Run();
+ }
+
+ protected:
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+ Config* config_;
+ std::map<std::string, proto::SegmentInfo> segment_db_entries_;
+ std::map<std::string, proto::SignalData> signal_db_entries_;
+ std::map<std::string, proto::SignalStorageConfigs>
+ segment_storage_config_db_entries_;
+ leveldb_proto::test::FakeDB<proto::SegmentInfo>* segment_db_;
+ leveldb_proto::test::FakeDB<proto::SignalData>* signal_db_;
+ leveldb_proto::test::FakeDB<proto::SignalStorageConfigs>*
+ segment_storage_config_db_;
+ optimization_guide::TestOptimizationGuideModelProvider model_provider_;
+ TestingPrefServiceSimple pref_service_;
+ base::SimpleTestClock test_clock_;
+ std::unique_ptr<SegmentationPlatformServiceImpl>
+ segmentation_platform_service_impl_;
+};
+
+TEST_F(SegmentationPlatformServiceImplTest, InitializationFlow) {
+ // Let the DB loading complete successfully.
+ segment_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ signal_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK);
+ segment_storage_config_db_->InitStatusCallback(
+ leveldb_proto::Enums::InitStatus::kOK);
+ segment_storage_config_db_->LoadCallback(true);
+
+ // If initialization is succeeded, model execution scheduler should start
+ // querying segment db.
+ segment_db_->LoadCallback(true);
+
+ // If we build with TF Lite, we need to also inspect whether the
+ // ModelExecutionManagerImpl is publishing the correct data and whether that
+ // leads to the SegmentationPlatformServiceImpl doing the right thing.
+#if BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+ proto::SegmentationModelMetadata metadata;
+ metadata.set_time_unit(proto::TimeUnit::DAY);
+ metadata.set_bucket_duration(42u);
+ // Add a test feature, which will later cause the signal storage DB to be
+ // updated.
+ auto* feature = metadata.add_features();
+ feature->set_type(proto::SignalType::HISTOGRAM_VALUE);
+ feature->set_name("other");
+ feature->set_name_hash(base::HashMetricName("other"));
+ feature->set_aggregation(proto::Aggregation::BUCKETED_SUM);
+ feature->set_bucket_count(3);
+ feature->set_tensor_length(3);
+
+ ModelExecutionManagerImpl* mem_impl = static_cast<ModelExecutionManagerImpl*>(
+ segmentation_platform_service_impl_->model_execution_manager_.get());
+
+ // This method is invoked from SegmentationModelHandler whenever a model has
+ // been updated and every time at startup. This will first read the old info
+ // from the database, and then write the merged result of the old and new to
+ // the database.
+ base::HistogramTester histogram_tester;
+ mem_impl->OnSegmentationModelUpdated(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE, metadata);
+ segment_db_->GetCallback(true);
+ segment_db_->UpdateCallback(true);
+
+ // Since the updated config had a new feature, the SignalStorageConfigs DB
+ // should have been updated.
+ segment_storage_config_db_->UpdateCallback(true);
+
+ // The SignalFilterProcessor needs to read the segment information from the
+ // database before starting to listen to the updated signals.
+ segment_db_->LoadCallback(true);
+ // We should have started recording 1 value histogram, once.
+ EXPECT_EQ(
+ 1, histogram_tester.GetBucketCount(
+ "SegmentationPlatform.Signals.ListeningCount.HistogramValue", 1));
+#endif // BUILDFLAG(BUILD_WITH_TFLITE_LIB)
+
+ // Database maintenance tasks should try to cleanup the signals after a short
+ // delay, which starts with looking up data from the SegmentInfoDatabase.
+ task_environment_.FastForwardUntilNoTasksRemain();
+ segment_db_->LoadCallback(true);
+}
+
+TEST_F(SegmentationPlatformServiceImplTest,
+ GetSelectedSegmentBeforeInitialization) {
+ SegmentSelectionResult expected;
+ expected.is_ready = true;
+ expected.segment = OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE;
+ base::RunLoop loop;
+ segmentation_platform_service_impl_->GetSelectedSegment(
+ kTestSegmentationKey,
+ base::BindOnce(&SegmentationPlatformServiceImplTest::OnGetSelectedSegment,
+ base::Unretained(this), loop.QuitClosure(), expected));
+ loop.Run();
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/selection/segment_selector.h b/chromium/components/segmentation_platform/internal/selection/segment_selector.h
new file mode 100644
index 00000000000..9dd8a8a25b6
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/selection/segment_selector.h
@@ -0,0 +1,59 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENT_SELECTOR_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENT_SELECTOR_H_
+
+#include "base/callback.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/execution/model_execution_status.h"
+#include "components/segmentation_platform/internal/scheduler/model_execution_scheduler.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+using optimization_guide::proto::OptimizationTarget;
+
+namespace segmentation_platform {
+struct SegmentSelectionResult;
+
+// Central class for segment selection that can be used by clients to find the
+// best selected segment or result of a particular segment. Listens for model
+// execution events, on which it selects the best segment and writes it to
+// prefs. The computed results are only used in the next session. Current
+// session uses results from the last session.
+class SegmentSelector : public ModelExecutionScheduler::Observer {
+ public:
+ virtual ~SegmentSelector() = default;
+
+ using SegmentSelectionCallback =
+ base::OnceCallback<void(const SegmentSelectionResult&)>;
+ using SingleSegmentResultCallback =
+ base::OnceCallback<void(absl::optional<float>)>;
+
+ // Called to initialize the selector. Reads results from last session into
+ // memory. Must be invoked before calling any other method except
+ // GetSelectedSegment which is served from prefs.
+ // TODO(shaktisahu): Remove this method. Save model scores to prefs, and read
+ // them back in constructor. After that, none of the public methods will need
+ // to wait for the segment DB loading.
+ virtual void Initialize(base::OnceClosure callback) = 0;
+
+ // Client API. Returns the selected segment from the last session. If none,
+ // returns empty result.
+ virtual void GetSelectedSegment(SegmentSelectionCallback callback) = 0;
+
+ // Client API to get the score for a single segment. Returns the cached score
+ // from the last session.
+ virtual void GetSegmentScore(OptimizationTarget segment_id,
+ SingleSegmentResultCallback callback) = 0;
+
+ // Client API. Called when the segment is actually used by the client
+ // features, so that we have to honor segment_selection_ttl_days. Should be
+ // saved to prefs. If the selected segment hasn't been used, the pref result
+ // can be overwritten any number of times.
+ virtual void OnSegmentUsed(OptimizationTarget segment_id) = 0;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENT_SELECTOR_H_
diff --git a/chromium/components/segmentation_platform/internal/selection/segment_selector_impl.cc b/chromium/components/segmentation_platform/internal/selection/segment_selector_impl.cc
new file mode 100644
index 00000000000..de5b951da24
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/selection/segment_selector_impl.cc
@@ -0,0 +1,190 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/selection/segment_selector_impl.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/segmentation_platform/internal/constants.h"
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h"
+#include "components/segmentation_platform/internal/stats.h"
+#include "components/segmentation_platform/public/config.h"
+
+namespace segmentation_platform {
+
+SegmentSelectorImpl::SegmentSelectorImpl(SegmentInfoDatabase* segment_database,
+ SegmentationResultPrefs* result_prefs,
+ Config* config)
+ : segment_database_(segment_database),
+ result_prefs_(result_prefs),
+ config_(config),
+ initialized_(false) {
+ // Read selected segment from prefs.
+ const auto& selected_segment =
+ result_prefs_->ReadSegmentationResultFromPref(config_->segmentation_key);
+ if (selected_segment.has_value()) {
+ selected_segment_last_session_.segment = selected_segment->segment_id;
+ selected_segment_last_session_.is_ready = true;
+ }
+}
+
+SegmentSelectorImpl::~SegmentSelectorImpl() = default;
+
+void SegmentSelectorImpl::Initialize(base::OnceClosure callback) {
+ // Read model results from DB.
+ segment_database_->GetSegmentInfoForSegments(
+ config_->segment_ids,
+ base::BindOnce(&SegmentSelectorImpl::ReadScoresFromLastSession,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void SegmentSelectorImpl::GetSelectedSegment(
+ SegmentSelectionCallback callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback), selected_segment_last_session_));
+}
+
+void SegmentSelectorImpl::GetSegmentScore(
+ OptimizationTarget segment_id,
+ SingleSegmentResultCallback callback) {
+ DCHECK(initialized_);
+
+ absl::optional<float> score;
+ auto iter = segment_score_last_session_.find(segment_id);
+ if (iter != segment_score_last_session_.end())
+ score = iter->second;
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), score));
+}
+
+void SegmentSelectorImpl::OnSegmentUsed(OptimizationTarget segment_id) {
+ DCHECK(initialized_);
+ // TODO(shaktisahu): Implement this.
+}
+
+void SegmentSelectorImpl::OnModelExecutionCompleted(
+ OptimizationTarget segment_id) {
+ segment_database_->GetSegmentInfoForSegments(
+ config_->segment_ids,
+ base::BindOnce(&SegmentSelectorImpl::FindBestSegment,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void SegmentSelectorImpl::FindBestSegment(
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ all_segments) {
+ int max_score = 0;
+ OptimizationTarget max_score_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN;
+ // Loop through all the results. Convert them to discrete scores. Select the
+ // one with highest discrete score.
+ for (const auto& pair : all_segments) {
+ OptimizationTarget id = pair.first;
+ const proto::SegmentInfo& info = pair.second;
+ if (id == OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN)
+ continue;
+
+ if (!info.has_prediction_result())
+ continue;
+
+ int score = ConvertToDiscreteScore(id, config_->segmentation_key,
+ info.prediction_result().result(),
+ info.model_metadata());
+ if (score > max_score) {
+ max_score = score;
+ max_score_id = id;
+ } else if (score == max_score && score > 0) {
+ // TODO(shaktisahu): Use fallback priority.
+ }
+ }
+
+ UpdateSelectedSegment(max_score_id);
+}
+
+void SegmentSelectorImpl::UpdateSelectedSegment(
+ OptimizationTarget new_selection) {
+ const auto& previous_selection =
+ result_prefs_->ReadSegmentationResultFromPref(config_->segmentation_key);
+
+ bool skip_updating_prefs = false;
+ if (previous_selection.has_value()) {
+ skip_updating_prefs =
+ new_selection == previous_selection->segment_id ||
+ (previous_selection->selection_time + config_->segment_selection_ttl >
+ base::Time::Now());
+ // TODO(shaktisahu): Use segment selection inertia.
+ }
+
+ stats::RecordSegmentSelectionComputed(
+ new_selection, previous_selection.has_value()
+ ? absl::make_optional(previous_selection->segment_id)
+ : absl::nullopt);
+
+ if (skip_updating_prefs)
+ return;
+
+ // Write result to prefs. Delete if no valid selection.
+ absl::optional<SelectedSegment> updated_selection;
+ if (new_selection != OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN) {
+ updated_selection = absl::make_optional<SelectedSegment>(new_selection);
+ updated_selection->selection_time = base::Time::Now();
+ }
+ result_prefs_->SaveSegmentationResultToPref(config_->segmentation_key,
+ updated_selection);
+}
+
+void SegmentSelectorImpl::ReadScoresFromLastSession(
+ base::OnceClosure callback,
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ all_segments) {
+ // Read results from last session to memory.
+ for (const auto& pair : all_segments) {
+ OptimizationTarget id = pair.first;
+ const proto::SegmentInfo& info = pair.second;
+ if (!info.has_prediction_result())
+ continue;
+
+ float result = info.prediction_result().result();
+ segment_score_last_session_.emplace(std::make_pair(id, result));
+ }
+
+ initialized_ = true;
+ std::move(callback).Run();
+}
+
+int SegmentSelectorImpl::ConvertToDiscreteScore(
+ OptimizationTarget segment_id,
+ const std::string& mapping_key,
+ float score,
+ const proto::SegmentationModelMetadata& metadata) {
+ auto iter = metadata.discrete_mappings().find(mapping_key);
+ if (iter == metadata.discrete_mappings().end()) {
+ iter =
+ metadata.discrete_mappings().find(metadata.default_discrete_mapping());
+ if (iter == metadata.discrete_mappings().end())
+ return 0;
+ }
+ DCHECK(iter != metadata.discrete_mappings().end());
+
+ const auto& mapping = iter->second;
+
+ // Iterate over the entries and find the last entry whose min result is equal
+ // to or less than the input.
+ int discrete_result = 0;
+ for (int i = 0; i < mapping.entries_size(); i++) {
+ const auto& entry = mapping.entries(i);
+ if (score < entry.min_result())
+ break;
+
+ discrete_result = entry.rank();
+ }
+
+ return discrete_result;
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/selection/segment_selector_impl.h b/chromium/components/segmentation_platform/internal/selection/segment_selector_impl.h
new file mode 100644
index 00000000000..e2582f4714d
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/selection/segment_selector_impl.h
@@ -0,0 +1,97 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENT_SELECTOR_IMPL_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENT_SELECTOR_IMPL_H_
+
+#include "components/segmentation_platform/internal/selection/segment_selector.h"
+
+#include "base/callback_helpers.h"
+#include "components/segmentation_platform/public/segment_selection_result.h"
+
+namespace segmentation_platform {
+
+struct Config;
+class ModelExecutionScheduler;
+class SegmentationResultPrefs;
+class SegmentInfoDatabase;
+
+namespace proto {
+class SegmentInfo;
+class SegmentationModelMetadata;
+} // namespace proto
+
+class SegmentSelectorImpl : public SegmentSelector {
+ public:
+ SegmentSelectorImpl(SegmentInfoDatabase* segment_database,
+ SegmentationResultPrefs* result_prefs,
+ Config* config);
+
+ ~SegmentSelectorImpl() override;
+
+ // SegmentSelector overrides.
+ void Initialize(base::OnceClosure callback) override;
+ void GetSelectedSegment(SegmentSelectionCallback callback) override;
+ void GetSegmentScore(OptimizationTarget segment_id,
+ SingleSegmentResultCallback callback) override;
+ void OnSegmentUsed(OptimizationTarget segment_id) override;
+
+ // ModelExecutionScheduler::Observer overrides.
+
+ // Called whenever a model eval completes. Runs segment selection to find the
+ // best segment, and writes it to the pref.
+ void OnModelExecutionCompleted(OptimizationTarget segment_id) override;
+
+ private:
+ // For testing.
+ friend class SegmentSelectorTest;
+
+ // Loops through all segments, performs discrete mapping, honors finch
+ // supplied tie-breakers, TTL, inertia etc, and finds the highest score.
+ // Ignores the segments that have no results.
+ void FindBestSegment(
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ all_segments);
+
+ // Helper function to update the selected segment in the prefs, if the new
+ // selection passes the criteria for segment selection TTL, and segment
+ // selection inertia.
+ void UpdateSelectedSegment(OptimizationTarget new_selection);
+
+ // Callback method used during initialization to read the model results into
+ // memory.
+ void ReadScoresFromLastSession(
+ base::OnceClosure callback,
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ all_segments);
+
+ // Helper method to convert continuous to discrete score.
+ int ConvertToDiscreteScore(OptimizationTarget segment_id,
+ const std::string& mapping_key,
+ float score,
+ const proto::SegmentationModelMetadata& metadata);
+
+ // The database storing metadata and results.
+ SegmentInfoDatabase* segment_database_;
+
+ // Helper class to read/write results to the prefs.
+ SegmentationResultPrefs* result_prefs_;
+
+ // The config for providing configuration params.
+ Config* config_;
+
+ // These values are read from prefs or db on init and used for serving the
+ // clients in the current session.
+ SegmentSelectionResult selected_segment_last_session_;
+ std::map<OptimizationTarget, float> segment_score_last_session_;
+
+ // Whether the initialization is complete through an Initialize call.
+ bool initialized_;
+
+ base::WeakPtrFactory<SegmentSelectorImpl> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENT_SELECTOR_IMPL_H_
diff --git a/chromium/components/segmentation_platform/internal/selection/segment_selector_unittest.cc b/chromium/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
new file mode 100644
index 00000000000..58ec89a50c0
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/selection/segment_selector_unittest.cc
@@ -0,0 +1,280 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/selection/segment_selector_impl.h"
+
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "components/segmentation_platform/internal/constants.h"
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/database/test_segment_info_database.h"
+#include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h"
+#include "components/segmentation_platform/public/config.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::Return;
+using testing::SaveArg;
+
+namespace segmentation_platform {
+namespace proto {
+class SegmentInfo;
+} // namespace proto
+
+namespace {
+
+Config CreateTestConfig() {
+ Config config;
+ config.segmentation_key = "some_key";
+ config.segment_selection_ttl = base::TimeDelta::FromDays(28);
+ config.segment_ids = {
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE};
+ return config;
+}
+} // namespace
+
+class MockSegmentationResultPrefs : public SegmentationResultPrefs {
+ public:
+ MockSegmentationResultPrefs() : SegmentationResultPrefs(nullptr) {}
+ MOCK_METHOD(void,
+ SaveSegmentationResultToPref,
+ (const std::string&, const absl::optional<SelectedSegment>&));
+ MOCK_METHOD(absl::optional<SelectedSegment>,
+ ReadSegmentationResultFromPref,
+ (const std::string&));
+};
+
+class SegmentSelectorTest : public testing::Test {
+ public:
+ SegmentSelectorTest() = default;
+ ~SegmentSelectorTest() override = default;
+
+ void SetUp() override {
+ config_ = CreateTestConfig();
+ segment_database_ = std::make_unique<test::TestSegmentInfoDatabase>();
+ prefs_ = std::make_unique<MockSegmentationResultPrefs>();
+ segment_selector_ = std::make_unique<SegmentSelectorImpl>(
+ segment_database_.get(), prefs_.get(), &config_);
+ }
+
+ int ConvertToDiscreteScore(OptimizationTarget segment_id,
+ const std::string& mapping_key,
+ float score,
+ const proto::SegmentationModelMetadata& metadata) {
+ return segment_selector_->ConvertToDiscreteScore(segment_id, mapping_key,
+ score, metadata);
+ }
+
+ void GetSelectedSegment(const SegmentSelectionResult& expected) {
+ base::RunLoop loop;
+ segment_selector_->GetSelectedSegment(
+ base::BindOnce(&SegmentSelectorTest::OnGetSelectedSegment,
+ base::Unretained(this), loop.QuitClosure(), expected));
+ loop.Run();
+ }
+
+ void OnGetSelectedSegment(base::RepeatingClosure closure,
+ const SegmentSelectionResult& expected,
+ const SegmentSelectionResult& actual) {
+ ASSERT_EQ(expected, actual);
+ std::move(closure).Run();
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ Config config_;
+ std::unique_ptr<test::TestSegmentInfoDatabase> segment_database_;
+ std::unique_ptr<MockSegmentationResultPrefs> prefs_;
+ std::unique_ptr<SegmentSelectorImpl> segment_selector_;
+};
+
+TEST_F(SegmentSelectorTest, CheckDiscreteMapping) {
+ OptimizationTarget segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ float mapping[][2] = {{0.2, 1}, {0.5, 3}, {0.7, 4}};
+ segment_database_->AddDiscreteMapping(segment_id, mapping, 3,
+ config_.segmentation_key);
+ proto::SegmentInfo* segment_info =
+ segment_database_->FindOrCreateSegment(segment_id);
+ const proto::SegmentationModelMetadata& metadata =
+ segment_info->model_metadata();
+
+ ASSERT_EQ(0, ConvertToDiscreteScore(segment_id, config_.segmentation_key, 0.1,
+ metadata));
+ ASSERT_EQ(1, ConvertToDiscreteScore(segment_id, config_.segmentation_key, 0.4,
+ metadata));
+ ASSERT_EQ(3, ConvertToDiscreteScore(segment_id, config_.segmentation_key, 0.5,
+ metadata));
+ ASSERT_EQ(3, ConvertToDiscreteScore(segment_id, config_.segmentation_key, 0.6,
+ metadata));
+ ASSERT_EQ(4, ConvertToDiscreteScore(segment_id, config_.segmentation_key, 0.9,
+ metadata));
+}
+
+TEST_F(SegmentSelectorTest, CheckMissingDiscreteMapping) {
+ OptimizationTarget segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ proto::SegmentInfo* segment_info =
+ segment_database_->FindOrCreateSegment(segment_id);
+ const proto::SegmentationModelMetadata& metadata =
+ segment_info->model_metadata();
+
+ // Any value should result in a 0 mapping, since no mapping exists.
+ ASSERT_EQ(0, ConvertToDiscreteScore(segment_id, config_.segmentation_key, 0.9,
+ metadata));
+}
+
+TEST_F(SegmentSelectorTest, CheckDefaultDiscreteMapping) {
+ OptimizationTarget segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ float mapping_specific[][2] = {{0.2, 1}, {0.5, 3}, {0.7, 4}};
+ float mapping_default[][2] = {{0.2, 5}, {0.5, 6}, {0.7, 7}};
+ segment_database_->AddDiscreteMapping(segment_id, mapping_specific, 3,
+ config_.segmentation_key);
+ segment_database_->AddDiscreteMapping(segment_id, mapping_default, 3,
+ "my-default");
+ proto::SegmentInfo* segment_info =
+ segment_database_->FindOrCreateSegment(segment_id);
+ proto::SegmentationModelMetadata* metadata =
+ segment_info->mutable_model_metadata();
+
+ // No valid mapping should be found since there is no default mapping.
+ EXPECT_EQ(0, ConvertToDiscreteScore(segment_id, "non-existing-key", 0.6,
+ *metadata));
+
+ metadata->set_default_discrete_mapping("my-default");
+ // Should now use the default values instead of the one from the
+ // one in the configuration key.
+ EXPECT_EQ(6, ConvertToDiscreteScore(segment_id, "non-existing-key", 0.6,
+ *metadata));
+}
+
+TEST_F(SegmentSelectorTest, CheckMissingDefaultDiscreteMapping) {
+ OptimizationTarget segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ float mapping_default[][2] = {{0.2, 5}, {0.5, 6}, {0.7, 7}};
+ segment_database_->AddDiscreteMapping(segment_id, mapping_default, 3,
+ "my-default");
+ proto::SegmentInfo* segment_info =
+ segment_database_->FindOrCreateSegment(segment_id);
+ proto::SegmentationModelMetadata* metadata =
+ segment_info->mutable_model_metadata();
+ metadata->set_default_discrete_mapping("not-my-default");
+
+ // Should not find 'not-my-default' mapping, since it is registered as
+ // 'my-default', so we should get a 0 result.
+ EXPECT_EQ(0, ConvertToDiscreteScore(segment_id, "non-existing-key", 0.6,
+ *metadata));
+}
+
+TEST_F(SegmentSelectorTest, FindBestSegmentFlowWithTwoSegments) {
+ OptimizationTarget segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ float mapping[][2] = {{0.2, 1}, {0.5, 3}, {0.7, 4}};
+ segment_database_->AddDiscreteMapping(segment_id, mapping, 3,
+ config_.segmentation_key);
+
+ OptimizationTarget segment_id2 =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE;
+ float mapping2[][2] = {{0.3, 1}, {0.4, 4}};
+ segment_database_->AddDiscreteMapping(segment_id2, mapping2, 2,
+ config_.segmentation_key);
+
+ base::Time result_timestamp = base::Time::Now();
+ segment_database_->AddPredictionResult(segment_id, 0.6, result_timestamp);
+ segment_database_->AddPredictionResult(segment_id2, 0.5, result_timestamp);
+
+ absl::optional<SelectedSegment> selected_segment;
+ EXPECT_CALL(*prefs_, SaveSegmentationResultToPref(_, _))
+ .Times(1)
+ .WillOnce(SaveArg<1>(&selected_segment));
+
+ segment_selector_->OnModelExecutionCompleted(segment_id);
+ ASSERT_TRUE(selected_segment.has_value());
+ ASSERT_EQ(segment_id2, selected_segment->segment_id);
+}
+
+TEST_F(SegmentSelectorTest, NewSegmentResultOverridesThePreviousBest) {
+ OptimizationTarget segment_id1 =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ float mapping1[][2] = {{0.2, 1}, {0.5, 3}, {0.7, 4}};
+ segment_database_->AddDiscreteMapping(segment_id1, mapping1, 3,
+ config_.segmentation_key);
+
+ base::Time result_timestamp = base::Time::Now();
+ segment_database_->AddPredictionResult(segment_id1, 0.6, result_timestamp);
+
+ absl::optional<SelectedSegment> selected_segment;
+ EXPECT_CALL(*prefs_, SaveSegmentationResultToPref(_, _))
+ .Times(1)
+ .WillOnce(SaveArg<1>(&selected_segment));
+
+ segment_selector_->OnModelExecutionCompleted(segment_id1);
+ ASSERT_TRUE(selected_segment.has_value());
+ ASSERT_EQ(segment_id1, selected_segment->segment_id);
+
+ // Another model completes execution. The selection should update.
+ OptimizationTarget segment_id2 =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE;
+ float mapping2[][2] = {{0.3, 1}, {0.4, 4}};
+ segment_database_->AddDiscreteMapping(segment_id2, mapping2, 2,
+ config_.segmentation_key);
+
+ segment_database_->AddPredictionResult(segment_id2, 0.5, result_timestamp);
+ EXPECT_CALL(*prefs_, SaveSegmentationResultToPref(_, _))
+ .Times(1)
+ .WillOnce(SaveArg<1>(&selected_segment));
+
+ segment_selector_->OnModelExecutionCompleted(segment_id2);
+ ASSERT_TRUE(selected_segment.has_value());
+ ASSERT_EQ(segment_id2, selected_segment->segment_id);
+}
+
+TEST_F(SegmentSelectorTest,
+ GetSelectedSegmentReturnsResultFromPreviousSession) {
+ // Set up a selected segment in prefs.
+ OptimizationTarget segment_id0 =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE;
+ SelectedSegment from_history(segment_id0);
+ EXPECT_CALL(*prefs_, ReadSegmentationResultFromPref(_))
+ .WillRepeatedly(Return(from_history));
+
+ // Construct a segment selector. It should read result from last session.
+ segment_selector_ = std::make_unique<SegmentSelectorImpl>(
+ segment_database_.get(), prefs_.get(), &config_);
+
+ base::RunLoop loop;
+ segment_selector_->Initialize(loop.QuitClosure());
+ loop.Run();
+
+ SegmentSelectionResult result;
+ result.segment = segment_id0;
+ result.is_ready = true;
+ GetSelectedSegment(result);
+
+ // Add results for a new segment.
+ OptimizationTarget segment_id1 =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ float mapping1[][2] = {{0.2, 1}, {0.5, 3}, {0.7, 4}};
+ segment_database_->AddDiscreteMapping(segment_id1, mapping1, 3,
+ config_.segmentation_key);
+
+ base::Time result_timestamp = base::Time::Now();
+ segment_database_->AddPredictionResult(segment_id1, 0.6, result_timestamp);
+
+ absl::optional<SelectedSegment> selected_segment;
+ EXPECT_CALL(*prefs_, SaveSegmentationResultToPref(_, _))
+ .Times(1)
+ .WillOnce(SaveArg<1>(&selected_segment));
+
+ segment_selector_->OnModelExecutionCompleted(segment_id1);
+ ASSERT_TRUE(selected_segment.has_value());
+ ASSERT_EQ(segment_id1, selected_segment->segment_id);
+
+ // GetSelectedSegment should still return value from previous session.
+ GetSelectedSegment(result);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs.cc b/chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs.cc
new file mode 100644
index 00000000000..0287165de78
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs.cc
@@ -0,0 +1,70 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h"
+
+#include "base/util/values/values_util.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/segmentation_platform/internal/constants.h"
+#include "components/segmentation_platform/public/segmentation_platform_service.h"
+
+namespace segmentation_platform {
+
+SelectedSegment::SelectedSegment(OptimizationTarget segment_id)
+ : segment_id(segment_id), in_use(false) {}
+
+SelectedSegment::~SelectedSegment() = default;
+
+SegmentationResultPrefs::SegmentationResultPrefs(PrefService* pref_service)
+ : prefs_(pref_service) {}
+
+void SegmentationResultPrefs::SaveSegmentationResultToPref(
+ const std::string& result_key,
+ const absl::optional<SelectedSegment>& selected_segment) {
+ DictionaryPrefUpdate update(prefs_, kSegmentationResultPref);
+ base::DictionaryValue* dictionary = update.Get();
+ if (!selected_segment.has_value()) {
+ dictionary->RemoveKey(result_key);
+ return;
+ }
+
+ base::Value segmentation_result(base::Value::Type::DICTIONARY);
+ segmentation_result.SetIntKey("segment_id", selected_segment->segment_id);
+ segmentation_result.SetBoolKey("in_use", selected_segment->in_use);
+ segmentation_result.SetKey(
+ "selection_time", util::TimeToValue(selected_segment->selection_time));
+ dictionary->SetKey(result_key, std::move(segmentation_result));
+}
+
+absl::optional<SelectedSegment>
+SegmentationResultPrefs::ReadSegmentationResultFromPref(
+ const std::string& result_key) {
+ const base::DictionaryValue* dictionary =
+ prefs_->GetDictionary(kSegmentationResultPref);
+ DCHECK(dictionary);
+
+ const base::Value* value = dictionary->FindKey(result_key);
+ if (!value)
+ return absl::nullopt;
+
+ const base::DictionaryValue& segmentation_result =
+ base::Value::AsDictionaryValue(*value);
+
+ absl::optional<int> segment_id = segmentation_result.FindIntKey("segment_id");
+ absl::optional<bool> in_use = segmentation_result.FindBoolKey("in_use");
+ absl::optional<base::Time> selection_time =
+ util::ValueToTime(segmentation_result.FindPath("selection_time"));
+
+ SelectedSegment selected_segment(
+ static_cast<OptimizationTarget>(segment_id.value()));
+ if (in_use.has_value())
+ selected_segment.in_use = in_use.value();
+ if (selection_time.has_value())
+ selected_segment.selection_time = selection_time.value();
+
+ return selected_segment;
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs.h b/chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs.h
new file mode 100644
index 00000000000..c82080ed3ea
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs.h
@@ -0,0 +1,65 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENTATION_RESULT_PREFS_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENTATION_RESULT_PREFS_H_
+
+#include "base/time/time.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+using optimization_guide::proto::OptimizationTarget;
+
+class PrefService;
+
+namespace segmentation_platform {
+
+// Struct containing information about the selected segment. Convenient for
+// reading and writing to prefs.
+struct SelectedSegment {
+ public:
+ explicit SelectedSegment(OptimizationTarget segment_id);
+ ~SelectedSegment();
+
+ // The segment selection result.
+ OptimizationTarget segment_id;
+
+ // The time when the segment was selected.
+ base::Time selection_time;
+
+ // Whether or not the segment selection result is in use.
+ bool in_use;
+};
+
+// Stores the result of segmentation into prefs for faster lookup. The result
+// consists of (1) The selected segment ID. (2) The time when the segment was
+// first selected. Used to enforce segment selection TTL. (3) Whether the
+// selected segment has started to be used by clients.
+class SegmentationResultPrefs {
+ public:
+ explicit SegmentationResultPrefs(PrefService* pref_service);
+ virtual ~SegmentationResultPrefs() = default;
+
+ // Disallow copy/assign.
+ SegmentationResultPrefs(const SegmentationResultPrefs& other) = delete;
+ SegmentationResultPrefs operator=(const SegmentationResultPrefs& other) =
+ delete;
+
+ // Writes the selected segment to prefs. Deletes the previous results if
+ // |selected_segment| is empty.
+ virtual void SaveSegmentationResultToPref(
+ const std::string& result_key,
+ const absl::optional<SelectedSegment>& selected_segment);
+
+ // Reads the selected segment from pref, if any.
+ virtual absl::optional<SelectedSegment> ReadSegmentationResultFromPref(
+ const std::string& result_key);
+
+ private:
+ PrefService* prefs_;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SELECTION_SEGMENTATION_RESULT_PREFS_H_
diff --git a/chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs_unittest.cc b/chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs_unittest.cc
new file mode 100644
index 00000000000..c105671ef5e
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/selection/segmentation_result_prefs_unittest.cc
@@ -0,0 +1,95 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/selection/segmentation_result_prefs.h"
+
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/segmentation_platform/internal/constants.h"
+#include "components/segmentation_platform/public/segmentation_platform_service.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace segmentation_platform {
+
+class SegmentationResultPrefsTest : public testing::Test {
+ public:
+ SegmentationResultPrefsTest() = default;
+ ~SegmentationResultPrefsTest() override = default;
+
+ void SetUp() override {
+ result_prefs_ = std::make_unique<SegmentationResultPrefs>(&pref_service_);
+ pref_service_.registry()->RegisterDictionaryPref(kSegmentationResultPref);
+ }
+
+ protected:
+ base::test::TaskEnvironment task_environment_;
+ TestingPrefServiceSimple pref_service_;
+ std::unique_ptr<SegmentationResultPrefs> result_prefs_;
+};
+
+TEST_F(SegmentationResultPrefsTest, WriteResultAndRead) {
+ std::string result_key = "some_key";
+ // Start test with no result.
+ absl::optional<SelectedSegment> current_result =
+ result_prefs_->ReadSegmentationResultFromPref(result_key);
+ EXPECT_FALSE(current_result.has_value());
+
+ // Save a result. Verify by reading the result back.
+ OptimizationTarget segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB;
+ SelectedSegment selected_segment(segment_id);
+ result_prefs_->SaveSegmentationResultToPref(result_key, selected_segment);
+ current_result = result_prefs_->ReadSegmentationResultFromPref(result_key);
+ EXPECT_TRUE(current_result.has_value());
+ EXPECT_EQ(segment_id, current_result->segment_id);
+ EXPECT_FALSE(current_result->in_use);
+ EXPECT_EQ(base::Time(), current_result->selection_time);
+
+ // Overwrite the result with a new segment.
+ selected_segment.segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE;
+ selected_segment.in_use = true;
+ base::Time now = base::Time::Now();
+ selected_segment.selection_time = now;
+ result_prefs_->SaveSegmentationResultToPref(result_key, selected_segment);
+ current_result = result_prefs_->ReadSegmentationResultFromPref(result_key);
+ EXPECT_TRUE(current_result.has_value());
+ EXPECT_EQ(selected_segment.segment_id, current_result->segment_id);
+ EXPECT_TRUE(current_result->in_use);
+ EXPECT_EQ(now, current_result->selection_time);
+
+ // Write another result with a different key. This shouldn't overwrite the
+ // first key.
+ std::string result_key2 = "some_key2";
+ selected_segment.segment_id =
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE;
+ result_prefs_->SaveSegmentationResultToPref(result_key2, selected_segment);
+ current_result = result_prefs_->ReadSegmentationResultFromPref(result_key2);
+ EXPECT_TRUE(current_result.has_value());
+ EXPECT_EQ(selected_segment.segment_id, current_result->segment_id);
+
+ current_result = result_prefs_->ReadSegmentationResultFromPref(result_key);
+ EXPECT_TRUE(current_result.has_value());
+ EXPECT_EQ(OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE,
+ current_result->segment_id);
+
+ // Save empty result. It should delete the current result.
+ result_prefs_->SaveSegmentationResultToPref(result_key, absl::nullopt);
+ current_result = result_prefs_->ReadSegmentationResultFromPref(result_key);
+ EXPECT_FALSE(current_result.has_value());
+}
+
+TEST_F(SegmentationResultPrefsTest, CorruptedValue) {
+ std::string result_key = "some_key";
+ SelectedSegment selected_segment(static_cast<OptimizationTarget>(100));
+ result_prefs_->SaveSegmentationResultToPref(result_key, selected_segment);
+ absl::optional<SelectedSegment> current_result =
+ result_prefs_->ReadSegmentationResultFromPref(result_key);
+ EXPECT_TRUE(current_result.has_value());
+ EXPECT_EQ(100, current_result->segment_id);
+}
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/signals/histogram_signal_handler.cc b/chromium/components/segmentation_platform/internal/signals/histogram_signal_handler.cc
new file mode 100644
index 00000000000..f5d570f28ba
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/signals/histogram_signal_handler.cc
@@ -0,0 +1,50 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/signals/histogram_signal_handler.h"
+
+#include "base/metrics/metrics_hashes.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+
+namespace segmentation_platform {
+
+HistogramSignalHandler::HistogramSignalHandler(SignalDatabase* signal_database)
+ : db_(signal_database), metrics_enabled_(false) {}
+
+HistogramSignalHandler::~HistogramSignalHandler() = default;
+
+void HistogramSignalHandler::SetRelevantHistograms(
+ const std::set<std::pair<std::string, proto::SignalType>>& histograms) {
+ histogram_observers_.clear();
+ for (const auto& pair : histograms) {
+ const auto& histogram_name = pair.first;
+ proto::SignalType signal_type = pair.second;
+ auto histogram_observer = std::make_unique<
+ base::StatisticsRecorder::ScopedHistogramSampleObserver>(
+ histogram_name,
+ base::BindRepeating(&HistogramSignalHandler::OnHistogramSample,
+ weak_ptr_factory_.GetWeakPtr(), signal_type));
+ histogram_observers_[histogram_name] = std::move(histogram_observer);
+ }
+}
+
+void HistogramSignalHandler::EnableMetrics(bool enable_metrics) {
+ if (metrics_enabled_ == enable_metrics)
+ return;
+
+ metrics_enabled_ = enable_metrics;
+}
+
+void HistogramSignalHandler::OnHistogramSample(
+ proto::SignalType signal_type,
+ const char* histogram_name,
+ uint64_t name_hash,
+ base::HistogramBase::Sample sample) {
+ if (!metrics_enabled_)
+ return;
+
+ db_->WriteSample(signal_type, name_hash, sample, base::DoNothing());
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/signals/histogram_signal_handler.h b/chromium/components/segmentation_platform/internal/signals/histogram_signal_handler.h
new file mode 100644
index 00000000000..aaf65bd168a
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/signals/histogram_signal_handler.h
@@ -0,0 +1,67 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_HISTOGRAM_SIGNAL_HANDLER_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_HISTOGRAM_SIGNAL_HANDLER_H_
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+
+#include "base/memory/weak_ptr.h"
+#include "base/metrics/histogram_base.h"
+#include "base/metrics/statistics_recorder.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+
+namespace segmentation_platform {
+
+class SignalDatabase;
+
+// Responsible for listening to histogram sample collection events and
+// persisting them to the internal database for future processing.
+class HistogramSignalHandler {
+ public:
+ explicit HistogramSignalHandler(SignalDatabase* signal_database);
+ virtual ~HistogramSignalHandler();
+
+ // Disallow copy/assign.
+ HistogramSignalHandler(const HistogramSignalHandler&) = delete;
+ HistogramSignalHandler& operator=(const HistogramSignalHandler&) = delete;
+
+ // Called to notify about a set of histograms which the segmentation models
+ // care about.
+ virtual void SetRelevantHistograms(
+ const std::set<std::pair<std::string, proto::SignalType>>& histograms);
+
+ // Called to enable or disable metrics collection for segmentation platform.
+ virtual void EnableMetrics(bool enable_metrics);
+
+ private:
+ void OnHistogramSample(proto::SignalType signal_type,
+ const char* histogram_name,
+ uint64_t name_hash,
+ base::HistogramBase::Sample sample);
+
+ // The database storing relevant histogram samples.
+ SignalDatabase* db_;
+
+ // Whether or not the segmentation platform should record metrics events.
+ bool metrics_enabled_;
+
+ // Tracks the histogram names we are currently listening to along with their
+ // corresponding observers.
+ std::map<
+ std::string,
+ std::unique_ptr<base::StatisticsRecorder::ScopedHistogramSampleObserver>>
+ histogram_observers_;
+
+ base::WeakPtrFactory<HistogramSignalHandler> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_HISTOGRAM_SIGNAL_HANDLER_H_
diff --git a/chromium/components/segmentation_platform/internal/signals/histogram_signal_handler_unittest.cc b/chromium/components/segmentation_platform/internal/signals/histogram_signal_handler_unittest.cc
new file mode 100644
index 00000000000..28a06f65b23
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/signals/histogram_signal_handler_unittest.cc
@@ -0,0 +1,107 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/signals/histogram_signal_handler.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/metrics_hashes.h"
+#include "base/test/task_environment.h"
+#include "components/segmentation_platform/internal/database/mock_signal_database.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::Eq;
+
+namespace segmentation_platform {
+
+namespace {
+
+constexpr char kExpectedHistogram[] = "some_histogram";
+const uint64_t kExpectedHash = base::HashMetricName(kExpectedHistogram);
+
+} // namespace
+
+class HistogramSignalHandlerTest : public testing::Test {
+ public:
+ HistogramSignalHandlerTest() = default;
+ ~HistogramSignalHandlerTest() override = default;
+
+ void SetUp() override {
+ signal_database_ = std::make_unique<MockSignalDatabase>();
+ histogram_signal_handler_ =
+ std::make_unique<HistogramSignalHandler>(signal_database_.get());
+ }
+
+ void SetupHistograms() {
+ std::set<std::pair<std::string, proto::SignalType>> histograms;
+ histograms.insert(
+ std::make_pair(kExpectedHistogram, proto::SignalType::HISTOGRAM_ENUM));
+ histogram_signal_handler_->SetRelevantHistograms(histograms);
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<MockSignalDatabase> signal_database_;
+ std::unique_ptr<HistogramSignalHandler> histogram_signal_handler_;
+};
+
+TEST_F(HistogramSignalHandlerTest, HistogramsAreRecorded) {
+ // Initialize and register the list of histograms we are listening to.
+ histogram_signal_handler_->EnableMetrics(true);
+ SetupHistograms();
+
+ // Record a registered histogram sample. It should be recorded.
+ EXPECT_CALL(*signal_database_, WriteSample(proto::SignalType::HISTOGRAM_ENUM,
+ kExpectedHash, Eq(1), _));
+
+ UMA_HISTOGRAM_BOOLEAN(kExpectedHistogram, true);
+ task_environment_.RunUntilIdle();
+
+ // Record an unrelated histogram sample. It should be ignored.
+ std::string kUnrelatedHistogram = "unrelated_histogram";
+ EXPECT_CALL(*signal_database_,
+ WriteSample(_, base::HashMetricName(kUnrelatedHistogram), _, _))
+ .Times(0);
+ UMA_HISTOGRAM_BOOLEAN(kUnrelatedHistogram, true);
+ task_environment_.RunUntilIdle();
+}
+
+TEST_F(HistogramSignalHandlerTest, DisableMetrics) {
+ SetupHistograms();
+
+ // Metrics is disabled on startup.
+ EXPECT_CALL(*signal_database_, WriteSample(proto::SignalType::HISTOGRAM_ENUM,
+ kExpectedHash, Eq(1), _))
+ .Times(0);
+
+ UMA_HISTOGRAM_BOOLEAN(kExpectedHistogram, true);
+ task_environment_.RunUntilIdle();
+
+ // Enable metrics.
+ histogram_signal_handler_->EnableMetrics(true);
+ EXPECT_CALL(*signal_database_, WriteSample(proto::SignalType::HISTOGRAM_ENUM,
+ kExpectedHash, Eq(1), _))
+ .Times(1);
+ UMA_HISTOGRAM_BOOLEAN(kExpectedHistogram, true);
+ task_environment_.RunUntilIdle();
+
+ // Disable metrics again.
+ histogram_signal_handler_->EnableMetrics(false);
+ EXPECT_CALL(*signal_database_, WriteSample(proto::SignalType::HISTOGRAM_ENUM,
+ kExpectedHash, Eq(1), _))
+ .Times(0);
+ UMA_HISTOGRAM_BOOLEAN(kExpectedHistogram, true);
+ task_environment_.RunUntilIdle();
+
+ // Enable metrics again.
+ histogram_signal_handler_->EnableMetrics(true);
+ EXPECT_CALL(*signal_database_, WriteSample(proto::SignalType::HISTOGRAM_ENUM,
+ kExpectedHash, Eq(1), _))
+ .Times(1);
+ UMA_HISTOGRAM_BOOLEAN(kExpectedHistogram, true);
+ task_environment_.RunUntilIdle();
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/signals/signal_filter_processor.cc b/chromium/components/segmentation_platform/internal/signals/signal_filter_processor.cc
new file mode 100644
index 00000000000..591f866a647
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/signals/signal_filter_processor.cc
@@ -0,0 +1,72 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/signals/signal_filter_processor.h"
+
+#include <set>
+
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/proto/model_prediction.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "components/segmentation_platform/internal/signals/histogram_signal_handler.h"
+#include "components/segmentation_platform/internal/signals/user_action_signal_handler.h"
+#include "components/segmentation_platform/internal/stats.h"
+
+namespace segmentation_platform {
+
+SignalFilterProcessor::SignalFilterProcessor(
+ SegmentInfoDatabase* segment_database,
+ UserActionSignalHandler* user_action_signal_handler,
+ HistogramSignalHandler* histogram_signal_handler)
+ : segment_database_(segment_database),
+ user_action_signal_handler_(user_action_signal_handler),
+ histogram_signal_handler_(histogram_signal_handler) {}
+
+SignalFilterProcessor::~SignalFilterProcessor() = default;
+
+void SignalFilterProcessor::OnSignalListUpdated() {
+ segment_database_->GetAllSegmentInfo(base::BindOnce(
+ &SignalFilterProcessor::FilterSignals, weak_ptr_factory_.GetWeakPtr()));
+}
+
+void SignalFilterProcessor::FilterSignals(
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ segment_infos) {
+ std::set<uint64_t> user_actions;
+ std::set<std::pair<std::string, proto::SignalType>> histograms;
+ for (const auto& pair : segment_infos) {
+ const proto::SegmentInfo& segment_info = pair.second;
+ const auto& metadata = segment_info.model_metadata();
+ for (int i = 0; i < metadata.features_size(); i++) {
+ const auto& feature = metadata.features(i);
+ if (feature.type() == proto::SignalType::USER_ACTION &&
+ feature.name_hash() != 0) {
+ user_actions.insert(feature.name_hash());
+ continue;
+ }
+
+ if ((feature.type() == proto::SignalType::HISTOGRAM_VALUE ||
+ feature.type() == proto::SignalType::HISTOGRAM_ENUM) &&
+ !feature.name().empty()) {
+ histograms.insert(std::make_pair(feature.name(), feature.type()));
+ continue;
+ }
+
+ // TODO(shaktisahu): We can filter out enum values as an optimization
+ // before storing in DB.
+ }
+ }
+
+ stats::RecordSignalsListeningCount(user_actions, histograms);
+
+ user_action_signal_handler_->SetRelevantUserActions(std::move(user_actions));
+ histogram_signal_handler_->SetRelevantHistograms(histograms);
+}
+
+void SignalFilterProcessor::EnableMetrics(bool enable_metrics) {
+ user_action_signal_handler_->EnableMetrics(enable_metrics);
+ histogram_signal_handler_->EnableMetrics(enable_metrics);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/signals/signal_filter_processor.h b/chromium/components/segmentation_platform/internal/signals/signal_filter_processor.h
new file mode 100644
index 00000000000..c2c8737b90a
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/signals/signal_filter_processor.h
@@ -0,0 +1,62 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_SIGNAL_FILTER_PROCESSOR_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_SIGNAL_FILTER_PROCESSOR_H_
+
+#include "base/memory/weak_ptr.h"
+#include "components/optimization_guide/proto/models.pb.h"
+
+using optimization_guide::proto::OptimizationTarget;
+
+namespace segmentation_platform {
+
+namespace proto {
+class SegmentInfo;
+} // namespace proto
+
+class HistogramSignalHandler;
+class SegmentInfoDatabase;
+class UserActionSignalHandler;
+
+// Responsible for listening to the metadata updates for the models and
+// registers various signal handlers for the relevant UMA signals specified in
+// the metadata.
+class SignalFilterProcessor {
+ public:
+ SignalFilterProcessor(SegmentInfoDatabase* segment_database,
+ UserActionSignalHandler* user_action_signal_handler,
+ HistogramSignalHandler* histogram_signal_handler);
+ ~SignalFilterProcessor();
+
+ // Disallow copy/assign.
+ SignalFilterProcessor(const SignalFilterProcessor&) = delete;
+ SignalFilterProcessor& operator=(const SignalFilterProcessor&) = delete;
+
+ // Called whenever the metadata about the models are updated. Registers
+ // handlers for the relevant signals specified in the metadata. If handlers
+ // are already registered, it will reset and register again with the new set
+ // of signals.
+ void OnSignalListUpdated();
+
+ // Called to enable or disable metrics collection for segmentation platform.
+ // This is often invoked early even before the signal list is obtained. Must
+ // be explicitly called on startup.
+ void EnableMetrics(bool enable_metrics);
+
+ private:
+ void FilterSignals(
+ std::vector<std::pair<OptimizationTarget, proto::SegmentInfo>>
+ segment_infos);
+
+ SegmentInfoDatabase* segment_database_;
+ UserActionSignalHandler* user_action_signal_handler_;
+ HistogramSignalHandler* histogram_signal_handler_;
+
+ base::WeakPtrFactory<SignalFilterProcessor> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_SIGNAL_FILTER_PROCESSOR_H_
diff --git a/chromium/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc b/chromium/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc
new file mode 100644
index 00000000000..cf6a8322f95
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/signals/signal_filter_processor_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/signals/signal_filter_processor.h"
+
+#include "base/metrics/metrics_hashes.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "components/segmentation_platform/internal/database/segment_info_database.h"
+#include "components/segmentation_platform/internal/database/test_segment_info_database.h"
+#include "components/segmentation_platform/internal/proto/aggregation.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "components/segmentation_platform/internal/signals/histogram_signal_handler.h"
+#include "components/segmentation_platform/internal/signals/user_action_signal_handler.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::Contains;
+using testing::SaveArg;
+
+namespace segmentation_platform {
+
+class MockUserActionSignalHandler : public UserActionSignalHandler {
+ public:
+ MockUserActionSignalHandler() : UserActionSignalHandler(nullptr) {}
+ MOCK_METHOD(void, SetRelevantUserActions, (std::set<uint64_t>));
+ MOCK_METHOD(void, EnableMetrics, (bool));
+};
+
+class MockHistogramSignalHandler : public HistogramSignalHandler {
+ public:
+ MockHistogramSignalHandler() : HistogramSignalHandler(nullptr) {}
+ using HistogramAndSignalTypeSet =
+ const std::set<std::pair<std::string, proto::SignalType>>&;
+ MOCK_METHOD(void, SetRelevantHistograms, (HistogramAndSignalTypeSet));
+ MOCK_METHOD(void, EnableMetrics, (bool));
+};
+
+class SignalFilterProcessorTest : public testing::Test {
+ public:
+ SignalFilterProcessorTest() = default;
+ ~SignalFilterProcessorTest() override = default;
+
+ void SetUp() override {
+ base::SetRecordActionTaskRunner(
+ task_environment_.GetMainThreadTaskRunner());
+ segment_database_ = std::make_unique<test::TestSegmentInfoDatabase>();
+ user_action_signal_handler_ =
+ std::make_unique<MockUserActionSignalHandler>();
+ histogram_signal_handler_ = std::make_unique<MockHistogramSignalHandler>();
+ signal_filter_processor_ = std::make_unique<SignalFilterProcessor>(
+ segment_database_.get(), user_action_signal_handler_.get(),
+ histogram_signal_handler_.get());
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<test::TestSegmentInfoDatabase> segment_database_;
+ std::unique_ptr<MockUserActionSignalHandler> user_action_signal_handler_;
+ std::unique_ptr<MockHistogramSignalHandler> histogram_signal_handler_;
+ std::unique_ptr<SignalFilterProcessor> signal_filter_processor_;
+};
+
+TEST_F(SignalFilterProcessorTest, UserActionRegistrationFlow) {
+ std::string kUserActionName1 = "some_action_1";
+ segment_database_->AddUserActionFeature(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ kUserActionName1, 0, 0, proto::Aggregation::COUNT);
+ std::string kUserActionName2 = "some_action_2";
+ segment_database_->AddUserActionFeature(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE,
+ kUserActionName2, 0, 0, proto::Aggregation::COUNT);
+
+ std::set<uint64_t> actions;
+ EXPECT_CALL(*user_action_signal_handler_, SetRelevantUserActions(_))
+ .Times(1)
+ .WillOnce(SaveArg<0>(&actions));
+
+ signal_filter_processor_->OnSignalListUpdated();
+ ASSERT_THAT(actions, Contains(base::HashMetricName(kUserActionName1)));
+ ASSERT_THAT(actions, Contains(base::HashMetricName(kUserActionName2)));
+}
+
+TEST_F(SignalFilterProcessorTest, HistogramRegistrationFlow) {
+ std::string kHistogramName1 = "some_histogram_1";
+ segment_database_->AddHistogramValueFeature(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ kHistogramName1, 1, 1, proto::Aggregation::COUNT);
+ std::string kHistogramName2 = "some_histogram_2";
+ segment_database_->AddHistogramValueFeature(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE,
+ kHistogramName2, 1, 1, proto::Aggregation::COUNT);
+ std::string kHistogramName3 = "some_histogram_3";
+ segment_database_->AddHistogramEnumFeature(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE,
+ kHistogramName3, 1, 1, proto::Aggregation::COUNT, {3, 4});
+
+ std::set<std::pair<std::string, proto::SignalType>> histograms;
+ EXPECT_CALL(*histogram_signal_handler_, SetRelevantHistograms(_))
+ .Times(1)
+ .WillOnce(SaveArg<0>(&histograms));
+
+ signal_filter_processor_->OnSignalListUpdated();
+ ASSERT_THAT(histograms,
+ Contains(std::make_pair(kHistogramName1,
+ proto::SignalType::HISTOGRAM_VALUE)));
+ ASSERT_THAT(histograms,
+ Contains(std::make_pair(kHistogramName2,
+ proto::SignalType::HISTOGRAM_VALUE)));
+ ASSERT_THAT(histograms,
+ Contains(std::make_pair(kHistogramName3,
+ proto::SignalType::HISTOGRAM_ENUM)));
+}
+
+TEST_F(SignalFilterProcessorTest, EnableMetrics) {
+ EXPECT_CALL(*user_action_signal_handler_, EnableMetrics(true));
+ EXPECT_CALL(*histogram_signal_handler_, EnableMetrics(true));
+ signal_filter_processor_->EnableMetrics(true);
+ EXPECT_CALL(*user_action_signal_handler_, EnableMetrics(false));
+ EXPECT_CALL(*histogram_signal_handler_, EnableMetrics(false));
+ signal_filter_processor_->EnableMetrics(false);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/signals/user_action_signal_handler.cc b/chromium/components/segmentation_platform/internal/signals/user_action_signal_handler.cc
new file mode 100644
index 00000000000..af8195fab44
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/signals/user_action_signal_handler.cc
@@ -0,0 +1,57 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/signals/user_action_signal_handler.h"
+
+#include "base/callback_helpers.h"
+#include "base/metrics/metrics_hashes.h"
+#include "components/segmentation_platform/internal/database/signal_database.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+
+namespace segmentation_platform {
+
+UserActionSignalHandler::UserActionSignalHandler(
+ SignalDatabase* signal_database)
+ : db_(signal_database), metrics_enabled_(false) {
+ action_callback_ = base::BindRepeating(&UserActionSignalHandler::OnUserAction,
+ weak_ptr_factory_.GetWeakPtr());
+}
+
+UserActionSignalHandler::~UserActionSignalHandler() {
+ base::RemoveActionCallback(action_callback_);
+}
+
+void UserActionSignalHandler::EnableMetrics(bool enable_metrics) {
+ if (metrics_enabled_ == enable_metrics)
+ return;
+
+ metrics_enabled_ = enable_metrics;
+
+ // As an added optimization, we unregister the callback when metrics is
+ // disabled.
+ if (metrics_enabled_) {
+ base::AddActionCallback(action_callback_);
+ } else {
+ base::RemoveActionCallback(action_callback_);
+ }
+}
+
+void UserActionSignalHandler::SetRelevantUserActions(
+ std::set<uint64_t> user_actions) {
+ user_actions_ = std::move(user_actions);
+}
+
+void UserActionSignalHandler::OnUserAction(const std::string& user_action,
+ base::TimeTicks action_time) {
+ DCHECK(metrics_enabled_);
+ uint64_t user_action_hash = base::HashMetricName(user_action);
+ auto iter = user_actions_.find(user_action_hash);
+ if (iter == user_actions_.end())
+ return;
+
+ db_->WriteSample(proto::SignalType::USER_ACTION, user_action_hash,
+ absl::nullopt, base::DoNothing());
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/signals/user_action_signal_handler.h b/chromium/components/segmentation_platform/internal/signals/user_action_signal_handler.h
new file mode 100644
index 00000000000..7fa5eb0c453
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/signals/user_action_signal_handler.h
@@ -0,0 +1,60 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_USER_ACTION_SIGNAL_HANDLER_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_USER_ACTION_SIGNAL_HANDLER_H_
+
+#include <set>
+
+#include "base/memory/weak_ptr.h"
+#include "base/metrics/user_metrics.h"
+#include "base/time/time.h"
+
+namespace segmentation_platform {
+
+class SignalDatabase;
+
+// Responsible for listening to user action events and persisting it to the
+// internal database for future processing.
+class UserActionSignalHandler {
+ public:
+ explicit UserActionSignalHandler(SignalDatabase* signal_database);
+ virtual ~UserActionSignalHandler();
+
+ // Disallow copy/assign.
+ UserActionSignalHandler(const UserActionSignalHandler&) = delete;
+ UserActionSignalHandler& operator=(const UserActionSignalHandler&) = delete;
+
+ // Called to notify about a set of user actions which the segmentation models
+ // care about.
+ virtual void SetRelevantUserActions(std::set<uint64_t> user_actions);
+
+ // Called to enable or disable metrics collection for segmentation platform.
+ // This can be called early even before relevant user actions are known.
+ virtual void EnableMetrics(bool enable_metrics);
+
+ private:
+ void OnUserAction(const std::string& user_action,
+ base::TimeTicks action_time);
+
+ // The database storing relevant user actions.
+ SignalDatabase* db_;
+
+ // The callback registered with user metrics module that gets invoked for
+ // every user action.
+ base::ActionCallback action_callback_;
+
+ // The set of user actions relevant to the segmentation platform. Everything
+ // else will be filtered out.
+ std::set<uint64_t> user_actions_;
+
+ // Whether or not the segmentation platform should record metrics events.
+ bool metrics_enabled_;
+
+ base::WeakPtrFactory<UserActionSignalHandler> weak_ptr_factory_{this};
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_SIGNALS_USER_ACTION_SIGNAL_HANDLER_H_
diff --git a/chromium/components/segmentation_platform/internal/signals/user_action_signal_handler_unittest.cc b/chromium/components/segmentation_platform/internal/signals/user_action_signal_handler_unittest.cc
new file mode 100644
index 00000000000..e2decdb7698
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/signals/user_action_signal_handler_unittest.cc
@@ -0,0 +1,110 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/signals/user_action_signal_handler.h"
+
+#include "base/metrics/metrics_hashes.h"
+#include "base/test/task_environment.h"
+#include "components/segmentation_platform/internal/database/mock_signal_database.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::Eq;
+
+namespace segmentation_platform {
+
+namespace {
+const char kExpectedUserAction[] = "some_event";
+const uint64_t kExpectedHash = base::HashMetricName(kExpectedUserAction);
+
+} // namespace
+
+class UserActionSignalHandlerTest : public testing::Test {
+ public:
+ UserActionSignalHandlerTest() = default;
+ ~UserActionSignalHandlerTest() override = default;
+
+ void SetUp() override {
+ base::SetRecordActionTaskRunner(
+ task_environment_.GetMainThreadTaskRunner());
+ signal_database_ = std::make_unique<MockSignalDatabase>();
+ user_action_signal_handler_ =
+ std::make_unique<UserActionSignalHandler>(signal_database_.get());
+ }
+
+ void SetupUserActions() {
+ std::set<uint64_t> actions;
+ actions.insert(kExpectedHash);
+ user_action_signal_handler_->SetRelevantUserActions(actions);
+ }
+
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<MockSignalDatabase> signal_database_;
+ std::unique_ptr<UserActionSignalHandler> user_action_signal_handler_;
+};
+
+TEST_F(UserActionSignalHandlerTest, UserActionsAreRecorded) {
+ // Initialize and register the list of user actions we are listening to.
+ user_action_signal_handler_->EnableMetrics(true);
+ SetupUserActions();
+
+ // Fire a registered user action. It should be recorded.
+ EXPECT_CALL(*signal_database_,
+ WriteSample(proto::SignalType::USER_ACTION, kExpectedHash,
+ Eq(absl::nullopt), _));
+ base::RecordComputedActionAt(kExpectedUserAction, base::TimeTicks::Now());
+
+ // Fire an unrelated user action. It should be ignored.
+ std::string kUnrelatedUserAction = "unrelated_event";
+ EXPECT_CALL(*signal_database_,
+ WriteSample(proto::SignalType::USER_ACTION,
+ base::HashMetricName(kUnrelatedUserAction),
+ Eq(absl::nullopt), _))
+ .Times(0);
+ base::RecordComputedActionAt(kUnrelatedUserAction, base::TimeTicks::Now());
+}
+
+TEST_F(UserActionSignalHandlerTest, DisableMetrics) {
+ base::TimeTicks time = base::TimeTicks::Now();
+ SetupUserActions();
+
+ // Metrics is disabled on startup.
+ EXPECT_CALL(*signal_database_,
+ WriteSample(proto::SignalType::USER_ACTION,
+ base::HashMetricName(kExpectedUserAction),
+ Eq(absl::nullopt), _))
+ .Times(0);
+ base::RecordComputedActionAt(kExpectedUserAction, time);
+
+ // Enable metrics.
+ user_action_signal_handler_->EnableMetrics(true);
+ EXPECT_CALL(*signal_database_,
+ WriteSample(proto::SignalType::USER_ACTION,
+ base::HashMetricName(kExpectedUserAction),
+ Eq(absl::nullopt), _))
+ .Times(1);
+ base::RecordComputedActionAt(kExpectedUserAction, time);
+
+ // Disable metrics again.
+ user_action_signal_handler_->EnableMetrics(false);
+ EXPECT_CALL(*signal_database_,
+ WriteSample(proto::SignalType::USER_ACTION,
+ base::HashMetricName(kExpectedUserAction),
+ Eq(absl::nullopt), _))
+ .Times(0);
+ base::RecordComputedActionAt(kExpectedUserAction, time);
+
+ // Enable metrics again.
+ user_action_signal_handler_->EnableMetrics(true);
+ EXPECT_CALL(*signal_database_,
+ WriteSample(proto::SignalType::USER_ACTION,
+ base::HashMetricName(kExpectedUserAction),
+ Eq(absl::nullopt), _))
+ .Times(1);
+ base::RecordComputedActionAt(kExpectedUserAction, time);
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/stats.cc b/chromium/components/segmentation_platform/internal/stats.cc
new file mode 100644
index 00000000000..0f4ab711270
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/stats.cc
@@ -0,0 +1,402 @@
+// Copyright 2021 The Chromium Authors. 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/segmentation_platform/internal/stats.h"
+
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/notreached.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+
+namespace segmentation_platform {
+namespace stats {
+namespace {
+// Should map to SegmentationModel variant in
+// //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
+std::string OptimizationTargetToHistogramVariant(
+ OptimizationTarget segment_id) {
+ switch (segment_id) {
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
+ return "NewTab";
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
+ return "Share";
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
+ return "Voice";
+ default:
+ NOTREACHED();
+ return "Unknown";
+ }
+}
+
+// Keep in sync with AdaptiveToolbarButtonVariant in enums.xml.
+enum class AdaptiveToolbarButtonVariant {
+ kUnknown = 0,
+ kNone = 1,
+ kNewTab = 2,
+ kShare = 3,
+ kVoice = 4,
+ kMaxValue = kVoice,
+};
+
+// This is the segmentation subset of
+// optimization_guide::proto::OptimizationTarget.
+// Keep in sync with SegmentationPlatformSegmenationModel in
+// //tools/metrics/histograms/enums.xml.
+// See also SegmentationModel variant in
+// //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
+enum class SegmentationModel {
+ kUnknown = 0,
+ kNewTab = 4,
+ kShare = 5,
+ kVoice = 6,
+ kMaxValue = kVoice,
+};
+
+AdaptiveToolbarButtonVariant OptimizationTargetToAdaptiveToolbarButtonVariant(
+ OptimizationTarget segment_id) {
+ switch (segment_id) {
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
+ return AdaptiveToolbarButtonVariant::kNewTab;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
+ return AdaptiveToolbarButtonVariant::kShare;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
+ return AdaptiveToolbarButtonVariant::kVoice;
+ case OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN:
+ return AdaptiveToolbarButtonVariant::kNone;
+ default:
+ return AdaptiveToolbarButtonVariant::kUnknown;
+ }
+}
+
+AdaptiveToolbarSegmentSwitch GetSegmentSwitch(
+ OptimizationTarget new_selection,
+ OptimizationTarget previous_selection) {
+ switch (previous_selection) {
+ case OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN:
+ switch (new_selection) {
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
+ return AdaptiveToolbarSegmentSwitch::kNoneToNewTab;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
+ return AdaptiveToolbarSegmentSwitch::kNoneToShare;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
+ return AdaptiveToolbarSegmentSwitch::kNoneToVoice;
+ default:
+ NOTREACHED();
+ return AdaptiveToolbarSegmentSwitch::kUnknown;
+ }
+ break;
+
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
+ switch (new_selection) {
+ case OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN:
+ return AdaptiveToolbarSegmentSwitch::kNewTabToNone;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
+ return AdaptiveToolbarSegmentSwitch::kNewTabToShare;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
+ return AdaptiveToolbarSegmentSwitch::kNewTabToVoice;
+ default:
+ NOTREACHED();
+ return AdaptiveToolbarSegmentSwitch::kUnknown;
+ }
+ break;
+
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
+ switch (new_selection) {
+ case OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN:
+ return AdaptiveToolbarSegmentSwitch::kShareToNone;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
+ return AdaptiveToolbarSegmentSwitch::kShareToNewTab;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
+ return AdaptiveToolbarSegmentSwitch::kShareToVoice;
+ default:
+ NOTREACHED();
+ return AdaptiveToolbarSegmentSwitch::kUnknown;
+ }
+ break;
+
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
+ switch (new_selection) {
+ case OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN:
+ return AdaptiveToolbarSegmentSwitch::kVoiceToNone;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
+ return AdaptiveToolbarSegmentSwitch::kVoiceToNewTab;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
+ return AdaptiveToolbarSegmentSwitch::kVoiceToShare;
+ default:
+ NOTREACHED();
+ return AdaptiveToolbarSegmentSwitch::kUnknown;
+ }
+ break;
+
+ default:
+ NOTREACHED();
+ return AdaptiveToolbarSegmentSwitch::kUnknown;
+ }
+}
+
+SegmentationModel OptimizationTargetToSegmentationModel(
+ OptimizationTarget segment_id) {
+ switch (segment_id) {
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
+ return SegmentationModel::kNewTab;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
+ return SegmentationModel::kShare;
+ case OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
+ return SegmentationModel::kVoice;
+ default:
+ return SegmentationModel::kUnknown;
+ }
+}
+
+// Should map to ModelExecutionStatus variant string in
+// //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
+std::string ModelExecutionStatusToHistogramVariant(
+ ModelExecutionStatus status) {
+ switch (status) {
+ case ModelExecutionStatus::kSuccess:
+ return "Success";
+ case ModelExecutionStatus::kExecutionError:
+ return "ExecutionError";
+ case ModelExecutionStatus::kInvalidMetadata:
+ return "InvalidMetadata";
+ default:
+ NOTREACHED();
+ return "Unknown";
+ }
+}
+
+// Should map to SignalType variant string in
+// //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
+std::string SignalTypeToHistogramVariant(proto::SignalType signal_type) {
+ switch (signal_type) {
+ case proto::SignalType::USER_ACTION:
+ return "UserAction";
+ case proto::SignalType::HISTOGRAM_ENUM:
+ return "HistogramEnum";
+ case proto::SignalType::HISTOGRAM_VALUE:
+ return "HistogramValue";
+ default:
+ NOTREACHED();
+ return "Unknown";
+ }
+}
+
+float ZeroValueFraction(const std::vector<float>& tensor) {
+ if (tensor.size() == 0)
+ return 0;
+
+ size_t zero_values = 0;
+ for (float feature : tensor) {
+ if (feature == 0)
+ ++zero_values;
+ }
+ return static_cast<float>(zero_values) / static_cast<float>(tensor.size());
+}
+
+} // namespace
+
+void RecordModelScore(OptimizationTarget segment_id, float score) {
+ base::UmaHistogramPercentage(
+ "SegmentationPlatform.AdaptiveToolbar.ModelScore." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ score * 100);
+}
+
+void RecordSegmentSelectionComputed(
+ OptimizationTarget new_selection,
+ absl::optional<OptimizationTarget> previous_selection) {
+ base::UmaHistogramEnumeration(
+ "SegmentationPlatform.AdaptiveToolbar.SegmentSelection.Computed",
+ OptimizationTargetToAdaptiveToolbarButtonVariant(new_selection));
+
+ OptimizationTarget prev_segment =
+ previous_selection.has_value()
+ ? previous_selection.value()
+ : OptimizationTarget::OPTIMIZATION_TARGET_UNKNOWN;
+
+ if (prev_segment == new_selection)
+ return;
+
+ base::UmaHistogramEnumeration(
+ "SegmentationPlatform.AdaptiveToolbar.SegmentSwitched",
+ GetSegmentSwitch(new_selection, prev_segment));
+}
+
+void RecordMaintenanceCleanupSignalSuccessCount(size_t count) {
+ UMA_HISTOGRAM_COUNTS_1000(
+ "SegmentationPlatform.Maintenance.CleanupSignalSuccessCount", count);
+}
+
+void RecordMaintenanceCompactionResult(proto::SignalType signal_type,
+ bool success) {
+ base::UmaHistogramBoolean(
+ "SegmentationPlatform.Maintenance.CompactionResult." +
+ SignalTypeToHistogramVariant(signal_type),
+ success);
+}
+
+void RecordMaintenanceSignalIdentifierCount(size_t count) {
+ UMA_HISTOGRAM_COUNTS_1000(
+ "SegmentationPlatform.Maintenance.SignalIdentifierCount", count);
+}
+
+void RecordModelDeliveryHasMetadata(OptimizationTarget segment_id,
+ bool has_metadata) {
+ base::UmaHistogramBoolean(
+ "SegmentationPlatform.ModelDelivery.HasMetadata." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ has_metadata);
+}
+
+void RecordModelDeliveryMetadataFeatureCount(OptimizationTarget segment_id,
+ size_t count) {
+ base::UmaHistogramCounts1000(
+ "SegmentationPlatform.ModelDelivery.Metadata.FeatureCount." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ count);
+}
+
+void RecordModelDeliveryMetadataValidation(
+ OptimizationTarget segment_id,
+ bool processed,
+ metadata_utils::ValidationResult validation_result) {
+ // Should map to ValidationPhase variant string in
+ // //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
+ std::string validation_phase = processed ? "Processed" : "Incoming";
+ base::UmaHistogramEnumeration(
+ "SegmentationPlatform.ModelDelivery.Metadata.Validation." +
+ validation_phase + "." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ validation_result);
+}
+
+void RecordModelDeliveryReceived(OptimizationTarget segment_id) {
+ UMA_HISTOGRAM_ENUMERATION("SegmentationPlatform.ModelDelivery.Received",
+ OptimizationTargetToSegmentationModel(segment_id));
+}
+
+void RecordModelDeliverySaveResult(OptimizationTarget segment_id,
+ bool success) {
+ base::UmaHistogramBoolean(
+ "SegmentationPlatform.ModelDelivery.SaveResult." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ success);
+}
+
+void RecordModelDeliverySegmentIdMatches(OptimizationTarget segment_id,
+ bool matches) {
+ base::UmaHistogramBoolean(
+ "SegmentationPlatform.ModelDelivery.SegmentIdMatches." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ matches);
+}
+
+void RecordModelExecutionDurationFeatureProcessing(
+ OptimizationTarget segment_id,
+ base::TimeDelta duration) {
+ base::UmaHistogramTimes(
+ "SegmentationPlatform.ModelExecution.Duration.FeatureProcessing." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ duration);
+}
+
+void RecordModelExecutionDurationModel(OptimizationTarget segment_id,
+ bool success,
+ base::TimeDelta duration) {
+ ModelExecutionStatus status = success ? ModelExecutionStatus::kSuccess
+ : ModelExecutionStatus::kExecutionError;
+ base::UmaHistogramTimes(
+ "SegmentationPlatform.ModelExecution.Duration.Model." +
+ OptimizationTargetToHistogramVariant(segment_id) + "." +
+ ModelExecutionStatusToHistogramVariant(status),
+ duration);
+}
+
+void RecordModelExecutionDurationTotal(OptimizationTarget segment_id,
+ ModelExecutionStatus status,
+ base::TimeDelta duration) {
+ base::UmaHistogramTimes(
+ "SegmentationPlatform.ModelExecution.Duration.Total." +
+ OptimizationTargetToHistogramVariant(segment_id) + "." +
+ ModelExecutionStatusToHistogramVariant(status),
+ duration);
+}
+
+void RecordModelExecutionResult(OptimizationTarget segment_id, float result) {
+ base::UmaHistogramPercentage(
+ "SegmentationPlatform.ModelExecution.Result." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ result * 100);
+}
+
+void RecordModelExecutionSaveResult(OptimizationTarget segment_id,
+ bool success) {
+ base::UmaHistogramBoolean(
+ "SegmentationPlatform.ModelExecution.SaveResult." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ success);
+}
+
+void RecordModelExecutionStatus(OptimizationTarget segment_id,
+ ModelExecutionStatus status) {
+ base::UmaHistogramEnumeration(
+ "SegmentationPlatform.ModelExecution.Status." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ status);
+}
+
+void RecordModelExecutionZeroValuePercent(OptimizationTarget segment_id,
+ const std::vector<float>& tensor) {
+ base::UmaHistogramPercentage(
+ "SegmentationPlatform.ModelExecution.ZeroValuePercent." +
+ OptimizationTargetToHistogramVariant(segment_id),
+ ZeroValueFraction(tensor) * 100);
+}
+
+void RecordSignalDatabaseGetSamplesDatabaseEntryCount(size_t count) {
+ UMA_HISTOGRAM_COUNTS_1000(
+ "SegmentationPlatform.SignalDatabase.GetSamples.DatabaseEntryCount",
+ count);
+}
+
+void RecordSignalDatabaseGetSamplesResult(bool success) {
+ UMA_HISTOGRAM_BOOLEAN("SegmentationPlatform.SignalDatabase.GetSamples.Result",
+ success);
+}
+
+void RecordSignalDatabaseGetSamplesSampleCount(size_t count) {
+ UMA_HISTOGRAM_COUNTS_10000(
+ "SegmentationPlatform.SignalDatabase.GetSamples.SampleCount", count);
+}
+
+void RecordSignalsListeningCount(
+ const std::set<uint64_t>& user_actions,
+ const std::set<std::pair<std::string, proto::SignalType>>& histograms) {
+ uint64_t user_action_count = user_actions.size();
+ uint64_t histogram_enum_count = 0;
+ uint64_t histogram_value_count = 0;
+ for (auto& s : histograms) {
+ if (s.second == proto::SignalType::HISTOGRAM_ENUM)
+ ++histogram_enum_count;
+ if (s.second == proto::SignalType::HISTOGRAM_VALUE)
+ ++histogram_value_count;
+ }
+
+ base::UmaHistogramCounts1000(
+ "SegmentationPlatform.Signals.ListeningCount." +
+ SignalTypeToHistogramVariant(proto::SignalType::USER_ACTION),
+ user_action_count);
+ base::UmaHistogramCounts1000(
+ "SegmentationPlatform.Signals.ListeningCount." +
+ SignalTypeToHistogramVariant(proto::SignalType::HISTOGRAM_ENUM),
+ histogram_enum_count);
+ base::UmaHistogramCounts1000(
+ "SegmentationPlatform.Signals.ListeningCount." +
+ SignalTypeToHistogramVariant(proto::SignalType::HISTOGRAM_VALUE),
+ histogram_value_count);
+}
+
+} // namespace stats
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/internal/stats.h b/chromium/components/segmentation_platform/internal/stats.h
new file mode 100644
index 00000000000..b092a2eda95
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/stats.h
@@ -0,0 +1,139 @@
+// Copyright 2021 The Chromium Authors. 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_SEGMENTATION_PLATFORM_INTERNAL_STATS_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_STATS_H_
+
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/database/metadata_utils.h"
+#include "components/segmentation_platform/internal/execution/model_execution_status.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+using optimization_guide::proto::OptimizationTarget;
+
+namespace segmentation_platform {
+namespace stats {
+
+// Keep in sync with AdaptiveToolbarSegmentSwitch in enums.xml.
+// Visible for testing.
+enum class AdaptiveToolbarSegmentSwitch {
+ kUnknown = 0,
+ kNoneToNewTab = 1,
+ kNoneToShare = 2,
+ kNoneToVoice = 3,
+ kNewTabToNone = 4,
+ kShareToNone = 5,
+ kVoiceToNone = 6,
+ kNewTabToShare = 7,
+ kNewTabToVoice = 8,
+ kShareToNewTab = 9,
+ kShareToVoice = 10,
+ kVoiceToNewTab = 11,
+ kVoiceToShare = 12,
+ kMaxValue = kVoiceToShare,
+};
+
+// Records the score computed for a given segment.
+void RecordModelScore(OptimizationTarget segment_id, float score);
+
+// Records the result of segment selection whenever segment selection is
+// computed.
+void RecordSegmentSelectionComputed(
+ OptimizationTarget new_selection,
+ absl::optional<OptimizationTarget> previous_selection);
+
+// Database Maintenance metrics.
+// Records the number of unique signal identifiers that were successfully
+// cleaned up.
+void RecordMaintenanceCleanupSignalSuccessCount(size_t count);
+// Records the result for each compaction attempt for a particular signal type.
+void RecordMaintenanceCompactionResult(proto::SignalType signal_type,
+ bool success);
+// Records the number of signal identifiers that were found that we should aim
+// to clean up.
+void RecordMaintenanceSignalIdentifierCount(size_t count);
+
+// Model Delivery metrics.
+// Records whether any incoming ML model had metadata attached that we were able
+// to parse.
+void RecordModelDeliveryHasMetadata(OptimizationTarget segment_id,
+ bool has_metadata);
+// Records the number of tensor features an updated ML model has.
+void RecordModelDeliveryMetadataFeatureCount(OptimizationTarget segment_id,
+ size_t count);
+// Records the result of validating the metadata of an incoming ML model.
+// Recorded before and after it has been merged with the already stored
+// metadata.
+void RecordModelDeliveryMetadataValidation(
+ OptimizationTarget segment_id,
+ bool processed,
+ metadata_utils::ValidationResult validation_result);
+// Record what type of model metadata we received.
+void RecordModelDeliveryReceived(OptimizationTarget segment_id);
+// Records the result of attempting to save an updated version of the model
+// metadata.
+void RecordModelDeliverySaveResult(OptimizationTarget segment_id, bool success);
+// Records whether the currently stored segment_id matches the incoming
+// segment_id, as these are expected to match.
+void RecordModelDeliverySegmentIdMatches(OptimizationTarget segment_id,
+ bool matches);
+
+// Model Execution metrics.
+// Records the duration of processing a single ML feature. This only takes into
+// account the time it takes to process (aggregate) a feature result, not
+// fetching it from the database. It also takes into account filtering any
+// enum histograms.
+void RecordModelExecutionDurationFeatureProcessing(
+ OptimizationTarget segment_id,
+ base::TimeDelta duration);
+// Records the duration of executing an ML model. This only takes into account
+// the time it takes to invoke and wait for a result from the underlying ML
+// infrastructure from //components/optimization_guide, and not fetching the
+// relevant data from the database.
+void RecordModelExecutionDurationModel(OptimizationTarget segment_id,
+ bool success,
+ base::TimeDelta duration);
+// Records the duration of fetching data for, processing, and executing an ML
+// model.
+void RecordModelExecutionDurationTotal(OptimizationTarget segment_id,
+ ModelExecutionStatus status,
+ base::TimeDelta duration);
+// Records the result value after successfully executing an ML model.
+void RecordModelExecutionResult(OptimizationTarget segment_id, float result);
+// Records whether the result value of of executing an ML model was successfully
+// saved.
+void RecordModelExecutionSaveResult(OptimizationTarget segment_id,
+ bool success);
+// Records the final execution status for any ML model execution.
+void RecordModelExecutionStatus(OptimizationTarget segment_id,
+ ModelExecutionStatus status);
+// Records the percent of features in a tensor that are equal to 0 when the
+// segmentation model is executed.
+void RecordModelExecutionZeroValuePercent(OptimizationTarget segment_id,
+ const std::vector<float>& tensor);
+
+// Signal Database metrics.
+// Records the number of database entries that were fetched from the database
+// during a call to GetSamples. This is not the same as the sample count since
+// each database entry can contain multiple samples.
+void RecordSignalDatabaseGetSamplesDatabaseEntryCount(size_t count);
+// Records the result of fetching data from the database during a call to
+// GetSamples.
+void RecordSignalDatabaseGetSamplesResult(bool success);
+// Records the number of samples that were returned after reading entries from
+// the database, during a call to GetSamples. This is not the same as the
+// database entry count, since each entry can contain multiple samples.
+void RecordSignalDatabaseGetSamplesSampleCount(size_t count);
+
+// Records the number of unique user action and histogram signals that we are
+// currently tracking.
+void RecordSignalsListeningCount(
+ const std::set<uint64_t>& user_actions,
+ const std::set<std::pair<std::string, proto::SignalType>>& histograms);
+
+} // namespace stats
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_STATS_H_
diff --git a/chromium/components/segmentation_platform/internal/stats_unittest.cc b/chromium/components/segmentation_platform/internal/stats_unittest.cc
new file mode 100644
index 00000000000..e5cf0fff08b
--- /dev/null
+++ b/chromium/components/segmentation_platform/internal/stats_unittest.cc
@@ -0,0 +1,131 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/internal/stats.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "components/optimization_guide/proto/models.pb.h"
+#include "components/segmentation_platform/internal/proto/types.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace segmentation_platform {
+using proto::SignalType;
+namespace stats {
+
+class StatsTest : public testing::Test {
+ public:
+ ~StatsTest() override = default;
+};
+
+TEST_F(StatsTest, ModelExecutionZeroValuePercent) {
+ base::HistogramTester tester;
+ std::vector<float> empty{};
+ std::vector<float> single_zero{0};
+ std::vector<float> single_non_zero{1};
+ std::vector<float> all_zeroes{0, 0, 0};
+ std::vector<float> one_non_zero{0, 2, 0};
+ std::vector<float> all_non_zero{1, 2, 3};
+
+ RecordModelExecutionZeroValuePercent(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, empty);
+ EXPECT_EQ(
+ 1, tester.GetBucketCount(
+ "SegmentationPlatform.ModelExecution.ZeroValuePercent.NewTab", 0));
+
+ RecordModelExecutionZeroValuePercent(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ single_zero);
+ EXPECT_EQ(
+ 1,
+ tester.GetBucketCount(
+ "SegmentationPlatform.ModelExecution.ZeroValuePercent.NewTab", 100));
+
+ RecordModelExecutionZeroValuePercent(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ single_non_zero);
+ EXPECT_EQ(
+ 2, tester.GetBucketCount(
+ "SegmentationPlatform.ModelExecution.ZeroValuePercent.NewTab", 0));
+
+ RecordModelExecutionZeroValuePercent(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB, all_zeroes);
+ EXPECT_EQ(
+ 2,
+ tester.GetBucketCount(
+ "SegmentationPlatform.ModelExecution.ZeroValuePercent.NewTab", 100));
+
+ RecordModelExecutionZeroValuePercent(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ one_non_zero);
+ EXPECT_EQ(
+ 1,
+ tester.GetBucketCount(
+ "SegmentationPlatform.ModelExecution.ZeroValuePercent.NewTab", 66));
+
+ RecordModelExecutionZeroValuePercent(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ all_non_zero);
+ EXPECT_EQ(
+ 3, tester.GetBucketCount(
+ "SegmentationPlatform.ModelExecution.ZeroValuePercent.NewTab", 0));
+}
+
+TEST_F(StatsTest, SegmentSwitch) {
+ std::string histogram("SegmentationPlatform.AdaptiveToolbar.SegmentSwitched");
+ base::HistogramTester tester;
+
+ // Share -> New tab.
+ RecordSegmentSelectionComputed(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB,
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE);
+
+ // None -> Share.
+ RecordSegmentSelectionComputed(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE,
+ absl::nullopt);
+
+ // Share -> Share.
+ RecordSegmentSelectionComputed(
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE,
+ OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_SHARE);
+ tester.ExpectTotalCount(histogram, 2);
+
+ EXPECT_THAT(
+ tester.GetAllSamples(histogram),
+ testing::ElementsAre(
+ base::Bucket(
+ static_cast<int>(AdaptiveToolbarSegmentSwitch::kNoneToShare), 1),
+ base::Bucket(
+ static_cast<int>(AdaptiveToolbarSegmentSwitch::kShareToNewTab),
+ 1)));
+ tester.ExpectTotalCount(
+ "SegmentationPlatform.AdaptiveToolbar.SegmentSelection.Computed", 3);
+}
+
+TEST_F(StatsTest, SignalsListeningCount) {
+ base::HistogramTester tester;
+ std::set<uint64_t> user_actions{1, 2, 3, 4};
+ std::set<std::pair<std::string, proto::SignalType>> histograms;
+ histograms.insert(std::make_pair("hist1", SignalType::HISTOGRAM_ENUM));
+ histograms.insert(std::make_pair("hist2", SignalType::HISTOGRAM_ENUM));
+ histograms.insert(std::make_pair("hist3", SignalType::HISTOGRAM_ENUM));
+ histograms.insert(std::make_pair("hist4", SignalType::HISTOGRAM_VALUE));
+ histograms.insert(std::make_pair("hist5", SignalType::HISTOGRAM_VALUE));
+
+ RecordSignalsListeningCount(user_actions, histograms);
+
+ EXPECT_EQ(1,
+ tester.GetBucketCount(
+ "SegmentationPlatform.Signals.ListeningCount.UserAction", 4));
+ EXPECT_EQ(
+ 1, tester.GetBucketCount(
+ "SegmentationPlatform.Signals.ListeningCount.HistogramEnum", 3));
+ EXPECT_EQ(
+ 1, tester.GetBucketCount(
+ "SegmentationPlatform.Signals.ListeningCount.HistogramValue", 2));
+}
+
+} // namespace stats
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/public/BUILD.gn b/chromium/components/segmentation_platform/public/BUILD.gn
new file mode 100644
index 00000000000..0108d5437b6
--- /dev/null
+++ b/chromium/components/segmentation_platform/public/BUILD.gn
@@ -0,0 +1,56 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (is_android) {
+ import("//build/config/android/config.gni")
+ import("//build/config/android/rules.gni")
+}
+
+source_set("public") {
+ sources = [
+ "config.cc",
+ "config.h",
+ "segment_selection_result.cc",
+ "segment_selection_result.h",
+ "segmentation_platform_service.cc",
+ "segmentation_platform_service.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/keyed_service/core",
+ "//components/optimization_guide/proto:optimization_guide_proto",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+
+ # IMPORTANT NOTE: When adding new tests, also remember to update the list of
+ # tests in //components/segmentation_platform/components_unittests.filter
+ sources = []
+
+ deps = [
+ ":public",
+ "//testing/gtest",
+ ]
+}
+
+if (is_android) {
+ android_library("public_java") {
+ sources = [
+ "android/java/src/org/chromium/components/segmentation_platform/SegmentSelectionResult.java",
+ "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformService.java",
+ ]
+
+ deps = [
+ "//base:base_java",
+ "//third_party/androidx:androidx_annotation_annotation_java",
+ ]
+
+ public_deps = [
+ "//components/optimization_guide/proto:optimization_guide_proto_java",
+ ]
+ }
+}
diff --git a/chromium/components/segmentation_platform/public/config.cc b/chromium/components/segmentation_platform/public/config.cc
new file mode 100644
index 00000000000..4bf44032533
--- /dev/null
+++ b/chromium/components/segmentation_platform/public/config.cc
@@ -0,0 +1,17 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/public/config.h"
+
+namespace segmentation_platform {
+
+Config::Config() = default;
+
+Config::~Config() = default;
+
+Config::Config(const Config& other) = default;
+
+Config& Config::operator=(const Config& other) = default;
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/public/config.h b/chromium/components/segmentation_platform/public/config.h
new file mode 100644
index 00000000000..520665a6a3b
--- /dev/null
+++ b/chromium/components/segmentation_platform/public/config.h
@@ -0,0 +1,39 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_CONFIG_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_CONFIG_H_
+
+#include <string>
+
+#include "base/time/time.h"
+#include "components/optimization_guide/proto/models.pb.h"
+
+namespace segmentation_platform {
+
+// Contains various finch configuration params used by the segmentation
+// platform.
+struct Config {
+ Config();
+ ~Config();
+
+ Config(const Config& other);
+ Config& operator=(const Config& other);
+
+ // The key is used to distinguish between different types of segmentation
+ // usages. Currently it is mainly used by the segment selector to find the
+ // discrete mapping and writing results to prefs.
+ std::string segmentation_key;
+
+ // Time to live for a segment selection. Segment selection can't be changed
+ // before this duration.
+ base::TimeDelta segment_selection_ttl;
+
+ // List of segment ids that the current config requires to be available.
+ std::vector<optimization_guide::proto::OptimizationTarget> segment_ids;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_CONFIG_H_
diff --git a/chromium/components/segmentation_platform/public/segment_selection_result.cc b/chromium/components/segmentation_platform/public/segment_selection_result.cc
new file mode 100644
index 00000000000..2ef56ee70a2
--- /dev/null
+++ b/chromium/components/segmentation_platform/public/segment_selection_result.cc
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/public/segment_selection_result.h"
+
+namespace segmentation_platform {
+
+SegmentSelectionResult::SegmentSelectionResult() = default;
+
+SegmentSelectionResult::~SegmentSelectionResult() = default;
+
+SegmentSelectionResult::SegmentSelectionResult(
+ const SegmentSelectionResult& other) = default;
+
+SegmentSelectionResult& SegmentSelectionResult::operator=(
+ const SegmentSelectionResult& other) = default;
+
+bool SegmentSelectionResult::operator==(
+ const SegmentSelectionResult& other) const {
+ return is_ready == other.is_ready && segment == other.segment;
+}
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/public/segment_selection_result.h b/chromium/components/segmentation_platform/public/segment_selection_result.h
new file mode 100644
index 00000000000..917ba61ca78
--- /dev/null
+++ b/chromium/components/segmentation_platform/public/segment_selection_result.h
@@ -0,0 +1,34 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_SEGMENT_SELECTION_RESULT_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_SEGMENT_SELECTION_RESULT_H_
+
+#include "components/optimization_guide/proto/models.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+using optimization_guide::proto::OptimizationTarget;
+
+namespace segmentation_platform {
+
+// The result of segmentation and related metadata.
+struct SegmentSelectionResult {
+ SegmentSelectionResult();
+ ~SegmentSelectionResult();
+ SegmentSelectionResult(const SegmentSelectionResult& other);
+ SegmentSelectionResult& operator=(const SegmentSelectionResult& other);
+ bool operator==(const SegmentSelectionResult& other) const;
+
+ // Whether or not the segmentation backend is ready, and has enough data for
+ // computing a segment.
+ bool is_ready{false};
+
+ // The result of segmentation. Can be empty if the the backend couldn't select
+ // a segment with confidence.
+ absl::optional<OptimizationTarget> segment;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_SEGMENT_SELECTION_RESULT_H_
diff --git a/chromium/components/segmentation_platform/public/segmentation_platform_service.cc b/chromium/components/segmentation_platform/public/segmentation_platform_service.cc
new file mode 100644
index 00000000000..3df13532ab6
--- /dev/null
+++ b/chromium/components/segmentation_platform/public/segmentation_platform_service.cc
@@ -0,0 +1,15 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/segmentation_platform/public/segmentation_platform_service.h"
+
+namespace segmentation_platform {
+namespace features {
+
+// Core feature flag for segmentation platform.
+const base::Feature kSegmentationPlatformFeature{
+ "SegmentationPlatform", base::FEATURE_DISABLED_BY_DEFAULT};
+} // namespace features
+
+} // namespace segmentation_platform
diff --git a/chromium/components/segmentation_platform/public/segmentation_platform_service.h b/chromium/components/segmentation_platform/public/segmentation_platform_service.h
new file mode 100644
index 00000000000..f3af35c8ad4
--- /dev/null
+++ b/chromium/components/segmentation_platform/public/segmentation_platform_service.h
@@ -0,0 +1,68 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_SEGMENTATION_PLATFORM_SERVICE_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_SEGMENTATION_PLATFORM_SERVICE_H_
+
+#include <string>
+
+#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/supports_user_data.h"
+#include "build/build_config.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/jni_android.h"
+#endif // defined(OS_ANDROID)
+
+class PrefRegistrySimple;
+
+namespace segmentation_platform {
+namespace features {
+extern const base::Feature kSegmentationPlatformFeature;
+} // namespace features
+
+struct SegmentSelectionResult;
+
+// The core class of segmentation platform that integrates all the required
+// pieces on the client side.
+class SegmentationPlatformService : public KeyedService,
+ public base::SupportsUserData {
+ public:
+#if defined(OS_ANDROID)
+ // Returns a Java object of the type SegmentationPlatformService for the given
+ // SegmentationPlatformService.
+ static base::android::ScopedJavaLocalRef<jobject> GetJavaObject(
+ SegmentationPlatformService* segmentation_platform_service);
+#endif // defined(OS_ANDROID)
+
+ SegmentationPlatformService() = default;
+ ~SegmentationPlatformService() override = default;
+
+ // Disallow copy/assign.
+ SegmentationPlatformService(const SegmentationPlatformService&) = delete;
+ SegmentationPlatformService& operator=(const SegmentationPlatformService&) =
+ delete;
+
+ // Registers preferences used by this class in the provided |registry|. This
+ // should be called for the Profile registry.
+ static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+ using SegmentSelectionCallback =
+ base::OnceCallback<void(const SegmentSelectionResult&)>;
+
+ // Called to get the selected segment. If none, returns empty result.
+ virtual void GetSelectedSegment(const std::string& segmentation_key,
+ SegmentSelectionCallback callback) = 0;
+
+ // Called to enable or disable metrics collection. Must be explicitly called
+ // on startup.
+ virtual void EnableMetrics(bool signal_collection_allowed) = 0;
+};
+
+} // namespace segmentation_platform
+
+#endif // COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_SEGMENTATION_PLATFORM_SERVICE_H_
diff --git a/chromium/components/send_tab_to_self/BUILD.gn b/chromium/components/send_tab_to_self/BUILD.gn
index 67f5f6d65c2..d53f76ff410 100644
--- a/chromium/components/send_tab_to_self/BUILD.gn
+++ b/chromium/components/send_tab_to_self/BUILD.gn
@@ -8,6 +8,8 @@ static_library("send_tab_to_self") {
"fake_send_tab_to_self_model.h",
"features.cc",
"features.h",
+ "metrics_util.cc",
+ "metrics_util.h",
"pref_names.cc",
"pref_names.h",
"send_tab_to_self_bridge.cc",
diff --git a/chromium/components/send_tab_to_self/OWNERS b/chromium/components/send_tab_to_self/OWNERS
index 25e38d8eae2..42b16b0636a 100644
--- a/chromium/components/send_tab_to_self/OWNERS
+++ b/chromium/components/send_tab_to_self/OWNERS
@@ -3,7 +3,6 @@ hansberry@chromium.org
jeffreycohen@chromium.org
kmilka@chromium.org
kristipark@chromium.org
-ramyan@chromium.org
sebsg@chromium.org
skare@chromium.org
tgupta@chromium.org
diff --git a/chromium/components/send_tab_to_self/features.cc b/chromium/components/send_tab_to_self/features.cc
index 15861b7a2dc..69c902f2b99 100644
--- a/chromium/components/send_tab_to_self/features.cc
+++ b/chromium/components/send_tab_to_self/features.cc
@@ -14,6 +14,8 @@ const base::Feature kSendTabToSelfWhenSignedIn{
"SendTabToSelfWhenSignedIn", base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kSendTabToSelfUseFakeBackend{
"SendTabToSelfUseFakeBackend", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kSendTabToSelfV2{"SendTabToSelfV2",
+ base::FEATURE_DISABLED_BY_DEFAULT};
bool IsReceivingEnabledByUserOnThisDevice(PrefService* prefs) {
// TODO(crbug.com/1015322): SyncPrefs is used directly instead of methods in
diff --git a/chromium/components/send_tab_to_self/features.h b/chromium/components/send_tab_to_self/features.h
index 114f78725ac..6413c7e694f 100644
--- a/chromium/components/send_tab_to_self/features.h
+++ b/chromium/components/send_tab_to_self/features.h
@@ -20,6 +20,10 @@ extern const base::Feature kSendTabToSelfWhenSignedIn;
// hardcoded list of share targets, for UI work & debugging.
extern const base::Feature kSendTabToSelfUseFakeBackend;
+// If this feature is enabled, show received tabs in a new UI next to the
+// profile icon rather than in a system notification.
+extern const base::Feature kSendTabToSelfV2;
+
// Returns whether the receiving components of the feature is enabled on this
// device. This doesn't rely on the SendTabToSelfSyncService to be actively up
// and ready.
diff --git a/chromium/components/send_tab_to_self/metrics_util.cc b/chromium/components/send_tab_to_self/metrics_util.cc
new file mode 100644
index 00000000000..724f2d08701
--- /dev/null
+++ b/chromium/components/send_tab_to_self/metrics_util.cc
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/send_tab_to_self/metrics_util.h"
+
+#include "base/metrics/histogram_functions.h"
+#include "base/strings/strcat.h"
+
+namespace send_tab_to_self {
+
+namespace {
+
+// State of the send tab to self option in the UI.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class ClickResult {
+ // kShowItem = 0,
+ kClickItem = 1,
+ // kShowDeviceList = 2,
+ kMaxValue = kClickItem,
+};
+
+std::string GetEntryPointHistogramString(ShareEntryPoint entry_point) {
+ switch (entry_point) {
+ case ShareEntryPoint::kShareSheet:
+ return "ShareSheet";
+ case ShareEntryPoint::kOmniboxIcon:
+ return "OmniboxIcon";
+ case ShareEntryPoint::kContentMenu:
+ return "ContentMenu";
+ case ShareEntryPoint::kLinkMenu:
+ return "LinkMenu";
+ case ShareEntryPoint::kOmniboxMenu:
+ return "OmniboxMenu";
+ case ShareEntryPoint::kTabMenu:
+ return "TabMenu";
+ case ShareEntryPoint::kShareMenu:
+ return "ShareMenu";
+ }
+}
+
+} // namespace
+
+void RecordDeviceClicked(ShareEntryPoint entry_point) {
+ // TODO(crbug.com/956722): Only kClickItem is used today, so we should replace
+ // this with a histogram which doesn't use the ClickResult enum.
+ base::UmaHistogramEnumeration(
+ base::StrCat({"SendTabToSelf.", GetEntryPointHistogramString(entry_point),
+ ".ClickResult"}),
+ ClickResult::kClickItem);
+}
+
+} // namespace send_tab_to_self
diff --git a/chromium/components/send_tab_to_self/metrics_util.h b/chromium/components/send_tab_to_self/metrics_util.h
new file mode 100644
index 00000000000..2de88d396e0
--- /dev/null
+++ b/chromium/components/send_tab_to_self/metrics_util.h
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SEND_TAB_TO_SELF_METRICS_UTIL_H_
+#define COMPONENTS_SEND_TAB_TO_SELF_METRICS_UTIL_H_
+
+namespace send_tab_to_self {
+
+enum class ShareEntryPoint {
+ kContentMenu,
+ kLinkMenu,
+ kOmniboxIcon,
+ kOmniboxMenu,
+ kShareMenu,
+ kShareSheet,
+ kTabMenu,
+};
+
+// Records whether the user clicked to send a tab to a device.
+void RecordDeviceClicked(ShareEntryPoint entry_point);
+
+} // namespace send_tab_to_self
+
+#endif // COMPONENTS_SEND_TAB_TO_SELF_METRICS_UTIL_H_
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 ea6ee67e379..6ba16ad963c 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
@@ -11,7 +11,6 @@
#include "base/check_op.h"
#include "base/guid.h"
#include "base/memory/ptr_util.h"
-#include "base/optional.h"
#include "base/strings/string_util.h"
#include "base/time/clock.h"
#include "base/time/time.h"
@@ -27,6 +26,7 @@
#include "components/sync/protocol/model_type_state.pb.h"
#include "components/sync_device_info/device_info_tracker.h"
#include "components/sync_device_info/local_device_info_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace send_tab_to_self {
@@ -56,7 +56,7 @@ std::unique_ptr<syncer::EntityData> CopyToEntityData(
// Parses the content of |record_list| into |*initial_data|. The output
// parameter is first for binding purposes.
-base::Optional<syncer::ModelError> ParseLocalEntriesOnBackendSequence(
+absl::optional<syncer::ModelError> ParseLocalEntriesOnBackendSequence(
base::Time now,
std::map<std::string, std::unique_ptr<SendTabToSelfEntry>>* entries,
std::string* local_personalizable_device_name,
@@ -79,7 +79,7 @@ base::Optional<syncer::ModelError> ParseLocalEntriesOnBackendSequence(
}
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace
@@ -118,7 +118,7 @@ SendTabToSelfBridge::CreateMetadataChangeList() {
return ModelTypeStore::WriteBatch::CreateMetadataChangeList();
}
-base::Optional<syncer::ModelError> SendTabToSelfBridge::MergeSyncData(
+absl::optional<syncer::ModelError> SendTabToSelfBridge::MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
DCHECK(entries_.empty());
@@ -126,7 +126,7 @@ base::Optional<syncer::ModelError> SendTabToSelfBridge::MergeSyncData(
std::move(entity_data));
}
-base::Optional<syncer::ModelError> SendTabToSelfBridge::ApplySyncChanges(
+absl::optional<syncer::ModelError> SendTabToSelfBridge::ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) {
std::vector<const SendTabToSelfEntry*> added;
@@ -194,7 +194,7 @@ base::Optional<syncer::ModelError> SendTabToSelfBridge::ApplySyncChanges(
NotifyRemoteSendTabToSelfEntryAdded(added);
NotifyRemoteSendTabToSelfEntryOpened(opened);
- return base::nullopt;
+ return absl::nullopt;
}
void SendTabToSelfBridge::GetData(StorageKeyList storage_keys,
@@ -524,7 +524,7 @@ void SendTabToSelfBridge::NotifySendTabToSelfModelLoaded() {
}
void SendTabToSelfBridge::OnStoreCreated(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore> store) {
if (error) {
change_processor()->ReportError(*error);
@@ -550,7 +550,7 @@ void SendTabToSelfBridge::OnStoreCreated(
void SendTabToSelfBridge::OnReadAllData(
std::unique_ptr<SendTabToSelfEntries> initial_entries,
std::unique_ptr<std::string> local_device_name,
- const base::Optional<syncer::ModelError>& error) {
+ const absl::optional<syncer::ModelError>& error) {
DCHECK(initial_entries);
DCHECK(local_device_name);
@@ -567,7 +567,7 @@ void SendTabToSelfBridge::OnReadAllData(
}
void SendTabToSelfBridge::OnReadAllMetadata(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
if (error) {
change_processor()->ReportError(*error);
@@ -580,7 +580,7 @@ void SendTabToSelfBridge::OnReadAllMetadata(
}
void SendTabToSelfBridge::OnCommit(
- const base::Optional<syncer::ModelError>& error) {
+ const absl::optional<syncer::ModelError>& error) {
if (error) {
change_processor()->ReportError(*error);
}
diff --git a/chromium/components/send_tab_to_self/send_tab_to_self_bridge.h b/chromium/components/send_tab_to_self/send_tab_to_self_bridge.h
index 1ba260720c7..e718b9a5f60 100644
--- a/chromium/components/send_tab_to_self/send_tab_to_self_bridge.h
+++ b/chromium/components/send_tab_to_self/send_tab_to_self_bridge.h
@@ -53,10 +53,10 @@ class SendTabToSelfBridge : public syncer::ModelTypeSyncBridge,
// syncer::ModelTypeSyncBridge overrides.
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
@@ -116,14 +116,14 @@ class SendTabToSelfBridge : public syncer::ModelTypeSyncBridge,
void NotifySendTabToSelfModelLoaded();
// Methods used as callbacks given to DataTypeStore.
- void OnStoreCreated(const base::Optional<syncer::ModelError>& error,
+ void OnStoreCreated(const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore> store);
void OnReadAllData(std::unique_ptr<SendTabToSelfEntries> initial_entries,
std::unique_ptr<std::string> local_device_name,
- const base::Optional<syncer::ModelError>& error);
- void OnReadAllMetadata(const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error);
+ void OnReadAllMetadata(const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch);
- void OnCommit(const base::Optional<syncer::ModelError>& error);
+ void OnCommit(const absl::optional<syncer::ModelError>& error);
// Persists the changes in the given aggregators
void Commit(std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch);
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 56684359e4b..2ea36b99ae0 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
@@ -85,8 +85,8 @@ std::unique_ptr<syncer::DeviceInfo> CreateDevice(
sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "scoped_id", "manufacturer",
"model", "full_hardware_class", last_updated_timestamp,
syncer::DeviceInfoUtil::GetPulseInterval(),
- send_tab_to_self_receiving_enabled, /*sharing_info=*/base::nullopt,
- /*paask_info=*/base::nullopt,
+ send_tab_to_self_receiving_enabled, /*sharing_info=*/absl::nullopt,
+ /*paask_info=*/absl::nullopt,
/*fcm_registration_token=*/std::string(),
/*interested_data_types=*/syncer::ModelTypeSet());
}
diff --git a/chromium/components/send_tab_to_self/send_tab_to_self_model.h b/chromium/components/send_tab_to_self/send_tab_to_self_model.h
index e484b13c518..4bbad7486b3 100644
--- a/chromium/components/send_tab_to_self/send_tab_to_self_model.h
+++ b/chromium/components/send_tab_to_self/send_tab_to_self_model.h
@@ -90,4 +90,4 @@ class SendTabToSelfModel {
} // namespace send_tab_to_self
-#endif // COMPONENTS_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_MODEL_H
+#endif // COMPONENTS_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_MODEL_H_
diff --git a/chromium/components/send_tab_to_self/send_tab_to_self_sync_service.h b/chromium/components/send_tab_to_self/send_tab_to_self_sync_service.h
index 2dd9097788b..7e780603b3d 100644
--- a/chromium/components/send_tab_to_self/send_tab_to_self_sync_service.h
+++ b/chromium/components/send_tab_to_self/send_tab_to_self_sync_service.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SEND_TAB_TO_SELF_SEND_TAB_TO_SELF_SYNC_SERVICE_H_
#include <memory>
-#include <string>
#include "base/memory/weak_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
diff --git a/chromium/components/send_tab_to_self/target_device_info_unittest.cc b/chromium/components/send_tab_to_self/target_device_info_unittest.cc
index 53500cfee45..c15d28d0d33 100644
--- a/chromium/components/send_tab_to_self/target_device_info_unittest.cc
+++ b/chromium/components/send_tab_to_self/target_device_info_unittest.cc
@@ -42,7 +42,7 @@ static std::unique_ptr<syncer::DeviceInfo> CreateFakeDeviceInfo(
{"sender_id_fcm_token", "sender_id_p256dh", "sender_id_auth_secret"},
std::set<sync_pb::SharingSpecificFields::EnabledFeatures>{
sync_pb::SharingSpecificFields::CLICK_TO_CALL_V2}),
- /*paask_info=*/base::nullopt,
+ /*paask_info=*/absl::nullopt,
/*fcm_registration_token=*/std::string(),
/*interested_data_types=*/syncer::ModelTypeSet());
}
diff --git a/chromium/components/services/app_service/README.md b/chromium/components/services/app_service/README.md
index 9aee4e7b4b3..2e8dd6c5486 100644
--- a/chromium/components/services/app_service/README.md
+++ b/chromium/components/services/app_service/README.md
@@ -225,8 +225,8 @@ which have the same type: `App`). Specifically, last known value wins. Any
known field in the delta overwrites the corresponding field in the old state,
any unknown field in the delta is ignored. For example, if an app's name
changed but its icon didn't, the delta's `App.name` field (a
-`base::Optional<std::string>`) would be known (not `base::nullopt`) and copied
-over but its `App.icon` field would be unknown (`base::nullopt`) and not copied
+`absl::optional<std::string>`) would be known (not `absl::nullopt`) and copied
+over but its `App.icon` field would be unknown (`absl::nullopt`) and not copied
over.
The current state is thus the merger or sum of all previous deltas, including
diff --git a/chromium/components/services/app_service/app_service_impl.cc b/chromium/components/services/app_service/app_service_impl.cc
index e719df4d9cc..57cb52ef92f 100644
--- a/chromium/components/services/app_service/app_service_impl.cc
+++ b/chromium/components/services/app_service/app_service_impl.cc
@@ -376,11 +376,11 @@ void AppServiceImpl::RemovePreferredApp(apps::mojom::AppType app_type,
return;
}
- preferred_apps_.DeleteAppId(app_id);
+ if (preferred_apps_.DeleteAppId(app_id)) {
+ WriteToJSON(profile_dir_, preferred_apps_);
+ }
LogPreferredAppUpdateAction(PreferredAppsUpdateAction::kDeleteForAppId);
-
- WriteToJSON(profile_dir_, preferred_apps_);
}
void AppServiceImpl::RemovePreferredAppForFilter(
@@ -396,12 +396,12 @@ void AppServiceImpl::RemovePreferredAppForFilter(
return;
}
- preferred_apps_.DeletePreferredApp(app_id, intent_filter);
-
- WriteToJSON(profile_dir_, preferred_apps_);
+ if (preferred_apps_.DeletePreferredApp(app_id, intent_filter)) {
+ WriteToJSON(profile_dir_, preferred_apps_);
- for (auto& subscriber : subscribers_) {
- subscriber->OnPreferredAppRemoved(app_id, intent_filter->Clone());
+ for (auto& subscriber : subscribers_) {
+ subscriber->OnPreferredAppRemoved(app_id, intent_filter->Clone());
+ }
}
LogPreferredAppUpdateAction(PreferredAppsUpdateAction::kDeleteForFilter);
diff --git a/chromium/components/services/app_service/app_service_impl.h b/chromium/components/services/app_service/app_service_impl.h
index e709b3728d4..ccfc54a9c8a 100644
--- a/chromium/components/services/app_service/app_service_impl.h
+++ b/chromium/components/services/app_service/app_service_impl.h
@@ -175,4 +175,4 @@ class AppServiceImpl : public apps::mojom::AppService {
} // namespace apps
-#endif // CHROME_SERVICES_APP_SERVICE_APP_SERVICE_IMPL_H_
+#endif // COMPONENTS_SERVICES_APP_SERVICE_APP_SERVICE_IMPL_H_
diff --git a/chromium/components/services/app_service/app_service_impl_unittest.cc b/chromium/components/services/app_service/app_service_impl_unittest.cc
index ed7fb8bfa67..9869d3ebe58 100644
--- a/chromium/components/services/app_service/app_service_impl_unittest.cc
+++ b/chromium/components/services/app_service/app_service_impl_unittest.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "components/services/app_service/app_service_impl.h"
#include "components/services/app_service/public/cpp/app_capability_access_cache.h"
@@ -26,6 +25,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace apps {
@@ -50,8 +50,8 @@ class FakePublisher : public apps::PublisherBase {
}
void ModifyCapabilityAccess(const std::string& app_id,
- base::Optional<bool> accessing_camera,
- base::Optional<bool> accessing_microphone) {
+ absl::optional<bool> accessing_camera,
+ absl::optional<bool> accessing_microphone) {
if (accessing_camera.has_value()) {
if (accessing_camera.value()) {
apps_accessing_camera_.insert(app_id);
@@ -258,12 +258,12 @@ TEST_F(AppServiceImplTest, PubSub) {
EXPECT_EQ("", sub0.AppIdsAccessingCamera());
EXPECT_EQ("", sub0.AppIdsAccessingMicrophone());
- pub0.ModifyCapabilityAccess("B", base::nullopt, base::nullopt);
+ pub0.ModifyCapabilityAccess("B", absl::nullopt, absl::nullopt);
impl.FlushMojoCallsForTesting();
EXPECT_EQ("", sub0.AppIdsAccessingCamera());
EXPECT_EQ("", sub0.AppIdsAccessingMicrophone());
- pub0.ModifyCapabilityAccess("B", true, base::nullopt);
+ pub0.ModifyCapabilityAccess("B", true, absl::nullopt);
impl.FlushMojoCallsForTesting();
EXPECT_EQ("B", sub0.AppIdsAccessingCamera());
EXPECT_EQ("", sub0.AppIdsAccessingMicrophone());
@@ -287,8 +287,8 @@ TEST_F(AppServiceImplTest, PubSub) {
// Have both publishers publish more apps.
pub0.PublishMoreApps(std::vector<std::string>{"F"});
pub1.PublishMoreApps(std::vector<std::string>{"n"});
- pub0.ModifyCapabilityAccess("B", false, base::nullopt);
- pub1.ModifyCapabilityAccess("n", base::nullopt, true);
+ pub0.ModifyCapabilityAccess("B", false, absl::nullopt);
+ pub1.ModifyCapabilityAccess("n", absl::nullopt, true);
impl.FlushMojoCallsForTesting();
EXPECT_EQ("ABCDEFmn", sub0.AppIdsSeen());
EXPECT_EQ("D", sub0.AppIdsAccessingCamera());
@@ -307,7 +307,7 @@ TEST_F(AppServiceImplTest, PubSub) {
// Publish more apps.
pub0.ModifyCapabilityAccess("D", false, false);
pub1.PublishMoreApps(std::vector<std::string>{"o", "p", "q"});
- pub1.ModifyCapabilityAccess("n", true, base::nullopt);
+ pub1.ModifyCapabilityAccess("n", true, absl::nullopt);
impl.FlushMojoCallsForTesting();
EXPECT_EQ("ABCDEFmnopq", sub0.AppIdsSeen());
EXPECT_EQ("ABCDEFmnopq", sub1.AppIdsSeen());
@@ -409,13 +409,13 @@ TEST_F(AppServiceImplTest, PreferredApps) {
apps_util::CreateIntentFilterForUrlScope(another_filter_url);
task_environment_.RunUntilIdle();
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
sub0.PreferredApps().FindPreferredAppForUrl(filter_url));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
sub1.PreferredApps().FindPreferredAppForUrl(filter_url));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
sub0.PreferredApps().FindPreferredAppForUrl(another_filter_url));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
sub1.PreferredApps().FindPreferredAppForUrl(another_filter_url));
impl.AddPreferredApp(
@@ -436,13 +436,13 @@ TEST_F(AppServiceImplTest, PreferredApps) {
// Test that uninstall removes all the settings for the app.
pub0.UninstallApps(std::vector<std::string>{kAppId2}, &impl);
task_environment_.RunUntilIdle();
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
sub0.PreferredApps().FindPreferredAppForUrl(filter_url));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
sub1.PreferredApps().FindPreferredAppForUrl(filter_url));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
sub0.PreferredApps().FindPreferredAppForUrl(another_filter_url));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
sub1.PreferredApps().FindPreferredAppForUrl(another_filter_url));
impl.AddPreferredApp(
@@ -465,9 +465,9 @@ TEST_F(AppServiceImplTest, PreferredApps) {
impl.RemovePreferredAppForFilter(apps::mojom::AppType::kUnknown, kAppId2,
intent_filter->Clone());
task_environment_.RunUntilIdle();
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
sub0.PreferredApps().FindPreferredAppForUrl(filter_url));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
sub1.PreferredApps().FindPreferredAppForUrl(filter_url));
EXPECT_EQ(kAppId2,
sub0.PreferredApps().FindPreferredAppForUrl(another_filter_url));
@@ -587,10 +587,10 @@ TEST_F(AppServiceImplTest, PreferredAppsUpgrade) {
intent_filter2_with_action->Clone());
task_environment_.RunUntilIdle();
EXPECT_EQ(
- base::nullopt,
+ absl::nullopt,
impl.GetPreferredAppsForTesting().FindPreferredAppForUrl(filter_url1));
EXPECT_EQ(
- base::nullopt,
+ absl::nullopt,
impl.GetPreferredAppsForTesting().FindPreferredAppForUrl(filter_url2));
}
}
diff --git a/chromium/components/services/app_service/public/cpp/BUILD.gn b/chromium/components/services/app_service/public/cpp/BUILD.gn
index ba640fbf441..583ae597d06 100644
--- a/chromium/components/services/app_service/public/cpp/BUILD.gn
+++ b/chromium/components/services/app_service/public/cpp/BUILD.gn
@@ -169,6 +169,15 @@ source_set("test_support") {
]
}
+source_set("types") {
+ sources = [
+ "types_util.cc",
+ "types_util.h",
+ ]
+
+ deps = [ "//components/services/app_service/public/mojom" ]
+}
+
source_set("unit_tests") {
testonly = true
diff --git a/chromium/components/services/app_service/public/cpp/app_update_unittest.cc b/chromium/components/services/app_service/public/cpp/app_update_unittest.cc
index 496452536b3..7c8bee81e19 100644
--- a/chromium/components/services/app_service/public/cpp/app_update_unittest.cc
+++ b/chromium/components/services/app_service/public/cpp/app_update_unittest.cc
@@ -251,7 +251,7 @@ class AppUpdateTest : public testing::Test {
expect_readiness_changed_ = true;
CheckExpects(u);
- delta->name = base::nullopt;
+ delta->name = absl::nullopt;
expect_name_ = state ? test_name_0 : "";
expect_name_changed_ = false;
CheckExpects(u);
diff --git a/chromium/components/services/app_service/public/cpp/file_handler.cc b/chromium/components/services/app_service/public/cpp/file_handler.cc
index 80d69ecd65c..1fdf1b0a164 100644
--- a/chromium/components/services/app_service/public/cpp/file_handler.cc
+++ b/chromium/components/services/app_service/public/cpp/file_handler.cc
@@ -40,16 +40,20 @@ std::set<std::string> GetFileExtensionsFromFileHandlers(
std::ostream& operator<<(std::ostream& out,
const FileHandler::AcceptEntry& accept_entry) {
- out << "mime_type: " << accept_entry.mime_type << " file_extensions:";
+ out << " mime_type: " << accept_entry.mime_type << std::endl;
+ out << " file_extensions:";
for (const auto& file_extension : accept_entry.file_extensions)
out << " " << file_extension;
+ out << std::endl;
return out;
}
std::ostream& operator<<(std::ostream& out, const FileHandler& file_handler) {
- out << "action: " << file_handler.action;
- for (const auto& accept_entry : file_handler.accept)
- out << " accept: " << accept_entry;
+ out << "action: " << file_handler.action << std::endl;
+ for (const auto& accept_entry : file_handler.accept) {
+ out << " accept:" << std::endl;
+ out << accept_entry;
+ }
return out;
}
diff --git a/chromium/components/services/app_service/public/cpp/instance.cc b/chromium/components/services/app_service/public/cpp/instance.cc
index 0eba9b740c7..4ff8f9c114c 100644
--- a/chromium/components/services/app_service/public/cpp/instance.cc
+++ b/chromium/components/services/app_service/public/cpp/instance.cc
@@ -8,15 +8,32 @@
namespace apps {
-Instance::Instance(const std::string& app_id, aura::Window* window)
- : app_id_(app_id), window_(window) {
+Instance::InstanceKey::InstanceKey(aura::Window* window) : window_(window) {}
+
+bool Instance::InstanceKey::operator<(const InstanceKey& other) const {
+ return Window() < other.Window();
+}
+
+bool Instance::InstanceKey::operator==(const InstanceKey& other) const {
+ return Window() == other.Window();
+}
+
+bool Instance::InstanceKey::operator!=(const InstanceKey& other) const {
+ return Window() != other.Window();
+}
+
+Instance::Instance(const std::string& app_id,
+ std::unique_ptr<InstanceKey> instance_key)
+ : app_id_(app_id), instance_key_(std::move(instance_key)) {
+ DCHECK(instance_key_);
state_ = InstanceState::kUnknown;
}
Instance::~Instance() = default;
std::unique_ptr<Instance> Instance::Clone() {
- auto instance = std::make_unique<Instance>(this->AppId(), this->Window());
+ auto instance = std::make_unique<Instance>(
+ this->AppId(), std::make_unique<InstanceKey>(this->Window()));
instance->SetLaunchId(this->LaunchId());
instance->UpdateState(this->State(), this->LastUpdatedTime());
instance->SetBrowserContext(this->BrowserContext());
@@ -34,3 +51,13 @@ void Instance::SetBrowserContext(content::BrowserContext* browser_context) {
}
} // namespace apps
+
+std::ostream& operator<<(std::ostream& os,
+ const apps::Instance::InstanceKey& instance_key) {
+ return os << "InstanceKey {Window: " << instance_key.Window() << "}";
+}
+
+size_t InstanceKeyHash::operator()(
+ const apps::Instance::InstanceKey& key) const {
+ return std::hash<aura::Window*>()(key.Window());
+}
diff --git a/chromium/components/services/app_service/public/cpp/instance.h b/chromium/components/services/app_service/public/cpp/instance.h
index 45c1a5cfe31..2a28d64f607 100644
--- a/chromium/components/services/app_service/public/cpp/instance.h
+++ b/chromium/components/services/app_service/public/cpp/instance.h
@@ -7,6 +7,7 @@
#include <memory>
#include <string>
+#include <utility>
#include "base/time/time.h"
#include "content/public/browser/browser_context.h"
@@ -27,7 +28,26 @@ enum InstanceState {
// Instance is used to represent an App Instance, or a running app.
class Instance {
public:
- Instance(const std::string& app_id, aura::Window* window);
+ // InstanceKey is the unique key for the instance.
+ class InstanceKey {
+ public:
+ explicit InstanceKey(aura::Window* window);
+ ~InstanceKey() = default;
+ aura::Window* Window() const { return window_; }
+ bool operator<(const InstanceKey& other) const;
+ bool operator==(const InstanceKey& other) const;
+ bool operator!=(const InstanceKey& other) const;
+
+ private:
+ // window_ is owned by ash and will be deleted when the user closes the
+ // window. Instance itself doesn't observe the window. The window's observer
+ // is responsible to delete Instance from InstanceRegistry when the window
+ // is destroyed.
+ aura::Window* window_;
+ };
+
+ Instance(const std::string& app_id,
+ std::unique_ptr<InstanceKey> instance_key);
~Instance();
Instance(const Instance&) = delete;
@@ -40,7 +60,8 @@ class Instance {
void SetBrowserContext(content::BrowserContext* browser_context);
const std::string& AppId() const { return app_id_; }
- aura::Window* Window() const { return window_; }
+ const InstanceKey& GetInstanceKey() const { return *instance_key_; }
+ aura::Window* Window() const { return instance_key_->Window(); }
const std::string& LaunchId() const { return launch_id_; }
InstanceState State() const { return state_; }
const base::Time& LastUpdatedTime() const { return last_updated_time_; }
@@ -48,12 +69,7 @@ class Instance {
private:
std::string app_id_;
-
- // window_ is owned by ash and will be deleted when the user closes the
- // window. Instance itself doesn't observe the window. The window's observer
- // is responsible to delete Instance from InstanceRegistry when the window is
- // destroyed.
- aura::Window* window_;
+ std::unique_ptr<InstanceKey> instance_key_;
std::string launch_id_;
InstanceState state_;
base::Time last_updated_time_;
@@ -62,4 +78,11 @@ class Instance {
} // namespace apps
+std::ostream& operator<<(std::ostream& os,
+ const apps::Instance::InstanceKey& instance_key);
+
+struct InstanceKeyHash {
+ size_t operator()(const apps::Instance::InstanceKey& key) const;
+};
+
#endif // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_INSTANCE_H_
diff --git a/chromium/components/services/app_service/public/cpp/instance_registry.cc b/chromium/components/services/app_service/public/cpp/instance_registry.cc
index beb08b7cf76..9b597a1fe12 100644
--- a/chromium/components/services/app_service/public/cpp/instance_registry.cc
+++ b/chromium/components/services/app_service/public/cpp/instance_registry.cc
@@ -59,17 +59,19 @@ void InstanceRegistry::OnInstances(const Instances& deltas) {
DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
for (auto& delta : deltas) {
- // If the window state is not kDestroyed, adds to |app_id_to_app_window_|,
- // otherwise removes the window from |app_id_to_app_window_|.
+ // If the instance state is not kDestroyed, adds to
+ // |app_id_to_app_instance_key_|, otherwise removes the instance key from
+ // |app_id_to_app_instance_key_|.
if (static_cast<InstanceState>(delta.get()->State() &
InstanceState::kDestroyed) ==
InstanceState::kUnknown) {
- app_id_to_app_windows_[delta.get()->AppId()].insert(
- delta.get()->Window());
+ app_id_to_app_instance_key_[delta.get()->AppId()].insert(
+ delta.get()->GetInstanceKey());
} else {
- app_id_to_app_windows_[delta.get()->AppId()].erase(delta.get()->Window());
- if (app_id_to_app_windows_[delta.get()->AppId()].size() == 0) {
- app_id_to_app_windows_.erase(delta.get()->AppId());
+ app_id_to_app_instance_key_[delta.get()->AppId()].erase(
+ delta.get()->GetInstanceKey());
+ if (app_id_to_app_instance_key_[delta.get()->AppId()].size() == 0) {
+ app_id_to_app_instance_key_.erase(delta.get()->AppId());
}
}
}
@@ -90,29 +92,34 @@ void InstanceRegistry::OnInstances(const Instances& deltas) {
std::set<aura::Window*> InstanceRegistry::GetWindows(
const std::string& app_id) {
- auto it = app_id_to_app_windows_.find(app_id);
- if (it != app_id_to_app_windows_.end()) {
- return it->second;
+ auto it = app_id_to_app_instance_key_.find(app_id);
+ auto windows = std::set<aura::Window*>{};
+ if (it != app_id_to_app_instance_key_.end()) {
+ for (auto instance_key : it->second) {
+ windows.insert(instance_key.Window());
+ }
}
- return std::set<aura::Window*>{};
+ return windows;
}
-InstanceState InstanceRegistry::GetState(aura::Window* window) const {
- auto s_iter = states_.find(window);
+InstanceState InstanceRegistry::GetState(
+ const Instance::InstanceKey& instance_key) const {
+ auto s_iter = states_.find(instance_key);
return (s_iter != states_.end()) ? s_iter->second.get()->State()
: InstanceState::kUnknown;
}
-ash::ShelfID InstanceRegistry::GetShelfId(aura::Window* window) const {
- auto s_iter = states_.find(window);
+ash::ShelfID InstanceRegistry::GetShelfId(
+ const Instance::InstanceKey& instance_key) const {
+ auto s_iter = states_.find(instance_key);
return (s_iter != states_.end())
? ash::ShelfID(s_iter->second.get()->AppId(),
s_iter->second.get()->LaunchId())
: ash::ShelfID();
}
-bool InstanceRegistry::Exists(aura::Window* window) const {
- return states_.find(window) != states_.end();
+bool InstanceRegistry::Exists(const Instance::InstanceKey& instance_key) const {
+ return states_.find(instance_key) != states_.end();
}
void InstanceRegistry::DoOnInstances(const Instances& deltas) {
@@ -122,20 +129,20 @@ void InstanceRegistry::DoOnInstances(const Instances& deltas) {
// OninstanceUpdate is called for each updates, and notify the observers for
// every de-duplicated delta. Also update the states for every delta.
for (const auto& d_iter : deltas) {
- auto s_iter = states_.find(d_iter->Window());
+ auto s_iter = states_.find(d_iter->GetInstanceKey());
Instance* state =
(s_iter != states_.end()) ? s_iter->second.get() : nullptr;
if (InstanceUpdate::Equals(state, d_iter.get())) {
continue;
}
- std::unique_ptr<Instance> old_state = nullptr;
+ std::unique_ptr<Instance> old_state;
if (state) {
old_state = state->Clone();
InstanceUpdate::Merge(state, d_iter.get());
} else {
- states_.insert(
- std::make_pair(d_iter.get()->Window(), (d_iter.get()->Clone())));
+ states_.insert(std::make_pair(d_iter.get()->GetInstanceKey(),
+ (d_iter.get()->Clone())));
}
for (auto& obs : observers_) {
@@ -145,7 +152,7 @@ void InstanceRegistry::DoOnInstances(const Instances& deltas) {
if (static_cast<InstanceState>(d_iter.get()->State() &
InstanceState::kDestroyed) !=
InstanceState::kUnknown) {
- states_.erase(d_iter.get()->Window());
+ states_.erase(d_iter.get()->GetInstanceKey());
}
}
in_progress_ = false;
diff --git a/chromium/components/services/app_service/public/cpp/instance_registry.h b/chromium/components/services/app_service/public/cpp/instance_registry.h
index ca627904758..0ee7b841ab4 100644
--- a/chromium/components/services/app_service/public/cpp/instance_registry.h
+++ b/chromium/components/services/app_service/public/cpp/instance_registry.h
@@ -94,14 +94,14 @@ class InstanceRegistry {
// Return windows for the |app_id|.
std::set<aura::Window*> GetWindows(const std::string& app_id);
- // Return the state for the |window|.
- InstanceState GetState(aura::Window* window) const;
+ // Return the state for the |instance_key|.
+ InstanceState GetState(const Instance::InstanceKey& instance_key) const;
- // Return the shelf id for the |window|.
- ash::ShelfID GetShelfId(aura::Window* window) const;
+ // Return the shelf id for the |instance_key|.
+ ash::ShelfID GetShelfId(const Instance::InstanceKey& instance_key) const;
- // Return true if there is an instance for the |window|.
- bool Exists(aura::Window* window) const;
+ // Return true if there is an instance for the |instance_key|.
+ bool Exists(const Instance::InstanceKey& instance_key) const;
// Calls f, a void-returning function whose arguments are (const
// apps::InstanceUpdate&), on each window in the instance_registry.
@@ -128,7 +128,7 @@ class InstanceRegistry {
// Calls f, a void-returning function whose arguments are (const
// apps::InstanceUpdate&), on the instance in the instance_registry with the
- // given window. It will return true (and call f) if there is such an
+ // given instance_key. It will return true (and call f) if there is such an
// instance, otherwise it will return false (and not call f). The
// InstanceUpdate argument to f has the same semantics as for ForEachInstance,
// above.
@@ -136,10 +136,11 @@ class InstanceRegistry {
// f must be synchronous, and if it asynchronously calls ForOneInstance again,
// it's not guaranteed to see a consistent state.
template <typename FunctionType>
- bool ForOneInstance(const aura::Window* window, FunctionType f) {
+ bool ForOneInstance(const Instance::InstanceKey& instance_key,
+ FunctionType f) {
DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
- auto s_iter = states_.find(window);
+ auto s_iter = states_.find(instance_key);
apps::Instance* state =
(s_iter != states_.end()) ? s_iter->second.get() : nullptr;
if (state) {
@@ -167,12 +168,14 @@ class InstanceRegistry {
// exactly once, and deltas_pending_ will stay empty.
bool in_progress_ = false;
- // Maps from window to the latest state: the "sum" of all previous deltas.
- std::map<const aura::Window*, InstancePtr> states_;
+ // Maps from instance key to the latest state: the "sum" of all previous
+ // deltas.
+ std::map<const Instance::InstanceKey, InstancePtr> states_;
Instances deltas_pending_;
- // Maps from app id to app windows.
- std::map<const std::string, std::set<aura::Window*>> app_id_to_app_windows_;
+ // Maps from app id to app instance key.
+ std::map<const std::string, std::set<const Instance::InstanceKey>>
+ app_id_to_app_instance_key_;
SEQUENCE_CHECKER(my_sequence_checker_);
};
diff --git a/chromium/components/services/app_service/public/cpp/instance_registry_unittest.cc b/chromium/components/services/app_service/public/cpp/instance_registry_unittest.cc
index 49120032d2c..07db407b001 100644
--- a/chromium/components/services/app_service/public/cpp/instance_registry_unittest.cc
+++ b/chromium/components/services/app_service/public/cpp/instance_registry_unittest.cc
@@ -20,8 +20,8 @@ class InstanceRegistryTest : public testing::Test,
aura::Window* window,
apps::InstanceState state = apps::InstanceState::kUnknown,
base::Time time = base::Time()) {
- std::unique_ptr<apps::Instance> instance =
- std::make_unique<apps::Instance>(app_id, window);
+ std::unique_ptr<apps::Instance> instance = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(window));
instance->UpdateState(state, time);
return instance;
}
@@ -35,7 +35,7 @@ class InstanceRegistryTest : public testing::Test,
apps::InstanceState GetState(apps::InstanceRegistry& instance_registry,
aura::Window* window) {
- return instance_registry.GetState(window);
+ return instance_registry.GetState(apps::Instance::InstanceKey(window));
}
// apps::InstanceRegistry::Observer overrides.
@@ -102,7 +102,8 @@ class InstanceRecursiveObserver : public apps::InstanceRegistry::Observer {
});
EXPECT_TRUE(instance_registry_->ForOneInstance(
- outer.Window(), [&outer](const apps::InstanceUpdate& inner) {
+ apps::Instance::InstanceKey(outer.Window()),
+ [&outer](const apps::InstanceUpdate& inner) {
ExpectEq(outer, inner);
}));
@@ -230,7 +231,8 @@ TEST_F(InstanceRegistryTest, ForEachInstance) {
bool found_window4 = false;
EXPECT_TRUE(instance_registry.ForOneInstance(
- &window4, [&found_window4](const apps::InstanceUpdate& update) {
+ apps::Instance::InstanceKey(&window4),
+ [&found_window4](const apps::InstanceUpdate& update) {
found_window4 = true;
EXPECT_EQ("c", update.AppId());
}));
@@ -240,7 +242,8 @@ TEST_F(InstanceRegistryTest, ForEachInstance) {
aura::Window window5(nullptr);
window5.Init(ui::LAYER_NOT_DRAWN);
EXPECT_FALSE(instance_registry.ForOneInstance(
- &window5, [&found_window5](const apps::InstanceUpdate& update) {
+ apps::Instance::InstanceKey(&window5),
+ [&found_window5](const apps::InstanceUpdate& update) {
found_window5 = true;
}));
EXPECT_FALSE(found_window5);
@@ -370,7 +373,8 @@ TEST_F(InstanceRegistryTest, WholeProcessForOneWindow) {
bool found_window = false;
EXPECT_FALSE(instance_registry.ForOneInstance(
- &window, [&found_window](const apps::InstanceUpdate& update) {
+ apps::Instance::InstanceKey(&window),
+ [&found_window](const apps::InstanceUpdate& update) {
found_window = true;
}));
EXPECT_FALSE(found_window);
@@ -385,7 +389,8 @@ TEST_F(InstanceRegistryTest, WholeProcessForOneWindow) {
found_window = false;
EXPECT_TRUE(instance_registry.ForOneInstance(
- &window, [&found_window](const apps::InstanceUpdate& update) {
+ apps::Instance::InstanceKey(&window),
+ [&found_window](const apps::InstanceUpdate& update) {
found_window = true;
}));
EXPECT_TRUE(found_window);
@@ -472,28 +477,32 @@ TEST_F(InstanceRegistryTest, Recursive) {
bool found_window = false;
EXPECT_FALSE(instance_registry.ForOneInstance(
- &window2, [&found_window](const apps::InstanceUpdate& update) {
+ apps::Instance::InstanceKey(&window2),
+ [&found_window](const apps::InstanceUpdate& update) {
found_window = true;
}));
EXPECT_FALSE(found_window);
found_window = false;
EXPECT_FALSE(instance_registry.ForOneInstance(
- &window4, [&found_window](const apps::InstanceUpdate& update) {
+ apps::Instance::InstanceKey(&window4),
+ [&found_window](const apps::InstanceUpdate& update) {
found_window = true;
}));
EXPECT_FALSE(found_window);
found_window = false;
EXPECT_FALSE(instance_registry.ForOneInstance(
- &window3, [&found_window](const apps::InstanceUpdate& update) {
+ apps::Instance::InstanceKey(&window3),
+ [&found_window](const apps::InstanceUpdate& update) {
found_window = true;
}));
EXPECT_FALSE(found_window);
found_window = false;
EXPECT_FALSE(instance_registry.ForOneInstance(
- &window1, [&found_window](const apps::InstanceUpdate& update) {
+ apps::Instance::InstanceKey(&window1),
+ [&found_window](const apps::InstanceUpdate& update) {
found_window = true;
}));
EXPECT_FALSE(found_window);
@@ -508,7 +517,8 @@ TEST_F(InstanceRegistryTest, Recursive) {
found_window = false;
EXPECT_TRUE(instance_registry.ForOneInstance(
- &window2, [&found_window](const apps::InstanceUpdate& update) {
+ apps::Instance::InstanceKey(&window2),
+ [&found_window](const apps::InstanceUpdate& update) {
found_window = true;
}));
EXPECT_TRUE(found_window);
diff --git a/chromium/components/services/app_service/public/cpp/instance_update.cc b/chromium/components/services/app_service/public/cpp/instance_update.cc
index afc29179952..0d27f4057bd 100644
--- a/chromium/components/services/app_service/public/cpp/instance_update.cc
+++ b/chromium/components/services/app_service/public/cpp/instance_update.cc
@@ -17,10 +17,10 @@ void InstanceUpdate::Merge(Instance* state, const Instance* delta) {
return;
}
if ((delta->AppId() != state->AppId()) ||
- delta->Window() != state->Window()) {
- LOG(ERROR) << "inconsistent (app_id, window): (" << delta->AppId() << ", "
- << delta->Window() << ") vs (" << state->AppId() << ", "
- << state->Window() << ") ";
+ delta->GetInstanceKey() != state->GetInstanceKey()) {
+ LOG(ERROR) << "inconsistent (app_id, instance_key): (" << delta->AppId()
+ << ", " << delta->GetInstanceKey() << ") vs (" << state->AppId()
+ << ", " << state->GetInstanceKey() << ") ";
DCHECK(false);
return;
}
@@ -52,10 +52,10 @@ bool InstanceUpdate::Equals(const Instance* state, const Instance* delta) {
}
if ((delta->AppId() != state->AppId()) ||
- delta->Window() != state->Window()) {
- LOG(ERROR) << "inconsistent (app_id, window): (" << delta->AppId() << ", "
- << delta->Window() << ") vs (" << state->AppId() << ", "
- << state->Window() << ") ";
+ delta->GetInstanceKey() != state->GetInstanceKey()) {
+ LOG(ERROR) << "inconsistent (app_id, instance_key): (" << delta->AppId()
+ << ", " << delta->GetInstanceKey() << ") vs (" << state->AppId()
+ << ", " << state->GetInstanceKey() << ") ";
DCHECK(false);
return false;
}
@@ -81,7 +81,7 @@ InstanceUpdate::InstanceUpdate(Instance* state, Instance* delta)
DCHECK(state_ || delta_);
if (state_ && delta_) {
DCHECK(state_->AppId() == delta->AppId());
- DCHECK(state_->Window() == delta->Window());
+ DCHECK(state_->GetInstanceKey() == delta->GetInstanceKey());
}
}
@@ -103,7 +103,11 @@ const std::string& InstanceUpdate::AppId() const {
}
aura::Window* InstanceUpdate::Window() const {
- return delta_ ? delta_->Window() : state_->Window();
+ return InstanceKey().Window();
+}
+
+const Instance::InstanceKey& InstanceUpdate::InstanceKey() const {
+ return delta_ ? delta_->GetInstanceKey() : state_->GetInstanceKey();
}
const std::string& InstanceUpdate::LaunchId() const {
diff --git a/chromium/components/services/app_service/public/cpp/instance_update.h b/chromium/components/services/app_service/public/cpp/instance_update.h
index 376a869ad66..3bd9a9a334d 100644
--- a/chromium/components/services/app_service/public/cpp/instance_update.h
+++ b/chromium/components/services/app_service/public/cpp/instance_update.h
@@ -64,6 +64,8 @@ class InstanceUpdate {
aura::Window* Window() const;
+ const Instance::InstanceKey& InstanceKey() const;
+
const std::string& LaunchId() const;
bool LaunchIdChanged() const;
diff --git a/chromium/components/services/app_service/public/cpp/instance_update_unittest.cc b/chromium/components/services/app_service/public/cpp/instance_update_unittest.cc
index 67a507ed819..57e307ac597 100644
--- a/chromium/components/services/app_service/public/cpp/instance_update_unittest.cc
+++ b/chromium/components/services/app_service/public/cpp/instance_update_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "components/services/app_service/public/cpp/instance_update.h"
+#include "base/strings/string_util.h"
#include "chrome/test/base/testing_profile.h"
#include "components/services/app_service/public/cpp/instance.h"
#include "content/public/test/browser_task_environment.h"
@@ -108,8 +109,8 @@ class InstanceUpdateTest : public testing::Test {
TEST_F(InstanceUpdateTest, StateIsNonNull) {
aura::Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
- std::unique_ptr<apps::Instance> state =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> state = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
EXPECT_TRUE(apps::InstanceUpdate::Equals(state.get(), nullptr));
TestInstanceUpdate(state.get(), nullptr);
}
@@ -117,8 +118,8 @@ TEST_F(InstanceUpdateTest, StateIsNonNull) {
TEST_F(InstanceUpdateTest, DeltaIsNonNull) {
aura::Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
- std::unique_ptr<apps::Instance> delta =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> delta = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
EXPECT_FALSE(apps::InstanceUpdate::Equals(nullptr, delta.get()));
TestInstanceUpdate(nullptr, delta.get());
}
@@ -126,10 +127,10 @@ TEST_F(InstanceUpdateTest, DeltaIsNonNull) {
TEST_F(InstanceUpdateTest, BothAreNonNull) {
aura::Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
- std::unique_ptr<apps::Instance> state =
- std::make_unique<apps::Instance>(app_id, &window);
- std::unique_ptr<apps::Instance> delta =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> state = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
+ std::unique_ptr<apps::Instance> delta = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
EXPECT_TRUE(apps::InstanceUpdate::Equals(state.get(), delta.get()));
TestInstanceUpdate(state.get(), delta.get());
}
@@ -137,10 +138,10 @@ TEST_F(InstanceUpdateTest, BothAreNonNull) {
TEST_F(InstanceUpdateTest, LaunchIdIsUpdated) {
aura::Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
- std::unique_ptr<apps::Instance> state =
- std::make_unique<apps::Instance>(app_id, &window);
- std::unique_ptr<apps::Instance> delta =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> state = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
+ std::unique_ptr<apps::Instance> delta = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
delta->SetLaunchId("abc");
EXPECT_FALSE(apps::InstanceUpdate::Equals(state.get(), delta.get()));
}
@@ -148,21 +149,21 @@ TEST_F(InstanceUpdateTest, LaunchIdIsUpdated) {
TEST_F(InstanceUpdateTest, LaunchIdIsNotUpdated) {
aura::Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
- std::unique_ptr<apps::Instance> state =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> state = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
state->SetLaunchId("abc");
- std::unique_ptr<apps::Instance> delta =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> delta = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
EXPECT_TRUE(apps::InstanceUpdate::Equals(state.get(), delta.get()));
}
TEST_F(InstanceUpdateTest, StateIsUpdated) {
aura::Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
- std::unique_ptr<apps::Instance> state =
- std::make_unique<apps::Instance>(app_id, &window);
- std::unique_ptr<apps::Instance> delta =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> state = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
+ std::unique_ptr<apps::Instance> delta = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
delta->UpdateState(apps::InstanceState::kStarted, base::Time::Now());
EXPECT_FALSE(apps::InstanceUpdate::Equals(state.get(), delta.get()));
}
@@ -170,23 +171,23 @@ TEST_F(InstanceUpdateTest, StateIsUpdated) {
TEST_F(InstanceUpdateTest, StateIsNotUpdated) {
aura::Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
- std::unique_ptr<apps::Instance> state =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> state = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
state->UpdateState(apps::InstanceState::kStarted, base::Time::Now());
- std::unique_ptr<apps::Instance> delta =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> delta = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
EXPECT_TRUE(apps::InstanceUpdate::Equals(state.get(), delta.get()));
}
TEST_F(InstanceUpdateTest, BothLaunchAndStateIsUpdated) {
aura::Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
- std::unique_ptr<apps::Instance> state =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> state = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
state->SetLaunchId("aaa");
state->UpdateState(apps::InstanceState::kStarted, base::Time::Now());
- std::unique_ptr<apps::Instance> delta =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> delta = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
delta->SetLaunchId("bbb");
delta->UpdateState(apps::InstanceState::kRunning, base::Time::Now());
EXPECT_FALSE(apps::InstanceUpdate::Equals(state.get(), delta.get()));
@@ -195,10 +196,10 @@ TEST_F(InstanceUpdateTest, BothLaunchAndStateIsUpdated) {
TEST_F(InstanceUpdateTest, BrowserContextIsUpdated) {
aura::Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
- std::unique_ptr<apps::Instance> state =
- std::make_unique<apps::Instance>(app_id, &window);
- std::unique_ptr<apps::Instance> delta =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> state = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
+ std::unique_ptr<apps::Instance> delta = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
delta->SetBrowserContext(&profile_);
EXPECT_FALSE(apps::InstanceUpdate::Equals(state.get(), delta.get()));
}
@@ -206,10 +207,10 @@ TEST_F(InstanceUpdateTest, BrowserContextIsUpdated) {
TEST_F(InstanceUpdateTest, BrowserContextIsNotUpdated) {
aura::Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
- std::unique_ptr<apps::Instance> state =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> state = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
state->SetBrowserContext(&profile_);
- std::unique_ptr<apps::Instance> delta =
- std::make_unique<apps::Instance>(app_id, &window);
+ std::unique_ptr<apps::Instance> delta = std::make_unique<apps::Instance>(
+ app_id, std::make_unique<apps::Instance::InstanceKey>(&window));
EXPECT_TRUE(apps::InstanceUpdate::Equals(state.get(), delta.get()));
}
diff --git a/chromium/components/services/app_service/public/cpp/intent_filter_util.cc b/chromium/components/services/app_service/public/cpp/intent_filter_util.cc
index f022171b067..b6e522cef39 100644
--- a/chromium/components/services/app_service/public/cpp/intent_filter_util.cc
+++ b/chromium/components/services/app_service/public/cpp/intent_filter_util.cc
@@ -166,4 +166,51 @@ bool IsBrowserFilter(const apps::mojom::IntentFilterPtr& filter) {
return false;
}
+// This function returns all of the links that the given intent filter would
+// accept, to be used in listing all of the supported links for a given app.
+std::set<std::string> AppManagementGetSupportedLinks(
+ const apps::mojom::IntentFilterPtr& intent_filter) {
+ std::set<std::string> supported_links;
+ std::set<std::string> schemes;
+ std::set<std::string> hosts;
+
+ for (auto& condition : intent_filter->conditions) {
+ // For scheme conditions we add each value to the the |schemes| set.
+ if (condition->condition_type == apps::mojom::ConditionType::kScheme) {
+ for (auto& condition_value : condition->condition_values) {
+ // We only care about http and https schemes.
+ if (condition_value->value == url::kHttpScheme ||
+ condition_value->value == url::kHttpsScheme) {
+ schemes.insert(condition_value->value);
+ }
+ }
+
+ // There should only be one condition of type |kScheme| so if there
+ // aren't any http or https scheme values this indicates that no http or
+ // https scheme exists in the intent filter and thus we will have to
+ // return an empty list.
+ if (schemes.empty()) {
+ break;
+ }
+ }
+
+ // For host conditions we add each value to the the |hosts| set.
+ if (condition->condition_type != apps::mojom::ConditionType::kHost) {
+ for (auto& condition_value : condition->condition_values) {
+ hosts.insert(condition_value->value);
+ }
+ }
+ }
+
+ // Loop through all combinations of scheme and host and add to
+ // supported links.
+ for (auto& scheme : schemes) {
+ for (auto& host : hosts) {
+ supported_links.insert(scheme + url::kStandardSchemeSeparator + host);
+ }
+ }
+
+ return supported_links;
+}
+
} // namespace apps_util
diff --git a/chromium/components/services/app_service/public/cpp/intent_filter_util.h b/chromium/components/services/app_service/public/cpp/intent_filter_util.h
index 03977727dfd..0fc83fa7568 100644
--- a/chromium/components/services/app_service/public/cpp/intent_filter_util.h
+++ b/chromium/components/services/app_service/public/cpp/intent_filter_util.h
@@ -87,6 +87,10 @@ void UpgradeFilter(apps::mojom::IntentFilterPtr& filter);
// or http scheme.
bool IsBrowserFilter(const apps::mojom::IntentFilterPtr& filter);
+// Convert an intent filter to a list of its supported links.
+std::set<std::string> AppManagementGetSupportedLinks(
+ const apps::mojom::IntentFilterPtr& intent_filter);
+
} // namespace apps_util
#endif // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_INTENT_FILTER_UTIL_H_
diff --git a/chromium/components/services/app_service/public/cpp/intent_util.cc b/chromium/components/services/app_service/public/cpp/intent_util.cc
index d96c5e99e3f..c5af81177c9 100644
--- a/chromium/components/services/app_service/public/cpp/intent_util.cc
+++ b/chromium/components/services/app_service/public/cpp/intent_util.cc
@@ -10,9 +10,10 @@
#include "base/compiler_specific.h"
#include "base/containers/flat_map.h"
-#include "base/optional.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "base/values.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace {
@@ -35,7 +36,7 @@ const char kUiBypassedKey[] = "ui_bypassed";
const char kExtrasKey[] = "extras";
// Get the intent condition value based on the condition type.
-base::Optional<std::string> GetIntentConditionValueByType(
+absl::optional<std::string> GetIntentConditionValueByType(
apps::mojom::ConditionType condition_type,
const apps::mojom::IntentPtr& intent) {
switch (condition_type) {
@@ -43,16 +44,16 @@ base::Optional<std::string> GetIntentConditionValueByType(
return intent->action;
case apps::mojom::ConditionType::kScheme:
return intent->url.has_value()
- ? base::Optional<std::string>(intent->url->scheme())
- : base::nullopt;
+ ? absl::optional<std::string>(intent->url->scheme())
+ : absl::nullopt;
case apps::mojom::ConditionType::kHost:
return intent->url.has_value()
- ? base::Optional<std::string>(intent->url->host())
- : base::nullopt;
+ ? absl::optional<std::string>(intent->url->host())
+ : absl::nullopt;
case apps::mojom::ConditionType::kPattern:
return intent->url.has_value()
- ? base::Optional<std::string>(intent->url->path())
- : base::nullopt;
+ ? absl::optional<std::string>(intent->url->path())
+ : absl::nullopt;
case apps::mojom::ConditionType::kMimeType:
return intent->mime_type;
}
@@ -246,7 +247,7 @@ bool ConditionValueMatches(
bool IntentMatchesCondition(const apps::mojom::IntentPtr& intent,
const apps::mojom::ConditionPtr& condition) {
- base::Optional<std::string> value_to_match =
+ absl::optional<std::string> value_to_match =
GetIntentConditionValueByType(condition->condition_type, intent);
if (!value_to_match.has_value()) {
return false;
@@ -449,15 +450,15 @@ base::Value ConvertIntentToValue(const apps::mojom::IntentPtr& intent) {
return intent_value;
}
-base::Optional<std::string> GetStringValueFromDict(
+absl::optional<std::string> GetStringValueFromDict(
const base::DictionaryValue& dict,
const std::string& key_name) {
if (!dict.HasKey(key_name))
- return base::nullopt;
+ return absl::nullopt;
const std::string* value = dict.FindStringKey(key_name);
if (!value || value->empty())
- return base::nullopt;
+ return absl::nullopt;
return *value;
}
@@ -468,7 +469,7 @@ apps::mojom::OptionalBool GetBoolValueFromDict(
if (!dict.HasKey(key_name))
return apps::mojom::OptionalBool::kUnknown;
- base::Optional<bool> value = dict.FindBoolKey(key_name);
+ absl::optional<bool> value = dict.FindBoolKey(key_name);
if (!value.has_value())
return apps::mojom::OptionalBool::kUnknown;
@@ -476,31 +477,31 @@ apps::mojom::OptionalBool GetBoolValueFromDict(
: apps::mojom::OptionalBool::kFalse;
}
-base::Optional<GURL> GetGurlValueFromDict(const base::DictionaryValue& dict,
+absl::optional<GURL> GetGurlValueFromDict(const base::DictionaryValue& dict,
const std::string& key_name) {
if (!dict.HasKey(key_name))
- return base::nullopt;
+ return absl::nullopt;
const std::string* url_spec = dict.FindStringKey(key_name);
if (!url_spec)
- return base::nullopt;
+ return absl::nullopt;
GURL url(*url_spec);
if (!url.is_valid())
- return base::nullopt;
+ return absl::nullopt;
return url;
}
-base::Optional<std::vector<::GURL>> GetFileUrlsFromDict(
+absl::optional<std::vector<::GURL>> GetFileUrlsFromDict(
const base::DictionaryValue& dict,
const std::string& key_name) {
if (!dict.HasKey(key_name))
- return base::nullopt;
+ return absl::nullopt;
const base::Value* value = dict.FindListKey(key_name);
if (!value || !value->is_list() || value->GetList().empty())
- return base::nullopt;
+ return absl::nullopt;
std::vector<::GURL> file_urls;
for (const auto& item : value->GetList()) {
@@ -511,15 +512,15 @@ base::Optional<std::vector<::GURL>> GetFileUrlsFromDict(
return file_urls;
}
-base::Optional<std::vector<std::string>> GetCategoriesFromDict(
+absl::optional<std::vector<std::string>> GetCategoriesFromDict(
const base::DictionaryValue& dict,
const std::string& key_name) {
if (!dict.HasKey(key_name))
- return base::nullopt;
+ return absl::nullopt;
const base::Value* value = dict.FindListKey(key_name);
if (!value || !value->is_list() || value->GetList().empty())
- return base::nullopt;
+ return absl::nullopt;
std::vector<std::string> categories;
for (const auto& item : value->GetList())
@@ -528,15 +529,15 @@ base::Optional<std::vector<std::string>> GetCategoriesFromDict(
return categories;
}
-base::Optional<base::flat_map<std::string, std::string>> GetExtrasFromDict(
+absl::optional<base::flat_map<std::string, std::string>> GetExtrasFromDict(
const base::DictionaryValue& dict,
const std::string& key_name) {
if (!dict.HasKey(key_name))
- return base::nullopt;
+ return absl::nullopt;
const base::Value* value = dict.FindDictKey(key_name);
if (!value || !value->is_dict())
- return base::nullopt;
+ return absl::nullopt;
base::flat_map<std::string, std::string> extras;
for (const auto& pair : value->DictItems()) {
diff --git a/chromium/components/services/app_service/public/cpp/intent_util.h b/chromium/components/services/app_service/public/cpp/intent_util.h
index 1c2936f7b60..1b398e2caea 100644
--- a/chromium/components/services/app_service/public/cpp/intent_util.h
+++ b/chromium/components/services/app_service/public/cpp/intent_util.h
@@ -13,6 +13,11 @@
#include "components/services/app_service/public/mojom/types.mojom.h"
#include "url/gurl.h"
+namespace base {
+class DictionaryValue;
+class Value;
+} // namespace base
+
namespace apps_util {
extern const char kIntentActionMain[];
@@ -102,7 +107,7 @@ base::Value ConvertIntentToValue(const apps::mojom::IntentPtr& intent);
// Gets the string value from base::DictionaryValue, e.g. { "key": "value" }
// returns "value".
-base::Optional<std::string> GetStringValueFromDict(
+absl::optional<std::string> GetStringValueFromDict(
const base::DictionaryValue& dict,
const std::string& key_name);
@@ -114,12 +119,12 @@ apps::mojom::OptionalBool GetBoolValueFromDict(
// Gets GURL from base::DictionaryValue, e.g. { "url": "abc.com" } returns
// "abc.com".
-base::Optional<GURL> GetGurlValueFromDict(const base::DictionaryValue& dict,
+absl::optional<GURL> GetGurlValueFromDict(const base::DictionaryValue& dict,
const std::string& key_name);
// Gets std::vector<::GURL> from base::DictionaryValue, e.g. { "file_urls":
// "/abc, /a" } returns std::vector<::GURL>{"/abc, /a"}.
-base::Optional<std::vector<::GURL>> GetFileUrlsFromDict(
+absl::optional<std::vector<::GURL>> GetFileUrlsFromDict(
const base::DictionaryValue& dict,
const std::string& key_name);
diff --git a/chromium/components/services/app_service/public/cpp/intent_util_unittest.cc b/chromium/components/services/app_service/public/cpp/intent_util_unittest.cc
index 2c7dbf8905e..c664ea57239 100644
--- a/chromium/components/services/app_service/public/cpp/intent_util_unittest.cc
+++ b/chromium/components/services/app_service/public/cpp/intent_util_unittest.cc
@@ -4,6 +4,7 @@
#include "components/services/app_service/public/cpp/intent_util.h"
+#include "base/values.h"
#include "components/services/app_service/public/cpp/intent_filter_util.h"
#include "components/services/app_service/public/cpp/intent_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc b/chromium/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc
index bd4a30385bb..2ac2f54dd31 100644
--- a/chromium/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc
+++ b/chromium/components/services/app_service/public/cpp/preferred_apps_converter_unittest.cc
@@ -59,11 +59,11 @@ TEST_F(PreferredAppsConverterTest, ConvertSimpleEntry) {
auto preferred_apps_list = apps::ParseValueToPreferredApps(converted_value);
preferred_apps.Init();
- EXPECT_EQ(base::nullopt, preferred_apps.FindPreferredAppForUrl(filter_url));
+ EXPECT_EQ(absl::nullopt, preferred_apps.FindPreferredAppForUrl(filter_url));
preferred_apps.Init(preferred_apps_list);
EXPECT_EQ(kAppId1, preferred_apps.FindPreferredAppForUrl(filter_url));
GURL url_wrong_host = GURL("https://www.hahaha.com/");
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps.FindPreferredAppForUrl(url_wrong_host));
}
@@ -101,7 +101,7 @@ TEST_F(PreferredAppsConverterTest, ConvertSimpleEntryJson) {
" } ]"
"} ],"
"\"version\": 0}";
- base::Optional<base::Value> expected_output =
+ absl::optional<base::Value> expected_output =
base::JSONReader::Read(expected_output_string);
ASSERT_TRUE(expected_output);
EXPECT_EQ(expected_output.value(), converted_value);
@@ -148,7 +148,7 @@ TEST_F(PreferredAppsConverterTest, ConvertUpgradedSimpleEntryJson) {
" } ]"
"} ],"
"\"version\": 1}";
- base::Optional<base::Value> expected_output =
+ absl::optional<base::Value> expected_output =
base::JSONReader::Read(expected_output_string);
ASSERT_TRUE(expected_output);
EXPECT_EQ(expected_output.value(), converted_value);
@@ -178,7 +178,7 @@ TEST_F(PreferredAppsConverterTest, ParseSimpleEntryJson) {
" } ]"
" } ]"
"} ]";
- base::Optional<base::Value> test_value = base::JSONReader::Read(test_string);
+ absl::optional<base::Value> test_value = base::JSONReader::Read(test_string);
ASSERT_TRUE(test_value);
auto parsed_entry = apps::ParseValueToPreferredApps(test_value.value());
EXPECT_FALSE(apps::IsUpgradedForSharing(test_value.value()));
@@ -225,7 +225,7 @@ TEST_F(PreferredAppsConverterTest, ParseUpgradedSimpleEntryJson) {
" } ]"
"} ],"
"\"version\": 1}";
- base::Optional<base::Value> test_value = base::JSONReader::Read(test_string);
+ absl::optional<base::Value> test_value = base::JSONReader::Read(test_string);
ASSERT_TRUE(test_value);
auto parsed_entry = apps::ParseValueToPreferredApps(test_value.value());
EXPECT_TRUE(apps::IsUpgradedForSharing(test_value.value()));
@@ -266,7 +266,7 @@ TEST_F(PreferredAppsConverterTest, ParseJsonWithInvalidAppId) {
" } ]"
" } ]"
"} ]";
- base::Optional<base::Value> test_value = base::JSONReader::Read(test_key);
+ absl::optional<base::Value> test_value = base::JSONReader::Read(test_key);
ASSERT_TRUE(test_value);
auto parsed_entry = apps::ParseValueToPreferredApps(test_value.value());
EXPECT_TRUE(parsed_entry.empty());
@@ -324,7 +324,7 @@ TEST_F(PreferredAppsConverterTest, ParseJsonWithInvalidIntentFilter) {
" } ]"
" } ]"
"} ]";
- base::Optional<base::Value> test_value = base::JSONReader::Read(test_key);
+ absl::optional<base::Value> test_value = base::JSONReader::Read(test_key);
ASSERT_TRUE(test_value);
auto parsed_entry = apps::ParseValueToPreferredApps(test_value.value());
EXPECT_TRUE(parsed_entry.empty());
@@ -364,7 +364,7 @@ TEST_F(PreferredAppsConverterTest, ParseJsonWithInvalidConditionType) {
" } ]"
" } ]"
"} ]";
- base::Optional<base::Value> test_value = base::JSONReader::Read(test_key);
+ absl::optional<base::Value> test_value = base::JSONReader::Read(test_key);
ASSERT_TRUE(test_value);
auto parsed_entry = apps::ParseValueToPreferredApps(test_value.value());
EXPECT_TRUE(parsed_entry.empty());
@@ -422,7 +422,7 @@ TEST_F(PreferredAppsConverterTest, ParseJsonWithInvalidValues) {
" } ]"
" } ]"
"} ]";
- base::Optional<base::Value> test_value = base::JSONReader::Read(test_key);
+ absl::optional<base::Value> test_value = base::JSONReader::Read(test_key);
ASSERT_TRUE(test_value);
auto parsed_entry = apps::ParseValueToPreferredApps(test_value.value());
EXPECT_TRUE(parsed_entry.empty());
@@ -477,7 +477,7 @@ TEST_F(PreferredAppsConverterTest, ParseJsonWithInvalidMatchType) {
" } ]"
" } ]"
"} ]";
- base::Optional<base::Value> test_value = base::JSONReader::Read(test_key);
+ absl::optional<base::Value> test_value = base::JSONReader::Read(test_key);
ASSERT_TRUE(test_value);
auto parsed_entry = apps::ParseValueToPreferredApps(test_value.value());
EXPECT_TRUE(parsed_entry.empty());
@@ -535,7 +535,7 @@ TEST_F(PreferredAppsConverterTest, ParseJsonWithInvalidValue) {
" } ]"
" } ]"
"} ]";
- base::Optional<base::Value> test_value = base::JSONReader::Read(test_key);
+ absl::optional<base::Value> test_value = base::JSONReader::Read(test_key);
ASSERT_TRUE(test_value);
auto parsed_entry = apps::ParseValueToPreferredApps(test_value.value());
EXPECT_TRUE(parsed_entry.empty());
diff --git a/chromium/components/services/app_service/public/cpp/preferred_apps_list.cc b/chromium/components/services/app_service/public/cpp/preferred_apps_list.cc
index 8c6eb107436..96ce5585db7 100644
--- a/chromium/components/services/app_service/public/cpp/preferred_apps_list.cc
+++ b/chromium/components/services/app_service/public/cpp/preferred_apps_list.cc
@@ -21,14 +21,75 @@ void Clone(apps::PreferredAppsList::PreferredApps& source,
}
}
+// Given an intent filter, decide if the filter matches the required parameters
+// that determine that a filter has a supported link.
+bool IsSupportedLink(const apps::mojom::IntentFilterPtr& intent_filter) {
+ bool scheme = false;
+ bool host = false;
+ for (auto& condition : intent_filter->conditions) {
+ if (condition->condition_type == apps::mojom::ConditionType::kScheme) {
+ for (auto& condition_value : condition->condition_values) {
+ if (condition_value->value == "http" ||
+ condition_value->value == "https") {
+ scheme = true;
+ break;
+ }
+ }
+ } else if (condition->condition_type == apps::mojom::ConditionType::kHost) {
+ host = true;
+ }
+
+ if (scheme && host) {
+ break;
+ }
+ }
+
+ return scheme && host;
+}
+
} // namespace
namespace apps {
+PreferredAppsList::Observer::Observer(PreferredAppsList* list) {
+ Observe(list);
+}
+
+PreferredAppsList::Observer::Observer() = default;
+
+PreferredAppsList::Observer::~Observer() {
+ if (list_) {
+ list_->RemoveObserver(this);
+ }
+}
+
+void PreferredAppsList::Observer::Observe(PreferredAppsList* list) {
+ if (list == list_) {
+ // Early exit to avoid infinite loops if we're in the middle of a callback.
+ return;
+ }
+ if (list_) {
+ list_->RemoveObserver(this);
+ }
+ list_ = list;
+ if (list_) {
+ list_->AddObserver(this);
+ }
+}
+
PreferredAppsList::PreferredAppsList() = default;
PreferredAppsList::~PreferredAppsList() = default;
-base::Optional<std::string> PreferredAppsList::FindPreferredAppForUrl(
+void PreferredAppsList::AddObserver(Observer* observer) {
+ DCHECK(observer);
+ observers_.AddObserver(observer);
+}
+
+void PreferredAppsList::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+absl::optional<std::string> PreferredAppsList::FindPreferredAppForUrl(
const GURL& url) {
auto intent = apps_util::CreateIntentFromUrl(url);
return FindPreferredAppForIntent(intent);
@@ -65,35 +126,59 @@ apps::mojom::ReplacedAppPreferencesPtr PreferredAppsList::AddPreferredApp(
auto new_preferred_app =
apps::mojom::PreferredApp::New(intent_filter->Clone(), app_id);
preferred_apps_.push_back(std::move(new_preferred_app));
+
+ if (IsSupportedLink(intent_filter)) {
+ for (auto& obs : observers_) {
+ obs.OnPreferredAppChanged(app_id, true);
+ }
+ }
return replaced_app_preferences;
}
-void PreferredAppsList::DeletePreferredApp(
+bool PreferredAppsList::DeletePreferredApp(
const std::string& app_id,
const apps::mojom::IntentFilterPtr& intent_filter) {
// Go through the list and see if there are overlapped intent filters with the
// same app id in the list. If there are, delete the entry.
+ bool found = false;
auto iter = preferred_apps_.begin();
while (iter != preferred_apps_.end()) {
if ((*iter)->app_id == app_id &&
apps_util::FiltersHaveOverlap((*iter)->intent_filter, intent_filter)) {
+ found = true;
iter = preferred_apps_.erase(iter);
} else {
iter++;
}
}
+
+ if (IsSupportedLink(intent_filter)) {
+ for (auto& obs : observers_) {
+ obs.OnPreferredAppChanged(app_id, false);
+ }
+ }
+
+ return found;
}
-void PreferredAppsList::DeleteAppId(const std::string& app_id) {
+bool PreferredAppsList::DeleteAppId(const std::string& app_id) {
+ bool found = false;
auto iter = preferred_apps_.begin();
// Go through the list and delete the entry with requested app_id.
while (iter != preferred_apps_.end()) {
if ((*iter)->app_id == app_id) {
+ found = true;
iter = preferred_apps_.erase(iter);
} else {
iter++;
}
}
+
+ for (auto& obs : observers_) {
+ obs.OnPreferredAppChanged(app_id, false);
+ }
+
+ return found;
}
void PreferredAppsList::Init() {
@@ -103,6 +188,15 @@ void PreferredAppsList::Init() {
void PreferredAppsList::Init(PreferredApps& preferred_apps) {
Clone(preferred_apps, &preferred_apps_);
+ auto iter = preferred_apps_.begin();
+ while (iter != preferred_apps_.end()) {
+ if (IsSupportedLink((*iter)->intent_filter)) {
+ for (auto& obs : observers_) {
+ obs.OnPreferredAppChanged((*iter)->app_id, true);
+ }
+ }
+ iter++;
+ }
initialized_ = true;
}
@@ -121,9 +215,9 @@ const PreferredAppsList::PreferredApps& PreferredAppsList::GetReference()
return preferred_apps_;
}
-base::Optional<std::string> PreferredAppsList::FindPreferredAppForIntent(
+absl::optional<std::string> PreferredAppsList::FindPreferredAppForIntent(
const apps::mojom::IntentPtr& intent) {
- base::Optional<std::string> best_match_app_id = base::nullopt;
+ absl::optional<std::string> best_match_app_id = absl::nullopt;
int best_match_level = apps_util::IntentFilterMatchLevel::kNone;
for (auto& preferred_app : preferred_apps_) {
if (apps_util::IntentMatchesFilter(intent, preferred_app->intent_filter)) {
@@ -143,4 +237,16 @@ size_t PreferredAppsList::GetEntrySize() {
return preferred_apps_.size();
}
+bool PreferredAppsList::IsPreferredAppForSupportedLinks(
+ const std::string& app_id) {
+ for (const auto& preferred_app : preferred_apps_) {
+ if (preferred_app->app_id == app_id &&
+ IsSupportedLink(preferred_app->intent_filter)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace apps
diff --git a/chromium/components/services/app_service/public/cpp/preferred_apps_list.h b/chromium/components/services/app_service/public/cpp/preferred_apps_list.h
index b3989e88d40..2dd109294fd 100644
--- a/chromium/components/services/app_service/public/cpp/preferred_apps_list.h
+++ b/chromium/components/services/app_service/public/cpp/preferred_apps_list.h
@@ -9,8 +9,10 @@
#include <string>
#include <vector>
-#include "base/optional.h"
+#include "base/observer_list.h"
+#include "base/observer_list_types.h"
#include "components/services/app_service/public/mojom/types.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -20,20 +22,58 @@ namespace apps {
// an list of |intent_filter| vs. app_id.
class PreferredAppsList {
public:
+ class Observer : public base::CheckedObserver {
+ public:
+ virtual void OnPreferredAppChanged(const std::string& app_id,
+ bool is_preferred_app) = 0;
+
+ // Called when the PreferredAppsList object (the thing that this observer
+ // observes) will be destroyed. In response, the observer, |this|, should
+ // call "cache->RemoveObserver(this)", whether directly or indirectly (e.g.
+ // via base::ScopedObservation::Remove or via Observe(nullptr)).
+ virtual void OnPreferredAppsListWillBeDestroyed(
+ PreferredAppsList* list) = 0;
+
+ Observer(const Observer&) = delete;
+ Observer& operator=(const Observer&) = delete;
+
+ protected:
+ // Use this constructor when the observer |this| is tied to a single
+ // PreferredAppsList for its entire lifetime, or until the observee (the
+ // PreferredAppsList) is destroyed, whichever comes first.
+ explicit Observer(PreferredAppsList* list);
+
+ // Use this constructor when the observer |this| wants to observe a
+ // PreferredAppsList for part of its lifetime. It can then call Observe() to
+ // start and stop observing.
+ Observer();
+ ~Observer() override;
+
+ // Start observing a different PreferredAppsList. |cache| may be nullptr,
+ // meaning to stop observing.
+ void Observe(PreferredAppsList* list);
+
+ private:
+ PreferredAppsList* list_ = nullptr;
+ };
+
PreferredAppsList();
~PreferredAppsList();
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
PreferredAppsList(const PreferredAppsList&) = delete;
PreferredAppsList& operator=(const PreferredAppsList&) = delete;
using PreferredApps = std::vector<apps::mojom::PreferredAppPtr>;
// Find preferred app id for an |intent|.
- base::Optional<std::string> FindPreferredAppForIntent(
+ absl::optional<std::string> FindPreferredAppForIntent(
const apps::mojom::IntentPtr& intent);
// Find preferred app id for an |url|.
- base::Optional<std::string> FindPreferredAppForUrl(const GURL& url);
+ absl::optional<std::string> FindPreferredAppForUrl(const GURL& url);
// Add a preferred app for an |intent_filter|, and returns a group of
// |app_ids| that is no longer preferred app of their corresponding
@@ -43,11 +83,13 @@ class PreferredAppsList {
const apps::mojom::IntentFilterPtr& intent_filter);
// Delete a preferred app for an |intent_filter| with the same |app_id|.
- void DeletePreferredApp(const std::string& app_id,
+ // Returns |true| if |app_id| was found in the list of preferred apps.
+ bool DeletePreferredApp(const std::string& app_id,
const apps::mojom::IntentFilterPtr& intent_filter);
// Delete all settings for an |app_id|.
- void DeleteAppId(const std::string& app_id);
+ // Returns |true| if |app_id| was found in the list of preferred apps.
+ bool DeleteAppId(const std::string& app_id);
// Initialize the preferred app with empty list or existing |preferred_apps|;
void Init();
@@ -63,8 +105,11 @@ class PreferredAppsList {
// Get the entry size of the preferred app list.
size_t GetEntrySize();
+ bool IsPreferredAppForSupportedLinks(const std::string& app_id);
+
private:
PreferredApps preferred_apps_;
+ base::ObserverList<Observer> observers_;
bool initialized_ = false;
};
diff --git a/chromium/components/services/app_service/public/cpp/preferred_apps_list_unittest.cc b/chromium/components/services/app_service/public/cpp/preferred_apps_list_unittest.cc
index be050a84108..71ffd81c4b2 100644
--- a/chromium/components/services/app_service/public/cpp/preferred_apps_list_unittest.cc
+++ b/chromium/components/services/app_service/public/cpp/preferred_apps_list_unittest.cc
@@ -51,15 +51,15 @@ TEST_F(PreferredAppListTest, AddPreferredAppForURL) {
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(url_in_scope));
GURL url_wrong_scheme = GURL("tel://www.google.com/");
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(url_wrong_scheme));
GURL url_wrong_host = GURL("https://www.hahaha.com/");
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(url_wrong_host));
GURL url_not_in_scope = GURL("https://www.google.com/a");
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(url_not_in_scope));
}
@@ -73,7 +73,7 @@ TEST_F(PreferredAppListTest, TopLayerFilters) {
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(url_in_scope));
GURL url_not_in_scope = GURL("http://www.google.com");
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(url_not_in_scope));
}
@@ -99,7 +99,7 @@ TEST_F(PreferredAppListTest, MixLayerFilters) {
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(url_1));
EXPECT_EQ(kAppId2, preferred_apps_.FindPreferredAppForUrl(url_2));
EXPECT_EQ(kAppId3, preferred_apps_.FindPreferredAppForUrl(url_3));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(url_out_scope));
}
@@ -144,9 +144,9 @@ TEST_F(PreferredAppListTest, MultipleConditionValues) {
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(url_https));
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(url_http));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(url_http_out_of_scope));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(url_wrong_scheme));
}
@@ -171,7 +171,7 @@ TEST_F(PreferredAppListTest, DifferentPatterns) {
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(url_1));
EXPECT_EQ(kAppId2, preferred_apps_.FindPreferredAppForUrl(url_2));
EXPECT_EQ(kAppId3, preferred_apps_.FindPreferredAppForUrl(url_3));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(url_out_scope));
}
@@ -212,7 +212,7 @@ TEST_F(PreferredAppListTest, OverlapPreferredApp) {
apps_util::MakeConditionValue(filter_url_2.host(),
apps::mojom::PatternMatchType::kNone));
preferred_apps_.AddPreferredApp(kAppId2, intent_filter_2);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_1));
EXPECT_EQ(kAppId2, preferred_apps_.FindPreferredAppForUrl(filter_url_2));
EXPECT_EQ(kAppId2, preferred_apps_.FindPreferredAppForUrl(filter_url_3));
@@ -310,7 +310,7 @@ TEST_F(PreferredAppListTest, DeletePreferredAppForURL) {
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(filter_url));
preferred_apps_.DeletePreferredApp(kAppId1, intent_filter);
- EXPECT_EQ(base::nullopt, preferred_apps_.FindPreferredAppForUrl(filter_url));
+ EXPECT_EQ(absl::nullopt, preferred_apps_.FindPreferredAppForUrl(filter_url));
}
// Test for preferred app with filter that does not have all condition
@@ -323,7 +323,7 @@ TEST_F(PreferredAppListTest, DeleteForTopLayerFilters) {
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(url_in_scope));
preferred_apps_.DeletePreferredApp(kAppId1, intent_filter);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(url_in_scope));
}
@@ -344,8 +344,8 @@ TEST_F(PreferredAppListTest, DeleteMultipleConditionValues) {
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(url_http));
preferred_apps_.DeletePreferredApp(kAppId1, intent_filter);
- EXPECT_EQ(base::nullopt, preferred_apps_.FindPreferredAppForUrl(url_https));
- EXPECT_EQ(base::nullopt, preferred_apps_.FindPreferredAppForUrl(url_http));
+ EXPECT_EQ(absl::nullopt, preferred_apps_.FindPreferredAppForUrl(url_https));
+ EXPECT_EQ(absl::nullopt, preferred_apps_.FindPreferredAppForUrl(url_http));
}
// Test for more than one pattern available, we can delete the filter.
@@ -370,14 +370,14 @@ TEST_F(PreferredAppListTest, DeleteDifferentPatterns) {
EXPECT_EQ(kAppId3, preferred_apps_.FindPreferredAppForUrl(url_3));
preferred_apps_.DeletePreferredApp(kAppId1, intent_filter_literal);
- EXPECT_EQ(base::nullopt, preferred_apps_.FindPreferredAppForUrl(url_1));
+ EXPECT_EQ(absl::nullopt, preferred_apps_.FindPreferredAppForUrl(url_1));
EXPECT_EQ(kAppId2, preferred_apps_.FindPreferredAppForUrl(url_2));
EXPECT_EQ(kAppId3, preferred_apps_.FindPreferredAppForUrl(url_3));
preferred_apps_.DeletePreferredApp(kAppId2, intent_filter_prefix);
- EXPECT_EQ(base::nullopt, preferred_apps_.FindPreferredAppForUrl(url_2));
+ EXPECT_EQ(absl::nullopt, preferred_apps_.FindPreferredAppForUrl(url_2));
EXPECT_EQ(kAppId3, preferred_apps_.FindPreferredAppForUrl(url_3));
preferred_apps_.DeletePreferredApp(kAppId3, intent_filter_glob);
- EXPECT_EQ(base::nullopt, preferred_apps_.FindPreferredAppForUrl(url_3));
+ EXPECT_EQ(absl::nullopt, preferred_apps_.FindPreferredAppForUrl(url_3));
}
// Test that can delete properly for super set filters. E.g. the filter
@@ -400,7 +400,7 @@ TEST_F(PreferredAppListTest, DeleteForNotCompletedFilter) {
preferred_apps_.DeletePreferredApp(kAppId1, intent_filter_to_delete);
- EXPECT_EQ(base::nullopt, preferred_apps_.FindPreferredAppForUrl(url));
+ EXPECT_EQ(absl::nullopt, preferred_apps_.FindPreferredAppForUrl(url));
}
// Test that when there are more than one entry has overlap filter.
@@ -447,13 +447,13 @@ TEST_F(PreferredAppListTest, DeleteOverlapFilters) {
// Filter 2 has overlap with both filter 1 and 3, delete this should remove
// all entries.
preferred_apps_.DeletePreferredApp(kAppId1, intent_filter_2);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_1));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_2));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_3));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_4));
}
@@ -467,7 +467,7 @@ TEST_F(PreferredAppListTest, DeleteAppIdForOneFilter) {
preferred_apps_.DeleteAppId(kAppId1);
- EXPECT_EQ(base::nullopt, preferred_apps_.FindPreferredAppForUrl(filter_url));
+ EXPECT_EQ(absl::nullopt, preferred_apps_.FindPreferredAppForUrl(filter_url));
}
// Test that when multiple filters set to the same app id, DeleteAppId() can
@@ -493,11 +493,11 @@ TEST_F(PreferredAppListTest, DeleteAppIdForMultipleFilters) {
preferred_apps_.DeleteAppId(kAppId1);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_1));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_2));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_3));
}
@@ -518,8 +518,8 @@ TEST_F(PreferredAppListTest, DeleteAppIdForMultipleConditionValues) {
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(url_http));
preferred_apps_.DeleteAppId(kAppId1);
- EXPECT_EQ(base::nullopt, preferred_apps_.FindPreferredAppForUrl(url_https));
- EXPECT_EQ(base::nullopt, preferred_apps_.FindPreferredAppForUrl(url_http));
+ EXPECT_EQ(absl::nullopt, preferred_apps_.FindPreferredAppForUrl(url_https));
+ EXPECT_EQ(absl::nullopt, preferred_apps_.FindPreferredAppForUrl(url_http));
}
// Test that for multiple filters set to different app ids, DeleteAppId() only
@@ -562,24 +562,24 @@ TEST_F(PreferredAppListTest, DeleteAppIdForMultipleAppIds) {
EXPECT_EQ(kAppId3, preferred_apps_.FindPreferredAppForUrl(filter_url_6));
preferred_apps_.DeleteAppId(kAppId1);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_1));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_2));
EXPECT_EQ(kAppId2, preferred_apps_.FindPreferredAppForUrl(filter_url_3));
EXPECT_EQ(kAppId2, preferred_apps_.FindPreferredAppForUrl(filter_url_4));
EXPECT_EQ(kAppId3, preferred_apps_.FindPreferredAppForUrl(filter_url_5));
EXPECT_EQ(kAppId3, preferred_apps_.FindPreferredAppForUrl(filter_url_6));
preferred_apps_.DeleteAppId(kAppId2);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_3));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_4));
EXPECT_EQ(kAppId3, preferred_apps_.FindPreferredAppForUrl(filter_url_5));
EXPECT_EQ(kAppId3, preferred_apps_.FindPreferredAppForUrl(filter_url_6));
preferred_apps_.DeleteAppId(kAppId3);
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_5));
- EXPECT_EQ(base::nullopt,
+ EXPECT_EQ(absl::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_6));
}
diff --git a/chromium/components/services/app_service/public/cpp/protocol_handler_info.h b/chromium/components/services/app_service/public/cpp/protocol_handler_info.h
index 99cf266e74f..5cefeb6f97f 100644
--- a/chromium/components/services/app_service/public/cpp/protocol_handler_info.h
+++ b/chromium/components/services/app_service/public/cpp/protocol_handler_info.h
@@ -6,6 +6,7 @@
#define COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_PROTOCOL_HANDLER_INFO_H_
#include <string>
+#include <vector>
#include "url/gurl.h"
@@ -20,6 +21,7 @@ struct ProtocolHandlerInfo {
std::string protocol;
GURL url;
};
+using ProtocolHandlers = std::vector<ProtocolHandlerInfo>;
bool operator==(const ProtocolHandlerInfo& handler1,
const ProtocolHandlerInfo& handler2);
diff --git a/chromium/components/services/app_service/public/cpp/publisher_base.cc b/chromium/components/services/app_service/public/cpp/publisher_base.cc
index 0534b57b7c7..bc2e7b4b6b4 100644
--- a/chromium/components/services/app_service/public/cpp/publisher_base.cc
+++ b/chromium/components/services/app_service/public/cpp/publisher_base.cc
@@ -69,8 +69,8 @@ void PublisherBase::Publish(
void PublisherBase::ModifyCapabilityAccess(
const mojo::RemoteSet<apps::mojom::Subscriber>& subscribers,
const std::string& app_id,
- base::Optional<bool> accessing_camera,
- base::Optional<bool> accessing_microphone) {
+ absl::optional<bool> accessing_camera,
+ absl::optional<bool> accessing_microphone) {
if (!accessing_camera.has_value() && !accessing_microphone.has_value()) {
return;
}
diff --git a/chromium/components/services/app_service/public/cpp/publisher_base.h b/chromium/components/services/app_service/public/cpp/publisher_base.h
index f2ad1d4a3c3..45ca3a4a039 100644
--- a/chromium/components/services/app_service/public/cpp/publisher_base.h
+++ b/chromium/components/services/app_service/public/cpp/publisher_base.h
@@ -52,8 +52,8 @@ class PublisherBase : public apps::mojom::Publisher {
void ModifyCapabilityAccess(
const mojo::RemoteSet<apps::mojom::Subscriber>& subscribers,
const std::string& app_id,
- base::Optional<bool> accessing_camera,
- base::Optional<bool> accessing_microphone);
+ absl::optional<bool> accessing_camera,
+ absl::optional<bool> accessing_microphone);
mojo::Receiver<apps::mojom::Publisher>& receiver() { return receiver_; }
diff --git a/chromium/components/services/app_service/public/cpp/share_target.cc b/chromium/components/services/app_service/public/cpp/share_target.cc
index 320eed8cf79..e8122fac07a 100644
--- a/chromium/components/services/app_service/public/cpp/share_target.cc
+++ b/chromium/components/services/app_service/public/cpp/share_target.cc
@@ -84,15 +84,16 @@ std::ostream& operator<<(std::ostream& out, const ShareTarget::Params& params) {
out << "title: " << params.title << std::endl;
out << "text: " << params.text << std::endl;
out << "url: " << params.url << std::endl;
+ out << "files:" << std::endl;
for (const auto& files_entry : params.files)
out << files_entry;
return out;
}
std::ostream& operator<<(std::ostream& out, const ShareTarget::Files& files) {
- out << "name: " << files.name << std::endl;
+ out << " name: " << files.name << std::endl;
for (const auto& accept_entry : files.accept)
- out << "accept: " << accept_entry << std::endl;
+ out << " accept: " << accept_entry << std::endl;
return out;
}
diff --git a/chromium/components/services/app_service/public/cpp/types_util.cc b/chromium/components/services/app_service/public/cpp/types_util.cc
new file mode 100644
index 00000000000..e7d7e7b4e80
--- /dev/null
+++ b/chromium/components/services/app_service/public/cpp/types_util.cc
@@ -0,0 +1,25 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/app_service/public/cpp/types_util.h"
+
+namespace apps_util {
+
+bool IsInstalled(apps::mojom::Readiness readiness) {
+ switch (readiness) {
+ case apps::mojom::Readiness::kReady:
+ case apps::mojom::Readiness::kDisabledByBlocklist:
+ case apps::mojom::Readiness::kDisabledByPolicy:
+ case apps::mojom::Readiness::kDisabledByUser:
+ case apps::mojom::Readiness::kTerminated:
+ return true;
+ case apps::mojom::Readiness::kUninstalledByUser:
+ case apps::mojom::Readiness::kUninstalledByMigration:
+ case apps::mojom::Readiness::kRemoved:
+ case apps::mojom::Readiness::kUnknown:
+ return false;
+ }
+}
+
+} // namespace apps_util
diff --git a/chromium/components/services/app_service/public/cpp/types_util.h b/chromium/components/services/app_service/public/cpp/types_util.h
new file mode 100644
index 00000000000..2b2de6aaf9e
--- /dev/null
+++ b/chromium/components/services/app_service/public/cpp/types_util.h
@@ -0,0 +1,18 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_TYPES_UTIL_H_
+#define COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_TYPES_UTIL_H_
+
+// Utility functions for App Service types.
+
+#include "components/services/app_service/public/mojom/types.mojom.h"
+
+namespace apps_util {
+
+bool IsInstalled(apps::mojom::Readiness readiness);
+
+} // namespace apps_util
+
+#endif // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_TYPES_UTIL_H_
diff --git a/chromium/components/services/app_service/public/cpp/url_handler_info.cc b/chromium/components/services/app_service/public/cpp/url_handler_info.cc
index 5aad8f5ffdb..0b176e54c29 100644
--- a/chromium/components/services/app_service/public/cpp/url_handler_info.cc
+++ b/chromium/components/services/app_service/public/cpp/url_handler_info.cc
@@ -63,15 +63,15 @@ bool operator<(const UrlHandlerInfo& handler1, const UrlHandlerInfo& handler2) {
}
std::ostream& operator<<(std::ostream& out, const UrlHandlerInfo& handler) {
- out << "origin: " << handler.origin;
- out << "has_origin_wildcard: "
- << (handler.has_origin_wildcard ? "true" : "false");
+ out << "origin: " << handler.origin << std::endl;
+ out << " has_origin_wildcard: "
+ << (handler.has_origin_wildcard ? "true" : "false") << std::endl;
- out << "paths: ";
+ out << " paths:" << std::endl;
for (auto path : handler.paths)
out << " " << path << std::endl;
- out << "exclude_paths: ";
+ out << " exclude_paths:" << std::endl;
for (auto path : handler.exclude_paths)
out << " " << path << std::endl;
diff --git a/chromium/components/services/app_service/public/mojom/types.mojom b/chromium/components/services/app_service/public/mojom/types.mojom
index b33d2f14ec7..faf4b531c57 100644
--- a/chromium/components/services/app_service/public/mojom/types.mojom
+++ b/chromium/components/services/app_service/public/mojom/types.mojom
@@ -91,17 +91,17 @@ struct Permission {
// The types of apps available in the registry.
enum AppType {
kUnknown = 0,
- kArc, // Android app.
- kBuiltIn, // Built-in app.
- kCrostini, // Linux (via Crostini) app.
- kExtension, // Extension-backed app.
- kWeb, // Web app.
- kMacOs, // Mac OS app.
- kPluginVm, // Plugin VM app, see go/pluginvm.
- kLacros, // Lacros browser app, see //docs/lacros.md.
- kRemote, // Remote app.
- kBorealis, // Borealis app, see go/borealis-app.
- kSystemWeb, // System web app.
+ kArc, // Android app.
+ kBuiltIn, // Built-in app.
+ kCrostini, // Linux (via Crostini) app.
+ kExtension, // Extension-backed app.
+ kWeb, // Web app.
+ kMacOs, // Mac OS app.
+ kPluginVm, // Plugin VM app, see go/pluginvm.
+ kStandaloneBrowser, // Lacros browser app, see //docs/lacros.md.
+ kRemote, // Remote app.
+ kBorealis, // Borealis app, see go/borealis-app.
+ kSystemWeb, // System web app.
};
// Whether an app is ready to launch, i.e. installed.
@@ -118,6 +118,7 @@ enum Readiness {
// apps, so publishers must set the app as uninstalled before
// removing it.
kRemoved,
+ kUninstalledByMigration,
};
// How the app was installed.
@@ -134,8 +135,10 @@ enum InstallSource {
// What caused the app to be uninstalled.
enum UninstallSource {
kUnknown = 0,
- kUser, // Uninstall by user action.
- kMigration, // Uninstall by app migration.
+ kAppList, // Uninstall by the user from the App List (Launcher)
+ kAppManagement, // Uninstall by the user from the App Management page
+ kShelf, // Uninstall by the user from the Shelf
+ kMigration, // Uninstall by app migration.
};
// Augments a bool to include an 'unknown' value.
@@ -199,7 +202,10 @@ struct IconValue {
};
// Enumeration of possible app launch sources.
-// This should be kept in sync with histogram_suffixes_list.xml.
+// This should be kept in sync with histogram_suffixes_list.xml, and
+// LaunchSource in enums.xml.
+// Note the enumeration is used in UMA histogram so entries should not be
+// re-ordered or removed. New entries should be added at the bottom.
enum LaunchSource {
kUnknown = 0,
kFromAppListGrid = 1, // Grid of apps, not the search box.
@@ -226,6 +232,7 @@ enum LaunchSource {
kFromReleaseNotesNotification = 19, // Release Notes Notification.
kFromFullRestore = 20, // Full restore.
kFromSmartTextContextMenu = 21, // Smart text selection context menu.
+ kFromDiscoverTabNotification = 22, // Discover Tab Notification.
};
enum TriState {
@@ -440,7 +447,7 @@ struct Rect {
// The window information to launch an app.
struct WindowInfo {
int32 window_id = -1;
- int32 state = -1;
+ int32 state = 0;
int64 display_id = -1;
Rect? bounds;
};
diff --git a/chromium/components/services/filesystem/OWNERS b/chromium/components/services/filesystem/OWNERS
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/components/services/filesystem/OWNERS
+++ /dev/null
diff --git a/chromium/components/services/filesystem/directory_impl.cc b/chromium/components/services/filesystem/directory_impl.cc
index df0e0ccc79b..6959dd1364f 100644
--- a/chromium/components/services/filesystem/directory_impl.cc
+++ b/chromium/components/services/filesystem/directory_impl.cc
@@ -47,8 +47,8 @@ void DirectoryImpl::Read(ReadCallback callback) {
std::move(callback).Run(base::File::Error::FILE_OK,
entries.empty()
- ? base::nullopt
- : base::make_optional(std::move(entries)));
+ ? absl::nullopt
+ : absl::make_optional(std::move(entries)));
}
// TODO(erg): Consider adding an implementation of Stat()/Touch() to the
diff --git a/chromium/components/services/filesystem/directory_impl_unittest.cc b/chromium/components/services/filesystem/directory_impl_unittest.cc
index 70f8261a4d5..66c4279efef 100644
--- a/chromium/components/services/filesystem/directory_impl_unittest.cc
+++ b/chromium/components/services/filesystem/directory_impl_unittest.cc
@@ -13,6 +13,7 @@
#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.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -66,7 +67,7 @@ TEST_F(DirectoryImplTest, Read) {
EXPECT_EQ(base::File::Error::FILE_OK, error);
error = base::File::Error::FILE_ERROR_FAILED;
- base::Optional<std::vector<mojom::DirectoryEntryPtr>> directory_contents;
+ absl::optional<std::vector<mojom::DirectoryEntryPtr>> directory_contents;
handled = directory->Read(&error, &directory_contents);
ASSERT_TRUE(handled);
EXPECT_EQ(base::File::Error::FILE_OK, error);
diff --git a/chromium/components/services/filesystem/file_impl.cc b/chromium/components/services/filesystem/file_impl.cc
index 9404d7e1afa..29e51005498 100644
--- a/chromium/components/services/filesystem/file_impl.cc
+++ b/chromium/components/services/filesystem/file_impl.cc
@@ -92,28 +92,28 @@ void FileImpl::Read(uint32_t num_bytes_to_read,
mojom::Whence whence,
ReadCallback callback) {
if (!file_.IsValid()) {
- std::move(callback).Run(GetError(file_), base::nullopt);
+ std::move(callback).Run(GetError(file_), absl::nullopt);
return;
}
if (num_bytes_to_read > kMaxReadSize) {
std::move(callback).Run(base::File::Error::FILE_ERROR_INVALID_OPERATION,
- base::nullopt);
+ absl::nullopt);
return;
}
base::File::Error error = IsOffsetValid(offset);
if (error != base::File::Error::FILE_OK) {
- std::move(callback).Run(error, base::nullopt);
+ std::move(callback).Run(error, absl::nullopt);
return;
}
error = IsWhenceValid(whence);
if (error != base::File::Error::FILE_OK) {
- std::move(callback).Run(error, base::nullopt);
+ std::move(callback).Run(error, absl::nullopt);
return;
}
if (file_.Seek(static_cast<base::File::Whence>(whence), offset) == -1) {
std::move(callback).Run(base::File::Error::FILE_ERROR_FAILED,
- base::nullopt);
+ absl::nullopt);
return;
}
@@ -122,7 +122,7 @@ void FileImpl::Read(uint32_t num_bytes_to_read,
reinterpret_cast<char*>(&bytes_read.front()), num_bytes_to_read);
if (num_bytes_read < 0) {
std::move(callback).Run(base::File::Error::FILE_ERROR_FAILED,
- base::nullopt);
+ absl::nullopt);
return;
}
diff --git a/chromium/components/services/filesystem/file_impl.h b/chromium/components/services/filesystem/file_impl.h
index f48dc58355e..f8864bb3ea5 100644
--- a/chromium/components/services/filesystem/file_impl.h
+++ b/chromium/components/services/filesystem/file_impl.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "build/build_config.h"
#include "components/services/filesystem/public/mojom/directory.mojom.h"
+#include "components/services/filesystem/public/mojom/file.mojom.h"
namespace base {
class FilePath;
diff --git a/chromium/components/services/filesystem/file_impl_unittest.cc b/chromium/components/services/filesystem/file_impl_unittest.cc
index 74fcdd8e747..97f77106239 100644
--- a/chromium/components/services/filesystem/file_impl_unittest.cc
+++ b/chromium/components/services/filesystem/file_impl_unittest.cc
@@ -12,6 +12,7 @@
#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.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -87,7 +88,7 @@ TEST_F(FileImplTest, CreateWriteCloseRenameOpenRead) {
EXPECT_EQ(base::File::Error::FILE_OK, error);
// Read from it.
- base::Optional<std::vector<uint8_t>> bytes_read;
+ absl::optional<std::vector<uint8_t>> bytes_read;
error = base::File::Error::FILE_ERROR_FAILED;
handled = file->Read(3, 1, mojom::Whence::FROM_BEGIN, &error, &bytes_read);
ASSERT_TRUE(handled);
@@ -248,7 +249,7 @@ TEST_F(FileImplTest, OpenInAppendMode) {
EXPECT_EQ(base::File::Error::FILE_OK, error);
// Read from it.
- base::Optional<std::vector<uint8_t>> bytes_read;
+ absl::optional<std::vector<uint8_t>> bytes_read;
error = base::File::Error::FILE_ERROR_FAILED;
handled = file->Read(12, 0, mojom::Whence::FROM_BEGIN, &error, &bytes_read);
ASSERT_TRUE(handled);
@@ -343,7 +344,7 @@ TEST_F(FileImplTest, OpenInTruncateMode) {
EXPECT_EQ(base::File::Error::FILE_OK, error);
// Read from it.
- base::Optional<std::vector<uint8_t>> bytes_read;
+ absl::optional<std::vector<uint8_t>> bytes_read;
error = base::File::Error::FILE_ERROR_FAILED;
handled = file->Read(7, 0, mojom::Whence::FROM_BEGIN, &error, &bytes_read);
ASSERT_TRUE(handled);
@@ -589,7 +590,7 @@ TEST_F(FileImplTest, Dup) {
EXPECT_EQ(base::File::Error::FILE_OK, error);
// Read everything using |file2|.
- base::Optional<std::vector<uint8_t>> bytes_read;
+ absl::optional<std::vector<uint8_t>> bytes_read;
error = base::File::Error::FILE_ERROR_FAILED;
handled =
file2->Read(1000, 0, mojom::Whence::FROM_BEGIN, &error, &bytes_read);
@@ -691,7 +692,7 @@ TEST_F(FileImplTest, AsHandle) {
EXPECT_EQ(base::File::Error::FILE_OK, error);
// Verify that we wrote data raw on the file descriptor.
- base::Optional<std::vector<uint8_t>> bytes_read;
+ absl::optional<std::vector<uint8_t>> bytes_read;
error = base::File::Error::FILE_ERROR_FAILED;
handled = file2->Read(5, 0, mojom::Whence::FROM_BEGIN, &error, &bytes_read);
ASSERT_TRUE(handled);
diff --git a/chromium/components/services/font/font_service_app.cc b/chromium/components/services/font/font_service_app.cc
index 54a7f8d492c..4bbeebcb52c 100644
--- a/chromium/components/services/font/font_service_app.cc
+++ b/chromium/components/services/font/font_service_app.cc
@@ -209,7 +209,7 @@ void FontServiceApp::MatchFontByPostscriptNameOrFullFontName(
TRACE_EVENT0("fonts",
"FontServiceApp::MatchFontByPostscriptNameOrFullFontName");
- base::Optional<FontConfigLocalMatching::FontConfigMatchResult> match_result =
+ absl::optional<FontConfigLocalMatching::FontConfigMatchResult> match_result =
FontConfigLocalMatching::FindFontByPostscriptNameOrFullFontName(family);
if (match_result) {
uint32_t fontconfig_interface_id = FindOrAddPath(match_result->file_path);
diff --git a/chromium/components/services/font/fontconfig_matching.cc b/chromium/components/services/font/fontconfig_matching.cc
index 8b2f3b11297..a7882461333 100644
--- a/chromium/components/services/font/fontconfig_matching.cc
+++ b/chromium/components/services/font/fontconfig_matching.cc
@@ -13,13 +13,13 @@
namespace font_service {
-base::Optional<FontConfigLocalMatching::FontConfigMatchResult>
+absl::optional<FontConfigLocalMatching::FontConfigMatchResult>
FontConfigLocalMatching::FindFontByPostscriptNameOrFullFontName(
const std::string& font_name) {
// TODO(crbug.com/876652): This FontConfig-backed implementation will
// match PostScript and full font name in any language, and we're okay
// with that for now since it is what FireFox does.
- base::Optional<FontConfigLocalMatching::FontConfigMatchResult>
+ absl::optional<FontConfigLocalMatching::FontConfigMatchResult>
postscript_result =
FindFontBySpecifiedName(FC_POSTSCRIPT_NAME, font_name);
if (postscript_result)
@@ -28,7 +28,7 @@ FontConfigLocalMatching::FindFontByPostscriptNameOrFullFontName(
return FindFontBySpecifiedName(FC_FULLNAME, font_name);
}
-base::Optional<FontConfigLocalMatching::FontConfigMatchResult>
+absl::optional<FontConfigLocalMatching::FontConfigMatchResult>
FontConfigLocalMatching::FindFontBySpecifiedName(
const char* fontconfig_parameter_name,
const std::string& font_name) {
@@ -37,7 +37,7 @@ FontConfigLocalMatching::FindFontBySpecifiedName(
std::string(FC_POSTSCRIPT_NAME));
if (!base::IsStringUTF8(font_name))
- return base::nullopt;
+ return absl::nullopt;
std::unique_ptr<FcPattern, void (*)(FcPattern*)> pattern(FcPatternCreate(),
FcPatternDestroy);
@@ -60,7 +60,7 @@ FontConfigLocalMatching::FindFontBySpecifiedName(
FcFontList(nullptr, pattern.get(), object_set.get()), FcFontSetDestroy);
if (!font_set || !font_set->nfont)
- return base::nullopt;
+ return absl::nullopt;
FcPattern* current = font_set->fonts[0];
@@ -68,7 +68,7 @@ FontConfigLocalMatching::FindFontBySpecifiedName(
if (FcPatternGetString(current, FC_FILE, 0,
reinterpret_cast<FcChar8**>(const_cast<char**>(
&c_filename))) != FcResultMatch) {
- return base::nullopt;
+ return absl::nullopt;
}
const char* sysroot =
reinterpret_cast<const char*>(FcConfigGetSysRoot(nullptr));
@@ -78,7 +78,8 @@ FontConfigLocalMatching::FindFontBySpecifiedName(
// very good way of detecting this so we'll filter based on the
// filename.
bool is_sfnt = false;
- static const char kSFNTExtensions[][5] = {".ttf", ".otc", ".TTF", ".ttc", ""};
+ static const char kSFNTExtensions[][5] = {".ttf", ".otc", ".TTF", ".ttc",
+ ".otf", ".OTF", ""};
for (size_t j = 0;; j++) {
if (kSFNTExtensions[j][0] == 0) {
// None of the extensions matched.
@@ -92,18 +93,18 @@ FontConfigLocalMatching::FindFontBySpecifiedName(
}
if (!is_sfnt)
- return base::nullopt;
+ return absl::nullopt;
base::FilePath font_file_path(filename);
base::File verify_file_exists(font_file_path,
base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!verify_file_exists.IsValid())
- return base::nullopt;
+ return absl::nullopt;
int ttc_index = 0;
FcPatternGetInteger(current, FC_INDEX, 0, &ttc_index);
if (ttc_index < 0)
- return base::nullopt;
+ return absl::nullopt;
FontConfigMatchResult match_result;
match_result.file_path = font_file_path;
match_result.ttc_index = ttc_index;
diff --git a/chromium/components/services/font/fontconfig_matching.h b/chromium/components/services/font/fontconfig_matching.h
index 19069c2b33a..7152349ca43 100644
--- a/chromium/components/services/font/fontconfig_matching.h
+++ b/chromium/components/services/font/fontconfig_matching.h
@@ -6,7 +6,7 @@
#define COMPONENTS_SERVICES_FONT_FONTCONFIG_MATCHING_H_
#include "base/files/file_path.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace font_service {
// Searches FontConfig for a system font uniquely identified by full font name
@@ -19,15 +19,15 @@ class FontConfigLocalMatching {
unsigned ttc_index;
};
- static base::Optional<FontConfigMatchResult>
+ static absl::optional<FontConfigMatchResult>
FindFontByPostscriptNameOrFullFontName(const std::string& font_name);
private:
- static base::Optional<FontConfigMatchResult> FindFontBySpecifiedName(
+ static absl::optional<FontConfigMatchResult> FindFontBySpecifiedName(
const char* fontconfig_parameter_name,
const std::string& font_name);
};
} // namespace font_service
-#endif
+#endif // COMPONENTS_SERVICES_FONT_FONTCONFIG_MATCHING_H_
diff --git a/chromium/components/services/heap_profiling/json_exporter.cc b/chromium/components/services/heap_profiling/json_exporter.cc
index 159232ba972..dd77e64d88f 100644
--- a/chromium/components/services/heap_profiling/json_exporter.cc
+++ b/chromium/components/services/heap_profiling/json_exporter.cc
@@ -5,6 +5,7 @@
#include "components/services/heap_profiling/json_exporter.h"
#include <inttypes.h>
+
#include <map>
#include <unordered_map>
@@ -13,6 +14,7 @@
#include "base/json/string_escape.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
+#include "base/trace_event/traced_value.h"
#include "base/values.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer_traced_value.h"
diff --git a/chromium/components/services/heap_profiling/json_exporter_unittest.cc b/chromium/components/services/heap_profiling/json_exporter_unittest.cc
index ccb60ea6eda..e8a17017bb4 100644
--- a/chromium/components/services/heap_profiling/json_exporter_unittest.cc
+++ b/chromium/components/services/heap_profiling/json_exporter_unittest.cc
@@ -27,7 +27,7 @@ static constexpr int kNoParent = -1;
// Finds the first vm region in the given periodic interval. Returns null on
// failure.
const base::Value* FindFirstRegionWithAnyName(
- const base::Optional<base::Value>& root) {
+ const absl::optional<base::Value>& root) {
const base::Value* found_mmaps =
root->FindKeyOfType("process_mmaps", base::Value::Type::DICTIONARY);
if (!found_mmaps)
@@ -155,7 +155,7 @@ TEST(ProfilingJsonExporterTest, Simple) {
std::string json = ExportMemoryMapsAndV2StackTraceToJSON(&params);
// JSON should parse.
- base::Optional<base::Value> root = base::JSONReader::Read(json);
+ absl::optional<base::Value> root = base::JSONReader::Read(json);
ASSERT_TRUE(root);
// Validate the allocators summary.
@@ -292,7 +292,7 @@ TEST(ProfilingJsonExporterTest, MemoryMaps) {
std::string json = ExportMemoryMapsAndV2StackTraceToJSON(&params);
// JSON should parse.
- base::Optional<base::Value> root = base::JSONReader::Read(json);
+ absl::optional<base::Value> root = base::JSONReader::Read(json);
ASSERT_TRUE(root);
const base::Value* region = FindFirstRegionWithAnyName(root);
@@ -340,7 +340,7 @@ TEST(ProfilingJsonExporterTest, Context) {
std::string json = ExportMemoryMapsAndV2StackTraceToJSON(&params);
// JSON should parse.
- base::Optional<base::Value> root = base::JSONReader::Read(json);
+ absl::optional<base::Value> root = base::JSONReader::Read(json);
ASSERT_TRUE(root);
// Retrieve the allocations.
diff --git a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.cc b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.cc
index b0796c03f24..de8d419ce4b 100644
--- a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.cc
+++ b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.cc
@@ -8,9 +8,11 @@
#include "base/memory/discardable_memory.h"
#include "base/memory/discardable_memory_allocator.h"
+#include "base/system/sys_info.h"
#include "build/build_config.h"
#include "content/public/utility/utility_thread.h"
#include "third_party/skia/include/core/SkFontMgr.h"
+#include "third_party/skia/include/core/SkGraphics.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#if defined(OS_WIN)
@@ -30,6 +32,24 @@ PaintPreviewCompositorCollectionImpl::PaintPreviewCompositorCollectionImpl(
if (receiver)
receiver_.Bind(std::move(receiver));
+ listener_ = std::make_unique<base::MemoryPressureListener>(
+ FROM_HERE, base::BindRepeating(
+ &PaintPreviewCompositorCollectionImpl::OnMemoryPressure,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ // Adapted from content::InitializeSkia().
+ // TODO(crbug/1199857): Tune these limits.
+ constexpr int kMB = 1024 * 1024;
+#if defined(OS_ANDROID)
+ SkGraphics::SetFontCacheLimit(base::SysInfo::IsLowEndDevice() ? kMB
+ : 8 * kMB);
+ SkGraphics::SetResourceCacheTotalByteLimit(
+ base::SysInfo::IsLowEndDevice() ? 32 * kMB : 64 * kMB);
+ SkGraphics::SetResourceCacheSingleAllocationByteLimit(16 * kMB);
+#else
+ SkGraphics::SetResourceCacheSingleAllocationByteLimit(64 * kMB);
+#endif // defined(OS_ANDROID)
+
if (!initialize_environment_)
return;
@@ -72,6 +92,22 @@ PaintPreviewCompositorCollectionImpl::~PaintPreviewCompositorCollectionImpl() {
#endif
}
+void PaintPreviewCompositorCollectionImpl::OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
+ if (memory_pressure_level >=
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
+ receiver_.reset();
+ return;
+ }
+ if (memory_pressure_level >=
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE) {
+ SkGraphics::PurgeAllCaches();
+ if (discardable_shared_memory_manager_) {
+ discardable_shared_memory_manager_->ReleaseFreeMemory();
+ }
+ }
+}
+
void PaintPreviewCompositorCollectionImpl::SetDiscardableSharedMemoryManager(
mojo::PendingRemote<
discardable_memory::mojom::DiscardableSharedMemoryManager> manager) {
diff --git a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.h b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.h
index 5da7a70b249..0b94a226f66 100644
--- a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.h
+++ b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl.h
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/containers/flat_map.h"
+#include "base/memory/memory_pressure_listener.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
@@ -60,6 +61,8 @@ class PaintPreviewCompositorCollectionImpl
void ListCompositors(ListCompositorsCallback callback) override;
private:
+ void OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
// Invoked by a |compositor| when it is disconnected from its remote. Used to
// delete the corresponding instance from |compositors_|.
void OnDisconnect(const base::UnguessableToken& id);
@@ -80,6 +83,7 @@ class PaintPreviewCompositorCollectionImpl
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager>
discardable_shared_memory_manager_;
+ std::unique_ptr<base::MemoryPressureListener> listener_;
base::WeakPtrFactory<PaintPreviewCompositorCollectionImpl> weak_ptr_factory_{
this};
diff --git a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl_unittest.cc b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl_unittest.cc
index be5a3fca616..36e63432d33 100644
--- a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl_unittest.cc
+++ b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_collection_impl_unittest.cc
@@ -105,4 +105,38 @@ TEST(PaintPreviewCompositorCollectionTest,
compositor->SetRootFrameUrl(GURL("https://www.foo.com"));
}
+TEST(PaintPreviewCompositorCollectionTest, MemoryPressure) {
+ base::test::TaskEnvironment task_environment;
+
+ base::UnguessableToken token;
+ auto create_cb = base::BindOnce(
+ [](base::UnguessableToken* out_token,
+ const base::UnguessableToken& token) { *out_token = token; },
+ base::Unretained(&token));
+ ASSERT_TRUE(token.is_empty());
+ mojo::Remote<mojom::PaintPreviewCompositor> compositor;
+ {
+ mojo::Remote<mojom::PaintPreviewCompositorCollection> collection;
+ PaintPreviewCompositorCollectionImpl collection_instance(
+ collection.BindNewPipeAndPassReceiver(), false, nullptr);
+ task_environment.RunUntilIdle();
+ EXPECT_TRUE(collection.is_bound());
+ EXPECT_TRUE(collection.is_connected());
+ // Moderate will just purge caches. They aren't needed as urgently.
+ base::MemoryPressureListener::SimulatePressureNotification(
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
+ task_environment.RunUntilIdle();
+ EXPECT_TRUE(collection.is_bound());
+ EXPECT_TRUE(collection.is_connected());
+
+ // Critial will kill process.
+ base::MemoryPressureListener::SimulatePressureNotification(
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
+ task_environment.RunUntilIdle();
+ EXPECT_TRUE(collection.is_bound());
+ EXPECT_FALSE(collection.is_connected());
+ }
+ task_environment.RunUntilIdle();
+}
+
} // namespace paint_preview
diff --git a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl.cc b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl.cc
index c871fa90e6a..af3ecd8f67b 100644
--- a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl.cc
+++ b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl.cc
@@ -8,7 +8,6 @@
#include <utility>
#include "base/memory/memory_pressure_listener.h"
-#include "base/optional.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/common/trace_event_common.h"
@@ -19,6 +18,7 @@
#include "components/paint_preview/common/serialized_recording.h"
#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
#include "skia/ext/legacy_display_globals.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImageInfo.h"
@@ -32,32 +32,32 @@ namespace paint_preview {
namespace {
// Returns |nullopt| if |proto_memory| cannot be mapped or parsed.
-base::Optional<PaintPreviewProto> ParsePaintPreviewProto(
+absl::optional<PaintPreviewProto> ParsePaintPreviewProto(
const base::ReadOnlySharedMemoryRegion& proto_memory) {
auto mapping = proto_memory.Map();
if (!mapping.IsValid()) {
DVLOG(1) << "Failed to map proto in shared memory.";
- return base::nullopt;
+ return absl::nullopt;
}
PaintPreviewProto paint_preview;
bool ok = paint_preview.ParseFromArray(mapping.memory(), mapping.size());
if (!ok) {
DVLOG(1) << "Failed to parse proto.";
- return base::nullopt;
+ return absl::nullopt;
}
return {paint_preview};
}
-base::Optional<PaintPreviewFrame> BuildFrame(
+absl::optional<PaintPreviewFrame> BuildFrame(
const base::UnguessableToken& token,
const PaintPreviewFrameProto& frame_proto,
const base::flat_map<base::UnguessableToken, SkpResult>& results) {
TRACE_EVENT0("paint_preview", "PaintPreviewCompositorImpl::BuildFrame");
auto it = results.find(token);
if (it == results.end())
- return base::nullopt;
+ return absl::nullopt;
const SkpResult& result = it->second;
PaintPreviewFrame frame;
@@ -127,7 +127,7 @@ gfx::Rect AdjustClipRect(const gfx::Rect& clip_rect,
// Holds a ref to the discardable_shared_memory_manager so it sticks around
// until at least after skia is finished with it.
-base::Optional<SkBitmap> CreateBitmap(
+absl::optional<SkBitmap> CreateBitmap(
scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager>
discardable_shared_memory_manager,
sk_sp<SkPicture> skp,
@@ -139,7 +139,7 @@ base::Optional<SkBitmap> CreateBitmap(
SkBitmap bitmap;
if (!bitmap.tryAllocPixels(
SkImageInfo::MakeN32Premul(clip_rect.width(), clip_rect.height()))) {
- return base::nullopt;
+ return absl::nullopt;
}
SkCanvas canvas(bitmap, skia::LegacyDisplayGlobals::GetSkSurfaceProps());
SkMatrix matrix;
@@ -161,10 +161,6 @@ PaintPreviewCompositorImpl::PaintPreviewCompositorImpl(
receiver_.Bind(std::move(receiver));
receiver_.set_disconnect_handler(std::move(disconnect_handler));
}
- listener_ = std::make_unique<base::MemoryPressureListener>(
- FROM_HERE,
- base::BindRepeating(&PaintPreviewCompositorImpl::OnMemoryPressure,
- weak_ptr_factory_.GetWeakPtr()));
}
PaintPreviewCompositorImpl::~PaintPreviewCompositorImpl() {
@@ -183,7 +179,7 @@ void PaintPreviewCompositorImpl::BeginSeparatedFrameComposite(
frames_.clear();
auto response = mojom::PaintPreviewBeginCompositeResponse::New();
- base::Optional<PaintPreviewProto> paint_preview =
+ absl::optional<PaintPreviewProto> paint_preview =
ParsePaintPreviewProto(request->proto);
if (!paint_preview.has_value()) {
// Cannot send a null token over mojo. This will be ignored downstream.
@@ -255,7 +251,7 @@ void PaintPreviewCompositorImpl::BitmapForSeparatedFrame(
frame_it->second.skp, clip_rect, scale_factor),
base::BindOnce(
[](BitmapForSeparatedFrameCallback callback,
- const base::Optional<SkBitmap>& maybe_bitmap) {
+ const absl::optional<SkBitmap>& maybe_bitmap) {
if (!maybe_bitmap.has_value()) {
std::move(callback).Run(
mojom::PaintPreviewCompositor::BitmapStatus::kAllocFailed,
@@ -276,7 +272,7 @@ void PaintPreviewCompositorImpl::BeginMainFrameComposite(
"PaintPreviewCompositorImpl::BeginMainFrameComposite");
frames_.clear();
auto response = mojom::PaintPreviewBeginCompositeResponse::New();
- base::Optional<PaintPreviewProto> paint_preview =
+ absl::optional<PaintPreviewProto> paint_preview =
ParsePaintPreviewProto(request->proto);
if (!paint_preview.has_value()) {
response->root_frame_guid = base::UnguessableToken::Create();
@@ -355,7 +351,7 @@ void PaintPreviewCompositorImpl::BitmapForMainFrame(
root_frame_, clip_rect, scale_factor),
base::BindOnce(
[](BitmapForMainFrameCallback callback,
- const base::Optional<SkBitmap>& maybe_bitmap) {
+ const absl::optional<SkBitmap>& maybe_bitmap) {
if (!maybe_bitmap.has_value()) {
std::move(callback).Run(
mojom::PaintPreviewCompositor::BitmapStatus::kAllocFailed,
@@ -373,14 +369,6 @@ void PaintPreviewCompositorImpl::SetRootFrameUrl(const GURL& url) {
url_ = url;
}
-void PaintPreviewCompositorImpl::OnMemoryPressure(
- base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
- if (memory_pressure_level >=
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
- receiver_.reset();
- }
-}
-
bool PaintPreviewCompositorImpl::AddFrame(
const PaintPreviewFrameProto& frame_proto,
const base::flat_map<base::UnguessableToken, SkpResult>& skp_map,
@@ -388,7 +376,7 @@ bool PaintPreviewCompositorImpl::AddFrame(
base::UnguessableToken guid = base::UnguessableToken::Deserialize(
frame_proto.embedding_token_high(), frame_proto.embedding_token_low());
- base::Optional<PaintPreviewFrame> maybe_frame =
+ absl::optional<PaintPreviewFrame> maybe_frame =
BuildFrame(guid, frame_proto, skp_map);
if (!maybe_frame.has_value())
return false;
@@ -418,7 +406,7 @@ PaintPreviewCompositorImpl::DeserializeAllFrames(RecordingMap&& recording_map) {
results.reserve(recording_map.size());
for (auto& it : recording_map) {
- base::Optional<SkpResult> maybe_result = std::move(it.second).Deserialize();
+ absl::optional<SkpResult> maybe_result = std::move(it.second).Deserialize();
if (!maybe_result.has_value())
continue;
diff --git a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl.h b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl.h
index 4d7220e0317..33c78842ac5 100644
--- a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl.h
+++ b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl.h
@@ -9,8 +9,6 @@
#include "base/callback.h"
#include "base/containers/flat_map.h"
-#include "base/memory/memory_pressure_listener.h"
-#include "base/optional.h"
#include "components/discardable_memory/client/client_discardable_shared_memory_manager.h"
#include "components/paint_preview/common/proto/paint_preview.pb.h"
#include "components/paint_preview/common/recording_map.h"
@@ -18,6 +16,7 @@
#include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
@@ -65,9 +64,6 @@ class PaintPreviewCompositorImpl : public mojom::PaintPreviewCompositor {
void SetRootFrameUrl(const GURL& url) override;
private:
- void OnMemoryPressure(
- base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
-
// Adds |frame_proto| to |frames_| and copies required data into |response|.
// Consumes the corresponding file in |file_map|. Returns true on success.
bool AddFrame(
@@ -107,8 +103,6 @@ class PaintPreviewCompositorImpl : public mojom::PaintPreviewCompositor {
// Must be modified only by |BeginMainFrameComposite|.
sk_sp<SkPicture> root_frame_;
- std::unique_ptr<base::MemoryPressureListener> listener_;
-
scoped_refptr<discardable_memory::ClientDiscardableSharedMemoryManager>
discardable_shared_memory_manager_;
diff --git a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl_unittest.cc b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl_unittest.cc
index 99d7b431a61..b0c25b28f6c 100644
--- a/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl_unittest.cc
+++ b/chromium/components/services/paint_preview_compositor/paint_preview_compositor_impl_unittest.cc
@@ -16,7 +16,6 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/test/task_environment.h"
#include "base/unguessable_token.h"
#include "components/paint_preview/common/capture_result.h"
@@ -28,6 +27,7 @@
#include "mojo/public/cpp/base/big_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkMatrix.h"
@@ -127,7 +127,7 @@ SkRect ToSkRect(const gfx::Rect& rect) {
void DrawDummyTestPicture(SkCanvas* canvas,
SkColor rect_fill_color,
const gfx::Size& scroll_extents,
- base::Optional<gfx::Rect> clip_rect = base::nullopt,
+ absl::optional<gfx::Rect> clip_rect = absl::nullopt,
gfx::Size scroll_offsets = gfx::Size()) {
canvas->save();
if (clip_rect.has_value()) {
@@ -232,7 +232,7 @@ void PopulateFrameProto(
size_t serialized_size = 0;
ASSERT_TRUE(RecordToFile(
base::File(path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE),
- pic, &tracker, base::nullopt, &serialized_size));
+ pic, &tracker, absl::nullopt, &serialized_size));
ASSERT_GE(serialized_size, 0u);
expected_data->insert({guid, std::move(expected_frame_data)});
@@ -645,7 +645,7 @@ TEST(PaintPreviewCompositorTest, TestCompositeWithMemoryBuffer) {
/*is_main_frame=*/true);
size_t serialized_size = 0;
auto result =
- RecordToBuffer(pic, &tracker, base::nullopt, &serialized_size);
+ RecordToBuffer(pic, &tracker, absl::nullopt, &serialized_size);
ASSERT_TRUE(result.has_value());
buffer = std::move(result.value());
diff --git a/chromium/components/services/patch/file_patcher_impl.h b/chromium/components/services/patch/file_patcher_impl.h
index 5e4caeb2316..fab102fabd4 100644
--- a/chromium/components/services/patch/file_patcher_impl.h
+++ b/chromium/components/services/patch/file_patcher_impl.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SERVICES_PATCH_FILE_PATCHER_IMPL_H_
#define COMPONENTS_SERVICES_PATCH_FILE_PATCHER_IMPL_H_
-#include <memory>
-
#include "base/files/file.h"
#include "base/macros.h"
#include "components/services/patch/public/mojom/file_patcher.mojom.h"
diff --git a/chromium/components/services/print_compositor/print_compositor_impl.h b/chromium/components/services/print_compositor/print_compositor_impl.h
index 6a97b2703b7..1cf62a73c28 100644
--- a/chromium/components/services/print_compositor/print_compositor_impl.h
+++ b/chromium/components/services/print_compositor/print_compositor_impl.h
@@ -17,13 +17,13 @@
#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 "build/build_config.h"
#include "components/services/print_compositor/public/cpp/print_service_mojo_types.h"
#include "components/services/print_compositor/public/mojom/print_compositor.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "printing/buildflags/buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkStream.h"
diff --git a/chromium/components/services/print_compositor/public/mojom/BUILD.gn b/chromium/components/services/print_compositor/public/mojom/BUILD.gn
index d28ece2d6e7..176291aa38f 100644
--- a/chromium/components/services/print_compositor/public/mojom/BUILD.gn
+++ b/chromium/components/services/print_compositor/public/mojom/BUILD.gn
@@ -14,6 +14,7 @@ mojom("mojom") {
]
if (enable_tagged_pdf) {
+ assert(enable_print_preview)
enabled_features = [ "enable_tagged_pdf" ]
# Accessibility dependencies for exporting tagged PDFs on platforms
diff --git a/chromium/components/services/quarantine/BUILD.gn b/chromium/components/services/quarantine/BUILD.gn
index 79a97348fc5..4411ebbb4a4 100644
--- a/chromium/components/services/quarantine/BUILD.gn
+++ b/chromium/components/services/quarantine/BUILD.gn
@@ -37,6 +37,14 @@ static_library("quarantine") {
"Foundation.framework",
]
}
+
+ if (is_chromeos) {
+ sources += [ "quarantine_chromeos.cc" ]
+ deps += [
+ "//chromeos/dbus/dlp",
+ "//chromeos/dbus/dlp:dlp_proto",
+ ]
+ }
}
source_set("common") {
diff --git a/chromium/components/services/quarantine/DEPS b/chromium/components/services/quarantine/DEPS
index 9d3031f8980..1769016ef33 100644
--- a/chromium/components/services/quarantine/DEPS
+++ b/chromium/components/services/quarantine/DEPS
@@ -1,3 +1,4 @@
include_rules = [
+ "+chromeos/dbus/dlp",
"+net/base/filename_util.h",
]
diff --git a/chromium/components/services/quarantine/quarantine.cc b/chromium/components/services/quarantine/quarantine.cc
index 412ddd42486..83e907cbfb4 100644
--- a/chromium/components/services/quarantine/quarantine.cc
+++ b/chromium/components/services/quarantine/quarantine.cc
@@ -6,17 +6,18 @@
#include "build/build_config.h"
-#if !defined(OS_WIN) && !defined(OS_APPLE)
+#if !defined(OS_WIN) && !defined(OS_APPLE) && !defined(OS_CHROMEOS)
namespace quarantine {
-QuarantineFileResult QuarantineFile(const base::FilePath& file,
- const GURL& source_url,
- const GURL& referrer_url,
- const std::string& client_guid) {
- return QuarantineFileResult::OK;
+void QuarantineFile(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url,
+ const std::string& client_guid,
+ mojom::Quarantine::QuarantineFileCallback callback) {
+ std::move(callback).Run(QuarantineFileResult::OK);
}
} // namespace quarantine
-#endif // !WIN && !MAC
+#endif // !WIN && !MAC && !CHROMEOS
diff --git a/chromium/components/services/quarantine/quarantine.h b/chromium/components/services/quarantine/quarantine.h
index 3c3bf149ca2..949a17921ba 100644
--- a/chromium/components/services/quarantine/quarantine.h
+++ b/chromium/components/services/quarantine/quarantine.h
@@ -60,16 +60,18 @@ using mojom::QuarantineFileResult;
// |referrer_url|: Referring URL. This is empty for off-the-record download.
// |client_guid|: Only used on Windows. Identifies the client application
// that downloaded the file.
+// |callback|: Will be called with the quarantine result on completion.
//
// Note: The |source_url| and |referrer_url| will be stripped of unnecessary
// parts using SanitizeUrlForQuarantine() before they are used for annotation
// or notification purposes. If the URLs are sensitive -- e.g. because the
// download was made using an off-the-record profile -- then pass in an empty
// GURL() instead.
-QuarantineFileResult QuarantineFile(const base::FilePath& file,
- const GURL& source_url,
- const GURL& referrer_url,
- const std::string& client_guid);
+void QuarantineFile(const base::FilePath& file,
+ const GURL& source_url,
+ const GURL& referrer_url,
+ const std::string& client_guid,
+ mojom::Quarantine::QuarantineFileCallback callback);
#if defined(OS_WIN)
QuarantineFileResult SetInternetZoneIdentifierDirectly(
diff --git a/chromium/components/services/quarantine/quarantine_chromeos.cc b/chromium/components/services/quarantine/quarantine_chromeos.cc
new file mode 100644
index 00000000000..8996ed3046c
--- /dev/null
+++ b/chromium/components/services/quarantine/quarantine_chromeos.cc
@@ -0,0 +1,44 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/quarantine/quarantine.h"
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "chromeos/dbus/dlp/dlp_client.h"
+#include "chromeos/dbus/dlp/dlp_service.pb.h"
+#include "url/gurl.h"
+
+namespace quarantine {
+
+void OnFileAdded(mojom::Quarantine::QuarantineFileCallback callback,
+ const dlp::AddFileResponse response) {
+ if (response.has_error_message()) {
+ DVLOG(1) << "Failed to quarantine: " << response.error_message();
+ std::move(callback).Run(QuarantineFileResult::ANNOTATION_FAILED);
+ return;
+ }
+ std::move(callback).Run(QuarantineFileResult::OK);
+}
+
+void QuarantineFile(const base::FilePath& file,
+ const GURL& source_url_unsafe,
+ const GURL& referrer_url_unsafe,
+ const std::string& client_guid,
+ mojom::Quarantine::QuarantineFileCallback callback) {
+ if (!chromeos::DlpClient::Get() || !chromeos::DlpClient::Get()->IsAlive()) {
+ std::move(callback).Run(QuarantineFileResult::OK);
+ return;
+ }
+ dlp::AddFileRequest request;
+ request.set_file_path(file.value());
+ request.set_source_url(source_url_unsafe.spec());
+ request.set_referrer_url(referrer_url_unsafe.spec());
+ chromeos::DlpClient::Get()->AddFile(
+ request, base::BindOnce(&OnFileAdded, std::move(callback)));
+}
+
+} // namespace quarantine
diff --git a/chromium/components/services/quarantine/quarantine_impl.cc b/chromium/components/services/quarantine/quarantine_impl.cc
index 8324caabc6c..5fcd99151c8 100644
--- a/chromium/components/services/quarantine/quarantine_impl.cc
+++ b/chromium/components/services/quarantine/quarantine_impl.cc
@@ -5,19 +5,22 @@
#include "components/services/quarantine/quarantine_impl.h"
#include "base/bind.h"
-#include "base/files/file_util.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
-#include "base/task_runner_util.h"
-#include "build/build_config.h"
#include "components/services/quarantine/quarantine.h"
-#if defined(OS_WIN)
-#include "components/services/quarantine/public/cpp/quarantine_features_win.h"
-#endif // OS_WIN
-
namespace quarantine {
+namespace {
+
+void ReplyToCallback(scoped_refptr<base::TaskRunner> task_runner,
+ mojom::Quarantine::QuarantineFileCallback callback,
+ QuarantineFileResult result) {
+ task_runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback), result));
+}
+
+} // namespace
+
QuarantineImpl::QuarantineImpl() = default;
QuarantineImpl::QuarantineImpl(
@@ -26,46 +29,29 @@ QuarantineImpl::QuarantineImpl(
QuarantineImpl::~QuarantineImpl() = default;
-namespace {
-
-#if defined(OS_WIN)
-scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() {
- return base::ThreadPool::CreateCOMSTATaskRunner(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
-}
-#else // OS_WIN
-scoped_refptr<base::TaskRunner> GetTaskRunner() {
- return base::ThreadPool::CreateTaskRunner(
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
-}
-#endif // OS_WIN
-
-} // namespace
-
void QuarantineImpl::QuarantineFile(
const base::FilePath& full_path,
const GURL& source_url,
const GURL& referrer_url,
const std::string& client_guid,
mojom::Quarantine::QuarantineFileCallback callback) {
-#if defined(OS_WIN)
- if (base::FeatureList::IsEnabled(quarantine::kOutOfProcessQuarantine)) {
- // In out of process case, we are running in a utility process,
- // so directly call QuarantineFile and send the result.
- QuarantineFileResult result = quarantine::QuarantineFile(
- full_path, source_url, referrer_url, client_guid);
-
- std::move(callback).Run(result);
- return;
- }
-#endif // OS_WIN
- // For in-proc case, or non-Windows platforms, we are running in the browser
- // process, so post a task to do the potentially blocking quarantine work.
- base::PostTaskAndReplyWithResult(
- GetTaskRunner().get(), FROM_HERE,
- base::BindOnce(&quarantine::QuarantineFile, full_path, source_url,
- referrer_url, client_guid),
- std::move(callback));
+#if defined(OS_MAC)
+ // On Mac posting to a new task runner to do the potentially blocking
+ // quarantine work.
+ scoped_refptr<base::TaskRunner> task_runner =
+ base::ThreadPool::CreateTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+#else // OS_MAC
+ scoped_refptr<base::TaskRunner> task_runner =
+ base::ThreadTaskRunnerHandle::Get();
+#endif // OS_MAC
+ task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &quarantine::QuarantineFile, full_path, source_url, referrer_url,
+ client_guid,
+ base::BindOnce(&ReplyToCallback, base::ThreadTaskRunnerHandle::Get(),
+ std::move(callback))));
}
} // namespace quarantine
diff --git a/chromium/components/services/quarantine/quarantine_mac.mm b/chromium/components/services/quarantine/quarantine_mac.mm
index 1673e9b358e..fef1c3860e2 100644
--- a/chromium/components/services/quarantine/quarantine_mac.mm
+++ b/chromium/components/services/quarantine/quarantine_mac.mm
@@ -194,12 +194,15 @@ bool AddQuarantineMetadataToFile(const base::FilePath& file,
} // namespace
-QuarantineFileResult QuarantineFile(const base::FilePath& file,
- const GURL& source_url_unsafe,
- const GURL& referrer_url_unsafe,
- const std::string& client_guid) {
- if (!base::PathExists(file))
- return QuarantineFileResult::FILE_MISSING;
+void QuarantineFile(const base::FilePath& file,
+ const GURL& source_url_unsafe,
+ const GURL& referrer_url_unsafe,
+ const std::string& client_guid,
+ mojom::Quarantine::QuarantineFileCallback callback) {
+ if (!base::PathExists(file)) {
+ std::move(callback).Run(QuarantineFileResult::FILE_MISSING);
+ return;
+ }
GURL source_url = SanitizeUrlForQuarantine(source_url_unsafe);
GURL referrer_url = SanitizeUrlForQuarantine(referrer_url_unsafe);
@@ -208,8 +211,9 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file,
AddOriginMetadataToFile(file, source_url, referrer_url);
bool quarantine_succeeded =
AddQuarantineMetadataToFile(file, source_url, referrer_url);
- return quarantine_succeeded ? QuarantineFileResult::OK
- : QuarantineFileResult::ANNOTATION_FAILED;
+ std::move(callback).Run(quarantine_succeeded
+ ? QuarantineFileResult::OK
+ : QuarantineFileResult::ANNOTATION_FAILED);
}
} // namespace quarantine
diff --git a/chromium/components/services/quarantine/quarantine_mac_unittest.mm b/chromium/components/services/quarantine/quarantine_mac_unittest.mm
index 8fb074951de..c7358a3ddff 100644
--- a/chromium/components/services/quarantine/quarantine_mac_unittest.mm
+++ b/chromium/components/services/quarantine/quarantine_mac_unittest.mm
@@ -9,13 +9,16 @@
#import <ApplicationServices/ApplicationServices.h>
#import <Foundation/Foundation.h>
+#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h"
+#include "base/run_loop.h"
#include "base/strings/sys_string_conversions.h"
+#include "base/test/task_environment.h"
#include "components/services/quarantine/test_support.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
@@ -24,6 +27,11 @@
namespace quarantine {
namespace {
+void CheckQuarantineResult(QuarantineFileResult result,
+ QuarantineFileResult expected_result) {
+ EXPECT_EQ(expected_result, result);
+}
+
class QuarantineMacTest : public testing::Test {
public:
QuarantineMacTest()
@@ -52,6 +60,7 @@ class QuarantineMacTest : public testing::Test {
ASSERT_TRUE(success);
}
+ base::test::SingleThreadTaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
base::FilePath test_file_;
const GURL source_url_;
@@ -60,17 +69,22 @@ class QuarantineMacTest : public testing::Test {
};
TEST_F(QuarantineMacTest, CheckMetadataSetCorrectly) {
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, source_url_, referrer_url_, ""));
+ QuarantineFile(
+ test_file_, source_url_, referrer_url_, "",
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, referrer_url_));
}
TEST_F(QuarantineMacTest, SetMetadataMultipleTimes) {
GURL dummy_url("http://www.dummy.example.com");
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, source_url_, referrer_url_, ""));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, dummy_url, dummy_url, ""));
+ QuarantineFile(
+ test_file_, source_url_, referrer_url_, "",
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ QuarantineFile(
+ test_file_, dummy_url, dummy_url, "",
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, referrer_url_));
}
@@ -84,8 +98,10 @@ TEST_F(QuarantineMacTest, IsFileQuarantined_NoAnnotationsOnFile) {
}
TEST_F(QuarantineMacTest, IsFileQuarantined_SourceUrlOnly) {
- ASSERT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, source_url_, GURL(), std::string()));
+ QuarantineFile(
+ test_file_, source_url_, GURL(), std::string(),
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, GURL()));
EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), GURL()));
EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), referrer_url_));
@@ -93,9 +109,10 @@ TEST_F(QuarantineMacTest, IsFileQuarantined_SourceUrlOnly) {
}
TEST_F(QuarantineMacTest, IsFileQuarantined_FullMetadata) {
- ASSERT_EQ(
- QuarantineFileResult::OK,
- QuarantineFile(test_file_, source_url_, referrer_url_, std::string()));
+ QuarantineFile(
+ test_file_, source_url_, referrer_url_, std::string(),
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), GURL()));
EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, GURL()));
EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, referrer_url_));
@@ -110,15 +127,19 @@ TEST_F(QuarantineMacTest, IsFileQuarantined_Sanitize) {
GURL referrer_url{"https://user:pass@example.com/foo/index?x#y"};
GURL referrer_url_clean{"https://example.com/foo/index?x#y"};
- ASSERT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, host_url, referrer_url, std::string()));
+ QuarantineFile(
+ test_file_, host_url, referrer_url, std::string(),
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(
IsFileQuarantined(test_file_, host_url_clean, referrer_url_clean));
}
TEST_F(QuarantineMacTest, NoWhereFromsKeyIfNoURLs) {
- ASSERT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, GURL(), GURL(), std::string()));
+ QuarantineFile(
+ test_file_, GURL(), GURL(), std::string(),
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
NSString* file_path = base::mac::FilePathToNSString(test_file_);
ASSERT_NE(nullptr, file_path);
diff --git a/chromium/components/services/quarantine/quarantine_unittest.cc b/chromium/components/services/quarantine/quarantine_unittest.cc
index 6929217148e..2e47de6c18e 100644
--- a/chromium/components/services/quarantine/quarantine_unittest.cc
+++ b/chromium/components/services/quarantine/quarantine_unittest.cc
@@ -7,10 +7,13 @@
#include <iterator>
#include <string>
+#include "base/bind.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/run_loop.h"
#include "base/stl_util.h"
+#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -23,9 +26,15 @@ const char kInternetURL[] = "http://example.com/some-url";
const char kInternetReferrerURL[] = "http://example.com/some-other-url";
const char kTestGUID[] = "69f8621d-c46a-4e88-b915-1ce5415cb008";
+void CheckQuarantineResult(QuarantineFileResult result,
+ QuarantineFileResult expected_result) {
+ EXPECT_EQ(expected_result, result);
+}
+
} // namespace
TEST(QuarantineTest, FileCanBeOpenedForReadAfterAnnotation) {
+ base::test::SingleThreadTaskEnvironment task_environment;
base::ScopedTempDir test_dir;
ASSERT_TRUE(test_dir.CreateUniqueTempDir());
@@ -33,9 +42,10 @@ TEST(QuarantineTest, FileCanBeOpenedForReadAfterAnnotation) {
ASSERT_EQ(static_cast<int>(base::size(kTestData)),
base::WriteFile(test_file, kTestData, base::size(kTestData)));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(kInternetURL),
- GURL(kInternetReferrerURL), kTestGUID));
+ QuarantineFile(
+ test_file, GURL(kInternetURL), GURL(kInternetReferrerURL), kTestGUID,
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
std::string contents;
EXPECT_TRUE(base::ReadFileToString(test_file, &contents));
@@ -43,6 +53,7 @@ TEST(QuarantineTest, FileCanBeOpenedForReadAfterAnnotation) {
}
TEST(QuarantineTest, FileCanBeAnnotatedWithNoGUID) {
+ base::test::SingleThreadTaskEnvironment task_environment;
base::ScopedTempDir test_dir;
ASSERT_TRUE(test_dir.CreateUniqueTempDir());
@@ -50,9 +61,10 @@ TEST(QuarantineTest, FileCanBeAnnotatedWithNoGUID) {
ASSERT_EQ(static_cast<int>(base::size(kTestData)),
base::WriteFile(test_file, kTestData, base::size(kTestData)));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(kInternetURL),
- GURL(kInternetReferrerURL), std::string()));
+ QuarantineFile(
+ test_file, GURL(kInternetURL), GURL(kInternetReferrerURL), std::string(),
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
}
} // namespace quarantine
diff --git a/chromium/components/services/quarantine/quarantine_win.cc b/chromium/components/services/quarantine/quarantine_win.cc
index ac20b025d49..6c11fc6909c 100644
--- a/chromium/components/services/quarantine/quarantine_win.cc
+++ b/chromium/components/services/quarantine/quarantine_win.cc
@@ -228,16 +228,19 @@ QuarantineFileResult SetInternetZoneIdentifierDirectly(
: QuarantineFileResult::ANNOTATION_FAILED;
}
-QuarantineFileResult QuarantineFile(const base::FilePath& file,
- const GURL& source_url_unsafe,
- const GURL& referrer_url_unsafe,
- const std::string& client_guid) {
+void QuarantineFile(const base::FilePath& file,
+ const GURL& source_url_unsafe,
+ const GURL& referrer_url_unsafe,
+ const std::string& client_guid,
+ mojom::Quarantine::QuarantineFileCallback callback) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
int64_t file_size = 0;
- if (!base::PathExists(file) || !base::GetFileSize(file, &file_size))
- return QuarantineFileResult::FILE_MISSING;
+ if (!base::PathExists(file) || !base::GetFileSize(file, &file_size)) {
+ std::move(callback).Run(QuarantineFileResult::FILE_MISSING);
+ return;
+ }
std::string braces_guid = "{" + client_guid + "}";
GUID guid = GUID_NULL;
@@ -254,16 +257,20 @@ QuarantineFileResult QuarantineFile(const base::FilePath& file,
// Calling InvokeAttachmentServices on an empty file can result in the file
// being deleted. Also an anti-virus scan doesn't make a lot of sense to
// perform on an empty file.
- return SetInternetZoneIdentifierDirectly(file, source_url, referrer_url);
+ std::move(callback).Run(
+ SetInternetZoneIdentifierDirectly(file, source_url, referrer_url));
+ return;
}
QuarantineFileResult attachment_services_result = QuarantineFileResult::OK;
if (InvokeAttachmentServices(file, source_url, referrer_url, guid,
&attachment_services_result)) {
- return attachment_services_result;
+ std::move(callback).Run(attachment_services_result);
+ return;
}
- return SetInternetZoneIdentifierDirectly(file, source_url, referrer_url);
+ std::move(callback).Run(
+ SetInternetZoneIdentifierDirectly(file, source_url, referrer_url));
}
} // namespace quarantine
diff --git a/chromium/components/services/quarantine/quarantine_win_unittest.cc b/chromium/components/services/quarantine/quarantine_win_unittest.cc
index ac3570f7bcd..5f81c486cae 100644
--- a/chromium/components/services/quarantine/quarantine_win_unittest.cc
+++ b/chromium/components/services/quarantine/quarantine_win_unittest.cc
@@ -6,12 +6,15 @@
#include <wininet.h>
+#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/task_environment.h"
#include "base/test/test_file_util.h"
#include "base/test/test_reg_util_win.h"
#include "base/win/scoped_com_initializer.h"
@@ -123,6 +126,11 @@ bool AddInternetZoneIdentifierDirectly(const base::FilePath& file_path) {
static_cast<int>(base::size(kMotwForInternetZone));
}
+void CheckQuarantineResult(QuarantineFileResult result,
+ QuarantineFileResult expected_result) {
+ EXPECT_EQ(expected_result, result);
+}
+
} // namespace
class QuarantineWinTest : public ::testing::Test {
@@ -155,6 +163,8 @@ class QuarantineWinTest : public ::testing::Test {
const wchar_t* GetInternetSite() { return L"example.com"; }
private:
+ base::test::SingleThreadTaskEnvironment task_environment_;
+
registry_util::RegistryOverrideManager registry_override_;
base::ScopedTempDir scoped_temp_dir_;
@@ -173,10 +183,12 @@ class QuarantineWinTest : public ::testing::Test {
// If the file is missing, the QuarantineFile() call should return FILE_MISSING.
TEST_F(QuarantineWinTest, MissingFile) {
- EXPECT_EQ(QuarantineFileResult::FILE_MISSING,
- QuarantineFile(GetTempDir().AppendASCII("does-not-exist.exe"),
- GURL(kDummySourceUrl), GURL(kDummyReferrerUrl),
- kDummyClientGuid));
+ QuarantineFile(GetTempDir().AppendASCII("does-not-exist.exe"),
+ GURL(kDummySourceUrl), GURL(kDummyReferrerUrl),
+ kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult,
+ QuarantineFileResult::FILE_MISSING));
+ base::RunLoop().RunUntilIdle();
}
// On Windows systems, files downloaded from a local source are considered
@@ -195,9 +207,10 @@ TEST_F(QuarantineWinTest, LocalFile_DependsOnLocalConfig) {
ASSERT_TRUE(CreateFile(test_file));
- EXPECT_EQ(
- QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(source_url), GURL(), kDummyClientGuid));
+ QuarantineFile(
+ test_file, GURL(source_url), GURL(), kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
std::string zone_identifier;
GetZoneIdentifierStreamContents(test_file, &zone_identifier);
@@ -220,9 +233,11 @@ TEST_F(QuarantineWinTest, DownloadedFile_DependsOnLocalConfig) {
SCOPED_TRACE(::testing::Message() << "Trying URL " << source_url);
ASSERT_TRUE(CreateFile(test_file));
- EXPECT_EQ(
- QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(source_url), GURL(), kDummyClientGuid));
+
+ QuarantineFile(
+ test_file, GURL(source_url), GURL(), kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
std::string zone_identifier;
ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
@@ -251,9 +266,11 @@ TEST_F(QuarantineWinTest, UnsafeReferrer_DependsOnLocalConfig) {
SCOPED_TRACE(::testing::Message() << "Trying URL " << referrer_url);
ASSERT_TRUE(CreateFile(test_file));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL("http://example.com/good"),
- GURL(referrer_url), kDummyClientGuid));
+ QuarantineFile(
+ test_file, GURL("http://example.com/good"), GURL(referrer_url),
+ kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
std::string zone_identifier;
ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
@@ -273,8 +290,10 @@ TEST_F(QuarantineWinTest, EmptySource_DependsOnLocalConfig) {
base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
ASSERT_TRUE(CreateFile(test_file));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(), GURL(), kDummyClientGuid));
+ QuarantineFile(
+ test_file, GURL(), GURL(), kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
std::string zone_identifier;
ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
@@ -292,9 +311,10 @@ TEST_F(QuarantineWinTest, EmptyFile) {
base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
ASSERT_EQ(0, base::WriteFile(test_file, "", 0u));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, net::FilePathToFileURL(test_file), GURL(),
- kDummyClientGuid));
+ QuarantineFile(
+ test_file, net::FilePathToFileURL(test_file), GURL(), kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
std::string zone_identifier;
ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
@@ -313,9 +333,10 @@ TEST_F(QuarantineWinTest, NoClientGuid) {
base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
ASSERT_TRUE(CreateFile(test_file));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, net::FilePathToFileURL(test_file), GURL(),
- std::string()));
+ QuarantineFile(
+ test_file, net::FilePathToFileURL(test_file), GURL(), std::string(),
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
std::string zone_identifier;
ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
@@ -335,8 +356,10 @@ TEST_F(QuarantineWinTest, SuperLongURL) {
std::string source_url("http://example.com/");
source_url.append(INTERNET_MAX_URL_LENGTH * 2, 'a');
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(source_url), GURL(), std::string()));
+ QuarantineFile(
+ test_file, GURL(source_url), GURL(), std::string(),
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
std::string zone_identifier;
ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
@@ -354,8 +377,10 @@ TEST_F(QuarantineWinTest, TrustedSite) {
base::StringPrintf(L"https://%ls/folder/good.exe", GetTrustedSite())));
ASSERT_TRUE(CreateFile(test_file));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, source_url, GURL(), kDummyClientGuid));
+ QuarantineFile(
+ test_file, source_url, GURL(), kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
// No zone identifier.
std::string zone_identifier;
@@ -371,8 +396,10 @@ TEST_F(QuarantineWinTest, RestrictedSite) {
ASSERT_TRUE(CreateFile(test_file));
// Files from a restricted site are deleted.
- EXPECT_EQ(QuarantineFileResult::BLOCKED_BY_POLICY,
- QuarantineFile(test_file, source_url, GURL(), kDummyClientGuid));
+ QuarantineFile(test_file, source_url, GURL(), kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult,
+ QuarantineFileResult::BLOCKED_BY_POLICY));
+ base::RunLoop().RunUntilIdle();
std::string zone_identifier;
EXPECT_FALSE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
@@ -387,8 +414,10 @@ TEST_F(QuarantineWinTest, TrustedSite_AlreadyQuarantined) {
ASSERT_TRUE(CreateFile(test_file));
// Ensure the file already contains a zone identifier.
ASSERT_TRUE(AddInternetZoneIdentifierDirectly(test_file));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, source_url, GURL(), kDummyClientGuid));
+ QuarantineFile(
+ test_file, source_url, GURL(), kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
// The existing zone identifier was not removed.
std::string zone_identifier;
@@ -408,8 +437,10 @@ TEST_F(QuarantineWinTest, RestrictedSite_AlreadyQuarantined) {
ASSERT_TRUE(AddInternetZoneIdentifierDirectly(test_file));
// Files from a restricted site are deleted.
- EXPECT_EQ(QuarantineFileResult::BLOCKED_BY_POLICY,
- QuarantineFile(test_file, source_url, GURL(), kDummyClientGuid));
+ QuarantineFile(test_file, source_url, GURL(), kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult,
+ QuarantineFileResult::BLOCKED_BY_POLICY));
+ base::RunLoop().RunUntilIdle();
std::string zone_identifier;
EXPECT_FALSE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
@@ -429,8 +460,10 @@ TEST_F(QuarantineWinTest, MetaData_ApplyMOTW_Directly) {
base::StringPrintf(L"https://%ls/folder/index?x#y", GetInternetSite())));
// An invalid GUID will cause QuarantineFile() to apply the MOTW directly.
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, host_url, referrer_url, std::string()));
+ QuarantineFile(
+ test_file, host_url, referrer_url, std::string(),
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsFileQuarantined(test_file, host_url_clean, referrer_url_clean));
}
@@ -448,9 +481,10 @@ TEST_F(QuarantineWinTest, MetaData_InvokeAS) {
GURL referrer_url_clean = GURL(base::WideToUTF8(
base::StringPrintf(L"https://%ls/folder/index?x#y", GetInternetSite())));
- EXPECT_EQ(
- QuarantineFileResult::OK,
- QuarantineFile(test_file, host_url, referrer_url, kDummyClientGuid));
+ QuarantineFile(
+ test_file, host_url, referrer_url, kDummyClientGuid,
+ base::BindOnce(&CheckQuarantineResult, QuarantineFileResult::OK));
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(IsFileQuarantined(test_file, host_url_clean, referrer_url_clean));
}
diff --git a/chromium/components/services/quarantine/test_support.h b/chromium/components/services/quarantine/test_support.h
index 1a1bf013ec2..5ccfa776d05 100644
--- a/chromium/components/services/quarantine/test_support.h
+++ b/chromium/components/services/quarantine/test_support.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SERVICES_QUARANTINE_TEST_SUPPORT_H_
#define COMPONENTS_SERVICES_QUARANTINE_TEST_SUPPORT_H_
-#include <string>
-
class GURL;
namespace base {
diff --git a/chromium/components/services/storage/BUILD.gn b/chromium/components/services/storage/BUILD.gn
index 140cd17933c..3d540f5cf75 100644
--- a/chromium/components/services/storage/BUILD.gn
+++ b/chromium/components/services/storage/BUILD.gn
@@ -177,8 +177,10 @@ source_set("tests") {
"//base",
"//base/test:test_support",
"//components/services/storage/public/cpp",
+ "//components/services/storage/public/cpp:tests",
"//components/services/storage/public/cpp/filesystem:tests",
"//components/services/storage/public/mojom",
+ "//components/services/storage/public/mojom:tests",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//net",
diff --git a/chromium/components/services/storage/dom_storage/DIR_METADATA b/chromium/components/services/storage/dom_storage/DIR_METADATA
index f5d80839f32..69f4bfe2410 100644
--- a/chromium/components/services/storage/dom_storage/DIR_METADATA
+++ b/chromium/components/services/storage/dom_storage/DIR_METADATA
@@ -2,4 +2,3 @@ monorail {
component: "Blink>Storage>DOMStorage"
}
-team_email: "storage-dev@chromium.org"
diff --git a/chromium/components/services/storage/dom_storage/async_dom_storage_database.cc b/chromium/components/services/storage/dom_storage/async_dom_storage_database.cc
index 5a17141ab33..2c5d5fe12f8 100644
--- a/chromium/components/services/storage/dom_storage/async_dom_storage_database.cc
+++ b/chromium/components/services/storage/dom_storage/async_dom_storage_database.cc
@@ -11,10 +11,9 @@
#include <string>
#include <utility>
-#include "base/optional.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
@@ -26,7 +25,7 @@ std::unique_ptr<AsyncDomStorageDatabase> AsyncDomStorageDatabase::OpenDirectory(
const leveldb_env::Options& options,
const base::FilePath& directory,
const std::string& dbname,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
StatusCallback callback) {
@@ -41,7 +40,7 @@ std::unique_ptr<AsyncDomStorageDatabase> AsyncDomStorageDatabase::OpenDirectory(
// static
std::unique_ptr<AsyncDomStorageDatabase> AsyncDomStorageDatabase::OpenInMemory(
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
const std::string& tracking_name,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
diff --git a/chromium/components/services/storage/dom_storage/async_dom_storage_database.h b/chromium/components/services/storage/dom_storage/async_dom_storage_database.h
index 9ce591c8add..26ae951e43c 100644
--- a/chromium/components/services/storage/dom_storage/async_dom_storage_database.h
+++ b/chromium/components/services/storage/dom_storage/async_dom_storage_database.h
@@ -37,13 +37,13 @@ class AsyncDomStorageDatabase {
const leveldb_env::Options& options,
const base::FilePath& directory,
const std::string& dbname,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
StatusCallback callback);
static std::unique_ptr<AsyncDomStorageDatabase> OpenInMemory(
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
const std::string& tracking_name,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
diff --git a/chromium/components/services/storage/dom_storage/dom_storage_database.cc b/chromium/components/services/storage/dom_storage/dom_storage_database.cc
index 6ebb0aa3516..7bbf0bcd44c 100644
--- a/chromium/components/services/storage/dom_storage/dom_storage_database.cc
+++ b/chromium/components/services/storage/dom_storage/dom_storage_database.cc
@@ -181,7 +181,7 @@ DomStorageDatabase::DomStorageDatabase(
const base::FilePath& directory,
const std::string& name,
const leveldb_env::Options& options,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
StatusCallback callback)
@@ -194,7 +194,7 @@ DomStorageDatabase::DomStorageDatabase(
DomStorageDatabase::DomStorageDatabase(
const std::string& tracking_name,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
StatusCallback callback)
@@ -209,7 +209,7 @@ DomStorageDatabase::DomStorageDatabase(
const std::string& name,
std::unique_ptr<leveldb::Env> env,
const leveldb_env::Options& options,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
StatusCallback callback)
@@ -240,7 +240,7 @@ void DomStorageDatabase::OpenDirectory(
const base::FilePath& directory,
const std::string& name,
const leveldb_env::Options& options,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
OpenCallback callback) {
@@ -253,7 +253,7 @@ void DomStorageDatabase::OpenDirectory(
// static
void DomStorageDatabase::OpenInMemory(
const std::string& name,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
OpenCallback callback) {
diff --git a/chromium/components/services/storage/dom_storage/dom_storage_database.h b/chromium/components/services/storage/dom_storage/dom_storage_database.h
index ffe142c3c6e..2388d41e21b 100644
--- a/chromium/components/services/storage/dom_storage/dom_storage_database.h
+++ b/chromium/components/services/storage/dom_storage/dom_storage_database.h
@@ -16,12 +16,12 @@
#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/abseil-cpp/absl/types/optional.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"
@@ -86,7 +86,7 @@ class DomStorageDatabase : private base::trace_event::MemoryDumpProvider {
const base::FilePath& directory,
const std::string& name,
const leveldb_env::Options& options,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
OpenCallback callback);
@@ -98,7 +98,7 @@ class DomStorageDatabase : private base::trace_event::MemoryDumpProvider {
// sequence once the operation completes.
static void OpenInMemory(
const std::string& name,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
OpenCallback callback);
@@ -166,7 +166,7 @@ class DomStorageDatabase : private base::trace_event::MemoryDumpProvider {
const base::FilePath& directory,
const std::string& name,
const leveldb_env::Options& options,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
StatusCallback callback);
@@ -175,7 +175,7 @@ class DomStorageDatabase : private base::trace_event::MemoryDumpProvider {
// internally for memory dump details.
DomStorageDatabase(
const std::string& tracking_name,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>&
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>&
memory_dump_id,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
StatusCallback callback);
@@ -184,7 +184,7 @@ class DomStorageDatabase : private base::trace_event::MemoryDumpProvider {
const std::string& name,
std::unique_ptr<leveldb::Env> env,
const leveldb_env::Options& options,
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>
memory_dump_id_,
scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
StatusCallback callback);
@@ -196,7 +196,7 @@ class DomStorageDatabase : private base::trace_event::MemoryDumpProvider {
const std::string name_;
const std::unique_ptr<leveldb::Env> env_;
const leveldb_env::Options options_;
- const base::Optional<base::trace_event::MemoryAllocatorDumpGuid>
+ const absl::optional<base::trace_event::MemoryAllocatorDumpGuid>
memory_dump_id_;
std::unique_ptr<leveldb::DB> db_;
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
index f183c32379d..398e2e80696 100644
--- a/chromium/components/services/storage/dom_storage/dom_storage_database_unittest.cc
+++ b/chromium/components/services/storage/dom_storage/dom_storage_database_unittest.cc
@@ -59,7 +59,7 @@ DomStorageDatabase::KeyValuePair MakeKeyValuePair(base::StringPiece key,
}
std::string MakePrefixedKey(base::StringPiece prefix, base::StringPiece key) {
- return prefix.as_string() + key.as_string();
+ return std::string(prefix) + std::string(key);
}
class StorageServiceDomStorageDatabaseTest : public testing::Test {
@@ -75,7 +75,7 @@ class StorageServiceDomStorageDatabaseTest : public testing::Test {
base::SequenceBound<DomStorageDatabase> result;
base::RunLoop loop;
DomStorageDatabase::OpenInMemory(
- db_name, /*memory_dump_id=*/base::nullopt, blocking_task_runner_,
+ db_name, /*memory_dump_id=*/absl::nullopt, blocking_task_runner_,
base::BindLambdaForTesting(
[&](base::SequenceBound<DomStorageDatabase> database,
leveldb::Status status) {
@@ -94,7 +94,7 @@ class StorageServiceDomStorageDatabaseTest : public testing::Test {
base::SequenceBound<DomStorageDatabase> result;
base::RunLoop loop;
DomStorageDatabase::OpenDirectory(
- directory, db_name, options, /*memory_dump_id=*/base::nullopt,
+ directory, db_name, options, /*memory_dump_id=*/absl::nullopt,
blocking_task_runner_,
base::BindLambdaForTesting(
[&](base::SequenceBound<DomStorageDatabase> database,
diff --git a/chromium/components/services/storage/dom_storage/legacy_dom_storage_database.cc b/chromium/components/services/storage/dom_storage/legacy_dom_storage_database.cc
index 716f17196a0..e953815ffe1 100644
--- a/chromium/components/services/storage/dom_storage/legacy_dom_storage_database.cc
+++ b/chromium/components/services/storage/dom_storage/legacy_dom_storage_database.cc
@@ -91,7 +91,7 @@ bool LegacyDomStorageDatabase::CommitChanges(
for (; it != changes.end(); ++it) {
sql::Statement statement;
const std::u16string& key = it->first;
- const base::Optional<std::u16string>& value = it->second;
+ const absl::optional<std::u16string>& value = it->second;
if (!value.has_value()) {
statement.Assign(db_->GetCachedStatement(
SQL_FROM_HERE, "DELETE FROM ItemTable WHERE key=?"));
@@ -240,7 +240,7 @@ bool LegacyDomStorageDatabase::DeleteFileAndRecreate() {
tried_to_recreate_ = true;
- base::Optional<base::File::Info> info =
+ absl::optional<base::File::Info> info =
filesystem_proxy_->GetFileInfo(file_path_);
// If it's not a directory and we can delete the file, try and open it again.
if (info && !info->is_directory && sql::Database::Delete(file_path_)) {
diff --git a/chromium/components/services/storage/dom_storage/legacy_dom_storage_database.h b/chromium/components/services/storage/dom_storage/legacy_dom_storage_database.h
index 5227ba99e6e..4592339bd09 100644
--- a/chromium/components/services/storage/dom_storage/legacy_dom_storage_database.h
+++ b/chromium/components/services/storage/dom_storage/legacy_dom_storage_database.h
@@ -24,7 +24,7 @@ namespace storage {
class FilesystemProxy;
using LegacyDomStorageValuesMap =
- std::map<std::u16string, base::Optional<std::u16string>>;
+ std::map<std::u16string, absl::optional<std::u16string>>;
// Represents a SQLite based backing for DOM storage data. This
// class is designed to be used on a single thread.
diff --git a/chromium/components/services/storage/dom_storage/legacy_dom_storage_database_unittest.cc b/chromium/components/services/storage/dom_storage/legacy_dom_storage_database_unittest.cc
index d4cf2881b99..f187579a570 100644
--- a/chromium/components/services/storage/dom_storage/legacy_dom_storage_database_unittest.cc
+++ b/chromium/components/services/storage/dom_storage/legacy_dom_storage_database_unittest.cc
@@ -56,8 +56,8 @@ void CheckValuesMatch(LegacyDomStorageDatabase* db,
LegacyDomStorageValuesMap::const_iterator it = values_read.begin();
for (; it != values_read.end(); ++it) {
const std::u16string& key = it->first;
- const base::Optional<std::u16string>& value = it->second;
- const base::Optional<std::u16string>& expected_value =
+ const absl::optional<std::u16string>& value = it->second;
+ const absl::optional<std::u16string>& expected_value =
expected.find(key)->second;
EXPECT_EQ(expected_value, value);
}
@@ -135,7 +135,7 @@ TEST(LegacyDomStorageDatabaseTest, CloseEmptyDatabaseDeletesFile) {
ASSERT_TRUE(db.CommitChanges(false, storage));
auto it = storage.begin();
for (; it != storage.end(); ++it)
- it->second = base::nullopt;
+ it->second = absl::nullopt;
ASSERT_TRUE(db.CommitChanges(false, storage));
}
EXPECT_FALSE(base::PathExists(file_name));
@@ -229,7 +229,7 @@ TEST(LegacyDomStorageDatabaseTest, TestSimpleRemoveOneValue) {
LegacyDomStorageValuesMap values;
// A null string in the map should mean that that key gets
// removed.
- values[kCannedKey] = base::nullopt;
+ values[kCannedKey] = absl::nullopt;
EXPECT_TRUE(db.CommitChanges(false, values));
expected.clear();
diff --git a/chromium/components/services/storage/dom_storage/local_storage_impl.cc b/chromium/components/services/storage/dom_storage/local_storage_impl.cc
index 33d8bdbb13b..53f4bcd8f3f 100644
--- a/chromium/components/services/storage/dom_storage/local_storage_impl.cc
+++ b/chromium/components/services/storage/dom_storage/local_storage_impl.cc
@@ -21,7 +21,6 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
-#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
@@ -43,6 +42,7 @@
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "sql/database.h"
#include "storage/common/database/database_identifier.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/leveldb_chrome.h"
@@ -98,14 +98,14 @@ DomStorageDatabase::Key CreateMetaDataKey(const url::Origin& origin) {
return key;
}
-base::Optional<url::Origin> ExtractOriginFromMetaDataKey(
+absl::optional<url::Origin> ExtractOriginFromMetaDataKey(
const DomStorageDatabase::Key& key) {
DCHECK_GT(key.size(), base::size(kMetaPrefix));
const base::StringPiece key_string(reinterpret_cast<const char*>(key.data()),
key.size());
const GURL url(key_string.substr(base::size(kMetaPrefix)));
if (!url.is_valid())
- return base::nullopt;
+ return absl::nullopt;
return url::Origin::Create(url);
}
@@ -225,7 +225,7 @@ std::vector<mojom::StorageUsageInfoPtr> GetLegacyLocalStorageUsage(
for (const auto& path : result.value()) {
if (!path.MatchesExtension(kLegacyDatabaseFileExtension))
continue;
- base::Optional<base::File::Info> info = fs->GetFileInfo(path);
+ absl::optional<base::File::Info> info = fs->GetFileInfo(path);
if (!info)
continue;
infos.emplace_back(mojom::StorageUsageInfo::New(
@@ -391,7 +391,7 @@ class LocalStorageImpl::StorageAreaHolder final
key[out] = char_val;
}
// Delete incorrect key.
- changes.push_back(std::make_pair(it.first, base::nullopt));
+ changes.push_back(std::make_pair(it.first, absl::nullopt));
fix_count++;
// Check if correct key already exists in data.
auto new_it = data.find(key);
@@ -1044,7 +1044,7 @@ void LocalStorageImpl::OnGotMetaData(
std::vector<mojom::StorageUsageInfoPtr> result;
std::set<url::Origin> origins;
for (const auto& row : data) {
- base::Optional<url::Origin> origin = ExtractOriginFromMetaDataKey(row.key);
+ absl::optional<url::Origin> origin = ExtractOriginFromMetaDataKey(row.key);
origins.insert(origin.value_or(url::Origin()));
if (!origin) {
// TODO(mek): Deal with database corruption.
diff --git a/chromium/components/services/storage/dom_storage/local_storage_impl_unittest.cc b/chromium/components/services/storage/dom_storage/local_storage_impl_unittest.cc
index b96ca1d7e5d..cee781065ae 100644
--- a/chromium/components/services/storage/dom_storage/local_storage_impl_unittest.cc
+++ b/chromium/components/services/storage/dom_storage/local_storage_impl_unittest.cc
@@ -53,7 +53,7 @@ class TestLevelDBObserver : public blink::mojom::StorageAreaObserver {
struct Observation {
enum { kChange, kChangeFailed, kDelete, kDeleteAll } type;
std::string key;
- base::Optional<std::string> old_value;
+ absl::optional<std::string> old_value;
std::string new_value;
std::string source;
};
@@ -69,12 +69,12 @@ class TestLevelDBObserver : public blink::mojom::StorageAreaObserver {
private:
void KeyChanged(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& new_value,
- const base::Optional<std::vector<uint8_t>>& old_value,
+ const absl::optional<std::vector<uint8_t>>& old_value,
const std::string& source) override {
observations_.push_back(
{Observation::kChange, Uint8VectorToStdString(key),
- old_value ? base::make_optional(Uint8VectorToStdString(*old_value))
- : base::nullopt,
+ old_value ? absl::make_optional(Uint8VectorToStdString(*old_value))
+ : absl::nullopt,
Uint8VectorToStdString(new_value), source});
}
void KeyChangeFailed(const std::vector<uint8_t>& key,
@@ -83,12 +83,12 @@ class TestLevelDBObserver : public blink::mojom::StorageAreaObserver {
Uint8VectorToStdString(key), "", "", source});
}
void KeyDeleted(const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& old_value,
+ const absl::optional<std::vector<uint8_t>>& old_value,
const std::string& source) override {
observations_.push_back(
{Observation::kDelete, Uint8VectorToStdString(key),
- old_value ? base::make_optional(Uint8VectorToStdString(*old_value))
- : base::nullopt,
+ old_value ? absl::make_optional(Uint8VectorToStdString(*old_value))
+ : absl::nullopt,
"", source});
}
void AllDeleted(bool was_nonempty, const std::string& source) override {
@@ -209,7 +209,7 @@ class LocalStorageImplTest : public testing::Test {
return result;
}
- base::Optional<std::vector<uint8_t>> DoTestGet(
+ absl::optional<std::vector<uint8_t>> DoTestGet(
const std::vector<uint8_t>& key) {
const url::Origin kOrigin = url::Origin::Create(GURL("http://foobar.com"));
mojo::Remote<blink::mojom::StorageArea> area;
@@ -220,8 +220,8 @@ class LocalStorageImplTest : public testing::Test {
dummy_area.BindNewPipeAndPassReceiver());
std::vector<uint8_t> result;
bool success = test::GetSync(area.get(), key, &result);
- return success ? base::Optional<std::vector<uint8_t>>(result)
- : base::nullopt;
+ return success ? absl::optional<std::vector<uint8_t>>(result)
+ : absl::nullopt;
}
// Pumps both the main-thread sequence and the background database sequence
@@ -235,7 +235,7 @@ class LocalStorageImplTest : public testing::Test {
base::RunLoop run_loop;
context()->BindStorageArea(url::Origin::Create(GURL("http://foobar.com")),
area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source",
+ area->Put(key, value, absl::nullopt, "source",
test::MakeSuccessCallback(run_loop.QuitClosure(), &success));
run_loop.Run();
EXPECT_TRUE(success);
@@ -305,7 +305,7 @@ TEST_F(LocalStorageImplTest, Basic) {
context()->BindStorageArea(url::Origin::Create(GURL("http://foobar.com")),
area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
RunUntilIdle();
@@ -325,11 +325,11 @@ TEST_F(LocalStorageImplTest, OriginsAreIndependent) {
mojo::Remote<blink::mojom::StorageArea> area;
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
- area->Put(key1, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key1, value, absl::nullopt, "source", base::DoNothing());
area.reset();
context()->BindStorageArea(origin2, area.BindNewPipeAndPassReceiver());
- area->Put(key2, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key2, value, absl::nullopt, "source", base::DoNothing());
area.reset();
RunUntilIdle();
@@ -347,7 +347,7 @@ TEST_F(LocalStorageImplTest, WrapperOutlivesMojoConnection) {
const url::Origin kOrigin(url::Origin::Create(GURL("http://foobar.com")));
context()->BindStorageArea(kOrigin, area.BindNewPipeAndPassReceiver());
context()->BindStorageArea(kOrigin, dummy_area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
dummy_area.reset();
@@ -365,7 +365,7 @@ TEST_F(LocalStorageImplTest, WrapperOutlivesMojoConnection) {
context()->PurgeMemory();
// And make sure caches were actually cleared.
- EXPECT_EQ(base::nullopt, DoTestGet(key));
+ EXPECT_EQ(absl::nullopt, DoTestGet(key));
}
TEST_F(LocalStorageImplTest, OpeningWrappersPurgesInactiveWrappers) {
@@ -376,7 +376,7 @@ TEST_F(LocalStorageImplTest, OpeningWrappersPurgesInactiveWrappers) {
mojo::Remote<blink::mojom::StorageArea> area;
context()->BindStorageArea(url::Origin::Create(GURL("http://foobar.com")),
area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
RunUntilIdle();
@@ -396,7 +396,7 @@ TEST_F(LocalStorageImplTest, OpeningWrappersPurgesInactiveWrappers) {
RunUntilIdle();
// And make sure caches were actually cleared.
- EXPECT_EQ(base::nullopt, DoTestGet(key));
+ EXPECT_EQ(absl::nullopt, DoTestGet(key));
}
TEST_F(LocalStorageImplTest, ValidVersion) {
@@ -415,11 +415,11 @@ TEST_F(LocalStorageImplTest, InvalidVersion) {
// Force the a reload of the database, which should fail due to invalid
// version data.
ResetStorage(storage_path());
- EXPECT_EQ(base::nullopt, DoTestGet(StdStringToUint8Vector("key")));
+ EXPECT_EQ(absl::nullopt, DoTestGet(StdStringToUint8Vector("key")));
}
TEST_F(LocalStorageImplTest, VersionOnlyWrittenOnCommit) {
- EXPECT_EQ(base::nullopt, DoTestGet(StdStringToUint8Vector("key")));
+ EXPECT_EQ(absl::nullopt, DoTestGet(StdStringToUint8Vector("key")));
RunUntilIdle();
EXPECT_TRUE(GetDatabaseContents().empty());
@@ -442,12 +442,12 @@ TEST_F(LocalStorageImplTest, GetStorageUsage_Data) {
mojo::Remote<blink::mojom::StorageArea> area;
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
- area->Put(key1, value, base::nullopt, "source", base::DoNothing());
- area->Put(key2, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key1, value, absl::nullopt, "source", base::DoNothing());
+ area->Put(key2, value, absl::nullopt, "source", base::DoNothing());
area.reset();
context()->BindStorageArea(origin2, area.BindNewPipeAndPassReceiver());
- area->Put(key2, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key2, value, absl::nullopt, "source", base::DoNothing());
area.reset();
// Make sure all data gets committed to disk.
@@ -477,10 +477,10 @@ TEST_F(LocalStorageImplTest, MetaDataClearedOnDelete) {
mojo::Remote<blink::mojom::StorageArea> area;
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
context()->BindStorageArea(origin2, area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
area->Delete(key, value, "source", base::DoNothing());
@@ -510,10 +510,10 @@ TEST_F(LocalStorageImplTest, MetaDataClearedOnDeleteAll) {
mojo::Remote<blink::mojom::StorageArea> area;
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
context()->BindStorageArea(origin2, area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
@@ -556,11 +556,11 @@ TEST_F(LocalStorageImplTest, DeleteStorageWithoutConnection) {
mojo::Remote<blink::mojom::StorageArea> area;
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
context()->BindStorageArea(origin2, area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
// Make sure all data gets committed to disk.
@@ -591,11 +591,11 @@ TEST_F(LocalStorageImplTest, DeleteStorageNotifiesWrapper) {
mojo::Remote<blink::mojom::StorageArea> area;
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
context()->BindStorageArea(origin2, area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
// Make sure all data gets committed to disk.
@@ -635,11 +635,11 @@ TEST_F(LocalStorageImplTest, DeleteStorageWithPendingWrites) {
mojo::Remote<blink::mojom::StorageArea> area;
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
context()->BindStorageArea(origin2, area.BindNewPipeAndPassReceiver());
- area->Put(key, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key, value, absl::nullopt, "source", base::DoNothing());
area.reset();
// Make sure all data gets committed to disk.
@@ -649,7 +649,7 @@ TEST_F(LocalStorageImplTest, DeleteStorageWithPendingWrites) {
TestLevelDBObserver observer;
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
area->AddObserver(observer.Bind());
- area->Put(StdStringToUint8Vector("key2"), value, base::nullopt, "source",
+ area->Put(StdStringToUint8Vector("key2"), value, absl::nullopt, "source",
base::DoNothing());
RunUntilIdle();
@@ -816,12 +816,12 @@ TEST_F(LocalStorageImplTest, ShutdownClearsData) {
mojo::Remote<blink::mojom::StorageArea> area;
context()->BindStorageArea(origin1, area.BindNewPipeAndPassReceiver());
- area->Put(key1, value, base::nullopt, "source", base::DoNothing());
- area->Put(key2, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key1, value, absl::nullopt, "source", base::DoNothing());
+ area->Put(key2, value, absl::nullopt, "source", base::DoNothing());
area.reset();
context()->BindStorageArea(origin2, area.BindNewPipeAndPassReceiver());
- area->Put(key2, value, base::nullopt, "source", base::DoNothing());
+ area->Put(key2, value, absl::nullopt, "source", base::DoNothing());
area.reset();
// Make sure all data gets committed to the DB.
@@ -980,8 +980,8 @@ TEST_F(LocalStorageImplTest, CorruptionOnDisk) {
}
TEST_F(LocalStorageImplTest, RecreateOnCommitFailure) {
- base::Optional<base::RunLoop> open_loop;
- base::Optional<base::RunLoop> destruction_loop;
+ absl::optional<base::RunLoop> open_loop;
+ absl::optional<base::RunLoop> destruction_loop;
size_t num_database_open_requests = 0;
context()->SetDatabaseOpenCallbackForTesting(base::BindLambdaForTesting([&] {
++num_database_open_requests;
@@ -1042,7 +1042,7 @@ TEST_F(LocalStorageImplTest, RecreateOnCommitFailure) {
// Start a put operation on the third connection before starting to commit
// a lot of data on the first origin. This put operation should result in a
// pending commit that will get cancelled when the database is destroyed.
- area3->Put(key, value, base::nullopt, "source",
+ area3->Put(key, value, absl::nullopt, "source",
base::BindOnce([](bool success) { EXPECT_TRUE(success); }));
// Repeatedly write data to the database, to trigger enough commit errors.
@@ -1050,7 +1050,7 @@ TEST_F(LocalStorageImplTest, RecreateOnCommitFailure) {
while (area1.is_connected()) {
// Every write needs to be different to make sure there actually is a
value[0]++;
- area1->Put(key, value, base::nullopt, "source",
+ area1->Put(key, value, absl::nullopt, "source",
base::BindLambdaForTesting([&](bool success) {
EXPECT_TRUE(success);
values_written++;
@@ -1080,7 +1080,7 @@ TEST_F(LocalStorageImplTest, RecreateOnCommitFailure) {
bool success = true;
TestLevelDBObserver observer3;
area1->AddObserver(observer3.Bind());
- area1->Delete(key, base::nullopt, "source",
+ area1->Delete(key, absl::nullopt, "source",
base::BindLambdaForTesting([&](bool success_in) {
success = success_in;
delete_loop.Quit();
@@ -1113,7 +1113,7 @@ TEST_F(LocalStorageImplTest, RecreateOnCommitFailure) {
TEST_F(LocalStorageImplTest, DontRecreateOnRepeatedCommitFailure) {
// Ensure that the opened database always fails on write.
- base::Optional<base::RunLoop> open_loop;
+ absl::optional<base::RunLoop> open_loop;
size_t num_database_open_requests = 0;
size_t num_databases_destroyed = 0;
context()->SetDatabaseOpenCallbackForTesting(base::BindLambdaForTesting([&] {
@@ -1149,7 +1149,7 @@ TEST_F(LocalStorageImplTest, DontRecreateOnRepeatedCommitFailure) {
open_loop.emplace();
// Repeatedly write data to the database, to trigger enough commit errors.
- base::Optional<std::vector<uint8_t>> old_value;
+ absl::optional<std::vector<uint8_t>> old_value;
while (area.is_connected()) {
// Every write needs to be different to make sure there actually is a
// change to commit.
@@ -1186,7 +1186,7 @@ TEST_F(LocalStorageImplTest, DontRecreateOnRepeatedCommitFailure) {
// getting ignored.
context()->BindStorageArea(url::Origin::Create(GURL("http://foobar.com")),
area.BindNewPipeAndPassReceiver());
- old_value = base::nullopt;
+ old_value = absl::nullopt;
for (int i = 0; i < 64; ++i) {
// Every write needs to be different to make sure there actually is a
// change to commit.
diff --git a/chromium/components/services/storage/dom_storage/session_storage_area_impl.cc b/chromium/components/services/storage/dom_storage/session_storage_area_impl.cc
index 527c77f06d0..7c4cbef16f3 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_area_impl.cc
+++ b/chromium/components/services/storage/dom_storage/session_storage_area_impl.cc
@@ -22,23 +22,25 @@ SessionStorageAreaImpl::SessionStorageAreaImpl(
: namespace_entry_(namespace_entry),
origin_(std::move(origin)),
shared_data_map_(std::move(data_map)),
- register_new_map_callback_(std::move(register_new_map_callback)) {}
+ register_new_map_callback_(std::move(register_new_map_callback)) {
+ receivers_.set_disconnect_handler(base::BindRepeating(
+ &SessionStorageAreaImpl::OnConnectionError, base::Unretained(this)));
+}
SessionStorageAreaImpl::~SessionStorageAreaImpl() {
- if (receiver_.is_bound())
+ if (IsBound())
shared_data_map_->RemoveBindingReference();
}
void SessionStorageAreaImpl::Bind(
mojo::PendingReceiver<blink::mojom::StorageArea> receiver) {
- if (IsBound()) {
- receiver_.reset();
- } else {
+ if (!IsBound())
shared_data_map_->AddBindingReference();
- }
- receiver_.Bind(std::move(receiver));
- receiver_.set_disconnect_handler(base::BindOnce(
- &SessionStorageAreaImpl::OnConnectionError, base::Unretained(this)));
+ receivers_.Add(this, std::move(receiver));
+}
+
+bool SessionStorageAreaImpl::IsBound() const {
+ return !receivers_.empty();
}
std::unique_ptr<SessionStorageAreaImpl> SessionStorageAreaImpl::Clone(
@@ -69,26 +71,26 @@ void SessionStorageAreaImpl::AddObserver(
void SessionStorageAreaImpl::Put(
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
PutCallback callback) {
DCHECK(IsBound());
DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
if (shared_data_map_->map_data()->ReferenceCount() > 1)
- CreateNewMap(NewMapType::FORKED, base::nullopt);
+ CreateNewMap(NewMapType::FORKED, absl::nullopt);
shared_data_map_->storage_area()->Put(key, value, client_old_value, source,
std::move(callback));
}
void SessionStorageAreaImpl::Delete(
const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
DeleteCallback callback) {
DCHECK(IsBound());
DCHECK_NE(0, shared_data_map_->map_data()->ReferenceCount());
if (shared_data_map_->map_data()->ReferenceCount() > 1)
- CreateNewMap(NewMapType::FORKED, base::nullopt);
+ CreateNewMap(NewMapType::FORKED, absl::nullopt);
shared_data_map_->storage_area()->Delete(key, client_old_value, source,
std::move(callback));
}
@@ -133,17 +135,14 @@ void SessionStorageAreaImpl::GetAll(
}
void SessionStorageAreaImpl::FlushForTesting() {
- receiver_.FlushForTesting();
+ receivers_.FlushForTesting();
}
// Note: this can be called after invalidation of the |namespace_entry_|.
void SessionStorageAreaImpl::OnConnectionError() {
+ if (IsBound())
+ return;
shared_data_map_->RemoveBindingReference();
- // Make sure we totally unbind the receiver - this doesn't seem to happen
- // automatically on connection error. The bound status is used in the
- // destructor to know if |RemoveBindingReference| was already called.
- if (receiver_.is_bound())
- receiver_.reset();
}
void SessionStorageAreaImpl::OnGetAllResult(
@@ -166,7 +165,7 @@ void SessionStorageAreaImpl::OnDeleteAllResult(
void SessionStorageAreaImpl::CreateNewMap(
NewMapType map_type,
- const base::Optional<std::string>& delete_all_source) {
+ const absl::optional<std::string>& delete_all_source) {
bool bound = IsBound();
if (bound)
shared_data_map_->RemoveBindingReference();
diff --git a/chromium/components/services/storage/dom_storage/session_storage_area_impl.h b/chromium/components/services/storage/dom_storage/session_storage_area_impl.h
index 8aa3c0a90a0..a0b9fe8ae53 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_area_impl.h
+++ b/chromium/components/services/storage/dom_storage/session_storage_area_impl.h
@@ -10,11 +10,11 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/services/storage/dom_storage/session_storage_metadata.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote_set.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
#include "url/origin.h"
@@ -64,7 +64,7 @@ class SessionStorageAreaImpl : public blink::mojom::StorageArea {
void Bind(mojo::PendingReceiver<blink::mojom::StorageArea> receiver);
- bool IsBound() const { return receiver_.is_bound(); }
+ bool IsBound() const;
SessionStorageDataMap* data_map() { return shared_data_map_.get(); }
@@ -76,11 +76,11 @@ class SessionStorageAreaImpl : public blink::mojom::StorageArea {
mojo::PendingRemote<blink::mojom::StorageAreaObserver> observer) override;
void Put(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
PutCallback callback) override;
void Delete(const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
DeleteCallback callback) override;
void DeleteAll(
@@ -108,7 +108,7 @@ class SessionStorageAreaImpl : public blink::mojom::StorageArea {
enum class NewMapType { FORKED, EMPTY_FROM_DELETE_ALL };
void CreateNewMap(NewMapType map_type,
- const base::Optional<std::string>& delete_all_source);
+ const absl::optional<std::string>& delete_all_source);
SessionStorageMetadata::NamespaceEntry namespace_entry_;
url::Origin origin_;
@@ -116,7 +116,7 @@ class SessionStorageAreaImpl : public blink::mojom::StorageArea {
RegisterNewAreaMap register_new_map_callback_;
mojo::RemoteSet<blink::mojom::StorageAreaObserver> observers_;
- mojo::Receiver<blink::mojom::StorageArea> receiver_{this};
+ mojo::ReceiverSet<blink::mojom::StorageArea> receivers_;
base::WeakPtrFactory<SessionStorageAreaImpl> weak_ptr_factory_{this};
diff --git a/chromium/components/services/storage/dom_storage/session_storage_area_impl_unittest.cc b/chromium/components/services/storage/dom_storage/session_storage_area_impl_unittest.cc
index 7378b1d1862..6c3c6575858 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_area_impl_unittest.cc
+++ b/chromium/components/services/storage/dom_storage/session_storage_area_impl_unittest.cc
@@ -60,7 +60,7 @@ class SessionStorageAreaImplTest : public testing::Test {
test_origin1_(url::Origin::Create(GURL("https://host1.com:1/"))),
test_origin2_(url::Origin::Create(GURL("https://host2.com:2/"))) {
leveldb_database_ = AsyncDomStorageDatabase::OpenInMemory(
- base::nullopt, "SessionStorageAreaImplTestDatabase",
+ absl::nullopt, "SessionStorageAreaImplTestDatabase",
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}),
base::DoNothing());
leveldb_database_->Put(StdStringToUint8Vector("map-0-key1"),
@@ -176,16 +176,23 @@ TEST_F(SessionStorageAreaImplTest, DoubleBind) {
mojo::Remote<blink::mojom::StorageArea> ss_leveldb1;
base::RunLoop loop;
ss_leveldb_impl->Bind(ss_leveldb1.BindNewPipeAndPassReceiver());
- ss_leveldb1.set_disconnect_handler(loop.QuitClosure());
+
+ // Get data from the first binding.
+ std::vector<blink::mojom::KeyValuePtr> data1;
+ EXPECT_TRUE(test::GetAllSync(ss_leveldb1.get(), &data1));
+ ASSERT_EQ(1ul, data1.size());
+
// Check that we can bind twice and get data from the second binding.
mojo::Remote<blink::mojom::StorageArea> ss_leveldb2;
ss_leveldb_impl->Bind(ss_leveldb2.BindNewPipeAndPassReceiver());
- std::vector<blink::mojom::KeyValuePtr> data;
- EXPECT_TRUE(test::GetAllSync(ss_leveldb2.get(), &data));
- ASSERT_EQ(1ul, data.size());
+ std::vector<blink::mojom::KeyValuePtr> data2;
+ EXPECT_TRUE(test::GetAllSync(ss_leveldb2.get(), &data2));
+ ASSERT_EQ(1ul, data2.size());
- // Make sure the first binding was closed.
- loop.Run();
+ // Check that we can still get data from the first binding.
+ std::vector<blink::mojom::KeyValuePtr> data3;
+ EXPECT_TRUE(test::GetAllSync(ss_leveldb1.get(), &data3));
+ ASSERT_EQ(1ul, data3.size());
EXPECT_CALL(listener_, OnDataMapDestruction(StdStringToUint8Vector("0")))
.Times(1);
@@ -230,7 +237,7 @@ TEST_F(SessionStorageAreaImplTest, Cloning) {
EXPECT_CALL(listener_, OnCommitResult(OKStatus()))
.Times(testing::AnyNumber());
EXPECT_TRUE(test::PutSync(ss_leveldb2.get(), StdStringToUint8Vector("key2"),
- StdStringToUint8Vector("data2"), base::nullopt,
+ StdStringToUint8Vector("data2"), absl::nullopt,
""));
// The maps were forked on the above put.
diff --git a/chromium/components/services/storage/dom_storage/session_storage_data_map.h b/chromium/components/services/storage/dom_storage/session_storage_data_map.h
index cf9cbbbadca..2cb0aa7b4dd 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_data_map.h
+++ b/chromium/components/services/storage/dom_storage/session_storage_data_map.h
@@ -10,9 +10,9 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "components/services/storage/dom_storage/session_storage_metadata.h"
#include "components/services/storage/dom_storage/storage_area_impl.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace storage {
diff --git a/chromium/components/services/storage/dom_storage/session_storage_data_map_unittest.cc b/chromium/components/services/storage/dom_storage/session_storage_data_map_unittest.cc
index f658e6d1518..e4af8a33eeb 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_data_map_unittest.cc
+++ b/chromium/components/services/storage/dom_storage/session_storage_data_map_unittest.cc
@@ -73,7 +73,7 @@ class SessionStorageDataMapTest : public testing::Test {
: test_origin_(url::Origin::Create(GURL("http://host1.com:1"))) {
base::RunLoop loop;
database_ = AsyncDomStorageDatabase::OpenInMemory(
- base::nullopt, "SessionStorageDataMapTest",
+ absl::nullopt, "SessionStorageDataMapTest",
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}),
base::BindLambdaForTesting([&](leveldb::Status status) {
ASSERT_TRUE(status.ok());
diff --git a/chromium/components/services/storage/dom_storage/session_storage_impl.cc b/chromium/components/services/storage/dom_storage/session_storage_impl.cc
index 40e8a560d03..3ef943bee84 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_impl.cc
+++ b/chromium/components/services/storage/dom_storage/session_storage_impl.cc
@@ -891,7 +891,7 @@ SessionStorageImpl::ParseDatabaseVersion(
if (version.status.IsNotFound()) {
// treat as v0 or new database
- metadata_.ParseDatabaseVersion(base::nullopt, migration_tasks);
+ metadata_.ParseDatabaseVersion(absl::nullopt, migration_tasks);
return {OpenResult::kSuccess, ""};
}
diff --git a/chromium/components/services/storage/dom_storage/session_storage_impl_unittest.cc b/chromium/components/services/storage/dom_storage/session_storage_impl_unittest.cc
index af2c8efbd90..6a95a53beb3 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_impl_unittest.cc
+++ b/chromium/components/services/storage/dom_storage/session_storage_impl_unittest.cc
@@ -116,12 +116,12 @@ class SessionStorageImplTest : public testing::Test {
area.BindNewPipeAndPassReceiver(),
base::DoNothing());
EXPECT_TRUE(test::PutSync(area.get(), StringPieceToUint8Vector(key),
- StringPieceToUint8Vector(value), base::nullopt,
+ StringPieceToUint8Vector(value), absl::nullopt,
source));
session_storage()->DeleteNamespace(namespace_id, true);
}
- base::Optional<std::vector<uint8_t>> DoTestGet(
+ absl::optional<std::vector<uint8_t>> DoTestGet(
const std::string& namespace_id,
const url::Origin& origin,
base::StringPiece key) {
@@ -142,7 +142,7 @@ class SessionStorageImplTest : public testing::Test {
return key_value->value;
}
}
- return base::nullopt;
+ return absl::nullopt;
}
protected:
@@ -239,7 +239,7 @@ TEST_F(SessionStorageImplTest, StartupShutdownSave) {
// Put some data.
EXPECT_TRUE(test::PutSync(area_n1.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
// Verify data is there.
@@ -295,7 +295,7 @@ TEST_F(SessionStorageImplTest, CloneBeforeBrowserClone) {
// Put some data.
EXPECT_TRUE(test::PutSync(area_n1.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
ss_namespace1->Clone(namespace_id2);
@@ -340,7 +340,7 @@ TEST_F(SessionStorageImplTest, Cloning) {
// Put some data.
EXPECT_TRUE(test::PutSync(area_n1.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
ss_namespace1->Clone(namespace_id2);
@@ -366,7 +366,7 @@ TEST_F(SessionStorageImplTest, Cloning) {
// Put some data in namespace 2.
EXPECT_TRUE(test::PutSync(area_n2.get(), StringPieceToUint8Vector("key2"),
- StringPieceToUint8Vector("value2"), base::nullopt,
+ StringPieceToUint8Vector("value2"), absl::nullopt,
"source1"));
EXPECT_TRUE(test::GetAllSync(area_n2.get(), &data));
EXPECT_EQ(2ul, data.size());
@@ -418,7 +418,7 @@ TEST_F(SessionStorageImplTest, ImmediateCloning) {
// Put some data.
EXPECT_TRUE(test::PutSync(area_n1.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value2"), base::nullopt,
+ StringPieceToUint8Vector("value2"), absl::nullopt,
"source1"));
session_storage()->CloneNamespace(namespace_id1, namespace_id2,
@@ -476,7 +476,7 @@ TEST_F(SessionStorageImplTest, Scavenging) {
area_n1.BindNewPipeAndPassReceiver(),
base::DoNothing());
EXPECT_TRUE(test::PutSync(area_n1.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
area_n1.reset();
@@ -539,7 +539,7 @@ TEST_F(SessionStorageImplTest, InvalidVersionOnDisk) {
// Initialize Session Storage, add some data to it, and check that it's there.
DoTestPut(namespace_id, origin, "key", "value", "source");
- base::Optional<std::vector<uint8_t>> opt_value =
+ absl::optional<std::vector<uint8_t>> opt_value =
DoTestGet(namespace_id, origin, "key");
ASSERT_TRUE(opt_value);
EXPECT_EQ(StringPieceToUint8Vector("value"), opt_value.value());
@@ -578,7 +578,7 @@ TEST_F(SessionStorageImplTest, CorruptionOnDisk) {
// Initialize Session Storage, add some data to it, and check that it's there.
DoTestPut(namespace_id, origin, "key", "value", "source");
- base::Optional<std::vector<uint8_t>> opt_value =
+ absl::optional<std::vector<uint8_t>> opt_value =
DoTestGet(namespace_id, origin, "key");
ASSERT_TRUE(opt_value);
EXPECT_EQ(StringPieceToUint8Vector("value"), opt_value.value());
@@ -617,7 +617,7 @@ TEST_F(SessionStorageImplTest, RecreateOnCommitFailure) {
url::Origin origin2 = url::Origin::Create(GURL("http://asf.com"));
url::Origin origin3 = url::Origin::Create(GURL("http://example.com"));
- base::Optional<base::RunLoop> open_loop;
+ absl::optional<base::RunLoop> open_loop;
size_t num_database_open_requests = 0;
size_t num_databases_destroyed = 0;
session_storage_impl()->SetDatabaseOpenCallbackForTesting(
@@ -677,7 +677,7 @@ TEST_F(SessionStorageImplTest, RecreateOnCommitFailure) {
// pending commit that will get cancelled when the database connection is
// closed.
auto value = StringPieceToUint8Vector("avalue");
- area_o3->Put(StringPieceToUint8Vector("w3key"), value, base::nullopt,
+ area_o3->Put(StringPieceToUint8Vector("w3key"), value, absl::nullopt,
"source",
base::BindOnce([](bool success) { EXPECT_TRUE(success); }));
@@ -689,7 +689,7 @@ TEST_F(SessionStorageImplTest, RecreateOnCommitFailure) {
// change to commit.
std::vector<uint8_t> old_value = value;
value[0]++;
- area_o1->Put(StringPieceToUint8Vector("key"), value, base::nullopt,
+ area_o1->Put(StringPieceToUint8Vector("key"), value, absl::nullopt,
"source", base::BindLambdaForTesting([&](bool success) {
EXPECT_TRUE(success);
}));
@@ -723,7 +723,7 @@ TEST_F(SessionStorageImplTest, RecreateOnCommitFailure) {
bool success = true;
test::MockLevelDBObserver observer4;
area_o1->AddObserver(observer4.Bind());
- area_o1->Delete(StringPieceToUint8Vector("key"), base::nullopt, "source",
+ area_o1->Delete(StringPieceToUint8Vector("key"), absl::nullopt, "source",
base::BindLambdaForTesting([&](bool success_in) {
success = success_in;
delete_loop.Quit();
@@ -738,7 +738,7 @@ TEST_F(SessionStorageImplTest, RecreateOnCommitFailure) {
{
// Committing data should now work.
DoTestPut(namespace_id, origin1, "key", "value", "source");
- base::Optional<std::vector<uint8_t>> opt_value =
+ absl::optional<std::vector<uint8_t>> opt_value =
DoTestGet(namespace_id, origin1, "key");
ASSERT_TRUE(opt_value);
EXPECT_EQ(StringPieceToUint8Vector("value"), opt_value.value());
@@ -749,7 +749,7 @@ TEST_F(SessionStorageImplTest, DontRecreateOnRepeatedCommitFailure) {
std::string namespace_id = base::GenerateGUID();
url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
- base::Optional<base::RunLoop> open_loop;
+ absl::optional<base::RunLoop> open_loop;
size_t num_database_open_requests = 0;
size_t num_databases_destroyed = 0;
session_storage_impl()->SetDatabaseOpenCallbackForTesting(
@@ -794,7 +794,7 @@ TEST_F(SessionStorageImplTest, DontRecreateOnRepeatedCommitFailure) {
// Repeatedly write data to the database, to trigger enough commit errors.
auto value = StringPieceToUint8Vector("avalue");
- base::Optional<std::vector<uint8_t>> old_value = base::nullopt;
+ absl::optional<std::vector<uint8_t>> old_value = absl::nullopt;
while (area.is_connected()) {
// Every write needs to be different to make sure there actually is a
// change to commit.
@@ -827,7 +827,7 @@ TEST_F(SessionStorageImplTest, DontRecreateOnRepeatedCommitFailure) {
area.BindNewPipeAndPassReceiver(),
base::DoNothing());
- old_value = base::nullopt;
+ old_value = absl::nullopt;
for (int i = 0; i < 64; ++i) {
// Every write needs to be different to make sure there actually is a
// change to commit.
@@ -862,7 +862,7 @@ TEST_F(SessionStorageImplTest, GetUsage) {
base::DoNothing());
// Put some data.
EXPECT_TRUE(test::PutSync(area.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
base::RunLoop loop;
@@ -889,7 +889,7 @@ TEST_F(SessionStorageImplTest, DeleteStorage) {
// Put some data.
EXPECT_TRUE(test::PutSync(area.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
session_storage()->DeleteStorage(origin1, namespace_id1, base::DoNothing());
@@ -901,7 +901,7 @@ TEST_F(SessionStorageImplTest, DeleteStorage) {
// Next, test that it deletes the data even if there isn't a namespace open.
// Put some data.
EXPECT_TRUE(test::PutSync(area.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
area.reset();
@@ -935,7 +935,7 @@ TEST_F(SessionStorageImplTest, PurgeInactiveWrappers) {
// Put some data in both.
EXPECT_TRUE(test::PutSync(area.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
session_storage_impl()->FlushAreaForTesting(namespace_id1, origin1);
@@ -990,7 +990,7 @@ TEST_F(SessionStorageImplTest, ClearDiskState) {
// Put some data.
EXPECT_TRUE(test::PutSync(area.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
area.reset();
@@ -1147,10 +1147,10 @@ TEST_F(SessionStorageImplTest, PurgeMemoryDoesNotCrashOrHang) {
// Put some data in both.
EXPECT_TRUE(test::PutSync(area_n1.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
EXPECT_TRUE(test::PutSync(area_n2.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value2"), base::nullopt,
+ StringPieceToUint8Vector("value2"), absl::nullopt,
"source1"));
session_storage_impl()->FlushAreaForTesting(namespace_id1, origin1);
@@ -1175,7 +1175,7 @@ TEST_F(SessionStorageImplTest, PurgeMemoryDoesNotCrashOrHang) {
EXPECT_TRUE(test::GetAllSync(area_n1.get(), &data));
EXPECT_EQ(1ul, data.size());
- base::Optional<std::vector<uint8_t>> opt_value2 =
+ absl::optional<std::vector<uint8_t>> opt_value2 =
DoTestGet(namespace_id2, origin1, "key1");
ASSERT_TRUE(opt_value2);
EXPECT_EQ(StringPieceToUint8Vector("value2"), opt_value2.value());
@@ -1193,7 +1193,7 @@ TEST_F(SessionStorageImplTest, DeleteWithPersistBeforeBrowserClone) {
// Put some data.
EXPECT_TRUE(test::PutSync(area_n1.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
// Delete the origin namespace, but save it.
@@ -1228,7 +1228,7 @@ TEST_F(SessionStorageImplTest, DeleteWithoutPersistBeforeBrowserClone) {
// Put some data.
EXPECT_TRUE(test::PutSync(area_n1.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
// Delete the origin namespace and don't save it.
@@ -1263,7 +1263,7 @@ TEST_F(SessionStorageImplTest, DeleteAfterCloneWithoutMojoClone) {
// Put some data.
EXPECT_TRUE(test::PutSync(area_n1.get(), StringPieceToUint8Vector("key1"),
- StringPieceToUint8Vector("value1"), base::nullopt,
+ StringPieceToUint8Vector("value1"), absl::nullopt,
"source1"));
// Do the browser-side clone.
diff --git a/chromium/components/services/storage/dom_storage/session_storage_metadata.cc b/chromium/components/services/storage/dom_storage/session_storage_metadata.cc
index bc7b6411c2a..c4aa4c08293 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_metadata.cc
+++ b/chromium/components/services/storage/dom_storage/session_storage_metadata.cc
@@ -8,8 +8,8 @@
#include "base/macros.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "components/services/storage/dom_storage/async_dom_storage_database.h"
#include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
#include "url/gurl.h"
@@ -103,7 +103,7 @@ SessionStorageMetadata::SetupNewDatabase() {
}
bool SessionStorageMetadata::ParseDatabaseVersion(
- base::Optional<std::vector<uint8_t>> value,
+ absl::optional<std::vector<uint8_t>> value,
std::vector<AsyncDomStorageDatabase::BatchDatabaseTask>* upgrade_tasks) {
if (!value) {
initial_database_version_from_disk_ = 0;
@@ -201,7 +201,7 @@ bool SessionStorageMetadata::ParseNamespaces(
auto origin = url::Origin::Create(origin_gurl);
if (namespace_id != last_namespace_id) {
- last_namespace_id = namespace_id.as_string();
+ last_namespace_id = std::string(namespace_id);
DCHECK(namespace_origin_map_.find(last_namespace_id) ==
namespace_origin_map_.end());
last_namespace = &(namespace_origin_map_[last_namespace_id]);
diff --git a/chromium/components/services/storage/dom_storage/session_storage_metadata.h b/chromium/components/services/storage/dom_storage/session_storage_metadata.h
index 82bb6b575d2..59a12ae8249 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_metadata.h
+++ b/chromium/components/services/storage/dom_storage/session_storage_metadata.h
@@ -90,7 +90,7 @@ class SessionStorageMetadata {
std::vector<AsyncDomStorageDatabase::BatchDatabaseTask> SetupNewDatabase();
// This parses the database version from the bytes that were stored on
- // disk, or if there was no version saved then passes a base::nullopt. This
+ // disk, or if there was no version saved then passes a absl::nullopt. This
// call is not necessary on new databases. The |upgrade_tasks| are populated
// with any tasks needed to upgrade the databases versioning metadata. Note
// this is different than the namespaces metadata, which will be upgraded in
@@ -98,7 +98,7 @@ class SessionStorageMetadata {
//
// Returns |true| if the parsing is correct and we support the version read.
bool ParseDatabaseVersion(
- base::Optional<std::vector<uint8_t>> value,
+ absl::optional<std::vector<uint8_t>> value,
std::vector<AsyncDomStorageDatabase::BatchDatabaseTask>* upgrade_tasks);
// Parses all namespaces and maps, and stores all metadata locally. This
diff --git a/chromium/components/services/storage/dom_storage/session_storage_metadata_unittest.cc b/chromium/components/services/storage/dom_storage/session_storage_metadata_unittest.cc
index 8fcd4b779ba..f0cfef3e686 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_metadata_unittest.cc
+++ b/chromium/components/services/storage/dom_storage/session_storage_metadata_unittest.cc
@@ -63,7 +63,7 @@ class SessionStorageMetadataTest : public testing::Test {
test_origin2_(url::Origin::Create(GURL("http://host2:2/"))) {
base::RunLoop loop;
database_ = AsyncDomStorageDatabase::OpenInMemory(
- base::nullopt, "SessionStorageMetadataTest",
+ absl::nullopt, "SessionStorageMetadataTest",
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}),
base::BindLambdaForTesting([&](leveldb::Status) { loop.Quit(); }));
loop.Run();
@@ -499,7 +499,7 @@ TEST_F(SessionStorageMetadataMigrationTest, MigrateV0ToV1) {
leveldb::Status s = db()->Get(options, leveldb::Slice("version"), &db_value);
EXPECT_TRUE(s.IsNotFound());
std::vector<AsyncDomStorageDatabase::BatchDatabaseTask> migration_tasks;
- EXPECT_TRUE(metadata.ParseDatabaseVersion(base::nullopt, &migration_tasks));
+ EXPECT_TRUE(metadata.ParseDatabaseVersion(absl::nullopt, &migration_tasks));
EXPECT_FALSE(migration_tasks.empty());
EXPECT_EQ(1ul, migration_tasks.size());
diff --git a/chromium/components/services/storage/dom_storage/session_storage_namespace_impl_unittest.cc b/chromium/components/services/storage/dom_storage/session_storage_namespace_impl_unittest.cc
index 435a8ea767a..7864f62c1d4 100644
--- a/chromium/components/services/storage/dom_storage/session_storage_namespace_impl_unittest.cc
+++ b/chromium/components/services/storage/dom_storage/session_storage_namespace_impl_unittest.cc
@@ -73,7 +73,7 @@ class SessionStorageNamespaceImplTest
// Create a database that already has a namespace saved.
base::RunLoop loop;
database_ = AsyncDomStorageDatabase::OpenInMemory(
- base::nullopt, "SessionStorageNamespaceImplTest",
+ absl::nullopt, "SessionStorageNamespaceImplTest",
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}),
base::BindLambdaForTesting([&](leveldb::Status) { loop.Quit(); }));
loop.Run();
@@ -225,7 +225,7 @@ TEST_F(SessionStorageNamespaceImplTest, MetadataLoadWithMapOperations) {
.Times(1)
.WillOnce(testing::Invoke([&](auto error) { commit_loop.Quit(); }));
test::PutSync(leveldb_1.get(), StdStringToUint8Vector("key2"),
- StdStringToUint8Vector("data2"), base::nullopt, "");
+ StdStringToUint8Vector("data2"), absl::nullopt, "");
commit_loop.Run();
std::vector<blink::mojom::KeyValuePtr> data;
@@ -281,7 +281,7 @@ TEST_F(SessionStorageNamespaceImplTest, CloneBeforeBind) {
OnDataMapCreation(StdStringToUint8Vector("1"), testing::_))
.Times(1);
test::PutSync(leveldb_2.get(), StdStringToUint8Vector("key2"),
- StdStringToUint8Vector("data2"), base::nullopt, "");
+ StdStringToUint8Vector("data2"), absl::nullopt, "");
commit_loop.Run();
std::vector<blink::mojom::KeyValuePtr> data;
@@ -346,7 +346,7 @@ TEST_F(SessionStorageNamespaceImplTest, CloneAfterBind) {
.Times(1)
.WillOnce(testing::Invoke([&](auto error) { commit_loop.Quit(); }));
test::PutSync(leveldb_n2_o2.get(), StdStringToUint8Vector("key2"),
- StdStringToUint8Vector("data2"), base::nullopt, "");
+ StdStringToUint8Vector("data2"), absl::nullopt, "");
commit_loop.Run();
std::vector<blink::mojom::KeyValuePtr> data;
diff --git a/chromium/components/services/storage/dom_storage/storage_area_impl.cc b/chromium/components/services/storage/dom_storage/storage_area_impl.cc
index 4be7ebc30c4..c0b8c3d2fc8 100644
--- a/chromium/components/services/storage/dom_storage/storage_area_impl.cc
+++ b/chromium/components/services/storage/dom_storage/storage_area_impl.cc
@@ -241,7 +241,7 @@ void StorageAreaImpl::AddObserver(
void StorageAreaImpl::Put(
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
PutCallback callback) {
if (!IsMapLoaded() || IsMapUpgradeNeeded()) {
@@ -254,7 +254,7 @@ void StorageAreaImpl::Put(
size_t old_item_size = 0;
size_t old_item_memory = 0;
size_t new_item_memory = 0;
- base::Optional<std::vector<uint8_t>> old_value;
+ absl::optional<std::vector<uint8_t>> old_value;
if (map_state_ == MapState::LOADED_KEYS_ONLY) {
KeysOnlyMap::const_iterator found = keys_only_map_.find(key);
if (found != keys_only_map_.end()) {
@@ -355,7 +355,7 @@ void StorageAreaImpl::Put(
void StorageAreaImpl::Delete(
const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
DeleteCallback callback) {
// Map upgrade check is required because the cache state could be changed
@@ -380,7 +380,7 @@ void StorageAreaImpl::Delete(
// the change request, as clients may rely on this acknowledgement for
// caching behavior.
for (const auto& observer : observers_)
- observer->KeyDeleted(key, base::nullopt, source);
+ observer->KeyDeleted(key, absl::nullopt, source);
std::move(callback).Run(true);
return;
}
@@ -416,7 +416,7 @@ void StorageAreaImpl::Delete(
// the change request, as clients may rely on this acknowledgement for
// caching behavior.
for (const auto& observer : observers_)
- observer->KeyDeleted(key, base::nullopt, source);
+ observer->KeyDeleted(key, absl::nullopt, source);
std::move(callback).Run(true);
return;
}
@@ -791,7 +791,7 @@ void StorageAreaImpl::CommitChanges(base::OnceClosure callback) {
bool clear_all_first;
std::vector<DomStorageDatabase::KeyValuePair> entries_to_add;
std::vector<DomStorageDatabase::Key> keys_to_delete;
- base::Optional<DomStorageDatabase::Key> copy_to_prefix;
+ absl::optional<DomStorageDatabase::Key> copy_to_prefix;
};
Commit commit;
diff --git a/chromium/components/services/storage/dom_storage/storage_area_impl.h b/chromium/components/services/storage/dom_storage/storage_area_impl.h
index b057e970147..9bc8a4cfde2 100644
--- a/chromium/components/services/storage/dom_storage/storage_area_impl.h
+++ b/chromium/components/services/storage/dom_storage/storage_area_impl.h
@@ -13,12 +13,12 @@
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/services/storage/dom_storage/dom_storage_database.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote_set.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
namespace base {
@@ -47,7 +47,7 @@ class StorageAreaImpl : public blink::mojom::StorageArea {
using ValueMap = std::map<std::vector<uint8_t>, std::vector<uint8_t>>;
using ValueMapCallback = base::OnceCallback<void(std::unique_ptr<ValueMap>)>;
using Change =
- std::pair<std::vector<uint8_t>, base::Optional<std::vector<uint8_t>>>;
+ std::pair<std::vector<uint8_t>, absl::optional<std::vector<uint8_t>>>;
using KeysOnlyMap = std::map<std::vector<uint8_t>, size_t>;
class Delegate {
@@ -185,11 +185,11 @@ class StorageAreaImpl : public blink::mojom::StorageArea {
mojo::PendingRemote<blink::mojom::StorageAreaObserver> observer) override;
void Put(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
PutCallback callback) override;
void Delete(const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
const std::string& source,
DeleteCallback callback) override;
void DeleteAll(
@@ -245,7 +245,7 @@ class StorageAreaImpl : public blink::mojom::StorageArea {
bool clear_all_first = false;
// Prefix copying is performed before applying changes.
- base::Optional<std::vector<uint8_t>> copy_to_prefix;
+ absl::optional<std::vector<uint8_t>> copy_to_prefix;
// Used if the map_type_ is LOADED_KEYS_ONLY.
std::map<std::vector<uint8_t>, std::vector<uint8_t>> changed_values;
// Used if the map_type_ is LOADED_KEYS_AND_VALUES.
diff --git a/chromium/components/services/storage/dom_storage/storage_area_impl_unittest.cc b/chromium/components/services/storage/dom_storage/storage_area_impl_unittest.cc
index 6c2761aa002..0ff2e312af9 100644
--- a/chromium/components/services/storage/dom_storage/storage_area_impl_unittest.cc
+++ b/chromium/components/services/storage/dom_storage/storage_area_impl_unittest.cc
@@ -141,7 +141,7 @@ class StorageAreaImplTest : public testing::Test,
struct Observation {
enum { kChange, kChangeFailed, kDelete, kDeleteAll, kSendOldValue } type;
std::string key;
- base::Optional<std::string> old_value;
+ absl::optional<std::string> old_value;
std::string new_value;
std::string source;
bool should_send_old_value;
@@ -150,7 +150,7 @@ class StorageAreaImplTest : public testing::Test,
StorageAreaImplTest() {
base::RunLoop loop;
db_ = AsyncDomStorageDatabase::OpenInMemory(
- base::nullopt, "StorageAreaImplTest",
+ absl::nullopt, "StorageAreaImplTest",
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}),
base::BindLambdaForTesting(
[&](leveldb::Status status) { loop.Quit(); }));
@@ -248,7 +248,7 @@ class StorageAreaImplTest : public testing::Test,
bool DeleteSync(
blink::mojom::StorageArea* area,
const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& client_old_value) {
+ const absl::optional<std::vector<uint8_t>>& client_old_value) {
return test::DeleteSync(area, key, client_old_value, test_source_);
}
@@ -262,14 +262,14 @@ class StorageAreaImplTest : public testing::Test,
bool PutSync(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
std::string source = kTestSource) {
return test::PutSync(storage_area(), key, value, client_old_value, source);
}
bool DeleteSync(
const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& client_old_value) {
+ const absl::optional<std::vector<uint8_t>>& client_old_value) {
return DeleteSync(storage_area(), key, client_old_value);
}
@@ -332,9 +332,9 @@ class StorageAreaImplTest : public testing::Test,
// blink::mojom::StorageAreaObserver:
void KeyChanged(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& new_value,
- const base::Optional<std::vector<uint8_t>>& old_value,
+ const absl::optional<std::vector<uint8_t>>& old_value,
const std::string& source) override {
- base::Optional<std::string> optional_old_value;
+ absl::optional<std::string> optional_old_value;
if (old_value)
optional_old_value = ToString(*old_value);
observations_.push_back({Observation::kChange, ToString(key),
@@ -347,9 +347,9 @@ class StorageAreaImplTest : public testing::Test,
{Observation::kChangeFailed, ToString(key), "", "", source, false});
}
void KeyDeleted(const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& old_value,
+ const absl::optional<std::vector<uint8_t>>& old_value,
const std::string& source) override {
- base::Optional<std::string> optional_old_value;
+ absl::optional<std::string> optional_old_value;
if (old_value)
optional_old_value = ToString(*old_value);
observations_.push_back({Observation::kDelete, ToString(key),
@@ -440,7 +440,7 @@ TEST_F(StorageAreaImplTest, GetFromPutNewKey) {
std::vector<uint8_t> key = ToBytes("newkey");
std::vector<uint8_t> value = ToBytes("foo");
- EXPECT_TRUE(PutSync(key, value, base::nullopt));
+ EXPECT_TRUE(PutSync(key, value, absl::nullopt));
std::vector<uint8_t> result;
EXPECT_TRUE(GetSync(key, &result));
@@ -456,7 +456,7 @@ TEST_F(StorageAreaImplTest, PutLoadsValuesAfterCacheModeUpgrade) {
storage_area_impl()->cache_mode());
// Do a put to load the key-only cache.
- EXPECT_TRUE(PutSync(key, value1, base::nullopt));
+ EXPECT_TRUE(PutSync(key, value1, absl::nullopt));
BlockingCommit();
EXPECT_EQ(StorageAreaImpl::MapState::LOADED_KEYS_ONLY,
storage_area_impl()->map_state_);
@@ -499,7 +499,7 @@ TEST_P(StorageAreaImplParamTest, CommitPutToDB) {
ToBytes(key1), ToBytes(value1), test_value2_bytes_, test_source_,
MakeSuccessCallback(barrier.AddClosure(), &put_success1));
storage_area()->Put(
- ToBytes(key2), ToBytes("old value"), base::nullopt, test_source_,
+ ToBytes(key2), ToBytes("old value"), absl::nullopt, test_source_,
MakeSuccessCallback(barrier.AddClosure(), &put_success2));
storage_area()->Put(
ToBytes(key2), ToBytes(value2), ToBytes("old value"), test_source_,
@@ -528,12 +528,12 @@ TEST_P(StorageAreaImplParamTest, PutObservations) {
std::string source1 = "source1";
std::string source2 = "source2";
- EXPECT_TRUE(PutSync(ToBytes(key), ToBytes(value1), base::nullopt, source1));
+ EXPECT_TRUE(PutSync(ToBytes(key), ToBytes(value1), absl::nullopt, source1));
ASSERT_EQ(1u, observations().size());
EXPECT_EQ(Observation::kChange, observations()[0].type);
EXPECT_EQ(key, observations()[0].key);
EXPECT_EQ(value1, observations()[0].new_value);
- EXPECT_EQ(base::nullopt, observations()[0].old_value);
+ EXPECT_EQ(absl::nullopt, observations()[0].old_value);
EXPECT_EQ(source1, observations()[0].source);
EXPECT_TRUE(PutSync(ToBytes(key), ToBytes(value2), ToBytes(value1), source2));
@@ -607,7 +607,7 @@ TEST_P(StorageAreaImplParamTest, DeleteAllWithoutLoadedMap) {
// And now we've deleted all, writing something the quota size should work.
EXPECT_TRUE(PutSync(std::vector<uint8_t>(kTestSizeLimit, 'b'),
- std::vector<uint8_t>(), base::nullopt));
+ std::vector<uint8_t>(), absl::nullopt));
}
TEST_P(StorageAreaImplParamTest, DeleteAllWithLoadedMap) {
@@ -617,7 +617,7 @@ TEST_P(StorageAreaImplParamTest, DeleteAllWithLoadedMap) {
std::string dummy_key = "foobar";
SetDatabaseEntry(dummy_key, value);
- EXPECT_TRUE(PutSync(ToBytes(key), ToBytes(value), base::nullopt));
+ EXPECT_TRUE(PutSync(ToBytes(key), ToBytes(value), absl::nullopt));
EXPECT_TRUE(DeleteAllSync());
ASSERT_EQ(2u, observations().size());
@@ -638,7 +638,7 @@ TEST_P(StorageAreaImplParamTest, DeleteAllWithPendingMapLoad) {
std::string dummy_key = "foobar";
SetDatabaseEntry(dummy_key, value);
- storage_area()->Put(ToBytes(key), ToBytes(value), base::nullopt, kTestSource,
+ storage_area()->Put(ToBytes(key), ToBytes(value), absl::nullopt, kTestSource,
base::DoNothing());
EXPECT_TRUE(DeleteAllSync());
@@ -668,10 +668,10 @@ TEST_F(StorageAreaImplParamTest, PutOverQuotaLargeValue) {
std::vector<uint8_t> key = ToBytes("newkey");
std::vector<uint8_t> value(kTestSizeLimit, 4);
- EXPECT_FALSE(PutSync(key, value, base::nullopt));
+ EXPECT_FALSE(PutSync(key, value, absl::nullopt));
value.resize(kTestSizeLimit / 2);
- EXPECT_TRUE(PutSync(key, value, base::nullopt));
+ EXPECT_TRUE(PutSync(key, value, absl::nullopt));
}
TEST_F(StorageAreaImplParamTest, PutOverQuotaLargeKey) {
@@ -679,10 +679,10 @@ TEST_F(StorageAreaImplParamTest, PutOverQuotaLargeKey) {
std::vector<uint8_t> key(kTestSizeLimit, 'a');
std::vector<uint8_t> value = ToBytes("newvalue");
- EXPECT_FALSE(PutSync(key, value, base::nullopt));
+ EXPECT_FALSE(PutSync(key, value, absl::nullopt));
key.resize(kTestSizeLimit / 2);
- EXPECT_TRUE(PutSync(key, value, base::nullopt));
+ EXPECT_TRUE(PutSync(key, value, absl::nullopt));
}
TEST_F(StorageAreaImplParamTest, PutWhenAlreadyOverQuota) {
@@ -694,14 +694,14 @@ TEST_F(StorageAreaImplParamTest, PutWhenAlreadyOverQuota) {
SetDatabaseEntry(test_prefix_ + key, ToString(value));
// Put with same data should succeed.
- EXPECT_TRUE(PutSync(ToBytes(key), value, base::nullopt));
+ EXPECT_TRUE(PutSync(ToBytes(key), value, absl::nullopt));
// Put with same data size should succeed.
value[1] = 13;
EXPECT_TRUE(PutSync(ToBytes(key), value, old_value));
// Adding a new key when already over quota should not succeed.
- EXPECT_FALSE(PutSync(ToBytes("newkey"), {1, 2, 3}, base::nullopt));
+ EXPECT_FALSE(PutSync(ToBytes("newkey"), {1, 2, 3}, absl::nullopt));
// Reducing size should also succeed.
old_value = value;
@@ -780,7 +780,7 @@ TEST_P(StorageAreaImplParamTest, FixUpData) {
storage_area_impl()->SetCacheModeForTesting(GetParam());
std::vector<StorageAreaImpl::Change> changes;
changes.push_back(std::make_pair(test_key1_bytes_, ToBytes("foo")));
- changes.push_back(std::make_pair(test_key2_bytes_, base::nullopt));
+ changes.push_back(std::make_pair(test_key2_bytes_, absl::nullopt));
changes.push_back(std::make_pair(test_prefix_bytes_, ToBytes("bla")));
delegate()->set_mock_changes(std::move(changes));
@@ -815,7 +815,7 @@ TEST_F(StorageAreaImplTest, SetOnlyKeysWithoutDatabase) {
// Put and Get can work synchronously without reload.
bool put_callback_called = false;
- storage_area.Put(key, value, base::nullopt, "source",
+ storage_area.Put(key, value, absl::nullopt, "source",
base::BindOnce(
[](bool* put_callback_called, bool success) {
EXPECT_TRUE(success);
@@ -844,7 +844,7 @@ TEST_P(StorageAreaImplParamTest, CommitOnDifferentCacheModes) {
std::vector<uint8_t> value3 = ToBytes("foobar");
// The initial map always has values, so a nullopt is fine for the old value.
- ASSERT_TRUE(PutSync(key, value, base::nullopt));
+ ASSERT_TRUE(PutSync(key, value, absl::nullopt));
ASSERT_TRUE(storage_area_impl()->commit_batch_);
// Area stays in CacheMode::KEYS_AND_VALUES until the first commit has
@@ -912,7 +912,7 @@ TEST_F(StorageAreaImplTest, GetAllWhenCacheOnlyKeys) {
std::vector<uint8_t> value2 = ToBytes("foobar");
// Go to load state only keys.
- ASSERT_TRUE(PutSync(key, value, base::nullopt));
+ ASSERT_TRUE(PutSync(key, value, absl::nullopt));
BlockingCommit();
ASSERT_TRUE(PutSync(key, value2, value));
EXPECT_TRUE(storage_area_impl()->has_changes_to_commit());
@@ -969,7 +969,7 @@ TEST_F(StorageAreaImplTest, GetAllAfterSetCacheMode) {
std::vector<uint8_t> value2 = ToBytes("foobar");
// Go to load state only keys.
- ASSERT_TRUE(PutSync(key, value, base::nullopt));
+ ASSERT_TRUE(PutSync(key, value, absl::nullopt));
BlockingCommit();
EXPECT_TRUE(storage_area_impl()->map_state_ ==
StorageAreaImpl::MapState::LOADED_KEYS_ONLY);
@@ -1045,7 +1045,7 @@ TEST_F(StorageAreaImplTest, SetCacheModeConsistent) {
// Clear the database before the area loads data.
ClearDatabase();
- EXPECT_TRUE(PutSync(key, value, base::nullopt));
+ EXPECT_TRUE(PutSync(key, value, absl::nullopt));
EXPECT_TRUE(storage_area_impl()->has_changes_to_commit());
BlockingCommit();
@@ -1096,11 +1096,11 @@ TEST_F(StorageAreaImplTest, SendOldValueObservations) {
should_record_send_old_value_observations(true);
storage_area_impl()->SetCacheModeForTesting(CacheMode::KEYS_AND_VALUES);
// Flush tasks on mojo thread to observe callback.
- EXPECT_TRUE(DeleteSync(ToBytes("doesn't exist"), base::nullopt));
+ EXPECT_TRUE(DeleteSync(ToBytes("doesn't exist"), absl::nullopt));
storage_area_impl()->SetCacheModeForTesting(
CacheMode::KEYS_ONLY_WHEN_POSSIBLE);
// Flush tasks on mojo thread to observe callback.
- EXPECT_TRUE(DeleteSync(ToBytes("doesn't exist"), base::nullopt));
+ EXPECT_TRUE(DeleteSync(ToBytes("doesn't exist"), absl::nullopt));
ASSERT_EQ(4u, observations().size());
EXPECT_EQ(Observation::kSendOldValue, observations()[0].type);
@@ -1201,7 +1201,7 @@ TEST_P(StorageAreaImplParamTest, PrefixForkAfterLoad) {
const std::vector<uint8_t> kValueVec = ToBytes(kValue);
// Do a sync put so the map loads.
- EXPECT_TRUE(PutSync(test_key1_bytes_, kValueVec, base::nullopt));
+ EXPECT_TRUE(PutSync(test_key1_bytes_, kValueVec, absl::nullopt));
// Execute the fork.
MockDelegate fork1_delegate;
@@ -1225,8 +1225,8 @@ std::string GetNewPrefix(int* i) {
}
struct FuzzState {
- base::Optional<std::vector<uint8_t>> val1;
- base::Optional<std::vector<uint8_t>> val2;
+ absl::optional<std::vector<uint8_t>> val1;
+ absl::optional<std::vector<uint8_t>> val2;
};
} // namespace
@@ -1267,7 +1267,7 @@ TEST_F(StorageAreaImplTest, PrefixForkingPsuedoFuzzer) {
}
if (i % 13 == 0) {
FuzzState old_state = state;
- state.val1 = base::nullopt;
+ state.val1 = absl::nullopt;
successes.push_back(false);
areas[i]->Delete(
kKey1Vec, old_state.val1, test_source_,
@@ -1275,7 +1275,7 @@ TEST_F(StorageAreaImplTest, PrefixForkingPsuedoFuzzer) {
}
if (i % 4 == 0) {
FuzzState old_state = state;
- state.val2 = base::make_optional<std::vector<uint8_t>>(
+ state.val2 = absl::make_optional<std::vector<uint8_t>>(
{static_cast<uint8_t>(i)});
successes.push_back(false);
areas[i]->Put(
@@ -1284,7 +1284,7 @@ TEST_F(StorageAreaImplTest, PrefixForkingPsuedoFuzzer) {
}
if (i % 3 == 0) {
FuzzState old_state = state;
- state.val1 = base::make_optional<std::vector<uint8_t>>(
+ state.val1 = absl::make_optional<std::vector<uint8_t>>(
{static_cast<uint8_t>(i + 5)});
successes.push_back(false);
areas[i]->Put(
@@ -1292,8 +1292,8 @@ TEST_F(StorageAreaImplTest, PrefixForkingPsuedoFuzzer) {
MakeSuccessCallback(barrier.AddClosure(), &successes.back()));
}
if (i % 11 == 0) {
- state.val1 = base::nullopt;
- state.val2 = base::nullopt;
+ state.val1 = absl::nullopt;
+ state.val2 = absl::nullopt;
successes.push_back(false);
areas[i]->DeleteAll(
test_source_, mojo::NullRemote(),
@@ -1310,7 +1310,7 @@ TEST_F(StorageAreaImplTest, PrefixForkingPsuedoFuzzer) {
}
if (i % 3 == 0) {
FuzzState old_state = state;
- state.val1 = base::make_optional<std::vector<uint8_t>>(
+ state.val1 = absl::make_optional<std::vector<uint8_t>>(
{static_cast<uint8_t>(i + 9)});
successes.push_back(false);
areas[i]->Put(
diff --git a/chromium/components/services/storage/dom_storage/storage_area_test_util.cc b/chromium/components/services/storage/dom_storage/storage_area_test_util.cc
index b426a152240..7eaa6555e54 100644
--- a/chromium/components/services/storage/dom_storage/storage_area_test_util.cc
+++ b/chromium/components/services/storage/dom_storage/storage_area_test_util.cc
@@ -31,7 +31,7 @@ base::OnceCallback<void(bool)> MakeSuccessCallback(base::OnceClosure callback,
bool PutSync(blink::mojom::StorageArea* area,
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
- const base::Optional<std::vector<uint8_t>>& old_value,
+ const absl::optional<std::vector<uint8_t>>& old_value,
const std::string& source) {
bool success = false;
base::RunLoop loop;
@@ -76,7 +76,7 @@ bool GetAllSync(blink::mojom::StorageArea* area,
bool DeleteSync(blink::mojom::StorageArea* area,
const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
const std::string& source) {
bool success = false;
base::RunLoop loop;
diff --git a/chromium/components/services/storage/dom_storage/storage_area_test_util.h b/chromium/components/services/storage/dom_storage/storage_area_test_util.h
index 584d2b4efa5..63af5d65811 100644
--- a/chromium/components/services/storage/dom_storage/storage_area_test_util.h
+++ b/chromium/components/services/storage/dom_storage/storage_area_test_util.h
@@ -9,10 +9,10 @@
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
// Utility functions and classes for testing StorageArea implementations.
@@ -30,7 +30,7 @@ base::OnceCallback<void(bool)> MakeSuccessCallback(base::OnceClosure callback,
bool PutSync(blink::mojom::StorageArea* area,
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value,
- const base::Optional<std::vector<uint8_t>>& old_value,
+ const absl::optional<std::vector<uint8_t>>& old_value,
const std::string& source);
bool GetSync(blink::mojom::StorageArea* area,
@@ -44,7 +44,7 @@ bool GetAllSync(blink::mojom::StorageArea* area,
// received. Returns if the call was successful.
bool DeleteSync(blink::mojom::StorageArea* area,
const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& client_old_value,
+ const absl::optional<std::vector<uint8_t>>& client_old_value,
const std::string& source);
// Does a |DeleteAll| call on the area and waits until the response is
@@ -65,14 +65,14 @@ class MockLevelDBObserver : public blink::mojom::StorageAreaObserver {
MOCK_METHOD4(KeyChanged,
void(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& new_value,
- const base::Optional<std::vector<uint8_t>>& old_value,
+ const absl::optional<std::vector<uint8_t>>& old_value,
const std::string& source));
MOCK_METHOD2(KeyChangeFailed,
void(const std::vector<uint8_t>& key,
const std::string& source));
MOCK_METHOD3(KeyDeleted,
void(const std::vector<uint8_t>& key,
- const base::Optional<std::vector<uint8_t>>& old_value,
+ const absl::optional<std::vector<uint8_t>>& old_value,
const std::string& source));
MOCK_METHOD2(AllDeleted, void(bool was_nonempty, const std::string& source));
MOCK_METHOD1(ShouldSendOldValueOnMutations, void(bool value));
diff --git a/chromium/components/services/storage/dom_storage/testing_legacy_session_storage_database.cc b/chromium/components/services/storage/dom_storage/testing_legacy_session_storage_database.cc
index 436cef3b85f..de639864998 100644
--- a/chromium/components/services/storage/dom_storage/testing_legacy_session_storage_database.cc
+++ b/chromium/components/services/storage/dom_storage/testing_legacy_session_storage_database.cc
@@ -719,7 +719,7 @@ bool TestingLegacySessionStorageDatabase::ReadMap(
std::u16string key16 =
base::UTF8ToUTF16(key.substr(map_start_key.length()));
if (only_keys) {
- (*result)[key16] = base::nullopt;
+ (*result)[key16] = absl::nullopt;
} else {
// Convert the raw data stored in std::string (it->value()) to raw data
// stored in std::u16string.
@@ -737,7 +737,7 @@ void TestingLegacySessionStorageDatabase::WriteValuesToMap(
const LegacyDomStorageValuesMap& values,
leveldb::WriteBatch* batch) {
for (auto it = values.begin(); it != values.end(); ++it) {
- const base::Optional<std::u16string>& value = it->second;
+ const absl::optional<std::u16string>& value = it->second;
std::string key = MapKey(map_id, base::UTF16ToUTF8(it->first));
if (!value.has_value()) {
batch->Delete(key);
diff --git a/chromium/components/services/storage/indexed_db/DIR_METADATA b/chromium/components/services/storage/indexed_db/DIR_METADATA
index af99a94598b..0d8be5e617d 100644
--- a/chromium/components/services/storage/indexed_db/DIR_METADATA
+++ b/chromium/components/services/storage/indexed_db/DIR_METADATA
@@ -2,4 +2,3 @@ monorail {
component: "Blink>Storage>IndexedDB"
}
-team_email: "storage-dev@chromium.org"
diff --git a/chromium/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.cc b/chromium/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.cc
index 44b8288c1de..64c4e429484 100644
--- a/chromium/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.cc
+++ b/chromium/components/services/storage/indexed_db/leveldb/fake_leveldb_factory.cc
@@ -11,10 +11,10 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
-#include "base/optional.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "components/services/storage/indexed_db/leveldb/leveldb_state.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/slice.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
@@ -36,17 +36,17 @@ class FlakyDB : public leveldb::DB {
~FlakyDB() override = default;
// Returns a FlakePoint if the current operation is flaky with the flake
- // information. Otherwise it returns a base::nullopt.
+ // information. Otherwise it returns a absl::nullopt.
// This call is threadsafe.
- base::Optional<FakeLevelDBFactory::FlakePoint> FlakePointForNextOperation() {
+ absl::optional<FakeLevelDBFactory::FlakePoint> FlakePointForNextOperation() {
base::AutoLock lock(lock_);
if (flake_points_.empty())
- return base::nullopt;
+ return absl::nullopt;
DCHECK_GE(flake_points_.front().calls_before_flake, 0);
flake_points_.front().calls_before_flake--;
FakeLevelDBFactory::FlakePoint flake_point = flake_points_.front();
if (flake_point.calls_before_flake >= 0)
- return base::nullopt;
+ return absl::nullopt;
flake_points_.pop();
return flake_point;
}
@@ -55,7 +55,7 @@ class FlakyDB : public leveldb::DB {
leveldb::Status Put(const leveldb::WriteOptions& options,
const leveldb::Slice& key,
const leveldb::Slice& value) override {
- base::Optional<FakeLevelDBFactory::FlakePoint> flake_status =
+ absl::optional<FakeLevelDBFactory::FlakePoint> flake_status =
FlakePointForNextOperation();
if (flake_status.has_value())
return flake_status->flake_status;
@@ -63,7 +63,7 @@ class FlakyDB : public leveldb::DB {
}
leveldb::Status Delete(const leveldb::WriteOptions& options,
const leveldb::Slice& key) override {
- base::Optional<FakeLevelDBFactory::FlakePoint> flake_status =
+ absl::optional<FakeLevelDBFactory::FlakePoint> flake_status =
FlakePointForNextOperation();
if (flake_status.has_value())
return flake_status->flake_status;
@@ -71,7 +71,7 @@ class FlakyDB : public leveldb::DB {
}
leveldb::Status Write(const leveldb::WriteOptions& options,
leveldb::WriteBatch* updates) override {
- base::Optional<FakeLevelDBFactory::FlakePoint> flake_status =
+ absl::optional<FakeLevelDBFactory::FlakePoint> flake_status =
FlakePointForNextOperation();
if (flake_status.has_value())
return flake_status->flake_status;
@@ -80,7 +80,7 @@ class FlakyDB : public leveldb::DB {
leveldb::Status Get(const leveldb::ReadOptions& options,
const leveldb::Slice& key,
std::string* value) override {
- base::Optional<FakeLevelDBFactory::FlakePoint> flake_status =
+ absl::optional<FakeLevelDBFactory::FlakePoint> flake_status =
FlakePointForNextOperation();
if (flake_status.has_value()) {
if (flake_status->flake_status.ok())
@@ -173,7 +173,7 @@ class FlakyIterator : public leveldb::Iterator {
// The current flake is cleared & optionally set on every call to Seek*, Next,
// and Prev.
- base::Optional<FakeLevelDBFactory::FlakePoint> current_flake_;
+ absl::optional<FakeLevelDBFactory::FlakePoint> current_flake_;
std::unique_ptr<leveldb::Iterator> delegate_;
};
@@ -353,7 +353,7 @@ class BreakOnCallbackDB : public leveldb::DB {
private:
base::Lock lock_;
const std::unique_ptr<leveldb::DB> db_;
- base::Optional<leveldb::Status> broken_status_ GUARDED_BY(lock_);
+ absl::optional<leveldb::Status> broken_status_ GUARDED_BY(lock_);
};
} // namespace
diff --git a/chromium/components/services/storage/indexed_db/scopes/disjoint_range_lock_manager.h b/chromium/components/services/storage/indexed_db/scopes/disjoint_range_lock_manager.h
index b7c50e94d44..121fb96f521 100644
--- a/chromium/components/services/storage/indexed_db/scopes/disjoint_range_lock_manager.h
+++ b/chromium/components/services/storage/indexed_db/scopes/disjoint_range_lock_manager.h
@@ -12,10 +12,10 @@
#include "base/containers/flat_set.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "components/services/storage/indexed_db/scopes/scopes_lock_manager.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
#include "third_party/leveldatabase/src/include/leveldb/slice.h"
diff --git a/chromium/components/services/storage/indexed_db/scopes/leveldb_scope.cc b/chromium/components/services/storage/indexed_db/scopes/leveldb_scope.cc
index 9e5c8d2681c..b4a7fb8cb57 100644
--- a/chromium/components/services/storage/indexed_db/scopes/leveldb_scope.cc
+++ b/chromium/components/services/storage/indexed_db/scopes/leveldb_scope.cc
@@ -10,8 +10,8 @@
#include "base/compiler_specific.h"
#include "base/debug/stack_trace.h"
#include "base/memory/ptr_util.h"
-#include "base/optional.h"
#include "components/services/storage/indexed_db/scopes/leveldb_scopes_coding.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
diff --git a/chromium/components/services/storage/indexed_db/scopes/leveldb_scopes.cc b/chromium/components/services/storage/indexed_db/scopes/leveldb_scopes.cc
index 1f6d99a8979..f5c2d9ec0e0 100644
--- a/chromium/components/services/storage/indexed_db/scopes/leveldb_scopes.cc
+++ b/chromium/components/services/storage/indexed_db/scopes/leveldb_scopes.cc
@@ -13,7 +13,6 @@
#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
#include "base/memory/ptr_util.h"
-#include "base/optional.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/post_task.h"
@@ -27,6 +26,7 @@
#include "components/services/storage/indexed_db/scopes/leveldb_scopes_tasks.h"
#include "components/services/storage/indexed_db/scopes/scopes_lock_manager.h"
#include "components/services/storage/indexed_db/scopes/scopes_metadata.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
#include "third_party/leveldatabase/src/include/leveldb/slice.h"
diff --git a/chromium/components/services/storage/indexed_db/scopes/leveldb_scopes.h b/chromium/components/services/storage/indexed_db/scopes/leveldb_scopes.h
index e616373a586..0b1596e51d3 100644
--- a/chromium/components/services/storage/indexed_db/scopes/leveldb_scopes.h
+++ b/chromium/components/services/storage/indexed_db/scopes/leveldb_scopes.h
@@ -36,7 +36,6 @@ class LevelDBScopes {
public:
using TearDownCallback = base::RepeatingCallback<void(leveldb::Status)>;
using EmptyRange = std::pair<std::string, std::string>;
- static constexpr const size_t kDefaultMaxWriteBatchSizeBytes = 1024 * 1024;
enum class TaskRunnerMode {
// No new sequence runners are created. Both the cleanup and the revert
diff --git a/chromium/components/services/storage/indexed_db/scopes/scope_lock.h b/chromium/components/services/storage/indexed_db/scopes/scope_lock.h
index 26067646c51..35cde17e232 100644
--- a/chromium/components/services/storage/indexed_db/scopes/scope_lock.h
+++ b/chromium/components/services/storage/indexed_db/scopes/scope_lock.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_SCOPE_LOCK_H_
#include <iosfwd>
-#include <string>
#include "base/callback.h"
#include "base/callback_helpers.h"
diff --git a/chromium/components/services/storage/indexed_db/scopes/scope_lock_range.h b/chromium/components/services/storage/indexed_db/scopes/scope_lock_range.h
index d941bdd079a..0f85ccb8127 100644
--- a/chromium/components/services/storage/indexed_db/scopes/scope_lock_range.h
+++ b/chromium/components/services/storage/indexed_db/scopes/scope_lock_range.h
@@ -33,4 +33,4 @@ bool operator!=(const ScopeLockRange& x, const ScopeLockRange& y);
} // namespace content
-#endif /* COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_SCOPE_LOCK_RANGE_H_ */
+#endif // COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_SCOPE_LOCK_RANGE_H_
diff --git a/chromium/components/services/storage/indexed_db/scopes/scopes_lock_manager.h b/chromium/components/services/storage/indexed_db/scopes/scopes_lock_manager.h
index 3af61e05a66..46228663333 100644
--- a/chromium/components/services/storage/indexed_db/scopes/scopes_lock_manager.h
+++ b/chromium/components/services/storage/indexed_db/scopes/scopes_lock_manager.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SERVICES_STORAGE_INDEXED_DB_SCOPES_SCOPES_LOCK_MANAGER_H_
#include <iosfwd>
-#include <string>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h b/chromium/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h
index 080da231322..dbdcf1e59c2 100644
--- a/chromium/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h
+++ b/chromium/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_database.h
@@ -6,11 +6,11 @@
#define COMPONENTS_SERVICES_STORAGE_INDEXED_DB_TRANSACTIONAL_LEVELDB_TRANSACTIONAL_LEVELDB_DATABASE_H_
#include <memory>
+#include <set>
#include <string>
#include "base/containers/flat_set.h"
#include "base/containers/mru_cache.h"
-#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_transaction_unittest.cc b/chromium/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_transaction_unittest.cc
index 4042de63d93..644beeed548 100644
--- a/chromium/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_transaction_unittest.cc
+++ b/chromium/components/services/storage/indexed_db/transactional_leveldb/transactional_leveldb_transaction_unittest.cc
@@ -637,13 +637,13 @@ TEST_P(LevelDBTransactionRangeTest, RemoveRangeIteratorRetainsKey) {
ASSERT_TRUE(it->IsValid());
EXPECT_EQ(Compare(key_in_range2_, it->Key()), 0)
- << key_in_range2_ << " != " << it->Key().as_string();
+ << key_in_range2_ << " != " << it->Key();
status = it->Next();
EXPECT_TRUE(status.ok());
ASSERT_TRUE(it->IsValid());
EXPECT_EQ(Compare(key_after_range_, it->Key()), 0)
- << key_after_range_ << " != " << it->Key().as_string();
+ << key_after_range_ << " != " << it->Key();
status = transaction_->Commit(/*sync_on_commit=*/false);
EXPECT_TRUE(status.ok());
diff --git a/chromium/components/services/storage/partition_impl.cc b/chromium/components/services/storage/partition_impl.cc
index 2ea4dcf24ab..a462d52f11c 100644
--- a/chromium/components/services/storage/partition_impl.cc
+++ b/chromium/components/services/storage/partition_impl.cc
@@ -48,7 +48,7 @@ void ShutDown(std::unique_ptr<T> object) {
} // namespace
PartitionImpl::PartitionImpl(StorageServiceImpl* service,
- const base::Optional<base::FilePath>& path)
+ const absl::optional<base::FilePath>& path)
: service_(service), path_(path) {
receivers_.set_disconnect_handler(base::BindRepeating(
&PartitionImpl::OnDisconnect, base::Unretained(this)));
diff --git a/chromium/components/services/storage/partition_impl.h b/chromium/components/services/storage/partition_impl.h
index 1a1e434faa1..d69f9253222 100644
--- a/chromium/components/services/storage/partition_impl.h
+++ b/chromium/components/services/storage/partition_impl.h
@@ -9,11 +9,11 @@
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
namespace storage {
@@ -30,10 +30,10 @@ class PartitionImpl : public mojom::Partition {
public:
// |service| owns and outlives this object.
explicit PartitionImpl(StorageServiceImpl* service,
- const base::Optional<base::FilePath>& path);
+ const absl::optional<base::FilePath>& path);
~PartitionImpl() override;
- const base::Optional<base::FilePath>& path() const { return path_; }
+ const absl::optional<base::FilePath>& path() const { return path_; }
const mojo::ReceiverSet<mojom::Partition>& receivers() const {
return receivers_;
@@ -63,7 +63,7 @@ class PartitionImpl : public mojom::Partition {
void RemoveOriginContext(const url::Origin& origin);
StorageServiceImpl* const service_;
- const base::Optional<base::FilePath> path_;
+ const absl::optional<base::FilePath> path_;
mojo::ReceiverSet<mojom::Partition> receivers_;
std::map<url::Origin, std::unique_ptr<OriginContextImpl>> origin_contexts_;
diff --git a/chromium/components/services/storage/partition_impl_unittest.cc b/chromium/components/services/storage/partition_impl_unittest.cc
index 85362572ea1..016d5e3ca98 100644
--- a/chromium/components/services/storage/partition_impl_unittest.cc
+++ b/chromium/components/services/storage/partition_impl_unittest.cc
@@ -24,7 +24,7 @@ class StorageServicePartitionImplTest : public testing::Test {
void SetUp() override {
remote_service_->BindPartition(
- base::nullopt, remote_test_partition_.BindNewPipeAndPassReceiver());
+ absl::nullopt, remote_test_partition_.BindNewPipeAndPassReceiver());
remote_test_partition_.FlushForTesting();
ASSERT_EQ(1u, service_.partitions().size());
diff --git a/chromium/components/services/storage/public/cpp/BUILD.gn b/chromium/components/services/storage/public/cpp/BUILD.gn
index 30d12827a65..f3021e1ce45 100644
--- a/chromium/components/services/storage/public/cpp/BUILD.gn
+++ b/chromium/components/services/storage/public/cpp/BUILD.gn
@@ -8,6 +8,7 @@ component("cpp") {
public = [
"constants.h",
"quota_client_callback_wrapper.h",
+ "quota_error_or.h",
]
sources = [
@@ -16,6 +17,7 @@ component("cpp") {
]
public_deps = [
+ ":storage_key",
"//base",
"//components/services/storage/public/cpp/filesystem",
"//components/services/storage/public/mojom",
@@ -23,3 +25,27 @@ component("cpp") {
defines = [ "IS_STORAGE_SERVICE_PUBLIC_IMPL" ]
}
+
+component("storage_key") {
+ output_name = "storage_service_storage_key_support"
+
+ public = [ "storage_key.h" ]
+
+ sources = [ "storage_key.cc" ]
+
+ public_deps = [
+ "//base",
+ "//url",
+ ]
+
+ defines = [ "IS_STORAGE_SERVICE_STORAGE_KEY_SUPPORT_IMPL" ]
+}
+
+source_set("tests") {
+ testonly = true
+ sources = [ "storage_key_unittest.cc" ]
+ deps = [
+ ":storage_key",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/services/storage/public/cpp/constants.cc b/chromium/components/services/storage/public/cpp/constants.cc
index a9f47f86545..c79decd3187 100644
--- a/chromium/components/services/storage/public/cpp/constants.cc
+++ b/chromium/components/services/storage/public/cpp/constants.cc
@@ -6,6 +6,11 @@
namespace storage {
+// The base path where StorageBuckets data is persisted on disk, relative to a
+// storage partition's root directory.
+const base::FilePath::CharType kWebStorageDirectory[] =
+ FILE_PATH_LITERAL("WebStorage");
+
// The path where Local Storage data is persisted on disk, relative to a storage
// partition's root directory.
const base::FilePath::CharType kLocalStoragePath[] =
diff --git a/chromium/components/services/storage/public/cpp/constants.h b/chromium/components/services/storage/public/cpp/constants.h
index dced5eccc37..3897d6b73b4 100644
--- a/chromium/components/services/storage/public/cpp/constants.h
+++ b/chromium/components/services/storage/public/cpp/constants.h
@@ -11,6 +11,9 @@
namespace storage {
COMPONENT_EXPORT(STORAGE_SERVICE_PUBLIC)
+extern const base::FilePath::CharType kWebStorageDirectory[];
+
+COMPONENT_EXPORT(STORAGE_SERVICE_PUBLIC)
extern const base::FilePath::CharType kLocalStoragePath[];
COMPONENT_EXPORT(STORAGE_SERVICE_PUBLIC)
diff --git a/chromium/components/services/storage/public/cpp/filesystem/file_error_or.h b/chromium/components/services/storage/public/cpp/filesystem/file_error_or.h
index 087df89d5cc..4840f080ff1 100644
--- a/chromium/components/services/storage/public/cpp/filesystem/file_error_or.h
+++ b/chromium/components/services/storage/public/cpp/filesystem/file_error_or.h
@@ -8,7 +8,7 @@
#include <utility>
#include "base/files/file.h"
-#include "base/optional.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace storage {
@@ -21,7 +21,7 @@ class FileErrorOr {
explicit FileErrorOr() = default;
FileErrorOr(base::File::Error error) : error_(error) {}
FileErrorOr(ValueType&& value)
- : maybe_value_(base::in_place, std::move(value)) {}
+ : maybe_value_(absl::in_place, std::move(value)) {}
FileErrorOr(const FileErrorOr&) = delete;
FileErrorOr(FileErrorOr&&) = default;
FileErrorOr& operator=(const FileErrorOr&) = delete;
@@ -39,7 +39,7 @@ class FileErrorOr {
private:
base::File::Error error_ = base::File::FILE_ERROR_FAILED;
- base::Optional<ValueType> maybe_value_;
+ absl::optional<ValueType> maybe_value_;
};
} // namespace storage
diff --git a/chromium/components/services/storage/public/cpp/filesystem/filesystem_impl.cc b/chromium/components/services/storage/public/cpp/filesystem/filesystem_impl.cc
index 2986906cac6..b42a6066867 100644
--- a/chromium/components/services/storage/public/cpp/filesystem/filesystem_impl.cc
+++ b/chromium/components/services/storage/public/cpp/filesystem/filesystem_impl.cc
@@ -225,7 +225,7 @@ void FilesystemImpl::GetFileInfo(const base::FilePath& path,
if (base::GetFileInfo(MakeAbsolute(path), &info))
std::move(callback).Run(std::move(info));
else
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
}
void FilesystemImpl::GetPathAccess(const base::FilePath& path,
diff --git a/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy.cc b/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy.cc
index bef4260562d..a259a057c91 100644
--- a/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy.cc
+++ b/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy.cc
@@ -248,21 +248,21 @@ bool FilesystemProxy::DeletePathRecursively(const base::FilePath& path) {
return success;
}
-base::Optional<base::File::Info> FilesystemProxy::GetFileInfo(
+absl::optional<base::File::Info> FilesystemProxy::GetFileInfo(
const base::FilePath& path) {
if (!remote_directory_) {
base::File::Info info;
if (base::GetFileInfo(MaybeMakeAbsolute(path), &info))
return info;
- return base::nullopt;
+ return absl::nullopt;
}
- base::Optional<base::File::Info> info;
+ absl::optional<base::File::Info> info;
remote_directory_->GetFileInfo(MakeRelative(path), &info);
return info;
}
-base::Optional<FilesystemProxy::PathAccessInfo> FilesystemProxy::GetPathAccess(
+absl::optional<FilesystemProxy::PathAccessInfo> FilesystemProxy::GetPathAccess(
const base::FilePath& path) {
mojom::PathAccessInfoPtr info;
if (!remote_directory_)
@@ -271,12 +271,12 @@ base::Optional<FilesystemProxy::PathAccessInfo> FilesystemProxy::GetPathAccess(
remote_directory_->GetPathAccess(MakeRelative(path), &info);
if (!info)
- return base::nullopt;
+ return absl::nullopt;
return PathAccessInfo{info->can_read, info->can_write};
}
-base::Optional<int> FilesystemProxy::GetMaximumPathComponentLength(
+absl::optional<int> FilesystemProxy::GetMaximumPathComponentLength(
const base::FilePath& path) {
if (!remote_directory_)
return base::GetMaximumPathComponentLength(MaybeMakeAbsolute(path));
@@ -286,7 +286,7 @@ base::Optional<int> FilesystemProxy::GetMaximumPathComponentLength(
remote_directory_->GetMaximumPathComponentLength(MakeRelative(path), &success,
&len);
if (!success)
- return base::nullopt;
+ return absl::nullopt;
return len;
}
@@ -357,7 +357,7 @@ int64_t FilesystemProxy::ComputeDirectorySize(const base::FilePath& path) {
return running_size;
for (auto& entry : entries) {
- base::Optional<base::File::Info> info;
+ absl::optional<base::File::Info> info;
base::FilePath path = entry;
remote_directory_->GetFileInfo(relative_path.Append(entry), &info);
if (info.has_value())
diff --git a/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy.h b/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy.h
index e8d0c795064..47c0abd1f51 100644
--- a/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy.h
+++ b/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy.h
@@ -107,7 +107,7 @@ class COMPONENT_EXPORT(STORAGE_SERVICE_FILESYSTEM_SUPPORT) FilesystemProxy {
// Retrieves information about a file or directory at |path|. Returns a valid
// base::File::Info value on success, or null on failure.
- base::Optional<base::File::Info> GetFileInfo(const base::FilePath& path);
+ absl::optional<base::File::Info> GetFileInfo(const base::FilePath& path);
// Retrieves information about access rights for a path in the filesystem.
// Returns a valid PathAccessInfo on success, or null on failure.
@@ -115,11 +115,11 @@ class COMPONENT_EXPORT(STORAGE_SERVICE_FILESYSTEM_SUPPORT) FilesystemProxy {
bool can_read = false;
bool can_write = false;
};
- base::Optional<PathAccessInfo> GetPathAccess(const base::FilePath& path);
+ absl::optional<PathAccessInfo> GetPathAccess(const base::FilePath& path);
// Returns the maximum length of path component on the volume containing the
// directory |path|, in the number of FilePath::CharType, or -1 on failure.
- base::Optional<int> GetMaximumPathComponentLength(const base::FilePath& path);
+ absl::optional<int> GetMaximumPathComponentLength(const base::FilePath& path);
// Renames a file from |old_path| to |new_path|. Must be atomic.
base::File::Error RenameFile(const base::FilePath& old_path,
diff --git a/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy_unittest.cc b/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy_unittest.cc
index 990ff2f3088..156d5a35001 100644
--- a/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy_unittest.cc
+++ b/chromium/components/services/storage/public/cpp/filesystem/filesystem_proxy_unittest.cc
@@ -359,22 +359,22 @@ TEST_P(FilesystemProxyTest, DeletePathRecursively) {
TEST_P(FilesystemProxyTest, GetMaximumPathComponentLength) {
// This has different values on different platforms, so merely smoke test
// this to make sure it returns a reasonable valid value.
- base::Optional<int> max = proxy().GetMaximumPathComponentLength(kDir1);
+ absl::optional<int> max = proxy().GetMaximumPathComponentLength(kDir1);
ASSERT_TRUE(max.has_value());
EXPECT_GT(*max, 50);
}
TEST_P(FilesystemProxyTest, GetFileInfo) {
- base::Optional<base::File::Info> file1_info = proxy().GetFileInfo(kFile1);
+ absl::optional<base::File::Info> file1_info = proxy().GetFileInfo(kFile1);
ASSERT_TRUE(file1_info.has_value());
EXPECT_FALSE(file1_info->is_directory);
EXPECT_EQ(static_cast<int>(base::size(kFile1Contents) - 1), file1_info->size);
- base::Optional<base::File::Info> dir1_info = proxy().GetFileInfo(kDir1);
+ absl::optional<base::File::Info> dir1_info = proxy().GetFileInfo(kDir1);
ASSERT_TRUE(dir1_info.has_value());
EXPECT_TRUE(dir1_info->is_directory);
- base::Optional<base::File::Info> dir1_file1_info =
+ absl::optional<base::File::Info> dir1_file1_info =
proxy().GetFileInfo(kDir1.Append(kDir1File1));
ASSERT_TRUE(dir1_file1_info.has_value());
EXPECT_FALSE(dir1_file1_info->is_directory);
diff --git a/chromium/components/services/storage/public/cpp/quota_error_or.h b/chromium/components/services/storage/public/cpp/quota_error_or.h
new file mode 100644
index 00000000000..ceb35f0c241
--- /dev/null
+++ b/chromium/components/services/storage/public/cpp/quota_error_or.h
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SERVICES_STORAGE_PUBLIC_CPP_QUOTA_ERROR_OR_H_
+#define COMPONENTS_SERVICES_STORAGE_PUBLIC_CPP_QUOTA_ERROR_OR_H_
+
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace storage {
+
+enum class QuotaError {
+ kNone = 0,
+ kUnknownError,
+ kDatabaseError,
+ kEntryExistsError,
+};
+
+// Helper for methods which perform database operations which may fail. Objects
+// of this type can on either a QuotaError or a result value of arbitrary type.
+template <typename ValueType>
+class QuotaErrorOr {
+ public:
+ QuotaErrorOr() = default;
+ QuotaErrorOr(QuotaError error) : error_(error) {} // NOLINT
+ QuotaErrorOr(const ValueType& value) : maybe_value_(value) {} // NOLINT
+ QuotaErrorOr(ValueType&& value) // NOLINT
+ : maybe_value_(absl::in_place, std::move(value)) {}
+ QuotaErrorOr(const QuotaErrorOr&) = delete;
+ QuotaErrorOr(QuotaErrorOr&&) noexcept = default;
+ QuotaErrorOr& operator=(const QuotaErrorOr&) = delete;
+ QuotaErrorOr& operator=(QuotaErrorOr&&) noexcept = default;
+ ~QuotaErrorOr() = default;
+
+ bool ok() const { return maybe_value_.has_value(); }
+ QuotaError error() const {
+ DCHECK(!ok());
+ return error_;
+ }
+
+ ValueType& value() { return maybe_value_.value(); }
+ const ValueType& value() const { return maybe_value_.value(); }
+
+ ValueType* operator->() { return &maybe_value_.value(); }
+ const ValueType* operator->() const { return &maybe_value_.value(); }
+
+ private:
+ QuotaError error_ = QuotaError::kNone;
+ absl::optional<ValueType> maybe_value_;
+};
+
+} // namespace storage
+
+#endif // COMPONENTS_SERVICES_STORAGE_PUBLIC_CPP_QUOTA_ERROR_OR_H_
diff --git a/chromium/components/services/storage/public/cpp/storage_key.cc b/chromium/components/services/storage/public/cpp/storage_key.cc
new file mode 100644
index 00000000000..787aa3330a3
--- /dev/null
+++ b/chromium/components/services/storage/public/cpp/storage_key.cc
@@ -0,0 +1,32 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/storage/public/cpp/storage_key.h"
+
+#include "url/gurl.h"
+
+namespace storage {
+
+StorageKey StorageKey::Deserialize(const std::string& in) {
+ return StorageKey(url::Origin::Create(GURL(in)));
+}
+
+std::string StorageKey::Serialize() const {
+ DCHECK(!opaque());
+ return origin_.GetURL().spec();
+}
+
+bool operator==(const StorageKey& lhs, const StorageKey& rhs) {
+ return lhs.origin_ == rhs.origin_;
+}
+
+bool operator!=(const StorageKey& lhs, const StorageKey& rhs) {
+ return !(lhs == rhs);
+}
+
+bool operator<(const StorageKey& lhs, const StorageKey& rhs) {
+ return lhs.origin_ < rhs.origin_;
+}
+
+} // namespace storage
diff --git a/chromium/components/services/storage/public/cpp/storage_key.h b/chromium/components/services/storage/public/cpp/storage_key.h
new file mode 100644
index 00000000000..ca26e4d256e
--- /dev/null
+++ b/chromium/components/services/storage/public/cpp/storage_key.h
@@ -0,0 +1,61 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SERVICES_STORAGE_PUBLIC_CPP_STORAGE_KEY_H_
+#define COMPONENTS_SERVICES_STORAGE_PUBLIC_CPP_STORAGE_KEY_H_
+
+#include <string>
+
+#include "base/component_export.h"
+#include "url/origin.h"
+
+namespace storage {
+
+// A class representing the key that Storage APIs use to key their storage on.
+class COMPONENT_EXPORT(STORAGE_SERVICE_STORAGE_KEY_SUPPORT) StorageKey {
+ public:
+ StorageKey() = default;
+ explicit StorageKey(const url::Origin& origin) : origin_(origin) {}
+
+ // Copyable and Moveable.
+ StorageKey(const StorageKey& other) = default;
+ StorageKey& operator=(const StorageKey& other) = default;
+ StorageKey(StorageKey&& other) = default;
+ StorageKey& operator=(StorageKey&& other) = default;
+
+ ~StorageKey() = default;
+
+ // Returns a newly constructed StorageKey from, a previously serialized, `in`.
+ // If `in` is invalid then the StorageKey will be opaque. A deserialized
+ // StorageKey will be equivalent to the StorageKey that was initially
+ // serialized.
+ static StorageKey Deserialize(const std::string& in);
+
+ // Serializes the `StorageKey` into a string.
+ // This function will return the spec url of the underlying Origin. Do not
+ // call if `this` is opaque.
+ std::string Serialize() const;
+
+ bool opaque() const { return origin_.opaque(); }
+
+ const url::Origin& origin() const { return origin_; }
+
+ private:
+ COMPONENT_EXPORT(STORAGE_SERVICE_STORAGE_KEY_SUPPORT)
+ friend bool operator==(const StorageKey& lhs, const StorageKey& rhs);
+
+ COMPONENT_EXPORT(STORAGE_SERVICE_STORAGE_KEY_SUPPORT)
+ friend bool operator!=(const StorageKey& lhs, const StorageKey& rhs);
+
+ // Allows StorageKey to be used as a key in STL (for example, a std::set or
+ // std::map).
+ COMPONENT_EXPORT(STORAGE_SERVICE_STORAGE_KEY_SUPPORT)
+ friend bool operator<(const StorageKey& lhs, const StorageKey& rhs);
+
+ url::Origin origin_;
+};
+
+} // namespace storage
+
+#endif // COMPONENTS_SERVICES_STORAGE_PUBLIC_CPP_STORAGE_KEY_H_
diff --git a/chromium/components/services/storage/public/cpp/storage_key_unittest.cc b/chromium/components/services/storage/public/cpp/storage_key_unittest.cc
new file mode 100644
index 00000000000..8e9065b882e
--- /dev/null
+++ b/chromium/components/services/storage/public/cpp/storage_key_unittest.cc
@@ -0,0 +1,115 @@
+// Copyright 2021 The Chromium Authors. 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/public/cpp/storage_key.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace storage {
+
+// Test when a constructed StorageKey object should be considered valid/opaque.
+TEST(StorageStorageKeyTest, ConstructionValidity) {
+ StorageKey empty = StorageKey();
+ EXPECT_TRUE(empty.opaque());
+
+ url::Origin valid_origin = url::Origin::Create(GURL("https://example.com"));
+ StorageKey valid = StorageKey(valid_origin);
+ EXPECT_FALSE(valid.opaque());
+
+ url::Origin invalid_origin =
+ url::Origin::Create(GURL("I'm not a valid URL."));
+ StorageKey invalid = StorageKey(invalid_origin);
+ EXPECT_TRUE(invalid.opaque());
+}
+
+// Test that StorageKeys are/aren't equivalent as expected.
+TEST(StorageStorageKeyTest, Equivalance) {
+ url::Origin origin1 = url::Origin::Create(GURL("https://example.com"));
+ url::Origin origin2 = url::Origin::Create(GURL("https://test.example"));
+ url::Origin origin3 = url::Origin();
+ url::Origin origin4 =
+ url::Origin(); // Creates a different opaque origin than origin3.
+
+ StorageKey key1_origin1 = StorageKey(origin1);
+ StorageKey key2_origin1 = StorageKey(origin1);
+ StorageKey key3_origin2 = StorageKey(origin2);
+
+ StorageKey key4_origin3 = StorageKey(origin3);
+ StorageKey key5_origin3 = StorageKey(origin3);
+ StorageKey key6_origin4 = StorageKey(origin4);
+ EXPECT_TRUE(key4_origin3.opaque());
+ EXPECT_TRUE(key5_origin3.opaque());
+ EXPECT_TRUE(key6_origin4.opaque());
+
+ // All are equivalent to themselves
+ EXPECT_EQ(key1_origin1, key1_origin1);
+ EXPECT_EQ(key2_origin1, key2_origin1);
+ EXPECT_EQ(key3_origin2, key3_origin2);
+ EXPECT_EQ(key4_origin3, key4_origin3);
+ EXPECT_EQ(key5_origin3, key5_origin3);
+ EXPECT_EQ(key6_origin4, key6_origin4);
+
+ // StorageKeys created from the same origins are equivalent.
+ EXPECT_EQ(key1_origin1, key2_origin1);
+ EXPECT_EQ(key4_origin3, key5_origin3);
+
+ // StorageKeys created from different origins are not equivalent.
+ EXPECT_NE(key1_origin1, key3_origin2);
+ EXPECT_NE(key4_origin3, key6_origin4);
+}
+
+// Test that StorageKeys Serialize to the expected value.
+TEST(StorageStorageKeyTest, Serialize) {
+ std::string example = "https://example.com/";
+ std::string example_no_trailing_slash = "https://example.com";
+ std::string test = "https://test.example/";
+ StorageKey key1 = StorageKey(url::Origin::Create(GURL(example)));
+ StorageKey key2 =
+ StorageKey(url::Origin::Create(GURL(example_no_trailing_slash)));
+ StorageKey key3 = StorageKey(url::Origin::Create(GURL(test)));
+
+ EXPECT_EQ(key1.Serialize(), example);
+ // URLs will be normalized into the same spec format.
+ EXPECT_EQ(key2.Serialize(), example);
+ EXPECT_EQ(key3.Serialize(), test);
+}
+
+// Test that deserialized StorageKeys are valid/opaque as expected.
+TEST(StorageStorageKeyTest, Deserialize) {
+ std::string example = "https://example.com/";
+ std::string test = "https://test.example/";
+ std::string wrong = "I'm not a valid URL.";
+
+ StorageKey key1 = StorageKey::Deserialize(example);
+ StorageKey key2 = StorageKey::Deserialize(test);
+ StorageKey key3 = StorageKey::Deserialize(wrong);
+ StorageKey key4 = StorageKey::Deserialize(std::string());
+
+ EXPECT_FALSE(key1.opaque());
+ EXPECT_FALSE(key2.opaque());
+ EXPECT_TRUE(key3.opaque());
+ EXPECT_TRUE(key4.opaque());
+}
+
+// Test that a StorageKey, constructed by deserializing another serialized
+// StorageKey, is equivalent to the original.
+TEST(StorageStorageKeyTest, SerializeDeserialize) {
+ url::Origin origin1 = url::Origin::Create(GURL("https://example.com"));
+ url::Origin origin2 = url::Origin::Create(GURL("https://test.example"));
+
+ StorageKey key1 = StorageKey(origin1);
+ StorageKey key2 = StorageKey(origin2);
+
+ std::string key1_string = key1.Serialize();
+ std::string key2_string = key2.Serialize();
+
+ StorageKey key1_deserialized = StorageKey::Deserialize(key1_string);
+ StorageKey key2_deserialized = StorageKey::Deserialize(key2_string);
+
+ EXPECT_EQ(key1, key1_deserialized);
+ EXPECT_EQ(key2, key2_deserialized);
+}
+
+} // namespace storage
diff --git a/chromium/components/services/storage/public/mojom/BUILD.gn b/chromium/components/services/storage/public/mojom/BUILD.gn
index df4c03bf3d5..58eeb069280 100644
--- a/chromium/components/services/storage/public/mojom/BUILD.gn
+++ b/chromium/components/services/storage/public/mojom/BUILD.gn
@@ -25,6 +25,7 @@ mojom("mojom") {
public_deps = [
"//components/services/storage/public/mojom/filesystem",
+ "//components/services/storage/public/mojom/storage_key",
"//mojo/public/mojom/base",
"//services/network/public/mojom",
"//third_party/blink/public/mojom:mojom_core",
@@ -49,3 +50,15 @@ mojom("test_api") {
testonly = true
sources = [ "test_api.test-mojom" ]
}
+
+source_set("tests") {
+ testonly = true
+ sources = [ "storage_key/storage_key_mojom_traits_unittest.cc" ]
+ deps = [
+ "//components/services/storage/public/cpp:storage_key",
+ "//components/services/storage/public/mojom/storage_key",
+ "//mojo/public/cpp/bindings",
+ "//mojo/public/cpp/test_support:test_utils",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/components/services/storage/public/mojom/service_worker_storage_control.mojom b/chromium/components/services/storage/public/mojom/service_worker_storage_control.mojom
index c35a4e4fbb2..67e380e73d1 100644
--- a/chromium/components/services/storage/public/mojom/service_worker_storage_control.mojom
+++ b/chromium/components/services/storage/public/mojom/service_worker_storage_control.mojom
@@ -6,10 +6,10 @@ module storage.mojom;
import "components/services/storage/public/mojom/storage_policy_update.mojom";
import "components/services/storage/public/mojom/service_worker_database.mojom";
+import "components/services/storage/public/mojom/storage_key/storage_key.mojom";
import "mojo/public/mojom/base/big_buffer.mojom";
import "mojo/public/mojom/base/time.mojom";
import "services/network/public/mojom/url_response_head.mojom";
-import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";
// An interface that is used to keep track of which service worker versions are
@@ -54,10 +54,10 @@ struct ServiceWorkerFindRegistrationResult {
// Used to tell the browser process or embedders if there are registrations
// after ServiceWorkerStorageControl::DeleteRegistration().
-enum ServiceWorkerStorageOriginState {
- // Registrations may exist for the origin. It cannot be deleted.
+enum ServiceWorkerStorageStorageKeyState {
+ // Registrations may exist for the StorageKey. It cannot be deleted.
kKeep,
- // No registrations exist for the origin. It can be deleted.
+ // No registrations exist for the StorageKey. It can be deleted.
kDelete,
};
@@ -139,30 +139,31 @@ interface ServiceWorkerStorageControl {
// have been deleted.
Recover(array<ServiceWorkerLiveVersionInfo> versions) => ();
- // Returns all origins which have service worker registrations.
- GetRegisteredOrigins() => (array<url.mojom.Origin> origins);
+ // Returns all StorageKeys which have service worker registrations.
+ GetRegisteredStorageKeys() => (array<storage.mojom.StorageKey> keys);
- // Reads a stored registration for |client_id|.
- FindRegistrationForClientUrl(url.mojom.Url client_url) =>
+ // Reads a stored registration for `client_url` that is associated with `key`.
+ FindRegistrationForClientUrl(url.mojom.Url client_url,
+ storage.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status,
ServiceWorkerFindRegistrationResult? result);
- // Reads a stored registration for |scope|.
- FindRegistrationForScope(url.mojom.Url scope) =>
+ // Reads a stored registration for `scope` that is associated with `key`.
+ FindRegistrationForScope(url.mojom.Url scope, storage.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status,
ServiceWorkerFindRegistrationResult? result);
- // Reads a stored registration for |registration_id|. |origin| is to
+ // Reads a stored registration for `registration_id`. `key` is to
// be used as a hint to look up the registration faster.
- FindRegistrationForId(int64 registration_id, url.mojom.Origin? origin) =>
+ FindRegistrationForId(int64 registration_id, storage.mojom.StorageKey? key) =>
(ServiceWorkerDatabaseStatus status,
ServiceWorkerFindRegistrationResult? result);
- // Returns all stored registrations for a given origin.
- GetRegistrationsForOrigin(url.mojom.Origin origin) =>
+ // Returns all stored registrations for a given StorageKey.
+ GetRegistrationsForStorageKey(storage.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status,
array<ServiceWorkerFindRegistrationResult> registrations);
- // Returns the total resource size for a given origin.
- GetUsageForOrigin(url.mojom.Origin origin) =>
+ // Returns the total resource size for a given StorageKey.
+ GetUsageForStorageKey(storage.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status, int64 usage);
// Returns all stored registrations.
@@ -182,29 +183,29 @@ interface ServiceWorkerStorageControl {
// Deletes the registration specified by `registration_id`.
// `deleted_resources_size` carries the total size of deleted resources.
- // `origin_state` is kDelete if there is no registration for |origin| after
+ // `storage_key_state` is kDelete if there is no registration for `key` after
// deletion.
- DeleteRegistration(int64 registration_id, url.mojom.Url origin) =>
+ DeleteRegistration(int64 registration_id, storage.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status,
uint64 deleted_resources_size,
- ServiceWorkerStorageOriginState origin_state);
+ ServiceWorkerStorageStorageKeyState storage_key_state);
// Updates the state of the registration's stored version to active.
- UpdateToActiveState(int64 registration_id, url.mojom.Url origin) =>
+ UpdateToActiveState(int64 registration_id, storage.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status);
// Updates the last update check time on the storage.
UpdateLastUpdateCheckTime(int64 registration_id,
- url.mojom.Url origin,
+ storage.mojom.StorageKey key,
mojo_base.mojom.Time last_update_check_time) =>
(ServiceWorkerDatabaseStatus status);
// Updates the registration's navigation preload enabled flag in storage.
UpdateNavigationPreloadEnabled(int64 registration_id,
- url.mojom.Url origin,
+ storage.mojom.StorageKey key,
bool enable) =>
(ServiceWorkerDatabaseStatus status);
// Updates the registration's navigation preload header in storage.
UpdateNavigationPreloadHeader(int64 registration_id,
- url.mojom.Url origin,
+ storage.mojom.StorageKey key,
string value) =>
(ServiceWorkerDatabaseStatus status);
@@ -253,9 +254,9 @@ interface ServiceWorkerStorageControl {
// of |values| are the same as |keys|.
GetUserData(int64 registration_id, array<string> keys) =>
(ServiceWorkerDatabaseStatus status, array<string> values);
- // Stores |user_data| on persistent storage.
+ // Stores `user_data` on persistent storage.
StoreUserData(int64 registration_id,
- url.mojom.Origin origin,
+ storage.mojom.StorageKey key,
array<ServiceWorkerUserData> user_data) =>
(ServiceWorkerDatabaseStatus status);
// Clears user data specified by |registration_id| and |keys|.
diff --git a/chromium/components/services/storage/public/mojom/storage_key/BUILD.gn b/chromium/components/services/storage/public/mojom/storage_key/BUILD.gn
new file mode 100644
index 00000000000..18d72f7c075
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/storage_key/BUILD.gn
@@ -0,0 +1,31 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("storage_key") {
+ sources = [ "storage_key.mojom" ]
+
+ public_deps = [
+ "//mojo/public/mojom/base",
+ "//url/mojom:url_mojom_origin",
+ ]
+
+ cpp_typemaps = [
+ {
+ types = [
+ {
+ mojom = "storage.mojom.StorageKey"
+ cpp = "::storage::StorageKey"
+ },
+ ]
+ traits_headers = [ "storage_key_mojom_traits.h" ]
+ traits_sources = [ "storage_key_mojom_traits.cc" ]
+ traits_public_deps = [
+ "//components/services/storage/public/cpp:storage_key",
+ "//url/mojom:url_mojom_origin",
+ ]
+ },
+ ]
+}
diff --git a/chromium/components/services/storage/public/mojom/storage_key/OWNERS b/chromium/components/services/storage/public/mojom/storage_key/OWNERS
new file mode 100644
index 00000000000..d9703077f8b
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/storage_key/OWNERS
@@ -0,0 +1,4 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
+per-file *_mojom_traits*.*=set noparent
+per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/chromium/components/services/storage/public/mojom/storage_key/storage_key.mojom b/chromium/components/services/storage/public/mojom/storage_key/storage_key.mojom
new file mode 100644
index 00000000000..2694331d23f
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/storage_key/storage_key.mojom
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module storage.mojom;
+
+import "url/mojom/origin.mojom";
+
+// Represents a storage::StorageKey (components/services/storage/public/cpp).
+struct StorageKey {
+ url.mojom.Origin origin;
+};
diff --git a/chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits.cc b/chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits.cc
new file mode 100644
index 00000000000..2e0a95dd04a
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits.cc
@@ -0,0 +1,22 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/storage/public/mojom/storage_key/storage_key_mojom_traits.h"
+
+#include "url/origin.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<storage::mojom::StorageKeyDataView, storage::StorageKey>::
+ Read(storage::mojom::StorageKeyDataView data, storage::StorageKey* out) {
+ url::Origin origin;
+ if (!data.ReadOrigin(&origin))
+ return false;
+
+ *out = storage::StorageKey(origin);
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits.h b/chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits.h
new file mode 100644
index 00000000000..61452e17fc5
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits.h
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SERVICES_STORAGE_PUBLIC_MOJOM_STORAGE_KEY_STORAGE_KEY_MOJOM_TRAITS_H_
+#define COMPONENTS_SERVICES_STORAGE_PUBLIC_MOJOM_STORAGE_KEY_STORAGE_KEY_MOJOM_TRAITS_H_
+
+#include "components/services/storage/public/cpp/storage_key.h"
+#include "components/services/storage/public/mojom/storage_key/storage_key.mojom.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+
+namespace url {
+class Origin;
+} // namespace url
+
+namespace mojo {
+
+template <>
+class StructTraits<storage::mojom::StorageKeyDataView, storage::StorageKey> {
+ public:
+ static const url::Origin& origin(const storage::StorageKey& key) {
+ return key.origin();
+ }
+
+ static bool Read(storage::mojom::StorageKeyDataView data,
+ storage::StorageKey* out);
+};
+
+} // namespace mojo
+
+#endif // COMPONENTS_SERVICES_STORAGE_PUBLIC_MOJOM_STORAGE_KEY_STORAGE_KEY_MOJOM_TRAITS_H_
diff --git a/chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits_unittest.cc b/chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits_unittest.cc
new file mode 100644
index 00000000000..2cc8506c2c6
--- /dev/null
+++ b/chromium/components/services/storage/public/mojom/storage_key/storage_key_mojom_traits_unittest.cc
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/storage/public/mojom/storage_key/storage_key_mojom_traits.h"
+
+#include "components/services/storage/public/cpp/storage_key.h"
+#include "components/services/storage/public/mojom/storage_key/storage_key.mojom.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace storage {
+namespace {
+
+TEST(StorageKeyMojomTraitsTest, SerializeAndDeserialize) {
+ StorageKey test_keys[] = {
+ StorageKey(url::Origin::Create(GURL("https://example.com"))),
+ StorageKey(url::Origin::Create(GURL("http://example.com"))),
+ StorageKey(url::Origin::Create(GURL("https://example.test"))),
+ StorageKey(url::Origin::Create(GURL("https://sub.example.com"))),
+ StorageKey(url::Origin::Create(GURL("http://sub2.example.com"))),
+ StorageKey(url::Origin()),
+ };
+
+ for (auto& original : test_keys) {
+ StorageKey copied;
+ EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::StorageKey>(original,
+ copied));
+ EXPECT_EQ(original, copied);
+ }
+}
+
+} // namespace
+} // namespace storage \ No newline at end of file
diff --git a/chromium/components/services/storage/sandboxed_vfs_delegate.cc b/chromium/components/services/storage/sandboxed_vfs_delegate.cc
index 646edb45d2d..c4f433a3ef9 100644
--- a/chromium/components/services/storage/sandboxed_vfs_delegate.cc
+++ b/chromium/components/services/storage/sandboxed_vfs_delegate.cc
@@ -9,9 +9,9 @@
#include "base/files/file.h"
#include "base/files/file_path.h"
-#include "base/optional.h"
#include "components/services/storage/public/cpp/filesystem/file_error_or.h"
#include "components/services/storage/public/cpp/filesystem/filesystem_proxy.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace storage {
@@ -38,12 +38,12 @@ int SandboxedVfsDelegate::DeleteFile(const base::FilePath& file_path,
return SQLITE_OK;
}
-base::Optional<sql::SandboxedVfs::PathAccessInfo>
+absl::optional<sql::SandboxedVfs::PathAccessInfo>
SandboxedVfsDelegate::GetPathAccess(const base::FilePath& file_path) {
- base::Optional<FilesystemProxy::PathAccessInfo> info =
+ absl::optional<FilesystemProxy::PathAccessInfo> info =
filesystem_->GetPathAccess(file_path);
if (!info)
- return base::nullopt;
+ return absl::nullopt;
sql::SandboxedVfs::PathAccessInfo access;
access.can_read = info->can_read;
diff --git a/chromium/components/services/storage/sandboxed_vfs_delegate.h b/chromium/components/services/storage/sandboxed_vfs_delegate.h
index e9c63c87db8..b3cf2c68632 100644
--- a/chromium/components/services/storage/sandboxed_vfs_delegate.h
+++ b/chromium/components/services/storage/sandboxed_vfs_delegate.h
@@ -21,7 +21,7 @@ class SandboxedVfsDelegate : public sql::SandboxedVfs::Delegate {
// sql::SandboxedVfs::Delegate implementation:
base::File OpenFile(const base::FilePath& file_path,
int sqlite_requested_flags) override;
- base::Optional<sql::SandboxedVfs::PathAccessInfo> GetPathAccess(
+ absl::optional<sql::SandboxedVfs::PathAccessInfo> GetPathAccess(
const base::FilePath& file_path) override;
int DeleteFile(const base::FilePath& file_path, bool sync_dir) override;
bool SetFileLength(const base::FilePath& file_path,
diff --git a/chromium/components/services/storage/service_worker/service_worker_database.cc b/chromium/components/services/storage/service_worker/service_worker_database.cc
index d9e116c8d10..d108d6c2b22 100644
--- a/chromium/components/services/storage/service_worker/service_worker_database.cc
+++ b/chromium/components/services/storage/service_worker/service_worker_database.cc
@@ -45,13 +45,19 @@
// key: "INITDATA_NEXT_VERSION_ID"
// value: <int64_t 'next_available_version_id'>
//
-// key: "INITDATA_UNIQUE_ORIGIN:" + <GURL 'origin'>
+// Note: This has changed from `GURL origin` to StorageKey but the name will
+// be updated in the future to avoid a migration.
+// TODO(crbug.com/1199077): Update name during a migration to Version 3.
+// key: "INITDATA_UNIQUE_ORIGIN:" + <StorageKey 'key'>
// value: <empty>
//
// key: "PRES:" + <int64_t 'purgeable_resource_id'>
// value: <empty>
//
-// key: "REG:" + <GURL 'origin'> + '\x00' + <int64_t 'registration_id'>
+// Note: This has changed from `GURL origin` to StorageKey but the name will
+// be updated in the future to avoid a migration.
+// TODO(crbug.com/1199077): Update name during a migration to Version 3.
+// key: "REG:" + <StorageKey 'key'> + '\x00' + <int64_t 'registration_id'>
// (ex. "REG:http://example.com\x00123456")
// value: <ServiceWorkerRegistrationData serialized as a string>
//
@@ -73,6 +79,9 @@
//
// Version 2
//
+// Note: This has changed from `GURL origin` to StorageKey but the name will
+// be updated in the future to avoid a migration.
+// TODO(crbug.com/1199077): Update name during a migration to Version 3.
// key: "REGID_TO_ORIGIN:" + <int64_t 'registration_id'>
// value: <GURL 'origin'>
//
@@ -144,15 +153,15 @@ bool RemovePrefix(const std::string& str,
return true;
}
-std::string CreateRegistrationKeyPrefix(const url::Origin& origin) {
+std::string CreateRegistrationKeyPrefix(const StorageKey& key) {
return base::StringPrintf("%s%s%c", service_worker_internals::kRegKeyPrefix,
- origin.GetURL().spec().c_str(),
+ key.Serialize().c_str(),
service_worker_internals::kKeySeparator);
}
std::string CreateRegistrationKey(int64_t registration_id,
- const url::Origin& origin) {
- return CreateRegistrationKeyPrefix(origin).append(
+ const StorageKey& key) {
+ return CreateRegistrationKeyPrefix(key).append(
base::NumberToString(registration_id));
}
@@ -167,9 +176,9 @@ std::string CreateResourceRecordKey(int64_t version_id, int64_t resource_id) {
.append(base::NumberToString(resource_id));
}
-std::string CreateUniqueOriginKey(const GURL& origin) {
+std::string CreateUniqueOriginKey(const StorageKey& key) {
return base::StringPrintf("%s%s", service_worker_internals::kUniqueOriginKey,
- origin.GetOrigin().spec().c_str());
+ key.Serialize().c_str());
}
std::string CreateResourceIdKey(const char* key_prefix, int64_t resource_id) {
@@ -201,15 +210,15 @@ std::string CreateHasUserDataKey(int64_t registration_id,
.append(base::NumberToString(registration_id));
}
-std::string CreateRegistrationIdToOriginKey(int64_t registration_id) {
+std::string CreateRegistrationIdToStorageKey(int64_t registration_id) {
return base::StringPrintf("%s%s",
service_worker_internals::kRegIdToOriginKeyPrefix,
base::NumberToString(registration_id).c_str());
}
-void PutUniqueOriginToBatch(const GURL& origin, leveldb::WriteBatch* batch) {
+void PutUniqueOriginToBatch(const StorageKey& key, leveldb::WriteBatch* batch) {
// Value should be empty.
- batch->Put(CreateUniqueOriginKey(origin), "");
+ batch->Put(CreateUniqueOriginKey(key), "");
}
void PutPurgeableResourceIdToBatch(int64_t resource_id,
@@ -339,10 +348,10 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetNextAvailableIds(
}
ServiceWorkerDatabase::Status
-ServiceWorkerDatabase::GetOriginsWithRegistrations(
- std::set<url::Origin>* origins) {
+ServiceWorkerDatabase::GetStorageKeysWithRegistrations(
+ std::set<StorageKey>* keys) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(origins->empty());
+ DCHECK(keys->empty());
Status status = LazyOpen(false);
if (IsNewOrNonexistentDatabase(status))
@@ -357,24 +366,23 @@ ServiceWorkerDatabase::GetOriginsWithRegistrations(
itr->Next()) {
status = LevelDBStatusToServiceWorkerDBStatus(itr->status());
if (status != Status::kOk) {
- origins->clear();
+ keys->clear();
break;
}
- std::string origin_str;
+ std::string key_str;
if (!RemovePrefix(itr->key().ToString(),
- service_worker_internals::kUniqueOriginKey,
- &origin_str))
+ service_worker_internals::kUniqueOriginKey, &key_str))
break;
- GURL origin(origin_str);
- if (!origin.is_valid()) {
+ StorageKey key = StorageKey::Deserialize(key_str);
+ if (key.opaque()) {
status = Status::kErrorCorrupted;
- origins->clear();
+ keys->clear();
break;
}
- origins->insert(url::Origin::Create(origin));
+ keys->insert(key);
}
}
@@ -382,8 +390,9 @@ ServiceWorkerDatabase::GetOriginsWithRegistrations(
return status;
}
-ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetRegistrationsForOrigin(
- const url::Origin& origin,
+ServiceWorkerDatabase::Status
+ServiceWorkerDatabase::GetRegistrationsForStorageKey(
+ const StorageKey& key,
std::vector<mojom::ServiceWorkerRegistrationDataPtr>* registrations,
std::vector<std::vector<mojom::ServiceWorkerResourceRecordPtr>>*
opt_resources_list) {
@@ -396,7 +405,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetRegistrationsForOrigin(
if (status != Status::kOk)
return status;
- std::string prefix = CreateRegistrationKeyPrefix(origin);
+ std::string prefix = CreateRegistrationKeyPrefix(key);
// Read all registrations.
{
@@ -454,8 +463,8 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetRegistrationsForOrigin(
return status;
}
-ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetUsageForOrigin(
- const url::Origin& origin,
+ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetUsageForStorageKey(
+ const StorageKey& key,
int64_t& out_usage) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -467,7 +476,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetUsageForOrigin(
if (status != Status::kOk)
return status;
- std::string prefix = CreateRegistrationKeyPrefix(origin);
+ std::string prefix = CreateRegistrationKeyPrefix(key);
// Read all registrations.
{
@@ -548,7 +557,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetAllRegistrations(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
mojom::ServiceWorkerRegistrationDataPtr* registration,
std::vector<mojom::ServiceWorkerResourceRecordPtr>* resources) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -561,8 +570,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration(
if (status != Status::kOk)
return status;
- status = ReadRegistrationData(registration_id, url::Origin::Create(origin),
- registration);
+ status = ReadRegistrationData(registration_id, key, registration);
if (status != Status::kOk)
return status;
@@ -577,11 +585,11 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration(
return Status::kOk;
}
-ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationOrigin(
+ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationStorageKey(
int64_t registration_id,
- GURL* origin) {
+ StorageKey* key) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(origin);
+ DCHECK(key);
Status status = LazyOpen(true);
if (IsNewOrNonexistentDatabase(status))
@@ -592,21 +600,21 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationOrigin(
std::string value;
status = LevelDBStatusToServiceWorkerDBStatus(
db_->Get(leveldb::ReadOptions(),
- CreateRegistrationIdToOriginKey(registration_id), &value));
+ CreateRegistrationIdToStorageKey(registration_id), &value));
if (status != Status::kOk) {
HandleReadResult(FROM_HERE,
status == Status::kErrorNotFound ? Status::kOk : status);
return status;
}
- GURL parsed(value);
- if (!parsed.is_valid()) {
+ StorageKey parsed = StorageKey::Deserialize(value);
+ if (parsed.opaque()) {
status = Status::kErrorCorrupted;
HandleReadResult(FROM_HERE, status);
return status;
}
- *origin = parsed;
+ *key = std::move(parsed);
HandleReadResult(FROM_HERE, Status::kOk);
return Status::kOk;
}
@@ -627,7 +635,8 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch);
BumpNextVersionIdIfNeeded(registration.version_id, &batch);
- PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch);
+ PutUniqueOriginToBatch(
+ StorageKey(url::Origin::Create(registration.scope.GetOrigin())), &batch);
DCHECK_EQ(AccumulateResourceSizeInBytes(resources),
registration.resources_total_size_bytes)
@@ -635,8 +644,11 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
<< "sizes of the resources.";
WriteRegistrationDataInBatch(registration, &batch);
- batch.Put(CreateRegistrationIdToOriginKey(registration.registration_id),
- registration.scope.GetOrigin().spec());
+ // TODO(crbug.com/1199077): Update when RegistrationData uses StorageKey
+ StorageKey key(url::Origin::Create(registration.scope.GetOrigin()));
+
+ batch.Put(CreateRegistrationIdToStorageKey(registration.registration_id),
+ key.Serialize());
// Used for avoiding multiple writes for the same resource id or url.
std::set<int64_t> pushed_resources;
@@ -663,9 +675,9 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
// Retrieve a previous version to sweep purgeable resources.
mojom::ServiceWorkerRegistrationDataPtr old_registration;
- status = ReadRegistrationData(registration.registration_id,
- url::Origin::Create(registration.scope),
- &old_registration);
+ status = ReadRegistrationData(
+ registration.registration_id,
+ StorageKey(url::Origin::Create(registration.scope)), &old_registration);
if (status != Status::kOk && status != Status::kErrorNotFound)
return status;
if (status == Status::kOk) {
@@ -696,19 +708,18 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateVersionToActive(
int64_t registration_id,
- const GURL& origin) {
+ const StorageKey& key) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Status status = LazyOpen(false);
if (IsNewOrNonexistentDatabase(status))
return Status::kErrorNotFound;
if (status != Status::kOk)
return status;
- if (!origin.is_valid())
+ if (key.opaque())
return Status::kErrorFailed;
mojom::ServiceWorkerRegistrationDataPtr registration;
- status = ReadRegistrationData(registration_id, url::Origin::Create(origin),
- &registration);
+ status = ReadRegistrationData(registration_id, key, &registration);
if (status != Status::kOk)
return status;
@@ -721,7 +732,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateVersionToActive(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateLastCheckTime(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
const base::Time& time) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Status status = LazyOpen(false);
@@ -729,12 +740,11 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateLastCheckTime(
return Status::kErrorNotFound;
if (status != Status::kOk)
return status;
- if (!origin.is_valid())
+ if (key.opaque())
return Status::kErrorFailed;
mojom::ServiceWorkerRegistrationDataPtr registration;
- status = ReadRegistrationData(registration_id, url::Origin::Create(origin),
- &registration);
+ status = ReadRegistrationData(registration_id, key, &registration);
if (status != Status::kOk)
return status;
@@ -747,7 +757,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateLastCheckTime(
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::UpdateNavigationPreloadEnabled(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
bool enable) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Status status = LazyOpen(false);
@@ -755,12 +765,11 @@ ServiceWorkerDatabase::UpdateNavigationPreloadEnabled(int64_t registration_id,
return Status::kErrorNotFound;
if (status != Status::kOk)
return status;
- if (!origin.is_valid())
+ if (key.opaque())
return Status::kErrorFailed;
mojom::ServiceWorkerRegistrationDataPtr registration;
- status = ReadRegistrationData(registration_id, url::Origin::Create(origin),
- &registration);
+ status = ReadRegistrationData(registration_id, key, &registration);
if (status != Status::kOk)
return status;
@@ -773,7 +782,7 @@ ServiceWorkerDatabase::UpdateNavigationPreloadEnabled(int64_t registration_id,
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::UpdateNavigationPreloadHeader(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
const std::string& value) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Status status = LazyOpen(false);
@@ -781,12 +790,11 @@ ServiceWorkerDatabase::UpdateNavigationPreloadHeader(int64_t registration_id,
return Status::kErrorNotFound;
if (status != Status::kOk)
return status;
- if (!origin.is_valid())
+ if (key.opaque())
return Status::kErrorFailed;
mojom::ServiceWorkerRegistrationDataPtr registration;
- status = ReadRegistrationData(registration_id, url::Origin::Create(origin),
- &registration);
+ status = ReadRegistrationData(registration_id, key, &registration);
if (status != Status::kOk)
return status;
@@ -799,7 +807,7 @@ ServiceWorkerDatabase::UpdateNavigationPreloadHeader(int64_t registration_id,
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
DeletedVersion* deleted_version) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(deleted_version);
@@ -809,29 +817,27 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration(
return Status::kOk;
if (status != Status::kOk)
return status;
- if (!origin.is_valid())
+ if (key.opaque())
return Status::kErrorFailed;
leveldb::WriteBatch batch;
- // Remove |origin| from unique origins if a registration specified by
- // |registration_id| is the only one for |origin|.
+ // Remove |key| from unique origins if a registration specified by
+ // |registration_id| is the only one for |key|.
// TODO(nhiroki): Check the uniqueness by more efficient way.
std::vector<mojom::ServiceWorkerRegistrationDataPtr> registrations;
- status = GetRegistrationsForOrigin(url::Origin::Create(origin),
- &registrations, nullptr);
+ status = GetRegistrationsForStorageKey(key, &registrations, nullptr);
if (status != Status::kOk)
return status;
if (registrations.size() == 1 &&
registrations[0]->registration_id == registration_id) {
- batch.Delete(CreateUniqueOriginKey(origin));
+ batch.Delete(CreateUniqueOriginKey(key));
}
// Delete a registration specified by |registration_id|.
- batch.Delete(
- CreateRegistrationKey(registration_id, url::Origin::Create(origin)));
- batch.Delete(CreateRegistrationIdToOriginKey(registration_id));
+ batch.Delete(CreateRegistrationKey(registration_id, key));
+ batch.Delete(CreateRegistrationIdToStorageKey(registration_id));
// Delete resource records and user data associated with the registration.
for (const auto& registration : registrations) {
@@ -985,7 +991,7 @@ ServiceWorkerDatabase::ReadUserKeysAndDataByKeyPrefix(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteUserData(
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
const std::vector<mojom::ServiceWorkerUserDataPtr>& user_data) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
@@ -999,7 +1005,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteUserData(
// There should be the registration specified by |registration_id|.
mojom::ServiceWorkerRegistrationDataPtr registration;
- status = ReadRegistrationData(registration_id, origin, &registration);
+ status = ReadRegistrationData(registration_id, key, &registration);
if (status != Status::kOk)
return status;
@@ -1346,8 +1352,9 @@ ServiceWorkerDatabase::PurgeUncommittedResourceIds(
return WriteBatch(&batch);
}
-ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigins(
- const std::set<GURL>& origins,
+ServiceWorkerDatabase::Status
+ServiceWorkerDatabase::DeleteAllDataForStorageKeys(
+ const std::set<StorageKey>& keys,
std::vector<int64_t>* newly_purgeable_resources) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Status status = LazyOpen(false);
@@ -1357,24 +1364,22 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigins(
return status;
leveldb::WriteBatch batch;
- for (const GURL& origin : origins) {
- if (!origin.is_valid())
+ for (const StorageKey& key : keys) {
+ if (key.opaque())
return Status::kErrorFailed;
// Delete from the unique origin list.
- batch.Delete(CreateUniqueOriginKey(origin));
+ batch.Delete(CreateUniqueOriginKey(key));
std::vector<mojom::ServiceWorkerRegistrationDataPtr> registrations;
- status = GetRegistrationsForOrigin(url::Origin::Create(origin),
- &registrations, nullptr);
+ status = GetRegistrationsForStorageKey(key, &registrations, nullptr);
if (status != Status::kOk)
return status;
// Delete registrations, resource records and user data.
for (const auto& data : registrations) {
- batch.Delete(CreateRegistrationKey(data->registration_id,
- url::Origin::Create(origin)));
- batch.Delete(CreateRegistrationIdToOriginKey(data->registration_id));
+ batch.Delete(CreateRegistrationKey(data->registration_id, key));
+ batch.Delete(CreateRegistrationIdToStorageKey(data->registration_id));
status = DeleteResourceRecords(data->version_id,
newly_purgeable_resources, &batch);
@@ -1507,15 +1512,16 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadNextAvailableId(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationData(
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
mojom::ServiceWorkerRegistrationDataPtr* registration) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(registration);
- const std::string key = CreateRegistrationKey(registration_id, origin);
+ const std::string registration_key =
+ CreateRegistrationKey(registration_id, key);
std::string value;
Status status = LevelDBStatusToServiceWorkerDBStatus(
- db_->Get(leveldb::ReadOptions(), key, &value));
+ db_->Get(leveldb::ReadOptions(), registration_key, &value));
if (status != Status::kOk) {
HandleReadResult(FROM_HERE,
status == Status::kErrorNotFound ? Status::kOk : status);
@@ -1624,11 +1630,19 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ParseRegistrationData(
}
if (data.has_cross_origin_embedder_policy_value()) {
- (*out)->cross_origin_embedder_policy.value =
- data.cross_origin_embedder_policy_value() ==
- ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST
- ? network::mojom::CrossOriginEmbedderPolicyValue::kNone
- : network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
+ switch (data.cross_origin_embedder_policy_value()) {
+ case ServiceWorkerRegistrationData::REQUIRE_CORP:
+ (*out)->cross_origin_embedder_policy.value =
+ network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
+ break;
+ case ServiceWorkerRegistrationData::CREDENTIALLESS:
+ (*out)->cross_origin_embedder_policy.value =
+ network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless;
+ break;
+ default:
+ (*out)->cross_origin_embedder_policy.value =
+ network::mojom::CrossOriginEmbedderPolicyValue::kNone;
+ }
}
if (data.has_cross_origin_embedder_policy_reporting_endpoint()) {
@@ -1637,11 +1651,19 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ParseRegistrationData(
}
if (data.has_cross_origin_embedder_policy_report_only_value()) {
- (*out)->cross_origin_embedder_policy.report_only_value =
- data.cross_origin_embedder_policy_report_only_value() ==
- ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST
- ? network::mojom::CrossOriginEmbedderPolicyValue::kNone
- : network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
+ switch (data.cross_origin_embedder_policy_report_only_value()) {
+ case ServiceWorkerRegistrationData::REQUIRE_CORP:
+ (*out)->cross_origin_embedder_policy.report_only_value =
+ network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
+ break;
+ case ServiceWorkerRegistrationData::CREDENTIALLESS:
+ (*out)->cross_origin_embedder_policy.report_only_value =
+ network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless;
+ break;
+ default:
+ (*out)->cross_origin_embedder_policy.report_only_value =
+ network::mojom::CrossOriginEmbedderPolicyValue::kNone;
+ }
}
if (data.has_cross_origin_embedder_policy_report_only_reporting_endpoint()) {
@@ -1706,20 +1728,36 @@ void ServiceWorkerDatabase::WriteRegistrationDataInBatch(
ServiceWorkerRegistrationData_ServiceWorkerUpdateViaCacheType>(
registration.update_via_cache));
- data.set_cross_origin_embedder_policy_value(
- registration.cross_origin_embedder_policy.value ==
- network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp
- ? ServiceWorkerRegistrationData::REQUIRE_CORP
- : ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST);
+ switch (registration.cross_origin_embedder_policy.value) {
+ case network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp:
+ data.set_cross_origin_embedder_policy_value(
+ ServiceWorkerRegistrationData::REQUIRE_CORP);
+ break;
+ case network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless:
+ data.set_cross_origin_embedder_policy_value(
+ ServiceWorkerRegistrationData::CREDENTIALLESS);
+ break;
+ default:
+ data.set_cross_origin_embedder_policy_value(
+ ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST);
+ }
if (registration.cross_origin_embedder_policy.reporting_endpoint) {
data.set_cross_origin_embedder_policy_reporting_endpoint(
registration.cross_origin_embedder_policy.reporting_endpoint.value());
}
- data.set_cross_origin_embedder_policy_report_only_value(
- registration.cross_origin_embedder_policy.report_only_value ==
- network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp
- ? ServiceWorkerRegistrationData::REQUIRE_CORP
- : ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST);
+ switch (registration.cross_origin_embedder_policy.report_only_value) {
+ case network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp:
+ data.set_cross_origin_embedder_policy_report_only_value(
+ ServiceWorkerRegistrationData::REQUIRE_CORP);
+ break;
+ case network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless:
+ data.set_cross_origin_embedder_policy_report_only_value(
+ ServiceWorkerRegistrationData::CREDENTIALLESS);
+ break;
+ default:
+ data.set_cross_origin_embedder_policy_report_only_value(
+ ServiceWorkerRegistrationData::NONE_OR_NOT_EXIST);
+ }
if (registration.cross_origin_embedder_policy
.report_only_reporting_endpoint) {
data.set_cross_origin_embedder_policy_report_only_reporting_endpoint(
@@ -1730,8 +1768,8 @@ void ServiceWorkerDatabase::WriteRegistrationDataInBatch(
std::string value;
bool success = data.SerializeToString(&value);
DCHECK(success);
- url::Origin origin = url::Origin::Create(registration.scope);
- batch->Put(CreateRegistrationKey(data.registration_id(), origin), value);
+ StorageKey key(url::Origin::Create(registration.scope));
+ batch->Put(CreateRegistrationKey(data.registration_id(), key), value);
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceRecords(
diff --git a/chromium/components/services/storage/service_worker/service_worker_database.h b/chromium/components/services/storage/service_worker/service_worker_database.h
index 2d0611fa291..bdf1c8f592a 100644
--- a/chromium/components/services/storage/service_worker/service_worker_database.h
+++ b/chromium/components/services/storage/service_worker/service_worker_database.h
@@ -17,12 +17,13 @@
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
+#include "components/services/storage/public/cpp/storage_key.h"
#include "components/services/storage/public/mojom/service_worker_database.mojom.h"
#include "components/services/storage/public/mojom/service_worker_storage_control.mojom.h"
#include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/service_worker/navigation_preload_state.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration_options.mojom.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
@@ -83,21 +84,21 @@ class ServiceWorkerDatabase {
int64_t* next_avail_version_id,
int64_t* next_avail_resource_id);
- // Reads origins that have one or more than one registration from the
+ // Reads keys that have one or more registration from the
// database. Returns OK if they are successfully read or not found.
// Otherwise, returns an error.
- Status GetOriginsWithRegistrations(std::set<url::Origin>* origins);
+ Status GetStorageKeysWithRegistrations(std::set<StorageKey>* key);
- // Reads registrations for |origin| from the database. Returns OK if they are
+ // Reads registrations for |key| from the database. Returns OK if they are
// successfully read or not found. Otherwise, returns an error.
- Status GetRegistrationsForOrigin(
- const url::Origin& origin,
+ Status GetRegistrationsForStorageKey(
+ const StorageKey& key,
std::vector<mojom::ServiceWorkerRegistrationDataPtr>* registrations,
std::vector<std::vector<mojom::ServiceWorkerResourceRecordPtr>>*
opt_resources_list);
- // Reads the total resource size stored in the database for |origin|.
- Status GetUsageForOrigin(const url::Origin& origin, int64_t& out_usage);
+ // Reads the total resource size stored in the database for |key|.
+ Status GetUsageForStorageKey(const StorageKey& key, int64_t& out_usage);
// Reads all registrations from the database. Returns OK if successfully read
// or not found. Otherwise, returns an error.
@@ -114,14 +115,14 @@ class ServiceWorkerDatabase {
// Otherwise, returns an error.
Status ReadRegistration(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
mojom::ServiceWorkerRegistrationDataPtr* registration,
std::vector<mojom::ServiceWorkerResourceRecordPtr>* resources);
- // Looks up the origin for the registration with |registration_id|. Returns OK
+ // Looks up the key for the registration with |registration_id|. Returns OK
// if a registration was found and read successfully. Otherwise, returns an
// error.
- Status ReadRegistrationOrigin(int64_t registration_id, GURL* origin);
+ Status ReadRegistrationStorageKey(int64_t registration_id, StorageKey* key);
// Writes |registration| and |resources| into the database and does following
// things:
@@ -138,21 +139,21 @@ class ServiceWorkerDatabase {
// Updates a registration for |registration_id| to an active state. Returns OK
// if it's successfully updated. Otherwise, returns an error.
- Status UpdateVersionToActive(int64_t registration_id, const GURL& origin);
+ Status UpdateVersionToActive(int64_t registration_id, const StorageKey& key);
// Updates last check time of a registration for |registration_id| by |time|.
// Returns OK if it's successfully updated. Otherwise, returns an error.
Status UpdateLastCheckTime(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
const base::Time& time);
// Updates the navigation preload state for the specified registration.
// Returns OK if it's successfully updated. Otherwise, returns an error.
Status UpdateNavigationPreloadEnabled(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
bool enable);
Status UpdateNavigationPreloadHeader(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
const std::string& value);
// Deletes a registration for |registration_id| and moves resource records
@@ -162,7 +163,7 @@ class ServiceWorkerDatabase {
// Returns OK if it's successfully deleted or not found in the database.
// Otherwise, returns an error.
Status DeleteRegistration(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
DeletedVersion* deleted_version);
// Reads user data for |registration_id| and |user_data_names| from the
@@ -192,7 +193,7 @@ class ServiceWorkerDatabase {
// registration specified by |registration_id| does not exist in the database.
Status WriteUserData(
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
const std::vector<mojom::ServiceWorkerUserDataPtr>& user_data);
// Deletes user data for |registration_id| and |user_data_names| from the
@@ -260,12 +261,12 @@ class ServiceWorkerDatabase {
// returns an error.
Status PurgeUncommittedResourceIds(const std::vector<int64_t>& ids);
- // Deletes all data for |origins|, namely, unique origin, registrations and
+ // Deletes all data for |keys|, namely, unique origin, registrations and
// resource records. Resources are moved to the purgeable list. Returns OK if
// they are successfully deleted or not found in the database. Otherwise,
// returns an error.
- Status DeleteAllDataForOrigins(
- const std::set<GURL>& origins,
+ Status DeleteAllDataForStorageKeys(
+ const std::set<StorageKey>& keys,
std::vector<int64_t>* newly_purgeable_resources);
// Completely deletes the contents of the database.
@@ -293,7 +294,7 @@ class ServiceWorkerDatabase {
// if successfully reads. Otherwise, returns an error.
Status ReadRegistrationData(
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
mojom::ServiceWorkerRegistrationDataPtr* registration);
// Parses |serialized| as a RegistrationData object and pushes it into |out|.
diff --git a/chromium/components/services/storage/service_worker/service_worker_database.proto b/chromium/components/services/storage/service_worker/service_worker_database.proto
index 550c4bf54ac..940b0efb60c 100644
--- a/chromium/components/services/storage/service_worker/service_worker_database.proto
+++ b/chromium/components/services/storage/service_worker/service_worker_database.proto
@@ -35,6 +35,7 @@ message ServiceWorkerRegistrationData {
enum CrossOriginEmbedderPolicyValue {
NONE_OR_NOT_EXIST = 0;
REQUIRE_CORP = 1;
+ CREDENTIALLESS = 2;
}
required int64 registration_id = 1;
diff --git a/chromium/components/services/storage/service_worker/service_worker_database_unittest.cc b/chromium/components/services/storage/service_worker/service_worker_database_unittest.cc
index 16707c8f02b..49d1c1a5355 100644
--- a/chromium/components/services/storage/service_worker/service_worker_database_unittest.cc
+++ b/chromium/components/services/storage/service_worker/service_worker_database_unittest.cc
@@ -9,9 +9,10 @@
#include <string>
+#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/stl_util.h"
+#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "components/services/storage/service_worker/service_worker_database.pb.h"
@@ -104,6 +105,12 @@ network::CrossOriginEmbedderPolicy CrossOriginEmbedderPolicyRequireCorp() {
return out;
}
+network::CrossOriginEmbedderPolicy CrossOriginEmbedderPolicyCredentialless() {
+ network::CrossOriginEmbedderPolicy out;
+ out.value = network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless;
+ return out;
+}
+
std::vector<mojom::ServiceWorkerUserDataPtr> CreateUserData(
int64_t registration_id,
const std::vector<std::pair<std::string, std::string>>& key_value_pairs) {
@@ -166,6 +173,7 @@ TEST(ServiceWorkerDatabaseTest, DatabaseVersion_ValidSchemaVersion) {
resources.push_back(CreateResource(1, URL(origin, "/resource"), 10));
ServiceWorkerDatabase::DeletedVersion deleted_version;
RegistrationData data;
+ data.scope = origin;
data.resources_total_size_bytes = 10;
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteRegistration(data, resources, &deleted_version));
@@ -189,6 +197,7 @@ TEST(ServiceWorkerDatabaseTest, DatabaseVersion_ObsoleteSchemaVersion) {
resources.push_back(CreateResource(1, URL(origin, "/resource"), 10));
ServiceWorkerDatabase::DeletedVersion deleted_version;
RegistrationData data;
+ data.scope = origin;
data.resources_total_size_bytes = 10;
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteRegistration(data, resources, &deleted_version));
@@ -227,6 +236,7 @@ TEST(ServiceWorkerDatabaseTest, DatabaseVersion_CorruptedSchemaVersion) {
resources.push_back(CreateResource(1, URL(origin, "/resource"), 10));
ServiceWorkerDatabase::DeletedVersion deleted_version;
RegistrationData data;
+ data.scope = origin;
data.resources_total_size_bytes = 10;
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteRegistration(data, resources, &deleted_version));
@@ -348,21 +358,22 @@ TEST(ServiceWorkerDatabaseTest, GetNextAvailableIds) {
EXPECT_EQ(21, ids.res_id);
}
-TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
+TEST(ServiceWorkerDatabaseTest, GetStorageKeysWithRegistrations) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
- std::set<url::Origin> origins;
+ std::set<StorageKey> keys;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->GetOriginsWithRegistrations(&origins));
- EXPECT_TRUE(origins.empty());
+ database->GetStorageKeysWithRegistrations(&keys));
+ EXPECT_TRUE(keys.empty());
ServiceWorkerDatabase::DeletedVersion deleted_version;
- url::Origin origin1 = url::Origin::Create(GURL("https://example.com"));
+ GURL origin1 = GURL("https://example.com");
+ StorageKey key1(url::Origin::Create(origin1));
RegistrationData data1;
data1.registration_id = 123;
- data1.scope = URL(origin1.GetURL(), "/foo");
- data1.script = URL(origin1.GetURL(), "/script1.js");
+ data1.scope = URL(origin1, "/foo");
+ data1.script = URL(origin1, "/script1.js");
data1.version_id = 456;
data1.resources_total_size_bytes = 100;
std::vector<ResourceRecordPtr> resources1;
@@ -370,11 +381,12 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteRegistration(data1, resources1, &deleted_version));
- url::Origin origin2 = url::Origin::Create(GURL("https://www.example.com"));
+ GURL origin2 = GURL("https://www.example.com");
+ StorageKey key2(url::Origin::Create(origin2));
RegistrationData data2;
data2.registration_id = 234;
- data2.scope = URL(origin2.GetURL(), "/bar");
- data2.script = URL(origin2.GetURL(), "/script2.js");
+ data2.scope = URL(origin2, "/bar");
+ data2.script = URL(origin2, "/script2.js");
data2.version_id = 567;
data2.resources_total_size_bytes = 200;
std::vector<ResourceRecordPtr> resources2;
@@ -382,11 +394,12 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteRegistration(data2, resources2, &deleted_version));
- url::Origin origin3 = url::Origin::Create(GURL("https://example.org"));
+ GURL origin3 = GURL("https://example.org");
+ StorageKey key3(url::Origin::Create(origin3));
RegistrationData data3;
data3.registration_id = 345;
- data3.scope = URL(origin3.GetURL(), "/hoge");
- data3.script = URL(origin3.GetURL(), "/script3.js");
+ data3.scope = URL(origin3, "/hoge");
+ data3.script = URL(origin3, "/script3.js");
data3.version_id = 678;
data3.resources_total_size_bytes = 300;
std::vector<ResourceRecordPtr> resources3;
@@ -394,11 +407,11 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteRegistration(data3, resources3, &deleted_version));
- // |origin3| has two registrations.
+ // |key3| has two registrations.
RegistrationData data4;
data4.registration_id = 456;
- data4.scope = URL(origin3.GetURL(), "/fuga");
- data4.script = URL(origin3.GetURL(), "/script4.js");
+ data4.scope = URL(origin3, "/fuga");
+ data4.script = URL(origin3, "/script4.js");
data4.version_id = 789;
data4.resources_total_size_bytes = 400;
std::vector<ResourceRecordPtr> resources4;
@@ -406,55 +419,59 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteRegistration(data4, resources4, &deleted_version));
- origins.clear();
+ keys.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->GetOriginsWithRegistrations(&origins));
- EXPECT_EQ(3U, origins.size());
- EXPECT_TRUE(base::Contains(origins, origin1));
- EXPECT_TRUE(base::Contains(origins, origin2));
- EXPECT_TRUE(base::Contains(origins, origin3));
+ database->GetStorageKeysWithRegistrations(&keys));
+ EXPECT_EQ(3U, keys.size());
+ EXPECT_TRUE(base::Contains(keys, key1));
+ EXPECT_TRUE(base::Contains(keys, key2));
+ EXPECT_TRUE(base::Contains(keys, key3));
- // |origin3| has another registration, so should not remove it from the
+ // |key3| has another registration, so should not remove it from the
// unique origin list.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(data4.registration_id,
- origin3.GetURL(), &deleted_version));
+ database->DeleteRegistration(data4.registration_id, key3,
+ &deleted_version));
EXPECT_EQ(data4.registration_id, deleted_version.registration_id);
- origins.clear();
+ keys.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->GetOriginsWithRegistrations(&origins));
- EXPECT_EQ(3U, origins.size());
- EXPECT_TRUE(base::Contains(origins, origin1));
- EXPECT_TRUE(base::Contains(origins, origin2));
- EXPECT_TRUE(base::Contains(origins, origin3));
+ database->GetStorageKeysWithRegistrations(&keys));
+ EXPECT_EQ(3U, keys.size());
+ EXPECT_TRUE(base::Contains(keys, key1));
+ EXPECT_TRUE(base::Contains(keys, key2));
+ EXPECT_TRUE(base::Contains(keys, key3));
- // |origin3| should be removed from the unique origin list.
+ // |key3| should be removed from the unique origin list.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(data3.registration_id,
- origin3.GetURL(), &deleted_version));
+ database->DeleteRegistration(data3.registration_id, key3,
+ &deleted_version));
EXPECT_EQ(data3.registration_id, deleted_version.registration_id);
- origins.clear();
+ keys.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->GetOriginsWithRegistrations(&origins));
- EXPECT_EQ(2U, origins.size());
- EXPECT_TRUE(base::Contains(origins, origin1));
- EXPECT_TRUE(base::Contains(origins, origin2));
+ database->GetStorageKeysWithRegistrations(&keys));
+ EXPECT_EQ(2U, keys.size());
+ EXPECT_TRUE(base::Contains(keys, key1));
+ EXPECT_TRUE(base::Contains(keys, key2));
}
-TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
+TEST(ServiceWorkerDatabaseTest, GetRegistrationsForStorageKey) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
GURL origin1("https://example.com");
GURL origin2("https://www.example.com");
GURL origin3("https://example.org");
+ StorageKey key1(url::Origin::Create(origin1));
+ StorageKey key2(url::Origin::Create(origin2));
+ StorageKey key3(url::Origin::Create(origin3));
+
std::vector<mojom::ServiceWorkerRegistrationDataPtr> registrations;
std::vector<std::vector<ResourceRecordPtr>> resources_list;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->GetRegistrationsForOrigin(
- url::Origin::Create(origin1), &registrations, &resources_list));
+ database->GetRegistrationsForStorageKey(key1, &registrations,
+ &resources_list));
EXPECT_TRUE(registrations.empty());
EXPECT_TRUE(resources_list.empty());
@@ -476,8 +493,8 @@ TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
registrations.clear();
resources_list.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->GetRegistrationsForOrigin(
- url::Origin::Create(origin1), &registrations, &resources_list));
+ database->GetRegistrationsForStorageKey(key1, &registrations,
+ &resources_list));
EXPECT_EQ(1U, registrations.size());
VerifyRegistrationData(data1, *registrations[0]);
EXPECT_EQ(1U, resources_list.size());
@@ -499,8 +516,8 @@ TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
registrations.clear();
resources_list.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->GetRegistrationsForOrigin(
- url::Origin::Create(origin2), &registrations, &resources_list));
+ database->GetRegistrationsForStorageKey(key2, &registrations,
+ &resources_list));
EXPECT_EQ(1U, registrations.size());
VerifyRegistrationData(data2, *registrations[0]);
EXPECT_EQ(1U, resources_list.size());
@@ -519,7 +536,7 @@ TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteRegistration(data3, resources3, &deleted_version));
- // |origin3| has two registrations.
+ // |key3| has two registrations.
RegistrationData data4;
data4.registration_id = 400;
data4.scope = URL(origin3, "/fuga");
@@ -527,7 +544,8 @@ TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
data4.version_id = 4000;
data4.resources_total_size_bytes = 400;
data4.script_response_time = base::Time::FromJsTime(4200);
- data4.cross_origin_embedder_policy = CrossOriginEmbedderPolicyRequireCorp();
+ data4.cross_origin_embedder_policy =
+ CrossOriginEmbedderPolicyCredentialless();
std::vector<ResourceRecordPtr> resources4;
resources4.push_back(CreateResource(4, data4.script, 400));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
@@ -536,8 +554,8 @@ TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
registrations.clear();
resources_list.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->GetRegistrationsForOrigin(
- url::Origin::Create(origin3), &registrations, &resources_list));
+ database->GetRegistrationsForStorageKey(key3, &registrations,
+ &resources_list));
EXPECT_EQ(2U, registrations.size());
VerifyRegistrationData(data3, *registrations[0]);
VerifyRegistrationData(data4, *registrations[1]);
@@ -545,12 +563,12 @@ TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
VerifyResourceRecords(resources3, resources_list[0]);
VerifyResourceRecords(resources4, resources_list[1]);
- // The third parameter |opt_resources_list| to GetRegistrationsForOrigin()
+ // The third parameter |opt_resources_list| to GetRegistrationsForStorageKey()
// is optional. So, nullptr should be acceptable.
registrations.clear();
- EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->GetRegistrationsForOrigin(url::Origin::Create(origin1),
- &registrations, nullptr));
+ EXPECT_EQ(
+ ServiceWorkerDatabase::Status::kOk,
+ database->GetRegistrationsForStorageKey(key1, &registrations, nullptr));
EXPECT_EQ(1U, registrations.size());
VerifyRegistrationData(data1, *registrations[0]);
}
@@ -599,6 +617,8 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
data3.script = URL(origin3, "/script3.js");
data3.version_id = 3000;
data3.resources_total_size_bytes = 300;
+ data3.cross_origin_embedder_policy =
+ CrossOriginEmbedderPolicyCredentialless();
std::vector<ResourceRecordPtr> resources3;
resources3.push_back(CreateResource(3, data3.script, 300));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
@@ -631,6 +651,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
GURL origin("https://example.com");
+ StorageKey key(url::Origin::Create(origin));
RegistrationData data;
data.registration_id = 100;
data.scope = URL(origin, "/foo");
@@ -670,15 +691,15 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
RegistrationDataPtr data_out;
std::vector<ResourceRecordPtr> resources_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data.registration_id, origin, &data_out,
+ database->ReadRegistration(data.registration_id, key, &data_out,
&resources_out));
VerifyRegistrationData(data, *data_out);
VerifyResourceRecords(resources, resources_out);
- GURL origin_out;
+ StorageKey key_out;
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistrationOrigin(data.registration_id, &origin_out));
- EXPECT_EQ(origin, origin_out);
+ database->ReadRegistrationStorageKey(data.registration_id, &key_out));
+ EXPECT_EQ(key, key_out);
// Make sure that the resource is removed from the uncommitted list.
uncommitted_ids_out.clear();
@@ -687,7 +708,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
EXPECT_TRUE(uncommitted_ids_out.empty());
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(data.registration_id, origin,
+ database->DeleteRegistration(data.registration_id, key,
&deleted_version));
EXPECT_EQ(data.version_id, deleted_version.version_id);
ASSERT_EQ(resources.size(), deleted_version.newly_purgeable_resources.size());
@@ -698,12 +719,12 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
// Make sure that the registration and resource records are gone.
resources_out.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->ReadRegistration(data.registration_id, origin, &data_out,
+ database->ReadRegistration(data.registration_id, key, &data_out,
&resources_out));
EXPECT_TRUE(resources_out.empty());
EXPECT_EQ(
ServiceWorkerDatabase::Status::kErrorNotFound,
- database->ReadRegistrationOrigin(data.registration_id, &origin_out));
+ database->ReadRegistrationStorageKey(data.registration_id, &key_out));
// Resources should be purgeable because these are no longer referred.
std::vector<int64_t> purgeable_ids_out;
@@ -744,8 +765,9 @@ TEST(ServiceWorkerDatabaseTest, DeleteNonExistentRegistration) {
deleted_version.version_id = kArbitraryVersionId;
deleted_version.newly_purgeable_resources.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(kNonExistentRegistrationId, origin,
- &deleted_version));
+ database->DeleteRegistration(
+ kNonExistentRegistrationId,
+ StorageKey(url::Origin::Create(origin)), &deleted_version));
EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
deleted_version.version_id);
EXPECT_TRUE(deleted_version.newly_purgeable_resources.empty());
@@ -754,9 +776,10 @@ TEST(ServiceWorkerDatabaseTest, DeleteNonExistentRegistration) {
deleted_version.version_id = kArbitraryVersionId;
deleted_version.newly_purgeable_resources.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(kNonExistentRegistrationId,
- GURL("https://example.net"),
- &deleted_version));
+ database->DeleteRegistration(
+ kNonExistentRegistrationId,
+ StorageKey(url::Origin::Create(GURL("https://example.net"))),
+ &deleted_version));
EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
deleted_version.version_id);
EXPECT_TRUE(deleted_version.newly_purgeable_resources.empty());
@@ -766,6 +789,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
GURL origin("https://example.com");
+ StorageKey key(url::Origin::Create(origin));
RegistrationData data;
data.registration_id = 100;
data.scope = URL(origin, "/foo");
@@ -793,7 +817,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
RegistrationDataPtr data_out;
std::vector<ResourceRecordPtr> resources_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data.registration_id, origin, &data_out,
+ database->ReadRegistration(data.registration_id, key, &data_out,
&resources_out));
VerifyRegistrationData(data, *data_out);
VerifyResourceRecords(resources1, resources_out);
@@ -828,7 +852,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
// is moved to the purgeable list.
resources_out.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(updated_data->registration_id, origin,
+ database->ReadRegistration(updated_data->registration_id, key,
&data_out, &resources_out));
VerifyRegistrationData(*updated_data, *data_out);
VerifyResourceRecords(resources2, resources_out);
@@ -844,6 +868,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
GURL origin("https://example.com");
+ StorageKey key(url::Origin::Create(origin));
ServiceWorkerDatabase::DeletedVersion deleted_version;
@@ -879,27 +904,27 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
RegistrationDataPtr data_out;
std::vector<ResourceRecordPtr> resources_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data1.registration_id, origin, &data_out,
+ database->ReadRegistration(data1.registration_id, key, &data_out,
&resources_out));
VerifyRegistrationData(data1, *data_out);
VerifyResourceRecords(resources1, resources_out);
- GURL origin_out;
+ StorageKey key_out;
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistrationOrigin(data1.registration_id, &origin_out));
- EXPECT_EQ(origin, origin_out);
+ database->ReadRegistrationStorageKey(data1.registration_id, &key_out));
+ EXPECT_EQ(key, key_out);
// Make sure that registration2 is also stored.
resources_out.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data2.registration_id, origin, &data_out,
+ database->ReadRegistration(data2.registration_id, key, &data_out,
&resources_out));
VerifyRegistrationData(data2, *data_out);
VerifyResourceRecords(resources2, resources_out);
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistrationOrigin(data2.registration_id, &origin_out));
- EXPECT_EQ(origin, origin_out);
+ database->ReadRegistrationStorageKey(data2.registration_id, &key_out));
+ EXPECT_EQ(key, key_out);
std::vector<int64_t> purgeable_ids_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
@@ -908,19 +933,19 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
// Delete registration1.
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(data1.registration_id, origin,
+ database->DeleteRegistration(data1.registration_id, key,
&deleted_version));
EXPECT_EQ(data1.registration_id, deleted_version.registration_id);
// Make sure that registration1 is gone.
resources_out.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->ReadRegistration(data1.registration_id, origin, &data_out,
+ database->ReadRegistration(data1.registration_id, key, &data_out,
&resources_out));
EXPECT_TRUE(resources_out.empty());
EXPECT_EQ(
ServiceWorkerDatabase::Status::kErrorNotFound,
- database->ReadRegistrationOrigin(data1.registration_id, &origin_out));
+ database->ReadRegistrationStorageKey(data1.registration_id, &key_out));
purgeable_ids_out.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
@@ -932,35 +957,36 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
// Make sure that registration2 is still alive.
resources_out.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data2.registration_id, origin, &data_out,
+ database->ReadRegistration(data2.registration_id, key, &data_out,
&resources_out));
VerifyRegistrationData(data2, *data_out);
VerifyResourceRecords(resources2, resources_out);
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistrationOrigin(data2.registration_id, &origin_out));
- EXPECT_EQ(origin, origin_out);
+ database->ReadRegistrationStorageKey(data2.registration_id, &key_out));
+ EXPECT_EQ(key, key_out);
}
TEST(ServiceWorkerDatabaseTest, Registration_UninitializedDatabase) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
const GURL origin("https://example.com");
+ StorageKey key(url::Origin::Create(origin));
// Should be failed because the database does not exist.
RegistrationDataPtr data_out;
std::vector<ResourceRecordPtr> resources_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->ReadRegistration(100, origin, &data_out, &resources_out));
+ database->ReadRegistration(100, key, &data_out, &resources_out));
EXPECT_TRUE(data_out.is_null());
EXPECT_TRUE(resources_out.empty());
- GURL origin_out;
+ StorageKey key_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->ReadRegistrationOrigin(100, &origin_out));
+ database->ReadRegistrationStorageKey(100, &key_out));
// Deleting non-existent registration should succeed.
ServiceWorkerDatabase::DeletedVersion deleted_version;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(100, origin, &deleted_version));
+ database->DeleteRegistration(100, key, &deleted_version));
EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
deleted_version.version_id);
EXPECT_TRUE(deleted_version.newly_purgeable_resources.empty());
@@ -972,15 +998,15 @@ TEST(ServiceWorkerDatabaseTest, Registration_UninitializedDatabase) {
ASSERT_EQ(ServiceWorkerDatabase::DATABASE_STATE_UNINITIALIZED,
database->state_);
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->ReadRegistration(100, origin, &data_out, &resources_out));
+ database->ReadRegistration(100, key, &data_out, &resources_out));
EXPECT_TRUE(data_out.is_null());
EXPECT_TRUE(resources_out.empty());
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->ReadRegistrationOrigin(100, &origin_out));
+ database->ReadRegistrationStorageKey(100, &key_out));
// Deleting non-existent registration should succeed.
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(100, origin, &deleted_version));
+ database->DeleteRegistration(100, key, &deleted_version));
EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
deleted_version.version_id);
EXPECT_TRUE(deleted_version.newly_purgeable_resources.empty());
@@ -1039,24 +1065,27 @@ TEST(ServiceWorkerDatabaseTest, Registration_ScriptType) {
RegistrationDataPtr data;
std::vector<ResourceRecordPtr> resources;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data1.registration_id, origin1, &data,
- &resources));
+ database->ReadRegistration(data1.registration_id,
+ StorageKey(url::Origin::Create(origin1)),
+ &data, &resources));
VerifyRegistrationData(data1, *data);
VerifyResourceRecords(resources1, resources);
EXPECT_EQ(2U, resources.size());
resources.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data2.registration_id, origin2, &data,
- &resources));
+ database->ReadRegistration(data2.registration_id,
+ StorageKey(url::Origin::Create(origin2)),
+ &data, &resources));
VerifyRegistrationData(data2, *data);
VerifyResourceRecords(resources2, resources);
EXPECT_EQ(2U, resources.size());
resources.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data3.registration_id, origin3, &data,
- &resources));
+ database->ReadRegistration(data3.registration_id,
+ StorageKey(url::Origin::Create(origin3)),
+ &data, &resources));
VerifyRegistrationData(data3, *data);
VerifyResourceRecords(resources3, resources);
EXPECT_EQ(2U, resources.size());
@@ -1066,6 +1095,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_ScriptType) {
TEST(ServiceWorkerDatabaseTest, UserData_Basic) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
+ StorageKey key(kOrigin);
// Add a registration.
RegistrationData data;
@@ -1084,7 +1114,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_Basic) {
std::vector<std::string> user_data_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data.registration_id, kOrigin,
+ data.registration_id, key,
CreateUserData(data.registration_id, {{"key1", "data"}})));
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
@@ -1094,14 +1124,14 @@ TEST(ServiceWorkerDatabaseTest, UserData_Basic) {
// Writing user data not associated with the stored registration should be
// failed.
- EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->WriteUserData(
- 300, kOrigin,
- CreateUserData(data.registration_id, {{"key1", "data"}})));
+ EXPECT_EQ(
+ ServiceWorkerDatabase::Status::kErrorNotFound,
+ database->WriteUserData(
+ 300, key, CreateUserData(data.registration_id, {{"key1", "data"}})));
// Write empty user data for a different key.
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->WriteUserData(data.registration_id, kOrigin,
+ database->WriteUserData(data.registration_id, key,
CreateUserData(data.registration_id,
{{"key2", std::string()}})));
EXPECT_EQ(
@@ -1118,7 +1148,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_Basic) {
// Overwrite the existing user data.
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data.registration_id, kOrigin,
+ data.registration_id, key,
CreateUserData(data.registration_id, {{"key1", "overwrite"}})));
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
@@ -1142,7 +1172,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_Basic) {
// Write/overwrite multiple user data keys.
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data.registration_id, kOrigin,
+ data.registration_id, key,
CreateUserData(data.registration_id, {{"key2", "overwrite2"},
{"key3", "data3"},
{"key4", "data4"}})));
@@ -1186,6 +1216,7 @@ TEST(ServiceWorkerDatabaseTest,
UserData_ReadUserDataForAllRegistrationsByKeyPrefix) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
+ StorageKey key(kOrigin);
// Add registration 1.
RegistrationData data1;
@@ -1216,39 +1247,39 @@ TEST(ServiceWorkerDatabaseTest,
// Write user data associated with the registration1.
ASSERT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->WriteUserData(data1.registration_id, kOrigin,
+ database->WriteUserData(data1.registration_id, key,
CreateUserData(data1.registration_id,
{{"key_prefix:key1", "value1"}})));
ASSERT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->WriteUserData(data1.registration_id, kOrigin,
+ database->WriteUserData(data1.registration_id, key,
CreateUserData(data1.registration_id,
{{"key_prefix:key2", "value2"}})));
ASSERT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->WriteUserData(data1.registration_id, kOrigin,
+ database->WriteUserData(data1.registration_id, key,
CreateUserData(data1.registration_id,
{{"key_prefix:key3", "value3"}})));
// Write user data associated with the registration2.
ASSERT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->WriteUserData(data2.registration_id, kOrigin,
+ database->WriteUserData(data2.registration_id, key,
CreateUserData(data2.registration_id,
{{"key_prefix:key1", "value1"}})));
ASSERT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->WriteUserData(data2.registration_id, kOrigin,
+ database->WriteUserData(data2.registration_id, key,
CreateUserData(data2.registration_id,
{{"key_prefix:key2", "value2"}})));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data2.registration_id, kOrigin,
+ data2.registration_id, key,
CreateUserData(data2.registration_id,
{{"another_key_prefix:key1", "value1"}})));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data2.registration_id, kOrigin,
+ data2.registration_id, key,
CreateUserData(data2.registration_id,
{{"another_key_prefix:key2", "value2"}})));
@@ -1296,7 +1327,7 @@ TEST(ServiceWorkerDatabaseTest, ReadUserDataByKeyPrefix) {
// Write user data associated with the registration.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data.registration_id, kOrigin,
+ data.registration_id, StorageKey(kOrigin),
CreateUserData(data.registration_id,
{{"key_prefix:key1", "value_c1"},
{"key_prefix:key2", "value_c2"},
@@ -1342,7 +1373,7 @@ TEST(ServiceWorkerDatabaseTest, ReadUserKeysAndDataByKeyPrefix) {
// Write user data associated with the registration.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data.registration_id, kOrigin,
+ data.registration_id, StorageKey(kOrigin),
CreateUserData(data.registration_id,
{{"key_prefix:key1", "value_c1"},
{"key_prefix:key2", "value_c2"},
@@ -1375,6 +1406,7 @@ TEST(ServiceWorkerDatabaseTest, ReadUserKeysAndDataByKeyPrefix) {
TEST(ServiceWorkerDatabaseTest, UserData_DeleteUserDataByKeyPrefixes) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
+ StorageKey key(kOrigin);
// Add registration 1.
RegistrationData data1;
@@ -1405,7 +1437,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_DeleteUserDataByKeyPrefixes) {
// Write user data associated with registration 1.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data1.registration_id, kOrigin,
+ data1.registration_id, key,
CreateUserData(data1.registration_id,
{{"key_prefix:key1", "value_a1"},
{"key_prefix:key2", "value_a2"},
@@ -1415,7 +1447,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_DeleteUserDataByKeyPrefixes) {
// Write user data associated with registration 2.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data2.registration_id, kOrigin,
+ data2.registration_id, key,
CreateUserData(data2.registration_id,
{{"key_prefix:key1", "value_c1"},
{"key_prefix:key2", "value_c2"},
@@ -1483,6 +1515,7 @@ TEST(ServiceWorkerDatabaseTest,
UserData_DeleteUserDataForAllRegistrationsByKeyPrefix) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
+ StorageKey key(kOrigin);
// Add registration 1.
RegistrationData data1;
@@ -1513,7 +1546,7 @@ TEST(ServiceWorkerDatabaseTest,
// Write user data associated with registration 1.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data1.registration_id, kOrigin,
+ data1.registration_id, key,
CreateUserData(data1.registration_id,
{{"key_prefix:key1", "value_a1"},
{"key_prefix:key2", "value_a2"},
@@ -1523,7 +1556,7 @@ TEST(ServiceWorkerDatabaseTest,
// Write user data associated with registration 2.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data2.registration_id, kOrigin,
+ data2.registration_id, key,
CreateUserData(data2.registration_id,
{{"key_prefix:key1", "value_c1"},
{"key_prefix:key2", "value_c2"},
@@ -1570,6 +1603,7 @@ TEST(ServiceWorkerDatabaseTest,
TEST(ServiceWorkerDatabaseTest, UserData_DataIsolation) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
+ StorageKey key(kOrigin);
// Add registration 1.
RegistrationData data1;
@@ -1602,7 +1636,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_DataIsolation) {
std::vector<std::string> user_data_out;
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data1.registration_id, kOrigin,
+ data1.registration_id, key,
CreateUserData(data1.registration_id, {{"key", "value1"}})));
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
@@ -1617,7 +1651,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_DataIsolation) {
// the data associated with registration1.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data2.registration_id, kOrigin,
+ data2.registration_id, key,
CreateUserData(data2.registration_id, {{"key", "value2"}})));
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
@@ -1668,6 +1702,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_DataIsolation) {
TEST(ServiceWorkerDatabaseTest, UserData_DeleteRegistration) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
+ StorageKey key(kOrigin);
// Add registration 1.
RegistrationData data1;
@@ -1699,11 +1734,11 @@ TEST(ServiceWorkerDatabaseTest, UserData_DeleteRegistration) {
std::vector<std::string> user_data_out;
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data1.registration_id, kOrigin,
+ data1.registration_id, key,
CreateUserData(data1.registration_id, {{"key1", "value1"}})));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data1.registration_id, kOrigin,
+ data1.registration_id, key,
CreateUserData(data1.registration_id, {{"key2", "value2"}})));
ASSERT_EQ(
ServiceWorkerDatabase::Status::kOk,
@@ -1719,7 +1754,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_DeleteRegistration) {
// Write user data associated with the registration2.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data2.registration_id, kOrigin,
+ data2.registration_id, key,
CreateUserData(data2.registration_id, {{"key3", "value3"}})));
ASSERT_EQ(
ServiceWorkerDatabase::Status::kOk,
@@ -1730,8 +1765,8 @@ TEST(ServiceWorkerDatabaseTest, UserData_DeleteRegistration) {
// Delete all data associated with the registration1. This shouldn't delete
// the data associated with registration2.
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(data1.registration_id,
- kOrigin.GetURL(), &deleted_version));
+ database->DeleteRegistration(data1.registration_id, key,
+ &deleted_version));
EXPECT_EQ(
ServiceWorkerDatabase::Status::kErrorNotFound,
database->ReadUserData(data1.registration_id, {"key1"}, &user_data_out));
@@ -1748,6 +1783,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_DeleteRegistration) {
TEST(ServiceWorkerDatabaseTest, UserData_UninitializedDatabase) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
+ StorageKey key(kOrigin);
// Should be failed because the database does not exist.
std::vector<std::string> user_data_out;
@@ -1756,7 +1792,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_UninitializedDatabase) {
// Should be failed because the associated registration does not exist.
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->WriteUserData(100, kOrigin,
+ database->WriteUserData(100, key,
CreateUserData(100, {{"key", "value"}})));
// Deleting non-existent entry should succeed.
@@ -1772,7 +1808,7 @@ TEST(ServiceWorkerDatabaseTest, UserData_UninitializedDatabase) {
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
database->ReadUserData(100, {"key"}, &user_data_out));
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->WriteUserData(100, kOrigin,
+ database->WriteUserData(100, key,
CreateUserData(100, {{"key", "value"}})));
// Deleting non-existent entry should succeed.
@@ -1783,12 +1819,13 @@ TEST(ServiceWorkerDatabaseTest, UserData_UninitializedDatabase) {
TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
GURL origin("https://example.com");
+ StorageKey key(url::Origin::Create(origin));
ServiceWorkerDatabase::DeletedVersion deleted_version;
// Should be false because a registration does not exist.
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->UpdateVersionToActive(0, origin));
+ database->UpdateVersionToActive(0, key));
// Add a registration.
RegistrationData data;
@@ -1807,19 +1844,19 @@ TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) {
RegistrationDataPtr data_out;
std::vector<ResourceRecordPtr> resources_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data.registration_id, origin, &data_out,
+ database->ReadRegistration(data.registration_id, key, &data_out,
&resources_out));
VerifyRegistrationData(data, *data_out);
EXPECT_EQ(1u, resources_out.size());
// Activate the registration.
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->UpdateVersionToActive(data.registration_id, origin));
+ database->UpdateVersionToActive(data.registration_id, key));
// Make sure that the registration is activated.
resources_out.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data.registration_id, origin, &data_out,
+ database->ReadRegistration(data.registration_id, key, &data_out,
&resources_out));
mojom::ServiceWorkerRegistrationDataPtr expected_data = data.Clone();
expected_data->is_active = true;
@@ -1828,23 +1865,24 @@ TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) {
// Delete the registration.
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(data.registration_id, origin,
+ database->DeleteRegistration(data.registration_id, key,
&deleted_version));
EXPECT_EQ(data.registration_id, deleted_version.registration_id);
// Should be false because the registration is gone.
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->UpdateVersionToActive(data.registration_id, origin));
+ database->UpdateVersionToActive(data.registration_id, key));
}
TEST(ServiceWorkerDatabaseTest, UpdateLastCheckTime) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
GURL origin("https://example.com");
+ StorageKey key(url::Origin::Create(origin));
ServiceWorkerDatabase::DeletedVersion deleted_version;
// Should be false because a registration does not exist.
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->UpdateLastCheckTime(0, origin, base::Time::Now()));
+ database->UpdateLastCheckTime(0, key, base::Time::Now()));
// Add a registration.
RegistrationData data;
@@ -1863,21 +1901,21 @@ TEST(ServiceWorkerDatabaseTest, UpdateLastCheckTime) {
RegistrationDataPtr data_out;
std::vector<ResourceRecordPtr> resources_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data.registration_id, origin, &data_out,
+ database->ReadRegistration(data.registration_id, key, &data_out,
&resources_out));
VerifyRegistrationData(data, *data_out);
EXPECT_EQ(1u, resources_out.size());
// Update the last check time.
base::Time updated_time = base::Time::Now();
- EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->UpdateLastCheckTime(data.registration_id, origin,
- updated_time));
+ EXPECT_EQ(
+ ServiceWorkerDatabase::Status::kOk,
+ database->UpdateLastCheckTime(data.registration_id, key, updated_time));
// Make sure that the registration is updated.
resources_out.clear();
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data.registration_id, origin, &data_out,
+ database->ReadRegistration(data.registration_id, key, &data_out,
&resources_out));
mojom::ServiceWorkerRegistrationDataPtr expected_data = data.Clone();
expected_data->last_update_check = updated_time;
@@ -1886,13 +1924,13 @@ TEST(ServiceWorkerDatabaseTest, UpdateLastCheckTime) {
// Delete the registration.
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteRegistration(data.registration_id, origin,
+ database->DeleteRegistration(data.registration_id, key,
&deleted_version));
EXPECT_EQ(data.registration_id, deleted_version.registration_id);
// Should be false because the registration is gone.
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound,
- database->UpdateLastCheckTime(data.registration_id, origin,
+ database->UpdateLastCheckTime(data.registration_id, key,
base::Time::Now()));
}
@@ -1944,17 +1982,19 @@ TEST(ServiceWorkerDatabaseTest, UncommittedAndPurgeableResourceIds) {
EXPECT_EQ(expected, ids_out);
}
-TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
+TEST(ServiceWorkerDatabaseTest, DeleteAllDataForStorageKey) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
ServiceWorkerDatabase::DeletedVersion deleted_version;
- // Data associated with |origin1| will be removed.
+ // Data associated with |key1| will be removed.
GURL url1("https://example.com");
GURL url2("https://example.org");
url::Origin origin1 = url::Origin::Create(url1);
url::Origin origin2 = url::Origin::Create(url2);
+ StorageKey key1(origin1);
+ StorageKey key2(origin2);
- // |origin1| has two registrations (registration1 and registration2).
+ // |key1| has two registrations (registration1 and registration2).
RegistrationData data1;
data1.registration_id = 10;
data1.scope = URL(url1, "/foo");
@@ -1969,11 +2009,11 @@ TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
database->WriteRegistration(data1, resources1, &deleted_version));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data1.registration_id, origin1,
+ data1.registration_id, key1,
CreateUserData(data1.registration_id, {{"key1", "value1"}})));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data1.registration_id, origin1,
+ data1.registration_id, key1,
CreateUserData(data1.registration_id, {{"key2", "value2"}})));
RegistrationData data2;
@@ -1990,14 +2030,14 @@ TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
database->WriteRegistration(data2, resources2, &deleted_version));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data2.registration_id, origin1,
+ data2.registration_id, key1,
CreateUserData(data2.registration_id, {{"key3", "value3"}})));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data2.registration_id, origin1,
+ data2.registration_id, key1,
CreateUserData(data2.registration_id, {{"key4", "value4"}})));
- // |origin2| has one registration (registration3).
+ // |key2| has one registration (registration3).
RegistrationData data3;
data3.registration_id = 12;
data3.scope = URL(url2, "/hoge");
@@ -2012,52 +2052,52 @@ TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
database->WriteRegistration(data3, resources3, &deleted_version));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data3.registration_id, origin2,
+ data3.registration_id, key2,
CreateUserData(data3.registration_id, {{"key5", "value5"}})));
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteUserData(
- data3.registration_id, origin2,
+ data3.registration_id, key2,
CreateUserData(data3.registration_id, {{"key6", "value6"}})));
- std::set<GURL> origins_to_delete;
+ std::set<StorageKey> keys_to_delete;
std::vector<int64_t> newly_purgeable_resources;
- origins_to_delete.insert(url1);
+ keys_to_delete.insert(key1);
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->DeleteAllDataForOrigins(origins_to_delete,
- &newly_purgeable_resources));
+ database->DeleteAllDataForStorageKeys(keys_to_delete,
+ &newly_purgeable_resources));
- // |origin1| should be removed from the unique origin list.
- std::set<url::Origin> unique_origins;
+ // |key1| should be removed from the unique origin list.
+ std::set<StorageKey> unique_keys;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->GetOriginsWithRegistrations(&unique_origins));
- EXPECT_EQ(1u, unique_origins.size());
- EXPECT_TRUE(base::Contains(unique_origins, origin2));
+ database->GetStorageKeysWithRegistrations(&unique_keys));
+ EXPECT_EQ(1u, unique_keys.size());
+ EXPECT_TRUE(base::Contains(unique_keys, key2));
- // The registrations for |origin1| should be removed.
+ // The registrations for |key1| should be removed.
std::vector<mojom::ServiceWorkerRegistrationDataPtr> registrations;
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->GetRegistrationsForOrigin(origin1, &registrations, nullptr));
+ database->GetRegistrationsForStorageKey(key1, &registrations, nullptr));
EXPECT_TRUE(registrations.empty());
- GURL origin_out;
+ StorageKey key_out;
EXPECT_EQ(
ServiceWorkerDatabase::Status::kErrorNotFound,
- database->ReadRegistrationOrigin(data1.registration_id, &origin_out));
+ database->ReadRegistrationStorageKey(data1.registration_id, &key_out));
- // The registration for |origin2| should not be removed.
+ // The registration for |key2| should not be removed.
RegistrationDataPtr data_out;
std::vector<ResourceRecordPtr> resources_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistration(data3.registration_id, url2, &data_out,
+ database->ReadRegistration(data3.registration_id, key2, &data_out,
&resources_out));
VerifyRegistrationData(data3, *data_out);
VerifyResourceRecords(resources3, resources_out);
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
- database->ReadRegistrationOrigin(data3.registration_id, &origin_out));
- EXPECT_EQ(url2, origin_out);
+ database->ReadRegistrationStorageKey(data3.registration_id, &key_out));
+ EXPECT_EQ(key2, key_out);
- // The resources associated with |origin1| should be purgeable.
+ // The resources associated with |key1| should be purgeable.
std::vector<int64_t> purgeable_ids_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
database->GetPurgeableResourceIds(&purgeable_ids_out));
@@ -2067,7 +2107,7 @@ TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
EXPECT_TRUE(base::Contains(purgeable_ids_out, 3));
EXPECT_TRUE(base::Contains(purgeable_ids_out, 4));
- // The user data associated with |origin1| should be removed.
+ // The user data associated with |key1| should be removed.
std::vector<std::string> user_data_out;
EXPECT_EQ(
ServiceWorkerDatabase::Status::kErrorNotFound,
@@ -2082,7 +2122,7 @@ TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
ServiceWorkerDatabase::Status::kErrorNotFound,
database->ReadUserData(data2.registration_id, {"key4"}, &user_data_out));
- // The user data associated with |origin2| should not be removed.
+ // The user data associated with |key2| should not be removed.
EXPECT_EQ(
ServiceWorkerDatabase::Status::kOk,
database->ReadUserData(data3.registration_id, {"key5"}, &user_data_out));
@@ -2133,19 +2173,21 @@ TEST(ServiceWorkerDatabaseTest, Corruption_NoMainResource) {
RegistrationDataPtr data_out;
std::vector<ResourceRecordPtr> resources_out;
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorCorrupted,
- database->ReadRegistration(data.registration_id, origin, &data_out,
- &resources_out));
+ database->ReadRegistration(data.registration_id,
+ StorageKey(url::Origin::Create(origin)),
+ &data_out, &resources_out));
EXPECT_TRUE(resources_out.empty());
}
-// Tests that GetRegistrationsForOrigin() detects corruption without crashing.
-// It must delete the database after freeing the iterator it uses to read all
-// registrations. Regression test for https://crbug.com/909024.
-TEST(ServiceWorkerDatabaseTest, Corruption_GetRegistrationsForOrigin) {
+// Tests that GetRegistrationsForStorageKey() detects corruption without
+// crashing. It must delete the database after freeing the iterator it uses to
+// read all registrations. Regression test for https://crbug.com/909024.
+TEST(ServiceWorkerDatabaseTest, Corruption_GetRegistrationsForStorageKey) {
std::unique_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
ServiceWorkerDatabase::DeletedVersion deleted_version;
std::vector<ResourceRecordPtr> resources;
GURL origin("https://example.com");
+ StorageKey key(url::Origin::Create(origin));
// Write a normal registration.
RegistrationData data1;
@@ -2172,14 +2214,14 @@ TEST(ServiceWorkerDatabaseTest, Corruption_GetRegistrationsForOrigin) {
ASSERT_EQ(ServiceWorkerDatabase::Status::kOk,
database->WriteRegistration(data2, resources, &deleted_version));
- // Call GetRegistrationsForOrigin(). It should detect corruption, and not
+ // Call GetRegistrationsForStorageKey(). It should detect corruption, and not
// crash.
base::HistogramTester histogram_tester;
std::vector<mojom::ServiceWorkerRegistrationDataPtr> registrations;
std::vector<std::vector<ResourceRecordPtr>> resources_list;
EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorCorrupted,
- database->GetRegistrationsForOrigin(
- url::Origin::Create(origin), &registrations, &resources_list));
+ database->GetRegistrationsForStorageKey(key, &registrations,
+ &resources_list));
EXPECT_TRUE(registrations.empty());
EXPECT_TRUE(resources_list.empty());
@@ -2266,10 +2308,10 @@ TEST(ServiceWorkerDatabaseTest, CrossOriginEmbedderPolicyStoreRestore) {
// Restore.
std::vector<mojom::ServiceWorkerRegistrationDataPtr> registrations;
std::vector<std::vector<ResourceRecordPtr>> resources_list;
- EXPECT_EQ(
- ServiceWorkerDatabase::Status::kOk,
- database->GetRegistrationsForOrigin(url::Origin::Create(origin),
- &registrations, &resources_list));
+ EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
+ database->GetRegistrationsForStorageKey(
+ StorageKey(url::Origin::Create(origin)), &registrations,
+ &resources_list));
// The data must not have been altered.
VerifyRegistrationData(data, *registrations[0]);
@@ -2281,6 +2323,9 @@ TEST(ServiceWorkerDatabaseTest, CrossOriginEmbedderPolicyStoreRestore) {
store_and_restore(policy);
policy.value = network::mojom::CrossOriginEmbedderPolicyValue::kNone;
store_and_restore(policy);
+ policy.value =
+ network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless;
+ store_and_restore(policy);
}
{
@@ -2297,6 +2342,9 @@ TEST(ServiceWorkerDatabaseTest, CrossOriginEmbedderPolicyStoreRestore) {
policy.report_only_value =
network::mojom::CrossOriginEmbedderPolicyValue::kNone;
store_and_restore(policy);
+ policy.report_only_value =
+ network::mojom::CrossOriginEmbedderPolicyValue::kCredentialless;
+ store_and_restore(policy);
}
{
@@ -2336,4 +2384,52 @@ TEST(ServiceWorkerDatabaseTest, NoCrossOriginEmbedderPolicyValue) {
registration->cross_origin_embedder_policy.value);
}
+// As part of crbug.com/1199077 ServiceWorkerDataBase was refactored to use
+// StorageKey instead of url::Origin/GURL. The refactor is/should be a no-op but
+// this test exists to confirms that a DB created with the Origin/GURL impl can
+// still be correctly read by the StorageKey impl.
+TEST(ServiceWorkerDatabaseTest, StorageKeyImplCanReadPreviousOriginImplDB) {
+ base::FilePath root_path;
+ base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path);
+ base::FilePath database_dir = root_path.AppendASCII(
+ "components/test/data/service_worker/created_by_origin_impl/Database/");
+
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+ ASSERT_TRUE(base::CopyDirectory(database_dir, temp_dir.GetPath(),
+ /*recursive=*/true));
+
+ base::FilePath temp_database_dir = temp_dir.GetPath();
+ temp_database_dir = temp_database_dir.AppendASCII("Database");
+
+ std::unique_ptr<ServiceWorkerDatabase> database(
+ CreateDatabase(temp_database_dir));
+
+ int64_t next_registration_id;
+ int64_t next_version_id;
+ int64_t next_resource_id;
+ // Make sure to read in the IDs first, otherwise the
+ // GetRegistrationsForStorageKey will return as corrupted.
+ EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
+ database->GetNextAvailableIds(&next_registration_id,
+ &next_version_id, &next_resource_id));
+ EXPECT_EQ(next_registration_id, 1);
+ EXPECT_EQ(next_version_id, 1);
+ EXPECT_EQ(next_resource_id, 1);
+
+ // https://googlechrome.github.io/samples/service-worker/basic/ provided the
+ // service worker for this test.
+ StorageKey key(url::Origin::Create(GURL("https://googlechrome.github.io/")));
+
+ std::vector<mojom::ServiceWorkerRegistrationDataPtr> registrations;
+ std::vector<std::vector<ResourceRecordPtr>> resources_list;
+ EXPECT_EQ(ServiceWorkerDatabase::Status::kOk,
+ database->GetRegistrationsForStorageKey(key, &registrations,
+ &resources_list));
+
+ EXPECT_FALSE(registrations.empty());
+ EXPECT_FALSE(resources_list.empty());
+}
+
} // namespace storage
diff --git a/chromium/components/services/storage/service_worker/service_worker_disk_cache.cc b/chromium/components/services/storage/service_worker/service_worker_disk_cache.cc
index cbe90893f0e..c8491a8692d 100644
--- a/chromium/components/services/storage/service_worker/service_worker_disk_cache.cc
+++ b/chromium/components/services/storage/service_worker/service_worker_disk_cache.cc
@@ -11,10 +11,10 @@
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/check.h"
+#include "base/containers/contains.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/cache_type.h"
#include "net/base/completion_once_callback.h"
diff --git a/chromium/components/services/storage/service_worker/service_worker_resource_ops.cc b/chromium/components/services/storage/service_worker/service_worker_resource_ops.cc
index a0922e0b547..426bc1da60e 100644
--- a/chromium/components/services/storage/service_worker/service_worker_resource_ops.cc
+++ b/chromium/components/services/storage/service_worker/service_worker_resource_ops.cc
@@ -615,10 +615,10 @@ void ServiceWorkerResourceReaderImpl::CompleteReadResponseHead(int status) {
#endif
DCHECK(read_response_head_callback_);
- base::Optional<mojo_base::BigBuffer> metadata =
+ absl::optional<mojo_base::BigBuffer> metadata =
metadata_buffer_
- ? base::Optional<mojo_base::BigBuffer>(metadata_buffer_->TakeBuffer())
- : base::nullopt;
+ ? absl::optional<mojo_base::BigBuffer>(metadata_buffer_->TakeBuffer())
+ : absl::nullopt;
metadata_buffer_ = nullptr;
diff --git a/chromium/components/services/storage/service_worker/service_worker_storage.cc b/chromium/components/services/storage/service_worker/service_worker_storage.cc
index ce3b147c0bb..50a3c31b22a 100644
--- a/chromium/components/services/storage/service_worker/service_worker_storage.cc
+++ b/chromium/components/services/storage/service_worker/service_worker_storage.cc
@@ -6,16 +6,17 @@
#include <stddef.h>
+#include <algorithm>
#include <memory>
#include <utility>
#include "base/callback_helpers.h"
+#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/task_runner_util.h"
@@ -65,10 +66,10 @@ ServiceWorkerStorage::InitialData::~InitialData() = default;
ServiceWorkerStorage::DidDeleteRegistrationParams::DidDeleteRegistrationParams(
int64_t registration_id,
- GURL origin,
+ const StorageKey& key,
DeleteRegistrationCallback callback)
: registration_id(registration_id),
- origin(origin),
+ key(key),
callback(std::move(callback)) {}
ServiceWorkerStorage::DidDeleteRegistrationParams::
@@ -88,31 +89,31 @@ std::unique_ptr<ServiceWorkerStorage> ServiceWorkerStorage::Create(
user_data_directory, std::move(database_task_runner)));
}
-void ServiceWorkerStorage::GetRegisteredOrigins(
- GetRegisteredOriginsCallback callback) {
+void ServiceWorkerStorage::GetRegisteredStorageKeys(
+ GetRegisteredStorageKeysCallback callback) {
switch (state_) {
case STORAGE_STATE_DISABLED:
- std::move(callback).Run(/*origins=*/std::vector<url::Origin>());
+ std::move(callback).Run(/*keys=*/std::vector<StorageKey>());
return;
case STORAGE_STATE_INITIALIZING:
// Fall-through.
case STORAGE_STATE_UNINITIALIZED:
- LazyInitialize(base::BindOnce(&ServiceWorkerStorage::GetRegisteredOrigins,
- weak_factory_.GetWeakPtr(),
- std::move(callback)));
+ LazyInitialize(
+ base::BindOnce(&ServiceWorkerStorage::GetRegisteredStorageKeys,
+ weak_factory_.GetWeakPtr(), std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
break;
}
- std::vector<url::Origin> origins;
- for (const auto& origin : registered_origins_)
- origins.push_back(origin);
- std::move(callback).Run(std::move(origins));
+ std::vector<StorageKey> keys(registered_keys_.begin(),
+ registered_keys_.end());
+ std::move(callback).Run(std::move(keys));
}
void ServiceWorkerStorage::FindRegistrationForClientUrl(
const GURL& client_url,
+ const StorageKey& key,
FindRegistrationDataCallback callback) {
DCHECK(!client_url.has_ref());
switch (state_) {
@@ -126,7 +127,7 @@ void ServiceWorkerStorage::FindRegistrationForClientUrl(
case STORAGE_STATE_UNINITIALIZED:
LazyInitialize(base::BindOnce(
&ServiceWorkerStorage::FindRegistrationForClientUrl,
- weak_factory_.GetWeakPtr(), client_url, std::move(callback)));
+ weak_factory_.GetWeakPtr(), client_url, key, std::move(callback)));
TRACE_EVENT_INSTANT1(
"ServiceWorker",
"ServiceWorkerStorage::FindRegistrationForClientUrl:LazyInitialize",
@@ -137,7 +138,7 @@ void ServiceWorkerStorage::FindRegistrationForClientUrl(
}
// Bypass database lookup when there is no stored registration.
- if (!base::Contains(registered_origins_, url::Origin::Create(client_url))) {
+ if (!base::Contains(registered_keys_, key)) {
std::move(callback).Run(
/*data=*/nullptr, /*resources=*/nullptr,
ServiceWorkerDatabase::Status::kErrorNotFound);
@@ -147,11 +148,12 @@ void ServiceWorkerStorage::FindRegistrationForClientUrl(
database_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&FindForClientUrlInDB, database_.get(),
base::ThreadTaskRunnerHandle::Get(), client_url,
- std::move(callback)));
+ key, std::move(callback)));
}
void ServiceWorkerStorage::FindRegistrationForScope(
const GURL& scope,
+ const StorageKey& key,
FindRegistrationDataCallback callback) {
switch (state_) {
case STORAGE_STATE_DISABLED:
@@ -165,14 +167,14 @@ void ServiceWorkerStorage::FindRegistrationForScope(
case STORAGE_STATE_UNINITIALIZED:
LazyInitialize(base::BindOnce(
&ServiceWorkerStorage::FindRegistrationForScope,
- weak_factory_.GetWeakPtr(), scope, std::move(callback)));
+ weak_factory_.GetWeakPtr(), scope, key, std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
break;
}
// Bypass database lookup when there is no stored registration.
- if (!base::Contains(registered_origins_, url::Origin::Create(scope))) {
+ if (!base::Contains(registered_keys_, key)) {
RunSoon(FROM_HERE,
base::BindOnce(std::move(callback),
/*data=*/nullptr, /*resources=*/nullptr,
@@ -182,13 +184,13 @@ void ServiceWorkerStorage::FindRegistrationForScope(
database_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&FindForScopeInDB, database_.get(),
- base::ThreadTaskRunnerHandle::Get(), scope,
+ base::ThreadTaskRunnerHandle::Get(), scope, key,
std::move(callback)));
}
void ServiceWorkerStorage::FindRegistrationForId(
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
FindRegistrationDataCallback callback) {
switch (state_) {
case STORAGE_STATE_DISABLED:
@@ -201,7 +203,7 @@ void ServiceWorkerStorage::FindRegistrationForId(
case STORAGE_STATE_UNINITIALIZED:
LazyInitialize(
base::BindOnce(&ServiceWorkerStorage::FindRegistrationForId,
- weak_factory_.GetWeakPtr(), registration_id, origin,
+ weak_factory_.GetWeakPtr(), registration_id, key,
std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
@@ -209,7 +211,7 @@ void ServiceWorkerStorage::FindRegistrationForId(
}
// Bypass database lookup when there is no stored registration.
- if (!base::Contains(registered_origins_, origin)) {
+ if (!base::Contains(registered_keys_, key)) {
std::move(callback).Run(
/*data=*/nullptr, /*resources=*/nullptr,
ServiceWorkerDatabase::Status::kErrorNotFound);
@@ -219,7 +221,7 @@ void ServiceWorkerStorage::FindRegistrationForId(
database_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&FindForIdInDB, database_.get(),
base::ThreadTaskRunnerHandle::Get(),
- registration_id, origin, std::move(callback)));
+ registration_id, key, std::move(callback)));
}
void ServiceWorkerStorage::FindRegistrationForIdOnly(
@@ -248,8 +250,8 @@ void ServiceWorkerStorage::FindRegistrationForIdOnly(
registration_id, std::move(callback)));
}
-void ServiceWorkerStorage::GetRegistrationsForOrigin(
- const url::Origin& origin,
+void ServiceWorkerStorage::GetRegistrationsForStorageKey(
+ const StorageKey& key,
GetRegistrationsDataCallback callback) {
switch (state_) {
case STORAGE_STATE_DISABLED:
@@ -262,9 +264,9 @@ void ServiceWorkerStorage::GetRegistrationsForOrigin(
case STORAGE_STATE_INITIALIZING:
// Fall-through.
case STORAGE_STATE_UNINITIALIZED:
- LazyInitialize(base::BindOnce(
- &ServiceWorkerStorage::GetRegistrationsForOrigin,
- weak_factory_.GetWeakPtr(), origin, std::move(callback)));
+ LazyInitialize(
+ base::BindOnce(&ServiceWorkerStorage::GetRegistrationsForStorageKey,
+ weak_factory_.GetWeakPtr(), key, std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
break;
@@ -277,17 +279,17 @@ void ServiceWorkerStorage::GetRegistrationsForOrigin(
base::PostTaskAndReplyWithResult(
database_task_runner_.get(), FROM_HERE,
- base::BindOnce(&ServiceWorkerDatabase::GetRegistrationsForOrigin,
- base::Unretained(database_.get()), origin,
- registrations_ptr, resource_lists_ptr),
- base::BindOnce(&ServiceWorkerStorage::DidGetRegistrationsForOrigin,
+ base::BindOnce(&ServiceWorkerDatabase::GetRegistrationsForStorageKey,
+ base::Unretained(database_.get()), key, registrations_ptr,
+ resource_lists_ptr),
+ base::BindOnce(&ServiceWorkerStorage::DidGetRegistrationsForStorageKey,
weak_factory_.GetWeakPtr(), std::move(callback),
std::move(registrations), std::move(resource_lists)));
}
-void ServiceWorkerStorage::GetUsageForOrigin(
- const url::Origin& origin,
- GetUsageForOriginCallback callback) {
+void ServiceWorkerStorage::GetUsageForStorageKey(
+ const StorageKey& key,
+ GetUsageForStorageKeyCallback callback) {
switch (state_) {
case STORAGE_STATE_DISABLED:
RunSoon(FROM_HERE,
@@ -298,9 +300,9 @@ void ServiceWorkerStorage::GetUsageForOrigin(
case STORAGE_STATE_INITIALIZING:
// Fall-through.
case STORAGE_STATE_UNINITIALIZED:
- LazyInitialize(base::BindOnce(&ServiceWorkerStorage::GetUsageForOrigin,
- weak_factory_.GetWeakPtr(), origin,
- std::move(callback)));
+ LazyInitialize(
+ base::BindOnce(&ServiceWorkerStorage::GetUsageForStorageKey,
+ weak_factory_.GetWeakPtr(), key, std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
break;
@@ -308,9 +310,9 @@ void ServiceWorkerStorage::GetUsageForOrigin(
database_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(&ServiceWorkerStorage::GetUsageForOriginInDB,
- database_.get(), base::ThreadTaskRunnerHandle::Get(),
- origin, std::move(callback)));
+ base::BindOnce(&ServiceWorkerStorage::GetUsageForStorageKeyInDB,
+ database_.get(), base::ThreadTaskRunnerHandle::Get(), key,
+ std::move(callback)));
}
void ServiceWorkerStorage::GetAllRegistrations(
@@ -387,7 +389,7 @@ void ServiceWorkerStorage::StoreRegistrationData(
void ServiceWorkerStorage::UpdateToActiveState(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
DatabaseStatusCallback callback) {
switch (state_) {
case STORAGE_STATE_DISABLED:
@@ -398,7 +400,7 @@ void ServiceWorkerStorage::UpdateToActiveState(
case STORAGE_STATE_UNINITIALIZED:
LazyInitialize(base::BindOnce(&ServiceWorkerStorage::UpdateToActiveState,
weak_factory_.GetWeakPtr(), registration_id,
- origin, std::move(callback)));
+ key, std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
break;
@@ -407,14 +409,13 @@ void ServiceWorkerStorage::UpdateToActiveState(
base::PostTaskAndReplyWithResult(
database_task_runner_.get(), FROM_HERE,
base::BindOnce(&ServiceWorkerDatabase::UpdateVersionToActive,
- base::Unretained(database_.get()), registration_id,
- origin),
+ base::Unretained(database_.get()), registration_id, key),
std::move(callback));
}
void ServiceWorkerStorage::UpdateLastUpdateCheckTime(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
base::Time last_update_check_time,
DatabaseStatusCallback callback) {
switch (state_) {
@@ -426,7 +427,7 @@ void ServiceWorkerStorage::UpdateLastUpdateCheckTime(
case STORAGE_STATE_UNINITIALIZED:
LazyInitialize(
base::BindOnce(&ServiceWorkerStorage::UpdateLastUpdateCheckTime,
- weak_factory_.GetWeakPtr(), registration_id, origin,
+ weak_factory_.GetWeakPtr(), registration_id, key,
last_update_check_time, std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
@@ -436,14 +437,14 @@ void ServiceWorkerStorage::UpdateLastUpdateCheckTime(
base::PostTaskAndReplyWithResult(
database_task_runner_.get(), FROM_HERE,
base::BindOnce(&ServiceWorkerDatabase::UpdateLastCheckTime,
- base::Unretained(database_.get()), registration_id, origin,
+ base::Unretained(database_.get()), registration_id, key,
last_update_check_time),
std::move(callback));
}
void ServiceWorkerStorage::UpdateNavigationPreloadEnabled(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
bool enable,
DatabaseStatusCallback callback) {
switch (state_) {
@@ -455,7 +456,7 @@ void ServiceWorkerStorage::UpdateNavigationPreloadEnabled(
case STORAGE_STATE_UNINITIALIZED:
LazyInitialize(
base::BindOnce(&ServiceWorkerStorage::UpdateNavigationPreloadEnabled,
- weak_factory_.GetWeakPtr(), registration_id, origin,
+ weak_factory_.GetWeakPtr(), registration_id, key,
enable, std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
@@ -465,14 +466,14 @@ void ServiceWorkerStorage::UpdateNavigationPreloadEnabled(
base::PostTaskAndReplyWithResult(
database_task_runner_.get(), FROM_HERE,
base::BindOnce(&ServiceWorkerDatabase::UpdateNavigationPreloadEnabled,
- base::Unretained(database_.get()), registration_id, origin,
+ base::Unretained(database_.get()), registration_id, key,
enable),
std::move(callback));
}
void ServiceWorkerStorage::UpdateNavigationPreloadHeader(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
const std::string& value,
DatabaseStatusCallback callback) {
switch (state_) {
@@ -484,7 +485,7 @@ void ServiceWorkerStorage::UpdateNavigationPreloadHeader(
case STORAGE_STATE_UNINITIALIZED:
LazyInitialize(
base::BindOnce(&ServiceWorkerStorage::UpdateNavigationPreloadHeader,
- weak_factory_.GetWeakPtr(), registration_id, origin,
+ weak_factory_.GetWeakPtr(), registration_id, key,
value, std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
@@ -494,20 +495,20 @@ void ServiceWorkerStorage::UpdateNavigationPreloadHeader(
base::PostTaskAndReplyWithResult(
database_task_runner_.get(), FROM_HERE,
base::BindOnce(&ServiceWorkerDatabase::UpdateNavigationPreloadHeader,
- base::Unretained(database_.get()), registration_id, origin,
+ base::Unretained(database_.get()), registration_id, key,
value),
std::move(callback));
}
void ServiceWorkerStorage::DeleteRegistration(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
DeleteRegistrationCallback callback) {
switch (state_) {
case STORAGE_STATE_DISABLED:
std::move(callback).Run(
ServiceWorkerDatabase::Status::kErrorDisabled,
- mojom::ServiceWorkerStorageOriginState::kKeep,
+ mojom::ServiceWorkerStorageStorageKeyState::kKeep,
/*deleted_version_id=*/blink::mojom::kInvalidServiceWorkerVersionId,
/*deleted_resources_size=*/0,
/*newly_purgeable_resources=*/std::vector<int64_t>());
@@ -517,7 +518,7 @@ void ServiceWorkerStorage::DeleteRegistration(
case STORAGE_STATE_UNINITIALIZED:
LazyInitialize(base::BindOnce(&ServiceWorkerStorage::DeleteRegistration,
weak_factory_.GetWeakPtr(), registration_id,
- origin, std::move(callback)));
+ key, std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
break;
@@ -527,13 +528,13 @@ void ServiceWorkerStorage::DeleteRegistration(
DeleteStaleResources();
auto params = std::make_unique<DidDeleteRegistrationParams>(
- registration_id, origin, std::move(callback));
+ registration_id, key, std::move(callback));
database_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&DeleteRegistrationFromDB, database_.get(),
- base::ThreadTaskRunnerHandle::Get(), registration_id, origin,
+ base::ThreadTaskRunnerHandle::Get(), registration_id, key,
base::BindOnce(&ServiceWorkerStorage::DidDeleteRegistration,
weak_factory_.GetWeakPtr(), std::move(params))));
}
@@ -701,7 +702,7 @@ void ServiceWorkerStorage::DoomUncommittedResources(
void ServiceWorkerStorage::StoreUserData(
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
std::vector<mojom::ServiceWorkerUserDataPtr> user_data,
DatabaseStatusCallback callback) {
switch (state_) {
@@ -715,7 +716,7 @@ void ServiceWorkerStorage::StoreUserData(
case STORAGE_STATE_UNINITIALIZED:
LazyInitialize(base::BindOnce(
&ServiceWorkerStorage::StoreUserData, weak_factory_.GetWeakPtr(),
- registration_id, origin, std::move(user_data), std::move(callback)));
+ registration_id, key, std::move(user_data), std::move(callback)));
return;
case STORAGE_STATE_INITIALIZED:
break;
@@ -741,7 +742,7 @@ void ServiceWorkerStorage::StoreUserData(
base::PostTaskAndReplyWithResult(
database_task_runner_.get(), FROM_HERE,
base::BindOnce(&ServiceWorkerDatabase::WriteUserData,
- base::Unretained(database_.get()), registration_id, origin,
+ base::Unretained(database_.get()), registration_id, key,
std::move(user_data)),
std::move(callback));
}
@@ -1196,11 +1197,11 @@ void ServiceWorkerStorage::ApplyPolicyUpdates(
}
for (const auto& update : policy_updates) {
- GURL url = update->origin.GetURL();
+ StorageKey key(update->origin);
if (!update->purge_on_shutdown)
- origins_to_purge_on_shutdown_.erase(url);
+ keys_to_purge_on_shutdown_.erase(key);
else
- origins_to_purge_on_shutdown_.insert(std::move(url));
+ keys_to_purge_on_shutdown_.insert(std::move(key));
}
std::move(callback).Run(ServiceWorkerDatabase::Status::kOk);
@@ -1302,10 +1303,10 @@ void ServiceWorkerStorage::DidReadInitialData(
next_registration_id_ = data->next_registration_id;
next_version_id_ = data->next_version_id;
next_resource_id_ = data->next_resource_id;
- registered_origins_.swap(data->origins);
+ registered_keys_.swap(data->keys);
state_ = STORAGE_STATE_INITIALIZED;
- base::UmaHistogramCounts1M("ServiceWorker.RegisteredOriginCount",
- registered_origins_.size());
+ base::UmaHistogramCounts1M("ServiceWorker.RegisteredStorageKeyCount",
+ registered_keys_.size());
} else {
DVLOG(2) << "Failed to initialize: "
<< ServiceWorkerDatabase::StatusToString(status);
@@ -1317,7 +1318,7 @@ void ServiceWorkerStorage::DidReadInitialData(
pending_tasks_.clear();
}
-void ServiceWorkerStorage::DidGetRegistrationsForOrigin(
+void ServiceWorkerStorage::DidGetRegistrationsForStorageKey(
GetRegistrationsDataCallback callback,
std::unique_ptr<RegistrationList> registration_data_list,
std::unique_ptr<std::vector<ResourceList>> resource_lists,
@@ -1336,7 +1337,7 @@ void ServiceWorkerStorage::DidGetAllRegistrations(
void ServiceWorkerStorage::DidStoreRegistrationData(
StoreRegistrationDataCallback callback,
uint64_t new_resources_total_size_bytes,
- const GURL& origin,
+ const StorageKey& key,
const ServiceWorkerDatabase::DeletedVersion& deleted_version,
ServiceWorkerDatabase::Status status) {
if (status != ServiceWorkerDatabase::Status::kOk) {
@@ -1345,7 +1346,7 @@ void ServiceWorkerStorage::DidStoreRegistrationData(
deleted_version.newly_purgeable_resources);
return;
}
- registered_origins_.insert(url::Origin::Create(origin));
+ registered_keys_.insert(key);
std::move(callback).Run(ServiceWorkerDatabase::Status::kOk,
deleted_version.version_id,
@@ -1355,22 +1356,22 @@ void ServiceWorkerStorage::DidStoreRegistrationData(
void ServiceWorkerStorage::DidDeleteRegistration(
std::unique_ptr<DidDeleteRegistrationParams> params,
- OriginState origin_state,
+ StorageKeyState storage_key_state,
const ServiceWorkerDatabase::DeletedVersion& deleted_version,
ServiceWorkerDatabase::Status status) {
if (status != ServiceWorkerDatabase::Status::kOk) {
std::move(params->callback)
- .Run(status, origin_state, deleted_version.version_id,
+ .Run(status, storage_key_state, deleted_version.version_id,
deleted_version.resources_total_size_bytes,
deleted_version.newly_purgeable_resources);
return;
}
- if (origin_state == OriginState::kDelete)
- registered_origins_.erase(url::Origin::Create(params->origin));
+ if (storage_key_state == StorageKeyState::kDelete)
+ registered_keys_.erase(params->key);
std::move(params->callback)
- .Run(ServiceWorkerDatabase::Status::kOk, origin_state,
+ .Run(ServiceWorkerDatabase::Status::kOk, storage_key_state,
deleted_version.version_id,
deleted_version.resources_total_size_bytes,
deleted_version.newly_purgeable_resources);
@@ -1519,8 +1520,8 @@ void ServiceWorkerStorage::DidCollectStaleResources(
void ServiceWorkerStorage::ClearSessionOnlyOrigins() {
database_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&DeleteAllDataForOriginsFromDB, database_.get(),
- origins_to_purge_on_shutdown_));
+ FROM_HERE, base::BindOnce(&DeleteAllDataForStorageKeysFromDB,
+ database_.get(), keys_to_purge_on_shutdown_));
}
void ServiceWorkerStorage::OnResourceReaderDisconnected(
@@ -1593,7 +1594,7 @@ void ServiceWorkerStorage::ReadInitialDataFromDB(
return;
}
- status = database->GetOriginsWithRegistrations(&data->origins);
+ status = database->GetStorageKeysWithRegistrations(&data->keys);
if (status != ServiceWorkerDatabase::Status::kOk) {
original_task_runner->PostTask(
FROM_HERE,
@@ -1609,16 +1610,16 @@ void ServiceWorkerStorage::DeleteRegistrationFromDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
DeleteRegistrationInDBCallback callback) {
DCHECK(database);
ServiceWorkerDatabase::DeletedVersion deleted_version;
ServiceWorkerDatabase::Status status =
- database->DeleteRegistration(registration_id, origin, &deleted_version);
+ database->DeleteRegistration(registration_id, key, &deleted_version);
if (status != ServiceWorkerDatabase::Status::kOk) {
original_task_runner->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), OriginState::kKeep,
+ FROM_HERE, base::BindOnce(std::move(callback), StorageKeyState::kKeep,
deleted_version, status));
return;
}
@@ -1626,19 +1627,19 @@ void ServiceWorkerStorage::DeleteRegistrationFromDB(
// TODO(nhiroki): Add convenient method to ServiceWorkerDatabase to check the
// unique origin list.
RegistrationList registrations;
- status = database->GetRegistrationsForOrigin(url::Origin::Create(origin),
- &registrations, nullptr);
+ status =
+ database->GetRegistrationsForStorageKey(key, &registrations, nullptr);
if (status != ServiceWorkerDatabase::Status::kOk) {
original_task_runner->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), OriginState::kKeep,
+ FROM_HERE, base::BindOnce(std::move(callback), StorageKeyState::kKeep,
deleted_version, status));
return;
}
- OriginState origin_state =
- registrations.empty() ? OriginState::kDelete : OriginState::kKeep;
+ StorageKeyState storage_key_state =
+ registrations.empty() ? StorageKeyState::kDelete : StorageKeyState::kKeep;
original_task_runner->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), origin_state,
+ FROM_HERE, base::BindOnce(std::move(callback), storage_key_state,
deleted_version, status));
}
@@ -1654,7 +1655,8 @@ void ServiceWorkerStorage::WriteRegistrationInDB(
database->WriteRegistration(*registration, resources, &deleted_version);
original_task_runner->PostTask(
FROM_HERE,
- base::BindOnce(std::move(callback), registration->script.GetOrigin(),
+ base::BindOnce(std::move(callback),
+ StorageKey(url::Origin::Create(registration->script)),
deleted_version, status));
}
@@ -1663,11 +1665,12 @@ void ServiceWorkerStorage::FindForClientUrlInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
const GURL& client_url,
+ const StorageKey& key,
FindInDBCallback callback) {
- GURL origin = client_url.GetOrigin();
RegistrationList registration_data_list;
- ServiceWorkerDatabase::Status status = database->GetRegistrationsForOrigin(
- url::Origin::Create(origin), &registration_data_list, nullptr);
+ ServiceWorkerDatabase::Status status =
+ database->GetRegistrationsForStorageKey(key, &registration_data_list,
+ nullptr);
if (status != ServiceWorkerDatabase::Status::kOk) {
original_task_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(callback),
@@ -1687,7 +1690,7 @@ void ServiceWorkerStorage::FindForClientUrlInDB(
if (matcher.MatchLongest(registration_data->scope))
match = registration_data->registration_id;
if (match != blink::mojom::kInvalidServiceWorkerRegistrationId)
- status = database->ReadRegistration(match, origin, &data, resources.get());
+ status = database->ReadRegistration(match, key, &data, resources.get());
original_task_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), std::move(data),
@@ -1699,11 +1702,12 @@ void ServiceWorkerStorage::FindForScopeInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
const GURL& scope,
+ const StorageKey& key,
FindInDBCallback callback) {
- GURL origin = scope.GetOrigin();
RegistrationList registration_data_list;
- ServiceWorkerDatabase::Status status = database->GetRegistrationsForOrigin(
- url::Origin::Create(origin), &registration_data_list, nullptr);
+ ServiceWorkerDatabase::Status status =
+ database->GetRegistrationsForStorageKey(key, &registration_data_list,
+ nullptr);
if (status != ServiceWorkerDatabase::Status::kOk) {
original_task_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(callback),
@@ -1719,8 +1723,8 @@ void ServiceWorkerStorage::FindForScopeInDB(
for (const auto& registration_data : registration_data_list) {
if (scope != registration_data->scope)
continue;
- status = database->ReadRegistration(registration_data->registration_id,
- origin, &data, resources.get());
+ status = database->ReadRegistration(registration_data->registration_id, key,
+ &data, resources.get());
break; // We're done looping.
}
@@ -1734,12 +1738,12 @@ void ServiceWorkerStorage::FindForIdInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
FindInDBCallback callback) {
mojom::ServiceWorkerRegistrationDataPtr data;
auto resources = std::make_unique<ResourceList>();
- ServiceWorkerDatabase::Status status = database->ReadRegistration(
- registration_id, origin.GetURL(), &data, resources.get());
+ ServiceWorkerDatabase::Status status =
+ database->ReadRegistration(registration_id, key, &data, resources.get());
original_task_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), std::move(data),
std::move(resources), status));
@@ -1751,9 +1755,9 @@ void ServiceWorkerStorage::FindForIdOnlyInDB(
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
int64_t registration_id,
FindInDBCallback callback) {
- GURL origin;
+ StorageKey key;
ServiceWorkerDatabase::Status status =
- database->ReadRegistrationOrigin(registration_id, &origin);
+ database->ReadRegistrationStorageKey(registration_id, &key);
if (status != ServiceWorkerDatabase::Status::kOk) {
original_task_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(callback),
@@ -1761,19 +1765,19 @@ void ServiceWorkerStorage::FindForIdOnlyInDB(
/*resources=*/nullptr, status));
return;
}
- FindForIdInDB(database, original_task_runner, registration_id,
- url::Origin::Create(origin), std::move(callback));
+ FindForIdInDB(database, original_task_runner, registration_id, key,
+ std::move(callback));
}
// static
-void ServiceWorkerStorage::GetUsageForOriginInDB(
+void ServiceWorkerStorage::GetUsageForStorageKeyInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
- url::Origin origin,
- GetUsageForOriginCallback callback) {
+ const StorageKey& key,
+ GetUsageForStorageKeyCallback callback) {
int64_t usage = 0;
ServiceWorkerDatabase::Status status =
- database->GetUsageForOrigin(origin, usage);
+ database->GetUsageForStorageKey(key, usage);
original_task_runner->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), status, usage));
}
@@ -1845,13 +1849,13 @@ void ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefixInDB(
base::BindOnce(std::move(callback), status, std::move(user_data)));
}
-void ServiceWorkerStorage::DeleteAllDataForOriginsFromDB(
+void ServiceWorkerStorage::DeleteAllDataForStorageKeysFromDB(
ServiceWorkerDatabase* database,
- const std::set<GURL>& origins) {
+ const std::set<StorageKey>& keys) {
DCHECK(database);
std::vector<int64_t> newly_purgeable_resources;
- database->DeleteAllDataForOrigins(origins, &newly_purgeable_resources);
+ database->DeleteAllDataForStorageKeys(keys, &newly_purgeable_resources);
}
void ServiceWorkerStorage::PerformStorageCleanupInDB(
diff --git a/chromium/components/services/storage/service_worker/service_worker_storage.h b/chromium/components/services/storage/service_worker/service_worker_storage.h
index 8cc0b709bd4..1e06c1bd34e 100644
--- a/chromium/components/services/storage/service_worker/service_worker_storage.h
+++ b/chromium/components/services/storage/service_worker/service_worker_storage.h
@@ -21,6 +21,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "components/services/storage/public/cpp/storage_key.h"
#include "components/services/storage/public/mojom/local_storage_control.mojom.h"
#include "components/services/storage/public/mojom/service_worker_storage_control.mojom.h"
#include "components/services/storage/public/mojom/storage_policy_update.mojom.h"
@@ -54,11 +55,11 @@ FORWARD_DECLARE_TEST(ServiceWorkerStorageTest, DisabledStorage);
// restarted.
class ServiceWorkerStorage {
public:
- using OriginState = mojom::ServiceWorkerStorageOriginState;
+ using StorageKeyState = mojom::ServiceWorkerStorageStorageKeyState;
using RegistrationList = std::vector<mojom::ServiceWorkerRegistrationDataPtr>;
using ResourceList = std::vector<mojom::ServiceWorkerResourceRecordPtr>;
- using GetRegisteredOriginsCallback =
- base::OnceCallback<void(const std::vector<url::Origin>& origins)>;
+ using GetRegisteredStorageKeysCallback =
+ base::OnceCallback<void(const std::vector<StorageKey>& keys)>;
using FindRegistrationDataCallback =
base::OnceCallback<void(mojom::ServiceWorkerRegistrationDataPtr data,
std::unique_ptr<ResourceList> resources,
@@ -67,7 +68,7 @@ class ServiceWorkerStorage {
ServiceWorkerDatabase::Status status,
std::unique_ptr<RegistrationList> registrations,
std::unique_ptr<std::vector<ResourceList>> resource_lists)>;
- using GetUsageForOriginCallback =
+ using GetUsageForStorageKeyCallback =
base::OnceCallback<void(ServiceWorkerDatabase::Status status,
int64_t usage)>;
using GetAllRegistrationsCallback =
@@ -80,7 +81,7 @@ class ServiceWorkerStorage {
const std::vector<int64_t>& newly_purgeable_resources)>;
using DeleteRegistrationCallback = base::OnceCallback<void(
ServiceWorkerDatabase::Status status,
- OriginState origin_state,
+ StorageKeyState storage_key_state,
int64_t deleted_version_id,
uint64_t deleted_resources_size,
const std::vector<int64_t>& newly_purgeable_resources)>;
@@ -104,31 +105,34 @@ class ServiceWorkerStorage {
const base::FilePath& user_data_directory,
scoped_refptr<base::SequencedTaskRunner> database_task_runner);
- // Returns all origins which have service worker registrations.
- void GetRegisteredOrigins(GetRegisteredOriginsCallback callback);
+ // Returns all StorageKeys which have service worker registrations.
+ void GetRegisteredStorageKeys(GetRegisteredStorageKeysCallback callback);
- // Reads stored registrations for |client_url| or |scope| or
- // |registration_id|. Returns ServiceWorkerDatabase::Status::kOk with
- // non-null RegistrationData and ResourceList if registration is found, or
- // returns ServiceWorkerDatabase::Status::kErrorNotFound if no matching
- // registration is found.
+ // Reads stored registrations for `client_url`, `scope`, or
+ // `registration_id` with the associated `key`. Returns
+ // ServiceWorkerDatabase::Status::kOk with non-null RegistrationData and
+ // ResourceList if registration is found, or returns
+ // ServiceWorkerDatabase::Status::kErrorNotFound if no matching registration
+ // is found.
void FindRegistrationForClientUrl(const GURL& client_url,
+ const StorageKey& key,
FindRegistrationDataCallback callback);
void FindRegistrationForScope(const GURL& scope,
+ const StorageKey& key,
FindRegistrationDataCallback callback);
void FindRegistrationForId(int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
FindRegistrationDataCallback callback);
void FindRegistrationForIdOnly(int64_t registration_id,
FindRegistrationDataCallback callback);
- // Returns all stored registrations for a given origin.
- void GetRegistrationsForOrigin(const url::Origin& origin,
- GetRegistrationsDataCallback callback);
+ // Returns all stored registrations for a given `key`.
+ void GetRegistrationsForStorageKey(const StorageKey& key,
+ GetRegistrationsDataCallback callback);
- // Reads the total resource size stored in the storage for a given origin.
- void GetUsageForOrigin(const url::Origin& origin,
- GetUsageForOriginCallback callback);
+ // Reads the total resource size stored in the storage for a given `key`.
+ void GetUsageForStorageKey(const StorageKey& key,
+ GetUsageForStorageKeyCallback callback);
// Returns all stored registrations.
void GetAllRegistrations(GetAllRegistrationsCallback callback);
@@ -141,31 +145,31 @@ class ServiceWorkerStorage {
// Updates the state of the registration's stored version to active.
void UpdateToActiveState(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
DatabaseStatusCallback callback);
// Updates the stored time to match the value of
// registration->last_update_check().
void UpdateLastUpdateCheckTime(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
base::Time last_update_check_time,
DatabaseStatusCallback callback);
// Updates the specified registration's navigation preload state in storage.
// The caller is responsible for mutating the live registration's state.
void UpdateNavigationPreloadEnabled(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
bool enable,
DatabaseStatusCallback callback);
void UpdateNavigationPreloadHeader(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
const std::string& value,
DatabaseStatusCallback callback);
// Deletes the registration specified by |registration_id|. This should be
// called only from ServiceWorkerRegistry.
void DeleteRegistration(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
DeleteRegistrationCallback callback);
// Removes traces of deleted data on disk.
@@ -215,7 +219,7 @@ class ServiceWorkerStorage {
// Stored data is deleted when the associated registraton is deleted.
void StoreUserData(int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
std::vector<mojom::ServiceWorkerUserDataPtr> user_data,
DatabaseStatusCallback callback);
// Responds OK if all are successfully deleted or not found in the database.
@@ -304,7 +308,7 @@ class ServiceWorkerStorage {
int64_t next_registration_id;
int64_t next_version_id;
int64_t next_resource_id;
- std::set<url::Origin> origins;
+ std::set<StorageKey> keys;
InitialData();
~InitialData();
@@ -313,11 +317,11 @@ class ServiceWorkerStorage {
// Because there are too many params for base::Bind to wrap a closure around.
struct DidDeleteRegistrationParams {
int64_t registration_id;
- GURL origin;
+ StorageKey key;
DeleteRegistrationCallback callback;
DidDeleteRegistrationParams(int64_t registration_id,
- GURL origin,
+ const StorageKey& key,
DeleteRegistrationCallback callback);
~DidDeleteRegistrationParams();
};
@@ -326,11 +330,11 @@ class ServiceWorkerStorage {
base::OnceCallback<void(std::unique_ptr<InitialData> data,
ServiceWorkerDatabase::Status status)>;
using WriteRegistrationCallback = base::OnceCallback<void(
- const GURL& origin,
+ const StorageKey& key,
const ServiceWorkerDatabase::DeletedVersion& deleted_version_data,
ServiceWorkerDatabase::Status status)>;
using DeleteRegistrationInDBCallback = base::OnceCallback<void(
- OriginState origin_state,
+ StorageKeyState storage_key_state,
const ServiceWorkerDatabase::DeletedVersion& deleted_version_data,
ServiceWorkerDatabase::Status status)>;
using FindInDBCallback =
@@ -351,7 +355,7 @@ class ServiceWorkerStorage {
void LazyInitialize(base::OnceClosure callback);
void DidReadInitialData(std::unique_ptr<InitialData> data,
ServiceWorkerDatabase::Status status);
- void DidGetRegistrationsForOrigin(
+ void DidGetRegistrationsForStorageKey(
GetRegistrationsDataCallback callback,
std::unique_ptr<RegistrationList> registrations,
std::unique_ptr<std::vector<ResourceList>> resource_lists,
@@ -363,12 +367,12 @@ class ServiceWorkerStorage {
void DidStoreRegistrationData(
StoreRegistrationDataCallback callback,
uint64_t new_resources_total_size_bytes,
- const GURL& origin,
+ const StorageKey& key,
const ServiceWorkerDatabase::DeletedVersion& deleted_version,
ServiceWorkerDatabase::Status status);
void DidDeleteRegistration(
std::unique_ptr<DidDeleteRegistrationParams> params,
- OriginState origin_state,
+ StorageKeyState storage_key_state,
const ServiceWorkerDatabase::DeletedVersion& deleted_version,
ServiceWorkerDatabase::Status status);
void DidDoomUncommittedResourceIds(const std::vector<int64_t>& resource_ids,
@@ -417,7 +421,7 @@ class ServiceWorkerStorage {
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
DeleteRegistrationInDBCallback callback);
static void WriteRegistrationInDB(
ServiceWorkerDatabase* database,
@@ -429,28 +433,30 @@ class ServiceWorkerStorage {
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
const GURL& client_url,
+ const StorageKey& key,
FindInDBCallback callback);
static void FindForScopeInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
const GURL& scope,
+ const StorageKey& key,
FindInDBCallback callback);
static void FindForIdInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
FindInDBCallback callback);
static void FindForIdOnlyInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
int64_t registration_id,
FindInDBCallback callback);
- static void GetUsageForOriginInDB(
+ static void GetUsageForStorageKeyInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
- url::Origin origin,
- GetUsageForOriginCallback callback);
+ const StorageKey& key,
+ GetUsageForStorageKeyCallback callback);
static void GetUserDataInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -479,8 +485,9 @@ class ServiceWorkerStorage {
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
const std::string& key_prefix,
GetUserDataForAllRegistrationsInDBCallback callback);
- static void DeleteAllDataForOriginsFromDB(ServiceWorkerDatabase* database,
- const std::set<GURL>& origins);
+ static void DeleteAllDataForStorageKeysFromDB(
+ ServiceWorkerDatabase* database,
+ const std::set<StorageKey>& keys);
static void PerformStorageCleanupInDB(ServiceWorkerDatabase* database);
static void GetPurgeableResourceIdsFromDB(
ServiceWorkerDatabase* database,
@@ -499,10 +506,10 @@ class ServiceWorkerStorage {
// Posted when we finish deleting the cache directory.
void DidDeleteDiskCache(DatabaseStatusCallback callback, bool result);
- // Origins having registations.
- std::set<url::Origin> registered_origins_;
- // The set of origins whose storage should be cleaned on shutdown.
- std::set<GURL> origins_to_purge_on_shutdown_;
+ // StorageKeys having registations.
+ std::set<StorageKey> registered_keys_;
+ // The set of StorageKeys whose storage should be cleaned on shutdown.
+ std::set<StorageKey> keys_to_purge_on_shutdown_;
// Pending database tasks waiting for initialization.
std::vector<base::OnceClosure> pending_tasks_;
diff --git a/chromium/components/services/storage/service_worker/service_worker_storage_control_impl.cc b/chromium/components/services/storage/service_worker/service_worker_storage_control_impl.cc
index f76a7a778c7..9bb3a9e0884 100644
--- a/chromium/components/services/storage/service_worker/service_worker_storage_control_impl.cc
+++ b/chromium/components/services/storage/service_worker/service_worker_storage_control_impl.cc
@@ -4,6 +4,7 @@
#include "components/services/storage/service_worker/service_worker_storage_control_impl.h"
+#include "components/services/storage/public/cpp/storage_key.h"
#include "components/services/storage/service_worker/service_worker_resource_ops.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
@@ -122,36 +123,38 @@ void ServiceWorkerStorageControlImpl::Recover(
std::move(callback).Run();
}
-void ServiceWorkerStorageControlImpl::GetRegisteredOrigins(
- GetRegisteredOriginsCallback callback) {
- storage_->GetRegisteredOrigins(std::move(callback));
+void ServiceWorkerStorageControlImpl::GetRegisteredStorageKeys(
+ GetRegisteredStorageKeysCallback callback) {
+ storage_->GetRegisteredStorageKeys(std::move(callback));
}
void ServiceWorkerStorageControlImpl::FindRegistrationForClientUrl(
const GURL& client_url,
+ const StorageKey& key,
FindRegistrationForClientUrlCallback callback) {
storage_->FindRegistrationForClientUrl(
- client_url,
+ client_url, key,
base::BindOnce(&ServiceWorkerStorageControlImpl::DidFindRegistration,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void ServiceWorkerStorageControlImpl::FindRegistrationForScope(
const GURL& scope,
+ const StorageKey& key,
FindRegistrationForClientUrlCallback callback) {
storage_->FindRegistrationForScope(
- scope,
+ scope, key,
base::BindOnce(&ServiceWorkerStorageControlImpl::DidFindRegistration,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void ServiceWorkerStorageControlImpl::FindRegistrationForId(
int64_t registration_id,
- const base::Optional<url::Origin>& origin,
+ const absl::optional<StorageKey>& key,
FindRegistrationForClientUrlCallback callback) {
- if (origin.has_value()) {
+ if (key.has_value()) {
storage_->FindRegistrationForId(
- registration_id, *origin,
+ registration_id, *key,
base::BindOnce(&ServiceWorkerStorageControlImpl::DidFindRegistration,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
} else {
@@ -162,20 +165,20 @@ void ServiceWorkerStorageControlImpl::FindRegistrationForId(
}
}
-void ServiceWorkerStorageControlImpl::GetRegistrationsForOrigin(
- const url::Origin& origin,
- GetRegistrationsForOriginCallback callback) {
- storage_->GetRegistrationsForOrigin(
- origin,
+void ServiceWorkerStorageControlImpl::GetRegistrationsForStorageKey(
+ const StorageKey& key,
+ GetRegistrationsForStorageKeyCallback callback) {
+ storage_->GetRegistrationsForStorageKey(
+ key,
base::BindOnce(
- &ServiceWorkerStorageControlImpl::DidGetRegistrationsForOrigin,
+ &ServiceWorkerStorageControlImpl::DidGetRegistrationsForStorageKey,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
-void ServiceWorkerStorageControlImpl::GetUsageForOrigin(
- const url::Origin& origin,
- GetUsageForOriginCallback callback) {
- storage_->GetUsageForOrigin(origin, std::move(callback));
+void ServiceWorkerStorageControlImpl::GetUsageForStorageKey(
+ const StorageKey& key,
+ GetUsageForStorageKeyCallback callback) {
+ storage_->GetUsageForStorageKey(key, std::move(callback));
}
void ServiceWorkerStorageControlImpl::GetAllRegistrationsDeprecated(
@@ -196,45 +199,45 @@ void ServiceWorkerStorageControlImpl::StoreRegistration(
void ServiceWorkerStorageControlImpl::DeleteRegistration(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
DeleteRegistrationCallback callback) {
storage_->DeleteRegistration(
- registration_id, origin,
+ registration_id, key,
base::BindOnce(&ServiceWorkerStorageControlImpl::DidDeleteRegistration,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void ServiceWorkerStorageControlImpl::UpdateToActiveState(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
UpdateToActiveStateCallback callback) {
- storage_->UpdateToActiveState(registration_id, origin, std::move(callback));
+ storage_->UpdateToActiveState(registration_id, key, std::move(callback));
}
void ServiceWorkerStorageControlImpl::UpdateLastUpdateCheckTime(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
base::Time last_update_check_time,
UpdateLastUpdateCheckTimeCallback callback) {
storage_->UpdateLastUpdateCheckTime(
- registration_id, origin, last_update_check_time, std::move(callback));
+ registration_id, key, last_update_check_time, std::move(callback));
}
void ServiceWorkerStorageControlImpl::UpdateNavigationPreloadEnabled(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
bool enable,
UpdateNavigationPreloadEnabledCallback callback) {
- storage_->UpdateNavigationPreloadEnabled(registration_id, origin, enable,
+ storage_->UpdateNavigationPreloadEnabled(registration_id, key, enable,
std::move(callback));
}
void ServiceWorkerStorageControlImpl::UpdateNavigationPreloadHeader(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
const std::string& value,
UpdateNavigationPreloadHeaderCallback callback) {
- storage_->UpdateNavigationPreloadHeader(registration_id, origin, value,
+ storage_->UpdateNavigationPreloadHeader(registration_id, key, value,
std::move(callback));
}
@@ -294,10 +297,10 @@ void ServiceWorkerStorageControlImpl::GetUserData(
void ServiceWorkerStorageControlImpl::StoreUserData(
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
std::vector<mojom::ServiceWorkerUserDataPtr> user_data,
StoreUserDataCallback callback) {
- storage_->StoreUserData(registration_id, origin, std::move(user_data),
+ storage_->StoreUserData(registration_id, key, std::move(user_data),
std::move(callback));
}
@@ -409,8 +412,8 @@ void ServiceWorkerStorageControlImpl::DidFindRegistration(
std::move(resource_list)));
}
-void ServiceWorkerStorageControlImpl::DidGetRegistrationsForOrigin(
- GetRegistrationsForOriginCallback callback,
+void ServiceWorkerStorageControlImpl::DidGetRegistrationsForStorageKey(
+ GetRegistrationsForStorageKeyCallback callback,
mojom::ServiceWorkerDatabaseStatus status,
std::unique_ptr<ServiceWorkerStorage::RegistrationList>
registration_data_list,
@@ -448,12 +451,12 @@ void ServiceWorkerStorageControlImpl::DidStoreRegistration(
void ServiceWorkerStorageControlImpl::DidDeleteRegistration(
DeleteRegistrationCallback callback,
mojom::ServiceWorkerDatabaseStatus status,
- ServiceWorkerStorage::OriginState origin_state,
+ ServiceWorkerStorage::StorageKeyState storage_key_state,
int64_t deleted_version_id,
uint64_t deleted_resources_size,
const std::vector<int64_t>& newly_purgeable_resources) {
MaybePurgeResources(deleted_version_id, newly_purgeable_resources);
- std::move(callback).Run(status, deleted_resources_size, origin_state);
+ std::move(callback).Run(status, deleted_resources_size, storage_key_state);
}
void ServiceWorkerStorageControlImpl::DidGetNewVersionId(
diff --git a/chromium/components/services/storage/service_worker/service_worker_storage_control_impl.h b/chromium/components/services/storage/service_worker/service_worker_storage_control_impl.h
index c3f706e7de7..dcaa9d390a8 100644
--- a/chromium/components/services/storage/service_worker/service_worker_storage_control_impl.h
+++ b/chromium/components/services/storage/service_worker/service_worker_storage_control_impl.h
@@ -49,21 +49,24 @@ class ServiceWorkerStorageControlImpl
void Delete(DeleteCallback callback) override;
void Recover(std::vector<mojom::ServiceWorkerLiveVersionInfoPtr> versions,
RecoverCallback callback) override;
- void GetRegisteredOrigins(GetRegisteredOriginsCallback callback) override;
+ void GetRegisteredStorageKeys(
+ GetRegisteredStorageKeysCallback callback) override;
void FindRegistrationForClientUrl(
const GURL& client_url,
+ const StorageKey& key,
FindRegistrationForClientUrlCallback callback) override;
void FindRegistrationForScope(
const GURL& scope,
+ const StorageKey& key,
FindRegistrationForScopeCallback callback) override;
void FindRegistrationForId(int64_t registration_id,
- const base::Optional<url::Origin>& origin,
+ const absl::optional<StorageKey>& key,
FindRegistrationForIdCallback callback) override;
- void GetRegistrationsForOrigin(
- const url::Origin& origin,
- GetRegistrationsForOriginCallback callback) override;
- void GetUsageForOrigin(const url::Origin& origin,
- GetUsageForOriginCallback callback) override;
+ void GetRegistrationsForStorageKey(
+ const StorageKey& key,
+ GetRegistrationsForStorageKeyCallback callback) override;
+ void GetUsageForStorageKey(const StorageKey& key,
+ GetUsageForStorageKeyCallback callback) override;
void GetAllRegistrationsDeprecated(
GetAllRegistrationsDeprecatedCallback calback) override;
void StoreRegistration(
@@ -71,24 +74,24 @@ class ServiceWorkerStorageControlImpl
std::vector<mojom::ServiceWorkerResourceRecordPtr> resources,
StoreRegistrationCallback callback) override;
void DeleteRegistration(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
DeleteRegistrationCallback callback) override;
void UpdateToActiveState(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
UpdateToActiveStateCallback callback) override;
void UpdateLastUpdateCheckTime(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
base::Time last_update_check_time,
UpdateLastUpdateCheckTimeCallback callback) override;
void UpdateNavigationPreloadEnabled(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
bool enable,
UpdateNavigationPreloadEnabledCallback callback) override;
void UpdateNavigationPreloadHeader(
int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
const std::string& value,
UpdateNavigationPreloadHeaderCallback callback) override;
void GetNewRegistrationId(GetNewRegistrationIdCallback callback) override;
@@ -116,7 +119,7 @@ class ServiceWorkerStorageControlImpl
const std::vector<std::string>& keys,
GetUserDataCallback callback) override;
void StoreUserData(int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
std::vector<mojom::ServiceWorkerUserDataPtr> user_data,
StoreUserDataCallback callback) override;
void ClearUserData(int64_t registration_id,
@@ -165,8 +168,8 @@ class ServiceWorkerStorageControlImpl
mojom::ServiceWorkerRegistrationDataPtr data,
std::unique_ptr<ResourceList> resources,
mojom::ServiceWorkerDatabaseStatus status);
- void DidGetRegistrationsForOrigin(
- GetRegistrationsForOriginCallback callback,
+ void DidGetRegistrationsForStorageKey(
+ GetRegistrationsForStorageKeyCallback callback,
mojom::ServiceWorkerDatabaseStatus status,
std::unique_ptr<ServiceWorkerStorage::RegistrationList>
registration_data_list,
@@ -180,7 +183,7 @@ class ServiceWorkerStorageControlImpl
void DidDeleteRegistration(
DeleteRegistrationCallback callback,
mojom::ServiceWorkerDatabaseStatus status,
- ServiceWorkerStorage::OriginState origin_state,
+ ServiceWorkerStorage::StorageKeyState storage_key_state,
int64_t deleted_version_id,
uint64_t deleted_resources_size,
const std::vector<int64_t>& newly_purgeable_resources);
@@ -205,4 +208,4 @@ class ServiceWorkerStorageControlImpl
} // namespace storage
-#endif // COMPONENTS_SERVICES_STORAGE_SERVICE_WORKER_SERVICE_WORKER_STORAGE_CONTROLIMPL_H_
+#endif // COMPONENTS_SERVICES_STORAGE_SERVICE_WORKER_SERVICE_WORKER_STORAGE_CONTROL_IMPL_H_
diff --git a/chromium/components/services/storage/service_worker/service_worker_storage_control_impl_unittest.cc b/chromium/components/services/storage/service_worker/service_worker_storage_control_impl_unittest.cc
index c9640f358e2..6fc439abf81 100644
--- a/chromium/components/services/storage/service_worker/service_worker_storage_control_impl_unittest.cc
+++ b/chromium/components/services/storage/service_worker/service_worker_storage_control_impl_unittest.cc
@@ -42,7 +42,7 @@ struct FindRegistrationResult {
struct ReadResponseHeadResult {
int status;
network::mojom::URLResponseHeadPtr response_head;
- base::Optional<mojo_base::BigBuffer> metadata;
+ absl::optional<mojo_base::BigBuffer> metadata;
};
struct ReadDataResult {
@@ -57,7 +57,7 @@ struct GetRegistrationsForOriginResult {
struct DeleteRegistrationResult {
DatabaseStatus status;
- mojom::ServiceWorkerStorageOriginState origin_state;
+ mojom::ServiceWorkerStorageStorageKeyState storage_key_state;
};
struct GetNewVersionIdResult {
@@ -91,7 +91,7 @@ ReadResponseHeadResult ReadResponseHead(
base::RunLoop loop;
reader->ReadResponseHead(base::BindLambdaForTesting(
[&](int status, network::mojom::URLResponseHeadPtr response_head,
- base::Optional<mojo_base::BigBuffer> metadata) {
+ absl::optional<mojo_base::BigBuffer> metadata) {
result.status = status;
result.response_head = std::move(response_head);
result.metadata = std::move(metadata);
@@ -199,11 +199,12 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
void LazyInitializeForTest() { storage_impl_->LazyInitializeForTest(); }
- FindRegistrationResult FindRegistrationForClientUrl(const GURL& client_url) {
+ FindRegistrationResult FindRegistrationForClientUrl(const GURL& client_url,
+ const StorageKey& key) {
FindRegistrationResult return_value;
base::RunLoop loop;
storage()->FindRegistrationForClientUrl(
- client_url,
+ client_url, key,
base::BindLambdaForTesting(
[&](DatabaseStatus status,
mojom::ServiceWorkerFindRegistrationResultPtr entry) {
@@ -215,28 +216,30 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
return return_value;
}
- FindRegistrationResult FindRegistrationForScope(const GURL& scope) {
+ FindRegistrationResult FindRegistrationForScope(const GURL& scope,
+ const StorageKey& key) {
FindRegistrationResult return_value;
base::RunLoop loop;
storage()->FindRegistrationForScope(
- scope, base::BindLambdaForTesting(
- [&](DatabaseStatus status,
- mojom::ServiceWorkerFindRegistrationResultPtr entry) {
- return_value.status = status;
- return_value.entry = std::move(entry);
- loop.Quit();
- }));
+ scope, key,
+ base::BindLambdaForTesting(
+ [&](DatabaseStatus status,
+ mojom::ServiceWorkerFindRegistrationResultPtr entry) {
+ return_value.status = status;
+ return_value.entry = std::move(entry);
+ loop.Quit();
+ }));
loop.Run();
return return_value;
}
FindRegistrationResult FindRegistrationForId(
int64_t registration_id,
- const base::Optional<url::Origin>& origin) {
+ const absl::optional<StorageKey>& key) {
FindRegistrationResult return_value;
base::RunLoop loop;
storage()->FindRegistrationForId(
- registration_id, origin,
+ registration_id, key,
base::BindLambdaForTesting(
[&](DatabaseStatus status,
mojom::ServiceWorkerFindRegistrationResultPtr entry) {
@@ -248,20 +251,19 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
return return_value;
}
- GetRegistrationsForOriginResult GetRegistrationsForOrigin(
- const url::Origin& origin) {
+ GetRegistrationsForOriginResult GetRegistrationsForStorageKey(
+ const StorageKey& key) {
GetRegistrationsForOriginResult result;
base::RunLoop loop;
- storage()->GetRegistrationsForOrigin(
- origin,
- base::BindLambdaForTesting(
- [&](DatabaseStatus status,
- std::vector<mojom::ServiceWorkerFindRegistrationResultPtr>
- registrations) {
- result.status = status;
- result.registrations = std::move(registrations);
- loop.Quit();
- }));
+ storage()->GetRegistrationsForStorageKey(
+ key, base::BindLambdaForTesting(
+ [&](DatabaseStatus status,
+ std::vector<mojom::ServiceWorkerFindRegistrationResultPtr>
+ registrations) {
+ result.status = status;
+ result.registrations = std::move(registrations);
+ loop.Quit();
+ }));
loop.Run();
return result;
}
@@ -283,16 +285,16 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
}
DeleteRegistrationResult DeleteRegistration(int64_t registration_id,
- const GURL& origin) {
+ const StorageKey& key) {
DeleteRegistrationResult result;
base::RunLoop loop;
storage()->DeleteRegistration(
- registration_id, origin,
+ registration_id, key,
base::BindLambdaForTesting(
[&](DatabaseStatus status, uint64_t /*deleted_resources_size*/,
- mojom::ServiceWorkerStorageOriginState origin_state) {
+ mojom::ServiceWorkerStorageStorageKeyState storage_key_state) {
result.status = status;
- result.origin_state = origin_state;
+ result.storage_key_state = storage_key_state;
loop.Quit();
}));
loop.Run();
@@ -300,11 +302,11 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
}
DatabaseStatus UpdateToActiveState(int64_t registration_id,
- const GURL& origin) {
+ const StorageKey& key) {
DatabaseStatus out_status;
base::RunLoop loop;
storage()->UpdateToActiveState(
- registration_id, origin,
+ registration_id, key,
base::BindLambdaForTesting([&](DatabaseStatus status) {
out_status = status;
loop.Quit();
@@ -314,12 +316,12 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
}
DatabaseStatus UpdateLastUpdateCheckTime(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
base::Time last_update_check_time) {
DatabaseStatus out_status;
base::RunLoop loop;
storage()->UpdateLastUpdateCheckTime(
- registration_id, origin, last_update_check_time,
+ registration_id, key, last_update_check_time,
base::BindLambdaForTesting([&](DatabaseStatus status) {
out_status = status;
loop.Quit();
@@ -329,12 +331,12 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
}
DatabaseStatus UpdateNavigationPreloadEnabled(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
bool enable) {
DatabaseStatus out_status;
base::RunLoop loop;
storage()->UpdateNavigationPreloadEnabled(
- registration_id, origin, enable,
+ registration_id, key, enable,
base::BindLambdaForTesting([&](DatabaseStatus status) {
out_status = status;
loop.Quit();
@@ -344,12 +346,12 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
}
DatabaseStatus UpdateNavigationPreloadHeader(int64_t registration_id,
- const GURL& origin,
+ const StorageKey& key,
const std::string& value) {
DatabaseStatus out_status;
base::RunLoop loop;
storage()->UpdateNavigationPreloadHeader(
- registration_id, origin, value,
+ registration_id, key, value,
base::BindLambdaForTesting([&](DatabaseStatus status) {
out_status = status;
loop.Quit();
@@ -439,12 +441,12 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
DatabaseStatus StoreUserData(
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
std::vector<mojom::ServiceWorkerUserDataPtr> user_data) {
DatabaseStatus return_value;
base::RunLoop loop;
storage()->StoreUserData(
- registration_id, origin, std::move(user_data),
+ registration_id, key, std::move(user_data),
base::BindLambdaForTesting([&](DatabaseStatus status) {
return_value = status;
loop.Quit();
@@ -680,37 +682,40 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
// anything.
TEST_F(ServiceWorkerStorageControlImplTest, FindRegistration_NoRegistration) {
const GURL kScope("https://www.example.com/scope/");
+ const StorageKey kKey(url::Origin::Create(kScope));
const GURL kClientUrl("https://www.example.com/scope/document.html");
const int64_t kRegistrationId = 0;
LazyInitializeForTest();
{
- FindRegistrationResult result = FindRegistrationForClientUrl(kClientUrl);
+ FindRegistrationResult result =
+ FindRegistrationForClientUrl(kClientUrl, kKey);
EXPECT_EQ(result.status, DatabaseStatus::kErrorNotFound);
}
{
- FindRegistrationResult result = FindRegistrationForScope(kScope);
+ FindRegistrationResult result = FindRegistrationForScope(kScope, kKey);
EXPECT_EQ(result.status, DatabaseStatus::kErrorNotFound);
}
{
FindRegistrationResult result =
- FindRegistrationForId(kRegistrationId, url::Origin::Create(kScope));
+ FindRegistrationForId(kRegistrationId, kKey);
EXPECT_EQ(result.status, DatabaseStatus::kErrorNotFound);
}
{
FindRegistrationResult result =
- FindRegistrationForId(kRegistrationId, base::nullopt);
+ FindRegistrationForId(kRegistrationId, absl::nullopt);
EXPECT_EQ(result.status, DatabaseStatus::kErrorNotFound);
}
}
-// Tests that storing/finding/deleting a registration work.
+// Tests that storing/finding/deleting a registration works.
TEST_F(ServiceWorkerStorageControlImplTest, StoreAndDeleteRegistration) {
const GURL kScope("https://www.example.com/scope/");
+ const StorageKey kKey(url::Origin::Create(kScope));
const GURL kScriptUrl("https://www.example.com/scope/sw.js");
const GURL kClientUrl("https://www.example.com/scope/document.html");
const int64_t kScriptSize = 10;
@@ -747,7 +752,8 @@ TEST_F(ServiceWorkerStorageControlImplTest, StoreAndDeleteRegistration) {
// Find the registration. Find operations should succeed.
{
- FindRegistrationResult result = FindRegistrationForClientUrl(kClientUrl);
+ FindRegistrationResult result =
+ FindRegistrationForClientUrl(kClientUrl, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
EXPECT_EQ(result.entry->registration->registration_id, kRegistrationId);
EXPECT_EQ(result.entry->registration->scope, kScope);
@@ -757,39 +763,38 @@ TEST_F(ServiceWorkerStorageControlImplTest, StoreAndDeleteRegistration) {
resources_total_size_bytes);
EXPECT_EQ(result.entry->resources.size(), 1UL);
- result = FindRegistrationForScope(kScope);
+ result = FindRegistrationForScope(kScope, kKey);
EXPECT_EQ(result.status, DatabaseStatus::kOk);
- result =
- FindRegistrationForId(kRegistrationId, url::Origin::Create(kScope));
+ result = FindRegistrationForId(kRegistrationId, kKey);
EXPECT_EQ(result.status, DatabaseStatus::kOk);
- result = FindRegistrationForId(kRegistrationId, base::nullopt);
+ result = FindRegistrationForId(kRegistrationId, absl::nullopt);
EXPECT_EQ(result.status, DatabaseStatus::kOk);
}
// Delete the registration.
{
- DeleteRegistrationResult result =
- DeleteRegistration(kRegistrationId, kScope.GetOrigin());
+ DeleteRegistrationResult result = DeleteRegistration(kRegistrationId, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
- EXPECT_EQ(result.origin_state,
- mojom::ServiceWorkerStorageOriginState::kDelete);
+ EXPECT_EQ(result.storage_key_state,
+ mojom::ServiceWorkerStorageStorageKeyState::kDelete);
}
// Try to find the deleted registration. These operation should result in
// kErrorNotFound.
{
- FindRegistrationResult result = FindRegistrationForClientUrl(kClientUrl);
+ FindRegistrationResult result =
+ FindRegistrationForClientUrl(kClientUrl, kKey);
EXPECT_EQ(result.status, DatabaseStatus::kErrorNotFound);
- result = FindRegistrationForScope(kScope);
+ result = FindRegistrationForScope(kScope, kKey);
EXPECT_EQ(result.status, DatabaseStatus::kErrorNotFound);
- result =
- FindRegistrationForId(kRegistrationId, url::Origin::Create(kScope));
+ result = FindRegistrationForId(kRegistrationId, kKey);
EXPECT_EQ(result.status, DatabaseStatus::kErrorNotFound);
}
}
TEST_F(ServiceWorkerStorageControlImplTest, UpdateToActiveState) {
const GURL kScope("https://www.example.com/");
+ const StorageKey kKey(url::Origin::Create(kScope));
const GURL kScriptUrl("https://www.example.com/sw.js");
const int64_t kScriptSize = 10;
@@ -807,19 +812,19 @@ TEST_F(ServiceWorkerStorageControlImplTest, UpdateToActiveState) {
// The stored registration shouldn't be activated yet.
{
FindRegistrationResult result =
- FindRegistrationForId(registration_id, url::Origin::Create(kScope));
+ FindRegistrationForId(registration_id, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
EXPECT_FALSE(result.entry->registration->is_active);
}
// Set the registration is active in storage.
- status = UpdateToActiveState(registration_id, kScope.GetOrigin());
+ status = UpdateToActiveState(registration_id, kKey);
ASSERT_EQ(status, DatabaseStatus::kOk);
// Now the stored registration should be active.
{
FindRegistrationResult result =
- FindRegistrationForId(registration_id, url::Origin::Create(kScope));
+ FindRegistrationForId(registration_id, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
EXPECT_TRUE(result.entry->registration->is_active);
}
@@ -827,6 +832,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, UpdateToActiveState) {
TEST_F(ServiceWorkerStorageControlImplTest, UpdateLastUpdateCheckTime) {
const GURL kScope("https://www.example.com/");
+ const StorageKey kKey(url::Origin::Create(kScope));
const GURL kScriptUrl("https://www.example.com/sw.js");
const int64_t kScriptSize = 10;
@@ -844,20 +850,20 @@ TEST_F(ServiceWorkerStorageControlImplTest, UpdateLastUpdateCheckTime) {
// The stored registration shouldn't have the last update check time yet.
{
FindRegistrationResult result =
- FindRegistrationForId(registration_id, url::Origin::Create(kScope));
+ FindRegistrationForId(registration_id, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
EXPECT_EQ(result.entry->registration->last_update_check, base::Time());
}
// Set the last update check time.
const base::Time now = base::Time::Now();
- status = UpdateLastUpdateCheckTime(registration_id, kScope.GetOrigin(), now);
+ status = UpdateLastUpdateCheckTime(registration_id, kKey, now);
ASSERT_EQ(status, DatabaseStatus::kOk);
// Now the stored registration should be active.
{
FindRegistrationResult result =
- FindRegistrationForId(registration_id, url::Origin::Create(kScope));
+ FindRegistrationForId(registration_id, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
EXPECT_EQ(result.entry->registration->last_update_check, now);
}
@@ -865,6 +871,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, UpdateLastUpdateCheckTime) {
TEST_F(ServiceWorkerStorageControlImplTest, Update) {
const GURL kScope("https://www.example.com/");
+ const StorageKey kKey(url::Origin::Create(kScope));
const GURL kScriptUrl("https://www.example.com/sw.js");
const int64_t kScriptSize = 10;
@@ -882,7 +889,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, Update) {
// Check the stored registration has default navigation preload fields.
{
FindRegistrationResult result =
- FindRegistrationForId(registration_id, url::Origin::Create(kScope));
+ FindRegistrationForId(registration_id, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
EXPECT_FALSE(result.entry->registration->navigation_preload_state->enabled);
EXPECT_EQ(result.entry->registration->navigation_preload_state->header,
@@ -891,17 +898,15 @@ TEST_F(ServiceWorkerStorageControlImplTest, Update) {
// Update navigation preload fields.
const std::string header_value = "my-header";
- status =
- UpdateNavigationPreloadEnabled(registration_id, kScope.GetOrigin(), true);
+ status = UpdateNavigationPreloadEnabled(registration_id, kKey, true);
ASSERT_EQ(status, DatabaseStatus::kOk);
- status = UpdateNavigationPreloadHeader(registration_id, kScope.GetOrigin(),
- header_value);
+ status = UpdateNavigationPreloadHeader(registration_id, kKey, header_value);
ASSERT_EQ(status, DatabaseStatus::kOk);
// Check navigation preload fields are updated.
{
FindRegistrationResult result =
- FindRegistrationForId(registration_id, url::Origin::Create(kScope));
+ FindRegistrationForId(registration_id, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
EXPECT_TRUE(result.entry->registration->navigation_preload_state->enabled);
EXPECT_EQ(result.entry->registration->navigation_preload_state->header,
@@ -910,7 +915,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, Update) {
}
// Tests that getting registrations works.
-TEST_F(ServiceWorkerStorageControlImplTest, GetRegistrationsForOrigin) {
+TEST_F(ServiceWorkerStorageControlImplTest, GetRegistrationsForStorageKey) {
const GURL kScope1("https://www.example.com/foo/");
const GURL kScriptUrl1("https://www.example.com/foo/sw.js");
const GURL kScope2("https://www.example.com/bar/");
@@ -941,7 +946,8 @@ TEST_F(ServiceWorkerStorageControlImplTest, GetRegistrationsForOrigin) {
const url::Origin origin = url::Origin::Create(kScope1);
std::vector<mojom::ServiceWorkerFindRegistrationResultPtr> registrations;
- GetRegistrationsForOriginResult result = GetRegistrationsForOrigin(origin);
+ GetRegistrationsForOriginResult result =
+ GetRegistrationsForStorageKey(StorageKey(origin));
ASSERT_EQ(result.status, DatabaseStatus::kOk);
EXPECT_EQ(result.registrations.size(), 2UL);
@@ -960,7 +966,8 @@ TEST_F(ServiceWorkerStorageControlImplTest, GetRegistrationsForOrigin) {
url::Origin::Create(GURL("https://www.example.test/"));
std::vector<mojom::ServiceWorkerFindRegistrationResultPtr> registrations;
- GetRegistrationsForOriginResult result = GetRegistrationsForOrigin(origin);
+ GetRegistrationsForOriginResult result =
+ GetRegistrationsForStorageKey(StorageKey(origin));
ASSERT_EQ(result.status, DatabaseStatus::kOk);
EXPECT_EQ(result.registrations.size(), 0UL);
}
@@ -1020,7 +1027,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, WriteAndReadResource) {
EXPECT_TRUE(result.response_head->ssl_info->is_valid());
EXPECT_EQ(result.response_head->ssl_info->cert->serial_number(),
ssl_info.cert->serial_number());
- EXPECT_EQ(result.metadata, base::nullopt);
+ EXPECT_EQ(result.metadata, absl::nullopt);
ReadDataResult data_result = ReadResponseData(reader.get(), data_size);
ASSERT_EQ(data_result.status, data_size);
@@ -1127,9 +1134,10 @@ TEST_F(ServiceWorkerStorageControlImplTest, DoomUncommittedResources) {
EXPECT_TRUE(uncommitted_ids.empty());
}
-// Tests that storing/getting user data for a registration work.
+// Tests that storing/getting user data for a registration works.
TEST_F(ServiceWorkerStorageControlImplTest, StoreAndGetUserData) {
const GURL kScope("https://www.example.com/");
+ const StorageKey kKey(url::Origin::Create(kScope));
const GURL kScriptUrl("https://www.example.com/sw.js");
const int64_t kScriptSize = 10;
@@ -1151,8 +1159,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, StoreAndGetUserData) {
user_data.push_back(
mojom::ServiceWorkerUserData::New(registration_id, "key2", "value2"));
- status = StoreUserData(registration_id, url::Origin::Create(kScope),
- std::move(user_data));
+ status = StoreUserData(registration_id, kKey, std::move(user_data));
ASSERT_EQ(status, DatabaseStatus::kOk);
}
@@ -1199,8 +1206,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, StoreAndGetUserData) {
const int64_t new_version_id = GetNewVersionId().version_id;
const int64_t new_resource_id = GetNewResourceId();
{
- DeleteRegistrationResult result =
- DeleteRegistration(registration_id, kScope.GetOrigin());
+ DeleteRegistrationResult result = DeleteRegistration(registration_id, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
status = CreateAndStoreRegistration(new_registration_id, new_version_id,
@@ -1221,6 +1227,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, StoreAndGetUserData) {
// Tests that storing/getting user data by key prefix works.
TEST_F(ServiceWorkerStorageControlImplTest, StoreAndGetUserDataByKeyPrefix) {
const GURL kScope("https://www.example.com/");
+ const StorageKey kKey(url::Origin::Create(kScope));
const GURL kScriptUrl("https://www.example.com/sw.js");
const int64_t kScriptSize = 10;
@@ -1244,8 +1251,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, StoreAndGetUserDataByKeyPrefix) {
mojom::ServiceWorkerUserData::New(registration_id, "prefixB", "value3"));
user_data.push_back(
mojom::ServiceWorkerUserData::New(registration_id, "prefixC", "value4"));
- status = StoreUserData(registration_id, url::Origin::Create(kScope),
- std::move(user_data));
+ status = StoreUserData(registration_id, kKey, std::move(user_data));
ASSERT_EQ(status, DatabaseStatus::kOk);
{
@@ -1295,8 +1301,10 @@ TEST_F(ServiceWorkerStorageControlImplTest, StoreAndGetUserDataByKeyPrefix) {
TEST_F(ServiceWorkerStorageControlImplTest,
StoreAndGetUserDataForAllRegistrations) {
const GURL kScope1("https://www.example.com/foo");
+ const StorageKey kKey1(url::Origin::Create(kScope1));
const GURL kScriptUrl1("https://www.example.com/foo/sw.js");
const GURL kScope2("https://www.example.com/bar");
+ const StorageKey kKey2(url::Origin::Create(kScope2));
const GURL kScriptUrl2("https://www.example.com/bar/sw.js");
const int64_t kScriptSize = 10;
@@ -1329,8 +1337,7 @@ TEST_F(ServiceWorkerStorageControlImplTest,
registration_id1, "key2", "registration1_value2"));
user_data.push_back(mojom::ServiceWorkerUserData::New(
registration_id1, "prefix1", "registration1_prefix_value1"));
- status = StoreUserData(registration_id1, url::Origin::Create(kScope1),
- std::move(user_data));
+ status = StoreUserData(registration_id1, kKey1, std::move(user_data));
ASSERT_EQ(status, DatabaseStatus::kOk);
}
{
@@ -1341,8 +1348,7 @@ TEST_F(ServiceWorkerStorageControlImplTest,
registration_id1, "key3", "registration2_value3"));
user_data.push_back(mojom::ServiceWorkerUserData::New(
registration_id1, "prefix2", "registration2_prefix_value2"));
- status = StoreUserData(registration_id2, url::Origin::Create(kScope2),
- std::move(user_data));
+ status = StoreUserData(registration_id2, kKey2, std::move(user_data));
ASSERT_EQ(status, DatabaseStatus::kOk);
}
@@ -1406,8 +1412,10 @@ TEST_F(ServiceWorkerStorageControlImplTest,
// Tests that apply policy updates work.
TEST_F(ServiceWorkerStorageControlImplTest, ApplyPolicyUpdates) {
const GURL kScope1("https://foo.example.com/");
+ const StorageKey kKey1(url::Origin::Create(kScope1));
const GURL kScriptUrl1("https://foo.example.com/sw.js");
const GURL kScope2("https://bar.example.com/");
+ const StorageKey kKey2(url::Origin::Create(kScope2));
const GURL kScriptUrl2("https://bar.example.com/sw.js");
const int64_t kScriptSize = 10;
@@ -1447,17 +1455,18 @@ TEST_F(ServiceWorkerStorageControlImplTest, ApplyPolicyUpdates) {
// but not for |kScope2|.
RestartStorage();
{
- FindRegistrationResult result = FindRegistrationForScope(kScope1);
+ FindRegistrationResult result = FindRegistrationForScope(kScope1, kKey1);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
}
{
- FindRegistrationResult result = FindRegistrationForScope(kScope2);
+ FindRegistrationResult result = FindRegistrationForScope(kScope2, kKey2);
ASSERT_EQ(result.status, DatabaseStatus::kErrorNotFound);
}
}
TEST_F(ServiceWorkerStorageControlImplTest, TrackRunningVersion) {
const GURL kScope("https://www.example.com/");
+ const StorageKey kKey(url::Origin::Create(kScope));
const GURL kScriptUrl("https://www.example.com/sw.js");
const GURL kImportedScriptUrl("https://www.example.com/imported.js");
@@ -1493,7 +1502,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, TrackRunningVersion) {
ASSERT_EQ(status, DatabaseStatus::kOk);
// Create three reference from 1. GetNewVersionId(), 2.
- // FindRegistrationForId(), and 3. GetRegistrationsForOrigin().
+ // FindRegistrationForId(), and 3. GetRegistrationsForStorageKey().
mojo::Remote<mojom::ServiceWorkerLiveVersionRef> reference1;
ASSERT_TRUE(new_version_id_result.reference);
reference1.Bind(std::move(new_version_id_result.reference));
@@ -1501,7 +1510,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, TrackRunningVersion) {
mojo::Remote<mojom::ServiceWorkerLiveVersionRef> reference2;
{
FindRegistrationResult result =
- FindRegistrationForId(registration_id, url::Origin::Create(kScope));
+ FindRegistrationForId(registration_id, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
ASSERT_TRUE(result.entry->version_reference);
reference2.Bind(std::move(result.entry->version_reference));
@@ -1510,7 +1519,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, TrackRunningVersion) {
mojo::Remote<mojom::ServiceWorkerLiveVersionRef> reference3;
{
GetRegistrationsForOriginResult result =
- GetRegistrationsForOrigin(url::Origin::Create(kScope));
+ GetRegistrationsForStorageKey(kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
ASSERT_EQ(result.registrations.size(), 1UL);
ASSERT_TRUE(result.registrations[0]->version_reference);
@@ -1520,8 +1529,7 @@ TEST_F(ServiceWorkerStorageControlImplTest, TrackRunningVersion) {
// Drop the first reference and delete the registration.
reference1.reset();
{
- DeleteRegistrationResult result =
- DeleteRegistration(registration_id, kScope.GetOrigin());
+ DeleteRegistrationResult result = DeleteRegistration(registration_id, kKey);
ASSERT_EQ(result.status, DatabaseStatus::kOk);
}
diff --git a/chromium/components/services/storage/service_worker/service_worker_storage_test_utils.h b/chromium/components/services/storage/service_worker/service_worker_storage_test_utils.h
index ebf9e6159b6..755d8da292e 100644
--- a/chromium/components/services/storage/service_worker/service_worker_storage_test_utils.h
+++ b/chromium/components/services/storage/service_worker/service_worker_storage_test_utils.h
@@ -8,11 +8,11 @@
#include <string>
#include "base/callback.h"
-#include "base/optional.h"
#include "components/services/storage/public/mojom/service_worker_storage_control.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/system/data_pipe.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace storage {
@@ -32,7 +32,7 @@ class FakeServiceWorkerDataPipeStateNotifier
// mojom::ServiceWorkerDataPipeStateNotifier implementations:
void OnComplete(int32_t status) override;
- base::Optional<int32_t> complete_status_;
+ absl::optional<int32_t> complete_status_;
base::OnceClosure on_complete_callback_;
mojo::Receiver<mojom::ServiceWorkerDataPipeStateNotifier> receiver_{this};
};
diff --git a/chromium/components/services/storage/service_worker/service_worker_storage_unittest.cc b/chromium/components/services/storage/service_worker/service_worker_storage_unittest.cc
index 2d60a4999bc..e0a8e293210 100644
--- a/chromium/components/services/storage/service_worker/service_worker_storage_unittest.cc
+++ b/chromium/components/services/storage/service_worker/service_worker_storage_unittest.cc
@@ -30,7 +30,7 @@ namespace service_worker_storage_unittest {
struct ReadResponseHeadResult {
int result;
network::mojom::URLResponseHeadPtr response_head;
- base::Optional<mojo_base::BigBuffer> metadata;
+ absl::optional<mojo_base::BigBuffer> metadata;
};
using RegistrationData = mojom::ServiceWorkerRegistrationData;
@@ -69,7 +69,7 @@ mojom::ServiceWorkerRegistrationDataPtr CreateRegistrationData(
void DatabaseStatusCallback(
base::OnceClosure quit_closure,
- base::Optional<ServiceWorkerDatabase::Status>* result,
+ absl::optional<ServiceWorkerDatabase::Status>* result,
ServiceWorkerDatabase::Status status) {
*result = status;
std::move(quit_closure).Run();
@@ -105,14 +105,15 @@ class ServiceWorkerStorageTest : public testing::Test {
void LazyInitialize() { storage()->LazyInitializeForTest(); }
ServiceWorkerDatabase::Status DeleteRegistration(int64_t registration_id,
- const GURL& origin) {
+ const StorageKey& key) {
ServiceWorkerDatabase::Status result;
base::RunLoop loop;
storage()->DeleteRegistration(
- registration_id, origin,
+ registration_id, key,
base::BindLambdaForTesting(
[&](ServiceWorkerDatabase::Status status,
- ServiceWorkerStorage::OriginState, int64_t /*deleted_version*/,
+ ServiceWorkerStorage::StorageKeyState,
+ int64_t /*deleted_version*/,
uint64_t /*deleted_resources_size*/,
const std::vector<int64_t>& /*newly_purgeable_resources*/) {
result = status;
@@ -138,33 +139,33 @@ class ServiceWorkerStorageTest : public testing::Test {
return result;
}
- ServiceWorkerDatabase::Status GetUsageForOrigin(const url::Origin& origin,
- int64_t& out_usage) {
+ ServiceWorkerDatabase::Status GetUsageForStorageKey(const StorageKey& key,
+ int64_t& out_usage) {
ServiceWorkerDatabase::Status result;
base::RunLoop loop;
- storage()->GetUsageForOrigin(
- origin, base::BindLambdaForTesting(
- [&](ServiceWorkerDatabase::Status status, int64_t usage) {
- result = status;
- out_usage = usage;
- loop.Quit();
- }));
+ storage()->GetUsageForStorageKey(
+ key, base::BindLambdaForTesting(
+ [&](ServiceWorkerDatabase::Status status, int64_t usage) {
+ result = status;
+ out_usage = usage;
+ loop.Quit();
+ }));
loop.Run();
return result;
}
- ServiceWorkerDatabase::Status GetRegistrationsForOrigin(
- const url::Origin& origin) {
+ ServiceWorkerDatabase::Status GetRegistrationsForStorageKey(
+ const StorageKey& key) {
ServiceWorkerDatabase::Status result;
base::RunLoop loop;
- storage()->GetRegistrationsForOrigin(
- origin, base::BindLambdaForTesting(
- [&](ServiceWorkerDatabase::Status status,
- std::unique_ptr<ServiceWorkerStorage::RegistrationList>,
- std::unique_ptr<std::vector<ResourceList>>) {
- result = status;
- loop.Quit();
- }));
+ storage()->GetRegistrationsForStorageKey(
+ key, base::BindLambdaForTesting(
+ [&](ServiceWorkerDatabase::Status status,
+ std::unique_ptr<ServiceWorkerStorage::RegistrationList>,
+ std::unique_ptr<std::vector<ResourceList>>) {
+ result = status;
+ loop.Quit();
+ }));
loop.Run();
return result;
}
@@ -207,7 +208,7 @@ class ServiceWorkerStorageTest : public testing::Test {
ServiceWorkerDatabase::Status StoreUserData(
int64_t registration_id,
- const url::Origin& origin,
+ const StorageKey& key,
const std::vector<std::pair<std::string, std::string>>& key_value_pairs) {
std::vector<mojom::ServiceWorkerUserDataPtr> user_data;
for (const auto& kv : key_value_pairs) {
@@ -218,7 +219,7 @@ class ServiceWorkerStorageTest : public testing::Test {
ServiceWorkerDatabase::Status result;
base::RunLoop loop;
storage()->StoreUserData(
- registration_id, origin, std::move(user_data),
+ registration_id, key, std::move(user_data),
base::BindLambdaForTesting([&](ServiceWorkerDatabase::Status status) {
result = status;
loop.Quit();
@@ -291,11 +292,11 @@ class ServiceWorkerStorageTest : public testing::Test {
}
ServiceWorkerDatabase::Status UpdateToActiveState(int64_t registration_id,
- const url::Origin& origin) {
+ const StorageKey& key) {
ServiceWorkerDatabase::Status result;
base::RunLoop loop;
storage()->UpdateToActiveState(
- registration_id, origin.GetURL(),
+ registration_id, key,
base::BindLambdaForTesting([&](ServiceWorkerDatabase::Status status) {
result = status;
loop.Quit();
@@ -305,11 +306,12 @@ class ServiceWorkerStorageTest : public testing::Test {
}
ServiceWorkerDatabase::Status FindRegistrationForClientUrl(
- const GURL& document_url) {
+ const GURL& document_url,
+ const StorageKey& key) {
ServiceWorkerDatabase::Status result;
base::RunLoop loop;
storage()->FindRegistrationForClientUrl(
- document_url,
+ document_url, key,
base::BindLambdaForTesting([&](mojom::ServiceWorkerRegistrationDataPtr,
std::unique_ptr<ResourceList>,
ServiceWorkerDatabase::Status status) {
@@ -320,11 +322,13 @@ class ServiceWorkerStorageTest : public testing::Test {
return result;
}
- ServiceWorkerDatabase::Status FindRegistrationForScope(const GURL& scope) {
+ ServiceWorkerDatabase::Status FindRegistrationForScope(
+ const GURL& scope,
+ const StorageKey& key) {
ServiceWorkerDatabase::Status result;
base::RunLoop loop;
storage()->FindRegistrationForScope(
- scope,
+ scope, key,
base::BindLambdaForTesting([&](mojom::ServiceWorkerRegistrationDataPtr,
std::unique_ptr<ResourceList>,
ServiceWorkerDatabase::Status status) {
@@ -335,13 +339,12 @@ class ServiceWorkerStorageTest : public testing::Test {
return result;
}
- ServiceWorkerDatabase::Status FindRegistrationForId(
- int64_t registration_id,
- const url::Origin& origin) {
+ ServiceWorkerDatabase::Status FindRegistrationForId(int64_t registration_id,
+ const StorageKey& key) {
ServiceWorkerDatabase::Status result;
base::RunLoop loop;
storage()->FindRegistrationForId(
- registration_id, origin,
+ registration_id, key,
base::BindLambdaForTesting([&](mojom::ServiceWorkerRegistrationDataPtr,
std::unique_ptr<ResourceList>,
ServiceWorkerDatabase::Status status) {
@@ -414,7 +417,7 @@ class ServiceWorkerStorageTest : public testing::Test {
reader->ReadResponseHead(base::BindLambdaForTesting(
[&](int result, network::mojom::URLResponseHeadPtr response_head,
- base::Optional<mojo_base::BigBuffer> metadata) {
+ absl::optional<mojo_base::BigBuffer> metadata) {
out.result = result;
out.response_head = std::move(response_head);
out.metadata = std::move(metadata);
@@ -524,6 +527,7 @@ class ServiceWorkerStorageTest : public testing::Test {
TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
const GURL kScope("http://www.example.com/scope/");
const url::Origin kOrigin = url::Origin::Create(kScope);
+ const StorageKey kKey(kOrigin);
const GURL kScript("http://www.example.com/script.js");
const GURL kDocumentUrl("http://www.example.com/scope/document.html");
const int64_t kRegistrationId = 0;
@@ -533,16 +537,16 @@ TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
LazyInitialize();
storage()->Disable();
- EXPECT_EQ(FindRegistrationForClientUrl(kDocumentUrl),
+ EXPECT_EQ(FindRegistrationForClientUrl(kDocumentUrl, kKey),
ServiceWorkerDatabase::Status::kErrorDisabled);
- EXPECT_EQ(FindRegistrationForScope(kScope),
+ EXPECT_EQ(FindRegistrationForScope(kScope, kKey),
ServiceWorkerDatabase::Status::kErrorDisabled);
- EXPECT_EQ(FindRegistrationForId(kRegistrationId, url::Origin::Create(kScope)),
+ EXPECT_EQ(FindRegistrationForId(kRegistrationId, kKey),
ServiceWorkerDatabase::Status::kErrorDisabled);
EXPECT_EQ(FindRegistrationForIdOnly(kRegistrationId),
ServiceWorkerDatabase::Status::kErrorDisabled);
- EXPECT_EQ(GetRegistrationsForOrigin(url::Origin::Create(kScope)),
+ EXPECT_EQ(GetRegistrationsForStorageKey(kKey),
ServiceWorkerDatabase::Status::kErrorDisabled);
EXPECT_EQ(GetAllRegistrations(),
@@ -557,10 +561,10 @@ TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
StoreRegistrationData(std::move(registration_data), std::move(resources)),
ServiceWorkerDatabase::Status::kErrorDisabled);
- EXPECT_EQ(UpdateToActiveState(kRegistrationId, kOrigin),
+ EXPECT_EQ(UpdateToActiveState(kRegistrationId, kKey),
ServiceWorkerDatabase::Status::kErrorDisabled);
- EXPECT_EQ(DeleteRegistration(kRegistrationId, kScope.GetOrigin()),
+ EXPECT_EQ(DeleteRegistration(kRegistrationId, kKey),
ServiceWorkerDatabase::Status::kErrorDisabled);
// Response reader and writer created by the disabled storage should fail to
@@ -576,7 +580,7 @@ TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
ServiceWorkerDatabase::Status::kErrorDisabled);
EXPECT_EQ(GetUserDataByKeyPrefix(kRegistrationId, "prefix", user_data_out),
ServiceWorkerDatabase::Status::kErrorDisabled);
- EXPECT_EQ(StoreUserData(kRegistrationId, kOrigin, {{kUserDataKey, "foo"}}),
+ EXPECT_EQ(StoreUserData(kRegistrationId, kKey, {{kUserDataKey, "foo"}}),
ServiceWorkerDatabase::Status::kErrorDisabled);
EXPECT_EQ(ClearUserData(kRegistrationId, {kUserDataKey}),
ServiceWorkerDatabase::Status::kErrorDisabled);
@@ -599,6 +603,7 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
const int64_t kRegistrationId = 1;
const GURL kScope("http://www.test.not/scope/");
const url::Origin kOrigin = url::Origin::Create(kScope);
+ const StorageKey kKey(kOrigin);
const GURL kScript("http://www.test.not/script.js");
LazyInitialize();
@@ -614,7 +619,7 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
// Store user data associated with the registration.
std::vector<std::string> data_out;
- EXPECT_EQ(StoreUserData(kRegistrationId, kOrigin, {{"key", "data"}}),
+ EXPECT_EQ(StoreUserData(kRegistrationId, kKey, {{"key", "data"}}),
ServiceWorkerDatabase::Status::kOk);
EXPECT_EQ(GetUserData(kRegistrationId, {"key"}, data_out),
ServiceWorkerDatabase::Status::kOk);
@@ -639,7 +644,7 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
// Write/overwrite multiple user data keys.
EXPECT_EQ(StoreUserData(
- kRegistrationId, kOrigin,
+ kRegistrationId, kKey,
{{"key", "overwrite"}, {"key3", "data3"}, {"key4", "data4"}}),
ServiceWorkerDatabase::Status::kOk);
EXPECT_EQ(GetUserData(kRegistrationId, {"key2"}, data_out),
@@ -671,7 +676,7 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
EXPECT_EQ("data4", data_out[0]);
// Get/delete multiple user data keys by prefixes.
- EXPECT_EQ(StoreUserData(kRegistrationId, kOrigin,
+ EXPECT_EQ(StoreUserData(kRegistrationId, kKey,
{{"prefixA", "data1"},
{"prefixA2", "data2"},
{"prefixB", "data3"},
@@ -698,14 +703,14 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
EXPECT_TRUE(data_out.empty());
// User data should be deleted when the associated registration is deleted.
- ASSERT_EQ(StoreUserData(kRegistrationId, kOrigin, {{"key", "data"}}),
+ ASSERT_EQ(StoreUserData(kRegistrationId, kKey, {{"key", "data"}}),
ServiceWorkerDatabase::Status::kOk);
ASSERT_EQ(GetUserData(kRegistrationId, {"key"}, data_out),
ServiceWorkerDatabase::Status::kOk);
ASSERT_EQ(1u, data_out.size());
ASSERT_EQ("data", data_out[0]);
- EXPECT_EQ(DeleteRegistration(kRegistrationId, kScope.GetOrigin()),
+ EXPECT_EQ(DeleteRegistration(kRegistrationId, kKey),
ServiceWorkerDatabase::Status::kOk);
EXPECT_EQ(GetUserData(kRegistrationId, {"key"}, data_out),
ServiceWorkerDatabase::Status::kErrorNotFound);
@@ -716,7 +721,7 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
// Data access with an invalid registration id should be failed.
EXPECT_EQ(StoreUserData(blink::mojom::kInvalidServiceWorkerRegistrationId,
- kOrigin, {{"key", "data"}}),
+ kKey, {{"key", "data"}}),
ServiceWorkerDatabase::Status::kErrorFailed);
EXPECT_EQ(GetUserData(blink::mojom::kInvalidServiceWorkerRegistrationId,
{"key"}, data_out),
@@ -733,12 +738,12 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
ServiceWorkerDatabase::Status::kErrorFailed);
// Data access with an empty key should be failed.
- EXPECT_EQ(StoreUserData(kRegistrationId, kOrigin,
+ EXPECT_EQ(StoreUserData(kRegistrationId, kKey,
std::vector<std::pair<std::string, std::string>>()),
ServiceWorkerDatabase::Status::kErrorFailed);
- EXPECT_EQ(StoreUserData(kRegistrationId, kOrigin, {{std::string(), "data"}}),
+ EXPECT_EQ(StoreUserData(kRegistrationId, kKey, {{std::string(), "data"}}),
ServiceWorkerDatabase::Status::kErrorFailed);
- EXPECT_EQ(StoreUserData(kRegistrationId, kOrigin,
+ EXPECT_EQ(StoreUserData(kRegistrationId, kKey,
{{std::string(), "data"}, {"key", "data"}}),
ServiceWorkerDatabase::Status::kErrorFailed);
EXPECT_EQ(GetUserData(kRegistrationId, std::vector<std::string>(), data_out),
@@ -770,9 +775,10 @@ TEST_F(ServiceWorkerStorageTest, StoreUserData) {
// called.
TEST_F(ServiceWorkerStorageTest, StoreUserData_BeforeInitialize) {
const int kRegistrationId = 0;
- EXPECT_EQ(StoreUserData(kRegistrationId,
- url::Origin::Create(GURL("https://example.com")),
- {{"key", "data"}}),
+ EXPECT_EQ(StoreUserData(
+ kRegistrationId,
+ StorageKey(url::Origin::Create(GURL("https://example.com"))),
+ {{"key", "data"}}),
ServiceWorkerDatabase::Status::kErrorNotFound);
}
@@ -844,7 +850,7 @@ TEST_F(ServiceWorkerStorageDiskTest, DeleteAndStartOver) {
ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
base::RunLoop run_loop;
- base::Optional<ServiceWorkerDatabase::Status> status;
+ absl::optional<ServiceWorkerDatabase::Status> status;
storage()->DeleteAndStartOver(
base::BindOnce(&DatabaseStatusCallback, run_loop.QuitClosure(), &status));
run_loop.Run();
@@ -868,7 +874,7 @@ TEST_F(ServiceWorkerStorageDiskTest, DeleteAndStartOver_UnrelatedFileExists) {
ASSERT_TRUE(base::PathExists(file_path));
base::RunLoop run_loop;
- base::Optional<ServiceWorkerDatabase::Status> status;
+ absl::optional<ServiceWorkerDatabase::Status> status;
storage()->DeleteAndStartOver(
base::BindOnce(&DatabaseStatusCallback, run_loop.QuitClosure(), &status));
run_loop.Run();
@@ -893,7 +899,7 @@ TEST_F(ServiceWorkerStorageDiskTest, DeleteAndStartOver_OpenedFileExists) {
ASSERT_TRUE(base::PathExists(file_path));
base::RunLoop run_loop;
- base::Optional<ServiceWorkerDatabase::Status> status;
+ absl::optional<ServiceWorkerDatabase::Status> status;
storage()->DeleteAndStartOver(
base::BindOnce(&DatabaseStatusCallback, run_loop.QuitClosure(), &status));
run_loop.Run();
@@ -948,23 +954,24 @@ TEST_F(ServiceWorkerStorageTest, GetStorageUsageForOrigin) {
// Storage usage should report total resource size from two registrations.
const url::Origin origin = url::Origin::Create(kScope1.GetOrigin());
+ const StorageKey key(origin);
int64_t usage;
- EXPECT_EQ(GetUsageForOrigin(origin, usage),
+ EXPECT_EQ(GetUsageForStorageKey(key, usage),
ServiceWorkerDatabase::Status::kOk);
EXPECT_EQ(usage, resources_total_size_bytes1 + resources_total_size_bytes2);
// Delete the first registration. Storage usage should report only the second
// registration.
- EXPECT_EQ(DeleteRegistration(kRegistrationId1, origin.GetURL()),
+ EXPECT_EQ(DeleteRegistration(kRegistrationId1, key),
ServiceWorkerDatabase::Status::kOk);
- EXPECT_EQ(GetUsageForOrigin(origin, usage),
+ EXPECT_EQ(GetUsageForStorageKey(key, usage),
ServiceWorkerDatabase::Status::kOk);
EXPECT_EQ(usage, resources_total_size_bytes2);
// Delete the second registration. No storage usage should be reported.
- EXPECT_EQ(DeleteRegistration(kRegistrationId2, origin.GetURL()),
+ EXPECT_EQ(DeleteRegistration(kRegistrationId2, key),
ServiceWorkerDatabase::Status::kOk);
- EXPECT_EQ(GetUsageForOrigin(origin, usage),
+ EXPECT_EQ(GetUsageForStorageKey(key, usage),
ServiceWorkerDatabase::Status::kOk);
EXPECT_EQ(usage, 0);
}
diff --git a/chromium/components/services/storage/storage_service_impl.cc b/chromium/components/services/storage/storage_service_impl.cc
index 8af7dfd5745..d119afafeb4 100644
--- a/chromium/components/services/storage/storage_service_impl.cc
+++ b/chromium/components/services/storage/storage_service_impl.cc
@@ -94,7 +94,7 @@ void StorageServiceImpl::SetDataDirectory(
#endif // !defined(OS_ANDROID)
void StorageServiceImpl::BindPartition(
- const base::Optional<base::FilePath>& path,
+ const absl::optional<base::FilePath>& path,
mojo::PendingReceiver<mojom::Partition> receiver) {
if (path.has_value()) {
if (!path->IsAbsolute()) {
diff --git a/chromium/components/services/storage/storage_service_impl.h b/chromium/components/services/storage/storage_service_impl.h
index 32d47b306e4..c12e2cc85ac 100644
--- a/chromium/components/services/storage/storage_service_impl.h
+++ b/chromium/components/services/storage/storage_service_impl.h
@@ -47,7 +47,7 @@ class StorageServiceImpl : public mojom::StorageService {
const base::FilePath& path,
mojo::PendingRemote<mojom::Directory> directory) override;
#endif
- void BindPartition(const base::Optional<base::FilePath>& path,
+ void BindPartition(const absl::optional<base::FilePath>& path,
mojo::PendingReceiver<mojom::Partition> receiver) override;
void BindTestApi(mojo::ScopedMessagePipeHandle test_api_receiver) override;
diff --git a/chromium/components/services/storage/storage_service_impl_unittest.cc b/chromium/components/services/storage/storage_service_impl_unittest.cc
index 87a8af2d191..29d197ec01c 100644
--- a/chromium/components/services/storage/storage_service_impl_unittest.cc
+++ b/chromium/components/services/storage/storage_service_impl_unittest.cc
@@ -40,7 +40,7 @@ TEST_F(StorageServiceImplTest, UniqueInMemoryPartitions) {
mojo::Remote<mojom::Partition> in_memory_partition1;
remote_service()->BindPartition(
- /*path=*/base::nullopt,
+ /*path=*/absl::nullopt,
in_memory_partition1.BindNewPipeAndPassReceiver());
in_memory_partition1.FlushForTesting();
@@ -48,7 +48,7 @@ TEST_F(StorageServiceImplTest, UniqueInMemoryPartitions) {
mojo::Remote<mojom::Partition> in_memory_partition2;
remote_service()->BindPartition(
- base::nullopt /* path */,
+ absl::nullopt /* path */,
in_memory_partition2.BindNewPipeAndPassReceiver());
in_memory_partition2.FlushForTesting();
diff --git a/chromium/components/services/unzip/public/cpp/unzip.h b/chromium/components/services/unzip/public/cpp/unzip.h
index f7926ba83dc..e62a4ac524d 100644
--- a/chromium/components/services/unzip/public/cpp/unzip.h
+++ b/chromium/components/services/unzip/public/cpp/unzip.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_UNZIP_H_
#define COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_UNZIP_H_
-#include <memory>
-
#include "base/callback_forward.h"
#include "components/services/unzip/public/mojom/unzipper.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/components/services/unzip/unzipper_impl.h b/chromium/components/services/unzip/unzipper_impl.h
index 9de2a096f96..4f81e4c9855 100644
--- a/chromium/components/services/unzip/unzipper_impl.h
+++ b/chromium/components/services/unzip/unzipper_impl.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SERVICES_UNZIP_UNZIPPER_IMPL_H_
#define COMPONENTS_SERVICES_UNZIP_UNZIPPER_IMPL_H_
-#include <memory>
-
#include "base/files/file.h"
#include "base/macros.h"
#include "components/services/unzip/public/mojom/unzipper.mojom.h"
diff --git a/chromium/components/session_manager/README.md b/chromium/components/session_manager/README.md
index a0a93cd3834..9fd093e0e89 100644
--- a/chromium/components/session_manager/README.md
+++ b/chromium/components/session_manager/README.md
@@ -19,5 +19,5 @@ SessionManager::Get() method gets the singleton like instance. The instance
in Chrome browser is ChromeSessionManager derived from SessionManager. This
is needed because SessionManager logic depends on policy code which is still
part of the browser. ChromeSessionManager is in browser/ and can access that.
-The ChromeSessionManager instance is created in the PreMainMessageLoopStart
+The ChromeSessionManager instance is created in the PreCreateMainMessageLoop
stage and destroyed in the PostMainMessageLoopRun.
diff --git a/chromium/components/session_manager/core/DIR_METADATA b/chromium/components/session_manager/core/DIR_METADATA
deleted file mode 100644
index d08126acf81..00000000000
--- a/chromium/components/session_manager/core/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "UI>Shell"
-}
diff --git a/chromium/components/session_manager/core/OWNERS b/chromium/components/session_manager/core/OWNERS
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/components/session_manager/core/OWNERS
+++ /dev/null
diff --git a/chromium/components/sessions/content/OWNERS b/chromium/components/sessions/content/OWNERS
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/components/sessions/content/OWNERS
+++ /dev/null
diff --git a/chromium/components/sessions/content/content_serialized_navigation_builder.cc b/chromium/components/sessions/content/content_serialized_navigation_builder.cc
index e5e435401e5..09afa86d3c8 100644
--- a/chromium/components/sessions/content/content_serialized_navigation_builder.cc
+++ b/chromium/components/sessions/content/content_serialized_navigation_builder.cc
@@ -23,11 +23,11 @@
namespace sessions {
namespace {
-base::Optional<SerializedNavigationEntry::ReplacedNavigationEntryData>
+absl::optional<SerializedNavigationEntry::ReplacedNavigationEntryData>
ConvertReplacedEntryData(
- const base::Optional<content::ReplacedNavigationEntryData>& input_data) {
+ const absl::optional<content::ReplacedNavigationEntryData>& input_data) {
if (!input_data.has_value())
- return base::nullopt;
+ return absl::nullopt;
SerializedNavigationEntry::ReplacedNavigationEntryData output_data;
output_data.first_committed_url = input_data->first_committed_url;
@@ -99,7 +99,7 @@ ContentSerializedNavigationBuilder::ToNavigationEntry(
// in favor of using the data stored in |navigation->encoded_page_state|.
GURL temporary_url;
content::Referrer temporary_referrer;
- base::Optional<url::Origin> temporary_initiator_origin;
+ absl::optional<url::Origin> temporary_initiator_origin;
std::unique_ptr<content::NavigationEntry> entry(
content::NavigationController::CreateNavigationEntry(
diff --git a/chromium/components/sessions/content/session_tab_helper_delegate.h b/chromium/components/sessions/content/session_tab_helper_delegate.h
index 45f7ee0c807..72e43a48133 100644
--- a/chromium/components/sessions/content/session_tab_helper_delegate.h
+++ b/chromium/components/sessions/content/session_tab_helper_delegate.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SESSIONS_CONTENT_SESSION_TAB_HELPER_DELEGATE_H_
#define COMPONENTS_SESSIONS_CONTENT_SESSION_TAB_HELPER_DELEGATE_H_
-#include <string>
-
#include "components/sessions/core/sessions_export.h"
class SessionID;
diff --git a/chromium/components/sessions/core/base_session_service_commands.cc b/chromium/components/sessions/core/base_session_service_commands.cc
index 8bb711a10f9..8a956cfe60e 100644
--- a/chromium/components/sessions/core/base_session_service_commands.cc
+++ b/chromium/components/sessions/core/base_session_service_commands.cc
@@ -187,7 +187,7 @@ bool RestoreSetTabUserAgentOverrideCommand2(
const SessionCommand& command,
SessionID* tab_id,
std::string* user_agent_override,
- base::Optional<std::string>* opaque_ua_metadata_override) {
+ absl::optional<std::string>* opaque_ua_metadata_override) {
std::unique_ptr<base::Pickle> pickle(command.PayloadAsPickle());
if (!pickle)
return false;
@@ -202,7 +202,7 @@ bool RestoreSetTabUserAgentOverrideCommand2(
if (!iterator.ReadBool(&has_ua_metadata_override))
return false;
if (!has_ua_metadata_override) {
- *opaque_ua_metadata_override = base::nullopt;
+ *opaque_ua_metadata_override = absl::nullopt;
return true;
}
diff --git a/chromium/components/sessions/core/base_session_service_commands.h b/chromium/components/sessions/core/base_session_service_commands.h
index a6942cecafa..d9b23cc5149 100644
--- a/chromium/components/sessions/core/base_session_service_commands.h
+++ b/chromium/components/sessions/core/base_session_service_commands.h
@@ -8,11 +8,11 @@
#include <memory>
#include <string>
-#include "base/optional.h"
#include "components/sessions/core/serialized_user_agent_override.h"
#include "components/sessions/core/session_command.h"
#include "components/sessions/core/session_id.h"
#include "components/sessions/core/sessions_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sessions {
class SessionCommand;
@@ -75,7 +75,7 @@ bool RestoreSetTabUserAgentOverrideCommand2(
const SessionCommand& command,
SessionID* tab_id,
std::string* user_agent_override,
- base::Optional<std::string>* opaque_ua_metadata_override);
+ absl::optional<std::string>* opaque_ua_metadata_override);
// Backwards compatible version that restores versions that didn't have
// structured user agent override.
diff --git a/chromium/components/sessions/core/command_storage_backend.cc b/chromium/components/sessions/core/command_storage_backend.cc
index ac568e53c7f..3b59e319781 100644
--- a/chromium/components/sessions/core/command_storage_backend.cc
+++ b/chromium/components/sessions/core/command_storage_backend.cc
@@ -572,7 +572,7 @@ void CommandStorageBackend::MoveCurrentSessionToLastSession() {
DeleteLastSession();
// Move current session to last.
- base::Optional<SessionInfo> new_last_session_info;
+ absl::optional<SessionInfo> new_last_session_info;
if (use_marker_) {
if (last_file_with_valid_marker_) {
new_last_session_info =
@@ -798,7 +798,7 @@ bool CommandStorageBackend::AppendEncryptedCommandToFile(
return true;
}
-base::Optional<CommandStorageBackend::SessionInfo>
+absl::optional<CommandStorageBackend::SessionInfo>
CommandStorageBackend::FindLastSessionFile() const {
// Determine the session with the most recent timestamp. This is called
// at startup, before `current_path_` is set, so no need to check it.
@@ -815,7 +815,7 @@ CommandStorageBackend::FindLastSessionFile() const {
GetLegacySessionPath(type_, supplied_path_, true);
if (base::PathExists(legacy_session))
return SessionInfo{legacy_session, base::Time()};
- return base::nullopt;
+ return absl::nullopt;
}
void CommandStorageBackend::DeleteLastSessionFiles() const {
diff --git a/chromium/components/sessions/core/command_storage_backend.h b/chromium/components/sessions/core/command_storage_backend.h
index ad71b33e0c7..d6029cc8026 100644
--- a/chromium/components/sessions/core/command_storage_backend.h
+++ b/chromium/components/sessions/core/command_storage_backend.h
@@ -8,15 +8,16 @@
#include <stddef.h>
#include <memory>
+#include <set>
#include <vector>
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
-#include "base/optional.h"
#include "components/sessions/core/command_storage_manager.h"
#include "components/sessions/core/session_command.h"
#include "components/sessions/core/sessions_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class File;
@@ -206,7 +207,7 @@ class SESSIONS_EXPORT CommandStorageBackend
bool IsEncrypted() const { return !crypto_key_.empty(); }
// Gets data for the last session file.
- base::Optional<SessionInfo> FindLastSessionFile() const;
+ absl::optional<SessionInfo> FindLastSessionFile() const;
// Attempt to delete all sessions besides the current and last. This is a
// best effort operation.
@@ -268,9 +269,9 @@ class SESSIONS_EXPORT CommandStorageBackend
base::Time timestamp_;
// Data for the last session. If unset, fallback to legacy session data.
- base::Optional<SessionInfo> last_session_info_;
+ absl::optional<SessionInfo> last_session_info_;
- base::Optional<base::FilePath> last_file_with_valid_marker_;
+ absl::optional<base::FilePath> last_file_with_valid_marker_;
bool force_append_commands_to_fail_for_testing_ = false;
};
diff --git a/chromium/components/sessions/core/command_storage_backend_unittest.cc b/chromium/components/sessions/core/command_storage_backend_unittest.cc
index 4922c26a8e9..97855b67f31 100644
--- a/chromium/components/sessions/core/command_storage_backend_unittest.cc
+++ b/chromium/components/sessions/core/command_storage_backend_unittest.cc
@@ -96,7 +96,7 @@ class CommandStorageBackendTest : public testing::TestWithParam<bool> {
}
// Functions that call into private members of CommandStorageBackend.
- base::Optional<CommandStorageBackend::SessionInfo> GetLastSessionInfo(
+ absl::optional<CommandStorageBackend::SessionInfo> GetLastSessionInfo(
CommandStorageBackend* backend) {
// Force `last_session_info_` to be updated.
backend->InitIfNecessary();
diff --git a/chromium/components/sessions/core/live_tab_context.h b/chromium/components/sessions/core/live_tab_context.h
index afdb32603fd..fd5f3a7b6e1 100644
--- a/chromium/components/sessions/core/live_tab_context.h
+++ b/chromium/components/sessions/core/live_tab_context.h
@@ -8,12 +8,12 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "components/sessions/core/session_id.h"
#include "components/sessions/core/session_types.h"
#include "components/sessions/core/sessions_export.h"
#include "components/tab_groups/tab_group_id.h"
#include "components/tab_groups/tab_group_visual_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ui_base_types.h"
@@ -42,7 +42,7 @@ class SESSIONS_EXPORT LiveTabContext {
virtual LiveTab* GetLiveTabAt(int index) const = 0;
virtual LiveTab* GetActiveLiveTab() const = 0;
virtual bool IsTabPinned(int index) const = 0;
- virtual base::Optional<tab_groups::TabGroupId> GetTabGroupForTab(
+ virtual absl::optional<tab_groups::TabGroupId> GetTabGroupForTab(
int index) const = 0;
// Should not be called for |group| unless GetTabGroupForTab() returned
// |group|.
@@ -67,7 +67,7 @@ class SESSIONS_EXPORT LiveTabContext {
int tab_index,
int selected_navigation,
const std::string& extension_app_id,
- base::Optional<tab_groups::TabGroupId> group,
+ absl::optional<tab_groups::TabGroupId> group,
const tab_groups::TabGroupVisualData& group_visual_data,
bool select,
bool pin,
@@ -80,7 +80,7 @@ class SESSIONS_EXPORT LiveTabContext {
// platform-specific data).
virtual LiveTab* ReplaceRestoredTab(
const std::vector<SerializedNavigationEntry>& navigations,
- base::Optional<tab_groups::TabGroupId> group,
+ absl::optional<tab_groups::TabGroupId> group,
int selected_navigation,
const std::string& extension_app_id,
const PlatformSpecificTabData* tab_platform_data,
diff --git a/chromium/components/sessions/core/serialized_navigation_entry.h b/chromium/components/sessions/core/serialized_navigation_entry.h
index e59b558b35b..448d5a9924b 100644
--- a/chromium/components/sessions/core/serialized_navigation_entry.h
+++ b/chromium/components/sessions/core/serialized_navigation_entry.h
@@ -13,9 +13,9 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/sessions/core/sessions_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
@@ -144,12 +144,12 @@ class SESSIONS_EXPORT SerializedNavigationEntry {
base::Time first_timestamp;
ui::PageTransition first_transition_type;
};
- const base::Optional<ReplacedNavigationEntryData>& replaced_entry_data()
+ const absl::optional<ReplacedNavigationEntryData>& replaced_entry_data()
const {
return replaced_entry_data_;
}
void set_replaced_entry_data(
- const base::Optional<ReplacedNavigationEntryData>& replaced_entry_data) {
+ const absl::optional<ReplacedNavigationEntryData>& replaced_entry_data) {
replaced_entry_data_ = replaced_entry_data;
}
@@ -201,7 +201,7 @@ class SESSIONS_EXPORT SerializedNavigationEntry {
int http_status_code_ = 0;
bool is_restored_ = false; // Not persisted.
std::vector<GURL> redirect_chain_; // Not persisted.
- base::Optional<ReplacedNavigationEntryData>
+ absl::optional<ReplacedNavigationEntryData>
replaced_entry_data_; // Not persisted.
// Additional information.
diff --git a/chromium/components/sessions/core/serialized_user_agent_override.h b/chromium/components/sessions/core/serialized_user_agent_override.h
index 6d91a68328f..2d67410086b 100644
--- a/chromium/components/sessions/core/serialized_user_agent_override.h
+++ b/chromium/components/sessions/core/serialized_user_agent_override.h
@@ -7,8 +7,8 @@
#include <string>
-#include "base/optional.h"
#include "components/sessions/core/sessions_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sessions {
@@ -45,7 +45,7 @@ struct SESSIONS_EXPORT SerializedUserAgentOverride {
// Override of user-agent client hints. Format is user dependent; content/
// encodes it via blink::UserAgentMetadata::Marshal(). Should be nullopt
// if |ua_string_override| is empty.
- base::Optional<std::string> opaque_ua_metadata_override;
+ absl::optional<std::string> opaque_ua_metadata_override;
};
} // namespace sessions
diff --git a/chromium/components/sessions/core/session_service_commands.cc b/chromium/components/sessions/core/session_service_commands.cc
index cace1749429..fda030d6a79 100644
--- a/chromium/components/sessions/core/session_service_commands.cc
+++ b/chromium/components/sessions/core/session_service_commands.cc
@@ -633,9 +633,9 @@ bool CreateTabsAndWindows(
const base::Token token(payload.maybe_group.id_high,
payload.maybe_group.id_low);
session_tab->group =
- payload.has_group ? base::make_optional(
+ payload.has_group ? absl::make_optional(
tab_groups::TabGroupId::FromRawToken(token))
- : base::nullopt;
+ : absl::nullopt;
break;
}
@@ -643,7 +643,7 @@ bool CreateTabsAndWindows(
std::unique_ptr<base::Pickle> pickle = command->PayloadAsPickle();
base::PickleIterator iter(*pickle);
- base::Optional<base::Token> group_token = ReadTokenFromPickle(&iter);
+ absl::optional<base::Token> group_token = ReadTokenFromPickle(&iter);
if (!group_token.has_value())
return true;
@@ -715,14 +715,14 @@ bool CreateTabsAndWindows(
SessionTab* tab = GetTab(tab_id, tabs);
tab->user_agent_override.ua_string_override.swap(user_agent_override);
- tab->user_agent_override.opaque_ua_metadata_override = base::nullopt;
+ tab->user_agent_override.opaque_ua_metadata_override = absl::nullopt;
break;
}
case kCommandSetTabUserAgentOverride2: {
SessionID tab_id = SessionID::InvalidValue();
std::string user_agent_override;
- base::Optional<std::string> opaque_ua_metadata_override;
+ absl::optional<std::string> opaque_ua_metadata_override;
if (!RestoreSetTabUserAgentOverrideCommand2(
*command, &tab_id, &user_agent_override,
&opaque_ua_metadata_override)) {
@@ -947,7 +947,7 @@ std::unique_ptr<SessionCommand> CreateSetWindowTypeCommand(
std::unique_ptr<SessionCommand> CreateTabGroupCommand(
const SessionID& tab_id,
- base::Optional<tab_groups::TabGroupId> group) {
+ absl::optional<tab_groups::TabGroupId> group) {
TabGroupPayload payload = {0};
payload.tab_id = tab_id.id();
if (group.has_value()) {
diff --git a/chromium/components/sessions/core/session_service_commands.h b/chromium/components/sessions/core/session_service_commands.h
index 202b7c69b24..0aeaf8b201f 100644
--- a/chromium/components/sessions/core/session_service_commands.h
+++ b/chromium/components/sessions/core/session_service_commands.h
@@ -9,13 +9,13 @@
#include <memory>
#include <string>
-#include "base/optional.h"
#include "components/sessions/core/command_storage_manager.h"
#include "components/sessions/core/session_command.h"
#include "components/sessions/core/session_types.h"
#include "components/sessions/core/sessions_export.h"
#include "components/tab_groups/tab_group_id.h"
#include "components/tab_groups/tab_group_visual_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/ui_base_types.h"
namespace sessions {
@@ -46,7 +46,7 @@ SESSIONS_EXPORT std::unique_ptr<SessionCommand> CreateSetWindowTypeCommand(
SessionWindow::WindowType type);
SESSIONS_EXPORT std::unique_ptr<SessionCommand> CreateTabGroupCommand(
const SessionID& tab_id,
- base::Optional<tab_groups::TabGroupId> group);
+ absl::optional<tab_groups::TabGroupId> group);
SESSIONS_EXPORT std::unique_ptr<SessionCommand>
CreateTabGroupMetadataUpdateCommand(
const tab_groups::TabGroupId group,
diff --git a/chromium/components/sessions/core/session_types.h b/chromium/components/sessions/core/session_types.h
index 8d373c96ff3..360b1e0817b 100644
--- a/chromium/components/sessions/core/session_types.h
+++ b/chromium/components/sessions/core/session_types.h
@@ -11,7 +11,6 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/token.h"
#include "components/sessions/core/serialized_navigation_entry.h"
@@ -21,6 +20,7 @@
#include "components/tab_groups/tab_group_id.h"
#include "components/tab_groups/tab_group_visual_data.h"
#include "components/variations/variations_associated_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/color_palette.h"
@@ -72,7 +72,7 @@ struct SESSIONS_EXPORT SessionTab {
int current_navigation_index;
// The tab's group ID, if any.
- base::Optional<tab_groups::TabGroupId> group;
+ absl::optional<tab_groups::TabGroupId> group;
// True if the tab is pinned.
bool pinned;
diff --git a/chromium/components/sessions/core/tab_restore_service.h b/chromium/components/sessions/core/tab_restore_service.h
index 899efe6c398..83f35342474 100644
--- a/chromium/components/sessions/core/tab_restore_service.h
+++ b/chromium/components/sessions/core/tab_restore_service.h
@@ -11,7 +11,6 @@
#include <vector>
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/token.h"
#include "components/keyed_service/core/keyed_service.h"
@@ -23,6 +22,7 @@
#include "components/sessions/core/sessions_export.h"
#include "components/tab_groups/tab_group_id.h"
#include "components/tab_groups/tab_group_visual_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/ui_base_types.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/geometry/rect.h"
@@ -123,10 +123,10 @@ class SESSIONS_EXPORT TabRestoreService : public KeyedService {
SerializedUserAgentOverride user_agent_override;
// The group the tab belonged to, if any.
- base::Optional<tab_groups::TabGroupId> group;
+ absl::optional<tab_groups::TabGroupId> group;
// The group metadata for the tab, if any.
- base::Optional<tab_groups::TabGroupVisualData> group_visual_data;
+ absl::optional<tab_groups::TabGroupVisualData> group_visual_data;
};
// Represents a previously open window.
@@ -196,7 +196,7 @@ class SESSIONS_EXPORT TabRestoreService : public KeyedService {
// Creates a Tab to represent |live_tab| and notifies observers the list of
// entries has changed. If successful, returns the unique SessionID associated
// with the Tab.
- virtual base::Optional<SessionID> CreateHistoricalTab(LiveTab* live_tab,
+ virtual absl::optional<SessionID> CreateHistoricalTab(LiveTab* live_tab,
int index) = 0;
// Creates a Group to represent a tab group with ID |id|, containing group
diff --git a/chromium/components/sessions/core/tab_restore_service_helper.cc b/chromium/components/sessions/core/tab_restore_service_helper.cc
index 0b18d3c0101..01ff463d542 100644
--- a/chromium/components/sessions/core/tab_restore_service_helper.cc
+++ b/chromium/components/sessions/core/tab_restore_service_helper.cc
@@ -91,23 +91,23 @@ void TabRestoreServiceHelper::RemoveObserver(
observer_list_.RemoveObserver(observer);
}
-base::Optional<SessionID> TabRestoreServiceHelper::CreateHistoricalTab(
+absl::optional<SessionID> TabRestoreServiceHelper::CreateHistoricalTab(
LiveTab* live_tab,
int index) {
if (restoring_)
- return base::nullopt;
+ return absl::nullopt;
// If an entire window or group is being closed than all of the tabs have
// already been persisted via "BrowserClosing" or "CreateHistoricalGroup".
// Ignore the subsequent tab closing notifications.
LiveTabContext* context = client_->FindLiveTabContextForTab(live_tab);
if (closing_contexts_.find(context) != closing_contexts_.end())
- return base::nullopt;
- base::Optional<tab_groups::TabGroupId> group =
- context ? context->GetTabGroupForTab(index) : base::nullopt;
+ return absl::nullopt;
+ absl::optional<tab_groups::TabGroupId> group =
+ context ? context->GetTabGroupForTab(index) : absl::nullopt;
if (group.has_value() &&
closing_groups_.find(group.value()) != closing_groups_.end()) {
- return base::nullopt;
+ return absl::nullopt;
}
// Save the Window as well as the Tab if this is the last tab of an appp
@@ -115,13 +115,13 @@ base::Optional<SessionID> TabRestoreServiceHelper::CreateHistoricalTab(
if (context && context->GetTabCount() == 1 &&
!context->GetAppName().empty()) {
BrowserClosing(context);
- return base::nullopt;
+ return absl::nullopt;
}
auto local_tab = std::make_unique<Tab>();
PopulateTab(local_tab.get(), index, context, live_tab);
if (local_tab->navigations.empty())
- return base::nullopt;
+ return absl::nullopt;
SessionID id = local_tab->id;
AddEntry(std::move(local_tab), true, true);
@@ -444,7 +444,7 @@ std::vector<LiveTab*> TabRestoreServiceHelper::RestoreEntryById(
// Relabel group IDs to prevent duplicating groups, e.g. if the same
// window is restored twice or a tab of the same ID is restored
// elsewhere. See crbug.com/1202102.
- base::Optional<tab_groups::TabGroupId> new_group;
+ absl::optional<tab_groups::TabGroupId> new_group;
if (tab.group) {
auto it = new_group_ids.find(*tab.group);
if (it == new_group_ids.end()) {
@@ -776,11 +776,11 @@ void TabRestoreServiceHelper::PopulateTab(Tab* tab,
tab->group = context->GetTabGroupForTab(tab->tabstrip_index);
tab->group_visual_data =
tab->group.has_value()
- ? base::Optional<
+ ? absl::optional<
tab_groups::TabGroupVisualData>{*context
->GetVisualDataForGroup(
tab->group.value())}
- : base::nullopt;
+ : absl::nullopt;
}
}
@@ -792,7 +792,7 @@ LiveTabContext* TabRestoreServiceHelper::RestoreTab(
LiveTab* restored_tab;
if (disposition == WindowOpenDisposition::CURRENT_TAB && context) {
restored_tab = context->ReplaceRestoredTab(
- tab.navigations, base::nullopt, tab.current_navigation_index,
+ tab.navigations, absl::nullopt, tab.current_navigation_index,
tab.extension_app_id, tab.platform_data.get(), tab.user_agent_override);
} else {
// We only respect the tab's original browser if there's no disposition.
diff --git a/chromium/components/sessions/core/tab_restore_service_helper.h b/chromium/components/sessions/core/tab_restore_service_helper.h
index c4687a7614e..086a996de70 100644
--- a/chromium/components/sessions/core/tab_restore_service_helper.h
+++ b/chromium/components/sessions/core/tab_restore_service_helper.h
@@ -10,7 +10,6 @@
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/trace_event/memory_dump_provider.h"
#include "build/build_config.h"
@@ -18,6 +17,7 @@
#include "components/sessions/core/session_types.h"
#include "components/sessions/core/sessions_export.h"
#include "components/sessions/core/tab_restore_service.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sessions {
@@ -86,7 +86,7 @@ class SESSIONS_EXPORT TabRestoreServiceHelper
// Helper methods used to implement TabRestoreService.
void AddObserver(TabRestoreServiceObserver* observer);
void RemoveObserver(TabRestoreServiceObserver* observer);
- base::Optional<SessionID> CreateHistoricalTab(LiveTab* live_tab, int index);
+ absl::optional<SessionID> CreateHistoricalTab(LiveTab* live_tab, int index);
void BrowserClosing(LiveTabContext* context);
void BrowserClosed(LiveTabContext* context);
void CreateHistoricalGroup(LiveTabContext* context,
diff --git a/chromium/components/sessions/core/tab_restore_service_impl.cc b/chromium/components/sessions/core/tab_restore_service_impl.cc
index fa355350cd6..6d5f24171a8 100644
--- a/chromium/components/sessions/core/tab_restore_service_impl.cc
+++ b/chromium/components/sessions/core/tab_restore_service_impl.cc
@@ -1024,7 +1024,7 @@ void TabRestoreServiceImpl::PersistenceDelegate::CreateEntriesFromCommands(
}
std::unique_ptr<base::Pickle> pickle(command.PayloadAsPickle());
base::PickleIterator iter(*pickle);
- base::Optional<base::Token> group_token = ReadTokenFromPickle(&iter);
+ absl::optional<base::Token> group_token = ReadTokenFromPickle(&iter);
std::u16string title;
uint32_t color_int;
if (!iter.ReadString16(&title)) {
@@ -1087,7 +1087,7 @@ void TabRestoreServiceImpl::PersistenceDelegate::CreateEntriesFromCommands(
current_tab->user_agent_override.ua_string_override.swap(
user_agent_override);
current_tab->user_agent_override.opaque_ua_metadata_override =
- base::nullopt;
+ absl::nullopt;
break;
}
@@ -1098,7 +1098,7 @@ void TabRestoreServiceImpl::PersistenceDelegate::CreateEntriesFromCommands(
}
SessionID tab_id = SessionID::InvalidValue();
std::string user_agent_override;
- base::Optional<std::string> opaque_ua_metadata_override;
+ absl::optional<std::string> opaque_ua_metadata_override;
if (!RestoreSetTabUserAgentOverrideCommand2(
command, &tab_id, &user_agent_override,
&opaque_ua_metadata_override)) {
@@ -1288,7 +1288,7 @@ void TabRestoreServiceImpl::RemoveObserver(
helper_.RemoveObserver(observer);
}
-base::Optional<SessionID> TabRestoreServiceImpl::CreateHistoricalTab(
+absl::optional<SessionID> TabRestoreServiceImpl::CreateHistoricalTab(
LiveTab* live_tab,
int index) {
return helper_.CreateHistoricalTab(live_tab, index);
diff --git a/chromium/components/sessions/core/tab_restore_service_impl.h b/chromium/components/sessions/core/tab_restore_service_impl.h
index 136087b54fe..98187d5a87c 100644
--- a/chromium/components/sessions/core/tab_restore_service_impl.h
+++ b/chromium/components/sessions/core/tab_restore_service_impl.h
@@ -10,12 +10,12 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/sessions/core/sessions_export.h"
#include "components/sessions/core/tab_restore_service.h"
#include "components/sessions/core/tab_restore_service_client.h"
#include "components/sessions/core/tab_restore_service_helper.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class PrefService;
class TabRestoreServiceImplTest;
@@ -35,7 +35,7 @@ class SESSIONS_EXPORT TabRestoreServiceImpl : public TabRestoreService {
// TabRestoreService:
void AddObserver(TabRestoreServiceObserver* observer) override;
void RemoveObserver(TabRestoreServiceObserver* observer) override;
- base::Optional<SessionID> CreateHistoricalTab(LiveTab* live_tab,
+ absl::optional<SessionID> CreateHistoricalTab(LiveTab* live_tab,
int index) override;
void BrowserClosing(LiveTabContext* context) override;
void BrowserClosed(LiveTabContext* context) override;
diff --git a/chromium/components/sessions/ios/OWNERS b/chromium/components/sessions/ios/OWNERS
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/components/sessions/ios/OWNERS
+++ /dev/null
diff --git a/chromium/components/shared_highlighting/core/common/shared_highlighting_features.cc b/chromium/components/shared_highlighting/core/common/shared_highlighting_features.cc
index e0cb0dd95d8..671104342ea 100644
--- a/chromium/components/shared_highlighting/core/common/shared_highlighting_features.cc
+++ b/chromium/components/shared_highlighting/core/common/shared_highlighting_features.cc
@@ -10,10 +10,17 @@ namespace shared_highlighting {
const base::Feature kPreemptiveLinkToTextGeneration{
"PreemptiveLinkToTextGeneration", base::FEATURE_DISABLED_BY_DEFAULT};
+constexpr base::FeatureParam<int> kPreemptiveLinkGenTimeoutLengthMs{
+ &kPreemptiveLinkToTextGeneration, "TimeoutLengthMs", 500};
const base::Feature kSharedHighlightingUseBlocklist{
"SharedHighlightingUseBlocklist", base::FEATURE_ENABLED_BY_DEFAULT};
+
const base::Feature kSharedHighlightingV2{"SharedHighlightingV2",
base::FEATURE_DISABLED_BY_DEFAULT};
+int GetPreemptiveLinkGenTimeoutLengthMs() {
+ return kPreemptiveLinkGenTimeoutLengthMs.Get();
+}
+
} // namespace shared_highlighting
diff --git a/chromium/components/shared_highlighting/core/common/shared_highlighting_features.h b/chromium/components/shared_highlighting/core/common/shared_highlighting_features.h
index 7dc99890b53..fa177ad3cbb 100644
--- a/chromium/components/shared_highlighting/core/common/shared_highlighting_features.h
+++ b/chromium/components/shared_highlighting/core/common/shared_highlighting_features.h
@@ -5,6 +5,8 @@
#ifndef COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_SHARED_HIGHLIGHTING_FEATURES_H_
#define COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_SHARED_HIGHLIGHTING_FEATURES_H_
+#include "base/metrics/field_trial_params.h"
+
namespace base {
struct Feature;
}
@@ -13,12 +15,19 @@ namespace shared_highlighting {
// Enables link to text to be generated in advance.
extern const base::Feature kPreemptiveLinkToTextGeneration;
+// Sets the timeout length for pre-emptive link generation.
+extern const base::FeatureParam<int> kPreemptiveLinkGenTimeoutLengthMs;
// If enabled, a blocklist will disable link generation on certain pages where
// the feature is unlikely to work correctly.
extern const base::Feature kSharedHighlightingUseBlocklist;
+
+// Enables the new UI features for highlighted text.
extern const base::Feature kSharedHighlightingV2;
+// Returns the pre-emptive link generation timeout length.
+int GetPreemptiveLinkGenTimeoutLengthMs();
+
} // namespace shared_highlighting
#endif // COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_SHARED_HIGHLIGHTING_FEATURES_H_
diff --git a/chromium/components/shared_highlighting/core/common/shared_highlighting_metrics.cc b/chromium/components/shared_highlighting/core/common/shared_highlighting_metrics.cc
index a30e7833715..ba30c06a542 100644
--- a/chromium/components/shared_highlighting/core/common/shared_highlighting_metrics.cc
+++ b/chromium/components/shared_highlighting/core/common/shared_highlighting_metrics.cc
@@ -22,6 +22,11 @@ TextFragmentLinkOpenSource GetLinkSource(const GURL& referrer) {
} // namespace
+void LogDesktopLinkGenerationCopiedLinkType(LinkGenerationCopiedLinkType type) {
+ base::UmaHistogramEnumeration("SharedHighlights.Desktop.CopiedLinkType",
+ type);
+}
+
void LogLinkGenerationErrorReason(LinkGenerationError reason) {
base::UmaHistogramEnumeration("SharedHighlights.LinkGenerated.Error", reason);
}
diff --git a/chromium/components/shared_highlighting/core/common/shared_highlighting_metrics.h b/chromium/components/shared_highlighting/core/common/shared_highlighting_metrics.h
index ce3ff6f0e86..ec128930401 100644
--- a/chromium/components/shared_highlighting/core/common/shared_highlighting_metrics.h
+++ b/chromium/components/shared_highlighting/core/common/shared_highlighting_metrics.h
@@ -14,6 +14,16 @@ namespace shared_highlighting {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
+// The type of copied Shared Highlighting Link on Desktop.
+// Update corresponding |LinkGenerationCopiedLinkType| in enums.xml.
+enum class LinkGenerationCopiedLinkType {
+ kCopiedFromNewGeneration = 0,
+ kCopiedFromExistingHighlight = 1,
+ kMaxValue = kCopiedFromExistingHighlight
+};
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
// The type of errors that can happen during link generation.
// Update corresponding |LinkGenerationError| in enums.xml.
enum class LinkGenerationError {
@@ -55,6 +65,9 @@ enum class TextFragmentLinkOpenSource {
kMaxValue = kSearchEngine,
};
+// Records the type of link generation that was copied on desktop.
+void LogDesktopLinkGenerationCopiedLinkType(LinkGenerationCopiedLinkType type);
+
// Records the reason why the link generation failed.
void LogLinkGenerationErrorReason(LinkGenerationError reason);
diff --git a/chromium/components/shared_highlighting/core/common/text_fragment.cc b/chromium/components/shared_highlighting/core/common/text_fragment.cc
index 3e489ece6dc..f7eeb49d25f 100644
--- a/chromium/components/shared_highlighting/core/common/text_fragment.cc
+++ b/chromium/components/shared_highlighting/core/common/text_fragment.cc
@@ -63,7 +63,7 @@ TextFragment::TextFragment(const TextFragment& other)
TextFragment::~TextFragment() = default;
// static
-base::Optional<TextFragment> TextFragment::FromEscapedString(
+absl::optional<TextFragment> TextFragment::FromEscapedString(
std::string escaped_string) {
// Text fragments have the format: [prefix-,]textStart[,textEnd][,-suffix]
// That is, textStart is the only required param, all params are separated by
@@ -93,7 +93,7 @@ base::Optional<TextFragment> TextFragment::FromEscapedString(
if (pieces.size() > 2 || pieces.empty() || pieces[0].empty()) {
// Malformed if no piece is left for the textStart
- return base::nullopt;
+ return absl::nullopt;
}
std::string text_start = pieces[0];
@@ -105,7 +105,7 @@ base::Optional<TextFragment> TextFragment::FromEscapedString(
suffix.find_first_of("&-,") != std::string::npos) {
// Malformed if any of the pieces contain characters that are supposed to be
// URL-encoded.
- return base::nullopt;
+ return absl::nullopt;
}
return TextFragment(Unescape(text_start), Unescape(text_end),
@@ -113,9 +113,9 @@ base::Optional<TextFragment> TextFragment::FromEscapedString(
}
// static
-base::Optional<TextFragment> TextFragment::FromValue(const base::Value* value) {
+absl::optional<TextFragment> TextFragment::FromValue(const base::Value* value) {
if (!value || !value->is_dict()) {
- return base::nullopt;
+ return absl::nullopt;
}
const std::string* text_start = value->FindStringKey(kFragmentTextStartKey);
@@ -125,7 +125,7 @@ base::Optional<TextFragment> TextFragment::FromValue(const base::Value* value) {
if (!HasValue(text_start)) {
// Text Start is the only required parameter.
- return base::nullopt;
+ return absl::nullopt;
}
return TextFragment(*text_start, ValueOrDefault(text_end),
diff --git a/chromium/components/shared_highlighting/core/common/text_fragment.h b/chromium/components/shared_highlighting/core/common/text_fragment.h
index bdb55ffb823..ff6a312ced6 100644
--- a/chromium/components/shared_highlighting/core/common/text_fragment.h
+++ b/chromium/components/shared_highlighting/core/common/text_fragment.h
@@ -7,8 +7,8 @@
#include <string>
-#include "base/optional.h"
#include "base/values.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace shared_highlighting {
@@ -29,15 +29,15 @@ class TextFragment {
// special characters have been escaped. The given string is expected to have
// the traditional text fragment format:
// [prefix-,]textStart[,textEnd][,-suffix]
- // Returns |base::nullopt| if parsing failed.
- static base::Optional<TextFragment> FromEscapedString(
+ // Returns |absl::nullopt| if parsing failed.
+ static absl::optional<TextFragment> FromEscapedString(
std::string escaped_string);
// Returns a TextFragment instance created from a dictionary |value|
// containing the right set of values. The values stored in |value| must be
// already unescaped.
- // Returns |base::nullopt| if parsing failed.
- static base::Optional<TextFragment> FromValue(const base::Value* value);
+ // Returns |absl::nullopt| if parsing failed.
+ static absl::optional<TextFragment> FromValue(const base::Value* value);
const std::string text_start() const { return text_start_; }
const std::string text_end() const { return text_end_; }
diff --git a/chromium/components/shared_highlighting/core/common/text_fragment_unittest.cc b/chromium/components/shared_highlighting/core/common/text_fragment_unittest.cc
index 43259aa1c27..e9cec761023 100644
--- a/chromium/components/shared_highlighting/core/common/text_fragment_unittest.cc
+++ b/chromium/components/shared_highlighting/core/common/text_fragment_unittest.cc
@@ -13,7 +13,7 @@ namespace shared_highlighting {
namespace {
base::Value TextFragmentToValue(const std::string& fragment) {
- base::Optional<TextFragment> opt_frag =
+ absl::optional<TextFragment> opt_frag =
TextFragment::FromEscapedString(fragment);
return opt_frag ? opt_frag->ToValue() : base::Value(base::Value::Type::NONE);
}
@@ -165,7 +165,7 @@ TEST(TextFragmentTest, FromValue) {
fragment_value.SetStringKey(kFragmentPrefixKey, prefix);
fragment_value.SetStringKey(kFragmentSuffixKey, suffix);
- base::Optional<TextFragment> opt_fragment =
+ absl::optional<TextFragment> opt_fragment =
TextFragment::FromValue(&fragment_value);
EXPECT_TRUE(opt_fragment.has_value());
TextFragment fragment = opt_fragment.value();
diff --git a/chromium/components/shared_highlighting/core/common/text_fragments_utils.cc b/chromium/components/shared_highlighting/core/common/text_fragments_utils.cc
index 0247e88b19f..8408a0ab7bb 100644
--- a/chromium/components/shared_highlighting/core/common/text_fragments_utils.cc
+++ b/chromium/components/shared_highlighting/core/common/text_fragments_utils.cc
@@ -7,12 +7,12 @@
#include <sstream>
#include "base/json/json_writer.h"
-#include "base/optional.h"
#include "base/strings/escape.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "components/shared_highlighting/core/common/text_fragment.h"
#include "components/shared_highlighting/core/common/text_fragments_constants.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace shared_highlighting {
@@ -25,7 +25,7 @@ base::Value ParseTextFragments(const GURL& url) {
base::Value parsed(base::Value::Type::LIST);
for (const std::string& fragment : fragments) {
- base::Optional<TextFragment> opt_frag =
+ absl::optional<TextFragment> opt_frag =
TextFragment::FromEscapedString(fragment);
if (opt_frag.has_value()) {
parsed.Append(opt_frag->ToValue());
@@ -108,8 +108,28 @@ GURL AppendFragmentDirectives(const GURL& base_url,
fragment_strings.push_back(fragment_string);
}
}
+ return AppendFragmentDirectives(base_url, fragment_strings);
+}
+
+GURL AppendSelectors(const GURL& base_url, std::vector<std::string> selectors) {
+ if (!base_url.is_valid()) {
+ return GURL();
+ }
+
+ std::vector<std::string> fragment_strings;
+ for (std::string& selector : selectors) {
+ if (!selector.empty()) {
+ fragment_strings.push_back(kFragmentParameterName + selector);
+ }
+ }
+
+ return AppendFragmentDirectives(base_url, fragment_strings);
+}
+
+GURL AppendFragmentDirectives(const GURL& base_url,
+ std::vector<std::string> directives) {
+ std::string fragments_string = base::JoinString(directives, "&");
- std::string fragments_string = base::JoinString(fragment_strings, "&");
if (fragments_string.empty()) {
return base_url;
}
diff --git a/chromium/components/shared_highlighting/core/common/text_fragments_utils.h b/chromium/components/shared_highlighting/core/common/text_fragments_utils.h
index d68409e9492..18c3bdbfbea 100644
--- a/chromium/components/shared_highlighting/core/common/text_fragments_utils.h
+++ b/chromium/components/shared_highlighting/core/common/text_fragments_utils.h
@@ -32,9 +32,32 @@ GURL RemoveTextFragments(const GURL& url);
// Appends a set of text |fragments| with the correct format to the given
// |base_url|. Returns an empty GURL if |base_url| is invalid.
+//
+// Example input:
+// TextFragment test_fragment("only,- start #2");
+// AppendFragmentDirectives(url, {test_fragment});
GURL AppendFragmentDirectives(const GURL& base_url,
std::vector<TextFragment> fragments);
+// Appends a set of text fragment |directives|, that have already been
+// converted to an escaped string, to the given |base_url|. Returns an
+// empty GURL if |base_url| is invalid.
+//
+// Example input:
+// TextFragment test_fragment("only,- start #2");
+// AppendFragmentDirectives(url, {test_fragment.ToEscapedString()});
+GURL AppendFragmentDirectives(const GURL& base_url,
+ std::vector<std::string> directives);
+
+// Appends a set of text |selectors|, the escaped strings used to identify
+// a text fragment, to the given |base_url|. Returns an empty GURL
+// if |base_url| is invalid.
+//
+// Example input:
+// std::string test_selector("only%2C%2D%20start%20%232");
+// AppendFragmentDirectives(url, {test_selector});
+GURL AppendSelectors(const GURL& base_url, std::vector<std::string> selectors);
+
} // namespace shared_highlighting
#endif // COMPONENTS_SHARED_HIGHLIGHTING_CORE_COMMON_TEXT_FRAGMENTS_UTILS_H_
diff --git a/chromium/components/shared_highlighting/core/common/text_fragments_utils_unittest.cc b/chromium/components/shared_highlighting/core/common/text_fragments_utils_unittest.cc
index 082cc17eaf7..b384155f982 100644
--- a/chromium/components/shared_highlighting/core/common/text_fragments_utils_unittest.cc
+++ b/chromium/components/shared_highlighting/core/common/text_fragments_utils_unittest.cc
@@ -164,5 +164,30 @@ TEST(TextFragmentsUtilsTest, AppendFragmentDirectivesTwoFragments) {
created_url.spec());
}
+TEST(TextFragmentsUtilsTest,
+ AppendSelectorsURLWithPoundAndExistingFragmentAndAnchor) {
+ GURL base_url("https://www.chromium.org/#SomeAnchor:~:text=some%20value");
+ std::string test_selector("only%20start");
+
+ GURL created_url = AppendSelectors(base_url, {test_selector});
+ EXPECT_EQ(
+ "https://www.chromium.org/"
+ "#SomeAnchor:~:text=only%20start",
+ created_url.spec());
+}
+
+TEST(TextFragmentsUtilsTest, AppendSelectorsTwoFragments) {
+ GURL base_url("https://www.chromium.org");
+ std::string first_test_selector("only start");
+ std::string second_test_selector("only%2C%2D%20start%20%232");
+
+ GURL created_url =
+ AppendSelectors(base_url, {first_test_selector, second_test_selector});
+ EXPECT_EQ(
+ "https://www.chromium.org/"
+ "#:~:text=only%20start&text=only%2C%2D%20start%20%232",
+ created_url.spec());
+}
+
} // namespace
} // namespace shared_highlighting
diff --git a/chromium/components/signin/OWNERS b/chromium/components/signin/OWNERS
index e2126a9765d..9dfe6d9bb76 100644
--- a/chromium/components/signin/OWNERS
+++ b/chromium/components/signin/OWNERS
@@ -1,3 +1,4 @@
+alexilin@chromium.org
bsazonov@chromium.org
droger@chromium.org
msalama@chromium.org
diff --git a/chromium/components/signin/core/browser/BUILD.gn b/chromium/components/signin/core/browser/BUILD.gn
index ed063470251..13e7ce4a768 100644
--- a/chromium/components/signin/core/browser/BUILD.gn
+++ b/chromium/components/signin/core/browser/BUILD.gn
@@ -20,6 +20,8 @@ static_library("browser") {
"account_reconcilor.h",
"account_reconcilor_delegate.cc",
"account_reconcilor_delegate.h",
+ "account_reconcilor_throttler.cc",
+ "account_reconcilor_throttler.h",
"chrome_connected_header_helper.cc",
"chrome_connected_header_helper.h",
"cookie_reminter.cc",
@@ -84,13 +86,23 @@ static_library("browser") {
"active_directory_account_reconcilor_delegate.cc",
"active_directory_account_reconcilor_delegate.h",
]
- deps += [ "//chromeos/tpm:tpm" ]
+ deps += [
+ "//chromeos/crosapi/mojom",
+ "//chromeos/tpm:tpm",
+ ]
sources -= [
"signin_status_metrics_provider.cc",
"signin_status_metrics_provider_delegate.cc",
]
}
+ if (is_chromeos_lacros) {
+ deps += [
+ "//chromeos/crosapi/mojom",
+ "//chromeos/lacros",
+ ]
+ }
+
if (!enable_dice_support) {
sources -= [
"dice_account_reconcilor_delegate.cc",
@@ -138,13 +150,24 @@ source_set("unit_tests") {
]
if (is_chromeos_ash) {
- deps += [ "//chromeos/tpm:test_support" ]
+ deps += [
+ "//chromeos/crosapi/mojom",
+ "//chromeos/tpm:test_support",
+ ]
sources -= [
"account_investigator_unittest.cc",
"signin_status_metrics_provider_unittest.cc",
]
}
+ if (is_chromeos_lacros) {
+ deps += [
+ "//chromeos/crosapi/mojom",
+ "//chromeos/lacros",
+ "//chromeos/lacros:test_support",
+ ]
+ }
+
if (!enable_dice_support) {
sources -= [ "dice_account_reconcilor_delegate_unittest.cc" ]
}
diff --git a/chromium/components/signin/core/browser/DEPS b/chromium/components/signin/core/browser/DEPS
index 080a1d60ee4..9712cbfae5a 100644
--- a/chromium/components/signin/core/browser/DEPS
+++ b/chromium/components/signin/core/browser/DEPS
@@ -11,5 +11,15 @@ specific_include_rules = {
"account_reconcilor_unittest.cc": [
"+chromeos/tpm/install_attributes.h",
"+chromeos/tpm/stub_install_attributes.h"
+ ],
+ # TODO(crbug.com/1198528): remove Lacros deps after the rollout.
+ "chrome_connected_header_helper.cc": [
+ "+chromeos/lacros/lacros_chrome_service_impl.h",
+ "+chromeos/crosapi/mojom/crosapi.mojom.h"
+ ],
+ "signin_header_helper_unittest.cc": [
+ "+chromeos/lacros/lacros_chrome_service_delegate.h",
+ "+chromeos/lacros/lacros_chrome_service_impl.h",
+ "+chromeos/lacros/lacros_test_helper.h"
]
}
diff --git a/chromium/components/signin/core/browser/about_signin_internals.cc b/chromium/components/signin/core/browser/about_signin_internals.cc
index 95f1a3ce24e..ef2abc091b7 100644
--- a/chromium/components/signin/core/browser/about_signin_internals.cc
+++ b/chromium/components/signin/core/browser/about_signin_internals.cc
@@ -203,6 +203,17 @@ std::string GetAccountConsistencyDescription(
return "";
}
+std::string GetSigninStatusDescription(
+ signin::IdentityManager* identity_manager) {
+ if (!identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSignin)) {
+ return "Not Signed In";
+ } else if (identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)) {
+ return "Signed In, Consented for Sync";
+ } else {
+ return "Signed In, Not Consented for Sync";
+ }
+}
+
} // anonymous namespace
AboutSigninInternals::AboutSigninInternals(
@@ -615,11 +626,8 @@ AboutSigninInternals::SigninStatus::ToValue(
AddSection(signin_info.get(), "Basic Information");
AddSectionEntry(basic_info, "Account Consistency",
GetAccountConsistencyDescription(account_consistency));
- AddSectionEntry(
- basic_info, "Signin Status",
- identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)
- ? "Signed In"
- : "Not Signed In");
+ AddSectionEntry(basic_info, "Signin Status",
+ GetSigninStatusDescription(identity_manager));
signin::LoadCredentialsState load_tokens_state =
identity_manager->GetDiagnosticsProvider()
->GetDetailedStateOfLoadingOfRefreshTokens();
@@ -629,9 +637,9 @@ AboutSigninInternals::SigninStatus::ToValue(
basic_info, "Gaia cookies state",
GetGaiaCookiesStateAsString(GetGaiaCookiesState(signin_client)));
- if (identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)) {
+ if (identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSignin)) {
CoreAccountInfo account_info =
- identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync);
+ identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin);
AddSectionEntry(basic_info,
SigninStatusFieldToLabel(signin_internals_util::ACCOUNT_ID),
account_info.account_id.ToString());
@@ -644,7 +652,7 @@ AboutSigninInternals::SigninStatus::ToValue(
if (signin_error_controller->HasError()) {
const CoreAccountId error_account_id =
signin_error_controller->error_account_id();
- const base::Optional<AccountInfo> error_account_info =
+ const absl::optional<AccountInfo> error_account_info =
identity_manager
->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
error_account_id);
diff --git a/chromium/components/signin/core/browser/account_investigator.cc b/chromium/components/signin/core/browser/account_investigator.cc
index 4924dd4b2ca..870e30210eb 100644
--- a/chromium/components/signin/core/browser/account_investigator.cc
+++ b/chromium/components/signin/core/browser/account_investigator.cc
@@ -37,12 +37,12 @@ bool AreSame(const CoreAccountInfo& info, const ListedAccount& account) {
// Returns the extended info for the primary account (no consent required) if
// available.
-base::Optional<AccountInfo> GetExtendedAccountInfo(
+absl::optional<AccountInfo> GetExtendedAccountInfo(
signin::IdentityManager* identity_manager) {
CoreAccountId account_id =
identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSignin);
if (account_id.empty())
- return base::nullopt;
+ return absl::nullopt;
return identity_manager
->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
account_id);
@@ -244,7 +244,7 @@ void AccountInvestigator::DoPeriodicReport(
if (identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSignin)) {
const bool is_syncing =
identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSync);
- base::Optional<AccountInfo> info =
+ absl::optional<AccountInfo> info =
GetExtendedAccountInfo(identity_manager_);
signin_metrics::LogSignedInCookiesCountsPerPrimaryAccountType(
signed_in_accounts.size(), is_syncing, info->IsManaged());
diff --git a/chromium/components/signin/core/browser/account_reconcilor.cc b/chromium/components/signin/core/browser/account_reconcilor.cc
index 35deb4520ad..57bb3635d06 100644
--- a/chromium/components/signin/core/browser/account_reconcilor.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor.cc
@@ -17,6 +17,8 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -175,6 +177,26 @@ bool HasUnknownInvalidAccountInCookie(
} // namespace
+// static
+const char AccountReconcilor::kOperationHistogramName[] =
+ "Signin.Reconciler.Operation";
+
+// static
+const char AccountReconcilor::kTriggerLogoutHistogramName[] =
+ "Signin.Reconciler.Trigger.Logout";
+
+// static
+const char AccountReconcilor::kTriggerMultiloginHistogramName[] =
+ "Signin.Reconciler.Trigger.Multilogin";
+
+// static
+const char AccountReconcilor::kTriggerNoopHistogramName[] =
+ "Signin.Reconciler.Trigger.Noop";
+
+// static
+const char AccountReconcilor::kTriggerThrottledHistogramName[] =
+ "Signin.Reconciler.Trigger.Throttled";
+
AccountReconcilor::Lock::Lock(AccountReconcilor* reconcilor)
: reconcilor_(reconcilor->weak_factory_.GetWeakPtr()) {
DCHECK(reconcilor_);
@@ -208,20 +230,7 @@ AccountReconcilor::AccountReconcilor(
std::unique_ptr<signin::AccountReconcilorDelegate> delegate)
: delegate_(std::move(delegate)),
identity_manager_(identity_manager),
- client_(client),
- registered_with_identity_manager_(false),
- registered_with_content_settings_(false),
- is_reconcile_started_(false),
- first_execution_(true),
- error_during_last_reconcile_(GoogleServiceAuthError::AuthErrorNone()),
- reconcile_is_noop_(true),
- set_accounts_in_progress_(false),
- log_out_in_progress_(false),
- chrome_accounts_changed_(false),
- account_reconcilor_lock_count_(0),
- reconcile_on_unblock_(false),
- timer_(new base::OneShotTimer),
- state_(signin_metrics::ACCOUNT_RECONCILOR_OK) {
+ client_(client) {
VLOG(1) << "AccountReconcilor::AccountReconcilor";
DCHECK(delegate_);
delegate_->set_reconcilor(this);
@@ -253,14 +262,14 @@ void AccountReconcilor::Initialize(bool start_reconcile_if_tokens_available) {
// Start a reconcile if the tokens are already loaded.
if (start_reconcile_if_tokens_available && IsIdentityManagerReady())
- StartReconcile();
+ StartReconcile(Trigger::kInitialized);
}
}
void AccountReconcilor::EnableReconcile() {
RegisterWithAllDependencies();
if (IsIdentityManagerReady())
- StartReconcile();
+ StartReconcile(Trigger::kEnableReconcile);
else
SetState(AccountReconcilorState::ACCOUNT_RECONCILOR_SCHEDULED);
}
@@ -360,7 +369,7 @@ void AccountReconcilor::OnContentSettingChanged(
}
VLOG(1) << "AccountReconcilor::OnContentSettingChanged";
- StartReconcile();
+ StartReconcile(Trigger::kCookieSettingChange);
}
void AccountReconcilor::OnEndBatchOfRefreshTokenStateChanges() {
@@ -368,11 +377,11 @@ void AccountReconcilor::OnEndBatchOfRefreshTokenStateChanges() {
<< "Reconcilor state: " << is_reconcile_started_;
// Remember that accounts have changed if a reconcile is already started.
chrome_accounts_changed_ = is_reconcile_started_;
- StartReconcile();
+ StartReconcile(Trigger::kTokenChange);
}
void AccountReconcilor::OnRefreshTokensLoaded() {
- StartReconcile();
+ StartReconcile(Trigger::kTokensLoaded);
}
void AccountReconcilor::OnErrorStateOfRefreshTokenUpdatedForAccount(
@@ -389,19 +398,8 @@ void AccountReconcilor::OnErrorStateOfRefreshTokenUpdatedForAccount(
identity_manager_->GetAccountsCookieMutator()->TriggerCookieJarUpdate();
}
-void AccountReconcilor::PerformMergeAction(const CoreAccountId& account_id) {
- DCHECK(!IsMultiloginEndpointEnabled());
- reconcile_is_noop_ = false;
- VLOG(1) << "AccountReconcilor::PerformMergeAction: " << account_id;
- identity_manager_->GetAccountsCookieMutator()->AddAccountToCookie(
- account_id, delegate_->GetGaiaApiSource(),
- base::BindOnce(&AccountReconcilor::OnAddAccountToCookieCompleted,
- weak_factory_.GetWeakPtr()));
-}
-
void AccountReconcilor::PerformSetCookiesAction(
const signin::MultiloginParameters& parameters) {
- DCHECK(IsMultiloginEndpointEnabled());
reconcile_is_noop_ = false;
VLOG(1) << "AccountReconcilor::PerformSetCookiesAction: "
<< base::JoinString(ToStringList(parameters.accounts_to_send), " ");
@@ -424,7 +422,7 @@ void AccountReconcilor::PerformLogoutAllAccountsAction() {
weak_factory_.GetWeakPtr()));
}
-void AccountReconcilor::StartReconcile() {
+void AccountReconcilor::StartReconcile(Trigger trigger) {
if (WasShutDown())
return;
@@ -459,11 +457,11 @@ void AccountReconcilor::StartReconcile() {
// Begin reconciliation. Reset initial states.
SetState(AccountReconcilorState::ACCOUNT_RECONCILOR_RUNNING);
- add_to_cookie_.clear();
reconcile_start_time_ = base::Time::Now();
is_reconcile_started_ = true;
error_during_last_reconcile_ = GoogleServiceAuthError::AuthErrorNone();
reconcile_is_noop_ = true;
+ trigger_ = trigger;
if (!timeout_.is_max()) {
timer_->Start(FROM_HERE, timeout_,
@@ -499,7 +497,6 @@ void AccountReconcilor::FinishReconcileWithMultiloginEndpoint(
const CoreAccountId& primary_account,
const std::vector<CoreAccountId>& chrome_accounts,
std::vector<gaia::ListedAccount>&& gaia_accounts) {
- DCHECK(IsMultiloginEndpointEnabled());
DCHECK(!set_accounts_in_progress_);
DCHECK(!log_out_in_progress_);
DCHECK_EQ(AccountReconcilorState::ACCOUNT_RECONCILOR_RUNNING, state_);
@@ -533,21 +530,37 @@ void AccountReconcilor::FinishReconcileWithMultiloginEndpoint(
primary_has_error);
}
if (CookieNeedsUpdate(parameters_for_multilogin, gaia_accounts)) {
- if (parameters_for_multilogin == kLogoutParameters) {
- // UPDATE mode does not support empty list of accounts, call logout
- // instead.
- log_out_in_progress_ = true;
- PerformLogoutAllAccountsAction();
+ // Verify the account reconcilor is not trapped into a loop of repeating the
+ // same request with the same params.
+ if (throttler_.TryMultiloginOperation(parameters_for_multilogin)) {
+ if (parameters_for_multilogin == kLogoutParameters) {
+ RecordReconcileOperation(trigger_, Operation::kLogout);
+ // UPDATE mode does not support empty list of accounts, call logout
+ // instead.
+ log_out_in_progress_ = true;
+ PerformLogoutAllAccountsAction();
+ } else {
+ // Reconcilor has to do some calls to gaia. is_reconcile_started_ is
+ // true and any StartReconcile() calls that are made in the meantime
+ // will be aborted until OnSetAccountsInCookieCompleted is called and
+ // is_reconcile_started_ is set to false.
+ RecordReconcileOperation(trigger_, Operation::kMultilogin);
+ set_accounts_in_progress_ = true;
+ PerformSetCookiesAction(parameters_for_multilogin);
+ }
} else {
- // Reconcilor has to do some calls to gaia. is_reconcile_started_ is true
- // and any StartReconcile() calls that are made in the meantime will be
- // aborted until OnSetAccountsInCookieCompleted is called and
- // is_reconcile_started_ is set to false.
- set_accounts_in_progress_ = true;
- PerformSetCookiesAction(parameters_for_multilogin);
+ // Too many requests with the same parameters led to a backoff time
+ // required between successive identical requests that has not yet passed.
+ error_during_last_reconcile_ =
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
+ CalculateIfMultiloginReconcileIsDone();
+ ScheduleStartReconcileIfChromeAccountsChanged();
+ RecordReconcileOperation(trigger_, Operation::kThrottled);
}
} else {
// Nothing to do, accounts already match.
+ RecordReconcileOperation(trigger_, Operation::kNoop);
+ throttler_.Reset();
error_during_last_reconcile_ = GoogleServiceAuthError::AuthErrorNone();
CalculateIfMultiloginReconcileIsDone();
@@ -585,16 +598,13 @@ void AccountReconcilor::OnAccountsInCookieUpdated(
// let it complete. Adding accounts to the cookie will trigger new
// notifications anyway, and these will be handled in a new reconciliation
// cycle. See https://crbug.com/923716
- if (IsMultiloginEndpointEnabled()) {
- if (set_accounts_in_progress_)
- return;
- } else {
- if (!add_to_cookie_.empty())
- return;
- }
+ //
+ // TODO(droger): Should we also check if |logout_in_progress_|?
+ if (set_accounts_in_progress_)
+ return;
if (!is_reconcile_started_) {
- StartReconcile();
+ StartReconcile(Trigger::kCookieChange);
return;
}
@@ -652,13 +662,8 @@ void AccountReconcilor::OnAccountsInCookieUpdated(
return;
}
- if (IsMultiloginEndpointEnabled()) {
- FinishReconcileWithMultiloginEndpoint(primary_account, chrome_accounts,
- std::move(verified_gaia_accounts));
- } else {
- FinishReconcile(primary_account, chrome_accounts,
- std::move(verified_gaia_accounts));
- }
+ FinishReconcileWithMultiloginEndpoint(primary_account, chrome_accounts,
+ std::move(verified_gaia_accounts));
}
void AccountReconcilor::OnAccountsCookieDeletedByUserAction() {
@@ -726,149 +731,15 @@ void AccountReconcilor::OnReceivedManageAccountsResponse(
}
}
-void AccountReconcilor::FinishReconcile(
- const CoreAccountId& primary_account,
- const std::vector<CoreAccountId>& chrome_accounts,
- std::vector<gaia::ListedAccount>&& gaia_accounts) {
- DCHECK(!IsMultiloginEndpointEnabled());
- VLOG(1) << "AccountReconcilor::FinishReconcile";
- DCHECK(add_to_cookie_.empty());
- DCHECK(delegate_->IsUnknownInvalidAccountInCookieAllowed())
- << "Only supported in UPDATE mode";
-
- size_t number_gaia_accounts = gaia_accounts.size();
- // If there are any accounts in the gaia cookie but not in chrome, then
- // those accounts need to be removed from the cookie. This means we need
- // to blow the cookie away.
- int removed_from_cookie = 0;
- for (size_t i = 0; i < number_gaia_accounts; ++i) {
- if (gaia_accounts[i].valid &&
- !base::Contains(chrome_accounts, gaia_accounts[i].id)) {
- ++removed_from_cookie;
- }
- }
-
- CoreAccountId first_account = delegate_->GetFirstGaiaAccountForReconcile(
- chrome_accounts, gaia_accounts, primary_account, first_execution_,
- removed_from_cookie > 0);
- bool first_account_mismatch =
- (number_gaia_accounts > 0) && (first_account != gaia_accounts[0].id);
-
- bool rebuild_cookie = first_account_mismatch || (removed_from_cookie > 0);
- std::vector<gaia::ListedAccount> original_gaia_accounts = gaia_accounts;
- if (rebuild_cookie) {
- VLOG(1) << "AccountReconcilor::FinishReconcile: rebuild cookie";
- // Really messed up state. Blow away the gaia cookie completely and
- // rebuild it, making sure the primary account as specified by the
- // IdentityManager is the first session in the gaia cookie.
- log_out_in_progress_ = true;
- PerformLogoutAllAccountsAction();
- gaia_accounts.clear();
- }
-
- if (first_account.empty()) {
- DCHECK(!delegate_->ShouldAbortReconcileIfPrimaryHasError());
- auto revoke_option =
- delegate_->ShouldRevokeTokensIfNoPrimaryAccount()
- ? AccountReconcilorDelegate::RevokeTokenOption::kRevoke
- : AccountReconcilorDelegate::RevokeTokenOption::kDoNotRevoke;
- reconcile_is_noop_ = !RevokeAllSecondaryTokens(
- identity_manager_, revoke_option, primary_account,
- signin_metrics::SourceForRefreshTokenOperation::
- kAccountReconcilor_Reconcile);
- } else {
- // Create a list of accounts that need to be added to the Gaia cookie.
- if (base::Contains(chrome_accounts, first_account)) {
- add_to_cookie_.push_back(first_account);
- } else {
- // If the first account is not empty and not in chrome_accounts, it is
- // impossible to rebuild it. It must be already the current default
- // account, and no logout can happen.
- DCHECK_EQ(gaia_accounts[0].id, first_account);
- DCHECK(!rebuild_cookie);
- }
- for (size_t i = 0; i < chrome_accounts.size(); ++i) {
- if (chrome_accounts[i] != first_account)
- add_to_cookie_.push_back(chrome_accounts[i]);
- }
- }
-
- // For each account known to chrome, PerformMergeAction() if the account is
- // not already in the cookie jar or its state is invalid, or signal merge
- // completed otherwise. Make a copy of |add_to_cookie_| since calls
- // to OnAddAccountToCookieCompleted() will change the array.
- 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 (ContainsGaiaAccount(gaia_accounts, add_to_cookie_copy[i])) {
- OnAddAccountToCookieCompleted(add_to_cookie_copy[i],
- GoogleServiceAuthError::AuthErrorNone());
- } else {
- PerformMergeAction(add_to_cookie_copy[i]);
- if (!ContainsGaiaAccount(original_gaia_accounts, add_to_cookie_copy[i])) {
- added_to_cookie++;
- }
- }
- }
-
- signin_metrics::LogSigninAccountReconciliation(
- chrome_accounts.size(), added_to_cookie, removed_from_cookie,
- !first_account_mismatch, first_execution_, number_gaia_accounts);
- first_execution_ = false;
- CalculateIfMergeSessionReconcileIsDone();
- if (!is_reconcile_started_)
- delegate_->OnReconcileFinished(first_account);
- ScheduleStartReconcileIfChromeAccountsChanged();
-}
-
void AccountReconcilor::AbortReconcile() {
VLOG(1) << "AccountReconcilor::AbortReconcile: try again later";
log_out_in_progress_ = false;
- if (IsMultiloginEndpointEnabled()) {
- set_accounts_in_progress_ = false;
- CalculateIfMultiloginReconcileIsDone();
- } else {
- add_to_cookie_.clear();
- CalculateIfMergeSessionReconcileIsDone();
- }
-
+ set_accounts_in_progress_ = false;
+ CalculateIfMultiloginReconcileIsDone();
DCHECK(!is_reconcile_started_);
DCHECK(!timer_->IsRunning());
}
-void AccountReconcilor::CalculateIfMergeSessionReconcileIsDone() {
- DCHECK(!IsMultiloginEndpointEnabled());
- base::TimeDelta duration = base::Time::Now() - reconcile_start_time_;
- // Record the duration if reconciliation was underway and now it is over.
- if (is_reconcile_started_ && add_to_cookie_.empty() &&
- !log_out_in_progress_) {
- bool was_last_reconcile_successful =
- (error_during_last_reconcile_.state() ==
- GoogleServiceAuthError::State::NONE);
- signin_metrics::LogSigninAccountReconciliationDuration(
- duration, was_last_reconcile_successful);
-
- // Reconciliation has actually finished (and hence stop the timer), but it
- // may have ended in some failures. Pass this information to the
- // |delegate_|.
- timer_->Stop();
- if (!was_last_reconcile_successful) {
- // Note: This is the only call to |OnReconcileError| in this file. We MUST
- // make sure that we do not call |OnReconcileError| multiple times in the
- // same reconciliation batch.
- // The enclosing if-condition |is_reconcile_started_ &&
- // add_to_cookie_.empty()| represents the halting condition for one batch
- // of reconciliation.
- delegate_->OnReconcileError(error_during_last_reconcile_);
- }
- }
-
- is_reconcile_started_ = !add_to_cookie_.empty() || log_out_in_progress_;
- if (!is_reconcile_started_)
- VLOG(1)
- << "AccountReconcilor::CalculateIfMergeSessionReconcileIsDone: done";
-}
-
void AccountReconcilor::ScheduleStartReconcileIfChromeAccountsChanged() {
if (is_reconcile_started_)
return;
@@ -883,7 +754,8 @@ void AccountReconcilor::ScheduleStartReconcileIfChromeAccountsChanged() {
SetState(AccountReconcilorState::ACCOUNT_RECONCILOR_SCHEDULED);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&AccountReconcilor::StartReconcile,
- base::Unretained(this)));
+ base::Unretained(this),
+ Trigger::kTokenChangeDuringReconcile));
} else if (error_during_last_reconcile_.state() ==
GoogleServiceAuthError::NONE) {
SetState(AccountReconcilorState::ACCOUNT_RECONCILOR_OK);
@@ -892,25 +764,12 @@ void AccountReconcilor::ScheduleStartReconcileIfChromeAccountsChanged() {
}
}
-// Remove the account from the list that is being merged.
-bool AccountReconcilor::MarkAccountAsAddedToCookie(
- const CoreAccountId& account_id) {
- for (auto i = add_to_cookie_.begin(); i != add_to_cookie_.end(); ++i) {
- if (account_id == *i) {
- add_to_cookie_.erase(i);
- return true;
- }
- }
- return false;
-}
-
bool AccountReconcilor::IsIdentityManagerReady() {
return identity_manager_->AreRefreshTokensLoaded();
}
void AccountReconcilor::OnSetAccountsInCookieCompleted(
signin::SetAccountsInCookieResult result) {
- DCHECK(IsMultiloginEndpointEnabled());
VLOG(1) << "AccountReconcilor::OnSetAccountsInCookieCompleted: "
<< "Error was " << static_cast<int>(result);
@@ -936,7 +795,6 @@ void AccountReconcilor::OnSetAccountsInCookieCompleted(
}
void AccountReconcilor::CalculateIfMultiloginReconcileIsDone() {
- DCHECK(IsMultiloginEndpointEnabled());
DCHECK(!set_accounts_in_progress_);
DCHECK(!log_out_in_progress_);
VLOG(1) << "AccountReconcilor::CalculateIfMultiloginReconcileIsDone: "
@@ -958,27 +816,6 @@ void AccountReconcilor::CalculateIfMultiloginReconcileIsDone() {
duration, was_last_reconcile_successful);
}
-void AccountReconcilor::OnAddAccountToCookieCompleted(
- const CoreAccountId& account_id,
- const GoogleServiceAuthError& error) {
- DCHECK(!IsMultiloginEndpointEnabled());
- VLOG(1) << "AccountReconcilor::OnAddAccountToCookieCompleted: "
- << "Account added: " << account_id << ", "
- << "Error was " << error.ToString();
- // Always listens to GaiaCookieManagerService. Only proceed if reconciling.
- if (is_reconcile_started_ && MarkAccountAsAddedToCookie(account_id)) {
- // We may have seen a series of errors during reconciliation. Delegates may
- // rely on the severity of the last seen error (see |OnReconcileError|) and
- // hence do not override a persistent error, if we have seen one.
- if (error.state() != GoogleServiceAuthError::State::NONE &&
- !error_during_last_reconcile_.IsPersistentError()) {
- error_during_last_reconcile_ = error;
- }
- CalculateIfMergeSessionReconcileIsDone();
- ScheduleStartReconcileIfChromeAccountsChanged();
- }
-}
-
void AccountReconcilor::OnLogOutFromCookieCompleted(
const GoogleServiceAuthError& error) {
VLOG(1) << "AccountReconcilor::OnLogOutFromCookieCompleted: "
@@ -995,13 +832,8 @@ void AccountReconcilor::OnLogOutFromCookieCompleted(
!error_during_last_reconcile_.IsPersistentError()) {
error_during_last_reconcile_ = error;
}
- if (IsMultiloginEndpointEnabled()) {
- CalculateIfMultiloginReconcileIsDone();
- ScheduleStartReconcileIfChromeAccountsChanged();
- } else {
- CalculateIfMergeSessionReconcileIsDone();
- ScheduleStartReconcileIfChromeAccountsChanged();
- }
+ CalculateIfMultiloginReconcileIsDone();
+ ScheduleStartReconcileIfChromeAccountsChanged();
}
}
@@ -1043,7 +875,7 @@ void AccountReconcilor::UnblockReconcile() {
observer.OnUnblockReconcile();
if (reconcile_on_unblock_) {
reconcile_on_unblock_ = false;
- StartReconcile();
+ StartReconcile(Trigger::kUnblockReconcile);
}
}
@@ -1064,15 +896,11 @@ void AccountReconcilor::HandleReconcileTimeout() {
// Will stop reconciliation and inform |delegate_| about
// |error_during_last_reconcile_|, through
- // |CalculateIfMergeSessionReconcileIsDone|.
+ // |CalculateIfReconcileIsDone|.
AbortReconcile();
DCHECK(!timer_->IsRunning());
}
-bool AccountReconcilor::IsMultiloginEndpointEnabled() const {
- return delegate_->IsMultiloginEndpointEnabled();
-}
-
bool AccountReconcilor::CookieNeedsUpdate(
const signin::MultiloginParameters& parameters,
const std::vector<gaia::ListedAccount>& existing_accounts) {
@@ -1118,3 +946,24 @@ void AccountReconcilor::SetState(AccountReconcilorState state) {
bool AccountReconcilor::WasShutDown() const {
return was_shut_down_;
}
+
+// static
+void AccountReconcilor::RecordReconcileOperation(Trigger trigger,
+ Operation operation) {
+ // Using the histogram macro for histogram that may be recorded in a loop.
+ UMA_HISTOGRAM_ENUMERATION(kOperationHistogramName, operation);
+ switch (operation) {
+ case Operation::kNoop:
+ base::UmaHistogramEnumeration(kTriggerNoopHistogramName, trigger);
+ break;
+ case Operation::kLogout:
+ base::UmaHistogramEnumeration(kTriggerLogoutHistogramName, trigger);
+ break;
+ case Operation::kMultilogin:
+ base::UmaHistogramEnumeration(kTriggerMultiloginHistogramName, trigger);
+ break;
+ case Operation::kThrottled:
+ UMA_HISTOGRAM_ENUMERATION(kTriggerThrottledHistogramName, trigger);
+ break;
+ }
+}
diff --git a/chromium/components/signin/core/browser/account_reconcilor.h b/chromium/components/signin/core/browser/account_reconcilor.h
index f31ab8d62db..fe573eeb0bd 100644
--- a/chromium/components/signin/core/browser/account_reconcilor.h
+++ b/chromium/components/signin/core/browser/account_reconcilor.h
@@ -5,10 +5,8 @@
#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_H_
#include <memory>
-#include <string>
#include <vector>
-#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -22,6 +20,7 @@
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
+#include "components/signin/core/browser/account_reconcilor_throttler.h"
#include "components/signin/core/browser/signin_header_helper.h"
#include "components/signin/public/base/signin_client.h"
#include "components/signin/public/base/signin_metrics.h"
@@ -127,8 +126,6 @@ class AccountReconcilor : public KeyedService,
bool IsReconcileBlocked() const;
protected:
- void OnAddAccountToCookieCompleted(const CoreAccountId& account_id,
- const GoogleServiceAuthError& error);
void OnSetAccountsInCookieCompleted(signin::SetAccountsInCookieResult result);
void OnLogOutFromCookieCompleted(const GoogleServiceAuthError& error);
@@ -136,6 +133,8 @@ class AccountReconcilor : public KeyedService,
friend class AccountReconcilorTest;
friend class DiceBrowserTest;
friend class BaseAccountReconcilorTestTable;
+ friend class AccountReconcilorThrottlerTest;
+ friend class AccountReconcilorTestForceDiceMigration;
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestForceDiceMigration,
TableRowTestCheckNoOp);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorMirrorTest,
@@ -151,21 +150,18 @@ class AccountReconcilor : public KeyedService,
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTestMiceMultilogin, TableRowTest);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorMiceTest,
AccountReconcilorStateScheduled);
- FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceEndpointParamTest,
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest,
DiceTokenServiceRegistration);
- FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceEndpointParamTest,
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest,
DiceReconcileWithoutSignin);
- FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceEndpointParamTest,
- DiceReconcileNoop);
- FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceEndpointParamTest,
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest, DiceReconcileNoop);
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest,
DiceLastKnownFirstAccount);
- FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceEndpointParamTest,
- UnverifiedAccountNoop);
- FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceEndpointParamTest,
- UnverifiedAccountMerge);
- FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceEndpointParamTest,
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest, UnverifiedAccountNoop);
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest, UnverifiedAccountMerge);
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest,
HandleSigninDuringReconcile);
- FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceEndpointParamTest,
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorDiceTest,
DiceReconcileReuseGaiaFirstAccount);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, DiceDeleteCookie);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorMirrorTest, TokensNotLoaded);
@@ -229,6 +225,39 @@ class AccountReconcilor : public KeyedService,
TableRowTestMultilogin);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, ReconcileAfterShutdown);
FRIEND_TEST_ALL_PREFIXES(AccountReconcilorTest, UnlockAfterShutdown);
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorThrottlerTest, RefillOneRequest);
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorThrottlerTest, RefillFiveRequests);
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorThrottlerTest,
+ NewRequestParamsPasses);
+ FRIEND_TEST_ALL_PREFIXES(AccountReconcilorThrottlerTest, BlockFiveRequests);
+
+ // Operation executed by the reconcilor.
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum class Operation {
+ kNoop = 0,
+ kLogout = 1,
+ kMultilogin = 2,
+ kThrottled = 3,
+
+ kMaxValue = kThrottled
+ };
+
+ // Event triggering a call to StartReconcile().
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum class Trigger {
+ kInitialized = 0,
+ kTokensLoaded = 1,
+ kEnableReconcile = 2,
+ kUnblockReconcile = 3,
+ kTokenChange = 4,
+ kTokenChangeDuringReconcile = 5,
+ kCookieChange = 6,
+ kCookieSettingChange = 7,
+
+ kMaxValue = kCookieSettingChange
+ };
void set_timer_for_testing(std::unique_ptr<base::OneShotTimer> timer);
@@ -246,27 +275,22 @@ class AccountReconcilor : public KeyedService,
// All actions with side effects, only doing meaningful work if account
// consistency is enabled. Virtual so that they can be overridden in tests.
- virtual void PerformMergeAction(const CoreAccountId& account_id);
virtual void PerformLogoutAllAccountsAction();
virtual void PerformSetCookiesAction(
const signin::MultiloginParameters& parameters);
// Used during periodic reconciliation.
- void StartReconcile();
+ void StartReconcile(Trigger trigger);
// |gaia_accounts| are the accounts in the Gaia cookie.
void FinishReconcile(const CoreAccountId& primary_account,
const std::vector<CoreAccountId>& chrome_accounts,
std::vector<gaia::ListedAccount>&& gaia_accounts);
void AbortReconcile();
- void CalculateIfMergeSessionReconcileIsDone();
void ScheduleStartReconcileIfChromeAccountsChanged();
// Returns the list of valid accounts from the TokenService.
std::vector<CoreAccountId> LoadValidAccountsFromTokenService() const;
- // Note internally that this |account_id| is added to the cookie jar.
- bool MarkAccountAsAddedToCookie(const CoreAccountId& account_id);
-
// The reconcilor only starts when the token service is ready.
bool IsIdentityManagerReady();
@@ -300,9 +324,6 @@ class AccountReconcilor : public KeyedService,
void HandleReconcileTimeout();
- // Returns true is multilogin endpoint can be enabled.
- bool IsMultiloginEndpointEnabled() const;
-
// Returns true if current array of existing accounts in cookie is different
// from the desired one. If this returns false, the multilogin call would be a
// no-op.
@@ -316,7 +337,17 @@ class AccountReconcilor : public KeyedService,
// Returns whether Shutdown() was called.
bool WasShutDown() const;
+ static void RecordReconcileOperation(Trigger trigger, Operation operation);
+
+ // Histogram names.
+ static const char kOperationHistogramName[];
+ static const char kTriggerLogoutHistogramName[];
+ static const char kTriggerMultiloginHistogramName[];
+ static const char kTriggerNoopHistogramName[];
+ static const char kTriggerThrottledHistogramName[];
+
std::unique_ptr<signin::AccountReconcilorDelegate> delegate_;
+ AccountReconcilorThrottler throttler_;
// The IdentityManager associated with this reconcilor.
signin::IdentityManager* identity_manager_;
@@ -324,16 +355,17 @@ class AccountReconcilor : public KeyedService,
// The SigninClient associated with this reconcilor.
SigninClient* client_;
- bool registered_with_identity_manager_;
- bool registered_with_content_settings_;
+ bool registered_with_identity_manager_ = false;
+ bool registered_with_content_settings_ = false;
// True while the reconcilor is busy checking or managing the accounts in
// this profile.
- bool is_reconcile_started_;
+ bool is_reconcile_started_ = false;
base::Time reconcile_start_time_;
+ Trigger trigger_ = Trigger::kInitialized;
// True iff this is the first time the reconcilor is executing.
- bool first_execution_;
+ bool first_execution_ = true;
// 'Most severe' error encountered during the last attempt to reconcile. If
// the last reconciliation attempt was successful, this will be
@@ -343,23 +375,23 @@ class AccountReconcilor : public KeyedService,
// error is considered more severe than all non-persistent errors, but
// persistent (or non-persistent) errors do not have an internal severity
// ordering among themselves.
- GoogleServiceAuthError error_during_last_reconcile_;
+ GoogleServiceAuthError error_during_last_reconcile_ =
+ GoogleServiceAuthError::AuthErrorNone();
// Used for Dice migration: migration can happen if the accounts are
// consistent, which is indicated by reconcile being a no-op.
- bool reconcile_is_noop_;
+ bool reconcile_is_noop_ = true;
// Used during reconcile action.
- std::vector<CoreAccountId> add_to_cookie_; // Progress of AddAccount calls.
- bool set_accounts_in_progress_; // Progress of SetAccounts calls.
- bool log_out_in_progress_; // Progress of LogOut calls.
- bool chrome_accounts_changed_;
+ bool set_accounts_in_progress_ = false; // Progress of SetAccounts calls.
+ bool log_out_in_progress_ = false; // Progress of LogOut calls.
+ bool chrome_accounts_changed_ = false;
// Used for the Lock.
// StartReconcile() is blocked while this is > 0.
- int account_reconcilor_lock_count_;
+ int account_reconcilor_lock_count_ = 0;
// StartReconcile() should be started when the reconcilor is unblocked.
- bool reconcile_on_unblock_;
+ bool reconcile_on_unblock_ = false;
base::ObserverList<Observer, true>::Unchecked observer_list_;
@@ -371,14 +403,16 @@ class AccountReconcilor : public KeyedService,
// of reconciliation completing within a finite time. It is technically
// possible for account reconciliation to be running/waiting forever in cases
// such as a network connection not being present.
- std::unique_ptr<base::OneShotTimer> timer_;
+ std::unique_ptr<base::OneShotTimer> timer_ =
+ std::make_unique<base::OneShotTimer>();
base::TimeDelta timeout_;
// Greater than 0 when synced data is being deleted, and it is important to
// not invalidate the primary token while this is happening.
int synced_data_deletion_in_progress_count_ = 0;
- signin_metrics::AccountReconcilorState state_;
+ signin_metrics::AccountReconcilorState state_ =
+ signin_metrics::ACCOUNT_RECONCILOR_OK;
// Set to true when Shutdown() is called.
bool was_shut_down_ = false;
diff --git a/chromium/components/signin/core/browser/account_reconcilor_delegate.cc b/chromium/components/signin/core/browser/account_reconcilor_delegate.cc
index a16384a0d34..4c64dbd9875 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_delegate.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor_delegate.cc
@@ -17,10 +17,6 @@ bool AccountReconcilorDelegate::IsReconcileEnabled() const {
return false;
}
-bool AccountReconcilorDelegate::IsMultiloginEndpointEnabled() const {
- return true;
-}
-
gaia::GaiaSource AccountReconcilorDelegate::GetGaiaApiSource() const {
NOTREACHED() << "Reconcile is not enabled, no Gaia API calls should be made.";
return gaia::GaiaSource::kChrome;
diff --git a/chromium/components/signin/core/browser/account_reconcilor_delegate.h b/chromium/components/signin/core/browser/account_reconcilor_delegate.h
index 7a6ecd71d66..7e6e287af9e 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_delegate.h
+++ b/chromium/components/signin/core/browser/account_reconcilor_delegate.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_DELEGATE_H_
#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_DELEGATE_H_
-#include <string>
#include <vector>
#include "base/time/time.h"
@@ -40,11 +39,6 @@ class AccountReconcilorDelegate {
// false.
virtual bool IsReconcileEnabled() const;
- // Returns whether the OAuth multilogin endpoint can be used to build the Gaia
- // cookies.
- // Default implementation returns true.
- virtual bool IsMultiloginEndpointEnabled() const;
-
// Returns the value to set in the "source" parameter for Gaia API calls.
virtual gaia::GaiaSource GetGaiaApiSource() const;
diff --git a/chromium/components/signin/core/browser/account_reconcilor_throttler.cc b/chromium/components/signin/core/browser/account_reconcilor_throttler.cc
new file mode 100644
index 00000000000..1742ff043c7
--- /dev/null
+++ b/chromium/components/signin/core/browser/account_reconcilor_throttler.cc
@@ -0,0 +1,113 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/account_reconcilor_throttler.h"
+
+#include "base/metrics/histogram_functions.h"
+
+namespace {
+MultiloginRequestType GetMultiloginRequestType(
+ const signin::MultiloginParameters& params) {
+ if (params.mode ==
+ gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER) {
+ return MultiloginRequestType::kPreserveCookieAccountsOrder;
+ }
+
+ // Update mode.
+ DCHECK_EQ(params.mode,
+ gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER);
+ if (params.accounts_to_send.size())
+ return MultiloginRequestType::kUpdateCookieAccountsOrder;
+
+ // Accounts to send is empty.
+ return MultiloginRequestType::kLogoutAllAccounts;
+}
+} // namespace
+
+// static
+constexpr float AccountReconcilorThrottler::kMaxAllowedRequestsPerBucket;
+// static
+constexpr float AccountReconcilorThrottler::kRefillRequestsBucketRatePerMinute;
+
+AccountReconcilorThrottler::AccountReconcilorThrottler() {
+ Reset();
+}
+
+AccountReconcilorThrottler::~AccountReconcilorThrottler() {
+ RecordAndResetNumberOfRejectedRequests();
+}
+
+void AccountReconcilorThrottler::Reset() {
+ // Needed for the case when the reconcilor is a no op and calls reset.
+ RecordAndResetNumberOfRejectedRequests();
+ last_request_params_ = absl::nullopt;
+ available_requests_bucket_ = kMaxAllowedRequestsPerBucket;
+ last_refill_time_stamp_ = base::TimeTicks::Now();
+}
+
+bool AccountReconcilorThrottler::IsDifferentRequest(
+ const signin::MultiloginParameters& params) const {
+ return !last_request_params_.has_value() ||
+ params != last_request_params_.value();
+}
+
+bool AccountReconcilorThrottler::TryMultiloginOperation(
+ const signin::MultiloginParameters& params) {
+ if (IsDifferentRequest(params))
+ Reset();
+
+ RefillAllowedRequests();
+ if (available_requests_bucket_ < 1.0) {
+ ++consecutive_rejected_requests_;
+ return false;
+ }
+
+ RecordMultiloginOperation(params);
+ RecordAndResetNumberOfRejectedRequests();
+ return true;
+}
+
+void AccountReconcilorThrottler::RecordMultiloginOperation(
+ const signin::MultiloginParameters& params) {
+ DCHECK_GE(available_requests_bucket_, 1.0f);
+ last_request_params_ = params;
+ available_requests_bucket_ -= 1.0f;
+}
+
+void AccountReconcilorThrottler::RefillAllowedRequests() {
+ float refill_requests =
+ (base::TimeTicks::Now() - last_refill_time_stamp_).InSecondsF() / 60.0 *
+ kRefillRequestsBucketRatePerMinute;
+
+ available_requests_bucket_ =
+ std::min(available_requests_bucket_ + refill_requests,
+ kMaxAllowedRequestsPerBucket);
+ last_refill_time_stamp_ = base::TimeTicks::Now();
+}
+
+void AccountReconcilorThrottler::RecordAndResetNumberOfRejectedRequests() {
+ if (!consecutive_rejected_requests_)
+ return;
+
+ DCHECK(last_request_params_.has_value());
+ switch (GetMultiloginRequestType(last_request_params_.value())) {
+ case MultiloginRequestType::kPreserveCookieAccountsOrder:
+ base::UmaHistogramCounts1000(
+ "Signin.Reconciler.RejectedRequestsDueToThrottler.Preserve",
+ consecutive_rejected_requests_);
+ break;
+ case MultiloginRequestType::kUpdateCookieAccountsOrder:
+ base::UmaHistogramCounts1000(
+ "Signin.Reconciler.RejectedRequestsDueToThrottler.Update",
+ consecutive_rejected_requests_);
+ break;
+ case MultiloginRequestType::kLogoutAllAccounts:
+ base::UmaHistogramCounts1000(
+ "Signin.Reconciler.RejectedRequestsDueToThrottler.LogoutAll",
+ consecutive_rejected_requests_);
+ break;
+ }
+
+ consecutive_rejected_requests_ = 0;
+}
diff --git a/chromium/components/signin/core/browser/account_reconcilor_throttler.h b/chromium/components/signin/core/browser/account_reconcilor_throttler.h
new file mode 100644
index 00000000000..e4e2e02c2e4
--- /dev/null
+++ b/chromium/components/signin/core/browser/account_reconcilor_throttler.h
@@ -0,0 +1,61 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_THROTTLER_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_THROTTLER_H_
+
+#include "base/time/time.h"
+#include "components/signin/public/base/multilogin_parameters.h"
+
+// Used for UMA logging, do not remove or reorder values.
+enum class MultiloginRequestType {
+ kPreserveCookieAccountsOrder = 0,
+ kUpdateCookieAccountsOrder = 1,
+ kLogoutAllAccounts = 2,
+ kMaxValue = kLogoutAllAccounts,
+};
+
+// Helper class to avoid the account reconcilor from getting into a loop,
+// repeating the same request and generating a spike in the number of requests.
+class AccountReconcilorThrottler {
+ public:
+ AccountReconcilorThrottler();
+ ~AccountReconcilorThrottler();
+
+ AccountReconcilorThrottler(const AccountReconcilorThrottler&) = delete;
+ AccountReconcilorThrottler& operator=(const AccountReconcilorThrottler&) =
+ delete;
+
+ // The multilogin operation should be sent or blocked based on the result of
+ // this function. It returns true if not all the |available_requests_ >= 1.0|
+ // has been consumed, and consumes one of the available requests.
+ bool TryMultiloginOperation(const signin::MultiloginParameters& params);
+
+ // Any request passed to |IsMultiloginOperationAllowed()| after |Reset()| is
+ // called is considered as a new different request.
+ // |available_requests_bucket_| is reset to its max allowance.
+ void Reset();
+
+ // Max bucket size. The throttler tolerates up to 30 successive identical
+ // requests before throttling.
+ static constexpr float kMaxAllowedRequestsPerBucket = 30.0f;
+
+ // Requests bucket is refilled with the rate of 0.5 per minute. If all the
+ // available requests have been consumed, the reconcilor will need to wait for
+ // 2 minutes from the last request to perform another identical request.
+ static constexpr float kRefillRequestsBucketRatePerMinute = 0.5f;
+
+ private:
+ bool IsDifferentRequest(const signin::MultiloginParameters& params) const;
+ void RefillAllowedRequests();
+ void RecordMultiloginOperation(const signin::MultiloginParameters& params);
+ void RecordAndResetNumberOfRejectedRequests();
+
+ // Reset for every new request with different parameters.
+ float available_requests_bucket_;
+ base::TimeTicks last_refill_time_stamp_;
+ absl::optional<signin::MultiloginParameters> last_request_params_;
+ size_t consecutive_rejected_requests_ = 0;
+};
+
+#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCOUNT_RECONCILOR_THROTTLER_H_
diff --git a/chromium/components/signin/core/browser/account_reconcilor_unittest.cc b/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
index ac9d75d907d..4933f0b9bd4 100644
--- a/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/chromium/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -175,7 +175,6 @@ class MockAccountReconcilor
SigninClient* client,
std::unique_ptr<signin::AccountReconcilorDelegate> delegate);
- MOCK_METHOD1(PerformMergeAction, void(const CoreAccountId& account_id));
MOCK_METHOD0(PerformLogoutAllAccountsAction, void());
MOCK_METHOD1(PerformSetCookiesAction,
void(const signin::MultiloginParameters& parameters));
@@ -252,10 +251,6 @@ class AccountReconcilorTest : public ::testing::Test {
CoreAccountId PickAccountIdForAccount(const std::string& gaia_id,
const std::string& username);
- void SimulateAddAccountToCookieCompleted(AccountReconcilor* reconcilor,
- const CoreAccountId& account_id,
- const GoogleServiceAuthError& error);
-
void SimulateSetAccountsInCookieCompleted(
AccountReconcilor* reconcilor,
signin::SetAccountsInCookieResult result);
@@ -379,13 +374,6 @@ CoreAccountId AccountReconcilorTest::PickAccountIdForAccount(
gaia_id, username);
}
-void AccountReconcilorTest::SimulateAddAccountToCookieCompleted(
- AccountReconcilor* reconcilor,
- const CoreAccountId& account_id,
- const GoogleServiceAuthError& error) {
- reconcilor->OnAddAccountToCookieCompleted(account_id, error);
-}
-
void AccountReconcilorTest::SimulateSetAccountsInCookieCompleted(
AccountReconcilor* reconcilor,
signin::SetAccountsInCookieResult result) {
@@ -437,9 +425,6 @@ struct AccountReconcilorTestTableParam {
const char* gaia_api_calls;
const char* tokens_after_reconcile;
const char* cookies_after_reconcile;
- const char* gaia_api_calls_multilogin;
- const char* tokens_after_reconcile_multilogin;
- const char* cookies_after_reconcile_multilogin;
// Int represents AccountReconcilorDelegate::InconsistencyReason.
const int inconsistency_reason;
};
@@ -480,26 +465,7 @@ void PrintTo(const AccountReconcilorTestTableParam& param, ::std::ostream* os) {
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) {
+ BaseAccountReconcilorTestTable() {
accounts_['A'] = {"a@gmail.com",
signin::GetTestGaiaIdForEmail("a@gmail.com")};
accounts_['B'] = {"b@gmail.com",
@@ -634,111 +600,11 @@ class BaseAccountReconcilorTestTable : public AccountReconcilorTest {
identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
}
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
- void RunReconcile() {
- // Setup cookies.
- std::vector<Cookie> cookies = ParseCookieString(cookies_);
- ConfigureCookieManagerService(cookies);
-
- // Call list accounts now so that the next call completes synchronously.
- identity_test_env()->identity_manager()->GetAccountsInCookieJar();
- base::RunLoop().RunUntilIdle();
-
- // Setup tokens. This triggers listing cookies so we need to setup cookies
- // before that.
- SetupTokens(tokens_);
-
- // 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{accounts_[cookie[0]].gaia_id, false /* is_valid */});
- if (it == cookies.end())
- cookies.push_back({accounts_[cookie[0]].gaia_id, 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;
- reconcilor->StartReconcile();
- for (int i = 0; gaia_api_calls_[i] != '\0'; ++i) {
- if (gaia_api_calls_[i] == 'X') {
- SimulateLogOutFromCookieCompleted(
- reconcilor, GoogleServiceAuthError::AuthErrorNone());
- 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.
@@ -746,35 +612,24 @@ class AccountReconcilorTestTable
: public BaseAccountReconcilorTestTable,
public ::testing::WithParamInterface<AccountReconcilorTestTableParam> {
protected:
- AccountReconcilorTestTable() : BaseAccountReconcilorTestTable(GetParam()) {}
+ AccountReconcilorTestTable() = default;
// Checks that reconcile is idempotent.
void CheckReconcileIdempotent(
const std::vector<AccountReconcilorTestTableParam>& params,
- const AccountReconcilorTestTableParam& param,
- bool multilogin) {
+ const AccountReconcilorTestTableParam& param) {
// Simulate another reconcile based on the results of this one: find the
// corresponding row in the table and check that it does nothing.
for (const AccountReconcilorTestTableParam& row : params) {
if (row.is_first_reconcile == IsFirstReconcile::kFirst)
continue;
- if (!((strcmp(row.tokens, param.tokens_after_reconcile) == 0 &&
- strcmp(row.cookies, param.cookies_after_reconcile) == 0 &&
- !multilogin) ||
- (strcmp(row.tokens, param.tokens_after_reconcile_multilogin) == 0 &&
- strcmp(row.cookies, param.cookies_after_reconcile_multilogin) ==
- 0 &&
- multilogin))) {
+ if (!(strcmp(row.tokens, param.tokens_after_reconcile) == 0 &&
+ strcmp(row.cookies, param.cookies_after_reconcile) == 0)) {
continue;
}
- if (multilogin) {
- EXPECT_STREQ(row.tokens, row.tokens_after_reconcile_multilogin);
- EXPECT_STREQ(row.cookies, row.cookies_after_reconcile_multilogin);
- } else {
- EXPECT_STREQ(row.tokens, row.tokens_after_reconcile);
- EXPECT_STREQ(row.cookies, row.cookies_after_reconcile);
- }
+ EXPECT_STREQ(row.tokens, row.tokens_after_reconcile);
+ EXPECT_STREQ(row.cookies, row.cookies_after_reconcile);
return;
}
@@ -810,7 +665,8 @@ TEST_F(AccountReconcilorMirrorTest, Reauth) {
auto* account_mutator =
identity_test_env()->identity_manager()->GetPrimaryAccountMutator();
DCHECK(account_mutator);
- account_mutator->SetPrimaryAccount(account_info.account_id);
+ account_mutator->SetPrimaryAccount(account_info.account_id,
+ signin::ConsentLevel::kSync);
ASSERT_TRUE(reconcilor->IsRegisteredWithIdentityManager());
}
@@ -878,248 +734,285 @@ const std::vector<AccountReconcilorTestTableParam> kDiceParams = {
// x: The next cookie is marked "invalid".
// - First Run: true if this is the first reconcile (i.e. Chrome startup).
// -------------------------------------------------------------------------
- // Tokens|Cookies|First Run|Gaia calls|Tokens aft.|Cookies aft.|M.calls| M.Tokens aft.| M.Cookies aft.| AccountReconcilorDelegate::InconsistencyReason |
+ // Tokens|Cookies|First Run|Gaia calls|Tokens aft.|Cookies aft.|AccountReconcilorDelegate::InconsistencyReason |
// -------------------------------------------------------------------------
// First reconcile (Chrome restart): Rebuild the Gaia cookie to match the
// tokens. Make the Sync account the default account in the Gaia cookie.
// Sync enabled.
- { "", "A", IsFirstReconcile::kBoth, "X", "", "", "U", "", "", 3},
- { "*AB", "AB", IsFirstReconcile::kBoth, "", "*AB", "AB", "", "*AB", "AB", 0},
- { "*A", "A", IsFirstReconcile::kBoth, "", "*A", "A", "", "*A" , "A", 0},
- { "*A", "", IsFirstReconcile::kBoth, "A", "*A", "A", "PA", "*A" , "A", 1},
- { "*A", "B", IsFirstReconcile::kBoth, "XA", "*A", "A", "UA", "*A" , "A", 1},
- { "*A", "AB", IsFirstReconcile::kBoth, "XA", "*A", "A", "UA", "*A" , "A", 5},
- { "*AB", "BA", IsFirstReconcile::kFirst, "XAB", "*AB", "AB", "UAB", "*AB", "AB", 7},
- { "*AB", "BA", IsFirstReconcile::kNotFirst, "", "*AB", "BA", "", "*AB", "BA", 0},
+ { "", "A", IsFirstReconcile::kBoth, "U", "", "", 3},
+ { "*AB", "AB", IsFirstReconcile::kBoth, "", "*AB", "AB", 0},
+ { "*A", "A", IsFirstReconcile::kBoth, "", "*A" , "A", 0},
+ { "*A", "", IsFirstReconcile::kBoth, "PA", "*A" , "A", 1},
+ { "*A", "B", IsFirstReconcile::kBoth, "UA", "*A" , "A", 1},
+ { "*A", "AB", IsFirstReconcile::kBoth, "UA", "*A" , "A", 5},
+ { "*AB", "BA", IsFirstReconcile::kFirst, "UAB", "*AB", "AB", 7},
+ { "*AB", "BA", IsFirstReconcile::kNotFirst,"", "*AB", "BA", 0},
- { "*AB", "A", IsFirstReconcile::kBoth, "B", "*AB", "AB", "PAB", "*AB", "AB", 4},
+ { "*AB", "A", IsFirstReconcile::kBoth, "PAB", "*AB", "AB", 4},
- { "*AB", "B", IsFirstReconcile::kFirst, "XAB", "*AB", "AB", "UAB", "*AB", "AB", 1},
- { "*AB", "B", IsFirstReconcile::kNotFirst, "A", "*AB", "BA", "PBA", "*AB", "BA", 1},
+ { "*AB", "B", IsFirstReconcile::kFirst, "UAB", "*AB", "AB", 1},
+ { "*AB", "B", IsFirstReconcile::kNotFirst,"PBA", "*AB", "BA", 1},
- { "*AB", "", IsFirstReconcile::kBoth, "AB", "*AB", "AB", "PAB", "*AB", "AB", 1},
+ { "*AB", "", IsFirstReconcile::kBoth, "PAB", "*AB", "AB", 1},
// Sync enabled, token error on primary.
- { "*xAB", "AB", IsFirstReconcile::kBoth, "X", "*xA", "" , "U", "*xA", "", 2},
- { "*xAB", "BA", IsFirstReconcile::kBoth, "XB", "*xAB", "B", "UB", "*xAB", "B", 2},
- { "*xAB", "A", IsFirstReconcile::kBoth, "X", "*xA", "" , "U", "*xA", "", 2},
- { "*xAB", "B", IsFirstReconcile::kBoth, "", "*xAB", "B", "", "*xAB", "B", 0},
- { "*xAB", "", IsFirstReconcile::kBoth, "B", "*xAB", "B", "PB", "*xAB", "B", 0},
+ { "*xAB", "AB", IsFirstReconcile::kBoth, "U", "*xA", "", 2},
+ { "*xAB", "BA", IsFirstReconcile::kBoth, "UB", "*xAB", "B", 2},
+ { "*xAB", "A", IsFirstReconcile::kBoth, "U", "*xA", "", 2},
+ { "*xAB", "B", IsFirstReconcile::kBoth, "", "*xAB", "B", 0},
+ { "*xAB", "", IsFirstReconcile::kBoth, "PB", "*xAB", "B", 0},
// Sync enabled, token error on secondary.
- { "*AxB", "AB", IsFirstReconcile::kBoth, "XA", "*A", "A", "UA", "*A", "A", 5},
- { "*AxB", "A", IsFirstReconcile::kBoth, "", "*A", "A", "", "*A", "A", 0},
- { "*AxB", "", IsFirstReconcile::kBoth, "A", "*A", "A", "PA", "*A", "A", 1},
+ { "*AxB", "AB", IsFirstReconcile::kBoth, "UA", "*A", "A", 5},
+ { "*AxB", "A", IsFirstReconcile::kBoth, "", "*A", "A", 0},
+ { "*AxB", "", IsFirstReconcile::kBoth, "PA", "*A", "A", 1},
// The first account in cookies is swapped even when Chrome is running.
// The swap would happen at next startup anyway and doing it earlier avoids signing the user out.
- { "*AxB", "BA", IsFirstReconcile::kBoth, "XA", "*A", "A", "UA", "*A", "A", 5},
- { "*AxB", "B", IsFirstReconcile::kBoth, "XA", "*A", "A", "UA", "*A", "A", 1},
+ { "*AxB", "BA", IsFirstReconcile::kBoth, "UA", "*A", "A", 5},
+ { "*AxB", "B", IsFirstReconcile::kBoth, "UA", "*A", "A", 1},
// Sync enabled, token error on both accounts.
- { "*xAxB", "AB", IsFirstReconcile::kBoth, "X", "*xA", "", "U", "*xA", "", 2},
- { "*xAxB", "BA", IsFirstReconcile::kBoth, "X", "*xA", "", "U", "*xA", "", 2},
- { "*xAxB", "A", IsFirstReconcile::kBoth, "X", "*xA", "", "U", "*xA", "", 2},
- { "*xAxB", "B", IsFirstReconcile::kBoth, "X", "*xA", "", "U", "*xA", "", 5},
- { "*xAxB", "", IsFirstReconcile::kBoth, "", "*xA", "", "", "*xA", "", 0},
+ { "*xAxB", "AB", IsFirstReconcile::kBoth, "U", "*xA", "", 2},
+ { "*xAxB", "BA", IsFirstReconcile::kBoth, "U", "*xA", "", 2},
+ { "*xAxB", "A", IsFirstReconcile::kBoth, "U", "*xA", "", 2},
+ { "*xAxB", "B", IsFirstReconcile::kBoth, "U", "*xA", "", 5},
+ { "*xAxB", "", IsFirstReconcile::kBoth, "", "*xA", "", 0},
// Sync disabled.
- { "AB", "AB", IsFirstReconcile::kBoth, "", "AB", "AB", "", "AB", "AB", 0},
- { "AB", "BA", IsFirstReconcile::kBoth, "", "AB", "BA", "", "AB", "BA", 0},
- { "AB", "A", IsFirstReconcile::kBoth, "B", "AB", "AB", "PAB", "AB", "AB", 4},
- { "AB", "B", IsFirstReconcile::kBoth, "A", "AB", "BA", "PBA", "AB", "BA", 4},
- { "AB", "", IsFirstReconcile::kBoth, "AB", "AB", "AB", "PAB", "AB", "AB", 0},
+ { "AB", "AB", IsFirstReconcile::kBoth, "", "AB", "AB", 0},
+ { "AB", "BA", IsFirstReconcile::kBoth, "", "AB", "BA", 0},
+ { "AB", "A", IsFirstReconcile::kBoth, "PAB", "AB", "AB", 4},
+ { "AB", "B", IsFirstReconcile::kBoth, "PBA", "AB", "BA", 4},
+ { "AB", "", IsFirstReconcile::kBoth, "PAB", "AB", "AB", 0},
// Sync disabled, token error on first account.
- { "xAB", "AB", IsFirstReconcile::kFirst, "XB", "B", "B", "UB", "B", "B", 3},
- { "xAB", "AB", IsFirstReconcile::kNotFirst, "X", "", "" , "U", "", "", 3},
+ { "xAB", "AB", IsFirstReconcile::kFirst, "UB", "B", "B", 3},
+ { "xAB", "AB", IsFirstReconcile::kNotFirst, "U", "", "", 3},
- { "xAB", "BA", IsFirstReconcile::kBoth, "XB", "B", "B", "UB", "B", "B", 5},
+ { "xAB", "BA", IsFirstReconcile::kBoth, "UB", "B", "B", 5},
- { "xAB", "A", IsFirstReconcile::kFirst, "XB", "B", "B", "UB", "B", "B", 3},
- { "xAB", "A", IsFirstReconcile::kNotFirst, "X", "", "" , "U", "", "", 3},
+ { "xAB", "A", IsFirstReconcile::kFirst, "UB", "B", "B", 3},
+ { "xAB", "A", IsFirstReconcile::kNotFirst, "U", "", "", 3},
- { "xAB", "B", IsFirstReconcile::kBoth, "", "B", "B", "", "B", "B", 0},
+ { "xAB", "B", IsFirstReconcile::kBoth, "", "B", "B", 0},
- { "xAB", "", IsFirstReconcile::kBoth, "B", "B", "B", "PB", "B", "B", 0},
- // Sync disabled, token error on second account .
- { "AxB", "AB", IsFirstReconcile::kBoth, "XA", "A", "A", "UA", "A", "A", 5},
+ { "xAB", "", IsFirstReconcile::kBoth, "PB", "B", "B", 0},
+ // Sync disabled, token error on second account
+ { "AxB", "AB", IsFirstReconcile::kBoth, "UA", "A", "A", 5},
- { "AxB", "BA", IsFirstReconcile::kFirst, "XA", "A", "A", "UA", "A", "A", 3},
- { "AxB", "BA", IsFirstReconcile::kNotFirst, "X", "", "" , "U", "", "", 3},
+ { "AxB", "BA", IsFirstReconcile::kFirst, "UA", "A", "A", 3},
+ { "AxB", "BA", IsFirstReconcile::kNotFirst, "U", "", "", 3},
- { "AxB", "A", IsFirstReconcile::kBoth, "", "A", "A", "", "A", "A", 0},
+ { "AxB", "A", IsFirstReconcile::kBoth, "", "A", "A", 0},
- { "AxB", "B", IsFirstReconcile::kFirst, "XA", "A", "A", "UA", "A", "A", 3},
- { "AxB", "B", IsFirstReconcile::kNotFirst, "X", "", "" , "U", "", "", 3},
+ { "AxB", "B", IsFirstReconcile::kFirst, "UA", "A", "A", 3},
+ { "AxB", "B", IsFirstReconcile::kNotFirst, "U", "", "", 3},
- { "AxB", "", IsFirstReconcile::kBoth, "A", "A", "A", "PA", "A", "A", 0},
+ { "AxB", "", IsFirstReconcile::kBoth, "PA", "A", "A", 0},
// Sync disabled, token error on both accounts.
- { "xAxB", "AB", IsFirstReconcile::kBoth, "X", "", "", "U", "", "", 3},
- { "xAxB", "BA", IsFirstReconcile::kBoth, "X", "", "", "U", "", "", 3},
- { "xAxB", "A", IsFirstReconcile::kBoth, "X", "", "", "U", "", "", 3},
- { "xAxB", "B", IsFirstReconcile::kBoth, "X", "", "", "U", "", "", 3},
- { "xAxB", "", IsFirstReconcile::kBoth, "", "", "", "", "", "", 0},
+ { "xAxB", "AB", IsFirstReconcile::kBoth, "U", "", "", 3},
+ { "xAxB", "BA", IsFirstReconcile::kBoth, "U", "", "", 3},
+ { "xAxB", "A", IsFirstReconcile::kBoth, "U", "", "", 3},
+ { "xAxB", "B", IsFirstReconcile::kBoth, "U", "", "", 3},
+ { "xAxB", "", IsFirstReconcile::kBoth, "", "", "", 0},
// Account marked as invalid in cookies.
// No difference between cookies and tokens, do not do do anything.
// Do not logout. Regression tests for http://crbug.com/854799
- { "", "xA", IsFirstReconcile::kBoth, "", "", "xA", "", "", "xA", 0},
- { "", "xAxB", IsFirstReconcile::kBoth, "", "", "xAxB", "", "", "xAxB", 0},
- { "xA", "xA", IsFirstReconcile::kBoth, "", "", "xA", "", "", "xA", 0},
- { "xAB", "xAB", IsFirstReconcile::kBoth, "", "B", "xAB", "", "B", "xAB", 0},
- { "AxB", "AxC", IsFirstReconcile::kBoth, "", "A", "AxC", "", "A", "AxC", 0},
- { "B", "xAB", IsFirstReconcile::kBoth, "", "B", "xAB", "", "B", "xAB", 0},
- { "*xA", "xA", IsFirstReconcile::kBoth, "", "*xA", "xA", "", "*xA", "xA", 0},
- { "*xA", "xB", IsFirstReconcile::kBoth, "", "*xA", "xB", "", "*xA", "xB", 0},
- { "*xAB", "xAB", IsFirstReconcile::kBoth, "", "*xAB", "xAB", "", "*xAB", "xAB", 0},
- { "*AxB", "xBA", IsFirstReconcile::kNotFirst, "", "*A", "xBA", "", "*A", "xBA", 0},
+ { "", "xA", IsFirstReconcile::kBoth, "", "", "xA", 0},
+ { "", "xAxB", IsFirstReconcile::kBoth, "", "", "xAxB", 0},
+ { "xA", "xA", IsFirstReconcile::kBoth, "", "", "xA", 0},
+ { "xAB", "xAB", IsFirstReconcile::kBoth, "", "B", "xAB", 0},
+ { "AxB", "AxC", IsFirstReconcile::kBoth, "", "A", "AxC", 0},
+ { "B", "xAB", IsFirstReconcile::kBoth, "", "B", "xAB", 0},
+ { "*xA", "xA", IsFirstReconcile::kBoth, "", "*xA", "xA", 0},
+ { "*xA", "xB", IsFirstReconcile::kBoth, "", "*xA", "xB", 0},
+ { "*xAB", "xAB", IsFirstReconcile::kBoth, "", "*xAB", "xAB", 0},
+ { "*AxB", "xBA", IsFirstReconcile::kNotFirst, "", "*A", "xBA", 0},
// Appending a new cookie after the invalid one.
- { "B", "xA", IsFirstReconcile::kBoth, "B", "B", "xAB", "PB", "B", "xAB", 4},
- { "xAB", "xA", IsFirstReconcile::kBoth, "B", "B", "xAB", "PB", "B", "xAB", 4},
+ { "B", "xA", IsFirstReconcile::kBoth, "PB", "B", "xAB", 4},
+ { "xAB", "xA", IsFirstReconcile::kBoth, "PB", "B", "xAB", 4},
// Refresh existing cookies.
- { "AB", "xAB", IsFirstReconcile::kBoth, "A", "AB", "AB", "PAB", "AB", "AB", 4},
- { "*AB", "xBxA", IsFirstReconcile::kNotFirst, "BA", "*AB", "BA", "PBA", "*AB", "BA", 1},
+ { "AB", "xAB", IsFirstReconcile::kBoth, "PAB", "AB", "AB", 4},
+ { "*AB", "xBxA", IsFirstReconcile::kNotFirst, "PBA", "*AB", "BA", 1},
// Appending and invalidating cookies at the same time.
- { "xAB", "xAC", IsFirstReconcile::kFirst, "XB", "B", "B", "UB", "B", "B", 6},
- { "xAB", "xAC", IsFirstReconcile::kNotFirst, "X", "", "", "U", "", "", 6},
+ { "xAB", "xAC", IsFirstReconcile::kFirst, "UB", "B", "B", 6},
+ { "xAB", "xAC", IsFirstReconcile::kNotFirst, "U", "", "", 6},
- { "xAB", "AxC", IsFirstReconcile::kFirst, "XB", "B", "B", "UB", "B", "B", 3},
- { "xAB", "AxC", IsFirstReconcile::kNotFirst, "X", "", "", "U", "", "", 3},
+ { "xAB", "AxC", IsFirstReconcile::kFirst, "UB", "B", "B", 3},
+ { "xAB", "AxC", IsFirstReconcile::kNotFirst, "U", "", "", 3},
- { "*xAB", "xABC", IsFirstReconcile::kFirst, "XB", "*xAB", "B", "UB", "*xAB", "B", 5},
- { "*xAB", "xABC", IsFirstReconcile::kNotFirst, "X", "*xA", "", "U", "*xA", "", 5},
+ { "*xAB", "xABC", IsFirstReconcile::kFirst, "UB", "*xAB", "B", 5},
+ { "*xAB", "xABC", IsFirstReconcile::kNotFirst, "U", "*xA", "", 5},
- { "xAB", "xABC", IsFirstReconcile::kFirst, "XB", "B", "B", "UB", "B", "B", 5},
- { "xAB", "xABC", IsFirstReconcile::kNotFirst, "X", "", "", "U", "", "", 5},
+ { "xAB", "xABC", IsFirstReconcile::kFirst, "UB", "B", "B", 5},
+ { "xAB", "xABC", IsFirstReconcile::kNotFirst, "U", "", "", 5},
// Miscellaneous cases.
- // Check that unknown Gaia accounts are signed out.
- { "*A", "AB", IsFirstReconcile::kBoth, "XA", "*A", "A", "UA", "*A", "A", 5},
+ // Check that unknown Gaia accounts are signed o.
+ { "*A", "AB", IsFirstReconcile::kBoth, "UA", "*A", "A", 5},
// Check that Gaia default account is kept in first position.
- { "AB", "BC", IsFirstReconcile::kBoth, "XBA", "AB", "BA", "UBA", "AB", "BA", 6},
+ { "AB", "BC", IsFirstReconcile::kBoth, "UBA", "AB", "BA", 6},
// Check that Gaia cookie order is preserved for B.
- { "*ABC", "CB", IsFirstReconcile::kFirst, "XABC", "*ABC", "ABC", "UABC", "*ABC", "ABC", 1},
+ { "*ABC", "CB", IsFirstReconcile::kFirst, "UABC", "*ABC", "ABC", 1},
// TODO(https://crbug.com/1129931): Merge session should do XCB instead.
- { "xABC", "ABC", IsFirstReconcile::kFirst, "XBC", "BC", "BC", "UCB", "BC", "CB", 1},
+ { "xABC", "ABC", IsFirstReconcile::kFirst, "UCB", "BC", "CB", 1},
// Check that order in the chrome_accounts is not important.
- { "A*B", "", IsFirstReconcile::kBoth, "BA", "A*B", "BA", "PBA", "A*B", "BA", 7},
- { "*xBA", "BA", IsFirstReconcile::kFirst, "X", "*xB", "" , "U", "*xB", "", 2},
+ { "A*B", "", IsFirstReconcile::kBoth, "PBA", "A*B", "BA", 7},
+ { "*xBA", "BA", IsFirstReconcile::kFirst, "U", "*xB", "", 2},
// Required for idempotency check.
- { "", "", IsFirstReconcile::kNotFirst, "", "", "", "", "", "", 0},
- { "", "xA", IsFirstReconcile::kNotFirst, "", "", "xA", "", "", "xA", 0},
- { "", "xB", IsFirstReconcile::kNotFirst, "", "", "xB", "", "", "xB", 0},
- { "", "xAxB", IsFirstReconcile::kNotFirst, "", "", "xAxB", "", "", "xAxB", 0},
- { "", "xBxA", IsFirstReconcile::kNotFirst, "", "", "xBxA", "", "", "xBxA", 0},
- { "*A", "A", IsFirstReconcile::kNotFirst, "", "*A", "A", "", "*A", "A", 0},
- { "*A", "xBA", IsFirstReconcile::kNotFirst, "", "*A", "xBA", "", "*A", "xBA", 0},
- { "*A", "AxB", IsFirstReconcile::kNotFirst, "", "*A", "AxB", "", "*A", "AxB", 0},
- { "A", "A", IsFirstReconcile::kNotFirst, "", "A", "A", "", "A", "A", 0},
- { "A", "xBA", IsFirstReconcile::kNotFirst, "", "A", "xBA", "", "A", "xBA", 0},
- { "A", "AxB", IsFirstReconcile::kNotFirst, "", "A", "AxB", "", "A", "AxB", 0},
- { "B", "B", IsFirstReconcile::kNotFirst, "", "B", "B", "", "B", "B", 0},
- { "B", "xAB", IsFirstReconcile::kNotFirst, "", "B", "xAB", "", "B", "xAB", 0},
- { "B", "BxA", IsFirstReconcile::kNotFirst, "", "B", "BxA", "", "B", "BxA", 0},
- { "*xA", "", IsFirstReconcile::kNotFirst, "", "*xA", "", "", "*xA", "", 0},
- { "*xA", "xAxB", IsFirstReconcile::kNotFirst, "", "*xA", "xAxB", "", "*xA", "xAxB", 0},
- { "*xA", "xBxA", IsFirstReconcile::kNotFirst, "", "*xA", "xBxA", "", "*xA", "xBxA", 0},
- { "*xA", "xA", IsFirstReconcile::kNotFirst, "", "*xA", "xA", "", "*xA", "xA", 0},
- { "*xA", "xB", IsFirstReconcile::kNotFirst, "", "*xA", "xB", "", "*xA", "xB", 0},
- { "*xAB", "B", IsFirstReconcile::kNotFirst, "", "*xAB", "B", "", "*xAB", "B", 0},
- { "*xAB", "BxA", IsFirstReconcile::kNotFirst, "", "*xAB", "BxA", "", "*xAB", "BxA", 0},
- { "*xAB", "xAB", IsFirstReconcile::kNotFirst, "", "*xAB", "xAB", "", "*xAB", "xAB", 0},
- { "*xAB", "xABxC",IsFirstReconcile::kNotFirst, "", "*xAB", "xABxC", "", "*xAB", "xABxC", 0},
- { "*xB", "", IsFirstReconcile::kNotFirst, "", "*xB", "", "", "*xB", "", 0},
- { "A*B", "BA", IsFirstReconcile::kNotFirst, "", "A*B", "BA", "", "A*B", "BA", 0},
- { "A*B", "AB", IsFirstReconcile::kNotFirst, "", "A*B", "AB", "", "A*B", "AB", 0},
- { "A", "AxC", IsFirstReconcile::kNotFirst, "", "A", "AxC", "", "A", "AxC", 0},
- { "AB", "BxCA", IsFirstReconcile::kNotFirst, "", "AB", "BxCA", "", "AB", "BxCA", 0},
- { "B", "xABxC",IsFirstReconcile::kNotFirst, "", "B", "xABxC", "", "B", "xABxC", 0},
- { "B", "xAxCB",IsFirstReconcile::kNotFirst, "", "B", "xAxCB", "", "B", "xAxCB", 0},
- { "*ABC", "ACB", IsFirstReconcile::kNotFirst, "", "*ABC", "ACB", "", "*ABC", "ACB", 0},
- { "*ABC", "ABC", IsFirstReconcile::kNotFirst, "", "*ABC", "ABC", "", "*ABC", "ABC", 0},
- { "BC", "BC", IsFirstReconcile::kNotFirst, "", "BC", "BC", "", "BC", "BC", 0},
- { "BC", "CB", IsFirstReconcile::kNotFirst, "", "BC", "CB", "", "BC", "CB", 0},
+ { "", "", IsFirstReconcile::kNotFirst, "", "", "", 0},
+ { "", "xA", IsFirstReconcile::kNotFirst, "", "", "xA", 0},
+ { "", "xB", IsFirstReconcile::kNotFirst, "", "", "xB", 0},
+ { "", "xAxB", IsFirstReconcile::kNotFirst, "", "", "xAxB", 0},
+ { "", "xBxA", IsFirstReconcile::kNotFirst, "", "", "xBxA", 0},
+ { "*A", "A", IsFirstReconcile::kNotFirst, "", "*A", "A", 0},
+ { "*A", "xBA", IsFirstReconcile::kNotFirst, "", "*A", "xBA", 0},
+ { "*A", "AxB", IsFirstReconcile::kNotFirst, "", "*A", "AxB", 0},
+ { "A", "A", IsFirstReconcile::kNotFirst, "", "A", "A", 0},
+ { "A", "xBA", IsFirstReconcile::kNotFirst, "", "A", "xBA", 0},
+ { "A", "AxB", IsFirstReconcile::kNotFirst, "", "A", "AxB", 0},
+ { "B", "B", IsFirstReconcile::kNotFirst, "", "B", "B", 0},
+ { "B", "xAB", IsFirstReconcile::kNotFirst, "", "B", "xAB", 0},
+ { "B", "BxA", IsFirstReconcile::kNotFirst, "", "B", "BxA", 0},
+ { "*xA", "", IsFirstReconcile::kNotFirst, "", "*xA", "", 0},
+ { "*xA", "xAxB", IsFirstReconcile::kNotFirst, "", "*xA", "xAxB", 0},
+ { "*xA", "xBxA", IsFirstReconcile::kNotFirst, "", "*xA", "xBxA", 0},
+ { "*xA", "xA", IsFirstReconcile::kNotFirst, "", "*xA", "xA", 0},
+ { "*xA", "xB", IsFirstReconcile::kNotFirst, "", "*xA", "xB", 0},
+ { "*xAB", "B", IsFirstReconcile::kNotFirst, "", "*xAB", "B", 0},
+ { "*xAB", "BxA", IsFirstReconcile::kNotFirst, "", "*xAB", "BxA", 0},
+ { "*xAB", "xAB", IsFirstReconcile::kNotFirst, "", "*xAB", "xAB", 0},
+ { "*xAB", "xABxC",IsFirstReconcile::kNotFirst, "", "*xAB", "xABxC", 0},
+ { "*xB", "", IsFirstReconcile::kNotFirst, "", "*xB", "", 0},
+ { "A*B", "BA", IsFirstReconcile::kNotFirst, "", "A*B", "BA", 0},
+ { "A*B", "AB", IsFirstReconcile::kNotFirst, "", "A*B", "AB", 0},
+ { "A", "AxC", IsFirstReconcile::kNotFirst, "", "A", "AxC", 0},
+ { "AB", "BxCA", IsFirstReconcile::kNotFirst, "", "AB", "BxCA", 0},
+ { "B", "xABxC",IsFirstReconcile::kNotFirst, "", "B", "xABxC", 0},
+ { "B", "xAxCB",IsFirstReconcile::kNotFirst, "", "B", "xAxCB", 0},
+ { "*ABC", "ACB", IsFirstReconcile::kNotFirst, "", "*ABC", "ACB", 0},
+ { "*ABC", "ABC", IsFirstReconcile::kNotFirst, "", "*ABC", "ABC", 0},
+ { "BC", "BC", IsFirstReconcile::kNotFirst, "", "BC", "BC", 0},
+ { "BC", "CB", IsFirstReconcile::kNotFirst, "", "BC", "CB", 0},
};
// clang-format on
-// Parameterized version of AccountReconcilorTest that tests Dice
-// implementation with MergeSession endpoint.
-class AccountReconcilorTestDiceMergeSession
- : public AccountReconcilorTestTable {
+class AccountReconcilorTestForceDiceMigration
+ : public BaseAccountReconcilorTestTable,
+ public ::testing::WithParamInterface<ForceDiceMigrationTestTableParam> {
public:
- AccountReconcilorTestDiceMergeSession() = default;
+ AccountReconcilorTestForceDiceMigration() = default;
- protected:
- base::test::ScopedFeatureList scoped_feature_list_;
+ void RunReconcile() {
+ // Setup cookies.
+ std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
+ ConfigureCookieManagerService(cookies);
+ std::vector<Cookie> cookies_after_reconcile = cookies;
- private:
- DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTestDiceMergeSession);
-};
+ // Call list accounts now so that the next call completes synchronously.
+ identity_test_env()->identity_manager()->GetAccountsInCookieJar();
+ base::RunLoop().RunUntilIdle();
-// Checks one row of the kDiceParams table above.
-TEST_P(AccountReconcilorTestDiceMergeSession, TableRowTest) {
- SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
- scoped_feature_list_.InitAndDisableFeature(kUseMultiloginEndpoint);
+ // Setup tokens. This triggers listing cookies so we need to setup cookies
+ // before that.
+ SetupTokens(GetParam().tokens);
- // Enable Dice.
- SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
+ // Setup expectations.
+ testing::InSequence mock_sequence;
+ bool should_logout;
+ if (GetParam().gaia_api_calls[0] != '\0') {
+ gaia::MultiloginMode mode =
+ GetParam().gaia_api_calls[0] == 'U'
+ ? gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER
+ : gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER;
+ // Generate expected array of accounts in cookies and set fake gaia
+ // response.
+ std::vector<CoreAccountId> accounts_to_send;
+ for (int i = 1; GetParam().gaia_api_calls[i] != '\0'; ++i) {
+ accounts_to_send.push_back(
+ CoreAccountId(accounts_[GetParam().gaia_api_calls[i]].gaia_id));
+ }
+ const signin::MultiloginParameters params(mode, accounts_to_send);
+ cookies_after_reconcile = FakeSetAccountsInCookie(params, cookies);
+ should_logout =
+ accounts_to_send.empty() &&
+ (mode ==
+ gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER);
+ if (should_logout) {
+ EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
+ .Times(1);
+ } else {
+ EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params))
+ .Times(1);
+ }
+ }
+ // Reconcile.
+ AccountReconcilor* reconcilor = GetMockReconcilor();
+ ASSERT_TRUE(reconcilor);
+ ASSERT_TRUE(reconcilor->first_execution_);
+ reconcilor->first_execution_ = true;
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
+ if (GetParam().gaia_api_calls[0] != '\0') {
+ if (should_logout) {
+ SimulateLogOutFromCookieCompleted(
+ reconcilor, GoogleServiceAuthError::AuthErrorNone());
+ } else {
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
+ }
+ }
- // Check that reconcile is idempotent: when called twice in a row it should do
- // nothing on the second call.
- CheckReconcileIdempotent(kDiceParams, GetParam(), /*multilogin=*/false);
- RunReconcile();
-}
+ 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));
-INSTANTIATE_TEST_SUITE_P(
- DiceTable,
- AccountReconcilorTestDiceMergeSession,
- ::testing::ValuesIn(GenerateTestCasesFromParams(kDiceParams)));
+ std::vector<Cookie> cookies_after =
+ ParseCookieString(GetParam().cookies_after_reconcile);
+ EXPECT_EQ(cookies_after, cookies_after_reconcile);
-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) {
- // ForceDiceMigration is temporary and the migration was enabled in in
- // Q1 2020. It is expected to be removed in 2021 Q2.
- // Simply disable the OAuthmultilogin endpoint instead of migrating the
- // tests.
- scoped_feature_list_.InitAndDisableFeature(kUseMultiloginEndpoint);
+ testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
+
+ // Another reconcile is sometimes triggered if Chrome accounts have
+ // changed. Allow it to finish.
+ EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(testing::_))
+ .WillRepeatedly(testing::Return());
+ ConfigureCookieManagerService({});
+ base::RunLoop().RunUntilIdle();
}
private:
- base::test::ScopedFeatureList scoped_feature_list_;
-
DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTestForceDiceMigration);
};
// clang-format off
const std::vector<ForceDiceMigrationTestTableParam> kForceDiceParams = {
- {"*A", "AB", "XA", "*A", "A" },
- {"*AxB", "AB", "XA", "*A", "A" },
- {"AxB", "AB", "XA", "A", "A" },
- {"xAxB", "AB", "X", "", "" },
+ {"*A", "AB", "UA", "*A", "A" },
+ {"*AxB", "AB", "UA", "*A", "A" },
+ {"AxB", "AB", "UA", "A", "A" },
+ {"xAxB", "AB", "U", "", "" },
{"*A", "", "", "*xA", "" },
- {"*A", "B", "X", "*xA", "" },
+ {"*A", "B", "U", "*xA", "" },
{"*AB", "B", "", "*xAB", "B" },
- {"*AxB", "B", "X", "*xA", "" },
+ {"*AxB", "B", "U", "*xA", "" },
{"*ABC", "CB", "", "*xABC", "CB" },
{"*AB", "A", "", "*A", "A" },
{"AB", "A", "", "A", "A" },
{"AB", "", "", "", "" },
{"xAB", "", "", "", "" },
- {"xAB", "A", "X", "", "" },
+ {"xAB", "A", "U", "", "" },
{"xAB", "xA", "", "", "xA" },
{"xAB", "B", "", "B", "B" },
- {"AxB", "B", "X", "", "" },
+ {"AxB", "B", "U", "", "" },
{"AxB", "", "", "", "" },
{"xAxB", "", "", "", "" },
{"B", "xA", "", "", "xA" },
{"AB", "xAB", "", "B", "xAB" },
- {"xAB", "xAC", "X", "", "" },
- {"xAB", "AxC", "X", "", "" },
- {"AB", "BC", "XB", "B", "B" },
+ {"xAB", "xAC", "U", "", "" },
+ {"xAB", "AxC", "U", "", "" },
+ {"AB", "BC", "UB", "B", "B" },
{"*AB", "", "", "*xA", "" },
{"*xAB", "", "", "*xA", "" },
{"*AxB", "", "", "*xA", "" },
@@ -1127,7 +1020,6 @@ const std::vector<ForceDiceMigrationTestTableParam> kForceDiceParams = {
};
// 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());
@@ -1143,7 +1035,8 @@ TEST_P(AccountReconcilorTestForceDiceMigration, TableRowTest) {
TEST_P(AccountReconcilorTestForceDiceMigration, TableRowTestCheckNoOp) {
SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
// Setup cookies.
- std::vector<Cookie> cookies = ParseCookieString(cookies_after_reconcile_);
+ std::vector<Cookie> cookies =
+ ParseCookieString(GetParam().cookies_after_reconcile);
ConfigureCookieManagerService(cookies);
// Call list accounts now so that the next call completes synchronously.
@@ -1152,16 +1045,15 @@ TEST_P(AccountReconcilorTestForceDiceMigration, TableRowTestCheckNoOp) {
// Setup tokens. This triggers listing cookies so we need to setup cookies
// before that.
- SetupTokens(tokens_after_reconcile_);
+ SetupTokens(GetParam().tokens_after_reconcile);
- 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();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
@@ -1177,9 +1069,6 @@ class AccountReconcilorTestDiceMultilogin : public AccountReconcilorTestTable {
public:
AccountReconcilorTestDiceMultilogin() = default;
- protected:
- base::test::ScopedFeatureList scoped_feature_list_;
-
private:
DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTestDiceMultilogin);
};
@@ -1187,9 +1076,8 @@ class AccountReconcilorTestDiceMultilogin : public AccountReconcilorTestTable {
// Checks one row of the kDiceParams table above.
TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
- scoped_feature_list_.InitAndEnableFeature(kUseMultiloginEndpoint);
- CheckReconcileIdempotent(kDiceParams, GetParam(), /*multilogin=*/true);
+ CheckReconcileIdempotent(kDiceParams, GetParam());
// Setup cookies.
std::vector<Cookie> cookies = ParseCookieString(GetParam().cookies);
@@ -1206,18 +1094,18 @@ TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
// Setup expectations.
testing::InSequence mock_sequence;
- bool should_logout;
- if (GetParam().gaia_api_calls_multilogin[0] != '\0') {
+ bool should_logout = false;
+ if (GetParam().gaia_api_calls[0] != '\0') {
gaia::MultiloginMode mode =
- GetParam().gaia_api_calls_multilogin[0] == 'U'
+ GetParam().gaia_api_calls[0] == 'U'
? gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER
: gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER;
// Generate expected array of accounts in cookies and set fake gaia
// response.
std::vector<CoreAccountId> accounts_to_send;
- for (int i = 1; GetParam().gaia_api_calls_multilogin[i] != '\0'; ++i) {
- accounts_to_send.push_back(CoreAccountId(
- accounts_[GetParam().gaia_api_calls_multilogin[i]].gaia_id));
+ for (int i = 1; GetParam().gaia_api_calls[i] != '\0'; ++i) {
+ accounts_to_send.push_back(
+ CoreAccountId(accounts_[GetParam().gaia_api_calls[i]].gaia_id));
}
const signin::MultiloginParameters params(mode, accounts_to_send);
cookies_after_reconcile = FakeSetAccountsInCookie(params, cookies);
@@ -1238,8 +1126,8 @@ TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
ASSERT_TRUE(reconcilor->first_execution_);
reconcilor->first_execution_ =
GetParam().is_first_reconcile == IsFirstReconcile::kFirst ? true : false;
- reconcilor->StartReconcile();
- if (GetParam().gaia_api_calls_multilogin[0] != '\0') {
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
+ if (GetParam().gaia_api_calls[0] != '\0') {
if (should_logout) {
SimulateLogOutFromCookieCompleted(
reconcilor, GoogleServiceAuthError::AuthErrorNone());
@@ -1250,7 +1138,7 @@ TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
}
ASSERT_FALSE(reconcilor->is_reconcile_started_);
- if (GetParam().tokens == GetParam().tokens_after_reconcile_multilogin) {
+ 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
@@ -1258,11 +1146,10 @@ TEST_P(AccountReconcilorTestDiceMultilogin, TableRowTest) {
EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED,
reconcilor->GetState());
}
- VerifyCurrentTokens(
- ParseTokenString(GetParam().tokens_after_reconcile_multilogin));
+ VerifyCurrentTokens(ParseTokenString(GetParam().tokens_after_reconcile));
std::vector<Cookie> cookies_after =
- ParseCookieString(GetParam().cookies_after_reconcile_multilogin);
+ ParseCookieString(GetParam().cookies_after_reconcile);
EXPECT_EQ(cookies_after, cookies_after_reconcile);
testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
@@ -1280,28 +1167,18 @@ INSTANTIATE_TEST_SUITE_P(
AccountReconcilorTestDiceMultilogin,
::testing::ValuesIn(GenerateTestCasesFromParams(kDiceParams)));
-class AccountReconcilorDiceEndpointParamTest
- : public AccountReconcilorTest,
- public ::testing::WithParamInterface<bool> {
+class AccountReconcilorDiceTest : public AccountReconcilorTest {
public:
- AccountReconcilorDiceEndpointParamTest() {
+ AccountReconcilorDiceTest() {
SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
- if (IsMultiloginEnabled())
- scoped_feature_list_.InitAndEnableFeature(kUseMultiloginEndpoint);
- else
- scoped_feature_list_.InitAndDisableFeature(kUseMultiloginEndpoint);
}
- bool IsMultiloginEnabled() { return GetParam(); }
-
- protected:
- base::test::ScopedFeatureList scoped_feature_list_;
private:
- DISALLOW_COPY_AND_ASSIGN(AccountReconcilorDiceEndpointParamTest);
+ DISALLOW_COPY_AND_ASSIGN(AccountReconcilorDiceTest);
};
// Tests that the AccountReconcilor is always registered.
-TEST_P(AccountReconcilorDiceEndpointParamTest, DiceTokenServiceRegistration) {
+TEST_F(AccountReconcilorDiceTest, DiceTokenServiceRegistration) {
AccountReconcilor* reconcilor = GetMockReconcilor();
ASSERT_TRUE(reconcilor);
ASSERT_TRUE(reconcilor->IsRegisteredWithIdentityManager());
@@ -1320,7 +1197,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceTokenServiceRegistration) {
}
// Tests that reconcile starts even when Sync is not enabled.
-TEST_P(AccountReconcilorDiceEndpointParamTest, DiceReconcileWithoutSignin) {
+TEST_F(AccountReconcilorDiceTest, DiceReconcileWithoutSignin) {
// Add a token in Chrome but do not sign in. Making account available (setting
// a refresh token) triggers listing cookies so we need to setup cookies
// before that.
@@ -1328,44 +1205,34 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceReconcileWithoutSignin) {
const CoreAccountId account_id =
identity_test_env()->MakeAccountAvailable("user@gmail.com").account_id;
- if (!IsMultiloginEnabled()) {
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id));
- } else {
std::vector<CoreAccountId> accounts_to_send = {account_id};
const signin::MultiloginParameters params(
gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
- }
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(reconcilor->is_reconcile_started_);
- if (!IsMultiloginEnabled()) {
- SimulateAddAccountToCookieCompleted(
- reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
- } else {
- SimulateSetAccountsInCookieCompleted(
- reconcilor, signin::SetAccountsInCookieResult::kSuccess);
- }
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
}
// Checks that nothing happens when there is no Chrome account and no Gaia
// cookie.
-TEST_P(AccountReconcilorDiceEndpointParamTest, DiceReconcileNoop) {
+TEST_F(AccountReconcilorDiceTest, DiceReconcileNoop) {
// No Chrome account and no cookie.
signin::SetListAccountsResponseNoAccounts(&test_url_loader_factory_);
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_)).Times(0);
EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()).Times(0);
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(testing::_))
.Times(0);
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -1373,8 +1240,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceReconcileNoop) {
}
// Tests that the first Gaia account is re-used when possible.
-TEST_P(AccountReconcilorDiceEndpointParamTest,
- DiceReconcileReuseGaiaFirstAccount) {
+TEST_F(AccountReconcilorDiceTest, DiceReconcileReuseGaiaFirstAccount) {
// Add account "other" to the Gaia cookie.
signin::SetListAccountsResponseTwoAccounts(
"other@gmail.com", signin::GetTestGaiaIdForEmail("other@gmail.com"),
@@ -1395,13 +1261,6 @@ TEST_P(AccountReconcilorDiceEndpointParamTest,
ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1));
ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_2));
- if (!IsMultiloginEnabled()) {
- testing::InSequence mock_sequence;
- EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction());
- // Account 2 is added first.
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_2));
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_1));
- } else {
std::vector<CoreAccountId> accounts_to_send = {account_id_2, account_id_1};
// Send accounts to Gaia in order of chrome accounts. Account 2 is added
// first.
@@ -1409,30 +1268,20 @@ TEST_P(AccountReconcilorDiceEndpointParamTest,
gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
- }
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
- if (!IsMultiloginEnabled()) {
- SimulateLogOutFromCookieCompleted(reconcilor,
- GoogleServiceAuthError::AuthErrorNone());
- SimulateAddAccountToCookieCompleted(
- reconcilor, account_id_1, GoogleServiceAuthError::AuthErrorNone());
- SimulateAddAccountToCookieCompleted(
- reconcilor, account_id_2, GoogleServiceAuthError::AuthErrorNone());
- } else {
SimulateSetAccountsInCookieCompleted(
reconcilor, signin::SetAccountsInCookieResult::kSuccess);
- }
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
}
// Tests that the first account is kept in cache and reused when cookies are
// lost.
-TEST_P(AccountReconcilorDiceEndpointParamTest, DiceLastKnownFirstAccount) {
+TEST_F(AccountReconcilorDiceTest, DiceLastKnownFirstAccount) {
// Add accounts to the token service and the Gaia cookie in a different order.
// Making account available (setting a refresh token) triggers listing cookies
// so we need to setup cookies before that.
@@ -1459,14 +1308,13 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceLastKnownFirstAccount) {
// Do one reconcile. It should do nothing but to populating the last known
// account.
{
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_)).Times(0);
EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
.Times(0);
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(testing::_))
.Times(0);
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -1477,17 +1325,6 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceLastKnownFirstAccount) {
signin::SetListAccountsResponseNoAccounts(&test_url_loader_factory_);
identity_test_env()->SetFreshnessOfAccountsInGaiaCookie(false);
- if (!IsMultiloginEnabled()) {
- // Reconcile again and check that account_id_2 is added first.
- testing::InSequence mock_sequence;
-
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_2))
- .Times(1);
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_1))
- .Times(1);
- EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
- .Times(0);
- } else {
// Since Gaia can't know about cached account, make sure that we reorder
// chrome accounts accordingly even in PRESERVE mode.
std::vector<CoreAccountId> accounts_to_send = {account_id_2, account_id_1};
@@ -1495,27 +1332,19 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceLastKnownFirstAccount) {
gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
- }
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
- if (!IsMultiloginEnabled()) {
- SimulateAddAccountToCookieCompleted(
- reconcilor, account_id_2, GoogleServiceAuthError::AuthErrorNone());
- SimulateAddAccountToCookieCompleted(
- reconcilor, account_id_1, GoogleServiceAuthError::AuthErrorNone());
- } else {
SimulateSetAccountsInCookieCompleted(
reconcilor, signin::SetAccountsInCookieResult::kSuccess);
- }
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
}
// Checks that the reconcilor does not log out unverified accounts.
-TEST_P(AccountReconcilorDiceEndpointParamTest, UnverifiedAccountNoop) {
+TEST_F(AccountReconcilorDiceTest, UnverifiedAccountNoop) {
// Add a unverified account to the Gaia cookie.
signin::SetListAccountsResponseOneAccountWithParams(
{"user@gmail.com", "12345", true /* valid */, false /* signed_out */,
@@ -1523,13 +1352,12 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, UnverifiedAccountNoop) {
&test_url_loader_factory_);
// Check that nothing happens.
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(testing::_)).Times(0);
EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()).Times(0);
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(testing::_))
.Times(0);
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -1538,7 +1366,7 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, UnverifiedAccountNoop) {
// Checks that the reconcilor does not log out unverified accounts when adding
// a new account to the Gaia cookie.
-TEST_P(AccountReconcilorDiceEndpointParamTest, UnverifiedAccountMerge) {
+TEST_F(AccountReconcilorDiceTest, UnverifiedAccountMerge) {
// Add a unverified account to the Gaia cookie.
signin::SetListAccountsResponseOneAccountWithParams(
{"user@gmail.com", "12345", true /* valid */, false /* signed_out */,
@@ -1549,14 +1377,6 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, UnverifiedAccountMerge) {
const CoreAccountId chrome_account_id =
identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id;
- if (!IsMultiloginEnabled()) {
- // Check that the Chrome account is merged and the unverified account is not
- // logged out.
- EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(chrome_account_id))
- .Times(1);
- EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction())
- .Times(0);
- } else {
// In PRESERVE mode it is up to Gaia to not delete existing accounts in
// cookies and not sign out unveridied accounts.
std::vector<CoreAccountId> accounts_to_send = {chrome_account_id};
@@ -1564,27 +1384,17 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, UnverifiedAccountMerge) {
gaia::MultiloginMode::MULTILOGIN_PRESERVE_COOKIE_ACCOUNTS_ORDER,
accounts_to_send);
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
- }
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
- if (!IsMultiloginEnabled()) {
- SimulateAddAccountToCookieCompleted(
- reconcilor, chrome_account_id, GoogleServiceAuthError::AuthErrorNone());
- } else {
SimulateSetAccountsInCookieCompleted(
reconcilor, signin::SetAccountsInCookieResult::kSuccess);
- }
ASSERT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
}
-INSTANTIATE_TEST_SUITE_P(TestDiceEndpoint,
- AccountReconcilorDiceEndpointParamTest,
- ::testing::ValuesIn({false, true}));
-
TEST_F(AccountReconcilorTest, DiceDeleteCookie) {
SetAccountConsistency(signin::AccountConsistencyMethod::kDice);
@@ -1761,7 +1571,7 @@ TEST_P(AccountReconcilorTestMirrorMultilogin, TableRowTest) {
ASSERT_TRUE(reconcilor->first_execution_);
reconcilor->first_execution_ =
GetParam().is_first_reconcile == IsFirstReconcile::kFirst ? true : false;
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
SimulateSetAccountsInCookieCompleted(
reconcilor, signin::SetAccountsInCookieResult::kSuccess);
@@ -1881,7 +1691,7 @@ TEST_P(AccountReconcilorTestActiveDirectory, TableRowTestMultilogin) {
ASSERT_TRUE(reconcilor->first_execution_);
reconcilor->first_execution_ =
GetParam().is_first_reconcile == IsFirstReconcile::kFirst ? true : false;
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
if (GetParam().gaia_api_calls[0] != '\0') {
if (should_logout) {
SimulateLogOutFromCookieCompleted(
@@ -1923,7 +1733,7 @@ TEST_F(AccountReconcilorMirrorTest, TokensNotLoaded) {
identity_test_env()->ResetToAccountsNotYetLoadedFromDiskState();
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
// No reconcile when tokens are not loaded.
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -1937,6 +1747,7 @@ TEST_F(AccountReconcilorMirrorTest, TokensNotLoaded) {
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
ASSERT_TRUE(reconcilor->is_reconcile_started_);
+ EXPECT_EQ(AccountReconcilor::Trigger::kTokensLoaded, reconcilor->trigger_);
base::RunLoop().RunUntilIdle();
SimulateSetAccountsInCookieCompleted(
@@ -1965,7 +1776,7 @@ TEST_F(AccountReconcilorMirrorTest, GetAccountsFromCookieSuccess) {
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED,
reconcilor->GetState());
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING, reconcilor->GetState());
base::RunLoop().RunUntilIdle();
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING, reconcilor->GetState());
@@ -1999,7 +1810,7 @@ TEST_F(AccountReconcilorMirrorTest, EnableReconcileWhileAlreadyRunning) {
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED,
reconcilor->GetState());
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING, reconcilor->GetState());
reconcilor->EnableReconcile();
EXPECT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING, reconcilor->GetState());
@@ -2024,7 +1835,7 @@ TEST_F(AccountReconcilorMirrorTest, GetAccountsFromCookieFailure) {
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED,
reconcilor->GetState());
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING, reconcilor->GetState());
base::RunLoop().RunUntilIdle();
@@ -2061,7 +1872,7 @@ TEST_F(AccountReconcilorMirrorTest, ExtraCookieChangeNotification) {
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_SCHEDULED,
reconcilor->GetState());
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_RUNNING, reconcilor->GetState());
// Add extra cookie change notification. Reconcilor should ignore it.
@@ -2090,11 +1901,18 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileNoop) {
signin::SetListAccountsResponseOneAccount(
account_info.email, account_info.gaia, &test_url_loader_factory_);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
+
+ histogram_tester()->ExpectUniqueSample(
+ AccountReconcilor::kOperationHistogramName,
+ AccountReconcilor::Operation::kNoop, 1);
+ histogram_tester()->ExpectUniqueSample(
+ AccountReconcilor::kTriggerNoopHistogramName,
+ AccountReconcilor::Trigger::kCookieChange, 1);
}
TEST_F(AccountReconcilorMirrorTest, StartReconcileCookiesDisabled) {
@@ -2106,7 +1924,7 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileCookiesDisabled) {
AccountReconcilor* reconcilor = GetMockReconcilor();
ASSERT_TRUE(reconcilor);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_FALSE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
@@ -2135,6 +1953,8 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileContentSettings) {
SimulateCookieContentSettingsChanged(reconcilor,
ContentSettingsPattern::Wildcard());
ASSERT_TRUE(reconcilor->is_reconcile_started_);
+ EXPECT_EQ(AccountReconcilor::Trigger::kCookieSettingChange,
+ reconcilor->trigger_);
}
TEST_F(AccountReconcilorMirrorTest, StartReconcileContentSettingsGaiaUrl) {
@@ -2202,7 +2022,7 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileNoopWithDots) {
AccountReconcilor* reconcilor = GetMockReconcilor();
ASSERT_TRUE(reconcilor);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
}
@@ -2218,7 +2038,7 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileNoopMultiple) {
AccountReconcilor* reconcilor = GetMockReconcilor();
ASSERT_TRUE(reconcilor);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
}
@@ -2240,7 +2060,7 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileAddToCookie) {
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(reconcilor->is_reconcile_started_);
@@ -2255,6 +2075,19 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileAddToCookie) {
EXPECT_THAT(histogram_tester()->GetTotalCountsForPrefix(
"Signin.Reconciler.Duration.UpTo3mins.Success"),
testing::ContainerEq(expected_counts));
+
+ histogram_tester()->ExpectUniqueSample(
+ AccountReconcilor::kOperationHistogramName,
+ AccountReconcilor::Operation::kMultilogin, 1);
+ histogram_tester()->ExpectUniqueSample(
+ AccountReconcilor::kTriggerMultiloginHistogramName,
+ AccountReconcilor::Trigger::kCookieChange, 1);
+ histogram_tester()->ExpectTotalCount(
+ AccountReconcilor::kTriggerLogoutHistogramName, 0);
+ histogram_tester()->ExpectTotalCount(
+ AccountReconcilor::kTriggerNoopHistogramName, 0);
+ histogram_tester()->ExpectTotalCount(
+ AccountReconcilor::kTriggerThrottledHistogramName, 0);
}
TEST_F(AccountReconcilorTest, AuthErrorTriggersListAccount) {
@@ -2332,7 +2165,7 @@ TEST_F(AccountReconcilorMirrorTest, SignoutAfterErrorDoesNotRecordUma) {
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(reconcilor->is_reconcile_started_);
@@ -2366,7 +2199,7 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileRemoveFromCookie) {
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
@@ -2389,7 +2222,7 @@ TEST_F(AccountReconcilorMirrorTest, TokenErrorOnPrimary) {
&test_url_loader_factory_);
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
@@ -2416,7 +2249,7 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileAddToCookieTwice) {
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(ml_params_1));
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(reconcilor->is_reconcile_started_);
@@ -2443,6 +2276,7 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileAddToCookieTwice) {
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(reconcilor->is_reconcile_started_);
+ EXPECT_EQ(AccountReconcilor::Trigger::kTokenChange, reconcilor->trigger_);
SimulateSetAccountsInCookieCompleted(
reconcilor, signin::SetAccountsInCookieResult::kSuccess);
@@ -2468,7 +2302,7 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileBadPrimary) {
EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(params));
AccountReconcilor* reconcilor = GetMockReconcilor();
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(reconcilor->is_reconcile_started_);
@@ -2488,7 +2322,7 @@ TEST_F(AccountReconcilorMirrorTest, StartReconcileOnlyOnce) {
ASSERT_TRUE(reconcilor);
ASSERT_FALSE(reconcilor->is_reconcile_started_);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
@@ -2529,7 +2363,7 @@ TEST_F(AccountReconcilorMirrorTest, Lock) {
std::unique_ptr<AccountReconcilor::Lock> lock_1 =
std::make_unique<AccountReconcilor::Lock>(reconcilor);
EXPECT_EQ(1, reconcilor->account_reconcilor_lock_count_);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
// lock_1 is blocking the reconcile.
EXPECT_FALSE(reconcilor->is_reconcile_started_);
{
@@ -2551,6 +2385,8 @@ TEST_F(AccountReconcilorMirrorTest, Lock) {
EXPECT_EQ(1, observer.started_count_);
EXPECT_EQ(1, observer.unblocked_count_);
EXPECT_EQ(1, observer.blocked_count_);
+ EXPECT_EQ(AccountReconcilor::Trigger::kUnblockReconcile,
+ reconcilor->trigger_);
// Lock aborts current reconcile, and restarts it later.
{
@@ -2590,9 +2426,6 @@ TEST_P(AccountReconcilorMethodParamTest,
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(
@@ -2612,20 +2445,14 @@ TEST_P(AccountReconcilorMethodParamTest,
NOTREACHED();
break;
}
- }
ASSERT_FALSE(reconcilor->is_reconcile_started_);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
- if (!reconcilor->IsMultiloginEndpointEnabled()) {
- SimulateAddAccountToCookieCompleted(
- reconcilor, account_id, GoogleServiceAuthError::AuthErrorNone());
- } else {
SimulateSetAccountsInCookieCompleted(
reconcilor, signin::SetAccountsInCookieResult::kSuccess);
- }
ASSERT_FALSE(reconcilor->is_reconcile_started_);
}
@@ -2648,7 +2475,7 @@ TEST_F(AccountReconcilorMirrorTest,
ASSERT_TRUE(reconcilor);
ASSERT_FALSE(reconcilor->is_reconcile_started_);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
@@ -2685,7 +2512,7 @@ TEST_F(AccountReconcilorMirrorTest, NoLoopWithBadPrimary) {
AccountReconcilor* reconcilor = GetMockReconcilor();
ASSERT_TRUE(reconcilor);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(reconcilor->is_reconcile_started_);
@@ -2707,7 +2534,7 @@ TEST_F(AccountReconcilorMirrorTest, NoLoopWithBadPrimary) {
identity_test_env()->identity_manager(), account_id1, error);
// A second attempt to reconcile should be a noop.
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(reconcilor->is_reconcile_started_);
testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
@@ -2740,7 +2567,7 @@ TEST_F(AccountReconcilorMirrorTest, WontMergeAccountsWithError) {
AccountReconcilor* reconcilor = GetMockReconcilor();
ASSERT_TRUE(reconcilor);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(reconcilor->is_reconcile_started_);
@@ -2765,7 +2592,7 @@ TEST_F(AccountReconcilorTest, DelegateTimeoutIsCalled) {
base::MockOneShotTimer* timer = timer0.get();
reconcilor->set_timer_for_testing(std::move(timer0));
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
ASSERT_TRUE(timer->IsRunning());
@@ -2788,7 +2615,7 @@ TEST_F(AccountReconcilorMirrorTest, DelegateTimeoutIsNotCalled) {
base::MockOneShotTimer* timer = timer0.get();
reconcilor->set_timer_for_testing(std::move(timer0));
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
EXPECT_TRUE(reconcilor->is_reconcile_started_);
EXPECT_FALSE(timer->IsRunning());
}
@@ -2806,7 +2633,7 @@ TEST_F(AccountReconcilorTest, DelegateTimeoutIsNotCalledIfTimeoutIsNotReached) {
base::MockOneShotTimer* timer = timer0.get();
reconcilor->set_timer_for_testing(std::move(timer0));
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
ASSERT_TRUE(timer->IsRunning());
@@ -2870,13 +2697,23 @@ TEST_F(AccountReconcilorTest, MultiloginLogout) {
// No multilogin call.
EXPECT_CALL(*reconcilor, PerformSetCookiesAction(testing::_)).Times(0);
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
ASSERT_TRUE(reconcilor->is_reconcile_started_);
base::RunLoop().RunUntilIdle();
SimulateLogOutFromCookieCompleted(reconcilor,
GoogleServiceAuthError::AuthErrorNone());
EXPECT_FALSE(reconcilor->is_reconcile_started_);
ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState());
+ histogram_tester()->ExpectUniqueSample(
+ AccountReconcilor::kOperationHistogramName,
+ AccountReconcilor::Operation::kLogout, 1);
+ histogram_tester()->ExpectUniqueSample(
+ AccountReconcilor::kTriggerLogoutHistogramName,
+ AccountReconcilor::Trigger::kCookieChange, 1);
+ histogram_tester()->ExpectTotalCount(
+ AccountReconcilor::kTriggerThrottledHistogramName, 0);
+ histogram_tester()->ExpectTotalCount(
+ AccountReconcilor::kTriggerMultiloginHistogramName, 0);
}
// Reconcilor does not start after being shutdown. Regression test for
@@ -2887,7 +2724,8 @@ TEST_F(AccountReconcilorTest, ReconcileAfterShutdown) {
EXPECT_FALSE(reconcilor->WasShutDown());
reconcilor->Shutdown();
EXPECT_TRUE(reconcilor->WasShutDown());
- reconcilor->StartReconcile(); // This should not crash.
+ // This should not crash.
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
EXPECT_FALSE(reconcilor->is_reconcile_started_);
}
@@ -2901,10 +2739,229 @@ TEST_F(AccountReconcilorTest, UnlockAfterShutdown) {
// Reconcile does not start now because of the Lock, but is scheduled to start
// when the lock is released.
- reconcilor->StartReconcile();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
EXPECT_FALSE(reconcilor->is_reconcile_started_);
reconcilor->Shutdown();
lock.reset(); // This should not crash.
EXPECT_FALSE(reconcilor->is_reconcile_started_);
}
+
+class AccountReconcilorThrottlerTest : public AccountReconcilorTest {
+ public:
+ AccountReconcilorThrottlerTest() {
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+ signin::AccountConsistencyMethod account_consistency =
+ signin::AccountConsistencyMethod::kDice;
+ SetAccountConsistency(account_consistency);
+#else
+ signin::AccountConsistencyMethod account_consistency =
+ signin::AccountConsistencyMethod::kMirror;
+ SetAccountConsistency(account_consistency);
+#endif
+ minutes_to_refill_per_request_ =
+ 1 / AccountReconcilorThrottler::kRefillRequestsBucketRatePerMinute;
+ }
+
+ void ConsumeRequests(size_t number_of_requests,
+ const signin::MultiloginParameters& expected_params) {
+ AccountReconcilor* reconcilor = GetMockReconcilor();
+ for (size_t i = 0; i < number_of_requests; ++i) {
+ EXPECT_CALL(*GetMockReconcilor(),
+ PerformSetCookiesAction(expected_params));
+ ASSERT_FALSE(reconcilor->is_reconcile_started_);
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
+ base::RunLoop().RunUntilIdle();
+ // Reconciliation not blocked.
+ ASSERT_TRUE(reconcilor->is_reconcile_started_);
+
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
+ ASSERT_FALSE(reconcilor->is_reconcile_started_);
+ ASSERT_EQ(GoogleServiceAuthError::State::NONE,
+ reconcilor->error_during_last_reconcile_.state());
+ testing::Mock::VerifyAndClearExpectations(GetMockReconcilor());
+ }
+ }
+
+ void VerifyRequestsBlockedByThrottler() {
+ AccountReconcilor* reconcilor = GetMockReconcilor();
+ reconcilor->StartReconcile(AccountReconcilor::Trigger::kCookieChange);
+ base::RunLoop().RunUntilIdle();
+ // Reconciliation should fail.
+ ASSERT_FALSE(reconcilor->is_reconcile_started_);
+ ASSERT_EQ(GoogleServiceAuthError::State::REQUEST_CANCELED,
+ reconcilor->error_during_last_reconcile_.state());
+ }
+
+ void FastForwadTimeToRefillRequests(size_t number_of_requests) {
+ task_environment()->FastForwardBy(base::TimeDelta::FromMinutes(
+ minutes_to_refill_per_request_ * number_of_requests));
+ }
+
+ private:
+ size_t minutes_to_refill_per_request_;
+ DISALLOW_COPY_AND_ASSIGN(AccountReconcilorThrottlerTest);
+};
+
+TEST_F(AccountReconcilorThrottlerTest, RefillOneRequest) {
+ AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
+ const CoreAccountId account_id = account_info.account_id;
+ signin::SetListAccountsResponseOneAccount(
+ "other@gmail.com", signin::GetTestGaiaIdForEmail("other@gmail.com"),
+ &test_url_loader_factory_);
+
+ signin::MultiloginParameters params(
+ gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
+ {account_id});
+
+ // Consume all available requests.
+ ConsumeRequests(AccountReconcilorThrottler::kMaxAllowedRequestsPerBucket,
+ params);
+ histogram_tester()->ExpectUniqueSample(
+ AccountReconcilor::kTriggerMultiloginHistogramName,
+ AccountReconcilor::Trigger::kCookieChange, 30);
+ histogram_tester()->ExpectTotalCount(
+ AccountReconcilor::kTriggerThrottledHistogramName, 0);
+
+ // At this point all the requests in the available request buckets should
+ // have been consumed.
+ VerifyRequestsBlockedByThrottler();
+
+ // Allow enough time to refill 1 request.
+ FastForwadTimeToRefillRequests(1);
+ ConsumeRequests(1, params);
+
+ // The blocked request recorded upon allowing a new request.
+ histogram_tester()->ExpectBucketCount(
+ "Signin.Reconciler.RejectedRequestsDueToThrottler.Update", 1, 1);
+ histogram_tester()->ExpectBucketCount(
+ AccountReconcilor::kOperationHistogramName,
+ AccountReconcilor::Operation::kThrottled, 1);
+ histogram_tester()->ExpectUniqueSample(
+ AccountReconcilor::kTriggerThrottledHistogramName,
+ AccountReconcilor::Trigger::kCookieChange, 1);
+ histogram_tester()->ExpectBucketCount(
+ AccountReconcilor::kOperationHistogramName,
+ AccountReconcilor::Operation::kMultilogin, 31);
+ histogram_tester()->ExpectUniqueSample(
+ AccountReconcilor::kTriggerMultiloginHistogramName,
+ AccountReconcilor::Trigger::kCookieChange, 31);
+ histogram_tester()->ExpectTotalCount(
+ AccountReconcilor::kTriggerLogoutHistogramName, 0);
+ histogram_tester()->ExpectTotalCount(
+ AccountReconcilor::kTriggerNoopHistogramName, 0);
+
+ // No Available requests.
+ VerifyRequestsBlockedByThrottler();
+
+ DeleteReconcilor();
+ histogram_tester()->ExpectBucketCount(
+ "Signin.Reconciler.RejectedRequestsDueToThrottler.Update", 1, 2);
+}
+
+TEST_F(AccountReconcilorThrottlerTest, RefillFiveRequests) {
+ AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
+ const CoreAccountId account_id = account_info.account_id;
+ signin::SetListAccountsResponseOneAccount(
+ "other@gmail.com", signin::GetTestGaiaIdForEmail("other@gmail.com"),
+ &test_url_loader_factory_);
+
+ signin::MultiloginParameters params(
+ gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
+ {account_id});
+
+ // Consume all available requests.
+ ConsumeRequests(AccountReconcilorThrottler::kMaxAllowedRequestsPerBucket,
+ params);
+
+ // At this point all the requests in the available request buckets should
+ // have been consumed.
+ VerifyRequestsBlockedByThrottler();
+
+ // Allow enough time to refill 1 request.
+ FastForwadTimeToRefillRequests(5);
+ ConsumeRequests(5, params);
+
+ // The blocked request recorded upon allowing a new request.
+ histogram_tester()->ExpectBucketCount(
+ "Signin.Reconciler.RejectedRequestsDueToThrottler.Update", 1, 1);
+
+ // No Available requests.
+ VerifyRequestsBlockedByThrottler();
+
+ DeleteReconcilor();
+ histogram_tester()->ExpectBucketCount(
+ "Signin.Reconciler.RejectedRequestsDueToThrottler.Update", 1, 2);
+}
+
+TEST_F(AccountReconcilorThrottlerTest, NewRequestParamsPasses) {
+ AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
+ const CoreAccountId account_id = account_info.account_id;
+ signin::SetListAccountsResponseOneAccount(
+ "other@gmail.com", signin::GetTestGaiaIdForEmail("other@gmail.com"),
+ &test_url_loader_factory_);
+
+ signin::MultiloginParameters params(
+ gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
+ {account_id});
+
+ // Consume all available requests.
+ ConsumeRequests(AccountReconcilorThrottler::kMaxAllowedRequestsPerBucket,
+ params);
+
+ // Next request should fail.
+ VerifyRequestsBlockedByThrottler();
+
+ // Trigger different params.
+ AccountReconcilor* reconcilor = GetMockReconcilor();
+ EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(testing::_));
+ identity_test_env()->MakeAccountAvailable("other@gmail.com");
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(reconcilor->is_reconcile_started_);
+ SimulateSetAccountsInCookieCompleted(
+ reconcilor, signin::SetAccountsInCookieResult::kSuccess);
+ ASSERT_FALSE(reconcilor->is_reconcile_started_);
+
+ histogram_tester()->ExpectBucketCount(
+ "Signin.Reconciler.RejectedRequestsDueToThrottler.Update", 1, 1);
+}
+
+TEST_F(AccountReconcilorThrottlerTest, BlockFiveRequests) {
+ AccountInfo account_info = ConnectProfileToAccount("user@gmail.com");
+ const CoreAccountId account_id = account_info.account_id;
+ signin::SetListAccountsResponseOneAccount(
+ "other@gmail.com", signin::GetTestGaiaIdForEmail("other@gmail.com"),
+ &test_url_loader_factory_);
+
+ signin::MultiloginParameters params(
+ gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
+ {account_id});
+
+ // Consume all available requests.
+ ConsumeRequests(AccountReconcilorThrottler::kMaxAllowedRequestsPerBucket,
+ params);
+
+ // At this point all the requests in the available request buckets should
+ // have been consumed.
+ size_t rejected_requests = 5;
+ for (size_t i = 0; i < rejected_requests; ++i) {
+ VerifyRequestsBlockedByThrottler();
+ }
+
+ // Allow enough time to refill 1 request.
+ FastForwadTimeToRefillRequests(1);
+ ConsumeRequests(1, params);
+
+ // The blocked request recorded upon allowing a new request.
+ histogram_tester()->ExpectBucketCount(
+ "Signin.Reconciler.RejectedRequestsDueToThrottler.Update",
+ rejected_requests, 1);
+
+ // Allow a new request with no blocked requests in between.
+ FastForwadTimeToRefillRequests(1);
+ ConsumeRequests(1, params);
+ // The number of samples should remain 1.
+ histogram_tester()->ExpectTotalCount(
+ "Signin.Reconciler.RejectedRequestsDueToThrottler.Update", 1);
+}
diff --git a/chromium/components/signin/core/browser/chrome_connected_header_helper.cc b/chromium/components/signin/core/browser/chrome_connected_header_helper.cc
index 1a5205a5fc2..ea3ac36f547 100644
--- a/chromium/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/chromium/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -20,7 +20,8 @@
#include "url/gurl.h"
#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "components/signin/public/base/signin_switches.h"
+#include "chromeos/crosapi/mojom/crosapi.mojom.h"
+#include "chromeos/lacros/lacros_chrome_service_impl.h"
#endif
namespace signin {
@@ -39,7 +40,7 @@ const char kProfileModeAttrName[] = "mode";
const char kServiceTypeAttrName[] = "action";
const char kSupervisedAttrName[] = "supervised";
const char kSourceAttrName[] = "source";
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
const char kEligibleForConsistency[] = "eligible_for_consistency";
const char kShowConsistencyPromo[] = "show_consistency_promo";
#endif
@@ -83,7 +84,7 @@ std::string ChromeConnectedHeaderHelper::BuildRequestCookieIfPossible(
// this information in the ChromeConnected cookie.
return chrome_connected_helper.BuildRequestHeader(
false /* is_header_request */, url, gaia_id,
- base::nullopt /* is_child_account */, profile_mode_mask, "" /* source */,
+ absl::nullopt /* is_child_account */, profile_mode_mask, "" /* source */,
false /* force_account_consistency */);
}
@@ -108,7 +109,7 @@ ManageAccountsParams ChromeConnectedHeaderHelper::BuildManageAccountsParams(
params.continue_url = value;
} else if (key_name == kIsSameTabAttrName) {
params.is_same_tab = value == "true";
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
} else if (key_name == kShowConsistencyPromo) {
params.show_consistency_promo = value == "true";
#endif
@@ -187,7 +188,7 @@ std::string ChromeConnectedHeaderHelper::BuildRequestHeader(
bool is_header_request,
const GURL& url,
const std::string& gaia_id,
- const base::Optional<bool>& is_child_account,
+ const absl::optional<bool>& is_child_account,
int profile_mode_mask,
const std::string& source,
bool force_account_consistency) {
@@ -203,16 +204,12 @@ std::string ChromeConnectedHeaderHelper::BuildRequestHeader(
// Sessions and Active Directory logins. Guest Sessions have already been
// filtered upstream and we want to enforce account consistency in Public
// Sessions and Active Directory logins.
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
force_account_consistency = true;
-#elif BUILDFLAG(IS_CHROMEOS_LACROS)
- if (base::FeatureList::IsEnabled(switches::kUseAccountManagerFacade)) {
- force_account_consistency = true;
- }
#endif
if (!force_account_consistency && gaia_id.empty()) {
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
if (base::FeatureList::IsEnabled(kMobileIdentityConsistency) &&
gaia::IsGaiaSignonRealm(url.GetOrigin())) {
parts.push_back(
diff --git a/chromium/components/signin/core/browser/chrome_connected_header_helper.h b/chromium/components/signin/core/browser/chrome_connected_header_helper.h
index c17dc782c61..703f5d3747b 100644
--- a/chromium/components/signin/core/browser/chrome_connected_header_helper.h
+++ b/chromium/components/signin/core/browser/chrome_connected_header_helper.h
@@ -7,9 +7,9 @@
#include <string>
-#include "base/optional.h"
#include "components/signin/core/browser/signin_header_helper.h"
#include "components/signin/public/base/account_consistency_method.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -47,7 +47,7 @@ class ChromeConnectedHeaderHelper : public SigninHeaderHelper {
std::string BuildRequestHeader(bool is_header_request,
const GURL& url,
const std::string& gaia_id,
- const base::Optional<bool>& is_child_account,
+ const absl::optional<bool>& is_child_account,
int profile_mode_mask,
const std::string& source,
bool force_account_consistency);
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 08dd3c8f0e7..ee59bfb477c 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.cc
@@ -14,9 +14,6 @@
#include "components/signin/public/base/signin_client.h"
#include "components/signin/public/base/signin_pref_names.h"
-const base::Feature kUseMultiloginEndpoint{"UseMultiloginEndpoint",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
namespace signin {
DiceAccountReconcilorDelegate::DiceAccountReconcilorDelegate(
@@ -31,10 +28,6 @@ bool DiceAccountReconcilorDelegate::IsReconcileEnabled() const {
return true;
}
-bool DiceAccountReconcilorDelegate::IsMultiloginEndpointEnabled() const {
- return base::FeatureList::IsEnabled(kUseMultiloginEndpoint);
-}
-
DiceAccountReconcilorDelegate::InconsistencyReason
DiceAccountReconcilorDelegate::GetInconsistencyReason(
const CoreAccountId& primary_account,
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 534a2be68b8..55635846dd6 100644
--- a/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h
+++ b/chromium/components/signin/core/browser/dice_account_reconcilor_delegate.h
@@ -5,17 +5,12 @@
#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_DICE_ACCOUNT_RECONCILOR_DELEGATE_H_
#define COMPONENTS_SIGNIN_CORE_BROWSER_DICE_ACCOUNT_RECONCILOR_DELEGATE_H_
-#include <string>
-
#include "base/macros.h"
#include "components/signin/core/browser/account_reconcilor_delegate.h"
#include "components/signin/public/base/account_consistency_method.h"
class SigninClient;
-// Enables usage of Gaia Auth Multilogin endpoint for identity consistency.
-extern const base::Feature kUseMultiloginEndpoint;
-
namespace signin {
// AccountReconcilorDelegate specialized for Dice.
@@ -27,7 +22,6 @@ class DiceAccountReconcilorDelegate : public AccountReconcilorDelegate {
// AccountReconcilorDelegate:
bool IsReconcileEnabled() const override;
- bool IsMultiloginEndpointEnabled() const override;
gaia::GaiaSource GetGaiaApiSource() const override;
CoreAccountId GetFirstGaiaAccountForReconcile(
const std::vector<CoreAccountId>& chrome_accounts,
diff --git a/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.cc b/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.cc
index 2accff2fc0e..c1185dcc5dd 100644
--- a/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.cc
+++ b/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.cc
@@ -39,12 +39,19 @@ bool MirrorAccountReconcilorDelegate::ShouldAbortReconcileIfPrimaryHasError()
ConsentLevel MirrorAccountReconcilorDelegate::GetConsentLevelForPrimaryAccount()
const {
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_IOS)
if (base::FeatureList::IsEnabled(kMobileIdentityConsistency)) {
return ConsentLevel::kSignin;
}
-#endif
return ConsentLevel::kSync;
+#elif BUILDFLAG(IS_CHROMEOS_LACROS)
+ // Whenever Mirror is enabled on a Lacros Profile, the Primary Account may or
+ // may not have consented to Chrome Sync. But we want to enable
+ // `AccountReconcilor` regardless - for minting Gaia cookies.
+ return ConsentLevel::kSignin;
+#else
+ return ConsentLevel::kSync;
+#endif
}
CoreAccountId MirrorAccountReconcilorDelegate::GetFirstGaiaAccountForReconcile(
diff --git a/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.h b/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.h
index 192325ee2f5..08ff4ecd9ee 100644
--- a/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.h
+++ b/chromium/components/signin/core/browser/mirror_account_reconcilor_delegate.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_MIRROR_ACCOUNT_RECONCILOR_DELEGATE_H_
#define COMPONENTS_SIGNIN_CORE_BROWSER_MIRROR_ACCOUNT_RECONCILOR_DELEGATE_H_
-#include <string>
#include <vector>
#include "base/macros.h"
diff --git a/chromium/components/signin/core/browser/signin_error_controller.h b/chromium/components/signin/core/browser/signin_error_controller.h
index 8a5fcfb7dc9..3859c9bf97f 100644
--- a/chromium/components/signin/core/browser/signin_error_controller.h
+++ b/chromium/components/signin/core/browser/signin_error_controller.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_ERROR_CONTROLLER_H_
#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_ERROR_CONTROLLER_H_
-#include <string>
-
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
diff --git a/chromium/components/signin/core/browser/signin_header_helper.cc b/chromium/components/signin/core/browser/signin_header_helper.cc
index d8fabb6b2bf..8188d319443 100644
--- a/chromium/components/signin/core/browser/signin_header_helper.cc
+++ b/chromium/components/signin/core/browser/signin_header_helper.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_functions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "components/google/core/common/google_util.h"
#include "components/signin/core/browser/chrome_connected_header_helper.h"
@@ -24,6 +25,7 @@ namespace signin {
const char kChromeConnectedHeader[] = "X-Chrome-Connected";
const char kChromeManageAccountsHeader[] = "X-Chrome-Manage-Accounts";
+const char kAutoLoginHeader[] = "X-Auto-Login";
const char kDiceRequestHeader[] = "X-Chrome-ID-Consistency-Request";
const char kDiceResponseHeader[] = "X-Chrome-ID-Consistency-Response";
@@ -148,9 +150,9 @@ SigninHeaderHelper::ParseAccountConsistencyResponseHeader(
continue;
}
dictionary.insert(
- {field.substr(0, delim).as_string(),
+ {std::string(field.substr(0, delim)),
net::UnescapeURLComponent(
- field.substr(delim + 1).as_string(),
+ field.substr(delim + 1),
net::UnescapeRule::PATH_SEPARATORS |
net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS)});
}
@@ -167,7 +169,7 @@ void AppendOrRemoveMirrorRequestHeader(
RequestAdapter* request,
const GURL& redirect_url,
const std::string& gaia_id,
- const base::Optional<bool>& is_child_account,
+ const absl::optional<bool>& is_child_account,
AccountConsistencyMethod account_consistency,
const content_settings::CookieSettings* cookie_settings,
int profile_mode_mask,
diff --git a/chromium/components/signin/core/browser/signin_header_helper.h b/chromium/components/signin/core/browser/signin_header_helper.h
index bf76900e121..d87917cf169 100644
--- a/chromium/components/signin/core/browser/signin_header_helper.h
+++ b/chromium/components/signin/core/browser/signin_header_helper.h
@@ -40,6 +40,13 @@ extern const char kChromeManageAccountsHeader[];
extern const char kDiceRequestHeader[];
extern const char kDiceResponseHeader[];
+// The X-Auto-Login header detects when a user is prompted to enter their
+// credentials on the Gaia sign-in page. It is sent with an empty email if the
+// user is on the Gaia sign-in email page or a pre-filled email if the user has
+// selected an account on the AccountChooser. X-Auto-Login is not sent following
+// a reauth request.
+extern const char kAutoLoginHeader[];
+
// The ServiceType specified by Gaia in the response header accompanying the 204
// response. This indicates the action Chrome is supposed to lead the user to
// perform.
@@ -197,10 +204,6 @@ class SigninHeaderHelper {
const GURL& url,
const content_settings::CookieSettings* cookie_settings) = 0;
- protected:
- SigninHeaderHelper();
- virtual ~SigninHeaderHelper();
-
// Dictionary of fields in a account consistency response header.
using ResponseHeaderDictionary = std::multimap<std::string, std::string>;
@@ -209,6 +212,10 @@ class SigninHeaderHelper {
static ResponseHeaderDictionary ParseAccountConsistencyResponseHeader(
const std::string& header_value);
+ protected:
+ SigninHeaderHelper();
+ virtual ~SigninHeaderHelper();
+
// Returns whether the url is eligible for the request header.
virtual bool IsUrlEligibleForRequestHeader(const GURL& url) = 0;
@@ -238,7 +245,7 @@ void AppendOrRemoveMirrorRequestHeader(
RequestAdapter* request,
const GURL& redirect_url,
const std::string& gaia_id,
- const base::Optional<bool>& is_child_account,
+ const absl::optional<bool>& is_child_account,
AccountConsistencyMethod account_consistency,
const content_settings::CookieSettings* cookie_settings,
int profile_mode_mask,
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 b5e4ff3a984..ad5614f996d 100644
--- a/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
+++ b/chromium/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -27,7 +27,9 @@
#include "url/gurl.h"
#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "components/signin/public/base/signin_switches.h"
+#include "chromeos/lacros/lacros_chrome_service_delegate.h"
+#include "chromeos/lacros/lacros_chrome_service_impl.h"
+#include "chromeos/lacros/lacros_test_helper.h"
#endif
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
@@ -72,6 +74,14 @@ class SigninHeaderHelperTest : public testing::Test {
content_settings::CookieSettings::RegisterProfilePrefs(prefs_.registry());
HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+ // TODO(crbug.com/1198528): remove this after the rollout.
+ if (!chromeos::LacrosChromeServiceImpl::Get()) {
+ scoped_lacros_test_helper_ =
+ std::make_unique<chromeos::ScopedLacrosServiceTestHelper>();
+ }
+#endif
+
settings_map_ = new HostContentSettingsMap(
&prefs_, false /* is_off_the_record */, false /* store_last_modified */,
false /* restore_session */);
@@ -93,7 +103,7 @@ class SigninHeaderHelperTest : public testing::Test {
net::HttpRequestHeaders CreateRequest(
const GURL& url,
const std::string& account_id,
- const base::Optional<bool>& is_child_account) {
+ const absl::optional<bool>& is_child_account) {
net::HttpRequestHeaders original_headers;
RequestAdapterWrapper request_adapter(url, original_headers);
AppendOrRemoveMirrorRequestHeader(
@@ -121,7 +131,7 @@ class SigninHeaderHelperTest : public testing::Test {
void CheckMirrorHeaderRequest(const GURL& url,
const std::string& account_id,
- const base::Optional<bool>& is_child_account,
+ const absl::optional<bool>& is_child_account,
const std::string& expected_request) {
net::HttpRequestHeaders headers =
CreateRequest(url, account_id, is_child_account);
@@ -132,7 +142,7 @@ class SigninHeaderHelperTest : public testing::Test {
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
void CheckDiceHeaderRequest(const GURL& url,
const std::string& account_id,
- const base::Optional<bool>& is_child_account,
+ const absl::optional<bool>& is_child_account,
const std::string& expected_mirror_request,
const std::string& expected_dice_request) {
net::HttpRequestHeaders headers =
@@ -144,7 +154,7 @@ class SigninHeaderHelperTest : public testing::Test {
}
#endif
- base::test::SingleThreadTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
bool sync_enabled_ = false;
std::string device_id_ = kTestDeviceId;
@@ -154,6 +164,10 @@ class SigninHeaderHelperTest : public testing::Test {
sync_preferences::TestingPrefServiceSyncable prefs_;
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+ std::unique_ptr<chromeos::ScopedLacrosServiceTestHelper>
+ scoped_lacros_test_helper_;
+#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
scoped_refptr<HostContentSettingsMap> settings_map_;
scoped_refptr<content_settings::CookieSettings> cookie_settings_;
};
@@ -163,24 +177,25 @@ class SigninHeaderHelperTest : public testing::Test {
// account id).
TEST_F(SigninHeaderHelperTest, TestMirrorRequestNoAccountIdChromeOS) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
- if (!base::FeatureList::IsEnabled(switches::kUseAccountManagerFacade)) {
+ const crosapi::mojom::BrowserInitParams* init_params =
+ chromeos::LacrosChromeServiceImpl::Get()->init_params();
+ if (!init_params->use_new_account_manager)
return;
- }
#endif
account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(
GURL("https://docs.google.com"), /*gaia_id=*/"",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,mode=0,enable_account_consistency=true,"
"consistency_enabled_by_default=false");
CheckMirrorCookieRequest(GURL("https://docs.google.com"), /*gaia_id=*/"",
"mode=0:enable_account_consistency=true:"
"consistency_enabled_by_default=false");
}
-#else // !BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
-#if defined(OS_ANDROID) || defined(OS_IOS)
-// Tests that eligible_for_consistency request is returned on mobile (Android,
-// iOS) when reaching to Gaia origin and there's no primary account. Only
+#else // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if defined(OS_ANDROID)
+// Tests that eligible_for_consistency request is returned on Android
+// when reaching to Gaia origin and there's no primary account. Only
// applicable when the Mobile Identity Consistency is enabled.
TEST_F(SigninHeaderHelperTest, TestEligibleForConsistencyRequestGaiaOrigin) {
base::test::ScopedFeatureList feature_list;
@@ -188,15 +203,15 @@ TEST_F(SigninHeaderHelperTest, TestEligibleForConsistencyRequestGaiaOrigin) {
account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(GURL("https://accounts.google.com"), /*gaia_id=*/"",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,eligible_for_consistency=true");
CheckMirrorCookieRequest(GURL("https://accounts.google.com"), /*gaia_id=*/"",
"eligible_for_consistency=true");
}
-// Tests that eligible_for_consistency request is NOT returned on mobile
-// (Android, iOS) when reaching to NON-Gaia origin and there's no primary
-// account. Only applicable when the Mobile Identity Consistency is enabled.
+// Tests that eligible_for_consistency request is NOT returned on Android
+// when reaching to NON-Gaia origin and there's no primary account
+// Only applicable when the Mobile Identity Consistency is enabled.
TEST_F(SigninHeaderHelperTest,
TestNoEligibleForConsistencyRequestNonGaiaOrigin) {
base::test::ScopedFeatureList feature_list;
@@ -204,7 +219,7 @@ TEST_F(SigninHeaderHelperTest,
account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(GURL("https://docs.google.com"), /*gaia_id=*/"",
- /*is_child_account=*/base::nullopt, "");
+ /*is_child_account=*/absl::nullopt, "");
CheckMirrorCookieRequest(GURL("https://docs.google.com"), /*gaia_id=*/"", "");
}
@@ -218,18 +233,18 @@ TEST_F(SigninHeaderHelperTest, TestForceAccountConsistencyMobile) {
force_account_consistency_ = true;
CheckMirrorHeaderRequest(
GURL("https://docs.google.com"), /*gaia_id=*/"",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,mode=0,enable_account_consistency=true,"
"consistency_enabled_by_default=false");
}
-#endif // defined(OS_ANDROID) || defined(OS_IOS)
+#endif // defined(OS_ANDROID)
// Tests that no Mirror request is returned when the user is not signed in (no
// account id), for non Chrome OS platforms.
TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestNoAccountId) {
account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(GURL("https://docs.google.com"), /*gaia_id=*/"",
- /*is_child_account=*/base::nullopt, "");
+ /*is_child_account=*/absl::nullopt, "");
CheckMirrorCookieRequest(GURL("https://docs.google.com"), /*gaia_id=*/"", "");
}
#endif
@@ -240,7 +255,7 @@ TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestCookieSettingBlocked) {
account_consistency_ = AccountConsistencyMethod::kMirror;
cookie_settings_->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
CheckMirrorHeaderRequest(GURL("https://docs.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt, "");
+ /*is_child_account=*/absl::nullopt, "");
CheckMirrorCookieRequest(GURL("https://docs.google.com"), "0123456789", "");
}
@@ -248,7 +263,7 @@ TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestCookieSettingBlocked) {
TEST_F(SigninHeaderHelperTest, TestNoMirrorRequestExternalURL) {
account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(GURL("https://foo.com"), "0123456789",
- /*is_child_account=*/base::nullopt, "");
+ /*is_child_account=*/absl::nullopt, "");
CheckMirrorCookieRequest(GURL("https://foo.com"), "0123456789", "");
}
@@ -258,7 +273,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleTLD) {
account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(
GURL("https://google.fr"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,mode=0,enable_account_consistency=true,"
"consistency_enabled_by_default=false");
CheckMirrorCookieRequest(GURL("https://google.de"), "0123456789",
@@ -272,7 +287,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleCom) {
account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(
GURL("https://www.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,mode=0,enable_account_consistency=true,"
"consistency_enabled_by_default=false");
CheckMirrorCookieRequest(GURL("https://www.google.com"), "0123456789",
@@ -287,7 +302,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleComNoProfileConsistency) {
original_headers);
AppendOrRemoveMirrorRequestHeader(
request_adapter.adapter(), GURL(), "0123456789",
- /*is_child_account=*/base::nullopt, account_consistency_,
+ /*is_child_account=*/absl::nullopt, account_consistency_,
cookie_settings_.get(), PROFILE_MODE_DEFAULT, kTestSource,
false /* force_account_consistency */);
CheckAccountConsistencyHeaderRequest(request_adapter.GetFinalHeaders(),
@@ -302,7 +317,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleComProfileConsistency) {
original_headers);
AppendOrRemoveMirrorRequestHeader(
request_adapter.adapter(), GURL(), "0123456789",
- /*is_child_account=*/base::nullopt, account_consistency_,
+ /*is_child_account=*/absl::nullopt, account_consistency_,
cookie_settings_.get(), PROFILE_MODE_DEFAULT, kTestSource,
false /* force_account_consistency */);
CheckAccountConsistencyHeaderRequest(
@@ -315,17 +330,17 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGoogleComSupervised) {
account_consistency_ = AccountConsistencyMethod::kMirror;
CheckMirrorHeaderRequest(
GURL("https://www.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,mode=0,enable_account_consistency=true,"
"consistency_enabled_by_default=false");
CheckMirrorHeaderRequest(
GURL("https://www.google.com"), "0123456789",
- /*is_child_account=*/base::Optional<bool>(true),
+ /*is_child_account=*/absl::optional<bool>(true),
"source=TestSource,mode=0,enable_account_consistency=true,"
"supervised=true,consistency_enabled_by_default=false");
CheckMirrorHeaderRequest(
GURL("https://www.google.com"), "0123456789",
- /*is_child_account=*/base::Optional<bool>(false),
+ /*is_child_account=*/absl::optional<bool>(false),
"source=TestSource,mode=0,enable_account_consistency=true,"
"supervised=false,consistency_enabled_by_default=false");
}
@@ -338,7 +353,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGaiaURL) {
// No request when account consistency is disabled.
account_consistency_ = AccountConsistencyMethod::kDisabled;
CheckMirrorHeaderRequest(GURL("https://accounts.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
/*expected_request=*/"");
CheckMirrorCookieRequest(GURL("https://accounts.google.com"), "0123456789",
/*expected_request=*/"");
@@ -347,7 +362,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGaiaURL) {
// No request when Mirror account consistency enabled, but user not signed in
// to Chrome.
CheckMirrorHeaderRequest(GURL("https://accounts.google.com"), /*gaia_id=*/"",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
/*expected_request=*/"");
CheckMirrorCookieRequest(GURL("https://accounts.google.com"), /*gaia_id=*/"",
/*expected_request=*/"");
@@ -356,7 +371,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorRequestGaiaURL) {
// signed in to Chrome.
CheckMirrorHeaderRequest(
GURL("https://accounts.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,mode=0,enable_account_consistency=true,"
"consistency_enabled_by_default=false");
CheckMirrorCookieRequest(GURL("https://accounts.google.com"), "0123456789",
@@ -370,7 +385,7 @@ TEST_F(SigninHeaderHelperTest, TestDiceRequest) {
// ChromeConnected but no Dice for Docs URLs.
CheckDiceHeaderRequest(
GURL("https://docs.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,id=0123456789,mode=0,enable_account_consistency=false,"
"consistency_enabled_by_default=false",
/*expected_dice_request=*/"");
@@ -381,7 +396,7 @@ TEST_F(SigninHeaderHelperTest, TestDiceRequest) {
ASSERT_FALSE(client_id.empty());
CheckDiceHeaderRequest(
GURL("https://accounts.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
/*expected_mirror_request=*/"",
base::StringPrintf(
"version=%s,client_id=%s,device_id=DeviceID,signin_mode=all_accounts,"
@@ -392,7 +407,7 @@ TEST_F(SigninHeaderHelperTest, TestDiceRequest) {
sync_enabled_ = true;
CheckDiceHeaderRequest(
GURL("https://accounts.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
/*expected_mirror_request=*/"",
base::StringPrintf("version=%s,client_id=%s,device_id=DeviceID,"
"sync_account_id=0123456789,signin_mode=all_accounts,"
@@ -402,7 +417,7 @@ TEST_F(SigninHeaderHelperTest, TestDiceRequest) {
// No ChromeConnected and no Dice for other URLs.
CheckDiceHeaderRequest(GURL("https://www.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
/*expected_mirror_request=*/"",
/*expected_dice_request=*/"");
}
@@ -416,7 +431,7 @@ TEST_F(SigninHeaderHelperTest, DiceCookiesBlocked) {
ASSERT_FALSE(client_id.empty());
CheckDiceHeaderRequest(
GURL("https://accounts.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt, "",
+ /*is_child_account=*/absl::nullopt, "",
base::StringPrintf(
"version=%s,client_id=%s,device_id=DeviceID,signin_mode=all_accounts,"
"signout_mode=show_confirmation",
@@ -428,7 +443,7 @@ TEST_F(SigninHeaderHelperTest, TestNoDiceRequestWhenDisabled) {
account_consistency_ = AccountConsistencyMethod::kMirror;
CheckDiceHeaderRequest(
GURL("https://accounts.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,mode=0,enable_account_consistency=true,"
"consistency_enabled_by_default=false",
"");
@@ -443,7 +458,7 @@ TEST_F(SigninHeaderHelperTest, TestDiceEmptyDeviceID) {
CheckDiceHeaderRequest(
GURL("https://accounts.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
/*expected_mirror_request=*/"",
base::StringPrintf("version=%s,client_id=%s,signin_mode=all_accounts,"
"signout_mode=show_confirmation",
@@ -458,7 +473,7 @@ TEST_F(SigninHeaderHelperTest, TestSignoutConfirmation) {
CheckDiceHeaderRequest(
GURL("https://accounts.google.com"), "0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
/*expected_mirror_request=*/"",
base::StringPrintf(
"version=%s,client_id=%s,device_id=DeviceID,signin_mode=all_accounts,"
@@ -477,7 +492,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderRequestDriveSignedOut) {
AccountConsistencyMethod::kMirror, AccountConsistencyMethod::kDice}) {
account_consistency_ = account_consistency;
CheckMirrorHeaderRequest(url, /*gaia_id=*/"",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
/*expected_request=*/"");
CheckMirrorCookieRequest(url, /*gaia_id=*/"",
/*expected_request=*/"");
@@ -494,7 +509,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderRequestDriveSignedIn) {
// Request with Gaia ID when Mirror account consistency is enabled and user
// is signed in to Chrome.
CheckMirrorHeaderRequest(url, /*gaia_id=*/"0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,id=0123456789,mode=0,enable_"
"account_consistency=true,"
"consistency_enabled_by_default=false");
@@ -508,7 +523,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderRequestDriveSignedIn) {
// Request with Gaia ID when DICE account consistency is enabled and user is
// opted in to sycn.
CheckMirrorHeaderRequest(url, /*gaia_id=*/"0123456789",
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
"source=TestSource,id=0123456789,mode=0,enable_"
"account_consistency=false,"
"consistency_enabled_by_default=false");
@@ -658,7 +673,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderEligibleRedirectURL) {
RequestAdapterWrapper request_adapter(url, original_headers);
AppendOrRemoveMirrorRequestHeader(
request_adapter.adapter(), redirect_url, account_id,
- /*is_child_account=*/base::nullopt, account_consistency_,
+ /*is_child_account=*/absl::nullopt, account_consistency_,
cookie_settings_.get(), PROFILE_MODE_DEFAULT, kTestSource,
false /* force_account_consistency */);
EXPECT_TRUE(
@@ -677,7 +692,7 @@ TEST_F(SigninHeaderHelperTest, TestMirrorHeaderNonEligibleRedirectURL) {
RequestAdapterWrapper request_adapter(url, original_headers);
AppendOrRemoveMirrorRequestHeader(
request_adapter.adapter(), redirect_url, account_id,
- /*is_child_account=*/base::nullopt, account_consistency_,
+ /*is_child_account=*/absl::nullopt, account_consistency_,
cookie_settings_.get(), PROFILE_MODE_DEFAULT, kTestSource,
false /* force_account_consistency */);
EXPECT_FALSE(
@@ -697,7 +712,7 @@ TEST_F(SigninHeaderHelperTest, TestIgnoreMirrorHeaderNonEligibleURLs) {
RequestAdapterWrapper request_adapter(url, original_headers);
AppendOrRemoveMirrorRequestHeader(
request_adapter.adapter(), redirect_url, account_id,
- /*is_child_account=*/base::nullopt, account_consistency_,
+ /*is_child_account=*/absl::nullopt, account_consistency_,
cookie_settings_.get(), PROFILE_MODE_DEFAULT, kTestSource,
false /* force_account_consistency */);
std::string header;
@@ -730,7 +745,7 @@ TEST_F(SigninHeaderHelperTest, TestBuildManageAccountsParams) {
EXPECT_EQ(true, params.is_saml);
EXPECT_EQ(true, params.is_same_tab);
EXPECT_EQ(GURL(kContinueURL), params.continue_url);
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
EXPECT_EQ(true, params.show_consistency_promo);
#endif
}
diff --git a/chromium/components/signin/core/browser/signin_internals_util.h b/chromium/components/signin/core/browser/signin_internals_util.h
index dc6a0e240ea..09e80e87532 100644
--- a/chromium/components/signin/core/browser/signin_internals_util.h
+++ b/chromium/components/signin/core/browser/signin_internals_util.h
@@ -11,7 +11,6 @@
#include <memory>
#include <string>
-#include "base/values.h"
namespace signin_internals_util {
diff --git a/chromium/components/signin/internal/identity_manager/BUILD.gn b/chromium/components/signin/internal/identity_manager/BUILD.gn
index 8f54d7a1cc9..171d8a0719b 100644
--- a/chromium/components/signin/internal/identity_manager/BUILD.gn
+++ b/chromium/components/signin/internal/identity_manager/BUILD.gn
@@ -96,6 +96,14 @@ source_set("identity_manager") {
deps += [ "//components/user_manager" ]
} else {
+ if (is_chromeos_lacros) {
+ # TODO(bsazonov): Simplify this after removing profile_oauth2_token_service_delegate_chromeos_legacy.
+ sources += [
+ "profile_oauth2_token_service_delegate_chromeos.cc",
+ "profile_oauth2_token_service_delegate_chromeos.h",
+ ]
+ deps += [ "//components/account_manager_core" ]
+ }
sources += [
"primary_account_policy_manager_impl.cc",
"primary_account_policy_manager_impl.h",
@@ -159,6 +167,7 @@ source_set("unit_tests") {
"//components/signin/public/base:signin_buildflags",
"//components/signin/public/base:test_support",
"//components/signin/public/identity_manager",
+ "//components/signin/public/identity_manager:test_support",
"//components/signin/public/webdata",
"//components/sync_preferences:test_support",
"//components/webdata/common",
@@ -173,8 +182,6 @@ source_set("unit_tests") {
if (is_android) {
sources += [ "profile_oauth2_token_service_delegate_android_unittest.cc" ]
-
- deps += [ "//components/signin/public/identity_manager:test_support" ]
}
if (is_chromeos_ash) {
diff --git a/chromium/components/signin/internal/identity_manager/account_info_util.cc b/chromium/components/signin/internal/identity_manager/account_info_util.cc
index cb77753ba13..7e2d28d222f 100644
--- a/chromium/components/signin/internal/identity_manager/account_info_util.cc
+++ b/chromium/components/signin/internal/identity_manager/account_info_util.cc
@@ -18,22 +18,22 @@ const char kLocaleKey[] = "locale";
const char kPictureUrlKey[] = "picture";
} // namespace
-base::Optional<AccountInfo> AccountInfoFromUserInfo(
+absl::optional<AccountInfo> AccountInfoFromUserInfo(
const base::Value& user_info) {
if (!user_info.is_dict())
- return base::nullopt;
+ return absl::nullopt;
// Both |gaia_id| and |email| are required value in the JSON reply, so
// return empty result if any is missing.
const base::Value* gaia_id_value =
user_info.FindKeyOfType(kGaiaIdKey, base::Value::Type::STRING);
if (!gaia_id_value)
- return base::nullopt;
+ return absl::nullopt;
const base::Value* email_value =
user_info.FindKeyOfType(kEmailKey, base::Value::Type::STRING);
if (!email_value)
- return base::nullopt;
+ return absl::nullopt;
AccountInfo account_info;
account_info.email = email_value->GetString();
diff --git a/chromium/components/signin/internal/identity_manager/account_info_util.h b/chromium/components/signin/internal/identity_manager/account_info_util.h
index 53207e5c483..74330a7bbc3 100644
--- a/chromium/components/signin/internal/identity_manager/account_info_util.h
+++ b/chromium/components/signin/internal/identity_manager/account_info_util.h
@@ -5,13 +5,13 @@
#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_INFO_UTIL_H_
#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_INFO_UTIL_H_
-#include "base/optional.h"
#include "base/values.h"
#include "components/signin/public/identity_manager/account_info.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
// Builds an AccountInfo from the JSON data returned by the gaia servers (the
// data should have been converted to base::Value), if possible.
-base::Optional<AccountInfo> AccountInfoFromUserInfo(
+absl::optional<AccountInfo> AccountInfoFromUserInfo(
const base::Value& user_info);
#endif // COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_ACCOUNT_INFO_UTIL_H_
diff --git a/chromium/components/signin/internal/identity_manager/account_info_util_unittest.cc b/chromium/components/signin/internal/identity_manager/account_info_util_unittest.cc
index cc658a06104..a3aa467d47f 100644
--- a/chromium/components/signin/internal/identity_manager/account_info_util_unittest.cc
+++ b/chromium/components/signin/internal/identity_manager/account_info_util_unittest.cc
@@ -49,7 +49,7 @@ using AccountInfoUtilTest = PlatformTest;
// Tests that AccountInfoFromUserInfo returns an AccountInfo with the value
// extracted from the passed base::Value.
TEST_F(AccountInfoUtilTest, FromUserInfo) {
- base::Optional<AccountInfo> maybe_account_info =
+ absl::optional<AccountInfo> maybe_account_info =
AccountInfoFromUserInfo(CreateUserInfoWithValues(
/*email=*/"user@example.com", /*gaia=*/"gaia_id_user_example_com",
/*hosted_domain=*/"example.com", /*full_name=*/"full name",
@@ -71,7 +71,7 @@ TEST_F(AccountInfoUtilTest, FromUserInfo) {
// Tests that AccountInfoFromUserInfo returns an AccountInfo with empty or
// default values if no fields are set in the user_info.
TEST_F(AccountInfoUtilTest, FromUserInfo_EmptyValues) {
- base::Optional<AccountInfo> maybe_account_info =
+ absl::optional<AccountInfo> maybe_account_info =
AccountInfoFromUserInfo(CreateUserInfoWithValues(
/*email=*/"", /*gaia=*/"", /*hosted_domain=*/"", /*full_name=*/"",
/*given_name=*/"", /*locale=*/"", /*picture_url=*/""));
@@ -92,7 +92,7 @@ TEST_F(AccountInfoUtilTest, FromUserInfo_EmptyValues) {
// extracted from the passed base::Value, with default value for |hosted_domain|
// if missing.
TEST_F(AccountInfoUtilTest, FromUserInfo_NoHostedDomain) {
- base::Optional<AccountInfo> maybe_account_info =
+ absl::optional<AccountInfo> maybe_account_info =
AccountInfoFromUserInfo(CreateUserInfoWithValues(
/*email=*/"user@example.com", /*gaia=*/"gaia_id_user_example_com",
/*hosted_domain=*/nullptr, /*full_name=*/"full name",
@@ -109,7 +109,7 @@ TEST_F(AccountInfoUtilTest, FromUserInfo_NoHostedDomain) {
// extracted from the passed base::Value, with default value for |picture_url|
// if missing.
TEST_F(AccountInfoUtilTest, FromUserInfo_NoPictureUrl) {
- base::Optional<AccountInfo> maybe_account_info =
+ absl::optional<AccountInfo> maybe_account_info =
AccountInfoFromUserInfo(CreateUserInfoWithValues(
/*email=*/"user@example.com", /*gaia=*/"gaia_id_user_example_com",
/*hosted_domain=*/"example.com", /*full_name=*/"full name",
@@ -125,7 +125,7 @@ TEST_F(AccountInfoUtilTest, FromUserInfo_NoPictureUrl) {
// Tests that if AccountInfoFromUserInfo fails if the value passed has no
// value for |email|.
TEST_F(AccountInfoUtilTest, FromUserInfo_NoEmail) {
- base::Optional<AccountInfo> maybe_account_info =
+ absl::optional<AccountInfo> maybe_account_info =
AccountInfoFromUserInfo(CreateUserInfoWithValues(
/*email=*/nullptr, /*gaia=*/"gaia_id_user_example_com",
/*hosted_domain=*/"example.com", /*full_name=*/"full name",
@@ -138,7 +138,7 @@ TEST_F(AccountInfoUtilTest, FromUserInfo_NoEmail) {
// Tests that if AccountInfoFromUserInfo fails if the value passed has no
// value for |gaia|.
TEST_F(AccountInfoUtilTest, FromUserInfo_NoGaiaId) {
- base::Optional<AccountInfo> maybe_account_info =
+ absl::optional<AccountInfo> maybe_account_info =
AccountInfoFromUserInfo(CreateUserInfoWithValues(
/*email=*/"user@example.com", /*gaia=*/nullptr,
/*hosted_domain=*/"example.com", /*full_name=*/"full name",
@@ -151,7 +151,7 @@ TEST_F(AccountInfoUtilTest, FromUserInfo_NoGaiaId) {
// Tests that if AccountInfoFromUserInfo fails if the value passed is not a
// dictionary.
TEST_F(AccountInfoUtilTest, FromUserInfo_NotADictionary) {
- base::Optional<AccountInfo> maybe_account_info =
+ absl::optional<AccountInfo> maybe_account_info =
AccountInfoFromUserInfo(base::Value("not a dictionary"));
EXPECT_FALSE(maybe_account_info.has_value());
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 68944ea785b..44a587f233e 100644
--- a/chromium/components/signin/internal/identity_manager/account_tracker_service.cc
+++ b/chromium/components/signin/internal/identity_manager/account_tracker_service.cc
@@ -238,7 +238,7 @@ void AccountTrackerService::SetAccountInfoFromUserInfo(
DCHECK(base::Contains(accounts_, account_id));
AccountInfo& account_info = accounts_[account_id];
- base::Optional<AccountInfo> maybe_account_info =
+ absl::optional<AccountInfo> maybe_account_info =
AccountInfoFromUserInfo(*user_info);
if (maybe_account_info) {
// Should we DCHECK that the account stored in |accounts_| has the same
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 e52e1547813..276f18b3f51 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
@@ -36,7 +36,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_ANDROID)
-#include "components/signin/internal/identity_manager/child_account_info_fetcher_android.h"
+#include "components/signin/public/identity_manager/identity_test_utils.h"
#endif
namespace {
@@ -177,7 +177,9 @@ class AccountTrackerServiceTest : public testing::Test {
: signin_client_(&pref_service_),
fake_oauth2_token_service_(&pref_service_) {
#if defined(OS_ANDROID)
- ChildAccountInfoFetcherAndroid::InitializeForTests();
+ // Mock AccountManagerFacade in java code for tests that require its
+ // initialization.
+ signin::SetUpMockAccountManagerFacade();
#endif
AccountTrackerService::RegisterPrefs(pref_service_.registry());
diff --git a/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc b/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc
index d03c005f806..8ce9809a78d 100644
--- a/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc
+++ b/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc
@@ -116,4 +116,13 @@ void AccountsCookieMutatorImpl::LogOutAllAccounts(
source, std::move(completion_callback));
}
+void AccountsCookieMutatorImpl::RemoveLoggedOutAccountByGaiaId(
+ const std::string& gaia_id) {
+ // Note that RemoveLoggedOutAccountByGaiaId() does NOT internally trigger a
+ // ListAccounts fetch. It could make sense to force a request here, e.g. via
+ // ForceOnCookieChangeProcessing(), but this isn't considered important enough
+ // to justify the risk for overloading the server.
+ gaia_cookie_manager_service_->RemoveLoggedOutAccountByGaiaId(gaia_id);
+}
+
} // namespace signin
diff --git a/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h b/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h
index cf8dc8e6d5b..d98f0afc47a 100644
--- a/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h
+++ b/chromium/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.h
@@ -69,6 +69,8 @@ class AccountsCookieMutatorImpl : public AccountsCookieMutator {
gaia::GaiaSource source,
LogOutFromCookieCompletedCallback completion_callback) override;
+ void RemoveLoggedOutAccountByGaiaId(const std::string& gaia_id) override;
+
private:
class MultiloginHelperWrapper : public SetAccountsInCookieTask {
public:
diff --git a/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.cc b/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.cc
index ab5c2d7499e..f939edfcec3 100644
--- a/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.cc
+++ b/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.cc
@@ -4,7 +4,6 @@
#include "components/signin/internal/identity_manager/accounts_mutator_impl.h"
-#include "base/optional.h"
#include "build/chromeos_buildflags.h"
#include "components/prefs/pref_service.h"
#include "components/signin/internal/identity_manager/account_tracker_service.h"
@@ -15,6 +14,7 @@
#include "components/signin/public/identity_manager/account_info.h"
#include "google_apis/gaia/core_account_id.h"
#include "google_apis/gaia/gaia_constants.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace signin {
@@ -63,8 +63,8 @@ CoreAccountId AccountsMutatorImpl::AddOrUpdateAccount(
void AccountsMutatorImpl::UpdateAccountInfo(
const CoreAccountId& account_id,
- base::Optional<bool> is_child_account,
- base::Optional<bool> is_under_advanced_protection) {
+ absl::optional<bool> is_child_account,
+ absl::optional<bool> is_under_advanced_protection) {
if (is_child_account.has_value()) {
account_tracker_service_->SetIsChildAccount(account_id,
is_child_account.value());
diff --git a/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.h b/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.h
index 742b026de0b..19cc2c096ae 100644
--- a/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.h
+++ b/chromium/components/signin/internal/identity_manager/accounts_mutator_impl.h
@@ -42,8 +42,8 @@ class AccountsMutatorImpl : public AccountsMutator {
signin_metrics::SourceForRefreshTokenOperation source) override;
void UpdateAccountInfo(
const CoreAccountId& account_id,
- base::Optional<bool> is_child_account,
- base::Optional<bool> is_under_advanced_protection) override;
+ absl::optional<bool> is_child_account,
+ absl::optional<bool> is_under_advanced_protection) override;
void RemoveAccount(
const CoreAccountId& account_id,
signin_metrics::SourceForRefreshTokenOperation source) override;
diff --git a/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.cc b/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.cc
index e8bad35a5bf..b59fe1cd5e5 100644
--- a/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.cc
+++ b/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.cc
@@ -31,11 +31,6 @@ ChildAccountInfoFetcherAndroid::Create(AccountFetcherService* service,
new ChildAccountInfoFetcherAndroid(service, account_info));
}
-void ChildAccountInfoFetcherAndroid::InitializeForTests() {
- signin::Java_ChildAccountInfoFetcher_initializeForTests(
- base::android::AttachCurrentThread());
-}
-
ChildAccountInfoFetcherAndroid::ChildAccountInfoFetcherAndroid(
AccountFetcherService* service,
const CoreAccountInfo& account_info) {
diff --git a/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.h b/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.h
index e51b1334922..864e7347945 100644
--- a/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.h
+++ b/chromium/components/signin/internal/identity_manager/child_account_info_fetcher_android.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_CHILD_ACCOUNT_INFO_FETCHER_ANDROID_H_
#include <jni.h>
-#include <string>
#include "base/android/scoped_java_ref.h"
#include "components/signin/public/identity_manager/account_info.h"
diff --git a/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc b/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc
index 2d732c23a33..f284e6a8ca0 100644
--- a/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc
+++ b/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.cc
@@ -19,7 +19,7 @@ DeviceAccountsSynchronizerImpl::~DeviceAccountsSynchronizerImpl() = default;
void DeviceAccountsSynchronizerImpl::
ReloadAllAccountsFromSystemWithPrimaryAccount(
- const base::Optional<CoreAccountId>& primary_account_id) {
+ const absl::optional<CoreAccountId>& primary_account_id) {
token_service_delegate_->ReloadAllAccountsFromSystemWithPrimaryAccount(
primary_account_id);
}
diff --git a/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h b/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h
index 0ee9d2fdd56..e2283bc8dde 100644
--- a/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h
+++ b/chromium/components/signin/internal/identity_manager/device_accounts_synchronizer_impl.h
@@ -21,7 +21,7 @@ class DeviceAccountsSynchronizerImpl : public DeviceAccountsSynchronizer {
// DeviceAccountsSynchronizer implementation.
void ReloadAllAccountsFromSystemWithPrimaryAccount(
- const base::Optional<CoreAccountId>& primary_account_id) override;
+ const absl::optional<CoreAccountId>& primary_account_id) override;
#if defined(OS_IOS)
void ReloadAccountFromSystem(const CoreAccountId& account_id) override;
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 773aa6063e7..cb65ddf82c9 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
@@ -14,6 +14,7 @@
#include "base/callback.h"
#include "base/callback_helpers.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"
@@ -99,6 +100,11 @@ void RecordLogoutRequestState(LogoutRequestState logout_state) {
UMA_HISTOGRAM_ENUMERATION("Signin.GaiaCookieManager.Logout", logout_state);
}
+void RecordRemoveLocalAccountOutcome(
+ GaiaCookieManagerService::RemoveLocalAccountOutcome outcome) {
+ base::UmaHistogramEnumeration("Signin.RemoveLocalAccountOutcome", outcome);
+}
+
} // namespace
GaiaCookieManagerService::GaiaCookieRequest::SetAccountsParams::
@@ -663,6 +669,36 @@ void GaiaCookieManagerService::LogOutAllAccounts(
}
}
+void GaiaCookieManagerService::RemoveLoggedOutAccountByGaiaId(
+ const std::string& gaia_id) {
+ VLOG(1) << "GaiaCookieManagerService::RemoveLoggedOutAccountByGaiaId";
+
+ if (list_accounts_stale_) {
+ RecordRemoveLocalAccountOutcome(RemoveLocalAccountOutcome::kAccountsStale);
+ return;
+ }
+
+ const bool accounts_updated =
+ base::EraseIf(signed_out_accounts_,
+ [&gaia_id](const gaia::ListedAccount& account) {
+ return account.gaia_id == gaia_id;
+ }) != 0;
+
+ if (!accounts_updated) {
+ RecordRemoveLocalAccountOutcome(
+ RemoveLocalAccountOutcome::kSignedOutAccountMissing);
+ return;
+ }
+
+ RecordRemoveLocalAccountOutcome(RemoveLocalAccountOutcome::kSuccess);
+
+ if (gaia_accounts_updated_in_cookie_callback_) {
+ gaia_accounts_updated_in_cookie_callback_.Run(
+ listed_accounts_, signed_out_accounts_,
+ GoogleServiceAuthError(GoogleServiceAuthError::NONE));
+ }
+}
+
void GaiaCookieManagerService::CancelAll() {
VLOG(1) << "GaiaCookieManagerService::CancelAll";
gaia_auth_fetcher_.reset();
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 b1c7391940a..201bc6c0674 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
@@ -8,7 +8,6 @@
#include <map>
#include <memory>
#include <string>
-#include <unordered_map>
#include <utility>
#include <vector>
@@ -69,6 +68,19 @@ class GaiaCookieManagerService
SET_ACCOUNTS
};
+ // The result of processing a request to remove an account (i.e.
+ // Google-Accounts-RemoveLocalAccount). Used as entry for histogram
+ // |Signin.RemoveLocalAccountOutcome|, hence entries should not be renumbered
+ // and numeric values should never be reused. Exposed publicly for testing
+ // purposes.
+ enum class RemoveLocalAccountOutcome {
+ kSuccess = 0,
+ kAccountsStale = 1,
+ // Missing means the account is not listed in |signed_out_accounts_|.
+ kSignedOutAccountMissing = 2,
+ kMaxValue = kSignedOutAccountMissing
+ };
+
typedef base::OnceCallback<void(signin::SetAccountsInCookieResult)>
SetAccountsInCookieCompletedCallback;
typedef base::OnceCallback<void(const CoreAccountId&,
@@ -271,6 +283,11 @@ class GaiaCookieManagerService
void LogOutAllAccounts(gaia::GaiaSource source,
LogOutFromCookieCompletedCallback callback);
+ // Indicates that an account previously listed via ListAccounts should now
+ // be removed. Does not trigger a ListAccounts request and does not change the
+ // staleness of the account information.
+ void RemoveLoggedOutAccountByGaiaId(const std::string& gaia_id);
+
// Call observers when setting accounts in cookie completes.
void SignalSetAccountsComplete(signin::SetAccountsInCookieResult result);
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 bbe4939cd8c..3326598ac54 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
@@ -98,6 +98,11 @@ MATCHER_P(ListedAccountEquals, expected, "") {
return AreAccountListsEqual(expected, arg);
}
+// Custom matcher for ListedAccount.
+MATCHER_P(ListedAccountMatchesGaiaId, gaia_id, "") {
+ return arg.gaia_id == std::string(gaia_id);
+}
+
class InstrumentedGaiaCookieManagerService : public GaiaCookieManagerService {
public:
InstrumentedGaiaCookieManagerService(ProfileOAuth2TokenService* token_service,
@@ -248,6 +253,7 @@ class GaiaCookieManagerServiceTest : public testing::Test {
} // namespace
using ::testing::_;
+using ::testing::ElementsAre;
TEST_F(GaiaCookieManagerServiceTest, Success) {
InstrumentedGaiaCookieManagerService helper(token_service(), signin_client());
@@ -1097,3 +1103,147 @@ TEST_F(GaiaCookieManagerServiceTest, UbertokenSuccessFetchesExternalCCOnce) {
EXPECT_CALL(helper, StartFetchingMergeSession());
SimulateUbertokenSuccess(&helper, "token3");
}
+
+TEST_F(GaiaCookieManagerServiceTest, RemoveLoggedOutAccountByGaiaId) {
+ const std::string kTestGaiaId1 = "8";
+ const std::string kTestGaiaId2 = "9";
+
+ ::testing::NiceMock<InstrumentedGaiaCookieManagerService> helper(
+ token_service(), signin_client());
+ ::testing::NiceMock<MockObserver> observer(&helper);
+
+ std::vector<gaia::ListedAccount> signed_in_accounts;
+ std::vector<gaia::ListedAccount> signed_out_accounts;
+ ASSERT_FALSE(helper.ListAccounts(&signed_in_accounts, &signed_out_accounts));
+
+ // Simulate two signed out accounts being listed.
+ SimulateListAccountsSuccess(
+ &helper,
+ base::StringPrintf(
+ "[\"f\","
+ "[[\"a\", 0, \"n\", \"a@d.com\", \"p\", 0, 0, 0, 0, 1, \"%s\","
+ "null,null,null,1],"
+ "[\"b\", 0, \"n\", \"b@d.com\", \"p\", 0, 0, 0, 0, 1, \"%s\","
+ "null,null,null,1]]]",
+ kTestGaiaId1.c_str(), kTestGaiaId2.c_str()));
+
+ ASSERT_TRUE(helper.ListAccounts(&signed_in_accounts, &signed_out_accounts));
+ ASSERT_THAT(signed_out_accounts,
+ ElementsAre(ListedAccountMatchesGaiaId(kTestGaiaId1),
+ ListedAccountMatchesGaiaId(kTestGaiaId2)));
+
+ // The removal should notify observers, with one account removed.
+ EXPECT_CALL(observer,
+ OnGaiaAccountsInCookieUpdated(
+ _, /*signed_out_accounts=*/
+ ElementsAre(ListedAccountMatchesGaiaId(kTestGaiaId2)), _));
+ EXPECT_CALL(helper, StartFetchingListAccounts()).Times(0);
+ base::HistogramTester histograms;
+ helper.RemoveLoggedOutAccountByGaiaId(kTestGaiaId1);
+
+ // Verify that ListAccounts wasn't triggered.
+ EXPECT_FALSE(helper.is_running());
+ EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(&helper));
+
+ ASSERT_TRUE(helper.ListAccounts(&signed_in_accounts, &signed_out_accounts));
+ EXPECT_THAT(signed_out_accounts,
+ ElementsAre(ListedAccountMatchesGaiaId(kTestGaiaId2)));
+
+ histograms.ExpectUniqueSample(
+ "Signin.RemoveLocalAccountOutcome",
+ GaiaCookieManagerService::RemoveLocalAccountOutcome::kSuccess, 1);
+}
+
+TEST_F(GaiaCookieManagerServiceTest,
+ RemoveLoggedOutAccountByGaiaIdWhileAccountsStale) {
+ const std::string kTestGaiaId1 = "8";
+
+ ::testing::NiceMock<InstrumentedGaiaCookieManagerService> helper(
+ token_service(), signin_client());
+ ::testing::NiceMock<MockObserver> observer(&helper);
+
+ std::vector<gaia::ListedAccount> signed_in_accounts;
+ std::vector<gaia::ListedAccount> signed_out_accounts;
+ ASSERT_FALSE(helper.ListAccounts(&signed_in_accounts, &signed_out_accounts));
+
+ // Simulate one signed out account being listed.
+ SimulateListAccountsSuccess(
+ &helper,
+ base::StringPrintf(
+ "[\"f\","
+ "[[\"a\", 0, \"n\", \"a@d.com\", \"p\", 0, 0, 0, 0, 1, \"%s\","
+ "null,null,null,1]]]",
+ kTestGaiaId1.c_str()));
+
+ // Change list account state to be stale, which will trigger list accounts
+ // request.
+ helper.ForceOnCookieChangeProcessing();
+
+ ASSERT_FALSE(helper.ListAccounts(&signed_in_accounts, &signed_out_accounts));
+ ASSERT_THAT(signed_out_accounts,
+ ElementsAre(ListedAccountMatchesGaiaId(kTestGaiaId1)));
+
+ // The removal should be ignored because the account list is stale.
+ EXPECT_CALL(observer, OnGaiaAccountsInCookieUpdated(_, _, _)).Times(0);
+ EXPECT_CALL(helper, StartFetchingListAccounts()).Times(0);
+ base::HistogramTester histograms;
+ helper.RemoveLoggedOutAccountByGaiaId(kTestGaiaId1);
+
+ // Verify that ListAccounts wasn't triggered again.
+ EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(&helper));
+
+ ASSERT_FALSE(helper.ListAccounts(&signed_in_accounts, &signed_out_accounts));
+ EXPECT_THAT(signed_out_accounts,
+ ElementsAre(ListedAccountMatchesGaiaId(kTestGaiaId1)));
+
+ histograms.ExpectUniqueSample(
+ "Signin.RemoveLocalAccountOutcome",
+ GaiaCookieManagerService::RemoveLocalAccountOutcome::kAccountsStale, 1);
+}
+
+TEST_F(GaiaCookieManagerServiceTest,
+ RemoveLoggedOutAccountByGaiaIdForMissingAccount) {
+ const std::string kTestGaiaId1 = "8";
+ const std::string kNonListedAccount = "9";
+
+ ::testing::NiceMock<InstrumentedGaiaCookieManagerService> helper(
+ token_service(), signin_client());
+ ::testing::NiceMock<MockObserver> observer(&helper);
+
+ std::vector<gaia::ListedAccount> signed_in_accounts;
+ std::vector<gaia::ListedAccount> signed_out_accounts;
+ ASSERT_FALSE(helper.ListAccounts(&signed_in_accounts, &signed_out_accounts));
+
+ // Simulate one signed out account being listed.
+ SimulateListAccountsSuccess(
+ &helper,
+ base::StringPrintf(
+ "[\"f\","
+ "[[\"a\", 0, \"n\", \"a@d.com\", \"p\", 0, 0, 0, 0, 1, \"%s\","
+ "null,null,null,1]]]",
+ kTestGaiaId1.c_str()));
+
+ ASSERT_TRUE(helper.ListAccounts(&signed_in_accounts, &signed_out_accounts));
+ ASSERT_THAT(signed_out_accounts,
+ ElementsAre(ListedAccountMatchesGaiaId(kTestGaiaId1)));
+
+ // The removal should be ignored because the Gaia ID is not listed/known.
+ EXPECT_CALL(observer, OnGaiaAccountsInCookieUpdated(_, _, _)).Times(0);
+ EXPECT_CALL(helper, StartFetchingListAccounts()).Times(0);
+ base::HistogramTester histograms;
+ helper.RemoveLoggedOutAccountByGaiaId(kNonListedAccount);
+
+ // Verify that ListAccounts wasn't triggered.
+ EXPECT_FALSE(helper.is_running());
+ EXPECT_TRUE(testing::Mock::VerifyAndClearExpectations(&helper));
+
+ ASSERT_TRUE(helper.ListAccounts(&signed_in_accounts, &signed_out_accounts));
+ EXPECT_THAT(signed_out_accounts,
+ ElementsAre(ListedAccountMatchesGaiaId(kTestGaiaId1)));
+
+ histograms.ExpectUniqueSample(
+ "Signin.RemoveLocalAccountOutcome",
+ GaiaCookieManagerService::RemoveLocalAccountOutcome::
+ kSignedOutAccountMissing,
+ 1);
+}
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 26d866036d9..82a6d6698bb 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
@@ -50,30 +50,6 @@ enum class LoadTokenFromDBStatus {
NUM_LOAD_TOKEN_FROM_DB_STATUS
};
-// Used to record events related to token revocation requests in histograms.
-// Do not change existing values, new values can only be added at the end.
-enum class TokenRevocationRequestProgress {
- // The request was created.
- kRequestCreated = 0,
- // The request was sent over the network.
- kRequestStarted = 1,
- // The network request completed with a failure.
- kRequestFailed = 2,
- // The network request completed with a success.
- kRequestSucceeded = 3,
-
- kMaxValue = kRequestSucceeded
-};
-
-// Adds a sample to the TokenRevocationRequestProgress histogram. Encapsuled in
-// a function to reduce executable size, because histogram macros may generate a
-// lot of code.
-void RecordRefreshTokenRevocationRequestEvent(
- TokenRevocationRequestProgress event) {
- UMA_HISTOGRAM_ENUMERATION("Signin.RefreshTokenRevocationRequestProgress",
- event);
-}
-
std::string ApplyAccountIdPrefix(const std::string& account_id) {
return kAccountIdPrefix + account_id;
}
@@ -166,8 +142,6 @@ MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken::
token_service_delegate_->GetURLLoaderFactory()),
refresh_token_(refresh_token),
attempt_(attempt) {
- RecordRefreshTokenRevocationRequestEvent(
- TokenRevocationRequestProgress::kRequestCreated);
client->DelayNetworkCall(
base::BindRepeating(&MutableProfileOAuth2TokenServiceDelegate::
RevokeServerRefreshToken::Start,
@@ -176,8 +150,6 @@ MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken::
void MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken::
Start() {
- RecordRefreshTokenRevocationRequestEvent(
- TokenRevocationRequestProgress::kRequestStarted);
fetcher_.StartRevokeOAuth2Token(refresh_token_);
}
@@ -207,18 +179,11 @@ bool MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken::
void MutableProfileOAuth2TokenServiceDelegate::RevokeServerRefreshToken::
OnOAuth2RevokeTokenCompleted(
GaiaAuthConsumer::TokenRevocationStatus status) {
- UMA_HISTOGRAM_ENUMERATION("Signin.RefreshTokenRevocationStatus", status);
if (ShouldRetry(status)) {
token_service_delegate_->server_revokes_.push_back(
std::make_unique<RevokeServerRefreshToken>(
token_service_delegate_, token_service_delegate_->client_,
refresh_token_, attempt_ + 1));
- } else {
- RecordRefreshTokenRevocationRequestEvent(
- (status == GaiaAuthConsumer::TokenRevocationStatus::kSuccess)
- ? TokenRevocationRequestProgress::kRequestSucceeded
- : TokenRevocationRequestProgress::kRequestFailed);
- UMA_HISTOGRAM_ENUMERATION("Signin.RefreshTokenRevocationCompleted", status);
}
// |this| pointer will be deleted when removed from the vector, so don't
// access any members after call to erase().
diff --git a/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.h b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.h
index d60787cc73e..f64019b108f 100644
--- a/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.h
+++ b/chromium/components/signin/internal/identity_manager/oauth_multilogin_helper.h
@@ -19,7 +19,6 @@
#include "google_apis/gaia/gaia_auth_consumer.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "net/cookies/cookie_access_result.h"
-#include "services/network/public/mojom/cookie_manager.mojom.h"
class GaiaAuthFetcher;
class GoogleServiceAuthError;
diff --git a/chromium/components/signin/internal/identity_manager/primary_account_manager.cc b/chromium/components/signin/internal/identity_manager/primary_account_manager.cc
index 332632058a7..14095b440a4 100644
--- a/chromium/components/signin/internal/identity_manager/primary_account_manager.cc
+++ b/chromium/components/signin/internal/identity_manager/primary_account_manager.cc
@@ -56,6 +56,7 @@ void PrimaryAccountManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterBooleanPref(prefs::kAutologinEnabled, true);
registry->RegisterListPref(prefs::kReverseAutologinRejectedEmailList);
registry->RegisterBooleanPref(prefs::kSigninAllowed, true);
+ registry->RegisterBooleanPref(prefs::kSigninAllowedByPolicy, true);
registry->RegisterBooleanPref(prefs::kSignedInWithCredentialProvider, false);
}
@@ -353,7 +354,7 @@ void PrimaryAccountManager::OnSignoutDecisionReached(
break;
case RemoveAccountsOption::kKeepAllAccounts:
if (previous_state.consent_level == signin::ConsentLevel::kSignin) {
- // Nothing to update as the primary account is already at kNotRequired
+ // Nothing to update as the primary account is already at kSignin
// consent level. Prefer returning to avoid firing useless
// OnPrimaryAccountChanged() notifications.
return;
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 700d8217dca..a87da779070 100644
--- a/chromium/components/signin/internal/identity_manager/primary_account_manager.h
+++ b/chromium/components/signin/internal/identity_manager/primary_account_manager.h
@@ -19,18 +19,17 @@
#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MANAGER_H_
#include <memory>
-#include <string>
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
-#include "base/optional.h"
#include "build/chromeos_buildflags.h"
#include "components/signin/internal/identity_manager/profile_oauth2_token_service_observer.h"
#include "components/signin/public/base/signin_client.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/primary_account_change_event.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class AccountTrackerService;
class PrefRegistrySimple;
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 83900c87bc1..b61786ed770 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
@@ -46,40 +46,41 @@ PrimaryAccountMutatorImpl::PrimaryAccountMutatorImpl(
PrimaryAccountMutatorImpl::~PrimaryAccountMutatorImpl() {}
bool PrimaryAccountMutatorImpl::SetPrimaryAccount(
- const CoreAccountId& account_id) {
+ const CoreAccountId& account_id,
+ ConsentLevel consent_level) {
+ DCHECK(!account_id.empty());
AccountInfo account_info = account_tracker_->GetAccountInfo(account_id);
-
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
- if (!pref_service_->GetBoolean(prefs::kSigninAllowed))
+ if (account_info.IsEmpty())
return false;
- if (primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSync))
- return false;
+ DCHECK_EQ(account_info.account_id, account_id);
+ DCHECK(!account_info.email.empty());
+ DCHECK(!account_info.gaia.empty());
- if (account_info.account_id != account_id || account_info.email.empty())
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+ if (!pref_service_->GetBoolean(prefs::kSigninAllowed))
return false;
-
- // TODO(crbug.com/889899): should check that the account email is allowed.
#endif
- primary_account_manager_->SetSyncPrimaryAccountInfo(account_info);
- return true;
-}
-
-void PrimaryAccountMutatorImpl::SetUnconsentedPrimaryAccount(
- const CoreAccountId& account_id) {
+ switch (consent_level) {
+ case ConsentLevel::kSync:
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
+ if (primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSync))
+ return false;
+#endif
+ primary_account_manager_->SetSyncPrimaryAccountInfo(account_info);
+ return true;
+ case ConsentLevel::kSignin:
#if BUILDFLAG(IS_CHROMEOS_ASH)
- // On Chrome OS the UPA can only be set once and never removed or changed.
- DCHECK(!account_id.empty());
- DCHECK(!primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSignin));
+ // On Chrome OS the UPA can only be set once and never removed or changed.
+ DCHECK(
+ !primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSignin));
#endif
- AccountInfo account_info;
- if (!account_id.empty()) {
- account_info = account_tracker_->GetAccountInfo(account_id);
- DCHECK(!account_info.IsEmpty());
+ DCHECK(!primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSync));
+ primary_account_manager_->SetUnconsentedPrimaryAccountInfo(account_info);
+ return true;
}
-
- primary_account_manager_->SetUnconsentedPrimaryAccountInfo(account_info);
+ return false;
}
#if !BUILDFLAG(IS_CHROMEOS_ASH)
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 99b74257624..0fe82594a61 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
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MUTATOR_IMPL_H_
#define COMPONENTS_SIGNIN_INTERNAL_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MUTATOR_IMPL_H_
-#include <string>
-
#include "build/chromeos_buildflags.h"
#include "components/signin/public/base/account_consistency_method.h"
#include "components/signin/public/identity_manager/primary_account_mutator.h"
@@ -31,8 +29,8 @@ class PrimaryAccountMutatorImpl : public PrimaryAccountMutator {
~PrimaryAccountMutatorImpl() override;
// PrimaryAccountMutator implementation.
- bool SetPrimaryAccount(const CoreAccountId& account_id) override;
- void SetUnconsentedPrimaryAccount(const CoreAccountId& account_id) override;
+ bool SetPrimaryAccount(const CoreAccountId& account_id,
+ ConsentLevel consent_level) override;
void RevokeSyncConsent(signin_metrics::ProfileSignout source_metric,
signin_metrics::SignoutDelete delete_metric) override;
#if !BUILDFLAG(IS_CHROMEOS_ASH)
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 2757404a0d7..5e9d4c37529 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
@@ -31,6 +31,10 @@
#include "components/user_manager/user_manager.h"
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_chromeos.h"
+#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
+
#if defined(OS_IOS)
#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h"
#include "components/signin/public/identity_manager/ios/device_accounts_provider.h"
@@ -74,6 +78,19 @@ std::unique_ptr<ProfileOAuth2TokenServiceDelegate> CreateCrOsOAuthDelegate(
is_regular_profile);
}
#elif BUILDFLAG(ENABLE_DICE_SUPPORT)
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+std::unique_ptr<ProfileOAuth2TokenServiceDelegate> CreateCrOsOAuthDelegate(
+ AccountTrackerService* account_tracker_service,
+ network::NetworkConnectionTracker* network_connection_tracker,
+ account_manager::AccountManagerFacade* account_manager_facade,
+ bool is_regular_profile) {
+ return std::make_unique<signin::ProfileOAuth2TokenServiceDelegateChromeOS>(
+ account_tracker_service, network_connection_tracker,
+ account_manager_facade, is_regular_profile);
+}
+#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
+
std::unique_ptr<MutableProfileOAuth2TokenServiceDelegate>
CreateMutableProfileOAuthDelegate(
AccountTrackerService* account_tracker_service,
@@ -111,9 +128,11 @@ CreateOAuth2TokenServiceDelegate(
SigninClient* signin_client,
#if BUILDFLAG(IS_CHROMEOS_ASH)
ash::AccountManager* account_manager,
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
account_manager::AccountManagerFacade* account_manager_facade,
bool is_regular_profile,
-#endif
+#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
#if !defined(OS_ANDROID)
bool delete_signin_cookies_on_exit,
scoped_refptr<TokenWebData> token_web_data,
@@ -136,9 +155,24 @@ CreateOAuth2TokenServiceDelegate(
return CreateCrOsOAuthDelegate(account_tracker_service,
network_connection_tracker, account_manager,
account_manager_facade, is_regular_profile);
+#elif BUILDFLAG(IS_CHROMEOS_LACROS)
+ // For the time being, Mirror is enabled only in the first / "Main" Profile in
+ // Lacros.
+ if (account_consistency == signin::AccountConsistencyMethod::kMirror) {
+ return CreateCrOsOAuthDelegate(account_tracker_service,
+ network_connection_tracker,
+ account_manager_facade, is_regular_profile);
+ } else {
+ // TODO(crbug.com/1198490): Remove this when we don't need DICE and
+ // `MutableProfileOAuth2TokenServiceDelegate` on Lacros anymore.
+ return CreateMutableProfileOAuthDelegate(
+ account_tracker_service, account_consistency,
+ delete_signin_cookies_on_exit, token_web_data, signin_client,
+ network_connection_tracker);
+ }
#elif BUILDFLAG(ENABLE_DICE_SUPPORT)
// Fall back to |MutableProfileOAuth2TokenServiceDelegate| on all platforms
- // other than Android, iOS, and Chrome OS.
+ // other than Android, iOS, and Chrome OS (Ash and Lacros).
return CreateMutableProfileOAuthDelegate(
account_tracker_service, account_consistency,
delete_signin_cookies_on_exit, token_web_data, signin_client,
@@ -161,9 +195,11 @@ std::unique_ptr<ProfileOAuth2TokenService> BuildProfileOAuth2TokenService(
signin::AccountConsistencyMethod account_consistency,
#if BUILDFLAG(IS_CHROMEOS_ASH)
ash::AccountManager* account_manager,
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
account_manager::AccountManagerFacade* account_manager_facade,
bool is_regular_profile,
-#endif
+#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
#if !defined(OS_ANDROID)
bool delete_signin_cookies_on_exit,
scoped_refptr<TokenWebData> token_web_data,
@@ -190,8 +226,11 @@ std::unique_ptr<ProfileOAuth2TokenService> BuildProfileOAuth2TokenService(
CreateOAuth2TokenServiceDelegate(
account_tracker_service, account_consistency, signin_client,
#if BUILDFLAG(IS_CHROMEOS_ASH)
- account_manager, account_manager_facade, is_regular_profile,
-#endif
+ account_manager,
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+ account_manager_facade, is_regular_profile,
+#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
#if !defined(OS_ANDROID)
delete_signin_cookies_on_exit, token_web_data,
#endif
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h
index 1e7659c9f54..baaaa27fa04 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_builder.h
@@ -43,11 +43,13 @@ class TokenWebData;
namespace ash {
class AccountManager;
}
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
namespace account_manager {
class AccountManagerFacade;
}
-#endif
+#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
std::unique_ptr<ProfileOAuth2TokenService> BuildProfileOAuth2TokenService(
PrefService* pref_service,
@@ -56,9 +58,11 @@ std::unique_ptr<ProfileOAuth2TokenService> BuildProfileOAuth2TokenService(
signin::AccountConsistencyMethod account_consistency,
#if BUILDFLAG(IS_CHROMEOS_ASH)
ash::AccountManager* account_manager,
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
account_manager::AccountManagerFacade* account_manager_facade,
bool is_regular_profile,
-#endif
+#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
#if !defined(OS_ANDROID)
bool delete_signin_cookies_on_exit,
scoped_refptr<TokenWebData> token_web_data,
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 999e6461529..9e3156a4167 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
@@ -19,6 +19,7 @@
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_manager.h"
#include "net/base/backoff_entry.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
@@ -129,7 +130,7 @@ class ProfileOAuth2TokenServiceDelegate {
#if defined(OS_IOS) || defined(OS_ANDROID)
// Triggers platform specific implementation to reload accounts from system.
virtual void ReloadAllAccountsFromSystemWithPrimaryAccount(
- const base::Optional<CoreAccountId>& primary_account_id) {}
+ const absl::optional<CoreAccountId>& primary_account_id) {}
#endif
#if defined(OS_IOS)
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc
index c7872b8b7ae..0de4283023b 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc
@@ -310,7 +310,7 @@ void ProfileOAuth2TokenServiceDelegateAndroid::OnAccessTokenInvalidated(
void ProfileOAuth2TokenServiceDelegateAndroid::
ReloadAllAccountsFromSystemWithPrimaryAccount(
- const base::Optional<CoreAccountId>& primary_account_id) {
+ const absl::optional<CoreAccountId>& primary_account_id) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> j_account_id =
@@ -326,7 +326,7 @@ void ProfileOAuth2TokenServiceDelegateAndroid::
ReloadAllAccountsWithPrimaryAccountAfterSeeding(
JNIEnv* env,
const base::android::JavaParamRef<jstring>& account_id) {
- base::Optional<CoreAccountId> core_account_id;
+ absl::optional<CoreAccountId> core_account_id;
if (account_id) {
core_account_id =
CoreAccountId::FromString(ConvertJavaStringToUTF8(env, account_id));
@@ -335,7 +335,7 @@ void ProfileOAuth2TokenServiceDelegateAndroid::
}
void ProfileOAuth2TokenServiceDelegateAndroid::UpdateAccountList(
- const base::Optional<CoreAccountId>& signed_in_account_id,
+ const absl::optional<CoreAccountId>& signed_in_account_id,
const std::vector<CoreAccountId>& prev_ids,
const std::vector<CoreAccountId>& curr_ids) {
DVLOG(1) << "ProfileOAuth2TokenServiceDelegateAndroid::UpdateAccountList:"
@@ -388,7 +388,7 @@ void ProfileOAuth2TokenServiceDelegateAndroid::UpdateAccountList(
}
bool ProfileOAuth2TokenServiceDelegateAndroid::UpdateAccountList(
- const base::Optional<CoreAccountId>& signed_in_id,
+ const absl::optional<CoreAccountId>& signed_in_id,
const std::vector<CoreAccountId>& prev_ids,
const std::vector<CoreAccountId>& curr_ids,
std::vector<CoreAccountId>* refreshed_ids,
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.h
index 95196ec1410..46ed5cdd374 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.h
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.h
@@ -51,7 +51,7 @@ class ProfileOAuth2TokenServiceDelegateAndroid
void LoadCredentials(const CoreAccountId& primary_account_id) override;
void ReloadAllAccountsFromSystemWithPrimaryAccount(
- const base::Optional<CoreAccountId>& primary_account_id) override;
+ const absl::optional<CoreAccountId>& primary_account_id) override;
// Resumes the reload of accounts once the account seeding is complete.
// TODO(crbug.com/934688) Once ProfileOAuth2TokenServiceDelegate.java is
@@ -65,7 +65,7 @@ class ProfileOAuth2TokenServiceDelegateAndroid
// NOTE: TokenAvailable notifications will be sent for all accounts, even if
// they were already known. See https://crbug.com/939470 for details.
void UpdateAccountList(
- const base::Optional<CoreAccountId>& signed_in_account_id,
+ const absl::optional<CoreAccountId>& signed_in_account_id,
const std::vector<CoreAccountId>& prev_ids,
const std::vector<CoreAccountId>& curr_ids);
@@ -100,7 +100,7 @@ class ProfileOAuth2TokenServiceDelegateAndroid
// Return whether accounts are valid and we have access to all the tokens in
// |curr_ids|.
- bool UpdateAccountList(const base::Optional<CoreAccountId>& signed_in_id,
+ bool UpdateAccountList(const absl::optional<CoreAccountId>& signed_in_id,
const std::vector<CoreAccountId>& prev_ids,
const std::vector<CoreAccountId>& curr_ids,
std::vector<CoreAccountId>* refreshed_ids,
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 7c773db3497..eff34b2c6e5 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
@@ -11,6 +11,8 @@
#include "base/bind.h"
#include "base/containers/contains.h"
#include "base/logging.h"
+#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
#include "components/signin/internal/identity_manager/account_tracker_service.h"
#include "google_apis/gaia/oauth2_access_token_fetcher_immediate_error.h"
#include "net/base/backoff_entry.h"
@@ -98,6 +100,7 @@ class PersistentErrorsHelper : public base::RefCounted<PersistentErrorsHelper> {
// No accounts to get error status for, run callback immediately.
std::move(callback).Run(
std::map<account_manager::AccountKey, GoogleServiceAuthError>());
+ return;
}
// The ownership of this object is shared between callbacks passed to
@@ -318,9 +321,21 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::LoadCredentials(
void ProfileOAuth2TokenServiceDelegateChromeOS::UpdateCredentials(
const CoreAccountId& account_id,
const std::string& refresh_token) {
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+ NOTREACHED()
+ << "If you're seeing this error in a browser_test, consider "
+ "disabling the test while we set up the testing "
+ "infrastructure to talk to Ash in a browser_test. Also, please add a "
+ "comment / CL ref. to crbug.com/1197201 if you disable your test.";
+ // TODO(sinhak): We need a way to write accounts to Account Manager in
+ // browser_tests and lacros_chrome_browsertests. For browser_tests, the
+ // solution may be to build Account Manager in Lacros. For
+ // lacros_chrome_browsertests, we will need to talk to EngProd.
+#else
// UpdateCredentials should not be called on Chrome OS. Credentials should be
// updated through Chrome OS Account Manager.
NOTREACHED();
+#endif
}
scoped_refptr<network::SharedURLLoaderFactory>
@@ -502,12 +517,12 @@ void ProfileOAuth2TokenServiceDelegateChromeOS::OnAccountRemoved(
void ProfileOAuth2TokenServiceDelegateChromeOS::RevokeCredentials(
const CoreAccountId& account_id) {
- // Signing out of Chrome is not possible on Chrome OS.
+ // Signing out of Chrome is not possible on Chrome OS Ash / Lacros.
NOTREACHED();
}
void ProfileOAuth2TokenServiceDelegateChromeOS::RevokeAllCredentials() {
- // Signing out of Chrome is not possible on Chrome OS.
+ // Signing out of Chrome is not possible on Chrome OS Ash / Lacros.
NOTREACHED();
}
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h
index 3cac71d9c1f..ef414ca0ee3 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.h
@@ -54,7 +54,7 @@ class ProfileOAuth2TokenServiceIOSDelegate
void RevokeAllCredentials() override;
void ReloadAllAccountsFromSystemWithPrimaryAccount(
- const base::Optional<CoreAccountId>& primary_account_id) override;
+ const absl::optional<CoreAccountId>& primary_account_id) override;
void ReloadAccountFromSystem(const CoreAccountId& account_id) override;
// Adds |account_id| to |accounts_| if it does not exist or udpates
diff --git a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm
index 62c473e0b2c..cde6ddfd83a 100644
--- a/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm
+++ b/chromium/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_ios.mm
@@ -294,7 +294,7 @@ void ProfileOAuth2TokenServiceIOSDelegate::RevokeAllCredentials() {
void ProfileOAuth2TokenServiceIOSDelegate::
ReloadAllAccountsFromSystemWithPrimaryAccount(
- const base::Optional<CoreAccountId>& primary_account_id) {
+ const absl::optional<CoreAccountId>& primary_account_id) {
ReloadCredentials(primary_account_id.value_or(CoreAccountId()));
}
diff --git a/chromium/components/signin/ios/DIR_METADATA b/chromium/components/signin/ios/DIR_METADATA
deleted file mode 100644
index 5fad6891646..00000000000
--- a/chromium/components/signin/ios/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Services>SignIn"
-}
diff --git a/chromium/components/signin/ios/browser/account_consistency_service.h b/chromium/components/signin/ios/browser/account_consistency_service.h
index ca895d52b10..7220a445097 100644
--- a/chromium/components/signin/ios/browser/account_consistency_service.h
+++ b/chromium/components/signin/ios/browser/account_consistency_service.h
@@ -7,7 +7,6 @@
#include <map>
#include <set>
-#include <string>
#include "base/callback.h"
#include "base/macros.h"
@@ -52,14 +51,6 @@ class AccountConsistencyService : public KeyedService,
// Removes the handler associated with |web_state|.
void RemoveWebStateHandler(web::WebState* web_state);
- // Checks for the presence of Gaia cookies and if they have been deleted
- // notifies the AccountReconcilor (the class responsible for rebuilding Gaia
- // cookies if needed). Calls callback if Gaia cookies were restored.
- //
- // Applies a one hour time restriction in between updates to avoid too many
- // |GetAllCookies| calls on the cookie manager.
- void SetGaiaCookiesIfDeleted(base::OnceClosure cookies_restored_callback);
-
// Notifies the AccountReconcilor that Gaia cookies have been deleted. Calls
// callback once the Gaia cookies have been restored and returns YES on
// success. Note that in order to avoid redirect loops this method applies a
@@ -100,16 +91,6 @@ class AccountConsistencyService : public KeyedService,
void OnDeleteCookiesFinished(base::OnceClosure callback,
uint32_t num_cookies_deleted);
- // Triggers a Gaia cookie update on the Google domain. Calls
- // |cookies_restored_callback| if the Gaia cookies were restored.
- void TriggerGaiaCookieChangeIfDeleted(
- base::OnceClosure cookies_restored_callback,
- const net::CookieAccessResultList& cookie_list,
- const net::CookieAccessResultList& excluded_cookies);
-
- // Clears all pending cookie requests and cached domains.
- void ResetInternalState();
-
// IdentityManager::Observer implementation.
void OnPrimaryAccountChanged(
const signin::PrimaryAccountChangeEvent& event) override;
@@ -134,7 +115,6 @@ class AccountConsistencyService : public KeyedService,
int64_t active_cookie_manager_requests_for_testing_;
// Last time Gaia cookie was updated for the Google domain.
- base::Time last_gaia_cookie_verification_time_;
base::Time last_gaia_cookie_update_time_;
// List of callbacks to be called following GAIA cookie restoration.
diff --git a/chromium/components/signin/ios/browser/account_consistency_service.mm b/chromium/components/signin/ios/browser/account_consistency_service.mm
index 5ff4951ab1d..0e46b18de4c 100644
--- a/chromium/components/signin/ios/browser/account_consistency_service.mm
+++ b/chromium/components/signin/ios/browser/account_consistency_service.mm
@@ -136,14 +136,10 @@ class AccountConsistencyService::AccountConsistencyHandler
base::OnceCallback<void(PolicyDecision)> callback) override;
void WebStateDestroyed() override;
- // Marks that GAIA cookies have been restored.
- void MarkGaiaCookiesRestored();
-
// Loads |url| in the current tab.
void NavigateToURL(GURL url);
bool show_consistency_promo_ = false;
- bool gaia_cookies_restored_ = false;
AccountConsistencyService* account_consistency_service_; // Weak.
AccountReconcilor* account_reconcilor_; // Weak.
signin::IdentityManager* identity_manager_;
@@ -199,38 +195,36 @@ void AccountConsistencyService::AccountConsistencyHandler::ShouldAllowResponse(
GURL url = net::GURLWithNSURL(http_response.URL);
// User is showing intent to navigate to a Google-owned domain. Set GAIA and
- // CHROME_CONNECTED cookies if the user is signed in or if they are not signed
- // in and navigating to a GAIA sign-on (this is filtered in
+ // CHROME_CONNECTED cookies if the user is signed in (this is filtered in
// ChromeConnectedHelper).
if (signin::IsUrlEligibleForMirrorCookie(url)) {
account_consistency_service_->SetChromeConnectedCookieWithUrls(
{url, GURL(kGoogleUrl)});
}
- // Chrome monitors GAIA cookies when navigating to Google associated domains
- // to ensure that signed-in users remain signed-in to their Google services on
- // the web. This includes redirects to accounts.google.com.
- if (google_util::IsGoogleAssociatedDomainUrl(url)) {
- // TODO(crbug.com/1131027): Disable GAIA cookie restore on Google URLs that
- // may display cookie consent in the content area that conflict with the
- // sign-in notification. This will be removed once we perform cookie
- // restoration before sending a navigation request.
- if (!(google_util::IsGoogleHomePageUrl(url) ||
- google_util::IsGoogleSearchUrl(url))) {
- // Reset boolean that tracks displaying the sign-in notification infobar.
- // This ensures that only the most recent navigation will trigger an
- // infobar.
- gaia_cookies_restored_ = false;
- account_consistency_service_->SetGaiaCookiesIfDeleted(
- base::BindOnce(&AccountConsistencyHandler::MarkGaiaCookiesRestored,
- weak_ptr_factory_.GetWeakPtr()));
- }
- }
+ // Reset boolean that tracks displaying the sign-in consistency promo. This
+ // ensures that the promo is cancelled once navigation has started and the
+ // WKWebView is cancelling previous navigations.
+ show_consistency_promo_ = false;
if (!gaia::IsGaiaSignonRealm(url.GetOrigin())) {
std::move(callback).Run(PolicyDecision::Allow());
return;
}
+
+ // If the user has been prompted to enter their credentials on a Gaia sign-on
+ // page show the account consistency promo.
+ NSString* x_autologin_header = [[http_response allHeaderFields]
+ objectForKey:[NSString stringWithUTF8String:signin::kAutoLoginHeader]];
+ if (signin::IsMICEWebSignInEnabled() && x_autologin_header) {
+ show_consistency_promo_ = true;
+ // Allows the URL response to load before showing the consistency promo.
+ // The promo should always be displayed in the foreground of Gaia
+ // sign-on.
+ std::move(callback).Run(PolicyDecision::Allow());
+ return;
+ }
+
NSString* manage_accounts_header = [[http_response allHeaderFields]
objectForKey:
[NSString stringWithUTF8String:signin::kChromeManageAccountsHeader]];
@@ -243,10 +237,6 @@ void AccountConsistencyService::AccountConsistencyHandler::ShouldAllowResponse(
base::SysNSStringToUTF8(manage_accounts_header));
account_reconcilor_->OnReceivedManageAccountsResponse(params.service_type);
- // Reset boolean that tracks displaying the sign-in consistency promo. This
- // ensures that the promo is cancelled once navigation has started and the
- // WKWebView is cancelling previous navigations.
- show_consistency_promo_ = false;
switch (params.service_type) {
case signin::GAIA_SERVICE_TYPE_INCOGNITO: {
@@ -278,16 +268,7 @@ void AccountConsistencyService::AccountConsistencyHandler::ShouldAllowResponse(
}
}
}
- if (params.show_consistency_promo) {
- show_consistency_promo_ = true;
- // Allows the URL response to load before showing the consistency promo.
- // The promo should always be displayed in the foreground of Gaia
- // sign-on.
- std::move(callback).Run(PolicyDecision::Allow());
- return;
- } else {
- [delegate_ onAddAccount];
- }
+ [delegate_ onAddAccount];
break;
case signin::GAIA_SERVICE_TYPE_SIGNOUT:
case signin::GAIA_SERVICE_TYPE_DEFAULT:
@@ -308,11 +289,6 @@ void AccountConsistencyService::AccountConsistencyHandler::ShouldAllowResponse(
std::move(callback).Run(PolicyDecision::Cancel());
}
-void AccountConsistencyService::AccountConsistencyHandler::
- MarkGaiaCookiesRestored() {
- gaia_cookies_restored_ = true;
-}
-
void AccountConsistencyService::AccountConsistencyHandler::NavigateToURL(
GURL url) {
web_state_->OpenURL(web::WebState::OpenURLParams(
@@ -334,26 +310,9 @@ void AccountConsistencyService::AccountConsistencyHandler::PageLoaded(
return;
}
- // Displays the sign-in notification infobar if GAIA cookies have been
- // restored. This occurs once the URL has been loaded to avoid a race
- // condition in which the infobar is dismissed prior to the page load.
- if (gaia_cookies_restored_) {
- [delegate_ onRestoreGaiaCookies];
- LogIOSGaiaCookiesState(
- GaiaCookieStateOnSignedInNavigation::kGaiaCookieRestoredOnShowInfobar);
- gaia_cookies_restored_ = false;
- }
-
if (show_consistency_promo_ && gaia::IsGaiaSignonRealm(url.GetOrigin())) {
- [delegate_ onShowConsistencyPromo];
+ [delegate_ onShowConsistencyPromo:url];
show_consistency_promo_ = false;
-
- // Chrome uses the CHROME_CONNECTED cookie to determine whether the
- // eligibility promo should be shown. Once it is shown we should remove the
- // cookie, since it should otherwise not be used unless the user is signed
- // in.
- account_consistency_service_->RemoveAllChromeConnectedCookies(
- base::OnceClosure());
}
}
@@ -423,55 +382,6 @@ void AccountConsistencyService::RemoveWebStateHandler(
web_state->RemoveObserver(handler.get());
}
-void AccountConsistencyService::SetGaiaCookiesIfDeleted(
- base::OnceClosure cookies_restored_callback) {
- // We currently enforce a time threshold to update the Gaia cookie
- // for signed-in users to prevent calling the expensive method
- // |GetAllCookies| in the cookie manager.
- if (base::Time::Now() - last_gaia_cookie_verification_time_ <
- GetDelayThresholdToUpdateGaiaCookie() ||
- !identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSignin)) {
- return;
- }
- network::mojom::CookieManager* cookie_manager =
- browser_state_->GetCookieManager();
- cookie_manager->GetCookieList(
- GaiaUrls::GetInstance()->secure_google_url(),
- net::CookieOptions::MakeAllInclusive(),
- base::BindOnce(
- &AccountConsistencyService::TriggerGaiaCookieChangeIfDeleted,
- base::Unretained(this), std::move(cookies_restored_callback)));
- last_gaia_cookie_verification_time_ = base::Time::Now();
-}
-
-void AccountConsistencyService::TriggerGaiaCookieChangeIfDeleted(
- base::OnceClosure cookies_restored_callback,
- const net::CookieAccessResultList& cookie_list,
- const net::CookieAccessResultList& unused_excluded_cookies) {
- for (const auto& cookie : cookie_list) {
- if (cookie.cookie.Name() == GaiaConstants::kGaiaSigninCookieName) {
- LogIOSGaiaCookiesState(
- GaiaCookieStateOnSignedInNavigation::kGaiaCookiePresentOnNavigation);
- return;
- }
- }
-
- // The SAPISID cookie may have been deleted previous to this update due to
- // ITP restrictions marking Google domains as potential trackers.
- LogIOSGaiaCookiesState(
- GaiaCookieStateOnSignedInNavigation::
- kGaiaCookieAbsentOnGoogleAssociatedDomainNavigation);
-
- if (!base::FeatureList::IsEnabled(signin::kRestoreGaiaCookiesIfDeleted)) {
- return;
- }
-
- // Re-generate cookie to ensure that the user is properly signed in.
- identity_manager_->GetAccountsCookieMutator()->ForceTriggerOnCookieChange();
- gaia_cookies_restored_callbacks_.push_back(
- std::move(cookies_restored_callback));
-}
-
void AccountConsistencyService::RemoveAllChromeConnectedCookies(
base::OnceClosure callback) {
DCHECK(!browser_state_->IsOffTheRecord());
@@ -488,7 +398,6 @@ void AccountConsistencyService::RemoveAllChromeConnectedCookies(
std::move(filter),
base::BindOnce(&AccountConsistencyService::OnDeleteCookiesFinished,
base::Unretained(this), std::move(callback)));
- last_gaia_cookie_verification_time_ = base::Time();
}
void AccountConsistencyService::OnDeleteCookiesFinished(
@@ -518,7 +427,7 @@ void AccountConsistencyService::SetChromeConnectedCookieWithUrl(
const std::string domain = GetDomainFromUrl(url);
std::string cookie_value = signin::BuildMirrorRequestCookieIfPossible(
url,
- identity_manager_->GetPrimaryAccountInfo(signin::ConsentLevel::kSync)
+ identity_manager_->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin)
.gaia,
signin::AccountConsistencyMethod::kMirror, cookie_settings_.get(),
signin::PROFILE_MODE_DEFAULT);
@@ -572,10 +481,6 @@ void AccountConsistencyService::AddChromeConnectedCookies() {
}
void AccountConsistencyService::OnBrowsingDataRemoved() {
- // CHROME_CONNECTED cookies have been removed, update internal state
- // accordingly.
- last_gaia_cookie_verification_time_ = base::Time();
-
// SAPISID cookie has been removed, notify the GCMS.
// TODO(https://crbug.com/930582) : Remove the need to expose this method
// or move it to the network::CookieManager.
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 6c1f3807ffe..f87374e3423 100644
--- a/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
+++ b/chromium/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -195,7 +195,8 @@ class AccountConsistencyServiceTest : public PlatformTest {
// Identity APIs.
void SignIn() {
signin::MakePrimaryAccountAvailable(identity_test_env_->identity_manager(),
- kFakeEmail);
+ kFakeEmail,
+ signin::ConsentLevel::kSync);
WaitUntilAllCookieRequestsAreApplied();
}
@@ -225,9 +226,8 @@ class AccountConsistencyServiceTest : public PlatformTest {
// Verifies the time that the Gaia cookie was last updated for google.com.
void CheckGaiaCookieWithUpdateTime(base::Time time) {
- EXPECT_EQ(
- time,
- account_consistency_service_->last_gaia_cookie_verification_time_);
+ EXPECT_EQ(time,
+ account_consistency_service_->last_gaia_cookie_update_time_);
}
// Navigation APIs.
@@ -280,7 +280,7 @@ class AccountConsistencyServiceTest : public PlatformTest {
network::mojom::CookieDeletionFilterPtr filter =
network::mojom::CookieDeletionFilter::New();
filter->including_domains =
- base::Optional<std::vector<std::string>>({kGoogleDomain});
+ absl::optional<std::vector<std::string>>({kGoogleDomain});
cookie_manager->DeleteCookies(std::move(filter),
base::OnceCallback<void(uint)>());
}
@@ -456,25 +456,25 @@ TEST_F(AccountConsistencyServiceTest, ChromeManageAccountsDefault) {
}
// Tests that the ManageAccountsDelegate is notified when a navigation on Gaia
-// signon realm returns with a X-Chrome-Manage-Accounts header with show
-// consistency promo and ADDSESSION action.
-TEST_F(AccountConsistencyServiceTest,
- ChromeManageAccountsShowConsistencyPromo) {
+// signon realm returns with a X-Auto-Login header.
+TEST_F(AccountConsistencyServiceTest, ChromeShowConsistencyPromo) {
+ base::test::ScopedFeatureList consistency_feature_list;
+ consistency_feature_list.InitAndEnableFeature(
+ signin::kMobileIdentityConsistency);
+ base::test::ScopedFeatureList websignin_feature_list;
+ websignin_feature_list.InitAndEnableFeature(signin::kMICEWebSignIn);
+
id delegate =
[OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
- [[delegate expect] onShowConsistencyPromo];
+ [[[delegate expect] ignoringNonObjectArgs] onShowConsistencyPromo:GURL()];
- NSDictionary* headers = [NSDictionary
- dictionaryWithObject:@"action=ADDSESSION,show_consistency_promo=true"
- forKey:@"X-Chrome-Manage-Accounts"];
+ NSDictionary* headers = [NSDictionary dictionaryWithObject:@"args=unused"
+ forKey:@"X-Auto-Login"];
NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"]
statusCode:200
HTTPVersion:@"HTTP/1.1"
headerFields:headers];
- EXPECT_CALL(*account_reconcilor_, OnReceivedManageAccountsResponse(
- signin::GAIA_SERVICE_TYPE_ADDSESSION))
- .Times(1);
SimulateNavigateToURL(response, delegate);
@@ -483,22 +483,20 @@ TEST_F(AccountConsistencyServiceTest,
// Tests that the consistency promo is not displayed when a page fails to load.
TEST_F(AccountConsistencyServiceTest,
- ChromeManageAccountsNotShowConsistencyPromoOnPageLoadFailure) {
+ ChromeNotShowConsistencyPromoOnPageLoadFailure) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(signin::kMobileIdentityConsistency);
id delegate =
[OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
- [[delegate reject] onShowConsistencyPromo];
+ [[[delegate reject] ignoringNonObjectArgs] onShowConsistencyPromo:GURL()];
- NSDictionary* headers = [NSDictionary
- dictionaryWithObject:@"action=ADDSESSION,show_consistency_promo=true"
- forKey:@"X-Chrome-Manage-Accounts"];
+ NSDictionary* headers = [NSDictionary dictionaryWithObject:@"args=unused"
+ forKey:@"X-Auto-Login"];
NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"]
statusCode:200
HTTPVersion:@"HTTP/1.1"
headerFields:headers];
- EXPECT_CALL(*account_reconcilor_, OnReceivedManageAccountsResponse(
- signin::GAIA_SERVICE_TYPE_ADDSESSION))
- .Times(1);
SimulateNavigateToURLWithPageLoadFailure(response, delegate);
@@ -508,19 +506,20 @@ TEST_F(AccountConsistencyServiceTest,
// Tests that the consistency promo is not displayed when a page fails to load
// and user chooses another action.
TEST_F(AccountConsistencyServiceTest,
- ChromeManageAccountsNotShowConsistencyPromoOnPageLoadFailureRedirect) {
+ ChromeNotShowConsistencyPromoOnPageLoadFailureRedirect) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(signin::kMobileIdentityConsistency);
+
id delegate =
[OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
[[delegate expect] onAddAccount];
- [[delegate reject] onShowConsistencyPromo];
+ [[[delegate reject] ignoringNonObjectArgs] onShowConsistencyPromo:GURL()];
EXPECT_CALL(*account_reconcilor_, OnReceivedManageAccountsResponse(
- signin::GAIA_SERVICE_TYPE_ADDSESSION))
- .Times(2);
+ signin::GAIA_SERVICE_TYPE_ADDSESSION));
- NSDictionary* headers = [NSDictionary
- dictionaryWithObject:@"action=ADDSESSION,show_consistency_promo=true"
- forKey:@"X-Chrome-Manage-Accounts"];
+ NSDictionary* headers = [NSDictionary dictionaryWithObject:@"args=unused"
+ forKey:@"X-Auto-Login"];
NSHTTPURLResponse* responseSignin = [[NSHTTPURLResponse alloc]
initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"]
statusCode:200
@@ -543,28 +542,6 @@ TEST_F(AccountConsistencyServiceTest,
EXPECT_OCMOCK_VERIFY(delegate);
}
-// Tests that the consistency promo is not displayed when a non GAIA URL is
-// committed.
-TEST_F(AccountConsistencyServiceTest,
- ChromeManageAccountsNotShowConsistencyPromoOnNonGaiaURL) {
- id delegate =
- [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
- [[delegate reject] onShowConsistencyPromo];
-
- NSDictionary* headers = [NSDictionary
- dictionaryWithObject:@"action=ADDSESSION,show_consistency_promo=true"
- forKey:@"X-Chrome-Manage-Accounts"];
- NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
- initWithURL:[NSURL URLWithString:@"https://youtube.com//"]
- statusCode:200
- HTTPVersion:@"HTTP/1.1"
- headerFields:headers];
-
- SimulateNavigateToURL(response, delegate);
-
- EXPECT_OCMOCK_VERIFY(delegate);
-}
-
// Tests that the ManageAccountsDelegate is notified when a navigation on Gaia
// signon realm returns with a X-Chrome-Manage-Accounts header with ADDSESSION
// action.
@@ -673,74 +650,6 @@ TEST_F(AccountConsistencyServiceTest, SetChromeConnectedCookie) {
CheckDomainHasChromeConnectedCookie(kYoutubeDomain);
}
-// Tests that the GAIA cookie update time is not updated before the scheduled
-// interval.
-TEST_F(AccountConsistencyServiceTest, SetGaiaCookieUpdateNotUpdateTime) {
- SignIn();
-
- // HTTP response URL is eligible for Mirror (the test does not use google.com
- // since the CHROME_CONNECTED cookie is generated for it by default.
- NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
- initWithURL:[NSURL URLWithString:@"https://youtube.com"]
- statusCode:200
- HTTPVersion:@"HTTP/1.1"
- headerFields:@{}];
-
- SimulateNavigateToURL(response, nil);
-
- // Advance clock, but stay within the one-hour Gaia update time.
- base::TimeDelta oneMinuteDelta = base::TimeDelta::FromMinutes(1);
- task_environment_.FastForwardBy(oneMinuteDelta);
- SimulateNavigateToURL(response, nil);
-
- CheckGaiaCookieWithUpdateTime(base::Time::Now() - oneMinuteDelta);
-}
-
-// Tests that the GAIA cookie update time is updated at the scheduled interval.
-TEST_F(AccountConsistencyServiceTest, SetGaiaCookieUpdateAtUpdateTime) {
- SignIn();
-
- // HTTP response URL is eligible for Mirror (the test does not use google.com
- // since the CHROME_CONNECTED cookie is generated for it by default.
- NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
- initWithURL:[NSURL URLWithString:@"https://youtube.com"]
- statusCode:200
- HTTPVersion:@"HTTP/1.1"
- headerFields:@{}];
-
- SimulateNavigateToURL(response, nil);
-
- // Advance clock past one-hour Gaia update time.
- task_environment_.FastForwardBy(base::TimeDelta::FromHours(2));
- SimulateNavigateToURL(response, nil);
-
- CheckGaiaCookieWithUpdateTime(base::Time::Now());
-}
-
-// Ensures that the presence or absence of GAIA cookies is logged even if the
-// |kRestoreGAIACookiesIfDeleted| experiment is disabled.
-TEST_F(AccountConsistencyServiceTest, GAIACookieStatusLoggedProperly) {
- // HTTP response URL is eligible for Mirror (the test does not use google.com
- // since the CHROME_CONNECTED cookie is generated for it by default.
- NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
- initWithURL:[NSURL URLWithString:@"https://youtube.com"]
- statusCode:200
- HTTPVersion:@"HTTP/1.1"
- headerFields:@{}];
-
- base::HistogramTester histogram_tester;
- histogram_tester.ExpectTotalCount(kGAIACookieOnNavigationHistogram, 0);
-
- SimulateNavigateToURL(response, nil);
- base::RunLoop().RunUntilIdle();
- histogram_tester.ExpectTotalCount(kGAIACookieOnNavigationHistogram, 0);
-
- SignIn();
- SimulateNavigateToURL(response, nil);
- base::RunLoop().RunUntilIdle();
- histogram_tester.ExpectTotalCount(kGAIACookieOnNavigationHistogram, 1);
-}
-
// Tests that navigating to accounts.google.com without a GAIA cookie is logged
// by the navigation histogram.
TEST_F(AccountConsistencyServiceTest, GAIACookieMissingOnSignin) {
@@ -817,7 +726,7 @@ TEST_F(AccountConsistencyServiceTest, SetChromeConnectedCookiesAfterDelete) {
// is signed out and navigating to google.com for |kMobileIdentityConsistency|
// experiment.
TEST_F(AccountConsistencyServiceTest,
- SetMiceChromeConnectedCookiesSignedOutGoogleVisitor) {
+ SetChromeConnectedCookiesSignedOutGoogleVisitor) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(signin::kMobileIdentityConsistency);
id delegate =
@@ -840,21 +749,21 @@ TEST_F(AccountConsistencyServiceTest,
EXPECT_OCMOCK_VERIFY(delegate);
}
-// Ensures that CHROME_CONNECTED cookies are only set on GAIA urls when the user
-// is signed out and taps sign-in button for |kMobileIdentityConsistency|
-// experiment. These cookies are immediately removed after the sign-in promo is
-// shown.
+// Ensures that CHROME_CONNECTED cookies are not set when the user is signed out
+// after the sign-in promo is shown.
TEST_F(AccountConsistencyServiceTest,
- SetMiceChromeConnectedCookiesSignedOutGaiaVisitor) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(signin::kMobileIdentityConsistency);
+ SetChromeConnectedCookiesSignedOutGaiaVisitor) {
+ base::test::ScopedFeatureList consistency_feature_list;
+ consistency_feature_list.InitAndEnableFeature(
+ signin::kMobileIdentityConsistency);
+ base::test::ScopedFeatureList websignin_feature_list;
+ websignin_feature_list.InitAndEnableFeature(signin::kMICEWebSignIn);
id delegate =
[OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)];
- [[delegate expect] onShowConsistencyPromo];
+ [[[delegate expect] ignoringNonObjectArgs] onShowConsistencyPromo:GURL()];
- NSDictionary* headers = [NSDictionary
- dictionaryWithObject:@"action=ADDSESSION,show_consistency_promo=true"
- forKey:@"X-Chrome-Manage-Accounts"];
+ NSDictionary* headers = [NSDictionary dictionaryWithObject:@"args=unused"
+ forKey:@"X-Auto-Login"];
NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"]
statusCode:200
@@ -865,11 +774,61 @@ TEST_F(AccountConsistencyServiceTest,
EXPECT_TRUE(web_state_.ShouldAllowResponse(response,
/* for_main_frame = */ true));
- CheckDomainHasChromeConnectedCookie("accounts.google.com");
-
web_state_.SetCurrentURL(net::GURLWithNSURL(response.URL));
web_state_.OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS);
CheckNoChromeConnectedCookies();
EXPECT_OCMOCK_VERIFY(delegate);
}
+
+TEST_F(AccountConsistencyServiceTest, SetGaiaCookieUpdateBeforeDelay) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(signin::kRestoreGaiaCookiesOnUserAction);
+
+ SignIn();
+
+ NSDictionary* headers =
+ [NSDictionary dictionaryWithObject:@"action=ADDSESSION"
+ forKey:@"X-Chrome-Manage-Accounts"];
+ NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
+ initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"]
+ statusCode:200
+ HTTPVersion:@"HTTP/1.1"
+ headerFields:headers];
+
+ SimulateNavigateToURL(response, nil);
+
+ // Advance clock, but stay within the one-hour Gaia update time.
+ base::TimeDelta oneMinuteDelta = base::TimeDelta::FromMinutes(1);
+ task_environment_.FastForwardBy(oneMinuteDelta);
+ SimulateNavigateToURLWithInterruption(response, nil);
+
+ // Does not process the second Gaia restore event.
+ CheckGaiaCookieWithUpdateTime(base::Time::Now() - oneMinuteDelta);
+}
+
+TEST_F(AccountConsistencyServiceTest, SetGaiaCookieUpdateAfterDelay) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(signin::kRestoreGaiaCookiesOnUserAction);
+
+ SignIn();
+
+ NSDictionary* headers =
+ [NSDictionary dictionaryWithObject:@"action=ADDSESSION"
+ forKey:@"X-Chrome-Manage-Accounts"];
+ NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
+ initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"]
+ statusCode:200
+ HTTPVersion:@"HTTP/1.1"
+ headerFields:headers];
+
+ SimulateNavigateToURL(response, nil);
+
+ // Advance clock past the one-hour Gaia update time.
+ base::TimeDelta twoHourDelta = base::TimeDelta::FromHours(2);
+ task_environment_.FastForwardBy(twoHourDelta);
+ SimulateNavigateToURL(response, nil);
+
+ // Will process the second Gaia restore event, since it is past the delay.
+ CheckGaiaCookieWithUpdateTime(base::Time::Now());
+}
diff --git a/chromium/components/signin/ios/browser/features.cc b/chromium/components/signin/ios/browser/features.cc
index 8d2e2601f9a..a6e86425ff8 100644
--- a/chromium/components/signin/ios/browser/features.cc
+++ b/chromium/components/signin/ios/browser/features.cc
@@ -16,9 +16,6 @@ bool ForceStartupSigninPromo() {
return base::FeatureList::IsEnabled(kForceStartupSigninPromo);
}
-const base::Feature kRestoreGaiaCookiesIfDeleted{
- "RestoreGAIACookiesIfDeleted", base::FEATURE_DISABLED_BY_DEFAULT};
-
const base::Feature kRestoreGaiaCookiesOnUserAction{
"RestoreGAIACookiesOnUserAction", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromium/components/signin/ios/browser/features.h b/chromium/components/signin/ios/browser/features.h
index 89efdcecc00..3ee40d81779 100644
--- a/chromium/components/signin/ios/browser/features.h
+++ b/chromium/components/signin/ios/browser/features.h
@@ -18,9 +18,6 @@ extern const base::Feature kSimplifySignOutIOS;
// Returns true if the startup sign-in promo should be displayed at boot.
bool ForceStartupSigninPromo();
-// Feature controlling whether to restore GAIA cookies if they are deleted.
-extern const base::Feature kRestoreGaiaCookiesIfDeleted;
-
// Feature controlling whether to restore GAIA cookies when the user explicitly
// requests to sign in to a Google service.
extern const base::Feature kRestoreGaiaCookiesOnUserAction;
diff --git a/chromium/components/signin/ios/browser/manage_accounts_delegate.h b/chromium/components/signin/ios/browser/manage_accounts_delegate.h
index 763d93944cc..637b30f492c 100644
--- a/chromium/components/signin/ios/browser/manage_accounts_delegate.h
+++ b/chromium/components/signin/ios/browser/manage_accounts_delegate.h
@@ -22,7 +22,9 @@ class GURL;
// Called when the user taps a sign-in or add account button in a Google web
// property with signin::kMobileIdentityConsistency enabled.
-- (void)onShowConsistencyPromo;
+// |url| is the continuation URL received from the server. If it is valid,
+// then this delegate should navigate to |url|.
+- (void)onShowConsistencyPromo:(const GURL&)url;
// Called when the user taps on go incognito button in a Google web property.
// |url| is the continuation URL received from the server. If it is valid,
diff --git a/chromium/components/signin/public/android/BUILD.gn b/chromium/components/signin/public/android/BUILD.gn
index 06f18bf999e..f25e8537171 100644
--- a/chromium/components/signin/public/android/BUILD.gn
+++ b/chromium/components/signin/public/android/BUILD.gn
@@ -5,9 +5,11 @@ android_library("java") {
"$google_play_services_package:google_play_services_auth_base_java",
"$google_play_services_package:google_play_services_base_java",
"//base:base_java",
+ "//components/externalauth/android:java",
"//net/android:net_java",
"//third_party/android_deps:android_support_v4_java",
"//third_party/android_deps:chromium_play_services_availability_java",
+ "//third_party/android_deps:guava_android_java",
"//third_party/androidx:androidx_annotation_annotation_java",
]
@@ -19,23 +21,17 @@ android_library("java") {
sources = [
"java/src/org/chromium/components/signin/AccessTokenData.java",
"java/src/org/chromium/components/signin/AccountManagerDelegate.java",
- "java/src/org/chromium/components/signin/AccountManagerDelegateException.java",
"java/src/org/chromium/components/signin/AccountManagerFacade.java",
"java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java",
"java/src/org/chromium/components/signin/AccountManagerFacadeProvider.java",
- "java/src/org/chromium/components/signin/AccountManagerResult.java",
"java/src/org/chromium/components/signin/AccountRenameChecker.java",
- "java/src/org/chromium/components/signin/AccountTrackerService.java",
+ "java/src/org/chromium/components/signin/AccountRestrictionPatternReceiver.java",
"java/src/org/chromium/components/signin/AccountUtils.java",
"java/src/org/chromium/components/signin/AccountsChangeObserver.java",
"java/src/org/chromium/components/signin/AuthException.java",
"java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java",
"java/src/org/chromium/components/signin/ChildAccountStatus.java",
"java/src/org/chromium/components/signin/ConnectionRetry.java",
- "java/src/org/chromium/components/signin/GmsAvailabilityException.java",
- "java/src/org/chromium/components/signin/GmsJustUpdatedException.java",
- "java/src/org/chromium/components/signin/MutableObservableValue.java",
- "java/src/org/chromium/components/signin/ObservableValue.java",
"java/src/org/chromium/components/signin/PatternMatcher.java",
"java/src/org/chromium/components/signin/ProfileDataSource.java",
"java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java",
@@ -44,6 +40,7 @@ android_library("java") {
"java/src/org/chromium/components/signin/base/CoreAccountInfo.java",
"java/src/org/chromium/components/signin/base/GoogleServiceAuthError.java",
"java/src/org/chromium/components/signin/identitymanager/AccountInfoService.java",
+ "java/src/org/chromium/components/signin/identitymanager/AccountTrackerService.java",
"java/src/org/chromium/components/signin/identitymanager/IdentityManager.java",
"java/src/org/chromium/components/signin/identitymanager/IdentityMutator.java",
"java/src/org/chromium/components/signin/identitymanager/PrimaryAccountChangeEvent.java",
@@ -57,12 +54,12 @@ generate_jni("jni_headers") {
namespace = "signin"
sources = [
"java/src/org/chromium/components/signin/AccountManagerFacadeProvider.java",
- "java/src/org/chromium/components/signin/AccountTrackerService.java",
"java/src/org/chromium/components/signin/ChildAccountInfoFetcher.java",
"java/src/org/chromium/components/signin/base/AccountInfo.java",
"java/src/org/chromium/components/signin/base/CoreAccountId.java",
"java/src/org/chromium/components/signin/base/CoreAccountInfo.java",
"java/src/org/chromium/components/signin/base/GoogleServiceAuthError.java",
+ "java/src/org/chromium/components/signin/identitymanager/AccountTrackerService.java",
"java/src/org/chromium/components/signin/identitymanager/IdentityManager.java",
"java/src/org/chromium/components/signin/identitymanager/IdentityMutator.java",
"java/src/org/chromium/components/signin/identitymanager/PrimaryAccountChangeEvent.java",
@@ -83,6 +80,7 @@ android_library("signin_java_test_support") {
":test_support_jni_headers",
"//base:base_java",
"//base:jni_java",
+ "//third_party/android_deps:guava_android_java",
"//third_party/androidx:androidx_annotation_annotation_java",
"//third_party/mockito:mockito_java",
]
@@ -129,10 +127,9 @@ java_library("junit") {
sources = [
"junit/src/org/chromium/components/signin/AccountManagerFacadeImplTest.java",
"junit/src/org/chromium/components/signin/AccountRenameCheckerTest.java",
- "junit/src/org/chromium/components/signin/AccountTrackerServiceTest.java",
- "junit/src/org/chromium/components/signin/ObservableValueTest.java",
"junit/src/org/chromium/components/signin/PatternMatcherTest.java",
"junit/src/org/chromium/components/signin/identitymanager/AccountInfoServiceTest.java",
+ "junit/src/org/chromium/components/signin/identitymanager/AccountTrackerServiceTest.java",
]
deps = [
":java",
@@ -141,8 +138,13 @@ java_library("junit") {
"//base:base_java",
"//base:base_java_test_support",
"//base:base_junit_test_support",
+ "//components/externalauth/android:google_delegate_public_impl_java",
+ "//components/externalauth/android:java",
"//testing/android/junit:junit_test_support",
+ "//third_party/android_deps:guava_android_java",
"//third_party/android_deps:robolectric_all_java",
+ "//third_party/androidx:androidx_annotation_annotation_java",
+ "//third_party/androidx:androidx_test_rules_java",
"//third_party/junit",
"//third_party/mockito:mockito_java",
]
diff --git a/chromium/components/signin/public/android/DEPS b/chromium/components/signin/public/android/DEPS
index b8ac3035f71..944f0130c2e 100644
--- a/chromium/components/signin/public/android/DEPS
+++ b/chromium/components/signin/public/android/DEPS
@@ -1,3 +1,4 @@
include_rules = [
+ "+components/externalauth/android/java/src/org/chromium/components/externalauth/ExternalAuthUtils.java",
"+content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestThreadUtils.java",
]
diff --git a/chromium/components/signin/public/android/DIR_METADATA b/chromium/components/signin/public/android/DIR_METADATA
deleted file mode 100644
index 4735e25f37d..00000000000
--- a/chromium/components/signin/public/android/DIR_METADATA
+++ /dev/null
@@ -1,5 +0,0 @@
-monorail {
- component: "Services>SignIn"
-}
-
-team_email: "chrome-signin@chromium.org"
diff --git a/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountManagerFacadeImplTest.java b/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountManagerFacadeImplTest.java
index 2da2805f72a..07343569a1d 100644
--- a/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountManagerFacadeImplTest.java
+++ b/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountManagerFacadeImplTest.java
@@ -4,18 +4,21 @@
package org.chromium.components.signin;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
+import android.Manifest;
import android.accounts.Account;
+import android.accounts.AccountManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserManager;
+import androidx.test.rule.GrantPermissionRule;
+
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
@@ -24,87 +27,95 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import org.mockito.quality.Strictness;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowAccountManager;
+import org.robolectric.shadows.ShadowUserManager;
+import org.chromium.base.ThreadUtils;
import org.chromium.base.metrics.UmaRecorder;
import org.chromium.base.metrics.UmaRecorderHolder;
import org.chromium.base.task.test.CustomShadowAsyncTask;
import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.components.externalauth.ExternalAuthUtils;
import org.chromium.components.signin.AccountManagerFacade.ChildAccountStatusListener;
import org.chromium.components.signin.test.util.AccountHolder;
import org.chromium.components.signin.test.util.FakeAccountManagerDelegate;
-import org.chromium.testing.local.CustomShadowUserManager;
import java.util.List;
-import java.util.concurrent.TimeoutException;
/**
* Robolectric tests for {@link AccountManagerFacade}. See also {@link AccountManagerFacadeTest}.
*/
@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE,
- shadows = {CustomShadowAsyncTask.class, CustomShadowUserManager.class})
+@Config(shadows = {CustomShadowAsyncTask.class, ShadowUserManager.class,
+ ShadowAccountManager.class})
public class AccountManagerFacadeImplTest {
private static final String TEST_TOKEN_SCOPE = "test-token-scope";
- private CustomShadowUserManager mShadowUserManager;
- private FakeAccountManagerDelegate mDelegate;
- private AccountManagerFacade mFacade;
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
@Rule
- public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ public final GrantPermissionRule mGrantPermissionRule =
+ GrantPermissionRule.grant(Manifest.permission.GET_ACCOUNTS);
@Mock
private UmaRecorder mUmaRecorderMock;
+ @Mock
+ ExternalAuthUtils mExternalAuthUtilsMock;
+
+ @Mock
+ private AccountsChangeObserver mObserverMock;
+
+ @Mock
+ private ChildAccountStatusListener mChildAccountStatusListenerMock;
+
+ private final Context mContext = RuntimeEnvironment.application;
+ private ShadowUserManager mShadowUserManager;
+ private ShadowAccountManager mShadowAccountManager;
+ private FakeAccountManagerDelegate mDelegate;
+ private AccountManagerFacade mFacade;
+
+ // Prefer to use the facade with the real system delegate instead of the fake delegate
+ // to test the facade more thoroughly
+ private AccountManagerFacade mFacadeWithSystemDelegate;
+
@Before
public void setUp() {
UmaRecorderHolder.setNonNativeDelegate(mUmaRecorderMock);
- Context context = RuntimeEnvironment.application;
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- mShadowUserManager = (CustomShadowUserManager) shadowOf(userManager);
+ when(mExternalAuthUtilsMock.canUseGooglePlayServices()).thenReturn(true);
+ ExternalAuthUtils.setInstanceForTesting(mExternalAuthUtilsMock);
+
+ mShadowUserManager =
+ shadowOf((UserManager) mContext.getSystemService(Context.USER_SERVICE));
+ mShadowAccountManager = shadowOf(AccountManager.get(mContext));
+ ThreadUtils.setThreadAssertsDisabledForTesting(true);
mDelegate = new FakeAccountManagerDelegate();
mFacade = new AccountManagerFacadeImpl(mDelegate);
- }
- private void setAccountRestrictionPatterns(String... patterns) {
- Bundle restrictions = new Bundle();
- restrictions.putStringArray(
- AccountManagerFacadeImpl.ACCOUNT_RESTRICTION_PATTERNS_KEY, patterns);
- mShadowUserManager.setApplicationRestrictions(
- RuntimeEnvironment.application.getPackageName(), restrictions);
- RuntimeEnvironment.application.sendBroadcast(
- new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED));
- }
-
- private void clearAccountRestrictionPatterns() {
- mShadowUserManager.setApplicationRestrictions(
- RuntimeEnvironment.application.getPackageName(), new Bundle());
- RuntimeEnvironment.application.sendBroadcast(
- new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED));
+ mFacadeWithSystemDelegate =
+ new AccountManagerFacadeImpl(new SystemAccountManagerDelegate());
}
@Test
- public void testRegisterObserversCalledInConstructor() {
- FakeAccountManagerDelegate delegate = spy(new FakeAccountManagerDelegate());
- verify(delegate, never()).registerObservers();
- AccountManagerFacade accountManagerFacade = new AccountManagerFacadeImpl(delegate);
- verify(delegate).registerObservers();
+ public void testAccountsChangerObservationInitialization() {
+ mFacadeWithSystemDelegate.addObserver(mObserverMock);
+ verify(mObserverMock, never()).onAccountsChanged();
+
+ mContext.sendBroadcast(new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION));
+
+ verify(mObserverMock).onAccountsChanged();
}
@Test
public void testCountOfAccountLoggedAfterAccountsFetched() {
addTestAccount("test@gmail.com");
+
AccountManagerFacade facade = new AccountManagerFacadeImpl(mDelegate);
- CallbackHelper callbackHelper = new CallbackHelper();
- facade.runAfterCacheIsPopulated(() -> callbackHelper.notifyCalled());
- try {
- callbackHelper.waitForFirst();
- } catch (TimeoutException e) {
- throw new RuntimeException("Timed out waiting for callback", e);
- }
+
verify(mUmaRecorderMock)
.recordLinearHistogram("Signin.AndroidNumberOfDeviceAccounts", 1, 1, 50, 51);
}
@@ -112,7 +123,7 @@ public class AccountManagerFacadeImplTest {
@Test
public void testCanonicalAccount() {
addTestAccount("test@gmail.com");
- List<Account> accounts = mFacade.tryGetGoogleAccounts();
+ List<Account> accounts = mFacade.getGoogleAccounts().get();
Assert.assertNotNull(AccountUtils.findAccountByName(accounts, "test@gmail.com"));
Assert.assertNotNull(AccountUtils.findAccountByName(accounts, "Test@gmail.com"));
@@ -125,7 +136,7 @@ public class AccountManagerFacadeImplTest {
@Test
public void testNonCanonicalAccount() {
addTestAccount("test.me@gmail.com");
- List<Account> accounts = mFacade.tryGetGoogleAccounts();
+ List<Account> accounts = mFacade.getGoogleAccounts().get();
Assert.assertNotNull(AccountUtils.findAccountByName(accounts, "test.me@gmail.com"));
Assert.assertNotNull(AccountUtils.findAccountByName(accounts, "testme@gmail.com"));
@@ -134,106 +145,152 @@ public class AccountManagerFacadeImplTest {
}
@Test
- public void testGetAccounts() throws AccountManagerDelegateException {
- Assert.assertEquals(List.of(), mFacade.getGoogleAccounts());
+ public void testGetAccounts() {
+ Assert.assertEquals(List.of(), mFacade.getGoogleAccounts().get());
Account account = addTestAccount("test@gmail.com");
- Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts().get());
Account account2 = addTestAccount("test2@gmail.com");
- Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts().get());
Account account3 = addTestAccount("test3@gmail.com");
- Assert.assertEquals(List.of(account, account2, account3), mFacade.getGoogleAccounts());
+ Assert.assertEquals(
+ List.of(account, account2, account3), mFacade.getGoogleAccounts().get());
removeTestAccount(account2);
- Assert.assertEquals(List.of(account, account3), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account, account3), mFacade.getGoogleAccounts().get());
}
@Test
- public void testGetAccountsWithAccountPattern() throws AccountManagerDelegateException {
+ public void testGetAccountsWithAccountPattern() {
setAccountRestrictionPatterns("*@example.com");
Account account = addTestAccount("test@example.com");
- Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts().get());
addTestAccount("test@gmail.com"); // Doesn't match the pattern.
- Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts().get());
Account account2 = addTestAccount("test2@example.com");
- Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts().get());
addTestAccount("test2@gmail.com"); // Doesn't match the pattern.
- Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts().get());
removeTestAccount(account);
- Assert.assertEquals(List.of(account2), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account2), mFacade.getGoogleAccounts().get());
}
@Test
- public void testGetAccountsWithTwoAccountPatterns() throws AccountManagerDelegateException {
+ public void testGetAccountsWithTwoAccountPatterns() {
setAccountRestrictionPatterns("test1@example.com", "test2@gmail.com");
addTestAccount("test@gmail.com"); // Doesn't match the pattern.
addTestAccount("test@example.com"); // Doesn't match the pattern.
- Assert.assertEquals(List.of(), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(), mFacade.getGoogleAccounts().get());
Account account = addTestAccount("test1@example.com");
- Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts().get());
addTestAccount("test2@example.com"); // Doesn't match the pattern.
- Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts().get());
Account account2 = addTestAccount("test2@gmail.com");
- Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts().get());
}
@Test
- public void testGetAccountsWithAccountPatternsChange() throws AccountManagerDelegateException {
- Assert.assertEquals(List.of(), mFacade.getGoogleAccounts());
+ public void testGetAccountsWithAccountPatternsChange() {
+ Assert.assertEquals(List.of(), mFacade.getGoogleAccounts().get());
Account account = addTestAccount("test@gmail.com");
- Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts().get());
Account account2 = addTestAccount("test2@example.com");
- Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts().get());
Account account3 = addTestAccount("test3@gmail.com");
- Assert.assertEquals(List.of(account, account2, account3), mFacade.getGoogleAccounts());
+ Assert.assertEquals(
+ List.of(account, account2, account3), mFacade.getGoogleAccounts().get());
setAccountRestrictionPatterns("test@gmail.com");
- Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts().get());
setAccountRestrictionPatterns("*@example.com", "test3@gmail.com");
- Assert.assertEquals(List.of(account2, account3), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account2, account3), mFacade.getGoogleAccounts().get());
removeTestAccount(account3);
- Assert.assertEquals(List.of(account2), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account2), mFacade.getGoogleAccounts().get());
+ }
+
+ @Test
+ public void testGetAccountsWithAccountPatternsCleared() {
+ final Account account1 = addTestAccount("test1@gmail.com");
+ final Account account2 = addTestAccount("testexample2@example.com");
+ setAccountRestrictionPatterns("*@example.com");
+ Assert.assertEquals(List.of(account2), mFacade.getGoogleAccounts().get());
- clearAccountRestrictionPatterns();
- Assert.assertEquals(List.of(account, account2), mFacade.getGoogleAccounts());
+ mShadowUserManager.setApplicationRestrictions(mContext.getPackageName(), new Bundle());
+ mContext.sendBroadcast(new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED));
+
+ Assert.assertEquals(List.of(account1, account2), mFacade.getGoogleAccounts().get());
}
@Test
- public void testGetAccountsMultipleMatchingPatterns() throws AccountManagerDelegateException {
+ public void testGetAccountsMultipleMatchingPatterns() {
setAccountRestrictionPatterns("*@gmail.com", "test@gmail.com");
Account account = addTestAccount("test@gmail.com"); // Matches both patterns
- Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts());
+ Assert.assertEquals(List.of(account), mFacade.getGoogleAccounts().get());
}
@Test
- public void testCheckChildAccount() {
- Account testAccount = addTestAccount("test@gmail.com");
- Account ucaAccount = addTestAccount(
+ public void testCheckChildAccountForRegularChild() {
+ final Account account = setFeaturesForAccount(
"uca@gmail.com", AccountManagerFacadeImpl.FEATURE_IS_CHILD_ACCOUNT_KEY);
- Account usmAccount = addTestAccount(
+
+ mFacadeWithSystemDelegate.checkChildAccountStatus(account, mChildAccountStatusListenerMock);
+
+ verify(mChildAccountStatusListenerMock).onStatusReady(ChildAccountStatus.REGULAR_CHILD);
+ }
+
+ @Test
+ public void testCheckChildAccountForUSMChild() {
+ final Account account = setFeaturesForAccount(
"usm@gmail.com", AccountManagerFacadeImpl.FEATURE_IS_USM_ACCOUNT_KEY);
- Account bothAccount = addTestAccount("uca_usm@gmail.com",
- AccountManagerFacadeImpl.FEATURE_IS_CHILD_ACCOUNT_KEY,
- AccountManagerFacadeImpl.FEATURE_IS_USM_ACCOUNT_KEY);
-
- assertChildAccountStatus(testAccount, ChildAccountStatus.NOT_CHILD);
- assertChildAccountStatus(ucaAccount, ChildAccountStatus.REGULAR_CHILD);
- assertChildAccountStatus(usmAccount, ChildAccountStatus.USM_CHILD);
- assertChildAccountStatus(bothAccount, ChildAccountStatus.REGULAR_CHILD);
+
+ mFacadeWithSystemDelegate.checkChildAccountStatus(account, mChildAccountStatusListenerMock);
+
+ verify(mChildAccountStatusListenerMock).onStatusReady(ChildAccountStatus.USM_CHILD);
+ }
+
+ @Test
+ public void testCheckChildAccountForRegularUSMChild() {
+ final Account account = setFeaturesForAccount("usm_uca@gmail.com",
+ AccountManagerFacadeImpl.FEATURE_IS_USM_ACCOUNT_KEY,
+ AccountManagerFacadeImpl.FEATURE_IS_CHILD_ACCOUNT_KEY);
+
+ mFacadeWithSystemDelegate.checkChildAccountStatus(account, mChildAccountStatusListenerMock);
+
+ verify(mChildAccountStatusListenerMock).onStatusReady(ChildAccountStatus.REGULAR_CHILD);
+ }
+
+ @Test
+ public void testCheckChildAccountForAdult() {
+ final Account account = setFeaturesForAccount("adult@gmail.com");
+
+ mFacadeWithSystemDelegate.checkChildAccountStatus(account, mChildAccountStatusListenerMock);
+
+ verify(mChildAccountStatusListenerMock).onStatusReady(ChildAccountStatus.NOT_CHILD);
+ }
+
+ @Test
+ public void testGetAccessToken() throws AuthException {
+ final Account account = AccountUtils.createAccountFromName("test@gmail.com");
+ final AccessTokenData originalToken =
+ mFacadeWithSystemDelegate.getAccessToken(account, TEST_TOKEN_SCOPE);
+
+ Assert.assertEquals("The same token should be returned.",
+ mFacadeWithSystemDelegate.getAccessToken(account, TEST_TOKEN_SCOPE).getToken(),
+ originalToken.getToken());
}
@Test
@@ -243,7 +300,9 @@ public class AccountManagerFacadeImplTest {
Assert.assertEquals("The same token should be returned before invalidating the token.",
mFacade.getAccessToken(account, TEST_TOKEN_SCOPE).getToken(),
originalToken.getToken());
+
mFacade.invalidateAccessToken(originalToken.getToken());
+
final AccessTokenData newToken = mFacade.getAccessToken(account, TEST_TOKEN_SCOPE);
Assert.assertNotEquals(
"A different token should be returned since the original token is invalidated.",
@@ -255,22 +314,26 @@ public class AccountManagerFacadeImplTest {
AccountManagerFacadeProvider.getInstance();
}
- private Account addTestAccount(String accountEmail, String... features) {
- AccountHolder holder = AccountHolder.builder(accountEmail)
- .addFeatures(features)
- .build();
+ private Account setFeaturesForAccount(String email, String... features) {
+ final Account account = AccountUtils.createAccountFromName(email);
+ mShadowAccountManager.setFeatures(account, features);
+ return account;
+ }
+
+ private void setAccountRestrictionPatterns(String... patterns) {
+ Bundle restrictions = new Bundle();
+ restrictions.putStringArray("RestrictAccountsToPatterns", patterns);
+ mShadowUserManager.setApplicationRestrictions(mContext.getPackageName(), restrictions);
+ mContext.sendBroadcast(new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED));
+ }
+
+ private Account addTestAccount(String accountEmail) {
+ final AccountHolder holder = AccountHolder.createFromEmail(accountEmail);
mDelegate.addAccount(holder);
- Assert.assertFalse(((AccountManagerFacadeImpl) mFacade).isUpdatePending().get());
return holder.getAccount();
}
private void removeTestAccount(Account account) {
- mDelegate.removeAccount(AccountHolder.builder(account).build());
- }
-
- private void assertChildAccountStatus(Account account, @ChildAccountStatus.Status int status) {
- ChildAccountStatusListener listenerMock = mock(ChildAccountStatusListener.class);
- mFacade.checkChildAccountStatus(account, listenerMock);
- verify(listenerMock).onStatusReady(status);
+ mDelegate.removeAccount(AccountHolder.createFromAccount(account));
}
}
diff --git a/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountRenameCheckerTest.java b/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountRenameCheckerTest.java
index 52d9c158509..af336538277 100644
--- a/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountRenameCheckerTest.java
+++ b/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountRenameCheckerTest.java
@@ -7,6 +7,8 @@ package org.chromium.components.signin;
import android.accounts.Account;
import android.content.Context;
+import androidx.annotation.Nullable;
+
import com.google.android.gms.auth.AccountChangeEvent;
import com.google.android.gms.auth.GoogleAuthUtil;
@@ -18,6 +20,7 @@ import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
+import org.chromium.base.task.test.CustomShadowAsyncTask;
import org.chromium.base.test.BaseRobolectricTestRunner;
import java.util.ArrayList;
@@ -25,31 +28,35 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
/**
* JUnit tests of the class {@link AccountRenameChecker}.
*/
@RunWith(BaseRobolectricTestRunner.class)
-@Config(shadows = {AccountRenameCheckerTest.ShadowGoogleAuthUtil.class})
+@Config(shadows = {AccountRenameCheckerTest.ShadowGoogleAuthUtil.class,
+ CustomShadowAsyncTask.class})
public class AccountRenameCheckerTest {
@Implements(GoogleAuthUtil.class)
static final class ShadowGoogleAuthUtil {
- private static final Map<String, String> sEvents = new HashMap<>();
+ private static final Map<String, List<AccountChangeEvent>> sEvents = new HashMap<>();
@Implementation
public static List<AccountChangeEvent> getAccountChangeEvents(
Context context, int eventIndex, String accountEmail) {
- if (sEvents.containsKey(accountEmail)) {
- final AccountChangeEvent event = new AccountChangeEvent(0L, accountEmail,
- GoogleAuthUtil.CHANGE_TYPE_ACCOUNT_RENAMED_TO, 0,
- sEvents.get(accountEmail));
- return List.of(event);
- }
- return Collections.emptyList();
+ return sEvents.getOrDefault(accountEmail, Collections.emptyList());
}
static void insertRenameEvent(String from, String to) {
- sEvents.put(from, to);
+ addEvent(from,
+ new AccountChangeEvent(
+ 0L, from, GoogleAuthUtil.CHANGE_TYPE_ACCOUNT_RENAMED_TO, 0, to));
+ }
+
+ static void addEvent(String email, AccountChangeEvent event) {
+ final List<AccountChangeEvent> events = sEvents.getOrDefault(email, new ArrayList<>());
+ events.add(event);
+ sEvents.put(email, events);
}
static void clearAllEvents() {
@@ -57,7 +64,7 @@ public class AccountRenameCheckerTest {
}
}
- private final AccountRenameChecker mChecker = new AccountRenameChecker();
+ private final AccountRenameChecker mChecker = AccountRenameChecker.get();
@After
public void tearDown() {
@@ -68,21 +75,30 @@ public class AccountRenameCheckerTest {
public void newNameIsValidWhenTheRenamedAccountIsPresent() {
ShadowGoogleAuthUtil.insertRenameEvent("A", "B");
- Assert.assertEquals("B", mChecker.getNewNameOfRenamedAccount("A", getAccounts("B")));
+ Assert.assertEquals("B", getNewNameOfRenamedAccount("A", List.of("B")));
+ }
+
+ @Test
+ public void newNameIsValidWhenOldAccountIsRemovedAndThenRenamed() {
+ ShadowGoogleAuthUtil.addEvent("A",
+ new AccountChangeEvent(0L, "A", GoogleAuthUtil.CHANGE_TYPE_ACCOUNT_REMOVED, 0, ""));
+ ShadowGoogleAuthUtil.insertRenameEvent("A", "B");
+
+ Assert.assertEquals("B", getNewNameOfRenamedAccount("A", List.of("B")));
}
@Test
public void newNameIsNullWhenTheOldAccountIsNotRenamed() {
ShadowGoogleAuthUtil.insertRenameEvent("B", "C");
- Assert.assertNull(mChecker.getNewNameOfRenamedAccount("A", getAccounts("D")));
+ Assert.assertNull(getNewNameOfRenamedAccount("A", List.of("D")));
}
@Test
public void newNameIsNullWhenTheRenamedAccountIsNotPresent() {
ShadowGoogleAuthUtil.insertRenameEvent("B", "C");
- Assert.assertNull(mChecker.getNewNameOfRenamedAccount("B", getAccounts("D")));
+ Assert.assertNull(getNewNameOfRenamedAccount("B", List.of("D")));
}
@Test
@@ -90,7 +106,7 @@ public class AccountRenameCheckerTest {
ShadowGoogleAuthUtil.insertRenameEvent("A", "B");
ShadowGoogleAuthUtil.insertRenameEvent("B", "C");
- Assert.assertEquals("C", mChecker.getNewNameOfRenamedAccount("A", getAccounts("C")));
+ Assert.assertEquals("C", getNewNameOfRenamedAccount("A", List.of("C")));
}
@Test
@@ -102,7 +118,7 @@ public class AccountRenameCheckerTest {
ShadowGoogleAuthUtil.insertRenameEvent("B", "C");
ShadowGoogleAuthUtil.insertRenameEvent("C", "D");
- Assert.assertEquals("D", mChecker.getNewNameOfRenamedAccount("A", getAccounts("D")));
+ Assert.assertEquals("D", getNewNameOfRenamedAccount("A", List.of("D")));
}
@Test
@@ -115,14 +131,18 @@ public class AccountRenameCheckerTest {
ShadowGoogleAuthUtil.insertRenameEvent("C", "D");
ShadowGoogleAuthUtil.insertRenameEvent("D", "A"); // Looped.
- Assert.assertEquals("D", mChecker.getNewNameOfRenamedAccount("A", getAccounts("D", "X")));
+ Assert.assertEquals("D", getNewNameOfRenamedAccount("A", List.of("D", "X")));
}
- private List<Account> getAccounts(String... names) {
+ private @Nullable String getNewNameOfRenamedAccount(
+ String oldAccountEmail, List<String> accountEmails) {
final List<Account> accounts = new ArrayList<>();
- for (String name : names) {
- accounts.add(AccountUtils.createAccountFromName(name));
+ for (String email : accountEmails) {
+ accounts.add(AccountUtils.createAccountFromName(email));
}
- return accounts;
+ final AtomicReference<String> newAccountName = new AtomicReference<>();
+ mChecker.getNewNameOfRenamedAccountAsync(oldAccountEmail, accounts)
+ .then(newAccountName::set);
+ return newAccountName.get();
}
}
diff --git a/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/ObservableValueTest.java b/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/ObservableValueTest.java
deleted file mode 100644
index ab684c86961..00000000000
--- a/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/ObservableValueTest.java
+++ /dev/null
@@ -1,109 +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.
-package org.chromium.components.signin;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNull;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Robolectric tests for {@link ObservableValue}.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class ObservableValueTest {
- @Test
- public void testNullAllowed() {
- MutableObservableValue<Integer> value = new MutableObservableValue<>(null);
- // Using null as a value should be allowed.
- assertNull(value.get());
- }
-
- @Test
- public void testAddObserverNoCallsToOnValueChanged() {
- MutableObservableValue<Integer> value = new MutableObservableValue<>(0);
- ObservableValue.Observer observer = mock(ObservableValue.Observer.class);
- value.addObserver(observer);
- verifyZeroInteractions(observer);
- }
-
- @Test
- public void testObserverIsNotifiedOnSet() {
- MutableObservableValue<Integer> value = new MutableObservableValue<>(0);
- ObservableValue.Observer observer = mock(ObservableValue.Observer.class);
- value.addObserver(observer);
-
- value.set(1);
- assertEquals(1, (int) value.get());
- verify(observer, times(1)).onValueChanged();
- }
-
- @Test
- public void testObserverIsNotNotifiedOnSetWithTheSameValue() {
- MutableObservableValue<Integer> value = new MutableObservableValue<>(123);
- ObservableValue.Observer observer = mock(ObservableValue.Observer.class);
- value.addObserver(observer);
-
- // Manually allocate the new value to make sure it's a different object and not a reference
- // to the same object from Java integer pool.
- @SuppressWarnings("UnnecessaryBoxing")
- Integer newValue = new Integer(123);
-
- value.set(newValue);
- assertEquals(123, (int) value.get());
- verifyZeroInteractions(observer);
- }
-
- @Test
- public void testObserverIsNotNotifiedAfterRemoval() {
- MutableObservableValue<Integer> value = new MutableObservableValue<>(0);
- ObservableValue.Observer observer = mock(ObservableValue.Observer.class);
- value.addObserver(observer);
-
- value.removeObserver(observer);
- value.set(321);
- assertEquals(321, (int) value.get());
- verifyZeroInteractions(observer);
- }
-
- @Test
- public void testGetReturnsUpdatedValueFromObserver() {
- MutableObservableValue<Integer> value = new MutableObservableValue<>(0);
- AtomicInteger valueHolder = new AtomicInteger(0);
- value.addObserver(() -> valueHolder.set(value.get()));
-
- value.set(123);
- assertEquals(123, valueHolder.get());
- }
-
- @Test
- public void testCanModifyObserverListFromOnValueChanged() {
- MutableObservableValue<Integer> value = new MutableObservableValue<>(0);
- AtomicInteger callCounter = new AtomicInteger(0);
- ObservableValue.Observer observer = new ObservableValue.Observer() {
- @Override
- public void onValueChanged() {
- callCounter.incrementAndGet();
- value.removeObserver(this);
- }
- };
- value.addObserver(observer);
- value.set(234);
- assertEquals("Observer should be invoked once", 1, callCounter.get());
- value.set(345);
- assertEquals("Observer should've been removed after the first call", 1, callCounter.get());
- }
-}
diff --git a/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/identitymanager/AccountInfoServiceTest.java b/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/identitymanager/AccountInfoServiceTest.java
index c3a3a692757..88e7a54aa87 100644
--- a/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/identitymanager/AccountInfoServiceTest.java
+++ b/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/identitymanager/AccountInfoServiceTest.java
@@ -37,6 +37,9 @@ public class AccountInfoServiceTest {
private IdentityManager mIdentityManagerMock;
@Mock
+ private AccountTrackerService mAccountTrackerServiceMock;
+
+ @Mock
private AccountInfoService.Observer mObserverMock;
private final AccountInfo mAccountInfoWithAvatar =
@@ -47,7 +50,7 @@ public class AccountInfoServiceTest {
@Before
public void setUp() {
- AccountInfoService.init(mIdentityManagerMock);
+ AccountInfoService.init(mIdentityManagerMock, mAccountTrackerServiceMock);
mService = AccountInfoService.get();
}
diff --git a/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountTrackerServiceTest.java b/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/identitymanager/AccountTrackerServiceTest.java
index e8fcb271e69..14597aad2e8 100644
--- a/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/AccountTrackerServiceTest.java
+++ b/chromium/components/signin/public/android/junit/src/org/chromium/components/signin/identitymanager/AccountTrackerServiceTest.java
@@ -2,7 +2,7 @@
// 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;
+package org.chromium.components.signin.identitymanager;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -38,6 +38,8 @@ import org.chromium.base.Callback;
import org.chromium.base.task.test.CustomShadowAsyncTask;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.JniMocker;
+import org.chromium.components.signin.AccountManagerFacadeProvider;
+import org.chromium.components.signin.AccountUtils;
import org.chromium.components.signin.base.CoreAccountInfo;
import org.chromium.components.signin.test.util.FakeAccountManagerFacade;
@@ -98,16 +100,6 @@ public class AccountTrackerServiceTest {
}
@Test
- public void testSeedAccountsWithoutGooglePlayServices() {
- when(mFakeAccountManagerFacade.isGooglePlayServicesAvailable()).thenReturn(false);
-
- mService.seedAccountsIfNeeded(mRunnableMock);
-
- verify(mFakeAccountManagerFacade, never()).tryGetGoogleAccounts(any());
- verify(mRunnableMock, never()).run();
- }
-
- @Test
public void testSeedAccountsIfNeededBeforeAccountsAreSeeded() {
mService.seedAccountsIfNeeded(mRunnableMock);
@@ -227,7 +219,7 @@ public class AccountTrackerServiceTest {
final AtomicInteger invocationCount = new AtomicInteger(0);
doAnswer(AdditionalAnswers.answerVoid((VoidAnswer1<Callback<List<Account>>>) argument0 -> {
if (invocationCount.incrementAndGet() < expectedNumberOfInvocations) {
- argument0.onResult(mFakeAccountManagerFacade.tryGetGoogleAccounts());
+ argument0.onResult(mFakeAccountManagerFacade.getGoogleAccounts().get());
}
}))
.when(mFakeAccountManagerFacade)
diff --git a/chromium/components/signin/public/base/account_consistency_method.cc b/chromium/components/signin/public/base/account_consistency_method.cc
index 9898ec09bed..1e706d0d992 100644
--- a/chromium/components/signin/public/base/account_consistency_method.cc
+++ b/chromium/components/signin/public/base/account_consistency_method.cc
@@ -19,17 +19,29 @@ const base::Feature kMobileIdentityConsistencyVar{
// Feature flag for FRE related changes as part of MICE.
const base::Feature kMobileIdentityConsistencyFRE{
"MobileIdentityConsistencyFRE", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kMobileIdentityConsistencyPromos{
+ "MobileIdentityConsistencyPromos", base::FEATURE_DISABLED_BY_DEFAULT};
#endif
#if defined(OS_IOS)
const base::Feature kMobileIdentityConsistency{
"MobileIdentityConsistency", base::FEATURE_DISABLED_BY_DEFAULT};
-#endif
+
+const base::Feature kMICEWebSignIn{"MICEWebSignInEnabled",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+#endif // defined(OS_IOS)
#if defined(OS_ANDROID) || defined(OS_IOS)
bool IsMobileIdentityConsistencyEnabled() {
return base::FeatureList::IsEnabled(kMobileIdentityConsistency);
}
-#endif
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+
+#if defined(OS_IOS)
+bool IsMICEWebSignInEnabled() {
+ return IsMobileIdentityConsistencyEnabled() &&
+ base::FeatureList::IsEnabled(kMICEWebSignIn);
+}
+#endif // defined(OS_IOS)
} // namespace signin
diff --git a/chromium/components/signin/public/base/account_consistency_method.h b/chromium/components/signin/public/base/account_consistency_method.h
index b0779772fb5..e4a6ea6ee40 100644
--- a/chromium/components/signin/public/base/account_consistency_method.h
+++ b/chromium/components/signin/public/base/account_consistency_method.h
@@ -27,7 +27,19 @@ bool IsMobileIdentityConsistencyEnabled();
// Feature flag for FRE related changes as part of MICE.
extern const base::Feature kMobileIdentityConsistencyFRE;
-#endif
+
+// Feature flag for promo-related changes of `kMobileIdentityConsistency`.
+extern const base::Feature kMobileIdentityConsistencyPromos;
+#endif // defined(OS_ANDROID) || defined(OS_IOS)
+
+#if defined(OS_IOS)
+// Feature flag for promo-related changes of `kMobileIdentityConsistency`.
+extern const base::Feature kMICEWebSignIn;
+
+// Returns true if the flags |kMICEWebSignInEnabled| and
+// |kMobileIdentityConsistency| are enabled for the platform.
+bool IsMICEWebSignInEnabled();
+#endif // defined(OS_IOS)
enum class AccountConsistencyMethod : int {
// No account consistency.
diff --git a/chromium/components/signin/public/base/multilogin_parameters.cc b/chromium/components/signin/public/base/multilogin_parameters.cc
index ce5878cf683..19ec7b85267 100644
--- a/chromium/components/signin/public/base/multilogin_parameters.cc
+++ b/chromium/components/signin/public/base/multilogin_parameters.cc
@@ -6,8 +6,7 @@
namespace signin {
-MultiloginParameters::MultiloginParameters()
- : mode(gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER) {}
+MultiloginParameters::MultiloginParameters() = default;
MultiloginParameters::MultiloginParameters(
const gaia::MultiloginMode mode,
diff --git a/chromium/components/signin/public/base/multilogin_parameters.h b/chromium/components/signin/public/base/multilogin_parameters.h
index efb672e3e0b..4859c7c6749 100644
--- a/chromium/components/signin/public/base/multilogin_parameters.h
+++ b/chromium/components/signin/public/base/multilogin_parameters.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_SIGNIN_PUBLIC_BASE_MULTILOGIN_PARAMETERS_H_
#define COMPONENTS_SIGNIN_PUBLIC_BASE_MULTILOGIN_PARAMETERS_H_
-#include <string>
#include <vector>
#include "google_apis/gaia/core_account_id.h"
@@ -26,7 +25,12 @@ struct MultiloginParameters {
return mode == other.mode && accounts_to_send == other.accounts_to_send;
}
- gaia::MultiloginMode mode;
+ bool operator!=(const MultiloginParameters& other) const {
+ return !(*this == other);
+ }
+
+ gaia::MultiloginMode mode =
+ gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER;
std::vector<CoreAccountId> accounts_to_send;
};
} // namespace signin
diff --git a/chromium/components/signin/public/base/signin_client.h b/chromium/components/signin/public/base/signin_client.h
index 2f917a15cab..48b496d10a4 100644
--- a/chromium/components/signin/public/base/signin_client.h
+++ b/chromium/components/signin/public/base/signin_client.h
@@ -9,7 +9,6 @@
#include "base/callback.h"
#include "base/callback_list.h"
-#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/keyed_service/core/keyed_service.h"
@@ -19,8 +18,8 @@
#include "url/gurl.h"
#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "base/optional.h"
#include "components/account_manager_core/account.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#endif
class PrefService;
@@ -100,7 +99,7 @@ class SigninClient : public KeyedService {
virtual bool IsNonEnterpriseUser(const std::string& username);
#if BUILDFLAG(IS_CHROMEOS_LACROS)
- virtual base::Optional<account_manager::Account>
+ virtual absl::optional<account_manager::Account>
GetInitialPrimaryAccount() = 0;
#endif
};
diff --git a/chromium/components/signin/public/base/signin_metrics.cc b/chromium/components/signin/public/base/signin_metrics.cc
index 9f4b9c7853a..40e268f9be6 100644
--- a/chromium/components/signin/public/base/signin_metrics.cc
+++ b/chromium/components/signin/public/base/signin_metrics.cc
@@ -43,10 +43,6 @@ void RecordSigninUserActionForAccessPoint(AccessPoint access_point) {
base::RecordAction(
base::UserMetricsAction("Signin_Signin_FromExtensions"));
break;
- case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
- base::RecordAction(
- base::UserMetricsAction("Signin_Signin_FromAppsPageLink"));
- break;
case AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE:
base::RecordAction(
base::UserMetricsAction("Signin_Signin_FromBookmarkBubble"));
@@ -198,7 +194,6 @@ void RecordSigninWithDefaultUserActionForAccessPoint(
case AccessPoint::ACCESS_POINT_MENU:
case AccessPoint::ACCESS_POINT_SUPERVISED_USER:
case AccessPoint::ACCESS_POINT_EXTENSIONS:
- case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
case AccessPoint::ACCESS_POINT_USER_MANAGER:
case AccessPoint::ACCESS_POINT_DEVICES_PAGE:
case AccessPoint::ACCESS_POINT_CLOUD_PRINT:
@@ -278,7 +273,6 @@ void RecordSigninNotDefaultUserActionForAccessPoint(
case AccessPoint::ACCESS_POINT_MENU:
case AccessPoint::ACCESS_POINT_SUPERVISED_USER:
case AccessPoint::ACCESS_POINT_EXTENSIONS:
- case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
case AccessPoint::ACCESS_POINT_USER_MANAGER:
case AccessPoint::ACCESS_POINT_DEVICES_PAGE:
case AccessPoint::ACCESS_POINT_CLOUD_PRINT:
@@ -362,7 +356,6 @@ void RecordSigninNewAccountNoExistingAccountUserActionForAccessPoint(
case AccessPoint::ACCESS_POINT_MENU:
case AccessPoint::ACCESS_POINT_SUPERVISED_USER:
case AccessPoint::ACCESS_POINT_EXTENSIONS:
- case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
case AccessPoint::ACCESS_POINT_USER_MANAGER:
case AccessPoint::ACCESS_POINT_DEVICES_PAGE:
case AccessPoint::ACCESS_POINT_CLOUD_PRINT:
@@ -449,7 +442,6 @@ void RecordSigninNewAccountExistingAccountUserActionForAccessPoint(
case AccessPoint::ACCESS_POINT_MENU:
case AccessPoint::ACCESS_POINT_SUPERVISED_USER:
case AccessPoint::ACCESS_POINT_EXTENSIONS:
- case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
case AccessPoint::ACCESS_POINT_USER_MANAGER:
case AccessPoint::ACCESS_POINT_DEVICES_PAGE:
case AccessPoint::ACCESS_POINT_CLOUD_PRINT:
@@ -825,10 +817,6 @@ void RecordSigninImpressionUserActionForAccessPoint(AccessPoint access_point) {
base::RecordAction(base::UserMetricsAction(
"Signin_Impression_FromExtensionInstallBubble"));
break;
- case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
- base::RecordAction(
- base::UserMetricsAction("Signin_Impression_FromAppsPageLink"));
- break;
case AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE:
base::RecordAction(
base::UserMetricsAction("Signin_Impression_FromBookmarkBubble"));
@@ -1025,7 +1013,6 @@ void RecordSigninImpressionWithAccountUserActionForAccessPoint(
case AccessPoint::ACCESS_POINT_MENU:
case AccessPoint::ACCESS_POINT_SUPERVISED_USER:
case AccessPoint::ACCESS_POINT_EXTENSIONS:
- case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
case AccessPoint::ACCESS_POINT_USER_MANAGER:
case AccessPoint::ACCESS_POINT_DEVICES_PAGE:
case AccessPoint::ACCESS_POINT_CLOUD_PRINT:
diff --git a/chromium/components/signin/public/base/signin_metrics.h b/chromium/components/signin/public/base/signin_metrics.h
index b9e4d70c593..f4cf883cb24 100644
--- a/chromium/components/signin/public/base/signin_metrics.h
+++ b/chromium/components/signin/public/base/signin_metrics.h
@@ -148,7 +148,7 @@ enum class AccessPoint : int {
ACCESS_POINT_SUPERVISED_USER = 4,
ACCESS_POINT_EXTENSION_INSTALL_BUBBLE = 5,
ACCESS_POINT_EXTENSIONS = 6,
- ACCESS_POINT_APPS_PAGE_LINK = 7,
+ // ACCESS_POINT_APPS_PAGE_LINK = 7, no longer used.
ACCESS_POINT_BOOKMARK_BUBBLE = 8,
ACCESS_POINT_BOOKMARK_MANAGER = 9,
ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN = 10,
@@ -222,52 +222,51 @@ enum class AccountConsistencyPromoAction : int {
// Promo is not shown as there are no accounts on device.
SUPPRESSED_NO_ACCOUNTS = 0,
// User has dismissed the promo by tapping back button.
- DISMISSED_BACK,
+ DISMISSED_BACK = 1,
// User has tapped |Add account to device| from expanded account list.
- ADD_ACCOUNT_STARTED,
- // User tapped the button from the expanded account list to open the incognito
- // interstitial
- // then confirmed opening the page in the incognito tab by tapping |Continue|
- // in the incognito
- // interstitial.
- STARTED_INCOGNITO_SESSION,
+ ADD_ACCOUNT_STARTED = 2,
+
+ // Deprecated 05/2021, since the Incognito option has been removed from
+ // account picker bottomsheet.
+ // STARTED_INCOGNITO_SESSION = 3,
+
// User has selected the default account and signed in with it
- SIGNED_IN_WITH_DEFAULT_ACCOUNT,
+ SIGNED_IN_WITH_DEFAULT_ACCOUNT = 4,
// User has selected one of the non default accounts and signed in with it.
- SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT,
+ SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT = 5,
// The promo was shown to user.
- SHOWN,
+ SHOWN = 6,
// Promo is not shown due to sign-in being disallowed either by an enterprise
// policy
// or by |Allow Chrome sign-in| toggle.
- SUPPRESSED_SIGNIN_NOT_ALLOWED,
+ SUPPRESSED_SIGNIN_NOT_ALLOWED = 7,
// User has added an account and signed in with this account.
// When this metric is recorded, we won't record
// SIGNED_IN_WITH_DEFAULT_ACCOUNT or
// SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT.
- SIGNED_IN_WITH_ADDED_ACCOUNT,
+ SIGNED_IN_WITH_ADDED_ACCOUNT = 8,
// User has dismissed the promo by tapping on the scrim above the bottom
// sheet.
- DISMISSED_SCRIM,
+ DISMISSED_SCRIM = 9,
// User has dismissed the promo by swiping down the bottom sheet.
- DISMISSED_SWIPE_DOWN,
+ DISMISSED_SWIPE_DOWN = 10,
// User has dismissed the promo by other means.
- DISMISSED_OTHER,
+ DISMISSED_OTHER = 11,
// The auth error screen was shown to the user.
- AUTH_ERROR_SHOWN,
+ AUTH_ERROR_SHOWN = 12,
// The generic error screen was shown to the user.
- GENERIC_ERROR_SHOWN,
+ GENERIC_ERROR_SHOWN = 13,
// User has dismissed the promo by tapping on the dismissal button in the
// bottom sheet.
- DISMISSED_BUTTON,
+ DISMISSED_BUTTON = 14,
// User has completed the account addition flow triggered from the bottom
// sheet.
- ADD_ACCOUNT_COMPLETED,
+ ADD_ACCOUNT_COMPLETED = 15,
// The bottom sheet was suppressed as the user hit consecutive active
// dismissal limit.
- SUPPRESSED_CONSECUTIVE_DISMISSALS,
+ SUPPRESSED_CONSECUTIVE_DISMISSALS = 16,
- MAX,
+ MAX = 17,
};
// This class is used to record web sign-in events within 2 minutes after
diff --git a/chromium/components/signin/public/base/signin_metrics_unittest.cc b/chromium/components/signin/public/base/signin_metrics_unittest.cc
index bda46e4f579..540566d8d54 100644
--- a/chromium/components/signin/public/base/signin_metrics_unittest.cc
+++ b/chromium/components/signin/public/base/signin_metrics_unittest.cc
@@ -23,7 +23,6 @@ const AccessPoint kAccessPointsThatSupportUserAction[] = {
AccessPoint::ACCESS_POINT_SUPERVISED_USER,
AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE,
AccessPoint::ACCESS_POINT_EXTENSIONS,
- AccessPoint::ACCESS_POINT_APPS_PAGE_LINK,
AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE,
AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER,
AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN,
@@ -50,7 +49,6 @@ const AccessPoint kAccessPointsThatSupportImpression[] = {
AccessPoint::ACCESS_POINT_MENU,
AccessPoint::ACCESS_POINT_SETTINGS,
AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE,
- AccessPoint::ACCESS_POINT_APPS_PAGE_LINK,
AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE,
AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER,
AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN,
@@ -97,8 +95,6 @@ class SigninMetricsTest : public ::testing::Test {
return "ExtensionInstallBubble";
case AccessPoint::ACCESS_POINT_EXTENSIONS:
return "Extensions";
- case AccessPoint::ACCESS_POINT_APPS_PAGE_LINK:
- return "AppsPageLink";
case AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE:
return "BookmarkBubble";
case AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER:
diff --git a/chromium/components/signin/public/base/signin_pref_names.cc b/chromium/components/signin/public/base/signin_pref_names.cc
index bba71b0bc08..1803fb0eb3a 100644
--- a/chromium/components/signin/public/base/signin_pref_names.cc
+++ b/chromium/components/signin/public/base/signin_pref_names.cc
@@ -85,6 +85,10 @@ const char kSignedInWithCredentialProvider[] =
// Boolean which stores if the user is allowed to signin to chrome.
const char kSigninAllowed[] = "signin.allowed";
+// Boolean which stores if the user is allowed to signin to chrome with the
+// current applied policies.
+const char kSigninAllowedByPolicy[] = "signin.allowed_by_policy";
+
// True if the token service has been prepared for Dice migration.
const char kTokenServiceDiceCompatible[] = "token_service.dice_compatible";
diff --git a/chromium/components/signin/public/base/signin_pref_names.h b/chromium/components/signin/public/base/signin_pref_names.h
index 3230e8533db..8d49c5b4c57 100644
--- a/chromium/components/signin/public/base/signin_pref_names.h
+++ b/chromium/components/signin/public/base/signin_pref_names.h
@@ -27,6 +27,7 @@ extern const char kGoogleServicesUsernamePattern[];
extern const char kReverseAutologinRejectedEmailList[];
extern const char kSignedInWithCredentialProvider[];
extern const char kSigninAllowed[];
+extern const char kSigninAllowedByPolicy[];
extern const char kTokenServiceDiceCompatible[];
extern const char kGaiaCookieLastListAccountsData[];
diff --git a/chromium/components/signin/public/base/signin_switches.cc b/chromium/components/signin/public/base/signin_switches.cc
index 8243123737b..58f66e6b66e 100644
--- a/chromium/components/signin/public/base/signin_switches.cc
+++ b/chromium/components/signin/public/base/signin_switches.cc
@@ -4,6 +4,7 @@
#include "components/signin/public/base/signin_switches.h"
+#include "base/feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -29,13 +30,16 @@ const base::Feature kForceAccountIdMigration{"ForceAccountIdMigration",
// Menagerie API.
const base::Feature kDeprecateMenagerieAPI{"DeprecateMenagerieAPI",
base::FEATURE_DISABLED_BY_DEFAULT};
+// This feature flag is used to wipe device data on child account signin.
+const base::Feature kWipeDataOnChildAccountSignin{
+ "WipeDataOnChildAccountSignin", base::FEATURE_DISABLED_BY_DEFAULT};
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
const base::Feature kUseAccountManagerFacade{"kUseAccountManagerFacade",
base::FEATURE_ENABLED_BY_DEFAULT};
-#elif BUILDFLAG(IS_CHROMEOS_LACROS)
-const base::Feature kUseAccountManagerFacade{"kUseAccountManagerFacade",
- base::FEATURE_DISABLED_BY_DEFAULT};
#endif
+
+const base::Feature kMinorModeSupport{"MinorModeSupport",
+ base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace switches
diff --git a/chromium/components/signin/public/base/signin_switches.h b/chromium/components/signin/public/base/signin_switches.h
index fa46dd79e23..9a634b37dbc 100644
--- a/chromium/components/signin/public/base/signin_switches.h
+++ b/chromium/components/signin/public/base/signin_switches.h
@@ -31,12 +31,17 @@ extern const base::Feature kForceAccountIdMigration;
// This feature flag is for the deprecating of the Android profile data
// Menagerie API.
extern const base::Feature kDeprecateMenagerieAPI;
+// This feature flag is used to wipe device data on child account signin.
+extern const base::Feature kWipeDataOnChildAccountSignin;
#endif // defined(OS_ANDROID)
-#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
// Killswitch for PO2TS migration to AccountManagerFacade.
extern const base::Feature kUseAccountManagerFacade;
#endif
+
+// Support for the minor mode.
+extern const base::Feature kMinorModeSupport;
} // namespace switches
#endif // COMPONENTS_SIGNIN_PUBLIC_BASE_SIGNIN_SWITCHES_H_
diff --git a/chromium/components/signin/public/base/test_signin_client.cc b/chromium/components/signin/public/base/test_signin_client.cc
index 767a7aa6bd8..871b1bd2501 100644
--- a/chromium/components/signin/public/base/test_signin_client.cc
+++ b/chromium/components/signin/public/base/test_signin_client.cc
@@ -14,8 +14,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "base/optional.h"
#include "components/account_manager_core/account.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#endif
TestSigninClient::TestSigninClient(
@@ -122,14 +122,14 @@ bool TestSigninClient::IsNonEnterpriseUser(const std::string& email) {
}
#if BUILDFLAG(IS_CHROMEOS_LACROS)
-base::Optional<account_manager::Account>
+absl::optional<account_manager::Account>
TestSigninClient::GetInitialPrimaryAccount() {
return initial_primary_account_;
}
void TestSigninClient::SetInitialPrimaryAccountForTests(
const account_manager::Account& account) {
- initial_primary_account_ = base::make_optional(account);
+ initial_primary_account_ = absl::make_optional(account);
}
#endif
diff --git a/chromium/components/signin/public/base/test_signin_client.h b/chromium/components/signin/public/base/test_signin_client.h
index 7c2b09f37dc..a8bd37e7788 100644
--- a/chromium/components/signin/public/base/test_signin_client.h
+++ b/chromium/components/signin/public/base/test_signin_client.h
@@ -21,8 +21,8 @@
#include "services/network/test/test_url_loader_factory.h"
#if BUILDFLAG(IS_CHROMEOS_LACROS)
-#include "base/optional.h"
#include "components/account_manager_core/account.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#endif
class PrefService;
@@ -96,7 +96,7 @@ class TestSigninClient : public SigninClient {
void SetDiceMigrationCompleted() override;
bool IsNonEnterpriseUser(const std::string& email) override;
#if BUILDFLAG(IS_CHROMEOS_LACROS)
- base::Optional<account_manager::Account> GetInitialPrimaryAccount() override;
+ absl::optional<account_manager::Account> GetInitialPrimaryAccount() override;
#endif
#if BUILDFLAG(IS_CHROMEOS_LACROS)
@@ -119,7 +119,7 @@ class TestSigninClient : public SigninClient {
std::vector<base::OnceClosure> delayed_network_calls_;
#if BUILDFLAG(IS_CHROMEOS_LACROS)
- base::Optional<account_manager::Account> initial_primary_account_;
+ absl::optional<account_manager::Account> initial_primary_account_;
#endif
DISALLOW_COPY_AND_ASSIGN(TestSigninClient);
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 54ddaf3a6af..0e6161b5236 100644
--- a/chromium/components/signin/public/identity_manager/access_token_fetcher.cc
+++ b/chromium/components/signin/public/identity_manager/access_token_fetcher.cc
@@ -8,6 +8,7 @@
#include "base/check_op.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "components/signin/public/identity_manager/access_token_constants.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "google_apis/gaia/gaia_constants.h"
diff --git a/chromium/components/signin/public/identity_manager/account_info.h b/chromium/components/signin/public/identity_manager/account_info.h
index dbffa5e86ff..739f77ceab3 100644
--- a/chromium/components/signin/public/identity_manager/account_info.h
+++ b/chromium/components/signin/public/identity_manager/account_info.h
@@ -7,9 +7,9 @@
#include <string>
-#include "base/optional.h"
#include "build/build_config.h"
#include "google_apis/gaia/core_account_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/image/image.h"
#if defined(OS_ANDROID)
diff --git a/chromium/components/signin/public/identity_manager/accounts_cookie_mutator.h b/chromium/components/signin/public/identity_manager/accounts_cookie_mutator.h
index 200fd2a1f69..81df07c1fd8 100644
--- a/chromium/components/signin/public/identity_manager/accounts_cookie_mutator.h
+++ b/chromium/components/signin/public/identity_manager/accounts_cookie_mutator.h
@@ -132,6 +132,10 @@ class AccountsCookieMutator {
gaia::GaiaSource source,
LogOutFromCookieCompletedCallback completion_callback) = 0;
+ // Indicates that an account previously listed via ListAccounts should now
+ // be removed.
+ virtual void RemoveLoggedOutAccountByGaiaId(const std::string& gaia_id) = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(AccountsCookieMutator);
};
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 77a4839d460..3ab7cb41a99 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
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "base/test/task_environment.h"
diff --git a/chromium/components/signin/public/identity_manager/accounts_mutator.h b/chromium/components/signin/public/identity_manager/accounts_mutator.h
index ab675b1712d..b2c34f4e908 100644
--- a/chromium/components/signin/public/identity_manager/accounts_mutator.h
+++ b/chromium/components/signin/public/identity_manager/accounts_mutator.h
@@ -8,9 +8,9 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "build/chromeos_buildflags.h"
#include "components/signin/public/base/signin_buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace signin_metrics {
enum class SourceForRefreshTokenOperation;
@@ -39,8 +39,8 @@ class AccountsMutator {
// Updates the information about account identified by |account_id|.
virtual void UpdateAccountInfo(
const CoreAccountId& account_id,
- base::Optional<bool> is_child_account,
- base::Optional<bool> is_under_advanced_protection) = 0;
+ absl::optional<bool> is_child_account,
+ absl::optional<bool> is_under_advanced_protection) = 0;
// Removes the account given by |account_id|. Also revokes the token
// server-side if needed.
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 fef09d7213b..0daef5ace2b 100644
--- a/chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/accounts_mutator_unittest.cc
@@ -5,7 +5,6 @@
#include "components/signin/internal/identity_manager/accounts_mutator_impl.h"
#include "base/bind.h"
-#include "base/optional.h"
#include "base/test/gtest_util.h"
#include "base/test/task_environment.h"
#include "build/chromeos_buildflags.h"
@@ -18,6 +17,7 @@
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace {
@@ -157,7 +157,7 @@ TEST_F(AccountsMutatorTest, UpdateAccountInfo) {
accounts_mutator()->UpdateAccountInfo(
account_id,
/*is_child_account=*/true,
- /*is_under_advanced_protection=*/base::nullopt);
+ /*is_under_advanced_protection=*/absl::nullopt);
AccountInfo updated_account_info_1 =
identity_manager()
->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
@@ -175,7 +175,7 @@ TEST_F(AccountsMutatorTest, UpdateAccountInfo) {
original_account_info.is_under_advanced_protection);
accounts_mutator()->UpdateAccountInfo(account_id,
- /*is_child_account=*/base::nullopt,
+ /*is_child_account=*/absl::nullopt,
/*is_under_advanced_protection=*/true);
AccountInfo updated_account_info_2 =
identity_manager()
@@ -334,8 +334,8 @@ TEST_F(AccountsMutatorTest,
// Set up the primary account.
std::string primary_account_email("primary.account@example.com");
- AccountInfo primary_account_info =
- MakePrimaryAccountAvailable(identity_manager(), primary_account_email);
+ AccountInfo primary_account_info = MakePrimaryAccountAvailable(
+ identity_manager(), primary_account_email, signin::ConsentLevel::kSync);
// Now try invalidating the primary account, and check that it gets updated.
base::RunLoop run_loop;
@@ -372,8 +372,8 @@ TEST_F(
// Set up the primary account.
std::string primary_account_email("primary.account@example.com");
- AccountInfo primary_account_info =
- MakePrimaryAccountAvailable(identity_manager(), primary_account_email);
+ AccountInfo primary_account_info = MakePrimaryAccountAvailable(
+ identity_manager(), primary_account_email, signin::ConsentLevel::kSync);
// Next, add a secondary account.
base::RunLoop run_loop;
diff --git a/chromium/components/signin/public/identity_manager/device_accounts_synchronizer.h b/chromium/components/signin/public/identity_manager/device_accounts_synchronizer.h
index 3c441ae850f..20c2e3a551f 100644
--- a/chromium/components/signin/public/identity_manager/device_accounts_synchronizer.h
+++ b/chromium/components/signin/public/identity_manager/device_accounts_synchronizer.h
@@ -5,9 +5,9 @@
#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_DEVICE_ACCOUNTS_SYNCHRONIZER_H_
#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_DEVICE_ACCOUNTS_SYNCHRONIZER_H_
-#include "base/optional.h"
#include "build/build_config.h"
#include "google_apis/gaia/core_account_id.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace signin {
@@ -22,7 +22,7 @@ class DeviceAccountsSynchronizer {
// accounts will be visible in IdentityManager::GetAccountsWithRefreshTokens()
// with any persistent errors cleared after this method is called.
virtual void ReloadAllAccountsFromSystemWithPrimaryAccount(
- const base::Optional<CoreAccountId>& primary_account_id) = 0;
+ const absl::optional<CoreAccountId>& primary_account_id) = 0;
#if defined(OS_IOS)
// Reloads the information of the device-level account with |account_id|. The
diff --git a/chromium/components/signin/public/identity_manager/identity_manager.cc b/chromium/components/signin/public/identity_manager/identity_manager.cc
index 16c774d763c..2c6f6372c02 100644
--- a/chromium/components/signin/public/identity_manager/identity_manager.cc
+++ b/chromium/components/signin/public/identity_manager/identity_manager.cc
@@ -7,7 +7,6 @@
#include <string>
#include "base/bind.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/signin/internal/identity_manager/account_fetcher_service.h"
@@ -23,6 +22,7 @@
#include "components/signin/public/identity_manager/diagnostics_provider.h"
#include "components/signin/public/identity_manager/primary_account_mutator.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if defined(OS_ANDROID)
#include "base/android/jni_string.h"
@@ -60,12 +60,13 @@ void SetPrimaryAccount(IdentityManager* identity_manager,
const CoreAccountId account_id = account_tracker_service->SeedAccountInfo(
/*gaia=*/device_account.key.id, device_account.raw_email);
// TODO(https://crbug.com/1194983): Figure out how split sync settings will
- // work here.
- identity_manager->GetPrimaryAccountMutator()->SetUnconsentedPrimaryAccount(
- account_id);
+ // work here. For now, we will mimic Ash's behaviour of having sync turned on
+ // by default.
+ identity_manager->GetPrimaryAccountMutator()->SetPrimaryAccount(
+ account_id, ConsentLevel::kSync);
- CHECK(identity_manager->HasPrimaryAccount(ConsentLevel::kSignin));
- CHECK_EQ(identity_manager->GetPrimaryAccountInfo(ConsentLevel::kSignin).gaia,
+ CHECK(identity_manager->HasPrimaryAccount(ConsentLevel::kSync));
+ CHECK_EQ(identity_manager->GetPrimaryAccountInfo(ConsentLevel::kSync).gaia,
device_account.key.id);
}
#endif
@@ -136,7 +137,7 @@ IdentityManager::IdentityManager(IdentityManager::InitParameters&& parameters)
// Profile / KeyedServices - but with the availability of IdentityManager. We
// don't have such a place in Lacros - which guarantees that the Primary
// Account will be available on startup - just like Ash.
- base::Optional<account_manager::Account> initial_account =
+ absl::optional<account_manager::Account> initial_account =
signin_client_->GetInitialPrimaryAccount();
if (initial_account.has_value()) {
SetPrimaryAccount(this, account_tracker_service_.get(), signin_client_,
@@ -178,7 +179,7 @@ void IdentityManager::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
-// TODO(862619) change return type to base::Optional<CoreAccountInfo>
+// TODO(862619) change return type to absl::optional<CoreAccountInfo>
CoreAccountInfo IdentityManager::GetPrimaryAccountInfo(
ConsentLevel consent) const {
return primary_account_manager_->GetPrimaryAccountInfo(consent);
@@ -297,7 +298,16 @@ GoogleServiceAuthError IdentityManager::GetErrorStateOfRefreshTokenForAccount(
return token_service_->GetAuthError(account_id);
}
-base::Optional<AccountInfo>
+absl::optional<AccountInfo> IdentityManager::FindExtendedAccountInfoByAccountId(
+ const CoreAccountId& account_id) const {
+ AccountInfo account_info =
+ account_tracker_service_->GetAccountInfo(account_id);
+ if (account_info.IsEmpty())
+ return absl::nullopt;
+ return account_info;
+}
+
+absl::optional<AccountInfo>
IdentityManager::FindExtendedAccountInfoForAccountWithRefreshToken(
const CoreAccountInfo& account_info) const {
AccountInfo extended_account_info =
@@ -307,12 +317,12 @@ IdentityManager::FindExtendedAccountInfoForAccountWithRefreshToken(
// case of failure, the AccountInfo will be unpopulated, thus we should not
// be able to find a valid refresh token.
if (!HasAccountWithRefreshToken(extended_account_info.account_id))
- return base::nullopt;
+ return absl::nullopt;
return GetAccountInfoForAccountWithRefreshToken(account_info.account_id);
}
-base::Optional<AccountInfo>
+absl::optional<AccountInfo>
IdentityManager::FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
const CoreAccountId& account_id) const {
AccountInfo account_info =
@@ -322,12 +332,12 @@ IdentityManager::FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
// case of failure, the AccountInfo will be unpopulated, thus we should not
// be able to find a valid refresh token.
if (!HasAccountWithRefreshToken(account_info.account_id))
- return base::nullopt;
+ return absl::nullopt;
return GetAccountInfoForAccountWithRefreshToken(account_info.account_id);
}
-base::Optional<AccountInfo> IdentityManager::
+absl::optional<AccountInfo> IdentityManager::
FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
const std::string& email_address) const {
AccountInfo account_info =
@@ -337,12 +347,12 @@ base::Optional<AccountInfo> IdentityManager::
// case of failure, the AccountInfo will be unpopulated, thus we should not
// be able to find a valid refresh token.
if (!HasAccountWithRefreshToken(account_info.account_id))
- return base::nullopt;
+ return absl::nullopt;
return GetAccountInfoForAccountWithRefreshToken(account_info.account_id);
}
-base::Optional<AccountInfo>
+absl::optional<AccountInfo>
IdentityManager::FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
const std::string& gaia_id) const {
AccountInfo account_info =
@@ -352,7 +362,7 @@ IdentityManager::FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
// case of failure, the AccountInfo will be unpopulated, thus we should not
// be able to find a valid refresh token.
if (!HasAccountWithRefreshToken(account_info.account_id))
- return base::nullopt;
+ return absl::nullopt;
return GetAccountInfoForAccountWithRefreshToken(account_info.account_id);
}
diff --git a/chromium/components/signin/public/identity_manager/identity_manager.h b/chromium/components/signin/public/identity_manager/identity_manager.h
index ce7d2a4cc23..20c54fca5ca 100644
--- a/chromium/components/signin/public/identity_manager/identity_manager.h
+++ b/chromium/components/signin/public/identity_manager/identity_manager.h
@@ -251,17 +251,23 @@ class IdentityManager : public KeyedService,
GoogleServiceAuthError GetErrorStateOfRefreshTokenForAccount(
const CoreAccountId& account_id) const;
+ // Returns extended information for account identified by |account_id|.
+ // The information will be returned if the information is available regardless
+ // of whether the refresh token is available for the account.
+ absl::optional<AccountInfo> FindExtendedAccountInfoByAccountId(
+ const CoreAccountId& account_id) const;
+
// 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> FindExtendedAccountInfoForAccountWithRefreshToken(
+ absl::optional<AccountInfo> FindExtendedAccountInfoForAccountWithRefreshToken(
const CoreAccountInfo& account_info) const;
// Looks up and returns information for account with given |account_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>
+ absl::optional<AccountInfo>
FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
const CoreAccountId& account_id) const;
@@ -269,7 +275,7 @@ class IdentityManager : public KeyedService,
// 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>
+ absl::optional<AccountInfo>
FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
const std::string& email_address) const;
@@ -277,7 +283,7 @@ class IdentityManager : public KeyedService,
// 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>
+ absl::optional<AccountInfo>
FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
const std::string& gaia_id) const;
@@ -486,10 +492,8 @@ class IdentityManager : public KeyedService,
private:
// These test helpers need to use some of the private methods below.
friend CoreAccountInfo SetPrimaryAccount(IdentityManager* identity_manager,
- const std::string& email);
- friend CoreAccountInfo SetUnconsentedPrimaryAccount(
- IdentityManager* identity_manager,
- const std::string& email);
+ const std::string& email,
+ ConsentLevel consent_level);
friend void SetRefreshTokenForPrimaryAccount(
IdentityManager* identity_manager,
const std::string& token_value);
@@ -499,7 +503,8 @@ class IdentityManager : public KeyedService,
IdentityManager* identity_manager);
friend AccountInfo MakePrimaryAccountAvailable(
IdentityManager* identity_manager,
- const std::string& email);
+ const std::string& email,
+ ConsentLevel consent_level);
friend void RevokeSyncConsent(IdentityManager* identity_manager);
friend void ClearPrimaryAccount(IdentityManager* identity_manager);
friend AccountInfo MakeAccountAvailable(IdentityManager* identity_manager,
diff --git a/chromium/components/signin/public/identity_manager/identity_manager_builder.cc b/chromium/components/signin/public/identity_manager/identity_manager_builder.cc
index cff722fb004..18eef228dd3 100644
--- a/chromium/components/signin/public/identity_manager/identity_manager_builder.cc
+++ b/chromium/components/signin/public/identity_manager/identity_manager_builder.cc
@@ -115,9 +115,11 @@ IdentityManager::InitParameters BuildIdentityManagerInitParameters(
params->pref_service, account_tracker_service.get(),
params->network_connection_tracker, params->account_consistency,
#if BUILDFLAG(IS_CHROMEOS_ASH)
- params->account_manager, params->account_manager_facade,
- params->is_regular_profile,
-#endif
+ params->account_manager,
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
+ params->account_manager_facade, params->is_regular_profile,
+#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
#if !defined(OS_ANDROID)
params->delete_signin_cookies_on_exit, params->token_web_data,
#endif
diff --git a/chromium/components/signin/public/identity_manager/identity_manager_builder.h b/chromium/components/signin/public/identity_manager/identity_manager_builder.h
index dfd07ac8789..26818a57ebf 100644
--- a/chromium/components/signin/public/identity_manager/identity_manager_builder.h
+++ b/chromium/components/signin/public/identity_manager/identity_manager_builder.h
@@ -51,6 +51,12 @@ class AccountManagerFacade;
}
#endif
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+namespace account_manager {
+class AccountManagerFacade;
+}
+#endif
+
namespace signin {
enum class AccountConsistencyMethod;
@@ -58,25 +64,31 @@ struct IdentityManagerBuildParams {
IdentityManagerBuildParams();
~IdentityManagerBuildParams();
- AccountConsistencyMethod account_consistency;
+ AccountConsistencyMethod account_consistency =
+ AccountConsistencyMethod::kDisabled;
std::unique_ptr<AccountTrackerService> account_tracker_service;
std::unique_ptr<image_fetcher::ImageDecoder> image_decoder;
- PrefService* local_state;
+ PrefService* local_state = nullptr;
network::NetworkConnectionTracker* network_connection_tracker;
- PrefService* pref_service;
+ PrefService* pref_service = nullptr;
base::FilePath profile_path;
- SigninClient* signin_client;
+ SigninClient* signin_client = nullptr;
std::unique_ptr<ProfileOAuth2TokenService> token_service;
#if !defined(OS_ANDROID)
- bool delete_signin_cookies_on_exit;
+ bool delete_signin_cookies_on_exit = false;
scoped_refptr<TokenWebData> token_web_data;
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
- ash::AccountManager* account_manager;
- account_manager::AccountManagerFacade* account_manager_facade;
- bool is_regular_profile;
+ ash::AccountManager* account_manager = nullptr;
+ account_manager::AccountManagerFacade* account_manager_facade = nullptr;
+ bool is_regular_profile = false;
+#endif
+
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+ account_manager::AccountManagerFacade* account_manager_facade = nullptr;
+ bool is_regular_profile = false;
#endif
#if defined(OS_IOS)
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 bdf6ef105fb..9206820d912 100644
--- a/chromium/components/signin/public/identity_manager/identity_manager_unittest.cc
+++ b/chromium/components/signin/public/identity_manager/identity_manager_unittest.cc
@@ -562,7 +562,7 @@ TEST_F(IdentityManagerTest, PrimaryAccountInfoAtStartup) {
TEST_F(IdentityManagerTest, PrimaryAccountInfoAfterSignin) {
ClearPrimaryAccount(identity_manager());
- SetPrimaryAccount(identity_manager(), kTestEmail);
+ SetPrimaryAccount(identity_manager(), kTestEmail, ConsentLevel::kSync);
auto event = identity_manager_observer()->GetPrimaryAccountChangedEvent();
EXPECT_EQ(PrimaryAccountChangeEvent::Type::kSet,
event.GetEventTypeFor(ConsentLevel::kSync));
@@ -598,7 +598,7 @@ TEST_F(IdentityManagerTest, PrimaryAccountInfoAfterSigninAndSignout) {
ClearPrimaryAccount(identity_manager());
// First ensure that the user is signed in from the POV of the
// IdentityManager.
- SetPrimaryAccount(identity_manager(), kTestEmail);
+ SetPrimaryAccount(identity_manager(), kTestEmail, ConsentLevel::kSync);
// Sign the user out and check that the IdentityManager responds
// appropriately.
@@ -642,7 +642,7 @@ TEST_F(IdentityManagerTest,
ClearPrimaryAccount(identity_manager());
// First ensure that the user is signed in from the POV of the
// IdentityManager.
- SetPrimaryAccount(identity_manager(), kTestEmail);
+ SetPrimaryAccount(identity_manager(), kTestEmail, ConsentLevel::kSync);
identity_manager()->account_fetcher_service_->EnableAccountRemovalForTest();
// Revoke the primary's account credentials from the token service and
@@ -1259,8 +1259,7 @@ TEST_F(IdentityManagerTest, RemoveAccessTokenFromCache) {
identity_manager()->GetAccountTrackerService()->SeedAccountInfo(kTestGaiaId,
kTestEmail);
identity_manager()->GetPrimaryAccountMutator()->SetPrimaryAccount(
- primary_account_id());
-
+ primary_account_id(), ConsentLevel::kSync);
SetRefreshTokenForAccount(identity_manager(), primary_account_id(),
"refresh_token");
@@ -1303,7 +1302,7 @@ TEST_F(IdentityManagerTest,
identity_manager()->GetAccountTrackerService()->SeedAccountInfo(kTestGaiaId,
kTestEmail);
identity_manager()->GetPrimaryAccountMutator()->SetPrimaryAccount(
- primary_account_id());
+ primary_account_id(), ConsentLevel::kSync);
SetRefreshTokenForAccount(identity_manager(), primary_account_id(),
"refresh_token");
@@ -1396,7 +1395,7 @@ TEST_F(IdentityManagerTest, ObserveAccessTokenFetch) {
identity_manager()->GetAccountTrackerService()->SeedAccountInfo(kTestGaiaId,
kTestEmail);
identity_manager()->GetPrimaryAccountMutator()->SetPrimaryAccount(
- primary_account_id());
+ primary_account_id(), ConsentLevel::kSync);
SetRefreshTokenForAccount(identity_manager(), primary_account_id(),
"refresh_token");
@@ -1454,7 +1453,7 @@ TEST_F(IdentityManagerTest,
identity_manager()->GetAccountTrackerService()->SeedAccountInfo(kTestGaiaId,
kTestEmail);
identity_manager()->GetPrimaryAccountMutator()->SetPrimaryAccount(
- primary_account_id());
+ primary_account_id(), ConsentLevel::kSync);
SetRefreshTokenForAccount(identity_manager(), primary_account_id(),
"refresh_token");
token_service()->set_auto_post_fetch_response_on_message_loop(true);
@@ -2146,7 +2145,7 @@ TEST_F(IdentityManagerTest,
identity_manager()->GetAccountTrackerService()->SeedAccountInfo(kTestGaiaId,
kTestEmail);
identity_manager()->GetPrimaryAccountMutator()->SetPrimaryAccount(
- primary_account_id());
+ primary_account_id(), ConsentLevel::kSync);
SetRefreshTokenForAccount(identity_manager(), primary_account_id(),
"refresh_token");
@@ -2157,6 +2156,26 @@ TEST_F(IdentityManagerTest,
identity_manager_observer()->BatchChangeRecords().at(0).at(0));
}
+// Checks that FindExtendedAccountInfoByAccountId() returns information about
+// the account if the account is found or nullopt if there are no accounts with
+// requested |account_id|.
+TEST_F(IdentityManagerTest, FindExtendedAccountInfoByAccountId) {
+ auto account_id =
+ identity_manager()->PickAccountIdForAccount(kTestGaiaId, kTestEmail);
+
+ absl::optional<AccountInfo> maybe_account_info;
+ maybe_account_info = identity_manager()->FindExtendedAccountInfoByAccountId(
+ CoreAccountId("dummy_value"));
+ EXPECT_FALSE(maybe_account_info.has_value());
+
+ maybe_account_info =
+ identity_manager()->FindExtendedAccountInfoByAccountId(account_id);
+ EXPECT_TRUE(maybe_account_info.has_value());
+ EXPECT_EQ(account_id, maybe_account_info.value().account_id);
+ EXPECT_EQ(kTestEmail, maybe_account_info.value().email);
+ EXPECT_EQ(kTestGaiaId, maybe_account_info.value().gaia);
+}
+
// Checks that FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId()
// returns information about the account if the account is found or nullopt if
// there are no accounts with requested |account_id|.
@@ -2167,7 +2186,7 @@ TEST_F(IdentityManagerTest,
const AccountInfo foo_account_info =
MakeAccountAvailable(identity_manager(), "foo@bar.com");
- base::Optional<AccountInfo> maybe_account_info;
+ absl::optional<AccountInfo> maybe_account_info;
maybe_account_info =
identity_manager()
->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
@@ -2194,7 +2213,7 @@ TEST_F(IdentityManagerTest,
const AccountInfo foo_account_info =
MakeAccountAvailable(identity_manager(), "foo@bar.com");
- base::Optional<AccountInfo> maybe_account_info;
+ absl::optional<AccountInfo> maybe_account_info;
maybe_account_info =
identity_manager()
->FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(
@@ -2221,7 +2240,7 @@ TEST_F(IdentityManagerTest,
const AccountInfo foo_account_info =
MakeAccountAvailable(identity_manager(), "foo@bar.com");
- base::Optional<AccountInfo> maybe_account_info;
+ absl::optional<AccountInfo> maybe_account_info;
maybe_account_info =
identity_manager()
->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(
@@ -2375,7 +2394,7 @@ TEST_F(IdentityManagerTest, FindExtendedAccountInfoForAccountWithRefreshToken) {
// FindExtendedAccountInfoForAccountWithRefreshToken() returns extended
// account information if the account is known and has valid refresh token.
- const base::Optional<AccountInfo> extended_account_info =
+ const absl::optional<AccountInfo> extended_account_info =
identity_manager()->FindExtendedAccountInfoForAccountWithRefreshToken(
account_info);
@@ -2388,9 +2407,9 @@ TEST_F(IdentityManagerTest, FindExtendedAccountInfoForAccountWithRefreshToken) {
#if defined(OS_ANDROID)
TEST_F(IdentityManagerTest, ForceRefreshOfExtendedAccountInfo) {
// The flow of this test results in an interaction with
- // ChildAccountInfoFetcherAndroid, which requires initialization in order to
- // avoid a crash.
- ChildAccountInfoFetcherAndroid::InitializeForTests();
+ // ChildAccountInfoFetcherAndroid, which requires initialization of
+ // AccountManagerFacade in java code to avoid a crash.
+ SetUpMockAccountManagerFacade();
identity_manager()->GetAccountFetcherService()->OnNetworkInitialized();
AccountInfo account_info =
diff --git a/chromium/components/signin/public/identity_manager/identity_mutator.cc b/chromium/components/signin/public/identity_manager/identity_mutator.cc
index fe5b5bac5c9..094e4406a8f 100644
--- a/chromium/components/signin/public/identity_manager/identity_mutator.cc
+++ b/chromium/components/signin/public/identity_manager/identity_mutator.cc
@@ -29,20 +29,10 @@ bool JniIdentityMutator::SetPrimaryAccount(
PrimaryAccountMutator* primary_account_mutator =
identity_mutator_->GetPrimaryAccountMutator();
DCHECK(primary_account_mutator);
- // TODO(https://crbug.com/1046746): Refactor PrimaryAccountMutator API and
- // pass ConsentLevel directly there.
- switch (static_cast<ConsentLevel>(j_consent_level)) {
- case ConsentLevel::kSync:
- return primary_account_mutator->SetPrimaryAccount(
- ConvertFromJavaCoreAccountId(env, primary_account_id));
- case ConsentLevel::kSignin:
- primary_account_mutator->SetUnconsentedPrimaryAccount(
- ConvertFromJavaCoreAccountId(env, primary_account_id));
- return true;
- default:
- NOTREACHED() << "Unknown consent level: " << j_consent_level;
- return false;
- }
+
+ return primary_account_mutator->SetPrimaryAccount(
+ ConvertFromJavaCoreAccountId(env, primary_account_id),
+ static_cast<ConsentLevel>(j_consent_level));
}
bool JniIdentityMutator::ClearPrimaryAccount(JNIEnv* env,
@@ -62,7 +52,7 @@ void JniIdentityMutator::ReloadAllAccountsFromSystemWithPrimaryAccount(
DeviceAccountsSynchronizer* device_accounts_synchronizer =
identity_mutator_->GetDeviceAccountsSynchronizer();
DCHECK(device_accounts_synchronizer);
- base::Optional<CoreAccountId> primary_account_id;
+ absl::optional<CoreAccountId> primary_account_id;
if (j_primary_account_id) {
primary_account_id =
ConvertFromJavaCoreAccountId(env, j_primary_account_id);
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 d5bd7fee328..72280aa9e8a 100644
--- a/chromium/components/signin/public/identity_manager/identity_test_environment.cc
+++ b/chromium/components/signin/public/identity_manager/identity_test_environment.cc
@@ -376,12 +376,14 @@ void IdentityTestEnvironment::WaitForRefreshTokensLoaded() {
CoreAccountInfo IdentityTestEnvironment::SetPrimaryAccount(
const std::string& email) {
- return signin::SetPrimaryAccount(identity_manager(), email);
+ return signin::SetPrimaryAccount(identity_manager(), email,
+ signin::ConsentLevel::kSync);
}
CoreAccountInfo IdentityTestEnvironment::SetUnconsentedPrimaryAccount(
const std::string& email) {
- return signin::SetUnconsentedPrimaryAccount(identity_manager(), email);
+ return signin::SetPrimaryAccount(identity_manager(), email,
+ signin::ConsentLevel::kSignin);
}
void IdentityTestEnvironment::SetRefreshTokenForPrimaryAccount() {
@@ -398,7 +400,8 @@ void IdentityTestEnvironment::RemoveRefreshTokenForPrimaryAccount() {
AccountInfo IdentityTestEnvironment::MakePrimaryAccountAvailable(
const std::string& email) {
- return signin::MakePrimaryAccountAvailable(identity_manager(), email);
+ return signin::MakePrimaryAccountAvailable(identity_manager(), email,
+ signin::ConsentLevel::kSync);
}
AccountInfo IdentityTestEnvironment::MakeUnconsentedPrimaryAccountAvailable(
@@ -408,8 +411,8 @@ AccountInfo IdentityTestEnvironment::MakeUnconsentedPrimaryAccountAvailable(
// Chrome OS sets the unconsented primary account during login and does not
// allow signout.
AccountInfo account_info = MakeAccountAvailable(email);
- identity_manager()->GetPrimaryAccountMutator()->SetUnconsentedPrimaryAccount(
- account_info.account_id);
+ identity_manager()->GetPrimaryAccountMutator()->SetPrimaryAccount(
+ account_info.account_id, signin::ConsentLevel::kSignin);
#elif defined(OS_IOS)
// iOS only support the primary account.
AccountInfo account_info = MakePrimaryAccountAvailable(email);
@@ -421,9 +424,8 @@ AccountInfo IdentityTestEnvironment::MakeUnconsentedPrimaryAccountAvailable(
// Tests that don't use the |SigninManager| needs the unconsented primary
// account to be set manually.
if (!identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin)) {
- identity_manager()
- ->GetPrimaryAccountMutator()
- ->SetUnconsentedPrimaryAccount(account_info.account_id);
+ identity_manager()->GetPrimaryAccountMutator()->SetPrimaryAccount(
+ account_info.account_id, signin::ConsentLevel::kSignin);
}
#endif
DCHECK(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
@@ -491,7 +493,7 @@ void IdentityTestEnvironment::
const std::string& token,
const base::Time& expiration,
const std::string& id_token) {
- WaitForAccessTokenRequestIfNecessary(base::nullopt);
+ WaitForAccessTokenRequestIfNecessary(absl::nullopt);
fake_token_service()->IssueTokenForAllPendingRequests(
TokenResponseBuilder()
.WithAccessToken(token)
@@ -521,7 +523,7 @@ void IdentityTestEnvironment::
const base::Time& expiration,
const std::string& id_token,
const ScopeSet& scopes) {
- WaitForAccessTokenRequestIfNecessary(base::nullopt);
+ WaitForAccessTokenRequestIfNecessary(absl::nullopt);
fake_token_service()->IssueTokenForScope(scopes,
TokenResponseBuilder()
.WithAccessToken(token)
@@ -533,7 +535,7 @@ void IdentityTestEnvironment::
void IdentityTestEnvironment::
WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
const GoogleServiceAuthError& error) {
- WaitForAccessTokenRequestIfNecessary(base::nullopt);
+ WaitForAccessTokenRequestIfNecessary(absl::nullopt);
fake_token_service()->IssueErrorForAllPendingRequests(error);
}
@@ -611,7 +613,7 @@ void IdentityTestEnvironment::HandleOnAccessTokenRequested(
}
void IdentityTestEnvironment::WaitForAccessTokenRequestIfNecessary(
- base::Optional<CoreAccountId> account_id) {
+ absl::optional<CoreAccountId> account_id) {
// Handle HandleOnAccessTokenRequested getting called before
// WaitForAccessTokenRequestIfNecessary.
if (account_id) {
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 48054519d75..5db0d967ae9 100644
--- a/chromium/components/signin/public/identity_manager/identity_test_environment.h
+++ b/chromium/components/signin/public/identity_manager/identity_test_environment.h
@@ -10,7 +10,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -19,6 +18,7 @@
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "components/signin/public/identity_manager/scope_set.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class FakeProfileOAuth2TokenService;
class IdentityTestEnvironmentProfileAdaptor;
@@ -346,7 +346,7 @@ class IdentityTestEnvironment : public IdentityManager::DiagnosticsObserver,
kPending,
kAvailable,
} state;
- base::Optional<CoreAccountId> account_id;
+ absl::optional<CoreAccountId> account_id;
base::OnceClosure on_available;
};
@@ -421,7 +421,7 @@ class IdentityTestEnvironment : public IdentityManager::DiagnosticsObserver,
// Otherwise and runs a nested runloop until a matching access token request
// is observed.
void WaitForAccessTokenRequestIfNecessary(
- base::Optional<CoreAccountId> account_id);
+ absl::optional<CoreAccountId> account_id);
// Returns the FakeProfileOAuth2TokenService owned by IdentityManager.
FakeProfileOAuth2TokenService* fake_token_service();
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 5562e06d554..81c68a3fcca 100644
--- a/chromium/components/signin/public/identity_manager/identity_test_utils.cc
+++ b/chromium/components/signin/public/identity_manager/identity_test_utils.cc
@@ -16,7 +16,6 @@
#include "components/signin/internal/identity_manager/profile_oauth2_token_service.h"
#include "components/signin/internal/identity_manager/profile_oauth2_token_service_delegate.h"
#include "components/signin/public/base/list_accounts_test_utils.h"
-#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/primary_account_mutator.h"
#include "components/signin/public/identity_manager/test_identity_manager_observer.h"
@@ -132,26 +131,9 @@ void WaitForRefreshTokensLoaded(IdentityManager* identity_manager) {
}
CoreAccountInfo SetPrimaryAccount(IdentityManager* identity_manager,
- const std::string& email) {
- DCHECK(!identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
- PrimaryAccountManager* primary_account_manager =
- identity_manager->GetPrimaryAccountManager();
- DCHECK(!primary_account_manager->HasPrimaryAccount(ConsentLevel::kSync));
-
- AccountInfo account_info =
- EnsureAccountExists(identity_manager->GetAccountTrackerService(), email);
- DCHECK(!account_info.gaia.empty());
-
- primary_account_manager->SetSyncPrimaryAccountInfo(account_info);
-
- DCHECK(primary_account_manager->HasPrimaryAccount(ConsentLevel::kSync));
- DCHECK(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
- return identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync);
-}
-
-CoreAccountInfo SetUnconsentedPrimaryAccount(IdentityManager* identity_manager,
- const std::string& email) {
- DCHECK(!identity_manager->HasPrimaryAccount(ConsentLevel::kSignin));
+ const std::string& email,
+ ConsentLevel consent_level) {
+ DCHECK(!identity_manager->HasPrimaryAccount(consent_level));
AccountInfo account_info =
EnsureAccountExists(identity_manager->GetAccountTrackerService(), email);
@@ -159,48 +141,54 @@ CoreAccountInfo SetUnconsentedPrimaryAccount(IdentityManager* identity_manager,
PrimaryAccountManager* primary_account_manager =
identity_manager->GetPrimaryAccountManager();
- primary_account_manager->SetUnconsentedPrimaryAccountInfo(account_info);
-
- DCHECK(identity_manager->HasPrimaryAccount(ConsentLevel::kSignin));
- DCHECK_EQ(
- account_info.gaia,
- identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin)
- .gaia);
- return identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin);
+ switch (consent_level) {
+ case ConsentLevel::kSync:
+ primary_account_manager->SetSyncPrimaryAccountInfo(account_info);
+ break;
+ case ConsentLevel::kSignin:
+ primary_account_manager->SetUnconsentedPrimaryAccountInfo(account_info);
+ }
+
+ DCHECK(identity_manager->HasPrimaryAccount(consent_level));
+ DCHECK_EQ(account_info.gaia,
+ identity_manager->GetPrimaryAccountInfo(consent_level).gaia);
+ return identity_manager->GetPrimaryAccountInfo(consent_level);
}
void SetRefreshTokenForPrimaryAccount(IdentityManager* identity_manager,
const std::string& token_value) {
- DCHECK(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
+ DCHECK(identity_manager->HasPrimaryAccount(ConsentLevel::kSync));
CoreAccountId account_id =
- identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSync);
+ identity_manager->GetPrimaryAccountId(ConsentLevel::kSync);
SetRefreshTokenForAccount(identity_manager, account_id, token_value);
}
void SetInvalidRefreshTokenForPrimaryAccount(
IdentityManager* identity_manager) {
- DCHECK(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
+ DCHECK(identity_manager->HasPrimaryAccount(ConsentLevel::kSync));
CoreAccountId account_id =
- identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSync);
+ identity_manager->GetPrimaryAccountId(ConsentLevel::kSync);
SetInvalidRefreshTokenForAccount(identity_manager, account_id);
}
void RemoveRefreshTokenForPrimaryAccount(IdentityManager* identity_manager) {
- if (!identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync))
+ if (!identity_manager->HasPrimaryAccount(ConsentLevel::kSync))
return;
CoreAccountId account_id =
- identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSync);
+ identity_manager->GetPrimaryAccountId(ConsentLevel::kSync);
RemoveRefreshTokenForAccount(identity_manager, account_id);
}
AccountInfo MakePrimaryAccountAvailable(IdentityManager* identity_manager,
- const std::string& email) {
- CoreAccountInfo account_info = SetPrimaryAccount(identity_manager, email);
+ const std::string& email,
+ ConsentLevel consent_level) {
+ CoreAccountInfo account_info =
+ SetPrimaryAccount(identity_manager, email, consent_level);
SetRefreshTokenForPrimaryAccount(identity_manager);
- base::Optional<AccountInfo> primary_account_info =
+ absl::optional<AccountInfo> primary_account_info =
identity_manager
->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
account_info.account_id);
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 619d83be4f0..40dc2edc7e6 100644
--- a/chromium/components/signin/public/identity_manager/identity_test_utils.h
+++ b/chromium/components/signin/public/identity_manager/identity_test_utils.h
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "build/build_config.h"
#include "components/signin/public/identity_manager/account_info.h"
+#include "components/signin/public/identity_manager/consent_level.h"
namespace network {
class TestURLLoaderFactory;
@@ -39,18 +40,15 @@ class IdentityManager;
void WaitForRefreshTokensLoaded(IdentityManager* identity_manager);
// Sets the primary account (which must not already be set) to the given email
-// address, generating a GAIA ID that corresponds uniquely to that email
-// address. On non-ChromeOS, results in the firing of the IdentityManager and
-// PrimaryAccountManager callbacks for signin success. Blocks until the primary
-// account is set. Returns the CoreAccountInfo of the newly-set account.
+// address with corresponding consent level, generating a GAIA ID that
+// corresponds uniquely to that email address. On non-ChromeOS, results in the
+// firing of the IdentityManager and PrimaryAccountManager callbacks for signin
+// success. Blocks until the primary account is set. Returns the CoreAccountInfo
+// of the newly-set account.
// NOTE: See disclaimer at top of file re: direct usage.
CoreAccountInfo SetPrimaryAccount(IdentityManager* identity_manager,
- const std::string& email);
-
-// As above, but adds an "unconsented" primary account. See ./README.md for
-// the distinction between primary and unconsented primary accounts.
-CoreAccountInfo SetUnconsentedPrimaryAccount(IdentityManager* identity_manager,
- const std::string& email);
+ const std::string& email,
+ ConsentLevel consent_level);
// Sets a refresh token for the primary account (which must already be set).
// Blocks until the refresh token is set. If |token_value| is empty a default
@@ -78,7 +76,8 @@ void RemoveRefreshTokenForPrimaryAccount(IdentityManager* identity_manager);
// newly-available account.
// NOTE: See disclaimer at top of file re: direct usage.
AccountInfo MakePrimaryAccountAvailable(IdentityManager* identity_manager,
- const std::string& email);
+ const std::string& email,
+ ConsentLevel consent_level);
// Revokes sync consent from the primary account: the primary account is left
// at ConsentLevel::kSignin.
diff --git a/chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h b/chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h
index 975eccf41a5..3af5f868746 100644
--- a/chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h
+++ b/chromium/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_OBJC_IDENTITY_MANAGER_OBSERVER_BRIDGE_H_
#import <Foundation/Foundation.h>
-#include <vector>
#include "components/signin/public/identity_manager/identity_manager.h"
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 0675918925b..f05f22c7a9a 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
@@ -166,7 +166,7 @@ class PrimaryAccountAccessTokenFetcher : public IdentityManager::Observer {
bool access_token_request_retried() { return access_token_retried_; }
private:
- // Returns the primary account ID. If consent is |kNotRequired| this may be
+ // Returns the primary account ID. If consent is |kSignin| this may be
// the "unconsented" primary account ID.
CoreAccountId GetAccountId() const;
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 9695b5993b8..604daa2ab88 100644
--- a/chromium/components/signin/public/identity_manager/primary_account_mutator.h
+++ b/chromium/components/signin/public/identity_manager/primary_account_mutator.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MUTATOR_H_
#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_MUTATOR_H_
-#include <string>
-
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -18,6 +16,7 @@ enum class SignoutDelete;
struct CoreAccountId;
namespace signin {
+enum class ConsentLevel;
// PrimaryAccountMutator is the interface to set and clear the primary account
// (see IdentityManager for more information).
@@ -40,6 +39,7 @@ class PrimaryAccountMutator {
PrimaryAccountMutator const& operator=(const PrimaryAccountMutator& other) =
delete;
+ // For ConsentLevel::kSync -
// Marks the account with |account_id| as the primary account, and returns
// whether the operation succeeded or not. To succeed, this requires that:
// - the account is known by the IdentityManager.
@@ -49,14 +49,14 @@ class PrimaryAccountMutator {
// - there is not already a primary account set.
// TODO(https://crbug.com/983124): Investigate adding all the extra
// requirements on ChromeOS as well.
- virtual bool SetPrimaryAccount(const CoreAccountId& account_id) = 0;
-
+ //
+ // For ConsentLevel::kSignin -
// Sets the account with |account_id| as the unconsented primary account
// (i.e. without implying browser sync consent). Requires that the account
// is known by the IdentityManager. See README.md for details on the meaning
- // of "unconsented".
- virtual void SetUnconsentedPrimaryAccount(
- const CoreAccountId& account_id) = 0;
+ // of "unconsented". Returns whether the operation succeeded or not.
+ virtual bool SetPrimaryAccount(const CoreAccountId& account_id,
+ ConsentLevel consent_level) = 0;
// Revokes sync consent from the primary account. We distinguish the following
// cases:
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 d77e1876dc3..68288e3474b 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
@@ -127,8 +127,8 @@ void RunRevokeConsentTest(
identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
AccountInfo account_info =
environment.MakeAccountAvailable(kPrimaryAccountEmail);
- EXPECT_TRUE(
- primary_account_mutator->SetPrimaryAccount(account_info.account_id));
+ EXPECT_TRUE(primary_account_mutator->SetPrimaryAccount(
+ account_info.account_id, signin::ConsentLevel::kSync));
EXPECT_TRUE(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
EXPECT_TRUE(identity_manager->HasPrimaryAccountWithRefreshToken(
signin::ConsentLevel::kSync));
@@ -265,8 +265,8 @@ TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount) {
EXPECT_FALSE(environment.identity_manager()->HasPrimaryAccount(
signin::ConsentLevel::kSync));
- EXPECT_TRUE(
- primary_account_mutator->SetPrimaryAccount(account_info.account_id));
+ EXPECT_TRUE(primary_account_mutator->SetPrimaryAccount(
+ account_info.account_id, signin::ConsentLevel::kSync));
EXPECT_TRUE(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
EXPECT_EQ(identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSync),
@@ -297,7 +297,7 @@ TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_NoAccount) {
EXPECT_FALSE(
identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount(
- CoreAccountId(kUnknownAccountId)));
+ CoreAccountId(kUnknownAccountId), signin::ConsentLevel::kSync));
}
// Checks that setting the primary account fails if the account is unknown.
@@ -320,7 +320,7 @@ TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_UnknownAccount) {
EXPECT_FALSE(
identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount(
- CoreAccountId(kUnknownAccountId)));
+ CoreAccountId(kUnknownAccountId), signin::ConsentLevel::kSync));
}
// Checks that trying to set the primary account fails when there is already a
@@ -346,11 +346,11 @@ TEST_F(PrimaryAccountMutatorTest, SetPrimaryAccount_AlreadyHasPrimaryAccount) {
EXPECT_FALSE(
identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
EXPECT_TRUE(primary_account_mutator->SetPrimaryAccount(
- primary_account_info.account_id));
+ primary_account_info.account_id, signin::ConsentLevel::kSync));
EXPECT_TRUE(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount(
- another_account_info.account_id));
+ another_account_info.account_id, signin::ConsentLevel::kSync));
EXPECT_EQ(identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSync),
primary_account_info.account_id);
@@ -384,7 +384,7 @@ TEST_F(PrimaryAccountMutatorTest,
EXPECT_FALSE(
identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync));
EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount(
- primary_account_info.account_id));
+ primary_account_info.account_id, signin::ConsentLevel::kSync));
}
// End of tests of preconditions not being satisfied causing the setting of
diff --git a/chromium/components/signin/public/webdata/token_web_data.cc b/chromium/components/signin/public/webdata/token_web_data.cc
index 9d6077da0ab..a213d159f7c 100644
--- a/chromium/components/signin/public/webdata/token_web_data.cc
+++ b/chromium/components/signin/public/webdata/token_web_data.cc
@@ -13,7 +13,7 @@
#include "components/signin/public/webdata/token_service_table.h"
#include "components/webdata/common/web_database_service.h"
-using base::Bind;
+using base::BindOnce;
using base::Time;
class TokenWebDataBackend
@@ -78,27 +78,28 @@ TokenWebData::TokenWebData(
void TokenWebData::SetTokenForService(const std::string& service,
const std::string& token) {
- wdbs_->ScheduleDBTask(
- FROM_HERE, Bind(&TokenWebDataBackend::SetTokenForService, token_backend_,
- service, token));
+ wdbs_->ScheduleDBTask(FROM_HERE,
+ BindOnce(&TokenWebDataBackend::SetTokenForService,
+ token_backend_, service, token));
}
void TokenWebData::RemoveAllTokens() {
wdbs_->ScheduleDBTask(
- FROM_HERE, Bind(&TokenWebDataBackend::RemoveAllTokens, token_backend_));
+ FROM_HERE,
+ BindOnce(&TokenWebDataBackend::RemoveAllTokens, token_backend_));
}
void TokenWebData::RemoveTokenForService(const std::string& service) {
wdbs_->ScheduleDBTask(FROM_HERE,
- Bind(&TokenWebDataBackend::RemoveTokenForService,
- token_backend_, service));
+ BindOnce(&TokenWebDataBackend::RemoveTokenForService,
+ token_backend_, service));
}
// Null on failure. Success is WDResult<std::string>
WebDataServiceBase::Handle TokenWebData::GetAllTokens(
WebDataServiceConsumer* consumer) {
return wdbs_->ScheduleDBTaskWithResult(
- FROM_HERE, Bind(&TokenWebDataBackend::GetAllTokens, token_backend_),
+ FROM_HERE, BindOnce(&TokenWebDataBackend::GetAllTokens, token_backend_),
consumer);
}
diff --git a/chromium/components/signin/public/webdata/token_web_data.h b/chromium/components/signin/public/webdata/token_web_data.h
index 680b904ed7c..fdefff11e66 100644
--- a/chromium/components/signin/public/webdata/token_web_data.h
+++ b/chromium/components/signin/public/webdata/token_web_data.h
@@ -13,8 +13,6 @@
#include <string>
#include <vector>
-#include "base/callback_forward.h"
-#include "base/files/file_path.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/components/site_isolation/BUILD.gn b/chromium/components/site_isolation/BUILD.gn
index ee7127a3ab2..464d6840d96 100644
--- a/chromium/components/site_isolation/BUILD.gn
+++ b/chromium/components/site_isolation/BUILD.gn
@@ -49,6 +49,7 @@ source_set("site_isolation") {
deps = [
":buildflags",
"//base",
+ "//base/util/values:values_util",
"//components/prefs",
"//components/user_prefs",
"//content/public/browser",
diff --git a/chromium/components/site_isolation/features.cc b/chromium/components/site_isolation/features.cc
index 7d180987b95..022480ae326 100644
--- a/chromium/components/site_isolation/features.cc
+++ b/chromium/components/site_isolation/features.cc
@@ -26,6 +26,20 @@ const base::Feature kSiteIsolationForPasswordSites {
#endif
};
+// Controls a mode for dynamically process-isolating sites where the user has
+// logged in via OAuth. These sites are determined by runtime heuristics.
+//
+// This is intended to be used primarily when full site isolation is turned
+// off. To check whether this mode is enabled, use
+// SiteIsolationPolicy::IsIsolationForOAuthSitesEnabled() rather than
+// checking the feature directly, since that decision is influenced by other
+// factors as well.
+//
+// This feature does not affect Android Webview, which does not include this
+// code.
+const base::Feature kSiteIsolationForOAuthSites{
+ "SiteIsolationForOAuthSites", base::FEATURE_DISABLED_BY_DEFAULT};
+
// kSitePerProcessOnlyForHighMemoryClients is checked before kSitePerProcess,
// and (if enabled) can restrict if kSitePerProcess feature is checked at all -
// no check will be made on devices with low memory (these devices will have no
diff --git a/chromium/components/site_isolation/features.h b/chromium/components/site_isolation/features.h
index 4fb00df2546..5c75cf40aca 100644
--- a/chromium/components/site_isolation/features.h
+++ b/chromium/components/site_isolation/features.h
@@ -11,6 +11,7 @@ namespace site_isolation {
namespace features {
extern const base::Feature kSiteIsolationForPasswordSites;
+extern const base::Feature kSiteIsolationForOAuthSites;
extern const base::Feature kSitePerProcessOnlyForHighMemoryClients;
extern const char kSitePerProcessOnlyForHighMemoryClientsParamName[];
diff --git a/chromium/components/site_isolation/pref_names.cc b/chromium/components/site_isolation/pref_names.cc
index 403cf018f8e..4bd35dd47b1 100644
--- a/chromium/components/site_isolation/pref_names.cc
+++ b/chromium/components/site_isolation/pref_names.cc
@@ -8,10 +8,20 @@ namespace site_isolation {
namespace prefs {
// A list of origins that were heuristically determined to need process
-// isolation. For example, an origin may be placed on this list in response to
-// the user typing a password on it.
+// isolation due to an action triggered by the user. For example, an origin may
+// be placed on this list in response to the user typing a password on it.
const char kUserTriggeredIsolatedOrigins[] =
"site_isolation.user_triggered_isolated_origins";
+// A list of origins that were determined to need process isolation based on
+// heuristics triggered directly by web sites. For example, an origin may be
+// placed on this list in response to serving Cross-Origin-Opener-Policy
+// headers. Unlike the user-triggered list above, web-triggered isolated
+// origins are subject to stricter size and eviction policies, to guard against
+// too many sites triggering isolation and to eventually stop isolation if web
+// sites stop serving headers that triggered it.
+const char kWebTriggeredIsolatedOrigins[] =
+ "site_isolation.web_triggered_isolated_origins";
+
} // namespace prefs
} // namespace site_isolation
diff --git a/chromium/components/site_isolation/pref_names.h b/chromium/components/site_isolation/pref_names.h
index ffdf32f2e1e..c3909459865 100644
--- a/chromium/components/site_isolation/pref_names.h
+++ b/chromium/components/site_isolation/pref_names.h
@@ -9,8 +9,9 @@ namespace site_isolation {
namespace prefs {
extern const char kUserTriggeredIsolatedOrigins[];
+extern const char kWebTriggeredIsolatedOrigins[];
} // namespace prefs
} // namespace site_isolation
-#endif // COMPONENTS_SITE_ISOLATION_PREF_NAMES_H
+#endif // COMPONENTS_SITE_ISOLATION_PREF_NAMES_H_
diff --git a/chromium/components/site_isolation/site_isolation_policy.cc b/chromium/components/site_isolation/site_isolation_policy.cc
index 2c619285588..4f2bd1ebfe5 100644
--- a/chromium/components/site_isolation/site_isolation_policy.cc
+++ b/chromium/components/site_isolation/site_isolation_policy.cc
@@ -5,19 +5,29 @@
#include "components/site_isolation/site_isolation_policy.h"
#include "base/metrics/field_trial_params.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
#include "base/system/sys_info.h"
+#include "base/util/values/values_util.h"
#include "build/build_config.h"
#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
#include "components/site_isolation/features.h"
#include "components/site_isolation/pref_names.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/browser_context.h"
-#include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/site_instance.h"
#include "content/public/browser/site_isolation_policy.h"
+#include "content/public/common/content_features.h"
namespace site_isolation {
+namespace {
+
+using IsolatedOriginSource =
+ content::ChildProcessSecurityPolicy::IsolatedOriginSource;
+
+} // namespace
+
// static
bool SiteIsolationPolicy::IsIsolationForPasswordSitesEnabled() {
// If the user has explicitly enabled site isolation for password sites from
@@ -47,6 +57,32 @@ bool SiteIsolationPolicy::IsIsolationForPasswordSitesEnabled() {
}
// static
+bool SiteIsolationPolicy::IsIsolationForOAuthSitesEnabled() {
+ // If the user has explicitly enabled site isolation for OAuth sites from the
+ // command line, honor this regardless of policies that may disable site
+ // isolation.
+ if (base::FeatureList::GetInstance()->IsFeatureOverriddenFromCommandLine(
+ features::kSiteIsolationForOAuthSites.name,
+ base::FeatureList::OVERRIDE_ENABLE_FEATURE)) {
+ return true;
+ }
+
+ // Don't isolate anything when site isolation is turned off by the user or
+ // policy. This includes things like the switches::kDisableSiteIsolation
+ // command-line switch, the corresponding "Disable site isolation" entry in
+ // chrome://flags, enterprise policy controlled via
+ // switches::kDisableSiteIsolationForPolicy, and memory threshold checks in
+ // ShouldDisableSiteIsolationDueToMemoryThreshold().
+ if (!content::SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled())
+ return false;
+
+ // The feature needs to be checked last, because checking the feature
+ // activates the field trial and assigns the client either to a control or an
+ // experiment group - such assignment should be final.
+ return base::FeatureList::IsEnabled(features::kSiteIsolationForOAuthSites);
+}
+
+// static
bool SiteIsolationPolicy::IsEnterprisePolicyApplicable() {
#if defined(OS_ANDROID)
// https://crbug.com/844118: Limiting policy to devices with > 1GB RAM.
@@ -103,31 +139,187 @@ bool SiteIsolationPolicy::ShouldDisableSiteIsolationDueToMemoryThreshold() {
}
// static
+void SiteIsolationPolicy::PersistIsolatedOrigin(
+ content::BrowserContext* context,
+ const url::Origin& origin,
+ IsolatedOriginSource source) {
+ DCHECK(context);
+ DCHECK(!context->IsOffTheRecord());
+ DCHECK(!origin.opaque());
+
+ // This function currently supports two sources for persistence, for
+ // user-triggered and web-triggered isolated origins.
+ if (source == IsolatedOriginSource::USER_TRIGGERED) {
+ PersistUserTriggeredIsolatedOrigin(context, origin);
+ } else if (source == IsolatedOriginSource::WEB_TRIGGERED) {
+ PersistWebTriggeredIsolatedOrigin(context, origin);
+ } else {
+ NOTREACHED();
+ }
+}
+
+// static
+void SiteIsolationPolicy::PersistUserTriggeredIsolatedOrigin(
+ content::BrowserContext* context,
+ const url::Origin& origin) {
+ // User-triggered isolated origins are currently stored in a simple list of
+ // unlimited size.
+ // TODO(alexmos): Cap the maximum number of entries and evict older entries.
+ // See https://crbug.com/1172407.
+ ListPrefUpdate update(user_prefs::UserPrefs::Get(context),
+ site_isolation::prefs::kUserTriggeredIsolatedOrigins);
+ base::ListValue* list = update.Get();
+ base::Value value(origin.Serialize());
+ if (!base::Contains(list->GetList(), value))
+ list->Append(std::move(value));
+}
+
+// static
+void SiteIsolationPolicy::PersistWebTriggeredIsolatedOrigin(
+ content::BrowserContext* context,
+ const url::Origin& origin) {
+ // Web-triggered isolated origins are stored in a dictionary of (origin,
+ // timestamp) pairs. The number of entries is capped by a field trial param,
+ // and older entries are evicted.
+ DictionaryPrefUpdate update(
+ user_prefs::UserPrefs::Get(context),
+ site_isolation::prefs::kWebTriggeredIsolatedOrigins);
+ base::DictionaryValue* dict = update.Get();
+
+ // Add the origin. If it already exists, this will just update the
+ // timestamp.
+ dict->SetKey(origin.Serialize(), util::TimeToValue(base::Time::Now()));
+
+ // Check whether the maximum number of stored sites was exceeded and remove
+ // one or more entries, starting with the oldest timestamp. Note that more
+ // than one entry may need to be removed, since the maximum number of entries
+ // could change over time (via a change in the field trial param).
+ size_t max_size =
+ ::features::kSiteIsolationForCrossOriginOpenerPolicyMaxSitesParam.Get();
+ while (dict->DictSize() > max_size) {
+ auto items = dict->DictItems();
+ auto oldest_site_time_pair = std::min_element(
+ items.begin(), items.end(), [](auto pair_a, auto pair_b) {
+ absl::optional<base::Time> time_a = util::ValueToTime(pair_a.second);
+ absl::optional<base::Time> time_b = util::ValueToTime(pair_b.second);
+ // has_value() should always be true unless the prefs were corrupted.
+ // In that case, prioritize the corrupted entry for removal.
+ return (time_a.has_value() ? time_a.value() : base::Time::Min()) <
+ (time_b.has_value() ? time_b.value() : base::Time::Min());
+ });
+ dict->RemoveKey(oldest_site_time_pair->first);
+ }
+}
+
+// static
void SiteIsolationPolicy::ApplyPersistedIsolatedOrigins(
content::BrowserContext* browser_context) {
+ auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
+
// If the user turned off password-triggered isolation, don't apply any
// stored isolated origins, but also don't clear them from prefs, so that
// they can be used if password-triggered isolation is re-enabled later.
- if (!IsIsolationForPasswordSitesEnabled())
- return;
+ if (IsIsolationForPasswordSitesEnabled()) {
+ std::vector<url::Origin> origins;
+ for (const auto& value : user_prefs::UserPrefs::Get(browser_context)
+ ->GetList(prefs::kUserTriggeredIsolatedOrigins)
+ ->GetList()) {
+ origins.push_back(url::Origin::Create(GURL(value.GetString())));
+ }
+
+ if (!origins.empty()) {
+ policy->AddFutureIsolatedOrigins(
+ origins, IsolatedOriginSource::USER_TRIGGERED, browser_context);
+ }
- std::vector<url::Origin> origins;
- for (const auto& value :
- *user_prefs::UserPrefs::Get(browser_context)
- ->GetList(prefs::kUserTriggeredIsolatedOrigins)) {
- origins.push_back(url::Origin::Create(GURL(value.GetString())));
+ base::UmaHistogramCounts1000(
+ "SiteIsolation.SavedUserTriggeredIsolatedOrigins.Size", origins.size());
}
- if (!origins.empty()) {
- auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
- using IsolatedOriginSource =
- content::ChildProcessSecurityPolicy::IsolatedOriginSource;
- policy->AddFutureIsolatedOrigins(
- origins, IsolatedOriginSource::USER_TRIGGERED, browser_context);
+ // Similarly, load saved web-triggered isolated origins only if isolation of
+ // COOP sites (currently the only source of these origins) is enabled with
+ // persistence, but don't remove them from prefs otherwise.
+ if (content::SiteIsolationPolicy::ShouldPersistIsolatedCOOPSites()) {
+ std::vector<url::Origin> origins;
+ std::vector<std::string> expired_entries;
+
+ auto* pref_service = user_prefs::UserPrefs::Get(browser_context);
+ auto* dict =
+ pref_service->GetDictionary(prefs::kWebTriggeredIsolatedOrigins);
+ if (dict) {
+ for (const auto& site_time_pair : dict->DictItems()) {
+ // Only isolate origins that haven't expired.
+ absl::optional<base::Time> timestamp =
+ util::ValueToTime(site_time_pair.second);
+ base::TimeDelta expiration_timeout =
+ ::features::
+ kSiteIsolationForCrossOriginOpenerPolicyExpirationTimeoutParam
+ .Get();
+ if (timestamp.has_value() &&
+ base::Time::Now() - timestamp.value() <= expiration_timeout) {
+ origins.push_back(url::Origin::Create(GURL(site_time_pair.first)));
+ } else {
+ expired_entries.push_back(site_time_pair.first);
+ }
+ }
+ // Remove expired entries (as well as those with an invalid timestamp).
+ if (!expired_entries.empty()) {
+ DictionaryPrefUpdate update(pref_service,
+ prefs::kWebTriggeredIsolatedOrigins);
+ base::DictionaryValue* updated_dict = update.Get();
+ for (const auto& entry : expired_entries)
+ updated_dict->RemoveKey(entry);
+ }
+ }
+
+ if (!origins.empty()) {
+ policy->AddFutureIsolatedOrigins(
+ origins, IsolatedOriginSource::WEB_TRIGGERED, browser_context);
+ }
+
+ base::UmaHistogramCounts100(
+ "SiteIsolation.SavedWebTriggeredIsolatedOrigins.Size", origins.size());
}
+}
+
+// static
+void SiteIsolationPolicy::IsolateStoredOAuthSites(
+ content::BrowserContext* browser_context,
+ const std::vector<url::Origin>& logged_in_sites) {
+ // Only isolate logged-in sites if the corresponding feature is enabled and
+ // other isolation requirements (such as memory threshold) are satisfied.
+ // Note that we don't clear logged-in sites from prefs if site isolation is
+ // disabled so that they can be used if isolation is re-enabled later.
+ if (!IsIsolationForOAuthSitesEnabled())
+ return;
+
+ auto* policy = content::ChildProcessSecurityPolicy::GetInstance();
+ policy->AddFutureIsolatedOrigins(
+ logged_in_sites,
+ content::ChildProcessSecurityPolicy::IsolatedOriginSource::USER_TRIGGERED,
+ browser_context);
+
+ // Note that the max count matches
+ // login_detection::GetOauthLoggedInSitesMaxSize().
+ base::UmaHistogramCounts100("SiteIsolation.SavedOAuthSites.Size",
+ logged_in_sites.size());
+}
+
+// static
+void SiteIsolationPolicy::IsolateNewOAuthURL(
+ content::BrowserContext* browser_context,
+ const GURL& signed_in_url) {
+ if (!IsIsolationForOAuthSitesEnabled())
+ return;
+
+ // OAuth information is currently persisted and restored by other layers. See
+ // login_detection::prefs::SaveSiteToOAuthSignedInList().
+ constexpr bool kShouldPersist = false;
- UMA_HISTOGRAM_COUNTS_1000(
- "SiteIsolation.SavedUserTriggeredIsolatedOrigins.Size", origins.size());
+ content::SiteInstance::StartIsolatingSite(
+ browser_context, signed_in_url,
+ content::ChildProcessSecurityPolicy::IsolatedOriginSource::USER_TRIGGERED,
+ kShouldPersist);
}
// static
diff --git a/chromium/components/site_isolation/site_isolation_policy.h b/chromium/components/site_isolation/site_isolation_policy.h
index 2a56331cb09..55e13128c12 100644
--- a/chromium/components/site_isolation/site_isolation_policy.h
+++ b/chromium/components/site_isolation/site_isolation_policy.h
@@ -5,12 +5,21 @@
#ifndef COMPONENTS_SITE_ISOLATION_SITE_ISOLATION_POLICY_H_
#define COMPONENTS_SITE_ISOLATION_SITE_ISOLATION_POLICY_H_
+#include <vector>
+
#include "base/macros.h"
+#include "content/public/browser/child_process_security_policy.h"
+
+class GURL;
namespace content {
class BrowserContext;
}
+namespace url {
+class Origin;
+}
+
namespace site_isolation {
// A centralized place for making policy decisions about site isolation modes
@@ -24,18 +33,46 @@ class SiteIsolationPolicy {
// enter passwords is enabled.
static bool IsIsolationForPasswordSitesEnabled();
+ // Returns true if the site isolation mode for isolating sites where users
+ // log in via OAuth, as determined by runtime heuristics.
+ static bool IsIsolationForOAuthSitesEnabled();
+
// Returns true if Site Isolation related enterprise policies should take
// effect (e.g. such policies might not be applicable to low-end Android
// devices because of 1) performance impact and 2) infeasibility of
// Spectre-like attacks on such devices).
static bool IsEnterprisePolicyApplicable();
+ // Saves a new dynamic isolated origin to user prefs associated with
+ // `context` so that it can be persisted across restarts. `source`
+ // specifies why the isolated origin was added; different sources may have
+ // different persistence policies.
+ static void PersistIsolatedOrigin(
+ content::BrowserContext* context,
+ const url::Origin& origin,
+ content::ChildProcessSecurityPolicy::IsolatedOriginSource source);
+
// Reads and applies any isolated origins stored in user prefs associated with
// |browser_context|. This is expected to be called on startup after user
// prefs have been loaded.
static void ApplyPersistedIsolatedOrigins(
content::BrowserContext* browser_context);
+ // Helper to register all passed-in `logged_in_sites` as isolated sites in
+ // the provided `browser_context`. Should be called on startup before any
+ // navigations in `browser_context`.
+ static void IsolateStoredOAuthSites(
+ content::BrowserContext* browser_context,
+ const std::vector<url::Origin>& logged_in_sites);
+
+ // Called when runtime heuristics have determined a user logging in via
+ // OAuth on `signed_in_url`, so that site isolation can be applied to the
+ // corresponding site (i.e., scheme + eTLD+1). Used only when site isolation
+ // for OAuth sites is enabled (see IsIsolationForOAuthSitesEnabled() above),
+ // which is typically on Android.
+ static void IsolateNewOAuthURL(content::BrowserContext* browser_context,
+ const GURL& signed_in_url);
+
// Determines whether Site Isolation should be disabled because the device
// does not have the minimum required amount of memory.
//
@@ -50,6 +87,14 @@ class SiteIsolationPolicy {
static bool ShouldPdfCompositorBeEnabledForOopifs();
private:
+ // Helpers for implementing PersistIsolatedOrigin().
+ static void PersistUserTriggeredIsolatedOrigin(
+ content::BrowserContext* context,
+ const url::Origin& origin);
+ static void PersistWebTriggeredIsolatedOrigin(
+ content::BrowserContext* context,
+ const url::Origin& origin);
+
DISALLOW_IMPLICIT_CONSTRUCTORS(SiteIsolationPolicy);
};
diff --git a/chromium/components/site_isolation/site_isolation_policy_unittest.cc b/chromium/components/site_isolation/site_isolation_policy_unittest.cc
index 99665ffc0b7..a9f9bf66c37 100644
--- a/chromium/components/site_isolation/site_isolation_policy_unittest.cc
+++ b/chromium/components/site_isolation/site_isolation_policy_unittest.cc
@@ -10,6 +10,7 @@
#include "base/test/mock_entropy_provider.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_field_trial_list_resetter.h"
+#include "base/util/values/values_util.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/prefs/pref_registry_simple.h"
@@ -38,6 +39,9 @@
namespace site_isolation {
namespace {
+using IsolatedOriginSource =
+ content::ChildProcessSecurityPolicy::IsolatedOriginSource;
+
// Some command-line switches override field trials - the tests need to be
// skipped in this case.
bool ShouldSkipBecauseOfConflictingCommandLineSwitches() {
@@ -99,8 +103,13 @@ class BaseSiteIsolationTest : public testing::Test {
class SiteIsolationPolicyTest : public BaseSiteIsolationTest {
public:
- SiteIsolationPolicyTest() {
+ explicit SiteIsolationPolicyTest(
+ content::BrowserTaskEnvironment::TimeSource time_source =
+ content::BrowserTaskEnvironment::TimeSource::DEFAULT)
+ : task_environment_(time_source) {
prefs_.registry()->RegisterListPref(prefs::kUserTriggeredIsolatedOrigins);
+ prefs_.registry()->RegisterDictionaryPref(
+ prefs::kWebTriggeredIsolatedOrigins);
user_prefs::UserPrefs::Set(&browser_context_, &prefs_);
}
@@ -109,6 +118,10 @@ class SiteIsolationPolicyTest : public BaseSiteIsolationTest {
PrefService* prefs() { return &prefs_; }
+ content::BrowserTaskEnvironment* task_environment() {
+ return &task_environment_;
+ }
+
private:
content::BrowserTaskEnvironment task_environment_;
content::TestBrowserContext browser_context_;
@@ -117,6 +130,195 @@ class SiteIsolationPolicyTest : public BaseSiteIsolationTest {
DISALLOW_COPY_AND_ASSIGN(SiteIsolationPolicyTest);
};
+class WebTriggeredIsolatedOriginsPolicyTest : public SiteIsolationPolicyTest {
+ public:
+ explicit WebTriggeredIsolatedOriginsPolicyTest(
+ content::BrowserTaskEnvironment::TimeSource time_source =
+ content::BrowserTaskEnvironment::TimeSource::DEFAULT)
+ : SiteIsolationPolicyTest(time_source) {}
+
+ void PersistOrigin(const std::string& origin) {
+ SiteIsolationPolicy::PersistIsolatedOrigin(
+ browser_context(), url::Origin::Create(GURL(origin)),
+ IsolatedOriginSource::WEB_TRIGGERED);
+ }
+
+ std::vector<std::string> GetStoredOrigins() {
+ std::vector<std::string> origins;
+ auto* dict = user_prefs::UserPrefs::Get(browser_context())
+ ->GetDictionary(prefs::kWebTriggeredIsolatedOrigins);
+ for (auto pair : dict->DictItems())
+ origins.push_back(pair.first);
+ return origins;
+ }
+
+ protected:
+ void SetUp() override {
+ // Set up the COOP isolation feature with persistence enabled and a maximum
+ // of 3 stored sites.
+ base::test::ScopedFeatureList::FeatureAndParams coop_feature = {
+ ::features::kSiteIsolationForCrossOriginOpenerPolicy,
+ {{::features::kSiteIsolationForCrossOriginOpenerPolicyMaxSitesParam
+ .name,
+ base::NumberToString(3)},
+ {::features::kSiteIsolationForCrossOriginOpenerPolicyShouldPersistParam
+ .name,
+ "true"}}};
+
+ // Some machines running this test may be below the default memory
+ // threshold. To ensure that COOP isolation is also enabled on those
+ // machines, set a very low 128MB threshold.
+ base::test::ScopedFeatureList::FeatureAndParams memory_threshold_feature = {
+ site_isolation::features::kSitePerProcessOnlyForHighMemoryClients,
+ {{site_isolation::features::
+ kSitePerProcessOnlyForHighMemoryClientsParamName,
+ "128"}}};
+
+ feature_list_.InitWithFeaturesAndParameters(
+ /* enabled_features = */ {coop_feature, memory_threshold_feature},
+ /* disabled_features = */ {});
+
+ // Disable strict site isolation to observe effects of COOP isolation.
+ SetEnableStrictSiteIsolation(false);
+ SiteIsolationPolicyTest::SetUp();
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebTriggeredIsolatedOriginsPolicyTest);
+};
+
+// Verify that persisting web-triggered isolated origins properly saves the
+// origins to prefs and respects the maximum number of entries (3 in this
+// test).
+TEST_F(WebTriggeredIsolatedOriginsPolicyTest, PersistIsolatedOrigin) {
+ PersistOrigin("https://foo1.com");
+ PersistOrigin("https://foo2.com");
+ PersistOrigin("https://foo3.com");
+
+ EXPECT_THAT(GetStoredOrigins(),
+ testing::UnorderedElementsAre(
+ "https://foo1.com", "https://foo2.com", "https://foo3.com"));
+
+ // Adding foo4.com should evict the oldest entry (foo1.com).
+ PersistOrigin("https://foo4.com");
+ EXPECT_THAT(GetStoredOrigins(),
+ testing::UnorderedElementsAre(
+ "https://foo2.com", "https://foo3.com", "https://foo4.com"));
+
+ // Adding foo5.com and foo6.com should evict the next two oldest entries.
+ PersistOrigin("https://foo5.com");
+ PersistOrigin("https://foo6.com");
+ EXPECT_THAT(GetStoredOrigins(),
+ testing::UnorderedElementsAre(
+ "https://foo4.com", "https://foo5.com", "https://foo6.com"));
+
+ // Updating the timestamp on foo5.com should keep the current three entries.
+ PersistOrigin("https://foo5.com");
+ EXPECT_THAT(GetStoredOrigins(),
+ testing::UnorderedElementsAre(
+ "https://foo4.com", "https://foo5.com", "https://foo6.com"));
+
+ // Adding two new entries should now evict foo4.com and foo6.com, since
+ // foo5.com has a more recent timestamp.
+ PersistOrigin("https://foo7.com");
+ PersistOrigin("https://foo8.com");
+ EXPECT_THAT(GetStoredOrigins(),
+ testing::UnorderedElementsAre(
+ "https://foo5.com", "https://foo7.com", "https://foo8.com"));
+}
+
+// Verify that when origins stored in prefs contain more than the current
+// maximum number of entries, we clean up older entries when adding a new one
+// to go back under the size limit.
+TEST_F(WebTriggeredIsolatedOriginsPolicyTest, UpdatedMaxSize) {
+ // Populate the pref manually with more entries than the 3 allowed by the
+ // field trial param.
+ DictionaryPrefUpdate update(
+ user_prefs::UserPrefs::Get(browser_context()),
+ site_isolation::prefs::kWebTriggeredIsolatedOrigins);
+ base::DictionaryValue* dict = update.Get();
+ dict->SetKey("https://foo1.com", util::TimeToValue(base::Time::Now()));
+ dict->SetKey("https://foo2.com", util::TimeToValue(base::Time::Now()));
+ dict->SetKey("https://foo3.com", util::TimeToValue(base::Time::Now()));
+ dict->SetKey("https://foo4.com", util::TimeToValue(base::Time::Now()));
+ dict->SetKey("https://foo5.com", util::TimeToValue(base::Time::Now()));
+ EXPECT_THAT(GetStoredOrigins(),
+ testing::UnorderedElementsAre(
+ "https://foo1.com", "https://foo2.com", "https://foo3.com",
+ "https://foo4.com", "https://foo5.com"));
+
+ // Now, attempt to save a new origin. This should evict the three oldest
+ // entries to make room for the new origin.
+ PersistOrigin("https://foo6.com");
+ EXPECT_THAT(GetStoredOrigins(),
+ testing::UnorderedElementsAre(
+ "https://foo4.com", "https://foo5.com", "https://foo6.com"));
+}
+
+// WebTriggeredIsolatedOriginsPolicyTest subclass for tests that want to use
+// mock time.
+class WebTriggeredIsolatedOriginsPolicyTestWithMockTime
+ : public WebTriggeredIsolatedOriginsPolicyTest {
+ public:
+ WebTriggeredIsolatedOriginsPolicyTestWithMockTime()
+ : WebTriggeredIsolatedOriginsPolicyTest(
+ content::BrowserTaskEnvironment::TimeSource::MOCK_TIME) {}
+};
+
+// Verify that when origins stored in prefs expire, we don't apply them when
+// loading persisted isolated origins, and we remove them from prefs.
+TEST_F(WebTriggeredIsolatedOriginsPolicyTestWithMockTime, Expiration) {
+ // Running this test with a command-line --site-per-process flag (which might
+ // be the case on some bots) conflicts with the feature configuration in this
+ // test.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess)) {
+ return;
+ }
+
+ EXPECT_TRUE(content::SiteIsolationPolicy::IsSiteIsolationForCOOPEnabled());
+ EXPECT_TRUE(content::SiteIsolationPolicy::ShouldPersistIsolatedCOOPSites());
+
+ // Persist two origins which will eventually expire.
+ PersistOrigin("https://foo1.com");
+ PersistOrigin("https://foo2.com");
+ EXPECT_THAT(GetStoredOrigins(), testing::UnorderedElementsAre(
+ "https://foo1.com", "https://foo2.com"));
+
+ // Fast-forward time so we exceed the default expiration timeout.
+ base::TimeDelta default_timeout =
+ ::features::kSiteIsolationForCrossOriginOpenerPolicyExpirationTimeoutParam
+ .default_value;
+ task_environment()->FastForwardBy(default_timeout +
+ base::TimeDelta::FromDays(1));
+
+ // foo1.com and foo2.com should still be in prefs. (Expired entries are only
+ // removed when we try to load them from prefs.)
+ EXPECT_THAT(GetStoredOrigins(), testing::UnorderedElementsAre(
+ "https://foo1.com", "https://foo2.com"));
+
+ // Persist another origin which should remain below expiration threshold.
+ PersistOrigin("https://foo3.com");
+ EXPECT_THAT(GetStoredOrigins(),
+ testing::UnorderedElementsAre(
+ "https://foo1.com", "https://foo2.com", "https://foo3.com"));
+
+ // Loading persisted isolated origins should only load foo3.com. Also,
+ // it should remove foo1.com and foo2.com from prefs.
+ SiteIsolationPolicy::ApplyPersistedIsolatedOrigins(browser_context());
+
+ auto* cpsp = content::ChildProcessSecurityPolicy::GetInstance();
+ std::vector<url::Origin> isolated_origins = cpsp->GetIsolatedOrigins(
+ IsolatedOriginSource::WEB_TRIGGERED, browser_context());
+ EXPECT_THAT(isolated_origins,
+ testing::UnorderedElementsAre(
+ url::Origin::Create(GURL("https://foo3.com"))));
+ EXPECT_THAT(GetStoredOrigins(),
+ testing::UnorderedElementsAre("https://foo3.com"));
+}
+
// Helper class that enables site isolation for password sites.
class PasswordSiteIsolationPolicyTest : public SiteIsolationPolicyTest {
public:
diff --git a/chromium/components/soda/BUILD.gn b/chromium/components/soda/BUILD.gn
index 161d7a76cc5..b4a8af8cb23 100644
--- a/chromium/components/soda/BUILD.gn
+++ b/chromium/components/soda/BUILD.gn
@@ -2,6 +2,36 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/chromeos/ui_mode.gni")
+
+source_set("soda") {
+ sources = [
+ "soda_installer.cc",
+ "soda_installer.h",
+ ]
+
+ deps = [
+ ":constants",
+ "//base",
+ "//components/live_caption:constants",
+ "//components/prefs",
+ "//media",
+ ]
+
+ if (is_chromeos_ash) {
+ sources += [
+ "soda_installer_impl_chromeos.cc",
+ "soda_installer_impl_chromeos.h",
+ ]
+
+ deps += [
+ "//ash/public/cpp",
+ "//chromeos/dbus/dlcservice",
+ "//ui/base",
+ ]
+ }
+}
+
source_set("constants") {
sources = [
"constants.cc",
@@ -13,6 +43,7 @@ source_set("constants") {
deps = [
"//base",
"//components/component_updater",
+ "//components/crx_file",
"//components/strings/",
]
}
diff --git a/chromium/components/soda/DEPS b/chromium/components/soda/DEPS
index 9ebf19d0e25..2a23cda2f86 100644
--- a/chromium/components/soda/DEPS
+++ b/chromium/components/soda/DEPS
@@ -1,4 +1,11 @@
include_rules = [
+ "+ash/public/cpp",
+ "+chromeos/dbus/dlcservice/dlcservice_client.h",
"+components/component_updater/component_updater_paths.h",
+ "+components/crx_file",
+ "+components/live_caption",
+ "+components/prefs",
"+components/strings/grit/components_strings.h",
+ "+media/base",
+ "+ui/base",
]
diff --git a/chromium/components/soda/OWNERS b/chromium/components/soda/OWNERS
index a8d94654e17..13d5ab6b669 100644
--- a/chromium/components/soda/OWNERS
+++ b/chromium/components/soda/OWNERS
@@ -1,2 +1,2 @@
-
+abigailbklein@google.com
evliu@google.com
diff --git a/chromium/components/soda/constants.cc b/chromium/components/soda/constants.cc
index d40d058e877..89531227f3d 100644
--- a/chromium/components/soda/constants.cc
+++ b/chromium/components/soda/constants.cc
@@ -10,9 +10,10 @@
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/path_service.h"
#include "components/component_updater/component_updater_paths.h"
+#include "components/crx_file/id_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace speech {
@@ -90,7 +91,7 @@ const base::FilePath GetSodaBinaryPath() {
: soda_dir.Append(kSodaBinaryRelativePath);
}
-base::Optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig(
+absl::optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig(
LanguageCode language_code) {
for (const SodaLanguagePackComponentConfig& config :
kLanguageComponentConfigs) {
@@ -99,10 +100,10 @@ base::Optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig(
}
}
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig(
+absl::optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig(
const std::string& language_name) {
for (const SodaLanguagePackComponentConfig& config :
kLanguageComponentConfigs) {
@@ -111,6 +112,33 @@ base::Optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig(
}
}
- return base::nullopt;
+ return absl::nullopt;
}
+
+LanguageCode GetLanguageCodeByComponentId(const std::string& component_id) {
+ for (const SodaLanguagePackComponentConfig& config :
+ kLanguageComponentConfigs) {
+ if (crx_file::id_util::GenerateIdFromHash(config.public_key_sha,
+ sizeof(config.public_key_sha)) ==
+ component_id) {
+ return config.language_code;
+ }
+ }
+
+ return LanguageCode::kNone;
+}
+
+std::string GetLanguageName(LanguageCode language_code) {
+ std::string language_name;
+ if (language_code != speech::LanguageCode::kNone) {
+ absl::optional<speech::SodaLanguagePackComponentConfig> language_config =
+ speech::GetLanguageComponentConfig(language_code);
+ if (language_config.has_value()) {
+ language_name = language_config.value().language_name;
+ }
+ }
+
+ return language_name;
+}
+
} // namespace speech
diff --git a/chromium/components/soda/constants.h b/chromium/components/soda/constants.h
index af0bd9dc71e..6fdfa5afc58 100644
--- a/chromium/components/soda/constants.h
+++ b/chromium/components/soda/constants.h
@@ -8,9 +8,9 @@
#include <string>
#include "base/files/file_path.h"
-#include "base/optional.h"
#include "components/soda/pref_names.h"
#include "components/strings/grit/components_strings.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace speech {
@@ -126,12 +126,16 @@ const base::FilePath GetLatestSodaDirectory();
// installed.
const base::FilePath GetSodaBinaryPath();
-base::Optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig(
+absl::optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig(
LanguageCode language_code);
-base::Optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig(
+absl::optional<SodaLanguagePackComponentConfig> GetLanguageComponentConfig(
const std::string& language_name);
+LanguageCode GetLanguageCodeByComponentId(const std::string& component_id);
+
+std::string GetLanguageName(LanguageCode language_code);
+
} // namespace speech
#endif // COMPONENTS_SODA_CONSTANTS_H_
diff --git a/chromium/components/soda/pref_names.cc b/chromium/components/soda/pref_names.cc
index a007136b48e..7e455cf6ea2 100644
--- a/chromium/components/soda/pref_names.cc
+++ b/chromium/components/soda/pref_names.cc
@@ -38,4 +38,9 @@ const char kSodaFrFrConfigPath[] =
const char kSodaItItConfigPath[] =
"accessibility.captions.soda_it_it_config_path";
+// The list of Speech On-Device API (SODA) language packs installed or
+// registered to be installed.
+const char kSodaRegisteredLanguagePacks[] =
+ "accessibility.captions.soda_registered_language_packs";
+
} // namespace prefs
diff --git a/chromium/components/soda/pref_names.h b/chromium/components/soda/pref_names.h
index 434c026b1eb..bb2445fa6d9 100644
--- a/chromium/components/soda/pref_names.h
+++ b/chromium/components/soda/pref_names.h
@@ -17,6 +17,7 @@ extern const char kSodaEsEsConfigPath[];
extern const char kSodaFrFrConfigPath[];
extern const char kSodaItItConfigPath[];
+extern const char kSodaRegisteredLanguagePacks[];
} // namespace prefs
#endif // COMPONENTS_SODA_PREF_NAMES_H_
diff --git a/chromium/components/soda/soda_installer.cc b/chromium/components/soda/soda_installer.cc
new file mode 100644
index 00000000000..da01a6940cf
--- /dev/null
+++ b/chromium/components/soda/soda_installer.cc
@@ -0,0 +1,156 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/soda/soda_installer.h"
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "ash/public/cpp/ash_pref_names.h"
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#include "base/feature_list.h"
+#include "base/values.h"
+#include "components/live_caption/pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/soda/constants.h"
+#include "components/soda/pref_names.h"
+#include "media/base/media_switches.h"
+
+namespace {
+
+constexpr int kSodaCleanUpDelayInDays = 30;
+
+} // namespace
+
+namespace speech {
+
+SodaInstaller::SodaInstaller() = default;
+
+SodaInstaller::~SodaInstaller() = default;
+
+void SodaInstaller::Init(PrefService* profile_prefs,
+ PrefService* global_prefs) {
+ if (!base::FeatureList::IsEnabled(media::kUseSodaForLiveCaption) ||
+ soda_installer_initialized_) {
+ return;
+ }
+
+ if (IsAnyFeatureUsingSodaEnabled(profile_prefs)) {
+ soda_installer_initialized_ = true;
+ global_prefs->SetTime(prefs::kSodaScheduledDeletionTime, base::Time());
+ speech::SodaInstaller::GetInstance()->InstallSoda(global_prefs);
+ for (const auto& language :
+ global_prefs->GetList(prefs::kSodaRegisteredLanguagePacks)
+ ->GetList()) {
+ speech::SodaInstaller::GetInstance()->InstallLanguage(
+ language.GetString(), global_prefs);
+ }
+ } else {
+ base::Time deletion_time =
+ global_prefs->GetTime(prefs::kSodaScheduledDeletionTime);
+ if (!deletion_time.is_null() && deletion_time < base::Time::Now()) {
+ UninstallSoda(global_prefs);
+ }
+ }
+}
+
+void SodaInstaller::SetUninstallTimer(PrefService* profile_prefs,
+ PrefService* global_prefs) {
+ // Do not schedule uninstallation if any SODA client features are still
+ // enabled.
+ if (IsAnyFeatureUsingSodaEnabled(profile_prefs))
+ return;
+
+ // Schedule deletion.
+ global_prefs->SetTime(
+ prefs::kSodaScheduledDeletionTime,
+ base::Time::Now() + base::TimeDelta::FromDays(kSodaCleanUpDelayInDays));
+}
+
+void SodaInstaller::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void SodaInstaller::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void SodaInstaller::NotifySodaInstalledForTesting() {
+ soda_binary_installed_ = true;
+ language_installed_ = true;
+ NotifyOnSodaInstalled();
+}
+
+void SodaInstaller::RegisterRegisteredLanguagePackPref(
+ PrefRegistrySimple* registry) {
+ // TODO: Default to one of the user's languages.
+ base::Value::ListStorage default_languages;
+ default_languages.push_back(base::Value("en-US"));
+ registry->RegisterListPref(prefs::kSodaRegisteredLanguagePacks,
+ base::Value(std::move(default_languages)));
+}
+
+void SodaInstaller::NotifyOnSodaInstalled() {
+ for (Observer& observer : observers_)
+ observer.OnSodaInstalled();
+}
+
+void SodaInstaller::NotifyOnSodaLanguagePackInstalled(
+ speech::LanguageCode language_code) {
+ if (base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage)) {
+ for (Observer& observer : observers_)
+ observer.OnSodaLanguagePackInstalled(language_code);
+ }
+}
+
+void SodaInstaller::NotifyOnSodaError() {
+ for (Observer& observer : observers_)
+ observer.OnSodaError();
+}
+
+void SodaInstaller::NotifyOnSodaLanguagePackError(
+ speech::LanguageCode language_code) {
+ if (base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage)) {
+ for (Observer& observer : observers_)
+ observer.OnSodaLanguagePackError(language_code);
+ }
+}
+
+void SodaInstaller::NotifyOnSodaProgress(int combined_progress) {
+ for (Observer& observer : observers_)
+ observer.OnSodaProgress(combined_progress);
+}
+
+void SodaInstaller::NotifyOnSodaLanguagePackProgress(
+ int language_progress,
+ LanguageCode language_code) {
+ if (base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage)) {
+ for (Observer& observer : observers_)
+ observer.OnSodaLanguagePackProgress(language_progress, language_code);
+ }
+}
+
+void SodaInstaller::RegisterLanguage(const std::string& language,
+ PrefService* global_prefs) {
+ ListPrefUpdate update(global_prefs, prefs::kSodaRegisteredLanguagePacks);
+ if (!base::Contains(update->GetList(), base::Value(language))) {
+ update->Append(language);
+ }
+}
+
+void SodaInstaller::UnregisterLanguages(PrefService* global_prefs) {
+ ListPrefUpdate update(global_prefs, prefs::kSodaRegisteredLanguagePacks);
+ update->Clear();
+}
+
+bool SodaInstaller::IsAnyFeatureUsingSodaEnabled(PrefService* prefs) {
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ // TODO(crbug.com/1165437): Add Projector feature.
+ return prefs->GetBoolean(prefs::kLiveCaptionEnabled) ||
+ prefs->GetBoolean(ash::prefs::kAccessibilityDictationEnabled);
+#else // !BUILDFLAG(IS_CHROMEOS_ASH)
+ return prefs->GetBoolean(prefs::kLiveCaptionEnabled);
+#endif
+}
+
+} // namespace speech
diff --git a/chromium/components/soda/soda_installer.h b/chromium/components/soda/soda_installer.h
new file mode 100644
index 00000000000..efc790c2e16
--- /dev/null
+++ b/chromium/components/soda/soda_installer.h
@@ -0,0 +1,167 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SODA_SODA_INSTALLER_H_
+#define COMPONENTS_SODA_SODA_INSTALLER_H_
+
+#include "base/files/file_path.h"
+#include "base/observer_list.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/soda/constants.h"
+
+class PrefService;
+
+namespace speech {
+
+// Installer of SODA (Speech On-Device API). This is a singleton because there
+// is only one installation of SODA per device.
+class SodaInstaller {
+ public:
+ // Observer of the SODA (Speech On-Device API) installation.
+ class Observer : public base::CheckedObserver {
+ public:
+ // Called when the SODA binary component and at least one language pack is
+ // installed.
+ virtual void OnSodaInstalled() = 0;
+
+ // Called when a SODA language pack component is installed.
+ virtual void OnSodaLanguagePackInstalled(LanguageCode language_code) = 0;
+
+ // Called if there is an error in the SODA binary or language pack
+ // installation.
+ virtual void OnSodaError() = 0;
+
+ // Called if there is an error in a SODA language pack installation.
+ virtual void OnSodaLanguagePackError(
+ speech::LanguageCode language_code) = 0;
+
+ // Called during the SODA installation. Progress is the weighted average of
+ // the download percentage of the SODA binary and at least one language
+ // pack.
+ virtual void OnSodaProgress(int combined_progress) = 0;
+
+ // Called during the SODA installation. Progress is the download percentage
+ // out of 100.
+ virtual void OnSodaLanguagePackProgress(int language_progress,
+ LanguageCode language_code) = 0;
+ };
+
+ SodaInstaller();
+ virtual ~SodaInstaller();
+ SodaInstaller(const SodaInstaller&) = delete;
+ SodaInstaller& operator=(const SodaInstaller&) = delete;
+
+ // Implemented in the platform-specific subclass to get the SodaInstaller
+ // instance.
+ static SodaInstaller* GetInstance();
+
+ // Registers user preferences related to the Speech On-Device API (SODA)
+ // component.
+ static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+
+ // Initialize SODA if any SODA-utilising feature is enabled. Intended to be
+ // called during embedder startup. Checks whether SODA is due for
+ // uninstallation, and if so, triggers uninstallation.
+ void Init(PrefService* profile_prefs, PrefService* global_prefs);
+
+ // Schedules SODA for uninstallation if no SODA client features are
+ // currently enabled. Should be called when client features using SODA are
+ // disabled.
+ void SetUninstallTimer(PrefService* profile_prefs, PrefService* global_prefs);
+
+ // Gets the directory path of the installed SODA lib bundle, or an empty path
+ // if not installed. Currently Chrome OS only, returns empty path on other
+ // platforms.
+ virtual base::FilePath GetSodaBinaryPath() const = 0;
+
+ // Gets the directory path of the installed SODA language bundle, or an empty
+ // path if not installed. Currently Chrome OS only, returns empty path on
+ // other platforms.
+ virtual base::FilePath GetLanguagePath() const = 0;
+
+ // Installs the user-selected SODA language model. Called by
+ // LiveCaptionController when the kLiveCaptionEnabled or
+ // kLiveCaptionLanguageCode preferences change. `language` is a localized
+ // language e.g. "en-US". `global_prefs` is passed as part of component
+ // registration for the non-ChromeOS implementation.
+ virtual void InstallLanguage(const std::string& language,
+ PrefService* global_prefs) = 0;
+
+ // Returns whether or not SODA is installed on this device. Will return a
+ // stale value until InstallSoda() and InstallLanguage() have run and
+ // asynchronously returned an answer.
+ virtual bool IsSodaInstalled() const = 0;
+
+ // Returns whether or not the language pack for a given language or locale
+ // code is installed.
+ virtual bool IsLanguageInstalled(
+ const std::string& locale_or_language) const = 0;
+
+ // Adds an observer to the observer list.
+ void AddObserver(Observer* observer);
+
+ // Removes an observer from the observer list.
+ void RemoveObserver(Observer* observer);
+
+ void NotifySodaInstalledForTesting();
+
+ protected:
+ // Registers the preference tracking the installed SODA language packs.
+ static void RegisterRegisteredLanguagePackPref(PrefRegistrySimple* registry);
+
+ // Installs the SODA binary. `global_prefs` is passed as part of component
+ // registration for the non-chromeos implementation.
+ virtual void InstallSoda(PrefService* global_prefs) = 0;
+
+ // Uninstalls SODA and associated language model(s). On some platforms, disc
+ // space may not be freed immediately.
+ virtual void UninstallSoda(PrefService* global_prefs) = 0;
+
+ // Notifies the observers that the installation of the SODA binary and at
+ // least one language pack has completed.
+ void NotifyOnSodaInstalled();
+
+ // Notifies the observers that a SODA language pack installation has
+ // completed.
+ void NotifyOnSodaLanguagePackInstalled(speech::LanguageCode language_code);
+
+ // Notifies the observers that there is an error in the SODA binary
+ // installation.
+ void NotifyOnSodaError();
+
+ // Notifies the observers that there is an error in a SODA language pack
+ // installation.
+ void NotifyOnSodaLanguagePackError(speech::LanguageCode language_code);
+
+ // Notifies the observers of the combined progress as the SODA binary and
+ // language pack are installed. Progress is the download percentage out of
+ // 100.
+ void NotifyOnSodaProgress(int combined_progress);
+
+ // Notifies the observers of the progress percentage the SODA language pack is
+ // installed. Progress is the download percentage out of 100.
+ void NotifyOnSodaLanguagePackProgress(int language_progress,
+ LanguageCode language_code);
+
+ // Registers a language pack by adding it to the preference tracking the
+ // installed SODA language packs.
+ void RegisterLanguage(const std::string& language, PrefService* global_prefs);
+
+ // Unregisters all language packs by clearing the preference tracking the
+ // installed SODA language packs.
+ void UnregisterLanguages(PrefService* global_prefs);
+
+ base::ObserverList<Observer> observers_;
+ bool soda_binary_installed_ = false;
+ bool language_installed_ = false;
+ bool soda_installer_initialized_ = false;
+
+ private:
+ // Any new feature using SODA should add its pref here.
+ bool IsAnyFeatureUsingSodaEnabled(PrefService* prefs);
+};
+
+} // namespace speech
+
+#endif // COMPONENTS_SODA_SODA_INSTALLER_H_
diff --git a/chromium/components/soda/soda_installer_impl_chromeos.cc b/chromium/components/soda/soda_installer_impl_chromeos.cc
new file mode 100644
index 00000000000..d24c22f43f0
--- /dev/null
+++ b/chromium/components/soda/soda_installer_impl_chromeos.cc
@@ -0,0 +1,199 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/soda/soda_installer_impl_chromeos.h"
+
+#include "base/bind.h"
+#include "base/feature_list.h"
+#include "base/no_destructor.h"
+#include "chromeos/dbus/dlcservice/dlcservice_client.h"
+#include "components/live_caption/pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "components/soda/pref_names.h"
+#include "media/base/media_switches.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+constexpr char kSodaDlcName[] = "libsoda";
+constexpr char kSodaEnglishUsDlcName[] = "libsoda-model-en-us";
+
+} // namespace
+
+namespace speech {
+
+SodaInstaller* SodaInstaller::GetInstance() {
+ static base::NoDestructor<SodaInstallerImplChromeOS> instance;
+ return instance.get();
+}
+
+// static
+void SodaInstaller::RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
+ registry->RegisterTimePref(prefs::kSodaScheduledDeletionTime, base::Time());
+ SodaInstaller::RegisterRegisteredLanguagePackPref(registry);
+}
+
+SodaInstallerImplChromeOS::SodaInstallerImplChromeOS() = default;
+
+SodaInstallerImplChromeOS::~SodaInstallerImplChromeOS() = default;
+
+base::FilePath SodaInstallerImplChromeOS::GetSodaBinaryPath() const {
+ return soda_lib_path_;
+}
+
+base::FilePath SodaInstallerImplChromeOS::GetLanguagePath() const {
+ return language_path_;
+}
+
+void SodaInstallerImplChromeOS::InstallSoda(PrefService* global_prefs) {
+ if (!base::FeatureList::IsEnabled(media::kUseSodaForLiveCaption))
+ return;
+
+ // Clear cached path in case this is a reinstallation (path could
+ // change).
+ SetSodaBinaryPath(base::FilePath());
+
+ soda_binary_installed_ = false;
+ is_soda_downloading_ = true;
+ soda_progress_ = 0.0;
+
+ // Install SODA DLC.
+ chromeos::DlcserviceClient::Get()->Install(
+ kSodaDlcName,
+ base::BindOnce(&SodaInstallerImplChromeOS::OnSodaInstalled,
+ base::Unretained(this)),
+ base::BindRepeating(&SodaInstallerImplChromeOS::OnSodaProgress,
+ base::Unretained(this)));
+}
+
+void SodaInstallerImplChromeOS::InstallLanguage(const std::string& language,
+ PrefService* global_prefs) {
+ if (!base::FeatureList::IsEnabled(media::kUseSodaForLiveCaption))
+ return;
+
+ SodaInstaller::RegisterLanguage(language, global_prefs);
+ // Clear cached path in case this is a reinstallation (path could
+ // change).
+ SetLanguagePath(base::FilePath());
+
+ // TODO(crbug.com/1055150): Compare user's language to a list of
+ // supported languages and map it to a DLC ID. For now, default to
+ // installing the SODA English-US DLC.
+ DCHECK_EQ(language, "en-US");
+
+ language_installed_ = false;
+ is_language_downloading_ = true;
+ language_progress_ = 0.0;
+
+ chromeos::DlcserviceClient::Get()->Install(
+ kSodaEnglishUsDlcName,
+ base::BindOnce(&SodaInstallerImplChromeOS::OnLanguageInstalled,
+ base::Unretained(this)),
+ base::BindRepeating(&SodaInstallerImplChromeOS::OnLanguageProgress,
+ base::Unretained(this)));
+}
+
+bool SodaInstallerImplChromeOS::IsSodaInstalled() const {
+ DCHECK(base::FeatureList::IsEnabled(media::kUseSodaForLiveCaption));
+ return (soda_binary_installed_ && language_installed_) ||
+ soda_installed_for_test_;
+}
+
+bool SodaInstallerImplChromeOS::IsLanguageInstalled(
+ const std::string& locale_or_language) const {
+ // TODO(crbug.com/1161569): SODA is only available for English right now.
+ // Update this to check installation of language pack when available.
+ return (l10n_util::GetLanguage(locale_or_language) == "en" &&
+ language_installed_) ||
+ soda_installed_for_test_;
+}
+
+void SodaInstallerImplChromeOS::UninstallSoda(PrefService* global_prefs) {
+ soda_binary_installed_ = false;
+ SetSodaBinaryPath(base::FilePath());
+ chromeos::DlcserviceClient::Get()->Uninstall(
+ kSodaDlcName, base::BindOnce(&SodaInstallerImplChromeOS::OnDlcUninstalled,
+ base::Unretained(this), kSodaDlcName));
+ language_installed_ = false;
+ SodaInstaller::UnregisterLanguages(global_prefs);
+ SetLanguagePath(base::FilePath());
+ chromeos::DlcserviceClient::Get()->Uninstall(
+ kSodaEnglishUsDlcName,
+ base::BindOnce(&SodaInstallerImplChromeOS::OnDlcUninstalled,
+ base::Unretained(this), kSodaEnglishUsDlcName));
+ global_prefs->SetTime(prefs::kSodaScheduledDeletionTime, base::Time());
+}
+
+void SodaInstallerImplChromeOS::SetSodaBinaryPath(base::FilePath new_path) {
+ soda_lib_path_ = new_path;
+}
+
+void SodaInstallerImplChromeOS::SetLanguagePath(base::FilePath new_path) {
+ language_path_ = new_path;
+}
+
+void SodaInstallerImplChromeOS::OnSodaInstalled(
+ const chromeos::DlcserviceClient::InstallResult& install_result) {
+ if (install_result.error == dlcservice::kErrorNone) {
+ soda_binary_installed_ = true;
+ SetSodaBinaryPath(base::FilePath(install_result.root_path));
+ if (language_installed_) {
+ NotifyOnSodaInstalled();
+ }
+ } else {
+ soda_binary_installed_ = false;
+ soda_progress_ = 0.0;
+ NotifyOnSodaError();
+ }
+ is_soda_downloading_ = false;
+}
+
+void SodaInstallerImplChromeOS::OnLanguageInstalled(
+ const chromeos::DlcserviceClient::InstallResult& install_result) {
+ if (install_result.error == dlcservice::kErrorNone) {
+ language_installed_ = true;
+ SetLanguagePath(base::FilePath(install_result.root_path));
+ if (soda_binary_installed_) {
+ NotifyOnSodaInstalled();
+ }
+ } else {
+ language_installed_ = false;
+ language_progress_ = 0.0;
+
+ // TODO: Notify the observer of the specific language pack that failed to
+ // install. ChromeOS currently only supports the en-US language pack.
+ NotifyOnSodaLanguagePackError(speech::LanguageCode::kEnUs);
+ }
+ is_language_downloading_ = false;
+}
+
+void SodaInstallerImplChromeOS::OnSodaProgress(double progress) {
+ soda_progress_ = progress;
+ OnSodaCombinedProgress();
+}
+
+void SodaInstallerImplChromeOS::OnLanguageProgress(double progress) {
+ language_progress_ = progress;
+
+ // TODO: Notify the observer of the specific language pack that is currently
+ // being installed. ChromeOS currently only supports the en-US language pack.
+ NotifyOnSodaLanguagePackProgress(progress, speech::LanguageCode::kEnUs);
+}
+
+void SodaInstallerImplChromeOS::OnSodaCombinedProgress() {
+ // TODO(crbug.com/1055150): Consider updating this implementation.
+ // e.g.: (1) starting progress from 0% if we are downloading language
+ // only (2) weighting download progress proportionally to DLC binary size.
+ const double progress = (soda_progress_ + language_progress_) / 2;
+ NotifyOnSodaProgress(int{100 * progress});
+}
+
+void SodaInstallerImplChromeOS::OnDlcUninstalled(const std::string& dlc_id,
+ const std::string& err) {
+ if (err != dlcservice::kErrorNone) {
+ LOG(ERROR) << "Failed to uninstall DLC " << dlc_id << ". Error: " << err;
+ }
+}
+
+} // namespace speech
diff --git a/chromium/components/soda/soda_installer_impl_chromeos.h b/chromium/components/soda/soda_installer_impl_chromeos.h
new file mode 100644
index 00000000000..cbcb13c0a6b
--- /dev/null
+++ b/chromium/components/soda/soda_installer_impl_chromeos.h
@@ -0,0 +1,95 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SODA_SODA_INSTALLER_IMPL_CHROMEOS_H_
+#define COMPONENTS_SODA_SODA_INSTALLER_IMPL_CHROMEOS_H_
+
+#include "base/files/file_path.h"
+#include "chromeos/dbus/dlcservice/dlcservice_client.h"
+#include "components/soda/soda_installer.h"
+
+class PrefService;
+class OnDeviceSpeechRecognizerTest;
+
+namespace ash {
+class DictationTest;
+} // namespace ash
+
+namespace speech {
+
+// Installer of SODA (Speech On-Device API) for the Live Caption feature on
+// ChromeOS.
+class SodaInstallerImplChromeOS : public SodaInstaller {
+ public:
+ SodaInstallerImplChromeOS();
+ ~SodaInstallerImplChromeOS() override;
+ SodaInstallerImplChromeOS(const SodaInstallerImplChromeOS&) = delete;
+ SodaInstallerImplChromeOS& operator=(const SodaInstallerImplChromeOS&) =
+ delete;
+
+ // Where the SODA DLC was installed. Cached on completed installation.
+ // Empty if SODA DLC not installed yet.
+ base::FilePath GetSodaBinaryPath() const override;
+
+ // Where the SODA language pack DLC was installed. Cached on completed
+ // installation. Empty if not installed yet.
+ base::FilePath GetLanguagePath() const override;
+
+ // SodaInstaller:
+ void InstallLanguage(const std::string& language,
+ PrefService* global_prefs) override;
+ bool IsSodaInstalled() const override;
+ bool IsLanguageInstalled(
+ const std::string& locale_or_language) const override;
+
+ private:
+ friend class ::ash::DictationTest;
+ friend class ::OnDeviceSpeechRecognizerTest;
+
+ // SodaInstaller:
+ void InstallSoda(PrefService* global_prefs) override;
+ // Here "uninstall" is used in the DLC sense of the term: Uninstallation will
+ // disable a DLC but not immediately remove it from disk.
+ // Once a refcount to the DLC reaches 0 (meaning all profiles which had it
+ // installed have called to uninstall it), the DLC will remain in cache; if it
+ // is then not installed within a (DLC-service-defined) window of time, the
+ // DLC is automatically purged from disk.
+ void UninstallSoda(PrefService* global_prefs) override;
+
+ void SetSodaBinaryPath(base::FilePath new_path);
+ void SetLanguagePath(base::FilePath new_path);
+
+ // These functions are the InstallCallbacks for DlcserviceClient::Install().
+ void OnSodaInstalled(
+ const chromeos::DlcserviceClient::InstallResult& install_result);
+ void OnLanguageInstalled(
+ const chromeos::DlcserviceClient::InstallResult& install_result);
+
+ // These functions are the ProgressCallbacks for DlcserviceClient::Install().
+ void OnSodaProgress(double progress);
+ void OnLanguageProgress(double progress);
+
+ void OnSodaCombinedProgress();
+
+ // This is the UninstallCallback for DlcserviceClient::Uninstall().
+ void OnDlcUninstalled(const std::string& dlc_id, const std::string& err);
+
+ // When true, IsSodaInstalled() will return true. This may be used by tests
+ // that need to pretend soda is installed before using
+ // FakeSpeechRecognitionService.
+ bool soda_installed_for_test_ = false;
+
+ bool is_soda_downloading_ = false;
+ bool is_language_downloading_ = false;
+
+ double soda_progress_ = 0.0;
+ double language_progress_ = 0.0;
+
+ base::FilePath soda_lib_path_;
+ base::FilePath language_path_;
+};
+
+} // namespace speech
+
+#endif // COMPONENTS_SODA_SODA_INSTALLER_IMPL_CHROMEOS_H_
diff --git a/chromium/components/speech/chunked_byte_buffer.h b/chromium/components/speech/chunked_byte_buffer.h
index dddc2ee26eb..418ceaa7204 100644
--- a/chromium/components/speech/chunked_byte_buffer.h
+++ b/chromium/components/speech/chunked_byte_buffer.h
@@ -9,7 +9,6 @@
#include <stdint.h>
#include <memory>
-#include <string>
#include <vector>
#include "base/macros.h"
diff --git a/chromium/components/speech/upstream_loader.cc b/chromium/components/speech/upstream_loader.cc
index 0f00733d888..dfbdbd4f9cc 100644
--- a/chromium/components/speech/upstream_loader.cc
+++ b/chromium/components/speech/upstream_loader.cc
@@ -4,7 +4,6 @@
#include "components/speech/upstream_loader.h"
-#include "base/callback_forward.h"
#include "components/speech/upstream_loader_client.h"
namespace speech {
diff --git a/chromium/components/spellcheck/browser/pref_names.h b/chromium/components/spellcheck/browser/pref_names.h
index 9474028f3c1..43aadaef04c 100644
--- a/chromium/components/spellcheck/browser/pref_names.h
+++ b/chromium/components/spellcheck/browser/pref_names.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_BROWSER_PREF_NAMES_H
-#define COMPONENTS_SPELLCHECK_BROWSER_PREF_NAMES_H
+#ifndef COMPONENTS_SPELLCHECK_BROWSER_PREF_NAMES_H_
+#define COMPONENTS_SPELLCHECK_BROWSER_PREF_NAMES_H_
namespace spellcheck {
namespace prefs {
@@ -19,4 +19,4 @@ extern const char kSpellCheckUseSpellingService[];
} // namespace prefs
} // namespace spellcheck
-#endif // COMPONENTS_SPELLCHECK_BROWSER_PREF_NAMES_H
+#endif // COMPONENTS_SPELLCHECK_BROWSER_PREF_NAMES_H_
diff --git a/chromium/components/spellcheck/browser/spelling_service_client.cc b/chromium/components/spellcheck/browser/spelling_service_client.cc
index 22c9a43b982..9c47f225108 100644
--- a/chromium/components/spellcheck/browser/spelling_service_client.cc
+++ b/chromium/components/spellcheck/browser/spelling_service_client.cc
@@ -149,11 +149,10 @@ bool SpellingServiceClient::RequestTextCheck(
std::make_unique<TextCheckCallbackData>(std::move(simple_url_loader),
std::move(callback), text));
network::SimpleURLLoader* loader = it->get()->simple_url_loader.get();
- auto url_loader_factory =
- url_loader_factory_for_testing_
- ? url_loader_factory_for_testing_
- : content::BrowserContext::GetDefaultStoragePartition(context)
- ->GetURLLoaderFactoryForBrowserProcess();
+ auto url_loader_factory = url_loader_factory_for_testing_
+ ? url_loader_factory_for_testing_
+ : context->GetDefaultStoragePartition()
+ ->GetURLLoaderFactoryForBrowserProcess();
loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
url_loader_factory.get(),
base::BindOnce(&SpellingServiceClient::OnSimpleLoaderComplete,
diff --git a/chromium/components/spellcheck/common/spellcheck_common.cc b/chromium/components/spellcheck/common/spellcheck_common.cc
index b7cd4102d77..f3e9dff9c7a 100644
--- a/chromium/components/spellcheck/common/spellcheck_common.cc
+++ b/chromium/components/spellcheck/common/spellcheck_common.cc
@@ -9,6 +9,7 @@
#include "base/containers/contains.h"
#include "base/files/file_path.h"
#include "base/metrics/field_trial.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "third_party/icu/source/common/unicode/uloc.h"
#include "third_party/icu/source/common/unicode/urename.h"
@@ -104,7 +105,7 @@ std::string GetSpellCheckLanguageRegion(base::StringPiece input_language) {
return lang_region.language_region;
}
- return input_language.as_string();
+ return std::string(input_language);
}
base::FilePath GetVersionedFileName(base::StringPiece input_language,
@@ -168,7 +169,7 @@ std::string GetCorrespondingSpellCheckLanguage(base::StringPiece language) {
for (const auto& lang_region : kSupportedSpellCheckerLanguages) {
// First look for exact match in the language region of the list.
if (lang_region.language == language)
- return language.as_string();
+ return std::string(language);
// Next, look for exact match in the language_region part of the list.
if (lang_region.language_region == language) {
diff --git a/chromium/components/spellcheck/renderer/empty_local_interface_provider.h b/chromium/components/spellcheck/renderer/empty_local_interface_provider.h
index d861c9fed06..2c1b927df7a 100644
--- a/chromium/components/spellcheck/renderer/empty_local_interface_provider.h
+++ b/chromium/components/spellcheck/renderer/empty_local_interface_provider.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SPELLCHECK_EMPTY_LOCAL_INTERFACE_PROVIDER_H_
-#define COMPONENTS_SPELLCHECK_EMPTY_LOCAL_INTERFACE_PROVIDER_H_
+#ifndef COMPONENTS_SPELLCHECK_RENDERER_EMPTY_LOCAL_INTERFACE_PROVIDER_H_
+#define COMPONENTS_SPELLCHECK_RENDERER_EMPTY_LOCAL_INTERFACE_PROVIDER_H_
#include "services/service_manager/public/cpp/local_interface_provider.h"
@@ -21,4 +21,4 @@ class EmptyLocalInterfaceProvider
} // namespace spellcheck
-#endif // COMPONENTS_SPELLCHECK_EMPTY_LOCAL_INTERFACE_PROVIDER_H_
+#endif // COMPONENTS_SPELLCHECK_RENDERER_EMPTY_LOCAL_INTERFACE_PROVIDER_H_
diff --git a/chromium/components/spellcheck/renderer/spellcheck.cc b/chromium/components/spellcheck/renderer/spellcheck.cc
index 060afcfa513..8a268689f9b 100644
--- a/chromium/components/spellcheck/renderer/spellcheck.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck.cc
@@ -424,8 +424,8 @@ void SpellCheck::RequestTextChecking(
if (pending_request_param_)
pending_request_param_->completion()->DidCancelCheckingText();
- pending_request_param_.reset(
- new SpellcheckRequest(text, std::move(completion)));
+ pending_request_param_ =
+ std::make_unique<SpellcheckRequest>(text, std::move(completion));
// We will check this text after we finish loading the hunspell dictionary.
if (InitializeIfNeeded())
return;
diff --git a/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc b/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
index 63ab75328d9..af88e901a2b 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
@@ -53,8 +53,8 @@ class MultilingualSpellCheckTest : public testing::Test {
void ReinitializeSpellCheck(const std::string& unsplit_languages) {
spellcheck_ = new SpellCheck(&embedder_provider_);
- provider_.reset(
- new TestingSpellCheckProvider(spellcheck_, &embedder_provider_));
+ provider_ = std::make_unique<TestingSpellCheckProvider>(
+ spellcheck_, &embedder_provider_);
InitializeSpellCheck(unsplit_languages);
}
diff --git a/chromium/components/spellcheck/renderer/spellcheck_panel.h b/chromium/components/spellcheck/renderer/spellcheck_panel.h
index 5565b404cc3..36bf2e1cee7 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_panel.h
+++ b/chromium/components/spellcheck/renderer/spellcheck_panel.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_RENDERER_SPELLCHECK_PANEL_H
-#define COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_PANEL_H
+#ifndef COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_PANEL_H_
+#define COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_PANEL_H_
#include "base/macros.h"
#include "components/spellcheck/common/spellcheck_panel.mojom.h"
@@ -63,4 +63,4 @@ class SpellCheckPanel : public content::RenderFrameObserver,
DISALLOW_COPY_AND_ASSIGN(SpellCheckPanel);
};
-#endif
+#endif // COMPONENTS_SPELLCHECK_RENDERER_SPELLCHECK_PANEL_H_
diff --git a/chromium/components/spellcheck/renderer/spellcheck_provider_unittest.cc b/chromium/components/spellcheck/renderer/spellcheck_provider_unittest.cc
index f25403a5af5..ff1c38e6238 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_provider_unittest.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_provider_unittest.cc
@@ -263,11 +263,11 @@ INSTANTIATE_TEST_SUITE_P(
{SpellCheckResult(SpellCheckResult::SPELLING,
0,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
9,
4,
- {base::ASCIIToUTF16("foo")})},
+ {std::u16string(u"foo")})},
false,
blink::WebVector<blink::WebTextCheckingResult>(
{blink::WebTextCheckingResult(
@@ -294,27 +294,27 @@ INSTANTIATE_TEST_SUITE_P(
{SpellCheckResult(SpellCheckResult::SPELLING,
0,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
9,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
14,
5,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
20,
2,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
23,
5,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
29,
6,
- {base::ASCIIToUTF16("foo")})},
+ {std::u16string(u"foo")})},
false,
blink::WebVector<blink::WebTextCheckingResult>(
{blink::WebTextCheckingResult(
@@ -336,11 +336,11 @@ INSTANTIATE_TEST_SUITE_P(
{SpellCheckResult(SpellCheckResult::SPELLING,
0,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
9,
4,
- {base::ASCIIToUTF16("foo")})},
+ {std::u16string(u"foo")})},
true,
blink::WebVector<blink::WebTextCheckingResult>(
{blink::WebTextCheckingResult(
@@ -363,11 +363,11 @@ INSTANTIATE_TEST_SUITE_P(
{SpellCheckResult(SpellCheckResult::SPELLING,
0,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::GRAMMAR,
9,
4,
- {base::ASCIIToUTF16("foo")})},
+ {std::u16string(u"foo")})},
true,
blink::WebVector<blink::WebTextCheckingResult>(
{blink::WebTextCheckingResult(
@@ -397,11 +397,11 @@ INSTANTIATE_TEST_SUITE_P(
{SpellCheckResult(SpellCheckResult::SPELLING,
0,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
9,
4,
- {base::ASCIIToUTF16("foo")})},
+ {std::u16string(u"foo")})},
false,
blink::WebVector<blink::WebTextCheckingResult>(
{blink::WebTextCheckingResult(
@@ -425,19 +425,19 @@ INSTANTIATE_TEST_SUITE_P(
SpellCheckResult(SpellCheckResult::SPELLING,
0,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
5,
3,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
9,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
14,
12,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
},
false,
blink::WebVector<blink::WebTextCheckingResult>(
@@ -461,11 +461,11 @@ INSTANTIATE_TEST_SUITE_P(
{SpellCheckResult(SpellCheckResult::SPELLING,
5,
3,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
14,
12,
- {base::ASCIIToUTF16("foo")})},
+ {std::u16string(u"foo")})},
false,
blink::WebVector<blink::WebTextCheckingResult>()},
@@ -480,15 +480,15 @@ INSTANTIATE_TEST_SUITE_P(
{SpellCheckResult(SpellCheckResult::SPELLING,
0,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
5,
3,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
35,
6,
- {base::ASCIIToUTF16("foo")})},
+ {std::u16string(u"foo")})},
false,
blink::WebVector<blink::WebTextCheckingResult>(
std::vector<blink::WebTextCheckingResult>(
@@ -508,15 +508,15 @@ INSTANTIATE_TEST_SUITE_P(
{SpellCheckResult(SpellCheckResult::SPELLING,
0,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
5,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
36,
6,
- {base::ASCIIToUTF16("foo")})},
+ {std::u16string(u"foo")})},
false,
blink::WebVector<blink::WebTextCheckingResult>(
{blink::WebTextCheckingResult(
@@ -539,11 +539,11 @@ INSTANTIATE_TEST_SUITE_P(
{SpellCheckResult(SpellCheckResult::SPELLING,
0,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::GRAMMAR,
9,
4,
- {base::ASCIIToUTF16("foo")})},
+ {std::u16string(u"foo")})},
true,
blink::WebVector<blink::WebTextCheckingResult>(
{blink::WebTextCheckingResult(
@@ -566,11 +566,11 @@ INSTANTIATE_TEST_SUITE_P(
{SpellCheckResult(SpellCheckResult::SPELLING,
0,
4,
- {base::ASCIIToUTF16("foo")}),
+ {std::u16string(u"foo")}),
SpellCheckResult(SpellCheckResult::SPELLING,
9,
4,
- {base::ASCIIToUTF16("foo")})},
+ {std::u16string(u"foo")})},
true,
blink::WebVector<blink::WebTextCheckingResult>(
{blink::WebTextCheckingResult(blink::WebTextDecorationType::
diff --git a/chromium/components/spellcheck/renderer/spellcheck_unittest.cc b/chromium/components/spellcheck/renderer/spellcheck_unittest.cc
index c2d149a6b37..387fb378b80 100644
--- a/chromium/components/spellcheck/renderer/spellcheck_unittest.cc
+++ b/chromium/components/spellcheck/renderer/spellcheck_unittest.cc
@@ -1065,12 +1065,12 @@ TEST_F(SpellCheckTest, SpellCheckParagraphMultipleMisspellings) {
TEST_F(SpellCheckTest, SpellCheckParagraphLongSentence) {
std::vector<SpellCheckResult> expected;
// The text is taken from US constitution preamble.
- const std::u16string text = base::UTF8ToUTF16(
- "We the people of the United States, in order to form a more perfect "
- "union, establish justice, insure domestic tranquility, provide for "
- "the common defense, promote the general welfare, and secure the "
- "blessings of liberty to ourselves and our posterity, do ordain and "
- "establish this Constitution for the United States of America.");
+ const std::u16string text =
+ u"We the people of the United States, in order to form a more perfect "
+ u"union, establish justice, insure domestic tranquility, provide for "
+ u"the common defense, promote the general welfare, and secure the "
+ u"blessings of liberty to ourselves and our posterity, do ordain and "
+ u"establish this Constitution for the United States of America.";
TestSpellCheckParagraph(text, expected);
}
@@ -1080,12 +1080,12 @@ TEST_F(SpellCheckTest, SpellCheckParagraphLongSentenceMultipleMisspellings) {
std::vector<SpellCheckResult> expected;
// All 'the' are converted to 'hte' in US consitition preamble.
- const std::u16string text = base::UTF8ToUTF16(
- "We hte people of hte United States, in order to form a more perfect "
- "union, establish justice, insure domestic tranquility, provide for "
- "hte common defense, promote hte general welfare, and secure hte "
- "blessings of liberty to ourselves and our posterity, do ordain and "
- "establish this Constitution for hte United States of America.");
+ const std::u16string text =
+ u"We hte people of hte United States, in order to form a more perfect "
+ u"union, establish justice, insure domestic tranquility, provide for "
+ u"hte common defense, promote hte general welfare, and secure hte "
+ u"blessings of liberty to ourselves and our posterity, do ordain and "
+ u"establish this Constitution for hte United States of America.";
expected.push_back(SpellCheckResult(
SpellCheckResult::SPELLING, 3, 3));
diff --git a/chromium/components/sqlite_proto/key_value_data.h b/chromium/components/sqlite_proto/key_value_data.h
index fcd50e23409..77bb0549ff3 100644
--- a/chromium/components/sqlite_proto/key_value_data.h
+++ b/chromium/components/sqlite_proto/key_value_data.h
@@ -16,11 +16,11 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/timer/timer.h"
#include "components/sqlite_proto/key_value_table.h"
#include "components/sqlite_proto/table_manager.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sqlite_proto {
@@ -44,7 +44,7 @@ struct FakeCompare {
// NOTE: If the data store is larger than the maximum cache size, it
// will be pruned on construction to satisfy the size invariant specified
// by |max_num_entries|. If this is undesirable, set a sufficiently high
-// |max_num_entries| (or pass |max_num_entries| = base::nullopt for
+// |max_num_entries| (or pass |max_num_entries| = absl::nullopt for
// unbounded size).
//
// InitializeOnDBSequence() must be called on the DB sequence of the
@@ -65,7 +65,7 @@ class KeyValueData {
// pass writes and deletes through immediately.
KeyValueData(scoped_refptr<TableManager> manager,
KeyValueTable<T>* backend,
- base::Optional<size_t> max_num_entries,
+ absl::optional<size_t> max_num_entries,
base::TimeDelta flush_delay);
KeyValueData(const KeyValueData&) = delete;
@@ -111,7 +111,7 @@ class KeyValueData {
std::unordered_map<std::string, DeferredOperation> deferred_updates_;
base::RepeatingTimer flush_timer_;
const base::TimeDelta flush_delay_;
- const base::Optional<size_t> max_num_entries_;
+ const absl::optional<size_t> max_num_entries_;
EntryCompare entry_compare_;
SEQUENCE_CHECKER(sequence_checker_);
@@ -120,7 +120,7 @@ class KeyValueData {
template <typename T, typename Compare>
KeyValueData<T, Compare>::KeyValueData(scoped_refptr<TableManager> manager,
KeyValueTable<T>* backend,
- base::Optional<size_t> max_num_entries,
+ absl::optional<size_t> max_num_entries,
base::TimeDelta flush_delay)
: manager_(manager),
backend_table_(backend),
diff --git a/chromium/components/sqlite_proto/key_value_data_unittest.cc b/chromium/components/sqlite_proto/key_value_data_unittest.cc
index cfc21e6d0b4..62effcd69a9 100644
--- a/chromium/components/sqlite_proto/key_value_data_unittest.cc
+++ b/chromium/components/sqlite_proto/key_value_data_unittest.cc
@@ -5,7 +5,6 @@
#include "components/sqlite_proto/key_value_data.h"
#include "base/memory/scoped_refptr.h"
-#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -86,7 +85,7 @@ class KeyValueDataTest : public ::testing::Test {
public:
KeyValueDataTest()
: manager_(base::MakeRefCounted<FakeTableManager>()),
- data_(manager_, &table_, base::nullopt, base::TimeDelta()) {
+ data_(manager_, &table_, absl::nullopt, base::TimeDelta()) {
// In these tests, we're using the current thread as the DB sequence.
data_.InitializeOnDBSequence();
}
@@ -190,7 +189,7 @@ TEST(KeyValueDataTestSize, PrunesOverlargeTable) {
// Initialization: write a table of size 2 to |manager|'s backend.
{
KeyValueData<TestProto, TestProtoCompare> data(
- manager, &table, /*max_num_entries=*/base::nullopt,
+ manager, &table, /*max_num_entries=*/absl::nullopt,
/*flush_delay=*/base::TimeDelta());
// In these tests, we're using the current thread as the DB sequence.
data.InitializeOnDBSequence();
@@ -220,7 +219,7 @@ TEST(KeyValueDataTestSize, PrunesOverlargeTable) {
{
KeyValueData<TestProto, TestProtoCompare> data(
- manager, &table, /*max_num_entries=*/base::nullopt,
+ manager, &table, /*max_num_entries=*/absl::nullopt,
/*flush_delay=*/base::TimeDelta());
// In these tests, we're using the current thread as the DB sequence.
data.InitializeOnDBSequence();
diff --git a/chromium/components/sqlite_proto/proto_table_manager.h b/chromium/components/sqlite_proto/proto_table_manager.h
index ced520dc645..9508b6a58b3 100644
--- a/chromium/components/sqlite_proto/proto_table_manager.h
+++ b/chromium/components/sqlite_proto/proto_table_manager.h
@@ -7,7 +7,6 @@
#include <string>
-#include "base/callback_forward.h"
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/sequenced_task_runner.h"
diff --git a/chromium/components/sqlite_proto/proto_table_manager_unittest.cc b/chromium/components/sqlite_proto/proto_table_manager_unittest.cc
index 1b921aaed01..2df861fcfaf 100644
--- a/chromium/components/sqlite_proto/proto_table_manager_unittest.cc
+++ b/chromium/components/sqlite_proto/proto_table_manager_unittest.cc
@@ -57,7 +57,7 @@ TEST(ProtoTableTest, PutReinitializeAndGet) {
{
KeyValueData<TestProto> data(manager, &table,
- /*max_num_entries=*/base::nullopt,
+ /*max_num_entries=*/absl::nullopt,
/*flush_delay=*/base::TimeDelta());
// In these tests, we're using the current thread as the DB sequence.
@@ -70,7 +70,7 @@ TEST(ProtoTableTest, PutReinitializeAndGet) {
{
KeyValueData<TestProto> data(manager, &table,
- /*max_num_entries=*/base::nullopt,
+ /*max_num_entries=*/absl::nullopt,
/*flush_delay=*/base::TimeDelta());
data.InitializeOnDBSequence();
diff --git a/chromium/components/ssl_errors/error_info.h b/chromium/components/ssl_errors/error_info.h
index ced95db6bb7..b4080f53cd8 100644
--- a/chromium/components/ssl_errors/error_info.h
+++ b/chromium/components/ssl_errors/error_info.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SSL_ERRORS_SSL_ERROR_INFO_H_
-#define COMPONENTS_SSL_ERRORS_SSL_ERROR_INFO_H_
+#ifndef COMPONENTS_SSL_ERRORS_ERROR_INFO_H_
+#define COMPONENTS_SSL_ERRORS_ERROR_INFO_H_
#include <string>
#include <vector>
@@ -80,4 +80,4 @@ class ErrorInfo {
} // namespace ssl_errors
-#endif // COMPONENTS_SSL_ERRORS_SSL_ERROR_INFO_H_
+#endif // COMPONENTS_SSL_ERRORS_ERROR_INFO_H_
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 1fca1d3987a..bb280e469de 100644
--- a/chromium/components/startup_metric_utils/browser/startup_metric_utils.cc
+++ b/chromium/components/startup_metric_utils/browser/startup_metric_utils.cc
@@ -16,7 +16,6 @@
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/notreached.h"
-#include "base/optional.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/platform_thread.h"
@@ -24,6 +23,7 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/version_info/version_info.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if defined(OS_WIN)
#include <windows.h>
@@ -129,13 +129,13 @@ typedef NTSTATUS (WINAPI *NtQuerySystemInformationPtr)(
// Returns the hard fault count of the current process, or nullopt if it can't
// be determined.
-base::Optional<uint32_t> GetHardFaultCountForCurrentProcess() {
+absl::optional<uint32_t> GetHardFaultCountForCurrentProcess() {
// Get the function pointer.
static const NtQuerySystemInformationPtr query_sys_info =
reinterpret_cast<NtQuerySystemInformationPtr>(::GetProcAddress(
GetModuleHandle(L"ntdll.dll"), "NtQuerySystemInformation"));
if (query_sys_info == nullptr)
- return base::nullopt;
+ return absl::nullopt;
// The output of this system call depends on the number of threads and
// processes on the entire system, and this can change between calls. Retry
@@ -164,7 +164,7 @@ base::Optional<uint32_t> GetHardFaultCountForCurrentProcess() {
// fill a large buffer just to record histograms.
constexpr ULONG kMaxLength = 512 * 1024;
if (return_length >= kMaxLength)
- return base::nullopt;
+ return absl::nullopt;
// Resize the buffer and retry, if the buffer hasn't already been resized
// too many times.
@@ -179,7 +179,7 @@ base::Optional<uint32_t> GetHardFaultCountForCurrentProcess() {
// insufficient buffer length, or if the buffer was resized too many times.
DCHECK(return_length <= buffer.size() ||
num_buffer_resize >= kMaxNumBufferResize);
- return base::nullopt;
+ return absl::nullopt;
}
// Look for the struct housing information for the current process.
@@ -194,11 +194,11 @@ base::Optional<uint32_t> GetHardFaultCountForCurrentProcess() {
// The list ends when NextEntryOffset is zero. This also prevents busy
// looping if the data is in fact invalid.
if (proc_info->NextEntryOffset <= 0)
- return base::nullopt;
+ return absl::nullopt;
index += proc_info->NextEntryOffset;
}
- return base::nullopt;
+ return absl::nullopt;
}
#endif // defined(OS_WIN)
@@ -297,7 +297,7 @@ void RecordHardFaultHistogram() {
#if defined(OS_WIN)
DCHECK_EQ(UNDETERMINED_STARTUP_TEMPERATURE, g_startup_temperature);
- const base::Optional<uint32_t> hard_fault_count =
+ const absl::optional<uint32_t> hard_fault_count =
GetHardFaultCountForCurrentProcess();
if (hard_fault_count.has_value()) {
@@ -476,6 +476,23 @@ void RecordBrowserMainMessageLoopStart(base::TimeTicks ticks,
}
}
+void RecordBrowserMainLoopFirstIdle(base::TimeTicks ticks) {
+ DCHECK(!g_application_start_ticks.is_null());
+
+#if DCHECK_IS_ON()
+ static bool is_first_call = true;
+ DCHECK(is_first_call);
+ is_first_call = false;
+#endif // DCHECK_IS_ON()
+
+ if (!ShouldLogStartupHistogram())
+ return;
+
+ UmaHistogramWithTraceAndTemperature(&base::UmaHistogramLongTimes100,
+ "Startup.BrowserMessageLoopFirstIdle",
+ g_application_start_ticks, ticks);
+}
+
void RecordBrowserWindowDisplay(base::TimeTicks ticks) {
DCHECK(!ticks.is_null());
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 ca65780ae2f..be29c3d4cc5 100644
--- a/chromium/components/startup_metric_utils/browser/startup_metric_utils.h
+++ b/chromium/components/startup_metric_utils/browser/startup_metric_utils.h
@@ -53,6 +53,11 @@ void RecordChromeMainEntryTime(base::TimeTicks ticks);
void RecordBrowserMainMessageLoopStart(base::TimeTicks ticks,
bool is_first_run);
+// Call this with the time recorded just after the message loop first reaches
+// idle. Must be called after RecordApplicationStartTime(), because it computes
+// time deltas based on application start time.
+void RecordBrowserMainLoopFirstIdle(base::TimeTicks ticks);
+
// Call this with the time when the first browser window became visible.
void RecordBrowserWindowDisplay(base::TimeTicks ticks);
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 5a7a8bd306a..5f0b892e12a 100644
--- a/chromium/components/storage_monitor/mtp_manager_client_chromeos_unittest.cc
+++ b/chromium/components/storage_monitor/mtp_manager_client_chromeos_unittest.cc
@@ -31,8 +31,10 @@ namespace {
const char kStorageWithInvalidInfo[] = "usb:2,3:11111";
const char kStorageWithValidInfo[] = "usb:2,2:88888";
const char kStorageVendor[] = "ExampleVendor";
+const char16_t kStorageVendor16[] = u"ExampleVendor";
const uint32_t kStorageVendorId = 0x040a;
const char kStorageProduct[] = "ExampleCamera";
+const char16_t kStorageProduct16[] = u"ExampleCamera";
const uint32_t kStorageProductId = 0x0160;
const uint32_t kStorageDeviceFlags = 0x0004000;
const uint32_t kStorageType = 3; // Fixed RAM
@@ -112,7 +114,7 @@ class MtpManagerClientChromeOSTest : public testing::Test {
protected:
void SetUp() override {
- mock_storage_observer_.reset(new MockRemovableStorageObserver);
+ mock_storage_observer_ = std::make_unique<MockRemovableStorageObserver>();
TestStorageMonitor* monitor = TestStorageMonitor::CreateAndInstall();
mtp_device_observer_ = std::make_unique<FakeMtpManagerClientChromeOS>(
monitor->receiver(), monitor->media_transfer_protocol_manager());
@@ -155,10 +157,8 @@ TEST_F(MtpManagerClientChromeOSTest, BasicAttachDetach) {
EXPECT_EQ(device_id, observer().last_attached().device_id());
EXPECT_EQ(GetDeviceLocationFromStorageName(kStorageWithValidInfo),
observer().last_attached().location());
- EXPECT_EQ(base::ASCIIToUTF16(kStorageVendor),
- observer().last_attached().vendor_name());
- EXPECT_EQ(base::ASCIIToUTF16(kStorageProduct),
- observer().last_attached().model_name());
+ EXPECT_EQ(kStorageVendor16, observer().last_attached().vendor_name());
+ EXPECT_EQ(kStorageProduct16, observer().last_attached().model_name());
// Detach the attached storage.
mtp_device_observer()->MtpStorageDetached(kStorageWithValidInfo);
diff --git a/chromium/components/storage_monitor/removable_device_constants.h b/chromium/components/storage_monitor/removable_device_constants.h
index 55d92959422..cbbd6a5101d 100644
--- a/chromium/components/storage_monitor/removable_device_constants.h
+++ b/chromium/components/storage_monitor/removable_device_constants.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_STORAGE_MONITOR_REMOVABLE_DEVICE_CONSTANTS_H_
#define COMPONENTS_STORAGE_MONITOR_REMOVABLE_DEVICE_CONSTANTS_H_
-#include <string>
-
#include "base/files/file_path.h"
#include "build/build_config.h"
diff --git a/chromium/components/storage_monitor/storage_info_utils.cc b/chromium/components/storage_monitor/storage_info_utils.cc
index 0a777b3605b..49fefa18e80 100644
--- a/chromium/components/storage_monitor/storage_info_utils.cc
+++ b/chromium/components/storage_monitor/storage_info_utils.cc
@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "components/storage_monitor/removable_device_constants.h"
@@ -27,7 +28,7 @@ const char kRootPath[] = "/";
std::string GetStorageIdFromStorageName(const std::string& storage_name) {
std::vector<base::StringPiece> name_parts = base::SplitStringPiece(
storage_name, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- return name_parts.size() == 3 ? name_parts[2].as_string() : std::string();
+ return name_parts.size() == 3 ? std::string(name_parts[2]) : std::string();
}
// Returns the |data_store_id| string in the required format.
diff --git a/chromium/components/storage_monitor/storage_monitor_chromeos_unittest.cc b/chromium/components/storage_monitor/storage_monitor_chromeos_unittest.cc
index 1529bf5e26f..e3c299f4439 100644
--- a/chromium/components/storage_monitor/storage_monitor_chromeos_unittest.cc
+++ b/chromium/components/storage_monitor/storage_monitor_chromeos_unittest.cc
@@ -177,7 +177,7 @@ void StorageMonitorCrosTest::SetUp() {
DiskMountManager::InitializeForTesting(disk_mount_manager_mock_);
disk_mount_manager_mock_->SetupDefaultReplies();
- mock_storage_observer_.reset(new MockRemovableStorageObserver);
+ mock_storage_observer_ = std::make_unique<MockRemovableStorageObserver>();
// Initialize the test subject.
TestStorageMonitor::Destroy();
diff --git a/chromium/components/storage_monitor/storage_monitor_mac.mm b/chromium/components/storage_monitor/storage_monitor_mac.mm
index fe7b24f92ea..c61c5870d56 100644
--- a/chromium/components/storage_monitor/storage_monitor_mac.mm
+++ b/chromium/components/storage_monitor/storage_monitor_mac.mm
@@ -26,7 +26,7 @@ namespace storage_monitor {
namespace {
-const char kDiskImageModelName[] = "Disk Image";
+const char16_t kDiskImageModelName[] = u"Disk Image";
std::u16string GetUTF16FromDictionary(CFDictionaryRef dictionary,
CFStringRef key) {
@@ -353,9 +353,8 @@ bool StorageMonitorMac::ShouldPostNotificationForDisk(
const StorageInfo& info) const {
// Only post notifications about disks that have no empty fields and
// are removable. Also exclude disk images (DMGs).
- return !info.device_id().empty() &&
- !info.location().empty() &&
- info.model_name() != base::ASCIIToUTF16(kDiskImageModelName) &&
+ return !info.device_id().empty() && !info.location().empty() &&
+ info.model_name() != kDiskImageModelName &&
StorageInfo::IsMassStorageDevice(info.device_id());
}
diff --git a/chromium/components/storage_monitor/storage_monitor_win.cc b/chromium/components/storage_monitor/storage_monitor_win.cc
index 8844a2b7c34..3c7e7420629 100644
--- a/chromium/components/storage_monitor/storage_monitor_win.cc
+++ b/chromium/components/storage_monitor/storage_monitor_win.cc
@@ -10,6 +10,9 @@
#include <shlobj.h>
#include <stddef.h>
+#include <utility>
+#include <vector>
+
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/wrapped_window_proc.h"
@@ -25,14 +28,10 @@
namespace storage_monitor {
StorageMonitorWin::StorageMonitorWin(
- VolumeMountWatcherWin* volume_mount_watcher,
- PortableDeviceWatcherWin* portable_device_watcher)
- : window_class_(0),
- instance_(nullptr),
- window_(nullptr),
- shell_change_notify_id_(0),
- volume_mount_watcher_(volume_mount_watcher),
- portable_device_watcher_(portable_device_watcher) {
+ std::unique_ptr<VolumeMountWatcherWin> volume_mount_watcher,
+ std::unique_ptr<PortableDeviceWatcherWin> portable_device_watcher)
+ : volume_mount_watcher_(std::move(volume_mount_watcher)),
+ portable_device_watcher_(std::move(portable_device_watcher)) {
DCHECK(volume_mount_watcher_);
DCHECK(portable_device_watcher_);
volume_mount_watcher_->SetNotifications(receiver());
@@ -195,8 +194,8 @@ void StorageMonitorWin::OnMediaChange(WPARAM wparam, LPARAM lparam) {
}
StorageMonitor* StorageMonitor::CreateInternal() {
- return new StorageMonitorWin(new VolumeMountWatcherWin(),
- new PortableDeviceWatcherWin());
+ return new StorageMonitorWin(std::make_unique<VolumeMountWatcherWin>(),
+ std::make_unique<PortableDeviceWatcherWin>());
}
} // namespace storage_monitor
diff --git a/chromium/components/storage_monitor/storage_monitor_win.h b/chromium/components/storage_monitor/storage_monitor_win.h
index d0e3e425c5a..a79fd6d3a33 100644
--- a/chromium/components/storage_monitor/storage_monitor_win.h
+++ b/chromium/components/storage_monitor/storage_monitor_win.h
@@ -5,14 +5,14 @@
#ifndef COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_WIN_H_
#define COMPONENTS_STORAGE_MONITOR_STORAGE_MONITOR_WIN_H_
+#include <windows.h>
+
#include <memory>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "components/storage_monitor/storage_monitor.h"
-#include <windows.h>
-
namespace base {
class FilePath;
}
@@ -30,8 +30,9 @@ class StorageMonitorWin : public StorageMonitor {
// To support unit tests, this constructor takes |volume_mount_watcher| and
// |portable_device_watcher| objects. These params are either constructed in
// unit tests or in StorageMonitorWin CreateInternal() function.
- StorageMonitorWin(VolumeMountWatcherWin* volume_mount_watcher,
- PortableDeviceWatcherWin* portable_device_watcher);
+ StorageMonitorWin(
+ std::unique_ptr<VolumeMountWatcherWin> volume_mount_watcher,
+ std::unique_ptr<PortableDeviceWatcherWin> portable_device_watcher);
~StorageMonitorWin() override;
// Must be called after the file thread is created.
@@ -44,7 +45,6 @@ class StorageMonitorWin : public StorageMonitor {
const std::string& storage_device_id,
std::wstring* device_location,
std::wstring* storage_object_id) const override;
-
void EjectDevice(const std::string& device_id,
base::OnceCallback<void(EjectStatus)> callback) override;
@@ -69,21 +69,21 @@ class StorageMonitorWin : public StorageMonitor {
void OnMediaChange(WPARAM wparam, LPARAM lparam);
// The window class of |window_|.
- ATOM window_class_;
+ ATOM window_class_ = 0;
// The handle of the module that contains the window procedure of |window_|.
- HMODULE instance_;
- HWND window_;
+ HMODULE instance_ = nullptr;
+ HWND window_ = nullptr;
// The handle of a registration for shell notifications.
- ULONG shell_change_notify_id_;
+ ULONG shell_change_notify_id_ = 0;
// The volume mount point watcher, used to manage the mounted devices.
- std::unique_ptr<VolumeMountWatcherWin> volume_mount_watcher_;
+ const std::unique_ptr<VolumeMountWatcherWin> volume_mount_watcher_;
// The portable device watcher, used to manage media transfer protocol
// devices.
- std::unique_ptr<PortableDeviceWatcherWin> portable_device_watcher_;
+ const std::unique_ptr<PortableDeviceWatcherWin> portable_device_watcher_;
DISALLOW_COPY_AND_ASSIGN(StorageMonitorWin);
};
diff --git a/chromium/components/storage_monitor/storage_monitor_win_unittest.cc b/chromium/components/storage_monitor/storage_monitor_win_unittest.cc
index 62521e20bc9..08b73a7e7e6 100644
--- a/chromium/components/storage_monitor/storage_monitor_win_unittest.cc
+++ b/chromium/components/storage_monitor/storage_monitor_win_unittest.cc
@@ -8,6 +8,7 @@
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "base/macros.h"
@@ -84,9 +85,11 @@ StorageMonitorWinTest::~StorageMonitorWinTest() {
}
void StorageMonitorWinTest::SetUp() {
- volume_mount_watcher_ = new TestVolumeMountWatcherWin;
- monitor_.reset(new TestStorageMonitorWin(volume_mount_watcher_,
- new TestPortableDeviceWatcherWin));
+ auto volume_mount_watcher = std::make_unique<TestVolumeMountWatcherWin>();
+ volume_mount_watcher_ = volume_mount_watcher.get();
+ monitor_ = std::make_unique<TestStorageMonitorWin>(
+ std::move(volume_mount_watcher),
+ std::make_unique<TestPortableDeviceWatcherWin>());
monitor_->Init();
content::RunAllTasksUntilIdle();
@@ -104,7 +107,8 @@ void StorageMonitorWinTest::TearDown() {
void StorageMonitorWinTest::PreAttachDevices() {
monitor_.reset();
- volume_mount_watcher_ = new TestVolumeMountWatcherWin;
+ auto volume_mount_watcher = std::make_unique<TestVolumeMountWatcherWin>();
+ volume_mount_watcher_ = volume_mount_watcher.get();
volume_mount_watcher_->SetAttachedDevicesFake();
int expect_attach_calls = 0;
@@ -118,8 +122,9 @@ void StorageMonitorWinTest::PreAttachDevices() {
expect_attach_calls++;
}
- monitor_.reset(new TestStorageMonitorWin(volume_mount_watcher_,
- new TestPortableDeviceWatcherWin));
+ monitor_ = std::make_unique<TestStorageMonitorWin>(
+ std::move(volume_mount_watcher),
+ std::make_unique<TestPortableDeviceWatcherWin>());
monitor_->AddObserver(&observer_);
monitor_->Init();
diff --git a/chromium/components/storage_monitor/test_storage_monitor_win.cc b/chromium/components/storage_monitor/test_storage_monitor_win.cc
index b85aeb05ffd..601fa93341d 100644
--- a/chromium/components/storage_monitor/test_storage_monitor_win.cc
+++ b/chromium/components/storage_monitor/test_storage_monitor_win.cc
@@ -6,17 +6,20 @@
#include "components/storage_monitor/test_storage_monitor_win.h"
+#include <utility>
+
#include "components/storage_monitor/test_portable_device_watcher_win.h"
#include "components/storage_monitor/test_volume_mount_watcher_win.h"
namespace storage_monitor {
TestStorageMonitorWin::TestStorageMonitorWin(
- TestVolumeMountWatcherWin* volume_mount_watcher,
- TestPortableDeviceWatcherWin* portable_device_watcher)
- : StorageMonitorWin(volume_mount_watcher, portable_device_watcher) {
+ std::unique_ptr<TestVolumeMountWatcherWin> volume_mount_watcher,
+ std::unique_ptr<TestPortableDeviceWatcherWin> portable_device_watcher)
+ : StorageMonitorWin(std::move(volume_mount_watcher),
+ std::move(portable_device_watcher)) {
DCHECK(volume_mount_watcher_);
- DCHECK(portable_device_watcher);
+ DCHECK(portable_device_watcher_);
}
TestStorageMonitorWin::~TestStorageMonitorWin() {
diff --git a/chromium/components/storage_monitor/test_storage_monitor_win.h b/chromium/components/storage_monitor/test_storage_monitor_win.h
index 12a34baf3f9..37e4df9f4c3 100644
--- a/chromium/components/storage_monitor/test_storage_monitor_win.h
+++ b/chromium/components/storage_monitor/test_storage_monitor_win.h
@@ -10,6 +10,8 @@
#include <windows.h>
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "components/storage_monitor/storage_monitor_win.h"
@@ -22,8 +24,8 @@ class TestVolumeMountWatcherWin;
class TestStorageMonitorWin: public StorageMonitorWin {
public:
TestStorageMonitorWin(
- TestVolumeMountWatcherWin* volume_mount_watcher,
- TestPortableDeviceWatcherWin* portable_device_watcher);
+ std::unique_ptr<TestVolumeMountWatcherWin> volume_mount_watcher,
+ std::unique_ptr<TestPortableDeviceWatcherWin> portable_device_watcher);
~TestStorageMonitorWin() override;
diff --git a/chromium/components/storage_monitor/test_volume_mount_watcher_win.cc b/chromium/components/storage_monitor/test_volume_mount_watcher_win.cc
index 5e67dcfa63d..7697c001d38 100644
--- a/chromium/components/storage_monitor/test_volume_mount_watcher_win.cc
+++ b/chromium/components/storage_monitor/test_volume_mount_watcher_win.cc
@@ -6,6 +6,8 @@
#include "components/storage_monitor/test_volume_mount_watcher_win.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
@@ -116,9 +118,9 @@ void TestVolumeMountWatcherWin::DeviceCheckComplete(
}
void TestVolumeMountWatcherWin::BlockDeviceCheckForTesting() {
- device_check_complete_event_.reset(
- new base::WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED));
+ device_check_complete_event_ = std::make_unique<base::WaitableEvent>(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
devices_checked_.clear();
}
diff --git a/chromium/components/strings/components_chromium_strings_gu.xtb b/chromium/components/strings/components_chromium_strings_gu.xtb
index 733bbc7de3e..edd9987778c 100644
--- a/chromium/components/strings/components_chromium_strings_gu.xtb
+++ b/chromium/components/strings/components_chromium_strings_gu.xtb
@@ -17,7 +17,7 @@
LAN સેટિંગ
પર જાઓ અને "તમારા LAN માટે પà«àª°à«‰àª•à«àª¸à«€ સરà«àªµàª°àª¨à«‹ ઉપયોગ કરો" ચેકબૉકà«àª¸àª¥à«€ પસંદ હટાવો.</translation>
<translation id="4622039161600275920">Chromium દà«àªµàª¾àª°àª¾ આ પેજને બà«àª²à«‰àª• કરવામાં આવà«àª¯à«àª‚ છે</translation>
-<translation id="48558539577516920">Chromium ને તમારી ફાયરવોલ અથવા àªàª¨à«àªŸàª¿àªµàª¾àª¯àª°àª¸ સેટિંગà«àª¸àª®àª¾àª‚ નેટવરà«àª• àªàª•à«àª¸à«‡àª¸ કરવાની
+<translation id="48558539577516920">Chromiumને તમારા ફાયરવૉલ અથવા àªàª¨à«àªŸàª¿àªµàª¾àª¯àª°àª¸ સેટિંગમાં નેટવરà«àª• àªàª•à«àª¸à«‡àª¸ કરવાની
મંજૂરી આપો.</translation>
<translation id="580822234363523061">Chromium મેનૂ &gt;
<ph name="SETTINGS_TITLE" />
diff --git a/chromium/components/strings/components_chromium_strings_ky.xtb b/chromium/components/strings/components_chromium_strings_ky.xtb
index 521dd349f53..1ea0f6fa276 100644
--- a/chromium/components/strings/components_chromium_strings_ky.xtb
+++ b/chromium/components/strings/components_chromium_strings_ky.xtb
@@ -37,7 +37,7 @@
Эгер ушуну менен маÑеле чечилбеÑе, иштин майнаптуулугун жогорулатуу үчүн бул параметрди
кайра тандаңыз.</translation>
<translation id="8187289872471304532">Төмөнкүгө өтүңүз
- Колдонмолор &gt; Тутумдун жөндөөлөрү &gt; Тармак &gt; Өркүндөтүлгөн &gt; ПрокÑилер
+ Колдонмолор &gt; СиÑтеманын жөндөөлөрү &gt; Тармак &gt; Өркүндөтүлгөн &gt; ПрокÑилер
жана тандалган бардык прокÑилерди тандоодон чыгарыңыз.</translation>
<translation id="8684913864886094367">Chromium туура ÑÐ¼ÐµÑ Ð¶Ð°Ð±Ñ‹Ð»Ñ‹Ð¿ калды.</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/components/strings/components_chromium_strings_te.xtb b/chromium/components/strings/components_chromium_strings_te.xtb
index 54ca0a48677..1a907fc0888 100644
--- a/chromium/components/strings/components_chromium_strings_te.xtb
+++ b/chromium/components/strings/components_chromium_strings_te.xtb
@@ -2,7 +2,7 @@
<!DOCTYPE translationbundle>
<translationbundle lang="te">
<translation id="130631256467250065">మీ మారà±à°ªà±à°²à± మీరౠమీ పరికరానà±à°¨à°¿ à°ªà±à°¨à°ƒà°ªà±à°°à°¾à°°à°‚భించే తరà±à°µà°¾à°¤à°¿à°¸à°¾à°°à°¿ అమలà±à°²à±‹à°•à°¿ వసà±à°¤à°¾à°¯à°¿.</translation>
-<translation id="275588974610408078">Chromiumలో à°•à±à°°à°¾à°·à± నివేదిక à°…à°‚à°¦à±à°¬à°¾à°Ÿà±à°²à±‹ లేదà±.</translation>
+<translation id="275588974610408078">Chromiumలో à°•à±à°°à°¾à°·à± రిపోరà±à°Ÿà±â€Œ à°…à°‚à°¦à±à°¬à°¾à°Ÿà±à°²à±‹ లేదà±.</translation>
<translation id="3064346599913645280">మీరౠసà±à°°à°•à±à°·à°¿à°¤à°®à±ˆà°¨ Chromium పేజీని వీకà±à°·à°¿à°¸à±à°¤à±à°¨à±à°¨à°¾à°°à±</translation>
<translation id="3550966579244642892">Chromium OS దాని à°ªà±à°°à°¾à°¥à°®à°¿à°• సెటపà±â€Œà°¨à± పూరà±à°¤à°¿ చేయలేదà±.</translation>
<translation id="358997566136285270">Chromium లోగో</translation>
diff --git a/chromium/components/strings/components_google_chrome_strings_gu.xtb b/chromium/components/strings/components_google_chrome_strings_gu.xtb
index 5da0fefa703..00f5579db40 100644
--- a/chromium/components/strings/components_google_chrome_strings_gu.xtb
+++ b/chromium/components/strings/components_google_chrome_strings_gu.xtb
@@ -7,7 +7,7 @@
<translation id="2874156562296220396">Google Chrome <ph name="BEGIN_LINK_CHROMIUM" />Chromium<ph name="END_LINK_CHROMIUM" /> ઓપન સોરà«àª¸ પà«àª°à«‹àªœà«‡àª•à«àªŸ અને અનà«àª¯ <ph name="BEGIN_LINK_OSS" />ઓપન સોરà«àª¸ સૉફà«àªŸàªµà«‡àª°<ph name="END_LINK_OSS" /> દà«àªµàª¾àª°àª¾ સંભવ થયà«àª‚ છે.</translation>
<translation id="3140883423282498090">તમે આગલી વખત Google Chrome ને ફરીથી શરૂ કરશો તà«àª¯àª¾àª°à«‡ તમારા ફેરફારો પà«àª°àª­àª¾àªµà«€ થશે.</translation>
<translation id="3444832043240812445">જો તમે <ph name="BEGIN_LINK" />કà«àª°à«…શ રિપોરà«àªŸàª¿àª‚ગ ચાલૠકરો છો<ph name="END_LINK" /> તો આ પેજ માતà«àª° તમારા હાલનાં કà«àª°à«…શ પર માહિતી બતાવે છે</translation>
-<translation id="3875312571075912821">Chrome ને તમારી ફાયરવોલ અથવા àªàª¨à«àªŸàª¿àªµàª¾àª¯àª°àª¸ સેટિંગà«àª¸àª®àª¾àª‚ નેટવરà«àª• àªàª•à«àª¸à«‡àª¸ કરવાની
+<translation id="3875312571075912821">Chromeને તમારા ફાયરવૉલ અથવા àªàª¨à«àªŸàª¿àªµàª¾àª¯àª°àª¸ સેટિંગમાં નેટવરà«àª• àªàª•à«àª¸à«‡àª¸ કરવાની
મંજૂરી આપો.</translation>
<translation id="4010643444566880169">Chrome OSનà«àª‚ શરૂઆતનà«àª‚ સેટઅપ પૂરà«àª‚ થયà«àª‚ નથી.</translation>
<translation id="4853578032408195113">તમે àªàª• સà«àª°àª•à«àª·àª¿àª¤ Google Chrome પૃષà«àª  જોઈ રહà«àª¯àª¾àª‚ છો.</translation>
diff --git a/chromium/components/strings/components_google_chrome_strings_ky.xtb b/chromium/components/strings/components_google_chrome_strings_ky.xtb
index 1f4c21334cc..c871fd4572e 100644
--- a/chromium/components/strings/components_google_chrome_strings_ky.xtb
+++ b/chromium/components/strings/components_google_chrome_strings_ky.xtb
@@ -38,6 +38,6 @@
LAN жөндөөлөрү
жана "LAN үчүн прокÑи Ñервер колдонулÑун" параметрин алып Ñалыңыз.</translation>
<translation id="8187289872471304532">Төмөнкүгө өтүңүз
- Колдонмолор &gt; Тутумдун жөндөөлөрү &gt; Тармак &gt; Өркүндөтүлгөн &gt; ПрокÑилер
+ Колдонмолор &gt; СиÑтеманын жөндөөлөрү &gt; Тармак &gt; Өркүндөтүлгөн &gt; ПрокÑилер
жана тандалган бардык прокÑилерди тандоодон чыгарыңыз.</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/components/strings/components_google_chrome_strings_te.xtb b/chromium/components/strings/components_google_chrome_strings_te.xtb
index 37996321efc..b008bf6be30 100644
--- a/chromium/components/strings/components_google_chrome_strings_te.xtb
+++ b/chromium/components/strings/components_google_chrome_strings_te.xtb
@@ -6,7 +6,7 @@
<translation id="2588322182880276190">Chrome లోగో</translation>
<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="3444832043240812445">మీరౠ<ph name="BEGIN_LINK" />à°•à±à°°à°¾à°·à±â€Œ రిపోరà±à°Ÿà±â€Œà°¨à± à°ªà±à°°à°¾à°°à°‚భించినపà±à°¡à±<ph name="END_LINK" /> à°ˆ పేజీ మీ ఇటీవలి à°•à±à°°à°¾à°·à±â€Œà°² సమాచారానà±à°¨à°¿ మాతà±à°°à°®à±‡ చూపిసà±à°¤à±à°‚ది.</translation>
<translation id="3875312571075912821">మీ ఫైరà±â€Œà°µà°¾à°²à± లేదా యాంటీవైరసౠసెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à±à°²à±‹ నెటà±â€Œà°µà°°à±à°•à±â€Œà°¨à± యాకà±à°¸à±†à°¸à± చేయడానికి
Chromeనౠఅనà±à°®à°¤à°¿à°‚à°šà°‚à°¡à°¿.</translation>
<translation id="4010643444566880169">Chrome OS దాని à°ªà±à°°à°¾à°¥à°®à°¿à°• సెటపà±â€Œà°¨à± పూరà±à°¤à°¿ చేయలేదà±.</translation>
diff --git a/chromium/components/strings/components_strings_af.xtb b/chromium/components/strings/components_strings_af.xtb
index a727cdb5d2b..2f535013e19 100644
--- a/chromium/components/strings/components_strings_af.xtb
+++ b/chromium/components/strings/components_strings_af.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Indien gemerk, sal Chrome 'n kopie van jou kaart op hierdie toestel berg om vorms vinniger in te vul.</translation>
<translation id="1110994991967754504">Kies toestemming vir <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">Ontdoen herrangskikking</translation>
+<translation id="1123753900084781868">Intydse Onderskrifte is nie nou onmiddellik beskikbaar nie</translation>
<translation id="1125573121925420732">Waarskuwings kan algemeen wees terwyl webwerwe hul sekuriteit opdateer. Dit behoort binnekort te verbeter.</translation>
<translation id="112840717907525620">Beleidkas OK</translation>
<translation id="1130564665089811311">Vertaal Bladsy-knoppie; druk Enter om hierdie bladsy met Google Vertaal te vertaal</translation>
@@ -74,6 +75,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="1240347957665416060">Jou toestelnaam</translation>
<translation id="124116460088058876">Meer tale</translation>
<translation id="1243027604378859286">Outeur:</translation>
+<translation id="1246424317317450637">Vetdruk</translation>
<translation id="1250759482327835220">Stoor jou kaart, naam en faktureringadres in jou Google-rekening om volgende keer vinniger te betaal.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (gesinkroniseer)</translation>
<translation id="1256368399071562588">&lt;p&gt;As jy probeer om 'n webwerf te besoek en dit maak nie oop nie, kan jy eers probeer om die fout met hierdie foutsporingstappe reg te stel:&lt;/p&gt;
@@ -156,6 +158,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="1476595624592550506">Verander jou wagwoord</translation>
<translation id="1484290072879560759">Kies versendingadres</translation>
<translation id="1492194039220927094">Deurstuur van beleide:</translation>
+<translation id="1495677929897281669">Terug na oortjie</translation>
<translation id="1501859676467574491">Wys kaarte van jou Google-rekening</translation>
<translation id="1507202001669085618">&lt;p&gt;Jy sal hierdie fout sien as jy 'n Wi-Fi-portaal gebruik waar jy moet aanmeld voordat jy aanlyn kan gaan.&lt;/p&gt;
&lt;p&gt;Klik &lt;strong&gt;Koppel&lt;/strong&gt; op die bladsy wat jy probeer oopmaak om die fout reg te stel.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="1532118530259321453">Hierdie bladsy sê</translation>
<translation id="153384715582417236">Dis al vir nou</translation>
<translation id="1536390784834419204">Vertaal bladsy</translation>
+<translation id="1539840569003678498">Verslag is gestuur:</translation>
<translation id="154408704832528245">Kies afleweringadres</translation>
<translation id="1549470594296187301">JavaScript moet geaktiveer wees om hierdie kenmerk te gebruik.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="1682696192498422849">Kort kant eerste</translation>
<translation id="168693727862418163">Hierdie beleidwaarde kon nie teen die skema bekragtig word nie en sal geïgnoreer word.</translation>
<translation id="168841957122794586">Die bedienersertifikaat bevat 'n swak kriptografiese sleutel.</translation>
+<translation id="1696290444144917273">Bekyk virtuele kaart se besonderhede</translation>
<translation id="1697532407822776718">Als is nou reg!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Hierdie bediener kon nie bewys dat hy <ph name="DOMAIN" /> is nie; sy sekuriteitsertifikaat geld kwansuis van môre af. Dit is dalk veroorsaak deur 'n wanopstelling of 'n aanvaller wat jou verbinding onderskep het.}other{Hierdie bediener kon nie bewys dat hy <ph name="DOMAIN" /> is nie; sy sekuriteitsertifikaat geld kwansuis van # dae in die toekoms af. Dit is dalk veroorsaak deur 'n wanopstelling of 'n aanvaller wat jou verbinding onderskep het.}}</translation>
<translation id="1710259589646384581">Bedryfstelsel</translation>
+<translation id="1711234383449478798">Geïgnoreer omdat <ph name="POLICY_NAME" /> nie op <ph name="VALUE" /> gestel is nie.</translation>
<translation id="1712552549805331520"><ph name="URL" /> wil data permanent op jou plaaslike rekenaar berg</translation>
<translation id="1713628304598226412">Laai 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Posbus 3</translation>
<translation id="1718029547804390981">Dokument is te groot om aantekeninge by te maak</translation>
<translation id="1721424275792716183">* Veld word vereis</translation>
+<translation id="1727613060316725209">Sertifikaat is geldig</translation>
<translation id="1727741090716970331">Voeg geldige kaartnommer by</translation>
<translation id="1728677426644403582">Jy bekyk tans die bron van 'n webbladsy</translation>
<translation id="173080396488393970">Hierdie tipe kaart word nie gesteun nie</translation>
@@ -246,7 +253,6 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
vir <ph name="SITE" /> uit te voer. Werfoperateurs kan oorsprongbeleide gebruik om
sekuriteit- en ander eienskappe vir 'n werf op te stel.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Dateer asseblief jou sinkroniseringwagfrase op.</translation>
<translation id="1787142507584202372">Jou oop oortjies verskyn hier</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, veelvuldige handelinge is beskikbaar; druk Tab om deur hulle te beweeg</translation>
@@ -279,6 +285,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="1919345977826869612">Advertensies</translation>
<translation id="1919367280705858090">Kry hulp met 'n spesifieke foutboodskap</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Geen}=1{1 werf}other{# werwe}}</translation>
+<translation id="1924727005275031552">Nuut</translation>
<translation id="1945968466830820669">Jy kan toegang tot jou organisasie se rekening verloor of identiteitdiefstal ervaar. Chromium beveel aan dat jy jou wagwoord nou verander.</translation>
<translation id="1947454675006758438">Kram regs bo</translation>
<translation id="1958218078413065209">Jou hoogste telling is <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="2042213636306070719">Laai 7</translation>
<translation id="204357726431741734">Meld aan om wagwoorde te gebruik wat in jou Google-rekening gestoor is</translation>
<translation id="2053111141626950936">Bladsye in <ph name="LANGUAGE" /> sal nie vertaal word nie.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Wanneer hierdie kontrole aan is en die status aktief is, bepaal Chrome met watter groot groep mense, of "kohort", jou onlangse blaai-aktiwiteit die meeste ooreenstem. Adverteerders kan advertensies vir die groep kies en jou blaai-aktiwiteit word privaat op jou toestel gehou. Jou groep word elke dag opgedateer.}=1{Wanneer hierdie kontrole aan is en die status aktief is, bepaal Chrome met watter groot groep mense, of "kohort", jou onlangse blaai-aktiwiteit die meeste ooreenstem. Adverteerders kan advertensies vir die groep kies en jou blaai-aktiwiteit word privaat op jou toestel gehou. Jou groep word elke dag opgedateer.}other{Wanneer hierdie kontrole aan is en die status aktief is, bepaal Chrome met watter groot groep mense, of "kohort", jou onlangse blaai-aktiwiteit die meeste ooreenstem. Adverteerders kan advertensies vir die groep kies en jou blaai-aktiwiteit word privaat op jou toestel gehou. Jou groep word elke {NUM_DAYS} dae opgedateer.}}</translation>
<translation id="2053553514270667976">Poskode</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 voorstel}other{# voorstelle}}</translation>
<translation id="2071692954027939183">Kennisgewings is outomaties geblokkeer omdat jy hulle gewoonlik nie toelaat nie</translation>
<translation id="2079545284768500474">Ontdoen</translation>
<translation id="20817612488360358">Stelsel se instaanbedienerinstellings word gestel om gebruik te word, maar doelbewuste instaanbedieneropstelling word ook gespesifiseer.</translation>
<translation id="2082238445998314030">Resultaat <ph name="RESULT_NUMBER" /> van <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Stoor …</translation>
<translation id="2088086323192747268">Bestuur Sinkronisering-knoppie, druk Enter om te bestuur watter inligting jy in Chrome-instellings sinkroniseer</translation>
<translation id="2091887806945687916">Klank</translation>
<translation id="2094505752054353250">Domein stem nie ooreen nie</translation>
@@ -379,6 +388,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="2317259163369394535"><ph name="DOMAIN" /> vereis 'n gebruikernaam en wagwoord.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, verval op <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Instelling word deur jou administrateur gekontroleer</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> wil saambind</translation>
<translation id="2344028582131185878">Outomatiese aflaaie</translation>
<translation id="2346319942568447007">Prent wat jy gekopieer het</translation>
<translation id="2354001756790975382">Ander boekmerke</translation>
@@ -386,8 +396,10 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="2355395290879513365">Aanvallers sal dalk die prente kan sien waarna jy op hierdie werf kyk en jou mislei deur hulle te wysig.</translation>
<translation id="2356070529366658676">Vra</translation>
<translation id="2357481397660644965">Jou toestel word deur <ph name="DEVICE_MANAGER" /> bestuur en jou rekening word deur <ph name="ACCOUNT_MANAGER" /> bestuur.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Oor minder as 'n dag}=1{Oor 'n dag}other{Oor {NUM_DAYS} dae}}</translation>
<translation id="2359629602545592467">Veelvuldige</translation>
<translation id="2359808026110333948">Gaan voort</translation>
+<translation id="2359961752320758691">Jou virtuelekaartnommer is toegepas.</translation>
<translation id="2367567093518048410">Vlak</translation>
<translation id="2372464001869762664">Nadat jy bevestig het, sal kaartbesonderhede vanaf jou Google-rekening met hierdie werf gedeel word. Kry die CVC in jou Plex-rekeningbesonderhede.</translation>
<translation id="2380886658946992094">Wetlik</translation>
@@ -398,6 +410,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="239429038616798445">Daardie versendingmetode is nie beskikbaar nie. Probeer 'n ander metode.</translation>
<translation id="2396249848217231973">Ontdoen uitvee</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Oud</translation>
<translation id="2413528052993050574">Hierdie bediener kon nie bewys dat dit <ph name="DOMAIN" /> is nie; sy sekuriteitsertifikaat is dalk herroep. Dit kan veroorsaak word deur 'n wanopstelling of 'n aanvaller wat jou verbinding onderskep.</translation>
<translation id="2414886740292270097">Donker</translation>
<translation id="2438874542388153331">Vierpons regs</translation>
@@ -425,10 +438,10 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="2521385132275182522">Kram regs onder</translation>
<translation id="2523886232349826891">Net op hierdie toestel gestoor</translation>
<translation id="2524461107774643265">Voeg meer inligting by</translation>
-<translation id="2526590354069164005">Rekenaar</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{en nog 1}other{en nog #}}</translation>
<translation id="2536110899380797252">Voeg adres by</translation>
<translation id="2539524384386349900">Bespeur</translation>
+<translation id="2541219929084442027">Bladsye wat jy in Incognito-oortjies bekyk, sal nie in jou blaaier se geskiedenis, webkoekiestoor of soekgeskiedenis bly nadat jy al jou Incognito-oortjies toegemaak het nie. Enige lêers wat jy aflaai of boekmerke wat jy skep, sal gehou word.</translation>
<translation id="2544644783021658368">Een dokument</translation>
<translation id="254947805923345898">Beleidwaarde is nie geldig nie.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> het 'n ongeldige antwoord gestuur.</translation>
@@ -448,6 +461,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="2629325967560697240"><ph name="BEGIN_ENHANCED_PROTECTION_LINK" />Skakel gevorderde beskerming aan<ph name="END_ENHANCED_PROTECTION_LINK" /> om Chrome se hoogste vlak van beskerming te kry</translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> se bediener se IP-adres kon nie gevind word nie.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Geen versoenbare toestelle gekry nie.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, druk Tab en dan Enter om jou blaaigeskiedenis, webkoekies, kas en meer in Chrome-instellings uit te vee</translation>
<translation id="2650446666397867134">Toegang tot die leêr is geweier</translation>
@@ -494,6 +508,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="2799223571221894425">Begin weer</translation>
<translation id="2803306138276472711">Google Veiligblaai het onlangs <ph name="BEGIN_LINK" />wanware bespeur<ph name="END_LINK" /> op <ph name="SITE" />. Webwerwe wat gewoonlik veilig is, word soms met wanware besmet.</translation>
<translation id="2807052079800581569">Prent se posisie op Y-as</translation>
+<translation id="2820957248982571256">Skandeer tans …</translation>
<translation id="2824775600643448204">Adres- en soekbalk</translation>
<translation id="2826760142808435982">Die verbinding is geënkripteer en gestaaf deur <ph name="CIPHER" /> te gebruik, en gebruik <ph name="KX" /> as die sleuteluitruilmeganisme.</translation>
<translation id="2835170189407361413">Maak vorm skoon</translation>
@@ -501,6 +516,8 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="2850739647070081192">Invite (Envelope)</translation>
<translation id="2856444702002559011">Aanvallers probeer dalk om jou inligting (byvoorbeeld: wagwoorde, boodskappe of kredietkaartinligting) op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> te steel. <ph name="BEGIN_LEARN_MORE_LINK" />Kom meer te wete<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Hierdie werf wys indringerige of misleidende advertensies.</translation>
+<translation id="287596039013813457">Vriendelik</translation>
+<translation id="2876489322757410363">Verlaat tans Incognitomodus om deur 'n eksterne program te betaal. Gaan voort?</translation>
<translation id="2878197950673342043">Plakkaatvou</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Vensterplasing</translation>
@@ -550,7 +567,6 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, druk Tab en dan Enter om veiligheidskontrole in Chrome-instellings te doen</translation>
<translation id="3061707000357573562">Regstellingdiens</translation>
-<translation id="3064966200440839136">Verlaat incognito-modus om via 'n eksterne program te betaal. Gaan voort?</translation>
<translation id="306573536155379004">Speletjie het begin.</translation>
<translation id="3080254622891793721">Grafika</translation>
<translation id="3086579638707268289">Jou aktiwiteit op die web word gemonitor</translation>
@@ -573,7 +589,6 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="315504272643575312">Jou rekening word bestuur deur <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Stel terug</translation>
<translation id="3162559335345991374">Die Wi-Fi wat jy gebruik, kan vereis dat jy sy aanmeldbladsy besoek.</translation>
-<translation id="3167968892399408617">Bladsye wat jy in incognito-oortjies bekyk, sal nie in jou blaaier se geskiedenis, webkoekiewinkel of soekgeskiedenis wys nadat jy al jou incognito-oortjies toegemaak het nie. Enige lêers wat jy aflaai of boekmerk, sal gehou word.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Eiland</translation>
<translation id="3176929007561373547">Gaan jou instaanbedienerinstellings na of kontak jou netwerkadministrateur om
@@ -599,10 +614,12 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="3229041911291329567">Weergawe-inligting oor jou toestel en blaaier</translation>
<translation id="323107829343500871">Voer die CVC vir <ph name="CREDIT_CARD" /> in</translation>
<translation id="3234666976984236645">Bespeur altyd belangrike inhoud op hierdie werf</translation>
+<translation id="3249845759089040423">Fantasties</translation>
<translation id="3252266817569339921">Frans</translation>
<translation id="3266793032086590337">Waarde (konflik)</translation>
<translation id="3268451620468152448">Maak oortjies oop</translation>
<translation id="3270847123878663523">Ontdoen herrangskikking</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> wil koppel</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Jou organisasie, <ph name="ENROLLMENT_DOMAIN" />, het sommige inligting, soos instellings of beleide, na die volgende webwerwe gestuur.</translation>
<translation id="3282497668470633863">Voeg naam op kaart by</translation>
@@ -655,6 +672,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="3428151540071562330">Een of meer van die DnsOverHttpsTemplates-bedienertemplaat se URI's is ongeldig en sal nie gebruik word nie.</translation>
<translation id="3431636764301398940">Stoor hierdie kaart op hierdie toestel</translation>
<translation id="3432601291244612633">Maak bladsy toe</translation>
+<translation id="3435738964857648380">Sekuriteit</translation>
<translation id="3435896845095436175">Aktiveer</translation>
<translation id="3438829137925142401">Gebruik wagwoorde wat in jou Google-rekening gestoor is</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="3584299510153766161">Dubbelpons onder</translation>
<translation id="3586931643579894722">Versteek besonderhede</translation>
<translation id="3587738293690942763">Middel</translation>
+<translation id="3590643883886679995">Aanmelddata sal op hierdie toestel geberg word nadat jy Incognitomodus verlaat het.</translation>
+<translation id="359126217934908072">Maand/jaar:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Jy kan jou groep enige tyd terugstel. Dit neem omtrent 'n dag om by 'n nuwe groep aan te sluit.}=1{Jy kan jou groep enige tyd terugstel. Dit neem omtrent 'n dag om by 'n nuwe groep aan te sluit.}other{Jy kan jou groep enige tyd terugstel. Dit neem {NUM_DAYS} dae om by 'n nuwe groep aan te sluit.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Jou administrateur blokkeer die program</translation>
<translation id="3608932978122581043">Stroomoriëntasie</translation>
@@ -706,13 +727,13 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="3615877443314183785">Voer 'n geldige vervaldatum in</translation>
<translation id="36224234498066874">Vee blaaierdata uit …</translation>
<translation id="362276910939193118">Wys hele geskiedenis</translation>
-<translation id="3625635938337243871">Aanmelddata sal op hierdie toestel geberg word nadat jy Incognitomodus verlaat het.</translation>
<translation id="3630155396527302611">As dit reeds gelys is as 'n program wat by die netwerk mag ingaan, probeer
om dit van die lys af te verwyder en dit weer by te voeg.</translation>
<translation id="3630699740441428070">Administrateurs van hierdie toestel het jou netwerkverbinding opgestel wat hulle dalk toelaat om jou netwerkverkeer te sien, insluitend watter webwerwe jy besoek.</translation>
<translation id="3631244953324577188">Biometrie</translation>
<translation id="3633738897356909127">Dateer Chrome Op-knoppie; druk Enter om Chrome vanuit jou Chrome-instellings op te dateer</translation>
<translation id="3634530185120165534">Laai 5</translation>
+<translation id="3637662659967048211">Stoor in Google-rekening</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Program:</translation>
<translation id="3650584904733503804">Stawing suksesvol</translation>
@@ -753,6 +774,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="3781428340399460090">Helderpienk</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth-toestelle</translation>
+<translation id="3787675388804467730">Virtuele kaart se nommer</translation>
<translation id="3787705759683870569">Verval <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Grootte 16</translation>
<translation id="3789841737615482174">Installeer</translation>
@@ -772,6 +794,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="3841184659773414994">Lêerhanteerders</translation>
<translation id="385051799172605136">Terug</translation>
<translation id="3858027520442213535">Dateer datum en tyd op</translation>
+<translation id="3881478300875776315">Wys minder reëls</translation>
<translation id="3884278016824448484">Teenstrydige toestelidentifiseerder</translation>
<translation id="3885155851504623709">Gemeente</translation>
<translation id="388632593194507180">Monitering is bespeur</translation>
@@ -797,6 +820,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="397105322502079400">Bereken tans …</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> is geblokkeer</translation>
<translation id="3973357910713125165">Doen Chrome-veiligheidskontrole-knoppie; druk Enter om veiligheidskontrole in Chrome-instellings te doen</translation>
+<translation id="3986705137476756801">Skakel Intydse Onderskrifte af vir nou</translation>
<translation id="3987405730340719549">Chrome het bepaal dat hierdie werf dalk vals of bedrieglik is.
Besoek https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals as jy meen dat dit verkeerdelik gewys word.</translation>
@@ -893,13 +917,14 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="4275830172053184480">Herbegin jou toestel</translation>
<translation id="4277028893293644418">Stel wagwoord terug</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Hierdie kaart is in jou Google-rekening gestoor}other{Hierdie kaarte is in jou Google-rekening gestoor}}</translation>
+<translation id="4287885627794386150">Kwalifiseer vir proeflopie, maar nie aktief nie</translation>
<translation id="4297502707443874121">Kleinkiekie vir bladsy <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Vou uit</translation>
<translation id="4300675098767811073">Veelvuldige pons regs</translation>
<translation id="4302514097724775343">Tik op die dinosourus om te speel</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Kon nie toegang tot jou lêer kry nie</translation>
-<translation id="4305817255990598646">Skakel oor</translation>
+<translation id="4306529830550717874">Stoor adres?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokkeer (verstek)</translation>
<translation id="4314815835985389558">Bestuur sinkronisering</translation>
@@ -926,6 +951,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="4377125064752653719">Jy het probeer om <ph name="DOMAIN" /> te bereik, maar die sertifikaat wat die bediener voorgehou het, is deur sy uitreiker herroep. Dit beteken dat die sekuriteitseiebewyse wat die bediener uitgereik het, onder geen omstandighede vertrou mag word nie. Jy kommunikeer dalk met 'n aanvaller.</translation>
<translation id="4378154925671717803">Foon</translation>
<translation id="4390472908992056574">Rand</translation>
+<translation id="4406883609789734330">Intydse Onderskrifte</translation>
<translation id="4406896451731180161">soekresultate</translation>
<translation id="4408413947728134509">Webkoekies <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Jy het sopas jou wagwoord op 'n misleidende werf ingevoer. Chrome beveel aan dat jy gaan na <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> en ander werwe waarop jy hierdie wagwoord gebruik en dit nou verander.</translation>
@@ -938,7 +964,6 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Die gebruik van 'n instaanbediener is gedeaktiveer, maar 'n eksplisiete instaanbedieneropstelling word gespesifiseer.</translation>
<translation id="4464826014807964867">Webwerwe met inligting van jou organisasie</translation>
-<translation id="4466881336512663640">Vormveranderinge sal verloor word. Is jy seker jy wil voortgaan?</translation>
<translation id="4476953670630786061">Hierdie vorm is nie veilig nie. Outovul is afgeskakel.</translation>
<translation id="4477350412780666475">Volgende snit</translation>
<translation id="4482953324121162758">Hierdie werf sal nie vertaal word nie.</translation>
@@ -972,6 +997,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="4594403342090139922">Ontdoen uitvee</translation>
<translation id="4597348597567598915">Grootte 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Treffend</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Kontantterugbetaling is gekoppel</translation>
<translation id="4636930964841734540">Inligting</translation>
@@ -991,6 +1017,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Kant</translation>
+<translation id="4702656508969495934">Intydse Onderskrif sigbaar; gebruik vensterwisselaar om te fokus</translation>
<translation id="4708268264240856090">Jou verbinding is onderbreek</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Voer tans Windows Network Diagnostics uit<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="4738601419177586157"><ph name="TEXT" />-soekvoorstel</translation>
<translation id="4742407542027196863">Bestuur wagwoorde …</translation>
<translation id="4744603770635761495">Uitvoerbare pad</translation>
+<translation id="4749011317274908093">Jy is nou Incognito</translation>
<translation id="4750917950439032686">Jou inligting (byvoorbeeld, wagwoorde en kredietkaartnommers) is privaat wanneer dit na hierdie werf gestuur word.</translation>
<translation id="4756388243121344051">Geskiedenis</translation>
<translation id="4758311279753947758">Voeg kontakinligting by</translation>
@@ -1033,6 +1061,8 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="4813512666221746211">Netwerkfout</translation>
<translation id="4816492930507672669">Pas op bladsy</translation>
<translation id="4819347708020428563">Redigeer aantekeninge in verstekaansig?</translation>
+<translation id="4825507807291741242">Kragtig</translation>
+<translation id="4838327282952368871">Dromerig</translation>
<translation id="484462545196658690">Outo</translation>
<translation id="4850886885716139402">Bekyk</translation>
<translation id="485316830061041779">Duits</translation>
@@ -1169,6 +1199,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="5314967030527622926">Brosjuremaker</translation>
<translation id="5316812925700871227">Draai antikloksgewys</translation>
<translation id="5317780077021120954">Berg</translation>
+<translation id="5321288445143113935">Gemaksimeer</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> uit <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Kies kontakinligting</translation>
<translation id="5327248766486351172">Naam</translation>
@@ -1176,11 +1207,13 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="5332219387342487447">Versendingmetode</translation>
<translation id="5333022057423422993">Chrome het die wagwoord wat jy sopas gebruik het, in 'n dataskending gekry. Gaan jou gestoorde wagwoorde na om jou rekeninge te beveilig.</translation>
<translation id="5334013548165032829">Gedetailleerde stelselloglêers</translation>
+<translation id="5334145288572353250">Stoor adres?</translation>
<translation id="5340250774223869109">Program word geblokkeer</translation>
<translation id="534295439873310000">NFC-toestelle</translation>
<translation id="5344579389779391559">Hierdie bladsy kan dalk geld van jou probeer hef</translation>
<translation id="5355557959165512791">Jy kan nie <ph name="SITE" /> nou onmiddellik besoek nie omdat sy sertifikaat herroep is. Netwerkfoute is gewoonlik tydelik en daarom sal hierdie bladsy waarskynlik later werk.</translation>
<translation id="536296301121032821">Kon nie beleidinstellings stoor nie</translation>
+<translation id="5363309033720083897">Reekspoort deur jou administrateur toegelaat</translation>
<translation id="5371425731340848620">Dateer kaart op</translation>
<translation id="5377026284221673050">"Jou horlosie is agter" of "Jou horlosie is voor" of "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
<translation id="5386426401304769735">Die sertifikaatketting vir hierdie werf bevat 'n sertifikaat wat met gebruik van SHA-1 onderteken is.</translation>
@@ -1189,6 +1222,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="5398772614898833570">Advertensies is geblokkeer</translation>
<translation id="5400836586163650660">Grys</translation>
<translation id="540969355065856584">Hierdie bediener kon nie bewys dat dit <ph name="DOMAIN" /> is nie; sy sekuriteitsertifikaat is nie op die oomblik geldig nie. Dit kan veroorsaak word deur 'n wanopstelling of 'n aanvaller wat jou verbinding onderskep.</translation>
+<translation id="541143247543991491">Wolk (hele stelsel)</translation>
<translation id="541416427766103491">Stapelaar 4</translation>
<translation id="5421136146218899937">Vee blaaidata uit …</translation>
<translation id="5426179911063097041"><ph name="SITE" /> wil vir jou kennisgewings stuur</translation>
@@ -1202,6 +1236,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="5455374756549232013">Swak beleidtydstempel</translation>
<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="5463625433003343978">Soek tans toestelle …</translation>
<translation id="5469868506864199649">Italiaans</translation>
<translation id="5470861586879999274">Herdoen wysiging</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1251,7 +1286,6 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="5624120631404540903">Bestuur wagwoorde</translation>
<translation id="5629630648637658800">Kon nie beleidinstellings laai nie</translation>
<translation id="5631439013527180824">Ongeldige toestelbestuurtoken</translation>
-<translation id="5632627355679805402">Jou data is vanaf <ph name="TIME" /> met jou <ph name="BEGIN_LINK" />Google-wagwoord<ph name="END_LINK" /> geënkripteer. Voer dit in om sinkronisering te begin.</translation>
<translation id="5633066919399395251">Aanvallers wat tans op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> is, kan dalk probeer om gevaarlike programme op jou rekenaar te installeer wat jou inligting (byvoorbeeld: foto's, wagwoorde, boodskappe en kredietkaartinligting) steel of uitvee. <ph name="BEGIN_LEARN_MORE_LINK" />Kom meer te wete<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Misleidende inhoud is geblokkeer.</translation>
<translation id="5644090287519800334">Skuif prent langs X-as op kant 1</translation>
@@ -1290,12 +1324,12 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="5785756445106461925">Hierdie bladsy sluit verder ander hulpbronne in wat nie veilig is nie. Hierdie hulpbronne kan deur ander mense bekyk word terwyl hulle op pad is, en kan deur 'n aanvaller aangepas word om die bladsy se voorkoms te verander.</translation>
<translation id="5786044859038896871">Wil jy jou kaartinligting invul?</translation>
<translation id="578633867165174378">Chrome het die wagwoord wat jy sopas gebruik het, in 'n dataskending gekry. Ons beveel aan dat jy hierdie wagwoord nou verander.</translation>
-<translation id="5798290721819630480">Gooi veranderinge weg?</translation>
<translation id="5803412860119678065">Wil jy jou <ph name="CARD_DETAIL" /> invul?</translation>
<translation id="5804241973901381774">Toestemmings</translation>
<translation id="5804427196348435412">Gebruik NFC-toestelle</translation>
<translation id="5810442152076338065">Jou verbinding aan <ph name="DOMAIN" /> is geënkripteer deur 'n verouderde syferreeks te gebruik.</translation>
<translation id="5813119285467412249">Herdoen byvoeging</translation>
+<translation id="5817918615728894473">Bind saam</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Betaling sal van hierdie kaart gehef word wanneer jy betaal, maar sy regte nommer sal nie met hierdie werf gedeel word nie. 'n Tydelike CVC sal gegenereer word vir bykomende sekuriteit.}other{Betaling sal van die kaart wat jy kies gehef word wanneer jy betaal, maar sy regte nommer sal nie met hierdie werf gedeel word nie. 'n Tydelike CVC sal gegenereer word vir bykomende sekuriteit.}}</translation>
<translation id="5826507051599432481">Algemene naam (AN)</translation>
<translation id="5838278095973806738">Jy moenie enige sensitiewe inligting (byvoorbeeld, wagwoorde en kredietkaartnommers) op hierdie werf invoer nie, want aanvallers kan dit steel.</translation>
@@ -1303,6 +1337,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="5855253129151731373">Hierdie werf se gasheernaam lyk soortgelyk aan <ph name="LOOKALIKE_DOMAIN" />. Aanvallers boots soms werwe na deur klein veranderinge aan die domeinnaam te maak wat moeilik is om te sien.
Besoek https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals as jy meen dat dit verkeerdelik gewys word.</translation>
+<translation id="5860033963881614850">Af</translation>
<translation id="5862579898803147654">Stapelaar 8</translation>
<translation id="5863847714970149516">Die bladsy wat volg kan dalk geld van jou hef</translation>
<translation id="5866257070973731571">Voeg foonnommer by</translation>
@@ -1319,6 +1354,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="5913377024445952699">Skermskoot is onderbreek</translation>
<translation id="59174027418879706">Geaktiveer</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 word gebruik}other{# word gebruik}}</translation>
<translation id="5921185718311485855">Aan</translation>
<translation id="5921639886840618607">Stoor kaart in Google-rekening?</translation>
<translation id="5922853866070715753">Amper klaar</translation>
@@ -1338,6 +1374,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="5989320800837274978">Nie vaste instaanbedieners of 'n .pac-skrip-URL is gespesifiseer nie.</translation>
<translation id="5992691462791905444">Ingenieur-Z-vou</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultate vir "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Klassiek</translation>
<translation id="6008122969617370890">Volgorde: N-tot-1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Gaan jou wagwoorde na</translation>
@@ -1359,6 +1396,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="6045164183059402045">Inslaanwerktemplaat</translation>
<translation id="6047233362582046994">As jy die gevare vir jou veiligheid verstaan, kan jy <ph name="BEGIN_LINK" />hierdie werf besoek<ph name="END_LINK" /> voordat die skadelike programme verwyder is.</translation>
<translation id="6047927260846328439">Hierdie inhoud mag jou dalk probeer mislei om sagteware wat persoonlike inligting openbaar, te installeer. <ph name="BEGIN_LINK" />Wys in elk geval<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Druk en hou |<ph name="ACCELERATOR" />| om volskerm te verlaat</translation>
<translation id="6049488691372270142">Bladsylewering</translation>
<translation id="6051221802930200923">Jy kan nie <ph name="SITE" /> nou onmiddellik besoek nie omdat die webwerf sertifikaatvasspelding gebruik. Netwerkfoute en -aanvalle is gewoonlik tydelik en daarom sal hierdie bladsy waarskynlik later werk.</translation>
<translation id="6051898664905071243">Aantal bladsye:</translation>
@@ -1375,6 +1413,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="610911394827799129">Jou Google-rekening kan dalk ander vorme van blaaigeskiedenis hê by <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">Sien teks en prente wat na die knipbord gekopieer is</translation>
<translation id="6120179357481664955">Onthou jy jou UPI-ID?</translation>
+<translation id="6123290840358279103">Bekyk virtuele kaart</translation>
<translation id="6124432979022149706">Chrome Enterprise-verbinders</translation>
<translation id="6146055958333702838">Gaan alle kabels na en herselflaai enige roeteerders, modems of ander
netwerktoestelle wat jy gebruik.</translation>
@@ -1411,6 +1450,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="6289939620939689042">Bladsykleur</translation>
<translation id="6290238015253830360">Jou voorgestelde artikels verskyn hier</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google Assistent in Chrome stop tans</translation>
<translation id="6305205051461490394"><ph name="URL" /> is onbereikbaar.</translation>
<translation id="6312113039770857350">Webbladsy is nie beskikbaar nie</translation>
@@ -1436,6 +1476,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="6390200185239044127">Halwe Z-vou</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Administrateurbeleid blokkeer plak van <ph name="ORIGIN_NAME" /> af na hierdie ligging toe</translation>
+<translation id="6398765197997659313">Gaan by volskerm uit</translation>
<translation id="6401136357288658127">Hierdie beleid is opgeskort. Jy moet liewer die <ph name="NEW_POLICY" />-beleid gebruik.</translation>
<translation id="6404511346730675251">Wysig boekmerk</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1448,7 +1489,6 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="6428450836711225518">Verifieer jou foonnommer</translation>
<translation id="6433490469411711332">Wysig kontakinligting</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> het geweier om te koppel.</translation>
-<translation id="6434309073475700221">Gooi weg</translation>
<translation id="6440503408713884761">Geïgnoreer</translation>
<translation id="6443406338865242315">Watter uitbreidings en inproppe jy geïnstalleer het</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1491,6 +1531,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="6624427990725312378">Kontakinligting</translation>
<translation id="6626291197371920147">Voeg geldige kaartnommer by</translation>
<translation id="6628463337424475685"><ph name="ENGINE" />-soektog</translation>
+<translation id="6630043285902923878">Soek tans USB-toestelle …</translation>
<translation id="6630809736994426279">Aanvallers wat tans op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> is, kan probeer om gevaarlike programme op jou Mac te installeer wat jou inligting (byvoorbeeld: foto's, wagwoorde, boodskappe en kredietkaartinligting) steel of uitvee. <ph name="BEGIN_LEARN_MORE_LINK" />Kom meer te wete<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Vee uit</translation>
@@ -1506,6 +1547,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="6671697161687535275">Verwyder vormvoorstel uit Chromium?</translation>
<translation id="6685834062052613830">Meld af en voltooi opstelling</translation>
<translation id="6687335167692595844">Lettertipegrootte versoek</translation>
+<translation id="6688743156324860098">Dateer op …</translation>
<translation id="6689249931105087298">Relatief met swartpuntsaampersing</translation>
<translation id="6689271823431384964">Chrome bied aan om jou kaarte in jou Google-rekening te stoor omdat jy aangemeld is. Jy kan hierdie gedrag in instellings verander. Die kaarthouernaam kom van jou rekening af.</translation>
<translation id="6698381487523150993">Geskep:</translation>
@@ -1521,6 +1563,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="6744009308914054259">Terwyl jy vir 'n verbinding wag, kan jy Aflaaie besoek om vanlyn artikels te lees.</translation>
<translation id="6753269504797312559">Beleidwaarde</translation>
<translation id="6757797048963528358">Jou toestel het gaan slaap.</translation>
+<translation id="6767985426384634228">Dateer adres op?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Pers</translation>
@@ -1543,6 +1586,7 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome het hierdie bladsy vereenvoudig om dit makliker te maak om te lees. Chrome het die oorspronklike bladsy oor 'n onveilige verbinding gaan haal.</translation>
<translation id="6891596781022320156">Beleidvlak word nie gesteun nie.</translation>
+<translation id="6895143722905299846">Virtuele nommer:</translation>
<translation id="6895330447102777224">Jou kaart is bevestig</translation>
<translation id="6897140037006041989">Gebruikeragent</translation>
<translation id="6898699227549475383">Organisasie (O)</translation>
@@ -1578,10 +1622,10 @@ Dit sal andersins deur jou privaatheidinstellings geblokkeer word. Dit sal die i
<translation id="7004583254764674281">Gebruik Windows Hello om kaarte vinniger te bevestig</translation>
<translation id="7006930604109697472">Stuur in elk geval</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Grootteverandering-instellings</translation>
<translation id="7014741021609395734">Zoemvlak</translation>
<translation id="7016992613359344582">Hierdie heffings kan eenmalig of herhalend wees en is dalk nie ooglopend nie.</translation>
<translation id="7029809446516969842">Wagwoorde</translation>
+<translation id="7030436163253143341">Sertifikaat is nie geldig nie</translation>
<translation id="7031646650991750659">Watter Google Play-programme jy geïnstalleer het</translation>
<translation id="7050187094878475250">Jy het <ph name="DOMAIN" /> probeer bereik, maar die bediener het 'n sertifikaat aangebied waarvan die geldigheidtydperk te lank is om betroubaar te wees.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Hierdie kaart kan nie op die oomblik gestoor word nie}other{Hierdie kaarte kan nie op die oomblik gestoor word nie}}</translation>
@@ -1651,12 +1695,14 @@ Bykomende besonderhede:
<translation id="7300012071106347854">Kobaltblou</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Hoog</translation>
+<translation id="7305756307268530424">Begin stadiger</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Verbindinghulp</translation>
<translation id="7323804146520582233">Versteek die "<ph name="SECTION" />"-afdeling</translation>
<translation id="733354035281974745">Toestel se plaaslike rekening is geïgnoreer</translation>
<translation id="7333654844024768166">Jy het sopas jou wagwoord op 'n misleidende werf ingevoer. Chromium beveel aan dat jy gaan na <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> en ander werwe waarop jy hierdie wagwoord gebruik en dit nou verander.</translation>
<translation id="7334320624316649418">Herdoen herrangskikking</translation>
+<translation id="7337248890521463931">Wys meer reëls</translation>
<translation id="7337706099755338005">Nie op jou platform beskikbaar nie.</translation>
<translation id="733923710415886693">Hierdie bediener se sertifikaat is nie via sertifikaatdeursigtigheid openbaar gemaak nie.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1664,6 +1710,7 @@ Bykomende besonderhede:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Bevellyn</translation>
<translation id="7359588939039777303">Advertensies is geblokkeer.</translation>
+<translation id="7363096869660964304">Jy is egter nie onsigbaar nie. As jy Incognito is, versteek dit nie jou blaaihandelinge vir jou werkgewer, jou internetdiensverskaffer of die webwerwe wat jy besoek nie.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, druk Tab en dan Enter om adresse in Chrome-instellings by te voeg en te bestuur</translation>
<translation id="7365849542400970216">Weet wanneer jy toestel gebruik?</translation>
<translation id="7372973238305370288">soekresultaat</translation>
@@ -1674,7 +1721,9 @@ Bykomende besonderhede:
<translation id="7378594059915113390">Media-kontroles</translation>
<translation id="7378627244592794276">Nee</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Nie van toepassing nie</translation>
<translation id="7390545607259442187">Bevestig kaart</translation>
+<translation id="7392089738299859607">Dateer adres op</translation>
<translation id="7399802613464275309">Veiligheidskontrole</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Jou <ph name="DEVICE_NAME" /> word bestuur</translation>
@@ -1689,6 +1738,7 @@ Bykomende besonderhede:
&lt;li&gt;Besoek die &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome-hulpsentrum&lt;/a&gt;
om uit te vind hoe om die sagteware permanent van jou rekenaar te verwyder&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Lieflik</translation>
<translation id="7416351320495623771">Bestuur wagwoorde …</translation>
<translation id="7419106976560586862">Profielpad</translation>
<translation id="7437289804838430631">Voeg kontakinligting by</translation>
@@ -1704,7 +1754,7 @@ om uit te vind hoe om die sagteware permanent van jou rekenaar te verwyder&lt;/o
<translation id="7481312909269577407">Vorentoe</translation>
<translation id="7485870689360869515">Geen data gevind nie.</translation>
<translation id="7495528107193238112">Hierdie inhoud is geblokkeer. Kontak die werfeienaar om die kwessie reg te stel.</translation>
-<translation id="7498234416455752244">Hou aan wysig</translation>
+<translation id="7498193950643227031">Dit kan anders as verwag werk as die grootte verander word. Jy kan nou in <ph name="SETTINGS" /> die vermoë beperk om programme se grootte te verander.</translation>
<translation id="7503664977220660814">Jy het sopas jou wagwoord op 'n misleidende werf ingevoer. Chromium beveel aan dat jy jou gestoorde wagwoorde vir <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> en ander werwe waar jy hierdie wagwoord gebruik, nou nagaan.</translation>
<translation id="7508255263130623398">Teruggestuurde beleidtoestel-ID is leeg of stem nie met huidige toestel-ID ooreen nie</translation>
<translation id="7508870219247277067">Avokadogroen</translation>
@@ -1724,6 +1774,7 @@ om uit te vind hoe om die sagteware permanent van jou rekenaar te verwyder&lt;/o
<translation id="7548892272833184391">Stel verbindingfoute reg</translation>
<translation id="7549584377607005141">Hierdie webbladsy vereis data wat jy vroeër ingevoer het om behoorlik gewys te word. Jy kan hierdie data weer stuur, maar deur dit te doen, herhaal jy enige handeling wat hierdie bladsy voorheen uitgevoer het.</translation>
<translation id="7550637293666041147">Jou toestelgebruikernaam en Chrome-gebruikernaam</translation>
+<translation id="755279583747225797">Proeflopie is aktief</translation>
<translation id="7552846755917812628">Probeer die volgende wenke:</translation>
<translation id="7554475479213504905">Herlaai en wys in elk geval</translation>
<translation id="7554791636758816595">Nuwe oortjie</translation>
@@ -1742,7 +1793,6 @@ om uit te vind hoe om die sagteware permanent van jou rekenaar te verwyder&lt;/o
<translation id="7610193165460212391">Waarde is buite die reeks <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Verval: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, druk Tab en dan Enter om jou wagwoorde in Chrome-instellings te bekyk en te bestuur</translation>
-<translation id="7615602087246926389">Jy het reeds data wat geënkripteer is deur 'n ander weergawe van jou Google-rekeningwagwoord te gebruik. Voer dit asseblief hieronder in.</translation>
<translation id="7616645509853975347">Jou administrateur het Chrome Enterprise Connectors op jou blaaier aangeskakel. Hierdie verbinders het toegang tot van jou data.</translation>
<translation id="7619838219691048931">Eindbladsy</translation>
<translation id="762844065391966283">Een vir een</translation>
@@ -1807,13 +1857,12 @@ om uit te vind hoe om die sagteware permanent van jou rekenaar te verwyder&lt;/o
<translation id="782886543891417279">Die Wi-Fi wat jy gebruik (<ph name="WIFI_NAME" />), kan vereis dat jy sy aanmeldbladsy besoek.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Geen}=1{1 program (<ph name="EXAMPLE_APP_1" />)}=2{2 programme (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# programme (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Jy is egter nie onsigbaar nie. As jy incognito is, versteek dit nie jou blaaihandelinge vir jou werkgewer, jou internetdiensverskaffer of die webwerwe wat jy besoek nie.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Maak lêers met lêertipe-assosiasies oop.</translation>
<translation id="7862185352068345852">Verlaat werf?</translation>
<translation id="7865448901209910068">Beste spoed</translation>
<translation id="7874263914261512992">Jy het sopas jou wagwoord op 'n misleidende werf ingevoer. Chrome beveel aan dat jy jou gestoorde wagwoorde vir <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> en ander werwe waar jy hierdie wagwoord gebruik, nou nagaan.</translation>
<translation id="7878562273885520351">Jou wagwoord is dalk in gevaar</translation>
+<translation id="7880146494886811634">Stoor adres</translation>
<translation id="7882421473871500483">Bruin</translation>
<translation id="7887683347370398519">Gaan jou CVC na en probeer weer</translation>
<translation id="7887885240995164102">Gaan na prent-in-prent</translation>
@@ -1821,6 +1870,7 @@ om uit te vind hoe om die sagteware permanent van jou rekenaar te verwyder&lt;/o
<translation id="7894280532028510793">As die spelling korrek is, kan jy <ph name="BEGIN_LINK" />Netwerkdiagnostiek probeer gebruik<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Onbekend</translation>
+<translation id="793209273132572360">Dateer adres op?</translation>
<translation id="7932579305932748336">Bestryk</translation>
<translation id="79338296614623784">Voer 'n geldige foonnommer in</translation>
<translation id="7934052535022478634">Betaling voltooi</translation>
@@ -1891,6 +1941,7 @@ om uit te vind hoe om die sagteware permanent van jou rekenaar te verwyder&lt;/o
<translation id="8175796834047840627">Chrome bied aan om jou kaarte in jou Google-rekening te stoor omdat jy aangemeld is. Jy kan hierdie gedrag in instellings verander.</translation>
<translation id="8176440868214972690">Die administrateur van hierdie toestel het sommige inligting, soos instellings of beleide, na die volgende webwerwe gestuur.</translation>
<translation id="8184538546369750125">Gebruik globale verstek (Laat toe)</translation>
+<translation id="8193086767630290324">Handelinge uitgevoer met data wat as vertroulik gevlag is</translation>
<translation id="8194797478851900357">Ontdoen skuif</translation>
<translation id="8201077131113104583">Ongeldige opdatering-URL vir uitbreiding met ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Bestellingopsomming</translation>
@@ -1913,6 +1964,7 @@ om uit te vind hoe om die sagteware permanent van jou rekenaar te verwyder&lt;/o
<translation id="8249296373107784235">Staak</translation>
<translation id="8249320324621329438">Laas gehaal:</translation>
<translation id="8253091569723639551">Faktureringadres word vereis</translation>
+<translation id="8257387598443225809">Hierdie program is vir mobiele toestelle ontwerp</translation>
<translation id="825929999321470778">Wys alle gestoorde wagwoorde</translation>
<translation id="8261506727792406068">Vee uit</translation>
<translation id="8262952874573525464">Randhegting onder</translation>
@@ -2036,7 +2088,6 @@ Bykomende besonderhede:
<translation id="8719528812645237045">Veelvuldige pons bo</translation>
<translation id="8725066075913043281">Probeer weer</translation>
<translation id="8726549941689275341">Bladsygrootte:</translation>
-<translation id="8728672262656704056">Jy is nou incognito.</translation>
<translation id="8730621377337864115">Gedoen</translation>
<translation id="8731544501227493793">Bestuur Wagwoorde-knoppie; druk Enter om jou wagwoorde in Chrome-instellings te bekyk en te bestuur</translation>
<translation id="8734529307927223492">Jou <ph name="DEVICE_TYPE" /> word bestuur deur <ph name="MANAGER" /></translation>
@@ -2113,6 +2164,7 @@ Bykomende besonderhede:
<translation id="9020542370529661692">Hierdie bladsy is in <ph name="TARGET_LANGUAGE" /> vertaal</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Ongeldig)</translation>
+<translation id="9030265603405983977">Eenkleurig</translation>
<translation id="9035022520814077154">Sekuriteitsfout</translation>
<translation id="9038649477754266430">Gebruik 'n voorspellingdiens om bladsye vinniger te laai</translation>
<translation id="9039213469156557790">Hierdie bladsy sluit verder ander hulpbronne in wat nie veilig is nie. Hierdie hulpbronne kan deur ander mense bekyk word terwyl hulle op pad is, en kan deur 'n aanvaller aangepas word om die bladsy se gedrag te verander.</translation>
@@ -2136,6 +2188,7 @@ Bykomende besonderhede:
<translation id="91108059142052966">Administrateursbeleid deaktiveer skermdeling met <ph name="APPLICATION_TITLE" /> wanneer vertroulike inhoud sigbaar is</translation>
<translation id="9114524666733003316">Bevestig tans kaart …</translation>
<translation id="9114581008513152754">Hierdie blaaier word nie deur 'n maatskappy of ander organisasie bestuur nie. Aktiwiteit op hierdie toestel kan buite Chrome bestuur word. <ph name="BEGIN_LINK" />Kom meer te wete<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Vars</translation>
<translation id="9119042192571987207">Opgelaai</translation>
<translation id="9128016270925453879">Beleide is gelaai</translation>
<translation id="9128870381267983090">Koppel aan netwerk</translation>
@@ -2154,6 +2207,7 @@ Bykomende besonderhede:
<translation id="9170848237812810038">Ontdoen</translation>
<translation id="9171296965991013597">Verlaat program?</translation>
<translation id="9173282814238175921">Een dokument/Nuwe bladsy</translation>
+<translation id="9173995187295789444">Soek tans na Bluetooth-toestelle …</translation>
<translation id="917450738466192189">Bedienersertifikaat is ongeldig.</translation>
<translation id="9174917557437862841">Oortjiewisselingknoppie, druk Enter om na hierdie oortjie toe te wissel</translation>
<translation id="9179703756951298733">Bestuur jou betalings en kredietkaartinligting in Chrome-instellings</translation>
diff --git a/chromium/components/strings/components_strings_am.xtb b/chromium/components/strings/components_strings_am.xtb
index b52f4160539..52f4421e58e 100644
--- a/chromium/components/strings/components_strings_am.xtb
+++ b/chromium/components/strings/components_strings_am.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">áˆáˆáŠ­á‰µ ከተደረገበትᣠChrome ለተሻለ áˆáŒ£áŠ• የቅጽ አሞላሠየካርድዎን ቅጂ በዚህ መሣሪያ ላይ ያከማቻáˆá¢</translation>
<translation id="1110994991967754504">ለ<ph name="PERMISSION_NAME" /> áˆá‰ƒá‹µ አቀናብር</translation>
<translation id="1113869188872983271">&amp;እንደገና ደርድርን ቀáˆá‰¥áˆµ</translation>
+<translation id="1123753900084781868">የቀጥታ መáŒáˆˆáŒ« ጽሑá አáˆáŠ• ላይ አይገáŠáˆ</translation>
<translation id="1125573121925420732">ማስጠንቀቂያዎች ድርጣቢያዎች የእáŠáˆ­áˆ±áŠ• ደህንáŠá‰µ በሚያዘáˆáŠ‘በት ጊዜ የተለመዱ ሊሆኑ ይችላሉᢠይህ በቅርቡ መሻሻሠአለበትá¢</translation>
<translation id="112840717907525620">የመáˆáˆªá‹« መሸጎጫ እሺ</translation>
<translation id="1130564665089811311">የገጽ ተርጉሠአá‹áˆ«áˆ­á£ ይህን ገጽ በGoogle ትርጉሠለመተርጎሠአስገባን ይጫኑá¢</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">የእርስዎ የመሣሪያ ስáˆ</translation>
<translation id="124116460088058876">ተጨማሪ ቋንቋዎች</translation>
<translation id="1243027604378859286">ደራሲá¦</translation>
+<translation id="1246424317317450637">ደማቅ</translation>
<translation id="1250759482327835220">በሚቀጥለዠጊዜ በበለጠ áጥáŠá‰µ ለመክáˆáˆ ካርድዎን እና የማስከáˆá‹« አድራሻዎን በGoogle መለያዎ ላይ ያስቀáˆáŒ¡á¢</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />ᣠ<ph name="TYPE_2" /> (ሰáˆáˆ¯áˆ)</translation>
<translation id="1256368399071562588">&lt;p&gt;አንድ ድር ጣቢያ ለመጎብኘት ሞክረዠአáˆáŠ¨áˆá‰µ ካለ መጀመሪያ ስህተቱን በእáŠá‹šáˆ… መላ መáˆáˆˆáŒŠá‹« ደረጃዎች ለመáታት ይሞክሩá¦&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">የይለá ቃáˆá‹ŽáŠ• ይቀይሩ</translation>
<translation id="1484290072879560759">የመላኪያ አድራሻ á‹­áˆáˆ¨áŒ¡</translation>
<translation id="1492194039220927094">የመመሪያዎች áŒáŠá‰µá¦</translation>
+<translation id="1495677929897281669">ወደ ትር ተመለስ</translation>
<translation id="1501859676467574491">ከእርስዎ የGoogle መለያ ካርዶችን አሳይ</translation>
<translation id="1507202001669085618">&lt;p&gt;መስመር ላይ መሆን ከመቻáˆá‹Ž በáŠá‰µ በመለያ መáŒá‰£á‰µ የሚያስáˆáˆáŒá‰ á‰µ የWi-Fi መáŒá‰¢á‹« እየተጠቀሙ ከሆኑ ይህን ስህተት ይመለከታሉá¢&lt;/p&gt;
&lt;p&gt;ይህን ስህተት ለመáታት ለመክáˆá‰µ እየሞከሩ ባለዠገጽ ላይ &lt;strong&gt;ተገናáŠ&lt;/strong&gt;ን ጠቅ ያድርጉá¢&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">ይህ ገጽ እንዲህ ይላáˆá¦</translation>
<translation id="153384715582417236">ለአáˆáŠ• ያለዠይኸዠáŠá‹</translation>
<translation id="1536390784834419204">ገጽ ተርጉáˆ</translation>
+<translation id="1539840569003678498">ሪá–ርት ተáˆáŠ³áˆá¦</translation>
<translation id="154408704832528245">የማድረሻ አድራሻ á‹­áˆáˆ¨áŒ¡</translation>
<translation id="1549470594296187301">ይህን ባህሪ ለመጠቀሠጃቫስክሪá•á‰µ መንቃት አለበትá¢</translation>
<translation id="155039086686388498">áˆáˆ•áŠ•á‹µáˆµáŠ“-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">አጭር ጠርዠመጀመሪያ</translation>
<translation id="168693727862418163">ይህ የመመሪያ እሴት ከዕቅዱ ጋር ሲተያይ ማረጋገጥ አáˆá‰»áˆˆáˆá£ እና ችላ ይባላáˆá¢</translation>
<translation id="168841957122794586">የአገáˆáŒ‹á‹­ እá‹á‰…ና ማረጋገጫዠደካማ የሆአባለስá‹áˆ­ መረጃ á‰áˆá áŠá‹ ያለá‹á¢</translation>
+<translation id="1696290444144917273">áˆáŠ“ባዊ የካርድ á‹áˆ­á‹áˆ®á‰½áŠ• ይመáˆáŠ¨á‰±</translation>
<translation id="1697532407822776718">በቃ ጨርሰዋáˆ!</translation>
<translation id="1703835215927279855">ደብዳቤ</translation>
<translation id="1706954506755087368">{1,plural, =1{ይህ አገáˆáŒ‹á‹­ <ph name="DOMAIN" /> እንደሆአማረጋገጥ አáˆá‰»áˆˆáˆá¤ የደህንáŠá‰µ ማረጋገጫ እá‹á‰…ና ማረጋገጫዠከáŠáŒˆ የመጣ áŠá‹ ይላáˆá¢ ይሄ በተሳሳተ አወቃቀር ወይሠአንድ አጥቂ áŒáŠ•áŠ™áŠá‰µá‹ŽáŠ• በመጥለበየተከሰተ ሊሆን ይችላáˆá¢}one{ይህ አገáˆáŒ‹á‹­ <ph name="DOMAIN" /> እንደሆአማረጋገጥ አáˆá‰»áˆˆáˆá¤ የደህንáŠá‰µ ማረጋገጫ እá‹á‰…ና ማረጋገጫዠየወደáŠá‰µ # ቀንኖች የመጣ áŠá‹ ይላáˆá¢ ይሄ በተሳሳተ አወቃቀር ወይሠአንድ አጥቂ áŒáŠ•áŠ™áŠá‰µá‹ŽáŠ• በመጥለበየተከሰተ ሊሆን ይችላáˆá¢}other{ይህ አገáˆáŒ‹á‹­ <ph name="DOMAIN" /> እንደሆአማረጋገጥ አáˆá‰»áˆˆáˆá¤ የደህንáŠá‰µ ማረጋገጫ እá‹á‰…ና ማረጋገጫዠየወደáŠá‰µ # ቀንኖች የመጣ áŠá‹ ይላáˆá¢ ይሄ በተሳሳተ አወቃቀር ወይሠአንድ አጥቂ áŒáŠ•áŠ™áŠá‰µá‹ŽáŠ• በመጥለበየተከሰተ ሊሆን ይችላáˆá¢}}</translation>
<translation id="1710259589646384581">ስርዓተ ክወና</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> ወደ <ph name="VALUE" /> ስላáˆá‰°á‰€áŠ“በረ ችላ ተብáˆáˆá¢</translation>
<translation id="1712552549805331520"><ph name="URL" /> á‹áˆ‚ብ በአካባቢያዊ ኮáˆá’á‹á‰°áˆ­á‹Ž ላይ እስከመጨረሻዠማከማቸት á‹­áˆáˆáŒ‹áˆ</translation>
<translation id="1713628304598226412">መሳቢያ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">የመáˆá‹•áŠ­á‰µ ሳጥን 3</translation>
<translation id="1718029547804390981">ሰáŠá‹µ ለመብራራት ከáˆáŠ­ በላይ ትáˆá‰… áŠá‹</translation>
<translation id="1721424275792716183">* መስክ ያስáˆáˆáŒ‹áˆ</translation>
+<translation id="1727613060316725209">የዕá‹á‰…ና ማረጋገጫ áˆáŠ­ የሆአáŠá‹</translation>
<translation id="1727741090716970331">የሚሰራ የካርድ á‰áŒ¥áˆ­ ያክሉ</translation>
<translation id="1728677426644403582">የአንድ ድረ-ገጽ áˆáŠ•áŒ­ እየተመለከቱ áŠá‹</translation>
<translation id="173080396488393970">የዚህ á‹“á‹­áŠá‰± ካርድ አይደገááˆ</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />የWindows አá‹á‰³áˆ¨ መረብ መመርመሪያá‹áŠ• ለማሄድ ይሞክሩ<ph name="END_LINK" />á¢</translation>
<translation id="1772163372082567643">እየሄዱበት ያለዠአገáˆáŒ‹á‹­ <ph name="ORIGIN" /> ወደ እሱ በሚደረጉ áˆáˆ‰áˆ ጥያቄዎች ላይ የáˆáŠ•áŒ­ መመሪያ እንዲተገብር የሚáˆáˆáŒ ራስጌ አቀናብሯáˆá¢ áŠáŒˆáˆ­ áŒáŠ• ራስጌዠየተበላሸ áŠá‹á£ ይህ አሳሹ <ph name="SITE" /> ጥያቄዎን እንዳያሟላ ይከለክለዋáˆá¢ የáˆáŠ•áŒ­ መመሪያዎች በጣቢያ ሥርዓት ከዋáŠáŠžá‰½ የደኅንáŠá‰µ እና ሌላ ባሕሪያትን ለጣቢያዠለማዋቀር ጥቅሠላይ ሊá‹áˆ ይችላáˆá¢</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">እባክዎ የማመሳሰሠይለá áˆáˆ¨áŒá‹ŽáŠ• ያዘáˆáŠ‘á¢</translation>
<translation id="1787142507584202372">የእርስዎ ክáት ትሮች እዚህ ይመጣሉ</translation>
<translation id="1791429645902722292">Google ዘመናዊ á‰áˆá</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />ᣠርካታ እርáˆáŒƒá‹Žá‰½ ይገኛሉᣠበእáŠáˆ± á‹áˆµáŒ¥ ለማሰስ ትርን ይጫኑ</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">ማስታወቂያዎች</translation>
<translation id="1919367280705858090">በአንድ የተወሰአየስህተት መáˆá‹•áŠ­á‰µ ላይ እገዛ á‹«áŒáŠ™</translation>
<translation id="192020519938775529">{COUNT,plural, =0{áˆáŠ•áˆ}=1{1 ጣቢያ}one{# ጣቢያዎች}other{# ጣቢያዎች}}</translation>
+<translation id="1924727005275031552">አዲስ</translation>
<translation id="1945968466830820669">የድርጅት መለያዎን መዳረሻ ሊያጡ ወይሠየማንáŠá‰µ ስርቆት ሊያጋጥመዎት ይችላሉᢠChromium የይለá ቃáˆá‹ŽáŠ• አáˆáŠ• እንዲቀይሩ ይመክራáˆá¢</translation>
<translation id="1947454675006758438">በቀአበኩሠስቴá•áˆˆáˆ­ áˆá‰³</translation>
<translation id="1958218078413065209">የእርስዎ ከáተኛ á‹áŒ¤á‰µ <ph name="SCORE" /> áŠá‹á¢</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">መሳቢያ 7</translation>
<translation id="204357726431741734">በእርስዎ Google መለያ á‹áˆµáŒ¥ የተከማቹ የይለá ቃላትን ለመጠቀሠይáŒá‰¡</translation>
<translation id="2053111141626950936">በ<ph name="LANGUAGE" /> ያሉ ገጾች አይተረጎሙáˆá¢</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{ይህ መቆጣጠሪያ ሲበራ እና áˆáŠ”ታዠንበሲሆን Chrome የቅርብ ጊዜ የአሰሳ እንቅስቃሴዎ ከየትኛዠየብዙ ሰዎች ስብስብ ወይሠ«የተመሳሳይ ሰዎች ስብስቦች» ጋር በጣሠእንደሚቀራረብ ይወስናáˆá¢ ማስታወቂያ ሰሪዎች ለቡድኑ ማስታወቂያዎችን መáˆáˆ¨áŒ¥ ይችላሉᣠእንዲáˆáˆ የአሰሳ እንቅስቃሴዎ በመሣሪያዎ ላይ በáŒáˆ ሆኖ ይቀመጣáˆá¢ የእርስዎ ቡድን በየቀኑ ይዘáˆáŠ“áˆá¢}=1{ይህ መቆጣጠሪያ ሲበራ እና áˆáŠ”ታዠንበሲሆን Chrome የቅርብ ጊዜ የአሰሳ እንቅስቃሴዎ ከየትኛዠየብዙ ሰዎች ስብስብ ወይሠ«የተመሳሳይ ሰዎች ስብስቦች» ጋር በጣሠእንደሚቀራረብ ይወስናáˆá¢ ማስታወቂያ ሰሪዎች ለቡድኑ ማስታወቂያዎችን መáˆáˆ¨áŒ¥ ይችላሉᣠእንዲáˆáˆ የአሰሳ እንቅስቃሴዎ በመሣሪያዎ ላይ በáŒáˆ ሆኖ ይቀመጣáˆá¢ የእርስዎ ቡድን በየቀኑ ይዘáˆáŠ“áˆá¢}one{ይህ መቆጣጠሪያ ሲበራ እና áˆáŠ”ታዠንበሲሆን Chrome የቅርብ ጊዜ የአሰሳ እንቅስቃሴዎ ከየትኛዠየብዙ ሰዎች ስብስብ ወይሠ«የተመሳሳይ ሰዎች ስብስቦች» ጋር በጣሠእንደሚቀራረብ ይወስናáˆá¢ ማስታወቂያ ሰሪዎች ለቡድኑ ማስታወቂያዎችን መáˆáˆ¨áŒ¥ ይችላሉᣠእንዲáˆáˆ የአሰሳ እንቅስቃሴዎ በመሣሪያዎ ላይ በáŒáˆ ሆኖ ይቀመጣáˆá¢ የእርስዎ ቡድን በየ{NUM_DAYS} ቀኖች ይዘመናáˆá¢}other{ይህ መቆጣጠሪያ ሲበራ እና áˆáŠ”ታዠንበሲሆን Chrome የቅርብ ጊዜ የአሰሳ እንቅስቃሴዎ ከየትኛዠየብዙ ሰዎች ስብስብ ወይሠ«የተመሳሳይ ሰዎች ስብስቦች» ጋር በጣሠእንደሚቀራረብ ይወስናáˆá¢ ማስታወቂያ ሰሪዎች ለቡድኑ ማስታወቂያዎችን መáˆáˆ¨áŒ¥ ይችላሉᣠእንዲáˆáˆ የአሰሳ እንቅስቃሴዎ በመሣሪያዎ ላይ በáŒáˆ ሆኖ ይቀመጣáˆá¢ የእርስዎ ቡድን በየ{NUM_DAYS} ቀኖች ይዘመናáˆá¢}}</translation>
<translation id="2053553514270667976">ዚᕠኮድ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 የአስተያየት ጥቆማ}one{# የአስተያየት ጥቆማዎች}other{# የአስተያየት ጥቆማዎች}}</translation>
<translation id="2071692954027939183">ማሳወቂያዎች ብዙá‹áŠ• ጊዜ ስለማይáˆá‰…ዱáˆá‰¸á‹ በራስ-ሰር ታáŒá‹°á‹‹áˆ</translation>
<translation id="2079545284768500474">ቀáˆá‰¥áˆµ</translation>
<translation id="20817612488360358">የስርዓት ተኪ ቅንብሮች ስራ ላይ እንዲá‹áˆ‰ ተቀናብረዋሠáŒáŠ• áŒáˆáŒ½ የሆአየተኪ á‹á‰…ርሠተገáˆáŒ¿áˆá¢</translation>
<translation id="2082238445998314030">á‹áŒ¤á‰µ <ph name="RESULT_NUMBER" /> ከ<ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">አስቀáˆáŒ¥â€¦</translation>
<translation id="2088086323192747268">የአስáˆáˆ­ አá‹áˆ«áˆ­áŠ• ያቀናብሩᣠበChrome ቅንብሮች á‹áˆµáŒ¥ áˆáŠ• መረጃ እንደሚያሰáˆáˆ© ለማቀናበር አስገባን ይጫኑ</translation>
<translation id="2091887806945687916">ድáˆá…</translation>
<translation id="2094505752054353250">የጎራ አለመዛመድ</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> የተጠቃሚ ስሠእና የይለá ቃሠያስáˆáˆáŒˆá‹‹áˆá¢</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />ᣠበ<ph name="EXPIRATION_DATE_ABBR" /> አገáˆáŒáˆŽá‰µ ጊዜዠያበቃáˆ</translation>
<translation id="2337852623177822836">ቅንብር በአስተዳዳሪዎ áŠá‹ á‰áŒ¥áŒ¥áˆ­ የሚደረáŒá‰ á‰µ</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> መጣመር á‹­áˆáˆáŒ‹áˆ</translation>
<translation id="2344028582131185878">የራስ ሰር ማá‹áˆ¨á‹¶á‰½</translation>
<translation id="2346319942568447007">እርስዎ የቀዱት áˆáˆµáˆ</translation>
<translation id="2354001756790975382">ሌላ እáˆá‰£á‰¶á‰½</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">አጥቂዎች በዚህ ጣቢያ ላይ እርስዎ እየተመለከቱዋቸዠያሉ áˆáˆµáˆŽá‰½áŠ• ማየት እና በላያቸዠላይ ለá‹áŒ¦á‰½áŠ• በማድረጠሊያታáˆáˆá‹Žá‰µ ይችሉ ይሆናáˆá¢</translation>
<translation id="2356070529366658676">ጠይቅ</translation>
<translation id="2357481397660644965">የእርስዎ መሣሪያ የሚተዳደረዠበ<ph name="DEVICE_MANAGER" /> ሲሆን መለያዎ የሚተዳደረዠበ<ph name="ACCOUNT_MANAGER" /> áŠá‹á¢</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ከአንድ ቀን ባáŠáˆ° ጊዜ á‹áˆµáŒ¥}=1{በአንድ ቀን á‹áˆµáŒ¥}one{በ{NUM_DAYS} ቀኖች á‹áˆµáŒ¥}other{በ{NUM_DAYS} ቀኖች á‹áˆµáŒ¥}}</translation>
<translation id="2359629602545592467">በርካታ</translation>
<translation id="2359808026110333948">ቀጥáˆ</translation>
+<translation id="2359961752320758691">የእርስዎ áˆáŠ“ባዊ ካርድ á‰áŒ¥áˆ­ ተተáŒá‰¥áˆ¯áˆá¢</translation>
<translation id="2367567093518048410">ደረጃ</translation>
<translation id="2372464001869762664">ካረጋገጡ በኋላ የGoogle መለያዎ ካርድ á‹áˆ­á‹áˆ®á‰½ ለዚህ ጣቢያ ይጋራሉᢠበእርስዎ Plex መለያ á‹áˆ­á‹áˆ®á‰½ á‹áˆµáŒ¥ CVC á‹«áŒáŠ™á¢</translation>
<translation id="2380886658946992094">የሕáŒ</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">ይህ የመላኪያ ዘዴ አይገáŠáˆá¢ የተለየ ዘዴ ይሞክሩá¢</translation>
<translation id="2396249848217231973">&amp;ስረዛን ቀáˆá‰¥áˆµ</translation>
<translation id="2410754574180102685">መንáŒáˆµá‰µ-የህáŒ</translation>
+<translation id="2413155254802890957">የቆየ</translation>
<translation id="2413528052993050574">ይህ አገáˆáŒ‹á‹­ <ph name="DOMAIN" /> መሆኑን ሊያረጋáŒáŒ¥ አáˆá‰»áˆˆáˆá¤ የደህንáŠá‰µ እá‹á‰…ና ማረጋገጫዠተሽሮ ሊሆን ይችላáˆá¢ ይሄ በተሳሳተ አወቃቀር ወይሠአንድ አጥቂ áŒáŠ•áŠ™áŠá‰µá‹ŽáŠ• በመጥለበየተከሰተ ሊሆን ይችላáˆá¢</translation>
<translation id="2414886740292270097">ጨለማ</translation>
<translation id="2438874542388153331">በቀአበኩሠአራቴ ብሳ</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">ከáŒáˆ«áŒŒ በቀአበኩሠስቴá•áˆˆáˆ­ áˆá‰³</translation>
<translation id="2523886232349826891">በዚህ መሣሪያ ላይ ብቻ ይቀመጣáˆ</translation>
<translation id="2524461107774643265">ተጨማሪ መረጃ ያክሉ</translation>
-<translation id="2526590354069164005">ዴስክቶá•</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{እና 1 ተጨማሪ}one{እና # ተጨማሪ}other{እና # ተጨማሪ}}</translation>
<translation id="2536110899380797252">አድራሻ ያክሉ</translation>
<translation id="2539524384386349900">አáŒáŠ</translation>
+<translation id="2541219929084442027">ማንáŠá‰µáŠ• በማያሳá‹á‰… ትሮች á‹áˆµáŒ¥ የሚያዩዋቸዠገጾች áˆáˆ‰áŠ•áˆ ማንáŠá‰µ የማያሳá‹á‰ ትሮችዎን ከዘጉ በኋላ በአሳሽዎ ታሪክᣠየኩኪ ማከማቻᣠወይሠየáለጋ ታሪክ á‹áˆµáŒ¥ አይቀመጡáˆá¢ ማንáŠá‰µ በማያስá‹á‰… áˆáŠá‰³ መሥራት የሌሎች ሰዎችᣠአገáˆáŒ‹á‹®á‰½á£ ሶáትዌሮች ወይሠከጀርባዎ በቆሙ የሌሎች ሰዎች ባህሪ ላይ ለá‹áŒ¥ አያመጣáˆá¢</translation>
<translation id="2544644783021658368">áŠáŒ áˆ‹ ሰáŠá‹µ</translation>
<translation id="254947805923345898">የመመሪያ እሴት የሚሰራ አይደለáˆá¢</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> áˆáŠ­ á‹«áˆáŠ¾áŠ áˆáˆ‹áˆ½ áˆáŠ³áˆá¢</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">የChrome ከáተኛዠየደህንáŠá‰µ ደረጃን ለማáŒáŠ˜á‰µ <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />የተሻሻለá‹áŠ• ጥበቃ ያብሩ<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">የ<ph name="HOST_NAME" /> አገáˆáŒ‹á‹­ አይᒠአድራሻ ሊገአአáˆá‰»áˆˆáˆá¢</translation>
<translation id="2639739919103226564">áˆáŠ”ታá¦</translation>
+<translation id="264810637653812429">áˆáŠ•áˆ ተኳሃአመሣሪያዎች አáˆá‰°áŒˆáŠ™áˆá¢</translation>
<translation id="2649204054376361687"><ph name="CITY" />ᣠ<ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />ᣠየእርስዎን የአሰሳ ታሪክᣠኩኪዎችᣠመሸጎጫ እና ተጨማሪ áŠáŒˆáˆ®á‰½ ለማጽዳት ትርን ይጫኑᣠከዚያ በChrome ቅንብሮች á‹áˆµáŒ¥ አስገባን ይጫኑ</translation>
<translation id="2650446666397867134">የá‹á‹­áˆ‰ መዳረሻ ተከáˆáŠ­áˆáˆ</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">ዳáŒáˆ አስጀáˆáˆ­</translation>
<translation id="2803306138276472711">Google የጥንቃቄ አሰሳ በቅርብ ጊዜ <ph name="SITE" /> ላይ <ph name="BEGIN_LINK" />ተንኮáˆ-አዘሠዌር<ph name="END_LINK" /> አáŒáŠá‰·áˆá¢ በመደበኛ ጊዜ ደህንáŠá‰³á‰¸á‹ የተጠበበድር ጣቢያዎች አንዳንድ ጊዜ በተንኮáˆ-አዘሠዌር ይጠቃሉá¢</translation>
<translation id="2807052079800581569">የáˆáˆµáˆ Y አቀማመጥ</translation>
+<translation id="2820957248982571256">በመቃኘት ላይ...</translation>
<translation id="2824775600643448204">የአድራሻ እና áለጋ አሞሌ</translation>
<translation id="2826760142808435982">áŒáŠ•áŠ™áŠá‰± የተመሰጠረ እና <ph name="CIPHER" />ን በመጠቀሠየተረጋገጠ áŠá‹á£ እና <ph name="KX" />ን እንደ የá‰áˆá መቀያየሪያ ስáˆá‰µ ይጠቀáˆá‰ á‰³áˆá¢</translation>
<translation id="2835170189407361413">ቅጽ አጽዳ</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">áŒá‰¥á‹£ (የደብዳቤ á–ስታ)</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="2859806420264540918">ይህ ጣቢያ ረባሽ ወይሠአሳሳች ማስታወቂያዎችን ያሳያáˆá¢</translation>
+<translation id="287596039013813457">የወዳጅáŠá‰µ</translation>
+<translation id="2876489322757410363">በá‹áŒ«á‹Š ማከማቻ በኩሠለማጫወት ማንáŠá‰µ ከማያሳá‹á‰… áˆáŠá‰³ በመá‹áŒ£á‰µ ላይᢠይቀጥáˆ?</translation>
<translation id="2878197950673342043">የá–ስተር እጥá‹á‰µ</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">የመስኮት áˆá‹°á‰£</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">C9 (የደብዳቤ á–ስታ)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />ᣠበ Chrome ቅንብሮች á‹áˆµáŒ¥ የደህንáŠá‰µ áተሻን ለማሄድ ትርን ከዚያ አስገባን ይጫኑ</translation>
<translation id="3061707000357573562">የመጠገኛ አገáˆáŒáˆŽá‰µ</translation>
-<translation id="3064966200440839136">በá‹áŒ«á‹Š ማከማቻ በኩሠለማጫወት ማንáŠá‰µ ከማያሳá‹á‰… áˆáŠá‰³ በመá‹áŒ£á‰µ ላይᢠይቀጥáˆ?</translation>
<translation id="306573536155379004">ጨዋታዠተጀáˆáˆ¯áˆá¢</translation>
<translation id="3080254622891793721">áŒáˆ«áŠáŠ­</translation>
<translation id="3086579638707268289">የእርስዎ በድር ላይ ያለ እንቅስቃሴ ክትትሠእየተደረገበት áŠá‹</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">የእርስዎ መለያ በ<ph name="MANAGER" /> áŠá‹ የሚተዳደረá‹á¢</translation>
<translation id="3157931365184549694">እáŠá‰ áˆ¨á‰ á‰µ መáˆáˆµ</translation>
<translation id="3162559335345991374">እየተጠቀሙ ያሉት Wi-Fi በመለያ መáŒá‰¢á‹« ገጹን እንዲጎበኙ ሊጠይቅዎት ይችላáˆá¢</translation>
-<translation id="3167968892399408617">ማንáŠá‰µáŠ• በማያሳá‹á‰… ትሮች á‹áˆµáŒ¥ የሚያዩዋቸዠገጾች áˆáˆ‰áŠ•áˆ ማንáŠá‰µ የማያሳá‹á‰ ትሮችዎን ከዘጉ በኋላ በአሳሽዎ ታሪክᣠየኩኪ ማከማቻᣠወይሠየáለጋ ታሪክ á‹áˆµáŒ¥ አይቀመጡáˆá¢ ማንáŠá‰µ በማያስá‹á‰… áˆáŠá‰³ መሥራት የሌሎች ሰዎችᣠአገáˆáŒ‹á‹®á‰½á£ ሶáትዌሮች ወይሠከጀርባዎ የቆሙ የሌሎች ሰዎች ባህሪይ ላይ ለá‹áŒ¥ አያመጣáˆá¢</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">ደሴት</translation>
<translation id="3176929007561373547">ተኪ አገáˆáŒ‹á‹© በአáŒá‰£á‰¡ እየሰራ መሆኑን ለማረጋገጥ የተኪ ቅንብሮችዎን á‹­áˆá‰µáˆ¹ ወይሠየአá‹á‰³áˆ¨
@@ -592,10 +607,12 @@
<translation id="3229041911291329567">የእርስዎ መሣሪያ እና አሳሽ የስሪት መረጃ</translation>
<translation id="323107829343500871">የ<ph name="CREDIT_CARD" /> ሲቪሲ ያስገቡ</translation>
<translation id="3234666976984236645">áˆáˆáŒŠá‹œ በዚህ ጣቢያ ላይ ያለ አስáˆáˆ‹áŒŠ ይዘትን አáŒáŠ</translation>
+<translation id="3249845759089040423">ቅጥ ያለá‹</translation>
<translation id="3252266817569339921">áˆáˆ¨áŠ•áˆ³á‹­áŠ›</translation>
<translation id="3266793032086590337">እሴት (áŒáŒ­á‰µ)</translation>
<translation id="3268451620468152448">ክáት ትሮች</translation>
<translation id="3270847123878663523">&amp;ዳáŒáˆ ደርድርን ቀáˆá‰¥áˆµ</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> መገናኘት á‹­áˆáˆáŒ‹áˆ</translation>
<translation id="3274521967729236597">á“-ካይ</translation>
<translation id="3282085321714087552">ድርጅትዎ <ph name="ENROLLMENT_DOMAIN" /> እንደ ቅንብሮች ወይሠመመሪያዎች ላሉት ለሚከተሉት ድር ጣቢያዎች የተወሰአመረጃ áˆáŠ³áˆá¢</translation>
<translation id="3282497668470633863">በካርድ ላይ ስሠያክሉ</translation>
@@ -648,6 +665,7 @@
<translation id="3428151540071562330">አንድ ወይሠተጨማሪ የDnsOverHttpsTemplates አገáˆáŒ‹á‹­ ቅንብር ደንብ ዩአርአዮች áˆáŠ­ á‹«áˆáˆ†áŠ‘ ናቸá‹á£ እና ስራ ላይ አይá‹áˆ‰áˆá¢</translation>
<translation id="3431636764301398940">ይህን ካርድ ወደዚህ መሣሪያ አስቀáˆáŒ¥</translation>
<translation id="3432601291244612633">ገጽ á‹­á‹áŒ‰</translation>
+<translation id="3435738964857648380">የደህንáŠá‰µ ጥበቃ</translation>
<translation id="3435896845095436175">አንቃ</translation>
<translation id="3438829137925142401">በእርስዎ የGoogle መለያ á‹áˆµáŒ¥ የተቀመጡ የይለá ቃሎችን ይጠቀሙ</translation>
<translation id="3443726618221119081">áŒáˆ®-ኩ-ካይ</translation>
@@ -690,7 +708,10 @@
<translation id="3584299510153766161">ድርብ ብስ ከታች</translation>
<translation id="3586931643579894722">á‹áˆ­á‹áˆ­ ደብቅ</translation>
<translation id="3587738293690942763">መሃáˆ</translation>
+<translation id="3590643883886679995">ከማንáŠá‰µáŠ• የማያሳá‹á‰… áˆáŠá‰³ ከወጡ በኋላ በዚህ መሣሪያ á‹áˆµáŒ¥ የመለያ መáŒá‰¢á‹« á‹áˆ‚ብ ይከማቻáˆá¢</translation>
+<translation id="359126217934908072">ወር/ዓመትá¦</translation>
<translation id="3592413004129370115">ጣáˆá‹«áŠ•áŠ› (የደብዳቤ á–ስታ)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{ቡድንዎን በማንኛá‹áˆ ጊዜ ዳáŒáˆ ማስጀመር ይችላሉᢠአዲስ ቡድን ለመቀላቀሠአንድ ቀን ያህሠጊዜ ይወስዳáˆá¢}=1{ቡድንዎን በማንኛá‹áˆ ጊዜ ዳáŒáˆ ማስጀመር ይችላሉᢠአዲስ ቡድን ለመቀላቀሠአንድ ቀን ያህሠጊዜ ይወስዳáˆá¢}one{ቡድንዎን በማንኛá‹áˆ ጊዜ ዳáŒáˆ ማስጀመር ይችላሉᢠአዲስ ቡድን ለመቀላቀሠ{NUM_DAYS} ቀኖች ያህሠጊዜ ይወስዳáˆá¢}other{ቡድንዎን በማንኛá‹áˆ ጊዜ ዳáŒáˆ ማስጀመር ይችላሉᢠአዲስ ቡድን ለመቀላቀሠ{NUM_DAYS} ቀኖች ያህሠጊዜ ይወስዳáˆá¢}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />ᣠ<ph name="DOMAIN" />ᣠ<ph name="TIME" /></translation>
<translation id="3603507503523709">መተáŒá‰ áˆªá‹« በእርስዎ አስተዳዳሪ ታáŒá‹·áˆ</translation>
<translation id="3608932978122581043">የáˆáŒˆá‰£ አቀማመጥ</translation>
@@ -699,13 +720,13 @@
<translation id="3615877443314183785">ትክክለኛ የአገáˆáŒáˆŽá‰µ ማብቂያ ቀን ያስገቡ</translation>
<translation id="36224234498066874">የአሰሳ á‹áˆ‚ብ አስወáŒá‹µâ€¦</translation>
<translation id="362276910939193118">ሙሉ ታሪክ አሳይ</translation>
-<translation id="3625635938337243871">ከማንáŠá‰µáŠ• የማያሳá‹á‰… áˆáŠá‰³ ከወጡ በኋላ በዚህ መሣሪያ á‹áˆµáŒ¥ በመለያ መáŒá‰¢á‹« á‹áˆ‚ብ ይከማቻáˆá¢</translation>
<translation id="3630155396527302611">አá‹á‰³áˆ¨ መረቡ እንዲደርስ የተáˆá‰€á‹°áˆˆá‰µ መሣሪያ áŠá‹ ተብሎ አስቀድሞ ከተዘረዘረ ከá‹áˆ­á‹áˆ©
አስወáŒá‹°á‹ እንደገና ለማከሠይሞክሩá¢</translation>
<translation id="3630699740441428070">የዚህ መሣሪያ አስተዳዳሪዎች የአá‹á‰³áˆ¨ መረብዎን áŒáŠ•áŠ™áŠá‰µ አዋቅረá‹á‰³áˆá£ ይህሠየትኛዎቹን ድር ጣቢያዎች እንደጎበኙ ጨáˆáˆ® የአá‹á‰³áˆ¨ መረብዎን ትራáŠáŠ­ እንዲመለከቱ ያስችላቸዋáˆá¢</translation>
<translation id="3631244953324577188">ባዮሜትሪክስ</translation>
<translation id="3633738897356909127">የChrome አá‹áˆ«áˆ­áŠ• ያዘáˆáŠ‘ᣠChromeን ለማዘመን ከእርስዎ Chrome ቅንብሮች ሆáŠá‹ አስገባን ይጫኑ</translation>
<translation id="3634530185120165534">መሳቢያ 5</translation>
+<translation id="3637662659967048211">ወደ Google መለያ አስቀáˆáŒ¥</translation>
<translation id="3640766068866876100">መረጃ ጠቋሚ-4x6-Ext</translation>
<translation id="3642638418806704195">መተáŒá‰ áˆªá‹«á¦</translation>
<translation id="3650584904733503804">ማረጋገጥ ተሳክቷáˆ</translation>
@@ -746,6 +767,7 @@
<translation id="3781428340399460090">ደመቅ ያለ ሮá‹</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">የብሉቱዠመሣሪያዎች</translation>
+<translation id="3787675388804467730">áˆáŠ“ባዊ የካርድ á‰áŒ¥áˆ­</translation>
<translation id="3787705759683870569">በ<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> ላይ የአገáˆáŒáˆŽá‰µ ጊዜዠያበቃáˆ</translation>
<translation id="3789155188480882154">መጠን 16</translation>
<translation id="3789841737615482174">ጫን </translation>
@@ -765,6 +787,7 @@
<translation id="3841184659773414994">የá‹á‹­áˆ ተቆጣጣሪዎች</translation>
<translation id="385051799172605136">ተመለስ</translation>
<translation id="3858027520442213535">ቀን እና ሰዓትን አዘáˆáŠ•</translation>
+<translation id="3881478300875776315">á‹«áŠáˆ± መስመሮችን አሳይ</translation>
<translation id="3884278016824448484">የሚጋጭ የመሣሪያ ለዪ</translation>
<translation id="3885155851504623709">á“ሪሽ</translation>
<translation id="388632593194507180">ክትትሠእንዳለ ተደርሶበታáˆ</translation>
@@ -790,6 +813,7 @@
<translation id="397105322502079400">በማስላት ላይ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ታáŒá‹·áˆ</translation>
<translation id="3973357910713125165">በChrome ቅንብሮች á‹áˆµáŒ¥ የደህንáŠá‰µ áተሻን ለማሄድ የChrome ደህንáŠá‰µ áተሻ á‰áˆáን ያሂዱᣠከዚያ አስገባን ይጫኑ</translation>
+<translation id="3986705137476756801">ለአáˆáŠ• የቀጥታ መáŒáˆˆáŒ« ጽሑáን አጥá‹</translation>
<translation id="3987405730340719549">Chrome ይህ ጣቢያ áˆáˆ°á‰°áŠ› ወይሠአጭበርባሪ ሊሆን እንደሚችሠወስኗáˆá¢
ይህ የሚታየዠበስህተት áŠá‹ ብለዠካሰቡ እባክዎ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals ይጎብኙá¢</translation>
@@ -883,13 +907,14 @@
<translation id="4275830172053184480">መሣሪያዎን ዳáŒáˆ ያስጀáˆáˆ©</translation>
<translation id="4277028893293644418">የይለá ቃሠዳáŒáˆ አቀናብር</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ይህ ካርድ በእርስዎ የGoogle መለያ ላይ ተቀáˆáŒ§áˆ}one{እáŠá‹šáˆ… ካርዶች በእርስዎ የGoogle መለያ ላይ ተቀáˆáŒ á‹‹áˆ}other{እáŠá‹šáˆ… ካርዶች በእርስዎ የGoogle መለያ ላይ ተቀáˆáŒ á‹‹áˆ}}</translation>
+<translation id="4287885627794386150">ለሙከራ ብበáŠá‹á£ áŠáŒˆáˆ­ áŒáŠ• ንበአይደለáˆ</translation>
<translation id="4297502707443874121">የገጽ <ph name="THUMBNAIL_PAGE" /> ድንክዬ</translation>
<translation id="42981349822642051">ዘርጋ</translation>
<translation id="4300675098767811073">በርካታ ብስ ቀáŠ</translation>
<translation id="4302514097724775343">ለማጫወት ዲኖá‹áŠ• መታ ያድርጉ</translation>
<translation id="4302965934281694568">Chou3 (የደብዳቤ á–ስታ)</translation>
<translation id="4305666528087210886">የእርስዎ á‹á‹­áˆ ሊደርስበት አáˆá‰°á‰»áˆˆáˆ</translation>
-<translation id="4305817255990598646">ቀይር</translation>
+<translation id="4306529830550717874">አድራሻ ይቀመጥ?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">አáŒá‹µ (áŠá‰£áˆª)</translation>
<translation id="4314815835985389558">ስáˆáˆ¨á‰µáŠ• ያቀናብሩ</translation>
@@ -916,6 +941,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" />ን ለመድረስ ሞክረዋáˆá£ áŠáŒˆáˆ­ áŒáŠ• አገáˆáŒ‹á‹© ያቀረበዠየእá‹á‰…ና ማረጋገጫ በሰጪዠተሽሯáˆá¢ ይህ ማለት አገáˆáŒ‹á‹© ያቀረበዠየደህንáŠá‰µ áˆáˆµáŠ­áˆ­áŠá‰¶á‰½ áˆáŒ½áˆž ሊታመኑ አይገባáˆá¢ ከአጥቂ ጋር እየተገናኙ ሊሆን ይችላáˆá¢</translation>
<translation id="4378154925671717803">ስáˆáŠ­</translation>
<translation id="4390472908992056574">ከáˆá</translation>
+<translation id="4406883609789734330">የቀጥታ ስርጭት መáŒáˆˆáŒ« ጽሑá</translation>
<translation id="4406896451731180161">የáለጋ á‹áŒ¤á‰¶á‰½</translation>
<translation id="4408413947728134509">ኩኪዎች <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">አáˆáŠ• የይለá ቃáˆá‹ŽáŠ• በአንድ አታላይ ጣቢያ ላይ አስገብተዋáˆá¢ Chrome ወደ <ph name="WEBSITE_1" />ᣠ<ph name="WEBSITE_2" />ᣠ<ph name="WEBSITE_3" /> እና ይህን የይለá ቃሠበሚጠቀሙባቸዠሌሎች ጣቢያዎች ሄደዠአáˆáŠ‘ኑ እንዲለá‹áŒ¡á‰µ ይመክራáˆá¢</translation>
@@ -928,7 +954,6 @@
<translation id="4435702339979719576">የá–ስታ ካርድ)</translation>
<translation id="443673843213245140">የተኪ መጠቀሠተሰናክáˆáˆ áŒáŠ• áŒáˆáŒ½ የሆአየተኪ á‹á‰…ር ተገáˆáŒ¿áˆá¢</translation>
<translation id="4464826014807964867">ከድርጅትዎ መረጃ ያላቸዠድርጣቢያዎች</translation>
-<translation id="4466881336512663640">የቅጽ ለá‹áŒ¦á‰½ ይጠá‹áˆ‰á¢ እርáŒáŒ áŠ› áŠá‹Žá‰µ መቀጠሠይáˆáˆáŒ‹áˆ‰?</translation>
<translation id="4476953670630786061">ይህ ቅጽ ደህንáŠá‰± የተጠበቀ አይደለáˆá¢ ራስ-ሙላ ጠáቷáˆá¢</translation>
<translation id="4477350412780666475">ቀጣይ ትራክ</translation>
<translation id="4482953324121162758">ይህ ጣቢያ አይተረጎáˆáˆá¢</translation>
@@ -962,6 +987,7 @@
<translation id="4594403342090139922">&amp;ሰርá‹áŠ• ቀáˆá‰¥áˆµ</translation>
<translation id="4597348597567598915">መጠን 8</translation>
<translation id="4600854749408232102">C6/C5 (የደብዳቤ á–ስታ)</translation>
+<translation id="4606870351894164739">ተጽዕኖ áˆáŒ£áˆª</translation>
<translation id="4628948037717959914">áŽá‰¶</translation>
<translation id="4631649115723685955">ከተመላሽ ገንዘብ ጋር ተገናáŠá‰·áˆ</translation>
<translation id="4636930964841734540">መረጃ</translation>
@@ -981,6 +1007,7 @@
<translation id="4691835149146451662">ስáŠ-ሕንጻ-A (የደብዳቤ á–ስታ)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">ጎን</translation>
+<translation id="4702656508969495934">የቀጥታ መáŒáˆˆáŒ« ጽሑá ይታያáˆá£ ለትኩረት መስኮት መቀየሪያን ይጠቀሙ</translation>
<translation id="4708268264240856090">የእርስዎ áŒáŠ•áŠ™áŠá‰µ ተቋርጧáˆ</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />የWindows አá‹á‰³áˆ¨ መረብ መመርመሪያን በማሄድ ላይ<ph name="END_LINK" /></translation>
@@ -994,6 +1021,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> የáለጋ አስተያየት ጥቆማ</translation>
<translation id="4742407542027196863">የይለá ቃላትን ያስተዳድሩ...</translation>
<translation id="4744603770635761495">የሚáˆáŒ¸áˆ ዱካ</translation>
+<translation id="4749011317274908093">ወደ ማንáŠá‰µ የማያሳá‹á‰… áˆáŠá‰³ ሄደዋáˆ</translation>
<translation id="4750917950439032686">የእርስዎ መረጃ (ለáˆáˆ³áˆŒá¦ የይለá ቃሎች ወይሠየክሬዲት ካርድ á‰áŒ¥áˆ®á‰½) ወደዚህ ጣቢያ በሚላክበት ጊዜ የáŒáˆ áŠá‹á¢</translation>
<translation id="4756388243121344051">&amp;ታሪክ</translation>
<translation id="4758311279753947758">የእá‹á‰‚á‹« መረጃን ያክሉ</translation>
@@ -1023,6 +1051,8 @@
<translation id="4813512666221746211">የአá‹á‰³áˆ¨ መረብ ስህተት</translation>
<translation id="4816492930507672669">ገጹን አመጣጥን</translation>
<translation id="4819347708020428563">በáŠá‰£áˆª እይታ á‹áˆµáŒ¥ ማብራሪያዎችን ያርትዑ?</translation>
+<translation id="4825507807291741242">ኃይለኛ</translation>
+<translation id="4838327282952368871">ህáˆáˆ˜áŠ›</translation>
<translation id="484462545196658690">ራስ-ሰር</translation>
<translation id="4850886885716139402">አሳይ</translation>
<translation id="485316830061041779">ጀርመን</translation>
@@ -1034,7 +1064,7 @@
<translation id="4879491255372875719">ራስ-ሰር (áŠá‰£áˆª)</translation>
<translation id="4879725228911483934">በእርስዎ ማያ ገጾች ላይ መስኮቶችን ይክáˆá‰± እና ይመድቡ</translation>
<translation id="4880827082731008257">የáለጋ ታሪክ</translation>
-<translation id="4881695831933465202">ክáˆá‰µ</translation>
+<translation id="4881695831933465202">ክáት የሚሆንባቸá‹</translation>
<translation id="4885256590493466218">ከáሎ መá‹áŒ«á‹ ላይ በ<ph name="CARD_DETAIL" /> ይክáˆáˆ‰</translation>
<translation id="4889420713887366944">ማንáŠá‰µ የማያሳá‹á‰… መስኮት አá‹áˆ«áˆ­áŠ• ይክáˆá‰±á£ በáŒáˆ እንዲያስሱ አዲስ ማንáŠá‰µ የማያሳá‹á‰… መስኮትን ለመክáˆá‰µ አስገባን ይጫኑ</translation>
<translation id="4892518386797173871">የኋላ</translation>
@@ -1159,6 +1189,7 @@
<translation id="5314967030527622926">የአáŠáˆ°á‰°áŠ› መጽáˆá መሥሪያ</translation>
<translation id="5316812925700871227">በተቃራኒ ሰዓት አቅጣጫ አሽከርክር</translation>
<translation id="5317780077021120954">አስቀáˆáŒ¥</translation>
+<translation id="5321288445143113935">ሰáቷáˆ</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />ᣠ<ph name="MATCH_POSITION" /> ከ<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">የእá‹á‰‚á‹« መረጃ á‹­áˆáˆ¨áŒ¡</translation>
<translation id="5327248766486351172">ስáˆ</translation>
@@ -1166,11 +1197,13 @@
<translation id="5332219387342487447">የመላኪያ መንገድ</translation>
<translation id="5333022057423422993">Chrome እርስዎ አáˆáŠ• የተጠቀሙበትን የይለá ቃሠበá‹áˆ‚ብ ጥሰት á‹áˆµáŒ¥ አáŒáŠá‰·áˆá¢ የመለያዎችዎን ደህንáŠá‰µ ለማስጠበቅ የተቀመጡ የይለá ቃላትዎን እንዲáˆá‰µáˆ¹ እንመክራለንá¢</translation>
<translation id="5334013548165032829">á‹áˆ­á‹áˆ­ የስርዓት áˆá‹áŒá‰¥ ማስታወሻዎች</translation>
+<translation id="5334145288572353250">አድራሻ ይቀመጥ?</translation>
<translation id="5340250774223869109">መተáŒá‰ áˆªá‹« ታáŒá‹·áˆ</translation>
<translation id="534295439873310000">የNFC መሣሪያዎች</translation>
<translation id="5344579389779391559">ይህ ገጽ እርስዎን ገንዘብ ለማስከáˆáˆ ሊሞክር ይችላáˆ</translation>
<translation id="5355557959165512791">የዕá‹á‰…ና ማረጋገጫዠስለተሻረ <ph name="SITE" />ን መጎብኘት አይችሉáˆá¢ የአá‹á‰³áˆ¨ መረብ ስህተቶች እና ጥቃቶች አብዛኛዠጊዜ ጊዜያዊ ብቻ ናቸá‹á£ ስለዚህ ይህ ገጽ በኋላ ላይ ሊሠራ ይችላáˆá¢</translation>
<translation id="536296301121032821">የመáˆáˆªá‹« ቅንብሮችን ማከማቸት አáˆá‰°áˆ³áŠ«áˆ</translation>
+<translation id="5363309033720083897">በአስተዳዳሪዎ የተáˆá‰€á‹° ተከታታይ ወደብ</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="5386426401304769735">የዚህ ጣቢያ የዕá‹á‰…ና ማረጋገጫ ሰንሰለቱ SHA-1 በመጠቀሠየተáˆáˆ¨áˆ˜ የዕá‹á‰…ና ማረጋገጫን ያካትታáˆá¢</translation>
@@ -1179,6 +1212,7 @@
<translation id="5398772614898833570">ማስታወቂያዎች ታáŒá‹°á‹‹áˆ</translation>
<translation id="5400836586163650660">áŒáˆ«áŒ«</translation>
<translation id="540969355065856584">ይህ አገáˆáŒ‹á‹­ <ph name="DOMAIN" /> መሆኑን ሊያረጋáŒáŒ¥ አáˆá‰»áˆˆáˆá¤ የደህንáŠá‰µ እá‹á‰…ና ማረጋገጫዠበዚህ ጊዜ ላይ የሚሰራ አይደለáˆá¢ ይሄ በተሳሳተ አወቃቀር ወይሠአንድ አጥቂ áŒáŠ•áŠ™áŠá‰µá‹ŽáŠ• በመጥለበየተከሰተ ሊሆን ይችላáˆá¢</translation>
+<translation id="541143247543991491">ደመና (በመላá‹-ስርዓት)</translation>
<translation id="541416427766103491">á‰áˆáˆ 4</translation>
<translation id="5421136146218899937">የአሰሳ á‹áˆ‚ብ አጽዳ…</translation>
<translation id="5426179911063097041"><ph name="SITE" /> ማሳወቂያዎችን ለእርስዎ መላክ á‹­áˆáˆáŒ‹áˆ</translation>
@@ -1192,6 +1226,7 @@
<translation id="5455374756549232013">መጥᎠየመáˆáˆªá‹« ጊዜ ማህተáˆ</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" /> ተጨማሪ}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="5463625433003343978">መሣሪያዎችን በማáŒáŠ˜á‰µ ላይ...</translation>
<translation id="5469868506864199649">ጣሊያንኛ</translation>
<translation id="5470861586879999274">&amp;አርትዕን ድገáˆ</translation>
<translation id="5478437291406423475">B6/C4 (የደብዳቤ á–ስታ)</translation>
@@ -1241,7 +1276,6 @@
<translation id="5624120631404540903">የይለá ቃሎችን አስተዳድር</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="563324245173044180">አታላይ ይዘት ታáŒá‹·áˆá¢</translation>
<translation id="5644090287519800334">ጎን 1 áˆáˆµáˆ X ሽáŒáˆ½áŒ</translation>
@@ -1280,12 +1314,12 @@
<translation id="5785756445106461925">በተጨማሪᣠይህ ገጽ ደህንáŠá‰³á‰¸á‹ á‹«áˆá‰°áŒ á‰ á‰€ ሌሎች ንብረቶችን አካትቷáˆá¢ እáŠá‹šáˆ… ንብረቶች በሽáŒáŒáˆ­ ወቅት በሌሎች ሊታዩ ይችላሉᣠእናሠየገጹን መáˆáŠ­ ለመለወጥ በአጥቂዎች ሊቀየሩ ይችላሉá¢</translation>
<translation id="5786044859038896871">የካርድዎን መረጃ መሙላት á‹­áˆáˆáŒ‹áˆ‰?</translation>
<translation id="578633867165174378">Chrome እርስዎ አáˆáŠ• የተጠቀሙበትን የይለá ቃሠበá‹áˆ‚ብ ጥሰት á‹áˆµáŒ¥ አáŒáŠá‰·áˆá¢ ይህንን የይለá ቃሠአáˆáŠ• እንዲቀይሩ እንመክራለንá¢</translation>
-<translation id="5798290721819630480">ለá‹áŒ¦á‰½ ይወገዱ?</translation>
<translation id="5803412860119678065">የእርስዎን <ph name="CARD_DETAIL" /> መሙላት á‹­áˆáˆáŒ‹áˆ‰?</translation>
<translation id="5804241973901381774">áቃዶች</translation>
<translation id="5804427196348435412">የNFC መሣሪያዎችን ይጠቀሙ</translation>
<translation id="5810442152076338065">ወደ <ph name="DOMAIN" /> áŒáŠ•áŠ™áŠá‰µá‹Ž áጹማዊ ስአመሰá‹áˆ­ ጥቅሠበመጠቀሠየተመሳጠረ áŠá‹á¢</translation>
<translation id="5813119285467412249">&amp;አክáˆáŠ• ድገáˆ</translation>
+<translation id="5817918615728894473">አጣáˆáˆ­</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ይህ ካርድ እርስዎ ሲከáሉ ይሞላáˆá£ ሆኖሠትክክለኛ á‰áŒ¥áˆ© ከዚህ ጣቢያ ጋር አይጋራáˆá¢ ለደህንáŠá‰µ ጥበቃ ሲባáˆá£ ጊዜያዊ CVC እንዲáˆáˆá‰… ይደረጋáˆá¢}one{የመረጡት ካርድ እርስዎ ሲከáሉ ይሞላሠሆኖሠትክክለኛ á‰áŒ¥áˆ© ከዚህ ጣቢያ ጋር አይጋራáˆá¢ ለደህንáŠá‰µ ጥበቃ ሲባáˆá£ ጊዜያዊ CVC እንዲáˆáˆá‰… ይደረጋáˆá¢}other{የመረጡት ካርድ እርስዎ ሲከáሉ ይሞላሠሆኖሠትክክለኛ á‰áŒ¥áˆ© ከዚህ ጣቢያ ጋር አይጋራáˆá¢ ለደህንáŠá‰µ ጥበቃ ሲባáˆá£ ጊዜያዊ CVC እንዲáˆáˆá‰… ይደረጋáˆá¢}}</translation>
<translation id="5826507051599432481">የጋር ስሠ(CN)</translation>
<translation id="5838278095973806738">በአጥቂዎች ሊሰረቅ ስለሚችሠበዚህ ጣቢያ ላይ ማናቸá‹áˆ አደጋን ሊያስከትሠየሚችሠመረጃ (ለáˆáˆ³áˆŒá¦ የይለá ቃሎች ወይሠየክሬዲት ካርዶች) ማስገባት የለብዎትáˆá¢</translation>
@@ -1293,6 +1327,7 @@
<translation id="5855253129151731373">የጣቢያዠአስተናጋጅ ስሠከ<ph name="LOOKALIKE_DOMAIN" /> ጋር ይመሳሰላáˆá¢ አጥቂዎች አንዳንድ ጊዜ በጎራዠስሠላይ ለመታየት የሚያስቸáŒáˆ© አáŠáˆµá‰°áŠ› ለá‹áŒ¦á‰½áŠ• በማድረጠጣቢያዎችን ያስመስላሉá¢
ይህ የሚታየዠበስህተት áŠá‹ ብለዠካሰቡ እባክዎ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals ይጎብኙá¢</translation>
+<translation id="5860033963881614850">አጥá‹</translation>
<translation id="5862579898803147654">á‰áˆáˆ 8</translation>
<translation id="5863847714970149516">ከáŠá‰µ ያለዠገጽ እርስዎን ገንዘብ ለማስከáˆáˆ ሊሞክር ይችላáˆ</translation>
<translation id="5866257070973731571">ስáˆáŠ­ á‰áŒ¥áˆ­ ያክሉ</translation>
@@ -1309,6 +1344,7 @@
<translation id="5913377024445952699">የማያ ገጽ ቀረጻ ባለበት ቆሟáˆ</translation>
<translation id="59174027418879706">áŠá‰…ቷáˆ</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 ጥቅሠላይ ያለ}one{# ጥቅሠላይ ያለ}other{# ጥቅሠላይ}}</translation>
<translation id="5921185718311485855">አብራ</translation>
<translation id="5921639886840618607">ወደ Google መለያ ካርድ ይቀመጥ?</translation>
<translation id="5922853866070715753">በቃ ሊያáˆá‰… áŠá‹</translation>
@@ -1328,6 +1364,7 @@
<translation id="5989320800837274978">ቋሚ ተኪ አገáˆáŒ‹á‹®á‰½áˆ ሆኑ የ.pac ስክሪá•á‰µ ዩአርኤሠአáˆá‰°áŒˆáˆˆáŒ¹áˆá¢</translation>
<translation id="5992691462791905444">Z-እጥá‹á‰µáŠ• በመቀየስ ላይ</translation>
<translation id="6000758707621254961">ለ«<ph name="SEARCH_TEXT" />» <ph name="RESULT_COUNT" /> á‹áŒ¤á‰¶á‰½áŠ• አሳይ</translation>
+<translation id="6006484371116297560">የታወቀ ገጽታ</translation>
<translation id="6008122969617370890">N-ለ1 ቅደáˆ-ተከተáˆ</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">የእርስዎን የይለá ቃላት á‹­áˆá‰µáˆ¹</translation>
@@ -1349,6 +1386,7 @@
<translation id="6045164183059402045">የማስáˆáŒ¸áˆšá‹« ቅንብር ደንብ</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="6049004884579590341">ከሙሉ ማያ ገጽ ለመá‹áŒ£á‰µ |<ph name="ACCELERATOR" />|ን ተጭáŠá‹ á‹­á‹«á‹™</translation>
<translation id="6049488691372270142">ገጽ ማድረስ</translation>
<translation id="6051221802930200923"><ph name="SITE" /> የዕá‹á‰…ና ማረጋገጫ ሚስማር መሰካትን ስለሚጠቀሠድር ጣቢያá‹áŠ• አáˆáŠ• መጎብኘት አይችሉáˆá¢ የአá‹á‰³áˆ¨ መረብ ስህተቶች እና ጥቃቶች ብዙá‹áŠ• ጊዜ ጊዜያዊ ስለሆኑ ይህ ገጽ በኋላ ላይ ሊሠራ ይችላáˆá¢</translation>
<translation id="6051898664905071243">የገጽ ብዛትá¦</translation>
@@ -1365,6 +1403,7 @@
<translation id="610911394827799129">የእርስዎ Google መለያ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> ላይ ሌሎች የአሰሳ ታሪክ á‹“á‹­áŠá‰¶á‰½ ሊኖረዠይችላáˆá¢</translation>
<translation id="6116338172782435947">ወደ ቅንጥብ ሰሌዳዠየተቀዱ ጽሑá እና áˆáˆµáˆŽá‰½áŠ• ይመáˆáŠ¨á‰±</translation>
<translation id="6120179357481664955">የእርስዎን UPI መታወቂያ ያስታá‹áˆ³áˆ‰?</translation>
+<translation id="6123290840358279103">áˆáŠ“ባዊ ካርድ ይመáˆáŠ¨á‰±</translation>
<translation id="6124432979022149706">Chrome Enterprise አያያዦች</translation>
<translation id="6146055958333702838">ማናቸá‹áˆ ገመዶችን á‹­áˆá‰µáˆ¹áŠ“ እየተጠቀሙ ሊሆኑ የሚችáˆá‰¸á‹áŠ• ማንኛá‹áˆ ራá‹á‰°áˆ®á‰½á£
ሞደሞችን ወይሠሌላ አá‹á‰³áˆ¨ መረብ መሣሪያዎችን ዳáŒáˆ ያስጀáˆáˆ©á¢</translation>
@@ -1401,6 +1440,7 @@
<translation id="6289939620939689042">ገጽ ቀለáˆ</translation>
<translation id="6290238015253830360">የእርስዎ የተጠቆሙ ዘገባዎች እዚህ ይመጣሉ</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">ካርድ ማረጋገጫ ኮድá¦</translation>
<translation id="6302269476990306341">በChrome á‹áˆµáŒ¥ Google ረዳት እያቆመ áŠá‹</translation>
<translation id="6305205051461490394"><ph name="URL" /> ሊደረስበት አይችáˆáˆá¢</translation>
<translation id="6312113039770857350">ድረ-ገጽ አይገáŠáˆ</translation>
@@ -1426,6 +1466,7 @@
<translation id="6390200185239044127">Z-እጥá‹á‰µ áŒáˆ›áˆ½</translation>
<translation id="6390662030813198813">áˆáˆ•áŠ•á‹µáˆµáŠ“-E</translation>
<translation id="6393956493820063117">ከ<ph name="ORIGIN_NAME" /> ወደዚህ አካባቢ መለጠá በአስተዳዳሪ መመሪያ ታáŒá‹·áˆ</translation>
+<translation id="6398765197997659313">ከሙሉ ማሳያ መስኮት á‹­á‹áŒ¡</translation>
<translation id="6401136357288658127">ይህ መመሪያ ተቋርጧáˆá¢ በáˆá‰µáŠ© የ<ph name="NEW_POLICY" /> መመሪያá‹áŠ• መጠቀሠአለብዎትá¢</translation>
<translation id="6404511346730675251">á‹•áˆá‰£á‰µ አርትዕ</translation>
<translation id="6406765186087300643">C0 (የደብዳቤ á–ስታ)</translation>
@@ -1438,7 +1479,6 @@
<translation id="6428450836711225518">ስáˆáŠ­ á‰áŒ¥áˆ­á‹ŽáŠ• ያረጋáŒáŒ¡</translation>
<translation id="6433490469411711332">የዕá‹á‰‚á‹« መረጃን ያርትዑ</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ማገናኘት አሻáˆáˆ¨áŠ ብáˆáˆá¢</translation>
-<translation id="6434309073475700221">ጣለá‹</translation>
<translation id="6440503408713884761">የተተወ</translation>
<translation id="6443406338865242315">የትኛዎቹ ቅጥያዎች እና ተሰኪዎች ናቸዠእርስዎ የጫኑት</translation>
<translation id="6446163441502663861">ካሠ(የደብዳቤ á–ስታ)</translation>
@@ -1481,6 +1521,7 @@
<translation id="6624427990725312378">የዕá‹á‰‚á‹« መረጃ</translation>
<translation id="6626291197371920147">የሚሰራ የካርድ á‰áŒ¥áˆ­ ያክሉ</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> áለጋ</translation>
+<translation id="6630043285902923878">የዩኤስቢ መሣሪያዎችን በማáŒáŠ˜á‰µ ላይ...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">አጽዳ</translation>
@@ -1490,12 +1531,13 @@
<translation id="6648524591329069940">ባለጭረት ቅርጸ-á‰áˆáŠ</translation>
<translation id="6651270836885078973">በሚከተለዠየሚተዳደር áŠá‹á¦</translation>
<translation id="6652101503459149953">Windows Helloን ይጠቀሙ</translation>
-<translation id="6657585470893396449">የይለá ቃáˆá¦</translation>
+<translation id="6657585470893396449">የይለá ቃáˆ</translation>
<translation id="666259744093848177">(x86_64 የተተረጎመ)</translation>
<translation id="6665553082534466207">ሦስቴ ብስ ቀáŠ</translation>
<translation id="6671697161687535275">የአስተያየት ጥቆማ ከChromium ይወገድ?</translation>
<translation id="6685834062052613830">ዘáŒá‰°á‹ á‹­á‹áŒ¡ እና ቅንብርን ያጠናቅá‰</translation>
<translation id="6687335167692595844">የቅርጸ-á‰áˆáŠ መጠን ተጠይቋáˆ</translation>
+<translation id="6688743156324860098">አዘáˆáŠ•â€¦</translation>
<translation id="6689249931105087298">አንጻራዊ ከጥá‰áˆ­ áŠáŒ¥á‰¥ እመቃ ጋር</translation>
<translation id="6689271823431384964">በመለያ ስለገቡ Chrome ካርዶችዎን በGoogle መለያዎ ሊያስቀáˆáŒ¥áˆá‹Ž እየጠየቀ áŠá‹á¢ ይህን ባህሪ በቅንብሮች á‹áˆµáŒ¥ መቀየር ይችላሉᢠየካርድ ያዢዠስሠከመለያዎ áŠá‹ የመጣá‹á¢</translation>
<translation id="6698381487523150993">ተáˆáŒ áˆ¨:</translation>
@@ -1511,6 +1553,7 @@
<translation id="6744009308914054259">áŒáŠ•áŠ™áŠá‰µáŠ• እየተጠባበበሳሉ የመስመር á‹áŒª ጽሑáŽá‰½áŠ• ለማንበብ á‹áˆ­á‹¶á‰½áŠ• መጎብኘት ይችላሉá¢</translation>
<translation id="6753269504797312559">የመáˆáˆªá‹« እሴት</translation>
<translation id="6757797048963528358">የእርስዎ መሣሪያ ተáŠá‰·áˆá¢</translation>
+<translation id="6767985426384634228">አድራሻ ይዘáˆáŠ•?</translation>
<translation id="6768213884286397650">ሃጋኪ (á–ስታ ካርድ)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ወይን ጠጅ</translation>
@@ -1533,6 +1576,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome ለማንበብ እንዲቀáˆáˆ ይህን ገጽ አቃáˆáˆŽá‰³áˆá¢ Chrome የመጀመሪያá‹áŠ• ገጽ ደህንáŠá‰± ባáˆá‰°áŒ á‰ á‰€ áŒáŠ•áŠ™áŠá‰µ ላይ ሰርስሮ አá‹áŒ¥á‰¶á‰³áˆá¢</translation>
<translation id="6891596781022320156">የመመሪያ ደረጃ አይደገááˆá¢</translation>
+<translation id="6895143722905299846">áˆáŠ“ባዊ á‰áŒ¥áˆ­á¦</translation>
<translation id="6895330447102777224">የእርስዎ ካርድ ተረጋáŒáŒ§áˆ</translation>
<translation id="6897140037006041989">የተጠቀሚ ተወካይ</translation>
<translation id="6898699227549475383">ድርጅት (O)</translation>
@@ -1568,10 +1612,10 @@
<translation id="7004583254764674281">ካርዶችን በበለጠ áጥáŠá‰µ ለማረጋገጥ Windows Helloን ይጠቀሙ</translation>
<translation id="7006930604109697472">ለማንኛá‹áˆ ላክ</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">የቅንብሮችን መጠን ቀይር</translation>
<translation id="7014741021609395734">የማጉላት ደረጃ</translation>
<translation id="7016992613359344582">እáŠá‹šáˆ… ክáያዎች የአንድ ጊዜ ወይሠተደጋጋሚᣠእና የማያስታá‹á‰ ሊሆኑ ይችላሉá¢</translation>
<translation id="7029809446516969842">የይለá ቃላት</translation>
+<translation id="7030436163253143341">የዕá‹á‰…ና ማረጋገጫዠáˆáŠ­ á‹«áˆáˆ†áŠ áŠá‹</translation>
<translation id="7031646650991750659">የትኛዎቹን የGoogle Play መተáŒá‰ áˆªá‹«á‹Žá‰½ እንደጫኑ</translation>
<translation id="7050187094878475250"><ph name="DOMAIN" /> ጋር ለመድረስ ሞክረዋáˆá£ áŠáŒˆáˆ­ áŒáŠ• አገáˆáŒ‹á‹© አስተማማአለመሆን የሚያስቸáŒáˆ­ በጣሠረጅሠየሆአየማረጋገጫ ጊዜ áŠá‹ ያለá‹á¢</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ይህ ካርድ አáˆáŠ• ሊቀመጥ አይችáˆáˆ}one{እáŠá‹šáˆ… ካርዶች አáˆáŠ• ሊቀመጡ አይችሉáˆ}other{እáŠá‹šáˆ… ካርዶች አáˆáŠ• ሊቀመጡ አይችሉáˆ}}</translation>
@@ -1641,12 +1685,14 @@
<translation id="7300012071106347854">በራ ያለ á‹áˆƒ ሰማያዊ</translation>
<translation id="7302712225291570345">«<ph name="TEXT" />»</translation>
<translation id="7304030187361489308">ከá ያለ</translation>
+<translation id="7305756307268530424">በá‹áŒá‰³ ይጀáˆáˆ©</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">የáŒáŠ•áŠ™áŠá‰µ እገዛ</translation>
<translation id="7323804146520582233">የ«<ph name="SECTION" />» ክáሉን ሰርá‹</translation>
<translation id="733354035281974745">የመሣሪያ አካባቢያዊ መለያ መሻር</translation>
<translation id="7333654844024768166">አáˆáŠ• የይለá ቃáˆá‹ŽáŠ• በአንድ አታላይ ጣቢያ ላይ አስገብተዋáˆá¢ Chromium ወደ <ph name="WEBSITE_1" />ᣠ<ph name="WEBSITE_2" />ᣠ<ph name="WEBSITE_3" /> እና የይህን ይለá ቃሠወደሚጠቀሙባቸዠሌሎች ጣቢያዎች ሄደዠአáˆáŠ‘ኑ እንዲለá‹áŒ¡á‰µ ይመክራáˆá¢</translation>
<translation id="7334320624316649418">&amp;ማስተካከáˆáŠ• ድገáˆ</translation>
+<translation id="7337248890521463931">ተጨማሪ መስመሮችን አሳይ</translation>
<translation id="7337706099755338005">በእርስዎ የመሣሪያ ስርዓት ላይ አይገáŠáˆá¢</translation>
<translation id="733923710415886693">የአገáˆáŒ‹á‹© የእá‹á‰…ና ማረጋገጫ በእá‹á‰…ና ማረጋገጫ áŒáˆáŒ½áŠá‰µ በኩሠአáˆá‰°áŒˆáˆˆáŒ¸áˆá¢</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1654,6 +1700,7 @@
<translation id="7349430561505560861">A4-ተጨማሪ</translation>
<translation id="7353601530677266744">የትእዛዠመስመር</translation>
<translation id="7359588939039777303">ማስታወቂያዎች ታáŒá‹°á‹‹áˆá¢</translation>
+<translation id="7363096869660964304">á‹­áˆáŠ•áŠ“ᣠእርስዎ የማይታዩ አይደሉáˆá¢ ማንáŠá‰µ የማያሳá‹á‰… áˆáŠá‰³ መጠቀሠየእርስዎን አሰሳᣠየበይáŠáˆ˜áˆ¨á‰¥ አገáˆáŒáˆŽá‰µ አቅራቢ ወይሠየሚጎበኟቸዠድር ጣቢያዎች ከአሰሪዎ አይደብቃቸá‹áˆá¢</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />ᣠበChrome ቅንብሮች á‹áˆµáŒ¥ አድራሻዎችን ለማከሠእና ለማቀናበር ትርን ከዚያ አስገባን ይጫኑ</translation>
<translation id="7365849542400970216">የመሣሪያዎን አጠቃቀሠያá‹á‰ƒáˆ‰?</translation>
<translation id="7372973238305370288">የáለጋ á‹áŒ¤á‰µ</translation>
@@ -1664,7 +1711,9 @@
<translation id="7378594059915113390">የሚዲያ መቆጣጠሪያዎች</translation>
<translation id="7378627244592794276">አይ</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">አይመለከተá‹áˆ</translation>
<translation id="7390545607259442187">ካርድ ያረጋáŒáŒ¡</translation>
+<translation id="7392089738299859607">አድራሻን ያዘáˆáŠ‘</translation>
<translation id="7399802613464275309">የደህንáŠá‰µ áተሻ</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">የእርስዎ <ph name="DEVICE_NAME" /> የሚተዳደር áŠá‹</translation>
@@ -1679,6 +1728,7 @@
&lt;li&gt;እንዴት ሶáትዌሩን ከኮáˆá’á‹á‰°áˆ­á‹Ž እስከመጨረሻዠማስወገድ እንደሚችሉ ለማወቅ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;የChrome እገዛ ማዕከáˆ&lt;/a&gt;ን ይጎብኙ
&lt;/ol&gt;</translation>
<translation id="741007362987735528">ሰáŠ-ቅርጸት</translation>
+<translation id="7410471291937727359">ተወዳጅ</translation>
<translation id="7416351320495623771">የይለá ቃላትን ያስተዳድሩ...</translation>
<translation id="7419106976560586862">የመገለጫ ዱካ</translation>
<translation id="7437289804838430631">የእá‹á‰‚á‹« መረጃ አክáˆ</translation>
@@ -1694,7 +1744,7 @@
<translation id="7481312909269577407">ወደ áŠá‰µ</translation>
<translation id="7485870689360869515">áˆáŠ•áˆ á‹áˆ‚ብ አáˆá‰°áŒˆáŠ˜áˆá¢</translation>
<translation id="7495528107193238112">ይህ ይዘት ታáŒá‹·áˆá¢ ችáŒáˆ©áŠ• ለማስተካከሠየጣቢያá‹áŠ• ባለቤት á‹«áŠáŒ‹áŒáˆ©á¢</translation>
-<translation id="7498234416455752244">አርትዖቱን ቀጥáˆ</translation>
+<translation id="7498193950643227031">መጠኑ ከተቀየረ á‹«áˆá‰°áŒ á‰ á‰€ ባሕሪ ሊያሳይ ይችላáˆá¢ አáˆáŠ• በ<ph name="SETTINGS" /> á‹áˆµáŒ¥ የመተáŒá‰ áˆªá‹«á‹Žá‰½ መጠንን ለመቀየር ያለá‹áŠ• ችሎታ መገደብ ይችላሉá¢</translation>
<translation id="7503664977220660814">አáˆáŠ• የይለá ቃáˆá‹ŽáŠ• በአንድ አታላይ ጣቢያ ላይ አስገብተዋáˆá¢ Chromium የ<ph name="WEBSITE_1" />ᣠ<ph name="WEBSITE_2" /> እና አáˆáŠ• ይህን የይለá ቃሠየተጠቀሙባቸዠየሌሎች ጣቢያዎች የተቀመጡ የይለá ቃላትዎን መáˆá‰°áˆ½ ይመክራáˆá¢</translation>
<translation id="7508255263130623398">የተመላሽ መመሪያ መሣሪያ መታወቂያ ባዶ áŠá‹ ወይሠከአáˆáŠ‘ የመሣሪያ መታወቂያ ጋር አይዛመድáˆ</translation>
<translation id="7508870219247277067">አቮካዶ አረንጓዴ</translation>
@@ -1714,6 +1764,7 @@
<translation id="7548892272833184391">የáŒáŠ•áŠ™áŠá‰µ ስህተቶችን ያስተካክሉ</translation>
<translation id="7549584377607005141">ይህ ድረ-ገጽ በአáŒá‰£á‰¡ እንዲታይ ቀደሠብለዠያስገቡት á‹áˆ‚ብ ያስáˆáˆáŒˆá‹‹áˆá¢ ይህን á‹áˆ‚ብ እንደገና መላክ ይችላሉᣠáŠáŒˆáˆ­ áŒáŠ• ይህን በማድረáŒá‹Ž ይህ ገጽ ከዚህ በáŠá‰µ ያከናወáŠá‹ ማንኛá‹áˆ እርáˆáŒƒ á‹­á‹°áŒáˆ›áˆ‰á¢</translation>
<translation id="7550637293666041147">የእርስዎ መሣሪያ ተጠቃሚ ስሠእና የ Chrome ተጠቃሚ ስáˆ</translation>
+<translation id="755279583747225797">ሙከራ ንበáŠá‹</translation>
<translation id="7552846755917812628">የሚከተሉትን ጠቃሚ áˆáŠ­áˆ®á‰½ ይሞክሩá¦</translation>
<translation id="7554475479213504905">ለማንኛá‹áˆ እንደገና ጫን እና አሳይ</translation>
<translation id="7554791636758816595">አዲስ ትር</translation>
@@ -1732,7 +1783,6 @@
<translation id="7610193165460212391">እሴት ከክáˆáˆ <ph name="VALUE" /> á‹áŒª áŠá‹á¢</translation>
<translation id="7613889955535752492">የሚያበቃበት ጊዜᦠ<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />ᣠትር ይጫኑ በመቀጠሠበChrome ቅንብሮች á‹áˆµáŒ¥ የእርስዎን የይለá ቃላት ለማየት እና ለማስተዳደር አስገባን ይጫኑ</translation>
-<translation id="7615602087246926389">አስቀድሞ በተለየ የGoogle መለያዎ ይለá ቃሠስሪት የተመሰጠረ á‹áˆ‚ብ አለዎትᢠእባክዎ ከታች ያስገቡትá¢</translation>
<translation id="7616645509853975347">የእርስዎ አስተዳዳሪ በአሳሽዎ ላይ የChrome Enterprise አገናኞችን አብርቷáˆá¢ እáŠá‹šáˆ… አገናኞች የአንዳንድ á‹áˆ‚ብዎ መዳረሻ አላቸá‹á¢</translation>
<translation id="7619838219691048931">የመጨረሻ ሉህ</translation>
<translation id="762844065391966283">አንድ በአንድ</translation>
@@ -1797,13 +1847,12 @@
<translation id="782886543891417279">እየተጠቀሙበት ያለዠWi-Fi (<ph name="WIFI_NAME" />) በመለያ መáŒá‰¢á‹« ገጹን እንዲጎበኙ ሊጠይቅዎት ይችላáˆá¢</translation>
<translation id="7836231406687464395">Postfix (የደብዳቤ á–ስታ)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{áˆáŠ•áˆ}=1{1 መተáŒá‰ áˆªá‹« (<ph name="EXAMPLE_APP_1" />)}=2{2 መተáŒá‰ áˆªá‹«á‹Žá‰½ (<ph name="EXAMPLE_APP_1" />ᣠ<ph name="EXAMPLE_APP_2" />)}one{# መተáŒá‰ áˆªá‹«á‹Žá‰½ (<ph name="EXAMPLE_APP_1" />ᣠ<ph name="EXAMPLE_APP_2" />ᣠ<ph name="AND_MORE" />)}other{# መተáŒá‰ áˆªá‹«á‹Žá‰½ (<ph name="EXAMPLE_APP_1" />ᣠ<ph name="EXAMPLE_APP_2" />ᣠ<ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">ሆኖሠáŒáŠ• የማይታዩ አይደሉáˆá¢ ማንáŠá‰µ የማያሳá‹á‰… áˆáŠá‰³ መጠቀሠየእርስዎን አሰሳᣠየበይáŠáˆ˜áˆ¨á‰¥ አገáˆáŒáˆŽá‰µ አቅራቢ ወይሠየሚጎበኟቸዠድር ጣቢያዎች ከአሰሪዎ አይደብቃቸá‹áˆá¢</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">በá‹á‹­áˆ á‹“á‹­áŠá‰µ á‹áˆá‹µáŠ“ዎች አማካáŠáŠá‰µ á‹á‹­áˆŽá‰½áŠ• ይክáˆá‰±á¢</translation>
<translation id="7862185352068345852">ከጣቢያ ይወጡ?</translation>
<translation id="7865448901209910068">áˆáˆ­áŒ¥ áጥáŠá‰µ</translation>
<translation id="7874263914261512992">አáˆáŠ• የይለá ቃáˆá‹ŽáŠ• በአንድ አታላይ ጣቢያ ላይ አስገብተዋáˆá¢ Chrome የ<ph name="WEBSITE_1" />ᣠ<ph name="WEBSITE_2" /> እና አáˆáŠ• ይህን የይለá ቃሠየተጠቀሙባቸዠየሌሎች ጣቢያዎች የተቀመጡ የይለá ቃላትዎን መáˆá‰°áˆ½ ይመክራáˆá¢</translation>
<translation id="7878562273885520351">የእርስዎ ይለá ቃሠተሰርቆ ሊሆን ይችላáˆ</translation>
+<translation id="7880146494886811634">አድራሻን ያስቀáˆáŒ¡</translation>
<translation id="7882421473871500483">ቡናማ</translation>
<translation id="7887683347370398519">የእርስዎን CVC á‹­áˆá‰µáˆ¹ እና እንደገና ይሞክሩ</translation>
<translation id="7887885240995164102">ወደ ስዕáˆ-á‹áˆµáŒ¥-ስዕሠይáŒá‰¡</translation>
@@ -1811,6 +1860,7 @@
<translation id="7894280532028510793">የáŠá‹°áˆ አጻጻበትክክሠከሆአ<ph name="BEGIN_LINK" />የአá‹á‰³áˆ¨ መረብ áˆáˆ­áˆ˜áˆ«áŠ• ለማስኬድ ይሞክሩ<ph name="END_LINK" />á¢</translation>
<translation id="7904208859782148177">C3 (የደብዳቤ á–ስታ)</translation>
<translation id="7931318309563332511">á‹«áˆá‰³á‹ˆá‰€</translation>
+<translation id="793209273132572360">አድራሻ ይዘáˆáŠ•?</translation>
<translation id="7932579305932748336">ኮት</translation>
<translation id="79338296614623784">የሚሰራ ስáˆáŠ­ á‰áŒ¥áˆ­ ያስገቡ</translation>
<translation id="7934052535022478634">ክáá‹« ተጠናቅቋáˆ</translation>
@@ -1881,6 +1931,7 @@
<translation id="8175796834047840627">እርስዎ በመለያ ስለገቡ Chrome ወደ የእርስዎ የGoogle መለያ ለማስቀመጥ አማራጭ እያቀረበ áŠá‹á¢ ይህን ባህሪ በቅንብሮች á‹áˆµáŒ¥ መለወጥ ይችላሉá¢</translation>
<translation id="8176440868214972690">የዚህ መሣሪያ አስተዳዳሪ እንደ ቅንብሮች ወይሠመመሪያዎች ላሉት ለሚከተሉት ድር ጣቢያዎች የተወሰአመረጃ áˆáŠ³áˆá¢</translation>
<translation id="8184538546369750125">áˆáˆˆáŠ•á‰°áŠ“á‹Š áŠá‰£áˆªá‹áŠ• ተጠቀሠ(áቀድ)</translation>
+<translation id="8193086767630290324">ሚስጥራዊ ተብሎ በተጠቆመ á‹áˆ‚ብ ላይ የተወሰዱ እርáˆáŒƒá‹Žá‰½</translation>
<translation id="8194797478851900357">&amp;á‹áˆ°á‹µáŠ• ቀáˆá‰¥áˆµ</translation>
<translation id="8201077131113104583">የማይሰራ የURL á‹áˆ›áŠ” ለቅጥያ ከመታወቂያ «<ph name="EXTENSION_ID" />» ጋርá¢</translation>
<translation id="8202097416529803614">የትዕዛዠማጠቃለያ</translation>
@@ -1903,6 +1954,7 @@
<translation id="8249296373107784235">አጨንáŒá</translation>
<translation id="8249320324621329438">ለመጨረሻ ጊዜ የመጣá‹á¦</translation>
<translation id="8253091569723639551">የማስከáˆá‹« አድራሻ ያስáˆáˆáŒ‹áˆ</translation>
+<translation id="8257387598443225809">ይህ መተáŒá‰ áˆªá‹« የተáŠá‹°áˆá‹ ለሞባይሠáŠá‹</translation>
<translation id="825929999321470778">áˆáˆ‰áŠ•áˆ የተቀመጡ የይለá ቃላትን አሳይ</translation>
<translation id="8261506727792406068">ሰርá‹</translation>
<translation id="8262952874573525464">ከታች ጫáᣠጫá‰áŠ• ስá‹</translation>
@@ -2027,7 +2079,6 @@
<translation id="8719528812645237045">በርካታ ብስ ከላይ</translation>
<translation id="8725066075913043281">እንደገና ይሞክሩ</translation>
<translation id="8726549941689275341">የገጽ መጠንá¦</translation>
-<translation id="8728672262656704056">ማንáŠá‰µ የማያሳá‹á‰… áˆáŠá‰³ á‹áˆµáŒ¥ ገብተዋáˆ</translation>
<translation id="8730621377337864115">ተከናá‹áŠ—áˆ</translation>
<translation id="8731544501227493793">የይለá ቃላት አá‹áˆ«áˆ­áŠ• ያቀናብሩᣠየእርስዎን የይለá ቃላት በChrome ቅንብሮች á‹áˆµáŒ¥ ለማየት እና ለማቀናበር አስገባን ይጫኑ</translation>
<translation id="8734529307927223492">የእርስዎ <ph name="DEVICE_TYPE" /> በ<ph name="MANAGER" /> የሚተዳደር áŠá‹</translation>
@@ -2104,6 +2155,7 @@
<translation id="9020542370529661692">ይህ ገጽ ወደ <ph name="TARGET_LANGUAGE" /> ተተርጉሟáˆ</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(áˆáŠ­ á‹«áˆáˆ†áŠ)</translation>
+<translation id="9030265603405983977">ባለአንድ ቀለáˆ</translation>
<translation id="9035022520814077154">የደህንáŠá‰µ ጥበቃ ስህተት</translation>
<translation id="9038649477754266430">ገጾችን ይበáˆáŒ¥ በáጥáŠá‰µ ለመጫን የáŒáˆ˜á‰³ አገáˆáŒáˆŽá‰µáŠ• ይጠቀሙ</translation>
<translation id="9039213469156557790">በተጨማሪᣠይህ ገጽ ደህንáŠá‰³á‰¸á‹ á‹«áˆá‰°áŒ á‰ á‰€ ሌሎች ንብረቶችን አካትቷáˆá¢ እáŠá‹šáˆ… ንብረቶች በሽáŒáŒáˆ­ ወቅት በሌሎች ሊታዩ ይችላሉᣠእናሠየገጹን ባህሪ ለመለወጥ በአጥቂዎች ሊቀየሩ ይችላሉá¢</translation>
@@ -2127,6 +2179,7 @@
<translation id="91108059142052966">ሚስጥራዊ ይዘት በሚታይበት ጊዜ የአስተዳዳሪ መመሪያ ከ <ph name="APPLICATION_TITLE" /> ጋር የማያ ገጽ መጋራትን ያሰናክላáˆ</translation>
<translation id="9114524666733003316">ካርድን በማረጋገጥ ላይ...</translation>
<translation id="9114581008513152754">ይህ አሳሽ በኩባንያ ወይሠሌላ ድርጅት አይተዳደርáˆá¢ በዚህ መሣሪያ ላይ ያለ እንቅስቃሴ ከChrome á‹áŒ­ ሊተዳደር ይችላáˆá¢ <ph name="BEGIN_LINK" />የበለጠ ለመረዳት<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">አዲስ</translation>
<translation id="9119042192571987207">ተሰቅáˆáˆ</translation>
<translation id="9128016270925453879">መመሪያዎች ተጭáŠá‹‹áˆ</translation>
<translation id="9128870381267983090">ከአá‹á‰³áˆ¨ መረብ ጋር ይገናኙ</translation>
@@ -2145,6 +2198,7 @@
<translation id="9170848237812810038">&amp;ቀáˆá‰¥áˆµ</translation>
<translation id="9171296965991013597">መተáŒá‰ áˆªá‹« ይተá‹?</translation>
<translation id="9173282814238175921">áŠáŒ áˆ‹ ሰáŠá‹µ/አዲስ ሉህ</translation>
+<translation id="9173995187295789444">የብሉቱዠመሣሪያዎችን በመቃኘት ላይ...</translation>
<translation id="917450738466192189">የአገáˆáŒ‹á‹­ እá‹á‰…ና ማረጋገጫ áˆáŠ­ á‹«áˆáŠ¾áŠ áŠá‹á¢</translation>
<translation id="9174917557437862841">የማብሪያ ማጥáŠá‹« አá‹áˆ«áˆ­ ትርᣠወደዚህ ትር ለመቀየር Enter ይጫኑ</translation>
<translation id="9179703756951298733">በChrome ቅንብሮች á‹áˆµáŒ¥ የእርስዎን ክáያዎች እና የክሬዲት ካርድ መረጃ ያስተዳድሩ</translation>
diff --git a/chromium/components/strings/components_strings_ar.xtb b/chromium/components/strings/components_strings_ar.xtb
index 1024d5a145c..c48f705cae0 100644
--- a/chromium/components/strings/components_strings_ar.xtb
+++ b/chromium/components/strings/components_strings_ar.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">â€Ø¥Ø°Ø§ تم وضع علامة على هذا الخيار، سيخزّن Chrome نسخة من هذه البطاقة على هذا الجهاز لتعبئة النماذج بشكل أسرع.</translation>
<translation id="1110994991967754504">اختيار إذن لـ <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">تراجع عن إعادة الت&amp;رتيب</translation>
+<translation id="1123753900084781868">لا تتوÙّر ميزة "النسخ النصي التلقائي" ÙÙŠ الوقت الحالي.</translation>
<translation id="1125573121925420732">قد يكثر ظهور التحذيرات أثناء إجراء المواقع الإلكترونية لتحديثات الأمان، لكنّ هذه المسألة ستتحسَّن قريبًا.</translation>
<translation id="112840717907525620">ذاكرة التخزين المؤقت للسياسة بحالة جيدة</translation>
<translation id="1130564665089811311">â€Ø²Ø± "ترجمة الصÙحة"ØŒ اضغط على Ù…Ùتاح Enter لترجمة هذه الصÙحة باستخدام "ترجمة Google".</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">اسم الجهاز</translation>
<translation id="124116460088058876">مزيد من اللغات</translation>
<translation id="1243027604378859286">المؤلÙ:</translation>
+<translation id="1246424317317450637">غامق</translation>
<translation id="1250759482327835220">â€Ù„لدÙع بشكل٠أسرع ÙÙŠ المرة القادمة، يمكنك Ø­Ùظ البطاقة والاسم وعنوان إرسال الÙواتير ÙÙŠ حسابك على Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />، <ph name="TYPE_2" /> (تمت المزامنة)</translation>
<translation id="1256368399071562588">â€&lt;p&gt;إذا تعذّر Ùتح أحد المواقع الإلكترونية التي تحاول زيارتها، يمكنك تحرّي الخطأ وإصلاحه باتّباع الخطوات التالية:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">عليك تغيير كلمة مرورك</translation>
<translation id="1484290072879560759">اختيار عنوان الشحن</translation>
<translation id="1492194039220927094">إرسال السياسات:</translation>
+<translation id="1495677929897281669">الرجوع إلى علامة التبويب</translation>
<translation id="1501859676467574491">â€Ø¹Ø±Ø¶ البطاقات من حسابك على Google</translation>
<translation id="1507202001669085618">â€&lt;p&gt;سيظهر هذا الخطأ عند استخدام بوابة شبكة Wi-Fi تتطلّب تسجيل الدخول قبل الاتصال بالإنترنت.&lt;/p&gt;
&lt;p&gt;لإصلاح الخطأ، انقر على &lt;strong&gt;"اتصال"&lt;/strong&gt; ÙÙŠ الصÙحة التي تحاول Ùتحها.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">تعرض هذه الصÙحة</translation>
<translation id="153384715582417236">هذا كل شيء الآن</translation>
<translation id="1536390784834419204">ترجمة الصÙحة</translation>
+<translation id="1539840569003678498">تاريخ ووقت إرسال الإبلاغ:</translation>
<translation id="154408704832528245">اختيار عنوان التسليم للمستخدم</translation>
<translation id="1549470594296187301">â€ÙŠØ¬Ø¨ تÙعيل JavaScript لاستخدام هذه الميزة.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">حاÙØ© قصيرة أولًا</translation>
<translation id="168693727862418163">تعذّر التحقّÙÙ‚ من قيمة السياسة هذه ÙˆÙقًا لمخططها وسيتم تجاهلها.</translation>
<translation id="168841957122794586">تحتوي شهادة الخادم على Ù…Ùتاح ترميز ضعيÙ.</translation>
+<translation id="1696290444144917273">عرض تÙاصيل البطاقة الاÙتراضية</translation>
<translation id="1697532407822776718">أنت الآن على أتم استعداد.</translation>
<translation id="1703835215927279855">خطاب</translation>
<translation id="1706954506755087368">{1,plural, =1{هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />Ø› من المÙترض أن تبدأ شهادة أمانه من الغد. ربما يكون السبب ÙÙŠ ذلك خطأ ÙÙŠ الإعداد أو مهاجمًا يعترض اتصالك.}zero{هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />Ø› من المÙترض أن تبدأ شهادة أمانه خلال # يوم ÙÙŠ المستقبل. ربما يكون السبب ÙÙŠ ذلك خطأ ÙÙŠ الإعداد أو مهاجمًا يعترض اتصالك.}two{هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />Ø› من المÙترض أن تبدأ شهادة أمانه خلال يومين (#) ÙÙŠ المستقبل. ربما يكون السبب ÙÙŠ ذلك خطأ ÙÙŠ الإعداد أو مهاجمًا يعترض اتصالك.}few{هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />Ø› من المÙترض أن تبدأ شهادة أمانه خلال # أيام ÙÙŠ المستقبل. ربما يكون السبب ÙÙŠ ذلك خطأ ÙÙŠ الإعداد أو مهاجمًا يعترض اتصالك.}many{هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />Ø› من المÙترض أن تبدأ شهادة أمانه خلال # يومًا ÙÙŠ المستقبل. ربما يكون السبب ÙÙŠ ذلك خطأ ÙÙŠ الإعداد أو مهاجمًا يعترض اتصالك.}other{هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />Ø› من المÙترض أن تبدأ شهادة أمانه خلال # يوم ÙÙŠ المستقبل. ربما يكون السبب ÙÙŠ ذلك خطأ ÙÙŠ الإعداد أو مهاجمًا يعترض اتصالك.}}</translation>
<translation id="1710259589646384581">نظام التشغيل</translation>
+<translation id="1711234383449478798">تم تجاهل السياسة بسبب عدم ضبط <ph name="POLICY_NAME" /> على <ph name="VALUE" />.</translation>
<translation id="1712552549805331520">يريد <ph name="URL" /> تخزين بيانات على جهاز الكمبيوتر المحلي بشكل دائم.</translation>
<translation id="1713628304598226412">الدÙرج 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">صندوق البريد الإلكتروني 3</translation>
<translation id="1718029547804390981">حجم المستند كبير جدًا بحيث تتعذّر إضاÙØ© تعليق توضيحي إليه</translation>
<translation id="1721424275792716183">* هناك حقل مطلوب</translation>
+<translation id="1727613060316725209">الشهادة صالحة</translation>
<translation id="1727741090716970331">إضاÙØ© رقم بطاقة صالح</translation>
<translation id="1728677426644403582">أنت تعرض مصدر صÙحة ويب</translation>
<translation id="173080396488393970">لا يتم دعم هذا النوع من البطاقات</translation>
@@ -246,7 +253,6 @@
طلبك ذي الصلة بالموقع الإلكتروني <ph name="SITE" />. ويمكن استخدام سياسات المصدر من خلال
عوامل تشغيل المواقع الإلكترونية لضبط الأمان والخصائص الأخرى لموقع إلكتروني.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">ÙŠÙرجى تحديث عبارة مرور المزامنة.</translation>
<translation id="1787142507584202372">تظهر علامات التبويب المÙتوحة هنا</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742">â€<ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ تتوÙّر عدة إجراءات، اضغط على Ù…Ùتاح التبويب (Tab) للتنقّل بينها.</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">الإعلانات</translation>
<translation id="1919367280705858090">الحصول على مساعدة بخصوص رسالة خطأ محددة</translation>
<translation id="192020519938775529">{COUNT,plural, =0{بدون}=1{موقع واحد}two{ موقعان (#)}few{# مواقع}many{# موقعًا}other{# موقع}}</translation>
+<translation id="1924727005275031552">جديد</translation>
<translation id="1945968466830820669">â€Ù‚د تÙقد إمكانية الوصول إلى حساب مؤسستك أو تتعرَّض لسرقة هويتك. لذا، يوصي Chromium بتغيير كلمة مرورك الآن.</translation>
<translation id="1947454675006758438">وضع دبوس أعلى اليمين</translation>
<translation id="1958218078413065209">أعلى نتيجة حققتها هي <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">الدÙرج 7</translation>
<translation id="204357726431741734">â€ÙŠÙرجى تسجيل الدخول لاستخدام كلمات المرور المحÙوظة ÙÙŠ حسابك على Google.</translation>
<translation id="2053111141626950936">لن تتم ترجمة الصÙحات باللغة <ph name="LANGUAGE" />.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{â€Ø¹Ù†Ø¯Ù…ا يكون عنصر التحكم هذا Ù…Ùعّلاً ونشطًا، يحدّد Chrome "المجموعة النموذجية" التي تضم عددًا كبيرًا من الأشخاص الذين تتشابه أنشطة تصÙّحهم مع أنشطة تصÙّحك الأخيرة. ويمكن للمعلÙنين اختيار الإعلانات التي يريدون عرضها للمجموعة ويتم الحÙاظ على خصوصية سجلّ التصÙّح على جهازك، مع العÙلم أنّ مجموعتك يتم تعديلها كل يوم.}=1{â€Ø¹Ù†Ø¯Ù…ا يكون عنصر التحكم هذا Ù…Ùعّلاً ونشطًا، يحدّد Chrome "المجموعة النموذجية" التي تضم عددًا كبيرًا من الأشخاص الذين تتشابه أنشطة تصÙّحهم مع أنشطة تصÙّحك الأخيرة. ويمكن للمعلÙنين اختيار الإعلانات التي يريدون عرضها للمجموعة ويتم الحÙاظ على خصوصية سجلّ التصÙّح على جهازك، مع العÙلم أنّ مجموعتك يتم تعديلها كل يوم.}two{â€Ø¹Ù†Ø¯Ù…ا يكون عنصر التحكم هذا Ù…Ùعّلاً ونشطًا، يحدّد Chrome "المجموعة النموذجية" التي تضم عددًا كبيرًا من الأشخاص الذين تتشابه أنشطة تصÙّحهم مع أنشطة تصÙّحك الأخيرة. ويمكن للمعلÙنين اختيار الإعلانات التي يريدون عرضها للمجموعة ويتم الحÙاظ على خصوصية سجلّ التصÙّح على جهازك، مع العÙلم أنّ مجموعتك يتم تعديلها كل يومَين ({NUM_DAYS}).}few{â€Ø¹Ù†Ø¯Ù…ا يكون عنصر التحكم هذا Ù…Ùعّلاً ونشطًا، يحدّد Chrome "المجموعة النموذجية" التي تضم عددًا كبيرًا من الأشخاص الذين تتشابه أنشطة تصÙّحهم مع أنشطة تصÙّحك الأخيرة. ويمكن للمعلÙنين اختيار الإعلانات التي يريدون عرضها للمجموعة ويتم الحÙاظ على خصوصية سجلّ التصÙّح على جهازك، مع العÙلم أنّ مجموعتك يتم تعديلها كل {NUM_DAYS} أيام.}many{â€Ø¹Ù†Ø¯Ù…ا يكون عنصر التحكم هذا Ù…Ùعّلاً ونشطًا، يحدّد Chrome "المجموعة النموذجية" التي تضم عددًا كبيرًا من الأشخاص الذين تتشابه أنشطة تصÙّحهم مع أنشطة تصÙّحك الأخيرة. ويمكن للمعلÙنين اختيار الإعلانات التي يريدون عرضها للمجموعة ويتم الحÙاظ على خصوصية سجلّ التصÙّح على جهازك، مع العÙلم أنّ مجموعتك يتم تعديلها كل {NUM_DAYS} يومًا.}other{â€Ø¹Ù†Ø¯Ù…ا يكون عنصر التحكم هذا Ù…Ùعّلاً ونشطًا، يحدّد Chrome "المجموعة النموذجية" التي تضم عددًا كبيرًا من الأشخاص الذين تتشابه أنشطة تصÙّحهم مع أنشطة تصÙّحك الأخيرة. ويمكن للمعلÙنين اختيار الإعلانات التي يريدون عرضها للمجموعة ويتم الحÙاظ على خصوصية سجلّ التصÙّح على جهازك، مع العÙلم أنّ مجموعتك يتم تعديلها كل {NUM_DAYS} يوم.}}</translation>
<translation id="2053553514270667976">الرمز البريدي</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{اقتراح واحد}zero{# اقتراح}two{اقتراحان (#)}few{# اقتراحات}many{# اقتراحًا}other{# اقتراح}}</translation>
<translation id="2071692954027939183">تم حظر الإشعارات تلقائيًا لأنّك عادةً لا تسمح بظهورها.</translation>
<translation id="2079545284768500474">تراجع</translation>
<translation id="20817612488360358">تم ضبط إعدادات الخادم الوكيل ليتم استخدامها وتم أيضًا تحديد إعداد صريح للخادم الوكيل.</translation>
<translation id="2082238445998314030">النتيجة <ph name="RESULT_NUMBER" /> من <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Ø­Ùظ…</translation>
<translation id="2088086323192747268">â€Ø²Ø± "إدارة المزامنة"ØŒ اضغط على Ù…Ùتاح Enter لإدارة نوع المعلومات التي تريد مزامنتها من خلال إعدادات Chrome.</translation>
<translation id="2091887806945687916">الصوت</translation>
<translation id="2094505752054353250">النطاق غير متطابق</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535">يتطلَّب <ph name="DOMAIN" /> اسم مستخدم وكلمة مرور.</translation>
<translation id="2330137317877982892">تنتهي صلاحية <ph name="CREDIT_CARD" /> ÙÙŠ <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">يتم التحكّم ÙÙŠ الإعداد من قبل المشرÙ</translation>
+<translation id="2340263603246777781">يريد <ph name="ORIGIN" /> الاقتران</translation>
<translation id="2344028582131185878">عمليات التنزيل التلقائية</translation>
<translation id="2346319942568447007">الصورة التي نسختها</translation>
<translation id="2354001756790975382">الإشارات الأخرى</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">قد يتمكن المهاجمون من رؤية الصور التي تتطلع عليها على هذا الموقع وخداعك من خلال تعديلها.</translation>
<translation id="2356070529366658676">طلب</translation>
<translation id="2357481397660644965">يدير <ph name="DEVICE_MANAGER" /> جهازك، ويدير <ph name="ACCOUNT_MANAGER" /> حسابك.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{خلال أقل من يوم}=1{خلال يوم واحد}two{خلال يومَين ({NUM_DAYS})}few{خلال {NUM_DAYS} أيام}many{خلال {NUM_DAYS} يومًا}other{خلال {NUM_DAYS} يوم}}</translation>
<translation id="2359629602545592467">متعددة</translation>
<translation id="2359808026110333948">متابعة</translation>
+<translation id="2359961752320758691">تم استخدام رقم البطاقة الاÙتراضية.</translation>
<translation id="2367567093518048410">المستوى</translation>
<translation id="2372464001869762664">â€Ø¨Ø¹Ø¯ التأكيد، ستتم مشاركة تÙاصيل البطاقة من حسابك على Google مع هذا الموقع الإلكتروني. يمكنك العثور على رمز التحقق من البطاقة (CVC) ÙÙŠ تÙاصيل حسابك على Plex.</translation>
<translation id="2380886658946992094">قانوني</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">طريقة الشحن هذه غير متاحة، جرّÙب طريقة أخرى.</translation>
<translation id="2396249848217231973">تراجع عن الحذ&amp;Ù</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">قديم</translation>
<translation id="2413528052993050574">هذا الخادم لم يتمكن من إثبات أن ذلك <ph name="DOMAIN" />Ø› بل إنه شهادة أمان ربما تم إلغاء صلاحيتها. وربما يكون السبب ÙÙŠ ذلك خطأ ÙÙŠ التكوين أو مهاجمًا يعترض اتصالك.</translation>
<translation id="2414886740292270097">داكن</translation>
<translation id="2438874542388153331">عمل أربعة ثقوب يمينًا</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">وضع دبوس أسÙÙ„ اليمين</translation>
<translation id="2523886232349826891">سيتم Ø­Ùظ البطاقة على هذا الجهاز Ùقط</translation>
<translation id="2524461107774643265">إضاÙØ© مزيد من المعلومات</translation>
-<translation id="2526590354069164005">سطح المكتب</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{وكلمة مرور واحدة أخرى}zero{و# كلمة مرور أخرى}two{وكلمتا مرور أخريان}few{و# كلمات مرور أخرى}many{و# كلمة مرور أخرى}other{و# كلمة مرور أخرى}}</translation>
<translation id="2536110899380797252">إضاÙØ© عنوان</translation>
<translation id="2539524384386349900">اكتشاÙ</translation>
+<translation id="2541219929084442027">إنّ الصÙحات التي تعرضها ÙÙŠ علامات التبويب ÙÙŠ وضع التصÙÙ‘ÙØ­ المتخÙÙŠ لن يتم الاحتÙاظ بها ÙÙŠ سجلّ المتصÙÙ‘ÙØ­ أو مخزن ملÙات تعري٠الارتباط أو سجلّ البحث بعد إغلاق جميع علامات التبويب ÙÙŠ وضع التصÙÙ‘ÙØ­ المتخÙÙŠØŒ ولكن سيتم الاحتÙاظ بأي ملÙات تنزّÙلها أو إشارات مرجعية تنشئها.</translation>
<translation id="2544644783021658368">مستند واحد</translation>
<translation id="254947805923345898">قيمة السياسة غير صحيحة.</translation>
<translation id="255002559098805027">أرسل <ph name="HOST_NAME" /> استجابة غير صالحة.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">â€Ù„لحصول على أعلى مستوى من الحماية ÙÙŠ متصÙÙ‘ÙØ­ ChromeØŒ يمكنك <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />تÙعيل "الحماية المÙحسَّنة"<ph name="END_ENHANCED_PROTECTION_LINK" />.</translation>
<translation id="2634124572758952069">â€ØªØ¹Ø°Ù‘ر العثور على عنوان IP لخادم <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">الحالة:</translation>
+<translation id="264810637653812429">لم يتم العثور على أي أجهزة متواÙقة.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861">â€<ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ اضغط على Ù…Ùتاح التبويب (Tab) ثم Ù…Ùتاح Enter لمحو سجلّ التصÙÙ‘ÙØ­ وملÙات تعري٠الارتباط وذاكرة التخزين المؤقت وغير ذلك ÙÙŠ إعدادات Chrome.</translation>
<translation id="2650446666397867134">تم رÙض الدخول إلى الملÙ</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">إعادة تشغيل</translation>
<translation id="2803306138276472711">â€Ø§ÙƒØªØ´Ù التصÙØ­ الآمن من Google مؤخرًا <ph name="BEGIN_LINK" />برامج ضارة<ph name="END_LINK" /> على <ph name="SITE" />. أحيانًا تصاب المواقع الإلكترونية الآمنة ÙÙŠ الوضع العادي ببرامج ضارة.</translation>
<translation id="2807052079800581569">الإحداثي الصادي للصورة</translation>
+<translation id="2820957248982571256">جار٠الÙحص...</translation>
<translation id="2824775600643448204">شريط العناوين والبحث</translation>
<translation id="2826760142808435982">تم ترميز الاتصال ومصادقته باستخدام <ph name="CIPHER" />، ويستخدم <ph name="KX" /> كآلية التبادل الرئيسية.</translation>
<translation id="2835170189407361413">محو النموذج</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">دعوة (مغلÙ)</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="2859806420264540918">يعرض هذا الموقع الإلكتروني إعلانات مضلّÙلة أو غير مرغوب Ùيها.</translation>
+<translation id="287596039013813457">سهل الاستخدام</translation>
+<translation id="2876489322757410363">ستتم مغادرة وضع التصÙÙ‘ÙØ­ المتخÙÙŠ للدÙع عبر تطبيق خارجي. هل تريد المتابعة؟</translation>
<translation id="2878197950673342043">الطي على شكل ملصق</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">موضÙع الناÙذة</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">â€C9 (مغلÙ)</translation>
<translation id="3060557858482803256">â€<ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ اضغط على Ù…Ùتاح التبويب (Tab) ثم Enter لتشغيل ميزة "تأكيد السلامة" ÙÙŠ إعدادات Chrome.</translation>
<translation id="3061707000357573562">خدمة رمز التصحيح</translation>
-<translation id="3064966200440839136">ستتم مغادرة وضع التصÙØ­ المتخÙÙŠ للدÙع عبر تطبيق خارجي. هل تريد المتابعة؟</translation>
<translation id="306573536155379004">بدأت اللعبة.</translation>
<translation id="3080254622891793721">الرسم البياني</translation>
<translation id="3086579638707268289">تتم مراقبة نشاطك على الويب.</translation>
@@ -573,8 +589,7 @@
<translation id="315504272643575312">يدير <ph name="MANAGER" /> حسابك.</translation>
<translation id="3157931365184549694">استعادة</translation>
<translation id="3162559335345991374">â€Ù‚د يتطلب Wi-Fi الذي تستخدمه زيارة صÙحة تسجيل الدخول.</translation>
-<translation id="3167968892399408617">لن يتم تسجيل الصÙحات التي تعرضها ÙÙŠ علامات تبويب التصÙØ­ المتخÙÙŠ ÙÙŠ سجل المتصÙØ­ أو مخزن ملÙات تعري٠الارتباط أو سجل البحث بعد إغلاق جميع علامات التبويب ÙÙŠ وضع التصÙØ­ المتخÙÙŠ. ولكن سيتم الاحتÙاظ بأي ملÙات تنزلها أو إشارات مرجعية تنشئها.</translation>
-<translation id="3169472444629675720">Discover</translation>
+<translation id="3169472444629675720">اقتراحات</translation>
<translation id="3174168572213147020">جزيرة</translation>
<translation id="3176929007561373547">تحقق من إعدادات الخادم الوكيل أو اتصل بمشر٠الشبكة
للتأكد من عمل الخادم الوكيل. Ùإذا كنت لا تعتقد أنه يجب عليك استخدام
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">معلومات الإصدار حول جهازك ومتصÙÙّحك</translation>
<translation id="323107829343500871">â€Ø£Ø¯Ø®ÙÙ„ رمز التحقّق (CVC) لبطاقة <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">الكش٠دائمًا عن المحتوى المهم على هذا الموقع</translation>
+<translation id="3249845759089040423">أنيق</translation>
<translation id="3252266817569339921">الÙرنسية</translation>
<translation id="3266793032086590337">القيمة (المتعارضة)</translation>
<translation id="3268451620468152448">علامات التبويب المÙتوحة</translation>
<translation id="3270847123878663523">تراجع عن إعادة الت&amp;رتيب</translation>
+<translation id="3271648667212143903">يريد <ph name="ORIGIN" /> الاتصال</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">أرسلت مؤسستك التي تمتلك النطاق <ph name="ENROLLMENT_DOMAIN" /> بعض المعلومات، مثل الإعدادات أو السياسات، إلى المواقع الإلكترونية التالية.</translation>
<translation id="3282497668470633863">إضاÙØ© الاسم الوارد ÙÙŠ البطاقة</translation>
@@ -655,6 +672,7 @@
<translation id="3428151540071562330">â€Ø¥Ù†Ù‘ معرّ٠واحد أو أكثر من معرّÙات الموارد المنتظمة (URI) لنموذج خادم DnsOverHttpsTemplates غير صالح وبالتالي لن يتم استخدامه.</translation>
<translation id="3431636764301398940">Ø­Ùظ هذه البطاقة إلى هذا الجهاز</translation>
<translation id="3432601291244612633">إغلاق الصÙحة</translation>
+<translation id="3435738964857648380">أمن المعلومات</translation>
<translation id="3435896845095436175">تÙعيل الإضاÙات</translation>
<translation id="3438829137925142401">â€Ø§Ø³ØªØ®Ø¯Ø§Ù… كلمات المرور المحÙوظة ÙÙŠ حسابك على Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@
<translation id="3584299510153766161">عمل ثقبَين بالأسÙÙ„</translation>
<translation id="3586931643579894722">إخÙاء التÙاصيل</translation>
<translation id="3587738293690942763">متوسط</translation>
+<translation id="3590643883886679995">سيتم Ø­Ùظ بيانات تسجيل الدخول على هذا الجهاز بعد الخروج من "وضع التصÙÙ‘ÙØ­ المتخÙÙŠ".</translation>
+<translation id="359126217934908072">الشهر/السنة:</translation>
<translation id="3592413004129370115">â€Italian (مغلÙ)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{يمكنك إعادة ضبط مجموعتك متى شئت، مع العÙلم أنّ الانضمام إلى مجموعة جديدة يستغرق يومًا تقريبًا.}=1{يمكنك إعادة ضبط مجموعتك متى شئت، مع العÙلم أنّ الانضمام إلى مجموعة جديدة يستغرق يومًا واحدًا تقريبًا.}two{يمكنك إعادة ضبط مجموعتك متى شئت، مع العÙلم أنّ الانضمام إلى مجموعة جديدة يستغرق يومَين ({NUM_DAYS}) تقريبًا.}few{يمكنك إعادة ضبط مجموعتك متى شئت، مع العÙلم أنّ الانضمام إلى مجموعة جديدة يستغرق {NUM_DAYS} أيام تقريبًا.}many{يمكنك إعادة ضبط مجموعتك متى شئت، مع العÙلم أنّ الانضمام إلى مجموعة جديدة يستغرق {NUM_DAYS} يومًا تقريبًا.}other{يمكنك إعادة ضبط مجموعتك متى شئت، مع العÙلم أنّ الانضمام إلى مجموعة جديدة يستغرق {NUM_DAYS} يوم تقريبًا.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />، و<ph name="DOMAIN" />، و<ph name="TIME" /></translation>
<translation id="3603507503523709">حظر مشرÙÙƒ التطبيق</translation>
<translation id="3608932978122581043">تخطيط الاتجاه</translation>
@@ -706,13 +727,13 @@
<translation id="3615877443314183785">أدخÙÙ„ تاريخ انتهاء صلاحية صحيحًا</translation>
<translation id="36224234498066874">محو بيانات التصÙّح...</translation>
<translation id="362276910939193118">عرض السجلّ بكامله</translation>
-<translation id="3625635938337243871">سيتم Ø­Ùظ بيانات تسجيل الدخول على هذا الجهاز بعد الخروج من "وضع التصÙÙ‘ÙØ­ المتخÙÙŠ".</translation>
<translation id="3630155396527302611">إذا تم بالÙعل إدراج صÙحة الويب كبرنامج مسموح له بالدخول إلى الشبكة، Ùجرّب
إزالتها من القائمة وإضاÙتها مرةً أخرى.</translation>
<translation id="3630699740441428070">أعدَّ مشرÙÙˆ هذا الجهاز اتصالك بالشبكة، ما قد يسمح لهم بالاطّلاع على حركة بيانات الشبكة الخاصة بك، بما ÙÙŠ ذلك المواقع الإلكترونية التي تزورها.</translation>
<translation id="3631244953324577188">المقاييس الحيوية</translation>
<translation id="3633738897356909127">â€Ø²Ø± "تحديث Chrome"ØŒ اضغط على Ù…Ùتاح Enter لتحديث Chrome من إعداداته.</translation>
<translation id="3634530185120165534">الدÙرج 5</translation>
+<translation id="3637662659967048211">â€Ø­Ùظ المعلومات ÙÙŠ حساب Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">التطبيق:</translation>
<translation id="3650584904733503804">تم التحقق بنجاح</translation>
@@ -753,6 +774,7 @@
<translation id="3781428340399460090">وردي برّاق</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">أجهزة بلوتوث</translation>
+<translation id="3787675388804467730">رقم البطاقة الاÙتراضية</translation>
<translation id="3787705759683870569">تنتهي ÙÙŠ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">الحجم 16</translation>
<translation id="3789841737615482174">تثبيت</translation>
@@ -772,6 +794,7 @@
<translation id="3841184659773414994">معالÙجات الملÙات</translation>
<translation id="385051799172605136">رجوع</translation>
<translation id="3858027520442213535">تحديث التاريخ والوقت</translation>
+<translation id="3881478300875776315">عرض أسطر أقل</translation>
<translation id="3884278016824448484">معر٠جهاز متضارب</translation>
<translation id="3885155851504623709">الأبرشية</translation>
<translation id="388632593194507180">تم رصد المراقبة</translation>
@@ -797,6 +820,7 @@
<translation id="397105322502079400">جار٠الحساب...</translation>
<translation id="3973234410852337861">تم حظر <ph name="HOST_NAME" /></translation>
<translation id="3973357910713125165">â€Ø²Ø± تشغيل ميزة "تأكيد السلامة" ÙÙŠ ChromeØŒ اضغط على Ù…Ùتاح Enter لتشغيل هذه الميزة ÙÙŠ إعدادات Chrome.</translation>
+<translation id="3986705137476756801">إيقا٠ميزة "النسخ النصي التلقائي" مؤقتًا</translation>
<translation id="3987405730340719549">â€ØªØ¨ÙŠÙ‘Ù† لمتصÙØ­ Chrome أن هذا الموقع الإلكتروني قد يكون مزيÙًا أو احتياليًا.
إذا كنت تعتقد أنّه تم عرض هذه الرسالة عن طريق الخطأ، ÙŠÙرجى الانتقال إلى https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -819,7 +843,7 @@
<translation id="4082393374666368382">الإعدادات - الإدارة</translation>
<translation id="4084120443451129199">â€ÙˆØ¶Ø¹ "البحث"ØŒ ÙŠÙرجى الضغط على Ù…Ùتاح Enter للبحث عن <ph name="KEYWORD_SUFFIX" />.</translation>
<translation id="4088981014127559358">â€Ø·Ø¨Ø§Ø¹Ø© جانب واحد image Y shift</translation>
-<translation id="4098354747657067197">أمامك موقع مخادع</translation>
+<translation id="4098354747657067197">أنت بصدد الانتقال إلى موقع إلكتروني مخادع</translation>
<translation id="4101413244023615925">النص والرسم</translation>
<translation id="4103249731201008433">الرقم التسلسلي للجهاز غير صالح</translation>
<translation id="4110652170750985508">مراجعة الدÙعة</translation>
@@ -893,13 +917,14 @@
<translation id="4275830172053184480">إعادة تشغيل جهازك</translation>
<translation id="4277028893293644418">إعادة ضبط كلمة المرور</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{â€ØªÙ… Ø­Ùظ هذه البطاقة ÙÙŠ حسابك على Google}zero{â€ØªÙ… Ø­Ùظ هذه البطاقات ÙÙŠ حسابك على Google}two{â€ØªÙ… Ø­Ùظ هاتين البطاقتين ÙÙŠ حسابك على Google}few{â€ØªÙ… Ø­Ùظ هذه البطاقات ÙÙŠ حسابك على Google}many{â€ØªÙ… Ø­Ùظ هذه البطاقات ÙÙŠ حسابك على Google}other{â€ØªÙ… Ø­Ùظ هذه البطاقات ÙÙŠ حسابك على Google}}</translation>
+<translation id="4287885627794386150">حسابك مؤهّل للحصول على إصدار تجريبي ولكنّه غير نشÙØ·.</translation>
<translation id="4297502707443874121">صورة مصغّرة لصÙحة <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">توسيع</translation>
<translation id="4300675098767811073">عمل عدة ثقوب يمينًا</translation>
<translation id="4302514097724775343">انقر على الديناصور لبدء اللعب.</translation>
<translation id="4302965934281694568">â€Chou3 (مغلÙ)</translation>
<translation id="4305666528087210886">تعذّر الوصول لملÙÙƒ</translation>
-<translation id="4305817255990598646">تبديل</translation>
+<translation id="4306529830550717874">هل تريد Ø­Ùظ العنوان؟</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">حظر (تلقائي)</translation>
<translation id="4314815835985389558">إدارة المزامنة</translation>
@@ -926,6 +951,7 @@
<translation id="4377125064752653719">لقد حاولت الوصول إلى <ph name="DOMAIN" />ØŒ ولكن جهة إصدار الشهادة التي قدمها الخادم قد أبطلت الشهادة. وهذا يعني أن بيانات اعتماد الأمان التي قدمها الخادم يجب عدم الوثوق بها مطلقًا. Ùقد تكون على اتصال بأحد المهاجمين.</translation>
<translation id="4378154925671717803">هاتÙ</translation>
<translation id="4390472908992056574">حاÙّة</translation>
+<translation id="4406883609789734330">النسخ النصي التلقائي</translation>
<translation id="4406896451731180161">نتائج البحث</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> من ملÙات تعري٠الارتباط</translation>
<translation id="4414290883293381923">â€Ù„قد أدخلت للتو كلمة المرور ÙÙŠ موقع إلكتروني مريب. وبالتالي، ينصح Chrome بالانتقال إلى <ph name="WEBSITE_1" /> Ùˆ<ph name="WEBSITE_2" /> Ùˆ<ph name="WEBSITE_3" /> ومواقع إلكترونية أخرى تستخدم Ùيها كلمة المرور هذه، وتغيير كلمة المرور الآن.</translation>
@@ -938,7 +964,6 @@
<translation id="4435702339979719576">بطاقة بريدية)</translation>
<translation id="443673843213245140">تم إيقا٠استخدام الخادم الوكيل ولكن تم تحديد إعداد صريح للخادم الوكيل.</translation>
<translation id="4464826014807964867">المواقع الإلكترونية التي تحتوي على معلومات واردة من مؤسستك</translation>
-<translation id="4466881336512663640">سيتم Ùقدان تغييرات النموذج. هل تريد Ùعلاً المتابعة؟</translation>
<translation id="4476953670630786061">هذا النموذج غير آمن. تمّ إيقا٠ميزة "الملء التلقائي".</translation>
<translation id="4477350412780666475">المقطع الصوتي التالي</translation>
<translation id="4482953324121162758">لن تتم ترجمة هذا الموقع.</translation>
@@ -972,6 +997,7 @@
<translation id="4594403342090139922">تراجع عن الحذ&amp;Ù</translation>
<translation id="4597348597567598915">الحجم 8</translation>
<translation id="4600854749408232102">â€C6/C5 (مغلÙ)</translation>
+<translation id="4606870351894164739">مؤثّÙر</translation>
<translation id="4628948037717959914">صورة</translation>
<translation id="4631649115723685955">تم ربط مكاÙأة لاسترداد جزء من المال.</translation>
<translation id="4636930964841734540">معلومات</translation>
@@ -991,6 +1017,7 @@
<translation id="4691835149146451662">â€Architecture-A (مغلÙ)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" />†<ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">الجانب</translation>
+<translation id="4702656508969495934">ميزة "النسخ النصي التلقائي" مرئية، ÙŠÙرجى استخدام مبدّÙÙ„ النواÙØ° للتركيز.</translation>
<translation id="4708268264240856090">تم قطع اتصالك</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131">â€<ph name="BEGIN_LINK" />تشغيل بيانات تشخيص شبكة Windows<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> اقتراحات البحث</translation>
<translation id="4742407542027196863">إدارة كلمات المرور…</translation>
<translation id="4744603770635761495">المسار التنÙيذي</translation>
+<translation id="4749011317274908093">لقد انتقلت إلى وضع التصÙÙ‘ÙØ­ المتخÙÙŠ</translation>
<translation id="4750917950439032686">ستكون معلوماتك (مثل كلمات المرور أو أرقام بطاقة الائتمان) خاصة عند إرسالها إلى هذا الموقع.</translation>
<translation id="4756388243121344051">ال&amp;سجل</translation>
<translation id="4758311279753947758">إضاÙØ© معلومات الاتصال</translation>
@@ -1033,6 +1061,8 @@
<translation id="4813512666221746211">حدث خطأ ÙÙŠ الشبكة</translation>
<translation id="4816492930507672669">احتواء ضمن الصÙحة</translation>
<translation id="4819347708020428563">هل تريد تعديل التعليقات التوضيحية ÙÙŠ العرض التلقائي؟</translation>
+<translation id="4825507807291741242">قوي</translation>
+<translation id="4838327282952368871">جذّاب</translation>
<translation id="484462545196658690">تلقائي</translation>
<translation id="4850886885716139402">عرض</translation>
<translation id="485316830061041779">الألمانية</translation>
@@ -1169,6 +1199,7 @@
<translation id="5314967030527622926">أداة إنشاء الكتيبات</translation>
<translation id="5316812925700871227">تدوير عكس اتجاه عقارب الساعة</translation>
<translation id="5317780077021120954">Ø­Ùظ</translation>
+<translation id="5321288445143113935">ناÙذة كبيرة الحجم</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />، <ph name="MATCH_POSITION" /> من <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">اختيار معلومات الاتصال</translation>
<translation id="5327248766486351172">الاسم</translation>
@@ -1176,11 +1207,13 @@
<translation id="5332219387342487447">طريقة الشحن</translation>
<translation id="5333022057423422993">â€Ù„قد عثر Chrome ÙÙŠ عمليّة اختراق للبيانات على كلمة المرور التي استخدمتها للتو. لحماية حساباتك، ننصحك بالتحقّق من كلمات مرورك المحÙوظة.</translation>
<translation id="5334013548165032829">سجلّات النظام التÙصيلية</translation>
+<translation id="5334145288572353250">هل تريد Ø­Ùظ العنوان؟</translation>
<translation id="5340250774223869109">التطبيق محظور</translation>
<translation id="534295439873310000">â€Ø£Ø¬Ù‡Ø²Ø© NFC</translation>
<translation id="5344579389779391559">قد تÙحاول هذه الصÙحة تحصيل رسوم منك</translation>
<translation id="5355557959165512791">لا يمكنك زيارة <ph name="SITE" /> الآن لأنه تم إبطال شهادته. أخطاء الشبكة والهجمات عليها عادةً ما تكون مؤقتة، لذا ستعمل هذه الصÙحة ÙÙŠ وقت على الأرجح.</translation>
<translation id="536296301121032821">تعذّر تخزين إعدادات السياسة</translation>
+<translation id="5363309033720083897">منÙØ° تسلسلي سمحَ به مشرÙÙƒ</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="5386426401304769735">â€ØªØªØ¶Ù…Ù† سلسلة الشهادات لهذا الموقع شهادة موقعة باستخدام SHA-1.</translation>
@@ -1189,6 +1222,7 @@
<translation id="5398772614898833570">تم حظر الإعلانات</translation>
<translation id="5400836586163650660">رمادي</translation>
<translation id="540969355065856584">لم يتمكن هذا الخادم من إثبات أنه <ph name="DOMAIN" />Ø› بل إن شهادة الأمان الخاصة به غير صالحة حاليًا. وربما يكون السبب ÙÙŠ ذلك وجود خطأ ÙÙŠ التكوين أو اعترض أحد المهاجمين للاتصال.</translation>
+<translation id="541143247543991491">السحابة الإلكترونية (على مستوى النظام)</translation>
<translation id="541416427766103491">المكدّÙس 4</translation>
<translation id="5421136146218899937">محو بيانات التصÙّح...</translation>
<translation id="5426179911063097041">يريد موقع <ph name="SITE" /> إرسال إشعارات إليك.</translation>
@@ -1202,6 +1236,7 @@
<translation id="5455374756549232013">الطابع الزمني للسياسة سيئ</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" />) أخريان}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="5463625433003343978">جار٠البحث عن أجهزة...</translation>
<translation id="5469868506864199649">الإيطالية</translation>
<translation id="5470861586879999274">إعادة الت&amp;حرير</translation>
<translation id="5478437291406423475">â€B6/C4 (مغلÙ)</translation>
@@ -1251,7 +1286,6 @@
<translation id="5624120631404540903">إدارة كلمات المرور</translation>
<translation id="5629630648637658800">تعذّر تحميل إعدادات السياسة</translation>
<translation id="5631439013527180824">الرمز المميز لإدارة الجهاز غير صالح</translation>
-<translation id="5632627355679805402">â€ØªÙ… ترميز بياناتك باستخدام <ph name="BEGIN_LINK" />كلمة مرور Google<ph name="END_LINK" /> اعتبارًا من. <ph name="TIME" />. ÙŠÙرجى إدخالها لبدء المزامنة.</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="5644090287519800334">â€Ø·Ø¨Ø§Ø¹Ø© الجانب الأول image X shift</translation>
@@ -1290,12 +1324,12 @@
<translation id="5785756445106461925">إضاÙØ© إلى ذلك، تتضمن هذه الصÙحة موارد أخرى غير آمنة. ويستطيع الآخرون مشاهدة هذه الموارد أثناء نقلها، كما يستطيع أي مهاجم تعديلها لتغيير مظهر الصÙحة.</translation>
<translation id="5786044859038896871">هل تريد ملء معلومات بطاقتك؟</translation>
<translation id="578633867165174378">â€Ù„قد عثر Chrome ÙÙŠ عمليّة اختراق للبيانات على كلمة المرور التي استخدمتها للتو. ننصحك بتغيير كلمة المرور هذه الآن.</translation>
-<translation id="5798290721819630480">هل تريد تجاهل التغييرات؟</translation>
<translation id="5803412860119678065">هل تريد ملء <ph name="CARD_DETAIL" />؟</translation>
<translation id="5804241973901381774">الأذونات</translation>
<translation id="5804427196348435412">â€Ø§Ø³ØªØ®Ø¯Ø§Ù… أجهزة NFC</translation>
<translation id="5810442152076338065">يتم ترميز اتصالك بالنطاق <ph name="DOMAIN" /> باستخدام مجموعة ترميز قديمة.</translation>
<translation id="5813119285467412249">إعا&amp;دة الإضاÙØ©</translation>
+<translation id="5817918615728894473">إقران</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{â€Ø³ÙŠØªÙ… تحصيل الرسوم من هذه البطاقة عند إجراء عملية الدÙع، ولن تتم مشاركة رقم البطاقة الحقيقي مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}zero{â€Ù„Ù… تختر أي بطاقة لتحصيل الرسوم منها عند إجراء عملية الدÙع، ولن تتم مشاركة رقم البطاقة الحقيقي مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}two{â€Ø¹Ù†Ø¯ إجراء عملية الدÙع، سيتم تحصيل الرسوم من البطاقتين اللتين تختارهما، ولن تتم مشاركة رقمَي البطاقتين الحقيقيَين مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}few{â€Ø¹Ù†Ø¯ إجراء عملية الدÙع، سيتم تحصيل الرسوم من البطاقات التي تختارها، ولن تتم مشاركة أرقام البطاقات الحقيقية مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}many{â€Ø¹Ù†Ø¯ إجراء عملية الدÙع، سيتم تحصيل الرسوم من البطاقات التي تختارها، ولن تتم مشاركة أرقام البطاقات الحقيقية مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}other{â€Ø¹Ù†Ø¯ إجراء عملية الدÙع، سيتم تحصيل الرسوم من البطاقات التي تختارها، ولن تتم مشاركة أرقام البطاقات الحقيقية مع هذا الموقع. لمزيد من الأمان، سيتم إنشاء رمز التحقق من البطاقة (CVC) بشكل مؤقت.}}</translation>
<translation id="5826507051599432481">â€Ø§Ù„اسم الشائع (CN)</translation>
<translation id="5838278095973806738">يجب عدم إدخال معلومات حسّاسة على هذا الموقع (مثل كلمات المرور أو بطاقات الائتمان) لأنه قد تتم سرقتها من Ù‚Ùبل المهاجمين.</translation>
@@ -1303,6 +1337,7 @@
<translation id="5855253129151731373">â€Ø§Ù„اسم المضي٠لهذا الموقع الإلكتروني يشبه النطاق <ph name="LOOKALIKE_DOMAIN" />. يحاكي المخترÙقون أحيانًا المواقع الإلكترونية من خلال إجراء تغييرات بسيطة يصعب رؤيتها على اسم النطاق.
إذا كنت تعتقد أنّه تم عرض هذه الرسالة عن طريق الخطأ، ÙŠÙرجى الانتقال إلى https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">غير Ù…Ùعّل</translation>
<translation id="5862579898803147654">المكدّÙس 8</translation>
<translation id="5863847714970149516">قد تحاول الصÙحة التالية تحصيل رسوم منك</translation>
<translation id="5866257070973731571">إضاÙØ© رقم الهاتÙ</translation>
@@ -1319,6 +1354,7 @@
<translation id="5913377024445952699">إيقا٠وضع "التقاط الشاشة" مؤقتًا</translation>
<translation id="59174027418879706">تم التÙعيل</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 قيد الاستخدام}zero{# قيد الاستخدام}two{# قيد الاستخدام}few{# قيد الاستخدام}many{# قيد الاستخدام}other{# قيد الاستخدام}}</translation>
<translation id="5921185718311485855">Ù…Ùعّل</translation>
<translation id="5921639886840618607">â€Ù‡Ù„ تريد Ø­Ùظ البطاقة ÙÙŠ حساب GoogleØŸ</translation>
<translation id="5922853866070715753">أوشكْت على الانتهاء.</translation>
@@ -1338,6 +1374,7 @@
<translation id="5989320800837274978">â€Ù„Ù… يتم تحديد أي من الخوادم الوكيلة الثابتة ولا عنوان URL للنص البرمجي pac.</translation>
<translation id="5992691462791905444">â€ØªØµÙ…يم الطي على شكل حر٠Z</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> من نتائج البحث عن "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">كلاسيكي</translation>
<translation id="6008122969617370890">طباعة الصÙحات بالترتيب المعكوس</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">التحقق من كلمات المرور</translation>
@@ -1359,6 +1396,7 @@
<translation id="6045164183059402045">نموذج الأمر</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="6049004884579590341">الضغط مع الاستمرار على |<ph name="ACCELERATOR" />| للخروج من وضع ملء الشاشة</translation>
<translation id="6049488691372270142">تسليم الصÙحة</translation>
<translation id="6051221802930200923">لا يمكنك زيارة <ph name="SITE" /> ÙÙŠ الوقت الحالي لأن الموقع يستخدم أداة التحقق من صحة الشهادات. أخطاء الشبكة والهجمات عليها عادةً ما تكون مؤقتة، لذا ستعمل هذه الصÙحة ÙÙŠ وقت لاحق على الأرجح.</translation>
<translation id="6051898664905071243">عدد الصÙحات:</translation>
@@ -1375,6 +1413,7 @@
<translation id="610911394827799129">â€Ù‚د يتضمّن حسابك على Google نماذج أخرى من سجلّ التصÙّح على <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">الاطلاع على النصوص والصور التي تم نسخها إلى الحاÙظة</translation>
<translation id="6120179357481664955">هل تتذكر معرّ٠واجهة الدÙعات الموحّدة؟</translation>
+<translation id="6123290840358279103">عرض البطاقة الاÙتراضية</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">تحقق من أي كابلات وأعد تشغيل أي أجهزة توجيه أو أجهزة مودم أو أجهزة شبكة
أخرى ربما تستخدمها.</translation>
@@ -1411,6 +1450,7 @@
<translation id="6289939620939689042">لون الصÙحة</translation>
<translation id="6290238015253830360">ستظهر المقالات المقترحة هنا</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">â€Ø¬Ø§Ø±Ù إيقا٠"مساعد Google" على Chrome</translation>
<translation id="6305205051461490394">يتعذر الوصول إلى <ph name="URL" />.</translation>
<translation id="6312113039770857350">صÙحة الويب غير متاحة</translation>
@@ -1436,6 +1476,7 @@
<translation id="6390200185239044127">â€Ø§Ù„طي إلى نصÙَين على شكل حر٠Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">تحظر سياسة المشر٠إمكانية اللصق من <ph name="ORIGIN_NAME" /> إلى هذا المكان.</translation>
+<translation id="6398765197997659313">إنهاء وضع ملء الشاشة</translation>
<translation id="6401136357288658127">تم إيقا٠هذه السياسة. يمكنك استخدام السياسة <ph name="NEW_POLICY" /> بدلاً من ذلك.</translation>
<translation id="6404511346730675251">تعديل الإشارة المرجعية</translation>
<translation id="6406765186087300643">â€C0 (مغلÙ)</translation>
@@ -1448,7 +1489,6 @@
<translation id="6428450836711225518">إثبات ملكية رقم الهاتÙ</translation>
<translation id="6433490469411711332">تعديل معلومات الاتصال</translation>
<translation id="6433595998831338502">رÙض <ph name="HOST_NAME" /> الاتصال.</translation>
-<translation id="6434309073475700221">تجاهل</translation>
<translation id="6440503408713884761">تم تجاهله</translation>
<translation id="6443406338865242315">الإضاÙات والمكوّنات الإضاÙية التي تثبّتها</translation>
<translation id="6446163441502663861">â€Kahu (مغلÙ)</translation>
@@ -1491,6 +1531,7 @@
<translation id="6624427990725312378">معلومات الاتصال</translation>
<translation id="6626291197371920147">إضاÙØ© رقم بطاقة صالح</translation>
<translation id="6628463337424475685">بحث <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">â€Ø¬Ø§Ø±Ù البحث عن أجهزة USB...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">محو</translation>
@@ -1506,6 +1547,7 @@
<translation id="6671697161687535275">â€Ù‡Ù„ تريد إزالة اقتراح النموذج من ChromiumØŸ</translation>
<translation id="6685834062052613830">الخروج وإكمال الإعداد</translation>
<translation id="6687335167692595844">حجم الخط المطلوب</translation>
+<translation id="6688743156324860098">تعديل…</translation>
<translation id="6689249931105087298">طباعة نسبية باستخدام ميزة "تعويض النقاط السوداء"</translation>
<translation id="6689271823431384964">â€ÙŠØªÙŠØ­ لك Chrome Ø­Ùظ بطاقاتك ÙÙŠ حسابك على Google لأنك سجَّلت الدخول. يمكنك تغيير هذا السلوك ÙÙŠ الإعدادات. ويتم الحصول على اسم حامل البطاقة من حسابك.</translation>
<translation id="6698381487523150993">تاريخ الإنشاء:</translation>
@@ -1521,6 +1563,7 @@
<translation id="6744009308914054259">أثناء انتظار اتصال، يمكنك الانتقال إلى مجلد "المحتوى الذي تم تنزيله" للاطّÙلاع على المقالات بلا اتصال بالإنترنت.</translation>
<translation id="6753269504797312559">قيمة السياسة</translation>
<translation id="6757797048963528358">خضع جهازك إلى وضع السكون.</translation>
+<translation id="6767985426384634228">هل تريد تعديل العنوان؟</translation>
<translation id="6768213884286397650">â€Hagaki (بطاقة بريدية)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">بنÙسجي</translation>
@@ -1543,6 +1586,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">â€Ø¨Ø³Ù‘ÙŽØ· Chrome عرض هذه الصÙحة لتسهيل قراءتها. استرَدّ Chrome الصÙحة الأصلية عبر اتصال غير آمن.</translation>
<translation id="6891596781022320156">مستوى السياسة غير مدعوم.</translation>
+<translation id="6895143722905299846">الرقم الاÙتراضي:</translation>
<translation id="6895330447102777224">تم التأكد من بطاقتك</translation>
<translation id="6897140037006041989">وكيل المستخدم</translation>
<translation id="6898699227549475383">â€Ø§Ù„مؤسسة (O)</translation>
@@ -1578,10 +1622,10 @@
<translation id="7004583254764674281">â€Ø§Ø³ØªØ®Ø¯Ø§Ù… Windows Hello للتأكد من البطاقات بشكل٠أسرع</translation>
<translation id="7006930604109697472">إرسال على أيّ حال</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">إعدادات تغيير الحجم</translation>
<translation id="7014741021609395734">مستوى التكبير أو التصغير</translation>
<translation id="7016992613359344582">قد يتمّ تحصيل هذه الرسوم لمرة واحدة أو بشكل متكرر، وقد تكون غير واضحة.</translation>
<translation id="7029809446516969842">كلمات المرور</translation>
+<translation id="7030436163253143341">الشهادة غير صالحة</translation>
<translation id="7031646650991750659">â€ØªØ·Ø¨ÙŠÙ‚ات Google Play التي ثبّتها</translation>
<translation id="7050187094878475250">لقد حاولت الوصول إلى <ph name="DOMAIN" />، ولكن الخادم قدم شهادة مدة صلاحيتها طويلة جدًا مما يجعلها غير جديرة بالثقة.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{تتعذَّر إضاÙØ© هذه البطاقة الآن}zero{تتعذَّر إضاÙØ© هذه البطاقات الآن}two{تتعذَّر إضاÙØ© هاتين البطاقتين الآن}few{تتعذَّر إضاÙØ© هذه البطاقات الآن}many{تتعذَّر إضاÙØ© هذه البطاقات الآن}other{تتعذَّر إضاÙØ© هذه البطاقات الآن}}</translation>
@@ -1651,12 +1695,14 @@
<translation id="7300012071106347854">أزرق كوبالت</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">مرتÙع</translation>
+<translation id="7305756307268530424">تشغيل اللعبة ببطء</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">المساعدة بشأن الاتصال</translation>
<translation id="7323804146520582233">إخÙاء قسم "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">إلغاء حساب الجهاز المحلي</translation>
<translation id="7333654844024768166">â€Ù„قد أدخلت للتو كلمة المرور ÙÙŠ موقع إلكتروني مريب. وبالتالي، ينصح Chromium بالانتقال إلى <ph name="WEBSITE_1" /> Ùˆ<ph name="WEBSITE_2" /> Ùˆ<ph name="WEBSITE_3" /> ومواقع إلكترونية أخرى تستخدم Ùيها كلمة المرور هذه، وتغيير كلمة المرور الآن.</translation>
<translation id="7334320624316649418">إعادة إ&amp;جراء الترتيب</translation>
+<translation id="7337248890521463931">عرض المزيد من الأسطر</translation>
<translation id="7337706099755338005">غير متاحة على نظامك الأساسي.</translation>
<translation id="733923710415886693">لم يتم الكش٠عن شهادة الخادم عن طريق شهادة الشÙاÙية.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1664,6 +1710,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">سطر الأوامر</translation>
<translation id="7359588939039777303">تم حظر الإعلانات.</translation>
+<translation id="7363096869660964304">على الرغم من أنّ نشاطك غير مرئي، إلا أنّ وضع التصÙÙ‘ÙØ­ المتخÙÙŠ لا يخÙÙŠ بيانات تصÙÙ‘Ùحك عن صاحب العمل أو مزوّد خدمة الإنترنت أو المواقع الإلكترونية التي تزورها.</translation>
<translation id="7365596969960773405">â€<ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ اضغط على Ù…Ùتاح التبويب (Tab) ثم Ù…Ùتاح Enter لإضاÙØ© عناوين وإدارتها ÙÙŠ إعدادات متصÙّح Chrome.</translation>
<translation id="7365849542400970216">هل تسمح للموقع الإلكتروني برصد استخدامك للجهاز؟</translation>
<translation id="7372973238305370288">نتيجة البحث</translation>
@@ -1674,7 +1721,9 @@
<translation id="7378594059915113390">عناصر التحكم ÙÙŠ الوسائط</translation>
<translation id="7378627244592794276">لا</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">غير سارÙ</translation>
<translation id="7390545607259442187">التأكد من البطاقة</translation>
+<translation id="7392089738299859607">تعديل العنوان</translation>
<translation id="7399802613464275309">تأكيد السلامة</translation>
<translation id="7400418766976504921">â€Ø¹Ù†ÙˆØ§Ù† URL</translation>
<translation id="7403591733719184120">إدارة <ph name="DEVICE_NAME" /></translation>
@@ -1689,6 +1738,7 @@
&lt;li&gt;انتقÙÙ„ إلى &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;مركز مساعدة Chrome&lt;/a&gt; لمعرÙØ© كيÙية إزالة البرنامج من جهاز الكمبيوتر نهائيًا
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">رائع</translation>
<translation id="7416351320495623771">إدارة كلمات المرور…</translation>
<translation id="7419106976560586862">مسار المل٠الشخصي</translation>
<translation id="7437289804838430631">إضاÙØ© معلومات الاتصال</translation>
@@ -1704,7 +1754,7 @@
<translation id="7481312909269577407">إلى الأمام</translation>
<translation id="7485870689360869515">لم يتم العثور على بيانات.</translation>
<translation id="7495528107193238112">هذا المحتوى محظور. يمكنك التواصل مع مالك الموقع الإلكتروني لحلّ المشكلة.</translation>
-<translation id="7498234416455752244">متابعة التعديل</translation>
+<translation id="7498193950643227031">قد لا يعمل التطبيق بالشكل المطلوب إذا تم تغيير حجمه. يمكنك الآن إيقا٠ميزة تغيير حجم التطبيقات من خلال <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">â€Ù„قد أدخلت للتو كلمة المرور ÙÙŠ موقع إلكتروني مريب. وللحÙاظ على أمان بياناتك، ينصحك Chromium بالتحقّق من كلمات المرور المحÙوظة للموقعين الإلكترونيين <ph name="WEBSITE_1" /> Ùˆ<ph name="WEBSITE_2" /> وغيرهما من المواقع التي تستخدم Ùيها الآن كلمة المرور هذه.</translation>
<translation id="7508255263130623398">رقم تعري٠الجهاز المعروض للسياسة Ùارغ أو لا يتطابق مع رقم تعري٠الجهاز الحالي</translation>
<translation id="7508870219247277067">أخضر مصÙر</translation>
@@ -1724,6 +1774,7 @@
<translation id="7548892272833184391">إصلاح أخطاء الاتصال</translation>
<translation id="7549584377607005141">تتطلب صÙحة الويب هذه البيانات التي أدخلتها ÙÙŠ وقت سابق لعرضها بشكل صحيح. يمكنك إرسال هذه المعلومات مرة أخرى ولكن بذلك ستكرر أي إجراء اتخذته هذه الصÙحة ÙÙŠ وقت سابق.</translation>
<translation id="7550637293666041147">â€Ø§Ø³Ù… مستخدم الجهاز واسم مستخدم Chrome</translation>
+<translation id="755279583747225797">الإصدار التجريبي نشÙØ·.</translation>
<translation id="7552846755917812628">جرّب النصائح التالية:</translation>
<translation id="7554475479213504905">إعادة التحميل والعرض على أيّ حال</translation>
<translation id="7554791636758816595">علامة تبويب جديدة</translation>
@@ -1742,7 +1793,6 @@
<translation id="7610193165460212391">القيمة خارج النطاق <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">تاريخ انتهاء الصلاحية: <ph name="EXPIRATION_MONTH" /> / <ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628">â€<ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ اضغط على Ù…Ùتاح التبويب (Tab) ثم Ù…Ùتاح Enter لعرض كلمات المرور ÙÙŠ إعدادات Chrome وإدارتها.</translation>
-<translation id="7615602087246926389">â€Ù„ديك Ùعلاً بيانات تم تشÙيرها باستخدام نسخة أخرى من كلمة مرور حسابك ÙÙŠ Google. ÙŠÙرجى إدخالها أدناه.</translation>
<translation id="7616645509853975347">â€Ù„قد Ùعّل مشرÙÙƒ "وصلات Chrome Enterprise" على متصÙّحك. لدى هذه الوصلات إذن بالوصول إلى بعض بياناتك.</translation>
<translation id="7619838219691048931">ورقة النهاية</translation>
<translation id="762844065391966283">واحد تلو الآخر</translation>
@@ -1807,13 +1857,12 @@
<translation id="782886543891417279">â€Ù‚د يتطلب Wi-Fi الذي تستخدمه (<ph name="WIFI_NAME" />) زيارة صÙحة تسجيل الدخول.</translation>
<translation id="7836231406687464395">â€Postfix (مغلÙ)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{لا تتوÙَّر تطبيقات}=1{تطبيق واحد (<ph name="EXAMPLE_APP_1" />)}=2{تطبيقان (<ph name="EXAMPLE_APP_1" />ØŒ Ùˆ<ph name="EXAMPLE_APP_2" />)}few{# تطبيقات (<ph name="EXAMPLE_APP_1" />ØŒ Ùˆ<ph name="EXAMPLE_APP_2" />ØŒ Ùˆ<ph name="AND_MORE" /> من التطبيقات الأخرى)}many{# تطبيقات (<ph name="EXAMPLE_APP_1" />ØŒ Ùˆ<ph name="EXAMPLE_APP_2" />ØŒ Ùˆ<ph name="AND_MORE" /> من التطبيقات الأخرى)}other{# تطبيقات (<ph name="EXAMPLE_APP_1" />ØŒ Ùˆ<ph name="EXAMPLE_APP_2" />ØŒ Ùˆ<ph name="AND_MORE" /> من التطبيقات الأخرى)}}</translation>
-<translation id="785549533363645510">ومع ذلك، أنت غير مرئي. لا يخÙÙŠ الانتقال إلى وضع التخÙÙŠ التصÙØ­ من صاحب العمل أو مزود خدمة الإنترنت أو المواقع التي تزورها.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Ùتح أنواع الملÙات ذات الصلة</translation>
<translation id="7862185352068345852">هل تريد مغادرة الموقع؟</translation>
<translation id="7865448901209910068">Ø£Ùضل سرعة</translation>
<translation id="7874263914261512992">â€Ù„قد أدخلت للتو كلمة المرور ÙÙŠ موقع إلكتروني مريب. وللحÙاظ على أمان بياناتك، ينصحك متصÙّح Chrome بالتحقّق من كلمات المرور المحÙوظة للموقعين الإلكترونيين <ph name="WEBSITE_1" /> Ùˆ<ph name="WEBSITE_2" /> وغيرهما من المواقع التي تستخدم Ùيها الآن كلمة المرور هذه.</translation>
<translation id="7878562273885520351">من المحتمل أنه تم اختراق كلمة مرورك</translation>
+<translation id="7880146494886811634">Ø­Ùظ العنوان</translation>
<translation id="7882421473871500483">بني</translation>
<translation id="7887683347370398519">â€ØªØ­Ù‚Ù‚ من رمز التحقق من البطاقة (CVC) ثم أعد المحاولة.</translation>
<translation id="7887885240995164102">الدخول ÙÙŠ وضع "ناÙذة ضمن ناÙذة"</translation>
@@ -1821,6 +1870,7 @@
<translation id="7894280532028510793">إذا تم التأكÙد من عدم ورود أخطاء إملائية، ÙŠÙرجى <ph name="BEGIN_LINK" />محاولة تشغيل بيانات تشخيص الشبكة<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">â€C3 (مغلÙ)</translation>
<translation id="7931318309563332511">غير معروÙ</translation>
+<translation id="793209273132572360">هل تريد تعديل العنوان؟</translation>
<translation id="7932579305932748336">الطبقة الخارجية</translation>
<translation id="79338296614623784">أدخÙÙ„ رقم هات٠صحيحًا</translation>
<translation id="7934052535022478634">اكتمل إجراء الدÙع</translation>
@@ -1891,6 +1941,7 @@
<translation id="8175796834047840627">â€ÙŠØªÙŠØ­ لك Chrome Ø­Ùظ بطاقاتك ÙÙŠ حسابك على Google لأنك سجَّلت الدخول. يمكنك تغيير هذا السلوك ÙÙŠ الإعدادات.</translation>
<translation id="8176440868214972690">أرسل مشر٠هذا الجهاز بعض المعلومات، مثل الإعدادات أو السياسات، إلى المواقع الإلكترونية التالية.</translation>
<translation id="8184538546369750125">استخدام الإعداد التلقائي العمومي (سماح)</translation>
+<translation id="8193086767630290324">الإجراءات المÙتَّخَذة بخصوص البيانات التي يتم وضع علامة عليها على أنّها سرية</translation>
<translation id="8194797478851900357">تراجع عن ال&amp;نقل</translation>
<translation id="8201077131113104583">â€Ø¹Ù†ÙˆØ§Ù† URL لتحديث الإضاÙØ© التي تحتوي على رقم التعري٠"<ph name="EXTENSION_ID" />" غير صالح.</translation>
<translation id="8202097416529803614">ملخص الطلب</translation>
@@ -1913,6 +1964,7 @@
<translation id="8249296373107784235">إلغاء</translation>
<translation id="8249320324621329438">تاريخ آخر عملية جلب:</translation>
<translation id="8253091569723639551">عنوان إرسال الÙواتير مطلوب</translation>
+<translation id="8257387598443225809">هذا التطبيق مصمّم للعمل مع الأجهزة الجوّالة</translation>
<translation id="825929999321470778">عرض جميع كلمات المرور المحÙوظة</translation>
<translation id="8261506727792406068">حذÙ</translation>
<translation id="8262952874573525464">خزم الحوا٠من الأسÙÙ„</translation>
@@ -2037,7 +2089,6 @@
<translation id="8719528812645237045">عمل عدة ثقوب بالأعلى</translation>
<translation id="8725066075913043281">أعد المحاولة</translation>
<translation id="8726549941689275341">حجم الصÙحة:</translation>
-<translation id="8728672262656704056">لقد انتقلت إلى التصÙّح المتخÙÙŠ</translation>
<translation id="8730621377337864115">تم</translation>
<translation id="8731544501227493793">â€Ø²Ø± "إدارة كلمات المرور"ØŒ اضغط على Ù…Ùتاح Enter لعرض كلمات المرور ÙÙŠ إعدادات متصÙÙ‘ÙØ­ Chrome وإدارتها.</translation>
<translation id="8734529307927223492">يدير <ph name="MANAGER" /> الجهاز <ph name="DEVICE_TYPE" />.</translation>
@@ -2114,6 +2165,7 @@
<translation id="9020542370529661692">تمت ترجمة هذه الصÙحة إلى <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(غير صالحة)</translation>
+<translation id="9030265603405983977">أحادي اللون</translation>
<translation id="9035022520814077154">خطأ متعلق بالأمان</translation>
<translation id="9038649477754266430">استخدام إحدى خدمات التوقع لتحميل الصÙحات بسرعة أكبر</translation>
<translation id="9039213469156557790">إضاÙØ© إلى ذلك، تتضمن هذه الصÙحة موارد أخرى غير آمنة. ويستطيع الآخرون مشاهدة هذه الموارد أثناء نقلها، كما يستطيع أي مهاجم تعديلها لتغيير سلوك الصÙحة.</translation>
@@ -2137,6 +2189,7 @@
<translation id="91108059142052966">تحظر سياسة المشر٠إمكانية مشاركة الشاشة مع <ph name="APPLICATION_TITLE" /> عند عرض محتوى سري.</translation>
<translation id="9114524666733003316">جار٠التحقق من البطاقة...</translation>
<translation id="9114581008513152754">â€Ù„ا تتم إدارة هذا المتصÙÙ‘ÙØ­ من خلال شركة أو مؤسسة أخرى. وقد تتم إدارة النشاط على هذا الجهاز خارج Chrome. <ph name="BEGIN_LINK" />مزيد من المعلومات<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">جديد</translation>
<translation id="9119042192571987207">تم التحميل</translation>
<translation id="9128016270925453879">تم تحميل السياسات.</translation>
<translation id="9128870381267983090">الاتصال بالشبكة</translation>
@@ -2155,6 +2208,7 @@
<translation id="9170848237812810038">&amp;إلغاء</translation>
<translation id="9171296965991013597">هل تريد مغادرة التطبيق؟</translation>
<translation id="9173282814238175921">مستند واحد/ورقة جديدة</translation>
+<translation id="9173995187295789444">جار٠البحث عن أجهزة بلوتوث...</translation>
<translation id="917450738466192189">شهادة الخادم غير صالحة.</translation>
<translation id="9174917557437862841">â€Ø²Ø± التبديل بين علامات التبويب، اضغط على Enter للتبديل إلى علامة التبويب هذه</translation>
<translation id="9179703756951298733">â€Ø¥Ø¯Ø§Ø±Ø© معلومات الدÙعات وبطاقة الائتمان ÙÙŠ إعدادات متصÙÙ‘ÙØ­ Chrome</translation>
diff --git a/chromium/components/strings/components_strings_as.xtb b/chromium/components/strings/components_strings_as.xtb
index e06564c3944..dfe17e06e77 100644
--- a/chromium/components/strings/components_strings_as.xtb
+++ b/chromium/components/strings/components_strings_as.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">যদি চà§à¦šà§‡à¦• বাকচটো চà§à¦šà§‡à¦• কৰা হয় তেনà§à¦¤à§‡ Chromeঠফরà§à¦®à§° কà§à¦·à¦¿à¦ªà§à§°à¦¤à¦¾à§°à§‡ পà§à§°à¦¾à¦¬à¦²à§ˆ আপোনাৰ কারà§à¦¡à§° à¦à¦Ÿà¦¾ পà§à§°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿ à¦à¦‡ ডিভাইচত ষà§à¦Ÿâ€™à§° কৰিব।</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" />ৰ বাবে অনà§à¦®à¦¤à¦¿ বাছনি কৰক</translation>
<translation id="1113869188872983271">পà§à¦¨à¦ƒà¦•à§à§°à¦® কৰাটো &amp;আনডৠকৰক</translation>
+<translation id="1123753900084781868">à¦à¦‡ মà§à¦¹à§‚ৰà§à¦¤à¦¤ লাইভ কেপশà§à¦¬à¦¨ উপলবà§à¦§ নহয়</translation>
<translation id="1125573121925420732">ৱেবছাইটসমূহে নিজৰ সà§à§°à¦•à§à¦·à¦¾ আপডে'ট কৰোà¦à¦¤à§‡ সরà§à¦¤à¦•à¦¤à¦¾ বারà§à¦¤à¦¾ পোৱাটো সাধাৰণ কথা। à¦à¦‡à§Ÿà¦¾ অতি সোনকালেই উনà§à¦¨à¦¤ হ'ব লাগে।</translation>
<translation id="112840717907525620">নীতিটোৰ কেশà§à¦¬ ঠিকে আছে</translation>
<translation id="1130564665089811311">পৃষà§à¦ à¦¾ অনà§à¦¬à¦¾à¦¦ কৰক বà§à¦Ÿà¦¾à¦®, à¦à¦‡ পৃষà§à¦ à¦¾à¦–ন Google Translateৰ জৰিয়তে অনà§à¦¬à¦¾à¦¦ কৰিবলৈ à¦à¦£à§à¦Ÿà¦¾à§° টিপক</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">আপোনাৰ ডিভাইচৰ নাম</translation>
<translation id="124116460088058876">অধিক ভাষা</translation>
<translation id="1243027604378859286">লেখক:</translation>
+<translation id="1246424317317450637">ব’লà§à¦¡</translation>
<translation id="1250759482327835220">পৰৱৰà§à¦¤à§€ সময়ত দà§à§°à§à¦¤à¦­à¦¾à§±à§‡ পৰিশোধ কৰিবলৈ আপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦¤ নিজৰ কাৰà§à¦¡, নাম আৰৠবিলিঙৰ ঠিকনা ছেভ কৰক।</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (ছিংক কৰা আছে)</translation>
<translation id="1256368399071562588">&lt;p&gt;আপà§à¦¨à¦¿ চাব খোজা কোনো ৱেবছাইট নà§à¦–à§à¦²à¦¿à¦²à§‡, পà§à§°à¦¥à¦®à§‡ আসোà¦à§±à¦¾à¦¹à¦Ÿà§‹ à¦à¦‡ সমসà§à¦¯à¦¾ সমাধানৰ পদকà§à¦·à§‡à¦ªà¦¸à¦®à§‚হৰ জৰিয়তে সমাধান কৰিবলৈ চাওক:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">আপোনাৰ পাছৱরà§à¦¡ সলনি কৰক</translation>
<translation id="1484290072879560759">শà§à¦¬à¦¿à¦ªà¦¿à¦™à§° ঠিকনা বাছনি কৰক</translation>
<translation id="1492194039220927094">নীতি বলৱৎ কৰা:</translation>
+<translation id="1495677929897281669">টেবলৈ উভতি যাওক</translation>
<translation id="1501859676467574491">আপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà§° পৰা কারà§à¦¡à¦¸à¦®à§‚হ দেখà§à§±à¦¾à¦“ক</translation>
<translation id="1507202001669085618">&lt;p&gt;আপà§à¦¨à¦¿ অনলাইন হোৱাৰ পূরà§à¦¬à§‡ ছাইন ইন কৰিব লগা কোনো ৱাই-ফাই পরà§à¦Ÿà§‡à¦² বà§à¦¯à§±à¦¹à¦¾à§° কৰিলে à¦à¦‡ সমসà§à¦¯à¦Ÿà§‹à§° সনà§à¦®à§à¦–ীন হ’ব।&lt;/p&gt;
&lt;p&gt;à¦à¦‡ সমসà§à¦¯à¦¾à¦Ÿà§‹ সমাধান কৰিবলৈ, আপà§à¦¨à¦¿ খà§à¦²à¦¿à¦¬à¦²à§ˆ চেষà§à¦Ÿà¦¾ কৰি থকা পৃষà§à¦ à¦¾à¦Ÿà§‹à¦¤ &lt;শকà§à¦¤à¦¿à¦¶à¦¾à¦²à§€&gt;সংযোগ কৰক&lt;/শকà§à¦¤à¦¿à¦¶à¦¾à¦²à§€&gt;-ত কà§à¦²à¦¿à¦• কৰক।&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">à¦à¦‡ পৃষà§à¦ à¦¾à¦Ÿà§‹à§±à§‡ কৈছে</translation>
<translation id="153384715582417236">à¦à¦¤à¦¿à§Ÿà¦¾à§° বাবে ইমানেই</translation>
<translation id="1536390784834419204">পৃষà§à¦ à¦¾à¦–ন অনà§à¦¬à¦¾à¦¦ কৰক</translation>
+<translation id="1539840569003678498">অভিযোগ পঠিওৱা হ’ল:</translation>
<translation id="154408704832528245">ডেলিভাৰী ঠিকনা বাছনি কৰক</translation>
<translation id="1549470594296187301">à¦à¦‡ সà§à¦¬à¦¿à¦§à¦¾à¦Ÿà§‹ বà§à¦¯à§±à¦¹à¦¾à§° কৰিবলৈ হ'লে JavaScript সকà§à¦·à¦® কৰা থাকিবই লাগিব।</translation>
<translation id="155039086686388498">অভিযানà§à¦¤à§à¦°à¦¿à¦•-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">চà§à¦Ÿà¦¿ কাষটো পà§à§°à¦¥à¦®à§‡</translation>
<translation id="168693727862418163">à¦à¦‡ নীতিৰ মানটোৱে ইয়াৰ সà§à¦•à§€à¦®à¦¾à§° বিৰà§à¦¦à§à¦§à§‡ সতà§à¦¯à¦¾à¦ªà¦¨ কৰিব নোৱাৰিলে আৰৠইয়াক উপেকà§à¦·à¦¾ কৰা হ’ব।</translation>
<translation id="168841957122794586">ছারà§à¦­à¦¾à§° পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§°à¦–নত à¦à¦Ÿà¦¾ দà§à§°à§à¦¬à¦² কà§à§°à¦¿à¦ªà§à¦Ÿà¦—à§à§°à¦¾à¦«à¦¿à¦• কী আছে।</translation>
+<translation id="1696290444144917273">ভাৰà§à¦›à§à§±à§‡à¦² কাৰà§à¦¡à§° সবিশেষ চাওক</translation>
<translation id="1697532407822776718">আপà§à¦¨à¦¿ সমà§à¦ªà§‚ৰà§à¦£ সাজà§!</translation>
<translation id="1703835215927279855">লেটাৰ</translation>
<translation id="1706954506755087368">{1,plural, =1{à¦à¦‡ ছাৰà§à¦­à¦¾à§°à¦Ÿà§‹à§±à§‡ à¦à¦‡à¦Ÿà§‹à¦• <ph name="DOMAIN" /> বà§à¦²à¦¿ পà§à§°à¦®à¦¾à¦£ কৰিব নোৱাৰিলে, ইয়াৰ সà§à§°à¦•à§à¦·à¦¾ পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§° কাইলৈৰপৰা মানà§à¦¯ হ’লহেà¦à¦¤à§‡à¦¨à¥¤ কোনো ভà§à¦² কনফিগাৰেশà§à¦¬à¦¨à§° বাবে বা কোনো আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à§Ÿà§‡ আপোনাৰ সংযোগ অৱৰোধ কৰাৰ বাবে à¦à§Ÿà¦¾ হ’ব পাৰে।}one{à¦à¦‡ ছাৰà§à¦­à¦¾à§°à¦Ÿà§‹à§±à§‡ à¦à¦‡à¦Ÿà§‹à¦• <ph name="DOMAIN" /> বà§à¦²à¦¿ পà§à§°à¦®à¦¾à¦£ কৰিব নোৱাৰিলে, ইয়াৰ সà§à§°à¦•à§à¦·à¦¾ পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§° # দিনৰ পিছত মানà§à¦¯ হ’লহেà¦à¦¤à§‡à¦¨à¥¤ কোনো ভà§à¦² কনফিগাৰেশà§à¦¬à¦¨à§° বাবে বা কোনো আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à§Ÿà§‡ আপোনাৰ সংযোগ অৱৰোধ কৰাৰ বাবে à¦à§Ÿà¦¾ হ’ব পাৰে।}other{à¦à¦‡ ছাৰà§à¦­à¦¾à§°à¦Ÿà§‹à§±à§‡ à¦à¦‡à¦Ÿà§‹à¦• <ph name="DOMAIN" /> বà§à¦²à¦¿ পà§à§°à¦®à¦¾à¦£ কৰিব নোৱাৰিলে, ইয়াৰ সà§à§°à¦•à§à¦·à¦¾ পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§° # দিনৰ পিছত মানà§à¦¯ হ’লহেà¦à¦¤à§‡à¦¨à¥¤ কোনো ভà§à¦² কনফিগাৰেশà§à¦¬à¦¨à§° বাবে বা কোনো আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à§Ÿà§‡ আপোনাৰ সংযোগ অৱৰোধ কৰাৰ বাবে à¦à§Ÿà¦¾ হ’ব পাৰে।}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" />টো <ph name="VALUE" /> হিচাপে ছেট কৰা নাই বাবে অৱজà§à¦žà¦¾ কৰা হৈছে।</translation>
<translation id="1712552549805331520"><ph name="URL" />ঠআপোনাৰ ল’কেল কমà§à¦ªà¦¿à¦‰à¦Ÿà¦¾à§°à¦¤ সà§à¦¥à¦¾à§Ÿà§€à¦­à¦¾à§±à§‡ ডেটা ষà§à¦Ÿâ€™à§° কৰিব বিচাৰে</translation>
<translation id="1713628304598226412">টà§à§°à§‡â€™ ২</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">মেইলবকà§à¦¸ ৩</translation>
<translation id="1718029547804390981">নথিটো ইমানেই ডাঙৰ যে সেইটো à¦à¦¨â€™à¦Ÿà§‡à¦Ÿ কৰিব নোৱাৰি</translation>
<translation id="1721424275792716183">* কà§à¦·à§‡à¦¤à§à§°à¦Ÿà§‹ আৱশà§à¦¯à¦•à§€à¦¯à¦¼</translation>
+<translation id="1727613060316725209">পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§°à¦–ন মানà§à¦¯</translation>
<translation id="1727741090716970331">মানà§à¦¯ কাৰà§à¦¡à§° নমà§à¦¬à§° যোগ কৰক</translation>
<translation id="1728677426644403582">আপà§à¦¨à¦¿ কোনো ৱেব পৃষà§à¦ à¦¾à§° উৎস চাই আছে</translation>
<translation id="173080396488393970">à¦à¦‡ ধৰণৰ কারà§à¦¡ সমরà§à¦¥à¦¨ নকৰে</translation>
@@ -246,7 +253,6 @@
অনà§à§°à§‹à¦§à¦Ÿà§‹ পৰিপূৰà§à¦£ কৰাত বাধা দিয়ে। কোনো ছাইটৰ বাবে
সà§à§°à¦•à§à¦·à¦¾ আৰৠঅনà§à¦¯ বৈশিষà§à¦Ÿà§à¦¯à¦¸à¦®à§‚হ কনফিগাৰ কৰিবলৈ ছাইট অপাৰেটৰসকলে মূল নীতিসমূহ বà§à¦¯à§±à¦¹à¦¾à§° কৰিব পাৰে।</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">অনà§à¦—à§à§°à¦¹ কৰি আপোনাৰ ছিংক পাছফà§à§°à§‡à¦œ আপডে’ট কৰক।</translation>
<translation id="1787142507584202372">আপà§à¦¨à¦¿ খোলা টেববোৰ ইয়াত দেখা যাব</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, à¦à¦•à¦¾à¦§à¦¿à¦• কাৰà§à¦¯ উপলবà§à¦§, সেইবিলাক à¦à¦Ÿà¦¾ à¦à¦Ÿà¦¾à¦•à§ˆ চাবলৈ টেব টিপক</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">বিজà§à¦žà¦¾à¦ªà¦¨à¦¸à¦®à§‚হ</translation>
<translation id="1919367280705858090">কোনো নিরà§à¦¦à¦¿à¦·à§à¦Ÿ আসোà¦à§±à¦¾à¦¹ বারà§à¦¤à¦¾à§° জৰিয়তে সহায় পাওক</translation>
<translation id="192020519938775529">{COUNT,plural, =0{à¦à¦Ÿà¦¾à¦“ নহয়}=1{১টা ছাইট}one{#টা ছাইট}other{#টা ছাইট}}</translation>
+<translation id="1924727005275031552">নতà§à¦¨</translation>
<translation id="1945968466830820669">আপà§à¦¨à¦¿ আপোনাৰ পà§à§°à¦¤à¦¿à¦·à§à¦ à¦¾à¦¨à§° à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦Ÿà§‹ à¦à¦•à§à¦¸à§‡à¦› কৰিব নোৱাৰা হ‘ব পাৰে বা আপোনাৰ পৰিচয় চà§à§°à¦¿ হোৱাৰ নিচিনা ঘটনাৰ মà§à¦–ামà§à¦–ী হ‘ব পাৰে। Chromiumঠআপোনাৰ পাছৱৰà§à¦¡à¦Ÿà§‹ à¦à¦¤à¦¿à§Ÿà¦¾à¦‡ সলনি কৰাটো চà§à¦ªà¦¾à§°à¦¿à¦› কৰিছে।</translation>
<translation id="1947454675006758438">সোà¦à¦«à¦¾à¦²à§‡ ওপৰৰ অংশত ষà§à¦Ÿà§‡'পল কৰক</translation>
<translation id="1958218078413065209">আপোনাৰ সৰà§à¦¬à§‹à¦šà§à¦š সà§à¦•â€™à§° হৈছে <ph name="SCORE" />।</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">টà§à§°à§‡â€™ ৭</translation>
<translation id="204357726431741734">আপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦¤ ষà§à¦Ÿâ€™à§° হৈ থকা পাছৱৰà§à¦¡à¦¸à¦®à§‚হ বà§à¦¯à§±à¦¹à¦¾à§° কৰিবলৈ ছাইন ইন কৰক</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> ভাষাৰ পৃষà§à¦ à¦¾à¦¸à¦®à§‚হ অনà§à¦¬à¦¾à¦¦ কৰা নহয়।</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{à¦à¦‡ নিয়নà§à¦¤à§à§°à¦£à¦Ÿà§‹ অন কৰা অৱসà§à¦¥à¦¾à¦¤ আৰৠসà§à¦¥à¦¿à¦¤à¦¿à¦Ÿà§‹ সকà§à§°à¦¿à§Ÿ হৈ থাকিলে, Chromeঠআপোনাৰ শেহতীয়া বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§° কাৰà§à¦¯à¦•à¦²à¦¾à¦ªà§° সৈতে সকলোতকৈ বেছি মিলা বহà§à¦¤à§‹ লোকৰ গোট অথবা “à¦à¦•à§‡à¦§à§°à¦£à§° বৈশিষà§à¦Ÿà§à¦¯ শà§à¦¬à§‡à§Ÿà¦¾à§° কৰা গোট†নিৰà§à¦§à¦¾à§°à¦£ কৰে। বিজà§à¦žà¦¾à¦ªà¦¨à¦¦à¦¾à¦¤à¦¾à¦‡ গোটটোৰ বাবে বিজà§à¦žà¦¾à¦ªà¦¨ বাছনি কৰিব পাৰে আৰৠআপোনাৰ ডিভাইচত আপোনাৰ বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§° কাৰà§à¦¯à¦•à¦²à¦¾à¦ª বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত কৰি ৰখা হয়। আপোনাৰ গোটটো পà§à§°à¦¤à¦¿à¦¦à¦¿à¦¨à§‡ আপডে’ট কৰা হয়।}=1{à¦à¦‡ নিয়নà§à¦¤à§à§°à¦£à¦Ÿà§‹ অন কৰা অৱসà§à¦¥à¦¾à¦¤ আৰৠসà§à¦¥à¦¿à¦¤à¦¿à¦Ÿà§‹ সকà§à§°à¦¿à§Ÿ হৈ থাকিলে, Chromeঠআপোনাৰ শেহতীয়া বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§° কাৰà§à¦¯à¦•à¦²à¦¾à¦ªà§° সৈতে সকলোতকৈ বেছি মিলা বহà§à¦¤à§‹ লোকৰ গোট অথবা “à¦à¦•à§‡à¦§à§°à¦£à§° বৈশিষà§à¦Ÿà§à¦¯ শà§à¦¬à§‡à§Ÿà¦¾à§° কৰা গোট†নিৰà§à¦§à¦¾à§°à¦£ কৰে। বিজà§à¦žà¦¾à¦ªà¦¨à¦¦à¦¾à¦¤à¦¾à¦‡ গোটটোৰ বাবে বিজà§à¦žà¦¾à¦ªà¦¨ বাছনি কৰিব পাৰে আৰৠআপোনাৰ ডিভাইচত আপোনাৰ বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§° কাৰà§à¦¯à¦•à¦²à¦¾à¦ª বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত কৰি ৰখা হয়। আপোনাৰ গোটটো পà§à§°à¦¤à¦¿à¦¦à¦¿à¦¨à§‡ আপডে’ট কৰা হয়।}one{à¦à¦‡ নিয়নà§à¦¤à§à§°à¦£à¦Ÿà§‹ অন কৰা অৱসà§à¦¥à¦¾à¦¤ আৰৠসà§à¦¥à¦¿à¦¤à¦¿à¦Ÿà§‹ সকà§à§°à¦¿à§Ÿ হৈ থাকিলে, Chromeঠআপোনাৰ শেহতীয়া বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§° কাৰà§à¦¯à¦•à¦²à¦¾à¦ªà§° সৈতে সকলোতকৈ বেছি মিলা বহà§à¦¤à§‹ লোকৰ গোট অথবা “à¦à¦•à§‡à¦§à§°à¦£à§° বৈশিষà§à¦Ÿà§à¦¯ শà§à¦¬à§‡à§Ÿà¦¾à§° কৰা গোট†নিৰà§à¦§à¦¾à§°à¦£ কৰে। বিজà§à¦žà¦¾à¦ªà¦¨à¦¦à¦¾à¦¤à¦¾à¦‡ গোটটোৰ বাবে বিজà§à¦žà¦¾à¦ªà¦¨ বাছনি কৰিব পাৰে আৰৠআপোনাৰ ডিভাইচত আপোনাৰ বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§° কাৰà§à¦¯à¦•à¦²à¦¾à¦ª বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত কৰি ৰখা হয়। আপোনাৰ গোটটো পà§à§°à¦¤à¦¿ {NUM_DAYS} দিনত আপডে’ট কৰা হয়।}other{à¦à¦‡ নিয়নà§à¦¤à§à§°à¦£à¦Ÿà§‹ অন কৰা অৱসà§à¦¥à¦¾à¦¤ আৰৠসà§à¦¥à¦¿à¦¤à¦¿à¦Ÿà§‹ সকà§à§°à¦¿à§Ÿ হৈ থাকিলে, Chromeঠআপোনাৰ শেহতীয়া বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§° কাৰà§à¦¯à¦•à¦²à¦¾à¦ªà§° সৈতে সকলোতকৈ বেছি মিলা বহà§à¦¤à§‹ লোকৰ গোট অথবা “à¦à¦•à§‡à¦§à§°à¦£à§° বৈশিষà§à¦Ÿà§à¦¯ শà§à¦¬à§‡à§Ÿà¦¾à§° কৰা গোট†নিৰà§à¦§à¦¾à§°à¦£ কৰে। বিজà§à¦žà¦¾à¦ªà¦¨à¦¦à¦¾à¦¤à¦¾à¦‡ গোটটোৰ বাবে বিজà§à¦žà¦¾à¦ªà¦¨ বাছনি কৰিব পাৰে আৰৠআপোনাৰ ডিভাইচত আপোনাৰ বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§° কাৰà§à¦¯à¦•à¦²à¦¾à¦ª বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত কৰি ৰখা হয়। আপোনাৰ গোটটো পà§à§°à¦¤à¦¿ {NUM_DAYS} দিনত আপডে’ট কৰা হয়।}}</translation>
<translation id="2053553514270667976">পিন ক’ড</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{১টা পৰামৰà§à¦¶}one{#টা পৰামৰà§à¦¶}other{#টা পৰামৰà§à¦¶}}</translation>
<translation id="2071692954027939183">জাননীসমূহ সà§à¦¬à¦¯à¦¼à¦‚কà§à§°à¦¿à¦¯à¦¼à¦­à¦¾à§±à§‡ অৱৰোধ কৰা হৈছে কাৰণ আপà§à¦¨à¦¿ সাধাৰণতে সেইসমূহক অনà§à¦®à¦¤à¦¿ নিদিয়ে</translation>
<translation id="2079545284768500474">আনডৠকৰক</translation>
<translation id="20817612488360358">ছিষà§à¦Ÿà§‡à¦® পà§à§°à¦•à§à¦¸à¦¿ ছেটিংসমূহ বà§à¦¯à§±à¦¹à¦¾à§° কৰিবলৈ ছেট কৰা হৈছে কিনà§à¦¤à§ কà§à¦·à¦¤à¦¿à¦•à¦¾à§°à¦• পà§à§°à¦•à§à¦¸à¦¿ কনফিগাৰেশà§à¦¬à¦¨à§‹ নিরà§à¦¦à¦¿à¦·à§à¦Ÿ কৰা হৈছে।</translation>
<translation id="2082238445998314030">ফলাফল <ph name="TOTAL_RESULTS" />ৰ ভিতৰত <ph name="RESULT_NUMBER" /></translation>
+<translation id="2085876078937250610">ছেভ কৰক…</translation>
<translation id="2088086323192747268">ছিংক কৰা বà§à¦Ÿà¦¾à¦® পৰিচালনা কৰক, আপà§à¦¨à¦¿ Chromeৰ ছেটিঙত কি তথà§à¦¯ ছিংক কৰিব সেয়া পৰিচালনা কৰিবলৈ à¦à¦£à§à¦Ÿà¦¾à§° টিপক</translation>
<translation id="2091887806945687916">শবà§à¦¦</translation>
<translation id="2094505752054353250">ড‘মেইন অমিল</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" />ৰ বাবে à¦à¦Ÿà¦¾ বà§à¦¯à§±à¦¹à¦¾à§°à¦•à¦¾à§°à§€à§° নাম আৰৠপাছৱৰà§à¦¡à§° পà§à§°à§Ÿà§‹à¦œà¦¨à¥¤</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" />ত মà§à¦¯à¦¾à¦¦ উকলিব</translation>
<translation id="2337852623177822836">ছেটিংটো আপোনাৰ পà§à§°à¦¶à¦¾à¦¸à¦•à§° দà§à¦¬à¦¾à§°à¦¾ নিয়নà§à¦¤à§à§°à¦£ কৰা হয়</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" />ঠযোৰা লাগিব খোজে</translation>
<translation id="2344028582131185878">সà§à¦¬à§Ÿà¦‚কà§à§°à¦¿à§Ÿà¦­à¦¾à§±à§‡ হোৱা ডাউনল’ড</translation>
<translation id="2346319942568447007">আপà§à¦¨à¦¿ পà§à§°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿ কৰা পà§à§°à¦¤à¦¿à¦šà§à¦›à¦¬à¦¿</translation>
<translation id="2354001756790975382">অনà§à¦¯ বà§à¦•à¦®à¦¾à§°à§à¦•à¦¸à¦®à§‚হ</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à¦¯à¦¼à§‡ আপà§à¦¨à¦¿ à¦à¦‡ ছাইটটোত চাই থকা পà§à§°à¦¤à¦¿à¦šà§à¦›à¦¬à¦¿à¦¸à¦®à§‚হ চাব পাৰিব পাৰে আৰৠসেইসমূহ সলনি কৰি আপোনাক জালত পেলাব পাৰে।</translation>
<translation id="2356070529366658676">সোধক</translation>
<translation id="2357481397660644965">আপোনাৰ ডিভাইচটো <ph name="DEVICE_MANAGER" />ঠআৰৠআপোনাৰ à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦Ÿà§‹ <ph name="ACCOUNT_MANAGER" />ঠপৰিচালনা কৰে।</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{à¦à¦¦à¦¿à¦¨à¦¤à¦•à§ˆà¦“ কম সময়ত}=1{à¦à¦¦à¦¿à¦¨à¦¤}one{{NUM_DAYS} দিনত}other{{NUM_DAYS} দিনত}}</translation>
<translation id="2359629602545592467">à¦à¦•à¦¾à¦§à¦¿à¦•</translation>
<translation id="2359808026110333948">অবà§à¦¯à¦¾à¦¹à¦¤ ৰাখক</translation>
+<translation id="2359961752320758691">আপোনাৰ ভাৰà§à¦šà§à§±à§‡à¦² কাৰà§à¦¡ নমà§à¦¬à§°à¦Ÿà§‹ পà§à§°à§Ÿà§‹à¦— কৰা হৈছে।</translation>
<translation id="2367567093518048410">সà§à¦¤à§°</translation>
<translation id="2372464001869762664">আপà§à¦¨à¦¿ নিশà§à¦šà¦¿à¦¤ কৰাৰ পাছত আপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà§° পৰা আপোনাৰ কাৰà§à¦¡à§° সবিশেষ à¦à¦‡ ছাইটটোৰ সৈতে শà§à¦¬à§‡à§Ÿà¦¾à§° কৰা হ’ব। আপোনাৰ Plex à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà§° সবিশেষত CVC বিচাৰক।</translation>
<translation id="2380886658946992094">লিগেল</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">à¦à¦‡ শà§à¦¬à¦¿à¦ªà¦¿à¦‚ পদà§à¦§à¦¤à¦¿à¦Ÿà§‹ উপলবà§à¦§ নহয়৷ অনà§à¦¯ কোনো পদà§à¦§à¦¤à¦¿ বà§à¦¯à§±à¦¹à¦¾à§° কৰি চাওক।</translation>
<translation id="2396249848217231973">মচা কারà§à¦¯à¦Ÿà§‹ &amp;আনডৠকৰক</translation>
<translation id="2410754574180102685">চৰকাৰ-আইনী</translation>
+<translation id="2413155254802890957">পà§à§°à¦£à¦¿</translation>
<translation id="2413528052993050574">à¦à¦‡ ছারà§à¦­à¦¾à§°à§‡ নিজকে <ph name="DOMAIN" /> বà§à¦²à¦¿ পà§à§°à¦®à¦¾à¦£ কৰিব নোৱাৰিলে আৰৠইয়াৰ সà§à§°à¦•à§à¦·à¦¾ পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§° হয়তো পà§à§°à¦¤à§à¦¯à¦¾à¦¹à¦¾à§° কৰা হৈছে। à¦à§Ÿà¦¾ কোনো ভà§à¦² কনফিগাৰেশà§à¦¬à¦¨à§° বাবে বা কোনো আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à§Ÿà§‡ আপোনাৰ সংযোগ পà§à§°à¦¤à¦¿à§°à§‹à¦§ কৰাৰ বাবে হ‘ব পাৰে।</translation>
<translation id="2414886740292270097">গাà§</translation>
<translation id="2438874542388153331">সোà¦à¦«à¦¾à¦²à§‡ চতà§à¦°à§à¦­à§‚জ আকাৰত পাঞà§à¦š কৰক</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">তলৰ অংশৰ সোà¦à¦«à¦¾à¦²à§‡ ষà§à¦Ÿà§‡'পল কৰক</translation>
<translation id="2523886232349826891">কেৱল à¦à¦‡ ডিভাইচটোত ছেভ কৰা হয়</translation>
<translation id="2524461107774643265">অধিক তথà§à¦¯ যোগ কৰক</translation>
-<translation id="2526590354069164005">ডেসà§à¦•à¦Ÿà¦ª</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{আৰৠ১টা}one{আৰৠঅনà§à¦¯ #টা}other{আৰৠঅনà§à¦¯ #টা}}</translation>
<translation id="2536110899380797252">ঠিকনা যোগ কৰক</translation>
<translation id="2539524384386349900">চিনাকà§à¦¤ কৰক</translation>
+<translation id="2541219929084442027">আপà§à¦¨à¦¿ আটাইবোৰ ইনক’গনিট’ টেব বনà§à¦§ কৰাৰ পাছত আপà§à¦¨à¦¿ তাত চোৱা পৃষà§à¦ à¦¾à¦¸à¦®à§‚হ আপোনাৰ বà§à§°à¦¾à¦‰à¦œà¦¾à§°à§° ইতিহাস, কà§à¦•à¦¿à§° ষà§à¦Ÿâ€™à§° অথবা সনà§à¦§à¦¾à¦¨à§° ইতিহাসত নাথাকে। আপà§à¦¨à¦¿ ডাউনল’ড কৰা যিকোনো ফাইল অথবা আপà§à¦¨à¦¿ সৃষà§à¦Ÿà¦¿ কৰা বà§à¦•à¦®à¦¾à¦°à§à¦•à¦¸à¦®à§‚হ ৰখা হ’ব।</translation>
<translation id="2544644783021658368">à¦à¦•à¦• নথি</translation>
<translation id="254947805923345898">নীতিৰ মান মানà§à¦¯ নহয়।</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" />ঠà¦à¦Ÿà¦¾ অমানà§à¦¯ সà¦à¦¹à¦¾à§°à¦¿ পঠিয়াইছে।</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Chromeৰ সৰà§à¦¬à§‹à¦šà§à¦š সà§à¦¤à§°à§° সà§à§°à¦•à§à¦·à¦¾ লাভ কৰিবলৈ <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />বৰà§à¦§à¦¿à¦¤ সà§à§°à¦•à§à¦·à¦¾à§° সà§à¦¬à¦¿à¦§à¦¾à¦Ÿà§‹ অন কৰক<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" />ৰ ছাৰà§à¦­à¦¾à§°à§° IP ঠিকনাটো বিচাৰি পোৱা নগ’ল।</translation>
<translation id="2639739919103226564">সà§à¦¥à¦¿à¦¤à¦¿:</translation>
+<translation id="264810637653812429">মিল থকা কোনো ডিভাইচ বিচাৰি পোৱা নগ’ল।</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chromeৰ ছেটিংসমূহত আপোনাৰ বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§° ইতিহাস, কà§à¦•à¦¿à¦¸à¦®à§‚হ, কেশà§à¦¬ আৰৠবহà§à¦¤à§‹ মচিবলৈ পà§à§°à¦¥à¦®à§‡ টেব আৰৠতাৰ পাছত à¦à¦£à§à¦Ÿà¦¾à§° টিপক</translation>
<translation id="2650446666397867134">ফাইলটোৰ à¦à¦•à§à¦¸à§‡à¦› অসà§à¦¬à§€à¦•à¦¾à§° কৰা হ’ল</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">পà§à¦¨à§° লঞà§à¦š কৰক</translation>
<translation id="2803306138276472711">Googleৰ সà§à§°à¦•à§à¦·à¦¿à¦¤ বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§‡ শেহতীয়াকৈ<ph name="SITE" />ত <ph name="BEGIN_LINK" />মালৱেৰ চিনাকà§à¦¤ কৰিছে<ph name="END_LINK" />। সাধাৰণতে সà§à§°à¦•à§à¦·à¦¿à¦¤ ৱেবছাইটসমূহ কেতিয়াবা মালৱেৰৰ দà§à¦¬à¦¾à§°à¦¾ পà§à§°à¦­à¦¾à§±à¦¿à¦¤ হয়।</translation>
<translation id="2807052079800581569">পà§à§°à¦¤à¦¿à¦šà§à¦›à¦¬à¦¿à§° Y সà§à¦¥à¦¾à¦¨</translation>
+<translation id="2820957248982571256">সà§à¦•à§‡à¦¨ কৰি থকা হৈছে...</translation>
<translation id="2824775600643448204">ঠিকনা আৰৠসনà§à¦§à¦¾à¦¨à§° বাৰ</translation>
<translation id="2826760142808435982">à¦à¦‡ সংযোগটো à¦à¦¨à¦•à§à§°à¦¿à¦ªà§à¦Ÿ কৰিবলৈ তথা সেইটোৰ বিশà§à¦¬à¦¾à¦¸à¦¯à§‹à¦—à§à¦¯à¦¤à¦¾à§° সতà§à¦¯à¦¾à¦ªà¦¨ কৰিবলৈ <ph name="CIPHER" /> বà§à¦¯à§±à¦¹à¦¾à§° কৰা হৈছে আৰৠসেইটোৱে <ph name="KX" />ক সলনা সলনিৰ মà§à¦–à§à¦¯ উপায় হিচাপে বà§à¦¯à§±à¦¹à¦¾à§° কৰে।</translation>
<translation id="2835170189407361413">ফরà§à¦® মচক</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">আমনà§à¦¤à§à§°à¦£ (লেফাফা)</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="2859806420264540918">à¦à¦‡ ছাইটোৱে বিনা অনà§à¦®à¦¤à¦¿à¦¤ বা কোনো বিভà§à§°à¦¾à¦¨à§à¦¤à¦¿à¦•à§° বিজà§à¦žà¦¾à¦ªà¦¨ দেখà§à§±à¦¾à§Ÿà¥¤</translation>
+<translation id="287596039013813457">বনà§à¦§à§à¦¤à§à¦¬à¦¸à§à¦²à¦­</translation>
+<translation id="2876489322757410363">বাহà§à¦¯à¦¿à¦• কোনো à¦à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à§à¦¬à¦¨à§‡à§°à§‡ পৰিশোধ কৰিবলৈ ইনক’গনিট’ ম’ড à¦à§°à¦¿ আছে। অবà§à¦¯à¦¾à¦¹à¦¤ ৰাখিবনে?</translation>
<translation id="2878197950673342043">প'ষà§à¦Ÿà¦¾à§° ফ'লà§à¦¡</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ৱিণà§à¦¡â€™à¦• নিৰà§à¦¦à¦¿à¦·à§à¦Ÿ ঠাইত ৰখা</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (লেফাফা)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chromeৰ ছেটিঙত সà§à§°à¦•à§à¦·à¦¾ পৰীকà§à¦·à¦¾ চলাবলৈ টেবত আৰৠতাৰ পাছত à¦à¦£à§à¦Ÿà¦¾à§°à¦¤ টিপক</translation>
<translation id="3061707000357573562">পেচà§à¦šà§â€Œ সেৱা</translation>
-<translation id="3064966200440839136">বাহà§à¦¯à¦¿à¦• কোনো à¦à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à§à¦¬à¦¨à§‡à§°à§‡ পৰিশোধ কৰিবলৈ ইনক’গনিট’ ম’ড à¦à§°à¦¿ গৈ থকা হৈছে। অবà§à¦¯à¦¾à¦¹à¦¤ ৰাখিবনে?</translation>
<translation id="306573536155379004">গে’ম আৰমà§à¦­ হৈছে।</translation>
<translation id="3080254622891793721">গà§à§°à¦¾à¦«à¦¿à¦•</translation>
<translation id="3086579638707268289">ৱেবত আপোনাৰ কাৰà§à¦¯à¦•à¦²à¦¾à¦ª নিৰীকà§à¦·à¦£ কৰি থকা হৈছে</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">আপোনাৰ à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦Ÿà§‹ <ph name="MANAGER" />ঠপৰিচালনা কৰে।</translation>
<translation id="3157931365184549694">পà§à¦¨à¦ƒà¦¸à§à¦¥à¦¾à¦ªà¦¨ কৰক</translation>
<translation id="3162559335345991374">আপà§à¦¨à¦¿ বà§à¦¯à§±à¦¹à¦¾à§° কৰি থকা ৱাই-ফাইটোৰ বাবে আপà§à¦¨à¦¿ à¦à¦‡à¦Ÿà§‹à§° লগ ইন পৃষà§à¦ à¦¾à¦²à§ˆ যাব লগা হ'ব পাৰে।</translation>
-<translation id="3167968892399408617">আপà§à¦¨à¦¿ নিজৰ সকলো ইনক’গনিট’ টেব বনà§à¦§ কৰাৰ পাছত আপà§à¦¨à¦¿ ইনক’গনিট’ টেবত চোৱা পৃষà§à¦ à¦¾à¦¸à¦®à§‚হ নিজৰ বà§à§°à¦¾à¦‰à¦œà¦¾à§°à§° ইতিহাস, কà§à¦•à¦¿ ষà§à¦Ÿâ€™à§° বা সনà§à¦§à¦¾à¦¨à§° ইতিহাসত জমা হৈ নাথাকে। আপà§à¦¨à¦¿ ডাউনল’ড কৰা যিকোনো ফাইল বা আপà§à¦¨à¦¿ সৃষà§à¦Ÿà¦¿ কৰা বà§à¦•à¦®à¦¾à¦°à§à¦•à¦¸à¦®à§‚হ ৰখা হ’ব।</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">দà§à¦¬à§€à¦ª</translation>
<translation id="3176929007561373547">আপোনাৰ পà§à§°â€™à¦•à§à¦¸à¦¿ ছেটিংসমূহ পৰীকà§à¦·à¦¾ কৰক বা পà§à§°â€™à¦•à§à¦¸à¦¿ ছারà§à¦­à¦¾à§°à§‡ কাম কৰি থকাটো নিশà§à¦šà¦¿à¦¤ কৰিবলৈ নিজৰ নেটৱরà§à¦• পà§à§°à¦¶à¦¾à¦¸à¦•à§° সৈতে যোগাযোগ কৰক। যদি আপà§à¦¨à¦¿ বিশà§à¦¬à¦¾à¦¸ কৰা নাই তেনà§à¦¤à§‡ আপà§à¦¨à¦¿ কোনো পà§à§°â€™à¦•à§à¦¸à¦¿ ছারà§à¦­à¦¾à§° বà§à¦¯à§±à¦¹à¦¾à§° কৰি আছে:
@@ -597,10 +612,12 @@
<translation id="3229041911291329567">আপোনাৰ ডিভাইচ আৰৠবà§à§°à¦¾à¦‰à¦œà¦¾à§°à§° সংসà§à¦•à§°à¦£à§° তথà§à¦¯</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" />ৰ CVC দিয়ক</translation>
<translation id="3234666976984236645">à¦à¦‡ ছাইটটোত সদায়েই গà§à§°à§à¦¤à§à¦¬à¦ªà§‚ৰà§à¦£ সমল ধৰা পেলাওক</translation>
+<translation id="3249845759089040423">আকৰà§à¦·à¦£à§€à§Ÿ</translation>
<translation id="3252266817569339921">ফৰাচী</translation>
<translation id="3266793032086590337">মান (সংঘাত)</translation>
<translation id="3268451620468152448">খà§à¦²à¦¿ ৰখা টেব</translation>
<translation id="3270847123878663523">পà§à¦¨à¦ƒà¦•à§à§°à¦® কৰাটো &amp;আনডৠকৰক</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" />ঠসংযোগ কৰিবলৈ বিচাৰিছে</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">আপোনাৰ পà§à§°à¦¤à¦¿à¦·à§à¦ à¦¾à¦¨ <ph name="ENROLLMENT_DOMAIN" />ঠà¦à¦‡ ৱেবছাইটসমূহলৈ ছেটিং অথবা নীতিৰ দৰে কিছà§à¦®à¦¾à¦¨ তথà§à¦¯ পঠিয়াইছে।</translation>
<translation id="3282497668470633863">কাৰà§à¦¡à¦¤ নাম যোগ কৰক</translation>
@@ -653,6 +670,7 @@
<translation id="3428151540071562330">à¦à¦Ÿà¦¾ অথবা à¦à¦•à¦¾à¦§à¦¿à¦• DnsOverHttpsTemplates ছারà§à¦­à¦¾à§° টেমপà§à¦²à§‡à¦Ÿà§° URIসমূহ মানà§à¦¯ নহয় আৰৠসেয়া বà§à¦¯à§±à¦¹à¦¾à§° কৰা নহ’ব।</translation>
<translation id="3431636764301398940">à¦à¦‡ ডিভাইচটোত à¦à¦‡ কাৰà§à¦¡à¦–ন ছেভ কৰক</translation>
<translation id="3432601291244612633">পৃষà§à¦ à¦¾à¦–ন বনà§à¦§ কৰক</translation>
+<translation id="3435738964857648380">সà§à§°à¦•à§à¦·à¦¾</translation>
<translation id="3435896845095436175">সকà§à¦·à¦® কৰক</translation>
<translation id="3438829137925142401">আপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦¤ ছেভ কৰা পাছৱৰà§à¦¡à¦¸à¦®à§‚হ বà§à¦¯à§±à¦¹à¦¾à§° কৰক</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -694,7 +712,10 @@
<translation id="3584299510153766161">তলৰ অংশত দà§à¦¬à¦¾à§° পাঞà§à¦š কৰক</translation>
<translation id="3586931643579894722">সবিশেষ লà§à¦•à§à§±à¦¾à¦“ক</translation>
<translation id="3587738293690942763">মাজভাগ</translation>
+<translation id="3590643883886679995">আপà§à¦¨à¦¿ ইনক’গনিট’ ম’ডৰ পৰা বাহিৰ ওলোৱাৰ পাছত à¦à¦‡ ডিভাইচটোত ছাইন-ইনৰ ডেটা ষà§à¦Ÿâ€™à§° কৰা হ’ব।</translation>
+<translation id="359126217934908072">মাহ/বছৰ:</translation>
<translation id="3592413004129370115">ইটালিয়ান (লেফাফা)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{আপà§à¦¨à¦¿ যিকোনো সময়তে নিজৰ গোটটো ৰিছেট কৰিব পাৰে। à¦à¦Ÿà¦¾ নতà§à¦¨ গোটত যোগদান কৰিবলৈ পà§à§°à¦¾à§Ÿ à¦à¦¦à¦¿à¦¨ সময় লাগে।}=1{আপà§à¦¨à¦¿ যিকোনো সময়তে নিজৰ গোটটো ৰিছেট কৰিব পাৰে। à¦à¦Ÿà¦¾ নতà§à¦¨ গোটত যোগদান কৰিবলৈ পà§à§°à¦¾à§Ÿ à¦à¦¦à¦¿à¦¨ সময় লাগে।}one{আপà§à¦¨à¦¿ যিকোনো সময়তে নিজৰ গোটটো ৰিছেট কৰিব পাৰে। à¦à¦Ÿà¦¾ নতà§à¦¨ গোটত যোগদান কৰিবলৈ {NUM_DAYS} দিন সময় লাগে।}other{আপà§à¦¨à¦¿ যিকোনো সময়তে নিজৰ গোটটো ৰিছেট কৰিব পাৰে। à¦à¦Ÿà¦¾ নতà§à¦¨ গোটত যোগদান কৰিবলৈ {NUM_DAYS} দিন সময় লাগে।}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">আপোনাৰ পà§à§°à¦¶à¦¾à¦¸à¦•à§° দà§à¦¬à¦¾à§°à¦¾ à¦à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à§à¦¬à¦¨à¦Ÿà§‹ অৱৰোধ কৰা হৈছে</translation>
<translation id="3608932978122581043">ফীডৰ দিশ</translation>
@@ -703,13 +724,13 @@
<translation id="3615877443314183785">কোনো মানà§à¦¯ মà§à¦¯à¦¾à¦¦ উকলাৰ তাৰিখ দিয়ক</translation>
<translation id="36224234498066874">বà§à§°à¦¾à¦‰à¦œà¦¿à¦‚ ডেটা মচক...</translation>
<translation id="362276910939193118">সমà§à¦ªà§‚ৰà§à¦£ ইতিহাস দেখà§à§±à¦¾à¦“ক</translation>
-<translation id="3625635938337243871">আপà§à¦¨à¦¿ ইনক’গনিট’ ম’ডৰ পৰা বাহিৰ ওলোৱাৰ পাছত à¦à¦‡ ডিভাইচটোত ছাইন-ইনৰ ডেটা ষà§à¦Ÿâ€™à§° কৰা হ’ব।</translation>
<translation id="3630155396527302611">যদি ইয়াক ইতিমধà§à¦¯à§‡ à¦à¦Ÿà¦¾ নেটৱৰà§à¦•à¦Ÿà§‹ à¦à¦•à§à¦¸à§‡à¦› কৰিব পৰা পà§à§°â€˜à¦—à§à§°à§‡à¦® হিচাপে তালিকাভà§à¦•à§à¦¤ কৰি থোৱা থাকে, তেনà§à¦¤à§‡
সেই তালিকাখনৰ পৰা ইয়াক আà¦à¦¤à§°à¦¾à¦‡ পà§à¦¨à§° যোগ কৰি চাওক</translation>
<translation id="3630699740441428070">à¦à¦‡ ডিভাইচটোৰ পà§à§°à¦¶à¦¾à¦¸à¦•à¦¸à¦•à¦²à§‡ আপোনাৰ নেটৱৰà§à¦•à§° সংযোগটো কনফিগাৰ কৰিছে, যিটোৱে তেওà¦à¦²à§‹à¦•à¦• আপà§à¦¨à¦¿ চোৱা ৱেৱছাইটসমূহকে ধৰি আপোনাৰ নেটৱৰà§à¦•à§° টà§à§°à§‡à¦«à¦¿à¦• চাবলৈ দিব পাৰে।</translation>
<translation id="3631244953324577188">বায়’মেটà§à§°à¦¿à¦•à§à¦¸</translation>
<translation id="3633738897356909127">Chrome আপডে’ট কৰক বà§à¦Ÿà¦¾à¦®, Chromeৰ ছেটিংসমূহৰ পৰা Chrome আপডে’ট কৰিবলৈ à¦à¦£à§à¦Ÿà¦¾à§° টিপক</translation>
<translation id="3634530185120165534">টà§à§°à§‡â€™ ৫</translation>
+<translation id="3637662659967048211">Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦¤ ছেভ কৰক</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">à¦à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à§à¦¬à¦¨:</translation>
<translation id="3650584904733503804">মানà§à¦¯à¦¤à¦¾à¦•à§°à¦£ সফল</translation>
@@ -750,6 +771,7 @@
<translation id="3781428340399460090">উজà§à¦œà§à¦¬à¦² গà§à¦²à¦ªà§€à§Ÿà¦¾</translation>
<translation id="3783418713923659662">MasterCard গà§à§°à¦¹à¦£ কৰে</translation>
<translation id="3784372983762739446">বà§à¦²à§à¦Ÿà§à¦¥ ডিভাইচসমূহ</translation>
+<translation id="3787675388804467730">ভাৰà§à¦›à§à§±à§‡à¦² কাৰà§à¦¡à§° নমà§à¦¬à§°</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" />ত মà§à¦¯à¦¾à¦¦ উকলিব</translation>
<translation id="3789155188480882154">আকাৰ ১৬</translation>
<translation id="3789841737615482174">ইনষà§à¦Ÿà¦² কৰক</translation>
@@ -769,6 +791,7 @@
<translation id="3841184659773414994">ফাইল নিয়নà§à¦¤à§à§°à¦•</translation>
<translation id="385051799172605136">উভতি যাওক</translation>
<translation id="3858027520442213535">তাৰিখ আৰৠসময় আপডে’ট কৰক</translation>
+<translation id="3881478300875776315">শাৰী কমকৈ দেখà§à§±à¦¾à¦“ক</translation>
<translation id="3884278016824448484">বিৰোধাতà§à¦®à¦• ডিভাইচ চিনাকà§à¦¤à¦•à¦¾à§°à§€</translation>
<translation id="3885155851504623709">গাà¦à¦“</translation>
<translation id="388632593194507180">নিৰীকà§à¦·à¦£ কৰি থকা বà§à¦²à¦¿ চিনাকà§à¦¤ কৰা হৈছে</translation>
@@ -794,6 +817,7 @@
<translation id="397105322502079400">গণনা কৰি থকা হৈছে…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" />ক অৱৰোধ কৰা হৈছে</translation>
<translation id="3973357910713125165">Chromeৰ সà§à§°à¦•à§à¦·à¦¾ পৰীকà§à¦·à¦¾à§° বà§à¦Ÿà¦¾à¦®à¦Ÿà§‹ চলাওক, Chromeৰ ছেটিঙত সà§à§°à¦•à§à¦·à¦¾ পৰীকà§à¦·à¦¾ চলাবলৈ à¦à¦£à§à¦Ÿà¦¾à§°à¦¤ টিপক</translation>
+<translation id="3986705137476756801">à¦à¦¤à¦¿à§Ÿà¦¾à§° বাবে লাইভ কেপশà§à¦¬à¦¨ অফ কৰক</translation>
<translation id="3987405730340719549">Chromeঠà¦à¦‡ ছাইটটো ভà§à§±à¦¾ অথবা পà§à§°à¦¤à¦¾à§°à¦£à¦¾à¦®à§‚লক হ'ব পাৰে বà§à¦²à¦¿ চিনাকà§à¦¤ কৰিছে।
যদি আপà§à¦¨à¦¿ বিশà§à¦¬à¦¾à¦¸ কৰিছে যে à¦à¦‡à¦Ÿà§‹ ভà§à¦²à¦¤à§‡ দেখà§à¦“ৱা হৈছে, অনà§à¦—à§à§°à¦¹ কৰি https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals চাওক।</translation>
@@ -888,13 +912,14 @@
<translation id="4275830172053184480">আপোনাৰ ডিভাইচটো ৰিষà§à¦Ÿà¦¾à§°à§à¦Ÿ কৰক</translation>
<translation id="4277028893293644418">পাছৱৰà§à¦¡ ৰিছেট কৰক</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{à¦à¦‡ কাৰà§à¦¡à¦–ন আপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦¤ ছেভ কৰা হৈছে}one{à¦à¦‡ কাৰà§à¦¡à¦¸à¦®à§‚হ আপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦¤ ছেভ কৰা হৈছে}other{à¦à¦‡ কাৰà§à¦¡à¦¸à¦®à§‚হ আপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦¤ ছেভ কৰা হৈছে}}</translation>
+<translation id="4287885627794386150">টà§à§°à¦¾à§Ÿà§‡à¦²à§° বাবে যোগà§à¦¯ কিনà§à¦¤à§ সকà§à§°à¦¿à§Ÿ নহয়</translation>
<translation id="4297502707443874121">পৃষà§à¦ à¦¾ <ph name="THUMBNAIL_PAGE" />ৰ বাবে থামà§à¦¬à¦¨à§‡à¦‡à¦²</translation>
<translation id="42981349822642051">বিসà§à¦¤à¦¾à§° কৰক</translation>
<translation id="4300675098767811073">সোà¦à¦«à¦¾à¦²à§‡ à¦à¦•à¦¾à¦§à¦¿à¦• পাঞà§à¦š কৰক</translation>
<translation id="4302514097724775343">খেলিবলৈ ডাইন’ছৰত টিপক</translation>
<translation id="4302965934281694568">Chou3 (লেফাফা)</translation>
<translation id="4305666528087210886">আপোনাৰ ফাইলটো à¦à¦•à§à¦¸à§‡à¦› কৰিব পৰা নগ’ল</translation>
-<translation id="4305817255990598646">সলনি কৰক</translation>
+<translation id="4306529830550717874">ঠিকনাটো চেভ কৰিবনে?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">অৱৰোধ কৰক (ডিফ’লà§à¦Ÿ)</translation>
<translation id="4314815835985389558">ছিংক পৰিচালনা কৰক</translation>
@@ -921,6 +946,7 @@
<translation id="4377125064752653719">আপà§à¦¨à¦¿ <ph name="DOMAIN" /> পাবলৈ পà§à§°à§Ÿà¦¾à¦¸ কৰিছিল কিনà§à¦¤à§ ছারà§à¦­à¦¾à§°à§‡ দিয়া পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§°à¦–ন ইয়াৰ পà§à§°à¦¦à¦¾à¦¨à¦•à¦¾à§°à§€à§Ÿà§‡ পà§à§°à¦¤à§à¦¯à¦¾à¦¹à¦¾à§° কৰিছে। তাৰমানে ছারà§à¦­à¦¾à§°à¦Ÿà§‹à§±à§‡ দিয়া সà§à§°à¦•à§à¦·à¦¾ সমà§à¦ªà¦°à§à¦•à§€à§Ÿ কà§à§°à§‡à¦¡à§‡à¦¨à¦¶à§à¦¬à¦¿à§Ÿà§‡à¦²à¦¸à¦®à§‚হ সমà§à¦ªà§‚রà§à¦£à§°à§‚পে বিশà§à¦¬à¦¾à¦¸ কৰিব নোৱাৰি। আপà§à¦¨à¦¿ কোনো আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à§° সৈতে যোগাযোগ কৰি থাকিব পাৰে।</translation>
<translation id="4378154925671717803">ফ'ন</translation>
<translation id="4390472908992056574">বà§à§°à¦¿à¦®</translation>
+<translation id="4406883609789734330">লাইভ কেপশà§à¦¬à¦¨</translation>
<translation id="4406896451731180161">সনà§à¦§à¦¾à¦¨à§° ফলাফল</translation>
<translation id="4408413947728134509">কà§à¦•à§€ <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">আপà§à¦¨à¦¿ à¦à¦Ÿà¦¾ পà§à§°à§±à¦žà§à¦šà¦¨à¦¾à¦®à§‚লক ছাইটত à¦à¦‡à¦®à¦¾à¦¤à§à§° নিজৰ পাছৱৰà§à¦¡à¦Ÿà§‹ দিছে। Chromeঠ<ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> আৰৠআপà§à¦¨à¦¿ à¦à¦‡ পাছৱৰà§à¦¡à¦Ÿà§‹ বà§à¦¯à§±à¦¹à¦¾à§° কৰা অনà§à¦¯ ছাইটসমূহলৈ গৈ à¦à¦‡à¦Ÿà§‹ à¦à¦¤à¦¿à¦¯à¦¼à¦¾à¦‡ সলনি কৰাটো চà§à¦ªà¦¾à§°à¦¿à¦› কৰে।</translation>
@@ -933,7 +959,6 @@
<translation id="4435702339979719576">প’ষà§à¦Ÿà¦•à¦¾à¦°à§à¦¡)</translation>
<translation id="443673843213245140">à¦à¦Ÿà¦¾ পà§à§°à¦•à§à¦¸à¦¿à§° বà§à¦¯à§±à¦¹à¦¾à§° অকà§à¦·à¦® কৰা হৈছে কিনà§à¦¤à§ à¦à¦Ÿà¦¾ মà§à¦–à§à¦¯ পà§à§°à¦•à§à¦¸à¦¿à§° কনফিগাৰেশà§à¦¬à¦¨ নিৰà§à¦¦à¦¿à¦·à§à¦Ÿ কৰা হৈছে।</translation>
<translation id="4464826014807964867">আপোনাৰ পà§à§°à¦¤à¦¿à¦·à§à¦ à¦¾à¦¨à§° তথà§à¦¯ থকা ৱেবছাইট</translation>
-<translation id="4466881336512663640">ফৰà§à¦®à¦¤ কৰা সালসলনি নোহোৱা হৈ যাব। আপà§à¦¨à¦¿ অবà§à¦¯à¦¾à¦¹à¦¤ ৰাখিবলৈ বিচাৰে বà§à¦²à¦¿ নিশà§à¦šà¦¿à¦¤à¦¨à§‡?</translation>
<translation id="4476953670630786061">à¦à¦‡ ফৰà§à¦®à¦–ন সà§à§°à¦•à§à¦·à¦¿à¦¤ নহয়। সà§à¦¬à§Ÿà¦‚কà§à¦°à¦¿à§Ÿà¦­à¦¾à§±à§‡ পূৰ কৰাৰ সà§à¦¬à¦¿à¦§à¦¾à¦Ÿà§‹ অফ কৰা হৈছে।</translation>
<translation id="4477350412780666475">পৰৱৰà§à¦¤à§€ টà§à§°à§‡à¦•</translation>
<translation id="4482953324121162758">à¦à¦‡ ছাইটটো অনà§à¦¬à¦¾à¦¦ কৰা নহয়।</translation>
@@ -967,6 +992,7 @@
<translation id="4594403342090139922">মচা কারà§à¦¯à¦Ÿà§‹ &amp;আনডৠকৰক</translation>
<translation id="4597348597567598915">আকাৰ ৮</translation>
<translation id="4600854749408232102">C6/C5 (লেফাফা)</translation>
+<translation id="4606870351894164739">পà§à§°à¦­à¦¾à§±à¦¶à¦¾à¦²à§€</translation>
<translation id="4628948037717959914">Photo</translation>
<translation id="4631649115723685955">কেশà§à¦¬à¦¬à§‡à¦• লিংক কৰা হ'ল</translation>
<translation id="4636930964841734540">তথà§à¦¯</translation>
@@ -986,6 +1012,7 @@
<translation id="4691835149146451662">সà§à¦¥à¦¾à¦ªà¦¤à§à¦¯ বিদà§à¦¯à¦¾-A (লেফাফা)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">কাষ</translation>
+<translation id="4702656508969495934">লাইভ কেপশà§à¦¬à¦¨ দৃশà§à¦¯à¦®à¦¾à¦¨ হৈ আছে, মনোযোগ দিবলৈ ৱিণà§à¦¡' সলনি কৰোà¦à¦¤à¦¾ বà§à¦¯à§±à¦¹à¦¾à§° কৰক</translation>
<translation id="4708268264240856090">আপোনাৰ সংযোগটো বাধাপà§à§°à¦¾à¦ªà§à¦¤ হৈছিল</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows Network Diagnostics চলি আছে<ph name="END_LINK" /></translation>
@@ -999,6 +1026,7 @@
<translation id="4738601419177586157">পৰামরà§à¦¶à§° সনà§à¦§à¦¾à¦¨ <ph name="TEXT" /></translation>
<translation id="4742407542027196863">পাছৱৰà§à¦¡à¦¬à§‹à§° পৰিচালনা কৰক…</translation>
<translation id="4744603770635761495">সমà§à¦ªà¦¾à¦¦à¦¨à¦¯à§‹à¦—à§à¦¯ পথ</translation>
+<translation id="4749011317274908093">আপà§à¦¨à¦¿ ইনক’গনিট’ ম’ড বà§à¦¯à§±à¦¹à¦¾à§° কৰিছে</translation>
<translation id="4750917950439032686">আপোনাৰ তথà§à¦¯ (উদাহৰণ সà§à¦¬à§°à§à¦ªà§‡ পাছৱৰà§à¦¡ বা কà§à§°à§‡à¦¡à¦¿à¦Ÿ কাৰà§à¦¡à§° নমà§à¦¬à§°) à¦à¦‡ ছাইটলৈ পঠিওৱাৰ পিছতো বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত হৈ থাকিব।</translation>
<translation id="4756388243121344051">&amp;ইতিহাস</translation>
<translation id="4758311279753947758">সমà§à¦ªà¦°à§à¦•à§° তথà§à¦¯ যোগ কৰক</translation>
@@ -1028,6 +1056,8 @@
<translation id="4813512666221746211">নেটৱৰà§à¦•à§° আসোà¦à§±à¦¾à¦¹</translation>
<translation id="4816492930507672669">পৃষà§à¦ à¦¾à§° আকাৰ অনà§à¦¸à§°à¦¿ খাপ খà§à§±à¦¾à¦“ক</translation>
<translation id="4819347708020428563">ডিফ’লà§à¦Ÿ ভিউত à¦à¦¨â€™à¦Ÿà§‡à¦¶à§à¦¬à¦¨ সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ কৰিবনে?</translation>
+<translation id="4825507807291741242">শকà§à¦¤à¦¿à¦¶à¦¾à¦²à§€</translation>
+<translation id="4838327282952368871">সà§à¦¬à¦ªà§à¦¨à¦®à¦¯à¦¼</translation>
<translation id="484462545196658690">সà§à¦¬à§Ÿà¦‚কà§à§°à¦¿à§Ÿ</translation>
<translation id="4850886885716139402">চাওক</translation>
<translation id="485316830061041779">জাৰà§à¦®à¦¾à¦¨</translation>
@@ -1164,6 +1194,7 @@
<translation id="5314967030527622926">বà§à¦•à¦²à§‡à¦Ÿ পà§à§°à¦¸à§à¦¤à§à¦¤ কৰোà¦à¦¤à¦¾</translation>
<translation id="5316812925700871227">ঘড়ীৰ কাà¦à¦Ÿà¦¾à§° বিপৰীত দিশত ঘূৰাওক</translation>
<translation id="5317780077021120954">ছেভ কৰক</translation>
+<translation id="5321288445143113935">আকাৰ বিসà§à¦¤à¦¾à§°à¦¿à¦¤ কৰা হ'ল</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" />ৰ <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">সমà§à¦ªà¦°à§à¦•à§° তথà§à¦¯ বাছনি কৰক</translation>
<translation id="5327248766486351172">নাম</translation>
@@ -1171,11 +1202,13 @@
<translation id="5332219387342487447">শà§à¦¬à¦¿à¦ªà¦¿à¦™à§° পদà§à¦§à¦¤à¦¿</translation>
<translation id="5333022057423422993">Chromeঠআপà§à¦¨à¦¿ à¦à¦‡à¦®à¦¾à¦¤à§à§° ডেটা উলংঘনত বà§à¦¯à§±à¦¹à¦¾à§° কৰা পাছৱৰà§à¦¡à¦Ÿà§‹ বিচাৰি পাইছে। আপোনাৰ à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿ সà§à§°à¦•à§à¦·à¦¿à¦¤ কৰিবলৈ, আপà§à¦¨à¦¿ নিজৰ ছেভ কৰি ৰখা পাছৱৰà§à¦¡ পৰীকà§à¦·à¦¾ কৰাটো আমি চà§à¦ªà¦¾à§°à¦¿à¦› কৰোà¦à¥¤</translation>
<translation id="5334013548165032829">ছিষà§à¦Ÿà§‡à¦®à§° সূকà§à¦·à§à¦®à¦¾à¦¤à¦¿à¦¸à§‚কà§à¦·à§à¦® লগ</translation>
+<translation id="5334145288572353250">ঠিকনা ছেভ কৰিবনে?</translation>
<translation id="5340250774223869109">à¦à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à§à¦¬à¦¨à¦Ÿà§‹ অৱৰোধ কৰা হৈছে</translation>
<translation id="534295439873310000">NFC ডিভাইচসমূহ</translation>
<translation id="5344579389779391559">à¦à¦‡ পৃষà§à¦ à¦¾à¦Ÿà§‹à§±à§‡ আপোনাৰ পৰা মাচà§à¦² লোৱাৰ চেষà§à¦Ÿà¦¾ কৰিব পাৰে</translation>
<translation id="5355557959165512791">বরà§à¦¤à¦®à¦¾à¦¨ আপà§à¦¨à¦¿ <ph name="SITE" />ৰ চাব নোৱাৰে কাৰণ ইয়াৰ পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§° পà§à§°à¦¤à§à¦¯à¦¾à¦¹à¦¾à§° কৰা হৈছে। নেটৱরà§à¦•à§° সমসà§à¦¯à¦¾ আৰৠআকà§à§°à¦®à¦£à¦¬à§‹à§° সাধাৰণতে অসà§à¦¥à¦¾à§Ÿà§€ হয় গতিকে à¦à¦‡ পৃষà§à¦ à¦¾à¦Ÿà§‹à§±à§‡ পাছত কাম কৰিব পাৰে।</translation>
<translation id="536296301121032821">নীতিৰ ছেটিংসমূহ ষà§à¦Ÿâ€™à§° কৰিবলৈ সকà§à¦·à¦® নহ’ল</translation>
+<translation id="5363309033720083897">আপোনাৰ পà§à§°à¦¶à¦¾à¦¸à¦•à§‡ অনà§à¦®à¦¤à¦¿ দিয়া কà§à§°à¦®à¦¿à¦• পৰà§à¦Ÿ</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="5386426401304769735">à¦à¦‡ ছাইটটোৰ পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§°à§° চà§à¦šà§‡à¦‡à¦¨à¦¤ SHA-1 বà§à¦¯à§±à¦¹à¦¾à§° কৰি ছাইন কৰা à¦à¦–ন পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§° আছে।</translation>
@@ -1184,6 +1217,7 @@
<translation id="5398772614898833570">বিজà§à¦žà¦¾à¦ªà¦¨ অৱৰোধ কৰা হৈছে</translation>
<translation id="5400836586163650660">ধোà¦à§±à¦¾à¦¬à§°à¦£à§€à§Ÿà¦¾</translation>
<translation id="540969355065856584">à¦à¦‡ ছারà§à¦­à¦¾à§°à¦Ÿà§‹à§±à§‡ নিজকে <ph name="DOMAIN" />; বà§à¦²à¦¿ পà§à§°à¦®à¦¾à¦£ কৰিব নোৱাৰিলে; বৰà§à¦¤à¦®à¦¾à¦¨ ইয়াৰ সà§à§°à¦•à§à¦·à¦¾ পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§° মানà§à¦¯ নহয়৷ à¦à§Ÿà¦¾ কোনো ভà§à¦² কনফিগাৰেশà§à¦¬à¦¨à§° বাবে বা কোনো আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à§Ÿà§‡ আপোনাৰ সংযোগ অৱৰোধ কৰাৰ বাবে হ’ব পাৰে।</translation>
+<translation id="541143247543991491">কà§à¦²à¦¾à¦‰à¦¡ (সমগà§à§° ছিষà§à¦Ÿà§‡à¦®à¦¤ পà§à§°à¦¯à§‹à¦œà§à¦¯)</translation>
<translation id="541416427766103491">ষà§à¦Ÿà§‡à¦•à¦¾à§° ৪</translation>
<translation id="5421136146218899937">বà§à§°à¦¾à¦‰à¦œà¦¿à¦‚ ডেটা মচক...</translation>
<translation id="5426179911063097041"><ph name="SITE" />ঠআপোনালৈ জাননী পঠিয়াব বিচাৰে</translation>
@@ -1197,6 +1231,7 @@
<translation id="5455374756549232013">নীতিৰ timestamp বেয়া</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" />টা}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="5463625433003343978">ডিভাইচ বিচাৰি থকা হৈছে...</translation>
<translation id="5469868506864199649">ইটালিয়ান</translation>
<translation id="5470861586879999274">&amp;সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ ৰিডৠকৰক</translation>
<translation id="5478437291406423475">B6/C4 (লেফাফা)</translation>
@@ -1246,7 +1281,6 @@
<translation id="5624120631404540903">পাছৱৰà§à¦¡ সলনি কৰক</translation>
<translation id="5629630648637658800">নীতিৰ ছেটিংসমূহ ল’ড কৰিব পৰা নগ’ল</translation>
<translation id="5631439013527180824">অমানà§à¦¯ ডিভাইচ পৰিচালনাৰ ট’কেন</translation>
-<translation id="5632627355679805402">আপোনাৰ ডেটা <ph name="BEGIN_LINK" />Google পাছৱৰà§à¦¡<ph name="END_LINK" />ৰ সৈতে <ph name="TIME" /> পরà§à¦¯à¦¨à§à¦¤ à¦à¦¨à¦•à§à§°à¦¿à¦ªà§à¦Ÿ কৰা হৈছে। ছিংক কৰা আৰমà§à¦­ কৰিবলৈ à¦à¦‡à¦Ÿà§‹ দিয়ক।</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="5644090287519800334">কাষৰ ১ পà§à§°à¦¤à¦¿à¦šà§à¦›à¦¬à¦¿ X শà§à¦¬à¦¿à¦«à§à¦Ÿ</translation>
@@ -1285,12 +1319,12 @@
<translation id="5785756445106461925">তাৰোপৰি, à¦à¦‡ পৃষà§à¦ à¦¾à¦¤ কিছà§à¦®à¦¾à¦¨ অসà§à§°à¦•à§à¦·à¦¿à¦¤ সমল আছে। à¦à¦‡ সমল পৰিবহণৰ সময়ত অনà§à¦¯ লোকসকলে চাব পাৰিব আৰৠপৃষà§à¦ à¦¾à¦Ÿà§‹à§° ৰূপ সলনি কৰিবলৈ কোনো আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à§Ÿà§‡ à¦à¦‡ সমল সংশোধন কৰিব পাৰে।</translation>
<translation id="5786044859038896871">আপà§à¦¨à¦¿ আপোনাৰ কাৰà§à¦¡à§° তথà§à¦¯ ভৰাব খোজে নেকি?</translation>
<translation id="578633867165174378">Chromeঠআপà§à¦¨à¦¿ à¦à¦‡à¦®à¦¾à¦¤à§à§° ডেটা উলংঘনত বà§à¦¯à§±à¦¹à¦¾à§° কৰা পাছৱৰà§à¦¡à¦Ÿà§‹ বিচাৰি পাইছে। আমি à¦à¦‡ পাছৱৰà§à¦¡à¦Ÿà§‹ à¦à¦¤à¦¿à§Ÿà¦¾à¦‡ সলনি কৰাটো চà§à¦ªà¦¾à§°à¦¿à¦› কৰোà¦à¥¤</translation>
-<translation id="5798290721819630480">সালসলনিসমূহ বাতিল কৰিবনে?</translation>
<translation id="5803412860119678065">আপà§à¦¨à¦¿ নিজৰ <ph name="CARD_DETAIL" /> পà§à§°à¦¾à¦¬ খোজেনে?</translation>
<translation id="5804241973901381774">অনà§à¦®à¦¤à¦¿</translation>
<translation id="5804427196348435412">NFC ডিভাইচসমূহ বà§à¦¯à§±à¦¹à¦¾à§° কৰক</translation>
<translation id="5810442152076338065">আপোনাৰ <ph name="DOMAIN" />ৰ সৈতে থকা সংযোগ কোনো অপà§à§°à¦šà¦²à¦¿à¦¤ চাইফাৰ ছà§à¦Ÿ বà§à¦¯à§±à¦¹à¦¾à§° কৰি à¦à¦¨à¦•à§à§°à¦¿à¦ªà§à¦Ÿ কৰা হৈছে।</translation>
<translation id="5813119285467412249">যোগ কৰা কারà§à¦¯ &amp;ৰিডৠকৰক</translation>
+<translation id="5817918615728894473">যোৰা লগাওক</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{আপà§à¦¨à¦¿ পৰিশোধ কৰিলে à¦à¦‡ কাৰà§à¦¡à¦–নৰ পৰা টকা আদায় দিয়া হ’ব কিনà§à¦¤à§ ইয়াৰ পà§à§°à¦•à§ƒà¦¤ নমà§à¦¬à§°à¦Ÿà§‹ à¦à¦‡ ছাইটটোৰ সৈতে শà§à¦¬à§‡à¦¯à¦¼à¦¾à§° কৰা নহ’ব। অতিৰিকà§à¦¤ সà§à§°à¦•à§à¦·à¦¾à§° বাবে à¦à¦Ÿà¦¾ সাময়িক CVC সৃষà§à¦Ÿà¦¿ কৰা হ’ব।}one{আপà§à¦¨à¦¿ পৰিশোধ কৰিলে আপà§à¦¨à¦¿ বাছনি কৰা কাৰà§à¦¡à¦–নৰ পৰা টকা আদায় দিয়া হ’ব কিনà§à¦¤à§ ইয়াৰ পà§à§°à¦•à§ƒà¦¤ নমà§à¦¬à§°à¦Ÿà§‹ à¦à¦‡ ছাইটটোৰ সৈতে শà§à¦¬à§‡à¦¯à¦¼à¦¾à§° কৰা নহ’ব। অতিৰিকà§à¦¤ সà§à§°à¦•à§à¦·à¦¾à§° বাবে à¦à¦Ÿà¦¾ সাময়িক CVC সৃষà§à¦Ÿà¦¿ কৰা হ’ব।}other{আপà§à¦¨à¦¿ পৰিশোধ কৰিলে আপà§à¦¨à¦¿ বাছনি কৰা কাৰà§à¦¡à¦–নৰ পৰা টকা আদায় দিয়া হ’ব কিনà§à¦¤à§ ইয়াৰ পà§à§°à¦•à§ƒà¦¤ নমà§à¦¬à§°à¦Ÿà§‹ à¦à¦‡ ছাইটটোৰ সৈতে শà§à¦¬à§‡à¦¯à¦¼à¦¾à§° কৰা নহ’ব। অতিৰিকà§à¦¤ সà§à§°à¦•à§à¦·à¦¾à§° বাবে à¦à¦Ÿà¦¾ সাময়িক CVC সৃষà§à¦Ÿà¦¿ কৰা হ’ব।}}</translation>
<translation id="5826507051599432481">কামাণà§à¦¡à§° নাম (CN)</translation>
<translation id="5838278095973806738">আপà§à¦¨à¦¿ à¦à¦‡ চাইটটোত কোনো সংবেদনশীল তথà§à¦¯ দিয়াটো উচিত নহয় (উদাহৰণ সà§à¦¬à§°à§‚পে, পাছৱৰà§à¦¡ বা কà§à§°à§‡à¦¡à¦¿à¦Ÿ কাৰà§à¦¡) কাৰণ à¦à§Ÿà¦¾ আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à§Ÿà§‡ চà§à§° কৰিব পাৰে।</translation>
@@ -1298,6 +1332,7 @@
<translation id="5855253129151731373">à¦à¦‡ ছাইটটোৰ হ'ষà§à¦Ÿà¦¨à¦¾à¦® <ph name="LOOKALIKE_DOMAIN" />ৰ দৰে à¦à¦•à§‡à¦‡ যেন লাগিছে। আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à¦¸à¦•à¦²à§‡ ড’মেইনৰ নামত কেতিয়াবা সৰà§, সহজে চকà§à¦¤ নপৰা সালসলনিসমূহ কৰি ছাইটসমূহ নকল কৰিব পাৰে।
যদি আপà§à¦¨à¦¿ বিশà§à¦¬à¦¾à¦¸ কৰিছে যে à¦à¦‡à¦Ÿà§‹ ভà§à¦²à¦¤à§‡ দেখà§à¦“ৱা হৈছে, অনà§à¦—à§à§°à¦¹ কৰি https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals চাওক।</translation>
+<translation id="5860033963881614850">অফ আছে</translation>
<translation id="5862579898803147654">ষà§à¦Ÿà§‡à¦•à¦¾à§° ৮</translation>
<translation id="5863847714970149516">পৰৱরà§à¦¤à§€ পৃষà§à¦ à¦¾à¦Ÿà§‹à§±à§‡ আপোনাৰ পৰা মাচà§à¦² ল’বলৈ চেষà§à¦Ÿà¦¾ কৰিব পাৰে</translation>
<translation id="5866257070973731571">ফ'ন নমà§à¦¬à§° যোগ কৰক</translation>
@@ -1314,6 +1349,7 @@
<translation id="5913377024445952699">সà§à¦•à§à§°à§€à¦¨ কেপচাৰ সà§à¦¬à¦¿à¦§à¦¾à¦Ÿà§‹ পজ কৰা হ'ল</translation>
<translation id="59174027418879706">সকà§à¦·à¦® কৰা আছে</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{১টা বà§à¦¯à§±à¦¹à¦¾à§° হৈ আছে}one{#টা বà§à¦¯à§±à¦¹à¦¾à§° হৈ আছে}other{#টা বà§à¦¯à§±à¦¹à¦¾à§° হৈ আছে}}</translation>
<translation id="5921185718311485855">অন</translation>
<translation id="5921639886840618607">কাৰà§à¦¡à¦–ন Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦¤ ছেভ কৰিবনে?</translation>
<translation id="5922853866070715753">পà§à§°à¦¾à§Ÿ সমà§à¦ªà§‚রà§à¦£ হৈছেই</translation>
@@ -1332,6 +1368,7 @@
<translation id="5989320800837274978">কোনো সà§à¦¥à¦¿à§° পà§à§°â€™à¦•à§à¦¸à§€ ছাৰà§à¦­à¦¾à§° নাইবা কোনো .pac সà§à¦•à§à§°à¦¿à¦ªà§à¦Ÿ URL নিৰà§à¦¦à¦¿à¦·à§à¦Ÿ কৰা নাই৷</translation>
<translation id="5992691462791905444">অভিযানà§à¦¤à§à¦°à¦¿à¦• Z-ফ'লà§à¦¡</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />'ৰ বাবে <ph name="RESULT_COUNT" />টা ফলাফল</translation>
+<translation id="6006484371116297560">ধà§à§°à§‚পদী</translation>
<translation id="6008122969617370890">বহà§à¦¤à§‹à§° পৰা à¦à¦Ÿà¦¾ কà§à§°à¦®</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">আপোনাৰ পাছৱরà§à¦¡à¦¬à§‹à§° পৰীকà§à¦·à¦¾ কৰক</translation>
@@ -1353,6 +1390,7 @@
<translation id="6045164183059402045">ইমà§à¦ªà¦œà¦¿à¦¶à§à¦¬à¦¨ টেমপà§à¦²à§‡â€™à¦Ÿ</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="6049004884579590341">সমà§à¦ªà§‚ৰà§à¦£ সà§à¦•à§à¦°à§€à¦£à§° পৰা পà§à§°à¦¸à§à¦¥à¦¾à¦¨ কৰিবলৈ |<ph name="ACCELERATOR" />| সà§à¦ªà§°à§à¦¶ কৰি ধৰি ৰাখক</translation>
<translation id="6049488691372270142">পৃষà§à¦ à¦¾ ডেলিভাৰী</translation>
<translation id="6051221802930200923">আপà§à¦¨à¦¿ à¦à¦‡ মà§à¦¹à§‚ৰà§à¦¤à¦¤ <ph name="SITE" /> চাব নোৱাৰে কাৰণ à¦à¦‡ ৱেবছাইটটোৱে পà§à§°à¦®à¦¾à¦£ পতà§à§° পিন কৰা সà§à¦¬à¦¿à¦§à¦¾à¦Ÿà§‹ বà§à¦¯à§±à¦¹à¦¾à§° কৰে। নেটৱরà§à¦• সমà§à¦ªà¦°à§à¦•à§€à§Ÿ আসোà¦à§±à¦¾à¦¹ আৰৠআকà§à§°à¦®à¦£à¦¸à¦®à§‚হ সাধাৰণতে অসà§à¦¥à¦¾à§Ÿà§€ হয় গতিকে à¦à¦‡ পৃষà§à¦ à¦¾à¦Ÿà§‹à§±à§‡ কিছà§à¦¸à¦®à§Ÿà§° পাছত কাম কৰিব পাৰে।</translation>
<translation id="6051898664905071243">পৃষà§à¦ à¦¾à§° সংখà§à¦¯à¦¾:</translation>
@@ -1369,6 +1407,7 @@
<translation id="610911394827799129">আপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà§° <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />ত অনà§à¦¯ বà§à§°à¦¾à¦‰à¦œà¦¿à¦‚ ইতিহাস থাকিব পাৰে৷</translation>
<translation id="6116338172782435947">কà§à¦²à¦¿à¦ªà¦¬â€™à§°à§à¦¡à¦²à§ˆ পà§à§°à¦¤à¦¿à¦²à¦¿à¦ªà¦¿ কৰা পাঠ আৰৠপà§à§°à¦¤à¦¿à¦šà§à¦›à¦¬à¦¿ চাওক</translation>
<translation id="6120179357481664955">আপোনাৰ UPI IDটো মনত আছেনে?</translation>
+<translation id="6123290840358279103">ভাৰà§à¦šà§à§±à§‡à¦² কাৰà§à¦¡à¦–ন চাওক</translation>
<translation id="6124432979022149706">Chrome à¦à¦£à§à¦Ÿà¦¾à§°à¦ªà§à§°à¦¾à¦‡à¦œ কানেকà§à¦Ÿà§°à¦¸à¦®à§‚হ</translation>
<translation id="6146055958333702838">কোনো কেবল পৰীকà§à¦·à¦¾ কৰক আৰৠআপà§à¦¨à¦¿ বà§à¦¯à§±à¦¹à¦¾à§° কৰি থকা কোনো ৰাউটাৰ, ম’ডেম বা অনà§à¦¯ নেটৱৰà§à¦• ডিভাইচ ৰিবà§à¦Ÿ কৰক।</translation>
<translation id="614940544461990577">à¦à¦‡à¦–িনি কৰি চাওক:</translation>
@@ -1404,6 +1443,7 @@
<translation id="6289939620939689042">পৃষà§à¦ à¦¾à§° ৰং</translation>
<translation id="6290238015253830360">আপà§à¦¨à¦¿ পৰামৰà§à¦¶ দিয়া পà§à§°à¦¬à¦¨à§à¦§à¦¬à§‹à§° ইয়াত দেখা যাব</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">চিভিচি:</translation>
<translation id="6302269476990306341">Chromeত Google Assistant বনà§à¦§ হ'ব</translation>
<translation id="6305205051461490394"><ph name="URL" />ত উপনীত হ’ব নোৱাৰি৷</translation>
<translation id="6312113039770857350">ৱেবপৃষà§à¦ à¦¾ উপলবà§à¦§ নহয়</translation>
@@ -1429,6 +1469,7 @@
<translation id="6390200185239044127">Z-ফ'লà§à¦¡ আধা</translation>
<translation id="6390662030813198813">অভিযানà§à¦¤à§à¦°à¦¿à¦•-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" />ৰ পৰা à¦à¦‡ অৱসà§à¦¥à¦¾à¦¨à¦Ÿà§‹à¦¤ পে’ষà§à¦Ÿ কৰাৰ সà§à¦¬à¦¿à¦§à¦¾à¦Ÿà§‹ পà§à¦°à¦¶à¦¾à¦¸à¦•à§° নীতিয়ে অৱৰোধ কৰিছে</translation>
+<translation id="6398765197997659313">সমà§à¦ªà§‚রà§à¦£ সà§à¦•à§à§°à§€à¦£ ম’ডৰ পৰা বাহিৰ হওক</translation>
<translation id="6401136357288658127">à¦à¦‡ নীতিটো অপà§à§°à¦šà¦²à¦¿à¦¤à¥¤ আপà§à¦¨à¦¿ তাৰ পৰিৱৰà§à¦¤à§‡ <ph name="NEW_POLICY" /> নীতিটো বà§à¦¯à§±à¦¹à¦¾à§° কৰা উচিত।</translation>
<translation id="6404511346730675251">বà§à¦•à¦®à¦¾à¦°à§à¦• সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ কৰক</translation>
<translation id="6406765186087300643">C0 (লেফাফা)</translation>
@@ -1441,7 +1482,6 @@
<translation id="6428450836711225518">আপোনাৰ ফ’ন নমà§à¦¬à§°à¦Ÿà§‹ সতà§à¦¯à¦¾à¦ªà¦¨ কৰক</translation>
<translation id="6433490469411711332">সমà§à¦ªà¦°à§à¦•à§° তথà§à¦¯ সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ কৰক</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" />ঠসংযোগ কৰিবলৈ অসà§à¦¬à§€à¦•à¦¾à§° কৰিছে।</translation>
-<translation id="6434309073475700221">পà§à§°à¦¤à§à¦¯à¦¾à¦–à§à¦¯à¦¾à¦¨ কৰক</translation>
<translation id="6440503408713884761">উপেকà§à¦·à¦¿à¦¤ কৰা হৈছে</translation>
<translation id="6443406338865242315">আপà§à¦¨à¦¿ ইনষà§à¦Ÿà¦² কৰা à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à§à¦¬à¦¨ আৰৠপà§à¦²à¦¾à¦—ইনসমূহ</translation>
<translation id="6446163441502663861">কাহৠ(লেফাফা)</translation>
@@ -1484,6 +1524,7 @@
<translation id="6624427990725312378">যোগাযোগৰ তথà§à¦¯</translation>
<translation id="6626291197371920147">মানà§à¦¯ কারà§à¦¡ নমà§à¦¬à§° যোগ কৰক</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Search</translation>
+<translation id="6630043285902923878">ইউà¦à¦›à¦¬à¦¿ ডিভাইচ বিচাৰি থকা হৈছে...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">মচক</translation>
@@ -1499,6 +1540,7 @@
<translation id="6671697161687535275">Chromiumৰ পৰা ফ’ৰà§à¦®à§° পৰামৰà§à¦¶ আà¦à¦¤à§°à¦¾à¦¬à¦¨à§‡?</translation>
<translation id="6685834062052613830">ছাইন আউট কৰি ছেট আপ সমà§à¦ªà§‚ৰà§à¦£ কৰক</translation>
<translation id="6687335167692595844">ফ’ণà§à¦Ÿà§° আকাৰ অনà§à§°à§‹à¦§ কৰা হৈছে</translation>
+<translation id="6688743156324860098">আপডে’ট কৰক…</translation>
<translation id="6689249931105087298">ক’লা পইণà§à¦Ÿà§° কমপà§à§°à§‡à¦¶à§à¦¬à¦¨à§° সৈতে আপেকà§à¦·à¦¿à¦•</translation>
<translation id="6689271823431384964">আপà§à¦¨à¦¿ ছাইন ইন কৰি থোৱাৰ বাবে Chromeঠআপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦¤ আপোনাৰ কারà§à¦¡à¦¸à¦®à§‚হ ছেভ কৰাৰ সà§à¦¬à¦¿à¦§à¦¾ দিছে। আপà§à¦¨à¦¿ ছেটিংসমূহত à¦à¦‡ আচৰণ সলনি কৰিব পাৰে। কাৰà§à¦¡à§° ধাৰকৰ নামটো আপোনাৰ à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà§° পৰা আহে।</translation>
<translation id="6698381487523150993">সৃষà§à¦Ÿà¦¿ কৰাৰ সময়:</translation>
@@ -1514,6 +1556,7 @@
<translation id="6744009308914054259">সংযোগলৈ অপেকà§à¦·à¦¾ কৰি থকা সময়ত আপà§à¦¨à¦¿ ডাউনল’ড-লৈ গৈ অফলাইনত থকা লেখাসমূহ পà§à¦¿à¦¬ পাৰে।</translation>
<translation id="6753269504797312559">নীতিৰ মান</translation>
<translation id="6757797048963528358">আপোনাৰ ডিভাইচটো সà§à¦ªà§à¦¤ অৱসà§à¦¥à¦¾à¦²à§ˆ গৈছে।</translation>
+<translation id="6767985426384634228">ঠিকনা আপডে’ট কৰিবনে?</translation>
<translation id="6768213884286397650">হেগাকি (প'ষà§à¦Ÿà¦•à¦¾à§°à§à¦¡)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">বেঙà§à¦¨à§€à§Ÿà¦¾</translation>
@@ -1536,6 +1579,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chromeঠà¦à¦‡ পৃষà§à¦ à¦¾à¦–ন সৰলীকৃত কৰিছে যাতে à¦à¦‡à¦–ন সহজে পঢ়িব পাৰি। à¦à¦Ÿà¦¾ অসà§à§°à¦•à§à¦·à¦¿à¦¤ সংযোগৰ জৰিয়তে Chromeঠমূল পৃষà§à¦ à¦¾à¦–ন পà§à¦¨à§°à§à¦¦à§à¦§à¦¾à§° কৰিছে।</translation>
<translation id="6891596781022320156">নীতিটোৰ সà§à¦¤à§° সমরà§à¦¥à¦¨ নকৰে।</translation>
+<translation id="6895143722905299846">ভাৰà§à¦›à§à§±à§‡à¦² নমà§à¦¬à§°:</translation>
<translation id="6895330447102777224">আপোনাৰ কারà§à¦¡ নিশà§à¦šà¦¿à¦¤ কৰা হৈছে</translation>
<translation id="6897140037006041989">বà§à¦¯à§±à¦¹à¦¾à§°à¦•à¦¾à§°à§€à§° à¦à¦œà§‡à¦£à§à¦Ÿ</translation>
<translation id="6898699227549475383">পà§à§°à¦¤à¦¿à¦·à§à¦ à¦¾à¦¨ (O)</translation>
@@ -1571,10 +1615,10 @@
<translation id="7004583254764674281">কাৰà§à¦¡à¦¸à¦®à§‚হ খৰতকীয়াকৈ নিশà§à¦šà¦¿à¦¤ কৰিবলৈ Windows Hello বà§à¦¯à§±à¦¹à¦¾à§° কৰক</translation>
<translation id="7006930604109697472">তথাপি পঠিয়াওক</translation>
<translation id="7012363358306927923">China Union Pay</translation>
-<translation id="7012404007611495949">আকাৰ সলনি কৰাৰ ছেটিং</translation>
<translation id="7014741021609395734">জà§à¦®à§° সà§à¦¤à§°</translation>
<translation id="7016992613359344582">à¦à¦‡ মাচà§à¦²à¦Ÿà§‹ à¦à¦¬à¦¾à§°à§‡à¦‡ বা বাৰে বাৰে দিবলগীয়া হ’ব পাৰে আৰৠসেইটো সà§à¦¨à¦¿à§°à§à¦¦à¦¿à¦·à§à¦Ÿ নহ’ব পাৰে।</translation>
<translation id="7029809446516969842">পাছৱৰà§à¦¡à¦¸à¦®à§‚হ</translation>
+<translation id="7030436163253143341">পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§°à¦–ন মানà§à¦¯ নহয়</translation>
<translation id="7031646650991750659">আপà§à¦¨à¦¿ কোনবোৰ Google Play à¦à¦ªà§â€Œ ইনষà§à¦Ÿà¦² কৰিছে</translation>
<translation id="7050187094878475250">আপà§à¦¨à¦¿ <ph name="DOMAIN" />লৈ যাবলৈ চেষà§à¦Ÿà¦¾ কৰিছিল, কিনà§à¦¤à§ ছাৰà§à¦­à¦¾à§°à¦Ÿà§‹à§±à§‡ à¦à¦–ন পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§° উপসà§à¦¥à¦¾à¦ªà¦¨ কৰিছে যাৰ মà§à¦¯à¦¾à¦¦ উকলাৰ সময় অৱধি যথেষà§à¦Ÿ দীঘল হোৱাৰ বাবে সেইখন বিশà§à¦¬à¦¾à¦¸ কৰিব নোৱাৰি।</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{à¦à¦‡ মà§à¦¹à§‚ৰà§à¦¤à¦¤ à¦à¦‡ কারà§à¦¡à¦–ন ছেভ কৰিব নোৱাৰি}one{à¦à¦‡ মà§à¦¹à§‚ৰà§à¦¤à¦¤ à¦à¦‡ কারà§à¦¡à¦¸à¦®à§‚হ ছেভ কৰিব নোৱাৰি}other{à¦à¦‡ মà§à¦¹à§‚ৰà§à¦¤à¦¤ à¦à¦‡ কারà§à¦¡à¦¸à¦®à§‚হ ছেভ কৰিব নোৱাৰি}}</translation>
@@ -1642,12 +1686,14 @@
<translation id="7300012071106347854">ক’বালà§à¦Ÿ বà§à¦²à§</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">উচà§à¦š</translation>
+<translation id="7305756307268530424">লেহেমীয়া গতি আৰমà§à¦­ কৰক</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">সংযোগ সমà§à¦ªà§°à§à¦•à§€à§Ÿ সহায়</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" শাখাটো লà§à¦•à§à§±à¦¾à¦“ক</translation>
<translation id="733354035281974745">ডিভাইচ ল’কেল à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿ অ’ভাৰৰাইড</translation>
<translation id="7333654844024768166">আপà§à¦¨à¦¿ à¦à¦Ÿà¦¾ পà§à§°à§±à¦žà§à¦šà¦¨à¦¾à¦®à§‚লক ছাইটত à¦à¦‡à¦®à¦¾à¦¤à§à§° নিজৰ পাছৱৰà§à¦¡à¦Ÿà§‹ দিছে। Chromiumঠ<ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> আৰৠআপà§à¦¨à¦¿ à¦à¦‡ পাছৱৰà§à¦¡à¦Ÿà§‹ বà§à¦¯à§±à¦¹à¦¾à§° কৰা অনà§à¦¯ ছাইটসমূহলৈ গৈ à¦à¦‡à¦Ÿà§‹ à¦à¦¤à¦¿à¦¯à¦¼à¦¾à¦‡ সলনি কৰাটো চà§à¦ªà¦¾à§°à¦¿à¦› কৰে।</translation>
<translation id="7334320624316649418">&amp;পà§à¦¨à§° কà§à§°à¦®à¦¬à¦¦à§à¦§ কৰাটো ৰিডৠকৰক</translation>
+<translation id="7337248890521463931">অধিক শাৰী দেখà§à§±à¦¾à¦“ক</translation>
<translation id="7337706099755338005">আপোনাৰ পà§à¦²à§‡à¦Ÿà¦«â€™à§°à§à¦®à¦¤ উপলবà§à¦§ নহয়৷</translation>
<translation id="733923710415886693">ছারà§à¦­à¦¾à§°à§° পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§°à¦–ন পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§°à§° সà§à¦¬à¦šà§à¦›à¦¤à¦¾à§° মাধà§à¦¯à¦®à§‡à§°à§‡ ঘোষণা কৰা হোৱা নাছিল।</translation>
<translation id="734600844861828519">১১x১৫</translation>
@@ -1655,6 +1701,7 @@
<translation id="7349430561505560861">A4-অতিৰিকà§à¦¤</translation>
<translation id="7353601530677266744">কামাণà§à¦¡ লাইন</translation>
<translation id="7359588939039777303">বিজà§à¦žà¦¾à¦ªà¦¨ অৱৰোধ কৰা হ'ল।</translation>
+<translation id="7363096869660964304">তথাপি, আপà§à¦¨à¦¿ অদৃশà§à¦¯ নহয়। আপà§à¦¨à¦¿ ইনক’গনিট’ টেব বà§à¦¯à§±à¦¹à¦¾à§° কৰিলেও আপোনাৰ নিয়োগকৰà§à¦¤à¦¾, ইণà§à¦Ÿà¦¾à§°à¦¨à§‡à¦Ÿ সেৱা পà§à§°à¦¦à¦¾à¦¨à¦•à¦¾à§°à§€ অথবা আপà§à¦¨à¦¿ চোৱা ৱেবছাইটে আপোনাৰ বà§à§°à¦¾à¦‰à¦œà¦¿à¦™à§° তথà§à¦¯ চাব পাৰে।</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chromeৰ ছেটিঙত ঠিকনা যোগ দিবলৈ আৰৠপৰিচালনা কৰিবলৈ পà§à§°à¦¥à¦®à§‡ টেব আৰৠতাৰ পাছত à¦à¦£à§à¦Ÿà¦¾à§° টিপক</translation>
<translation id="7365849542400970216">আপোনাৰ ডিভাইচটো বà§à¦¯à§±à¦¹à¦¾à§° কৰাৰ সমà§à¦ªà§°à§à¦•à§‡ জানেনে?</translation>
<translation id="7372973238305370288">ফলাফল সনà§à¦§à¦¾à¦¨ কৰক</translation>
@@ -1665,7 +1712,9 @@
<translation id="7378594059915113390">মিডিয়াৰ নিয়নà§à¦¤à§à§°à¦£à¦¸à¦®à§‚হ</translation>
<translation id="7378627244592794276">নহয়</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">পà§à§°à¦¯à§‹à¦œà§à¦¯ নহয়</translation>
<translation id="7390545607259442187">কাৰà§à¦¡à¦–ন নিশà§à¦šà¦¿à¦¤ কৰক</translation>
+<translation id="7392089738299859607">ঠিকনা আপডে’ট কৰক</translation>
<translation id="7399802613464275309">সà§à§°à¦•à§à¦·à¦¾ পৰীকà§à¦·à¦¾</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">আপোনাৰ <ph name="DEVICE_NAME" /> পৰিচালিত</translation>
@@ -1680,6 +1729,7 @@
&lt;li&gt;আপোনাৰ কমà§à¦ªà¦¿à¦‰à¦Ÿà¦¾à§°à§° পৰা ছফà§â€Œà¦Ÿà§±à§‡à§°à¦Ÿà§‹ কেনেকৈ সà§à¦¥à¦¾à§Ÿà§€à¦­à¦¾à§±à§‡ আà¦à¦¤à§°à¦¾à§Ÿ সেই সমà§à¦ªà§°à§à¦•à§‡ জানিবলৈ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome সহায় কেনà§à¦¦à§à§°&lt;/a&gt; চাওক
&lt;/ol&gt;</translation>
<translation id="741007362987735528">বহল-ফৰà§à¦®à§‡à¦Ÿ</translation>
+<translation id="7410471291937727359">মৰম-লগা</translation>
<translation id="7416351320495623771">পাছৱৰà§à¦¡ পৰিচালনা কৰক…</translation>
<translation id="7419106976560586862">পà§à§°â€™à¦«à¦¾à¦‡à¦²à§° পথ</translation>
<translation id="7437289804838430631">সমà§à¦ªà¦°à§à¦•à§° তথà§à¦¯ যোগ কৰক</translation>
@@ -1695,7 +1745,7 @@
<translation id="7481312909269577407">ফৰৱাৰà§à¦¡ কৰক</translation>
<translation id="7485870689360869515">কোনো ডেটা বিচাৰি পোৱা নগ’ল।</translation>
<translation id="7495528107193238112">à¦à¦‡ সমলটো অৱৰোধ কৰা হৈছে। সমসà§à¦¯à¦¾à¦Ÿà§‹ সমাধান কৰিবলৈ ছাইটৰ গৰাকীৰ সৈতে যোগাযোগ কৰক।</translation>
-<translation id="7498234416455752244">সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ কৰি থাকক</translation>
+<translation id="7498193950643227031">à¦à¦‡à¦Ÿà§‹à§° আকাৰ সলনি কৰিলে ই অসà§à¦¬à¦¾à¦­à¦¾à§±à¦¿à¦•à¦­à¦¾à§±à§‡ আচৰণ কৰিব পাৰে। আপà§à¦¨à¦¿ à¦à¦¤à¦¿à§Ÿà¦¾ <ph name="SETTINGS" />ত à¦à¦ªà§° আকাৰ সলনি কৰিব পৰাটো সীমিত কৰিব পাৰে।</translation>
<translation id="7503664977220660814">আপà§à¦¨à¦¿ à¦à¦Ÿà¦¾ পà§à§°à§±à¦žà§à¦šà¦¨à¦¾à¦®à§‚লক ছাইটত à¦à¦‡à¦®à¦¾à¦¤à§à§° নিজৰ পাছৱৰà§à¦¡à¦Ÿà§‹ দিছে। Chromiumঠ<ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> আৰৠঅনà§à¦¯ ছাইটসমূহ, য’ত আপà§à¦¨à¦¿ à¦à¦‡ পাছৱৰà§à¦¡à¦Ÿà§‹ বà§à¦¯à§±à¦¹à¦¾à§° কৰে সেইবিলাকত ছেভ কৰি থোৱা আপোনাৰ পাছৱৰà§à¦¡à¦¸à¦®à§‚হ à¦à¦¤à¦¿à§Ÿà¦¾à¦‡ পৰীকà§à¦·à¦¾ কৰাটো চà§à¦ªà¦¾à§°à¦¿à¦› কৰে।</translation>
<translation id="7508255263130623398">উভতোৱা নীতিৰ ডিভাইচ আইডি খালী বা বরà§à¦¤à¦®à¦¾à¦¨ আইডি সৈতে অমিল</translation>
<translation id="7508870219247277067">গাৠসেউজীয়া</translation>
@@ -1715,6 +1765,7 @@
<translation id="7548892272833184391">সংযোগ সমà§à¦ªà¦°à§à¦•à§€à§Ÿ সমসà§à¦¯à¦¾à§° সমাধান কৰক</translation>
<translation id="7549584377607005141">সঠিকভাৱে দেখà§à§±à¦¾à¦¬à¦²à§ˆ ৱেব পৃষà§à¦ à¦¾à¦Ÿà§‹à¦• আপà§à¦¨à¦¿ আগতে দিয়া ডেটাৰ পà§à§°à¦¯à¦¼à§‹à¦œà¦¨ হ'ব। আপà§à¦¨à¦¿ à¦à¦‡ ডেটাখিনি পà§à¦¨à§° পঠিয়াব পাৰে, কিনà§à¦¤à§ সেয়া কৰিলে à¦à¦‡ পৃষà§à¦ à¦¾à¦Ÿà§‹à§±à§‡ কৰা পূৰà§à¦¬à§±à§°à§à¦¤à§€ কোনো কাৰà§à¦¯à§° পà§à¦¨à§°à¦¾à¦¬à§ƒà¦¤à§à¦¤à¦¿ হ'ব পাৰে।</translation>
<translation id="7550637293666041147">আপোনাৰ ডিভাইচৰ বà§à¦¯à§±à¦¹à¦¾à§°à¦•à¦¾à§°à§€ নাম আৰৠChromeৰ বà§à¦¯à§±à¦¹à¦¾à§°à¦•à¦¾à§°à§€ নাম</translation>
+<translation id="755279583747225797">টà§à§°à¦¾à§Ÿà§‡à¦²à¦Ÿà§‹ সকà§à§°à¦¿à§Ÿ হৈ আছে</translation>
<translation id="7554475479213504905">পà§à¦¨à§° ল’ড কৰক আৰৠতথাপিও দেখà§à§±à¦¾à¦“ক</translation>
<translation id="7554791636758816595">নতà§à¦¨ টেব</translation>
<translation id="7564049878696755256">আপà§à¦¨à¦¿ <ph name="ORG_NAME" /> à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦Ÿà§‹ à¦à¦•à§à¦¸à§‡à¦› কৰিব নোৱাৰা হ’ব পাৰে বা আপোনাৰ পৰিচয় চà§à§°à¦¿ হোৱাৰ নিচিনা ঘটনাৰ মà§à¦–ামà§à¦–ী হ’ব পাৰে। Chromeঠআপোনাৰ পাছৱৰà§à¦¡à¦Ÿà§‹ à¦à¦¤à¦¿à¦¯à¦¼à¦¾à¦‡ সলনি কৰাটো চà§à¦ªà¦¾à§°à¦¿à¦› কৰে।</translation>
@@ -1732,7 +1783,6 @@
<translation id="7610193165460212391"><ph name="VALUE" /> মান পৰিসৰৰ বাহিৰৰ।</translation>
<translation id="7613889955535752492">মà§à¦¯à¦¾à¦¦ উকলিব: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chromeৰ ছেটিংসমূহত আপোনাৰ পাছৱৰà§à¦¡à¦¸à¦®à§‚হ চাবলৈ আৰৠপৰিচালনা কৰিবলৈ পà§à§°à¦¥à¦®à§‡ টেব আৰৠতাৰ পাছত à¦à¦£à§à¦Ÿà¦¾à§° টিপক</translation>
-<translation id="7615602087246926389">আপোনাৰ ওচৰত ইতিমধà§à¦¯à§‡à¦‡ à¦à¦¨à§‡à¦•à§à§±à¦¾ ডেটা আছে যিবোৰ আপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà§° পাছৱৰà§à¦¡à§° কোনো ভিনà§à¦¨ সংসà§à¦•à§°à¦£ বà§à¦¯à§±à¦¹à¦¾à§° কৰি à¦à¦¨à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ কৰা হৈছে। অনà§à¦—à§à§°à¦¹ কৰি সেইটো তলত দিয়ক।</translation>
<translation id="7616645509853975347">আপোনাৰ পà§à§°à¦¶à¦¾à¦¸à¦•à§‡ আপোনাৰ বà§à§°à¦¾à¦‰à¦œà¦¾à§°à¦¤ Chrome à¦à¦£à§à¦Ÿà¦¾à§°à¦ªà§à§°à¦¾à¦‡à¦œ কানেকà§à¦Ÿà§°à¦¸à¦®à§‚হ অন কৰিছে। à¦à¦‡ কানেকà§à¦Ÿà§°à¦¸à¦®à§‚হৰ আপোনাৰ কিছà§à¦®à¦¾à¦¨ ডেটালৈ à¦à¦•à§à¦¸à§‡à¦› আছে।</translation>
<translation id="7619838219691048931">অনà§à¦¤à¦¿à¦®à¦–ন শà§à¦¬à§€à¦Ÿ</translation>
<translation id="762844065391966283">à¦à¦¬à¦¾à§°à¦¤ à¦à¦Ÿà¦¾</translation>
@@ -1797,13 +1847,12 @@
<translation id="782886543891417279">আপà§à¦¨à¦¿ বà§à¦¯à§±à¦¹à¦¾à§° কৰি থকা ৱাই-ফাইটোৰ(<ph name="WIFI_NAME" />) বাবে আপà§à¦¨à¦¿ তাৰ লগ ইন কৰা পৃষà§à¦ à¦¾à¦²à§ˆ যাব লগা হ’ব পাৰে।</translation>
<translation id="7836231406687464395">প'ষà§à¦Ÿà¦«à¦¿à¦•à§à¦¸ (লেফাফা)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{à¦à¦Ÿà¦¾à¦“ নহয়}=1{১টা à¦à¦ªà§ (<ph name="EXAMPLE_APP_1" />)}=2{২টা à¦à¦ªà§ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{#টা à¦à¦ªà§ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{#টা à¦à¦ªà§ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">তথাপি, আপà§à¦¨à¦¿ অদৃশà§à¦¯ নহয়। আপà§à¦¨à¦¿ ইনক'গনিট' ৱিণà§à¦¡' বà§à¦¯à§±à¦¹à¦¾à§° কৰিলেও আপোনাৰ নিয়োগদাতা, ইণà§à¦Ÿà¦¾à§°à¦¨à§‡à¦Ÿ সেৱা পà§à§°à¦¦à¦¾à¦¨à¦•à¦¾à§°à§€ বা আপà§à¦¨à¦¿ চোৱা ৱেবছাইতে আপোনাৰ বà§à§°à¦¾à¦‰à¦œà¦¿à¦‚ৰ তথà§à¦¯ চাব পাৰে।</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ফাইলৰ পà§à§°à¦•à¦¾à§° সহযোগী থকা ফাইল খোলক।</translation>
<translation id="7862185352068345852">ছাইটোৰ পৰা বাহিৰ হ’বনে?</translation>
<translation id="7865448901209910068">উতà§à¦¤à¦® বেগ</translation>
<translation id="7874263914261512992">আপà§à¦¨à¦¿ à¦à¦Ÿà¦¾ পà§à§°à§±à¦žà§à¦šà¦¨à¦¾à¦®à§‚লক ছাইটত à¦à¦‡à¦®à¦¾à¦¤à§à§° নিজৰ পাছৱৰà§à¦¡à¦Ÿà§‹ দিছে। Chromeঠ<ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> আৰৠঅনà§à¦¯ ছাইটসমূহ, য’ত আপà§à¦¨à¦¿ à¦à¦‡ পাছৱৰà§à¦¡à¦Ÿà§‹ বà§à¦¯à§±à¦¹à¦¾à§° কৰে সেইবিলাকত ছেভ কৰি থোৱা আপোনাৰ পাছৱৰà§à¦¡à¦¸à¦®à§‚হ à¦à¦¤à¦¿à§Ÿà¦¾à¦‡ পৰীকà§à¦·à¦¾ কৰাটো চà§à¦ªà¦¾à§°à¦¿à¦› কৰে।</translation>
<translation id="7878562273885520351">আপোনাৰ পাছৱৰà§à¦¡à¦Ÿà§‹ হয়তো হেক হৈছে</translation>
+<translation id="7880146494886811634">ঠিকনা ছেভ কৰক</translation>
<translation id="7882421473871500483">মাটীয়া</translation>
<translation id="7887683347370398519">আপোনাৰ CVC পৰীকà§à¦·à¦¾ কৰি আকৌ চেষà§à¦Ÿà¦¾ কৰক</translation>
<translation id="7887885240995164102">চিতà§à§°à§° ভিতৰত চিতà§à§° আৰমà§à¦­ কৰক</translation>
@@ -1811,6 +1860,7 @@
<translation id="7894280532028510793">যদি বানান ঠিকে আছে, <ph name="BEGIN_LINK" />নেটৱৰà§à¦• ডায়গন’ষà§à¦Ÿà¦¿à¦•à§à¦¸ চলাই চাওক<ph name="END_LINK" />।</translation>
<translation id="7904208859782148177">C3 (লেফাফা)</translation>
<translation id="7931318309563332511">অজà§à¦žà¦¾à¦¤</translation>
+<translation id="793209273132572360">ঠিকনা আপডে’ট কৰিবনে?</translation>
<translation id="7932579305932748336">ক'ট কৰক</translation>
<translation id="79338296614623784">à¦à¦Ÿà¦¾ মানà§à¦¯ ফ’ন নমà§à¦¬à§° দিয়ক</translation>
<translation id="7934052535022478634">পৰিশোধ কৰা হ'ল</translation>
@@ -1881,6 +1931,7 @@
<translation id="8175796834047840627">আপà§à¦¨à¦¿ ছাইন ইন কৰি থোৱাৰ বাবে Chromeঠআপোনাৰ Google à¦à¦•à¦¾à¦‰à¦£à§à¦Ÿà¦¤ আপোনাৰ কারà§à¦¡à¦¸à¦®à§‚হ ছেভ কৰাৰ সà§à¦¬à¦¿à¦§à¦¾ দিছে। আপà§à¦¨à¦¿ ছেটিংসমূহ-ত à¦à§Ÿà¦¾ সলনি কৰিব পাৰে।</translation>
<translation id="8176440868214972690">à¦à¦‡ ডিভাইচটোৰ পà§à§°à¦¶à¦¾à¦¸à¦•à§‡ à¦à¦‡ ৱেবছাইটসমূহলৈ ছেটিং অথবা নীতিৰ দৰে কিছà§à¦®à¦¾à¦¨ তথà§à¦¯ পঠিয়াইছে।</translation>
<translation id="8184538546369750125">গà§à¦²â€™à¦¬à§‡à¦² ডিফ’লà§à¦Ÿ বà§à¦¯à§±à¦¹à¦¾à§° কৰক (অনà§à¦®à¦¤à¦¿ দিয়ক)</translation>
+<translation id="8193086767630290324">গোপনীয় হিচাপে চিহà§à¦¨à¦¿à¦¤ কৰা ডেটা সমà§à¦ªà§°à§à¦•à§‡ লোৱা কাৰà§à¦¯à¦¬à§à¦¯à§±à¦¸à§à¦¥à¦¾</translation>
<translation id="8194797478851900357">আà¦à¦¤à§°à§‹à§±à¦¾ কাৰà§à¦¯ &amp;আনডৠকৰক</translation>
<translation id="8201077131113104583">আইডি "<ph name="EXTENSION_ID" />"যà§à¦•à§à¦¤ à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à§à¦¬à¦¨à§° আপডে‘ট URL মানà§à¦¯ নহয়।</translation>
<translation id="8202097416529803614">অ’ৰà§à¦¡à¦¾à§°à§° সাৰাংশ</translation>
@@ -1903,6 +1954,7 @@
<translation id="8249296373107784235">নিষà§à¦«à¦² কৰক</translation>
<translation id="8249320324621329438">অনà§à¦¤à¦¿à¦®à¦¬à¦¾à§° বিচৰা হৈছিল:</translation>
<translation id="8253091569723639551">বিলিঙৰ ঠিকনা আৱশà§à¦¯à¦•</translation>
+<translation id="8257387598443225809">à¦à¦‡ à¦à¦ªà§â€Œà¦Ÿà§‹ ম'বাইলৰ বাবে ডিজাইন কৰা হৈছে</translation>
<translation id="825929999321470778">ছেভ কৰি থোৱা সকলো পাছৱৰà§à¦¡ দেখà§à§±à¦¾à¦“ক</translation>
<translation id="8261506727792406068">মচক</translation>
<translation id="8262952874573525464">তলৰ অংশৰ কাষত চিলাওক</translation>
@@ -2026,7 +2078,6 @@
<translation id="8719528812645237045">ওপৰৰ অংশত à¦à¦•à¦¾à¦§à¦¿à¦• পাঞà§à¦š কৰক</translation>
<translation id="8725066075913043281">আকৌ চেষà§à¦Ÿà¦¾ কৰক</translation>
<translation id="8726549941689275341">পৃষà§à¦ à¦¾à§° আকাৰ:</translation>
-<translation id="8728672262656704056">আপà§à¦¨à¦¿ ইনক’গনিট’ ম’ডত পà§à§°à§±à§‡à¦¶ কৰিছে</translation>
<translation id="8730621377337864115">হ’ল</translation>
<translation id="8731544501227493793">পাছৱৰà§à¦¡à¦¸à¦®à§‚হ পৰিচালনা কৰক বà§à¦Ÿà¦¾à¦®, Chromeৰ ছেটিংসমূহত আপোনাৰ পাছৱৰà§à¦¡à¦¸à¦®à§‚হ চাবলৈ আৰৠপৰিচালনা কৰিবলৈ à¦à¦£à§à¦Ÿà¦¾à§° টিপক</translation>
<translation id="8734529307927223492">আপোনাৰ <ph name="DEVICE_TYPE" /> <ph name="MANAGER" />ঠপৰিচালনা কৰে</translation>
@@ -2103,6 +2154,7 @@
<translation id="9020542370529661692">à¦à¦‡ পৃষà§à¦ à¦¾à¦Ÿà§‹ <ph name="TARGET_LANGUAGE" />লৈ অনà§à¦¬à¦¾à¦¦ কৰা হৈছে</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(অমানà§à¦¯)</translation>
+<translation id="9030265603405983977">ম’ন’কà§à§°à¦®</translation>
<translation id="9035022520814077154">সà§à§°à¦•à§à¦·à¦¾à¦œà¦¨à¦¿à¦¤ আসোà¦à§±à¦¾à¦¹</translation>
<translation id="9038649477754266430">পৃষà§à¦ à¦¾à¦¸à¦®à§‚হ অধিক কà§à¦·à¦¿à¦ªà§à§°à¦­à¦¾à§±à§‡ ল'ড কৰিবলৈ কোনো অনà§à¦®à¦¾à¦¨ কৰা সেৱা বà§à¦¯à§±à¦¹à¦¾à§° কৰক</translation>
<translation id="9039213469156557790">তদà§à¦ªà§°à¦¿, à¦à¦‡ পৃষà§à¦ à¦¾à¦¤ কিছà§à¦®à¦¾à¦¨ অসà§à§°à¦•à§à¦·à¦¿à¦¤ সমল আছে। à¦à¦‡ সমল পৰিবহণৰ সময়ত অনà§à¦¯ লোকসকলে চাব পাৰিব আৰৠপৃষà§à¦ à¦¾à¦Ÿà§‹à§° কারà§à¦¯à¦•à¦²à¦¾à¦ª সলনি কৰিবলৈ কোনো আকà§à§°à¦®à¦£à¦•à¦¾à§°à§€à§Ÿà§‡ à¦à¦‡ সমল সংশোধন কৰিব পাৰে।</translation>
@@ -2126,6 +2178,7 @@
<translation id="91108059142052966">পà§à§°à¦¶à¦¾à¦¸à¦•à§° নীতিয়ে গোপনীয় সমল দৃশà§à¦¯à¦®à¦¾à¦¨ হৈ থাকোà¦à¦¤à§‡ <ph name="APPLICATION_TITLE" />ৰ সৈতে সà§à¦•à§à§°à§€à¦¨ শà§à¦¬à§‡à§Ÿà¦¾à§° কৰাৰ সà§à¦¬à¦¿à¦§à¦¾à¦Ÿà§‹ অকà§à¦·à¦® কৰে</translation>
<translation id="9114524666733003316">কারà§à¦¡ নিশà§à¦šà¦¿à¦¤ কৰি থকা হৈছে...</translation>
<translation id="9114581008513152754">à¦à¦‡ বà§à§°à¦¾à¦‰à¦œà¦¾à§°à¦Ÿà§‹ কোনো কোমà§à¦ªà¦¾à¦¨à§€ অথবা অনà§à¦¯ পà§à§°à¦¤à¦¿à¦·à§à¦ à¦¾à¦¨à§° দà§à¦¬à¦¾à§°à¦¾ পৰিচালিত। à¦à¦‡ ডিভাইচটোৰ কাৰà§à¦¯à¦•à¦²à¦¾à¦ª Chromeৰ বাহিৰত পৰিচালনা কৰা হৈ থাকিব পাৰে। <ph name="BEGIN_LINK" />অধিক জানক<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">সজীৱ</translation>
<translation id="9119042192571987207">আপল’ড কৰা হৈছে</translation>
<translation id="9128016270925453879">নীতি ল’ড কৰা হৈছে</translation>
<translation id="9128870381267983090">নেটৱৰà§à¦•à¦¤ সংযোগ কৰক</translation>
@@ -2144,6 +2197,7 @@
<translation id="9170848237812810038">&amp;আনডৠকৰক</translation>
<translation id="9171296965991013597">à¦à¦ªà§â€Œà¦Ÿà§‹ বাদ দিবনে?</translation>
<translation id="9173282814238175921">à¦à¦•à¦• নথি/নতà§à¦¨ শà§à¦¬à§€à¦Ÿ</translation>
+<translation id="9173995187295789444">বà§à¦²à§à¦Ÿà§à¦¥ ডিভাইচ সà§à¦•à§‡à¦¨ কৰি থকা হৈছে...</translation>
<translation id="917450738466192189">ছাৰà§à¦­à¦¾à§°à§° পà§à§°à¦®à¦¾à¦£à¦ªà¦¤à§à§° অমানà§à¦¯à¥¤</translation>
<translation id="9174917557437862841">টেব সলনি কৰা বà§à¦Ÿà¦¾à¦®, à¦à¦‡ টেবটো বà§à¦¯à§±à¦¹à¦¾à§° কৰিবলৈ à¦à¦£à§à¦Ÿà¦¾à§° টিপক</translation>
<translation id="9179703756951298733">Chromeৰ ছেটিংসমূহত আপোনাৰ পৰিশোধ আৰৠকà§à§°à§‡à¦¡à¦¿à¦Ÿ কাৰà§à¦¡à§° তথà§à¦¯ পৰিচালনা কৰক</translation>
diff --git a/chromium/components/strings/components_strings_az.xtb b/chromium/components/strings/components_strings_az.xtb
index 708ad1a583d..50273d70b6c 100644
--- a/chromium/components/strings/components_strings_az.xtb
+++ b/chromium/components/strings/components_strings_az.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Qeyd edildiyi halda Chrome kartınızın kopyasını bu cihazda saxlayacaq ki, forma doldurmaq daha sürətli olsun.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> üçün icazə seçin</translation>
<translation id="1113869188872983271">&amp;Yerbəyer etməyi ləğv edin</translation>
+<translation id="1123753900084781868">Canlı Altyazı hazırda əlçatan deyil</translation>
<translation id="1125573121925420732">Veb saytlar təhlükəsizliyi yeniləyərkən xəbərdarlıqlar ümumi ola bilər. Bu tezliklə təkmilləşdirilməlidir.</translation>
<translation id="112840717907525620">Siyasət keşi OK-dir</translation>
<translation id="1130564665089811311">"Səhifəni tərcümə edin" düyməsi, Google Tərcümə ilə bu səhifəni tərcümə etmək üçün Enter düyməsinə basın</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Cihaz adı</translation>
<translation id="124116460088058876">Digər dillər</translation>
<translation id="1243027604378859286">Müəllif:</translation>
+<translation id="1246424317317450637">Qalın</translation>
<translation id="1250759482327835220">Növbəti dəfə daha sürətli ödəniş etmək üçün kartı, adı və faktura ünvanını Google Hesabınızda yadda saxlayın.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sinxronlaşdırıldı)</translation>
<translation id="1256368399071562588">&lt;p&gt;Vebsayta daxil olarkən sayt açılmırsa, əvvəlcə mərhələlərlə bunu həll etməyə çalışın:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Parolunuzu dəyişin</translation>
<translation id="1484290072879560759">Göndəriş Ünvanı seçin</translation>
<translation id="1492194039220927094">Siyasət bildirişləri:</translation>
+<translation id="1495677929897281669">Taba geri qayıdın</translation>
<translation id="1501859676467574491">Google Hesabındakı kartları göstərin</translation>
<translation id="1507202001669085618">&lt;p&gt;Onlayn olmadan öncə giriş tələb edilən Wi-Fi portalından istifadə edirsinizsə, bu xətanı görəcəksiniz.&lt;/p&gt;
&lt;p&gt;Bunu həlle etmək üçün açdığınız səhifədə &lt;strong&gt;Connect&lt;/strong&gt; üzərinə klikləyin.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Bu səhifə deyir:</translation>
<translation id="153384715582417236">İndilik bu qədər</translation>
<translation id="1536390784834419204">Səhifəni tərcümə edin</translation>
+<translation id="1539840569003678498">Şikayət göndərildi:</translation>
<translation id="154408704832528245">Çatdırılma Ünvanı seçin</translation>
<translation id="1549470594296187301">JavaScript bu funksiyanı istifadə etmək üçün aktiv olmalıdır.</translation>
<translation id="155039086686388498">Texniki-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">Qısa kənar əvvəldə</translation>
<translation id="168693727862418163">Bu siyasət dəyəri sxem əsasında doğrulanmadı və nəzərə alınmayacaq.</translation>
<translation id="168841957122794586">Server sertifikatının kriptoqrafik açarı zəifdir.</translation>
+<translation id="1696290444144917273">Virtual kart detallarına baxın</translation>
<translation id="1697532407822776718">Hər şey hazırdır!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Bu server <ph name="DOMAIN" /> olduğunu sübut edə bilmədi; böyük ehtimal təhlükəsizlik sertifikatı sabahdan etibarən nəzərdə tutulub. Buna yanlış konfiqurasiya və ya hücumçu tərəfindən bağlantının ələ keçirilməsi səbəb ola bilər.}other{Bu server <ph name="DOMAIN" /> olduğunu sübut edə bilmədi; təhlükəsizlik sertifikatı gələcəkdə # gündən sonra nəzərdə tutulub. Buna yanlış konfiqurasiya və ya hücumçu tərəfindən bağlantının ələ keçirilməsi səbəb ola bilər.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> <ph name="VALUE" /> olaraq ayarlanmadığına görə nəzərə alınmayıb.</translation>
<translation id="1712552549805331520"><ph name="URL" /> datanı həmişəlik lokal kompüterinizdə yadda saxlamaq istəyir</translation>
<translation id="1713628304598226412">Qab 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Poçt qutusu 3</translation>
<translation id="1718029547804390981">Sənəd annotasiya üçün çox böyükdür</translation>
<translation id="1721424275792716183">* Sahə tələb olunur</translation>
+<translation id="1727613060316725209">Sertifikat etibarlıdır</translation>
<translation id="1727741090716970331">Düzgün Kart NömrÉ™si ÆlavÉ™ edin</translation>
<translation id="1728677426644403582">Veb səhifənin mənbəyinə baxırsınız</translation>
<translation id="173080396488393970">Bu kart növü dəstəklənmir</translation>
@@ -246,7 +253,6 @@
üzrə olan sorğunuzu yerinə yetirməsinə mane olur. Mənbə siyasətlər
təhlükəsizlik və digər xüsusiyyətləri konfiqurasiya etmək üçün sayt operatorları tərəfindən istifadə edilə bilər.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Lütfən, sinxronizasiya parol ifadəsini güncəlləşdirin.</translation>
<translation id="1787142507584202372">Açıq tablarınız burada görünür</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, bir neçə əməliyyat əlçatandır, onları nəzərdən keçirmək üçün Tab düyməsinə basın</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">Reklamlar</translation>
<translation id="1919367280705858090">Spesifik xəta mesajı ilə bağlı yardım əldə edin</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Yoxdur}=1{1 sayt}other{# sayt}}</translation>
+<translation id="1924727005275031552">Yeni</translation>
<translation id="1945968466830820669">Təşkilat hesabına girişi itirə və ya kimlik oğurluğu ilə üzləşə bilərsiniz. Chromium parollarınızı indi dəyişməyi məsləhət görür.</translation>
<translation id="1947454675006758438">Yuxarı sağ tərəfdən ştapel vurun</translation>
<translation id="1958218078413065209">Æn yüksÉ™k xalınız: <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">Qab 7</translation>
<translation id="204357726431741734">Google Hesabınızda saxlanılan parollardan istifadə etmək üçün daxil olun</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> dilindəki səhifələr tərcümə edilməyəcək.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Bu kontrol aktiv olduqda və status "aktiv" olduğu zaman Chrome axtarış fəaliyyətinizin ən çox bənzədiyi çox iştirakçısı olan qrupu, yaxud "kohortu" müəyyən edir. Reklamçılar qrup üçün reklamlar seçə bilər və axtarış fəaliyyətiniz cihazınızda məxfi saxlanılır. Qrupunuz hər gün yenilənir.}=1{Bu kontrol aktiv olduqda və status "aktiv" olduğu zaman Chrome axtarış fəaliyyətinizin ən çox bənzədiyi çox iştirakçısı olan qrupu, yaxud "kohortu" müəyyən edir. Reklamçılar qrup üçün reklamlar seçə bilər və axtarış fəaliyyətiniz cihazınızda məxfi saxlanılır. Qrupunuz hər gün yenilənir.}other{Bu kontrol aktiv olduqda və status "aktiv" olduğu zaman Chrome axtarış fəaliyyətinizin ən çox bənzədiyi çox iştirakçısı olan qrupu, yaxud "kohortu" müəyyən edir. Reklamçılar qrup üçün reklamlar seçə bilər və axtarış fəaliyyətiniz cihazınızda məxfi saxlanılır. Qrupunuz {NUM_DAYS} gündən bir yenilənir.}}</translation>
<translation id="2053553514270667976">Poçt indeksi</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 təklif}other{# təklif}}</translation>
<translation id="2071692954027939183">Bildirişlərə adətən icazə vermədiyinizə görə onlar avtomatik olaraq bloklanıb</translation>
<translation id="2079545284768500474">Geri qaytarın</translation>
<translation id="20817612488360358">Sistem proksi ayarları işlənməyə ayarlanıb, lakin açıq proksi sazlanması da bəlirlənib.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> nəticədən <ph name="RESULT_NUMBER" /></translation>
+<translation id="2085876078937250610">Yadda saxlanılır…</translation>
<translation id="2088086323192747268">"Sinxronlaşdırmanı idarə edin" düyməsi, Chrome ayarlarında sinxronlaşdırdığınız məlumatları idarə etmək üçün Enter düyməsinə basın</translation>
<translation id="2091887806945687916">Səs</translation>
<translation id="2094505752054353250">Domen uyÄŸunsuzluÄŸu</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> istifadəçi adı və parol tələb edir.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" /> tarixindÉ™ bitir</translation>
<translation id="2337852623177822836">Ayara administrator tərəfindən nəzarət edilir</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ütləndirmək istəyir</translation>
<translation id="2344028582131185878">Avtomatik endirmələr</translation>
<translation id="2346319942568447007">Kopyalanmış şəkil</translation>
<translation id="2354001756790975382">Digər əlfəcinlər</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">Hücumçular bu saytda baxdığınız şəkilləri görə bilər və onları deyişdirərək Sizi aldada bilər.</translation>
<translation id="2356070529366658676">SoruÅŸun</translation>
<translation id="2357481397660644965">Cihazı <ph name="DEVICE_MANAGER" />, hesabı isə<ph name="ACCOUNT_MANAGER" /> idarə edir.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Maksimum bir gün ərzində}=1{Bir gün ərzində}other{{NUM_DAYS} gün ərzində}}</translation>
<translation id="2359629602545592467">Çoxsaylı</translation>
<translation id="2359808026110333948">Davam edin</translation>
+<translation id="2359961752320758691">Virtual kart adınız tətbiq edildi.</translation>
<translation id="2367567093518048410">Səviyyə</translation>
<translation id="2372464001869762664">Təsdiqlədikdən sonra Google Hesabınızdakı kart məlumatları bu sayt ilə paylaşılacaq. Plex Hesabı detallarınızda CVC kodunu tapın.</translation>
<translation id="2380886658946992094">Hüquqi</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">Bu göndərmə üsulu əlçatan deyil. Başqa üsul seçin.</translation>
<translation id="2396249848217231973">&amp;Silinməni ləğv edin</translation>
<translation id="2410754574180102685">Hüquqi Hökumət</translation>
+<translation id="2413155254802890957">Köhnə</translation>
<translation id="2413528052993050574">Bu server <ph name="DOMAIN" /> domenini təsdiqləyə bilmir; təhlükəsizlik sertifikatı ləğv edilə bilər. Buna yanlış konfiqurasiya və ya hücumçu tərəfindən bağlantının ələ keçirilməsi səbəb ola bilər.</translation>
<translation id="2414886740292270097">Qara</translation>
<translation id="2438874542388153331">Sağdan dördlü deşik açın</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">Aşağı sağdan ştapel vurun</translation>
<translation id="2523886232349826891">Yalnız bu cihaz yadda saxlanıldı</translation>
<translation id="2524461107774643265">Ætraflı MÉ™lumat ÆlavÉ™ Edin</translation>
-<translation id="2526590354069164005">Masaüstü</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{vÉ™ daha 1}other{and daha #}}</translation>
<translation id="2536110899380797252">Ãœnvan ÆlavÉ™ Edin</translation>
<translation id="2539524384386349900">Aşkarlayın</translation>
+<translation id="2541219929084442027">Bütün Anonim tabları bağladıqdan sonra Anonim rejimdə baxdığınız səhifələr brauzerinizin tarixçəsində, kuki yaddaşında və ya axtarış tarixçəsində saxlanılmayacaq. Endirdiyiniz və ya əlfəcin yaratdığınız fayllar isə saxlanılacaq.</translation>
<translation id="2544644783021658368">Tək sənəd</translation>
<translation id="254947805923345898">Siyasət dəyəri düzgün deyil.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> yalnış cavab göndərdi.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Chrome'un ən yüksək təhlükəsizlik səviyyəsini əldə etmək üçün<ph name="BEGIN_ENHANCED_PROTECTION_LINK" />genişləndirilmiş qorumanı aktiv edin<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> serverinin IP ünvanı tapılmadı.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Uyğun cihaz tapılmadı.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Tab düyməsi, sonra Enter düyməsinə basaraq Chrome ayarlarında baxış tarixçəsi, kukilər, keş və daha çoxunu təmizləyin</translation>
<translation id="2650446666397867134">Fayla giriş rədd edildi</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">Yenidən başladın</translation>
<translation id="2803306138276472711">Google Güvənlik Baxış <ph name="SITE" /> saytında <ph name="BEGIN_LINK" />zərərli proqram aşkar etdi<ph name="END_LINK" />. Adətən güvənli olan veb saytlar bəzən zərərli proqramlar ilə yoluxur.</translation>
<translation id="2807052079800581569">Şəklin Y oxu üzrə mövqeyi</translation>
+<translation id="2820957248982571256">Skan edilir...</translation>
<translation id="2824775600643448204">Ünvan və axtarış paneli</translation>
<translation id="2826760142808435982">Bağlantı şifrələnib və <ph name="CIPHER" /> işlədərək doğrulanıb və açar mübadiləsi olaraq <ph name="KX" /> işlədir.</translation>
<translation id="2835170189407361413">Formanı təmizləyin</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Dəvət edin (Zərf)</translation>
<translation id="2856444702002559011">Hücumçular <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> saytından mÉ™lumat (mÉ™sÉ™lÉ™n, parol, mesaj vÉ™ ya kredit kartları) oÄŸurlamaÄŸa çalışa bilÉ™rlÉ™r. <ph name="BEGIN_LEARN_MORE_LINK" />Ætraflı mÉ™lumat<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Bu sayt inadçı və ya aldadıcı reklamlar göstərir.</translation>
+<translation id="287596039013813457">Dost</translation>
+<translation id="2876489322757410363">Xarici tətbiqlə ödəniş etmək üçün Anonim rejimdən çıxırsınız. Davam edilsin?</translation>
<translation id="2878197950673342043">Poster formasında qatlayın</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Pəncərənin yerləşdirilməsi</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (Zərf)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Tab düyməsi, sonra Enter düyməsinə basaraq Chrome ayarlarında Təhlükəsizlik Yoxlanışını icra edin</translation>
<translation id="3061707000357573562">Təmir Xidməti</translation>
-<translation id="3064966200440839136">Xarici tətbiqlə ödəniş etmək üçün gizli rejimdən çıxırsınız. Davam edilsin?</translation>
<translation id="306573536155379004">Oyun başladı.</translation>
<translation id="3080254622891793721">Qrafik</translation>
<translation id="3086579638707268289">Vebdəki fəaliyyətinizə nəzarət edilir</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">Hesabınızı <ph name="MANAGER" /> idarə edir.</translation>
<translation id="3157931365184549694">Bərpa edin</translation>
<translation id="3162559335345991374">İstifadə etdiyiniz Wi-Fi login səhifəsinə daxil olmağınızı tələb edə bilər.</translation>
-<translation id="3167968892399408617">Bütün gizlik panelləri bağladıqdan sonra gizli rejimdə baxdığınız səhifələr brauzerinizin tarixçəsində, kuki yaddaşında və ya axtarış tarixçəsində saxlanılmayacaq. Endirdiyiniz və ya əlfəcin yaratdığınız fayllar isə saxlanılacaq.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ada</translation>
<translation id="3176929007561373547">Proksi serverin işləməsinə əmin olmaq üçün proksi ayarlarınızı yoxlayın və ya şəbəkə administratorunuzla əlaqə saxlayın. Proksi server işlətməli olduğunuza inanmırsınızsa:
@@ -597,10 +612,12 @@
<translation id="3229041911291329567">Cihaz və brauzer haqqında versiya məlumatı</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> üçün CVC kodu daxil edin</translation>
<translation id="3234666976984236645">Bu saytda həmişə önəmli məzmunu aşkarlayın</translation>
+<translation id="3249845759089040423">Modern</translation>
<translation id="3252266817569339921">Fransız</translation>
<translation id="3266793032086590337">Dəyər (zidd)</translation>
<translation id="3268451620468152448">Panelləri Açın</translation>
<translation id="3270847123878663523">Təkrar sıralamanı geri qaytarın</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> qoşulmaq istəyir</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Təşkilatınız <ph name="ENROLLMENT_DOMAIN" /> aşağıdakı veb saytlara ayarlar və ya siyasətlər kimi bəzi məlumatlar göndərib.</translation>
<translation id="3282497668470633863">Kart üzərindəki adı daxil edin</translation>
@@ -653,6 +670,7 @@
<translation id="3428151540071562330">Bir və ya bir neçə DnsOverHttpsTemplates server şablonu URI'si yanlışdır və istifadə edilməyəcək.</translation>
<translation id="3431636764301398940">Bu kartı bu cihaza yazın</translation>
<translation id="3432601291244612633">Səhifəni bağlayın</translation>
+<translation id="3435738964857648380">Təhlükəsizlik</translation>
<translation id="3435896845095436175">Aktivləşdirin</translation>
<translation id="3438829137925142401">Google Hesabınızda saxlanılan parollardan istifadə edin</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -694,7 +712,10 @@
<translation id="3584299510153766161">Altdan qoşa deşik açın</translation>
<translation id="3586931643579894722">Detalları gizlədin</translation>
<translation id="3587738293690942763">Orta</translation>
+<translation id="3590643883886679995">Anonim rejimdən çıxdıqdan sonra giriş datası bu cihazda saxlanılacaq.</translation>
+<translation id="359126217934908072">Ay/Ä°l:</translation>
<translation id="3592413004129370115">İtalyan (Zərf)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Qrupunuzu istənilən vaxt sıfırlaya bilərsiniz. Yeni bir qrupa qoşulmaq təxminən bir gün çəkir.}=1{Qrupunuzu istənilən vaxt sıfırlaya bilərsiniz. Yeni bir qrupa qoşulmaq təxminən bir gün çəkir.}other{Qrupunuzu istənilən vaxt sıfırlaya bilərsiniz. Yeni bir qrupa qoşulmaq təxminən {NUM_DAYS} gün çəkir.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Tətbiq admin tərəfindən bloklanıb</translation>
<translation id="3608932978122581043">İstiqaməti tənzimləyin</translation>
@@ -703,12 +724,12 @@
<translation id="3615877443314183785">Düzgün bitmə tarixi daxil edin</translation>
<translation id="36224234498066874">Axtarış Datasını Silin...</translation>
<translation id="362276910939193118">Tam tarixçəni göstərin</translation>
-<translation id="3625635938337243871">Anonim rejimdən çıxdıqdan sonra giriş datası bu cihazda saxlanılacaq.</translation>
<translation id="3630155396527302611">Şəbəkəyə girmək icazəsi olan proqram olaraq siyahılanıb, onu siyahıdan silin və yenidən əlavə edin.</translation>
<translation id="3630699740441428070">Bu cihazın administratorları onların şəbəkə trafiki, o cümlədən daxil olduğunuz veb saytlara baxmasına imkan verə biləcək şəbəkə bağlantısı konfiqurasiya edib.</translation>
<translation id="3631244953324577188">Biometriklər</translation>
<translation id="3633738897356909127">"Chrome'u güncəlləyin" düyməsi, Chrome ayarlarında Chrome'u güncəlləmək üçün Enter düyməsinə basın</translation>
<translation id="3634530185120165534">Qab 5</translation>
+<translation id="3637662659967048211">Google Hesabında saxlayın</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Tətbiq:</translation>
<translation id="3650584904733503804">Yoxlama uÄŸurludur</translation>
@@ -749,6 +770,7 @@
<translation id="3781428340399460090">Parlaq Çəhrayı</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth cihazları</translation>
+<translation id="3787675388804467730">Virtual kart nömrəsi</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> tarixindÉ™ bitir</translation>
<translation id="3789155188480882154">Ölçü 16</translation>
<translation id="3789841737615482174">Quraşdırın</translation>
@@ -768,6 +790,7 @@
<translation id="3841184659773414994">Fayl İdarəçiləri</translation>
<translation id="385051799172605136">Geri</translation>
<translation id="3858027520442213535">Tarix və saatı güncəlləşdirin</translation>
+<translation id="3881478300875776315">Daha az sətir göstərin</translation>
<translation id="3884278016824448484">Ziddiyyətli cihaz identifikatoru</translation>
<translation id="3885155851504623709">KilsÉ™</translation>
<translation id="388632593194507180">Nəzarət Aşkarlanıb</translation>
@@ -793,6 +816,7 @@
<translation id="397105322502079400">Hesablanır...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> blok edilib</translation>
<translation id="3973357910713125165">Chrome Təhlükəsizlik Yoxlanışını İcra Edin düyməsi, Chrome ayarlarında Təhlükəsizlik Yoxlanışını icra etmək üçün Enter düyməsinə basın</translation>
+<translation id="3986705137476756801">Canlı Subtitri hələlik deaktiv edin</translation>
<translation id="3987405730340719549">Chrome bu saytın saxta və ya fırıldaqçı ola biləcəyini təyin etmişdir.
Bunun səhvən göstərildiyini düşünürsünüzsə, bu ünvana baş çəkin: https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -888,13 +912,14 @@
<translation id="4275830172053184480">Cihazınızı yenidən başladın</translation>
<translation id="4277028893293644418">Parolu sıfırlayın</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Bu kart Google Hesabında yadda saxlanılıb}other{Bu kartlar Google Hesabında yadda saxlanılıb}}</translation>
+<translation id="4287885627794386150">Sınaq üçün uyğundur, lakin aktiv deyil</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> səhifəsi üçün miniatür</translation>
<translation id="42981349822642051">Genişləndirin</translation>
<translation id="4300675098767811073">Sağdan çoxsaylı deşik açın</translation>
<translation id="4302514097724775343">Oxutmaq üçün dinozavra toxunun</translation>
<translation id="4302965934281694568">Chou3 (Zərf)</translation>
<translation id="4305666528087210886">Faylınıza giriş mümkün olmadı</translation>
-<translation id="4305817255990598646">Dəyişin</translation>
+<translation id="4306529830550717874">Ünvan saxlanılsın?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blok edin (defolt)</translation>
<translation id="4314815835985389558">Sinxronizasiyanı idarə edin</translation>
@@ -921,6 +946,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" /> domeninə daxil olmağa çalışdınız, onun sertifikatı geri alınıb. Bu o deməkdir ki, güvənlik kredensiallarına kəsinliklə inanmaq olmaz. Ola bilər ki, hücumçu ilə əlaqəyə girirsiniz.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Xətlər</translation>
+<translation id="4406883609789734330">Avtomatik subtitrlər</translation>
<translation id="4406896451731180161">axtarış nəticələri</translation>
<translation id="4408413947728134509">Kukilər <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">İndicə parolunuzu aldadıcı saytda daxil etdiniz. Chrome indi <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> və bu parolu istifadə etdiyiniz digər saytlara keçərək parolunuzu dəyişmənizi tövsiyə edir.</translation>
@@ -933,7 +959,6 @@
<translation id="4435702339979719576">Postkart)</translation>
<translation id="443673843213245140">Proksi istifadəsi deaktiv edilib, amma ətraflı proksi konfiqurasiyası müəyyən edilib.</translation>
<translation id="4464826014807964867">Təşkilatınızın məlumatları olan veb saytlar</translation>
-<translation id="4466881336512663640">Formaya edilmiş dəyişikliklər silinəcək. Davam etmək istədiyinizə əminsiniz?</translation>
<translation id="4476953670630786061">Bu forma güvənli deyil. Avto doldurma deaktiv edilib.</translation>
<translation id="4477350412780666475">Növbəti trek</translation>
<translation id="4482953324121162758">Bu sayt tərcümə edilməyəcək.</translation>
@@ -967,6 +992,7 @@
<translation id="4594403342090139922">&amp;Silinməni ləğv edin</translation>
<translation id="4597348597567598915">Ölçü 8</translation>
<translation id="4600854749408232102">C6/C5 (Zərf)</translation>
+<translation id="4606870351894164739">Təsirli</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Keşbek əlaqələndirilib</translation>
<translation id="4636930964841734540">Ä°nfo</translation>
@@ -986,6 +1012,7 @@
<translation id="4691835149146451662">Arxitektura-A (Zərf)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Tərəf</translation>
+<translation id="4702656508969495934">Canlı Altyazı görünür, fokuslanmaq üçün pəncərə dəyişdiricisindən istifadə edin</translation>
<translation id="4708268264240856090">Bağlantınız kəsildi</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows Şəbəkə Diaqnostikası İşləyir<ph name="END_LINK" /></translation>
@@ -999,6 +1026,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> axtarış təklifi</translation>
<translation id="4742407542027196863">Parolları idarə edin...</translation>
<translation id="4744603770635761495">Ä°cra olunan yol</translation>
+<translation id="4749011317274908093">Anonim rejimə keçdiniz</translation>
<translation id="4750917950439032686">Bu saytda göndərildiyi zaman məlumatınız (məsələn, parol və ya kredit kartı nömrəsi) gizli saxlanır.</translation>
<translation id="4756388243121344051">&amp;Tarixçə</translation>
<translation id="4758311279753947758">Kontakt məlumatı əlavə edin</translation>
@@ -1028,6 +1056,8 @@
<translation id="4813512666221746211">Şəbəkə xətası</translation>
<translation id="4816492930507672669">Səhifəyə uyğunlaşsın</translation>
<translation id="4819347708020428563">Annotasiyalar defolt görünüşdə redaktə edilsin?</translation>
+<translation id="4825507807291741242">Güclü</translation>
+<translation id="4838327282952368871">Xəyali</translation>
<translation id="484462545196658690">Avtomatik</translation>
<translation id="4850886885716139402">Görünüş</translation>
<translation id="485316830061041779">Alman</translation>
@@ -1164,6 +1194,7 @@
<translation id="5314967030527622926">Buklet düzəldən</translation>
<translation id="5316812925700871227">Saat əqrəbinin əksi istiqamətində fırladın</translation>
<translation id="5317780077021120954">Yadda saxlayın</translation>
+<translation id="5321288445143113935">Böyüdülüb</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" />/<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Kontakt Məlumatı seçin</translation>
<translation id="5327248766486351172">Ad</translation>
@@ -1171,11 +1202,13 @@
<translation id="5332219387342487447">Göndəriş Üsulu</translation>
<translation id="5333022057423422993">Chrome indicə istifadə etdiyiniz parolu bir data pozuntusunda tapıb. Hesablarınızı qorumaq üçün yadda saxlanmış parollarınızı yoxlamağınızı tövsiyə edirik.</translation>
<translation id="5334013548165032829">Ætraflı sistem qeydlÉ™ri</translation>
+<translation id="5334145288572353250">Ünvan saxlanılsın?</translation>
<translation id="5340250774223869109">Tətbiq bloklanıb</translation>
<translation id="534295439873310000">NFC cihazları</translation>
<translation id="5344579389779391559">Bu səhifədə Sizdən ödəniş tutula bilər</translation>
<translation id="5355557959165512791">Hazırda <ph name="SITE" /> saytına daxil olmaq mümkün deyil, çünki onun sertifikatı silinib. Şəbəkə xətaları və hücumları adətən müvəqqəti olur, beləliklə, səhifə yəqin ki daha sonra işləyəcək.</translation>
<translation id="536296301121032821">Siyasət ayarlarını saxlamaq uğursuz oldu</translation>
+<translation id="5363309033720083897">Administratorunuz tərəfindən icazə verilən ardıcıl port</translation>
<translation id="5371425731340848620">Kartı yeniləyin</translation>
<translation id="5377026284221673050">"Saatınız geridədir" və ya "Saatınız qabaqdadır" və ya "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
<translation id="5386426401304769735">Bu saytın sertifikat zənciri SHA-1 istifadə edərək imzalanmış sertifikatdan ibarətdir.</translation>
@@ -1184,6 +1217,7 @@
<translation id="5398772614898833570">Reklamlar blok edildi</translation>
<translation id="5400836586163650660">Boz</translation>
<translation id="540969355065856584">Bu server <ph name="DOMAIN" /> domenini təsdiqləyə bilmir; güvənlik sertifikatı hazırda etibarlı deyil. Buna yanlış konfiqurasiya və ya hücumçu tərəfindən bağlantının ələ keçirilməsi səbəb ola bilər.</translation>
+<translation id="541143247543991491">Bulud (sistem)</translation>
<translation id="541416427766103491">Yığıcı 4</translation>
<translation id="5421136146218899937">Baxış datasını silin...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> Sizə bildiriş göndərmək istəyir</translation>
@@ -1197,6 +1231,7 @@
<translation id="5455374756549232013">Uğursuz qaydalar zaman ştampı</translation>
<translation id="5457113250005438886">Yanlış</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> vÉ™ daha <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> vÉ™ daha <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
+<translation id="5463625433003343978">Cihazlar axtarılır...</translation>
<translation id="5469868506864199649">Ä°talyan</translation>
<translation id="5470861586879999274">&amp;Düzəlişi yenidən edin</translation>
<translation id="5478437291406423475">B6/C4 (Zərf)</translation>
@@ -1246,7 +1281,6 @@
<translation id="5624120631404540903">Parolları idarə edin</translation>
<translation id="5629630648637658800">Siyasət ayarlarını yükləmək uğursuz oldu</translation>
<translation id="5631439013527180824">Yanlış cihaz idarəetmə markeri</translation>
-<translation id="5632627355679805402">Data <ph name="TIME" /> tarixindən etibarən <ph name="BEGIN_LINK" />Google parolu<ph name="END_LINK" /> ilə şifrələnib. Sinxronizasiyanı başlatmaq üçün daxil edin.</translation>
<translation id="5633066919399395251">Hazırda <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> saytındakı hücumçular kompüterdÉ™ki mÉ™lumatları (mÉ™sÉ™lÉ™n, foto, parol, mesaj vÉ™ kredit kartları) oÄŸurlayan vÉ™ ya silÉ™n zÉ™rÉ™rli proqramlar quraÅŸdırmaÄŸa cÉ™hd edÉ™ bilÉ™r. <ph name="BEGIN_LEARN_MORE_LINK" />Ætraflı mÉ™lumat<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Aldadıcı kontent blok edildi.</translation>
<translation id="5644090287519800334">Şəklin 1-ci tərəfinin X oxu üzrə yerdəyişməsi</translation>
@@ -1285,12 +1319,12 @@
<translation id="5785756445106461925">Bundan əlavə, bu səhifəyə təhlükəsiz olmayan başqa resurslar daxildir. Bu resurslar keçid zamanı başqaları tərəfindən görüntülən bilər və hücumçu tərəfindən səhifə görünüşünün dəyişdirilməsi üçün modifikasiya edilə bilər.</translation>
<translation id="5786044859038896871">Kart məlumatlarını doldurmaq istəyirsiniz?</translation>
<translation id="578633867165174378">Chrome indicə istifadə etdiyiniz parolu bir data pozuntusunda tapıb. Bu parolu indi dəyişdirmənizi tövsiyə edirik.</translation>
-<translation id="5798290721819630480">Dəyişikliklər ləğv edilsin?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" /> doldurmaq istəyirsiniz?</translation>
<translation id="5804241973901381774">İcazələr</translation>
<translation id="5804427196348435412">NFC cihazlarını istifadə edin</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> domeninə bağlantınız köhnə şifrə paketi ilə şifrələnib.</translation>
<translation id="5813119285467412249">Yenidən əlavə edin</translation>
+<translation id="5817918615728894473">QoÅŸulsun</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ÖdÉ™niÅŸ etdiyiniz zaman bu kartdan mÉ™bləğ tutulacaq, ancaq onun É™sl nömrÉ™si bu saytla paylaşılmayacaq. ÆlavÉ™ tÉ™hlükÉ™sizlik üçün müvÉ™qqÉ™ti CVC yaradılacaq.}other{ÖdÉ™niÅŸ etdiyiniz zaman seçdiyiniz kartdan mÉ™bləğ tutulacaq, ancaq onun É™sl nömrÉ™si bu saytla paylaşılmayacaq. ÆlavÉ™ tÉ™hlükÉ™sizlik üçün müvÉ™qqÉ™ti CVC yaradılacaq.}}</translation>
<translation id="5826507051599432481">Ümumi Adı (CN)</translation>
<translation id="5838278095973806738">Bu saytda hər hansı həssəs məlumatı (məsələn, parollar və kredit kartları) yerləşdirməməlisiniz, cünki, hücumçular tərəfindən oğurlana bilər.</translation>
@@ -1298,6 +1332,7 @@
<translation id="5855253129151731373">Bu saytın host adı <ph name="LOOKALIKE_DOMAIN" /> ilə oxşar görünür. Hücum edənlər bəzən domen adına kiçik, çətin sezilə bilən dəyişikliklər etməklə saytları təqlid edir.
Bunun səhvən göstərildiyini düşünürsünüzsə, bu ünvana baş çəkin: https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Deaktiv</translation>
<translation id="5862579898803147654">Yığıcı 8</translation>
<translation id="5863847714970149516">Növbəti səhifədə Sizdən ödəniş tutula bilər</translation>
<translation id="5866257070973731571">Telefon NömrÉ™si ÆlavÉ™ Edin</translation>
@@ -1314,6 +1349,7 @@
<translation id="5913377024445952699">Ekranın çəkilməsinə pauza verildi</translation>
<translation id="59174027418879706">Aktiv edilib</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 istifadÉ™ edilir}other{# istifadÉ™ edilir}}</translation>
<translation id="5921185718311485855">Aktiv</translation>
<translation id="5921639886840618607">Kart Google Hesabında yadda saxlanılsın?</translation>
<translation id="5922853866070715753">Demək olar ki, hazırdır</translation>
@@ -1333,6 +1369,7 @@
<translation id="5989320800837274978">Proksi serverlər və .pac skript URL-i göstərilməyib.</translation>
<translation id="5992691462791905444">Mühəndislikdə Z-qatlama</translation>
<translation id="6000758707621254961">"<ph name="SEARCH_TEXT" />" üçün <ph name="RESULT_COUNT" /> nəticə</translation>
+<translation id="6006484371116297560">Klassik</translation>
<translation id="6008122969617370890">N-1 sırası</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Parolları yoxlayın</translation>
@@ -1354,6 +1391,7 @@
<translation id="6045164183059402045">Tətbiq şablonu</translation>
<translation id="6047233362582046994">Təhlükəsizliklə bağlı riskləri başa düşürsünüzsə, zərərli tətbiqlər silinmədən əvvəl <ph name="BEGIN_LINK" />bu sayta daxil ola<ph name="END_LINK" /> bilərsiniz.</translation>
<translation id="6047927260846328439">Bu kontent Sizi proqram təminatı quraşdırmaq və ya şəxsi məlumatı aşkar etmək üçün aldatmağa cəhd edə bilər. <ph name="BEGIN_LINK" />Hər bir halda göstərin<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Tam ekrandan çıxmaq üçün |<ph name="ACCELERATOR" />| düyməsinə basıb saxlayın</translation>
<translation id="6049488691372270142">Səhifə çatdırılması</translation>
<translation id="6051221802930200923">Hazırda <ph name="SITE" /> saytına daxil olmaq mümkün deyil, çünki veb səhifə sertifikat bağlantısı istifadə edir. Şəbəkə xətaları və hücumları adətən müvəqqəti olur, beləliklə, səhifə yəqin ki daha sonra işləyəcək.</translation>
<translation id="6051898664905071243">Səhifə sayı:</translation>
@@ -1370,6 +1408,7 @@
<translation id="610911394827799129"><ph name="BEGIN_LINK" />history.google.com<ph name="END_LINK" /> linkində Google Hesabına məxsus axtarış tarixçəsinin başqa formaları ola bilər</translation>
<translation id="6116338172782435947">Buferə kopyalanan mətn və şəkillərə baxın</translation>
<translation id="6120179357481664955">UPI ID'niz yadda saxlansın?</translation>
+<translation id="6123290840358279103">Virtual karta baxın</translation>
<translation id="6124432979022149706">Chrome Enterprise Birləşdiriciləri</translation>
<translation id="6146055958333702838">Kabelləri yoxlayın və istifadə edəcəyiniz hər hansı router, modem və ya digər
şəbəkə cihazlarını yenidən yükləyin.</translation>
@@ -1406,6 +1445,7 @@
<translation id="6289939620939689042">Səhifə Rəngi</translation>
<translation id="6290238015253830360">Təklif edilən məqalələriniz burada görünür</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google Assistent Chrome'da dayanmağa başlayır</translation>
<translation id="6305205051461490394"><ph name="URL" /> əlçatmazdır.</translation>
<translation id="6312113039770857350">Veb səhifə əlçatan deyil</translation>
@@ -1431,6 +1471,7 @@
<translation id="6390200185239044127">Yarımçıq Z-qatlama</translation>
<translation id="6390662030813198813">Texniki-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> mənbəyindən bu məkana əlavə etmək administrator siyasətinə əsasən bloklanıb</translation>
+<translation id="6398765197997659313">Tam ekrandan çıxın</translation>
<translation id="6401136357288658127">Bu siyasÉ™t ləğv edilib. ÆvÉ™zinÉ™ <ph name="NEW_POLICY" /> siyasÉ™tindÉ™n istifadÉ™ edin.</translation>
<translation id="6404511346730675251">ÆlfÉ™cinÉ™ düzÉ™liÅŸ edin</translation>
<translation id="6406765186087300643">C0 (Zərf)</translation>
@@ -1443,7 +1484,6 @@
<translation id="6428450836711225518">Telefon nömrənizi doğrulayın</translation>
<translation id="6433490469411711332">Kontakt məlumatını redaktə edin</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> qoşulmaq istəmədi.</translation>
-<translation id="6434309073475700221">Ləğv edin</translation>
<translation id="6440503408713884761">İqnor edilənlər</translation>
<translation id="6443406338865242315">Quraşdırdığınız artırmalar və qoşmalar</translation>
<translation id="6446163441502663861">Kahu (Zərf)</translation>
@@ -1486,6 +1526,7 @@
<translation id="6624427990725312378">Kontakt Məlumatı</translation>
<translation id="6626291197371920147">Düzgün kart nömrəsi əlavə edin</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> axtarışı</translation>
+<translation id="6630043285902923878">USB cihazları axtarılır...</translation>
<translation id="6630809736994426279">Hazırda <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> saytındakı hücumçular Mac cihazındakı mÉ™lumatları (mÉ™sÉ™lÉ™n, foto, parol, mesaj vÉ™ kredit kartları) oÄŸurlayan vÉ™ ya silÉ™n tÉ™hlükÉ™li proqramlar quraÅŸdırmaÄŸa cÉ™hd edÉ™ bilÉ™r. <ph name="BEGIN_LEARN_MORE_LINK" />Ætraflı mÉ™lumat<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Silin</translation>
@@ -1501,6 +1542,7 @@
<translation id="6671697161687535275">Təkliflər Chromium'dan silinsin?</translation>
<translation id="6685834062052613830">Çıxın və quraşdırmanı tamamlayın</translation>
<translation id="6687335167692595844">Şrift ölçüsü üzrə sorğu göndərildi</translation>
+<translation id="6688743156324860098">Güncəlləmə…</translation>
<translation id="6689249931105087298">Qara nöqtə sıxılması ilə nisbi</translation>
<translation id="6689271823431384964">Daxil olduğunuza görə Chrome kartları Google Hesabında yadda saxlamağı təklif edir. Bunu ayarlarda dəyişə bilərsiniz. Kart sahibinin adı hesabınızdan götürülüb.</translation>
<translation id="6698381487523150993">Yaradılıb:</translation>
@@ -1516,6 +1558,7 @@
<translation id="6744009308914054259">Bağlantı gözlənilərkən oflayn məqalələri oxumaq üçün Endirilənlərə baxa bilərsiniz.</translation>
<translation id="6753269504797312559">Siyasət dəyəri</translation>
<translation id="6757797048963528358">Cihazınız yatmağa getdi.</translation>
+<translation id="6767985426384634228">Ünvan yenilənsin?</translation>
<translation id="6768213884286397650">Hagaki (Postkart)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Tünd-bənövşəyi</translation>
@@ -1538,6 +1581,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome bu səhifənin daha rahat oxunması üçün onu sadələşdirib. Chrome güvənsiz bağlantı üzərindən ilkin səhifəni açdı.</translation>
<translation id="6891596781022320156">Qayda səviyyəsi dəstəklənmir.</translation>
+<translation id="6895143722905299846">Virtual nömrə:</translation>
<translation id="6895330447102777224">Kartınız təsdiqləndi</translation>
<translation id="6897140037006041989">İstifadəçi Agent</translation>
<translation id="6898699227549475383">Təşkilat (T)</translation>
@@ -1573,10 +1617,10 @@
<translation id="7004583254764674281">Kartları daha sürətli təsdiqləmək üçün Windows Hello istifadə edin</translation>
<translation id="7006930604109697472">İstənilən halda göndərin</translation>
<translation id="7012363358306927923">Çin UnionPay</translation>
-<translation id="7012404007611495949">Yenidən ölçüləndirmə ayarları</translation>
<translation id="7014741021609395734">Miqyas səviyyəsi</translation>
<translation id="7016992613359344582">Bu ödənişlər birdəfəlik və ya təkrarlanan ola bilər. Onlar, eyni zamanda görünməyə bilər.</translation>
<translation id="7029809446516969842">Parollar</translation>
+<translation id="7030436163253143341">Sertifikat etibarlı deyil</translation>
<translation id="7031646650991750659">Quraşdırdığınız Google Play tətbiqləri</translation>
<translation id="7050187094878475250"><ph name="DOMAIN" /> domeninə girmək istədiniz, lakin server etibarlıq müddəti güvənmək üçün həddən uzun olan sertifikat təqdim edib.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Hazırda bu kartı yadda saxlamaq mümkün deyil}other{Hazırda bu kartları yadda saxlamaq mümkün deyil}}</translation>
@@ -1646,12 +1690,14 @@
<translation id="7300012071106347854">Kobalt Mavisi</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Yüksək</translation>
+<translation id="7305756307268530424">Daha asta sürəti başladın</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Bağlantı Yardımı</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" bölməsini gizlədin</translation>
<translation id="733354035281974745">Cihazın lokal hesabı əvəz edilib</translation>
<translation id="7333654844024768166">İndicə parolunuzu aldadıcı saytda daxil etdiniz. Chromium indi <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> və bu parolu istifadə etdiyiniz digər saytlara keçərək parolunuzu dəyişmənizi tövsiyə edir.</translation>
<translation id="7334320624316649418">&amp;Yenidən yerbəyer edin</translation>
+<translation id="7337248890521463931">Daha çox sətir göstərin</translation>
<translation id="7337706099755338005">Platformanızda əlçatan deyil.</translation>
<translation id="733923710415886693">Serverin sertifikatı Sertifikat Şəffaflığı vasitəsi ilə aşkarlanmayıb.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1659,6 +1705,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Æmr sahÉ™si</translation>
<translation id="7359588939039777303">Reklamlar blok edildi.</translation>
+<translation id="7363096869660964304">Siz görünməz olmursunuz. Anonim rejim brauzeri şirkətinizdən, internet xidməti provayderi və ya daxil olduğunuz veb saytdan gizlətmir.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ayarlarında ünvanlar əlavə etmək və idarə etmək üçün Tab, sonra Enter düyməsinə basın</translation>
<translation id="7365849542400970216">Cihazdan istifadəniz bilinsin?</translation>
<translation id="7372973238305370288">axtarış nəticəsi</translation>
@@ -1669,7 +1716,9 @@
<translation id="7378594059915113390">Media Nəzarətləri</translation>
<translation id="7378627244592794276">Xeyr</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Tətbiq olunmur</translation>
<translation id="7390545607259442187">Kartı Təsdiqləyin</translation>
+<translation id="7392089738299859607">Ünvanı yeniləyin</translation>
<translation id="7399802613464275309">Təhlükəsizlik Yoxlanışı</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> idarÉ™ edilir</translation>
@@ -1684,6 +1733,7 @@
&lt;li&gt;Kompüterdən proqramı birdəfəlik silmək haqqında məlumat üçün &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome help center&lt;/a&gt; ünvanına daxil olun
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Geniş Formatlı</translation>
+<translation id="7410471291937727359">Sevimli</translation>
<translation id="7416351320495623771">Parolları İdarə edin...</translation>
<translation id="7419106976560586862">Profil yolu</translation>
<translation id="7437289804838430631">Kontakt MÉ™lumatı ÆlavÉ™ Edin</translation>
@@ -1699,7 +1749,7 @@
<translation id="7481312909269577407">İrəli</translation>
<translation id="7485870689360869515">Heç bir data tapılmadı.</translation>
<translation id="7495528107193238112">Bu məzmun bloklanıb. Problemi düzəltmək üçün sayt sahibi ilə əlaqə saxlayın.</translation>
-<translation id="7498234416455752244">Düzəlişə davam edin</translation>
+<translation id="7498193950643227031">Ölçüsü dəyişdirildiyi təqdirdə gözlənilmədən hərəkət edə bilər. İndi <ph name="SETTINGS" /> bölməsində tətbiqlərin ölçüsünü dəyişdirmək imkanını məhdudlaşdıra bilərsiniz.</translation>
<translation id="7503664977220660814">İndicə parolunuzu aldadıcı saytda daxil etdiniz. Chromium <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> saytlarında və bu paroldan istifadə etdiyiniz digər saytlarda saxlanılmış parollarınızı indi yoxlamağı tövsiyə edir.</translation>
<translation id="7508255263130623398">Qaytarılmış qaydalar cihaz İD'si boşdur və ya cari cihaz İD'si ilə üst-üstə düşmür</translation>
<translation id="7508870219247277067">Avokado Yaşılı</translation>
@@ -1719,6 +1769,7 @@
<translation id="7548892272833184391">Bağlantı xətalarını həll edin</translation>
<translation id="7549584377607005141">Bu veb səhifə düzgün görüntülənmək üçün əvvəlcə daxil etdiyiniz datanı tələb edir. Bu datanı yenidən göndərə bilərsiniz, amma bununla, bu səhifənin əvvəllər etdiyi əməliyyatı təkrarlamış olacaqsınız.</translation>
<translation id="7550637293666041147">Cihazın istifadəçi adı və Chrome istifadəçi adı</translation>
+<translation id="755279583747225797">Sınaq aktivdir</translation>
<translation id="7552846755917812628">Aşağıdakı məsləhətləri sınayın:</translation>
<translation id="7554475479213504905">İstənilən halda yenidən yükləyin və göstərin</translation>
<translation id="7554791636758816595">Yeni Panel</translation>
@@ -1737,7 +1788,6 @@
<translation id="7610193165460212391">Dəyər <ph name="VALUE" /> aralığından kənardır.</translation>
<translation id="7613889955535752492">BitmÉ™ tarixi: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Tab düyməsi, sonra Enter düyməsinə basaraq Chrome ayarlarında parollarınıza baxın və idarə edin</translation>
-<translation id="7615602087246926389">Google Hesab parolunuzun fərqli versiyasını istifadə edərək şifrələnən data artıq varınızdır. Onu aşağıda daxil edin.</translation>
<translation id="7616645509853975347">Administratorunuz brauzerinizdə Chrome Enterprise Connectors funksiyasını aktivləşdirib. Bu birləşdiricilərin verilənlərinizdən bəzilərinə giriş imkanı var.</translation>
<translation id="7619838219691048931">Son vərəq</translation>
<translation id="762844065391966283">Bir-bir</translation>
@@ -1802,13 +1852,12 @@
<translation id="782886543891417279">İstifadə etdiyiniz Wi-Fi (<ph name="WIFI_NAME" />) Sizdən login səhifəsinə daxil olmağınızı tələb edə bilər.</translation>
<translation id="7836231406687464395">Postfix (Zərf)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Heç bir tətbiq}=1{1 tətbiq (<ph name="EXAMPLE_APP_1" />)}=2{2 tətbiq (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# tətbiq (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Siz görünməz olmursunuz. Gizli rejim brauzeri şirkətinizdən, internet xidməti provayderi və ya daxil olduğunuz veb saytdan gizlətmir.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Fayl növü əlaqələri olan faylları açın.</translation>
<translation id="7862185352068345852">Saytdan çıxılsın?</translation>
<translation id="7865448901209910068">Æn yüksÉ™k sürÉ™t</translation>
<translation id="7874263914261512992">İndicə parolunuzu aldadıcı saytda daxil etdiniz. Chrome <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> saytlarında və bu paroldan istifadə etdiyiniz digər saytlarda saxlanılmış parollarınızı indi yoxlamağı tövsiyə edir.</translation>
<translation id="7878562273885520351">Parolunuz təhlükədə ola bilər</translation>
+<translation id="7880146494886811634">Ünvanın Yadda Saxlanması</translation>
<translation id="7882421473871500483">Qəhvəyi</translation>
<translation id="7887683347370398519">CVC kodunuzu yoxlayın və yenidən cəhd edin</translation>
<translation id="7887885240995164102">Şəkildə şəkil xüsusiyyətinə daxil olun</translation>
@@ -1816,6 +1865,7 @@
<translation id="7894280532028510793">Yazılış doğrudursa, <ph name="BEGIN_LINK" />Şəbəkə Diaqnostikasını icra edin<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Zərf)</translation>
<translation id="7931318309563332511">Naməlum</translation>
+<translation id="793209273132572360">Ünvan yenilənsin?</translation>
<translation id="7932579305932748336">Palto</translation>
<translation id="79338296614623784">Düzgün telefon nömrəsi daxil edin</translation>
<translation id="7934052535022478634">Ödəmə tamamlandı</translation>
@@ -1886,6 +1936,7 @@
<translation id="8175796834047840627">Daxil olduğunuza görə Chrome kartları Google Hesabında yadda saxlamağı təklif edir. Bunu ayarlarda dəyişə bilərsiniz.</translation>
<translation id="8176440868214972690">Bu cihazın administratoru aşağıdakı veb saytlara ayarlar və ya siyasətlər kimi bəzi məlumatlar göndərib.</translation>
<translation id="8184538546369750125">Qlobal defoltdan istifadÉ™ edin (Ä°cazÉ™ verin)</translation>
+<translation id="8193086767630290324">Məxfi olaraq işarələnmiş məlumatlarla aparılan əməliyyatlar</translation>
<translation id="8194797478851900357">&amp;Ləğv edin</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" identifikasiyalı artırma üçün güncəllənmə linki yanlışdır</translation>
<translation id="8202097416529803614">Sifariş xülasəsi</translation>
@@ -1908,6 +1959,7 @@
<translation id="8249296373107784235">Dayandırın</translation>
<translation id="8249320324621329438">Son əldə etmə:</translation>
<translation id="8253091569723639551">Faktura ünvanı tələb olunur</translation>
+<translation id="8257387598443225809">Bu tətbiq mobil üçün nəzərdə tutulmuşdur</translation>
<translation id="825929999321470778">Yadda Saxlanmış Bütün Parolları Göstərin</translation>
<translation id="8261506727792406068">Silin</translation>
<translation id="8262952874573525464">Aşağıdan kənarını tikin</translation>
@@ -2031,7 +2083,6 @@
<translation id="8719528812645237045">Yuxarıdan çoxsaylı deşik açın</translation>
<translation id="8725066075913043281">Yenidən cəhd edin</translation>
<translation id="8726549941689275341">Səhifə ölçüsü:</translation>
-<translation id="8728672262656704056">Gizli rejimə keçdiniz</translation>
<translation id="8730621377337864115">Tamamdır</translation>
<translation id="8731544501227493793">"Parolları idarə edin" düyməsi, Chrome ayarlarında parollarınıza baxmaq və idarə etmək üçün Enter düyməsinə basın</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> cihazınız <ph name="MANAGER" /> tərəfindən idarə edilir</translation>
@@ -2108,6 +2159,7 @@
<translation id="9020542370529661692">Bu səhifə <ph name="TARGET_LANGUAGE" /> dilinə tərcümə edilmişdir</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Yanlış)</translation>
+<translation id="9030265603405983977">Monoxrom</translation>
<translation id="9035022520814077154">Güvənlik xətası</translation>
<translation id="9038649477754266430">Səhifələri daha sürətlə yükləmək üçün proqnozlaşdırma xidmətindən istifadə edin</translation>
<translation id="9039213469156557790">Bundan əlavə, bu səhifəyə təhlükəsiz olmayan başqa resurslar daxildir. Bu resurslar keçid zamanı başqaları tərəfindən görüntülən bilər və hücumçu tərəfindən səhifə rejiminin dəyişdirilməsi üçün modifikasiya edilə bilər.</translation>
@@ -2131,6 +2183,7 @@
<translation id="91108059142052966">Administrator suyasəti məxfi məzmun göründüyü zaman <ph name="APPLICATION_TITLE" /> ilə ekran paylaşımını deaktiv edir</translation>
<translation id="9114524666733003316">Kart təsdiqlənir...</translation>
<translation id="9114581008513152754">Bu brauzer ÅŸirkÉ™t vÉ™ ya baÅŸqa təşkilat tÉ™rÉ™findÉ™n idarÉ™ edilmir. Bu cihazdakı fÉ™aliyyÉ™t Chrome'dan kÉ™narda idarÉ™ edilÉ™ bilÉ™r. <ph name="BEGIN_LINK" />Ætraflı mÉ™lumat<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Təzə</translation>
<translation id="9119042192571987207">Yüklənib</translation>
<translation id="9128016270925453879">Siyasətlər yüklənib</translation>
<translation id="9128870381267983090">Şəbəkəyə qoşulun</translation>
@@ -2149,6 +2202,7 @@
<translation id="9170848237812810038">Ləğv edin</translation>
<translation id="9171296965991013597">Tətbiqdən çıxılsın?</translation>
<translation id="9173282814238175921">Tək sənəd/Yeni vərəq</translation>
+<translation id="9173995187295789444">Bluetooth cihazları skan edilir...</translation>
<translation id="917450738466192189">Serverin sertifikatı yanlışdlr.</translation>
<translation id="9174917557437862841">Bu taba keçmək üçün keçid düyməsinə klikləyib "Daxil olun" düyməsinə basın</translation>
<translation id="9179703756951298733">Ödəniş və kredit kartı məlumatlarınızı Chrome ayarlarında idarə edin</translation>
diff --git a/chromium/components/strings/components_strings_be.xtb b/chromium/components/strings/components_strings_be.xtb
index b9d49520938..f62f3de488c 100644
--- a/chromium/components/strings/components_strings_be.xtb
+++ b/chromium/components/strings/components_strings_be.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Калі тут паÑтавіць птушку, Chrome будзе захоўваць копію вашай карткі на гÑтай прыладзе Ñž мÑтах хутчÑйшага Ð·Ð°Ð¿Ð°ÑžÐ½ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€Ð¼.</translation>
<translation id="1110994991967754504">Выберыце дазвол Ð´Ð»Ñ <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Ðдрабіць змÑненне парадку</translation>
+<translation id="1123753900084781868">Ð†Ð¼Ð³Ð½ÐµÐ½Ð½Ñ‹Ñ Ñубцітры зараз недаÑтупныÑ</translation>
<translation id="1125573121925420732">Пакуль Ñайты абнаўлÑюць ÑÑ–ÑÑ‚Ñму бÑÑпекі, папÑÑ€Ñджанні могуць з'ÑўлÑцца чаÑта. Ðеўзабаве гÑта павінна выправіцца.</translation>
<translation id="112840717907525620">У кÑшы правіла нÑма памылак</translation>
<translation id="1130564665089811311">Кнопка "ПераклаÑці Ñтаронку". Каб пераклаÑці гÑту Ñтаронку Ñž Перакладчыку Google, націÑніце Enter</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Ðазва вашай прылады</translation>
<translation id="124116460088058876">Ð†Ð½ÑˆÑ‹Ñ Ð¼Ð¾Ð²Ñ‹</translation>
<translation id="1243027604378859286">Ðўтар:</translation>
+<translation id="1246424317317450637">ПаўтлуÑÑ‚Ñ‹</translation>
<translation id="1250759482327835220">Каб наÑтупны раз плаціць хутчÑй, захавайце картку, Ñ–Ð¼Ñ Ñ– Ð°Ð´Ñ€Ð°Ñ Ð´Ð»Ñ Ð²Ñ‹ÑÑ‚Ð°ÑžÐ»ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÐ°Ñž ва Уліковым запіÑе Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (ÑінхранізаваныÑ)</translation>
<translation id="1256368399071562588">&lt;p&gt;Калі патрÑбны вÑб-Ñайт не адкрываецца, паÑпрабуйце знайÑці Ñ– вырашыць праблему наÑтупным чынам:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">ЗмÑніце пароль</translation>
<translation id="1484290072879560759">Выбраць Ð°Ð´Ñ€Ð°Ñ Ð´Ð°Ñтаўкі</translation>
<translation id="1492194039220927094">Паказ палітык:</translation>
+<translation id="1495677929897281669">Ð’Ñрнуцца на ўкладку</translation>
<translation id="1501859676467574491">Паказаць карткі з вашага Уліковага запіÑу Google</translation>
<translation id="1507202001669085618">&lt;p&gt;ГÑта памылка ўзнікае, калі вы карыÑтаецеÑÑ Ð¿Ð°Ñ€Ñ‚Ð°Ð»Ð°Ð¼ Wi-Fi, на Ñкім перад выхадам у інтÑрнÑÑ‚ Ñ‚Ñ€Ñба выканаць уваход.&lt;/p&gt;
&lt;p&gt;Каб выправіць памылку, націÑніце &lt;strong&gt;Падключыцца&lt;/strong&gt; на Ñтаронцы, Ñкую вы Ñпрабуеце адкрыць.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð°Ð´ Ñтаронкі</translation>
<translation id="153384715582417236">Пакуль што ÑžÑÑ‘!</translation>
<translation id="1536390784834419204">ПераклаÑці Ñтаронку</translation>
+<translation id="1539840569003678498">Справаздача адпраўлена:</translation>
<translation id="154408704832528245">Выбраць Ð°Ð´Ñ€Ð°Ñ Ð´Ð°Ñтаўкі</translation>
<translation id="1549470594296187301">Каб карыÑтацца гÑтай функцыÑй, Ñ‚Ñ€Ñба ўключыць JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">Спачатку кароткі край</translation>
<translation id="168693727862418163">Ðе ўдалоÑÑ Ð¿Ð°Ñ†Ð²ÐµÑ€Ð´Ð·Ñ–Ñ†ÑŒ адпаведнаÑць значÑÐ½Ð½Ñ Ð¿Ð°Ð»Ñ–Ñ‚Ñ‹ÐºÑ– Ñхеме, таму Ñно будзе ігнаравацца.</translation>
<translation id="168841957122794586">У Ñертыфіката Ñервера Ñлабы крыптаграфічны ключ.</translation>
+<translation id="1696290444144917273">ПаглÑдзець Ñ€Ñквізіты віртуальнай карткі</translation>
<translation id="1697532407822776718">УÑÑ‘ гатова!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Серверу не ўдалоÑÑ Ð´Ð°ÐºÐ°Ð·Ð°Ñ†ÑŒ, што гÑта дамен <ph name="DOMAIN" />. Здаецца, Ñго Ñертыфікат бÑÑпекі пачынае дзейнічаць з заўтрашнÑга днÑ. Прычынай могуць быць нÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ або зламыÑнік, Ñкі Ñпрабуе перахапіць падключÑнне.}one{Серверу не ўдалоÑÑ Ð´Ð°ÐºÐ°Ð·Ð°Ñ†ÑŒ, што гÑта дамен <ph name="DOMAIN" />. Здаецца, Ñго Ñертыфікат бÑÑпекі пачынае дзейнічаць праз # дзень. Прычынай могуць быць нÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ або зламыÑнік, Ñкі Ñпрабуе перахапіць падключÑнне.}few{Серверу не ўдалоÑÑ Ð´Ð°ÐºÐ°Ð·Ð°Ñ†ÑŒ, што гÑта дамен <ph name="DOMAIN" />. Здаецца, Ñго Ñертыфікат бÑÑпекі пачынае дзейнічаць праз # дні. Прычынай могуць быць нÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ або зламыÑнік, Ñкі Ñпрабуе перахапіць падключÑнне.}many{Серверу не ўдалоÑÑ Ð´Ð°ÐºÐ°Ð·Ð°Ñ†ÑŒ, што гÑта дамен <ph name="DOMAIN" />. Здаецца, Ñго Ñертыфікат бÑÑпекі пачынае дзейнічаць праз # дзён. Прычынай могуць быць нÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ або зламыÑнік, Ñкі Ñпрабуе перахапіць падключÑнне.}other{Серверу не ўдалоÑÑ Ð´Ð°ÐºÐ°Ð·Ð°Ñ†ÑŒ, што гÑта дамен <ph name="DOMAIN" />. Здаецца, Ñго Ñертыфікат бÑÑпекі пачынае дзейнічаць праз # днÑ. Прычынай могуць быць нÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ або зламыÑнік, Ñкі Ñпрабуе перахапіць падключÑнне.}}</translation>
<translation id="1710259589646384581">ÐС</translation>
+<translation id="1711234383449478798">Ðе прымÑнÑецца, паколькі палітыка "<ph name="POLICY_NAME" />" не мае значÑÐ½Ð½Ñ "<ph name="VALUE" />".</translation>
<translation id="1712552549805331520">Сайт <ph name="URL" /> запытвае дазволу захоўваць Ð´Ð°Ð½Ñ‹Ñ Ð½Ð° лакальным камп'ютары</translation>
<translation id="1713628304598226412">Латок 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">ÐŸÐ°ÑˆÑ‚Ð¾Ð²Ð°Ñ Ñкрынка 3</translation>
<translation id="1718029547804390981">Занадта вÑлікі дакумент Ð´Ð»Ñ Ð°Ð½Ð°Ñ‚Ð°Ñ†Ñ‹Ð¹</translation>
<translation id="1721424275792716183">* ÐбавÑзковае поле</translation>
+<translation id="1727613060316725209">Сертыфікат з’ÑўлÑецца Ñапраўдным</translation>
<translation id="1727741090716970331">Дадайце нумар дзеючай карткі</translation>
<translation id="1728677426644403582">Ð’Ñ‹ праглÑдаеце крыніцу вÑб-Ñтаронкі</translation>
<translation id="173080396488393970">Карткі гÑтага тыпу не падтрымліваюцца</translation>
@@ -246,7 +253,6 @@
выканаць запыт Ñайта "<ph name="SITE" />". Палітыкі крыніцы могуць выкарыÑтоўвацца
аператарамі Ñайтаў Ð´Ð»Ñ Ð½Ð°Ð»Ð°Ð´Ð¶Ð²Ð°Ð½Ð½Ñ Ð±ÑÑпекі Ñ– іншых улаÑціваÑцей Ñайта.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Ðбнавіце фразу-пароль Ð´Ð»Ñ Ñінхранізацыі.</translation>
<translation id="1787142507584202372">ÐÐ´ÐºÑ€Ñ‹Ñ‚Ñ‹Ñ ÑžÐºÐ»Ð°Ð´ÐºÑ– з'ÑвÑцца тут</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, даÑтупна некалькі дзеÑннÑÑž. Ð”Ð»Ñ Ñ–Ñ… праглÑду націÑкайце Tab</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">РÑклама</translation>
<translation id="1919367280705858090">Дапамога пры аÑобных паведамленнÑÑ… аб памылцы</translation>
<translation id="192020519938775529">{COUNT,plural, =0{ÐÑма}=1{1 Ñайт}one{# Ñайт}few{# Ñайты}many{# Ñайтаў}other{# Ñайта}}</translation>
+<translation id="1924727005275031552">ÐÐ¾Ð²Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð°</translation>
<translation id="1945968466830820669">Ð’Ñ‹ можаце Ñтраціць доÑтуп да ўліковага запіÑу арганізацыі, або Ñž Ð²Ð°Ñ Ð¼Ð¾Ð³ÑƒÑ†ÑŒ ÑкраÑці аÑабіÑÑ‚Ñ‹Ñ Ð´Ð°Ð½Ñ‹Ñ. Chromium Ñ€Ñкамендуе змÑніць пароль.</translation>
<translation id="1947454675006758438">Скаба зверху Ñправа</translation>
<translation id="1958218078413065209">Ваш Ñ€Ñзультат: <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">Латок 7</translation>
<translation id="204357726431741734">Каб выкарыÑтоўваць Ð·Ð°Ñ…Ð°Ð²Ð°Ð½Ñ‹Ñ Ð²Ð° Уліковым запіÑе Google паролі, увайдзіце Ñž Ñго</translation>
<translation id="2053111141626950936">Старонкі на мове <ph name="LANGUAGE" /> не будуць перакладацца.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Калі гÑÑ‚Ñ‹ Ñлемент ÐºÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ ÑžÐºÐ»ÑŽÑ‡Ð°Ð½Ñ‹ Ñ– Ñ‚ÑÑ…Ð½Ð°Ð»Ð¾Ð³Ñ–Ñ FLoC актывавана, Chrome выÑўлÑе, да дзеÑннÑÑž Ñкой вÑлікай групы людзей ("кагорты") больш за ÑžÑÑ‘ Ð¿Ð°Ð´Ð¾Ð±Ð½Ñ‹Ñ Ð²Ð°ÑˆÑ‹ нÑÐ´Ð°ÑžÐ½Ñ–Ñ Ð´Ð·ÐµÑнні Ñž браўзеры. РÑкламадаўцы могуць падбіраць Ñ€Ñкламу Ð´Ð»Ñ Ð³Ñтай групы, а звеÑткі пра дзеÑнні Ñž браўзеры пры гÑтым будуць прыватна захоўвацца на вашай прыладзе. Параметры вашай групы абнаўлÑюцца кожны дзень.}=1{Калі гÑÑ‚Ñ‹ Ñлемент ÐºÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ ÑžÐºÐ»ÑŽÑ‡Ð°Ð½Ñ‹ Ñ– Ñ‚ÑÑ…Ð½Ð°Ð»Ð¾Ð³Ñ–Ñ FLoC актывавана, Chrome выÑўлÑе, да дзеÑннÑÑž Ñкой вÑлікай групы людзей ("кагорты") больш за ÑžÑÑ‘ Ð¿Ð°Ð´Ð¾Ð±Ð½Ñ‹Ñ Ð²Ð°ÑˆÑ‹ нÑÐ´Ð°ÑžÐ½Ñ–Ñ Ð´Ð·ÐµÑнні Ñž браўзеры. РÑкламадаўцы могуць падбіраць Ñ€Ñкламу Ð´Ð»Ñ Ð³Ñтай групы, а звеÑткі пра дзеÑнні Ñž браўзеры пры гÑтым будуць прыватна захоўвацца на вашай прыладзе. Параметры вашай групы абнаўлÑюцца кожны дзень.}one{Калі гÑÑ‚Ñ‹ Ñлемент ÐºÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ ÑžÐºÐ»ÑŽÑ‡Ð°Ð½Ñ‹ Ñ– Ñ‚ÑÑ…Ð½Ð°Ð»Ð¾Ð³Ñ–Ñ FLoC актывавана, Chrome выÑўлÑе, да дзеÑннÑÑž Ñкой вÑлікай групы людзей ("кагорты") больш за ÑžÑÑ‘ Ð¿Ð°Ð´Ð¾Ð±Ð½Ñ‹Ñ Ð²Ð°ÑˆÑ‹ нÑÐ´Ð°ÑžÐ½Ñ–Ñ Ð´Ð·ÐµÑнні Ñž браўзеры. РÑкламадаўцы могуць падбіраць Ñ€Ñкламу Ð´Ð»Ñ Ð³Ñтай групы, а звеÑткі пра дзеÑнні Ñž браўзеры пры гÑтым будуць прыватна захоўвацца на вашай прыладзе. Параметры вашай групы абнаўлÑюцца кожны {NUM_DAYS} дзень.}few{Калі гÑÑ‚Ñ‹ Ñлемент ÐºÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ ÑžÐºÐ»ÑŽÑ‡Ð°Ð½Ñ‹ Ñ– Ñ‚ÑÑ…Ð½Ð°Ð»Ð¾Ð³Ñ–Ñ FLoC актывавана, Chrome выÑўлÑе, да дзеÑннÑÑž Ñкой вÑлікай групы людзей ("кагорты") больш за ÑžÑÑ‘ Ð¿Ð°Ð´Ð¾Ð±Ð½Ñ‹Ñ Ð²Ð°ÑˆÑ‹ нÑÐ´Ð°ÑžÐ½Ñ–Ñ Ð´Ð·ÐµÑнні Ñž браўзеры. РÑкламадаўцы могуць падбіраць Ñ€Ñкламу Ð´Ð»Ñ Ð³Ñтай групы, а звеÑткі пра дзеÑнні Ñž браўзеры пры гÑтым будуць прыватна захоўвацца на вашай прыладзе. Параметры вашай групы абнаўлÑюцца ÐºÐ¾Ð¶Ð½Ñ‹Ñ {NUM_DAYS} дні.}many{Калі гÑÑ‚Ñ‹ Ñлемент ÐºÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ ÑžÐºÐ»ÑŽÑ‡Ð°Ð½Ñ‹ Ñ– Ñ‚ÑÑ…Ð½Ð°Ð»Ð¾Ð³Ñ–Ñ FLoC актывавана, Chrome выÑўлÑе, да дзеÑннÑÑž Ñкой вÑлікай групы людзей ("кагорты") больш за ÑžÑÑ‘ Ð¿Ð°Ð´Ð¾Ð±Ð½Ñ‹Ñ Ð²Ð°ÑˆÑ‹ нÑÐ´Ð°ÑžÐ½Ñ–Ñ Ð´Ð·ÐµÑнні Ñž браўзеры. РÑкламадаўцы могуць падбіраць Ñ€Ñкламу Ð´Ð»Ñ Ð³Ñтай групы, а звеÑткі пра дзеÑнні Ñž браўзеры пры гÑтым будуць прыватна захоўвацца на вашай прыладзе. Параметры вашай групы абнаўлÑюцца ÐºÐ¾Ð¶Ð½Ñ‹Ñ {NUM_DAYS} дзён.}other{Калі гÑÑ‚Ñ‹ Ñлемент ÐºÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ ÑžÐºÐ»ÑŽÑ‡Ð°Ð½Ñ‹ Ñ– Ñ‚ÑÑ…Ð½Ð°Ð»Ð¾Ð³Ñ–Ñ FLoC актывавана, Chrome выÑўлÑе, да дзеÑннÑÑž Ñкой вÑлікай групы людзей ("кагорты") больш за ÑžÑÑ‘ Ð¿Ð°Ð´Ð¾Ð±Ð½Ñ‹Ñ Ð²Ð°ÑˆÑ‹ нÑÐ´Ð°ÑžÐ½Ñ–Ñ Ð´Ð·ÐµÑнні Ñž браўзеры. РÑкламадаўцы могуць падбіраць Ñ€Ñкламу Ð´Ð»Ñ Ð³Ñтай групы, а звеÑткі пра дзеÑнні Ñž браўзеры пры гÑтым будуць прыватна захоўвацца на вашай прыладзе. Параметры вашай групы абнаўлÑюцца ÐºÐ¾Ð¶Ð½Ñ‹Ñ {NUM_DAYS} днÑ.}}</translation>
<translation id="2053553514270667976">Паштовы індÑкÑ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 прапанова}one{# прапанова}few{# прапановы}many{# прапаноў}other{# прапановы}}</translation>
<translation id="2071692954027939183">ÐпавÑшчÑнні былі заблакіраваны аўтаматычна, бо звычайна вы не даÑце дазволу на Ñ–Ñ… паказ</translation>
<translation id="2079545284768500474">Ðдрабіць</translation>
<translation id="20817612488360358">СіÑÑ‚ÑÐ¼Ð½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ прокÑÑ– зададзены Ð´Ð»Ñ Ð²Ñ‹ÐºÐ°Ñ€Ñ‹ÑтаннÑ, але ÑÑžÐ½Ð°Ñ ÐºÐ°Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð¾ÐºÑÑ– такÑама вызначана.</translation>
<translation id="2082238445998314030">Вынік <ph name="RESULT_NUMBER" /> з <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Захаваць…</translation>
<translation id="2088086323192747268">Кнопка "Кіраваць ÑінхранізацыÑй". Каб задаць у наладах Chrome, ÑÐºÐ°Ñ Ñ–Ð¼ÐµÐ½Ð½Ð° Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð±ÑƒÐ´Ð·Ðµ Ñінхранізавацца, націÑніце Enter</translation>
<translation id="2091887806945687916">Гук</translation>
<translation id="2094505752054353250">ÐеÑупадзенне дамена</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535">Ð”Ð»Ñ <ph name="DOMAIN" /> патрабуецца Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Ñ– пароль.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, дзейнічае да <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Ðаладай кіруе ваш адмініÑтратар</translation>
+<translation id="2340263603246777781">Сайт <ph name="ORIGIN" /> запытвае ÑпалучÑнне</translation>
<translation id="2344028582131185878">ÐÑžÑ‚Ð°Ð¼Ð°Ñ‚Ñ‹Ñ‡Ð½Ñ‹Ñ Ñпампоўкі</translation>
<translation id="2346319942568447007">Скапіраваны вамі відарыÑ</translation>
<translation id="2354001756790975382">Ð†Ð½ÑˆÑ‹Ñ Ð·Ð°ÐºÐ»Ð°Ð´ÐºÑ–</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">ЗламыÑнікі могуць бачыць відарыÑÑ‹, ÑÐºÑ–Ñ Ð²Ñ‹ праглÑдаеце на гÑтым Ñайце, Ñ– падмануць ваÑ, мадыфікуючы Ñ–Ñ….</translation>
<translation id="2356070529366658676">Запытваць</translation>
<translation id="2357481397660644965">Вашай прыладай кіруе <ph name="DEVICE_MANAGER" />, а вашым уліковым запіÑам – <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Менш чым праз дзень}=1{Праз дзень}one{Праз {NUM_DAYS} дзень}few{Праз {NUM_DAYS} дні}many{Праз {NUM_DAYS} дзён}other{Праз {NUM_DAYS} днÑ}}</translation>
<translation id="2359629602545592467">Ðекалькі</translation>
<translation id="2359808026110333948">ПрацÑгнуць</translation>
+<translation id="2359961752320758691">Ðумар віртуальнай карткі прыменены.</translation>
<translation id="2367567093518048410">Узровень</translation>
<translation id="2372464001869762664">ПаÑÐ»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° пацвÑрджÑÐ½Ð½Ñ Ð´Ð°Ð½Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ– з Уліковага запіÑу Google будуць абагулены з гÑтым Ñайтам. Ð’Ñ‹ можаце знайÑці код CVC у даных уліковага запіÑу Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">ГÑÑ‚Ñ‹ ÑпоÑаб даÑтаўкі недаÑтупны. Выберыце іншы ÑпоÑаб.</translation>
<translation id="2396249848217231973">&amp;Ðдрабіць выдаленне</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Ð¡Ñ‚Ð°Ñ€Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð°</translation>
<translation id="2413528052993050574">Серверу не ўдалоÑÑ Ð´Ð°ÐºÐ°Ð·Ð°Ñ†ÑŒ, што гÑта <ph name="DOMAIN" />; магчыма, Ñго Ñертыфікат бÑÑпекі адкліканы. Прычынай могуць быць нÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ або зламыÑнік, Ñкі Ñпрабуе перахапіць падключÑнне.</translation>
<translation id="2414886740292270097">ЦёмнаÑ</translation>
<translation id="2438874542388153331">Чатыры дзіркі Ñправа</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">Скаба знізу Ñправа</translation>
<translation id="2523886232349826891">Захавана толькі на гÑтай прыладзе</translation>
<translation id="2524461107774643265">Дадаць болей звеÑтак</translation>
-<translation id="2526590354069164005">Працоўны Ñтол</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{Ñ– ÑÑˆÑ‡Ñ 1}one{Ñ– ÑÑˆÑ‡Ñ #}few{Ñ– ÑÑˆÑ‡Ñ #}many{Ñ– ÑÑˆÑ‡Ñ #}other{Ñ– ÑÑˆÑ‡Ñ #}}</translation>
<translation id="2536110899380797252">Дадаць адраÑ</translation>
<translation id="2539524384386349900">Ð’Ñ‹Ñвіць</translation>
+<translation id="2541219929084442027">Старонкі, Ð½Ð°Ð²ÐµÐ´Ð°Ð½Ñ‹Ñ Ð²Ð° ўкладках у Ñ€Ñжыме інкогніта, не будуць заÑтавацца Ñž гіÑторыі браўзера, Ñховішчы файлаў cookie Ñ– гіÑторыі пошуку, паÑÐ»Ñ Ñ‚Ð°Ð³Ð¾ Ñк вы закрыеце ÑžÑе Ñ‚Ð°ÐºÑ–Ñ ÑžÐºÐ»Ð°Ð´ÐºÑ–. УÑе ÑÐ¿Ð°Ð¼Ð¿Ð°Ð²Ð°Ð½Ñ‹Ñ Ñ„Ð°Ð¹Ð»Ñ‹ Ñ– ÑÑ‚Ð²Ð¾Ñ€Ð°Ð½Ñ‹Ñ Ð·Ð°ÐºÐ»Ð°Ð´ÐºÑ– будуць захаваны.</translation>
<translation id="2544644783021658368">Ðдзіны дакумент</translation>
<translation id="254947805923345898">ЗначÑнне палітыкі неÑапраўднае.</translation>
<translation id="255002559098805027">ХоÑÑ‚ <ph name="HOST_NAME" /> адправіў нÑправільны адказ.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Каб у браўзеры Chrome падтрымліваўÑÑ Ð½Ð°Ð¹Ð²Ñ‹ÑˆÑйшы ўзровень бÑÑпекі, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />уключыце палепшаную абарону<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">IP-Ð°Ð´Ñ€Ð°Ñ Ñервера хоÑта <ph name="HOST_NAME" /> не знойдзены.</translation>
<translation id="2639739919103226564">Стан:</translation>
+<translation id="264810637653812429">СумÑÑˆÑ‡Ð°Ð»ÑŒÐ½Ñ‹Ñ Ð¿Ñ€Ñ‹Ð»Ð°Ð´Ñ‹ не знойдзены.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. Каб выдаліць Ð´Ð°Ð½Ñ‹Ñ Ð³Ñ–Ñторыі праглÑдаў Ñайтаў, файлы cookie, кÑшаванае змеÑціва Ñ– іншае праз налады Chrome, націÑніце Tab, затым Enter</translation>
<translation id="2650446666397867134">У доÑтупе да файла адмоўлена</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">ПеразапуÑціць</translation>
<translation id="2803306138276472711">Google БÑÑпечны праглÑд толькі што <ph name="BEGIN_LINK" />выÑвіў шкоднае ПЗ<ph name="END_LINK" /> на Ñайце <ph name="SITE" />. Сайты, ÑÐºÑ–Ñ Ð·Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ð° з'ÑўлÑюцца надзейнымі, чаÑам заражаюцца шкодным ПЗ.</translation>
<translation id="2807052079800581569">РазмÑшчÑнне відарыÑа па воÑÑ– Y</translation>
+<translation id="2820957248982571256">Ідзе пошук...</translation>
<translation id="2824775600643448204">ÐдраÑны радок Ñ– панÑль пошуку</translation>
<translation id="2826760142808435982">ПадключÑнне зашыфравана Ñ– аўтÑнтыфікавана з дапамогай <ph name="CIPHER" />, механізм абмену ключамі – <ph name="KX" />.</translation>
<translation id="2835170189407361413">ÐчыÑціць форму</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Invite (канверт)</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="2859806420264540918">ГÑÑ‚Ñ‹ Ñайт паказвае назойлівую Ñ€Ñкламу або Ñ€Ñкламу, ÑÐºÐ°Ñ ÑžÐ²Ð¾Ð´Ð·Ñ–Ñ†ÑŒ у зман.</translation>
+<translation id="287596039013813457">ТаварыÑкі</translation>
+<translation id="2876489322757410363">Ðдбудзецца выхад з Ñ€Ñжыму інкогніта Ð´Ð»Ñ Ð¿Ð»Ð°Ñ†Ñжу праз знешнюю праграму. ПрацÑгнуць?</translation>
<translation id="2878197950673342043">Плакатны згіб</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">РазмÑшчÑнне вокнаў</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (канверт)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, каб выканаць праверку бÑÑпекі Ñž наладах Chrome, націÑніце Tab, затым Enter</translation>
<translation id="3061707000357573562">СÑÑ€Ð²Ñ–Ñ Ð²Ñ‹Ð¿Ñ€Ð°ÑžÐ»ÐµÐ½Ð½ÑÑž</translation>
-<translation id="3064966200440839136">Выхад з Ñ€Ñжыму інкогніта Ð´Ð»Ñ Ð¿Ð»Ð°Ñ†Ñжу праз знешнюю праграму. ПрацÑгнуць?</translation>
<translation id="306573536155379004">Ð“ÑƒÐ»ÑŒÐ½Ñ Ð¿Ð°Ñ‡Ð°Ð»Ð°ÑÑ.</translation>
<translation id="3080254622891793721">Графіка</translation>
<translation id="3086579638707268289">Вашы дзеÑнні Ñž інтÑрнÑце адÑочваюцца</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">ГÑтым уліковым запіÑам кіруе <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Ðднавіць</translation>
<translation id="3162559335345991374">Сетка Wi-Fi, Ñкую вы выкарыÑтоўваеце, можа запатрабаваць ад Ð²Ð°Ñ Ð½Ð°Ð²ÐµÐ´Ð°Ñ†ÑŒ Ñе Ñтаронку ўваходу.</translation>
-<translation id="3167968892399408617">Старонкі, Ð½Ð°Ð²ÐµÐ´Ð°Ð½Ñ‹Ñ Ð²Ð° ўкладках інкогніта, не будуць заÑтавацца Ñž гіÑторыі браўзера, Ñховішчы файлаў cookie або гіÑторыі пошуку, паÑÐ»Ñ Ñ‚Ð°Ð³Ð¾ Ñк вы закрыеце ÑžÑе ўкладкі інкогніта. УÑе ÑÐ¿Ð°Ð¼Ð¿Ð°Ð²Ð°Ð½Ñ‹Ñ Ñ„Ð°Ð¹Ð»Ñ‹ Ñ– ÑÑ‚Ð²Ð¾Ñ€Ð°Ð½Ñ‹Ñ Ð·Ð°ÐºÐ»Ð°Ð´ÐºÑ– будуць захаваны.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">ВоÑтраў</translation>
<translation id="3176929007561373547">Праверце налады прокÑÑ– або звÑрніцеÑÑ Ð´Ð° адмініÑтратара Ñеткі, каб
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">ЗвеÑткі пра верÑÑ–ÑŽ прылады Ñ– браўзера</translation>
<translation id="323107829343500871">УвÑдзіце CVC-код карткі <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">ЗаўÑёды выÑўлÑць важнае змеÑціва на гÑтым Ñайце</translation>
+<translation id="3249845759089040423">Стыльны</translation>
<translation id="3252266817569339921">ФранцузÑкаÑ</translation>
<translation id="3266793032086590337">ЗначÑнне (канфліктуючае)</translation>
<translation id="3268451620468152448">ÐÐ´ÐºÑ€Ñ‹Ñ‚Ñ‹Ñ ÑžÐºÐ»Ð°Ð´ÐºÑ–</translation>
<translation id="3270847123878663523">&amp;Ðдрабіць змÑненне парадку</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> запытвае падключÑнне</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Ваша Ð°Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ‹Ñ (<ph name="ENROLLMENT_DOMAIN" />) адправіла на наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð²Ñб-Ñайты пÑÑžÐ½Ñ‹Ñ Ð·Ð²ÐµÑткі (напрыклад, налады або палітыкі).</translation>
<translation id="3282497668470633863">Дадайце імÑ, указанае на картцы</translation>
@@ -655,6 +672,7 @@
<translation id="3428151540071562330">Ðдзін або некалькі URI шаблонаў Ñервераў з палітыкі DnsOverHttpsTemplates нÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ñ‹Ñ Ñ– выкарыÑтоўвацца не будуць.</translation>
<translation id="3431636764301398940">Захаваць гÑту картку на гÑту прыладу</translation>
<translation id="3432601291244612633">Закрыць Ñтаронку</translation>
+<translation id="3435738964857648380">БÑÑпека</translation>
<translation id="3435896845095436175">Уключыць</translation>
<translation id="3438829137925142401">ВыкарыÑтаць паролі, Ð·Ð°Ñ…Ð°Ð²Ð°Ð½Ñ‹Ñ Ð²Ð° Уліковым запіÑе Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -696,7 +714,10 @@
<translation id="3584299510153766161">Дзве дзіркі знізу</translation>
<translation id="3586931643579894722">Схаваць падрабÑзнаÑці</translation>
<translation id="3587738293690942763">СÑÑ€Ñдні</translation>
+<translation id="3590643883886679995">ПаÑÐ»Ñ Ð²Ñ‹Ñ…Ð°Ð´Ñƒ з Ñ€Ñжыму інкогніта Ð´Ð°Ð½Ñ‹Ñ Ð´Ð»Ñ ÑžÐ²Ð°Ñ…Ð¾Ð´Ñƒ будуць захоўвацца на гÑтай прыладзе.</translation>
+<translation id="359126217934908072">МеÑÑц/год:</translation>
<translation id="3592413004129370115">Italian (канверт)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Ð’Ñ‹ можаце Ñкінуць параметры Ñваёй групы Ñž любы чаÑ. ДалучÑнне да новай групы адбываецца прыблізна праз дзень.}=1{Ð’Ñ‹ можаце Ñкінуць параметры Ñваёй групы Ñž любы чаÑ. ДалучÑнне да новай групы адбываецца прыблізна праз дзень.}one{Ð’Ñ‹ можаце Ñкінуць параметры Ñваёй групы Ñž любы чаÑ. ДалучÑнне да новай групы адбываецца прыблізна праз {NUM_DAYS} дзень.}few{Ð’Ñ‹ можаце Ñкінуць параметры Ñваёй групы Ñž любы чаÑ. ДалучÑнне да новай групы адбываецца прыблізна праз {NUM_DAYS} дні.}many{Ð’Ñ‹ можаце Ñкінуць параметры Ñваёй групы Ñž любы чаÑ. ДалучÑнне да новай групы адбываецца прыблізна праз {NUM_DAYS} дзён.}other{Ð’Ñ‹ можаце Ñкінуць параметры Ñваёй групы Ñž любы чаÑ. ДалучÑнне да новай групы адбываецца прыблізна праз {NUM_DAYS} днÑ.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Праграма заблакіравана адмініÑтратарам</translation>
<translation id="3608932978122581043">ÐÑ€Ñ‹ÐµÐ½Ñ‚Ð°Ñ†Ñ‹Ñ Ð¿Ð°Ð´Ð°Ñ‡Ñ‹</translation>
@@ -705,13 +726,13 @@
<translation id="3615877443314183785">УвÑдзіце Ñапраўдную дату заканчÑÐ½Ð½Ñ Ñ‚Ñрміну дзеÑннÑ</translation>
<translation id="36224234498066874">Выдаліць гіÑторыю праглÑдаў...</translation>
<translation id="362276910939193118">Паказаць уÑÑŽ гіÑторыю</translation>
-<translation id="3625635938337243871">Ð”Ð°Ð½Ñ‹Ñ Ð´Ð»Ñ ÑžÐ²Ð°Ñ…Ð¾Ð´Ñƒ будуць захаваны на гÑтай прыладзе паÑÐ»Ñ Ð²Ñ‹Ñ…Ð°Ð´Ñƒ з Ñ€Ñжыму інкогніта.</translation>
<translation id="3630155396527302611">Калі браўзер ужо ўказаны Ñк праграма, Ñкой дазволены доÑтуп да Ñеткі, паÑпрабуйце
выдаліць Ñго Ñа ÑпіÑа Ñ– дадаць зноў.</translation>
<translation id="3630699740441428070">ÐдмініÑтратары прылады наладзілі падключÑнне да Ñеткі Ñ– цÑпер могуць бачыць інфармацыю пра ваш Ñеткавы трафік, у тым ліку ÑÐºÑ–Ñ Ð²Ñб-Ñайты вы наведваеце.</translation>
<translation id="3631244953324577188">БіÑметрыÑ</translation>
<translation id="3633738897356909127">Кнопка "Ðбнавіць Chrome". Каб абнавіць браўзер Chrome праз Ñго налады, націÑніце Enter</translation>
<translation id="3634530185120165534">Латок 5</translation>
+<translation id="3637662659967048211">Захоўванне даных ва Уліковым запіÑе Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Праграма:</translation>
<translation id="3650584904733503804">Праверка прайшла паÑпÑхова</translation>
@@ -752,6 +773,7 @@
<translation id="3781428340399460090">Ярка-ружовы</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Прылады Bluetooth</translation>
+<translation id="3787675388804467730">Ðумар віртуальнай карткі</translation>
<translation id="3787705759683870569">ТÑрмін дзеÑннÑ: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Памер 16</translation>
<translation id="3789841737615482174">УÑталÑваць</translation>
@@ -771,6 +793,7 @@
<translation id="3841184659773414994">Ðпрацоўшчыкі файлаў</translation>
<translation id="385051799172605136">Ðазад</translation>
<translation id="3858027520442213535">Ðбнавіць дату Ñ– чаÑ</translation>
+<translation id="3881478300875776315">Паказваць менш радкоў</translation>
<translation id="3884278016824448484">Канфлікт ідÑнтыфікатара прылады</translation>
<translation id="3885155851504623709">Прыход</translation>
<translation id="388632593194507180">Ð’Ñ‹Ñўлена ажыццÑўленне маніторынгу</translation>
@@ -796,6 +819,7 @@
<translation id="397105322502079400">Ідзе разлік...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> заблакіраваны</translation>
<translation id="3973357910713125165">Кнопка "ЗапуÑціць праверку бÑÑпекі Chrome", націÑніце Enter, каб выканаць праверку бÑÑпекі Ñž наладах Chrome</translation>
+<translation id="3986705137476756801">Выключыць Ð†Ð¼Ð³Ð½ÐµÐ½Ð½Ñ‹Ñ Ñубцітры</translation>
<translation id="3987405730340719549">Chrome выÑвіў, што гÑÑ‚Ñ‹ Ñайт можа быць фальшывым ці махлÑÑ€Ñкім.
Калі вы лічыце, што гÑта папÑÑ€Ñджанне паказваецца вам памылкова, перайдзіце па ÑпаÑылцы https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -892,13 +916,14 @@
<translation id="4275830172053184480">ПеразапуÑціце прыладу</translation>
<translation id="4277028893293644418">Скінуць пароль</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ГÑта картка захавана Ñž вашым Уліковым запіÑе Google}one{ГÑÑ‚Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ– захаваны Ñž вашым Уліковым запіÑе Google}few{ГÑÑ‚Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ– захаваны Ñž вашым Уліковым запіÑе Google}many{ГÑÑ‚Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ– захаваны Ñž вашым Уліковым запіÑе Google}other{ГÑÑ‚Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ– захаваны Ñž вашым Уліковым запіÑе Google}}</translation>
+<translation id="4287885627794386150">ÐŸÑ€Ð¾Ð±Ð½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ‹Ñ– можа выкарыÑтоўвацца, але ÑÑˆÑ‡Ñ Ð½Ðµ актывавана</translation>
<translation id="4297502707443874121">МініÑцюра Ñтаронкі <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Разгарнуць</translation>
<translation id="4300675098767811073">Ðекалькі дзірак Ñправа</translation>
<translation id="4302514097724775343">Каб пачаць гульню, дакраніцеÑÑ Ð´Ð° дыназаўра</translation>
<translation id="4302965934281694568">Chou3 (канверт)</translation>
<translation id="4305666528087210886">Ðе ўдалоÑÑ Ð°Ñ‚Ñ€Ñ‹Ð¼Ð°Ñ†ÑŒ доÑтуп да файла</translation>
-<translation id="4305817255990598646">Пераключыцца</translation>
+<translation id="4306529830550717874">Захаваць адраÑ?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Блакіраваць (Ñтандартна)</translation>
<translation id="4314815835985389558">Кіраванне ÑінхранізацыÑй</translation>
@@ -925,6 +950,7 @@
<translation id="4377125064752653719">Ð’Ñ‹ Ñпрабавалі перайÑці на Ñайт <ph name="DOMAIN" />, але Ñервер выдаў Ñертыфікат, Ñкі быў адкліканы выдаўцом. ГÑта азначае, што ўліковым даным бÑÑпекі, ÑÐºÑ–Ñ Ð²Ñ‹Ð´Ð°Ñž Ñервер, нельга давÑраць. Магчыма, вы абменьваецеÑÑ Ð´Ð°Ð½Ñ‹Ð¼Ñ– Ñа зламыÑнікам.</translation>
<translation id="4378154925671717803">ТÑлефон</translation>
<translation id="4390472908992056574">ÐœÑжа</translation>
+<translation id="4406883609789734330">Ð†Ð¼Ð³Ð½ÐµÐ½Ð½Ñ‹Ñ Ñубцітры</translation>
<translation id="4406896451731180161">вынікі пошуку</translation>
<translation id="4408413947728134509">Файлы cookie: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Ð’Ñ‹ толькі што ўвÑлі Ñвой пароль на Ñайце, вÑдомым падманнымі паводзінамі. Chrome Ñ€Ñкамендуе неадкладна змÑніць пароль на Ñайтах <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> Ñ– на іншых Ñайтах, дзе выкарыÑтоўваецца гÑÑ‚Ñ‹ пароль.</translation>
@@ -937,7 +963,6 @@
<translation id="4435702339979719576">паштоўка)</translation>
<translation id="443673843213245140">ВыкарыÑтанне прокÑÑ–-Ñервера выключана, але ÑÑžÐ½Ð°Ñ ÐºÐ°Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð¾ÐºÑÑ– вызначана.</translation>
<translation id="4464826014807964867">Ð’Ñб-Ñайты Ñа звеÑткамі ад вашай арганізацыі</translation>
-<translation id="4466881336512663640">Змены Ñž форме будуць Ñтрачаны. Ð’Ñ‹ Ñапраўды хочаце працÑгнуць?</translation>
<translation id="4476953670630786061">ГÑта форма не з'ÑўлÑецца бÑÑпечнай. Ðўтазапаўненне было выключана.</translation>
<translation id="4477350412780666475">ÐаÑтупны Ñ‚Ñ€Ñк</translation>
<translation id="4482953324121162758">ГÑÑ‚Ñ‹ Ñайт не будзе перакладацца.</translation>
@@ -971,6 +996,7 @@
<translation id="4594403342090139922">&amp;Ðдрабіць выдаленне</translation>
<translation id="4597348597567598915">Памер 8</translation>
<translation id="4600854749408232102">C6/C5 (канверт)</translation>
+<translation id="4606870351894164739">Уражальны</translation>
<translation id="4628948037717959914">Фота</translation>
<translation id="4631649115723685955">З вÑртаннем грошай</translation>
<translation id="4636930964841734540">ІнфармацыÑ</translation>
@@ -990,6 +1016,7 @@
<translation id="4691835149146451662">Architecture-A (канверт)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Бакавы</translation>
+<translation id="4702656508969495934">Паказваюцца Ñ–Ð¼Ð³Ð½ÐµÐ½Ð½Ñ‹Ñ Ñубцітры. Ð’Ñ‹ можаце перайÑці да Ñ–Ñ…, выкарыÑтаўшы пераключальнік вокнаў</translation>
<translation id="4708268264240856090">ПадключÑнне перапынена</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />ЗапуÑціць дыÑгноÑтыку Ñеткі Windows<ph name="END_LINK" /></translation>
@@ -1003,6 +1030,7 @@
<translation id="4738601419177586157">Прапанова пошуку: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Кіраваць паролÑмі…</translation>
<translation id="4744603770635761495">Выканальны шлÑÑ…</translation>
+<translation id="4749011317274908093">Ð’Ñ‹ перайшлі Ñž Ñ€Ñжым інкогніта</translation>
<translation id="4750917950439032686">Ваша Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ (напрыклад, паролі або нумары крÑдытных картак) пры адпраўцы на гÑÑ‚Ñ‹ Ñайт заÑтаецца прыватнай.</translation>
<translation id="4756388243121344051">&amp;ГіÑторыÑ</translation>
<translation id="4758311279753947758">Дадаць кантактную інфармацыю</translation>
@@ -1032,6 +1060,8 @@
<translation id="4813512666221746211">Памылка Ñеткі</translation>
<translation id="4816492930507672669">ДапаÑаваць да памераў Ñтаронкі</translation>
<translation id="4819347708020428563">ЗбіраецеÑÑ Ð·Ð¼ÑнÑць анатацыі Ñž Ñтандартным выглÑдзе?</translation>
+<translation id="4825507807291741242">Моцны</translation>
+<translation id="4838327282952368871">Летуценны</translation>
<translation id="484462545196658690">Ðўтаматычна</translation>
<translation id="4850886885716139402">ПраглÑдзець</translation>
<translation id="485316830061041779">ÐÑмецкаÑ</translation>
@@ -1168,6 +1198,7 @@
<translation id="5314967030527622926">СтварÑнне брашур</translation>
<translation id="5316812925700871227">ПавÑрнуць Ñупраць гадзіннікавай ÑÑ‚Ñ€Ñлкі</translation>
<translation id="5317780077021120954">Захаваць</translation>
+<translation id="5321288445143113935">МакÑімальны памер</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> з <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Выбраць ÐºÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð½Ñ‹Ñ Ð·Ð²ÐµÑткі</translation>
<translation id="5327248766486351172">ІмÑ</translation>
@@ -1175,11 +1206,13 @@
<translation id="5332219387342487447">СпоÑаб даÑтаўкі</translation>
<translation id="5333022057423422993">Браўзер Chrome выÑвіў, што пароль, Ñкі вы толькі што выкарыÑталі, быў раÑкрыты пры ўцечцы даных. Мы Ñ€Ñкамендуем вам абараніць Ñвае ÑžÐ»Ñ–ÐºÐ¾Ð²Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹, праверыўшы Ð·Ð°Ñ…Ð°Ð²Ð°Ð½Ñ‹Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ–.</translation>
<translation id="5334013548165032829">ПадрабÑÐ·Ð½Ñ‹Ñ ÑÑ–ÑÑ‚ÑÐ¼Ð½Ñ‹Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñ‹</translation>
+<translation id="5334145288572353250">Захаваць адраÑ?</translation>
<translation id="5340250774223869109">Праграма заблакіравана</translation>
<translation id="534295439873310000">Прылады NFC</translation>
<translation id="5344579389779391559">ГÑта Ñтаронка можа паÑпрабаваць Ñпагнаць з Ð²Ð°Ñ Ð³Ñ€Ð¾ÑˆÑ‹</translation>
<translation id="5355557959165512791">Ðаведаць Ñайт <ph name="SITE" /> зараз нельга: Ñго Ñертыфікат адкліканы. Звычайна ÑÐµÑ‚ÐºÐ°Ð²Ñ‹Ñ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÑ– Ñ– атакі – чаÑÐ¾Ð²Ð°Ñ Ð·'Ñва, таму гÑта Ñтаронка будзе, хутчÑй за ÑžÑÑ‘, працаваць пазней.</translation>
<translation id="536296301121032821">Ðе ўдалоÑÑ Ð·Ð°Ñ…Ð°Ð²Ð°Ñ†ÑŒ налады палітыкі</translation>
+<translation id="5363309033720083897">ÐдмініÑтратар дазволіў гÑÑ‚Ñ‹ паÑлÑдоўны порт</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="5386426401304769735">Ланцужок Ñертыфікатаў Ð´Ð»Ñ Ð³Ñтага Ñайта змÑшчае Ñертыфікат, падпіÑаны з выкарыÑтаннем алгарытму SHA-1.</translation>
@@ -1188,6 +1221,7 @@
<translation id="5398772614898833570">РÑклама заблакіравана</translation>
<translation id="5400836586163650660">ШÑры</translation>
<translation id="540969355065856584">Серверу не ўдалоÑÑ Ð´Ð°ÐºÐ°Ð·Ð°Ñ†ÑŒ, што гÑта <ph name="DOMAIN" />; Ñертыфікат бÑÑпекі гÑтага Ñайта не раÑпазнаецца Ñк Ñапраўдны. Прычынай могуць быць нÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ або зламыÑнік, Ñкі Ñпрабуе перахапіць падключÑнне.</translation>
+<translation id="541143247543991491">Воблака (у маштабе ÑÑ–ÑÑ‚Ñмы)</translation>
<translation id="541416427766103491">Укладчык 4</translation>
<translation id="5421136146218899937">Выдаліць гіÑторыю праглÑдаў...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> запытвае дазвол адпраўлÑць вам апавÑшчÑнні</translation>
@@ -1201,6 +1235,7 @@
<translation id="5455374756549232013">ÐÐµÐ´Ð°Ð¿ÑƒÑˆÑ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ð¼ÐµÑ‚ÐºÐ° чаÑу палітыкі</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" />}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="5463625433003343978">Ідзе пошук прылад...</translation>
<translation id="5469868506864199649">ІтальÑнÑкаÑ</translation>
<translation id="5470861586879999274">&amp;Ðдрабіць змену</translation>
<translation id="5478437291406423475">B6/C4 (канверт)</translation>
@@ -1250,7 +1285,6 @@
<translation id="5624120631404540903">Кіраваць паролÑмі</translation>
<translation id="5629630648637658800">Ðе ўдалоÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ñ–Ñ†ÑŒ налады палітыкі</translation>
<translation id="5631439013527180824">ÐеÑапраўдны маркер Ð´Ð»Ñ ÐºÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ñ€Ñ‹Ð»Ð°Ð´Ð°Ð¹</translation>
-<translation id="5632627355679805402">Вашы Ð´Ð°Ð½Ñ‹Ñ Ð±Ñ‹Ð»Ñ– зашыфраваны <ph name="BEGIN_LINK" />паролем Google<ph name="END_LINK" /> <ph name="TIME" />. УвÑдзіце Ñго, каб запуÑціць Ñінхранізацыю.</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="5644090287519800334">Зрух відарыÑа па воÑÑ– X, бок 1</translation>
@@ -1289,12 +1323,12 @@
<translation id="5785756445106461925">ÐÐºÑ€Ð°Ð¼Ñ Ñ‚Ð°Ð³Ð¾, на гÑтай Ñтаронцы Ñ‘Ñць Ñ–Ð½ÑˆÑ‹Ñ Ñ€ÑÑурÑÑ‹, ÑÐºÑ–Ñ Ð½Ðµ з'ÑўлÑюцца бÑÑпечнымі: Ñны могуць быць прагледжаны іншымі Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð¿ÐµÑ€Ð°Ð´Ð°Ñ‡Ñ‹, а такÑама могуць быць мадыфікаваны зламыÑнікам з мÑтай змÑніць выглÑд Ñтаронкі.</translation>
<translation id="5786044859038896871">Запоўніць Ð´Ð°Ð½Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ–?</translation>
<translation id="578633867165174378">Браўзер Chrome выÑвіў, што пароль, Ñкі вы толькі што выкарыÑталі, быў раÑкрыты пры ўцечцы даных. Мы Ñ€Ñкамендуем змÑніць Ñго зараз жа.</translation>
-<translation id="5798290721819630480">Ðдхіліць змены?</translation>
<translation id="5803412860119678065">Запоўніць наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð´Ð°Ð½Ñ‹Ñ: <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Дазволы</translation>
<translation id="5804427196348435412">выкарыÑтоўваць прылады NFC</translation>
<translation id="5810442152076338065">ПадключÑнне да дамена <ph name="DOMAIN" /> зашыфравана з дапамогай ÑаÑтарÑлага алгарытму шыфраваннÑ.</translation>
<translation id="5813119285467412249">&amp;Узнавіць дадаванне</translation>
+<translation id="5817918615728894473">Спалучыць</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Пры ажыццÑўленні плацÑжу Ñродкі Ñпішуцца з гÑтай карткі, але Ñе Ñапраўдны нумар не будзе абагулены з гÑтым Ñайтам. У мÑтах дадатковай бÑÑпекі будзе Ñтвораны чаÑовы код CVC.}one{Пры ажыццÑўленні плацÑжу Ñродкі Ñпішуцца з выбранай вамі карткі, але Ñе Ñапраўдны нумар не будзе абагулены з гÑтым Ñайтам. У мÑтах дадатковай бÑÑпекі будзе Ñтвораны чаÑовы код CVC.}few{Пры ажыццÑўленні плацÑжу Ñродкі Ñпішуцца з выбранай вамі карткі, але Ñе Ñапраўдны нумар не будзе абагулены з гÑтым Ñайтам. У мÑтах дадатковай бÑÑпекі будзе Ñтвораны чаÑовы код CVC.}many{Пры ажыццÑўленні плацÑжу Ñродкі Ñпішуцца з выбранай вамі карткі, але Ñе Ñапраўдны нумар не будзе абагулены з гÑтым Ñайтам. У мÑтах дадатковай бÑÑпекі будзе Ñтвораны чаÑовы код CVC.}other{Пры ажыццÑўленні плацÑжу Ñродкі Ñпішуцца з выбранай вамі карткі, але Ñе Ñапраўдны нумар не будзе абагулены з гÑтым Ñайтам. У мÑтах дадатковай бÑÑпекі будзе Ñтвораны чаÑовы код CVC.}}</translation>
<translation id="5826507051599432481">Звычайнае Ñ–Ð¼Ñ (ЗІ)</translation>
<translation id="5838278095973806738">Раім не ўводзіць на гÑтым Ñайце ніÑкай канфідÑнцыÑльнай інфармацыі (паролÑÑž, даных крÑдытных картак Ñ– інш.), бо гÑту інфармацыю могуць украÑці зламыÑнікі.</translation>
@@ -1302,6 +1336,7 @@
<translation id="5855253129151731373">Ð†Ð¼Ñ Ñ…Ð¾Ñта гÑтага Ñайта падобнае да <ph name="LOOKALIKE_DOMAIN" />. ЗламыÑнікі чаÑам імітуюць Ñайты, уноÑÑчы невÑлікіÑ, амаль Ð½ÐµÐ¿Ñ€Ñ‹ÐºÐ¼ÐµÑ‚Ð½Ñ‹Ñ Ð·Ð¼Ñненні Ñž назву дамена.
Калі вы лічыце, што гÑта папÑÑ€Ñджанне паказваецца вам памылкова, перайдзіце па ÑпаÑылцы https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Выключана</translation>
<translation id="5862579898803147654">Укладчык 8</translation>
<translation id="5863847714970149516">Старонка, на Ñкую вы збіраецеÑÑ Ð¿ÐµÑ€Ð°Ð¹Ñці, можа Ñпагнаць з Ð²Ð°Ñ Ð³Ñ€Ð¾ÑˆÑ‹</translation>
<translation id="5866257070973731571">Дадаванне нумара Ñ‚Ñлефона</translation>
@@ -1318,6 +1353,7 @@
<translation id="5913377024445952699">Здымка Ñкрана прыпынена</translation>
<translation id="59174027418879706">Уключана</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{ВыкарыÑтоўваецца 1}one{ВыкарыÑтоўваецца #}few{ВыкарыÑтоўваецца #}many{ВыкарыÑтоўваецца #}other{ВыкарыÑтоўваецца #}}</translation>
<translation id="5921185718311485855">уключана</translation>
<translation id="5921639886840618607">Захаваць картку ва Уліковы Ð·Ð°Ð¿Ñ–Ñ Google?</translation>
<translation id="5922853866070715753">Ðмаль гатова</translation>
@@ -1337,6 +1373,7 @@
<translation id="5989320800837274978">Ðе ўказаны ні фікÑÐ°Ð²Ð°Ð½Ñ‹Ñ Ð¿Ñ€Ð¾ÐºÑÑ–-Ñерверы, ні URL-Ð°Ð´Ñ€Ð°Ñ ÑцÑÐ½Ð°Ñ€Ñ‹Ñ .pac.</translation>
<translation id="5992691462791905444">Z-падобны згіб (Ñ‚ÑÑ…Ð½Ñ–Ñ‡Ð½Ð°Ñ Ð´Ð°ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ‹Ñ)</translation>
<translation id="6000758707621254961">Вынікаў па запыце "<ph name="SEARCH_TEXT" />": <ph name="RESULT_COUNT" /></translation>
+<translation id="6006484371116297560">КлаÑічнаÑ</translation>
<translation id="6008122969617370890">Парадак "ад N да 1"</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Праверце Ñвае паролі</translation>
@@ -1358,6 +1395,7 @@
<translation id="6045164183059402045">Шаблон накладаннÑ</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="6049004884579590341">Каб выйÑці з поўнаÑкраннага Ñ€Ñжыму, націÑніце Ñ– ўтрымлівайце "<ph name="ACCELERATOR" />"</translation>
<translation id="6049488691372270142">ДаÑтаўка Ñтаронак</translation>
<translation id="6051221802930200923">Ð’Ñ‹ не можаце адкрыць вÑб-Ñайт <ph name="SITE" />, бо ён выкарыÑтоўвае механізм Ð·Ð°Ð¼Ð°Ñ†Ð¾ÑžÐ²Ð°Ð½Ð½Ñ Ñертыфікатаў. Ð¡ÐµÑ‚ÐºÐ°Ð²Ñ‹Ñ Ð¿Ð°Ð¼Ñ‹Ð»ÐºÑ– Ñ– атакі звычайна маюць чаÑовы характар. ХутчÑй за ÑžÑÑ‘, праз некаторы Ñ‡Ð°Ñ Ð²Ñб-Ñайт будзе працаваць зноў.</translation>
<translation id="6051898664905071243">КолькаÑць Ñтаронак:</translation>
@@ -1374,6 +1412,7 @@
<translation id="610911394827799129">Ðа Ñайце <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> могуць быць Ñ–Ð½ÑˆÑ‹Ñ Ñ„Ð¾Ñ€Ð¼Ñ‹ запіÑу гіÑторыі праглÑду Ñайтаў Ð´Ð»Ñ Ð²Ð°ÑˆÐ°Ð³Ð° Уліковага запіÑу Google</translation>
<translation id="6116338172782435947">ПраглÑдаць Ñ‚ÑкÑÑ‚ Ñ– відарыÑÑ‹, ÑÐºÐ°Ð¿Ñ–Ñ€Ð°Ð²Ð°Ð½Ñ‹Ñ Ñž буфер абмену</translation>
<translation id="6120179357481664955">Запомніць ідÑнтыфікатар UPI?</translation>
+<translation id="6123290840358279103">ПраглÑдзець віртуальную картку</translation>
<translation id="6124432979022149706">Злучальнікі Chrome Enterprise</translation>
<translation id="6146055958333702838">Праверце кабелі Ñ– перазагрузіце маршрутызатары, мадÑмы або Ñ–Ð½ÑˆÑ‹Ñ ÑеткавыÑ
прылады, ÑÐºÑ–Ñ Ð²Ñ‹ÐºÐ°Ñ€Ñ‹Ñтоўваеце.</translation>
@@ -1410,6 +1449,7 @@
<translation id="6289939620939689042">Колер Ñтаронкі</translation>
<translation id="6290238015253830360">РÑÐºÐ°Ð¼ÐµÐ½Ð´Ð°Ð²Ð°Ð½Ñ‹Ñ Ð²Ð°Ð¼ артыкулы з'ÑвÑцца тут</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Памочнік Google у Chrome ÑпынÑецца</translation>
<translation id="6305205051461490394">Сайт <ph name="URL" /> недаÑтупны.</translation>
<translation id="6312113039770857350">Ð’Ñб-Ñтаронка недаÑтупнаÑ</translation>
@@ -1435,6 +1475,7 @@
<translation id="6390200185239044127">Z-падобны згіб напалову Ñагнутага аркуша</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Палітыка, Ð·Ð°Ð´Ð°Ð´Ð·ÐµÐ½Ð°Ñ Ð°Ð´Ð¼Ñ–Ð½Ñ–Ñтратарам, блакіруе магчымаÑць уÑтаўлÑць Ñюды Ñлементы з Ñайта <ph name="ORIGIN_NAME" /></translation>
+<translation id="6398765197997659313">Выключыць поўнаÑкранны Ñ€Ñжым</translation>
<translation id="6401136357288658127">ГÑта палітыка ÑаÑтарÑла – выкарыÑтоўвайце замеÑÑ‚ Ñе "<ph name="NEW_POLICY" />".</translation>
<translation id="6404511346730675251">ЗмÑніце закладку</translation>
<translation id="6406765186087300643">C0 (канверт)</translation>
@@ -1447,7 +1488,6 @@
<translation id="6428450836711225518">Спраўдзіце Ñвой нумар Ñ‚Ñлефона</translation>
<translation id="6433490469411711332">Змена кантактных звеÑтак</translation>
<translation id="6433595998831338502">ХоÑÑ‚ <ph name="HOST_NAME" /> адмовіўÑÑ Ð°Ð´ падключÑннÑ.</translation>
-<translation id="6434309073475700221">Ðдхіліць</translation>
<translation id="6440503408713884761">Ігнаруецца</translation>
<translation id="6443406338865242315">Ð¯ÐºÑ–Ñ Ð¿Ð°ÑˆÑ‹Ñ€Ñнні Ñ– ўбудовы вы ÑžÑталÑвалі.</translation>
<translation id="6446163441502663861">Kahu (канверт)</translation>
@@ -1490,6 +1530,7 @@
<translation id="6624427990725312378">ÐšÐ°Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ</translation>
<translation id="6626291197371920147">Дадайце Ñапраўдны нумар карткі</translation>
<translation id="6628463337424475685">Пошук <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Ідзе пошук прылад USB...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ÐчыÑціць</translation>
@@ -1505,6 +1546,7 @@
<translation id="6671697161687535275">Выдаліць прапанову Ð°ÑžÑ‚Ð°Ð·Ð°Ð¿Ð°ÑžÐ½ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€Ð¼ з Chromium?</translation>
<translation id="6685834062052613830">Выйдзіце Ñ– завÑршыце наладжванне</translation>
<translation id="6687335167692595844">Запытаны памер шрыфту</translation>
+<translation id="6688743156324860098">Ðбнавіць…</translation>
<translation id="6689249931105087298">ÐдноÑны Ñа ÑціÑканнем чорных пунктаў</translation>
<translation id="6689271823431384964">Chrome прапаноўвае захоўваць карткі ва Уліковым запіÑе Google, бо вы ўвайшлі Ñž ÑÑ–ÑÑ‚Ñму. ГÑту функцыю можна выключыць у наладах. Ð†Ð¼Ñ ÑžÐ»Ð°Ð´Ð°Ð»ÑŒÐ½Ñ–ÐºÐ° карткі ўзÑта з вашага ўліковага запіÑу.</translation>
<translation id="6698381487523150993">Створаны:</translation>
@@ -1520,6 +1562,7 @@
<translation id="6744009308914054259">Пакуль чакаецца падключÑнне, вы можаце пачытаць артыкулы, ÑÐ¿Ð°Ð¼Ð¿Ð°Ð²Ð°Ð½Ñ‹Ñ Ñ€Ð°Ð½ÐµÐ¹.</translation>
<translation id="6753269504797312559">ЗначÑнне палітыкі</translation>
<translation id="6757797048963528358">Прылада перайшла Ñž Ñ€Ñжым Ñну.</translation>
+<translation id="6767985426384634228">Ðбнавіць адраÑ?</translation>
<translation id="6768213884286397650">Hagaki (паштоўка)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ФіÑлетавы</translation>
@@ -1542,6 +1585,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome ÑпраÑціў гÑту Ñтаронку Ð´Ð»Ñ Ð±Ð¾Ð»ÑŒÑˆ зручнага чытаннÑ. Ðн атрымаў зыходную Ñтаронку па небÑÑпечным падключÑнні.</translation>
<translation id="6891596781022320156">Узровень палітыкі не падтрымліваецца.</translation>
+<translation id="6895143722905299846">Віртуальны нумар:</translation>
<translation id="6895330447102777224">Картка пацверджана</translation>
<translation id="6897140037006041989">Ðгент карыÑтальніка</translation>
<translation id="6898699227549475383">ÐÑ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ‹Ñ (Ð)</translation>
@@ -1577,10 +1621,10 @@
<translation id="7004583254764674281">ВыкарыÑтоўваць Windows Hello Ð´Ð»Ñ Ñ…ÑƒÑ‚Ñ‡Ñйшага пацвÑрджÑÐ½Ð½Ñ ÐºÐ°Ñ€Ñ‚Ð°Ðº</translation>
<translation id="7006930604109697472">УÑÑ‘ роўна адправіць</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Ðалады змÑÐ½ÐµÐ½Ð½Ñ Ð¿Ð°Ð¼ÐµÑ€Ñƒ</translation>
<translation id="7014741021609395734">Маштаб</translation>
<translation id="7016992613359344582">ПлацÑжы могуць быць Ð°Ð´Ð½Ð°Ñ€Ð°Ð·Ð¾Ð²Ñ‹Ñ Ð°Ð±Ð¾ Ñ€ÑгулÑрныÑ, Ñ– Ñ–Ñ… можа быць цÑжка заўважыць.</translation>
<translation id="7029809446516969842">Паролі</translation>
+<translation id="7030436163253143341">Сертыфікат неÑапраўдны</translation>
<translation id="7031646650991750659">Ð¯ÐºÑ–Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹ Google Play вы ÑžÑталÑвалі.</translation>
<translation id="7050187094878475250">Ð’Ñ‹ Ñпрабавалі трапіць звÑрнуцца да дамена <ph name="DOMAIN" />, але Ñервер выдаў Ñертыфікат, чый Ñ‚Ñрмін дзеÑÐ½Ð½Ñ Ð·Ð°Ð½Ð°Ð´Ñ‚Ð° доўгі, каб быць надзейным.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ГÑта картка не можа быць зараз захавана}one{ГÑÑ‚Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ– не могуць быць зараз захаваны}few{ГÑÑ‚Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ– не могуць быць зараз захаваны}many{ГÑÑ‚Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ– не могуць быць зараз захаваны}other{ГÑÑ‚Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ– не могуць быць зараз захаваны}}</translation>
@@ -1650,12 +1694,14 @@
<translation id="7300012071106347854">Кобальтавы</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Ð’Ñ‹ÑокаÑ</translation>
+<translation id="7305756307268530424">ЗапуÑціць павальней</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Даведка па падключÑнні</translation>
<translation id="7323804146520582233">Схаваць раздзел "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">ПеравызначÑнне лакальнага ўліковага запіÑу прылады</translation>
<translation id="7333654844024768166">Ð’Ñ‹ толькі што ўвÑлі Ñвой пароль на Ñайце, вÑдомым падманнымі паводзінамі. Chromium Ñ€Ñкамендуе неадкладна змÑніць пароль на Ñайтах <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> Ñ– на іншых Ñайтах, дзе выкарыÑтоўваецца гÑÑ‚Ñ‹ пароль.</translation>
<translation id="7334320624316649418">&amp;Паўтарыць змÑненне парадку</translation>
+<translation id="7337248890521463931">Паказваць больш радкоў</translation>
<translation id="7337706099755338005">ÐедаÑтупна на вашай платформе.</translation>
<translation id="733923710415886693">Сертыфікат Ñервера не быў раÑкрыты Ñž адпаведнаÑці Ñа Ñтандартам "ПразрыÑтаÑць Ñертыфікатаў".</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1663,6 +1709,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Камандны радок</translation>
<translation id="7359588939039777303">РÑклама заблакіравана.</translation>
+<translation id="7363096869660964304">Ðле памÑтайце, што вы не ÑтановіцеÑÑ Ð½Ñбачнымі. Праца Ñž Ñ€Ñжыме інкогніта не дазволіць вам Ñхаваць Ñвае дзеÑнні Ñž інтÑрнÑце ад працадаўцы, інтÑрнÑÑ‚-правайдара Ñ– наведаных вÑб-Ñайтаў.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />. Каб дадаваць адраÑÑ‹ Ñ– кіраваць імі праз налады Chrome, націÑніце Tab, затым Enter</translation>
<translation id="7365849542400970216">Ці даваць Ñайтам знаць, калі вы карыÑтаецеÑÑ Ð¿Ñ€Ñ‹Ð»Ð°Ð´Ð°Ð¹?</translation>
<translation id="7372973238305370288">вынік пошуку</translation>
@@ -1673,7 +1720,9 @@
<translation id="7378594059915113390">Элементы ÐºÑ–Ñ€Ð°Ð²Ð°Ð½Ð½Ñ Ð¼ÑƒÐ»ÑŒÑ‚Ñ‹Ð¼ÐµÐ´Ñ‹Ð¹Ð½Ñ‹Ð¼ змеÑцівам</translation>
<translation id="7378627244592794276">РвоÑÑŒ i не!</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ÐедаÑтаÑоўна</translation>
<translation id="7390545607259442187">Пацвердзіце картку</translation>
+<translation id="7392089738299859607">Ðбнавіць адраÑ</translation>
<translation id="7399802613464275309">Праверка бÑÑпекі</translation>
<translation id="7400418766976504921">URL-адраÑ</translation>
<translation id="7403591733719184120">Прылада "<ph name="DEVICE_NAME" />" знаходзіцца пад кіраваннем</translation>
@@ -1689,6 +1738,7 @@
&lt;li&gt;Каб даведацца, Ñк назаўжды выдаліць гÑта праграмнае забеÑпÑчÑнне з вашага камп'ютара, наведайце Ñтаронку &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Даведачны цÑнтр Chrome&lt;/a&gt;.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Шырокі фармат</translation>
+<translation id="7410471291937727359">Мілы</translation>
<translation id="7416351320495623771">Кіраваць паролÑмі…</translation>
<translation id="7419106976560586862">ШлÑÑ… да профілю</translation>
<translation id="7437289804838430631">Дадаць кантактную інфармацыю</translation>
@@ -1704,7 +1754,7 @@
<translation id="7481312909269577407">Далей</translation>
<translation id="7485870689360869515">Ð”Ð°Ð½Ñ‹Ñ Ð½Ðµ знойдзены.</translation>
<translation id="7495528107193238112">ГÑта змеÑціва заблакіравана. Каб вырашыць праблему, звÑрніцеÑÑ Ð´Ð° ўладальніка Ñайта.</translation>
-<translation id="7498234416455752244">РÑдагаваць далей</translation>
+<translation id="7498193950643227031">Пры змÑненні памеру праграма можа паводзіць ÑÑбе нечакана. ЦÑпер вы можаце абмÑжоўваць магчымаÑць змÑнÑць памер праграм у раздзеле "<ph name="SETTINGS" />".</translation>
<translation id="7503664977220660814">Ð’Ñ‹ толькі што ўвÑлі Ñвой пароль на Ñайце, вÑдомым падманнымі паводзінамі. Chromium Ñ€Ñкамендуе праверыць Ð·Ð°Ñ…Ð°Ð²Ð°Ð½Ñ‹Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ– на Ñайтах <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> Ñ– на іншых Ñайтах, дзе выкарыÑтоўваецца гÑÑ‚Ñ‹ пароль.</translation>
<translation id="7508255263130623398">Ðтрыманы з палітыкі ідÑнтыфікатар прылады пуÑÑ‚Ñ‹ або не Ñупадае з бÑгучым ідÑнтыфікатарам прылады</translation>
<translation id="7508870219247277067">Цёмна-зÑлёны</translation>
@@ -1724,6 +1774,7 @@
<translation id="7548892272833184391">Выпраўленне памылак падключÑннÑ</translation>
<translation id="7549584377607005141">Ð”Ð»Ñ Ð¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ð°Ð³Ð° паказу Ñтаронкі патрабуюцца ÑžÐ²ÐµÐ´Ð·ÐµÐ½Ñ‹Ñ Ñ€Ð°Ð½ÐµÐ¹ даныÑ. Можна адправіць гÑÑ‚Ñ‹Ñ Ð´Ð°Ð½Ñ‹Ñ ÑÑˆÑ‡Ñ Ñ€Ð°Ð·, але тым Ñамым будуць паўтораны дзеÑнні, Ð²Ñ‹ÐºÐ°Ð½Ð°Ð½Ñ‹Ñ Ð½Ð° гÑтай Ñтаронцы раней.</translation>
<translation id="7550637293666041147">Ваша Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка Chrome Ñ– Ñ–Ð¼Ñ ÐºÐ°Ñ€Ñ‹Ñтальніка на прыладзе</translation>
+<translation id="755279583747225797">Дзейнічае Ð¿Ñ€Ð¾Ð±Ð½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ</translation>
<translation id="7552846755917812628">ПаÑпрабуйце наÑтупнае:</translation>
<translation id="7554475479213504905">Перазагрузіць Ñ– ÑžÑÑ‘ роўна паказаць</translation>
<translation id="7554791636758816595">ÐÐ¾Ð²Ð°Ñ ÑžÐºÐ»Ð°Ð´ÐºÐ°</translation>
@@ -1742,7 +1793,6 @@
<translation id="7610193165460212391">ЗначÑнне параметра знаходзіцца па-за межамі дыÑпазону (<ph name="VALUE" />).</translation>
<translation id="7613889955535752492">Да: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Каб паглÑдзець паролі або кіраваць імі Ñž наладах Chrome, націÑніце Tab, затым Enter</translation>
-<translation id="7615602087246926389">У Ð²Ð°Ñ ÑƒÐ¶Ð¾ Ñ‘Ñць даныÑ, Ð·Ð°ÑˆÑ‹Ñ„Ñ€Ð°Ð²Ð°Ð½Ñ‹Ñ Ð· дапамогай іншай верÑÑ–Ñ– Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð£Ð»Ñ–ÐºÐ¾Ð²Ð°Ð³Ð° запіÑу Google. УвÑдзіце гÑÑ‚Ñ‹ пароль ніжÑй.</translation>
<translation id="7616645509853975347">ÐдмініÑтратар уключыў злучальнікі Chrome Enterprise Connectors у вашым браўзеры. У злучальнікаў Ñ‘Ñць доÑтуп да некаторых вашых даных.</translation>
<translation id="7619838219691048931">Канцавы аркуш</translation>
<translation id="762844065391966283">Па адным за раз</translation>
@@ -1807,13 +1857,12 @@
<translation id="782886543891417279">Сетка Wi-Fi, Ñкую вы выкарыÑтоўваеце (<ph name="WIFI_NAME" />), можа запатрабаваць ад Ð²Ð°Ñ Ð½Ð°Ð²ÐµÐ´Ð°Ñ†ÑŒ Ñе Ñтаронку ўваходу.</translation>
<translation id="7836231406687464395">Postfix (канверт)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ÐÑма}=1{1 праграма (<ph name="EXAMPLE_APP_1" />)}=2{2 праграмы (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# праграма (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}few{# праграмы (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}many{# праграм (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# праграмы (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Ðле памÑтайце, што вы не ÑтановіцеÑÑ Ð½Ñбачнымі. Праца Ñž Ñ€Ñжыме інкогніта не дазволіць вам Ñхаваць Ñвае дзеÑнні Ñž інтÑрнÑце ад працадаўцы, інтÑрнÑÑ‚-правайдара Ñ– наведаных вÑб-Ñайтаў.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Ðдкрываць файлы, выкарыÑтоўваючы ÑупаÑтаўленне тыпаў файлаў.</translation>
<translation id="7862185352068345852">Закрыць Ñайт?</translation>
<translation id="7865448901209910068">ÐÐ°Ð¹Ð»ÐµÐ¿ÑˆÐ°Ñ Ñ…ÑƒÑ‚ÐºÐ°Ñць</translation>
<translation id="7874263914261512992">Ð’Ñ‹ толькі што ўвÑлі Ñвой пароль на Ñайце, вÑдомым падманнымі паводзінамі. Chrome Ñ€Ñкамендуе праверыць Ð·Ð°Ñ…Ð°Ð²Ð°Ð½Ñ‹Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ– на Ñайтах <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> Ñ– на іншых Ñайтах, дзе выкарыÑтоўваецца гÑÑ‚Ñ‹ пароль.</translation>
<translation id="7878562273885520351">Ваш пароль можа быць раÑкрыты</translation>
+<translation id="7880146494886811634">Захаваць адраÑ</translation>
<translation id="7882421473871500483">Карычневы</translation>
<translation id="7887683347370398519">Праверце код CVC Ñ– паўтарыце Ñпробу</translation>
<translation id="7887885240995164102">Уключыць Ñ€Ñжым "Ð’Ñ–Ð´Ð°Ñ€Ñ‹Ñ Ñƒ відарыÑе"</translation>
@@ -1821,6 +1870,7 @@
<translation id="7894280532028510793">Калі напіÑанне правільнае, <ph name="BEGIN_LINK" />паÑпрабуйце запуÑціць дыÑгноÑтыку Ñеткі<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (канверт)</translation>
<translation id="7931318309563332511">ÐевÑдома</translation>
+<translation id="793209273132572360">Ðбнавіць адраÑ?</translation>
<translation id="7932579305932748336">Пакрыццё</translation>
<translation id="79338296614623784">УвÑдзіце Ñапраўдны нумар Ñ‚Ñлефона</translation>
<translation id="7934052535022478634">Ðплата завершана</translation>
@@ -1891,6 +1941,7 @@
<translation id="8175796834047840627">Chrome прапаноўвае захоўваць карткі ва Уліковым запіÑе Google, бо вы ўвайшлі Ñž ÑÑ–ÑÑ‚Ñму. ГÑту функцыю можна выключыць у наладах.</translation>
<translation id="8176440868214972690">ÐдмініÑтратар гÑтай прылады адправіў на наÑÑ‚ÑƒÐ¿Ð½Ñ‹Ñ Ð²Ñб-Ñайты пÑÑžÐ½Ñ‹Ñ Ð·Ð²ÐµÑткі (напрыклад, налады або палітыкі).</translation>
<translation id="8184538546369750125">ВыкарыÑтоўваць Ð³Ð»Ð°Ð±Ð°Ð»ÑŒÐ½Ñ‹Ñ ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ñ‹Ñ Ð½Ð°Ð»Ð°Ð´Ñ‹ (дазволіць)</translation>
+<translation id="8193086767630290324">ДзеÑнні з данымі, пазначанымі Ñк канфідÑнцыÑльныÑ</translation>
<translation id="8194797478851900357">&amp;Ðдрабіць перамÑшчÑнне</translation>
<translation id="8201077131113104583">Ðедапушчальны URL-Ð°Ð´Ñ€Ð°Ñ Ð°Ð±Ð½Ð°ÑžÐ»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¿Ð°ÑˆÑ‹Ñ€ÑÐ½Ð½Ñ Ð· ідÑнтыфікатарам "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Зводка па заказе</translation>
@@ -1913,6 +1964,7 @@
<translation id="8249296373107784235">СкаÑаваць</translation>
<translation id="8249320324621329438">ÐпошнÑе абнаўленне:</translation>
<translation id="8253091569723639551">Патрабуецца Ð°Ð´Ñ€Ð°Ñ Ð´Ð»Ñ Ð²Ñ‹ÑÑ‚Ð°ÑžÐ»ÐµÐ½Ð½Ñ Ñ€Ð°Ñ…ÑƒÐ½ÐºÐ°Ñž</translation>
+<translation id="8257387598443225809">ГÑта праграма Ñтворана Ð´Ð»Ñ Ð¼Ð°Ð±Ñ–Ð»ÑŒÐ½Ñ‹Ñ… прылад</translation>
<translation id="825929999321470778">Паказаць уÑе Ð·Ð°Ñ…Ð°Ð²Ð°Ð½Ñ‹Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ–</translation>
<translation id="8261506727792406068">Выдаліць</translation>
<translation id="8262952874573525464">Сшыванне па краі знізу</translation>
@@ -2036,7 +2088,6 @@
<translation id="8719528812645237045">Ðекалькі дзірак зверху</translation>
<translation id="8725066075913043281">Паўтарыць Ñпробу</translation>
<translation id="8726549941689275341">Памер Ñтаронкі:</translation>
-<translation id="8728672262656704056">Ð’Ñ‹ перайшлі Ñž Ñ€Ñжым інкогніта</translation>
<translation id="8730621377337864115">Гатова</translation>
<translation id="8731544501227493793">Кнопка "Кіраваць паролÑмі". Каб паглÑдзець паролі або кіраваць імі Ñž наладах Chrome, націÑніце Enter</translation>
<translation id="8734529307927223492">Вашай прыладай <ph name="DEVICE_TYPE" /> кіруе <ph name="MANAGER" />.</translation>
@@ -2113,6 +2164,7 @@
<translation id="9020542370529661692">ГÑта Ñтаронка была перакладзена на наÑтупную мову: <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ÐеÑапраўдны)</translation>
+<translation id="9030265603405983977">Манахромны</translation>
<translation id="9035022520814077154">Памылка бÑÑпекі</translation>
<translation id="9038649477754266430">ВыкарыÑтоўваць ÑÑÑ€Ð²Ñ–Ñ Ð¿Ñ€Ð°Ð³Ð½Ð°Ð·Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð±Ð¾Ð»ÑŒÑˆ хуткай загрузкі Ñтаронак</translation>
<translation id="9039213469156557790">ÐÐºÑ€Ð°Ð¼Ñ Ñ‚Ð°Ð³Ð¾, на гÑтай Ñтаронцы Ñ‘Ñць Ñ–Ð½ÑˆÑ‹Ñ Ñ€ÑÑурÑÑ‹, ÑÐºÑ–Ñ Ð½Ðµ з'ÑўлÑюцца бÑÑпечнымі: Ñны могуць быць прагледжаны іншымі Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð¿ÐµÑ€Ð°Ð´Ð°Ñ‡Ñ‹, а такÑама могуць быць мадыфікаваны зламыÑнікам з мÑтай змÑніць паводзіны Ñтаронкі.</translation>
@@ -2136,6 +2188,7 @@
<translation id="91108059142052966">Згодна з палітыкай, зададзенай адмініÑтратарам, <ph name="APPLICATION_TITLE" /> не можа выкарыÑтоўвацца Ð´Ð»Ñ Ð°Ð±Ð°Ð³ÑƒÐ»ÑŒÐ²Ð°Ð½Ð½Ñ Ñкрана, калі на ім паказваецца прыватнае змеÑціва.</translation>
<translation id="9114524666733003316">ПацвÑрджаюцца Ð´Ð°Ð½Ñ‹Ñ ÐºÐ°Ñ€Ñ‚ÐºÑ–...</translation>
<translation id="9114581008513152754">ГÑÑ‚Ñ‹ браўзер не знаходзіцца пад кіраваннем кампаніі або іншай арганізацыі. Ðднак Ñама прылада можа знаходзіцца пад знешнім кіраваннем. <ph name="BEGIN_LINK" />Даведацца больш<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Свежы</translation>
<translation id="9119042192571987207">Запампавана</translation>
<translation id="9128016270925453879">Палітыкі загружаны</translation>
<translation id="9128870381267983090">ПадключыцеÑÑ Ð´Ð° Ñеткі</translation>
@@ -2154,6 +2207,7 @@
<translation id="9170848237812810038">&amp;Ðдрабіць</translation>
<translation id="9171296965991013597">ВыйÑці з праграмы?</translation>
<translation id="9173282814238175921">Ðдзіны дакумент, новы аркуш</translation>
+<translation id="9173995187295789444">Ідзе пошук прылад Bluetooth...</translation>
<translation id="917450738466192189">ÐÑправільны Ñертыфікат Ñервера.</translation>
<translation id="9174917557437862841">Кнопка пераключÑÐ½Ð½Ñ ÑžÐºÐ»Ð°Ð´Ð°Ðº. ÐаціÑніце Enter, каб пераключыцца на гÑту ўкладку</translation>
<translation id="9179703756951298733">Кіраваць плацÑжамі Ñ– звеÑткамі крÑдытнай карткі Ñž наладах Chrome</translation>
diff --git a/chromium/components/strings/components_strings_bg.xtb b/chromium/components/strings/components_strings_bg.xtb
index c14f60ebe62..d4dd719270a 100644
--- a/chromium/components/strings/components_strings_bg.xtb
+++ b/chromium/components/strings/components_strings_bg.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Ðко поÑтавите отметка, Chrome ще ÑъхранÑва копие на картата ви на това уÑтройÑтво Ñ Ñ†ÐµÐ» по-бързо попълване на формулÑри.</translation>
<translation id="1110994991967754504">Избиране на разрешението за <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;ОтмÑна на пренареждането</translation>
+<translation id="1123753900084781868">ПонаÑтоÑщем функциÑта „ÐадпиÑи на живо“ не е налице</translation>
<translation id="1125573121925420732">Възможно е да виждате Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ‡ÐµÑто, докато уебÑайтовете актуализират мерките Ñи за ÑигурноÑÑ‚. Това би Ñ‚Ñ€Ñбвало Ñкоро да Ñе подобри.</translation>
<translation id="112840717907525620">Кешът на правилото е в добро ÑÑŠÑтоÑние</translation>
<translation id="1130564665089811311">Бутон „Превод на Ñтраницата“. ÐатиÑнете Enter, за да преведете тази Ñтраница Ñ Google Преводач</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Името на уÑтройÑтвото ви</translation>
<translation id="124116460088058876">Още езици</translation>
<translation id="1243027604378859286">Ðвтор:</translation>
+<translation id="1246424317317450637">Удебелен текÑÑ‚</translation>
<translation id="1250759482327835220">За да платите по-бързо ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð¿ÑŠÑ‚, запазете картата, името и адреÑа Ñи за фактуриране в профила Ñи в Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (Ñинхронизирани)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ðко опитате да поÑетите уебÑайт и той не Ñе отварÑ, първо, пробвайте да изпълните Ñледните Ñтъпки за отÑтранÑване на неизправноÑти:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Променете паролата Ñи</translation>
<translation id="1484290072879560759">Избиране на Ð°Ð´Ñ€ÐµÑ Ð·Ð° доÑтавка</translation>
<translation id="1492194039220927094">РазпроÑтранение на правилата:</translation>
+<translation id="1495677929897281669">Ðазад към раздела</translation>
<translation id="1501859676467574491">Показване на картите от профила ви в Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Ще виждате това Ñъобщение за грешка, ако използвате портал за Wi-Fi, където Ñ‚Ñ€Ñбва да влезете в профил, преди да можете да преминете онлайн.&lt;/p&gt;
&lt;p&gt;За да отÑтраните грешката, кликнете върху &lt;strong&gt;Свързване&lt;/strong&gt; на Ñтраницата, коÑто опитвате да отворите.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Тази Ñтраница изпраща Ñъобщение</translation>
<translation id="153384715582417236">Това е вÑичко заÑега</translation>
<translation id="1536390784834419204">Превод на Ñтраницата</translation>
+<translation id="1539840569003678498">Сигналът е изпратен на:</translation>
<translation id="154408704832528245">Избиране на Ð°Ð´Ñ€ÐµÑ Ð·Ð° бърза доÑтавка</translation>
<translation id="1549470594296187301">ТрÑбва да активирате JavaScript, за да използвате тази функциÑ.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">КъÑата Ñтрана напред</translation>
<translation id="168693727862418163">СтойноÑтта на това правило не бе потвърдена ÑпрÑмо Ñъответната Ñхема и ще бъде пренебрегната.</translation>
<translation id="168841957122794586">Сертификатът на Ñървъра Ñъдържа Ñлаб криптографÑки ключ.</translation>
+<translation id="1696290444144917273">Преглед на данните за виртуалната карта</translation>
<translation id="1697532407822776718">Готово!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Сървърът не можа да докаже, че е <ph name="DOMAIN" />. Сертификатът му за ÑигурноÑÑ‚ е от утре. Това може да Ñе дължи на неправилно конфигуриране или на прехващане на връзката ви от извършител на атака.}other{Сървърът не можа да докаже, че е <ph name="DOMAIN" />. Сертификатът му за ÑигурноÑÑ‚ е от # дни в бъдещето. Това може да Ñе дължи на неправилно конфигуриране или на прехващане на връзката ви от извършител на атака.}}</translation>
<translation id="1710259589646384581">ОС</translation>
+<translation id="1711234383449478798">Пренебрегнато, защото <ph name="POLICY_NAME" /> не е „<ph name="VALUE" />“.</translation>
<translation id="1712552549805331520"><ph name="URL" /> иÑка да ÑъхранÑва за поÑтоÑнно данни на Ð»Ð¾ÐºÐ°Ð»Ð½Ð¸Ñ Ð²Ð¸ компютър</translation>
<translation id="1713628304598226412">Тава 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">ПощенÑка ÐºÑƒÑ‚Ð¸Ñ 3</translation>
<translation id="1718029547804390981">Документът е твърде голÑм за добавÑне на поÑÑнениÑ</translation>
<translation id="1721424275792716183">* Полето е задължително</translation>
+<translation id="1727613060316725209">Сертификатът е валиден</translation>
<translation id="1727741090716970331">ДобавÑне на валиден номер на карта</translation>
<translation id="1728677426644403582">Преглеждате Ð¸Ð·Ñ…Ð¾Ð´Ð½Ð¸Ñ ÐºÐ¾Ð´ на уеб Ñтраница</translation>
<translation id="173080396488393970">Този тип карта не Ñе поддържа</translation>
@@ -244,7 +251,6 @@
изиÑкваща за вÑички заÑвки към него да Ñе прилага правило за източник. Ð¢Ñ Ð¾Ð±Ð°Ñ‡Ðµ е неправилно образувана, поради което браузърът не може да изпълни заÑвката ви за <ph name="SITE" />. Операторите на Ñайтове могат да използват правилата за източник,
за да конфигурират ÑигурноÑтта и други ÑвойÑтва за даден Ñайт.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">МолÑ, актуализирайте пропуÑка Ñи за Ñинхронизиране.</translation>
<translation id="1787142507584202372">Тук ще Ñе показват отворените ви раздели</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Възможни Ñа нÑколко дейÑтвиÑ. ÐатиÑкайте Tab, за да преминавате циклично между Ñ‚ÑÑ…</translation>
@@ -277,6 +283,7 @@
<translation id="1919345977826869612">Реклами</translation>
<translation id="1919367280705858090">Получаване на помощ за конкретно Ñъобщение за грешка</translation>
<translation id="192020519938775529">{COUNT,plural, =0{ÐÑма}=1{1 Ñайт}other{# Ñайта}}</translation>
+<translation id="1924727005275031552">Ðов</translation>
<translation id="1945968466830820669">Възможно е да загубите доÑтъп до профила Ñи в организациÑта или ÑамоличноÑтта ви да бъде открадната. Chromium препоръчва да промените паролата Ñи Ñега.</translation>
<translation id="1947454675006758438">Телбодиране горе вдÑÑно</translation>
<translation id="1958218078413065209">Ðай-виÑокиÑÑ‚ ви резултат е <ph name="SCORE" />.</translation>
@@ -299,12 +306,14 @@
<translation id="2042213636306070719">Тава 7</translation>
<translation id="204357726431741734">Влезте в профила Ñи в Google, за да използвате запазените в него пароли</translation>
<translation id="2053111141626950936">Страниците на <ph name="LANGUAGE" /> нÑма да Ñе превеждат.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Когато тази контрола е включена и ÑÑŠÑтоÑнието е активно, Chrome Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ Ð´Ð¾ ÐºÐ¾Ñ Ð³Ð¾Ð»Ñма група от хора, или кохорта, е най-Ñходна Ñкорошната ви активноÑÑ‚ при Ñърфиране. Рекламодателите могат да избират реклами за групата, а активноÑтта ви при Ñърфиране оÑтава чаÑтна на уÑтройÑтвото ви. Групата ви Ñе актуализира вÑеки ден.}=1{Когато тази контрола е включена и ÑÑŠÑтоÑнието е активно, Chrome Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ Ð´Ð¾ ÐºÐ¾Ñ Ð³Ð¾Ð»Ñма група от хора, или кохорта, е най-Ñходна Ñкорошната ви активноÑÑ‚ при Ñърфиране. Рекламодателите могат да избират реклами за групата, а активноÑтта ви при Ñърфиране оÑтава чаÑтна на уÑтройÑтвото ви. Групата ви Ñе актуализира вÑеки ден.}other{Когато тази контрола е включена и ÑÑŠÑтоÑнието е активно, Chrome Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ Ð´Ð¾ ÐºÐ¾Ñ Ð³Ð¾Ð»Ñма група от хора, или кохорта, е най-Ñходна Ñкорошната ви активноÑÑ‚ при Ñърфиране. Рекламодателите могат да избират реклами за групата, а активноÑтта ви при Ñърфиране оÑтава чаÑтна на уÑтройÑтвото ви. Групата ви Ñе актуализира на вÑеки {NUM_DAYS} дни.}}</translation>
<translation id="2053553514270667976">ПощенÑки код</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 предложение}other{# предложениÑ}}</translation>
<translation id="2071692954027939183">ИзвеÑтиÑта бÑха блокирани автоматично, защото обикновено не ги разрешавате</translation>
<translation id="2079545284768500474">ОтмÑна</translation>
<translation id="20817612488360358">За използване Ñа зададени ÑиÑтемни наÑтройки за прокÑи Ñървъра, но е поÑочена и изрична конфигурациÑ.</translation>
<translation id="2082238445998314030">Резултат <ph name="RESULT_NUMBER" /> от <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Запазване…</translation>
<translation id="2088086323192747268">Бутон „Управление на Ñинхронизирането“. ÐатиÑнете Enter, за да управлÑвате данните, които да Ñе Ñинхронизират, от наÑтройките на Chrome</translation>
<translation id="2091887806945687916">Звук</translation>
<translation id="2094505752054353250">ÐеÑъответÑтвие в домейна</translation>
@@ -377,6 +386,7 @@
<translation id="2317259163369394535">ИзиÑкват Ñе потребителÑко име и парола за <ph name="DOMAIN" />.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, изтича на <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">ÐаÑтройката Ñе контролира от админиÑтратора ви</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> иÑка да Ñе Ñдвои</translation>
<translation id="2344028582131185878">Ðвтоматични изтеглÑниÑ</translation>
<translation id="2346319942568447007">Копирано от Ð²Ð°Ñ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ðµ</translation>
<translation id="2354001756790975382">Други отметки</translation>
@@ -384,8 +394,10 @@
<translation id="2355395290879513365">Извършители на атаки може да Ñа в ÑÑŠÑтоÑние да видÑÑ‚ изображениÑта, които преглеждате на този Ñайт, и да ви подведат, като ги променÑÑ‚.</translation>
<translation id="2356070529366658676">Попитайте ме</translation>
<translation id="2357481397660644965">УÑтройÑтвото ви Ñе управлÑва от <ph name="DEVICE_MANAGER" />, а профилът ви Ñе управлÑва от <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{След по-малко от един ден}=1{След един ден}other{След {NUM_DAYS} дни}}</translation>
<translation id="2359629602545592467">ÐÑколко</translation>
<translation id="2359808026110333948">Ðапред</translation>
+<translation id="2359961752320758691">Ðомерът на виртуалната ви карта е приложен.</translation>
<translation id="2367567093518048410">Ðиво</translation>
<translation id="2372464001869762664">След като потвърдите картата Ñи, данните за Ð½ÐµÑ Ð¾Ñ‚ профила ви в Google ще бъдат Ñподелени Ñ Ñ‚Ð¾Ð·Ð¸ Ñайт. Ще намерите кода за проверка в подробноÑтите за профила ви в Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -396,6 +408,7 @@
<translation id="239429038616798445">Този начин на доÑтавка не Ñе поддържа. Опитайте Ñ Ð´Ñ€ÑƒÐ³.</translation>
<translation id="2396249848217231973">&amp;ОтмÑна на изтриването</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Стар</translation>
<translation id="2413528052993050574">Сървърът не можа да докаже, че е <ph name="DOMAIN" />; възможно е Ñертификатът му за ÑигурноÑÑ‚ да е оттеглен. Това може да Ñе дължи на неправилно конфигуриране или на прихващане на връзката ви от атакуващ.</translation>
<translation id="2414886740292270097">Тъмно</translation>
<translation id="2438874542388153331">Четворно перфориране отдÑÑно</translation>
@@ -423,10 +436,10 @@
<translation id="2521385132275182522">Телбодиране долу вдÑÑно</translation>
<translation id="2523886232349826891">Запазено Ñамо на това уÑтройÑтво</translation>
<translation id="2524461107774643265">ДобавÑне на още информациÑ</translation>
-<translation id="2526590354069164005">Работен плот</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{и още 1}other{и още #}}</translation>
<translation id="2536110899380797252">ДобавÑне на адреÑ</translation>
<translation id="2539524384386349900">Откриване</translation>
+<translation id="2541219929084442027">Страниците, които преглеждате в разделите в режим „инкогнито“, нÑма да оÑтанат в иÑториÑта на браузъра, хранилището за „биÑквитки“ или иÑториÑта на Ñ‚ÑŠÑ€Ñенето, Ñлед като затворите вÑички раздели в този режим. Изтеглените от Ð²Ð°Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ðµ или Ñъздадените от Ð²Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ¸ обаче ще бъдат запазени.</translation>
<translation id="2544644783021658368">Един документ</translation>
<translation id="254947805923345898">СтойноÑтта на правилото не е валидна.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> изпрати невалиден отговор.</translation>
@@ -446,6 +459,7 @@
<translation id="2629325967560697240">За да използвате най-виÑокото ниво на ÑигурноÑÑ‚ на Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />включете подобрената защита<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">IP адреÑÑŠÑ‚ на Ñървъра на <ph name="HOST_NAME" /> не можа да бъде намерен.</translation>
<translation id="2639739919103226564">СъÑтоÑние:</translation>
+<translation id="264810637653812429">ÐÑма намерени ÑъвмеÑтими уÑтройÑтва.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. ÐатиÑнете Tab и Ñлед това – Enter, за да изчиÑтите иÑториÑта на Ñърфиране, „биÑквитките“, кеша и др. в наÑтройките на Chrome</translation>
<translation id="2650446666397867134">ДоÑтъпът до файла бе отказан</translation>
@@ -490,6 +504,7 @@
<translation id="2799223571221894425">Стартиране отново</translation>
<translation id="2803306138276472711">Google БезопаÑно Ñърфиране наÑкоро <ph name="BEGIN_LINK" />откри злонамерен Ñофтуер<ph name="END_LINK" /> на <ph name="SITE" />. УебÑайтовете, които обикновено Ñа надеждни, понÑкога Ñе заразÑват Ñ Ð¾Ð¿Ð°Ñен Ñофтуер.</translation>
<translation id="2807052079800581569">ÐŸÐ¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° изображението по оÑта Y</translation>
+<translation id="2820957248982571256">Сканира Ñе...</translation>
<translation id="2824775600643448204">Лента за адреÑи и за Ñ‚ÑŠÑ€Ñене</translation>
<translation id="2826760142808435982">Връзката е шифрована и удоÑтоверена поÑредÑтвом <ph name="CIPHER" /> и използва <ph name="KX" /> като механизъм за обмен на ключове.</translation>
<translation id="2835170189407361413">ИзчиÑтване на формулÑра</translation>
@@ -497,6 +512,8 @@
<translation id="2850739647070081192">Invite (плик)</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="2859806420264540918">Ðа този Ñайт Ñе показват натрапчиви или подвеждащи реклами.</translation>
+<translation id="287596039013813457">ПриÑтелÑко</translation>
+<translation id="2876489322757410363">Ще напуÑнете режим „инкогнито“, за да платите във външно приложение. ИÑкате ли да продължите?</translation>
<translation id="2878197950673342043">КръÑтоÑано Ñгъване</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Разположение на прозорците</translation>
@@ -546,7 +563,6 @@
<translation id="3060227939791841287">C9 (плик)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />. ÐатиÑнете Tab и Ñлед това Enter, за да Ñтартирате проверка на безопаÑноÑтта от наÑтройките на Chrome</translation>
<translation id="3061707000357573562">УÑлуга за корекции</translation>
-<translation id="3064966200440839136">Ще напуÑнете режим „инкогнито“, за да платите във външно приложение. ИÑкате ли да продължите?</translation>
<translation id="306573536155379004">Играта е Ñтартирана.</translation>
<translation id="3080254622891793721">Графика</translation>
<translation id="3086579638707268289">ÐктивноÑтта ви в мрежата Ñе наблюдава</translation>
@@ -569,7 +585,6 @@
<translation id="315504272643575312">Профилът ви Ñе управлÑва от <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">ВъзÑтановÑване</translation>
<translation id="3162559335345991374">Използваната от Ð²Ð°Ñ Wi-Fi мрежа може да изиÑква да поÑетите Ñтраницата й за вход.</translation>
-<translation id="3167968892399408617">Страниците, които преглеждате в разделите в режим „инкогнито“, нÑма да оÑтанат в иÑториÑта на браузъра, хранилището за „биÑквитки“ или иÑториÑта на Ñ‚ÑŠÑ€Ñенето, Ñлед като затворите вÑички раздели в този режим. Изтеглените от Ð²Ð°Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ðµ или Ñъздадените от Ð²Ð°Ñ Ð¾Ñ‚Ð¼ÐµÑ‚ÐºÐ¸ обаче ще бъдат запазени.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">ОÑтров</translation>
<translation id="3176929007561373547">За да Ñе уверите, че прокÑи Ñървърът работи,
@@ -595,10 +610,12 @@
<translation id="3229041911291329567">ИнформациÑта за верÑиÑта на уÑтройÑтвото и браузъра</translation>
<translation id="323107829343500871">Въведете кода за проверка за <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Важното Ñъдържание на този Ñайт да Ñе открива винаги</translation>
+<translation id="3249845759089040423">ПриÑтно</translation>
<translation id="3252266817569339921">френÑки</translation>
<translation id="3266793032086590337">СтойноÑÑ‚ (неÑъвмеÑтима)</translation>
<translation id="3268451620468152448">Отворени раздели</translation>
<translation id="3270847123878663523">&amp;ОтмÑна на пренареждането</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> иÑка да Ñе Ñвърже</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">ОрганизациÑта ви (<ph name="ENROLLMENT_DOMAIN" />) изпрати извеÑтна информациÑ, като например наÑтройки или правила, до долупоÑочените уебÑайтове.</translation>
<translation id="3282497668470633863">ДобавÑне на името на картодържателÑ</translation>
@@ -651,6 +668,7 @@
<translation id="3428151540071562330">Един или повече от URI адреÑите на шаблон за Ñървър в DnsOverHttpsTemplates Ñа невалидни и нÑма да Ñе използват.</translation>
<translation id="3431636764301398940">Запазване на картата на това уÑтройÑтво</translation>
<translation id="3432601291244612633">ЗатварÑне на Ñтраницата</translation>
+<translation id="3435738964857648380">СигурноÑÑ‚</translation>
<translation id="3435896845095436175">Ðктивиране</translation>
<translation id="3438829137925142401">Използване на паролите, запазени в профила ви в Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -693,7 +711,10 @@
<translation id="3584299510153766161">Двойно перфориране в долната чаÑÑ‚</translation>
<translation id="3586931643579894722">Скриване на подробноÑтите</translation>
<translation id="3587738293690942763">Среден</translation>
+<translation id="3590643883886679995">Данните за вход в профила ще бъдат Ñъхранени на това уÑтройÑтво, Ñлед като излезете от режим „инкогнито“.</translation>
+<translation id="359126217934908072">МеÑец/година:</translation>
<translation id="3592413004129370115">Italian (плик)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Можете да зададете повторно групата Ñи по вÑÑко време. ПриÑъединÑването към нова група отнема около един ден.}=1{Можете да зададете повторно групата Ñи по вÑÑко време. ПриÑъединÑването към нова група отнема около един ден.}other{Можете да зададете повторно групата Ñи по вÑÑко време. ПриÑъединÑването към нова група отнема около {NUM_DAYS} дни.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Приложението е блокирано от админиÑтратора ви</translation>
<translation id="3608932978122581043">ÐžÑ€Ð¸ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸ подаване</translation>
@@ -702,13 +723,13 @@
<translation id="3615877443314183785">Въведете валидна дата на изтичане</translation>
<translation id="36224234498066874">ИзчиÑтване на данните за Ñърфирането...</translation>
<translation id="362276910939193118">ЦÑлата иÑториÑ</translation>
-<translation id="3625635938337243871">Данните за вход в профила ще бъдат Ñъхранени на това уÑтройÑтво, Ñлед като излезете от режим „инкогнито“.</translation>
<translation id="3630155396527302611">Ðко браузърът вече е в ÑпиÑъка Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸ Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½ доÑтъп до мрежата, опитайте
да го премахнете оттам и да го добавите отново.</translation>
<translation id="3630699740441428070">Мрежовата ви връзка е конфигурирана от админиÑтраторите на това уÑтройÑтво, което може да им даде възможноÑÑ‚ да виждат Ð¼Ñ€ÐµÐ¶Ð¾Ð²Ð¸Ñ Ð²Ð¸ трафик, включително кои уебÑайтове поÑещавате.</translation>
<translation id="3631244953324577188">Биометрика</translation>
<translation id="3633738897356909127">Бутон „Ðктуализиране на Chrome“. ÐатиÑнете Enter, за да актуализирате Chrome от наÑтройките</translation>
<translation id="3634530185120165534">Тава 5</translation>
+<translation id="3637662659967048211">Запазване в профила в Google</translation>
<translation id="3640766068866876100">Index-4 x 6-Ext</translation>
<translation id="3642638418806704195">Приложение:</translation>
<translation id="3650584904733503804">Потвърждаването е уÑпешно</translation>
@@ -749,6 +770,7 @@
<translation id="3781428340399460090">Ñрко розово</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth уÑтройÑтва</translation>
+<translation id="3787675388804467730">Ðомер на виртуална карта</translation>
<translation id="3787705759683870569">Изтича на <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Размер 16</translation>
<translation id="3789841737615482174">ИнÑталиране</translation>
@@ -768,6 +790,7 @@
<translation id="3841184659773414994">Манипулатори на файлове</translation>
<translation id="385051799172605136">Ðазад</translation>
<translation id="3858027520442213535">Ðктуализиране на датата и чаÑа</translation>
+<translation id="3881478300875776315">Показване на по-малко редове</translation>
<translation id="3884278016824448484">ИдентификационниÑÑ‚ номер на уÑтройÑтвото е неÑъвмеÑтим</translation>
<translation id="3885155851504623709">ЕнориÑ</translation>
<translation id="388632593194507180">УÑтановено е наблюдение</translation>
@@ -793,6 +816,7 @@
<translation id="397105322502079400">ИзчиÑлÑва Ñе...</translation>
<translation id="3973234410852337861">ХоÑÑ‚ÑŠÑ‚ <ph name="HOST_NAME" /> е блокиран</translation>
<translation id="3973357910713125165">Бутон за Ñтартиране на проверка на безопаÑноÑтта в Chrome. ÐатиÑнете Enter, за да Ñтартирате проверка от наÑтройките на браузъра</translation>
+<translation id="3986705137476756801">Изключване на „ÐадпиÑи на живо“ заÑега</translation>
<translation id="3987405730340719549">Chrome уÑтанови, че този Ñайт може да е фалшив или измамничеÑки.
Ðко ÑмÑтате, че това е грешка, молÑ, поÑетете https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -889,13 +913,14 @@
<translation id="4275830172053184480">РеÑтартиране на уÑтройÑтвото ви</translation>
<translation id="4277028893293644418">Повторно задаване на паролата</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Тази карта е запазена в профила ви в Google}other{Тези карти Ñа запазени в профила ви в Google}}</translation>
+<translation id="4287885627794386150">ÐžÑ‚Ð³Ð¾Ð²Ð°Ñ€Ñ Ð½Ð° уÑловиÑта за изпробване, но не е активно</translation>
<translation id="4297502707443874121">Миниизображение на Ñтраницата <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Разгъване</translation>
<translation id="4300675098767811073">ÐÑколко перфорации отдÑÑно</translation>
<translation id="4302514097724775343">ДокоÑнете динозавъра, за да играете</translation>
<translation id="4302965934281694568">Chou3 (плик)</translation>
<translation id="4305666528087210886">ÐÑма доÑтъп до файла</translation>
-<translation id="4305817255990598646">Превключване</translation>
+<translation id="4306529830550717874">Да Ñе запази ли адреÑÑŠÑ‚?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Блокиране (по подразбиране)</translation>
<translation id="4314815835985389558">Управление на Ñинхронизирането</translation>
@@ -922,6 +947,7 @@
<translation id="4377125064752653719">Ðаправихте опит да Ñе Ñвържете Ñ/ÑŠÑ <ph name="DOMAIN" />, но Ñървърът предoÑтави Ñертификат, анулиран от Ð¸Ð·Ð´Ð°Ñ‚ÐµÐ»Ñ Ñи. Това означава, че в никакъв Ñлучай не Ñ‚Ñ€Ñбва да Ñе доверÑвате на предÑтавените от Ñървъра идентификационни данни за ÑигурноÑÑ‚. Възможно е да Ñте Ñе Ñвързали Ñ Ð¸Ð·Ð²ÑŠÑ€ÑˆÐ¸Ñ‚ÐµÐ» на атака.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4390472908992056574">ПерифериÑ</translation>
+<translation id="4406883609789734330">ÐадпиÑи на живо</translation>
<translation id="4406896451731180161">резултата от Ñ‚ÑŠÑ€Ñенето</translation>
<translation id="4408413947728134509">„БиÑквитки“ <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Току-що въведохте паролата Ñи в измамничеÑки Ñайт. Chrome препоръчва да поÑетите <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> и другите Ñайтове, за които Ñ Ð¸Ð·Ð¿Ð¾Ð»Ð·Ð²Ð°Ñ‚Ðµ, и да Ñ Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ð¸Ñ‚Ðµ в Ñ‚ÑÑ… Ñега.</translation>
@@ -934,7 +960,6 @@
<translation id="4435702339979719576">пощенÑка картичка)</translation>
<translation id="443673843213245140">Използването на прокÑи Ñървър е деактивирано, но е поÑочена изрична негова конфигурациÑ.</translation>
<translation id="4464826014807964867">УебÑайтове, които разполагат Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ организациÑта ви</translation>
-<translation id="4466881336512663640">Промените във формулÑра ще бъдат заличени. ÐаиÑтина ли иÑкате да продължите?</translation>
<translation id="4476953670630786061">Този формулÑÑ€ не е защитен. Ðвтоматичното попълване е изключено.</translation>
<translation id="4477350412780666475">Следващ запиÑ</translation>
<translation id="4482953324121162758">Този Ñайт нÑма да Ñе превежда.</translation>
@@ -968,6 +993,7 @@
<translation id="4594403342090139922">&amp;ОтмÑна на изтриването</translation>
<translation id="4597348597567598915">Размер 8</translation>
<translation id="4600854749408232102">C6/C5 (плик)</translation>
+<translation id="4606870351894164739">ВъздейÑтващо</translation>
<translation id="4628948037717959914">Снимка</translation>
<translation id="4631649115723685955">ОпциÑта за връщане на пари при покупка е Ñвързана</translation>
<translation id="4636930964841734540">ИнформациÑ</translation>
@@ -987,6 +1013,7 @@
<translation id="4691835149146451662">Architecture-A (плик)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Страна</translation>
+<translation id="4702656508969495934">Показват Ñе надпиÑи на живо. Използвайте Ð¿Ñ€ÐµÐ²ÐºÐ»ÑŽÑ‡Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ð° прозорци, за да премеÑтите фокуÑа</translation>
<translation id="4708268264240856090">Връзката ви бе прекъÑната</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Стартирайте мрежова диагноÑтика в Windows<ph name="END_LINK" /></translation>
@@ -1000,6 +1027,7 @@
<translation id="4738601419177586157">Предложение за Ñ‚ÑŠÑ€Ñене на „<ph name="TEXT" />“</translation>
<translation id="4742407542027196863">Управление на паролите…</translation>
<translation id="4744603770635761495">Път към Ð¸Ð·Ð¿ÑŠÐ»Ð½Ð¸Ð¼Ð¸Ñ Ñ„Ð°Ð¹Ð»</translation>
+<translation id="4749011317274908093">Преминахте в режим „инкогнито“</translation>
<translation id="4750917950439032686">ИнформациÑта ви (например пароли или номера на кредитни карти) е чаÑтна, когато Ñе изпраща до този Ñайт.</translation>
<translation id="4756388243121344051">&amp;ИÑториÑ</translation>
<translation id="4758311279753947758">ДобавÑне на Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° връзка</translation>
@@ -1029,6 +1057,8 @@
<translation id="4813512666221746211">Грешка в мрежата</translation>
<translation id="4816492930507672669">Да Ñе побере в Ñтраницата</translation>
<translation id="4819347708020428563">ИÑкате ли да редактирате поÑÑнениÑта в ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð¸Ð·Ð³Ð»ÐµÐ´?</translation>
+<translation id="4825507807291741242">ВпечатлÑващо</translation>
+<translation id="4838327282952368871">Замечтано</translation>
<translation id="484462545196658690">Ðвтоматично</translation>
<translation id="4850886885716139402">Изглед</translation>
<translation id="485316830061041779">немÑки</translation>
@@ -1165,6 +1195,7 @@
<translation id="5314967030527622926">Дизайнер на брошури</translation>
<translation id="5316812925700871227">Завъртане обратно на чаÑовниковата Ñтрелка</translation>
<translation id="5317780077021120954">Запазване</translation>
+<translation id="5321288445143113935">Увеличено</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> от <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Избиране на Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° връзка</translation>
<translation id="5327248766486351172">Име</translation>
@@ -1172,11 +1203,13 @@
<translation id="5332219387342487447">Ðачин за доÑтавка</translation>
<translation id="5333022057423422993">Chrome разкри паролата, коÑто току-що използвахте, при нарушение на ÑигурноÑтта на данните. За да защитите профилите Ñи, ви препоръчваме да проверите запазените Ñи пароли.</translation>
<translation id="5334013548165032829">Подробните ÑиÑтемни региÑтрационни файлове</translation>
+<translation id="5334145288572353250">Да Ñе запази ли адреÑÑŠÑ‚?</translation>
<translation id="5340250774223869109">Приложението е блокирано</translation>
<translation id="534295439873310000">УÑтройÑтва Ñ NFC</translation>
<translation id="5344579389779391559">Тази Ñтраница може да опита да ви такÑува пари</translation>
<translation id="5355557959165512791">Ð’ момента не можете да поÑетите Ñайта <ph name="SITE" />, защото Ñертификатът му е анулиран. Обикновено грешките в мрежата и атаките Ñрещу Ð½ÐµÑ Ñа временни, така че тази Ñтраница вероÑтно ще работи по-къÑно.</translation>
<translation id="536296301121032821">СъхранÑването на наÑтройките за правилото не бе уÑпешно</translation>
+<translation id="5363309033720083897">Сериен порт, разрешен от админиÑтратора ви</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="5386426401304769735">Веригата от Ñертификати за този Ñайт Ñъдържа Ñертификат, подпиÑан Ñ SHA-1.</translation>
@@ -1185,6 +1218,7 @@
<translation id="5398772614898833570">Рекламите Ñа блокирани</translation>
<translation id="5400836586163650660">Ñиво</translation>
<translation id="540969355065856584">Сървърът не можа да докаже, че е <ph name="DOMAIN" />. ПонаÑтоÑщем Ñертификатът му за ÑигурноÑÑ‚ не е валиден. Това може да Ñе дължи на неправилно конфигуриране или на прихващане на връзката ви от извършител на атака.</translation>
+<translation id="541143247543991491">Облака (за цÑлата ÑиÑтема)</translation>
<translation id="541416427766103491">Стакер 4</translation>
<translation id="5421136146218899937">ИзчиÑтване на данните за Ñърфирането...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> иÑка да ви изпраща извеÑтиÑ</translation>
@@ -1198,6 +1232,7 @@
<translation id="5455374756549232013">Ðевалидно клеймо за дата и Ñ‡Ð°Ñ Ð½Ð° правилото</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" />}other{<ph name="CONTACT_PREVIEW" /> и още <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
+<translation id="5463625433003343978">ТърÑÑÑ‚ Ñе уÑтройÑтва...</translation>
<translation id="5469868506864199649">италианÑки</translation>
<translation id="5470861586879999274">&amp;ВъзÑтановÑване на редактирането</translation>
<translation id="5478437291406423475">B6/C4 (плик)</translation>
@@ -1247,7 +1282,6 @@
<translation id="5624120631404540903">Управление на паролите</translation>
<translation id="5629630648637658800">Зареждането на наÑтройките за правилото не бе уÑпешно</translation>
<translation id="5631439013527180824">Ðевалидно означение за управление на уÑтройÑтвото</translation>
-<translation id="5632627355679805402">Данните ви Ñа шифровани Ñ <ph name="BEGIN_LINK" />паролата ви за Google<ph name="END_LINK" /> от <ph name="TIME" />. Въведете Ñ, за да Ñтартирате Ñинхронизирането.</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="5644090287519800334">ИзмеÑтване на изображението от Ñтрана 1 по оÑта X</translation>
@@ -1286,12 +1320,12 @@
<translation id="5785756445106461925">ОÑвен това тази Ñтраница включва други реÑурÑи, които не Ñа защитени. Докато Ñе предават, те могат да бъдат видени от други хора и да бъдат модифицирани от извършител на атака, така че да Ñе промени изгледът на Ñтраницата.</translation>
<translation id="5786044859038896871">ИÑкате ли да Ñе попълнÑÑ‚ данните за кредитната ви карта?</translation>
<translation id="578633867165174378">Chrome разкри паролата, коÑто току-що използвахте, при нарушение на ÑигурноÑтта на данните. Препоръчваме ви да Ñ Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ð¸Ñ‚Ðµ Ñега.</translation>
-<translation id="5798290721819630480">Да Ñе отхвърлÑÑ‚ ли промените?</translation>
<translation id="5803412860119678065">ИÑкате ли да Ñе попълнÑÑ‚ данните за <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">РазрешениÑ</translation>
<translation id="5804427196348435412">Използване на уÑтройÑтва Ñ NFC</translation>
<translation id="5810442152076338065">Връзката ви Ñ/ÑŠÑ <ph name="DOMAIN" /> е шифрована Ñ Ð¾ÑтарÑл криптографÑки пакет.</translation>
<translation id="5813119285467412249">&amp;ВъзÑтановÑване на добавÑнето</translation>
+<translation id="5817918615728894473">СдвоÑване</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Тази карта ще бъде такÑувана, когато плащате, но реалниÑÑ‚ Ñ Ð½Ð¾Ð¼ÐµÑ€ нÑма да бъде Ñподелен Ñ Ñ‚Ð¾Ð·Ð¸ Ñайт. За допълнителна ÑигурноÑÑ‚ ще бъде генериран временен код за проверка.}other{Избраната от Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° ще бъде такÑувана, когато плащате, но реалниÑÑ‚ Ñ Ð½Ð¾Ð¼ÐµÑ€ нÑма да бъде Ñподелен Ñ Ñ‚Ð¾Ð·Ð¸ Ñайт. За допълнителна ÑигурноÑÑ‚ ще бъде генериран временен код за проверка.}}</translation>
<translation id="5826507051599432481">Общо име (CN)</translation>
<translation id="5838278095973806738">Ðе ви препоръчваме да въвеждате поверителна Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð² този Ñайт (например пароли или номера на кредитни карти), тъй като може да бъде открадната от извършители на атаки.</translation>
@@ -1299,6 +1333,7 @@
<translation id="5855253129151731373">Името на хоÑта за този Ñайт наподобÑва това на <ph name="LOOKALIKE_DOMAIN" />. ПонÑкога извършителите на атаки имитират Ñайтове, като правÑÑ‚ незначителни, труднозабележими промени в името на домейна.
Ðко ÑмÑтате, че това е грешка, молÑ, поÑетете https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Изключено</translation>
<translation id="5862579898803147654">Стакер 8</translation>
<translation id="5863847714970149516">Ðа Ñтраницата, коÑто иÑкате да поÑетите, е възможно да ви бъдат удържани ÑредÑтва</translation>
<translation id="5866257070973731571">ДобавÑне на телефонен номер</translation>
@@ -1315,6 +1350,7 @@
<translation id="5913377024445952699">ФункциÑта за заÑнемане на екрана е поÑтавена на пауза</translation>
<translation id="59174027418879706">Ðктивирано</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{Използва Ñе 1}other{Използват Ñе #}}</translation>
<translation id="5921185718311485855">Включено</translation>
<translation id="5921639886840618607">Картата да Ñе запази ли в профила в Google?</translation>
<translation id="5922853866070715753">Почти готово</translation>
@@ -1334,6 +1370,7 @@
<translation id="5989320800837274978">Ðе Ñа поÑочени нито фикÑирани прокÑи Ñървъри, нито URL Ð°Ð´Ñ€ÐµÑ Ð½Ð° Ñкрипт във формат .pac.</translation>
<translation id="5992691462791905444">Z-образно Ñгъване на A3 до размер A4</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> резултата за „<ph name="SEARCH_TEXT" />“</translation>
+<translation id="6006484371116297560">КлаÑичеÑка тема</translation>
<translation id="6008122969617370890">Подредба от N до 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Проверка на паролите ви</translation>
@@ -1355,6 +1392,7 @@
<translation id="6045164183059402045">Шаблон за налагане</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="6049004884579590341">ÐатиÑнете и задръжте |<ph name="ACCELERATOR" />| за изход от режима на цÑл екран</translation>
<translation id="6049488691372270142">Извеждане на Ñтраниците</translation>
<translation id="6051221802930200923">Ð’ момента не можете да поÑетите <ph name="SITE" />, защото уебÑайтът използва метод за допълнително потвърждаване на Ñертификатите. Обикновено грешките в мрежата и атаките Ñрещу Ð½ÐµÑ Ñа временни, така че тази Ñтраница вероÑтно ще работи по-къÑно.</translation>
<translation id="6051898664905071243">Брой Ñтраници:</translation>
@@ -1371,6 +1409,7 @@
<translation id="610911394827799129">Ð’ профила ви в Google може да има други видове иÑÑ‚Ð¾Ñ€Ð¸Ñ Ð½Ð° Ñърфиране, ÑъхранÑвани на Ð°Ð´Ñ€ÐµÑ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">Да преглежда текÑта и изображениÑта, копирани в буферната памет</translation>
<translation id="6120179357481664955">Помните ли Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¾Ð½Ð½Ð¸Ñ Ñи номер за UPI?</translation>
+<translation id="6123290840358279103">Преглед на виртуалната карта</translation>
<translation id="6124432979022149706">Конектори за Chrome Enterprise</translation>
<translation id="6146055958333702838">Проверете вÑички кабели и реÑтартирайте маршрутизаторите, модемите или другите мрежови
уÑтройÑтва, които може да използвате.</translation>
@@ -1407,6 +1446,7 @@
<translation id="6289939620939689042">ЦвÑÑ‚ на Ñтраницата</translation>
<translation id="6290238015253830360">Предложените ви Ñтатии ще Ñе показват тук</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">Код за ÑигурноÑÑ‚:</translation>
<translation id="6302269476990306341">Google ÐÑиÑтент в Chrome Ñе Ñпира</translation>
<translation id="6305205051461490394">ÐÑма доÑтъп до <ph name="URL" />.</translation>
<translation id="6312113039770857350">Уеб Ñтраницата не е налице</translation>
@@ -1432,6 +1472,7 @@
<translation id="6390200185239044127">Двойно Z-образно Ñгъване</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">ПоÑтавÑнето на Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ <ph name="ORIGIN_NAME" /> тук е блокирано от админиÑтраторÑки правила</translation>
+<translation id="6398765197997659313">Изход от цÑл екран</translation>
<translation id="6401136357288658127">Това правило е оттеглено. ВмеÑто него използвайте <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Редактиране на отметката</translation>
<translation id="6406765186087300643">C0 (плик)</translation>
@@ -1444,7 +1485,6 @@
<translation id="6428450836711225518">Потвърдете Ñ‚ÐµÐ»ÐµÑ„Ð¾Ð½Ð½Ð¸Ñ Ñи номер</translation>
<translation id="6433490469411711332">Редактиране на информациÑта за връзка</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> отказа да уÑтанови връзка.</translation>
-<translation id="6434309073475700221">ОтхвърлÑне</translation>
<translation id="6440503408713884761">Пренебрегнато</translation>
<translation id="6443406338865242315">Кои Ñ€Ð°Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð¸ приÑтавки Ñте инÑталирали</translation>
<translation id="6446163441502663861">Kahu (плик)</translation>
@@ -1487,6 +1527,7 @@
<translation id="6624427990725312378">Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° връзка</translation>
<translation id="6626291197371920147">ДобавÑне на валиден номер на карта</translation>
<translation id="6628463337424475685">ТърÑене Ñ/ÑŠÑ <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">ТърÑÑÑ‚ Ñе USB уÑтройÑтва...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ИзчиÑтване</translation>
@@ -1502,6 +1543,7 @@
<translation id="6671697161687535275">Предложението за формулÑри да Ñе премахне ли от Chromium?</translation>
<translation id="6685834062052613830">Излизане от профила и завършване на наÑтройването</translation>
<translation id="6687335167692595844">Размерът на шрифта е заÑвен</translation>
+<translation id="6688743156324860098">Ðктуализира Ñе…</translation>
<translation id="6689249931105087298">ОтноÑително Ñ ÐºÐ¾Ð¼Ð¿ÐµÐ½Ñиране на черните точки</translation>
<translation id="6689271823431384964">Chrome предлага да запази картите ви в профила ви в Google, защото Ñте влезли в него. Можете да промените това поведение от наÑтройките. Името на ÐºÐ°Ñ€Ñ‚Ð¾Ð´ÑŠÑ€Ð¶Ð°Ñ‚ÐµÐ»Ñ Ðµ от профила ви.</translation>
<translation id="6698381487523150993">Създадено:</translation>
@@ -1517,6 +1559,7 @@
<translation id="6744009308914054259">Докато чакате да Ñе уÑтанови връзка, можете да поÑетите Ñтраницата „ИзтеглÑниÑ“, за да четете офлайн Ñтатии.</translation>
<translation id="6753269504797312559">СтойноÑÑ‚ за правилото</translation>
<translation id="6757797048963528358">УÑтройÑтвото ви премина в ÑпÑщ режим.</translation>
+<translation id="6767985426384634228">Да Ñе актуализира ли адреÑÑŠÑ‚?</translation>
<translation id="6768213884286397650">Hagaki (пощенÑка картичка)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">виолетово</translation>
@@ -1539,6 +1582,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome опроÑти тази Ñтраница, за да улеÑни четенето Ñ. Оригиналната Ñтраница бе извлечена през незащитена връзка.</translation>
<translation id="6891596781022320156">Ðивото на правилото не Ñе поддържа.</translation>
+<translation id="6895143722905299846">Виртуален номер:</translation>
<translation id="6895330447102777224">Картата ви е потвърдена</translation>
<translation id="6897140037006041989">ПотребителÑки агент</translation>
<translation id="6898699227549475383">ÐžÑ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ (О)</translation>
@@ -1574,10 +1618,10 @@
<translation id="7004583254764674281">Използвайте Windows Hello, за да потвърждавате картите по-бързо</translation>
<translation id="7006930604109697472">Изпращане въпреки това</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ÐаÑтройки за преоразмерÑване</translation>
<translation id="7014741021609395734">Увеличение</translation>
<translation id="7016992613359344582">Тези такÑÑƒÐ²Ð°Ð½Ð¸Ñ Ð¼Ð¾Ð¶Ðµ да Ñа еднократни или повтарÑщи Ñе и е възможно да не Ñа Ñвни.</translation>
<translation id="7029809446516969842">Пароли</translation>
+<translation id="7030436163253143341">Сертификатът не е валиден</translation>
<translation id="7031646650991750659">Кои Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¾Ñ‚ Google Play Ñте инÑталирали</translation>
<translation id="7050187094878475250">Опитахте да Ñе Ñвържете Ñ/ÑŠÑ <ph name="DOMAIN" />, но Ñървърът предоÑтави Ñертификат, чийто период на валидноÑÑ‚ е твърде дълъг, за да е надежден.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Тази карта не може да бъде запазена в момента}other{Тези карти не могат да бъдат запазени в момента}}</translation>
@@ -1647,12 +1691,14 @@
<translation id="7300012071106347854">кобалтовоÑиньо</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />“</translation>
<translation id="7304030187361489308">ВиÑока</translation>
+<translation id="7305756307268530424">Стартиране Ñ Ð¿Ð¾-бавна ÑкороÑÑ‚</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Помощ при проблеми Ñ Ð²Ñ€ÑŠÐ·ÐºÐ°Ñ‚Ð°</translation>
<translation id="7323804146520582233">Скриване на ÑекциÑта „<ph name="SECTION" />“</translation>
<translation id="733354035281974745">Отменено от Ð»Ð¾ÐºÐ°Ð»Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð» на уÑтройÑтвото</translation>
<translation id="7333654844024768166">Току-що въведохте паролата Ñи в измамничеÑки Ñайт. Chromium препоръчва да поÑетите <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> и другите Ñайтове, за които Ñ Ð¸Ð·Ð¿Ð¾Ð»Ð·Ð²Ð°Ñ‚Ðµ, и да Ñ Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ð¸Ñ‚Ðµ в Ñ‚ÑÑ… Ñега.</translation>
<translation id="7334320624316649418">&amp;ВъзÑтановÑване на пренареждането</translation>
+<translation id="7337248890521463931">Показване на повече редове</translation>
<translation id="7337706099755338005">Ðе е налице за платформата ви.</translation>
<translation id="733923710415886693">Сертификатът на Ñървъра не е разкрит чрез ПрозрачноÑÑ‚ на Ñертификатите.</translation>
<translation id="734600844861828519">11 x 15</translation>
@@ -1660,6 +1706,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Команден ред</translation>
<translation id="7359588939039777303">Рекламите Ñа блокирани.</translation>
+<translation id="7363096869660964304">Сърфирането ви обаче не е невидимо. При преминаване в режим „инкогнито“ то не Ñе Ñкрива от Ñ€Ð°Ð±Ð¾Ñ‚Ð¾Ð´Ð°Ñ‚ÐµÐ»Ñ Ð²Ð¸ и от доÑтавчика ви на интернет уÑлуги, нито от уебÑайтовете, които поÑещавате.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />. ÐатиÑнете Tab и Ñлед това Enter, за да добавÑте адреÑи и да ги управлÑвате от наÑтройките на Chrome</translation>
<translation id="7365849542400970216">Да Ñе разреши ли доÑтъп до данните за използването на уÑтройÑтвото ви?</translation>
<translation id="7372973238305370288">резултат от Ñ‚ÑŠÑ€Ñенето</translation>
@@ -1670,7 +1717,9 @@
<translation id="7378594059915113390">Контроли за мултимедиÑ</translation>
<translation id="7378627244592794276">Ðе</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ðе е приложимо</translation>
<translation id="7390545607259442187">Потвърждаване на картата</translation>
+<translation id="7392089738299859607">Ðктуализиране на адреÑ</translation>
<translation id="7399802613464275309">Проверка на безопаÑноÑтта</translation>
<translation id="7400418766976504921">URL адреÑ</translation>
<translation id="7403591733719184120">УÑтройÑтвото ви <ph name="DEVICE_NAME" /> е управлÑвано</translation>
@@ -1685,6 +1734,7 @@
&lt;li&gt;ПоÑетете &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;ÐŸÐ¾Ð¼Ð¾Ñ‰Ð½Ð¸Ñ Ñ†ÐµÐ½Ñ‚ÑŠÑ€ на Chrome&lt;/a&gt;, за да научите как да премахнете за поÑтоÑнно Ñофтуера от компютъра Ñи.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Очарователно</translation>
<translation id="7416351320495623771">Управление на паролите…</translation>
<translation id="7419106976560586862">Път на потребителÑÐºÐ¸Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»</translation>
<translation id="7437289804838430631">ДобавÑне на Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° връзка</translation>
@@ -1700,7 +1750,7 @@
<translation id="7481312909269577407">Ðапред</translation>
<translation id="7485870689360869515">ÐÑма намерени данни.</translation>
<translation id="7495528107193238112">Това Ñъдържание е блокирано. Свържете Ñе ÑÑŠÑ ÑобÑтвеника на Ñайта, за да отÑтрани проблема.</translation>
-<translation id="7498234416455752244">Продължаване Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð°Ð½ÐµÑ‚Ð¾</translation>
+<translation id="7498193950643227031">Ðко го преоразмерите, може да Ñе държи по неочакван начин. Вече можете да ограничите възможноÑтта за преоразмерÑване на Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð² <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Току-що въведохте паролата Ñи в измамничеÑки Ñайт. Chromium препоръчва да проверите запазените Ñи пароли за <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> и други Ñайтове, на които понаÑтоÑщем използвате тази парола.</translation>
<translation id="7508255263130623398">ВърнатиÑÑ‚ от правилата идентификационен номер на уÑтройÑтвото е празен или не ÑъответÑтва на текущиÑ</translation>
<translation id="7508870219247277067">авокадовозелено</translation>
@@ -1720,6 +1770,7 @@
<translation id="7548892272833184391">ОтÑтранÑване на грешки във връзката</translation>
<translation id="7549584377607005141">За да Ñе покаже правилно тази уеб Ñтраница, Ñа необходими по-рано въведените от Ð²Ð°Ñ Ð´Ð°Ð½Ð½Ð¸. Можете да ги изпратите отново, но така ще повторите вÑÑко изпълнено от Ð½ÐµÑ Ð´ÐµÐ¹Ñтвие.</translation>
<translation id="7550637293666041147">ПотребителÑкото име на уÑтройÑтвото ви и в Chrome</translation>
+<translation id="755279583747225797">ЕкÑпериментът е активен</translation>
<translation id="7552846755917812628">Изпробвайте Ñледните Ñъвети:</translation>
<translation id="7554475479213504905">Презареждане и показване въпреки това</translation>
<translation id="7554791636758816595">Ðов раздел</translation>
@@ -1738,7 +1789,6 @@
<translation id="7610193165460212391">СтойноÑтта е извън обхват <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Валидна до: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. ÐатиÑнете Tab и Ñлед това – Enter, за да прегледате и управлÑвате паролите Ñи в наÑтройките на Chrome</translation>
-<translation id="7615602087246926389">Вече имате данни, които Ñа шифровани поÑредÑтвом друга верÑÐ¸Ñ Ð½Ð° паролата за профила ви в Google. МолÑ, въведете Ñ Ð¿Ð¾-долу.</translation>
<translation id="7616645509853975347">ÐдминиÑтраторът ви е включил Chrome Enterprise Connectors в браузъра ви. Тези конектори имат доÑтъп до нÑкои от данните ви.</translation>
<translation id="7619838219691048931">ПоÑледен лиÑÑ‚</translation>
<translation id="762844065391966283">Един по един</translation>
@@ -1803,13 +1853,12 @@
<translation id="782886543891417279">Използваната от Ð²Ð°Ñ Wi-Fi мрежа (<ph name="WIFI_NAME" />) може да изиÑква да поÑетите Ñтраницата й за вход.</translation>
<translation id="7836231406687464395">Postfix (плик)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ÐÑма}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">ÐžÑ‚Ð²Ð°Ñ€Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ðµ от аÑоциираните типове.</translation>
<translation id="7862185352068345852">ИÑкате ли да напуÑнете Ñайта?</translation>
<translation id="7865448901209910068">Ðай-добра ÑкороÑÑ‚</translation>
<translation id="7874263914261512992">Току-що въведохте паролата Ñи в измамничеÑки Ñайт. Chrome препоръчва да проверите запазените Ñи пароли за <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> и други Ñайтове, на които понаÑтоÑщем използвате тази парола.</translation>
<translation id="7878562273885520351">Възможно е паролата ви да е компрометирана</translation>
+<translation id="7880146494886811634">Запазване на адреÑ</translation>
<translation id="7882421473871500483">кафÑво</translation>
<translation id="7887683347370398519">Прегледайте кода за проверка и опитайте отново</translation>
<translation id="7887885240995164102">Преминаване в режим „Картина в картината“</translation>
@@ -1817,6 +1866,7 @@
<translation id="7894280532028510793">Ðко изпиÑването е правилно, <ph name="BEGIN_LINK" />Ñтартирайте мрежова диагноÑтика<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (плик)</translation>
<translation id="7931318309563332511">ÐеизвеÑтно</translation>
+<translation id="793209273132572360">Да Ñе актуализира ли адреÑÑŠÑ‚?</translation>
<translation id="7932579305932748336">Покритие</translation>
<translation id="79338296614623784">Въведете валиден телефонен номер</translation>
<translation id="7934052535022478634">Плащането бе извършено</translation>
@@ -1887,6 +1937,7 @@
<translation id="8175796834047840627">Chrome предлага да запази картите ви в профила ви в Google, защото Ñте влезли в него. Можете да промените това поведение от наÑтройките.</translation>
<translation id="8176440868214972690">ÐдминиÑтраторът на това уÑтройÑтво изпрати извеÑтна информациÑ, като например наÑтройки или правила, до долупоÑочените уебÑайтове.</translation>
<translation id="8184538546369750125">Използване на глобалната Ñтандартна ÑтойноÑÑ‚ (разрешаване)</translation>
+<translation id="8193086767630290324">ДейÑтвиÑ, предприети Ñ Ð´Ð°Ð½Ð½Ð¸, означени като поверителни</translation>
<translation id="8194797478851900357">&amp;ОтмÑна на премеÑтването</translation>
<translation id="8201077131113104583">Ðевалиден URL Ð°Ð´Ñ€ÐµÑ Ð·Ð° актуализиране на разширението Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ð¾Ð½ÐµÐ½ номер <ph name="EXTENSION_ID" />.</translation>
<translation id="8202097416529803614">Обобщена Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° поръчката</translation>
@@ -1909,6 +1960,7 @@
<translation id="8249296373107784235">ПрекратÑване</translation>
<translation id="8249320324621329438">ПоÑледно извличане:</translation>
<translation id="8253091569723639551">ÐдреÑÑŠÑ‚ за фактуриране е задължителен</translation>
+<translation id="8257387598443225809">Това приложение е предназначено за мобилни уÑтройÑтва</translation>
<translation id="825929999321470778">Показване на вÑички запазени пароли</translation>
<translation id="8261506727792406068">Изтриване</translation>
<translation id="8262952874573525464">Зашиване на Ð´Ð¾Ð»Ð½Ð¸Ñ Ñ€ÑŠÐ±</translation>
@@ -2032,7 +2084,6 @@
<translation id="8719528812645237045">ÐÑколко перфорации в горната чаÑÑ‚</translation>
<translation id="8725066075913043281">Опитайте отново</translation>
<translation id="8726549941689275341">Размер на Ñтраниците:</translation>
-<translation id="8728672262656704056">Преминахте в режим „инкогнито“</translation>
<translation id="8730621377337864115">Готово</translation>
<translation id="8731544501227493793">Бутон „Управление на паролите“. ÐатиÑнете Enter, за да прегледате и управлÑвате паролите в наÑтройките на Chrome</translation>
<translation id="8734529307927223492">ВашиÑÑ‚ <ph name="DEVICE_TYPE" /> Ñе управлÑва от <ph name="MANAGER" /></translation>
@@ -2109,6 +2160,7 @@
<translation id="9020542370529661692">Тази Ñтраница е преведена на <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(невалиден)</translation>
+<translation id="9030265603405983977">Монохромно</translation>
<translation id="9035022520814077154">Грешка в ÑигурноÑтта</translation>
<translation id="9038649477754266430">Използване на уÑлуга за предвиждане Ñ Ñ†ÐµÐ» по-бързо зареждане на Ñтраниците</translation>
<translation id="9039213469156557790">ОÑвен това тази Ñтраница включва други реÑурÑи, които не Ñа защитени. Докато Ñе предават, те могат да бъдат видени от други хора и да бъдат модифицирани от извършител на атака, така че да Ñе промени поведението на Ñтраницата.</translation>
@@ -2132,6 +2184,7 @@
<translation id="91108059142052966">СподелÑнето на екрана Ñ(ÑŠÑ) <ph name="APPLICATION_TITLE" />, когато Ñе вижда поверително Ñъдържание, е деактивирано от админиÑтраторÑки правила</translation>
<translation id="9114524666733003316">Картата Ñе потвърждава...</translation>
<translation id="9114581008513152754">Този браузър не Ñе управлÑва от дружеÑтво или друга организациÑ. Възможно е активноÑтта на уÑтройÑтвото да Ñе управлÑва извън Chrome. <ph name="BEGIN_LINK" />Ðаучете повече<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Свежо</translation>
<translation id="9119042192571987207">Качено</translation>
<translation id="9128016270925453879">Правилата Ñа заредени</translation>
<translation id="9128870381267983090">Свързване към мрежа</translation>
@@ -2150,6 +2203,7 @@
<translation id="9170848237812810038">&amp;ОтмÑна</translation>
<translation id="9171296965991013597">ИÑкате ли да затворите приложението?</translation>
<translation id="9173282814238175921">Един документ/нов лиÑÑ‚</translation>
+<translation id="9173995187295789444">Сканира Ñе за уÑтройÑтва Ñ Bluetooth...</translation>
<translation id="917450738466192189">Сертификатът на Ñървъра е невалиден.</translation>
<translation id="9174917557437862841">Бутон за превключване между раздели. ÐатиÑнете Enter, за да преминете към този раздел</translation>
<translation id="9179703756951298733">УправлÑвайте информациÑта Ñи за плащане и данните за кредитните Ñи карти в наÑтройките на Chrome</translation>
diff --git a/chromium/components/strings/components_strings_bn.xtb b/chromium/components/strings/components_strings_bn.xtb
index abc8565effc..aa3f82bc049 100644
--- a/chromium/components/strings/components_strings_bn.xtb
+++ b/chromium/components/strings/components_strings_bn.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">যদি চেক করা হয়, দà§à¦°à§à¦¤ ফরà§à¦® পূরণ করার জনà§à¦¯ à¦à¦‡ ডিভাইসে থাকা আপনার কারà§à¦¡à§‡à¦° à¦à¦•à¦Ÿà¦¿ কপি Chrome সà§à¦Ÿà§‹à¦° করবে৷</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> à¦à¦° জনà§à¦¯ অনà§à¦®à¦¤à¦¿ বেছে নিন</translation>
<translation id="1113869188872983271">&amp;পà§à¦¨à¦°à§à¦¬à¦¿à¦¨à§à¦¯à¦¾à¦¸à¦•à§‡ পূরà§à¦¬à¦¾à¦¬à¦¸à§à¦¥à¦¾à¦¯à¦¼ ফেরান</translation>
+<translation id="1123753900084781868">'লাইভ কà§à¦¯à¦¾à¦ªà¦¶à¦¨' ফিচারের সà§à¦¬à¦¿à¦§à¦¾ à¦à¦–নই পাওয়া যাবে না</translation>
<translation id="1125573121925420732">ওয়েবসাইটগà§à¦²à¦¿à¦° নিরাপতà§à¦¤à¦¾ আপডেট করার সময় সতরà§à¦•à¦¤à¦¾ দেখানো খà§à¦¬à¦‡ সà§à¦¬à¦­à¦¾à¦¬à¦¿à¦•à¥¤ à¦à¦Ÿà¦¿ শীঘà§à¦°à¦‡ উনà§à¦¨à¦¤ করা উচিত।</translation>
<translation id="112840717907525620">নীতি কà§à¦¯à¦¾à¦¶à§‡à¦Ÿà¦¿ ঠিক আছে</translation>
<translation id="1130564665089811311">'পৃষà§à¦ à¦¾ অনà§à¦¬à¦¾à¦¦ করà§à¦¨' বোতাম, Google Translate বà§à¦¯à¦¬à¦¹à¦¾à¦° করে à¦à¦‡ পৃষà§à¦ à¦¾ অনà§à¦¬à¦¾à¦¦ করতে Enter পà§à¦°à§‡à¦¸ করà§à¦¨à¥¤</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">আপনার ডিভাইসের নাম</translation>
<translation id="124116460088058876">আরও ভাষা</translation>
<translation id="1243027604378859286">লেখক:</translation>
+<translation id="1246424317317450637">বোলà§à¦¡</translation>
<translation id="1250759482327835220">পরেরবার আরও দà§à¦°à§à¦¤ পেমেনà§à¦Ÿ করা জনà§à¦¯ আপনার কারà§à¦¡, নাম à¦à¦¬à¦‚ বিলিং ঠিকানাটি Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡ সেভ করে রাখà§à¦¨à¥¤</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (সিঙà§à¦• হয়েছে)</translation>
<translation id="1256368399071562588">&lt;p&gt;আপনি যে ওয়েবসাইটে যেতে চান সেটি যদি না খোলে তাহলে পà§à¦°à¦¥à¦®à§‡ à¦à¦‡ ধাপগà§à¦²à¦¿ অনà§à¦¸à¦°à¦£ করে সমসà§à¦¯à¦¾à¦Ÿà¦¿à¦° সমাধান করার চেষà§à¦Ÿà¦¾ করà§à¦¨:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">আপনার পাসওয়ারà§à¦¡ পরিবরà§à¦¤à¦¨ করà§à¦¨</translation>
<translation id="1484290072879560759">শিপিং ঠিকানা বেছে নিন</translation>
<translation id="1492194039220927094">নীতি সংকà§à¦°à¦¾à¦¨à§à¦¤ পà§à¦¶:</translation>
+<translation id="1495677929897281669">টà§à¦¯à¦¾à¦¬à§‡ ফিরে যান</translation>
<translation id="1501859676467574491">আপনার Google Account থেকে কারà§à¦¡ দেখà§à¦¨</translation>
<translation id="1507202001669085618">&lt;p&gt;আপনি যদি à¦à¦®à¦¨ কোনও ওয়াই-ফাই পোরà§à¦Ÿà¦¾à¦² বà§à¦¯à¦¬à¦¹à¦¾à¦° করেন যেখানে অনলাইন হওয়ার জনà§à¦¯ সাইন-ইন করতে হয়, তাহলে à¦à¦‡ সমসà§à¦¯à¦¾à¦Ÿà¦¿ হতে পারে।&lt;/p&gt;
&lt;p&gt;à¦à¦‡ সমসà§à¦¯à¦¾à¦° সমাধান করতে, যে পৃষà§à¦ à¦¾à¦Ÿà¦¿ খà§à¦²à¦¤à§‡ চান সেটিতে &lt;strong&gt;কানেকà§à¦Ÿ করà§à¦¨&lt;/strong&gt; বোতামে কà§à¦²à¦¿à¦• করà§à¦¨à¥¤&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">à¦à¦‡ পৃষà§à¦ à¦¾à§Ÿ à¦à¦Ÿà¦¿ দেখানো হচà§à¦›à§‡</translation>
<translation id="153384715582417236">à¦à¦–ন à¦à¦‡ পরà§à¦¯à¦¨à§à¦¤à¦‡</translation>
<translation id="1536390784834419204">পৃষà§à¦ à¦¾à¦Ÿà¦¿ অনà§à¦¬à¦¾à¦¦ করà§à¦¨</translation>
+<translation id="1539840569003678498">রিপোরà§à¦Ÿ পাঠানো হয়েছে:</translation>
<translation id="154408704832528245">ডেলিভারি ঠিকানা বেছে নিন</translation>
<translation id="1549470594296187301">à¦à¦‡ বৈশিষà§à¦Ÿà§à¦¯à¦Ÿà¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করার জনà§à¦¯ জাভাসà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ চালৠকরা পà§à¦°à§Ÿà§‹à¦œà¦¨à¥¤</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">আগে ছোট পà§à¦°à¦¾à¦¨à§à¦¤</translation>
<translation id="168693727862418163">à¦à¦‡ নীতির মান সেটির সà§à¦•à¦¿à¦®à¦¾à¦° সাথে যাচাই করা যায়নি, তাই সেটি উপেকà§à¦·à¦¾ করা হবে।</translation>
<translation id="168841957122794586">সারà§à¦­à¦¾à¦° সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿà§‡ à¦à¦•à¦Ÿà¦¿ দà§à¦°à§à¦¬à¦² কà§à¦°à¦¿à¦ªà§à¦Ÿà§‹à¦—à§à¦°à¦¾à¦«à¦¿à¦• কী আছে৷</translation>
+<translation id="1696290444144917273">ভারà§à¦šà§à§Ÿà¦¾à¦² কারà§à¦¡à§‡à¦° বিবরণ দেখà§à¦¨</translation>
<translation id="1697532407822776718">আপনার সমসà§à¦¤ সেট আছে!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{à¦à¦‡ সারà§à¦­à¦¾à¦° যে <ph name="DOMAIN" /> তা à¦à¦Ÿà¦¿ পà§à¦°à¦®à¦¾à¦£ করতে পারেনি; à¦à¦° নিরাপতà§à¦¤à¦¾ সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿà¦Ÿà¦¿ আগামীকালের বলে মনে হচà§à¦›à§‡à¥¤ কোনও ভà§à¦² কনফিগারেশনের কারণে অথবা আপনার সংযোগে বাধাপà§à¦°à¦¦à¦¾à¦¨à¦•à¦¾à¦°à§€ কোনও আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€à¦° কারণে à¦à¦®à¦¨à¦Ÿà¦¿ হতে পারে।}one{à¦à¦‡ সারà§à¦­à¦¾à¦° যে <ph name="DOMAIN" /> তা à¦à¦Ÿà¦¿ পà§à¦°à¦®à¦¾à¦£ করতে পারেনি; à¦à¦° নিরাপতà§à¦¤à¦¾ সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿà¦Ÿà¦¿ আগামী # দিন পরের বলে মনে হচà§à¦›à§‡à¥¤ কোনও ভà§à¦² কনফিগারেশনের কারণে অথবা আপনার সংযোগে বাধাপà§à¦°à¦¦à¦¾à¦¨à¦•à¦¾à¦°à§€ কোনও আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€à¦° কারণে à¦à¦®à¦¨à¦Ÿà¦¿ হতে পারে।}other{à¦à¦‡ সারà§à¦­à¦¾à¦° যে <ph name="DOMAIN" /> তা à¦à¦Ÿà¦¿ পà§à¦°à¦®à¦¾à¦£ করতে পারেনি; à¦à¦° নিরাপতà§à¦¤à¦¾ সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿà¦Ÿà¦¿ আগামী # দিন পরের বলে মনে হচà§à¦›à§‡à¥¤ কোনও ভà§à¦² কনফিগারেশনের কারণে অথবা আপনার সংযোগে বাধাপà§à¦°à¦¦à¦¾à¦¨à¦•à¦¾à¦°à§€ কোনও আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€à¦° কারণে à¦à¦®à¦¨à¦Ÿà¦¿ হতে পারে।}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">à¦à¦¡à¦¼à¦¿à§Ÿà§‡ যাওয়া হয়েছে কারণ <ph name="VALUE" />-à¦à¦° নীতির মাধà§à¦¯à¦®à§‡ <ph name="POLICY_NAME" /> সেট করা হয়নি।</translation>
<translation id="1712552549805331520"><ph name="URL" /> সà§à¦¥à¦¾à§Ÿà§€à¦­à¦¾à¦¬à§‡ আপনার কমà§à¦ªà¦¿à¦‰à¦Ÿà¦¾à¦°à§‡ ডেটা সà§à¦Ÿà§‹à¦° করতে চায়</translation>
<translation id="1713628304598226412">টà§à¦°à§‡ ২</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">মেলবকà§à¦¸ ৩</translation>
<translation id="1718029547804390981">বà§à¦¯à¦¾à¦–à§à¦¯à¦¾à¦° জনà§à¦¯ ডকà§à¦®à§‡à¦¨à§à¦Ÿà§‡à¦° সাইজ বেশি বড়</translation>
<translation id="1721424275792716183">* à¦à¦‡ ফিলà§à¦¡à§‡ কিছৠলেখা পà§à¦°à§Ÿà§‹à¦œà¦¨</translation>
+<translation id="1727613060316725209">সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿà¦Ÿà¦¿ সঠিক</translation>
<translation id="1727741090716970331">সঠিক কারà§à¦¡ নমà§à¦¬à¦° যোগ করà§à¦¨</translation>
<translation id="1728677426644403582">আপনি à¦à¦•à¦Ÿà¦¿ ওয়েব পৃষà§à¦ à¦¾à¦° উৎস কোড দেখছেন</translation>
<translation id="173080396488393970">à¦à¦–ানে à¦à¦‡ ধরনের কারà§à¦¡ কাজ করে না</translation>
@@ -246,7 +253,6 @@
সাথে যোগাযোগ বা তা অà§à¦¯à¦¾à¦•à§à¦¸à§‡à¦¸ করতে পারছে না। সাইট অপারেটর কোনও সাইটের
নিরাপতà§à¦¤à¦¾ ও অনà§à¦¯à¦¾à¦¨à§à¦¯ পà§à¦°à¦ªà¦¾à¦°à§à¦Ÿà¦¿ কনফিগার করতে 'অরিজিন নীতি' বà§à¦¯à¦¬à¦¹à¦¾à¦° করতে পারে।</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">দয়া করে আপনার সিঙà§à¦• পাসফà§à¦°à§‡à¦œ আপডেট করà§à¦¨à§·</translation>
<translation id="1787142507584202372">আপনার খোলা টà§à¦¯à¦¾à¦¬à¦—à§à¦²à¦¿ à¦à¦–ানে দেখা যাবে</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, à¦à¦•à¦¾à¦§à¦¿à¦• কাজ করা যাবে, বিকলà§à¦ªà¦—à§à¦²à¦¿ à¦à¦• à¦à¦• করে দেখতে টà§à¦¯à¦¾à¦¬ টিপà§à¦¨</translation>
@@ -280,6 +286,7 @@
<translation id="1919345977826869612">বিজà§à¦žà¦¾à¦ªà¦¨</translation>
<translation id="1919367280705858090">কোনও নিরà§à¦¦à¦¿à¦·à§à¦Ÿ à¦à¦°à¦° মেসেজের বিষয়ে সাহাযà§à¦¯ পান</translation>
<translation id="192020519938775529">{COUNT,plural, =0{কিছà§à¦‡ নয়}=1{১টি সাইট}one{#টি সাইট}other{#টি সাইট}}</translation>
+<translation id="1924727005275031552">নতà§à¦¨</translation>
<translation id="1945968466830820669">আপনি নিজের পà§à¦°à¦¤à¦¿à¦·à§à¦ à¦¾à¦¨à§‡à¦° অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡à¦° অà§à¦¯à¦¾à¦•à§à¦¸à§‡à¦¸ হারাতে পারেন অথবা আপনার পরিচয় চà§à¦°à¦¿ হয়ে যেতে পারে। Chromium à¦à¦–নই আপনার পাসওয়ারà§à¦¡ পরিবরà§à¦¤à¦¨ করার আরà§à¦œà¦¿ জানাচà§à¦›à§‡à¥¤</translation>
<translation id="1947454675006758438">উপরের ডানদিকে সà§à¦Ÿà§‡à¦ªà¦² করà§à¦¨</translation>
<translation id="1958218078413065209">আপনার সরà§à¦¬à§‹à¦šà§à¦š সà§à¦•à§‹à¦° <ph name="SCORE" />।</translation>
@@ -302,12 +309,14 @@
<translation id="2042213636306070719">টà§à¦°à§‡ ৭</translation>
<translation id="204357726431741734">আপনার Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡ সেভ করা পাসওয়ারà§à¦¡ বà§à¦¯à¦¬à¦¹à¦¾à¦° করতে সাইন-ইন করà§à¦¨</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> ভাষার পৃষà§à¦ à¦¾ অনà§à¦¬à¦¾à¦¦ করা হবে না।</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{à¦à¦‡ কনà§à¦Ÿà§à¦°à§‹à¦² চালৠà¦à¦¬à¦‚ সà§à¦Ÿà§à¦¯à¦¾à¦Ÿà¦¾à¦¸ অà§à¦¯à¦¾à¦•à§à¦Ÿà¦¿à¦­ থাকলে আপনার সামà§à¦ªà§à¦°à¦¤à¦¿à¦• বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚-à¦à¦° ইতিহাস, আরও বড় কোন গà§à¦°à§à¦ª বা 'দল'-à¦à¦° সাথে সবচেয়ে বেশি মেলে, 'Chrome' তা নিরà§à¦§à¦¾à¦°à¦£ করে। বিজà§à¦žà¦¾à¦ªà¦¨à¦¦à¦¾à¦¤à¦¾à¦°à¦¾ গà§à¦°à§à¦ªà§‡à¦° জনà§à¦¯ বিজà§à¦žà¦¾à¦ªà¦¨ বেছে নিতে পারেন à¦à¦¬à¦‚ আপনার বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚-à¦à¦° ইতিহাস ডিভাইসে বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত রাখা হয়। আপনার গà§à¦°à§à¦ª পà§à¦°à¦¤à§à¦¯à§‡à¦•à¦¦à¦¿à¦¨ আপডেট করা হয়।}=1{à¦à¦‡ কনà§à¦Ÿà§à¦°à§‹à¦² চালৠà¦à¦¬à¦‚ সà§à¦Ÿà§à¦¯à¦¾à¦Ÿà¦¾à¦¸ অà§à¦¯à¦¾à¦•à§à¦Ÿà¦¿à¦­ থাকলে আপনার সামà§à¦ªà§à¦°à¦¤à¦¿à¦• বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚-à¦à¦° ইতিহাস, আরও বড় কোন গà§à¦°à§à¦ª বা 'দল'-à¦à¦° সাথে সবচেয়ে বেশি মেলে, 'Chrome' তা নিরà§à¦§à¦¾à¦°à¦£ করে। বিজà§à¦žà¦¾à¦ªà¦¨à¦¦à¦¾à¦¤à¦¾à¦°à¦¾ গà§à¦°à§à¦ªà§‡à¦° জনà§à¦¯ বিজà§à¦žà¦¾à¦ªà¦¨ বেছে নিতে পারেন à¦à¦¬à¦‚ আপনার বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚-à¦à¦° ইতিহাস ডিভাইসে বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত রাখা হয়। আপনার গà§à¦°à§à¦ª পà§à¦°à¦¤à§à¦¯à§‡à¦•à¦¦à¦¿à¦¨ আপডেট করা হয়।}one{à¦à¦‡ কনà§à¦Ÿà§à¦°à§‹à¦² চালৠà¦à¦¬à¦‚ সà§à¦Ÿà§à¦¯à¦¾à¦Ÿà¦¾à¦¸ অà§à¦¯à¦¾à¦•à§à¦Ÿà¦¿à¦­ থাকলে আপনার সামà§à¦ªà§à¦°à¦¤à¦¿à¦• বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚-à¦à¦° ইতিহাস, আরও বড় কোন গà§à¦°à§à¦ª বা 'দল'-à¦à¦° সাথে সবচেয়ে বেশি মেলে, 'Chrome' তা নিরà§à¦§à¦¾à¦°à¦£ করে। বিজà§à¦žà¦¾à¦ªà¦¨à¦¦à¦¾à¦¤à¦¾à¦°à¦¾ গà§à¦°à§à¦ªà§‡à¦° জনà§à¦¯ বিজà§à¦žà¦¾à¦ªà¦¨ বেছে নিতে পারেন à¦à¦¬à¦‚ আপনার বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚-à¦à¦° ইতিহাস ডিভাইসে বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত রাখা হয়। আপনার গà§à¦°à§à¦ª পà§à¦°à¦¤à¦¿ {NUM_DAYS} দিনে আপডেট করা হয়।}other{à¦à¦‡ কনà§à¦Ÿà§à¦°à§‹à¦² চালৠà¦à¦¬à¦‚ সà§à¦Ÿà§à¦¯à¦¾à¦Ÿà¦¾à¦¸ অà§à¦¯à¦¾à¦•à§à¦Ÿà¦¿à¦­ থাকলে আপনার সামà§à¦ªà§à¦°à¦¤à¦¿à¦• বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚-à¦à¦° ইতিহাস, আরও বড় কোন গà§à¦°à§à¦ª বা 'দল'-à¦à¦° সাথে সবচেয়ে বেশি মেলে, 'Chrome' তা নিরà§à¦§à¦¾à¦°à¦£ করে। বিজà§à¦žà¦¾à¦ªà¦¨à¦¦à¦¾à¦¤à¦¾à¦°à¦¾ গà§à¦°à§à¦ªà§‡à¦° জনà§à¦¯ বিজà§à¦žà¦¾à¦ªà¦¨ বেছে নিতে পারেন à¦à¦¬à¦‚ আপনার বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚-à¦à¦° ইতিহাস ডিভাইসে বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত রাখা হয়। আপনার গà§à¦°à§à¦ª পà§à¦°à¦¤à¦¿ {NUM_DAYS} দিনে আপডেট করা হয়।}}</translation>
<translation id="2053553514270667976">পিন কোড</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{১টি পà§à¦°à¦¸à§à¦¤à¦¾à¦¬}one{#টি পà§à¦°à¦¸à§à¦¤à¦¾à¦¬}other{#টি পà§à¦°à¦¸à§à¦¤à¦¾à¦¬}}</translation>
<translation id="2071692954027939183">আপনি সাধারণত বিজà§à¦žà¦ªà§à¦¤à¦¿ অনà§à¦®à§‹à¦¦à¦¨ না করার জনà§à¦¯ অটোমেটিক বà§à¦²à¦• হয়ে গেছে</translation>
<translation id="2079545284768500474">আগের অবসà§à¦¥à¦¾à§Ÿ ফিরà§à¦¨</translation>
<translation id="20817612488360358">সিসà§à¦Ÿà§‡à¦® পà§à¦°à¦•à§à¦¸à¦¿ সেটিংস বà§à¦¯à¦¬à¦¹à¦¾à¦° করার জনà§à¦¯ সেট আছে কিনà§à¦¤à§ à¦à¦•à¦Ÿà¦¿ সà§à¦¨à¦¿à¦°à§à¦¦à¦¿à¦·à§à¦Ÿ পà§à¦°à¦•à§à¦¸à¦¿ কনফিগারেশনও নিরà§à¦¦à¦¿à¦·à§à¦Ÿ করা আছে৷</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> à¦à¦° মধà§à¦¯à§‡ <ph name="RESULT_NUMBER" /> টি ফলাফল</translation>
+<translation id="2085876078937250610">সেভ করà§à¦¨â€¦</translation>
<translation id="2088086323192747268">সিঙà§à¦• করার বোতাম মà§à¦¯à¦¾à¦¨à§‡à¦œ করà§à¦¨, Chrome সেটিংসে আপনি কী ধরনের তথà§à¦¯ সিঙà§à¦• করবেন, তা মà§à¦¯à¦¾à¦¨à§‡à¦œ করতে Enter পà§à¦°à§‡à¦¸ করà§à¦¨</translation>
<translation id="2091887806945687916">আওয়াজ</translation>
<translation id="2094505752054353250">ডোমেন মেলেনি</translation>
@@ -380,6 +389,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> à¦à¦° জনà§à¦¯ à¦à¦•à¦Ÿà¦¿ ইউজারনেম à¦à¦¬à¦‚ পাসওয়ারà§à¦¡ পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨à¥¤</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />-à¦à¦° মেয়াদ, <ph name="EXPIRATION_DATE_ABBR" /> তারিখে শেষ হবে</translation>
<translation id="2337852623177822836">সেটিংস আপনার পà§à¦°à¦¶à¦¾à¦¸à¦• নিয়নà§à¦¤à§à¦°à¦£ করে</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> à¦à¦¦à§‡à¦° সঙà§à¦—ে যà§à¦•à§à¦¤ হতে চাচà§à¦›à§‡</translation>
<translation id="2344028582131185878">অটোমেটিক ডাউনলোডগà§à¦²à¦¿</translation>
<translation id="2346319942568447007">আপনার কপি করা ছবি</translation>
<translation id="2354001756790975382">অনà§à¦¯ বà§à¦•à¦®à¦¾à¦°à§à¦•</translation>
@@ -387,8 +397,10 @@
<translation id="2355395290879513365">আপনি à¦à¦‡ সাইটে যেসব ছবি দেখছেন, আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€à¦°à¦¾ সেগà§à¦²à¦¿ দেখতে পেতে পারে à¦à¦¬à¦‚ সেগà§à¦²à¦¿ পরিবরà§à¦¤à¦¨ করে আপনাকে বোকা বানাতে পারে।</translation>
<translation id="2356070529366658676">জিজà§à¦žà¦¾à¦¸à¦¾ করà§à¦¨</translation>
<translation id="2357481397660644965">আপনার ডিভাইস <ph name="DEVICE_MANAGER" />-à¦à¦° মাধà§à¦¯à¦®à§‡ à¦à¦¬à¦‚ আপনার অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ <ph name="ACCOUNT_MANAGER" />-à¦à¦° মাধà§à¦¯à¦®à§‡ মà§à¦¯à¦¾à¦¨à§‡à¦œ করা হয়।</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{à¦à¦• দিনের থেকে কম সময়ের মধà§à¦¯à§‡}=1{à¦à¦• দিনের মধà§à¦¯à§‡}one{{NUM_DAYS} দিনের মধà§à¦¯à§‡}other{{NUM_DAYS} দিনের মধà§à¦¯à§‡}}</translation>
<translation id="2359629602545592467">à¦à¦•à¦¾à¦§à¦¿à¦•</translation>
<translation id="2359808026110333948">চালিয়ে যান</translation>
+<translation id="2359961752320758691">আপনার ভারà§à¦šà§à§Ÿà¦¾à¦² কারà§à¦¡à§‡à¦° নমà§à¦¬à¦° পà§à¦°à§Ÿà§‹à¦— করা হয়েছে।</translation>
<translation id="2367567093518048410">সà§à¦¤à¦°</translation>
<translation id="2372464001869762664">আপনি কনফারà§à¦® করার পর, আপনার Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ থেকে কারà§à¦¡à§‡à¦° বিবরণ à¦à¦‡ সাইটে শেয়ার করা হবে। আপনার Plex অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ সংকà§à¦°à¦¾à¦¨à§à¦¤ বিবরণ থেকে সিভিসি দেখে নিন।</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -399,6 +411,7 @@
<translation id="239429038616798445">à¦à¦‡ পদà§à¦§à¦¤à¦¿à¦¤à§‡ শিপিং করা যাবে না। অনà§à¦¯ পদà§à¦§à¦¤à¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨à¥¤</translation>
<translation id="2396249848217231973">&amp;মà§à¦›à§‡ ফেলাকে পূরà§à¦¬à¦¾à¦¬à¦¸à§à¦¥à¦¾à¦¯à¦¼ ফেরান</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">পà§à¦°à¦¨à§‹</translation>
<translation id="2413528052993050574">à¦à¦‡ সারà§à¦­à¦¾à¦° পà§à¦°à¦®à¦¾à¦£ করতে পারেনি যে à¦à¦Ÿà¦¿ <ph name="DOMAIN" />; à¦à¦° নিরাপতà§à¦¤à¦¾ সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿ পà§à¦°à¦¤à§à¦¯à¦¾à¦¹à¦¾à¦° করা হতে পারে। কোনো ভà§à¦² কনফিগারেশনের কারণে অথবা কোনো আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€ আপনার সংযোগ মাà¦à¦ªà¦¥à§‡ আটকে দিচà§à¦›à§‡ বলে à¦à¦®à¦¨à¦Ÿà¦¾ হতে পারে।</translation>
<translation id="2414886740292270097">অনà§à¦§à¦•à¦¾à¦°</translation>
<translation id="2438874542388153331">ডানদিকে কোয়াড পাঞà§à¦š</translation>
@@ -426,10 +439,10 @@
<translation id="2521385132275182522">নিচে ডানদিকে সà§à¦Ÿà§‡à¦ªà¦² করà§à¦¨</translation>
<translation id="2523886232349826891">শà§à¦§à§à¦®à¦¾à¦¤à§à¦° à¦à¦‡ ডিভাইসে সেভ করা যাবে</translation>
<translation id="2524461107774643265">আরও তথà§à¦¯ যোগ করà§à¦¨</translation>
-<translation id="2526590354069164005">ডেসà§à¦•à¦Ÿà¦ª</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{à¦à¦¬à¦‚ আরও ১টি}one{à¦à¦¬à¦‚ আরও #টি}other{à¦à¦¬à¦‚ আরও #টি}}</translation>
<translation id="2536110899380797252">ঠিকানা যোগ করà§à¦¨</translation>
<translation id="2539524384386349900">শনাকà§à¦¤ করà§à¦¨</translation>
+<translation id="2541219929084442027">ছদà§à¦®à¦¬à§‡à¦¶à§€ টà§à¦¯à¦¾à¦¬à§‡ আপনি যেসব পৃষà§à¦ à¦¾ দেখবেন সেগà§à¦²à¦¿ বনà§à¦§ করার পরে বà§à¦°à¦¾à¦‰à¦œà¦¾à¦° ইতিহাস, কà§à¦•à¦¿ সà§à¦Ÿà§‹à¦° বা সারà§à¦š ইতিহাসে থাকবে না। আপনি কোনও ফাইল ডাউনলোড করলে বা বà§à¦•à¦®à¦¾à¦°à§à¦• তৈরি করলে, সেটি সেভ করা থাকবে।</translation>
<translation id="2544644783021658368">à¦à¦•à¦• ডকà§à¦®à§‡à¦¨à§à¦Ÿ</translation>
<translation id="254947805923345898">নীতির মান সঠিক নয়।</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> à¦à¦•à¦Ÿà¦¿ ভà§à¦² পà§à¦°à¦¤à¦¿à¦•à§à¦°à¦¿à¦¯à¦¼à¦¾ পাঠিয়েছে।</translation>
@@ -449,6 +462,7 @@
<translation id="2629325967560697240">Chrome-ঠসবচেয়ে বেশি সà§à¦°à¦•à§à¦·à¦¾ পেতে, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />উনà§à¦¨à¦¤ সà§à¦°à¦•à§à¦·à¦¾ চালৠকরà§à¦¨<ph name="END_ENHANCED_PROTECTION_LINK" />।</translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" />-à¦à¦° সারà§à¦­à¦¾à¦° আইপি অà§à¦¯à¦¾à¦¡à§à¦°à§‡à¦¸ পাওয়া যায়নি।</translation>
<translation id="2639739919103226564">সà§à¦¥à¦¿à¦¤à¦¿: </translation>
+<translation id="264810637653812429">উপযà§à¦•à§à¦¤ ডিভাইস খà§à¦à¦œà§‡ পাওয়া যায়নি।</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome সেটিংসে আপনার বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚ ইতিহাস, কà§à¦•à¦¿, কà§à¦¯à¦¾à¦¶à§‡ ও আরও অনেক কিছৠমà§à¦›à¦¤à§‡ পà§à¦°à¦¥à¦®à§‡ Tab আর তারপরে Enter পà§à¦°à§‡à¦¸ করà§à¦¨</translation>
<translation id="2650446666397867134">ফাইলে অà§à¦¯à¦¾à¦•à§à¦¸à§‡à¦¸ অসà§à¦¬à§€à¦•à§ƒà¦¤ হয়েছে</translation>
@@ -495,6 +509,7 @@
<translation id="2799223571221894425">পà§à¦¨à¦ƒà¦¶à§à¦°à§</translation>
<translation id="2803306138276472711">Google নিরাপদ বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚ সামà§à¦ªà§à¦°à¦¤à¦¿à¦• <ph name="SITE" />-ঠ<ph name="BEGIN_LINK" />মà§à¦¯à¦¾à¦²à¦“য়à§à¦¯à¦¾à¦° শনাকà§à¦¤ করেছে<ph name="END_LINK" />। যেসব ওয়েবসাইট সাধারণত নিরাপদ থাকে, সেগà§à¦²à¦¿ কখনও কখনও মà§à¦¯à¦¾à¦²à¦“য়à§à¦¯à¦¾à¦° দিয়ে আকà§à¦°à¦¾à¦¨à§à¦¤ হয়।</translation>
<translation id="2807052079800581569">ছবি Y পজিশন</translation>
+<translation id="2820957248982571256">সà§à¦•à§à¦¯à¦¾à¦¨ করা হচà§à¦›à§‡â€¦</translation>
<translation id="2824775600643448204">ঠিকানা à¦à¦¬à¦‚ সারà§à¦š দণà§à¦¡</translation>
<translation id="2826760142808435982"><ph name="CIPHER" /> বà§à¦¯à¦¬à¦¹à¦¾à¦° করে à¦à¦‡ সংযোগটি à¦à¦¨à¦•à§à¦°à¦¿à¦ªà§à¦Ÿà§‡à¦¡ à¦à¦¬à¦‚ পà§à¦°à¦®à¦¾à¦£à§€à¦•à§ƒà¦¤ করা হয়েছে à¦à¦¬à¦‚ কী à¦à¦•à§à¦¸à¦šà§‡à¦žà§à¦œ পà§à¦°à¦•à§à¦°à¦¿à§Ÿà¦¾ হিসাবে <ph name="KX" /> বà§à¦¯à¦¬à¦¹à¦¾à¦° করে৷</translation>
<translation id="2835170189407361413">ফরà§à¦® সাফ করà§à¦¨</translation>
@@ -502,6 +517,8 @@
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">à¦à¦‡ সাইট বà§à¦¯à¦¾à¦˜à¦¾à¦¤ সৃষà§à¦Ÿà¦¿à¦•à¦¾à¦°à§€ বা বিভà§à¦°à¦¾à¦¨à§à¦¤à¦¿à¦•à¦° বিজà§à¦žà¦¾à¦ªà¦¨ দেখায়।</translation>
+<translation id="287596039013813457">বনà§à¦§à§à¦¤à§à¦¬à¦ªà§‚রà§à¦£</translation>
+<translation id="2876489322757410363">à¦à¦•à§à¦¸à¦Ÿà¦¾à¦°à§à¦¨à¦¾à¦² অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¨à§‡à¦° মাধà§à¦¯à¦®à§‡ পেমেনà§à¦Ÿ করার জনà§à¦¯ ছদà§à¦®à¦¬à§‡à¦¶à§€ মোড ছেড়ে বেরিয়ে আসা হচà§à¦›à§‡à¥¤ চালিয়ে যেতে চান?</translation>
<translation id="2878197950673342043">পোসà§à¦Ÿà¦¾à¦° ফোলà§à¦¡</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">উইনà§à¦¡à§‹ পà§à¦²à§‡à¦¸à¦®à§‡à¦¨à§à¦Ÿ</translation>
@@ -551,7 +568,6 @@
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome সেটিংসে 'নিরাপতà§à¦¤à¦¾ সংকà§à¦°à¦¾à¦¨à§à¦¤ পরীকà§à¦·à¦¾' চালাতে পà§à¦°à¦¥à¦®à§‡ Tab আর তারপরে Enter কী পà§à¦°à§‡à¦¸ করà§à¦¨</translation>
<translation id="3061707000357573562">পà§à¦¯à¦¾à¦š পরিষেবা</translation>
-<translation id="3064966200440839136">বহিরাগত অà§à¦¯à¦¾à¦ªà§‡à¦° মাধà§à¦¯à¦®à§‡ পেমেনà§à¦Ÿ করার জনà§à¦¯ ছদà§à¦®à¦¬à§‡à¦¶à§€ মোড থেকে বেরিয়ে যাচà§à¦›à§‡à¥¤ চালিয়ে যাবেন?</translation>
<translation id="306573536155379004">গেম শà§à¦°à§ হয়েছে।</translation>
<translation id="3080254622891793721">গà§à¦°à¦¾à¦«à¦¿à¦•</translation>
<translation id="3086579638707268289">ওয়েবে আপনার অà§à¦¯à¦¾à¦•à§à¦Ÿà¦¿à¦­à¦¿à¦Ÿà¦¿ নজরে রাখা হচà§à¦›à§‡</translation>
@@ -574,7 +590,6 @@
<translation id="315504272643575312">আপনার অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ <ph name="MANAGER" />-à¦à¦° মাধà§à¦¯à¦®à§‡ মà§à¦¯à¦¾à¦¨à§‡à¦œ করা হয়।</translation>
<translation id="3157931365184549694">পà§à¦¨à¦°à§à¦¦à§à¦§à¦¾à¦° করà§à¦¨</translation>
<translation id="3162559335345991374">আপনি যে ওয়াই-ফাইটি বà§à¦¯à¦¬à¦¹à¦¾à¦° করছেন সেটির জনà§à¦¯ অপনাকে à¦à¦Ÿà¦¿à¦° লগ-ইন পৃষà§à¦ à¦¾à¦¤à§‡ যেতে হতে পরে৷</translation>
-<translation id="3167968892399408617">ছদà§à¦®à¦¬à§‡à¦¶à§€ টà§à¦¯à¦¾à¦¬à¦—à§à¦²à¦¿à¦¤à§‡ আপনি যে পৃষà§à¦ à¦¾à¦—à§à¦²à¦¿ দেখেন সেগà§à¦²à¦¿ আপনার সব ছদà§à¦®à¦¬à§‡à¦¶à§€ টà§à¦¯à¦¾à¦¬ বনà§à¦§ করে দেওয়ার পর বà§à¦°à¦¾à¦‰à¦œà¦¾à¦°à§‡à¦° ইতিহাস, কà§à¦•à¦¿ সà§à¦Ÿà§‹à¦° বা সারà§à¦š ইতিহাসে থাকবে না। আপনি ডাউনলোড করেছেন à¦à¦®à¦¨ ফাইল বা বà§à¦•à¦®à¦¾à¦°à§à¦• তৈরি করছেন à¦à¦®à¦¨ সবগà§à¦²à¦¿ রেখে দেওয়া হবে।</translation>
<translation id="3169472444629675720">আবিষà§à¦•à¦¾à¦° করà§à¦¨</translation>
<translation id="3174168572213147020">আইলà§à¦¯à¦¾à¦£à§à¦¡</translation>
<translation id="3176929007561373547">পà§à¦°à¦•à§à¦¸à§€ সারà§à¦­à¦¾à¦° কাজ করছে কি না, তা নিশà§à¦šà¦¿à¦¤ করতে আপনার পà§à¦°à¦•à§à¦¸à§€ সেটিংস পরীকà§à¦·à¦¾ করà§à¦¨
@@ -600,10 +615,12 @@
<translation id="3229041911291329567">আপনার ডিভাইস à¦à¦¬à¦‚ বà§à¦°à¦¾à¦‰à¦œà¦¾à¦°à§‡à¦° ভারà§à¦¸à¦¨ সমà§à¦¬à¦¨à§à¦§à§€à§Ÿ তথà§à¦¯</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" />-à¦à¦° CVC লিখà§à¦¨</translation>
<translation id="3234666976984236645">à¦à¦‡ সাইটে সবসময় গà§à¦°à§à¦¤à§à¦¬à¦ªà§‚রà§à¦£ কনà§à¦Ÿà§‡à¦¨à§à¦Ÿ শনাকà§à¦¤ করà§à¦¨</translation>
+<translation id="3249845759089040423">গà§à§°à§à¦­à¦¿</translation>
<translation id="3252266817569339921">ফরাসী</translation>
<translation id="3266793032086590337">মান (মà§à¦¯à¦¾à¦š করছে না)</translation>
<translation id="3268451620468152448">ওপেন টà§à¦¯à¦¾à¦¬</translation>
<translation id="3270847123878663523">&amp;পà§à¦¨à¦°à§à¦¬à¦¿à¦¨à§à¦¯à¦¾à¦¸à¦•à§‡ পূরà§à¦¬à¦¾à¦¬à¦¸à§à¦¥à¦¾à¦¯à¦¼ ফেরান</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> à¦à¦¦à§‡à¦° সঙà§à¦—ে সংযà§à¦•à§à¦¤ হতে চায়</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">আপনার সংসà§à¦¥à¦¾, <ph name="ENROLLMENT_DOMAIN" />, নিমà§à¦¨à¦²à¦¿à¦–িত ওয়েবসাইটগà§à¦²à¦¿à¦•à§‡ সেটিংস বা নীতির মতো কিছৠতথà§à¦¯ পাঠিয়েছে।</translation>
<translation id="3282497668470633863">কারà§à¦¡à§‡ থাকা নাম যোগ করà§à¦¨</translation>
@@ -656,6 +673,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates সারà§à¦­à¦¾à¦°à§‡à¦° à¦à¦• বা à¦à¦•à¦¾à¦§à¦¿à¦• টেমপà§à¦²à§‡à¦Ÿ ইউআরআই সঠিক নয় à¦à¦¬à¦‚ বà§à¦¯à¦¬à¦¹à¦¾à¦° করা যাবে না।</translation>
<translation id="3431636764301398940">à¦à¦‡ ডিভাইসে à¦à¦‡ কারà§à¦¡à¦Ÿà¦¿ সেভ করà§à¦¨</translation>
<translation id="3432601291244612633">পৃষà§à¦ à¦¾ বনà§à¦§ করà§à¦¨</translation>
+<translation id="3435738964857648380">নিরাপতà§à¦¤à¦¾</translation>
<translation id="3435896845095436175">সকà§à¦·à¦® করà§à¦¨</translation>
<translation id="3438829137925142401">আপনার Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡ সেভ করা পাসওয়ারà§à¦¡ বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -698,7 +716,10 @@
<translation id="3584299510153766161">নিচে ডà§à§Ÿà¦¾à¦² পাঞà§à¦š</translation>
<translation id="3586931643579894722">বিশদ বিবরণ লà§à¦•à¦¾à¦¨</translation>
<translation id="3587738293690942763">মাà¦à¦¾à¦°à¦¿</translation>
+<translation id="3590643883886679995">ছদà§à¦®à¦¬à§‡à¦¶à§€ মোড ছেড়ে বেরিয়ে আসলে à¦à¦‡ ডিভাইসে সাইন-ইন ডেটা সেভ করা হবে।</translation>
+<translation id="359126217934908072">মাস/বছর:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{আপনি যেকোনও সময় আপনার গà§à¦°à§à¦ª রিসেট করতে পারবেন। নতà§à¦¨ গà§à¦°à§à¦ªà§‡ যোগ দিতে পà§à¦°à¦¾à§Ÿ à¦à¦• দিন সময় লাগে।}=1{আপনি যেকোনও সময় আপনার গà§à¦°à§à¦ª রিসেট করতে পারবেন। নতà§à¦¨ গà§à¦°à§à¦ªà§‡ যোগ দিতে পà§à¦°à¦¾à§Ÿ à¦à¦• দিন সময় লাগে।}one{আপনি যেকোনও সময় আপনার গà§à¦°à§à¦ª রিসেট করতে পারবেন। নতà§à¦¨ গà§à¦°à§à¦ªà§‡ যোগ দিতে {NUM_DAYS} দিন সময় লাগে।}other{আপনি যেকোনও সময় আপনার গà§à¦°à§à¦ª রিসেট করতে পারবেন। নতà§à¦¨ গà§à¦°à§à¦ªà§‡ যোগ দিতে {NUM_DAYS} দিন সময় লাগে।}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¨à¦Ÿà¦¿à¦•à§‡ আপনার অà§à¦¯à¦¾à¦¡à¦®à¦¿à¦¨à¦¿à¦¸à§à¦Ÿà§à¦°à§‡à¦Ÿà¦° বà§à¦²à¦• করেছে</translation>
<translation id="3608932978122581043">ফিড ওরিয়েনà§à¦Ÿà§‡à¦¶à¦¨</translation>
@@ -707,13 +728,13 @@
<translation id="3615877443314183785">মেয়াদ শেষ হওয়ার তারিখের সঠিক মান লিখà§à¦¨</translation>
<translation id="36224234498066874">বà§à¦°à¦¾à¦‰à¦œ করা ডেটা সাফ করà§à¦¨...</translation>
<translation id="362276910939193118">সমà§à¦ªà§‚রà§à¦£ ইতিহাস দেখà§à¦¨</translation>
-<translation id="3625635938337243871">আপনি 'ছদà§à¦®à¦¬à§‡à¦¶à§€ মোড' থেকে বেরিয়ে আসার পরেই সাইন-ইন সংকà§à¦°à¦¾à¦¨à§à¦¤ ডেটা à¦à¦‡ ডিভাইসে সà§à¦Ÿà§‹à¦° করা হবে।</translation>
<translation id="3630155396527302611">নেটওয়ারà§à¦• অà§à¦¯à¦¾à¦•à§à¦¸à§‡à¦¸ করতে à¦à¦Ÿà¦¿ যদি ইতোমধà§à¦¯à§‡ মঞà§à¦œà§à¦°à¦¿à¦•à§ƒà¦¤ পà§à¦°à§‹à¦—à§à¦°à¦¾à¦® হিসাবে তালিকাতে থাকে, তাহলে
তালিকাটি থেকে à¦à¦Ÿà¦¿ সরানোর চেষà§à¦Ÿà¦¾ করে আবার যোগ করে দেখà§à¦¨à¥¤</translation>
<translation id="3630699740441428070">à¦à¦‡ ডিভাইসের অà§à¦¯à¦¾à¦¡à¦®à¦¿à¦¨à¦¿à¦¸à§à¦Ÿà§à¦°à§‡à¦Ÿà¦° আপনার নেটওয়ারà§à¦• কানেকশন কনফিগার করেছেন। à¦à¦° ফলে, আপনি যে ওয়েবসাইটগà§à¦²à¦¿à¦¤à§‡ যান সেগà§à¦²à¦¿ সহ আপনার নেটওয়ারà§à¦• টà§à¦°à¦¾à¦«à¦¿à¦• তিনি দেখতে পাবেন।</translation>
<translation id="3631244953324577188">বায়োমেটà§à¦°à¦¿à¦•à§à¦¸</translation>
<translation id="3633738897356909127">Chrome আপডেট করার বোতাম, আপনার Chrome সেটিংসে Chrome আপডেট করতে Enter পà§à¦°à§‡à¦¸ করà§à¦¨</translation>
<translation id="3634530185120165534">টà§à¦°à§‡ ৫</translation>
+<translation id="3637662659967048211">Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡ সেভ করà§à¦¨</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¨:</translation>
<translation id="3650584904733503804">বৈধতা যাচাইকরণ সফল হয়েছে</translation>
@@ -754,6 +775,7 @@
<translation id="3781428340399460090">হট গোলাপী</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">বà§à¦²à§à¦Ÿà§à¦¥ ডিভাইস</translation>
+<translation id="3787675388804467730">ভারà§à¦šà§à§Ÿà¦¾à¦² কারà§à¦¡à§‡à¦° সংখà§à¦¯à¦¾</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> ঠমেয়াদ শেষ হবে</translation>
<translation id="3789155188480882154">সাইজ ১৬</translation>
<translation id="3789841737615482174">ইনসà§à¦Ÿà¦² করà§à¦¨</translation>
@@ -773,6 +795,7 @@
<translation id="3841184659773414994">ফাইল হà§à¦¯à¦¾à¦¨à§à¦¡à¦²à¦¾à¦°</translation>
<translation id="385051799172605136">ফিরà§à¦¨</translation>
<translation id="3858027520442213535">তারিখ à¦à¦¬à¦‚ সময় আপডেট করà§à¦¨</translation>
+<translation id="3881478300875776315">কম লাইন দেখà§à¦¨</translation>
<translation id="3884278016824448484">পরসà§à¦ªà¦° বিরোধী ডিভাইস সনাকà§à¦¤à¦•à¦¾à¦°à§€</translation>
<translation id="3885155851504623709">পà§à¦¯à¦¾à¦°à¦¿à¦¶</translation>
<translation id="388632593194507180">মনিটর করা হচà§à¦›à§‡, সেটি শনাকà§à¦¤ করা গেছে</translation>
@@ -798,6 +821,7 @@
<translation id="397105322502079400">গণনা করা হচà§à¦›à§‡...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> অবরà§à¦¦à§à¦§ হয়ে রয়েছে</translation>
<translation id="3973357910713125165">'Chrome নিরাপতà§à¦¤à¦¾ সংকà§à¦°à¦¾à¦¨à§à¦¤ পরীকà§à¦·à¦¾ চালান' বোতাম, Chrome সেটিংসে নিরাপতà§à¦¤à¦¾ সংকà§à¦°à¦¾à¦¨à§à¦¤ পরীকà§à¦·à¦¾ চালাতে Enter কী পà§à¦°à§‡à¦¸ করà§à¦¨</translation>
+<translation id="3986705137476756801">à¦à¦–নকার মতো লাইভ কà§à¦¯à¦¾à¦ªà¦¶à¦¨ বনà§à¦§ করে দিন</translation>
<translation id="3987405730340719549">à¦à¦‡ সাইট জাল বা পà§à¦°à¦¤à¦¾à¦°à¦£à¦¾à¦®à§‚লক হতে পারে বলে Chrome শনাকà§à¦¤ করেছে।
à¦à¦Ÿà¦¿ ভà§à¦² করে দেখানো হচà§à¦›à§‡ বলে মনে হলে, https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals লিঙà§à¦•à¦Ÿà¦¿ দেখà§à¦¨à¥¤</translation>
@@ -894,13 +918,14 @@
<translation id="4275830172053184480">আপনার ডিভাইস বনà§à¦§ করে চালৠকরà§à¦¨</translation>
<translation id="4277028893293644418">পাসওয়ারà§à¦¡ রিসেট করà§à¦¨</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{à¦à¦‡ কারà§à¦¡à¦Ÿà¦¿ আপনার Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡ সেভ করা হয়েছে}one{à¦à¦‡ কারà§à¦¡à¦—à§à¦²à¦¿ আপনার Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡ সেভ করা হয়েছে}other{à¦à¦‡ কারà§à¦¡à¦—à§à¦²à¦¿ আপনার Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡ সেভ করা হয়েছে}}</translation>
+<translation id="4287885627794386150">টà§à¦°à¦¾à§Ÿà¦¾à¦² করা যেতে পারে কিনà§à¦¤à§ অà§à¦¯à¦¾à¦•à§à¦Ÿà¦¿à¦­ নেই</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> পৃষà§à¦ à¦¾à¦° থামà§à¦¬à¦¨à§‡à¦²</translation>
<translation id="42981349822642051">পà§à¦°à¦¸à¦¾à¦°à¦¿à¦¤ করà§à¦¨</translation>
<translation id="4300675098767811073">ডানদিকে মালà§à¦Ÿà¦¿à¦ªà¦² পাঞà§à¦š</translation>
<translation id="4302514097724775343">ডাইনোসর গেম খেলতে, টà§à¦¯à¦¾à¦ª করà§à¦¨</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">আপনার ফাইল অà§à¦¯à¦¾à¦•à§à¦¸à§‡à¦¸ করা যায়নি</translation>
-<translation id="4305817255990598646">পালà§à¦Ÿà¦¾à¦¨</translation>
+<translation id="4306529830550717874">ঠিকানা সেভ করবেন?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">অবরà§à¦¦à§à¦§ করà§à¦¨ (ডিফলà§à¦Ÿ)</translation>
<translation id="4314815835985389558">সিঙà§à¦• মà§à¦¯à¦¾à¦¨à§‡à¦œ করà§à¦¨</translation>
@@ -927,6 +952,7 @@
<translation id="4377125064752653719">আপনি <ph name="DOMAIN" />-ঠপৌà¦à¦›à¦¾à¦¨à§‹à¦° পà§à¦°à¦šà§‡à¦·à§à¦Ÿà¦¾ করেছেন, তবে সারà§à¦­à¦¾à¦°à¦Ÿà¦¿ যে সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿà¦Ÿà¦¿ উপসà§à¦¥à¦¾à¦ªà¦¨ করেছে সেটির জারিকরà§à¦¤à¦¾ সেটিকে পà§à¦°à¦¤à§à¦¯à¦¾à¦¹à¦¾à¦° করেছে৷ à¦à¦° অরà§à¦¥ হ'ল সারà§à¦­à¦¾à¦°à¦Ÿà¦¿ যে সà§à¦°à¦•à§à¦·à¦¾ পà§à¦°à¦®à¦¾à¦¨à¦ªà¦¤à§à¦° উপসà§à¦¥à¦¾à¦ªà¦¨ করেছে তা কোনওমতেই বিশà§à¦¬à¦¾à¦¸à¦¯à§‹à¦—à§à¦¯ নয়৷ হতে পারে আপনি à¦à¦•à¦œà¦¨ আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€à¦° সাথে যোগাযোগ করছেন৷</translation>
<translation id="4378154925671717803">ফোন</translation>
<translation id="4390472908992056574">বà§à¦°à¦¿à¦®</translation>
+<translation id="4406883609789734330">লাইভ কà§à¦¯à¦¾à¦ªà¦¶à¦¨</translation>
<translation id="4406896451731180161">সারà§à¦šà§‡à¦° ফলাফলগà§à¦²à¦¿</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" />টি কà§à¦•à¦¿à¦œ</translation>
<translation id="4414290883293381923">আপনি à¦à¦–নই পà§à¦°à¦¤à¦¾à¦°à¦£à¦¾à¦®à§‚লক à¦à¦•à¦Ÿà¦¿ সাইটে নিজের পাসওয়ারà§à¦¡ লিখেছেন। <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> à¦à¦¬à¦‚ অনà§à¦¯à¦¾à¦¨à§à¦¯ সাইটে, যেখানে যেখানে আপনি à¦à¦‡ পাসওয়ারà§à¦¡à¦Ÿà¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করেন, সেইসব জায়গায় গিয়ে à¦à¦–নই à¦à¦Ÿà¦¿ পরিবরà§à¦¤à¦¨ করতে Chromium আপনাকে সাজেসà§à¦Ÿ করেছে।</translation>
@@ -939,7 +965,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">পà§à¦°à¦•à§à¦¸à¦¿à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦° অকà§à¦·à¦® করা হয়েছে কিনà§à¦¤à§ কোনো সà§à¦ªà¦·à§à¦Ÿ পà§à¦°à¦•à§à¦¸à¦¿ কনফিগারেশান নিরà§à¦¦à¦¿à¦·à§à¦Ÿ করা হয়েছে৷</translation>
<translation id="4464826014807964867">à¦à¦®à¦¨ ওয়েবসাইট যার বà§à¦¯à¦¾à¦ªà¦¾à¦°à§‡ আপনার সংসà§à¦¥à¦¾à¦° কাছ থেকে তথà§à¦¯ পাওয়া গেছে</translation>
-<translation id="4466881336512663640">ফরà§à¦®à§‡ করা পরিবরà§à¦¤à¦¨à¦—à§à¦²à¦¿ সেভ হবে না। আপনি কি চালিয়ে যেতে চান?</translation>
<translation id="4476953670630786061">à¦à¦‡ ফরà§à¦® নিরাপদ নয়। অটোফিল বনà§à¦§ করে দেওয়া হয়েছে।</translation>
<translation id="4477350412780666475">পরের টà§à¦°à§à¦¯à¦¾à¦• চালান</translation>
<translation id="4482953324121162758">à¦à¦‡ সাইটটি অনà§à¦¬à¦¾à¦¦ করা হবে না।</translation>
@@ -957,7 +982,7 @@
<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>
<translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> মিলিমিটার (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">বিশদ বিবরণ</translation>
+<translation id="4522570452068850558">বিবরণগà§à¦²à¦¿</translation>
<translation id="4524138615196389145">à¦à¦–ন থেকে WebAuthn বà§à¦¯à¦¬à¦¹à¦¾à¦° করে আপনার কারà§à¦¡ আরও দà§à¦°à§à¦¤ কনফারà§à¦® করà§à¦¨</translation>
<translation id="4524805452350978254">কারà§à¦¡ মà§à¦¯à¦¾à¦¨à§‡à¦œ করà§à¦¨</translation>
<translation id="4542971377163063093">টà§à¦°à§‡ ৬</translation>
@@ -973,6 +998,7 @@
<translation id="4594403342090139922">&amp;মà§à¦›à§‡ ফেলাকে পূরà§à¦¬à¦¾à¦¬à¦¸à§à¦¥à¦¾à¦¯à¦¼ ফেরান</translation>
<translation id="4597348597567598915">সাইজ ৮</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">পà§à¦°à¦­à¦¾à¦¬à¦¶à¦¾à¦²à§€</translation>
<translation id="4628948037717959914">ফটো</translation>
<translation id="4631649115723685955">কà§à¦¯à¦¾à¦¶à¦¬à§à¦¯à¦¾à¦• অফার লিঙà§à¦• করা হয়েছে</translation>
<translation id="4636930964841734540">তথà§à¦¯</translation>
@@ -992,6 +1018,7 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">সাইড</translation>
+<translation id="4702656508969495934">লাইভ কà§à¦¯à¦¾à¦ªà¦¶à¦¨ দেখা যাচà§à¦›à§‡, ফোকাস করতে উইনà§à¦¡à§‹ পরিবরà§à¦¤à¦¨à¦•à¦¾à¦°à§€ বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨</translation>
<translation id="4708268264240856090">আপনার সংযোগ বাধাপà§à¦°à¦¾à¦ªà§à¦¤ হয়েছে</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows নেটওয়ারà§à¦• ডায়গনিসà§à¦Ÿà¦¿à¦•à§à¦¸ চালান<ph name="END_LINK" /></translation>
@@ -1005,6 +1032,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> সারà§à¦š সাজেশন</translation>
<translation id="4742407542027196863">পাসওয়ারà§à¦¡à¦—à§à¦²à¦¿ পরিচালনা করà§à¦¨â€¦</translation>
<translation id="4744603770635761495">সমà§à¦ªà¦¾à¦¦à¦¨à¦¯à§‹à¦—à§à¦¯ পাথ</translation>
+<translation id="4749011317274908093">আপনি ছদà§à¦®à¦¬à§‡à¦¶à§€ মোড বà§à¦¯à¦¬à¦¹à¦¾à¦° করছেন</translation>
<translation id="4750917950439032686">আপনার তথà§à¦¯ (উদাহরণসà§à¦¬à¦°à§‚প, পাসওয়ারà§à¦¡ বা কà§à¦°à§‡à¦¡à¦¿à¦Ÿ কারà§à¦¡ নমà§à¦¬à¦°) যখন à¦à¦‡ সাইটে পাঠানো হয় তখন সেটি বà§à¦¯à¦•à§à¦¤à¦¿à¦—ত থাকে।</translation>
<translation id="4756388243121344051">&amp;ইতিহাস</translation>
<translation id="4758311279753947758">পরিচিতির তথà§à¦¯ জà§à§œà§à¦¨</translation>
@@ -1034,6 +1062,8 @@
<translation id="4813512666221746211">নেটওয়ারà§à¦• তà§à¦°à§à¦Ÿà¦¿</translation>
<translation id="4816492930507672669">পৃষà§à¦ à¦¾à¦¤à§‡ মানানসই</translation>
<translation id="4819347708020428563">ডিফলà§à¦Ÿ ভিউতে অà§à¦¯à¦¾à¦¨à§‹à¦Ÿà§‡à¦¶à¦¨ à¦à¦¡à¦¿à¦Ÿ করবেন?</translation>
+<translation id="4825507807291741242">কà§à¦·à¦®à¦¤à¦¾à¦¶à¦¾à¦²à§€</translation>
+<translation id="4838327282952368871">সà§à¦¬à¦ªà§à¦¨à¦¾à¦²à§</translation>
<translation id="484462545196658690">অটো</translation>
<translation id="4850886885716139402">দেখà§à¦¨</translation>
<translation id="485316830061041779">জারà§à¦®à¦¾à¦¨</translation>
@@ -1170,6 +1200,7 @@
<translation id="5314967030527622926">বà§à¦•à¦²à§‡à¦Ÿ পà§à¦°à¦¸à§à¦¤à§à¦¤à¦•à¦¾à¦°à§€</translation>
<translation id="5316812925700871227">ঘড়ির কাà¦à¦Ÿà¦¾à¦° বিপরীত দিকে ঘোরান</translation>
<translation id="5317780077021120954">সেভ করà§à¦¨</translation>
+<translation id="5321288445143113935">বড় করা হয়েছে</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> à¦à¦° মধà§à¦¯à§‡ <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">পরিচিতির তথà§à¦¯ বেছে নিন</translation>
<translation id="5327248766486351172">নাম</translation>
@@ -1177,11 +1208,13 @@
<translation id="5332219387342487447">শিপিংয়ের মাধà§à¦¯à¦®</translation>
<translation id="5333022057423422993">Chrome-à¦à¦° হিসেবে আপনার à¦à¦–নই বà§à¦¯à¦¬à¦¹à¦¾à¦° করা পাসওয়ারà§à¦¡à§‡à¦° তথà§à¦¯ চà§à¦°à¦¿ হয়ে গেছে। আপনার অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ সà§à¦°à¦•à§à¦·à¦¿à¦¤ রাখতে, আপনার সেভ করা পাসওয়ারà§à¦¡ চেক করার জনà§à¦¯ সাজেসà§à¦Ÿ করছি।</translation>
<translation id="5334013548165032829">বিসà§à¦¤à¦¾à¦°à¦¿à¦¤ সিসà§à¦Ÿà§‡à¦® লগ</translation>
+<translation id="5334145288572353250">ঠিকানা সেভ করবেন?</translation>
<translation id="5340250774223869109">অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•à§‡à¦¶à¦¨à¦Ÿà¦¿ বà§à¦²à¦• করা আছে</translation>
<translation id="534295439873310000">NFC ডিভাইস</translation>
<translation id="5344579389779391559">à¦à¦‡ পৃষà§à¦ à¦¾à¦¤à§‡ আপনাকে চারà§à¦œ করা হতে পারে</translation>
<translation id="5355557959165512791">ওয়েবসাইটটির সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿ তà§à¦²à§‡ নেওয়ার কারণে আপনি à¦à¦–ন <ph name="SITE" /> ঠযেতে পারবেন না। নেটওয়ারà§à¦• সমসà§à¦¯à¦¾ à¦à¦¬à¦‚ আকà§à¦°à¦®à¦£ সাধারণত সাময়িকভাবে হয়, তাই à¦à¦‡ পৃষà§à¦ à¦¾à¦Ÿà¦¿ সমà§à¦­à¦¬à¦¤ পরে কাজ করবে।</translation>
<translation id="536296301121032821">নীতি সেটিংস সংরকà§à¦·à¦£ করতে বà§à¦¯à¦°à§à¦¥ হয়েছে</translation>
+<translation id="5363309033720083897">আপনার অà§à¦¯à¦¾à¦¡à¦®à¦¿à¦¨à¦¿à¦¸à§à¦Ÿà§à¦°à§‡à¦Ÿà¦°à§‡à¦° তরফ থেকে অনà§à¦®à§‹à¦¦à¦¿à¦¤ সিরিয়াল পোরà§à¦Ÿ</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="5386426401304769735">à¦à¦‡ সাইটের সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿ শৃঙà§à¦–লে SHA-1 বà§à¦¯à¦¬à¦¹à¦¾à¦° করে সà§à¦¬à¦¾à¦•à§à¦·à¦° করা à¦à¦•à¦Ÿà¦¿ সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿ রয়েছে।</translation>
@@ -1190,6 +1223,7 @@
<translation id="5398772614898833570">বিজà§à¦žà¦¾à¦ªà¦¨ বà§à¦²à¦• করা হয়েছে</translation>
<translation id="5400836586163650660">ধূসর</translation>
<translation id="540969355065856584">à¦à¦‡ সারà§à¦­à¦¾à¦° পà§à¦°à¦®à¦¾à¦£ করতে পারেনি যে à¦à¦Ÿà¦¿ <ph name="DOMAIN" />; à¦à¦° নিরাপতà§à¦¤à¦¾ সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿ à¦à¦‡ সময়ে বৈধ নয়। কোনো ভà§à¦² কনফিগারেশনের কারণে অথবা কোনো আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€ আপনার সংযোগ মাà¦à¦ªà¦¥à§‡ আটকে দিচà§à¦›à§‡ বলে à¦à¦®à¦¨à¦Ÿà¦¾ হতে পারে।</translation>
+<translation id="541143247543991491">কà§à¦²à¦¾à¦‰à¦¡ (সমà§à¦ªà§‚রà§à¦£ সিসà§à¦Ÿà§‡à¦®à§‡)</translation>
<translation id="541416427766103491">সà§à¦Ÿà§à¦¯à¦¾à¦•à¦¾à¦° ৪</translation>
<translation id="5421136146218899937">বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚ ডেটা সাফ করà§à¦¨...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> আপনাকে বিজà§à¦žà¦ªà§à¦¤à¦¿ পাঠাতে চায়</translation>
@@ -1203,6 +1237,7 @@
<translation id="5455374756549232013">তà§à¦°à§à¦Ÿà¦¿à¦ªà§‚রà§à¦£ নীতি টাইমসà§à¦Ÿà§à¦¯à¦¾à¦®à§à¦ª</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" />টি}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="5463625433003343978">ডিভাইস খোà¦à¦œà¦¾ হচà§à¦›à§‡...</translation>
<translation id="5469868506864199649">ইতালীয়</translation>
<translation id="5470861586879999274">&amp;সমà§à¦ªà¦¾à¦¦à¦¨à¦¾à¦•à§‡ আবার করà§à¦¨</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1252,7 +1287,6 @@
<translation id="5624120631404540903">পাসওয়ারà§à¦¡à¦—à§à¦²à¦¿ পরিচালনা করà§à¦¨</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="563324245173044180">পà§à¦°à¦¤à¦¾à¦°à¦£à¦¾à¦®à§‚লক কনà§à¦Ÿà§‡à¦¨à§à¦Ÿ বà§à¦²à¦• করা হয়েছে।</translation>
<translation id="5644090287519800334">সাইড 1 ছবি X শিফà§à¦Ÿ</translation>
@@ -1291,12 +1325,12 @@
<translation id="5785756445106461925">উপরনà§à¦¤à§, à¦à¦‡ পৃষà§à¦ à¦¾à¦¤à§‡ অনà§à¦¯à¦¾à¦¨à§à¦¯ সংসà§à¦¥à¦¾à¦¨ অনà§à¦¤à¦°à§à¦­à§à¦•à§à¦¤ রয়েছে যা নিরাপদ নয়৷ à¦à¦‡ সংসà§à¦¥à¦¾à¦¨à¦—à§à¦²à¦¿ টà§à¦°à¦¾à¦¨à¦œà¦¿à¦Ÿà§‡à¦° সময় অনà§à¦¯à¦°à¦¾ দেখতে পাবে à¦à¦¬à¦‚ পৃষà§à¦ à¦¾à¦Ÿà¦¿à¦° চেহারাটি পরিবরà§à¦¤à¦¨ করতে কোনও আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€ à¦à¦° পরিবরà§à¦¤à¦¨ করতে পারেন৷</translation>
<translation id="5786044859038896871">আপনি কি আপনার কারà§à¦¡à§‡à¦° তথà§à¦¯ পূরণ করতে চান?</translation>
<translation id="578633867165174378">Chrome-à¦à¦° হিসেবে আপনার à¦à¦–নই বà§à¦¯à¦¬à¦¹à¦¾à¦° করা পাসওয়ারà§à¦¡à§‡à¦° তথà§à¦¯ চà§à¦°à¦¿ হয়ে গেছে। আমরা সাজেসà§à¦Ÿ করছি à¦à¦–নই à¦à¦‡ পাসওয়ারà§à¦¡ পরিবরà§à¦¤à¦¨ করà§à¦¨à¥¤</translation>
-<translation id="5798290721819630480">পরিবরà§à¦¤à¦¨à¦—à§à¦²à¦¿ খারিজ করবেন?</translation>
<translation id="5803412860119678065">আপনি কি আপনার <ph name="CARD_DETAIL" /> à¦à¦° তথà§à¦¯ পূরণ করতে চান?</translation>
<translation id="5804241973901381774">অনà§à¦®à¦¤à¦¿à¦—à§à¦²à¦¿</translation>
<translation id="5804427196348435412">NFC ডিভাইস বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" />-ঠআপনার সংযোগ à¦à¦•à¦Ÿà¦¿ অপà§à¦°à¦šà¦²à¦¿à¦¤ সাইফার সà§à¦¯à§à¦Ÿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করে à¦à¦¨à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ করা হয়েছে৷</translation>
<translation id="5813119285467412249">&amp;যোগ করাকে পà§à¦¨à¦°à¦¾à¦¯à¦¼ করà§à¦¨</translation>
+<translation id="5817918615728894473">যà§à¦•à§à¦¤ করà§à¦¨</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{আপনি পেমেনà§à¦Ÿ করলে à¦à¦‡ কারà§à¦¡à§‡ চারà§à¦œ করা হবে, তবে à¦à¦Ÿà¦¿à¦° আসল নমà§à¦¬à¦° à¦à¦‡ সাইটের সাথে শেয়ার করা হবে না। অতিরিকà§à¦¤ নিরাপতà§à¦¤à¦¾à¦° জনà§à¦¯, à¦à¦•à¦Ÿà¦¿ অসà§à¦¥à¦¾à§Ÿà§€ সিভিসি জেনারেট করা হবে।}one{আপনি পেমেনà§à¦Ÿ করলে বেছে নেওয়া কারà§à¦¡à¦Ÿà¦¿à¦¤à§‡ চারà§à¦œ করা হবে, তবে à¦à¦Ÿà¦¿à¦° আসল নমà§à¦¬à¦° à¦à¦‡ সাইটের সাথে শেয়ার করা হবে না। অতিরিকà§à¦¤ নিরাপতà§à¦¤à¦¾à¦° জনà§à¦¯, à¦à¦•à¦Ÿà¦¿ অসà§à¦¥à¦¾à§Ÿà§€ সিভিসি জেনারেট করা হবে।}other{আপনি পেমেনà§à¦Ÿ করলে বেছে নেওয়া কারà§à¦¡à¦Ÿà¦¿à¦¤à§‡ চারà§à¦œ করা হবে, তবে à¦à¦Ÿà¦¿à¦° আসল নমà§à¦¬à¦° à¦à¦‡ সাইটের সাথে শেয়ার করা হবে না। অতিরিকà§à¦¤ নিরাপতà§à¦¤à¦¾à¦° জনà§à¦¯, à¦à¦•à¦Ÿà¦¿ অসà§à¦¥à¦¾à§Ÿà§€ সিভিসি জেনারেট করা হবে।}}</translation>
<translation id="5826507051599432481">কমন নেম (CN)</translation>
<translation id="5838278095973806738">à¦à¦‡ সাইটে আপনার কোনো সংবেদনশীল তথà§à¦¯ দেওয়া উচিত হবে না (উদাহরণসà§à¦¬à¦°à§‚প, পাসওয়ারà§à¦¡ বা কà§à¦°à§‡à¦¡à¦¿à¦Ÿ কারà§à¦¡) কারণ আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€à¦°à¦¾ à¦à¦—à§à¦²à¦¿ চà§à¦°à¦¿ করতে পারে।</translation>
@@ -1304,6 +1338,7 @@
<translation id="5855253129151731373">à¦à¦‡ সাইটের হোসà§à¦Ÿà¦¨à§‡à¦® <ph name="LOOKALIKE_DOMAIN" />-à¦à¦° মতো মনে হচà§à¦›à§‡à¥¤ আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€à¦°à¦¾ কখনও কখনও ডোমেনের নামে সামানà§à¦¯ বা সহজে দেখা যায় না à¦à¦®à¦¨ পরিবরà§à¦¤à¦¨ করে কোনও সাইটের নকল করেন।
à¦à¦Ÿà¦¿ ভà§à¦² করে দেখানো হচà§à¦›à§‡ বলে মনে হলে, https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals লিঙà§à¦•à¦Ÿà¦¿ দেখà§à¦¨à¥¤</translation>
+<translation id="5860033963881614850">বনà§à¦§ করà§à¦¨</translation>
<translation id="5862579898803147654">সà§à¦Ÿà§à¦¯à¦¾à¦•à¦¾à¦° ৮</translation>
<translation id="5863847714970149516">পরের পৃষà§à¦ à¦¾à¦¤à§‡ আপনাকে চারà§à¦œ করা হতে পারে</translation>
<translation id="5866257070973731571">ফোন নমà§à¦¬à¦° যোগ করà§à¦¨</translation>
@@ -1320,6 +1355,7 @@
<translation id="5913377024445952699">সà§à¦•à§à¦°à¦¿à¦¨ কà§à¦¯à¦¾à¦ªà¦šà¦¾à¦° পজ করা হয়েছে</translation>
<translation id="59174027418879706">সকà§à¦·à¦®à¦¿à¦¤</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{১টি বà§à¦¯à¦¬à¦¹à§ƒà¦¤ হচà§à¦›à§‡}one{#টি বà§à¦¯à¦¬à¦¹à§ƒà¦¤ হচà§à¦›à§‡}other{#টি বà§à¦¯à¦¬à¦¹à§ƒà¦¤ হচà§à¦›à§‡}}</translation>
<translation id="5921185718311485855">চালৠকরা আছে</translation>
<translation id="5921639886840618607">Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡ কারà§à¦¡ সেভ করবেন?</translation>
<translation id="5922853866070715753">পà§à¦°à¦¾à¦¯à¦¼ শেষ</translation>
@@ -1339,6 +1375,7 @@
<translation id="5989320800837274978">কোনো নিরà§à¦§à¦¾à¦°à¦¿à¦¤ পà§à¦°à¦•à§à¦¸à¦¿ সারà§à¦­à¦¾à¦° অথবা à¦à¦•à¦Ÿà¦¿.pac সà§à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ UR সà§à¦°à§à¦¨à¦¿à¦¦à¦¿à¦·à§à¦Ÿà¦­à¦¾à¦¬à§‡ উলà§à¦²à§‡à¦– করা হয়নি৷</translation>
<translation id="5992691462791905444">ইঞà§à¦œà¦¿à¦¨à¦¿à§Ÿà¦¾à¦°à¦¿à¦‚ জেড-ফোলà§à¦¡</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />'-à¦à¦° জনà§à¦¯ <ph name="RESULT_COUNT" />টি ফলাফল</translation>
+<translation id="6006484371116297560">কà§à¦²à¦¾à¦¸à¦¿à¦•</translation>
<translation id="6008122969617370890">N-to-1 অরà§à¦¡à¦¾à¦°</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">আপনার পাসওয়ারà§à¦¡ চেক করà§à¦¨</translation>
@@ -1360,6 +1397,7 @@
<translation id="6045164183059402045">ইমà§à¦ªà§‹à¦œà¦¿à¦¶à¦¨ টেমপà§à¦²à§‡à¦Ÿ</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="6049004884579590341">সমà§à¦ªà§‚রà§à¦£ সà§à¦•à§à¦°à¦¿à¦¨ মোড থেকে বেরোতে |<ph name="ACCELERATOR" />| টিপে ধরে রাখà§à¦¨</translation>
<translation id="6049488691372270142">পৃষà§à¦ à¦¾à¦° ডেলিভারি</translation>
<translation id="6051221802930200923">ওয়েবসাইটটি পিন করা সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করার কারণে আপনি à¦à¦–ন <ph name="SITE" /> ঠযেতে পারবেন না। নেটওয়ারà§à¦• সমসà§à¦¯à¦¾ à¦à¦¬à¦‚ আকà§à¦°à¦®à¦£ সাধারণত সাময়িকভাবে হয়, তাই à¦à¦‡ পৃষà§à¦ à¦¾à¦Ÿà¦¿ সমà§à¦­à¦¬à¦¤ পরে কাজ করবে।</translation>
<translation id="6051898664905071243">পৃষà§à¦ à¦¾à¦° সংখà§à¦¯à¦¾:</translation>
@@ -1376,6 +1414,7 @@
<translation id="610911394827799129"><ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />-ঠআপনার Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡à¦° অনà§à¦¯à¦¾à¦¨à§à¦¯ ধরনের বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚য়ের ইতিহাস থাকতে পারে</translation>
<translation id="6116338172782435947">কà§à¦²à¦¿à¦ªà¦¬à§‹à¦°à§à¦¡à§‡ কপি করা টেকà§à¦¸à¦Ÿ à¦à¦¬à¦‚ ছবি দেখতে</translation>
<translation id="6120179357481664955">আপনার UPI আইডি মনে আছে?</translation>
+<translation id="6123290840358279103">ভারà§à¦šà§à§Ÿà¦¾à¦² কারà§à¦¡ দেখà§à¦¨</translation>
<translation id="6124432979022149706">Chrome Enterprise কানেকà§à¦Ÿà¦°</translation>
<translation id="6146055958333702838">সব কেবল পরীকà§à¦·à¦¾ করà§à¦¨ à¦à¦¬à¦‚ আপনি বà§à¦¯à¦¬à¦¹à¦¾à¦° করছেন à¦à¦®à¦¨ যেকোনো রাউটার, মডেম বা অনà§à¦¯à¦¾à¦¨à§à¦¯ নেটওয়ারà§à¦• ডিভাইসগà§à¦²à¦¿ আবার চালৠকরà§à¦¨à¥¤</translation>
<translation id="614940544461990577">à¦à¦Ÿà¦¿ করে দেখà§à¦¨:</translation>
@@ -1411,6 +1450,7 @@
<translation id="6289939620939689042">পৃষà§à¦ à¦¾à¦° রঙ</translation>
<translation id="6290238015253830360">আপনার পà§à¦°à¦¸à§à¦¤à¦¾à¦¬à¦¿à¦¤ নিবনà§à¦§à¦—à§à¦²à¦¿ à¦à¦–ানে দেখা যাবে</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome-ঠGoogle অà§à¦¯à¦¾à¦¸à¦¿à¦¸à§à¦Ÿà§à¦¯à¦¾à¦¨à§à¦Ÿ à¦à¦¤à¦•à§à¦·à¦£ পরে বনà§à¦§ হয়ে যাবে:</translation>
<translation id="6305205051461490394"><ph name="URL" /> ঠপৌà¦à¦›à¦¾à¦¨à§‹ যাচà§à¦›à§‡ না</translation>
<translation id="6312113039770857350">Webpage not available</translation>
@@ -1436,6 +1476,7 @@
<translation id="6390200185239044127">অরà§à¦§à§‡à¦• জেড-ফোলà§à¦¡</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> থেকে কপি করে à¦à¦‡ লোকেশনে পেসà§à¦Ÿ করা অà§à¦¯à¦¾à¦¡à¦®à¦¿à¦¨à¦¿à¦¸à§à¦Ÿà§à¦°à§‡à¦Ÿà¦° পলিসির মাধà§à¦¯à¦®à§‡ বà§à¦²à¦• করা হয়েছে</translation>
+<translation id="6398765197997659313">পূরà§à¦£ সà§à¦•à§à¦°à§€à¦£ বনà§à¦§ করà§à¦¨</translation>
<translation id="6401136357288658127">à¦à¦‡ নীতি বনà§à¦§ করে দেওয়া হয়েছে। পরিবরà§à¦¤à§‡ আপনাকে <ph name="NEW_POLICY" /> নীতি বà§à¦¯à¦¬à¦¹à¦¾à¦° করতে হবে।</translation>
<translation id="6404511346730675251">বà§à¦•à¦®à¦¾à¦°à§à¦• সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ করà§à¦¨</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1448,7 +1489,6 @@
<translation id="6428450836711225518">আপনার ফোন নমà§à¦¬à¦° যাচাই করà§à¦¨</translation>
<translation id="6433490469411711332">পরিচিতি তথà§à¦¯ সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ করà§à¦¨</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> সংযোগ করতে পà§à¦°à¦¤à§à¦¯à¦¾à¦–à§à¦¯à¦¾à¦¨ করেছে।</translation>
-<translation id="6434309073475700221">বাতিল</translation>
<translation id="6440503408713884761">à¦à§œà¦¾à¦¨à§‹ হয়েছে</translation>
<translation id="6443406338865242315">কোন কোন à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨ ও পà§à¦²à¦¾à¦—-ইন আপনি ইনসà§à¦Ÿà¦² করেছেন</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1491,6 +1531,7 @@
<translation id="6624427990725312378">পরিচিতির তথà§à¦¯</translation>
<translation id="6626291197371920147">বৈধ কারà§à¦¡ নমà§à¦¬à¦° যোগ করà§à¦¨</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> সারà§à¦š</translation>
+<translation id="6630043285902923878">USB ডিভাইস খোà¦à¦œà¦¾ হচà§à¦›à§‡...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">সাফ করà§à¦¨</translation>
@@ -1506,6 +1547,7 @@
<translation id="6671697161687535275">Chromium থেকে ফরà§à¦® পà§à¦°à¦¸à§à¦¤à¦¾à¦¬à¦¨à¦¾ সরাবেন?</translation>
<translation id="6685834062052613830">সাইন-আউট করে সেট-আপ সমà§à¦ªà§‚রà§à¦£ করà§à¦¨</translation>
<translation id="6687335167692595844">ফনà§à¦Ÿ সাইজের অনà§à¦°à§‹à¦§ করা হয়েছে</translation>
+<translation id="6688743156324860098">আপডেট করà§à¦¨â€¦</translation>
<translation id="6689249931105087298">বà§à¦²à§à¦¯à¦¾à¦• পয়েনà§à¦Ÿ কমà§à¦ªà§à¦°à§‡à¦¶à¦¨à§‡à¦° সাথে রিলেটিভ</translation>
<translation id="6689271823431384964">আপনি সাইন-ইন করে আছেন বলে, Chrome আপনার কারà§à¦¡à¦—à§à¦²à¦¿ Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡ সেভ করতে চান কিনা তা জানতে চাইছে। সেটিংস থেকে আপনি à¦à¦‡ বিকলà§à¦ª পরিবরà§à¦¤à¦¨ করতে পারেন। আপনার অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ থেকেই কারà§à¦¡à¦¹à§‹à¦²à§à¦¡à¦¾à¦°à§‡à¦° নাম পাওয়া গেছে।</translation>
<translation id="6698381487523150993">তৈরি হয়েছে:</translation>
@@ -1521,6 +1563,7 @@
<translation id="6744009308914054259">কানেকশনের জনà§à¦¯ অপেকà§à¦·à¦¾ করার সময়, আপনি ডাউনলোডে গিয়ে অফলাইন নিবনà§à¦§à¦—à§à¦²à¦¿ পড়তে পারেন।</translation>
<translation id="6753269504797312559">নীতি মান</translation>
<translation id="6757797048963528358">আপনার ডিভাইস নিদà§à¦°à¦¾ মোডে গিয়েছে।</translation>
+<translation id="6767985426384634228">ঠিকানা আপডেট করবেন?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">বেগà§à¦¨à¦¿</translation>
@@ -1543,6 +1586,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">পৃষà§à¦ à¦¾à¦Ÿà¦¿ যাতে সহজপাঠà§à¦¯ হয়, তার জনà§à¦¯ Chrome à¦à¦Ÿà¦¿à¦•à§‡ সহজ করে তà§à¦²à§‡à¦›à§‡à¥¤ à¦à¦•à¦Ÿà¦¿ অসà§à¦°à¦•à§à¦·à¦¿à¦¤ কানেকশন বà§à¦¯à¦¬à¦¹à¦¾à¦° করে Chrome আবার মূল পৃষà§à¦ à¦¾à§Ÿ ফিরে à¦à¦¸à§‡à¦›à§‡à¥¤</translation>
<translation id="6891596781022320156">নীতি সà§à¦¤à¦° সমরà§à¦¥à¦¿à¦¤ নয়।</translation>
+<translation id="6895143722905299846">ভারà§à¦šà§à§Ÿà¦¾à¦² সংখà§à¦¯à¦¾:</translation>
<translation id="6895330447102777224">আপনার কারà§à¦¡à¦Ÿà¦¿ নিশà§à¦šà¦¿à¦¤ করা হয়েছে</translation>
<translation id="6897140037006041989">বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€ à¦à¦œà§‡à¦¨à§à¦Ÿ</translation>
<translation id="6898699227549475383">সংসà§à¦¥à¦¾ (O)</translation>
@@ -1578,10 +1622,10 @@
<translation id="7004583254764674281">কারà§à¦¡ আরও দà§à¦°à§à¦¤ কনফারà§à¦® করতে Windows Hello বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨</translation>
<translation id="7006930604109697472">নিরাপদ না হলেও পাঠান</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ছোট বড় করার সেটিংস</translation>
<translation id="7014741021609395734">জà§à¦® লেভেল</translation>
<translation id="7016992613359344582">à¦à¦‡ চারà§à¦œà¦Ÿà¦¿ à¦à¦•à¦¬à¦¾à¦° করা হতে পারে অথবা বারবার করা হতে পারে à¦à¦¬à¦‚ সà§à¦ªà¦·à§à¦Ÿà¦­à¦¾à¦¬à§‡ তথà§à¦¯ নাও থাকতে পারে।</translation>
<translation id="7029809446516969842">পাসওয়ারà§à¦¡</translation>
+<translation id="7030436163253143341">সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿà¦Ÿà¦¿ সঠিক নয়</translation>
<translation id="7031646650991750659">কোন কোন Google Play অà§à¦¯à¦¾à¦ª আপনি ইনসà§à¦Ÿà¦² করেছেন</translation>
<translation id="7050187094878475250">আমি <ph name="DOMAIN" />-ঠসংযোগ করার চেষà§à¦Ÿà¦¾ করেছেন, কিনà§à¦¤à§ সারà§à¦­à¦¾à¦° à¦à¦•à¦Ÿà¦¿ সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿ উপসà§à¦¥à¦¾à¦ªà¦¨ করেছে যার বৈধতার সময়সীমা à¦à¦¤ বেশী যে বিশà§à¦¬à¦¾à¦¸à¦¯à§‹à¦—à§à¦¯ নয়।</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{à¦à¦‡ মà§à¦¹à§‚রà§à¦¤à§‡ কারà§à¦¡à¦Ÿà¦¿ সেভ করা যাবে না}one{à¦à¦‡ মà§à¦¹à§‚রà§à¦¤à§‡ কারà§à¦¡à¦—à§à¦²à¦¿ সেভ করা যাবে না}other{à¦à¦‡ মà§à¦¹à§‚রà§à¦¤à§‡ কারà§à¦¡à¦—à§à¦²à¦¿ সেভ করা যাবে না}}</translation>
@@ -1651,12 +1695,14 @@
<translation id="7300012071106347854">কোবালà§à¦Ÿ নীল</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">বেশি</translation>
+<translation id="7305756307268530424">কম সà§à¦ªà¦¿à¦¡à§‡ শà§à¦°à§ করà§à¦¨</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">কানেকশন সহায়তা</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" বিভাগ লà§à¦•à¦¾à¦¨</translation>
<translation id="733354035281974745">ডিভাইসের সà§à¦¥à¦¾à¦¨à§€à§Ÿ অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿ ওভাররাইড করা</translation>
<translation id="7333654844024768166">আপনি à¦à¦–নই পà§à¦°à¦¤à¦¾à¦°à¦£à¦¾à¦®à§‚লক à¦à¦•à¦Ÿà¦¿ সাইটে নিজের পাসওয়ারà§à¦¡ লিখেছেন। Chromium আপনাকে সাজেসà§à¦Ÿ করছে যে আপনি <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> à¦à¦¬à¦‚ অনà§à¦¯à¦¾à¦¨à§à¦¯ সাইটে যান যেখানে যেখানে আপনি à¦à¦‡ পাসওয়ারà§à¦¡à¦Ÿà¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করেন à¦à¦¬à¦‚ à¦à¦–নই সেইসব জায়গায় à¦à¦Ÿà¦¿ পরিবরà§à¦¤à¦¨ করà§à¦¨à¥¤</translation>
<translation id="7334320624316649418">&amp;পà§à¦¨à¦°à§à¦¬à¦¿à¦¨à§à¦¯à¦¾à¦¸à¦•à§‡ আবার করà§à¦¨</translation>
+<translation id="7337248890521463931">বেশি লাইন দেখà§à¦¨</translation>
<translation id="7337706099755338005">আপনার পà§à¦²à§à¦¯à¦¾à¦Ÿà¦«à¦°à§à¦®à§‡ উপলভà§à¦¯ নেই।</translation>
<translation id="733923710415886693">সারà§à¦­à¦¾à¦°à§‡à¦° সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿà¦Ÿà¦¿ সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿà§‡à¦° সà§à¦¬à¦šà§à¦›à¦¤à¦¾à¦° মাধà§à¦¯à¦®à§‡ পà§à¦°à¦•à¦¾à¦¶ করা হয়নি।</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1664,6 +1710,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">কমà§à¦¯à¦¾à¦¨à§à¦¡ লাইন</translation>
<translation id="7359588939039777303">বিজà§à¦žà¦¾à¦ªà¦¨ বà§à¦²à¦• করা হয়েছে।</translation>
+<translation id="7363096869660964304">তবে, আপনি অদৃশà§à¦¯ থাকবেন না। ছদà§à¦®à¦¬à§‡à¦¶à§€ মোড বà§à¦¯à¦¬à¦¹à¦¾à¦° করলেও আপনার বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚ ইতিহাস নিয়োগকরà§à¦¤à¦¾, ইনà§à¦Ÿà¦¾à¦°à¦¨à§‡à¦Ÿ পরিষেবা পà§à¦°à¦¦à¦¾à¦¨à¦•à¦¾à¦°à§€ বা আপনার দেখা ওয়েবসাইটের থেকে লà§à¦•à¦¾à¦¨à§‹ যাবে না।</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome সেটিংসে ঠিকানা যোগ ও মà§à¦¯à¦¾à¦¨à§‡à¦œ করতে পà§à¦°à¦¥à¦®à§‡ Tab, তারপরে Enter পà§à¦°à§‡à¦¸ করà§à¦¨</translation>
<translation id="7365849542400970216">আপনি জানেন আপনার ডিভাইস কী কাজে বà§à¦¯à¦¬à¦¹à¦¾à¦° হয়?</translation>
<translation id="7372973238305370288">ফলাফল খà§à¦à¦œà§à¦¨</translation>
@@ -1674,7 +1721,9 @@
<translation id="7378594059915113390">মিডিয়ার নিয়নà§à¦¤à§à¦°à¦£</translation>
<translation id="7378627244592794276">না</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">পà§à¦°à¦¯à§‹à¦œà§à¦¯ নয়</translation>
<translation id="7390545607259442187">কারà§à¦¡ নিশà§à¦šà¦¿à¦¤ করà§à¦¨</translation>
+<translation id="7392089738299859607">ঠিকানা আপডেট করà§à¦¨</translation>
<translation id="7399802613464275309">নিরাপতà§à¦¤à¦¾ পরীকà§à¦·à¦¾</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">আপনার <ph name="DEVICE_NAME" /> মà§à¦¯à¦¾à¦¨à§‡à¦œ করা হচà§à¦›à§‡</translation>
@@ -1689,6 +1738,7 @@
&lt;li&gt;কমà§à¦ªà¦¿à¦‰à¦Ÿà¦¾à¦° থেকে সফà§à¦Ÿà¦“য়à§à¦¯à¦¾à¦°à¦Ÿà¦¿ সà§à¦¥à¦¾à§Ÿà§€à¦­à¦¾à¦¬à§‡ সরিয়ে দেওয়ার পদà§à¦§à¦¤à¦¿ জানতে &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome সহায়তা কেনà§à¦¦à§à¦°à§‡&lt;/a&gt; যান
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">সà§à¦¨à§à¦¦à¦°</translation>
<translation id="7416351320495623771">পাসওয়ারà§à¦¡à¦—à§à¦²à¦¿ পরিচালনা করà§à¦¨â€¦</translation>
<translation id="7419106976560586862">পà§à¦°à§‹à¦«à¦¾à¦‡à¦² পাথ</translation>
<translation id="7437289804838430631">পরিচিতির তথà§à¦¯ যোগ করà§à¦¨</translation>
@@ -1704,7 +1754,7 @@
<translation id="7481312909269577407">ফরওয়ারà§à¦¡</translation>
<translation id="7485870689360869515">কোনো ডেটা পাওয়া যায়নি৷</translation>
<translation id="7495528107193238112">à¦à¦‡ কনà§à¦Ÿà§‡à¦¨à§à¦Ÿ বà§à¦²à¦• করা হয়েছে। à¦à¦‡ সমসà§à¦¯à¦¾à¦° সমাধান করতে সাইটের মালিকের সাথে যোগাযোগ করà§à¦¨à¥¤</translation>
-<translation id="7498234416455752244">à¦à¦¡à¦¿à¦Ÿ করতে থাকà§à¦¨</translation>
+<translation id="7498193950643227031">ছোট বড় করলে, à¦à¦Ÿà¦¿ অপà§à¦°à¦¤à§à¦¯à¦¾à¦¶à¦¿à¦¤à¦­à¦¾à¦¬à§‡ কাজ করতে পারে। আপনি à¦à¦–ন <ph name="SETTINGS" /> থেকে অà§à¦¯à¦¾à¦ªà§‡à¦° ছোট বড় করার কà§à¦·à¦®à¦¤à¦¾ সীমিত করতে পারেন।</translation>
<translation id="7503664977220660814">আপনি à¦à¦‡à¦®à¦¾à¦¤à§à¦° à¦à¦•à¦Ÿà¦¿ পà§à¦°à¦¤à¦¾à¦°à¦£à¦¾à¦®à§‚লক সাইটে আপনার পাসওয়ারà§à¦¡ লিখেছেন। <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> à¦à¦¬à¦‚ অনà§à¦¯à¦¾à¦¨à§à¦¯ সাইটে, যেখানে যেখানে আপনি à¦à¦‡ পাসওয়ারà§à¦¡à¦Ÿà¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করেন, Chromium আপনাকে সেইসব জায়গায় গিয়ে আপনার সেভ করা পাসওয়ারà§à¦¡à¦—à§à¦²à¦¿ পরিবরà§à¦¤à¦¨ করতে সাজেসà§à¦Ÿ করছে।</translation>
<translation id="7508255263130623398">ফিরে পাওয়া নীতির ডিভাইস আইডি খালি অথবা বরà§à¦¤à¦®à¦¾à¦¨ ডিভাইস আইডির সাথে মিলছে না</translation>
<translation id="7508870219247277067">অà§à¦¯à¦¾à¦­à§‹à¦•à¦¾à¦¡à§‹ সবà§à¦œ</translation>
@@ -1724,6 +1774,7 @@
<translation id="7548892272833184391">কানেকশনের সমসà§à¦¯à¦¾à¦° সমাধান করà§à¦¨</translation>
<translation id="7549584377607005141">ঠিকঠাক ডিসপà§à¦²à§‡ করার জনà§à¦¯ à¦à¦‡ ওয়েবপৃষà§à¦ à¦¾à¦° আপনার আগে দেওয়া ডেটা পà§à¦°à¦¯à§‹à¦œà¦¨à§· আপনি à¦à¦‡ ডেটাটি আবার পাঠাতে পারেন, কিনà§à¦¤à§ à¦à¦®à¦¨à¦Ÿà¦¿ করে আপনি যেকোনো পদকà§à¦·à§‡à¦ªà§‡à¦° পà§à¦¨à¦°à¦¾à¦¬à§ƒà¦¤à§à¦¤à¦¿ করবেন যা à¦à¦‡ পৃষà§à¦ à¦¾à¦Ÿà¦¿ আগেই সমà§à¦ªà¦¾à¦¦à¦¨à¦¾ করেছে৷</translation>
<translation id="7550637293666041147">আপনার ডিভাইসের বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€à¦° নাম à¦à¦¬à¦‚ Chrome-à¦à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦°à¦•à¦¾à¦°à§€à¦° নাম</translation>
+<translation id="755279583747225797">টà§à¦°à¦¾à§Ÿà¦¾à¦² চালৠআছে</translation>
<translation id="7552846755917812628">নিমà§à¦¨à§‹à¦²à§à¦²à¦¿à¦–িত টিপà§à¦¸ বà§à¦¯à¦¬à¦¹à¦¾à¦° করে দেখà§à¦¨:</translation>
<translation id="7554475479213504905">ঠিক আছে, আবার লোড করে দেখান</translation>
<translation id="7554791636758816595">নতà§à¦¨ টà§à¦¯à¦¾à¦¬</translation>
@@ -1742,7 +1793,6 @@
<translation id="7610193165460212391">সীমার বাইরে মান <ph name="VALUE" />৷</translation>
<translation id="7613889955535752492">মেয়াদোতà§à¦¤à§€à¦°à§à¦£: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome সেটিংসে আপনার পাসওয়ারà§à¦¡ দেখতে ও মà§à¦¯à¦¾à¦¨à§‡à¦œ করতে পà§à¦°à¦¥à¦®à§‡ Tab আর তারপরে Enter পà§à¦°à§‡à¦¸ করà§à¦¨</translation>
-<translation id="7615602087246926389">আপনার কাছে ইতিমধà§à¦¯à§‡à¦‡ à¦à¦®à¦¨ ডেটা আছে যা Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡à¦° পাসওয়ারà§à¦¡à§‡à¦° কোনো ভিনà§à¦¨ ভারà§à¦¸à¦¨ বà§à¦¯à¦¬à¦¹à¦¾à¦°à§‡à¦° দà§à¦¬à¦¾à¦°à¦¾ à¦à¦¨à¦•à§à¦°à¦¿à¦ªà§à¦Ÿ করা হয়৷ অনà§à¦—à§à¦°à¦¹ করে à¦à¦Ÿà¦¿à¦•à§‡ নিচে লিখà§à¦¨à§·</translation>
<translation id="7616645509853975347">আপনার অà§à¦¯à¦¾à¦¡à¦®à¦¿à¦¨à¦¿à¦¸à§à¦Ÿà§à¦°à§‡à¦Ÿà¦° Chrome Enterprise কানেকà§à¦Ÿà¦°à¦—à§à¦²à¦¿à¦•à§‡ আপনার বà§à¦°à¦¾à¦‰à¦œà¦¾à¦°à§‡ চালৠকরেছে। à¦à¦‡ কানেকà§à¦Ÿà¦° আপনার কিছৠডেটা অà§à¦¯à¦¾à¦•à§à¦¸à§‡à¦¸ করতে পারবে।</translation>
<translation id="7619838219691048931">শেষ শিট</translation>
<translation id="762844065391966283">à¦à¦• à¦à¦• করে</translation>
@@ -1807,13 +1857,12 @@
<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" />)}one{#টি অà§à¦¯à¦¾à¦ª (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}other{#টি অà§à¦¯à¦¾à¦ª (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">আপনি অবশà§à¦¯ অদৃশà§à¦¯ থাকবেন না। ছদà§à¦®à¦¬à§‡à¦¶à§€ মোডে গেলেও তা আপনার নিয়োগকরà§à¦¤à¦¾, আপনার ইনà§à¦Ÿà¦¾à¦°à¦¨à§‡à¦Ÿ পরিষেবা পà§à¦°à¦¦à¦¾à¦¨à¦•à¦¾à¦°à§€ অথবা আপনার পরিদরà§à¦¶à¦¨ করা ওয়েবসাইট থেকে আপনার বà§à¦°à¦¾à¦‰à¦œà¦¿à¦‚কে আড়াল করবে না।</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ফাইল টাইপ অà§à¦¯à¦¾à¦¸à§‹à¦¸à¦¿à§Ÿà§‡à¦¶à¦¨à§‡à¦° সাহাযà§à¦¯à§‡ ফাইল খà§à¦²à§à¦¨à¥¤</translation>
<translation id="7862185352068345852">সাইট ছেড়ে যাবেন?</translation>
<translation id="7865448901209910068">সরà§à¦¬à§‹à¦šà§à¦š গতি</translation>
<translation id="7874263914261512992">আপনি à¦à¦‡à¦®à¦¾à¦¤à§à¦° à¦à¦•à¦Ÿà¦¿ পà§à¦°à¦¤à¦¾à¦°à¦£à¦¾à¦®à§‚লক সাইটে আপনার পাসওয়ারà§à¦¡ লিখেছেন। <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> à¦à¦¬à¦‚ অনà§à¦¯à¦¾à¦¨à§à¦¯ সাইটে, যেখানে যেখানে আপনি à¦à¦‡ পাসওয়ারà§à¦¡à¦Ÿà¦¿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করেন, Chrome আপনাকে সেইসব জায়গায় গিয়ে আপনার সেভ করা পাসওয়ারà§à¦¡à¦—à§à¦²à¦¿ পরিবরà§à¦¤à¦¨ করতে সাজেসà§à¦Ÿ করছে।</translation>
<translation id="7878562273885520351">আপনার পাসওয়ারà§à¦¡ অনà§à¦¯ কেউ পরিবরà§à¦¤à¦¨ করার চেষà§à¦Ÿà¦¾ করেছে</translation>
+<translation id="7880146494886811634">ঠিকানা সেভ করà§à¦¨</translation>
<translation id="7882421473871500483">খয়েরি</translation>
<translation id="7887683347370398519">আপনার CVC পরীকà§à¦·à¦¾ করে আবার চেষà§à¦Ÿà¦¾ করà§à¦¨</translation>
<translation id="7887885240995164102">'ছবির-মধà§à¦¯à§‡-ছবি' মোডে পà§à¦°à¦¬à§‡à¦¶ করà§à¦¨</translation>
@@ -1821,6 +1870,7 @@
<translation id="7894280532028510793">বানান সঠিক হলে, <ph name="BEGIN_LINK" />'নেটওয়ারà§à¦• ডায়াগনসà§à¦Ÿà¦¿à¦•' টà§à¦² চালিয়ে দেখà§à¦¨<ph name="END_LINK" />।</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">অজানা</translation>
+<translation id="793209273132572360">ঠিকানা আপডেট করবেন?</translation>
<translation id="7932579305932748336">কোট</translation>
<translation id="79338296614623784">à¦à¦•à¦Ÿà¦¿ সঠিক ফোন নমà§à¦¬à¦° লিখà§à¦¨</translation>
<translation id="7934052535022478634">পেমেনà§à¦Ÿ হয়ে গেছে</translation>
@@ -1891,6 +1941,7 @@
<translation id="8175796834047840627">আপনি সাইন-ইন করে রয়েছেন বলে, Chrome আপনার কারà§à¦¡à¦—à§à¦²à¦¿ আপনার Google অà§à¦¯à¦¾à¦•à¦¾à¦‰à¦¨à§à¦Ÿà§‡ সেভ করার অফার করছে। সেটিংসে গিয়ে à¦à¦‡ আচরণটি পরিবরà§à¦¤à¦¨ করতে পারেন।</translation>
<translation id="8176440868214972690">à¦à¦‡ ডিভাইসের অà§à¦¯à¦¾à¦¡à¦®à¦¿à¦¨à¦¿à¦¸à§à¦Ÿà§à¦°à§‡à¦Ÿà¦° নিমà§à¦¨à¦²à¦¿à¦–িত ওয়েবসাইটগà§à¦²à¦¿à¦•à§‡ সেটিংস বা নীতির মতো কিছৠতথà§à¦¯ পাঠিয়েছে।</translation>
<translation id="8184538546369750125">বিশà§à¦¬à¦¬à§à¦¯à¦¾à¦ªà§€ ডিফলà§à¦Ÿ বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨ (অনà§à¦®à¦¤à¦¿ দিন)</translation>
+<translation id="8193086767630290324">গোপন হিসেবে চিহà§à¦¨à¦¿à¦¤ ডেটা বà§à¦¯à¦¬à¦¹à¦¾à¦° করে যে অà§à¦¯à¦¾à¦•à¦¶à¦¨ নেওয়া হয়েছে</translation>
<translation id="8194797478851900357">&amp;সরানোকে পূরà§à¦¬à¦¾à¦¬à¦¸à§à¦¥à¦¾à¦¯à¦¼ ফেরান</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" ID যà§à¦•à§à¦¤ à¦à¦•à§à¦¸à¦Ÿà§‡à¦¨à¦¶à¦¨à§‡à¦° ভà§à¦² আপডেট ইউআরà¦à¦²à¥¤</translation>
<translation id="8202097416529803614">অরà§à¦¡à¦¾à¦°à§‡à¦° সারসংকà§à¦·à§‡à¦ª</translation>
@@ -1913,6 +1964,7 @@
<translation id="8249296373107784235">বাতিল</translation>
<translation id="8249320324621329438">সরà§à¦¬à¦¶à§‡à¦· পà§à¦°à¦¾à¦ªà§à¦¤ করেছে:</translation>
<translation id="8253091569723639551">বিলিং ঠিকানা পà§à¦°à¦¯à¦¼à§‹à¦œà¦¨</translation>
+<translation id="8257387598443225809">à¦à¦‡ অà§à¦¯à¦¾à¦ªà¦Ÿà¦¿ মোবাইলের কথা ভেবে তৈরি করা হয়েছে</translation>
<translation id="825929999321470778">সেভ করা সমসà§à¦¤ পাসওয়ারà§à¦¡ দেখান</translation>
<translation id="8261506727792406068">মà§à¦›à§à¦¨</translation>
<translation id="8262952874573525464">নিচে ধারের দিকে সেলাই</translation>
@@ -2036,7 +2088,6 @@
<translation id="8719528812645237045">উপরে মালà§à¦Ÿà¦¿à¦ªà¦² পাঞà§à¦š</translation>
<translation id="8725066075913043281">আবার চেষà§à¦Ÿà¦¾ করà§à¦¨</translation>
<translation id="8726549941689275341">পৃষà§à¦ à¦¾à¦° সাইজ:</translation>
-<translation id="8728672262656704056">আপনি গà§à¦ªà§à¦¤ মোডে চলে গেছেন</translation>
<translation id="8730621377337864115">হয়ে গেছে</translation>
<translation id="8731544501227493793">পাসওয়ারà§à¦¡ মà§à¦¯à¦¾à¦¨à§‡à¦œ করার বোতাম, Chrome সেটিংসে আপনার পাসওয়ারà§à¦¡ দেখতে ও মà§à¦¯à¦¾à¦¨à§‡à¦œ করতে Enter পà§à¦°à§‡à¦¸ করà§à¦¨</translation>
<translation id="8734529307927223492">আপনার <ph name="DEVICE_TYPE" />, <ph name="MANAGER" />-à¦à¦° মাধà§à¦¯à¦®à§‡ মà§à¦¯à¦¾à¦¨à§‡à¦œ করা হয়</translation>
@@ -2113,6 +2164,7 @@
<translation id="9020542370529661692">à¦à¦‡ পৃষà§à¦ à¦¾à¦Ÿà¦¿ <ph name="TARGET_LANGUAGE" /> ঠঅনà§à¦¬à¦¾à¦¦ করা হয়েছে</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ভà§à¦²)</translation>
+<translation id="9030265603405983977">মোনোকà§à¦°à§‹à¦®</translation>
<translation id="9035022520814077154">নিরাপতà§à¦¤à¦¾ তà§à¦°à§à¦Ÿà¦¿</translation>
<translation id="9038649477754266430">পৃষà§à¦ à¦¾ আরও দà§à¦°à§à¦¤ লোড করার জনà§à¦¯ কোনো পূরà§à¦¬à¦¾à¦­à¦¾à¦· পরিষেবা বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨</translation>
<translation id="9039213469156557790">উপরনà§à¦¤à§, à¦à¦‡ পৃষà§à¦ à¦¾à¦¤à§‡ অনà§à¦¯à¦¾à¦¨à§à¦¯ সংসà§à¦¥à¦¾à¦¨ অনà§à¦¤à¦°à§à¦­à§à¦•à§à¦¤ রয়েছে যা নিরাপদ নয়৷ à¦à¦‡ সংসà§à¦¥à¦¾à¦¨à¦—à§à¦²à¦¿ টà§à¦°à¦¾à¦¨à¦œà¦¿à¦Ÿà§‡à¦° সময় অনà§à¦¯à¦°à¦¾ দেখতে পাবে à¦à¦¬à¦‚ পৃষà§à¦ à¦¾à¦Ÿà¦¿à¦° আচরণ পরিবরà§à¦¤à¦¨ করার জনà§à¦¯ কোনো আকà§à¦°à¦®à¦£à¦•à¦¾à¦°à§€ à¦à¦° পরিবরà§à¦¤à¦¨ করতে পারেন৷</translation>
@@ -2136,6 +2188,7 @@
<translation id="91108059142052966">কোনও গোপন কনà§à¦Ÿà§‡à¦¨à§à¦Ÿ দেখা গেলে 'অà§à¦¯à¦¾à¦¡à¦®à¦¿à¦¨à¦¿à¦¸à§à¦Ÿà§à¦°à§‡à¦Ÿà¦° নীতি' অনà§à¦¯à¦¾à§Ÿà§€ <ph name="APPLICATION_TITLE" />-à¦à¦° সাথে সà§à¦•à§à¦°à¦¿à¦¨ শেয়ার করা হবে না</translation>
<translation id="9114524666733003316">কারà§à¦¡ নিশà§à¦šà¦¿à¦¤ করা হচà§à¦›à§‡...</translation>
<translation id="9114581008513152754">কোনও কোমà§à¦ªà¦¾à¦¨à¦¿ বা অনà§à¦¯ কোনও সংসà§à¦¥à¦¾ à¦à¦‡ বà§à¦°à¦¾à¦‰à¦œà¦¾à¦° মà§à¦¯à¦¾à¦¨à§‡à¦œ করে না। à¦à¦‡ ডিভাইসের অà§à¦¯à¦¾à¦•à§à¦Ÿà¦¿à¦­à¦¿à¦Ÿà¦¿ Chrome-à¦à¦° বাইরে থেকে মà§à¦¯à¦¾à¦¨à§‡à¦œ করা যেতে পারে। <ph name="BEGIN_LINK" />আরও জানà§à¦¨<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">তাজা</translation>
<translation id="9119042192571987207">আপলোড করা হয়েছে</translation>
<translation id="9128016270925453879">নীতি লোড হয়েছে</translation>
<translation id="9128870381267983090">নেটওয়ারà§à¦•à§‡ সংযোগ করà§à¦¨</translation>
@@ -2154,6 +2207,7 @@
<translation id="9170848237812810038">&amp;পূরà§à¦¬à¦¾à¦¬à¦¸à§à¦¥à¦¾à§Ÿ ফিরà§à¦¨</translation>
<translation id="9171296965991013597">অà§à¦¯à¦¾à¦ª থেকে বেরিয়ে আসতে চান?</translation>
<translation id="9173282814238175921">à¦à¦•à¦• ডকà§à¦®à§‡à¦¨à§à¦Ÿ/নতà§à¦¨ শিট</translation>
+<translation id="9173995187295789444">বà§à¦²à§à¦Ÿà§à¦¥ ডিভাইসগà§à¦²à¦¿à¦° জনà§à¦¯ সà§à¦•à§à¦¯à¦¾à¦¨ করা হচà§à¦›à§‡...</translation>
<translation id="917450738466192189">সারà§à¦­à¦¾à¦°à§‡à¦° সারà§à¦Ÿà¦¿à¦«à¦¿à¦•à§‡à¦Ÿ অকারà§à¦¯à¦•à¦°à§·</translation>
<translation id="9174917557437862841">টà§à¦¯à¦¾à¦¬ সà§à¦‡à¦š বোতাম, à¦à¦‡ টà§à¦¯à¦¾à¦¬à§‡ পরিবরà§à¦¤à¦¨ করতে à¦à¦¨à§à¦Ÿà¦¾à¦° পà§à¦°à§‡à¦¸ করà§à¦¨</translation>
<translation id="9179703756951298733">Chrome সেটিংস থেকে আপনার পেমেনà§à¦Ÿ ও কà§à¦°à§‡à¦¡à¦¿à¦Ÿ কারà§à¦¡à§‡à¦° তথà§à¦¯ মà§à¦¯à¦¾à¦¨à§‡à¦œ করà§à¦¨</translation>
diff --git a/chromium/components/strings/components_strings_bs.xtb b/chromium/components/strings/components_strings_bs.xtb
index f5ea8797fe9..83d42a5bb81 100644
--- a/chromium/components/strings/components_strings_bs.xtb
+++ b/chromium/components/strings/components_strings_bs.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Ako je oznaÄeno, Chrome će saÄuvati kopiju vaÅ¡e kartice na ovaj ureÄ‘aj zbog bržeg popunjavanja obrazaca.</translation>
<translation id="1110994991967754504">Odaberite odobrenje za <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">Poništi pre&amp;uređenje</translation>
+<translation id="1123753900084781868">Automatski titlovi trenutno nisu dostupni</translation>
<translation id="1125573121925420732">Upozorenja mogu biti uobiÄajena dok web-lokacije ažuriraju sigurnost. To bi se uskoro trebalo poboljÅ¡ati.</translation>
<translation id="112840717907525620">Keš memorija pravila UREDU</translation>
<translation id="1130564665089811311">Dugme Prevedi stranicu, pritisnite Enter da prevedete ovu stranicu pomoću Google Prevodioca</translation>
@@ -74,6 +75,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="1240347957665416060">Naziv vašeg uređaja</translation>
<translation id="124116460088058876">Više jezika</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Podebljano</translation>
<translation id="1250759482327835220">Da biste sljedeći put platili brže, spremite karticu, ime i adresu za naplatu na svoj Google raÄun.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sinhronizirano)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ako pokušate posjetiti web lokaciju i ona se ne otvori, najprije pokušajte riješiti grešku ovim koracima za rješavanje problema:&lt;/p&gt;
@@ -156,6 +158,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="1476595624592550506">Promijenite lozinku</translation>
<translation id="1484290072879560759">Odaberite adresu za dostavu</translation>
<translation id="1492194039220927094">Slanje pravila:</translation>
+<translation id="1495677929897281669">Natrag na karticu</translation>
<translation id="1501859676467574491">Prikažite kartice s Google raÄuna</translation>
<translation id="1507202001669085618">&lt;p&gt;Ova greška će se prikazati ako koristite WiFi portal na koji se morate prijaviti za povezivanje na internet.&lt;/p&gt;
&lt;p&gt;Za ispravljanje greške, kliknite na &lt;strong&gt;Poveži se&lt;/strong&gt; na stranici koju pokušavate otvoriti.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="1532118530259321453">Na ovoj stranici piše</translation>
<translation id="153384715582417236">To je sve za sada</translation>
<translation id="1536390784834419204">Prevedi stranicu</translation>
+<translation id="1539840569003678498">Prijava je poslana:</translation>
<translation id="154408704832528245">Odaberite adresu za isporuku</translation>
<translation id="1549470594296187301">Za korištenje ove funkcije trebate omogućiti JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -180,7 +184,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="1559528461873125649">Nema takvog fajla ili direktorijuma</translation>
<translation id="1559572115229829303">&lt;p&gt;Nije moguće uspostaviti privatnu vezu s domenom <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> jer datum i vrijeme (<ph name="DATE_AND_TIME" />) na vaÅ¡em ureÄ‘aju nisu taÄni.&lt;/p&gt;
- &lt;p&gt;Podesite datum i vrijeme iz odjeljka &lt;strong&gt;Općenito&lt;/strong&gt; u aplikaciji &lt;strong&gt;Postavke&lt;/strong&gt;.&lt;/p&gt;</translation>
+ &lt;p&gt;Podesite datum i vrijeme iz odjeljka &lt;strong&gt;Opće&lt;/strong&gt; u aplikaciji &lt;strong&gt;Postavke&lt;/strong&gt;.&lt;/p&gt;</translation>
<translation id="1567040042588613346">Ovo pravilo radi kako je predviđeno, ali je ista vrijednost postavljena negdje drugo i ovo pravilo ju je zaobišlo.</translation>
<translation id="1569487616857761740">Unesite datum isteka</translation>
<translation id="1581080074034554886">CVC</translation>
@@ -213,16 +217,19 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="1682696192498422849">Najprije kratka strana</translation>
<translation id="168693727862418163">Vrijednost ovog pravila u odnosu na njegovu šemu nije potvrđena pa će biti zanemareno.</translation>
<translation id="168841957122794586">Potvrda servera sadrži slab kriptografski kljuÄ.</translation>
+<translation id="1696290444144917273">Pogledajte detalje virtuelne kartice</translation>
<translation id="1697532407822776718">Sve je spremno!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Ovaj server nije uspio dokazati da predstavlja domenu <ph name="DOMAIN" />; njegova potvrda sigurnosti je navodno izdata sutra. Uzrok tome može biti pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vaÅ¡u vezu.}one{Ovaj server nije uspio dokazati da predstavlja domenu <ph name="DOMAIN" />; njegova potvrda sigurnosti je navodno izdata # dan u budućnosti. Uzrok tome može biti pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vaÅ¡u vezu.}few{Ovaj server nije uspio dokazati da predstavlja domenu <ph name="DOMAIN" />; njegova potvrda sigurnosti je navodno izdata # dana u budućnosti. Uzrok tome može biti pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vaÅ¡u vezu.}other{Ovaj server nije uspio dokazati da predstavlja domenu <ph name="DOMAIN" />; njegova potvrda sigurnosti je navodno izdata # dana u budućnosti. Uzrok tome može biti pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vaÅ¡u vezu.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Zanemareno je jer pravilo <ph name="POLICY_NAME" /> nije postavljeno na <ph name="VALUE" />.</translation>
<translation id="1712552549805331520">URL <ph name="URL" /> želi trajno pohraniti podatke na vaÅ¡ lokalni raÄunar</translation>
<translation id="1713628304598226412">Ladica 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">PoÅ¡tansko sanduÄe 3</translation>
<translation id="1718029547804390981">Dokument je prevelik da bi se obilježio</translation>
<translation id="1721424275792716183">* Obavezno polje</translation>
+<translation id="1727613060316725209">Certifikat je važeći</translation>
<translation id="1727741090716970331">Dodajte važeći broj kartice</translation>
<translation id="1728677426644403582">Pregledate izvor web stranice</translation>
<translation id="173080396488393970">Ova vrsta kartice nije podržana</translation>
@@ -246,7 +253,6 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
vaš zahtjev za web lokaciju <ph name="SITE" />. Operateri web lokacija mogu koristiti izvorna pravila
za konfiguriranje sigurnosti i drugih osobina web lokacije.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Ažurirajte pristupni izraz za sinhronizaciju.</translation>
<translation id="1787142507584202372">Ovdje se prikazuju vaše otvorene kartice</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Dostupno je više radnji. Pritisnite Tab da ih prelistate</translation>
@@ -279,6 +285,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="1919345977826869612">Oglasi</translation>
<translation id="1919367280705858090">Potražite pomoć za određene poruke o greškama</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Nema}=1{1 web lokacija}one{# web lokacija}few{# web lokacije}other{# web lokacija}}</translation>
+<translation id="1924727005275031552">Novo</translation>
<translation id="1945968466830820669">Možete izgubiti pristup raÄunu svoje organizacije ili doživjeti kraÄ‘u identiteta. Chromium preporuÄuje da odmah promijenite lozinku.</translation>
<translation id="1947454675006758438">Spajanje u gornjem desnom uglu</translation>
<translation id="1958218078413065209">Vaš najbolji rezultat je <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="2042213636306070719">Ladica 7</translation>
<translation id="204357726431741734">Prijavite se da koristite lozinke saÄuvane na Google raÄunu</translation>
<translation id="2053111141626950936">Stranice Äiji jezik je <ph name="LANGUAGE" />, neće se prevoditi.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Kada je ova kontrola ukljuÄena i status aktivan, Chrome odreÄ‘uje kojoj je velikoj grupi ljudi, ili "kohorti", vaÅ¡a nedavna aktivnost pregledanja najsliÄnija. OglaÅ¡ivaÄi mogu odabrati oglase za tu grupu, a vaÅ¡a aktivnost pregledanja ostaje privatna na vaÅ¡em ureÄ‘aju. VaÅ¡a grupa se ažurira svaki dan.}=1{Kada je ova kontrola ukljuÄena i status aktivan, Chrome odreÄ‘uje kojoj je velikoj grupi ljudi, ili "kohorti", vaÅ¡a nedavna aktivnost pregledanja najsliÄnija. OglaÅ¡ivaÄi mogu odabrati oglase za tu grupu, a vaÅ¡a aktivnost pregledanja ostaje privatna na vaÅ¡em ureÄ‘aju. VaÅ¡a grupa se ažurira svaki dan.}one{Kada je ova kontrola ukljuÄena i status aktivan, Chrome odreÄ‘uje kojoj je velikoj grupi ljudi, ili "kohorti", vaÅ¡a nedavna aktivnost pregledanja najsliÄnija. OglaÅ¡ivaÄi mogu odabrati oglase za tu grupu, a vaÅ¡a aktivnost pregledanja ostaje privatna na vaÅ¡em ureÄ‘aju. VaÅ¡a grupa se ažurira svakih {NUM_DAYS} dan.}few{Kada je ova kontrola ukljuÄena i status aktivan, Chrome odreÄ‘uje kojoj je velikoj grupi ljudi, ili "kohorti", vaÅ¡a nedavna aktivnost pregledanja najsliÄnija. OglaÅ¡ivaÄi mogu odabrati oglase za tu grupu, a vaÅ¡a aktivnost pregledanja ostaje privatna na vaÅ¡em ureÄ‘aju. VaÅ¡a grupa se ažurira svaka {NUM_DAYS} dana.}other{Kada je ova kontrola ukljuÄena i status aktivan, Chrome odreÄ‘uje kojoj je velikoj grupi ljudi, ili "kohorti", vaÅ¡a nedavna aktivnost pregledanja najsliÄnija. OglaÅ¡ivaÄi mogu odabrati oglase za tu grupu, a vaÅ¡a aktivnost pregledanja ostaje privatna na vaÅ¡em ureÄ‘aju. VaÅ¡a grupa se ažurira svakih {NUM_DAYS} dana.}}</translation>
<translation id="2053553514270667976">Poštanski broj</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{Jedan prijedlog}one{# prijedlog}few{# prijedloga}other{# prijedloga}}</translation>
<translation id="2071692954027939183">ObavjeÅ¡tenja su automatski blokirana jer ih obiÄno ne dozvoljavate</translation>
<translation id="2079545284768500474">Vrati</translation>
<translation id="20817612488360358">Postavke sistema proksi servera su postavljene za korištenje, ali je određena i eksplicitna konfiguracija proksi servera.</translation>
<translation id="2082238445998314030">Rezultat <ph name="RESULT_NUMBER" /> od <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">SaÄuvaj…</translation>
<translation id="2088086323192747268">Dugme Upravljajte sinhronizacijom, pritisnite Enter da upravljate time koje će se informacije sinhronizirati u postavkama Chromea</translation>
<translation id="2091887806945687916">Zvuk</translation>
<translation id="2094505752054353250">Nepodudaranje domene</translation>
@@ -379,6 +388,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="2317259163369394535"><ph name="DOMAIN" /> zahtijeva korisniÄko ime i zaporku.</translation>
<translation id="2330137317877982892">Kartica <ph name="CREDIT_CARD" />, istiÄe <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Postavkom upravlja administrator</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> se želi upariti</translation>
<translation id="2344028582131185878">Automatska preuzimanja</translation>
<translation id="2346319942568447007">Slika koju ste kopirali</translation>
<translation id="2354001756790975382">Ostale oznake</translation>
@@ -386,8 +396,10 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="2355395290879513365">NapadaÄi mogu vidjeti slike koje gledate na ovoj web lokaciji i navesti vas da ih izmijenite.</translation>
<translation id="2356070529366658676">Pitaj</translation>
<translation id="2357481397660644965">VaÅ¡im ureÄ‘ajem upravlja <ph name="DEVICE_MANAGER" />, a vaÅ¡im raÄunom upravlja <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Za manje od jednog dana}=1{Za jedan dan}one{Za {NUM_DAYS} dan}few{Za {NUM_DAYS} dana}other{Za {NUM_DAYS} dana}}</translation>
<translation id="2359629602545592467">Veći broj</translation>
<translation id="2359808026110333948">Nastavi</translation>
+<translation id="2359961752320758691">Broj virtuelne kartice je primijenjen.</translation>
<translation id="2367567093518048410">Razina</translation>
<translation id="2372464001869762664">Nakon vaÅ¡e potvrde, detalji o kartici s vaÅ¡eg Google raÄuna će se dijeliti s ovom web lokacijom. PronaÄ‘ite CVC u detaljima Plex raÄuna.</translation>
<translation id="2380886658946992094">Pravo</translation>
@@ -398,6 +410,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="239429038616798445">Ovaj naÄin isporuke nije dostupan. Probajte drugi naÄin.</translation>
<translation id="2396249848217231973">&amp;Poništi brisanje</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Staro</translation>
<translation id="2413528052993050574">Ovaj server nije uspio dokazati da je <ph name="DOMAIN" />; možda je njegova potvrda sigurnosti opozvana. Uzrok tome može biti pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vaÅ¡u vezu.</translation>
<translation id="2414886740292270097">Tamno</translation>
<translation id="2438874542388153331">Četverostruko bušenje na desnoj strani</translation>
@@ -425,10 +438,10 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="2521385132275182522">Spajanje u donjem desnom uglu</translation>
<translation id="2523886232349826891">SaÄuvano iskljuÄivo na ovom ureÄ‘aju</translation>
<translation id="2524461107774643265">Dodajte više informacija</translation>
-<translation id="2526590354069164005">Radna površina</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{i još 1}one{i još #}few{i još #}other{i još #}}</translation>
<translation id="2536110899380797252">Dodaj adresu</translation>
<translation id="2539524384386349900">Otkrij</translation>
+<translation id="2541219929084442027">Stranice koje pregledate u anonimnim karticama neće ostati u historiji preglednika, pohrani kolaÄića ili historiji pretraživanja nakon Å¡to zatvorite sve anonimne kartice. Zadržat će se svi fajlovi koje preuzmete ili oznake koje kreirate.</translation>
<translation id="2544644783021658368">Jedan dokument</translation>
<translation id="254947805923345898">Vrijednost pravila nije važeća.</translation>
<translation id="255002559098805027">Host raÄunar <ph name="HOST_NAME" /> je poslao nevažeći odgovor.</translation>
@@ -448,6 +461,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="2629325967560697240">Da postignete najviÅ¡i nivo sigurnosti Chromea, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ukljuÄite poboljÅ¡anu zaÅ¡titu<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">IP adresa poslužitelja hosta <ph name="HOST_NAME" /> nije pronađena.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Nije pronađen nijedan kompatibilni uređaj.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. Pritisnite Tab, a zatim Enter da obriÅ¡ete historiju pregledanja, kolaÄiće, keÅ¡ memoriju i drugi sadržaj u postavkama Chromea</translation>
<translation id="2650446666397867134">Pristup fajlu je odbijen</translation>
@@ -494,6 +508,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="2799223571221894425">Ponovo pokreni</translation>
<translation id="2803306138276472711">Sigurno pregledanje na Googleu je nedavno <ph name="BEGIN_LINK" />otkrilo zlonamjerni softver<ph name="END_LINK" /> na <ph name="SITE" />. Web lokacije koje su inaÄe sigurne, ponekad se zaraze zlonamjernim softverom.</translation>
<translation id="2807052079800581569">Y položaj slike</translation>
+<translation id="2820957248982571256">Skeniranje...</translation>
<translation id="2824775600643448204">Traka za adresu i pretraživanje</translation>
<translation id="2826760142808435982">Veza je šifrirana i autentificirana koristeći <ph name="CIPHER" /> i koristi <ph name="KX" /> kao glavni mehanizam za razmjenu.</translation>
<translation id="2835170189407361413">Obriši polja obrasca</translation>
@@ -501,6 +516,8 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="2850739647070081192">Invite (koverta)</translation>
<translation id="2856444702002559011">Moguće je da napadaÄi pokuÅ¡avaju ukrasti vaÅ¡e podatke s web lokacije <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (naprimjer, lozinke, poruke ili kreditne kartice). <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte viÅ¡e<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Ova web lokacija prikazuje nametljive ili obmanjujuće oglase.</translation>
+<translation id="287596039013813457">Prijateljski</translation>
+<translation id="2876489322757410363">NapuÅ¡tate anonimni naÄin rada radi plaćanja putem vanjske aplikacije. Nastaviti?</translation>
<translation id="2878197950673342043">Presavijanje postera</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Postavljanje prozora</translation>
@@ -550,7 +567,6 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="3060227939791841287">C9 (omotnica)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, a zatim Enter da pokrenete Sigurnosnu provjeru u postavkama Chromea</translation>
<translation id="3061707000357573562">Usluga za zakrpe</translation>
-<translation id="3064966200440839136">NapuÅ¡tate anonimni naÄin rada radi plaćanja putem vanjske aplikacije. Nastaviti?</translation>
<translation id="306573536155379004">Igra je poÄela.</translation>
<translation id="3080254622891793721">Grafika</translation>
<translation id="3086579638707268289">Neko nadzire vašu aktivnost na webu</translation>
@@ -573,7 +589,6 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="315504272643575312">VaÅ¡im raÄunom upravlja <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Vrati</translation>
<translation id="3162559335345991374">WiFi koji koristite može tražiti da posjetite njegovu stranicu za prijavu.</translation>
-<translation id="3167968892399408617">Stranice koje pregledate u anonimnim karticama neće ostati u historiji preglednika ili historiji prikazivanja nakon što zatvorite sve anonimne kartice. Zadržat će se svi fajlovi koje preuzmete ili oznake koje kreirate.</translation>
<translation id="3169472444629675720">Otkrijte</translation>
<translation id="3174168572213147020">Ostrvo</translation>
<translation id="3176929007561373547">Provjerite postavke proxyja ili se obratite mrežnom administratoru da
@@ -599,10 +614,12 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="3229041911291329567">Informacije o verziji vašeg uređaja i preglednika</translation>
<translation id="323107829343500871">Unesite CVC za <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Uvijek detektiraj važan sadržaj s ove web lokacije</translation>
+<translation id="3249845759089040423">Cool</translation>
<translation id="3252266817569339921">Francuska</translation>
<translation id="3266793032086590337">Vrijednost (konflikt)</translation>
<translation id="3268451620468152448">Otvorene kartice</translation>
<translation id="3270847123878663523">&amp;Poništi preuređivanje</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> se želi povezati</translation>
<translation id="3274521967729236597">Pa Kai</translation>
<translation id="3282085321714087552">Vaša organizacija, <ph name="ENROLLMENT_DOMAIN" />, je poslala određene informacije web lokacijama u nastavku, naprimjer postavke ili pravila.</translation>
<translation id="3282497668470633863">Dodajte ime na kartici</translation>
@@ -655,6 +672,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="3428151540071562330">Jedan ili više URI-ja šablona servera DnsOverHttpsTemplates su nevažeći i neće se koristiti.</translation>
<translation id="3431636764301398940">SaÄuvaj ovu karticu na ovaj ureÄ‘aj</translation>
<translation id="3432601291244612633">Zatvori stranicu</translation>
+<translation id="3435738964857648380">Sigurnost</translation>
<translation id="3435896845095436175">Omogući</translation>
<translation id="3438829137925142401">Koristite lozinke saÄuvane na Google raÄunu</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="3584299510153766161">Dvostruko bušenje na dnu</translation>
<translation id="3586931643579894722">Sakrij detalje</translation>
<translation id="3587738293690942763">Srednje</translation>
+<translation id="3590643883886679995">Podaci za prijavu će se pohraniti na ovom ureÄ‘aju nakon Å¡to izaÄ‘ete iz anonimnog naÄina rada.</translation>
+<translation id="359126217934908072">Mjesec/godina:</translation>
<translation id="3592413004129370115">Italijanska (koverta)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Možete vratiti grupu na zadano kad god želite. Potreban je otprilike jedan dan da se pridružite novoj grupi.}=1{Možete vratiti grupu na zadano kad god želite. Potreban je otprilike jedan dan da se pridružite novoj grupi.}one{Možete vratiti grupu na zadano kad god želite. Potreban je otprilike {NUM_DAYS} dan da se pridružite novoj grupi.}few{Možete vratiti grupu na zadano kad god želite. Potrebna su otprilike {NUM_DAYS} dana da se pridružite novoj grupi.}other{Možete vratiti grupu na zadano kad god želite. Potrebno je otprilike {NUM_DAYS} dana da se pridružite novoj grupi.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplikaciju je blokirao vaš administrator</translation>
<translation id="3608932978122581043">Orijentacija sažetka sadržaja</translation>
@@ -706,13 +727,13 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="3615877443314183785">Unesite važeći datum isteka</translation>
<translation id="36224234498066874">Obriši podatke pregledanja...</translation>
<translation id="362276910939193118">Prikaži cijelu historiju</translation>
-<translation id="3625635938337243871">Podaci za prijavu će se pohraniti na ovom ureÄ‘aju nakon Å¡to izaÄ‘ete iz anonimnog naÄina rada.</translation>
<translation id="3630155396527302611">Ako je već naveden kao program kome je dozvoljen pristup mreži, pokušajte
ga ukloniti s liste pa ponovo dodati.</translation>
<translation id="3630699740441428070">Administratori ovog ureÄ‘aja su konfigurirali vaÅ¡u mrežnu vezu, Å¡to im može dozvoliti pregled vaÅ¡eg mrežnog saobraćaja, ukljuÄujući web lokacije koje posjećujete.</translation>
<translation id="3631244953324577188">Biometrija</translation>
<translation id="3633738897356909127">Dugme Ažuriraj Chrome, pritisnite Enter da ažurirate Chrome iz postavki Chromea</translation>
<translation id="3634530185120165534">Ladica 5</translation>
+<translation id="3637662659967048211">SaÄuvajte na Google raÄun</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplikacija:</translation>
<translation id="3650584904733503804">Potvrda valjanosti je uspjela</translation>
@@ -753,6 +774,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="3781428340399460090">Vatreno ružiÄasta</translation>
<translation id="3783418713923659662">MasterCard</translation>
<translation id="3784372983762739446">Bluetooth uređaji</translation>
+<translation id="3787675388804467730">Broj virtuelne kartice</translation>
<translation id="3787705759683870569">IstiÄe: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">VeliÄina 16</translation>
<translation id="3789841737615482174">Instaliraj</translation>
@@ -772,6 +794,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="3841184659773414994">ObraÄ‘ivaÄi fajlova</translation>
<translation id="385051799172605136">Nazad</translation>
<translation id="3858027520442213535">Ažuriraj datum i vrijeme</translation>
+<translation id="3881478300875776315">Prikaži manje redova</translation>
<translation id="3884278016824448484">Identifikator uređaja koji je u konfliktu</translation>
<translation id="3885155851504623709">Parohija</translation>
<translation id="388632593194507180">Otkriveno je praćenje</translation>
@@ -797,6 +820,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="397105322502079400">RaÄunanje…</translation>
<translation id="3973234410852337861">Host <ph name="HOST_NAME" /> je blokiran</translation>
<translation id="3973357910713125165">Dugme Pokrenite Sigurnosnu provjeru Chromea, pritisnite Enter da pokrenete Sigurnosnu provjeru u postavkama Chromea</translation>
+<translation id="3986705137476756801">IskljuÄite Automatske titlove za sada</translation>
<translation id="3987405730340719549">Chrome je utvrdio da bi ova web lokacija mogla biti lažna ili obmanjujućeg sadržaja.
Ako smatrate da je ovo prikazano greškom, posjetite https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="4275830172053184480">Ponovo pokrenite uređaj</translation>
<translation id="4277028893293644418">Ponovo postavi lozinku</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Ova kartica je saÄuvana na vaÅ¡em Google raÄunu}one{Ove kartice su saÄuvane na vaÅ¡em Google raÄunu}few{Ove kartice su saÄuvane na vaÅ¡em Google raÄunu}other{Ove kartice su saÄuvane na vaÅ¡em Google raÄunu}}</translation>
+<translation id="4287885627794386150">Ispunjava uslove za probni period, ali nije aktivno</translation>
<translation id="4297502707443874121">SliÄica za stranicu <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Proširi</translation>
<translation id="4300675098767811073">Višestruko bušenje na desnoj strani</translation>
<translation id="4302514097724775343">Dodirnite dinosaura da igrate</translation>
<translation id="4302965934281694568">Chou3 (koverta)</translation>
<translation id="4305666528087210886">Pristupanje vašem fajlu nije uspjelo</translation>
-<translation id="4305817255990598646">Prebaci</translation>
+<translation id="4306529830550717874">SaÄuvati adresu?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokiraj (zadano)</translation>
<translation id="4314815835985389558">Upravljanje sinhronizacijom</translation>
@@ -926,6 +951,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="4377125064752653719">PokuÅ¡ali ste prići domeni <ph name="DOMAIN" />, ali je potvrdu koju je server prikazao odbio njen izdavaÄ. Ovo znaÄi da sigurnosnim akreditivima koje je server prikazao ne treba ni u kom sluÄaju vjerovati. Možda komunicirate baÅ¡ sa napadaÄem.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Rub</translation>
+<translation id="4406883609789734330">Automatski titlovi</translation>
<translation id="4406896451731180161">rezultati pretraživanja</translation>
<translation id="4408413947728134509">Broj kolaÄića: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Upravo ste unijeli lozinku na obmanjujućoj web lokaciji. Chrome preporuÄuje da odete na <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> i druge web lokacije na kojima koristite ovu lozinku i odmah je promijenite.</translation>
@@ -938,7 +964,6 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="4435702339979719576">Razglednica)</translation>
<translation id="443673843213245140">Korištenje proksi servera je onemogućeno ali je određena eksplicitna konfiguracija proksi servera.</translation>
<translation id="4464826014807964867">Web lokacije s informacijama o vašoj organizaciji</translation>
-<translation id="4466881336512663640">Izgubit ćete izmjene obrasca Jeste li sigurni da želite nastaviti?</translation>
<translation id="4476953670630786061">Ovaj obrazac nije siguran. Automatsko popunjavanje je iskljuÄeno.</translation>
<translation id="4477350412780666475">Sljedeća numera</translation>
<translation id="4482953324121162758">Ova web lokacija neće biti prevedena.</translation>
@@ -972,6 +997,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="4594403342090139922">&amp;Vrati obrisano</translation>
<translation id="4597348597567598915">VeliÄina 8</translation>
<translation id="4600854749408232102">C6/C5 (Koverta)</translation>
+<translation id="4606870351894164739">PrivlaÄno</translation>
<translation id="4628948037717959914">Fotografija</translation>
<translation id="4631649115723685955">Usluga povrata novca je povezana</translation>
<translation id="4636930964841734540">Informacije</translation>
@@ -991,6 +1017,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="4691835149146451662">Architecture-A (omotnica)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Strana</translation>
+<translation id="4702656508969495934">Automatski titlovi su vidljivi, koristite prebacivaÄ prozora da fokusirate</translation>
<translation id="4708268264240856090">Vaša veza je prekinuta</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Pokrenuti Mrežnu dijagnostiku za Windows<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="4738601419177586157">Prijedlog za pretraživanje: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Upravljanje lozinkama…</translation>
<translation id="4744603770635761495">Izvršna putanja</translation>
+<translation id="4749011317274908093">UÅ¡li ste u anonimni naÄin rada</translation>
<translation id="4750917950439032686">Vaše informacije (naprimjer, lozinke ili brojevi kreditnih kartica) su privatne kada se šalju na ovu web lokaciju.</translation>
<translation id="4756388243121344051">&amp;Historija</translation>
<translation id="4758311279753947758">Dodaj informacije o kontaktu</translation>
@@ -1033,6 +1061,8 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="4813512666221746211">Greška na mreži</translation>
<translation id="4816492930507672669">Prilagodi stranici</translation>
<translation id="4819347708020428563">Urediti bilješke u zadanom prikazu?</translation>
+<translation id="4825507807291741242">Snažno</translation>
+<translation id="4838327282952368871">Sanjivo</translation>
<translation id="484462545196658690">Automatski</translation>
<translation id="4850886885716139402">Prikaz</translation>
<translation id="485316830061041779">NjemaÄka</translation>
@@ -1169,6 +1199,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="5314967030527622926">Alat za brošure</translation>
<translation id="5316812925700871227">Zakretanje u suprotnom smjeru od kazaljke na satu</translation>
<translation id="5317780077021120954">SaÄuvaj</translation>
+<translation id="5321288445143113935">Maksimizirano</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> od <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Odaberi kontakt informacije</translation>
<translation id="5327248766486351172">Ime</translation>
@@ -1176,11 +1207,13 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="5332219387342487447">NaÄin dostave</translation>
<translation id="5333022057423422993">Chrome je u naruÅ¡avanju podataka pronaÅ¡ao lozinku koju ste upravo koristili. Da zaÅ¡titite raÄune, preporuÄujemo da provjerite saÄuvane lozinke.</translation>
<translation id="5334013548165032829">Detaljni zapisnici sistema</translation>
+<translation id="5334145288572353250">SaÄuvati adresu?</translation>
<translation id="5340250774223869109">Aplikacija je blokirana</translation>
<translation id="534295439873310000">NFC uređaji</translation>
<translation id="5344579389779391559">Ova stranica vam može pokušati nešto naplatiti</translation>
<translation id="5355557959165512791">Trenutno ne možete posjetiti web lokaciju <ph name="SITE" /> jer je njena potvrda opozvana. GreÅ¡ke i napadi na mreži su obiÄno privremenog karaktera, tako da će ova stranica vjerovatno funkcionirati kasnije.</translation>
<translation id="536296301121032821">Pohranjivanje postavki pravila nije uspjelo</translation>
+<translation id="5363309033720083897">Serijski prikljuÄak koji je dozvolio vaÅ¡ administrator</translation>
<translation id="5371425731340848620">Ažuriraj karticu</translation>
<translation id="5377026284221673050">"Sat kasni" ili "Sat brza" ili "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
<translation id="5386426401304769735">Lanac potvrda za ovu web lokaciju sadrži potvrdu koja je izdata koristeći SHA-1.</translation>
@@ -1189,6 +1222,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="5398772614898833570">Oglasi su blokirani</translation>
<translation id="5400836586163650660">Siva</translation>
<translation id="540969355065856584">Ovaj server nije uspio dokazati da je <ph name="DOMAIN" />; njegova potvrda sigurnosti trenutno nije važeća. Uzrok tome može biti pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vaÅ¡u vezu.</translation>
+<translation id="541143247543991491">Oblak (cijeli sistem)</translation>
<translation id="541416427766103491">SlagaÄ 4</translation>
<translation id="5421136146218899937">Obriši podatke pregledanja…</translation>
<translation id="5426179911063097041">Web lokacija <ph name="SITE" /> vam želi slati obavještenja</translation>
@@ -1202,6 +1236,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="5455374756549232013">Neispravna vremenska oznaka pravila</translation>
<translation id="5457113250005438886">Nevaž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="5463625433003343978">Pronalaženje uređaja…</translation>
<translation id="5469868506864199649">italijanski</translation>
<translation id="5470861586879999274">Poništi u&amp;ređivanje</translation>
<translation id="5478437291406423475">B6/C4 (koverta)</translation>
@@ -1251,7 +1286,6 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="5624120631404540903">Upravljajte lozinkama</translation>
<translation id="5629630648637658800">UÄitavanje postavki pravila nije uspjelo</translation>
<translation id="5631439013527180824">Nevažeći token za upravljanje uređajem</translation>
-<translation id="5632627355679805402">VaÅ¡i podaci su Å¡ifrirani vaÅ¡om <ph name="BEGIN_LINK" />lozinkom za Google<ph name="END_LINK" /> od <ph name="TIME" />. Unesite je da poÄnete sinhronizaciju.</translation>
<translation id="5633066919399395251">NapadaÄi koji su trenutno na web lokaciji <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogu pokuÅ¡ati instalirati opasne programe na vaÅ¡ raÄunar koji kradu ili briÅ¡u informacije (npr, fotografije, lozinke, poruke i podatke s kreditnih kartica). <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte viÅ¡e<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Blokiran je obmanjujući sadržaj.</translation>
<translation id="5644090287519800334">Pomak slike X sa strane 1</translation>
@@ -1290,12 +1324,12 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="5785756445106461925">Dalje, ova stranica obuhvata druge resurse koji nisu sigurni. Te resurse mogu vidjeti drugi dok su u tranzitu, a može ih promijeniti napadaÄ kako bi promijenio izgled stranice.</translation>
<translation id="5786044859038896871">Želite li popuniti informacije o svojoj kartici?</translation>
<translation id="578633867165174378">Chrome je u naruÅ¡avanju podataka pronaÅ¡ao lozinku koju ste upravo koristili. PreporuÄujemo da odmah promijenite tu lozinku.</translation>
-<translation id="5798290721819630480">Odbaciti promjene?</translation>
<translation id="5803412860119678065">Želite li popuniti svoju karticu <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Odobrenja</translation>
<translation id="5804427196348435412">Koristiti NFC uređaje</translation>
<translation id="5810442152076338065">Veza s domenom <ph name="DOMAIN" /> je šifrirana pomoću zastarjelog paketa šifriranja.</translation>
<translation id="5813119285467412249">&amp;Ponovi dodavanje</translation>
+<translation id="5817918615728894473">Upari</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Ova kartica će se teretiti prilikom plaćanja, ali se njen stvarni broj neće dijeliti s ovom web lokacijom. Za dodatnu sigurnost će se generirati privremeni CVC.}one{Kartica koju odaberete će se teretiti prilikom plaćanja, ali se njen stvarni broj neće dijeliti s ovom web lokacijom. Za dodatnu sigurnost će se generirati privremeni CVC.}few{Kartica koju odaberete će se teretiti prilikom plaćanja, ali se njen stvarni broj neće dijeliti s ovom web lokacijom. Za dodatnu sigurnost će se generirati privremeni CVC.}other{Kartica koju odaberete će se teretiti prilikom plaćanja, ali se njen stvarni broj neće dijeliti s ovom web lokacijom. Za dodatnu sigurnost će se generirati privremeni CVC.}}</translation>
<translation id="5826507051599432481">UobiÄajeni naziv (CN)</translation>
<translation id="5838278095973806738">Na ovoj stranici ne trebate unositi nikakve osjetljive informacije (naprimjer, lozinke ili kreditne kartice) jer ih napadaÄi mogu ukrasti.</translation>
@@ -1303,6 +1337,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="5855253129151731373">Naziv hosta ove web lokacije je sliÄan domeni <ph name="LOOKALIKE_DOMAIN" />. NapadaÄi ponekad oponaÅ¡aju web lokacije uz male, teÅ¡ko uoÄljive izmjene naziva domene.
Ako smatrate da je ovo prikazano greškom, posjetite https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Isklj.</translation>
<translation id="5862579898803147654">SlagaÄ 8</translation>
<translation id="5863847714970149516">Stranica koja slijedi može pokušati izvršiti naplatu</translation>
<translation id="5866257070973731571">Dodajte broj telefona</translation>
@@ -1319,6 +1354,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="5913377024445952699">Snimanje ekrana je pauzirano</translation>
<translation id="59174027418879706">Omogućeno</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 u upotrebi}one{# u upotrebi}few{# u upotrebi}other{# u upotrebi}}</translation>
<translation id="5921185718311485855">UkljuÄeno</translation>
<translation id="5921639886840618607">SaÄuvati karticu na Google raÄunu?</translation>
<translation id="5922853866070715753">Skoro je gotovo</translation>
@@ -1338,6 +1374,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="5989320800837274978">Nije naveden fiksni proksi server niti URL pac skripte.</translation>
<translation id="5992691462791905444">Inženjersko Z-presavijanje</translation>
<translation id="6000758707621254961">Broj rezultata <ph name="RESULT_COUNT" /> za "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">KlasiÄno</translation>
<translation id="6008122969617370890">Redoslijed od N do 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Provjerite svoje lozinke</translation>
@@ -1359,6 +1396,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="6045164183059402045">Šablon položaja</translation>
<translation id="6047233362582046994">Ako razumijete rizike po vašu sigurnost, možete <ph name="BEGIN_LINK" />posjetiti ovu web lokaciju<ph name="END_LINK" /> prije uklanjanja štetnih aplikacija.</translation>
<translation id="6047927260846328439">Ovaj sadržaj vas može navesti da instalirate softver ili otkrijete liÄne informacije. <ph name="BEGIN_LINK" />Ipak pokaži<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Pritisnite i držite tipku |<ph name="ACCELERATOR" />| da izađete iz cijelog ekrana</translation>
<translation id="6049488691372270142">Izlaz stranica</translation>
<translation id="6051221802930200923">Trenutno ne možete posjetiti web lokaciju <ph name="SITE" />, jer web lokacija koristi kaÄenje potvrde. GreÅ¡ke i napadi na mreži su obiÄno privremenog karaktera, tako da će ova stranica vjerovatno raditi kasnije.</translation>
<translation id="6051898664905071243">Broj stranica:</translation>
@@ -1375,6 +1413,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="610911394827799129">Google raÄun može imati druge oblike historije pregledanja na <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">Pogledajte tekst i slike kopirane u međumemoriju</translation>
<translation id="6120179357481664955">Zapamtiti vaš UPI ID?</translation>
+<translation id="6123290840358279103">Prikaži virtuelnu karticu</translation>
<translation id="6124432979022149706">Konektori Chromea za preduzeća</translation>
<translation id="6146055958333702838">Provjerite sve kablove i ponovo pokrenite sve rutere, modeme ili druge mrežne
uređaje koje koristite.</translation>
@@ -1411,6 +1450,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="6289939620939689042">Boja stranice</translation>
<translation id="6290238015253830360">Predloženi Älanci će se pojaviti ovdje</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Zaustavljanje Google Asistenta u Chromeu</translation>
<translation id="6305205051461490394"><ph name="URL" /> je nedostupan.</translation>
<translation id="6312113039770857350">Web stranica nije dostupna</translation>
@@ -1436,6 +1476,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="6390200185239044127">Z-presavijanje napola</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Lijepljenje sa <ph name="ORIGIN_NAME" /> na ovu lokaciju je blokirano pravilom administratora</translation>
+<translation id="6398765197997659313">Napusti prikaz preko cijelog ekrana</translation>
<translation id="6401136357288658127">Ovo pravilo je zastarjelo. Umjesto njega koristite pravilo <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Uredite oznaku</translation>
<translation id="6406765186087300643">C0 (koverta)</translation>
@@ -1448,7 +1489,6 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="6428450836711225518">Potvrdite broj telefona</translation>
<translation id="6433490469411711332">Uređivanje podataka za kontakt</translation>
<translation id="6433595998831338502">Host raÄunar <ph name="HOST_NAME" /> je odbio povezivanje.</translation>
-<translation id="6434309073475700221">Odbaci</translation>
<translation id="6440503408713884761">Zanemareno</translation>
<translation id="6443406338865242315">Koje ekstenzije i dodatke ste instalirali</translation>
<translation id="6446163441502663861">Kahu (koverta)</translation>
@@ -1491,6 +1531,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="6624427990725312378">Kontakt podaci</translation>
<translation id="6626291197371920147">Dodajte važeći broj kartice</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> pretraživanje</translation>
+<translation id="6630043285902923878">Pronalaženje USB uređaja…</translation>
<translation id="6630809736994426279">NapadaÄi koji su trenutno na web lokaciji <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogu pokuÅ¡ati instalirati opasne programe na vaÅ¡ Mac raÄunar koji kradu ili briÅ¡u informacije (npr., fotografije, lozinke, poruke i podatke s kreditnih kartica). <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte viÅ¡e<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Obriši</translation>
@@ -1506,6 +1547,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="6671697161687535275">Ukloniti prijedlog obrasca iz Chromiuma?</translation>
<translation id="6685834062052613830">Odjavite se i završite podešavanje</translation>
<translation id="6687335167692595844">Zatražena je veliÄina fonta</translation>
+<translation id="6688743156324860098">Ažuriranje…</translation>
<translation id="6689249931105087298">Relativno s kompresijom crne taÄke</translation>
<translation id="6689271823431384964">Chrome vam nudi pohranjivanje kartica na Google raÄunu zato Å¡to ste prijavljeni. Ovo ponaÅ¡anje možete promjeniti u postavkama. Ime vlasnika kartice je ime s vaÅ¡eg raÄuna.</translation>
<translation id="6698381487523150993">Autor/ica:</translation>
@@ -1521,6 +1563,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="6744009308914054259">Posjetite Preuzimanja da proÄitate Älanke van mreže dok Äekate vezu.</translation>
<translation id="6753269504797312559">Vrijednost pravila</translation>
<translation id="6757797048963528358">Vaš uređaj je u stanju mirovanja.</translation>
+<translation id="6767985426384634228">Ažurirati adresu?</translation>
<translation id="6768213884286397650">Hagaki (dopisnica)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">LjubiÄasta</translation>
@@ -1543,6 +1586,7 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome je pojednostavio ovu stranicu za lakÅ¡e Äitanje. Chrome je preuzeo originalnu stranicu putem nesigurne veze.</translation>
<translation id="6891596781022320156">Nije podržan nivo pravila.</translation>
+<translation id="6895143722905299846">Virtuelni broj:</translation>
<translation id="6895330447102777224">Vaša kartica je potvrđena</translation>
<translation id="6897140037006041989">KorisniÄki agent</translation>
<translation id="6898699227549475383">Organizacija (O)</translation>
@@ -1578,10 +1622,10 @@ To će u suprotnom biti blokirano prema vašim postavkama privatnosti. Ovo će o
<translation id="7004583254764674281">Koristite Windows Hello da brže potvrdite kartice</translation>
<translation id="7006930604109697472">Svejedno pošalji</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Postavke promjene veliÄine</translation>
<translation id="7014741021609395734">Nivo zumiranja</translation>
<translation id="7016992613359344582">Ti troškovi mogu biti jednokratni ili ponavljajući te također mogu biti diskretni.</translation>
<translation id="7029809446516969842">Lozinke</translation>
+<translation id="7030436163253143341">Certifikat nije važeći</translation>
<translation id="7031646650991750659">Koje Google Play aplikacije ste instalirali</translation>
<translation id="7050187094878475250">PokuÅ¡ali ste pristupiti domeni <ph name="DOMAIN" />, ali je server prikazao potvrdu Äiji period važenja je predugaÄak da bi bio vjerodostojan.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Trenutno nije moguće saÄuvati ovu karticu}one{Trenutno nije moguće saÄuvati ove kartice}few{Trenutno nije moguće saÄuvati ove kartice}other{Trenutno nije moguće saÄuvati ove kartice}}</translation>
@@ -1651,12 +1695,14 @@ Dodatni detalji:
<translation id="7300012071106347854">Kobaltno plava</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Visoka</translation>
+<translation id="7305756307268530424">PoÄni sporije</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Pomoć s povezivanjem</translation>
<translation id="7323804146520582233">Sakrij odjeljak "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Zaobilaženje lokalnog raÄuna ureÄ‘aja</translation>
<translation id="7333654844024768166">Upravo ste unijeli lozinku na obmanjujućoj web lokaciji. Chromium preporuÄuje da odete na <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> i druge web lokacije na kojima koristite ovu lozinku i odmah je promijenite.</translation>
<translation id="7334320624316649418">&amp;Ponovi preuređivanje</translation>
+<translation id="7337248890521463931">Prikaži više redova</translation>
<translation id="7337706099755338005">Nije dostupno na vašoj platformi.</translation>
<translation id="733923710415886693">Potvrda servera nije otkrivena korištenjem pravila o transparentnosti potvrde.</translation>
<translation id="734600844861828519">11 x 15</translation>
@@ -1664,6 +1710,7 @@ Dodatni detalji:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Komandna linija</translation>
<translation id="7359588939039777303">Oglasi su blokirani.</translation>
+<translation id="7363096869660964304">MeÄ‘utim, niste nevidljivi. Ako koristite anonimni naÄin rada, time ne skrivate pregledani sadržaj od svog poslodavca, pružaoca internet usluga ili web lokacija koje posjetite.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, a zatim Enter da dodate adrese i upravljate njima u postavkama Chromea</translation>
<translation id="7365849542400970216">Može li web lokacija znati kada koristite uređaj?</translation>
<translation id="7372973238305370288">rezultat pretraživanja</translation>
@@ -1674,7 +1721,9 @@ Dodatni detalji:
<translation id="7378594059915113390">Upravljanje medijima</translation>
<translation id="7378627244592794276">Ne</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Nije primjenjivo</translation>
<translation id="7390545607259442187">Potvrdite karticu</translation>
+<translation id="7392089738299859607">Ažurirajte adresu</translation>
<translation id="7399802613464275309">Sigurnosna provjera</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Uređaj <ph name="DEVICE_NAME" /> je upravljani uređaj</translation>
@@ -1689,6 +1738,7 @@ Dodatni detalji:
&lt;li&gt;Posjetite &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome Centar za pomoć&lt;/a&gt; da saznate kako trajno ukloniti softver s raÄunara
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Å iroki format</translation>
+<translation id="7410471291937727359">Divno</translation>
<translation id="7416351320495623771">Upravljaj lozinkama…</translation>
<translation id="7419106976560586862">Putanja profila</translation>
<translation id="7437289804838430631">Dodaj kontakt podatke</translation>
@@ -1704,7 +1754,7 @@ Dodatni detalji:
<translation id="7481312909269577407">Proslijedi</translation>
<translation id="7485870689360869515">Nije pronađen nijedan rezultat.</translation>
<translation id="7495528107193238112">Ovaj sadržaj je blokiran. Kontaktirajte vlasnika web lokacije da riješite problem.</translation>
-<translation id="7498234416455752244">Nastavi uređivanje</translation>
+<translation id="7498193950643227031">Ako se veliÄina promijeni, može doći do neoÄekivanog ponaÅ¡anja. Sada možete ograniÄiti mogućnost promjene veliÄine aplikacija u meniju <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Upravo ste unijeli lozinku na obmanjujućoj web lokaciji. Chromium preporuÄuje provjeru saÄuvanih lozinki za <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> i druge web lokacije na kojima sada koristite ovu lozinku.</translation>
<translation id="7508255263130623398">Vraćeni ID uređaja pravila ne postoji ili ne odgovara trenutnom ID-u uređaja</translation>
<translation id="7508870219247277067">Avokado zelena</translation>
@@ -1724,6 +1774,7 @@ Dodatni detalji:
<translation id="7548892272833184391">Ispravite greške s povezivanjem</translation>
<translation id="7549584377607005141">Za ispravan prikaz ove web lokacije potrebni su podaci koje ste ranije unijeli. Možete ponovo poslati te podatke, ali ćete time ponoviti sve radnje koje je ova web lokacija prethodno izvršila.</translation>
<translation id="7550637293666041147">KorisniÄko ime na vaÅ¡em ureÄ‘aju i korisniÄko ime na Chromeu</translation>
+<translation id="755279583747225797">Probni period je aktivan</translation>
<translation id="7552846755917812628">Isprobajte sljedeće savjete:</translation>
<translation id="7554475479213504905">Ponovo uÄitaj i ipak prikaži</translation>
<translation id="7554791636758816595">Nova kartica</translation>
@@ -1742,7 +1793,6 @@ Dodatni detalji:
<translation id="7610193165460212391">Vrijednost je izvan raspona <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">IstiÄe: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Pritisnite Tab, a zatim Enter da pregledate lozinke i upravljate njima u postavkama Chromea</translation>
-<translation id="7615602087246926389">Već imate podatke koji su Å¡ifrirani pomoću druge verzije lozinke vaÅ¡eg Google raÄuna. Unesite je u nastavku.</translation>
<translation id="7616645509853975347">VaÅ¡ administrator je ukljuÄio Konektore Chromea za preduzeća u vaÅ¡em pregledniku. Pomoću tih konektora je moguće pristupiti nekim vaÅ¡im podacima.</translation>
<translation id="7619838219691048931">Zadnja tabela</translation>
<translation id="762844065391966283">Jedno po jedno</translation>
@@ -1807,13 +1857,12 @@ Dodatni detalji:
<translation id="782886543891417279">WiFi koji koristite (<ph name="WIFI_NAME" />) može zahtijevati da posjetite stranicu za prijavu.</translation>
<translation id="7836231406687464395">Postfix (koverta)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ništa}=1{1 aplikacija (<ph name="EXAMPLE_APP_1" />)}=2{2 aplikacije (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# aplikacija (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}few{# aplikacije (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# aplikacija (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">MeÄ‘utim, niste nevidljivi. Ako koristite anonimni naÄin rada, time ne skrivate pregledani sadržaj od svog poslodavca, pružaoca internet usluga ili web lokacija koje posjetite.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">otvori fajlove s vezama vrsta fajlova.</translation>
<translation id="7862185352068345852">Napustiti web lokaciju?</translation>
<translation id="7865448901209910068">Najbolja brzina</translation>
<translation id="7874263914261512992">Upravo ste unijeli lozinku na obmanjujućoj web lokaciji. Chrome preporuÄuje provjeru saÄuvanih lozinki za <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> i druge web lokacije na kojima sada koristite ovu lozinku.</translation>
<translation id="7878562273885520351">Moguće je da je vaša lozinka ugrožena</translation>
+<translation id="7880146494886811634">SaÄuvajte adresu</translation>
<translation id="7882421473871500483">Smeđa</translation>
<translation id="7887683347370398519">Provjerite CVC i pokušajte ponovo</translation>
<translation id="7887885240995164102">Pokreni naÄin rada slika u slici</translation>
@@ -1821,6 +1870,7 @@ Dodatni detalji:
<translation id="7894280532028510793">Ako nema greške u pravopisu, <ph name="BEGIN_LINK" />pokušajte pokrenuti Dijagnostiku mreže<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (koverta)</translation>
<translation id="7931318309563332511">Nepoznato</translation>
+<translation id="793209273132572360">Ažurirati adresu?</translation>
<translation id="7932579305932748336">Premaz</translation>
<translation id="79338296614623784">Unesite važeći broj telefona</translation>
<translation id="7934052535022478634">Plaćanje je izvršeno</translation>
@@ -1891,6 +1941,7 @@ Dodatni detalji:
<translation id="8175796834047840627">Chrome vam nudi pohranjivanje vaÅ¡ih kartica na Google raÄunu zato Å¡to ste prijavljeni. Ovo ponaÅ¡anje možete promjeniti u postavkama</translation>
<translation id="8176440868214972690">Administrator ovog uređaja je poslao određene informacije web lokacijama u nastavku, naprimjer postavke ili pravila.</translation>
<translation id="8184538546369750125">Koristi opću zadanu postavku (dozvoli)</translation>
+<translation id="8193086767630290324">Radnje poduzete s podacima koji su oznaÄeni kao povjerljivi</translation>
<translation id="8194797478851900357">&amp;Opozovi premještanje</translation>
<translation id="8201077131113104583">Nevažeći URL za ažuriranje za ekstenziju koja ima ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Sažetak narudžbe</translation>
@@ -1913,6 +1964,7 @@ Dodatni detalji:
<translation id="8249296373107784235">Prekini</translation>
<translation id="8249320324621329438">Zadnje dohvatanje:</translation>
<translation id="8253091569723639551">Potrebno je navesti adresu za naplatu</translation>
+<translation id="8257387598443225809">Ova aplikacija je dizajnirana za mobilne uređaje</translation>
<translation id="825929999321470778">Prikaži sve saÄuvane lozinke</translation>
<translation id="8261506727792406068">Izbriši</translation>
<translation id="8262952874573525464">Uvez donjeg ruba</translation>
@@ -2036,7 +2088,6 @@ Dodatni detalji:
<translation id="8719528812645237045">Višestruko bušenje na gornjoj strani</translation>
<translation id="8725066075913043281">Pokušaj ponovo</translation>
<translation id="8726549941689275341">VeliÄina stranice:</translation>
-<translation id="8728672262656704056">UÅ¡li ste u anonimni naÄin rada</translation>
<translation id="8730621377337864115">Gotovo</translation>
<translation id="8731544501227493793">Dugme Upravljaj lozinkama, pritisnite Enter da pregledate lozinke i upravljate njima u postavkama Chromea</translation>
<translation id="8734529307927223492">Uređajem <ph name="DEVICE_TYPE" /> upravlja <ph name="MANAGER" /></translation>
@@ -2113,6 +2164,7 @@ Dodatni detalji:
<translation id="9020542370529661692">Ova stranica je prevedena na <ph name="TARGET_LANGUAGE" /> jezik</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Nevažeće)</translation>
+<translation id="9030265603405983977">Jednobojno</translation>
<translation id="9035022520814077154">Sigurnosna greška</translation>
<translation id="9038649477754266430">Upotreba usluge predviÄ‘anja za brže uÄitavanje stranica</translation>
<translation id="9039213469156557790">Dalje, ova stranica obuhvata druge resurse koji nisu sigurni. Te resurse mogu vidjeti drugi dok su u tranzitu, a može ih izmijeniti napadaÄ kako bi promijenio ponaÅ¡anje stranice.</translation>
@@ -2136,6 +2188,7 @@ Dodatni detalji:
<translation id="91108059142052966">Pravilo administratora onemogućava dijeljenje ekrana s aplikacijom <ph name="APPLICATION_TITLE" /> kada je vidljiv povjerljivi sadržaj</translation>
<translation id="9114524666733003316">Potvrđivanje kartice...</translation>
<translation id="9114581008513152754">Ovim preglednikom ne upravlja kompanija ili neka druga organizacija. Aktivnostima na ovom uređaju se može upravljati van Chromea. <ph name="BEGIN_LINK" />Saznajte više<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Svježe</translation>
<translation id="9119042192571987207">Otpremljeno</translation>
<translation id="9128016270925453879">Pravila su uÄitana</translation>
<translation id="9128870381267983090">Spoji se na mrežu</translation>
@@ -2154,6 +2207,7 @@ Dodatni detalji:
<translation id="9170848237812810038">&amp;Poništi</translation>
<translation id="9171296965991013597">Napustiti aplikaciju?</translation>
<translation id="9173282814238175921">Jedan dokument/nova tabela</translation>
+<translation id="9173995187295789444">Skeniranje Bluetooth uređaja...</translation>
<translation id="917450738466192189">Potvrda servera je nevažeća.</translation>
<translation id="9174917557437862841">Dugme za promjenu kartice. Pritisnite Enter da se prebacite na ovu karticu</translation>
<translation id="9179703756951298733">Upravljajte plaćanjima i informacijama o kreditnim karticama u postavkama Chromea</translation>
diff --git a/chromium/components/strings/components_strings_ca.xtb b/chromium/components/strings/components_strings_ca.xtb
index fd1dace7bdf..e17c412fb9e 100644
--- a/chromium/components/strings/components_strings_ca.xtb
+++ b/chromium/components/strings/components_strings_ca.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Selecciona un permís per a <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Desfés el canvi d'ordre</translation>
+<translation id="1123753900084781868">La funció Subtítols instantanis no està disponible en aquests moments</translation>
<translation id="1125573121925420732">És probable que rebis advertiments mentre s'actualitza la seguretat als llocs web, però això millorarà aviat.</translation>
<translation id="112840717907525620">La memòria cau de la política està en bon estat</translation>
<translation id="1130564665089811311">Botó Tradueix la pàgina; prem Retorn per traduir aquesta pàgina amb el Traductor de Google</translation>
@@ -74,6 +75,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="1240347957665416060">Nom del teu dispositiu</translation>
<translation id="124116460088058876">Més idiomes</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Negreta</translation>
<translation id="1250759482327835220">Perquè la propera vegada puguis pagar més ràpidament, desa la targeta, el nom i l'adreça de facturació al Compte de Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (informació sincronitzada)</translation>
<translation id="1256368399071562588">&lt;p&gt;Si proveu de visitar un lloc web i no s'obre, en primer lloc mireu de resoldre el problema amb aquests passos:&lt;/p&gt;
@@ -156,6 +158,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="1476595624592550506">Canvia la contrasenya</translation>
<translation id="1484290072879560759">Tria l'adreça d'enviament</translation>
<translation id="1492194039220927094">Tramesa automàtica de les polítiques:</translation>
+<translation id="1495677929897281669">Torna a la pestanya</translation>
<translation id="1501859676467574491">Mostra les targetes del Compte de Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Aquest error es mostra si utilitzeu un portal Wi-Fi en què cal que inicieu la sessió per connectar-vos a Internet.&lt;/p&gt;
&lt;p&gt;Per solucionar l'error, feu clic a &lt;strong&gt;Connecta&lt;/strong&gt; a la pàgina que proveu d'obrir.</translation>
@@ -171,6 +174,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="1532118530259321453">Aquesta pàgina diu</translation>
<translation id="153384715582417236">De moment, això és tot</translation>
<translation id="1536390784834419204">Tradueix la pàgina</translation>
+<translation id="1539840569003678498">S'ha enviat l'informe:</translation>
<translation id="154408704832528245">Tria l'adreça d'entrega</translation>
<translation id="1549470594296187301">Heu d'activar el JavaScript per utilitzar aquesta funció.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="1682696192498422849">La vora curta primer</translation>
<translation id="168693727862418163">No s'ha pogut validar el valor d'aquesta política comparant-lo amb l'esquema i, per tant, s'ignorarà.</translation>
<translation id="168841957122794586">El certificat de servidor conté una clau criptogràfica dèbil.</translation>
+<translation id="1696290444144917273">Mostra les dades de la targeta virtual</translation>
<translation id="1697532407822776718">Ja estàs a punt!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Aquest servidor no ha pogut demostrar que sigui <ph name="DOMAIN" /> perquè, suposadament, el seu certificat de seguretat té la data de demà. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la vostra connexió.}other{Aquest servidor no ha pogut demostrar que sigui <ph name="DOMAIN" />; perquè, suposadament, el seu certificat de seguretat té una data que és d'aquí a # dies. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la vostra connexió.}}</translation>
<translation id="1710259589646384581">SO</translation>
+<translation id="1711234383449478798">S'ha ignorat perquè la política <ph name="POLICY_NAME" /> no s'ha establert com a <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> vol emmagatzemar dades a l'ordinador local de manera permanent</translation>
<translation id="1713628304598226412">Safata 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Bústia de correu 3</translation>
<translation id="1718029547804390981">No es poden afegir anotacions a aquest fitxer perquè és massa gran</translation>
<translation id="1721424275792716183">* El camp és obligatori</translation>
+<translation id="1727613060316725209">El certificat és vàlid</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>
<translation id="173080396488393970">Aquest tipus de targeta no s'admet</translation>
@@ -242,7 +249,6 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Prova d'executar el diagnòstic de xarxes de Windows<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">El servidor de destinació, <ph name="ORIGIN" />, ha establert una capçalera en què se sol·licita que s'apliqui una política d'origen a totes les sol·licituds que rebi. Tanmateix, com que la capçalera no està ben formada, el navegador no pot completar la sol·licitud que has fet per a <ph name="SITE" />. Els operadors de llocs web poden fer servir les polítiques d'origen per configurar la seguretat i altres propietats d'un lloc web.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Actualitzeu la frase de contrasenya de sincronització.</translation>
<translation id="1787142507584202372">Les pestanyes obertes es mostren aquí</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, hi ha diverses accions disponibles, prem el tabulador per moure't d'una acció a una altra</translation>
@@ -275,6 +281,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="1919345977826869612">Anuncis</translation>
<translation id="1919367280705858090">Obtenir ajuda amb un missatge d'error específic</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Cap}=1{1 lloc}other{# llocs}}</translation>
+<translation id="1924727005275031552">Nous</translation>
<translation id="1945968466830820669">Podries perdre l'accés al compte de la teva organització o ser víctima d'un robatori d'identitat. Chromium et recomana que canviïs la contrasenya ara.</translation>
<translation id="1947454675006758438">Grapat a la part superior dreta</translation>
<translation id="1958218078413065209">La teva puntuació més alta és <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="2042213636306070719">Safata 7</translation>
<translation id="204357726431741734">Inicia la sessió per utilitzar les contrasenyes desades al teu Compte de Google</translation>
<translation id="2053111141626950936">Les pàgines en <ph name="LANGUAGE" /> no es traduiran.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Quan aquest control està activat i la prova està activa, Chrome determina en quin grup gran de persones, o cohort, hi ha una activitat de navegació recent més semblant a la teva. Els anunciants poden seleccionar anuncis per al grup i la teva activitat de navegació es manté privada al teu dispositiu. El teu grup s'actualitza cada dia.}=1{Quan aquest control està activat i la prova està activa, Chrome determina en quin grup gran de persones, o cohort, hi ha una activitat de navegació recent més semblant a la teva. Els anunciants poden seleccionar anuncis per al grup i la teva activitat de navegació es manté privada al teu dispositiu. El teu grup s'actualitza cada dia.}other{Quan aquest control està activat i la prova està activa, Chrome determina en quin grup gran de persones, o cohort, hi ha una activitat de navegació recent més semblant a la teva. Els anunciants poden seleccionar anuncis per al grup i la teva activitat de navegació es manté privada al teu dispositiu. El teu grup s'actualitza cada {NUM_DAYS} dies}}</translation>
<translation id="2053553514270667976">Codi postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggeriment}other{# suggeriments}}</translation>
<translation id="2071692954027939183">Les notificacions s'han bloquejat automàticament perquè normalment no les permets</translation>
<translation id="2079545284768500474">Desfés</translation>
<translation id="20817612488360358">S'ha definit la configuració del servidor intermediari del sistema perquè es pugui utilitzar, però també s'ha especificat una configuració del servidor intermediari explícita.</translation>
<translation id="2082238445998314030">Resultat <ph name="RESULT_NUMBER" /> de <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Desa…</translation>
<translation id="2088086323192747268">Botó Gestiona la sincronització: prem Retorn per gestionar la informació que sincronitzes a la configuració de Chrome</translation>
<translation id="2091887806945687916">So</translation>
<translation id="2094505752054353250">Els dominis no coincideixen.</translation>
@@ -375,6 +384,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="2317259163369394535"><ph name="DOMAIN" /> requereix un nom d'usuari i una contrasenya.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, data de caducitat: <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">L'administrador controla l'opció de configuració</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> es vol vincular</translation>
<translation id="2344028582131185878">Baixades automàtiques</translation>
<translation id="2346319942568447007">Imatge que has copiat</translation>
<translation id="2354001756790975382">Altres adreces d'interès</translation>
@@ -382,8 +392,10 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="2355395290879513365">És possible que els atacants puguin veure les imatges que miris en aquest lloc i que les modifiquin per enganyar-te.</translation>
<translation id="2356070529366658676">Pregunta-ho</translation>
<translation id="2357481397660644965">El dispositiu està gestionat per <ph name="DEVICE_MANAGER" /> i el compte està gestionat per <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{En menys d'un dia}=1{En un dia}other{D'aquí a {NUM_DAYS} dies}}</translation>
<translation id="2359629602545592467">Diverses</translation>
<translation id="2359808026110333948">Continua</translation>
+<translation id="2359961752320758691">S'ha aplicat el número de la teva targeta virtual.</translation>
<translation id="2367567093518048410">Nivell</translation>
<translation id="2372464001869762664">Un cop confirmada, les dades de la targeta del teu Compte de Google es compartiran amb aquest lloc web. Trobaràs el CVC a les dades del teu compte de Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="239429038616798445">Aquest mètode d'enviament no està disponible. Prova'n un altre.</translation>
<translation id="2396249848217231973">&amp;Desfés la supressió</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Anteriors</translation>
<translation id="2413528052993050574">El servidor no ha pogut comprovar que sigui <ph name="DOMAIN" /> perquè és possible que el seu certificat de seguretat s'hagi revocat. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la vostra connexió.</translation>
<translation id="2414886740292270097">Fosc</translation>
<translation id="2438874542388153331">Encunyació quàdruple a la dreta</translation>
@@ -421,10 +434,10 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="2521385132275182522">Grapat a la part inferior dreta</translation>
<translation id="2523886232349826891">Només es desarà en aquest dispositiu</translation>
<translation id="2524461107774643265">Afegeix més informació</translation>
-<translation id="2526590354069164005">Escriptori</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{i 1 més}other{i # més}}</translation>
<translation id="2536110899380797252">Afegeix una adreça</translation>
<translation id="2539524384386349900">Detecta</translation>
+<translation id="2541219929084442027">Les pàgines que consultis en pestanyes d'incògnit no s'emmagatzemaran a l'historial del navegador, al magatzem de galetes ni a l'historial de cerques després d'haver tancat totes les pestanyes d'incògnit. Els fitxers que baixis i les adreces d'interès que creïs sí que es desaran.</translation>
<translation id="2544644783021658368">Document únic</translation>
<translation id="254947805923345898">El valor de la política no és vàlid.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ha enviat una resposta que no és vàlida.</translation>
@@ -444,6 +457,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="2629325967560697240">Per obtenir el màxim nivell de seguretat de Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />activa la protecció millorada<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">No s'ha trobat l'adreça IP del servidor de l'amfitrió <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Estat:</translation>
+<translation id="264810637653812429">No s'ha trobat cap dispositiu compatible.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />; prem Tab i després Retorn per esborrar l'historial de navegació, les galetes, la memòria cau i altres dades des de la configuració de Chrome</translation>
<translation id="2650446666397867134">S'ha denegat l'accés al fitxer</translation>
@@ -488,6 +502,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<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="2807052079800581569">Posició de la imatge a l'eix Y</translation>
+<translation id="2820957248982571256">S'està cercant...</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>
@@ -495,6 +510,8 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="2850739647070081192">Invite (sobre)</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="2859806420264540918">Aquest lloc web mostra anuncis intrusius o enganyosos.</translation>
+<translation id="287596039013813457">Amistosa</translation>
+<translation id="2876489322757410363">Per pagar amb una aplicació externa, sortiràs del mode d'incògnit. Vols continuar?</translation>
<translation id="2878197950673342043">Plegat en pòster</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Col·locació de finestres</translation>
@@ -544,7 +561,6 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="3060227939791841287">C9 (sobre)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />; prem Tab i després Retorn per executar la comprovació de seguretat a la configuració de Chrome</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>
<translation id="306573536155379004">S'ha iniciat el joc.</translation>
<translation id="3080254622891793721">Gràfic</translation>
<translation id="3086579638707268289">La teva activitat al web s'està supervisant</translation>
@@ -567,7 +583,6 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="315504272643575312">El teu compte està gestionat per <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Restaura</translation>
<translation id="3162559335345991374">És possible que la xarxa Wi-Fi que esteu fent servir requereixi que visiteu la seva pàgina d'inici de sessió.</translation>
-<translation id="3167968892399408617">Les pàgines que consulteu en pestanyes d'incògnit no s'emmagatzemaran a l'historial del navegador, al magatzem de galetes ni a l'historial de cerques després d'haver tancat totes les pestanyes d'incògnit. Els fitxers que baixeu i les adreces d'interès que creeu sí que es desaran.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Illa</translation>
<translation id="3176929007561373547">Comproveu la configuració del servidor intermediari o contacteu amb l'administrador de la xarxa per
@@ -593,10 +608,12 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<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="3249845759089040423">Atrevida</translation>
<translation id="3252266817569339921">Francès</translation>
<translation id="3266793032086590337">Valor (en conflicte)</translation>
<translation id="3268451620468152448">Pestanyes obertes</translation>
<translation id="3270847123878663523">&amp;Desfés el canvi d'ordre</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> es vol connectar</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">La teva organització, <ph name="ENROLLMENT_DOMAIN" />, ha enviat informació als llocs web següents, com ara opcions de configuració o polítiques.</translation>
<translation id="3282497668470633863">Afegeix el titular de la targeta</translation>
@@ -649,6 +666,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="3428151540071562330">Un o més dels URI de plantilla de servidor corresponents a DnsOverHttpsTemplates no són vàlids i no s'utilitzaran.</translation>
<translation id="3431636764301398940">Desa aquesta targeta al dispositiu</translation>
<translation id="3432601291244612633">Tanca la pàgina</translation>
+<translation id="3435738964857648380">Seguretat</translation>
<translation id="3435896845095436175">Activa</translation>
<translation id="3438829137925142401">Utilitza les contrasenyes desades al teu Compte de Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -691,7 +709,10 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="3584299510153766161">Encunyació doble a la part inferior</translation>
<translation id="3586931643579894722">Oculta els detalls</translation>
<translation id="3587738293690942763">Mitjà</translation>
+<translation id="3590643883886679995">Les dades d'inici de sessió s'emmagatzemaran en aquest dispositiu quan surtis del mode d'incògnit.</translation>
+<translation id="359126217934908072">Mes/Any:</translation>
<translation id="3592413004129370115">Italian (sobre)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Pots restablir el teu grup en qualsevol moment. Ha de transcórrer aproximadament un dia per unir-te a un grup nou.}=1{Pots restablir el teu grup en qualsevol moment. Ha de transcórrer aproximadament un dia per unir-te a un grup nou.}other{Pots restablir el teu grup en qualsevol moment. Han de transcórrer aproximadament {NUM_DAYS} dies per unir-te a un grup nou.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplicació bloquejada per l'administrador</translation>
<translation id="3608932978122581043">Orientació de l'entrada</translation>
@@ -700,13 +721,13 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="3615877443314183785">Introdueix una data de caducitat vàlida</translation>
<translation id="36224234498066874">Esborra dades de navegació</translation>
<translation id="362276910939193118">Mostra l'historial complet</translation>
-<translation id="3625635938337243871">Les dades d'inici de sessió s'emmagatzemaran en aquest dispositiu quan surtis del mode d'incògnit.</translation>
<translation id="3630155396527302611">Si ja està inclòs a la llista de programes autoritzats per accedir a la xarxa, proveu
de suprimir-lo de la llista i torneu-lo a afegir.</translation>
<translation id="3630699740441428070">Els administradors d'aquest dispositiu han configurat la connexió de la xarxa, la qual cosa és possible que els permeti veure el trànsit de la teva xarxa, inclosos els llocs web que visites.</translation>
<translation id="3631244953324577188">Biometria</translation>
<translation id="3633738897356909127">Botó Actualitza Chrome; prem Retorn per actualitzar Chrome des de la configuració de Chrome</translation>
<translation id="3634530185120165534">Safata 5</translation>
+<translation id="3637662659967048211">Desa al Compte de Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplicació:</translation>
<translation id="3650584904733503804">Validació correcta</translation>
@@ -747,6 +768,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="3781428340399460090">Rosa fúcsia</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Dispositius Bluetooth</translation>
+<translation id="3787675388804467730">Número de targeta virtual</translation>
<translation id="3787705759683870569">Data de caducitat: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Mida 16</translation>
<translation id="3789841737615482174">Instal·la</translation>
@@ -766,6 +788,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="3841184659773414994">Gestors de fitxers</translation>
<translation id="385051799172605136">Enrere</translation>
<translation id="3858027520442213535">Actualitza la data i l'hora</translation>
+<translation id="3881478300875776315">Mostra menys línies</translation>
<translation id="3884278016824448484">L'identificador del dispositiu ja s'està utilitzant</translation>
<translation id="3885155851504623709">Districte</translation>
<translation id="388632593194507180">S'ha detectat supervisió</translation>
@@ -791,6 +814,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="397105322502079400">S’està calculant...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> està bloquejat</translation>
<translation id="3973357910713125165">Botó per executar la comprovació de seguretat de Chrome; prem Retorn per executar la comprovació de seguretat a la configuració de Chrome</translation>
+<translation id="3986705137476756801">Desactiva Subtítols instantanis per ara</translation>
<translation id="3987405730340719549">Chrome ha determinat que aquest lloc web podria ser fals o fraudulent.
Si creus que aquest advertiment s'ha mostrat per error, ves a https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -882,13 +906,14 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="4275830172053184480">Reinici del dispositiu</translation>
<translation id="4277028893293644418">Restableix la contrasenya</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="4287885627794386150">Apte per a la prova, però no actiu</translation>
<translation id="4297502707443874121">Miniatura de la pàgina <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Desplega</translation>
<translation id="4300675098767811073">Encunyació múltiple a la dreta</translation>
<translation id="4302514097724775343">Toca el dinosaure per jugar</translation>
<translation id="4302965934281694568">Chou3 (sobre)</translation>
<translation id="4305666528087210886">No s'ha pogut accedir al fitxer</translation>
-<translation id="4305817255990598646">Canvia</translation>
+<translation id="4306529830550717874">Vols desar l'adreça?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloqueja (opció predeterminada)</translation>
<translation id="4314815835985389558">Gestiona la sincronització</translation>
@@ -915,6 +940,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="4377125064752653719">Heu provat d'accedir a <ph name="DOMAIN" />, però l'emissor ha revocat el certificat que ha presentat el servidor. Això vol dir que no heu de confiar gens en les credencials de seguretat que ha presentat el servidor. És possible que us estigueu comunicant amb un atacant.</translation>
<translation id="4378154925671717803">Telèfon</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Subtítols instantanis</translation>
<translation id="4406896451731180161">resultats de la cerca</translation>
<translation id="4408413947728134509">Galetes <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Acabes d'introduir la contrasenya en un lloc web enganyós. Chrome et recomana que vagis a <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> i a altres llocs web en què utilitzis aquesta contrasenya i que la canviïs ara.</translation>
@@ -927,7 +953,6 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<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="4464826014807964867">Llocs web amb informació sobre la teva organització</translation>
-<translation id="4466881336512663640">Es perdran els canvis fets al formulari. Confirmes que vols continuar?</translation>
<translation id="4476953670630786061">Aquest formulari no és segur. S'ha desactivat l'emplenament automàtic.</translation>
<translation id="4477350412780666475">Pista següent</translation>
<translation id="4482953324121162758">Aquest lloc web no es traduirà.</translation>
@@ -961,6 +986,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="4594403342090139922">&amp;Desfés la supressió</translation>
<translation id="4597348597567598915">Mida 8</translation>
<translation id="4600854749408232102">C6/C5 (sobre)</translation>
+<translation id="4606870351894164739">Impactant</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Devolució de diners associada</translation>
<translation id="4636930964841734540">Informació</translation>
@@ -980,6 +1006,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="4691835149146451662">Architecture-A (sobre)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Costat</translation>
+<translation id="4702656508969495934">Els subtítols instantanis estan visibles; utilitza el botó de canvi de finestra per posar el focus</translation>
<translation id="4708268264240856090">La connexió s'ha interromput</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Executar el diagnòstic de xarxes de Windows<ph name="END_LINK" />.</translation>
@@ -993,6 +1020,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="4738601419177586157">Suggeriment de cerca de <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Gestiona les contrasenyes…</translation>
<translation id="4744603770635761495">Camí executable</translation>
+<translation id="4749011317274908093">Has passat al mode d'incògnit</translation>
<translation id="4750917950439032686">La teva informació (com ara les contrasenyes o els números de targeta de crèdit) és privada quan s'envia a aquest lloc web.</translation>
<translation id="4756388243121344051">&amp;Historial</translation>
<translation id="4758311279753947758">Afegiu informació de contacte</translation>
@@ -1020,8 +1048,10 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<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="4809079943450490359">Instruccions de l'administrador del dispositiu:</translation>
<translation id="4813512666221746211">Error de la xarxa</translation>
-<translation id="4816492930507672669">Ajusta a la mida de la pàgina</translation>
+<translation id="4816492930507672669">Ajusta a la pàgina</translation>
<translation id="4819347708020428563">Vols editar les anotacions en la visualització predeterminada?</translation>
+<translation id="4825507807291741242">Potent</translation>
+<translation id="4838327282952368871">Somiadora</translation>
<translation id="484462545196658690">Automàtic</translation>
<translation id="4850886885716139402">Mostra</translation>
<translation id="485316830061041779">Alemany</translation>
@@ -1158,6 +1188,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="5314967030527622926">Creador de fullets</translation>
<translation id="5316812925700871227">Gira en sentit antihorari</translation>
<translation id="5317780077021120954">Desa</translation>
+<translation id="5321288445143113935">Maximitzada</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> de <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Tria la informació de contacte</translation>
<translation id="5327248766486351172">Nom</translation>
@@ -1165,11 +1196,13 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="5332219387342487447">Mètode d'enviament</translation>
<translation id="5333022057423422993">Chrome ha trobat la contrasenya que acabes de fer servir en una violació de les dades. Per protegir els teus comptes, et recomanem que comprovis les teves contrasenyes desades.</translation>
<translation id="5334013548165032829">Registres detallats del sistema</translation>
+<translation id="5334145288572353250">Vols desar l'adreça?</translation>
<translation id="5340250774223869109">L'aplicació està bloquejada</translation>
<translation id="534295439873310000">Dispositius amb NFC</translation>
<translation id="5344579389779391559">És possible que aquesta pàgina provi de fer-te algun càrrec</translation>
<translation id="5355557959165512791">En aquest moment no pots visitar <ph name="SITE" /> perquè se li ha revocat el certificat. 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="536296301121032821">No s'ha pogut emmagatzemar la configuració de la política</translation>
+<translation id="5363309033720083897">Port en sèrie admès pel teu administrador</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="5386426401304769735">La cadena de certificats d'aquest lloc conté un certificat que s'ha signat amb SHA-1.</translation>
@@ -1178,6 +1211,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="5398772614898833570">Anuncis bloquejats</translation>
<translation id="5400836586163650660">Gris</translation>
<translation id="540969355065856584">Aquest servidor no ha pogut demostrar que sigui <ph name="DOMAIN" /> perquè el seu certificat de seguretat no és vàlid en aquest moment. Això pot ser a causa d'una configuració incorrecta o d'un atacant que intercepta la connexió.</translation>
+<translation id="541143247543991491">Núvol (a tot el sistema)</translation>
<translation id="541416427766103491">Apiladora 4</translation>
<translation id="5421136146218899937">Esborra dades de navegació...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> et vol enviar notificacions</translation>
@@ -1191,6 +1225,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="5455374756549232013">Marca de temps de la política incorrecta</translation>
<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="5463625433003343978">S'estan cercant dispositius...</translation>
<translation id="5469868506864199649">Italià</translation>
<translation id="5470861586879999274">&amp;Refés la modificació</translation>
<translation id="5478437291406423475">B6/C4 (sobre)</translation>
@@ -1228,7 +1263,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="5586446728396275693">No hi ha cap adreça desada</translation>
<translation id="5593349413089863479">La connexió no és totalment segura</translation>
<translation id="5595485650161345191">Edita l'adreça</translation>
-<translation id="5598944008576757369">Selecciona una forma de pagament</translation>
+<translation id="5598944008576757369">Tria la forma de pagament</translation>
<translation id="560412284261940334">Gestió no compatible</translation>
<translation id="5605670050355397069">Ledger</translation>
<translation id="5607240918979444548">Architecture-C</translation>
@@ -1240,7 +1275,6 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="5624120631404540903">Gestiona les contrasenyes</translation>
<translation id="5629630648637658800">No s'ha pogut carregar la configuració de la política</translation>
<translation id="5631439013527180824">Testimoni de gestió del dispositiu no vàlid</translation>
-<translation id="5632627355679805402">Les teves dades s'han encriptat amb la <ph name="BEGIN_LINK" />contrasenya de Google<ph name="END_LINK" /> a partir del dia <ph name="TIME" />. Introdueix-la per començar la sincronització.</translation>
<translation id="5633066919399395251">És possible que els atacants del lloc web <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> provin d'instal·lar programes perillosos a l'ordinador per robar o suprimir la teva informació (per exemple, les fotos, les contrasenyes, els missatges i les targetes de crèdit). <ph name="BEGIN_LEARN_MORE_LINK" />Més informació<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">S'ha bloquejat el contingut enganyós.</translation>
<translation id="5644090287519800334">Desplaçament a l'eix X del costat 1 de la imatge</translation>
@@ -1279,12 +1313,12 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="5785756445106461925">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 l'aparença de la pàgina.</translation>
<translation id="5786044859038896871">Vols emplenar la informació de la teva targeta?</translation>
<translation id="578633867165174378">Chrome ha trobat la contrasenya que acabes de fer servir en una violació de les dades. Et recomanem que canviïs la contrasenya ara.</translation>
-<translation id="5798290721819630480">Vols descartar els canvis?</translation>
<translation id="5803412860119678065">Vols emplenar la informació de la teva targeta <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Permisos</translation>
<translation id="5804427196348435412">Utilitza dispositius amb NFC</translation>
<translation id="5810442152076338065">La connexió a <ph name="DOMAIN" /> s'ha encriptat amb un sistema de xifratge obsolet.</translation>
<translation id="5813119285467412249">&amp;Refés l'addició</translation>
+<translation id="5817918615728894473">Vincula</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Es farà un càrrec a aquesta targeta quan paguis, però el número real de la targeta no es compartirà amb aquest lloc web. Per a més seguretat, es generarà un CVC temporal.}other{Es farà un càrrec a la targeta que hagis seleccionat quan paguis, però el número real de la targeta no es compartirà amb aquest lloc web. Per a més seguretat, es generarà un CVC temporal.}}</translation>
<translation id="5826507051599432481">Nom comú (CN)</translation>
<translation id="5838278095973806738">És recomanable que no introdueixis informació sensible en aquest lloc web (com ara contrasenyes o targetes de crèdit), ja que alguns atacants podrien robar-la.</translation>
@@ -1292,6 +1326,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="5855253129151731373">El nom d'amfitrió d'aquest lloc web s'assembla a <ph name="LOOKALIKE_DOMAIN" />. De vegades, els atacants imiten llocs web introduint petits canvis difícils de veure al nom del domini.
Si creus que aquest advertiment s'ha mostrat per error, ves a https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Desactivat</translation>
<translation id="5862579898803147654">Apiladora 8</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>
@@ -1308,6 +1343,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="5913377024445952699">La captura de pantalla s'ha posat en pausa</translation>
<translation id="59174027418879706">Activat</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 en ús}other{# en ús}}</translation>
<translation id="5921185718311485855">Activat</translation>
<translation id="5921639886840618607">Vols desar la targeta al Compte de Google?</translation>
<translation id="5922853866070715753">Ja queda poc</translation>
@@ -1327,6 +1363,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="5989320800837274978">No s'especifiquen servidors intermediaris ni URL de script .pac.</translation>
<translation id="5992691462791905444">Plegat en Z per a enginyeria</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultats per a "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Clàssic</translation>
<translation id="6008122969617370890">Ordre de N a 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Comprova les contrasenyes</translation>
@@ -1348,6 +1385,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="6045164183059402045">Plantilla d'imposició</translation>
<translation id="6047233362582046994">Si entens el risc que suposa per a la teva seguretat, pots <ph name="BEGIN_LINK" />visitar aquest lloc web<ph name="END_LINK" /> abans que no s'hagin suprimit les aplicacions perjudicials.</translation>
<translation id="6047927260846328439">Aquest contingut pot provar d'enganyar-te perquè instal·lis programari o proporcionis informació personal. <ph name="BEGIN_LINK" />Mostra igualment<ph name="END_LINK" />.</translation>
+<translation id="6049004884579590341">Mantén premut |<ph name="ACCELERATOR" />| per sortir del mode de pantalla completa</translation>
<translation id="6049488691372270142">Lliurament de les pàgines</translation>
<translation id="6051221802930200923">En aquests moments no pots visitar <ph name="SITE" /> perquè el lloc web fa servir una fixació de certificat. 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="6051898664905071243">Nombre de pàgines:</translation>
@@ -1364,6 +1402,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<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>
<translation id="6116338172782435947">Veure el text i les imatges copiats al porta-retalls</translation>
<translation id="6120179357481664955">Recordes el teu identificador d'UPI?</translation>
+<translation id="6123290840358279103">Mostra la targeta virtual</translation>
<translation id="6124432979022149706">Connectors de Chrome Enterprise</translation>
<translation id="6146055958333702838">Reviseu els cables i reinicieu els encaminadors, els mòdems o altres
dispositius de xarxa que feu servir.</translation>
@@ -1400,6 +1439,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="6289939620939689042">Color de la pàgina</translation>
<translation id="6290238015253830360">Els articles suggerits es mostren aquí</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">S'està aturant l'Assistent de Google a Chrome</translation>
<translation id="6305205051461490394">No es pot accedir a <ph name="URL" />.</translation>
<translation id="6312113039770857350">La pàgina web no està disponible</translation>
@@ -1425,6 +1465,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="6390200185239044127">Plegat en Z fins a la meitat</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">La política de l'administrador no permet enganxar contingut de <ph name="ORIGIN_NAME" /> en aquesta ubicació</translation>
+<translation id="6398765197997659313">Surt del mode de pantalla completa</translation>
<translation id="6401136357288658127">Aquesta política es considera obsoleta. Hauries de fer servir la política <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Edita l'adreça d'interès</translation>
<translation id="6406765186087300643">C0 (sobre)</translation>
@@ -1437,7 +1478,6 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="6428450836711225518">Verifica el número de telèfon</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 els canvis</translation>
<translation id="6440503408713884761">Ignorada</translation>
<translation id="6443406338865242315">Quines extensions i connectors has instal·lat</translation>
<translation id="6446163441502663861">Kahu (sobre)</translation>
@@ -1480,6 +1520,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="6624427990725312378">Informació de contacte</translation>
<translation id="6626291197371920147">Afegeix un número de targeta vàlid</translation>
<translation id="6628463337424475685">Cerca de <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">S'estan cercant dispositius USB...</translation>
<translation id="6630809736994426279">És possible que els atacants que es troben a <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> provin d'instal·lar programes perillosos a l'ordinador Mac per robar-te o suprimir-te informació (per exemple, fotos, contrasenyes, missatges i targetes de crèdit). <ph name="BEGIN_LEARN_MORE_LINK" />Més informació<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Esborra</translation>
@@ -1495,6 +1536,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<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="6687335167692595844">Mida de la lletra sol·licitada</translation>
+<translation id="6688743156324860098">Actualitza…</translation>
<translation id="6689249931105087298">Relatiu amb compressió de punts negres</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="6698381487523150993">Creat:</translation>
@@ -1510,6 +1552,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="6744009308914054259">Mentre esperes a tenir connexió, pots visitar Baixades per llegir articles sense connexió.</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="6767985426384634228">Vols actualitzar l'adreça?</translation>
<translation id="6768213884286397650">Hagaki (postal)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violeta</translation>
@@ -1532,6 +1575,7 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> (<ph name="SHORT_URL" />)</translation>
<translation id="6888584790432772780">Chrome ha simplificat aquesta pàgina perquè sigui més fàcil de llegir. A més, ha recuperat la pàgina original amb una connexió no segura.</translation>
<translation id="6891596781022320156">No s'admet el nivell de la política.</translation>
+<translation id="6895143722905299846">Número virtual:</translation>
<translation id="6895330447102777224">La teva targeta s'ha confirmat</translation>
<translation id="6897140037006041989">Agent d'usuari</translation>
<translation id="6898699227549475383">Organització (O)</translation>
@@ -1567,10 +1611,10 @@ En cas contrari, la configuració de privadesa el bloquejarà. Això permetrà q
<translation id="7004583254764674281">Fes servir Windows Hello per confirmar les targetes més ràpidament</translation>
<translation id="7006930604109697472">Envia de totes maneres</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Configuració del canvi de mida</translation>
<translation id="7014741021609395734">Nivell de zoom</translation>
<translation id="7016992613359344582">Aquests càrrecs poden ser únics o periòdics i és possible que no s'indiquin d'una manera evident.</translation>
<translation id="7029809446516969842">Contrasenyes</translation>
+<translation id="7030436163253143341">El certificat no és vàlid</translation>
<translation id="7031646650991750659">Quines aplicacions de Google Play has instal·lat</translation>
<translation id="7050187094878475250">Has provat de connectar-te a <ph name="DOMAIN" />, però el servidor ha presentat un certificat amb un període de validesa massa llarg per poder confiar-hi.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{En aquest moment no es pot desar la targeta}other{En aquest moment no es poden desar les targetes}}</translation>
@@ -1640,12 +1684,14 @@ Detalls addicionals:
<translation id="7300012071106347854">Blau de cobalt</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Alt</translation>
+<translation id="7305756307268530424">Inicia més a poc a poc</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Ajuda amb la connexió</translation>
<translation id="7323804146520582233">Amaga la secció "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Substitució del compte local del dispositiu</translation>
<translation id="7333654844024768166">Acabes d'introduir la contrasenya en un lloc web enganyós. Chromium et recomana que vagis a <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> i a altres llocs web en què utilitzis aquesta contrasenya i que la canviïs ara.</translation>
<translation id="7334320624316649418">&amp;Refés el canvi d'ordre</translation>
+<translation id="7337248890521463931">Mostra més línies</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>
@@ -1653,6 +1699,7 @@ Detalls addicionals:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Línia d'ordres</translation>
<translation id="7359588939039777303">S'han bloquejat els anuncis.</translation>
+<translation id="7363096869660964304">Tanmateix, no ets invisible. La teva empresa, el teu proveïdor de serveis d'Internet i els llocs web que visites poden veure la navegació d'incògnit.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, prem Tab i després Retorn per afegir i gestionar adreces a la configuració de Chrome</translation>
<translation id="7365849542400970216">Vols deixar que se sàpiga l'ús que fas del dispositiu?</translation>
<translation id="7372973238305370288">resultat de la cerca</translation>
@@ -1663,7 +1710,9 @@ Detalls addicionals:
<translation id="7378594059915113390">Controls multimèdia</translation>
<translation id="7378627244592794276">No</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">No aplicable</translation>
<translation id="7390545607259442187">Confirma la targeta</translation>
+<translation id="7392089738299859607">Actualitza l'adreça</translation>
<translation id="7399802613464275309">Comprovació de seguretat</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">El dispositiu <ph name="DEVICE_NAME" /> està gestionat</translation>
@@ -1678,6 +1727,7 @@ Detalls addicionals:
&lt;li&gt;Visiteu el &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centre d'ajuda de Chrome&lt;/a&gt; per obtenir informació sobre com podeu suprimir permanentment el programari de l'ordinador.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Encantadora</translation>
<translation id="7416351320495623771">Gestiona les contrasenyes…</translation>
<translation id="7419106976560586862">Camí del perfil</translation>
<translation id="7437289804838430631">Afegeix informació de contacte</translation>
@@ -1693,7 +1743,7 @@ Detalls addicionals:
<translation id="7481312909269577407">Endavant</translation>
<translation id="7485870689360869515">No s'han trobat dades.</translation>
<translation id="7495528107193238112">Aquest contingut està bloquejat. Contacta amb el propietari del lloc web per resoldre el problema.</translation>
-<translation id="7498234416455752244">Continua editant</translation>
+<translation id="7498193950643227031">Les aplicacions poden comportar-se de manera inesperada si se'n canvia la mida. Ara pots limitar la possibilitat de canviar-ne la mida a <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Acabes d'introduir la contrasenya en un lloc web enganyós. Chromium et recomana que comprovis les teves contrasenyes desades per a <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> i altres llocs web en què utilitzis aquesta contrasenya ara.</translation>
<translation id="7508255263130623398">L'identificador de dispositiu de la política que s'ha tornat és buit o no coincideix amb l'actual</translation>
<translation id="7508870219247277067">Verd alvocat</translation>
@@ -1713,6 +1763,7 @@ Detalls addicionals:
<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="755279583747225797">La prova està activa</translation>
<translation id="7552846755917812628">Prova els consells següents:</translation>
<translation id="7554475479213504905">Torna'l a carregar i mostra'l igualment</translation>
<translation id="7554791636758816595">Pestanya nova</translation>
@@ -1731,7 +1782,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />; prem Tab i després Retorn per veure i gestionar les contrasenyes a la configuració de Chrome</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="7616645509853975347">L'administrador ha activat Chrome Enterprise Connectors al navegador. Aquests connectors tenen accés a algunes de les teves dades.</translation>
<translation id="7619838219691048931">Full final</translation>
<translation id="762844065391966283">Un element cada cop</translation>
@@ -1796,13 +1846,12 @@ Detalls addicionals:
<translation id="782886543891417279">És possible que la xarxa Wi-Fi (<ph name="WIFI_NAME" />) que esteu fent servir requereixi que visiteu la seva pàgina d'inici de sessió.</translation>
<translation id="7836231406687464395">Postfix (sobre)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Cap}=1{1 aplicació (<ph name="EXAMPLE_APP_1" />)}=2{2 aplicacions (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# aplicacions (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Tanmateix, no sou invisible. La vostra empresa, el vostre proveïdor de serveis d'Internet i els llocs web que visiteu poden veure la vostra navegació d'incògnit.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Obrir fitxers amb associacions de tipus de fitxers.</translation>
<translation id="7862185352068345852">Vols sortir del lloc web?</translation>
<translation id="7865448901209910068">Velocitat òptima</translation>
<translation id="7874263914261512992">Acabes d'introduir la contrasenya en un lloc web enganyós. Chrome et recomana que comprovis les teves contrasenyes desades per a <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> i altres llocs web en què utilitzis aquesta contrasenya ara.</translation>
<translation id="7878562273885520351">La teva contrasenya pot estar en perill</translation>
+<translation id="7880146494886811634">Desa l'adreça</translation>
<translation id="7882421473871500483">Marró</translation>
<translation id="7887683347370398519">Comproveu el CVC i torneu-ho a provar</translation>
<translation id="7887885240995164102">Entra a pantalla en pantalla</translation>
@@ -1810,6 +1859,7 @@ Detalls addicionals:
<translation id="7894280532028510793">Si està ben escrit, <ph name="BEGIN_LINK" />prova d'executar el diagnòstic de xarxes<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (sobre)</translation>
<translation id="7931318309563332511">Desconegut</translation>
+<translation id="793209273132572360">Vols actualitzar l'adreça?</translation>
<translation id="7932579305932748336">Recobriment</translation>
<translation id="79338296614623784">Introdueix un número de telèfon vàlid</translation>
<translation id="7934052535022478634">Pagament completat</translation>
@@ -1880,6 +1930,7 @@ Detalls addicionals:
<translation id="8175796834047840627">Chrome t'està oferint desar les targetes al Compte de Google perquè tens la sessió iniciada. Pots canviar aquest comportament a la configuració.</translation>
<translation id="8176440868214972690">L'administrador d'aquest dispositiu ha enviat informació als llocs web següents, com ara opcions de configuració o polítiques.</translation>
<translation id="8184538546369750125">Utilitza l'opció predeterminada global (Permet)</translation>
+<translation id="8193086767630290324">Accions dutes a terme amb dades marcades com a confidencials</translation>
<translation id="8194797478851900357">&amp;Desfés el moviment</translation>
<translation id="8201077131113104583">L'URL d'actualització per a l'extensió amb identificador "<ph name="EXTENSION_ID" />" no és vàlid.</translation>
<translation id="8202097416529803614">Resum de la comanda</translation>
@@ -1902,6 +1953,7 @@ Detalls addicionals:
<translation id="8249296373107784235">Cancel·la</translation>
<translation id="8249320324621329438">Última obtenció:</translation>
<translation id="8253091569723639551">Cal indicar l'adreça de facturació</translation>
+<translation id="8257387598443225809">Aquesta aplicació està dissenyada per a mòbils</translation>
<translation id="825929999321470778">Mostra totes les contrasenyes desades</translation>
<translation id="8261506727792406068">Suprimeix</translation>
<translation id="8262952874573525464">Cosit de la vora a la part inferior</translation>
@@ -2025,7 +2077,6 @@ Detalls addicionals:
<translation id="8719528812645237045">Encunyació múltiple a la part superior</translation>
<translation id="8725066075913043281">Torna-ho a provar</translation>
<translation id="8726549941689275341">Mida de la pàgina:</translation>
-<translation id="8728672262656704056">Has passat al mode d'incògnit</translation>
<translation id="8730621377337864115">Fet</translation>
<translation id="8731544501227493793">Botó Gestiona les contrasenyes; prem Retorn per veure i gestionar les teves contrasenyes a la configuració de Chrome</translation>
<translation id="8734529307927223492">El teu dispositiu <ph name="DEVICE_TYPE" /> està gestionat per <ph name="MANAGER" /></translation>
@@ -2102,6 +2153,7 @@ Detalls addicionals:
<translation id="9020542370529661692">Aquesta pàgina s'ha traduït a <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(No vàlid)</translation>
+<translation id="9030265603405983977">Monocroma</translation>
<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>
@@ -2125,6 +2177,7 @@ Detalls addicionals:
<translation id="91108059142052966">La política de l'administrador desactiva la compartició de pantalla amb <ph name="APPLICATION_TITLE" /> quan es mostra contingut confidencial</translation>
<translation id="9114524666733003316">S'està confirmant la targeta...</translation>
<translation id="9114581008513152754">Cap empresa ni cap altra organització no gestiona 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="9117930699067497412">Fresca</translation>
<translation id="9119042192571987207">Penjat</translation>
<translation id="9128016270925453879">Les polítiques s'han carregat</translation>
<translation id="9128870381267983090">Connecta't a la xarxa</translation>
@@ -2143,6 +2196,7 @@ Detalls addicionals:
<translation id="9170848237812810038">&amp;Desfés</translation>
<translation id="9171296965991013597">Vols sortir de l'aplicació?</translation>
<translation id="9173282814238175921">Document únic / Full nou</translation>
+<translation id="9173995187295789444">S'estan cercant dispositius Bluetooth...</translation>
<translation id="917450738466192189">El certificat del servidor no és vàlid.</translation>
<translation id="9174917557437862841">Botó per canviar de pestanya; prem Retorn per canviar a aquesta pestanya</translation>
<translation id="9179703756951298733">Gestiona la informació dels pagaments i de les targetes de crèdit a la configuració de Chrome</translation>
diff --git a/chromium/components/strings/components_strings_cs.xtb b/chromium/components/strings/components_strings_cs.xtb
index 74eabb2918e..7a6d9cc944c 100644
--- a/chromium/components/strings/components_strings_cs.xtb
+++ b/chromium/components/strings/components_strings_cs.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Vyberte oprávnění pro <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Vrátit změnu uspořádání zpět</translation>
+<translation id="1123753900084781868">Živý pÅ™epis teÄ není k dispozici</translation>
<translation id="1125573121925420732">BÄ›hem aktualizace zabezpeÄení na webech mohou být upozornÄ›ní běžná. Brzy by se to mÄ›lo zlepÅ¡it.</translation>
<translation id="112840717907525620">Mezipaměť zásady je v pořádku</translation>
<translation id="1130564665089811311">TlaÄítko PÅ™eložit stránku, stisknutím klávesy Enter tuto stránku pÅ™eložíte pomocí PÅ™ekladaÄe Google</translation>
@@ -74,6 +75,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="1240347957665416060">Název zařízení</translation>
<translation id="124116460088058876">Další jazyky</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">TuÄné</translation>
<translation id="1250759482327835220">Abyste příštÄ› mohli zaplatit rychleji, uložte si kartu, jméno a fakturaÄní adresu do úÄtu Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (synchronizováno)</translation>
<translation id="1256368399071562588">&lt;p&gt;Pokud se pokoušíte navštívit konkrétní web, ale ten se neotevírá, nejdříve chybu zkuste opravit provedením těchto kroků:&lt;/p&gt;
@@ -156,6 +158,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="1476595624592550506">Změňte heslo</translation>
<translation id="1484290072879560759">Vybrat dodací adresu</translation>
<translation id="1492194039220927094">Přenesení zásad:</translation>
+<translation id="1495677929897281669">Zpět na kartu</translation>
<translation id="1501859676467574491">Zobrazit karty z vaÅ¡eho úÄtu Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Tato chyba se zobrazí při použití portálu Wi-Fi, na kterém je třeba se před přístupem na internet přihlásit.&lt;/p&gt;
&lt;p&gt;Chybu odstraníte tím, že na stránce, kterou se snažíte otevřít, kliknete na &lt;strong&gt;Připojení&lt;/strong&gt;.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="1532118530259321453">Tato stránka říká</translation>
<translation id="153384715582417236">To je prozatím vše</translation>
<translation id="1536390784834419204">Přeložit stránku</translation>
+<translation id="1539840569003678498">Hlášení bylo odesláno:</translation>
<translation id="154408704832528245">Vybrat adresu doruÄení</translation>
<translation id="1549470594296187301">Chcete-li tuto funkci použít, musí být aktivován JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="1682696192498422849">Krátkou hranou napřed</translation>
<translation id="168693727862418163">Hodnotu zásady se nepodařilo ověřit proti schématu a bude ignorována.</translation>
<translation id="168841957122794586">Certifikát serveru obsahuje slabý kryptografický klíÄ.</translation>
+<translation id="1696290444144917273">Zobrazit podrobnosti o virtuální kartě</translation>
<translation id="1697532407822776718">VÅ¡e je nastaveno!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Server nedokázal prokázat, že patří doménÄ› <ph name="DOMAIN" />. Uvedené datum vystavení jeho bezpeÄnostního certifikátu je zítra. Může to být způsobeno nesprávnou konfigurací nebo tím, že vaÅ¡e pÅ™ipojení zachytává útoÄník.}few{Server nedokázal prokázat, že patří doménÄ› <ph name="DOMAIN" />. Uvedené datum vystavení jeho bezpeÄnostního certifikátu je až za # dny. Může to být způsobeno nesprávnou konfigurací nebo tím, že vaÅ¡e pÅ™ipojení zachytává útoÄník.}many{Server nedokázal prokázat, že patří doménÄ› <ph name="DOMAIN" />. Uvedené datum vystavení jeho bezpeÄnostního certifikátu je až za # dne. Může to být způsobeno nesprávnou konfigurací nebo tím, že vaÅ¡e pÅ™ipojení zachytává útoÄník.}other{Server nedokázal prokázat, že patří doménÄ› <ph name="DOMAIN" />. Uvedené datum vystavení jeho bezpeÄnostního certifikátu je až za # dní. 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="1710259589646384581">OperaÄní systém</translation>
+<translation id="1711234383449478798">Ignorováno, protože název zásady <ph name="POLICY_NAME" /> není nastaven na hodnotu <ph name="VALUE" />.</translation>
<translation id="1712552549805331520">Stránka <ph name="URL" /> chce trvale ukládat data v místním poÄítaÄi</translation>
<translation id="1713628304598226412">Přihrádka 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Schránka 3</translation>
<translation id="1718029547804390981">Dokument je na pÅ™idání oznaÄení a poznámek příliÅ¡ velký</translation>
<translation id="1721424275792716183">* Pole je povinné</translation>
+<translation id="1727613060316725209">Certifikát je platný</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>
<translation id="173080396488393970">Tento typ karty není podporován</translation>
@@ -242,7 +249,6 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Zkuste spustit Diagnostiku sítě systému Windows<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">Server, na který pÅ™echázíte (<ph name="ORIGIN" />), nastavil záhlaví, které vyžaduje, aby se na vÅ¡echny na nÄ›j odesílané požadavky vztahovaly zásady ohlednÄ› původu. Záhlaví má ale nesprávný tvar. ProhlížeÄ proto váš požadavek na web <ph name="SITE" /> nemůže splnit. Zásady ohlednÄ› původu mohou použít provozovatelé webů ke konfiguraci bezpeÄnostních a dalších vlastností webu.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Aktualizujte prosím heslovou frázi pro synchronizaci.</translation>
<translation id="1787142507584202372">Zde se zobrazí otevřené karty</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, je k dispozici několik akcí, můžete je procházet stisknutím klávesy Tab</translation>
@@ -275,6 +281,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="1919345977826869612">Reklamy</translation>
<translation id="1919367280705858090">Nápověda ke konkrétní chybové zprávě</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Žádné}=1{1 web}few{# weby}many{# webu}other{# webů}}</translation>
+<translation id="1924727005275031552">Nová</translation>
<translation id="1945968466830820669">Mohli byste ztratit přístup k úÄtu organizace nebo by mohlo dojít k odcizení vaší identity. Chromium doporuÄuje okamžitÄ› zmÄ›nit heslo.</translation>
<translation id="1947454675006758438">Sponka vpravo nahoře</translation>
<translation id="1958218078413065209">Vaše nejvyšší skóre je <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="2042213636306070719">Přihrádka 7</translation>
<translation id="204357726431741734">Chcete-li používat hesla uložená v úÄtu Google, pÅ™ihlaste se</translation>
<translation id="2053111141626950936">Stránky v jazyce <ph name="LANGUAGE" /> se nebudou překládat.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Když je tento ovládací prvek zapnutý a stav je aktivní, Chrome urÄuje, které skupinÄ› lidí (neboli kohortÄ›) se vaÅ¡e nedávná aktivita prohlížení nejvíce podobá. Inzerenti mohou vybírat reklamy podle skupin a vaÅ¡e historie prohlížení zůstává soukromá ve vaÅ¡em zařízení. VaÅ¡e skupina se každý den aktualizuje.}=1{Když je tento ovládací prvek zapnutý a stav je aktivní, Chrome urÄuje, které skupinÄ› lidí (neboli kohortÄ›) se vaÅ¡e nedávná aktivita prohlížení nejvíce podobá. Inzerenti mohou vybírat reklamy podle skupin a vaÅ¡e historie prohlížení zůstává soukromá ve vaÅ¡em zařízení. VaÅ¡e skupina se každý den aktualizuje.}few{Když je tento ovládací prvek zapnutý a stav je aktivní, Chrome urÄuje, které skupinÄ› lidí (neboli kohortÄ›) se vaÅ¡e nedávná aktivita prohlížení nejvíce podobá. Inzerenti mohou vybírat reklamy podle skupin a vaÅ¡e historie prohlížení zůstává soukromá ve vaÅ¡em zařízení. VaÅ¡e skupina se každé {NUM_DAYS} dny aktualizuje.}many{Když je tento ovládací prvek zapnutý a stav je aktivní, Chrome urÄuje, které skupinÄ› lidí (neboli kohortÄ›) se vaÅ¡e nedávná aktivita prohlížení nejvíce podobá. Inzerenti mohou vybírat reklamy podle skupin a vaÅ¡e historie prohlížení zůstává soukromá ve vaÅ¡em zařízení. VaÅ¡e skupina se každých {NUM_DAYS} dne aktualizuje.}other{Když je tento ovládací prvek zapnutý a stav je aktivní, Chrome urÄuje, které skupinÄ› lidí (neboli kohortÄ›) se vaÅ¡e nedávná aktivita prohlížení nejvíce podobá. Inzerenti mohou vybírat reklamy podle skupin a vaÅ¡e historie prohlížení zůstává soukromá ve vaÅ¡em zařízení. VaÅ¡e skupina se každých {NUM_DAYS} dní aktualizuje.}}</translation>
<translation id="2053553514270667976">PSČ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 návrh}few{# návrhy}many{# návrhu}other{# návrhů}}</translation>
<translation id="2071692954027939183">Oznámení byla automaticky zablokována, protože je obvykle nepovolujete</translation>
<translation id="2079545284768500474">Vrátit zpět</translation>
<translation id="20817612488360358">Jako aktivní jsou nakonfigurována systémová nastavení proxy serveru, je vÅ¡ak urÄena i explicitní konfigurace proxy serveru.</translation>
<translation id="2082238445998314030">Výsledek <ph name="RESULT_NUMBER" /> z <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Uložit…</translation>
<translation id="2088086323192747268">TlaÄítko Správa synchronizace, stisknutím klávesy Enter můžete v nastavení Chromu spravovat, jaké informace synchronizujete</translation>
<translation id="2091887806945687916">Zvuk</translation>
<translation id="2094505752054353250">Neshoda domén</translation>
@@ -375,6 +384,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="2317259163369394535">Doména <ph name="DOMAIN" /> vyžaduje zadání uživatelského jména a hesla.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, platnost vyprší <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Nastavení je spravováno administrátorem</translation>
+<translation id="2340263603246777781">Web <ph name="ORIGIN" /> žádá o spárování</translation>
<translation id="2344028582131185878">Automatická stahování</translation>
<translation id="2346319942568447007">Obrázek, který jste zkopírovali</translation>
<translation id="2354001756790975382">Ostatní záložky</translation>
@@ -382,8 +392,10 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="2355395290879513365">ÚtoÄníci mohou vidÄ›t obrázky, které si na tomto webu prohlížíte, a oklamat vás tím, že tyto obrázky upraví.</translation>
<translation id="2356070529366658676">Zeptat se</translation>
<translation id="2357481397660644965">VaÅ¡e zařízení spravuje doména <ph name="DEVICE_MANAGER" /> a váš úÄet spravuje doména <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Za méně než den}=1{Za den}few{Za {NUM_DAYS} dny}many{Za {NUM_DAYS} dne}other{Za {NUM_DAYS} dní}}</translation>
<translation id="2359629602545592467">Několik</translation>
<translation id="2359808026110333948">PokraÄovat</translation>
+<translation id="2359961752320758691">Je použito Äíslo vaší virtuální karty.</translation>
<translation id="2367567093518048410">Úroveň</translation>
<translation id="2372464001869762664">Po potvrzení budou údaje o kartÄ› z vaÅ¡eho úÄtu Google poskytnuty tomuto webu. Kód CVC najdete v podrobnostech o svém úÄtu Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="239429038616798445">Tento způsob dopravy není k dispozici. Zkuste použít jiný způsob.</translation>
<translation id="2396249848217231973">&amp;Vrátit smazání zpět</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Stará</translation>
<translation id="2413528052993050574">Server nedokázal prokázat, že patří doménÄ› <ph name="DOMAIN" />. Jeho bezpeÄnostní certifikát byl zÅ™ejmÄ› zruÅ¡en. 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="2414886740292270097">Tmavé</translation>
<translation id="2438874542388153331">Čtyři otvory vpravo</translation>
@@ -421,10 +434,10 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="2521385132275182522">Sponka vpravo dole</translation>
<translation id="2523886232349826891">Uloženo pouze do tohoto zařízení</translation>
<translation id="2524461107774643265">Přidání dalších informací</translation>
-<translation id="2526590354069164005">Plocha</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{a 1 další}few{a # další}many{a # další}other{a # dalších}}</translation>
<translation id="2536110899380797252">Přidat adresu</translation>
<translation id="2539524384386349900">Rozpoznat</translation>
+<translation id="2541219929084442027">Stránky, které otevÅ™ete na anonymních kartách, po zavÅ™ení vÅ¡ech anonymních karet nezanechají žádné stopy v historii prohlížeÄe, v úložiÅ¡ti souborů cookie ani v historii vyhledávání. Zachovány vÅ¡ak zůstanou vÅ¡echny stažené soubory a vytvoÅ™ené záložky.</translation>
<translation id="2544644783021658368">Jeden dokument</translation>
<translation id="254947805923345898">Hodnota zásady není platná.</translation>
<translation id="255002559098805027">Web <ph name="HOST_NAME" /> vrátil neplatnou odpovÄ›Ä.</translation>
@@ -444,6 +457,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="2629325967560697240">Pokud v Chromu chcete mít nejvyšší úroveň zabezpeÄení, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />zapnÄ›te vylepÅ¡enou ochranu<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">IP adresa serveru <ph name="HOST_NAME" /> nebyla nalezena.</translation>
<translation id="2639739919103226564">Stav:</translation>
+<translation id="264810637653812429">Nebyla nalezena žádná kompatibilní zařízení.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, stisknutím klávesy Tab a poté Enter vymažete historii prohlížení, soubory cookie, mezipaměť a další položky v nastavení Chromu</translation>
<translation id="2650446666397867134">Přístup k souboru byl odepřen.</translation>
@@ -488,6 +502,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<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="2807052079800581569">Pozice obrázku na ose Y</translation>
+<translation id="2820957248982571256">Vyhledávání...</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>
@@ -495,6 +510,8 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="2850739647070081192">Invite (obálka)</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="2859806420264540918">Tento web zobrazuje rušivé nebo zavádějící reklamy.</translation>
+<translation id="287596039013813457">Přátelské</translation>
+<translation id="2876489322757410363">Chystáte se opustit anonymní režim, abyste mohli zaplatit v externí aplikaci. PokraÄovat?</translation>
<translation id="2878197950673342043">Plakátové přeložení</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Umístění oken</translation>
@@ -544,7 +561,6 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="3060227939791841287">C9 (obálka)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, stisknutím klávesy Tab a poté Enter spustíte bezpeÄnostní kontrolu v nastavení Chromu</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>
<translation id="306573536155379004">Hra byla spuštěna.</translation>
<translation id="3080254622891793721">Obrázek</translation>
<translation id="3086579638707268289">Vaše aktivita na webu je sledována</translation>
@@ -567,7 +583,6 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="315504272643575312">Váš úÄet je spravován doménou <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Obnovit</translation>
<translation id="3162559335345991374">Síť Wi-Fi, kterou používáte, může vyžadovat, abyste navštívili její stránku přihlášení.</translation>
-<translation id="3167968892399408617">Stránky, které otevÅ™ete na anonymních kartách, po zavÅ™ení vÅ¡ech anonymních karet nezanechají žádné stopy v historii prohlížeÄe, v úložiÅ¡ti souborů cookie ani v historii vyhledávání. Zachovány vÅ¡ak zůstanou vÅ¡echny stažené soubory a vytvoÅ™ené záložky.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ostrov</translation>
<translation id="3176929007561373547">Zkontrolujte nastavení proxy serveru nebo se obraťte na správce sítě, aby ověřil, zda proxy server funguje. Pokud se domníváte, že by proxy server neměl být používán: <ph name="PLATFORM_TEXT" /></translation>
@@ -590,10 +605,12 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<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="3249845759089040423">Elegantní</translation>
<translation id="3252266817569339921">francouzština</translation>
<translation id="3266793032086590337">Hodnota (konflikt)</translation>
<translation id="3268451620468152448">Otevřené karty</translation>
<translation id="3270847123878663523">&amp;Vrátit změnu uspořádání zpět</translation>
+<translation id="3271648667212143903">Web <ph name="ORIGIN" /> žádá o připojení</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">VaÅ¡e organizace, <ph name="ENROLLMENT_DOMAIN" />, odeslala urÄité informace (například nastavení nebo zásady) následujícím webům.</translation>
<translation id="3282497668470633863">Přidání jména na kartě</translation>
@@ -646,6 +663,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="3428151540071562330">Některé identifikátory URI šablon serverů DnsOverHttpsTemplates jsou neplatné a nebudou použity.</translation>
<translation id="3431636764301398940">Uložit tuto kartu do zařízení</translation>
<translation id="3432601291244612633">Zavřít stránku</translation>
+<translation id="3435738964857648380">ZabezpeÄení</translation>
<translation id="3435896845095436175">Aktivovat</translation>
<translation id="3438829137925142401">Použít hesla uložená v úÄtu Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -688,7 +706,10 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="3584299510153766161">Dvě díry dole</translation>
<translation id="3586931643579894722">Skrýt podrobnosti</translation>
<translation id="3587738293690942763">Střední</translation>
+<translation id="3590643883886679995">PÅ™ihlaÅ¡ovací údaje zůstanou v tomto zařízení uložené i po ukonÄení anonymního režimu.</translation>
+<translation id="359126217934908072">Měsíc/rok:</translation>
<translation id="3592413004129370115">Italian (obálka)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Skupinu můžete kdykoli resetovat. Zařazení do nové skupiny trvá přibližně jeden den.}=1{Skupinu můžete kdykoli resetovat. Zařazení do nové skupiny trvá přibližně jeden den.}few{Skupinu můžete kdykoli resetovat. Zařazení do nové skupiny trvá přibližně {NUM_DAYS} dny.}many{Skupinu můžete kdykoli resetovat. Zařazení do nové skupiny trvá přibližně {NUM_DAYS} dne.}other{Skupinu můžete kdykoli resetovat. Zařazení do nové skupiny trvá přibližně {NUM_DAYS} dní.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplikace je blokována administrátorem</translation>
<translation id="3608932978122581043">Orientace podávání</translation>
@@ -697,12 +718,12 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="3615877443314183785">Zadejte platné datum vypršení platnosti</translation>
<translation id="36224234498066874">Vymazat údaje o prohlížení...</translation>
<translation id="362276910939193118">Zobrazit celou historii</translation>
-<translation id="3625635938337243871">PÅ™ihlaÅ¡ovací údaje zůstanou v tomto zařízení uložené i po ukonÄení anonymního režimu.</translation>
<translation id="3630155396527302611">Pokud je program v seznamu programů s oprávněním přistupovat k síti již uveden, zkuste jej ze seznamu odebrat a znovu přidat.</translation>
<translation id="3630699740441428070">AdministrátoÅ™i tohoto zařízení nakonfigurovali vaÅ¡e pÅ™ipojení k síti, což jim může umožnit sledovat váš síťový provoz, vÄetnÄ› webů, které navÅ¡tÄ›vujete.</translation>
<translation id="3631244953324577188">Biometrické systémy</translation>
<translation id="3633738897356909127">TlaÄítko Aktualizovat Chrome, stisknutím klávesy Enter aktualizujete Chrome v nastavení Chromu</translation>
<translation id="3634530185120165534">Přihrádka 5</translation>
+<translation id="3637662659967048211">Uložit do úÄtu Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplikace:</translation>
<translation id="3650584904733503804">Ověření proběhlo úspěšně</translation>
@@ -743,6 +764,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="3781428340399460090">Jasně růžová</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Zařízení Bluetooth</translation>
+<translation id="3787675388804467730">Číslo virtuální karty</translation>
<translation id="3787705759683870569">Platnost do: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Velikost 16</translation>
<translation id="3789841737615482174">Instalovat</translation>
@@ -762,6 +784,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="3841184659773414994">Obslužné nástroje pro soubory</translation>
<translation id="385051799172605136">Zpět</translation>
<translation id="3858027520442213535">Aktualizovat datum a Äas</translation>
+<translation id="3881478300875776315">Zobrazit méně řádků</translation>
<translation id="3884278016824448484">Konfliktní identifikátor zařízení</translation>
<translation id="3885155851504623709">Farnost</translation>
<translation id="388632593194507180">Bylo zjištěno sledování</translation>
@@ -787,6 +810,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="397105322502079400">Probíhá výpoÄet…</translation>
<translation id="3973234410852337861">Web <ph name="HOST_NAME" /> je blokován</translation>
<translation id="3973357910713125165">TlaÄítko Spustit bezpeÄnostní kontrolu Chromu, stisknutím klávesy Enter spustíte bezpeÄnostní kontrolu v nastavení Chromu</translation>
+<translation id="3986705137476756801">Zatím živý přepis vypnout</translation>
<translation id="3987405730340719549">Chrome zjistil, že by tento web mohl být falešný nebo podvodný.
Pokud se domníváte, že se tato zpráva zobrazila v důsledku chyby, navštivte web https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -878,13 +902,14 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="4275830172053184480">Restartovat zařízení</translation>
<translation id="4277028893293644418">Resetovat heslo</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="4287885627794386150">Vhodné k testování technologie, ale neaktivní</translation>
<translation id="4297502707443874121">Miniatura stránky <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Rozbalit</translation>
<translation id="4300675098767811073">Několik děr vpravo</translation>
<translation id="4302514097724775343">Klepnutím na dinosaura spustíte hru</translation>
<translation id="4302965934281694568">Chou3 (obálka)</translation>
<translation id="4305666528087210886">K souboru nelze získat přístup</translation>
-<translation id="4305817255990598646">Přejít</translation>
+<translation id="4306529830550717874">Uložit adresu?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokovat (výchozí)</translation>
<translation id="4314815835985389558">Správa synchronizace</translation>
@@ -911,6 +936,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="4377125064752653719">Pokusili jste se pÅ™ejít na web <ph name="DOMAIN" />, ale certifikát prezentovaný tímto webem byl vydavatelem certifikátu zruÅ¡en. To znamená, že bezpeÄnostním pověřením, která web prezentoval, nelze zcela důvěřovat. Je možné, že komunikujete s útoÄníkem.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Živý přepis</translation>
<translation id="4406896451731180161">výsledky vyhledávání</translation>
<translation id="4408413947728134509">Soubory cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">PrávÄ› jste své heslo zadali na klamavém webu. Chrome doporuÄuje navÅ¡tívit weby <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />a další weby, na nichž toto heslo používáte, a okamžitÄ› ho zmÄ›nit.</translation>
@@ -923,7 +949,6 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<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="4464826014807964867">Weby s informacemi od vaší organizace</translation>
-<translation id="4466881336512663640">ZmÄ›ny ve formuláři budou ztraceny. Opravdu chcete pokraÄovat?</translation>
<translation id="4476953670630786061">Tento formulář není zabezpeÄený. Automatické vyplňování bylo vypnuto.</translation>
<translation id="4477350412780666475">Další skladba</translation>
<translation id="4482953324121162758">Tento web se nebude překládat.</translation>
@@ -957,6 +982,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<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="4606870351894164739">Působivé</translation>
<translation id="4628948037717959914">Fotka</translation>
<translation id="4631649115723685955">Cashback je propojen</translation>
<translation id="4636930964841734540">Informace</translation>
@@ -976,6 +1002,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="4691835149146451662">Architecture-A (obálka)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">BoÄní</translation>
+<translation id="4702656508969495934">Živý pÅ™epis je viditelný, vyberete ho pomocí pÅ™epínaÄe oken</translation>
<translation id="4708268264240856090">Připojení bylo přerušeno</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Spustit Diagnostiku sítě systému Windows<ph name="END_LINK" /></translation>
@@ -989,6 +1016,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="4738601419177586157">Návrh vyhledávacího dotazu <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Spravovat hesla…</translation>
<translation id="4744603770635761495">Spustitelná cesta</translation>
+<translation id="4749011317274908093">Jste v anonymním režimu</translation>
<translation id="4750917950439032686">VaÅ¡e údaje (například hesla nebo Äísla platebních karet) jsou pÅ™i odesílání na tento web soukromé.</translation>
<translation id="4756388243121344051">Historie</translation>
<translation id="4758311279753947758">Přidat kontaktní údaje</translation>
@@ -1018,6 +1046,8 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="4813512666221746211">Chyba sítě</translation>
<translation id="4816492930507672669">Přizpůsobit na stránku</translation>
<translation id="4819347708020428563">Upravit poznámky ve výchozím zobrazení?</translation>
+<translation id="4825507807291741242">Důrazné</translation>
+<translation id="4838327282952368871">Zasněné</translation>
<translation id="484462545196658690">Automaticky</translation>
<translation id="4850886885716139402">Zobrazit</translation>
<translation id="485316830061041779">nÄ›mÄina</translation>
@@ -1154,6 +1184,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="5314967030527622926">Brožura</translation>
<translation id="5316812925700871227">OtoÄit proti smÄ›ru hodinových ruÄiÄek</translation>
<translation id="5317780077021120954">Uložit</translation>
+<translation id="5321288445143113935">Maximalizováno</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> z <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Vybrat kontaktní údaje</translation>
<translation id="5327248766486351172">Jméno</translation>
@@ -1161,11 +1192,13 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="5332219387342487447">Způsob dopravy</translation>
<translation id="5333022057423422993">Chrome zjistil, že právÄ› použité heslo bylo vyzrazeno pÅ™i poruÅ¡ení zabezpeÄení údajů. Pokud svá hesla chcete zabezpeÄit, doporuÄujeme vám zkontrolovat uložená hesla.</translation>
<translation id="5334013548165032829">Podrobné systémové protokoly</translation>
+<translation id="5334145288572353250">Uložit adresu?</translation>
<translation id="5340250774223869109">Aplikace je blokována</translation>
<translation id="534295439873310000">Zařízení NFC</translation>
<translation id="5344579389779391559">Tato stránka se vám může pokusit naúÄtovat poplatky</translation>
<translation id="5355557959165512791">Web <ph name="SITE" /> teÄ nemůžete navÅ¡tívit, protože jeho certifikát byl zruÅ¡en. Síťové chyby a útoky jsou obvykle doÄasné, tato stránka pravdÄ›podobnÄ› pozdÄ›ji bude fungovat.</translation>
<translation id="536296301121032821">Ukládání nastavení zásady se nezdařilo</translation>
+<translation id="5363309033720083897">Sériový port je povolen administrátorem</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="5386426401304769735">Řetězec certifikátů tohoto webu obsahuje certifikát podepsaný algoritmem SHA-1.</translation>
@@ -1174,6 +1207,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="5398772614898833570">Byly zablokovány reklamy</translation>
<translation id="5400836586163650660">Šedá</translation>
<translation id="540969355065856584">Server nedokázal prokázat, že patří doménÄ› <ph name="DOMAIN" />. Jeho bezpeÄnostní certifikát v tuto chvíli není platný. 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="541143247543991491">Cloud (celosystémové)</translation>
<translation id="541416427766103491">StohovaÄ 4</translation>
<translation id="5421136146218899937">Vymazat údaje o prohlížení...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> vám chce zasílat oznámení</translation>
@@ -1187,6 +1221,7 @@ Jinak to vaše nastavení ochrany soukromí bude blokovat. Povolením umožníte
<translation id="5455374756549232013">Chybné Äasové razítko zásady</translation>
<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="5463625433003343978">Hledání zařízení…</translation>
<translation id="5469868506864199649">italština</translation>
<translation id="5470861586879999274">&amp;Opakovat úpravy</translation>
<translation id="5478437291406423475">B6/C4 (obálka)</translation>
@@ -1236,7 +1271,6 @@ Kontaktujte administrátora systému.</translation>
<translation id="5624120631404540903">Spravovat hesla</translation>
<translation id="5629630648637658800">NaÄítání nastavení zásady se nezdaÅ™ilo</translation>
<translation id="5631439013527180824">Neplatný token správy zařízení</translation>
-<translation id="5632627355679805402">VaÅ¡e údaje byly zaÅ¡ifrovány pomocí <ph name="BEGIN_LINK" />hesla úÄtu Google<ph name="END_LINK" /> ze dne <ph name="TIME" />. Chcete-li spustit synchronizaci, zadejte jej.</translation>
<translation id="5633066919399395251">ÚtoÄníci, kteří se aktuálnÄ› nacházejí na webu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, se mohou pokusit nainstalovat vám do poÄítaÄe nebezpeÄné programy, které mohou ukrást nebo smazat vaÅ¡e informace (například fotky, hesla, zprávy nebo platební karty). <ph name="BEGIN_LEARN_MORE_LINK" />Další informace<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Byl zablokován klamavý obsah.</translation>
<translation id="5644090287519800334">Posun obrázku strany 1 na ose X</translation>
@@ -1275,12 +1309,12 @@ Kontaktujte administrátora systému.</translation>
<translation id="5785756445106461925">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 vzhled stránky.</translation>
<translation id="5786044859038896871">Chcete vyplnit informace o kartě?</translation>
<translation id="578633867165174378">Chrome zjistil, že právÄ› použité heslo bylo vyzrazeno pÅ™i poruÅ¡ení zabezpeÄení údajů. DoporuÄujeme vám ihned toto heslo zmÄ›nit.</translation>
-<translation id="5798290721819630480">Zahodit změny?</translation>
<translation id="5803412860119678065">Chcete vyplnit informace o kartě <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Oprávnění</translation>
<translation id="5804427196348435412">Používat zařízení NFC</translation>
<translation id="5810442152076338065">Vaše připojení k doméně <ph name="DOMAIN" /> je šifrováno za použití zastaralé šifrovací sady.</translation>
<translation id="5813119285467412249">&amp;Opakovat přidání</translation>
+<translation id="5817918615728894473">Spárovat</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{PÅ™i placení budou z této karty strženy peníze, ale její skuteÄné Äíslo nebude s tímto webem sdíleno. Kvůli vÄ›tšímu zabezpeÄení bude vygenerován doÄasný kód CVC.}few{PÅ™i placení budou z vybrané karty strženy peníze, ale její skuteÄné Äíslo nebude s tímto webem sdíleno. Kvůli vÄ›tšímu zabezpeÄení bude vygenerován doÄasný kód CVC.}many{PÅ™i placení budou z vybrané karty strženy peníze, ale její skuteÄné Äíslo nebude s tímto webem sdíleno. Kvůli vÄ›tšímu zabezpeÄení bude vygenerován doÄasný kód CVC.}other{PÅ™i placení budou z vybrané karty strženy peníze, ale její skuteÄné Äíslo nebude s tímto webem sdíleno. Kvůli vÄ›tšímu zabezpeÄení bude vygenerován doÄasný kód CVC.}}</translation>
<translation id="5826507051599432481">Běžný název (CN)</translation>
<translation id="5838278095973806738">Na tento web byste nemÄ›li zadávat citlivé údaje (například hesla nebo Äísla platebních karet), protože by je mohli odcizit útoÄníci.</translation>
@@ -1288,6 +1322,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="5855253129151731373">Název hostitele tohoto webu se podobá webu <ph name="LOOKALIKE_DOMAIN" />. ÚtoÄníci nÄ›kdy weby napodobují provedením drobných, snadno pÅ™ehlédnutelných zmÄ›n v názvu domény.
Pokud se domníváte, že se tato zpráva zobrazila v důsledku chyby, navštivte web https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Vypnuto</translation>
<translation id="5862579898803147654">StohovaÄ 8</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>
@@ -1304,6 +1339,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="5913377024445952699">Záznam obrazovky je pozastaven</translation>
<translation id="59174027418879706">Povoleno</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{Používá se 1}few{Používají se #}many{Používá se #}other{Používá se #}}</translation>
<translation id="5921185718311485855">Zapnuto</translation>
<translation id="5921639886840618607">Uložit kartu do úÄtu Google?</translation>
<translation id="5922853866070715753">Téměř dokonÄeno</translation>
@@ -1323,6 +1359,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="5989320800837274978">Nejsou urÄeny pevnÄ› dané servery proxy ani adresa URL skriptu PAC.</translation>
<translation id="5992691462791905444">Technické přeložení do Z</translation>
<translation id="6000758707621254961">Výsledky pro dotaz <ph name="SEARCH_TEXT" /> (<ph name="RESULT_COUNT" />)</translation>
+<translation id="6006484371116297560">Klasické</translation>
<translation id="6008122969617370890">Pořadí N stránek na list</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Kontrola hesel</translation>
@@ -1344,6 +1381,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="6045164183059402045">Šablona zavedení</translation>
<translation id="6047233362582046994">Pokud bezpeÄnostní rizika chápete, můžete <ph name="BEGIN_LINK" />tento web navÅ¡tívit<ph name="END_LINK" /> pÅ™ed tím, než budou nebezpeÄné aplikace odstranÄ›ny.</translation>
<translation id="6047927260846328439">Tento obsah by se vás podvodem mohl pokusit přimět k instalaci softwaru nebo odhalení osobních údajů. <ph name="BEGIN_LINK" />Přesto zobrazit<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Režim celé obrazovky ukonÄíte podržením klávesy |<ph name="ACCELERATOR" />|</translation>
<translation id="6049488691372270142">Dodání stránky</translation>
<translation id="6051221802930200923">Web <ph name="SITE" /> teÄ nemůžete navÅ¡tívit, protože používá pÅ™ipínání certifikátů. Síťové chyby a útoky jsou obvykle doÄasné, tato stránka pravdÄ›podobnÄ› pozdÄ›ji bude fungovat.</translation>
<translation id="6051898664905071243">PoÄet stránek:</translation>
@@ -1360,6 +1398,7 @@ Kontaktujte administrátora systému.</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>
<translation id="6116338172782435947">Přístup k textu a obrázkům zkopírovaným do schránky</translation>
<translation id="6120179357481664955">Uložit vaše UPI ID?</translation>
+<translation id="6123290840358279103">Zobrazit virtuální kartu</translation>
<translation id="6124432979022149706">Konektory Chrome Enterprise</translation>
<translation id="6146055958333702838">Zkontrolujte vÅ¡echny kabely a restartujte vÅ¡echny smÄ›rovaÄe, modemy a další síťová zařízení, která používáte.</translation>
<translation id="614940544461990577">Zkuste:</translation>
@@ -1395,6 +1434,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="6289939620939689042">Barva stránky</translation>
<translation id="6290238015253830360">Zde se zobrazí navrhované Älánky</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">BezpeÄnostní kód kreditní karty (CVC):</translation>
<translation id="6302269476990306341">Zastavování Asistenta Google v Chromu</translation>
<translation id="6305205051461490394">Web <ph name="URL" /> není dostupný.</translation>
<translation id="6312113039770857350">Webová stránka není k dispozici</translation>
@@ -1420,6 +1460,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="6390200185239044127">Přeložení napůl do Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Vkládání ze zdroje <ph name="ORIGIN_NAME" /> do tohoto umístění blokuje zásada administrátora</translation>
+<translation id="6398765197997659313">UkonÄit režim celé obrazovky</translation>
<translation id="6401136357288658127">Podpora této zásady byla ukonÄena. MÄ›li byste místo ní používat zásadu <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Upravit záložku</translation>
<translation id="6406765186087300643">C0 (obálka)</translation>
@@ -1432,7 +1473,6 @@ Kontaktujte administrátora systému.</translation>
<translation id="6428450836711225518">Ověření telefonního Äísla</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="6440503408713884761">Ignorováno</translation>
<translation id="6443406338865242315">Která rozšíření a pluginy máte nainstalované</translation>
<translation id="6446163441502663861">Kahu (obálka)</translation>
@@ -1475,6 +1515,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="6624427990725312378">Kontaktní údaje</translation>
<translation id="6626291197371920147">PÅ™idání platného Äísla karty</translation>
<translation id="6628463337424475685">Vyhledávání <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Hledání zařízení USB…</translation>
<translation id="6630809736994426279">ÚtoÄníci, kteří se aktuálnÄ› nacházejí na webu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, se mohou pokusit nainstalovat do vaÅ¡eho poÄítaÄe Mac nebezpeÄné programy, které mohou ukrást nebo smazat vaÅ¡e informace (například fotky, hesla, zprávy nebo platební karty). <ph name="BEGIN_LEARN_MORE_LINK" />Další informace<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Vymazat</translation>
@@ -1490,6 +1531,7 @@ Kontaktujte administrátora systému.</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="6687335167692595844">Požadována velikost písma</translation>
+<translation id="6688743156324860098">Aktualizovat…</translation>
<translation id="6689249931105087298">Relativní s kompresí Äerného bodu</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="6698381487523150993">Vytvořil:</translation>
@@ -1505,6 +1547,7 @@ Kontaktujte administrátora systému.</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="6753269504797312559">Hodnota zásady</translation>
<translation id="6757797048963528358">Zařízení přešlo do režimu spánku.</translation>
+<translation id="6767985426384634228">Aktualizovat adresu?</translation>
<translation id="6768213884286397650">Hagaki (pohlednice)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Fialová</translation>
@@ -1527,6 +1570,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome tuto stránku zjednoduÅ¡il, aby se snadnÄ›ji Äetla. Původní stránku Chrome naÄetl pÅ™es nezabezpeÄené pÅ™ipojení.</translation>
<translation id="6891596781022320156">Úroveň zásady není podporována.</translation>
+<translation id="6895143722905299846">Virtuální Äíslo:</translation>
<translation id="6895330447102777224">Vaše karta je ověřena</translation>
<translation id="6897140037006041989">User agent</translation>
<translation id="6898699227549475383">Organizace (O)</translation>
@@ -1562,10 +1606,10 @@ Kontaktujte administrátora systému.</translation>
<translation id="7004583254764674281">Potvrzovat karty rychleji pomocí technologie Windows Hello</translation>
<translation id="7006930604109697472">Přesto odeslat</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Změnit velikost nastavení</translation>
<translation id="7014741021609395734">Úroveň přiblížení</translation>
<translation id="7016992613359344582">Může se jednat o jednorázové nebo opakované poplatky, které nemusejí být jasně patrné.</translation>
<translation id="7029809446516969842">Hesla</translation>
+<translation id="7030436163253143341">Certifikát není platný</translation>
<translation id="7031646650991750659">Které aplikace Google Play máte nainstalované</translation>
<translation id="7050187094878475250">Pokusili jste se připojit k doméně <ph name="DOMAIN" />, ale server předložil certifikát, který má příliš dlouhé období platnosti a je proto nedůvěryhodný.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Tuto kartu v tuto chvíli nelze uložit}few{Tyto karty v tuto chvíli nelze uložit}many{Tyto karty v tuto chvíli nelze uložit}other{Tyto karty v tuto chvíli nelze uložit}}</translation>
@@ -1634,12 +1678,14 @@ Kontaktujte administrátora systému.</translation>
<translation id="7300012071106347854">Sytě modrá</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />“</translation>
<translation id="7304030187361489308">Vysoký</translation>
+<translation id="7305756307268530424">ZaÄít pomaleji</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Pomoc s připojením</translation>
<translation id="7323804146520582233">Skrýt sekci <ph name="SECTION" /></translation>
<translation id="733354035281974745">Místní pÅ™epsání úÄtu na zařízení</translation>
<translation id="7333654844024768166">PrávÄ› jste své heslo zadali na klamavém webu. Chromium doporuÄuje navÅ¡tívit weby <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> a další weby, na nichž toto heslo používáte, a okamžitÄ› ho zmÄ›nit.</translation>
<translation id="7334320624316649418">&amp;Opakovat změnu uspořádání</translation>
+<translation id="7337248890521463931">Zobrazit další řádky</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>
@@ -1647,6 +1693,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Příkazový řádek</translation>
<translation id="7359588939039777303">Byly zablokovány reklamy.</translation>
+<translation id="7363096869660964304">To neznamená, že jste neviditelní. Anonymní režim neskryje vaši aktivitu před vaším zaměstnavatelem, poskytovatelem internetových služeb ani webovými stránkami, které navštívíte.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, stisknutím tabulátoru a poté klávesy Enter můžete přidávat a spravovat adresy v nastavení Chromu</translation>
<translation id="7365849542400970216">Zjišťovat využití vašeho zařízení?</translation>
<translation id="7372973238305370288">výsledek vyhledávání</translation>
@@ -1657,7 +1704,9 @@ Kontaktujte administrátora systému.</translation>
<translation id="7378594059915113390">Ovládání médií</translation>
<translation id="7378627244592794276">Ne</translation>
<translation id="7378810950367401542"> / </translation>
+<translation id="7386364858855961704">Nelze použít</translation>
<translation id="7390545607259442187">Ověření karty</translation>
+<translation id="7392089738299859607">Aktualizovat adresu</translation>
<translation id="7399802613464275309">BezpeÄnostní kontrola</translation>
<translation id="7400418766976504921">Adresa URL</translation>
<translation id="7403591733719184120">Vaše zařízení <ph name="DEVICE_NAME" /> je spravováno</translation>
@@ -1672,6 +1721,7 @@ Kontaktujte administrátora systému.</translation>
&lt;li&gt;Informace o tom, jak tento software trvale odstranit z poÄítaÄe, naleznete v &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;centru nápovÄ›dy prohlížeÄe Chrome&lt;/a&gt;.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Půvabné</translation>
<translation id="7416351320495623771">Spravovat hesla…</translation>
<translation id="7419106976560586862">Cesta k profilu</translation>
<translation id="7437289804838430631">Přidat kontaktní údaje</translation>
@@ -1687,7 +1737,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="7481312909269577407">Vpřed</translation>
<translation id="7485870689360869515">Nebyla nalezena žádná data.</translation>
<translation id="7495528107193238112">Tento obsah je blokován. Požádejte vlastníka webu, aby tento problém vyřešil.</translation>
-<translation id="7498234416455752244">PokraÄovat v úpravách</translation>
+<translation id="7498193950643227031">V případÄ› zmÄ›ny velikosti se může chovat neoÄekávanÄ›. Možnost zmÄ›ny velikosti aplikací můžete zakázat v <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">PrávÄ› jste své heslo zadali na klamavém webu. Chromium doporuÄuje zkontrolovat uložená hesla pro weby <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> a další weby, na nichž toto heslo používáte.</translation>
<translation id="7508255263130623398">Vrácené ID zařízení pro zásady je prázdné nebo neodpovídá aktuálnímu ID zařízení</translation>
<translation id="7508870219247277067">Žlutozelená</translation>
@@ -1707,6 +1757,7 @@ Kontaktujte administrátora systému.</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="755279583747225797">Testování technologie je aktivní</translation>
<translation id="7552846755917812628">Vyzkoušejte následující tipy:</translation>
<translation id="7554475479213504905">PÅ™esto znovu naÄíst a zobrazit</translation>
<translation id="7554791636758816595">Nová karta</translation>
@@ -1725,7 +1776,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, stisknutím klávesy Tab a poté Enter můžete zobrazit a spravovat hesla v nastavení Chromu</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="7616645509853975347">Administrátor vám v prohlížeÄi zapnul konektory Chrome Enterprise Connectors. Tyto konektory mají přístup k nÄ›kterým vaÅ¡im datům.</translation>
<translation id="7619838219691048931">Koncový list</translation>
<translation id="762844065391966283">JednotlivÄ›</translation>
@@ -1790,13 +1840,12 @@ Kontaktujte administrátora systému.</translation>
<translation id="782886543891417279">Síť Wi-Fi, kterou používáte (<ph name="WIFI_NAME" />), může vyžadovat, abyste navštívili její stránku přihlášení.</translation>
<translation id="7836231406687464395">Postfix (obálka)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Žádné}=1{1 aplikace (<ph name="EXAMPLE_APP_1" />)}=2{2 aplikace (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}few{# aplikace (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}many{# aplikace (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# aplikací (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">To neznamená, že jste neviditelní. Anonymní režim neskryje vaši aktivitu před vaším zaměstnavatelem, poskytovatelem internetových služeb ani webovými stránkami, které navštívíte.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Otevírat přidružené typy souborů.</translation>
<translation id="7862185352068345852">Opustit web?</translation>
<translation id="7865448901209910068">Nejlepší rychlost</translation>
<translation id="7874263914261512992">PrávÄ› jste své heslo zadali na klamavém webu. Chrome doporuÄuje zkontrolovat uložená hesla pro weby <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> a další weby, na nichž toto heslo používáte.</translation>
<translation id="7878562273885520351">Heslo může být prolomeno</translation>
+<translation id="7880146494886811634">Uložit adresu</translation>
<translation id="7882421473871500483">Hnědá</translation>
<translation id="7887683347370398519">Zkontrolujte kód CVC a zkuste to znovu</translation>
<translation id="7887885240995164102">Spustit režim obrazu v obraze</translation>
@@ -1804,6 +1853,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="7894280532028510793">Pokud je adresa zadána správně, <ph name="BEGIN_LINK" />zkuste spustit Diagnostiku sítě<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (obálka)</translation>
<translation id="7931318309563332511">Neznámé</translation>
+<translation id="793209273132572360">Aktualizovat adresu?</translation>
<translation id="7932579305932748336">Potah</translation>
<translation id="79338296614623784">Zadejte platné telefonní Äíslo</translation>
<translation id="7934052535022478634">Platba dokonÄena</translation>
@@ -1874,6 +1924,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="8175796834047840627">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í.</translation>
<translation id="8176440868214972690">Administrátor tohoto zařízení odeslal urÄité informace (například nastavení nebo zásady) následujícím webům.</translation>
<translation id="8184538546369750125">Použít výchozí globální hodnotu (Povolit)</translation>
+<translation id="8193086767630290324">Akce provedené s daty, která byla oznaÄena jako důvÄ›rná</translation>
<translation id="8194797478851900357">&amp;Vrátit přesunutí zpět</translation>
<translation id="8201077131113104583">Neplatná adresa URL aktualizace rozšíření s ID <ph name="EXTENSION_ID" />.</translation>
<translation id="8202097416529803614">Shrnutí objednávky</translation>
@@ -1896,6 +1947,7 @@ Kontaktujte administrátora systému.</translation>
<translation id="8249296373107784235">Zrušit</translation>
<translation id="8249320324621329438">Naposledy naÄteno:</translation>
<translation id="8253091569723639551">FakturaÄní adresa je povinná</translation>
+<translation id="8257387598443225809">Tato aplikace je urÄena pro mobily</translation>
<translation id="825929999321470778">Zobrazit všechna uložená hesla</translation>
<translation id="8261506727792406068">Smazat</translation>
<translation id="8262952874573525464">Sešití na spodním okraji</translation>
@@ -2020,7 +2072,6 @@ Další podrobnosti:
<translation id="8719528812645237045">Několik otvorů nahoře</translation>
<translation id="8725066075913043281">Zkusit znovu</translation>
<translation id="8726549941689275341">Velikost stránky:</translation>
-<translation id="8728672262656704056">Jste v anonymním režimu</translation>
<translation id="8730621377337864115">Hotovo</translation>
<translation id="8731544501227493793">TlaÄítko Spravovat hesla, stisknutím klávesy Enter můžete zobrazit a spravovat hesla v nastavení Chromu</translation>
<translation id="8734529307927223492">Váš <ph name="DEVICE_TYPE" /> spravuje doména <ph name="MANAGER" /></translation>
@@ -2097,6 +2148,7 @@ Další podrobnosti:
<translation id="9020542370529661692">Stránka byla přeložena do jazyka <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(neplatný)</translation>
+<translation id="9030265603405983977">Monochromatické</translation>
<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>
@@ -2120,6 +2172,7 @@ Další podrobnosti:
<translation id="91108059142052966">Zásada administrátora zakazuje sdílení obrazovky s aplikací <ph name="APPLICATION_TITLE" />, když je viditelný důvěrný obsah</translation>
<translation id="9114524666733003316">Ověřování karty...</translation>
<translation id="9114581008513152754">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="9117930699067497412">Svěží</translation>
<translation id="9119042192571987207">Nahráno</translation>
<translation id="9128016270925453879">Zásady jsou naÄteny</translation>
<translation id="9128870381267983090">Připojit k síti</translation>
@@ -2138,6 +2191,7 @@ Další podrobnosti:
<translation id="9170848237812810038">Z&amp;pět</translation>
<translation id="9171296965991013597">Zavřít aplikaci?</translation>
<translation id="9173282814238175921">Jeden dokument / nový list</translation>
+<translation id="9173995187295789444">Vyhledávání zařízení Bluetooth...</translation>
<translation id="917450738466192189">Certifikát serveru je neplatný.</translation>
<translation id="9174917557437862841">TlaÄítko pÅ™epínání karet. Stisknutím klávesy Enter pÅ™ejdete na tuto kartu</translation>
<translation id="9179703756951298733">Spravujte své platební údaje a informace o platebních kartách v nastavení Chromu</translation>
diff --git a/chromium/components/strings/components_strings_da.xtb b/chromium/components/strings/components_strings_da.xtb
index 722d4bd8583..ee47098e852 100644
--- a/chromium/components/strings/components_strings_da.xtb
+++ b/chromium/components/strings/components_strings_da.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Vælg tilladelse til <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Fortryd omarrangering</translation>
+<translation id="1123753900084781868">Livetekstning er ikke tilgængelig lige nu</translation>
<translation id="1125573121925420732">Advarsler kan almindeligt forekomme, når websites opdaterer deres sikkerhed. Dette forbedres snart.</translation>
<translation id="112840717907525620">Cache for politik er OK</translation>
<translation id="1130564665089811311">Knappen Oversæt side – tryk på Enter for at oversætte denne side med Google Oversæt</translation>
@@ -74,6 +75,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="1240347957665416060">Navnet på din enhed</translation>
<translation id="124116460088058876">Flere sprog</translation>
<translation id="1243027604378859286">Forfatter:</translation>
+<translation id="1246424317317450637">Fed</translation>
<translation id="1250759482327835220">Gem dit kort, dit navn og din faktureringsadresse på din Google-konto for at betale hurtigere næste gang.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (synkroniseret)</translation>
<translation id="1256368399071562588">&lt;p&gt;Hvis du forsøger at besøge et website, og det ikke åbnes, kan du starte med at prøve at rette fejlen med følgende fejlfindingstrin:&lt;/p&gt;
@@ -156,6 +158,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="1476595624592550506">Skift adgangskode</translation>
<translation id="1484290072879560759">Vælg leveringsadresse</translation>
<translation id="1492194039220927094">Underretning om politikker:</translation>
+<translation id="1495677929897281669">Tilbage til fanen</translation>
<translation id="1501859676467574491">Vis kort fra din Google-konto</translation>
<translation id="1507202001669085618">&lt;p&gt;Denne fejl vises, hvis du bruger en Wi-Fi-portal, hvor du skal logge ind, før du kan komme på nettet.&lt;/p&gt;
&lt;p&gt;Du kan rette fejlen ved at klikke på &lt;strong&gt;Opret forbindelse&lt;/strong&gt; på den side, du forsøger at åbne.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="1532118530259321453">Denne side siger</translation>
<translation id="153384715582417236">Det var det hele indtil videre</translation>
<translation id="1536390784834419204">Oversæt side</translation>
+<translation id="1539840569003678498">Rapporten blev sendt:</translation>
<translation id="154408704832528245">Vælg leveringsadresse</translation>
<translation id="1549470594296187301">JavaScript skal være aktiveret, før du kan bruge denne funktion.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="1682696192498422849">Kort kant først</translation>
<translation id="168693727862418163">Politikkens værdi blev ikke bekræftet i forhold til dens skema, og den ignoreres derfor.</translation>
<translation id="168841957122794586">Servercertifikatet indeholder en svag kryptografisk nøgle.</translation>
+<translation id="1696290444144917273">Se virtuelle kortoplysninger</translation>
<translation id="1697532407822776718">Fuldført</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da dens sikkerhedscertifikat tilsyneladende først gælder fra i morgen. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.}one{Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da dens sikkerhedscertifikat tilsyneladende først gælder fra om # dag. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.}other{Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da dens sikkerhedscertifikat tilsyneladende først gælder fra om # dage. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Ignoreret, da <ph name="POLICY_NAME" /> ikke er angivet til <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> anmoder om at gemme data permanent på din lokale computer</translation>
<translation id="1713628304598226412">Bakke 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Postkasse 3</translation>
<translation id="1718029547804390981">Dokumenterne er for store til at blive annoteret</translation>
<translation id="1721424275792716183">* Feltet skal udfyldes</translation>
+<translation id="1727613060316725209">Certifikatet er gyldigt</translation>
<translation id="1727741090716970331">Tilføj et gyldigt kortnummer</translation>
<translation id="1728677426644403582">Du ser kilden for en webside</translation>
<translation id="173080396488393970">Denne korttype understøttes ikke</translation>
@@ -246,7 +253,6 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
din anmodning til <ph name="SITE" />. Politikker for oprindelse kan anvendes af
websiteoperatorer til at konfigurere sikkerhed og andre egenskaber for et website.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Opdater din adgangssætning til synkronisering.</translation>
<translation id="1787142507584202372">Dine åbne faner vises her</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, flere handlinger er tilgængelige, tryk på Tab-tasten for at gennemse dem</translation>
@@ -279,6 +285,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="1919345977826869612">Annoncer</translation>
<translation id="1919367280705858090">Få hjælp til en specifik fejlmeddelelse</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ingen}=1{1 website}one{# website}other{# websites}}</translation>
+<translation id="1924727005275031552">Ny</translation>
<translation id="1945968466830820669">Du kan miste adgangen til din organisations konto eller udsættes for identitetstyveri. Chromium anbefaler, at du skifter din adgangskode nu.</translation>
<translation id="1947454675006758438">Hæftning øverst til højre</translation>
<translation id="1958218078413065209">Din rekord er <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="2042213636306070719">Bakke 7</translation>
<translation id="204357726431741734">Log ind for at bruge de adgangskoder, du har gemt på din Google-konto</translation>
<translation id="2053111141626950936">Sider på <ph name="LANGUAGE" /> oversættes ikke.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Når denne indstilling er aktiveret og angives som aktiv, fastslår Chrome, hvilken stor gruppe eller "kohorte" din seneste browseraktivitet minder mest om. Annoncører kan vælge annoncer til gruppen, og din browserhistorik forbliver privat på din enhed. Din gruppe opdateres hver dag.}=1{Når denne indstilling er aktiveret og angives som aktiv, fastslår Chrome, hvilken stor gruppe eller "kohorte" din seneste browseraktivitet minder mest om. Annoncører kan vælge annoncer til gruppen, og din browserhistorik forbliver privat på din enhed. Din gruppe opdateres hver dag.}one{Når denne indstilling er aktiveret og angives som aktiv, fastslår Chrome, hvilken stor gruppe eller "kohorte" din seneste browseraktivitet minder mest om. Annoncører kan vælge annoncer til gruppen, og din browserhistorik forbliver privat på din enhed. Din gruppe opdateres med {NUM_DAYS} dags mellemrum.}other{Når denne indstilling er aktiveret og angives som aktiv, fastslår Chrome, hvilken stor gruppe eller "kohorte" din seneste browseraktivitet minder mest om. Annoncører kan vælge annoncer til gruppen, og din browserhistorik forbliver privat på din enhed. Din gruppe opdateres med {NUM_DAYS} dages mellemrum.}}</translation>
<translation id="2053553514270667976">Postnummer</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 forslag}one{# forslag}other{# forslag}}</translation>
<translation id="2071692954027939183">Der blev automatisk blokeret notifikationer, da du som regel ikke tillader notifikationer</translation>
<translation id="2079545284768500474">Fortryd</translation>
<translation id="20817612488360358">Indstillingerne for systemproxy er angivet at blive brugt, men en eksplicit proxykonfiguration er også angivet.</translation>
<translation id="2082238445998314030">Resultat <ph name="RESULT_NUMBER" /> af <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Gem…</translation>
<translation id="2088086323192747268">Knappen Administrer synkronisering – tryk på Enter for at administrere, hvilke oplysninger der skal synkroniseres, i Chrome-indstillingerne</translation>
<translation id="2091887806945687916">Lyd</translation>
<translation id="2094505752054353250">Uoverensstemmelse mellem domæner</translation>
@@ -379,6 +388,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="2317259163369394535"><ph name="DOMAIN" /> kræver et brugernavn og en adgangskode.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, udløber <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Indstillingen styres af din administrator</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> vil gerne parre</translation>
<translation id="2344028582131185878">Automatiske downloads</translation>
<translation id="2346319942568447007">Billede, du har kopieret</translation>
<translation id="2354001756790975382">Andre bogmærker</translation>
@@ -386,8 +396,10 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="2355395290879513365">Hackere kan muligvis se de billeder, du kigger på på dette website, og narre dig ved at ændre dem.</translation>
<translation id="2356070529366658676">Spørg</translation>
<translation id="2357481397660644965">Din enhed administreres af <ph name="DEVICE_MANAGER" />, og din konto administreres af <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Om mindre end en dag}=1{Om en dag}one{Om {NUM_DAYS} dag}other{Om {NUM_DAYS} dage}}</translation>
<translation id="2359629602545592467">Flere</translation>
<translation id="2359808026110333948">Fortsæt</translation>
+<translation id="2359961752320758691">Dit virtuelle kortnummer er tilføjet.</translation>
<translation id="2367567093518048410">Niveau</translation>
<translation id="2372464001869762664">Når du bekræfter, deles kortoplysningerne på din Google-konto med dette website. Find kontrolkoden under oplysningerne om din Plex-konto.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="239429038616798445">Denne forsendelsesmetode er ikke tilgængelig. Prøv en anden metode.</translation>
<translation id="2396249848217231973">&amp;Fortryd sletning</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Gammel</translation>
<translation id="2413528052993050574">Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da sikkerhedscertifikatet muligvis er blevet tilbagekaldt. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.</translation>
<translation id="2414886740292270097">Mørk</translation>
<translation id="2438874542388153331">Fire huller i højre side</translation>
@@ -425,10 +438,10 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="2521385132275182522">Hæftning nederst til højre</translation>
<translation id="2523886232349826891">Gemmes kun på denne enhed</translation>
<translation id="2524461107774643265">Tilføj flere oplysninger</translation>
-<translation id="2526590354069164005">Skrivebord</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{og 1 mere}one{og # mere}other{og # mere}}</translation>
<translation id="2536110899380797252">Tilføj adresse</translation>
<translation id="2539524384386349900">Registrer</translation>
+<translation id="2541219929084442027">Når du har lukket alle dine inkognitofaner, gemmes der hverken cookies, browser- eller søgehistorik for de sider, du besøger i inkognitotilstand. Dog gemmes alle de filer, du downloader, og bogmærker, du opretter.</translation>
<translation id="2544644783021658368">Enkelt dokument</translation>
<translation id="254947805923345898">Værdien for politikken er ikke gyldig.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> sendte et ugyldigt svar.</translation>
@@ -448,6 +461,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="2629325967560697240"><ph name="BEGIN_ENHANCED_PROTECTION_LINK" />Aktivér forbedret beskyttelse<ph name="END_ENHANCED_PROTECTION_LINK" /> for at få Chromes højeste sikkerhedsniveau</translation>
<translation id="2634124572758952069">IP-adressen på serveren for <ph name="HOST_NAME" /> blev ikke fundet.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Der blev ikke fundet nogen kompatible enheder.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, tryk på Tab-tasten efterfulgt af Enter for at rydde browserhistorik, cookies, cache m.m. i Chrome-indstillingerne</translation>
<translation id="2650446666397867134">Der blev nægtet adgang til filen</translation>
@@ -494,6 +508,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<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="2807052079800581569">Billedposition Y</translation>
+<translation id="2820957248982571256">Scanner…</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>
@@ -501,6 +516,8 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">Dette website viser påtrængende eller vildledende annoncer.</translation>
+<translation id="287596039013813457">Afslappet</translation>
+<translation id="2876489322757410363">Du forlader inkognitotilstand for at betale via en ekstern app. Vil du fortsætte?</translation>
<translation id="2878197950673342043">Plakatfals</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Placering af vinduer</translation>
@@ -550,7 +567,6 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, tryk på Tab-tasten efterfulgt af Enter for at køre sikkerhedstjekket i Chrome-indstillingerne</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>
<translation id="306573536155379004">Spillet er startet.</translation>
<translation id="3080254622891793721">Grafik</translation>
<translation id="3086579638707268289">Din aktivitet på nettet overvåges</translation>
@@ -573,7 +589,6 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="315504272643575312">Din konto administreres af <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Gendan</translation>
<translation id="3162559335345991374">Det Wi-Fi-netværk, du bruger, kan kræve, at du går til netværkets loginside.</translation>
-<translation id="3167968892399408617">Når du har lukket alle dine inkognitofaner, gemmes der hverken cookies, browser- eller søgehistorik for de sider, du besøger i inkognitotilstand. Dog gemmes alle de filer, du downloader, og bogmærker, du opretter.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ø</translation>
<translation id="3176929007561373547">Kontrollér dine proxyindstillinger, eller kontakt din netværksadministrator
@@ -599,10 +614,12 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<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="3249845759089040423">Groovy</translation>
<translation id="3252266817569339921">Fransk</translation>
<translation id="3266793032086590337">Værdi (modstridende)</translation>
<translation id="3268451620468152448">Ã…bne faner</translation>
<translation id="3270847123878663523">&amp;Fortryd omarrangering</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> vil gerne oprette forbindelse</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Din organisation <ph name="ENROLLMENT_DOMAIN" /> har sendt nogle oplysninger til følgende websites, f.eks. indstillinger eller politikker.</translation>
<translation id="3282497668470633863">Tilføj navn på kort</translation>
@@ -655,6 +672,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="3428151540071562330">En eller flere af serverskabelon-URI'erne for DnsOverHttpsTemplates er ugyldige og anvendes ikke.</translation>
<translation id="3431636764301398940">Gem dette kort på denne enhed</translation>
<translation id="3432601291244612633">Luk side</translation>
+<translation id="3435738964857648380">Sikkerhed</translation>
<translation id="3435896845095436175">Aktivér</translation>
<translation id="3438829137925142401">Brug de adgangskoder, der er gemt på din Google-konto</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="3584299510153766161">To huller nederst</translation>
<translation id="3586931643579894722">Skjul oplysninger</translation>
<translation id="3587738293690942763">I midten</translation>
+<translation id="3590643883886679995">Dine logindata gemmes på denne enhed, når du afslutter inkognitotilstand.</translation>
+<translation id="359126217934908072">MÃ¥ned/Ã¥r:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Du kan til enhver tid nulstille din gruppe. Det tager ca. en dag at blive medlem af en nye gruppe.}=1{Du kan til enhver tid nulstille din gruppe. Det tager ca. en dag at blive medlem af en nye gruppe.}one{Du kan til enhver tid nulstille din gruppe. Det tager {NUM_DAYS} dag at blive medlem af en ny gruppe.}other{Du kan til enhver tid nulstille din gruppe. Det tager {NUM_DAYS} dage at blive medlem af en ny gruppe.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Appen er blokeret af din administrator</translation>
<translation id="3608932978122581043">Retning for indførelse</translation>
@@ -706,13 +727,13 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="3615877443314183785">Angiv en gyldig udløbsdato</translation>
<translation id="36224234498066874">Ryd browserdata...</translation>
<translation id="362276910939193118">Vis hele historikken</translation>
-<translation id="3625635938337243871">Dine logindata gemmes på denne enhed, når du afslutter inkognitotilstand.</translation>
<translation id="3630155396527302611">Hvis programmet allerede står på listen over programmer, der har adgang til netværket, kan du prøve
at fjerne det fra listen og tilføje det igen.</translation>
<translation id="3630699740441428070">Administratorer af denne enhed har konfigureret din netværksforbindelse, hvilket kan give dem mulighed for at se din netværkstrafik, herunder hvilke websites du besøger.</translation>
<translation id="3631244953324577188">Biometri</translation>
<translation id="3633738897356909127">Knappen Opdater Chrome – tryk på Enter for at opdatere Chrome i dine Chrome-indstillinger</translation>
<translation id="3634530185120165534">Bakke 5</translation>
+<translation id="3637662659967048211">Gem på Google-konto</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Program:</translation>
<translation id="3650584904733503804">Valideringen er fuldført</translation>
@@ -753,6 +774,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="3781428340399460090">Varm lyserød</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth-enheder</translation>
+<translation id="3787675388804467730">Virtuelt kortnummer</translation>
<translation id="3787705759683870569">Udløber <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Størrelse 16</translation>
<translation id="3789841737615482174">Installer</translation>
@@ -772,6 +794,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="3841184659773414994">Filhandlers</translation>
<translation id="385051799172605136">Tilbage</translation>
<translation id="3858027520442213535">Opdater dato og tid</translation>
+<translation id="3881478300875776315">Vis færre linjer</translation>
<translation id="3884278016824448484">Modstridende enheds-id</translation>
<translation id="3885155851504623709">Amt</translation>
<translation id="388632593194507180">Overvågning blev registreret.</translation>
@@ -797,6 +820,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="397105322502079400">Beregner...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> er blokeret</translation>
<translation id="3973357910713125165">Knappen Kør Chrome-sikkerhedstjek – tryk på Enter for at køre sikkerhedstjekket i Chrome-indstillingerne</translation>
+<translation id="3986705137476756801">Deaktiver Livetekstning indtil videre</translation>
<translation id="3987405730340719549">Chrome har registreret, at dette website kan være falsk eller svigagtigt.
Hvis du mener, at denne advarsel er en fejl, kan du besøge https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="4275830172053184480">Genstart din enhed</translation>
<translation id="4277028893293644418">Nulstil adgangskoden</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="4287885627794386150">Kvalificeret til en prøveperiode, men ikke aktiv.</translation>
<translation id="4297502707443874121">Miniature for siden <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Udvid</translation>
<translation id="4300675098767811073">Flere huller i højre side</translation>
<translation id="4302514097724775343">Tryk på dinoen for at spille</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Din fil kunne ikke tilgås</translation>
-<translation id="4305817255990598646">Skift</translation>
+<translation id="4306529830550717874">Vil du gemme adressen?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloker (standardindstilling)</translation>
<translation id="4314815835985389558">Administrer synkronisering</translation>
@@ -926,6 +951,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="4377125064752653719">Du har forsøgt at få fat på <ph name="DOMAIN" />, men serverens certifikat er blevet tilbagekaldt af udgiveren. Det betyder, at du bestemt ikke bør have tillid til serverens sikkerhedsoplysninger. Du kommunikerer muligvis med en hacker.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Kant</translation>
+<translation id="4406883609789734330">Livetekstning</translation>
<translation id="4406896451731180161">søgeresultater</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Du har lige angivet din adgangskode på et vildledende website. Chrome anbefaler, at du straks går til <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> og eventuelle andre websites, hvor du bruger denne adgangskode, og ændrer den.</translation>
@@ -938,7 +964,6 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Brug af en proxy er deaktiveret, men en eksplicit proxykonfiguration er angivet.</translation>
<translation id="4464826014807964867">Websites med oplysninger fra din organisation</translation>
-<translation id="4466881336512663640">Du mister eventuelle formularændringer. Er du sikker på, at du vil fortsætte?</translation>
<translation id="4476953670630786061">Denne formular er ikke sikker. Autofyld er blevet deaktiveret.</translation>
<translation id="4477350412780666475">Næste nummer</translation>
<translation id="4482953324121162758">Dette website kan ikke oversættes.</translation>
@@ -972,6 +997,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="4594403342090139922">&amp;Fortryd sletning</translation>
<translation id="4597348597567598915">Størrelse 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Virkningsfuld</translation>
<translation id="4628948037717959914">Billede</translation>
<translation id="4631649115723685955">Penge tilbage er tilknyttet</translation>
<translation id="4636930964841734540">Oplysninger</translation>
@@ -991,6 +1017,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Side</translation>
+<translation id="4702656508969495934">Livetekstning er synlig, brug vindueskifteren for at fokusere</translation>
<translation id="4708268264240856090">Din forbindelse blev afbrudt</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Køre Windows Netværksdiagnosticering<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="4738601419177586157"><ph name="TEXT" />-søgeforslag</translation>
<translation id="4742407542027196863">Administrer adgangskoder…</translation>
<translation id="4744603770635761495">Eksekverbar sti</translation>
+<translation id="4749011317274908093">Du er i inkognitotilstand</translation>
<translation id="4750917950439032686">Dine oplysninger (f.eks. adgangskoder eller kreditkortnumre) er private, når de sendes til dette website.</translation>
<translation id="4756388243121344051">&amp;Historik</translation>
<translation id="4758311279753947758">Tilføj kontaktoplysninger</translation>
@@ -1033,6 +1061,8 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="4813512666221746211">Netværksfejl</translation>
<translation id="4816492930507672669">Tilpas til siden</translation>
<translation id="4819347708020428563">Vil du redigere annoteringer i standardvisningen?</translation>
+<translation id="4825507807291741242">Kraftfuld</translation>
+<translation id="4838327282952368871">Drømmende</translation>
<translation id="484462545196658690">Automatisk</translation>
<translation id="4850886885716139402">Vis</translation>
<translation id="485316830061041779">Tysk</translation>
@@ -1169,6 +1199,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="5314967030527622926">Brochureværktøj</translation>
<translation id="5316812925700871227">Rotér mod uret</translation>
<translation id="5317780077021120954">Gem</translation>
+<translation id="5321288445143113935">Maksimeret</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> af <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Vælg kontaktoplysninger</translation>
<translation id="5327248766486351172">Navn</translation>
@@ -1176,11 +1207,13 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="5332219387342487447">Leveringsmetode</translation>
<translation id="5333022057423422993">Chrome har fundet den adgangskode, du netop har brugt, i forbindelse med et brud på datasikkerheden. For at beskytte dine konti anbefaler vi, at du tjekker dine gemte adgangskoder.</translation>
<translation id="5334013548165032829">Detaljerede systemlogs</translation>
+<translation id="5334145288572353250">Vil du gemme adressen?</translation>
<translation id="5340250774223869109">Appen er blokeret</translation>
<translation id="534295439873310000">NFC-enheder</translation>
<translation id="5344579389779391559">Denne side forsøger muligvis at opkræve penge af dig</translation>
<translation id="5355557959165512791">Du kan ikke besøge <ph name="SITE" /> lige nu, da dets certifikat er blevet tilbagekaldt. Netværksfejl og angreb er normalt midlertidige, så siden vil sandsynligvis fungere igen senere.</translation>
<translation id="536296301121032821">Der kunne ikke gemmes indstillinger for politik</translation>
+<translation id="5363309033720083897">Din administrator har tilladt denne serieport</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="5386426401304769735">Certifikatkæden for dette website indeholder et certifikat, der er signeret med SHA-1.</translation>
@@ -1189,6 +1222,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="5398772614898833570">Annoncer er blokeret</translation>
<translation id="5400836586163650660">Grå</translation>
<translation id="540969355065856584">Denne server kunne ikke bevise, at den er <ph name="DOMAIN" />, da dens sikkerhedscertifikat ikke er gyldigt i øjeblikket. Dette kan skyldes en fejlkonfiguration, eller at en hacker har opfanget din forbindelse.</translation>
+<translation id="541143247543991491">Cloud (for hele systemet)</translation>
<translation id="541416427766103491">Stabler 4</translation>
<translation id="5421136146218899937">Ryd browserdata...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> vil gerne sende notifikationer til dig</translation>
@@ -1202,6 +1236,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="5455374756549232013">Forkert tidsstempel for politik</translation>
<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="5463625433003343978">Finder enheder...</translation>
<translation id="5469868506864199649">Italiensk</translation>
<translation id="5470861586879999274">&amp;Annuller fortryd redigering</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1251,7 +1286,6 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="5624120631404540903">Administrer adgangskoder</translation>
<translation id="5629630648637658800">Der kunne ikke indlæses indstillinger for politik</translation>
<translation id="5631439013527180824">Ugyldigt token for enhedsadministration</translation>
-<translation id="5632627355679805402">Dine data er krypteret med din <ph name="BEGIN_LINK" />Google-adgangskode<ph name="END_LINK" /> fra <ph name="TIME" />. Angiv den for at starte synkroniseringen.</translation>
<translation id="5633066919399395251">Brugere med ondsindede hensigter, der i øjeblikket er på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, kan forsøge at installere farlige programmer på din computer, der stjæler eller sletter dine oplysninger (f.eks. fotos, adgangskoder, beskeder og kreditkort). <ph name="BEGIN_LEARN_MORE_LINK" />Få flere oplysninger<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Vildledende indhold er blokeret.</translation>
<translation id="5644090287519800334">Billedskift X på side 1</translation>
@@ -1290,12 +1324,12 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="5785756445106461925">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 ser anderledes ud.</translation>
<translation id="5786044859038896871">Skal dine kortoplysninger udfyldes?</translation>
<translation id="578633867165174378">Chrome har fundet den adgangskode, du netop har brugt, i forbindelse med et brud på datasikkerheden. Vi anbefaler, at du ændrer adgangskoden med det samme.</translation>
-<translation id="5798290721819630480">Vil du kassere ændringerne?</translation>
<translation id="5803412860119678065">Skal <ph name="CARD_DETAIL" /> udfyldes?</translation>
<translation id="5804241973901381774">Tilladelser</translation>
<translation id="5804427196348435412">Brug NFC-enheder</translation>
<translation id="5810442152076338065">Din forbindelse til <ph name="DOMAIN" /> er krypteret ved hjælp af en forældet krypteringspakke.</translation>
<translation id="5813119285467412249">&amp;Annuller fortryd tilføjelse</translation>
+<translation id="5817918615728894473">Start parring</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Dette kort debiteres, når du betaler, men kortets faktiske nummer deles ikke med dette website. Som ekstra beskyttelse genereres der en midlertidig kontrolkode.}one{Det kort, du vælger, debiteres, når du betaler, men kortets faktiske nummer deles ikke med dette website. Som ekstra beskyttelse genereres der en midlertidig kontrolkode.}other{De kort, du vælger, debiteres, når du betaler, men kortenes faktiske numre deles ikke med dette website. Som ekstra beskyttelse genereres der en midlertidig kontrolkode.}}</translation>
<translation id="5826507051599432481">Kaldenavn (CN)</translation>
<translation id="5838278095973806738">Du bør ikke indtaste følsomme oplysninger på dette website (f.eks. adgangskoder eller kreditkortoplysninger), da de kan blive stjålet af hackere.</translation>
@@ -1303,6 +1337,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="5855253129151731373">Hostname for dette website minder om <ph name="LOOKALIKE_DOMAIN" />. Svindlere efterligner nogle gange websites ved at lave små ændringer af domænenavnet, som er svære at se.
Hvis du mener, at denne advarsel er en fejl, kan du besøge https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Fra</translation>
<translation id="5862579898803147654">Stabler 8</translation>
<translation id="5863847714970149516">Siden forude kan forsøge at opkræve dig penge</translation>
<translation id="5866257070973731571">Tilføj telefonnummer</translation>
@@ -1319,6 +1354,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="5913377024445952699">Screenshots er sat på pause</translation>
<translation id="59174027418879706">Aktiveret</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 i brug}one{# i brug}other{# i brug}}</translation>
<translation id="5921185718311485855">Til</translation>
<translation id="5921639886840618607">Vil du gemme kortet på din Google-konto?</translation>
<translation id="5922853866070715753">Næsten færdig</translation>
@@ -1338,6 +1374,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="5989320800837274978">Der er hverken angivet faste proxyservere eller en .pac-scriptwebadresse.</translation>
<translation id="5992691462791905444">Z-fals med kant foroven</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultater for "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Klassisk</translation>
<translation id="6008122969617370890">N-til-1-rækkefølge</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Tjek dine adgangskoder</translation>
@@ -1359,6 +1396,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="6045164183059402045">Skabelon for indførelse</translation>
<translation id="6047233362582046994">Hvis du er indforstået med de forbundne sikkerhedsrisici, kan du <ph name="BEGIN_LINK" />besøge dette website<ph name="END_LINK" />, inden de skadelige apps fjernes.</translation>
<translation id="6047927260846328439">Dette indhold forsøger muligvis at narre dig til at installere software eller afsløre personlige oplysninger. <ph name="BEGIN_LINK" />Vis alligevel<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Hold |<ph name="ACCELERATOR" />| nede for at afslutte fuld skærm</translation>
<translation id="6049488691372270142">Sidelevering</translation>
<translation id="6051221802930200923">Du kan ikke besøge <ph name="SITE" /> lige nu, da websitet bruger certifikatlåsning. Netværksfejl og angreb er normalt midlertidige, så siden vil sandsynligvis fungere igen senere.</translation>
<translation id="6051898664905071243">Sideantal:</translation>
@@ -1375,6 +1413,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<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>
<translation id="6116338172782435947">Se tekst og billeder, der er kopieret til udklipsholderen</translation>
<translation id="6120179357481664955">Skal dit UPI-id huskes?</translation>
+<translation id="6123290840358279103">Se virtuelt kort</translation>
<translation id="6124432979022149706">Chrome Enterprise-connectorer</translation>
<translation id="6146055958333702838">Kontrollér eventuelle kabler, og genstart alle routere, modemmer eller andre
netværksenheder, du bruger.</translation>
@@ -1411,6 +1450,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="6289939620939689042">Farve på side</translation>
<translation id="6290238015253830360">Forslag til artikler til dig vises her</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google Assistent i Chrome stopper</translation>
<translation id="6305205051461490394"><ph name="URL" /> kan ikke nås.</translation>
<translation id="6312113039770857350">Websiden er ikke tilgængelig</translation>
@@ -1436,6 +1476,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="6390200185239044127">Z-fals halvt</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Administratorpolitikken tillader ikke, at du indsætter fra <ph name="ORIGIN_NAME" /> på denne placering</translation>
+<translation id="6398765197997659313">Afslut fuld skærm</translation>
<translation id="6401136357288658127">Denne politik er udfaset. Du bør bruge politikken <ph name="NEW_POLICY" /> i stedet.</translation>
<translation id="6404511346730675251">Rediger bogmærke</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1448,7 +1489,6 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="6428450836711225518">Bekræft dit telefonnummer</translation>
<translation id="6433490469411711332">Rediger kontaktoplysninger</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> nægtede at oprette forbindelse.</translation>
-<translation id="6434309073475700221">Kassér</translation>
<translation id="6440503408713884761">Ignoreret</translation>
<translation id="6443406338865242315">Hvilke udvidelser og plugins, du har installeret</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1491,6 +1531,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="6624427990725312378">Kontaktoplysninger</translation>
<translation id="6626291197371920147">Tilføj gyldigt kortnummer</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> -søgning</translation>
+<translation id="6630043285902923878">Finder USB-enheder...</translation>
<translation id="6630809736994426279">Brugere med ondsindede hensigter, der i øjeblikket er på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, kan forsøge at installere farlige programmer på din Mac, som stjæler eller sletter dine oplysninger (f.eks. fotos, adgangskoder, beskeder og kreditkort). <ph name="BEGIN_LEARN_MORE_LINK" />Få flere oplysninger<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Ryd</translation>
@@ -1506,6 +1547,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="6671697161687535275">Vil du fjerne formularforslag fra Chromium?</translation>
<translation id="6685834062052613830">Log ud, og fuldfør konfigurationen</translation>
<translation id="6687335167692595844">Der blev anmodet om størrelse på skrifttype</translation>
+<translation id="6688743156324860098">Opdater…</translation>
<translation id="6689249931105087298">Relativ komprimering med sorte punkter</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="6698381487523150993">Oprettet:</translation>
@@ -1521,6 +1563,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="6744009308914054259">Mens du venter på en forbindelse, kan du gå til Downloads for at læse artikler offline.</translation>
<translation id="6753269504797312559">Politikkens værdi</translation>
<translation id="6757797048963528358">Din enhed gik i dvale.</translation>
+<translation id="6767985426384634228">Vil du opdatere adressen?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violet</translation>
@@ -1543,6 +1586,7 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome har forenklet denne side for at gøre den nemmere at læse. Chrome har hentet den oprindelige side via en usikker forbindelse.</translation>
<translation id="6891596781022320156">Politikniveauet understøttes ikke.</translation>
+<translation id="6895143722905299846">Virtuelt nummer:</translation>
<translation id="6895330447102777224">Dit kort er bekræftet</translation>
<translation id="6897140037006041989">Brugeragent</translation>
<translation id="6898699227549475383">Organisation (O)</translation>
@@ -1578,10 +1622,10 @@ Ellers vil det blive blokeret af dine privatlivsindstillinger. Det giver det ind
<translation id="7004583254764674281">Brug Windows Hello til at bekræfte kort hurtigere</translation>
<translation id="7006930604109697472">Send alligevel</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Indstillinger for størrelsesjustering</translation>
<translation id="7014741021609395734">Zoomniveau</translation>
<translation id="7016992613359344582">Disse debiteringer kan være enkeltstående eller gentagne og fremgår muligvis ikke tydeligt.</translation>
<translation id="7029809446516969842">Adgangskoder</translation>
+<translation id="7030436163253143341">Certifikatet er ikke gyldigt</translation>
<translation id="7031646650991750659">Hvilke Google Play-apps, du har installeret</translation>
<translation id="7050187094878475250">Du forsøgte at gå til <ph name="DOMAIN" />, men serveren præsenterede et certifikat, hvis gyldighedsperiode er for lang til at være pålidelig.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Kortet kan ikke tilføjes lige nu}one{Kortet kan ikke tilføjes lige nu}other{Kortene kan ikke tilføjes lige nu}}</translation>
@@ -1651,12 +1695,14 @@ Yderligere oplysninger:
<translation id="7300012071106347854">Koboltblå</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Højt</translation>
+<translation id="7305756307268530424">Start langsommere</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Hjælp til at oprette forbindelse</translation>
<translation id="7323804146520582233">Skjul sektionen "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Tilsidesættelse af enhedslokal konto</translation>
<translation id="7333654844024768166">Du har lige angivet din adgangskode på et vildledende website. Chromium anbefaler, at du straks går til <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> og eventuelle andre websites, hvor du bruger denne adgangskode, og ændrer adgangskoden.</translation>
<translation id="7334320624316649418">&amp;Annuller fortryd omarrangering</translation>
+<translation id="7337248890521463931">Vis flere linjer</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>
@@ -1664,6 +1710,7 @@ Yderligere oplysninger:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Kommandolinje</translation>
<translation id="7359588939039777303">Annoncer er blokeret.</translation>
+<translation id="7363096869660964304">Du er dog ikke usynlig. Inkognitotilstand skjuler ikke din browserhistorik over for din arbejdsgiver, din internetudbyder eller de websites, du besøger.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, tryk på Tab-tasten efterfulgt af Enter for at tilføje og administrere adresser i Chrome-indstillingerne</translation>
<translation id="7365849542400970216">Kende din enhedsbrug?</translation>
<translation id="7372973238305370288">søgeresultat</translation>
@@ -1674,7 +1721,9 @@ Yderligere oplysninger:
<translation id="7378594059915113390">Mediestyring</translation>
<translation id="7378627244592794276">Nej</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ikke relevant</translation>
<translation id="7390545607259442187">Bekræft kort</translation>
+<translation id="7392089738299859607">Opdater adresse</translation>
<translation id="7399802613464275309">Sikkerhedstjek</translation>
<translation id="7400418766976504921">Webadresse</translation>
<translation id="7403591733719184120">Din <ph name="DEVICE_NAME" /> administreres</translation>
@@ -1689,6 +1738,7 @@ Yderligere oplysninger:
&lt;li&gt;Gå til &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Hjælp til Chrome&lt;/a&gt; for at se, hvordan du permanent fjerner softwaren fra din computer
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Sød</translation>
<translation id="7416351320495623771">Administrer adgangskoder…</translation>
<translation id="7419106976560586862">Profilsti</translation>
<translation id="7437289804838430631">Tilføj kontaktoplysninger</translation>
@@ -1704,7 +1754,7 @@ Yderligere oplysninger:
<translation id="7481312909269577407">Frem</translation>
<translation id="7485870689360869515">Der blev ikke fundet nogen data.</translation>
<translation id="7495528107193238112">Dette indhold er blokeret. Kontakt ejeren af websitet for at løse problemet.</translation>
-<translation id="7498234416455752244">Fortsæt redigering</translation>
+<translation id="7498193950643227031">Appen fungerer muligvis ikke korrekt, hvis du ændrer dens størrelse. Du kan nu begrænse muligheden for at ændre størrelsen på apps under <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Du har lige angivet din adgangskode på et vildledende website. Chromium anbefaler, at du straks tjekker dine gemte adgangskoder til <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> og andre websites, hvor du bruger denne adgangskode.</translation>
<translation id="7508255263130623398">Det returnerede enheds-id for politikken er tomt eller stemmer ikke overens med det nuværende enheds-id</translation>
<translation id="7508870219247277067">Avocadogrøn</translation>
@@ -1724,6 +1774,7 @@ Yderligere oplysninger:
<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="755279583747225797">Prøveperioden er aktiv</translation>
<translation id="7552846755917812628">Prøv de følgende tips:</translation>
<translation id="7554475479213504905">Genindlæs, og vis alligevel</translation>
<translation id="7554791636758816595">Ny fane</translation>
@@ -1742,7 +1793,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" /> – tryk på Tab-tasten efterfulgt af Enter for at se og administrere dine adgangskoder i Chrome-indstillingerne</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="7616645509853975347">Din administrator har aktiveret Chrome Enterprise Connectors i din browser. Disse connectorer har adgang til nogle af dine data.</translation>
<translation id="7619838219691048931">Sidste ark</translation>
<translation id="762844065391966283">Ét ad gangen</translation>
@@ -1807,13 +1857,12 @@ Yderligere oplysninger:
<translation id="782886543891417279">Det Wi-Fi-netværk, du bruger (<ph name="WIFI_NAME" />), kan kræve, at du går til netværkets loginside.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ingen}=1{1 app (<ph name="EXAMPLE_APP_1" />)}=2{2 apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# app (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}other{# apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Du er dog ikke usynlig. Inkognitotilstand skjuler ikke din browserhistorik over for din arbejdsgiver, din internetudbyder eller de websites, du besøger.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Ã…bne filer med tilknyttede filtyper.</translation>
<translation id="7862185352068345852">Vil du forlade websitet?</translation>
<translation id="7865448901209910068">Bedste hastighed</translation>
<translation id="7874263914261512992">Du har lige angivet din adgangskode på et vildledende website. Chrome anbefaler, at du straks tjekker dine gemte adgangskoder til <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> og andre websites, hvor du bruger denne adgangskode.</translation>
<translation id="7878562273885520351">Din adgangskode kan være kompromitteret</translation>
+<translation id="7880146494886811634">Gem adresse</translation>
<translation id="7882421473871500483">Brun</translation>
<translation id="7887683347370398519">Kontrollér, om din kontrolkode er korrekt, og prøv igen.</translation>
<translation id="7887885240995164102">Ã…bn integreret billede</translation>
@@ -1821,6 +1870,7 @@ Yderligere oplysninger:
<translation id="7894280532028510793">Hvis stavningen er korrekt, kan du <ph name="BEGIN_LINK" />prøve at køre Netværksdiagnosticering<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">ukendt</translation>
+<translation id="793209273132572360">Vil du opdater adressen?</translation>
<translation id="7932579305932748336">Bestrygning</translation>
<translation id="79338296614623784">Angiv et gyldigt telefonnummer</translation>
<translation id="7934052535022478634">Betalingen er gennemført</translation>
@@ -1891,6 +1941,7 @@ Yderligere oplysninger:
<translation id="8175796834047840627">Chrome tilbyder at gemme dine kort på din Google-konto, fordi du er logget ind. Du kan ændre dette i indstillingerne.</translation>
<translation id="8176440868214972690">Administratoren af denne enhed har sendt nogle oplysninger til følgende websites, f.eks. indstillinger eller politikker.</translation>
<translation id="8184538546369750125">Brug global standard (tillad)</translation>
+<translation id="8193086767630290324">Handlinger, der foretages i forbindelse med brug af data, rapporteres som fortrolige</translation>
<translation id="8194797478851900357">&amp;Fortryd flytning</translation>
<translation id="8201077131113104583">Ugyldig webadresse til opdatering for udvidelse med id'et "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Ordreoversigt</translation>
@@ -1913,6 +1964,7 @@ Yderligere oplysninger:
<translation id="8249296373107784235">Annuller</translation>
<translation id="8249320324621329438">Sidste hentet:</translation>
<translation id="8253091569723639551">Faktureringsadresse skal angives</translation>
+<translation id="8257387598443225809">Denne app er udviklet til mobilenheder</translation>
<translation id="825929999321470778">Se alle gemte adgangskoder</translation>
<translation id="8261506727792406068">Slet</translation>
<translation id="8262952874573525464">Kanthæftning nederst</translation>
@@ -2037,7 +2089,6 @@ Yderligere oplysninger:
<translation id="8719528812645237045">Flere huller øverst</translation>
<translation id="8725066075913043281">Forsøg igen</translation>
<translation id="8726549941689275341">Sidestørrelse:</translation>
-<translation id="8728672262656704056">Du er nu i inkognito</translation>
<translation id="8730621377337864115">Udfør</translation>
<translation id="8731544501227493793">Knappen Administrer adgangskoder – tryk på Enter for at se og administrere dine adgangskoder i Chrome-indstillingerne</translation>
<translation id="8734529307927223492">Din <ph name="DEVICE_TYPE" /> administreres af <ph name="MANAGER" /></translation>
@@ -2114,6 +2165,7 @@ Yderligere oplysninger:
<translation id="9020542370529661692">Denne side er oversat til <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ugyldigt)</translation>
+<translation id="9030265603405983977">Monokrom</translation>
<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>
@@ -2137,6 +2189,7 @@ Yderligere oplysninger:
<translation id="91108059142052966">Administratorpolitikken deaktiverer skærmdeling med <ph name="APPLICATION_TITLE" />, når fortroligt indhold er synligt</translation>
<translation id="9114524666733003316">Bekræfter kort...</translation>
<translation id="9114581008513152754">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="9117930699067497412">Frisk</translation>
<translation id="9119042192571987207">Uploadet</translation>
<translation id="9128016270925453879">Politikkerne er indlæst</translation>
<translation id="9128870381267983090">Opret forbindelse til netværk</translation>
@@ -2155,6 +2208,7 @@ Yderligere oplysninger:
<translation id="9170848237812810038">&amp;Fortryd</translation>
<translation id="9171296965991013597">Vil du lukke appen?</translation>
<translation id="9173282814238175921">Enkelt dokument/nyt ark</translation>
+<translation id="9173995187295789444">Søger efter Bluetooth-enheder...</translation>
<translation id="917450738466192189">Serverens certifikat er ugyldigt.</translation>
<translation id="9174917557437862841">Knap til faneskift. Tryk på Enter for at skifte til denne fane</translation>
<translation id="9179703756951298733">Administrer dine betalings- og kortoplysninger i Chrome-indstillingerne</translation>
diff --git a/chromium/components/strings/components_strings_de.xtb b/chromium/components/strings/components_strings_de.xtb
index 63f814d1630..3d313256b5e 100644
--- a/chromium/components/strings/components_strings_de.xtb
+++ b/chromium/components/strings/components_strings_de.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Bei Aktivierung speichert Chrome eine Kopie Ihrer Karte auf diesem Gerät, damit Formulare schneller ausgefüllt werden können.</translation>
<translation id="1110994991967754504">Berechtigung für <ph name="PERMISSION_NAME" /> auswählen</translation>
<translation id="1113869188872983271">&amp;Neu anordnen rückgängig machen</translation>
+<translation id="1123753900084781868">Die Funktion „Automatische Untertitel“ ist derzeit nicht verfügbar</translation>
<translation id="1125573121925420732">Wenn die Sicherheitsfunktionen von Websites aktualisiert werden, können Warnungen häufiger auftreten. Dies sollte sich bald verbessern.</translation>
<translation id="112840717907525620">Richtlinien-Cache einwandfrei</translation>
<translation id="1130564665089811311">Schaltfläche "Seite übersetzen" – drücken Sie die Eingabetaste, um diese Seite mit Google Übersetzer übersetzen zu lassen</translation>
@@ -74,6 +75,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="1240347957665416060">Gerätename</translation>
<translation id="124116460088058876">Weitere Sprachen</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Fett</translation>
<translation id="1250759482327835220">Damit Zahlungen zukünftig schneller abgewickelt werden können, speichern Sie Ihre Kreditkartendaten, Ihren Namen und Ihre Rechnungsadresse in Ihrem Google-Konto.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (synchronisiert)</translation>
<translation id="1256368399071562588">&lt;p&gt;Wenn Sie eine bestimmte Website nicht aufrufen können, versuchen Sie zuerst, das Problem folgendermaßen zu beheben:&lt;/p&gt;
@@ -156,6 +158,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="1476595624592550506">Passwort ändern</translation>
<translation id="1484290072879560759">Versandadresse auswählen</translation>
<translation id="1492194039220927094">Richtlinien per Push-Benachrichtigung:</translation>
+<translation id="1495677929897281669">Zurück zum Tab</translation>
<translation id="1501859676467574491">Zeigen Sie Karten von Ihrem Google-Konto</translation>
<translation id="1507202001669085618">&lt;p&gt;Diese Fehlermeldung wird angezeigt, wenn Sie ein WLAN-Portal verwenden, bei dem eine Anmeldung erforderlich ist, bevor Sie online gehen können.&lt;/p&gt;
&lt;p&gt;Klicken Sie auf der Seite, die Sie öffnen möchten, auf &lt;strong&gt;Verbinden&lt;/strong&gt;, um den Fehler zu beheben.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="1532118530259321453">Auf dieser Seite wird Folgendes angezeigt</translation>
<translation id="153384715582417236">Das ist im Moment alles</translation>
<translation id="1536390784834419204">Seite übersetzen</translation>
+<translation id="1539840569003678498">Bericht gesendet:</translation>
<translation id="154408704832528245">Lieferadresse auswählen</translation>
<translation id="1549470594296187301">Für diese Funktion muss JavaScript aktiviert sein.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="1682696192498422849">Kurze Seite zuerst</translation>
<translation id="168693727862418163">Die Richtlinienwertprüfung des Schemas ist fehlgeschlagen. Der Richtlinienwert wird ignoriert.</translation>
<translation id="168841957122794586">Das Serverzertifikat weist einen schwachen kryptografischen Schlüssel auf.</translation>
+<translation id="1696290444144917273">Details der virtuellen Karte anzeigen</translation>
<translation id="1697532407822776718">Fertig!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat gilt vermutlich erst ab morgen. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.}other{Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat gilt vermutlich erst in # Tagen. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.}}</translation>
<translation id="1710259589646384581">Betriebssystem</translation>
+<translation id="1711234383449478798">Ignoriert, weil <ph name="POLICY_NAME" /> nicht auf <ph name="VALUE" /> festgelegt ist.</translation>
<translation id="1712552549805331520"><ph name="URL" /> möchte Daten dauerhaft auf Ihrem lokalen Computer speichern</translation>
<translation id="1713628304598226412">Fach 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Ablage 3</translation>
<translation id="1718029547804390981">Das Dokument kann aufgrund seiner Größe nicht mit Anmerkungen versehen werden</translation>
<translation id="1721424275792716183">* Pflichtfeld</translation>
+<translation id="1727613060316725209">Zertifikat ist gültig</translation>
<translation id="1727741090716970331">Gültige Kartennummer hinzufügen</translation>
<translation id="1728677426644403582">Dies ist die Quelle einer Webseite</translation>
<translation id="173080396488393970">Dieser Kartentyp wird nicht unterstützt</translation>
@@ -242,7 +249,6 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Versuchen Sie, die Windows-Netzwerkdiagnose auszuführen.<ph name="END_LINK" /></translation>
<translation id="1772163372082567643">Der Server <ph name="ORIGIN" />, zu dem Sie gehen, verlangt in einer Header-Datei, dass auf alle an ihn gerichteten Anfragen eine Ursprungsrichtlinie angewendet wird. Die Header-Datei ist allerdings fehlerhaft. Daher kann der Browser Ihre Anforderung für <ph name="SITE" /> nicht ausführen. Ursprungsrichtlinien können von Websitebetreibern verwendet werden, um die Sicherheit und andere Eigenschaften einer Website zu konfigurieren.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Synchronisierungs-Passphrase aktualisieren</translation>
<translation id="1787142507584202372">Hier werden Ihre offenen Tabs angezeigt</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, es sind mehrere Aktionen verfügbar, drücken Sie die Tabulatortaste, um sie durchzugehen</translation>
@@ -275,6 +281,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="1919345977826869612">Werbung</translation>
<translation id="1919367280705858090">Hilfe bei bestimmten Fehlermeldungen</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Keine}=1{1 Website}other{# Websites}}</translation>
+<translation id="1924727005275031552">Neu</translation>
<translation id="1945968466830820669">Sie könnten den Zugriff auf das Konto Ihres Unternehmens verlieren oder zum Opfer von Identitätsdiebstahl werden. Chromium empfiehlt Ihnen, Ihr Passwort jetzt zu ändern.</translation>
<translation id="1947454675006758438">Heftklammer oben rechts</translation>
<translation id="1958218078413065209">Ihr Highscore ist <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="2042213636306070719">Fach 7</translation>
<translation id="204357726431741734">Anmelden, um die in Ihrem Google-Konto gespeicherten Passwörter zu verwenden</translation>
<translation id="2053111141626950936">Seiten auf <ph name="LANGUAGE" /> werden nicht übersetzt.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Wenn dieses Steuerelement aktiviert und aktiv ist, bestimmt Chrome, welcher großen Personengruppe oder „Kohorte“ Ihre aktuellen Browseraktivitäten am ähnlichsten sind. Werbetreibende können Werbung für die einzelnen Gruppen auswählen und Ihre Browseraktivitäten werden sicher auf Ihrem Gerät gespeichert. Ihre Gruppe wird täglich aktualisiert.}=1{Wenn dieses Steuerelement aktiviert und aktiv ist, bestimmt Chrome, welcher großen Personengruppe oder „Kohorte“ Ihre aktuellen Browseraktivitäten am ähnlichsten sind. Werbetreibende können Werbung für die einzelnen Gruppen auswählen und Ihre Browseraktivitäten werden sicher auf Ihrem Gerät gespeichert. Ihre Gruppe wird täglich aktualisiert.}other{Wenn dieses Steuerelement aktiviert und aktiv ist, bestimmt Chrome, welcher großen Personengruppe oder „Kohorte“ Ihre aktuellen Browseraktivitäten am ähnlichsten sind. Werbetreibende können Werbung für die einzelnen Gruppen auswählen und Ihre Browseraktivitäten werden sicher auf Ihrem Gerät gespeichert. Ihre Gruppe wird alle {NUM_DAYS} Tage aktualisiert.}}</translation>
<translation id="2053553514270667976">Postleitzahl</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 Vorschlag}other{# Vorschläge}}</translation>
<translation id="2071692954027939183">Benachrichtigungen wurden automatisch blockiert, da Sie sie normalerweise nicht zulassen</translation>
<translation id="2079545284768500474">Rückgängig machen</translation>
<translation id="20817612488360358">Die System-Proxy-Einstellungen sind zur Verwendung angegeben, gleichzeitig wurde aber auch eine explizite Proxy-Konfiguration festgelegt.</translation>
<translation id="2082238445998314030">Ergebnis <ph name="RESULT_NUMBER" /> von <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Speichern…</translation>
<translation id="2088086323192747268">Schaltfläche zum Verwalten der Synchronisierung – drücken Sie die Eingabetaste, um in den Chrome-Einstellungen zu verwalten, welche Informationen synchronisiert werden</translation>
<translation id="2091887806945687916">Ton</translation>
<translation id="2094505752054353250">Domains stimmen nicht überein.</translation>
@@ -375,6 +384,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="2317259163369394535">Für <ph name="DOMAIN" /> sind ein Nutzername und ein Passwort erforderlich.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, läuft am <ph name="EXPIRATION_DATE_ABBR" /> ab</translation>
<translation id="2337852623177822836">Einstellung wird von Ihrem Administrator gesteuert</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> möchte eine Kopplung durchführen</translation>
<translation id="2344028582131185878">Auto-Downloads</translation>
<translation id="2346319942568447007">Von Ihnen kopiertes Bild</translation>
<translation id="2354001756790975382">Weitere Lesezeichen</translation>
@@ -382,8 +392,10 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="2355395290879513365">Angreifer können unter Umständen die Bilder sehen, die Sie sich auf dieser Website ansehen, und könnten dann versuchen, Sie durch Ändern der Bilder zu täuschen.</translation>
<translation id="2356070529366658676">Nachfragen</translation>
<translation id="2357481397660644965">Dein Gerät wird von <ph name="DEVICE_MANAGER" /> und dein Konto von <ph name="ACCOUNT_MANAGER" /> verwaltet.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{In weniger als einem Tag}=1{In einem Tag}other{In {NUM_DAYS} Tagen}}</translation>
<translation id="2359629602545592467">Mehrere</translation>
<translation id="2359808026110333948">Weiter</translation>
+<translation id="2359961752320758691">Ihre virtuelle Kartennummer wurde eingefügt.</translation>
<translation id="2367567093518048410">Ebene</translation>
<translation id="2372464001869762664">Nach erfolgter Bestätigung werden die Kartendetails Ihres Google-Kontos an diese Website weitergegeben. Den CVC finden Sie in den Details Ihres Plex-Kontos.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="239429038616798445">Diese Versandart ist nicht verfügbar. Bitte wählen Sie eine andere aus.</translation>
<translation id="2396249848217231973">&amp;Löschen rückgängig machen</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Alt</translation>
<translation id="2413528052993050574">Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat wurde möglicherweise widerrufen. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.</translation>
<translation id="2414886740292270097">Dunkel</translation>
<translation id="2438874542388153331">Vierfache Lochung rechts</translation>
@@ -421,10 +434,10 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="2521385132275182522">Heftklammer unten rechts</translation>
<translation id="2523886232349826891">Nur auf diesem Gerät gespeichert</translation>
<translation id="2524461107774643265">Weitere Informationen hinzufügen</translation>
-<translation id="2526590354069164005">Desktop</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{und 1 weitere}other{und # weitere}}</translation>
<translation id="2536110899380797252">Adresse hinzufügen</translation>
<translation id="2539524384386349900">Erkennen</translation>
+<translation id="2541219929084442027">Seiten, die Sie sich auf Inkognitotabs ansehen, werden nach dem Schließen aller Inkognitotabs nicht in Ihrem Browserverlauf, Cookiespeicher oder Suchverlauf gespeichert. Ihre Lesezeichen und heruntergeladenen Dateien bleiben erhalten.</translation>
<translation id="2544644783021658368">Einzelnes Dokument</translation>
<translation id="254947805923345898">Der Richtlinienwert ist ungültig.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> hat eine ungültige Antwort gesendet.</translation>
@@ -444,6 +457,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="2629325967560697240">Schalten Sie für größtmögliche Sicherheit in Chrome das <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />erweiterte Safe Browsing<ph name="END_ENHANCED_PROTECTION_LINK" /> ein</translation>
<translation id="2634124572758952069">Die Server-IP-Adresse von <ph name="HOST_NAME" /> wurde nicht gefunden.</translation>
<translation id="2639739919103226564">Status: </translation>
+<translation id="264810637653812429">Es wurden keine kompatiblen Geräte gefunden.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" /> – drücken Sie die Tabulatortaste und dann die Eingabetaste, um in den Chrome-Einstellungen Ihren Browserverlauf, Ihre Cookies und andere Daten zu löschen sowie den Cache zu leeren</translation>
<translation id="2650446666397867134">Der Zugriff auf die Datei wurde verweigert.</translation>
@@ -488,6 +502,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<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="2807052079800581569">Y-Position des Bilds</translation>
+<translation id="2820957248982571256">Wird gescannt...</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>
@@ -495,6 +510,8 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="2850739647070081192">Invite (Umschlag)</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="2859806420264540918">Diese Website zeigt aufdringliche oder irreführende Werbung an.</translation>
+<translation id="287596039013813457">Freundlich</translation>
+<translation id="2876489322757410363">Der Inkognitomodus wird deaktiviert, um über eine externe Anwendung zu zahlen. Möchten Sie fortfahren?</translation>
<translation id="2878197950673342043">Posterfaltung</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Fensterpositionierung</translation>
@@ -544,7 +561,6 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="3060227939791841287">C9 (Umschlag)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" /> – drücken Sie die Tabulatortaste und dann die Eingabetaste, um den Sicherheitscheck in den Chrome-Einstellungen auszuführen</translation>
<translation id="3061707000357573562">Patchdienst</translation>
-<translation id="3064966200440839136">Der Inkognitomodus wird beendet, um über eine externe Anwendung zu zahlen. Fortfahren?</translation>
<translation id="306573536155379004">Spiel gestartet.</translation>
<translation id="3080254622891793721">Grafik</translation>
<translation id="3086579638707268289">Ihre Aktivitäten im Web werden überwacht</translation>
@@ -567,7 +583,6 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="315504272643575312">Dein Konto wird von <ph name="MANAGER" /> verwaltet.</translation>
<translation id="3157931365184549694">Wiederherstellen</translation>
<translation id="3162559335345991374">Unter Umständen müssen Sie die Anmeldeseite des verwendeten WLAN-Netzwerken aufrufen.</translation>
-<translation id="3167968892399408617">Seiten, die Sie sich auf Inkognito-Tabs ansehen, werden nach dem Schließen aller Inkognito-Tabs nicht in Ihrem Browserverlauf, Cookiespeicher oder Suchverlauf gespeichert. Ihre Lesezeichen und heruntergeladenen Dateien bleiben erhalten.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Insel</translation>
<translation id="3176929007561373547">Vergewissern Sie sich, dass der Proxyserver funktioniert. Überprüfen Sie die
@@ -593,10 +608,12 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<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="3249845759089040423">Cool</translation>
<translation id="3252266817569339921">Französisch</translation>
<translation id="3266793032086590337">Wert (Konflikt)</translation>
<translation id="3268451620468152448">Geöffnete Tabs</translation>
<translation id="3270847123878663523">&amp;Neu anordnen rückgängig machen</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> möchte eine Verbindung herstellen</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Ihre Organisation, <ph name="ENROLLMENT_DOMAIN" />, hat Informationen wie z. B. Einstellungen oder Richtlinien an folgende Websites gesendet.</translation>
<translation id="3282497668470633863">Angabe für "Name auf der Karte" hinzufügen</translation>
@@ -649,6 +666,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="3428151540071562330">Einer oder mehrere der "DnsOverHttpsTemplates"-Servervorlagen-URIs sind ungültig und werden nicht verwendet.</translation>
<translation id="3431636764301398940">Diese Karte für dieses Gerät speichern</translation>
<translation id="3432601291244612633">Seite schließen</translation>
+<translation id="3435738964857648380">Sicherheit</translation>
<translation id="3435896845095436175">Aktivieren</translation>
<translation id="3438829137925142401">Im Google-Konto gespeicherte Passwörter verwenden</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -690,7 +708,10 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="3584299510153766161">Doppelte Lochung unten</translation>
<translation id="3586931643579894722">Details ausblenden</translation>
<translation id="3587738293690942763">Mitte</translation>
+<translation id="3590643883886679995">Nach dem Deaktivieren des Inkognitomodus werden Anmeldedaten auf diesem Gerät gespeichert.</translation>
+<translation id="359126217934908072">Monat/Jahr:</translation>
<translation id="3592413004129370115">Italian (Umschlag)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Sie können Ihre Gruppe jederzeit zurücksetzen. Es dauert ungefähr einen Tag, einer neuen Gruppe beizutreten.}=1{Sie können Ihre Gruppe jederzeit zurücksetzen. Es dauert ungefähr einen Tag, einer neuen Gruppe beizutreten.}other{Sie können Ihre Gruppe jederzeit zurücksetzen. Es dauert {NUM_DAYS} Tage, einer neuen Gruppe beizutreten.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">App durch Administrator blockiert</translation>
<translation id="3608932978122581043">Einzugsausrichtung</translation>
@@ -699,12 +720,12 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="3615877443314183785">Geben Sie ein gültiges Ablaufdatum ein</translation>
<translation id="36224234498066874">Browserdaten löschen...</translation>
<translation id="362276910939193118">Gesamtverlauf anzeigen</translation>
-<translation id="3625635938337243871">Nach dem Verlassen des Inkognitomodus werden Anmeldedaten auf diesem Gerät gespeichert.</translation>
<translation id="3630155396527302611">Falls das Programm schon in der Liste mit erlaubtem Netzwerkzugriff eingetragen ist, entfernen Sie es aus der Liste und fügen Sie es noch einmal hinzu.</translation>
<translation id="3630699740441428070">Administratoren dieses Geräts haben Ihre Netzwerkverbindung konfiguriert. Dadurch erhalten sie möglicherweise Einblick in Ihren Netzwerkverkehr und können sehen, welche Websites Sie besuchen.</translation>
<translation id="3631244953324577188">Biometrisches Verfahren</translation>
<translation id="3633738897356909127">Schaltfläche "Chrome aktualisieren" – drücken Sie die Eingabetaste, um Chrome über die Chrome-Einstellungen zu aktualisieren</translation>
<translation id="3634530185120165534">Fach 5</translation>
+<translation id="3637662659967048211">In Google-Konto speichern</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Anwendung:</translation>
<translation id="3650584904733503804">Überprüfung erfolgreich</translation>
@@ -745,6 +766,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="3781428340399460090">Dunkelrosa</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth-Geräte</translation>
+<translation id="3787675388804467730">Nummer der virtuellen Karte</translation>
<translation id="3787705759683870569">Ablaufdatum: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Größe 16</translation>
<translation id="3789841737615482174">Installieren</translation>
@@ -764,6 +786,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="3841184659773414994">Datei-Handler</translation>
<translation id="385051799172605136">Zurück</translation>
<translation id="3858027520442213535">Datum und Uhrzeit aktualisieren</translation>
+<translation id="3881478300875776315">Weniger Zeilen anzeigen</translation>
<translation id="3884278016824448484">In Konflikt stehende Gerätekennung</translation>
<translation id="3885155851504623709">Gemeinde</translation>
<translation id="388632593194507180">Ãœberwachung erkannt</translation>
@@ -789,6 +812,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="397105322502079400">Wird berechnet...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ist gesperrt</translation>
<translation id="3973357910713125165">Schaltfläche zum Ausführen des Chrome-Sicherheitschecks – drücken Sie die Eingabetaste, um den Sicherheitscheck in den Chrome-Einstellungen auszuführen</translation>
+<translation id="3986705137476756801">Automatische Untertitel vorerst deaktivieren</translation>
<translation id="3987405730340719549">Chrome hat festgestellt, dass diese Website eventuell gefälscht oder betrügerisch ist.
Wenn dies Ihrer Meinung nach fälschlicherweise angezeigt wird, gehen Sie bitte auf: https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -880,13 +904,14 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="4275830172053184480">Gerät neu starten</translation>
<translation id="4277028893293644418">Passwort zurücksetzen</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="4287885627794386150">Testversion möglich, aber nicht aktiv</translation>
<translation id="4297502707443874121">Miniaturansicht für Seite <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Maximieren</translation>
<translation id="4300675098767811073">Mehrfache Lochung rechts</translation>
<translation id="4302514097724775343">Tippen Sie auf den Dino, um die Wiedergabe zu starten</translation>
<translation id="4302965934281694568">Chou3 (Umschlag)</translation>
<translation id="4305666528087210886">Zugriff auf die Datei nicht möglich</translation>
-<translation id="4305817255990598646">Wechseln</translation>
+<translation id="4306529830550717874">Adresse speichern?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blockieren (Standard)</translation>
<translation id="4314815835985389558">Synchronisierung verwalten</translation>
@@ -913,6 +938,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="4377125064752653719">Sie haben versucht, auf <ph name="DOMAIN" /> zuzugreifen, das vom Server übermittelte Zertifikat wurde jedoch vom entsprechenden Aussteller widerrufen. Das bedeutet, dass die vom Server übermittelten Sicherheitsinformationen nicht vertrauenswürdig sind. Möglicherweise kommunizieren Sie mit einem Hacker.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Automatische Untertitel</translation>
<translation id="4406896451731180161">Suchergebnisse</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Sie haben Ihr Passwort gerade auf einer verdächtigen Seite eingegeben. Chrome empfiehlt, Ihr Passwort auf <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> und allen anderen Websites, auf denen Sie es verwendet haben, zu ändern.</translation>
@@ -925,7 +951,6 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="4435702339979719576">Postkarte)</translation>
<translation id="443673843213245140">Die Proxy-Nutzung ist deaktiviert, es ist jedoch eine explizite Proxy-Konfiguration festgelegt.</translation>
<translation id="4464826014807964867">Websites mit Informationen Ihrer Organisation</translation>
-<translation id="4466881336512663640">Änderungen im Formular gehen verloren. Möchten Sie den Vorgang wirklich fortsetzen?</translation>
<translation id="4476953670630786061">Dieses Formular ist nicht sicher. Die Funktion „Automatisches Ausfüllen“ wurde deaktiviert.</translation>
<translation id="4477350412780666475">Nächster Titel</translation>
<translation id="4482953324121162758">Diese Website wird nicht übersetzt.</translation>
@@ -959,6 +984,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<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="4606870351894164739">Wirkungsvoll</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Cashback zugeordnet</translation>
<translation id="4636930964841734540">Info</translation>
@@ -978,6 +1004,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="4691835149146451662">Architecture-A (Umschlag)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Seite</translation>
+<translation id="4702656508969495934">Automatische Untertitel sind sichtbar, Fensterwechsel zum Fokussieren verwenden</translation>
<translation id="4708268264240856090">Die Verbindung wurde unterbrochen</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows-Netzwerkdiagnose ausführen<ph name="END_LINK" /></translation>
@@ -991,6 +1018,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="4738601419177586157">Suchvorschlag: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Passwörter verwalten…</translation>
<translation id="4744603770635761495">Programmdateipfad</translation>
+<translation id="4749011317274908093">Sie befinden sich jetzt im Inkognitomodus</translation>
<translation id="4750917950439032686">Ihre Daten wie Passwörter oder Kreditkartennummern sind geschützt, wenn Sie sie an diese Website senden.</translation>
<translation id="4756388243121344051">&amp;Verlauf</translation>
<translation id="4758311279753947758">Kontaktdaten hinzufügen</translation>
@@ -1020,6 +1048,8 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="4813512666221746211">Netzwerkfehler</translation>
<translation id="4816492930507672669">An Seite anpassen</translation>
<translation id="4819347708020428563">Anmerkungen in der Standardansicht bearbeiten?</translation>
+<translation id="4825507807291741242">Beeindruckend</translation>
+<translation id="4838327282952368871">Träumerisch</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">Anzeigen</translation>
<translation id="485316830061041779">Deutsch</translation>
@@ -1156,6 +1186,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="5314967030527622926">Falzmaschine</translation>
<translation id="5316812925700871227">Gegen den Uhrzeigersinn drehen</translation>
<translation id="5317780077021120954">Speichern</translation>
+<translation id="5321288445143113935">Maximiert</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> von <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Kontaktdaten auswählen</translation>
<translation id="5327248766486351172">Name</translation>
@@ -1163,11 +1194,13 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="5332219387342487447">Versandart</translation>
<translation id="5333022057423422993">Chrome hat das Passwort, das Sie gerade verwendet haben, in einer Datenpanne gefunden. Wir empfehlen Ihnen, Ihre gespeicherten Passwörter zu prüfen, um Ihre Konten besser zu schützen.</translation>
<translation id="5334013548165032829">Detaillierte Systemprotokolle</translation>
+<translation id="5334145288572353250">Adresse speichern?</translation>
<translation id="5340250774223869109">Die App ist blockiert</translation>
<translation id="534295439873310000">NFC-Geräte</translation>
<translation id="5344579389779391559">Auf dieser Seite wird möglicherweise versucht, Ihnen etwas in Rechnung zu stellen</translation>
<translation id="5355557959165512791">Sie können <ph name="SITE" /> zurzeit nicht aufrufen, da das Zertifikat widerrufen wurde. Netzwerkfehler und Angriffe sind in der Regel nur vorübergehend, sodass die Seite wahrscheinlich später wieder funktioniert.</translation>
<translation id="536296301121032821">Fehler beim Speichern der Richtlinieneinstellungen</translation>
+<translation id="5363309033720083897">Serielle Ports sind von Ihrem Administrator zugelassen</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="5386426401304769735">Die Zertifikatskette für diese Website enthält ein Zertifikat mit SHA-1-Signatur.</translation>
@@ -1176,6 +1209,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="5398772614898833570">Werbung blockiert</translation>
<translation id="5400836586163650660">Grau</translation>
<translation id="540969355065856584">Dieser Server konnte nicht beweisen, dass er <ph name="DOMAIN" /> ist. Sein Sicherheitszertifikat ist zurzeit ungültig. Mögliche Gründe sind eine fehlerhafte Konfiguration oder ein Angreifer, der Ihre Verbindung abfängt.</translation>
+<translation id="541143247543991491">Cloud (für das ganze System)</translation>
<translation id="541416427766103491">Stapelfach 4</translation>
<translation id="5421136146218899937">Browserdaten löschen...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> möchte Ihnen Benachrichtigungen senden</translation>
@@ -1189,6 +1223,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="5455374756549232013">Zeitstempel der Richtlinie ist fehlerhaft.</translation>
<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="5463625433003343978">Geräte werden gesucht…</translation>
<translation id="5469868506864199649">Italienisch</translation>
<translation id="5470861586879999274">&amp;Bearbeiten wiederholen</translation>
<translation id="5478437291406423475">B6/C4 (Umschlag)</translation>
@@ -1238,7 +1273,6 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="5624120631404540903">Passwörter verwalten</translation>
<translation id="5629630648637658800">Fehler beim Laden der Richtlinieneinstellungen</translation>
<translation id="5631439013527180824">Ungültiges Management-Token für das Gerät</translation>
-<translation id="5632627355679805402">Ihre Daten sind seit dem <ph name="TIME" /> mit Ihrem <ph name="BEGIN_LINK" />Google-Passwort<ph name="END_LINK" /> verschlüsselt. Geben Sie dieses ein, um die Synchronisierung zu starten.</translation>
<translation id="5633066919399395251">Zurzeit auf <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> befindliche Hacker könnten versuchen, gefährliche Programme auf Ihrem Computer zu installieren, um Daten wie Fotos, Passwörter, Nachrichten und Kreditkartendaten zu stehlen oder zu löschen. <ph name="BEGIN_LEARN_MORE_LINK" />Weitere Informationen<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Betrügerische Inhalte blockiert.</translation>
<translation id="5644090287519800334">Seite 1 – X-Verschiebung des Bilds</translation>
@@ -1277,12 +1311,12 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="5785756445106461925">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 Layout der Seite verändern.</translation>
<translation id="5786044859038896871">Möchten Sie Ihre Kreditkarteninformationen eingeben?</translation>
<translation id="578633867165174378">Chrome hat das Passwort, das Sie gerade verwendet haben, in einer Datenpanne gefunden. Wie empfehlen Ihnen, dieses Passwort jetzt zu ändern.</translation>
-<translation id="5798290721819630480">Änderungen verwerfen?</translation>
<translation id="5803412860119678065">Möchten Sie die Daten Ihrer <ph name="CARD_DETAIL" /> eingeben?</translation>
<translation id="5804241973901381774">Berechtigungen</translation>
<translation id="5804427196348435412">NFC-Geräte verwenden</translation>
<translation id="5810442152076338065">Ihre Verbindung zu <ph name="DOMAIN" /> ist mit einer veralteten Codier-Suite verschlüsselt.</translation>
<translation id="5813119285467412249">&amp;Hinzufügen wiederholen</translation>
+<translation id="5817918615728894473">Koppeln</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Diese Karte wird beim Bezahlen zwar belastet, doch die echte Kreditkartennummer wird nicht an diese Website weitergegeben. Für zusätzliche Sicherheit wird ein temporärer CVC generiert.}other{Die ausgewählte Karte wird beim Bezahlen zwar belastet, doch die echte Kreditkartennummer wird nicht an diese Website weitergegeben. Für zusätzliche Sicherheit wird ein temporärer CVC generiert.}}</translation>
<translation id="5826507051599432481">Allgemeiner Name (CN)</translation>
<translation id="5838278095973806738">Sie sollten keine vertraulichen Informationen wie Passwörter oder Kreditkartennummern auf dieser Website eingeben, da sie von Angreifern gestohlen werden könnten.</translation>
@@ -1290,6 +1324,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="5855253129151731373">Der Hostname dieser Website ähnelt dem von <ph name="LOOKALIKE_DOMAIN" />. Angreifer kopieren manchmal Websites und nehmen kleine, unauffällige Änderungen an der URL vor.
Wenn dies Ihrer Meinung nach fälschlicherweise angezeigt wird, gehen Sie bitte auf: https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Aus</translation>
<translation id="5862579898803147654">Stapelfach 8</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>
@@ -1306,6 +1341,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="5913377024445952699">Bildschirmaufnahme pausiert</translation>
<translation id="59174027418879706">Aktiviert</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 wird verwendet}other{# werden verwendet}}</translation>
<translation id="5921185718311485855">An</translation>
<translation id="5921639886840618607">Karte im Google-Konto speichern?</translation>
<translation id="5922853866070715753">Fast fertig</translation>
@@ -1325,6 +1361,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="5989320800837274978">Weder feste Proxyserver noch eine PAC-Skript-URL sind festgelegt.</translation>
<translation id="5992691462791905444">Technische Z-Faltung</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> Ergebnisse für "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Klassisch</translation>
<translation id="6008122969617370890">N-zu-1-Reihenfolge</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Passwörter prüfen</translation>
@@ -1346,6 +1383,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="6045164183059402045">Vorlage für Ausschießen</translation>
<translation id="6047233362582046994">Wenn Sie die Sicherheitsrisiken kennen, können Sie <ph name="BEGIN_LINK" />diese Website aufrufen<ph name="END_LINK" />, bevor die schädlichen Apps entfernt wurden.</translation>
<translation id="6047927260846328439">Mit diesen Inhalten wird möglicherweise versucht, Sie zu täuschen und so zur Installation von Software oder der Offenlegung personenbezogener Daten zu bringen. <ph name="BEGIN_LINK" />Trotzdem anzeigen<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">|<ph name="ACCELERATOR" />| gedrückt halten, um den Vollbildmodus zu beenden</translation>
<translation id="6049488691372270142">Ausgabe der Seiten</translation>
<translation id="6051221802930200923">Sie können <ph name="SITE" /> zurzeit nicht aufrufen, weil die Website das Zertifikats-Pinning nutzt. Netzwerkfehler und Angriffe sind in der Regel nur vorübergehend, sodass die Seite wahrscheinlich später wieder funktioniert.</translation>
<translation id="6051898664905071243">Seitenzahl:</translation>
@@ -1362,6 +1400,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<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>
<translation id="6116338172782435947">Texte und Bilder aus der Zwischenablage abrufen</translation>
<translation id="6120179357481664955">Soll Ihre UPI-ID gespeichert werden?</translation>
+<translation id="6123290840358279103">Virtuelle Karte ansehen</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Überprüfen Sie alle Kabel und starten Sie alle verwendeten Router, Modems und
anderen Netzwerkgeräte neu.</translation>
@@ -1398,6 +1437,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="6289939620939689042">Seitenfarbe</translation>
<translation id="6290238015253830360">Hier werden Ihre vorgeschlagenen Artikel angezeigt</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google Assistant für Chrome wird beendet</translation>
<translation id="6305205051461490394"><ph name="URL" /> ist nicht erreichbar.</translation>
<translation id="6312113039770857350">Webseite nicht verfügbar</translation>
@@ -1423,6 +1463,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="6390200185239044127">Halbierte Z-Faltung</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Die Administratorrichtlinie blockiert das Einfügen von Inhalten aus <ph name="ORIGIN_NAME" /> an dieser Stelle</translation>
+<translation id="6398765197997659313">Vollbildmodus beenden</translation>
<translation id="6401136357288658127">Diese Richtlinie ist veraltet. Verwenden Sie stattdessen die Richtlinie "<ph name="NEW_POLICY" />".</translation>
<translation id="6404511346730675251">Lesezeichen bearbeiten</translation>
<translation id="6406765186087300643">C0 (Umschlag)</translation>
@@ -1435,7 +1476,6 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="6428450836711225518">Telefonnummer bestätigen</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="6440503408713884761">Ignoriert</translation>
<translation id="6443406338865242315">Welche Erweiterungen und Plug-ins Sie installiert haben</translation>
<translation id="6446163441502663861">Kahu (Umschlag)</translation>
@@ -1478,6 +1518,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="6624427990725312378">Kontaktdaten</translation>
<translation id="6626291197371920147">Gültige Kartennummer hinzufügen</translation>
<translation id="6628463337424475685"><ph name="ENGINE" />-Suche</translation>
+<translation id="6630043285902923878">USB-Geräte werden gesucht…</translation>
<translation id="6630809736994426279">Zurzeit auf <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> befindliche Hacker könnten versuchen, gefährliche Programme auf Ihrem Mac zu installieren, um Daten wie Fotos, Passwörter, Nachrichten und Kreditkartendaten zu stehlen oder zu löschen. <ph name="BEGIN_LEARN_MORE_LINK" />Weitere Informationen<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Löschen</translation>
@@ -1493,6 +1534,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="6671697161687535275">Vorschlag für das Formular aus Chromium entfernen?</translation>
<translation id="6685834062052613830">Abmelden und Einrichtung abschließen</translation>
<translation id="6687335167692595844">Gewünschte Schriftgröße</translation>
+<translation id="6688743156324860098">Aktualisieren…</translation>
<translation id="6689249931105087298">Relativ mit Schwarzpunktkompensation</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="6698381487523150993">Erstellt:</translation>
@@ -1508,6 +1550,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="6744009308914054259">Während Sie auf eine Verbindung warten, können Sie "Downloads" aufrufen und Offline-Artikel lesen.</translation>
<translation id="6753269504797312559">Wert der Richtlinie</translation>
<translation id="6757797048963528358">Ihr Gerät ist im Ruhemodus.</translation>
+<translation id="6767985426384634228">Adresse aktualisieren?</translation>
<translation id="6768213884286397650">Hagaki (Postkarte)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violett</translation>
@@ -1530,6 +1573,7 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Diese Seite wird in Chrome vereinfacht dargestellt, damit sie leichter zu lesen ist. Die Originalseite hat Chrome über eine unsichere Verbindung abgerufen.</translation>
<translation id="6891596781022320156">Richtlinienebene wird nicht unterstützt.</translation>
+<translation id="6895143722905299846">Virtuelle Nummer:</translation>
<translation id="6895330447102777224">Ihre Karte wurde bestätigt</translation>
<translation id="6897140037006041989">User-Agent</translation>
<translation id="6898699227549475383">Organisation (O)</translation>
@@ -1565,10 +1609,10 @@ Sie werden sonst gemäß Ihren Datenschutzeinstellungen blockiert. Wenn Cookies
<translation id="7004583254764674281">Windows Hello verwenden und Karten schneller bestätigen</translation>
<translation id="7006930604109697472">Trotzdem senden</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Einstellungen zum Anpassen der Größe</translation>
<translation id="7014741021609395734">Zoomstufe</translation>
<translation id="7016992613359344582">Diese Belastungen können einmalig oder wiederkehrend sein und sind vielleicht nicht offensichtlich.</translation>
<translation id="7029809446516969842">Passwörter</translation>
+<translation id="7030436163253143341">Zertifikat ist ungültig</translation>
<translation id="7031646650991750659">Welche Google Play-Apps Sie installiert haben</translation>
<translation id="7050187094878475250">Sie haben versucht, <ph name="DOMAIN" /> zu erreichen. Der Server hat jedoch ein Zertifikat präsentiert, dessen Gültigkeitsdauer zu lang ist, um vertrauenswürdig zu sein.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Diese Karte kann momentan nicht gespeichert werden}other{Diese Karten können momentan nicht gespeichert werden}}</translation>
@@ -1638,12 +1682,14 @@ Weitere Details:
<translation id="7300012071106347854">Kobaltblau</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Hoch</translation>
+<translation id="7305756307268530424">Verlangsamen</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Hilfe bei der Verbindungsherstellung</translation>
<translation id="7323804146520582233">Abschnitt "<ph name="SECTION" />" ausblenden</translation>
<translation id="733354035281974745">Durch Sitzung mit einem lokalen Gerätekonto überschrieben</translation>
<translation id="7333654844024768166">Sie haben Ihr Passwort gerade auf einer verdächtigen Seite eingegeben. Chromium empfiehlt, Ihr Passwort auf <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> und allen anderen Websites, auf denen Sie es verwendet haben, zu ändern.</translation>
<translation id="7334320624316649418">&amp;Neu anordnen wiederholen</translation>
+<translation id="7337248890521463931">Mehr Zeilen anzeigen</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>
@@ -1651,6 +1697,7 @@ Weitere Details:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Befehlszeile</translation>
<translation id="7359588939039777303">Werbung blockiert.</translation>
+<translation id="7363096869660964304">Sie sind jedoch nicht unsichtbar. Der Inkognitomodus verhindert nicht, dass Informationen zu Ihren Webaktivitäten von Ihrem Arbeitgeber, Ihrem Internetanbieter oder den von Ihnen besuchten Websites erfasst werden.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" /> – drücken Sie die Tabulatortaste und dann die Eingabetaste, um Adressen in den Chrome-Einstellungen hinzuzufügen und zu verwalten</translation>
<translation id="7365849542400970216">Informationen zu Ihrer Gerätenutzung abrufen?</translation>
<translation id="7372973238305370288">Suchergebnis</translation>
@@ -1661,7 +1708,9 @@ Weitere Details:
<translation id="7378594059915113390">Mediensteuerelemente</translation>
<translation id="7378627244592794276">Nein</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Nicht zutreffend</translation>
<translation id="7390545607259442187">Karte bestätigen</translation>
+<translation id="7392089738299859607">Adresse aktualisieren</translation>
<translation id="7399802613464275309">Sicherheitscheck</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Ihr <ph name="DEVICE_NAME" /> wird verwaltet</translation>
@@ -1676,6 +1725,7 @@ Weitere Details:
&lt;li&gt;In der &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome-Hilfe&lt;/a&gt; finden Sie eine Anleitung dazu, wie Sie die Software von Ihrem Computer entfernen.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Hübsch</translation>
<translation id="7416351320495623771">Passwörter verwalten…</translation>
<translation id="7419106976560586862">Profilpfad</translation>
<translation id="7437289804838430631">Kontaktdaten hinzufügen</translation>
@@ -1691,7 +1741,7 @@ Weitere Details:
<translation id="7481312909269577407">Vorwärts</translation>
<translation id="7485870689360869515">Keine Daten gefunden</translation>
<translation id="7495528107193238112">Dieser Inhalt ist blockiert. Setzen Sie sich mit dem Websiteinhaber in Verbindung, um das Problem zu beheben.</translation>
-<translation id="7498234416455752244">Weiter bearbeiten</translation>
+<translation id="7498193950643227031">Wenn die Größe von Apps geändert wird, kann das zu unerwartetem Verhalten führen. Sie können jetzt in den <ph name="SETTINGS" /> das Ändern der App-Größe einschränken.</translation>
<translation id="7503664977220660814">Sie haben Ihr Passwort gerade auf einer verdächtigen Seite eingegeben. Chromium empfiehlt, Ihre gespeicherten Passwörter für <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> und alle anderen Websites, auf denen Sie dieses Passwort verwenden, zu prüfen.</translation>
<translation id="7508255263130623398">Zurückgegebene Geräte-ID der Richtlinie ist leer oder entspricht nicht der aktuellen Geräte-ID</translation>
<translation id="7508870219247277067">Avocadogrün</translation>
@@ -1711,6 +1761,7 @@ Weitere Details:
<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">Ihre Nutzernamen auf dem Gerät und in Chrome</translation>
+<translation id="755279583747225797">Testversion ist aktiv</translation>
<translation id="7552846755917812628">Probieren Sie folgende Tipps aus:</translation>
<translation id="7554475479213504905">Aktualisieren und trotzdem anzeigen</translation>
<translation id="7554791636758816595">Neuer Tab</translation>
@@ -1729,7 +1780,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" /> – drücken Sie die Tabulatortaste und dann die Eingabetaste, um Passwörter in den Chrome-Einstellungen abzurufen und zu verwalten</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="7616645509853975347">Ihr Administrator hat Chrome Enterprise Connectors für Ihren Browser aktiviert. Diese Connectors haben Zugriff auf einen Teil Ihrer Daten.</translation>
<translation id="7619838219691048931">Endblatt</translation>
<translation id="762844065391966283">Einzeln</translation>
@@ -1794,13 +1844,12 @@ Weitere Details:
<translation id="782886543891417279">Unter Umständen müssen Sie die Anmeldeseite des verwendeten WLAN-Netzwerken (<ph name="WIFI_NAME" />) aufrufen.</translation>
<translation id="7836231406687464395">Postfix (Umschlag)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Keine}=1{1 App (<ph name="EXAMPLE_APP_1" />)}=2{2 Apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# Apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Sie sind jedoch nicht unsichtbar. Der Inkognitomodus verhindert nicht, dass Informationen zu Ihren Webaktivitäten von Ihrem Arbeitgeber, Ihrem Internetanbieter oder den von Ihnen besuchten Websites erfasst werden.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Dateien mit Dateitypzuordnungen öffnen.</translation>
<translation id="7862185352068345852">Website verlassen?</translation>
<translation id="7865448901209910068">Beste Geschwindigkeit</translation>
<translation id="7874263914261512992">Sie haben Ihr Passwort gerade auf einer verdächtigen Seite eingegeben. Chrome empfiehlt, Ihre gespeicherten Passwörter für <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> und alle anderen Websites, auf denen Sie dieses Passwort verwenden, zu prüfen.</translation>
<translation id="7878562273885520351">Ihr Passwort könnte gefährdet sein</translation>
+<translation id="7880146494886811634">Adresse speichern</translation>
<translation id="7882421473871500483">Braun</translation>
<translation id="7887683347370398519">Prüfen Sie Ihren CVC und versuchen Sie es dann erneut.</translation>
<translation id="7887885240995164102">Bild im Bild aktivieren</translation>
@@ -1808,6 +1857,7 @@ Weitere Details:
<translation id="7894280532028510793">Wenn die URL keinen Tippfehler enthält, <ph name="BEGIN_LINK" />können Sie die Netzwerkdiagnose durchführen<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Umschlag)</translation>
<translation id="7931318309563332511">Unbekannt</translation>
+<translation id="793209273132572360">Adresse aktualisieren?</translation>
<translation id="7932579305932748336">Im­prä­g­nie­ren</translation>
<translation id="79338296614623784">Geben Sie eine gültige Telefonnummer ein</translation>
<translation id="7934052535022478634">Zahlung abgeschlossen</translation>
@@ -1878,6 +1928,7 @@ Weitere Details:
<translation id="8175796834047840627">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.</translation>
<translation id="8176440868214972690">Der Administrator dieses Geräts hat Informationen wie z. B. Einstellungen oder Richtlinien an folgende Websites gesendet.</translation>
<translation id="8184538546369750125">Globalen Standard verwenden (Zulassen)</translation>
+<translation id="8193086767630290324">Maßnahmen, die für als vertraulich gekennzeichnete Daten ergriffen werden</translation>
<translation id="8194797478851900357">&amp;Verschieben rückgängig machen</translation>
<translation id="8201077131113104583">Ungültige Update-URL für Erweiterung mit der ID "<ph name="EXTENSION_ID" />"</translation>
<translation id="8202097416529803614">Zusammenfassung der Bestellung</translation>
@@ -1900,6 +1951,7 @@ Weitere Details:
<translation id="8249296373107784235">Abbrechen</translation>
<translation id="8249320324621329438">Letzter Abruf: </translation>
<translation id="8253091569723639551">Rechnungsadresse ist erforderlich</translation>
+<translation id="8257387598443225809">Diese App wurde für Mobilgeräte entwickelt</translation>
<translation id="825929999321470778">Alle gespeicherten Passwörter anzeigen</translation>
<translation id="8261506727792406068">Löschen</translation>
<translation id="8262952874573525464">Mehrere Heftklammern unten</translation>
@@ -2024,7 +2076,6 @@ Weitere Details:
<translation id="8719528812645237045">Mehrfache Lochung oben</translation>
<translation id="8725066075913043281">Erneut versuchen</translation>
<translation id="8726549941689275341">Seitengröße:</translation>
-<translation id="8728672262656704056">Sie haben den Inkognitomodus aktiviert</translation>
<translation id="8730621377337864115">Fertig</translation>
<translation id="8731544501227493793">Schaltfläche "Passwörter verwalten" – drücken Sie die Eingabetaste, um Passwörter in den Chrome-Einstellungen abzurufen und zu verwalten</translation>
<translation id="8734529307927223492">Dein <ph name="DEVICE_TYPE" /> wird von <ph name="MANAGER" /> verwaltet</translation>
@@ -2101,6 +2152,7 @@ Weitere Details:
<translation id="9020542370529661692">Die Seite wurde übersetzt und liegt nun auf <ph name="TARGET_LANGUAGE" /> vor.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Ungültig)</translation>
+<translation id="9030265603405983977">Schwarz-weiß</translation>
<translation id="9035022520814077154">Sicherheitsfehler</translation>
<translation id="9038649477754266430">Vorhersagefunktion zum schnelleren Laden von Seiten verwenden
</translation>
@@ -2125,6 +2177,7 @@ Weitere Details:
<translation id="91108059142052966">Die Administratorrichtlinie blockiert die Bildschirmfreigabe mit <ph name="APPLICATION_TITLE" />, wenn vertrauliche Inhalte sichtbar sind</translation>
<translation id="9114524666733003316">Karte wird bestätigt…</translation>
<translation id="9114581008513152754">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="9117930699067497412">Frisch</translation>
<translation id="9119042192571987207">Hochgeladen</translation>
<translation id="9128016270925453879">Richtlinien wurden geladen</translation>
<translation id="9128870381267983090">Mit Netzwerk verbinden</translation>
@@ -2143,6 +2196,7 @@ Weitere Details:
<translation id="9170848237812810038">&amp;Rückgängig</translation>
<translation id="9171296965991013597">App verlassen?</translation>
<translation id="9173282814238175921">Einzeldokument/neues Blatt</translation>
+<translation id="9173995187295789444">Nach Bluetooth-Geräten wird gesucht…</translation>
<translation id="917450738466192189">Das Serverzertifikat ist ungültig.</translation>
<translation id="9174917557437862841">Schaltfläche zum Wechseln des Tabs, Eingabetaste drücken, um zu diesem Tab zu wechseln</translation>
<translation id="9179703756951298733">Zahlungsmethoden und Kreditkartendaten in den Chrome-Einstellungen verwalten</translation>
diff --git a/chromium/components/strings/components_strings_el.xtb b/chromium/components/strings/components_strings_el.xtb
index 8d986af5e23..99adedde316 100644
--- a/chromium/components/strings/components_strings_el.xtb
+++ b/chromium/components/strings/components_strings_el.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Εάν επιλεγεί, το Chrome θα αποθηκεÏει ένα αντίγÏαφο της κάÏτας σας σε αυτήν τη συσκευή για ταχÏτεÏη συμπλήÏωση φοÏμών.</translation>
<translation id="1110994991967754504">Επιλέξτε άδεια για <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;ΑναίÏεση αναδιάταξης</translation>
+<translation id="1123753900084781868">Οι Ζωντανοί υπότιτλοι δεν είναι διαθέσιμοι αυτήν τη στιγμή.</translation>
<translation id="1125573121925420732">Οι Ï€Ïοειδοποιήσεις μποÏεί να είναι συνήθεις ενώ οι ιστότοποι ενημεÏώνουν την ασφάλειά τους. Αυτό αναμένεται να βελτιωθεί σÏντομα.</translation>
<translation id="112840717907525620">Η Ï€ÏοσωÏινή μνήμη της πολιτικής είναι εντάξει</translation>
<translation id="1130564665089811311">Κουμπί μετάφÏασης σελίδας, πατήστε Enter για μετάφÏαση της σελίδας με τη ΜετάφÏαση Google.</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Το όνομα της συσκευής σας</translation>
<translation id="124116460088058876">ΠεÏισσότεÏες γλώσσες</translation>
<translation id="1243027604378859286">Συντάκτης:</translation>
+<translation id="1246424317317450637">Έντονη γÏαφή</translation>
<translation id="1250759482327835220">Για πιο γÏήγοÏες πληÏωμές στο μέλλον, αποθηκεÏστε τα στοιχεία της κάÏτας σας, το όνομα και τη διεÏθυνση χÏέωσης στον ΛογαÏιασμό σας Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (συγχÏονισμένο)</translation>
<translation id="1256368399071562588">&lt;p&gt;Αν Ï€Ïοσπαθείτε να επισκεφτείτε έναν ιστότοπο και ο ιστότοπος δεν ανοίγει, δοκιμάστε Ï€Ïώτα να διοÏθώσετε το σφάλμα, ακολουθώντας τα παÏακάτω βήματα αντιμετώπισης Ï€Ïοβλημάτων:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Αλλάξτε τον κωδικό Ï€Ïόσβασης</translation>
<translation id="1484290072879560759">Επιλογή διεÏθυνσης αποστολής</translation>
<translation id="1492194039220927094">ΠÏοώθηση πολιτικών:</translation>
+<translation id="1495677929897281669">ΕπιστÏοφή στην καÏτέλα</translation>
<translation id="1501859676467574491">Εμφάνιση καÏτών από τον ΛογαÏιασμό σας Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Αυτό το σφάλμα παÏουσιάζεται εάν χÏησιμοποιείτε μια Ï€Ïλη Wi-Fi στην οποία Ï€Ïέπει να συνδέεστε, για να μποÏέσετε να πεÏιηγηθείτε στο διαδίκτυο.&lt;/p&gt;
&lt;p&gt;Για να διοÏθώσετε το σφάλμα, κάντε κλικ στο κουμπί &lt;strong&gt;ΣÏνδεση&lt;/strong&gt; στη σελίδα που Ï€Ïοσπαθείτε να ανοίξετε.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Αυτή η σελίδα λέει</translation>
<translation id="153384715582417236">Αυτά Ï€Ïος το παÏόν</translation>
<translation id="1536390784834419204">ΜετάφÏαση σελίδας</translation>
+<translation id="1539840569003678498">Η αναφοÏά στάλθηκε:</translation>
<translation id="154408704832528245">Επιλογή διεÏθυνσης παÏάδοσης</translation>
<translation id="1549470594296187301">Θα Ï€Ïέπει να ενεÏγοποιηθεί η JavaScript για τη χÏήση αυτής της λειτουÏγίας.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">ΠÏώτα η μικÏή πλευÏά</translation>
<translation id="168693727862418163">Αυτή η τιμή πολιτικής δεν επικυÏώθηκε με επιτυχία έναντι του σχήματός της και θα παÏαβλεφθεί.</translation>
<translation id="168841957122794586">Το πιστοποιητικό διακομιστή πεÏιέχει ένα αδÏναμο κÏυπτογÏαφικό κλειδί.</translation>
+<translation id="1696290444144917273">ΠÏοβολή λεπτομεÏειών εικονικής κάÏτας</translation>
<translation id="1697532407822776718">Είστε έτοιμοι!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Αυτός ο διακομιστής δεν μπόÏεσε να αποδείξει ότι είναι το <ph name="DOMAIN" />. Η ημεÏομηνία του Ï€Î¹ÏƒÏ„Î¿Ï€Î¿Î¹Î·Ï„Î¹ÎºÎ¿Ï Î±ÏƒÏ†Î±Î»ÎµÎ¯Î±Ï‚ του υποτίθεται ότι είναι αυÏιανή. Αυτό μποÏεί να οφείλεται σε εσφαλμένη ÏÏθμιση ή σε κάποιον εισβολέα που παÏεμβαίνει στη σÏνδεσή σας.}other{Αυτός ο διακομιστής δεν μπόÏεσε να αποδείξει ότι είναι το <ph name="DOMAIN" />. Η ημεÏομηνία του Ï€Î¹ÏƒÏ„Î¿Ï€Î¿Î¹Î·Ï„Î¹ÎºÎ¿Ï Î±ÏƒÏ†Î±Î»ÎµÎ¯Î±Ï‚ του υποτίθεται ότι είναι από # ημέÏες μετά. Αυτό μποÏεί να οφείλεται σε εσφαλμένη ÏÏθμιση ή σε κάποιον εισβολέα που παÏεμβαίνει στη σÏνδεσή σας.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">ΠαÏαβλέφθηκε επειδή η πολιτική <ph name="POLICY_NAME" /> δεν έχει οÏιστεί σε <ph name="VALUE" />.</translation>
<translation id="1712552549805331520">Ο ιστότοπος <ph name="URL" /> θέλει να αποθηκεÏσει μόνιμα δεδομένα στον τοπικό υπολογιστή σας</translation>
<translation id="1713628304598226412">Δίσκος 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">ΓÏαμματοκιβώτιο 3</translation>
<translation id="1718029547804390981">Το έγγÏαφο είναι πάÏα Ï€Î¿Î»Ï Î¼ÎµÎ³Î¬Î»Î¿ για σχολιασμό.</translation>
<translation id="1721424275792716183">* Το πεδίο είναι υποχÏεωτικό</translation>
+<translation id="1727613060316725209">Το πιστοποιητικό είναι έγκυÏο</translation>
<translation id="1727741090716970331">ΠÏοσθήκη έγκυÏου αÏÎ¹Î¸Î¼Î¿Ï ÎºÎ¬Ïτας</translation>
<translation id="1728677426644403582">Βλέπετε την πηγή μιας ιστοσελίδας</translation>
<translation id="173080396488393970">Αυτός ο Ï„Ïπος κάÏτας δεν υποστηÏίζεται</translation>
@@ -246,7 +253,6 @@
για τον ιστότοπο <ph name="SITE" /> από το Ï€ÏόγÏαμμα πεÏιήγησης. Οι πολιτικές Ï€Ïοέλευσης μποÏοÏν να χÏησιμοποιηθοÏν από
χειÏιστές ιστοτόπων για τη διαμόÏφωση της ασφάλειας και άλλων ιδιοτήτων ενός ιστοτόπου.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">ΕνημεÏώστε την κωδική φÏάση Ï€Ïόσβασης συγχÏονισμοÏ.</translation>
<translation id="1787142507584202372">Οι ανοιχτές καÏτέλες σας εμφανίζονται εδώ</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />. ΥπάÏχουν πολλές διαθέσιμες ενέÏγειες. Πατήστε το πλήκτÏο Tab για να μετακινηθείτε ανάμεσά τους.</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">Διαφημίσεις</translation>
<translation id="1919367280705858090">Λήψη βοήθειας για συγκεκÏιμένο μήνυμα σφάλματος</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Κανένας}=1{1 ιστότοπος}other{# ιστότοποι}}</translation>
+<translation id="1924727005275031552">Îέο</translation>
<translation id="1945968466830820669">ΥπάÏχει κίνδυνος να χάσετε την Ï€Ïόσβαση στον λογαÏιασμό της επιχείÏησής σας ή να σας κλέψουν τη διαδικτυακή σας ταυτότητα. Το Chromium συνιστά να αλλάξετε τον κωδικό Ï€Ïόσβασής σας Ï„ÏŽÏα.</translation>
<translation id="1947454675006758438">ΣυÏÏαφή επάνω δεξιά</translation>
<translation id="1958218078413065209">Η υψηλότεÏη βαθμολογία σας είναι <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">Δίσκος 7</translation>
<translation id="204357726431741734">Συνδεθείτε, για να χÏησιμοποιήσετε κωδικοÏÏ‚ Ï€Ïόσβασης που είναι αποθηκευμένοι στον ΛογαÏιασμό σας Google.</translation>
<translation id="2053111141626950936">Οι σελίδες στα <ph name="LANGUAGE" /> δεν θα μεταφÏάζονται.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Όταν αυτό το στοιχείο ελέγχου είναι ενεÏγοποιημένο και η κατάσταση είναι ενεÏγή, το Chrome καθοÏίζει τη μεγάλη ομάδα ατόμων ή "κοόÏτη" με την οποία μοιάζει πεÏισσότεÏο η πιο Ï€Ïόσφατη δÏαστηÏιότητα πεÏιήγησής σας. Οι διαφημιζόμενοι μποÏοÏν να επιλέξουν διαφημίσεις για την ομάδα και η δÏαστηÏιότητα πεÏιήγησής σας διατηÏείται ιδιωτική στη συσκευή σας. Η ομάδα σας ενημεÏώνεται καθημεÏινά.}=1{Όταν αυτό το στοιχείο ελέγχου είναι ενεÏγοποιημένο και η κατάσταση είναι ενεÏγή, το Chrome καθοÏίζει τη μεγάλη ομάδα ατόμων ή "κοόÏτη" με την οποία μοιάζει πεÏισσότεÏο η πιο Ï€Ïόσφατη δÏαστηÏιότητα πεÏιήγησής σας. Οι διαφημιζόμενοι μποÏοÏν να επιλέξουν διαφημίσεις για την ομάδα και η δÏαστηÏιότητα πεÏιήγησής σας διατηÏείται ιδιωτική στη συσκευή σας. Η ομάδα σας ενημεÏώνεται καθημεÏινά.}other{Όταν αυτό το στοιχείο ελέγχου είναι ενεÏγοποιημένο και η κατάσταση είναι ενεÏγή, το Chrome καθοÏίζει τη μεγάλη ομάδα ατόμων ή "κοόÏτη" με την οποία μοιάζει πεÏισσότεÏο η πιο Ï€Ïόσφατη δÏαστηÏιότητα πεÏιήγησής σας. Οι διαφημιζόμενοι μποÏοÏν να επιλέξουν διαφημίσεις για την ομάδα και η δÏαστηÏιότητα πεÏιήγησής σας διατηÏείται ιδιωτική στη συσκευή σας. Η ομάδα σας ενημεÏώνεται κάθε {NUM_DAYS} ημέÏες.}}</translation>
<translation id="2053553514270667976">ΤαχυδÏομικός κώδικας</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 Ï€Ïόταση}other{# Ï€Ïοτάσεις}}</translation>
<translation id="2071692954027939183">Οι ειδοποιήσεις αποκλείστηκαν αυτόματα επειδή συνήθως δεν τις επιτÏέπετε</translation>
<translation id="2079545284768500474">ΑναίÏεση</translation>
<translation id="20817612488360358">Οι Ïυθμίσεις διακομιστή μεσολάβησης του συστήματος έχουν οÏιστεί για να χÏησιμοποιηθοÏν, αλλά καθοÏίζεται επίσης μια Ïητή διαμόÏφωση του διακομιστή μεσολάβησης.</translation>
<translation id="2082238445998314030">Αποτέλεσμα <ph name="RESULT_NUMBER" /> από <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Αποθήκευση…</translation>
<translation id="2088086323192747268">Κουμπί διαχείÏισης συγχÏονισμοÏ, πατήστε Enter για να διαχειÏιστείτε τις πληÏοφοÏίες που συγχÏονίζετε από τις Ïυθμίσεις του Chrome</translation>
<translation id="2091887806945687916">Ήχος</translation>
<translation id="2094505752054353250">Αναντιστοιχία τομέα</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535">Ο τομέας <ph name="DOMAIN" /> απαιτεί ένα όνομα χÏήστη και έναν κωδικό Ï€Ïόσβασης.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, λήγει στις <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Η ÏÏθμιση ελέγχεται από τον διαχειÏιστή σας</translation>
+<translation id="2340263603246777781">Ο ιστότοπος <ph name="ORIGIN" /> επιθυμεί σÏζευξη</translation>
<translation id="2344028582131185878">Αυτόματες λήψεις</translation>
<translation id="2346319942568447007">Εικόνα που αντιγÏάψατε</translation>
<translation id="2354001756790975382">Άλλοι σελιδοδείκτες</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">Οι εισβολείς ενδέχεται να έχουν τη δυνατότητα να δουν τις εικόνες που Ï€Ïοβάλετε σε αυτόν τον ιστότοπο και να σας εξαπατήσουν Ï„Ïοποποιώντας τες.</translation>
<translation id="2356070529366658676">Îα γίνεται εÏώτηση</translation>
<translation id="2357481397660644965">Η διαχείÏιση της συσκευής σας γίνεται από τον τομέα <ph name="DEVICE_MANAGER" /> και του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ±Ï‚ από τον τομέα <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Σε λιγότεÏο από μία ημέÏα}=1{Σε μία ημέÏα}other{Σε {NUM_DAYS} ημέÏες}}</translation>
<translation id="2359629602545592467">Πολλά</translation>
<translation id="2359808026110333948">Συνέχεια</translation>
+<translation id="2359961752320758691">ΕφαÏμόστηκε ο αÏιθμός εικονικής κάÏτας σας.</translation>
<translation id="2367567093518048410">Επίπεδο</translation>
<translation id="2372464001869762664">Μετά την επιβεβαίωση, τα στοιχεία της κάÏτας από τον ΛογαÏιασμό Google θα κοινοποιηθοÏν σε αυτόν τον ιστότοπο. Î’Ïείτε το CVC στις πληÏοφοÏίες λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">Αυτός ο Ï„Ïόπος αποστολής δεν είναι διαθέσιμος. Δοκιμάστε έναν άλλο Ï„Ïόπο.</translation>
<translation id="2396249848217231973">&amp;ΑναίÏεση διαγÏαφής</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Παλαιά</translation>
<translation id="2413528052993050574">Ο διακομιστής δεν κατάφεÏε να αποδείξει ότι είναι <ph name="DOMAIN" />. Το πιστοποιητικό ασφαλείας του μποÏεί να έχει ανακληθεί. Αυτό μποÏεί να οφείλεται σε λανθασμένη ÏÏθμιση ή σε κάποιον Ï„Ïίτο που επιτίθεται στη σÏνδεσή σας.</translation>
<translation id="2414886740292270097">ΣκοÏÏο</translation>
<translation id="2438874542388153331">ΤετÏαπλό Ï„ÏÏπημα στα δεξιά</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">ΣυÏÏαφή κάτω δεξιά</translation>
<translation id="2523886232349826891">ΑποθηκεÏτηκε μόνο σε αυτήν τη συσκευή</translation>
<translation id="2524461107774643265">ΠÏοσθήκη πεÏισσότεÏων πληÏοφοÏιών</translation>
-<translation id="2526590354069164005">Επιφάνεια εÏγασίας</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{και 1 ακόμα}other{και # ακόμα}}</translation>
<translation id="2536110899380797252">ΠÏοσθήκη διεÏθυνσης</translation>
<translation id="2539524384386349900">ΑναγνώÏιση</translation>
+<translation id="2541219929084442027">Οι σελίδες που Ï€Ïοβάλλετε στις καÏτέλες ανώνυμης πεÏιήγησης δεν διατηÏοÏνται στο ιστοÏικό του Ï€ÏογÏάμματος πεÏιήγησης, στα cookie ή στο ιστοÏικό αναζήτησης, Î±Ï†Î¿Ï ÎºÎ»ÎµÎ¯ÏƒÎµÏ„Îµ όλες τις καÏτέλες της ανώνυμης πεÏιήγησης. Τα αÏχεία που κατεβάζετε ή οι σελιδοδείκτες που δημιουÏγείτε θα διατηÏοÏνται.</translation>
<translation id="2544644783021658368">Ένα έγγÏαφο</translation>
<translation id="254947805923345898">Η τιμή πολιτικής δεν είναι έγκυÏη.</translation>
<translation id="255002559098805027">Ο κεντÏικός υπολογιστής <ph name="HOST_NAME" /> έστειλε μια μη έγκυÏη απόκÏιση.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Για να λάβετε το υψηλότεÏο επίπεδο ασφάλειας του Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ενεÏγοποιήστε τη βελτιωμένη Ï€Ïοστασία<ph name="END_ENHANCED_PROTECTION_LINK" />.</translation>
<translation id="2634124572758952069">Δεν ήταν δυνατή η εÏÏεση της διεÏθυνσης IP διακομιστή του κεντÏÎ¹ÎºÎ¿Ï Ï…Ï€Î¿Î»Î¿Î³Î¹ÏƒÏ„Î® <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Κατάσταση:</translation>
+<translation id="264810637653812429">Δεν βÏέθηκαν συμβατές συσκευές.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, πατήστε Tab και έπειτα Enter για εκκαθάÏιση του ιστοÏÎ¹ÎºÎ¿Ï Ï€ÎµÏιήγησης, των cookie, της κÏυφής μνήμης κ.α. στις Ïυθμίσεις του Chrome.</translation>
<translation id="2650446666397867134">Η Ï€Ïόσβαση στο αÏχείο αποÏÏίφθηκε</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">Επανεκκίνηση</translation>
<translation id="2803306138276472711">ΠÏόσφατα η Ασφαλής πεÏιήγηση Google <ph name="BEGIN_LINK" />εντόπισε κακόβουλο λογισμικό<ph name="END_LINK" /> στον ιστότοπο <ph name="SITE" />. Οι ιστότοποι που είναι ασφαλείς υπό φυσιολογικές συνθήκες μεÏικές φοÏές Ï€Ïοσβάλλονται από κακόβουλα λογισμικά.</translation>
<translation id="2807052079800581569">Θέση εικόνας στον άξονα Y</translation>
+<translation id="2820957248982571256">ΣάÏωση…</translation>
<translation id="2824775600643448204">ΓÏαμμή διευθÏνσεων και αναζήτησης</translation>
<translation id="2826760142808435982">Η κÏυπτογÏάφηση και ο έλεγχος ταυτότητας της σÏνδεσης γίνονται με <ph name="CIPHER" /> και χÏησιμοποιεί το <ph name="KX" /> ως μηχανισμό ανταλλαγής κλειδιών.</translation>
<translation id="2835170189407361413">ΔιαγÏαφή φόÏμας</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Invite (Φάκελος)</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="2859806420264540918">Αυτός ο ιστότοπος εμφανίζει παÏεμβατικές ή παÏαπλανητικές διαφημίσεις.</translation>
+<translation id="287596039013813457">Φιλικό</translation>
+<translation id="2876489322757410363">Έξοδος από την κατάσταση ανώνυμης πεÏιήγησης για πληÏωμή μέσω εξωτεÏικής εφαÏμογής. Θέλετε να συνεχίστε;</translation>
<translation id="2878197950673342043">Δίπλωση αφίσας</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Τοποθέτηση παÏαθÏÏου</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (Φάκελος)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, πατήστε Tab και έπειτα Enter για εκτέλεση του Ελέγχου ασφαλείας στις Ïυθμίσεις του Chrome</translation>
<translation id="3061707000357573562">ΥπηÏεσία ενημέÏωσης κώδικα</translation>
-<translation id="3064966200440839136">ΑποχώÏηση από την κατάσταση ανώνυμης πεÏιήγησης για πληÏωμή μέσω εξωτεÏικής εφαÏμογής. Συνέχεια;</translation>
<translation id="306573536155379004">Το παιχνίδι ξεκίνησε.</translation>
<translation id="3080254622891793721">ΓÏαφικά</translation>
<translation id="3086579638707268289">Η δÏαστηÏιότητά σας στον ιστό παÏακολουθείται</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">Η διαχείÏιση του λογαÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÎ±Ï‚ γίνεται από τον τομέα <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">ΕπαναφοÏά</translation>
<translation id="3162559335345991374">Το Wi-Fi που χÏησιμοποιείτε ενδέχεται να σας ζητήσει να επισκεφτείτε τη σελίδα σÏνδεσής του.</translation>
-<translation id="3167968892399408617">Οι σελίδες που Ï€Ïοβάλλετε στις καÏτέλες της ανώνυμης πεÏιήγησης δεν διατηÏοÏνται στο ιστοÏικό του Ï€ÏογÏάμματος πεÏιήγησης, στα cookie ή στο ιστοÏικό αναζήτησης, Î±Ï†Î¿Ï ÎºÎ»ÎµÎ¯ÏƒÎµÏ„Îµ όλες τις καÏτέλες της ανώνυμης πεÏιήγησης. Τα αÏχεία που κατεβάζετε ή οι σελιδοδείκτες που δημιουÏγείτε θα διατηÏοÏνται.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Îήσος</translation>
<translation id="3176929007561373547">Ελέγξτε τις Ïυθμίσεις του διακομιστή μεσολάβησης ή επικοινωνήστε με το διαχειÏιστή του δικτÏου σας, για
@@ -599,11 +614,13 @@
<translation id="3229041911291329567">ΠληÏοφοÏίες έκδοσης σχετικά με τη συσκευή και το Ï€ÏόγÏαμμα πεÏιήγησης</translation>
<translation id="323107829343500871">Εισαγάγετε τον κωδικό CVC για την πιστωτική κάÏτα <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Îα εντοπίζεται πάντα σημαντικό πεÏιεχόμενο σε αυτόν τον ιστότοπο</translation>
+<translation id="3249845759089040423">Μοδάτο</translation>
<translation id="3252266817569339921">Γαλλικά
</translation>
<translation id="3266793032086590337">Τιμή (διένεξη)</translation>
<translation id="3268451620468152448">Ανοικτές καÏτέλες</translation>
<translation id="3270847123878663523">&amp;ΑναίÏεση αναδιάταξης</translation>
+<translation id="3271648667212143903">Ο ιστότοπος <ph name="ORIGIN" /> επιθυμεί σÏνδεση</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Ο οÏγανισμός σας, <ph name="ENROLLMENT_DOMAIN" />, έστειλε οÏισμένες πληÏοφοÏίες στους παÏακάτω ιστοτόπους, όπως Ïυθμίσεις ή πολιτικές.</translation>
<translation id="3282497668470633863">ΠÏοσθήκη ονόματος στην κάÏτα</translation>
@@ -656,6 +673,7 @@
<translation id="3428151540071562330">Ένα ή πεÏισσότεÏα από τα URI Ï€ÏοτÏπου διακομιστή DnsOverHttpsTemplates δεν είναι έγκυÏα και δεν θα χÏησιμοποιηθοÏν.</translation>
<translation id="3431636764301398940">Αποθήκευση αυτής της κάÏτας στη συγκεκÏιμένη συσκευή</translation>
<translation id="3432601291244612633">Κλείσιμο σελίδας</translation>
+<translation id="3435738964857648380">Ασφάλεια</translation>
<translation id="3435896845095436175">ΕνεÏγοποίηση</translation>
<translation id="3438829137925142401">ΧÏησιμοποιήστε τους κωδικοÏÏ‚ Ï€Ïόσβασης που έχουν αποθηκευτεί στον ΛογαÏιασμό σας Google.</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -698,7 +716,10 @@
<translation id="3584299510153766161">Διπλό Ï„ÏÏπημα στο κάτω μέÏος</translation>
<translation id="3586931643579894722">ΑπόκÏυψη λεπτομεÏειών</translation>
<translation id="3587738293690942763">Μέσο</translation>
+<translation id="3590643883886679995">Τα δεδομένα σÏνδεσης θα αποθηκευτοÏν σε αυτήν τη συσκευή Î±Ï†Î¿Ï ÎµÎ¾Î­Î»Î¸ÎµÏ„Îµ από την κατάσταση ανώνυμης πεÏιήγησης.</translation>
+<translation id="359126217934908072">Μήνας/Έτος:</translation>
<translation id="3592413004129370115">Italian (Φάκελος)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{ΜποÏείτε να επαναφέÏετε την ομάδα σας ανά πάσα στιγμή. ΧÏειάζεται πεÏίπου μία μέÏα για να εγγÏαφείτε σε μια νέα ομάδα.}=1{ΜποÏείτε να επαναφέÏετε την ομάδα σας ανά πάσα στιγμή. ΧÏειάζεται πεÏίπου μία μέÏα για να εγγÏαφείτε σε μια νέα ομάδα.}other{ΜποÏείτε να επαναφέÏετε την ομάδα σας ανά πάσα στιγμή. ΧÏειάζονται {NUM_DAYS} ημέÏες για να εγγÏαφείτε σε μια νέα ομάδα.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Η εφαÏμογή έχει αποκλειστεί από τον διαχειÏιστή σας.</translation>
<translation id="3608932978122581043">ΠÏοσανατολισμός Ïοής</translation>
@@ -707,13 +728,13 @@
<translation id="3615877443314183785">Εισαγάγετε μια έγκυÏη ημεÏομηνία λήξης</translation>
<translation id="36224234498066874">ΔιαγÏαφή δεδομένων πεÏιήγησης…</translation>
<translation id="362276910939193118">Εμφάνιση πλήÏους ιστοÏικοÏ</translation>
-<translation id="3625635938337243871">Τα δεδομένα σÏνδεσης θα αποθηκεÏονται σε αυτήν τη συσκευή μετά την έξοδο από την κατάσταση ανώνυμης πεÏιήγησης.</translation>
<translation id="3630155396527302611">Εάν έχει ήδη καταχωÏιστεί ως Ï€ÏόγÏαμμα στο οποίο επιτÏέπεται η Ï€Ïόσβαση στο δίκτυο, δοκιμάστε
να το καταÏγήσετε από τη λίστα και να το Ï€Ïοσθέσετε ξανά.</translation>
<translation id="3630699740441428070">Οι διαχειÏιστές αυτής της συσκευής έχουν διαμοÏφώσει τη σÏνδεση δικτÏου σας, η οποία ενδέχεται να τους επιτÏέπει να βλέπουν την επισκεψιμότητα δικτÏου σας, συμπεÏιλαμβανομένων των ιστοτόπων που επισκέπτεστε.</translation>
<translation id="3631244953324577188">ΒιομετÏικά</translation>
<translation id="3633738897356909127">Κουμπί ενημέÏωσης Chrome, πατήστε Enter για να ενημεÏώσετε το Chrome από τις Ïυθμίσεις του Chrome.</translation>
<translation id="3634530185120165534">Δίσκος 5</translation>
+<translation id="3637662659967048211">Αποθήκευση στον ΛογαÏιασμό Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">ΕφαÏμογή:</translation>
<translation id="3650584904733503804">Επιτυχής επικÏÏωση</translation>
@@ -754,6 +775,7 @@
<translation id="3781428340399460090">Έντονο Ïοζ</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Συσκευές Bluetooth</translation>
+<translation id="3787675388804467730">ΑÏιθμός εικονικής κάÏτας</translation>
<translation id="3787705759683870569">Λήγει <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Μέγεθος 16</translation>
<translation id="3789841737615482174">Εγκατάσταση</translation>
@@ -773,6 +795,7 @@
<translation id="3841184659773414994">Δείκτες χειÏÎ¹ÏƒÎ¼Î¿Ï Î±Ïχείων</translation>
<translation id="385051799172605136">Πίσω</translation>
<translation id="3858027520442213535">ΕνημέÏωση ημεÏομηνίας και ÏŽÏας</translation>
+<translation id="3881478300875776315">Εμφάνιση λιγότεÏων γÏαμμών</translation>
<translation id="3884278016824448484">ΑναγνωÏιστικό συσκευής που Ï€Ïοκαλεί διένεξη</translation>
<translation id="3885155851504623709">ΕνοÏία</translation>
<translation id="388632593194507180">Εντοπίστηκε παÏακολοÏθηση</translation>
@@ -798,6 +821,7 @@
<translation id="397105322502079400">Υπολογισμός…</translation>
<translation id="3973234410852337861">Ο κεντÏικός υπολογιστής <ph name="HOST_NAME" /> είναι αποκλεισμένος</translation>
<translation id="3973357910713125165">Κουμπί Εκτέλεση Ελέγχου ασφαλείας Chrome, πατήστε Enter για εκτέλεση του Ελέγχου ασφαλείας στις Ïυθμίσεις του Chrome</translation>
+<translation id="3986705137476756801">ΑπενεÏγοποίηση Ζωντανών υπότιτλων Ï€Ïος το παÏόν</translation>
<translation id="3987405730340719549">Το Chrome διαπίστωσε ότι αυτός ο ιστότοπος μποÏεί να είναι ψεÏτικος ή μη νόμιμος.
Εάν πιστεÏετε ότι αυτό το μήνυμα εμφανίζεται κατά λάθος, επισκεφτείτε τη διεÏθυνση https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -895,13 +919,14 @@
<translation id="4275830172053184480">Επανεκκινήστε τη συσκευή σας</translation>
<translation id="4277028893293644418">ΕπαναφοÏά ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Αυτή η κάÏτα αποθηκεÏτηκε στον ΛογαÏιασμό σας Google}other{Αυτές οι κάÏτες αποθηκεÏτηκαν στον ΛογαÏιασμό σας Google}}</translation>
+<translation id="4287885627794386150">ΠληÏοί τις Ï€Ïοϋποθέσεις για δοκιμή αλλά δεν έχει ενεÏγοποιηθεί</translation>
<translation id="4297502707443874121">ΜικÏογÏαφία για τη σελίδα <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Επέκταση</translation>
<translation id="4300675098767811073">Πολλαπλό Ï„ÏÏπημα στα δεξιά</translation>
<translation id="4302514097724775343">Πατήστε τον δεινόσαυÏο για να παίξετε.</translation>
<translation id="4302965934281694568">Chou3 (Φάκελος)</translation>
<translation id="4305666528087210886">Δεν ήταν δυνατή η Ï€Ïόσβαση στο αÏχείο σας</translation>
-<translation id="4305817255990598646">Εναλλαγή</translation>
+<translation id="4306529830550717874">Αποθήκευση διεÏθυνσης;</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Αποκλεισμός (Ï€Ïοεπιλογή)</translation>
<translation id="4314815835985389558">ΔιαχείÏιση συγχÏονισμοÏ</translation>
@@ -928,6 +953,7 @@
<translation id="4377125064752653719">ΠÏοσπαθήσατε να μεταβείτε στον τομέα <ph name="DOMAIN" />, όμως το πιστοποιητικό που παÏουσιάστηκε από το διακομιστή ανακλήθηκε από τον εκδότη του. Αυτό σημαίνει ότι τα διαπιστευτήÏια ασφαλείας που παÏουσιάστηκαν από το διακομιστή δεν Ï€Ïέπει σε καμία πεÏίπτωση να θεωÏηθοÏν αξιόπιστα. Ενδέχεται να επικοινωνείτε με κάποιον εισβολέα.</translation>
<translation id="4378154925671717803">Τηλέφωνο</translation>
<translation id="4390472908992056574">Χείλος</translation>
+<translation id="4406883609789734330">Ζωντανοί υπότιτλοι</translation>
<translation id="4406896451731180161">αποτελέσματα αναζήτησης</translation>
<translation id="4408413947728134509">Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Μόλις καταχωÏίσατε τον κωδικό Ï€Ïόσβασής σας σε έναν παÏαπλανητικό ιστότοπο. Το Chrome συνιστά να μεταβείτε στους ιστοτόπους <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> και <ph name="WEBSITE_3" />, καθώς και σε άλλους ιστοτόπους όπου χÏησιμοποιείτε αυτόν τον κωδικό Ï€Ïόσβασης και να τον αλλάξετε άμεσα.</translation>
@@ -940,7 +966,6 @@
<translation id="4435702339979719576">ΤαχυδÏομική κάÏτα)</translation>
<translation id="443673843213245140">Η χÏήση ενός διακομιστή μεσολάβησης είναι απενεÏγοποιημένη, αλλά έχει καθοÏιστεί μια Ïητή διαμόÏφωση διακομιστή μεσολάβησης.</translation>
<translation id="4464826014807964867">Ιστότοποι με πληÏοφοÏίες από τον οÏγανισμό σας</translation>
-<translation id="4466881336512663640">Οι αλλαγές που Ï€Ïαγματοποιήθηκαν στη φόÏμα θα χαθοÏν. Είστε βέβαιοι ότι θέλετε να συνεχίσετε;</translation>
<translation id="4476953670630786061">Αυτή η φόÏμα δεν είναι ασφαλής. Η αυτόματη συμπλήÏωση έχει απενεÏγοποιηθεί.</translation>
<translation id="4477350412780666475">Επόμενο κομμάτι</translation>
<translation id="4482953324121162758">Αυτός ο ιστότοπος δεν θα μεταφÏαστεί.</translation>
@@ -974,6 +999,7 @@
<translation id="4594403342090139922">&amp;ΑναίÏεση διαγÏαφής</translation>
<translation id="4597348597567598915">Μέγεθος 8</translation>
<translation id="4600854749408232102">C6/C5 (Φάκελος)</translation>
+<translation id="4606870351894164739">Εμφατικό</translation>
<translation id="4628948037717959914">ΦωτογÏαφία</translation>
<translation id="4631649115723685955">Συνδέθηκε επιστÏοφή μετÏητών</translation>
<translation id="4636930964841734540">ΠληÏοφοÏίες</translation>
@@ -993,6 +1019,7 @@
<translation id="4691835149146451662">Architecture-A (Φάκελος)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">ΠλευÏά</translation>
+<translation id="4702656508969495934">Οι Ζωντανοί υπότιτλοι είναι οÏατοί, χÏησιμοποιήστε την εναλλαγή παÏαθÏÏων για εστίαση</translation>
<translation id="4708268264240856090">Η σÏνδεσή σας διακόπηκε</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Îα εκτελέσετε τον Διαγνωστικό έλεγχο δικτÏου των Windows<ph name="END_LINK" /></translation>
@@ -1006,6 +1033,7 @@
<translation id="4738601419177586157">ΠÏόταση αναζήτησης <ph name="TEXT" /></translation>
<translation id="4742407542027196863">ΔιαχείÏιση κωδικών Ï€Ïόσβασης…</translation>
<translation id="4744603770635761495">ΔιαδÏομή εκτελέσιμου</translation>
+<translation id="4749011317274908093">Είστε σε κατάσταση ανώνυμης πεÏιήγησης.</translation>
<translation id="4750917950439032686">Οι πληÏοφοÏίες σας (για παÏάδειγμα, οι κωδικοί Ï€Ïόσβασης ή οι αÏιθμοί πιστωτικών καÏτών) είναι ιδιωτικές κατά την αποστολή σε αυτόν τον ιστότοπο.</translation>
<translation id="4756388243121344051">&amp;ΙστοÏικό</translation>
<translation id="4758311279753947758">ΠÏοσθήκη στοιχείων επικοινωνίας</translation>
@@ -1035,6 +1063,8 @@
<translation id="4813512666221746211">Σφάλμα δικτÏου</translation>
<translation id="4816492930507672669">ΠÏοσαÏμογή στη σελίδα</translation>
<translation id="4819347708020428563">ΕπεξεÏγασία σχολιασμών στην Ï€Ïοεπιλεγμένη Ï€Ïοβολή;</translation>
+<translation id="4825507807291741242">ΙσχυÏÏŒ</translation>
+<translation id="4838327282952368871">ΟνειÏικό</translation>
<translation id="484462545196658690">Αυτόματα</translation>
<translation id="4850886885716139402">ΠÏοβολή</translation>
<translation id="485316830061041779">ΓεÏμανικά
@@ -1172,6 +1202,7 @@
<translation id="5314967030527622926">ΕÏγαλείο δημιουÏγίας φυλλαδίων</translation>
<translation id="5316812925700871227">ΠεÏιστÏοφή Ï€Ïος τα αÏιστεÏά</translation>
<translation id="5317780077021120954">Αποθήκευση</translation>
+<translation id="5321288445143113935">Μεγιστοποιημένη</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> από <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Επιλογή στοιχείων επικοινωνίας</translation>
<translation id="5327248766486351172">Όνομα</translation>
@@ -1179,11 +1210,13 @@
<translation id="5332219387342487447">Μέθοδος αποστολής</translation>
<translation id="5333022057423422993">Το Chrome εντόπισε σε μια παÏαβίαση δεδομένων τον κωδικό Ï€Ïόσβασης που μόλις χÏησιμοποιήσατε. Για να Ï€Ïοστατέψετε τους λογαÏιασμοÏÏ‚ σας, συνιστοÏμε να ελέγξετε τους αποθηκευμένους κωδικοÏÏ‚ Ï€Ïόσβασής σας.</translation>
<translation id="5334013548165032829">ΛεπτομεÏή αÏχεία καταγÏαφής συστήματος</translation>
+<translation id="5334145288572353250">Αποθήκευση διεÏθυνσης;</translation>
<translation id="5340250774223869109">Η εφαÏμογή αποκλείστηκε</translation>
<translation id="534295439873310000">Συσκευές NFC</translation>
<translation id="5344579389779391559">Αυτή η σελίδα μποÏεί να Ï€Ïοσπαθήσει να σας χÏεώσει</translation>
<translation id="5355557959165512791">Δεν μποÏείτε να επισκεφτείτε τον ιστότοπο <ph name="SITE" /> αυτήν τη στιγμή επειδή το πιστοποιητικό έχει ανακληθεί. Τα σφάλματα δικτÏου και οι επιθέσεις είναι συνήθως Ï€ÏοσωÏινά, συνεπώς αυτή η σελίδα πιθανότατα θα λειτουÏγήσει αÏγότεÏα.</translation>
<translation id="536296301121032821">Αποτυχία αποθήκευσης Ïυθμίσεων πολιτικής</translation>
+<translation id="5363309033720083897">ΣειÏιακή θÏÏα που επιτÏέπεται από τον διαχειÏιστή σας</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="5386426401304769735">Η αλυσίδα Ï€Î¹ÏƒÏ„Î¿Ï€Î¿Î¹Î·Ï„Î¹ÎºÎ¿Ï Î³Î¹Î± αυτόν τον ιστότοπο πεÏιέχει ένα πιστοποιητικό το οποίο είναι υπογεγÏαμμένο με χÏήση SHA-1.</translation>
@@ -1192,6 +1225,7 @@
<translation id="5398772614898833570">Αποκλείστηκαν διαφημίσεις</translation>
<translation id="5400836586163650660">ΓκÏι</translation>
<translation id="540969355065856584">Αυτός ο διακομιστής δεν μπόÏεσε να αποδείξει ότι είναι <ph name="DOMAIN" />. Το πιστοποιητικό ασφαλείας του δεν είναι έγκυÏο αυτήν τη στιγμή. Αυτό μποÏεί να οφείλεται σε εσφαλμένη ÏÏθμιση ή σε κάποιον εισβολέα που παÏεμβαίνει στη σÏνδεσή σας.</translation>
+<translation id="541143247543991491">Cloud (σε ολόκληÏο το σÏστημα)</translation>
<translation id="541416427766103491">Μονάδα στοίβαξης 4</translation>
<translation id="5421136146218899937">ΔιαγÏαφή δεδομένων πεÏιήγησης...</translation>
<translation id="5426179911063097041">Η διεÏθυνση <ph name="SITE" /> θέλει να σας στείλει ειδοποιήσεις</translation>
@@ -1206,6 +1240,7 @@
<translation id="5455374756549232013">Εσφαλμένη χÏονική σήμανση πολιτικής</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" /> ακόμη}other{<ph name="CONTACT_PREVIEW" /> και <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ακόμη}}</translation>
+<translation id="5463625433003343978">ΕÏÏεση συσκευών…</translation>
<translation id="5469868506864199649">Ιταλικά</translation>
<translation id="5470861586879999274">&amp;Επανάληψη επεξεÏγασίας</translation>
<translation id="5478437291406423475">B6/C4 (Φάκελος)</translation>
@@ -1255,7 +1290,6 @@
<translation id="5624120631404540903">ΔιαχείÏιση κωδικών Ï€Ïόσβασης</translation>
<translation id="5629630648637658800">Αποτυχία φόÏτωσης Ïυθμίσεων πολιτικής</translation>
<translation id="5631439013527180824">Μη έγκυÏο διακÏιτικό διαχείÏισης συσκευής</translation>
-<translation id="5632627355679805402">Τα δεδομένα σας κÏυπτογÏαφήθηκαν με τον <ph name="BEGIN_LINK" />κωδικό Ï€Ïόσβασης Google<ph name="END_LINK" /> στις <ph name="TIME" />. ΚαταχωÏίστε τον, για να ξεκινήσει ο συγχÏονισμός.</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="5644090287519800334">ΠλευÏά 1 μετατόπιση εικόνας στον άξονα X</translation>
@@ -1294,12 +1328,12 @@
<translation id="5785756445106461925">Επίσης, αυτή η σελίδα πεÏιέχει άλλους πόÏους, οι οποίοι δεν είναι ασφαλείς. Αυτοί οι πόÏοι μποÏοÏν να Ï€ÏοβληθοÏν από άλλους χÏήστες κατά τη μετάβαση και μποÏοÏν να Ï„ÏοποποιηθοÏν από έναν εισβολέα ώστε να αλλάξει η εμφάνιση της σελίδας.</translation>
<translation id="5786044859038896871">Θέλετε να συμπληÏωθοÏν τα στοιχεία της κάÏτας σας;</translation>
<translation id="578633867165174378">Το Chrome εντόπισε σε μια παÏαβίαση δεδομένων τον κωδικό Ï€Ïόσβασης που μόλις χÏησιμοποιήσατε. ΣυνιστοÏμε να αλλάξετε άμεσα αυτόν τον κωδικό Ï€Ïόσβασης.</translation>
-<translation id="5798290721819630480">ΑπόÏÏιψη αλλαγών;</translation>
<translation id="5803412860119678065">Θέλετε να συμπληÏωθοÏν τα στοιχεία της κάÏτας <ph name="CARD_DETAIL" />;</translation>
<translation id="5804241973901381774">Άδειες</translation>
<translation id="5804427196348435412">ΧÏήση συσκευών NFC</translation>
<translation id="5810442152076338065">Η σÏνδεσή σας στο <ph name="DOMAIN" /> κÏυπτογÏαφείται χÏησιμοποιώντας ένα απαÏχαιωμένο Ï€ÏόγÏαμμα κÏυπτογÏάφησης.</translation>
<translation id="5813119285467412249">&amp;Επανάληψη Ï€Ïοσθήκης</translation>
+<translation id="5817918615728894473">ΣÏζευξη</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Η συγκεκÏιμένη κάÏτα θα χÏεώνεται κάθε φοÏά που πληÏώνετε, αλλά ο Ï€Ïαγματικός της αÏιθμός δεν θα κοινοποιείται σε αυτόν τον ιστότοπο. Για επιπλέον ασφάλεια, θα δημιουÏγηθεί ένα Ï€ÏοσωÏινό CVC.}other{Η κάÏτα που επιλέγετε θα χÏεώνεται κάθε φοÏά που πληÏώνετε, αλλά ο Ï€Ïαγματικός της αÏιθμός δεν θα κοινοποιείται σε αυτόν τον ιστότοπο. Για επιπλέον ασφάλεια, θα δημιουÏγηθεί ένα Ï€ÏοσωÏινό CVC.}}</translation>
<translation id="5826507051599432481">Κοινό όνομα (CN)</translation>
<translation id="5838278095973806738">Δεν θα Ï€Ïέπει να εισαγάγετε ευαίσθητες πληÏοφοÏίες σε αυτόν τον ιστότοπο (για παÏάδειγμα, κωδικοÏÏ‚ Ï€Ïόσβασης ή πιστωτικές κάÏτες), επειδή ενδέχεται να υποκλαποÏν από εισβολείς.</translation>
@@ -1307,6 +1341,7 @@
<translation id="5855253129151731373">Το όνομα Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… κεντÏÎ¹ÎºÎ¿Ï Ï…Ï€Î¿Î»Î¿Î³Î¹ÏƒÏ„Î® φαίνεται παÏόμοιο με του ιστοτόπου <ph name="LOOKALIKE_DOMAIN" />. Οι εισβολείς απομιμοÏνται μεÏικές φοÏές ιστοτόπους κάνοντας μικÏές, δυσδιάκÏιτες αλλαγές στο όνομα τομέα.
Εάν πιστεÏετε ότι αυτό το μήνυμα εμφανίζεται κατά λάθος, επισκεφτείτε τη διεÏθυνση https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">ΑπενεÏγοποιημένη</translation>
<translation id="5862579898803147654">Μονάδα στοίβαξης 8</translation>
<translation id="5863847714970149516">Η σελίδα που ακολουθεί μποÏεί να Ï€Ïοσπαθήσει να σας χÏεώσει</translation>
<translation id="5866257070973731571">ΠÏοσθήκη αÏÎ¹Î¸Î¼Î¿Ï Ï„Î·Î»ÎµÏ†ÏŽÎ½Î¿Ï…</translation>
@@ -1323,6 +1358,7 @@
<translation id="5913377024445952699">Η καταγÏαφή οθόνης τέθηκε σε παÏση</translation>
<translation id="59174027418879706">ΕνεÏγοποιημένο</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 σε χÏήση}other{# σε χÏήση}}</translation>
<translation id="5921185718311485855">ΕνεÏγοποιημένο</translation>
<translation id="5921639886840618607">Αποθήκευση κάÏτας στον ΛογαÏιασμό Google;</translation>
<translation id="5922853866070715753">Σχεδόν ολοκληÏώθηκε</translation>
@@ -1342,6 +1378,7 @@
<translation id="5989320800837274978">Δεν Ï€ÏοσδιοÏίζονται οÏτε οι σταθεÏοί διακομιστές μεσολάβησης οÏτε μια διεÏθυνση URL σεναÏίου .pac.</translation>
<translation id="5992691462791905444">Δίπλωση Ζ τεχνικών εγγÏάφων</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> αποτελέσματα για την αναζήτηση "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Κλασικό</translation>
<translation id="6008122969617370890">ΣειÏά N Ï€Ïος 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Ελέγξτε τους κωδικοÏÏ‚ Ï€Ïόσβασής σας</translation>
@@ -1363,6 +1400,7 @@
<translation id="6045164183059402045">ΠÏότυπο ένθεσης</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="6049004884579590341">Πατήστε παÏατεταμένα το πλήκτÏο |<ph name="ACCELERATOR" />|, για να εξέλθετε από την πλήÏη οθόνη</translation>
<translation id="6049488691372270142">ΠαÏάδοση σελίδας</translation>
<translation id="6051221802930200923">Δεν μποÏείτε να επισκεφτείτε το <ph name="SITE" /> αυτήν τη στιγμή επειδή ο ιστότοπος χÏησιμοποιεί certificate pinning (κλείδωμα πιστοποιητικών). Τα σφάλματα δικτÏου και οι επιθέσεις είναι συνήθως Ï€ÏοσωÏινά, συνεπώς αυτή η σελίδα πιθανότατα θα λειτουÏγήσει αÏγότεÏα.</translation>
<translation id="6051898664905071243">Πλήθος σελίδων:</translation>
@@ -1379,6 +1417,7 @@
<translation id="610911394827799129">Ο ΛογαÏιασμός Google ενδέχεται να διαθέτει άλλες μοÏφές ιστοÏÎ¹ÎºÎ¿Ï Ï€ÎµÏιήγησης στη διεÏθυνση <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">Δει κείμενο και εικόνες που αντιγÏάψατε στο Ï€ÏόχειÏο</translation>
<translation id="6120179357481664955">Θυμάστε το αναγνωÏιστικό UPI;</translation>
+<translation id="6123290840358279103">ΠÏοβολή εικονικής κάÏτας</translation>
<translation id="6124432979022149706">ΕφαÏμογές σÏνδεσης Chrome για επιχειÏήσεις</translation>
<translation id="6146055958333702838">Ελέγξτε τυχόν καλώδια και επανεκκινήστε δÏομολογητές, μόντεμ ή άλλες συσκευές
του δικτÏου που ενδεχομένως χÏησιμοποιείτε.</translation>
@@ -1415,6 +1454,7 @@
<translation id="6289939620939689042">ΧÏώμα σελίδας</translation>
<translation id="6290238015253830360">Τα Ï€Ïοτεινόμενα άÏθÏα σας εμφανίζονται εδώ</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Διακοπή Î’Î¿Î·Î¸Î¿Ï Google στο Chrome</translation>
<translation id="6305205051461490394">Δεν είναι δυνατή η Ï€Ïόσβαση στο <ph name="URL" />.</translation>
<translation id="6312113039770857350">Η ιστοσελίδα δεν είναι διαθέσιμη</translation>
@@ -1440,6 +1480,7 @@
<translation id="6390200185239044127">Δίπλωμα Z στη μέση</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Η επικόλληση από το <ph name="ORIGIN_NAME" /> σε αυτήν την τοποθεσία έχει αποκλειστεί από την πολιτική του διαχειÏιστή.</translation>
+<translation id="6398765197997659313">Έξοδος από πλήÏη οθόνη</translation>
<translation id="6401136357288658127">Αυτή η πολιτική έχει καταÏγηθεί. Θα Ï€Ïέπει να χÏησιμοποιήσετε εναλλακτικά την πολιτική <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">ΕπεξεÏγασία σελιδοδείκτη</translation>
<translation id="6406765186087300643">C0 (Φάκελος)</translation>
@@ -1452,7 +1493,6 @@
<translation id="6428450836711225518">Επαλήθευση του αÏÎ¹Î¸Î¼Î¿Ï Ï„Î·Î»ÎµÏ†ÏŽÎ½Î¿Ï… σας</translation>
<translation id="6433490469411711332">ΕπεξεÏγασία στοιχείων επαφής</translation>
<translation id="6433595998831338502">Ο κεντÏικός υπολογιστής <ph name="HOST_NAME" /> απέÏÏιψε τη σÏνδεση.</translation>
-<translation id="6434309073475700221">ΑπόÏÏιψη</translation>
<translation id="6440503408713884761">Αγνοείται</translation>
<translation id="6443406338865242315">Ποιες επεκτάσεις και Ï€Ïοσθήκες έχετε εγκαταστήσει</translation>
<translation id="6446163441502663861">Kahu (Φάκελος)</translation>
@@ -1495,6 +1535,7 @@
<translation id="6624427990725312378">Στοιχεία επικοινωνίας</translation>
<translation id="6626291197371920147">ΠÏοσθήκη έγκυÏου αÏÎ¹Î¸Î¼Î¿Ï ÎºÎ¬Ïτας</translation>
<translation id="6628463337424475685">Αναζήτηση <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">ΕÏÏεση συσκευών USB…</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ΔιαγÏαφή</translation>
@@ -1504,12 +1545,13 @@
<translation id="6648524591329069940">ΓÏαμματοσειÏά Serif</translation>
<translation id="6651270836885078973">Η διαχείÏιση γίνεται από:</translation>
<translation id="6652101503459149953">ΧÏήση Windows Hello</translation>
-<translation id="6657585470893396449">Κωδικός Ï€Ïόσβασης</translation>
+<translation id="6657585470893396449">Κωδικός ΠÏόσβασης</translation>
<translation id="666259744093848177">(x86_64 μεταφÏασμένο)</translation>
<translation id="6665553082534466207">ΤÏιπλό Ï„ÏÏπημα στα δεξιά</translation>
<translation id="6671697161687535275">Îα καταÏγηθεί η Ï€Ïόταση φόÏμας από το Chromium;</translation>
<translation id="6685834062052613830">Αποσυνδεθείτε και ολοκληÏώστε την εγκατάσταση</translation>
<translation id="6687335167692595844">Ζητήθηκε μέγεθος γÏαμματοσειÏάς</translation>
+<translation id="6688743156324860098">ΕνημέÏωση…</translation>
<translation id="6689249931105087298">Σχετική με τη συμπίεση μαÏÏου σημείου</translation>
<translation id="6689271823431384964">Το Chrome Ï€ÏοσφέÏεται να αποθηκεÏσει τις κάÏτες σας στον ΛογαÏιασμό σας Google, επειδή έχετε συνδεθεί. ΜποÏείτε να αλλάξετε αυτήν τη συμπεÏιφοÏά στις Ïυθμίσεις. Το όνομα του κατόχου κάÏτας Ï€ÏοέÏχεται από τον λογαÏιασμό σας.</translation>
<translation id="6698381487523150993">ΔημιουÏγήθηκε:</translation>
@@ -1525,6 +1567,7 @@
<translation id="6744009308914054259">Ενώ πεÏιμένετε για την επίτευξη κάποιας σÏνδεσης, μποÏείτε να μεταβείτε στις Λήψεις, για να διαβάσετε άÏθÏα εκτός σÏνδεσης.</translation>
<translation id="6753269504797312559">Τιμή πολιτικής</translation>
<translation id="6757797048963528358">Η συσκευή σας τέθηκε σε αδÏάνεια.</translation>
+<translation id="6767985426384634228">ΕνημέÏωση διεÏθυνσης;</translation>
<translation id="6768213884286397650">Hagaki (ΤαχυδÏομική κάÏτα)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Βιολετί</translation>
@@ -1547,6 +1590,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Το Chrome απλοποίησε αυτήν τη σελίδα για να διευκολÏνει την ανάγνωσή της. Το Chrome ανέκτησε την αÏχική σελίδα μέσω μη ασφαλοÏÏ‚ σÏνδεσης.</translation>
<translation id="6891596781022320156">Το επίπεδο πολιτικής δεν υποστηÏίζεται.</translation>
+<translation id="6895143722905299846">Εικονικός αÏιθμός:</translation>
<translation id="6895330447102777224">Η κάÏτα σας επιβεβαιώθηκε</translation>
<translation id="6897140037006041989">ΠαÏάγοντας χÏήστη</translation>
<translation id="6898699227549475383">ΟÏγάνωση (O)</translation>
@@ -1582,10 +1626,10 @@
<translation id="7004583254764674281">ΧÏησιμοποιήστε το Windows Hello για πιο γÏήγοÏη επιβεβαίωση καÏτών</translation>
<translation id="7006930604109697472">Αποστολή οÏτως ή άλλως</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Ρυθμίσεις αλλαγής μεγέθους</translation>
<translation id="7014741021609395734">Επίπεδο εστίασης</translation>
<translation id="7016992613359344582">Αυτές οι χÏεώσεις μποÏεί να είναι εφάπαξ ή επαναλαμβανόμενες και ίσως να μην είναι εμφανείς.</translation>
<translation id="7029809446516969842">Κωδ. Ï€Ïόσβασης</translation>
+<translation id="7030436163253143341">Το πιστοποιητικό δεν είναι έγκυÏο</translation>
<translation id="7031646650991750659">Ποιες εφαÏμογές Google Play έχετε εγκαταστήσει</translation>
<translation id="7050187094878475250">ΕπιχειÏήσατε να μεταβείτε στο <ph name="DOMAIN" />, αλλά ο διακομιστής παÏουσίασε ένα πιστοποιητικό με πεÏίοδο εγκυÏότητας η οποία είναι Ï€Î¿Î»Ï Î¼ÎµÎ³Î¬Î»Î· για να θεωÏηθεί αξιόπιστη.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Αυτήν τη στιγμή, δεν είναι δυνατή η αποθήκευση αυτής της κάÏτας}other{Αυτήν τη στιγμή, δεν είναι δυνατή η αποθήκευση αυτών των καÏτών}}</translation>
@@ -1655,12 +1699,14 @@
<translation id="7300012071106347854">Î’Î±Î¸Ï Î¼Ï€Î»Îµ</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Υψηλός</translation>
+<translation id="7305756307268530424">ΈναÏξη σε πιο αÏγή ταχÏτητα</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Βοήθεια σÏνδεσης</translation>
<translation id="7323804146520582233">ΑπόκÏυψη της ενότητας "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">ΠαÏάκαμψη Ï„Î¿Ï€Î¹ÎºÎ¿Ï Î»Î¿Î³Î±ÏÎ¹Î±ÏƒÎ¼Î¿Ï ÏƒÏ…ÏƒÎºÎµÏ…Î®Ï‚</translation>
<translation id="7333654844024768166">Μόλις καταχωÏίσατε τον κωδικό Ï€Ïόσβασής σας σε έναν παÏαπλανητικό ιστότοπο. Το Chromium συνιστά να μεταβείτε στους ιστοτόπους <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> και <ph name="WEBSITE_3" />, καθώς και σε άλλους ιστοτόπους όπου χÏησιμοποιείτε αυτόν τον κωδικό Ï€Ïόσβασης και να τον αλλάξετε άμεσα.</translation>
<translation id="7334320624316649418">&amp;Επανάληψη αναδιάταξης</translation>
+<translation id="7337248890521463931">Εμφάνιση πεÏισσότεÏων γÏαμμών</translation>
<translation id="7337706099755338005">Δεν είναι διαθέσιμο στην πλατφόÏμα σας.</translation>
<translation id="733923710415886693">Το πιστοποιητικό του διακομιστή δεν αποκαλÏφθηκε μέσω της Διαφάνειας πιστοποιητικών.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1668,6 +1714,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">ΓÏαμμή εντολών</translation>
<translation id="7359588939039777303">Αποκλείστηκαν διαφημίσεις.</translation>
+<translation id="7363096869660964304">Ωστόσο, δεν είστε αόÏατοι. Με την κατάσταση ανώνυμης πεÏιήγησης δεν μποÏείτε να αποκÏÏψετε τα στοιχεία της πεÏιήγησής σας από τους εÏγοδότες σας, τον πάÏοχο υπηÏεσιών διαδικτÏου που χÏησιμοποιείτε ή τους ιστοτόπους που επισκέπτεστε.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, πατήστε Tab και μετά Enter για να Ï€Ïοσθέσετε και να διαχειÏιστείτε διευθÏνσεις από τις Ïυθμίσεις του Chrome</translation>
<translation id="7365849542400970216">Îα γνωÏίζει πληÏοφοÏίες για τη χÏήση της συσκευής σας;</translation>
<translation id="7372973238305370288">αποτέλεσμα αναζήτησης</translation>
@@ -1678,7 +1725,9 @@
<translation id="7378594059915113390">Στοιχεία ελέγχου μέσων</translation>
<translation id="7378627244592794276">Όχι</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Δεν ισχÏει</translation>
<translation id="7390545607259442187">Επιβεβαίωση κάÏτας</translation>
+<translation id="7392089738299859607">ΕνημέÏωση διεÏθυνσης</translation>
<translation id="7399802613464275309">Έλεγχος ασφαλείας</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Η συσκευή <ph name="DEVICE_NAME" /> είναι διαχειÏιζόμενη</translation>
@@ -1693,6 +1742,7 @@
&lt;li&gt;Επισκεφτείτε το &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;ΚέντÏο βοήθειας του Chrome&lt;/a&gt;, για να μάθετε πώς μποÏείτε να καταÏγήσετε οÏιστικά το λογισμικό από τον υπολογιστή σας
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Αξιαγάπητο</translation>
<translation id="7416351320495623771">ΔιαχείÏιση κωδικών Ï€Ïόσβασης…</translation>
<translation id="7419106976560586862">ΔιαδÏομή Ï€Ïοφίλ</translation>
<translation id="7437289804838430631">ΠÏοσθήκη στοιχείων επικοινωνίας</translation>
@@ -1708,7 +1758,7 @@
<translation id="7481312909269577407">ΠÏοώθηση</translation>
<translation id="7485870689360869515">Δεν βÏέθηκαν δεδομένα</translation>
<translation id="7495528107193238112">Αυτό το πεÏιεχόμενο είναι αποκλεισμένο. Επικοινωνήστε με τον κάτοχο του ιστοτόπου για να διοÏθώσετε το Ï€Ïόβλημα.</translation>
-<translation id="7498234416455752244">Συνέχιση επεξεÏγασίας</translation>
+<translation id="7498193950643227031">ΜποÏεί να συμπεÏιφέÏεται με μη αναμενόμενο Ï„Ïόπο εάν αλλάξει μέγεθος. ΜποÏείτε πλέον να πεÏιοÏίσετε τη δυνατότητα αλλαγής μεγέθους εφαÏμογών στις <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Μόλις καταχωÏίσατε τον κωδικό Ï€Ïόσβασής σας σε έναν παÏαπλανητικό ιστότοπο. Το Chromium συνιστά να ελέγξετε τους αποθηκευμένους κωδικοÏÏ‚ Ï€Ïόσβασής σας για τους ιστοτόπους <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> και τους άλλους ιστοτόπους όπου χÏησιμοποιείτε αυτόν τον κωδικό Ï€Ïόσβασης Ï„ÏŽÏα.</translation>
<translation id="7508255263130623398">Η εμφανιζόμενη συσκευή πολιτικής είναι κενή ή δεν αντιστοιχεί στο Ï„Ïέχον αναγνωÏιστικό συσκευής</translation>
<translation id="7508870219247277067">ΠÏάσινο αβοκάντο</translation>
@@ -1728,6 +1778,7 @@
<translation id="7548892272833184391">ΔιόÏθωση σφαλμάτων σÏνδεσης</translation>
<translation id="7549584377607005141">Για τη σωστή εμφάνιση αυτής της ιστοσελίδας, απαιτοÏνται δεδομένα που καταχωÏίσατε νωÏίτεÏα. ΜποÏείτε να αποστείλετε ξανά αυτά τα δεδομένα, ωστόσο, έτσι θα επαναλάβετε κάθε ενέÏγεια που εκτέλεσε νωÏίτεÏα αυτή η σελίδα.</translation>
<translation id="7550637293666041147">Το όνομα χÏήστη της συσκευής σας και το όνομα χÏήστη Chrome</translation>
+<translation id="755279583747225797">Η δοκιμή είναι ενεÏγή</translation>
<translation id="7552846755917812628">Δοκιμάστε τις παÏακάτω συμβουλές:</translation>
<translation id="7554475479213504905">Επανάληψη φόÏτωσης και εμφάνιση οÏτως ή άλλως</translation>
<translation id="7554791636758816595">Îέα καÏτέλα</translation>
@@ -1746,7 +1797,6 @@
<translation id="7610193165460212391">Η τιμή είναι εκτός του εÏÏους τιμών <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Λήξη: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, πατήστε Tab και έπειτα Enter για να δείτε και να διαχειÏιστείτε τους κωδικοÏÏ‚ Ï€Ïόσβασής σας στις Ïυθμίσεις του Chrome.</translation>
-<translation id="7615602087246926389">Έχετε ήδη δεδομένα που είναι κÏυπτογÏαφημένα με χÏήση διαφοÏετικής έκδοσης του ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης για τον ΛογαÏιασμό σας Google. Εισαγάγετέ τον παÏακάτω.</translation>
<translation id="7616645509853975347">Ο διαχειÏιστής σας ενεÏγοποίησε το Chrome Enterprise Connectors στο Ï€ÏόγÏαμμα πεÏιήγησής σας. Αυτές οι εφαÏμογές σÏνδεσης έχουν Ï€Ïόσβαση σε οÏισμένα από τα δεδομένα σας.</translation>
<translation id="7619838219691048931">Τελευταίο φÏλλο</translation>
<translation id="762844065391966283">Ένα τη φοÏά</translation>
@@ -1811,13 +1861,12 @@
<translation id="782886543891417279">Το Wi-Fi που χÏησιμοποιείτε (<ph name="WIFI_NAME" />) ενδέχεται να σας ζητήσει να επισκεφτείτε τη σελίδα σÏνδεσής του.</translation>
<translation id="7836231406687464395">Postfix (Φάκελος)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Κανένα}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Îα ανοίξει αÏχεία με συσχετισμοÏÏ‚ Ï„Ïπων αÏχείων.</translation>
<translation id="7862185352068345852">Θέλετε να αποχωÏήσετε από τον ιστότοπο;</translation>
<translation id="7865448901209910068">Βέλτιστη ταχÏτητα</translation>
<translation id="7874263914261512992">Μόλις καταχωÏίσατε τον κωδικό Ï€Ïόσβασής σας σε έναν παÏαπλανητικό ιστότοπο. Το Chrome συνιστά να ελέγξετε τους αποθηκευμένους κωδικοÏÏ‚ Ï€Ïόσβασής σας για τους ιστοτόπους <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> και τους άλλους ιστοτόπους όπου χÏησιμοποιείτε αυτόν τον κωδικό Ï€Ïόσβασης Ï„ÏŽÏα.</translation>
<translation id="7878562273885520351">Ο κωδικός Ï€Ïόσβασής σας μποÏεί να έχει παÏαβιαστεί</translation>
+<translation id="7880146494886811634">Αποθήκευση διεÏθυνσης</translation>
<translation id="7882421473871500483">Καφέ</translation>
<translation id="7887683347370398519">Ελέγξτε τον κωδικό σας CVC και δοκιμάστε ξανά</translation>
<translation id="7887885240995164102">Είσοδος στη λειτουÏγία picture-in-picture</translation>
@@ -1825,6 +1874,7 @@
<translation id="7894280532028510793">Εάν δεν υπάÏχει οÏθογÏαφικό λάθος, <ph name="BEGIN_LINK" />δοκιμάστε να εκτελέσετε έναν έλεγχο Διαγνωστικών δικτÏου<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Φάκελος)</translation>
<translation id="7931318309563332511">Άγνωστη</translation>
+<translation id="793209273132572360">ΕνημέÏωση διεÏθυνσης;</translation>
<translation id="7932579305932748336">Επικάλυψη</translation>
<translation id="79338296614623784">Εισαγάγετε έναν έγκυÏο αÏιθμό τηλεφώνου</translation>
<translation id="7934052535022478634">Η πληÏωμή ολοκληÏώθηκε</translation>
@@ -1895,6 +1945,7 @@
<translation id="8175796834047840627">Το Chrome Ï€ÏοσφέÏεται να αποθηκεÏσει τις κάÏτες σας στον ΛογαÏιασμό σας Google επειδή έχετε συνδεθεί. ΜποÏείτε να αλλάξετε αυτήν τη συμπεÏιφοÏά στις Ïυθμίσεις.</translation>
<translation id="8176440868214972690">Ο διαχειÏιστής αυτής της συσκευής έστειλε οÏισμένες πληÏοφοÏίες στους παÏακάτω ιστοτόπους, όπως Ïυθμίσεις ή πολιτικές.</translation>
<translation id="8184538546369750125">ΧÏήση καθολικής Ï€Ïοεπιλεγμένης ÏÏθμισης (ΕπιτÏέπεται)</translation>
+<translation id="8193086767630290324">ΕνέÏγειες με δεδομένα που έχουν επισημανθεί ως εμπιστευτικά</translation>
<translation id="8194797478851900357">&amp;ΑναίÏεση μετακίνησης</translation>
<translation id="8201077131113104583">Η διεÏθυνση URL ενημέÏωσης για την επέκταση με αναγνωÏιστικό ID "<ph name="EXTENSION_ID" />", δεν είναι έγκυÏη.</translation>
<translation id="8202097416529803614">ΣÏνοψη παÏαγγελίας</translation>
@@ -1917,6 +1968,7 @@
<translation id="8249296373107784235">Ματαίωση</translation>
<translation id="8249320324621329438">Τελευταία ανάκτηση:</translation>
<translation id="8253091569723639551">Απαιτείται διεÏθυνση χÏέωσης</translation>
+<translation id="8257387598443225809">Αυτή η εφαÏμογή έχει σχεδιαστεί για κινητά</translation>
<translation id="825929999321470778">Εμφάνιση όλων των αποθηκευμένων κωδικών Ï€Ïόσβασης</translation>
<translation id="8261506727792406068">ΔιαγÏαφή</translation>
<translation id="8262952874573525464">Ραφή στο κάτω άκÏο</translation>
@@ -2043,7 +2095,6 @@
<translation id="8719528812645237045">Πολλαπλό Ï„ÏÏπημα στο επάνω μέÏος</translation>
<translation id="8725066075913043281">ΠÏοσπαθήστε ξανά</translation>
<translation id="8726549941689275341">Μέγεθος σελίδας:</translation>
-<translation id="8728672262656704056">ΠÏαγματοποιείτε ανώνυμη πεÏιήγηση</translation>
<translation id="8730621377337864115">ΟλοκληÏώθηκε</translation>
<translation id="8731544501227493793">Κουμπί διαχείÏισης κωδικών Ï€Ïόσβασης, πατήστε Enter για Ï€Ïοβολή και διαχείÏιση των κωδικών Ï€Ïόσβασής σας στις Ïυθμίσεις του Chrome</translation>
<translation id="8734529307927223492">Η διαχείÏιση της συσκευής <ph name="DEVICE_TYPE" /> γίνεται από τον τομέα <ph name="MANAGER" /></translation>
@@ -2120,6 +2171,7 @@
<translation id="9020542370529661692">Αυτή η σελίδα έχει μεταφÏαστεί στα <ph name="TARGET_LANGUAGE" />.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Μη έγκυÏο)</translation>
+<translation id="9030265603405983977">ΜονόχÏωμο</translation>
<translation id="9035022520814077154">Σφάλμα ασφάλειας</translation>
<translation id="9038649477754266430">ΧÏήση μιας υπηÏεσίας Ï€Ïόβλεψης για ταχÏτεÏη φόÏτωση σελίδων</translation>
<translation id="9039213469156557790">Επίσης, αυτή η σελίδα πεÏιέχει άλλους πόÏους, οι οποίοι δεν είναι ασφαλείς. Αυτοί οι πόÏοι μποÏοÏν να Ï€ÏοβληθοÏν από άλλους χÏήστες κατά τη μετάβαση και μποÏοÏν να Ï„ÏοποποιηθοÏν από έναν εισβολέα ώστε να αλλάξει η συμπεÏιφοÏά της σελίδας.</translation>
@@ -2143,6 +2195,7 @@
<translation id="91108059142052966">Η πολιτική διαχειÏιστή απενεÏγοποιεί την κοινή χÏήση οθόνης με την εφαÏμογή <ph name="APPLICATION_TITLE" /> όταν εμφανίζεται εμπιστευτικό πεÏιεχόμενο.</translation>
<translation id="9114524666733003316">Επιβεβαίωση κάÏτας…</translation>
<translation id="9114581008513152754">Αυτός ο ιστότοπος δεν είναι διαχειÏιζόμενος από κάποια εταιÏεία ή άλλον οÏγανισμό. Η διαχείÏιση της δÏαστηÏιότητας σε αυτήν τη συσκευή μποÏεί να Ï€Ïαγματοποιηθεί εκτός Chrome. <ph name="BEGIN_LINK" />Μάθετε πεÏισσότεÏα<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ΦÏέσκο</translation>
<translation id="9119042192571987207">Έγινε μεταφόÏτωση</translation>
<translation id="9128016270925453879">Οι πολιτικές φοÏτώθηκαν</translation>
<translation id="9128870381267983090">ΣÏνδεση σε δίκτυο</translation>
@@ -2161,6 +2214,7 @@
<translation id="9170848237812810038">Αναί&amp;Ïεση</translation>
<translation id="9171296965991013597">ΑποχώÏηση από την εφαÏμογή;</translation>
<translation id="9173282814238175921">Ένα έγγÏαφο/Îέο φÏλλο</translation>
+<translation id="9173995187295789444">ΣάÏωση για συσκευές Bluetooth…</translation>
<translation id="917450738466192189">Το πιστοποιητικό του διακομιστή δεν είναι έγκυÏο.</translation>
<translation id="9174917557437862841">Κουμπί εναλλαγής καÏτέλας, πατήστε Enter για μετάβαση σε αυτήν την καÏτέλα</translation>
<translation id="9179703756951298733">ΔιαχειÏιστείτε τις πληÏωμές και τα στοιχεία της πιστωτικής σας κάÏτας στις Ïυθμίσεις του Chrome.</translation>
diff --git a/chromium/components/strings/components_strings_en-GB.xtb b/chromium/components/strings/components_strings_en-GB.xtb
index 39a551941bd..43a00fabe7e 100644
--- a/chromium/components/strings/components_strings_en-GB.xtb
+++ b/chromium/components/strings/components_strings_en-GB.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">If ticked, Chrome will store a copy of your card on this device for faster form filling.</translation>
<translation id="1110994991967754504">Select permission for <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Undo reorder</translation>
+<translation id="1123753900084781868">Live Caption is not available at the moment</translation>
<translation id="1125573121925420732">Warnings may be common while websites update their security. This should improve soon.</translation>
<translation id="112840717907525620">Policy cache OK</translation>
<translation id="1130564665089811311">Translate page button; press enter to translate this page with Google Translate</translation>
@@ -74,6 +75,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="1240347957665416060">Your device name</translation>
<translation id="124116460088058876">More languages</translation>
<translation id="1243027604378859286">Author:</translation>
+<translation id="1246424317317450637">Bold</translation>
<translation id="1250759482327835220">To pay faster next time, save your card, name and billing address to your Google Account.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (synced)</translation>
<translation id="1256368399071562588">&lt;p&gt;If you try to visit a website and it doesn’t open, first try to fix the error with these troubleshooting steps:&lt;/p&gt;
@@ -156,6 +158,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="1476595624592550506">Change your password</translation>
<translation id="1484290072879560759">Choose delivery address</translation>
<translation id="1492194039220927094">Policies push:</translation>
+<translation id="1495677929897281669">Back to tab</translation>
<translation id="1501859676467574491">Show cards from your Google Account</translation>
<translation id="1507202001669085618">&lt;p&gt;You'll see this error if you're using a Wi-Fi portal where you have to sign in before you can get online.&lt;/p&gt;
&lt;p&gt;To fix the error, click &lt;strong&gt;Connect&lt;/strong&gt; on the page that you're trying to open.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="1532118530259321453">This page says</translation>
<translation id="153384715582417236">That’s all for now</translation>
<translation id="1536390784834419204">Translate page</translation>
+<translation id="1539840569003678498">Report sent:</translation>
<translation id="154408704832528245">Choose delivery address</translation>
<translation id="1549470594296187301">JavaScript must be enabled to use this feature.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="1682696192498422849">Short edge first</translation>
<translation id="168693727862418163">This policy value failed to validate against its schema and will be ignored.</translation>
<translation id="168841957122794586">The server certificate contains a weak cryptographic key.</translation>
+<translation id="1696290444144917273">View virtual card details</translation>
<translation id="1697532407822776718">You're all set!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{This server could not prove that it is <ph name="DOMAIN" />; its security certificate is supposedly from tomorrow. This may be caused by a misconfiguration or an attacker intercepting your connection.}other{This server could not prove that it is <ph name="DOMAIN" />; its security certificate is supposedly from # days in the future. This may be caused by a misconfiguration or an attacker intercepting your connection.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Ignored because <ph name="POLICY_NAME" /> is not set to <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> wants to permanently store data on your local computer</translation>
<translation id="1713628304598226412">Tray 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Mailbox 3</translation>
<translation id="1718029547804390981">Document is too large to be annotated</translation>
<translation id="1721424275792716183">* Field is required</translation>
+<translation id="1727613060316725209">Certificate is valid</translation>
<translation id="1727741090716970331">Add Valid Card Number</translation>
<translation id="1728677426644403582">You're viewing the source of a web page</translation>
<translation id="173080396488393970">This type of card isn’t supported</translation>
@@ -245,7 +252,6 @@ This will otherwise be blocked by your privacy settings. This will allow the con
the header is malformed, which prevents the browser from fulfilling
your request for <ph name="SITE" />. Origin policies can be used by site operators to configure security and other properties for a site.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Please update your sync passphrase.</translation>
<translation id="1787142507584202372">Your open tabs appear here</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, multiple actions are available; press 'Tab' to cycle through them</translation>
@@ -278,6 +284,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="1919345977826869612">Ads</translation>
<translation id="1919367280705858090">Get help with a specific error message</translation>
<translation id="192020519938775529">{COUNT,plural, =0{None}=1{1 site}other{# sites}}</translation>
+<translation id="1924727005275031552">New</translation>
<translation id="1945968466830820669">You could lose access to your organisation's account or experience identity theft. Chromium recommends changing your password now.</translation>
<translation id="1947454675006758438">Staple top right</translation>
<translation id="1958218078413065209">Your highest score is <ph name="SCORE" />.</translation>
@@ -300,12 +307,14 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="2042213636306070719">Tray 7</translation>
<translation id="204357726431741734">Sign in to use passwords saved in your Google Account</translation>
<translation id="2053111141626950936">Pages in <ph name="LANGUAGE" /> will not be translated.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{When this control is on and the status is active, Chrome determines which large group of people, or 'cohort', your recent browsing activity is most similar to. Advertisers can select ads for the group, and your browsing activity is kept private on your device. Your group is updated every day.}=1{When this control is on and the status is active, Chrome determines which large group of people, or 'cohort', your recent browsing activity is most similar to. Advertisers can select ads for the group, and your browsing activity is kept private on your device. Your group is updated every day.}other{When this control is on and the status is active, Chrome determines which large group of people, or 'cohort', your recent browsing activity is most similar to. Advertisers can select ads for the group, and your browsing activity is kept private on your device. Your group is updated every {NUM_DAYS} days.}}</translation>
<translation id="2053553514270667976">ZIP code</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggestion}other{# suggestions}}</translation>
<translation id="2071692954027939183">Notifications were automatically blocked because you usually don't allow them</translation>
<translation id="2079545284768500474">Undo</translation>
<translation id="20817612488360358">System proxy settings are set to be used but an explicit proxy configuration is also specified.</translation>
<translation id="2082238445998314030">Result <ph name="RESULT_NUMBER" /> of <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Save…</translation>
<translation id="2088086323192747268">Manage sync button, press Enter to manage what info you sync in Chrome settings</translation>
<translation id="2091887806945687916">Sound</translation>
<translation id="2094505752054353250">Domain mismatch</translation>
@@ -378,6 +387,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="2317259163369394535"><ph name="DOMAIN" /> requires a username and password.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, expires on <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Setting controlled by your administrator</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> wants to pair</translation>
<translation id="2344028582131185878">Automatic downloads</translation>
<translation id="2346319942568447007">Image that you copied</translation>
<translation id="2354001756790975382">Other bookmarks</translation>
@@ -385,8 +395,10 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="2355395290879513365">Attackers might be able to see the images that you’re looking at on this site and trick you by modifying them.</translation>
<translation id="2356070529366658676">Ask</translation>
<translation id="2357481397660644965">Your device is managed by <ph name="DEVICE_MANAGER" /> and your account is managed by <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{In less than a day}=1{In a day}other{In {NUM_DAYS} days}}</translation>
<translation id="2359629602545592467">Multiple</translation>
<translation id="2359808026110333948">Continue</translation>
+<translation id="2359961752320758691">Your virtual card number is applied.</translation>
<translation id="2367567093518048410">Level</translation>
<translation id="2372464001869762664">Once you confirm, card details from your Google Account will be shared with this site. Find the CVC in your Plex account details.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -397,6 +409,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="239429038616798445">This delivery method isn’t available. Try a different method.</translation>
<translation id="2396249848217231973">&amp;Undo delete</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Old</translation>
<translation id="2413528052993050574">This server could not prove that it is <ph name="DOMAIN" />; its security certificate might be revoked. This may be caused by a misconfiguration or an attacker intercepting your connection.</translation>
<translation id="2414886740292270097">Dark</translation>
<translation id="2438874542388153331">Quad punch right</translation>
@@ -424,10 +437,10 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="2521385132275182522">Staple bottom right</translation>
<translation id="2523886232349826891">Saved on this device only</translation>
<translation id="2524461107774643265">Add More Information</translation>
-<translation id="2526590354069164005">Desktop</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{and 1 more}other{and # more}}</translation>
<translation id="2536110899380797252">Add Address</translation>
<translation id="2539524384386349900">Detect</translation>
+<translation id="2541219929084442027">Pages that you view in Incognito tabs won’t stick around in your browser’s history, cookie store or search history after you’ve closed all of your Incognito tabs. Any files that you download or bookmarks that you create will be kept.</translation>
<translation id="2544644783021658368">Single document</translation>
<translation id="254947805923345898">Policy value is not valid.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> sent an invalid response.</translation>
@@ -447,6 +460,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="2629325967560697240">To get Chrome’s highest level of security, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />turn on enhanced protection<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" />’s server IP address could not be found.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">No compatible devices found.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, press tab, then enter to clear your browsing history, cookies, cache and more in Chrome settings</translation>
<translation id="2650446666397867134">Access to the file was denied</translation>
@@ -493,6 +507,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<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="2807052079800581569">Image Y position</translation>
+<translation id="2820957248982571256">Scanning...</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>
@@ -500,6 +515,8 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">This site shows intrusive or misleading ads.</translation>
+<translation id="287596039013813457">Friendly</translation>
+<translation id="2876489322757410363">Leaving Incognito mode to pay via an external application. Continue?</translation>
<translation id="2878197950673342043">Poster fold</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Window placement</translation>
@@ -549,7 +566,6 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, press Tab then Enter to run safety check in Chrome settings</translation>
<translation id="3061707000357573562">Patch Service</translation>
-<translation id="3064966200440839136">Leaving incognito mode to pay via an external application. Continue?</translation>
<translation id="306573536155379004">Game started.</translation>
<translation id="3080254622891793721">Graphic</translation>
<translation id="3086579638707268289">Your activity on the web is being monitored</translation>
@@ -572,7 +588,6 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="315504272643575312">Your account is managed by <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Restore</translation>
<translation id="3162559335345991374">The Wi-Fi that you are using may require you to visit its login page.</translation>
-<translation id="3167968892399408617">Pages that you view in incognito tabs won’t stick around in your browser’s history, cookie store or search history after you’ve closed all of your incognito tabs. Any files you download or bookmarks you create will be kept.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Island</translation>
<translation id="3176929007561373547">Check your proxy settings or contact your network administrator to
@@ -598,10 +613,12 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<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="3249845759089040423">Groovy</translation>
<translation id="3252266817569339921">French</translation>
<translation id="3266793032086590337">Value (conflict)</translation>
<translation id="3268451620468152448">Open tabs</translation>
<translation id="3270847123878663523">&amp;Undo Reorder</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> wants to connect</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Your organisation, <ph name="ENROLLMENT_DOMAIN" />, has sent some info to the following websites, like settings or policies.</translation>
<translation id="3282497668470633863">Add name on card</translation>
@@ -654,6 +671,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="3428151540071562330">One or more of the DnsOverHttpsTemplates server template URIs is invalid and will not be used.</translation>
<translation id="3431636764301398940">Save this card to this device</translation>
<translation id="3432601291244612633">Close page</translation>
+<translation id="3435738964857648380">Security</translation>
<translation id="3435896845095436175">Enable</translation>
<translation id="3438829137925142401">Use passwords saved in your Google Account</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -696,7 +714,10 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="3584299510153766161">Dual punch bottom</translation>
<translation id="3586931643579894722">Hide details</translation>
<translation id="3587738293690942763">Middle</translation>
+<translation id="3590643883886679995">Sign-in data will be stored on this device after you exit Incognito mode.</translation>
+<translation id="359126217934908072">Month/Year:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{You can reset your group at any time. It takes about a day to join a new group.}=1{You can reset your group at any time. It takes about a day to join a new group.}other{You can reset your group at any time. It takes {NUM_DAYS} days to join a new group.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Application blocked by your administrator</translation>
<translation id="3608932978122581043">Feed orientation</translation>
@@ -705,13 +726,13 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="3615877443314183785">Enter a valid expiry date</translation>
<translation id="36224234498066874">Clear Browsing Data...</translation>
<translation id="362276910939193118">Show full history</translation>
-<translation id="3625635938337243871">Sign-in data will be stored on this device after you exit Incognito mode.</translation>
<translation id="3630155396527302611">If it is already listed as a program allowed to access the network, try
removing it from the list and adding it again.</translation>
<translation id="3630699740441428070">Administrators of this device have configured your network connection, which may allow them to see your network traffic, including which websites that you visit.</translation>
<translation id="3631244953324577188">Biometrics</translation>
<translation id="3633738897356909127">Update Chrome button; press enter to update Chrome from your Chrome settings</translation>
<translation id="3634530185120165534">Tray 5</translation>
+<translation id="3637662659967048211">Save to Google Account</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Application:</translation>
<translation id="3650584904733503804">Validation successful</translation>
@@ -752,6 +773,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="3781428340399460090">Hot pink</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth devices</translation>
+<translation id="3787675388804467730">Virtual card number</translation>
<translation id="3787705759683870569">Expires <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Size 16</translation>
<translation id="3789841737615482174">Install</translation>
@@ -771,6 +793,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="3841184659773414994">File handlers</translation>
<translation id="385051799172605136">Back</translation>
<translation id="3858027520442213535">Update date and time</translation>
+<translation id="3881478300875776315">Show fewer lines</translation>
<translation id="3884278016824448484">Conflicting device identifier</translation>
<translation id="3885155851504623709">Parish</translation>
<translation id="388632593194507180">Monitoring detected</translation>
@@ -796,6 +819,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="397105322502079400">Calculating...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> is blocked</translation>
<translation id="3973357910713125165">Run Chrome safety check button; press Enter to run safety check in Chrome settings</translation>
+<translation id="3986705137476756801">Turn off Live Caption for now</translation>
<translation id="3987405730340719549">Chrome has determined that this site could be fake or fraudulent.
If you believe that this is shown in error please visit https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -892,13 +916,14 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="4275830172053184480">Restart your device</translation>
<translation id="4277028893293644418">Reset password</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="4287885627794386150">Eligible for trial but not active</translation>
<translation id="4297502707443874121">Thumbnail for page <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Expand</translation>
<translation id="4300675098767811073">Multiple punch right</translation>
<translation id="4302514097724775343">Tap the dino to play</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Your file couldn’t be accessed</translation>
-<translation id="4305817255990598646">Switch</translation>
+<translation id="4306529830550717874">Save address?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Block (default)</translation>
<translation id="4314815835985389558">Manage sync</translation>
@@ -925,6 +950,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="4377125064752653719">You attempted to reach <ph name="DOMAIN" />, but the certificate that the server presented has been revoked by its issuer. This means that the security credentials the server presented absolutely should not be trusted. You may be communicating with an attacker.</translation>
<translation id="4378154925671717803">Phone</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Live Caption</translation>
<translation id="4406896451731180161">search results</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">You just entered your password on a deceptive site. Chrome recommends going to <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> and other sites where you use this password and changing it now.</translation>
@@ -937,7 +963,6 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Use of a proxy is disabled but an explicit proxy configuration is specified.</translation>
<translation id="4464826014807964867">Websites with info from your organisation</translation>
-<translation id="4466881336512663640">Form changes will be lost. Are you sure that you want to continue?</translation>
<translation id="4476953670630786061">This form is not secure. Auto-fill has been turned off.</translation>
<translation id="4477350412780666475">Next track</translation>
<translation id="4482953324121162758">This site will not be translated.</translation>
@@ -971,6 +996,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="4594403342090139922">&amp;Undo Delete</translation>
<translation id="4597348597567598915">Size 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Impactful</translation>
<translation id="4628948037717959914">Photo</translation>
<translation id="4631649115723685955">Cashback linked</translation>
<translation id="4636930964841734540">Info</translation>
@@ -990,6 +1016,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Side</translation>
+<translation id="4702656508969495934">Live Caption visible; use window switcher to focus</translation>
<translation id="4708268264240856090">Your connection was interrupted</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Running Windows Network Diagnostics<ph name="END_LINK" /></translation>
@@ -1003,6 +1030,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="4738601419177586157"><ph name="TEXT" /> search suggestion</translation>
<translation id="4742407542027196863">Manage passwords…</translation>
<translation id="4744603770635761495">Executable Path</translation>
+<translation id="4749011317274908093">You’ve gone Incognito</translation>
<translation id="4750917950439032686">Your information (for example, passwords or credit card numbers) is private when it is sent to this site.</translation>
<translation id="4756388243121344051">&amp;History</translation>
<translation id="4758311279753947758">Add contact info</translation>
@@ -1032,6 +1060,8 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="4813512666221746211">Network error</translation>
<translation id="4816492930507672669">Fit to page</translation>
<translation id="4819347708020428563">Edit annotations in default view?</translation>
+<translation id="4825507807291741242">Powerful</translation>
+<translation id="4838327282952368871">Dreamy</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">View</translation>
<translation id="485316830061041779">German</translation>
@@ -1168,6 +1198,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="5314967030527622926">Booklet maker</translation>
<translation id="5316812925700871227">Rotate Anti-clockwise</translation>
<translation id="5317780077021120954">Save</translation>
+<translation id="5321288445143113935">Maximised</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> of <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Choose contact info</translation>
<translation id="5327248766486351172">Name</translation>
@@ -1175,11 +1206,13 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="5332219387342487447">Delivery method</translation>
<translation id="5333022057423422993">Chrome found the password that you just used in a data breach. To secure your accounts, we recommend checking your saved passwords.</translation>
<translation id="5334013548165032829">Detailed system logs</translation>
+<translation id="5334145288572353250">Save address?</translation>
<translation id="5340250774223869109">Application is blocked</translation>
<translation id="534295439873310000">NFC devices</translation>
<translation id="5344579389779391559">This page may try to charge you money</translation>
<translation id="5355557959165512791">You cannot visit <ph name="SITE" /> right now because its certificate has been revoked. Network errors and attacks are usually temporary, so this page will probably work later.</translation>
<translation id="536296301121032821">Failed to store policy settings</translation>
+<translation id="5363309033720083897">Serial port allowed by your administrator</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="5386426401304769735">The certificate chain for this site contains a certificate signed using SHA-1.</translation>
@@ -1188,6 +1221,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="5398772614898833570">Ads blocked</translation>
<translation id="5400836586163650660">Grey</translation>
<translation id="540969355065856584">This server could not prove that it is <ph name="DOMAIN" />; its security certificate is not valid at this time. This may be caused by a misconfiguration or an attacker intercepting your connection.</translation>
+<translation id="541143247543991491">Cloud (system-wide)</translation>
<translation id="541416427766103491">Stacker 4</translation>
<translation id="5421136146218899937">Clear browsing data...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> wants to send you notifications</translation>
@@ -1201,6 +1235,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="5455374756549232013">Bad policy timestamp</translation>
<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="5463625433003343978">Finding devices…</translation>
<translation id="5469868506864199649">Italian</translation>
<translation id="5470861586879999274">&amp;Redo edit</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1250,7 +1285,6 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="5624120631404540903">Manage passwords</translation>
<translation id="5629630648637658800">Failed to load policy settings</translation>
<translation id="5631439013527180824">Invalid device management token</translation>
-<translation id="5632627355679805402">Your data was encrypted with your <ph name="BEGIN_LINK" />Google password<ph name="END_LINK" /> as of <ph name="TIME" />. Enter it to start sync.</translation>
<translation id="5633066919399395251">Attackers currently on <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> might attempt to install dangerous programs on your computer that steal or delete your information (for example, photos, passwords, messages and credit cards). <ph name="BEGIN_LEARN_MORE_LINK" />Learn more<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Deceptive content blocked.</translation>
<translation id="5644090287519800334">Side 1 image X shift</translation>
@@ -1289,12 +1323,12 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="5785756445106461925">Further, 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 look of the page.</translation>
<translation id="5786044859038896871">Do you want to fill in your card info?</translation>
<translation id="578633867165174378">Chrome found the password that you just used in a data breach. We recommend changing this password now.</translation>
-<translation id="5798290721819630480">Discard changes?</translation>
<translation id="5803412860119678065">Do you want to fill in your <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Permissions</translation>
<translation id="5804427196348435412">Use NFC devices</translation>
<translation id="5810442152076338065">Your connection to <ph name="DOMAIN" /> is encrypted using an obsolete cipher suite.</translation>
<translation id="5813119285467412249">&amp;Redo Add</translation>
+<translation id="5817918615728894473">Pair</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{This card will be charged when you pay, but its real number won't be shared with this site. For extra security, a temporary CVC will be generated.}other{The card that you select will be charged when you pay, but its real number won't be shared with this site. For extra security, a temporary CVC will be generated.}}</translation>
<translation id="5826507051599432481">Common Name (CN)</translation>
<translation id="5838278095973806738">You should not enter any sensitive information on this site (for example, passwords or credit cards) because it could be stolen by attackers.</translation>
@@ -1302,6 +1336,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="5855253129151731373">This site's hostname looks similar to <ph name="LOOKALIKE_DOMAIN" />. Attackers sometimes mimic sites by making small, hard-to-see changes to the domain name.
If you believe that this is shown in error please visit https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Off</translation>
<translation id="5862579898803147654">Stacker 8</translation>
<translation id="5863847714970149516">The page ahead may try to charge you money</translation>
<translation id="5866257070973731571">Add Phone Number</translation>
@@ -1318,6 +1353,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="5913377024445952699">Screen capture paused</translation>
<translation id="59174027418879706">Enabled</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 in use}other{# in use}}</translation>
<translation id="5921185718311485855">On</translation>
<translation id="5921639886840618607">Save card to Google Account?</translation>
<translation id="5922853866070715753">Almost finished</translation>
@@ -1337,6 +1373,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="5989320800837274978">Neither fixed proxy servers nor a .pac script URL are specified.</translation>
<translation id="5992691462791905444">Engineering Z-fold</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> results for '<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">Classic</translation>
<translation id="6008122969617370890">N-to-1 order</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Check your passwords</translation>
@@ -1358,6 +1395,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="6045164183059402045">Imposition template</translation>
<translation id="6047233362582046994">If you understand the risks to your security, you may <ph name="BEGIN_LINK" />visit this site<ph name="END_LINK" /> before the harmful apps have been removed.</translation>
<translation id="6047927260846328439">This content might try to trick you into installing software or revealing personal information. <ph name="BEGIN_LINK" />Show anyway<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Press and hold |<ph name="ACCELERATOR" />| to exit full screen</translation>
<translation id="6049488691372270142">Page delivery</translation>
<translation id="6051221802930200923">You cannot visit <ph name="SITE" /> right now because the website uses certificate pinning. Network errors and attacks are usually temporary, so this page will probably work later.</translation>
<translation id="6051898664905071243">Page count:</translation>
@@ -1374,6 +1412,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<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>
<translation id="6116338172782435947">See text and images copied to the clipboard</translation>
<translation id="6120179357481664955">Remember your UPI ID?</translation>
+<translation id="6123290840358279103">View virtual card</translation>
<translation id="6124432979022149706">Chrome Enterprise connectors</translation>
<translation id="6146055958333702838">Check any cables and reboot any routers, modems or other network
devices you may be using.</translation>
@@ -1410,6 +1449,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="6289939620939689042">Page colour</translation>
<translation id="6290238015253830360">Your suggested articles appear here</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google Assistant in Chrome stopping</translation>
<translation id="6305205051461490394"><ph name="URL" /> is unreachable.</translation>
<translation id="6312113039770857350">Web page not available</translation>
@@ -1435,6 +1475,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="6390200185239044127">Z-fold half</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Pasting from <ph name="ORIGIN_NAME" /> to this location is blocked by administrator policy</translation>
+<translation id="6398765197997659313">Exit full screen</translation>
<translation id="6401136357288658127">This policy is deprecated. You should use the <ph name="NEW_POLICY" /> policy instead.</translation>
<translation id="6404511346730675251">Edit bookmark</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1447,7 +1488,6 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="6428450836711225518">Verifying your phone number</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="6440503408713884761">Ignored</translation>
<translation id="6443406338865242315">Which extensions and plug-ins you have installed</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1490,6 +1530,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="6624427990725312378">Contact Info</translation>
<translation id="6626291197371920147">Add valid card number</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Search</translation>
+<translation id="6630043285902923878">Finding USB devices…</translation>
<translation id="6630809736994426279">Attackers currently on <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> might attempt to install dangerous programs on your Mac that steal or delete your information (for example, photos, passwords, messages and credit cards). <ph name="BEGIN_LEARN_MORE_LINK" />Learn more<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Clear</translation>
@@ -1505,6 +1546,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="6671697161687535275">Remove form suggestion from Chromium?</translation>
<translation id="6685834062052613830">Sign out and complete setup</translation>
<translation id="6687335167692595844">Font size requested</translation>
+<translation id="6688743156324860098">Update…</translation>
<translation id="6689249931105087298">Relative with black point compression</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="6698381487523150993">Created:</translation>
@@ -1520,6 +1562,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="6744009308914054259">While waiting for a connection, you can visit Downloads to read offline articles.</translation>
<translation id="6753269504797312559">Policy Value</translation>
<translation id="6757797048963528358">Your device went to sleep.</translation>
+<translation id="6767985426384634228">Update address?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violet</translation>
@@ -1542,6 +1585,7 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome simplified this page to make it easier to read. Chrome retrieved the original page over an insecure connection.</translation>
<translation id="6891596781022320156">Policy level is not supported.</translation>
+<translation id="6895143722905299846">Virtual number:</translation>
<translation id="6895330447102777224">Your card is confirmed</translation>
<translation id="6897140037006041989">User agent</translation>
<translation id="6898699227549475383">Organisation (O)</translation>
@@ -1577,10 +1621,10 @@ This will otherwise be blocked by your privacy settings. This will allow the con
<translation id="7004583254764674281">Use Windows Hello to confirm cards faster</translation>
<translation id="7006930604109697472">Send anyway</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Resize settings</translation>
<translation id="7014741021609395734">Zoom level</translation>
<translation id="7016992613359344582">These charges could be one-off or recurring and may not be obvious.</translation>
<translation id="7029809446516969842">Passwords</translation>
+<translation id="7030436163253143341">Certificate is not valid</translation>
<translation id="7031646650991750659">Which Google Play apps you have installed</translation>
<translation id="7050187094878475250">You attempted to reach <ph name="DOMAIN" />, but the server presented a certificate whose validity period is too long to be trustworthy.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{This card can't be saved at the moment}other{These cards can't be saved at the moment}}</translation>
@@ -1650,12 +1694,14 @@ Additional details:
<translation id="7300012071106347854">Cobalt blue</translation>
<translation id="7302712225291570345">'<ph name="TEXT" />'</translation>
<translation id="7304030187361489308">High</translation>
+<translation id="7305756307268530424">Start slower</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Connection help</translation>
<translation id="7323804146520582233">Hide the '<ph name="SECTION" />' section</translation>
<translation id="733354035281974745">Device local account override</translation>
<translation id="7333654844024768166">You just entered your password on a deceptive site. Chromium recommends going to <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> and other sites where you use this password and changing it now.</translation>
<translation id="7334320624316649418">&amp;Redo reorder</translation>
+<translation id="7337248890521463931">Show more lines</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>
@@ -1663,6 +1709,7 @@ Additional details:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Command Line</translation>
<translation id="7359588939039777303">Ads blocked.</translation>
+<translation id="7363096869660964304">However, you aren’t invisible. Going Incognito doesn’t hide your browsing from your employer, your Internet service provider, or the websites that you visit.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, press Tab then Enter to add and manage addresses in Chrome settings</translation>
<translation id="7365849542400970216">Know your device use?</translation>
<translation id="7372973238305370288">search result</translation>
@@ -1673,7 +1720,9 @@ Additional details:
<translation id="7378594059915113390">Media controls</translation>
<translation id="7378627244592794276">Nope</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Not applicable</translation>
<translation id="7390545607259442187">Confirm Card</translation>
+<translation id="7392089738299859607">Update address</translation>
<translation id="7399802613464275309">Safety check</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Your <ph name="DEVICE_NAME" /> is managed</translation>
@@ -1688,6 +1737,7 @@ Additional details:
&lt;li&gt;Visit the &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome help centre&lt;/a&gt; to find out how to permanently remove the software from your computer
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Lovely</translation>
<translation id="7416351320495623771">Manage passwords...</translation>
<translation id="7419106976560586862">Profile Path</translation>
<translation id="7437289804838430631">Add contact info</translation>
@@ -1703,7 +1753,7 @@ Additional details:
<translation id="7481312909269577407">Forward</translation>
<translation id="7485870689360869515">No data found.</translation>
<translation id="7495528107193238112">This content is blocked. Contact the site owner to fix the issue.</translation>
-<translation id="7498234416455752244">Keep editing</translation>
+<translation id="7498193950643227031">It may behave unexpectedly if resized. You can now limit the ability to resize apps in <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">You just entered your password on a deceptive site. Chromium recommends checking your saved passwords for <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> and other sites where you use this password now.</translation>
<translation id="7508255263130623398">Returned policy device ID is empty or doesn't match current device ID</translation>
<translation id="7508870219247277067">Avocado green</translation>
@@ -1723,6 +1773,7 @@ Additional details:
<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="755279583747225797">Trial is active</translation>
<translation id="7552846755917812628">Try the following tips:</translation>
<translation id="7554475479213504905">Reload and show anyway</translation>
<translation id="7554791636758816595">New Tab</translation>
@@ -1741,7 +1792,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, press tab, then enter to view and manage your passwords in Chrome settings</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="7616645509853975347">Your administrator has turned on Chrome Enterprise Connectors on your browser. These connectors have access to some of your data.</translation>
<translation id="7619838219691048931">End sheet</translation>
<translation id="762844065391966283">One at a time</translation>
@@ -1806,13 +1856,12 @@ Additional details:
<translation id="782886543891417279">The Wi-Fi that you are using (<ph name="WIFI_NAME" />) may require you to visit its login page.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{None}=1{1 app (<ph name="EXAMPLE_APP_1" />)}=2{2 apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">However, you aren’t invisible. Going incognito doesn’t hide your browsing from your employer, your Internet service provider or the websites that you visit.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Open files with file type associations.</translation>
<translation id="7862185352068345852">Leave site?</translation>
<translation id="7865448901209910068">Best speed</translation>
<translation id="7874263914261512992">You just entered your password on a deceptive site. Chrome recommends checking your saved passwords for <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> and other sites where you use this password now.</translation>
<translation id="7878562273885520351">Your password may be compromised</translation>
+<translation id="7880146494886811634">Save address</translation>
<translation id="7882421473871500483">Brown</translation>
<translation id="7887683347370398519">Check your CVC and try again</translation>
<translation id="7887885240995164102">Enter picture-in-picture</translation>
@@ -1820,6 +1869,7 @@ Additional details:
<translation id="7894280532028510793">If spelling is correct, <ph name="BEGIN_LINK" />try running network Diagnostics<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Unknown</translation>
+<translation id="793209273132572360">Update address?</translation>
<translation id="7932579305932748336">Coat</translation>
<translation id="79338296614623784">Enter a valid phone number</translation>
<translation id="7934052535022478634">Payment complete</translation>
@@ -1890,6 +1940,7 @@ Additional details:
<translation id="8175796834047840627">Chrome is offering to save your cards in your Google Account because you are signed in. You can change this behaviour in settings.</translation>
<translation id="8176440868214972690">The administrator of this device has sent some info to the following websites, like settings or policies.</translation>
<translation id="8184538546369750125">Use global default (Allow)</translation>
+<translation id="8193086767630290324">Actions taken with data flagged as confidential</translation>
<translation id="8194797478851900357">&amp;Undo Move</translation>
<translation id="8201077131113104583">Invalid update URL for extension with ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Order summary</translation>
@@ -1912,6 +1963,7 @@ Additional details:
<translation id="8249296373107784235">Abort</translation>
<translation id="8249320324621329438">Last fetched:</translation>
<translation id="8253091569723639551">Billing address required</translation>
+<translation id="8257387598443225809">This app is designed for mobile</translation>
<translation id="825929999321470778">Show all saved passwords</translation>
<translation id="8261506727792406068">Delete</translation>
<translation id="8262952874573525464">Edge stitch bottom</translation>
@@ -2035,7 +2087,6 @@ Additional details:
<translation id="8719528812645237045">Multiple punch top</translation>
<translation id="8725066075913043281">Try again</translation>
<translation id="8726549941689275341">Page size:</translation>
-<translation id="8728672262656704056">You’ve gone incognito</translation>
<translation id="8730621377337864115">Done</translation>
<translation id="8731544501227493793">Manage passwords button; press enter to view and manage your passwords in Chrome settings</translation>
<translation id="8734529307927223492">Your <ph name="DEVICE_TYPE" /> is managed by <ph name="MANAGER" /></translation>
@@ -2112,6 +2163,7 @@ Additional details:
<translation id="9020542370529661692">This page has been translated to <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Invalid)</translation>
+<translation id="9030265603405983977">Monochrome</translation>
<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>
@@ -2135,6 +2187,7 @@ Additional details:
<translation id="91108059142052966">Administrator policy disables screen sharing with <ph name="APPLICATION_TITLE" /> when confidential content is visible</translation>
<translation id="9114524666733003316">Confirming card...</translation>
<translation id="9114581008513152754">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" />Learn more<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Fresh</translation>
<translation id="9119042192571987207">Uploaded</translation>
<translation id="9128016270925453879">Policies is loaded</translation>
<translation id="9128870381267983090">Connect to network</translation>
@@ -2153,6 +2206,7 @@ Additional details:
<translation id="9170848237812810038">&amp;Undo</translation>
<translation id="9171296965991013597">Leave app?</translation>
<translation id="9173282814238175921">Single document/New sheet</translation>
+<translation id="9173995187295789444">Scanning for Bluetooth devices...</translation>
<translation id="917450738466192189">Server's certificate is invalid.</translation>
<translation id="9174917557437862841">Tab switch button, press Enter to switch to this tab</translation>
<translation id="9179703756951298733">Manage your payments and credit card info in Chrome settings</translation>
diff --git a/chromium/components/strings/components_strings_es-419.xtb b/chromium/components/strings/components_strings_es-419.xtb
index debe9061d95..ca7219a447a 100644
--- a/chromium/components/strings/components_strings_es-419.xtb
+++ b/chromium/components/strings/components_strings_es-419.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Selecciona el permiso para <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Deshacer Reorganizar</translation>
+<translation id="1123753900084781868">El Subtitulado instantáneo no está disponible en este momento</translation>
<translation id="1125573121925420732">Las advertencias pueden ser habituales cuando las páginas web actualizan su seguridad. Esto debería mejorar pronto.</translation>
<translation id="112840717907525620">Caché de política correcta</translation>
<translation id="1130564665089811311">Botón Traducir página: presiona Intro para traducir esta página con Google Traductor</translation>
@@ -74,6 +75,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="1240347957665416060">Tu nombre de dispositivo</translation>
<translation id="124116460088058876">Más idiomas</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Negrita</translation>
<translation id="1250759482327835220">Para realizar pagos de forma más rápida la próxima vez, guarda tu tarjeta, nombre y dirección de facturación en tu Cuenta de Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sincronizados)</translation>
<translation id="1256368399071562588">&lt;p&gt;Si intentas visitar un sitio web y no se abre, primero intenta corregir el error con estos pasos para solucionar problemas:&lt;/p&gt;
@@ -156,6 +158,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="1476595624592550506">Cambia la contraseña</translation>
<translation id="1484290072879560759">Elegir dirección de envío</translation>
<translation id="1492194039220927094">Notificaciones push de políticas:</translation>
+<translation id="1495677929897281669">Volver a la pestaña</translation>
<translation id="1501859676467574491">Mostrar tarjetas de tu Cuenta de Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Se muestra este error si usas un portal Wi-Fi donde debes acceder para establecer la conexión.&lt;/p&gt;
&lt;p&gt;Para solucionar el error, haz clic en &lt;strong&gt;Conectar&lt;/strong&gt; en la página que deseas abrir.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="1532118530259321453">Esta página dice</translation>
<translation id="153384715582417236">Eso es todo por ahora</translation>
<translation id="1536390784834419204">Traducir la página</translation>
+<translation id="1539840569003678498">Fecha de envío del informe:</translation>
<translation id="154408704832528245">Elegir dirección de entrega</translation>
<translation id="1549470594296187301">JavaScript debe estar habilitado para usar esta función.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="1682696192498422849">Borde corto primero</translation>
<translation id="168693727862418163">No se pudo validar el valor de esta política con su esquema y, por lo tanto, se ignorará.</translation>
<translation id="168841957122794586">El certificado del servidor contiene una clave criptográfica no segura.</translation>
+<translation id="1696290444144917273">Ver detalles de la tarjeta virtual</translation>
<translation id="1697532407822776718">¡Listo!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{El servidor no logró comprobar si el dominio es <ph name="DOMAIN" />; supuestamente, el certificado de seguridad entra en vigencia mañana. Es posible que esto se deba a una configuración incorrecta o a que un atacante haya interceptado la conexión.}other{El servidor no logró comprobar si el dominio es <ph name="DOMAIN" />; supuestamente, el certificado de seguridad entra en vigencia en # días. Es posible que esto se deba a una configuración incorrecta o a que un atacante haya interceptado la conexión.}}</translation>
<translation id="1710259589646384581">SO</translation>
+<translation id="1711234383449478798">Se ignoró porque <ph name="POLICY_NAME" /> no se estableció como <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> desea almacenar de forma permanente los datos en tu computadora local</translation>
<translation id="1713628304598226412">Bandeja 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Buzón 3</translation>
<translation id="1718029547804390981">El documento es demasiado grande para contener anotaciones</translation>
<translation id="1721424275792716183">* El campo es obligatorio</translation>
+<translation id="1727613060316725209">El certificado es válido</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>
<translation id="173080396488393970">No se acepta este tipo de tarjeta</translation>
@@ -242,7 +249,6 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Intenta ejecutar el Diagnóstico de red de Windows<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">El servidor <ph name="ORIGIN" /> al que te diriges estableció un encabezado donde se indica que se aplica una política de origen a todas las solicitudes. Sin embargo, el encabezado tiene un formato no válido, por lo que el navegador no puede cumplir con tu solicitud para <ph name="SITE" />. Los operadores de sitios pueden usar políticas de origen para configurar la seguridad y otras propiedades de un sitio.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Actualiza tu frase de contraseña de sincronización.</translation>
<translation id="1787142507584202372">Tus pestañas abiertas aparecen aquí</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />: hay varias acciones disponibles; presiona Tab para elegir una</translation>
@@ -275,6 +281,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="1919345977826869612">Anuncios</translation>
<translation id="1919367280705858090">Cómo obtener ayuda con un mensaje de error específico</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ninguno}=1{1 sitio}other{# sitios}}</translation>
+<translation id="1924727005275031552">Nuevas</translation>
<translation id="1945968466830820669">Es posible que hayas perdido el acceso a la cuenta de tu organización o sufrido un robo de identidad. Chromium te recomienda que cambies la contraseña ahora.</translation>
<translation id="1947454675006758438">Grapa en la esquina superior derecha</translation>
<translation id="1958218078413065209">Tu puntuación más alta es <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="2042213636306070719">Bandeja 7</translation>
<translation id="204357726431741734">Accede a tu Cuenta de Google para usar las contraseñas guardadas allí</translation>
<translation id="2053111141626950936">No se traducirán las páginas en <ph name="LANGUAGE" />.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Si habilitas este control y su estado es "activado", Chrome determinará el grupo grande de personas, o "cohorte", al que más se asemeja tu actividad de navegación reciente. Los anunciantes podrán seleccionar los anuncios para el grupo, y tu actividad de navegación se mantendrá privada en tu dispositivo. Tu grupo se actualiza todos los días.}=1{Si habilitas este control y su estado es "activado", Chrome determinará el grupo grande de personas, o "cohorte", al que más se asemeja tu actividad de navegación reciente. Los anunciantes podrán seleccionar los anuncios para el grupo, y tu actividad de navegación se mantendrá privada en tu dispositivo. Tu grupo se actualiza todos los días.}other{Si habilitas este control y su estado es "activado", Chrome determinará el grupo grande de personas, o "cohorte", al que más se asemeja tu actividad de navegación reciente. Los anunciantes podrán seleccionar los anuncios para el grupo, y tu actividad de navegación se mantendrá privada en tu dispositivo. Tu grupo se actualiza cada {NUM_DAYS} días.}}</translation>
<translation id="2053553514270667976">Código Postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugerencia}other{# sugerencias}}</translation>
<translation id="2071692954027939183">Se bloquearon las notificaciones de forma automática porque no sueles permitirlas.</translation>
<translation id="2079545284768500474">Deshacer</translation>
<translation id="20817612488360358">Se ha establecido la configuración de proxy del sistema, pero también se ha especificado una configuración explícita de proxy.</translation>
<translation id="2082238445998314030">Resultado <ph name="RESULT_NUMBER" /> de <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Guardar…</translation>
<translation id="2088086323192747268">Botón Administrar la sincronización: presiona Intro para administrar en la configuración de Chrome qué información sincronizar</translation>
<translation id="2091887806945687916">Sonido</translation>
<translation id="2094505752054353250">El dominio no coincide.</translation>
@@ -375,6 +384,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="2317259163369394535"><ph name="DOMAIN" /> requiere un nombre de usuario y una contraseña.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, fecha de vencimiento: <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Configuración controlada por tu administrador</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> desea sincronizarse</translation>
<translation id="2344028582131185878">Descargas automáticas</translation>
<translation id="2346319942568447007">Imagen que copiaste</translation>
<translation id="2354001756790975382">Otros favoritos</translation>
@@ -382,8 +392,10 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="2355395290879513365">Es posible que los atacantes vean las imágenes que observas en este sitio y las modifiquen para engañarte.</translation>
<translation id="2356070529366658676">Preguntar</translation>
<translation id="2357481397660644965"><ph name="DEVICE_MANAGER" /> y <ph name="ACCOUNT_MANAGER" /> administran tu dispositivo y tu cuenta, respectivamente.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{En menos de un día}=1{En un día}other{En {NUM_DAYS} días}}</translation>
<translation id="2359629602545592467">Varias</translation>
<translation id="2359808026110333948">Continuar</translation>
+<translation id="2359961752320758691">Se aplicó tu número de tarjeta virtual.</translation>
<translation id="2367567093518048410">Nivel</translation>
<translation id="2372464001869762664">Después de que confirmes la información, se compartirán con este sitio los detalles de la tarjeta registrados en tu Cuenta de Google. Puedes consultar el código CVC en los detalles de tu cuenta de Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="239429038616798445">El método de envío no está disponible. Prueba otro método.</translation>
<translation id="2396249848217231973">&amp;Deshacer Eliminar</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Antiguas</translation>
<translation id="2413528052993050574">Este servidor no pudo probar que su dominio es <ph name="DOMAIN" /> y se podría revocar el certificado de seguridad. Es posible que esto se deba a una configuración incorrecta o a que un atacante interceptó la conexión.</translation>
<translation id="2414886740292270097">Oscuro</translation>
<translation id="2438874542388153331">Perforación cuádruple a la derecha</translation>
@@ -421,10 +434,10 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="2521385132275182522">Grapa en la esquina inferior derecha</translation>
<translation id="2523886232349826891">Solo se guardará en este dispositivo</translation>
<translation id="2524461107774643265">Agregar más información</translation>
-<translation id="2526590354069164005">Escritorio</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{y 1 más}other{y # más}}</translation>
<translation id="2536110899380797252">Agregar dirección</translation>
<translation id="2539524384386349900">Detectar</translation>
+<translation id="2541219929084442027">Una vez que cierres todas las pestañas de incógnito, las páginas que hayas visitado en ese modo no se guardarán en el historial del navegador, en la lista de cookies ni en el historial de búsqueda. Sí se guardarán los archivos que descargues y los favoritos que crees.</translation>
<translation id="2544644783021658368">Documento único</translation>
<translation id="254947805923345898">El valor de la política no es válido.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> envió una respuesta no válida.</translation>
@@ -444,6 +457,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="2629325967560697240">Para acceder al nivel más alto de seguridad de Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />activa la protección mejorada<ph name="END_ENHANCED_PROTECTION_LINK" />.</translation>
<translation id="2634124572758952069">No se pudo encontrar la dirección IP del servidor de <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Estado:</translation>
+<translation id="264810637653812429">No se encontraron dispositivos compatibles.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />: presiona Tab y, luego, Intro para borrar tu historial de navegación, cookies, memoria caché y más en la configuración de Chrome</translation>
<translation id="2650446666397867134">Se denegó el acceso al archivo.</translation>
@@ -488,6 +502,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<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="2807052079800581569">Posición de la imagen en el eje Y</translation>
+<translation id="2820957248982571256">Buscando…</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>
@@ -495,6 +510,8 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">Este sitio muestra anuncios intrusivos o engañosos.</translation>
+<translation id="287596039013813457">Friendly</translation>
+<translation id="2876489322757410363">Saldrás del modo Incógnito para pagar mediante una aplicación externa. ¿Deseas continuar?</translation>
<translation id="2878197950673342043">Plegado de póster</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Ubicación de ventanas</translation>
@@ -544,7 +561,6 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />: presiona Tab y, luego, Intro para realizar la Verificación de seguridad en la configuración de Chrome</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>
<translation id="306573536155379004">Comenzó el juego.</translation>
<translation id="3080254622891793721">Gráfico</translation>
<translation id="3086579638707268289">Se supervisa tu actividad en la Web</translation>
@@ -567,7 +583,6 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="315504272643575312"><ph name="MANAGER" /> administra tu cuenta.</translation>
<translation id="3157931365184549694">Restaurar</translation>
<translation id="3162559335345991374">Es posible que la red Wi-Fi que estás usando requiera que visites la página de acceso.</translation>
-<translation id="3167968892399408617">Una vez que cierres todas las pestañas de incógnito, las páginas que hayas visitado en ese modo no se guardarán en el historial del navegador, en la lista de cookies ni en el historial de búsquedas. Se guardarán los archivos que descargues y los favoritos que crees.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Isla</translation>
<translation id="3176929007561373547">Comprueba la configuración del proxy o comunícate con tu
@@ -594,10 +609,12 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<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="3249845759089040423">Groovy</translation>
<translation id="3252266817569339921">Francés</translation>
<translation id="3266793032086590337">Valor (en conflicto)</translation>
<translation id="3268451620468152448">Pestañas abiertas</translation>
<translation id="3270847123878663523">&amp;Deshacer Reorganizar</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> desea conectarse</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Tu organización, <ph name="ENROLLMENT_DOMAIN" />, envió parte de la información, como la configuración o las políticas, a los siguientes sitios web.</translation>
<translation id="3282497668470633863">Agregar el nombre en la tarjeta</translation>
@@ -650,6 +667,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="3428151540071562330">Una o más URI de plantillas del servidor de la política DnsOverHttpsTemplates no son válidas, por lo que no se usarán.</translation>
<translation id="3431636764301398940">Guardar esta tarjeta para este dispositivo</translation>
<translation id="3432601291244612633">Cerrar página</translation>
+<translation id="3435738964857648380">Seguridad</translation>
<translation id="3435896845095436175">Habilitar</translation>
<translation id="3438829137925142401">Usar las contraseñas guardadas en tu Cuenta de Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -692,7 +710,10 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="3584299510153766161">Perforación doble en la parte inferior</translation>
<translation id="3586931643579894722">Ocultar detalles</translation>
<translation id="3587738293690942763">Medio</translation>
+<translation id="3590643883886679995">Los datos de acceso se almacenarán en este dispositivo cuando salgas del modo Incógnito.</translation>
+<translation id="359126217934908072">Mes/Año:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Puedes restablecer tu grupo en cualquier momento. Te llevará aproximadamente un día unirte a un grupo nuevo.}=1{Puedes restablecer tu grupo en cualquier momento. Te llevará aproximadamente un día unirte a un grupo nuevo.}other{Puedes restablecer tu grupo en cualquier momento. Te llevará {NUM_DAYS} días unirte a un grupo nuevo.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">El administrador bloqueó la aplicación</translation>
<translation id="3608932978122581043">Orientación de la entrada</translation>
@@ -701,13 +722,13 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="3615877443314183785">Ingresa una fecha de vencimiento válida</translation>
<translation id="36224234498066874">Borrar datos de navegación...</translation>
<translation id="362276910939193118">Mostrar historial completo</translation>
-<translation id="3625635938337243871">Los datos de acceso se almacenarán en este dispositivo cuando salgas del modo Incógnito.</translation>
<translation id="3630155396527302611">Si ya está incluido como un programa con permiso para acceder a la red, intenta
quitarlo de la lista y agregarlo de nuevo.</translation>
<translation id="3630699740441428070">Los administradores de este dispositivo configuraron tu conexión de red, lo cual puede permitirles ver tu tráfico de red, incluido los sitios web que visitas.</translation>
<translation id="3631244953324577188">Biométricos</translation>
<translation id="3633738897356909127">Botón Actualizar Chrome: presiona Intro para actualizar Chrome desde la configuración del navegador</translation>
<translation id="3634530185120165534">Bandeja 5</translation>
+<translation id="3637662659967048211">Guardar en la Cuenta de Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplicación:</translation>
<translation id="3650584904733503804">Validación correcta</translation>
@@ -748,6 +769,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="3781428340399460090">Fucsia</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Dispositivos Bluetooth</translation>
+<translation id="3787675388804467730">Número de la tarjeta virtual</translation>
<translation id="3787705759683870569">Vencimiento: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Tamaño 16</translation>
<translation id="3789841737615482174">Instalar</translation>
@@ -767,6 +789,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="3841184659773414994">Controladores de archivos</translation>
<translation id="385051799172605136">Atrás</translation>
<translation id="3858027520442213535">Actualizar fecha y hora</translation>
+<translation id="3881478300875776315">Mostrar menos líneas</translation>
<translation id="3884278016824448484">Hay un identificador de dispositivo en conflicto.</translation>
<translation id="3885155851504623709">Distrito</translation>
<translation id="388632593194507180">Se detectó una supervisión</translation>
@@ -792,6 +815,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="397105322502079400">Calculando...</translation>
<translation id="3973234410852337861">Se bloqueó <ph name="HOST_NAME" /></translation>
<translation id="3973357910713125165">Botón Realizar Verificación de seguridad de Chrome: presiona Intro para realizar la Verificación de seguridad en la configuración de Chrome</translation>
+<translation id="3986705137476756801">Desactivar el Subtitulado instantáneo por el momento</translation>
<translation id="3987405730340719549">Chrome determinó que este sitio podría ser falso o fraudulento.
Si consideras que se trata de un error, visita https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -883,13 +907,14 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="4275830172053184480">Reiniciar tu dispositivo</translation>
<translation id="4277028893293644418">Restablecer contraseña</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="4287885627794386150">Apta para pruebas, pero no está activada</translation>
<translation id="4297502707443874121">Miniatura para la página <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Expandir</translation>
<translation id="4300675098767811073">Perforaciones múltiples a la derecha</translation>
<translation id="4302514097724775343">Presiona el dinosaurio para jugar</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">No se pudo acceder a tu archivo</translation>
-<translation id="4305817255990598646">Cambiar</translation>
+<translation id="4306529830550717874">¿Quieres guardar la dirección?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloquear (predeterminado)</translation>
<translation id="4314815835985389558">Administrar la sincronización</translation>
@@ -916,6 +941,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="4377125064752653719">Intentaste acceder a <ph name="DOMAIN" />, pero el emisor anuló el certificado que presentó el servidor. Esto significa que no se debe confiar en absoluto en las credenciales de seguridad que presentó el servidor. Te puedes estar comunicando con un atacante.</translation>
<translation id="4378154925671717803">Teléfono</translation>
<translation id="4390472908992056574">Borde</translation>
+<translation id="4406883609789734330">Subtitulado instantáneo</translation>
<translation id="4406896451731180161">resultados de búsqueda</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Ingresaste tu contraseña en un sitio engañoso. Chrome te recomienda cambiar esta contraseña ahora en <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> y otros sitios donde la uses.</translation>
@@ -928,7 +954,6 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<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="4464826014807964867">Sitios web con información de tu organización</translation>
-<translation id="4466881336512663640">Se perderán los cambios del formulario. ¿Confirmas que deseas continuar?</translation>
<translation id="4476953670630786061">Este formulario no es seguro. Se desactivó la función Autocompletar.</translation>
<translation id="4477350412780666475">Siguiente pista</translation>
<translation id="4482953324121162758">Este sitio no se traducirá.</translation>
@@ -962,6 +987,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="4594403342090139922">&amp;Deshacer Eliminar</translation>
<translation id="4597348597567598915">Tamaño 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Impactful</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Devolución de dinero vinculada</translation>
<translation id="4636930964841734540">Información</translation>
@@ -981,6 +1007,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Lado</translation>
+<translation id="4702656508969495934">El Subtitulado instantáneo está visible; utiliza el botón de cambio de ventana para enfocar</translation>
<translation id="4708268264240856090">Se interrumpió la conexión</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Ejecución del Diagnóstico de red de Windows<ph name="END_LINK" /></translation>
@@ -994,6 +1021,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="4738601419177586157">Sugerencia de búsqueda: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Administrar contraseñas…</translation>
<translation id="4744603770635761495">Ruta ejecutable</translation>
+<translation id="4749011317274908093">Estás en modo Incógnito</translation>
<translation id="4750917950439032686">Tu información (p. ej., contraseñas o números de tarjetas de crédito) es privada cuando se envía a este sitio.</translation>
<translation id="4756388243121344051">&amp;Historial</translation>
<translation id="4758311279753947758">Agregar información de contacto</translation>
@@ -1023,6 +1051,8 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="4813512666221746211">Error de red</translation>
<translation id="4816492930507672669">Ajustar a la página</translation>
<translation id="4819347708020428563">¿Quieres editar anotaciones en la vista predeterminada?</translation>
+<translation id="4825507807291741242">Powerful</translation>
+<translation id="4838327282952368871">Dreamy</translation>
<translation id="484462545196658690">Automático</translation>
<translation id="4850886885716139402">Ver</translation>
<translation id="485316830061041779">Alemán</translation>
@@ -1072,7 +1102,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="5023310440958281426">Revisa las políticas del administrador.</translation>
<translation id="5029568752722684782">Borrar la copia</translation>
<translation id="5030338702439866405">Proporcionada por</translation>
-<translation id="503069730517007720">Se requiere un certificado raíz para "<ph name="SOFTWARE_NAME" />", pero no está instalado. Tu administrador de IT debe analizar las instrucciones de configuración de "<ph name="SOFTWARE_NAME" />" para corregir este problema. <ph name="FURTHER_EXPLANATION" /></translation>
+<translation id="503069730517007720">Se requiere un certificado raíz para "<ph name="SOFTWARE_NAME" />", pero no está instalado. Tu administrador de TI debe analizar las instrucciones de configuración de "<ph name="SOFTWARE_NAME" />" para corregir este problema. <ph name="FURTHER_EXPLANATION" /></translation>
<translation id="5031870354684148875">Acerca de Google Traductor</translation>
<translation id="503498442187459473"><ph name="HOST" /> desea usar tu cámara y micrófono</translation>
<translation id="5039762155821394373">Tamaño de fuente</translation>
@@ -1159,6 +1189,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="5314967030527622926">Creador de cuadernillos</translation>
<translation id="5316812925700871227">Girar a la izquierda</translation>
<translation id="5317780077021120954">Guardar</translation>
+<translation id="5321288445143113935">Maximizado</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> de <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Seleccionar información de contacto</translation>
<translation id="5327248766486351172">Nombre</translation>
@@ -1166,11 +1197,13 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="5332219387342487447">Método de envío</translation>
<translation id="5333022057423422993">Chrome encontró la contraseña que acabas de usar en una violación de la seguridad de los datos. Para proteger tus cuentas, te recomendamos revisar las contraseñas guardadas.</translation>
<translation id="5334013548165032829">Registros detallados del sistema</translation>
+<translation id="5334145288572353250">¿Deseas guardar la dirección?</translation>
<translation id="5340250774223869109">Se bloqueó la app</translation>
<translation id="534295439873310000">Dispositivos NFC</translation>
<translation id="5344579389779391559">Es posible que esta página intente cobrarte dinero</translation>
<translation id="5355557959165512791">No puedes visitar <ph name="SITE" /> ahora porque este certificado se revocó. 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="536296301121032821">Error al almacenar la configuración de la política</translation>
+<translation id="5363309033720083897">Puerto en serie que permite tu administrador</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="5386426401304769735">La cadena del certificado de este sitio web contiene un certificado que se firmó con SHA-1.</translation>
@@ -1179,6 +1212,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="5398772614898833570">Anuncios bloqueados</translation>
<translation id="5400836586163650660">Gris</translation>
<translation id="540969355065856584">Este servidor no pudo demostrar que se trata de <ph name="DOMAIN" />; el certificado de seguridad no es válido en este momento. Esto puede deberse a una configuración incorrecta o a un ataque que intercepta tu conexión.</translation>
+<translation id="541143247543991491">Nube (de todo el sistema)</translation>
<translation id="541416427766103491">Apilador 4</translation>
<translation id="5421136146218899937">Borrar datos de navegación...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> quiere enviarte notificaciones</translation>
@@ -1192,6 +1226,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="5455374756549232013">Marca de tiempo de política incorrecta</translation>
<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="5463625433003343978">Buscando dispositivos…</translation>
<translation id="5469868506864199649">Italiano</translation>
<translation id="5470861586879999274">&amp;Rehacer Editar</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1241,7 +1276,6 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="5624120631404540903">Administrar contraseñas</translation>
<translation id="5629630648637658800">Error al cargar la configuración de la política</translation>
<translation id="5631439013527180824">Token de administración de dispositivos no válido</translation>
-<translation id="5632627355679805402">Tus datos se encriptaron con tu <ph name="BEGIN_LINK" />contraseña de Google<ph name="END_LINK" /> el <ph name="TIME" />. Ingresa la contraseña para iniciar la sincronización.</translation>
<translation id="5633066919399395251">Es posible que los atacantes que actualmente se encuentran en <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> intenten instalar programas peligrosos en tu computadora para robar o borrar información (p. ej., fotos, contraseñas, mensajes y tarjetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Se bloqueó contenido engañoso.</translation>
<translation id="5644090287519800334">Cambio en el eje X del lado 1 de la imagen</translation>
@@ -1280,12 +1314,12 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="5785756445106461925">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 la apariencia de la página.</translation>
<translation id="5786044859038896871">¿Deseas llenar los campos con la información de tu tarjeta?</translation>
<translation id="578633867165174378">Chrome encontró la contraseña que acabas de usar en una violación de la seguridad de los datos. Te recomendamos cambiar la contraseña ahora.</translation>
-<translation id="5798290721819630480">¿Descartas los cambios?</translation>
<translation id="5803412860119678065">¿Deseas llenar los campos con la información de tu tarjeta <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Permisos</translation>
<translation id="5804427196348435412">Usar dispositivos con NFC</translation>
<translation id="5810442152076338065">Tu conexión a <ph name="DOMAIN" /> está encriptada con un conjunto de cifrado obsoleto.</translation>
<translation id="5813119285467412249">&amp;Rehacer Agregar</translation>
+<translation id="5817918615728894473">Sincronizar</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Cuando realices un pago, el importe se debitará de esta tarjeta, pero el sitio no tendrá acceso a su número real. Para reforzar la seguridad, se generará un CVC temporal.}other{Cuando realices un pago, el importe se debitará de la tarjeta que selecciones, pero el sitio no tendrá acceso a su número real. Para reforzar la seguridad, se generará un CVC temporal.}}</translation>
<translation id="5826507051599432481">Nombre común (CN)</translation>
<translation id="5838278095973806738">No debes ingresar información confidencial en este sitio (p. ej., contraseñas o tarjetas de crédito), ya que los atacantes podrían robarla.</translation>
@@ -1293,6 +1327,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="5855253129151731373">El nombre de host de este sitio es similar al de <ph name="LOOKALIKE_DOMAIN" />. A veces, los atacantes hacen cambios sutiles y difíciles de detectar en el nombre del dominio para imitar sitios.
Si consideras que se trata de un error, visita https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Desactivado</translation>
<translation id="5862579898803147654">Apilador 8</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>
@@ -1309,6 +1344,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="5913377024445952699">Se pausó la captura de pantalla</translation>
<translation id="59174027418879706">Habilitado</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 en uso}other{# en uso}}</translation>
<translation id="5921185718311485855">Sí</translation>
<translation id="5921639886840618607">¿Quieres guardar la tarjeta en la Cuenta de Google?</translation>
<translation id="5922853866070715753">Ya casi</translation>
@@ -1328,6 +1364,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="5989320800837274978">No se especifican servidores proxy fijos ni URL de secuencias de comandos .pac.</translation>
<translation id="5992691462791905444">Plegado en Z para ingeniería</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultados para "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Clásico</translation>
<translation id="6008122969617370890">Orden de N a 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Revisa tus contraseñas</translation>
@@ -1349,6 +1386,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="6045164183059402045">Plantilla de imposición</translation>
<translation id="6047233362582046994">Si comprendes los riesgos de seguridad, puedes <ph name="BEGIN_LINK" />visitar este sitio<ph name="END_LINK" /> antes de que se hayan quitado las apps dañinas.</translation>
<translation id="6047927260846328439">Es posible que este contenido trate de engañarte para que instales software o reveles información personal. <ph name="BEGIN_LINK" />Mostrar de todos modos<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Mantén presionada la tecla |<ph name="ACCELERATOR" />| para salir de la pantalla completa</translation>
<translation id="6049488691372270142">Entrega de páginas</translation>
<translation id="6051221802930200923">No puedes visitar <ph name="SITE" /> ahora porque el sitio web usa la fijación de certificados. 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="6051898664905071243">Cantidad de páginas:</translation>
@@ -1365,6 +1403,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<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>
<translation id="6116338172782435947">Ver el texto y las imágenes copiados en el portapapeles</translation>
<translation id="6120179357481664955">¿Recuerdas tu ID de IUP?</translation>
+<translation id="6123290840358279103">Ver la tarjeta virtual</translation>
<translation id="6124432979022149706">Conectores de Chrome Enterprise</translation>
<translation id="6146055958333702838">Revisa los cables y reinicia los routers, módems u otros dispositivos
de red que estés usando.</translation>
@@ -1401,6 +1440,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="6289939620939689042">Color de la página</translation>
<translation id="6290238015253830360">Tus artículos sugeridos aparecen aquí</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Se está deteniendo el Asistente de Google en Chrome</translation>
<translation id="6305205051461490394">No se puede acceder a <ph name="URL" />.</translation>
<translation id="6312113039770857350">Página web no disponible</translation>
@@ -1426,6 +1466,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="6390200185239044127">Plegado en Z a la mitad</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Una política del administrador no permite pegar contenido de <ph name="ORIGIN_NAME" /> en esta ubicación</translation>
+<translation id="6398765197997659313">Salir de pantalla completa</translation>
<translation id="6401136357288658127">Esta política es obsoleta. En su lugar, debes usar la política <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Editar marcador</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1438,7 +1479,6 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="6428450836711225518">Verifica tu número de teléfono</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">Descartar</translation>
<translation id="6440503408713884761">Ignorada</translation>
<translation id="6443406338865242315">Las extensiones y complementos que instalaste</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1481,6 +1521,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="6624427990725312378">Información de contacto</translation>
<translation id="6626291197371920147">Agregar un número de tarjeta válido</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Búsqueda</translation>
+<translation id="6630043285902923878">Buscando dispositivos USB…</translation>
<translation id="6630809736994426279">Es posible que los atacantes que actualmente se encuentran en <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> intenten instalar programas peligrosos en tu Mac para robar o borrar información (p. ej., fotos, contraseñas, mensajes y tarjetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Borrar</translation>
@@ -1496,6 +1537,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<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="6687335167692595844">Se necesita el tamaño de la fuente</translation>
+<translation id="6688743156324860098">Actualizar…</translation>
<translation id="6689249931105087298">Relativo con la compresión de puntos negros</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="6698381487523150993">Creado:</translation>
@@ -1511,6 +1553,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<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="6753269504797312559">Valor de la política</translation>
<translation id="6757797048963528358">El dispositivo se suspendió.</translation>
+<translation id="6767985426384634228">¿Deseas actualizar la dirección?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violeta</translation>
@@ -1533,6 +1576,7 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome simplificó esta página para facilitar la lectura. Chrome recuperó la página original a través de una conexión no segura.</translation>
<translation id="6891596781022320156">No se admite el nivel de políticas.</translation>
+<translation id="6895143722905299846">Número virtual:</translation>
<translation id="6895330447102777224">Tu tarjeta se confirmó</translation>
<translation id="6897140037006041989">Usuario-agente</translation>
<translation id="6898699227549475383">Organización (O)</translation>
@@ -1568,10 +1612,10 @@ De lo contrario, la configuración de privacidad bloqueará esta acción. Esto p
<translation id="7004583254764674281">Usa Windows Hello para verificar las tarjetas más rápido</translation>
<translation id="7006930604109697472">Enviar de todas formas</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Configuración de cambio de tamaño</translation>
<translation id="7014741021609395734">Nivel del zoom</translation>
<translation id="7016992613359344582">Estos cargos pueden ser únicos o recurrentes, y es posible que no sean evidentes.</translation>
<translation id="7029809446516969842">Contraseñas</translation>
+<translation id="7030436163253143341">El certificado no es válido</translation>
<translation id="7031646650991750659">Las apps de Google Play que instalaste</translation>
<translation id="7050187094878475250">Intentaste acceder a <ph name="DOMAIN" />, pero el certificado de servidor tenía un período de validez demasiado extenso para ser fiable.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{No se puede guardar esta tarjeta en este momento}other{No se pueden guardar estas tarjetas en este momento}}</translation>
@@ -1641,12 +1685,14 @@ Detalles adicionales:
<translation id="7300012071106347854">Azul cobalto</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Alto</translation>
+<translation id="7305756307268530424">Empezar más despacio</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Ayuda con la conexión</translation>
<translation id="7323804146520582233">Ocultar la sección "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Se anuló la cuenta local del dispositivo</translation>
<translation id="7333654844024768166">Ingresaste tu contraseña en un sitio engañoso. Chromium te recomienda cambiar esta contraseña ahora en <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> y otros sitios donde la uses.</translation>
<translation id="7334320624316649418">&amp;Rehacer Reorganizar</translation>
+<translation id="7337248890521463931">Mostrar más líneas</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>
@@ -1654,6 +1700,7 @@ Detalles adicionales:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Línea de comandos</translation>
<translation id="7359588939039777303">Se bloquearon anuncios.</translation>
+<translation id="7363096869660964304">Sin embargo, no vas a pasar completamente desapercibido. El modo Incógnito no oculta tu información de navegación de un empleador, del proveedor de servicios de Internet ni de los sitios web que visitas.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />: presiona Tab y, luego, Intro para agregar y administrar direcciones en la configuración de Chrome</translation>
<translation id="7365849542400970216">¿Permites conocer el uso de tu dispositivo?</translation>
<translation id="7372973238305370288">resultado de búsqueda</translation>
@@ -1664,7 +1711,9 @@ Detalles adicionales:
<translation id="7378594059915113390">Controles de contenido multimedia</translation>
<translation id="7378627244592794276">No</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">No aplicable</translation>
<translation id="7390545607259442187">Confirmar tarjeta</translation>
+<translation id="7392089738299859607">Actualizar dirección</translation>
<translation id="7399802613464275309">Verificación de seguridad</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Tu <ph name="DEVICE_NAME" /> está administrado</translation>
@@ -1679,6 +1728,7 @@ Detalles adicionales:
&lt;li&gt;Visita el &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centro de ayuda de Chrome&lt;/a&gt; para obtener información sobre cómo quitar el software de forma permanente de tu computadora.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Lovely</translation>
<translation id="7416351320495623771">Administrar contraseñas…</translation>
<translation id="7419106976560586862">Ruta del perfil</translation>
<translation id="7437289804838430631">Agregar información de contacto</translation>
@@ -1694,7 +1744,7 @@ Detalles adicionales:
<translation id="7481312909269577407">Reenviar</translation>
<translation id="7485870689360869515">No se encontró ningún dato.</translation>
<translation id="7495528107193238112">Este contenido está bloqueado. Comunícate con el propietario del sitio para solucionar el problema.</translation>
-<translation id="7498234416455752244">Seguir editando</translation>
+<translation id="7498193950643227031">Es posible que, si se cambia su tamaño, se comporte de forma inesperada. En <ph name="SETTINGS" />, ahora puedes limitar la capacidad de cambiar el tamaño de las apps.</translation>
<translation id="7503664977220660814">Ingresaste tu contraseña en un sitio engañoso. Chromium te recomienda revisar las contraseñas guardadas para <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> y otros sitios donde uses esta contraseña.</translation>
<translation id="7508255263130623398">El ID de dispositivo de la política que se muestra está vacío o no coincide con el ID de dispositivo actual</translation>
<translation id="7508870219247277067">Verde aguacate</translation>
@@ -1714,6 +1764,7 @@ Detalles adicionales:
<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="755279583747225797">La prueba está activada</translation>
<translation id="7552846755917812628">Intenta las siguientes sugerencias:</translation>
<translation id="7554475479213504905">Volver a cargar y mostrar de todas formas</translation>
<translation id="7554791636758816595">Nueva pestaña</translation>
@@ -1732,7 +1783,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />: presiona Tab y, luego, Intro para ver y administrar tus contraseñas en la configuración de Chrome</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="7616645509853975347">Tu administrador activó Chrome Enterprise Connectors en tu navegador. Estos conectores tienen acceso a algunos de tus datos.</translation>
<translation id="7619838219691048931">Final de la hoja</translation>
<translation id="762844065391966283">Uno por vez</translation>
@@ -1797,13 +1847,12 @@ Detalles adicionales:
<translation id="782886543891417279">Es posible que la red Wi-Fi que estás usando (<ph name="WIFI_NAME" />) requiera que visites la página de acceso.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ninguna}=1{1 app (<ph name="EXAMPLE_APP_1" />)}=2{2 apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Sin embargo, no eres invisible. El modo de navegación de incógnito no oculta tu navegación de tu empleador, de tu proveedor de servicios de Internet, ni de los sitios web que visitas.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Abrir archivos asociados a tipos específicos</translation>
<translation id="7862185352068345852">¿Deseas abandonar el sitio?</translation>
<translation id="7865448901209910068">Mejor velocidad</translation>
<translation id="7874263914261512992">Ingresaste tu contraseña en un sitio engañoso. Chrome te recomienda revisar las contraseñas guardadas para <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> y otros sitios donde uses esta contraseña.</translation>
<translation id="7878562273885520351">Es posible que tu contraseña esté en peligro</translation>
+<translation id="7880146494886811634">Guardar dirección</translation>
<translation id="7882421473871500483">Marrón</translation>
<translation id="7887683347370398519">Verifica tu CVC y vuelve a intentarlo.</translation>
<translation id="7887885240995164102">Ingresar al modo de pantalla en pantalla</translation>
@@ -1811,6 +1860,7 @@ Detalles adicionales:
<translation id="7894280532028510793">Si no hay errores, <ph name="BEGIN_LINK" />prueba ejecutar el diagnóstico de red<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Desconocido</translation>
+<translation id="793209273132572360">¿Quieres actualizar la dirección?</translation>
<translation id="7932579305932748336">Recubrimiento</translation>
<translation id="79338296614623784">Ingresa un número de teléfono válido</translation>
<translation id="7934052535022478634">Se completó el pago</translation>
@@ -1870,7 +1920,7 @@ Detalles adicionales:
<translation id="8103161714697287722">Forma de pago</translation>
<translation id="8105368624971345109">Desactivar</translation>
<translation id="8118489163946903409">Forma de pago</translation>
-<translation id="8127301229239896662">"<ph name="SOFTWARE_NAME" />" no se instaló correctamente en tu computadora o red. Solicita al administrador de IT que corrija este problema.</translation>
+<translation id="8127301229239896662">"<ph name="SOFTWARE_NAME" />" no se instaló correctamente en tu computadora o red. Solicita al administrador de TI que corrija este problema.</translation>
<translation id="8128526133099929547">Ingresaste tu contraseña en un sitio engañoso. Chrome te recomienda que la cambies ahora en <ph name="WEBSITE_1" /> y otros sitios donde la uses.</translation>
<translation id="8131740175452115882">Confirmar</translation>
<translation id="8148608574971654810">Versión de PDF:</translation>
@@ -1881,6 +1931,7 @@ Detalles adicionales:
<translation id="8175796834047840627">Como accediste a tu cuenta, Chrome te ofrece guardar tus tarjetas en tu Cuenta de Google. Puedes modificar este comportamiento en la configuración.</translation>
<translation id="8176440868214972690">El administrador de este dispositivo envió parte de la información, como la configuración o las políticas, a los siguientes sitios web.</translation>
<translation id="8184538546369750125">Usar configuración global predeterminada (Permitir)</translation>
+<translation id="8193086767630290324">Las acciones que se toman con los datos marcados como confidenciales</translation>
<translation id="8194797478851900357">&amp;Deshacer Mover</translation>
<translation id="8201077131113104583">URL de actualización no válida para la extensión con ID "<ph name="EXTENSION_ID" />"</translation>
<translation id="8202097416529803614">Resumen del pedido</translation>
@@ -1903,6 +1954,7 @@ Detalles adicionales:
<translation id="8249296373107784235">Anular</translation>
<translation id="8249320324621329438">Se obtuvo por última vez:</translation>
<translation id="8253091569723639551">Se requiere una dirección de facturación</translation>
+<translation id="8257387598443225809">Esta app está diseñada para dispositivos móviles</translation>
<translation id="825929999321470778">Mostrar todas las contraseñas guardadas</translation>
<translation id="8261506727792406068">Borrar</translation>
<translation id="8262952874573525464">Costura del borde inferior</translation>
@@ -2027,7 +2079,6 @@ Detalles adicionales:
<translation id="8719528812645237045">Perforaciones múltiples en la parte superior</translation>
<translation id="8725066075913043281">Intentar nuevamente</translation>
<translation id="8726549941689275341">Tamaño de la página:</translation>
-<translation id="8728672262656704056">Estás en modo incógnito</translation>
<translation id="8730621377337864115">Listo</translation>
<translation id="8731544501227493793">Botón Administrar contraseñas: presiona Intro para ver y administrar tus contraseñas en la configuración de Chrome</translation>
<translation id="8734529307927223492"><ph name="MANAGER" /> administra tu dispositivo <ph name="DEVICE_TYPE" /></translation>
@@ -2104,6 +2155,7 @@ Detalles adicionales:
<translation id="9020542370529661692">Esta página se tradujo al <ph name="TARGET_LANGUAGE" />.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(No válido)</translation>
+<translation id="9030265603405983977">Monochrome</translation>
<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>
@@ -2127,6 +2179,7 @@ Detalles adicionales:
<translation id="91108059142052966">La política del administrador inhabilita el uso compartido de pantallas con <ph name="APPLICATION_TITLE" /> cuando se muestra contenido confidencial</translation>
<translation id="9114524666733003316">Confirmando tarjeta…</translation>
<translation id="9114581008513152754">Este navegador no está administrado por una empresa ni por otra organización. Es posible que la actividad de este dispositivo se administre fuera de Chrome. <ph name="BEGIN_LINK" />Más información<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Fresh</translation>
<translation id="9119042192571987207">Subido</translation>
<translation id="9128016270925453879">Se cargaron las políticas</translation>
<translation id="9128870381267983090">Conectarse a una red</translation>
@@ -2145,6 +2198,7 @@ Detalles adicionales:
<translation id="9170848237812810038">&amp;Deshacer</translation>
<translation id="9171296965991013597">¿Deseas salir de la app?</translation>
<translation id="9173282814238175921">Documento único/hoja nueva</translation>
+<translation id="9173995187295789444">Buscando dispositivos Bluetooth…</translation>
<translation id="917450738466192189">El certificado del servidor no es válido.</translation>
<translation id="9174917557437862841">Botón para cambiar de pestaña; presiona Intro para cambiar a esta pestaña</translation>
<translation id="9179703756951298733">Administra tus pagos y la información de las tarjetas de crédito en la configuración de Chrome</translation>
diff --git a/chromium/components/strings/components_strings_es.xtb b/chromium/components/strings/components_strings_es.xtb
index 3824dd53412..27299614099 100644
--- a/chromium/components/strings/components_strings_es.xtb
+++ b/chromium/components/strings/components_strings_es.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Si se selecciona, Chrome almacenará una copia de tu tarjeta en este dispositivo para completar formularios más rápidamente.</translation>
<translation id="1110994991967754504">Seleccionar permiso de <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Deshacer reorganización</translation>
+<translation id="1123753900084781868">Subtítulos automáticos no está disponible en estos momentos</translation>
<translation id="1125573121925420732">Es probable que se muestren advertencias mientras se actualiza la seguridad de los sitios web, pero pronto se solucionará.</translation>
<translation id="112840717907525620">Caché de política correcta</translation>
<translation id="1130564665089811311">Botón Traducir página, pulsa Intro para traducir esta página con el Traductor de Google</translation>
@@ -74,6 +75,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="1240347957665416060">El nombre de tu dispositivo</translation>
<translation id="124116460088058876">Más idiomas</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Negrita</translation>
<translation id="1250759482327835220">Para pagar más rápido la próxima vez, guarda tu tarjeta, tu nombre y tu dirección de facturación en tu cuenta de Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sincronizados)</translation>
<translation id="1256368399071562588">&lt;p&gt;Si intentas acceder a un sitio web y no se abre, prueba estos pasos para solucionar problemas:&lt;/p&gt;
@@ -156,6 +158,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="1476595624592550506">Cambia la contraseña</translation>
<translation id="1484290072879560759">Seleccionar dirección de envío</translation>
<translation id="1492194039220927094">Envío de políticas:</translation>
+<translation id="1495677929897281669">Volver a la pestaña</translation>
<translation id="1501859676467574491">Mostrar las tarjetas de tu cuenta de Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Este error se muestra si utilizas un portal Wi‑Fi en el que debes iniciar sesión antes de conectarte a Internet.&lt;/p&gt;
&lt;p&gt;Para solucionar el problema, haz clic en &lt;strong&gt;Conectar&lt;/strong&gt; en la página que intentas abrir.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="1532118530259321453">Esta página dice</translation>
<translation id="153384715582417236">Eso es todo por ahora</translation>
<translation id="1536390784834419204">Traducir página</translation>
+<translation id="1539840569003678498">Informe enviado:</translation>
<translation id="154408704832528245">Seleccionar dirección de entrega</translation>
<translation id="1549470594296187301">JavaScript debe estar habilitado para utilizar esta función.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="1682696192498422849">Borde corto primero</translation>
<translation id="168693727862418163">No se ha podido validar el valor de esta política con su esquema y se ignorará.</translation>
<translation id="168841957122794586">El certificado del servidor contiene una clave criptográfica no segura.</translation>
+<translation id="1696290444144917273">Ver los detalle de la tarjeta virtual</translation>
<translation id="1697532407822776718">¡Listo!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Este servidor no ha podido demostrar que es <ph name="DOMAIN" />; supuestamente, su certificado de seguridad es válido a partir de mañana. Este problema puede deberse a una configuración incorrecta o a que un atacante ha interceptado la conexión.}other{Este servidor no ha podido demostrar que es <ph name="DOMAIN" />; supuestamente, su certificado de seguridad es válido dentro de # días. Este problema puede deberse a una configuración incorrecta o a que un atacante ha interceptado la conexión.}}</translation>
<translation id="1710259589646384581">Sistema operativo</translation>
+<translation id="1711234383449478798">Ignorada porque no se le ha asignado el valor <ph name="VALUE" /> a <ph name="POLICY_NAME" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> quiere almacenar datos de forma permanente en tu ordenador local</translation>
<translation id="1713628304598226412">Bandeja 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Buzón de correo 3</translation>
<translation id="1718029547804390981">El documento es demasiado grande para poder añadir anotaciones</translation>
<translation id="1721424275792716183">* El campo es obligatorio</translation>
+<translation id="1727613060316725209">El certificado es válido</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>
<translation id="173080396488393970">No se admite este tipo de tarjeta</translation>
@@ -246,7 +253,6 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
tu solicitud de ir a <ph name="SITE" />. Los operadores de sitios
pueden usar las políticas de origen para configurar la seguridad y otras propiedades de un sitio web.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Actualiza tu frase de contraseña de sincronización.</translation>
<translation id="1787142507584202372">Las pestañas abiertas aparecen aquí</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, hay varias acciones disponibles, pulsa Tabulador para desplazarte entre ellas</translation>
@@ -279,6 +285,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="1919345977826869612">Anuncios</translation>
<translation id="1919367280705858090">Solucionar un error específico</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ninguno}=1{1 sitio web}other{# sitios}}</translation>
+<translation id="1924727005275031552">Nueva</translation>
<translation id="1945968466830820669">Podrías perder el acceso a la cuenta de tu organización o tener problemas de suplantación de identidad. Chromium te recomienda que cambies tu contraseña ahora.</translation>
<translation id="1947454675006758438">Grapado en la parte superior derecha</translation>
<translation id="1958218078413065209">Tu mejor puntuación es <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="2042213636306070719">Bandeja 7</translation>
<translation id="204357726431741734">Inicia sesión para poder usar las contraseñas guardadas en tu cuenta de Google</translation>
<translation id="2053111141626950936">No se traducirán las páginas en <ph name="LANGUAGE" />.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Cuando el control está habilitado y en estado activo, Chrome determina qué grupo de personas o "cohorte" encaja mejor con tu actividad de navegación reciente. Los anunciantes pueden seleccionar anuncios para el grupo, y tu actividad de navegación se conservará en tu dispositivo y será privada. Tu grupo se actualiza todos los días.}=1{Cuando el control está habilitado y en estado activo, Chrome determina qué grupo de personas o "cohorte" encaja mejor con tu actividad de navegación reciente. Los anunciantes pueden seleccionar anuncios para el grupo, y tu actividad de navegación se conservará en tu dispositivo y será privada. Tu grupo se actualiza todos los días.}other{Cuando el control está habilitado y en estado activo, Chrome determina qué grupo de personas o "cohorte" encaja mejor con tu actividad de navegación reciente. Los anunciantes pueden seleccionar anuncios para el grupo, y tu actividad de navegación se conservará en tu dispositivo y será privada. Tu grupo se actualiza cada {NUM_DAYS} días.}}</translation>
<translation id="2053553514270667976">Código postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{Una sugerencia}other{# sugerencias}}</translation>
<translation id="2071692954027939183">Se han bloqueado automáticamente las notificaciones porque no las sueles permitir.</translation>
<translation id="2079545284768500474">Deshacer</translation>
<translation id="20817612488360358">Se ha establecido la configuración del proxy del sistema, pero también se han especificado ajustes de proxy explícitos.</translation>
<translation id="2082238445998314030">Resultado <ph name="RESULT_NUMBER" /> de <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Guardar…</translation>
<translation id="2088086323192747268">Botón Gestionar sincronización, pulsa Intro para gestionar la información que sincronizas en la configuración de Chrome</translation>
<translation id="2091887806945687916">Sonido</translation>
<translation id="2094505752054353250">El dominio no coincide</translation>
@@ -379,6 +388,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="2317259163369394535"><ph name="DOMAIN" /> necesita un nombre de usuario y una contraseña.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />; fecha de caducidad: <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Configuración controlada por el administrador</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> quiere emparejarse</translation>
<translation id="2344028582131185878">Descargas automáticas</translation>
<translation id="2346319942568447007">Imagen copiada</translation>
<translation id="2354001756790975382">Otros marcadores</translation>
@@ -386,8 +396,10 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="2355395290879513365">Es posible que los atacantes puedan ver las imágenes que ves en este sitio web y que las modifiquen para engañarte.</translation>
<translation id="2356070529366658676">Preguntar</translation>
<translation id="2357481397660644965"><ph name="DEVICE_MANAGER" /> gestiona tu dispositivo y <ph name="ACCOUNT_MANAGER" /> gestiona tu cuenta.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Dentro de menos de un día}=1{Dentro de un día}other{Dentro de {NUM_DAYS} días}}</translation>
<translation id="2359629602545592467">Varias</translation>
<translation id="2359808026110333948">Continuar</translation>
+<translation id="2359961752320758691">Número de tu tarjeta virtual aplicado.</translation>
<translation id="2367567093518048410">Nivel</translation>
<translation id="2372464001869762664">Una vez que confirmes esta acción, la información de la tarjeta de tu cuenta de Google se compartirá con este sitio. Busca el CVC en los datos de tu cuenta de Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="239429038616798445">Este método de envío no está disponible. Selecciona otro.</translation>
<translation id="2396249848217231973">&amp;Deshacer eliminación</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Antigua</translation>
<translation id="2413528052993050574">Este servidor no ha podido probar que su dominio es <ph name="DOMAIN" /> y se podría rechazar su certificado de seguridad. Este problema puede deberse a una configuración incorrecta o a que un atacante haya interceptado la conexión.</translation>
<translation id="2414886740292270097">Oscuro</translation>
<translation id="2438874542388153331">Perforado cuádruple en la parte derecha</translation>
@@ -425,10 +438,10 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="2521385132275182522">Grapado en la parte inferior derecha</translation>
<translation id="2523886232349826891">Solo se guardará en este dispositivo</translation>
<translation id="2524461107774643265">Añade más información</translation>
-<translation id="2526590354069164005">Escritorio</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{y 1 más}other{y # más}}</translation>
<translation id="2536110899380797252">Añadir dirección</translation>
<translation id="2539524384386349900">Detectar</translation>
+<translation id="2541219929084442027">Las páginas que veas en las pestañas de incógnito no se guardarán en el historial del navegador, en el almacén de cookies ni en el historial de búsqueda una vez que hayas cerrado todas tus pestañas de incógnito. Se mantendrán los archivos que descargues o los marcadores que crees.</translation>
<translation id="2544644783021658368">Documento individual</translation>
<translation id="254947805923345898">El valor de la política no es válido.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ha enviado una respuesta no válida.</translation>
@@ -448,6 +461,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="2629325967560697240">Para disfrutar del máximo nivel de seguridad en Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />activa la protección mejorada<ph name="END_ENHANCED_PROTECTION_LINK" />.</translation>
<translation id="2634124572758952069">No se ha podido encontrar la dirección IP del servidor de <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Estado:</translation>
+<translation id="264810637653812429">No se han podido encontrar dispositivos compatibles.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, pulsa Tabulador y, a continuación, Intro para borrar el historial de navegación, las cookies, la caché y más desde la configuración de Chrome</translation>
<translation id="2650446666397867134">Acceso al archivo denegado</translation>
@@ -494,6 +508,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<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="2807052079800581569">Posición de la imagen en el eje Y</translation>
+<translation id="2820957248982571256">Buscando...</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>
@@ -501,6 +516,8 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="2850739647070081192">Invite (sobre)</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="2859806420264540918">Este sitio web muestra anuncios invasivos o engañosos.</translation>
+<translation id="287596039013813457">Amistosa</translation>
+<translation id="2876489322757410363">Saldrás del modo de incógnito para pagar en una aplicación externa. ¿Quieres continuar?</translation>
<translation id="2878197950673342043">Plegado en cruz</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Ubicación de ventanas</translation>
@@ -550,7 +567,6 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="3060227939791841287">C9 (sobre)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, pulsa Tabulador y después Intro para realizar una comprobación de seguridad en la configuración de Chrome</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>
<translation id="306573536155379004">Juego iniciado.</translation>
<translation id="3080254622891793721">Gráfico</translation>
<translation id="3086579638707268289">Se está vigilando tu actividad en la Web</translation>
@@ -573,7 +589,6 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="315504272643575312"><ph name="MANAGER" /> gestiona tu cuenta.</translation>
<translation id="3157931365184549694">Restaurar</translation>
<translation id="3162559335345991374">La red Wi-Fi que estás utilizando puede requerir que accedas a su página de inicio de sesión.</translation>
-<translation id="3167968892399408617">Las páginas que aparezcan en las pestañas de incógnito no se guardarán en el historial del navegador, en el almacén de cookies ni en el historial de búsquedas una vez que hayas cerrado todas tus pestañas de incógnito. Se mantendrán los archivos que descargues o los marcadores que crees.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Isla</translation>
<translation id="3176929007561373547">Comprueba la configuración del proxy o ponte en contacto con el administrador de red para
@@ -599,10 +614,12 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<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="3249845759089040423">Estilosa</translation>
<translation id="3252266817569339921">Francés</translation>
<translation id="3266793032086590337">Valor (en conflicto)</translation>
<translation id="3268451620468152448">Pestañas abiertas</translation>
<translation id="3270847123878663523">&amp;Deshacer reorganización</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> quiere conectarse</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Tu organización, <ph name="ENROLLMENT_DOMAIN" />, ha enviado algunos datos (como ajustes o políticas) a los siguientes sitios web.</translation>
<translation id="3282497668470633863">Añadir un nombre de la tarjeta</translation>
@@ -655,6 +672,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="3428151540071562330">Una o varias URI de plantilla del servidor DnsOverHttpsTemplates no son válidas y no se utilizarán.</translation>
<translation id="3431636764301398940">Guardar esta tarjeta en el dispositivo</translation>
<translation id="3432601291244612633">Cerrar página</translation>
+<translation id="3435738964857648380">Seguridad</translation>
<translation id="3435896845095436175">Habilitar</translation>
<translation id="3438829137925142401">Usar las contraseñas guardadas en tu cuenta de Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="3584299510153766161">Perforado doble en la parte inferior</translation>
<translation id="3586931643579894722">Ocultar detalles</translation>
<translation id="3587738293690942763">Medio</translation>
+<translation id="3590643883886679995">Los datos de inicio de sesión se almacenarán en este dispositivo cuando salgas del modo de incógnito.</translation>
+<translation id="359126217934908072">Mes/año:</translation>
<translation id="3592413004129370115">Italian (sobre)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Puedes restablecer tu grupo en cualquier momento. Se tarda alrededor de un día en unirse a un nuevo grupo.}=1{Puedes restablecer tu grupo en cualquier momento. Se tarda alrededor de un día en unirse a un nuevo grupo.}other{Puedes restablecer tu grupo en cualquier momento. Se tardan {NUM_DAYS} días en unirse a un nuevo grupo.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Tu administrador ha bloqueado esta aplicación</translation>
<translation id="3608932978122581043">Orientación de entrada</translation>
@@ -706,13 +727,13 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="3615877443314183785">Introduce una fecha de vencimiento válida</translation>
<translation id="36224234498066874">Borrar datos de navegación...</translation>
<translation id="362276910939193118">Mostrar historial completo</translation>
-<translation id="3625635938337243871">Los datos de inicio de sesión se almacenarán en este dispositivo cuando salgas del modo de incógnito.</translation>
<translation id="3630155396527302611">Si ya está incluido como programa autorizado para acceder a la red,
elimínalo de la lista y vuelve a añadirlo.</translation>
<translation id="3630699740441428070">Los administradores de este dispositivo han configurado tu conexión de red y es posible que esto les permita ver tu tráfico de red (incluidos los sitios web que visitas).</translation>
<translation id="3631244953324577188">Biometría</translation>
<translation id="3633738897356909127">Botón Actualizar Chrome, pulsa Intro para actualizar Chrome desde la configuración de Chrome</translation>
<translation id="3634530185120165534">Bandeja 5</translation>
+<translation id="3637662659967048211">Guardar en tu cuenta de Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplicación:</translation>
<translation id="3650584904733503804">Validación correcta</translation>
@@ -753,6 +774,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="3781428340399460090">Rosa fucsia</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Dispositivos Bluetooth</translation>
+<translation id="3787675388804467730">Número de tarjeta virtual</translation>
<translation id="3787705759683870569">Vencimiento: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Tamaño 16</translation>
<translation id="3789841737615482174">Instalar</translation>
@@ -772,6 +794,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="3841184659773414994">Controladores de archivos</translation>
<translation id="385051799172605136">Volver</translation>
<translation id="3858027520442213535">Actualizar fecha y hora</translation>
+<translation id="3881478300875776315">Mostrar menos líneas</translation>
<translation id="3884278016824448484">Identificador de dispositivo en conflicto</translation>
<translation id="3885155851504623709">Municipio</translation>
<translation id="388632593194507180">Vigilancia detectada</translation>
@@ -797,6 +820,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="397105322502079400">Calculando...</translation>
<translation id="3973234410852337861">La página <ph name="HOST_NAME" /> está bloqueada</translation>
<translation id="3973357910713125165">Botón Realizar comprobación de seguridad de Chrome, pulsa Intro para hacer una comprobación de seguridad en la configuración de Chrome</translation>
+<translation id="3986705137476756801">Desactivar Subtítulos automáticos por el momento</translation>
<translation id="3987405730340719549">Chrome ha determinado que este sitio web podría ser falso o fraudulento.
Si crees que puede tratarse de un error, ve a https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="4275830172053184480">Reiniciar tu dispositivo</translation>
<translation id="4277028893293644418">Cambiar contraseña</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="4287885627794386150">Disponible para pruebas, pero no está activo</translation>
<translation id="4297502707443874121">Miniatura de la página <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Mostrar</translation>
<translation id="4300675098767811073">Perforado múltiple en la parte derecha</translation>
<translation id="4302514097724775343">Toca el dinosaurio para jugar</translation>
<translation id="4302965934281694568">Chou3 (sobre)</translation>
<translation id="4305666528087210886">No se ha podido acceder al archivo</translation>
-<translation id="4305817255990598646">Cambiar</translation>
+<translation id="4306529830550717874">¿Guardar dirección?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloquear (predeterminado)</translation>
<translation id="4314815835985389558">Gestionar sincronización</translation>
@@ -926,6 +951,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="4377125064752653719">Has intentado acceder a <ph name="DOMAIN" />, pero el emisor ha revocado el certificado mostrado por el servidor, lo que significa que las credenciales de seguridad presentadas por el servidor no son de confianza. Es posible que hayas accedido a la página de un atacante.</translation>
<translation id="4378154925671717803">Teléfono</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Subtítulos automáticos</translation>
<translation id="4406896451731180161">resultados de la búsqueda</translation>
<translation id="4408413947728134509">Cookies: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Acabas de introducir tu contraseña en un sitio web engañoso. Chrome te recomienda que accedas a <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> y otros sitios en los que uses esta contraseña y que la cambies ahora.</translation>
@@ -938,7 +964,6 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<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="4464826014807964867">Sitios web con información de tu organización</translation>
-<translation id="4466881336512663640">Se perderán los cambios realizados en el formulario. ¿Seguro que quieres continuar?</translation>
<translation id="4476953670630786061">Este formulario no es seguro. Autocompletar se ha desactivado.</translation>
<translation id="4477350412780666475">Pista siguiente</translation>
<translation id="4482953324121162758">Este sitio web no se traducirá.</translation>
@@ -972,6 +997,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="4594403342090139922">&amp;Deshacer eliminación</translation>
<translation id="4597348597567598915">Tamaño 8</translation>
<translation id="4600854749408232102">C6/C5 (sobre)</translation>
+<translation id="4606870351894164739">Impactante</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Devolución de dinero asociada</translation>
<translation id="4636930964841734540">Información</translation>
@@ -991,6 +1017,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="4691835149146451662">Architecture-A (sobre)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Cara</translation>
+<translation id="4702656508969495934">Subtítulos automáticos visibles; utiliza el botón de cambio de ventana para enfocarlos</translation>
<translation id="4708268264240856090">Se ha interrumpido la conexión</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Ejecutar Diagnósticos de red de Windows<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="4738601419177586157">Sugerencia de búsqueda de <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Gestionar contraseñas…</translation>
<translation id="4744603770635761495">Ruta del ejecutable</translation>
+<translation id="4749011317274908093">Estás en modo de incógnito</translation>
<translation id="4750917950439032686">Tu información (por ejemplo, tus contraseñas o números de tarjeta de crédito) es privada cuando se envía a este sitio web.</translation>
<translation id="4756388243121344051">&amp;Historial</translation>
<translation id="4758311279753947758">Añadir información de contacto</translation>
@@ -1033,6 +1061,8 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="4813512666221746211">Error de red</translation>
<translation id="4816492930507672669">Ajustar a página</translation>
<translation id="4819347708020428563">¿Editar anotaciones en la vista predeterminada?</translation>
+<translation id="4825507807291741242">Potente</translation>
+<translation id="4838327282952368871">De ensueño</translation>
<translation id="484462545196658690">Automático</translation>
<translation id="4850886885716139402">Ver</translation>
<translation id="485316830061041779">Alemán</translation>
@@ -1085,7 +1115,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="503069730517007720">Se necesita un certificado raíz para "<ph name="SOFTWARE_NAME" />", pero no está instalado. El administrador de TI debe comprobar las instrucciones de configuración de "<ph name="SOFTWARE_NAME" />" para solucionar este problema. <ph name="FURTHER_EXPLANATION" /></translation>
<translation id="5031870354684148875">Informacion del Traductor de Google</translation>
<translation id="503498442187459473"><ph name="HOST" /> quiere utilizar la cámara y el micrófono</translation>
-<translation id="5039762155821394373">Tamaño de la fuente</translation>
+<translation id="5039762155821394373">Tamaño de fuente</translation>
<translation id="5039804452771397117">Permitir</translation>
<translation id="5040262127954254034">Privacidad</translation>
<translation id="5043480802608081735">Enlace copiado</translation>
@@ -1169,6 +1199,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="5314967030527622926">Creación de cuadernillo</translation>
<translation id="5316812925700871227">Girar hacia la izquierda</translation>
<translation id="5317780077021120954">Guardar</translation>
+<translation id="5321288445143113935">Maximizada</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> de <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Seleccionar información de contacto</translation>
<translation id="5327248766486351172">Nombre</translation>
@@ -1176,11 +1207,13 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="5332219387342487447">Método de envío</translation>
<translation id="5333022057423422993">Chrome ha detectado que la contraseña que acabas de usar se ha visto expuesta en una quiebra de seguridad de datos. Para proteger tus cuentas, te recomendamos que compruebes las contraseñas que tengas guardadas.</translation>
<translation id="5334013548165032829">Registros detallados del sistema</translation>
+<translation id="5334145288572353250">¿Guardar dirección?</translation>
<translation id="5340250774223869109">Se ha bloqueado la aplicación</translation>
<translation id="534295439873310000">Dispositivos NFC</translation>
<translation id="5344579389779391559">Es posible que esta página intente aplicar algún cargo</translation>
<translation id="5355557959165512791">No puedes acceder a <ph name="SITE" /> en este momento porque su certificado se ha revocado. 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="536296301121032821">Error al almacenar la configuración de la política</translation>
+<translation id="5363309033720083897">Puerto serie permitido por tu administrador</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="5386426401304769735">La cadena de certificados de este sitio web contiene un certificado firmado con SHA-1.</translation>
@@ -1189,6 +1222,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="5398772614898833570">Anuncios bloqueados</translation>
<translation id="5400836586163650660">Gris</translation>
<translation id="540969355065856584">Este servidor no ha podido probar que su dominio es <ph name="DOMAIN" />, ya que su certificado de seguridad no es válido en este momento. Esto puede deberse a una configuración incorrecta o a que un atacante haya interceptado la conexión.</translation>
+<translation id="541143247543991491">Nube (todo el sistema)</translation>
<translation id="541416427766103491">Apilador 4</translation>
<translation id="5421136146218899937">Borrar datos de navegación...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> quiere enviarte notificaciones</translation>
@@ -1202,6 +1236,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="5455374756549232013">Marca de tiempo de política incorrecta</translation>
<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="5463625433003343978">Buscando dispositivos...</translation>
<translation id="5469868506864199649">Italiano</translation>
<translation id="5470861586879999274">&amp;Rehacer edición</translation>
<translation id="5478437291406423475">B6/C4 (sobre)</translation>
@@ -1251,7 +1286,6 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="5624120631404540903">Gestionar contraseñas</translation>
<translation id="5629630648637658800">Error al cargar la configuración de la política</translation>
<translation id="5631439013527180824">Token de administración de dispositivos no válido</translation>
-<translation id="5632627355679805402">Tus datos están cifrados con tu <ph name="BEGIN_LINK" />contraseña de Google<ph name="END_LINK" /> desde el <ph name="TIME" />. Introdúcela para iniciar la sincronización.</translation>
<translation id="5633066919399395251">Es posible que los atacantes que se encuentren en <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> intenten instalar programas peligrosos en tu ordenador para robar o eliminar tu información (por ejemplo, fotos, contraseñas, mensajes y tarjetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Contenido engañoso bloqueado.</translation>
<translation id="5644090287519800334">Cara 1 del desplazamiento de la imagen en el eje X</translation>
@@ -1290,12 +1324,12 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="5785756445106461925">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 aspecto de la página.</translation>
<translation id="5786044859038896871">¿Quieres rellenar la información de la tarjeta?</translation>
<translation id="578633867165174378">Chrome ha detectado que la contraseña que acabas de usar se ha visto expuesta en una quiebra de seguridad de datos. Te recomendamos que la cambies ahora.</translation>
-<translation id="5798290721819630480">¿Descartar cambios?</translation>
<translation id="5803412860119678065">¿Quieres rellenar la información de <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Permisos</translation>
<translation id="5804427196348435412">Usar dispositivos NFC</translation>
<translation id="5810442152076338065">Tu conexión con <ph name="DOMAIN" /> está cifrada con un conjunto de cifrado obsoleto.</translation>
<translation id="5813119285467412249">&amp;Rehacer acción de añadir</translation>
+<translation id="5817918615728894473">Emparejar</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Cuando pagues, se aplicarán cargos en esta tarjeta, pero el número real no se compartirá con este sitio web. Para una mayor seguridad, se generará un CVC temporal.}other{Cuando pagues, se aplicarán cargos en la tarjeta que selecciones, pero el número real no se compartirá con este sitio web. Para una mayor seguridad, se generará un CVC temporal.}}</translation>
<translation id="5826507051599432481">Nombre común (CN)</translation>
<translation id="5838278095973806738">No deberías introducir información confidencial en este sitio web (por ejemplo, contraseñas o tarjetas de crédito) porque los atacantes podrían robarla.</translation>
@@ -1303,6 +1337,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="5855253129151731373">El nombre de host de este sitio web se parece al de <ph name="LOOKALIKE_DOMAIN" />. Los atacantes a veces imitan a otros sitios haciendo pequeños cambios difíciles de ver en el nombre del dominio.
Si crees que puede tratarse de un error, ve a https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Desactivado</translation>
<translation id="5862579898803147654">Apilador 8</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>
@@ -1319,6 +1354,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="5913377024445952699">Grabación de pantalla pausada</translation>
<translation id="59174027418879706">Habilitado</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 en uso}other{# en uso}}</translation>
<translation id="5921185718311485855">Activado</translation>
<translation id="5921639886840618607">¿Quieres guardar la tarjeta en tu cuenta de Google?</translation>
<translation id="5922853866070715753">Casi hemos acabado</translation>
@@ -1338,6 +1374,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="5989320800837274978">No se han especificado servidores proxy fijos ni una URL de secuencia de comandos .pac.</translation>
<translation id="5992691462791905444">Plegado en Z asimétrico</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultados para "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Clásico</translation>
<translation id="6008122969617370890">Orden de N a 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Comprueba tus contraseñas</translation>
@@ -1359,6 +1396,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="6045164183059402045">Plantilla de imposición</translation>
<translation id="6047233362582046994">Si entiendes los riesgos para tu seguridad, puedes <ph name="BEGIN_LINK" />acceder a este sitio web<ph name="END_LINK" /> antes de que se hayan eliminado las aplicaciones dañinas.</translation>
<translation id="6047927260846328439">Es posible que este contenido intente engañarte para que instales software o reveles información personal. <ph name="BEGIN_LINK" />Mostrar de todos modos<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Mantén pulsado |<ph name="ACCELERATOR" />| para salir del modo pantalla completa</translation>
<translation id="6049488691372270142">Entrega de página</translation>
<translation id="6051221802930200923">No puedes acceder a <ph name="SITE" /> en este momento porque el sitio web utiliza la fijación de certificados. 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="6051898664905071243">Número de páginas:</translation>
@@ -1375,6 +1413,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<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>
<translation id="6116338172782435947">Ver el texto y las imágenes que se hayan copiado en el portapapeles</translation>
<translation id="6120179357481664955">¿Recuerdas tu ID de UPI?</translation>
+<translation id="6123290840358279103">Ver tarjeta virtual</translation>
<translation id="6124432979022149706">Conectores de Chrome Enterprise</translation>
<translation id="6146055958333702838">Comprueba los cables y reinicia los routers, los módems o cualquier otro dispositivo
de red que estés utilizando.</translation>
@@ -1411,6 +1450,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="6289939620939689042">Color de la página</translation>
<translation id="6290238015253830360">Los artículos sugeridos aparecen aquí</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Se está parando el Asistente de Google en Chrome</translation>
<translation id="6305205051461490394">No se puede acceder a <ph name="URL" />.</translation>
<translation id="6312113039770857350">Página web no disponible</translation>
@@ -1436,6 +1476,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="6390200185239044127">Plegado al medio en Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">La política del administrador no permite pegar desde <ph name="ORIGIN_NAME" /> en esta ubicación.</translation>
+<translation id="6398765197997659313">Salir del modo de pantalla completa</translation>
<translation id="6401136357288658127">Esta política está obsoleta. Deberías usar la política <ph name="NEW_POLICY" /> en su lugar.</translation>
<translation id="6404511346730675251">Editar marcador</translation>
<translation id="6406765186087300643">C0 (sobre)</translation>
@@ -1448,7 +1489,6 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="6428450836711225518">Verifica tu número de teléfono</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">Descartar</translation>
<translation id="6440503408713884761">Ignorada</translation>
<translation id="6443406338865242315">Qué extensiones y complementos tienes instalados</translation>
<translation id="6446163441502663861">Kahu (sobre)</translation>
@@ -1491,6 +1531,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="6624427990725312378">Información de contacto</translation>
<translation id="6626291197371920147">Añadir un número de tarjeta válido</translation>
<translation id="6628463337424475685">Búsqueda de <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Buscando dispositivos USB...</translation>
<translation id="6630809736994426279">Es posible que los atacantes que se encuentren en <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> intenten instalar programas peligrosos en tu Mac para robar o eliminar tu información (por ejemplo, fotos, contraseñas, mensajes y tarjetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Más información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Borrar</translation>
@@ -1506,6 +1547,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="6671697161687535275">¿Quitar sugerencia de formulario de Chromium?</translation>
<translation id="6685834062052613830">Cierra sesión y completa la configuración</translation>
<translation id="6687335167692595844">Tamaño de fuente solicitado</translation>
+<translation id="6688743156324860098">Actualizar…</translation>
<translation id="6689249931105087298">Relativo con compresión de puntos negros</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="6698381487523150993">Creado:</translation>
@@ -1521,6 +1563,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="6744009308914054259">Mientras esperas a que haya conexión, puedes ir a Descargas para leer artículos sin conexión.</translation>
<translation id="6753269504797312559">Valor de la política</translation>
<translation id="6757797048963528358">El dispositivo se ha suspendido.</translation>
+<translation id="6767985426384634228">¿Actualizar dirección?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violeta</translation>
@@ -1543,6 +1586,7 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome ha simplificado esta página para facilitar su lectura y ha recuperado la página original mediante una conexión no segura.</translation>
<translation id="6891596781022320156">No se admite el nivel de la política.</translation>
+<translation id="6895143722905299846">Número virtual:</translation>
<translation id="6895330447102777224">Tu tarjeta se ha confirmado</translation>
<translation id="6897140037006041989">User-agent</translation>
<translation id="6898699227549475383">Organización (O)</translation>
@@ -1578,10 +1622,10 @@ De lo contrario, lo impedirá tu configuración de privacidad. Permitirá que el
<translation id="7004583254764674281">Usa Windows Hello para confirmar tarjetas más rápido</translation>
<translation id="7006930604109697472">Enviar de todos modos</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Ajustes de cambio de tamaño</translation>
<translation id="7014741021609395734">Nivel de zoom</translation>
<translation id="7016992613359344582">Estos cargos pueden ser únicos o periódicos, y es posible que no se indiquen de una forma evidente.</translation>
<translation id="7029809446516969842">Contraseñas</translation>
+<translation id="7030436163253143341">El certificado no es válido</translation>
<translation id="7031646650991750659">Qué aplicaciones de Google Play tienes instaladas</translation>
<translation id="7050187094878475250">Has intentado acceder a <ph name="DOMAIN" />, pero el servidor ha presentado un certificado cuyo periodo de validez es demasiado largo para que se considere de confianza.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Ahora no se puede guardar esta tarjeta}other{Ahora no se pueden guardar estas tarjetas}}</translation>
@@ -1651,12 +1695,14 @@ Más información:
<translation id="7300012071106347854">Azul cobalto</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Alto</translation>
+<translation id="7305756307268530424">Empezar más lento</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Ayuda para la conexión</translation>
<translation id="7323804146520582233">Ocultar la sección "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Anulación de la cuenta local del dispositivo</translation>
<translation id="7333654844024768166">Acabas de introducir tu contraseña en un sitio web engañoso. Chromium te recomienda que accedas a <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> y otros sitios en los que uses esta contraseña y que la cambies ahora.</translation>
<translation id="7334320624316649418">&amp;Rehacer reorganización</translation>
+<translation id="7337248890521463931">Mostrar más líneas</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>
@@ -1664,6 +1710,7 @@ Más información:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Línea de comandos</translation>
<translation id="7359588939039777303">Los anuncios están bloqueados.</translation>
+<translation id="7363096869660964304">Sin embargo, tus acciones no son invisibles. El modo de incógnito no oculta tu actividad de navegación a tu empresa, a tu proveedor de Internet ni a los sitios web que visites.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, pulsa Tabulador y luego Intro para añadir y gestionar direcciones en la configuración de Chrome</translation>
<translation id="7365849542400970216">¿Detectar el uso de tu dispositivo?</translation>
<translation id="7372973238305370288">resultado de búsqueda</translation>
@@ -1674,7 +1721,9 @@ Más información:
<translation id="7378594059915113390">Controles multimedia</translation>
<translation id="7378627244592794276">No</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">No aplicable</translation>
<translation id="7390545607259442187">Confirmar tarjeta</translation>
+<translation id="7392089738299859607">Actualizar dirección</translation>
<translation id="7399802613464275309">Comprobación de seguridad</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Tu <ph name="DEVICE_NAME" /> está administrado</translation>
@@ -1689,6 +1738,7 @@ Más información:
&lt;li&gt;Visita el &lt;a href="https://support.google.com/chrome/answer/6098869?hl=es"&gt;Centro de Ayuda de Chrome&lt;/a&gt; para consultar cómo eliminar el software de forma permanente de tu ordenador
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Encantadora</translation>
<translation id="7416351320495623771">Gestionar contraseñas…</translation>
<translation id="7419106976560586862">Ruta del perfil</translation>
<translation id="7437289804838430631">Añade la información de contacto</translation>
@@ -1704,7 +1754,7 @@ Más información:
<translation id="7481312909269577407">Adelante</translation>
<translation id="7485870689360869515">No se han encontrado datos.</translation>
<translation id="7495528107193238112">Este contenido está bloqueado. Para solucionar el problema, ponte en contacto con el propietario del sitio web.</translation>
-<translation id="7498234416455752244">Seguir editando</translation>
+<translation id="7498193950643227031">Si se modifica el tamaño de la aplicación, es posible que se comporte de forma inesperada. Ahora puedes limitar la capacidad de modificar el tamaño de las aplicaciones en <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Acabas de escribir tu contraseña en un sitio web engañoso. Chromium te recomienda que compruebes las contraseñas que has guardado en <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> y otros sitios en los que uses esta contraseña.</translation>
<translation id="7508255263130623398">El ID de dispositivo de política devuelto está vacío o no coincide con el ID de dispositivo actual</translation>
<translation id="7508870219247277067">Verde aguacate</translation>
@@ -1724,6 +1774,7 @@ Más información:
<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="755279583747225797">Prueba activa</translation>
<translation id="7552846755917812628">Prueba los siguientes consejos:</translation>
<translation id="7554475479213504905">Volver a cargar y mostrar de todos modos</translation>
<translation id="7554791636758816595">Nueva pestaña</translation>
@@ -1742,7 +1793,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, pulsa Tabulador y, a continuación, Intro para ver y gestionar tus contraseñas desde la configuración de Chrome</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="7616645509853975347">Tu administrador ha activado Chrome Enterprise Connectors en tu navegador. Estos conectores tienen acceso a algunos de tus datos.</translation>
<translation id="7619838219691048931">Hoja final</translation>
<translation id="762844065391966283">De uno en uno</translation>
@@ -1807,13 +1857,12 @@ Más información:
<translation id="782886543891417279">La red Wi-Fi que estás utilizando (<ph name="WIFI_NAME" />) puede requerir que accedas a su página de inicio de sesión.</translation>
<translation id="7836231406687464395">Postfix (sobre)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ninguna}=1{1 aplicación (<ph name="EXAMPLE_APP_1" />)}=2{2 aplicaciones (<ph name="EXAMPLE_APP_1" /> y <ph name="EXAMPLE_APP_2" />)}other{# aplicaciones (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Ten en cuenta que tus acciones no serán totalmente invisibles. El uso del modo de incógnito no te permite ocultar tu actividad de navegación a tu empresa, a tu proveedor de servicios de Internet o a los sitios web que visites.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Abrir archivos con asociaciones de tipo de archivo.</translation>
<translation id="7862185352068345852">¿Quieres salir del sitio web?</translation>
<translation id="7865448901209910068">Mejor velocidad</translation>
<translation id="7874263914261512992">Acabas de escribir tu contraseña en un sitio web engañoso. Chrome te recomienda que compruebes las contraseñas que has guardado en <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> y otros sitios en los que uses esta contraseña.</translation>
<translation id="7878562273885520351">Es posible que tu contraseña se haya vulnerado</translation>
+<translation id="7880146494886811634">Guardar dirección</translation>
<translation id="7882421473871500483">Marrón</translation>
<translation id="7887683347370398519">Comprueba el código CVC y vuelve a intentarlo</translation>
<translation id="7887885240995164102">Activar el modo imagen en imagen</translation>
@@ -1821,6 +1870,7 @@ Más información:
<translation id="7894280532028510793">Si está escrito correctamente, <ph name="BEGIN_LINK" />prueba a ejecutar el diagnóstico de red<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (sobre)</translation>
<translation id="7931318309563332511">Desconocido</translation>
+<translation id="793209273132572360">¿Actualizar dirección?</translation>
<translation id="7932579305932748336">Capa</translation>
<translation id="79338296614623784">Introduce un número de teléfono válido</translation>
<translation id="7934052535022478634">Pago completado</translation>
@@ -1891,6 +1941,7 @@ Más información:
<translation id="8175796834047840627">Chrome te ofrece guardar las tarjetas en tu cuenta de Google porque has iniciado sesión. Puedes cambiar esta opción en los ajustes.</translation>
<translation id="8176440868214972690">El administrador de este dispositivo ha enviado algunos datos (como ajustes o políticas) a los siguientes sitios web.</translation>
<translation id="8184538546369750125">Utilizar valor predeterminado global (Permitir)</translation>
+<translation id="8193086767630290324">Acciones realizadas con datos marcados como confidenciales</translation>
<translation id="8194797478851900357">&amp;Deshacer movimiento</translation>
<translation id="8201077131113104583">URL de actualización no válida para la extensión <ph name="EXTENSION_ID" />.</translation>
<translation id="8202097416529803614">Resumen del pedido</translation>
@@ -1913,6 +1964,7 @@ Más información:
<translation id="8249296373107784235">Anular</translation>
<translation id="8249320324621329438">Última comprobación:</translation>
<translation id="8253091569723639551">Se necesita una dirección de facturación</translation>
+<translation id="8257387598443225809">Esta aplicación se ha diseñado para móviles</translation>
<translation id="825929999321470778">Mostrar todas las contraseñas guardadas</translation>
<translation id="8261506727792406068">Eliminar</translation>
<translation id="8262952874573525464">Grapado en el borde inferior</translation>
@@ -2036,7 +2088,6 @@ Más información:
<translation id="8719528812645237045">Perforado múltiple en la parte superior</translation>
<translation id="8725066075913043281">Reintentar</translation>
<translation id="8726549941689275341">Tamaño de página:</translation>
-<translation id="8728672262656704056">Has iniciado una sesión de incógnito</translation>
<translation id="8730621377337864115">Hecho</translation>
<translation id="8731544501227493793">Botón Gestionar contraseñas, pulsa Intro para ver y gestionar tus contraseñas desde la configuración de Chrome</translation>
<translation id="8734529307927223492"><ph name="MANAGER" /> gestiona tu <ph name="DEVICE_TYPE" /></translation>
@@ -2113,6 +2164,7 @@ Más información:
<translation id="9020542370529661692">Esta página se ha traducido al <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(no válido)</translation>
+<translation id="9030265603405983977">Monocromo</translation>
<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>
@@ -2136,6 +2188,7 @@ Más información:
<translation id="91108059142052966">La política del administrador inhabilita la pantalla compartida con <ph name="APPLICATION_TITLE" /> cuando se muestra contenido confidencial</translation>
<translation id="9114524666733003316">Confirmando tarjeta...</translation>
<translation id="9114581008513152754">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="9117930699067497412">Novedosa</translation>
<translation id="9119042192571987207">Subido</translation>
<translation id="9128016270925453879">Se han cargado las políticas</translation>
<translation id="9128870381267983090">Conéctate a la red</translation>
@@ -2154,6 +2207,7 @@ Más información:
<translation id="9170848237812810038">&amp;Deshacer</translation>
<translation id="9171296965991013597">¿Quieres salir de la aplicación?</translation>
<translation id="9173282814238175921">Documento individual/Nueva hoja</translation>
+<translation id="9173995187295789444">Buscando dispositivos Bluetooth...</translation>
<translation id="917450738466192189">El certificado del servidor no es válido.</translation>
<translation id="9174917557437862841">Botón de cambio de pestaña; pulsa Intro para cambiar a esta pestaña</translation>
<translation id="9179703756951298733">Gestiona la información de tus pagos y tarjetas de crédito desde la configuración de Chrome</translation>
diff --git a/chromium/components/strings/components_strings_et.xtb b/chromium/components/strings/components_strings_et.xtb
index af13ac82130..5f81e905578 100644
--- a/chromium/components/strings/components_strings_et.xtb
+++ b/chromium/components/strings/components_strings_et.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Kui see on märgitud, salvestab Chrome teie kaardi koopia sellesse seadmesse, et vormi kiiremini täita.</translation>
<translation id="1110994991967754504">Valige luba üksuse <ph name="PERMISSION_NAME" /> jaoks</translation>
<translation id="1113869188872983271">&amp;Võta korrastamine tagasi</translation>
+<translation id="1123753900084781868">Reaalajas subtiitrid ei ole praegu saadaval</translation>
<translation id="1125573121925420732">Sel ajal kui veebisaidid värskendavad turvafunktsioone, võite sageli hoiatusi näha. See olukord peaks varsti lahenema.</translation>
<translation id="112840717907525620">Reegli vahemälu töötab probleemideta</translation>
<translation id="1130564665089811311">Nupp Tõlgi leht, selle lehe tõlkimiseks rakendusega Google'i tõlge vajutage sisestusklahvi</translation>
@@ -74,6 +75,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="1240347957665416060">Teie seadme nimi</translation>
<translation id="124116460088058876">Rohkem keeli</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Paks</translation>
<translation id="1250759482327835220">Kui soovite järgmisel korral kiiremini maksta, salvestage kaart, nimi ja arveldusaadress oma Google'i kontole.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sünkroonitud)</translation>
<translation id="1256368399071562588">&lt;p&gt;Kui üritate külastada veebisaiti ja see ei avane, proovige vea parandamiseks esmalt neid veaotsingu toiminguid.&lt;/p&gt;
@@ -156,6 +158,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="1476595624592550506">Muutke oma parooli</translation>
<translation id="1484290072879560759">Valige tarneaadress</translation>
<translation id="1492194039220927094">Reeglite saatmine:</translation>
+<translation id="1495677929897281669">Tagasi vahelehele</translation>
<translation id="1501859676467574491">Kuva kaardid minu Google'i kontolt</translation>
<translation id="1507202001669085618">&lt;p&gt;Seda viga näete juhul, kui kasutate WiFi-portaali, kuhu tuleb enne võrguühenduse loomist sisse logida.&lt;/p&gt;
&lt;p&gt;Vea parandamiseks klõpsake avataval lehel käsul &lt;strong&gt;Loo ühendus&lt;/strong&gt;.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="1532118530259321453">Leht ütleb</translation>
<translation id="153384715582417236">See on praeguseks kõik</translation>
<translation id="1536390784834419204">Tõlgi leht</translation>
+<translation id="1539840569003678498">Aruanne saadeti:</translation>
<translation id="154408704832528245">Valige kohaletoimetamisaadress</translation>
<translation id="1549470594296187301">Selle funktsiooni kasutamiseks peab JavaScript olema lubatud.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="1682696192498422849">Lühem serv enne</translation>
<translation id="168693727862418163">Seda reegli väärtust ei õnnestunud skeemiga võrdluses kinnitada ja seda eiratakse.</translation>
<translation id="168841957122794586">Serveri sertifikaat sisaldab nõrka krüptograafilist võtit.</translation>
+<translation id="1696290444144917273">Virtuaalkaardi üksikasjade kuvamine</translation>
<translation id="1697532407822776718">Kõik on valmis!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Server ei suutnud tõestada, et tegemist on domeeniga <ph name="DOMAIN" />, selle turvasertifikaat hakkab väidetavalt kehtima homme. Selle põhjuseks võib olla vale seadistus või teie ühendust segav ründaja.}other{Server ei suutnud tõestada, et tegemist on domeeniga <ph name="DOMAIN" />, selle turvasertifikaat hakkab väidetavalt kehtima # päeva pärast. Selle põhjuseks võib olla vale seadistus või teie ühendust segav ründaja.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Eirati, kuna reegel <ph name="POLICY_NAME" /> pole seadistatud väärtusele <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> soovib andmed alaliselt teie kohalikku arvutisse salvestada</translation>
<translation id="1713628304598226412">Salv 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Postkast 3</translation>
<translation id="1718029547804390981">Dokument on märkuste lisamiseks liiga suur</translation>
<translation id="1721424275792716183">* Kohustuslik väli</translation>
+<translation id="1727613060316725209">Sertifikaat on kehtiv</translation>
<translation id="1727741090716970331">Kehtiva kaardinumbri lisamine</translation>
<translation id="1728677426644403582">Vaatate veebilehe lähtekoodi</translation>
<translation id="173080396488393970">Seda tüüpi kaarti ei toetata</translation>
@@ -245,7 +252,6 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
saidile <ph name="SITE" /> esitatud taotlust täita. Saidioperaatorid saavad kasutada
lähtekohareegleid saidi turbe ja muude atribuutide seadistamiseks.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Värskendage sünkroonimise parooli.</translation>
<translation id="1787142507584202372">Teie avatud vahelehed kuvatakse siin</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, saadaval on mitu toimingut, vajutage nende vahel vahetamiseks tabulaatorit</translation>
@@ -278,6 +284,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="1919345977826869612">Reklaamid</translation>
<translation id="1919367280705858090">Konkreetse veateate puhul abi hankimine</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ãœhtegi}=1{1 sait}other{# saiti}}</translation>
+<translation id="1924727005275031552">Uus</translation>
<translation id="1945968466830820669">Võite kaotada juurdepääsu oma organisatsiooni kontole või teie identiteet võidakse varastada. Chromium soovitab teil kohe oma parooli muuta.</translation>
<translation id="1947454675006758438">Kirjaklamber paremal ülal</translation>
<translation id="1958218078413065209">Teie parim tulemus on <ph name="SCORE" />.</translation>
@@ -300,12 +307,14 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="2042213636306070719">Salv 7</translation>
<translation id="204357726431741734">Logige sisse, et kasutada oma Google'i kontole salvestatud paroole</translation>
<translation id="2053111141626950936">Selles keeles lehti ei tõlgita: <ph name="LANGUAGE" />.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Kui see juhtelement on sisse lülitatud ja olek on aktiivne, määrab Chrome, millise suure grupi (ehk rühma) inimestega on teie hiljutine sirvimistegevus kõige sarnasem. Reklaamijad saavad grupi jaoks reklaame valida ja teie sirvimistegevus jääb teie seadmes privaatseks. Teie gruppi värskendatakse iga päev.}=1{Kui see juhtelement on sisse lülitatud ja olek on aktiivne, määrab Chrome, millise suure grupi (ehk rühma) inimestega on teie hiljutine sirvimistegevus kõige sarnasem. Reklaamijad saavad grupi jaoks reklaame valida ja teie sirvimistegevus jääb teie seadmes privaatseks. Teie gruppi värskendatakse iga päev.}other{Kui see juhtelement on sisse lülitatud ja olek on aktiivne, määrab Chrome, millise suure grupi (ehk rühma) inimestega on teie hiljutine sirvimistegevus kõige sarnasem. Reklaamijad saavad grupi jaoks reklaame valida ja teie sirvimistegevus jääb teie seadmes privaatseks. Teie gruppi värskendatakse iga {NUM_DAYS} päeva järel.}}</translation>
<translation id="2053553514270667976">Postiindeks</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 soovitus}other{# soovitust}}</translation>
<translation id="2071692954027939183">Märguanded blokeeriti automaatselt, kuna tavaliselt ei luba te neid kuvada</translation>
<translation id="2079545284768500474">Võta tagasi</translation>
<translation id="20817612488360358">Kasutamiseks on määratud süsteemi puhverserveri seaded, kuid määratud on ka konkreetne puhverserveri konfigureerimine.</translation>
<translation id="2082238445998314030">Tulemus <ph name="RESULT_NUMBER" />/<ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Salvestamine …</translation>
<translation id="2088086323192747268">Nupp Sünkroonimise haldamine, vajutage Chrome'i seadetes sünkroonitava teabe haldamiseks sisestusklahvi</translation>
<translation id="2091887806945687916">Heli</translation>
<translation id="2094505752054353250">Domeeni vastuolu</translation>
@@ -378,6 +387,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="2317259163369394535">Domeen <ph name="DOMAIN" /> nõuab kasutajanime ja parooli.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, aegub <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Seadet juhib administraator</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> soovib siduda</translation>
<translation id="2344028582131185878">Automaatsed allalaadimised</translation>
<translation id="2346319942568447007">Teie kopeeritud pilt</translation>
<translation id="2354001756790975382">Muud järjehoidjad</translation>
@@ -385,8 +395,10 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="2355395290879513365">Ründajad võivad näha pilte, mida sellel saidil vaatate, ja teid neid pilte muutes petta.</translation>
<translation id="2356070529366658676">Küsi</translation>
<translation id="2357481397660644965">Teie seadet haldab <ph name="DEVICE_MANAGER" /> ja teie kontot haldab <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Vähem kui päeva pärast}=1{Päeva pärast}other{{NUM_DAYS} päeva pärast}}</translation>
<translation id="2359629602545592467">Mitu</translation>
<translation id="2359808026110333948">Jätka</translation>
+<translation id="2359961752320758691">Sisestati teie virtuaalkaardi number.</translation>
<translation id="2367567093518048410">Tase</translation>
<translation id="2372464001869762664">Pärast kinnitamist jagatakse teie Google'i konto kaardi üksikasju selle saidiga. CVC leiate oma Plexi konto üksikasjade alt.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -397,6 +409,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="239429038616798445">See tarneviis pole saadaval. Proovige mõnda teist tarneviisi.</translation>
<translation id="2396249848217231973">&amp;Võta kustutamine tagasi</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Vana</translation>
<translation id="2413528052993050574">Server ei suutnud tõestada, et see on domeen <ph name="DOMAIN" />, selle turvasertifikaat võib olla tühistatud. Selle põhjuseks võib olla vale seadistus või ründaja, kes on sekkunud teie ühendusse.</translation>
<translation id="2414886740292270097">Tume</translation>
<translation id="2438874542388153331">Neli auku paremal</translation>
@@ -424,10 +437,10 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="2521385132275182522">Kirjaklamber paremal all</translation>
<translation id="2523886232349826891">Salvestatakse ainult sellesse seadmesse</translation>
<translation id="2524461107774643265">Lisateabe lisamine</translation>
-<translation id="2526590354069164005">Töölaud</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{ja veel 1}other{ja veel #}}</translation>
<translation id="2536110899380797252">Lisa aadress</translation>
<translation id="2539524384386349900">Tuvasta</translation>
+<translation id="2541219929084442027">Inkognito vahelehtedel kuvatavaid lehti ei talletata pärast inkognito vahelehtede sulgemist brauseri ajalukku, küpsistefailide salve ega otsinguajalukku. Allalaaditavad failid ja järjehoidjatesse lisatud sisu säilitatakse.</translation>
<translation id="2544644783021658368">Ãœks dokument</translation>
<translation id="254947805923345898">Reegli väärtus on kehtetu.</translation>
<translation id="255002559098805027">Host <ph name="HOST_NAME" /> saatis sobimatu vastuse.</translation>
@@ -447,6 +460,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="2629325967560697240">Chrome'i kõrgeima taseme turvalisuse saavutamiseks <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />lülitage sisse täiustatud kaitse<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Hosti <ph name="HOST_NAME" /> serveri IP-aadressi ei leitud.</translation>
<translation id="2639739919103226564">Olek:</translation>
+<translation id="264810637653812429">Ãœhilduvaid seadmeid ei leitud.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, vajutage Chrome'i seadetes sirvimisajaloo, küpsisefailide ja muu kustutamiseks ning vahemälu tühjendamiseks tabulaatorit ja seejärel sisestusklahvi</translation>
<translation id="2650446666397867134">Faili juurde ei saa pääseda</translation>
@@ -493,6 +507,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<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="2807052079800581569">Pildi asend Y-teljel</translation>
+<translation id="2820957248982571256">Skannimine …</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>
@@ -500,6 +515,8 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="2850739647070081192">Invite (ümbrik)</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="2859806420264540918">Sait kuvab sekkuvaid või eksitavaid reklaame.</translation>
+<translation id="287596039013813457">Sõbralik</translation>
+<translation id="2876489322757410363">Väljute inkognito režiimist, et välise rakenduse kaudu maksta. Kas soovite jätkata?</translation>
<translation id="2878197950673342043">Plakatikujuliselt volditud</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Akende paigutus</translation>
@@ -549,7 +566,6 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="3060227939791841287">C9 (ümbrik)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, vajutage tabulaatorit ja siis sisestusklahvi, et Chrome'i seadetes ohutuskontroll käitada</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>
<translation id="306573536155379004">Mäng algas.</translation>
<translation id="3080254622891793721">Graafika</translation>
<translation id="3086579638707268289">Teie tegevusi veebis jälgitakse</translation>
@@ -572,7 +588,6 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="315504272643575312">Teie kontot haldab <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Taasta</translation>
<translation id="3162559335345991374">WiFi-võrk, mida kasutate, võib nõuda sisselogimislehe külastamist.</translation>
-<translation id="3167968892399408617">Inkognito vahelehtedel kuvatavaid lehti ei talletata pärast vahelehtede sulgemist brauseri ajalukku, küpsistefailide salve ega otsinguajalukku. Allalaaditavad failid ja järjehoidjatesse lisatud sisu säilitatakse.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Saar</translation>
<translation id="3176929007561373547">Kontrollige puhverserveri seadeid või võtke ühendust võrguadministraatoriga
@@ -598,10 +613,12 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<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="3249845759089040423">Särtsakas</translation>
<translation id="3252266817569339921">prantsuse keel</translation>
<translation id="3266793032086590337">Väärtus (konflikt)</translation>
<translation id="3268451620468152448">Avatud vahelehed</translation>
<translation id="3270847123878663523">&amp;Võta korrastamine tagasi</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> soovib ühenduse luua</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Teie organisatsioon, <ph name="ENROLLMENT_DOMAIN" />, on järgmistele veebisaitidele teatud teavet saatnud, näiteks seadete ja eeskirjade teavet.</translation>
<translation id="3282497668470633863">Kaardil oleva nime lisamine</translation>
@@ -654,6 +671,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="3428151540071562330">Vähemalt üks reegli DnsOverHttpsTemplates serveri malli URI on kehtetu ja seda ei kasutata.</translation>
<translation id="3431636764301398940">Salvesta kaart sellesse seadmesse</translation>
<translation id="3432601291244612633">Sule leht</translation>
+<translation id="3435738964857648380">Turvalisus</translation>
<translation id="3435896845095436175">Luba</translation>
<translation id="3438829137925142401">Kasutage oma Google'i kontole salvestatud paroole</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -696,7 +714,10 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="3584299510153766161">Kaks auku all</translation>
<translation id="3586931643579894722">Peida üksikasjad</translation>
<translation id="3587738293690942763">Keskmine</translation>
+<translation id="3590643883886679995">Sisselogimisandmed salvestatakse sellesse seadmesse pärast inkognito režiimist väljumist.</translation>
+<translation id="359126217934908072">Kuu/aasta:</translation>
<translation id="3592413004129370115">Italian (ümbrik)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Saate grupi mis tahes ajal lähtestada. Uue grupiga liitumiseks kulub umbes päev.}=1{Saate grupi mis tahes ajal lähtestada. Uue grupiga liitumiseks kulub umbes päev.}other{Saate grupi mis tahes ajal lähtestada. Uue grupiga liitumiseks kulub {NUM_DAYS} päeva.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Rakenduse blokeeris administraator</translation>
<translation id="3608932978122581043">Voo suund</translation>
@@ -705,13 +726,13 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="3615877443314183785">Sisestage kehtiv aegumiskuupäev</translation>
<translation id="36224234498066874">Sirvimisandmete kustutamine...</translation>
<translation id="362276910939193118">Näita kogu ajalugu</translation>
-<translation id="3625635938337243871">Sisselogimisandmed salvestatakse sellesse seadmesse pärast inkognito režiimist väljumist.</translation>
<translation id="3630155396527302611">Kui see on juba loendis kui programm, millele on lubatud võrgujuurdepääs, proovige
see loendist eemaldada ja siis uuesti lisada.</translation>
<translation id="3630699740441428070">Seadme administraatorid on seadistanud teie võrguühenduse, mille abil võivad nad näha teie võrguliiklust, sealhulgas külastatavaid veebisaite.</translation>
<translation id="3631244953324577188">Biomeetria</translation>
<translation id="3633738897356909127">Nupp Värskenda Chrome'i, vajutage Chrome'i seadetes Chrome'i värskendamiseks sisestusklahvi</translation>
<translation id="3634530185120165534">Salv 5</translation>
+<translation id="3637662659967048211">Salvesta Google'i kontole</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Rakendus:</translation>
<translation id="3650584904733503804">Valideerimine õnnestus</translation>
@@ -752,6 +773,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="3781428340399460090">Erkroosa</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth-seadmed</translation>
+<translation id="3787675388804467730">Virtuaalkaardi number</translation>
<translation id="3787705759683870569">Aegub: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Suurus 16</translation>
<translation id="3789841737615482174">Installi</translation>
@@ -771,6 +793,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="3841184659773414994">Failitöötlejad</translation>
<translation id="385051799172605136">Tagasi</translation>
<translation id="3858027520442213535">Värskenda kuupäeva ja kellaaega</translation>
+<translation id="3881478300875776315">Kuva vähem ridu</translation>
<translation id="3884278016824448484">Seadme identifikaator on konfliktne</translation>
<translation id="3885155851504623709">Vald</translation>
<translation id="388632593194507180">Tuvastati jälgimine</translation>
@@ -796,6 +819,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="397105322502079400">Arvutamine ...</translation>
<translation id="3973234410852337861">Host <ph name="HOST_NAME" /> on blokeeritud</translation>
<translation id="3973357910713125165">Nupp Käita Chrome'i ohutuskontroll, vajutage sisestusklahvi, et Chrome'i seadetes ohutuskontroll käitada</translation>
+<translation id="3986705137476756801">Reaalajas subtiitrite praeguseks väljalülitamine</translation>
<translation id="3987405730340719549">Chrome tuvastas, et see sait võib olla võlts või petturlik.
Kui arvate, et tegemist on veaga, külastage saiti https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -892,13 +916,14 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="4275830172053184480">Taaskäivitage seade</translation>
<translation id="4277028893293644418">Lähtesta parool</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="4287885627794386150">Prooviversiooniks sobiv, kuid pole aktiivne</translation>
<translation id="4297502707443874121">Lehe <ph name="THUMBNAIL_PAGE" /> pisipilt</translation>
<translation id="42981349822642051">Laienda</translation>
<translation id="4300675098767811073">Mitu auku paremal</translation>
<translation id="4302514097724775343">Mängimiseks puudutage dinosaurust</translation>
<translation id="4302965934281694568">Chou3 (ümbrik)</translation>
<translation id="4305666528087210886">Teie failile ei pääsetud juurde</translation>
-<translation id="4305817255990598646">Lüliti</translation>
+<translation id="4306529830550717874">Kas salvestada aadress?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokeeri (vaikimisi)</translation>
<translation id="4314815835985389558">Sünkroonimise haldamine</translation>
@@ -925,6 +950,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="4377125064752653719">Püüdsite jõuda saidile <ph name="DOMAIN" />, kuid sertifikaadi väljaandja on serveri esitatud sertifikaadi tagasi võtnud. See tähendab, et serveri esitatud turvamandaate ei tohiks mingil juhul usaldada. Võimalik, et suhtlete ründajaga.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Serv</translation>
+<translation id="4406883609789734330">Reaalajas subtiitrid</translation>
<translation id="4406896451731180161">otsingutulemused</translation>
<translation id="4408413947728134509">Küpsisefailid: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Sisestasite äsja oma parooli kahtlasele saidile. Chrome soovitab teil minna veebisaitidele <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ja muudele saitidele, kus seda parooli kasutate, ning kohe oma parooli muuta.</translation>
@@ -937,7 +963,6 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="4435702339979719576">Postkaart)</translation>
<translation id="443673843213245140">Puhverserveri kasutamine on keelatud, kuid määratud on ka konkreetne puhverserveri konfigureerimine.</translation>
<translation id="4464826014807964867">Teie organisatsiooni teabega veebisaidid</translation>
-<translation id="4466881336512663640">Vormil tehtud muudatused lähevad kaotsi. Kas soovite kindlasti jätkata?</translation>
<translation id="4476953670630786061">See vorm pole turvaline. Automaattäide on välja lülitatud.</translation>
<translation id="4477350412780666475">Järgmine lugu</translation>
<translation id="4482953324121162758">Seda saiti ei tõlgita.</translation>
@@ -971,6 +996,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="4594403342090139922">&amp;Võta kustutamine tagasi</translation>
<translation id="4597348597567598915">Suurus 8</translation>
<translation id="4600854749408232102">C6/C5 (ümbrik)</translation>
+<translation id="4606870351894164739">Mõjukas</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Ostuboonus on lingitud</translation>
<translation id="4636930964841734540">Teave</translation>
@@ -990,6 +1016,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="4691835149146451662">Architecture-A (ümbrik)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Külg</translation>
+<translation id="4702656508969495934">Reaalajas subtiitrid on nähtavad, kasutage fokuseerimiseks aknalülitit</translation>
<translation id="4708268264240856090">Teie ühendus katkes</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windowsi võrgudiagnostika käitamine<ph name="END_LINK" /></translation>
@@ -1003,6 +1030,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="4738601419177586157">Otsingusoovitus: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Halda paroole …</translation>
<translation id="4744603770635761495">Täitmistee</translation>
+<translation id="4749011317274908093">Olete inkognito režiimis</translation>
<translation id="4750917950439032686">Teie teave (nt paroolid või krediitkaardi numbrid) on sellele saidile saates privaatne.</translation>
<translation id="4756388243121344051">&amp;Ajalugu</translation>
<translation id="4758311279753947758">Lisage kontaktteave</translation>
@@ -1032,6 +1060,8 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="4813512666221746211">Võrgu viga</translation>
<translation id="4816492930507672669">Sobita lehele</translation>
<translation id="4819347708020428563">Kas muuta märkusi vaikekuval?</translation>
+<translation id="4825507807291741242">Võimas</translation>
+<translation id="4838327282952368871">Unistav</translation>
<translation id="484462545196658690">Automaatne</translation>
<translation id="4850886885716139402">Kuva</translation>
<translation id="485316830061041779">saksa keel</translation>
@@ -1168,6 +1198,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="5314967030527622926">Brošüürilooja</translation>
<translation id="5316812925700871227">Pööra vastupäeva</translation>
<translation id="5317780077021120954">Salvesta</translation>
+<translation id="5321288445143113935">Maksimeeritud</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" />/<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Valige kontaktteave</translation>
<translation id="5327248766486351172">Nimi</translation>
@@ -1175,11 +1206,13 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="5332219387342487447">Tarneviis</translation>
<translation id="5333022057423422993">Chrome leidis äsja kasutatud parooli andmetega seotud rikkumisest. Oma kontode turvalisuse tagamiseks soovitame teil oma salvestatud paroole kontrollida.</translation>
<translation id="5334013548165032829">Üksikasjalikud süsteemilogid</translation>
+<translation id="5334145288572353250">Kas salvestada aadress?</translation>
<translation id="5340250774223869109">Rakendus on blokeeritud</translation>
<translation id="534295439873310000">NFC-seadmed</translation>
<translation id="5344579389779391559">Leht võib üritada teilt tasu võtta</translation>
<translation id="5355557959165512791">Te ei saa saiti <ph name="SITE" /> praegu külastada, sest selle sertifikaat on tühistatud. Võrguvead ja -rünnakud on tavaliselt ajutised, nii et leht tõenäoliselt hiljem töötab.</translation>
<translation id="536296301121032821">Reegli seadete talletamine ebaõnnestus</translation>
+<translation id="5363309033720083897">Jadaport, mille on lubanud teie administraator</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="5386426401304769735">Selle saidi sertifikaadiahel sisaldab sertifikaati, mis on allkirjastatud SHA-1-ga.</translation>
@@ -1188,6 +1221,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="5398772614898833570">Reklaamid on blokeeritud</translation>
<translation id="5400836586163650660">Hall</translation>
<translation id="540969355065856584">Server ei suutnud tõestada, et see on domeen <ph name="DOMAIN" />; selle turvasertifikaat pole praegu kehtiv. Selle põhjuseks võib olla vale seadistus või ründaja, kes on sekkunud teie ühendusse.</translation>
+<translation id="541143247543991491">Pilv (süsteemiülene)</translation>
<translation id="541416427766103491">Virnastaja 4</translation>
<translation id="5421136146218899937">Sirvimisandmete kustutamine ...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> soovib teile saata märguandeid</translation>
@@ -1201,6 +1235,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="5455374756549232013">Reegli ajatempel on sobimatu</translation>
<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="5463625433003343978">Seadmete otsimine …</translation>
<translation id="5469868506864199649">itaalia keel</translation>
<translation id="5470861586879999274">&amp;Muuda uuesti</translation>
<translation id="5478437291406423475">B6/C4 (ümbrik)</translation>
@@ -1250,7 +1285,6 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="5624120631404540903">Paroolide haldamine</translation>
<translation id="5629630648637658800">Reegli seadete laadimine ebaõnnestus</translation>
<translation id="5631439013527180824">Seadme halduse luba on kehtetu</translation>
-<translation id="5632627355679805402">Teie andmed krüpteeriti viimati teie <ph name="BEGIN_LINK" />Google’i parooliga<ph name="END_LINK" /> kuupäeva <ph name="TIME" /> seisuga. Sisestage see sünkroonimise alustamiseks.</translation>
<translation id="5633066919399395251">Saidil <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> olevad ründajad võivad proovida installida teie arvutisse ohtlikke programme, mis varastavad teie teavet või kustutavad selle (nt fotod, paroolid, sõnumid ja krediitkaarditeave). <ph name="BEGIN_LEARN_MORE_LINK" />Lisateave<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Petlik sisu blokeeriti.</translation>
<translation id="5644090287519800334">Pildi nihe X-teljel 1. poolel</translation>
@@ -1289,12 +1323,12 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="5785756445106461925">Lisaks sisaldab see leht teisi ressursse, mis pole turvalised. Edastamise ajal võivad ressursse vaadata ka teised ja ründajad saavad lehe välimuse muutmiseks ressursse muuta.</translation>
<translation id="5786044859038896871">Kas soovite sisestada oma kaarditeabe?</translation>
<translation id="578633867165174378">Chrome leidis äsja kasutatud parooli andmetega seotud rikkumisest. Soovitame parooli kohe muuta.</translation>
-<translation id="5798290721819630480">Kas soovite muudatustest loobuda?</translation>
<translation id="5803412860119678065">Kas soovite sisestada kirje <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Load</translation>
<translation id="5804427196348435412">NFC-seadmete kasutamine</translation>
<translation id="5810442152076338065">Teie ühendus domeeniga <ph name="DOMAIN" /> on krüpteeritud aegunud šifreerimiskomplektiga.</translation>
<translation id="5813119285467412249">&amp;Lisa uuesti</translation>
+<translation id="5817918615728894473">Seo</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Sellelt kaardilt võetakse tasu siis, kui maksate, kuid selle päris numbrit selle saidiga ei jagata. Lisaturvalisuse pakkumiseks luuakse ajutine CVC.}other{Teie valitud kaardilt võetakse tasu siis, kui maksate, kuid selle päris numbrit selle saidiga ei jagata. Lisaturvalisuse pakkumiseks luuakse ajutine CVC.}}</translation>
<translation id="5826507051599432481">Ãœldnimi (CN)</translation>
<translation id="5838278095973806738">Te ei tohiks sellele saidile sisestada tundlikku teavet (nt paroolid või krediitkaardid), kuna ründajad võivad selle varastada.</translation>
@@ -1302,6 +1336,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="5855253129151731373">Saidi hostinimi sarnaneb domeenile <ph name="LOOKALIKE_DOMAIN" />. Ründajad imiteerivad mõnikord saite, tehes domeeni nimes väikeseid raskesti märgatavaid muudatusi.
Kui arvate, et tegemist on veaga, külastage saiti https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Väljas</translation>
<translation id="5862579898803147654">Virnastaja 8</translation>
<translation id="5863847714970149516">Järgmisel lehel võidakse teilt üritada tasu võtta</translation>
<translation id="5866257070973731571">Telefoninumbri lisamine</translation>
@@ -1318,6 +1353,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="5913377024445952699">Ekraanikuva jäädvustamine on peatatud</translation>
<translation id="59174027418879706">Lubatud</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 on kasutusel}other{# on kasutusel}}</translation>
<translation id="5921185718311485855">Sees</translation>
<translation id="5921639886840618607">Kas salvestada kaart Google'i kontole?</translation>
<translation id="5922853866070715753">Peaaegu valmis</translation>
@@ -1337,6 +1373,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="5989320800837274978">Määratud ei ole fikseeritud puhverservereid ega pac-skriptiga URL-i.</translation>
<translation id="5992691462791905444">Z-kujuliselt volditud</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> tulemust otsingule „<ph name="SEARCH_TEXT" />â€</translation>
+<translation id="6006484371116297560">Klassikaline</translation>
<translation id="6008122969617370890">Järjestus n–1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Kontrollige oma paroole</translation>
@@ -1358,6 +1395,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="6045164183059402045">Kehtestamise mall</translation>
<translation id="6047233362582046994">Kui mõistate, kuidas see teie turvalisust ohustab, siis võite <ph name="BEGIN_LINK" />seda saiti külastada<ph name="END_LINK" /> enne, kui kahjulikud rakendused on eemaldatud.</translation>
<translation id="6047927260846328439">See sisu võib meelitada teid installima tarkvara või avaldama isiklikke andmeid. <ph name="BEGIN_LINK" />Kuva ikkagi<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Täisekraanilt väljumiseks vajutage pikalt klahvi |<ph name="ACCELERATOR" />|</translation>
<translation id="6049488691372270142">Lehe esitamine</translation>
<translation id="6051221802930200923">Te ei saa saiti <ph name="SITE" /> praegu külastada, sest veebisait kasutab sertifikaadi kinnitamist. Võrguvead ja -rünnakud on tavaliselt ajutised, nii et leht tõenäoliselt hiljem töötab.</translation>
<translation id="6051898664905071243">Lehtede arv:</translation>
@@ -1374,6 +1412,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<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>
<translation id="6116338172782435947">näha lõikelauale kopeeritud teksti ja kujutisi</translation>
<translation id="6120179357481664955">Kas jätta teie UPI ID meelde?</translation>
+<translation id="6123290840358279103">Kuva virtuaalkaart</translation>
<translation id="6124432979022149706">Chrome Enterprise'i liidesed</translation>
<translation id="6146055958333702838">Kontrollige kaableid ning taaskäivitage kõik ruuterid, modemid ja muud
kasutuses olevad võrguseadmed.</translation>
@@ -1410,6 +1449,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="6289939620939689042">Lehe värv</translation>
<translation id="6290238015253830360">Teie soovitatud artiklid kuvatakse siin</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome'ile mõeldud Google'i assistenti peatatakse</translation>
<translation id="6305205051461490394">URL-iga <ph name="URL" /> ei saa ühendust.</translation>
<translation id="6312113039770857350">Veebileht ei ole saadaval</translation>
@@ -1435,6 +1475,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="6390200185239044127">Z-kujuliselt volditud poolleht</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Saidilt <ph name="ORIGIN_NAME" /> sellesse asukohta kleepimine on administraatori reegliga blokeeritud</translation>
+<translation id="6398765197997659313">Välju täisekraanilt</translation>
<translation id="6401136357288658127">Selle reegli tugi on katkestatud. Peaksite selle asemel kasutama reeglit <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Muuda järjehoidjat</translation>
<translation id="6406765186087300643">C0 (ümbrik)</translation>
@@ -1447,7 +1488,6 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="6428450836711225518">Kinnitage oma telefoninumber</translation>
<translation id="6433490469411711332">Kontaktandmete muutmine</translation>
<translation id="6433595998831338502">Host <ph name="HOST_NAME" /> keeldus ühendamast.</translation>
-<translation id="6434309073475700221">Loobu</translation>
<translation id="6440503408713884761">Eiras</translation>
<translation id="6443406338865242315">Millised laiendused ja pistikprogrammid olete installinud</translation>
<translation id="6446163441502663861">Kahu (ümbrik)</translation>
@@ -1490,6 +1530,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="6624427990725312378">Kontaktteave</translation>
<translation id="6626291197371920147">Kehtiva kaardinumbri lisamine</translation>
<translation id="6628463337424475685"><ph name="ENGINE" />'i otsing</translation>
+<translation id="6630043285902923878">USB-seadmete otsimine …</translation>
<translation id="6630809736994426279">Saidil <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> olevad ründajad võivad proovida installida teie Maci ohtlikke programme, mis varastavad teie teavet või kustutavad selle (nt fotod, paroolid, sõnumid ja krediitkaarditeave). <ph name="BEGIN_LEARN_MORE_LINK" />Lisateave<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Tühjenda</translation>
@@ -1505,6 +1546,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="6671697161687535275">Kas eemaldada Chromiumist vormi soovitus?</translation>
<translation id="6685834062052613830">Logige välja ja viige seadistus lõpule</translation>
<translation id="6687335167692595844">Fondi taotletud suurus</translation>
+<translation id="6688743156324860098">Värskendage …</translation>
<translation id="6689249931105087298">Suhteline, musta punkti tihendamisega</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="6698381487523150993">Loodud:</translation>
@@ -1520,6 +1562,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="6744009308914054259">Ühenduse loomise ajal võite avada jaotise Allalaadimised ja lugeda võrguühenduseta artikleid.</translation>
<translation id="6753269504797312559">Reegli väärtus</translation>
<translation id="6757797048963528358">Teie seade lülitus unerežiimile.</translation>
+<translation id="6767985426384634228">Kas värskendada aadressi?</translation>
<translation id="6768213884286397650">Hagaki (postkaart)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violetne</translation>
@@ -1542,6 +1585,7 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome lihtsustas seda lehte, et seda oleks lihtsam lugeda. Chrome hankis algse lehe ebaturvalise ühenduse kaudu.</translation>
<translation id="6891596781022320156">Reegli taset ei toetata.</translation>
+<translation id="6895143722905299846">Virtuaalne number:</translation>
<translation id="6895330447102777224">Teie kaart on kinnitatud</translation>
<translation id="6897140037006041989">Kasutajaagent</translation>
<translation id="6898699227549475383">Organisatsioon (O)</translation>
@@ -1577,10 +1621,10 @@ Vastasel korral blokeeritakse see teie privaatsusseadetes. See võimaldab teie k
<translation id="7004583254764674281">Kasutage kaartide kiiremaks kinnitamiseks teenust Windows Hello</translation>
<translation id="7006930604109697472">Saada ikkagi</translation>
<translation id="7012363358306927923">Hiina UnionPay</translation>
-<translation id="7012404007611495949">Suuruse muutmise seaded</translation>
<translation id="7014741021609395734">Suumi tase</translation>
<translation id="7016992613359344582">Tasud võivad olla ühekordsed või korduvad ja need ei pruugi olla ilmselged.</translation>
<translation id="7029809446516969842">Paroolid</translation>
+<translation id="7030436163253143341">Sertifikaat ei kehti</translation>
<translation id="7031646650991750659">Millised Google Play rakendused olete installinud</translation>
<translation id="7050187094878475250">Üritasite jõuda domeenile <ph name="DOMAIN" />, kuid server esitas sertifikaadi, mille kehtivusaeg on liiga pikk, et olla usaldusväärne.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Seda kaarti ei saa praegu salvestada}other{Neid kaarte ei saa praegu salvestada}}</translation>
@@ -1650,12 +1694,14 @@ Lisateave:
<translation id="7300012071106347854">Koobaltsinine</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />â€</translation>
<translation id="7304030187361489308">Kõrge</translation>
+<translation id="7305756307268530424">Aeglasemalt alustamine</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Ãœhendamise abi</translation>
<translation id="7323804146520582233">Peida jaotis „<ph name="SECTION" />â€</translation>
<translation id="733354035281974745">Seadme kohaliku konto alistamine</translation>
<translation id="7333654844024768166">Sisestasite äsja oma parooli kahtlasele saidile. Chromium soovitab teil minna veebisaitidele <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ja muudele saitidele, kus seda parooli kasutate, ning kohe oma parooli muuta.</translation>
<translation id="7334320624316649418">&amp;Korrasta uuesti</translation>
+<translation id="7337248890521463931">Kuva rohkem ridu</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>
@@ -1663,6 +1709,7 @@ Lisateave:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Käsurida</translation>
<translation id="7359588939039777303">Reklaamid on blokeeritud.</translation>
+<translation id="7363096869660964304">Te pole siiski nähtamatu. Inkognito režiimi kasutamine ei varja teie sirvimist tööandja, internetiteenuse pakkuja ega külastatavate veebisaitide eest.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, vajutage Chrome'i seadetes aadresside lisamiseks ja haldamiseks tabulaatorit ja seejärel sisestusklahvi</translation>
<translation id="7365849542400970216">Kas teatakse teie seadme kasutuse kohta?</translation>
<translation id="7372973238305370288">otsingutulemus</translation>
@@ -1673,7 +1720,9 @@ Lisateave:
<translation id="7378594059915113390">Meedia juhtnupud</translation>
<translation id="7378627244592794276">Ei</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Pole asjakohane</translation>
<translation id="7390545607259442187">Kaardi kinnitamine</translation>
+<translation id="7392089738299859607">Värskenda aadressi</translation>
<translation id="7399802613464275309">Ohutuskontroll</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Teie seadet <ph name="DEVICE_NAME" /> hallatakse</translation>
@@ -1688,6 +1737,7 @@ Lisateave:
&lt;li&gt;Vaadake &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome'i abikeskusest&lt;/a&gt; teavet selle kohta, kuidas tarkvara arvutist jäädavalt eemaldada
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Armas</translation>
<translation id="7416351320495623771">Halda paroole …</translation>
<translation id="7419106976560586862">Profiili tee</translation>
<translation id="7437289804838430631">Lisa kontaktteave</translation>
@@ -1703,7 +1753,7 @@ Lisateave:
<translation id="7481312909269577407">Edasta</translation>
<translation id="7485870689360869515">Andmeid ei leitud.</translation>
<translation id="7495528107193238112">See sisu on blokeeritud. Probleemi lahendamiseks võtke ühendust saidi omanikuga.</translation>
-<translation id="7498234416455752244">Jätka muutmist</translation>
+<translation id="7498193950643227031">Suuruse muutmisel võib esineda ootamatut käitumist. Saate nüüd menüüs <ph name="SETTINGS" /> piirata rakenduste suuruse muutmise võimalusi.</translation>
<translation id="7503664977220660814">Sisestasite äsja oma parooli kahtlasele saidile. Chromium soovitab teil salvestatud paroole kontrollida saitide <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ja muude saitide puhul, kus praegu seda parooli kasutate.</translation>
<translation id="7508255263130623398">Tagastatud reegli seadme-ID on tühi või ei kattu praeguse seadme-ID-ga</translation>
<translation id="7508870219247277067">Avokaadoroheline</translation>
@@ -1723,6 +1773,7 @@ Lisateave:
<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="755279583747225797">Prooviperiood on aktiivne</translation>
<translation id="7552846755917812628">Proovige järgmiseid nõuandeid.</translation>
<translation id="7554475479213504905">Laadi uuesti ja kuva ikkagi</translation>
<translation id="7554791636758816595">Uus vaheleht</translation>
@@ -1741,7 +1792,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, vajutage Chrome'i seadetes paroolide vaatamiseks ja haldamiseks tabulaatorit ning seejärel sisestusklahvi</translation>
-<translation id="7615602087246926389">Teil on juba andmed, mis on krüpteeritud Google'i konto parooli teise versiooniga. Sisestage see allpool.</translation>
<translation id="7616645509853975347">Teie administraator lülitas teie brauseris sisse teenuse Chrome Enterprise Connectors. Nendel liidestel on juurdepääs osadele teie andmetele.</translation>
<translation id="7619838219691048931">Viimane leht</translation>
<translation id="762844065391966283">Ãœkshaaval</translation>
@@ -1806,13 +1856,12 @@ Lisateave:
<translation id="782886543891417279">WiFi-võrk, mida kasutate (<ph name="WIFI_NAME" />), võib nõuda sisselogimislehe külastamist.</translation>
<translation id="7836231406687464395">Postfix (ümbrik)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Puudub}=1{1 rakendus (<ph name="EXAMPLE_APP_1" />)}=2{2 rakendust (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# rakendust (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Te pole siiski nähtamatu. Inkognito režiimi kasutamine ei varja teie sirvimist tööandja, Interneti-teenuse pakkuja ega külastatavate veebisaitide eest.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Avada failitüübi seostega faile.</translation>
<translation id="7862185352068345852">Kas lahkuda saidilt?</translation>
<translation id="7865448901209910068">Suurim kiirus</translation>
<translation id="7874263914261512992">Sisestasite äsja oma parooli kahtlasele saidile. Chrome soovitab teil salvestatud paroole kontrollida saitide <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ja muude saitide puhul, kus praegu seda parooli kasutate.</translation>
<translation id="7878562273885520351">Teie parool võib olla ohus</translation>
+<translation id="7880146494886811634">Aadressi salvestamine</translation>
<translation id="7882421473871500483">Pruun</translation>
<translation id="7887683347370398519">Kontrollige CVC-d ja proovige uuesti</translation>
<translation id="7887885240995164102">Aktiveeri režiim Pilt pildis</translation>
@@ -1820,6 +1869,7 @@ Lisateave:
<translation id="7894280532028510793">Kui õigekirjavigu pole, <ph name="BEGIN_LINK" />käitage võrgudiagnostika<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (ümbrik)</translation>
<translation id="7931318309563332511">Teadmata</translation>
+<translation id="793209273132572360">Kas värskendada aadressi?</translation>
<translation id="7932579305932748336">Kate</translation>
<translation id="79338296614623784">Sisestage kehtiv telefoninumber</translation>
<translation id="7934052535022478634">Makse on töödeldud</translation>
@@ -1890,6 +1940,7 @@ Lisateave:
<translation id="8175796834047840627">Chrome pakub võimalust salvestada kaardid teie Google'i kontole, kuna olete sisse logitud. Seda käitumist saab seadetes muuta.</translation>
<translation id="8176440868214972690">Seadme administraator on järgmistele veebisaitidele teatud teavet saatnud, näiteks seadete ja eeskirjade teavet.</translation>
<translation id="8184538546369750125">Kasuta globaalset vaikeseadet (luba)</translation>
+<translation id="8193086767630290324">Andmetega seotud tegevused märgitakse konfidentsiaalseks</translation>
<translation id="8194797478851900357">&amp;Võta teisaldamine tagasi</translation>
<translation id="8201077131113104583">ID-ga „<ph name="EXTENSION_ID" />†laienduse kehtetu värskendamise URL.</translation>
<translation id="8202097416529803614">Tellimuse kokkuvõte</translation>
@@ -1912,6 +1963,7 @@ Lisateave:
<translation id="8249296373107784235">Katkesta</translation>
<translation id="8249320324621329438">Viimati toodud:</translation>
<translation id="8253091569723639551">Arveldusaadress on nõutav</translation>
+<translation id="8257387598443225809">See rakendus on loodud mobiilseadmetele</translation>
<translation id="825929999321470778">Kuva kõik salvestatud paroolid</translation>
<translation id="8261506727792406068">Kustuta</translation>
<translation id="8262952874573525464">Õmblus alaservas</translation>
@@ -2035,7 +2087,6 @@ Lisateave:
<translation id="8719528812645237045">Mitu auku ülal</translation>
<translation id="8725066075913043281">Proovi uuesti</translation>
<translation id="8726549941689275341">Lehe suurus:</translation>
-<translation id="8728672262656704056">Olete inkognito režiimis</translation>
<translation id="8730621377337864115">Valmis</translation>
<translation id="8731544501227493793">Nupp Paroolide haldamine, vajutage Chrome'i seadetes paroolide vaatamiseks ja haldamiseks sisestusklahvi</translation>
<translation id="8734529307927223492">Teie seadet <ph name="DEVICE_TYPE" /> haldab <ph name="MANAGER" /></translation>
@@ -2112,6 +2163,7 @@ Lisateave:
<translation id="9020542370529661692">See leht on tõlgitud <ph name="TARGET_LANGUAGE" /> keelde</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Kehtetu)</translation>
+<translation id="9030265603405983977">Mustvalge</translation>
<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>
@@ -2135,6 +2187,7 @@ Lisateave:
<translation id="91108059142052966">Administraatori eeskirjad keelavad ekraanikuva jagamise rakendusega <ph name="APPLICATION_TITLE" />, kui konfidentsiaalne sisu on nähtaval</translation>
<translation id="9114524666733003316">Kaardi kinnitamine …</translation>
<translation id="9114581008513152754">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="9117930699067497412">Värske</translation>
<translation id="9119042192571987207">Ãœles laaditud</translation>
<translation id="9128016270925453879">Reeglid on laaditud</translation>
<translation id="9128870381267983090">Ãœhendumine Internetiga</translation>
@@ -2153,6 +2206,7 @@ Lisateave:
<translation id="9170848237812810038">&amp;Võta tagasi</translation>
<translation id="9171296965991013597">Kas soovite rakendusest väljuda?</translation>
<translation id="9173282814238175921">Ãœks dokument / uus leht</translation>
+<translation id="9173995187295789444">Bluetoothi seadmete otsimine …</translation>
<translation id="917450738466192189">Serveri sertifikaat on kehtetu.</translation>
<translation id="9174917557437862841">Vahelehe vahetamise nupp, vajutage selle vahelehe aktiveerimiseks sisestusklahvi</translation>
<translation id="9179703756951298733">Hallake oma maksete ja krediitkaardi teavet Chrome'i seadetes</translation>
diff --git a/chromium/components/strings/components_strings_eu.xtb b/chromium/components/strings/components_strings_eu.xtb
index 8ed6cf12807..e34f8773c17 100644
--- a/chromium/components/strings/components_strings_eu.xtb
+++ b/chromium/components/strings/components_strings_eu.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Hautatuta badago, Chrome-k txartelaren kopia bat gordeko du gailu honetan inprimakiak azkarrago betetzeko.</translation>
<translation id="1110994991967754504">Hautatu honetarako baimena: <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Desegin berrantolatzea</translation>
+<translation id="1123753900084781868">Istanteko azpitituluak ez daude erabilgarri</translation>
<translation id="1125573121925420732">Baliteke webguneek segurtasuna eguneratu bitartean hainbat abisu jasotzea. Laster hobetuko da egoera.</translation>
<translation id="112840717907525620">Gidalerroaren cachea egoera onean dago</translation>
<translation id="1130564665089811311">"Itzuli orria" botoia: sakatu "Sartu" orria Google Translate-rekin itzultzeko</translation>
@@ -74,6 +75,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="1240347957665416060">Gailuaren izena</translation>
<translation id="124116460088058876">Hizkuntza gehiago</translation>
<translation id="1243027604378859286">Egilea:</translation>
+<translation id="1246424317317450637">Lodia</translation>
<translation id="1250759482327835220">Hurrengoan bizkorrago ordaintzeko, gorde txartela, izena eta fakturazio-helbidea Google-ko kontuan.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sinkronizatuta)</translation>
<translation id="1256368399071562588">&lt;p&gt;Webgune batean sartzen bazara eta hura irekitzen ez bada, lehenik eta behin saiatu arazoak konpontzeko urrats hauek egiten:&lt;/p&gt;
@@ -90,7 +92,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<ph name="BEGIN_LIST" />
<ph name="LIST_ITEM" />leiho honetan ikusten dituzun orriak,
<ph name="LIST_ITEM" />cookieak eta webguneetako datuak,
- <ph name="LIST_ITEM" />kontuaren informazioa (<ph name="LINK_BEGIN" />amaitu saioa<ph name="LINK_END" />).
+ <ph name="LIST_ITEM" />kontuari buruzko informazioa (<ph name="LINK_BEGIN" />amaitu saioa<ph name="LINK_END" />).
<ph name="END_LIST" /></translation>
<translation id="1270502636509132238">Jasotzeko modua</translation>
<translation id="1281476433249504884">1. pilatzailea</translation>
@@ -156,6 +158,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="1476595624592550506">Aldatu pasahitza</translation>
<translation id="1484290072879560759">Aukeratu bidalketa-helbidea</translation>
<translation id="1492194039220927094">Gidalerroen push gaitasuna:</translation>
+<translation id="1495677929897281669">Itzuli fitxara</translation>
<translation id="1501859676467574491">Erakutsi Google-ko kontuko txartelak</translation>
<translation id="1507202001669085618">&lt;p&gt;Internetera konektatzeko saioa hastea eskatzen dizun Wi-Fi atari bat erabiltzen ari bazara ikusiko duzu errore hori.&lt;/p&gt;
&lt;p&gt;Errorea konpontzeko, sakatu ireki nahi duzun orriko &lt;strong&gt;Konektatu&lt;/strong&gt; aukera.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="1532118530259321453">Orriak hau dio:</translation>
<translation id="153384715582417236">Hori da dena, oraingoz!</translation>
<translation id="1536390784834419204">Itzuli orria</translation>
+<translation id="1539840569003678498">Txostenaren bidaltze-data:</translation>
<translation id="154408704832528245">Aukeratu entrega-helbidea</translation>
<translation id="1549470594296187301">JavaScript aktibatu behar da eginbide hau erabiltzeko.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="1682696192498422849">Ertz laburra lehenbizi</translation>
<translation id="168693727862418163">Ezin izan da baliozkotu gidalerroaren balioa haren eskemarekin, eta ez ikusi egingo zaio.</translation>
<translation id="168841957122794586">Zerbitzariaren ziurtagiriak okerreko gako kriptografikoa du.</translation>
+<translation id="1696290444144917273">Ikusi txartel birtualaren xehetasunak</translation>
<translation id="1697532407822776718">Prest zaude!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Zerbitzariak ezin izan du frogatu <ph name="DOMAIN" /> dela; haren segurtasun-ziurtagiriak biharko data duela dirudi. Baliteke oker konfiguratuta dagoelako edo erasotzaile batek zure konexioa atzeman duelako izatea.}other{Zerbitzariak ezin izan du frogatu <ph name="DOMAIN" /> dela; haren segurtasun-ziurtagiriak gaurtik # egunerako data duela dirudi. Baliteke oker konfiguratuta dagoelako edo erasotzaile batek zure konexioa atzeman duelako izatea.}}</translation>
<translation id="1710259589646384581">Sistema eragilea</translation>
+<translation id="1711234383449478798">Ez ikusi egin zaio <ph name="POLICY_NAME" /> gidalerroa ez dagoelako <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> webguneak datuak gorde nahi ditu ordenagailuan modu iraunkorrean</translation>
<translation id="1713628304598226412">2. erretilua</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">3. postontzia</translation>
<translation id="1718029547804390981">Dokumentua handiegia da oharpenak egin ahal izateko.</translation>
<translation id="1721424275792716183">* Nahitaez bete behar da eremua</translation>
+<translation id="1727613060316725209">Ziurtagiriak balio du</translation>
<translation id="1727741090716970331">Zehaztu balio duen txartel-zenbaki bat</translation>
<translation id="1728677426644403582">Web-orri baten iturburua ari zara ikusten</translation>
<translation id="173080396488393970">Ez dira onartzen mota horretako txartelak</translation>
@@ -242,7 +249,6 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Exekutatu Windows-en sare-diagnostikoak<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">Aukeratu duzun zerbitzariak (<ph name="ORIGIN" />) goiburu bat ezarri du; haren arabera, jatorri-gidalerro bat aplikatuko zaie zerbitzari hartako eskaera guztiei. Alabaina, goiburua oker dago eratuta; ondorioz, arakatzaileak ezin du gauzatu <ph name="SITE" /> webgunean sartzeko egin duzun eskaera. Webgunearen segurtasuna eta beste propietate batzuk konfiguratzeko erabili ohi dituzte webguneen eragileek jatorri-gidalerroak.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Eguneratu sinkronizatzeko pasaesaldia.</translation>
<translation id="1787142507584202372">Ireki dituzun fitxak agertuko dira hemen</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />: hainbat ekintza dituzu eskuragarri. Sakatu tabuladorea batetik bestera joateko.</translation>
@@ -275,6 +281,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="1919345977826869612">Iragarkiak</translation>
<translation id="1919367280705858090">Lortu errore-mezu jakin bati buruzko laguntza</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Bat ere ez}=1{1 webgune}other{# webgune}}</translation>
+<translation id="1924727005275031552">Berriak</translation>
<translation id="1945968466830820669">Erakundearen konturako sarbidea gal zenezake, edo nortasuna lapur liezazukete. Pasahitza aldatzea gomendatzen dizu Chromium-ek.</translation>
<translation id="1947454675006758438">Grapa bat goian, eskuinetara</translation>
<translation id="1958218078413065209">Lortu duzun puntuazio handiena <ph name="SCORE" /> da.</translation>
@@ -297,12 +304,14 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="2042213636306070719">7. erretilua</translation>
<translation id="204357726431741734">Hasi saioa Google-ko kontuan gordetako pasahitzak erabiltzeko</translation>
<translation id="2053111141626950936">Ez dira itzuliko <ph name="LANGUAGE" /> darabilten orriak.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Kontrolatzeko aukera abian denean eta aktibo dagoenean, duela gutxi egin dituzun arakatze-jardueren antz handiena duen talde demografikoa zein den zehaztuko du Chrome-k. Iragarleek talde horretarako iragarkiak hauta ditzakete, eta arakatze-historia pribatu mantenduko da gailuan. Egunero eguneratuko da taldea.}=1{Kontrolatzeko aukera abian denean eta aktibo dagoenean, duela gutxi egin dituzun arakatze-jardueren antz handiena duen talde demografikoa zein den zehaztuko du Chrome-k. Iragarleek talde horretarako iragarkiak hauta ditzakete, eta arakatze-historia pribatu mantenduko da gailuan. Egunero eguneratuko da taldea.}other{Kontrolatzeko aukera abian denean eta aktibo dagoenean, duela gutxi egin dituzun arakatze-jardueren antz handiena duen talde demografikoa zein den zehaztuko du Chrome-k. Iragarleek talde horretarako iragarkiak hauta ditzakete, eta arakatze-historia pribatu mantenduko da gailuan. {NUM_DAYS} egunetik behin eguneratuko da taldea.}}</translation>
<translation id="2053553514270667976">Posta-kodea</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 iradokizun}other{# iradokizun}}</translation>
<translation id="2071692954027939183">Automatikoki blokeatu dira jakinarazpenak, normalean ez dituzulako onartzen</translation>
<translation id="2079545284768500474">Desegin</translation>
<translation id="20817612488360358">Erabiltzeko ezarri dira sistemaren proxy-ezarpenak, baina proxy-konfigurazio esplizitu bat ere zehaztu da.</translation>
<translation id="2082238445998314030"><ph name="RESULT_NUMBER" />/<ph name="TOTAL_RESULTS" /> emaitza</translation>
+<translation id="2085876078937250610">Gorde…</translation>
<translation id="2088086323192747268">Sinkronizazioa kudeatzeko botoia, sakatu Sartu Chrome-ren ezarpenetara joan, eta sinkronizatzen den informazioa kudeatzeko</translation>
<translation id="2091887806945687916">Soinua</translation>
<translation id="2094505752054353250">Domeinuak ez datoz bat</translation>
@@ -375,6 +384,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="2317259163369394535"><ph name="DOMAIN" /> domeinuak erabiltzaile-izena eta pasahitza behar ditu.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" /> (iraungitze-data: <ph name="EXPIRATION_DATE_ABBR" />)</translation>
<translation id="2337852623177822836">Administratzaileak kontrolatzen du ezarpena</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> webguneak parekatu egin nahi du</translation>
<translation id="2344028582131185878">Deskarga automatikoak</translation>
<translation id="2346319942568447007">Kopiatu duzun irudia</translation>
<translation id="2354001756790975382">Beste laster-markak</translation>
@@ -382,8 +392,10 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="2355395290879513365">Baliteke erasotzaileak webgune honetan zer irudi ikusi dituzun hautemateko eta, haiek aldatuz, zu engainatzeko gai izatea.</translation>
<translation id="2356070529366658676">Galdetu</translation>
<translation id="2357481397660644965"><ph name="DEVICE_MANAGER" /> domeinuak kudeatzen du gailua; <ph name="ACCOUNT_MANAGER" /> domeinuak, berriz, kontua.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Egun bat baino gutxiago barru}=1{Egun bat barru}other{{NUM_DAYS} egun barru}}</translation>
<translation id="2359629602545592467">Bat baino gehiago</translation>
<translation id="2359808026110333948">Jarraitu</translation>
+<translation id="2359961752320758691">Aplikatu da txartel birtualaren zenbakia.</translation>
<translation id="2367567093518048410">Maila</translation>
<translation id="2372464001869762664">Berretsi ondoren, webgune honekin partekatuko dira Google-ko kontuarekin lotutako txartelaren xehetasunak. Bilatu CVC kodea Plex-eko kontuaren xehetasunetan.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="239429038616798445">Ez dago erabilgarri bidalketa-metodo hori. Saiatu beste metodo batekin.</translation>
<translation id="2396249848217231973">&amp;Desegin ezabatzea</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Zaharrak</translation>
<translation id="2413528052993050574">Zerbitzari honek ezin izan du egiaztatu <ph name="DOMAIN" /> domeinua denik. Bere segurtasun-ziurtagiria baliogabetuta egon liteke. Baliteke gaizki konfiguratuta dagoelako izatea edo erasotzaile batek zure konexioa atzeman duelako izatea.</translation>
<translation id="2414886740292270097">Iluna</translation>
<translation id="2438874542388153331">Lau zulo eskuinean</translation>
@@ -421,10 +434,10 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="2521385132275182522">Grapa bat behean, eskuinetara</translation>
<translation id="2523886232349826891">Gailu honetan soilik gordeko da</translation>
<translation id="2524461107774643265">Gehitu informazio gehiago</translation>
-<translation id="2526590354069164005">Ordenagailua</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{eta beste bat}other{eta beste #}}</translation>
<translation id="2536110899380797252">Gehitu helbidea</translation>
<translation id="2539524384386349900">Hauteman</translation>
+<translation id="2541219929084442027">Ezkutuko moduko fitxetan ikusten dituzun orriak ez dira geratuko arakatzailearen historian, cookieen biltegian edo bilaketa-historian, ezkutuko moduko fitxa guztiak itxi ondoren. Deskargatutako fitxategiak edo sortutako laster-markak mantendu egingo dira.</translation>
<translation id="2544644783021658368">Dokumentu bakarra</translation>
<translation id="254947805923345898">Gidalerroaren balioak ez du balio.</translation>
<translation id="255002559098805027">Ez du balio <ph name="HOST_NAME" /> webguneak bidali duen erantzunak.</translation>
@@ -444,6 +457,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="2629325967560697240">Chrome-ren segurtasun-maila handiena lortzeko, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />aktibatu babes hobetua<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Ezin izan da aurkitu <ph name="HOST_NAME" /> ostalariaren IP helbidea.</translation>
<translation id="2639739919103226564">Egoera:</translation>
+<translation id="264810637653812429">Ez da aurkitu gailu bateragarririk.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />: sakatu tabuladorea eta, ondoren, sakatu Sartu arakatze-historia, cookieak, cachea eta beste garbitzeko Chrome-ren ezarpenetan</translation>
<translation id="2650446666397867134">Fitxategirako sarbidea debekatu da</translation>
@@ -488,6 +502,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="2799223571221894425">Abiarazi berriro</translation>
<translation id="2803306138276472711">Berriki Google-ren Arakatze seguruak <ph name="BEGIN_LINK" />malwarea hauteman du<ph name="END_LINK" /> <ph name="SITE" /> webgunean. Seguruak izan ohi diren webguneak batzuetan malwarearekin kutsatuta egoten dira.</translation>
<translation id="2807052079800581569">Irudiaren Y ardatzaren posizioa</translation>
+<translation id="2820957248982571256">Bilatzen…</translation>
<translation id="2824775600643448204">Helbide- eta bilaketa-barra</translation>
<translation id="2826760142808435982">Konexioa <ph name="CIPHER" /> bidez enkriptatuta eta autentifikatuta dago eta <ph name="KX" /> erabiltzen du gako-trukaketarako mekanismo gisa.</translation>
<translation id="2835170189407361413">Garbitu inprimakia</translation>
@@ -495,6 +510,8 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="2850739647070081192">Invite (gutun-azala)</translation>
<translation id="2856444702002559011">Baliteke erasotzaile batzuk <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> webgunean duzun informazioa lapurtzen saiatzen aritzea (adibidez, pasahitzak, mezuak edo kreditu-txartelen datuak). <ph name="BEGIN_LEARN_MORE_LINK" />Lortu informazio gehiago<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Webgune honek iragarki oztopatzaile edo iruzurrezkoak erakusten ditu.</translation>
+<translation id="287596039013813457">Polita</translation>
+<translation id="2876489322757410363">Ezkutuko modutik irtengo zara kanpoko aplikazio baten bidez ordaintzeko. Aurrera egin nahi duzu?</translation>
<translation id="2878197950673342043">Horma-irudi tolestura</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Leihoen agerpena</translation>
@@ -544,7 +561,6 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="3060227939791841287">C9 (gutun-azala)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />: sakatu tabuladorea eta, ondoren, sakatu Sartu segurtasun-egiaztapena egiteko Chrome-ren ezarpenetan</translation>
<translation id="3061707000357573562">Adabaki-zerbitzua</translation>
-<translation id="3064966200440839136">Ezkutuko modutik irtengo zara kanpoko aplikazio baten bidez ordaintzeko. Aurrera egin nahi duzu?</translation>
<translation id="306573536155379004">Hasi da jokoa.</translation>
<translation id="3080254622891793721">Grafikoa</translation>
<translation id="3086579638707268289">Webgunean egiten ari zarena gainbegiratzen ari dira</translation>
@@ -567,7 +583,6 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="315504272643575312"><ph name="MANAGER" /> domeinuak kudeatzen du kontua.</translation>
<translation id="3157931365184549694">Leheneratu</translation>
<translation id="3162559335345991374">Baliteke darabilzun Wi-Fi konexioaren saio-hasierako orrira joan behar izatea.</translation>
-<translation id="3167968892399408617">Ezkutuko moduko fitxetan ikusten dituzun orriak ez dira geratuko arakatzailearen historian, cookieen biltegian edo bilaketa-historian, ezkutuko moduko fitxa guztiak itxi ondoren. Deskargatutako fitxategiak edo sortutako laster-markak mantendu egingo dira.</translation>
<translation id="3169472444629675720">Ezagutu</translation>
<translation id="3174168572213147020">Uhartea</translation>
<translation id="3176929007561373547">Egiaztatu proxy-ezarpenak edo jarri sarearen administratzailearekin harremanetan proxy-zerbitzaria badabilela ziurtatzeko. Proxy-zerbitzaririk erabili beharko ez zenukeela uste baduzu: <ph name="PLATFORM_TEXT" /></translation>
@@ -590,10 +605,12 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="3229041911291329567">Gailuaren eta arakatzailearen bertsioari buruzko informazioa</translation>
<translation id="323107829343500871">Idatzi <ph name="CREDIT_CARD" /> txartelaren CVC kodea</translation>
<translation id="3234666976984236645">Hauteman beti webgune honetako eduki garrantzitsua</translation>
+<translation id="3249845759089040423">Modakoa</translation>
<translation id="3252266817569339921">Frantsesa</translation>
<translation id="3266793032086590337">Balioa (gatazka)</translation>
<translation id="3268451620468152448">Ireki fitxak</translation>
<translation id="3270847123878663523">&amp;Desegin berrantolatzea</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> webguneak konektatu egin nahi du</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Zure erakundeak (<ph name="ENROLLMENT_DOMAIN" />) ezarpenei eta gidalerroei buruzko informazioa bidali du, besteak beste, jarraian ageri diren webguneetara.</translation>
<translation id="3282497668470633863">Gehitu titularra</translation>
@@ -646,6 +663,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="3428151540071562330">DnsOverHttpsTemplates aukeraren zerbitzariko txantiloien URI batek edo gehiagok ez dute balio, eta ez dira erabiliko.</translation>
<translation id="3431636764301398940">Gorde txartela gailu honetan</translation>
<translation id="3432601291244612633">Itxi orria</translation>
+<translation id="3435738964857648380">Segurtasuna</translation>
<translation id="3435896845095436175">Gaitu</translation>
<translation id="3438829137925142401">Erabili Google-ko kontuan gordetako pasahitzak</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -687,7 +705,10 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="3584299510153766161">Bi zulo behean</translation>
<translation id="3586931643579894722">Ezkutatu xehetasunak</translation>
<translation id="3587738293690942763">Erdia</translation>
+<translation id="3590643883886679995">Ezkutuko modutik irteten zarenean, saioa hasteko datuak gailu honetan gordeko dira.</translation>
+<translation id="359126217934908072">Hilabetea/Urtea:</translation>
<translation id="3592413004129370115">Italian (gutun-azala)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Edozein unetan berrezar dezakezu taldea. Gutxi gorabehera egun bat behar da beste talde batean sartzeko.}=1{Edozein unetan berrezar dezakezu taldea. Gutxi gorabehera egun bat behar da beste talde batean sartzeko.}other{Edozein unetan berrezar dezakezu taldea. Gutxi gorabehera {NUM_DAYS} egun behar dira beste talde batean sartzeko.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" /> (<ph name="TIME" />)</translation>
<translation id="3603507503523709">Administratzaileak aplikazioa blokeatu du</translation>
<translation id="3608932978122581043">Papera sartzeko orientazioa</translation>
@@ -696,13 +717,13 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="3615877443314183785">Idatzi balio duen iraungitze-data bat</translation>
<translation id="36224234498066874">Garbitu arakatze-datuak…</translation>
<translation id="362276910939193118">Erakutsi historia osoa</translation>
-<translation id="3625635938337243871">Ezkutuko modutik irteten zarenean, saioa hasteko datuak gailu honetan gordeko dira.</translation>
<translation id="3630155396527302611">Dagoeneko zerrendatu bada sarean sartzeko baimena duen
programa gisa, kendu zerrendatik eta gehitu berriro.</translation>
<translation id="3630699740441428070">Gailu honen administratzaileek konfiguratu dute sareko konexioa. Hortaz, litekeena da sareko trafikoa ikusi ahal izatea (besteak beste, bisitatzen dituzun webguneak).</translation>
<translation id="3631244953324577188">Sistema biometrikoak</translation>
<translation id="3633738897356909127">"Eguneratu Chrome" botoia: sakatu "Sartu" Chrome eguneratzeko Chrome-ren ezarpenetan</translation>
<translation id="3634530185120165534">5. erretilua</translation>
+<translation id="3637662659967048211">Gorde Google-ko kontuan</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplikazioa:</translation>
<translation id="3650584904733503804">Behar bezala baliozkotu da</translation>
@@ -743,6 +764,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="3781428340399460090">Arrosa bizia</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth bidezko gailuak</translation>
+<translation id="3787675388804467730">Txartel birtualaren zenbakia</translation>
<translation id="3787705759683870569">Iraungitze-data: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Tamaina: 16</translation>
<translation id="3789841737615482174">Instalatu</translation>
@@ -762,6 +784,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="3841184659773414994">Fitxategi-kudeatzaileak</translation>
<translation id="385051799172605136">Atzera</translation>
<translation id="3858027520442213535">Eguneratu data eta ordua</translation>
+<translation id="3881478300875776315">Erakutsi lerro gutxiago</translation>
<translation id="3884278016824448484">Gailu-identifikatzaile gatazkatsua</translation>
<translation id="3885155851504623709">Barrutia</translation>
<translation id="388632593194507180">Sarea kontrolatzen ari direla hauteman da</translation>
@@ -787,6 +810,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="397105322502079400">Kalkulatzen…</translation>
<translation id="3973234410852337861">Blokeatuta dago <ph name="HOST_NAME" /></translation>
<translation id="3973357910713125165">"Egin Chrome-ren segurtasun-egiaztapena" botoia: sakatu "Sartu" segurtasun-egiaztapena egiteko Chrome-ren ezarpenetan</translation>
+<translation id="3986705137476756801">Desaktibatu Istanteko azpitituluak, momentuz</translation>
<translation id="3987405730340719549">Webgune hau faltsua edo iruzurrezkoa izan litekeela zehaztu du Chrome-k.
Abisu honek dioena oker dagoela uste baduzu, joan https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals helbidera.</translation>
@@ -878,13 +902,14 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="4275830172053184480">Berrabiarazi gailua</translation>
<translation id="4277028893293644418">Berrezarri pasahitza</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Google-ko kontuan gorde da txartela}other{Google-ko kontuan gorde dira txartelak}}</translation>
+<translation id="4287885627794386150">Probaldirako egokia da, baina ez dago aktibo</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> orriaren irudi txikia</translation>
<translation id="42981349822642051">Zabaldu</translation>
<translation id="4300675098767811073">Hainbat zulo eskuinean</translation>
<translation id="4302514097724775343">Sakatu dinosauroa jokatzeko</translation>
<translation id="4302965934281694568">Chou3 (gutun-azala)</translation>
<translation id="4305666528087210886">Ezin izan da atzitu fitxategia</translation>
-<translation id="4305817255990598646">Aldatu</translation>
+<translation id="4306529830550717874">Helbidea gorde nahi duzu?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokeatu (lehenetsia)</translation>
<translation id="4314815835985389558">Kudeatu sinkronizazioa</translation>
@@ -911,6 +936,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="4377125064752653719"><ph name="DOMAIN" /> domeinura konektatzen saiatu zara baina zerbitzariak aurkeztutako ziurtagiria baliogabetu egin du bere jaulkitzaileak. Horrek esan nahi du ez zarela inolaz ere fidatu behar zerbitzariak aurkeztutako segurtasun-kredentzialez. Agian erasotzaile batekin komunikatzen ari zara.</translation>
<translation id="4378154925671717803">Telefonoa</translation>
<translation id="4390472908992056574">Markoa</translation>
+<translation id="4406883609789734330">Istanteko azpitituluak</translation>
<translation id="4406896451731180161">bilaketa-emaitza</translation>
<translation id="4408413947728134509">Cookieak: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Webgune engainagarri batean idatzi duzu pasahitza. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> eta <ph name="WEBSITE_3" /> webguneetara eta pasahitz hori erabili duzun beste webgune batzuetara joatea gomendatzen dizu Chrome-k.</translation>
@@ -923,7 +949,6 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Proxya erabiltzeko aukera desgaitu da, baina proxy-konfigurazio esplizitua zehaztu da.</translation>
<translation id="4464826014807964867">Zure erakundeari buruzko informazioa duten webguneak</translation>
-<translation id="4466881336512663640">Inprimakiko aldaketak galdu egingo dira. Ziur aurrera egin nahi duzula?</translation>
<translation id="4476953670630786061">Inprimaki hau ez da segurua. Desaktibatu egin da automatikoki betetzeko aukera.</translation>
<translation id="4477350412780666475">Hurrengo pista</translation>
<translation id="4482953324121162758">Webgune hau ez da itzuliko.</translation>
@@ -957,6 +982,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="4594403342090139922">&amp;Desegin ezabatzea</translation>
<translation id="4597348597567598915">Tamaina: 8</translation>
<translation id="4600854749408232102">C6/C5 (gutun-azala)</translation>
+<translation id="4606870351894164739">Txundigarria</translation>
<translation id="4628948037717959914">Argazkia</translation>
<translation id="4631649115723685955">Dirua berreskuratzeko aukerarekin</translation>
<translation id="4636930964841734540">Informazioa</translation>
@@ -976,6 +1002,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="4691835149146451662">Architecture-A (gutun-azala)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Aldea</translation>
+<translation id="4702656508969495934">Istanteko azpitituluak ikusgai; fokuratzeko, erabili leiho-aldatzailea</translation>
<translation id="4708268264240856090">Eten egin da konexioa</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows-en sare-diagnostikoak exekutatzen<ph name="END_LINK" /></translation>
@@ -989,6 +1016,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="4738601419177586157">Bilaketa-iradokizuna: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Kudeatu pasahitzak…</translation>
<translation id="4744603770635761495">Exekuta daitekeen fitxategiaren bide-izena</translation>
+<translation id="4749011317274908093">Ezkutuko moduan zaude</translation>
<translation id="4750917950439032686">Informazioa (adibidez, pasahitzak edo kreditu-txartelen zenbakiak) eduki pribatu gisa bidaltzen da webgune honetara.</translation>
<translation id="4756388243121344051">&amp;Historia</translation>
<translation id="4758311279753947758">Gehitu harremanetarako informazioa</translation>
@@ -1018,6 +1046,8 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="4813512666221746211">Sareko errorea</translation>
<translation id="4816492930507672669">Egokitu orrira</translation>
<translation id="4819347708020428563">Ikuspegi lehenetsian editatu nahi dituzu oharpenak?</translation>
+<translation id="4825507807291741242">Indartsua</translation>
+<translation id="4838327282952368871">Ametsezkoa</translation>
<translation id="484462545196658690">Automatikoa</translation>
<translation id="4850886885716139402">Ikusi</translation>
<translation id="485316830061041779">Alemana</translation>
@@ -1154,6 +1184,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="5314967030527622926">Koadernagailua</translation>
<translation id="5316812925700871227">Biratu ezkerretara</translation>
<translation id="5317780077021120954">Gorde</translation>
+<translation id="5321288445143113935">Maximizatuta</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> partidatik <ph name="MATCH_POSITION" />garrena</translation>
<translation id="5324080437450482387">Aukeratu harremanetarako informazioa</translation>
<translation id="5327248766486351172">Izena</translation>
@@ -1161,11 +1192,13 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="5332219387342487447">Bidalketa-metodoa</translation>
<translation id="5333022057423422993">Chrome-k erabili berri duzun pasahitza aurkitu du datuen isilpekotasunaren urratze batean. Zure kontuak babesteko, gordeta dauzkazun pasahitzak egiaztatzea gomendatzen dizugu.</translation>
<translation id="5334013548165032829">Sistemaren erregistroen xehetasunak</translation>
+<translation id="5334145288572353250">Helbidea gorde nahi duzu?</translation>
<translation id="5340250774223869109">Aplikazioa blokeatuta dago</translation>
<translation id="534295439873310000">NFC darabilten gailuak</translation>
<translation id="5344579389779391559">Baliteke orri hau dirua kobratzen saiatzea</translation>
<translation id="5355557959165512791">Une honetan ezin zara joan <ph name="SITE" /> webgunera ziurtagiria ukatu egin delako. Sareko erroreak eta erasoak aldi baterakoak izan ohi dira; beraz, geroago funtzionatuko du orriak, segur aski.</translation>
<translation id="536296301121032821">Ezin izan dira gorde gidalerroaren ezarpenak</translation>
+<translation id="5363309033720083897">Administratzaileak onartu duen serieko ataka</translation>
<translation id="5371425731340848620">Eguneratu txartela</translation>
<translation id="5377026284221673050">"Erlojua atzeratuta duzu", "Erlojua aurreratuta duzu" edo "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
<translation id="5386426401304769735">Webgune honen ziurtagiri-kateak SHA-1 bidez sinatutako ziurtagiri bat dauka.</translation>
@@ -1174,6 +1207,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="5398772614898833570">Blokeatu egin dira iragarkiak</translation>
<translation id="5400836586163650660">Grisa</translation>
<translation id="540969355065856584">Zerbitzari honek ezin izan du egiaztatu <ph name="DOMAIN" /> denik. Une honetan, bere segurtasun-ziurtagiriak ez du balio. Oker konfiguratuta dagoelako izan liteke, edo erasotzaile batek zure konexioa atzeman duelako, bestela.</translation>
+<translation id="541143247543991491">Hodeian (sistema osoan)</translation>
<translation id="541416427766103491">4. pilatzailea</translation>
<translation id="5421136146218899937">Garbitu arakatze-datuak…</translation>
<translation id="5426179911063097041"><ph name="SITE" /> webguneak jakinarazpenak bidali nahi dizkizu</translation>
@@ -1187,6 +1221,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="5455374756549232013">Gidalerroaren denbora-zigiluak ez du balio</translation>
<translation id="5457113250005438886">Ez du balio</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> eta beste <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}other{<ph name="CONTACT_PREVIEW" /> eta beste <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
+<translation id="5463625433003343978">Gailuak bilatzen…</translation>
<translation id="5469868506864199649">Italiarra</translation>
<translation id="5470861586879999274">&amp;Berregin editatzea</translation>
<translation id="5478437291406423475">B6/C4 (gutun-azala)</translation>
@@ -1236,7 +1271,6 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="5624120631404540903">Kudeatu pasahitzak</translation>
<translation id="5629630648637658800">Ezin izan dira kargatu gidalerroen ezarpenak</translation>
<translation id="5631439013527180824">Gailu-kudeaketaren tokenak ez du balio</translation>
-<translation id="5632627355679805402">Data honetan hasi ziren enkriptatzen zure datuak <ph name="BEGIN_LINK" />Google pasahitzaren<ph name="END_LINK" /> bidez: <ph name="TIME" />. Idatz ezazu sinkronizatzen hasteko.</translation>
<translation id="5633066919399395251">Baliteke une honetan <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> webgunean dauden erasotzaileak ordenagailuan informazioa (besteak beste, argazkiak, pasahitzak, mezuak eta kreditu-txartelen datuak) lapurtzen edo ezabatzen duten programa arriskutsuak instalatzen saiatzea. <ph name="BEGIN_LEARN_MORE_LINK" />Lortu informazio gehiago<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Eduki iruzurtia blokeatu da.</translation>
<translation id="5644090287519800334">1. aldeko irudia X ardatzaren arabera aldatuta</translation>
@@ -1275,12 +1309,12 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="5785756445106461925">Gainera, orri honetan seguruak ez diren beste baliabide batzuk daude. Bidean dauden bitartean, beste pertsonek baliabide horiek ikus ditzakete eta erasotzaileek aldatu egin ditzakete orriaren portaera aldatzeko.</translation>
<translation id="5786044859038896871">Txartelaren datuak betetzea nahi duzu?</translation>
<translation id="578633867165174378">Chrome-k erabili berri duzun pasahitza aurkitu du datuen isilpekotasunaren urratze batean. Pasahitz hori berehala aldatzea gomendatzen dizugu.</translation>
-<translation id="5798290721819630480">Aldaketak baztertu nahi dituzu?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" /> txartelaren datuak betetzea nahi duzu?</translation>
<translation id="5804241973901381774">Baimenak</translation>
<translation id="5804427196348435412">Erabili NFC bidezko gailuak</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> domeinurako konexioa enkriptatze multzo zaharkitu bat erabilita enkriptatu da.</translation>
<translation id="5813119285467412249">&amp;Berregin gehitzea</translation>
+<translation id="5817918615728894473">Parekatu</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Ordaintzen duzunean, txartel honetan kobratuko dizugu zenbatekoa, baina txartelaren benetako zenbakia ez dugu partekatu webgunearekin. Segurtasun gehiago izateko, aldi baterako CVC kode bat sortuko dugu.}other{Ordaintzen duzunean, txartel honetan kobratuko dizugu zenbatekoa, baina txartelaren benetako zenbakia ez dugu partekatu webgunearekin. Segurtasun gehiago izateko, aldi baterako CVC kode bat sortuko dugu.}}</translation>
<translation id="5826507051599432481">Izen arrunta (CN)</translation>
<translation id="5838278095973806738">Ez zenuke kontuzko informaziorik (adibidez, pasahitzak edo kreditu-txartelak) eman behar webgune honetan, erasotzaileek lapur lezaketelako.</translation>
@@ -1288,6 +1322,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="5855253129151731373">Webgune honen eta <ph name="LOOKALIKE_DOMAIN" /> webgunearen ostalari-izenak antzekoak dira. Batzuetan, erasotzaileek webgune ofizialen plantak egiten dituzte domeinu-izenari aldaketa oso txikiak eginda.
Abisu honek dioena oker dagoela uste baduzu, joan https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals helbidera.</translation>
+<translation id="5860033963881614850">Desaktibatuta</translation>
<translation id="5862579898803147654">8. pilatzailea</translation>
<translation id="5863847714970149516">Baliteke orria dirua kobratzen saiatzea</translation>
<translation id="5866257070973731571">Gehitu telefono-zenbakia</translation>
@@ -1304,6 +1339,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="5913377024445952699">Pausatu da pantaila-argazkiak ateratzeko aukera</translation>
<translation id="59174027418879706">Gaituta</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 ari zara erabiltzen}other{# ari zara erabiltzen}}</translation>
<translation id="5921185718311485855">Aktibatuta</translation>
<translation id="5921639886840618607">Google-ko kontuan gorde nahi duzu txartela?</translation>
<translation id="5922853866070715753">Ia amaitu da</translation>
@@ -1323,6 +1359,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="5989320800837274978">Ez da zehaztu proxy-zerbitzari finkorik, ezta .pac scripteko URLrik ere.</translation>
<translation id="5992691462791905444">Z-erako tolestura laburra</translation>
<translation id="6000758707621254961">"<ph name="SEARCH_TEXT" />" bilaketak <ph name="RESULT_COUNT" /> emaitza ditu</translation>
+<translation id="6006484371116297560">Klasikoa</translation>
<translation id="6008122969617370890">N-tik 1erako ordena</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Egiaztatu pasahitzak</translation>
@@ -1344,6 +1381,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="6045164183059402045">Ezarritako txantiloia</translation>
<translation id="6047233362582046994">Eragiten dituen segurtasun-arriskuak ulertzen badituzu, <ph name="BEGIN_LINK" />webgune hau ikusi beharko zenuke<ph name="END_LINK" /> aplikazio kaltegarriak kendu aurretik.</translation>
<translation id="6047927260846328439">Eduki hau iruzur egiten saia liteke softwarea instala dezazun edo informazio pertsonala eman diezaiozun. <ph name="BEGIN_LINK" />Erakutsi, hala ere<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Pantaila osotik irteteko, eduki sakatuta |<ph name="ACCELERATOR" />|</translation>
<translation id="6049488691372270142">Orrien entrega</translation>
<translation id="6051221802930200923">Une honetan ezin zara joan <ph name="SITE" /> webgunera, ziurtagiri-ainguratzea baitarabil. Sareko erroreak eta erasoak aldi baterakoak izan ohi dira; beraz, geroago funtzionatuko du orriak, segur aski.</translation>
<translation id="6051898664905071243">Orri kopurua:</translation>
@@ -1360,6 +1398,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="610911394827799129">Google-ko kontuko arakatze-historiaren bestelako datu batzuk gera litezke <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> webgunean.</translation>
<translation id="6116338172782435947">Ikusi arbelean kopiatzen ditudan testuak eta irudiak</translation>
<translation id="6120179357481664955">Gogoan al duzu UPIko IDa?</translation>
+<translation id="6123290840358279103">Ikusi txartel birtuala</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Egiaztatu kableak konektatuta daudela eta berrabiarazi erabiltzen ari zaren bideratzaile, modem eta sare-gailu oro.</translation>
<translation id="614940544461990577">Konpontzeko, hauek egin ditzakezu:</translation>
@@ -1395,6 +1434,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="6289939620939689042">Orriaren kolorea</translation>
<translation id="6290238015253830360">Iradokitako artikuluak agertuko zaizkizu hemen</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome-rako Google-ren Laguntzailea gelditzen</translation>
<translation id="6305205051461490394">Ezin da konektatu <ph name="URL" /> webgunera.</translation>
<translation id="6312113039770857350">Ez dago erabilgarri web-orria</translation>
@@ -1420,6 +1460,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="6390200185239044127">Erdibitzeko Z-erako tolestura</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Administratzailearen gidalerroek blokeatu egin dute <ph name="ORIGIN_NAME" /> domeinuko edukia kokapen honetan itsasteko aukera</translation>
+<translation id="6398765197997659313">Irten pantaila osoko modutik</translation>
<translation id="6401136357288658127">Gidalerro hau zaharkituta dago. Horren ordez <ph name="NEW_POLICY" /> gidalerroa erabili beharko zenuke.</translation>
<translation id="6404511346730675251">Editatu laster-marka</translation>
<translation id="6406765186087300643">C0 (gutun-azala)</translation>
@@ -1432,7 +1473,6 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="6428450836711225518">Egiaztatu telefono-zenbakia</translation>
<translation id="6433490469411711332">Editatu harremanetarako informazioa</translation>
<translation id="6433595998831338502">Konexioa baztertu du <ph name="HOST_NAME" /> webguneak.</translation>
-<translation id="6434309073475700221">Baztertu</translation>
<translation id="6440503408713884761">Ez ikusi egin zaio</translation>
<translation id="6443406338865242315">Instalatuta dauzkazun luzapenak eta pluginak.</translation>
<translation id="6446163441502663861">Kahu (gutun-azala)</translation>
@@ -1475,6 +1515,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="6624427990725312378">Harremanetarako informazioa</translation>
<translation id="6626291197371920147">Zehaztu balio duen txartel-zenbaki bat</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Bilaketa</translation>
+<translation id="6630043285902923878">USB bidezko gailuak bilatzen…</translation>
<translation id="6630809736994426279">Baliteke une honetan <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> webgunean dauden erasotzaileak informazioa (besteak beste, argazkiak, pasahitzak, mezuak eta kreditu-txartelen datuak) lapurtzen edo ezabatzen duten programa arriskutsuak instalatzen saiatzea. <ph name="BEGIN_LEARN_MORE_LINK" />Lortu informazio gehiago<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Garbitu</translation>
@@ -1490,6 +1531,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="6671697161687535275">Inprimaki-iradokizuna Chromium-etik kendu nahi duzu?</translation>
<translation id="6685834062052613830">Amaitu saioa eta osatu konfigurazioa</translation>
<translation id="6687335167692595844">Eskatutako letra-tamaina</translation>
+<translation id="6688743156324860098">Eguneratu…</translation>
<translation id="6689249931105087298">Erlatiboa, puntu beltzen konprimaketarekin</translation>
<translation id="6689271823431384964">Saioa hasita duzunez, txartelak Google-ko kontuan gordetzeko aukera ematen dizu Chrome-k. Aukera hori aldatzeko, joan Ezarpenak atalera. Txartelaren titularraren izena kontutik hartu da.</translation>
<translation id="6698381487523150993">Sortze-data:</translation>
@@ -1505,6 +1547,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="6744009308914054259">Konexio baten zain zauden bitartean, Deskargak atalera joan zaitezke konexiorik behar ez duten artikuluak irakurtzera.</translation>
<translation id="6753269504797312559">Gidalerroaren balioa</translation>
<translation id="6757797048963528358">Inaktibo geratu da gailua.</translation>
+<translation id="6767985426384634228">Helbidea eguneratu nahi duzu?</translation>
<translation id="6768213884286397650">Hagaki (postala)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Bioleta</translation>
@@ -1527,6 +1570,7 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome-k sinplifikatu egin du orri hau errazago irakurri ahal izan dadin. Segurua ez den konexio baten bidez eskuratu du jatorrizko orria.</translation>
<translation id="6891596781022320156">Ez da gidalerroen maila onartzen.</translation>
+<translation id="6895143722905299846">Zenbaki birtuala:</translation>
<translation id="6895330447102777224">Berretsi da txartela</translation>
<translation id="6897140037006041989">Erabiltzaile-agentea</translation>
<translation id="6898699227549475383">Erakundea (O)</translation>
@@ -1562,10 +1606,10 @@ Bestela, pribatutasun-ezarpenek blokeatu egingo dute baimen hori. Baimen honekin
<translation id="7004583254764674281">Erabili Windows Hello txartelak bizkorrago berresteko</translation>
<translation id="7006930604109697472">Bidali hala ere</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Tamaina aldatzeko ezarpenak</translation>
<translation id="7014741021609395734">Zoom-maila</translation>
<translation id="7016992613359344582">Behin edo gehiagotan kobratzen saia liteke, eta baliteke zordunketa horiek begien bistakoak ez izatea.</translation>
<translation id="7029809446516969842">Pasahitzak</translation>
+<translation id="7030436163253143341">Ziurtagiriak ez du balio</translation>
<translation id="7031646650991750659">Instalatuta dauzkazun Google Play-ko aplikazioak.</translation>
<translation id="7050187094878475250"><ph name="DOMAIN" /> atzitzen saiatu zara, baina zerbitzariak balio-epe luzeegia duen ziurtagiri bat aurkeztu du eta ez da fidagarria.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Ezin da gorde txartela une honetan}other{Ezin dira gorde txartelak une honetan}}</translation>
@@ -1635,12 +1679,14 @@ Xehetasun gehiago:
<translation id="7300012071106347854">Kobaltoa</translation>
<translation id="7302712225291570345">“<ph name="TEXT" />â€</translation>
<translation id="7304030187361489308">Altua</translation>
+<translation id="7305756307268530424">Hasi motelago</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Konexioari buruzko laguntza</translation>
<translation id="7323804146520582233">Ezkutatu "<ph name="SECTION" />" atala</translation>
<translation id="733354035281974745">Gailuko kontua ordeztea</translation>
<translation id="7333654844024768166">Webgune engainagarri batean idatzi duzu pasahitza. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> eta <ph name="WEBSITE_3" /> webguneetara eta pasahitz hori erabili duzun beste webgune batzuetara joatea eta pasahitza aldatzea gomendatzen dizu Chromium-ek.</translation>
<translation id="7334320624316649418">&amp;Berregin berrantolatzea</translation>
+<translation id="7337248890521463931">Erakutsi lerro gehiago</translation>
<translation id="7337706099755338005">Ez dago erabilgarri darabilzun plataforman.</translation>
<translation id="733923710415886693">Zerbitzariaren ziurtagiria ez da ezagutarazi ziurtagirien gardentasun-gidalerroa erabilita.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1648,6 +1694,7 @@ Xehetasun gehiago:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Agindu-lerroa</translation>
<translation id="7359588939039777303">Blokeatu egin dira iragarkiak</translation>
+<translation id="7363096869660964304">Hala ere, ez zara ikusgaitz izango. Ezkutuko moduan egoteak ez du esan nahi zure enpresak, Interneteko zerbitzu-hornitzaileak edota bisitatzen dituzun webguneek arakatzen dituzun edukiak ikusi ezingo dituztenik.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, sakatu tabuladorea eta, ondoren, sakatu Sartu Chrome-ren ezarpenetara joan, eta helbideak gehitzeko eta kudeatzeko</translation>
<translation id="7365849542400970216">Gailuaren erabilera ezagutzeko baimena eman nahi diozu?</translation>
<translation id="7372973238305370288">bilaketa-emaitza</translation>
@@ -1658,7 +1705,9 @@ Xehetasun gehiago:
<translation id="7378594059915113390">Multimedia-edukia kontrolatzeko aukerak</translation>
<translation id="7378627244592794276">Ez</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ez aplikagarria</translation>
<translation id="7390545607259442187">Berretsi txartela</translation>
+<translation id="7392089738299859607">Eguneratu helbidea</translation>
<translation id="7399802613464275309">Segurtasun-egiaztapena</translation>
<translation id="7400418766976504921">URLa</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> gailuak kudeatzailea du</translation>
@@ -1673,6 +1722,7 @@ Xehetasun gehiago:
&lt;li&gt;Softwarea ordenagailutik betiko kentzeari buruzko informazio gehiago lortzeko, joan &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome laguntza-zentrora.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Atsegina</translation>
<translation id="7416351320495623771">Kudeatu pasahitzak…</translation>
<translation id="7419106976560586862">Profilaren bide-izena</translation>
<translation id="7437289804838430631">Gehitu harremanetarako informazioa</translation>
@@ -1688,7 +1738,7 @@ Xehetasun gehiago:
<translation id="7481312909269577407">Aurrera</translation>
<translation id="7485870689360869515">Ez da daturik aurkitu</translation>
<translation id="7495528107193238112">Eduki hori blokeatuta dago. Jarri harremanetan webgunearen arduradunarekin arazoa konpontzeko.</translation>
-<translation id="7498234416455752244">Jarraitu editatzen</translation>
+<translation id="7498193950643227031">Tamaina aldatuz gero, baliteke ustekabeko portaera bat izatea. Aplikazioen tamaina aldatzeko aukera mugatzeko, joan <ph name="SETTINGS" /> atalera.</translation>
<translation id="7503664977220660814">Webgune engainagarri batean idatzi duzu pasahitza. <ph name="WEBSITE_1" /> eta <ph name="WEBSITE_2" /> webguneetarako eta pasahitz hori erabili duzun beste webgune batzuetarako gordetako pasahitzak egiaztatzea gomendatzen dizu Chromium-ek.</translation>
<translation id="7508255263130623398">Itzuli den gidalerroaren gailu IDa hutsik dago edo ez dator bat gailuaren IDarekin</translation>
<translation id="7508870219247277067">Ahuakatea</translation>
@@ -1708,6 +1758,7 @@ Xehetasun gehiago:
<translation id="7548892272833184391">Konpondu konexio-erroreak</translation>
<translation id="7549584377607005141">Web-orriak lehen idatzitako datuak behar ditu behar bezala bistaratzeko. Datuak berriro bidal ditzakezu, baina, hori eginez gero, orriak lehen egindako ekintza bera gauzatuko du berriro.</translation>
<translation id="7550637293666041147">Gailuko eta Chrome-ko erabiltzaile-izenak</translation>
+<translation id="755279583747225797">Probaldia aktibo dago</translation>
<translation id="7552846755917812628">Saiatu hauek egiten:</translation>
<translation id="7554475479213504905">Kargatu berriro eta erakutsi, hala ere</translation>
<translation id="7554791636758816595">Fitxa berria</translation>
@@ -1726,7 +1777,6 @@ Xehetasun gehiago:
<translation id="7610193165460212391">Balioa barrutitik kanpo dago: <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Iraungitze-data: <ph name="EXPIRATION_YEAR" />/<ph name="EXPIRATION_MONTH" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />: sakatu tabuladorea eta, ondoren, sakatu Sartu pasahitzak ikusi eta kudeatzeko Chrome-ren ezarpenetan</translation>
-<translation id="7615602087246926389">Badituzu Google-ko kontuko pasahitzaren beste bertsio bat erabilita enkriptatu diren datuak. Idatzi pasahitza hemen behean.</translation>
<translation id="7616645509853975347">Administratzaileak Chrome Enterprise Connectors gaitu du arakatzailean. Konektore horiek zure datu batzuetarako sarbidea dute.</translation>
<translation id="7619838219691048931">Amaierako orria</translation>
<translation id="762844065391966283">Banaka</translation>
@@ -1791,13 +1841,12 @@ Xehetasun gehiago:
<translation id="782886543891417279">Baliteke darabilzun Wi-Fi konexioaren (<ph name="WIFI_NAME" />) saio-hasierako orrira joan behar izatea.</translation>
<translation id="7836231406687464395">Postfix (gutun-azala)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Bat ere ez}=1{1 aplikazio (<ph name="EXAMPLE_APP_1" />)}=2{2 aplikazio (<ph name="EXAMPLE_APP_1" /> eta <ph name="EXAMPLE_APP_2" />)}other{# aplikazio (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> eta<ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Hala ere, ez zara ikusgaitz izango. Ezkutuko moduan egoteak ez du esan nahi zure enpresak, Interneteko zerbitzu-hornitzaileak edota bisitatzen dituzun orriek arakatzen dituzun edukiak ikusi ezingo dituztenik.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Fitxategiak ireki fitxategi moten loturekin.</translation>
<translation id="7862185352068345852">Webgunetik irten nahi duzu?</translation>
<translation id="7865448901209910068">Abiadurarik onena</translation>
<translation id="7874263914261512992">Webgune engainagarri batean idatzi duzu pasahitza. <ph name="WEBSITE_1" /> eta <ph name="WEBSITE_2" /> webguneetarako eta pasahitz hori erabili duzun beste webgune batzuetarako gordetako pasahitzak egiaztatzea gomendatzen dizu Chrome-k.</translation>
<translation id="7878562273885520351">Baliteke pasahitza arriskuan egotea</translation>
+<translation id="7880146494886811634">Gorde helbidea</translation>
<translation id="7882421473871500483">Marroia</translation>
<translation id="7887683347370398519">Begiratu CVC kodea eta saiatu berriro</translation>
<translation id="7887885240995164102">Sartu pantaila txiki gainjarriko moduan</translation>
@@ -1805,6 +1854,7 @@ Xehetasun gehiago:
<translation id="7894280532028510793">Behar bezala idatzita badago, <ph name="BEGIN_LINK" />exekutatu sare-diagnostikoak<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (gutun-azala)</translation>
<translation id="7931318309563332511">Ezezaguna</translation>
+<translation id="793209273132572360">Helbidea eguneratu nahi duzu?</translation>
<translation id="7932579305932748336">Forratu</translation>
<translation id="79338296614623784">Idatzi balio duen telefono-zenbaki bat</translation>
<translation id="7934052535022478634">Egin da ordainketa</translation>
@@ -1875,6 +1925,7 @@ Xehetasun gehiago:
<translation id="8175796834047840627">Saioa hasita duzunez, txartelak Google-ko kontuan gordetzeko aukera ematen dizu Chrome-k. Aukera hori aldatzeko, joan Ezarpenak atalera.</translation>
<translation id="8176440868214972690">Gailuaren administratzaileak ezarpenei eta gidalerroei buruzko informazioa bidali du, besteak beste, jarraian ageri diren webguneetara.</translation>
<translation id="8184538546369750125">Erabili lehenespen globala (Baimendu)</translation>
+<translation id="8193086767630290324">Konfidentzial gisa markatuta dauden datuak dituzten hartutako ekintzak</translation>
<translation id="8194797478851900357">&amp;Desegin mugitzea</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" IDa duen luzapena eguneratzeko URLak ez du balio.</translation>
<translation id="8202097416529803614">Eskaeraren laburpena</translation>
@@ -1897,6 +1948,7 @@ Xehetasun gehiago:
<translation id="8249296373107784235">Utzi bertan behera</translation>
<translation id="8249320324621329438">Eskuratutako azkena:</translation>
<translation id="8253091569723639551">Fakturazio-helbidea behar da</translation>
+<translation id="8257387598443225809">Mugikorretan erabiltzeko dago diseinatuta aplikazioa</translation>
<translation id="825929999321470778">Erakutsi gordetako pasahitz guztiak</translation>
<translation id="8261506727792406068">Ezabatu</translation>
<translation id="8262952874573525464">Beheko ertza josita</translation>
@@ -2020,7 +2072,6 @@ Xehetasun gehiago:
<translation id="8719528812645237045">Hainbat zulo goian</translation>
<translation id="8725066075913043281">Saiatu berriro</translation>
<translation id="8726549941689275341">Orriaren tamaina:</translation>
-<translation id="8728672262656704056">Ezkutuko moduan zaude</translation>
<translation id="8730621377337864115">Eginda</translation>
<translation id="8731544501227493793">"Kudeatu pasahitzak" botoia: sakatu "Sartu"·pasahitzak ikusi eta kudeatzeko Chrome-ren ezarpenetan</translation>
<translation id="8734529307927223492"><ph name="MANAGER" /> domeinuak kudeatzen du <ph name="DEVICE_TYPE" /> gailua</translation>
@@ -2097,6 +2148,7 @@ Xehetasun gehiago:
<translation id="9020542370529661692">Orria <ph name="TARGET_LANGUAGE" /> hizkuntzara itzuli da</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ez du balio)</translation>
+<translation id="9030265603405983977">Monokromoa</translation>
<translation id="9035022520814077154">Segurtasun-errorea</translation>
<translation id="9038649477754266430">Erabili iragarpen-zerbitzua orriak bizkorrago kargatzeko</translation>
<translation id="9039213469156557790">Gainera, orri honetan seguruak ez diren beste baliabide batzuk daude. Bidean dauden bitartean, beste pertsonek baliabide horiek ikus ditzakete eta erasotzaileek aldatu egin ditzakete orriaren portaera aldatzeko.</translation>
@@ -2120,6 +2172,7 @@ Xehetasun gehiago:
<translation id="91108059142052966">Administratzailearen gidalerroek <ph name="APPLICATION_TITLE" /> bidez pantaila partekatzea eragozten dute isilpeko edukia ikusgai dagoenean</translation>
<translation id="9114524666733003316">Txartela berresten…</translation>
<translation id="9114581008513152754">Arakatzailea ez du enpresa edo erakunde batek kudeatzen. Baliteke gailu honetako jarduerak Chrome-tik kanpo kudeatzea. <ph name="BEGIN_LINK" />Lortu informazio gehiago<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Freskoa</translation>
<translation id="9119042192571987207">Kargatuta</translation>
<translation id="9128016270925453879">Kargatu dira gidalerroak</translation>
<translation id="9128870381267983090">Konektatu sarera</translation>
@@ -2138,6 +2191,7 @@ Xehetasun gehiago:
<translation id="9170848237812810038">&amp;Desegin</translation>
<translation id="9171296965991013597">Aplikaziotik irten nahi duzu?</translation>
<translation id="9173282814238175921">Dokumentu bakarra / Orri berria</translation>
+<translation id="9173995187295789444">Bluetooth bidezko gailuak bilatzen…</translation>
<translation id="917450738466192189">Zerbitzariaren ziurtagiriak ez du balio.</translation>
<translation id="9174917557437862841">Fitxa aldatzeko botoia. Fitxa honetara joateko, sakatu Sartu.</translation>
<translation id="9179703756951298733">Kudeatu ordainketak eta kreditu-txartelari buruzko informazioa Chrome-ren ezarpenetan</translation>
diff --git a/chromium/components/strings/components_strings_fa.xtb b/chromium/components/strings/components_strings_fa.xtb
index de2df07b411..7ef82b6ecfb 100644
--- a/chromium/components/strings/components_strings_fa.xtb
+++ b/chromium/components/strings/components_strings_fa.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">â€Ø§Ú¯Ø± علامت زده شود، Chrome یک Ú©Ù¾ÛŒ از این کارت را در دستگاه نگهداری می‌کند تا برای پرکردن Ùرم‌ها از آن استÙاده شود.</translation>
<translation id="1110994991967754504">مجوز <ph name="PERMISSION_NAME" /> را انتخاب کنید</translation>
<translation id="1113869188872983271">&amp;واگرد ترتیب‌بندی مجدد</translation>
+<translation id="1123753900084781868">درحال‌حاضر «زیرنویس ناشنوایان زنده» در دسترس نیست</translation>
<translation id="1125573121925420732">در مدتی Ú©Ù‡ وب‌سایت‌ها امنیتشان را به‌روزرسانی می‌کنند، ممکن است به‌طور معمول اخطارهایی دریاÙت کنید. این مورد به‌زودی اصلاح می‌شود.</translation>
<translation id="112840717907525620">حاÙظه پنهان خط‌مشی مورد تأیید است</translation>
<translation id="1130564665089811311">â€Ø¯Ú©Ù…Ù‡ «ترجمه صÙحه»، برای ترجمه کردن این صÙحه بااستÙاده از «ترجمه Google»، کلید Enter (ورود) را Ùشار دهید</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">نام دستگاهتان</translation>
<translation id="124116460088058876">زبان‌های بیشتر</translation>
<translation id="1243027604378859286">نویسنده:</translation>
+<translation id="1246424317317450637">سیاه</translation>
<translation id="1250759482327835220">â€Ø¨Ø±Ø§ÛŒ اینکه دÙعه بعد پرداخت سریع‌تری داشته باشید، اطلاعات کارت، نام Ùˆ نشانی صورت‌حسابتان را در حساب Google خود ذخیره کنید.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />، <ph name="TYPE_2" /> (همگام‌سازی‌شده)</translation>
<translation id="1256368399071562588">â€&lt;p&gt;اگر می‌خواهید از وب‌سایتی بازدید کنید Ùˆ باز نمی‌شود، ابتدا سعی کنید با این مراحل عیب‌یابی خطا را برطر٠کنید:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">گذرواژه‌تان را تغییر دهید</translation>
<translation id="1484290072879560759">انتخاب نشانی تحویل کالا</translation>
<translation id="1492194039220927094">اعمال خط‌مشی‌ها:</translation>
+<translation id="1495677929897281669">برگشتن به برگه</translation>
<translation id="1501859676467574491">â€Ú©Ø§Ø±Øªâ€ŒÙ‡Ø§ را از حساب Google خود نمایش دهید</translation>
<translation id="1507202001669085618">â€&lt;p&gt;اگر از پورتالی از Wi-Fi استÙاده می‌کنید Ú©Ù‡ پیش از آنلاین شدن شما را ملزم به ورود به سیستم می‌کند، این خطا را می‌بینید.&lt;/p&gt;
&lt;p&gt;برای برطر٠کردن این خطا، در صÙحه‌ای Ú©Ù‡ می‌خواهید باز کنید روی &lt;strong&gt;اتصال&lt;/strong&gt; کلیک کنید.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">این صÙحه می‌گوید</translation>
<translation id="153384715582417236">درحال‌حاضر مورد دیگری وجود ندارد</translation>
<translation id="1536390784834419204">ترجمه صÙحه</translation>
+<translation id="1539840569003678498">گزارش ارسال شد:</translation>
<translation id="154408704832528245">انتخاب نشانی ارسال</translation>
<translation id="1549470594296187301">برای استÙاده از این قابلیت، جاوا اسکریپت باید Ùعال باشد.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">ابتدا لبه کوتاه</translation>
<translation id="168693727862418163">این مقدار خط‌مشی در رابطه با طرح آن تأیید نشده است Ùˆ نادیده گرÙته می‌شود.</translation>
<translation id="168841957122794586">گواهی‌نامه سرور دارای یک کلید رمزنگاری ضعی٠است.</translation>
+<translation id="1696290444144917273">مشاهده جزئیات کارت مجازی</translation>
<translation id="1697532407822776718">همه چیز مرتب است.</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{این سرور نتوانست ثابت کند این <ph name="DOMAIN" /> است؛ اعتبار گواهی امنیتی آن ظاهراً Ùردا شروع می‌شود. ممکن است علت این موضوع پیکربندی اشتباه باشد یا مهاجمی اتصالتان را قطع می‌کند.}one{این سرور نتوانست ثابت کند این <ph name="DOMAIN" /> است؛ اعتبار گواهی امنیتی آن ظاهراً # روز دیگر شروع می‌شود. ممکن است علت این موضوع پیکربندی اشتباه باشد یا مهاجمی اتصالتان را قطع می‌کند.}other{این سرور نتوانست ثابت کند این <ph name="DOMAIN" /> است؛ اعتبار گواهی امنیتی آن ظاهراً # روز دیگر شروع می‌شود. ممکن است علت این موضوع پیکربندی اشتباه باشد یا مهاجمی اتصالتان را قطع می‌کند.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">نادیده گرÙته شده است زیرا <ph name="POLICY_NAME" /> روی <ph name="VALUE" /> تنظیم نشده است.</translation>
<translation id="1712552549805331520"><ph name="URL" /> می‌خواهد داده‌ها را برای همیشه در رایانه محلی‌تان ذخیره کند</translation>
<translation id="1713628304598226412">سینی ۲</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">صندوق پست ۳</translation>
<translation id="1718029547804390981">این سند بسیار بزرگ است و نمی‌تواند حاشیه‌نویسی شود</translation>
<translation id="1721424275792716183">* این Ùیلد اجباری است</translation>
+<translation id="1727613060316725209">گواهینامه معتبر است</translation>
<translation id="1727741090716970331">اÙزودن شماره کارت معتبر</translation>
<translation id="1728677426644403582">درحال مشاهده منبع یک صÙحه وب هستید</translation>
<translation id="173080396488393970">این نوع کارت پشتیبانی نمی‌شود</translation>
@@ -246,7 +253,6 @@
مرورگر درخواستتان را برای <ph name="SITE" /> اجرا کند. اپراتورهای سایت می‌توانند از
خط‌مشی‌های اصلی برای پیکربندی امنیت Ùˆ دیگر ویژگی‌های سایت استÙاده کنند.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">لطÙاً «گذرعبارتی همگام‌سازی» خود را به‌روزرسانی کنید.</translation>
<translation id="1787142507584202372">برگه‌های بازتان در اینجا نشان داده می‌شوند</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742">â€<ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ چند کنش دردسترس است، برای جابه‌جایی بین آن‌ها، کلید Tab را Ùشار دهید</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">آگهی‌ها</translation>
<translation id="1919367280705858090">دریاÙت راهنمایی برای پیام خطایی خاص</translation>
<translation id="192020519938775529">{COUNT,plural, =0{هیچ‌کدام}=1{۱ سایت}one{# سایت}other{# سایت}}</translation>
+<translation id="1924727005275031552">جدید</translation>
<translation id="1945968466830820669">â€Ù…Ù…Ú©Ù† است دسترسی به حساب سازمانتان را از دست بدهید یا به سرقت هویت دچار شوید. Chromium توصیه می‌کند هم‌اکنون گذرواژه‌تان را تغییر دهید.</translation>
<translation id="1947454675006758438">منگنه در بالا راست</translation>
<translation id="1958218078413065209">بالاترین امتیاز شما <ph name="SCORE" /> است.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">سینی ۷</translation>
<translation id="204357726431741734">â€ÙˆØ±ÙˆØ¯ به سیستم برای استÙاده از گذرواژه‌های ذخیره‌شده در «حساب Google»</translation>
<translation id="2053111141626950936">صÙحه‌های <ph name="LANGUAGE" /> ترجمه نخواهند شد.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{â€ÙˆÙ‚تی این کنترل روشن باشد Ùˆ وضعیت روی Ùعال تنظیم شده باشد، Chrome تعیین می‌کند Ùعالیت مرور اخیر شما بیشتر شبیه کدام «هم‌گروه» یا گروه بزرگ از اÙراد است. تبلیغ‌کنندگان می‌توانند برای آن گروه٠به‌خصوص Ø¢Ú¯Ù‡ÛŒ انتخاب کنند Ùˆ سابقه مرور شما به‌صورت خصوصی در دستگاهتان Ù†Ú¯Ù‡ داشته می‌شود. گروهتان هر روز به‌روزرسانی می‌شود.}=1{â€ÙˆÙ‚تی این کنترل روشن باشد Ùˆ وضعیت روی Ùعال تنظیم شده باشد، Chrome تعیین می‌کند Ùعالیت مرور اخیر شما بیشتر شبیه کدام «هم‌گروه» یا گروه بزرگ از اÙراد است. تبلیغ‌کنندگان می‌توانند برای آن گروه٠به‌خصوص Ø¢Ú¯Ù‡ÛŒ انتخاب کنند Ùˆ سابقه مرور شما به‌صورت خصوصی در دستگاهتان Ù†Ú¯Ù‡ داشته می‌شود. گروهتان هر روز به‌روزرسانی می‌شود.}one{â€ÙˆÙ‚تی این کنترل روشن باشد Ùˆ وضعیت روی Ùعال تنظیم شده باشد، Chrome تعیین می‌کند Ùعالیت مرور اخیر شما بیشتر شبیه کدام «هم‌گروه» یا گروه بزرگ از اÙراد است. تبلیغ‌کنندگان می‌توانند برای آن گروه٠به‌خصوص Ø¢Ú¯Ù‡ÛŒ انتخاب کنند Ùˆ سابقه مرور شما به‌صورت خصوصی در دستگاهتان Ù†Ú¯Ù‡ داشته می‌شود. گروهتان هر {NUM_DAYS} روز یکبار به‌روزرسانی می‌شود.}other{â€ÙˆÙ‚تی این کنترل روشن باشد Ùˆ وضعیت روی Ùعال تنظیم شده باشد، Chrome تعیین می‌کند Ùعالیت مرور اخیر شما بیشتر شبیه کدام «هم‌گروه» یا گروه بزرگ از اÙراد است. تبلیغ‌کنندگان می‌توانند برای آن گروه٠به‌خصوص Ø¢Ú¯Ù‡ÛŒ انتخاب کنند Ùˆ سابقه مرور شما به‌صورت خصوصی در دستگاهتان Ù†Ú¯Ù‡ داشته می‌شود. گروهتان هر {NUM_DAYS} روز یکبار به‌روزرسانی می‌شود.}}</translation>
<translation id="2053553514270667976">کد پستی</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{۱ پیشنهاد}one{# پیشنهاد}other{# پیشنهاد}}</translation>
<translation id="2071692954027939183">اعلان‌ها به‌طور خودکار مسدود شدند چون شما معمولاً اجازه نمی‌دهید نمایش داده شوند</translation>
<translation id="2079545284768500474">لغو</translation>
<translation id="20817612488360358">تنظیمات پروکسی سیستم تنظیم شده تا مورد استÙاده قرار گیرد، اما یک پیکربندی مشخص برای پروکسی نیز تعیین شده است.</translation>
<translation id="2082238445998314030"><ph name="RESULT_NUMBER" /> نتیجه از <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">ذخیره…</translation>
<translation id="2088086323192747268">â€Ø¯Ú©Ù…Ù‡ مدیریت همگام‌سازی، کلید «ورود» را Ùشار دهید تا اطلاعاتی را Ú©Ù‡ همگام‌سازی می‌کنید در تنظیمات Chrome مدیریت کنید</translation>
<translation id="2091887806945687916">صدا</translation>
<translation id="2094505752054353250">عدم تطابق دامنه</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> به نام کاربری و گذرواژه نیاز دارد.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />، در <ph name="EXPIRATION_DATE_ABBR" /> منقضی می‌شود</translation>
<translation id="2337852623177822836">تنظیم توسط سرپرست کنترل می‌شود</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> می‌خواهد مرتبط شود</translation>
<translation id="2344028582131185878">بارگیری‌های خودکار</translation>
<translation id="2346319942568447007">تصویری که کپی کرده‌اید</translation>
<translation id="2354001756790975382">نشانک‌های دیگر</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">مهاجمین ممکن است بتوانند تصاویری را Ú©Ù‡ در این سایت می‌بینید مشاهده کنند Ùˆ با دست‌کاری آن‌ها شما را Ùریب دهند.</translation>
<translation id="2356070529366658676">سؤال شود</translation>
<translation id="2357481397660644965">دستگاهتان توسط <ph name="DEVICE_MANAGER" />، و حسابتان توسط <ph name="ACCOUNT_MANAGER" /> مدیریت می‌شود.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{کمتر از یک روز}=1{تا یک روز دیگر}one{تا {NUM_DAYS} روز دیگر}other{تا {NUM_DAYS} روز دیگر}}</translation>
<translation id="2359629602545592467">چند ارز</translation>
<translation id="2359808026110333948">ادامه</translation>
+<translation id="2359961752320758691">شماره کارت مجازی اعمال شد.</translation>
<translation id="2367567093518048410">سطح</translation>
<translation id="2372464001869762664">â€Ø¨Ø¹Ø¯Ø§Ø² تأیید کردن، جزئیات کارت از «حساب Google » شما با این سایت هم‌رسانی می‌شود. CVC را در جزئیات حساب Plex پیدا کنید.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">این روش ارسال در دسترس نیست. روش دیگری را امتحان کنید.</translation>
<translation id="2396249848217231973">&amp;واگرد حذÙ</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">قدیمی</translation>
<translation id="2413528052993050574">این سرور نتوانست اثبات کند که این <ph name="DOMAIN" /> است؛ ممکن است گواهی امنیتی آن باطل شده باشد. ممکن است علت این موضوع پیکربندی اشتباه باشد یا مهاجمی اتصال شما را قطع کرده است.</translation>
<translation id="2414886740292270097">تاریک</translation>
<translation id="2438874542388153331">چهار سوراخ در راست</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">منگنه در پایین سمت راست</translation>
<translation id="2523886232349826891">Ùقط در این دستگاه ذخیره شد</translation>
<translation id="2524461107774643265">اÙزودن اطلاعات بیشتر</translation>
-<translation id="2526590354069164005">دسک تاپ</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{و ۱ مورد دیگر}one{و # مورد دیگر}other{و # مورد دیگر}}</translation>
<translation id="2536110899380797252">اÙزودن نشانی</translation>
<translation id="2539524384386349900">تشخیص</translation>
+<translation id="2541219929084442027">صÙحه‌هایی Ú©Ù‡ در «برگه‌های ناشناس» مشاهده می‌کنید، پس‌از بستن همه «برگه‌های ناشناس»، در حاÙظه کوکی، سابقه جستجو، یا سابقه مرورگرتان باقی نمی‌ماند. هر Ùایلی Ú©Ù‡ بارگیری می‌کنید یا نشانکی Ú©Ù‡ ایجاد می‌کنید Ø­Ùظ می‌شود.</translation>
<translation id="2544644783021658368">سند تکی</translation>
<translation id="254947805923345898">مقدار خط‌مشی معتبر نیست.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> پاسخی نامعتبر ارسال کرد.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">â€Ø¨Ø±Ø§ÛŒ بهره‌مندی از بالاترین سطح امنیت در ChromeØŒ <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />«محاÙظت بهبودیاÙته» را روشن کنید<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">â€Ù†Ø´Ø§Ù†ÛŒ IP سرور <ph name="HOST_NAME" /> پیدا نشد.</translation>
<translation id="2639739919103226564">وضعیت:</translation>
+<translation id="264810637653812429">هیچ دستگاه سازگاری پیدا نشد.</translation>
<translation id="2649204054376361687"><ph name="CITY" />، <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861">â€<ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ برای پاک کردن سابقه مرور، کوکی‌ها، حاÙظه پنهان، Ùˆ غیره در تنظیمات ChromeØŒ کلید Tab (جهش) Ùˆ سپس Enter (ورود) را Ùشار دهید</translation>
<translation id="2650446666397867134">دسترسی به Ùایل رد شد</translation>
@@ -463,7 +477,7 @@
<translation id="2677748264148917807">خروج</translation>
<translation id="2684561033061424857">11x12</translation>
<translation id="2687555958734450033">بهترین اندازه</translation>
-<translation id="2688969097326701645">بله، ادامه</translation>
+<translation id="2688969097326701645">بله، ادامه می‌دهم</translation>
<translation id="2691924980723297736">هشدار ایمنی</translation>
<translation id="2699302886720511147">کارت‌های قابل‌‌قبول</translation>
<translation id="2701514975700770343">روبه‌پایین</translation>
@@ -492,6 +506,7 @@
<translation id="2799223571221894425">راه‌اندازی مجدد</translation>
<translation id="2803306138276472711">â€Google Safe Browsing به تازگی در <ph name="SITE" />ØŒ â€<ph name="BEGIN_LINK" />بداÙزار شناسایی کرده است<ph name="END_LINK" />. گاهی اوقات وب‌سایت‌هایی Ú©Ù‡ معمولاً ایمن هستند با بداÙزار آلوده می‌شوند.</translation>
<translation id="2807052079800581569">â€Ù…وقعیت Y تصویر</translation>
+<translation id="2820957248982571256">درحال اسکن کردن…</translation>
<translation id="2824775600643448204">نوار جستجو و آدرس</translation>
<translation id="2826760142808435982">اتصال با استÙاده از <ph name="CIPHER" /> رمزگذاری Ùˆ راستی‌آزمایی شده است Ùˆ از <ph name="KX" /> به عنوان مکانیسم تبادل کلید استÙاده می‌کند.</translation>
<translation id="2835170189407361413">پاک کردن Ùرم</translation>
@@ -499,6 +514,8 @@
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">این سایتْ آگهی‌های مزاحم یا گمراه‌کننده نشان می‌دهد.</translation>
+<translation id="287596039013813457">دوستانه</translation>
+<translation id="2876489322757410363">برای پرداخت ازطریق یک برنامه خارجی، از «حالت ناشناس» خارج می‌شوید. ادامه می‌دهید؟</translation>
<translation id="2878197950673342043">تاخوردگی پوسترمانند</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">جای‌گذاری پنجره</translation>
@@ -548,7 +565,6 @@
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256">â€<ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ برای راندن «بررسی ایمنی» در تنظیمات ChromeØŒ کلید «جهش» Ùˆ سپس «ورود» را Ùشار دهید.</translation>
<translation id="3061707000357573562">سرویس وصله</translation>
-<translation id="3064966200440839136">درحال خروج از حالت ناشناس، برای پرداخت ازطریق یک برنامه خارجی. ادامه می‌دهید؟</translation>
<translation id="306573536155379004">بازی شروع شد.</translation>
<translation id="3080254622891793721">ترسیمی</translation>
<translation id="3086579638707268289">Ùعالیتتان در وب تحت‌نظارت است</translation>
@@ -571,7 +587,6 @@
<translation id="315504272643575312">حساب شما توسط <ph name="MANAGER" /> مدیریت می‌شود.</translation>
<translation id="3157931365184549694">بازیابی</translation>
<translation id="3162559335345991374">â€Ø´Ø¨Ú©Ù‡ Wi-Fi مورد استÙاده‌تان احتمالاً نیاز دارد Ú©Ù‡ به یک صÙحه ورود به سیستم بروید.</translation>
-<translation id="3167968892399408617">صÙحه‌هایی Ú©Ù‡ در برگه‌های حالت ناشناس مرور می‌کنید، بعد از بستن همه برگه‌های حالت ناشناس در سابقه مرورگر، Ùضای ذخیره Ú©ÙˆÚ©ÛŒ یا سابقه جستجو باقی نمی‌مانند. Ùایل‌هایی Ú©Ù‡ بارگیری می‌کنید یا نشانک‌هایی Ú©Ù‡ ایجاد می‌کنید Ø­Ùظ می‌شود.</translation>
<translation id="3169472444629675720">کش٠کردن</translation>
<translation id="3174168572213147020">ایسلند</translation>
<translation id="3176929007561373547">تنظیمات پروکسی‌ را بررسی کنید یا با سرپرست شبکه‌‌تان تماس بگیرید تا
@@ -597,10 +612,12 @@
<translation id="3229041911291329567">اطلاعات مربوط به نسخه دستگاه و مرورگر</translation>
<translation id="323107829343500871">â€CVC کارت <ph name="CREDIT_CARD" /> را وارد کنید</translation>
<translation id="3234666976984236645">همیشه محتوای مهم در این سایت شناسایی شود</translation>
+<translation id="3249845759089040423">شیک</translation>
<translation id="3252266817569339921">Ùرانسوی</translation>
<translation id="3266793032086590337">مقدار (مغایر)</translation>
<translation id="3268451620468152448">برگه‌های باز</translation>
<translation id="3270847123878663523">&amp;واگرد ترتیب‌بندی مجدد</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> می‌خواهد مرتبط شود</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">سازمان شما، <ph name="ENROLLMENT_DOMAIN" />، اطلاعاتی (مثل تنظیمات یا خط‌مشی‌ها) را به وب‌سایت‌های زیر ارسال کرده است.</translation>
<translation id="3282497668470633863">اÙزودن نام روی کارت</translation>
@@ -653,6 +670,7 @@
<translation id="3428151540071562330">â€ÛŒÚ© یا چند سرور نشانی وب الگوی سرور DnsOverHttpsTemplates نامعتبر است Ùˆ استÙاده نخواهد شد.</translation>
<translation id="3431636764301398940">این کارت را در این دستگاه ذخیره کنید</translation>
<translation id="3432601291244612633">بستن صÙحه</translation>
+<translation id="3435738964857648380">امنیت</translation>
<translation id="3435896845095436175">Ùعال کردن</translation>
<translation id="3438829137925142401">â€Ø§Ø³ØªÙاده از گذرواژه‌های ذخیره‌شده در «حساب Google»</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -695,7 +713,10 @@
<translation id="3584299510153766161">دو سوراخ پایین</translation>
<translation id="3586931643579894722">عدم نمایش جزئیات</translation>
<translation id="3587738293690942763">وسط</translation>
+<translation id="3590643883886679995">پس‌از خروج از «حالت ناشناس»، داده‌های ورود به سیستم در این دستگاه ذخیره خواهد شد.</translation>
+<translation id="359126217934908072">ماه/سال:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{هرزمان خواستید می‌توانید گروه را بازنشانی کنید. پیوستن به گروه جدید حدود یک روز طول می‌کشد.}=1{هرزمان خواستید می‌توانید گروه را بازنشانی کنید. پیوستن به گروه جدید حدود یک روز طول می‌کشد.}one{هرزمان خواستید می‌توانید گروه را بازنشانی کنید. پیوستن به گروه جدید {NUM_DAYS} روز طول می‌کشد.}other{هرزمان خواستید می‌توانید گروه را بازنشانی کنید. پیوستن به گروه جدید {NUM_DAYS} روز طول می‌کشد.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />، <ph name="DOMAIN" />، <ph name="TIME" /></translation>
<translation id="3603507503523709">سرپرست برنامه را مسدود کرده است</translation>
<translation id="3608932978122581043">جهت تغذیه کاغذ</translation>
@@ -704,13 +725,13 @@
<translation id="3615877443314183785">تاریخ انقضای معتبری وارد کنید</translation>
<translation id="36224234498066874">پاک کردن داده‌های محصول مرور…</translation>
<translation id="362276910939193118">نمایش کل سابقه</translation>
-<translation id="3625635938337243871">پس‌از خروج از «حالت ناشناس»، داده‌های ورود به سیستم در این دستگاه ذخیره خواهد شد.</translation>
<translation id="3630155396527302611">اگر درحال حاضر به‌عنوان برنامه‌ای برای دسترسی به شبکه در Ùهرست قرار دارد،
سعی کنید آن را از Ùهرست حذ٠کرده Ùˆ دوباره به Ùهرست اضاÙÙ‡ کنید.</translation>
<translation id="3630699740441428070">سرپرستان این دستگاه اتصال شبکه شما را پیکربندی کرده‌اند Ú©Ù‡ می‌تواند به آن‌ها اجازه دهد تراÙیک شبکه شما را (ازجمله وب‌سایت‌هایی Ú©Ù‡ بازدید می‌کنید) ببینند.</translation>
<translation id="3631244953324577188">زیست‌سنجشی</translation>
<translation id="3633738897356909127">â€Ø¯Ú©Ù…Ù‡ «به‌روزرسانی Chrome»، برای به‌روزرسانی Chrome ازطریق تنظیمات ChromeØŒ کلید Enter (ورود) را Ùشار دهید</translation>
<translation id="3634530185120165534">سینی ۵</translation>
+<translation id="3637662659967048211">â€Ø°Ø®ÛŒØ±Ù‡ در «حساب Google»</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">برنامه:</translation>
<translation id="3650584904733503804">ارزیابی موÙÙ‚ بود</translation>
@@ -751,6 +772,7 @@
<translation id="3781428340399460090">صورتی پررنگ</translation>
<translation id="3783418713923659662">مسترکارت</translation>
<translation id="3784372983762739446">دستگاه‌های بلوتوث</translation>
+<translation id="3787675388804467730">شماره کارت مجازی</translation>
<translation id="3787705759683870569">تاریخ انقضا <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">اندازه ۱۶</translation>
<translation id="3789841737615482174">نصب</translation>
@@ -770,6 +792,7 @@
<translation id="3841184659773414994">کنترل‌کننده Ùایل</translation>
<translation id="385051799172605136">بازگشت</translation>
<translation id="3858027520442213535">به‌روزرسانی تاریخ و زمان</translation>
+<translation id="3881478300875776315">نمایش خطوط کمتر</translation>
<translation id="3884278016824448484">شناسه دستگاه یکسان نیست</translation>
<translation id="3885155851504623709">استان</translation>
<translation id="388632593194507180">نظارت تشخیص داده شد</translation>
@@ -795,6 +818,7 @@
<translation id="397105322502079400">در حال محاسبه…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> مسدود شده است</translation>
<translation id="3973357910713125165">â€Ø¯Ú©Ù…Ù‡ «راندن بررسی ایمنی در Chrome»، کلید «ورود» را Ùشار دهید تا «بررسی ایمنی» در تنظیمات Chrome اجرا شود</translation>
+<translation id="3986705137476756801">«زیرنویس ناشنوایان زنده» Ùعلاً خاموش شود</translation>
<translation id="3987405730340719549">â€Chrome تشخیص داده است Ú©Ù‡ این سایت ممکن است جعلی یا کلاهبردارانه باشد.
اگر Ùکر می‌کنید این مورد به‌اشتباه نشان داده شده است، لطÙاً از https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals دیدن کنید.</translation>
@@ -891,13 +915,14 @@
<translation id="4275830172053184480">راه‌اندازی دستگاه خود</translation>
<translation id="4277028893293644418">بازنشانی گذرواژه</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{â€Ø§ÛŒÙ† کارت در حساب Google ذخیره شده است}one{â€Ø§ÛŒÙ† کارت‌ها در حساب Google ذخیره شده‌اند}other{â€Ø§ÛŒÙ† کارت‌ها در حساب Google ذخیره شده‌اند}}</translation>
+<translation id="4287885627794386150">برای دوره آزمایشی واجدشرایط هستید، اما Ùعال نیست</translation>
<translation id="4297502707443874121">تصویر Ú©ÙˆÚ†Ú© صÙحه <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">بزرگ کردن</translation>
<translation id="4300675098767811073">چند سوراخ در راست</translation>
<translation id="4302514097724775343">برای بازی کردن، روی دایناسور ضربه بزنید</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">دسترسی به Ùایل شما ممکن نبود</translation>
-<translation id="4305817255990598646">جابه‌جایی</translation>
+<translation id="4306529830550717874">نشانی ذخیره شود؟</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">مسدود کردن (پیش‌Ùرض)</translation>
<translation id="4314815835985389558">مدیریت همگام‌سازی</translation>
@@ -924,6 +949,7 @@
<translation id="4377125064752653719">شما سعی در دسترسی به <ph name="DOMAIN" /> را داشتید، اما صادر کننده، گواهی ارائه شده از سوی سرور را باطل کرده است. یعنی اصلاً نباید به اطلاعات کاربری که این سرور ارائه می‌کند اطمینان کرد. ممکن است شما با مهاجمی در ارتباط باشید.</translation>
<translation id="4378154925671717803">تلÙÙ†</translation>
<translation id="4390472908992056574">لبه</translation>
+<translation id="4406883609789734330">زیرنویس زنده</translation>
<translation id="4406896451731180161">نتایج جستجو</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> کوکی</translation>
<translation id="4414290883293381923">â€Ø§Ø®ÛŒØ±Ø§Ù‹ گذرواژه‌تان را در سایتی Ùریب‌کار وارد کرده‌اید. Chrome توصیه می‌کند همین حالا به <ph name="WEBSITE_1" />ØŒ <ph name="WEBSITE_2" />ØŒ <ph name="WEBSITE_3" />ØŒ Ùˆ سایت‌های دیگری Ú©Ù‡ در آن‌ها از این گذرواژه استÙاده می‌کنید بروید Ùˆ گذرواژه را تغییر دهید.</translation>
@@ -936,7 +962,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">استÙاده از پروکسی غیرÙعال است اما یک پیکربندی خاص برای پروکسی تعیین شده است.</translation>
<translation id="4464826014807964867">وب‌سایت‌های حاوی اطلاعات سازمان شما</translation>
-<translation id="4466881336512663640">تغییرات Ùرم از بین می‌رود. مطمئن هستید می‌خواهید ادامه دهید؟</translation>
<translation id="4476953670630786061">این Ùرم ایمن نیست. تکمیل خودکار خاموش شده است.</translation>
<translation id="4477350412780666475">آهنگ بعدی</translation>
<translation id="4482953324121162758">این سایت ترجمه نخواهد شد.</translation>
@@ -970,6 +995,7 @@
<translation id="4594403342090139922">&amp;واگرد حذÙ</translation>
<translation id="4597348597567598915">اندازه ۸</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">تأثیرگذار</translation>
<translation id="4628948037717959914">عکس</translation>
<translation id="4631649115723685955">بازگشت نقدی پیوند داده شده است</translation>
<translation id="4636930964841734540">اطلاعات</translation>
@@ -989,6 +1015,7 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">رو</translation>
+<translation id="4702656508969495934">«زیرنویس ناشنوایان زنده» نمایان است، برای کانونی کردن آن از تعویض‌کننده پنجره استÙاده کنید</translation>
<translation id="4708268264240856090">اتصال شما قطع شد</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131">â€<ph name="BEGIN_LINK" />اجرای Windows Network Diagnostics<ph name="END_LINK" /></translation>
@@ -1002,6 +1029,7 @@
<translation id="4738601419177586157">پیشنهاد جستجوی <ph name="TEXT" /></translation>
<translation id="4742407542027196863">مدیریت گذرواژه‌ها…</translation>
<translation id="4744603770635761495">مسیر قابل اجرا</translation>
+<translation id="4749011317274908093">به «حالت ناشناس» رÙته‌اید</translation>
<translation id="4750917950439032686">اطلاعات شما (به‌عنوان مثال، گذرواژه‌ها یا شماره‌ کارت‌های اعتباری) وقتی به این سایت ارسال می‌شوند، خصوصی هستند.</translation>
<translation id="4756388243121344051">&amp;سابقه</translation>
<translation id="4758311279753947758">اÙزودن اطلاعات تماس</translation>
@@ -1031,6 +1059,8 @@
<translation id="4813512666221746211">خطای شبکه</translation>
<translation id="4816492930507672669">متناسب با صÙحه</translation>
<translation id="4819347708020428563">یادداشت‌ها در نمای پیش‌Ùرض ویرایش شوند؟</translation>
+<translation id="4825507807291741242">نیرومند</translation>
+<translation id="4838327282952368871">رؤیایی</translation>
<translation id="484462545196658690">خودکار</translation>
<translation id="4850886885716139402">نما</translation>
<translation id="485316830061041779">آلمانی</translation>
@@ -1167,6 +1197,7 @@
<translation id="5314967030527622926">دÙترچه‌ساز</translation>
<translation id="5316812925700871227">چرخش خلا٠جهت عقربه‌های ساعت</translation>
<translation id="5317780077021120954">ذخیره</translation>
+<translation id="5321288445143113935">بزرگ‌ترین اندازه</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> از <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">انتخاب اطلاعات تماس</translation>
<translation id="5327248766486351172">نام</translation>
@@ -1174,11 +1205,13 @@
<translation id="5332219387342487447">روش ارسال کالا</translation>
<translation id="5333022057423422993">â€Chrome گذرواژه‌ای را Ú©Ù‡ اکنون استÙاده کردید در سرقت اطلاعات شبکه پیدا کرده است. برای ایمن کردن حساب‌هایتان، توصیه می‌کنیم گذرواژه‌های ذخیره‌شده‌تان را بررسی کنید.</translation>
<translation id="5334013548165032829">گزارش دقیق سیستم</translation>
+<translation id="5334145288572353250">نشانی ذخیره شود؟</translation>
<translation id="5340250774223869109">برنامه مسدود شده است</translation>
<translation id="534295439873310000">â€Ø¯Ø³ØªÚ¯Ø§Ù‡â€ŒÙ‡Ø§ÛŒ NFC</translation>
<translation id="5344579389779391559">این صÙحه ممکن است تلاش کند از شما پول دریاÙت کند</translation>
<translation id="5355557959165512791">درحال‌حاضر نمی‌توانید از <ph name="SITE" /> دیدن کنید، زیرا گواهینامه آن لغو شده است. معمولاً خطاهای شبکه Ùˆ حمله‌ها موقتی هستند، بنابراین احتمالاً این صÙحه بعداً کار خواهد کرد.</translation>
<translation id="536296301121032821">تنظیمات خط‌‌مشی ذخیره نشد</translation>
+<translation id="5363309033720083897">سرپرستتان درگاه سریالی را مجاز کرده است</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="5386426401304769735">â€Ø²Ù†Ø¬ÛŒØ±Ù‡ گواهی این سایت حاوی یک گواهی با امضای SHA-1 است.</translation>
@@ -1187,6 +1220,7 @@
<translation id="5398772614898833570">آگهی‌ها مسدود شدند</translation>
<translation id="5400836586163650660">خاکستری</translation>
<translation id="540969355065856584">این سرور نتوانست ثابت کند که <ph name="DOMAIN" /> است؛ در حال حاضر، گواهی امنیتی آن معتبر نیست. ممکن است این مشکل به دلیل پیکربندی نادرست یا قطع اتصال شما توسط حمله‌کننده ایجاد شده باشد.</translation>
+<translation id="541143247543991491">ابر (سراسر سیستم)</translation>
<translation id="541416427766103491">پشته‌ساز ۴</translation>
<translation id="5421136146218899937">پاک کردن داده‌های مرور...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> می‌خواهد برایتان اعلان ارسال کند</translation>
@@ -1200,6 +1234,7 @@
<translation id="5455374756549232013">مهر زمان خط‌مشی نادرست است</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" /> مخاطب دیگر}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="5463625433003343978">درحال پیدا کردن دستگاه‌ها…</translation>
<translation id="5469868506864199649">ایتالیایی</translation>
<translation id="5470861586879999274">&amp;انجام مجدد ویرایش</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1249,7 +1284,6 @@
<translation id="5624120631404540903">مدیریت گذرواژه‌ها</translation>
<translation id="5629630648637658800">تنظیمات خط‌مشی بارگیری نشد</translation>
<translation id="5631439013527180824">نشانه مدیریت دستگاه نامعتبر است</translation>
-<translation id="5632627355679805402">â€Ø¯Ø§Ø¯Ù‡â€ŒÙ‡Ø§ با <ph name="BEGIN_LINK" />گذرواژه Google<ph name="END_LINK" /> شما از <ph name="TIME" /> رمز می‌شود. برای شروع همگام‌سازی، آن را وارد کنید.</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="5644090287519800334">â€Ø±ÙˆÛŒ ۱، تغییر جهت تصویر حول محور X</translation>
@@ -1288,12 +1322,12 @@
<translation id="5785756445106461925">علاوه بر این، این صÙحه دارای منابع دیگری است Ú©Ù‡ امن نیستند. دیگران می‌توانند در حین انتقال، این منابع را ببینند Ùˆ این منابع می‌توانند برای تغییر Ù‚ÙÙ„ صÙحه، توسط یک مهاجم تغییر داده شوند.</translation>
<translation id="5786044859038896871">می‌خواهید اطلاعات کارتتان را وارد کنید؟</translation>
<translation id="578633867165174378">â€Chrome گذرواژه‌ای را Ú©Ù‡ اکنون استÙاده کردید در سرقت اطلاعات شبکه پیدا کرده است. توصیه می‌کنیم این گذرواژه را همین حالا تغییر دهید.</translation>
-<translation id="5798290721819630480">از تغییرات صرÙ‌‌نظر می‌کنید؟</translation>
<translation id="5803412860119678065">می‌خواهید <ph name="CARD_DETAIL" /> خود را وارد کنید؟</translation>
<translation id="5804241973901381774">مجوزها</translation>
<translation id="5804427196348435412">â€Ø§Ø³ØªÙاده از دستگاه‌های مجهز به NFC</translation>
<translation id="5810442152076338065">اتصال شما به <ph name="DOMAIN" /> با استÙاده از یک مجموعه رمز منسوخ، رمزگذاری شده است.</translation>
<translation id="5813119285467412249">&amp;انجام مجدد اÙزودن</translation>
+<translation id="5817918615728894473">مرتبط‌سازی</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{â€Ù‡Ù†Ú¯Ø§Ù… پرداخت کردن، هزینه از این کارت کسر خواهد شد، اما شماره واقعی آن در اختیار این سایت قرار نخواهد گرÙت. برای امنیت بیشتر، یک CVC موقت ایجاد خواهد شد.}one{â€Ù‡Ù†Ú¯Ø§Ù… پرداخت کردن، هزینه از کارتی Ú©Ù‡ انتخاب می‌کنید کسر خواهد شد، اما شماره واقعی آن در اختیار این سایت قرار نخواهد گرÙت. برای امنیت بیشتر، یک CVC موقت ایجاد خواهد شد.}other{â€Ù‡Ù†Ú¯Ø§Ù… پرداخت کردن، هزینه از کارتی Ú©Ù‡ انتخاب می‌کنید کسر خواهد شد، اما شماره واقعی آن در اختیار این سایت قرار نخواهد گرÙت. برای امنیت بیشتر، یک CVC موقت ایجاد خواهد شد.}}</translation>
<translation id="5826507051599432481">â€Ù†Ø§Ù… مشترک (CN)</translation>
<translation id="5838278095973806738">نباید هیچ اطلاعات حساسی (مثل گذرواژه یا کارت اعتباری) را در این سایت وارد کنید، زیرا ممکن است مهاجمین آن‌ها را سرقت کنند.</translation>
@@ -1301,6 +1335,7 @@
<translation id="5855253129151731373">â€Ù†Ø§Ù… میزبان این سایت شبیه به نام <ph name="LOOKALIKE_DOMAIN" /> است. گاهی‌اوقات مهاجمان با ایجاد تغییراتی Ú©ÙˆÚ†Ú© در نام دامنه Ú©Ù‡ به‌آسانی قابل‌دیدن نیست، سایت‌ها را جعل می‌کنند.
اگر Ùکر می‌کنید این مورد به‌اشتباه نشان داده شده است، لطÙاً از https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals دیدن کنید.</translation>
+<translation id="5860033963881614850">خاموش</translation>
<translation id="5862579898803147654">پشته‌ساز ۸</translation>
<translation id="5863847714970149516">صÙحه پیش‌رو ممکن است تلاش کند از شما پول دریاÙت کند</translation>
<translation id="5866257070973731571">اÙزودن شماره تلÙÙ†</translation>
@@ -1317,6 +1352,7 @@
<translation id="5913377024445952699">ضبط صÙحه‌نمایش متوق٠شد</translation>
<translation id="59174027418879706">Ùعال شد</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{Û± Ú©ÙˆÚ©ÛŒ درحال استÙاده}one{# Ú©ÙˆÚ©ÛŒ درحال استÙاده}other{# Ú©ÙˆÚ©ÛŒ درحال استÙاده}}</translation>
<translation id="5921185718311485855">روشن</translation>
<translation id="5921639886840618607">â€Ú©Ø§Ø±Øª در حساب Google ذخیره شود؟</translation>
<translation id="5922853866070715753">تقريباً تمام است</translation>
@@ -1336,6 +1372,7 @@
<translation id="5989320800837274978">â€Ø³Ø±ÙˆØ± پروکسی ثابت Ùˆ URL اسکریپت pac. تعیین نشده‌اند.</translation>
<translation id="5992691462791905444">â€ØªØ§Ø®ÙˆØ±Ø¯Ú¯ÛŒ Z Ø´Ú©Ù„ مهندسی</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> نتیجه برای «<ph name="SEARCH_TEXT" />»</translation>
+<translation id="6006484371116297560">کلاسيک</translation>
<translation id="6008122969617370890">â€ØªØ±ØªÛŒØ¨ N تا Û±</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">بررسی گذرواژه</translation>
@@ -1357,6 +1394,7 @@
<translation id="6045164183059402045">الگوی چاپ مضاعÙ</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="6049004884579590341">برای خروج از حالت تمام صÙحه، |<ph name="ACCELERATOR" />| را Ùشار دهید Ùˆ نگه‌دارید</translation>
<translation id="6049488691372270142">ارائه صÙحه</translation>
<translation id="6051221802930200923">درحال‌حاضر نمی‌توانید از <ph name="SITE" /> دیدن کنید، زیرا وب‌سایت از سنجاق کردن گواهینامه استÙاده می‌کند. خطاهای شبکه Ùˆ حمله‌ها موقتی هستند، بنابراین احتمالاً این صÙحه بعداً کار خواهد کرد.</translation>
<translation id="6051898664905071243">تعداد صÙحه:</translation>
@@ -1373,6 +1411,7 @@
<translation id="610911394827799129">â€Ù…Ù…Ú©Ù† است حساب Google شما اشکال دیگری از سابقه مرور در <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> داشته باشد</translation>
<translation id="6116338172782435947">به نوشتار و تصاویر کپی‌شده در بریده‌دان دسترسی پیدا کند</translation>
<translation id="6120179357481664955">â€Ø´Ù†Ø§Ø³Ù‡ «رابط پرداخت‌های یکپارچه» (UPI) شما به‌خاطر سپرده شود؟</translation>
+<translation id="6123290840358279103">مشاهده کارت مجازی</translation>
<translation id="6124432979022149706">â€Ø±Ø§Ø¨Ø·â€ŒÙ‡Ø§ÛŒ Chrome Enterprise</translation>
<translation id="6146055958333702838">همه کابل‌ها را بررسی کنید و همه ره‌یاب‌ها، مودم‌ها، یا دیگر دستگاه‌های
 شبکه‌ای را Ú©Ù‡ ممکن است درحال استÙاده از آن‌ها باشید مجدداً راه‌اندازی کنید.</translation>
@@ -1409,6 +1448,7 @@
<translation id="6289939620939689042">رنگ صÙحه</translation>
<translation id="6290238015253830360">مقاله‌های پیشنهادی شما در اینجا نشان داده می‌شوند</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">â€ØªÙˆÙ‚٠«دستیار Google» در Chrome</translation>
<translation id="6305205051461490394">دسترسی به <ph name="URL" /> امکان‌پذیر نیست.</translation>
<translation id="6312113039770857350">صÙحه وب در دسترس نیست</translation>
@@ -1434,6 +1474,7 @@
<translation id="6390200185239044127">â€ØªØ§Ø®ÙˆØ±Ø¯Ú¯ÛŒ Z Ø´Ú©Ù„ از وسط</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">براساس خط‌مشی سرپرست، جای‌گذاری از <ph name="ORIGIN_NAME" /> در این ناحیه مسدود شده است</translation>
+<translation id="6398765197997659313">خروج از حالت تمام صÙحه</translation>
<translation id="6401136357288658127">این خط‌مشی منسوخ شده است. درعوض، باید از خط‌مشی <ph name="NEW_POLICY" /> استÙاده کنید.</translation>
<translation id="6404511346730675251">ویرایش نشانک</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1446,7 +1487,6 @@
<translation id="6428450836711225518">به‌تأیید رساندن شماره تلÙÙ†</translation>
<translation id="6433490469411711332">ویرایش اطلاعات تماس</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> از اتصال خودداری کرد.</translation>
-<translation id="6434309073475700221">صرÙ‌نظرکردن</translation>
<translation id="6440503408713884761">نادیده گرÙته شد</translation>
<translation id="6443406338865242315">اÙزونه‌ها Ùˆ اÙزایه‌هایی Ú©Ù‡ نصب کرده‌اید</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1489,6 +1529,7 @@
<translation id="6624427990725312378">اطلاعات تماس</translation>
<translation id="6626291197371920147">اÙزودن شماره کارت معتبر</translation>
<translation id="6628463337424475685">جستجوی <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">â€Ø¯Ø±Ø­Ø§Ù„ پیدا کردن دستگاه‌های USB…</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">پاک کردن</translation>
@@ -1504,6 +1545,7 @@
<translation id="6671697161687535275">â€Ù¾ÛŒØ´Ù†Ù‡Ø§Ø¯ Ùرم از Chromium پاک شود؟</translation>
<translation id="6685834062052613830">خروج از سیستم و تکمیل راه‌اندازی</translation>
<translation id="6687335167692595844">اندازه قلم درخواست شد</translation>
+<translation id="6688743156324860098">به‌روزرسانی…</translation>
<translation id="6689249931105087298">نسبی با Ùشرده‌سازی نقطه سیاه</translation>
<translation id="6689271823431384964">â€Ú†ÙˆÙ† به سیستم وارد شده‌اید، Chrome پیشنهاد می‌کند کارت‌ها را در حساب Google ذخیره کنید. در تنظیمات می‌توانید این رÙتار را تغییر دهید. نام دارنده کارت از حساب شما گرÙته شده است.</translation>
<translation id="6698381487523150993">ایجاد شده:</translation>
@@ -1519,6 +1561,7 @@
<translation id="6744009308914054259">وقتی درانتظار اتصال هستید، می‌توانید برای خواندن مقاله‌های Ø¢Ùلاین، «بارگیری‌ها» را مشاهده کنید.</translation>
<translation id="6753269504797312559">مقدار خط‌‌مشی</translation>
<translation id="6757797048963528358">دستگاهتان به خواب رÙته است.</translation>
+<translation id="6767985426384634228">نشانی به‌روزرسانی شود؟</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">بنÙØ´</translation>
@@ -1541,6 +1584,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">â€Chrome این صÙحه را ساده کرده است تا خواندن آن آسان‌تر باشد Chrome صÙحه اصلی را ازطریق اتصالی غیرایمن بازیابی کرد.</translation>
<translation id="6891596781022320156">سطح خط‌مشی پشتیبانی نمی‌شود.</translation>
+<translation id="6895143722905299846">شماره مجازی:</translation>
<translation id="6895330447102777224">کارتتان تأیید شد</translation>
<translation id="6897140037006041989">نماینده کاربر</translation>
<translation id="6898699227549475383">â€Ø³Ø§Ø²Ù…ان (O)</translation>
@@ -1576,10 +1620,10 @@
<translation id="7004583254764674281">â€Ø¨Ø±Ø§ÛŒ به‌تأیید رساندن سریع‌تر کارت‌ها، از Windows Hello استÙاده شود</translation>
<translation id="7006930604109697472">در هر حال Ùرستاده شود</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">تنظیمات تغییر اندازه</translation>
<translation id="7014741021609395734">میزان بزرگ‌نمایی</translation>
<translation id="7016992613359344582">ممکن است این هزینه‌ها یک‌باره یا تکرارشونده باشند و واضح نباشند.</translation>
<translation id="7029809446516969842">گذرواژه‌ها</translation>
+<translation id="7030436163253143341">گواهی معتبر نیست</translation>
<translation id="7031646650991750659">â€Ø¨Ø±Ù†Ø§Ù…ه‌های Google Play Ú©Ù‡ نصب کرده‌اید</translation>
<translation id="7050187094878475250">تلاش کردید به دامنه <ph name="DOMAIN" /> بروید اما گواهینامه‌ای که سرور ارائه کرد، دارای یک تاریخ اعتبار بسیار طولانی است و مورداعتماد نیست.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{درحال‌حاضر این کارت ذخیره نمی‌شود}one{درحال‌حاضر این کارت‌ها ذخیره نمی‌شوند}other{درحال‌حاضر این کارت‌ها ذخیره نمی‌شوند}}</translation>
@@ -1649,12 +1693,14 @@
<translation id="7300012071106347854">آبی پررنگ</translation>
<translation id="7302712225291570345">«<ph name="TEXT" />»</translation>
<translation id="7304030187361489308">بالا</translation>
+<translation id="7305756307268530424">شروع آهسته‌تر</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">راهنمای اتصال</translation>
<translation id="7323804146520582233">پنهان کردن بخش «<ph name="SECTION" />»</translation>
<translation id="733354035281974745">لغو حساب محلی دستگاه</translation>
<translation id="7333654844024768166">â€Ø§Ø®ÛŒØ±Ø§Ù‹ گذرواژه‌تان را در سایتی Ùریب‌کار وارد کرده‌اید. Chromium توصیه می‌کند همین حالا به <ph name="WEBSITE_1" />،†<ph name="WEBSITE_2" />ØŒ <ph name="WEBSITE_3" />ØŒ Ùˆ سایت‌های دیگری Ú©Ù‡ در آن‌ها از این گذرواژه استÙاده می‌کنید بروید Ùˆ گذرواژه را تغییر دهید.</translation>
<translation id="7334320624316649418">&amp;انجام مجدد ترتیب‌بندی مجدد</translation>
+<translation id="7337248890521463931">نمایش خطوط بیشتر</translation>
<translation id="7337706099755338005">در پلتÙورم شما دردسترس نیست.</translation>
<translation id="733923710415886693">گواهی سرور از طریق Ø´ÙاÙیت گواهینامه نشان داده نشده بود.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1662,6 +1708,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">خط Ùرمان</translation>
<translation id="7359588939039777303">آگهی‌ها مسدود شدند.</translation>
+<translation id="7363096869660964304">اما، شما نامرئی نمی‌شوید. با استÙاده از «حالت ناشناس»، مرورتان از چشمان کارÙرمای شما، رساننده خدمات اینترنتی یا وب‌سایت‌هایی Ú©Ù‡ بازدید می‌کنید پنهان نمی‌ماند.</translation>
<translation id="7365596969960773405">â€<ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ کلید «جهش» Ùˆ سپس «ورود» را Ùشار دهید Ùˆ نشانی‌ها را در تنظیمات Chrome اضاÙÙ‡ Ùˆ مدیریت کنید</translation>
<translation id="7365849542400970216">می‌توانیم موارد استÙاده از دستگاهتان را بدانیم؟</translation>
<translation id="7372973238305370288">نتیجه جستجو</translation>
@@ -1672,7 +1719,9 @@
<translation id="7378594059915113390">کنترل‌های رسانه</translation>
<translation id="7378627244592794276">نه</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">نامربوط</translation>
<translation id="7390545607259442187">تأیید کارت</translation>
+<translation id="7392089738299859607">به‌روزرسانی نشانی</translation>
<translation id="7399802613464275309">بررسی ایمنی</translation>
<translation id="7400418766976504921">نشانی وب</translation>
<translation id="7403591733719184120">دستگاه <ph name="DEVICE_NAME" /> تحت مدیریت است</translation>
@@ -1687,6 +1736,7 @@
&lt;li&gt;برای آشنایی با نحوه برداشتن دائم نرم‌اÙزار از رایانه، از &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;مرکز راهنمای â€Chromeâ€&lt;/a&gt; بازدید کنید
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">دوست‌داشتنی</translation>
<translation id="7416351320495623771">مدیریت گذرواژه‌ها…</translation>
<translation id="7419106976560586862">مسیر نمایه</translation>
<translation id="7437289804838430631">اÙرودن اطلاعات تماس</translation>
@@ -1702,7 +1752,7 @@
<translation id="7481312909269577407">ارسال کردن</translation>
<translation id="7485870689360869515">هیچ داده‌ای یاÙت نشد.</translation>
<translation id="7495528107193238112">این محتوا مسدود شده است. برای برطر٠کردن مشکل با مالک سایت تماس بگیرید.</translation>
-<translation id="7498234416455752244">ادامه ویرایش</translation>
+<translation id="7498193950643227031">اگر اندازه آن تغییر کند ممکن است به‌طور غیرمنتظره‌ای رÙتار کند. اکنون می‌توانید قابلیت تغییر اندازه برنامه‌ها را در <ph name="SETTINGS" /> محدود کنید.</translation>
<translation id="7503664977220660814">â€Ø§Ø®ÛŒØ±Ø§Ù‹ گذرواژه‌تان را در سایتی Ùریب‌کار وارد کرده‌اید. Chromium توصیه می‌کند همین حالا گذرواژه‌های ذخیره‌شده برای <ph name="WEBSITE_1" />ØŒ <ph name="WEBSITE_2" />ØŒ Ùˆ سایت‌های دیگری را Ú©Ù‡ در آن‌ها از این گذرواژه استÙاده می‌کنید بررسی کنید.</translation>
<translation id="7508255263130623398">شناسه دستگاه خط‌مشی برگردانده‌شده خالی است یا با شناسه کنونی دستگاه مطابقت ندارد</translation>
<translation id="7508870219247277067">سبز مایل به زرد</translation>
@@ -1722,6 +1772,7 @@
<translation id="7548892272833184391">رÙع خطاهای اتصال</translation>
<translation id="7549584377607005141">این صÙحه وب برای نمایش صحیح به داده‌هایی نیاز دارد Ú©Ù‡ قبلاً وارد کرده‌اید. می‌توانید این داده‌ها را دوباره ارسال کنید، اما با انجام این کار، هر اقدامی Ú©Ù‡ این صÙحه قبلاً انجام داده است تکرار می‌شود.</translation>
<translation id="7550637293666041147">â€Ù†Ø§Ù… کاربری شما در دستگاه Ùˆ Chrome</translation>
+<translation id="755279583747225797">دوره آزمایش Ùعال است</translation>
<translation id="7552846755917812628">نکته‌های زیر را امتحان کنید:</translation>
<translation id="7554475479213504905">تازه‌سازی و نمایش درهرصورت</translation>
<translation id="7554791636758816595">برگهٔ جدید</translation>
@@ -1740,7 +1791,6 @@
<translation id="7610193165460212391">مقدار خارج از محدوده <ph name="VALUE" /> است.</translation>
<translation id="7613889955535752492">انقضا: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628">â€<ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ برای مشاهده Ùˆ مدیریت کردن گذرواژه‌ها در تنظیمات ChromeØŒ کلید Tab (جهش) Ùˆ سپس Enter (ورود) را Ùشار دهید</translation>
-<translation id="7615602087246926389">â€Ø´Ù…ا در حال حاضر داده‌هایی دارید Ú©Ù‡ با استÙاده از نسخه دیگری از گذرواژه حساب Google شما رمزگذاری شده‌اند. لطÙاً آن را در زیر وارد کنید.</translation>
<translation id="7616645509853975347">â€Ø³Ø±Ù¾Ø±Ø³ØªØªØ§Ù† «رابط‌های Chrome Enterprise» را در مرورگرتان روشن کرده است. این رابط‌ها به برخی از داده‌هایتان دسترسی دارند.</translation>
<translation id="7619838219691048931">برگ پایان</translation>
<translation id="762844065391966283">حذ٠تک تک</translation>
@@ -1805,13 +1855,12 @@
<translation id="782886543891417279">â€Ø´Ø¨Ú©Ù‡ Wi-Fi (<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" />)}one{# برنامه (<ph name="EXAMPLE_APP_1" />،†<ph name="EXAMPLE_APP_2" />،†<ph name="AND_MORE" />)}other{# برنامه (<ph name="EXAMPLE_APP_1" />،†<ph name="EXAMPLE_APP_2" />،†<ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">اما، شما نامرئی نیستید. با استÙاده از حالت ناشناس، مرورتان از چشمان کارÙرمای شما، ارائه‌دهنده خدمات اینترنت یا وب‌‌سایت‌هایی Ú©Ù‡ بازدید می‌کنید پنهان نمی‌ماند.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Ùایل‌ها را با پیوندهای نوع Ùایل باز کند.</translation>
<translation id="7862185352068345852">سایت را ترک می‌کنید؟</translation>
<translation id="7865448901209910068">بهترین سرعت</translation>
<translation id="7874263914261512992">â€Ø§Ø®ÛŒØ±Ø§Ù‹ گذرواژه‌تان را در سایتی Ùریب‌کار وارد کرده‌اید. Chrome توصیه می‌کند همین حالا گذرواژه‌های ذخیره‌شده برای <ph name="WEBSITE_1" />ØŒ <ph name="WEBSITE_2" />ØŒ Ùˆ سایت‌های دیگری را Ú©Ù‡ در آن‌ها از این گذرواژه استÙاده می‌کنید بررسی کنید.</translation>
<translation id="7878562273885520351">ممکن است گذرواژه‌تان درمعرض خطر باشد</translation>
+<translation id="7880146494886811634">ذخیره نشانی</translation>
<translation id="7882421473871500483">قهوه‌ای</translation>
<translation id="7887683347370398519">â€CVC را بررسی کرده Ùˆ دوباره امتحان کنید</translation>
<translation id="7887885240995164102">ورود به تصویر در تصویر</translation>
@@ -1819,6 +1868,7 @@
<translation id="7894280532028510793">اگر املا صحیح است، <ph name="BEGIN_LINK" />«عیب‌یابی شبکه» را اجرا کنید<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">ناشناس</translation>
+<translation id="793209273132572360">نشانی به‌روزرسانی شود؟</translation>
<translation id="7932579305932748336">جلد</translation>
<translation id="79338296614623784">شماره تلÙÙ† معتبری وارد کنید</translation>
<translation id="7934052535022478634">تکمیل پرداخت</translation>
@@ -1889,6 +1939,7 @@
<translation id="8175796834047840627">â€Ú†ÙˆÙ† به سیستم وارد شده‌اید، Chrome پیشنهاد می‌کند کارت‌ها را در حساب Google ذخیره کنید. در تنظیمات می‌توانید این رÙتار را تغییر دهید.</translation>
<translation id="8176440868214972690">سرپرست این دستگاه اطلاعاتی (مثل تنظیمات یا خط‌مشی‌ها) را به وب‌سایت‌های زیر ارسال کرده است.</translation>
<translation id="8184538546369750125">استÙاده از پیش‌Ùرض جهانی (مجاز)</translation>
+<translation id="8193086767630290324">اقدامات انجام‌شده با داده‌های پرچم‌گذاری‌شده به‌عنوان محرمانه</translation>
<translation id="8194797478851900357">&amp;واگرد انتقال</translation>
<translation id="8201077131113104583">نشانی وب به‌روزرسانی نامعتبر برای برنامه اÙزودنی با شناسه «<ph name="EXTENSION_ID" />».</translation>
<translation id="8202097416529803614">خلاصه سÙارش</translation>
@@ -1911,6 +1962,7 @@
<translation id="8249296373107784235">لغو</translation>
<translation id="8249320324621329438">آخرین واکشی شده:</translation>
<translation id="8253091569723639551">نشانی صورت‌حساب لازم است</translation>
+<translation id="8257387598443225809">این برنامه برای تلÙÙ† همراه طراحی شده است</translation>
<translation id="825929999321470778">نمایش همه گذرواژه‌های ذخیره‌شده</translation>
<translation id="8261506727792406068">حذÙ</translation>
<translation id="8262952874573525464">دوختن لبه پایین</translation>
@@ -2034,7 +2086,6 @@
<translation id="8719528812645237045">چند سوراخ در بالا</translation>
<translation id="8725066075913043281">سعی مجدد</translation>
<translation id="8726549941689275341">اندازه صÙحه:</translation>
-<translation id="8728672262656704056">اکنون در حالت ناشناس هستید</translation>
<translation id="8730621377337864115">تمام</translation>
<translation id="8731544501227493793">â€Ø¯Ú©Ù…Ù‡ «مدیریت گذرواژه‌ها»، برای مشاهده Ùˆ مدیریت گذرواژه‌ها در تنظیمات ChromeØŒ کلید Enter (ورود) را Ùشار دهید</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> شما توسط <ph name="MANAGER" /> مدیریت می‌شود.</translation>
@@ -2111,6 +2162,7 @@
<translation id="9020542370529661692">این صÙحه به <ph name="TARGET_LANGUAGE" /> ترجمه شده است</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(نامعتبر)</translation>
+<translation id="9030265603405983977">تک‌رنگ</translation>
<translation id="9035022520814077154">خطای امنیتی</translation>
<translation id="9038649477754266430">استÙاده از یک سرویس پیش‌بینی برای بار کردن سریع‌تر صÙحه‌ها</translation>
<translation id="9039213469156557790">علاوه بر این، این صÙحه دارای منابع دیگری است Ú©Ù‡ امن نیستند. دیگران می‌توانند در حین انتقال، این منابع را ببینند Ùˆ این منابع می‌توانند برای تغییر رÙتار صÙحه، توسط یک مهاجم تغییر داده شوند.</translation>
@@ -2134,6 +2186,7 @@
<translation id="91108059142052966">هروقت محتوای محرمانه نمایان باشد، خط‌مشی سرپرست هم‌رسانی صÙحه‌نمایش با <ph name="APPLICATION_TITLE" /> را غیرÙعال می‌کند</translation>
<translation id="9114524666733003316">درحال تأیید کردن کارت…</translation>
<translation id="9114581008513152754">â€Ø§ÛŒÙ† مرورگر را شرکت یا سازمان دیگری مدیریت نمی‌کند. Ùعالیت در این دستگاه ممکن است خارج از Chrome مدیریت شود. <ph name="BEGIN_LINK" />بیشتر بدانید<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">تازه</translation>
<translation id="9119042192571987207">بارگذاری‌شده</translation>
<translation id="9128016270925453879">خط‌مشی‌ها بار شد</translation>
<translation id="9128870381267983090">اتصال به شبکه</translation>
@@ -2152,6 +2205,7 @@
<translation id="9170848237812810038">&amp;واگرد</translation>
<translation id="9171296965991013597">از برنامه خارج می‌شوید؟</translation>
<translation id="9173282814238175921">سند تکی/برگ جدید</translation>
+<translation id="9173995187295789444">درحال جستجوی دستگاه‌های بلوتوث...</translation>
<translation id="917450738466192189">گواهی سرور نامعتبر است.</translation>
<translation id="9174917557437862841">â€Ø¯Ú©Ù…Ù‡ جابجایی برگه، برای جابجایی به این برگه، Enter را Ùشار دهید</translation>
<translation id="9179703756951298733">â€Ø§Ø·Ù„اعات پرداخت‌ها Ùˆ کارت اعتباری‌تان را در تنظیمات Chrome مدیریت کنید</translation>
diff --git a/chromium/components/strings/components_strings_fi.xtb b/chromium/components/strings/components_strings_fi.xtb
index 1108636c12a..01bce66fa91 100644
--- a/chromium/components/strings/components_strings_fi.xtb
+++ b/chromium/components/strings/components_strings_fi.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Jos tämä ruutu on valittu, Chrome tallentaa kortin kopion tälle laitteelle, jotta lomakkeiden täyttö nopeutuu.</translation>
<translation id="1110994991967754504">Valitse käyttöoikeus kohteelle <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">K&amp;umoa uudelleenjärjestely</translation>
+<translation id="1123753900084781868">Livetekstitys ei ole juuri nyt käytettävissä</translation>
<translation id="1125573121925420732">Varoituksia voi esiintyä usein, kun verkkosivustot päivittävät suojaustaan. Asian pitäisi korjaantua pian.</translation>
<translation id="112840717907525620">Käytännön välimuisti on OK</translation>
<translation id="1130564665089811311">Käännä sivu ‑painike, käännä tämä sivu Google Kääntäjällä painamalla Enter</translation>
@@ -74,6 +75,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="1240347957665416060">Laitteesi nimi</translation>
<translation id="124116460088058876">Lisää kieliä</translation>
<translation id="1243027604378859286">Tekijä:</translation>
+<translation id="1246424317317450637">Lihavoitu</translation>
<translation id="1250759482327835220">Jos haluat maksaa nopeammin ensi kerralla, tallenna kortti, nimi ja laskutusosoite Google-tilillesi.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (synkronoitu)</translation>
<translation id="1256368399071562588">&lt;p&gt;Jos verkkosivuston avaaminen ei onnistu, kokeile ensin seuraavia vianetsintäkeinoja:&lt;/p&gt;
@@ -156,6 +158,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="1476595624592550506">Vaihda salasana</translation>
<translation id="1484290072879560759">Valitse toimitusosoite</translation>
<translation id="1492194039220927094">Käytäntöjen kehotusviestit:</translation>
+<translation id="1495677929897281669">Takaisin välilehdelle</translation>
<translation id="1501859676467574491">Näytä Google-tilin kortit</translation>
<translation id="1507202001669085618">&lt;p&gt;Näet tämän virheen, jos käyttämäsi Wi-Fi-portaali edellyttää kirjautumista ennen verkon käyttöä.&lt;/p&gt;
&lt;p&gt;Korjaa virhe valitsemalla &lt;strong&gt;Yhdistä&lt;/strong&gt; sivulla, jota yrität avata.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="1532118530259321453">Viesti tältä sivulta</translation>
<translation id="153384715582417236">Siinä kaikki toistaiseksi</translation>
<translation id="1536390784834419204">Käännä sivu</translation>
+<translation id="1539840569003678498">Ilmoitus lähetetty:</translation>
<translation id="154408704832528245">Valitse jakeluosoite</translation>
<translation id="1549470594296187301">Tämän ominaisuuden käyttö edellyttää JavaScriptiä.</translation>
<translation id="155039086686388498">Insinööri-D</translation>
@@ -213,16 +217,19 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="1682696192498422849">Lyhyt reuna ensin</translation>
<translation id="168693727862418163">Tämän käytännön arvon ei onnistunut vahvistamaan kaavaa ja se ohitetaan.</translation>
<translation id="168841957122794586">Palvelinvarmenne sisältää heikon salausavaimen.</translation>
+<translation id="1696290444144917273">Näytä virtuaalisen kortin tiedot</translation>
<translation id="1697532407822776718">Kaikki on valmista.</translation>
<translation id="1703835215927279855">Kirje</translation>
<translation id="1706954506755087368">{1,plural, =1{Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; sen suojausvarmenne on päivätty huomiselle. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.}other{Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; sen suojausvarmenne on päivätty # päivää tulevaisuuteen. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.}}</translation>
<translation id="1710259589646384581">Käyttöjärjestelmä</translation>
+<translation id="1711234383449478798">Ohitettu, koska käytännön (<ph name="POLICY_NAME" />) arvoksi ei ole asetettu <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> haluaa tallentaa tietoja pysyvästi paikalliselle tietokoneellesi.</translation>
<translation id="1713628304598226412">Lokero 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Postilaatikko 3</translation>
<translation id="1718029547804390981">Tiedosto on liian suuri merkintöihin</translation>
<translation id="1721424275792716183">* Kenttä on pakollinen.</translation>
+<translation id="1727613060316725209">Varmenne on voimassa</translation>
<translation id="1727741090716970331">Lisää kelvollinen kortin numero</translation>
<translation id="1728677426644403582">Tämä on verkkosivun lähdekoodi.</translation>
<translation id="173080396488393970">Tätä korttityyppiä ei tueta.</translation>
@@ -246,7 +253,6 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
pyyntöäsi (<ph name="SITE" />). Alkuperäkäytäntöjen avulla
sivusto-operaattorit voivat määrittää sen tietosuojan ja muita ominaisuuksia.</translation>
<translation id="1778646502362731194">JIS B0 (1 030 mm x 1 456 mm)</translation>
-<translation id="1783075131180517613">Päivitä synkronoinnin tunnuslause.</translation>
<translation id="1787142507584202372">Avoimet välilehdet näkyvät tässä.</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, useita toimintoja saatavilla, selaa niitä painamalla sarkainta</translation>
@@ -279,6 +285,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="1919345977826869612">Mainokset</translation>
<translation id="1919367280705858090">Tiettyjen virheiden korjaaminen</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ei mitään}=1{1 sivusto}other{# sivustoa}}</translation>
+<translation id="1924727005275031552">Uusi</translation>
<translation id="1945968466830820669">Voit menettää organisaatiosi tilin käyttöoikeuden tai joutua identiteettivarkauden uhriksi. Chromium suosittelee vaihtamaan salasanan välittömästi.</translation>
<translation id="1947454675006758438">Niitti oikeassa yläkulmassa</translation>
<translation id="1958218078413065209">Parhaat pisteesi ovat <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="2042213636306070719">Lokero 7</translation>
<translation id="204357726431741734">Kirjaudu sisään käyttääksesi Google-tilillesi tallennettuja salasanoja</translation>
<translation id="2053111141626950936">Kielellä <ph name="LANGUAGE" /> kirjoitettuja sivuja ei käännetä.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Kun tämä asetus on päällä ja tila on aktiivinen, Chrome päättelee, minkä ihmisryhmän eli "kohortin" toimintaa viimeaikainen selaustoimintasi eniten muistuttaa. Mainostajat voivat valita ryhmälle mainoksia, ja selaustoimintasi pysyy yksityisenä laitteellasi. Ryhmäsi päivitetään päivittäin.}=1{Kun tämä asetus on päällä ja tila on aktiivinen, Chrome päättelee, minkä ihmisryhmän eli "kohortin" toimintaa viimeaikainen selaustoimintasi eniten muistuttaa. Mainostajat voivat valita ryhmälle mainoksia, ja selaustoimintasi pysyy yksityisenä laitteellasi. Ryhmäsi päivitetään päivittäin.}other{Kun tämä asetus on päällä ja tila on aktiivinen, Chrome päättelee, minkä ihmisryhmän eli "kohortin" toimintaa viimeaikainen selaustoimintasi eniten muistuttaa. Mainostajat voivat valita ryhmälle mainoksia, ja selaustoimintasi pysyy yksityisenä laitteellasi. Ryhmäsi päivitetään {NUM_DAYS} päivän välein.}}</translation>
<translation id="2053553514270667976">Postinumero</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ehdotus}other{# ehdotusta}}</translation>
<translation id="2071692954027939183">Ilmoitukset on estetty automaattisesti, koska et yleensä salli niitä</translation>
<translation id="2079545284768500474">Kumoa</translation>
<translation id="20817612488360358">Järjestelmän välityspalvelinasetukset on määritetty käytettäviksi, mutta erilliset välityspalvelimen asetukset on myös määritetty.</translation>
<translation id="2082238445998314030">Tulos <ph name="RESULT_NUMBER" />/<ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Tallenna…</translation>
<translation id="2088086323192747268">Muuta synkronointivalintoja ‑painike, paina Enter, niin voit valita synkronoitavat tiedot Chromen asetuksista</translation>
<translation id="2091887806945687916">Ääni</translation>
<translation id="2094505752054353250">Verkkotunnukset eivät ole yhteensopivat</translation>
@@ -379,6 +388,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="2317259163369394535"><ph name="DOMAIN" /> pyytää käyttäjänimeä ja salasanaa.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, vanhenee <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Järjestelmänvalvojan hallinnoima asetus</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> haluaa muodostaa laiteparin</translation>
<translation id="2344028582131185878">Automaattiset lataukset</translation>
<translation id="2346319942568447007">Kopioimasi kuva</translation>
<translation id="2354001756790975382">Muut kirjanmerkit</translation>
@@ -386,8 +396,10 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="2355395290879513365">Hyökkääjät voivat mahdollisesti nähdä kuvat, joita katselet tällä sivustolla, ja huijata sinua muokkaamalla niitä.</translation>
<translation id="2356070529366658676">Kysy</translation>
<translation id="2357481397660644965"><ph name="DEVICE_MANAGER" /> ylläpitää laitettasi ja <ph name="ACCOUNT_MANAGER" /> tiliäsi.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Alle päivän kuluttua}=1{Päivän kuluttua}other{{NUM_DAYS} päivän kuluttua}}</translation>
<translation id="2359629602545592467">Useita</translation>
<translation id="2359808026110333948">Jatka</translation>
+<translation id="2359961752320758691">Virtuaalinen korttinumero on käytössä.</translation>
<translation id="2367567093518048410">Taso</translation>
<translation id="2372464001869762664">Vahvistamisen jälkeen korttitiedot Google-tililtäsi jaetaan tälle sivustolle. Etsi CVC Plex-tilisi tiedoista.</translation>
<translation id="2380886658946992094">Lakiasiat</translation>
@@ -398,6 +410,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="239429038616798445">Lähetystapa ei ole käytettävissä. Kokeile toista tapaa.</translation>
<translation id="2396249848217231973">K&amp;umoa poisto</translation>
<translation id="2410754574180102685">Viranomaiset-lakiasiat</translation>
+<translation id="2413155254802890957">Vanha</translation>
<translation id="2413528052993050574">Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />; sen suojausvarmenne ei välttämättä ole voimassa. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.</translation>
<translation id="2414886740292270097">Tumma</translation>
<translation id="2438874542388153331">Neljä reikää oikealla</translation>
@@ -425,10 +438,10 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="2521385132275182522">Niitti oikeassa alareunassa</translation>
<translation id="2523886232349826891">Tallennetaan vain tälle laitteelle</translation>
<translation id="2524461107774643265">Lisää tietoja</translation>
-<translation id="2526590354069164005">Työpöytä</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{ja 1 muu}other{ja # muuta}}</translation>
<translation id="2536110899380797252">Lisää osoite</translation>
<translation id="2539524384386349900">Tunnista</translation>
+<translation id="2541219929084442027">Incognito-välilehdillä avattujen sivujen tietoja ei säilytetä selaimen historiassa, evästeissä tai hakuhistoriassa, kun kaikki incognito-välilehdet suljetaan. Ladatut tiedostot ja luodut kirjanmerkit säilytetään.</translation>
<translation id="2544644783021658368">Yksittäinen dokumentti</translation>
<translation id="254947805923345898">Käytännön arvo ei kelpaa.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> lähetti virheellisen vastauksen.</translation>
@@ -448,6 +461,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="2629325967560697240">Jos haluat käyttää Chromen tehokkainta suojausta, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ota parannettu suojaus käyttöön<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Sivuston <ph name="HOST_NAME" /> palvelimen IP-osoitetta ei löytynyt.</translation>
<translation id="2639739919103226564">Tila:</translation>
+<translation id="264810637653812429">Yhteensopivia laitteita ei löytynyt.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, tyhjennä selaushistoria, evästeet, välimuisti ja muita tietoja Chromen asetuksista painamalla sarkainta ja sitten Enter</translation>
<translation id="2650446666397867134">Tiedoston käyttöoikeus evättiin</translation>
@@ -494,6 +508,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<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="2807052079800581569">Kuvan Y sijainti</translation>
+<translation id="2820957248982571256">Etsitään…</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>
@@ -501,6 +516,8 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="2850739647070081192">Kutsu (kirjekuori)</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="2859806420264540918">Tällä sivustolla on häiritseviä tai harhaanjohtavia mainoksia.</translation>
+<translation id="287596039013813457">Ystävällinen</translation>
+<translation id="2876489322757410363">Poistutaan incognito-tilasta, jotta ulkoisessa sovelluksessa maksaminen onnistuu. Haluatko jatkaa?</translation>
<translation id="2878197950673342043">Julistetaitos</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Ikkunoiden sijoittelu</translation>
@@ -550,7 +567,6 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="3060227939791841287">C9 (kirjekuori)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, tee turvatarkistus Chromen asetuksissa painamalla sarkainta ja sitten Enter</translation>
<translation id="3061707000357573562">Virheenkorjauspalvelu</translation>
-<translation id="3064966200440839136">Incognito-tilasta poistutaan ulkoisessa sovelluksessa maksamisen vuoksi. Haluatko jatkaa?</translation>
<translation id="306573536155379004">Peli aloitettu</translation>
<translation id="3080254622891793721">Graafinen</translation>
<translation id="3086579638707268289">Toimintaasi verkossa valvotaan</translation>
@@ -573,7 +589,6 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="315504272643575312"><ph name="MANAGER" /> ylläpitää tiliäsi.</translation>
<translation id="3157931365184549694">Palauta</translation>
<translation id="3162559335345991374">Käyttämäsi Wi-Fi saattaa edellyttää kirjautumista.</translation>
-<translation id="3167968892399408617">Incognito-välilehdillä avattujen sivujen tietoja ei säilytetä selaimen historiassa, evästeissä tai hakuhistoriassa, kun kaikki incognito-välilehdet suljetaan. Ladatut tiedostot ja luodut kirjanmerkit säilytetään.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Saari</translation>
<translation id="3176929007561373547">Tarkista välityspalvelinasetukset tai ota yhteyttä verkon järjestelmänvalvojaan
@@ -600,10 +615,12 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<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="3249845759089040423">Svengaava</translation>
<translation id="3252266817569339921">ranska</translation>
<translation id="3266793032086590337">Arvo (ristiriita)</translation>
<translation id="3268451620468152448">Avoimet välilehdet</translation>
<translation id="3270847123878663523">K&amp;umoa uudelleenjärjestely</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> haluaa muodostaa yhteyden</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Organisaatiosi (<ph name="ENROLLMENT_DOMAIN" />) on lähettänyt seuraaville verkkosivustoille joitakin tietoja, kuten asetuksia tai käytäntöjä.</translation>
<translation id="3282497668470633863">Lisää kortissa oleva nimi</translation>
@@ -656,6 +673,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="3428151540071562330">Yksi tai useampi DnsOverHttpsTemplates-palvelinmallien URI-tunnuksista on virheellinen, eikä niitä käytetä.</translation>
<translation id="3431636764301398940">Tallenna kortti tälle laitteelle</translation>
<translation id="3432601291244612633">Sulje sivu</translation>
+<translation id="3435738964857648380">Suojaus</translation>
<translation id="3435896845095436175">Ota käyttöön</translation>
<translation id="3438829137925142401">Käytä Google-tilillesi tallennettuja salasanoja</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -698,7 +716,10 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="3584299510153766161">Kaksi reikää alareunassa</translation>
<translation id="3586931643579894722">Piilota lisätiedot</translation>
<translation id="3587738293690942763">Keskitaso</translation>
+<translation id="3590643883886679995">Kirjautumisdata pysyy tällä laitteella incognito-tilan sulkemisen jälkeen.</translation>
+<translation id="359126217934908072">Kuukausi/vuosi:</translation>
<translation id="3592413004129370115">Italialainen (kirjekuori)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Voit nollata ryhmän milloin tahansa. Uuteen ryhmään liittyminen vie noin päivän.}=1{Voit nollata ryhmän milloin tahansa. Uuteen ryhmään liittyminen vie noin päivän.}other{Voit nollata ryhmän milloin tahansa. Uuteen ryhmään liittyminen vie {NUM_DAYS} päivää.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Järjestelmänvalvoja esti sovelluksen</translation>
<translation id="3608932978122581043">Syöttösuunta</translation>
@@ -707,13 +728,13 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="3615877443314183785">Anna kelvollinen viimeinen voimassaolopäivä.</translation>
<translation id="36224234498066874">Poista selaustiedot...</translation>
<translation id="362276910939193118">Näytä koko selaushistoria</translation>
-<translation id="3625635938337243871">Kirjautumisdata pysyy tällä laitteella incognito-tilan sulkemisen jälkeen.</translation>
<translation id="3630155396527302611">Jos sillä on jo verkon käyttöoikeus, kokeile sen poistamista
sallittujen ohjelmien luettelosta ja lisäämistä sitten uudelleen.</translation>
<translation id="3630699740441428070">Laitteen järjestelmänvalvojat ovat valinneet yhteysasetuksesi, joten he saattavat nähdä verkkoliikenteen, myös avaamasi sivustot.</translation>
<translation id="3631244953324577188">Biometriikka</translation>
<translation id="3633738897356909127">Päivitä Chrome ‑painike, päivitä Chrome sen asetuksista painamalla Enter</translation>
<translation id="3634530185120165534">Lokero 5</translation>
+<translation id="3637662659967048211">Tallenna Google-tilille</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Sovellus:</translation>
<translation id="3650584904733503804">Todennus onnistui</translation>
@@ -754,6 +775,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="3781428340399460090">Pinkki</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth-laitteet</translation>
+<translation id="3787675388804467730">Virtuaalinen korttinumero</translation>
<translation id="3787705759683870569">Vanhenee <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Koko 16</translation>
<translation id="3789841737615482174">Asenna</translation>
@@ -773,6 +795,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="3841184659773414994">Tiedostojen käsittelijät</translation>
<translation id="385051799172605136">Takaisin</translation>
<translation id="3858027520442213535">Päivitä päivämäärä ja aika</translation>
+<translation id="3881478300875776315">Näytä vähemmän rivejä</translation>
<translation id="3884278016824448484">Ristiriitainen laitteen tunnus</translation>
<translation id="3885155851504623709">Kunta</translation>
<translation id="388632593194507180">Valvonta havaittu</translation>
@@ -798,6 +821,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="397105322502079400">Lasketaan...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> on estetty</translation>
<translation id="3973357910713125165">Tee Chromen turvatarkistus ‑painike, tee turvatarkistus Chromen asetuksissa painamalla Enter</translation>
+<translation id="3986705137476756801">Laita Livetekstitys päälle toistaiseksi</translation>
<translation id="3987405730340719549">Chrome epäilee tätä sivustoa vilpilliseksi tai valesivustoksi.
Jos uskot, että ilmoitus on virheellinen, siirry osoitteeseen https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -894,13 +918,14 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="4275830172053184480">Käynnistä laite uudelleen</translation>
<translation id="4277028893293644418">Pyydä uusi salasana</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="4287885627794386150">Kokeiluun hyväksyttävä, mutta ei aktiivinen</translation>
<translation id="4297502707443874121">Sivun <ph name="THUMBNAIL_PAGE" /> pikkukuva</translation>
<translation id="42981349822642051">Laajenna</translation>
<translation id="4300675098767811073">Useita reikiä oikealla</translation>
<translation id="4302514097724775343">Pelaa napauttamalla dinosaurusta</translation>
<translation id="4302965934281694568">Chou3 (kirjekuori)</translation>
<translation id="4305666528087210886">Tiedostoa ei voi käyttää</translation>
-<translation id="4305817255990598646">Vaihda</translation>
+<translation id="4306529830550717874">Tallennetaanko osoite?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Estä (oletus)</translation>
<translation id="4314815835985389558">Synkronointiasetusten muokkaus</translation>
@@ -927,6 +952,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="4377125064752653719">Yritit yhdistää sivustoon <ph name="DOMAIN" />, mutta varmenteen myöntäjä on kumonnut palvelimen esittämän varmenteen. Palvelimen esittämiin suojaustietoihin ei siis tule luottaa. Saatat olla tekemisissä hakkerin kanssa.</translation>
<translation id="4378154925671717803">Puhelin</translation>
<translation id="4390472908992056574">Reuna</translation>
+<translation id="4406883609789734330">Livetekstitys</translation>
<translation id="4406896451731180161">hakutulokset</translation>
<translation id="4408413947728134509">Evästeet <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Lisäsit juuri salasanasi petolliselle sivustolle. Chrome suosittelee vaihtamaan salasanan heti kaikilla sivustoilla, joilla käytät sitä (esim. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ja <ph name="WEBSITE_3" />).</translation>
@@ -939,7 +965,6 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<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="4464826014807964867">Verkkosivustot, joilla on tietoa organisaatiostasi</translation>
-<translation id="4466881336512663640">Lomakkeen muutokset menetetään. Haluatko varmasti jatkaa?</translation>
<translation id="4476953670630786061">Tämä lomake ei ole suojattu. Automaattinen täyttö on laitettu pois päältä.</translation>
<translation id="4477350412780666475">Seuraava kappale</translation>
<translation id="4482953324121162758">Tätä sivustoa ei käännetä.</translation>
@@ -973,6 +998,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="4594403342090139922">K&amp;umoa poisto</translation>
<translation id="4597348597567598915">Koko 8</translation>
<translation id="4600854749408232102">C6/C5 (kirjekuori)</translation>
+<translation id="4606870351894164739">Vaikuttava</translation>
<translation id="4628948037717959914">Kuva</translation>
<translation id="4631649115723685955">Hyvitystarjous linkitetty</translation>
<translation id="4636930964841734540">Tietoja</translation>
@@ -992,6 +1018,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="4691835149146451662">Arkkitehti-A (kirjekuori)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Puoli</translation>
+<translation id="4702656508969495934">Livetekstitys näkyvissä, siirrä kohdistusta ikkunan vaihdolla</translation>
<translation id="4708268264240856090">Yhteys keskeytyi</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windowsin verkon diagnostiikkaa<ph name="END_LINK" /></translation>
@@ -1005,6 +1032,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="4738601419177586157">Hakuehdotus <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Ylläpidä salasanoja…</translation>
<translation id="4744603770635761495">Suoritettavan tiedoston polku</translation>
+<translation id="4749011317274908093">Olet siirtynyt incognito-tilaan</translation>
<translation id="4750917950439032686">Salasanat, luottokorttinumerot ja muut tietosi pysyvät yksityisinä, kun ne lähetetään tälle sivustolle.</translation>
<translation id="4756388243121344051">&amp;Historia</translation>
<translation id="4758311279753947758">Lisää yhteystiedot</translation>
@@ -1034,6 +1062,8 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="4813512666221746211">Verkkovirhe</translation>
<translation id="4816492930507672669">Sovita sivulle</translation>
<translation id="4819347708020428563">Muokataanko merkintöjä oletusnäkymässä?</translation>
+<translation id="4825507807291741242">Tehokas</translation>
+<translation id="4838327282952368871">Unenomainen</translation>
<translation id="484462545196658690">Automaattinen</translation>
<translation id="4850886885716139402">Näytä</translation>
<translation id="485316830061041779">saksa</translation>
@@ -1170,6 +1200,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="5314967030527622926">Vihko</translation>
<translation id="5316812925700871227">Käännä vastapäivään</translation>
<translation id="5317780077021120954">Tallenna</translation>
+<translation id="5321288445143113935">Suurennettu</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" />/<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Valitse yhteystiedot</translation>
<translation id="5327248766486351172">Nimi</translation>
@@ -1177,11 +1208,13 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="5332219387342487447">Toimitustapa</translation>
<translation id="5333022057423422993">Chrome löysi juuri käyttämäsi salasanan tietosuojaloukkauksesta. Suosittelemme tarkistamaan tallennetut salasanasi tilisi suojaamiseksi.</translation>
<translation id="5334013548165032829">Yksityiskohtaiset järjestelmälokit</translation>
+<translation id="5334145288572353250">Tallennetaanko osoite?</translation>
<translation id="5340250774223869109">Sovellus on estetty</translation>
<translation id="534295439873310000">NFC-laitteet</translation>
<translation id="5344579389779391559">Tämä sivu voi yrittää veloittaa sinua</translation>
<translation id="5355557959165512791"><ph name="SITE" /> ei juuri nyt ole käytettävissä, koska sen varmenne ei ole voimassa. Verkkovirheet ja hyökkäykset ovat yleensä väliaikaisia, joten sivu luultavasti toimii myöhemmin.</translation>
<translation id="536296301121032821">Käytännön asetuksien tallentaminen epäonnistui</translation>
+<translation id="5363309033720083897">Järjestelmänvalvojan sallima sarjaportti</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="5386426401304769735">Tämän sivuston varmenneketju sisältää varmenteen, joka on allekirjoitettu SHA-1:llä.</translation>
@@ -1190,6 +1223,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="5398772614898833570">Mainokset estetty</translation>
<translation id="5400836586163650660">Harmaa</translation>
<translation id="540969355065856584">Palvelin ei voinut todistaa olevansa <ph name="DOMAIN" />, sillä sen suojausvarmenne ei tällä hetkellä ole kelvollinen. Tämä voi johtua määritysvirheestä tai verkkoyhteytesi siepanneesta hyökkääjästä.</translation>
+<translation id="541143247543991491">Pilvi (koko järjestelmä)</translation>
<translation id="541416427766103491">Pinoaja 4</translation>
<translation id="5421136146218899937">Poista selaustiedot...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> haluaa lähettää sinulle ilmoituksia</translation>
@@ -1203,6 +1237,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="5455374756549232013">Virheellinen käytännön aikaleima</translation>
<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="5463625433003343978">Haetaan laitteita…</translation>
<translation id="5469868506864199649">italia</translation>
<translation id="5470861586879999274">&amp;Toista muokkaus</translation>
<translation id="5478437291406423475">B6/C4 (kirjekuori)</translation>
@@ -1252,7 +1287,6 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="5624120631404540903">Hallitse salasanoja</translation>
<translation id="5629630648637658800">Käytännön asetuksien lataaminen epäonnistui</translation>
<translation id="5631439013527180824">Laitteenhallintatunnus on virheellinen</translation>
-<translation id="5632627355679805402">Datasi salattiin <ph name="BEGIN_LINK" />Google-salasanallasi<ph name="END_LINK" /> <ph name="TIME" />. Aloita synkronointi antamalla salasana.</translation>
<translation id="5633066919399395251">Sivustolle <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> hyökännyt taho voi yrittää asentaa tietokoneellesi vaarallisia ohjelmia, jotka varastavat tai poistavat tietojasi, esimerkiksi kuvia, salasanoja, viestejä tai luottokorttitietoja. <ph name="BEGIN_LEARN_MORE_LINK" />Lisätietoja<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Harhaanjohtava sisältö estetty</translation>
<translation id="5644090287519800334">1. puolen kuvan X vaihto</translation>
@@ -1291,12 +1325,12 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="5785756445106461925">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 ulkoasua muokkaamalla näitä osia.</translation>
<translation id="5786044859038896871">Täytetäänkö kortin tiedot?</translation>
<translation id="578633867165174378">Chrome löysi juuri käyttämäsi salasanan tietosuojaloukkauksesta. Suosittelemme vaihtamaan tämän salasanan heti.</translation>
-<translation id="5798290721819630480">Hylätäänkö muutokset?</translation>
<translation id="5803412860119678065">Täytetäänkö kortin <ph name="CARD_DETAIL" /> tiedot?</translation>
<translation id="5804241973901381774">Luvat</translation>
<translation id="5804427196348435412">Käytä NFC-laitteita</translation>
<translation id="5810442152076338065">Yhteytesi kohteeseen <ph name="DOMAIN" /> on salattu vanhentuneella salaustekniikalla.</translation>
<translation id="5813119285467412249">&amp;Toista lisäys</translation>
+<translation id="5817918615728894473">Muodosta laitepari</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Tätä korttia veloitetaan kun maksat, mutta sen oikeaa numeroa ei jaeta sivustolle. Väliaikainen CVC luodaan turvallisuuden parantamiseksi.}other{Valitsemaasi korttia veloitetaan kun maksat, mutta sen oikeaa numeroa ei jaeta sivustolle. Väliaikainen CVC luodaan turvallisuuden parantamiseksi.}}</translation>
<translation id="5826507051599432481">Yleinen nimi (CN)</translation>
<translation id="5838278095973806738">Älä anna tälle sivustolle salasanoja, luottokorttinumeroita tai muita arkaluonteisia tietoja, sillä hyökkääjät saattavat varastaa ne.</translation>
@@ -1304,6 +1338,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="5855253129151731373">Sivuston isäntänimi on samankaltainen kuin <ph name="LOOKALIKE_DOMAIN" />. Hyökkääjät jäljittelevät joskus sivustoja tekemällä verkkotunnukseen pieniä muutoksia, joita on vaikea havaita.
Jos uskot, että ilmoitus on virheellinen, siirry osoitteeseen https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Pois päältä</translation>
<translation id="5862579898803147654">Pinoaja 8</translation>
<translation id="5863847714970149516">Avaamasi sivu voi yrittää veloittaa sinulta rahaa</translation>
<translation id="5866257070973731571">Lisää puhelinnumero</translation>
@@ -1320,6 +1355,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="5913377024445952699">Näytön tallennus keskeytetty</translation>
<translation id="59174027418879706">Käytössä</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 käytössä}other{# käytössä}}</translation>
<translation id="5921185718311485855">Päällä</translation>
<translation id="5921639886840618607">Tallennetaanko kortti Google-tilille?</translation>
<translation id="5922853866070715753">Lähes valmis</translation>
@@ -1339,6 +1375,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="5989320800837274978">Kiinteitä välityspalvelimia tai .pac-URL-osoitetta ei ole määritetty.</translation>
<translation id="5992691462791905444">Kolmoistaite (engineering)</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> tulosta: <ph name="SEARCH_TEXT" /></translation>
+<translation id="6006484371116297560">Perinteinen</translation>
<translation id="6008122969617370890">N-to-1-järjestys</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Tarkista salasanasi</translation>
@@ -1360,6 +1397,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="6045164183059402045">Asetusmalli</translation>
<translation id="6047233362582046994">Jos ymmärrät käyntiä koskevat turvallisuusriskit, voit <ph name="BEGIN_LINK" />siirtyä tälle sivustolle<ph name="END_LINK" /> jo ennen haitallisten sovellusten poistamista.</translation>
<translation id="6047927260846328439">Tämä sisältö saattaa yrittää huijata sinua asentamaan ohjelmistoja tai paljastamaan henkilökohtaisia tietoja. <ph name="BEGIN_LINK" />Näytä silti<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Paina pitkään |<ph name="ACCELERATOR" />|, niin poistut koko näytön tilasta.</translation>
<translation id="6049488691372270142">Sivun toimitus</translation>
<translation id="6051221802930200923"><ph name="SITE" /> ei juuri nyt ole käytettävissä, koska se käyttää varmenteiden kiinnittämistä. Verkkovirheet ja hyökkäykset ovat yleensä väliaikaisia, joten sivu luultavasti toimii myöhemmin.</translation>
<translation id="6051898664905071243">Sivumäärä:</translation>
@@ -1376,6 +1414,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="610911394827799129">Google-tililläsi voi olla muita selaushistoriatietoja osoitteessa <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
<translation id="6116338172782435947">nähdä leikepöydälle kopioidun tekstin ja kuvat</translation>
<translation id="6120179357481664955">Muistatko UPI-tunnuksesi?</translation>
+<translation id="6123290840358279103">Näytä virtuaalinen kortti</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Tarkista kaikki kaapelit ja käynnistä uudelleen reitittimet, modeemit ja muut
käytössä olevat verkkolaitteet.</translation>
@@ -1412,6 +1451,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="6289939620939689042">Sivun väri</translation>
<translation id="6290238015253830360">Suositellut artikkelit näkyvät tässä.</translation>
<translation id="6293309776179964942">JIS B5 (182 mm x 257 mm)</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chromen Google Assistant suljetaan</translation>
<translation id="6305205051461490394">Sivustoon <ph name="URL" /> ei saada yhteyttä.</translation>
<translation id="6312113039770857350">Verkkosivu ei ole saatavilla</translation>
@@ -1437,6 +1477,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="6390200185239044127">Kolmoistaite puoliksi</translation>
<translation id="6390662030813198813">Insinööri-E</translation>
<translation id="6393956493820063117">Järjestelmänvalvojakäytäntö on estänyt tähän paikkaan liittämisen sivustolta<ph name="ORIGIN_NAME" /></translation>
+<translation id="6398765197997659313">Poistu koko näytön tilasta</translation>
<translation id="6401136357288658127">Tämä käytäntö on vanhentunut. Käytä <ph name="NEW_POLICY" /> ‑käytäntöä sen sijaan.</translation>
<translation id="6404511346730675251">Muokkaa kirjanmerkkiä</translation>
<translation id="6406765186087300643">C0 (kirjekuori)</translation>
@@ -1449,7 +1490,6 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="6428450836711225518">Vahvista puhelinnumerosi</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="6440503408713884761">Ohitettu</translation>
<translation id="6443406338865242315">Asentamasi laajennukset</translation>
<translation id="6446163441502663861">Kahu (kirjekuori)</translation>
@@ -1492,6 +1532,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="6624427990725312378">Yhteystiedot</translation>
<translation id="6626291197371920147">Lisää kelvollinen kortin numero</translation>
<translation id="6628463337424475685"><ph name="ENGINE" />-haku</translation>
+<translation id="6630043285902923878">Haetaan USB-laitteita…</translation>
<translation id="6630809736994426279">Sivustolle <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> hyökännyt taho voi yrittää asentaa Maciisi vaarallisia ohjelmia, jotka varastavat tai poistavat tietojasi, esimerkiksi kuvia, salasanoja, viestejä tai luottokorttitietoja. <ph name="BEGIN_LEARN_MORE_LINK" />Lisätietoja<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4 (257 mm x 364 mm)</translation>
<translation id="6643016212128521049">Tyhjennä</translation>
@@ -1507,6 +1548,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="6671697161687535275">Poistetaanko lomake-ehdotus Chromiumista?</translation>
<translation id="6685834062052613830">Kirjaudu ulos ja suorita määritys loppuun.</translation>
<translation id="6687335167692595844">Fonttikokoa pyydetty</translation>
+<translation id="6688743156324860098">Päivitä…</translation>
<translation id="6689249931105087298">Suhteellinen mustan pisteen pakkauksella</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="6698381487523150993">Luomispvm:</translation>
@@ -1522,6 +1564,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="6744009308914054259">Voit lukea artikkeleita offline-tilassa Lataukset-kohdassa, kun odotat yhteyden muodostamista.</translation>
<translation id="6753269504797312559">Käytännön arvo</translation>
<translation id="6757797048963528358">Laitteesi siirtyi virransäästötilaan.</translation>
+<translation id="6767985426384634228">Päivitetäänkö osoite?</translation>
<translation id="6768213884286397650">Hagaki (postikortti)</translation>
<translation id="6775759552199460396">JIS B2 (515 mm x 728 mm)</translation>
<translation id="67862343314499040">Lila</translation>
@@ -1544,6 +1587,7 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome teki sivusta yksinkertaisemman, jotta sen lukeminen olisi helpompaa. Chrome nouti alkuperäisen sivun suojaamattoman yhteyden kautta.</translation>
<translation id="6891596781022320156">Käytännön tasoa ei tueta.</translation>
+<translation id="6895143722905299846">Virtuaalinen numero:</translation>
<translation id="6895330447102777224">Korttisi vahvistettiin.</translation>
<translation id="6897140037006041989">User agent</translation>
<translation id="6898699227549475383">Organisaatio (O)</translation>
@@ -1579,10 +1623,10 @@ Muussa tapauksessa tämä estetään tietosuoja-asetuksilla. Jos sallit tämän,
<translation id="7004583254764674281">Vahvista kortteja nopeammin Windows Hellolla</translation>
<translation id="7006930604109697472">Lähetä silti</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Koon muuttamisasetukset</translation>
<translation id="7014741021609395734">Zoomauksen taso</translation>
<translation id="7016992613359344582">Veloitukset voivat olla kertaluontoisia tai toistuvia, eikä niitä välttämättä esitetä selkeästi.</translation>
<translation id="7029809446516969842">Salasanat</translation>
+<translation id="7030436163253143341">Varmenne ei ole voimassa</translation>
<translation id="7031646650991750659">Asentamasi Google Play ‑sovellukset</translation>
<translation id="7050187094878475250">Yritit muodostaa yhteyden verkkotunnukseen <ph name="DOMAIN" />, mutta palvelin esitti varmenteen, joka on voimassa liian kauan ollakseen luotettava.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Tätä korttia ei voi tallentaa juuri nyt}other{Näitä kortteja ei voi tallentaa juuri nyt}}</translation>
@@ -1652,12 +1696,14 @@ Lisätietoja:
<translation id="7300012071106347854">Koboltinsininen</translation>
<translation id="7302712225291570345"><ph name="TEXT" /></translation>
<translation id="7304030187361489308">Korkea</translation>
+<translation id="7305756307268530424">Aloita hitaampana</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Yhteysohjeet</translation>
<translation id="7323804146520582233">Piilota osio <ph name="SECTION" /></translation>
<translation id="733354035281974745">Laitteen paikallisen tilin ohitus</translation>
<translation id="7333654844024768166">Lisäsit juuri salasanasi petolliselle sivustolle. Chromium suosittelee vaihtamaan salasanan heti kaikilla sivustoilla, joilla käytät sitä (esim. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ja <ph name="WEBSITE_3" />).</translation>
<translation id="7334320624316649418">&amp;Toista uudelleenjärjestely</translation>
+<translation id="7337248890521463931">Näytä enemmän rivejä</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>
@@ -1665,6 +1711,7 @@ Lisätietoja:
<translation id="7349430561505560861">A4-ekstra</translation>
<translation id="7353601530677266744">Komentorivi</translation>
<translation id="7359588939039777303">Mainokset estetty</translation>
+<translation id="7363096869660964304">Et ole kuitenkaan näkymätön. Incognito-tilan käyttäminen ei kätke selaamistasi työnantajaltasi, internetpalveluntarjoajaltasi tai avaamiltasi sivustoilta.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, paina sarkainta ja Enter, niin voit lisätä ja muuttaa osoitteita Chromen asetuksista</translation>
<translation id="7365849542400970216">Tiedot laitteesi käytöstä?</translation>
<translation id="7372973238305370288">hakutulos</translation>
@@ -1675,7 +1722,9 @@ Lisätietoja:
<translation id="7378594059915113390">Mediaohjaimet</translation>
<translation id="7378627244592794276">Ei</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ei sovellu</translation>
<translation id="7390545607259442187">Vahvista kortti</translation>
+<translation id="7392089738299859607">Päivitä osoite</translation>
<translation id="7399802613464275309">Turvatarkistus</translation>
<translation id="7400418766976504921">URL-osoite</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> on ylläpidetty</translation>
@@ -1690,6 +1739,7 @@ Lisätietoja:
&lt;li&gt;Saat ohjeita ohjelmiston pysyvään poistamiseen tietokoneelta &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome-ohjekeskuksesta&lt;/a&gt;.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Leveä</translation>
+<translation id="7410471291937727359">Ihana</translation>
<translation id="7416351320495623771">Ylläpidä salasanoja…</translation>
<translation id="7419106976560586862">Profiilin polku</translation>
<translation id="7437289804838430631">Lisää yhteystieto</translation>
@@ -1705,7 +1755,7 @@ Lisätietoja:
<translation id="7481312909269577407">Seuraava</translation>
<translation id="7485870689360869515">Tietoja ei löydy.</translation>
<translation id="7495528107193238112">Tämä sisältö on estetty. Pyydä sivuston omistajalta apua ongelman korjaamiseen.</translation>
-<translation id="7498234416455752244">Jatka muokkausta</translation>
+<translation id="7498193950643227031">Koon muuttaminen voi saada sen toimimaan odottamattomalla tavalla. Voit nyt rajoittaa sovellusten koon muuttamisominaisuutta kohdasta <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Lisäsit juuri salasanasi petolliselle sivustolle. Chromium suosittelee tarkistamaan näihin tallentamasi salasanat: <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ja muut sivustot, joilla käytät salasanaa tällä hetkellä.</translation>
<translation id="7508255263130623398">Palautettu käytännön laitetunnus on tyhjä tai ei vastaa nykyistä laitetunnusta.</translation>
<translation id="7508870219247277067">Avokadonvihreä</translation>
@@ -1725,6 +1775,7 @@ Lisätietoja:
<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="755279583747225797">Kokeilu on aktiivinen</translation>
<translation id="7552846755917812628">Kokeile seuraavia keinoja:</translation>
<translation id="7554475479213504905">Päivitä ja näytä siitä huolimatta</translation>
<translation id="7554791636758816595">Uusi välilehti</translation>
@@ -1743,7 +1794,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, katso ja ylläpidä salasanojasi Chromen asetuksissa painamalla sarkainta ja sitten Enter</translation>
-<translation id="7615602087246926389">Tietojasi on jo salattu Google-tilisi salasanan muulla versiolla. Syötä salasana alla.</translation>
<translation id="7616645509853975347">Järjestelmänvalvoja on ottanut Chrome Enterprise Connectorsin käyttöön selaimellesi. Nämä liittimet pääsevät osaan datastasi.</translation>
<translation id="7619838219691048931">Viimeinen sivu</translation>
<translation id="762844065391966283">Yksi kerrallaan</translation>
@@ -1808,13 +1858,12 @@ Lisätietoja:
<translation id="782886543891417279">Käyttämäsi Wi-Fi (<ph name="WIFI_NAME" />) saattaa edellyttää kirjautumista.</translation>
<translation id="7836231406687464395">Postfix (kirjekuori)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ei mitään}=1{1 sovellus (<ph name="EXAMPLE_APP_1" />)}=2{2 sovellusta (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# sovellusta (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Et ole kuitenkaan näkymätön. Incognito-tilan käyttäminen ei kätke selaamistasi työnantajaltasi, internetpalveluntarjoajaltasi tai käyttämiltäsi sivustoilta.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">avata tiedostoja, joiden tiedostotyyppi on samankaltainen</translation>
<translation id="7862185352068345852">Poistutaanko sivustolta?</translation>
<translation id="7865448901209910068">Paras nopeus</translation>
<translation id="7874263914261512992">Lisäsit juuri salasanasi petolliselle sivustolle. Chrome suosittelee tarkistamaan näihin tallentamasi salasanat: <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ja muut sivustot, joilla salasana on käytössä tällä hetkellä.</translation>
<translation id="7878562273885520351">Salasanasi on saattanut vaarantua.</translation>
+<translation id="7880146494886811634">Tallenna osoite</translation>
<translation id="7882421473871500483">Ruskea</translation>
<translation id="7887683347370398519">Tarkista CVC ja yritä uudelleen.</translation>
<translation id="7887885240995164102">Avaa kuva kuvassa</translation>
@@ -1822,6 +1871,7 @@ Lisätietoja:
<translation id="7894280532028510793">Jos kirjoitusasu on oikein, <ph name="BEGIN_LINK" />kokeile verkon diagnostiikkaa<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (kirjekuori)</translation>
<translation id="7931318309563332511">Tuntematon</translation>
+<translation id="793209273132572360">Päivitetäänkö osoite?</translation>
<translation id="7932579305932748336">Päällystys</translation>
<translation id="79338296614623784">Anna kelvollinen puhelinnumero.</translation>
<translation id="7934052535022478634">Maksu valmis</translation>
@@ -1892,6 +1942,7 @@ Lisätietoja:
<translation id="8175796834047840627">Chrome tarjoaa korttien tallentamista Google-tilillesi, koska olet kirjautuneena sisään. Voit muuttaa tätä koska tahansa asetuksista.</translation>
<translation id="8176440868214972690">Laitteen järjestelmänvalvoja on lähettänyt seuraaville verkkosivustoille joitakin tietoja, esim. asetuksia tai käytäntöjä.</translation>
<translation id="8184538546369750125">Käytä yleistä oletusasetusta (salli)</translation>
+<translation id="8193086767630290324">Luottamukselliseen dataan liittyvät tapahtumat</translation>
<translation id="8194797478851900357">K&amp;umoa siirto</translation>
<translation id="8201077131113104583">Laajennuksella, jonka tunnus on <ph name="EXTENSION_ID" />, on virheellinen päivitys-URL-osoite.</translation>
<translation id="8202097416529803614">Tilauksen yhteenveto</translation>
@@ -1914,6 +1965,7 @@ Lisätietoja:
<translation id="8249296373107784235">Keskeytä</translation>
<translation id="8249320324621329438">Viimeksi haettu:</translation>
<translation id="8253091569723639551">Laskutusosoite tarvitaan</translation>
+<translation id="8257387598443225809">Tämä sovellus on suunniteltu mobiililaitteille</translation>
<translation id="825929999321470778">Näytä kaikki tallennetut salasanat</translation>
<translation id="8261506727792406068">Poista</translation>
<translation id="8262952874573525464">Reunasidonta alareunassa</translation>
@@ -2038,7 +2090,6 @@ Lisätietoja:
<translation id="8719528812645237045">Useita reikiä yläreunassa</translation>
<translation id="8725066075913043281">Yritä uudelleen</translation>
<translation id="8726549941689275341">Sivun koko:</translation>
-<translation id="8728672262656704056">Olet muuttunut näkymättömäksi</translation>
<translation id="8730621377337864115">Valmis</translation>
<translation id="8731544501227493793">Ylläpidä salasanoja ‑painike, katso ja ylläpidä salasanoja Chromen asetuksissa painamalla Enter</translation>
<translation id="8734529307927223492"><ph name="MANAGER" /> ylläpitää laitetta (<ph name="DEVICE_TYPE" />)</translation>
@@ -2115,6 +2166,7 @@ Lisätietoja:
<translation id="9020542370529661692">Sivu on käännetty kielelle <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Virheellinen)</translation>
+<translation id="9030265603405983977">Yksivärinen</translation>
<translation id="9035022520814077154">Suojausvirhe</translation>
<translation id="9038649477754266430">Käytä ennakointipalvelua nopeampaan sivujen lataamiseen</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>
@@ -2138,6 +2190,7 @@ Lisätietoja:
<translation id="91108059142052966">Järjestelmänvalvojakäytäntö poistaa näytön jakamisen (<ph name="APPLICATION_TITLE" />) käytöstä, kun näkyvissä on luottamuksellista sisältöä</translation>
<translation id="9114524666733003316">Vahvistetaan korttia…</translation>
<translation id="9114581008513152754">Yritys tai muu organisaatio ei ylläpidä selainta. Laitteen toimintaa saatetaan ylläpitää Chromen ulkopuolelta. <ph name="BEGIN_LINK" />Lue lisää<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Tuore</translation>
<translation id="9119042192571987207">Lähetetty</translation>
<translation id="9128016270925453879">Käytännöt on ladattu</translation>
<translation id="9128870381267983090">Yhdistä verkkoon</translation>
@@ -2156,6 +2209,7 @@ Lisätietoja:
<translation id="9170848237812810038">K&amp;umoa</translation>
<translation id="9171296965991013597">Poistutaanko sovelluksesta?</translation>
<translation id="9173282814238175921">Yksittäinen dokumentti / Uusi sivu</translation>
+<translation id="9173995187295789444">Haetaan Bluetooth-laitteita…</translation>
<translation id="917450738466192189">Palvelimen varmenne ei kelpaa.</translation>
<translation id="9174917557437862841">Välilehden vaihtopainike, paina Enter siirtyäksesi tälle välilehdelle</translation>
<translation id="9179703756951298733">Muuta maksu- ja credit-korttitietojasi Chromen asetuksissa</translation>
diff --git a/chromium/components/strings/components_strings_fil.xtb b/chromium/components/strings/components_strings_fil.xtb
index bf88c592d48..2b4e210bd48 100644
--- a/chromium/components/strings/components_strings_fil.xtb
+++ b/chromium/components/strings/components_strings_fil.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Pumili ng pahintulot para sa <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;I-undo ang pagbabago sa ayos</translation>
+<translation id="1123753900084781868">Hindi available sa ngayon ang Instant Caption</translation>
<translation id="1125573121925420732">Maaaring karaniwang may mga babala habang nag-a-update para sa seguridad ang mga website. Maaayos din ito sa lalong madaling panahon.</translation>
<translation id="112840717907525620">OK ang cache ng patakaran</translation>
<translation id="1130564665089811311">Button na Isalin ang page, pindutin ang Enter para isalin ang page na ito gamit ang Google Translate</translation>
@@ -74,6 +75,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="1240347957665416060">Ang pangalan ng iyong device</translation>
<translation id="124116460088058876">Higit pang wika</translation>
<translation id="1243027604378859286">May-akda:</translation>
+<translation id="1246424317317450637">Bold</translation>
<translation id="1250759482327835220">Para mas mabilis na makapagbayad sa susunod, i-save ang iyong card, pangalan, at billing address sa Google Account mo.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (naka-sync)</translation>
<translation id="1256368399071562588">&lt;p&gt;Kung sinubukan mong bisitahin ang isang website at hindi ito bumukas, subukan munang ayusin ang error gamit ang mga hakbang sa pag-troubleshoot na ito:&lt;/p&gt;
@@ -156,6 +158,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="1476595624592550506">Palitan ang iyong password</translation>
<translation id="1484290072879560759">Pumili ng Address sa Pagpapadala</translation>
<translation id="1492194039220927094">Pag-push ng mga patakaran:</translation>
+<translation id="1495677929897281669">Bumalik sa tab</translation>
<translation id="1501859676467574491">Ipakita ang mga card mula sa iyong Google Account</translation>
<translation id="1507202001669085618">&lt;p&gt;Makikita mo ang error na ito kung gumagamit ka ng Wi-Fi portal kung saan kailangan mong mag-sign in bago ka makapag-online.&lt;/p&gt;
&lt;p&gt;Para maayos ang error, i-click ang &lt;strong&gt;Kumonekta&lt;/strong&gt; sa page na sinusubukan mong buksan.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="1532118530259321453">Isinasaad ng page na ito na</translation>
<translation id="153384715582417236">'Yan na muna sa ngayon</translation>
<translation id="1536390784834419204">Isalin ang page</translation>
+<translation id="1539840569003678498">Naipadala ang ulat:</translation>
<translation id="154408704832528245">Pumili ng Address sa Paghahatid</translation>
<translation id="1549470594296187301">Dapat naka-enable ang JavaScript upang magamit ang feature na ito.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="1682696192498422849">Short edge muna</translation>
<translation id="168693727862418163">Hindi na-validate ang value ng patakarang ito sa schema nito at babalewalain ito.</translation>
<translation id="168841957122794586">Naglalaman ang server certificate ng isang mahinang cryptographic key.</translation>
+<translation id="1696290444144917273">Tingnan ang mga detalye ng virtual na card.</translation>
<translation id="1697532407822776718">Handa ka na!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Hindi mapatunayan ng server na ito na ito ang <ph name="DOMAIN" />; tinatayang mula sa susunod na araw ang certificate ng seguridad nito. Maaaring resulta ito ng maling configuration o kaya ng isang attacker na humahadlang sa iyong koneksyon.}one{Hindi mapatunayan ng server na ito na ito ang <ph name="DOMAIN" />; tinatayang mula sa # araw sa hinaharap ang certificate ng seguridad nito. Maaaring resulta ito ng maling configuration o kaya ng isang attacker na humahadlang sa iyong koneksyon.}other{Hindi mapatunayan ng server na ito na ito ang <ph name="DOMAIN" />; tinatayang mula sa # na araw sa hinaharap ang certificate ng seguridad nito. Maaaring resulta ito ng maling configuration o kaya ng isang attacker na humahadlang sa iyong koneksyon.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Binalewala dahil hindi nakatakda ang <ph name="POLICY_NAME" /> sa <ph name="VALUE" />.</translation>
<translation id="1712552549805331520">Gusto ng <ph name="URL" /> na permanenteng mag-store ng data sa iyong lokal na computer</translation>
<translation id="1713628304598226412">Tray 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Mailbox 3</translation>
<translation id="1718029547804390981">Masyadong malaki para i-annotate ang dokumento</translation>
<translation id="1721424275792716183">Kinakailangan ang field na may *</translation>
+<translation id="1727613060316725209">Valid ang certificate na ito</translation>
<translation id="1727741090716970331">Magdagdag ng Wastong Numero ng Card</translation>
<translation id="1728677426644403582">Pinagmulan ng isang web page ang tinitingnan mo</translation>
<translation id="173080396488393970">Hindi sinusuportahan ang uri ng card na ito</translation>
@@ -246,7 +253,6 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
ang iyong kahilingan para sa <ph name="SITE" />. Magagamit ng mga operator ng site ang mga patakaran ng
pinagmulan para i-configure ang seguridad at iba pang property para sa isang site.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Mangyaring i-update ang iyong passphrase ng pag-sync.</translation>
<translation id="1787142507584202372">Lalabas dito ang iyong mga bukas na tab</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, maraming available na pagkilos, pindutin ang Tab para makita ang mga ito</translation>
@@ -279,6 +285,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="1919345977826869612">Mga Ad</translation>
<translation id="1919367280705858090">Humingi ng tulong sa partikular na mensahe ng error</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Wala}=1{1 site}one{# site}other{# na site}}</translation>
+<translation id="1924727005275031552">Bago</translation>
<translation id="1945968466830820669">Maaari kang mawalan ng access sa account ng iyong organisasyon o manakawan ng pagkakakilanlan. Inirerekomenda ng Chromium na palitan ang iyong password ngayon.</translation>
<translation id="1947454675006758438">Staple top right</translation>
<translation id="1958218078413065209">Ang iyong pinakamataas na score ay <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="2042213636306070719">Tray 7</translation>
<translation id="204357726431741734">Mag-sign in para magamit ang mga naka-save na password sa iyong Google Account</translation>
<translation id="2053111141626950936">Hindi ita-translate ang mga page na nasa <ph name="LANGUAGE" />.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Kapag naka-on ang kontrol na ito at aktibo ang status, tinutukoy ng Chrome kung aling malaking grupo ng mga tao, o "cohort," ang pinakakatulad ng iyong kamakailang aktibidad sa pag-browse. Makakapili ang mga advertiser ng mga ad para sa grupo at pinapanatiling pribado sa iyong device ang aktibidad mo sa pag-browse. Ina-update ang iyong grupo araw-araw.}=1{Kapag naka-on ang kontrol na ito at aktibo ang status, tinutukoy ng Chrome kung aling malaking grupo ng mga tao, o "cohort," ang pinakakatulad ng iyong kamakailang aktibidad sa pag-browse. Makakapili ang mga advertiser ng mga ad para sa grupo at pinapanatiling pribado sa iyong device ang aktibidad mo sa pag-browse. Ina-update ang iyong grupo araw-araw.}one{Kapag naka-on ang kontrol na ito at aktibo ang status, tinutukoy ng Chrome kung aling malaking grupo ng mga tao, o "cohort," ang pinakakatulad ng iyong kamakailang aktibidad sa pag-browse. Makakapili ang mga advertiser ng mga ad para sa grupo at pinapanatiling pribado sa iyong device ang aktibidad mo sa pag-browse. Ina-update ang iyong grupo kada {NUM_DAYS} araw.}other{Kapag naka-on ang kontrol na ito at aktibo ang status, tinutukoy ng Chrome kung aling malaking grupo ng mga tao, o "cohort," ang pinakakatulad ng iyong kamakailang aktibidad sa pag-browse. Makakapili ang mga advertiser ng mga ad para sa grupo at pinapanatiling pribado sa iyong device ang aktibidad mo sa pag-browse. Ina-update ang iyong grupo kada {NUM_DAYS} na araw.}}</translation>
<translation id="2053553514270667976">ZIP code</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suhestyon}one{# suhestyon}other{# na suhestyon}}</translation>
<translation id="2071692954027939183">Awtomatikong na-block ang mga notification dahil karaniwang hindi mo pinapayagan ang mga ito</translation>
<translation id="2079545284768500474">I-undo</translation>
<translation id="20817612488360358">Itinatakda ang mga setting ng proxy ng system upang magamit ngunit tinutukoy rin ang isang tahasang configuration ng proxy.</translation>
<translation id="2082238445998314030">Resulta <ph name="RESULT_NUMBER" /> sa <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">I-save…</translation>
<translation id="2088086323192747268">Button na Pamahalaan ang pag-sync, pindutin ang Enter para pamahalaan kung anong impormasyon ang isi-sync mo sa mga setting ng Chrome</translation>
<translation id="2091887806945687916">Tunog</translation>
<translation id="2094505752054353250">Maling pagtutugma sa domain</translation>
@@ -379,6 +388,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="2317259163369394535">Kailangan ng <ph name="DOMAIN" /> ng username at password.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, mag-e-expire sa <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Kinokontrol ng iyong administrator ang setting</translation>
+<translation id="2340263603246777781">Gustong makipagpares ng <ph name="ORIGIN" /></translation>
<translation id="2344028582131185878">Mga Awtomatikong Pagda-download</translation>
<translation id="2346319942568447007">Larawang kinopya mo</translation>
<translation id="2354001756790975382">Iba pang mga bookmark</translation>
@@ -386,8 +396,10 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="2355395290879513365">Maaaring makita ng mga umaatake ang mga larawang tinitingnan mo sa site na ito at lilinlangin ka sa pamamagitan ng pagbago sa mga ito.</translation>
<translation id="2356070529366658676">Magtanong</translation>
<translation id="2357481397660644965">Pinapamahalaan ng <ph name="DEVICE_MANAGER" /> ang iyong device at pinapamahalaan ng <ph name="ACCOUNT_MANAGER" /> ang account mo.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Wala pang isang araw}=1{Sa loob ng isang araw}one{Sa loob ng {NUM_DAYS} araw}other{Sa loob ng {NUM_DAYS} na araw}}</translation>
<translation id="2359629602545592467">Marami</translation>
<translation id="2359808026110333948">Magpatuloy</translation>
+<translation id="2359961752320758691">Inilapat ang numero ng iyong virtual card.</translation>
<translation id="2367567093518048410">Antas</translation>
<translation id="2372464001869762664">Pagkatapos mong magkumpirma, ibabahagi sa site na ito ang mga detalye ng card mula sa iyong Google Account. Hanapin ang CVC sa mga detalye ng iyong Plex Account.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="239429038616798445">Hindi available ang paraan ng pagpapadala na ito. Sumubok ng ibang paraan.</translation>
<translation id="2396249848217231973">&amp;I-undo ang pagtanggal</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Luma</translation>
<translation id="2413528052993050574">Hindi mapatunayan ng server na ito na ito ay <ph name="DOMAIN" />; maaaring binawi ang certificate ng seguridad nito. Maaaring dulot ito ng maling configuration o isang umaatake na hinahadlangan ang iyong koneksyon.</translation>
<translation id="2414886740292270097">Madilim</translation>
<translation id="2438874542388153331">Quad punch right</translation>
@@ -425,10 +438,10 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="2521385132275182522">Staple bottom right</translation>
<translation id="2523886232349826891">Ise-save sa device lang na ito</translation>
<translation id="2524461107774643265">Magdagdag ng Higit Pang Impormasyon</translation>
-<translation id="2526590354069164005">Desktop</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{at 1 pa}one{at # pa}other{at # pa}}</translation>
<translation id="2536110899380797252">Magdagdag ng Address</translation>
<translation id="2539524384386349900">Tukuyin</translation>
+<translation id="2541219929084442027">Hindi mananatili ang mga page na titingnan mo sa mga tab na Incognito sa history, cookie store o history ng paghahanap ng iyong browser pagkatapos mong isara ang lahat ng iyong tab na incognito. Papanatilihin ang anumang file na ida-download o mga bookmark na gagawin mo.</translation>
<translation id="2544644783021658368">Isang dokumento</translation>
<translation id="254947805923345898">Di-wasto ang value ng patakaran.</translation>
<translation id="255002559098805027">Nagpadala ng di-wastong tugon ang <ph name="HOST_NAME" />.</translation>
@@ -448,6 +461,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="2629325967560697240">Para makuha ang pinakamataas na antas ng seguridad ng Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />i-on ang pinahusay na proteksyon<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Hindi makita ang IP address ng server ng <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Katayuan:</translation>
+<translation id="264810637653812429">Walang nahanap na tugmang device.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, pindutin ang Tab at pagkatapos ay ang Enter para I-clear ang iyong history ng pag-browse, cookies, cache, at higit pa sa mga setting ng Chrome</translation>
<translation id="2650446666397867134">Tinanggihan ang access sa file</translation>
@@ -494,6 +508,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<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="2807052079800581569">Posisyon ng larawan Y</translation>
+<translation id="2820957248982571256">Nagsa-scan...</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>
@@ -501,6 +516,8 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">Nagpapakita ang site na ito ng mga nakakasagabal o nakakapanlinlang na ad.</translation>
+<translation id="287596039013813457">Friendly</translation>
+<translation id="2876489322757410363">Aalis sa Incognito mode upang magbayad sa pamamagitan ng external na application. Magpatuloy?</translation>
<translation id="2878197950673342043">Poster fold</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Placement ng window</translation>
@@ -550,7 +567,6 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, pindutin ang Tab pagkatapos ay pindutin ang Enter para magpatakbo ng Pag-check sa Kaligtasan sa mga setting ng Chrome</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>
<translation id="306573536155379004">Nagsimula na ang laro.</translation>
<translation id="3080254622891793721">Graphic</translation>
<translation id="3086579638707268289">Sinusubaybayan ang iyong aktibidad sa web</translation>
@@ -573,7 +589,6 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="315504272643575312">Pinapamahalaan ng <ph name="MANAGER" /> ang iyong account.</translation>
<translation id="3157931365184549694">Ipanumbalik</translation>
<translation id="3162559335345991374">Maaaring hilingin ng Wi-Fi na ginagamit mo na bisitahin mo ang page nito sa pag-login.</translation>
-<translation id="3167968892399408617">Ang mga page na titingnan mo sa mga tab na incognito ay hindi mananatili sa history, cookie store o history ng paghahanap ng iyong browser kapag naisara mo na ang lahat ng iyong tab na incognito. Papanatilihin ang anumang mga file na ida-download mo o mga bookmark na gagawin mo.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Island</translation>
<translation id="3176929007561373547">Tingnan ang mga setting ng iyong proxy o makipag-ugnayan sa iyong network
@@ -599,10 +614,12 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<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="3249845759089040423">Groovy</translation>
<translation id="3252266817569339921">Pranses</translation>
<translation id="3266793032086590337">Value (hindi tumutugma)</translation>
<translation id="3268451620468152448">Mga Bukas na Tab</translation>
<translation id="3270847123878663523">&amp;I-undo ang Pagbabago sa Ayos</translation>
+<translation id="3271648667212143903">Gustong kumonekta ng <ph name="ORIGIN" /></translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Nagpadala ang iyong organisasyon, ang <ph name="ENROLLMENT_DOMAIN" />, ng ilang impormasyon sa mga sumusunod na website, tulad ng mga setting o patakaran.</translation>
<translation id="3282497668470633863">Magdagdag ng pangalan sa card</translation>
@@ -655,6 +672,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="3428151540071562330">Invalid at hindi gagamitin ang isa o higit pa sa mga URI ng template ng server ng DnsOverHttpsTemplates.</translation>
<translation id="3431636764301398940">I-save ang card na ito sa device na ito</translation>
<translation id="3432601291244612633">Isara ang page</translation>
+<translation id="3435738964857648380">Seguridad</translation>
<translation id="3435896845095436175">I-enable</translation>
<translation id="3438829137925142401">Gamitin ang mga naka-save na password sa iyong Google Account</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="3584299510153766161">Dual punch bottom</translation>
<translation id="3586931643579894722">Magtago ng mga detalye</translation>
<translation id="3587738293690942763">Gitna</translation>
+<translation id="3590643883886679995">Iso-store ang data ng pag-sign in sa device na ito pagkatapos mong lumabas sa Incognito mode.</translation>
+<translation id="359126217934908072">Buwan/Taon:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Puwede mong i-reset ang iyong grupo anumang oras. Inaabot nang humigit-kumulang isang araw para makasali sa isang bagong grupo.}=1{Puwede mong i-reset ang iyong grupo anumang oras. Inaabot nang humigit-kumulang isang araw para makasali sa isang bagong grupo.}one{Puwede mong i-reset ang iyong grupo anumang oras. Inaabot nang {NUM_DAYS} araw para makasali sa isang bagong grupo.}other{Puwede mong i-reset ang iyong grupo anumang oras. Inaabot nang {NUM_DAYS} na araw para makasali sa isang bagong grupo.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Na-block ng iyong administrator ang application</translation>
<translation id="3608932978122581043">Oryentasyon ng feed</translation>
@@ -706,13 +727,13 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="3615877443314183785">Maglagay ng wastong petsa ng pag-expire</translation>
<translation id="36224234498066874">I-clear ang Data sa Pag-browse...</translation>
<translation id="362276910939193118">Ipakita ang Buong History</translation>
-<translation id="3625635938337243871">Iso-store ang data sa pag-sign in sa device na ito pagkatapos mong lumabas sa incognito mode.</translation>
<translation id="3630155396527302611">Kung nakalista na ito bilang isang programang pinapahintulutang i-access ang network, subukang
alisin ito mula sa listahan at muli itong idagdag.</translation>
<translation id="3630699740441428070">Na-configure ng mga administrator ng device na ito ang koneksyon ng network mo, na posibleng magbigay-daan sa kanilang tingnan ang iyong trapiko sa network, kabilang ang kung aling mga website ang binibisita mo.</translation>
<translation id="3631244953324577188">Biometrics</translation>
<translation id="3633738897356909127">Button na I-update ang Chrome, pindutin ang Enter para i-update ang Chrome mula sa iyong mga setting ng Chrome</translation>
<translation id="3634530185120165534">Tray 5</translation>
+<translation id="3637662659967048211">I-save sa Google Account</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Application:</translation>
<translation id="3650584904733503804">Matagumpay ang pagpapatunay</translation>
@@ -753,6 +774,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="3781428340399460090">Hot Pink</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Mga device ng bluetooth</translation>
+<translation id="3787675388804467730">Virtual na numero ng card</translation>
<translation id="3787705759683870569">Mag-e-expire sa <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Laki 16</translation>
<translation id="3789841737615482174">Mag-install</translation>
@@ -772,6 +794,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="3841184659773414994">Mga Tagapangasiwa ng File</translation>
<translation id="385051799172605136">Bumalik</translation>
<translation id="3858027520442213535">I-update ang petsa at oras</translation>
+<translation id="3881478300875776315">Magpakita ng mas kaunting linya</translation>
<translation id="3884278016824448484">Sumasalungat na tagatukoy ng device</translation>
<translation id="3885155851504623709">Parish</translation>
<translation id="388632593194507180">May Na-detect na Pagsubaybay</translation>
@@ -797,6 +820,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="397105322502079400">Kinakalkula...</translation>
<translation id="3973234410852337861">Naka-block ang <ph name="HOST_NAME" /></translation>
<translation id="3973357910713125165">Pindutin ang button ng Pag-check sa Kaligtasan sa Chrome, pindutin ang Enter para magpatakbo ng Pag-check sa Kaligtasan sa Chrome sa mga setting ng Chrome</translation>
+<translation id="3986705137476756801">I-off muna sa ngayon ang Instant Caption</translation>
<translation id="3987405730340719549">Natukoy ng Chrome na posibleng peke o mapanloko ang site na ito.
Kung naniniwala kang mali ang pagpapakita nito, pakibisita ang https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="4275830172053184480">I-restart ang iyong device</translation>
<translation id="4277028893293644418">I-reset ang password</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="4287885627794386150">Kwalipikado para sa trial pero hindi aktibo</translation>
<translation id="4297502707443874121">Thumbnail para sa page <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Palawakin</translation>
<translation id="4300675098767811073">Multiple punch right</translation>
<translation id="4302514097724775343">I-tap ang dino para maglaro</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Hindi ma-access ang iyong file</translation>
-<translation id="4305817255990598646">Lumipat</translation>
+<translation id="4306529830550717874">I-save ang address?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">I-block (default)</translation>
<translation id="4314815835985389558">Pamahalaan ang pag-sync</translation>
@@ -926,6 +951,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="4377125064752653719">Tinangka mong maabot ang <ph name="DOMAIN" />, subalit ang certificate na ipinakita ng server ay binawi ng nagbigay nito. Nangangahulugan ito na ang mga kredensyal sa seguridad na ipinakita ng server ay talagang hindi dapat pagkatiwalaan. Maaaring nakikipag-ugnay ka sa isang nang-aatake.</translation>
<translation id="4378154925671717803">Telepono</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Instant Caption</translation>
<translation id="4406896451731180161">mga resulta ng paghahanap</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Kakalagay mo lang ng iyong password sa isang mapanlinang na site. Inirerekomenda ng Chrome na pumunta sa <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />, at iba pang site kung saan mo ginagamit ang password na ito at baguhin ito ngayon.</translation>
@@ -938,7 +964,6 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<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="4464826014807964867">Mga website na may impormasyon mula sa iyong organisasyon</translation>
-<translation id="4466881336512663640">Mawawala ang mga pagbabago sa form. Sigurado ka bang gusto mong magpatuloy?</translation>
<translation id="4476953670630786061">Hindi secure ang form na ito. Na-off ang autofill.</translation>
<translation id="4477350412780666475">Susunod na Track</translation>
<translation id="4482953324121162758">Hindi ita-translate ang site na ito.</translation>
@@ -972,6 +997,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="4594403342090139922">&amp;I-undo ang Pagtanggal</translation>
<translation id="4597348597567598915">Laki 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Nakakamangha</translation>
<translation id="4628948037717959914">Larawan</translation>
<translation id="4631649115723685955">May naka-link na cashback</translation>
<translation id="4636930964841734540">Impormasyon</translation>
@@ -991,6 +1017,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Gilid</translation>
+<translation id="4702656508969495934">Nakikita ang Instant Caption, gamitin ang tagalipat ng window para tumuon</translation>
<translation id="4708268264240856090">Naputol ang iyong koneksyon</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Magpatakbo ng Windows Network Diagnostics<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="4738601419177586157">Suhestyon sa paghahanap para sa <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Pamahalaan ang mga password...</translation>
<translation id="4744603770635761495">Naipapatupad na Path</translation>
+<translation id="4749011317274908093">Napunta ka sa Incognito</translation>
<translation id="4750917950439032686">Pribado ang iyong impormasyon (halimbawa, mga password o credit card number) kapag ipinadala ito sa site na ito.</translation>
<translation id="4756388243121344051">&amp;History</translation>
<translation id="4758311279753947758">Magdagdag ng impormasyon sa pakikipag-ugnayan</translation>
@@ -1033,6 +1061,8 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="4813512666221746211">Error sa network</translation>
<translation id="4816492930507672669">Pagkasyahin sa pahina</translation>
<translation id="4819347708020428563">I-edit ang mga anotasyon sa default na view?</translation>
+<translation id="4825507807291741242">Mahusay</translation>
+<translation id="4838327282952368871">Dreamy</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">View</translation>
<translation id="485316830061041779">German</translation>
@@ -1169,6 +1199,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="5314967030527622926">Booklet maker</translation>
<translation id="5316812925700871227">I-rotate pakaliwa</translation>
<translation id="5317780077021120954">I-save</translation>
+<translation id="5321288445143113935">Na-maximize</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> ng <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Pumili ng Impormasyon sa Pakikipag-ugnayan</translation>
<translation id="5327248766486351172">Pangalan</translation>
@@ -1176,11 +1207,13 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="5332219387342487447">Paraan ng Pagpapadala</translation>
<translation id="5333022057423422993">Nakita ng Chrome sa isang paglabag sa data ang password na kakagamit mo lang. Para i-secure ang iyong mga account, inirerekomenda naming suriin ang mga naka-save na password mo.</translation>
<translation id="5334013548165032829">Mga detalyadong log ng system</translation>
+<translation id="5334145288572353250">I-save ang Address?</translation>
<translation id="5340250774223869109">Naka-block ang application</translation>
<translation id="534295439873310000">Mga NFC device</translation>
<translation id="5344579389779391559">Maaari kang singilin ng pera ng page na ito</translation>
<translation id="5355557959165512791">Hindi mo maaaring bisitahin ang <ph name="SITE" /> sa ngayon dahil binawi na ang certificate nito. 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="536296301121032821">Nabigo i-load ang mga setting ng patakaran sa store</translation>
+<translation id="5363309033720083897">Serial port na pinapayagan ng iyong administrator</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="5386426401304769735">Naglalaman ang chain ng certificate para sa site na ito ng certificate na naka-sign gamit ang SHA-1.</translation>
@@ -1189,6 +1222,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="5398772614898833570">Na-block ang mga ad</translation>
<translation id="5400836586163650660">Grey</translation>
<translation id="540969355065856584">Hindi mapatunayan ng server na ito ay ang <ph name="DOMAIN" />; walang bisa ang certificate sa seguridad nito sa pagkakataong ito. Maaaring dahil ito sa isang maling pag-configure o may isang attacker na humahadlang sa iyong koneksyon.</translation>
+<translation id="541143247543991491">Cloud (buong system)</translation>
<translation id="541416427766103491">Stacker 4</translation>
<translation id="5421136146218899937">I-clear ang data sa pag-browse...</translation>
<translation id="5426179911063097041">Gusto ng <ph name="SITE" /> na padalhan ka ng mga notification</translation>
@@ -1202,6 +1236,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="5455374756549232013">Maling timestamp ng patakaran</translation>
<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="5463625433003343978">Naghahanap ng mga device...</translation>
<translation id="5469868506864199649">Italyano</translation>
<translation id="5470861586879999274">&amp;Gawing muli ang pag-e-edit</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1251,7 +1286,6 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="5624120631404540903">Pamahalaan ang mga password</translation>
<translation id="5629630648637658800">Nabigong i-load ang mga setting ng patakaran</translation>
<translation id="5631439013527180824">Di-wastong token sa pamamahala ng device</translation>
-<translation id="5632627355679805402">Na-encrypt ang data mo gamit ang iyong <ph name="BEGIN_LINK" />password sa Google<ph name="END_LINK" /> simula noong <ph name="TIME" />. Ilagay ito para simulan ang pag-sync.</translation>
<translation id="5633066919399395251">Maaaring magtangka ang mga attacker na kasalukuyang nasa <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> na mag-install ng mga mapanganib na program sa iyong computer na magnanakaw o magde-delete ng impormasyon mo (halimbawa, mga larawan, password, mensahe, at credit card). <ph name="BEGIN_LEARN_MORE_LINK" />Matuto pa<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Na-block ang mapanlinlang na content.</translation>
<translation id="5644090287519800334">Pag-shift ng gilid 1 larawan X</translation>
@@ -1290,12 +1324,12 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="5785756445106461925">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 hitsura ng page.</translation>
<translation id="5786044859038896871">Gusto mo bang ilagay ang impormasyon ng iyong card?</translation>
<translation id="578633867165174378">Nakita ng Chrome sa isang paglabag sa data ang password na kakagamit mo lang. Inirerekomenda naming palitan na ngayon ang password na ito.</translation>
-<translation id="5798290721819630480">I-discard ang mga pagbabago?</translation>
<translation id="5803412860119678065">Gusto mo bang ilagay ang iyong <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Mga Pahintulot</translation>
<translation id="5804427196348435412">Gumamit ng mga NFC device</translation>
<translation id="5810442152076338065">Naka-encrypt ang iyong koneksyon sa <ph name="DOMAIN" /> gamit ang isang hindi na ginagamit na cipher suite.</translation>
<translation id="5813119285467412249">&amp;Gawing Muli ang Pagdagdag</translation>
+<translation id="5817918615728894473">Ipares</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Sisingilin ang card na ito kapag nagbayad ka, pero hindi ibabahagi sa site na ito ang totoong numero nito. Para sa karagdagang seguridad, bubuo ng pansamantalang CVC.}one{Sisingilin ang card na iyong pipiliin kapag nagbayad ka, pero hindi ibabahagi sa site na ito ang totoong numero nito. Para sa karagdagang seguridad, bubuo ng pansamantalang CVC.}other{Sisingilin ang card na iyong pipiliin kapag nagbayad ka, pero hindi ibabahagi sa site na ito ang totoong numero nito. Para sa karagdagang seguridad, bubuo ng pansamantalang CVC.}}</translation>
<translation id="5826507051599432481">Common Name (CN)</translation>
<translation id="5838278095973806738">Hindi ka dapat maglagay ng anumang sensitibong impormasyon sa site na ito (halimbawa, mga password o credit card), dahil maaari itong nakawin ng mga umaatake.</translation>
@@ -1303,6 +1337,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="5855253129151731373">Mukhang katulad ng <ph name="LOOKALIKE_DOMAIN" /> ang hostname ng site na ito. Kung minsan, ginagaya ng mga attacker ang mga site sa pamamagitan ng paggawa ng mga maliit at mahirap makitang pagbabago sa domain name.
Kung naniniwala kang mali ang pagpapakita nito, pakibisita ang https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Naka-off</translation>
<translation id="5862579898803147654">Stacker 8</translation>
<translation id="5863847714970149516">Maaari kang singilin sa susunod na page</translation>
<translation id="5866257070973731571">Magdagdag ng Numero ng Telepono</translation>
@@ -1319,6 +1354,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="5913377024445952699">Na-pause ang screen capture</translation>
<translation id="59174027418879706">Pinagana</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 ang ginagamit}one{# ang ginagamit}other{# ang ginagamit}}</translation>
<translation id="5921185718311485855">Naka-on</translation>
<translation id="5921639886840618607">I-save ang card sa Google Account?</translation>
<translation id="5922853866070715753">Malapit nang matapos</translation>
@@ -1338,6 +1374,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="5989320800837274978">Hindi tunukoy ang alinman sa mga hindi nababagong proxy server o isang .pac script URL.</translation>
<translation id="5992691462791905444">Engineering Z-fold</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> (na) resulta para sa '<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">Classic</translation>
<translation id="6008122969617370890">N-to-1 na pagkakasunod-sunod</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Suriin ang iyong mga password</translation>
@@ -1359,6 +1396,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="6045164183059402045">Template ng imposition</translation>
<translation id="6047233362582046994">Kung nauunawaan mo ang mga panganib sa iyong seguridad, maaari mong <ph name="BEGIN_LINK" />bisitahin ang site na ito<ph name="END_LINK" /> bago maalis ang mga mapaminsalang app.</translation>
<translation id="6047927260846328439">Maaaring subukan ng content na ito na linlangin kang mag-install ng software o maghayag ng personal na impormasyon. <ph name="BEGIN_LINK" />Ipakita pa rin<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">I-press nang matagal ang |<ph name="ACCELERATOR" />| upang lumabas sa full screen</translation>
<translation id="6049488691372270142">Paghahatid ng page</translation>
<translation id="6051221802930200923">Hindi mo maaaring bisitahin ang <ph name="SITE" /> sa ngayon dahil gumagamit ng pag-pin ng certificate 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="6051898664905071243">Bilang ng page:</translation>
@@ -1375,6 +1413,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<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>
<translation id="6116338172782435947">Tingnan ang text at mga larawang kinopya sa clipboard</translation>
<translation id="6120179357481664955">Natatandaan mo ang iyong UPI ID?</translation>
+<translation id="6123290840358279103">Tingnan ang virtual card</translation>
<translation id="6124432979022149706">Mga Chrome Enterprise Connector</translation>
<translation id="6146055958333702838">Tingnan ang anumang mga kable at i-reboot ang anumang mga router, modem o iba
pang mga network device na maaaring ginagamit mo.</translation>
@@ -1411,6 +1450,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="6289939620939689042">Kulay ng Page</translation>
<translation id="6290238015253830360">Lalabas dito ang mga iminungkahi mong artikulo</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Ihinihinto ang Google Assistant sa Chrome</translation>
<translation id="6305205051461490394">Hindi makakonekta sa <ph name="URL" />.</translation>
<translation id="6312113039770857350">Hindi available ang webpage</translation>
@@ -1436,6 +1476,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="6390200185239044127">Z-fold half</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Na-block ng patakaran ng administrator ang pag-paste sa lokasyong ito mula sa <ph name="ORIGIN_NAME" /></translation>
+<translation id="6398765197997659313">Lumabas sa buong screen</translation>
<translation id="6401136357288658127">Hindi na ginagamit ang patakarang ito. Dapat mong gamitin ang patakarang <ph name="NEW_POLICY" /> sa halip.</translation>
<translation id="6404511346730675251">I-edit ang bookmark</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1448,7 +1489,6 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="6428450836711225518">I-verify ang iyong numero ng telepono</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">I-discard</translation>
<translation id="6440503408713884761">Binalewala</translation>
<translation id="6443406338865242315">Aling mga extension at plugin ang na-install mo</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1491,6 +1531,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="6624427990725312378">Impormasyon ng Contact</translation>
<translation id="6626291197371920147">Magdagdag ng wastong card number</translation>
<translation id="6628463337424475685">Paghahanap ng <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Naghahanap ng mga USB device...</translation>
<translation id="6630809736994426279">Maaaring magtangka ang mga attacker na kasalukuyang nasa <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> na mag-install ng mga mapanganib na program sa iyong Mac na magnanakaw o magde-delete ng impormasyon mo (halimbawa, mga larawan, password, mensahe, at credit card). <ph name="BEGIN_LEARN_MORE_LINK" />Matuto pa<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">I-clear</translation>
@@ -1506,6 +1547,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<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="6687335167692595844">Hiniling na laki ng font</translation>
+<translation id="6688743156324860098">I-update…</translation>
<translation id="6689249931105087298">Kaugnay sa black point compression</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="6698381487523150993">Nalikha:</translation>
@@ -1521,6 +1563,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="6744009308914054259">Habang naghihintay ng koneksyon, maaari mong bisitahin ang Mga Download para magbasa ng mga offline na artikulo.</translation>
<translation id="6753269504797312559">Halaga ng patakaran</translation>
<translation id="6757797048963528358">Nag-sleep ang iyong device.</translation>
+<translation id="6767985426384634228">I-update ang Address?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violet</translation>
@@ -1543,6 +1586,7 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Pinasimple ng Chrome ang page na ito para mas madali itong mabasa. Nakuha ng Chrome ang orihinal na page sa pamamagitan ng hindi secure na koneksyon.</translation>
<translation id="6891596781022320156">Hindi sinusuportahan ang antas ng patakaran.</translation>
+<translation id="6895143722905299846">Virtual na numero:</translation>
<translation id="6895330447102777224">Nakumpirma na ang iyong card</translation>
<translation id="6897140037006041989">User Agent</translation>
<translation id="6898699227549475383">Samahan (O)</translation>
@@ -1578,10 +1622,10 @@ Kung ayaw mo, iba-block ito ng iyong mga setting ng privacy. Papayagan nito ang
<translation id="7004583254764674281">Gamitin ang Windows Hello para kumpirmahin nang mas mabilis ang mga card</translation>
<translation id="7006930604109697472">Ipadala pa rin</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Mga Setting ng Pag-resize</translation>
<translation id="7014741021609395734">Antas ng pag-zoom</translation>
<translation id="7016992613359344582">Ang mga singil na ito ay maaaring isang beses lang o umuulit at maaaring hindi mo mapansin.</translation>
<translation id="7029809446516969842">Mga Password</translation>
+<translation id="7030436163253143341">Hindi valid ang certificate</translation>
<translation id="7031646650991750659">Aling mga Google Play app ang na-install mo</translation>
<translation id="7050187094878475250">Sinubukan mong puntahan ang <ph name="DOMAIN" />, ngunit nagpakita ang server ng certificate na masyadong mahaba ang panahon ng pagkakaroon ng bisa upang maging mapagkakatiwalaan.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Hindi mase-save sa ngayon ang card na ito}one{Hindi mase-save sa ngayon ang mga card na ito}other{Hindi mase-save sa ngayon ang mga card na ito}}</translation>
@@ -1651,12 +1695,14 @@ Mga karagdagang detalye:
<translation id="7300012071106347854">Cobalt Blue</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Mataas</translation>
+<translation id="7305756307268530424">Simulan nang mas mabagal</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Tulong sa Koneksyon</translation>
<translation id="7323804146520582233">Itago ang seksyong "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Pag-override ng lokal na account ng device</translation>
<translation id="7333654844024768166">Kakalagay mo lang ng iyong password sa isang mapanlinang na site. Inirerekomenda ng Chromium na pumunta sa <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />, at iba pang site kung saan mo ginagamit ang password na ito at baguhin ito ngayon.</translation>
<translation id="7334320624316649418">&amp;Gawing muli ang pagbabago sa ayos</translation>
+<translation id="7337248890521463931">Magpakita ng mas marami pang linya</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>
@@ -1664,6 +1710,7 @@ Mga karagdagang detalye:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Command Line</translation>
<translation id="7359588939039777303">Na-block ang mga ad.</translation>
+<translation id="7363096869660964304">Gayunpaman, hindi ka invisible. Kahit mag-Incognito ka, hindi matatago ang iyong pagba-browse mula sa iyong employer, sa iyong internet service provider o sa mga website na binibisita mo.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, pindutin ang Tab pagkatapos ay ang Enter para magdagdag at mamahala ng mga address sa mga setting ng Chrome</translation>
<translation id="7365849542400970216">Alam mo ba ang iyong paggamit ng device?</translation>
<translation id="7372973238305370288">resulta ng paghahanap</translation>
@@ -1674,7 +1721,9 @@ Mga karagdagang detalye:
<translation id="7378594059915113390">Mga Kontrol ng Media</translation>
<translation id="7378627244592794276">Hindi</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Hindi naaangkop</translation>
<translation id="7390545607259442187">Kumpirmahin ang Card</translation>
+<translation id="7392089738299859607">I-update ang Address</translation>
<translation id="7399802613464275309">Pagsusuri sa Kaligtasan</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Pinapamahalaan ang iyong <ph name="DEVICE_NAME" /></translation>
@@ -1689,6 +1738,7 @@ Mga karagdagang detalye:
&lt;li&gt;Bisitahin ang &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;help center ng Chrome&lt;/a&gt; para matutunan kung paano permanenteng alisin ang software sa iyong computer
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Maganda</translation>
<translation id="7416351320495623771">Pamahalaan ang Mga Password...</translation>
<translation id="7419106976560586862">Path ng Profile</translation>
<translation id="7437289804838430631">Magdagdag ng Impormasyon ng Contact</translation>
@@ -1704,7 +1754,7 @@ Mga karagdagang detalye:
<translation id="7481312909269577407">Sumulong</translation>
<translation id="7485870689360869515">Walang nahanap na data.</translation>
<translation id="7495528107193238112">Naka-block ang content na ito. Makipag-ugnayan sa may-ari ng site para maayos ang isyu.</translation>
-<translation id="7498234416455752244">Magpatuloy sa pag-edit</translation>
+<translation id="7498193950643227031">Posibleng biglaang mag-iba ang gawi nito kung ire-resize ito. Puwede mo na ngayong limitahan ang kakayahang mag-resize ng mga app sa <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Kakalagay mo lang ng iyong password sa isang mapanlinlang na site. Inirerekomenda ng Chromium na suriin mo ngayon ang iyong mga naka-save na password para sa <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, at iba pang site kung saan mo ginagamit ang password na ito.</translation>
<translation id="7508255263130623398">Walang laman ang ibinalik na device id ng patakaran o hindi ito tumutugma sa kasalukuyang device id</translation>
<translation id="7508870219247277067">Avocado Green</translation>
@@ -1724,6 +1774,7 @@ Mga karagdagang detalye:
<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="755279583747225797">Aktibo ang trial</translation>
<translation id="7552846755917812628">Subukan ang mga sumusunod na tip:</translation>
<translation id="7554475479213504905">I-reload at ipakita pa rin</translation>
<translation id="7554791636758816595">Bagong Tab</translation>
@@ -1742,7 +1793,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, pindutin ang Tab at pagkatapos ay ang Enter para tingnan at pamahalaan ang mga password mo sa mga setting ng Chrome</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="7616645509853975347">Na-on ng iyong administrator ang Chrome Enterprise Connectors sa browser mo. May access ang mga connector na ito sa ilan sa iyong data.</translation>
<translation id="7619838219691048931">Dulong sheet</translation>
<translation id="762844065391966283">Paisa-isa</translation>
@@ -1807,13 +1857,12 @@ Mga karagdagang detalye:
<translation id="782886543891417279">Maaaring hilingin ng Wi-Fi na ginagamit mo (<ph name="WIFI_NAME" />) na bisitahin mo ang page nito sa pag-login.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Wala}=1{1 app (<ph name="EXAMPLE_APP_1" />)}=2{2 app (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# (na) app (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# (na) app (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Gayunpaman, hindi ka invisible. Kahit mag-incognito ka, hindi matatago ang iyong pagba-browse mula sa iyong employer, sa iyong internet service provider o sa mga website na binibisita mo.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Magbukas ng mga file na may mga nauugnay na uri ng file.</translation>
<translation id="7862185352068345852">Umalis sa site?</translation>
<translation id="7865448901209910068">Pinakamabilis</translation>
<translation id="7874263914261512992">Kakalagay mo lang ng iyong password sa isang mapanlinlang na site. Inirerekomenda ng Chrome na suriin mo ngayon ang iyong mga naka-save na password para sa <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, at iba pang site kung saan mo ginagamit ang password na ito.</translation>
<translation id="7878562273885520351">Maaaring makompromismo ang iyong password</translation>
+<translation id="7880146494886811634">I-save ang Address</translation>
<translation id="7882421473871500483">Brown</translation>
<translation id="7887683347370398519">Tingnan ang iyong CVC at subukang muli</translation>
<translation id="7887885240995164102">Pumasok sa picture-in-picture</translation>
@@ -1821,6 +1870,7 @@ Mga karagdagang detalye:
<translation id="7894280532028510793">Kung tama ang pagbabaybay, <ph name="BEGIN_LINK" />subukang patakbuhin ang Mga Diagnostic ng Network<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Hindi Alam</translation>
+<translation id="793209273132572360">I-update ang address?</translation>
<translation id="7932579305932748336">Coat</translation>
<translation id="79338296614623784">Maglagay ng wastong numero ng telepono</translation>
<translation id="7934052535022478634">Kumpleto na ang pagbabayad</translation>
@@ -1891,6 +1941,7 @@ Mga karagdagang detalye:
<translation id="8175796834047840627">Nag-aalok ang Chrome na i-save ang iyong mga card sa Google Account mo dahil naka-sign in ka. Maaari mong baguhin ang gawing ito sa mga setting.</translation>
<translation id="8176440868214972690">Nagpadala ang administrator ng device na ito ng ilang impormasyon sa mga sumusunod na website, tulad ng mga setting o patakaran.</translation>
<translation id="8184538546369750125">Gamitin ang pangkalahatang default (Payagan)</translation>
+<translation id="8193086767630290324">Mga isinagawang pagkilos na may data na na-flag bilang kumpidensyal</translation>
<translation id="8194797478851900357">&amp;I-undo ang Paglilipat</translation>
<translation id="8201077131113104583">Di-wastong URL ng update para sa extension na may ID na "<ph name="EXTENSION_ID" />."</translation>
<translation id="8202097416529803614">Buod ng order</translation>
@@ -1913,6 +1964,7 @@ Mga karagdagang detalye:
<translation id="8249296373107784235">I-abort</translation>
<translation id="8249320324621329438">Huling kinuha:</translation>
<translation id="8253091569723639551">Kinakailangan ang billing address</translation>
+<translation id="8257387598443225809">Idinisenyo ang app na ito para sa mobile</translation>
<translation id="825929999321470778">Ipakita ang Lahat ng Naka-save na Password</translation>
<translation id="8261506727792406068">I-delete</translation>
<translation id="8262952874573525464">Edge stitch bottom</translation>
@@ -2036,7 +2088,6 @@ Mga karagdagang detalye:
<translation id="8719528812645237045">Multiple punch top</translation>
<translation id="8725066075913043281">Muling subukan</translation>
<translation id="8726549941689275341">Laki ng page:</translation>
-<translation id="8728672262656704056">Naging incognito ka</translation>
<translation id="8730621377337864115">Tapos na</translation>
<translation id="8731544501227493793">Button na Pamahalaan ang mga password, pindutin ang Enter para tingnan at pamahalaan ang mga password mo sa mga setting ng Chrome</translation>
<translation id="8734529307927223492">Pinapamahalaan ng <ph name="MANAGER" /> ang iyong <ph name="DEVICE_TYPE" /></translation>
@@ -2113,6 +2164,7 @@ Mga karagdagang detalye:
<translation id="9020542370529661692">Na-translate sa <ph name="TARGET_LANGUAGE" /> ang pahinang ito</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Invalid)</translation>
+<translation id="9030265603405983977">Monochrome</translation>
<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>
@@ -2136,6 +2188,7 @@ Mga karagdagang detalye:
<translation id="91108059142052966">Dini-disable ng patakaran ng administrator ang pagbabahagi ng screen sa <ph name="APPLICATION_TITLE" /> kapag may nakikitang kumpidensyal na content</translation>
<translation id="9114524666733003316">Kinukumpirma ang card...</translation>
<translation id="9114581008513152754">Hindi pinapamahalaan ng kumpanya o iba pang organisasyon ang browser na ito. Posibleng pinapamahalaan sa labas ng Chrome ang aktibidad sa device na ito. <ph name="BEGIN_LINK" />Matuto pa<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Bago</translation>
<translation id="9119042192571987207">Na-upload</translation>
<translation id="9128016270925453879">Na-load na ang mga patakaran</translation>
<translation id="9128870381267983090">Kumonekta sa network</translation>
@@ -2154,6 +2207,7 @@ Mga karagdagang detalye:
<translation id="9170848237812810038">&amp;I-undo</translation>
<translation id="9171296965991013597">Umalis sa app?</translation>
<translation id="9173282814238175921">Isang dokumento/Bagong sheet</translation>
+<translation id="9173995187295789444">Nagsa-scan ng mga Bluetooth device...</translation>
<translation id="917450738466192189">Di-wastong certificate ng server.</translation>
<translation id="9174917557437862841">Button na lumipat ng tab, pindutin ang Enter para lumipat sa tab na ito</translation>
<translation id="9179703756951298733">Pamahalaan ang iyong mga pagbabayad at impormasyon ng credit card sa mga setting ng Chrome</translation>
diff --git a/chromium/components/strings/components_strings_fr-CA.xtb b/chromium/components/strings/components_strings_fr-CA.xtb
index e0b56a0800d..c15b7f9aa50 100644
--- a/chromium/components/strings/components_strings_fr-CA.xtb
+++ b/chromium/components/strings/components_strings_fr-CA.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Chrome conservera une copie de votre carte sur cet appareil pour remplir plus rapidement vos formulaires, lorsque l’option est cochée.</translation>
<translation id="1110994991967754504">Sélectionner une autorisation pour <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Annuler la réorganisation</translation>
+<translation id="1123753900084781868">La transcription instantanée n'est pas accessible pour le moment</translation>
<translation id="1125573121925420732">Les avertissements peuvent être fréquents lorsque les sites Web mettent à jour leurs mesures de sécurité. Cette situation devrait bientôt s'améliorer.</translation>
<translation id="112840717907525620">Cache de la règle valide</translation>
<translation id="1130564665089811311">Bouton Traduire la page, appuyez sur la touche Entrée pour traduire cette page avec Google Traduction</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Le nom de votre appareil</translation>
<translation id="124116460088058876">Plus de langues</translation>
<translation id="1243027604378859286">Auteur :</translation>
+<translation id="1246424317317450637">Gras</translation>
<translation id="1250759482327835220">Pour accélérer le paiement la prochaine fois, enregistrez votre carte, votre nom et votre adresse de facturation dans votre compte Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (synchronisés)</translation>
<translation id="1256368399071562588">&lt;p&gt;Si vous essayez de consulter un site Web et si celui-ci ne s'ouvre pas, essayez de corriger l'erreur à l'aide des étapes de dépannage suivantes :&lt;/p&gt;
@@ -101,7 +103,7 @@
<translation id="129863573139666797"><ph name="BEGIN_LINK" />Essayez d'effacer vos témoins<ph name="END_LINK" /></translation>
<translation id="1301324364792935241">Vérifiez les paramètres de DNS sécurisés</translation>
<translation id="1307966114820526988">Fonctionnalités obsolètes</translation>
-<translation id="131405271941274527"><ph name="URL" /> souhaite vous envoyer et recevoir de l'information lorsque vous touchez votre téléphone sur un appareil NFC</translation>
+<translation id="131405271941274527"><ph name="URL" /> souhaite vous envoyer et recevoir de l'information lorsque vous touchez votre téléphone sur un appareil CCP</translation>
<translation id="1314509827145471431">Reliure à droite</translation>
<translation id="1320233736580025032">Enveloppe Prc1</translation>
<translation id="132301787627749051">Rechercher une image du presse-papiers</translation>
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Modifiez votre mot de passe</translation>
<translation id="1484290072879560759">Choisir une adresse d'expédition</translation>
<translation id="1492194039220927094">Notifications poussées des politiques :</translation>
+<translation id="1495677929897281669">Retour à l'onglet</translation>
<translation id="1501859676467574491">Afficher les cartes enregistrées dans votre compte Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Cette erreur s'affiche si vous utilisez un portail Wi-Fi auquel vous devez vous connecter avant de pouvoir aller en ligne.&lt;/p&gt;
&lt;p&gt;Pour corriger l'erreur, cliquez sur &lt;strong&gt;Connexion&lt;/strong&gt; sur la page que vous essayez d'ouvrir.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Cette page indique</translation>
<translation id="153384715582417236">C'est tout pour le moment</translation>
<translation id="1536390784834419204">Traduire la page</translation>
+<translation id="1539840569003678498">Envoi du rapport :</translation>
<translation id="154408704832528245">Choisir une adresse de livraison</translation>
<translation id="1549470594296187301">Pour utiliser cette fonctionnalité, vous devez activer JavaScript.</translation>
<translation id="155039086686388498">Ingénierie D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">Bord court en premier</translation>
<translation id="168693727862418163">La validation de la valeur de cette politique par rapport à son schéma a échoué. La politique sera ignorée.</translation>
<translation id="168841957122794586">Le certificat du serveur contient une clé de chiffrement faible.</translation>
+<translation id="1696290444144917273">Afficher les renseignements de la carte virtuelle</translation>
<translation id="1697532407822776718">Vous êtes prêt!</translation>
<translation id="1703835215927279855">Lettre</translation>
<translation id="1706954506755087368">{1,plural, =1{Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />, car la date d'émission de son certificat de sécurité semble dater de demain. Cela peut être dû à une mauvaise configuration ou à l'interception de votre connexion par un pirate informatique.}one{Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />, car la date d'émission de son certificat de sécurité est ultérieure de # jour à la date du jour. Cela peut être dû à une mauvaise configuration ou à l'interception de votre connexion par un pirate informatique.}other{Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />, car la date d'émission de son certificat de sécurité est ultérieure de # jours à la date du jour. Cela peut être dû à une mauvaise configuration ou à l'interception de votre connexion par un pirate informatique.}}</translation>
<translation id="1710259589646384581">Systèmes d'exploitation</translation>
+<translation id="1711234383449478798">Ignorée : <ph name="POLICY_NAME" /> n'est pas définie à <ph name="VALUE" />.</translation>
<translation id="1712552549805331520">L'URL <ph name="URL" /> veut stocker des données de façon permanente sur votre ordinateur local</translation>
<translation id="1713628304598226412">Bac 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Boîte aux lettres 3</translation>
<translation id="1718029547804390981">Ce document est trop volumineux pour être annoté</translation>
<translation id="1721424275792716183">* Ce champ est obligatoire</translation>
+<translation id="1727613060316725209">Le certificat est valide</translation>
<translation id="1727741090716970331">Ajouter un numéro de carte valide</translation>
<translation id="1728677426644403582">Vous consultez la source d'une page Web</translation>
<translation id="173080396488393970">Ce type de carte n'est pas pris en charge</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Essayer d'exécuter Windows Network Diagnostics<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">Le serveur auquel vous accédez, <ph name="ORIGIN" />, a défini un en-tête qui exige qu'une politique d'origine soit appliquée à toutes les demandes qu'il reçoit. Mais l'en-tête est formaté de manière incorrecte, ce qui empêche le navigateur de répondre à votre demande pour <ph name="SITE" />. Les exploitants de sites peuvent utiliser des politiques d'origine pour configurer la sécurité et d'autres propriétés d'un site.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Veuillez mettre à jour votre phrase de passe de synchronisation.</translation>
<translation id="1787142507584202372">Vos onglets ouverts s'affichent ici</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, plusieurs actions sont possibles, appuyez sur la touche Tabulation pour les parcourir</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">Annonces</translation>
<translation id="1919367280705858090">Obtenir de l'aide pour un message d'erreur spécifique</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Aucun}=1{1 site}one{# site}other{# sites}}</translation>
+<translation id="1924727005275031552">Nouvelles</translation>
<translation id="1945968466830820669">Vous risquez de perdre l'accès au compte de votre organisation ou d'être victime d'un vol d'identité. Chromium recommande de modifier votre mot de passe maintenant.</translation>
<translation id="1947454675006758438">Agrafe en haut à droite</translation>
<translation id="1958218078413065209">Votre pointage le plus élevé est <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">Bac 7</translation>
<translation id="204357726431741734">Connectez-vous pour utiliser les mots de passe enregistrés dans votre compte Google</translation>
<translation id="2053111141626950936">Les pages en <ph name="LANGUAGE" /> ne seront pas traduites.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Lorsque cette commande est activée et que son état est défini à actif, Chrome détermine à quel grand groupe de personnes, ou « cohorte », votre activité de navigation récente ressemble le plus. Les annonceurs peuvent sélectionner des annonces pour le groupe, et votre activité de navigation reste privée sur votre appareil. Votre groupe est mis à jour tous les jours.}=1{Lorsque cette commande est activée et que son état est défini à actif, Chrome détermine à quel grand groupe de personnes, ou « cohorte », votre activité de navigation récente ressemble le plus. Les annonceurs peuvent sélectionner des annonces pour le groupe, et votre activité de navigation reste privée sur votre appareil. Votre groupe est mis à jour tous les jours.}one{Lorsque cette commande est activée et que son état est défini à actif, Chrome détermine à quel grand groupe de personnes, ou « cohorte », votre activité de navigation récente ressemble le plus. Les annonceurs peuvent sélectionner des annonces pour le groupe, et votre activité de navigation reste privée sur votre appareil. Votre groupe est mis à jour chaque {NUM_DAYS} jour.}other{Lorsque cette commande est activée et que son état est défini à actif, Chrome détermine à quel grand groupe de personnes, ou « cohorte », votre activité de navigation récente ressemble le plus. Les annonceurs peuvent sélectionner des annonces pour le groupe, et votre activité de navigation reste privée sur votre appareil. Votre groupe est mis à jour tous les {NUM_DAYS} jours.}}</translation>
<translation id="2053553514270667976">Code postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggestion}one{# suggestion}other{# suggestions}}</translation>
<translation id="2071692954027939183">Les notifications ont été bloquées automatiquement parce que vous ne les autorisez généralement pas</translation>
<translation id="2079545284768500474">Annuler</translation>
<translation id="20817612488360358">Les paramètres de mandataire du système sont configurés pour être utilisés, mais une configuration de mandataire explicite est également spécifiée.</translation>
<translation id="2082238445998314030">Résultat <ph name="RESULT_NUMBER" /> sur <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Enregistrer…</translation>
<translation id="2088086323192747268">Bouton Gérer la synchronisation, appuyez sur Entrée pour gérer les données que vous synchronisez dans les paramètres de Chrome</translation>
<translation id="2091887806945687916">Son</translation>
<translation id="2094505752054353250">Le domaine ne correspond pas</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> requiert un nom d'utilisateur et un mot de passe.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, expire le <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Paramètre géré par votre administrateur</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> veut s'associer</translation>
<translation id="2344028582131185878">Téléchargements automatiques</translation>
<translation id="2346319942568447007">L'image que vous avez copiée</translation>
<translation id="2354001756790975382">Autres favoris</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">Des pirates pourraient être en mesure de voir les images que vous regardez sur ce site et vous tromper en les modifiant.</translation>
<translation id="2356070529366658676">Demander</translation>
<translation id="2357481397660644965">Votre appareil est géré par <ph name="DEVICE_MANAGER" />, et votre compte est géré par <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Dans moins d'un jour}=1{Dans un jour}one{Dans {NUM_DAYS} jour}other{Dans {NUM_DAYS} jours}}</translation>
<translation id="2359629602545592467">Plusieurs</translation>
<translation id="2359808026110333948">Continuer</translation>
+<translation id="2359961752320758691">Votre numéro de carte virtuelle a été appliqué.</translation>
<translation id="2367567093518048410">Niveau</translation>
<translation id="2372464001869762664">Après votre confirmation, les détails de la carte provenant de votre compte Google seront partagés avec ce site. Vous trouverez le code CVC dans les renseignements de votre compte Plex.</translation>
<translation id="2380886658946992094">Légal</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">Ce mode de livraison n'est pas disponible. Essayez un autre mode.</translation>
<translation id="2396249848217231973">&amp;Annuler la suppression</translation>
<translation id="2410754574180102685">Légal, gouvernement</translation>
+<translation id="2413155254802890957">Anciennes</translation>
<translation id="2413528052993050574">Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />. Il se peut que son certificat de sécurité ait été révoqué. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.</translation>
<translation id="2414886740292270097">Foncé</translation>
<translation id="2438874542388153331">Quadruple perforation à droite</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">Agrafe en bas à droite</translation>
<translation id="2523886232349826891">Carte enregistrée sur cet appareil uniquement</translation>
<translation id="2524461107774643265">Ajouter plus de renseignements</translation>
-<translation id="2526590354069164005">Ordinateur de bureau</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{et 1 autre}one{et # autre}other{et # autres}}</translation>
<translation id="2536110899380797252">Ajouter une adresse</translation>
<translation id="2539524384386349900">Détecter</translation>
+<translation id="2541219929084442027">Les pages que vous consultez dans des onglets de navigation privée ne sont pas enregistrées dans l'historique du navigateur, ni dans le dossier des témoins, ni dans l'historique des recherches, une fois que vous avez fermé tous les onglets de navigation privée. Les fichiers téléchargés et vos favoris sont toutefois conservés.</translation>
<translation id="2544644783021658368">Document simple</translation>
<translation id="254947805923345898">La valeur attribuée à la politique n'est pas valide.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> a envoyé une réponse non valide.</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">Pour profiter du niveau de sécurité le plus élevé de Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />activez la protection renforcée<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Impossible de trouver l'adresse IP du serveur de <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">État :</translation>
+<translation id="264810637653812429">Aucun appareil compatible trouvé.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, appuyez sur la touche Tabulation, puis sur la touche Entrée pour effacer votre historique de navigation, vos témoins, votre cache et plus encore dans les paramètres de Chrome</translation>
<translation id="2650446666397867134">Accès au fichier refusé</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">Redémarrer</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 inoffensif peut parfois être infecté par des logiciels malveillants.</translation>
<translation id="2807052079800581569">Position Y de l'image</translation>
+<translation id="2820957248982571256">Recherche en cours…</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 contenu du formulaire</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">Enveloppe d'invitation</translation>
<translation id="2856444702002559011">Les cyberpirates peuvent essayer de voler vos données à partir de <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (par exemple, des mots de passe, des messages ou des numéros de carte de crédit). <ph name="BEGIN_LEARN_MORE_LINK" />En savoir plus<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Ce site diffuse des annonces intrusives ou trompeuses.</translation>
+<translation id="287596039013813457">Amical</translation>
+<translation id="2876489322757410363">Vous devez désactiver le mode de navigation privée pour effectuer un paiement par l'intermédiaire d'une application externe. Continuer?</translation>
<translation id="2878197950673342043">Pli au format affiche</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Position des fenêtres</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">Enveloppe C9</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" /> : appuyez sur Tabulation, puis sur Entrée pour effectuer une vérification de sécurité dans les paramètres de Chrome</translation>
<translation id="3061707000357573562">Service de correctif</translation>
-<translation id="3064966200440839136">Vous devez quitter le mode de navigation privée pour effectuer un paiement par l'intermédiaire d'une application externe. Continuer?</translation>
<translation id="306573536155379004">Jeu démarré.</translation>
<translation id="3080254622891793721">Images</translation>
<translation id="3086579638707268289">Votre activité sur le Web est actuellement surveillée</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">Votre compte est géré par <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Restaurer</translation>
<translation id="3162559335345991374">Le réseau Wi-Fi que vous utilisez peut vous demander de visiter sa page de connexion.</translation>
-<translation id="3167968892399408617">Les pages que vous consultez dans les onglets de navigation privée ne sont pas consignées dans l'historique du navigateur, ni dans le dossier des témoins, ni dans l'historique des recherches, une fois que vous avez fermé tous les onglets de navigation privée. Les fichiers téléchargés et vos favoris sont toutefois conservés.</translation>
<translation id="3169472444629675720">Découvrir</translation>
<translation id="3174168572213147020">ÃŽle</translation>
<translation id="3176929007561373547">Vérifiez vos paramètres de mandataire ou communiquez avec votre administrateur
@@ -593,10 +608,12 @@
<translation id="3229041911291329567">Renseignements sur la version de votre appareil et de votre navigateur</translation>
<translation id="323107829343500871">Entrez le code de vérification de carte (CVC) pour <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Toujours détecter le contenu important sur ce site</translation>
+<translation id="3249845759089040423">Pimpant</translation>
<translation id="3252266817569339921">Français</translation>
<translation id="3266793032086590337">Valeur (conflit)</translation>
<translation id="3268451620468152448">Onglets ouverts</translation>
<translation id="3270847123878663523">&amp;Annuler la réorganisation</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> veut se connecter</translation>
<translation id="3274521967729236597">Pa Kai</translation>
<translation id="3282085321714087552">Votre organisation, <ph name="ENROLLMENT_DOMAIN" />, a envoyé de l'information, comme des paramètres ou des politiques, aux sites Web suivants.</translation>
<translation id="3282497668470633863">Ajouter le nom sur la carte</translation>
@@ -649,6 +666,7 @@
<translation id="3428151540071562330">Une ou plusieurs des URL de modèle de serveur DnsOverHttpsTemplates sont incorrectes et ne seront pas utilisées.</translation>
<translation id="3431636764301398940">Enregistrer cette carte sur cet appareil</translation>
<translation id="3432601291244612633">Fermer la page</translation>
+<translation id="3435738964857648380">Sécurité</translation>
<translation id="3435896845095436175">Activer</translation>
<translation id="3438829137925142401">Utiliser les mots de passe enregistrés dans votre compte Google</translation>
<translation id="3443726618221119081">Jurro Ku Kai</translation>
@@ -691,7 +709,10 @@
<translation id="3584299510153766161">Double perforation en bas</translation>
<translation id="3586931643579894722">Masquer les détails</translation>
<translation id="3587738293690942763">Centre</translation>
+<translation id="3590643883886679995">Les données de connexion seront stockées sur cet appareil lorsque vous quitterez le mode de navigation privée.</translation>
+<translation id="359126217934908072">Mois/Année :</translation>
<translation id="3592413004129370115">Enveloppe italienne</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Vous pouvez réinitialiser votre groupe en tout temps. Il faut environ un jour pour vous joindre à un nouveau groupe.}=1{Vous pouvez réinitialiser votre groupe en tout temps. Il faut environ un jour pour vous joindre à un nouveau groupe.}one{Vous pouvez réinitialiser votre groupe en tout temps. Il faut environ {NUM_DAYS} jour pour vous joindre à un nouveau groupe.}other{Vous pouvez réinitialiser votre groupe en tout temps. Il faut environ {NUM_DAYS} jours pour vous joindre à un nouveau groupe.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Application bloquée par votre administrateur</translation>
<translation id="3608932978122581043">Orientation de l'alimentation</translation>
@@ -700,13 +721,13 @@
<translation id="3615877443314183785">Entrez une date d'expiration valide</translation>
<translation id="36224234498066874">Effacer données navigation…</translation>
<translation id="362276910939193118">Afficher l'historique complet</translation>
-<translation id="3625635938337243871">Les données de connexion seront stockées sur cet appareil lorsque vous quitterez le mode de navigation privée.</translation>
<translation id="3630155396527302611">Si la page est déjà répertoriée comme étant un programme autorisé à accéder
au réseau, essayez de la supprimer de la liste, puis de la rajouter.</translation>
<translation id="3630699740441428070">Les administrateurs de cet appareil ont configuré votre connexion au réseau, ce qui peut leur permettre de voir votre trafic réseau, y compris les sites Web que vous consultez.</translation>
<translation id="3631244953324577188">Données biométriques</translation>
<translation id="3633738897356909127">Bouton Mise à jour de Chrome, appuyez sur la touche Entrée pour mettre à jour Chrome dans les paramètres de Chrome</translation>
<translation id="3634530185120165534">Bac 5</translation>
+<translation id="3637662659967048211">Enregistrer dans le compte Google</translation>
<translation id="3640766068866876100">Fiche, 4 po x 6 po, ext</translation>
<translation id="3642638418806704195">Application :</translation>
<translation id="3650584904733503804">Validation réussie</translation>
@@ -747,6 +768,7 @@
<translation id="3781428340399460090">Rose indien</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Appareils Bluetooth</translation>
+<translation id="3787675388804467730">Numéro de carte virtuelle</translation>
<translation id="3787705759683870569">Date d'expiration : <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Taille 16</translation>
<translation id="3789841737615482174">Installer</translation>
@@ -766,6 +788,7 @@
<translation id="3841184659773414994">Modules de traitement de fichiers</translation>
<translation id="385051799172605136">Retour</translation>
<translation id="3858027520442213535">Mettre à jour la date et l'heure</translation>
+<translation id="3881478300875776315">Afficher moins de lignes</translation>
<translation id="3884278016824448484">Identifiant de périphérique en conflit</translation>
<translation id="3885155851504623709">Paroisse</translation>
<translation id="388632593194507180">Surveillance détectée</translation>
@@ -791,6 +814,7 @@
<translation id="397105322502079400">Calcul en cours...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> est bloquée</translation>
<translation id="3973357910713125165">Bouton Effectuer une vérification de sécurité de Chrome : appuyez sur Entrée pour effectuer une vérification de sécurité dans les paramètres de Chrome</translation>
+<translation id="3986705137476756801">Désactiver la transcription instantanée pour le moment</translation>
<translation id="3987405730340719549">Chrome a déterminé que ce site pourrait être faux ou frauduleux.
Si vous pensez qu'il s'agit d'une erreur, veuillez visiter la page https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -882,13 +906,14 @@
<translation id="4275830172053184480">Redémarrer l'appareil</translation>
<translation id="4277028893293644418">Réinitialiser le mot de passe</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{La carte a été enregistrée dans votre compte Google}one{La carte a été enregistrée dans votre compte Google}other{Les cartes ont été enregistrées dans votre compte Google}}</translation>
+<translation id="4287885627794386150">Admissible à une version d'essai, mais pas actif</translation>
<translation id="4297502707443874121">Miniature pour la page <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Développer</translation>
<translation id="4300675098767811073">Multiple perforation à droite</translation>
<translation id="4302514097724775343">Touchez le dinosaure pour jouer</translation>
<translation id="4302965934281694568">Enveloppe Chou3</translation>
<translation id="4305666528087210886">Impossible d'accéder à votre fichier</translation>
-<translation id="4305817255990598646">Changer</translation>
+<translation id="4306529830550717874">Enregistrer l'adresse?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloquer (par défaut)</translation>
<translation id="4314815835985389558">Gérer la synchronisation</translation>
@@ -915,6 +940,7 @@
<translation id="4377125064752653719">Vous avez tenté d'accéder à <ph name="DOMAIN" />, mais le certificat présenté par le serveur a été révoqué par son émetteur, ce qui signifie qu'on ne peut plus faire confiance au certificat présenté par le serveur. Il est donc possible que vous communiquiez avec un pirate informatique.</translation>
<translation id="4378154925671717803">Numéro de téléphone</translation>
<translation id="4390472908992056574">Bord</translation>
+<translation id="4406883609789734330">Transcription instantanée</translation>
<translation id="4406896451731180161">résultats de recherche</translation>
<translation id="4408413947728134509">Témoins <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Vous venez d'entrer votre mot de passe sur un site trompeur. Chrome vous recommande de visiter <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ainsi que tout autre site sur lequel vous avez utilisé ce mot de passe, puis de le changer maintenant.</translation>
@@ -927,7 +953,6 @@
<translation id="4435702339979719576">Carte postale</translation>
<translation id="443673843213245140">L'utilisation d'un mandataire est désactivée, mais une configuration de mandataire explicite est spécifiée.</translation>
<translation id="4464826014807964867">Sites Web avec des données fournies par votre organisation</translation>
-<translation id="4466881336512663640">Les changements apportés aux formulaires seront perdus. Voulez-vous vraiment continuer?</translation>
<translation id="4476953670630786061">Ce formulaire n'est pas sécurisé. Le remplissage automatique a été désactivé.</translation>
<translation id="4477350412780666475">Chanson suivante</translation>
<translation id="4482953324121162758">Ce site ne sera pas traduit.</translation>
@@ -961,6 +986,7 @@
<translation id="4594403342090139922">&amp;Annuler la suppression</translation>
<translation id="4597348597567598915">Taille 8</translation>
<translation id="4600854749408232102">Enveloppe C6/C5</translation>
+<translation id="4606870351894164739">Remarquable</translation>
<translation id="4628948037717959914">Photo</translation>
<translation id="4631649115723685955">Avec remise en argent</translation>
<translation id="4636930964841734540">Renseignements</translation>
@@ -980,6 +1006,7 @@
<translation id="4691835149146451662">Enveloppe Architecture A</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Côté</translation>
+<translation id="4702656508969495934">La transcription instantanée est visible, servez-vous du commutateur de fenêtre pour y accéder</translation>
<translation id="4708268264240856090">Votre connexion a été interrompue</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />d'exécuter Windows Network Diagnostics<ph name="END_LINK" /></translation>
@@ -993,6 +1020,7 @@
<translation id="4738601419177586157">Suggestion de recherche <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Gérer les mots de passe…</translation>
<translation id="4744603770635761495">Chemin d'accès exécutable</translation>
+<translation id="4749011317274908093">Vous êtes passé en mode de navigation privée</translation>
<translation id="4750917950439032686">Vos données (par exemple, vos mots de passe ou vos numéros de carte de crédit) sont privées lorsqu'elles sont envoyées à ce site.</translation>
<translation id="4756388243121344051">&amp;Historique</translation>
<translation id="4758311279753947758">Ajouter des coordonnées</translation>
@@ -1022,6 +1050,8 @@
<translation id="4813512666221746211">Erreur réseau</translation>
<translation id="4816492930507672669">Ajuster à la page</translation>
<translation id="4819347708020428563">Modifier les annotations dans la vue par défaut?</translation>
+<translation id="4825507807291741242">Puissant</translation>
+<translation id="4838327282952368871">Rêveur</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">Affichage</translation>
<translation id="485316830061041779">Allemand</translation>
@@ -1158,6 +1188,7 @@
<translation id="5314967030527622926">Créateur de brochures</translation>
<translation id="5316812925700871227">Faire pivoter dans le sens antihoraire</translation>
<translation id="5317780077021120954">Enregistrer</translation>
+<translation id="5321288445143113935">Affichée en taille maximale</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> sur <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Choisir des coordonnées</translation>
<translation id="5327248766486351172">Nom</translation>
@@ -1165,11 +1196,13 @@
<translation id="5332219387342487447">Mode de livraison</translation>
<translation id="5333022057423422993">Chrome a trouvé le mot de passe que vous venez juste d'utiliser dans une violation de données. Afin de sécuriser vos comptes, nous vous recommandons de vérifier vos mots de passe enregistrés.</translation>
<translation id="5334013548165032829">Journaux détaillés du système</translation>
+<translation id="5334145288572353250">Enregistrer l'adresse?</translation>
<translation id="5340250774223869109">L'application est bloquée</translation>
-<translation id="534295439873310000">Appareils NFC</translation>
+<translation id="534295439873310000">Appareils CCP</translation>
<translation id="5344579389779391559">L'accès à cette page peut engendrer des frais</translation>
<translation id="5355557959165512791">Vous ne pouvez pas consulter le site <ph name="SITE" /> pour le moment, car son certificat a été révoqué. Les erreurs réseau et les attaques sont généralement temporaires, ce qui signifie que cette page devrait fonctionner de nouveau plus tard.</translation>
<translation id="536296301121032821">Échec de stockage des paramètres de la règle</translation>
+<translation id="5363309033720083897">Port série autorisé par votre administrateur</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="5386426401304769735">La chaîne de certificat pour ce site contient un certificat qui a été signé avec SHA-1.</translation>
@@ -1178,6 +1211,7 @@
<translation id="5398772614898833570">Annonces bloquées</translation>
<translation id="5400836586163650660">Gris</translation>
<translation id="540969355065856584">Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />, car son certificat de sécurité n'est pas valide présentement. Cela peut être dû à une mauvaise configuration ou à l'interception de votre connexion par une personne malveillante.</translation>
+<translation id="541143247543991491">Nuage (à l'échelle du système)</translation>
<translation id="541416427766103491">Empileur 4</translation>
<translation id="5421136146218899937">Effacer les données de navigation...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> veut vous envoyer des notifications.</translation>
@@ -1191,6 +1225,7 @@
<translation id="5455374756549232013">Horodatage de la règle incorrect.</translation>
<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 contact}one{<ph name="CONTACT_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> autre contact}other{<ph name="CONTACT_PREVIEW" /> et <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> autres contacts}}</translation>
+<translation id="5463625433003343978">Recherche d'appareils en cours…</translation>
<translation id="5469868506864199649">Italien</translation>
<translation id="5470861586879999274">&amp;Rétablir la modification</translation>
<translation id="5478437291406423475">Enveloppe B6/C4</translation>
@@ -1240,7 +1275,6 @@
<translation id="5624120631404540903">Gérer les mots de passe</translation>
<translation id="5629630648637658800">Échec du chargement des paramètres de la règle</translation>
<translation id="5631439013527180824">Jeton de gestion de l'appareil non valide.</translation>
-<translation id="5632627355679805402">Vos données ont été chiffrées avec votre <ph name="BEGIN_LINK" />mot de passe Google<ph name="END_LINK" /> à compter du <ph name="TIME" />. Entrez votre mot de passe pour démarrer la synchronisation.</translation>
<translation id="5633066919399395251">Les cyberpirates actuellement à l'œuvre sur le site <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> peuvent essayer d'installer des programmes dangereux sur votre ordinateur pour voler ou supprimer vos renseignements (par exemple, des photos, des mots de passe, des messages et des numéros de carte de crédit). <ph name="BEGIN_LEARN_MORE_LINK" />En savoir plus<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Contenu trompeur bloqué.</translation>
<translation id="5644090287519800334">Décalage X de l'image côté 1</translation>
@@ -1279,12 +1313,12 @@
<translation id="5785756445106461925">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 l’apparence de cette page.</translation>
<translation id="5786044859038896871">Voulez-vous fournir les renseignements concernant votre carte de crédit?</translation>
<translation id="578633867165174378">Chrome a trouvé le mot de passe que vous venez juste d'utiliser dans une violation de données. Nous vous recommandons de changer ce mot de passe maintenant.</translation>
-<translation id="5798290721819630480">Supprimer les modifications?</translation>
<translation id="5803412860119678065">Voulez-vous fournir les renseignements concernant votre carte <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Autorisations</translation>
-<translation id="5804427196348435412">Utiliser des appareils NFC</translation>
+<translation id="5804427196348435412">Utiliser des appareils CCP</translation>
<translation id="5810442152076338065">Votre connexion au domaine <ph name="DOMAIN" /> est protégée par une suite de chiffrement obsolète.</translation>
<translation id="5813119285467412249">&amp;Rétablir l'ajout</translation>
+<translation id="5817918615728894473">Associer</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Cette carte sera débitée lorsque vous payerez, mais son véritable numéro ne sera pas partagé avec ce site. Pour accroître la sécurité, un code CVC sera généré.}one{La carte que vous avez sélectionnée sera débitée lorsque vous payerez, mais son véritable numéro ne sera pas partagé avec ce site. Pour accroître la sécurité, un code CVC sera généré.}other{Les cartes que vous avez sélectionnées seront débitées lorsque vous payerez, mais leur véritable numéro ne sera pas partagé avec ce site. Pour accroître la sécurité, un code CVC sera généré.}}</translation>
<translation id="5826507051599432481">Nom commun (CN)</translation>
<translation id="5838278095973806738">Nous vous déconseillons d'entrer des données sensibles sur ce site (par exemple, des mots de passe ou des cartes de crédit), car elles pourraient être volées par des pirates.</translation>
@@ -1292,6 +1326,7 @@
<translation id="5855253129151731373">Le nom d'hôte de ce site est similaire à celui de <ph name="LOOKALIKE_DOMAIN" />. Les pirates tentent parfois d'imiter des sites Web en modifiant légèrement le nom de domaine utilisé.
Si vous pensez qu'il s'agit d'une erreur, veuillez visiter la page https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Désactivé</translation>
<translation id="5862579898803147654">Empileur 8</translation>
<translation id="5863847714970149516">La page suivante peut engendrer des frais</translation>
<translation id="5866257070973731571">Ajouter un numéro de téléphone</translation>
@@ -1308,6 +1343,7 @@
<translation id="5913377024445952699">Capture d'écran mise en pause</translation>
<translation id="59174027418879706">Activé</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 en cours d'utilisation}one{# en cours d'utilisation}other{# en cours d'utilisation}}</translation>
<translation id="5921185718311485855">Activé</translation>
<translation id="5921639886840618607">Enregistrer la carte dans votre compte Google?</translation>
<translation id="5922853866070715753">Vous avez presque terminé</translation>
@@ -1327,6 +1363,7 @@
<translation id="5989320800837274978">Aucun serveur mandataire fixe ni URL de script .pac indiqué.</translation>
<translation id="5992691462791905444">Technique de pli en Z</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> résultats trouvés pour « <ph name="SEARCH_TEXT" /> »</translation>
+<translation id="6006484371116297560">Classique</translation>
<translation id="6008122969617370890">Ordre N sur 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Vérifier vos mots de passe</translation>
@@ -1348,6 +1385,7 @@
<translation id="6045164183059402045">Modèle d'imposition</translation>
<translation id="6047233362582046994">Si vous comprenez les risques pour votre sécurité, vous pouvez <ph name="BEGIN_LINK" />vous rendre sur ce site<ph name="END_LINK" /> avant que les applications malveillantes aient été supprimées.</translation>
<translation id="6047927260846328439">Ce contenu pourrait essayer de vous faire installer un logiciel ou de vous faire dévoiler des renseignements personnels. <ph name="BEGIN_LINK" />Afficher quand même<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Maintenez le doigt sur |<ph name="ACCELERATOR" />| pour quitter le mode plein écran</translation>
<translation id="6049488691372270142">Livraison de la page</translation>
<translation id="6051221802930200923">Vous ne pouvez pas consulter le site <ph name="SITE" /> pour le moment, car le site Web utilise l'épinglage de certificat. 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="6051898664905071243">Nombre de pages :</translation>
@@ -1364,6 +1402,7 @@
<translation id="610911394827799129">D'autres formes d'historique de navigation peuvent exister sur votre compte Google à l'adresse <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">Voir le texte et les images copiés dans le presse-papiers</translation>
<translation id="6120179357481664955">Se souvenir de votre identifiant UPI?</translation>
+<translation id="6123290840358279103">Afficher la carte virtuelle</translation>
<translation id="6124432979022149706">Connecteurs Chrome Enterprise</translation>
<translation id="6146055958333702838">Vérifiez les câbles et redémarrez votre routeur, votre modem
ou tout autre périphérique réseau utilisé.</translation>
@@ -1400,6 +1439,7 @@
<translation id="6289939620939689042">Couleur de la page</translation>
<translation id="6290238015253830360">Les articles que vous avez suggérés s'afficheront ici</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">Code CVC :</translation>
<translation id="6302269476990306341">Arrêt de l'Assistant Google dans Chrome en cours…</translation>
<translation id="6305205051461490394">Impossible d'accéder à <ph name="URL" />.</translation>
<translation id="6312113039770857350">La page Web n'est pas disponible</translation>
@@ -1425,6 +1465,7 @@
<translation id="6390200185239044127">Demi-feuille de pli en Z</translation>
<translation id="6390662030813198813">Ingénierie E</translation>
<translation id="6393956493820063117">La politique de l'administrateur bloque le collage de contenu provenant de <ph name="ORIGIN_NAME" /> à cet endroit</translation>
+<translation id="6398765197997659313">Quitter le mode plein écran</translation>
<translation id="6401136357288658127">Cette politique est obsolète. Vous devriez utiliser la politique <ph name="NEW_POLICY" /> à la place.</translation>
<translation id="6404511346730675251">Modifier le favori</translation>
<translation id="6406765186087300643">Enveloppe C0</translation>
@@ -1437,7 +1478,6 @@
<translation id="6428450836711225518">Vérifier votre numéro de téléphone</translation>
<translation id="6433490469411711332">Modifier les coordonnées</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> a refusé la connexion.</translation>
-<translation id="6434309073475700221">Supprimer</translation>
<translation id="6440503408713884761">Ignorée</translation>
<translation id="6443406338865242315">Les extensions et les plugiciels que vous avez installés</translation>
<translation id="6446163441502663861">Enveloppe Kahu</translation>
@@ -1480,6 +1520,7 @@
<translation id="6624427990725312378">Coordonnées</translation>
<translation id="6626291197371920147">Ajouter un numéro de carte valide</translation>
<translation id="6628463337424475685">Recherche <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Recherche d'appareils USB en cours…</translation>
<translation id="6630809736994426279">Les cyberpirates actuellement à l'œuvre sur le site <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> peuvent essayer d'installer des programmes dangereux sur votre Mac qui volent ou suppriment vos renseignements (par exemple, des photos, des mots de passe, des messages et des numéros de carte de crédit). <ph name="BEGIN_LEARN_MORE_LINK" />En savoir plus<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Effacer</translation>
@@ -1495,6 +1536,7 @@
<translation id="6671697161687535275">Supprimer la suggestion de formulaire de Chromium?</translation>
<translation id="6685834062052613830">Déconnectez-vous et terminez la configuration</translation>
<translation id="6687335167692595844">Taille de police demandée</translation>
+<translation id="6688743156324860098">Mettre à jour…</translation>
<translation id="6689249931105087298">Valeur relative avec compression des points noirs</translation>
<translation id="6689271823431384964">Chrome vous propose d'enregistrer vos cartes dans votre compte Google parce que vous y êtes connecté. Vous pouvez modifier ce comportement dans les paramètres. Le nom du détenteur de la carte provient de votre compte.</translation>
<translation id="6698381487523150993">Créé :</translation>
@@ -1510,6 +1552,7 @@
<translation id="6744009308914054259">En attendant la connexion, vous pouvez consulter vos téléchargements pour lire des articles hors connexion.</translation>
<translation id="6753269504797312559">Valeur de la règle</translation>
<translation id="6757797048963528358">Votre appareil s'est mis en veille.</translation>
+<translation id="6767985426384634228">Mettre à jour l'adresse?</translation>
<translation id="6768213884286397650">Carte postale hagaki</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violet</translation>
@@ -1532,6 +1575,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome a simplifié cette page pour la rendre plus facile à lire. Chrome a téléchargé la page originale par connexion non sécurisée.</translation>
<translation id="6891596781022320156">Le niveau de politique n'est pas pris en charge.</translation>
+<translation id="6895143722905299846">Numéro de carte virtuelle :</translation>
<translation id="6895330447102777224">Votre carte est confirmée</translation>
<translation id="6897140037006041989">Agent utilisateur</translation>
<translation id="6898699227549475383">Organisation (O)</translation>
@@ -1567,10 +1611,10 @@
<translation id="7004583254764674281">Utiliser Windows Hello pour vérifier les cartes plus rapidement</translation>
<translation id="7006930604109697472">Envoyer quand même</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Paramètres de redimensionnement</translation>
<translation id="7014741021609395734">Niveau de zoom</translation>
<translation id="7016992613359344582">Ces frais peuvent être ponctuels ou récurrents, et peuvent ne pas être évidents.</translation>
<translation id="7029809446516969842">Mots de passe</translation>
+<translation id="7030436163253143341">Le certificat n'est pas valide</translation>
<translation id="7031646650991750659">Les applications Google Play que vous avez installées</translation>
<translation id="7050187094878475250">Vous avez essayé d’atteindre <ph name="DOMAIN" />, mais le serveur a présenté un certificat dont la période de validité est trop longue pour être sûre.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Cette carte ne peut pas être enregistrée pour le moment}one{Cette carte ne peut pas être enregistrée pour le moment}other{Ces cartes ne peuvent pas être enregistrées pour le moment}}</translation>
@@ -1640,12 +1684,14 @@ Détails supplémentaires :
<translation id="7300012071106347854">Cobalt</translation>
<translation id="7302712225291570345">« <ph name="TEXT" /> »</translation>
<translation id="7304030187361489308">Élevée</translation>
+<translation id="7305756307268530424">Vitesse plus lente</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Aide pour la connexion</translation>
<translation id="7323804146520582233">Masquer la section « <ph name="SECTION" /> »</translation>
<translation id="733354035281974745">Ignorer le compte local de l'appareil</translation>
<translation id="7333654844024768166">Vous venez d'entrer votre mot de passe sur un site trompeur. Chromium vous recommande de visiter <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ainsi que tout autre site sur lequel vous avez utilisé ce mot de passe, puis de le changer maintenant.</translation>
<translation id="7334320624316649418">&amp;Rétablir la réorganisation</translation>
+<translation id="7337248890521463931">Afficher plus de lignes</translation>
<translation id="7337706099755338005">Non disponible sur votre plateforme.</translation>
<translation id="733923710415886693">Le certificat du serveur n'a pas été divulgué par l'intermédiaire de l'outil Certificate Transparency.</translation>
<translation id="734600844861828519">11 po x 15 po</translation>
@@ -1653,6 +1699,7 @@ Détails supplémentaires :
<translation id="7349430561505560861">A4 Extra</translation>
<translation id="7353601530677266744">Ligne de commande</translation>
<translation id="7359588939039777303">Annonces bloquées.</translation>
+<translation id="7363096869660964304">Vous n'êtes cependant pas devenu invisible. L'utilisation du mode de navigation privée n'empêche pas votre employeur, votre fournisseur d'accès Internet ou les sites Web que vous avez consultés d'avoir accès aux données relatives à votre navigation.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, appuyez sur Tabulation, puis sur Entrée pour ajouter et gérer les adresses dans les paramètres de Chrome</translation>
<translation id="7365849542400970216">Autoriser le site Web à connaître votre utilisation de l'appareil?</translation>
<translation id="7372973238305370288">résultat de la recherche</translation>
@@ -1663,7 +1710,9 @@ Détails supplémentaires :
<translation id="7378594059915113390">Commandes multimédias</translation>
<translation id="7378627244592794276">Pas maintenant</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Non applicable</translation>
<translation id="7390545607259442187">Confirmer la carte</translation>
+<translation id="7392089738299859607">Mettre à jour l'adresse</translation>
<translation id="7399802613464275309">Vérification de sécurité</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Votre <ph name="DEVICE_NAME" /> est géré</translation>
@@ -1678,6 +1727,7 @@ Détails supplémentaires :
&lt;li&gt;Consultez le &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centre d'aide de Chrome&lt;/a&gt; pour apprendre à supprimer définitivement le logiciel de votre ordinateur
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Format large</translation>
+<translation id="7410471291937727359">Précieux</translation>
<translation id="7416351320495623771">Gérer les mots de passe…</translation>
<translation id="7419106976560586862">Chemin d'accès du profil</translation>
<translation id="7437289804838430631">Ajouter des coordonnées</translation>
@@ -1693,7 +1743,7 @@ Détails supplémentaires :
<translation id="7481312909269577407">Suivant</translation>
<translation id="7485870689360869515">Aucune donnée trouvée.</translation>
<translation id="7495528107193238112">Ce contenu est bloqué. Communiquez avec le propriétaire du site pour corriger le problème.</translation>
-<translation id="7498234416455752244">Poursuivre la modification</translation>
+<translation id="7498193950643227031">L'application pourrait se comporter de manière inattendue si vous la redimensionnez. Vous pouvez maintenant limiter la possibilité de redimensionner les applications dans le menu <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Vous venez d'entrer votre mot de passe sur un site trompeur. Chromium vous recommande de vérifier vos mots de passe enregistrés pour <ph name="WEBSITE_1" />, pour <ph name="WEBSITE_2" /> et pour tout autre site sur lequel vous utilisez ce mot de passe maintenant.</translation>
<translation id="7508255263130623398">L'ID d'appareil de la règle renvoyé est vide ou ne correspond pas à l'ID d'appareil actuel</translation>
<translation id="7508870219247277067">Avocat</translation>
@@ -1713,6 +1763,7 @@ Détails supplémentaires :
<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 entrées 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">Le nom d'utilisateur de votre appareil et de Chrome</translation>
+<translation id="755279583747225797">La version d'essai est active</translation>
<translation id="7552846755917812628">Essayez les conseils suivants :</translation>
<translation id="7554475479213504905">Relancer et afficher malgré tout</translation>
<translation id="7554791636758816595">Nouvel onglet</translation>
@@ -1731,7 +1782,6 @@ Détails supplémentaires :
<translation id="7610193165460212391">La valeur « <ph name="VALUE" /> » est hors limites.</translation>
<translation id="7613889955535752492">Expiration : <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, appuyez sur la touche Entrée pour afficher et gérer vos mots de passe dans les paramètres de Chrome</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 l'entrer ci-dessous.</translation>
<translation id="7616645509853975347">Votre administrateur a activé les connecteurs Chrome Enterprise dans votre navigateur. Ces connecteurs ont accès à certaines de vos données.</translation>
<translation id="7619838219691048931">Feuille de fin</translation>
<translation id="762844065391966283">Un à la fois</translation>
@@ -1796,13 +1846,12 @@ Détails supplémentaires :
<translation id="782886543891417279">Le réseau Wi-Fi que vous utilisez (<ph name="WIFI_NAME" />) peut vous demander de visiter sa page de connexion.</translation>
<translation id="7836231406687464395">Enveloppe Postfix</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Aucune}=1{1 application : <ph name="EXAMPLE_APP_1" />}=2{2 applications (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# application (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# applications (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Vous n'êtes cependant pas devenu(e) invisible. L'utilisation du mode de navigation privée n'empêche pas votre employeur, votre fournisseur d'accès Internet ou les sites Web que vous avez consultés d'avoir accès aux données relatives à votre navigation.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Ouvrir les fichiers pour lesquels il y a des associations de type de fichier.</translation>
<translation id="7862185352068345852">Quitter le site?</translation>
<translation id="7865448901209910068">Meilleure vitesse</translation>
<translation id="7874263914261512992">Vous venez d'entrer votre mot de passe sur un site trompeur. Chrome vous recommande de vérifier vos mots de passe enregistrés pour <ph name="WEBSITE_1" />, pour <ph name="WEBSITE_2" /> et pour tout autre site sur lequel vous utilisez ce mot de passe maintenant.</translation>
<translation id="7878562273885520351">Votre mot de passe a peut-être été compromis</translation>
+<translation id="7880146494886811634">Enregistrer l'adresse</translation>
<translation id="7882421473871500483">Brun</translation>
<translation id="7887683347370398519">Veuillez vérifier votre CVC et réessayer</translation>
<translation id="7887885240995164102">Lancer le mode d'incrustation d'image</translation>
@@ -1810,6 +1859,7 @@ Détails supplémentaires :
<translation id="7894280532028510793">S'il n'y a pas d'erreur, <ph name="BEGIN_LINK" />essayez d'exécuter les diagnostics de réseau<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">Enveloppe C3</translation>
<translation id="7931318309563332511">Inconnue</translation>
+<translation id="793209273132572360">Mettre à jour l'adresse?</translation>
<translation id="7932579305932748336">Revêtement</translation>
<translation id="79338296614623784">Entrez un numéro de téléphone valide</translation>
<translation id="7934052535022478634">Paiement effectué</translation>
@@ -1880,6 +1930,7 @@ Détails supplémentaires :
<translation id="8175796834047840627">Chrome vous propose d'enregistrer vos cartes dans votre compte Google parce que vous y êtes connecté. Vous pouvez modifier ce comportement dans les paramètres.</translation>
<translation id="8176440868214972690">L'administrateur de cet appareil a envoyé de l'information, comme des paramètres ou des politiques, aux sites Web suivants.</translation>
<translation id="8184538546369750125">Utiliser le paramètre global par défaut (« Autoriser »)</translation>
+<translation id="8193086767630290324">Actions effectuées avec les données signalées comme confidentielles</translation>
<translation id="8194797478851900357">&amp;Annuler le déplacement</translation>
<translation id="8201077131113104583">URL de mise à jour non valide pour l'extension avec l'identifiant « ᠎<ph name="EXTENSION_ID" /> ».</translation>
<translation id="8202097416529803614">Résumé de la commande</translation>
@@ -1902,6 +1953,7 @@ Détails supplémentaires :
<translation id="8249296373107784235">Interrompre</translation>
<translation id="8249320324621329438">Dernière récupération :</translation>
<translation id="8253091569723639551">Adresse de facturation requise</translation>
+<translation id="8257387598443225809">Cette application est conçue pour les appareils mobiles</translation>
<translation id="825929999321470778">Afficher tous les mots de passe enregistrés</translation>
<translation id="8261506727792406068">Supprimer</translation>
<translation id="8262952874573525464">Agrafage par le bord inférieur</translation>
@@ -2025,7 +2077,6 @@ Détails supplémentaires :
<translation id="8719528812645237045">Multiple perforation en haut</translation>
<translation id="8725066075913043281">Réessayer</translation>
<translation id="8726549941689275341">Taille de la page :</translation>
-<translation id="8728672262656704056">Vous êtes passé en mode de navigation privée</translation>
<translation id="8730621377337864115">Terminé</translation>
<translation id="8731544501227493793">Bouton Gérer les mots de passe, appuyez sur la touche Entrée pour afficher et gérer vos mots de passe dans les paramètres de Chrome</translation>
<translation id="8734529307927223492">Votre <ph name="DEVICE_TYPE" /> est géré par <ph name="MANAGER" /></translation>
@@ -2102,6 +2153,7 @@ Détails supplémentaires :
<translation id="9020542370529661692">Cette page a été traduite en <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Non valide)</translation>
+<translation id="9030265603405983977">Monochrome</translation>
<translation id="9035022520814077154">Erreur liée à la sécurité</translation>
<translation id="9038649477754266430">Utilisez 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>
@@ -2125,6 +2177,7 @@ Détails supplémentaires :
<translation id="91108059142052966">La politique définie par l'administrateur désactive le partage d'écran avec <ph name="APPLICATION_TITLE" /> lorsque le contenu affiché est confidentiel</translation>
<translation id="9114524666733003316">Confirmation de la carte en cours…</translation>
<translation id="9114581008513152754">Ce navigateur n'est pas géré par une entreprise ou une organisation. L'activité sur cet appareil peut être gérée à l'extérieur de Chrome. <ph name="BEGIN_LINK" />En savoir plus<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Frais</translation>
<translation id="9119042192571987207">Téléversé</translation>
<translation id="9128016270925453879">Les politiques ont été chargées</translation>
<translation id="9128870381267983090">Connexion au réseau</translation>
@@ -2143,6 +2196,7 @@ Détails supplémentaires :
<translation id="9170848237812810038">Ann&amp;uler</translation>
<translation id="9171296965991013597">Quitter l'application?</translation>
<translation id="9173282814238175921">Document unique/Nouvelle feuille</translation>
+<translation id="9173995187295789444">Recherche d'appareils Bluetooth en cours…</translation>
<translation id="917450738466192189">Le certificat du serveur n'est pas valide.</translation>
<translation id="9174917557437862841">Bouton de commutation d'onglet, appuyez sur Entrée pour basculer vers cet onglet</translation>
<translation id="9179703756951298733">Gérez vos données de paiement et vos cartes de crédit dans les paramètres de Chrome</translation>
diff --git a/chromium/components/strings/components_strings_fr.xtb b/chromium/components/strings/components_strings_fr.xtb
index b9fe88a1a37..fe63ab6c2af 100644
--- a/chromium/components/strings/components_strings_fr.xtb
+++ b/chromium/components/strings/components_strings_fr.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Sélectionnez une autorisation pour <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Annuler la réorganisation</translation>
+<translation id="1123753900084781868">Sous-titres instantanés non disponibles pour l'instant</translation>
<translation id="1125573121925420732">Les avertissements peuvent être fréquents en attendant que les sites Web finissent de mettre à jour leurs systèmes de sécurité. Ce problème devrait être bientôt résolu.</translation>
<translation id="112840717907525620">Cache de la règle valide.</translation>
<translation id="1130564665089811311">Bouton "Traduire la page" : appuyer sur Entrée pour traduire cette page avec Google Traduction</translation>
@@ -74,6 +75,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="1240347957665416060">Nom de votre appareil</translation>
<translation id="124116460088058876">Plus de langues</translation>
<translation id="1243027604378859286">Auteur :</translation>
+<translation id="1246424317317450637">Gras</translation>
<translation id="1250759482327835220">Pour régler vos achats plus rapidement la prochaine fois, enregistrez votre carte, votre nom et votre adresse de facturation dans votre compte Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (synchronisés)</translation>
<translation id="1256368399071562588">&lt;p&gt;Si vous ne parvenez pas à ouvrir un site Web dans Chrome, essayez d'abord de corriger le problème en suivant ces étapes :&lt;/p&gt;
@@ -156,6 +158,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="1476595624592550506">Modifiez votre mot de passe</translation>
<translation id="1484290072879560759">Sélectionner l'adresse de livraison</translation>
<translation id="1492194039220927094">Diffusion push des règles : </translation>
+<translation id="1495677929897281669">Retour à l'onglet</translation>
<translation id="1501859676467574491">Afficher les cartes de votre compte Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Ce message s'affiche si vous utilisez un portail Wi-Fi auquel vous devez vous connecter pour accéder à Internet.&lt;/p&gt;
&lt;p&gt;Pour corriger cette erreur, cliquez sur &lt;strong&gt;Se connecter&lt;/strong&gt; sur la page que vous essayez d'ouvrir.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="1532118530259321453">Cette page indique</translation>
<translation id="153384715582417236">C'est tout !</translation>
<translation id="1536390784834419204">Traduire la page</translation>
+<translation id="1539840569003678498">Rapport envoyé :</translation>
<translation id="154408704832528245">Sélectionner l'adresse d'expédition</translation>
<translation id="1549470594296187301">Vous devez activer JavaScript pour utiliser cette fonctionnalité.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="1682696192498422849">Bord court en premier</translation>
<translation id="168693727862418163">La valeur de la règle n'a pas été validée par rapport à son schéma et sera ignorée.</translation>
<translation id="168841957122794586">Le certificat du serveur contient une clé de chiffrement faible.</translation>
+<translation id="1696290444144917273">Afficher les informations relatives à la carte virtuelle</translation>
<translation id="1697532407822776718">Vous êtes prêt !</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Impossible de vérifier que ce serveur est bien <ph name="DOMAIN" />, car la date d'émission de son certificat de sécurité est fixée à demain. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.}one{Impossible de vérifier que ce serveur est bien <ph name="DOMAIN" />, car la date d'émission de son certificat de sécurité est ultérieure de # jour à la date du jour. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.}other{Impossible de vérifier que ce serveur est bien <ph name="DOMAIN" />, car la date d'émission de son certificat de sécurité est ultérieure de # jours à la date du jour. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.}}</translation>
<translation id="1710259589646384581">Système d'exploitation</translation>
+<translation id="1711234383449478798">Ignorée, car <ph name="POLICY_NAME" /> n'est pas définie sur <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> souhaite stocker des données de façon permanente sur votre ordinateur local</translation>
<translation id="1713628304598226412">Bac 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Boîte aux lettres 3</translation>
<translation id="1718029547804390981">Le document est trop volumineux pour être annoté</translation>
<translation id="1721424275792716183">* Champ obligatoire</translation>
+<translation id="1727613060316725209">Certificat valide</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>
<translation id="173080396488393970">Type de carte non accepté</translation>
@@ -246,7 +253,6 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
votre requête concernant <ph name="SITE" />. Les exploitants de sites peuvent utiliser
des règles d'origine pour en configurer la sécurité et d'autres propriétés.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Mettre à jour votre phrase secrète de synchronisation</translation>
<translation id="1787142507584202372">Les onglets ouverts s'affichent ici</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, plusieurs actions disponibles, appuyez sur Tabulation pour passer de l'une à l'autre</translation>
@@ -279,6 +285,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="1919345977826869612">Annonces</translation>
<translation id="1919367280705858090">Obtenir de l'aide pour un message d'erreur spécifique</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Aucun}=1{1 site}one{# site}other{# sites}}</translation>
+<translation id="1924727005275031552">Nouvelle</translation>
<translation id="1945968466830820669">Vous risquez de perdre l'accès au compte de votre organisation ou d'être victime d'usurpation d'identité. L'équipe Chromium vous recommande de modifier votre mot de passe maintenant.</translation>
<translation id="1947454675006758438">Agrafe en haut à droite</translation>
<translation id="1958218078413065209">Meilleur score : <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="2042213636306070719">Bac 7</translation>
<translation id="204357726431741734">Connectez-vous pour utiliser les mots de passe enregistrés dans votre compte Google</translation>
<translation id="2053111141626950936">Les pages en <ph name="LANGUAGE" /> ne seront pas traduites.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Lorsque cette option est activée et que son état est actif, Chrome détermine le groupe de personnes, ou "cohorte", le plus semblable à votre activité de navigation récente. Les annonceurs peuvent sélectionner des annonces pour ce groupe. Votre activité de navigation restera privée sur cet appareil. Votre groupe est mis à jour tous les jours.}=1{Lorsque cette option est activée et que son état est actif, Chrome détermine le groupe de personnes, ou "cohorte", le plus semblable à votre activité de navigation récente. Les annonceurs peuvent sélectionner des annonces pour ce groupe. Votre activité de navigation restera privée sur cet appareil. Votre groupe est mis à jour tous les jours.}one{Lorsque cette option est activée et que son état est actif, Chrome détermine le groupe de personnes, ou "cohorte", le plus semblable à votre activité de navigation récente. Les annonceurs peuvent sélectionner des annonces pour ce groupe. Votre activité de navigation restera privée sur cet appareil. Votre groupe est mis à jour {NUM_DAYS} fois par jour.}other{Lorsque cette option est activée et que son état est actif, Chrome détermine le groupe de personnes, ou "cohorte", le plus semblable à votre activité de navigation récente. Les annonceurs peuvent sélectionner des annonces pour ce groupe. Votre activité de navigation restera privée sur cet appareil. Votre groupe est mis à jour tous les {NUM_DAYS} jours.}}</translation>
<translation id="2053553514270667976">Code postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggestion}one{# suggestion}other{# suggestions}}</translation>
<translation id="2071692954027939183">Notifications bloquées automatiquement, car vous les refusez d'habitude</translation>
<translation id="2079545284768500474">Annuler</translation>
<translation id="20817612488360358">Les paramètres de proxy du système sont configurés pour être utilisés, mais une configuration de proxy explicite est également spécifiée.</translation>
<translation id="2082238445998314030">Résultat <ph name="RESULT_NUMBER" /> sur <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Enregistrer…</translation>
<translation id="2088086323192747268">Bouton "Gérer la synchronisation" : appuyez sur Entrée pour gérer les infos que vous synchronisez dans les paramètres Chrome</translation>
<translation id="2091887806945687916">Son</translation>
<translation id="2094505752054353250">Le domaine ne correspond pas</translation>
@@ -379,6 +388,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="2317259163369394535"><ph name="DOMAIN" /> nécessite un nom d'utilisateur et un mot de passe.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, arrive à expiration le <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Paramètre contrôlé par votre administrateur</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> tente de s'associer</translation>
<translation id="2344028582131185878">Téléchargements automatiques</translation>
<translation id="2346319942568447007">Image copiée</translation>
<translation id="2354001756790975382">Autres favoris</translation>
@@ -386,8 +396,10 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="2355395290879513365">Il se peut que des pirates informatiques puissent voir les images que vous regardez sur ce site et vous piègent en les modifiant.</translation>
<translation id="2356070529366658676">Demander</translation>
<translation id="2357481397660644965">Votre appareil est géré par <ph name="DEVICE_MANAGER" />, et votre compte par <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Dans moins de 1 jour}=1{Dans 1 jour}one{Dans {NUM_DAYS} jour}other{Dans {NUM_DAYS} jours}}</translation>
<translation id="2359629602545592467">Plusieurs</translation>
<translation id="2359808026110333948">Continuer</translation>
+<translation id="2359961752320758691">Votre numéro de carte virtuelle a été utilisé.</translation>
<translation id="2367567093518048410">Niveau</translation>
<translation id="2372464001869762664">Une fois la validation effectuée, les informations relatives à la carte de votre compte Google seront partagées avec ce site. Recherchez le code CVC dans les informations de votre compte Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="239429038616798445">Mode d'expédition non disponible. Choisissez-en un autre.</translation>
<translation id="2396249848217231973">&amp;Annuler la suppression</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Ancienne</translation>
<translation id="2413528052993050574">Impossible de vérifier sur le serveur qu'il s'agit bien du domaine <ph name="DOMAIN" />. Il se peut que son certificat de sécurité ait été révoqué. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.</translation>
<translation id="2414886740292270097">Sombre</translation>
<translation id="2438874542388153331">Quadruple perforation à droite</translation>
@@ -425,10 +438,10 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="2521385132275182522">Agrafe en bas à droite</translation>
<translation id="2523886232349826891">Enregistrée sur cet appareil uniquement</translation>
<translation id="2524461107774643265">Ajouter des informations</translation>
-<translation id="2526590354069164005">Bureau</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{et 1 autre}one{et # autre}other{et # autres}}</translation>
<translation id="2536110899380797252">Ajouter une adresse</translation>
<translation id="2539524384386349900">Détecter</translation>
+<translation id="2541219929084442027">Les pages consultées dans les onglets de navigation privée ne sont pas enregistrées dans l'historique de votre navigateur, dans les cookies ni dans l'historique des recherches une fois que vous avez fermé tous les onglets de navigation privée. Les fichiers téléchargés et les favoris ajoutés sont conservés.</translation>
<translation id="2544644783021658368">Document unique</translation>
<translation id="254947805923345898">La valeur de la règle n'est pas valide.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> a envoyé une réponse incorrecte.</translation>
@@ -448,6 +461,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="2629325967560697240">Pour bénéficier du niveau de sécurité le plus élevé de Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />activez la protection renforcée<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Impossible de trouver l'adresse IP du serveur de <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">État : </translation>
+<translation id="264810637653812429">Aucun appareil compatible détecté.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" /> : appuyer sur Tabulation, puis sur Entrée pour effacer votre historique de navigation et vos cookies, vider le cache et bien davantage dans les paramètres Chrome</translation>
<translation id="2650446666397867134">Accès au fichier refusé</translation>
@@ -492,6 +506,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<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="2807052079800581569">Position Y de l'image</translation>
+<translation id="2820957248982571256">Recherche…</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>
@@ -499,6 +514,8 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="2850739647070081192">Invite (enveloppe)</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="2859806420264540918">Ce site affiche des annonces intrusives ou trompeuses.</translation>
+<translation id="287596039013813457">Amical</translation>
+<translation id="2876489322757410363">En payant via une appli externe, vous allez quitter le mode navigation privée. Voulez-vous continuer ?</translation>
<translation id="2878197950673342043">Pli au format affiche</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Positionnement des fenêtres</translation>
@@ -548,7 +565,6 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="3060227939791841287">C9 (enveloppe)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" /> : appuyez sur Tabulation, puis sur Entrée pour effectuer un contrôle de sécurité dans les paramètres de Chrome</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>
<translation id="306573536155379004">Le jeu a commencé.</translation>
<translation id="3080254622891793721">Image</translation>
<translation id="3086579638707268289">Votre activité sur le Web est surveillée</translation>
@@ -571,7 +587,6 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="315504272643575312">Votre compte est géré par <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Restaurer</translation>
<translation id="3162559335345991374">Pour utiliser ce réseau Wi-Fi, il est possible que vous deviez vous rendre sur la page de connexion correspondante.</translation>
-<translation id="3167968892399408617">Les pages consultées dans les onglets de navigation privée ne sont pas enregistrées dans l'historique de votre navigateur, dans les cookies ni dans l'historique des recherches une fois que vous avez fermé tous les onglets de navigation privée. Les fichiers téléchargés et les favoris ajoutés sont conservés.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">ÃŽle</translation>
<translation id="3176929007561373547">Vérifiez vos paramètres de proxy ou contactez votre administrateur réseau pour
@@ -597,10 +612,12 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<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="3249845759089040423">Tendance</translation>
<translation id="3252266817569339921">Français</translation>
<translation id="3266793032086590337">Valeur (conflit)</translation>
<translation id="3268451620468152448">Onglets ouverts</translation>
<translation id="3270847123878663523">&amp;Annuler la réorganisation</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> tente de se connecter</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Votre organisation, <ph name="ENROLLMENT_DOMAIN" />, a envoyé des infos, comme des paramètres ou des règles, aux sites Web suivants.</translation>
<translation id="3282497668470633863">Ajouter le nom sur la carte</translation>
@@ -653,6 +670,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="3428151540071562330">Au moins un URI de modèle de serveur DnsOverHttpsTemplates n'est pas valide et ne sera pas utilisé.</translation>
<translation id="3431636764301398940">Enregistrer cette carte sur cet appareil</translation>
<translation id="3432601291244612633">Fermer la page</translation>
+<translation id="3435738964857648380">Sécurité</translation>
<translation id="3435896845095436175">Activer</translation>
<translation id="3438829137925142401">Utiliser les mots de passe enregistrés dans votre compte Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -695,7 +713,10 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="3584299510153766161">Double perforation en bas</translation>
<translation id="3586931643579894722">Masquer les détails</translation>
<translation id="3587738293690942763">Milieu</translation>
+<translation id="3590643883886679995">Les données de connexion seront stockées sur l'appareil lorsque vous aurez quitté le mode navigation privée.</translation>
+<translation id="359126217934908072">Mois/Année :</translation>
<translation id="3592413004129370115">Italian (enveloppe)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Vous pouvez réinitialiser votre groupe à tout moment. Comptez environ une journée pour rejoindre un nouveau groupe.}=1{Vous pouvez réinitialiser votre groupe à tout moment. Comptez environ une journée pour rejoindre un nouveau groupe.}one{Vous pouvez réinitialiser votre groupe à tout moment. Comptez {NUM_DAYS} jour pour rejoindre un nouveau groupe.}other{Vous pouvez réinitialiser votre groupe à tout moment. Comptez {NUM_DAYS} jours pour rejoindre un nouveau groupe.}}</translation>
<translation id="3600246354004376029">"<ph name="TITLE" />", <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Application bloquée par votre administrateur</translation>
<translation id="3608932978122581043">Orientation de l'alimentation</translation>
@@ -704,13 +725,13 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="3615877443314183785">Saisissez une date d'expiration valide</translation>
<translation id="36224234498066874">Effacer les données de navigation...</translation>
<translation id="362276910939193118">Afficher l'historique complet</translation>
-<translation id="3625635938337243871">Les données de connexion seront stockées sur l'appareil lorsque vous quitterez le mode navigation privée.</translation>
<translation id="3630155396527302611">S'il est déjà répertorié en tant que programme autorisé à accéder au réseau,
essayez de le supprimer de la liste, puis de le rajouter.</translation>
<translation id="3630699740441428070">Les administrateurs de cet appareil ont configuré votre connexion réseau grâce à laquelle ils ont la possibilité d'afficher le trafic de votre réseau, y compris les sites Web que vous consultez.</translation>
<translation id="3631244953324577188">Biométrie</translation>
<translation id="3633738897356909127">Bouton "Mise à jour de Chrome" : appuyer sur Entrée pour mettre à jour Chrome depuis les paramètres du navigateur</translation>
<translation id="3634530185120165534">Bac 5</translation>
+<translation id="3637662659967048211">Enregistrer dans le compte Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Application :</translation>
<translation id="3650584904733503804">Validation réussie.</translation>
@@ -751,6 +772,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="3781428340399460090">Rose foncé</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Appareils Bluetooth</translation>
+<translation id="3787675388804467730">Numéro de carte virtuelle</translation>
<translation id="3787705759683870569">Expire en <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Taille 16</translation>
<translation id="3789841737615482174">Installer</translation>
@@ -770,6 +792,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="3841184659773414994">Gestionnaires de fichiers</translation>
<translation id="385051799172605136">Retour</translation>
<translation id="3858027520442213535">Mettre à jour la date et l'heure</translation>
+<translation id="3881478300875776315">Afficher moins de lignes</translation>
<translation id="3884278016824448484">Identifiant de l'appareil en conflit.</translation>
<translation id="3885155851504623709">Paroisse</translation>
<translation id="388632593194507180">Activité de surveillance détectée</translation>
@@ -795,6 +818,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="397105322502079400">Calcul en cours…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> est bloqué</translation>
<translation id="3973357910713125165">Bouton "Effectuer un contrôle de sécurité de Chrome" : appuyez sur Entrée pour effectuer un contrôle de sécurité dans les paramètres de Chrome</translation>
+<translation id="3986705137476756801">Désactiver les sous-titres instantanés pour le moment</translation>
<translation id="3987405730340719549">Chrome a établi que ce site pouvait être fictif ou frauduleux.
Si vous pensez que ce message est affiché par erreur, veuillez consulter la page https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -891,13 +915,14 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="4275830172053184480">Redémarrer l'appareil</translation>
<translation id="4277028893293644418">Réinitialiser le mot de passe</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="4287885627794386150">Essai possible, mais non actif</translation>
<translation id="4297502707443874121">Vignette de la page <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Développer</translation>
<translation id="4300675098767811073">Multiple perforation à droite</translation>
<translation id="4302514097724775343">Appuyez sur le dinosaure pour jouer</translation>
<translation id="4302965934281694568">Chou3 (enveloppe)</translation>
<translation id="4305666528087210886">Impossible d'accéder à votre fichier</translation>
-<translation id="4305817255990598646">Changer</translation>
+<translation id="4306529830550717874">Enregistrer l'adresse ?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloquer (par défaut)</translation>
<translation id="4314815835985389558">Gérer la synchronisation</translation>
@@ -924,6 +949,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="4377125064752653719">Vous avez tenté d'accéder à <ph name="DOMAIN" />, mais le certificat présenté par le serveur a été révoqué par son émetteur. Cela signifie que le certificat présenté par le serveur ne doit pas être approuvé. Il est donc possible que vous communiquiez avec un pirate informatique.</translation>
<translation id="4378154925671717803">Téléphone</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Sous-titres instantanés</translation>
<translation id="4406896451731180161">résultats de recherche</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Vous venez de saisir votre mot de passe sur un site trompeur. Chrome vous recommande d'accéder à <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> et <ph name="WEBSITE_3" />, ainsi qu'aux autres sites sur lesquels vous utilisez ce mot de passe pour le modifier immédiatement.</translation>
@@ -936,7 +962,6 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<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="4464826014807964867">Sites Web avec des infos fournies par votre organisation</translation>
-<translation id="4466881336512663640">Les modifications apportées au formulaire seront perdues. Voulez-vous vraiment continuer ?</translation>
<translation id="4476953670630786061">Ce formulaire n'est pas sécurisé. La saisie automatique a été désactivée.</translation>
<translation id="4477350412780666475">Titre suivant</translation>
<translation id="4482953324121162758">Ce site ne sera pas traduit.</translation>
@@ -970,6 +995,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="4594403342090139922">&amp;Annuler la suppression</translation>
<translation id="4597348597567598915">Taille 8</translation>
<translation id="4600854749408232102">C6/C5 (enveloppe)</translation>
+<translation id="4606870351894164739">Percutant</translation>
<translation id="4628948037717959914">Photo</translation>
<translation id="4631649115723685955">Avec cashback</translation>
<translation id="4636930964841734540">Infos</translation>
@@ -989,6 +1015,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="4691835149146451662">Architecture-A (enveloppe)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Côté</translation>
+<translation id="4702656508969495934">Sous-titres instantanés visibles, utilisez le permuteur de fenêtres pour déplacer le curseur</translation>
<translation id="4708268264240856090">Votre connexion a été interrompue</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Exécutez les diagnostics réseau de Windows<ph name="END_LINK" /></translation>
@@ -1002,6 +1029,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="4738601419177586157">Suggestion de recherche sur "<ph name="TEXT" />"</translation>
<translation id="4742407542027196863">Gérer les mots de passe…</translation>
<translation id="4744603770635761495">Chemin d'accès exécutable</translation>
+<translation id="4749011317274908093">Vous êtes passé en navigation privée</translation>
<translation id="4750917950439032686">Vos informations, comme vos mots de passe ou vos numéros de carte de paiement, sont privées lorsqu'elles sont transmises à ce site.</translation>
<translation id="4756388243121344051">&amp;Historique</translation>
<translation id="4758311279753947758">Ajouter des coordonnées</translation>
@@ -1031,6 +1059,8 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="4813512666221746211">Erreur réseau.</translation>
<translation id="4816492930507672669">Ajuster à la page</translation>
<translation id="4819347708020428563">Modifier les annotations dans la vue par défaut ?</translation>
+<translation id="4825507807291741242">Puissant</translation>
+<translation id="4838327282952368871">Rêveur</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">Afficher</translation>
<translation id="485316830061041779">Allemand</translation>
@@ -1167,6 +1197,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="5314967030527622926">Créateur de brochures</translation>
<translation id="5316812925700871227">Faire pivoter vers la gauche</translation>
<translation id="5317780077021120954">Enregistrer</translation>
+<translation id="5321288445143113935">Taille maximale</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> sur <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Sélectionner les coordonnées</translation>
<translation id="5327248766486351172">Nom</translation>
@@ -1174,11 +1205,13 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="5332219387342487447">Mode de livraison</translation>
<translation id="5333022057423422993">Chrome a trouvé le mot de passe que vous venez d'utiliser lors d'une violation de données. Pour la sécurité de vos comptes, nous vous recommandons de vérifier immédiatement vos mots de passe enregistrés.</translation>
<translation id="5334013548165032829">Journaux système détaillés</translation>
+<translation id="5334145288572353250">Enregistrer l'adresse ?</translation>
<translation id="5340250774223869109">Application bloquée</translation>
<translation id="534295439873310000">Appareils NFC</translation>
<translation id="5344579389779391559">L'accès à la page suivante peut engendrer des frais</translation>
<translation id="5355557959165512791">Le site <ph name="SITE" /> est actuellement inaccessible, car son certificat a été révoqué. 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="536296301121032821">Échec du stockage des paramètres de la règle.</translation>
+<translation id="5363309033720083897">Port série autorisé par votre administrateur</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="5386426401304769735">La chaîne de certificats de ce site contient un certificat signé avec SHA-1.</translation>
@@ -1187,6 +1220,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="5398772614898833570">Annonces bloquées</translation>
<translation id="5400836586163650660">Gris</translation>
<translation id="540969355065856584">Impossible de vérifier que ce serveur est bien <ph name="DOMAIN" />, car son certificat de sécurité actuel n'est pas valide. Cela peut être dû à une mauvaise configuration ou bien à l'interception de votre connexion par un pirate informatique.</translation>
+<translation id="541143247543991491">Cloud (tout le système)</translation>
<translation id="541416427766103491">Empileur 4</translation>
<translation id="5421136146218899937">Effacer les données de navigation...</translation>
<translation id="5426179911063097041">"<ph name="SITE" />" souhaite vous envoyer des notifications</translation>
@@ -1200,6 +1234,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="5455374756549232013">Horodatage de la règle incorrect.</translation>
<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="5463625433003343978">Recherche d'appareils…</translation>
<translation id="5469868506864199649">Italien</translation>
<translation id="5470861586879999274">&amp;Rétablir la modification</translation>
<translation id="5478437291406423475">B6/C4 (enveloppe)</translation>
@@ -1249,7 +1284,6 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="5624120631404540903">Gérer les mots de passe</translation>
<translation id="5629630648637658800">Échec du chargement des paramètres de la règle.</translation>
<translation id="5631439013527180824">Jeton de gestion de l'appareil non valide.</translation>
-<translation id="5632627355679805402">Vos données ont été chiffrées avec votre <ph name="BEGIN_LINK" />mot de passe Google<ph name="END_LINK" /> depuis le <ph name="TIME" />. Saisissez-le pour lancer la synchronisation.</translation>
<translation id="5633066919399395251">Des individus malveillants à l'œuvre sur le site <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> pourraient tenter d'installer des programmes dangereux sur votre ordinateur afin de récupérer ou de supprimer certaines informations (photos, 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="563324245173044180">Contenu trompeur bloqué.</translation>
<translation id="5644090287519800334">Décalage X de l'image côté 1</translation>
@@ -1288,12 +1322,12 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="5785756445106461925">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 l'aspect de cette page.</translation>
<translation id="5786044859038896871">Souhaitez-vous indiquer vos informations de carte de paiement ?</translation>
<translation id="578633867165174378">Chrome a trouvé le mot de passe que vous venez d'utiliser lors d'une violation de données. Nous vous recommandons de le modifier immédiatement.</translation>
-<translation id="5798290721819630480">Supprimer les modifications ?</translation>
<translation id="5803412860119678065">Souhaitez-vous indiquer les informations "<ph name="CARD_DETAIL" />" ?</translation>
<translation id="5804241973901381774">Autorisations</translation>
<translation id="5804427196348435412">Utiliser des appareils NFC</translation>
<translation id="5810442152076338065">Votre connexion à <ph name="DOMAIN" /> est chiffrée à l'aide d'une méthode de chiffrement obsolète.</translation>
<translation id="5813119285467412249">&amp;Rétablir l'ajout</translation>
+<translation id="5817918615728894473">Associer</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Cette carte sera débitée lorsque vous effectuerez un paiement, mais son vrai numéro ne sera pas communiqué à ce site. Pour plus de sécurité, un code CVC provisoire sera généré.}one{La carte que vous aurez sélectionnée sera débitée lorsque vous effectuerez un paiement, mais son vrai numéro ne sera pas communiqué à ce site. Pour plus de sécurité, un code CVC provisoire sera généré.}other{Les cartes que vous aurez sélectionnées seront débitées lorsque vous effectuerez des paiements, mais leur vrai numéro ne sera pas communiqué à ce site. Pour plus de sécurité, un code CVC provisoire sera généré.}}</translation>
<translation id="5826507051599432481">Nom commun (CN)</translation>
<translation id="5838278095973806738">Vous ne devriez pas saisir d'informations sensibles sur ce site (par exemple, vos mots de passe ou les informations de votre carte de paiement), car elles risquent d'être dérobées par des pirates informatiques.</translation>
@@ -1301,6 +1335,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="5855253129151731373">Le nom d'hôte de ce site ressemble à <ph name="LOOKALIKE_DOMAIN" />. Les pirates informatiques tentent parfois d'imiter des sites Web en modifiant le nom de domaine de façon subtile pour que le changement passe inaperçu.
Si vous pensez que ce message est affiché par erreur, veuillez consulter la page https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Désactivé</translation>
<translation id="5862579898803147654">Empileur 8</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>
@@ -1317,6 +1352,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="5913377024445952699">Capture d'écran mise en pause</translation>
<translation id="59174027418879706">Activé</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 en cours d'utilisation}one{# en cours d'utilisation}other{# en cours d'utilisation}}</translation>
<translation id="5921185718311485855">Activé</translation>
<translation id="5921639886840618607">Enregistrer la carte dans votre compte Google ?</translation>
<translation id="5922853866070715753">Vous avez presque terminé !</translation>
@@ -1336,6 +1372,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="5989320800837274978">Aucun serveur proxy déterminé ou URL de script .pac n'a été indiqué.</translation>
<translation id="5992691462791905444">Technique de pli en Z</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> résultats pour "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Classique</translation>
<translation id="6008122969617370890">Ordre N à 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Vérifier vos mots de passe</translation>
@@ -1357,6 +1394,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="6045164183059402045">Modèle d'imposition</translation>
<translation id="6047233362582046994">Si vous êtes conscient des risques auxquels vous vous exposez, vous pouvez <ph name="BEGIN_LINK" />consulter ce site<ph name="END_LINK" /> avant que les applications dangereuses aient été supprimées.</translation>
<translation id="6047927260846328439">Ce contenu peut vous inciter à installer un logiciel ou vous soutirer des informations personnelles. <ph name="BEGIN_LINK" />Je souhaite y accéder malgré tout.<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Appuyez de manière prolongée sur |<ph name="ACCELERATOR" />| pour quitter le mode plein écran</translation>
<translation id="6049488691372270142">Livraison de la page</translation>
<translation id="6051221802930200923">Le site <ph name="SITE" /> est actuellement inaccessible, car il utilise l'épinglage des certificats. 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="6051898664905071243">Nombre de pages :</translation>
@@ -1373,6 +1411,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<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>
<translation id="6116338172782435947">Voir le texte et les images copiés dans le presse-papiers</translation>
<translation id="6120179357481664955">Souhaitez-vous mémoriser votre ID UPI ?</translation>
+<translation id="6123290840358279103">Afficher la carte virtuelle</translation>
<translation id="6124432979022149706">Connecteurs Chrome Enterprise</translation>
<translation id="6146055958333702838">Vérifiez les câbles et redémarrez votre routeur, votre modem
ou tout autre périphérique réseau utilisé.</translation>
@@ -1409,6 +1448,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="6289939620939689042">Couleur de la page</translation>
<translation id="6290238015253830360">Vos suggestions d'articles s'affichent ici</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">Cryptogramme :</translation>
<translation id="6302269476990306341">Arrêt de l'Assistant Google dans Chrome</translation>
<translation id="6305205051461490394"><ph name="URL" /> est inaccessible.</translation>
<translation id="6312113039770857350">Page Web non disponible</translation>
@@ -1434,6 +1474,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="6390200185239044127">Demi-feuille de pli en Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Le règlement de l'administrateur bloque le collage de contenus provenant de "<ph name="ORIGIN_NAME" />" à cet endroit</translation>
+<translation id="6398765197997659313">Quitter le mode plein écran</translation>
<translation id="6401136357288658127">Cette règle est obsolète. Vous devez utiliser la règle "<ph name="NEW_POLICY" />" à la place.</translation>
<translation id="6404511346730675251">Modifier le favori</translation>
<translation id="6406765186087300643">C0 (enveloppe)</translation>
@@ -1446,7 +1487,6 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="6428450836711225518">Validez votre numéro de téléphone</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">Supprimer</translation>
<translation id="6440503408713884761">Ignoré</translation>
<translation id="6443406338865242315">Les extensions et les plug-ins que vous avez installés</translation>
<translation id="6446163441502663861">Kahu (enveloppe)</translation>
@@ -1489,6 +1529,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="6624427990725312378">Coordonnées</translation>
<translation id="6626291197371920147">Ajouter un numéro de carte valide</translation>
<translation id="6628463337424475685">Recherche <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Recherche d'appareils USB…</translation>
<translation id="6630809736994426279">Des individus malveillants à l'œuvre sur le site <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> pourraient tenter d'installer des programmes dangereux sur votre Mac afin de récupérer ou de supprimer certaines informations (photos, 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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Effacer</translation>
@@ -1504,6 +1545,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<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="6687335167692595844">Taille de police demandée</translation>
+<translation id="6688743156324860098">Modifier…</translation>
<translation id="6689249931105087298">Valeur relative avec compression des points noirs</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="6698381487523150993">Créé :</translation>
@@ -1519,6 +1561,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<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="6753269504797312559">Valeur de la règle</translation>
<translation id="6757797048963528358">Votre appareil s'est mis en veille.</translation>
+<translation id="6767985426384634228">Modifier l'adresse ?</translation>
<translation id="6768213884286397650">Hagaki (carte postale)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Mauve</translation>
@@ -1541,6 +1584,7 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome a simplifié cette page pour qu'elle soit plus facile à lire. La page d'origine a été récupérée au moyen d'une connexion non sécurisée.</translation>
<translation id="6891596781022320156">Le niveau de la règle n'est pas accepté.</translation>
+<translation id="6895143722905299846">Numéro virtuel :</translation>
<translation id="6895330447102777224">Carte validée</translation>
<translation id="6897140037006041989">Agent utilisateur</translation>
<translation id="6898699227549475383">Organisation (O)</translation>
@@ -1576,10 +1620,10 @@ Par défaut, ce type d'accès est bloqué par vos paramètres de confidentialitÃ
<translation id="7004583254764674281">Utiliser Windows Hello pour confirmer les cartes plus rapidement</translation>
<translation id="7006930604109697472">Envoyer quand même</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Paramètres de redimensionnement</translation>
<translation id="7014741021609395734">Niveau de zoom</translation>
<translation id="7016992613359344582">Il peut s'agir de frais uniques ou récurrents qui ne sont pas toujours clairement signalés.</translation>
<translation id="7029809446516969842">Mots de passe</translation>
+<translation id="7030436163253143341">Certificat non valide</translation>
<translation id="7031646650991750659">Les applications Google Play que vous avez installées</translation>
<translation id="7050187094878475250">Vous avez essayé d'accéder à <ph name="DOMAIN" />, mais la durée de validité du certificat du serveur est trop longue pour être fiable.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Impossible d'enregistrer cette carte pour le moment}one{Impossible d'enregistrer cette carte pour le moment}other{Impossible d'enregistrer ces cartes pour le moment}}</translation>
@@ -1649,12 +1693,14 @@ Informations supplémentaires :
<translation id="7300012071106347854">Bleu cobalt</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Aigu</translation>
+<translation id="7305756307268530424">Vitesse plus lente</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Aide à la connexion</translation>
<translation id="7323804146520582233">Masquer la section "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Ignorer le compte local de l'appareil</translation>
<translation id="7333654844024768166">Vous venez de saisir votre mot de passe sur un site trompeur. Chromium vous recommande d'accéder à <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> et <ph name="WEBSITE_3" />, ainsi qu'aux autres sites sur lesquels vous utilisez ce mot de passe pour le modifier immédiatement.</translation>
<translation id="7334320624316649418">&amp;Rétablir la réorganisation</translation>
+<translation id="7337248890521463931">Afficher plus de lignes</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>
@@ -1662,6 +1708,7 @@ Informations supplémentaires :
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Ligne de commande</translation>
<translation id="7359588939039777303">Annonces bloquées.</translation>
+<translation id="7363096869660964304">Cela ne vous rend pas invisible pour autant. Si vous passez en navigation privée, votre employeur, votre fournisseur d'accès à Internet ou les sites Web que vous consultez pourront toujours avoir accès à votre navigation.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" /> : appuyez sur Tabulation, puis sur Entrée pour gérer les adresses et en ajouter dans les paramètres Chrome</translation>
<translation id="7365849542400970216">Savoir si vous utilisez cet appareil ?</translation>
<translation id="7372973238305370288">résultat de recherche</translation>
@@ -1672,7 +1719,9 @@ Informations supplémentaires :
<translation id="7378594059915113390">Commandes multimédias</translation>
<translation id="7378627244592794276">Non</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Non applicable</translation>
<translation id="7390545607259442187">Valider la carte</translation>
+<translation id="7392089738299859607">Modifier l'adresse</translation>
<translation id="7399802613464275309">Contrôle de sécurité</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Votre <ph name="DEVICE_NAME" /> est géré</translation>
@@ -1687,6 +1736,7 @@ Informations supplémentaires :
&lt;li&gt;Pour savoir comment supprimer définitivement le logiciel de votre ordinateur, consultez le &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centre d'aide Chrome&lt;/a&gt;
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Joli</translation>
<translation id="7416351320495623771">Gérer les mots de passe…</translation>
<translation id="7419106976560586862">Chemin d'accès au profil</translation>
<translation id="7437289804838430631">Ajouter des coordonnées</translation>
@@ -1702,7 +1752,7 @@ Informations supplémentaires :
<translation id="7481312909269577407">Avancer</translation>
<translation id="7485870689360869515">Aucune donnée n'a été trouvée.</translation>
<translation id="7495528107193238112">Ce contenu est bloqué. Pour résoudre le problème, contactez le propriétaire du site.</translation>
-<translation id="7498234416455752244">Poursuivre les modifications</translation>
+<translation id="7498193950643227031">Elle peut se comporter de façon inattendue si elle est redimensionnée. Vous pouvez limiter la capacité à redimensionner les applis dans <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Vous venez de saisir votre mot de passe sur un site trompeur. Chromium vous recommande de vérifier vos mots de passe enregistrés pour <ph name="WEBSITE_1" /> et <ph name="WEBSITE_2" />, ainsi que les autres sites pour lesquels vous utilisez ce mot de passe actuellement.</translation>
<translation id="7508255263130623398">L'ID d'appareil de la règle renvoyé est vide ou ne correspond pas à l'ID d'appareil actuel.</translation>
<translation id="7508870219247277067">Vert avocat</translation>
@@ -1722,6 +1772,7 @@ Informations supplémentaires :
<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="755279583747225797">Essai actif</translation>
<translation id="7552846755917812628">Essayez les astuces suivantes :</translation>
<translation id="7554475479213504905">Relancer et afficher malgré tout</translation>
<translation id="7554791636758816595">Nouvel onglet</translation>
@@ -1740,7 +1791,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" /> : appuyer sur Tabulation, puis sur Entrée pour consulter et gérer vos mots de passe dans les paramètres Chrome</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="7616645509853975347">Votre administrateur a activé ces connecteurs dans votre navigateur, lesquels ont accès à certaines de vos données.</translation>
<translation id="7619838219691048931">Feuille de fin</translation>
<translation id="762844065391966283">Un à la fois</translation>
@@ -1805,13 +1855,12 @@ Informations supplémentaires :
<translation id="782886543891417279">Pour utiliser ce réseau Wi-Fi (<ph name="WIFI_NAME" />), il est possible que vous deviez vous rendre sur la page de connexion correspondante.</translation>
<translation id="7836231406687464395">Postfix (enveloppe)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Aucune}=1{1 application (<ph name="EXAMPLE_APP_1" />)}=2{2 applications (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# application (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# applications (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Cependant, cela ne vous rend pas invisible. Si vous passez en mode navigation privée, votre employeur, votre fournisseur d'accès à Internet ou les sites Web que vous consultez pourront toujours avoir accès à votre historique de navigation.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> : <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Ouvrir certains types de fichiers.</translation>
<translation id="7862185352068345852">Quitter le site Web ?</translation>
<translation id="7865448901209910068">Vitesse optimale</translation>
<translation id="7874263914261512992">Vous venez de saisir votre mot de passe sur un site trompeur. Chrome vous recommande de vérifier vos mots de passe enregistrés pour <ph name="WEBSITE_1" /> et <ph name="WEBSITE_2" />, ainsi que les autres sites pour lesquels vous utilisez ce mot de passe actuellement.</translation>
<translation id="7878562273885520351">Votre mot de passe a peut-être été piraté</translation>
+<translation id="7880146494886811634">Enregistrer l'adresse</translation>
<translation id="7882421473871500483">Marron</translation>
<translation id="7887683347370398519">Veuillez vérifier votre code CVC et réessayer.</translation>
<translation id="7887885240995164102">Utiliser le mode Picture-in-picture</translation>
@@ -1819,6 +1868,7 @@ Informations supplémentaires :
<translation id="7894280532028510793">S'il n'y a pas d'erreur, essayez de <ph name="BEGIN_LINK" />faire un diagnostic réseau<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (enveloppe)</translation>
<translation id="7931318309563332511">Langue source inconnue</translation>
+<translation id="793209273132572360">Modifier l'adresse ?</translation>
<translation id="7932579305932748336">Revêtement</translation>
<translation id="79338296614623784">Saisissez un numéro de téléphone valide</translation>
<translation id="7934052535022478634">Paiement effectué</translation>
@@ -1889,6 +1939,7 @@ Informations supplémentaires :
<translation id="8175796834047840627">Chrome propose d'enregistrer vos cartes dans votre compte Google, car vous êtes connecté. Vous pouvez modifier ce comportement dans les paramètres.</translation>
<translation id="8176440868214972690">L'administrateur de cet appareil a envoyé des infos, comme des paramètres ou des règles, aux sites Web suivants.</translation>
<translation id="8184538546369750125">Utiliser le paramètre global par défaut ("Autoriser")</translation>
+<translation id="8193086767630290324">Actions effectuées sur des données signalées comme confidentielles</translation>
<translation id="8194797478851900357">&amp;Annuler le déplacement</translation>
<translation id="8201077131113104583">URL de mise à jour non valide pour l'extension associée à l'identifiant "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Récapitulatif de la commande</translation>
@@ -1911,6 +1962,7 @@ Informations supplémentaires :
<translation id="8249296373107784235">Annuler</translation>
<translation id="8249320324621329438">Dernière récupération : </translation>
<translation id="8253091569723639551">Adresse de facturation obligatoire</translation>
+<translation id="8257387598443225809">Cette appli est conçue pour les mobiles</translation>
<translation id="825929999321470778">Afficher tous les mots de passe enregistrés</translation>
<translation id="8261506727792406068">Supprimer</translation>
<translation id="8262952874573525464">Agrafage par le bord inférieur</translation>
@@ -2034,7 +2086,6 @@ Informations supplémentaires :
<translation id="8719528812645237045">Multiple perforation en haut</translation>
<translation id="8725066075913043281">Réessayer</translation>
<translation id="8726549941689275341">Format de page :</translation>
-<translation id="8728672262656704056">Vous êtes passé en mode navigation privée</translation>
<translation id="8730621377337864115">OK</translation>
<translation id="8731544501227493793">Bouton "Gérer les mots de passe" : appuyer sur Entrée pour consulter et gérer vos mots de passe dans les paramètres Chrome</translation>
<translation id="8734529307927223492">Votre <ph name="DEVICE_TYPE" /> est géré par <ph name="MANAGER" /></translation>
@@ -2111,6 +2162,7 @@ Informations supplémentaires :
<translation id="9020542370529661692">Cette page a été traduite en <ph name="TARGET_LANGUAGE" />.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Non valide)</translation>
+<translation id="9030265603405983977">Monochrome</translation>
<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>
@@ -2134,6 +2186,7 @@ Informations supplémentaires :
<translation id="91108059142052966">Les règles définies par l'administrateur désactivent le partage d'écran avec <ph name="APPLICATION_TITLE" /> lorsque le contenu affiché est confidentiel</translation>
<translation id="9114524666733003316">Validation de la carte…</translation>
<translation id="9114581008513152754">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="9117930699067497412">Frais</translation>
<translation id="9119042192571987207">Importation terminée</translation>
<translation id="9128016270925453879">Les règles sont chargées</translation>
<translation id="9128870381267983090">Connectez-vous au réseau</translation>
@@ -2152,6 +2205,7 @@ Informations supplémentaires :
<translation id="9170848237812810038">Ann&amp;uler</translation>
<translation id="9171296965991013597">Quitter l'application ?</translation>
<translation id="9173282814238175921">Document unique/Nouvelle feuille</translation>
+<translation id="9173995187295789444">Recherche d'appareils Bluetooth…</translation>
<translation id="917450738466192189">Le certificat du serveur n'est pas valide.</translation>
<translation id="9174917557437862841">Bouton pour changer d'onglet, appuyez sur Entrée pour passer à cet onglet</translation>
<translation id="9179703756951298733">Gérez vos paiements et les informations sur vos cartes de crédit dans les paramètres Chrome</translation>
diff --git a/chromium/components/strings/components_strings_gl.xtb b/chromium/components/strings/components_strings_gl.xtb
index b3bb5387ab3..e1685a8a63d 100644
--- a/chromium/components/strings/components_strings_gl.xtb
+++ b/chromium/components/strings/components_strings_gl.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Se se comproba, Chrome almacenará unha copia da túa tarxeta neste dispositivo para completar os formularios máis rápido.</translation>
<translation id="1110994991967754504">Seleccionar permiso para <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Desfacer o cambio de orde</translation>
+<translation id="1123753900084781868">A función Subtítulos instantáneos non está dispoñible nestes intres</translation>
<translation id="1125573121925420732">Podes ver avisos con frecuencia mentres os sitios web actualizan os seus sistemas de seguranza, pero a situación mellorará en breve.</translation>
<translation id="112840717907525620">Caché de política correcta</translation>
<translation id="1130564665089811311">Botón Traducir páxina, preme Intro para traducir esta páxina co Tradutor de Google</translation>
@@ -74,6 +75,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="1240347957665416060">O nome do teu dispositivo</translation>
<translation id="124116460088058876">Máis idiomas</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Negra</translation>
<translation id="1250759482327835220">Para pagar máis rápido a próxima vez, garda a túa tarxeta, o nome e o enderezo de facturación na túa Conta de Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" /> e <ph name="TYPE_2" /> (sincronizado)</translation>
<translation id="1256368399071562588">&lt;p&gt;Se tentas visitar un sitio web e non abre, proba estes pasos para solucionar problemas:&lt;/p&gt;
@@ -156,6 +158,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="1476595624592550506">Cambia o teu contrasinal</translation>
<translation id="1484290072879560759">Escoller enderezo de envío</translation>
<translation id="1492194039220927094">Aplicación de políticas:</translation>
+<translation id="1495677929897281669">Volver á pestana</translation>
<translation id="1501859676467574491">Mostra tarxetas da túa Conta de Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Verás este erro se utilizas un portal wifi no que tes que iniciar sesión para poder conectarte a Internet.&lt;/p&gt;
&lt;p&gt;Para solucionar o erro, fai clic en &lt;strong&gt;Conectar&lt;/strong&gt; na páxina que tentas abrir.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="1532118530259321453">Esta páxina di</translation>
<translation id="153384715582417236">Isto é todo polo momento</translation>
<translation id="1536390784834419204">Traducir páxina</translation>
+<translation id="1539840569003678498">Envío do informe:</translation>
<translation id="154408704832528245">Escoller enderezo de entrega</translation>
<translation id="1549470594296187301">JavaScript debe estar activado para usar esta función.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="1682696192498422849">Co bordo curto primeiro</translation>
<translation id="168693727862418163">Non puido cotexarse o valor desta política co seu esquema para levar a cabo a súa validación, así que se ignorará.</translation>
<translation id="168841957122794586">O certificado do servidor contén unha clave criptográfica non segura.</translation>
+<translation id="1696290444144917273">Ver detalles da tarxeta virtual</translation>
<translation id="1697532407822776718">Listo!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Este servidor non puido demostrar que é <ph name="DOMAIN" /> porque o seu certificado de seguranza supostamente é válido a partir de mañá. É posible que isto se deba a un erro de configuración ou a que un atacante interceptase a túa conexión.}other{Este servidor non puido demostrar que é <ph name="DOMAIN" /> porque o seu certificado de seguranza supostamente é válido dentro de # días. É posible que isto se deba a un erro de configuración ou a que un atacante interceptase a túa conexión.}}</translation>
<translation id="1710259589646384581">Sistema operativo</translation>
+<translation id="1711234383449478798">Ignorouse porque a política <ph name="POLICY_NAME" /> non se definiu co valor <ph name="VALUE" />.</translation>
<translation id="1712552549805331520">O URL <ph name="URL" /> quere almacenar datos de forma permanente no teu ordenador local</translation>
<translation id="1713628304598226412">Bandexa 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Caixa de correo 3</translation>
<translation id="1718029547804390981">O documento é demasiado grande para anotalo</translation>
<translation id="1721424275792716183">* O campo é obrigatorio</translation>
+<translation id="1727613060316725209">O certificado é válido</translation>
<translation id="1727741090716970331">Engade un número de tarxeta válido</translation>
<translation id="1728677426644403582">Estas vendo a fonte dunha páxina web</translation>
<translation id="173080396488393970">Este tipo de tarxeta non é compatible</translation>
@@ -245,7 +252,6 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
obstante, o título ten un formato incorrecto, o que impide que o navegador complete
a solicitude de <ph name="SITE" />. Os operadores dos sitios poden utilizar as políticas de orixe para configurar a seguranza e outras propiedades dos sitios.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Actualiza a túa frase de acceso de sincronización.</translation>
<translation id="1787142507584202372">As pestanas abertas aparecerán aquí</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Hai varias accións dispoñibles; para desprazarte por elas, preme Tab</translation>
@@ -278,6 +284,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="1919345977826869612">Anuncios</translation>
<translation id="1919367280705858090">Obter axuda cando aparece unha mensaxe de erro concreta</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ningún}=1{1 sitio}other{# sitios}}</translation>
+<translation id="1924727005275031552">Novo</translation>
<translation id="1945968466830820669">Poderías perder o acceso á conta da túa organización ou alguén podería roubarche a identidade. Chromium recoméndache que cambies de contrasinal agora.</translation>
<translation id="1947454675006758438">Grampa na parte superior dereita</translation>
<translation id="1958218078413065209">A túa máxima puntuación é <ph name="SCORE" />.</translation>
@@ -300,12 +307,14 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="2042213636306070719">Bandexa 7</translation>
<translation id="204357726431741734">Iniciar sesión para utilizar contrasinais gardados na túa Conta de Google</translation>
<translation id="2053111141626950936">Non se traducirán as páxinas en <ph name="LANGUAGE" />.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Cando este control está habilitado e co estado activo, Chrome determina con que grupo grande de persoas ou "cohorte" concorda máis a túa actividade de navegación recente. Os anunciantes poden seleccionar anuncios para o grupo, e a túa actividade de navegación mantense privada no dispositivo. O teu grupo actualízase a diario.}=1{Cando este control está habilitado e co estado activo, Chrome determina con que grupo grande de persoas ou "cohorte" concorda máis a túa actividade de navegación recente. Os anunciantes poden seleccionar anuncios para o grupo, e a túa actividade de navegación mantense privada no dispositivo. O teu grupo actualízase a diario.}other{Cando este control está habilitado e co estado activo, Chrome determina con que grupo grande de persoas ou "cohorte" concorda máis a túa actividade de navegación recente. Os anunciantes poden seleccionar anuncios para o grupo, e a túa actividade de navegación mantense privada no dispositivo. O teu grupo actualízase cada {NUM_DAYS} días.}}</translation>
<translation id="2053553514270667976">Código postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suxestión}other{# suxestións}}</translation>
<translation id="2071692954027939183">As notificacións bloqueáronse automaticamente porque non adoitas permitilas</translation>
<translation id="2079545284768500474">Desfacer</translation>
<translation id="20817612488360358">Estableceuse a configuración do proxy do sistema que debe utilizarse, pero tamén se especificou unha configuración de proxy explícita.</translation>
<translation id="2082238445998314030">Resultado <ph name="RESULT_NUMBER" /> de <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Gardar…</translation>
<translation id="2088086323192747268">Botón Xestionar sincronización. Para xestionar na configuración de Chrome a información que se sincroniza, preme Introducir</translation>
<translation id="2091887806945687916">Son</translation>
<translation id="2094505752054353250">Os dominios non coinciden</translation>
@@ -378,6 +387,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="2317259163369394535"><ph name="DOMAIN" /> require un nome de usuario e un contrasinal.</translation>
<translation id="2330137317877982892">A tarxeta <ph name="CREDIT_CARD" /> caduca o <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Opción de configuración controlada polo administrador</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> quere sincronizarse</translation>
<translation id="2344028582131185878">Descargas automáticas</translation>
<translation id="2346319942568447007">Imaxe que copiaches</translation>
<translation id="2354001756790975382">Outros marcadores</translation>
@@ -385,8 +395,10 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="2355395290879513365">É posible que os atacantes poidan ver as imaxes que estás observando neste sitio e enganarte modificándoas.</translation>
<translation id="2356070529366658676">Preguntar</translation>
<translation id="2357481397660644965"><ph name="DEVICE_MANAGER" /> xestiona o teu dispositivo e <ph name="ACCOUNT_MANAGER" /> xestiona a túa conta.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{En menos dun día}=1{Nun día}other{En {NUM_DAYS} días}}</translation>
<translation id="2359629602545592467">Varias divisas</translation>
<translation id="2359808026110333948">Continuar</translation>
+<translation id="2359961752320758691">Completouse o teu número de tarxeta virtual.</translation>
<translation id="2367567093518048410">Nivel</translation>
<translation id="2372464001869762664">Unha vez que confirmes os datos, os detalles da tarxeta da túa Conta de Google compartiranse con este sitio. Busca o CVC entre os datos da túa conta de Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -397,6 +409,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="239429038616798445">Este método de envío non está dispoñible. Proba cun diferente.</translation>
<translation id="2396249848217231973">&amp;Desfacer eliminación</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Antigo</translation>
<translation id="2413528052993050574">Este servidor non puido demostrar que é <ph name="DOMAIN" /> porque quizais se revogase o certificado de seguranza. É posible que isto se deba a un erro de configuración ou a que un atacante interceptase a túa conexión.</translation>
<translation id="2414886740292270097">Escuro</translation>
<translation id="2438874542388153331">Catro perforacións na parte dereita</translation>
@@ -424,10 +437,10 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="2521385132275182522">Grampa na parte inferior dereita</translation>
<translation id="2523886232349826891">Gardada só neste dispositivo</translation>
<translation id="2524461107774643265">Engadir máis información</translation>
-<translation id="2526590354069164005">Ordenador</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{e 1 máis}other{e # máis}}</translation>
<translation id="2536110899380797252">Engadir enderezo</translation>
<translation id="2539524384386349900">Detectar</translation>
+<translation id="2541219929084442027">As páxinas que ves nas pestanas do modo de incógnito non se conservarán no historial do teu navegador, no almacenamento de cookies nin no historial de busca unha vez pechadas todas as pestanas do modo de incógnito. Conservaranse todos os ficheiros que descargues ou os marcadores que crees.</translation>
<translation id="2544644783021658368">Documento individual</translation>
<translation id="254947805923345898">O valor da política non é válido.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> enviou unha resposta non válida.</translation>
@@ -447,6 +460,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="2629325967560697240">Para gozar do máximo nivel de seguranza de Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />activa a protección mellorada<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Non se puido atopar o enderezo IP do servidor de <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Estado:</translation>
+<translation id="264810637653812429">Non se atoparon dispositivos compatibles.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. Preme Tab e, a continuación, Intro para borrar o historial de navegación, as cookies, a memoria caché e outros datos desde a configuración de Chrome</translation>
<translation id="2650446666397867134">Denegouse o acceso ao ficheiro</translation>
@@ -491,6 +505,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="2799223571221894425">Iniciar de novo</translation>
<translation id="2803306138276472711">A navegación segura de Google <ph name="BEGIN_LINK" />detectou software malicioso<ph name="END_LINK" /> en <ph name="SITE" /> recentemente. Ãs veces, os sitios web que adoitan ser seguros inféctanse con software malicioso.</translation>
<translation id="2807052079800581569">Posición Y de imaxe</translation>
+<translation id="2820957248982571256">Buscando…</translation>
<translation id="2824775600643448204">Barra de enderezos e de busca</translation>
<translation id="2826760142808435982">A conexión cífrase e autentícase con <ph name="CIPHER" /> e utiliza <ph name="KX" /> como mecanismo de intercambio de claves.</translation>
<translation id="2835170189407361413">Borrar formulario</translation>
@@ -498,6 +513,8 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="2850739647070081192">Invite (sobre)</translation>
<translation id="2856444702002559011">É posible que os piratas informáticos tenten roubar a túa información de <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (por exemplo, contrasinais, mensaxes ou tarxetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Máis información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Este sitio mostra anuncios intrusivos ou enganosos.</translation>
+<translation id="287596039013813457">Amigable</translation>
+<translation id="2876489322757410363">Sairás do modo de incógnito para pagar a través dunha aplicación externa. Queres continuar?</translation>
<translation id="2878197950673342043">Dobrez de póster</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Colocación das ventás</translation>
@@ -547,7 +564,6 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="3060227939791841287">C9 (sobre)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />. Se queres executar unha comprobación de seguranza na configuración de Chrome, preme Tabulador e, a continuación, Introducir</translation>
<translation id="3061707000357573562">Servizo de parche</translation>
-<translation id="3064966200440839136">Sairás do modo de incógnito para pagar a través dunha aplicación externa. Queres continuar?</translation>
<translation id="306573536155379004">Comezou a partida.</translation>
<translation id="3080254622891793721">Libro gráfico</translation>
<translation id="3086579638707268289">Estase supervisando a túa actividade na Web</translation>
@@ -570,7 +586,6 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="315504272643575312"><ph name="MANAGER" /> xestiona a túa conta.</translation>
<translation id="3157931365184549694">Restaurar</translation>
<translation id="3162559335345991374">É posible que a rede wifi que utilizas requira o acceso á súa páxina de inicio de sesión.</translation>
-<translation id="3167968892399408617">As páxinas que ves nas pestanas do modo de incógnito non se conservarán no historial do teu navegador, no almacenamento de cookies nin no historial de busca unha vez pechadas todas as pestanas do modo de incógnito. Conservaranse todos os ficheiros que descargues ou os marcadores que crees.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Illa</translation>
<translation id="3176929007561373547">Comproba a configuración do teu proxy ou ponte en contacto co administrador da túa rede para
@@ -586,7 +601,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="3207960819495026254">Engadida a marcadores</translation>
<translation id="3209034400446768650">Nesta páxina pódense aplicar cargos</translation>
<translation id="3212581601480735796">Estase supervisando a túa actividade en <ph name="HOSTNAME" /></translation>
-<translation id="3212623355668894776">Pecha todas as ventás do modo de invitado para eliminar a túa actividade de navegación deste dispositivo.</translation>
+<translation id="3212623355668894776">Pecha todas as ventás do modo de convidado para eliminar a túa actividade de navegación deste dispositivo.</translation>
<translation id="3215092763954878852">Non se puido utilizar WebAuthn</translation>
<translation id="3218181027817787318">Relativo</translation>
<translation id="3225919329040284222">O servidor presentou un certificado que non coincide coas expectativas integradas. Estas expectativas inclúense para determinados sitios web de alta seguranza co fin de protexerte.</translation>
@@ -596,10 +611,12 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="3229041911291329567">Información sobre a versión do dispositivo e do navegador</translation>
<translation id="323107829343500871">Introduce o código CVC da tarxeta <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Detectar sempre contido importante neste sitio</translation>
+<translation id="3249845759089040423">Moderno</translation>
<translation id="3252266817569339921">Francés</translation>
<translation id="3266793032086590337">Valor (en conflito)</translation>
<translation id="3268451620468152448">Pestanas abertas</translation>
<translation id="3270847123878663523">&amp;Desfacer de cambio de orde</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> quere conectarse</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">A túa organización, <ph name="ENROLLMENT_DOMAIN" />, enviou algúns datos (por exemplo, opcións de configuración ou políticas) aos seguintes sitios web.</translation>
<translation id="3282497668470633863">Engadir o nome que aparece na tarxeta</translation>
@@ -652,6 +669,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="3428151540071562330">Un ou varios URI do modelo do servidor DnsOverHttpsTemplates non son válidos e non se utilizarán.</translation>
<translation id="3431636764301398940">Gardar esta tarxeta neste dispositivo</translation>
<translation id="3432601291244612633">Pechar páxina</translation>
+<translation id="3435738964857648380">Seguranza</translation>
<translation id="3435896845095436175">Activar</translation>
<translation id="3438829137925142401">Utilizar contrasinais gardados na túa Conta de Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -694,7 +712,10 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="3584299510153766161">Dúas perforacións na parte inferior</translation>
<translation id="3586931643579894722">Ocultar detalles</translation>
<translation id="3587738293690942763">Medio</translation>
+<translation id="3590643883886679995">Os datos de inicio de sesión almacenaranse neste dispositivo cando saias do modo de incógnito.</translation>
+<translation id="359126217934908072">Mes/Ano:</translation>
<translation id="3592413004129370115">Italian (sobre)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Podes restablecer o teu grupo cando queiras. Tardarás máis ou menos un día en unirte a un grupo novo.}=1{Podes restablecer o teu grupo cando queiras. Tardarás máis ou menos un día en unirte a un grupo novo.}other{Podes restablecer o teu grupo cando queiras. Tardarás {NUM_DAYS} días en unirte a un grupo novo.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">O administrador bloqueou a aplicación</translation>
<translation id="3608932978122581043">Orientación da alimentación</translation>
@@ -703,13 +724,13 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="3615877443314183785">Introduce unha data de caducidade válida</translation>
<translation id="36224234498066874">Borrar datos de navegación...</translation>
<translation id="362276910939193118">Mostrar historial completo</translation>
-<translation id="3625635938337243871">Os datos de inicio de sesión almacenaranse neste dispositivo cando saias do modo de incógnito.</translation>
<translation id="3630155396527302611">Se xa está incluído como programa autorizado para acceder á rede, proba
a eliminalo da lista e volver engadilo.</translation>
<translation id="3630699740441428070">Os administradores deste dispositivo configuraron a túa conexión de rede, o cal pode permitirlles ver o tráfico de rede, así como os sitios web que visitas.</translation>
<translation id="3631244953324577188">Autenticación biométrica</translation>
<translation id="3633738897356909127">Botón Actualizar Chrome. Preme Intro para actualizar Chrome desde a configuración do navegador</translation>
<translation id="3634530185120165534">Bandexa 5</translation>
+<translation id="3637662659967048211">Gardar na Conta de Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplicación:</translation>
<translation id="3650584904733503804">Validación realizada correctamente</translation>
@@ -750,6 +771,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="3781428340399460090">Rosa fucsia</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Dispositivos Bluetooth</translation>
+<translation id="3787675388804467730">Número da tarxeta virtual</translation>
<translation id="3787705759683870569">Caduca o <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Tamaño 16</translation>
<translation id="3789841737615482174">Instalar</translation>
@@ -769,6 +791,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="3841184659773414994">Controladores de ficheiros</translation>
<translation id="385051799172605136">Atrás</translation>
<translation id="3858027520442213535">Actualizar data e hora</translation>
+<translation id="3881478300875776315">Mostrar menos liñas</translation>
<translation id="3884278016824448484">Identificador de dispositivos en conflito</translation>
<translation id="3885155851504623709">Parroquia</translation>
<translation id="388632593194507180">Detectouse a supervisión</translation>
@@ -794,6 +817,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="397105322502079400">Calculando...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> está bloqueado</translation>
<translation id="3973357910713125165">Botón Executar comprobación de seguranza de Chrome. Se queres executar unha comprobación de seguranza na configuración de Chrome, preme Introducir</translation>
+<translation id="3986705137476756801">Desactivar polo momento a función Subtítulos instantáneos</translation>
<translation id="3987405730340719549">Chrome determinou que este sitio podería ser falso ou fraudulento.
Se cres que se trata dun erro, visita https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -890,13 +914,14 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="4275830172053184480">Reinicia o dispositivo</translation>
<translation id="4277028893293644418">Restablecer contrasinal</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Esta tarxeta gardouse na túa Conta de Google}other{Estas tarxetas gardáronse na túa Conta de Google}}</translation>
+<translation id="4287885627794386150">Cumpre os requisitos para a proba, pero a técnica non está activa</translation>
<translation id="4297502707443874121">Miniatura da páxina <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Ampliar</translation>
<translation id="4300675098767811073">Varias perforacións na parte dereita</translation>
<translation id="4302514097724775343">Toca o dinosauro para xogar</translation>
<translation id="4302965934281694568">Chou3 (sobre)</translation>
<translation id="4305666528087210886">Non se puido acceder ao ficheiro</translation>
-<translation id="4305817255990598646">Cambiar</translation>
+<translation id="4306529830550717874">Queres gardar o enderezo?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloquear (predeterminado)</translation>
<translation id="4314815835985389558">Xestionar sincronización</translation>
@@ -923,6 +948,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="4377125064752653719">Tentaches acceder a <ph name="DOMAIN" />, pero este emisor revogou o certificado presentado polo servidor. Isto significa que as credenciais de seguranza presentadas polo servidor non son de confianza. É posible que te esteas comunicando cun hacker.</translation>
<translation id="4378154925671717803">Teléfono</translation>
<translation id="4390472908992056574">Bordo</translation>
+<translation id="4406883609789734330">Subtítulos instantáneos</translation>
<translation id="4406896451731180161">Resultados da busca</translation>
<translation id="4408413947728134509">Cookies: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Acabas de escribir o teu contrasinal nun sitio enganoso. Chrome recoméndache que vaias a <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> e outros sitios nos que utilices este contrasinal para cambialo agora.</translation>
@@ -935,7 +961,6 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="4435702339979719576">Postal)</translation>
<translation id="443673843213245140">O uso dun proxy está desactivado, pero especifícase unha configuración de proxy explícita.</translation>
<translation id="4464826014807964867">Sitios web con información da túa organización</translation>
-<translation id="4466881336512663640">Perderanse os cambios que realizases no formulario. Seguro que queres continuar?</translation>
<translation id="4476953670630786061">Este formulario non é seguro, polo que se desactivou a función de autocompletar.</translation>
<translation id="4477350412780666475">Pista seguinte</translation>
<translation id="4482953324121162758">Non se traducirá este sitio.</translation>
@@ -969,6 +994,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="4594403342090139922">&amp;Desfacer eliminación</translation>
<translation id="4597348597567598915">Tamaño 8</translation>
<translation id="4600854749408232102">C6/C5 (sobre)</translation>
+<translation id="4606870351894164739">Chocante</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Devolución de cartos vinculada</translation>
<translation id="4636930964841734540">Información</translation>
@@ -979,7 +1005,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="4660119392514473465">Agora podes navegar de forma privada sen que os outros usuarios deste dispositivo vexan a túa actividade. Non obstante, gardaranse as descargas, os marcadores e os elementos da lista de lectura.</translation>
<translation id="4668929960204016307">,</translation>
<translation id="4670064810192446073">Realidade virtual</translation>
-<translation id="4675657451653251260">Non verás a información de ningún perfil de Chrome no modo de invitado. Podes <ph name="LINK_BEGIN" />iniciar sesión<ph name="LINK_END" /> para acceder á información (como os contrasinais e os métodos de pago) da túa conta de Google.</translation>
+<translation id="4675657451653251260">Non verás a información de ningún perfil de Chrome no modo de convidado. Podes <ph name="LINK_BEGIN" />iniciar sesión<ph name="LINK_END" /> para acceder á información (como os contrasinais e os métodos de pago) da túa conta de Google.</translation>
<translation id="467662567472608290">Este servidor non puido demostrar que é <ph name="DOMAIN" /> porque o seu certificado de seguranza contén erros. É posible que isto se deba a un erro de configuración ou a que un atacante interceptase a túa conexión.</translation>
<translation id="4677585247300749148">O URL <ph name="URL" /> quere responder a eventos de accesibilidade</translation>
<translation id="467809019005607715">Presentacións de Google</translation>
@@ -988,6 +1014,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="4691835149146451662">Architecture-A (sobre)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Lado</translation>
+<translation id="4702656508969495934">Subtítulos instantáneos visibles. Usa o conmutador de ventás para enfocalos</translation>
<translation id="4708268264240856090">Interrompeuse a túa conexión</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Executar diagnóstico de rede de Windows<ph name="END_LINK" /></translation>
@@ -1001,6 +1028,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="4738601419177586157">Suxestión de busca de "<ph name="TEXT" />"</translation>
<translation id="4742407542027196863">Xestionar contrasinais…</translation>
<translation id="4744603770635761495">Ruta executable</translation>
+<translation id="4749011317274908093">Pasaches ao modo de incógnito</translation>
<translation id="4750917950439032686">A túa información (por exemplo, os contrasinais ou os números da tarxeta de crédito) mantense en privado cando se envía a este sitio.</translation>
<translation id="4756388243121344051">&amp;Historial</translation>
<translation id="4758311279753947758">Engadir información de contacto</translation>
@@ -1030,6 +1058,8 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="4813512666221746211">Erro de rede</translation>
<translation id="4816492930507672669">Axustar á páxina</translation>
<translation id="4819347708020428563">Queres editar as anotacións na vista predeterminada?</translation>
+<translation id="4825507807291741242">Potente</translation>
+<translation id="4838327282952368871">Onírico</translation>
<translation id="484462545196658690">Automático</translation>
<translation id="4850886885716139402">Vista</translation>
<translation id="485316830061041779">Alemán</translation>
@@ -1166,6 +1196,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="5314967030527622926">Creador de folletos</translation>
<translation id="5316812925700871227">Xirar á esquerda</translation>
<translation id="5317780077021120954">Gardar</translation>
+<translation id="5321288445143113935">Aplicación maximizada</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> de <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Escoller información de contacto</translation>
<translation id="5327248766486351172">Nome</translation>
@@ -1173,11 +1204,13 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="5332219387342487447">Método de envío</translation>
<translation id="5333022057423422993">Chrome atopou o contrasinal que acabas de utilizar entre os datos dunha violación da seguranza dos datos. Para protexer as túas contas, recomendámosche que revises os contrasinais que tes gardados.</translation>
<translation id="5334013548165032829">Rexistros do sistema detallados</translation>
+<translation id="5334145288572353250">Queres gardar este enderezo?</translation>
<translation id="5340250774223869109">A aplicación está bloqueada</translation>
<translation id="534295439873310000">Dispositivos con NFC</translation>
<translation id="5344579389779391559">Esta páxina pode tentar aplicar cargos</translation>
<translation id="5355557959165512791">Non podes visitar <ph name="SITE" /> neste momento porque se revogou o seu certificado. Normalmente, os erros de rede e os ataques son temporais, polo que é posible que esta páxina funcione máis tarde.</translation>
<translation id="536296301121032821">Non se puido almacenar a configuración da política</translation>
+<translation id="5363309033720083897">O teu administrador permite o uso do porto en serie</translation>
<translation id="5371425731340848620">Actualizar tarxeta</translation>
<translation id="5377026284221673050">"O reloxo está atrasado", "O reloxo está adiantado" ou "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
<translation id="5386426401304769735">A cadea de certificados deste sitio contén un certificado que se asinou con SHA-1.</translation>
@@ -1186,6 +1219,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="5398772614898833570">Bloqueáronse os anuncios</translation>
<translation id="5400836586163650660">Gris</translation>
<translation id="540969355065856584">Este servidor non puido demostrar que é <ph name="DOMAIN" /> porque o seu certificado de seguranza non é válido neste momento. É posible que isto se deba a un erro de configuración ou a que un atacante interceptase a túa conexión.</translation>
+<translation id="541143247543991491">Nube (todo o sistema)</translation>
<translation id="541416427766103491">Amontoador 4</translation>
<translation id="5421136146218899937">Borrar datos de navegación...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> quere enviarche notificacións</translation>
@@ -1199,6 +1233,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="5455374756549232013">Marca de tempo da política incorrecta</translation>
<translation id="5457113250005438886">Non válidos</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> e <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> máis}other{<ph name="CONTACT_PREVIEW" /> e <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> máis}}</translation>
+<translation id="5463625433003343978">Buscando dispositivos…</translation>
<translation id="5469868506864199649">Italiano</translation>
<translation id="5470861586879999274">&amp;Refacer modificación</translation>
<translation id="5478437291406423475">B6/C4 (sobre)</translation>
@@ -1248,7 +1283,6 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="5624120631404540903">Xestionar contrasinais</translation>
<translation id="5629630648637658800">Erro ao cargar a configuración da política</translation>
<translation id="5631439013527180824">Token de xestión de dispositivo non válido</translation>
-<translation id="5632627355679805402">Os datos encriptáronse co teu <ph name="BEGIN_LINK" />contrasinal de Google<ph name="END_LINK" /> a partir do <ph name="TIME" />. Introdúceo para iniciar a sincronización.</translation>
<translation id="5633066919399395251">Os piratas informáticos do sitio <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> poderían tentar instalar programas perigosos no ordenador que rouben ou eliminen a túa información (por exemplo, fotos, contrasinais, mensaxes e tarxetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Máis información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Bloqueouse contido enganoso.</translation>
<translation id="5644090287519800334">Desprazamento do lado 1 da imaxe no eixe X</translation>
@@ -1287,12 +1321,12 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="5785756445106461925">Ademais, esta páxina inclúe outros recursos que non son seguros. Outros usuarios poden ver estes recursos mentres se desprazan e un atacante pode cambiar o aspecto da páxina.</translation>
<translation id="5786044859038896871">Queres completar a información da tarxeta de crédito?</translation>
<translation id="578633867165174378">Chrome atopou o contrasinal que acabas de utilizar entre os datos dunha violación da seguranza dos datos. Recomendámosche que o cambies de inmediato.</translation>
-<translation id="5798290721819630480">Queres descartar os cambios?</translation>
<translation id="5803412860119678065">Queres completar a información da tarxeta de crédito <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Permisos</translation>
<translation id="5804427196348435412">Utilizar dispositivos con NFC</translation>
<translation id="5810442152076338065">A túa conexión a <ph name="DOMAIN" /> está encriptada cun paquete de cifraxe obsoleto.</translation>
<translation id="5813119285467412249">&amp;Refacer adición</translation>
+<translation id="5817918615728894473">Sincronizar</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Cando pagues, cobrarase o importe correspondente utilizando esta tarxeta, pero o seu número real non se compartirá con este sitio. Para máis seguranza, xerarase un CVC temporal.}other{Cando pagues, cobrarase o importe correspondente utilizando a tarxeta que selecciones, pero o seu número real non se compartirá con este sitio. Para máis seguranza, xerarase un CVC temporal.}}</translation>
<translation id="5826507051599432481">Nome común (NC)</translation>
<translation id="5838278095973806738">Non debes introducir información confidencial neste sitio (por exemplo, contrasinais ou tarxetas de crédito), xa que os atacantes poden roubala.</translation>
@@ -1300,6 +1334,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="5855253129151731373">O nome do host deste sitio é similar ao de <ph name="LOOKALIKE_DOMAIN" />. Ãs veces, os atacantes crean copias de sitios introducindo nos nomes de dominio cambios pequenos e difíciles de ver.
Se cres que se trata dun erro, visita https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Non</translation>
<translation id="5862579898803147654">Amontoador 8</translation>
<translation id="5863847714970149516">A páxina á que vas acceder pode tentar aplicar cargos</translation>
<translation id="5866257070973731571">Engade un número de teléfono</translation>
@@ -1316,6 +1351,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="5913377024445952699">A captura de pantalla púxose en pausa</translation>
<translation id="59174027418879706">Activado</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 en uso}other{# en uso}}</translation>
<translation id="5921185718311485855">Activado</translation>
<translation id="5921639886840618607">Queres gardar a tarxeta na Conta de Google?</translation>
<translation id="5922853866070715753">Case está listo</translation>
@@ -1335,6 +1371,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="5989320800837274978">Non se especificaron nin servidores proxy fixos nin un URL de script .pac.</translation>
<translation id="5992691462791905444">Dobrez en Z para enxeñaría</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultados para "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Clásico</translation>
<translation id="6008122969617370890">Orde de N a 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Comproba os teus contrasinais</translation>
@@ -1356,6 +1393,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="6045164183059402045">Modelo de imposición</translation>
<translation id="6047233362582046994">Se aceptas os riscos para a túa seguranza, podes <ph name="BEGIN_LINK" />acceder a este sitio<ph name="END_LINK" /> antes de que se eliminen as aplicacións prexudiciais.</translation>
<translation id="6047927260846328439">É posible que con este contido se pretenda enganarte para instalar software ou revelar información persoal. <ph name="BEGIN_LINK" />Mostrar igualmente<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Mantén premida a tecla |<ph name="ACCELERATOR" />| para saír do modo de pantalla completa</translation>
<translation id="6049488691372270142">Entrega da páxina</translation>
<translation id="6051221802930200923">Non podes acceder a <ph name="SITE" /> agora momento porque o sitio web usa a fixación de certificados. Normalmente, os erros de rede e os ataques son temporais, polo que é posible que esta páxina funcione máis tarde.</translation>
<translation id="6051898664905071243">Número de páxinas:</translation>
@@ -1372,6 +1410,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="610911394827799129">É posible que a túa conta de Google teña outras formas do historial de navegación en <ph name="BEGIN_LINK" />history.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">Ver o texto e as imaxes que se copian no portapapeis</translation>
<translation id="6120179357481664955">Queres lembrar o teu código da UPI?</translation>
+<translation id="6123290840358279103">Ver tarxeta virtual</translation>
<translation id="6124432979022149706">Conectores de Chrome Enterprise</translation>
<translation id="6146055958333702838">Comproba os cables e reinicia os routers, módems e demais dispositivos
de rede que utilices.</translation>
@@ -1408,6 +1447,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="6289939620939689042">Cor das páxinas</translation>
<translation id="6290238015253830360">Os teus artigos suxeridos aparecerán aquí</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Detendo o Asistente de Google en Chrome</translation>
<translation id="6305205051461490394">Non se pode acceder a <ph name="URL" />.</translation>
<translation id="6312113039770857350">A páxina web non está dispoñible</translation>
@@ -1433,6 +1473,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="6390200185239044127">Dobrez en Z á metade</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">A política do administrador bloqueou a función de pegar contido nesta localización desde <ph name="ORIGIN_NAME" /></translation>
+<translation id="6398765197997659313">Saír do modo de pantalla completa</translation>
<translation id="6401136357288658127">Esta política quedou obsoleta. Debes utilizar a política <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Editar marcador</translation>
<translation id="6406765186087300643">C0 (sobre)</translation>
@@ -1445,7 +1486,6 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="6428450836711225518">Verificar o teu número de teléfono</translation>
<translation id="6433490469411711332">Editar información de contacto</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> rexeitou a conexión.</translation>
-<translation id="6434309073475700221">Descartar</translation>
<translation id="6440503408713884761">Política ignorada</translation>
<translation id="6443406338865242315">As extensións e os complementos que teñas instalados</translation>
<translation id="6446163441502663861">Kahu (sobre)</translation>
@@ -1488,6 +1528,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="6624427990725312378">Información de contacto</translation>
<translation id="6626291197371920147">Engade un número da tarxeta válido</translation>
<translation id="6628463337424475685">Busca de <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Buscando dispositivos USB…</translation>
<translation id="6630809736994426279">Os piratas informáticos do sitio <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> poderían tentar instalar programas perigosos no teu Mac que rouben ou eliminen a túa información (por exemplo, fotos, contrasinais, mensaxes e tarxetas de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Máis información<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Borrar</translation>
@@ -1503,6 +1544,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="6671697161687535275">Queres eliminar a túa suxestión de formulario de Chromium?</translation>
<translation id="6685834062052613830">Pecha sesión e finaliza o proceso de configuración</translation>
<translation id="6687335167692595844">Tamaño do tipo de letra solicitado</translation>
+<translation id="6688743156324860098">Actualizar…</translation>
<translation id="6689249931105087298">Relativo con compresión de puntos negros</translation>
<translation id="6689271823431384964">Chrome permíteche gardar as túas tarxetas na túa Conta de Google porque tes a sesión iniciada. Podes cambiar esta opción na configuración cando queiras. O nome do titular da tarxeta procede da túa conta.</translation>
<translation id="6698381487523150993">Creada:</translation>
@@ -1518,6 +1560,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="6744009308914054259">Mentres esperas a que se recupere a conexión, podes ler artigos sen conexión en Descargas.</translation>
<translation id="6753269504797312559">Valor de política</translation>
<translation id="6757797048963528358">O teu dispositivo entrou no modo de suspensión.</translation>
+<translation id="6767985426384634228">Queres actualizar este enderezo?</translation>
<translation id="6768213884286397650">Hagaki (postal)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violeta</translation>
@@ -1540,6 +1583,7 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome simplificou esta páxina para que sexa máis fácil de ler. Chrome recuperou a páxina orixinal a través dunha conexión insegura.</translation>
<translation id="6891596781022320156">O nivel da política non é compatible.</translation>
+<translation id="6895143722905299846">Número virtual:</translation>
<translation id="6895330447102777224">Confirmouse a túa tarxeta</translation>
<translation id="6897140037006041989">Axente de usuario</translation>
<translation id="6898699227549475383">Organización (O)</translation>
@@ -1575,10 +1619,10 @@ En caso contrario, a configuración de privacidade impedirao. Se o permites, o c
<translation id="7004583254764674281">Usar Windows Hello para confirmar as tarxetas máis rápido</translation>
<translation id="7006930604109697472">Enviar de todas formas</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Configuración do cambio de tamaño</translation>
<translation id="7014741021609395734">Nivel de zoom</translation>
<translation id="7016992613359344582">Ten en conta que estes cargos poden ser únicos ou periódicos e que quizais non se indiquen de forma evidente.</translation>
<translation id="7029809446516969842">Contrasinais</translation>
+<translation id="7030436163253143341">O certificado non é válido</translation>
<translation id="7031646650991750659">As aplicacións de Google Play que teñas instaladas</translation>
<translation id="7050187094878475250">Tentaches acceder a <ph name="DOMAIN" />, pero o servidor presentou un certificado cun período de validez demasiado longo para ser fiable.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Esta tarxeta non se pode gardar neste momento}other{Estas tarxetas non se poden gardar neste momento}}</translation>
@@ -1648,12 +1692,14 @@ Detalles adicionais:
<translation id="7300012071106347854">Azul cobalto</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Alto</translation>
+<translation id="7305756307268530424">Iniciar a menor velocidade</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Axuda de conexión</translation>
<translation id="7323804146520582233">Ocultar a sección <ph name="SECTION" /></translation>
<translation id="733354035281974745">Anulación da conta local do dispositivo</translation>
<translation id="7333654844024768166">Acabas de escribir o teu contrasinal nun sitio enganoso. Chromium recoméndache que vaias a <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> e outros sitios nos que utilices este contrasinal para cambialo agora.</translation>
<translation id="7334320624316649418">&amp;Refacer de cambio de orde</translation>
+<translation id="7337248890521463931">Mostrar máis liñas</translation>
<translation id="7337706099755338005">Non está dispoñible na túa plataforma.</translation>
<translation id="733923710415886693">O certificado do servidor non se indicou mediante Certificate Transparency.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1661,6 +1707,7 @@ Detalles adicionais:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Liña de comandos</translation>
<translation id="7359588939039777303">Bloqueáronse os anuncios.</translation>
+<translation id="7363096869660964304">Con todo, non es invisible. O modo de incógnito non impide que o teu xefe, o teu fornecedor de servizos de Internet ou os sitios web que visitas obteñan información sobre como navegas.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />. Para engadir e xestionar enderezos na configuración de Chrome, preme Tabulador e, a continuación, Introducir</translation>
<translation id="7365849542400970216">Queres permitir a detección do uso do dispositivo?</translation>
<translation id="7372973238305370288">resultado da busca</translation>
@@ -1671,7 +1718,9 @@ Detalles adicionais:
<translation id="7378594059915113390">Controis de contido multimedia</translation>
<translation id="7378627244592794276">Non</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Non aplicable</translation>
<translation id="7390545607259442187">Confirmar tarxeta</translation>
+<translation id="7392089738299859607">Actualizar enderezo</translation>
<translation id="7399802613464275309">Revisión de seguranza</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">O teu <ph name="DEVICE_NAME" /> está xestionado</translation>
@@ -1686,6 +1735,7 @@ Detalles adicionais:
&lt;li&gt;Accede ao &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centro de Axuda de Chrome&lt;/a&gt; para obter información sobre como eliminar permanentemente o software do ordenador
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Encantador</translation>
<translation id="7416351320495623771">Xestionar contrasinais…</translation>
<translation id="7419106976560586862">Ruta do perfil</translation>
<translation id="7437289804838430631">Engadir información de contacto</translation>
@@ -1701,7 +1751,7 @@ Detalles adicionais:
<translation id="7481312909269577407">Adiante</translation>
<translation id="7485870689360869515">Non se atoparon datos.</translation>
<translation id="7495528107193238112">Este contido está bloqueado. Ponte en contacto co propietario do sitio para corrixir o problema.</translation>
-<translation id="7498234416455752244">Seguir editando</translation>
+<translation id="7498193950643227031">Se se cambia o tamaño, podería funcionar de forma inesperada. Agora podes limitar o cambio de tamaño das aplicacións en <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Acabas de escribir o teu contrasinal nun sitio enganoso. Chromium recomenda comprobar os contrasinais gardados para <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> e outros sitios nos que esteas a utilizar este contrasinal neste momento.</translation>
<translation id="7508255263130623398">O código de dispositivo da política está baleiro ou non coincide co código do dispositivo actual</translation>
<translation id="7508870219247277067">Verde aguacate</translation>
@@ -1721,6 +1771,7 @@ Detalles adicionais:
<translation id="7548892272833184391">Solucionar erros de conexión</translation>
<translation id="7549584377607005141">Esta páxina web require datos introducidos anteriormente para mostrarse correctamente. Podes enviar estes datos de novo, pero volveranse repetir as accións que a páxina realizase previamente.</translation>
<translation id="7550637293666041147">O nome de usuario do teu dispositivo e o de Chrome</translation>
+<translation id="755279583747225797">A proba está activa</translation>
<translation id="7552846755917812628">Proba os seguintes consellos:</translation>
<translation id="7554475479213504905">Volver cargar e mostrar igualmente</translation>
<translation id="7554791636758816595">Nova pestana</translation>
@@ -1739,7 +1790,6 @@ Detalles adicionais:
<translation id="7610193165460212391">O valor está fóra do rango de <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Caducidade: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Preme Tab e, a continuación, Intro para ver e xestionar os teus contrasinais desde a configuración de Chrome</translation>
-<translation id="7615602087246926389">Anteriormente, utilizaches outra versión do contrasinal da túa conta de Google para o cifrado de datos. Introdúcea a continuación.</translation>
<translation id="7616645509853975347">O teu administrador activou Chrome Enterprise Connectors no teu navegador. Estes conectores teñen acceso a algúns dos teus datos.</translation>
<translation id="7619838219691048931">Folla final</translation>
<translation id="762844065391966283">Un de cada vez</translation>
@@ -1804,13 +1854,12 @@ Detalles adicionais:
<translation id="782886543891417279">É posible que a rede wifi que utilizas (<ph name="WIFI_NAME" />) requira o acceso á súa páxina de inicio de sesión.</translation>
<translation id="7836231406687464395">Postfix (sobre)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ningunha}=1{1 aplicación (<ph name="EXAMPLE_APP_1" />)}=2{2 aplicacións (<ph name="EXAMPLE_APP_1" /> e <ph name="EXAMPLE_APP_2" />)}other{# aplicacións (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> e <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Con todo, non es invisible. O modo de incógnito non impide que o teu xefe, o teu fornecedor de servizos de Internet nin os sitios web que visitas obteñan información sobre como navegas.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Abrir ficheiros con asociacións de tipos de ficheiro.</translation>
<translation id="7862185352068345852">Queres saír do sitio?</translation>
<translation id="7865448901209910068">A mellor velocidade</translation>
<translation id="7874263914261512992">Acabas de escribir o teu contrasinal nun sitio enganoso. Chrome recomenda comprobar os contrasinais gardados para <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> e outros sitios nos que esteas a utilizar este contrasinal neste momento.</translation>
<translation id="7878562273885520351">Pode que o teu contrasinal estea en perigo</translation>
+<translation id="7880146494886811634">Gardar enderezo</translation>
<translation id="7882421473871500483">Marrón</translation>
<translation id="7887683347370398519">Comproba o CVC e téntao de novo</translation>
<translation id="7887885240995164102">Acceder ao modo de pantalla superposta</translation>
@@ -1818,6 +1867,7 @@ Detalles adicionais:
<translation id="7894280532028510793">Se está ben escrito, podes <ph name="BEGIN_LINK" />probar a executar o diagnóstico de rede<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (sobre)</translation>
<translation id="7931318309563332511">Descoñecido</translation>
+<translation id="793209273132572360">Queres cambiar o enderezo?</translation>
<translation id="7932579305932748336">Recubrimento</translation>
<translation id="79338296614623784">Introduce un número de teléfono válido</translation>
<translation id="7934052535022478634">Completouse o pago</translation>
@@ -1888,6 +1938,7 @@ Detalles adicionais:
<translation id="8175796834047840627">Chrome permíteche gardar as túas tarxetas na túa Conta de Google porque tes a sesión iniciada. Podes cambiar esta opción na configuración cando queiras.</translation>
<translation id="8176440868214972690">O administrador deste dispositivo enviou algúns datos (por exemplo, opcións de configuración ou políticas) aos seguintes sitios web.</translation>
<translation id="8184538546369750125">Utilizar axuste predeterminado global (permitir)</translation>
+<translation id="8193086767630290324">Accións realizadas con datos marcados como confidenciais</translation>
<translation id="8194797478851900357">&amp;Desfacer movemento</translation>
<translation id="8201077131113104583">O URL de actualización para a extensión co ID "<ph name="EXTENSION_ID" />" non é válido.</translation>
<translation id="8202097416529803614">Resumo do pedido</translation>
@@ -1910,6 +1961,7 @@ Detalles adicionais:
<translation id="8249296373107784235">Cancelar</translation>
<translation id="8249320324621329438">Última comprobación:</translation>
<translation id="8253091569723639551">É obrigatorio introducir o enderezo de facturación</translation>
+<translation id="8257387598443225809">Esta aplicación está deseñada para dispositivos móbiles</translation>
<translation id="825929999321470778">Mostrar todos os contrasinais gardados</translation>
<translation id="8261506727792406068">Eliminar</translation>
<translation id="8262952874573525464">Grampa no bordo inferior</translation>
@@ -2033,7 +2085,6 @@ Detalles adicionais:
<translation id="8719528812645237045">Varias perforacións na parte superior</translation>
<translation id="8725066075913043281">Tentar de novo</translation>
<translation id="8726549941689275341">Tamaño da páxina:</translation>
-<translation id="8728672262656704056">Entraches no modo de incógnito</translation>
<translation id="8730621377337864115">Feito</translation>
<translation id="8731544501227493793">Botón Xestionar contrasinais. Preme Intro para ver e xestionar os teus contrasinais desde a configuración de Chrome</translation>
<translation id="8734529307927223492"><ph name="MANAGER" /> xestiona o teu dispositivo (<ph name="DEVICE_TYPE" />)</translation>
@@ -2110,6 +2161,7 @@ Detalles adicionais:
<translation id="9020542370529661692">Traduciuse esta páxina ao <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Non válido)</translation>
+<translation id="9030265603405983977">Monocromo</translation>
<translation id="9035022520814077154">Erro de seguranza</translation>
<translation id="9038649477754266430">Utilizar un servizo de predición para cargar as páxinas máis rápido</translation>
<translation id="9039213469156557790">Ademais, esta páxina inclúe outros recursos que non son seguros. Outros usuarios poden ver estes recursos mentres se desprazan e un atacante pode modificalos para cambiar o comportamento da páxina.</translation>
@@ -2133,6 +2185,7 @@ Detalles adicionais:
<translation id="91108059142052966">A política do administrador desactiva a pantalla compartida con <ph name="APPLICATION_TITLE" /> cando hai contido confidencial á vista</translation>
<translation id="9114524666733003316">Confirmando tarxeta…</translation>
<translation id="9114581008513152754">Ningunha compañía ou organización xestiona este navegador. A actividade deste dispositivo pódese xestionar fóra de Chrome. <ph name="BEGIN_LINK" />Máis información<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Novo</translation>
<translation id="9119042192571987207">Cargouse</translation>
<translation id="9128016270925453879">Cargáronse as políticas</translation>
<translation id="9128870381267983090">Conectarse á rede</translation>
@@ -2151,6 +2204,7 @@ Detalles adicionais:
<translation id="9170848237812810038">&amp;Desfacer</translation>
<translation id="9171296965991013597">Queres saír da aplicación?</translation>
<translation id="9173282814238175921">Documento único/folla nova</translation>
+<translation id="9173995187295789444">Buscando dispositivos Bluetooth…</translation>
<translation id="917450738466192189">O certificado do servidor non é válido.</translation>
<translation id="9174917557437862841">Botón de cambio de pestana; preme Intro para cambiar a esta pestana</translation>
<translation id="9179703756951298733">Xestiona os teus pagos e a información das tarxetas de crédito na configuración de Chrome</translation>
diff --git a/chromium/components/strings/components_strings_gu.xtb b/chromium/components/strings/components_strings_gu.xtb
index 1e13cbdbbb5..0b8cd6b817f 100644
--- a/chromium/components/strings/components_strings_gu.xtb
+++ b/chromium/components/strings/components_strings_gu.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">જો ચેક કરેલà«àª‚ હોય, તો àªàª¡àªªàª¥à«€ ફોરà«àª® ભરવા માટે Chrome આ ઉપકરણ પર તમારા કારà«àª¡àª¨à«€ àªàª• કૉપિ સંગà«àª°àª¹àª¶à«‡.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> માટે પરવાનગી પસંદ કરો</translation>
<translation id="1113869188872983271">&amp;પà«àª¨àªƒàª•à«àª°àª®àª¾àª‚કિત કરવà«àª‚ પૂરà«àªµàªµàª¤à« કરો</translation>
+<translation id="1123753900084781868">આ સમયે લાઇવ કૅપà«àª¶àª¨àª¨à«€ સà«àªµàª¿àª§àª¾ ઉપલબà«àª§ નથી</translation>
<translation id="1125573121925420732">વેબસાઇટ તેમની સà«àª°àª•à«àª·àª¾ અપડેટ કરી રહà«àª¯àª¾àª‚ હોય તà«àª¯àª¾àª°à«‡ ચેતવણીઓ દેખાવી સામાનà«àª¯ બાબત છે. ટૂંક સમયમાં જ આમાં સà«àª§àª¾àª°à«‹ કરવામાં આવશે.</translation>
<translation id="112840717907525620">પૉલિસી કૅશ મેમરી ઓકે</translation>
<translation id="1130564665089811311">પેજનો અનà«àªµàª¾àª¦ કરો બટન, Google Translate વડે આ પેજનો અનà«àªµàª¾àª¦ કરવા માટે Enter દબાવો</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">તમારા ડિવાઇસનà«àª‚ નામ</translation>
<translation id="124116460088058876">વધૠભાષાઓ</translation>
<translation id="1243027604378859286">લેખક:</translation>
+<translation id="1246424317317450637">ઘાટà«àª‚</translation>
<translation id="1250759482327835220">આગલી વખતે વધૠàªàª¡àªªàª¥à«€ ચà«àª•àªµàª£à«€ કરવા માટે, તમારા કારà«àª¡, નામ અને બિલિંગ સરનામાને તમારા Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ સાચવો.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (સમનà«àªµàª¯àª¿àª¤)</translation>
<translation id="1256368399071562588">&lt;p&gt;જો તમે કોઈ વેબસાઇટની મà«àª²àª¾àª•àª¾àª¤ લેવાનો પà«àª°àª¯àª¾àª¸ કરો અને તે ન ખૂલે, તો પહેલા સમસà«àª¯àª¾ નિવારણના આ પગલાં લઈને સમસà«àª¯àª¾ ઉકેલવાનો પà«àª°àª¯àª¾àª¸ કરો:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">તમારો પાસવરà«àª¡ બદલો</translation>
<translation id="1484290072879560759">વિતરણ માટેનà«àª‚ સરનામà«àª‚ પસંદ કરો</translation>
<translation id="1492194039220927094">પà«àª¶ કરેલી પૉલિસી:</translation>
+<translation id="1495677929897281669">ટૅબ પર પાછા જાઓ</translation>
<translation id="1501859676467574491">તમારા Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚થી કારà«àª¡ બતાવો</translation>
<translation id="1507202001669085618">&lt;p&gt;જો તમે ઑનલાઇન થાઓ ઠપહેલાં જà«àª¯àª¾àª‚ તમારે સાઇન ઇન કરવà«àª‚ જરૂરી હોય તેવા વાઇ-ફાઇ પોરà«àªŸàª²àª¨à«‹ ઉપયોગ કરી રહà«àª¯àª¾ હો, તો તમને આ ભૂલ દેખાશે.&lt;/p&gt;
&lt;p&gt;આ સમસà«àª¯àª¾ ઉકેલવા માટે, તમે ખોલવાનો પà«àª°àª¯àª¾àª¸ કરી રહà«àª¯àª¾ છો ઠપેજ પર &lt;strong&gt;કનેકà«àªŸ કરો&lt;/strong&gt; પર કà«àª²àª¿àª• કરો.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">આ પેજ કહે છે કે</translation>
<translation id="153384715582417236">હમણાં માટે બસ આટલà«àª‚ પૂરતà«àª‚ છે</translation>
<translation id="1536390784834419204">પેજનો અનà«àªµàª¾àª¦ કરો</translation>
+<translation id="1539840569003678498">રિપોરà«àªŸ મોકલà«àª¯à«‹:</translation>
<translation id="154408704832528245">વિતરણ માટેનà«àª‚ સરનામà«àª‚ પસંદ કરો</translation>
<translation id="1549470594296187301">આ સà«àªµàª¿àª§àª¾àª¨à«‹ ઉપયોગ કરવા માટે JavaScript સકà«àª·àª® કરેલ હોવી આવશà«àª¯àª• છે.</translation>
<translation id="155039086686388498">àªàª¨à«àªœàª¿àª¨àª¿àª¯àª°àª¿àª‚ગ-D</translation>
@@ -178,9 +182,9 @@
<translation id="1555130319947370107">વાદળી</translation>
<translation id="1559447966090556585">નોટિફિકેશન મેળવવા છે?</translation>
<translation id="1559528461873125649">આવી કોઈ ફાઇલ અથવા ડિરેકà«àªŸàª°à«€ નથી</translation>
-<translation id="1559572115229829303">&lt;p&gt;<ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> પર ખાનગી કનેકà«àª¶àª¨ સà«àª¥àª¾àªªàª¿àª¤ કરી શકાતà«àª‚ નથી કારણ કે તમારા ઉપકરણની તારીખ અને સમય (<ph name="DATE_AND_TIME" />) અયોગà«àª¯ છે.&lt;/p&gt;
+<translation id="1559572115229829303">&lt;p&gt;<ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> પર ખાનગી કનેકà«àª¶àª¨ સà«àª¥àª¾àªªàª¿àª¤ કરી શકાતà«àª‚ નથી કારણ કે તમારા ડિવાઇસની તારીખ અને સમય (<ph name="DATE_AND_TIME" />) અયોગà«àª¯ છે.&lt;/p&gt;
- &lt;p&gt;કૃપા કરીને &lt;strong&gt;સેટિંગà«àª¸&lt;/strong&gt; અâ€à«…પà«àª²àª¿àª•à«‡àª¶àª¨àª¨àª¾ &lt;strong&gt;સામાનà«àª¯&lt;/strong&gt; વિભાગમાં તારીખ અને સમય સમાયોજિત કરો.&lt;/p&gt;</translation>
+ &lt;p&gt;કૃપા કરીને &lt;strong&gt;સેટિંગ&lt;/strong&gt; અâ€à«…પના &lt;strong&gt;સામાનà«àª¯&lt;/strong&gt; વિભાગમાં તારીખ અને સમય ગોઠવો.&lt;/p&gt;</translation>
<translation id="1567040042588613346">આ પૉલિસી હેતૠમà«àªœàª¬ કારà«àª¯ કરી રહી છે પરંતૠસમાન મૂલà«àª¯ બીજે કà«àª¯àª¾àª‚ક સેટ કરવામાં આવà«àª¯à«àª‚ છે અને આ પૉલિસી તેની જગà«àª¯àª¾ લે છે.</translation>
<translation id="1569487616857761740">સમાપà«àª¤àª¿ તારીખ દાખલ કરો</translation>
<translation id="1581080074034554886">CVC</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">પહેલાં ટૂંકી કિનારી</translation>
<translation id="168693727862418163">આ પૉલિસીનà«àª‚ મૂલà«àª¯ તેના સà«àª•à«€àª®àª¾ સામે માનà«àª¯ કરવામાં નિષà«àª«àª³ ગયà«àª‚ છે અને તેને અવગણવામાં આવશે.</translation>
<translation id="168841957122794586">સરà«àªµàª° પà«àª°àª®àª¾àª£àªªàª¤à«àª° àªàª• નબળી કà«àª°àª¿àªªà«àªŸà«‹àª—à«àª°àª¾àª«àª¿àª• કી ધરાવે છે.</translation>
+<translation id="1696290444144917273">વરà«àªšà«àª¯à«àª…લ કારà«àª¡àª¨à«€ વિગતો જà«àª“</translation>
<translation id="1697532407822776718">તમારà«àª‚ બધà«àª‚ સેટ છે!</translation>
<translation id="1703835215927279855">અકà«àª·àª°</translation>
<translation id="1706954506755087368">{1,plural, =1{આ સરà«àªµàª° સાબિત કરી શકà«àª¯à«àª‚ નથી કે તે <ph name="DOMAIN" /> છે; તેનà«àª‚ સà«àª°àª•à«àª·àª¾ પà«àª°àª®àª¾àª£àªªàª¤à«àª° આવતીકાલથી માનવામાં આવે છે તે પà«àª°àª®àª¾àª£à«‡ છે. આ કોઇ ખોટી ગોઠવણીને કારણે થયà«àª‚ હશે અથવા કોઇ હà«àª®àª²àª¾àª–ોર તમારા કનેકà«àª¶àª¨àª¨à«‡ અટકાવી રહà«àª¯à«‹ છે.}one{આ સરà«àªµàª° સાબિત કરી શકà«àª¯à«àª‚ નથી કે તે <ph name="DOMAIN" /> છે; તેનà«àª‚ સà«àª°àª•à«àª·àª¾ પà«àª°àª®àª¾àª£àªªàª¤à«àª° માનવામાં આવે છે તે પà«àª°àª®àª¾àª£à«‡ ભવિષà«àª¯àª®àª¾àª‚ # દિવસથી છે. આ કોઇ ખોટી ગોઠવણીને કારણે થયà«àª‚ હશે અથવા કોઇ હà«àª®àª²àª¾àª–ોર તમારા કનેકà«àª¶àª¨àª¨à«‡ અટકાવી રહà«àª¯à«‹ છે.}other{આ સરà«àªµàª° સાબિત કરી શકà«àª¯à«àª‚ નથી કે તે <ph name="DOMAIN" /> છે; તેનà«àª‚ સà«àª°àª•à«àª·àª¾ પà«àª°àª®àª¾àª£àªªàª¤à«àª° માનવામાં આવે છે તે પà«àª°àª®àª¾àª£à«‡ ભવિષà«àª¯àª®àª¾àª‚ # દિવસથી છે. આ કોઇ ખોટી ગોઠવણીને કારણે થયà«àª‚ હશે અથવા કોઇ હà«àª®àª²àª¾àª–ોર તમારા કનેકà«àª¶àª¨àª¨à«‡ અટકાવી રહà«àª¯à«‹ છે.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">અવગણવામાં આવી કારણ કે <ph name="POLICY_NAME" />ને <ph name="VALUE" /> પર સેટ કરેલી નથી.</translation>
<translation id="1712552549805331520"><ph name="URL" /> તમારા સà«àª¥àª¾àª¨àª¿àª• કમà«àªªà«àª¯à«àªŸàª° પર કાયમી ધોરણે ડેટા સà«àªŸà«‹àª° કરવા માગે છે</translation>
<translation id="1713628304598226412">ટà«àª°à«‡ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">મેઇલબૉકà«àª¸ 3</translation>
<translation id="1718029547804390981">àªàª¨à«‹àªŸà«‡àªŸ કરવા માટે દસà«àª¤àª¾àªµà«‡àªœ ઘણો મોટો છે</translation>
<translation id="1721424275792716183">* ફીલà«àª¡ આવશà«àª¯àª• છે</translation>
+<translation id="1727613060316725209">પà«àª°àª®àª¾àª£àªªàª¤à«àª° માનà«àª¯ છે</translation>
<translation id="1727741090716970331">માનà«àª¯ કારà«àª¡ નંબર ઉમેરો</translation>
<translation id="1728677426644403582">તમે વેબ પેજનો સà«àª°à«‹àª¤ જોઈ રહà«àª¯àª¾àª‚ છો</translation>
<translation id="173080396488393970">આ પà«àª°àª•àª¾àª°àª¨à«àª‚ કારà«àª¡ સમરà«àª¥àª¿àª¤ નથી</translation>
@@ -246,7 +253,6 @@
<ph name="SITE" /> માટેની તમારી વિનંતી પૂરી કરતા અટકાવે છે. સાઇટ ઑપરેટર ઑરિજિન
પૉલિસીઓનો ઉપયોગ સાઇટ માટે સà«àª°àª•à«àª·àª¾ અને અનà«àª¯ પà«àª°à«‹àªªàª°à«àªŸà«€àª¨à«€ ગોઠવણી કરવા માટે કરી શકે છે.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">કૃપા કરી તમારા સમનà«àªµàª¯àª¨ પાસફà«àª°à«‡àªàª¨à«‡ અપડેટ કરો.</translation>
<translation id="1787142507584202372">તમારા ખà«àª²à«àª²àª¾ ટૅબà«àª¸ અહીં દેખાય છે</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, àªàª•àª¥à«€ વધારે કà«àª°àª¿àª¯àª¾àª“ ઉપલબà«àª§ છે, ઠબધી પર નજર કરવા માટે Tab કી દબાવો</translation>
@@ -275,10 +281,11 @@
<translation id="191374271204266022">JSON તરીકે કૉપિ કરો</translation>
<translation id="1914326953223720820">સેવાને અનàªàª¿àªª કરો</translation>
<translation id="1915697529809968049">CVCને બદલે Touch IDનો ઉપયોગ કરી�</translation>
-<translation id="1916770123977586577">આ સાઇટ પર તમારી અપડેટ કરેલ સેટિંગà«àª¸ લાગૠપાડવા માટે, આ પેજને ફરીથી લોડ કરો</translation>
+<translation id="1916770123977586577">આ સાઇટ પર તમારા અપડેટ કરેલા સેટિંગ લાગૠપાડવા માટે, આ પેજને ફરીથી લોડ કરો</translation>
<translation id="1919345977826869612">જાહેરાતો</translation>
<translation id="1919367280705858090">ભૂલના ચોકà«àª•àª¸ સંદેશ વડે સહાય મેળવો</translation>
<translation id="192020519938775529">{COUNT,plural, =0{કોઈ નહીં}=1{1 સાઇટ}one{# સાઇટ}other{# સાઇટ}}</translation>
+<translation id="1924727005275031552">નવà«àª‚</translation>
<translation id="1945968466830820669">તમે તમારી સંસà«àª¥àª¾àª¨àª¾ àªàª•àª¾àª‰àª¨à«àªŸ માટે àªàª•à«àª¸à«‡àª¸ ગà«àª®àª¾àªµà«€ શકો છો અથવા તમને ઓળખ ચોરીનો અનà«àª­àªµ થઈ શકે છે. Chromium તમને હમણાં જ તમારો પાસવરà«àª¡ બદલવાની ભલામણ કરે છે.</translation>
<translation id="1947454675006758438">ઉપર જમણી બાજà«àª સà«àªŸà«‡àªªàª² લગાવો</translation>
<translation id="1958218078413065209">તમારો સૌથી વધૠસà«àª•à«‹àª° <ph name="SCORE" /> છે.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">ટà«àª°à«‡ 7</translation>
<translation id="204357726431741734">તમારા Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ સà«àªŸà«‹àª° કરેલા પાસવરà«àª¡àª¨à«‹ ઉપયોગ કરવા માટે સાઇન ઇન કરો</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" />માં લખાયેલાં પેજનો અનà«àªµàª¾àª¦ થશે નહીં.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{જà«àª¯àª¾àª°à«‡ આ નિયંતà«àª°àª£ ચાલૠહોય અને સà«àªŸà«‡àªŸàª¸ સકà«àª°àª¿àª¯ હોય, તà«àª¯àª¾àª°à«‡ Chrome ઠનકà«àª•à«€ કરે છે કે તમારી તાજેતરની બà«àª°àª¾àª‰àªàª¿àª‚ગ પà«àª°àªµà«ƒàª¤à«àª¤àª¿ લોકોના કયા વિશાળ ગà«àª°à«‚પ અથવા "ગà«àª°à«‚પ" સાથે સૌથી વધૠસમાનતા ધરાવે છે. જાહેરાતકરà«àª¤àª¾àª“ ગà«àª°à«‚પ માટે જાહેરાતો પસંદ કરી શકે છે અને તમારી બà«àª°àª¾àª‰àªàª¿àª‚ગ પà«àª°àªµà«ƒàª¤à«àª¤àª¿àª¨à«‡ તમારા ડિવાઇસ પર ખાનગી રાખવામાં આવે છે. તમારà«àª‚ ગà«àª°à«‚પ દરરોજ અપડેટ થાય છે.}=1{જà«àª¯àª¾àª°à«‡ આ નિયંતà«àª°àª£ ચાલૠહોય અને સà«àªŸà«‡àªŸàª¸ સકà«àª°àª¿àª¯ હોય, તà«àª¯àª¾àª°à«‡ Chrome ઠનકà«àª•à«€ કરે છે કે તમારી તાજેતરની બà«àª°àª¾àª‰àªàª¿àª‚ગ પà«àª°àªµà«ƒàª¤à«àª¤àª¿ લોકોના કયા વિશાળ ગà«àª°à«‚પ અથવા "ગà«àª°à«‚પ" સાથે સૌથી વધૠસમાનતા ધરાવે છે. જાહેરાતકરà«àª¤àª¾àª“ ગà«àª°à«‚પ માટે જાહેરાતો પસંદ કરી શકે છે અને તમારી બà«àª°àª¾àª‰àªàª¿àª‚ગ પà«àª°àªµà«ƒàª¤à«àª¤àª¿àª¨à«‡ તમારા ડિવાઇસ પર ખાનગી રાખવામાં આવે છે. તમારà«àª‚ ગà«àª°à«‚પ દરરોજ અપડેટ થાય છે.}one{જà«àª¯àª¾àª°à«‡ આ નિયંતà«àª°àª£ ચાલૠહોય અને સà«àªŸà«‡àªŸàª¸ સકà«àª°àª¿àª¯ હોય, તà«àª¯àª¾àª°à«‡ Chrome ઠનકà«àª•à«€ કરે છે કે તમારી તાજેતરની બà«àª°àª¾àª‰àªàª¿àª‚ગ પà«àª°àªµà«ƒàª¤à«àª¤àª¿ લોકોના કયા વિશાળ ગà«àª°à«‚પ અથવા "ગà«àª°à«‚પ" સાથે સૌથી વધૠસમાનતા ધરાવે છે. જાહેરાતકરà«àª¤àª¾àª“ ગà«àª°à«‚પ માટે જાહેરાતો પસંદ કરી શકે છે અને તમારી બà«àª°àª¾àª‰àªàª¿àª‚ગ પà«àª°àªµà«ƒàª¤à«àª¤àª¿àª¨à«‡ તમારા ડિવાઇસ પર ખાનગી રાખવામાં આવે છે. તમારà«àª‚ ગà«àª°à«‚પ દર {NUM_DAYS} દિવસે અપડેટ થાય છે.}other{જà«àª¯àª¾àª°à«‡ આ નિયંતà«àª°àª£ ચાલૠહોય અને સà«àªŸà«‡àªŸàª¸ સકà«àª°àª¿àª¯ હોય, તà«àª¯àª¾àª°à«‡ Chrome ઠનકà«àª•à«€ કરે છે કે તમારી તાજેતરની બà«àª°àª¾àª‰àªàª¿àª‚ગ પà«àª°àªµà«ƒàª¤à«àª¤àª¿ લોકોના કયા વિશાળ ગà«àª°à«‚પ અથવા "ગà«àª°à«‚પ" સાથે સૌથી વધૠસમાનતા ધરાવે છે. જાહેરાતકરà«àª¤àª¾àª“ ગà«àª°à«‚પ માટે જાહેરાતો પસંદ કરી શકે છે અને તમારી બà«àª°àª¾àª‰àªàª¿àª‚ગ પà«àª°àªµà«ƒàª¤à«àª¤àª¿àª¨à«‡ તમારા ડિવાઇસ પર ખાનગી રાખવામાં આવે છે. તમારà«àª‚ ગà«àª°à«‚પ દર {NUM_DAYS} દિવસે અપડેટ થાય છે.}}</translation>
<translation id="2053553514270667976">પિન કોડ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 સૂચન}one{# સૂચન}other{# સૂચન}}</translation>
<translation id="2071692954027939183">નોટિફિકેશન ઑટોમૅટિક રીતે બà«àª²à«‰àª• કરવામાં આવà«àª¯àª¾ હતા કારણ કે તમે સામાનà«àª¯ રીતે તેમને મંજૂરી આપતા નથી</translation>
<translation id="2079545284768500474">છેલà«àª²à«‹ ફેરફાર રદ કરો</translation>
<translation id="20817612488360358">સિસà«àªŸàª® પà«àª°à«‰àª•à«àª¸à«€ સેટિંગ ઉપયોગમાં લેવા માટે સેટ છે પણ àªàª• સà«àªªàª·à«àªŸ પà«àª°à«‰àª•à«àª¸à«€ ગોઠવણીનો પણ ઉલà«àª²à«‡àª– કરાયેલો છે.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> માંથી <ph name="RESULT_NUMBER" /> પરિણામ</translation>
+<translation id="2085876078937250610">સાચવો…</translation>
<translation id="2088086323192747268">સિંક બટન મેનેજ કરો, તેમજ Chrome સેટિંગમાં તમે જે માહિતી સિંક કરવા ઇચà«àª›àª¤àª¾ હો, તે મેનેજ કરવા માટે Enter કી દબાવો</translation>
<translation id="2091887806945687916">ધà«àªµàª¨àª¿</translation>
<translation id="2094505752054353250">ડોમેન મેળ ખાતà«àª‚ નથી</translation>
@@ -379,15 +388,18 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> માટે વપરાશકરà«àª¤àª¾àª¨àª¾àª® અને પાસવરà«àª¡ આવશà«àª¯àª• છે.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" />ના રોજ સમાપà«àª¤ થાય છે</translation>
<translation id="2337852623177822836">તમારા વà«àª¯àªµàª¸à«àª¥àª¾àªªàª•à«‡ નિયંતà«àª°àª¿àª¤ કરેલ સેટિંગ</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" />, જોડી કરવા માગે છે</translation>
<translation id="2344028582131185878">ઑટોમૅટિક રીતે ડાઉનલોડ</translation>
<translation id="2346319942568447007">તમે કૉપિ કરેલી છબી</translation>
-<translation id="2354001756790975382">અનà«àª¯ બà«àª•àª®àª¾àª°à«àª•à«àª¸</translation>
+<translation id="2354001756790975382">અનà«àª¯ બà«àª•àª®àª¾àª°à«àª•</translation>
<translation id="2354430244986887761">Google સલામત બà«àª°àª¾àª‰àªàª¿àª‚ગને તાજેતરમાં <ph name="SITE" /> પર <ph name="BEGIN_LINK" />હાનિકારક àªàªªà«àª²àª¿àª•à«‡àª¶àª¨ મળી<ph name="END_LINK" />.</translation>
<translation id="2355395290879513365">તમે આ સાઇટ પર જોઈ રહà«àª¯àª¾àª‚ છો તે છબીઓને હà«àª®àª²àª¾àª–ોરો જોઈ શકે છે અને તેમને સંશોધિત કરીને તમને છેતરી શકે છે.</translation>
<translation id="2356070529366658676">કહો</translation>
<translation id="2357481397660644965">તમારà«àª‚ ડિવાઇસ <ph name="DEVICE_MANAGER" /> દà«àªµàª¾àª°àª¾ મેનેજ કરવામાં આવે છે અને તમારà«àª‚ àªàª•àª¾àª‰àª¨à«àªŸ <ph name="ACCOUNT_MANAGER" /> દà«àªµàª¾àª°àª¾ મેનેજ કરવામાં આવે છે.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{àªàª• દિવસથી ઓછા સમયમાં}=1{àªàª• દિવસમાં}one{{NUM_DAYS} દિવસમાં}other{{NUM_DAYS} દિવસમાં}}</translation>
<translation id="2359629602545592467">બહà«àªµàª¿àª§</translation>
<translation id="2359808026110333948">આગળ વધો</translation>
+<translation id="2359961752320758691">તમારો વરà«àªšà«àª¯à«àª…લ કારà«àª¡ નંબર લાગૠકરવામાં આવà«àª¯à«‹ છે.</translation>
<translation id="2367567093518048410">સà«àª¤àª°</translation>
<translation id="2372464001869762664">તમે કનà«àª«àª°à«àª® કરો પછી, આ સાઇટ સાથે તમારા Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚થી કારà«àª¡àª¨à«€ વિગતો શેર કરવામાં આવશે. તમારા Plex àªàª•àª¾àª‰àª¨à«àªŸàª¨à«€ વિગતોમાંથી CVC મેળવો.</translation>
<translation id="2380886658946992094">કાનૂની</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">આ વિતરણ પદà«àª§àª¤àª¿ ઉપલબà«àª§ નથી. કોઈ ભિનà«àª¨ પદà«àª§àª¤àª¿ અજમાવો.</translation>
<translation id="2396249848217231973">&amp;ડિલીટ રદ કરો</translation>
<translation id="2410754574180102685">સરકારી-કાનૂની</translation>
+<translation id="2413155254802890957">જૂનà«àª‚</translation>
<translation id="2413528052993050574">આ સરà«àªµàª° સાબિત કરી શકà«àª¯à«àª‚ નથી કે તે <ph name="DOMAIN" /> છે; તેનà«àª‚ સà«àª°àª•à«àª·àª¾ પà«àª°àª®àª¾àª£àªªàª¤à«àª° રદબાતલ થયà«àª‚ હશે. આ કોઈ ખોટી ગોઠવણીને કારણે થયà«àª‚ હશે અથવા કોઈ હà«àª®àª²àª¾àª–ોર તમારા કનેકà«àª¶àª¨àª¨à«‡ અટકાવી રહà«àª¯à«‹ છે.</translation>
<translation id="2414886740292270097">ઘાટà«àª‚</translation>
<translation id="2438874542388153331">જમણી બાજà«àª ચતà«àª·à«àª•à«‹àª£ કાણà«àª‚ પાડો</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">નીચે જમણી બાજà«àª સà«àªŸà«‡àªªàª² લાગાવો</translation>
<translation id="2523886232349826891">કારà«àª¡àª¨à«€ માહિતીને માતà«àª° આ ડિવાઇસ પર સાચવવામાં આવી છે</translation>
<translation id="2524461107774643265">વધૠમાહિતી ઉમેરો</translation>
-<translation id="2526590354069164005">ડેસà«àª•àªŸà«‰àªª</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{અને અનà«àª¯ 1}one{અને વધૠ#}other{અને વધૠ#}}</translation>
<translation id="2536110899380797252">સરનામà«àª‚ ઉમેરો</translation>
<translation id="2539524384386349900">શોધો</translation>
+<translation id="2541219929084442027">તમે છૂપા ટૅબમાં જà«àª“ છો ઠપેજ તમે તમારી બધી છૂપી ટૅબ બંધ કરી દો, ઠપછી તમારા બà«àª°àª¾àª‰àªàª°àª¨àª¾ ઇતિહાસ, કà«àª•à«€ સà«àªŸà«‹àª° અથવા શોધ ઇતિહાસમાં રહેશે નહીં. તમે ડાઉનલોડ કરો છો તે કોઈ પણ ફાઇલો અથવા તમે બનાવો છો તે બà«àª•àª®àª¾àª°à«àª• રાખવામાં આવશે.</translation>
<translation id="2544644783021658368">માતà«àª° àªàª• દસà«àª¤àª¾àªµà«‡àªœ</translation>
<translation id="254947805923345898">પૉલિસી મૂલà«àª¯ માનà«àª¯ નથી.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ઠઅમાનà«àª¯ પà«àª°àª¤àª¿àª¸àª¾àª¦ મોકલà«àª¯à«‹.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Chromeની સૌથી ઉચà«àªš લેવલની સà«àª°àª•à«àª·àª¾ મેળવવા માટે, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />વધારેલી સà«àª°àª•à«àª·àª¾ ચાલૠકરો<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" />નà«àª‚ સરà«àªµàª° IP àªàª¡à«àª°à«‡àª¸ ન મળà«àª¯à«àª‚.</translation>
<translation id="2639739919103226564">સà«àª¥àª¿àª¤àª¿:</translation>
+<translation id="264810637653812429">કોઈ સà«àª¸àª‚ગત ઉપકરણો મળà«àª¯àª¾àª‚ નથી.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome સેટિંગમાં તમારો બà«àª°àª¾àª‰àªàª¿àª‚ગ ઇતિહાસ, કà«àª•à«€, કૅશ મેમરી અને બીજà«àª‚ ઘણà«àª‚ સાફ કરવા માટે Tab પછી Enter દબાવો</translation>
<translation id="2650446666397867134">ફાઇલની àªàª•à«àª¸à«‡àª¸ નકારવામાં આવી હતી</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">ફરીથી લોંચ કરો</translation>
<translation id="2803306138276472711">Google Safe Browsing ને તાજેતરમાં <ph name="SITE" /> પર <ph name="BEGIN_LINK" />મૉલવેર મળà«àª¯à«àª‚<ph name="END_LINK" />. વેબસાઇટà«àª¸ કે જે સામાનà«àª¯ રીતે સà«àª°àª•à«àª·àª¿àª¤ છે તે કà«àª¯àª¾àª°à«‡àª• મૉલવેરથી દૂષિત હોય છે.</translation>
<translation id="2807052079800581569">છબીની Y અકà«àª· પરની સà«àª¥àª¿àª¤àª¿</translation>
+<translation id="2820957248982571256">સà«àª•à«…ન કરી રહà«àª¯àª¾àª‚ છીàªâ€¦</translation>
<translation id="2824775600643448204">સરનામà«àª‚ અને શોધ બાર</translation>
<translation id="2826760142808435982">કનેકà«àª¶àª¨ <ph name="CIPHER" />નો ઉપયોગ કરીને àªàª¨à«àª•à«àª°àª¿àªªà«àªŸ અને પà«àª°àª®àª¾àª£àª¿àª¤ કરેલà«àª‚ં છે અને મà«àª–à«àª¯ àªàª•à«àª¸àªšà«‡àª¨à«àªœ મેકેનિàªà«àª® તરીકે <ph name="KX" />નો ઉપયોગ કરે છે.</translation>
<translation id="2835170189407361413">ફોરà«àª® સાફ કરો</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">આમંતà«àª°àª£ (àªàª¨à«àªµàª²àªª)</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="2859806420264540918">આ સાઇટ ઘૃણાસà«àªªàª¦ અથવા ભà«àª°àª¾àª®àª• જાહેરાતો બતાવે છે.</translation>
+<translation id="287596039013813457">ફà«àª°à«‡àª¨à«àª¡àª²à«€</translation>
+<translation id="2876489322757410363">બાહà«àª¯ àªàªªà«àª²àª¿àª•à«‡àª¶àª¨ મારફતે ચà«àª•àªµàª£à«€ કરવા માટે છૂપો મોડ છોડી રહà«àª¯àª¾àª‚ છીàª. ચાલૠરાખીàª?</translation>
<translation id="2878197950673342043">પોસà«àªŸàª° ફોલà«àª¡</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">વિંડોનà«àª‚ સà«àª¥àª¾àª¨ નિયોજન</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (àªàª¨à«àªµàª²àªª)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome સેટિંગમાં સલામતી માટે તપાસ ચલાવવા માટે Tab પછી Enter દબાવો</translation>
<translation id="3061707000357573562">પૅચ સેવા</translation>
-<translation id="3064966200440839136">બાહà«àª¯ àªàªªà«àª²àª¿àª•à«‡àª¶àª¨ મારફતે ચà«àª•àªµàª£à«€ કરવા માટે છà«àªªà«‹ મોડ છોડી રહà«àª¯àª¾àª‚ છીàª. તો ચાલૠરાખીàª?</translation>
<translation id="306573536155379004">ગેમ શરૂ થઈ ગઈ છે.</translation>
<translation id="3080254622891793721">ગà«àª°àª¾àª«àª¿àª•</translation>
<translation id="3086579638707268289">વેબ પરની તમારી પà«àª°àªµà«ƒàª¤à«àª¤àª¿àª¨à«‡ મોનિટર કરવામાં આવે છે</translation>
@@ -571,9 +587,8 @@
<translation id="3150653042067488994">અસà«àª¥àª¾àª¯à«€ સરà«àªµàª° ભૂલ</translation>
<translation id="3154506275960390542">આ પૃષà«àª àª®àª¾àª‚ àªàª• ફૉરà«àª® છે, જે કદાચ સà«àª°àª•à«àª·àª¿àª¤ રીતે સબમિટ નહીં થાય. જે ડેટા તમે મોકલો તેને પરિવહન દરમિયાન અનà«àª¯ લોકો જોઈ શકશે અથવા સરà«àªµàª° જે મેળવે, તે બદલવા માટે હà«àª®àª²àª¾àª–ોર ફેરફાર કરી શકશે.</translation>
<translation id="315504272643575312"><ph name="MANAGER" /> દà«àªµàª¾àª°àª¾ તમારà«àª‚ àªàª•àª¾àª‰àª¨à«àªŸ મેનેજ કરવામાં આવે છે.</translation>
-<translation id="3157931365184549694">પà«àª¨àªƒàª¸à«àª¥àª¾àªªàª¿àª¤ કરો</translation>
+<translation id="3157931365184549694">રિસà«àªŸà«‹àª° કરો</translation>
<translation id="3162559335345991374">તમે ઉપયોગ કરી રહà«àª¯àª¾ છો તે વાઇ-ફાઇને તેના લોગિન પેજની મà«àª²àª¾àª•àª¾àª¤ લેવાની જરૂર હોઈ શકે છે.</translation>
-<translation id="3167968892399408617">તમે છૂપા ટૅબમાં જà«àª“ છો ઠપેજ તમે તમારા બધા છૂપા ટૅબ બંધ કરી દો, ઠપછી તમારા બà«àª°àª¾àª‰àªàª°àª¨àª¾ ઇતિહાસ, કà«àª•à«€ સà«àªŸà«‹àª° અથવા શોધ ઇતિહાસમાં રહેશે નહિ. તમે ડાઉનલોડ કરો છો તે કોઈ પણ ફાઇલો અથવા તમે બનાવો છો તે બà«àª•àª®àª¾àª°à«àª• રાખવામાં આવશે.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">આઇલેનà«àª¡</translation>
<translation id="3176929007561373547">પà«àª°à«‰àª•à«àª¸à«€ સરà«àªµàª° કારà«àª¯ કરી રહà«àª¯à«àª‚ છે તેની ખાતરી કરવા માટે તમારà«àª‚ પà«àª°à«‰àª•à«àª¸à«€ સેટિંગ તપાસો
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">તમારા ડિવાઇસ અને બà«àª°àª¾àª‰àªàª° વિશે વરà«àªàª¨ માહિતી</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> માટે CVC દાખલ કરો</translation>
<translation id="3234666976984236645">હંમેશાં આ સાઇટ પરનà«àª‚ મહતà«àª¤à«àªµàª¨à«àª‚ કનà«àªŸà«‡àª¨à«àªŸ શોધો</translation>
+<translation id="3249845759089040423">ગà«àª°à«‚વી</translation>
<translation id="3252266817569339921">ફà«àª°à«‡àª¨à«àªš</translation>
<translation id="3266793032086590337">મૂલà«àª¯ (વિરોધાભાસ)</translation>
<translation id="3268451620468152448">ઓપન ટેબà«àª¸</translation>
<translation id="3270847123878663523">&amp;પà«àª¨àªƒàª•à«àª°àª®àª¾àª‚કિત કરવà«àª‚ પૂરà«àªµàªµàª¤à« કરો</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" />, કનેકà«àªŸ કરવા માગે છે</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">તમારી સંસà«àª¥àª¾, <ph name="ENROLLMENT_DOMAIN" />ઠસેટિંગ અથવા પૉલિસી જેવી અમà«àª• માહિતી નીચેની વેબસાઇટને મોકલી છે.</translation>
<translation id="3282497668470633863">કારà«àª¡ પર નામ ઉમેરો</translation>
@@ -654,6 +671,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates સરà«àªµàª°àª¨àª¾ નમૂનાની àªàª• કે તેથી વધૠURI અમાનà«àª¯ છે અને તેનો ઉપયોગ કરવામાં આવશે નહીં.</translation>
<translation id="3431636764301398940">આ ડિવાઇસ પર આ કારà«àª¡ સાચવો</translation>
<translation id="3432601291244612633">પેજ બંધ કરો</translation>
+<translation id="3435738964857648380">સà«àª°àª•à«àª·àª¾</translation>
<translation id="3435896845095436175">ચાલૠકરો</translation>
<translation id="3438829137925142401">તમારા Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ સાચવેલા પાસવરà«àª¡àª¨à«‹ ઉપયોગ કરો</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -696,7 +714,10 @@
<translation id="3584299510153766161">નીચેની બાજà«àª બે કાણાં પાડો</translation>
<translation id="3586931643579894722">વિગતો છà«àªªàª¾àªµà«‹</translation>
<translation id="3587738293690942763">મધà«àª¯</translation>
+<translation id="3590643883886679995">તમે છૂપા મોડમાંથી બહાર નીકળો, તે પછી સાઇન-ઇન ડેટા આ ડિવાઇસ પર સà«àªŸà«‹àª° કરવામાં આવશે.</translation>
+<translation id="359126217934908072">મહિનો/વરà«àª·:</translation>
<translation id="3592413004129370115">ઇટાલિયન (àªàª¨à«àªµàª²àªª)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{તમે કોઈપણ સમયે તમારà«àª‚ ગà«àª°à«‚પ રીસેટ કરી શકો છો. નવા ગà«àª°à«‚પમાં જોડાવામાં આશરે àªàª• દિવસ લાગે છે.}=1{તમે કોઈપણ સમયે તમારà«àª‚ ગà«àª°à«‚પ રીસેટ કરી શકો છો. નવા ગà«àª°à«‚પમાં જોડાવામાં આશરે àªàª• દિવસ લાગે છે.}one{તમે કોઈપણ સમયે તમારà«àª‚ ગà«àª°à«‚પ રીસેટ કરી શકો છો. નવા ગà«àª°à«‚પમાં જોડાવામાં આશરે {NUM_DAYS} દિવસ લાગે છે.}other{તમે કોઈપણ સમયે તમારà«àª‚ ગà«àª°à«‚પ રીસેટ કરી શકો છો. નવા ગà«àª°à«‚પમાં જોડાવામાં આશરે {NUM_DAYS} દિવસ લાગે છે.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">તમારા વà«àª¯àªµàª¸à«àª¥àª¾àªªàª• દà«àªµàª¾àª°àª¾ બà«àª²à«‰àª• કરેલી àªàªªà«àª²àª¿àª•à«‡àª¶àª¨</translation>
<translation id="3608932978122581043">ફીડ ઓરિàªàª¨à«àªŸà«‡àª¶àª¨</translation>
@@ -705,13 +726,13 @@
<translation id="3615877443314183785">àªàª• માનà«àª¯ સમાપà«àª¤àª¿ તારીખ દાખલ કરો</translation>
<translation id="36224234498066874">બà«àª°àª¾àª‰àªàª¿àª‚ગ ડેટા સાફ કરો...</translation>
<translation id="362276910939193118">પૂરà«àª£ ઇતિહાસ બતાવો</translation>
-<translation id="3625635938337243871">તમે 'છૂપા મોડ'માંથી બહાર નીકળો, તે પછી સાઇન-ઇન ડેટા આ ડિવાઇસ પર સà«àªŸà«‹àª° કરવામાં આવશે.</translation>
<translation id="3630155396527302611">જો તે પહેલાંથી જ નેટવરà«àª• àªàª•à«àª¸à«‡àª¸ કરવા માટે મંજૂર પà«àª°à«‹àª—à«àª°àª¾àª® તરીકે સૂચિબદà«àª§ હોય, તો
તેને સૂચિમાંથી દૂર કરી અને તેને ફરીથી ઉમેરવાનો પà«àª°àª¯àª¾àª¸ કરો.</translation>
<translation id="3630699740441428070">આ ડિવાઇસના વà«àª¯àªµàª¸à«àª¥àª¾àªªàª•à«‹àª તમારà«àª‚ નેટવરà«àª• કનેકà«àª¶àª¨ ગોઠવà«àª¯à«àª‚ છે, જે અનà«àª¸àª¾àª° તેઓ તમે મà«àª²àª¾àª•àª¾àª¤ લીધેલી વેબસાઇટ સહિત તમારો નેટવરà«àª• ટà«àª°àª¾àª«àª¿àª• જોઈ શકે તેમ બની શકે છે.</translation>
<translation id="3631244953324577188">બાયોમેટà«àª°àª¿àª•à«àª¸</translation>
<translation id="3633738897356909127">Chrome અપડેટ કરો બટન, તમારા Chrome સેટિંગમાંથી Chrome અપડેટ કરવા માટે Enter દબાવો</translation>
<translation id="3634530185120165534">ટà«àª°à«‡ 5</translation>
+<translation id="3637662659967048211">Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ સાચવો</translation>
<translation id="3640766068866876100">અનà«àª•à«àª°àª®àª£àª¿àª•àª¾-4x6-Ext</translation>
<translation id="3642638418806704195">àªàªªà«àª²àª¿àª•à«‡àª¶àª¨:</translation>
<translation id="3650584904733503804">માનà«àª¯àª¤àª¾ સફળ</translation>
@@ -752,6 +773,7 @@
<translation id="3781428340399460090">ચળકતો ગà«àª²àª¾àª¬à«€</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">બà«àª²à«‚ટૂથ ડિવાઇસ</translation>
+<translation id="3787675388804467730">વરà«àªšà«àª¯à«àª…લ કારà«àª¡ નંબર</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> માં સમાપà«àª¤ થાય છે</translation>
<translation id="3789155188480882154">કદ 16</translation>
<translation id="3789841737615482174">ઇનà«àª¸à«àªŸà«‹àª² કરો</translation>
@@ -771,6 +793,7 @@
<translation id="3841184659773414994">ફાઇલ હૅનà«àª¡àª²àª°</translation>
<translation id="385051799172605136">પાછળ</translation>
<translation id="3858027520442213535">તારીખ અને સમય અપડેટ કરો</translation>
+<translation id="3881478300875776315">ઓછી પંકà«àª¤àª¿àª“ બતાવો</translation>
<translation id="3884278016824448484">વિરોધાભાસી ઉપકરણ ઓળખકરà«àª¤àª¾</translation>
<translation id="3885155851504623709">પેરિશ</translation>
<translation id="388632593194507180">નિરીકà«àª·àª£ કરતà«àª‚ જણાયà«àª‚</translation>
@@ -796,6 +819,7 @@
<translation id="397105322502079400">ગણના કરી રહà«àª¯à«àª‚ છે...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> અવરોધિત છે</translation>
<translation id="3973357910713125165">Chromeની સલામતી માટે તપાસ ચલાવો બટન, Chrome સેટિંગમાં સલામતી માટે તપાસ ચલાવવા માટે Enter દબાવો</translation>
+<translation id="3986705137476756801">હાલ પૂરતà«àª‚, લાઇવ કૅપà«àª¶àª¨àª¨à«€ સà«àªµàª¿àª§àª¾ બંધ કરો</translation>
<translation id="3987405730340719549">Chromeની તપાસણીમાં આ સાઇટ બનાવટી અથવા કપટપૂરà«àª£ હોઈ શકવાનà«àª‚ જણાઈ આવà«àª¯à«àª‚ છે.
જો તમે àªàª® માનતા હો કે આ ભૂલમાં બતાવવામાં આવà«àª¯à«àª‚ છે, તો કૃપા કરીને https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appealsની મà«àª²àª¾àª•àª¾àª¤ લો.</translation>
@@ -837,7 +861,7 @@
<translation id="4152318981910038897">{COUNT,plural, =1{પેજ 1}one{પેજ {COUNT}}other{પેજ {COUNT}}}</translation>
<translation id="4154664944169082762">ફિંગરપà«àª°à«€àª‚ટà«àª¸</translation>
<translation id="4159784952369912983">જાંબલી</translation>
-<translation id="4165986682804962316">સાઇટ સેટિંગà«àª¸</translation>
+<translation id="4165986682804962316">સાઇટ સેટિંગ</translation>
<translation id="4171400957073367226">ખોટી ચકાસણી સહી</translation>
<translation id="4171489848299289778"><ph name="RESULT_MODIFIED_DATE" /> - <ph name="RESULT_OWNER" /> - <ph name="RESULT_PRODUCT_SOURCE" /></translation>
<translation id="4172051516777682613">હંમેશા બતાવો</translation>
@@ -892,13 +916,14 @@
<translation id="4275830172053184480">તમારà«àª‚ ઉપકરણ પà«àª¨àªƒàªªà«àª°àª¾àª°àª‚ભ કરો</translation>
<translation id="4277028893293644418">પાસવરà«àª¡ રીસેટ કરો</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{આ કારà«àª¡àª¨à«‡ તમારા Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ સાચવવામાં આવà«àª¯à«àª‚ છે}one{આ કારà«àª¡àª¨à«‡ Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ સાચવવામાં આવà«àª¯àª¾àª‚ છે}other{આ કારà«àª¡àª¨à«‡ Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ સાચવવામાં આવà«àª¯àª¾àª‚ છે}}</translation>
+<translation id="4287885627794386150">અજમાયશ માટે યોગà«àª¯àª¤àª¾ ધરાવે છે, પણ સકà«àª°àª¿àª¯ નથી</translation>
<translation id="4297502707443874121">પેજ <ph name="THUMBNAIL_PAGE" /> માટે થંબનેલ</translation>
<translation id="42981349822642051">વિસà«àª¤à«ƒàª¤ કરો</translation>
<translation id="4300675098767811073">જમણી બાજà«àª àªàª•àª¥à«€ વધૠકાણાં પાડો</translation>
<translation id="4302514097724775343">રમવા માટે, ડાયનાસોર પર ટૅપ કરો</translation>
<translation id="4302965934281694568">Chou3 (àªàª¨à«àªµàª²àªª)</translation>
<translation id="4305666528087210886">તમારી ફાઇલ àªàª•à«àª¸à«‡àª¸ કરી શકાઈ નથી</translation>
-<translation id="4305817255990598646">સà«àªµàª¿àªš</translation>
+<translation id="4306529830550717874">સરનામà«àª‚ સાચવીàª?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">અવરોધિત કરો (ડિફૉલà«àªŸ)</translation>
<translation id="4314815835985389558">સિંક મેનેજ કરો</translation>
@@ -925,6 +950,7 @@
<translation id="4377125064752653719">તમે <ph name="DOMAIN" /> પર પહોંચવાનો પà«àª°àª¯àª¾àª¸ કરà«àª¯à«‹, પણ સરà«àªµàª° દà«àªµàª¾àª°àª¾ પà«àª°àª¸à«àª¤à«àª¤ કરવામાં આવેલà«àª‚ પà«àª°àª®àª¾àª£àªªàª¤à«àª° તેના રજૂકરà«àª¤àª¾ દà«àªµàª¾àª°àª¾ જ રદ કરવામાં આવà«àª¯à«àª‚ છે. આનો અરà«àª¥ છે કે સરà«àªµàª°à«‡ પà«àª°àª¸à«àª¤à«àª¤ કરેલા સà«àª°àª•à«àª·àª¾ પà«àª°àª®àª¾àª£àªªàª¤à«àª°à«‹ પૂરà«àª£àªªàª£à«‡ વિશà«àªµàª¸àª¨à«€àª¯ નથી. તમે કોઈ હà«àª®àª²àª¾àª–ોર જોડે વાત કરતા હોઈ શકો છો.</translation>
<translation id="4378154925671717803">ફોન</translation>
<translation id="4390472908992056574">બà«àª°àª¿àª®</translation>
+<translation id="4406883609789734330">લાઇવ કૅપà«àª¶àª¨</translation>
<translation id="4406896451731180161">શોધ પરિણામો</translation>
<translation id="4408413947728134509">કà«àª•à«€ <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">હમણાં જ કોઈ છેતરામણી સાઇટ પર તમે તમારો પાસવરà«àª¡ દાખલ કરà«àª¯à«‹. Chrome <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> તેમજ તમે આ પાસવરà«àª¡àª¨à«‹ જà«àª¯àª¾àª‚ ઉપયોગ કરતા હોય તે અનà«àª¯ સાઇટ પર જઈને તેને હમણાં જ બદલવાનો સà«àªàª¾àªµ આપે છે.</translation>
@@ -937,7 +963,6 @@
<translation id="4435702339979719576">પોસà«àªŸàª•àª¾àª°à«àª¡)</translation>
<translation id="443673843213245140">પà«àª°à«‰àª•à«àª¸à«€àª¨à«‹ ઉપયોગ બંધ કરેલો છે પણ àªàª• સà«àªªàª·à«àªŸ પà«àª°à«‰àª•à«àª¸à«€ ગોઠવણીનો ઉલà«àª²à«‡àª– કરેલો છે.</translation>
<translation id="4464826014807964867">તમારી સંસà«àª¥àª¾ દà«àªµàª¾àª°àª¾ પà«àª°àª¦àª¾àª¨ કરવામાં આવેલી માહિતી ધરાવતી વેબસાઇટ</translation>
-<translation id="4466881336512663640">ફોરà«àª®àª¨àª¾ ફેરફારો ગà«àª®àª¾àªµàª¶à«‹. શà«àª‚ તમે ખરેખર ચાલૠરાખવા માગો છો?</translation>
<translation id="4476953670630786061">આ ફોરà«àª® સà«àª°àª•à«àª·àª¿àª¤ નથી. ઑટોમૅટિક રીતે ભરવાની સà«àªµàª¿àª§àª¾ બંધ કરવામાં આવી છે.</translation>
<translation id="4477350412780666475">આગલો ટà«àª°à«…ક</translation>
<translation id="4482953324121162758">આ સાઇટનો અનà«àªµàª¾àª¦ થશે નહીં.</translation>
@@ -971,6 +996,7 @@
<translation id="4594403342090139922">&amp;ડિલીટ રદ કરો</translation>
<translation id="4597348597567598915">કદ 8</translation>
<translation id="4600854749408232102">C6/C5 (àªàª¨à«àªµàª²àªª)</translation>
+<translation id="4606870351894164739">અસરકારક</translation>
<translation id="4628948037717959914">ફોટો</translation>
<translation id="4631649115723685955">કૅશબૅક લિંક કરà«àª¯à«àª‚ છે</translation>
<translation id="4636930964841734540">માહિતી</translation>
@@ -990,6 +1016,7 @@
<translation id="4691835149146451662">સà«àª¥àª¾àªªàª¤à«àª¯-A (àªàª¨à«àªµàª²àªª)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">બાજà«</translation>
+<translation id="4702656508969495934">લાઇવ કૅપà«àª¶àª¨ જોઈ શકાય છે, ફોકસ કરવા માટે વિનà«àª¡à«‹ સà«àªµàª¿àªšàª°àª¨à«‹ ઉપયોગ કરો</translation>
<translation id="4708268264240856090">તમારà«àª‚ કનેકà«àª¶àª¨ અવરોધાયà«àª‚ હતà«àª‚</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows નેટવરà«àª• ડાયગà«àª¨à«‹àª¸à«àªŸàª¿àª•à«àª¸ ચલાવી રહà«àª¯àª¾àª‚ છે<ph name="END_LINK" /></translation>
@@ -1003,6 +1030,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> શોધ સૂચન</translation>
<translation id="4742407542027196863">પાસવરà«àª¡ મેનેજ કરો…</translation>
<translation id="4744603770635761495">અમલ કરવાયોગà«àª¯ પાથ</translation>
+<translation id="4749011317274908093">તમે છૂપા મોડમાં ગયા છો</translation>
<translation id="4750917950439032686">તમારી માહિતી (ઉદાહરણ તરીકે, પાસવરà«àª¡à«àª¸ અથવા કà«àª°à«‡àª¡àª¿àªŸ કારà«àª¡ નંબરà«àª¸) ખાનગી હોય છે જà«àª¯àª¾àª°à«‡ તે આ સાઇટ પર મોકલવામાં આવે.</translation>
<translation id="4756388243121344051">&amp;ઇતિહાસ</translation>
<translation id="4758311279753947758">સંપરà«àª• માહિતી ઉમેરો</translation>
@@ -1032,6 +1060,8 @@
<translation id="4813512666221746211">નેટવરà«àª• ભૂલ</translation>
<translation id="4816492930507672669">પૃષà«àª  પર ફિટ</translation>
<translation id="4819347708020428563">ટીકાટિપà«àªªàª£à«€àª®àª¾àª‚ ફેરફાર કરીને ડિફૉલà«àªŸ વà«àª¯à«‚ પસંદ કરીàª?</translation>
+<translation id="4825507807291741242">શકà«àª¤àª¿àª¶àª¾àª³à«€</translation>
+<translation id="4838327282952368871">સà«àªµàªªà«àª¨àª¶à«€àª²</translation>
<translation id="484462545196658690">ઑટો</translation>
<translation id="4850886885716139402">જà«àª“</translation>
<translation id="485316830061041779">જરà«àª®àª¨</translation>
@@ -1129,7 +1159,7 @@
<translation id="5171689220826475070">Fanfold-યà«àª°à«‹àªªàª¿àª¯àª¨</translation>
<translation id="5172758083709347301">મશીન</translation>
<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> માં નથી? આ ભૂલની જાણ કરો </translation>
-<translation id="5190835502935405962">બà«àª•àª®àª¾àª°à«àª•à«àª¸ બાર</translation>
+<translation id="5190835502935405962">બà«àª•àª®àª¾àª°à«àª• બાર</translation>
<translation id="519422657042045905">ટીકાટિપà«àªªàª£à«€ ઉપલબà«àª§ નથી</translation>
<translation id="5201306358585911203">આ પેજ પરનà«àª‚ શામેલ કરેલ પેજ કહે છે કે</translation>
<translation id="5205222826937269299">નામ આવશà«àª¯àª• છે</translation>
@@ -1168,6 +1198,7 @@
<translation id="5314967030527622926">બà«àª•àª²à«‡àªŸ મારà«àª•àª°</translation>
<translation id="5316812925700871227">ઘડિયાળની વિપરિત દિશામાં ફેરવો</translation>
<translation id="5317780077021120954">સાચવો</translation>
+<translation id="5321288445143113935">મોટà«àª‚ કરà«àª¯à«àª‚</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> માંથી <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">સંપરà«àª•àª¨à«€ માહિતી પસંદ કરો</translation>
<translation id="5327248766486351172">નામ</translation>
@@ -1175,11 +1206,13 @@
<translation id="5332219387342487447">શિપિંગ પદà«àª§àª¤àª¿</translation>
<translation id="5333022057423422993">Chromeને તમે હમણાં જ ડેટા ઉલà«àª²àª‚ઘનમાં ઉપયોગમાં લીધેલો પાસવરà«àª¡ મળà«àª¯à«‹ છે. તમારા àªàª•àª¾àª‰àª¨à«àªŸàª¨à«‡ સà«àª°àª•à«àª·àª¿àª¤ રાખવા માટે, અમે તમારા સાચવેલા પાસવરà«àª¡àª¨à«‡ ચેક કરવાનો સà«àªàª¾àªµ આપીઠછીàª.</translation>
<translation id="5334013548165032829">વિગતવાર સિસà«àªŸàª® લૉગ</translation>
+<translation id="5334145288572353250">સરનામà«àª‚ સાચવીàª?</translation>
<translation id="5340250774223869109">àªàªªà«àª²àª¿àª•à«‡àª¶àª¨ બà«àª²à«‰àª• કરેલી છે</translation>
<translation id="534295439873310000">NFC ડિવાઇસ</translation>
<translation id="5344579389779391559">આ પેજ કદાચ તમારી પાસેથી શà«àª²à«àª• વસૂલ કરવાનો પà«àª°àª¯àª¾àª¸ કરી શકે છે</translation>
<translation id="5355557959165512791">તમે અતà«àª¯àª¾àª°à«‡ <ph name="SITE" />ની મà«àª²àª¾àª•àª¾àª¤ લઈ શકતાં નથી કારણ કે તેનà«àª‚ પà«àª°àª®àª¾àª£àªªàª¤à«àª° રદબાતલ કરવામાં આવà«àª¯à«àª‚ છે. નેટવરà«àª•àª®àª¾àª‚ ભૂલ આવવી અને હà«àª®àª²àª¾ થવા સામાનà«àª¯ રીતે અસà«àª¥àª¾àª¯à«€ હોય છે, તેથી આ પેજ સંભવિત રૂપે થોડા સમય પછી કારà«àª¯ કરશે.</translation>
<translation id="536296301121032821">પૉલિસી સેટિંગ સà«àªŸà«‹àª° કરવામાં નિષà«àª«àª³ થયાં</translation>
+<translation id="5363309033720083897">તમારા વà«àª¯àªµàª¸à«àª¥àª¾àªªàª• દà«àªµàª¾àª°àª¾ મંજૂરી આપવામાં આવેલો સીરિયલ પોરà«àªŸ</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="5386426401304769735">આ સાઇટ માટેની પà«àª°àª®àª¾àª£àªªàª¤à«àª° શà«àª°à«ƒàª‚ખલા SHA-1 નો ઉપયોગ કરીને સહી કરેલ પà«àª°àª®àª¾àª£àªªàª¤à«àª° ધરાવે છે.</translation>
@@ -1188,6 +1221,7 @@
<translation id="5398772614898833570">જાહેરાતો અવરોધિત કરી</translation>
<translation id="5400836586163650660">ગà«àª°à«‡</translation>
<translation id="540969355065856584">આ સરà«àªµàª° સાબિત કરી શકà«àª¯à«àª‚ નથી કે તે <ph name="DOMAIN" /> છે; તેનà«àª‚ સà«àª°àª•à«àª·àª¾ પà«àª°àª®àª¾àª£àªªàª¤à«àª° આ સમયે માનà«àª¯ નથી. આ કોઇ ખોટી ગોઠવણીને કારણે થયà«àª‚ હોય અથવા કોઈ હà«àª®àª²àª¾àª–ોર તમારા કનેકà«àª¶àª¨àª¨à«‡ અટકાવી રહà«àª¯à«‹ હોઇ શકે છે.</translation>
+<translation id="541143247543991491">કà«àª²àª¾àª‰àª¡ (સિસà«àªŸàª®-વà«àª¯àª¾àªªà«€)</translation>
<translation id="541416427766103491">સà«àªŸà«…કર 4</translation>
<translation id="5421136146218899937">બà«àª°àª¾àª‰àªàª¿àª‚ગ ડેટા સાફ કરો...</translation>
<translation id="5426179911063097041"><ph name="SITE" />તમને નોટિફિકેશનો મોકલવા માગે છે</translation>
@@ -1201,6 +1235,7 @@
<translation id="5455374756549232013">ખરાબ પૉલિસી ટાઇમસà«àªŸà«‡àª®à«àªª</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" /> વધà«}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="5463625433003343978">ડિવાઇસ શોધી રહà«àª¯àª¾àª‚ છીàª...</translation>
<translation id="5469868506864199649">ઇટાલિયન</translation>
<translation id="5470861586879999274">&amp;ફરી ફેરફાર કરો</translation>
<translation id="5478437291406423475">B6/C4 (àªàª¨à«àªµàª²àªª)</translation>
@@ -1228,7 +1263,7 @@
<translation id="5542280138350899197">સà«àª°àª•à«àª·àª¾ સેટિંગના બટન મેનેજ કરો, તેમજ Chrome સેટિંગમાં Safe Browsing જેવી તમારી બીજી ઘણી સà«àªµàª¿àª§àª¾àª“ મેનેજ કરવા માટે Enter કી દબાવો</translation>
<translation id="5545756402275714221">તમારા માટે લેખ</translation>
<translation id="5552137475244467770">Chrome તમારા પાસવરà«àª¡àª¨à«‡ ઑનલાઇન પà«àª°àª•àª¾àª¶àª¿àª¤ કરવામાં આવેલી સૂચિઓ સામે સમય સમય પર ચેક કરે છે. આમ કરતી વખતે તમારા પાસવરà«àª¡ અને વપરાશકરà«àª¤àª¾ નામ àªàª¨à«àª•à«àª°àª¿àªªà«àªŸà«‡àª¡ હોય છે, જેથી Google સહિત, કોઈપણ તેને વાંચી શકતà«àª‚ નથી.</translation>
-<translation id="5556459405103347317">ફરિથી લોડ કરો</translation>
+<translation id="5556459405103347317">ફરીથી લોડ કરો</translation>
<translation id="5560088892362098740">સમાપà«àª¤àª¿ તારીખ</translation>
<translation id="55635442646131152">દસà«àª¤àª¾àªµà«‡àªœ આઉટલાઇન</translation>
<translation id="5565735124758917034">સકà«àª°àª¿àª¯</translation>
@@ -1250,7 +1285,6 @@
<translation id="5624120631404540903">પાસવરà«àª¡à«àª¸àª¨à«àª‚ સંચાલન કરો</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="563324245173044180">ભà«àª°àª¾àª®àª• કનà«àªŸà«‡àª¨à«àªŸ બà«àª²à«‰àª• કરી</translation>
<translation id="5644090287519800334">બાજૠ1 છબીને X અકà«àª· પર ખસેડો</translation>
@@ -1289,12 +1323,12 @@
<translation id="5785756445106461925">વળી, આ પૃષà«àª àª®àª¾àª‚ અનà«àª¯ àªàªµàª¾ સાધનો છે જે સà«àª°àª•à«àª·àª¿àª¤ નથી. ટà«àª°àª¾àª‚àªàª¿àªŸàª®àª¾àª‚ હોવા પર અનà«àª¯ લોકો દà«àªµàª¾àª°àª¾ આ સાધનો જોઈ શકાય છે અને પૃષà«àª àª¨à«‹ દેખાવ બદલવા માટે હà«àª®àª²àª¾àª–ોર દà«àªµàª¾àª°àª¾ સંશોધિત કરવામાં આવી શકે છે.</translation>
<translation id="5786044859038896871">શà«àª‚ તમે તમારી કારà«àª¡ માહિતી ભરવા માગો છો?</translation>
<translation id="578633867165174378">Chromeને તમે હમણાં જ ડેટા ઉલà«àª²àª‚ઘનમાં ઉપયોગમાં લીધેલો પાસવરà«àª¡ મળà«àª¯à«‹ છે. અમે આ પાસવરà«àª¡ હમણાં જ બદલવાનો સà«àªàª¾àªµ આપીઠછીàª.</translation>
-<translation id="5798290721819630480">ફેરફારો કાઢી નાખી�</translation>
<translation id="5803412860119678065">શà«àª‚ તમે તમારી <ph name="CARD_DETAIL" /> માહિતી ભરવા માગો છો?</translation>
<translation id="5804241973901381774">પરવાનગીઓ</translation>
<translation id="5804427196348435412">NFC ડિવાઇસનો ઉપયોગ કરો</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> સાથેના તમારા કનેકà«àª¶àª¨àª¨à«‡ ઑબà«àª¸à«‹àª²àª¿àªŸ સાઇફર સà«àª¯à«‚ટનો ઉપયોગ કરીને àªàª¨à«àª•à«àª°àª¿àªªà«àªŸ કરાયà«àª‚ છે.</translation>
<translation id="5813119285467412249">&amp;ઉમેરવà«àª‚ ફરી કરો</translation>
+<translation id="5817918615728894473">જોડી કરો</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{તમે ચà«àª•àªµàª£à«€ કરશો તà«àª¯àª¾àª°à«‡ આ કારà«àª¡àª¥à«€ શà«àª²à«àª• લેવામાં આવશે, પણ તેનો વાસà«àª¤àªµàª¿àª• નંબર આ સાઇટ સાથે શેર કરવામાં આવશે નહીં. વધારાની સà«àªµàª¿àª§àª¾ માટે, કામ ચલાઉ CVC જનરેટ કરવામાં આવશે.}one{તમે ચà«àª•àªµàª£à«€ કરશો તà«àª¯àª¾àª°à«‡ તમે પસંદ કરશો તે કારà«àª¡àª¥à«€ શà«àª²à«àª• લેવામાં આવશે, પણ તેનો વાસà«àª¤àªµàª¿àª• નંબર આ સાઇટ સાથે શેર કરવામાં આવશે નહીં. વધારાની સà«àªµàª¿àª§àª¾ માટે, કામ ચલાઉ CVC જનરેટ કરવામાં આવશે.}other{તમે ચà«àª•àªµàª£à«€ કરશો તà«àª¯àª¾àª°à«‡ તમે પસંદ કરશો તે કારà«àª¡àª¥à«€ શà«àª²à«àª• લેવામાં આવશે, પણ તેનો વાસà«àª¤àªµàª¿àª• નંબર આ સાઇટ સાથે શેર કરવામાં આવશે નહીં. વધારાની સà«àªµàª¿àª§àª¾ માટે, કામ ચલાઉ CVC જનરેટ કરવામાં આવશે.}}</translation>
<translation id="5826507051599432481">કોમન નેમ (CN)</translation>
<translation id="5838278095973806738">તમારે આ સાઇટ પર કોઈપણ સંવેદનશીલ માહિતી (ઉદાહરણ તરીકે, પાસવરà«àª¡à«àª¸ અથવા કà«àª°à«‡àª¡àª¿àªŸ કારà«àª¡à«àª¸) દાખલ કરવી જોઈઠનહીં, કારણ કે તે હà«àª®àª²àª¾àª–ોર દà«àªµàª¾àª°àª¾ ચોરવામાં આવી શકે છે.</translation>
@@ -1302,6 +1336,7 @@
<translation id="5855253129151731373">આ સાઇટના હોસà«àªŸàª¨à«àª‚ નામ <ph name="LOOKALIKE_DOMAIN" /> જેવà«àª‚ જ લાગી રહà«àª¯à«àª‚ છે. હà«àª®àª²àª¾àª–ોરો ઘણી વાર ડોમેન નામમાં સરળતાથી જોઈ ન શકાય àªàªµàª¾ મામૂલી ફેરફારો કરીને સાઇટની નકલ કરતા હોય છે.
જો તમે àªàª® માનતા હો કે આ ભૂલમાં બતાવવામાં આવà«àª¯à«àª‚ છે, તો કૃપા કરીને https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appealsની મà«àª²àª¾àª•àª¾àª¤ લો.</translation>
+<translation id="5860033963881614850">બંધ</translation>
<translation id="5862579898803147654">સà«àªŸà«…કર 8</translation>
<translation id="5863847714970149516">આગળનà«àª‚ પેજ તમને શà«àª²à«àª• લાગૠકરી શકે છે</translation>
<translation id="5866257070973731571">ફોન નંબર ઉમેરો</translation>
@@ -1318,6 +1353,7 @@
<translation id="5913377024445952699">સà«àª•à«àª°à«€àª¨ કૅપà«àªšàª°àª¨à«€ સà«àªµàª¿àª§àª¾ થોભાવવામાં આવી છે</translation>
<translation id="59174027418879706">સકà«àª·àª® કરેલà«àª‚</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 ઉપયોગમાં છે}one{# ઉપયોગમાં છે}other{# ઉપયોગમાં છે}}</translation>
<translation id="5921185718311485855">ચાલà«</translation>
<translation id="5921639886840618607">Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ કારà«àª¡ સાચવીàª?</translation>
<translation id="5922853866070715753">લગભગ થઈ ગયà«àª‚</translation>
@@ -1337,6 +1373,7 @@
<translation id="5989320800837274978">ફિકà«àª¸à«àª¡ પà«àª°à«‰àª•à«àª¸à«€ સરà«àªµàª° કે .pac સà«àª•à«àª°àª¿àªªà«àªŸ URL, બેમાંથી કોઈનો પણ ઉલà«àª²à«‡àª– કરેલો નથી.</translation>
<translation id="5992691462791905444">àªàª¨à«àªœàª¿àª¨àª¿àª¯àª°àª¿àª‚ગ Z-ફોલà«àª¡</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' માટે <ph name="RESULT_COUNT" /> પરિણામ</translation>
+<translation id="6006484371116297560">કà«àª²àª¾àª¸àª¿àª•</translation>
<translation id="6008122969617370890">N-થી-1 સà«àª§à«€àª¨à«‹ કà«àª°àª®</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">તમારા પાસવરà«àª¡ તપાસો</translation>
@@ -1358,6 +1395,7 @@
<translation id="6045164183059402045">લાગૠકરવા માટેનો નમૂનો</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="6049004884579590341">પૂરà«àª£ સà«àª•à«àª°à«€àª¨àª¥à«€ બહાર નીકળવા માટે |<ph name="ACCELERATOR" />|ને દબાવી રાખો</translation>
<translation id="6049488691372270142">પેજની ડિલિવરી</translation>
<translation id="6051221802930200923">તમે અતà«àª¯àª¾àª°à«‡ આ <ph name="SITE" />ની મà«àª²àª¾àª•àª¾àª¤ લઈ શકતાં નથી કારણ કે આ વેબસાઇટ પà«àª°àª®àª¾àª£àªªàª¤à«àª° પિનિંગનો ઉપયોગ કરે છે. નેટવરà«àª•àª®àª¾àª‚ ભૂલ આવવી અને હà«àª®àª²àª¾ થવા સામાનà«àª¯ રીતે અસà«àª¥àª¾àª¯à«€ હોય છે, તેથી આ પેજ સંભવિત રૂપે થોડા સમય પછી કારà«àª¯ કરશે.</translation>
<translation id="6051898664905071243">પેજની સંખà«àª¯àª¾:</translation>
@@ -1374,6 +1412,7 @@
<translation id="610911394827799129">તમારા Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> પર બà«àª°àª¾àª‰àªàª¿àª‚ગ ઇતિહાસના બીજા સà«àªµàª°à«‚પો હોય શકે છે</translation>
<translation id="6116338172782435947">કà«àª²àª¿àªªàª¬à«‹àª°à«àª¡ પર કૉપિ કરેલ ટેકà«àª¸à«àªŸ અને છબીઓને જà«àª“</translation>
<translation id="6120179357481664955">તમારà«àª‚ UPI ID યાદ રાખીàª?</translation>
+<translation id="6123290840358279103">વરà«àªšà«àª¯à«àª…લ કારà«àª¡ જà«àª“</translation>
<translation id="6124432979022149706">Chrome àªàª¨à«àªŸàª°àªªà«àª°àª¾àª‡àª કનેકà«àªŸàª°</translation>
<translation id="6146055958333702838">કોઈપણ કેબલà«àª¸ તપાસો અને તમે કદાચ ઉપયોગમાં લઇ રહà«àª¯àª¾àª‚ હોય તેવા કોઇપણ રાઉટરà«àª¸, મૉડેમà«àª¸Â 
અથવા અનà«àª¯ નેટવરà«àª• ઉપકરણોને રીબૂટ કરો.</translation>
@@ -1410,10 +1449,11 @@
<translation id="6289939620939689042">પેજનો રંગ</translation>
<translation id="6290238015253830360">તમારા સૂચવેલા લેખ અહીં દેખાય છે</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chromeમાં Google આસિસà«àªŸàª‚ટ રોકાઈ રહà«àª¯à«àª‚ છે</translation>
<translation id="6305205051461490394"><ph name="URL" />, પહોંચવા યોગà«àª¯ નથી.</translation>
<translation id="6312113039770857350">વેબપેજ ઉપલબà«àª§ નથી</translation>
-<translation id="6321917430147971392">તમારી DNS સેટિંગà«àª¸ તપાસો</translation>
+<translation id="6321917430147971392">તમારા DNS સેટિંગ તપાસો</translation>
<translation id="6322182122604171028">Windows Helloનો ઉપયોગ કરી શકà«àª¯àª¾àª‚ નથી</translation>
<translation id="6328639280570009161">નેટવરà«àª• પૂરà«àªµàª¾àª¨à«àª®àª¾àª¨àª¨à«‡ અકà«àª·àª® કરવાનો પà«àª°àª¯àª¾àª¸ કરો</translation>
<translation id="6328784461820205019">"તમારà«àª‚ કનેકà«àª¶àª¨ ખાનગી નથી" અથવા "&lt;span class="error-code"&gt;NET::ERR_CERT_AUTHORITY_INVALID&lt;/span&gt;" અથવા "&lt;span class="error-code"&gt;ERR_CERT_COMMON_NAME_INVALID&lt;/span&gt;" અથવા "&lt;span class="error-code"&gt;NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM&lt;/span&gt;" અથવા "&lt;span class="error-code"&gt;ERR_CERT_SYMANTEC_LEGACY&lt;/span&gt;" અથવા "SSL પà«àª°àª®àª¾àª£àªªàª¤à«àª° ભૂલ"</translation>
@@ -1435,6 +1475,7 @@
<translation id="6390200185239044127">અડધà«àª‚ Z-ફોલà«àª¡</translation>
<translation id="6390662030813198813">àªàª¨à«àªœàª¿àª¨àª¿àª¯àª°àª¿àª‚ગ-E</translation>
<translation id="6393956493820063117">વà«àª¯àªµàª¸à«àª¥àª¾àªªàª•àª¨à«€ નીતિને કારણે <ph name="ORIGIN_NAME" />થી આ સà«àª¥àª¾àª¨àª®àª¾àª‚ પેસà«àªŸ કરવાની સà«àªµàª¿àª§àª¾ બà«àª²à«‰àª• કરવામાં આવી છે</translation>
+<translation id="6398765197997659313">પૂરà«àª£ સà«àª•à«àª°à«€àª¨àª¥à«€ બહાર નીકળો</translation>
<translation id="6401136357288658127">આ પૉલિસી ટાળવામાં આવી છે. તેના બદલે તમારે <ph name="NEW_POLICY" /> પૉલિસીનો ઉપયોગ કરવો જોઈàª.</translation>
<translation id="6404511346730675251">બà«àª•àª®àª¾àª°à«àª•àª®àª¾àª‚ ફેરફાર કરો</translation>
<translation id="6406765186087300643">C0 (àªàª¨à«àªµàª²àªª)</translation>
@@ -1447,7 +1488,6 @@
<translation id="6428450836711225518">તમારો ફોન નંબર ચકાસો</translation>
<translation id="6433490469411711332">સંપરà«àª• માહિતીમાં ફેરફાર કરો</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ઠકનેકà«àªŸ કરવાનો ઇનકાર કરà«àª¯à«‹.</translation>
-<translation id="6434309073475700221">કાઢી નાખો</translation>
<translation id="6440503408713884761">અવગણી</translation>
<translation id="6443406338865242315">તમે કયા àªàª•à«àª¸à«àªŸà«‡àª‚શન અને પà«àª²àª—-ઇન ઇનà«àª¸à«àªŸà«‰àª² કરà«àª¯àª¾ છે</translation>
<translation id="6446163441502663861">Kahu (àªàª¨à«àªµàª²àªª)</translation>
@@ -1458,7 +1498,7 @@
<translation id="6457206614190510200">સૅડલ સà«àªŸàª¿àªš</translation>
<translation id="6458606150257356946">તેમ છતાં પેસà«àªŸ કરો</translation>
<translation id="6465306955648956876">બધા પાસવરà«àª¡ મેનેજ કરો…</translation>
-<translation id="6468485451923838994">ફોનà«àªŸà«àª¸</translation>
+<translation id="6468485451923838994">ફૉનà«àªŸ</translation>
<translation id="647261751007945333">ડિવાઇસ પૉલિસીઓ</translation>
<translation id="6476284679642588870">ચà«àª•àªµàª£à«€ પદà«àª§àª¤àª¿àª“ મેનેજ કરો</translation>
<translation id="6489534406876378309">કà«àª°à«‡àª¶ અપલોડ કરવાનà«àª‚ શરૂ કરો</translation>
@@ -1490,6 +1530,7 @@
<translation id="6624427990725312378">સંપરà«àª• માહિતી</translation>
<translation id="6626291197371920147">માનà«àª¯ કારà«àª¡ નંબર ઉમેરો</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> શોધ</translation>
+<translation id="6630043285902923878">USB ડિવાઇસ શોધી રહà«àª¯àª¾àª‚ છીàª...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">સાફ કરો</translation>
@@ -1505,6 +1546,7 @@
<translation id="6671697161687535275">Chromium માંથી ફોરà«àª® સૂચન દૂર કરીàª?</translation>
<translation id="6685834062052613830">સાઇન આઉટ કરો અને સેટઅપ પૂરà«àª£ કરો</translation>
<translation id="6687335167692595844">ફોનà«àªŸàª¨àª¾ કદ માટે વિનંતી કરી</translation>
+<translation id="6688743156324860098">અપડેટ કરો…</translation>
<translation id="6689249931105087298">કાળા પૉઇનà«àªŸàª¨à«‡ નાનો કરવા સંબંધિત</translation>
<translation id="6689271823431384964">તમે સાઇન ઇન કરેલà«àª‚ છે તેથી Chrome તમને તમારા કારà«àª¡ તમારા Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ સાચવવાની ઑફર કરે છે. તમે સેટિંગમાં આ વરà«àª¤àª£à«‚કને બદલી શકો છો. કારà«àª¡àª§àª¾àª°àª•àª¨à«àª‚ નામ તમારા àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚થી આવે છે.</translation>
<translation id="6698381487523150993">બનાવેલા:</translation>
@@ -1520,6 +1562,7 @@
<translation id="6744009308914054259">કનેકà«àª¶àª¨ માટે રાહ જોતી વખતે, ઑફલાઇન લેખ વાંચવા માટે તમે ડાઉનલોડની મà«àª²àª¾àª•àª¾àª¤ લઈ શકો.</translation>
<translation id="6753269504797312559">પૉલિસી મૂલà«àª¯</translation>
<translation id="6757797048963528358">તમારà«àª‚ ઉપકરણ નિષà«àª•à«àª°àª¿àª¯ થઈ ગયà«àª‚ હતà«àª‚.</translation>
+<translation id="6767985426384634228">સરનામà«àª‚ અપડેટ કરીàª?</translation>
<translation id="6768213884286397650">Hagaki (પોસà«àªŸàª•àª¾àª°à«àª¡)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">જાંબà«àª¡àª¿àª¯à«‹</translation>
@@ -1542,6 +1585,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome દà«àªµàª¾àª°àª¾ આ પેજને સરળ બનાવવામાં આવà«àª¯à«àª‚ છે જેથી તેને વધૠસરળતાથી વાંચી શકાય. Chrome દà«àªµàª¾àª°àª¾ અસà«àª°àª•à«àª·àª¿àª¤ કનેકà«àª¶àª¨ વડે ઑરિજિનલ પેજ પાછà«àª‚ મેળવવામાં આવà«àª¯à«àª‚.</translation>
<translation id="6891596781022320156">પૉલિસી લેવલ સમરà«àª¥àª¿àª¤ નથી.</translation>
+<translation id="6895143722905299846">વરà«àªšà«àª¯à«àª…લ નંબર:</translation>
<translation id="6895330447102777224">તમારા કારà«àª¡àª¨à«€ પà«àª·à«àªŸàª¿ કરવામાં આવી છે</translation>
<translation id="6897140037006041989">વપરાશકરà«àª¤àª¾ àªàªœàª¨à«àªŸ</translation>
<translation id="6898699227549475383">ઑરà«àª—ેનાઇàªà«‡àª¶àª¨ (O)</translation>
@@ -1571,16 +1615,16 @@
<translation id="6979158407327259162">Google Drive</translation>
<translation id="6979440798594660689">મà«àª¯à«‚ટ કરો (ડિફૉલà«àªŸ)</translation>
<translation id="6979983982287291980">તમે જે ફાઇલો ડાઉનલોડ કરો તેને Google Cloud અથવા તà«àª°à«€àªœàª¾ પકà«àª·à«‹àª¨à«‡ વિશà«àª²à«‡àª·àª£ માટે મોકલવામાં આવે છે. ઉદાહરણ તરીકે, તેને સંવેદનશીલ વà«àª¯àª•à«àª¤àª¿àª—ત ડેટા અથવા માલવેર માટે સà«àª•à«…ન કરવામાં આવી શકે છે.</translation>
-<translation id="6989763994942163495">વિગતવાર સેટિંગà«àª¸ બતાવો...</translation>
+<translation id="6989763994942163495">વિગતવાર સેટિંગ બતાવો...</translation>
<translation id="6993898126790112050">6x9 (àªàª¨à«àªµàª²àªª)</translation>
<translation id="6996312675313362352">હંમેશાં <ph name="ORIGINAL_LANGUAGE" />નો અનà«àªµàª¾àª¦ કરો</translation>
<translation id="7004583254764674281">કારà«àª¡àª¨à«‡ વધૠàªàª¡àªªàª¥à«€ કનà«àª«àª°à«àª® કરવા માટે Windows Helloનો ઉપયોગ કરો</translation>
<translation id="7006930604109697472">કોઈપણ રીતે મોકલો</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">કદ બદલવા માટેના સેટિંગ</translation>
<translation id="7014741021609395734">àªà«‚મ લેવલ</translation>
<translation id="7016992613359344582">આ શà«àª²à«àª• àªàª•-સમયનà«àª‚ અથવા પà«àª¨àª°àª¾àªµàª°à«àª¤àª¿àª¤ હોઈ શકે છે અને કદાચ દેખીતા શà«àª²à«àª• ન પણ હોય.</translation>
<translation id="7029809446516969842">પાસવરà«àª¡</translation>
+<translation id="7030436163253143341">પà«àª°àª®àª¾àª£àªªàª¤à«àª° માનà«àª¯ નથી</translation>
<translation id="7031646650991750659">તમે કઈ Google Play àªàªª ઇનà«àª¸à«àªŸà«‰àª² કરી છે</translation>
<translation id="7050187094878475250">તમે <ph name="DOMAIN" /> પર પહોંચવાનો પà«àª°àª¯àª¾àª¸ કરેલો, પરંતૠસરà«àªµàª°à«‡ àªàªµà«àª‚ પà«àª°àª®àª¾àª£àªªàª¤à«àª° પà«àª°àª¸à«àª¤à«àª¤ કરà«àª¯à«àª‚ જેની માનà«àª¯àª¤àª¾ અવધિ, વિશà«àªµàª¸àª¨à«€àª¯ હોવા માટે ખૂબ લાંબી છે.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{આ કારà«àª¡ અતà«àª¯àª¾àª°à«‡ સાચવી શકાતà«àª‚ નથી}one{આ કારà«àª¡ અતà«àª¯àª¾àª°à«‡ સાચવી શકાતાં નથી}other{આ કારà«àª¡ અતà«àª¯àª¾àª°à«‡ સાચવી શકાતાં નથી}}</translation>
@@ -1650,12 +1694,14 @@
<translation id="7300012071106347854">ઘેરો વાદળી</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">વધૠàªàª¡àªªà«‡</translation>
+<translation id="7305756307268530424">વધૠધીમી ગતિ પર શરૂ કરો</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">કનેકà«àª¶àª¨ સહાય</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" વિભાગને છà«àªªàª¾àªµà«‹</translation>
<translation id="733354035281974745">ડિવાઇસ સà«àª¥àª¾àª¨àª¿àª• àªàª•àª¾àª‰àª¨à«àªŸ ઓવરરાઇડ</translation>
<translation id="7333654844024768166">હમણાં જ કોઈ છેતરામણી સાઇટ પર તમે તમારો પાસવરà«àª¡ દાખલ કરà«àª¯à«‹. Chromium <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> તેમજ તમે આ પાસવરà«àª¡àª¨à«‹ જà«àª¯àª¾àª‚ ઉપયોગ કરતા હોય તે અનà«àª¯ સાઇટ પર જઈને તેને હમણાં જ બદલવાનો સà«àªàª¾àªµ આપે છે.</translation>
<translation id="7334320624316649418">&amp;પà«àª¨àªƒàª•à«àª°àª®àª¾àª‚કિત કરવà«àª‚ ફરી કરો</translation>
+<translation id="7337248890521463931">વધૠપંકà«àª¤àª¿àª“ બતાવો</translation>
<translation id="7337706099755338005">તમારા પà«àª²à«…ટફૉરà«àª® પર ઉપલબà«àª§ નથી.</translation>
<translation id="733923710415886693">પà«àª°àª®àª¾àª£àªªàª¤à«àª° પારદરà«àª¶àª¿àª¤àª¾ દà«àªµàª¾àª°àª¾ સરà«àªµàª°àª¨à«àª‚ પà«àª°àª®àª¾àª£àªªàª¤à«àª° જાહેર કરવામાં આવà«àª¯à«àª‚ ન હતà«àª‚.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1663,6 +1709,7 @@
<translation id="7349430561505560861">A4-અતિરિકà«àª¤</translation>
<translation id="7353601530677266744">આદેશ પંકà«àª¤àª¿</translation>
<translation id="7359588939039777303">જાહેરાતો અવરોધિત કરી.</translation>
+<translation id="7363096869660964304">જોકે, તમે અદૃશà«àª¯ નથી. છૂપા મોડમાં જવà«àª‚ તમારા નિયોકà«àª¤àª¾, તમારા ઇનà«àªŸàª°àª¨à«‡àªŸ સેવા પà«àª°àª¦àª¾àª¤àª¾ અથવા તમે મà«àª²àª¾àª•àª¾àª¤ લો છો તે વેબસાઇટથી તમારા બà«àª°àª¾àª‰àªàª¿àª‚ગને છà«àªªàª¾àªµàª¤à«àª‚ નથી.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, ટૅબ દબાવો અને પછી Chrome સેટિંગમાં àªàª¡à«àª°à«‡àª¸ ઉમેરવા અને તેને મેનેજ કરવા માટે Enter કી દબાવો</translation>
<translation id="7365849542400970216">તમારા ડિવાઇસનો ઉપયોગ જાણો છે?</translation>
<translation id="7372973238305370288">શોધ પરિણામ</translation>
@@ -1673,7 +1720,9 @@
<translation id="7378594059915113390">મીડિયા નિયંતà«àª°àª£à«‹</translation>
<translation id="7378627244592794276">ના</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">લાગૠથતà«àª‚ નથી</translation>
<translation id="7390545607259442187">કારà«àª¡àª¨à«€ પà«àª·à«àªŸàª¿ કરો</translation>
+<translation id="7392089738299859607">સરનામà«àª‚ અપડેટ કરો</translation>
<translation id="7399802613464275309">સલામતી માટે તપાસ</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">તમારà«àª‚ <ph name="DEVICE_NAME" /> મેનેજ કરવામાં આવે છે</translation>
@@ -1688,6 +1737,7 @@
&lt;li&gt;તમારા કમà«àªªà«àª¯à«àªŸàª° પરથી સૉફà«àªŸàªµà«‡àª°àª¨à«‡ કાયમી ધોરણે કાઢી નાંખવાની રીત જાણવા માટે, &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome સહાયતા કેનà«àª¦à«àª°&lt;/a&gt; પર જાઓ
&lt;/ol&gt;</translation>
<translation id="741007362987735528">પહોળાઈ-ફૉરà«àª®à«‡àªŸ</translation>
+<translation id="7410471291937727359">મનોરમ</translation>
<translation id="7416351320495623771">પાસવરà«àª¡ મેનેજ કરો…</translation>
<translation id="7419106976560586862">પà«àª°à«‹àª«àª¾àª‡àª² પાથ</translation>
<translation id="7437289804838430631">સંપરà«àª• માહિતી ઉમેરો</translation>
@@ -1703,7 +1753,7 @@
<translation id="7481312909269577407">ફોરà«àªµàª°à«àª¡ કરો</translation>
<translation id="7485870689360869515">કોઈ ડેટા મળà«àª¯à«‹ નથી.</translation>
<translation id="7495528107193238112">આ કનà«àªŸà«‡àª¨à«àªŸ બà«àª²à«‰àª• કરવામાં આવà«àª¯à«àª‚ છે. સમસà«àª¯àª¾àª¨àª¾àª‚ નિરાકરણ માટે, સાઇટના માલિકનો સંપરà«àª• કરો.</translation>
-<translation id="7498234416455752244">ફેરફાર કરવાનà«àª‚ ચાલૠરાખો</translation>
+<translation id="7498193950643227031">જો તેનà«àª‚ કદ બદલવામાં આવે તો તે અનપેકà«àª·àª¿àª¤ રીતે કારà«àª¯ કરી શકે છે. હવે તમે <ph name="SETTINGS" />માં àªàªªàª¨à«àª‚ કદ બદલવાની કà«àª·àª®àª¤àª¾àª¨à«‡ મરà«àª¯àª¾àª¦àª¿àª¤ કરી શકો છો.</translation>
<translation id="7503664977220660814">હમણાં જ કોઈ છેતરામણી સાઇટ પર તમે તમારો પાસવરà«àª¡ દાખલ કરà«àª¯à«‹. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> અને હવે તમે આ પાસવરà«àª¡àª¨à«‹ જà«àª¯àª¾àª‚ ઉપયોગ કરતા હો તે અનà«àª¯ સાઇટ પરના તમે સાચવેલા પાસવરà«àª¡ ચેક કરવાનો Chromium સà«àªàª¾àªµ આપે છે.</translation>
<translation id="7508255263130623398">પરત થયેલà«àª‚ પૉલિસી ડિવાઇસ id ખાલી છે અથવા વરà«àª¤àª®àª¾àª¨ ટોકન સાથે મેળ ખાતà«àª‚ નથી</translation>
<translation id="7508870219247277067">જમરૂખ જેવો લીલો</translation>
@@ -1723,6 +1773,7 @@
<translation id="7548892272833184391">કનેકà«àª¶àª¨ ભૂલો સà«àª§àª¾àª°à«‹</translation>
<translation id="7549584377607005141">આ વેબપેજને તે ડેટાની જરૂર છે જે તમે પહેલાં બરાબર રીતે પà«àª°àª¦àª°à«àª¶àª¿àª¤ થાય તે માટે દાખલ કરà«àª¯à«‹ હતો. તમે આ ડેટા ફરીથી મોકલી શકો છો, પણ આમ કરીને તમે કોઈપણ કà«àª°àª¿àª¯àª¾ કે જે પેજ પહેલાં જ કરી ચૂકà«àª¯à«àª‚ છે તેનà«àª‚ પà«àª¨àª°àª¾àªµàª°à«àª¤àª¨ કરશો.</translation>
<translation id="7550637293666041147">તમારà«àª‚ ડિવાઇસ વપરાશકરà«àª¤àª¾ નામ અને Chrome વપરાશકરà«àª¤àª¾ નામ</translation>
+<translation id="755279583747225797">અજમાયશ સકà«àª°àª¿àª¯ છે</translation>
<translation id="7552846755917812628">નીચેની ટિપને અજમાવો:</translation>
<translation id="7554475479213504905">કોઈપણ રીતે ફરીથી લોડ કરો અને બતાવો</translation>
<translation id="7554791636758816595">નવà«àª‚ ટૅબ</translation>
@@ -1741,7 +1792,6 @@
<translation id="7610193165460212391">મૂલà«àª¯ <ph name="VALUE" /> શà«àª°à«‡àª£à«€ બહારનà«àª‚ છે.</translation>
<translation id="7613889955535752492">સમાપà«àª¤àª¿: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome સેટિંગમાં તમારા પાસવરà«àª¡ જોવા અને તેમને મેનેજ કરવા માટે Tab પછી Enter દબાવો</translation>
-<translation id="7615602087246926389">તમારી પાસે પેહલાથી જ ડેટા છે જે તમારા Google àªàª•àª¾àª‰àª¨à«àªŸ પાસવરà«àª¡àª¨àª¾ વિવિધ વરà«àªàª¨àª¨à«‹ ઉપયોગ કરીને àªàª¨à«àª•à«àª°àª¿àªªà«àªŸ કરેલો છે.</translation>
<translation id="7616645509853975347">તમારા વà«àª¯àªµàª¸à«àª¥àª¾àªªàª•à«‡ તમારા બà«àª°àª¾àª‰àªàª° પર Chrome Enterprise Connectors ચાલૠકરà«àª¯à« છે. આ કનેકà«àªŸàª°àª¨à«‡ તમારા અમà«àª• ડેટાનો àªàª•à«àª¸à«‡àª¸ છે.</translation>
<translation id="7619838219691048931">છેલà«àª²à«€ શીટ</translation>
<translation id="762844065391966283">àªàª• સમયે માતà«àª° àªàª•</translation>
@@ -1754,7 +1804,7 @@
<translation id="7648992873808071793">આ ઉપકરણ પર ફાઇલો સાચવો</translation>
<translation id="7653957176542370971">ચà«àª•àªµàª£à«€ માટેની હૅનà«àª¡àª²àª° શીટ બંધ છે</translation>
<translation id="7654909834015434372">જà«àª¯àª¾àª°à«‡ તમે ટીકાટિપà«àªªàª£à«€àª®àª¾àª‚ ફેરફાર કરશો, તà«àª¯àª¾àª°à«‡ આ દસà«àª¤àª¾àªµà«‡àªœ તેના ઑરિજિનલ રોટેશન પર પાછો ફરશે</translation>
-<translation id="765676359832457558">વિગતવાર સેટિંગà«àª¸ છà«àªªàª¾àªµà«‹...</translation>
+<translation id="765676359832457558">વિગતવાર સેટિંગ છà«àªªàª¾àªµà«‹...</translation>
<translation id="7658239707568436148">રદ કરો</translation>
<translation id="7662298039739062396">àªàª•à«àª¸àªŸà«‡àª¨à«àª¶àª¨ દà«àªµàª¾àª°àª¾ સેટિંગ નિયંતà«àª°àª¿àª¤ કરેલ છે</translation>
<translation id="7663736086183791259">પà«àª°àª®àª¾àª£àªªàª¤à«àª° <ph name="CERTIFICATE_VALIDITY" /></translation>
@@ -1806,13 +1856,12 @@
<translation id="782886543891417279">તમે વાપરી રહેલા વાઇ-ફાઇ (<ph name="WIFI_NAME" />)ના લોગિન પેજ પર જવà«àª‚ પડી શકે.</translation>
<translation id="7836231406687464395">Postfix (àªàª¨à«àªµàª²àªª)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{કોઈ નહીં}=1{1 àªàªª (<ph name="EXAMPLE_APP_1" />)}=2{2 àªàªª (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# àªàªª (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# àªàªª (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">જોકે, તમે અદૃશà«àª¯ નથી. છà«àªªàª¾àª®àª¾àª‚ જવà«àª‚ તમારા નિયોકà«àª¤àª¾, તમારા ઇનà«àªŸàª°àª¨à«‡àªŸ સેવા પà«àª°àª¦àª¾àª¤àª¾ અથવા તમે મà«àª²àª¾àª•àª¾àª¤ લો છો તે વેબસાઇટથી તમારા બà«àª°àª¾àª‰àªàª¿àª‚ગને છà«àªªàª¾àªµàª¤à«àª‚ નથી.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ફાઇલ પà«àª°àª•àª¾àª° સાથે સà«àª¸àª‚ગત સૉફà«àªŸàªµà«‡àª° વડે ફાઇલો ખોલો.</translation>
<translation id="7862185352068345852">સાઇટ છોડવી છે?</translation>
<translation id="7865448901209910068">શà«àª°à«‡àª·à«àª  àªàª¡àªª</translation>
<translation id="7874263914261512992">હમણાં જ કોઈ છેતરામણી સાઇટ પર તમે તમારો પાસવરà«àª¡ દાખલ કરà«àª¯à«‹. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> અને હવે તમે આ પાસવરà«àª¡àª¨à«‹ જà«àª¯àª¾àª‚ ઉપયોગ કરતા હો તે અનà«àª¯ સાઇટ પરના તમે સાચવેલા પાસવરà«àª¡ ચેક કરવાનો Chrome સà«àªàª¾àªµ આપે છે.</translation>
<translation id="7878562273885520351">તમારા પાસવરà«àª¡ સાથે ચેડાં થઈ શકે છે</translation>
+<translation id="7880146494886811634">સરનામà«àª‚ સાચવો</translation>
<translation id="7882421473871500483">ભૂરો</translation>
<translation id="7887683347370398519">તમારà«àª‚ CVC તપાસો અને ફરીથી પà«àª°àª¯àª¾àª¸ કરો</translation>
<translation id="7887885240995164102">ચિતà«àª°-માં-ચિતà«àª° મોડમાં દાખલ થાઓ</translation>
@@ -1820,6 +1869,7 @@
<translation id="7894280532028510793">જો જોડણી સાચી હોય, તો <ph name="BEGIN_LINK" />નેટવરà«àª• નિદાન ચલાવવાનો પà«àª°àª¯àª¾àª¸ કરી જà«àª“<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (àªàª¨à«àªµàª²àªª)</translation>
<translation id="7931318309563332511">અજાણ</translation>
+<translation id="793209273132572360">સરનામà«àª‚ અપડેટ કરીàª?</translation>
<translation id="7932579305932748336">કોટ કરો</translation>
<translation id="79338296614623784">àªàª• માનà«àª¯ ફોન નંબર દાખલ કરો</translation>
<translation id="7934052535022478634">ચૂકવણી પૂરà«àª£</translation>
@@ -1890,6 +1940,7 @@
<translation id="8175796834047840627">તમે સાઇન ઇન કરેલà«àª‚ છે તેથી Chrome તમને તમારા કારà«àª¡ તમારા Google àªàª•àª¾àª‰àª¨à«àªŸàª®àª¾àª‚ સાચવવાની ઑફર કરે છે. તમે સેટિંગમાં આ વરà«àª¤àª£à«‚કને બદલી શકો છો.</translation>
<translation id="8176440868214972690">આ ડિવાઇસના વà«àª¯àªµàª¸à«àª¥àª¾àªªàª•à«‡ સેટિંગ અથવા પૉલિસી જેવી અમà«àª• માહિતી નીચેની વેબસાઇટને મોકલી છે.</translation>
<translation id="8184538546369750125">વૈશà«àªµàª¿àª• ડિફોલà«àªŸàª¨à«‹ ઉપયોગ કરો (મંજૂરી આપો)</translation>
+<translation id="8193086767630290324">ડેટાને ગોપનીય તરીકે ચિહà«àª¨àª¿àª¤ કરવાની કà«àª°àª¿àª¯àª¾àª“ કરી</translation>
<translation id="8194797478851900357">&amp;ખસેડવà«àª‚ પૂરà«àªµàªµàª¤à«â€Œ કરો</translation>
<translation id="8201077131113104583">ID "<ph name="EXTENSION_ID" />" સાથેના àªàª•à«àª¸àªŸà«‡àª¨à«àª¶àª¨ માટે અમાનà«àª¯ અપડેટ URL.</translation>
<translation id="8202097416529803614">ઓરà«àª¡àª°àª¨à«‹ સારાંશ</translation>
@@ -1912,6 +1963,7 @@
<translation id="8249296373107784235">છોડો</translation>
<translation id="8249320324621329438">છેલà«àª²à«àª‚ આનયન:</translation>
<translation id="8253091569723639551">બિલિંગ સરનામà«àª‚ આવશà«àª¯àª•</translation>
+<translation id="8257387598443225809">આ àªàªª મોબાઇલ માટે ડિàªàª¾àª‡àª¨ કરવામાં આવી છે</translation>
<translation id="825929999321470778">બધા સાચવેલા પાસવરà«àª¡ બતાવો</translation>
<translation id="8261506727792406068">ડિલીટ કરો</translation>
<translation id="8262952874573525464">નીચે કિનારી જોડવી</translation>
@@ -1942,7 +1994,7 @@
<translation id="8339163506404995330"><ph name="LANGUAGE" />માં છે તે પેજનો અનà«àªµàª¾àª¦ થશે નહીં</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>
+<translation id="8349305172487531364">બà«àª•àª®àª¾àª°à«àª• બાર</translation>
<translation id="8355270400102541638">સà«àª¥àª¾àª¨àª¿àª• કà«àª°à«…શ સંદરà«àª­:</translation>
<translation id="8363502534493474904">àªàª°àªªà«àª²à«‡àª¨ મોડ બંધ કરીને</translation>
<translation id="8364627913115013041">સેટ નથી.</translation>
@@ -2035,7 +2087,6 @@
<translation id="8719528812645237045">ઉપરની બાજà«àª àªàª•àª¥à«€ વધૠકાણાં પાડો</translation>
<translation id="8725066075913043281">ફરી પà«àª°àª¯àª¾àª¸ કરો</translation>
<translation id="8726549941689275341">પેજનà«àª‚ કદ:</translation>
-<translation id="8728672262656704056">તમે છà«àªªàª¾ મોડમાં ગયા છો</translation>
<translation id="8730621377337864115">થઈ ગયà«àª‚</translation>
<translation id="8731544501227493793">પાસવરà«àª¡ મેનેજ કરો બટન, Chrome સેટિંગમાં તમારા પાસવરà«àª¡ જોવા અને તેમને મેનેજ કરવા માટે Enter દબાવો</translation>
<translation id="8734529307927223492"><ph name="MANAGER" /> દà«àªµàª¾àª°àª¾ તમારા <ph name="DEVICE_TYPE" />ને મેનેજ કરવામાં આવે છે</translation>
@@ -2060,7 +2111,7 @@
<translation id="8807160976559152894">પà«àª°àª¤à«àª¯à«‡àª• પેજ પછી ટà«àª°àª¿àª® કરો</translation>
<translation id="8816395686387277279"><ph name="UPDATE_CHROME_FOCUSED_FRIENDLY_MATCH_TEXT" />, તમારા Chrome સેટિંગમાંથી Chrome અપડેટ કરવા માટે Tab પછી Enter દબાવો</translation>
<translation id="8820817407110198400">બà«àª•àª®àª¾àª°à«àª•</translation>
-<translation id="883848425547221593">અનà«àª¯ બà«àª•àª®àª¾àª°à«àª•à«àª¸</translation>
+<translation id="883848425547221593">અનà«àª¯ બà«àª•àª®àª¾àª°à«àª•</translation>
<translation id="884264119367021077">શિપિંગ સરનામà«àª‚</translation>
<translation id="884923133447025588">રદ કરવાની કોઈ મેકેનિàªàª® મળી નથી.</translation>
<translation id="885730110891505394">Google સાથે શેર કરવà«àª‚</translation>
@@ -2112,6 +2163,7 @@
<translation id="9020542370529661692">આ પૃષà«àª àª¨à«‹ <ph name="TARGET_LANGUAGE" /> માં અનà«àªµàª¾àª¦ કરવામાં આવà«àª¯à«‹ છે</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(અમાનà«àª¯)</translation>
+<translation id="9030265603405983977">મોનોકà«àª°à«‹àª®</translation>
<translation id="9035022520814077154">સà«àª°àª•à«àª·àª¾ ભૂલ</translation>
<translation id="9038649477754266430">પૃષà«àª à«‹àª¨à«‡ વધૠàªàª¡àªªàª¥à«€ લોડ કરવા માટે પૂરà«àªµàª¾àª¨à«àª®àª¾àª¨ સેવાનો ઉપયોગ કરો</translation>
<translation id="9039213469156557790">વળી, આ પૃષà«àª àª®àª¾àª‚ અનà«àª¯ àªàªµàª¾ સાધનો છે જે સà«àª°àª•à«àª·àª¿àª¤ નથી. ટà«àª°àª¾àª‚àªàª¿àªŸàª®àª¾àª‚ હોવા પર અનà«àª¯ લોકો દà«àªµàª¾àª°àª¾ આ સાધનો જોઈ શકાય છે અને પૃષà«àª àª¨à«‹ વà«àª¯àªµàª¹àª¾àª° બદલવા માટે હà«àª®àª²àª¾àª–ોર દà«àªµàª¾àª°àª¾ સંશોધિત કરવામાં આવી શકે છે.</translation>
@@ -2135,6 +2187,7 @@
<translation id="91108059142052966">ગોપનીય કનà«àªŸà«‡àª¨à«àªŸ દેખાય તà«àª¯àª¾àª°à«‡ વà«àª¯àªµàª¸à«àª¥àª¾àªªàª• પૉલિસી <ph name="APPLICATION_TITLE" /> સાથે સà«àª•à«àª°à«€àª¨ શેરિંગની સà«àªµàª¿àª§àª¾ બંધ કરે છે</translation>
<translation id="9114524666733003316">કારà«àª¡ કનà«àª«àª°à«àª® કરી રહà«àª¯àª¾àª‚ છીàª...</translation>
<translation id="9114581008513152754">આ બà«àª°àª¾àª‰àªàª° કંપની દà«àªµàª¾àª°àª¾ અથવા અનà«àª¯ સંસà«àª¥àª¾ દà«àªµàª¾àª°àª¾ મેનેજ કરવામાં આવતà«àª‚ નથી. આ ડિવાઇસ પરની પà«àª°àªµà«ƒàª¤à«àª¤àª¿ Chromeની બહાર મેનેજ કરી શકાય છે. <ph name="BEGIN_LINK" />વધૠજાણો<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">નવીન</translation>
<translation id="9119042192571987207">અપલોડ કરà«àª¯à«‹</translation>
<translation id="9128016270925453879">પૉલિસી લોડ કરવામાં આવી છે</translation>
<translation id="9128870381267983090">નેટવરà«àª•àª¥à«€ કનેકà«àªŸ કરો</translation>
@@ -2153,6 +2206,7 @@
<translation id="9170848237812810038">&amp;પૂરà«àªµàªµàª¤à« કરો</translation>
<translation id="9171296965991013597">àªàªª છોડીàª?</translation>
<translation id="9173282814238175921">માતà«àª° àªàª• દસà«àª¤àª¾àªµà«‡àªœ/નવી શીટ</translation>
+<translation id="9173995187295789444">બà«àª²à«‚ટૂથ ડિવાઇસ માટે સà«àª•à«…ન કરી રહà«àª¯àª¾ છીàª...</translation>
<translation id="917450738466192189">સરà«àªµàª°àª¨à«àª‚ પà«àª°àª®àª¾àª£àªªàª¤à«àª° અમાનà«àª¯ છે.</translation>
<translation id="9174917557437862841">ટૅબ, સà«àªµàª¿àªš બટન, આ ટૅબ પર સà«àªµàª¿àªš કરવા માટે Enter દબાવો</translation>
<translation id="9179703756951298733">Chrome સેટિંગમાં તમારી ચà«àª•àªµàª£à«€àª“ અને કà«àª°à«‡àª¡àª¿àªŸ કારà«àª¡àª¨à«€ માહિતી મેનેજ કરો</translation>
diff --git a/chromium/components/strings/components_strings_hi.xtb b/chromium/components/strings/components_strings_hi.xtb
index 9c36a4cd1e7..01186a9bdba 100644
--- a/chromium/components/strings/components_strings_hi.xtb
+++ b/chromium/components/strings/components_strings_hi.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">चेक किठहोने पर, ज़à¥à¤¯à¤¾à¤¦à¤¾ तेज़ फ़ॉरà¥à¤® भरने के लिठChrome इस डिवाइस पर आपके कारà¥à¤¡ की कॉपी संगà¥à¤°à¤¹à¤¿à¤¤ कर लेगा.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> के लिठअनà¥à¤®à¤¤à¤¿ चà¥à¤¨à¥‡à¤‚</translation>
<translation id="1113869188872983271">&amp;पà¥à¤¨: कà¥à¤°à¤®à¤¿à¤¤ करना वापस लाà¤à¤‚</translation>
+<translation id="1123753900084781868">अभी लाइव कैपà¥à¤¶à¤¨ की सà¥à¤µà¤¿à¤§à¤¾ उपलबà¥à¤§ नहीं है</translation>
<translation id="1125573121925420732">जब वेबसाइटें अपनी सà¥à¤°à¤•à¥à¤·à¤¾ अपडेट कर रही होती हैं, तब चेतावनियां आम हो सकती हैं. इसमें जलà¥à¤¦ ही सà¥à¤§à¤¾à¤° होगा.</translation>
<translation id="112840717907525620">नीति कैश मेमोरी ठीक है</translation>
<translation id="1130564665089811311">'पेज का अनà¥à¤µà¤¾à¤¦ करें' बटन, Google Translate की मदद से इस पेज का अनà¥à¤µà¤¾à¤¦ करने के लिठEnter दबाà¤à¤‚</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">आपके डिवाइस का नाम</translation>
<translation id="124116460088058876">ज़à¥à¤¯à¤¾à¤¦à¤¾ भाषाà¤à¤‚</translation>
<translation id="1243027604378859286">लेखक:</translation>
+<translation id="1246424317317450637">बोलà¥à¤¡ टेकà¥à¤¸à¥à¤Ÿ</translation>
<translation id="1250759482327835220">अगली बार तेज़ी से भà¥à¤—तान करने के लिà¤, अपने कारà¥à¤¡, नाम और बिलिंग पते को अपने 'Google खाते' में सेव करें.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (सिंक किठगà¤)</translation>
<translation id="1256368399071562588">&lt;p&gt;अगर आप किसी वेबसाइट पर जाने की कोशिश करते हैं और वह नहीं खà¥à¤²à¤¤à¥€ है तो, कृपया गड़बड़ी ठीक करने संबंधी इन कदमों के ज़रिठसमसà¥à¤¯à¤¾ का हल करने की कोशिश करें:&lt;/p&gt;
@@ -83,7 +85,7 @@
&lt;li&gt;वेबसाइट के मालिक से संपरà¥à¤• करें.&lt;/li&gt;
&lt;/ol&gt;</translation>
<translation id="1257286744552378071">आपने अपना पासवरà¥à¤¡ à¤à¤¸à¥€ साइट पर डाला है जिसे आपका संगठन पà¥à¤°à¤¬à¤‚धित नहीं करता है. अपना खाता सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ करने के लिà¤, दूसरे à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ और साइटों पर अपना पासवरà¥à¤¡ दोबारा इसà¥à¤¤à¥‡à¤®à¤¾à¤² न करें.</translation>
-<translation id="1263231323834454256">पठन सूची</translation>
+<translation id="1263231323834454256">रीडिंग लिसà¥à¤Ÿ</translation>
<translation id="1267173982554786072"><ph name="BEGIN_BOLD" />
ये गतिविधियां इस डिवाइस पर सेव नहीं की जाà¤à¤‚गी:
<ph name="END_BOLD" />
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">अपना पासवरà¥à¤¡ बदलें</translation>
<translation id="1484290072879560759">शिपिंग पता चà¥à¤¨à¥‡à¤‚</translation>
<translation id="1492194039220927094">नीतियां भेजें:</translation>
+<translation id="1495677929897281669">टैब पर वापस जाà¤à¤‚</translation>
<translation id="1501859676467574491">अपने Google खाते में मौजूद कारà¥à¤¡ दिखाà¤à¤‚</translation>
<translation id="1507202001669085618">&lt;p&gt;अगर आप à¤à¤¸à¥‡ वाई-फ़ाई पोरà¥à¤Ÿà¤² का इसà¥à¤¤à¥‡à¤®à¤¾à¤² कर रहे हैं, जिसमें ऑनलाइन होने से पहले साइन इन ज़रूरी है, तो आपको यह गड़बड़ी दिखाई देगी.&lt;/p&gt;
&lt;p&gt;गड़बड़ी ठीक करने के लिà¤, उस पेज पर &lt;strong&gt;कनेकà¥à¤Ÿ करें&lt;/strong&gt; को कà¥à¤²à¤¿à¤• करें, जिसे आप खोलने की कोशिश कर रहे हैं.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">इस पेज का कहना है कि</translation>
<translation id="153384715582417236">फिलहाल बस इतना ही</translation>
<translation id="1536390784834419204">पेज का अनà¥à¤µà¤¾à¤¦ करें</translation>
+<translation id="1539840569003678498">रिपोरà¥à¤Ÿ भेज दी गई:</translation>
<translation id="154408704832528245">डिलीवरी पता चà¥à¤¨à¥‡à¤‚</translation>
<translation id="1549470594296187301">इस सà¥à¤µà¤¿à¤§à¤¾ का उपयोग करने के लिठJavaScript को सकà¥à¤·à¤® किया जाना चाहिà¤.</translation>
<translation id="155039086686388498">इंजीनियरिंग-डी</translation>
@@ -213,16 +217,20 @@
<translation id="1682696192498422849">शॉरà¥à¤Ÿ à¤à¤œ फ़रà¥à¤¸à¥à¤Ÿ</translation>
<translation id="168693727862418163">इस नीति का मान अपनी सà¥à¤•à¥€à¤®à¤¾ के हिसाब से काम नहीं कर सका और इसे अनदेखा किया जाà¤à¤—ा.</translation>
<translation id="168841957122794586">सरà¥à¤µà¤° पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° में कमज़ोर कà¥à¤°à¤¿à¤ªà¥à¤Ÿà¥‹à¤—à¥à¤°à¤¾à¤«à¤¼à¤¿à¤• कà¥à¤‚जी है.</translation>
+<translation id="1696290444144917273">वरà¥à¤šà¥à¤…ल कारà¥à¤¡ की जानकारी देखें</translation>
<translation id="1697532407822776718">आप बिलà¥à¤•à¥à¤² तैयार हैं!</translation>
<translation id="1703835215927279855">लेटर</translation>
<translation id="1706954506755087368">{1,plural, =1{यह सरà¥à¤µà¤° पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤ नहीं कर सका कि यह <ph name="DOMAIN" /> है; इसका सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° कल से माना जाà¤à¤—ा. à¤à¤¸à¤¾ गलत कॉनà¥à¤«à¤¼à¤¿à¤—रेशन के कारण या किसी आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¤¾ दà¥à¤µà¤¾à¤°à¤¾ आपके कनेकà¥à¤¶à¤¨ को बाधित करने के कारण हो सकता है.}one{यह सरà¥à¤µà¤° पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤ नहीं कर सका कि यह <ph name="DOMAIN" /> है; इसका सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° # दिन बाद से माना जाà¤à¤—ा. à¤à¤¸à¤¾ गलत कॉनà¥à¤«à¤¼à¤¿à¤—रेशन के कारण या किसी आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¤¾ दà¥à¤µà¤¾à¤°à¤¾ आपके कनेकà¥à¤¶à¤¨ को बाधित करने के कारण हो सकता है.}other{यह सरà¥à¤µà¤° पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤ नहीं कर सका कि यह <ph name="DOMAIN" /> है; इसका सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° # दिन बाद से माना जाà¤à¤—ा. à¤à¤¸à¤¾ गलत कॉनà¥à¤«à¤¼à¤¿à¤—रेशन के कारण या किसी आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¤¾ दà¥à¤µà¤¾à¤°à¤¾ आपके कनेकà¥à¤¶à¤¨ को बाधित करने के कारण हो सकता है.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">नज़रअंदाज़ किया गया, कà¥à¤¯à¥‹à¤‚कि
+<ph name="POLICY_NAME" /> को <ph name="VALUE" /> पर सेट नहीं किया गया है.</translation>
<translation id="1712552549805331520"><ph name="URL" /> आपके सà¥à¤¥à¤¾à¤¨à¥€à¤¯ कंपà¥à¤¯à¥‚टर पर हमेशा के लिठडेटा संगà¥à¤°à¤¹à¤¿à¤¤ करना चाहता है</translation>
<translation id="1713628304598226412">टà¥à¤°à¥‡ 2</translation>
<translation id="1715874602234207">à¤à¤«à¤¼</translation>
<translation id="1717494416764505390">मेलबॉकà¥à¤¸ 3</translation>
<translation id="1718029547804390981">à¤à¤¨à¥‹à¤Ÿà¥‡à¤Ÿ करने के लिठदसà¥à¤¤à¤¾à¤µà¥‡à¤œà¤¼ बहà¥à¤¤ बड़ा है</translation>
<translation id="1721424275792716183">* फ़ीलà¥à¤¡ ज़रूरी है</translation>
+<translation id="1727613060316725209">पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° मानà¥à¤¯ है</translation>
<translation id="1727741090716970331">मानà¥à¤¯ कारà¥à¤¡ नंबर जोड़ें</translation>
<translation id="1728677426644403582">आप à¤à¤• वेब पेज का सà¥à¤°à¥‹à¤¤ देख रहे हैं</translation>
<translation id="173080396488393970">इस तरह का कारà¥à¤¡ काम नहीं करता</translation>
@@ -246,7 +254,6 @@
करने से रोकता है. साइट ऑपरेटर, साइट की सà¥à¤°à¤•à¥à¤·à¤¾ और दूसरी
पà¥à¤°à¥‰à¤ªà¤°à¥à¤Ÿà¥€ को कॉनà¥à¤«à¤¼à¤¿à¤—र करने के लिà¤, मूल नीतियों का इसà¥à¤¤à¥‡à¤®à¤¾à¤² कर सकते हैं.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">कृपया अपना सिंक 'पासफà¥à¤°à¥‡à¤œà¤¼' अपडेट करें.</translation>
<translation id="1787142507584202372"> खोले गठटैब, यहां दिखाई देंगे</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, à¤à¤• से ज़à¥à¤¯à¤¾à¤¦à¤¾ कारà¥à¤°à¤µà¤¾à¤‡à¤¯à¤¾à¤‚ उपलबà¥à¤§ हैं, à¤à¤•-à¤à¤• करके उन पर जाने के लिठTab दबाà¤à¤‚</translation>
@@ -279,6 +286,7 @@
<translation id="1919345977826869612">विजà¥à¤žà¤¾à¤ªà¤¨</translation>
<translation id="1919367280705858090">गड़बड़ी के किसी खास मैसेज से मदद पाना</translation>
<translation id="192020519938775529">{COUNT,plural, =0{कà¥à¤› नहीं}=1{1 साइट}one{# साइट}other{# साइट}}</translation>
+<translation id="1924727005275031552">नया</translation>
<translation id="1945968466830820669">आपके संगठन के खाते का à¤à¤•à¥à¤¸à¥‡à¤¸ खो सकता है या आपकी पहचान चोरी हो सकती है. Chromium आपको अभी अपना पासवरà¥à¤¡ बदलने का सà¥à¤à¤¾à¤µ देता है.</translation>
<translation id="1947454675006758438">सबसे ऊपर दाईं ओर सà¥à¤Ÿà¥‡à¤ªà¤²</translation>
<translation id="1958218078413065209">आपका सबसे ज़à¥à¤¯à¤¾à¤¦à¤¾ सà¥à¤•à¥‹à¤° <ph name="SCORE" /> है.</translation>
@@ -301,12 +309,14 @@
<translation id="2042213636306070719">टà¥à¤°à¥‡ 7</translation>
<translation id="204357726431741734">अपने Google खाते में सेव किठगठपासवरà¥à¤¡ इसà¥à¤¤à¥‡à¤®à¤¾à¤² करने के लिठसाइन इन करें</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> भाषा के पेजों का अनà¥à¤µà¤¾à¤¦ नहीं किया जाà¤à¤—ा.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{यह कंटà¥à¤°à¥‹à¤² चालू होने और सà¥à¤Ÿà¥‡à¤Ÿà¤¸ à¤à¤•à¥à¤Ÿà¤¿à¤µ होने पर, Chrome यह देखता है कि आपकी हाल की बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग गतिविधि, किस बड़े गà¥à¤°à¥à¤ª या "समानता रखने वाले लोगों" से काफ़ी हद तक मिलती है. विजà¥à¤žà¤¾à¤ªà¤¨ देने वाले, गà¥à¤°à¥à¤ª के लिठविजà¥à¤žà¤¾à¤ªà¤¨à¥‹à¤‚ को चà¥à¤¨ सकते हैं. साथ ही, आपकी बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग गतिविधि आपके डिवाइस पर गोपनीय रखी जाती है. आपका गà¥à¤°à¥à¤ª हर दिन अपडेट किया जाता है.}=1{यह कंटà¥à¤°à¥‹à¤² चालू होने और सà¥à¤Ÿà¥‡à¤Ÿà¤¸ à¤à¤•à¥à¤Ÿà¤¿à¤µ होने पर, Chrome यह देखता है कि आपकी हाल की बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग गतिविधि, किस बड़े गà¥à¤°à¥à¤ª या "समानता रखने वाले लोगों" से काफ़ी हद तक मिलती है. विजà¥à¤žà¤¾à¤ªà¤¨ देने वाले, गà¥à¤°à¥à¤ª के लिठविजà¥à¤žà¤¾à¤ªà¤¨à¥‹à¤‚ को चà¥à¤¨ सकते हैं. साथ ही, आपकी बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग गतिविधि आपके डिवाइस पर गोपनीय रखी जाती है. आपका गà¥à¤°à¥à¤ª हर दिन अपडेट किया जाता है.}one{यह कंटà¥à¤°à¥‹à¤² चालू होने और सà¥à¤Ÿà¥‡à¤Ÿà¤¸ à¤à¤•à¥à¤Ÿà¤¿à¤µ होने पर, Chrome यह देखता है कि आपकी हाल की बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग गतिविधि, किस बड़े गà¥à¤°à¥à¤ª या "समानता रखने वाले लोगों" से काफ़ी हद तक मिलती है. विजà¥à¤žà¤¾à¤ªà¤¨ देने वाले, गà¥à¤°à¥à¤ª के लिठविजà¥à¤žà¤¾à¤ªà¤¨à¥‹à¤‚ को चà¥à¤¨ सकते हैं. साथ ही, आपकी बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग गतिविधि आपके डिवाइस पर गोपनीय रखी जाती है. आपका गà¥à¤°à¥à¤ª हर {NUM_DAYS} दिन में अपडेट किया जाता है.}other{यह कंटà¥à¤°à¥‹à¤² चालू होने और सà¥à¤Ÿà¥‡à¤Ÿà¤¸ à¤à¤•à¥à¤Ÿà¤¿à¤µ होने पर, Chrome यह देखता है कि आपकी हाल की बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग गतिविधि, किस बड़े गà¥à¤°à¥à¤ª या "समानता रखने वाले लोगों" से काफ़ी हद तक मिलती है. विजà¥à¤žà¤¾à¤ªà¤¨ देने वाले, गà¥à¤°à¥à¤ª के लिठविजà¥à¤žà¤¾à¤ªà¤¨à¥‹à¤‚ को चà¥à¤¨ सकते हैं. साथ ही, आपकी बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग गतिविधि आपके डिवाइस पर गोपनीय रखी जाती है. आपका गà¥à¤°à¥à¤ª हर {NUM_DAYS} दिन में अपडेट किया जाता है.}}</translation>
<translation id="2053553514270667976">ज़िप कोड</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 सà¥à¤à¤¾à¤µ}one{# सà¥à¤à¤¾à¤µ}other{# सà¥à¤à¤¾à¤µ}}</translation>
<translation id="2071692954027939183">सूचनाओं को अपने-आप बà¥à¤²à¥‰à¤• कर दिया गया, कà¥à¤¯à¥‹à¤‚कि आम तौर पर आप उनà¥à¤¹à¥‡à¤‚ अनà¥à¤®à¤¤à¤¿ नहीं देते हैं</translation>
<translation id="2079545284768500474">पहले जैसा करें</translation>
<translation id="20817612488360358">सिसà¥â€à¤Ÿà¤® पà¥à¤°à¥‰à¤•à¥â€à¤¸à¥€ सेटिंग उपयोग किठजाने के लिठसेट हैं लेकिन कोई सà¥à¤ªà¤·à¥â€à¤Ÿ पà¥à¤°à¥‰à¤•à¥â€à¤¸à¥€ कॉनà¥à¥žà¤¿à¤—रेशन भी मौजूद है.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> में से <ph name="RESULT_NUMBER" /> परिणाम</translation>
+<translation id="2085876078937250610">सेव करें…</translation>
<translation id="2088086323192747268">सिंक करने का बटन मैनेज करें, Chrome की सेटिंग में आप जो जानकारी सिंक करते हैं उसे मैनेज करने के लिठEnter दबाà¤à¤‚</translation>
<translation id="2091887806945687916">आवाज़</translation>
<translation id="2094505752054353250">डोमेन का गलत-मिलान</translation>
@@ -379,6 +389,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> के लिठउपयोगकरà¥à¤¤à¤¾ नाम और पासवरà¥à¤¡ आवशà¥à¤¯à¤• है.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" /> को खतà¥à¤® होने वाला है</translation>
<translation id="2337852623177822836">वह सेटिंग जिसे आपका वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤• नियंतà¥à¤°à¤¿à¤¤ करता है</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> यà¥à¤—à¥à¤®à¤¿à¤¤ करना चाहता है</translation>
<translation id="2344028582131185878">अपने आप होने वाले डाउनलोड</translation>
<translation id="2346319942568447007">आपकी कॉपी की हà¥à¤ˆ इमेज</translation>
<translation id="2354001756790975382">अनà¥à¤¯ बà¥à¤•à¤®à¤¾à¤°à¥à¤•</translation>
@@ -386,8 +397,10 @@
<translation id="2355395290879513365">आप इस साइट पर जिन चितà¥à¤°à¥‹à¤‚ को देख रहे हैं, हो सकता है कि वे हमलावरों को दिखाई दें और हमलावर उनà¥à¤¹à¥‡à¤‚ बदलने के लिठआपको भà¥à¤°à¤®à¤¿à¤¤ करें.</translation>
<translation id="2356070529366658676">पूछें</translation>
<translation id="2357481397660644965">आपके डिवाइस को <ph name="DEVICE_MANAGER" /> और खाते को <ph name="ACCOUNT_MANAGER" /> पà¥à¤°à¤¬à¤‚धित करता है.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{à¤à¤• दिन से भी पहले}=1{à¤à¤• दिन में}one{{NUM_DAYS} दिन में}other{{NUM_DAYS} दिनों में}}</translation>
<translation id="2359629602545592467">à¤à¤• से ज़à¥à¤¯à¤¾à¤¦à¤¾</translation>
<translation id="2359808026110333948">जारी रखें</translation>
+<translation id="2359961752320758691">आपका वरà¥à¤šà¥à¤…ल कारà¥à¤¡ नंबर इसà¥à¤¤à¥‡à¤®à¤¾à¤² किया गया है.</translation>
<translation id="2367567093518048410">सà¥à¤¤à¤°</translation>
<translation id="2372464001869762664">आपके पà¥à¤·à¥à¤Ÿà¤¿ करने के बाद, Google खाते के कारà¥à¤¡ की जानकारी इस साइट से शेयर की जाà¤à¤—ी. सीवीसी को अपने Plex खाते की जानकारी में पाà¤à¤‚.</translation>
<translation id="2380886658946992094">कानूनी</translation>
@@ -398,6 +411,7 @@
<translation id="239429038616798445">शिपिंग का यह तरीका उपलबà¥à¤§ नहीं है. कोई दूसरा तरीका आज़माà¤à¤‚.</translation>
<translation id="2396249848217231973">मिटाना &amp;पहले जैसा करें</translation>
<translation id="2410754574180102685">सरकारी-कानूनी</translation>
+<translation id="2413155254802890957">पà¥à¤°à¤¾à¤¨à¤¾</translation>
<translation id="2413528052993050574">यह सरà¥à¤µà¤° यह पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤ नहीं कर सका कि यह <ph name="DOMAIN" />; इसका सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° निरसà¥à¤¤ कर दिया गया है. à¤à¤¸à¤¾ गलत कॉनà¥à¤«à¤¼à¤¿à¤—रेशन के कारण या किसी आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¤¾ दà¥à¤µà¤¾à¤°à¤¾ आपके कनेकà¥à¤¶à¤¨ में अवरोध डालने के कारण हो सकता है.</translation>
<translation id="2414886740292270097">गहरा</translation>
<translation id="2438874542388153331">दाईं ओर कà¥à¤µà¤¾à¤¡ पंच</translation>
@@ -425,10 +439,10 @@
<translation id="2521385132275182522">नीचे दाईं ओर सà¥à¤Ÿà¥‡à¤ªà¤²</translation>
<translation id="2523886232349826891">सिरà¥à¤«à¤¼ इस डिवाइस पर सेव किया गया</translation>
<translation id="2524461107774643265">ज़à¥à¤¯à¤¾à¤¦à¤¾ जानकारी जोड़ें</translation>
-<translation id="2526590354069164005">डेसà¥à¤•à¤Ÿà¥‰à¤ª</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{और 1 और वà¥à¤¯à¤•à¥à¤¤à¤¿}one{और # और लोग}other{और # और लोग}}</translation>
<translation id="2536110899380797252">पता जोड़ें</translation>
<translation id="2539524384386349900">पता लगाà¤à¤‚</translation>
+<translation id="2541219929084442027">आप गà¥à¤ªà¥à¤¤ टैब का इसà¥à¤¤à¥‡à¤®à¤¾à¤² करके जो पेज देखते हैं वे आपके गà¥à¤ªà¥à¤¤ टैब बंद कर देने के बाद, आपके बà¥à¤°à¤¾à¤‰à¥›à¤° के इतिहास, कà¥à¤•à¥€ संगà¥à¤°à¤¹, या खोज इतिहास में नहीं रहेंगे. आपकी डाउनलोड की गई सभी फ़ाइलें या बनाठगठबà¥à¤•à¤®à¤¾à¤°à¥à¤• रहेंगे.</translation>
<translation id="2544644783021658368">à¤à¤• दसà¥à¤¤à¤¾à¤µà¥‡à¥›</translation>
<translation id="254947805923345898">नीति का मान मानà¥à¤¯ नहीं है.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ने à¤à¤• गलत जवाब भेजा है.</translation>
@@ -448,6 +462,7 @@
<translation id="2629325967560697240">Chrome की सबसे बेहतर सà¥à¤°à¤•à¥à¤·à¤¾ पाने के लिà¤, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />बेहतर सà¥à¤°à¤•à¥à¤·à¤¾ की सà¥à¤µà¤¿à¤§à¤¾ चालू करें<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> का सरà¥à¤µà¤° आईपी पता नहीं मिल सका.</translation>
<translation id="2639739919103226564">सà¥à¤¥à¤¿à¤¤à¤¿:</translation>
+<translation id="264810637653812429">कोई संगत डिवाइस नहीं मिला.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome की सेटिंग में अपना बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग इतिहास, कà¥à¤•à¥€, कैश मेमोरी वगैरह मिटाने के लिà¤, पहले Tab और फिर Enter दबाà¤à¤‚</translation>
<translation id="2650446666397867134">फ़ाइल को à¤à¤•à¥à¤¸à¥‡à¤¸ नहीं दिया गया था</translation>
@@ -467,7 +482,7 @@
<translation id="2691924980723297736">सà¥à¤°à¤•à¥à¤·à¤¾ की चेतावनी</translation>
<translation id="2699302886720511147">सà¥à¤µà¥€à¤•à¤¾à¤° किठजाने वाले कारà¥à¤¡</translation>
<translation id="2701514975700770343">उलटा करके रखें</translation>
-<translation id="2702801445560668637">पठन सूची</translation>
+<translation id="2702801445560668637">रीडिंग लिसà¥à¤Ÿ</translation>
<translation id="2704283930420550640">मान का पà¥à¤°à¤¾à¤°à¥‚प से मिलान नहीं होता.</translation>
<translation id="2705137772291741111">इस साइट की सहेजी गई (संचित) कॉपी पढ़ने योगà¥à¤¯ नहीं थी.</translation>
<translation id="2709516037105925701">ऑटोमैटिक भरना</translation>
@@ -492,6 +507,7 @@
<translation id="2799223571221894425">फिर से लॉनà¥â€à¤š करें</translation>
<translation id="2803306138276472711">Google सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग को <ph name="SITE" /> पर हाल ही में <ph name="BEGIN_LINK" />मैलवेयर का पता चला<ph name="END_LINK" /> है. आमतौर पर सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ रहने वाली वेबसाइटें कभी-कभी मैलवेयर से संकà¥à¤°à¤®à¤¿à¤¤ हो जाती हैं.</translation>
<translation id="2807052079800581569">इमेज Y की सà¥à¤¥à¤¿à¤¤à¤¿</translation>
+<translation id="2820957248982571256">सà¥à¤•à¥ˆà¤¨ हो रहा है...</translation>
<translation id="2824775600643448204">पता और सरà¥à¤š बार</translation>
<translation id="2826760142808435982">कनेकà¥à¤¶à¤¨ को <ph name="CIPHER" /> का उपयोग करके सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ किया गया है और उसकी पहचान की गई है और यह मà¥à¤–à¥à¤¯ विनिमय तकनीक के रूप में <ph name="KX" /> का उपयोग करता है.</translation>
<translation id="2835170189407361413">फ़ॉरà¥à¤® साफ़ करें</translation>
@@ -499,6 +515,8 @@
<translation id="2850739647070081192">नà¥à¤¯à¥‹à¤¤à¤¾ (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</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="2859806420264540918">इस साइट में तंग करने वाले या गà¥à¤®à¤°à¤¾à¤¹ करने वाले विजà¥à¤žà¤¾à¤ªà¤¨ दिखाई देते हैं.</translation>
+<translation id="287596039013813457">दोसà¥à¤¤à¤¾à¤¨à¤¾</translation>
+<translation id="2876489322757410363">किसी बाहरी à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ के ज़रिठपैसे चà¥à¤•à¤¾à¤¨à¥‡ के लिठगà¥à¤ªà¥à¤¤ मोड छोड़ रहे हैं. कà¥à¤¯à¤¾ आप यह मोड बंद करना चाहते हैं?</translation>
<translation id="2878197950673342043">पोसà¥à¤Ÿà¤° फ़ोलà¥à¤¡</translation>
<translation id="2878424575911748999">à¤1</translation>
<translation id="2880660355386638022">विंडो पà¥à¤²à¥‡à¤¸à¤®à¥‡à¤‚ट</translation>
@@ -548,7 +566,6 @@
<translation id="3060227939791841287">सी9 (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome की सेटिंग में, सà¥à¤°à¤•à¥à¤·à¤¾ जांच करने के लिठपहले Tab दबाà¤à¤‚ और फिर Enter दबाà¤à¤‚</translation>
<translation id="3061707000357573562">पैच सेवा</translation>
-<translation id="3064966200440839136">किसी बाहरी à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ के ज़रिठभà¥à¤—तान करने के लिठगà¥à¤ªà¥à¤¤ मोड छोड़ रहे हैं. जारी रखना चाहते हैं?</translation>
<translation id="306573536155379004">गेम शà¥à¤°à¥‚ हो गया.</translation>
<translation id="3080254622891793721">गà¥à¤°à¤¾à¤«à¤¼à¤¿à¤•</translation>
<translation id="3086579638707268289">वेब पर की जा रही आपकी गतिविधि पर नज़र रखी जा रही है</translation>
@@ -571,7 +588,6 @@
<translation id="315504272643575312">आपके खाते को <ph name="MANAGER" /> पà¥à¤°à¤¬à¤‚धित करता है.</translation>
<translation id="3157931365184549694">वापस लाà¤à¤‚</translation>
<translation id="3162559335345991374">आप जिस वाई-फ़ाई का उपयोग कर रहे हैं, आपको उसके लॉगिन पेज पर जाने की ज़रूरत पड़ सकती है.</translation>
-<translation id="3167968892399408617">आप जो पेज गà¥à¤ªà¥à¤¤ टैब में देखते हैं, वे आपके गà¥à¤ªà¥à¤¤ टैब बंद कर देने के बाद आपके बà¥à¤°à¤¾à¤‰à¥›à¤° के इतिहास, कà¥à¤•à¥€ संगà¥à¤°à¤¹, या खोज इतिहास में नहीं रहेंगे. आपके डाउनलोड किठगठसभी फ़ाइल या बनाठगठबà¥à¤•à¤®à¤¾à¤°à¥à¤• रहेंगे.</translation>
<translation id="3169472444629675720">तलाश करें</translation>
<translation id="3174168572213147020">दà¥à¤µà¥€à¤ª</translation>
<translation id="3176929007561373547">यह पकà¥à¤•à¤¾ करने के लिठकि पà¥à¤°à¥‰à¤•à¥à¤¸à¥€ सरà¥à¤µà¤° काम कर रहा है,
@@ -596,10 +612,12 @@
<translation id="3229041911291329567">आपके डिवाइस और बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤° के वरà¥à¤¶à¤¨ के बारे में जानकारी</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> का CVC डालें.</translation>
<translation id="3234666976984236645">इस साइट पर हमेशा महतà¥â€à¤µà¤ªà¥‚रà¥à¤£ सामगà¥à¤°à¥€ का पता लगाà¤à¤‚</translation>
+<translation id="3249845759089040423">शानदार</translation>
<translation id="3252266817569339921">फ़à¥à¤°à¤¾à¤‚सीसी</translation>
<translation id="3266793032086590337">मान (मेल नहीं खा रहा)</translation>
<translation id="3268451620468152448">खà¥à¤²à¥‡ सतà¥à¤°</translation>
<translation id="3270847123878663523">&amp;पà¥à¤¨: कà¥à¤°à¤®à¤¿à¤¤ करना वापस लाà¤à¤‚</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> कनेकà¥à¤Ÿ करना चाहती है</translation>
<translation id="3274521967729236597">पा-काई</translation>
<translation id="3282085321714087552">आपके संगठन <ph name="ENROLLMENT_DOMAIN" /> ने नीचे दी गई वेबसाइटों को सेटिंग या नीतियों वगैरह के बारे में कà¥à¤› जानकारी भेजी है.</translation>
<translation id="3282497668470633863">कारà¥à¤¡ पर नाम जोड़ें</translation>
@@ -652,6 +670,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates सरà¥à¤µà¤° टेमà¥à¤ªà¥à¤²à¥‡à¤Ÿ का à¤à¤• या इससे ज़à¥à¤¯à¤¾à¤¦à¤¾ यूआरà¤à¤² अमानà¥à¤¯ है और इसका इसà¥à¤¤à¥‡à¤®à¤¾à¤² नहीं किया जाà¤à¤—ा.</translation>
<translation id="3431636764301398940">इस कारà¥à¤¡ को इस डिवाइस में सेव करें</translation>
<translation id="3432601291244612633">पेज बंद करें</translation>
+<translation id="3435738964857648380">सà¥à¤°à¤•à¥à¤·à¤¾</translation>
<translation id="3435896845095436175">चालू करें</translation>
<translation id="3438829137925142401">अपने Google खाते में सेव किठगठपासवरà¥à¤¡ इसà¥à¤¤à¥‡à¤®à¤¾à¤² करें</translation>
<translation id="3443726618221119081">जूरो-कà¥-काई</translation>
@@ -694,7 +713,10 @@
<translation id="3584299510153766161">नीचे की ओर डà¥à¤¯à¥à¤à¤² पंच</translation>
<translation id="3586931643579894722">विवरण छà¥à¤ªà¤¾à¤à¤‚</translation>
<translation id="3587738293690942763">मिडल</translation>
+<translation id="3590643883886679995">जब आप गà¥à¤ªà¥à¤¤ मोड से बाहर निकल जाà¤à¤‚गे, तब साइन इन करने का डेटा इस डिवाइस में सेव किया जाà¤à¤—ा.</translation>
+<translation id="359126217934908072">महीना/साल:</translation>
<translation id="3592413004129370115">इटैलियन (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{आप अपना पासवरà¥à¤¡ कभी भी रीसेट कर सकते हैं. नठगà¥à¤°à¥à¤ª से जà¥à¤¡à¤¼à¤¨à¥‡ में करीब-करीब à¤à¤• दिन लगता है.}=1{आप अपना पासवरà¥à¤¡ कभी भी रीसेट कर सकते हैं. नठगà¥à¤°à¥à¤ª से जà¥à¤¡à¤¼à¤¨à¥‡ में करीब-करीब à¤à¤• दिन लगता है.}one{आप अपना पासवरà¥à¤¡ कभी भी रीसेट कर सकते हैं. नठगà¥à¤°à¥à¤ª से जà¥à¤¡à¤¼à¤¨à¥‡ में {NUM_DAYS} दिन लगता है.}other{आप अपना पासवरà¥à¤¡ कभी भी रीसेट कर सकते हैं. नठगà¥à¤°à¥à¤ª से जà¥à¤¡à¤¼à¤¨à¥‡ में {NUM_DAYS} दिन लगते हैं.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">आपके à¤à¤¡à¤®à¤¿à¤¨ ने à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ को बà¥à¤²à¥‰à¤• कर दिया है</translation>
<translation id="3608932978122581043">फ़ीड ओरिà¤à¤‚टेशन</translation>
@@ -703,13 +725,13 @@
<translation id="3615877443314183785">खतà¥à¤® होने की मानà¥à¤¯ तारीख डालें</translation>
<translation id="36224234498066874">बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग डेटा साफ़ करें...</translation>
<translation id="362276910939193118">पूरा इतिहास दिखाà¤à¤‚</translation>
-<translation id="3625635938337243871">जब आप गà¥à¤ªà¥à¤¤ मोड से बाहर निकल जाà¤à¤‚गे, तब साइन इन करने का डेटा इस डिवाइस में सेव हो जाà¤à¤—ा.</translation>
<translation id="3630155396527302611">अगर वह नेटवरà¥à¤• à¤à¤•à¥à¤¸à¥‡à¤¸ करने की अनà¥à¤®à¤¤à¤¿ पाठहà¥à¤ पà¥à¤°à¥‹à¤—à¥à¤°à¤¾à¤® के रूप में पहले से ही सूची में शामिल है, तो
उसे सूची से हटाने और फिर से जोड़ने की कोशिश करें.</translation>
<translation id="3630699740441428070">इस डिवाइस के à¤à¤¡à¤®à¤¿à¤¨ ने आपके नेटवरà¥à¤• कनेकà¥à¤¶à¤¨ को कॉनà¥à¥žà¤¿à¤—र किया है. à¤à¤¸à¥‡ में, उनà¥à¤¹à¥‡à¤‚ आपके नेटवरà¥à¤• का टà¥à¤°à¥ˆà¤«à¤¼à¤¿à¤• दिख सकता है. इस टà¥à¤°à¥ˆà¤«à¤¼à¤¿à¤• में à¤à¤¸à¥€ वेबसाइटें शामिल हैं जिन पर आप जाते हैं.</translation>
<translation id="3631244953324577188">बायोमेटà¥à¤°à¤¿à¤•à¥à¤¸</translation>
<translation id="3633738897356909127">'Chrome अपडेट करें' बटन, अपनी Chrome सेटिंग से Chrome अपडेट करने के लिठEnter दबाà¤à¤‚</translation>
<translation id="3634530185120165534">टà¥à¤°à¥‡ 5</translation>
+<translation id="3637662659967048211">Google खाते में सेव करें</translation>
<translation id="3640766068866876100">इंडेकà¥à¤¸-4x6-à¤à¤•à¥à¤¸à¥à¤Ÿà¥à¤°à¤¾</translation>
<translation id="3642638418806704195">à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨:</translation>
<translation id="3650584904733503804">मानà¥à¤¯à¤•à¤°à¤£ सफल</translation>
@@ -750,6 +772,7 @@
<translation id="3781428340399460090">चमकीला गà¥à¤²à¤¾à¤¬à¥€</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">बà¥à¤²à¥‚टूथ डिवाइस</translation>
+<translation id="3787675388804467730">वरà¥à¤šà¥à¤…ल कारà¥à¤¡ नंबर</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> में खतà¥à¤® होगा</translation>
<translation id="3789155188480882154">आकार 16</translation>
<translation id="3789841737615482174">इंसà¥â€à¤Ÿà¥‰à¤² करें</translation>
@@ -769,6 +792,7 @@
<translation id="3841184659773414994">फ़ाइल हैंडलर</translation>
<translation id="385051799172605136">वापस जाà¤à¤‚</translation>
<translation id="3858027520442213535">तारीख और समय अपडेट करें</translation>
+<translation id="3881478300875776315">कम लाइनें दिखाà¤à¤‚</translation>
<translation id="3884278016824448484">विरोधाभासी डिवाइस पहचानकरà¥à¤¤à¤¾</translation>
<translation id="3885155851504623709">पैरिश</translation>
<translation id="388632593194507180">यह पता चला है कि नज़र रखी जा रही है</translation>
@@ -794,6 +818,7 @@
<translation id="397105322502079400">गणना की जा रही है...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> को बà¥à¤²à¥‰à¤• किया गया है</translation>
<translation id="3973357910713125165">यह 'Chrome की सà¥à¤°à¤•à¥à¤·à¤¾ जांच करें' बटन है. Chrome की सेटिंग में, सà¥à¤°à¤•à¥à¤·à¤¾ जांच करने के लिठEnter दबाà¤à¤‚</translation>
+<translation id="3986705137476756801">अभी के लिठलाइव कैपà¥à¤¶à¤¨ की सà¥à¤µà¤¿à¤§à¤¾ बंद करें</translation>
<translation id="3987405730340719549">Chrome के हिसाब से यह साइट नकली या धोखाधड़ी करने वाली हो सकती है.
अगर आपको लगता है कि à¤à¤¸à¤¾ गलती से दिखाया गया है, तो कृपया https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals पर जाà¤à¤‚.</translation>
@@ -890,13 +915,14 @@
<translation id="4275830172053184480">अपना डिवाइस फिर से पà¥à¤°à¤¾à¤°à¤‚भ करें</translation>
<translation id="4277028893293644418">पासवरà¥à¤¡ रीसेट करें</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{यह कारà¥à¤¡ आपके Google खाते में सेव कर लिया गया है}one{ये कारà¥à¤¡ आपके Google खाते में सेव कर लिठगठहैं}other{ये कारà¥à¤¡ आपके Google खाते में सेव कर लिठगठहैं}}</translation>
+<translation id="4287885627794386150">आज़माया जा सकता है, लेकिन चालू नहीं है</translation>
<translation id="4297502707443874121">पेज <ph name="THUMBNAIL_PAGE" /> का थंबनेल</translation>
<translation id="42981349822642051">विसà¥à¤¤à¥ƒà¤¤ करें</translation>
<translation id="4300675098767811073">दाईं ओर à¤à¤• से ज़à¥à¤¯à¤¾à¤¦à¤¾ पंच</translation>
<translation id="4302514097724775343">डायनो को चलाने के लिà¤, उस पर टैप करें</translation>
<translation id="4302965934281694568">शू3 (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
<translation id="4305666528087210886">आपकी फ़ाइल à¤à¤•à¥à¤¸à¥‡à¤¸ नहीं की जा सकी</translation>
-<translation id="4305817255990598646">बदलें</translation>
+<translation id="4306529830550717874">कà¥à¤¯à¤¾ आप पता सेव करना चाहते हैं?</translation>
<translation id="4312613361423056926">बी2</translation>
<translation id="4312866146174492540">बà¥à¤²à¥‰à¤• करें (डिफ़ॉलà¥à¤Ÿ)</translation>
<translation id="4314815835985389558">सिंक पà¥à¤°à¤¬à¤‚धित करें</translation>
@@ -923,6 +949,7 @@
<translation id="4377125064752653719">आपने <ph name="DOMAIN" /> तक पहà¥à¤‚चने की कोशिश की, लेकिन सरà¥à¤µà¤° से मिले पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° को उसके जारीकरà¥à¤¤à¤¾ ने रदà¥à¤¦ कर दिया है. इसका मतलब है कि सरà¥à¤µà¤° से मिली सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤¿à¤•à¤¤à¤¾ पर पूरी तरह भरोसा नहीं करना चाहिà¤. हो सकता है कि आप किसी हमलावर से बातचीत कर रहे हों.</translation>
<translation id="4378154925671717803">फ़ोन</translation>
<translation id="4390472908992056574">बà¥à¤°à¤¿à¤®</translation>
+<translation id="4406883609789734330">लाइव कैपà¥à¤¶à¤¨</translation>
<translation id="4406896451731180161">खोज नतीजे</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> कà¥à¤•à¥€</translation>
<translation id="4414290883293381923">आपने अभी जिस साइट पर अपना पासवरà¥à¤¡ डाला है वह सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नहीं है. Chrome, <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />, और उन साइटों पर जाकर पासवरà¥à¤¡ बदलने का सà¥à¤à¤¾à¤µ देता है जिन पर आपने इसका इसà¥à¤¤à¥‡à¤®à¤¾à¤² किया था.</translation>
@@ -935,7 +962,6 @@
<translation id="4435702339979719576">पोसà¥à¤Ÿà¤•à¤¾à¤°à¥à¤¡)</translation>
<translation id="443673843213245140">पà¥à¤°à¥‰à¤•à¥â€à¤¸à¥€ का उपयोग अकà¥à¤·à¤® है लेकिन कोई सà¥â€à¤ªà¤·à¥à¤Ÿ पà¥à¤°à¥‰à¤•à¥â€à¤¸à¥€ कॉनà¥à¥žà¤¿à¤—रेशन दरà¥à¤œ किया गया है.</translation>
<translation id="4464826014807964867">à¤à¤¸à¥€ वेबसाइटें जिनके बारे में आपके संगठन ने जानकारी दी है</translation>
-<translation id="4466881336512663640">फ़ॉरà¥à¤® में किठगठबदलाव हटा दिठजाà¤à¤à¤—े. कà¥à¤¯à¤¾ आप वाकई जारी रखना चाहते हैं?</translation>
<translation id="4476953670630786061">यह फ़ॉरà¥à¤® सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नहीं है. ऑटोमैटिक भरने की सà¥à¤µà¤¿à¤§à¤¾ बंद कर दी गई है.</translation>
<translation id="4477350412780666475">अगला टà¥à¤°à¥ˆà¤•</translation>
<translation id="4482953324121162758">इस साइट का अनà¥à¤µà¤¾à¤¦ नहीं किया जाà¤à¤—ा.</translation>
@@ -969,6 +995,7 @@
<translation id="4594403342090139922">मिटाना &amp;पहले जैसा करें</translation>
<translation id="4597348597567598915">आकार 8</translation>
<translation id="4600854749408232102">सी6/सी5 (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
+<translation id="4606870351894164739">असरदार</translation>
<translation id="4628948037717959914">फ़ोटो</translation>
<translation id="4631649115723685955">पैसे चà¥à¤•à¤¾à¤¨à¥‡ पर कैशबैक मिलेगा</translation>
<translation id="4636930964841734540">जानकारी</translation>
@@ -988,6 +1015,7 @@
<translation id="4691835149146451662">आरà¥à¤•à¤¿à¤Ÿà¥‡à¤•à¥à¤šà¤°-ठ(à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">साइड</translation>
+<translation id="4702656508969495934">लाइव कैपà¥à¤¶à¤¨ दिख रहा है, इस पर फ़ोकस ले जाने के लिà¤, विंडो बदलने का बटन इसà¥à¤¤à¥‡à¤®à¤¾à¤² करें</translation>
<translation id="4708268264240856090">आपका कनेकà¥à¤¶à¤¨ बाधित था</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows नेटवरà¥à¤• निदान चलाकर देखें<ph name="END_LINK" /></translation>
@@ -1001,6 +1029,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> खोज सà¥à¤à¤¾à¤µ</translation>
<translation id="4742407542027196863">पासवरà¥à¤¡ पà¥à¤°à¤¬à¤‚धित करें…</translation>
<translation id="4744603770635761495">निषà¥à¤ªà¤¾à¤¦à¤¿à¤¤ किठजाने वाले पाथ</translation>
+<translation id="4749011317274908093">आप गà¥à¤ªà¥à¤¤ मोड में चले गठहैं</translation>
<translation id="4750917950439032686">आपकी जानकारी (जैसे- पासवरà¥à¤¡ या कà¥à¤°à¥‡à¤¡à¤¿à¤Ÿ कारà¥à¤¡ नंबर वगैरह) जब इस साइट पर भेजी जाती है, तब वह निजी होती है.</translation>
<translation id="4756388243121344051">&amp;इतिहास</translation>
<translation id="4758311279753947758">संपरà¥à¤• जानकारी जोड़ें</translation>
@@ -1030,6 +1059,8 @@
<translation id="4813512666221746211">नेटवरà¥à¤• गड़बड़ी</translation>
<translation id="4816492930507672669">पेज में फ़िट करें</translation>
<translation id="4819347708020428563">कà¥à¤¯à¤¾ आप डिफ़ॉलà¥à¤Ÿ वà¥à¤¯à¥‚ में वीडियो के ऊपर टेकà¥à¤¸à¥à¤Ÿ, लिंक वगैरह में बदलाव करना चाहते हैं?</translation>
+<translation id="4825507807291741242">दमदार</translation>
+<translation id="4838327282952368871">खà¥à¤µà¤¾à¤¬ जैसा</translation>
<translation id="484462545196658690">ऑटो</translation>
<translation id="4850886885716139402">देखें</translation>
<translation id="485316830061041779">जरà¥à¤®à¤¨</translation>
@@ -1166,6 +1197,7 @@
<translation id="5314967030527622926">बà¥à¤•à¤²à¥‡à¤Ÿ मेकर</translation>
<translation id="5316812925700871227">घड़ी की विपरीत दिशा में घà¥à¤®à¤¾à¤à¤‚</translation>
<translation id="5317780077021120954">सेव करें</translation>
+<translation id="5321288445143113935">बड़ा किया गया</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> में से <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">संपरà¥à¤• जानकारी चà¥à¤¨à¥‡à¤‚</translation>
<translation id="5327248766486351172">नाम</translation>
@@ -1173,11 +1205,13 @@
<translation id="5332219387342487447">शिपिंग का तरीका</translation>
<translation id="5333022057423422993">Chrome के मà¥à¤¤à¤¾à¤¬à¤¿à¤•, आपने अभी जो पासवरà¥à¤¡ इसà¥à¤¤à¥‡à¤®à¤¾à¤² किया है वह लीक हो चà¥à¤•à¤¾ है. आपके खातों को सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ रखने के लिà¤, हमारा सà¥à¤à¤¾à¤µ है कि आप अपने सेव किठगठपासवरà¥à¤¡ की जांच करें.</translation>
<translation id="5334013548165032829">सिसà¥à¤Ÿà¤® लॉग की ज़à¥à¤¯à¤¾à¤¦à¤¾ जानकारी</translation>
+<translation id="5334145288572353250">कà¥à¤¯à¤¾ आप पता सेव करना चाहते हैं?</translation>
<translation id="5340250774223869109">à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ को बà¥à¤²à¥‰à¤• किया गया है</translation>
<translation id="534295439873310000">NFC डिवाइस</translation>
<translation id="5344579389779391559">यह पेज आपसे शà¥à¤²à¥à¤• लेने की कोशिश कर सकता है</translation>
<translation id="5355557959165512791">आप इस समय <ph name="SITE" /> पर नहीं जा सकते हैं कà¥à¤¯à¥‹à¤‚कि उसका पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° रदà¥à¤¦ कर दिया गया है. नेटवरà¥à¤• की गड़बड़ी और हमले आमतौर पर कà¥à¤› देर के लिठहोते हैं, इसलिठमà¥à¤®à¤•à¤¿à¤¨ है कि यह पेज बाद में काम करे.</translation>
<translation id="536296301121032821">नीति सेटिंग संगà¥à¤°à¤¹à¤¿à¤¤ करने में विफल</translation>
+<translation id="5363309033720083897">à¤à¤¸à¤¾ सीरियल पोरà¥à¤Ÿ जिसकी अनà¥à¤®à¤¤à¤¿ आपके à¤à¤¡à¤®à¤¿à¤¨ ने दी है</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="5386426401304769735">इस साइट की पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° शृंखला में, SHA-1 का उपयोग करके हसà¥à¤¤à¤¾à¤•à¥à¤·à¤° किया गया पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° शामिल है.</translation>
@@ -1186,6 +1220,7 @@
<translation id="5398772614898833570">विजà¥à¤žà¤¾à¤ªà¤¨ बà¥à¤²à¥‰à¤• हैं</translation>
<translation id="5400836586163650660">सà¥à¤²à¥‡à¤Ÿà¥€</translation>
<translation id="540969355065856584">यह सरà¥à¤µà¤° यह पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤ नहीं कर सका कि यह <ph name="DOMAIN" /> है; इसका सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£ पतà¥à¤° इस समय मानà¥à¤¯ नहीं है. à¤à¤¸à¤¾ गलत कॉनà¥à¥žà¤¿à¤—रेशन या किसी आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¤¾ दà¥à¤µà¤¾à¤°à¤¾ आपके कनेकà¥à¤¶à¤¨ में अवरोध डालने के कारण हो सकता है.</translation>
+<translation id="541143247543991491">कà¥à¤²à¤¾à¤‰à¤¡ (पूरे सिसà¥à¤Ÿà¤® में)</translation>
<translation id="541416427766103491">सà¥à¤Ÿà¥ˆà¤•à¤° 4</translation>
<translation id="5421136146218899937">बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग डेटा साफ़ करें...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> वेबसाइट आपको सूचनाà¤à¤‚ भेजना चाहती है</translation>
@@ -1199,6 +1234,7 @@
<translation id="5455374756549232013">खराब नीति टाइमसà¥à¤Ÿà¥ˆà¤®à¥à¤ª</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" /> अनà¥à¤¯}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="5463625433003343978">डिवाइस ढूंढे जा रहे हैं...</translation>
<translation id="5469868506864199649">इतालवी</translation>
<translation id="5470861586879999274">&amp;बदलाव को फिर से लागू करें</translation>
<translation id="5478437291406423475">बी6/सी4 (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
@@ -1248,7 +1284,6 @@
<translation id="5624120631404540903">पासवरà¥à¤¡ पà¥à¤°à¤¬à¤‚धित करें</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="563324245173044180">भà¥à¤°à¤¾à¤®à¤• सामगà¥à¤°à¥€ बà¥à¤²à¥‰à¤• की गई.</translation>
<translation id="5644090287519800334">साइड 1 इमेज X शिफ़à¥à¤Ÿ</translation>
@@ -1287,12 +1322,12 @@
<translation id="5785756445106461925">इसके अतिरिकà¥à¤¤, इस पेज में à¤à¤¸à¥‡ अनà¥à¤¯ संसाधन भी शामिल हैं, जो सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नहीं हैं. टà¥à¤°à¤¾à¤‚ज़िट में होने के दौरान ये संसाधन अनà¥à¤¯ लोगों दà¥à¤µà¤¾à¤°à¤¾ देखे जा सकते हैं और पेज का सà¥à¤µà¤°à¥‚प बदलने के लिठकिसी हमवलावर दà¥à¤µà¤¾à¤°à¤¾ इनमें बदलाव किठजा सकते हैं.</translation>
<translation id="5786044859038896871">कà¥à¤¯à¤¾ अपनी कारà¥à¤¡ जानकारी भरना चाहते हैं?</translation>
<translation id="578633867165174378">Chrome के मà¥à¤¤à¤¾à¤¬à¤¿à¤•, आपने अभी जो पासवरà¥à¤¡ इसà¥à¤¤à¥‡à¤®à¤¾à¤² किया है वह लीक हो चà¥à¤•à¤¾ है. हमारा सà¥à¤à¤¾à¤µ है कि आप इस पासवरà¥à¤¡ को अभी बदल दें.</translation>
-<translation id="5798290721819630480">बदलाव खारिज कर दें?</translation>
<translation id="5803412860119678065">कà¥à¤¯à¤¾ आप अपनी <ph name="CARD_DETAIL" /> भरना चाहते हैं?</translation>
<translation id="5804241973901381774">अनà¥à¤®à¤¤à¤¿à¤¯à¤¾à¤‚</translation>
<translation id="5804427196348435412">NFC डिवाइस इसà¥à¤¤à¥‡à¤®à¤¾à¤² करें</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> से आपके कनेकà¥à¤¶à¤¨ को किसी पà¥à¤°à¤¾à¤¨à¥‡ सिफ़र सà¥à¤‡à¤Ÿ का उपयोग करके सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ किया गया है.</translation>
<translation id="5813119285467412249">&amp;जोड़ना फिर से करें</translation>
+<translation id="5817918615728894473">यà¥à¤—à¥â€à¤®à¤¿à¤¤ करें</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{जब आप पैसे चà¥à¤•à¤¾à¤à¤‚गे, तब इस कारà¥à¤¡ से पैसे लिठजाà¤à¤‚गे. हालांकि, इसके सही नंबर को इस साइट के साथ शेयर नहीं किया जाà¤à¤—ा. ज़à¥à¤¯à¤¾à¤¦à¤¾ सà¥à¤°à¤•à¥à¤·à¤¾ के लिà¤, कà¥à¤› समय तक मानà¥à¤¯ रहने वाला कारà¥à¤¡ वेरीफ़िकेशन कोड (सीवीसी) जनरेट किया जाà¤à¤—ा.}one{जब आप पैसे चà¥à¤•à¤¾à¤à¤‚गे, तब आपके चà¥à¤¨à¥‡ हà¥à¤ कारà¥à¤¡ से पैसे लिठजाà¤à¤‚गे. हालांकि, इसके सही नंबर को इस साइट के साथ शेयर नहीं किया जाà¤à¤—ा. ज़à¥à¤¯à¤¾à¤¦à¤¾ सà¥à¤°à¤•à¥à¤·à¤¾ के लिà¤, कà¥à¤› समय तक मानà¥à¤¯ रहने वाला कारà¥à¤¡ वेरीफ़िकेशन कोड (सीवीसी) जनरेट किया जाà¤à¤—ा.}other{जब आप पैसे चà¥à¤•à¤¾à¤à¤‚गे, तब आपके चà¥à¤¨à¥‡ हà¥à¤ कारà¥à¤¡ से पैसे लिठजाà¤à¤‚गे. हालांकि, इसके सही नंबर को इस साइट के साथ शेयर नहीं किया जाà¤à¤—ा. ज़à¥à¤¯à¤¾à¤¦à¤¾ सà¥à¤°à¤•à¥à¤·à¤¾ के लिà¤, कà¥à¤› समय तक मानà¥à¤¯ रहने वाला कारà¥à¤¡ वेरीफ़िकेशन कोड (सीवीसी) जनरेट किया जाà¤à¤—ा.}}</translation>
<translation id="5826507051599432481">सामानà¥à¤¯ नाम (CN)</translation>
<translation id="5838278095973806738">आपको इस साइट पर कोई भी संवेदनशील जानकारी (उदाहरण के लिà¤, पासवरà¥à¤¡ या कà¥à¤°à¥‡à¤¡à¤¿à¤Ÿ कारà¥à¤¡) नहीं डालनी चाहिà¤, कà¥à¤¯à¥‹à¤‚कि उसे हमलावर चà¥à¤°à¤¾ सकते हैं.</translation>
@@ -1300,6 +1335,7 @@
<translation id="5855253129151731373">इस साइट का होसà¥à¤Ÿà¤¨à¤¾à¤® <ph name="LOOKALIKE_DOMAIN" /> से मिलता-जà¥à¤²à¤¤à¤¾ है. हमलावर कभी-कभी डोमेन नाम में छोटे और नज़र न आने वाले बदलाव करके, साइटों की नकल कर लेते हैं.
अगर आपको लगता है कि à¤à¤¸à¤¾ गलती से दिखाया गया है, तो कृपया https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals पर जाà¤à¤‚.</translation>
+<translation id="5860033963881614850">बंद</translation>
<translation id="5862579898803147654">सà¥à¤Ÿà¥ˆà¤•à¤° 8</translation>
<translation id="5863847714970149516">आगे आने वाला पेज आपसे शà¥à¤²à¥à¤• लेने की कोशिश कर सकता है</translation>
<translation id="5866257070973731571">फ़ोन नंबर जोड़ें</translation>
@@ -1316,6 +1352,7 @@
<translation id="5913377024445952699">सà¥à¤•à¥à¤°à¥€à¤¨ को कैपà¥à¤šà¤° करने की सà¥à¤µà¤¿à¤§à¤¾ रोक दी गई है</translation>
<translation id="59174027418879706">चालू किया गया</translation>
<translation id="5919090499915321845">बी10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 उपयोग में है}one{# उपयोग में हैं}other{# उपयोग में हैं}}</translation>
<translation id="5921185718311485855">चालू है</translation>
<translation id="5921639886840618607">कारà¥à¤¡ को Google खाते में सेव करें?</translation>
<translation id="5922853866070715753">करीब-करीब हो गया है</translation>
@@ -1335,6 +1372,7 @@
<translation id="5989320800837274978">न तो कोई फ़िकà¥â€à¤¸à¥â€à¤¡ पà¥à¤°à¥‰à¤•à¥â€à¤¸à¥€ सरà¥à¤µà¤° और न ही कोई .pac सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ URL साफ़ तौर पर बताया गया है.</translation>
<translation id="5992691462791905444">इंजीनियरिंग ज़ी-फ़ोलà¥à¤¡</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' के लिठ<ph name="RESULT_COUNT" /> नतीजे मिले हैं</translation>
+<translation id="6006484371116297560">कà¥à¤²à¤¾à¤¸à¤¿à¤•</translation>
<translation id="6008122969617370890">N-से-1 के कà¥à¤°à¤® में</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">अपना पासवरà¥à¤¡ जांचें</translation>
@@ -1356,6 +1394,7 @@
<translation id="6045164183059402045">इमà¥à¤ªà¥‹à¤œà¤¼à¤¿à¤¶à¤¨ टेमà¥à¤ªà¥à¤²à¥‡à¤Ÿ</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="6049004884579590341">पूरी सà¥à¤•à¥à¤°à¥€à¤¨ से बाहर निकलने के लिठ|<ph name="ACCELERATOR" />| दबाकर रखें</translation>
<translation id="6049488691372270142">पेज डिलीवरी</translation>
<translation id="6051221802930200923">आप इस समय <ph name="SITE" /> पर नहीं जा सकते कà¥à¤¯à¥‹à¤‚कि वेबसाइट, पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° पिनिंग का उपयोग करती है. नेटवरà¥à¤• की गड़बड़ियां और हमले आमतौर पर कà¥à¤› समय के लिठहोते हैं इसलिठयह पेज शायद बाद में ठीक से काम करेगा.</translation>
<translation id="6051898664905071243">पेजों की संखà¥à¤¯à¤¾:</translation>
@@ -1372,6 +1411,7 @@
<translation id="610911394827799129">आपके Google खाते में <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> पर दूसरी तरह के बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤¿à¤‚ग इतिहास हो सकते हैं</translation>
<translation id="6116338172782435947">कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡ पर कॉपी किठगठलेख और इमेज देखें</translation>
<translation id="6120179357481664955">कà¥à¤¯à¤¾ आप चाहते हैं कि हम आपका UPI आईडी रखें?</translation>
+<translation id="6123290840358279103">वरà¥à¤šà¥à¤…ल कारà¥à¤¡ देखें</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">सभी केबल जांचें और आपके उपयोग किठजा रहे सभी राउटर, मॉडेम या अनà¥à¤¯ नेटवरà¥à¤•
डिवाइस को 'फिर चालू करें'.</translation>
@@ -1408,6 +1448,7 @@
<translation id="6289939620939689042">पेज का रंग</translation>
<translation id="6290238015253830360">आपके सà¥à¤à¤¾à¤ हà¥à¤ लेख यहां दिखाई देते हैं</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">'Chrome में Google Assistant' को रोका जा रहा है</translation>
<translation id="6305205051461490394"><ph name="URL" /> तक नहीं पहà¥à¤‚चा जा सकता.</translation>
<translation id="6312113039770857350">वेबपेज उपलबà¥à¤§ नहीं है</translation>
@@ -1433,6 +1474,7 @@
<translation id="6390200185239044127">ज़ी-फ़ोलà¥à¤¡ हालà¥à¥ž</translation>
<translation id="6390662030813198813">इंजीनियरिंग-ई</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> से इस जगह पर टेकà¥à¤¸à¥à¤Ÿ चिपकाने की सà¥à¤µà¤¿à¤§à¤¾ को आपके à¤à¤¡à¤®à¤¿à¤¨ ने बà¥à¤²à¥‰à¤• कर दिया है</translation>
+<translation id="6398765197997659313">फ़à¥à¤² सà¥à¤•à¥à¤°à¥€à¤¨ से बाहर निकलें</translation>
<translation id="6401136357288658127">यह नीति हटा दी गई है. आपको इसके बजाय, इस <ph name="NEW_POLICY" /> नीति का इसà¥à¤¤à¥‡à¤®à¤¾à¤² करना चाहिà¤.</translation>
<translation id="6404511346730675251">बà¥à¤•à¤®à¤¾à¤°à¥à¤• में बदलाव करें</translation>
<translation id="6406765186087300643">सी0 (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
@@ -1445,7 +1487,6 @@
<translation id="6428450836711225518">अपने फ़ोन नंबर की पà¥à¤·à¥à¤Ÿà¤¿ करें</translation>
<translation id="6433490469411711332">संपरà¥à¤• जानकारी में बदलाव करें</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ने कनेकà¥à¤Ÿ करने से मना कर दिया है.</translation>
-<translation id="6434309073475700221">खारिज करें</translation>
<translation id="6440503408713884761">अनदेखा किया गया</translation>
<translation id="6443406338865242315">आपने कौनसे à¤à¤•à¥à¤¸à¤Ÿà¥‡à¤‚शन और पà¥à¤²à¤— इन इंसà¥à¤Ÿà¥‰à¤² किठहैं</translation>
<translation id="6446163441502663861">काहू (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
@@ -1488,6 +1529,7 @@
<translation id="6624427990725312378">संपरà¥à¤• जानकारी</translation>
<translation id="6626291197371920147">मानà¥à¤¯ कारà¥à¤¡ नंबर जोड़ें</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> सरà¥à¤š</translation>
+<translation id="6630043285902923878">यूà¤à¤¸à¤¬à¥€ डिवाइस ढूंढें जा रहे हैं...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">साफ़ करें</translation>
@@ -1503,6 +1545,7 @@
<translation id="6671697161687535275">कà¥à¤°à¥‹à¤®à¤¿à¤¯à¤® से फ़ॉरà¥à¤® सà¥à¤à¤¾à¤µ निकालें?</translation>
<translation id="6685834062052613830">पà¥à¤°à¤¸à¥à¤¥à¤¾à¤¨ करें और सेटअप पूरा करें</translation>
<translation id="6687335167692595844">फ़ॉनà¥à¤Ÿ साइज़ का अनà¥à¤°à¥‹à¤§ किया गया</translation>
+<translation id="6688743156324860098">अपडेट करें…</translation>
<translation id="6689249931105087298">बà¥à¤²à¥ˆà¤• पॉइंट कंपà¥à¤°à¥‡à¤¶à¤¨ से मिलता-जà¥à¤²à¤¤à¤¾</translation>
<translation id="6689271823431384964">आपके साइन इन किठहोने की वजह से, Chrome आपको Google खाते में कारà¥à¤¡ सेव करने की सà¥à¤µà¤¿à¤§à¤¾ देता है. आप 'सेटिंग' में जाकर इसे बदल सकते हैं. कारà¥à¤¡à¤§à¤¾à¤°à¤• का नाम आपके खाते से लिया जाता है.</translation>
<translation id="6698381487523150993">निरà¥à¤®à¤¿à¤¤:</translation>
@@ -1518,6 +1561,7 @@
<translation id="6744009308914054259">कनेकà¥à¤¶à¤¨ का इंतज़ार करते समय, ऑफ़लाइन लेख पढ़ने के लिठआप 'डाउनलोड' पर जा सकते हैं.</translation>
<translation id="6753269504797312559">नीति मान</translation>
<translation id="6757797048963528358">आपका डिवाइस निषà¥à¤•à¥à¤°à¤¿à¤¯ हो गया है.</translation>
+<translation id="6767985426384634228">कà¥à¤¯à¤¾ आप पता अपडेट करना चाहते हैं?</translation>
<translation id="6768213884286397650">हगाकी (पोसà¥à¤Ÿà¤•à¤¾à¤°à¥à¤¡)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">बैंगनी</translation>
@@ -1540,6 +1584,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome इस पेज को रीडर मोड में दिखा रहा है, ताकि इसे आसानी से पढ़ा जा सके. Chrome ने à¤à¤• असà¥à¤°à¤•à¥à¤·à¤¿à¤¤ कनेकà¥à¤¶à¤¨ पर मूल पेज काे फिर से पा लिया है.</translation>
<translation id="6891596781022320156">नीति सà¥à¤¤à¤° समरà¥à¤¥à¤¿à¤¤ नहीं है.</translation>
+<translation id="6895143722905299846">वरà¥à¤šà¥à¤…ल नंबर:</translation>
<translation id="6895330447102777224">आपके कारà¥à¤¡ की पà¥à¤·à¥à¤Ÿà¤¿ हो गई है</translation>
<translation id="6897140037006041989">उपयोगकरà¥à¤¤à¤¾ à¤à¤œà¥‡à¤‚ट</translation>
<translation id="6898699227549475383">संगठन (O)</translation>
@@ -1575,10 +1620,10 @@
<translation id="7004583254764674281">कारà¥à¤¡ की जलà¥à¤¦à¥€ पà¥à¤·à¥à¤Ÿà¤¿ करने के लिà¤, Windows Hello का इसà¥à¤¤à¥‡à¤®à¤¾à¤² करें</translation>
<translation id="7006930604109697472">फिर भी भेजें</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">साइज़ बदलने वाली सेटिंग</translation>
<translation id="7014741021609395734">ज़ूम लेवल</translation>
<translation id="7016992613359344582">ये शà¥à¤²à¥à¤• à¤à¤• बार लगने वाले या बार-बार लगने वाले हो सकते हैं और हो सकता है कि इनके बारे में सà¥à¤ªà¤·à¥à¤Ÿ जानकारी न दी जाà¤.</translation>
<translation id="7029809446516969842">पासवरà¥à¤¡</translation>
+<translation id="7030436163253143341">पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° मानà¥à¤¯ नहीं है</translation>
<translation id="7031646650991750659">आपने Google Play के कौनसे à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ इंसà¥à¤Ÿà¥‰à¤² किठहैं</translation>
<translation id="7050187094878475250">आपने <ph name="DOMAIN" /> तक पहà¥à¤‚चने का पà¥à¤°à¤¯à¤¾à¤¸ किया था, लेकिन सरà¥à¤µà¤° ने à¤à¤¸à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° पà¥à¤°à¤¸à¥â€à¤¤à¥à¤¤ किया जिसकी मानà¥â€à¤¯à¤¤à¤¾ अवधि विशà¥â€à¤µà¤¸à¤¨à¥€à¤¯ होने के लिठबहà¥à¤¤ लंबी है.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{यह कारà¥à¤¡ इस समय सेव नहीं किया जा सकता}one{ये कारà¥à¤¡ इस समय सेव नहीं किठजा सकते}other{ये कारà¥à¤¡ इस समय सेव नहीं किठजा सकते}}</translation>
@@ -1648,12 +1693,14 @@
<translation id="7300012071106347854">कोबालà¥à¤Ÿ नीला</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">ज़à¥à¤¯à¤¾à¤¦à¤¾</translation>
+<translation id="7305756307268530424">धीरे-धीरे शà¥à¤°à¥‚ करें</translation>
<translation id="7319430975418800333">à¤3</translation>
<translation id="7320336641823683070">कनेकà¥à¤¶à¤¨ संबंधी सहायता</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" सेकà¥à¤¶à¤¨ को छिपाà¤à¤‚</translation>
<translation id="733354035281974745">डिवाइस का सà¥à¤¥à¤¾à¤¨à¥€à¤¯ खाता बदलें</translation>
<translation id="7333654844024768166">आपने अभी जिस साइट पर अपना पासवरà¥à¤¡ डाला है वह सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नहीं है. कà¥à¤°à¥‹à¤®à¤¿à¤¯à¤®, <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />, और उन साइटों पर जाकर पासवरà¥à¤¡ बदलने का सà¥à¤à¤¾à¤µ देता है जिन पर आपने इसका इसà¥à¤¤à¥‡à¤®à¤¾à¤² किया था.</translation>
<translation id="7334320624316649418">&amp;पà¥à¤¨: कà¥à¤°à¤®à¤¿à¤¤ करना फिर से करें</translation>
+<translation id="7337248890521463931">और लाइनें दिखाà¤à¤‚</translation>
<translation id="7337706099755338005">आपके पà¥à¤²à¥‡à¤Ÿà¤«à¤¼à¥‰à¤°à¥à¤® पर उपलबà¥à¤§ नहीं है.</translation>
<translation id="733923710415886693">पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° पारदरà¥à¤¶à¤¿à¤¤à¤¾ के माधà¥à¤¯à¤® से सरà¥à¤µà¤° के पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° को पà¥à¤°à¤•à¤Ÿ नहीं किया गया.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1661,6 +1708,7 @@
<translation id="7349430561505560861">à¤4-à¤à¤•à¥à¤¸à¥à¤Ÿà¥à¤°à¤¾</translation>
<translation id="7353601530677266744">कमांड लाइन</translation>
<translation id="7359588939039777303">विजà¥à¤žà¤¾à¤ªà¤¨ बà¥à¤²à¥‰à¤• हैं.</translation>
+<translation id="7363096869660964304">हालांकि, गà¥à¤ªà¥à¤¤ मोड का मतलब यह नहीं है कि आपको कोई नहीं देख सकता. गà¥à¤ªà¥à¤¤ मोड में आप जो भी बà¥à¤°à¤¾à¤‰à¤œà¤¼ करते हैं उसे ये देख सकते हैं: आप जिस कंपनी में काम करते हैं, इंटरनेट सेवा देने वाली कंपनी या वे वेबसाइटें जिन पर आप जाते हैं.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome की सेटिंग में पते जोड़ने और मैनेज करने के लिà¤, पहले Tab और फिर Enter दबाà¤à¤‚</translation>
<translation id="7365849542400970216">कà¥à¤¯à¤¾ आप जानते हैं कि आपका डिवाइस किस काम आता है?</translation>
<translation id="7372973238305370288">खोज नतीजे</translation>
@@ -1671,7 +1719,9 @@
<translation id="7378594059915113390">मीडिया नियंतà¥à¤°à¤£</translation>
<translation id="7378627244592794276">नहीं</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">लागू नहीं</translation>
<translation id="7390545607259442187">कारà¥à¤¡ की पà¥à¤·à¥à¤Ÿà¤¿ करें</translation>
+<translation id="7392089738299859607">पता अपडेट करें</translation>
<translation id="7399802613464275309">सà¥à¤°à¤•à¥à¤·à¤¾ जांच</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">आपका <ph name="DEVICE_NAME" /> पà¥à¤°à¤¬à¤‚धित है</translation>
@@ -1686,6 +1736,7 @@
&lt;li&gt;&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome सहायता केंदà¥à¤°&lt;/a&gt; पर जाकर अपने कंपà¥à¤¯à¥‚टर से सॉफ़à¥à¤Ÿà¤µà¥‡à¤¯à¤° को हमेशा के लिठहटाने का तरीका जानें
&lt;/ol&gt;</translation>
<translation id="741007362987735528">चौड़े पेज वाला फ़ॉरà¥à¤®à¥ˆà¤Ÿ</translation>
+<translation id="7410471291937727359">पà¥à¤¯à¤¾à¤°à¤¾</translation>
<translation id="7416351320495623771">पासवरà¥à¤¡ पà¥à¤°à¤¬à¤‚धित करें…</translation>
<translation id="7419106976560586862">पà¥à¤°à¥‹à¥žà¤¾à¤‡à¤² पाथ</translation>
<translation id="7437289804838430631">संपरà¥à¤• जानकारी जोड़ें</translation>
@@ -1701,7 +1752,7 @@
<translation id="7481312909269577407">आगे जाà¤à¤‚</translation>
<translation id="7485870689360869515">कोई डेटा नहीं मिला</translation>
<translation id="7495528107193238112">इस कॉनà¥à¤Ÿà¥‡à¤‚ट को बà¥à¤²à¥‰à¤• कर दिया गया है. समसà¥à¤¯à¤¾ को ठीक करने के लिà¤, साइट के मालिक से संपरà¥à¤• करें.</translation>
-<translation id="7498234416455752244">बदलाव करना जारी रखें</translation>
+<translation id="7498193950643227031">हो सकता है कि साइज़ में बदलाव करने पर, यह अनचाहे तरीके से काम करे. अब आप <ph name="SETTINGS" /> में जाकर, à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ की साइज़ में बदलाव करने की सà¥à¤µà¤¿à¤§à¤¾ को सीमित कर सकते हैं.</translation>
<translation id="7503664977220660814">आपने अभी जिस साइट पर अपना पासवरà¥à¤¡ डाला है वह सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नहीं है. कà¥à¤°à¥‹à¤®à¤¿à¤¯à¤®, <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> और उन साइटों पर तà¥à¤°à¤‚त जाकर, सेव किठगठपासवरà¥à¤¡ की जांच करने का सà¥à¤à¤¾à¤µ देता है जिन पर आपने इस पासवरà¥à¤¡ का इसà¥à¤¤à¥‡à¤®à¤¾à¤² किया है.</translation>
<translation id="7508255263130623398">वापस लौटाया हà¥à¤† नीति डिवाइस आईडी खाली है या उसका मिलान वरà¥à¤¤à¤®à¤¾à¤¨ डिवाइस आईडी से नहीं होता है</translation>
<translation id="7508870219247277067">à¤à¤µà¥‹à¤•à¥ˆà¤¡à¥‹ हरा</translation>
@@ -1721,6 +1772,7 @@
<translation id="7548892272833184391">कनेकà¥à¤¶à¤¨ गड़बड़ियां ठीक करना</translation>
<translation id="7549584377607005141">इस वेबपेज को उस डेटा की ज़रूरत है जिसे आपने पहले सही तरह से दिखाने के लिठडाला था. आप इस डेटा को फिर से भेज सकते हैं, लेकिन à¤à¤¸à¤¾ करने से इस पेज पर पहले से हो चà¥à¤•à¥€ कारà¥à¤°à¤µà¤¾à¤ˆ फिर से होगी.</translation>
<translation id="7550637293666041147">आपके डिवाइस का उपयोगकरà¥à¤¤à¤¾ नाम और Chrome उपयोगकरà¥à¤¤à¤¾ नाम</translation>
+<translation id="755279583747225797">टà¥à¤°à¤¾à¤¯à¤² चालू है</translation>
<translation id="7552846755917812628">ये टिपà¥à¤¸ आज़माà¤à¤‚:</translation>
<translation id="7554475479213504905">फिर भी दोबारा लोड करें और दिखाà¤à¤‚</translation>
<translation id="7554791636758816595">नया टैब</translation>
@@ -1739,7 +1791,6 @@
<translation id="7610193165460212391"><ph name="VALUE" /> मान सीमा से बाहर है.</translation>
<translation id="7613889955535752492">समय-सीमा खतà¥à¤®: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome सेटिंग में अपने पासवरà¥à¤¡ देखने और उनà¥à¤¹à¥‡à¤‚ पà¥à¤°à¤¬à¤‚धित करने के लिà¤, पहले Tab और फिर Enter दबाà¤à¤‚</translation>
-<translation id="7615602087246926389">आपके पास पहले से à¤à¤¸à¤¾ डेटा है, जिसे आपके Google खाते के पासवरà¥à¤¡ के किसी अलग वरà¥à¤¶à¤¨ का इसà¥à¤¤à¥‡à¤®à¤¾à¤² करके सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ किया गया है. कृपया उसे नीचे लिखें.</translation>
<translation id="7616645509853975347">आपके à¤à¤¡à¤®à¤¿à¤¨ ने आपके बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤° पर Chrome Enterprise Connectors नाम की सेटिंग को चालू कर दिया है. इस सेटिंग की मदद से आपके कà¥à¤› डेटा को à¤à¤•à¥à¤¸à¥‡à¤¸ किया जा सकता है.</translation>
<translation id="7619838219691048931">à¤à¤‚ड शीट</translation>
<translation id="762844065391966283">à¤à¤• बार में à¤à¤•</translation>
@@ -1804,13 +1855,12 @@
<translation id="782886543891417279">आप जिस वाई-फ़ाई का उपयोग कर रहे हैं (<ph name="WIFI_NAME" />) आपको उसके लॉगिन पेज पर जाने की ज़रूरत पड़ सकती है.</translation>
<translation id="7836231406687464395">पोसà¥à¤Ÿà¤«à¤¼à¤¿à¤•à¥à¤¸ (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{कोई नहीं}=1{à¤à¤• à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ (<ph name="EXAMPLE_APP_1" />)}=2{दो à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">हालांकि, गà¥à¤ªà¥à¤¤ मोड का मतलब यह नहीं है कि आपको कोई भी नहीं देख सकता. गà¥à¤ªà¥à¤¤ मोड में आप जो भी बà¥à¤°à¤¾à¤‰à¤œà¤¿à¤‚ग करते हैं उसे, आपके नियोकà¥à¤¤à¤¾, इंटरनेट सेवा देने वाली कंपनी या आप जिन वेबसाइटों को देखते हैं, वे देख सकतीं हैं.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">अलग-अलग तरह के फ़ाइल टाइप असोसिà¤à¤¶à¤¨ की मदद से फ़ाइलें खोलें.</translation>
<translation id="7862185352068345852">साइट छोड़ें?</translation>
<translation id="7865448901209910068">सबसे अचà¥à¤›à¥€ रफ़à¥à¤¤à¤¾à¤°</translation>
<translation id="7874263914261512992">आपने अभी जिस साइट पर अपना पासवरà¥à¤¡ डाला है वह सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नहीं है. Chrome, <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> और उन साइटों पर तà¥à¤°à¤‚त जाकर, सेव किठगठपासवरà¥à¤¡ की जांच करने का सà¥à¤à¤¾à¤µ देता है जिन पर आपने इस पासवरà¥à¤¡ का इसà¥à¤¤à¥‡à¤®à¤¾à¤² किया है.</translation>
<translation id="7878562273885520351">आपके पासवरà¥à¤¡ से छेड़छाड़ की जा सकती है</translation>
+<translation id="7880146494886811634">पता सेव करें</translation>
<translation id="7882421473871500483">भूरा</translation>
<translation id="7887683347370398519">अपना कारà¥à¤¡ वेरीफ़िकेशन कोड (सीवीसी) जांचे और फिर से कोशिश करें</translation>
<translation id="7887885240995164102">पिकà¥à¤šà¤° में पिकà¥à¤šà¤° चालू करें</translation>
@@ -1818,6 +1868,7 @@
<translation id="7894280532028510793">अगर सà¥à¤ªà¥‡à¤²à¤¿à¤‚ग सही है, तो <ph name="BEGIN_LINK" />Network Diagnostics à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ चलाकर देखें<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">सी3 (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
<translation id="7931318309563332511">अजà¥à¤žà¤¾à¤¤</translation>
+<translation id="793209273132572360">कà¥à¤¯à¤¾ आप पता अपडेट करना चाहते हैं?</translation>
<translation id="7932579305932748336">कोट</translation>
<translation id="79338296614623784">मानà¥à¤¯ फ़ोन नंबर डालें</translation>
<translation id="7934052535022478634">पैसे भेज दिठगà¤</translation>
@@ -1888,13 +1939,14 @@
<translation id="8175796834047840627">आपके साइन इन किठहोने की वजह से Chrome आपको Google खाते में कारà¥à¤¡ सेव करने की सà¥à¤µà¤¿à¤§à¤¾ देता है. आप सेटिंग में जाकर इसे बदल सकते हैं.</translation>
<translation id="8176440868214972690">इस डिवाइस के à¤à¤¡à¤®à¤¿à¤¨ ने नीचे दी गई वेबसाइटों को सेटिंग या नीतियों वगैरह के बारे में कà¥à¤› जानकारी भेजी है.</translation>
<translation id="8184538546369750125">वैशà¥à¤µà¤¿à¤• डिफ़ॉलà¥à¤Ÿ का उपयोग करें (अनà¥à¤®à¤¤à¤¿ दें)</translation>
+<translation id="8193086767630290324">गोपनीय के तौर पर फ़à¥à¤²à¥ˆà¤— किठगठडेटा पर कारà¥à¤°à¤µà¤¾à¤ˆ की गई</translation>
<translation id="8194797478851900357">&amp;ले जाना वापस लाà¤à¤‚</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" आईडी वाले à¤à¤•à¥â€à¤¸à¤Ÿà¥‡à¤‚शन का अमानà¥â€à¤¯ अपडेट URL.</translation>
<translation id="8202097416529803614">ऑरà¥à¤¡à¤° की जानकारी</translation>
<translation id="8202370299023114387">विरोध</translation>
<translation id="8206978196348664717">पीआरसी4 (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
<translation id="8211406090763984747">कनेकà¥à¤¶à¤¨ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ है</translation>
-<translation id="8213464188712611711">मेमोरी</translation>
+<translation id="8213464188712611711">सà¥à¤Ÿà¥‹à¤°à¥‹à¤œ पेज</translation>
<translation id="8218327578424803826">सौंपा गया सà¥â€à¤¥à¤¾à¤¨:</translation>
<translation id="8220146938470311105">सी7/सी6 (à¤à¤¨à¥à¤µà¥‡à¤²à¤ª)</translation>
<translation id="8221250263817408492">आपने अभी-अभी जिस साइट पर अपना पासवरà¥à¤¡ डाला है वह सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नहीं है. कà¥à¤°à¥‹à¤®à¤¿à¤¯à¤®, <ph name="WEBSITE_1" /> और उन साइटों पर जाकर पासवरà¥à¤¡ बदलने का सà¥à¤à¤¾à¤µ देता है जिन पर आपने इसे इसà¥à¤¤à¥‡à¤®à¤¾à¤² किया था.</translation>
@@ -1910,6 +1962,7 @@
<translation id="8249296373107784235">रदà¥à¤¦ करें</translation>
<translation id="8249320324621329438">इससे पहले कब रीफ़à¥à¤°à¥‡à¤¶ हà¥à¤† था:</translation>
<translation id="8253091569723639551">बिलिंग पता आवशà¥à¤¯à¤•</translation>
+<translation id="8257387598443225809">यह à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨, मोबाइल के लिठडिज़ाइन किया गया है</translation>
<translation id="825929999321470778">सेव किठगठसभी पासवरà¥à¤¡ दिखाà¤à¤‚</translation>
<translation id="8261506727792406068">मिटाà¤à¤‚</translation>
<translation id="8262952874573525464">नीचे की ओर à¤à¤œà¤¼Â à¤¸à¥à¤Ÿà¤¿à¤š</translation>
@@ -2034,7 +2087,6 @@
<translation id="8719528812645237045">सबसे ऊपर à¤à¤• से ज़à¥à¤¯à¤¾à¤¦à¤¾ पंच</translation>
<translation id="8725066075913043281">फिर से कोशिश करें</translation>
<translation id="8726549941689275341">पेज का साइज़:</translation>
-<translation id="8728672262656704056">आप गà¥à¤ªà¥à¤¤ मोड में चले गठहैं</translation>
<translation id="8730621377337864115">हो गया</translation>
<translation id="8731544501227493793">'पासवरà¥à¤¡ पà¥à¤°à¤¬à¤‚धित करें' बटन, Chrome की सेटिंग में अपने पासवरà¥à¤¡ देखने और पà¥à¤°à¤¬à¤‚धित करने के लिठEnter दबाà¤à¤‚</translation>
<translation id="8734529307927223492">आपके <ph name="DEVICE_TYPE" /> को <ph name="MANAGER" /> पà¥à¤°à¤¬à¤‚धित करता है</translation>
@@ -2111,6 +2163,7 @@
<translation id="9020542370529661692">इस पेज का <ph name="TARGET_LANGUAGE" /> में अनà¥à¤µà¤¾à¤¦ कर दिया गया है</translation>
<translation id="9020742383383852663">à¤8</translation>
<translation id="9025348182339809926">(मानà¥à¤¯ नहीं है)</translation>
+<translation id="9030265603405983977">मोनोकà¥à¤°à¥‹à¤®</translation>
<translation id="9035022520814077154">सà¥à¤°à¤•à¥à¤·à¤¾ गड़बड़ी</translation>
<translation id="9038649477754266430">ज़à¥à¤¯à¤¾à¤¦à¤¾ तेज़ी से पेज लोड करने के लिठकिसी पूरà¥à¤µà¤¾à¤¨à¥à¤®à¤¾à¤¨ सेवा का उपयोग करें</translation>
<translation id="9039213469156557790">इसके अतिरिकà¥à¤¤, इस पेज में à¤à¤¸à¥‡ अनà¥à¤¯ संसाधन भी शामिल हैं, जो सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नहीं हैं. टà¥à¤°à¤¾à¤‚ज़िट में होने के दौरान ये संसाधन अनà¥à¤¯ लोगों दà¥à¤µà¤¾à¤°à¤¾ देखे जा सकते हैं और पेज का वà¥à¤¯à¤µà¤¹à¤¾à¤° बदलने के लिठकिसी हमवलावर दà¥à¤µà¤¾à¤°à¤¾ इनमें बदलाव किठजा सकते हैं.</translation>
@@ -2134,6 +2187,7 @@
<translation id="91108059142052966">à¤à¤¡à¤®à¤¿à¤¨ नीति के तहत, सà¥à¤•à¥à¤°à¥€à¤¨ पर गोपनीय कॉनà¥à¤Ÿà¥‡à¤‚ट दिखने पर, <ph name="APPLICATION_TITLE" /> के साथ सà¥à¤•à¥à¤°à¥€à¤¨ शेयर करना बंद कर दिया जाता है.</translation>
<translation id="9114524666733003316">कारà¥à¤¡ की पà¥à¤·à¥à¤Ÿà¤¿ की जा रही है...</translation>
<translation id="9114581008513152754">यह बà¥à¤°à¤¾à¤‰à¤œà¤¼à¤° कोई कंपनी या दूसरा संगठन पà¥à¤°à¤¬à¤‚धित नहीं करता. इस डिवाइस की गतिविधि Chrome से बाहर पà¥à¤°à¤¬à¤‚धित की जा सकती है. <ph name="BEGIN_LINK" />ज़à¥à¤¯à¤¾à¤¦à¤¾ जानें<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ताज़ा</translation>
<translation id="9119042192571987207">अपलोड किया गया</translation>
<translation id="9128016270925453879">नीतियां लोड हो गई हैं</translation>
<translation id="9128870381267983090">नेटवरà¥à¤• से कनेकà¥à¤Ÿ करें</translation>
@@ -2152,6 +2206,7 @@
<translation id="9170848237812810038">&amp;पूरà¥à¤µà¤µà¤¤à¥ करें</translation>
<translation id="9171296965991013597">à¤à¤ªà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ बंद करें?</translation>
<translation id="9173282814238175921">à¤à¤• दसà¥à¤¤à¤¾à¤µà¥‡à¤œà¤¼/नई शीट</translation>
+<translation id="9173995187295789444">बà¥à¤²à¥‚टूथ डिवाइस के लिठसà¥à¤•à¥ˆà¤¨ किया जा रहा है...</translation>
<translation id="917450738466192189">सरà¥à¤µà¤° का पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° अमानà¥à¤¯ है.</translation>
<translation id="9174917557437862841">टैब बदलने का बटन, इस टैब पर सà¥à¤µà¤¿à¤š करने के लिठEnter दबाà¤à¤‚</translation>
<translation id="9179703756951298733">Chrome की सेटिंग में, आप पैसे चà¥à¤•à¤¾à¤¨à¥‡ और कà¥à¤°à¥‡à¤¡à¤¿à¤Ÿ कारà¥à¤¡ की जानकारी को पà¥à¤°à¤¬à¤‚धित कर सकते हैं</translation>
diff --git a/chromium/components/strings/components_strings_hr.xtb b/chromium/components/strings/components_strings_hr.xtb
index 01bcf9a2cda..ad544f5044d 100644
--- a/chromium/components/strings/components_strings_hr.xtb
+++ b/chromium/components/strings/components_strings_hr.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Ako je oznaÄeno, Chrome će pohraniti kopiju vaÅ¡e kartice na ureÄ‘aj radi bržeg popunjavanja obrazaca.</translation>
<translation id="1110994991967754504">Odaberite dopuštenje: <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Poništi promjenu rasporeda</translation>
+<translation id="1123753900084781868">Automatski titlovi trenutaÄno nisu dostupni</translation>
<translation id="1125573121925420732">Upozorenja mogu biti uobiÄajena dok web-lokacije ažuriraju sigurnost. To bi se uskoro trebalo poboljÅ¡ati.</translation>
<translation id="112840717907525620">Predmemorija pravila ispravna je</translation>
<translation id="1130564665089811311">Gumb Prevedi stranicu, pritisnite Enter da biste preveli ovu stranicu s Google prevoditeljem</translation>
@@ -64,7 +65,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="1201402288615127009">Dalje</translation>
<translation id="1201895884277373915">Više s ove web-lokacije</translation>
<translation id="1206967143813997005">Potpis inicijalima nije ispravan</translation>
-<translation id="1209206284964581585">Sakrij za sad</translation>
+<translation id="1209206284964581585">Zasad sakrij</translation>
<translation id="121201262018556460">PokuÅ¡ali ste doseći domenu <ph name="DOMAIN" />, ali poslužitelj je predstavio certifikat potpisan slabim kljuÄem. NapadaÄ je možda otkrio privatni kljuÄ, a poslužitelj možda nije oÄekivani poslužitelj (možda ste u komunikaciji s napadaÄem).</translation>
<translation id="1219129156119358924">Sigurnost sustava</translation>
<translation id="1227224963052638717">Nepoznato pravilo.</translation>
@@ -74,6 +75,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="1240347957665416060">Naziv vašeg uređaja</translation>
<translation id="124116460088058876">Više jezika</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Podebljano</translation>
<translation id="1250759482327835220">Da biste sljedeći put platili brže, spremite karticu, ime i adresu za naplatu na svoj Google raÄun.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sinkronizirano)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ako pokušate otvoriti web-lokaciju i ona se ne otvara, najprije pokušajte riješiti poteškoću prema ovim uputama:&lt;/p&gt;
@@ -156,6 +158,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="1476595624592550506">Promijenite zaporku</translation>
<translation id="1484290072879560759">Odaberite adresu za dostavu</translation>
<translation id="1492194039220927094">Push slanje pravila:</translation>
+<translation id="1495677929897281669">Natrag na karticu</translation>
<translation id="1501859676467574491">Prikaži kartice s Google raÄuna</translation>
<translation id="1507202001669085618">&lt;p&gt;Ta će se pogreška prikazati ako upotrebljavate Wi-Fi portal na koji se morate prijaviti da biste se povezali s internetom.&lt;/p&gt;
&lt;p&gt;Da biste ispravili tu pogrešku, kliknite &lt;strong&gt;Poveži se&lt;/strong&gt; na stranici koju pokušavate otvoriti.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="1532118530259321453">Na ovoj se stranici navodi sljedeće</translation>
<translation id="153384715582417236">To je zasad sve</translation>
<translation id="1536390784834419204">Prevedi stranicu</translation>
+<translation id="1539840569003678498">Izvješće je poslano:</translation>
<translation id="154408704832528245">Odaberite adresu za isporuku</translation>
<translation id="1549470594296187301">Za upotrebu te znaÄajke mora biti omogućen JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="1682696192498422849">Najprije kratki rub</translation>
<translation id="168693727862418163">Ova vrijednost pravila nije uspjela potvrditi valjanost sheme i zanemarit će se.</translation>
<translation id="168841957122794586">Certifikat poslužitelja sadrži slab kriptografski kljuÄ!</translation>
+<translation id="1696290444144917273">Pregledajte pojedinosti virtualne kartice</translation>
<translation id="1697532407822776718">Potpuno ste spremni!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Poslužitelj nije mogao dokazati da je to <ph name="DOMAIN" /> jer je sigurnosni certifikat navodno izdan sutra. Razlog može biti pogrešna konfiguracija ili napad na vašu vezu.}one{Poslužitelj nije mogao dokazati da je to <ph name="DOMAIN" /> jer je sigurnosni certifikat navodno izdan # dan u budućnosti. Razlog može biti pogrešna konfiguracija ili napad na vašu vezu.}few{Poslužitelj nije mogao dokazati da je to <ph name="DOMAIN" /> jer je sigurnosni certifikat navodno izdan # dana u budućnosti. Razlog može biti pogrešna konfiguracija ili napad na vašu vezu.}other{Poslužitelj nije mogao dokazati da je to <ph name="DOMAIN" /> jer je sigurnosni certifikat navodno izdan # dana u budućnosti. Razlog može biti pogrešna konfiguracija ili napad na vašu vezu.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Zanemareno jer pravilo <ph name="POLICY_NAME" /> nije postavljeno na <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> želi trajno pohraniti podatke na vaÅ¡e lokalno raÄunalo</translation>
<translation id="1713628304598226412">Ladica 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Izlazni spremnik s odjeljcima 3</translation>
<translation id="1718029547804390981">Dokument je prevelik za dodavanje bilješki</translation>
<translation id="1721424275792716183">* Polje je obavezno</translation>
+<translation id="1727613060316725209">Certifikat je važeći</translation>
<translation id="1727741090716970331">Dodajte važeći broj kartice</translation>
<translation id="1728677426644403582">Gledate izvor web-stranice</translation>
<translation id="173080396488393970">Ova vrsta kartice nije podržana</translation>
@@ -246,7 +253,6 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
vašeg zahtjeva u pregledniku za web-lokaciju <ph name="SITE" />. Operatori web-lokacije mogu koristiti
izvorna pravila radi konfiguracije zaštite i drugih svojstava web-lokacije.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Ažurirajte zaporku za sinkronizaciju.</translation>
<translation id="1787142507584202372">Ovdje se prikazuju vaše otvorene kartice</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, dostupno je više radnji, pritišćite Tab da biste prelazili s jedne na drugu</translation>
@@ -279,6 +285,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="1919345977826869612">Oglasi</translation>
<translation id="1919367280705858090">Pomoć za konkretne poruke pogreške</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Nijedna}=1{1 web-lokacija}one{# web-lokacija}few{# web-lokacije}other{# web-lokacija}}</translation>
+<translation id="1924727005275031552">Novo</translation>
<translation id="1945968466830820669">Mogli biste izgubiti pristup raÄunu svoje organizacije ili bi netko mogao ukrasti vaÅ¡ identitet. Chromium preporuÄuje da odmah promijenite zaporku.</translation>
<translation id="1947454675006758438">Spajanje pri vrhu desno</translation>
<translation id="1958218078413065209">Vaš najbolji rezultat je <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="2042213636306070719">Ladica 7</translation>
<translation id="204357726431741734">Prijavite se kako biste upotrebljavali zaporke spremljene na Google raÄunu</translation>
<translation id="2053111141626950936">Neće se prevoditi <ph name="LANGUAGE" />.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Kada je ta kontrola ukljuÄena i status je aktivan, Chrome odreÄ‘uje kojoj je velikoj grupi ljudi, odnosno skupini, vaÅ¡a nedavna aktivnost pregledavanja najsliÄnija. OglaÅ¡ivaÄi mogu odabrati oglase za tu grupu, a vaÅ¡a aktivnost pregledavanja ostaje privatna na vaÅ¡em ureÄ‘aju. VaÅ¡a se grupa ažurira svaki dan.}=1{Kada je ta kontrola ukljuÄena i status je aktivan, Chrome odreÄ‘uje kojoj je velikoj grupi ljudi, odnosno skupini, vaÅ¡a nedavna aktivnost pregledavanja najsliÄnija. OglaÅ¡ivaÄi mogu odabrati oglase za tu grupu, a vaÅ¡a aktivnost pregledavanja ostaje privatna na vaÅ¡em ureÄ‘aju. VaÅ¡a se grupa ažurira svaki dan.}one{Kada je ta kontrola ukljuÄena i status je aktivan, Chrome odreÄ‘uje kojoj je velikoj grupi ljudi, odnosno skupini, vaÅ¡a nedavna aktivnost pregledavanja najsliÄnija. OglaÅ¡ivaÄi mogu odabrati oglase za tu grupu, a vaÅ¡a aktivnost pregledavanja ostaje privatna na vaÅ¡em ureÄ‘aju. VaÅ¡a se grupa ažurira svaki {NUM_DAYS} dan.}few{Kada je ta kontrola ukljuÄena i status je aktivan, Chrome odreÄ‘uje kojoj je velikoj grupi ljudi, odnosno skupini, vaÅ¡a nedavna aktivnost pregledavanja najsliÄnija. OglaÅ¡ivaÄi mogu odabrati oglase za tu grupu, a vaÅ¡a aktivnost pregledavanja ostaje privatna na vaÅ¡em ureÄ‘aju. VaÅ¡a se grupa ažurira svaka {NUM_DAYS} dana.}other{Kada je ta kontrola ukljuÄena i status je aktivan, Chrome odreÄ‘uje kojoj je velikoj grupi ljudi, odnosno skupini, vaÅ¡a nedavna aktivnost pregledavanja najsliÄnija. OglaÅ¡ivaÄi mogu odabrati oglase za tu grupu, a vaÅ¡a aktivnost pregledavanja ostaje privatna na vaÅ¡em ureÄ‘aju. VaÅ¡a se grupa ažurira svakih {NUM_DAYS} dana.}}</translation>
<translation id="2053553514270667976">ZIP kôd</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 prijedlog}one{# prijedlog}few{# prijedloga}other{# prijedloga}}</translation>
<translation id="2071692954027939183">Obavijesti su automatski blokirane jer ih obiÄno ne dopuÅ¡tate</translation>
<translation id="2079545284768500474">Poništi</translation>
<translation id="20817612488360358">Postavljena je upotreba sistemskih postavki proxy poslužitelja, ali takoÄ‘er je odreÄ‘ena izriÄita konfiguracija proxy poslužitelja.</translation>
<translation id="2082238445998314030"><ph name="RESULT_NUMBER" /> od <ph name="TOTAL_RESULTS" /> rezultata</translation>
+<translation id="2085876078937250610">Spremite…</translation>
<translation id="2088086323192747268">Gumb za upravljanje sinkronizacijom, pritisnite Enter da biste u postavkama Chromea upravljali time koji će se podaci sinkronizirati</translation>
<translation id="2091887806945687916">Zvuk</translation>
<translation id="2094505752054353250">Domena se ne podudara</translation>
@@ -379,6 +388,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="2317259163369394535"><ph name="DOMAIN" /> zahtijeva korisniÄko ime i zaporku.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, istjeÄe <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Postavkom upravlja administrator</translation>
+<translation id="2340263603246777781">Web-lokacija <ph name="ORIGIN" /> želi se upariti</translation>
<translation id="2344028582131185878">Automatska preuzimanja</translation>
<translation id="2346319942568447007">Slika koju ste kopirali</translation>
<translation id="2354001756790975382">Druge oznake</translation>
@@ -386,8 +396,10 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="2355395290879513365">NapadaÄi možda mogu vidjeti slike koje gledate na ovoj web-lokaciji i izmijeniti ih kako bi vas prevarili.</translation>
<translation id="2356070529366658676">Upitaj</translation>
<translation id="2357481397660644965">VaÅ¡im ureÄ‘ajem upravlja <ph name="DEVICE_MANAGER" />, a vaÅ¡im raÄunom upravlja <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Za manje od jednog dana}=1{Za jedan dan}one{Za {NUM_DAYS} dan}few{Za {NUM_DAYS} dana}other{Za {NUM_DAYS} dana}}</translation>
<translation id="2359629602545592467">Veći broj</translation>
<translation id="2359808026110333948">Nastavi</translation>
+<translation id="2359961752320758691">Primijenjen je broj virtualne kartice.</translation>
<translation id="2367567093518048410">Razina</translation>
<translation id="2372464001869762664">Nakon Å¡to ih potvrdite, podaci o kartici s Google raÄuna podijelit će se s ovom web-lokacijom. CVC možete pronaći u podacima o Plex raÄunu.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="239429038616798445">Taj naÄin dostave nije dostupan. PokuÅ¡ajte s drugim naÄinom.</translation>
<translation id="2396249848217231973">&amp;Poništi brisanje</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Stara</translation>
<translation id="2413528052993050574">Poslužitelj nije mogao dokazati da je <ph name="DOMAIN" />; njegov sigurnosni certifikat možda je opozvan. To može biti uzrokovano pogrešnom konfiguracijom ili napadom na vašu vezu.</translation>
<translation id="2414886740292270097">Tamno</translation>
<translation id="2438874542388153331">Četverostruko bušenje s desne strane</translation>
@@ -425,10 +438,10 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="2521385132275182522">Spajanje pri dnu desno</translation>
<translation id="2523886232349826891">Sprema se samo na ovom uređaju</translation>
<translation id="2524461107774643265">Dodajte još podataka</translation>
-<translation id="2526590354069164005">Radna površina</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{i još jedan sudionik}one{i još #}few{i još #}other{i još #}}</translation>
<translation id="2536110899380797252">Dodaj adresu</translation>
<translation id="2539524384386349900">Otkrij</translation>
+<translation id="2541219929084442027">Stranice koje pregledavate na anonimnim karticama ne zadržavaju se u povijesti preglednika, pohrani kolaÄića ni povijesti pretraživanja nakon Å¡to zatvorite sve anonimne kartice, ali će se zadržati sve datoteke koje preuzmete ili oznake koje izradite.</translation>
<translation id="2544644783021658368">Jedan dokument</translation>
<translation id="254947805923345898">Vrijednost pravila nije važeća.</translation>
<translation id="255002559098805027">Host <ph name="HOST_NAME" /> poslao je nevažeći odgovor.</translation>
@@ -448,6 +461,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="2629325967560697240">Da biste dobili najviÅ¡u Chromeovu razinu sigurnosti, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ukljuÄite poboljÅ¡anu zaÅ¡titu<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">IP adresa poslužitelja hosta <ph name="HOST_NAME" /> nije pronađena.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Nije pronađen nijedan kompatibilan uređaj.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, a zatim Enter da biste izbrisali povijest pregledavanja, kolaÄiće, predmemoriju i joÅ¡ mnogo toga u postavkama Chromea</translation>
<translation id="2650446666397867134">Pristup datoteci nije dopušten</translation>
@@ -494,6 +508,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<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="2807052079800581569">Y-položaj slike</translation>
+<translation id="2820957248982571256">Traženje...</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>
@@ -501,6 +516,8 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="2850739647070081192">Invite (omotnica)</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="2859806420264540918">Ova web-lokacija prikazuje ometajuće ili obmanjujuće oglase.</translation>
+<translation id="287596039013813457">Prijateljski</translation>
+<translation id="2876489322757410363">NapuÅ¡tate anonimni naÄin rada da biste platili putem vanjske aplikacije. Želite li nastaviti?</translation>
<translation id="2878197950673342043">Presavijanje u obliku postera</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Postavljanje prozora</translation>
@@ -550,7 +567,6 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="3060227939791841287">C9 (omotnica)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, a zatim Enter da biste pokrenuli sigurnosnu provjeru u postavkama Chromea</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>
<translation id="306573536155379004">Igra je pokrenuta.</translation>
<translation id="3080254622891793721">Grafika</translation>
<translation id="3086579638707268289">Vaša se aktivnost na webu nadzire</translation>
@@ -573,7 +589,6 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="315504272643575312">VaÅ¡im raÄunom upravlja <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Vrati</translation>
<translation id="3162559335345991374">Za Wi-Fi koji upotrebljavate možda ćete morati posjetiti stranicu za prijavu.</translation>
-<translation id="3167968892399408617">Stranice koje pregledavate na anonimnim karticama ne zadržavaju se u povijesti preglednika, pohrani kolaÄića ili povijesti pretraživanja nakon Å¡to zatvorite sve anonimne kartice, ali će se zadržati sve datoteke koje preuzmete ili oznake koje napravite.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Otok</translation>
<translation id="3176929007561373547">Provjerite postavke proxyja ili se obratite mrežnom administratoru da
@@ -599,10 +614,12 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<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="3249845759089040423">Živopisno</translation>
<translation id="3252266817569339921">Francuski</translation>
<translation id="3266793032086590337">Vrijednost (sukob)</translation>
<translation id="3268451620468152448">Otvorene kartice</translation>
<translation id="3270847123878663523">&amp;Poništi promjenu rasporeda</translation>
+<translation id="3271648667212143903">Web-lokacija <ph name="ORIGIN" /> želi se povezati</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Vaša organizacija, <ph name="ENROLLMENT_DOMAIN" />, poslala je neke podatke, poput postavki ili pravila, sljedećim web-lokacijama.</translation>
<translation id="3282497668470633863">Dodajte ime na kartici</translation>
@@ -655,6 +672,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="3428151540071562330">Jedan ili viÅ¡e URI-ja predloÅ¡ka poslužitelja DnsOverHttpsTemplates nije toÄan i neće se koristiti.</translation>
<translation id="3431636764301398940">Spremi tu karticu na ovaj uređaj</translation>
<translation id="3432601291244612633">Zatvori stranicu</translation>
+<translation id="3435738964857648380">Sigurnost</translation>
<translation id="3435896845095436175">Omogući</translation>
<translation id="3438829137925142401">Upotrebljavajte zaporke spremljene na Google raÄunu</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="3584299510153766161">Dvostruko bušenje pri dnu</translation>
<translation id="3586931643579894722">Sakrij detalje</translation>
<translation id="3587738293690942763">Srednji</translation>
+<translation id="3590643883886679995">Podaci za prijavu pohranit će se na ovom ureÄ‘aju nakon Å¡to izaÄ‘ete iz anonimnog naÄina.</translation>
+<translation id="359126217934908072">Mjesec/godina:</translation>
<translation id="3592413004129370115">Italian (omotnica)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Grupu uvijek možete poništiti. Za pridruživanje novoj grupi potreban je otprilike jedan dan.}=1{Grupu uvijek možete poništiti. Za pridruživanje novoj grupi potreban je otprilike jedan dan.}one{Grupu uvijek možete poništiti. Za pridruživanje novoj grupi potreban je {NUM_DAYS} dan.}few{Grupu uvijek možete poništiti. Za pridruživanje novoj grupi potrebna su {NUM_DAYS} dana.}other{Grupu uvijek možete poništiti. Za pridruživanje novoj grupi potrebno je {NUM_DAYS} dana.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Administrator je blokirao aplikaciju</translation>
<translation id="3608932978122581043">Usmjerenje umetanja</translation>
@@ -706,12 +727,12 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="3615877443314183785">Unesite važeći datum isteka</translation>
<translation id="36224234498066874">Obriši podatke o pregledavanju...</translation>
<translation id="362276910939193118">Pokaži cijelu povijest</translation>
-<translation id="3625635938337243871">Podaci za prijavu pohranit će se na ovom ureÄ‘aju nakon Å¡to izaÄ‘ete iz anonimnog naÄina.</translation>
<translation id="3630155396527302611">Ako je već navedena kao program koji smije pristupiti mreži, pokušajte je ukloniti s popisa pa je ponovo dodati.</translation>
<translation id="3630699740441428070">Administratori ureÄ‘aja konfigurirali su vaÅ¡u mrežnu vezu, Å¡to im može omogućiti prikaz vaÅ¡eg mrežnog prometa, ukljuÄujući web-lokacije koje posjećujete.</translation>
<translation id="3631244953324577188">Biometrijski podaci</translation>
<translation id="3633738897356909127">Gumb Ažuriranje Chromea, pritisnite Enter da biste ažurirali Chrome u postavkama Chromea</translation>
<translation id="3634530185120165534">Ladica 5</translation>
+<translation id="3637662659967048211">Spremanje na Google raÄun</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplikacija:</translation>
<translation id="3650584904733503804">Valjanost je uspješna</translation>
@@ -752,6 +773,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="3781428340399460090">Jarko ružiÄasta</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth uređaji</translation>
+<translation id="3787675388804467730">Broj virtualne kartice</translation>
<translation id="3787705759683870569">IstjeÄe <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">VeliÄina 16</translation>
<translation id="3789841737615482174">Instaliraj</translation>
@@ -771,6 +793,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="3841184659773414994">Rukovanje datotekama</translation>
<translation id="385051799172605136">Natrag</translation>
<translation id="3858027520442213535">Ažuriraj datum i vrijeme</translation>
+<translation id="3881478300875776315">Prikaži manje redaka</translation>
<translation id="3884278016824448484">Identifikator uređaja sukobljen je</translation>
<translation id="3885155851504623709">Župa</translation>
<translation id="388632593194507180">Otkriveno je praćenje</translation>
@@ -796,6 +819,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="397105322502079400">IzraÄun u tijeku…</translation>
<translation id="3973234410852337861">Host <ph name="HOST_NAME" /> je blokiran</translation>
<translation id="3973357910713125165">Gumb Pokreni Chromeovu sigurnosnu provjeru, pritisnite Enter da biste pokrenuli sigurnosnu provjeru u postavkama Chromea</translation>
+<translation id="3986705137476756801">Za sad iskljuÄi automatske titlove</translation>
<translation id="3987405730340719549">Chrome je utvrdio da je ta web-lokacija možda lažna ili joj je cilj prijevara.
Ako smatrate da se ova poruka prikazuje pogreškom, posjetite stranicu https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="4275830172053184480">Ponovo pokrenite svoj uređaj</translation>
<translation id="4277028893293644418">Poništi zaporku</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="4287885627794386150">Ispunjava kriterije za probu, ali proba nije aktivna</translation>
<translation id="4297502707443874121">Minijatura za stranicu <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Proširi</translation>
<translation id="4300675098767811073">Višestruko bušenje s desne strane</translation>
<translation id="4302514097724775343">Dodirnite dinosaura da biste poÄeli igrati</translation>
<translation id="4302965934281694568">Chou3 (omotnica)</translation>
<translation id="4305666528087210886">Pristup datoteci nije uspio</translation>
-<translation id="4305817255990598646">Prebaci</translation>
+<translation id="4306529830550717874">Želite li spremiti adresu?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokiraj (zadano)</translation>
<translation id="4314815835985389558">Upravljanje sinkronizacijom</translation>
@@ -926,6 +951,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="4377125064752653719">PokuÅ¡ali ste doseći domenu <ph name="DOMAIN" />, ali certifikat koji je poslužitelj predstavio povuÄen je od strane izdavaÄa. Prema tome nikako ne biste trebali vjerovati sigurnosnim certifikatima koje predstavlja poslužitelj. Možda komunicirate s napadaÄem.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Rub</translation>
+<translation id="4406883609789734330">Automatski titlovi</translation>
<translation id="4406896451731180161">rezultati pretraživanja</translation>
<translation id="4408413947728134509">KolaÄića: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Upravo ste unijeli zaporku na obmanjujućoj web-lokaciji. Chrome preporuÄuje da otvorite <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> i druge web-lokacije na kojima koristite tu zaporku i odmah je promijenite.</translation>
@@ -938,7 +964,6 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<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="4464826014807964867">Web-lokacije s podacima iz vaše organizacije</translation>
-<translation id="4466881336512663640">Izgubit će se promjene koje ste unijeli u obrazac. Jeste li sigurni da želite nastaviti?</translation>
<translation id="4476953670630786061">Ovaj obrazac nije siguran. Automatsko popunjavanje je iskljuÄeno.</translation>
<translation id="4477350412780666475">Sljedeća pjesma</translation>
<translation id="4482953324121162758">Ova web-lokacija neće biti prevedena.</translation>
@@ -956,7 +981,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="4515275063822566619">Kartice i adrese dolaze iz Cromea i vaÅ¡eg Google raÄuna (<ph name="ACCOUNT_EMAIL" />). Njima možete upravljati u <ph name="BEGIN_LINK" />Postavkama<ph name="END_LINK" />.</translation>
<translation id="4517607026994743406">Comm-10 (omotnica)</translation>
<translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> mm (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">Detalji</translation>
+<translation id="4522570452068850558">Pojedinosti</translation>
<translation id="4524138615196389145">Odsad brže potvrdite kartice upotrebom znaÄajke WebAuthn</translation>
<translation id="4524805452350978254">Upravljanje karticama</translation>
<translation id="4542971377163063093">Ladica 6</translation>
@@ -972,6 +997,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="4594403342090139922">&amp;Poništi brisanje</translation>
<translation id="4597348597567598915">VeliÄina 8</translation>
<translation id="4600854749408232102">C6/C5 (omotnica)</translation>
+<translation id="4606870351894164739">Dojmljivo</translation>
<translation id="4628948037717959914">Fotografija</translation>
<translation id="4631649115723685955">Povezano s gotovinskim povratom</translation>
<translation id="4636930964841734540">Informacije</translation>
@@ -991,6 +1017,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="4691835149146451662">Architecture-A (omotnica)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">BoÄni</translation>
+<translation id="4702656508969495934">Vidljivi su automatski titlovi, upotrijebite izmjenjivaÄ prozora za fokusiranje</translation>
<translation id="4708268264240856090">Veza je prekinuta</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />pokrenuti Mrežnu dijagnostiku sustava Windows<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="4738601419177586157">Prijedlog za pretraživanje <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Upravljaj zaporkama…</translation>
<translation id="4744603770635761495">Izvršna putanja</translation>
+<translation id="4749011317274908093">Sad ste u anonimnom naÄinu</translation>
<translation id="4750917950439032686">Vaši podaci (na primjer, zaporke i brojevi kreditnih kartica) privatni su kada se šalju na tu web-lokaciju.</translation>
<translation id="4756388243121344051">&amp;Povijest</translation>
<translation id="4758311279753947758">Dodaj pod. za kontakt</translation>
@@ -1033,6 +1061,8 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="4813512666221746211">Pogreška mreže</translation>
<translation id="4816492930507672669">Prilagodi stranici</translation>
<translation id="4819347708020428563">Želite li urediti napomene u zadanom prikazu?</translation>
+<translation id="4825507807291741242">Snažno</translation>
+<translation id="4838327282952368871">Sanjivo</translation>
<translation id="484462545196658690">Automatski</translation>
<translation id="4850886885716139402">Prikaz</translation>
<translation id="485316830061041779">NjemaÄki</translation>
@@ -1169,6 +1199,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="5314967030527622926">Alat za izradu knjižica</translation>
<translation id="5316812925700871227">Zakretanje u suprotnom smjeru od kazaljke na satu</translation>
<translation id="5317780077021120954">Spremi</translation>
+<translation id="5321288445143113935">Povećano do maksimuma</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> od <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Odaberite podatke za kontakt</translation>
<translation id="5327248766486351172">Naziv</translation>
@@ -1176,11 +1207,13 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="5332219387342487447">NaÄin otpreme</translation>
<translation id="5333022057423422993">Chrome je saznao da je zaporka koju ste upravo upotrijebili otkrivena u povredi podataka. Da biste zaÅ¡titili svoje raÄune, preporuÄujemo da provjerite spremljene zaporke.</translation>
<translation id="5334013548165032829">Detaljni zapisnici sustava</translation>
+<translation id="5334145288572353250">Želite li spremiti adresu?</translation>
<translation id="5340250774223869109">Aplikacija je blokirana</translation>
<translation id="534295439873310000">NFC uređaji</translation>
<translation id="5344579389779391559">Ta će vam stranica možda pokušati nešto naplatiti</translation>
<translation id="5355557959165512791">TrenutaÄno ne možete otvoriti web-lokaciju <ph name="SITE" /> jer je njezin certifikat opozvan. Mrežne pogreÅ¡ke i napadi uglavnom su privremeni i ta bi stranica kasnije trebala funkcionirati.</translation>
<translation id="536296301121032821">Pohrana postavki pravila nije uspjela</translation>
+<translation id="5363309033720083897">Serijski prikljuÄak koji dopuÅ¡ta vaÅ¡ administrator</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="5386426401304769735">Lanac certifikata za ovu web-lokaciju sadrži certifikat s SHA-1 potpisom.</translation>
@@ -1189,6 +1222,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="5398772614898833570">Oglasi su blokirani</translation>
<translation id="5400836586163650660">Siva</translation>
<translation id="540969355065856584">Poslužitelj nije uspio dokazati da je <ph name="DOMAIN" />; njegov sigurnosni certifikat trenutaÄno nije važeći. Uzrok tomu može biti pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vaÅ¡u vezu.</translation>
+<translation id="541143247543991491">Oblak (na razini sustava)</translation>
<translation id="541416427766103491">Spremnik za slaganje u snopove 4</translation>
<translation id="5421136146218899937">Izbriši podatke o pregledavanju...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> želi vam slati obavijesti</translation>
@@ -1202,6 +1236,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="5455374756549232013">Vremenska oznaka pravila koje nije valjano</translation>
<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="5463625433003343978">Traženje uređaja...</translation>
<translation id="5469868506864199649">Talijanski</translation>
<translation id="5470861586879999274">&amp;Ponovi uređivanje</translation>
<translation id="5478437291406423475">B6/C4 (omotnica)</translation>
@@ -1251,7 +1286,6 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="5624120631404540903">Upravljanje zaporkama</translation>
<translation id="5629630648637658800">UÄitavanje postavki pravila nije uspjelo</translation>
<translation id="5631439013527180824">Token za upravljanje uređajem nije važeći</translation>
-<translation id="5632627355679805402">Vaši su podaci kriptirani vašom <ph name="BEGIN_LINK" />Google zaporkom<ph name="END_LINK" /> od <ph name="TIME" />. Unesite je da biste pokrenuli sinkronizaciju.</translation>
<translation id="5633066919399395251">NapadaÄi koji su trenutaÄno na web-lokaciji <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogu pokuÅ¡ati instalirati opasne programe na vaÅ¡e raÄunalo radi kraÄ‘e ili brisanja vaÅ¡ih podataka (na primjer fotografija, zaporki, poruka i brojeva kreditnih kartica). <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte viÅ¡e<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Blokiran je obmanjujući sadržaj.</translation>
<translation id="5644090287519800334">X-pomak 1. strane slike</translation>
@@ -1290,12 +1324,12 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="5785756445106461925">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 izgled stranice.</translation>
<translation id="5786044859038896871">Želite li ispuniti podatke o kartici?</translation>
<translation id="578633867165174378">Chrome je saznao da je zaporka koju ste upravo upotrijebili otkrivena u povredi podataka. PreporuÄujemo da odmah promijenite tu zaporku.</translation>
-<translation id="5798290721819630480">Želite li odbaciti izmjene?</translation>
<translation id="5803412860119678065">Želite li ispuniti podatke o kartici <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Dozvoljeno</translation>
<translation id="5804427196348435412">koristiti NFC uređaje</translation>
<translation id="5810442152076338065">Vaša veza s domenom <ph name="DOMAIN" /> kriptirana je zastarjelim kriptografskim paketom.</translation>
<translation id="5813119285467412249">&amp;Ponovi dodavanje</translation>
+<translation id="5817918615728894473">Upari</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Kad platite, ova će se kartica teretiti, no njezin se stvarni broj neće dijeliti s ovom web-lokacijom. Radi dodatne sigurnosti generirat će se privremeni CVC.}one{Kad platite, teretit će se kartica koju odaberete, no njezin se stvarni broj neće dijeliti s ovom web-lokacijom. Radi dodatne sigurnosti generirat će se privremeni CVC.}few{Kad platite, teretit će se kartica koju odaberete, no njezin se stvarni broj neće dijeliti s ovom web-lokacijom. Radi dodatne sigurnosti generirat će se privremeni CVC.}other{Kad platite, teretit će se kartica koju odaberete, no njezin se stvarni broj neće dijeliti s ovom web-lokacijom. Radi dodatne sigurnosti generirat će se privremeni CVC.}}</translation>
<translation id="5826507051599432481">UobiÄajeni naziv (CN)</translation>
<translation id="5838278095973806738">Na ovu web-lokaciju nemojte unositi osjetljive podatke (na primjer, zaporke ili kreditne kartice) jer su je možda ukrali napadaÄi.</translation>
@@ -1303,6 +1337,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="5855253129151731373">Naziv hosta te web-lokacije sliÄan je nazivu <ph name="LOOKALIKE_DOMAIN" />. NapadaÄi ponekad oponaÅ¡aju web-lokacije unoÅ¡enjem malih, teÅ¡ko uoÄljivih promjena u naziv domene.
Ako smatrate da se ova poruka prikazuje pogreškom, posjetite stranicu https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">IskljuÄeno</translation>
<translation id="5862579898803147654">Spremnik za slaganje u snopove 8</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>
@@ -1319,6 +1354,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="5913377024445952699">Snimanje zaslona je pauzirano</translation>
<translation id="59174027418879706">Omogućeno</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 u upotrebi}one{# u upotrebi}few{# u upotrebi}other{# u upotrebi}}</translation>
<translation id="5921185718311485855">UkljuÄeno</translation>
<translation id="5921639886840618607">Želite li spremiti karticu na Google raÄun?</translation>
<translation id="5922853866070715753">Skoro gotovo</translation>
@@ -1338,6 +1374,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="5989320800837274978">Nisu određeni fiksni proxy poslužitelji ni URL .pac skripte.</translation>
<translation id="5992691462791905444">Presavijanje u obliku harmonike s dva nabora</translation>
<translation id="6000758707621254961">Rezultata za upit "<ph name="SEARCH_TEXT" />" ima <ph name="RESULT_COUNT" /></translation>
+<translation id="6006484371116297560">KlasiÄna</translation>
<translation id="6008122969617370890">Redoslijed N do 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Provjerite zaporke</translation>
@@ -1359,6 +1396,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="6045164183059402045">Predložak rasporeda stranice</translation>
<translation id="6047233362582046994">Ako ste svjesni sigurnosnih rizika, možete <ph name="BEGIN_LINK" />posjetiti ovu web-lokaciju<ph name="END_LINK" /> prije uklanjanja štetnih aplikacija.</translation>
<translation id="6047927260846328439">Ovaj vas sadržaj može na prijevaru pokušati navesti da instalirate softver ili odate svoje osobne podatke. <ph name="BEGIN_LINK" />Ipak prikaži<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Pritisnite i zadržite |<ph name="ACCELERATOR" />| da biste napustili prikaz na cijelom zaslonu</translation>
<translation id="6049488691372270142">Isporuka stranica</translation>
<translation id="6051221802930200923">TrenutaÄno ne možete otvoriti <ph name="SITE" /> jer web-lokacija upotrebljava prikvaÄivanje certifikata. Mrežne pogreÅ¡ke i napadi obiÄno su privremeni, tako da će stranica kasnije vjerojatno funkcionirati.</translation>
<translation id="6051898664905071243">Broj stranica:</translation>
@@ -1375,6 +1413,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<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>
<translation id="6116338172782435947">vidjeti tekst i slike koje kopirate u međuspremnik</translation>
<translation id="6120179357481664955">Upamtiti vaš UPI ID?</translation>
+<translation id="6123290840358279103">Prikaži virtualnu karticu</translation>
<translation id="6124432979022149706">PrikljuÄci za Chrome za poduzeća</translation>
<translation id="6146055958333702838">Provjerite kabele i ponovo pokrenite usmjerivaÄe, modeme ili druge mrežne
uređaje koje možda upotrebljavate.</translation>
@@ -1411,6 +1450,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="6289939620939689042">Boja stranice</translation>
<translation id="6290238015253830360">Ovdje će se prikazivati predloženi Älanci</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Zaustavljanje Google asistenta u Chromeu</translation>
<translation id="6305205051461490394">Web-lokacija <ph name="URL" /> nije dostupna.</translation>
<translation id="6312113039770857350">Web-stranica nije dostupna</translation>
@@ -1436,6 +1476,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="6390200185239044127">Cik-cak presavijanje napola</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Lijepljenje s <ph name="ORIGIN_NAME" /> na ovu lokaciju blokirano je pravilima administratora</translation>
+<translation id="6398765197997659313">Izađi iz cijelog zaslona</translation>
<translation id="6401136357288658127">Pravilo je ukinuto. Trebali biste koristiti pravilo <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Uredi oznaku</translation>
<translation id="6406765186087300643">C0 (omotnica)</translation>
@@ -1448,7 +1489,6 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="6428450836711225518">Potvrdite svoj telefonski broj</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="6440503408713884761">Zanemareno</translation>
<translation id="6443406338865242315">koja ste proširenja i dodatke instalirali</translation>
<translation id="6446163441502663861">Kahu (omotnica)</translation>
@@ -1491,6 +1531,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="6624427990725312378">Podaci za kontakt</translation>
<translation id="6626291197371920147">Dodajte važeći broj kartice</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Pretraživanje</translation>
+<translation id="6630043285902923878">Traženje USB uređaja...</translation>
<translation id="6630809736994426279">NapadaÄi koji su trenutaÄno na web-lokaciji <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogu pokuÅ¡ati instalirati opasne programe na vaÅ¡ Mac radi kraÄ‘e ili brisanja vaÅ¡ih podataka (na primjer fotografija, zaporki, poruka i brojeva kreditnih kartica). <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte viÅ¡e<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Izbriši</translation>
@@ -1506,6 +1547,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="6671697161687535275">Želite li ukloniti prijedlog iz Chromiuma?</translation>
<translation id="6685834062052613830">Odjavite se i dovršite postavljanje</translation>
<translation id="6687335167692595844">Zatražena je veliÄina fonta</translation>
+<translation id="6688743156324860098">Ažurirajte…</translation>
<translation id="6689249931105087298">Relativno s kompresijom crne toÄke</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="6698381487523150993">Autor/ica:</translation>
@@ -1521,6 +1563,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="6744009308914054259">Dok Äekate vezu, možete otvoriti Preuzimanja i Äitati offline Älanke.</translation>
<translation id="6753269504797312559">Vrijednost pravila</translation>
<translation id="6757797048963528358">Uređaj je u stanju mirovanja.</translation>
+<translation id="6767985426384634228">Želite li ažurirati adresu?</translation>
<translation id="6768213884286397650">Hagaki (dopisnica)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">LjubiÄasta</translation>
@@ -1543,6 +1586,7 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome je pojednostavio ovu stranicu radi lakÅ¡eg Äitanja. Chrome je dohvatio izvornu stranicu sigurnom vezom.</translation>
<translation id="6891596781022320156">Razina pravila nije podržana.</translation>
+<translation id="6895143722905299846">Virtualni broj:</translation>
<translation id="6895330447102777224">Kartica je potvrđena</translation>
<translation id="6897140037006041989">KorisniÄki agent</translation>
<translation id="6898699227549475383">Organizacija (O)</translation>
@@ -1578,10 +1622,10 @@ To će u suprotnom biti onemogućeno na temelju vaših postavki privatnosti. To
<translation id="7004583254764674281">Za brže potvrÄ‘ivanje kartica upotrijebite znaÄajku Windows Hello</translation>
<translation id="7006930604109697472">Svejedno pošalji</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Postavke promjene veliÄine</translation>
<translation id="7014741021609395734">Razina zumiranja</translation>
<translation id="7016992613359344582">Ta terećenja mogu biti jednokratna ili ponavljajuća i možda nisu odmah vidljiva.</translation>
<translation id="7029809446516969842">Zaporke</translation>
+<translation id="7030436163253143341">Certifikat nije važeći</translation>
<translation id="7031646650991750659">koje ste Google Play aplikacije instalirali</translation>
<translation id="7050187094878475250">Pokušali ste pristupiti domeni <ph name="DOMAIN" />, ali je poslužitelj pružio certifikat koji nije pouzdan zbog predugog razdoblja valjanosti.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Ta se kartica trenutaÄno ne može spremiti}one{Te se kartice trenutaÄno ne mogu spremiti}few{Te se kartice trenutaÄno ne mogu spremiti}other{Te se kartice trenutaÄno ne mogu spremiti}}</translation>
@@ -1651,12 +1695,14 @@ Dodatne pojedinosti:
<translation id="7300012071106347854">Kobaltno plava</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Visoka</translation>
+<translation id="7305756307268530424">Pokreni sporije</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Pomoć za povezivanje</translation>
<translation id="7323804146520582233">Sakrijte odjeljak "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">NadjaÄavanje lokalnog raÄuna na ureÄ‘aju</translation>
<translation id="7333654844024768166">Upravo ste unijeli zaporku na obmanjujućoj web-lokaciji. Chromium preporuÄuje da otvorite <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> i druge web-lokacije na kojima koristite tu zaporku i odmah je promijenite.</translation>
<translation id="7334320624316649418">&amp;Ponovi promjenu rasporeda</translation>
+<translation id="7337248890521463931">Prikaži više redaka</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>
@@ -1664,6 +1710,7 @@ Dodatne pojedinosti:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Naredbeni redak</translation>
<translation id="7359588939039777303">Oglasi su blokirani.</translation>
+<translation id="7363096869660964304">No, niste nevidljivi. Anonimni naÄin ne sakriva vaÅ¡e pregledavanje od poslodavca, davatelja internetskih usluga ni od posjećenih web-lokacija.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, a zatim Enter da biste u postavkama Chromea dodali adrese i upravljali njima</translation>
<translation id="7365849542400970216">Može li web-lokacija znati kad upotrebljavate uređaj?</translation>
<translation id="7372973238305370288">rezultat pretraživanja</translation>
@@ -1674,7 +1721,9 @@ Dodatne pojedinosti:
<translation id="7378594059915113390">Medijske kontrole</translation>
<translation id="7378627244592794276">Ne</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Nije primjenjivo</translation>
<translation id="7390545607259442187">Potvrda kartice</translation>
+<translation id="7392089738299859607">Ažurirajte adresu</translation>
<translation id="7399802613464275309">Sigurnosna provjera</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Uređaj <ph name="DEVICE_NAME" /> upravljani je uređaj</translation>
@@ -1689,6 +1738,7 @@ Dodatne pojedinosti:
&lt;li&gt;U &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;centru za pomoć za Chrome&lt;/a&gt; možete saznati kako trajno ukloniti softver s raÄunala
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Lijepo</translation>
<translation id="7416351320495623771">Upravljaj zaporkama…</translation>
<translation id="7419106976560586862">Putanja profila</translation>
<translation id="7437289804838430631">Dodajte podatke za kontakt</translation>
@@ -1704,7 +1754,7 @@ Dodatne pojedinosti:
<translation id="7481312909269577407">Naprijed</translation>
<translation id="7485870689360869515">Nema pronađenih podataka.</translation>
<translation id="7495528107193238112">Ovaj je sadržaj blokiran. Obratite se vlasniku web-lokacije da biste riješili problem.</translation>
-<translation id="7498234416455752244">Nastavi uređivati</translation>
+<translation id="7498193950643227031">Ako se promijeni veliÄina, može doći do neoÄekivanog ponaÅ¡anja. Mogućnost promjene veliÄine aplikacija možete ograniÄiti u odjeljku <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Upravo ste unijeli zaporku na obmanjujućoj web-lokaciji. Chromium preporuÄuje da odmah provjerite spremljene zaporke za <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> i druge web-lokacije na kojima koristite tu zaporku.</translation>
<translation id="7508255263130623398">Vraćeni ID ureÄ‘aja pravila prazan je ili ne odgovara trenutaÄnom ID-u ureÄ‘aja</translation>
<translation id="7508870219247277067">Zelenožuta</translation>
@@ -1724,6 +1774,7 @@ Dodatne pojedinosti:
<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="755279583747225797">Proba je aktivna</translation>
<translation id="7552846755917812628">PokuÅ¡ajte uÄiniti sljedeće:</translation>
<translation id="7554475479213504905">Ipak ponovno uÄitaj i prikaži</translation>
<translation id="7554791636758816595">Nova kartica</translation>
@@ -1742,7 +1793,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, a zatim Enter da biste vidjeli zaporke u postavkama Chromea i upravljali njima</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="7616645509853975347">VaÅ¡ administrator ukljuÄio je poveznike za Chrome za poduzeća u vaÅ¡em pregledniku. Ti poveznici imaju pristup nekim vaÅ¡im podacima.</translation>
<translation id="7619838219691048931">Zadnji list</translation>
<translation id="762844065391966283">PojedinaÄno</translation>
@@ -1807,13 +1857,12 @@ Dodatne pojedinosti:
<translation id="782886543891417279">Za Wi-Fi koji upotrebljavate (<ph name="WIFI_NAME" />) možda ćete morati posjetiti stranicu za prijavu.</translation>
<translation id="7836231406687464395">Postfix (omotnica)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ništa}=1{1 aplikacija (<ph name="EXAMPLE_APP_1" />)}=2{2 aplikacije (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# aplikacija (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}few{# aplikacije (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# aplikacija (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Niste nevidljivi. Anonimni naÄin ne sakriva vaÅ¡e pregledavanje od poslodavca, davatelja internetskih usluga ili posjećenih web-lokacija.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">otvoriti datoteke s povezanim vrstama datoteka.</translation>
<translation id="7862185352068345852">Želite li napustiti web-lokaciju?</translation>
<translation id="7865448901209910068">Najbolja brzina</translation>
<translation id="7874263914261512992">Upravo ste unijeli zaporku na obmanjujućoj web-lokaciji. Chrome preporuÄuje da odmah provjerite spremljene zaporke za <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> i druge web-lokacije na kojima koristite tu zaporku.</translation>
<translation id="7878562273885520351">Vaša je zaporka možda ugrožena</translation>
+<translation id="7880146494886811634">Spremanje adrese</translation>
<translation id="7882421473871500483">Smeđa</translation>
<translation id="7887683347370398519">Provjerite CVC i pokušajte ponovo</translation>
<translation id="7887885240995164102">Pokreni sliku u slici</translation>
@@ -1821,6 +1870,7 @@ Dodatne pojedinosti:
<translation id="7894280532028510793">Ako nema pravopisnih pogrešaka, <ph name="BEGIN_LINK" />pokušajte pokrenuti Mrežnu dijagnostiku<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (omotnica)</translation>
<translation id="7931318309563332511">Nepoznato</translation>
+<translation id="793209273132572360">Želite li ažurirati adresu?</translation>
<translation id="7932579305932748336">Omot</translation>
<translation id="79338296614623784">Unesite važeći telefonski broj</translation>
<translation id="7934052535022478634">Plaćanje je izvršeno</translation>
@@ -1891,6 +1941,7 @@ Dodatne pojedinosti:
<translation id="8175796834047840627">Chrome vam nudi spremanje vaÅ¡ih kartica na vaÅ¡ Google raÄun jer ste prijavljeni. To ponaÅ¡anje možete promijeniti u postavkama.</translation>
<translation id="8176440868214972690">Administrator uređaja poslao je neke podatke, poput postavki ili pravila, sljedećim web-lokacijama.</translation>
<translation id="8184538546369750125">Upotrijebi globalnu zadanu vrijednost (dopusti)</translation>
+<translation id="8193086767630290324">radnje s podacima koji su oznaÄeni kao povjerljivi</translation>
<translation id="8194797478851900357">&amp;Poništi premještanje</translation>
<translation id="8201077131113104583">Nevažeći URL ažuriranja za proširenje s ID-om "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Sažetak narudžbe</translation>
@@ -1913,6 +1964,7 @@ Dodatne pojedinosti:
<translation id="8249296373107784235">Prekini</translation>
<translation id="8249320324621329438">Zadnje dohvaćanje:</translation>
<translation id="8253091569723639551">Potrebna je adresa za naplatu</translation>
+<translation id="8257387598443225809">Ova je aplikacija izrađena za mobilne uređaje</translation>
<translation id="825929999321470778">Prikaži sve spremljene zaporke</translation>
<translation id="8261506727792406068">Izbriši</translation>
<translation id="8262952874573525464">Rubni Å¡av pri dnu</translation>
@@ -2037,7 +2089,6 @@ Dodatne pojedinosti:
<translation id="8719528812645237045">Višestruko bušenje pri vrhu</translation>
<translation id="8725066075913043281">Pokušajte ponovo</translation>
<translation id="8726549941689275341">VeliÄina stranica:</translation>
-<translation id="8728672262656704056">Radite u anonimnom naÄinu</translation>
<translation id="8730621377337864115">Gotovo</translation>
<translation id="8731544501227493793">Gumb Upravljajte zaporkama, pritisnite Enter da biste vidjeli zaporke u Chromeovim postavkama i upravljali njima</translation>
<translation id="8734529307927223492">Vašim uređajem <ph name="DEVICE_TYPE" /> upravlja <ph name="MANAGER" /></translation>
@@ -2114,6 +2165,7 @@ Dodatne pojedinosti:
<translation id="9020542370529661692">Ova je stranica prevedena na <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Nije važeće)</translation>
+<translation id="9030265603405983977">Jednobojno</translation>
<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>
@@ -2138,6 +2190,7 @@ i netoÄne vjerodajnice. To može znaÄiti da se neki napadaÄ pokuÅ¡ava predsta
<translation id="91108059142052966">Administratorsko pravilo onemogućuje dijeljenje zaslona s aplikacijom <ph name="APPLICATION_TITLE" /> ako je vidljiv povjerljiv sadržaj</translation>
<translation id="9114524666733003316">Potvrđivanje kartice...</translation>
<translation id="9114581008513152754">Preglednikom ne upravlja tvrtka ili neka druga organizacija. Aktivnostima na ovom uređaju možda se upravlja izvan Chromea. <ph name="BEGIN_LINK" />Saznajte više<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Novo</translation>
<translation id="9119042192571987207">Preneseno</translation>
<translation id="9128016270925453879">Pravila se uÄitavaju</translation>
<translation id="9128870381267983090">Povezivanje s mrežom</translation>
@@ -2156,6 +2209,7 @@ i netoÄne vjerodajnice. To može znaÄiti da se neki napadaÄ pokuÅ¡ava predsta
<translation id="9170848237812810038">&amp;Poništi</translation>
<translation id="9171296965991013597">Napustiti aplikaciju?</translation>
<translation id="9173282814238175921">Jedan dokument/novi list</translation>
+<translation id="9173995187295789444">Traženje Bluetooth uređaja...</translation>
<translation id="917450738466192189">Certifikat poslužitelja nije valjan.</translation>
<translation id="9174917557437862841">Gumb za promjenu kartice, pritisnite Enter za prebacivanje na tu karticu</translation>
<translation id="9179703756951298733">Upravljanje podacima o plaćanjima i kreditnim karticama u postavkama Chromea</translation>
diff --git a/chromium/components/strings/components_strings_hu.xtb b/chromium/components/strings/components_strings_hu.xtb
index 3aacf2ae963..2de57c16c33 100644
--- a/chromium/components/strings/components_strings_hu.xtb
+++ b/chromium/components/strings/components_strings_hu.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Engedély kiválasztása a következőhöz: <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Ãtrendezés visszavonása</translation>
+<translation id="1123753900084781868">Az élő feliratozás jelenleg nem áll rendelkezésre</translation>
<translation id="1125573121925420732">Gyakran előfordulhatnak figyelmeztetések, amikor a webhelyek frissítik biztonsági megoldásaikat. Ez a helyzet hamarosan javulhat.</translation>
<translation id="112840717907525620">Irányelv-gyorsítótár OK</translation>
<translation id="1130564665089811311">Oldal lefordítása gomb, az Enter billentyű megnyomásával lefordíttathatja ezt az oldalt a Google Fordító segítségével</translation>
@@ -74,6 +75,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="1240347957665416060">Az eszköze neve</translation>
<translation id="124116460088058876">További nyelvek…</translation>
<translation id="1243027604378859286">Szerző:</translation>
+<translation id="1246424317317450637">Félkövér</translation>
<translation id="1250759482327835220">A következő alkalommal gyorsabban fizethet, ha elmenti kártyáját, nevét és számlázási címét a Google-fiókjába.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (szinkronizálva)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ha nem nyílik meg a felkeresni kívánt webhely, először próbálja meg kijavítani a hibát a következő problémamegoldó lépések végrehajtásával:&lt;/p&gt;
@@ -156,6 +158,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="1476595624592550506">Módosítsa jelszavát</translation>
<translation id="1484290072879560759">Szállítási cím kiválasztása</translation>
<translation id="1492194039220927094">Irányelvek leküldése:</translation>
+<translation id="1495677929897281669">Vissza a lapra</translation>
<translation id="1501859676467574491">Jelenítsen meg kártyákat az Ön Google-fiókjából</translation>
<translation id="1507202001669085618">&lt;p&gt;Ez a hiba akkor fordul elő, ha olyan Wi-Fi-portált használ, amely bejelentkezést igényel, mielőtt kapcsolódna az internethez.&lt;/p&gt;
&lt;p&gt;A hiba kijavításához kattintson a &lt;strong&gt;Csatlakozás&lt;/strong&gt; lehetőségre a megnyitni próbált oldalon.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="1532118530259321453">Az oldal közlendője</translation>
<translation id="153384715582417236">Egyelőre ennyi</translation>
<translation id="1536390784834419204">Oldal fordítása</translation>
+<translation id="1539840569003678498">Bejelentés elküldve:</translation>
<translation id="154408704832528245">Kézbesítési cím kiválasztása</translation>
<translation id="1549470594296187301">A funkció használatához engedélyezni kell a JavaScriptet.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="1682696192498422849">Rövid él először</translation>
<translation id="168693727862418163">A házirend értéke nem egyezik a sémájával, ezért a rendszer figyelmen kívül hagyja.</translation>
<translation id="168841957122794586">A szervertanúsítvány gyenge titkosítási kulcsot tartalmaz.</translation>
+<translation id="1696290444144917273">Virtuális kártya adatainak megtekintése</translation>
<translation id="1697532407822776718">Máris elkészült!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{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 elméletileg holnaptól érvényes. Ennek oka lehet konfigurációs hiba, de az is lehet, hogy egy támadó eltérítette az Ön kapcsolódását.}other{A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványa elméletileg # nap múlva lép érvénybe. Ennek oka lehet konfigurációs hiba, de az is lehet, hogy egy támadó eltérítette az Ön kapcsolódását.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Figyelmen kívül hagyva, mivel a(z) <ph name="POLICY_NAME" /> nincs erre az értékre állítva: <ph name="VALUE" />.</translation>
<translation id="1712552549805331520">A(z) <ph name="URL" /> webhely állandó jelleggel adatokat szeretne tárolni a helyi számítógépen</translation>
<translation id="1713628304598226412">2. tálca</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">3. postaláda</translation>
<translation id="1718029547804390981">A dokumentum túl nagy a jegyzeteléshez</translation>
<translation id="1721424275792716183">* A mező kitöltése kötelező</translation>
+<translation id="1727613060316725209">A tanúsítvány érvényes</translation>
<translation id="1727741090716970331">Érvényes kártyaszámot adjon meg</translation>
<translation id="1728677426644403582">Jelenleg weboldal forrását tekinti meg</translation>
<translation id="173080396488393970">Ez a kártyatípus nem támogatott</translation>
@@ -246,7 +253,6 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
a(z) <ph name="SITE" /> webhelyre irányuló kérelmet. Az eredetházirendek segítségével
a webhelyek üzemeltetői a webhely biztonsági és egyéb tulajdonságait konfigurálhatják.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Kérjük, frissítse szinkronizálási összetett jelszavát.</translation>
<translation id="1787142507584202372">A megnyitott lapok helye</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, több művelet is rendelkezésre áll, a Tab gombbal mozoghat közöttük</translation>
@@ -279,6 +285,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="1919345977826869612">Hirdetések</translation>
<translation id="1919367280705858090">Segítség kérése adott hibaüzenet esetén</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Nincs}=1{1 webhely}other{# webhely}}</translation>
+<translation id="1924727005275031552">Új</translation>
<translation id="1945968466830820669">Elveszítheti a hozzáférést szervezete fiókjához, vagy visszaélhetnek személyes adataival. A Chromium azt javasolja, hogy azonnal módosítsa jelszavát.</translation>
<translation id="1947454675006758438">Kapocs jobbra fent</translation>
<translation id="1958218078413065209">A rekordja: <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="2042213636306070719">7. tálca</translation>
<translation id="204357726431741734">Jelentkezzen be a Google-fiókjába mentett jelszavak használatához</translation>
<translation id="2053111141626950936">A(z) <ph name="LANGUAGE" /> nyelvű oldalak nem lesznek lefordítva.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Ha ez a vezérlő be van kapcsolva, és az állapot aktív, a Chrome meghatározza, hogy az Ön legutóbbi böngészési tevékenysége melyik nagy társadalmi csoporthoz, azaz „kohorszhoz†hasonlít leginkább. A hirdetők kiválaszthatják a hirdetéseket a csoporthoz, ám a böngészési előzményeit privát módon tárolja a rendszer az eszközén. Csoportja minden nap frissül.}=1{Ha ez a vezérlő be van kapcsolva, és az állapot aktív, a Chrome meghatározza, hogy az Ön legutóbbi böngészési tevékenysége melyik nagy társadalmi csoporthoz, azaz „kohorszhoz†hasonlít leginkább. A hirdetők kiválaszthatják a hirdetéseket a csoporthoz, ám a böngészési előzményeit privát módon tárolja a rendszer az eszközén. Csoportja minden nap frissül.}other{Ha ez a vezérlő be van kapcsolva, és az állapot aktív, a Chrome meghatározza, hogy az Ön legutóbbi böngészési tevékenysége melyik nagy társadalmi csoporthoz, azaz „kohorszhoz†hasonlít leginkább. A hirdetők kiválaszthatják a hirdetéseket a csoporthoz, ám a böngészési előzményeit privát módon tárolja a rendszer az eszközén. Csoportja {NUM_DAYS} naponta frissül.}}</translation>
<translation id="2053553514270667976">Irányítószám</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 javaslat}other{# javaslat}}</translation>
<translation id="2071692954027939183">A rendszer automatikusan letiltotta az értesítéseket, mert Ön általában nem engedélyezi őket.</translation>
<translation id="2079545284768500474">Visszavonás</translation>
<translation id="20817612488360358">A rendszer proxybeállításai konfigurálva vannak a használathoz, de kifejezett proxykonfiguráció is meg van adva.</translation>
<translation id="2082238445998314030">Eredmény: <ph name="RESULT_NUMBER" />/<ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Mentés…</translation>
<translation id="2088086323192747268">Szinkronizálás kezelése gomb. Nyomja le az Enter billentyűt az adatok szinkronizálásának Chrome-beállítások közötti kezeléséhez.</translation>
<translation id="2091887806945687916">Hang</translation>
<translation id="2094505752054353250">Domainkeveredés</translation>
@@ -379,6 +388,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="2317259163369394535">A(z) <ph name="DOMAIN" /> felhasználónevet és jelszót kér.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, lejárat dátuma: <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">A beállítást a rendszergazda szabályozza</translation>
+<translation id="2340263603246777781">A(z) <ph name="ORIGIN" /> párosítást szeretne végrehajtani</translation>
<translation id="2344028582131185878">Automatikus letöltések</translation>
<translation id="2346319942568447007">Vágólapra másolt kép</translation>
<translation id="2354001756790975382">További könyvjelzők</translation>
@@ -386,8 +396,10 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="2355395290879513365">A felhasználók esetleg láthatják a webhelyen éppen megtekintett képeit, és a képeket módosítva félrevezethetik Önt.</translation>
<translation id="2356070529366658676">Kérés</translation>
<translation id="2357481397660644965">Eszközét a(z) <ph name="DEVICE_MANAGER" />, fiókját pedig a(z) <ph name="ACCOUNT_MANAGER" /> kezeli.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Kevesebb, mint egy napon belül}=1{Egy napon belül}other{{NUM_DAYS} napon belül}}</translation>
<translation id="2359629602545592467">Több</translation>
<translation id="2359808026110333948">Tovább</translation>
+<translation id="2359961752320758691">Beírtuk a virtuális kártyája számát.</translation>
<translation id="2367567093518048410">Szint</translation>
<translation id="2372464001869762664">A megerősítést követően a böngésző megosztja az Ön Google-fiókjából származó kártyaadatokat ezzel a webhellyel. Keresse meg a CVC-kódot Plex-fiókja adatai között.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="239429038616798445">Ez a szállítási mód nem áll rendelkezésre. Próbálkozzon másik móddal.</translation>
<translation id="2396249848217231973">&amp;Törlés visszavonása</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Régi</translation>
<translation id="2413528052993050574">A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványát visszavonhatták. Ennek oka lehet konfigurációs hiba, vagy hogy egy támadó eltérítette az Ön kapcsolódását.</translation>
<translation id="2414886740292270097">Sötét</translation>
<translation id="2438874542388153331">Négy lyuk a jobb oldalon</translation>
@@ -425,10 +438,10 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="2521385132275182522">Kapocs jobbra lent</translation>
<translation id="2523886232349826891">Csak erre az eszközre mentve</translation>
<translation id="2524461107774643265">További adatok hozzáadása</translation>
-<translation id="2526590354069164005">Asztal</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{és 1 további}other{és # további}}</translation>
<translation id="2536110899380797252">Cím hozzáadása</translation>
<translation id="2539524384386349900">Felismerés</translation>
+<translation id="2541219929084442027">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="2544644783021658368">Egyetlen dokumentum</translation>
<translation id="254947805923345898">A házirend értéke nem érvényes.</translation>
<translation id="255002559098805027">A(z) <ph name="HOST_NAME" /> érvénytelen választ küldött.</translation>
@@ -448,6 +461,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="2629325967560697240">A Chrome legmagasabb szintű biztonságának eléréséhez <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />kapcsolja be a speciális védelmet<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">A(z) <ph name="HOST_NAME" /> szerver IP-címe nem található.</translation>
<translation id="2639739919103226564">Ãllapot:</translation>
+<translation id="264810637653812429">Nem találhatók kompatibilis eszközök.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, nyomja le a Tab, majd az Enter billentyűt a böngészési előzményeknek, a cookie-knak, a gyorsítótárnak és egyebeknek a Chrome beállításaiban való törléséhez</translation>
<translation id="2650446666397867134">A hozzáférés a fájlhoz megtagadva.</translation>
@@ -492,6 +506,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<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="2807052079800581569">Kép Y-pozíciója</translation>
+<translation id="2820957248982571256">Keresés…</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>
@@ -499,6 +514,8 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="2850739647070081192">Invite (boríték)</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="2859806420264540918">Ez a webhely tolakodó vagy félrevezető hirdetéseket jelenít meg.</translation>
+<translation id="287596039013813457">Barátságos</translation>
+<translation id="2876489322757410363">Az inkognitó mód elhagyása külső alkalmazással történő fizetéshez. Folytatja?</translation>
<translation id="2878197950673342043">Kereszthajtás</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Ablakelhelyezés</translation>
@@ -548,7 +565,6 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="3060227939791841287">C9 (boríték)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />. Nyomja le a Tabot, majd az Entert a biztonsági ellenőrzés futtatásához a Chrome beállításaiban.</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>
<translation id="306573536155379004">A játék elindult.</translation>
<translation id="3080254622891793721">Grafika</translation>
<translation id="3086579638707268289">Megfigyelik az Ön interneten végzett tevékenységeit</translation>
@@ -571,7 +587,6 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="315504272643575312">Az Ön fiókkezelője: <ph name="MANAGER" />.</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>
<translation id="3174168572213147020">Sziget</translation>
<translation id="3176929007561373547">Ellenőrizze a proxybeállításokat, vagy kérdezze meg a rendszergazdájától, hogy a proxyszerver működik-e. Ha úgy gondolja, hogy nem használ proxyszervert:
@@ -595,10 +610,12 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<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="3249845759089040423">Izgalmas</translation>
<translation id="3252266817569339921">francia</translation>
<translation id="3266793032086590337">Érték (ütközés)</translation>
<translation id="3268451620468152448">Megnyitott lapok</translation>
<translation id="3270847123878663523">&amp;Ãtrendezés visszavonása</translation>
+<translation id="3271648667212143903">A(z) <ph name="ORIGIN" /> csatlakozni szeretne</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">A szervezete (<ph name="ENROLLMENT_DOMAIN" />) elküldött bizonyos információkat (pl. a beállításokat és a házirendeket) a következő webhelyeknek.</translation>
<translation id="3282497668470633863">Adja meg a kártyán szereplő nevet</translation>
@@ -651,6 +668,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="3428151540071562330">A DnsOverHttpsTemplates szerversablon-URI-k közül legalább egy érvénytelen, és nem használható.</translation>
<translation id="3431636764301398940">Kártya mentése az eszközre</translation>
<translation id="3432601291244612633">Oldal bezárása</translation>
+<translation id="3435738964857648380">Biztonság</translation>
<translation id="3435896845095436175">Engedélyezés</translation>
<translation id="3438829137925142401">A Google-fiókba mentett jelszavak használata</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -693,7 +711,10 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="3584299510153766161">Két lyuk alul</translation>
<translation id="3586931643579894722">Részletek elrejtése</translation>
<translation id="3587738293690942763">Közép</translation>
+<translation id="3590643883886679995">Az inkognitó mód elhagyása után ez az eszköz tárolja a bejelentkezési adatokat.</translation>
+<translation id="359126217934908072">Hónap/év:</translation>
<translation id="3592413004129370115">Italian (boríték)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Csoportját bármikor visszaállíthatja. Az új csoporthoz való csatlakozás körülbelül egy napig tart.}=1{Csoportját bármikor visszaállíthatja. Az új csoporthoz való csatlakozás körülbelül egy napig tart.}other{Csoportját bármikor visszaállíthatja. Az új csoporthoz való csatlakozás körülbelül {NUM_DAYS} napig tart.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">A rendszergazda letiltotta az alkalmazást</translation>
<translation id="3608932978122581043">Adagolás tájolása</translation>
@@ -702,13 +723,13 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="3615877443314183785">Érvényes lejárati dátumot kell megadnia</translation>
<translation id="36224234498066874">Böngészési adatok törlése…</translation>
<translation id="362276910939193118">Az összes előzmény</translation>
-<translation id="3625635938337243871">Az inkognitó mód elhagyása után ez az eszköz tárolja a bejelentkezési adatokat.</translation>
<translation id="3630155396527302611">Ha már megjelenik a hálózat elérésére engedélyezett programként, próbálkozzon
az eltávolításával, majd a listára való ismételt felvételével.</translation>
<translation id="3630699740441428070">Az eszköz rendszergazdái olyan hálózati kapcsolatot állítottak be Önnek, amely lehetővé teheti számukra az Ön hálózati forgalmának, köztük az Ön által felkeresett webhelyek tartalmának megtekintését.</translation>
<translation id="3631244953324577188">Biometria</translation>
<translation id="3633738897356909127">Chrome frissítése gomb, nyomja le az Enter billentyűt a Chrome-nak a Chrome beállításaiban való frissítéséhez</translation>
<translation id="3634530185120165534">5. tálca</translation>
+<translation id="3637662659967048211">Mentés Google-fiókba</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Alkalmazás:</translation>
<translation id="3650584904733503804">Sikeres érvényesítés</translation>
@@ -749,6 +770,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="3781428340399460090">Élénk rózsaszín</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth-eszközök</translation>
+<translation id="3787675388804467730">Virtuális kártya száma</translation>
<translation id="3787705759683870569">Lejárat dátuma: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Méret: 16</translation>
<translation id="3789841737615482174">Telepítés</translation>
@@ -768,6 +790,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="3841184659773414994">Fájlkezelők</translation>
<translation id="385051799172605136">Vissza</translation>
<translation id="3858027520442213535">Dátum és idő frissítése</translation>
+<translation id="3881478300875776315">Kevesebb sor megjelenítése</translation>
<translation id="3884278016824448484">Eszközazonosító-ütközés</translation>
<translation id="3885155851504623709">Körzet</translation>
<translation id="388632593194507180">Figyelés észlelve</translation>
@@ -793,6 +816,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="397105322502079400">Számítás…</translation>
<translation id="3973234410852337861">A(z) <ph name="HOST_NAME" /> le van tiltva</translation>
<translation id="3973357910713125165">A Chrome biztonsági ellenőrzését futtató gomb. Nyomja le az Entert a biztonsági ellenőrzés futtatásához a Chrome beállításaiban.</translation>
+<translation id="3986705137476756801">Élő feliratozás átmeneti kikapcsolása</translation>
<translation id="3987405730340719549">A Chrome azt észlelte, hogy ez a webhely hamis vagy megtévesztő szándékú lehet.
Ha úgy gondolja, hogy ez a figyelmeztetés téves, keresse fel a következő oldalt: https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -889,13 +913,14 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="4275830172053184480">Indítsa újra az eszközt</translation>
<translation id="4277028893293644418">Jelszó visszaállítása</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="4287885627794386150">Jogosult a próbaverzióra, de nem aktív</translation>
<translation id="4297502707443874121">A(z) <ph name="THUMBNAIL_PAGE" /> oldal indexképe</translation>
<translation id="42981349822642051">Kibontás</translation>
<translation id="4300675098767811073">Több lyuk a jobb oldalon</translation>
<translation id="4302514097724775343">A játékhoz koppintson a dinóra</translation>
<translation id="4302965934281694568">Chou3 (boríték)</translation>
<translation id="4305666528087210886">A fájlhoz nem sikerült hozzáférni</translation>
-<translation id="4305817255990598646">Váltás</translation>
+<translation id="4306529830550717874">Menti a címet?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Letiltás (alapértelmezett)</translation>
<translation id="4314815835985389558">Szinkronizálás kezelése</translation>
@@ -922,6 +947,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="4377125064752653719">A(z) <ph name="DOMAIN" /> webhelyet próbálta megnyitni, de a kiállító visszavonta a szerver által bemutatott tanúsítványt. Ez azt jelenti, hogy a szerver biztonsági igazolásaiban egyáltalán nem lehet megbízni. Lehet, hogy egy támadóval áll kapcsolatban.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Perem</translation>
+<translation id="4406883609789734330">Élő feliratozás</translation>
<translation id="4406896451731180161">keresési találat</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> cookie</translation>
<translation id="4414290883293381923">Megtévesztő webhelyen adta meg jelszavát. A Chrome azt javasolja, hogy keresse fel azokat a webhelyeket (pl. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> és <ph name="WEBSITE_3" />), amelyeken ezt a jelszót használja, és módosítsa most a jelszót.</translation>
@@ -934,7 +960,6 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<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="4464826014807964867">Webhelyek, amelyek a szervezetétől származó adatokkal rendelkeznek</translation>
-<translation id="4466881336512663640">Az űrlapon végzett módosítások elvesznek. Biztosan folytatni szeretné?</translation>
<translation id="4476953670630786061">Ez az űrlap nem biztonságos. Az automatikus kitöltés funkciót a rendszer kikapcsolta.</translation>
<translation id="4477350412780666475">Következő szám</translation>
<translation id="4482953324121162758">Nem fordítjuk le ezt a webhelyet.</translation>
@@ -968,6 +993,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<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="4606870351894164739">Hatásos</translation>
<translation id="4628948037717959914">Fénykép</translation>
<translation id="4631649115723685955">Pénzvisszatérítéssel összekapcsolva</translation>
<translation id="4636930964841734540">Információ</translation>
@@ -987,6 +1013,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="4691835149146451662">Architecture-A (boríték)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Oldal</translation>
+<translation id="4702656508969495934">Az Élő feliratozás látható, a fókuszáláshoz használja az ablakváltót</translation>
<translation id="4708268264240856090">Kapcsolata megszakadt</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />A Windows Hálózati diagnosztika futtatása<ph name="END_LINK" /></translation>
@@ -1000,6 +1027,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="4738601419177586157"><ph name="TEXT" /> keresési javaslat</translation>
<translation id="4742407542027196863">Jelszavak kezelése…</translation>
<translation id="4744603770635761495">Végrehajtható fájl útvonala</translation>
+<translation id="4749011317274908093">Ön inkognitó módra váltott</translation>
<translation id="4750917950439032686">Adatai (például jelszava vagy hitelkártyaszáma) nem láthatók más számára, amikor a rendszer elküldi őket a webhelynek.</translation>
<translation id="4756388243121344051">&amp;Előzmények</translation>
<translation id="4758311279753947758">Névjegyadatok hozzáadása</translation>
@@ -1029,6 +1057,8 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="4813512666221746211">Hálózati hiba</translation>
<translation id="4816492930507672669">Igazítás az oldalmérethez</translation>
<translation id="4819347708020428563">Szeretné a jelöléseket az alapértelmezett nézetben szerkeszteni?</translation>
+<translation id="4825507807291741242">Erőteljes</translation>
+<translation id="4838327282952368871">Ãlmodozó</translation>
<translation id="484462545196658690">Automatikus</translation>
<translation id="4850886885716139402">Nézet</translation>
<translation id="485316830061041779">német</translation>
@@ -1165,6 +1195,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="5314967030527622926">Brosúrakészítő</translation>
<translation id="5316812925700871227">Forgatás balra</translation>
<translation id="5317780077021120954">Mentés</translation>
+<translation id="5321288445143113935">Teljes méretű</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> elemből a következő pozícióban: <ph name="MATCH_POSITION" />.</translation>
<translation id="5324080437450482387">Kapcsolatfelvételi adatok kiválasztása</translation>
<translation id="5327248766486351172">Név</translation>
@@ -1172,11 +1203,13 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="5332219387342487447">Szállítási mód</translation>
<translation id="5333022057423422993">A Chrome észlelte, hogy a most használt jelszava adatvédelmi incidensben volt érintett. Fiókjai biztonsága érdekében javasoljuk a mentett jelszavak ellenőrzését.</translation>
<translation id="5334013548165032829">Részletes rendszernaplók</translation>
+<translation id="5334145288572353250">Menti a címet?</translation>
<translation id="5340250774223869109">Alkalmazás letiltva</translation>
<translation id="534295439873310000">NFC-eszközök</translation>
<translation id="5344579389779391559">Ez az oldal fizetésre próbálhatja meg rávenni</translation>
<translation id="5355557959165512791">Pillanatnyilag nem tudja felkeresni a(z) <ph name="SITE" /> webhelyet, mert a webhely tanúsítványát visszavonták. 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="536296301121032821">Az irányelv-beállítások tárolása sikertelen</translation>
+<translation id="5363309033720083897">Rendszergazda által engedélyezett soros port</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="5386426401304769735">A webhely tanúsítványlánca SHA-1 titkosítással aláírt tanúsítványt tartalmaz.</translation>
@@ -1185,6 +1218,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="5398772614898833570">Hirdetések letiltva</translation>
<translation id="5400836586163650660">Szürke</translation>
<translation id="540969355065856584">A szerver nem tudta bizonyítani, hogy valóban a(z) <ph name="DOMAIN" /> domainbe tartozik; biztonsági tanúsítványa jelenleg nem érvényes. Ennek oka lehet konfigurációs hiba, vagy hogy egy támadó eltérítette az Ön kapcsolatát.</translation>
+<translation id="541143247543991491">Felhő (rendszerszintű)</translation>
<translation id="541416427766103491">4. kötegelő</translation>
<translation id="5421136146218899937">Böngészési adatok törlése...</translation>
<translation id="5426179911063097041">A(z) <ph name="SITE" /> értesítéseket szeretne küldeni Önnek</translation>
@@ -1198,6 +1232,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="5455374756549232013">Hibás az irányelv időbélyege</translation>
<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="5463625433003343978">Eszközök keresése…</translation>
<translation id="5469868506864199649">olasz</translation>
<translation id="5470861586879999274">&amp;Szerkesztés újra</translation>
<translation id="5478437291406423475">B6/C4 (boríték)</translation>
@@ -1247,7 +1282,6 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="5624120631404540903">Jelszavak kezelése</translation>
<translation id="5629630648637658800">Az irányelv-beállítások betöltése sikertelen</translation>
<translation id="5631439013527180824">Érvénytelen eszközkezelési token</translation>
-<translation id="5632627355679805402">Adatai titkosítva lettek <ph name="BEGIN_LINK" />Google-jelszavával<ph name="END_LINK" /> ekkor: <ph name="TIME" />. Adja meg a jelszót a szinkronizálás megkezdéséhez.</translation>
<translation id="5633066919399395251">Előfordulhat, hogy a támadók a(z) <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> webhelyen veszélyes programokat kísérelnek meg telepíteni számítógépére, amelyek ellopják vagy törlik az Ön adatait (például fotóit, jelszavait, üzeneteit és bankkártyájának adatait). <ph name="BEGIN_LEARN_MORE_LINK" />További információ<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="563324245173044180">Megtévesztő tartalom letiltva.</translation>
<translation id="5644090287519800334">1. oldali kép X-eltolása</translation>
@@ -1286,12 +1320,12 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="5785756445106461925">Emellett az oldal azonban 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="5786044859038896871">Ki szeretné tölteni a kártyaadatait?</translation>
<translation id="578633867165174378">A Chrome észlelte, hogy a most használt jelszava adatvédelmi incidensben volt érintett. Javasoljuk a jelszó azonnali módosítását.</translation>
-<translation id="5798290721819630480">Elveti a módosításokat?</translation>
<translation id="5803412860119678065">Ki szeretné tölteni <ph name="CARD_DETAIL" /> kártyájának adataival?</translation>
<translation id="5804241973901381774">Engedélyek</translation>
<translation id="5804427196348435412">NFC-eszközök használata</translation>
<translation id="5810442152076338065">A(z) <ph name="DOMAIN" /> domainnel való kapcsolata elavult kriptográfiával van titkosítva.</translation>
<translation id="5813119285467412249">&amp;Hozzáadás újra</translation>
+<translation id="5817918615728894473">Párosítás</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{A rendszer fizetéskor ezt a kártyát terheli meg, de a kártya valódi számát nem osztja meg ezzel a webhellyel. A további védelem érdekében ideiglenes CVC-t is generál.}other{A rendszer fizetéskor az Ön által kiválasztott kártyát terheli meg, de a kártya valódi számát nem osztja meg ezzel a webhellyel. A további védelem érdekében ideiglenes CVC-t is generál.}}</translation>
<translation id="5826507051599432481">Név (CN)</translation>
<translation id="5838278095973806738">Ne írjon be semmilyen bizalmas adatot (például jelszót vagy hitelkártyaadatot) a webhelyen, mivel a támadók ellophatják.</translation>
@@ -1299,6 +1333,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="5855253129151731373">Ennek a webhelynek a gazdagépneve hasonló a következőhöz: <ph name="LOOKALIKE_DOMAIN" />. A támadók néha úgy próbálnak meg webhelyeket utánozni, hogy apró, alig észrevehető változtatásokat végeznek a webhely domainnevében.
Ha úgy gondolja, hogy ez a figyelmeztetés téves, keresse fel a következő oldalt: https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Kikapcsolva</translation>
<translation id="5862579898803147654">8. kötegelő</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>
@@ -1315,6 +1350,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="5913377024445952699">Képernyőrögzítés szüneteltetve</translation>
<translation id="59174027418879706">Engedélyezve</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 van használatban}other{# van használatban}}</translation>
<translation id="5921185718311485855">Be</translation>
<translation id="5921639886840618607">Menti a kártyát a Google-fiókjába?</translation>
<translation id="5922853866070715753">Majdnem kész</translation>
@@ -1334,6 +1370,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="5989320800837274978">Sem fix proxyszerver, sem pedig .pac típusú szkript URL-címe nincs megadva.</translation>
<translation id="5992691462791905444">Z-hajtás hellyel kötés, lyukasztás és kapcsok számára</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> találat a következőre: <ph name="SEARCH_TEXT" /></translation>
+<translation id="6006484371116297560">Klasszikus</translation>
<translation id="6008122969617370890">„N az 1-hez†sorrend</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Jelszavak ellenőrzése</translation>
@@ -1355,6 +1392,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="6045164183059402045">Ráhelyezési sablon</translation>
<translation id="6047233362582046994">Ha tisztában van a biztonságát fenyegető kockázatokkal, a káros alkalmazások eltávolítása előtt is <ph name="BEGIN_LINK" />felkeresheti ezt a webhelyet<ph name="END_LINK" />.</translation>
<translation id="6047927260846328439">Lehet, hogy ez a tartalom megpróbálja rávenni Önt szoftver telepítésére vagy személyes adatok kiadására. <ph name="BEGIN_LINK" />Megjelenítés mindenképpen<ph name="END_LINK" />.</translation>
+<translation id="6049004884579590341">Tartsa lenyomva a(z) |<ph name="ACCELERATOR" />| gombot a teljes képernyős mód elhagyásához</translation>
<translation id="6049488691372270142">Oldalkézbesítés</translation>
<translation id="6051221802930200923">Pillanatnyilag nem tudja felkeresni a(z) <ph name="SITE" /> webhelyet, mivel a webhely tanúsítványrögzítést 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="6051898664905071243">Oldalak száma:</translation>
@@ -1371,6 +1409,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<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>
<translation id="6116338172782435947">Megtekinteni a vágólapra másolt szövegeket és képeket</translation>
<translation id="6120179357481664955">Emlékszik UPI-azonosítójára?</translation>
+<translation id="6123290840358279103">Virtuális kártya megtekintése</translation>
<translation id="6124432979022149706">Chrome Enterprise csatlakozási szoftverek</translation>
<translation id="6146055958333702838">Ellenőrizze a kábeleket, majd indítsa újra a routert, modemet vagy más
hálózati eszközt, amelyet használ.</translation>
@@ -1407,6 +1446,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="6289939620939689042">Oldalszín</translation>
<translation id="6290238015253830360">A javasolt cikkek helye</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">A Google Segéd a Chrome-ban szolgáltatás leáll</translation>
<translation id="6305205051461490394">A(z) <ph name="URL" /> nem érhető el.</translation>
<translation id="6312113039770857350">A weboldal nem érhető el</translation>
@@ -1432,6 +1472,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="6390200185239044127">Félbehajtás Z-hajtással</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Rendszergazdai házirend tiltja a tartalmak ide történő beillesztését a következő helyről: <ph name="ORIGIN_NAME" />.</translation>
+<translation id="6398765197997659313">Kilépés a teljes képernyős módból</translation>
<translation id="6401136357288658127">Ez a házirend megszűnt. Használja helyette a(z) <ph name="NEW_POLICY" /> házirendet.</translation>
<translation id="6404511346730675251">Könyvjelző szerkesztése</translation>
<translation id="6406765186087300643">C0 (boríték)</translation>
@@ -1444,7 +1485,6 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="6428450836711225518">Telefonszám ellenőrzése</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="6440503408713884761">Figyelmen kívül hagyva</translation>
<translation id="6443406338865242315">Ön milyen bővítményeket és beépülő modulokat telepített.</translation>
<translation id="6446163441502663861">Kahu (boríték)</translation>
@@ -1487,6 +1527,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="6624427990725312378">Kapcsolatfelvételi adatok</translation>
<translation id="6626291197371920147">Adjon meg érvényes kártyaszámot</translation>
<translation id="6628463337424475685">Keresés: <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">USB-eszközök keresése…</translation>
<translation id="6630809736994426279">Előfordulhat, hogy a támadók a(z) <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> webhelyen olyan veszélyes programokat kísérelnek meg telepíteni az Ön Mac típusú számítógépére, amelyek ellopják vagy törlik adatait (például fotóit, jelszavait, üzeneteit és bankkártyájának adatait). <ph name="BEGIN_LEARN_MORE_LINK" />További információ<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Törlés</translation>
@@ -1502,6 +1543,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<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="6687335167692595844">Kért betűméret</translation>
+<translation id="6688743156324860098">Frissítés…</translation>
<translation id="6689249931105087298">Relatív, feketepontos tömörítéssel</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="6698381487523150993">Létrehozva:</translation>
@@ -1517,6 +1559,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="6744009308914054259">Miközben kapcsolatra vár, a Letöltések között elolvashatja az offline cikkeket.</translation>
<translation id="6753269504797312559">Házirend értéke</translation>
<translation id="6757797048963528358">Eszköze alvó üzemmódba váltott.</translation>
+<translation id="6767985426384634228">Frissíti a címet?</translation>
<translation id="6768213884286397650">Hagaki (képeslap)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Ibolyaszín</translation>
@@ -1539,6 +1582,7 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">A Chrome egyszerűsítette ezt az oldalt, hogy könnyebben olvasható legyen. Az eredeti oldalt nem biztonságos kapcsolaton keresztül kérte le.</translation>
<translation id="6891596781022320156">Ezt a házirendszintet a rendszer nem támogatja.</translation>
+<translation id="6895143722905299846">Virtuális szám:</translation>
<translation id="6895330447102777224">Kártyáját ellenőriztük</translation>
<translation id="6897140037006041989">User agent</translation>
<translation id="6898699227549475383">Szervezet (O)</translation>
@@ -1574,10 +1618,10 @@ Ezt egyéb esetben letiltják az Ön adatvédelmi beállításai. Az engedélyez
<translation id="7004583254764674281">A Windows Hello használata a kártyák gyorsabb ellenőrzése érdekében</translation>
<translation id="7006930604109697472">Küldés mégis</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Ãtméretezési beállítások</translation>
<translation id="7014741021609395734">Nagyítás/kicsinyítés szintje</translation>
<translation id="7016992613359344582">Ezek egyszeri vagy ismétlődő díjak lehetnek, és nem feltétlenül nyilvánvalóak.</translation>
<translation id="7029809446516969842">Jelszavak</translation>
+<translation id="7030436163253143341">A tanúsítvány nem érvényes</translation>
<translation id="7031646650991750659">Ön milyen Google Play-alkalmazásokat telepített.</translation>
<translation id="7050187094878475250">Ön megpróbálta elérni a(z) <ph name="DOMAIN" /> domaint, de a szerver olyan tanúsítványt küldött, amelynek érvényességi ideje túl hosszú ahhoz, hogy megbízható legyen.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Ez a kártya jelenleg nem menthető}other{Ezeket a kártyákat jelenleg nem lehet menteni}}</translation>
@@ -1647,12 +1691,14 @@ További részletek:
<translation id="7300012071106347854">Kobaltkék</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />â€</translation>
<translation id="7304030187361489308">Magas</translation>
+<translation id="7305756307268530424">Indítás lassabban</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Segítség a kapcsolódáshoz</translation>
<translation id="7323804146520582233">A(z) „<ph name="SECTION" />†szakasz elrejtése</translation>
<translation id="733354035281974745">Eszköz helyi fiókja általi felülbírálás</translation>
<translation id="7333654844024768166">Megtévesztő webhelyen adta meg jelszavát. A Chromium azt javasolja, hogy keresse fel azokat a webhelyeket (pl. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> és <ph name="WEBSITE_3" />), amelyeken ezt a jelszót használja, és módosítsa most a jelszót.</translation>
<translation id="7334320624316649418">&amp;Ãtrendezés újra</translation>
+<translation id="7337248890521463931">Több sor megjelenítése</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>
@@ -1660,6 +1706,7 @@ További részletek:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Parancssor</translation>
<translation id="7359588939039777303">Hirdetések letiltva.</translation>
+<translation id="7363096869660964304">Azonban Ön nem teljesen láthatatlan. Az inkognitó mód használata nem rejti el böngészési műveleteit munkáltatója, az internetszolgáltatója és a felkeresett webhelyek elől.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" /> Nyomja le a Tab, majd az Enter billentyűt a címek Chrome-beállítások közötti hozzáadásához és kezeléséhez.</translation>
<translation id="7365849542400970216">Ismerheti a webhely az Ön eszközhasználatát?</translation>
<translation id="7372973238305370288">keresési találat</translation>
@@ -1670,7 +1717,9 @@ További részletek:
<translation id="7378594059915113390">Médiatartalmak vezérlői</translation>
<translation id="7378627244592794276">Nem</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">–</translation>
<translation id="7390545607259442187">Kártya igazolása</translation>
+<translation id="7392089738299859607">Cím frissítése</translation>
<translation id="7399802613464275309">Biztonsági ellenőrzés</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> eszköze felügyelet alatt áll</translation>
@@ -1685,6 +1734,7 @@ További részletek:
&lt;li&gt;Keresse fel a &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome súgóját&lt;/a&gt;, ahol további információt talál a szoftver számítógépről történő végleges eltávolításáról.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Kedves</translation>
<translation id="7416351320495623771">Jelszavak kezelése…</translation>
<translation id="7419106976560586862">Profil elérési útja</translation>
<translation id="7437289804838430631">Kapcsolatfelvételi adatok hozzáadása</translation>
@@ -1700,7 +1750,7 @@ További részletek:
<translation id="7481312909269577407">Előre</translation>
<translation id="7485870689360869515">Nem található adat.</translation>
<translation id="7495528107193238112">Ez a tartalom le van tiltva. Vegye fel a kapcsolatot a webhely tulajdonosával a probléma elhárításához.</translation>
-<translation id="7498234416455752244">Szerkesztés folytatása</translation>
+<translation id="7498193950643227031">Az átméretezés váratlan viselkedést eredményezhet. A <ph name="SETTINGS" /> menüben korlátozhatja az alkalmazásátméretezési képességet.</translation>
<translation id="7503664977220660814">Megtévesztő webhelyen adta meg jelszavát. A Chromium azt javasolja, hogy azonnal módosítsa jelszavait azokon a webhelyeken, ahol ezt a jelszót használja (pl. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />).</translation>
<translation id="7508255263130623398">A visszakapott házirend eszközazonosítója üres, vagy nem felel meg a jelenlegi eszközazonosítónak</translation>
<translation id="7508870219247277067">Avokádózöld</translation>
@@ -1720,6 +1770,7 @@ További részletek:
<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="755279583747225797">A próba aktív</translation>
<translation id="7552846755917812628">Próbálja ki az alábbi tippeket:</translation>
<translation id="7554475479213504905">Újratöltés, majd megjelenítés mindenképpen</translation>
<translation id="7554791636758816595">Új lap</translation>
@@ -1738,7 +1789,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, nyomja le a Tab, majd az Enter billentyűt a jelszavaknak a Chrome beállításaiban való megtekintéséhez és kezeléséhez</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="7616645509853975347">Rendszergazdája bekapcsolta a Chrome Enterprise Connectors integrációs eszközöket az Ön böngészőjében. Az eszközök hozzáférnek bizonyos adatokhoz.</translation>
<translation id="7619838219691048931">Befejező lap</translation>
<translation id="762844065391966283">Egyesével</translation>
@@ -1803,13 +1853,12 @@ További részletek:
<translation id="782886543891417279">Az Ön által használt Wi-Fi-hálózat (<ph name="WIFI_NAME" />) megkövetelheti a bejelentkezést a bejelentkezési oldalán.</translation>
<translation id="7836231406687464395">Postfix (boríték)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Nincs}=1{1 alkalmazás (<ph name="EXAMPLE_APP_1" />)}=2{2 alkalmazás (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# alkalmazás (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Azonban Ön nem teljesen láthatatlan. Az inkognitó mód használata nem rejti el böngészési műveleteit munkáltatója, az internetszolgáltatója és a felkeresett webhelyek elől.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Fájlok megnyitása fájltípustársítások használatával.</translation>
<translation id="7862185352068345852">Elhagyja a webhelyet?</translation>
<translation id="7865448901209910068">Legjobb sebesség</translation>
<translation id="7874263914261512992">Megtévesztő webhelyen adta meg jelszavát. A Chrome azt javasolja, hogy azonnal módosítsa jelszavait azokon a webhelyeken, ahol ezt a jelszót használja (pl. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />).</translation>
<translation id="7878562273885520351">Előfordultat, hogy jelszava már nem biztonságos</translation>
+<translation id="7880146494886811634">Cím mentése</translation>
<translation id="7882421473871500483">Barna</translation>
<translation id="7887683347370398519">Ellenőrizze a CVC-t, majd próbálja újra</translation>
<translation id="7887885240995164102">Belépés a kép a képben módba</translation>
@@ -1817,6 +1866,7 @@ További részletek:
<translation id="7894280532028510793">Ha helyesen írta, <ph name="BEGIN_LINK" />próbálkozzon a hálózati diagnosztika futtatásával<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (boríték)</translation>
<translation id="7931318309563332511">Ismeretlen</translation>
+<translation id="793209273132572360">Frissíti a címet?</translation>
<translation id="7932579305932748336">Bevonat</translation>
<translation id="79338296614623784">Érvényes telefonszámot adjon meg</translation>
<translation id="7934052535022478634">A fizetés befejeződött</translation>
@@ -1887,6 +1937,7 @@ További részletek:
<translation id="8175796834047840627">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.</translation>
<translation id="8176440868214972690">Az eszköz rendszergazdája elküldött bizonyos információkat (pl. a beállításokat és a házirendeket) a következő webhelyeknek.</translation>
<translation id="8184538546369750125">Globális alapértelmezés használata (Engedélyezés)</translation>
+<translation id="8193086767630290324">Bizalmasként megjelölt adatokkal végzett műveletek</translation>
<translation id="8194797478851900357">&amp;Ãthelyezés visszavonása</translation>
<translation id="8201077131113104583">A(z) „<ph name="EXTENSION_ID" />†azonosítójú bővítmény frissítési URL-je érvénytelen.</translation>
<translation id="8202097416529803614">Rendelés összegzése</translation>
@@ -1909,6 +1960,7 @@ További részletek:
<translation id="8249296373107784235">Megszakítás</translation>
<translation id="8249320324621329438">Utolsó lekérés:</translation>
<translation id="8253091569723639551">A számlázási cím megadása kötelező</translation>
+<translation id="8257387598443225809">Ez az alkalmazás mobileszközökre készült</translation>
<translation id="825929999321470778">Az összes mentett jelszó megjelenítése</translation>
<translation id="8261506727792406068">Törlés</translation>
<translation id="8262952874573525464">Éltűzés alul</translation>
@@ -2033,7 +2085,6 @@ További részletek:
<translation id="8719528812645237045">Több lyuk felül</translation>
<translation id="8725066075913043281">Újrapróbálás</translation>
<translation id="8726549941689275341">Oldalméret:</translation>
-<translation id="8728672262656704056">Ön Inkognitó módra váltott</translation>
<translation id="8730621377337864115">Kész</translation>
<translation id="8731544501227493793">Jelszavak kezelése gomb, nyomja meg az Enter billentyűt a jelszavaknak a Chrome beállításaiban való megtekintéséhez és kezeléséhez</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> eszközét a(z) <ph name="MANAGER" /> kezeli</translation>
@@ -2110,6 +2161,7 @@ További részletek:
<translation id="9020542370529661692">Az oldalt lefordítottuk <ph name="TARGET_LANGUAGE" /> nyelvre.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Érvénytelen)</translation>
+<translation id="9030265603405983977">Fekete-fehér</translation>
<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>
@@ -2133,6 +2185,7 @@ További részletek:
<translation id="91108059142052966">Rendszergazdai házirend tiltja a(z) <ph name="APPLICATION_TITLE" /> alkalmazással való képernyőmegosztást, ha bizalmas tartalom látható a képernyőn.</translation>
<translation id="9114524666733003316">Kártya ellenőrzése…</translation>
<translation id="9114581008513152754">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="9117930699067497412">Friss</translation>
<translation id="9119042192571987207">Feltöltve</translation>
<translation id="9128016270925453879">Házirendek betöltve</translation>
<translation id="9128870381267983090">Csatlakozás hálózathoz</translation>
@@ -2151,6 +2204,7 @@ További részletek:
<translation id="9170848237812810038">&amp;Visszavonás</translation>
<translation id="9171296965991013597">Bezárja az alkalmazást?</translation>
<translation id="9173282814238175921">Egy dokumentum/Új lap</translation>
+<translation id="9173995187295789444">Bluetooth-eszközök keresése…</translation>
<translation id="917450738466192189">A szerver tanúsítványa érvénytelen.</translation>
<translation id="9174917557437862841">Lapváltó gomb. Az Enter billentyűvel erre a lapra válthat.</translation>
<translation id="9179703756951298733">A fizetéssel és a hitelkártyával kapcsolatos adatait a Chrome-beállítások között kezelheti</translation>
diff --git a/chromium/components/strings/components_strings_hy.xtb b/chromium/components/strings/components_strings_hy.xtb
index 409cb73c470..c900fbceeaf 100644
--- a/chromium/components/strings/components_strings_hy.xtb
+++ b/chromium/components/strings/components_strings_hy.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Õ†Õ·Õ¾Õ¡Õ® Õ¬Õ«Õ¶Õ¥Õ¬Õ¸Ö‚ Õ¤Õ¥ÕºÖ„Õ¸Ö‚Õ´ Chrome-Õ¨ Õ±Ö‡Õ¥Ö€Õ¸Ö‚Õ´ Õ¡Ö€Õ¡Õ£ Õ¬Ö€Õ¡ÖÕ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€ Õ¡ÕµÕ½ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´ Õ¯ÕºÕ¡Õ°Õ« Õ±Õ¥Ö€ Ö„Õ¡Ö€Õ¿Õ« ÕºÕ¡Õ¿Õ³Õ¥Õ¶Õ¨:</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" />Õ Õ¨Õ¶Õ¿Ö€Õ¥Ö„ Õ©Õ¸Ö‚ÕµÕ¬Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶</translation>
<translation id="1113869188872983271">&amp;Õ€Õ¥Õ¿Õ¡Ö€Õ¯Õ¥Õ¬ Õ¾Õ¥Ö€Õ¡Õ¤Õ¡Õ½Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¨</translation>
+<translation id="1123753900084781868">Ô¿Õ¥Õ¶Õ¤Õ¡Õ¶Õ« Õ¥Õ¶Õ©Õ¡Õ£Ö€Õ¥Ö€Õ¶ Õ¡ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ¥Õ¶</translation>
<translation id="1125573121925420732">Ô¿Õ¡ÕµÖ„Õ¥Ö€Õ« Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ¾Õ¡Õ½Õ¿Õ¡Õ£Ö€Õ¥Ö€Õ« Õ©Õ¡Ö€Õ´Õ¡ÖÕ´Õ¡Õ¶ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¦Õ£Õ¸Ö‚Õ·Õ¡ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ¥Õ¬: Ô±ÕµÕ½ Õ­Õ¶Õ¤Õ«Ö€Õ¨ Õ·Õ¸Ö‚Õ¿Õ¸Õ¾ Õ¯Õ·Õ¿Õ¯Õ¾Õ«:</translation>
<translation id="112840717907525620">Õ”Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Ö„Õ¥Õ·Õ¸Ö‚Õ´ Õ½Õ­Õ¡Õ¬Õ¶Õ¥Ö€ Õ¹Õ¥Õ¶ Õ£Õ¿Õ¶Õ¾Õ¥Õ¬</translation>
<translation id="1130564665089811311">«Թարգմանել էջը» կոճակ։ Այս էջը Google Translate-ով թարգմանելու համար սեղմեք Enter։</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">ÕÕ¥Ö€ Õ½Õ¡Ö€Ö„Õ« Õ¡Õ¶Õ¸Ö‚Õ¶Õ¨</translation>
<translation id="124116460088058876">Ô±ÕµÕ¬ Õ¬Õ¥Õ¦Õ¸Ö‚Õ¶Õ¥Ö€</translation>
<translation id="1243027604378859286">Õ€Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ</translation>
+<translation id="1246424317317450637">Ô¹Õ¡Õ¾</translation>
<translation id="1250759482327835220">Õ€Õ¡Õ»Õ¸Ö€Õ¤ Õ¡Õ¶Õ£Õ¡Õ´ Õ¡Õ¾Õ¥Õ¬Õ« Õ¡Ö€Õ¡Õ£ Õ¾Õ³Õ¡Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ ÕºÕ¡Õ°Õ¥Ö„ Õ±Õ¥Ö€ Ö„Õ¡Ö€Õ¿Õ¨, Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶ Õ¸Ö‚ Õ¾Õ³Õ¡Ö€Õ¡ÕµÕ«Õ¶ Õ°Õ¡Õ½ÖÕ¥Õ¶ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´:</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (Õ°Õ¡Õ´Õ¡ÕªÕ¡Õ´Õ¡ÖÕ¾Õ¡Õ®)</translation>
<translation id="1256368399071562588">&lt;p&gt;ÔµÖ€Õ¢ Õ¤Õ¸Ö‚Ö„ ÖƒÕ¸Ö€Õ±Õ¸Ö‚Õ´ Õ¥Ö„ Õ¸Ö€Ö‡Õ§ Õ¯Õ¡ÕµÖ„ Õ¢Õ¡ÖÕ¥Õ¬, Õ«Õ½Õ¯ Õ¡ÕµÕ¶ Õ¹Õ« Õ¢Õ¡ÖÕ¾Õ¸Ö‚Õ´, Õ¶Õ¡Õ­ ÖƒÕ¸Ö€Õ±Õ¥Ö„ Õ¾Õ¥Ö€Õ¡ÖÕ¶Õ¥Õ¬ Õ¡Õ¶Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ°Õ¥Õ¿Ö‡ÕµÕ¡Õ¬ Ö„Õ¡ÕµÕ¬Õ¥Ö€Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾.&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Õ“Õ¸Õ­Õ¥Ö„ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨</translation>
<translation id="1484290072879560759">Ô¸Õ¶Õ¿Ö€Õ¥Ö„ Õ¡Õ¼Õ¡Ö„Õ´Õ¡Õ¶ Õ°Õ¡Õ½ÖÕ¥Õ¶</translation>
<translation id="1492194039220927094">Ô¿Õ¡Õ¶Õ¸Õ¶Õ¶Õ¥Ö€Õ« Õ´Õ²Õ¸Ö‚Õ´Õ</translation>
+<translation id="1495677929897281669">ÕŽÕ¥Ö€Õ¡Õ¤Õ¡Õ¼Õ¶Õ¡Õ¬ Õ¶Õ¥Ö€Õ¤Õ«Ö€</translation>
<translation id="1501859676467574491">Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Ö„ Ö„Õ¡Ö€Õ¿Õ¥Ö€ Õ±Õ¥Ö€ Google Õ°Õ¡Õ·Õ¾Õ«Ö</translation>
<translation id="1507202001669085618">&lt;p&gt;Ô±ÕµÕ½ Õ½Õ­Õ¡Õ¬Õ¨ Õ¯ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ«, Õ¥Õ©Õ¥ Õ¤Õ¸Ö‚Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„ Wi-Fi ÕºÕ¸Ö€Õ¿Õ¡Õ¬, Õ¸Ö€Õ¿Õ¥Õ² ÖÕ¡Õ¶ÖÕ«Õ¶ Õ´Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ¡Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ Õ§ Õ´Õ¿Õ¶Õ¥Õ¬ Õ°Õ¡Õ·Õ«Õ¾Ö‰&lt;/p&gt;
&lt;p&gt;ÕÕ­Õ¡Õ¬Õ¨ Õ·Õ¿Õ¯Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„ &lt;strong&gt;Õ„Õ«Õ¡Õ¶Õ¡Õ¬&lt;/strong&gt; Õ¡ÕµÕ¶ Õ§Õ»Õ¸Ö‚Õ´, Õ¸Ö€Õ¨ ÖƒÕ¸Ö€Õ±Õ¸Ö‚Õ´ Õ¥Ö„ Õ¢Õ¡ÖÕ¥Õ¬Ö‰&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¡ÕµÕ½ Õ§Õ»Õ«Ö</translation>
<translation id="153384715582417236">Ô±Õ¼Õ¡ÕµÕªÕ´ Õ¡ÕµÕ½Ö„Õ¡Õ¶Õ¨</translation>
<translation id="1536390784834419204">Ô¹Õ¡Ö€Õ£Õ´Õ¡Õ¶Õ¥Õ¬ Õ§Õ»Õ¨</translation>
+<translation id="1539840569003678498">Õ€Õ¡Õ·Õ¾Õ¥Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¥Õ¬ Õ§Õ</translation>
<translation id="154408704832528245">Ô¸Õ¶Õ¿Ö€Õ¥Ö„ Õ¡Õ¼Õ¡Ö„Õ´Õ¡Õ¶ Õ°Õ¡Õ½ÖÕ¥Õ¶</translation>
<translation id="1549470594296187301">Ô±ÕµÕ½ Õ°Õ¡Õ¿Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ«Ö Ö…Õ£Õ¿Õ¾Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ°Õ¡Ö€Õ¯Õ¡Õ¾Õ¸Ö€ Õ§ Õ´Õ«Õ¡ÖÕ¶Õ¥Õ¬ JavaScript-Õ¨:</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">Ô¿Õ¡Ö€Õ³ Õ¥Õ¦Ö€Õ«Ö Õ½Õ¯Õ½Õ¡Õ®</translation>
<translation id="168693727862418163">Ô¿Õ¡Õ¶Õ¸Õ¶Õ¨ Õ¯Õ¡Õ¶Õ¿Õ¥Õ½Õ¾Õ«, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¤Ö€Õ¡ Õ¡Ö€ÕªÕ¥Ö„Õ¨ Õ¹Õ« Õ°Õ¡Õ´Õ¡ÕºÕ¡Õ¿Õ¡Õ½Õ­Õ¡Õ¶Õ¸Ö‚Õ´ Õ½Õ­Õ¥Õ´Õ¡ÕµÕ«Õ¶Ö‰</translation>
<translation id="168841957122794586">ÕÕ¥Ö€Õ¾Õ¥Ö€Õ« Õ¾Õ¯Õ¡ÕµÕ¡Õ£Õ«Ö€Õ¨ Õ©Õ¸Ö‚ÕµÕ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ£Ö€Õ´Õ¡Õ¶ Õ¢Õ¡Õ¶Õ¡Õ¬Õ« Õ¸Ö‚Õ¶Õ«:</translation>
+<translation id="1696290444144917273">Ô´Õ«Õ¿Õ¥Õ¬ Õ¾Õ«Ö€Õ¿Õ¸Ö‚Õ¡Õ¬ Ö„Õ¡Ö€Õ¿Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨</translation>
<translation id="1697532407822776718">ÕÕ¥Õ²Õ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ´Õ¨ Õ¢Õ¡Ö€Õ¥Õ°Õ¡Õ»Õ¸Õ² Õ¡Õ¾Õ¡Ö€Õ¿Õ¾Õ¡Õ® Õ§:</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Ô±ÕµÕ½ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¨ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡ÖÕ¡Õ¾ Õ¡ÕºÕ¡ÖÕ¸Ö‚ÖÕ¥Õ¬, Õ¸Ö€ Õ«Õ¶Ö„Õ¨ <ph name="DOMAIN" /> Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ¶ Õ§: Ô´Ö€Õ¡ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ¾Õ¡Õ½Õ¿Õ¡Õ£Õ«Ö€Õ¨ Õ¥Õ¶Õ©Õ¡Õ¤Ö€Õ¡Õ¢Õ¡Ö€ Õ¾Õ¡Õ²Õ¾Õ¡Õ¶Õ«Ö Õ¾Õ¡Õ¾Õ¥Ö€ Õ¯Õ¤Õ¡Õ¼Õ¶Õ¡: ÕŠÕ¡Õ¿Õ³Õ¡Õ¼Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¬Õ«Õ¶Õ¥Õ¬ Õ½Õ­Õ¡Õ¬ Õ¯Õ¡Õ¦Õ´Õ¡Õ±Ö‡Õ¸Ö‚Õ´Õ¨ Õ¯Õ¡Õ´ Õ°Õ¡Ö„Õ¥Ö€Õ¡ÕµÕ«Õ¶ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¸Ö‚Õ´Õ¨ Õ±Õ¥Ö€ Õ¯Õ¡ÕºÕ¸Ö‚Õ²Õ¸Ö‚ Õ¦Õ¡Õ¾Õ©Õ´Õ¡Õ´Õ¢ Ö‡ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¬Õ½Õ´Õ¡Õ´Õ¢Ö‰}one{Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¨ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡ÖÕ¡Õ¾ Õ¡ÕºÕ¡ÖÕ¸Ö‚ÖÕ¥Õ¬, Õ¸Ö€ Õ«Õ¶Ö„Õ¨ <ph name="DOMAIN" /> Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ¶ Õ§: Ô´Ö€Õ¡ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ¾Õ¡Õ½Õ¿Õ¡Õ£Õ«Ö€Õ¨ Õ¥Õ¶Õ©Õ¡Õ¤Ö€Õ¡Õ¢Õ¡Ö€ Õ¾Õ¡Õ¾Õ¥Ö€ Õ¯Õ¤Õ¡Õ¼Õ¶Õ¡ # Ö…Ö€ Õ°Õ¥Õ¿Õ¸: ÕŠÕ¡Õ¿Õ³Õ¡Õ¼Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¬Õ«Õ¶Õ¥Õ¬ Õ½Õ­Õ¡Õ¬ Õ¯Õ¡Õ¦Õ´Õ¡Õ±Ö‡Õ¸Ö‚Õ´Õ¨ Õ¯Õ¡Õ´ Õ°Õ¡Ö„Õ¥Ö€Õ¡ÕµÕ«Õ¶ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¸Ö‚Õ´Õ¨ Õ±Õ¥Ö€ Õ¯Õ¡ÕºÕ¸Ö‚Õ²Õ¸Ö‚ Õ¦Õ¡Õ¾Õ©Õ´Õ¡Õ´Õ¢ Ö‡ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¬Õ½Õ´Õ¡Õ´Õ¢Ö‰}other{Ô±ÕµÕ½ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¨ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡ÖÕ¡Õ¾ Õ¡ÕºÕ¡ÖÕ¸Ö‚ÖÕ¥Õ¬, Õ¸Ö€ Õ«Õ¶Ö„Õ¨ <ph name="DOMAIN" /> Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ¶ Õ§: Ô´Ö€Õ¡ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ¾Õ¡Õ½Õ¿Õ¡Õ£Õ«Ö€Õ¨ Õ¥Õ¶Õ©Õ¡Õ¤Ö€Õ¡Õ¢Õ¡Ö€ Õ¾Õ¡Õ¾Õ¥Ö€ Õ¯Õ¤Õ¡Õ¼Õ¶Õ¡ # Ö…Ö€ Õ°Õ¥Õ¿Õ¸: ÕŠÕ¡Õ¿Õ³Õ¡Õ¼Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¬Õ«Õ¶Õ¥Õ¬ Õ½Õ­Õ¡Õ¬ Õ¯Õ¡Õ¦Õ´Õ¡Õ±Ö‡Õ¸Ö‚Õ´Õ¨ Õ¯Õ¡Õ´ Õ°Õ¡Ö„Õ¥Ö€Õ¡ÕµÕ«Õ¶ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¸Ö‚Õ´Õ¨ Õ±Õ¥Ö€ Õ¯Õ¡ÕºÕ¸Ö‚Õ²Õ¸Ö‚ Õ¦Õ¡Õ¾Õ©Õ´Õ¡Õ´Õ¢ Ö‡ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¬Õ½Õ´Õ¡Õ´Õ¢Ö‰}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Ô±Õ¶Õ¿Õ¥Õ½Õ¾Õ¡Õ® Õ§, Ö„Õ¡Õ¶Õ« Õ¸Ö€ <ph name="POLICY_NAME" /> Õ¯Õ¡Õ¶Õ¸Õ¶Õ« Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¾Õ¡Õ® Õ¹Õ§ <ph name="VALUE" /> Õ¡Ö€ÕªÕ¥Ö„Õ¨Ö‰</translation>
<translation id="1712552549805331520"><ph name="URL" /> Õ¯Õ¡ÕµÖ„Õ¶ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ§ Õ±Õ¥Ö€ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¹Õ¸Ö‚Õ´ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€ Õ´Õ·Õ¿Õ¡ÕºÕ¥Õ½ ÕºÕ¡Õ°Õ¥Õ¬</translation>
<translation id="1713628304598226412">Ô´Õ¡Ö€Õ¡Õ¯ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Õ“Õ¸Õ½Õ¿Õ¡Ö€Õ¯Õ² 3</translation>
<translation id="1718029547804390981">Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ§ Õ®Õ¡Õ¶Õ¸Õ©Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬, Ö„Õ¡Õ¶Õ« Õ¸Ö€ ÖƒÕ¡Õ½Õ¿Õ¡Õ©Õ¸Ö‚Õ²Õ©Õ¨ Õ¹Õ¡ÖƒÕ¡Õ¦Õ¡Õ¶Ö Õ´Õ¥Õ® Õ§Ö‰</translation>
<translation id="1721424275792716183">* Ô´Õ¡Õ·Õ¿Õ¨ ÕºÕ¡Ö€Õ¿Õ¡Õ¤Õ«Ö€ Õ§</translation>
+<translation id="1727613060316725209">Õ€Õ¡Õ¾Õ¡Õ½Õ¿Õ¡Õ£Õ«Ö€Õ¨ Õ¾Õ¡Õ¾Õ¥Ö€ Õ§</translation>
<translation id="1727741090716970331">Ô±Õ¾Õ¥Õ¬Õ¡ÖÖ€Õ¥Ö„ Ö„Õ¡Ö€Õ¿Õ« Õ¾Õ¡Õ¾Õ¥Ö€ Õ°Õ¡Õ´Õ¡Ö€</translation>
<translation id="1728677426644403582">Ô´Õ¸Ö‚Ö„ Õ¤Õ«Õ¿Õ¸Ö‚Õ´ Õ¥Ö„ Õ¾Õ¥Õ¢ Õ§Õ»Õ« Õ¯Õ¸Õ¤Õ¨</translation>
<translation id="173080396488393970">Õ”Õ¡Ö€Õ¿Õ« Õ¡ÕµÕ½ Õ¿Õ¥Õ½Õ¡Õ¯Õ¨ Õ¹Õ« Õ¡Õ»Õ¡Õ¯ÖÕ¾Õ¸Ö‚Õ´</translation>
@@ -246,7 +253,6 @@
<ph name="SITE" /> Õ¯Õ¡ÕµÖ„Õ« Õ±Õ¥Ö€ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¨Ö‰ ÕÕ¯Õ¦Õ¢Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¯Õ¡Õ¶Õ¸Õ¶Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¥Õ¬
Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ« Ö…ÕºÕ¥Ö€Õ¡Õ¿Õ¸Ö€Õ¶Õ¥Ö€Õ« Õ¯Õ¸Õ²Õ´Õ«Ö Õ¯Õ¡ÕµÖ„Õ« Õ¿Õ¡Ö€Õ¡Õ¿Õ¥Õ½Õ¡Õ¯ ÕºÕ¡Ö€Õ¡Õ´Õ¥Õ¿Ö€Õ¥Ö€Õ« Ö‡ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Ô¹Õ¡Ö€Õ´Õ¡ÖÖ€Õ¥Ö„ Õ±Õ¥Ö€ Õ°Õ¡Õ´Õ¡ÕªÕ¡Õ´Õ¡ÖÕ´Õ¡Õ¶ Õ¡Õ¶ÖÕ¡Õ¢Õ¡Õ¼Õ¨:</translation>
<translation id="1787142507584202372">ÕÕ¥Ö€ Õ¢Õ¡ÖÕ¾Õ¡Õ® Õ¶Õ¥Ö€Õ¤Õ«Ö€Õ¶Õ¥Ö€Õ¨ Õ¯ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ¥Õ¶ Õ¡ÕµÕ½Õ¿Õ¥Õ²</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />Ö‰ Õ€Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¥Õ¶ Õ¢Õ¡Õ¦Õ´Õ¡Õ©Õ«Õ¾ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Ö‰ Ô´Ö€Õ¡Õ¶Ö„ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„ Tab:</translation>
@@ -279,7 +285,8 @@
<translation id="1919345977826869612">Ô³Õ¸Õ¾Õ¡Õ¦Õ¤</translation>
<translation id="1919367280705858090">ÕˆÖ€Õ¸Õ·Õ¡Õ¯Õ« Õ½Õ­Õ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¾Õ¥Ö€Õ¡ÖÕ´Õ¡Õ¶ Ö…Õ£Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶</translation>
<translation id="192020519938775529">{COUNT,plural, =0{ÕˆÕ¹Õ«Õ¶Õ¹ Õ¹Õ¯Õ¡}=1{1 Õ¯Õ¡ÕµÖ„}one{# Õ¯Õ¡ÕµÖ„}other{# Õ¯Õ¡ÕµÖ„}}</translation>
-<translation id="1945968466830820669">Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§Õ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ±Õ¥Ö€ Õ¯Õ¡Õ¦Õ´Õ¡Õ¯Õ¥Ö€ÕºÕ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ·Õ«Õ¾Õ¨, Õ¯Õ¡Õ´ Õ«Õ¶Õ¹-Õ¸Ö€ Õ´Õ¥Õ¯Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ£Õ¸Õ²Õ¡Õ¶Õ¡Õ¬ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
+<translation id="1924727005275031552">Õ†Õ¸Ö€</translation>
+<translation id="1945968466830820669">Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§Õ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ±Õ¥Ö€ Õ¯Õ¡Õ¦Õ´Õ¡Õ¯Õ¥Ö€ÕºÕ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ·Õ«Õ¾Õ¨, Õ¯Õ¡Õ´ Õ«Õ¶Õ¹-Õ¸Ö€ Õ´Õ¥Õ¯Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ°Õ¡ÖƒÕ·Õ¿Õ¡Õ¯Õ¥Õ¬ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
<translation id="1947454675006758438">Ô±Õ´Ö€Õ¡Õ¯ Õ¾Õ¥Ö€Ö‡Õ« Õ¡Õ» Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´</translation>
<translation id="1958218078413065209">ÕÕ¥Ö€ Õ¬Õ¡Õ¾Õ¡Õ£Õ¸Ö‚ÕµÕ¶ Õ¡Ö€Õ¤ÕµÕ¸Ö‚Õ¶Ö„Õ¨Õ <ph name="SCORE" />Ö‰</translation>
<translation id="1959001866257244765">Õ•Õ£Õ¶Õ¥Ö„ Õ¢Õ¡Ö€Õ±Ö€Õ¡ÖÕ¶Õ¥Õ¬ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ´Õ¡Õ¯Õ¡Ö€Õ¤Õ¡Õ¯Õ¨ Õ°Õ¡Õ´Õ¡ÖÕ¡Õ¶ÖÕ¸Ö‚Õ´Õ Google-Õ«Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬Õ¸Õ¾ <ph name="BEGIN_WHITEPAPER_LINK" />Õ±Õ¥Ö€ Õ¡ÕµÖÕ¥Õ¬Õ¡Õ® Õ¸Ö€Õ¸Õ· Õ§Õ»Õ¥Ö€Õ« Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€Õ¶ Õ¸Ö‚ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Ö‡ Õ¸Ö€Õ¸Õ·Õ¡Õ¯Õ« Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ« Õ´Õ¡Õ½Õ«Õ¶<ph name="END_WHITEPAPER_LINK" />Ö‰ <ph name="BEGIN_PRIVACY_PAGE_LINK" />Ô³Õ¡Õ²Õ¿Õ¶Õ«Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Ö„Õ¡Õ²Õ¡Ö„Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶<ph name="END_PRIVACY_PAGE_LINK" /></translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">Ô´Õ¡Ö€Õ¡Õ¯ 7</translation>
<translation id="204357726431741734">Õ„Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Ö„Õ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´ ÕºÕ¡Õ°Õ¾Õ¡Õ® Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> Õ¬Õ¥Õ¦Õ¾Õ¸Õ¾ Õ§Õ»Õ¥Ö€Õ¨ Õ¹Õ¥Õ¶ Õ©Õ¡Ö€Õ£Õ´Õ¡Õ¶Õ¾Õ«:</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{ÔµÖ€Õ¢ Õ¡ÕµÕ½ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¨ Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§ Ö‡ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯Õ¶ Õ¡Õ¯Õ¿Õ«Õ¾ Õ§, Chrome-Õ¨ Õ¸Ö€Õ¸Õ·Õ¸Ö‚Õ´ Õ§, Õ©Õ¥ Õ¸Ö€ Õ­Õ´Õ¢Õ«Õ¶ Õ¯Õ¡Õ´ «կոհորտին» Õ§ Õ¶Õ´Õ¡Õ¶ Õ±Õ¥Ö€ Õ¾Õ¥Ö€Õ»Õ«Õ¶ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¸Ö‚Õ´Ö‰ Ô³Õ¸Õ¾Õ¡Õ¦Õ¤Õ¡Õ¿Õ¸Ö‚Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ£Õ¸Õ¾Õ¡Õ¦Õ¤Õ¶Õ¥Ö€ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬ Õ­Õ´Õ¢Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰ ÕÕ¥Ö€ Õ¡ÕµÖÕ¥Õ¬Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ£Õ¡Õ²Õ¿Õ« Õ§ ÕºÕ¡Õ°Õ¾Õ¸Ö‚Õ´ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´Ö‰ ÕÕ¥Ö€ Õ­Õ¸Ö‚Õ´Õ¢Õ¶ Õ¡Õ´Õ¥Õ¶ Ö…Ö€ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¾Õ¸Ö‚Õ´ Õ§Ö‰}=1{ÔµÖ€Õ¢ Õ¡ÕµÕ½ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¨ Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§ Ö‡ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯Õ¶ Õ¡Õ¯Õ¿Õ«Õ¾ Õ§, Chrome-Õ¨ Õ¸Ö€Õ¸Õ·Õ¸Ö‚Õ´ Õ§, Õ©Õ¥ Õ¸Ö€ Õ­Õ´Õ¢Õ«Õ¶ Õ¯Õ¡Õ´ «կոհորտին» Õ§ Õ¶Õ´Õ¡Õ¶ Õ±Õ¥Ö€ Õ¾Õ¥Ö€Õ»Õ«Õ¶ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¸Ö‚Õ´Ö‰ Ô³Õ¸Õ¾Õ¡Õ¦Õ¤Õ¡Õ¿Õ¸Ö‚Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ£Õ¸Õ¾Õ¡Õ¦Õ¤Õ¶Õ¥Ö€ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬ Õ­Õ´Õ¢Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰ ÕÕ¥Ö€ Õ¡ÕµÖÕ¥Õ¬Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ£Õ¡Õ²Õ¿Õ« Õ§ ÕºÕ¡Õ°Õ¾Õ¸Ö‚Õ´ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´Ö‰ ÕÕ¥Ö€ Õ­Õ¸Ö‚Õ´Õ¢Õ¶ Õ¡Õ´Õ¥Õ¶ Ö…Ö€ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¾Õ¸Ö‚Õ´ Õ§Ö‰}one{ÔµÖ€Õ¢ Õ¡ÕµÕ½ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¨ Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§ Ö‡ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯Õ¶ Õ¡Õ¯Õ¿Õ«Õ¾ Õ§, Chrome-Õ¨ Õ¸Ö€Õ¸Õ·Õ¸Ö‚Õ´ Õ§, Õ©Õ¥ Õ¸Ö€ Õ­Õ´Õ¢Õ«Õ¶ Õ¯Õ¡Õ´ «կոհորտին» Õ§ Õ¶Õ´Õ¡Õ¶ Õ±Õ¥Ö€ Õ¾Õ¥Ö€Õ»Õ«Õ¶ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¸Ö‚Õ´Ö‰ Ô³Õ¸Õ¾Õ¡Õ¦Õ¤Õ¡Õ¿Õ¸Ö‚Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ£Õ¸Õ¾Õ¡Õ¦Õ¤Õ¶Õ¥Ö€ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬ Õ­Õ´Õ¢Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰ ÕÕ¥Ö€ Õ¡ÕµÖÕ¥Õ¬Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ£Õ¡Õ²Õ¿Õ« Õ§ ÕºÕ¡Õ°Õ¾Õ¸Ö‚Õ´ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´Ö‰ ÕÕ¥Ö€ Õ­Õ¸Ö‚Õ´Õ¢Õ¨ {NUM_DAYS} Ö…Ö€Õ¨ Õ´Õ¥Õ¯ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¾Õ¸Ö‚Õ´ Õ§Ö‰}other{ÔµÖ€Õ¢ Õ¡ÕµÕ½ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¨ Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§ Ö‡ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯Õ¶ Õ¡Õ¯Õ¿Õ«Õ¾ Õ§, Chrome-Õ¨ Õ¸Ö€Õ¸Õ·Õ¸Ö‚Õ´ Õ§, Õ©Õ¥ Õ¸Ö€ Õ­Õ´Õ¢Õ«Õ¶ Õ¯Õ¡Õ´ «կոհորտին» Õ§ Õ¶Õ´Õ¡Õ¶ Õ±Õ¥Ö€ Õ¾Õ¥Ö€Õ»Õ«Õ¶ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¸Ö‚Õ´Ö‰ Ô³Õ¸Õ¾Õ¡Õ¦Õ¤Õ¡Õ¿Õ¸Ö‚Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ£Õ¸Õ¾Õ¡Õ¦Õ¤Õ¶Õ¥Ö€ Õ¨Õ¶Õ¿Ö€Õ¥Õ¬ Õ­Õ´Õ¢Õ« Õ°Õ¡Õ´Õ¡Ö€Ö‰ ÕÕ¥Ö€ Õ¡ÕµÖÕ¥Õ¬Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ£Õ¡Õ²Õ¿Õ« Õ§ ÕºÕ¡Õ°Õ¾Õ¸Ö‚Õ´ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´Ö‰ ÕÕ¥Ö€ Õ­Õ¸Ö‚Õ´Õ¢Õ¨ {NUM_DAYS} Ö…Ö€Õ¨ Õ´Õ¥Õ¯ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¾Õ¸Ö‚Õ´ Õ§Ö‰}}</translation>
<translation id="2053553514270667976">Õ“Õ¸Õ½Õ¿Õ¡ÕµÕ«Õ¶ Õ¤Õ¡Õ½Õ«Õ¹</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 Õ¡Õ¼Õ¡Õ»Õ¡Ö€Õ¯}one{# Õ¡Õ¼Õ¡Õ»Õ¡Ö€Õ¯}other{# Õ¡Õ¼Õ¡Õ»Õ¡Ö€Õ¯}}</translation>
<translation id="2071692954027939183">Ô¾Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¶ Õ¡Õ¾Õ¿Õ¸Õ´Õ¡Õ¿ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¥Õ¬ Õ¥Õ¶, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¤Õ¸Ö‚Ö„ Õ¤Ö€Õ¡Õ¶Ö„ Õ½Õ¸Õ¾Õ¸Ö€Õ¡Õ¢Õ¡Ö€ Õ´Õ¥Ö€ÕªÕ¸Ö‚Õ´ Õ¥Ö„Ö‰</translation>
<translation id="2079545284768500474">Õ€Õ¥Õ¿Õ¡Ö€Õ¯Õ¥Õ¬</translation>
<translation id="20817612488360358">Õ€Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ« ÕºÖ€Õ¸Ö„Õ½Õ«-Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡ÕµÕ¾Õ¡Õ® Õ¥Õ¶, Õ¢Õ¡ÕµÖ Õ¶Õ¡Ö‡ Õ¶Õ·Õ¾Õ¡Õ® Õ§ Õ¶Ö€Õ¡ Õ¸Ö‚Õ²Õ²Õ¡Õ¯Õ« Õ¯Õ¡Õ¦Õ´Õ¡Õ±Ö‡Õ¸Ö‚Õ´:</translation>
<translation id="2082238445998314030"><ph name="RESULT_NUMBER" />-Õ«Ö <ph name="TOTAL_RESULTS" /> Õ¡Ö€Õ¤ÕµÕ¸Ö‚Õ¶Ö„</translation>
+<translation id="2085876078937250610">Պահել…</translation>
<translation id="2088086323192747268">«Կառավարել Õ°Õ¡Õ´Õ¡ÕªÕ¡Õ´Õ¡Öումը» Õ¯Õ¸Õ³Õ¡Õ¯Ö‰ Õ€Õ¡Õ´Õ¡ÕªÕ¡Õ´Õ¡ÖÕ¾Õ¸Õ² Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Chrome-Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´ Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„ EnterÖ‰</translation>
<translation id="2091887806945687916">ÕÕ¡ÕµÕ¶</translation>
<translation id="2094505752054353250">ÕÕ«Ö€Õ¸Ö‚ÕµÕ©Õ« Õ¡Õ¶Õ°Õ¡Õ´Õ¡ÕºÕ¡Õ¿Õ¡Õ½Õ­Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶</translation>
@@ -350,7 +359,7 @@
<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="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>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ¨ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¸Ö‚Õ´ Õ§ Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶ Ö‡ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼:</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, Õ¾Õ¡Õ¾Õ¥Ö€ Õ§ Õ´Õ«Õ¶Õ¹Ö‡ <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¨ Õ¾Õ¥Ö€Õ¡Õ°Õ½Õ¯Õ¾Õ¸Ö‚Õ´ Õ§ Õ±Õ¥Ö€ Õ¡Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€Õ« Õ¯Õ¸Õ²Õ´Õ«Ö</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> Õ¯Õ¡ÕµÖ„Õ¶ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ§ Õ¦Õ¸Ö‚Õ£Õ¡Õ¯ÖÕ¾Õ¥Õ¬</translation>
<translation id="2344028582131185878">Ô±Õ¾Õ¿Õ¸Õ´Õ¡Õ¿ Õ¶Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¸Ö‚Õ´Õ¶Õ¥Ö€</translation>
<translation id="2346319942568447007">ÕÕ¥Ö€ ÕºÕ¡Õ¿Õ³Õ¥Õ¶Õ¡Õ® ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¨</translation>
<translation id="2354001756790975382">Ô±ÕµÕ¬ Õ§Õ»Õ¡Õ¶Õ«Õ·Õ¶Õ¥Ö€</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">Õ€Õ¡Ö€Õ±Õ¡Õ¯Õ¾Õ¸Õ²Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ¨, Õ¸Ö€Õ¸Õ¶Ö„ Õ¤Õ«Õ¿Õ¸Ö‚Õ´ Õ¥Ö„, Ö‡ Õ­Õ¡Õ¢Õ¥Õ¬ Õ±Õ¥Õ¦` Õ¤Ö€Õ¡Õ¶Ö„ Õ±Ö‡Õ¡ÖƒÕ¸Õ­Õ¥Õ¬Õ¸Õ¾:</translation>
<translation id="2356070529366658676">Õ€Õ¡Ö€ÖÕ¶Õ¥Õ¬</translation>
<translation id="2357481397660644965">ÕÕ¥Ö€ Õ½Õ¡Ö€Ö„Õ¨ Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¾Õ¸Ö‚Õ´ Õ§ <ph name="DEVICE_MANAGER" />-Õ« Õ¯Õ¸Õ²Õ´Õ«Ö, Õ«Õ½Õ¯ Õ±Õ¥Ö€ Õ°Õ¡Õ·Õ«Õ¾Õ¨Õ <ph name="ACCOUNT_MANAGER" />-Õ« Õ¯Õ¸Õ²Õ´Õ«Ö:</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Õ„Õ«Õ¶Õ¹Ö‡ Õ´Õ¥Õ¯ Ö…Ö€Õ¾Õ¡ Õ¨Õ¶Õ©Õ¡ÖÖ„Õ¸Ö‚Õ´}=1{Õ„Õ¥Õ¯ Ö…Ö€Õ«Ö}one{{NUM_DAYS} Ö…Ö€Õ«Ö}other{{NUM_DAYS} Ö…Ö€Õ«Ö}}</translation>
<translation id="2359629602545592467">Õ„Õ« Ö„Õ¡Õ¶Õ«</translation>
<translation id="2359808026110333948">Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬</translation>
+<translation id="2359961752320758691">Ô¿Õ«Ö€Õ¡Õ¼Õ¾Õ¥Õ¬ Õ§ Õ±Õ¥Ö€ Õ¾Õ«Ö€Õ¿Õ¸Ö‚Õ¡Õ¬ Ö„Õ¡Ö€Õ¿Õ« Õ°Õ¡Õ´Õ¡Ö€Õ¨Ö‰</translation>
<translation id="2367567093518048410">Õ„Õ¡Õ¯Õ¡Ö€Õ¤Õ¡Õ¯</translation>
<translation id="2372464001869762664">Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´Õ«Ö Õ°Õ¥Õ¿Õ¸ Õ±Õ¥Ö€ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´ Õ¶Õ·Õ¾Õ¡Õ® Ö„Õ¡Ö€Õ¿Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¯ÖƒÕ¸Õ­Õ¡Õ¶ÖÕ¾Õ¥Õ¶ Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ«Õ¶Ö‰ CVC Õ¯Õ¸Õ¤Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ Õ£Õ¿Õ¶Õ¥Õ¬ Plex Õ°Õ¡Õ·Õ¾Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¸Ö‚Õ´Ö‰</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ´Õ¡Õ¶ Õ¡ÕµÕ½ Õ¥Õ²Õ¡Õ¶Õ¡Õ¯Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ§: Õ“Õ¸Ö€Õ±Õ¥Ö„ Õ¡ÕµÕ¬ Õ¥Õ²Õ¡Õ¶Õ¡Õ¯:</translation>
<translation id="2396249848217231973">&amp;Õ€Õ¥Õ¿Õ¡Ö€Õ¯Õ¥Õ¬ Õ»Õ¶Õ»Õ¸Ö‚Õ´Õ¨</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Õ€Õ«Õ¶</translation>
<translation id="2413528052993050574">Ô±ÕµÕ½ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¨ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ¡ÕºÕ¡ÖÕ¸Ö‚ÖÕ¥Õ¬, Õ¸Ö€ <ph name="DOMAIN" /> Õ§: Ô´Ö€Õ¡ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¾Õ¯Õ¡ÕµÕ¡Õ¯Õ¡Õ¶Õ¨, Õ°Õ¡Õ¾Õ¡Õ¶Õ¡Õ¢Õ¡Ö€, Õ°Õ¥Õ¿ Õ§ Õ¯Õ¡Õ¶Õ¹Õ¾Õ¥Õ¬: ÕŠÕ¡Õ¿Õ³Õ¡Õ¼Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¬Õ«Õ¶Õ¥Õ¬ Õ½Õ­Õ¡Õ¬ Õ¯Õ¡Õ¦Õ´Õ¡Õ±Ö‡Õ¸Ö‚Õ´Õ¨ Õ¯Õ¡Õ´ Õ¯Õ¡ÕºÕ¡Õ¯ÖÕ´Õ¡Õ¶ Õ­Õ¡ÖƒÕ¡Õ¶Õ¸Ö‚Õ´Õ¨ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¾Õ¸Õ²Õ« Õ¯Õ¸Õ²Õ´Õ«Ö:</translation>
<translation id="2414886740292270097">Õ„Õ¸Ö‚Õ£</translation>
<translation id="2438874542388153331">Õ‰Õ¸Ö€Õ½ Õ¡Õ¶ÖÖ„ Õ¡Õ» Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">Ô±Õ´Ö€Õ¡Õ¯ Õ¶Õ¥Ö€Ö„Ö‡Õ« Õ¡Õ» Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´</translation>
<translation id="2523886232349826891">Ô¿ÕºÕ¡Õ°Õ¾Õ« Õ´Õ«Õ¡ÕµÕ¶ Õ¡ÕµÕ½ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´</translation>
<translation id="2524461107774643265">Ô±Õ¾Õ¥Õ¬Õ¡ÖÖ€Õ¥Ö„ Õ¬Ö€Õ¡ÖÕ¸Ö‚ÖÕ«Õ¹ Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€</translation>
-<translation id="2526590354069164005">Ô±Õ·Õ­Õ¡Õ¿Õ¡Õ½Õ¥Õ²Õ¡Õ¶</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{Õ¸Ö‚ Ö‡Õ½ 1 Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©}one{Õ¸Ö‚ Ö‡Õ½ # Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©}other{Õ¸Ö‚ Ö‡Õ½ # Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©}}</translation>
<translation id="2536110899380797252">Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ½ÖÕ¥</translation>
<translation id="2539524384386349900">ÕƒÕ¡Õ¶Õ¡Õ¹Õ¥Õ¬</translation>
+<translation id="2541219929084442027">Ô²Õ¸Õ¬Õ¸Ö€ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¶Õ¥Ö€Õ¤Õ«Ö€Õ¶Õ¥Ö€Õ¨ ÖƒÕ¡Õ¯Õ¥Õ¬Õ¸Ö‚Ö Õ°Õ¥Õ¿Õ¸ Õ¤Õ«Õ¿Õ¾Õ¡Õ® Õ§Õ»Õ¥Ö€Õ¨ Õ¹Õ¥Õ¶ ÕºÕ¡Õ°Õ¾Õ¸Ö‚Õ´ Õ±Õ¥Ö€ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ« ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¡Õ¶, Ö„Õ¸Ö‚Ö„Õ«Õ¶Õ¥Ö€Õ« ÕºÕ¡Õ°Õ¸ÖÕ« Õ¯Õ¡Õ´ Õ¸Ö€Õ¸Õ¶Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ´Õ¥Õ»Ö‰ Õ†Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Õ´ Õ½Õ¿Õ¥Õ²Õ®Õ¡Õ® Õ§Õ»Õ¡Õ¶Õ«Õ·Õ¶Õ¥Ö€Õ¨ Õ¯ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ¾Õ¥Õ¶Ö‰</translation>
<translation id="2544644783021658368">Õ„Õ¥Õ¯ ÖƒÕ¡Õ½Õ¿Õ¡Õ©Õ¸Ö‚Õ²Õ©</translation>
<translation id="254947805923345898">Ô¿Õ¡Õ¶Õ¸Õ¶Õ¸Ö‚Õ´ Õ¶Õ·Õ¾Õ¡Õ® Õ¡Ö€ÕªÕ¥Ö„Õ¶ Õ¡Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ§Ö‰</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" />-Õ¨ Õ½Õ­Õ¡Õ¬ ÕºÕ¡Õ¿Õ¡Õ½Õ­Õ¡Õ¶ Õ§ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬:</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Chrome-Õ« Õ¬Õ¡Õ¾Õ¡Õ£Õ¸Ö‚ÕµÕ¶ ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¥Ö€Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />Õ´Õ«Õ¡ÖÖ€Õ¥Ö„ Õ¬Ö€Õ¡ÖÕ¸Ö‚ÖÕ«Õ¹ ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ£Õ¿Õ¶Õ¥Õ¬ <ph name="HOST_NAME" /> Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ« Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« IP Õ°Õ¡Õ½ÖÕ¥Õ¶Ö‰</translation>
<translation id="2639739919103226564">Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ«Õ³Õ¡Õ¯`</translation>
+<translation id="264810637653812429">Õ€Õ¡Õ´Õ¡Õ¿Õ¥Õ²Õ¥Õ¬Õ« Õ½Õ¡Ö€Ö„Õ¥Ö€ Õ¹Õ¥Õ¶ Õ£Õ¿Õ¶Õ¾Õ¥Õ¬:</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />Ö‰ Chrome-Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´ Õ¡ÕµÖÕ¥Õ¬Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨, Ö„Õ¸Ö‚Ö„Õ«Õ¶Õ¥Ö€Õ¨, Ö„Õ¥Õ·Õ¨ Ö‡ Õ¡ÕµÕ¬ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€ Õ»Õ¶Õ»Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„ Tab, Õ¡ÕºÕ¡Õ EnterÖ‰</translation>
<translation id="2650446666397867134">Õ–Õ¡ÕµÕ¬Õ« Õ´Õ¡Õ¿Õ¹Õ¸Ö‚Õ´Õ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¾Õ¡Õ® Õ§</translation>
@@ -494,13 +508,16 @@
<translation id="2799223571221894425">ÕŽÕ¥Ö€Õ¡Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¥Õ¬</translation>
<translation id="2803306138276472711">ÕŽÕ¥Ö€Õ»Õ¥Ö€Õ½ Google Safe Browsing-Õ¨ <ph name="BEGIN_LINK" />Õ¾Õ¶Õ¡Õ½Õ¡Õ£Õ«Ö€ Õ§ Õ°Õ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥Ö€Õ¥Õ¬<ph name="END_LINK" /> <ph name="SITE" /> Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´: Õ†Õ¸Ö‚ÕµÕ¶Õ«Õ½Õ¯ Õ¡ÕºÕ¡Õ°Õ¸Õ¾ Õ¾Õ¥Õ¢Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ¨ Õ¥Ö€Õ¢Õ¥Õ´Õ¶ Õ¾Õ¶Õ¡Õ½Õ¾Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¾Õ¶Õ¡Õ½Õ¡Õ£Ö€Õ¥Ö€Õ¸Õ¾:</translation>
<translation id="2807052079800581569">ÕŠÕ¡Õ¿Õ¯Õ¥Ö€Õ« Õ¤Õ«Ö€Ö„Õ¨ Y Õ¡Õ¼Õ¡Õ¶ÖÖ„Õ¸Õ¾</translation>
+<translation id="2820957248982571256">Որոնում…</translation>
<translation id="2824775600643448204">Õ€Õ¡Õ½ÖÕ¥Õ¡Õ£Õ¸Õ¿Õ« Ö‡ Õ¸Ö€Õ¸Õ¶Õ´Õ¡Õ¶ Õ£Õ¸Õ¿Õ«</translation>
<translation id="2826760142808435982">Ô¿Õ¡ÕºÕ¡Õ¯ÖÕ¸Ö‚Õ´Õ¨ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ£Ö€Õ¾Õ¡Õ® Ö‡ Õ½Õ¿Õ¸Ö‚Õ£Õ¾Õ¡Õ® Õ§ <ph name="CIPHER" />-Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾: ÕˆÖ€ÕºÕ¥Õ½ Õ¢Õ¡Õ¶Õ¡Õ¬Õ«Õ¶Õ¥Ö€Õ« ÖƒÕ¸Õ­Õ¡Õ¶Õ¡Õ¯Õ´Õ¡Õ¶ Õ´Õ¥Õ­Õ¡Õ¶Õ«Õ¦Õ´ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¸Ö‚Õ´ Õ§ <ph name="KX" />-Õ¨:</translation>
<translation id="2835170189407361413">Õ„Õ¡Ö„Ö€Õ¥Õ¬ Õ±Ö‡Õ¡Õ©Õ¸Ö‚Õ²Õ©Õ¨</translation>
<translation id="2839501879576190149">Ô¿Õ¡ÕµÖ„Õ¨, Õ¸Ö€Õ¨ ÕºÕ¡Õ¿Ö€Õ¡Õ½Õ¿Õ¾Õ¸Ö‚Õ´ Õ¥Ö„ Õ¡ÕµÖÕ¥Õ¬Õ¥Õ¬, Õ¯Õ¥Õ²Õ® Õ§</translation>
<translation id="2850739647070081192">Invite (Õ®Ö€Õ¡Ö€)</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="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="2859806420264540918">Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¨ Õ°Õ¸Õ£Õ¶Õ¥ÖÕ¶Õ¸Õ² Õ¯Õ¡Õ´ Õ´Õ¸Õ¬Õ¸Ö€Õ¥ÖÕ¶Õ¸Õ² Õ£Õ¸Õ¾Õ¡Õ¦Õ¤ Õ§ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ´Ö‰</translation>
+<translation id="287596039013813457">Ô¸Õ¶Õ¯Õ¥Ö€Õ¡Õ¯Õ¡Õ¶</translation>
+<translation id="2876489322757410363">Ô´Õ¸Ö‚Ö„ Õ¤Õ¸Ö‚Ö€Õ½ Õ¯Õ£Õ¡Ö„ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ«ÖÕ Õ¡Ö€Õ¿Õ¡Ö„Õ«Õ¶ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¸Ö‚Õ´ Õ¾Õ³Õ¡Ö€Õ¸Ö‚Õ´ Õ¯Õ¡Õ¿Õ¡Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥ÕžÕ¬Ö‰</translation>
<translation id="2878197950673342043">Ô¿Ö€Õ¯Õ¶Õ¡Õ¯Õ« Õ¸Ö‚Õ²Õ²Õ¡Õ±Õ«Õ£ Õ®Õ¡Õ¬Õ¸Ö‚Õ´</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ÕŠÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¶Õ¥Ö€Õ« Õ¿Õ¥Õ²Õ¡Õ¯Õ¡ÕµÕ¸Ö‚Õ´</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (Õ®Ö€Õ¡Ö€)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome-Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ½Õ¿Õ¸Ö‚Õ£Õ¸Ö‚Õ´ Õ¡Õ¶ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„ «Tab», Õ¡ÕºÕ¡Õ Â«Enter»։</translation>
<translation id="3061707000357573562">Ô½Õ¸ÖÕ¥Õ¬Õ«Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ·Õ¿Õ¯Õ¸Ö‚Õ´</translation>
-<translation id="3064966200440839136">Ô´Õ¸Ö‚Ö„ Õ¤Õ¸Ö‚Ö€Õ½ Õ¯Õ£Õ¡Ö„ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ«ÖÕ Õ¡Ö€Õ¿Õ¡Ö„Õ«Õ¶ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¸Ö‚Õ´ Õ¾Õ³Õ¡Ö€Õ¸Ö‚Õ´ Õ¯Õ¡Õ¿Õ¡Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥ÕžÕ¬Ö‰</translation>
<translation id="306573536155379004">Ô½Õ¡Õ²Õ¨ Õ½Õ¯Õ½Õ¾Õ¡Õ® Õ§Ö‰</translation>
<translation id="3080254622891793721">Ô³Ö€Õ¡Ö†Õ«Õ¯Õ¡</translation>
<translation id="3086579638707268289">ÕÕ¥Ö€ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ°Õ¡Õ´Õ¡ÖÕ¡Õ¶ÖÕ¸Ö‚Õ´ Õ°Õ¥Õ¿Õ¡Õ£Õ®Õ¾Õ¸Ö‚Õ´ Õ¥Õ¶</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">ÕÕ¥Ö€ Õ°Õ¡Õ·Õ«Õ¾Õ¨ ÕºÕ¡Õ¿Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ§ <ph name="MANAGER" />-Õ«Õ¶:</translation>
<translation id="3157931365184549694">ÕŽÕ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¥Õ¬</translation>
<translation id="3162559335345991374">Ô±Õ¶Õ¬Õ¡Ö€ Õ¯Õ¡ÕºÕ¨, Õ¸Ö€Õ«Ö Ö…Õ£Õ¿Õ¾Õ¸Ö‚Õ´ Õ¥Ö„, Õ¯Õ¡Ö€Õ¸Õ² Õ§ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¥Õ¬, Õ¸Ö€ÕºÕ¥Õ½Õ¦Õ« Õ¤Õ¸Ö‚Ö„ Õ¡ÕµÖÕ¥Õ¬Õ¥Ö„ Õ¶Ö€Õ¡ Õ´Õ¸Ö‚Õ¿Ö„Õ« Õ§Õ»Õ¨:</translation>
-<translation id="3167968892399408617">Ô»Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ¸Ö‚Õ´ Õ¤Õ«Õ¿Õ¾Õ¸Õ² Õ§Õ»Õ¥Ö€Õ¨ Õ¹Õ¥Õ¶ Õ´Õ¶Õ¡ Õ±Õ¥Ö€ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ« ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¡Õ¶, Ö„Õ¸Ö‚Ö„Õ«Õ¶Õ¥Ö€Õ« ÕºÕ¡Õ°Õ¥Õ½Õ¿Õ« Õ¯Õ¡Õ´ Õ¸Ö€Õ¸Õ¶Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ´Õ¥Õ»Õ Õ¢Õ¸Õ¬Õ¸Ö€ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¶Õ¥Ö€Õ¤Õ«Ö€Õ¶Õ¥Ö€Õ¨ ÖƒÕ¡Õ¯Õ¥Õ¬Õ¸Ö‚Ö Õ°Õ¥Õ¿Õ¸: Ô²Õ¸Õ¬Õ¸Ö€ Õ¶Õ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Õ´ Õ½Õ¿Õ¥Õ²Õ®Õ¡Õ® Õ§Õ»Õ¡Õ¶Õ«Õ·Õ¶Õ¥Ö€Õ¨ Õ¯ÕºÕ¡Õ°ÕºÕ¡Õ¶Õ¾Õ¥Õ¶:</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ô¿Õ²Õ¦Õ«</translation>
<translation id="3176929007561373547">ÕÕ¿Õ¸Ö‚Õ£Õ¥Ö„ Õ±Õ¥Ö€ Õ´Õ«Õ»Õ¶Õ¸Ö€Õ¤ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Õ´ Õ¯Õ¡ÕºÕ¾Õ¥Ö„
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">ÕÕ¥Ö€ Õ½Õ¡Ö€Ö„Õ« Ö‡ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ« Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ« Õ´Õ¡Õ½Õ«Õ¶ Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨</translation>
<translation id="323107829343500871">Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Ö„ <ph name="CREDIT_CARD" /> Ö„Õ¡Ö€Õ¿Õ« CVC Õ¯Õ¸Õ¤Õ¨</translation>
<translation id="3234666976984236645">Õ„Õ«Õ·Õ¿ Õ°Õ¡Õ¿Õ¯Õ¸Ö€Õ¸Õ·Õ¥Õ¬ Õ¯Õ¡Ö€Ö‡Õ¸Ö€ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´</translation>
+<translation id="3249845759089040423">Õ†Õ¸Ö€Õ¡Õ±Ö‡</translation>
<translation id="3252266817569339921">Õ–Ö€Õ¡Õ¶Õ½Õ«Õ¡Õ¯Õ¡Õ¶</translation>
<translation id="3266793032086590337">Ô±Ö€ÕªÕ¥Ö„Õ¨ (Õ°Õ¡Õ¯Õ¡Õ½Õ¡Õ¯Õ¡Õ¶)</translation>
<translation id="3268451620468152448">Ô²Õ¡Ö Õ¶Õ¥Ö€Õ¤Õ«Ö€Õ¶Õ¥Ö€Õ¨</translation>
<translation id="3270847123878663523">&amp;Õ€Õ¥Õ¿Õ¡Ö€Õ¯Õ¥Õ¬ Õ¾Õ¥Ö€Õ¡Õ¤Õ¡Õ½Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¨</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> Õ¯Õ¡ÕµÖ„Õ¨ ÖÕ¡Õ¶Õ¯Õ¡Õ¶Õ¸Ö‚Õ´ Õ§ Õ´Õ«Õ¡Õ¶Õ¡Õ¬</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">ÕÕ¥Ö€ Õ¯Õ¡Õ¦Õ´Õ¡Õ¯Õ¥Ö€ÕºÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ (<ph name="ENROLLMENT_DOMAIN" />) Õ°Õ¥Õ¿Ö‡ÕµÕ¡Õ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ§ Õ¸Ö€Õ¸Õ· Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€, Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€ Ö‡ Õ¯Õ¡Õ¶Õ¸Õ¶Õ¶Õ¥Ö€Ö‰</translation>
<translation id="3282497668470633863">Ô±Õ¾Õ¥Õ¬Õ¡ÖÖ€Õ¥Ö„ Ö„Õ¡Ö€Õ¿Õ¡ÕºÕ¡Õ¶Õ« Õ¡Õ¶Õ¸Ö‚Õ¶Õ¨</translation>
@@ -655,6 +672,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates Õ¯Õ¡Õ¶Õ¸Õ¶Õ« Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ±Ö‡Õ¡Õ¶Õ´Õ¸Ö‚Õ·Õ¶Õ¥Ö€Õ« URI-Õ¶Õ¥Ö€Õ«Ö Õ¡Õ¼Õ¶Õ¾Õ¡Õ¦Õ¶ Õ´Õ¥Õ¯Õ¶ Õ¡Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ§ Ö‡ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¥Õ¬:</translation>
<translation id="3431636764301398940">ÕŠÕ¡Õ°Õ¥Õ¬ Ö„Õ¡Ö€Õ¿Õ¶ Õ¡ÕµÕ½ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´</translation>
<translation id="3432601291244612633">Õ“Õ¡Õ¯Õ¥Õ¬ Õ§Õ»Õ¨</translation>
+<translation id="3435738964857648380">Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶</translation>
<translation id="3435896845095436175">Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬</translation>
<translation id="3438829137925142401">Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Ö„ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´ ÕºÕ¡Õ°Õ¾Õ¡Õ® Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@
<translation id="3584299510153766161">ÔµÖ€Õ¯Õ¸Ö‚ Õ¡Õ¶ÖÖ„ Õ¶Õ¥Ö€Ö„Ö‡Õ¸Ö‚Õ´</translation>
<translation id="3586931643579894722">Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ Õ´Õ¡Õ¶Ö€Õ¡Õ´Õ¡Õ½Õ¶Õ¥Ö€Õ¨</translation>
<translation id="3587738293690942763">Õ„Õ«Õ»Õ«Õ¶</translation>
+<translation id="3590643883886679995">Õ„Õ¸Ö‚Õ¿Ö„Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¯ÕºÕ¡Õ°Õ¾Õ¥Õ¶ Õ¡ÕµÕ½ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´, Õ¥Ö€Õ¢ Õ¤Õ¸Ö‚Ö„ Õ¤Õ¸Ö‚Ö€Õ½ Õ£Õ¡Ö„ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ«ÖÖ‰</translation>
+<translation id="359126217934908072">Ô±Õ´Õ«Õ½/Õ¿Õ¡Ö€Õ«Õ</translation>
<translation id="3592413004129370115">Italian (Õ®Ö€Õ¡Ö€)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Ô´Õ¸Ö‚Ö„ ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ Õ¦Ö€Õ¸ÕµÕ¡ÖÕ¶Õ¥Õ¬ Õ±Õ¥Ö€ Õ­Õ´Õ¢Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ´Õ¢Õ«Õ¶ Õ´Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ´Õ¸Õ¿ Õ´Õ¥Õ¯ Ö…Ö€ Õ§ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¾Õ¸Ö‚Õ´Ö‰}=1{Ô´Õ¸Ö‚Ö„ ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ Õ¦Ö€Õ¸ÕµÕ¡ÖÕ¶Õ¥Õ¬ Õ±Õ¥Ö€ Õ­Õ´Õ¢Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ´Õ¢Õ«Õ¶ Õ´Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ´Õ¸Õ¿ Õ´Õ¥Õ¯ Ö…Ö€ Õ§ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¾Õ¸Ö‚Õ´Ö‰}one{Ô´Õ¸Ö‚Ö„ ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ Õ¦Ö€Õ¸ÕµÕ¡ÖÕ¶Õ¥Õ¬ Õ±Õ¥Ö€ Õ­Õ´Õ¢Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ´Õ¢Õ«Õ¶ Õ´Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ´Õ¸Õ¿ {NUM_DAYS} Ö…Ö€ Õ§ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¾Õ¸Ö‚Õ´Ö‰}other{Ô´Õ¸Ö‚Ö„ ÖÕ¡Õ¶Õ¯Õ¡ÖÕ¡Õ® ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ Õ¦Ö€Õ¸ÕµÕ¡ÖÕ¶Õ¥Õ¬ Õ±Õ¥Ö€ Õ­Õ´Õ¢Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ´Õ¢Õ«Õ¶ Õ´Õ«Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ´Õ¸Õ¿ {NUM_DAYS} Ö…Ö€ Õ§ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¾Õ¸Ö‚Õ´Ö‰}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">ÕÕ¥Ö€ Õ¡Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€Õ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ§ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨</translation>
<translation id="3608932978122581043">Õ†Õ·Õ¥Õ¬ Õ¤Õ«Ö€Ö„Õ¨</translation>
@@ -706,13 +727,13 @@
<translation id="3615877443314183785">Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Ö„ Õ½ÕºÕ¡Õ¼Õ´Õ¡Õ¶ Õ¾Õ¡Õ¾Õ¥Ö€ Õ¡Õ´Õ½Õ¡Õ©Õ«Õ¾</translation>
<translation id="36224234498066874">Õ‹Õ¶Õ»Õ¥Õ¬ Õ¡ÕµÖÕ¥Õ¬Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨...</translation>
<translation id="362276910939193118">Õ‘Õ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬ Õ¡Õ´Õ¢Õ¸Õ²Õ» ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨</translation>
-<translation id="3625635938337243871">Õ„Õ¸Ö‚Õ¿Ö„Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¯ÕºÕ¡Õ°Õ¾Õ¥Õ¶ Õ¡ÕµÕ½ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´, Õ¥Ö€Õ¢ Õ¤Õ¸Ö‚Ö„ Õ¤Õ¸Ö‚Ö€Õ½ Õ£Õ¡Ö„ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ«ÖÖ‰</translation>
<translation id="3630155396527302611">ÔµÕ©Õ¥ Õ¡ÕµÕ¶ Õ¡Ö€Õ¤Õ¥Õ¶ Õ¶Õ·Õ¾Õ¡Õ® Õ§ Õ¸Ö€ÕºÕ¥Õ½ ÖÕ¡Õ¶ÖÕ«Õ¶ Õ¯Õ¡ÕºÕ¡Õ¯ÖÕ¾Õ¥Õ¬Õ¸Ö‚ Õ©Õ¸Ö‚ÕµÕ¬Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¸Ö‚Õ¶Õ¥ÖÕ¸Õ² Õ®Ö€Õ¡Õ£Õ«Ö€, ÖƒÕ¸Ö€Õ±Õ¥Ö„
Õ°Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ¡ÕµÕ¶ Ö‡ Õ¶Õ¸Ö€Õ«Ö Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬:</translation>
<translation id="3630699740441428070">Ô±ÕµÕ½ Õ½Õ¡Ö€Ö„Õ« Õ¡Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¥Õ¬ Õ¥Õ¶ Õ±Õ¥Ö€ ÖÕ¡Õ¶ÖÕ¡ÕµÕ«Õ¶ Õ¯Õ¡ÕºÕ¨, Õ«Õ¶Õ¹Õ« Õ·Õ¶Õ¸Ö€Õ°Õ«Õ¾ Õ¶Ö€Õ¡Õ¶Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¿Õ¥Õ½Õ¶Õ¥Õ¬ Õ±Õ¥Ö€ ÖÕ¡Õ¶ÖÕ« Õ©Ö€Õ¡Ö†Õ«Õ¯Õ¨, Õ¡ÕµÕ¤ Õ©Õ¾Õ¸Ö‚Õ´Õ Õ±Õ¥Ö€ Õ¡ÕµÖÕ¥Õ¬Õ¡Õ® Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ¨Ö‰</translation>
<translation id="3631244953324577188">Ô¿Õ¥Õ¶Õ½Õ¡Õ¹Õ¡ÖƒÕ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¥Ö€</translation>
<translation id="3633738897356909127">«ԹարմաÖÕ¶Õ¥Õ¬ Chrome-ը» Õ¯Õ¸Õ³Õ¡Õ¯Ö‰ ÕÕ¥Õ²Õ´Õ¥Ö„ EnterÕ Chrome-Õ¨ Õ©Õ¡Ö€Õ´Õ¡ÖÕ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰</translation>
<translation id="3634530185120165534">Ô´Õ¡Ö€Õ¡Õ¯ 5</translation>
+<translation id="3637662659967048211">ÕŠÕ¡Õ°Õ¥Ö„ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Ô¾Ö€Õ¡Õ£Õ«Ö€Õ¨Õ</translation>
<translation id="3650584904733503804">ÕŽÕ¡Õ¾Õ¥Ö€Õ¡ÖÕ¸Ö‚Õ´Õ¨ Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö</translation>
@@ -753,6 +774,7 @@
<translation id="3781428340399460090">ÕŽÕ¡Õ¼ Õ¾Õ¡Ö€Õ¤Õ¡Õ£Õ¸Ö‚ÕµÕ¶</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth Õ½Õ¡Ö€Ö„Õ¥Ö€</translation>
+<translation id="3787675388804467730">ÕŽÕ«Ö€Õ¿Õ¸Ö‚Õ¡Õ¬ Ö„Õ¡Ö€Õ¿Õ« Õ°Õ¡Õ´Õ¡Ö€Õ¨</translation>
<translation id="3787705759683870569">ÕÕºÕ¡Õ¼Õ´Õ¡Õ¶ ÕªÕ¡Õ´Õ¯Õ¥Õ¿Õ¨Õ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Õ‰Õ¡Öƒ 16</translation>
<translation id="3789841737615482174">ÕÕ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬</translation>
@@ -772,6 +794,7 @@
<translation id="3841184659773414994">Õ–Õ¡ÕµÕ¬Õ¥Ö€Õ« Õ´Õ·Õ¡Õ¯Õ«Õ¹Õ¶Õ¥Ö€</translation>
<translation id="385051799172605136">Õ€Õ¥Õ¿</translation>
<translation id="3858027520442213535">Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Õ¡Õ´Õ½Õ¡Õ©Õ«Õ¾Õ¨ Ö‡ ÕªÕ¡Õ´Õ¨</translation>
+<translation id="3881478300875776315">Õ‘Õ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬ Õ¡Õ¾Õ¥Õ¬Õ« Ö„Õ«Õ¹ Õ¿Õ¸Õ²Õ¥Ö€</translation>
<translation id="3884278016824448484">ÕÕ¡Ö€Ö„Õ¥Ö€Õ« Õ¶Õ¸Ö‚ÕµÕ¶Õ¡ÖÕ¸Ö‚ÖÕ«Õ¹Õ¶Õ¥Ö€Õ« Õ¨Õ¶Õ¤Õ°Õ¡Ö€Õ¸Ö‚Õ´</translation>
<translation id="3885155851504623709">Ô¾Õ¸Ö‚Õ­</translation>
<translation id="388632593194507180">Õ„Õ«Õ¡ÖÕ¸Ö‚Õ´Õ¨ Õ¾Õ¥Ö€Õ¡Õ°Õ½Õ¯Õ¾Õ¸Ö‚Õ´ Õ§</translation>
@@ -797,6 +820,7 @@
<translation id="397105322502079400">Հաշվարկում…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" />-Õ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ§</translation>
<translation id="3973357910713125165">«ԱնÖÕ¶Õ¥Õ¬ Chrome-Õ« Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ ստուգում» Õ¯Õ¸Õ³Õ¡Õ¯Ö‰ Chrome-Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ½Õ¿Õ¸Ö‚Õ£Õ¸Ö‚Õ´ Õ¡Õ¶ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„ «Enter»։</translation>
+<translation id="3986705137476756801">Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ Ô¿Õ¥Õ¶Õ¤Õ¡Õ¶Õ« Õ¥Õ¶Õ©Õ¡Õ£Ö€Õ¥Ö€Õ¨</translation>
<translation id="3987405730340719549">Chrome-Õ¨ Õ°Õ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥Ö€Õ¥Õ¬ Õ§, Õ¸Ö€ Õ½Õ¡ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¯Õ¥Õ²Õ® Õ¯Õ¡Õ´ Õ´Õ¸Õ¬Õ¸Ö€Õ¥ÖÕ¶Õ¸Õ² Õ¯Õ¡ÕµÖ„ Õ¬Õ«Õ¶Õ¥Õ¬:
ÔµÕ©Õ¥ Õ¯Õ¡Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„, Õ¸Ö€ Õ½Õ¡ Õ½Õ­Õ¡Õ¬Õ´Õ¸Ö‚Õ¶Ö„ Õ§, Õ¡ÕµÖÕ¥Õ¬Õ¥Ö„ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals Õ§Õ»Ö‰</translation>
@@ -893,13 +917,14 @@
<translation id="4275830172053184480">ÕÕ¡Ö€Ö„Õ« Õ¾Õ¥Ö€Õ¡Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¸Ö‚Õ´:</translation>
<translation id="4277028893293644418">Õ“Õ¸Õ­Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Õ”Õ¡Ö€Õ¿Õ¨ ÕºÕ¡Õ°Õ¾Õ¥Ö Õ±Õ¥Ö€ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´}one{Õ”Õ¡Ö€Õ¿Õ¨ ÕºÕ¡Õ°Õ¾Õ¥Ö Õ±Õ¥Ö€ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´}other{Õ”Õ¡Ö€Õ¿Õ¥Ö€Õ¨ ÕºÕ¡Õ°Õ¾Õ¥ÖÕ«Õ¶ Õ±Õ¥Ö€ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´}}</translation>
+<translation id="4287885627794386150">Õ“Õ¸Ö€Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ£Õ¸Ö€Õ®Õ¡Õ¼Õ¸Ö‚ÕµÕ©Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§, Õ½Õ¡Õ¯Õ¡ÕµÕ¶ Õ¡Õ¯Õ¿Õ«Õ¾Õ¡ÖÕ¾Õ¡Õ® Õ¹Õ§</translation>
<translation id="4297502707443874121">Ô·Õ» <ph name="THUMBNAIL_PAGE" />-Õ« Õ´Õ¡Õ¶Ö€Õ¡ÕºÕ¡Õ¿Õ¯Õ¥Ö€</translation>
<translation id="42981349822642051">Ô¸Õ¶Õ¤Õ¡Ö€Õ±Õ¡Õ¯Õ¥Õ¬</translation>
<translation id="4300675098767811073">Õ„Õ« Ö„Õ¡Õ¶Õ« Õ¡Õ¶ÖÖ„ Õ¡Õ» Õ¯Õ¸Õ²Õ´Õ¸Ö‚Õ´</translation>
<translation id="4302514097724775343">Ô½Õ¡Õ²Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„ Õ¤Õ«Õ¶Õ¸Õ¦Õ¡Õ¾Ö€Õ« Õ¾Ö€Õ¡</translation>
<translation id="4302965934281694568">Chou3 (Õ®Ö€Õ¡Ö€)</translation>
<translation id="4305666528087210886">Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ¢Õ¡ÖÕ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¨</translation>
-<translation id="4305817255990598646">Õ“Õ¸Õ­Õ¡Ö€Õ¯Õ¥Õ¬</translation>
+<translation id="4306529830550717874">ÕŠÕ¡Õ°Õ¥ÕžÕ¬ Õ°Õ¡Õ½ÖÕ¥Õ¶</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Ô±Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ (Õ¯Õ¡Õ¶Õ­Õ¡Õ¤Ö€Õ¾Õ¡Õ®)</translation>
<translation id="4314815835985389558">Õ€Õ¡Õ´Õ¡ÕªÕ¡Õ´Õ¡ÖÕ´Õ¡Õ¶ Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¸Ö‚Õ´</translation>
@@ -915,7 +940,7 @@
<translation id="4346197816712207223">ÕŽÕ¡Ö€Õ¯Õ¡ÕµÕ«Õ¶ Ö„Õ¡Ö€Õ¿Õ¥Ö€, Õ¸Ö€Õ¸Õ¶ÖÕ¸Õ¾ Õ¯Õ¡Ö€Õ¥Õ¬Õ« Õ§ Õ¾Õ³Õ¡Ö€Õ¥Õ¬</translation>
<translation id="4346833872170306413">Roc-16K</translation>
<translation id="4349531505348777662">Ô´Õ¸Ö‚Ö„ Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥ÖÕ«Ö„ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¯Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨, Õ¸Ö€Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> Ö‡ Õ¡ÕµÕ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ¸Ö‚Õ´Ö‰</translation>
-<translation id="4356973930735388585">Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´ Õ£Õ¿Õ¶Õ¾Õ¸Õ² Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¾Õ¸Õ²Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¾Õ¿Õ¡Õ¶Õ£Õ¡Õ¾Õ¸Ö€ Õ®Ö€Õ¡Õ£Ö€Õ¥Ö€ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬ Õ±Õ¥Ö€ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¹Õ¸Ö‚Õ´, Õ¸Ö€Õ¸Õ¶Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ£Õ¸Õ²Õ¡Õ¶Õ¡Õ¬ Õ¯Õ¡Õ´ Õ»Õ¶Õ»Õ¥Õ¬ Õ±Õ¥Ö€ Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ (Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ Õ¬Õ¸Ö‚Õ½Õ¡Õ¶Õ¯Õ¡Ö€Õ¶Õ¥Ö€Õ¨, Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨, Õ¶Õ¡Õ´Õ¡Õ¯Õ¶Õ¥Ö€Õ¨ Ö‡ Õ¾Õ¡Ö€Õ¯Õ¡ÕµÕ«Õ¶ Ö„Õ¡Ö€Õ¿Õ¥Ö€Õ¨):</translation>
+<translation id="4356973930735388585">Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´ Õ£Õ¿Õ¶Õ¾Õ¸Õ² Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¾Õ¸Õ²Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¾Õ¿Õ¡Õ¶Õ£Õ¡Õ¾Õ¸Ö€ Õ®Ö€Õ¡Õ£Ö€Õ¥Ö€ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬ Õ±Õ¥Ö€ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¹Õ¸Ö‚Õ´, Õ¸Ö€Õ¸Õ¶Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ°Õ¡ÖƒÕ·Õ¿Õ¡Õ¯Õ¥Õ¬ Õ¯Õ¡Õ´ Õ»Õ¶Õ»Õ¥Õ¬ Õ±Õ¥Ö€ Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ (Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ Õ¬Õ¸Ö‚Õ½Õ¡Õ¶Õ¯Õ¡Ö€Õ¶Õ¥Ö€Õ¨, Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨, Õ¶Õ¡Õ´Õ¡Õ¯Õ¶Õ¥Ö€Õ¨ Ö‡ Õ¾Õ¡Ö€Õ¯Õ¡ÕµÕ«Õ¶ Ö„Õ¡Ö€Õ¿Õ¥Ö€Õ¨):</translation>
<translation id="4358059973562876591">ÕÕ¥Ö€ Õ¶Õ·Õ¡Õ® Õ±Ö‡Õ¡Õ¶Õ´Õ¸Ö‚Õ·Õ¶Õ¥Ö€Õ¨ Õ¹Õ¥Õ¶ Õ¯Õ¡Ö€Õ¸Õ² Õ¯Õ«Ö€Õ¡Õ¼Õ¾Õ¥Õ¬ DnsOverHttpsMode Õ¯Õ¡Õ¶Õ¸Õ¶Õ« Õ°Õ¥Õ¿ Õ¯Õ¡ÕºÕ¾Õ¡Õ® Õ½Õ­Õ¡Õ¬Õ« ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾:</translation>
<translation id="4358461427845829800">ÕŽÕ³Õ¡Ö€Õ´Õ¡Õ¶ Õ¥Õ²Õ¡Õ¶Õ¡Õ¯Õ¶Õ¥Ö€Õ« Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¸Ö‚Õ´...</translation>
<translation id="4359160567981085931">Ô´Õ¸Ö‚Ö„ Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥ÖÕ«Ö„ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¯Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´Ö‰ Chrome-Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Ö…Õ£Õ¶Õ¥Õ¬Ö‰ ÕˆÖ€ÕºÕ¥Õ½Õ¦Õ« Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ ÖƒÕ¸Õ­Õ¥Ö„ Ö‡ Google-Õ«Õ¶ Õ¿Õ¥Õ²Õ¥Õ¯Õ¡ÖÕ¶Õ¥Ö„, Õ¸Ö€ Õ±Õ¥Ö€ Õ°Õ¡Õ·Õ«Õ¾Õ¨ Õ¾Õ¿Õ¡Õ¶Õ£Õ¾Õ¡Õ® Õ§, Õ½Õ¥Õ²Õ´Õ¥Ö„ «Պաշտպանել հաշիվը»։</translation>
@@ -926,6 +951,7 @@
<translation id="4377125064752653719">Ô´Õ¸Ö‚Ö„ ÖƒÕ¸Ö€Õ±Õ¸Ö‚Õ´ Õ§Õ«Ö„ Õ´Õ¸Ö‚Õ¿Ö„ Õ£Õ¸Ö€Õ®Õ¥Õ¬ <ph name="DOMAIN" />, Õ½Õ¡Õ¯Õ¡ÕµÕ¶ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ¶Õ¥Ö€Õ¯Õ¡ÕµÕ¡ÖÖ€Õ¡Õ® Õ¾Õ¯Õ¡ÕµÕ¡Õ£Õ«Ö€Õ¨ Õ¹Õ¥Õ²Õ¡Ö€Õ¯Õ¾Õ¥Õ¬ Õ§ Õ©Õ¸Õ²Õ¡Ö€Õ¯Õ¸Õ²Õ« Õ¯Õ¸Õ²Õ´Õ«Ö: ÕÕ¡ Õ¶Õ·Õ¡Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§, Õ¸Ö€ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ¯Õ¸Õ²Õ´Õ«Ö Õ¶Õ¥Ö€Õ¯Õ¡ÕµÕ¡ÖÕ¾Õ¡Õ® Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ¾Õ¡Õ¿Õ¡Ö€Õ´Õ¡Õ£Ö€Õ¥Ö€Õ¨ Õ¾Õ½Õ¿Õ¡Õ°Õ¥Õ¬Õ« Õ¹Õ¥Õ¶: Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§, Õ¤Õ¸Ö‚Ö„ Õ¯Õ¡Õº Õ¥Ö„ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¾Õ¸Õ²Õ« Õ°Õ¥Õ¿:</translation>
<translation id="4378154925671717803">Õ€Õ¥Õ¼Õ¡Õ­Õ¸Õ½</translation>
<translation id="4390472908992056574">Ô¼Õ¸Ö‚Õ½Õ¡Õ¶ÖÖ„</translation>
+<translation id="4406883609789734330">Ô¿Õ¥Õ¶Õ¤Õ¡Õ¶Õ« Õ¥Õ¶Õ©Õ¡Õ£Ö€Õ¥Ö€</translation>
<translation id="4406896451731180161">Õ¸Ö€Õ¸Õ¶Õ´Õ¡Õ¶ Õ¡Ö€Õ¤ÕµÕ¸Ö‚Õ¶Ö„Õ¶Õ¥Ö€</translation>
<translation id="4408413947728134509">Õ”Õ¸Ö‚Ö„Õ«Õ¶Õ¥Ö€Õ <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Ô´Õ¸Ö‚Ö„ Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥ÖÕ«Ö„ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¯Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨, Õ¸Ö€Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> Ö‡ Õ¡ÕµÕ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ¸Ö‚Õ´Ö‰</translation>
@@ -938,7 +964,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">ÕŠÖ€Õ¸Ö„Õ½Õ«-Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´Õ¶ Õ¡Õ¶Õ»Õ¡Õ¿Õ¾Õ¡Õ® Õ§, Õ¢Õ¡ÕµÖ Õ°Õ¡Õ¿Õ¯Õ¸Ö€Õ¸Õ·Õ¾Õ¡Õ® Õ§ Õ¸Ö‚Õ²Õ²Õ¡Õ¯Õ« Õ¯Õ¡Õ¦Õ´Õ¡Õ±Ö‡Õ¸Ö‚Õ´:</translation>
<translation id="4464826014807964867">Ô¿Õ¡ÕµÖ„Õ¥Ö€Õ Õ±Õ¥Ö€ Õ¯Õ¡Õ¦Õ´Õ¡Õ¯Õ¥Ö€ÕºÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ«Ö Õ½Õ¿Õ¡ÖÕ¡Õ® Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¸Õ¾</translation>
-<translation id="4466881336512663640">ÕÖ‡Õ¸Ö‚Õ´ Õ¡Ö€Õ¾Õ¡Õ® Õ¢Õ¸Õ¬Õ¸Ö€ ÖƒÕ¸ÖƒÕ¸Õ­Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¯Õ¯Õ¸Ö€Õ¥Õ¶: Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥ÕžÕ¬Ö‰</translation>
<translation id="4476953670630786061">Ô±ÕµÕ½ Õ±Ö‡Õ¶ Õ¡ÕºÕ¡Õ°Õ¸Õ¾ Õ¹Õ§Ö‰ Ô»Õ¶Ö„Õ¶Õ¡Õ¬Ö€Õ¡ÖÕ¸Ö‚Õ´Õ¶ Õ¡Õ¶Õ»Õ¡Õ¿Õ¾Õ¥Õ¬ Õ§Ö‰</translation>
<translation id="4477350412780666475">Õ€Õ¡Õ»Õ¸Ö€Õ¤ Õ¯Õ¡Õ¿Õ¡Ö€Õ¸Ö‚Õ´Õ¨</translation>
<translation id="4482953324121162758">Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¨ Õ¹Õ« Õ©Õ¡Ö€Õ£Õ´Õ¡Õ¶Õ¾Õ«:</translation>
@@ -972,6 +997,7 @@
<translation id="4594403342090139922">&amp;Õ€Õ¥Õ¿Õ¡Ö€Õ¯Õ¥Õ¬ Õ»Õ¶Õ»Õ¸Ö‚Õ´Õ¨</translation>
<translation id="4597348597567598915">Õ‰Õ¡Öƒ 8</translation>
<translation id="4600854749408232102">C6/C5 (Õ®Ö€Õ¡Ö€)</translation>
+<translation id="4606870351894164739">Ô±Õ¦Õ¤Õ¥ÖÕ«Õ¯</translation>
<translation id="4628948037717959914">Ô¼Õ¸Ö‚Õ½Õ¡Õ¶Õ¯Õ¡Ö€</translation>
<translation id="4631649115723685955">Õ”Õ¥Õ·Õ¢Õ¥Ö„Õ¸Õ¾</translation>
<translation id="4636930964841734540">ÕÕ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€</translation>
@@ -991,6 +1017,7 @@
<translation id="4691835149146451662">Architecture-A (Õ®Ö€Õ¡Ö€)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Ô¿Õ¸Õ²Õ´</translation>
+<translation id="4702656508969495934">Ô¿Õ¥Õ¶Õ¤Õ¡Õ¶Õ« Õ¥Õ¶Õ©Õ¡Õ£Ö€Õ¥Ö€Õ¨ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¥Õ¶, Õ¶Õ·Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Ö„ ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶Õ¶Õ¥Ö€Õ« ÖƒÕ¸Õ­Õ¡Ö€Õ¯Õ«Õ¹Õ¨Ö‰</translation>
<translation id="4708268264240856090">ÕÕ¥Ö€ Õ¯Õ¡ÕºÕ¶ Õ¨Õ¶Õ¤Õ°Õ¡Õ¿Õ¾Õ¥Õ¬ Õ§</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Ô³Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¥Õ¬ Windows-Õ« ÖÕ¡Õ¶ÖÕ« Õ¡Õ­Õ¿Õ¸Ö€Õ¸Õ·Õ¸Ö‚Õ´Õ¨<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@
<translation id="4738601419177586157">Ô±Õ¼Õ¡Õ»Õ¡Ö€Õ¯Õ¾Õ¸Õ² Õ¸Ö€Õ¸Õ¶Õ´Õ¡Õ¶ Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´Õ Â«<ph name="TEXT" />»</translation>
<translation id="4742407542027196863">Գաղտնաբառերի կառավարում…</translation>
<translation id="4744603770635761495">Õ„Õ·Õ¡Õ¯Õ¾Õ¸Õ² Ö†Õ¡ÕµÕ¬Õ« Õ¸Ö‚Õ²Õ«Õ¶</translation>
+<translation id="4749011317274908093">Ô´Õ¸Ö‚Ö„ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ¸Ö‚Õ´ Õ¥Ö„</translation>
<translation id="4750917950439032686">Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¸Õ² Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ (Ö…Ö€.` Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨ Õ¯Õ¡Õ´ Õ¾Õ¡Ö€Õ¯Õ¡ÕµÕ«Õ¶ Ö„Õ¡Ö€Õ¿Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨) ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¾Õ¡Õ® Õ¥Õ¶:</translation>
<translation id="4756388243121344051">&amp;ÕŠÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶</translation>
<translation id="4758311279753947758">Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¯Õ¸Õ¶Õ¿Õ¡Õ¯Õ¿Õ¡ÕµÕ«Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€</translation>
@@ -1033,6 +1061,8 @@
<translation id="4813512666221746211">Õ‘Õ¡Õ¶ÖÕ« Õ½Õ­Õ¡Õ¬</translation>
<translation id="4816492930507672669">Õ€Õ¡Ö€Õ´Õ¡Ö€Õ¥ÖÕ¶Õ¥Õ¬ Õ§Õ»Õ«Õ¶</translation>
<translation id="4819347708020428563">Ô½Õ´Õ¢Õ¡Õ£Ö€Õ¥ÕžÕ¬ Õ®Õ¡Õ¶Õ¸Õ©Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Õ¶Õ­Õ¡Õ¤Ö€Õ¾Õ¡Õ® Õ¤Õ«Õ¿Õ¡Õ¯Õ¥Ö€ÕºÕ¸Ö‚Õ´</translation>
+<translation id="4825507807291741242">Õ€Õ¦Õ¸Ö€</translation>
+<translation id="4838327282952368871">ÔµÖ€Õ¡Õ¦Õ¡ÕµÕ«Õ¶</translation>
<translation id="484462545196658690">Ô±Õ¾Õ¿Õ¸Õ´Õ¡Õ¿</translation>
<translation id="4850886885716139402">ÕÕ¥Õ½Ö„</translation>
<translation id="485316830061041779">Ô³Õ¥Ö€Õ´Õ¡Õ¶Õ¡Õ¯Õ¡Õ¶</translation>
@@ -1125,7 +1155,7 @@
<translation id="5161506081086828129">Õ‡Õ¥Õ²Õ»Õ«Õ¹ 9</translation>
<translation id="5164798890604758545">ÕÕ¥Ö„Õ½Õ¿Õ« Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¸Ö‚Õ´</translation>
<translation id="516920405563544094">Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Ö„ <ph name="CREDIT_CARD" /> Ö„Õ¡Ö€Õ¿Õ« CVC Õ¯Õ¸Õ¤Õ¨Ö‰ Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´Õ«Ö Õ°Õ¥Õ¿Õ¸ Õ±Õ¥Ö€ Google Õ°Õ¡Õ·Õ¾Õ«Õ¶ Õ¯ÖÕ¾Õ¡Õ® Ö„Õ¡Ö€Õ¿Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ¯Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¥Õ¶ Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ« Õ¯Õ¸Õ²Õ´Õ«ÖÖ‰</translation>
-<translation id="5169827969064885044">Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§Õ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ±Õ¥Ö€ Õ¯Õ¡Õ¦Õ´Õ¡Õ¯Õ¥Ö€ÕºÕ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ·Õ«Õ¾Õ¨, Õ¯Õ¡Õ´ Õ«Õ¶Õ¹-Õ¸Ö€ Õ´Õ¥Õ¯Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ£Õ¸Õ²Õ¡Õ¶Õ¡Õ¬ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
+<translation id="5169827969064885044">Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§Õ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ±Õ¥Ö€ Õ¯Õ¡Õ¦Õ´Õ¡Õ¯Õ¥Ö€ÕºÕ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ°Õ¡Õ·Õ«Õ¾Õ¨, Õ¯Õ¡Õ´ Õ«Õ¶Õ¹-Õ¸Ö€ Õ´Õ¥Õ¯Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ°Õ¡ÖƒÕ·Õ¿Õ¡Õ¯Õ¥Õ¬ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
<translation id="5171045022955879922">ÕˆÖ€Õ¸Õ¶Õ¥Ö„ Õ¯Õ¡Õ´ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Ö„ URL-Õ¨</translation>
<translation id="5171689220826475070">Fanfold-European</translation>
<translation id="5172758083709347301">Õ€Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ«Õ¹</translation>
@@ -1169,6 +1199,7 @@
<translation id="5314967030527622926">Ô²Õ¸Ö‚Õ¯Õ¬Õ¥Õ¿ ÕºÕ¡Õ¿Ö€Õ¡Õ½Õ¿Õ¥Õ¬Õ¸Ö‚ Õ£Õ¸Ö€Õ®Õ«Ö„</translation>
<translation id="5316812925700871227">ÕŠÕ¿Õ¿Õ¥Õ¬ ÕªÕ¡Õ´Õ¡ÖÕ¸Ö‚ÕµÖÕ« Õ½Õ¬Õ¡Ö„Õ« Õ°Õ¡Õ¯Õ¡Õ¼Õ¡Õ¯ Õ¸Ö‚Õ²Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢</translation>
<translation id="5317780077021120954">ÕŠÕ¡Õ°Õ¥Õ¬</translation>
+<translation id="5321288445143113935">Ô¾Õ¡Õ¾Õ¡Õ¬Õ¾Õ¡Õ® ÕºÕ¡Õ¿Õ¸Ö‚Õ°Õ¡Õ¶</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" />/<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Ô¸Õ¶Õ¿Ö€Õ¥Ö„ Õ¯Õ¸Õ¶Õ¿Õ¡Õ¯Õ¿Õ¡ÕµÕ«Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨</translation>
<translation id="5327248766486351172">Ô±Õ¶Õ¸Ö‚Õ¶</translation>
@@ -1176,11 +1207,13 @@
<translation id="5332219387342487447">Ô±Õ¼Õ¡Ö„Õ´Õ¡Õ¶ Õ¥Õ²Õ¡Õ¶Õ¡Õ¯Õ¨</translation>
<translation id="5333022057423422993">Chrome-Õ¨ Õ°Õ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥Ö€Õ¥Õ¬ Õ§, Õ¸Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨, Õ¸Ö€ Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥ÖÕ«Ö„, Õ¯Õ¸Õ¿Ö€Õ¾Õ¥Õ¬ Õ§ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¡Ö€Õ¿Õ¡Õ°Õ¸Õ½Ö„Õ« ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾Ö‰ ÕÕ¥Ö€ Õ°Õ¡Õ·Õ«Õ¾Õ¶Õ¥Ö€Õ¨ ÕºÕ¡Õ·Õ¿ÕºÕ¡Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ­Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ Õ½Õ¿Õ¸Ö‚Õ£Õ¥Õ¬ ÕºÕ¡Õ°Õ¾Õ¡Õ® Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ« Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨Ö‰</translation>
<translation id="5334013548165032829">Õ€Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ« Õ´Õ¡Õ¶Ö€Õ¡Õ´Õ¡Õ½Õ¶ Õ´Õ¡Õ¿ÕµÕ¡Õ¶Õ¶Õ¥Ö€</translation>
+<translation id="5334145288572353250">ÕŠÕ¡Õ°Õ¥ÕžÕ¬ Õ°Õ¡Õ½ÖÕ¥Õ¶</translation>
<translation id="5340250774223869109">Õ€Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ§</translation>
<translation id="534295439873310000">NFC Õ½Õ¡Ö€Ö„Õ¥Ö€</translation>
<translation id="5344579389779391559">Ô±ÕµÕ½ Õ§Õ»Õ¸Ö‚Õ´ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§ Õ±Õ¥Õ¦Õ¶Õ«Ö Õ£Õ¸Ö‚Õ´Õ¡Ö€ Õ£Õ¡Õ¶Õ±Õ¥Õ¬Õ¸Ö‚ ÖƒÕ¸Ö€Õ± Õ¡Ö€Õ¾Õ«</translation>
<translation id="5355557959165512791">Ô±ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ Õ¹Õ¥Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¡ÕµÖÕ¥Õ¬Õ¥Õ¬ <ph name="SITE" /> Õ¯Õ¡ÕµÖ„, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¤Ö€Õ¡ Õ°Õ¡Õ¾Õ¡Õ½Õ¿Õ¡Õ£Õ«Ö€Õ¨ Õ°Õ¥Õ¿ Õ§ Õ¯Õ¡Õ¶Õ¹Õ¾Õ¥Õ¬Ö‰ Õ‘Õ¡Õ¶ÖÕ¡ÕµÕ«Õ¶ Õ½Õ­Õ¡Õ¬Õ¶Õ¥Ö€Õ¶ Õ¸Ö‚ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ½Õ¸Õ¾Õ¸Ö€Õ¡Õ¢Õ¡Ö€ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡Õ¾Õ¸Ö€ Õ¢Õ¶Õ¸Ö‚ÕµÕ© Õ¥Õ¶ Õ¯Ö€Õ¸Ö‚Õ´, Ö‡ Õ°Õ¡Õ¾Õ¡Õ¶Õ¡Õ¢Õ¡Ö€ Õ¡ÕµÕ½ Õ§Õ»Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¯Õ¬Õ«Õ¶Õ« Õ¡Õ¾Õ¥Õ¬Õ« Õ¸Ö‚Õ·:</translation>
<translation id="536296301121032821">Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö ÕºÕ¡Õ°Õ¥Õ¬ Õ¯Õ¡Õ¶Õ¸Õ¶Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨</translation>
+<translation id="5363309033720083897">Ô±Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€Õ¨ Õ©Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬ Õ§ Õ°Õ¥Ö€Õ©Õ¡Õ¯Õ¡Õ¶ Õ´Õ«Õ¡ÖÖ„Õ¨</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="5386426401304769735">Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ« Õ¾Õ¯Õ¡ÕµÕ¡Õ£Ö€Õ¥Ö€Õ« Õ·Õ¡Ö€Ö„Õ¸Ö‚Õ´ Õ¡Õ¼Õ¯Õ¡ Õ§ Õ´Õ¥Õ¯ Õ¾Õ¯Õ¡ÕµÕ¡Õ£Õ«Ö€` SHA-1 Õ½Õ¿Õ¸Ö€Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢:</translation>
@@ -1189,6 +1222,7 @@
<translation id="5398772614898833570">Ô³Õ¸Õ¾Õ¡Õ¦Õ¤Õ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ§</translation>
<translation id="5400836586163650660">Õ„Õ¸Õ­Ö€Õ¡Õ£Õ¸Ö‚ÕµÕ¶</translation>
<translation id="540969355065856584">Ô±ÕµÕ½ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¨ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ¡ÕºÕ¡ÖÕ¸Ö‚ÖÕ¥Õ¬, Õ¸Ö€ <ph name="DOMAIN" /> Õ§: Ô´Ö€Õ¡ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¾Õ¯Õ¡ÕµÕ¡Õ¯Õ¡Õ¶Õ¶ Õ¡ÕµÕ½ Õ¡Õ¶Õ£Õ¡Õ´ Õ¾Õ¡Õ¾Õ¥Ö€ Õ¹Õ§: ÕŠÕ¡Õ¿Õ³Õ¡Õ¼Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¬Õ«Õ¶Õ¥Õ¬ Õ½Õ­Õ¡Õ¬ Õ¯Õ¡Õ¦Õ´Õ¡Õ±Ö‡Õ¸Ö‚Õ´Õ¨ Õ¯Õ¡Õ´ Õ¯Õ¡ÕºÕ¡Õ¯ÖÕ´Õ¡Õ¶ Õ­Õ¡ÖƒÕ¡Õ¶Õ¸Ö‚Õ´Õ¨ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¾Õ¸Õ²Õ« Õ¯Õ¸Õ²Õ´Õ«Ö:</translation>
+<translation id="541143247543991491">Ô±Õ´ÕºÕ¡ÕµÕ«Õ¶ (Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¡ÕµÕ«Õ¶)</translation>
<translation id="541416427766103491">Õ‡Õ¥Õ²Õ»Õ«Õ¹ 4</translation>
<translation id="5421136146218899937">Մաքրել դիտարկումների տվյալները…</translation>
<translation id="5426179911063097041"><ph name="SITE" /> Õ¯Õ¡ÕµÖ„Õ¶ Õ¸Ö‚Õ¦Õ¸Ö‚Õ´ Õ§ Õ±Õ¥Õ¦ Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬</translation>
@@ -1202,6 +1236,7 @@
<translation id="5455374756549232013">Ô¿Õ¡Õ¶Õ¸Õ¶Õ« Õ½Õ­Õ¡Õ¬ ÕªÕ¡Õ´Õ¡Õ¤Ö€Õ¸Õ·Õ´</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" /> Õ¯Õ¸Õ¶Õ¿Õ¡Õ¯Õ¿}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="5463625433003343978">ÕÕ¡Ö€Ö„Õ¥Ö€Õ« որոնում…</translation>
<translation id="5469868506864199649">Ô»Õ¿Õ¡Õ¬Õ¡Õ¯Õ¡Õ¶</translation>
<translation id="5470861586879999274">&amp;ÕŽÕ¥Ö€Õ¡Ö€Õ¯Õ¥Õ¬ ÖƒÕ¸ÖƒÕ¸Õ­Õ¸Ö‚Õ´Õ¨</translation>
<translation id="5478437291406423475">B6/C4 (Õ®Ö€Õ¡Ö€)</translation>
@@ -1251,8 +1286,7 @@
<translation id="5624120631404540903">Ô¿Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨</translation>
<translation id="5629630648637658800">Õ‰Õ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ¯Õ¡Õ¶Õ¸Õ¶Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨</translation>
<translation id="5631439013527180824">ÕÕ¡Ö€Ö„Õ« Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ´Õ¡Õ¶ Õ½Õ­Õ¡Õ¬ Õ°Õ¥Õ¿Ö„Õ¡Õ¶Õ·Õ«Õ¹</translation>
-<translation id="5632627355679805402">ÕÕ¥Ö€ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ£Ö€Õ¾Õ¥Õ¬ Õ¥Õ¶ Õ±Õ¥Ö€ <ph name="BEGIN_LINK" />Google Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ«<ph name="END_LINK" /> Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾ (<ph name="TIME" />): Õ€Õ¡Õ´Õ¡ÕªÕ¡Õ´Õ¡ÖÕ¸Ö‚Õ´Õ¨ Õ½Õ¯Õ½Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Ö„ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨:</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="5644090287519800334">ÕŠÕ¡Õ¿Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ« Õ¿Õ¥Õ²Õ¡Õ·Õ¡Ö€Õª Õ¥Ö€Õ¥Õ½Õ« Õ¯Õ¸Õ²Õ´Õ«ÖÕ X Õ¡Õ¼Õ¡Õ¶ÖÖ„Õ¸Õ¾</translation>
<translation id="5645854190134202180">Õ„Õ«Õ¶Õ¹Ö‡ Õ¥Ö€Õ¯Ö€Õ¸Ö€Õ¤ Õ°Õ¥Ö€Õ©Õ¡ÖƒÕ¸Õ­Õ¨</translation>
@@ -1290,12 +1324,12 @@
<translation id="5785756445106461925">Ô²Õ¡ÖÕ« Õ¡ÕµÕ¤, Õ¡ÕµÕ½ Õ§Õ»Õ¨ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§ Õ¡ÕµÕ¬ Õ¼Õ¥Õ½Õ¸Ö‚Ö€Õ½Õ¶Õ¥Ö€, Õ¸Ö€Õ¸Õ¶Ö„ Õ¡ÕºÕ¡Õ°Õ¸Õ¾ Õ¹Õ¥Õ¶: Ô±ÕµÕ½ Õ¼Õ¥Õ½Õ¸Ö‚Ö€Õ½Õ¶Õ¥Ö€Õ¨ Õ¿Õ¡Ö€Õ¡Õ¶ÖÕ´Õ¡Õ¶ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¤Õ«Õ¿Õ¾Õ¥Õ¬ Õ¸Ö‚Ö€Õ«Õ·Õ¶Õ¥Ö€Õ« Õ¯Õ¸Õ²Õ´Õ«Ö Ö‡ ÖƒÕ¸ÖƒÕ¸Õ­Õ¾Õ¥Õ¬ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¾Õ¸Õ²Õ« Õ¯Õ¸Õ²Õ´Õ«Ö, Õ«Õ¶Õ¹Õ¨ Õ¯ÖƒÕ¸Õ­Õ« Õ§Õ»Õ« Õ¿Õ¥Õ½Ö„Õ¨:</translation>
<translation id="5786044859038896871">ÕˆÖ‚Õ¦Õ¸ÕžÖ‚Õ´ Õ¥Ö„ Õ¬Ö€Õ¡ÖÕ¶Õ¥Õ¬ Õ±Õ¥Ö€ Ö„Õ¡Ö€Õ¿Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨:</translation>
<translation id="578633867165174378">Chrome-Õ¨ Õ°Õ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥Ö€Õ¥Õ¬ Õ§, Õ¸Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨, Õ¸Ö€ Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥ÖÕ«Ö„, Õ¯Õ¸Õ¿Ö€Õ¾Õ¥Õ¬ Õ§ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ« Õ¡Ö€Õ¿Õ¡Õ°Õ¸Õ½Ö„Õ« ÕºÕ¡Õ¿Õ³Õ¡Õ¼Õ¸Õ¾Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ Õ¡Õ¶Õ°Õ¡ÕºÕ¡Õ² ÖƒÕ¸Õ­Õ¥Õ¬ Õ¡ÕµÕ½ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
-<translation id="5798290721819630480">Õ€Ö€Õ¡ÕªÕ¡Ö€Õ¾Õ¥ÕžÕ¬ ÖƒÕ¸ÖƒÕ¸Õ­Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ«Ö:</translation>
<translation id="5803412860119678065">ÕˆÖ‚Õ¦Õ¸ÕžÖ‚Õ´ Õ¥Ö„ Õ¬Ö€Õ¡ÖÕ¶Õ¥Õ¬ Õ±Õ¥Ö€ <ph name="CARD_DETAIL" /> Ö„Õ¡Ö€Õ¿Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨:</translation>
<translation id="5804241973901381774">Ô¹Õ¸Ö‚ÕµÕ¬Õ¿Õ¾Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€</translation>
<translation id="5804427196348435412">Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ NFC Õ½Õ¡Ö€Ö„Õ¥Ö€Õ¨</translation>
<translation id="5810442152076338065">Ô¿Õ¡ÕºÕ¡Õ¯ÖÕ¸Ö‚Õ´Õ¨ <ph name="DOMAIN" />-Õ« Õ°Õ¥Õ¿ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ§ Õ°Õ¶Õ¡ÖÕ¡Õ® Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ£Ö€Õ¸Ö‚Õ´:</translation>
<translation id="5813119285467412249">&amp;ÕŽÕ¥Ö€Õ¡Ö€Õ¯Õ¥Õ¬ Õ°Õ¡Õ¾Õ¥Õ¬Õ¸Ö‚Õ´Õ¨</translation>
+<translation id="5817918615728894473">Ô¶Õ¸Ö‚Õ£Õ¡Õ¯ÖÕ¥Õ¬</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ÔµÖ€Õ¢ Õ¾Õ³Õ¡Ö€Õ¸Ö‚Õ´ Õ¯Õ¡Õ¿Õ¡Ö€Õ¥Ö„, Õ£Õ¸Ö‚Õ´Õ¡Ö€Õ¨ Õ¯Õ£Õ¡Õ¶Õ±Õ¾Õ« Õ¡ÕµÕ½ Ö„Õ¡Ö€Õ¿Õ«Ö, Õ½Õ¡Õ¯Õ¡ÕµÕ¶ Ö„Õ¡Ö€Õ¿Õ« Õ«Ö€Õ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€Õ¨ Õ¹Õ« Õ¿Ö€Õ¡Õ´Õ¡Õ¤Ö€Õ¾Õ« Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ«Õ¶Ö‰ Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¶Õ¯Õ¡Õ¿Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Õ¾ Õ¯Õ½Õ¿Õ¥Õ²Õ®Õ¾Õ« ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡Õ¾Õ¸Ö€ CVCÖ‰}one{ÔµÖ€Õ¢ Õ¾Õ³Õ¡Ö€Õ¸Ö‚Õ´ Õ¯Õ¡Õ¿Õ¡Ö€Õ¥Ö„, Õ£Õ¸Ö‚Õ´Õ¡Ö€Õ¨ Õ¯Õ£Õ¡Õ¶Õ±Õ¾Õ« Õ±Õ¥Ö€ Õ¨Õ¶Õ¿Ö€Õ¡Õ® Ö„Õ¡Ö€Õ¿Õ«Ö, Õ½Õ¡Õ¯Õ¡ÕµÕ¶ Ö„Õ¡Ö€Õ¿Õ« Õ«Ö€Õ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€Õ¨ Õ¹Õ« Õ¿Ö€Õ¡Õ´Õ¡Õ¤Ö€Õ¾Õ« Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ«Õ¶Ö‰ Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¶Õ¯Õ¡Õ¿Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Õ¾ Õ¯Õ½Õ¿Õ¥Õ²Õ®Õ¾Õ« ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡Õ¾Õ¸Ö€ CVCÖ‰}other{ÔµÖ€Õ¢ Õ¾Õ³Õ¡Ö€Õ¸Ö‚Õ´ Õ¯Õ¡Õ¿Õ¡Ö€Õ¥Ö„, Õ£Õ¸Ö‚Õ´Õ¡Ö€Õ¨ Õ¯Õ£Õ¡Õ¶Õ±Õ¾Õ« Õ±Õ¥Ö€ Õ¨Õ¶Õ¿Ö€Õ¡Õ® Ö„Õ¡Ö€Õ¿Õ«Ö, Õ½Õ¡Õ¯Õ¡ÕµÕ¶ Ö„Õ¡Ö€Õ¿Õ« Õ«Ö€Õ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€Õ¨ Õ¹Õ« Õ¿Ö€Õ¡Õ´Õ¡Õ¤Ö€Õ¾Õ« Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ«Õ¶Ö‰ Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¶Õ¯Õ¡Õ¿Õ¡Õ¼Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Õ¾ Õ¯Õ½Õ¿Õ¥Õ²Õ®Õ¾Õ« ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡Õ¾Õ¸Ö€ CVCÖ‰}}</translation>
<translation id="5826507051599432481">Ô¸Õ¶Õ¤Õ°Õ¡Õ¶Õ¸Ö‚Ö€ Õ¡Õ¶Õ¸Ö‚Õ¶ (CN)</translation>
<translation id="5838278095973806738">Õ„Õ« Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Ö„ Õ£Õ¡Õ²Õ¿Õ¶Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€ Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´ (Ö…Ö€.` Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨ Õ¯Õ¡Õ´ Õ¾Õ¡Ö€Õ¯Õ¡ÕµÕ«Õ¶ Ö„Õ¡Ö€Õ¿Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨), Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¤Ö€Õ¡Õ¶Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ°Õ¡ÕµÕ¿Õ¶Õ« Õ¤Õ¡Õ¼Õ¶Õ¡Õ¬ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¾Õ¸Õ²Õ¶Õ¥Ö€Õ«Õ¶Ö‰</translation>
@@ -1303,6 +1337,7 @@
<translation id="5855253129151731373">Ô±ÕµÕ½ Õ¯Õ¡ÕµÖ„Õ« Õ­Õ¶Õ¡Õ´Õ¸Ö€Õ¤Õ« Õ¡Õ¶Õ¸Ö‚Õ¶Õ¨ Õ¶Õ´Õ¡Õ¶ Õ§ <ph name="LOOKALIKE_DOMAIN" /> Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ« Õ¡Õ¶Õ¾Õ¡Õ¶Õ¨: Õ€Õ¡Ö„Õ¥Ö€Õ¶Õ¥Ö€Õ¨ Õ¥Ö€Õ¢Õ¥Õ´Õ¶ Õ½Õ¿Õ¥Õ²Õ®Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ« Õ¯Ö€Õ¯Õ¶Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ¶Õ¥Ö€Õ ÖƒÕ¸Ö„Ö€-Õ«Õ¶Õ¹ ÖƒÕ¸ÖƒÕ¸Õ­Õ¥Õ¬Õ¸Õ¾ Õ¤Ö€Õ¡Õ¶Ö Õ¿Õ«Ö€Õ¸Ö‚ÕµÕ©Õ« Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨, Õ«Õ¶Õ¹Õ¨ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ¹Õ§ Õ´Õ«Õ¡Õ¶Õ£Õ¡Õ´Õ«Ö Õ¶Õ¯Õ¡Õ¿Õ¥Õ¬Ö‰
ÔµÕ©Õ¥ Õ¯Õ¡Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„, Õ¸Ö€ Õ½Õ¡ Õ½Õ­Õ¡Õ¬Õ´Õ¸Ö‚Õ¶Ö„ Õ§, Õ¡ÕµÖÕ¥Õ¬Õ¥Ö„ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals Õ§Õ»Ö‰</translation>
+<translation id="5860033963881614850">Ô±Õ¶Õ»Õ¡Õ¿.</translation>
<translation id="5862579898803147654">Õ‡Õ¥Õ²Õ»Õ«Õ¹ 8</translation>
<translation id="5863847714970149516">Õ€Õ¡Õ»Õ¸Ö€Õ¤ Õ§Õ»Õ¸Ö‚Õ´ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§ Õ±Õ¥Õ¦Õ¶Õ«Ö Õ£Õ¸Ö‚Õ´Õ¡Ö€ Õ£Õ¡Õ¶Õ±Õ¥Õ¬Õ¸Ö‚ ÖƒÕ¸Ö€Õ± Õ¡Ö€Õ¾Õ«</translation>
<translation id="5866257070973731571">Ô±Õ¾Õ¥Õ¬Õ¡ÖÖ€Õ¥Ö„ Õ°Õ¥Õ¼Õ¡Õ­Õ¸Õ½Õ¡Õ°Õ¡Õ´Õ¡Ö€</translation>
@@ -1319,6 +1354,7 @@
<translation id="5913377024445952699">Ô·Õ¯Ö€Õ¡Õ¶Õ« Õ¿Õ¥Õ½Õ¡Õ£Ö€Õ¸Ö‚Õ´Õ¨ Õ¤Õ¡Õ¤Õ¡Ö€Õ¥ÖÕ¾Õ¡Õ® Õ§</translation>
<translation id="59174027418879706">Õ„Õ«Õ¡ÖÕ¾Õ¡Õ®</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¸Õ²}one{# in use}other{# Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¸Õ²}}</translation>
<translation id="5921185718311485855">Õ„Õ«Õ¡Ö</translation>
<translation id="5921639886840618607">ÕŠÕ¡Õ°Õ¥ÕžÕ¬ Ö„Õ¡Ö€Õ¿Õ¨ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´</translation>
<translation id="5922853866070715753">Ô³Ö€Õ¥Õ©Õ¥ ÕºÕ¡Õ¿Ö€Õ¡Õ½Õ¿ Õ§</translation>
@@ -1338,6 +1374,7 @@
<translation id="5989320800837274978">Õ†Õ·Õ¾Õ¡Õ® Õ¹Õ¥Õ¶ Õ¸Õ¹ Ö†Õ«Ö„Õ½Õ¾Õ¡Õ® ÕºÖ€Õ¸Ö„Õ½Õ«-Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¶Õ¥Ö€Õ¨, Õ¸Õ¹ PAC Õ½Õ¯Ö€Õ«ÕºÕ¿Õ¶Õ¥Ö€Õ« URL-Õ¶Õ¥Ö€Õ¨</translation>
<translation id="5992691462791905444">Ô¶Õ«Õ£Õ¦Õ¡Õ£Õ¡Õ±Ö‡ Õ®Õ¡Õ¬Õ¸Ö‚Õ´</translation>
<translation id="6000758707621254961">«<ph name="SEARCH_TEXT" />»-ի որոնման <ph name="RESULT_COUNT" /> արդյունք</translation>
+<translation id="6006484371116297560">Ô´Õ¡Õ½Õ¡Õ¯Õ¡Õ¶</translation>
<translation id="6008122969617370890">N-Õ«Ö 1 Õ°Õ¥Ö€Õ©Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¡Õ´Õ¢</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">ÕÕ¿Õ¸Ö‚Õ£Õ¥Ö„ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨</translation>
@@ -1359,6 +1396,7 @@
<translation id="6045164183059402045">Ô·Õ»Ö„Õ« Õ±Ö‡Õ¡Õ¶Õ´Õ¸Ö‚Õ·</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="6049004884579590341">ÕÕ¥Õ²Õ´Õ¥Ö„ Ö‡ ÕºÕ¡Õ°Õ¥Ö„ |<ph name="ACCELERATOR" />| Õ½Õ¿Õ¥Õ²Õ¶Õ¨Õ Õ¬Õ«Õ¡Õ§Õ¯Ö€Õ¡Õ¶ Õ¼Õ¥ÕªÕ«Õ´Õ«Ö Õ¤Õ¸Ö‚Ö€Õ½ Õ£Õ¡Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€</translation>
<translation id="6049488691372270142">Ô·Õ»Õ¥Ö€Õ« Õ´Õ¡Õ¿Õ¸Ö‚ÖÕ¸Ö‚Õ´</translation>
<translation id="6051221802930200923">Ô±ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ Õ¹Õ¥Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¡ÕµÖÕ¥Õ¬Õ¥Õ¬ <ph name="SITE" /> Õ¯Õ¡ÕµÖ„, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¡ÕµÕ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ§ Õ°Õ¡Õ¾Õ¡Õ½Õ¿Õ¡Õ£Ö€Õ« Õ¡Õ´Ö€Õ¡ÖÕ¸Ö‚Õ´Ö‰ Õ‘Õ¡Õ¶ÖÕ¡ÕµÕ«Õ¶ Õ½Õ­Õ¡Õ¬Õ¶Õ¥Ö€Õ¶ Õ¸Ö‚ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ½Õ¸Õ¾Õ¸Ö€Õ¡Õ¢Õ¡Ö€ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡Õ¾Õ¸Ö€ Õ¢Õ¶Õ¸Ö‚ÕµÕ© Õ¥Õ¶ Õ¯Ö€Õ¸Ö‚Õ´, Ö‡ Õ°Õ¡Õ¾Õ¡Õ¶Õ¡Õ¢Õ¡Ö€ Õ¡ÕµÕ½ Õ§Õ»Õ¨ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¯Õ¬Õ«Õ¶Õ« Õ¡Õ¾Õ¥Õ¬Õ« Õ¸Ö‚Õ·:</translation>
<translation id="6051898664905071243">Ô·Õ»Õ¥Ö€Õ« Ö„Õ¡Õ¶Õ¡Õ¯Õ¨Õ</translation>
@@ -1375,6 +1413,7 @@
<translation id="610911394827799129">ÕÕ¥Ö€ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¬Õ«Õ¶Õ¥Õ¬ Õ¡ÕµÖÕ¥Õ¬Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¡ÕµÕ¬ Õ±Ö‡Õ¥Ö€ Ö‡Õ½: Ô´Ö€Õ¡Õ¶Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ Õ£Õ¿Õ¶Õ¥Õ¬ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> Õ§Õ»Õ¸Ö‚Õ´:</translation>
<translation id="6116338172782435947">ÕÕ¥Õ½Õ¶Õ¥Õ¬ Õ½Õ¥Õ²Õ´Õ¡Õ¿Õ¡Õ­Õ¿Õ¡Õ¯Õ«Õ¶ ÕºÕ¡Õ¿Õ³Õ¥Õ¶Õ¾Õ¡Õ® Õ¿Õ¥Ö„Õ½Õ¿Õ¨ Ö‡ ÕºÕ¡Õ¿Õ¯Õ¥Ö€Õ¶Õ¥Ö€Õ¨</translation>
<translation id="6120179357481664955">Õ€Õ«Õ·Õ¸ÕžÖ‚Õ´ Õ¥Ö„ Õ±Õ¥Ö€ UPI ID-Õ¶</translation>
+<translation id="6123290840358279103">Ô´Õ«Õ¿Õ¥Õ¬ Õ¾Õ«Ö€Õ¿Õ¸Ö‚Õ¡Õ¬ Ö„Õ¡Ö€Õ¿Õ¨</translation>
<translation id="6124432979022149706">Chrome Enterprise-Õ« Õ´Õ«Õ¡Õ¯ÖÕ«Õ¹Õ¶Õ¥Ö€</translation>
<translation id="6146055958333702838">ÕÕ¿Õ¸Ö‚Õ£Õ¥Ö„ Õ¢Õ¸Õ¬Õ¸Ö€ Õ´Õ¡Õ¬Õ¸Ö‚Õ­Õ¶Õ¥Ö€Õ¨ Ö‡ Õ¾Õ¥Ö€Õ¡Õ¢Õ¥Õ¼Õ¶Õ¥Ö„ Õ¥Ö€Õ©Õ¸Ö‚Õ²Õ«Õ¹Õ¶Õ¥Ö€Õ¨, Õ´Õ¸Õ¤Õ¥Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Õ´ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¾Õ¸Õ²
Õ¡ÕµÕ¬ ÖÕ¡Õ¶ÖÕ¡ÕµÕ«Õ¶ Õ½Õ¡Ö€Ö„Õ¥Ö€Õ¨:</translation>
@@ -1411,6 +1450,7 @@
<translation id="6289939620939689042">Ô·Õ»Õ« Õ£Õ¸Ö‚ÕµÕ¶Õ¨</translation>
<translation id="6290238015253830360">Ô±ÕµÕ½Õ¿Õ¥Õ² Õ¯ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ¥Õ¶ Õ¡Õ¼Õ¡Õ»Õ¡Ö€Õ¯Õ¾Õ¸Õ² Õ°Õ¸Õ¤Õ¾Õ¡Õ®Õ¶Õ¥Ö€Õ¨</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC Õ¯Õ¸Õ¤Õ</translation>
<translation id="6302269476990306341">Google Õ•Õ£Õ¶Õ¡Õ¯Õ¡Õ¶Õ¨ Chrome-Õ¸Ö‚Õ´ Õ¯Õ¡Õ¶Õ»Õ¡Õ¿Õ¾Õ«</translation>
<translation id="6305205051461490394"><ph name="URL" />-Õ¶ Õ¡Õ¶Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§:</translation>
<translation id="6312113039770857350">Ô¿Õ¡ÕµÖ„Õ§Õ»Õ¶ Õ¡Õ¶Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ§</translation>
@@ -1436,6 +1476,7 @@
<translation id="6390200185239044127">Ô¶Õ«Õ£Õ¦Õ¡Õ£Õ¡Õ±Ö‡ Õ®Õ¡Õ¬Õ¸Ö‚Õ´ Õ¯Õ«Õ½Õ¸Õ¾ Õ¹Õ¡Öƒ</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Ô´Õ¸Ö‚Ö„ Õ¹Õ¥Ö„ Õ¯Õ¡Ö€Õ¸Õ² <ph name="ORIGIN_NAME" /> Õ¯Õ¡ÕµÖ„Õ«Ö Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬ Õ¡ÕµÕ½Õ¿Õ¥Õ², Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¡Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€Õ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ§ Õ¡ÕµÕ¤ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨Ö‰</translation>
+<translation id="6398765197997659313">ÔµÕ¬Õ¶Õ¥Õ¬ Õ¬Õ«Õ¡Õ§Õ¯Ö€Õ¡Õ¶ Õ¼Õ¥ÕªÕ«Õ´Õ«Ö</translation>
<translation id="6401136357288658127">Ô±ÕµÕ½ Õ¯Õ¡Õ¶Õ¸Õ¶Õ¨ Õ°Õ¶Õ¡ÖÕ¥Õ¬ Õ§: Õ“Õ¸Õ­Õ¡Ö€Õ¥Õ¶Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Ö„ <ph name="NEW_POLICY" /> Õ¯Õ¡Õ¶Õ¸Õ¶Õ¨Ö‰</translation>
<translation id="6404511346730675251">Õ“Õ¸ÖƒÕ¸Õ­Õ¥Õ¬ Õ§Õ»Õ¡Õ¶Õ«Õ·Õ¨</translation>
<translation id="6406765186087300643">C0 (Õ®Ö€Õ¡Ö€)</translation>
@@ -1448,7 +1489,6 @@
<translation id="6428450836711225518">Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Ö„ Õ±Õ¥Ö€ Õ°Õ¥Õ¼Õ¡Õ­Õ¸Õ½Õ¡Õ°Õ¡Õ´Õ¡Ö€Õ¨</translation>
<translation id="6433490469411711332">Õ“Õ¸ÖƒÕ¸Õ­Õ¥Ö„ Õ¯Õ¸Õ¶Õ¿Õ¡Õ¯Õ¿Õ¡ÕµÕ«Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" />-Õ¨ Õ´Õ¥Ö€ÕªÕ¥Ö Õ¯Õ¡ÕºÕ¡Õ¯ÖÕ¸Ö‚Õ´Õ¨:</translation>
-<translation id="6434309073475700221">Õ€Ö€Õ¡ÕªÕ¡Ö€Õ¾Õ¥Õ¬</translation>
<translation id="6440503408713884761">Ô±Õ¶Õ¿Õ¥Õ½Õ¾Õ¡Õ®</translation>
<translation id="6443406338865242315">Ô»Õ¶Õ¹ Õ¨Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ¸Ö‚Õ´Õ¶Õ¥Ö€ Ö‡ ÖƒÕ¬Õ¡Õ£Õ«Õ¶Õ¶Õ¥Ö€ Õ¥Ö„ Õ¤Õ¸Ö‚Ö„ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬</translation>
<translation id="6446163441502663861">Kahu (Õ®Ö€Õ¡Ö€)</translation>
@@ -1491,7 +1531,8 @@
<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="6630043285902923878">USB սարքերի որոնում…</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Õ„Õ¡Ö„Ö€Õ¥Õ¬</translation>
<translation id="6645291930348198241">Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Ö„Õ¸Ö‚Ö„Õ«Õ¶Õ¥Ö€Õ¶ Õ¸Ö‚ Õ¯Õ¡ÕµÖ„Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰</translation>
@@ -1506,6 +1547,7 @@
<translation id="6671697161687535275">Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥ÕžÕ¬ Õ±Ö‡Õ¥Ö€Õ« Õ¡Õ¼Õ¡Õ»Õ¡Ö€Õ¯Õ¶Õ¥Ö€Õ¨ Chromium-Õ«Ö:</translation>
<translation id="6685834062052613830">Ô´Õ¸Ö‚Ö€Õ½ Õ¥Õ¯Õ¥Ö„ Õ°Õ¡Õ·Õ¾Õ«Ö Ö‡ Õ¡Õ¾Õ¡Ö€Õ¿Õ¥Ö„ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¨</translation>
<translation id="6687335167692595844">ÕÕ¡Õ¼Õ¡Õ¹Õ¡ÖƒÕ« Õ°Õ¡Ö€ÖÕ¸Ö‚Õ´Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¾Õ¥Õ¬ Õ§</translation>
+<translation id="6688743156324860098">Ô¹Õ¡Ö€Õ´Õ¡Öնել…</translation>
<translation id="6689249931105087298">Õ€Õ¡Ö€Õ¡Õ¢Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ Õ½Ö‡ Õ¯Õ¥Õ¿Õ« Õ½Õ¥Õ²Õ´Õ¸Ö‚Õ´Õ¸Õ¾</translation>
<translation id="6689271823431384964">Chrome-Õ¶ Õ¡Õ¼Õ¡Õ»Õ¡Ö€Õ¯Õ¸Ö‚Õ´ Õ§ ÕºÕ¡Õ°Õ¥Õ¬ Ö„Õ¡Ö€Õ¿Õ¥Ö€Õ¨ Õ±Õ¥Ö€ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¤Õ¸Ö‚Ö„ Õ´Õ¿Õ¥Õ¬ Õ¥Ö„ Õ°Õ¡Õ·Õ«Õ¾: Ô±ÕµÕ½ Õ£Õ¸Ö€Õ®Õ¡Õ¼Õ¸Ö‚ÕµÕ©Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ ÖƒÕ¸Õ­Õ¥Õ¬ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´Ö‰ Õ”Õ¡Ö€Õ¿Õ¡ÕºÕ¡Õ¶Õ« Õ¡Õ¶Õ¸Ö‚Õ¶Õ¨ Õ¾Õ¥Ö€ÖÕ¾Õ¥Õ¬ Õ§ Õ±Õ¥Ö€ Õ°Õ¡Õ·Õ¾Õ«Ö:</translation>
<translation id="6698381487523150993">ÕÕ¿Õ¥Õ²Õ®Õ¾Õ¥Õ¬ Õ§`</translation>
@@ -1521,6 +1563,7 @@
<translation id="6744009308914054259">Õ”Õ¡Õ¶Õ« Õ¤Õ¥Õ¼ Õ¯Õ¡ÕºÕ¨ Õ¹Õ« Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ£Õ¶Õ¾Õ¥Õ¬, Õ¤Õ¸Ö‚Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ Õ¡Õ¶ÖÕ¶Õ¥Õ¬ «Ներբեռնումներ» Õ¢Õ¡ÕªÕ«Õ¶ Ö‡ Õ¯Õ¡Ö€Õ¤Õ¡Õ¬ Õ¡Õ¼ÖÕ¡Õ¶Ö Õ°Õ¸Õ¤Õ¾Õ¡Õ®Õ¶Õ¥Ö€Õ¨:</translation>
<translation id="6753269504797312559">Ô¿Õ¡Õ¶Õ¸Õ¶Õ« Õ¡Ö€ÕªÕ¥Ö„Õ¨</translation>
<translation id="6757797048963528358">ÕÕ¥Ö€ Õ½Õ¡Ö€Ö„Õ¨ Õ´Õ¿Õ¥Õ¬ Õ§ Ö„Õ¶Õ« Õ¼Õ¥ÕªÕ«Õ´:</translation>
+<translation id="6767985426384634228">Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥ÕžÕ¬ Õ°Õ¡Õ½ÖÕ¥Õ¶</translation>
<translation id="6768213884286397650">Hagaki (Õ¢Õ¡ÖÕ«Õ¯)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Ô²Õ¡Ö Õ´Õ¡Õ¶Õ¸Ö‚Õ·Õ¡Õ¯Õ¡Õ£Õ¸Ö‚ÕµÕ¶</translation>
@@ -1543,6 +1586,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome-Õ¨ ÕºÕ¡Ö€Õ¦Õ¥ÖÖ€Õ¥Õ¬ Õ§ Õ¡ÕµÕ½ Õ§Õ»Õ¨Õ Õ¡ÕµÕ¶ Õ¡Õ¾Õ¥Õ¬Õ« Õ¨Õ¶Õ©Õ¥Õ¼Õ¶Õ¥Õ¬Õ« Õ¤Õ¡Ö€Õ±Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€Ö‰ Chrome-Õ¨ Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Õ§ Õ½Õ¯Õ¦Õ¢Õ¶Õ¡Õ¯Õ¡Õ¶ Õ§Õ»Õ¨ Õ¸Õ¹ Õ¡ÕºÕ¡Õ°Õ¸Õ¾ Õ¯Õ¡ÕºÕ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾Ö‰</translation>
<translation id="6891596781022320156">Ô¿Õ¡Õ¶Õ¸Õ¶Õ« Õ´Õ¡Õ¯Õ¡Ö€Õ¤Õ¡Õ¯Õ¨ Õ¹Õ« Õ¡Õ»Õ¡Õ¯ÖÕ¾Õ¸Ö‚Õ´:</translation>
+<translation id="6895143722905299846">ÕŽÕ«Ö€Õ¿Õ¸Ö‚Õ¡Õ¬ Õ°Õ¡Õ´Õ¡Ö€Õ</translation>
<translation id="6895330447102777224">ÕÕ¥Ö€ Ö„Õ¡Ö€Õ¿Õ¨ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¾Õ¡Õ® Õ§</translation>
<translation id="6897140037006041989">Õ•Õ£Õ¿Õ¡Õ¿Õ«Ö€Õ¸Õ» Õ£Õ¸Ö€Õ®Õ¡Õ¯Õ¡Õ¬</translation>
<translation id="6898699227549475383">Ô¿Õ¡Õ¦Õ´Õ¡Õ¯Õ¥Ö€ÕºÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ (O)</translation>
@@ -1578,10 +1622,10 @@
<translation id="7004583254764674281">Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Windows Hello-Õ¶Õ Ö„Õ¡Ö€Õ¿Õ¥Ö€Õ¶ Õ¡Õ¾Õ¥Õ¬Õ« Õ¡Ö€Õ¡Õ£ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€</translation>
<translation id="7006930604109697472">ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Õ‰Õ¡ÖƒÕ¡ÖƒÕ¸Õ­Õ´Õ¡Õ¶ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€</translation>
<translation id="7014741021609395734">Õ„Õ¡Õ½Õ·Õ¿Õ¡Õ¢</translation>
<translation id="7016992613359344582">Ô±ÕµÕ½ Õ£Õ¡Õ¶Õ±Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ´Õ¥Õ¯Õ¡Õ¶Õ£Õ¡Õ´ÕµÕ¡ Õ¯Õ¡Õ´ ÕºÕ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ¡Õ¶ Õ¬Õ«Õ¶Õ¥Õ¬ Ö‡ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§ Õ¡Õ¯Õ¶Õ°Õ¡ÕµÕ¿ Õ¹Õ¥Ö€Ö‡Õ¡Õ¶:</translation>
<translation id="7029809446516969842">Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€</translation>
+<translation id="7030436163253143341">Õ€Õ¡Õ¾Õ¡Õ½Õ¿Õ¡Õ£Õ«Ö€Õ¶ Õ¡Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ§</translation>
<translation id="7031646650991750659">Ô»Õ¶Õ¹ Google Play Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¶Õ¥Ö€ Õ¥Ö„ Õ¤Õ¸Ö‚Ö„ Õ¿Õ¥Õ²Õ¡Õ¤Ö€Õ¥Õ¬</translation>
<translation id="7050187094878475250">Ô´Õ¸Ö‚Ö„ ÖƒÕ¸Ö€Õ±Õ¸Ö‚Õ´ Õ§Õ«Ö„ Õ´Õ¿Õ¶Õ¥Õ¬ <ph name="DOMAIN" />, Õ½Õ¡Õ¯Õ¡ÕµÕ¶ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ« Õ¯Õ¸Õ²Õ´Õ«Ö Õ¶Õ¥Ö€Õ¯Õ¡ÕµÕ¡ÖÕ¾Õ¡Õ® Õ¾Õ¯Õ¡ÕµÕ¡Õ¯Õ¡Õ¶Õ« Õ¾Õ¡Õ¾Õ¥Ö€Õ¡Õ¯Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¡Õ¶ ÕªÕ¡Õ´Õ¯Õ¥Õ¿Õ¨ Õ¹Õ¡ÖƒÕ¡Õ¦Õ¡Õ¶Ö Õ¥Ö€Õ¯Õ¡Ö€ Õ§, Õ«Õ¶Õ¹Õ¨ Õ¾Õ½Õ¿Õ¡Õ°Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¹Õ« Õ¶Õ¥Ö€Õ·Õ¶Õ¹Õ¸Ö‚Õ´:</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Õ”Õ¡Ö€Õ¿Õ¶ Õ¡ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² ÕºÕ¡Õ°Õ¾Õ¥Õ¬}one{Õ”Õ¡Ö€Õ¿Õ¶ Õ¡ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² ÕºÕ¡Õ°Õ¾Õ¥Õ¬}other{Õ”Õ¡Ö€Õ¿Õ¥Ö€Õ¶ Õ¡ÕµÕ½ ÕºÕ¡Õ°Õ«Õ¶ Õ¹Õ¥Õ¶ Õ¯Õ¡Ö€Õ¸Õ² ÕºÕ¡Õ°Õ¾Õ¥Õ¬}}</translation>
@@ -1651,12 +1695,14 @@
<translation id="7300012071106347854">Ô¿Õ¸Õ¢Õ¡Õ¬Õ¿Õ¥ Õ¯Õ¡ÕºÕ¸Ö‚ÕµÕ¿</translation>
<translation id="7302712225291570345">«<ph name="TEXT" />»</translation>
<translation id="7304030187361489308">Ô²Õ¡Ö€Õ±Ö€</translation>
+<translation id="7305756307268530424">Ô³Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¥Õ¬ Õ¡Õ¾Õ¥Õ¬Õ« Õ¤Õ¡Õ¶Õ¤Õ¡Õ²</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Õ•Õ£Õ¶Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ¯Õ¡ÕºÕ« Õ­Õ¶Õ¤Õ«Ö€Õ¶Õ¥Ö€Õ« Õ¤Õ¥ÕºÖ„Õ¸Ö‚Õ´</translation>
<translation id="7323804146520582233">Ô¹Õ¡Ö„ÖÕ¶Õ¥Õ¬ «<ph name="SECTION" />» Õ¢Õ¡ÕªÕ«Õ¶Õ¨</translation>
<translation id="733354035281974745">Ô¼Õ¸Õ¯Õ¡Õ¬ Õ°Õ¡Õ·Õ¾Õ« ÖƒÕ¸ÖƒÕ¸Õ­Õ¸Ö‚Õ´ Õ½Õ¡Ö€Ö„Õ¸Ö‚Õ´</translation>
<translation id="7333654844024768166">Ô´Õ¸Ö‚Ö„ Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥ÖÕ«Ö„ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¯Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨, Õ¸Ö€Õ¶ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> Ö‡ Õ¡ÕµÕ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ¸Ö‚Õ´Ö‰</translation>
<translation id="7334320624316649418">&amp;ÕŽÕ¥Ö€Õ¡Ö€Õ¯Õ¥Õ¬ Õ¾Õ¥Ö€Õ¡Õ¤Õ¡Õ½Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¨</translation>
+<translation id="7337248890521463931">Õ‘Õ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬ Õ¡Õ¾Õ¥Õ¬Õ« Õ·Õ¡Õ¿ Õ¿Õ¸Õ²Õ¥Ö€</translation>
<translation id="7337706099755338005">Õ€Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ§ Õ±Õ¥Ö€ Õ°Õ¡Ö€Õ©Õ¡Õ¯Õ¸Ö‚Õ´:</translation>
<translation id="733923710415886693">ÕÕ¥Ö€Õ¾Õ¥Ö€Õ« Õ¾Õ¯Õ¡ÕµÕ¡Õ£Õ«Ö€Õ¨ Õ¹Õ« Õ¢Õ¡ÖÕ¡Õ°Õ¡ÕµÕ¿Õ¾Õ¥Õ¬ «Վկայագրերի Õ©Õ¡ÖƒÕ¡Õ¶Öիկություն» Õ¯Õ¡Õ¶Õ¸Õ¶Õ« Õ´Õ«Õ»Õ¸ÖÕ¸Õ¾:</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1664,6 +1710,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Õ€Ö€Õ¡Õ´Õ¡Õ¶Õ¡Õ¿Õ¸Õ²</translation>
<translation id="7359588939039777303">Ô³Õ¸Õ¾Õ¡Õ¦Õ¤Õ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ§Ö‰</translation>
+<translation id="7363096869660964304">Ô±ÕµÕ¶Õ¸Ö‚Õ¡Õ´Õ¥Õ¶Õ¡ÕµÕ¶Õ«Õ¾ Õ¤Õ¸Ö‚Ö„ Õ¡Õ¶Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ¥Ö„Ö‰ Ô»Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ¨ Õ¹Õ« Õ©Õ¡Ö„ÖÕ¶Õ¸Ö‚Õ´ Õ¤Õ«Õ¿Õ¾Õ¡Õ® Õ§Õ»Õ¥Ö€Õ¨ Õ±Õ¥Ö€ Õ£Õ¸Ö€Õ®Õ¡Õ¿Õ¸Ö‚Õ«Ö, Õ«Õ¶Õ¿Õ¥Ö€Õ¶Õ¥Õ¿ Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« Õ´Õ¡Õ¿Õ¡Õ¯Õ¡Ö€Õ¡Ö€Õ«Ö Õ¯Õ¡Õ´ Õ±Õ¥Ö€ Õ¡ÕµÖÕ¥Õ¬Õ¡Õ® Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«ÖÖ‰</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />Ö‰ Õ€Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€ Õ¡Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Ö‡ Õ¤Ö€Õ¡Õ¶Ö„ Chrome-Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´ Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„ Tab, Õ¡ÕºÕ¡Õ EnterÖ‰</translation>
<translation id="7365849542400970216">Õ€Õ¡Õ²Õ¸Ö€Õ¤Õ¥ÕžÕ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶, Õ¥Ö€Õ¢ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„ Õ¡ÕµÕ½ Õ½Õ¡Ö€Ö„Õ¨</translation>
<translation id="7372973238305370288">Õ¸Ö€Õ¸Õ¶Õ´Õ¡Õ¶ Õ¡Ö€Õ¤ÕµÕ¸Ö‚Õ¶Ö„</translation>
@@ -1674,7 +1721,9 @@
<translation id="7378594059915113390">Õ„Õ¥Õ¤Õ«Õ¡ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€</translation>
<translation id="7378627244592794276">ÕˆÕ¹ Õ°Õ«Õ´Õ¡</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ô¿Õ«Ö€Õ¡Õ¼Õ¥Õ¬Õ« Õ¹Õ§</translation>
<translation id="7390545607259442187">Õ”Õ¡Ö€Õ¿Õ« Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´</translation>
+<translation id="7392089738299859607">Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ½ÖÕ¥Õ¶</translation>
<translation id="7399802613464275309">Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ½Õ¿Õ¸Ö‚Õ£Õ¸Ö‚Õ´</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">ÕÕ¥Ö€ <ph name="DEVICE_NAME" /> Õ½Õ¡Ö€Ö„Õ¨ Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¾Õ¸Ö‚Õ´ Õ§</translation>
@@ -1689,6 +1738,7 @@
&lt;li&gt;Ô±ÕµÖÕ¥Õ¬Õ¥Ö„ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome-Õ« Ö…Õ£Õ¶Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¯Õ¥Õ¶Õ¿Ö€Õ¸Õ¶&lt;/a&gt; Ö‡ Õ«Õ´Õ¡ÖÕ¥Ö„Õ Õ«Õ¶Õ¹ÕºÕ¥Õ½ Õ®Ö€Õ¡Õ£Õ«Ö€Õ¶ Õ¨Õ¶Õ¤Õ´Õ«Õ·Õ¿ Õ°Õ¥Õ¼Õ¡ÖÕ¶Õ¥Õ¬ Õ°Õ¡Õ´Õ¡Õ¯Õ¡Ö€Õ£Õ¹Õ«ÖÖ‰
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Õ€Õ¡Õ³Õ¥Õ¬Õ«</translation>
<translation id="7416351320495623771">Գաղտնաբառերի կառավարում…</translation>
<translation id="7419106976560586862">ÕŠÖ€Õ¸Ö†Õ«Õ¬Õ« Õ¸Ö‚Õ²Õ«</translation>
<translation id="7437289804838430631">Ô±Õ¾Õ¥Õ¬Õ¡ÖÕ¶Õ¥Õ¬ Õ¯Õ¸Õ¶Õ¿Õ¡Õ¯Õ¿Õ¡ÕµÕ«Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€</translation>
@@ -1704,7 +1754,7 @@
<translation id="7481312909269577407">Forward</translation>
<translation id="7485870689360869515">ÕÕ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€ Õ¹Õ¥Õ¶ Õ£Õ¿Õ¶Õ¾Õ¥Õ¬:</translation>
<translation id="7495528107193238112">Ô±ÕµÕ½ Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶ Õ¡Ö€Õ£Õ¥Õ¬Õ¡ÖƒÕ¡Õ¯Õ¾Õ¡Õ® Õ§Ö‰ Ô½Õ¶Õ¤Õ«Ö€Õ¨ Õ¾Õ¥Ö€Õ¡ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ¤Õ«Õ´Õ¥Ö„ Õ¯Õ¡ÕµÖ„Õ« Õ½Õ¥ÖƒÕ¡Õ¯Õ¡Õ¶Õ¡Õ¿Õ«Ö€Õ¸Õ»Õ¨Ö‰</translation>
-<translation id="7498234416455752244">Õ‡Õ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¥Õ¬ Õ¡Õ·Õ­Õ¡Õ¿Õ¡Õ¶Ö„Õ¨</translation>
+<translation id="7498193950643227031">Õ€Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ« Õ¹Õ¡ÖƒÕ¨ ÖƒÕ¸Õ­Õ¥Õ¬Õ¸Ö‚ Õ¤Õ¥ÕºÖ„Õ¸Ö‚Õ´ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ­Õ¶Õ¤Õ«Ö€Õ¶Õ¥Ö€ Õ¡Õ¼Õ¡Õ»Õ¡Õ¶Õ¡Õ¬Ö‰ Ô´Õ¸Ö‚Ö„ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ <ph name="SETTINGS" />Õ¸Ö‚Õ´ Õ½Õ¡Õ°Õ´Õ¡Õ¶Õ¡ÖƒÕ¡Õ¯Õ¥Õ¬ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¶Õ¥Ö€Õ« Õ¹Õ¡ÖƒÕ¥Ö€Õ¨ ÖƒÕ¸Õ­Õ¥Õ¬Õ¸Ö‚ Õ°Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨Ö‰</translation>
<translation id="7503664977220660814">Ô´Õ¸Ö‚Ö„ Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥ÖÕ«Ö„ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¯Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´Ö‰ Chromiume-Õ¨ Õ­Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ§ Õ¿Õ¡Õ¬Õ«Õ½ Õ½Õ¿Õ¸Ö‚Õ£Õ¥Õ¬ ÕºÕ¡Õ°Õ¾Õ¡Õ® Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> Ö‡ Õ¡ÕµÕ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€, Õ¸Ö€Õ¿Õ¥Õ² Õ¤Õ¸Ö‚Ö„ Õ¡ÕµÕªÕ´ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„ Õ¡ÕµÕ½ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
<translation id="7508255263130623398">ÕÕ¡Ö€Ö„Õ« Õ¾Õ¥Ö€Õ¡Õ¤Õ¡Ö€Õ±Õ¾Õ¡Õ® Õ¯Õ¡Õ¶Õ¸Õ¶Õ« ID-Õ¶ Õ¤Õ¡Õ¿Õ¡Ö€Õ¯ Õ§ Õ¯Õ¡Õ´ Õ¹Õ« Õ°Õ¡Õ´Õ¡ÕºÕ¡Õ¿Õ¡Õ½Õ­Õ¡Õ¶Õ¸Ö‚Õ´ Õ¨Õ¶Õ©Õ¡ÖÕ«Õ¯ ID-Õ«Õ¶</translation>
<translation id="7508870219247277067">Ô±Õ¾Õ¸Õ¯Õ¡Õ¤Õ¸ÕµÕ« Õ¯Õ¡Õ¶Õ¡Õ¹</translation>
@@ -1724,10 +1774,11 @@
<translation id="7548892272833184391">Ô»Õ¶Õ¹ÕºÕ¥Õ½ Õ·Õ¿Õ¯Õ¥Õ¬ Õ¯Õ¡ÕºÕ« Õ½Õ­Õ¡Õ¬Õ¶Õ¥Ö€Õ¨</translation>
<translation id="7549584377607005141">Ô±ÕµÕ½ Õ¾Õ¥Õ¢Õ§Õ»Õ« Õ³Õ«Õ·Õ¿ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€ Õ°Õ¡Ö€Õ¯Õ¡Õ¾Õ¸Ö€ Õ¥Õ¶ Õ±Õ¥Ö€ Õ¯Õ¸Õ²Õ´Õ«Ö Õ¶Õ¡Õ­Õ¯Õ«Õ¶Õ¸Ö‚Õ´ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¾Õ¡Õ® Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨: Ô¿Õ¡Ö€Õ¸Õ² Õ¥Ö„ Õ¶Õ¸Ö€Õ«Ö Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ¡ÕµÕ½ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨, Õ¢Õ¡ÕµÖ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬Õ¸Õ¾` Õ¡ÕµÕ½ Õ§Õ»Õ« Õ¶Õ¡Õ­Õ¯Õ«Õ¶Õ¸Ö‚Õ´ Õ¯Õ¡Õ¿Õ¡Ö€Õ¡Õ® Õ¢Õ¸Õ¬Õ¸Ö€ Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¯Õ¯Ö€Õ¯Õ¶Õ¾Õ¥Õ¶:</translation>
<translation id="7550637293666041147">ÕÕ¥Ö€ Õ½Õ¡Ö€Ö„Õ« Ö‡ Chrome-Õ« Ö…Õ£Õ¿Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨</translation>
+<translation id="755279583747225797">Õ“Õ¸Ö€Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ£Õ¸Ö€Õ®Õ¡Õ¼Õ¸Ö‚ÕµÕ©Õ¨ Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§</translation>
<translation id="7552846755917812628">Õ“Õ¸Ö€Õ±Õ¥Ö„ Õ¡Õ¶Õ¥Õ¬ Õ°Õ¥Õ¿Ö‡ÕµÕ¡Õ¬Õ¨Õ</translation>
<translation id="7554475479213504905">Ô¿Ö€Õ¯Õ«Õ¶ Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬ Ö‡ ÖÕ¸Ö‚ÕµÖ Õ¿Õ¡Õ¬</translation>
<translation id="7554791636758816595">Õ†Õ¸Ö€ Õ¶Õ¥Ö€Õ¤Õ«Ö€</translation>
-<translation id="7564049878696755256">Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§Õ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ±Õ¥Ö€ <ph name="ORG_NAME" /> Õ°Õ¡Õ·Õ«Õ¾Õ¨, Õ¯Õ¡Õ´ Õ«Õ¶Õ¹-Õ¸Ö€ Õ´Õ¥Õ¯Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ£Õ¸Õ²Õ¡Õ¶Õ¡Õ¬ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
+<translation id="7564049878696755256">Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§Õ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ±Õ¥Ö€ <ph name="ORG_NAME" /> Õ°Õ¡Õ·Õ«Õ¾Õ¨, Õ¯Õ¡Õ´ Õ«Õ¶Õ¹-Õ¸Ö€ Õ´Õ¥Õ¯Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ°Õ¡ÖƒÕ·Õ¿Õ¡Õ¯Õ¥Õ¬ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
<translation id="7567204685887185387">Ô±ÕµÕ½ Õ½Õ¥Ö€Õ¾Õ¥Ö€Õ¨ Õ¹Õ« Õ¯Õ¡Ö€Õ¸Õ² Õ¡ÕºÕ¡ÖÕ¸Ö‚ÖÕ¥Õ¬, Õ¸Ö€ <ph name="DOMAIN" /> Õ§: Ô´Ö€Õ¡ Õ¡Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¾Õ¯Õ¡ÕµÕ¡Õ¯Õ¡Õ¶Õ¨, Õ°Õ¡Õ¾Õ¡Õ¶Õ¡Õ¢Õ¡Ö€, Õ©Õ¸Õ²Õ¡Ö€Õ¯Õ¾Õ¥Õ¬ Õ§ Õ­Õ¡Ö€Õ¤Õ¡Õ­Õ¡Õ¢Õ¡Ö€: ÕŠÕ¡Õ¿Õ³Õ¡Õ¼Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ¬Õ«Õ¶Õ¥Õ¬ Õ½Õ­Õ¡Õ¬ Õ¯Õ¡Õ¦Õ´Õ¡Õ±Ö‡Õ¸Ö‚Õ´Õ¨ Õ¯Õ¡Õ´ Õ¯Õ¡ÕºÕ¡Õ¯ÖÕ´Õ¡Õ¶ Õ­Õ¡ÖƒÕ¡Õ¶Õ¸Ö‚Õ´Õ¨ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¾Õ¸Õ²Õ« Õ¯Õ¸Õ²Õ´Õ«Ö:</translation>
<translation id="7569952961197462199">Õ€Õ¥Õ¼Õ¡ÖÕ¶Õ¥ÕžÕ¬ Õ¾Õ¡Ö€Õ¯Õ¡ÕµÕ«Õ¶ Ö„Õ¡Ö€Õ¿Õ¨ Chrome-Õ«Ö:</translation>
<translation id="7569983096843329377">ÕÖ‡</translation>
@@ -1742,7 +1793,6 @@
<translation id="7610193165460212391">Ô±Ö€ÕªÕ¥Ö„Õ¨ Õ¤Õ¸Ö‚Ö€Õ½ Õ§ <ph name="VALUE" /> Õ¨Õ¶Õ¤Õ£Ö€Õ¯Õ¸Ö‚ÕµÕ©Õ«Ö:</translation>
<translation id="7613889955535752492">Ô³Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¡Õ¶ ÕªÕ¡Õ´Õ¯Õ¥Õ¿Õ¨Õ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />Ö‰ Chrome-Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨ Õ¤Õ«Õ¿Õ¥Õ¬Õ¸Ö‚ Ö‡ Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„ Tab, Õ¡ÕºÕ¡Õ EnterÖ‰</translation>
-<translation id="7615602087246926389">Ô´Õ¸Ö‚Ö„ Õ¡Ö€Õ¤Õ¥Õ¶ Õ¸Ö‚Õ¶Õ¥Ö„ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€, Õ¸Ö€Õ¸Õ¶Ö„ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ£Ö€Õ¾Õ¡Õ® Õ¥Õ¶ Google Õ°Õ¡Õ·Õ¾Õ« Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ« Õ¡ÕµÕ¬ Õ¿Õ¡Ö€Õ¢Õ¥Ö€Õ¡Õ¯Õ¸Õ¾: Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Ö„ Õ¡ÕµÕ¶ Õ¶Õ¥Ö€Ö„Ö‡Õ¸Ö‚Õ´:</translation>
<translation id="7616645509853975347">ÕÕ¥Ö€ Õ¡Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€Õ¨ Õ´Õ«Õ¡ÖÖ€Õ¥Õ¬ Õ§ Chrome Enterprise Connectors-Õ¨ Õ±Õ¥Ö€ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¸Ö‚Õ´Ö‰ Ô±ÕµÕ½ Õ´Õ«Õ¡Õ¯ÖÕ«Õ¹Õ¶Õ¥Ö€Õ«Õ¶ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¥Õ¶ Õ±Õ¥Õ¦ ÕºÕ¡Õ¿Õ¯Õ¡Õ¶Õ¸Õ² Õ¸Ö€Õ¸Õ· Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Ö‰</translation>
<translation id="7619838219691048931">ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ©Õ¥Ö€Õ©</translation>
<translation id="762844065391966283">Õ„Õ¥Õ¯Õ¡Õ¯Õ¡Õ¶ Ö…Õ¢ÕµÕ¥Õ¯Õ¿</translation>
@@ -1807,13 +1857,12 @@
<translation id="782886543891417279">Ô±Õ¶Õ¬Õ¡Ö€ Õ¯Õ¡ÕºÕ¨ (<ph name="WIFI_NAME" />), Õ¸Ö€Õ«Ö Ö…Õ£Õ¿Õ¾Õ¸Ö‚Õ´ Õ¥Ö„, Õ¯Õ¡Ö€Õ¸Õ² Õ§ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¥Õ¬, Õ¸Ö€ÕºÕ¥Õ½Õ¦Õ« Õ¤Õ¸Ö‚Ö„ Õ¡ÕµÖÕ¥Õ¬Õ¥Ö„ Õ¶Ö€Õ¡ Õ´Õ¸Ö‚Õ¿Ö„Õ« Õ§Õ»Õ¨:</translation>
<translation id="7836231406687464395">Postfix (Õ®Ö€Õ¡Ö€)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Õ‰Õ¯Õ¡}=1{1 Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ® (<ph name="EXAMPLE_APP_1" />)}=2{2 Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ® (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ® (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ® (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Ô±ÕµÕ¶Õ¸Ö‚Õ¡Õ´Õ¥Õ¶Õ¡ÕµÕ¶Õ«Õ¾, Õ¤Õ¸Ö‚Ö„ Õ¡Õ¶Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ¥Ö„: Ô»Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´Õ¨ Õ¹Õ« Õ©Õ¡Ö„ÖÕ¶Õ¸Ö‚Õ´ Õ±Õ¥Ö€ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ´Õ¡Õ¶ ÕºÕ¡Õ¿Õ´Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ±Õ¥Ö€ Õ£Õ¸Ö€Õ®Õ¡Õ¿Õ¸Ö‚Õ«Ö, Õ«Õ¶Õ¿Õ¥Ö€Õ¶Õ¥Õ¿Õ¡ÕµÕ«Õ¶ Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ« Õ´Õ¡Õ¿Õ¸Ö‚ÖÕ¸Õ²Õ«Ö Õ¯Õ¡Õ´ Õ±Õ¥Ö€ Õ¡ÕµÖÕ¥Õ¬Õ¡Õ® Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Ö:</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Ô²Õ¡ÖÕ¥Õ¬ Ö†Õ¡ÕµÕ¬Õ¥Ö€Õ Õ¨Õ½Õ¿ Ö†Õ¡ÕµÕ¬Õ« Õ¿Õ¥Õ½Õ¡Õ¯Õ« Õ°Õ¡Õ´Õ¡ÕºÕ¡Õ¿Õ¡Õ½Õ­Õ¡Õ¶Õ¸Ö‚Õ©ÕµÕ¡Õ¶</translation>
<translation id="7862185352068345852">Õ“Õ¡Õ¯Õ¥ÕžÕ¬ Õ¯Õ¡ÕµÖ„Õ¨</translation>
<translation id="7865448901209910068">Ô¼Õ¡Õ¾Õ¡Õ£Õ¸Ö‚ÕµÕ¶ Õ¡Ö€Õ¡Õ£Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶</translation>
<translation id="7874263914261512992">Ô´Õ¸Ö‚Ö„ Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥ÖÕ«Ö„ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¯Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´Ö‰ Chrome-Õ¨ Õ­Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ§ Õ¿Õ¡Õ¬Õ«Õ½ Õ½Õ¿Õ¸Ö‚Õ£Õ¥Õ¬ ÕºÕ¡Õ°Õ¾Õ¡Õ® Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> Ö‡ Õ¡ÕµÕ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€, Õ¸Ö€Õ¿Õ¥Õ² Õ¤Õ¸Ö‚Ö„ Õ¡ÕµÕªÕ´ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„ Õ¡ÕµÕ½ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
-<translation id="7878562273885520351">ÕÕ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ£Õ¸Õ²Õ¡Õ¶Õ¡Õ¬</translation>
+<translation id="7878562273885520351">ÕÕ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ°Õ¡ÖƒÕ·Õ¿Õ¡Õ¯Õ¥Õ¬</translation>
+<translation id="7880146494886811634">ÕŠÕ¡Õ°Õ¥Õ¬ Õ°Õ¡Õ½ÖÕ¥Õ¶</translation>
<translation id="7882421473871500483">Õ‡Õ¡Õ£Õ¡Õ¶Õ¡Õ¯Õ¡Õ£Õ¸Ö‚ÕµÕ¶</translation>
<translation id="7887683347370398519">ÕÕ¿Õ¸Ö‚Õ£Õ¥Ö„ Õ±Õ¥Ö€ CVC Õ¯Õ¸Õ¤Õ¨ Ö‡ Õ¶Õ¸Ö€Õ«Ö ÖƒÕ¸Ö€Õ±Õ¥Ö„</translation>
<translation id="7887885240995164102">Ô±Õ¶ÖÕ¶Õ¥Õ¬ «նկար Õ¶Õ¯Õ¡Ö€Õ« մեջ» Õ¼Õ¥ÕªÕ«Õ´Õ«</translation>
@@ -1821,6 +1870,7 @@
<translation id="7894280532028510793">ÔµÕ©Õ¥ Õ¿Õ¡Õ¼Õ¡Õ½Õ­Õ¡Õ¬ Õ¹Õ¯Õ¡, <ph name="BEGIN_LINK" />Õ£Õ¸Ö€Õ®Õ¡Ö€Õ¯Õ¥Ö„ ÖÕ¡Õ¶ÖÕ« Õ¤Õ«Õ¡Õ£Õ¶Õ¸Õ½Õ¿Õ«Õ¯Õ¡Õ¶<ph name="END_LINK" />Ö‰</translation>
<translation id="7904208859782148177">C3 (Õ®Ö€Õ¡Ö€)</translation>
<translation id="7931318309563332511">Ô±Õ¶Õ°Õ¡ÕµÕ¿</translation>
+<translation id="793209273132572360">Ô¹Õ¡Ö€Õ´Õ¡ÖÕ¶Õ¥ÕžÕ¬ Õ°Õ¡Õ½ÖÕ¥Õ¶</translation>
<translation id="7932579305932748336">Ô¾Õ¡Õ®Õ¯Õ¸Ö‚ÕµÕ©</translation>
<translation id="79338296614623784">Õ„Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥Ö„ Õ¾Õ¡Õ¾Õ¥Ö€ Õ°Õ¥Õ¼Õ¡Õ­Õ¸Õ½Õ¡Õ°Õ¡Õ´Õ¡Ö€</translation>
<translation id="7934052535022478634">ÕŽÕ³Õ¡Ö€Õ¸Ö‚Õ´Õ¨ Õ¯Õ¡Õ¿Õ¡Ö€Õ¾Õ¡Õ® Õ§</translation>
@@ -1891,6 +1941,7 @@
<translation id="8175796834047840627">Chrome-Õ¶ Õ¡Õ¼Õ¡Õ»Õ¡Ö€Õ¯Õ¸Ö‚Õ´ Õ§ ÕºÕ¡Õ°Õ¥Õ¬ Ö„Õ¡Ö€Õ¿Õ¥Ö€Õ¨ Õ±Õ¥Ö€ Google Õ°Õ¡Õ·Õ¾Õ¸Ö‚Õ´, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¤Õ¸Ö‚Ö„ Õ´Õ¿Õ¥Õ¬ Õ¥Ö„ Õ°Õ¡Õ·Õ«Õ¾: ÕÕ¡ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Ö„ ÖƒÕ¸Õ­Õ¥Õ¬ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´Ö‰</translation>
<translation id="8176440868214972690">ÕÕ¡Ö€Ö„Õ« Õ¡Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€Õ¨ Õ°Õ¥Õ¿Ö‡ÕµÕ¡Õ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ«Õ¶ Õ¸Ö‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Õ§ Õ¸Ö€Õ¸Õ· Õ¿Õ¥Õ²Õ¥Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€, Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€ Ö‡ Õ¯Õ¡Õ¶Õ¸Õ¶Õ¶Õ¥Ö€Ö‰</translation>
<translation id="8184538546369750125">Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ°Õ¡Õ´Õ¨Õ¶Õ¤Õ°Õ¡Õ¶Õ¸Ö‚Ö€ Õ¯Õ¡Õ¶Õ­Õ¡Õ¤Ö€Õ¾Õ¡Õ® Õ¡Ö€ÕªÕ¥Ö„Õ¨ (Ô¹Õ¸Ö‚ÕµÕ¬Õ¡Õ¿Ö€Õ¥Õ¬)</translation>
+<translation id="8193086767630290324">Ô³Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€ Õ°Õ¥Õ¿, Õ¸Ö€Õ¸Õ¶Ö„ Õ¶Õ·Õ¾Õ¡Õ® Õ¥Õ¶ Õ¸Ö€ÕºÕ¥Õ½ Õ£Õ¡Õ²Õ¿Õ¶Õ«</translation>
<translation id="8194797478851900357">&amp;Õ€Õ¥Õ¿Õ¡Ö€Õ¯Õ¥Õ¬ Õ¿Õ¥Õ²Õ¡ÖƒÕ¸Õ­Õ¸Ö‚Õ´Õ¨</translation>
<translation id="8201077131113104583">Ô¹Õ¡Ö€Õ´Õ¡ÖÕ´Õ¡Õ¶ Õ½Õ­Õ¡Õ¬ URL` «<ph name="EXTENSION_ID" />» ID-Õ¸Õ¾ Õ¨Õ¶Õ¤Õ¬Õ¡ÕµÕ¶Õ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€:</translation>
<translation id="8202097416529803614">ÕŠÕ¡Õ¿Õ¾Õ¥Ö€Õ« Õ¡Õ´ÖƒÕ¸ÖƒÕ¡Õ£Õ«Ö€Õ¨</translation>
@@ -1913,6 +1964,7 @@
<translation id="8249296373107784235">Ô¸Õ¶Õ¤Õ°Õ¡Õ¿Õ¥Õ¬</translation>
<translation id="8249320324621329438">ÕŽÕ¥Ö€Õ»Õ«Õ¶ Õ¡Õ¶Õ£Õ¡Õ´ Ö„Õ¡Õ·Õ¾Õ¥Õ¬ Õ§Õ</translation>
<translation id="8253091569723639551">Ô±Õ¶Õ°Ö€Õ¡ÕªÕ¥Õ·Õ¿ Õ§ Õ¶Õ·Õ¥Õ¬ Õ¾Õ³Õ¡Ö€Õ¡ÕµÕ«Õ¶ Õ°Õ¡Õ½ÖÕ¥Õ¶</translation>
+<translation id="8257387598443225809">Ô±ÕµÕ½ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨ Õ¶Õ¡Õ­Õ¡Õ¿Õ¥Õ½Õ¾Õ¡Õ® Õ§ Õ¢Õ»Õ»Õ¡ÕµÕ«Õ¶ Õ½Õ¡Ö€Ö„Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€</translation>
<translation id="825929999321470778">Õ‘Õ¸Ö‚ÖÕ¡Õ¤Ö€Õ¥Õ¬ Õ¢Õ¸Õ¬Õ¸Ö€ ÕºÕ¡Õ°Õ¾Õ¡Õ® Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨</translation>
<translation id="8261506727792406068">Õ‹Õ¶Õ»Õ¥Õ¬</translation>
<translation id="8262952874573525464">ÔµÕ¦Ö€Õ¡Õ¯Õ¡Ö€ Õ¶Õ¥Ö€Ö„Ö‡Õ¸Ö‚Õ´</translation>
@@ -2036,7 +2088,6 @@
<translation id="8719528812645237045">Õ„Õ« Ö„Õ¡Õ¶Õ« Õ¡Õ¶ÖÖ„ Õ¾Õ¥Ö€Ö‡Õ¸Ö‚Õ´</translation>
<translation id="8725066075913043281">Õ“Õ¸Ö€Õ±Õ¥Õ¬ Õ¯Ö€Õ¯Õ«Õ¶</translation>
<translation id="8726549941689275341">Ô·Õ»Õ« Õ¹Õ¡ÖƒÕ½Õ¨`</translation>
-<translation id="8728672262656704056">Ô´Õ¸Ö‚Ö„ Õ´Õ¿Õ¥Õ¬ Õ¥Ö„ Õ«Õ¶Õ¯Õ¸Õ£Õ¶Õ«Õ¿Õ¸ Õ¼Õ¥ÕªÕ«Õ´</translation>
<translation id="8730621377337864115">ÕŠÕ¡Õ¿Ö€Õ¡Õ½Õ¿ Õ§</translation>
<translation id="8731544501227493793">«Կառավարել գաղտնաբառերը» կոճակ։ Chrome-ի կարգավորումներում գաղտնաբառերը դիտելու և կառավարելու համար սեղմեք Enter։</translation>
<translation id="8734529307927223492">ÕÕ¥Ö€ <ph name="DEVICE_TYPE" /> Õ½Õ¡Ö€Ö„Õ¨ Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¾Õ¸Ö‚Õ´ Õ§ <ph name="MANAGER" />-Õ« Õ¯Õ¸Õ²Õ´Õ«Ö</translation>
@@ -2054,7 +2105,7 @@
<translation id="8774457497170244317">Ô´Õ¸Ö‚Ö„ Õ°Õ¥Õ¶Ö Õ¶Õ¸Ö€ Õ´Õ¸Ö‚Õ¿Ö„Õ¡Õ£Ö€Õ¥ÖÕ«Ö„ Õ±Õ¥Ö€ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨ Õ¯Õ¡Õ½Õ¯Õ¡Õ®Õ¥Õ¬Õ« Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´Ö‰ Chrome-Õ¨ Õ­Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ§ Õ¿Õ¡Õ¬Õ«Õ½ Õ½Õ¿Õ¸Ö‚Õ£Õ¥Õ¬ ÕºÕ¡Õ°Õ¾Õ¡Õ® Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¥Ö€Õ¨ <ph name="WEBSITE_1" /> Ö‡ Õ¡ÕµÕ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€, Õ¸Ö€Õ¿Õ¥Õ² Õ¤Õ¸Ö‚Ö„ Õ¡ÕµÕªÕ´ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´ Õ¥Ö„ Õ¡ÕµÕ½ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
<translation id="877985182522063539">A4</translation>
<translation id="8790007591277257123">&amp;ÕŽÕ¥Ö€Õ¡Ö€Õ¯Õ¥Õ¬ Õ»Õ¶Õ»Õ¸Ö‚Õ´Õ¨</translation>
-<translation id="8792621596287649091">Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§Õ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ <ph name="ORG_NAME" /> Õ°Õ¡Õ·Õ«Õ¾Õ¨, Õ¯Õ¡Õ´ Õ«Õ¶Õ¹-Õ¸Ö€ Õ´Õ¥Õ¯Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ£Õ¸Õ²Õ¡Õ¶Õ¡Õ¬ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
+<translation id="8792621596287649091">Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§Õ Õ¹Õ¯Õ¡Ö€Õ¸Õ²Õ¡Õ¶Õ¡Ö„ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ <ph name="ORG_NAME" /> Õ°Õ¡Õ·Õ«Õ¾Õ¨, Õ¯Õ¡Õ´ Õ«Õ¶Õ¹-Õ¸Ö€ Õ´Õ¥Õ¯Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ§ Õ°Õ¡ÖƒÕ·Õ¿Õ¡Õ¯Õ¥Õ¬ Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨Ö‰ Ô½Õ¸Ö€Õ°Õ¸Ö‚Ö€Õ¤ Õ¥Õ¶Ö„ Õ¿Õ¡Õ¬Õ«Õ½ ÖƒÕ¸Õ­Õ¥Õ¬ Õ£Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼Õ¨Ö‰</translation>
<translation id="8793655568873652685"><ph name="ENROLLMENT_DOMAIN" /> Õ¯Õ¡ÕµÖ„Õ¨ Õ´Õ«Õ¡ÖÖ€Õ¥Õ¬ Õ§ Chrome Enterprise Connectors-Õ¨ Õ±Õ¥Ö€ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¸Ö‚Õ´Ö‰ Ô±ÕµÕ½ Õ´Õ«Õ¡Õ¯ÖÕ«Õ¹Õ¶Õ¥Ö€Õ«Õ¶ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¥Õ¶ Õ±Õ¥Õ¦ ÕºÕ¡Õ¿Õ¯Õ¡Õ¶Õ¸Õ² Õ¸Ö€Õ¸Õ· Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Ö‰</translation>
<translation id="8798099450830957504">Ô¿Õ¡Õ¶Õ­Õ¡Õ¤Ö€Õ¾Õ¡Õ®</translation>
<translation id="8805819170075074995">«<ph name="LANGUAGE_ID" />» ÖÕ¡Õ¶Õ¯Õ« տարր․ Õ¡Õ¶Õ¿Õ¥Õ½Õ¾Õ¡Õ® Õ§, Ö„Õ¡Õ¶Õ« Õ¸Ö€ Õ¡ÕµÕ¶ Õ¡Ö€Õ¤Õ¥Õ¶ Õ¶Õ¥Ö€Õ¡Õ¼Õ¾Õ¡Õ® Õ§ SpellcheckLanguage Õ¯Õ¡Õ¶Õ¸Õ¶Õ¸Ö‚Õ´Ö‰</translation>
@@ -2096,7 +2147,7 @@
<translation id="8971063699422889582">ÕÕ¥Ö€Õ¾Õ¥Ö€Õ« Õ¾Õ¯Õ¡ÕµÕ¡Õ£Ö€Õ« ÕªÕ¡Õ´Õ¯Õ¥Õ¿Õ¶ Õ½ÕºÕ¡Õ¼Õ¾Õ¥Õ¬ Õ§:</translation>
<translation id="8975012916872825179">Ô±ÕµÕ¤ Õ©Õ¾Õ¸Ö‚Õ´Õ Õ°Õ¥Õ¼Õ¡Õ­Õ¸Õ½Õ¡Õ°Õ¡Õ´Õ¡Ö€Õ¶Õ¥Ö€Õ¨, Õ§Õ¬ÖƒÕ¸Õ½Õ¿Õ« Ö‡ Õ¡Õ¼Õ¡Ö„Õ´Õ¡Õ¶ Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€Õ¨</translation>
<translation id="8975263830901772334">ÕÕ¥Ö€ Õ¿ÕºÕ¡Õ® Ö†Õ¡ÕµÕ¬Õ¥Ö€Õ« Õ¡Õ¶Õ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨</translation>
-<translation id="8978053250194585037">ÕŽÕ¥Ö€Õ»Õ¥Ö€Õ½ Google Safe Browsing-Õ¨ <ph name="BEGIN_LINK" />Ö†Õ«Õ·Õ«Õ¶Õ£ Õ§ Õ°Õ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥Ö€Õ¥Õ¬<ph name="END_LINK" /> <ph name="SITE" /> Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´Ö‰ Õ†Õ´Õ¡Õ¶ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ¨ Õ¶Õ¥Ö€Õ¯Õ¡ÕµÕ¡Õ¶Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¡ÕµÕ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ« Õ¡Õ¶Õ¾Õ¡Õ¶ Õ¿Õ¡Õ¯` Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ£Õ¸Õ²Õ¡Õ¶Õ¡Õ¬Õ¸Ö‚ Õ¶ÕºÕ¡Õ¿Õ¡Õ¯Õ¸Õ¾:</translation>
+<translation id="8978053250194585037">ÕŽÕ¥Ö€Õ»Õ¥Ö€Õ½ Google Safe Browsing-Õ¨ <ph name="BEGIN_LINK" />Ö†Õ«Õ·Õ«Õ¶Õ£ Õ§ Õ°Õ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥Ö€Õ¥Õ¬<ph name="END_LINK" /> <ph name="SITE" /> Õ¯Õ¡ÕµÖ„Õ¸Ö‚Õ´Ö‰ Õ†Õ´Õ¡Õ¶ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ¨ Õ¶Õ¥Ö€Õ¯Õ¡ÕµÕ¡Õ¶Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¡ÕµÕ¬ Õ¯Õ¡ÕµÖ„Õ¥Ö€Õ« Õ¡Õ¶Õ¾Õ¡Õ¶ Õ¿Õ¡Õ¯` Õ±Õ¥Ö€ Õ¡Õ¶Õ±Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Õ°Õ¡ÖƒÕ·Õ¿Õ¡Õ¯Õ¥Õ¬Õ¸Ö‚ Õ¶ÕºÕ¡Õ¿Õ¡Õ¯Õ¸Õ¾:</translation>
<translation id="8983003182662520383">ÕŽÕ³Õ¡Ö€Õ´Õ¡Õ¶ Õ¥Õ²Õ¡Õ¶Õ¡Õ¯Õ¶Õ¥Ö€ Õ¸Ö‚ Õ°Õ¡Õ½ÖÕ¥Õ¶Õ¥Ö€ Google Pay-Õ«Ö</translation>
<translation id="8987927404178983737">Ô±Õ´Õ«Õ½</translation>
<translation id="8989148748219918422"><ph name="ORGANIZATION" /> [<ph name="COUNTRY" />]</translation>
@@ -2113,6 +2164,7 @@
<translation id="9020542370529661692">Ô±ÕµÕ½ Õ§Õ»Õ¨ Õ©Õ¡Ö€Õ£Õ´Õ¡Õ¶Õ¾Õ¥Õ¬ Õ§ <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Õ¡Õ¶Õ¾Õ¡Õ¾Õ¥Ö€)</translation>
+<translation id="9030265603405983977">Õ„Õ«Õ¡Õ£Õ¸Ö‚ÕµÕ¶</translation>
<translation id="9035022520814077154">Ô±Õ¶Õ¾Õ¿Õ¡Õ¶Õ£Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ½Õ­Õ¡Õ¬</translation>
<translation id="9038649477754266430">Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ¯Õ¡Õ¶Õ­Õ¡Õ¿Õ¥Õ½Õ´Õ¡Õ¶ Õ®Õ¡Õ¼Õ¡ÕµÕ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨Õ Õ§Õ»Õ¥Ö€Õ¶ Õ¡Õ¾Õ¥Õ¬Õ« Õ¡Ö€Õ¡Õ£ Õ¢Õ¥Õ¼Õ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€</translation>
<translation id="9039213469156557790">Ô²Õ¡ÖÕ« Õ¡ÕµÕ¤, Õ¡ÕµÕ½ Õ§Õ»Õ¨ ÕºÕ¡Ö€Õ¸Ö‚Õ¶Õ¡Õ¯Õ¸Ö‚Õ´ Õ§ Õ¡ÕµÕ¬ Õ¼Õ¥Õ½Õ¸Ö‚Ö€Õ½Õ¶Õ¥Ö€, Õ¸Ö€Õ¸Õ¶Ö„ Õ¡ÕºÕ¡Õ°Õ¸Õ¾ Õ¹Õ¥Õ¶: Ô±ÕµÕ½ Õ¼Õ¥Õ½Õ¸Ö‚Ö€Õ½Õ¶Õ¥Ö€Õ¨ Õ¿Õ¡Ö€Õ¡Õ¶ÖÕ´Õ¡Õ¶ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¤Õ«Õ¿Õ¾Õ¥Õ¬ Õ¸Ö‚Ö€Õ«Õ·Õ¶Õ¥Ö€Õ« Õ¯Õ¸Õ²Õ´Õ«Ö Ö‡ ÖƒÕ¸ÖƒÕ¸Õ­Õ¾Õ¥Õ¬ Õ°Õ¡Ö€Õ±Õ¡Õ¯Õ¾Õ¸Õ²Õ« Õ¯Õ¸Õ²Õ´Õ«Ö, Õ«Õ¶Õ¹Õ¨ Õ¯ÖƒÕ¸Õ­Õ« Õ§Õ»Õ« Õ¾Õ¡Ö€Ö„Õ¡Õ£Õ«Õ®Õ¨:</translation>
@@ -2136,6 +2188,7 @@
<translation id="91108059142052966">Ô±Õ¤Õ´Õ«Õ¶Õ«Õ½Õ¿Ö€Õ¡Õ¿Õ¸Ö€Õ¶ Õ¡Õ¶Õ»Õ¡Õ¿Õ¥Õ¬ Õ§ Õ§Õ¯Ö€Õ¡Õ¶Õ« ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¸Ö‚Õ´Õ¨ <ph name="APPLICATION_TITLE" /> Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ«Õ¶, Õ¥Ö€Õ¢ Õ£Õ¡Õ²Õ¿Õ¶Õ« Õ¢Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶ Õ§ Õ¿Õ¥Õ½Õ¡Õ¶Õ¥Õ¬Õ«</translation>
<translation id="9114524666733003316">Õ”Õ¡Ö€Õ¿Õ« Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¸Ö‚Õ´...</translation>
<translation id="9114581008513152754">ÕÕ¥Ö€ Õ¤Õ«Õ¿Õ¡Ö€Õ¯Õ«Õ¹Õ¨ Õ¹Õ« Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¾Õ¸Ö‚Õ´ Õ¸Ö€Ö‡Õ§ Õ¨Õ¶Õ¯Õ¥Ö€Õ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¯Õ¡Õ´ Õ¯Õ¡Õ¦Õ´Õ¡Õ¯Õ¥Ö€ÕºÕ¸Ö‚Õ©ÕµÕ¡Õ¶ Õ¯Õ¸Õ²Õ´Õ«ÖÖ‰ ÕÕ¡Ö€Ö„Õ¸Ö‚Õ´ Õ¡Ö€Õ¾Õ¸Õ² Õ£Õ¸Ö€Õ®Õ¸Õ²Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¾Õ¥Õ¬ Chrome-Õ«Ö Õ¤Õ¸Ö‚Ö€Õ½Ö‰ <ph name="BEGIN_LINK" />Ô»Õ´Õ¡Õ¶Õ¡Õ¬ Õ¡Õ¾Õ¥Õ¬Õ«Õ¶<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Ô¹Õ¡Ö€Õ´</translation>
<translation id="9119042192571987207">ÕŽÕ¥Ö€Õ¢Õ¥Õ¼Õ¶Õ¾Õ¡Õ® Õ§</translation>
<translation id="9128016270925453879">Ô¿Õ¡Õ¶Õ¸Õ¶Õ¶Õ¥Ö€Õ¨ Õ¢Õ¥Õ¼Õ¶Õ¾Õ¥Õ¬ Õ¥Õ¶</translation>
<translation id="9128870381267983090">Ô¿Õ¡ÕºÕ¡Õ¯ÖÕ¥Ö„ ÖÕ¡Õ¶ÖÕ«Õ¶</translation>
@@ -2154,6 +2207,7 @@
<translation id="9170848237812810038">&amp;Õ€Õ¥Õ¿Õ¡Ö€Õ¯Õ¥Õ¬</translation>
<translation id="9171296965991013597">Õ“Õ¡Õ¯Õ¥ÕžÕ¬ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨</translation>
<translation id="9173282814238175921">Õ„Õ¥Õ¯ ÖƒÕ¡Õ½Õ¿Õ¡Õ©Õ¸Ö‚Õ²Õ©/Õ¶Õ¸Ö€ Õ©Õ¥Ö€Õ©</translation>
+<translation id="9173995187295789444">Bluetooth Õ½Õ¡Ö€Ö„Õ¥Ö€Õ« Õ¸Ö€Õ¸Õ¶Õ¸Ö‚Õ´...</translation>
<translation id="917450738466192189">ÕÕ¥Ö€Õ¾Õ¥Ö€Õ« Õ¾Õ¯Õ¡ÕµÕ¡Õ£Õ«Ö€Õ¶ Õ¡Õ¶Õ¾Õ¡Õ¾Õ¥Ö€ Õ§:</translation>
<translation id="9174917557437862841">Õ†Õ¥Ö€Õ¤Õ«Ö€Õ¶Õ¥Ö€Õ« Õ´Õ«Õ»Ö‡ Õ¡Õ¶ÖÕ´Õ¡Õ¶ Õ¯Õ¸Õ³Õ¡Õ¯Ö‰ Ô±ÕµÕ½ Õ¶Õ¥Ö€Õ¤Õ«Ö€Õ«Õ¶ Õ¡Õ¶ÖÕ¶Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€ Õ½Õ¥Õ²Õ´Õ¥Ö„ «Enter»։</translation>
<translation id="9179703756951298733">Ô¿Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¥Ö„ Õ±Õ¥Ö€ Õ¾Õ³Õ¡Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Ö‡ Õ¾Õ¡Ö€Õ¯Õ¡ÕµÕ«Õ¶ Ö„Õ¡Ö€Õ¿Õ¥Ö€Õ« Õ¿Õ¾ÕµÕ¡Õ¬Õ¶Õ¥Ö€Õ¨ Chrome-Õ« Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¸Ö‚Õ´</translation>
diff --git a/chromium/components/strings/components_strings_id.xtb b/chromium/components/strings/components_strings_id.xtb
index b733d951af6..a58d11b8756 100644
--- a/chromium/components/strings/components_strings_id.xtb
+++ b/chromium/components/strings/components_strings_id.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Apabila dicentang, Chrome akan menyimpan salinan kartu Anda pada perangkat ini untuk pengisian formulir yang lebih cepat.</translation>
<translation id="1110994991967754504">Pilih izin untuk <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Urungkan pengaturan ulang</translation>
+<translation id="1123753900084781868">Teks Otomatis tidak tersedia untuk saat ini</translation>
<translation id="1125573121925420732">Peringatan mungkin akan sering ditampilkan selama situs mengupdate keamanannya. Situasi ini akan segera diperbaiki.</translation>
<translation id="112840717907525620">Cache kebijakan Oke</translation>
<translation id="1130564665089811311">Tombol Terjemahkan halaman, tekan Enter untuk menerjemahkan halaman ini dengan Google Terjemahan</translation>
@@ -74,6 +75,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="1240347957665416060">Nama perangkat Anda</translation>
<translation id="124116460088058876">Bahasa lainnya</translation>
<translation id="1243027604378859286">Pengarang:</translation>
+<translation id="1246424317317450637">Tebal</translation>
<translation id="1250759482327835220">Untuk membayar lebih cepat di pembelian berikutnya, simpan kartu, nama, dan alamat penagihan ke Akun Google Anda.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (disinkronkan)</translation>
<translation id="1256368399071562588">&lt;p&gt;Jika Anda mencoba membuka situs dan tidak terbuka, terlebih dahulu coba perbaiki error dengan langkah-langkah pemecahan masalah ini:&lt;/p&gt;
@@ -156,6 +158,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="1476595624592550506">Ubah sandi Anda</translation>
<translation id="1484290072879560759">Pilih Alamat Pengiriman</translation>
<translation id="1492194039220927094">Push kebijakan:</translation>
+<translation id="1495677929897281669">Kembali ke tab</translation>
<translation id="1501859676467574491">Tampilkan kartu dari Akun Google Anda</translation>
<translation id="1507202001669085618">&lt;p&gt;Anda akan melihat error ini jika menggunakan portal Wi-Fi yang mengharuskan Anda login sebelum terhubung online.&lt;/p&gt;
&lt;p&gt;Untuk memperbaiki error, klik &lt;strong&gt;Sambungkan&lt;/strong&gt; di halaman yang ingin Anda buka.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="1532118530259321453">Halaman ini menyatakan</translation>
<translation id="153384715582417236">Itu saja untuk sekarang</translation>
<translation id="1536390784834419204">Terjemahkan halaman</translation>
+<translation id="1539840569003678498">Laporan dikirim:</translation>
<translation id="154408704832528245">Pilih Alamat Pengiriman</translation>
<translation id="1549470594296187301">JavaScript harus diaktifkan untuk menggunakan fitur ini.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="1682696192498422849">Tepi pendek lebih dulu</translation>
<translation id="168693727862418163">Nilai kebijakan ini gagal memvalidasi skemanya dan akan diabaikan.</translation>
<translation id="168841957122794586">Sertifikat server berisi kunci kriptografis yang lemah.</translation>
+<translation id="1696290444144917273">Lihat detail kartu virtual</translation>
<translation id="1697532407822776718">Anda sudah siap!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya sepertinya dari esok hari. Hal ini mungkin disebabkan oleh kesalahan konfigurasi, atau ada penyerang yang memintas koneksi internet Anda.}other{Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya sepertinya dari # hari mendatang. Hal ini mungkin disebabkan oleh kesalahan konfigurasi, atau ada penyerang yang memintas koneksi internet Anda.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Diabaikan karena <ph name="POLICY_NAME" /> tidak disetel ke <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> ingin menyimpan data di komputer lokal Anda secara permanen</translation>
<translation id="1713628304598226412">Baki 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Kotak surat 3</translation>
<translation id="1718029547804390981">Dokumen terlalu besar untuk dianotasi</translation>
<translation id="1721424275792716183">* Kolom wajib diisi</translation>
+<translation id="1727613060316725209">Sertifikat valid</translation>
<translation id="1727741090716970331">Tambahkan Nomor Kartu yang Valid</translation>
<translation id="1728677426644403582">Anda melihat sumber halaman web</translation>
<translation id="173080396488393970">Jenis kartu tidak didukung</translation>
@@ -242,7 +249,6 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Coba jalankan Diagnostik Jaringan Windows<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">Server yang akan Anda akses, <ph name="ORIGIN" />, telah menetapkan header yang mengharuskan kebijakan asal diterapkan ke semua permintaan yang ditujukan kepadanya. Namun, format header tersebut salah, yang membuat browser tidak dapat memenuhi permintaan Anda untuk <ph name="SITE" />. Kebijakan asal dapat digunakan oleh operator situs guna mengonfigurasi keamanan dan properti lainnya untuk sebuah situs.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Perbarui frasa sandi sinkronisasi Anda.</translation>
<translation id="1787142507584202372">Tab yang terbuka muncul di sini</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, beberapa tindakan tersedia, tekan Tab untuk melihat semua tindakan</translation>
@@ -275,6 +281,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="1919345977826869612">Iklan</translation>
<translation id="1919367280705858090">Mendapatkan bantuan terkait pesan error tertentu</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Tidak ada}=1{1 situs}other{# situs}}</translation>
+<translation id="1924727005275031552">Baru</translation>
<translation id="1945968466830820669">Anda dapat kehilangan akses ke akun organisasi atau mengalami pencurian identitas. Chromium menyarankan Anda untuk mengubah sandi sekarang.</translation>
<translation id="1947454675006758438">Jepretan di kanan atas</translation>
<translation id="1958218078413065209">Skor tertinggi Anda adalah <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="2042213636306070719">Baki 7</translation>
<translation id="204357726431741734">Login untuk menggunakan sandi yang disimpan di Akun Google Anda</translation>
<translation id="2053111141626950936">Halaman dalam bahasa <ph name="LANGUAGE" /> tidak akan diterjemahkan.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Jika kontrol ini aktif dan statusnya masih berlaku, Chrome akan menentukan grup besar, atau "kohor", yang paling mirip dengan aktivitas penjelajahan terbaru Anda. Pengiklan dapat memilih iklan untuk grup tersebut dan aktivitas penjelajahan Anda tetap bersifat pribadi di perangkat Anda. Grup Anda diperbarui setiap hari.}=1{Jika kontrol ini aktif dan statusnya masih berlaku, Chrome akan menentukan grup besar, atau "kohor", yang paling mirip dengan aktivitas penjelajahan terbaru Anda. Pengiklan dapat memilih iklan untuk grup tersebut dan aktivitas penjelajahan Anda tetap bersifat pribadi di perangkat Anda. Grup Anda diperbarui setiap hari.}other{Jika kontrol ini aktif dan statusnya masih berlaku, Chrome akan menentukan grup besar, atau "kohor", yang paling mirip dengan aktivitas penjelajahan terbaru Anda. Pengiklan dapat memilih iklan untuk grup tersebut dan aktivitas penjelajahan Anda tetap bersifat pribadi di perangkat Anda. Grup Anda diperbarui setiap {NUM_DAYS} hari.}}</translation>
<translation id="2053553514270667976">Kode pos</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 saran}other{# saran}}</translation>
<translation id="2071692954027939183">Notifikasi otomatis diblokir karena Anda biasanya tidak mengizinkannya</translation>
<translation id="2079545284768500474">Urungkan</translation>
<translation id="20817612488360358">Setelan proxy sistem disetel untuk digunakan namun konfigurasi proxy eksplisit juga ditentukan.</translation>
<translation id="2082238445998314030">Hasil <ph name="RESULT_NUMBER" /> dari <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Simpan…</translation>
<translation id="2088086323192747268">Tombol Kelola sinkronisasi, tekan Enter untuk mengelola info apa saja yang Anda sinkronkan di setelan Chrome</translation>
<translation id="2091887806945687916">Suara</translation>
<translation id="2094505752054353250">Ketidakcocokan domain</translation>
@@ -375,6 +384,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="2317259163369394535"><ph name="DOMAIN" /> memerlukan nama pengguna dan sandi.</translation>
<translation id="2330137317877982892">Masa berlaku <ph name="CREDIT_CARD" /> habis pada <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Setelan dikontrol oleh administrator Anda</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ingin menyandingkan</translation>
<translation id="2344028582131185878">Download Otomatis</translation>
<translation id="2346319942568447007">Gambar yang Anda salin</translation>
<translation id="2354001756790975382">Bookmark lain</translation>
@@ -382,8 +392,10 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="2355395290879513365">Penyerang mungkin dapat melihat gambar yang sedang Anda lihat di situs dan mengelabui Anda dengan memodifikasinya.</translation>
<translation id="2356070529366658676">Tanya</translation>
<translation id="2357481397660644965">Perangkat Anda dikelola oleh <ph name="DEVICE_MANAGER" /> dan akun Anda dikelola oleh <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Dalam waktu kurang dari 1 hari}=1{Dalam waktu 1 hari}other{Dalam waktu {NUM_DAYS} hari}}</translation>
<translation id="2359629602545592467">Beberapa</translation>
<translation id="2359808026110333948">Lanjutkan</translation>
+<translation id="2359961752320758691">Nomor kartu virtual Anda diterapkan.</translation>
<translation id="2367567093518048410">Tingkat</translation>
<translation id="2372464001869762664">Setelah mengonfirmasi, detail kartu dari Akun Google Anda akan dibagikan ke situs ini. Temukan CVC di detail Akun Plex Anda.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="239429038616798445">Metode pengiriman tidak tersedia. Coba metode lain.</translation>
<translation id="2396249848217231973">&amp;Urungkan penghapusan</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Lama</translation>
<translation id="2413528052993050574">Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya mungkin dicabut. Hal ini dapat disebabkan oleh kesalahan konfigurasi atau penyerang memotong sambungan Anda.</translation>
<translation id="2414886740292270097">Gelap</translation>
<translation id="2438874542388153331">Empat lubang di kanan</translation>
@@ -421,10 +434,10 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="2521385132275182522">Jepretan di kanan bawah</translation>
<translation id="2523886232349826891">Hanya disimpan di perangkat ini</translation>
<translation id="2524461107774643265">Tambahkan Informasi Lainnya</translation>
-<translation id="2526590354069164005">Desktop</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{dan 1 lainnya}other{dan # lainnya}}</translation>
<translation id="2536110899380797252">Tambahkan Alamat</translation>
<translation id="2539524384386349900">Deteksi</translation>
+<translation id="2541219929084442027">Halaman yang Anda lihat di tab Samaran tidak akan disimpan di histori browser, penyimpanan cookie, atau histori penelusuran setelah Anda menutup semua tab Samaran. File apa pun yang didownload atau bookmark yang dibuat akan tetap disimpan.</translation>
<translation id="2544644783021658368">Dokumen tunggal</translation>
<translation id="254947805923345898">Nilai kebijakan tidak valid.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> mengirimkan tanggapan yang tidak valid.</translation>
@@ -441,9 +454,10 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="2609632851001447353">Variasi</translation>
<translation id="2618023639789766142">C10 (Amplop)</translation>
<translation id="2625385379895617796">Setelan jam terlalu cepat</translation>
-<translation id="2629325967560697240">Untuk mendapatkan tingkat keamanan tertinggi Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />aktifkan perlindungan yang disempurnakan<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
+<translation id="2629325967560697240">Untuk mendapatkan tingkat keamanan tertinggi Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />aktifkan perlindungan yang ditingkatkan<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Alamat IP server <ph name="HOST_NAME" /> tidak dapat ditemukan.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Tidak ditemukan perangkat yang kompatibel.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, tekan Tab lalu Enter untuk menghapus histori penjelajahan, cookie, cache, dan lainnya di setelan Chrome</translation>
<translation id="2650446666397867134">Akses ke file ditolak</translation>
@@ -490,6 +504,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<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="2807052079800581569">Posisi image Y</translation>
+<translation id="2820957248982571256">Memindai...</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>
@@ -497,6 +512,8 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">Situs ini menampilkan iklan yang mengganggu atau menyesatkan.</translation>
+<translation id="287596039013813457">Bersahabat</translation>
+<translation id="2876489322757410363">Keluar dari mode Samaran untuk membayar melalui aplikasi eksternal. Lanjutkan?</translation>
<translation id="2878197950673342043">Lipatan poster</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Penempatan jendela</translation>
@@ -546,7 +563,6 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, tekan Tab lalu Enter untuk menjalankan Pemeriksaan Keamanan di setelan Chrome</translation>
<translation id="3061707000357573562">Layanan Patch</translation>
-<translation id="3064966200440839136">Keluar dari mode samaran untuk membayar melalui aplikasi eksternal. Lanjutkan?</translation>
<translation id="306573536155379004">Game dimulai.</translation>
<translation id="3080254622891793721">Grafis</translation>
<translation id="3086579638707268289">Aktivitas Anda di web sedang dipantau</translation>
@@ -569,7 +585,6 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="315504272643575312">Akun Anda dikelola oleh <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Pulihkan</translation>
<translation id="3162559335345991374">Wi-Fi yang digunakan mungkin mewajibkan Anda mengunjungi halaman masuknya.</translation>
-<translation id="3167968892399408617">Halaman yang Anda lihat di tab samaran tidak akan disimpan dalam histori browser, penyimpanan cookie, atau histori penelusuran setelah Anda menutup semua tab samaran. File apa pun yang didownload atau bookmark yang dibuat akan tetap tersimpan.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Pulau</translation>
<translation id="3176929007561373547">Periksa setelan proxy atau hubungi administrator jaringan untuk
@@ -595,10 +610,12 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<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="3249845759089040423">Groovy</translation>
<translation id="3252266817569339921">Prancis</translation>
<translation id="3266793032086590337">Nilai (bertentangan)</translation>
<translation id="3268451620468152448">Tab Terbuka</translation>
<translation id="3270847123878663523">&amp;Urungkan Pengaturan Ulang</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> ingin terhubung</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Organisasi Anda, <ph name="ENROLLMENT_DOMAIN" />, telah mengirim beberapa info ke situs berikut, seperti setelan atau kebijakan.</translation>
<translation id="3282497668470633863">Tambahkan nama di kartu</translation>
@@ -651,6 +668,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="3428151540071562330">Satu atau beberapa URI template server DnsOverHttpsTemplates tidak valid dan tidak akan digunakan.</translation>
<translation id="3431636764301398940">Simpan kartu ini ke perangkat ini</translation>
<translation id="3432601291244612633">Tutup halaman</translation>
+<translation id="3435738964857648380">Keamanan</translation>
<translation id="3435896845095436175">Aktifkan</translation>
<translation id="3438829137925142401">Gunakan sandi yang disimpan di Akun Google Anda</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -692,7 +710,10 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="3584299510153766161">Dua lubang di bawah</translation>
<translation id="3586931643579894722">Sembunyikan detail</translation>
<translation id="3587738293690942763">Tengah</translation>
+<translation id="3590643883886679995">Data login akan disimpan di perangkat ini setelah Anda keluar dari mode Samaran.</translation>
+<translation id="359126217934908072">Bulan/Tahun:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Anda dapat mereset grup kapan saja. Perlu waktu sekitar 1 hari untuk bergabung ke grup baru.}=1{Anda dapat mereset grup kapan saja. Perlu waktu sekitar 1 hari untuk bergabung ke grup baru.}other{Anda dapat mereset grup kapan saja. Perlu waktu sekitar {NUM_DAYS} hari untuk bergabung ke grup baru.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplikasi diblokir oleh administrator Anda</translation>
<translation id="3608932978122581043">Feed orientasi</translation>
@@ -701,13 +722,13 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="3615877443314183785">Masukkan tanggal masa berlaku yang valid</translation>
<translation id="36224234498066874">Hapus Data Penjelajahan...</translation>
<translation id="362276910939193118">Tampilkan Histori Lengkap</translation>
-<translation id="3625635938337243871">Data login akan disimpan di perangkat ini setelah Anda keluar dari mode samaran.</translation>
<translation id="3630155396527302611">Jika sudah tercantum sebagai program yang diizinkan untuk mengakses jaringan,
coba hapus dari daftar dan tambahkan lagi.</translation>
<translation id="3630699740441428070">Administrator perangkat ini telah mengonfigurasi koneksi jaringan Anda, yang memungkinkan mereka untuk melihat traffic jaringan, termasuk situs yang Anda kunjungi.</translation>
<translation id="3631244953324577188">Biometrik</translation>
<translation id="3633738897356909127">Tombol Update Chrome, tekan Enter untuk mengupdate Chrome dari setelan Chrome</translation>
<translation id="3634530185120165534">Baki 5</translation>
+<translation id="3637662659967048211">Simpan ke Akun Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplikasi:</translation>
<translation id="3650584904733503804">Validasi berhasil</translation>
@@ -748,6 +769,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="3781428340399460090">Merah Muda Terang</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Perangkat bluetooth</translation>
+<translation id="3787675388804467730">Nomor kartu virtual</translation>
<translation id="3787705759683870569">Masa berlaku <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Ukuran 16</translation>
<translation id="3789841737615482174">Instal</translation>
@@ -767,6 +789,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="3841184659773414994">Pengendali File</translation>
<translation id="385051799172605136">Kembali</translation>
<translation id="3858027520442213535">Perbarui tanggal dan waktu</translation>
+<translation id="3881478300875776315">Tampilkan lebih sedikit baris</translation>
<translation id="3884278016824448484">Pengenal perangkat bertentangan</translation>
<translation id="3885155851504623709">Paroki</translation>
<translation id="388632593194507180">Pemantauan Terdeteksi</translation>
@@ -792,6 +815,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="397105322502079400">Menghitung...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> diblokir.</translation>
<translation id="3973357910713125165">Tombol Jalankan Pemeriksaan Keamanan Chrome, tekan Enter untuk menjalankan Pemeriksaan Keamanan di setelan Chrome</translation>
+<translation id="3986705137476756801">Nonaktifkan Teks Otomatis untuk saat ini</translation>
<translation id="3987405730340719549">Chrome telah menetapkan bahwa situs ini mungkin palsu atau menipu.
Jika Anda yakin bahwa ini keliru, kunjungi https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -883,13 +907,14 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="4275830172053184480">Mulai ulang perangkat Anda</translation>
<translation id="4277028893293644418">Reset sandi</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="4287885627794386150">Memenuhi syarat untuk uji coba tetapi tidak aktif</translation>
<translation id="4297502707443874121">Thumbnail untuk halaman <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Luaskan</translation>
<translation id="4300675098767811073">Beberapa lubang di kanan</translation>
<translation id="4302514097724775343">Ketuk dinosaurus untuk bermain</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">File Anda tidak dapat diakses</translation>
-<translation id="4305817255990598646">Alihkan</translation>
+<translation id="4306529830550717874">Simpan alamat?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokir (default)</translation>
<translation id="4314815835985389558">Kelola sinkronisasi</translation>
@@ -916,6 +941,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="4377125064752653719">Anda berusaha menjangkau <ph name="DOMAIN" />, tetapi sertifikat yang disajikan oleh server telah dibatalkan oleh penerbitnya. Artinya informasi rahasia keamanan yang disajikan tidak dapat dipercaya. Anda mungkin sedang berkomunikasi dengan penyerang.</translation>
<translation id="4378154925671717803">Ponsel</translation>
<translation id="4390472908992056574">Tepi</translation>
+<translation id="4406883609789734330">Teks Otomatis</translation>
<translation id="4406896451731180161">hasil penelusuran</translation>
<translation id="4408413947728134509">Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Anda baru saja memasukkan sandi ke situs penipuan. Chrome merekomendasikan Anda untuk membuka <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />, serta situs lain tempat Anda menggunakan sandi ini dan mengubahnya sekarang.</translation>
@@ -928,7 +954,6 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Penggunaan proxy dinonaktifkan tetapi konfigurasi proxy yang eksplisit ditentukan.</translation>
<translation id="4464826014807964867">Situs dengan info dari organisasi Anda</translation>
-<translation id="4466881336512663640">Perubahan pada formulir akan hilang. Yakin ingin melanjutkan?</translation>
<translation id="4476953670630786061">Formulir ini tidak aman. Isi otomatis telah dinonaktifkan.</translation>
<translation id="4477350412780666475">Lagu Berikutnya</translation>
<translation id="4482953324121162758">Situs ini tidak akan diterjemahkan.</translation>
@@ -962,6 +987,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="4594403342090139922">&amp;Urungkan Penghapusan</translation>
<translation id="4597348597567598915">Ukuran 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Berpengaruh</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Disertai cashback</translation>
<translation id="4636930964841734540">Info</translation>
@@ -981,6 +1007,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Sisi</translation>
+<translation id="4702656508969495934">Teks Otomatis akan terlihat, gunakan pengalih jendela untuk memfokuskan</translation>
<translation id="4708268264240856090">Sambungan Anda terganggu</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Jalankan Diagnostik Jaringan Windows<ph name="END_LINK" /></translation>
@@ -994,6 +1021,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="4738601419177586157">Saran penelusuran <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Kelola sandi...</translation>
<translation id="4744603770635761495">Jalur Yang Dapat Dijalankan</translation>
+<translation id="4749011317274908093">Anda masuk mode Samaran</translation>
<translation id="4750917950439032686">Informasi Anda (misalnya, sandi atau nomor kartu kredit) bersifat pribadi saat dikirimkan ke situs ini.</translation>
<translation id="4756388243121344051">&amp;Riwayat</translation>
<translation id="4758311279753947758">Tambahkan info kontak</translation>
@@ -1023,6 +1051,8 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="4813512666221746211">Kesalahan jaringan</translation>
<translation id="4816492930507672669">Paskan dengan halaman</translation>
<translation id="4819347708020428563">Edit anotasi dalam tampilan default?</translation>
+<translation id="4825507807291741242">Kuat</translation>
+<translation id="4838327282952368871">Sangat Indah</translation>
<translation id="484462545196658690">Otomatis</translation>
<translation id="4850886885716139402">Lihat</translation>
<translation id="485316830061041779">Jerman</translation>
@@ -1159,6 +1189,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="5314967030527622926">Pembuat buklet</translation>
<translation id="5316812925700871227">Putar berlawanan arah jarum jam</translation>
<translation id="5317780077021120954">Simpan</translation>
+<translation id="5321288445143113935">Dimaksimalkan</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> dari <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Pilih Info Kontak</translation>
<translation id="5327248766486351172">Nama</translation>
@@ -1166,11 +1197,13 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="5332219387342487447">Metode Pengiriman</translation>
<translation id="5333022057423422993">Chrome menemukan sandi yang baru saja Anda gunakan dalam pelanggaran data. Untuk mengamankan akun, sebaiknya periksa sandi tersimpan Anda.</translation>
<translation id="5334013548165032829">Log sistem mendetail</translation>
+<translation id="5334145288572353250">Simpan Alamat?</translation>
<translation id="5340250774223869109">Aplikasi diblokir</translation>
<translation id="534295439873310000">Perangkat NFC</translation>
<translation id="5344579389779391559">Halaman ini mungkin mencoba menagih Anda</translation>
<translation id="5355557959165512791">Anda tidak dapat membuka <ph name="SITE" /> sekarang karena sertifikatnya telah dicabut. Error jaringan dan serangan biasanya bersifat sementara, sehingga halaman ini mungkin akan berfungsi nanti.</translation>
<translation id="536296301121032821">Gagal menyimpan setelan kebijakan</translation>
+<translation id="5363309033720083897">Port serial yang diizinkan oleh administrator Anda</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="5386426401304769735">Rantai sertifikat untuk situs ini berisi sertifikat yang ditandatangani menggunakan SHA-1.</translation>
@@ -1179,6 +1212,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="5398772614898833570">Iklan diblokir</translation>
<translation id="5400836586163650660">Grey</translation>
<translation id="540969355065856584">Server ini tidak dapat membuktikan bahwa ini adalah <ph name="DOMAIN" />; sertifikat keamanannya saat ini tidak valid. Hal ini mungkin disebabkan oleh kesalahan konfigurasi atau ada penyerang yang mengganggu koneksi internet Anda.</translation>
+<translation id="541143247543991491">Cloud (seluruh sistem)</translation>
<translation id="541416427766103491">Tempat kertas 4</translation>
<translation id="5421136146218899937">Hapus data penjelajahan...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> ingin mengirimkan notifikasi kepada Anda</translation>
@@ -1192,6 +1226,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="5455374756549232013">Stempel waktu kebijakan salah</translation>
<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="5463625433003343978">Mencari perangkat ...</translation>
<translation id="5469868506864199649">Italia</translation>
<translation id="5470861586879999274">&amp;Ulangi pengeditan</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1241,7 +1276,6 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="5624120631404540903">Kelola sandi</translation>
<translation id="5629630648637658800">Gagal memuat setelan kebijakan</translation>
<translation id="5631439013527180824">Token pengelolaan perangkat tidak valid</translation>
-<translation id="5632627355679805402">Data Anda dienkripsi dengan <ph name="BEGIN_LINK" />sandi Google<ph name="END_LINK" /> mulai <ph name="TIME" />. Masukkan frasa sandi untuk memulai sinkronisasi.</translation>
<translation id="5633066919399395251">Penyerang yang saat ini berada di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mungkin berusaha menginstal program berbahaya di komputer Anda untuk mencuri atau menghapus informasi Anda (misalnya, foto, sandi, pesan, dan kartu kredit). <ph name="BEGIN_LEARN_MORE_LINK" />Pelajari lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Konten penipuan diblokir.</translation>
<translation id="5644090287519800334">Perpindahan image X sisi 1</translation>
@@ -1280,12 +1314,12 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="5785756445106461925">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 tampilan perangkat.</translation>
<translation id="5786044859038896871">Ingin mengisi informasi kartu?</translation>
<translation id="578633867165174378">Chrome menemukan sandi yang baru saja Anda gunakan dalam pelanggaran data. Sebaiknya ubah sandi ini sekarang.</translation>
-<translation id="5798290721819630480">Hapus perubahan?</translation>
<translation id="5803412860119678065">Ingin mengisi <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Izin</translation>
<translation id="5804427196348435412">Gunakan perangkat NFC</translation>
<translation id="5810442152076338065">Sambungan Anda ke <ph name="DOMAIN" /> dienkripsi menggunakan cipher suite yang sudah usang.</translation>
<translation id="5813119285467412249">&amp;Ulangi Penambahan</translation>
+<translation id="5817918615728894473">Sandingkan</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Kartu ini akan ditagih saat Anda membayar, tetapi nomor yang sebenarnya tidak akan dibagikan ke situs ini. Sebagai keamanan tambahan, CVC sementara akan diberikan.}other{Kartu yang Anda pilih akan ditagih saat Anda membayar, tetapi nomor yang sebenarnya tidak akan dibagikan ke situs ini. Sebagai keamanan tambahan, CVC sementara akan diberikan.}}</translation>
<translation id="5826507051599432481">Common Name (CN)</translation>
<translation id="5838278095973806738">Jangan masukkan informasi sensitif apa pun di situs ini (misalnya, sandi atau kartu kredit), karena penyerang dapat mencurinya.</translation>
@@ -1293,6 +1327,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="5855253129151731373">Hostname situs ini terlihat mirip dengan <ph name="LOOKALIKE_DOMAIN" />. Penyerang terkadang meniru situs dengan membuat perubahan kecil dan sulit terlihat pada nama domain.
Jika Anda yakin bahwa ini keliru, kunjungi https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Nonaktif</translation>
<translation id="5862579898803147654">Tempat kertas 8</translation>
<translation id="5863847714970149516">Halaman berikutnya mungkin mencoba menagih Anda.</translation>
<translation id="5866257070973731571">Tambahkan Nomor Telepon</translation>
@@ -1309,6 +1344,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="5913377024445952699">Tangkapan layar dijeda</translation>
<translation id="59174027418879706">Diaktifkan</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 terpakai}other{# terpakai}}</translation>
<translation id="5921185718311485855">Aktif</translation>
<translation id="5921639886840618607">Simpan kartu ke Akun Google?</translation>
<translation id="5922853866070715753">Hampir selesai</translation>
@@ -1328,6 +1364,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="5989320800837274978">Baik proxy server tetap ataupun URL skrip .pac tidak ditentukan.</translation>
<translation id="5992691462791905444">Lipatan format engineering Z</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> hasil untuk '<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">Klasik</translation>
<translation id="6008122969617370890">Urutan N-ke-1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Periksa sandi Anda</translation>
@@ -1349,6 +1386,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="6045164183059402045">Template imposisi</translation>
<translation id="6047233362582046994">Jika Anda memahami risiko keamanan tersebut, Anda dapat <ph name="BEGIN_LINK" />mengunjungi situs ini<ph name="END_LINK" /> sebelum aplikasi berbahaya tersebut dihapus.</translation>
<translation id="6047927260846328439">Konten ini mungkin mencoba mengelabui Anda agar menginstal software atau mengungkapkan informasi pribadi. <ph name="BEGIN_LINK" />Tetap tampilkan<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Tekan dan tahan |<ph name="ACCELERATOR" />| untuk keluar dari layar penuh</translation>
<translation id="6049488691372270142">Pengiriman halaman</translation>
<translation id="6051221802930200923">Anda tidak dapat membuka <ph name="SITE" /> sekarang karena situs menggunakan penyematan sertifikat. Error jaringan dan serangan biasanya bersifat sementara, sehingga halaman ini mungkin akan berfungsi nanti.</translation>
<translation id="6051898664905071243">Jumlah halaman:</translation>
@@ -1365,6 +1403,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<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>
<translation id="6116338172782435947">Melihat teks dan gambar yang disalin ke papan klip</translation>
<translation id="6120179357481664955">Ingat ID UPI Anda?</translation>
+<translation id="6123290840358279103">Lihat kartu virtual</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Periksa semua kabel dan boot ulang router, modem, atau perangkat
jaringan lain yang mungkin Anda gunakan.</translation>
@@ -1401,6 +1440,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="6289939620939689042">Warna Halaman</translation>
<translation id="6290238015253830360">Artikel yang disarankan ditampilkan di sini</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Asisten Google di Chrome sedang dihentikan</translation>
<translation id="6305205051461490394"><ph name="URL" /> tidak dapat dijangkau.</translation>
<translation id="6312113039770857350">Halaman web tidak tersedia</translation>
@@ -1426,6 +1466,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="6390200185239044127">Lipatan Z setengah</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Penempelan dari <ph name="ORIGIN_NAME" /> ke lokasi ini diblokir oleh kebijakan administrator</translation>
+<translation id="6398765197997659313">Keluar dari tampilan layar penuh</translation>
<translation id="6401136357288658127">Kebijakan ini tidak digunakan lagi. Sebaiknya Anda menggunakan kebijakan <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Edit bookmark</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1438,7 +1479,6 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="6428450836711225518">Verifikasi nomor telepon Anda</translation>
<translation id="6433490469411711332">Edit info kontak</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> menolak untuk tersambung.</translation>
-<translation id="6434309073475700221">Buang</translation>
<translation id="6440503408713884761">Diabaikan</translation>
<translation id="6443406338865242315">Ekstensi dan plugin yang telah Anda instal</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1481,6 +1521,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="6624427990725312378">Info Kontak</translation>
<translation id="6626291197371920147">Tambahkan kartu yang valid</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Penelusuran</translation>
+<translation id="6630043285902923878">Mencari perangkat USB ...</translation>
<translation id="6630809736994426279">Penyerang yang saat ini berada di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mungkin berusaha menginstal program berbahaya di Mac Anda untuk mencuri atau menghapus informasi Anda (misalnya, foto, sandi, pesan, dan kartu kredit). <ph name="BEGIN_LEARN_MORE_LINK" />Pelajari lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Hapus</translation>
@@ -1496,6 +1537,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="6671697161687535275">Hapus saran formulir dari Chromium?</translation>
<translation id="6685834062052613830">Keluar dan selesaikan penyiapan</translation>
<translation id="6687335167692595844">Ukuran font diminta</translation>
+<translation id="6688743156324860098">Perbarui…</translation>
<translation id="6689249931105087298">Relatif dengan kompresi titik hitam</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="6698381487523150993">Dibuat:</translation>
@@ -1511,6 +1553,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="6744009308914054259">Sambil menunggu koneksi, Anda dapat mengunjungi Hasil Download untuk membaca artikel secara offline.</translation>
<translation id="6753269504797312559">Nilai kebijakan</translation>
<translation id="6757797048963528358">Perangkat Anda sedang dalam mode tidur.</translation>
+<translation id="6767985426384634228">Perbarui Alamat?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violet</translation>
@@ -1533,6 +1576,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome menyederhanakan halaman ini agar lebih mudah dibaca. Chrome mengambil halaman asli melalui koneksi yang tidak aman.</translation>
<translation id="6891596781022320156">Tingkat kebijakan tidak didukung.</translation>
+<translation id="6895143722905299846">Nomor virtual:</translation>
<translation id="6895330447102777224">Kartu telah dikonfirmasi</translation>
<translation id="6897140037006041989">Agen Pengguna</translation>
<translation id="6898699227549475383">Organisasi (O)</translation>
@@ -1568,10 +1612,10 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="7004583254764674281">Gunakan Windows Hello untuk mengonfirmasi kartu lebih cepat</translation>
<translation id="7006930604109697472">Tetap kirim</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Setelan Pengubahan Ukuran</translation>
<translation id="7014741021609395734">Tingkat zoom</translation>
<translation id="7016992613359344582">Tagihan ini bisa hanya satu kali atau berulang, dan mungkin tidak pasti.</translation>
<translation id="7029809446516969842">Sandi</translation>
+<translation id="7030436163253143341">Sertifikat tidak valid</translation>
<translation id="7031646650991750659">Aplikasi Google Play yang telah diinstal</translation>
<translation id="7050187094878475250">Anda berusaha menjangkau <ph name="DOMAIN" />, namun server memberikan sertifikat yang masa berlakunya terlalu lama untuk dapat dipercaya.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Kartu ini tidak dapat disimpan sekarang}other{Kartu-kartu ini tidak dapat disimpan sekarang}}</translation>
@@ -1639,12 +1683,14 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="7300012071106347854">Biru Kobalt</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Tinggi</translation>
+<translation id="7305756307268530424">Mulai lebih lambat</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Bantuan Koneksi</translation>
<translation id="7323804146520582233">Sembunyikan bagian "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Penggantian akun lokal perangkat</translation>
<translation id="7333654844024768166">Anda baru saja memasukkan sandi ke situs penipuan. Chromium merekomendasikan Anda untuk membuka <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />, serta situs lain tempat Anda menggunakan sandi ini dan mengubahnya sekarang.</translation>
<translation id="7334320624316649418">&amp;Ulangi pengaturan ulang</translation>
+<translation id="7337248890521463931">Tampilkan lebih banyak baris</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>
@@ -1652,6 +1698,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Baris Perintah</translation>
<translation id="7359588939039777303">Iklan diblokir.</translation>
+<translation id="7363096869660964304">Namun, Anda masih dapat terlihat. Menggunakan mode Samaran tidak menyembunyikan penjelajahan Anda dari atasan, internet service provider, atau situs yang Anda buka.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, tekan Tab lalu Enter untuk menambahkan dan mengelola alamat di setelan Chrome</translation>
<translation id="7365849542400970216">Tahu penggunaan perangkat Anda?</translation>
<translation id="7372973238305370288">hasil penelusuran</translation>
@@ -1662,7 +1709,9 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="7378594059915113390">Kontrol Media</translation>
<translation id="7378627244592794276">Tidak</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Tidak berlaku</translation>
<translation id="7390545607259442187">Konfirmasi Kartu</translation>
+<translation id="7392089738299859607">Perbarui Alamat</translation>
<translation id="7399802613464275309">Pemeriksaan Keamanan</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> Anda dikelola</translation>
@@ -1677,6 +1726,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
&lt;li&gt;Buka &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Pusat bantuan Chrome&lt;/a&gt; untuk mempelajari cara menghapus software tersebut secara permanen dari komputer
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Cantik</translation>
<translation id="7416351320495623771">Kelola Sandi...</translation>
<translation id="7419106976560586862">Jalur Profil</translation>
<translation id="7437289804838430631">Tambahkan Info Kontak</translation>
@@ -1692,7 +1742,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="7481312909269577407">Maju</translation>
<translation id="7485870689360869515">Tidak ada data yang ditemukan.</translation>
<translation id="7495528107193238112">Konten ini diblokir. Hubungi pemilik situs untuk memperbaiki masalah.</translation>
-<translation id="7498234416455752244">Lanjut mengedit</translation>
+<translation id="7498193950643227031">Aplikasi mungkin menampilkan perilaku yang tidak terduga jika diubah ukurannya. Anda kini dapat membatasi kemampuan untuk mengubah ukuran aplikasi di <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Anda baru saja memasukkan sandi ke situs penipuan. Chromium merekomendasikan Anda memeriksa sandi yang disimpan untuk <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, dan situs lain tempat Anda menggunakan sandi ini sekarang.</translation>
<translation id="7508255263130623398">ID perangkat kebijakan yang dikembalikan kosong atau tidak cocok dengan ID perangkat saat ini</translation>
<translation id="7508870219247277067">Hijau Avokad</translation>
@@ -1712,6 +1762,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<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="755279583747225797">Uji coba aktif</translation>
<translation id="7552846755917812628">Coba tips berikut:</translation>
<translation id="7554475479213504905">Tetap muat ulang dan tampilkan</translation>
<translation id="7554791636758816595">Tab Baru</translation>
@@ -1730,7 +1781,6 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, tekan Tab lalu Enter untuk melihat dan mengelola sandi di setelan Chrome</translation>
-<translation id="7615602087246926389">Anda sudah memiliki data yang dienkripsi menggunakan versi sandi Akun Google yang berbeda. Masukkan sandi di bawah.</translation>
<translation id="7616645509853975347">Administrator Anda telah mengaktifkan Chrome Enterprise Connectors di browser Anda. Konektor ini memiliki akses ke beberapa data Anda.</translation>
<translation id="7619838219691048931">Lembar akhir</translation>
<translation id="762844065391966283">Satu per satu</translation>
@@ -1795,13 +1845,12 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="782886543891417279">Wi-Fi yang digunakan (<ph name="WIFI_NAME" />) mungkin mewajibkan Anda mengunjungi halaman masuknya.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Tidak ada}=1{1 aplikasi (<ph name="EXAMPLE_APP_1" />)}=2{2 aplikasi (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# aplikasi (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Namun, Anda masih dapat terlihat. Login ke mode samaran tidak menyembunyikan penjelajahan Anda dari atasan, penyedia layanan internet, atau situs web yang Anda kunjungi.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Membuka file dengan jenis file yang dikaitkan.</translation>
<translation id="7862185352068345852">Keluar dari situs?</translation>
<translation id="7865448901209910068">Paling cepat</translation>
<translation id="7874263914261512992">Anda baru saja memasukkan sandi ke situs penipuan. Chrome merekomendasikan Anda memeriksa sandi yang disimpan untuk <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, dan situs lain tempat Anda menggunakan sandi ini sekarang.</translation>
<translation id="7878562273885520351">Sandi Anda mungkin disusupi</translation>
+<translation id="7880146494886811634">Simpan Alamat</translation>
<translation id="7882421473871500483">Cokelat</translation>
<translation id="7887683347370398519">Periksa CVC dan coba lagi</translation>
<translation id="7887885240995164102">Masuk ke mode picture-in-picture</translation>
@@ -1809,6 +1858,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="7894280532028510793">Jika ejaan sudah benar, <ph name="BEGIN_LINK" />coba jalankan Diagnostik Jaringan<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Tidak dikenal</translation>
+<translation id="793209273132572360">Perbarui alamat?</translation>
<translation id="7932579305932748336">Lapisan</translation>
<translation id="79338296614623784">Masukkan nomor telepon yang valid</translation>
<translation id="7934052535022478634">Pembayaran selesai</translation>
@@ -1879,6 +1929,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="8175796834047840627">Chrome menawarkan untuk menyimpan informasi kartu ke Akun Google Anda karena Anda sedang login. Anda dapat mengubah perilaku ini di setelan.</translation>
<translation id="8176440868214972690">Administrator perangkat ini telah mengirim beberapa info ke situs berikut, seperti setelan atau kebijakan.</translation>
<translation id="8184538546369750125">Gunakan default global (Izinkan)</translation>
+<translation id="8193086767630290324">Tindakan yang dilakukan dengan data yang ditandai sebagai rahasia</translation>
<translation id="8194797478851900357">&amp;Urungkan Pemindahan</translation>
<translation id="8201077131113104583">URL pembaruan tidak valid untuk ekstensi dengan ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Ringkasan pesanan</translation>
@@ -1901,6 +1952,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="8249296373107784235">Batalkan</translation>
<translation id="8249320324621329438">Terakhir diambil:</translation>
<translation id="8253091569723639551">Perlu alamat penagihan</translation>
+<translation id="8257387598443225809">Aplikasi ini didesain untuk perangkat seluler</translation>
<translation id="825929999321470778">Tampilkan Semua Sandi Tersimpan</translation>
<translation id="8261506727792406068">Hapus</translation>
<translation id="8262952874573525464">Jahitan tepi di bawah</translation>
@@ -2022,7 +2074,6 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="8719528812645237045">Beberapa lubang di atas</translation>
<translation id="8725066075913043281">Coba lagi</translation>
<translation id="8726549941689275341">Ukuran halaman:</translation>
-<translation id="8728672262656704056">Anda masuk mode samaran</translation>
<translation id="8730621377337864115">Selesai</translation>
<translation id="8731544501227493793">Tombol Kelola sandi, tekan Enter untuk melihat dan mengelola sandi di setelan Chrome</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> Anda dikelola oleh <ph name="MANAGER" /></translation>
@@ -2099,6 +2150,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="9020542370529661692">Halaman ini telah diterjemahkan ke <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Tidak valid)</translation>
+<translation id="9030265603405983977">Monokrom</translation>
<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>
@@ -2122,6 +2174,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="91108059142052966">Kebijakan administrator menonaktifkan berbagi layar dengan <ph name="APPLICATION_TITLE" /> saat konten rahasia terlihat</translation>
<translation id="9114524666733003316">Mengonfirmasi kartu...</translation>
<translation id="9114581008513152754">Browser ini tidak dikelola oleh 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="9117930699067497412">Baru</translation>
<translation id="9119042192571987207">Diupload</translation>
<translation id="9128016270925453879">Kebijakan dimuat</translation>
<translation id="9128870381267983090">Sambungkan ke jaringan</translation>
@@ -2140,6 +2193,7 @@ Jika tidak, ini akan diblokir oleh setelan privasi Anda. Ini akan memungkinkan k
<translation id="9170848237812810038">&amp;Urung</translation>
<translation id="9171296965991013597">Tutup aplikasi?</translation>
<translation id="9173282814238175921">Dokumen tunggal/Lembar baru</translation>
+<translation id="9173995187295789444">Memindai perangkat Bluetooth...</translation>
<translation id="917450738466192189">Sertifikat server tidak valid.</translation>
<translation id="9174917557437862841">Tombol beralih tab, tekan Enter untuk beralih ke tab ini</translation>
<translation id="9179703756951298733">Kelola informasi pembayaran dan kartu kredit Anda di setelan Chrome</translation>
diff --git a/chromium/components/strings/components_strings_is.xtb b/chromium/components/strings/components_strings_is.xtb
index 869a9103250..e471fce4b59 100644
--- a/chromium/components/strings/components_strings_is.xtb
+++ b/chromium/components/strings/components_strings_is.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Ef hakað er við þetta mun Chrome geyma afrit af kortinu þínu í þessu tæki til að flýta fyrir útfyllingu eyðublaða.</translation>
<translation id="1110994991967754504">Velja heimild fyrir <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">Aft&amp;urkalla nýja röðun</translation>
+<translation id="1123753900084781868">Skjátextar í rauntíma eru ekki tiltækir núna</translation>
<translation id="1125573121925420732">Viðvaranir geta verið tíðar á meðan vefsvæði uppfæra öryggisvarnir sínar. Þetta ætti að lagast fljótlega.</translation>
<translation id="112840717907525620">Skyndiminni reglu í lagi</translation>
<translation id="1130564665089811311">Hnappurinn Þýða síðu, ýttu á Enter til að þýða þessa síðu með Google Translate</translation>
@@ -74,6 +75,7 @@ Ef þú gerir það ekki loka persónuverndarstillingar þínar á þennan aðga
<translation id="1240347957665416060">Heiti tækisins þíns</translation>
<translation id="124116460088058876">Fleiri tungumál</translation>
<translation id="1243027604378859286">Höfundur:</translation>
+<translation id="1246424317317450637">Feitletur</translation>
<translation id="1250759482327835220">Til að greiða hraðar næst geturðu vistað kortið og nafn og heimilisfang greiðanda á Google reikningnum.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (samstillt)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ef þú reynir að fara á vefsíðu og hún opnast ekki skaltu byrja á því að reyna að leysa vandann á eftirfarandi máta:&lt;/p&gt;
@@ -156,6 +158,7 @@ Ef þú gerir það ekki loka persónuverndarstillingar þínar á þennan aðga
<translation id="1476595624592550506">Breyta aðgangsorði</translation>
<translation id="1484290072879560759">Velja heimilisfang til sendingar</translation>
<translation id="1492194039220927094">Sending reglna:</translation>
+<translation id="1495677929897281669">Aftur á flipa</translation>
<translation id="1501859676467574491">Sýna kort af Google reikningnum þínum</translation>
<translation id="1507202001669085618">&lt;p&gt;Þú sérð þessa villu ef þú notar Wi-Fi gátt sem þú þarft að skrá þig inn á áður en þú tengist internetinu.&lt;/p&gt;
&lt;p&gt;Til að leysa vandann skaltu smella á &lt;strong&gt;Tengjast&lt;/strong&gt; á síðunni sem þú ert að reyna að opna.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Ef þú gerir það ekki loka persónuverndarstillingar þínar á þennan aðga
<translation id="1532118530259321453">Þessi síða segir</translation>
<translation id="153384715582417236">Það er allt og sumt í bili</translation>
<translation id="1536390784834419204">Þýða síðu</translation>
+<translation id="1539840569003678498">Skýrsla send:</translation>
<translation id="154408704832528245">Velja heimilisfang til afhendingar</translation>
<translation id="1549470594296187301">JavaScript verður að vera virkt til að hægt sé að nota þennan eiginleika.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -214,16 +218,19 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="1682696192498422849">Skammhlið fyrst</translation>
<translation id="168693727862418163">Ekki tókst að staðfesta gildi þessarar reglu gagnvart skema hennar og hún verður hunsuð.</translation>
<translation id="168841957122794586">Vottorð netþjónsins inniheldur ótraustan dulmálslykil.</translation>
+<translation id="1696290444144917273">Skoða frekari upplýsingar um sýndarkort</translation>
<translation id="1697532407822776718">Nú er allt tilbúið!</translation>
<translation id="1703835215927279855">Bréf</translation>
<translation id="1706954506755087368">{1,plural, =1{Þessi þjónn gat ekki sannað að hann væri <ph name="DOMAIN" />; öryggisvottorð hans er að sögn gefið út á morgun. Þetta kann að orsakast af rangri stillingu eða tölvuþrjóti sem hefur komist inn í tenginguna.}one{Þessi þjónn gat ekki sannað að hann væri <ph name="DOMAIN" />; öryggisvottorð hans er að sögn gefið út eftir # dag. Þetta kann að orsakast af rangri stillingu eða tölvuþrjóti sem hefur komist inn í tenginguna.}other{Þessi þjónn gat ekki sannað að hann væri <ph name="DOMAIN" />; öryggisvottorð hans er að sögn gefið út eftir # daga. Þetta kann að orsakast af rangri stillingu eða tölvuþrjóti sem hefur komist inn í tenginguna.}}</translation>
<translation id="1710259589646384581">Stýrikerfi</translation>
+<translation id="1711234383449478798">Hunsað vegna þess að <ph name="POLICY_NAME" /> er ekki stillt á <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> vill fá að geyma gögn varanlega í tölvunni þinni</translation>
<translation id="1713628304598226412">Bakki 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Pósthólf 3</translation>
<translation id="1718029547804390981">Þetta skjal er of stórt til að hægt sé að skrifa skýringar í það</translation>
<translation id="1721424275792716183">* Reiturinn má ekki vera auður</translation>
+<translation id="1727613060316725209">Vottorðið er gilt</translation>
<translation id="1727741090716970331">Bæta við gildu kortanúmeri</translation>
<translation id="1728677426644403582">Þú ert að skoða uppruna vefsíðu</translation>
<translation id="173080396488393970">Þessi kortategund er ekki studd</translation>
@@ -247,7 +254,6 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
beiðni þína fyrir <ph name="SITE" />. Notendur síðu geta notað upprunareglur
til að stilla öryggi og aðra eiginleika síðu.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Uppfærðu aðgangsorðið þitt fyrir samstillingu.</translation>
<translation id="1787142507584202372">Opnir flipar birtast hér</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, margar aðgerðir eru í boði, ýttu á Tab til að fletta í gegnum þær</translation>
@@ -280,6 +286,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="1919345977826869612">Auglýsingar</translation>
<translation id="1919367280705858090">Fáðu aðstoð varðandi einstök villuskilaboð</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ekkert}=1{Eitt vefsvæði}one{# vefsvæði}other{# vefsvæði}}</translation>
+<translation id="1924727005275031552">Nýtt</translation>
<translation id="1945968466830820669">Þú gætir misst aðgang að fyrirtækisreikningnum eða orðið fyrir auðkennisstuldi. Chromium mælir með því að þú skiptir um aðgangsorð núna.</translation>
<translation id="1947454675006758438">Hefti efst til hægri</translation>
<translation id="1958218078413065209">Stigametið þitt er <ph name="SCORE" />.</translation>
@@ -302,12 +309,14 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="2042213636306070719">Bakki 7</translation>
<translation id="204357726431741734">Skráðu þig inn til að nota aðgangsorð sem eru vistuð á Google reikningnum þínum</translation>
<translation id="2053111141626950936">Síður á þessu tungumáli verða ekki þýddar: <ph name="LANGUAGE" />.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Þegar kveikt er á þessari stýringu og staða hennar er virk metur Chrome hvaða stóra flokki eða „hópi“ fólks nýleg vafranotkun þín líkist mest. Auglýsendur geta valið auglýsingar fyrir hópinn og nýlegri vafranotkun þinni er haldið lokaðri í tækinu. Hópurinn þinn er uppfærður daglega.}=1{Þegar kveikt er á þessari stýringu og staða hennar er virk metur Chrome hvaða stóra flokki eða „hópi“ fólks nýleg vafranotkun þín líkist mest. Auglýsendur geta valið auglýsingar fyrir hópinn og nýlegri vafranotkun þinni er haldið lokaðri í tækinu. Hópurinn þinn er uppfærður daglega.}one{Þegar kveikt er á þessari stýringu og staða hennar er virk metur Chrome hvaða stóra flokki eða „hópi“ fólks nýleg vafranotkun þín líkist mest. Auglýsendur geta valið auglýsingar fyrir hópinn og nýlegri vafranotkun þinni er haldið lokaðri í tækinu. Hópurinn þinn er uppfærður á {NUM_DAYS} dags fresti.}other{Þegar kveikt er á þessari stýringu og staða hennar er virk metur Chrome hvaða stóra flokki eða „hópi“ fólks nýleg vafranotkun þín líkist mest. Auglýsendur geta valið auglýsingar fyrir hópinn og nýlegri vafranotkun þinni er haldið lokaðri í tækinu. Hópurinn þinn er uppfærður á {NUM_DAYS} daga fresti.}}</translation>
<translation id="2053553514270667976">Póstnúmer</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{Ein tillaga}one{# tillaga}other{# tillögur}}</translation>
<translation id="2071692954027939183">Lokað var sjálfkrafa á tilkynningar því þú leyfir þær yfirleitt ekki</translation>
<translation id="2079545284768500474">Afturkalla</translation>
<translation id="20817612488360358">Valið er að nota proxy-stillingar kerfis en skýr proxy-stilling er einnig tilgreind.</translation>
<translation id="2082238445998314030">Niðurstaða <ph name="RESULT_NUMBER" /> af <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Vista…</translation>
<translation id="2088086323192747268">Hnappurinn „Stjórna samstillingu“, ýttu á „Enter“ til að opna stillingar Chrome og stjórna því hvaða upplýsingar eru samstilltar</translation>
<translation id="2091887806945687916">Hljóð</translation>
<translation id="2094505752054353250">Misræmi í léni</translation>
@@ -380,6 +389,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="2317259163369394535"><ph name="DOMAIN" /> þarf notandanafn og aðgangsorð.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, rennur út <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Kerfisstjóri stýrir þessari stillingu</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> vill parast</translation>
<translation id="2344028582131185878">Sjálfvirkt niðurhal</translation>
<translation id="2346319942568447007">Mynd sem þú afritaðir</translation>
<translation id="2354001756790975382">Önnur bókamerki</translation>
@@ -387,8 +397,10 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="2355395290879513365">Tölvuþrjótar gætu séð myndirnar sem þú skoðar á þessu vefsvæði og gabbað þig með því að breyta þeim.</translation>
<translation id="2356070529366658676">Spyrja</translation>
<translation id="2357481397660644965"><ph name="DEVICE_MANAGER" /> hefur umsjón með tækinu þínu og <ph name="ACCOUNT_MANAGER" /> hefur umsjón með reikningnum þínum.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Eftir minna en einn dag}=1{Eftir einn dag}one{eftir {NUM_DAYS} dag}other{eftir {NUM_DAYS} daga}}</translation>
<translation id="2359629602545592467">Margir</translation>
<translation id="2359808026110333948">Halda áfram</translation>
+<translation id="2359961752320758691">Sýndarkortsnúmerið þitt er útfyllt.</translation>
<translation id="2367567093518048410">Stig</translation>
<translation id="2372464001869762664">Greiðslukortaupplýsingum af Google reikningnum þínum verður deilt með þessu vefsvæði eftir að þú staðfestir. Finndu CVC-númerið í Plex reikningsupplýsingunum þínum.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -399,6 +411,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="239429038616798445">Þessi sendingarmáti er ekki í boði. Prófaðu annan sendingarmáta.</translation>
<translation id="2396249848217231973">&amp;Afturkalla eyðingu</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Gamalt</translation>
<translation id="2413528052993050574">Þessi þjónn gat ekki sannað að hann væri <ph name="DOMAIN" />; öryggisvottorð hans gæti hafa verið afturkallað. Þetta kann að orsakast af vanstillingu eða tölvuþrjóti sem komist hefur inn í tenginguna.</translation>
<translation id="2414886740292270097">Dökkt</translation>
<translation id="2438874542388153331">Fjögur göt hægra megin</translation>
@@ -426,10 +439,10 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="2521385132275182522">Hefti neðst til hægri</translation>
<translation id="2523886232349826891">Aðeins vistað í þessu tæki</translation>
<translation id="2524461107774643265">Bæta við fleiri upplýsingum</translation>
-<translation id="2526590354069164005">Skjáborð</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{og 1 í viðbót}one{og # í viðbót}other{og # í viðbót}}</translation>
<translation id="2536110899380797252">Bæta við heimilisfangi</translation>
<translation id="2539524384386349900">Greina</translation>
+<translation id="2541219929084442027">Síður sem þú skoðar á huliðsflipum verða vistaðar í vafraferlinum, fótsporageymslunni eða leitarferlinum eftir að þú lokar öllum huliðsflipum. Skrár sem þú sækir eða bókamerki sem þú býrð til verða áfram til staðar.</translation>
<translation id="2544644783021658368">Stakt skjal</translation>
<translation id="254947805923345898">Gildi reglunnar er ógilt.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> sendi ógilt svar.</translation>
@@ -449,6 +462,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="2629325967560697240">Til að fá mesta öryggi sem Chrome býður upp á skaltu <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />kveikja á aukinni vörn<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">IP-tala þjóns <ph name="HOST_NAME" /> fannst ekki.</translation>
<translation id="2639739919103226564">Staða:</translation>
+<translation id="264810637653812429">Engin samhæf tæki fundust.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, ýttu á Tab og svo Enter til að hreinsa vafraferil, fótspor, skyndiminni og fleira í stillingum Chrome</translation>
<translation id="2650446666397867134">Aðgangi að skránni var hafnað</translation>
@@ -495,6 +509,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="2799223571221894425">Endurræsa</translation>
<translation id="2803306138276472711">Örugg vefnotkun Google <ph name="BEGIN_LINK" />greindi nýlega spilliforrit<ph name="END_LINK" /> á <ph name="SITE" />. Vefsvæði sem allajafna eru örugg smitast stundum af spilliforritum.</translation>
<translation id="2807052079800581569">Y-staðsetning myndar</translation>
+<translation id="2820957248982571256">Leitar...</translation>
<translation id="2824775600643448204">Veffanga- og leitarstika</translation>
<translation id="2826760142808435982">Tengingin er dulkóðuð og sannvottuð með <ph name="CIPHER" /> og <ph name="KX" /> er notað sem aðferð til að skiptast á lyklum.</translation>
<translation id="2835170189407361413">Hreinsa eyðublað</translation>
@@ -502,6 +517,8 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="2850739647070081192">Invite (umslag)</translation>
<translation id="2856444702002559011">Tölvuþrjótar gætu verið að reyna að stela upplýsingum þínum frá <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (til dæmis aðgangsorðum, skilaboðum eða kreditkortum). <ph name="BEGIN_LEARN_MORE_LINK" />Frekari upplýsingar<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Þetta vefsvæði sýnir ágengar eða villandi auglýsingar.</translation>
+<translation id="287596039013813457">Vinalegt</translation>
+<translation id="2876489322757410363">Slekkur á huliðsstillingu til að greiða með öðru forriti. Halda áfram?</translation>
<translation id="2878197950673342043">Veggspjaldabrot</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Gluggastaðsetning</translation>
@@ -551,7 +568,6 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="3060227939791841287">C9 (umslag)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, ýttu á dálkalykilinn og svo Enter til að keyra öryggisathugun í stillingum Chrome</translation>
<translation id="3061707000357573562">Plástraþjónusta</translation>
-<translation id="3064966200440839136">Slökkva þarf á huliðsstillingu til að greiða með öðru forriti. Halda áfram?</translation>
<translation id="306573536155379004">Leikur hafinn.</translation>
<translation id="3080254622891793721">Grafík</translation>
<translation id="3086579638707268289">Verið er að fylgjast með aðgerðum þínum á vefnum</translation>
@@ -574,7 +590,6 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="315504272643575312"><ph name="MANAGER" /> hefur umsjón með reikningnum þínum.</translation>
<translation id="3157931365184549694">Endurheimta</translation>
<translation id="3162559335345991374">Wi-Fi netið sem þú notar kann að fara fram á að þú farir á innskráningarsíðu þess.</translation>
-<translation id="3167968892399408617">Síður sem þú skoðar í huliðsflipum verða ekki áfram í vafraferlinum, fótsporageymslunni eða leitarferlinum eftir að þú hefur lokað öllum huliðsflipum. Skrár sem þú sækir eða bókamerki sem þú býrð til verða áfram til staðar.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Eyja</translation>
<translation id="3176929007561373547">Athugaðu stillingarnar þínar fyrir staðgengilsþjón eða hafðu samband við netstjórann þinn til að
@@ -600,10 +615,12 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="3229041911291329567">Upplýsingar um útgáfu tækisins þíns og vafrans</translation>
<translation id="323107829343500871">Sláðu inn CVC-númerið fyrir <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Greina alltaf mikilvægt efni á þessu vefsvæði</translation>
+<translation id="3249845759089040423">Mergjað</translation>
<translation id="3252266817569339921">Franskt</translation>
<translation id="3266793032086590337">Gildi (skörun)</translation>
<translation id="3268451620468152448">Opna flipa</translation>
<translation id="3270847123878663523">Aft&amp;urkalla nýja röðun</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> vill tengjast</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Fyrirtækið þitt, <ph name="ENROLLMENT_DOMAIN" />, hefur sent einhverjar upplýsingar á eftirfarandi vefsvæði, á borð við stillingar og reglur.</translation>
<translation id="3282497668470633863">Bæta við nafni á korti</translation>
@@ -656,6 +673,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="3428151540071562330">Eitt eða fleiri af URI sniðmátum netþjóns DnsOverHttpsTemplates eru ógild og verða ekki notuð.</translation>
<translation id="3431636764301398940">Vista kortið á þessu tæki</translation>
<translation id="3432601291244612633">Loka síðu</translation>
+<translation id="3435738964857648380">Öryggi</translation>
<translation id="3435896845095436175">Kveikja</translation>
<translation id="3438829137925142401">Nota aðgangsorð sem eru vistuð á Google reikningnum þínum</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -698,7 +716,10 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="3584299510153766161">Tvö göt neðst</translation>
<translation id="3586931643579894722">Fela upplýsingar</translation>
<translation id="3587738293690942763">Miðja</translation>
+<translation id="3590643883886679995">Innskráningargögn verða geymd í þessu tæki eftir að þú lokar huliðsstillingu.</translation>
+<translation id="359126217934908072">Mánuður/ár:</translation>
<translation id="3592413004129370115">Italian (umslag)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Þú getur endurstillt hópinn þinn hvenær sem er. Það tekur um einn dag að ganga í nýjan hóp.}=1{Þú getur endurstillt hópinn þinn hvenær sem er. Það tekur um einn dag að ganga í nýjan hóp.}one{Þú getur endurstillt hópinn þinn hvenær sem er. Það tekur {NUM_DAYS} dag að ganga í nýjan hóp.}other{Þú getur endurstillt hópinn þinn hvenær sem er. Það tekur {NUM_DAYS} daga að ganga í nýjan hóp.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Kerfisstjóri hefur lokað á þetta forrit</translation>
<translation id="3608932978122581043">Inntaksstefna</translation>
@@ -707,13 +728,13 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="3615877443314183785">Færðu inn gilda lokadagsetningu</translation>
<translation id="36224234498066874">Hreinsa vafragögn...</translation>
<translation id="362276910939193118">Sýna feril í heild</translation>
-<translation id="3625635938337243871">Innskráningargögn verða geymd í þessu tæki eftir að þú lokar huliðsstillingu.</translation>
<translation id="3630155396527302611">Ef síðan er þegar skráð sem forrit sem hefur aðgang að netinu skaltu prófa
að taka hana af listanum og bæta henni svo við aftur.</translation>
<translation id="3630699740441428070">Kerfisstjórar þessa tækis grunnstilltu nettenginguna þína sem kann að gera þeim kleift að skoða netumferðina þína, þar á meðal hvaða vefsvæði þú heimsækir.</translation>
<translation id="3631244953324577188">Lífkenni</translation>
<translation id="3633738897356909127">Hnappurinn Uppfæra Chrome, ýttu á Enter til að uppfæra Chrome úr stillingum Chrome</translation>
<translation id="3634530185120165534">Bakki 5</translation>
+<translation id="3637662659967048211">Vista á Google reikningi</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Forrit:</translation>
<translation id="3650584904733503804">Sannvottun heppnaðist</translation>
@@ -754,6 +775,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="3781428340399460090">Dökkbleikur</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth-tæki</translation>
+<translation id="3787675388804467730">Númer sýndarkorts</translation>
<translation id="3787705759683870569">Rennur út <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Stærð 16</translation>
<translation id="3789841737615482174">Setja upp</translation>
@@ -773,6 +795,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="3841184659773414994">Hjálparforrit skráa</translation>
<translation id="385051799172605136">Til baka</translation>
<translation id="3858027520442213535">Uppfæra dagsetningu og tíma</translation>
+<translation id="3881478300875776315">Sýna færri línur</translation>
<translation id="3884278016824448484">Ósamræmi í auðkenni tækis</translation>
<translation id="3885155851504623709">Sókn</translation>
<translation id="388632593194507180">Eftirlit greindist</translation>
@@ -798,6 +821,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="397105322502079400">Reiknar...</translation>
<translation id="3973234410852337861">Lokað er fyrir <ph name="HOST_NAME" /></translation>
<translation id="3973357910713125165">Hnappurinn „Keyra öryggisathugun í Chrome“, ýttu á „Enter“ til að keyra öryggisathugun í stillingum Chrome</translation>
+<translation id="3986705137476756801">Slökkva á skjátextum í rauntíma í bili</translation>
<translation id="3987405730340719549">Chrome telur að þetta vefsvæði gæti verið falsað eða sviksamlegt.
Ef þú telur að þetta sé ekki rétt skaltu fara á https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -894,13 +918,14 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="4275830172053184480">Endurræstu tækið</translation>
<translation id="4277028893293644418">Endurstilla aðgangsorð</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Þetta kort var vistað á Google reikningnum þínum}one{Þessi kort voru vistuð á Google reikningnum þínum}other{Þessi kort voru vistuð á Google reikningnum þínum}}</translation>
+<translation id="4287885627794386150">Getur fengið prufuútgáfu en hún er ekki virk</translation>
<translation id="4297502707443874121">Smámynd síðu <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Stækka</translation>
<translation id="4300675098767811073">Mörg göt hægra megin</translation>
<translation id="4302514097724775343">Ãttu á risaeðluna til að spila</translation>
<translation id="4302965934281694568">Chou3 (umslag)</translation>
<translation id="4305666528087210886">Ekki var hægt að opna skrána þína</translation>
-<translation id="4305817255990598646">Skipta</translation>
+<translation id="4306529830550717874">Vista heimilisfang?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Útiloka (sjálfgefið)</translation>
<translation id="4314815835985389558">Stjórna samstillingu</translation>
@@ -927,6 +952,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="4377125064752653719">Þú reyndir að ná í <ph name="DOMAIN" /> en vottorðið sem þjónninn gaf upp hefur verið afturkallað af útgefandanum. Þetta merkir að alls ekki skuli treysta öryggisskilríkjum þjónsins. Þú gætir verið að eiga samskipti við tölvuþrjót.</translation>
<translation id="4378154925671717803">Sími</translation>
<translation id="4390472908992056574">Brún</translation>
+<translation id="4406883609789734330">Skjátextar í rauntíma</translation>
<translation id="4406896451731180161">leitarniðurstöður</translation>
<translation id="4408413947728134509">Fótspor <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Þú gafst upp aðgangsorðið þitt á svindlsíðu. Chrome mælir með því að þú farir á <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> og önnur vefsvæði þar sem þú notar þetta aðgangsorð og breytir því núna.</translation>
@@ -939,7 +965,6 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="4435702339979719576">póstkort)</translation>
<translation id="443673843213245140">Slökkt er á notkun proxy-þjóns en sérstök proxy-stilling er tilgreind.</translation>
<translation id="4464826014807964867">Vefsvæði með upplýsingar frá þínu fyrirtæki</translation>
-<translation id="4466881336512663640">Breytingar á eyðublaði glatast. Viltu örugglega halda áfram?</translation>
<translation id="4476953670630786061">Þetta eyðublað er ekki öruggt. Slökkt var á sjálfvirkri útfyllingu.</translation>
<translation id="4477350412780666475">Næsta lag</translation>
<translation id="4482953324121162758">Þetta vefsvæði verður ekki þýtt.</translation>
@@ -973,6 +998,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="4594403342090139922">Aft&amp;urkalla eyðingu</translation>
<translation id="4597348597567598915">Stærð 8</translation>
<translation id="4600854749408232102">C6/C5 (umslag)</translation>
+<translation id="4606870351894164739">Ãhrifamikið</translation>
<translation id="4628948037717959914">Mynd</translation>
<translation id="4631649115723685955">Fjárvildarkerfi tengt</translation>
<translation id="4636930964841734540">Upplýsingar</translation>
@@ -992,6 +1018,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="4691835149146451662">Architecture-A (umslag)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Hlið</translation>
+<translation id="4702656508969495934">Skjátextar í rauntíma sýnilegir, notaðu gluggaval til að stilla fókus</translation>
<translation id="4708268264240856090">Tengingin þín var rofin</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Keyrir Windows-netgreiningu<ph name="END_LINK" /></translation>
@@ -1005,6 +1032,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="4738601419177586157"><ph name="TEXT" /> leitartillaga</translation>
<translation id="4742407542027196863">Stjórna aðgangsorðum…</translation>
<translation id="4744603770635761495">Keyranleg slóð</translation>
+<translation id="4749011317274908093">Þú ferð nú huldu höfði</translation>
<translation id="4750917950439032686">Upplýsingarnar þínar (t.d. aðgangsorð eða kreditkortanúmer) eru lokaðar þegar þær eru sendar á þetta vefsvæði.</translation>
<translation id="4756388243121344051">Ferill</translation>
<translation id="4758311279753947758">Bæta við samskiptaupplýsingum</translation>
@@ -1034,6 +1062,8 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="4813512666221746211">Netvilla</translation>
<translation id="4816492930507672669">Laga að síðu</translation>
<translation id="4819347708020428563">Breyta textaskýringum í sjálfgefnu sniði?</translation>
+<translation id="4825507807291741242">Kraftmikið</translation>
+<translation id="4838327282952368871">Draumkennt</translation>
<translation id="484462545196658690">Sjálfvirkt</translation>
<translation id="4850886885716139402">Yfirlit</translation>
<translation id="485316830061041779">Þýskt</translation>
@@ -1170,6 +1200,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="5314967030527622926">Bæklingagerð</translation>
<translation id="5316812925700871227">Snúa rangsælis</translation>
<translation id="5317780077021120954">Vista</translation>
+<translation id="5321288445143113935">Stækkað</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> af <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Velja samskiptaupplýsingar</translation>
<translation id="5327248766486351172">Heiti</translation>
@@ -1177,11 +1208,13 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="5332219387342487447">Sendingaraðferð</translation>
<translation id="5333022057423422993">Chrome fann aðgangsorðið sem þú varst að nota í öryggisbroti. Til að tryggja öryggi reikninganna þinna mælum við með að þú athugir vistuðu aðgangsorðin þín.</translation>
<translation id="5334013548165032829">Ãtarlegir kerfisannálar</translation>
+<translation id="5334145288572353250">Vista heimilisfang?</translation>
<translation id="5340250774223869109">Lokað er á forrit</translation>
<translation id="534295439873310000">NFC-tæki</translation>
<translation id="5344579389779391559">Þessi síða gæti reynt að rukka þig um greiðslu</translation>
<translation id="5355557959165512791">Þú getur ekki heimsótt <ph name="SITE" /> í augnablikinu vegna þess að þetta vottorð hefur verið afturkallað. Netvillur og árásir eru yfirleitt tímabundnar og því mun þessi síða líklega virka síðar.</translation>
<translation id="536296301121032821">Mistókst að vista reglustillingar</translation>
+<translation id="5363309033720083897">Raðtengi heimilað af stjórnanda</translation>
<translation id="5371425731340848620">Uppfæra kort</translation>
<translation id="5377026284221673050">„Klukkan er á eftir“, „Klukkan þín er á undan“ eða „&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;“</translation>
<translation id="5386426401304769735">Vottorðskeðja þessa vefsvæðis inniheldur vottorð sem var undirritað með SHA-1.</translation>
@@ -1190,6 +1223,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="5398772614898833570">Lokað á auglýsingar</translation>
<translation id="5400836586163650660">Grár</translation>
<translation id="540969355065856584">Þessi þjónn gat ekki sannað að hann væri <ph name="DOMAIN" />; öryggisvottorð hans er ekki gilt eins og er. Þetta kann að orsakast af vanstillingu eða þá að tölvuþrjótur er að reyna að komast inn í tenginguna þína.</translation>
+<translation id="541143247543991491">Ský (fyrir allt kerfið)</translation>
<translation id="541416427766103491">Staflari 4</translation>
<translation id="5421136146218899937">Hreinsa vafragögn...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> vill senda þér tilkynningar</translation>
@@ -1203,6 +1237,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="5455374756549232013">Rangur tímastimpill reglu</translation>
<translation id="5457113250005438886">Ógilt</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> í viðbót}one{<ph name="CONTACT_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> í viðbót}other{<ph name="CONTACT_PREVIEW" /> og <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> í viðbót}}</translation>
+<translation id="5463625433003343978">Leitar að tækjum...</translation>
<translation id="5469868506864199649">Ãtalskt</translation>
<translation id="5470861586879999274">&amp;Endurtaka breytingu</translation>
<translation id="5478437291406423475">B6/C4 (umslag)</translation>
@@ -1252,7 +1287,6 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="5624120631404540903">Stjórna aðgangsorðum</translation>
<translation id="5629630648637658800">Mistókst að hlaða reglustillingar</translation>
<translation id="5631439013527180824">Ógildur kóði tækjastjórnunar</translation>
-<translation id="5632627355679805402">Gögnin þín voru dulkóðuð með <ph name="BEGIN_LINK" />aðgangsorði Google<ph name="END_LINK" /> frá <ph name="TIME" />. Sláðu það inn til að hefja samstillingu.</translation>
<translation id="5633066919399395251">Tölvuþrjótar sem halda nú til á <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kunna að reyna að setja hættuleg forrit upp í tölvunni þinni, sem ætlað er að stela eða eyða upplýsingunum þínum (t.d. myndum, aðgangsorðum, skilaboðum og kreditkortum). <ph name="BEGIN_LEARN_MORE_LINK" />Frekari upplýsingar<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Lokað á villandi efni.</translation>
<translation id="5644090287519800334">X-færsla myndar á hlið 1</translation>
@@ -1291,12 +1325,12 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="5785756445106461925">Aukinheldur inniheldur þessi síða önnir tilföng sem ekki er hægt að treysta. Þessi tilföng kunna að vera skoðuð af öðrum á meðan þau eru í umferð, og tölvuþrjótur gæti breytt þeim til þess að reyna að breyta útliti síðunnar.</translation>
<translation id="5786044859038896871">Viltu fylla út upplýsingar um kortið?</translation>
<translation id="578633867165174378">Chrome fann aðgangsorðið sem þú varst að nota í öryggisbroti. Við mælum með að þessu aðgangsorði verði breytt núna.</translation>
-<translation id="5798290721819630480">Viltu hætta við breytingar?</translation>
<translation id="5803412860119678065">Viltu fylla út <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Heimildir</translation>
<translation id="5804427196348435412">Nota NFC-tæki</translation>
<translation id="5810442152076338065">Tengingin við <ph name="DOMAIN" /> er dulkóðuð með úreltu dulkóðunarsafni.</translation>
<translation id="5813119285467412249">Endu&amp;rtaka nýtt bókamerki</translation>
+<translation id="5817918615728894473">Para</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Skuldfært verður á þetta kort við greiðslu en kortanúmerinu verður ekki deilt með vefsvæðinu. Til að auka enn á öryggið myndast tímabundið CVC-númer.}one{Skuldfært verður á kortið sem þú velur við greiðslu en kortanúmerinu verður ekki deilt með vefsvæðinu. Til að auka enn á öryggið myndast tímabundið CVC-númer.}other{Skuldfært verður á kortið sem þú velur við greiðslu en kortanúmerinu verður ekki deilt með vefsvæðinu. Til að auka enn á öryggið myndast tímabundið CVC-númer.}}</translation>
<translation id="5826507051599432481">Almennt heiti (CN)</translation>
<translation id="5838278095973806738">Þú ættir ekki að færa inn neinar viðkvæmar upplýsingar á þessu vefsvæði (t.d. aðgangsorð eða kreditkortanúmer) því að tölvuþrjótar gætu stolið þeim.</translation>
@@ -1304,6 +1338,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="5855253129151731373">Hýsilheiti þessa vefsvæðis líkist <ph name="LOOKALIKE_DOMAIN" />. Stundum herma tölvuþrjótar eftir vefsvæðum með því að gera litlar og illgreinanlegar breytingar á lénsheitinu.
Ef þú telur að þetta sé ekki rétt skaltu fara á https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Slökkt</translation>
<translation id="5862579898803147654">Staflari 8</translation>
<translation id="5863847714970149516">Síðan gæti reynt að rukka þig um greiðslu</translation>
<translation id="5866257070973731571">Bæta við símanúmeri</translation>
@@ -1320,6 +1355,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="5913377024445952699">Hlé gert á skjámyndatöku</translation>
<translation id="59174027418879706">Virkt</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{Ein í notkun}one{# í notkun}other{# í notkun}}</translation>
<translation id="5921185718311485855">Kveikt</translation>
<translation id="5921639886840618607">Viltu vista kortið á Google reikningnum?</translation>
<translation id="5922853866070715753">Næstum búið</translation>
@@ -1339,6 +1375,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="5989320800837274978">Hvorki fastir proxy-þjónar né vefslóð á .pac-skriftu er skilgreind.</translation>
<translation id="5992691462791905444">Z-brot</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> niðurstöður fyrir „<ph name="SEARCH_TEXT" />“</translation>
+<translation id="6006484371116297560">Hefðbundið</translation>
<translation id="6008122969617370890">Röðun N til 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Athugaðu aðgangsorðin þín</translation>
@@ -1360,6 +1397,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="6045164183059402045">Ãsetningarsniðmát</translation>
<translation id="6047233362582046994">Ef þú skilur öryggisáhættuna sem það hefur í för með sér geturðu <ph name="BEGIN_LINK" />heimsótt þetta vefsvæði<ph name="END_LINK" /> áður en skaðlegu forritin hafa verið fjarlægð.</translation>
<translation id="6047927260846328439">Þetta efni kann að reyna að fá þig til að setja upp hugbúnað eða gefa upp persónuupplýsingar. <ph name="BEGIN_LINK" />Sýna samt<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Haltu inni |<ph name="ACCELERATOR" />| til að hætta birtingu á öllum skjánum</translation>
<translation id="6049488691372270142">Síðuafhending</translation>
<translation id="6051221802930200923">Þú getur ekki heimsótt <ph name="SITE" /> að svo stöddu þar sem vefsvæðið notast við vottorðafestingu. Netvillur og árásir eru yfirleitt tímabundnar og því mun þessi síða líklega virka síðar.</translation>
<translation id="6051898664905071243">Síðufjöldi:</translation>
@@ -1376,6 +1414,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="610911394827799129">Google reikningurinn þinn kann að vera með annars konar vefskoðunarferil á <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">Sjá texta og myndir sem þú afritar á klippiborðið</translation>
<translation id="6120179357481664955">Muna eftir UPI-auðkenni?</translation>
+<translation id="6123290840358279103">Skoða sýndarkort</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Kannaðu allar snúrur og endurræstu beina, mótöld og önnur
nettæki sem þú kannt að vera að nota.</translation>
@@ -1412,6 +1451,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="6289939620939689042">Síðulitur</translation>
<translation id="6290238015253830360">Tillögur að greinum birtast hér</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google hjálpari í Chrome stoppar</translation>
<translation id="6305205051461490394">Ekki næst í <ph name="URL" />.</translation>
<translation id="6312113039770857350">Vefsíðan er ekki tiltæk</translation>
@@ -1437,6 +1477,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="6390200185239044127">Z-brot í miðju</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Regla stjórnanda lokar á að hægt sé að líma frá <ph name="ORIGIN_NAME" /> á þessa staðsetningu</translation>
+<translation id="6398765197997659313">Hætta að nota allan skjáinn</translation>
<translation id="6401136357288658127">Þessi regla er úrelt. Þú ættir að nota regluna <ph name="NEW_POLICY" /> í staðinn.</translation>
<translation id="6404511346730675251">Breyta bókamerki</translation>
<translation id="6406765186087300643">C0 (umslag)</translation>
@@ -1449,7 +1490,6 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="6428450836711225518">Staðfestu símanúmerið þitt</translation>
<translation id="6433490469411711332">Breyta samskiptaupplýsingum</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> neitaði að koma á tengingu.</translation>
-<translation id="6434309073475700221">Fleygja</translation>
<translation id="6440503408713884761">Hunsað</translation>
<translation id="6443406338865242315">Hvaða viðbætur þú hefur sett upp</translation>
<translation id="6446163441502663861">Kahu (umslag)</translation>
@@ -1492,6 +1532,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="6624427990725312378">Upplýsingar um tengilið</translation>
<translation id="6626291197371920147">Bæta við gildu kortanúmeri</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> leit</translation>
+<translation id="6630043285902923878">Leitar að USB-tækjum...</translation>
<translation id="6630809736994426279">Tölvuþrjótar sem halda nú til á <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kunna að reyna að setja hættuleg forrit upp í Mac-tölvunni þinni til þess að stela eða eyða upplýsingunum þínum (t.d. myndum, aðgangsorðum, skilaboðum og kreditkortum). <ph name="BEGIN_LEARN_MORE_LINK" />Frekari upplýsingar<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Hreinsa</translation>
@@ -1507,6 +1548,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="6671697161687535275">Fjarlægja eyðublaðstillögu úr Chromium?</translation>
<translation id="6685834062052613830">Skráðu þig út og ljúktu við uppsetninguna</translation>
<translation id="6687335167692595844">Beðið um leturstærð</translation>
+<translation id="6688743156324860098">Uppfæra…</translation>
<translation id="6689249931105087298">Háð með þjöppun svartra punkta</translation>
<translation id="6689271823431384964">Chrome býður þér að vista kortin þín á Google reikningnum vegna þess að þú ert innskráð(ur). Þú getur breytt þessu í stillingunum. Nafn korthafa er sótt af reikningnum þínum.</translation>
<translation id="6698381487523150993">Búið til:</translation>
@@ -1522,6 +1564,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="6744009308914054259">à meðan þú bíður eftir tengingu geturðu skoðað „Niðurhal“ til að lesa greinar án nettengingar.</translation>
<translation id="6753269504797312559">Gildi reglu</translation>
<translation id="6757797048963528358">Tækið þitt fór að sofa.</translation>
+<translation id="6767985426384634228">Uppfæra heimilisfang?</translation>
<translation id="6768213884286397650">Hagaki (póstkort)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Fjólublár</translation>
@@ -1544,6 +1587,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome einfaldaði þessa síðu svo það yrði auðveldara að lesa hana. Chrome sótti upprunalegu síðuna um ótrausta tengingu.</translation>
<translation id="6891596781022320156">Stig stefnunnar er óstutt.</translation>
+<translation id="6895143722905299846">Sýndarnúmer:</translation>
<translation id="6895330447102777224">Kortið er staðfest</translation>
<translation id="6897140037006041989">Vafraupplýsingar</translation>
<translation id="6898699227549475383">Notendaskipan (O)</translation>
@@ -1579,10 +1623,10 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="7004583254764674281">Notaðu Windows Hello til að staðfesta kort hraðar</translation>
<translation id="7006930604109697472">Senda samt</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Stillingar breytinga á stærð</translation>
<translation id="7014741021609395734">Aðdráttarstig</translation>
<translation id="7016992613359344582">Greiðslur gætu verið stakar eða endurteknar og hugsanlega er ekki greinilegt að borga þurfi.</translation>
<translation id="7029809446516969842">Aðgangsorð</translation>
+<translation id="7030436163253143341">Vottorðið er ekki gilt</translation>
<translation id="7031646650991750659">Hvaða Google Play forrit þú hefur sett upp</translation>
<translation id="7050187094878475250">Þú reyndir að ná sambandi við <ph name="DOMAIN" /> en þjónninn framvísaði vottorði sem er með of langan gildistíma til að hægt sé að treysta því.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Ekki er hægt að vista þetta kort núna}one{Ekki er hægt að vista þessi kort núna}other{Ekki er hægt að vista þessi kort núna}}</translation>
@@ -1652,12 +1696,14 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="7300012071106347854">Kóbaltblár</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />“</translation>
<translation id="7304030187361489308">Mikil</translation>
+<translation id="7305756307268530424">Ræsa hægari útgáfu</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Tengingarhjálp</translation>
<translation id="7323804146520582233">Fela hlutann „<ph name="SECTION" />“</translation>
<translation id="733354035281974745">Hnekking staðbundins reiknings í tæki</translation>
<translation id="7333654844024768166">Þú gafst upp aðgangsorðið þitt á svindlsíðu. Chromium mælir með því að þú farir á <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> og önnur vefsvæði þar sem þú notar þetta aðgangsorð og breytir því núna.</translation>
<translation id="7334320624316649418">Endu&amp;rtaka nýja röðun</translation>
+<translation id="7337248890521463931">Sýna fleiri línur</translation>
<translation id="7337706099755338005">Ekki í boði fyrir stýrikerfið þitt.</translation>
<translation id="733923710415886693">Vottorð vefþjóns var ekki birt í gegnum gagnsæi vottorðs.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1665,6 +1711,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Skipanalína</translation>
<translation id="7359588939039777303">Lokað á auglýsingar.</translation>
+<translation id="7363096869660964304">Hafðu í huga að þú verður ekki ósýnileg(ur). Huliðsstillingin felur ekki vafraferilinn þinn gagnvart vinnuveitanda þínum eða netþjónustu, eða vefsvæðin sem þú skoðar.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, ýttu á dálkalykilinn (Tab) og svo „Enter“ til að bæta við og stjórna vefslóðum í stillingum Chrome</translation>
<translation id="7365849542400970216">Er þér kunnugt um notkun tækisins?</translation>
<translation id="7372973238305370288">leitarniðurstaða</translation>
@@ -1675,7 +1722,9 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="7378594059915113390">Spilunarstýringar</translation>
<translation id="7378627244592794276">Neibb</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">à ekki við</translation>
<translation id="7390545607259442187">Staðfesta kort</translation>
+<translation id="7392089738299859607">Uppfæra heimilisfang</translation>
<translation id="7399802613464275309">Öryggisathugun</translation>
<translation id="7400418766976504921">Vefslóð</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> er stjórnað</translation>
@@ -1690,6 +1739,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
&lt;li&gt;Farðu í &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;hjálparmiðstöð Chrome&lt;/a&gt; til að fá upplýsingar um hvernig hugbúnaður er fjarlægður varanlega af tölvunni
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Fagurt</translation>
<translation id="7416351320495623771">Stjórna aðgangsorðum…</translation>
<translation id="7419106976560586862">Slóð prófíls</translation>
<translation id="7437289804838430631">Bæta við samskiptaupplýsingum</translation>
@@ -1705,7 +1755,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="7481312909269577407">Ãfram</translation>
<translation id="7485870689360869515">Engin gögn fundust.</translation>
<translation id="7495528107193238112">Þetta efni er á bannlista. Hafðu samband við eiganda vefsvæðisins til að lagfæra vandamálið.</translation>
-<translation id="7498234416455752244">Halda áfram að breyta</translation>
+<translation id="7498193950643227031">Breyting á stærð getur leitt til óvæntrar virkni. Nú geturðu takmarkað getuna til að breyta stærð á forritum í <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Þú gafst upp aðgangsorðið þitt á svindlsíðu. Chromium mælir með því að þú athugir vistuðu aðgangsorðin þín fyrir <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> og önnur vefsvæði þar sem þú notar þetta aðgangsorð núna.</translation>
<translation id="7508255263130623398">Tækisauðkenni stefnu sem skilað var er autt eða stemmir ekki við núverandi tækisauðkenni</translation>
<translation id="7508870219247277067">Lárperugrænn</translation>
@@ -1725,6 +1775,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="7548892272833184391">Laga tengingarvillur</translation>
<translation id="7549584377607005141">Til að þessi vefsíða virki rétt þarf hún gögn sem þú slóst inn áður. Þú getur sent gögnin aftur en ef þú gerir það endurtekur þú allar aðgerðir sem þessi síða hefur áður framkvæmt.</translation>
<translation id="7550637293666041147">Notandanafn tækisins og notandanafn í Chrome</translation>
+<translation id="755279583747225797">Prufuútgáfa er virk</translation>
<translation id="7552846755917812628">Prófaðu eftirfarandi:</translation>
<translation id="7554475479213504905">Endurhlaða og sýna samt</translation>
<translation id="7554791636758816595">Nýr flipi</translation>
@@ -1743,7 +1794,6 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="7610193165460212391">Gildið er utan sviðs <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Rennur út: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ýttu á Tab og svo Enter til að skoða og stjórna aðgangsorðunum þínum í stillingum Chrome</translation>
-<translation id="7615602087246926389">Þú ert nú þegar með gögn sem eru dulkóðuð með annarri útgáfu af aðgangsorði Google reikningsins þíns. Sláðu það inn hér fyrir neðan.</translation>
<translation id="7616645509853975347">Kerfisstjórinn þinn hefur kveikt á Chrome Enterprise Connectors í vafranum þínum. Þessi tengi hafa aðgang að sumum af gögnunum þínum.</translation>
<translation id="7619838219691048931">Síðasta blað</translation>
<translation id="762844065391966283">Eitt í einu</translation>
@@ -1808,13 +1858,12 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="782886543891417279">Wi-Fi netið sem þú notar (<ph name="WIFI_NAME" />) kann að fara fram á að þú farir á innskráningarsíðu þess.</translation>
<translation id="7836231406687464395">Postfix (umslag)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ekkert}=1{1 forrit (<ph name="EXAMPLE_APP_1" />)}=2{2 forrit (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# forrit (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# forrit (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Hafðu í huga að þú verður samt ekki ósýnileg(ur). Huliðsstillingin felur ekki vafraferilinn þinn gagnvart vinnuveitanda þínum eða netveitu, eða vefsíðurnar sem þú skoðar.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Opna skrár með tengsl skráargerða.</translation>
<translation id="7862185352068345852">Viltu fara af vefsvæðinu?</translation>
<translation id="7865448901209910068">Mesti hraði</translation>
<translation id="7874263914261512992">Þú gafst upp aðgangsorðið þitt á svindlsíðu. Chrome mælir með því að þú athugir vistuðu aðgangsorðin þín fyrir <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> og önnur vefsvæði þar sem þú notar þetta aðgangsorð núna.</translation>
<translation id="7878562273885520351">Aðgangsorðinu þínu kann að hafa verið stolið</translation>
+<translation id="7880146494886811634">Vista heimilisfang</translation>
<translation id="7882421473871500483">Brúnn</translation>
<translation id="7887683347370398519">Athugaðu CVC-númerið og reyndu aftur</translation>
<translation id="7887885240995164102">Skoða mynd í mynd</translation>
@@ -1822,6 +1871,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="7894280532028510793">Ef stafsetningin er rétt skaltu <ph name="BEGIN_LINK" />prófa að keyra bilanaleit á netkerfi<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (umslag)</translation>
<translation id="7931318309563332511">Óþekkt</translation>
+<translation id="793209273132572360">Uppfæra heimilisfang?</translation>
<translation id="7932579305932748336">Kápa</translation>
<translation id="79338296614623784">Færðu inn gilt símanúmer</translation>
<translation id="7934052535022478634">Greiðslu lokið</translation>
@@ -1892,6 +1942,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="8175796834047840627">Chrome býður þér að vista kortin þín á Google reikningnum vegna þess að þú ert innskráð(ur). Þú getur breytt þessu í stillingunum.</translation>
<translation id="8176440868214972690">Stjórnandi tækisins hefur sent einhverjar upplýsingar á eftirfarandi vefsvæði, á borð við stillingar og reglur.</translation>
<translation id="8184538546369750125">Nota altækt sjálfgildi (leyfa)</translation>
+<translation id="8193086767630290324">Aðgerðir í gögnum sem eru merkt sem trúnaðarmál</translation>
<translation id="8194797478851900357">Aft&amp;urkalla flutning</translation>
<translation id="8201077131113104583">Ógild uppfærsluslóð fyrir viðbót með auðkennið „<ph name="EXTENSION_ID" />“.</translation>
<translation id="8202097416529803614">Yfirlit pöntunar</translation>
@@ -1914,6 +1965,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="8249296373107784235">Hætta</translation>
<translation id="8249320324621329438">Síðast sótt:</translation>
<translation id="8253091569723639551">Heimilisfangs greiðanda er krafist</translation>
+<translation id="8257387598443225809">Þetta forrit er hannað fyrir farsíma</translation>
<translation id="825929999321470778">Sýna öll vistuð aðgangsorð</translation>
<translation id="8261506727792406068">Eyða</translation>
<translation id="8262952874573525464">Saumur neðst</translation>
@@ -2037,7 +2089,6 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="8719528812645237045">Mörg göt efst</translation>
<translation id="8725066075913043281">Reyna aftur</translation>
<translation id="8726549941689275341">Síðustærð:</translation>
-<translation id="8728672262656704056">Þú ferð nú huldu höfði</translation>
<translation id="8730621377337864115">Lokið</translation>
<translation id="8731544501227493793">Hnappurinn Stjórna aðgangsorðum, ýttu á Enter til að skoða og stjórna aðgangsorðunum þínum í stillingum Chrome</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> er í umsjón <ph name="MANAGER" /></translation>
@@ -2114,6 +2165,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="9020542370529661692">Þessi síða var þýdd yfir á <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ógilt)</translation>
+<translation id="9030265603405983977">Svarthvítt</translation>
<translation id="9035022520814077154">Öryggisvilla</translation>
<translation id="9038649477754266430">Notaðu ágiskunarþjónustu til að flýta fyrir hleðslu á síðum</translation>
<translation id="9039213469156557790">Aukinheldur inniheldur þessi síða önnir tilföng sem ekki er hægt að treysta. Þessi tilföng kunna að vera skoðuð af öðrum á meðan þau eru í umferð, og tölvuþrjótur gæti breytt þeim til þess að reyna að breyta hegðun síðunnar.</translation>
@@ -2137,6 +2189,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="91108059142052966">Reglur stjórnenda útiloka skjádeilingu með <ph name="APPLICATION_TITLE" /> þegar trúnaðarefni er sýnilegt</translation>
<translation id="9114524666733003316">Staðfestir kort...</translation>
<translation id="9114581008513152754">Þessi vafri er ekki í umsjón fyrirtækis eða annarrar stofnunar. Hægt er að hafa umsjón með aðgerðum í þessu tæki utan Chrome. <ph name="BEGIN_LINK" />Frekari upplýsingar<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Ferskt</translation>
<translation id="9119042192571987207">Sent</translation>
<translation id="9128016270925453879">Reglum var hlaðið</translation>
<translation id="9128870381267983090">Tengjast neti</translation>
@@ -2155,6 +2208,7 @@ og röng skilríki til baka. Þetta getur gerst þegar tölvuþrjótur reynir aÃ
<translation id="9170848237812810038">Aft&amp;urkalla</translation>
<translation id="9171296965991013597">Loka forriti?</translation>
<translation id="9173282814238175921">Stakt skjal / nýtt blað</translation>
+<translation id="9173995187295789444">Leitar að Bluetooth-tækjum...</translation>
<translation id="917450738466192189">Vottorð þjónsins er ógilt.</translation>
<translation id="9174917557437862841">Hnappur til að skipta um flipa; ýttu á færslulykilinn til að skipta yfir í þennan flipa</translation>
<translation id="9179703756951298733">Stjórnaðu greiðslunum þínum og kreditkortaupplýsingum í stillingum Chrome</translation>
diff --git a/chromium/components/strings/components_strings_it.xtb b/chromium/components/strings/components_strings_it.xtb
index 6bc25fbc004..288d05d2e0b 100644
--- a/chromium/components/strings/components_strings_it.xtb
+++ b/chromium/components/strings/components_strings_it.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Se questa opzione viene selezionata, Chrome memorizza una copia della carta sul dispositivo per velocizzare la compilazione dei moduli.</translation>
<translation id="1110994991967754504">Seleziona l'autorizzazione per <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Annulla ridisposizione</translation>
+<translation id="1123753900084781868">La funzionalità Sottotitoli in tempo reale non è al momento disponibile</translation>
<translation id="1125573121925420732">Gli avvisi potrebbero essere frequenti durante l'aggiornamento della sicurezza dei siti web. La situazione dovrebbe migliorare a breve.</translation>
<translation id="112840717907525620">Cache dei criteri integra</translation>
<translation id="1130564665089811311">Pulsante Traduci pagina, premi Invio per tradurre questa pagina con Google Traduttore</translation>
@@ -74,6 +75,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="1240347957665416060">Il nome del tuo dispositivo</translation>
<translation id="124116460088058876">Altre lingue</translation>
<translation id="1243027604378859286">Autore:</translation>
+<translation id="1246424317317450637">Grassetto</translation>
<translation id="1250759482327835220">Per pagare più velocemente la prossima volta, salva la carta, il nome e l'indirizzo di fatturazione sul tuo Account Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sincronizzati)</translation>
<translation id="1256368399071562588">&lt;p&gt;Se il sito web che intendi visitare non si apre, prova innanzitutto a correggere l'errore con questi passaggi per la risoluzione dei problemi:&lt;/p&gt;
@@ -156,6 +158,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="1476595624592550506">Cambia la password</translation>
<translation id="1484290072879560759">Scegli l'indirizzo di spedizione</translation>
<translation id="1492194039220927094">Push dei criteri:</translation>
+<translation id="1495677929897281669">Torna alla scheda</translation>
<translation id="1501859676467574491">Mostra le carte dall'Account Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Vedrai questo errore se stai utilizzando un portale Wi-Fi che richiede l'accesso per poterti connettere a Internet.&lt;/p&gt;
&lt;p&gt;Per risolvere il problema, fai clic su &lt;strong&gt;Connetti&lt;/strong&gt; nella pagina che stai cercando di aprire.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="1532118530259321453">Questa pagina dice</translation>
<translation id="153384715582417236">Per il momento è tutto</translation>
<translation id="1536390784834419204">Traduci pagina</translation>
+<translation id="1539840569003678498">Data invio ultimo rapporto:</translation>
<translation id="154408704832528245">Scegli l'indirizzo di consegna</translation>
<translation id="1549470594296187301">JavaScript deve essere attivato per utilizzare questa funzione.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="1682696192498422849">Prima il lato corto</translation>
<translation id="168693727862418163">Impossibile convalidare il valore del criterio in base al relativo schema. Il valore verrà ignorato.</translation>
<translation id="168841957122794586">Il certificato del server contiene una chiave crittografica debole.</translation>
+<translation id="1696290444144917273">Visualizza i dettagli della carta virtuale</translation>
<translation id="1697532407822776718">Ecco fatto!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Questo server non è riuscito a verificare che si tratti di <ph name="DOMAIN" />; il relativo certificato di sicurezza potrebbe essere attivo da domani. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che intercetta la connessione.}other{Questo server non è riuscito a verificare che si tratti di <ph name="DOMAIN" />; il relativo certificato di sicurezza potrebbe essere attivo tra # giorni. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che intercetta la connessione.}}</translation>
<translation id="1710259589646384581">Sistema operativo</translation>
+<translation id="1711234383449478798">Criterio ignorato perché il criterio <ph name="POLICY_NAME" /> non è impostato su <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> vuole memorizzare in modo definitivo i dati sul computer locale</translation>
<translation id="1713628304598226412">Vassoio 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Mailbox 3</translation>
<translation id="1718029547804390981">Il documento è troppo voluminoso per potervi inserire annotazioni</translation>
<translation id="1721424275792716183">* Campo obbligatorio</translation>
+<translation id="1727613060316725209">Il certificato è valido</translation>
<translation id="1727741090716970331">Aggiungi un numero di carta valido</translation>
<translation id="1728677426644403582">È visualizzata l'origine di una pagina web</translation>
<translation id="173080396488393970">Questo tipo di carta non è supportato</translation>
@@ -246,7 +253,6 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
la tua richiesta per <ph name="SITE" />. I criteri di origine possono essere usati dagli
operatori del sito per configurare la sicurezza e altre proprietà del sito.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Aggiorna la tua passphrase di sincronizzazione.</translation>
<translation id="1787142507584202372">Le tue schede aperte vengono visualizzate qui</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, sono disponibili diverse azioni; premi Tab per scorrerle</translation>
@@ -279,6 +285,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="1919345977826869612">Annunci</translation>
<translation id="1919367280705858090">Assistenza per un messaggio di errore specifico</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Nessuno}=1{1 sito}other{# siti}}</translation>
+<translation id="1924727005275031552">Nuovi</translation>
<translation id="1945968466830820669">Potresti perdere l'accesso all'account della tua organizzazione oppure subire un furto d'identità. Chromium ti consiglia di cambiare subito la password.</translation>
<translation id="1947454675006758438">Pinzatura in alto a destra</translation>
<translation id="1958218078413065209">Il tuo punteggio migliore è <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="2042213636306070719">Vassoio 7</translation>
<translation id="204357726431741734">Accedi per usare le password salvate nel tuo Account Google</translation>
<translation id="2053111141626950936">Le pagine in <ph name="LANGUAGE" /> non verranno tradotte.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Quando questo controllo è attivato e lo stato è attivo, Chrome stabilisce a quale "coorte" (un gruppo numeroso di utenti) è più simile la tua attività di navigazione. Gli inserzionisti possono selezionare gli annunci per il gruppo e la tua attività di navigazione rimane privata sul tuo dispositivo. Il tuo gruppo viene aggiornato ogni giorno.}=1{Quando questo controllo è attivato e lo stato è attivo, Chrome stabilisce a quale "coorte" (un gruppo numeroso di utenti) è più simile la tua attività di navigazione. Gli inserzionisti possono selezionare gli annunci per il gruppo e la tua attività di navigazione rimane privata sul tuo dispositivo. Il tuo gruppo viene aggiornato ogni giorno.}other{Quando questo controllo è attivato e lo stato è attivo, Chrome stabilisce a quale "coorte" (un gruppo numeroso di utenti) è più simile la tua attività di navigazione. Gli inserzionisti possono selezionare gli annunci per il gruppo e la tua attività di navigazione rimane privata sul tuo dispositivo. Il tuo gruppo viene aggiornato ogni {NUM_DAYS} giorni}}</translation>
<translation id="2053553514270667976">ZIP</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggerimento}other{# suggerimenti}}</translation>
<translation id="2071692954027939183">Le notifiche sono state automaticamente bloccate perché solitamente non le consenti</translation>
<translation id="2079545284768500474">Annulla</translation>
<translation id="20817612488360358">Devono essere utilizzate le impostazioni del proxy di sistema ma è stata specificata anche una configurazione proxy esplicita.</translation>
<translation id="2082238445998314030">Risultato <ph name="RESULT_NUMBER" /> di <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Salva…</translation>
<translation id="2088086323192747268">Pulsante Gestisci sincronizzazione: premi Invio per gestire le informazioni da sincronizzare nelle impostazioni di Chrome</translation>
<translation id="2091887806945687916">Audio</translation>
<translation id="2094505752054353250">Dominio non corrispondente</translation>
@@ -379,6 +388,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="2317259163369394535"><ph name="DOMAIN" /> richiede un nome utente e una password.</translation>
<translation id="2330137317877982892">Scadenza della carta <ph name="CREDIT_CARD" />: <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Impostazione controllata dall'amministratore</translation>
+<translation id="2340263603246777781">Il sito <ph name="ORIGIN" /> desidera accoppiarsi</translation>
<translation id="2344028582131185878">Download automatici</translation>
<translation id="2346319942568447007">Immagine copiata</translation>
<translation id="2354001756790975382">Altri Preferiti</translation>
@@ -386,8 +396,10 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="2355395290879513365">Gli utenti malintenzionati potrebbero riuscire a vedere le immagini che visualizzi in questo sito e ingannarti modificandole.</translation>
<translation id="2356070529366658676">Chiedi</translation>
<translation id="2357481397660644965">Il tuo dispositivo è gestito da <ph name="DEVICE_MANAGER" /> e il tuo account da <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Tra meno di un giorno}=1{Tra un giorno}other{Tra {NUM_DAYS} giorni}}</translation>
<translation id="2359629602545592467">Multiple</translation>
<translation id="2359808026110333948">Continua</translation>
+<translation id="2359961752320758691">Il numero della tua carta virtuale è stato utilizzato.</translation>
<translation id="2367567093518048410">Livello</translation>
<translation id="2372464001869762664">Dopo la conferma, i dettagli della carta memorizzati nel tuo Account Google saranno condivisi con questo sito. Cerca il codice CVC nei dati del tuo account Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="239429038616798445">Questo metodo di spedizione non è disponibile. Prova un metodo diverso.</translation>
<translation id="2396249848217231973">&amp;Annulla eliminazione</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Precedenti</translation>
<translation id="2413528052993050574">Questo server non è riuscito a dimostrare che si tratta di <ph name="DOMAIN" />; il relativo certificato di sicurezza potrebbe essere revocato. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che intercetta la connessione.</translation>
<translation id="2414886740292270097">Scuro</translation>
<translation id="2438874542388153331">Perforatura quadrupla a destra</translation>
@@ -425,10 +438,10 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="2521385132275182522">Pinzatura in basso a destra</translation>
<translation id="2523886232349826891">Salvataggio effettuato solo su questo dispositivo</translation>
<translation id="2524461107774643265">Aggiungi altre informazioni</translation>
-<translation id="2526590354069164005">Desktop</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{e 1 altro}other{e altro #}}</translation>
<translation id="2536110899380797252">Aggiungi indirizzo</translation>
<translation id="2539524384386349900">Rileva</translation>
+<translation id="2541219929084442027">Le pagine visualizzate nelle schede di navigazione in incognito non vengono memorizzate nella cronologia del browser, nello spazio di archiviazione dei cookie o nella cronologia delle ricerche dopo avere chiuso tutte le schede di navigazione in incognito. I file scaricati o i preferiti creati verranno conservati.</translation>
<translation id="2544644783021658368">Documento singolo</translation>
<translation id="254947805923345898">Il valore della norma non è valido.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ha inviato una risposta non valida.</translation>
@@ -448,6 +461,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="2629325967560697240">Per il massimo livello di sicurezza di Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />attiva la protezione avanzata<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Impossibile trovare l'indirizzo IP del server di <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Stato:</translation>
+<translation id="264810637653812429">Nessun dispositivo compatibile trovato.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, premi Tab poi Invio per cancellare la cronologia di navigazione, i cookie, la cache e altri dati nelle impostazioni di Chrome</translation>
<translation id="2650446666397867134">L'accesso al file è stato negato</translation>
@@ -494,6 +508,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<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="2807052079800581569">Posizione Y immagine</translation>
+<translation id="2820957248982571256">Scansione…</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>
@@ -501,6 +516,8 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">Questo sito mostra annunci invasivi o fuorvianti.</translation>
+<translation id="287596039013813457">Amichevole</translation>
+<translation id="2876489322757410363">Per procedere al pagamento tramite un'applicazione esterna, uscirai dalla modalità di navigazione in incognito. Continuare?</translation>
<translation id="2878197950673342043">Piegatura a mappa</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Posizionamento delle finestre</translation>
@@ -550,7 +567,6 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, premi Tab e poi Invio per eseguire il controllo di sicurezza nelle impostazioni di Chrome</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>
<translation id="306573536155379004">Gioco iniziato.</translation>
<translation id="3080254622891793721">Grafico</translation>
<translation id="3086579638707268289">La tua attività sul Web viene monitorata</translation>
@@ -573,7 +589,6 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="315504272643575312">Il tuo account è gestito da <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Ripristina</translation>
<translation id="3162559335345991374">La rete Wi-Fi in uso potrebbe richiedere la visita della relativa pagina di accesso.</translation>
-<translation id="3167968892399408617">Le pagine visualizzate nelle schede in incognito non vengono memorizzate nella cronologia del browser, nell'archivio di cookie o nella cronologia delle ricerche dopo avere chiuso tutte le schede in incognito. I file scaricati o i preferiti creati verranno conservati.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Isola</translation>
<translation id="3176929007561373547">Controlla le impostazioni del proxy o contatta il tuo amministratore di rete per verificare che il server proxy funzioni. Se non ritieni di dover utilizzare un server proxy: <ph name="PLATFORM_TEXT" /></translation>
@@ -596,10 +611,12 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<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="3249845759089040423">Alla moda</translation>
<translation id="3252266817569339921">Francese</translation>
<translation id="3266793032086590337">Valore (conflitto)</translation>
<translation id="3268451620468152448">Schede aperte</translation>
<translation id="3270847123878663523">&amp;Annulla ridisposizione</translation>
+<translation id="3271648667212143903">Il sito <ph name="ORIGIN" /> desidera collegarsi</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">La tua organizzazione, <ph name="ENROLLMENT_DOMAIN" />, ha inviato alcune informazioni, quali impostazioni o criteri, ai siti web indicati di seguito.</translation>
<translation id="3282497668470633863">Aggiungi il nome indicato sulla carta</translation>
@@ -652,6 +669,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="3428151540071562330">Uno o più URI del modello server DnsOverHttpsTemplates non sono validi e non verranno utilizzati.</translation>
<translation id="3431636764301398940">Salva la carta per questo dispositivo</translation>
<translation id="3432601291244612633">Chiudi pagina</translation>
+<translation id="3435738964857648380">Sicurezza</translation>
<translation id="3435896845095436175">Abilita</translation>
<translation id="3438829137925142401">Usa le password salvate nel tuo Account Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -694,7 +712,10 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="3584299510153766161">Perforatura doppia in basso</translation>
<translation id="3586931643579894722">Nascondi dettagli</translation>
<translation id="3587738293690942763">Medio</translation>
+<translation id="3590643883886679995">I dati di accesso verranno memorizzati su questo dispositivo quando uscirai dalla modalità di navigazione in incognito.</translation>
+<translation id="359126217934908072">Mese/anno:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Puoi reimpostare il tuo gruppo in qualsiasi momento. Ci vorrà circa un giorno per unirsi a un nuovo gruppo.}=1{Puoi reimpostare il tuo gruppo in qualsiasi momento. Ci vorrà circa un giorno per unirsi a un nuovo gruppo.}other{Puoi reimpostare il tuo gruppo in qualsiasi momento. Ci vorranno {NUM_DAYS} giorni per unirsi a un nuovo gruppo.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Applicazione bloccata dal tuo amministratore</translation>
<translation id="3608932978122581043">Fornisci orientamento</translation>
@@ -703,13 +724,13 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="3615877443314183785">Inserisci una data di scadenza valida</translation>
<translation id="36224234498066874">Cancella dati di navigazione...</translation>
<translation id="362276910939193118">Mostra cronologia completa</translation>
-<translation id="3625635938337243871">I dati di accesso verranno memorizzati su questo dispositivo quando uscirai dalla modalità di navigazione in incognito.</translation>
<translation id="3630155396527302611">Se è già elencato come programma autorizzato ad accedere alla rete, prova a
rimuoverlo dall'elenco e ad aggiungerlo di nuovo.</translation>
<translation id="3630699740441428070">Gli amministratori di questo dispositivo hanno configurato la connessione di rete che potrebbe consentire loro di visualizzare il tuo traffico di rete, compresi i siti web che visiti.</translation>
<translation id="3631244953324577188">Dati biometrici</translation>
<translation id="3633738897356909127">Pulsante Aggiorna Chrome, premi Invio per aggiornare Chrome dalle relative impostazioni</translation>
<translation id="3634530185120165534">Vassoio 5</translation>
+<translation id="3637662659967048211">Salva nell'Account Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Applicazione:</translation>
<translation id="3650584904733503804">Convalida riuscita</translation>
@@ -750,6 +771,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="3781428340399460090">Fucsia</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Dispositivi Bluetooth</translation>
+<translation id="3787675388804467730">Numero carta virtuale</translation>
<translation id="3787705759683870569">Data di scadenza: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Dimensione 16</translation>
<translation id="3789841737615482174">Installa</translation>
@@ -769,6 +791,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="3841184659773414994">Gestori dei file</translation>
<translation id="385051799172605136">Indietro</translation>
<translation id="3858027520442213535">Aggiorna data e ora</translation>
+<translation id="3881478300875776315">Mostra meno righe</translation>
<translation id="3884278016824448484">Identificativo del dispositivo in conflitto</translation>
<translation id="3885155851504623709">Comune</translation>
<translation id="388632593194507180">Monitoraggio rilevato</translation>
@@ -794,6 +817,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="397105322502079400">Calcolo in corso...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> è bloccato</translation>
<translation id="3973357910713125165">Pulsante Esegui il controllo di sicurezza di Chrome, premi Invio per eseguire il controllo di sicurezza nelle impostazioni di Chrome</translation>
+<translation id="3986705137476756801">Disattiva Sottotitoli in tempo reale per ora</translation>
<translation id="3987405730340719549">Chrome ha stabilito che questo sito potrebbe essere falso o fraudolento.
Se ritieni che questo avviso sia stato mostrato per sbaglio, visita la pagina https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -890,13 +914,14 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="4275830172053184480">Riavvia il dispositivo</translation>
<translation id="4277028893293644418">Reimposta password</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="4287885627794386150">Funzionalità idonea per la prova, ma non attiva</translation>
<translation id="4297502707443874121">Miniatura della pagina <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Espandi</translation>
<translation id="4300675098767811073">Perforatura multipla a destra</translation>
<translation id="4302514097724775343">Tocca il dinosauro per giocare</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Impossibile accedere al file</translation>
-<translation id="4305817255990598646">Cambia</translation>
+<translation id="4306529830550717874">Vuoi salvare l'indirizzo?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blocca (predefinita)</translation>
<translation id="4314815835985389558">Gestisci sincronizzazione</translation>
@@ -923,6 +948,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="4377125064752653719">Hai tentato di accedere a <ph name="DOMAIN" /> ma il server ha presentato un certificato revocato dall'autorità di certificazione. Ciò significa che le credenziali di sicurezza presentate dal server non sono assolutamente attendibili. Potresti avere stabilito una comunicazione con un utente malintenzionato.</translation>
<translation id="4378154925671717803">Telefono</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Sottotitoli in tempo reale</translation>
<translation id="4406896451731180161">risultati di ricerca</translation>
<translation id="4408413947728134509">Cookie: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Hai appena inserito la tua password su un sito ingannevole. Chrome ti consiglia di visitare i siti <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> e altri siti in cui utilizzi questa password e di cambiarla subito.</translation>
@@ -935,7 +961,6 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<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="4464826014807964867">Siti web con informazioni della tua organizzazione</translation>
-<translation id="4466881336512663640">Le modifiche apportate al modulo andranno perse. Vuoi continuare?</translation>
<translation id="4476953670630786061">Questo modulo non è sicuro. La compilazione automatica è stata disattivata.</translation>
<translation id="4477350412780666475">Traccia successiva</translation>
<translation id="4482953324121162758">Questo sito non verrà tradotto.</translation>
@@ -969,6 +994,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="4594403342090139922">&amp;Annulla eliminazione</translation>
<translation id="4597348597567598915">Dimensione 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">D'impatto</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Rimborso collegato</translation>
<translation id="4636930964841734540">Info</translation>
@@ -988,6 +1014,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Lato</translation>
+<translation id="4702656508969495934">Sottotitoli in tempo reale visibili, utilizza il selettore di finestre per visualizzare la finestra</translation>
<translation id="4708268264240856090">La connessione è stata interrotta</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Eseguire lo strumento Diagnostica di rete Windows<ph name="END_LINK" /></translation>
@@ -1001,6 +1028,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="4738601419177586157"><ph name="TEXT" /> suggerimento di ricerca</translation>
<translation id="4742407542027196863">Gestisci password…</translation>
<translation id="4744603770635761495">Percorso eseguibile</translation>
+<translation id="4749011317274908093">Stai navigando in incognito</translation>
<translation id="4750917950439032686">Le tue informazioni (ad esempio password o numeri di carte di credito) restano private quando vengono inviate a questo sito.</translation>
<translation id="4756388243121344051">&amp;Cronologia</translation>
<translation id="4758311279753947758">Aggiungi informazioni di contatto</translation>
@@ -1030,6 +1058,8 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="4813512666221746211">Errore di rete</translation>
<translation id="4816492930507672669">Adatta alla pagina</translation>
<translation id="4819347708020428563">Vuoi modificare le annotazioni nella visualizzazione predefinita?</translation>
+<translation id="4825507807291741242">Potente</translation>
+<translation id="4838327282952368871">Surreale</translation>
<translation id="484462545196658690">Automatico</translation>
<translation id="4850886885716139402">Visualizza</translation>
<translation id="485316830061041779">Tedesco</translation>
@@ -1166,6 +1196,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="5314967030527622926">Fascicola</translation>
<translation id="5316812925700871227">Ruota in senso antiorario</translation>
<translation id="5317780077021120954">Salva</translation>
+<translation id="5321288445143113935">Ingrandita</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> di <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Scegli le informazioni di contatto</translation>
<translation id="5327248766486351172">Nome</translation>
@@ -1173,11 +1204,13 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="5332219387342487447">Modalità di spedizione</translation>
<translation id="5333022057423422993">Chrome ha rilevato che la password appena usata è stata esposta a una violazione dei dati. Per proteggere i tuoi account, ti consigliamo di controllare le password che hai salvato.</translation>
<translation id="5334013548165032829">Log di sistema dettagliati</translation>
+<translation id="5334145288572353250">Vuoi salvare l'indirizzo?</translation>
<translation id="5340250774223869109">L'applicazione è bloccata</translation>
<translation id="534295439873310000">Dispositivi NFC</translation>
<translation id="5344579389779391559">Questa pagina potrebbe tentare di addebitarti dei costi</translation>
<translation id="5355557959165512791">Al momento non puoi visitare il sito <ph name="SITE" /> perché il relativo certificato è stato revocato. In genere gli errori di rete e gli attacchi sono temporanei, pertanto questa pagina potrebbe funzionare più tardi.</translation>
<translation id="536296301121032821">Archiviazione delle impostazioni criterio non riuscita</translation>
+<translation id="5363309033720083897">Porta seriale consentita dal tuo amministratore</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="5386426401304769735">Il certificato di questo sito contiene un certificato che è stato firmato utilizzando SHA-1.</translation>
@@ -1186,6 +1219,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="5398772614898833570">Annunci bloccati</translation>
<translation id="5400836586163650660">Grigio</translation>
<translation id="540969355065856584">Questo server non è riuscito a verificare che si tratta di <ph name="DOMAIN" />; il relativo certificato di sicurezza non è considerato valido in questa fase. Il problema potrebbe essere dovuto a un'errata configurazione o a un malintenzionato che ha intercettato la connessione.</translation>
+<translation id="541143247543991491">Cloud (a livello di sistema)</translation>
<translation id="541416427766103491">Fascicolatore 4</translation>
<translation id="5421136146218899937">Cancella dati di navigazione...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> vuole inviarti notifiche</translation>
@@ -1199,6 +1233,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="5455374756549232013">Timestamp del criterio errato</translation>
<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="5463625433003343978">Ricerca di dispositivi in corso…</translation>
<translation id="5469868506864199649">Italiano</translation>
<translation id="5470861586879999274">&amp;Ripeti modifica</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1248,7 +1283,6 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="5624120631404540903">Gestisci password</translation>
<translation id="5629630648637658800">Caricamento delle impostazioni criterio non riuscito</translation>
<translation id="5631439013527180824">Token di gestione del dispositivo non valido</translation>
-<translation id="5632627355679805402">I tuoi dati sono stati criptati con la tua <ph name="BEGIN_LINK" />password Google<ph name="END_LINK" /> in data <ph name="TIME" />. Inserisci la password per avviare la sincronizzazione.</translation>
<translation id="5633066919399395251">Gli utenti malintenzionati attualmente presenti sul sito <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> potrebbero cercare di installare sul tuo computer programmi pericolosi che carpiscono o eliminano le tue informazioni (ad esempio, foto, password, messaggi e carte di credito). <ph name="BEGIN_LEARN_MORE_LINK" />Ulteriori informazioni<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Contenuti ingannevoli bloccati.</translation>
<translation id="5644090287519800334">Spostamento X lato 1 immagine</translation>
@@ -1287,12 +1321,12 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="5785756445106461925">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 l'aspetto della pagina.</translation>
<translation id="5786044859038896871">Vuoi inserire automaticamente i dati della carta?</translation>
<translation id="578633867165174378">Chrome ha rilevato che la password appena usata è stata esposta a una violazione dei dati. Ti consigliamo di cambiare subito questa password.</translation>
-<translation id="5798290721819630480">Vuoi annullare le modifiche?</translation>
<translation id="5803412860119678065">Vuoi inserire automaticamente <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Autorizzazioni</translation>
<translation id="5804427196348435412">Usare i dispositivi NFC</translation>
<translation id="5810442152076338065">La connessione a <ph name="DOMAIN" /> è criptata tramite un pacchetto di crittografia obsoleto.</translation>
<translation id="5813119285467412249">&amp;Ripeti aggiunta</translation>
+<translation id="5817918615728894473">Accoppia</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Gli importi dei pagamenti che effettuerai verranno addebitati su questa carta, ma il numero effettivo della carta non verrà condiviso con questo sito. Per maggiore sicurezza verrà generato un codice CVC temporaneo.}other{Gli importi dei pagamenti che effettuerai verranno addebitati sulla carta selezionata, ma il numero effettivo della carta non verrà condiviso con questo sito. Per maggiore sicurezza verrà generato un codice CVC temporaneo.}}</translation>
<translation id="5826507051599432481">Nome comune (CN)</translation>
<translation id="5838278095973806738">Non dovresti inserire dati sensibili in questo sito (ad esempio password o carte di credito) perché potrebbero essere intercettati da utenti malintenzionati.</translation>
@@ -1300,6 +1334,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="5855253129151731373">Il nome host di questo sito è simile a <ph name="LOOKALIKE_DOMAIN" />. A volte i malintenzionati imitano i siti modificando leggermente e in modo poco evidente il nome di dominio.
Se ritieni che questo avviso sia stato mostrato per sbaglio, visita la pagina https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Off</translation>
<translation id="5862579898803147654">Fascicolatore 8</translation>
<translation id="5863847714970149516">La pagina che segue potrebbe tentare di addebitarti dei costi</translation>
<translation id="5866257070973731571">Aggiungi numero di telefono</translation>
@@ -1316,6 +1351,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="5913377024445952699">Acquisizione schermo in pausa</translation>
<translation id="59174027418879706">Attivato</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 in uso}other{# in uso}}</translation>
<translation id="5921185718311485855">On</translation>
<translation id="5921639886840618607">Vuoi salvare la carta nell'Account Google?</translation>
<translation id="5922853866070715753">Hai quasi finito.</translation>
@@ -1335,6 +1371,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="5989320800837274978">Non sono stati specificati né server proxy fissi né un URL script .pac.</translation>
<translation id="5992691462791905444">Piegatura a Z</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> risultati per "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Classico</translation>
<translation id="6008122969617370890">Ordine da N a 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Controlla le tue password</translation>
@@ -1356,6 +1393,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="6045164183059402045">Modello imposizione</translation>
<translation id="6047233362582046994">Se sei consapevole dei rischi per la tua sicurezza, potresti <ph name="BEGIN_LINK" />visitare questo sito<ph name="END_LINK" /> senza aspettare che vengano rimosse le app dannose.</translation>
<translation id="6047927260846328439">Questi contenuti potrebbero cercare di indurti con l'inganno a installare software o a rivelare informazioni personali. <ph name="BEGIN_LINK" />Mostra comunque<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Tieni premuto |<ph name="ACCELERATOR" />| per uscire dallo schermo intero</translation>
<translation id="6049488691372270142">Consegna pagina</translation>
<translation id="6051221802930200923">Al momento non puoi visitare il sito web <ph name="SITE" /> perché utilizza il blocco dei certificati. In genere gli errori di rete e gli attacchi sono temporanei, pertanto questa pagina potrebbe funzionare più tardi.</translation>
<translation id="6051898664905071243">Numero di pagine:</translation>
@@ -1372,6 +1410,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<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>
<translation id="6116338172782435947">Leggere testi e immagini copiati negli appunti</translation>
<translation id="6120179357481664955">Ricordi il tuo ID UPI?</translation>
+<translation id="6123290840358279103">Visualizza carta virtuale</translation>
<translation id="6124432979022149706">Connettori di Chrome Enterprise</translation>
<translation id="6146055958333702838">Controlla eventuali cavi e riavvia eventuali router, modem o altri dispositivi di rete in uso.</translation>
<translation id="614940544461990577">Prova a:</translation>
@@ -1407,6 +1446,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="6289939620939689042">Colore pagina</translation>
<translation id="6290238015253830360">Gli articoli suggeriti vengono visualizzati qui</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Interruzione dell'Assistente Google in Chrome</translation>
<translation id="6305205051461490394"><ph name="URL" /> non è raggiungibile.</translation>
<translation id="6312113039770857350">Pagina web non disponibile</translation>
@@ -1432,6 +1472,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="6390200185239044127">Piegatura a Z a metà</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">La possibilità di incollare da <ph name="ORIGIN_NAME" /> a questa posizione è stata bloccata da un criterio dell'amministratore</translation>
+<translation id="6398765197997659313">Esci da schermo intero</translation>
<translation id="6401136357288658127">Questa norma è obsoleta. Dovresti usare invece la norma <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Modifica preferito</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1444,7 +1485,6 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="6428450836711225518">Verifica il numero di telefono</translation>
<translation id="6433490469411711332">Modifica informazioni di contatto</translation>
<translation id="6433595998831338502">Connessione negata da <ph name="HOST_NAME" />.</translation>
-<translation id="6434309073475700221">Elimina</translation>
<translation id="6440503408713884761">Ignorata</translation>
<translation id="6443406338865242315">Le estensioni e i plug-in che hai installato</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1487,6 +1527,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="6624427990725312378">Informazioni di contatto</translation>
<translation id="6626291197371920147">Aggiungi un numero di carta valido</translation>
<translation id="6628463337424475685">Ricerca <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Ricerca di dispositivi USB in corso…</translation>
<translation id="6630809736994426279">Gli utenti malintenzionati attualmente presenti sul sito <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> potrebbero cercare di installare sul tuo Mac programmi pericolosi che carpiscono o eliminano le tue informazioni (ad esempio, foto, password, messaggi e carte di credito). <ph name="BEGIN_LEARN_MORE_LINK" />Ulteriori informazioni<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Cancella</translation>
@@ -1502,6 +1543,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="6671697161687535275">Rimuovere il suggerimento per i moduli da Chromium?</translation>
<translation id="6685834062052613830">Esci e completa la configurazione</translation>
<translation id="6687335167692595844">Dimensioni carattere richieste</translation>
+<translation id="6688743156324860098">Aggiorna…</translation>
<translation id="6689249931105087298">Relativo con compressione del punto nero</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="6698381487523150993">Data creazione:</translation>
@@ -1517,6 +1559,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="6744009308914054259">In attesa di una connessione, puoi visitare la pagina Download per leggere gli articoli offline.</translation>
<translation id="6753269504797312559">Valore criterio</translation>
<translation id="6757797048963528358">Il dispositivo è entrato in modalità sospensione.</translation>
+<translation id="6767985426384634228">Vuoi aggiornare l'indirizzo?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Lilla</translation>
@@ -1539,6 +1582,7 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome ha semplificato questa pagina per facilitarne la lettura. Chrome ha recuperato la pagina originale tramite una connessione non sicura.</translation>
<translation id="6891596781022320156">Il livello della norma non è supportato.</translation>
+<translation id="6895143722905299846">Numero carta virtuale:</translation>
<translation id="6895330447102777224">La carta è stata confermata</translation>
<translation id="6897140037006041989">User-agent</translation>
<translation id="6898699227549475383">Organizzazione (O)</translation>
@@ -1574,10 +1618,10 @@ In caso contrario l'uso sarà bloccato dalle impostazioni sulla privacy. I conte
<translation id="7004583254764674281">Usa Windows Hello per verificare più velocemente le carte</translation>
<translation id="7006930604109697472">Invia comunque</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Impostazioni di ridimensionamento</translation>
<translation id="7014741021609395734">Livello di zoom</translation>
<translation id="7016992613359344582">L'addebito potrebbe essere singolo oppure ricorrente e potrebbe non essere evidente.</translation>
<translation id="7029809446516969842">Password</translation>
+<translation id="7030436163253143341">ll certificato non è valido</translation>
<translation id="7031646650991750659">Le app Google Play che hai installato</translation>
<translation id="7050187094878475250">Hai tentato di visitare il sito <ph name="DOMAIN" />, ma il server ha presentato un certificato con periodo di validità troppo lungo per poter essere ritenuto attendibile.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Al momento questa carta non può essere salvata}other{Al momento queste carte non possono essere salvate}}</translation>
@@ -1647,12 +1691,14 @@ Ulteriori dettagli:
<translation id="7300012071106347854">Blu cobalto</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Alto</translation>
+<translation id="7305756307268530424">Inizia più lentamente</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Guida alla connessione</translation>
<translation id="7323804146520582233">Nascondi la sezione "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Override account locale del dispositivo</translation>
<translation id="7333654844024768166">Hai appena inserito la tua password su un sito ingannevole. Chromium ti consiglia di visitare i siti <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> e altri siti in cui utilizzi questa password e di cambiarla subito.</translation>
<translation id="7334320624316649418">&amp;Ripeti ridisposizione</translation>
+<translation id="7337248890521463931">Mostra più righe</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>
@@ -1660,6 +1706,7 @@ Ulteriori dettagli:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Riga di comando</translation>
<translation id="7359588939039777303">Annunci bloccati.</translation>
+<translation id="7363096869660964304">Non sei completamente invisibile: se navighi in incognito, la tua navigazione non viene nascosta al tuo datore di lavoro, al provider di servizi Internet o ai siti web che visiti.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, premi Tab e poi Invio per aggiungere e gestire indirizzi nelle impostazioni di Chrome</translation>
<translation id="7365849542400970216">Conoscere l'utilizzo del tuo dispositivo?</translation>
<translation id="7372973238305370288">risultato della ricerca</translation>
@@ -1670,7 +1717,9 @@ Ulteriori dettagli:
<translation id="7378594059915113390">Controlli multimediali</translation>
<translation id="7378627244592794276">No</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Non applicabile</translation>
<translation id="7390545607259442187">Conferma della carta</translation>
+<translation id="7392089738299859607">Aggiorna indirizzo</translation>
<translation id="7399802613464275309">Controllo sicurezza</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Il tuo dispositivo <ph name="DEVICE_NAME" /> è gestito</translation>
@@ -1685,6 +1734,7 @@ Ulteriori dettagli:
&lt;li&gt;Visita il &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centro assistenza Chrome&lt;/a&gt; per avere informazioni su come rimuovere definitivamente il software dal computer.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Incantevole</translation>
<translation id="7416351320495623771">Gestisci password…</translation>
<translation id="7419106976560586862">Percorso profilo</translation>
<translation id="7437289804838430631">Aggiungi informazioni di contatto</translation>
@@ -1700,7 +1750,7 @@ Ulteriori dettagli:
<translation id="7481312909269577407">Avanti</translation>
<translation id="7485870689360869515">Nessun dato trovato.</translation>
<translation id="7495528107193238112">Questi contenuti sono bloccati. Contatta il proprietario del sito per risolvere il problema.</translation>
-<translation id="7498234416455752244">Continua modifica</translation>
+<translation id="7498193950643227031">Se viene ridimensionata potrebbe avere un comportamento imprevisto. Ora puoi limitare la possibilità di ridimensionare le app nelle <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Hai appena inserito la tua password su un sito ingannevole. Chromium ti consiglia di controllare le password salvate per <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> e altri siti su cui utilizzi questa password.</translation>
<translation id="7508255263130623398">L'ID dispositivo della norma restituito è vuoto o non corrisponde all'ID dispositivo corrente</translation>
<translation id="7508870219247277067">Verde pisello</translation>
@@ -1720,6 +1770,7 @@ Ulteriori dettagli:
<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="755279583747225797">La prova è attiva</translation>
<translation id="7552846755917812628">Prova i seguenti suggerimenti:</translation>
<translation id="7554475479213504905">Ricarica e mostra comunque</translation>
<translation id="7554791636758816595">Nuova scheda</translation>
@@ -1738,7 +1789,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, premi Tab poi Invio per visualizzare e gestire le password nelle impostazioni di Chrome</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="7616645509853975347">L'amministratore ha attivato Chrome Enterprise Connectors sul tuo browser. Questi connettori hanno accesso ad alcuni dei tuoi dati.</translation>
<translation id="7619838219691048931">Ultimo foglio</translation>
<translation id="762844065391966283">Un oggetto alla volta</translation>
@@ -1803,13 +1853,12 @@ Ulteriori dettagli:
<translation id="782886543891417279">La rete Wi-Fi in uso (<ph name="WIFI_NAME" />) potrebbe richiedere la visita della relativa pagina di accesso.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Nessuna}=1{1 app (<ph name="EXAMPLE_APP_1" />)}=2{2 app (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# app (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Non sei completamente invisibile: se navighi in incognito, la tua navigazione non viene nascosta al tuo datore di lavoro, al provider di servizi Internet o ai siti web che visiti.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Apri i file con associazioni a determinati tipi di file</translation>
<translation id="7862185352068345852">Vuoi uscire dal sito?</translation>
<translation id="7865448901209910068">Massima velocità</translation>
<translation id="7874263914261512992">Hai appena inserito la tua password su un sito ingannevole. Chrome ti consiglia di controllare le password salvate per <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> e altri siti su cui utilizzi questa password.</translation>
<translation id="7878562273885520351">La tua password potrebbe essere stata compromessa</translation>
+<translation id="7880146494886811634">Salva indirizzo</translation>
<translation id="7882421473871500483">Marrone</translation>
<translation id="7887683347370398519">Controlla il tuo codice CVC e riprova</translation>
<translation id="7887885240995164102">Attiva Picture in picture</translation>
@@ -1817,6 +1866,7 @@ Ulteriori dettagli:
<translation id="7894280532028510793">Se l'ortografia è corretta, <ph name="BEGIN_LINK" />prova a eseguire lo strumento Diagnostica di rete<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Sconosciuta</translation>
+<translation id="793209273132572360">Vuoi aggiornare l'indirizzo?</translation>
<translation id="7932579305932748336">Rivestimento</translation>
<translation id="79338296614623784">Inserisci un numero di telefono valido</translation>
<translation id="7934052535022478634">Pagamento completato</translation>
@@ -1887,6 +1937,7 @@ Ulteriori dettagli:
<translation id="8175796834047840627">Chrome chiede se vuoi salvare le tue carte nel tuo Account Google perché hai eseguito l'accesso. Puoi modificare questo comportamento nelle impostazioni.</translation>
<translation id="8176440868214972690">L'amministratore di questo dispositivo ha inviato alcune informazioni, quali impostazioni o criteri, ai siti web indicati di seguito.</translation>
<translation id="8184538546369750125">Usa predefinita globale (Consenti)</translation>
+<translation id="8193086767630290324">Azioni intraprese con dati segnalati come riservati</translation>
<translation id="8194797478851900357">&amp;Annulla spostamento</translation>
<translation id="8201077131113104583">URL di aggiornamento non valido per l'estensione con ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Riepilogo dell’ordine</translation>
@@ -1909,6 +1960,7 @@ Ulteriori dettagli:
<translation id="8249296373107784235">Interrompi</translation>
<translation id="8249320324621329438">Ultimo recupero:</translation>
<translation id="8253091569723639551">Indirizzo di fatturazione obbligatorio</translation>
+<translation id="8257387598443225809">Questa app è stata progettata per i dispositivi mobili</translation>
<translation id="825929999321470778">Mostra tutte le password salvate</translation>
<translation id="8261506727792406068">Elimina</translation>
<translation id="8262952874573525464">Impuntura in basso</translation>
@@ -2032,7 +2084,6 @@ Ulteriori dettagli:
<translation id="8719528812645237045">Perforatura multipla in alto</translation>
<translation id="8725066075913043281">Riprova</translation>
<translation id="8726549941689275341">Dimensioni pagina:</translation>
-<translation id="8728672262656704056">Sei passato alla navigazione in incognito</translation>
<translation id="8730621377337864115">Fine</translation>
<translation id="8731544501227493793">Pulsante Gestisci password, premi Invio per visualizzare e gestire le tue password nelle impostazioni di Chrome</translation>
<translation id="8734529307927223492">Il tuo dispositivo <ph name="DEVICE_TYPE" /> è gestito da <ph name="MANAGER" /></translation>
@@ -2109,6 +2160,7 @@ Ulteriori dettagli:
<translation id="9020542370529661692">Questa pagina è stata tradotta in <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Non valido)</translation>
+<translation id="9030265603405983977">In bianco e nero</translation>
<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>
@@ -2132,6 +2184,7 @@ Ulteriori dettagli:
<translation id="91108059142052966">Il criterio dell'amministratore disattiva la condivisione dello schermo con <ph name="APPLICATION_TITLE" /> quando sono visibili contenuti riservati</translation>
<translation id="9114524666733003316">Conferma della carta...</translation>
<translation id="9114581008513152754">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="9117930699067497412">Vivace</translation>
<translation id="9119042192571987207">Caricato</translation>
<translation id="9128016270925453879">I criteri sono stati caricati</translation>
<translation id="9128870381267983090">Collegati alla rete</translation>
@@ -2150,6 +2203,7 @@ Ulteriori dettagli:
<translation id="9170848237812810038">&amp;Annulla</translation>
<translation id="9171296965991013597">Uscire dall'app?</translation>
<translation id="9173282814238175921">Documento singolo/Nuovo foglio</translation>
+<translation id="9173995187295789444">Ricerca di dispositivi Bluetooth...</translation>
<translation id="917450738466192189">Il certificato del server non è valido.</translation>
<translation id="9174917557437862841">Pulsante per passare alla scheda, premi INVIO per passare a questa scheda</translation>
<translation id="9179703756951298733">Gestisci i metodi di pagamento e le informazioni delle tue carte di credito nelle impostazioni di Chrome</translation>
diff --git a/chromium/components/strings/components_strings_iw.xtb b/chromium/components/strings/components_strings_iw.xtb
index eef0d392fa7..8c1e682d7e3 100644
--- a/chromium/components/strings/components_strings_iw.xtb
+++ b/chromium/components/strings/components_strings_iw.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">â€×× ×”×פשרות הזו מסומנת, Chrome ישמור עותק של הכרטיס במכשיר ×”×–×” כדי ×œ×ž×œ× ×˜×¤×¡×™× ×‘×ž×”×™×¨×•×ª רבה יותר.</translation>
<translation id="1110994991967754504">צריך לבחור ×ת ההרש××” של <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;ביטול של שינוי סדר</translation>
+<translation id="1123753900084781868">הכתוביות המיידיות ×œ× ×–×ž×™× ×•×ª עכשיו.</translation>
<translation id="1125573121925420732">×œ×¤×¢×ž×™× ×ž×•×¤×™×¢×•×ª ×זהרות בזמן ש××ª×¨×™× ×ž×¢×“×›× ×™× ×ת ×”×בטחה שלה×. ×–×” ×מור להיפסק בקרוב.</translation>
<translation id="112840717907525620">המטמון של המדיניות תקין</translation>
<translation id="1130564665089811311">â€×”לחצן '×ª×¨×’×•× ×”×“×£', יש ללחוץ על Enter כדי ×œ×ª×¨×’× ×ת הדף ×”×–×” ב×מצעות Google Translate</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">×©× ×”×ž×›×©×™×¨ שלך</translation>
<translation id="124116460088058876">שפות נוספות</translation>
<translation id="1243027604378859286">מחבר:</translation>
+<translation id="1246424317317450637">מודגש</translation>
<translation id="1250759482327835220">â€×›×“×™ ×œ×©×œ× ×ž×”×¨ יותר ×‘×¤×¢× ×”×‘××”, ×פשר לשמור בחשבון Google ×ת פרטי הכרטיס, ×”×©× ×•×”×›×ª×•×‘×ª לחיוב.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (מסונכרני×)</translation>
<translation id="1256368399071562588">â€&lt;p&gt;×× × ×™×¡×™×ª להיכנס ל×תר ×•×”×•× ×œ× × ×¤×ª×—, ×§×•×“× ×™×© לנסות לפתור ×ת הבעיה בעזרת ×”×©×œ×‘×™× ×”×‘××™×:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">עליך לשנות ×ת הסיסמה</translation>
<translation id="1484290072879560759">בחירת כתובת למשלוח</translation>
<translation id="1492194039220927094">דחיפת מדיניות:</translation>
+<translation id="1495677929897281669">חזרה לכרטיסייה</translation>
<translation id="1501859676467574491">â€×”צגת ×›×¨×˜×™×¡×™× ×ž×—×©×‘×•×Ÿ Google שלך</translation>
<translation id="1507202001669085618">â€&lt;p&gt;השגי××” הזו תוצג ×× ×ž×©×ª×ž×©×™× ×‘×¤×•×¨×˜×œ Wi-Fi שבו צריך להיכנס לחשבון לפני התחברות לרשת.&lt;/p&gt;
&lt;p&gt;כדי לפתור ×ת השגי××”, צריך ללחוץ על &lt;strong&gt;התחברות&lt;/strong&gt; בדף ×©×ž× ×¡×™× ×œ×¤×ª×•×—.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">הדף ×”×–×” ×ומר</translation>
<translation id="153384715582417236">×–×” הכול בינתיי×</translation>
<translation id="1536390784834419204">×ª×¨×’×•× ×”×“×£</translation>
+<translation id="1539840569003678498">הדוח נשלח:</translation>
<translation id="154408704832528245">בחירת כתובת למסירה</translation>
<translation id="1549470594296187301">â€JavaScript צריך להיות מופעל כדי להשתמש בתכונה זו.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">הקצה הקצר ר×שון</translation>
<translation id="168693727862418163">×ימות ערך המדיניות ×”×–×” נכשל בבדיקה מול הסכימה והמערכת ×ª×ª×¢×œ× ×ž×ž× ×•.</translation>
<translation id="168841957122794586">×ישור השרת מכיל מפתח הצפנה חלש.</translation>
+<translation id="1696290444144917273">הצגת ×”×¤×¨×˜×™× ×©×œ הכרטיס הווירטו×לי</translation>
<translation id="1697532407822776718">הכול מוכן!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{השרת ×”×–×” ×œ× ×”×¦×œ×™×— להוכיח ×©×”×•× <ph name="DOMAIN" />; ×ישור ×”×בטחה שלו ×מור להיכנס לתוקף רק מחר. ייתכן שהסיבה לכך ×”×™× ×”×’×“×¨×” שגויה ×ו שתוקף מיירט ×ת החיבור שלך.}two{השרת ×”×–×” ×œ× ×”×¦×œ×™×— להוכיח ×©×”×•× <ph name="DOMAIN" />; ×ישור ×”×בטחה שלו ×מור להיכנס לתוקף רק בעוד יומיי×. ייתכן שהסיבה לכך ×”×™× ×”×’×“×¨×” שגויה ×ו שתוקף מיירט ×ת החיבור שלך.}many{השרת ×”×–×” ×œ× ×”×¦×œ×™×— להוכיח ×©×”×•× <ph name="DOMAIN" />; ×ישור ×”×בטחה שלו ×מור להיכנס לתוקף רק בעוד # ימי×. ייתכן שהסיבה לכך ×”×™× ×”×’×“×¨×” שגויה ×ו שתוקף מיירט ×ת החיבור שלך.}other{השרת ×”×–×” ×œ× ×”×¦×œ×™×— להוכיח ×©×”×•× <ph name="DOMAIN" />; ×ישור ×”×בטחה שלו ×מור להיכנס לתוקף רק בעוד # ימי×. ייתכן שהסיבה לכך ×”×™× ×”×’×“×¨×” שגויה ×ו שתוקף מיירט ×ת החיבור שלך.}}</translation>
<translation id="1710259589646384581">מערכת הפעלה</translation>
+<translation id="1711234383449478798">×ין התייחסות למדיניות ×›×™ ×œ× ×”×•×’×“×¨ הערך <ph name="VALUE" /> ב-<ph name="POLICY_NAME" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> רוצה ל×חסן × ×ª×•× ×™× ×‘×ž×—×©×‘ המקומי שלך ב×ופן קבוע</translation>
<translation id="1713628304598226412">מגש 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">תיבת דו×ר 3</translation>
<translation id="1718029547804390981">המסמך גדול מדי ×•×œ× × ×™×ª×Ÿ להוסיף לו הערות</translation>
<translation id="1721424275792716183">* זהו שדה חובה</translation>
+<translation id="1727613060316725209">×”×ישור תקין</translation>
<translation id="1727741090716970331">הוספת מספר כרטיס חוקי</translation>
<translation id="1728677426644403582">זהו המקור של דף ×ינטרנט</translation>
<translation id="173080396488393970">×ין תמיכה בכרטיס מסוג ×–×”</translation>
@@ -246,7 +253,6 @@
×ת הבקשה שלך בשביל <ph name="SITE" />. מפעילי ××ª×¨×™× ×™×›×•×œ×™× ×œ×”×©×ª×ž×© במדיניות מקור
כדי להגדיר מ×פייני ×בטחה ומ××¤×™×™× ×™× ××—×¨×™× ×¢×‘×•×¨ ×תר מסוי×.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">יש לעדכן ×ת ביטוי הסיסמה של הסנכרון.</translation>
<translation id="1787142507584202372">×›×ן מופיעות הכרטיסיות שפתחת</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742">â€<ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ניתן לבצע כמה פעולות, יש להקיש על Tab כדי לעבור ביניהן</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">מודעות</translation>
<translation id="1919367280705858090">עזרה לגבי הודעות שגי××” ספציפיות</translation>
<translation id="192020519938775529">{COUNT,plural, =0{לל×}=1{×תר ×חד}two{שני ×תרי×}many{# ×תרי×}other{# ×תרי×}}</translation>
+<translation id="1924727005275031552">חדשה</translation>
<translation id="1945968466830820669">â€×™×™×ª×›×Ÿ ×©×œ× ×™×ª×פשר לך לגשת לחשבון ×”×רגוני, והזהות שלך עלולה להיגנב. לגלישה בטוחה ב-Chromium, מומלץ לשנות ×ת הסיסמה עכשיו.</translation>
<translation id="1947454675006758438">סיכת הידוק בפינה הימנית העליונה</translation>
<translation id="1958218078413065209">הניקוד ×”×›×™ גבוה שלך ×”×•× <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">מגש 7</translation>
<translation id="204357726431741734">â€×›×“×™ להשתמש בסיסמ×ות השמורות בחשבון Google, עליך להיכנס שוב לחשבון</translation>
<translation id="2053111141626950936">×“×¤×™× ×‘<ph name="LANGUAGE" /> ×œ× ×™×ª×•×¨×’×ž×•.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{â€×›×©×”פקד ×”×–×” פועל והסטטוס פעיל, Chrome בודק מהי הקבוצה הגדולה של ×נשי×, ×ו "הקבוצה בעלת המ××¤×™×™× ×™× ×”×ž×©×•×ª×¤×™×", שפעילות הגלישה ×”×חרונה שלך ×”×›×™ דומה לה. ×ž×¤×¨×¡×ž×™× ×™×›×•×œ×™× ×œ×‘×—×•×¨ מודעות שמת×ימות לקבוצה, ופעילות הגלישה שלך נשמרת ב×ופן פרטי במכשיר. הקבוצה מתעדכנת מדי יו×.}=1{â€×›×©×”פקד ×”×–×” פועל והסטטוס פעיל, Chrome בודק מהי הקבוצה הגדולה של ×נשי×, ×ו "הקבוצה בעלת המ××¤×™×™× ×™× ×”×ž×©×•×ª×¤×™×", שפעילות הגלישה ×”×חרונה שלך ×”×›×™ דומה לה. ×ž×¤×¨×¡×ž×™× ×™×›×•×œ×™× ×œ×‘×—×•×¨ מודעות שמת×ימות לקבוצה, ופעילות הגלישה שלך נשמרת ב×ופן פרטי במכשיר. הקבוצה מתעדכנת מדי יו×.}two{â€×›×©×”פקד ×”×–×” פועל והסטטוס פעיל, Chrome בודק מהי הקבוצה הגדולה של ×נשי×, ×ו "הקבוצה בעלת המ××¤×™×™× ×™× ×”×ž×©×•×ª×¤×™×", שפעילות הגלישה ×”×חרונה שלך ×”×›×™ דומה לה. ×ž×¤×¨×¡×ž×™× ×™×›×•×œ×™× ×œ×‘×—×•×¨ מודעות שמת×ימות לקבוצה, ופעילות הגלישה שלך נשמרת ב×ופן פרטי במכשיר. הקבוצה מתעדכנת מדי ×™×•×ž×™×™× ({NUM_DAYS}).}many{â€×›×©×”פקד ×”×–×” פועל והסטטוס פעיל, Chrome בודק מהי הקבוצה הגדולה של ×נשי×, ×ו "הקבוצה בעלת המ××¤×™×™× ×™× ×”×ž×©×•×ª×¤×™×", שפעילות הגלישה ×”×חרונה שלך ×”×›×™ דומה לה. ×ž×¤×¨×¡×ž×™× ×™×›×•×œ×™× ×œ×‘×—×•×¨ מודעות שמת×ימות לקבוצה, ופעילות הגלישה שלך נשמרת ב×ופן פרטי במכשיר. הקבוצה מתעדכנת מדי {NUM_DAYS} ימי×.}other{â€×›×©×”פקד ×”×–×” פועל והסטטוס פעיל, Chrome בודק מהי הקבוצה הגדולה של ×נשי×, ×ו "הקבוצה בעלת המ××¤×™×™× ×™× ×”×ž×©×•×ª×¤×™×", שפעילות הגלישה ×”×חרונה שלך ×”×›×™ דומה לה. ×ž×¤×¨×¡×ž×™× ×™×›×•×œ×™× ×œ×‘×—×•×¨ מודעות שמת×ימות לקבוצה, ופעילות הגלישה שלך נשמרת ב×ופן פרטי במכשיר. הקבוצה מתעדכנת מדי {NUM_DAYS} ימי×.}}</translation>
<translation id="2053553514270667976">מיקוד</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{הצעה ×חת}two{שתי הצעות}many{# הצעות}other{# הצעות}}</translation>
<translation id="2071692954027939183">ההתר×ות נחסמו ב×ופן ×וטומטי ×›×™ לרוב ×œ× × ×™×ª× ×ª ממך הרש××” להציג ×ותן</translation>
<translation id="2079545284768500474">ביטול הפעולה</translation>
<translation id="20817612488360358">â€× ×§×‘×¢ שימוש בהגדרות שרת Proxy של מערכת ×ך בנוסף מצוינת ×’× ×ª×¦×•×¨×” מפורשת של שרת Proxy.</translation>
<translation id="2082238445998314030">תוצ××” <ph name="RESULT_NUMBER" /> מתוך <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">שמירה…</translation>
<translation id="2088086323192747268">â€×”לחצן 'ניהול הסנכרון', יש להקיש על Enter כדי לקבוע ××™×–×” מידע יסונכרן בהגדרות Chrome</translation>
<translation id="2091887806945687916">צליל</translation>
<translation id="2094505752054353250">××™ הת×מה בדומייני×</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> דורש ×©× ×ž×©×ª×ž×© וסיסמה.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, בתוקף עד <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">ההגדרה נשלטת על-ידי מנהל המערכת</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> רוצה לבצע הת×מה ×¢×</translation>
<translation id="2344028582131185878">הורדות ×וטומטיות</translation>
<translation id="2346319942568447007">תמונה שהעתקת</translation>
<translation id="2354001756790975382">סימניות ×חרות</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">ייתכן ×©×ª×•×§×¤×™× ×™×•×›×œ×• לר×ות ×ת התמונות שבהן צפית ב×תר ×–×”, ול×חר מכן ×”× ×™× ×¡×• להונות ×ותך על ידי שינוי התמונות.</translation>
<translation id="2356070529366658676">לש×ול</translation>
<translation id="2357481397660644965">המכשיר שלך מנוהל על ידי <ph name="DEVICE_MANAGER" /> והחשבון שלך מנוהל על ידי <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{בעוד פחות מיו×}=1{בעוד יו×}two{בעוד ×™×•×ž×™×™× ({NUM_DAYS})}many{בעוד {NUM_DAYS} ימי×}other{בעוד {NUM_DAYS} ימי×}}</translation>
<translation id="2359629602545592467">מטבעות מרובי×</translation>
<translation id="2359808026110333948">המשך</translation>
+<translation id="2359961752320758691">מספר הכרטיס הווירטו×לי שלך הוזן ב×ופן ×וטומטי.</translation>
<translation id="2367567093518048410">רמה</translation>
<translation id="2372464001869762664">â€×חרי שנקבל ממך ×ישור, נשתף ×¢× ×”×תר ×”×–×” ×ת פרטי הכרטיס מחשבון Google. ניתן ×œ×ž×¦×•× ×ת ×”-CVC ×‘×¤×¨×˜×™× ×©×œ חשבון Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">שיטת המשלוח הזו ×œ× ×–×ž×™× ×”. עליך לבחור שיטה ×חרת.</translation>
<translation id="2396249848217231973">&amp;ביטול מחיקה</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">ישנה</translation>
<translation id="2413528052993050574">השרת ×”×–×” ×œ× ×”×¦×œ×™×— להוכיח ×©×”×•× <ph name="DOMAIN" />. ייתכן ש×ישור ×”×בטחה שלו בוטל. הסיבה לכך עשויה להיות הגדרה שגויה ×ו תוקף המיירט ×ת החיבור שלך.</translation>
<translation id="2414886740292270097">×›×”×”</translation>
<translation id="2438874542388153331">4 × ×™×§×•×‘×™× ×‘×¦×“ ימין</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">סיכת הידוק בפינה הימנית התחתונה</translation>
<translation id="2523886232349826891">הכרטיס יישמר רק במכשיר הזה</translation>
<translation id="2524461107774643265">הוספת עוד מידע</translation>
-<translation id="2526590354069164005">שולחן עבודה</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{ודומיין ×חד נוסף}two{ו-# ×“×•×ž×™×™× ×™× × ×•×¡×¤×™×}many{ו-# ×“×•×ž×™×™× ×™× × ×•×¡×¤×™×}other{ו-# ×“×•×ž×™×™× ×™× × ×•×¡×¤×™×}}</translation>
<translation id="2536110899380797252">הוספת כתובת</translation>
<translation id="2539524384386349900">×–×”×”</translation>
+<translation id="2541219929084442027">â€×“×¤×™× ×©×”×¦×’×ª בכרטיסיות המצב ×”×נונימי ×œ× ×™×™×©×ž×¨×• בהיסטוריית הדפדפן, ב×חסון קובצי ×”-cookie ×ו בהיסטוריית ×”×—×™×¤×•×©×™× ×œ×חר שכל כרטיסיות המצב ×”×נונימי ייסגרו. ×§×‘×¦×™× ×©×”×•×¨×“×ª ×ו סימניות שיצרת יישמרו.</translation>
<translation id="2544644783021658368">מסמך יחיד</translation>
<translation id="254947805923345898">ערך המדיניות ×œ× ×—×•×§×™.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> שלח תגובה ×œ× ×—×•×§×™×ª.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">â€×›×“×™ ליהנות מ×בטחה ברמה הגבוהה ביותר ב-Chrome, יש <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />להפעיל ×ת ×”×”×’× ×” המשופרת<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">â€×œ× ניתן ×”×™×” ×œ×ž×¦×•× ×ת כתובת ×”-IP של השרת של <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">סטטוס:</translation>
+<translation id="264810637653812429">×œ× × ×ž×¦×ו ×ž×›×©×™×¨×™× ×ª×•×מי×.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861">â€<ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, יש להקיש על Tab ו××– על Enter כדי לנקות ×ת נתוני היסטוריית הגלישה, קובצי ×”-cookie, המטמון ועוד בהגדרות Chrome</translation>
<translation id="2650446666397867134">×œ× × ×™×ª×Ÿ לגשת לקובץ</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">הפעלה מחדש</translation>
<translation id="2803306138276472711">â€×œ×חרונה, 'גלישה בטוחה של Googleâ€' <ph name="BEGIN_LINK" />זיהתה תוכנה זדונית<ph name="END_LINK" /> ב×תר <ph name="SITE" />. ××ª×¨×™× ×©×‘×“×¨×š כלל × ×—×©×‘×™× ×œ×‘×˜×•×—×™× × ×“×‘×§×™× ×œ×¢×ª×™× ×‘×ª×•×›× ×” זדונית.</translation>
<translation id="2807052079800581569">â€×ž×™×§×•× תמונה על ציר Y</translation>
+<translation id="2820957248982571256">מתבצעת סריקה…</translation>
<translation id="2824775600643448204">שורת חיפוש וכתובות ×תרי×</translation>
<translation id="2826760142808435982">החיבור מוצפן ומ×ומת ב×מצעות <ph name="CIPHER" /> ומשתמש ב-<ph name="KX" /> כמנגנון להחלפת מפתחות.</translation>
<translation id="2835170189407361413">ניקוי הטופס</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Invite (Envelope)‎</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="2859806420264540918">ב×תר ×”×–×” מוצגות מודעות מפריעות ×ו מטעות.</translation>
+<translation id="287596039013813457">ידידותי</translation>
+<translation id="2876489322757410363">בחרת לצ×ת מהמצב ×”×נונימי כדי ×œ×©×œ× ×‘×מצעות ×פליקציה חיצונית. להמשיך?</translation>
<translation id="2878197950673342043">קיפול כרזה</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">×ž×™×§×•× ×—×œ×•× ×•×ª</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (Envelope)‎</translation>
<translation id="3060557858482803256">â€<ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, יש להקיש על Tab ו××– על Enter כדי להריץ בדיקת ×בטחה בהגדרות Chrome</translation>
<translation id="3061707000357573562">שירות תיקון</translation>
-<translation id="3064966200440839136">בחרת לצ×ת ממצב ×נונימי כדי ×œ×©×œ× ×‘×מצעות ×פליקציה חיצונית. להמשיך?</translation>
<translation id="306573536155379004">המשחק התחיל.</translation>
<translation id="3080254622891793721">גרפיקה</translation>
<translation id="3086579638707268289">הפעילות שלך ב×ינטרנט נמצ×ת במעקב</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">החשבון שלך מנוהל על-ידי <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">שחזור</translation>
<translation id="3162559335345991374">â€×™×™×ª×›×Ÿ שרשת ×”-Wi-Fi דורשת כניסה לדף ההתחברות שלה.</translation>
-<translation id="3167968892399408617">â€×“×¤×™× ×©×”×¦×’×ª בכרטיסיות מצב ×נונימי ×œ× ×™×™×©×ž×¨×• בהיסטוריית הדפדפן, ב×חסון קובצי ×”-Cookie ×ו בהיסטוריית ×”×—×™×¤×•×©×™× ×œ×חר שכל כרטיסיות המצב ×”×נונימי ייסגרו. ×§×‘×¦×™× ×©×”×•×¨×“×ª ×ו סימניות שיצרת יישמרו.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">××™</translation>
<translation id="3176929007561373547">â€×™×© לבדוק ×ת הגדרות שרת ×”-proxy ×ו לפנות למנהל הרשת
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">פרטי גרסה של המכשיר והדפדפן</translation>
<translation id="323107829343500871">יש להזין ×ת קוד ×”×ימות של הכרטיס <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">×–×”×” תמיד תוכן חשוב ב×תר ×–×”</translation>
+<translation id="3249845759089040423">מגניב</translation>
<translation id="3252266817569339921">צרפתית</translation>
<translation id="3266793032086590337">ערך (התנגשות)</translation>
<translation id="3268451620468152448">כרטיסיות פתוחות</translation>
<translation id="3270847123878663523">&amp;ביטול של שינוי סדר</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> רוצה להתחבר ×ל</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">×”×רגון שלך, <ph name="ENROLLMENT_DOMAIN" />, שלח מספר פרטי×, כמו הגדרות ומדיניות, ל××ª×¨×™× ×”×‘××™×.</translation>
<translation id="3282497668470633863">הוספה של ×”×©× ×”×ž×•×¤×™×¢ בכרטיס</translation>
@@ -655,6 +672,7 @@
<translation id="3428151540071562330">â€×חד ×ו יותר ממזהי ×”-URI של תבנית השרת DnsOverHttpsTemplates ××™× × ×—×•×§×™×™× ×•×œ× ×™×™×¢×©×” ×‘×”× ×©×™×ž×•×©.</translation>
<translation id="3431636764301398940">שמירת כרטיס זה במכשיר הנוכחי</translation>
<translation id="3432601291244612633">סגירת הדף</translation>
+<translation id="3435738964857648380">×בטחה</translation>
<translation id="3435896845095436175">הפעלה</translation>
<translation id="3438829137925142401">â€×©×™×ž×•×© בסיסמ×ות השמורות בחשבון Google שלך</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@
<translation id="3584299510153766161">שני × ×™×§×•×‘×™× ×‘×—×œ×§ התחתון</translation>
<translation id="3586931643579894722">הסתרת הפרטי×</translation>
<translation id="3587738293690942763">×מצעי</translation>
+<translation id="3590643883886679995">פרטי הכניסה ×™×וחסנו במכשיר ×”×–×” ×חרי היצי××” מהמצב ×”×נונימי.</translation>
+<translation id="359126217934908072">חודש/שנה:</translation>
<translation id="3592413004129370115">Italian (Envelope)‎</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{ניתן ל×פס ×ת הקבוצה מתי שרוצי×. הצטרפות לקבוצה חדשה נמשכת סביב ×™×•× ×חד.}=1{ניתן ל×פס ×ת הקבוצה מתי שרוצי×. הצטרפות לקבוצה חדשה נמשכת סביב ×™×•× ×חד.}two{ניתן ל×פס ×ת הקבוצה מתי שרוצי×. הצטרפות לקבוצה חדשה נמשכת סביב ×™×•×ž×™×™× ({NUM_DAYS}).}many{ניתן ל×פס ×ת הקבוצה מתי שרוצי×. הצטרפות לקבוצה חדשה נמשכת סביב {NUM_DAYS} ימי×.}other{ניתן ל×פס ×ת הקבוצה מתי שרוצי×. הצטרפות לקבוצה חדשה נמשכת סביב {NUM_DAYS} ימי×.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">×”×פליקציה נחסמה על ידי מנהל המערכת</translation>
<translation id="3608932978122581043">כיוון הזנה</translation>
@@ -706,13 +727,13 @@
<translation id="3615877443314183785">עליך להזין ת×ריך תפוגה חוקי</translation>
<translation id="36224234498066874">ניקוי נתוני גלישה…</translation>
<translation id="362276910939193118">כל ההיסטוריה</translation>
-<translation id="3625635938337243871">פרטי הכניסה ×™×וחסנו במכשיר ×”×–×” ×חרי היצי××” ממצב ×נונימי.</translation>
<translation id="3630155396527302611">×× ×”×™× ×›×‘×¨ רשומה כתוכנית המורשית לגשת לרשת, יש לנסות
להסיר ×ותה מהרשימה ולהוסיף ×ותה שוב.</translation>
<translation id="3630699740441428070">החיבור לרשת של המכשיר ×”×–×” הוגדר על ידי מנהלי המערכת, ועשויה להיות ×œ×”× ×פשרות לר×ות ×ת התנועה שלך ברשת, כולל ×”××ª×¨×™× ×©×‘×”× ×‘×™×§×¨×ª.</translation>
<translation id="3631244953324577188">מידע ביומטרי</translation>
<translation id="3633738897356909127">â€×”לחצן 'עדכון Chrome', יש להקיש על Enter כדי לעדכן ×ת דפדפן Chrome בהגדרות Chrome</translation>
<translation id="3634530185120165534">מגש 5</translation>
+<translation id="3637662659967048211">â€×©×ž×™×¨×” בחשבון Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">×פליקציה:</translation>
<translation id="3650584904733503804">×”×ימות בוצע בהצלחה</translation>
@@ -753,6 +774,7 @@
<translation id="3781428340399460090">ורוד בוהק</translation>
<translation id="3783418713923659662">מ×סטרק×רד</translation>
<translation id="3784372983762739446">â€×ž×›×©×™×¨×™ Bluetooth</translation>
+<translation id="3787675388804467730">מספר הכרטיס הווירטו×לי</translation>
<translation id="3787705759683870569">ת×ריך תפוגה: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">גודל 16</translation>
<translation id="3789841737615482174">התקנה</translation>
@@ -772,6 +794,7 @@
<translation id="3841184659773414994">â€×¨×›×™×‘×™ handler של קבצי×</translation>
<translation id="385051799172605136">חזרה</translation>
<translation id="3858027520442213535">עדכון הת×ריך והשעה</translation>
+<translation id="3881478300875776315">×× ×™ רוצה לר×ות פחות שורות</translation>
<translation id="3884278016824448484">מזהה מכשיר מתנגש</translation>
<translation id="3885155851504623709">פ×ריש</translation>
<translation id="388632593194507180">זוהה מעקב</translation>
@@ -797,6 +820,7 @@
<translation id="397105322502079400">מתבצע חישוב...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> חסו×</translation>
<translation id="3973357910713125165">â€×œ×—צן להרצת בדיקת ×בטחה ב-Chrome, יש להקיש על Enter כדי להריץ בדיקת ×בטחה בהגדרות Chrome</translation>
+<translation id="3986705137476756801">השבתת הכתוביות המיידיות נכון לעכשיו</translation>
<translation id="3987405730340719549">â€×œ×¤×™ ×מצעי ×”×בטחה של Chrome, ×”×תר ×”×–×” עשוי להיות מזויף ×ו ×תר שנועד להונ××”.
×× ×œ×“×¢×ª×š זו טעות, יש לעבור ×ל https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -891,13 +915,14 @@
<translation id="4275830172053184480">הפעלת המכשיר מחדש</translation>
<translation id="4277028893293644418">×יפוס סיסמה</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{â€×”כרטיס ×”×–×” נשמר בחשבון Google שלך}two{â€×”×›×¨×˜×™×¡×™× ×”×לה נשמרו בחשבון Google שלך}many{â€×”×›×¨×˜×™×¡×™× ×”×לה נשמרו בחשבון Google שלך}other{â€×”×›×¨×˜×™×¡×™× ×”×לה נשמרו בחשבון Google שלך}}</translation>
+<translation id="4287885627794386150">מת××™× ×œ×”×©×ª×ª×¤×•×ª בניסוי, ×œ× ×¤×¢×™×œ</translation>
<translation id="4297502707443874121">תמונה ממוזערת של הדף <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">הרחבה</translation>
<translation id="4300675098767811073">× ×™×§×•×‘×™× ×ž×¨×•×‘×™× ×‘×¦×“ ימין</translation>
<translation id="4302514097724775343">יש להקיש על הדינוז×ור כדי לשחק</translation>
<translation id="4302965934281694568">Chou3 (Envelope)‎</translation>
<translation id="4305666528087210886">×œ× × ×™×ª×Ÿ לגשת לקובץ</translation>
-<translation id="4305817255990598646">מעבר</translation>
+<translation id="4306529830550717874">לשמור ×ת הכתובת?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">חסומה (ברירת מחדל)</translation>
<translation id="4314815835985389558">ניהול הסנכרון</translation>
@@ -924,6 +949,7 @@
<translation id="4377125064752653719">ניסית להשיג ×ת <ph name="DOMAIN" />, ×ך ×”×ישור שהשרת הציג בוטל על ידי המנפיק שלו. פירוש הדבר ש×ין כל ×פשרות לתת ×מון ב×ישורי ×”×בטחה שהשרת הציג. ייתכן שהתקשורת שלך ×”×™× ×¢× ×ª×•×§×£.</translation>
<translation id="4378154925671717803">טלפון</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">כתוביות מיידיות</translation>
<translation id="4406896451731180161">תוצ×ות חיפוש</translation>
<translation id="4408413947728134509">â€×§×•×‘צי Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">â€×”זנת כרגע ×ת הסיסמה שלך ב×תר מטעה. ההמלצה של Chrome ×”×™× ×œ×¢×‘×•×¨ ×ל <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ו×ל ××ª×¨×™× ××—×¨×™× ×©×‘×”× ×”×¡×™×¡×ž×” הזו בשימוש ולשנות ×ותה עכשיו.</translation>
@@ -936,7 +962,6 @@
<translation id="4435702339979719576">Postcard)‎</translation>
<translation id="443673843213245140">â€×”שימוש בשרת Proxy הושבת, ×ך צוינה תצורת שרת Proxy מפורשת.</translation>
<translation id="4464826014807964867">××ª×¨×™× ×©×§×™×‘×œ×• ×¤×¨×˜×™× ×ž×”×רגון שלך</translation>
-<translation id="4466881336512663640">×”×©×™× ×•×™×™× ×‘×˜×•×¤×¡ יתבטלו. להמשיך?</translation>
<translation id="4476953670630786061">הטופס ×”×–×” ×œ× ×ž×ובטח. המילוי ×”×וטומטי נכבה.</translation>
<translation id="4477350412780666475">הטר×ק הב×</translation>
<translation id="4482953324121162758">×”×תר ×”×–×” ×œ× ×™×ª×•×¨×’×.</translation>
@@ -970,6 +995,7 @@
<translation id="4594403342090139922">&amp;ביטול מחיקה</translation>
<translation id="4597348597567598915">גודל 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)‎</translation>
+<translation id="4606870351894164739">מרשי×</translation>
<translation id="4628948037717959914">תמונה</translation>
<translation id="4631649115723685955">הק×שבק מקושר</translation>
<translation id="4636930964841734540">מידע</translation>
@@ -989,6 +1015,7 @@
<translation id="4691835149146451662">Architecture-A (Envelope)‎</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">צד</translation>
+<translation id="4702656508969495934">מוצגות כתוביות מיידיות, ניתן להשתמש במעבר בין החלונות כדי להתמקד</translation>
<translation id="4708268264240856090">החיבור נקטע</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131">â€<ph name="BEGIN_LINK" />מפעיל ×ת ×בחון הרשת של Windows<ph name="END_LINK" /></translation>
@@ -1002,6 +1029,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> – הצעת חיפוש</translation>
<translation id="4742407542027196863">ניהול סיסמ×ות…</translation>
<translation id="4744603770635761495">נתיב להפעלה</translation>
+<translation id="4749011317274908093">עברת למצב ×נונימי</translation>
<translation id="4750917950439032686">×”×¤×¨×˜×™× ×©×œ×š (כמו סיסמ×ות ×ו מספרי כרטיסי ×שר××™) × ×©×œ×—×™× ×œ×תר ×”×–×” במצב פרטי.</translation>
<translation id="4756388243121344051">&amp;היסטוריה</translation>
<translation id="4758311279753947758">הוספת ×¤×¨×˜×™× ×œ×™×¦×™×¨×ª קשר</translation>
@@ -1035,6 +1063,8 @@ Del</translation>
<translation id="4813512666221746211">שגי×ת רשת</translation>
<translation id="4816492930507672669">הת×מה לדף</translation>
<translation id="4819347708020428563">לערוך ×ת ההערות בתצוגת ברירת מחדל?</translation>
+<translation id="4825507807291741242">עוצמתי</translation>
+<translation id="4838327282952368871">חלומי</translation>
<translation id="484462545196658690">×וטומטי</translation>
<translation id="4850886885716139402">הצגה</translation>
<translation id="485316830061041779">גרמנית</translation>
@@ -1171,6 +1201,7 @@ Del</translation>
<translation id="5314967030527622926">יצירת חוברת</translation>
<translation id="5316812925700871227">סיבוב נגד כיוון השעון</translation>
<translation id="5317780077021120954">שמירה</translation>
+<translation id="5321288445143113935">גודל מקסימלי</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> מתוך <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">בחירת פרטי ×יש קשר</translation>
<translation id="5327248766486351172">ש×</translation>
@@ -1178,11 +1209,13 @@ Del</translation>
<translation id="5332219387342487447">שיטת משלוח</translation>
<translation id="5333022057423422993">â€Chrome ×יתר ×ת הסיסמה שבה השתמשת עכשיו בפרצה ב×בטחת מידע. כדי ל×בטח ×ת החשבונות שלך, מומלץ לבדוק ×ת הסיסמ×ות השמורות.</translation>
<translation id="5334013548165032829">יומני מערכת מפורטי×</translation>
+<translation id="5334145288572353250">לשמור ×ת הכתובת?</translation>
<translation id="5340250774223869109">×”×פליקציה חסומה</translation>
<translation id="534295439873310000">â€×ž×›×©×™×¨×™ NFC</translation>
<translation id="5344579389779391559">ייתכן שהדף ×”×–×” ינסה לדרוש ממך תשלו×</translation>
<translation id="5355557959165512791">נכון לעכשיו ××™ ×פשר לבקר ב×תר <ph name="SITE" /> מ×חר שה×ישור שלו בוטל. שגי×ות רשת ומתקפות הן בדרך כלל זמניות, כך שהדף ×”×–×” יחזור כנר××” לפעול מ×וחר יותר.</translation>
<translation id="536296301121032821">×חסון הגדרות המדיניות נכשל</translation>
+<translation id="5363309033720083897">יצי××” טורית ש×ושרה על ידי מנהל המערכת</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="5386426401304769735">â€×©×¨×©×¨×ª ×”××™×©×•×¨×™× ×©×œ ×”×תר ×”×–×” כוללת ×ישור ×©× ×—×ª× ×‘×מצעות SHA-1.</translation>
@@ -1191,6 +1224,7 @@ Del</translation>
<translation id="5398772614898833570">מודעות חסומות</translation>
<translation id="5400836586163650660">×פור</translation>
<translation id="540969355065856584">שרת ×–×” ×œ× ×”×¦×œ×™×— להוכיח ×©×”×•× <ph name="DOMAIN" />; ×ישור ×”×בטחה שלו ×ינו תקף כעת. הסיבה לכך עשויה להיות תצורה שגויה ×ו שתוקף מיירט ×ת החיבור שלך.</translation>
+<translation id="541143247543991491">ענן (כלל המערכת)</translation>
<translation id="541416427766103491">×ž×¢×¨×™× 4</translation>
<translation id="5421136146218899937">ניקוי נתוני גלישה...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> רוצה לשלוח לך הודעות</translation>
@@ -1204,6 +1238,7 @@ Del</translation>
<translation id="5455374756549232013">חותמת הזמן של המדיניות שגויה</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="5463625433003343978">מתבצע חיפוש מכשירי×…</translation>
<translation id="5469868506864199649">×יטלקית</translation>
<translation id="5470861586879999274">&amp;ביצוע מחדש של עריכה</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)‎</translation>
@@ -1254,7 +1289,6 @@ Del</translation>
<translation id="5624120631404540903">ניהול סיסמ×ות</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="563324245173044180">תוכן מטעה נחס×</translation>
<translation id="5644090287519800334">â€×”×–×–×” של תמונה בצד 1 על ציר X</translation>
@@ -1293,12 +1327,12 @@ Del</translation>
<translation id="5785756445106461925">כמו כן, דף ×–×” כולל מש××‘×™× × ×•×¡×¤×™× ×©××™× × ×ž×ובטחי×. ×’×•×¨×ž×™× ××—×¨×™× ×¢×œ×•×œ×™× ×œ×¨×ות ×ת המש××‘×™× ×”×לה במהלך העברת×, ותוקף עלול לשנות ××•×ª× ×‘×ופן שישנה ×ת מר××” הדף.</translation>
<translation id="5786044859038896871">×”×× ×‘×¨×¦×•× ×š ×œ×ž×œ× ×ת פרטי הכרטיס שלך?</translation>
<translation id="578633867165174378">â€Chrome ×יתר ×ת הסיסמה שבה השתמשת עכשיו בפרצה ב×בטחת מידע. מומלץ לשנות ×ת הסיסמה הזו מיד.</translation>
-<translation id="5798290721819630480">לבטל ×ת השינויי×?</translation>
<translation id="5803412860119678065">×”×× ×‘×¨×¦×•× ×š ×œ×ž×œ× ×ת פרטי הכרטיס <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">הרש×ות</translation>
<translation id="5804427196348435412">â€×©×™×ž×•×© בהתקני NFC</translation>
<translation id="5810442152076338065">החיבור שלך ×ל <ph name="DOMAIN" /> מוצפן ב×מצעות חבילת צופן מיושנת.</translation>
<translation id="5813119285467412249">&amp;ביצוע מחדש של הוספה</translation>
+<translation id="5817918615728894473">הת×מה</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{â€×”כרטיס ×”×–×” יחויב בזמן התשלו×, ×בל המספר ×”×מיתי שלו ×œ× ×™×©×•×ª×£ ×¢× ×”×תר ×”×–×”. כשכבת ×”×’× ×” נוספת, המערכת תיצור קוד ×ימות (CVC) חדש.}two{â€×”כרטיס שייבחר יחויב בזמן התשלו×, ×בל המספר ×”×מיתי שלו ×œ× ×™×©×•×ª×£ ×¢× ×”×תר ×”×–×”. כשכבת ×”×’× ×” נוספת, המערכת תיצור קוד ×ימות (CVC) חדש.}many{â€×”כרטיס שייבחר יחויב בזמן התשלו×, ×בל המספר ×”×מיתי שלו ×œ× ×™×©×•×ª×£ ×¢× ×”×תר ×”×–×”. כשכבת ×”×’× ×” נוספת, המערכת תיצור קוד ×ימות (CVC) חדש.}other{â€×”כרטיס שייבחר יחויב בזמן התשלו×, ×בל המספר ×”×מיתי שלו ×œ× ×™×©×•×ª×£ ×¢× ×”×תר ×”×–×”. כשכבת ×”×’× ×” נוספת, המערכת תיצור קוד ×ימות (CVC) חדש.}}</translation>
<translation id="5826507051599432481">â€×©× נפוץ (CN)</translation>
<translation id="5838278095973806738">×ין להזין מידע רגיש ב×תר ×”×–×” (כמו סיסמ×ות ×ו מספרי כרטיסי ×שר××™), מ×חר ×©×ª×•×§×¤×™× ×¢×œ×•×œ×™× ×œ×§×‘×œ ×ליו גישה.</translation>
@@ -1306,6 +1340,7 @@ Del</translation>
<translation id="5855253129151731373">â€×©× המ×רח של ×”×תר ×”×–×” נר××” דומה ל-<ph name="LOOKALIKE_DOMAIN" />. ×ª×•×§×¤×™× ×”×ž×—×§×™× ××ª×¨×™× ×œ×¤×¢×ž×™× ×ž×©×ª×ž×©×™× ×‘×©× ×”×“×•×ž×™×™×Ÿ של ×”×תר המקורי ×•×¢×•×©×™× ×‘×• ×©×™× ×•×™×™× ×§×œ×™× ×ž×וד כדי שיהיה קשה להבחין בהבדל.
×× ×œ×“×¢×ª×š זו טעות, יש לעבור ×ל https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">כבוי</translation>
<translation id="5862579898803147654">×ž×¢×¨×™× 8</translation>
<translation id="5863847714970149516">בדף ×”×‘× ×¢×©×•×™×” להיות דרישה לתשלו×</translation>
<translation id="5866257070973731571">הוספת מספר טלפון</translation>
@@ -1322,6 +1357,7 @@ Del</translation>
<translation id="5913377024445952699">×פשרות ×¦×™×œ×•× ×”×ž×¡×š מושהית</translation>
<translation id="59174027418879706">מופעל</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{×חד × ×ž×¦× ×‘×©×™×ž×•×©}two{×©× ×™×™× × ×ž×¦××™× ×‘×©×™×ž×•×©}many{# נמצ××™× ×‘×©×™×ž×•×©}other{# נמצ××™× ×‘×©×™×ž×•×©}}</translation>
<translation id="5921185718311485855">מופעל</translation>
<translation id="5921639886840618607">â€×œ×©×ž×•×¨ ×ת הכרטיס בחשבון Google?</translation>
<translation id="5922853866070715753">עוד רגע מסיימי×</translation>
@@ -1341,6 +1377,7 @@ Del</translation>
<translation id="5989320800837274978">â€×œ× צוינו שרתי Proxy ×§×‘×•×¢×™× ×•×œ× ×›×ª×•×‘×ª ×תר של סקריפט ‎.pac</translation>
<translation id="5992691462791905444">â€×§×™×¤×•×œ מסוג Engineering Z</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> תוצ×ות בשביל '<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">קל×סי</translation>
<translation id="6008122969617370890">â€×¡×™×“ור מ-N עד 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">בדיקת הסיסמ×ות</translation>
@@ -1362,6 +1399,7 @@ Del</translation>
<translation id="6045164183059402045">תבנית הצבה</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="6049004884579590341">יש ללחוץ לחיצה ×רוכה על |<ph name="ACCELERATOR" />| כדי לצ×ת ממסך מל×</translation>
<translation id="6049488691372270142">מסירת דף</translation>
<translation id="6051221802930200923">נכון לעכשיו ××™ ×פשר לבקר ב×תר <ph name="SITE" />, מ×חר שב×תר ×”×–×” נעשה שימוש בנעיצת ×ישורי×. שגי×ות רשת ומתקפות הן בדרך כלל זמניות, כך שהדף ×”×–×” יחזור כנר××” לפעול מ×וחר יותר.</translation>
<translation id="6051898664905071243">מספר דפי×:</translation>
@@ -1378,6 +1416,7 @@ Del</translation>
<translation id="610911394827799129">â€×™×™×ª×›×Ÿ שיהיה ×פשר לגשת ×œ×¡×•×’×™× ××—×¨×™× ×©×œ היסטוריית גלישה בחשבון Google בכתובת <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
<translation id="6116338172782435947">גישה ×ל טקסט ותמונות שהועתקו ללוח</translation>
<translation id="6120179357481664955">â€×ž×–×”×” UPI שלך זכור לך?</translation>
+<translation id="6123290840358279103">לצפייה בכרטיס הווירטו×לי</translation>
<translation id="6124432979022149706">â€×ž×—×‘×¨×™× ×©×œ Chrome Enterprise</translation>
<translation id="6146055958333702838">יש לבדוק ×ת ×”×›×‘×œ×™× ×•×œ×”×¤×¢×™×œ מחדש ×ת הנתבי×, ×”×ž×•×“×ž×™× ×•×©×ר התקני הרשת
×©×ž×©×ª×ž×©×™× ×‘×”×.</translation>
@@ -1414,6 +1453,7 @@ Del</translation>
<translation id="6289939620939689042">צבע הדף</translation>
<translation id="6290238015253830360">הצעות של מ××ž×¨×™× ×¢×‘×•×¨×š מופיעות ×›×ן</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">â€Google Assistant מופסקת ב-Chrome</translation>
<translation id="6305205051461490394">×œ× × ×™×ª×Ÿ לגשת ×ל <ph name="URL" />.</translation>
<translation id="6312113039770857350">דף ×”×ינטרנט ×ינו זמין</translation>
@@ -1439,6 +1479,7 @@ Del</translation>
<translation id="6390200185239044127">â€×§×™×¤×•×œ Z עד ×”×מצע</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">×פשרות ההדבקה מ-<ph name="ORIGIN_NAME" /> ×‘×ž×™×§×•× ×”×–×” חסומה בהת×× ×œ×ž×“×™× ×™×•×ª של מנהל המערכת</translation>
+<translation id="6398765197997659313">יצי××” ממסך מל×</translation>
<translation id="6401136357288658127">המדיניות הזו הוצ××” משימוש. במקומה יש להשתמש במדיניות <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">עריכת סימנייה</translation>
<translation id="6406765186087300643">C0 (Envelope)‎</translation>
@@ -1451,7 +1492,6 @@ Del</translation>
<translation id="6428450836711225518">×ימות מספר הטלפון שלך</translation>
<translation id="6433490469411711332">עריכת ×”×¤×¨×˜×™× ×œ×™×¦×™×¨×ª קשר</translation>
<translation id="6433595998831338502">×œ× × ×™×ª×Ÿ ×”×™×” להתחבר ×ל <ph name="HOST_NAME" />.</translation>
-<translation id="6434309073475700221">מחיקה</translation>
<translation id="6440503408713884761">המערכת מתעלמת מהפריט</translation>
<translation id="6443406338865242315">×ילו תוספות ויישומי פל×גין התקנת.</translation>
<translation id="6446163441502663861">Kahu (Envelope)‎</translation>
@@ -1494,6 +1534,7 @@ Del</translation>
<translation id="6624427990725312378">פרטי ×יש קשר</translation>
<translation id="6626291197371920147">הוספת מספר כרטיס חוקי</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> חיפוש</translation>
+<translation id="6630043285902923878">â€×ž×ª×‘צע ×יתור של התקני USB...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ניקוי</translation>
@@ -1509,6 +1550,7 @@ Del</translation>
<translation id="6671697161687535275">â€×”×× ×œ×”×¡×™×¨ מ-Chromium הצעות לטפסי×?</translation>
<translation id="6685834062052613830">יש לצ×ת ×•×œ×”×©×œ×™× ×ת ההגדרה</translation>
<translation id="6687335167692595844">גודל הגופן שהתבקש</translation>
+<translation id="6688743156324860098">עדכון…</translation>
<translation id="6689249931105087298">יחסי ×¢× ×“×—×™×¡×ª נקודות שחורות</translation>
<translation id="6689271823431384964">â€×ž×חר שנכנסת לחשבון, Chrome מציע לשמור ×ת ×”×›×¨×˜×™×¡×™× ×©×œ×š בחשבון Google. ×פשר לשנות ×ת ההתנהגות ×”×–×ת בהגדרות. ×©× ×‘×¢×œ הכרטיס מגיע מהחשבון שלך.</translation>
<translation id="6698381487523150993">נוצר:</translation>
@@ -1524,6 +1566,7 @@ Del</translation>
<translation id="6744009308914054259">בזמן ההמתנה לחיבור ×פשר לעבור ×ל 'הורדות' כדי ×œ×§×¨×•× ×ž××ž×¨×™× ×ופליין.</translation>
<translation id="6753269504797312559">ערך מדיניות</translation>
<translation id="6757797048963528358">המכשיר עבר למצב שינה.</translation>
+<translation id="6767985426384634228">לעדכן ×ת הכתובת?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)‎</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">סגול סיגלית</translation>
@@ -1546,6 +1589,7 @@ Del</translation>
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">â€Chrome יצר גרסה פשוטה של הדף ×”×–×” כדי להקל ×ת הקרי××” שלו. ×חזור הדף המקורי בוצע על-ידי Chrome ב×מצעות חיבור ×œ× ×ž×ובטח.</translation>
<translation id="6891596781022320156">רמת המדיניות ××™× ×” נתמכת.</translation>
+<translation id="6895143722905299846">מספר וירטו×לי:</translation>
<translation id="6895330447102777224">הכרטיס שלך מ×ושר</translation>
<translation id="6897140037006041989">User agent</translation>
<translation id="6898699227549475383">â€×רגון (O)</translation>
@@ -1581,10 +1625,10 @@ Del</translation>
<translation id="7004583254764674281">â€×›×“×™ ל×שר ×ת ×”×›×¨×˜×™×¡×™× ×ž×”×¨ יותר, ×פשר להשתמש ב-Windows Hello</translation>
<translation id="7006930604109697472">לשליחה בכל ×–×ת</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ההגדרות של שינוי הגודל</translation>
<translation id="7014741021609395734">המרחק מהתצוגה</translation>
<translation id="7016992613359344582">×”×ª×©×œ×•× ×¢×©×•×™ להיות חד-פעמי ×ו לכלול ×—×™×•×‘×™× ×—×•×–×¨×™× ×•×™×™×ª×›×Ÿ שהדרישה ×œ×ª×©×œ×•× ×œ× ×ª×•×¦×’ בצורה ברורה וחד-משמעית.</translation>
<translation id="7029809446516969842">סיסמ×ות</translation>
+<translation id="7030436163253143341">×”×ישור ×œ× ×ª×§×™×Ÿ</translation>
<translation id="7031646650991750659">â€×ילו ×פליקציות התקנת מ-Google Play.</translation>
<translation id="7050187094878475250">ניסית להגיע ×ל <ph name="DOMAIN" />, ×ך השרת הציג ×ישור שתקופת התוקף שלו ×רוכה מדי ולכן ×ינו מהימן.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{××™ ×פשר לשמור עכשיו ×ת הכרטיס ×”×–×”}two{××™ ×פשר לשמור עכשיו ×ת ×”×›×¨×˜×™×¡×™× ×”×לה}many{××™ ×פשר לשמור עכשיו ×ת ×”×›×¨×˜×™×¡×™× ×”×לה}other{××™ ×פשר לשמור עכשיו ×ת ×”×›×¨×˜×™×¡×™× ×”×לה}}</translation>
@@ -1654,12 +1698,14 @@ Del</translation>
<translation id="7300012071106347854">כחול קובלט</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">גבוה</translation>
+<translation id="7305756307268530424">התחלה ×יטית יותר</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">עזרה בחיבור</translation>
<translation id="7323804146520582233">הסתרת הקטע "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">ביטול עקב סשן חשבון מקומי במכשיר</translation>
<translation id="7333654844024768166">â€×”זנת כרגע ×ת הסיסמה שלך ב×תר מטעה. ההמלצה של Chromium ×”×™× ×œ×¢×‘×•×¨ ×ל <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ו×ל ××ª×¨×™× ××—×¨×™× ×©×‘×”× ×”×¡×™×¡×ž×” הזו בשימוש ולשנות ×ותה עכשיו.</translation>
<translation id="7334320624316649418">&amp;ביצוע מחדש של שינוי סדר</translation>
+<translation id="7337248890521463931">×× ×™ רוצה לר×ות יותר שורות</translation>
<translation id="7337706099755338005">×œ× ×–×ž×™×Ÿ בפלטפורמה שלך.</translation>
<translation id="733923710415886693">×ישור השרת ×œ× × ×—×©×£ דרך 'שקיפות ×ישורי×'.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1667,6 +1713,7 @@ Del</translation>
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">שורת פקודה </translation>
<translation id="7359588939039777303">מודעות חסומות.</translation>
+<translation id="7363096869660964304">×¢× ×–×ת, עדיין ×פשר לר×ות ×ותך. המעבר למצב ×נונימי ×œ× ×ž×¡×ª×™×¨ ×ת הגלישה שלך מהמעסיק, מספק ×”×ינטרנט ×ו מה××ª×¨×™× ×©××œ×™×”× × ×›× ×¡×ª.</translation>
<translation id="7365596969960773405">â€<ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, יש להקיש על Tab ו××– על Enter כדי להוסיף ולנהל כתובות בהגדרות Chrome</translation>
<translation id="7365849542400970216">רוצה שה×תר יקבל מידע לגבי השימוש שלך במכשיר?</translation>
<translation id="7372973238305370288">תוצ×ת חיפוש</translation>
@@ -1677,7 +1724,9 @@ Del</translation>
<translation id="7378594059915113390">פקדי מדיה</translation>
<translation id="7378627244592794276">ל×</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">×œ× ×¨×œ×•×•× ×˜×™</translation>
<translation id="7390545607259442187">×ישור הכרטיס</translation>
+<translation id="7392089738299859607">עדכון הכתובת</translation>
<translation id="7399802613464275309">בדיקת ×בטחה</translation>
<translation id="7400418766976504921">כתובת ×תר</translation>
<translation id="7403591733719184120">מכשיר <ph name="DEVICE_NAME" /> זה מנוהל</translation>
@@ -1692,6 +1741,7 @@ Del</translation>
&lt;li&gt;×¢×•×‘×¨×™× ×ל &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;מרכז העזרה של Chrome&lt;/a&gt; כדי ללמוד כיצד להסיר ×ת התוכנה מהמחשב
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">חביב</translation>
<translation id="7416351320495623771">ניהול סיסמ×ות…</translation>
<translation id="7419106976560586862">נתיב פרופיל</translation>
<translation id="7437289804838430631">הוספת ×¤×¨×˜×™× ×œ×™×¦×™×¨×ª קשר</translation>
@@ -1707,7 +1757,7 @@ Del</translation>
<translation id="7481312909269577407">קדימה</translation>
<translation id="7485870689360869515">×œ× × ×ž×¦×ו נתוני×.</translation>
<translation id="7495528107193238112">התוכן ×”×–×” חסו×. יש לפנות ×ל ×”×‘×¢×œ×™× ×©×œ ×”×תר כדי לפתור ×ת הבעיה.</translation>
-<translation id="7498234416455752244">המשך העריכה</translation>
+<translation id="7498193950643227031">שינוי הגודל עלול ×œ×’×¨×•× ×œ×”×ª× ×”×’×•×ª ×œ× ×¦×¤×•×™×”. עכשיו ×פשר להגביל ×ת ×”×פשרות לשינוי גודל של ×פליקציות ב<ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">â€×”זנת כרגע ×ת הסיסמה שלך ב×תר מטעה. ההמלצה של Chromium ×”×™× ×œ×‘×“×•×§ ב×ופן מיידי ×ת הסיסמ×ות השמורות של <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ו××ª×¨×™× ××—×¨×™× ×©×‘×”× ×”×¡×™×¡×ž×” הזו נמצ×ת בשימוש.</translation>
<translation id="7508255263130623398">מזהה המכשיר במדיניות שהוחזר ריק ×ו ש×ינו תו×× ×ת מזהה המכשיר הנוכחי</translation>
<translation id="7508870219247277067">ירוק ×בוקדו</translation>
@@ -1727,6 +1777,7 @@ Del</translation>
<translation id="7548892272833184391">פתרון שגי×ות חיבור</translation>
<translation id="7549584377607005141">דף ×ינטרנט ×–×” זקוק ×œ× ×ª×•× ×™× ×©×”×–× ×ª ×§×•×“× ×œ×›×Ÿ כדי ×©×”×•× ×™×•×¦×’ כר×וי. ניתן לשלוח שוב ×ת הנתוני×, ×ך פעולה זו ×ª×’×¨×•× ×œ×—×–×¨×” על כל פעולה שדף ×–×” ביצע בעבר.</translation>
<translation id="7550637293666041147">â€×©× המשתמש במכשיר ×•×©× ×”×ž×©×ª×ž×© ב-Chrome</translation>
+<translation id="755279583747225797">הניסוי הופעל</translation>
<translation id="7552846755917812628">×ולי ×”×˜×™×¤×™× ×”×לו יעזרו לך:</translation>
<translation id="7554475479213504905">לטעון מחדש ולהציג בכל ×–×ת?</translation>
<translation id="7554791636758816595">כרטיסייה חדשה</translation>
@@ -1745,7 +1796,6 @@ Del</translation>
<translation id="7610193165460212391">הערך מחוץ לטווח <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">תפוגה: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628">â€<ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, יש להקיש על Tab ו××– על Enter כדי להציג ולנהל סיסמ×ות בהגדרות Chrome</translation>
-<translation id="7615602087246926389">â€×™×© לך כבר × ×ª×•× ×™× ×©×”×•×¦×¤× ×• ב×מצעות גרסה ×חרת של סיסמת חשבון Google שלך. צריך להזין ×ותה למטה.</translation>
<translation id="7616645509853975347">â€×ž× ×”ל המערכת הפעיל ×ת Chrome Enterprise Connectors בדפדפן שלך. ×œ×ž×—×‘×¨×™× ×”×לה יש גישה ×ל חלק ×ž×”× ×ª×•× ×™× ×©×œ×š.</translation>
<translation id="7619838219691048931">גיליון סיו×</translation>
<translation id="762844065391966283">פריט מידע ×חד בכל פע×</translation>
@@ -1810,13 +1860,12 @@ Del</translation>
<translation id="782886543891417279">â€×™×™×ª×›×Ÿ שרשת ×”-Wi-Fi דורשת כניסה לדף ההתחברות שלה. (<ph name="WIFI_NAME" />).</translation>
<translation id="7836231406687464395">Postfix (Envelope)‎</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" />)}many{# ×פליקציות (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}other{# ×פליקציות (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">×¢× ×–×ת, עדיין ×פשר לר×ות ×ותך. המעבר למצב ×נונימי ×œ× ×ž×¡×ª×™×¨ ×ת הגלישה שלך מהמעסיק, מספק ×”×ינטרנט ×ו מה××ª×¨×™× ×©××œ×™×”× × ×›× ×¡×ª.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">לפתוח ×§×‘×¦×™× ×¢× ×©×™×•×›×™× ×œ×¡×•×’×™ קבצי×.</translation>
<translation id="7862185352068345852">לצ×ת מה×תר?</translation>
<translation id="7865448901209910068">המהירות הטובה ביותר</translation>
<translation id="7874263914261512992">â€×”זנת כרגע ×ת הסיסמה שלך ב×תר מטעה. ההמלצה של Chrome ×”×™× ×œ×‘×“×•×§ ב×ופן מיידי ×ת הסיסמ×ות השמורות של <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ו××ª×¨×™× ××—×¨×™× ×©×‘×”× ×”×¡×™×¡×ž×” הזו נמצ×ת בשימוש.</translation>
<translation id="7878562273885520351">ייתכן ש×בטחת הסיסמה שלך נפגעה</translation>
+<translation id="7880146494886811634">שמירת הכתובת</translation>
<translation id="7882421473871500483">חו×</translation>
<translation id="7887683347370398519">â€×™×© לבדוק ×ת ×”-CVC ולנסות שוב</translation>
<translation id="7887885240995164102">מעבר ×ל מצב 'תמונה בתוך תמונה'</translation>
@@ -1824,6 +1873,7 @@ Del</translation>
<translation id="7894280532028510793">×× ×”×יות תקין, <ph name="BEGIN_LINK" />יש לנסות להפעיל ×ת ×בחון הרשת<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)‎</translation>
<translation id="7931318309563332511">×œ× ×™×“×•×¢</translation>
+<translation id="793209273132572360">לעדכן ×ת הכתובת?</translation>
<translation id="7932579305932748336">ציפוי</translation>
<translation id="79338296614623784">עליך להזין מספר טלפון חוקי</translation>
<translation id="7934052535022478634">×”×ª×©×œ×•× ×”×•×©×œ×</translation>
@@ -1894,6 +1944,7 @@ Del</translation>
<translation id="8175796834047840627">â€Chrome מציע לשמור ×ת ×”×›×¨×˜×™×¡×™× ×©×œ×š בחשבון Google ×›×™ התחברת לחשבון. ×פשר לשנות ×ת ההתנהגות ×”×–×ת בהגדרות.</translation>
<translation id="8176440868214972690">מנהל המערכת של המכשיר ×”×–×” שלח מספר פרטי×, כמו הגדרות ומדיניות, ל××ª×¨×™× ×”×‘××™×.</translation>
<translation id="8184538546369750125">שימוש בברירת המחדל הכללית (×פשר)</translation>
+<translation id="8193086767630290324">פעולות שנעשו ×‘× ×ª×•× ×™× ×©×ž×¡×•×ž× ×™× ×›×¡×•×“×™×™×</translation>
<translation id="8194797478851900357">&amp;ביטול העברה</translation>
<translation id="8201077131113104583">כתובת ×תר ×œ× ×—×•×§×™×ª לעדכון עבור תוסף ×¢× ×”×ž×–×”×” "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">×¡×™×›×•× ×”×–×ž× ×”</translation>
@@ -1916,6 +1967,7 @@ Del</translation>
<translation id="8249296373107784235">ביטול</translation>
<translation id="8249320324621329438">בוצע ×חזור ×חרון:</translation>
<translation id="8253091569723639551">יש להזין כתובת לחיוב</translation>
+<translation id="8257387598443225809">×”×פליקציה הזו מיועדת לניידי×</translation>
<translation id="825929999321470778">הצגת כל הסיסמ×ות השמורות</translation>
<translation id="8261506727792406068">מחיקה</translation>
<translation id="8262952874573525464">הידוק קצוות בחלק התחתון</translation>
@@ -2039,7 +2091,6 @@ Del</translation>
<translation id="8719528812645237045">× ×™×§×•×‘×™× ×ž×¨×•×‘×™× ×‘×—×œ×§ העליון</translation>
<translation id="8725066075913043281">ניסיון חוזר</translation>
<translation id="8726549941689275341">גודל דף:</translation>
-<translation id="8728672262656704056">עברת למצב ×נונימי</translation>
<translation id="8730621377337864115">בוצע</translation>
<translation id="8731544501227493793">â€×”לחצן 'ניהול סיסמ×ות', יש להקיש על Enter כדי להציג ולנהל ×ת הסיסמ×ות בהגדרות Chrome</translation>
<translation id="8734529307927223492">ה-<ph name="DEVICE_TYPE" /> מנוהל על-ידי <ph name="MANAGER" /></translation>
@@ -2116,6 +2167,7 @@ Del</translation>
<translation id="9020542370529661692">הדף ×”×–×” ×ª×•×¨×’× ×œ<ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(×œ× ×—×•×§×™)</translation>
+<translation id="9030265603405983977">מונוכרומטי</translation>
<translation id="9035022520814077154">שגי×ת ×בטחה</translation>
<translation id="9038649477754266430">שימוש בשירות חיזוי כדי לטעון ×“×¤×™× ×ž×”×¨ יותר</translation>
<translation id="9039213469156557790">כמו כן, דף ×–×” כולל מש××‘×™× × ×•×¡×¤×™× ×©××™× × ×ž×ובטחי×. ×’×•×¨×ž×™× ××—×¨×™× ×¢×œ×•×œ×™× ×œ×¨×ות ×ת המש××‘×™× ×”×לה במהלך העברת×, ותוקף עלול לשנות ××•×ª× ×‘×ופן שישנה ×ת התנהגות הדף.</translation>
@@ -2139,6 +2191,7 @@ Del</translation>
<translation id="91108059142052966">בהת×× ×œ×ž×“×™× ×™×•×ª מנהל המערכת, שיתוף המסך ב×מצעות <ph name="APPLICATION_TITLE" /> מושבת כשמוצג תוכן סודי</translation>
<translation id="9114524666733003316">×ישור הכרטיס מתבצע...</translation>
<translation id="9114581008513152754">â€×”דפדפן ×”×–×” ×œ× ×ž× ×•×”×œ על ידי חברה ×ו ×רגון ×חר. ייתכן שהפעילות במכשיר ×”×–×” מנוהלת מחוץ ל-Chrome. <ph name="BEGIN_LINK" />מידע נוסף<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">מרענן</translation>
<translation id="9119042192571987207">הועלה</translation>
<translation id="9128016270925453879">המדיניות נטענה</translation>
<translation id="9128870381267983090">התחברות לרשת</translation>
@@ -2157,6 +2210,7 @@ Del</translation>
<translation id="9170848237812810038">&amp;ביטול</translation>
<translation id="9171296965991013597">לצ×ת מה×פליקציה?</translation>
<translation id="9173282814238175921">מסמך יחיד/גיליון חדש</translation>
+<translation id="9173995187295789444">â€×ž×ª×‘צע חיפוש של מכשירי Bluetooth...</translation>
<translation id="917450738466192189">×ישור השרת ×œ× ×—×•×§×™.</translation>
<translation id="9174917557437862841">â€×œ×—צן החלפת כרטיסיות, צריך להקיש על Enter כדי לעבור לכרטיסייה הזו</translation>
<translation id="9179703756951298733">â€× ×™×”ול ×”×ª×©×œ×•×ž×™× ×•×¤×¨×˜×™ כרטיס ×”×שר××™ בהגדרות Chrome</translation>
diff --git a/chromium/components/strings/components_strings_ja.xtb b/chromium/components/strings/components_strings_ja.xtb
index 1e38610500c..bf027e34c00 100644
--- a/chromium/components/strings/components_strings_ja.xtb
+++ b/chromium/components/strings/components_strings_ja.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã‚’オンã«ã™ã‚‹ã¨ã€Chrome ã¯ãƒ•ã‚©ãƒ¼ãƒ ã«è¿…速ã«å…¥åŠ›ã™ã‚‹ãŸã‚ã«ã€ã‚«ãƒ¼ãƒ‰æƒ…å ±ã®ã‚³ãƒ”ーをã“ã®ãƒ‡ãƒã‚¤ã‚¹ã«ä¿å­˜ã—ã¾ã™ã€‚</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> ã®æ¨©é™ã‚’é¸æŠžã—ã¾ã™</translation>
<translation id="1113869188872983271">é †åºå¤‰æ›´ã®å–り消ã—(&amp;U)</translation>
+<translation id="1123753900084781868">自動字幕起ã“ã—ã¯ç¾åœ¨ã”利用ã„ãŸã ã‘ã¾ã›ã‚“</translation>
<translation id="1125573121925420732">ウェブサイトã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£æ›´æ–°ä¸­ã¯è­¦å‘Šãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒè¡¨ç¤ºã•ã‚Œã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚ã“ã‚Œã¯ã¾ã‚‚ãªã改善ã•ã‚Œã‚‹äºˆå®šã§ã™ã€‚</translation>
<translation id="112840717907525620">ãƒãƒªã‚·ãƒ¼ キャッシュã¯æ­£å¸¸ã§ã™</translation>
<translation id="1130564665089811311">ページを翻訳ã™ã‚‹ãƒœã‚¿ãƒ³ã§ã™ã€‚Enter キーを押ã™ã¨ Google 翻訳を使用ã—ã¦ã“ã®ãƒšãƒ¼ã‚¸ã‚’翻訳ã—ã¾ã™</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">デãƒã‚¤ã‚¹å</translation>
<translation id="124116460088058876">ãã®ä»–ã®è¨€èªž</translation>
<translation id="1243027604378859286">作æˆè€…:</translation>
+<translation id="1246424317317450637">太字</translation>
<translation id="1250759482327835220">カードã€ãŠåå‰ã€è«‹æ±‚å…ˆä½æ‰€ã‚’ Google アカウントã«ä¿å­˜ã™ã‚‹ã¨ã€æ¬¡å›žã®ãŠæ”¯æ‰•ã„ãŒç°¡å˜ã«ãªã‚Šã¾ã™ã€‚</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />ã€<ph name="TYPE_2" />(åŒæœŸæ¸ˆã¿ï¼‰</translation>
<translation id="1256368399071562588">&lt;p&gt;ウェブサイトã«ã‚¢ã‚¯ã‚»ã‚¹ã—よã†ã¨ã—ã¦ã‚‚サイトãŒé–‹ã‹ãªã„å ´åˆã¯ã€ã¾ãšæ¬¡ã®è§£æ±ºæ–¹æ³•ã‚’è¡Œã£ã¦ã€ã‚¨ãƒ©ãƒ¼ãŒè§£æ¶ˆã•ã‚Œã‚‹ã‹ã”確èªãã ã•ã„。&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">パスワードを変更ã—ã¦ãã ã•ã„</translation>
<translation id="1484290072879560759">é…é€å…ˆä½æ‰€ã‚’é¸æŠž</translation>
<translation id="1492194039220927094">ãƒãƒªã‚·ãƒ¼ã®ãƒ—ッシュ:</translation>
+<translation id="1495677929897281669">タブã«æˆ»ã‚‹</translation>
<translation id="1501859676467574491">Google アカウントã«ä¿å­˜ã—ãŸã‚«ãƒ¼ãƒ‰ã‚’表示</translation>
<translation id="1507202001669085618">&lt;p&gt;インターãƒãƒƒãƒˆã«æŽ¥ç¶šã™ã‚‹ãŸã‚ã« Wi-Fi ãƒãƒ¼ã‚¿ãƒ«ã¸ã®ãƒ­ã‚°ã‚¤ãƒ³ãŒå¿…è¦ãªå ´åˆã¯ã€ã“ã®ã‚¨ãƒ©ãƒ¼ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚&lt;/p&gt;
&lt;p&gt;エラーを解決ã™ã‚‹ã«ã¯ã€é–‹ã“ã†ã¨ã—ã¦ã„るページ㧠[&lt;strong&gt;接続&lt;/strong&gt;] をクリックã—ã¾ã™ã€‚&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">ã“ã®ãƒšãƒ¼ã‚¸ã®å†…容</translation>
<translation id="153384715582417236">ç¾åœ¨ã€ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¯ã‚ã‚Šã¾ã›ã‚“</translation>
<translation id="1536390784834419204">ページを翻訳</translation>
+<translation id="1539840569003678498">レãƒãƒ¼ãƒˆã®é€ä¿¡æ—¥æ™‚:</translation>
<translation id="154408704832528245">é…é”å…ˆä½æ‰€ã‚’é¸æŠž</translation>
<translation id="1549470594296187301">ã“ã®æ©Ÿèƒ½ã‚’使用ã™ã‚‹ã«ã¯ JavaScript を有効ã«ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">短辺ã‹ã‚‰</translation>
<translation id="168693727862418163">ã“ã®ãƒãƒªã‚·ãƒ¼ã®å€¤ã¯ã€ã‚¹ã‚­ãƒ¼ãƒžã®æ¤œè¨¼ã§ã‚¨ãƒ©ãƒ¼ã¨ãªã£ãŸãŸã‚無視ã•ã‚Œã¾ã™ã€‚</translation>
<translation id="168841957122794586">サーãƒãƒ¼è¨¼æ˜Žæ›¸ã«è„†å¼±ãªæš—å·éµãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+<translation id="1696290444144917273">仮想カードã®è©³ç´°ã‚’表示ã—ã¾ã™</translation>
<translation id="1697532407822776718">設定ãŒå®Œäº†ã—ã¾ã—ãŸã€‚</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{ã“ã®ã‚µãƒ¼ãƒãƒ¼ãŒ <ph name="DOMAIN" /> ã§ã‚ã‚‹ã“ã¨ã‚’確èªã§ãã¾ã›ã‚“ã§ã—ãŸã€‚セキュリティ証明書ã¯ãŠãらã明日以é™ã«åˆ©ç”¨ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚原因ã¨ã—ã¦ã€è¨­å®šãŒä¸é©åˆ‡ã§ã‚ã‚‹ã‹ã€æ‚ªæ„ã®ã‚るユーザーãŒæŽ¥ç¶šã‚’妨害ã—ã¦ã„ã‚‹ã“ã¨ãŒè€ƒãˆã‚‰ã‚Œã¾ã™ã€‚}other{ã“ã®ã‚µãƒ¼ãƒãƒ¼ãŒ <ph name="DOMAIN" /> ã§ã‚ã‚‹ã“ã¨ã‚’確èªã§ãã¾ã›ã‚“ã§ã—ãŸã€‚セキュリティ証明書ã¯ãŠãらã # 日後ã‹ã‚‰åˆ©ç”¨ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚原因ã¨ã—ã¦ã€è¨­å®šãŒä¸é©åˆ‡ã§ã‚ã‚‹ã‹ã€æ‚ªæ„ã®ã‚るユーザーãŒæŽ¥ç¶šã‚’妨害ã—ã¦ã„ã‚‹ã“ã¨ãŒè€ƒãˆã‚‰ã‚Œã¾ã™ã€‚}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> ㌠<ph name="VALUE" /> ã«è¨­å®šã•ã‚Œã¦ã„ãªã„ãŸã‚無視ã•ã‚Œã¾ã—ãŸã€‚</translation>
<translation id="1712552549805331520"><ph name="URL" /> ã‹ã‚‰ã€ãƒ­ãƒ¼ã‚«ãƒ«ã®ãƒ‘ソコンã«ãƒ‡ãƒ¼ã‚¿ã‚’永続的ã«ä¿å­˜ã™ã‚‹è¨±å¯ã‚’求ã‚られã¦ã„ã¾ã™</translation>
<translation id="1713628304598226412">トレイ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">用紙å—ã‘ 3</translation>
<translation id="1718029547804390981">ドキュメントã®ã‚µã‚¤ã‚ºãŒå¤§ãã™ãŽã‚‹ãŸã‚注釈を追加ã§ãã¾ã›ã‚“</translation>
<translation id="1721424275792716183">* 必須欄ã§ã™</translation>
+<translation id="1727613060316725209">証明書ã¯æœ‰åŠ¹ã§ã™</translation>
<translation id="1727741090716970331">有効ãªã‚«ãƒ¼ãƒ‰ç•ªå·ã®è¿½åŠ </translation>
<translation id="1728677426644403582">ウェブページã®ã‚½ãƒ¼ã‚¹ã‚’表示ã—ã¦ã„ã¾ã™</translation>
<translation id="173080396488393970">ã“ã®ç¨®é¡žã®ã‚«ãƒ¼ãƒ‰ã¯ã”利用ã„ãŸã ã‘ã¾ã›ã‚“</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Windows ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯è¨ºæ–­ãƒ„ールを実行ã—ã¦ã¿ã¦ãã ã•ã„<ph name="END_LINK" />。</translation>
<translation id="1772163372082567643">アクセスã—ã¦ã„るサーãƒãƒ¼ <ph name="ORIGIN" /> ã§ã¯ã€ã‚µãƒ¼ãƒãƒ¼ã¸ã®ã™ã¹ã¦ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«ã‚ªãƒªã‚¸ãƒ³ ãƒãƒªã‚·ãƒ¼ã‚’é©ç”¨ã™ã‚‹ã“ã¨ã‚’求ã‚るヘッダーãŒè¨­å®šã•ã‚Œã¦ã„ã¾ã™ãŒã€ãƒ˜ãƒƒãƒ€ãƒ¼ã®å½¢å¼ãŒæ­£ã—ããªã„ãŸã‚ã€ãƒ–ラウザ㯠<ph name="SITE" /> ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’満ãŸã™ã“ã¨ãŒã§ãã¾ã›ã‚“。オリジン ãƒãƒªã‚·ãƒ¼ã¯ã€ã‚µã‚¤ãƒˆã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚„ãã®ä»–ã®ãƒ—ロパティを設定ã™ã‚‹ç›®çš„ã§ãƒ‘ブリッシャーãŒä½¿ç”¨ã™ã‚‹ã‚‚ã®ã§ã™ã€‚</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">åŒæœŸãƒ‘スフレーズを更新ã—ã¦ãã ã•ã„。</translation>
<translation id="1787142507584202372">最近開ã„ãŸã‚¿ãƒ–ãŒã“ã“ã«è¡¨ç¤ºã•ã‚Œã¾ã™</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" /> ã§ã™ã€‚複数ã®æ“作ãŒå¯èƒ½ã§ã€Tab キーを押ã™ã¨æ“作ãŒåˆ‡ã‚Šæ›¿ã‚ã‚Šã¾ã™</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">広告</translation>
<translation id="1919367280705858090">特定ã®ã‚¨ãƒ©ãƒ¼ メッセージã«é–¢ã™ã‚‹æƒ…å ±</translation>
<translation id="192020519938775529">{COUNT,plural, =0{ãªã—}=1{1 件ã®ã‚µã‚¤ãƒˆ}other{# 件ã®ã‚µã‚¤ãƒˆ}}</translation>
+<translation id="1924727005275031552">æ–°</translation>
<translation id="1945968466830820669">組織ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«ã‚¢ã‚¯ã‚»ã‚¹ã§ããªããªã£ãŸã‚Šã€å€‹äººæƒ…å ±ãŒç›—ã¾ã‚ŒãŸã‚Šã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚今ã™ãパスワードを変更ã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
<translation id="1947454675006758438">ステープル(å³ä¸Šï¼‰</translation>
<translation id="1958218078413065209">ãƒã‚¤ã‚¹ã‚³ã‚¢ã¯ <ph name="SCORE" /> ã§ã™ã€‚</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">トレイ 7</translation>
<translation id="204357726431741734">Google アカウントã«ä¿å­˜ã—ãŸãƒ‘スワードを使用ã™ã‚‹ã«ã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ãã ã•ã„</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" />ã®ãƒšãƒ¼ã‚¸ã¯ç¿»è¨³ã•ã‚Œã¾ã›ã‚“。</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{ã“ã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã‚’オンã«ã—ã¦ã€ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ãŒæœ‰åŠ¹ãªå ´åˆã€Chrome ã¯æœ€è¿‘ã®é–²è¦§ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティãŒæœ€ã‚‚é¡žä¼¼ã—ã¦ã„る「コホートã€ã¨ã„ã†å¤šäººæ•°ã®ã‚°ãƒ«ãƒ¼ãƒ—を特定ã—ã¾ã™ã€‚広告主ã¯ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å¯¾ã—ã¦åºƒå‘Šã‚’表示ã™ã‚‹ã‚ˆã†ã«è¨­å®šã§ãる一方ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®é–²è¦§ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティã¯ãƒ‡ãƒã‚¤ã‚¹ã«ä¿å­˜ã•ã‚Œã¦ãƒ—ライãƒã‚·ãƒ¼ãŒä¿ãŸã‚Œã¾ã™ã€‚ãªãŠã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¯æ¯Žæ—¥æ›´æ–°ã•ã‚Œã¾ã™ã€‚}=1{ã“ã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã‚’オンã«ã—ã¦ã€ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ãŒæœ‰åŠ¹ãªå ´åˆã€Chrome ã¯æœ€è¿‘ã®é–²è¦§ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティãŒæœ€ã‚‚é¡žä¼¼ã—ã¦ã„る「コホートã€ã¨ã„ã†å¤šäººæ•°ã®ã‚°ãƒ«ãƒ¼ãƒ—を特定ã—ã¾ã™ã€‚広告主ã¯ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å¯¾ã—ã¦åºƒå‘Šã‚’表示ã™ã‚‹ã‚ˆã†ã«è¨­å®šã§ãる一方ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®é–²è¦§ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティã¯ãƒ‡ãƒã‚¤ã‚¹ã«ä¿å­˜ã•ã‚Œã¦ãƒ—ライãƒã‚·ãƒ¼ãŒä¿ãŸã‚Œã¾ã™ã€‚ãªãŠã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¯æ¯Žæ—¥æ›´æ–°ã•ã‚Œã¾ã™ã€‚}other{ã“ã®ã‚³ãƒ³ãƒˆãƒ­ãƒ¼ãƒ«ã‚’オンã«ã—ã¦ã€ã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ãŒæœ‰åŠ¹ãªå ´åˆã€Chrome ã¯æœ€è¿‘ã®é–²è¦§ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティãŒæœ€ã‚‚é¡žä¼¼ã—ã¦ã„る「コホートã€ã¨ã„ã†å¤šäººæ•°ã®ã‚°ãƒ«ãƒ¼ãƒ—を特定ã—ã¾ã™ã€‚広告主ã¯ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«å¯¾ã—ã¦åºƒå‘Šã‚’表示ã™ã‚‹ã‚ˆã†ã«è¨­å®šã§ãる一方ã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®é–²è¦§ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティã¯ãƒ‡ãƒã‚¤ã‚¹ã«ä¿å­˜ã•ã‚Œã¦ãƒ—ライãƒã‚·ãƒ¼ãŒä¿ãŸã‚Œã¾ã™ã€‚ãªãŠã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—㯠{NUM_DAYS} æ—¥ã”ã¨ã«æ›´æ–°ã•ã‚Œã¾ã™ã€‚}}</translation>
<translation id="2053553514270667976">郵便番å·</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 件ã®å€™è£œ}other{# 件ã®å€™è£œ}}</translation>
<translation id="2071692954027939183">普段ã¯é€šçŸ¥ã‚’許å¯ã•ã‚Œãªã„よã†ã§ã™ã®ã§ã€é€šçŸ¥ã‚’自動的ã«ãƒ–ロックã—ã¾ã—ãŸ</translation>
<translation id="2079545284768500474">å…ƒã«æˆ»ã™</translation>
<translation id="20817612488360358">システム プロキシ設定を使用ã™ã‚‹ã‚ˆã†ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã™ãŒã€æ˜Žç¤ºçš„ãªãƒ—ロキシã®è¨­å®šã‚‚指定ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
<translation id="2082238445998314030">çµæžœ <ph name="TOTAL_RESULTS" /> 件中 <ph name="RESULT_NUMBER" /> 件目</translation>
+<translation id="2085876078937250610">ä¿å­˜â€¦</translation>
<translation id="2088086323192747268">åŒæœŸã‚’管ç†ã™ã‚‹ãƒœã‚¿ãƒ³ã§ã™ã€‚Enter キーを押ã—ã¦ã€Chrome ã®è¨­å®šã§åŒæœŸã™ã‚‹æƒ…報を管ç†ã—ã¾ã™</translation>
<translation id="2091887806945687916">音声</translation>
<translation id="2094505752054353250">ドメインãŒä¸€è‡´ã—ã¾ã›ã‚“</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> ã«ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードãŒå¿…è¦ã§ã™ã€‚</translation>
<translation id="2330137317877982892">「<ph name="CREDIT_CARD" />ã€ã®æœ‰åŠ¹æœŸé™ã¯ <ph name="EXPIRATION_DATE_ABBR" /> ã§ã™</translation>
<translation id="2337852623177822836">管ç†è€…ãŒæŒ‡å®šã™ã‚‹è¨­å®š</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ãŒãƒšã‚¢è¨­å®šã‚’è¦æ±‚ã—ã¦ã„ã¾ã™</translation>
<translation id="2344028582131185878">自動ダウンロード</translation>
<translation id="2346319942568447007">コピーã—ãŸç”»åƒ</translation>
<translation id="2354001756790975382">ãã®ä»–ã®ãƒ–ックマーク</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">ã“ã®ã‚µã‚¤ãƒˆã§ç›®ã«ã™ã‚‹ç”»åƒã¯ã€æ‚ªæ„ã®ã‚るユーザーã«ã‚ˆã£ã¦å·®ã—替ãˆã‚‰ã‚ŒãŸã‚‚ã®ã§ã‚ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
<translation id="2356070529366658676">確èªã™ã‚‹</translation>
<translation id="2357481397660644965">ã”使用ã®ãƒ‡ãƒã‚¤ã‚¹ã¯ <ph name="DEVICE_MANAGER" /> ã§ç®¡ç†ã•ã‚Œã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ <ph name="ACCOUNT_MANAGER" /> ã§ç®¡ç†ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{1 日以内}=1{1 日後}other{{NUM_DAYS} 日後}}</translation>
<translation id="2359629602545592467">複数</translation>
<translation id="2359808026110333948">続行</translation>
+<translation id="2359961752320758691">仮想カード番å·ã‚’é©ç”¨ã—ã¾ã—ãŸã€‚</translation>
<translation id="2367567093518048410">レベル</translation>
<translation id="2372464001869762664">確èªå¾Œã€Google アカウントã®ã‚«ãƒ¼ãƒ‰æƒ…å ±ãŒã“ã®ã‚µã‚¤ãƒˆã¨å…±æœ‰ã•ã‚Œã¾ã™ã€‚CVC 㯠Plex アカウントã®è©³ç´°ã§ç¢ºèªã§ãã¾ã™ã€‚</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">ã“ã®é…é€æ–¹æ³•ã¯ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。別ã®æ–¹æ³•ã‚’é¸æŠžã—ã¦ãã ã•ã„。</translation>
<translation id="2396249848217231973">削除ã®å–り消ã—(&amp;U)</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">æ—§</translation>
<translation id="2413528052993050574">ã“ã®ã‚µãƒ¼ãƒãƒ¼ãŒ <ph name="DOMAIN" /> ã§ã‚ã‚‹ã“ã¨ã‚’確èªã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã“ã®ã‚µãƒ¼ãƒãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£è¨¼æ˜Žæ›¸ã¯å–り消ã•ã‚Œã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚原因ã¨ã—ã¦ã¯ã€ä¸é©åˆ‡ãªè¨­å®šã‚„ã€æ‚ªæ„ã®ã‚るユーザーã«ã‚ˆã‚‹æŽ¥ç¶šå¦¨å®³ãŒè€ƒãˆã‚‰ã‚Œã¾ã™ã€‚</translation>
<translation id="2414886740292270097">æš—</translation>
<translation id="2438874542388153331">4 穴パンãƒï¼ˆå³ï¼‰</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">ステープル(å³ä¸‹ï¼‰</translation>
<translation id="2523886232349826891">カードã¯ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã®ã¿ã«ä¿å­˜ã•ã‚Œã¾ã™</translation>
<translation id="2524461107774643265">ãã®ä»–ã®æƒ…å ±ã®è¿½åŠ </translation>
-<translation id="2526590354069164005">デスクトップ</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{ã€ä»– 1 件}other{ã€ä»– # 件}}</translation>
<translation id="2536110899380797252">ä½æ‰€ã‚’追加</translation>
<translation id="2539524384386349900">検出</translation>
+<translation id="2541219929084442027">シークレット タブã§è¡¨ç¤ºã—ãŸãƒšãƒ¼ã‚¸ã®è¨˜éŒ²ã¯ã€ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆ タブをã™ã¹ã¦é–‰ã˜ãŸå¾Œã€ãƒ–ラウザã®å±¥æ­´ã€Cookie ã®ä¿å­˜å ´æ‰€ã€æ¤œç´¢å±¥æ­´ã‹ã‚‰å‰Šé™¤ã•ã‚Œã¾ã™ã€‚ãŸã ã—ã€ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚„作æˆã—ãŸãƒ–ックマークã¯ä¿å­˜ã•ã‚Œã¾ã™ã€‚</translation>
<translation id="2544644783021658368">1 ã¤ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ</translation>
<translation id="254947805923345898">ãƒãƒªã‚·ãƒ¼ã®å€¤ãŒç„¡åŠ¹ã§ã™ã€‚</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ã‹ã‚‰ç„¡åŠ¹ãªå¿œç­”ãŒé€ä¿¡ã•ã‚Œã¾ã—ãŸã€‚</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">Chrome ã®æœ€é«˜ãƒ¬ãƒ™ãƒ«ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã§ä¿è­·ã™ã‚‹ã«ã¯ã€<ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ä¿è­·å¼·åŒ–機能を有効ã«ã—ã¦ãã ã•ã„<ph name="END_ENHANCED_PROTECTION_LINK" />。</translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> ã®ã‚µãƒ¼ãƒãƒ¼ã® IP アドレスãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
<translation id="2639739919103226564">ステータス:</translation>
+<translation id="264810637653812429">対応デãƒã‚¤ã‚¹ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
<translation id="2649204054376361687"><ph name="COUNTRY" /> <ph name="CITY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" /> ã§ã™ã€‚Tab キーã€Enter キーã®é †ã«æŠ¼ã™ã¨ã€Chrome ã®è¨­å®šã§é–²è¦§å±¥æ­´ã€Cookieã€ã‚­ãƒ£ãƒƒã‚·ãƒ¥ãªã©ã‚’削除ã—ã¾ã™</translation>
<translation id="2650446666397867134">ファイルã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸ</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">å†èµ·å‹•</translation>
<translation id="2803306138276472711"><ph name="SITE" /> ã§ã¯æœ€è¿‘ã€Google セーフ ブラウジングã«ã‚ˆã‚Šã€<ph name="BEGIN_LINK" />ä¸æ­£ãªã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸ<ph name="END_LINK" />。通常ã¯å®‰å…¨ãªã‚¦ã‚§ãƒ–サイトã§ã‚ã£ã¦ã‚‚ã€ä¸æ­£ãªã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã«æ„ŸæŸ“ã—ã¦ã„ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚</translation>
<translation id="2807052079800581569">ç”»åƒã® Y 座標</translation>
+<translation id="2820957248982571256">スキャンã—ã¦ã„ã¾ã™â€¦</translation>
<translation id="2824775600643448204">アドレス検索ãƒãƒ¼</translation>
<translation id="2826760142808435982">接続㯠<ph name="CIPHER" /> を使用ã—ã¦æš—å·åŒ–ãŠã‚ˆã³èªè¨¼ã•ã‚Œã¦ãŠã‚Šã€<ph name="KX" /> ãŒéµäº¤æ›ãƒ¡ã‚«ãƒ‹ã‚ºãƒ ã¨ã—ã¦ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
<translation id="2835170189407361413">フォームをクリア</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">Invite(å°ç­’)</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="2859806420264540918">ã“ã®ã‚µã‚¤ãƒˆã§ã¯ç…©ã‚ã—ã„広告ã¾ãŸã¯èª¤è§£ã‚’æ‹›ã広告ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚</translation>
+<translation id="287596039013813457">フレンドリー</translation>
+<translation id="2876489322757410363">外部アプリケーションを経由ã—ãŸãŠæ”¯æ‰•ã„ã®å‡¦ç†ã«é€²ã‚€ãŸã‚ã€ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆ モードを解除ã—ã¾ã™ã€‚続行ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="2878197950673342043">ãƒã‚¹ã‚¿ãƒ¼æŠ˜ã‚Š</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ウィンドウã®é…ç½®</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">C9(å°ç­’)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" /> ã§ã™ã€‚Tab キーã€Enter キーã®é †ã«æŠ¼ã™ã¨ã€Chrome ã®è¨­å®šã§å®‰å…¨ç¢ºèªã‚’実行ã—ã¾ã™</translation>
<translation id="3061707000357573562">サービスã¸ã®ãƒ‘ッãƒã®é©ç”¨</translation>
-<translation id="3064966200440839136">外部アプリケーションを経由ã—ãŸãŠæ”¯æ‰•ã„ã®å‡¦ç†ã«é€²ã‚€ãŸã‚ã€ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆ モードを解除ã—ã¾ã™ã€‚続行ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="306573536155379004">ゲームを開始ã—ã¾ã—ãŸã€‚</translation>
<translation id="3080254622891793721">グラフィック</translation>
<translation id="3086579638707268289">ウェブã§ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティãŒç›£è¦–ã•ã‚Œã¦ã„ã¾ã™</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ <ph name="MANAGER" /> ã«ã‚ˆã£ã¦ç®¡ç†ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
<translation id="3157931365184549694">復元</translation>
<translation id="3162559335345991374">ã”利用㮠Wi-Fi ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã§ã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ãƒšãƒ¼ã‚¸ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒå¿…è¦ãªå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
-<translation id="3167968892399408617">シークレット タブã§è¡¨ç¤ºã—ãŸãƒšãƒ¼ã‚¸ã®è¨˜éŒ²ã¯ã€ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆ タブをã™ã¹ã¦é–‰ã˜ãŸå¾Œã€ãƒ–ラウザã®å±¥æ­´ã€Cookie ã®ä¿å­˜å ´æ‰€ã€æ¤œç´¢å±¥æ­´ã‹ã‚‰æ¶ˆåŽ»ã•ã‚Œã¾ã™ã€‚ãŸã ã—ã€ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ãŸãƒ•ã‚¡ã‚¤ãƒ«ã‚„作æˆã—ãŸãƒ–ックマークã¯ä¿å­˜ã•ã‚Œã¾ã™ã€‚</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">島</translation>
<translation id="3176929007561373547">プロキシã®è¨­å®šã‚’確èªã™ã‚‹ã‹ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ç®¡ç†è€…ã«å•ã„åˆã‚ã›ã¦ã€ãƒ—ロキシ サーãƒãƒ¼ãŒæ­£å¸¸ã«
@@ -593,10 +608,12 @@
<translation id="3229041911291329567">デãƒã‚¤ã‚¹ã¨ãƒ–ラウザã«é–¢ã™ã‚‹ãƒãƒ¼ã‚¸ãƒ§ãƒ³æƒ…å ±</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> 㮠CVC を入力</translation>
<translation id="3234666976984236645">ã“ã®ã‚µã‚¤ãƒˆã®é‡è¦ãªã‚³ãƒ³ãƒ†ãƒ³ãƒ„を常ã«æ¤œå‡º</translation>
+<translation id="3249845759089040423">グルービー</translation>
<translation id="3252266817569339921">フランス語</translation>
<translation id="3266793032086590337">値(競åˆï¼‰</translation>
<translation id="3268451620468152448">é–‹ã„ã¦ã„るタブ</translation>
<translation id="3270847123878663523">é †åºå¤‰æ›´ã®å–り消ã—(&amp;U)</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> ãŒæŽ¥ç¶šã‚’è¦æ±‚ã—ã¦ã„ã¾ã™</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">ã‚ãªãŸã®çµ„織(<ph name="ENROLLMENT_DOMAIN" />)ã¯æ¬¡ã®ã‚¦ã‚§ãƒ–サイトã«è¨­å®šã‚„ãƒãƒªã‚·ãƒ¼ãªã©ã®æƒ…報をé€ä¿¡ã™ã‚‹ã‚ˆã†è¨­å®šã—ã¦ã„ã¾ã™ã€‚</translation>
<translation id="3282497668470633863">å義人åを追加</translation>
@@ -649,6 +666,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates サーãƒãƒ¼ テンプレートã®ä¸€éƒ¨ã® URI ãŒç„¡åŠ¹ãªãŸã‚ã€ä½¿ç”¨ã•ã‚Œã¾ã›ã‚“。</translation>
<translation id="3431636764301398940">ã“ã®ã‚«ãƒ¼ãƒ‰æƒ…報をã“ã®ãƒ‡ãƒã‚¤ã‚¹ã«ä¿å­˜ã™ã‚‹</translation>
<translation id="3432601291244612633">ページを閉ã˜ã‚‹</translation>
+<translation id="3435738964857648380">セキュリティ</translation>
<translation id="3435896845095436175">有効ã«ã™ã‚‹</translation>
<translation id="3438829137925142401">Google アカウントã«ä¿å­˜ã—ãŸãƒ‘スワードを使用ã™ã‚‹</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -691,7 +709,10 @@
<translation id="3584299510153766161">2 穴パンãƒï¼ˆä¸‹ï¼‰</translation>
<translation id="3586931643579894722">詳細をéžè¡¨ç¤º</translation>
<translation id="3587738293690942763">中</translation>
+<translation id="3590643883886679995">ログインデータã¯ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆ モードã®çµ‚了後ã«ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã«ä¿å­˜ã•ã‚Œã¾ã™ã€‚</translation>
+<translation id="359126217934908072">月 / 年:</translation>
<translation id="3592413004129370115">Italian(å°ç­’)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{グループã¯ã„ã¤ã§ã‚‚リセットã§ãã¾ã™ã€‚æ–°ã—ã„グループã«åˆ†é¡žã•ã‚Œã‚‹ã¾ã§ã«ã¯ç´„ 1 æ—¥ã‹ã‹ã‚Šã¾ã™ã€‚}=1{グループã¯ã„ã¤ã§ã‚‚リセットã§ãã¾ã™ã€‚æ–°ã—ã„グループã«åˆ†é¡žã•ã‚Œã‚‹ã¾ã§ã«ã¯ç´„ 1 æ—¥ã‹ã‹ã‚Šã¾ã™ã€‚}other{グループã¯ã„ã¤ã§ã‚‚リセットã§ãã¾ã™ã€‚æ–°ã—ã„グループã«åˆ†é¡žã•ã‚Œã‚‹ã¾ã§ã«ã¯ {NUM_DAYS} æ—¥ã‹ã‹ã‚Šã¾ã™ã€‚}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />ã€<ph name="DOMAIN" />ã€<ph name="TIME" /></translation>
<translation id="3603507503523709">アプリケーションã¯ç®¡ç†è€…ã«ã‚ˆã£ã¦ãƒ–ロックã•ã‚Œã¦ã„ã¾ã™</translation>
<translation id="3608932978122581043">給紙方å‘</translation>
@@ -700,13 +721,13 @@
<translation id="3615877443314183785">有効期é™ï¼ˆæ—¥ï¼‰ã‚’入力ã—ã¦ãã ã•ã„</translation>
<translation id="36224234498066874">閲覧履歴データを削除...</translation>
<translation id="362276910939193118">全履歴を表示</translation>
-<translation id="3625635938337243871">ログインデータã¯ã‚·ãƒ¼ã‚¯ãƒ¬ãƒƒãƒˆ モードã®çµ‚了後ã«ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã«ä¿å­˜ã•ã‚Œã¾ã™ã€‚</translation>
<translation id="3630155396527302611">ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã•ã‚ŒãŸãƒ—ログラムã¨ã—ã¦æ—¢ã«è¡¨ç¤ºã•ã‚Œã¦ã„ã‚‹å ´åˆã¯ã€
ã„ã£ãŸã‚“リストã‹ã‚‰å‰Šé™¤ã—ã€ã‚‚ã†ä¸€åº¦è¿½åŠ ã—ã¦ã¿ã¦ãã ã•ã„。</translation>
<translation id="3630699740441428070">ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã®ç®¡ç†è€…ãŒè¨­å®šã—ãŸãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šã«ã‚ˆã£ã¦ã€ã‚¢ã‚¯ã‚»ã‚¹å…ˆã®ã‚¦ã‚§ãƒ–サイトをå«ã‚€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ トラフィックを管ç†è€…ãŒæŠŠæ¡ã§ãるよã†ã«ãªã£ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
<translation id="3631244953324577188">生体èªè¨¼ã‚·ã‚¹ãƒ†ãƒ </translation>
<translation id="3633738897356909127">Chrome ã‚’æ›´æ–°ã™ã‚‹ãƒœã‚¿ãƒ³ã§ã™ã€‚Enter キーを押ã™ã¨ Chrome ã®è¨­å®šã§ Chrome ã‚’æ›´æ–°ã—ã¾ã™</translation>
<translation id="3634530185120165534">トレイ 5</translation>
+<translation id="3637662659967048211">Google アカウントã«ä¿å­˜</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">アプリケーション:</translation>
<translation id="3650584904733503804">検証ãŒæ­£å¸¸ã«å®Œäº†ã—ã¾ã—ãŸ</translation>
@@ -747,6 +768,7 @@
<translation id="3781428340399460090">ホットピンク</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetoothデãƒã‚¤ã‚¹</translation>
+<translation id="3787675388804467730">仮想カード番å·</translation>
<translation id="3787705759683870569">有効期é™: <ph name="EXPIRATION_MONTH" /> / <ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">サイズ 16</translation>
<translation id="3789841737615482174">インストール</translation>
@@ -766,6 +788,7 @@
<translation id="3841184659773414994">ファイル ãƒãƒ³ãƒ‰ãƒ©</translation>
<translation id="385051799172605136">戻る</translation>
<translation id="3858027520442213535">日時を更新</translation>
+<translation id="3881478300875776315">表示ã™ã‚‹è¡Œæ•°ã‚’減らã™</translation>
<translation id="3884278016824448484">競åˆã™ã‚‹ãƒ‡ãƒã‚¤ã‚¹è­˜åˆ¥å­ã§ã™</translation>
<translation id="3885155851504623709">教区</translation>
<translation id="388632593194507180">監視ãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸ</translation>
@@ -791,6 +814,7 @@
<translation id="397105322502079400">計算ã—ã¦ã„ã¾ã™...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ã¯ãƒ–ロックã•ã‚Œã¦ã„ã¾ã™</translation>
<translation id="3973357910713125165">Chrome ã®å®‰å…¨ç¢ºèªã‚’実行ã™ã‚‹ãƒœã‚¿ãƒ³ã§ã™ã€‚Enter キーを押ã™ã¨ Chrome ã®è¨­å®šã§å®‰å…¨ç¢ºèªã‚’実行ã—ã¾ã™</translation>
+<translation id="3986705137476756801">今回ã®ã¿è‡ªå‹•å­—幕起ã“ã—をオフã«ã™ã‚‹</translation>
<translation id="3987405730340719549">å½ã®ã‚µã‚¤ãƒˆã¾ãŸã¯ä¸æ­£ãªã‚µã‚¤ãƒˆã®å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚
ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒèª¤ã£ã¦è¡¨ç¤ºã•ã‚ŒãŸã¨æ€ã‚れる場åˆã¯ã€https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals ã‹ã‚‰å•é¡Œã‚’報告ã—ã¦ãã ã•ã„。</translation>
@@ -882,13 +906,14 @@
<translation id="4275830172053184480">デãƒã‚¤ã‚¹ã®å†èµ·å‹•</translation>
<translation id="4277028893293644418">パスワードをå†è¨­å®š</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ã“ã®ã‚«ãƒ¼ãƒ‰ã‚’ Google アカウントã«ä¿å­˜ã—ã¾ã—ãŸ}other{ã“れらã®ã‚«ãƒ¼ãƒ‰ã‚’ Google アカウントã«ä¿å­˜ã—ã¾ã—ãŸ}}</translation>
+<translation id="4287885627794386150">試用版を使用ã§ãã¾ã™ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã›ã‚“</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> ページã®ã‚µãƒ ãƒã‚¤ãƒ«</translation>
<translation id="42981349822642051">展開</translation>
<translation id="4300675098767811073">多穴パンãƒï¼ˆå³ï¼‰</translation>
<translation id="4302514097724775343">プレイã™ã‚‹ã«ã¯æ竜をタップã—ã¦ãã ã•ã„</translation>
<translation id="4302965934281694568">é•·3(å°ç­’)</translation>
<translation id="4305666528087210886">ファイルã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“ã§ã—ãŸ</translation>
-<translation id="4305817255990598646">切り替ãˆ</translation>
+<translation id="4306529830550717874">ä½æ‰€ã‚’ä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">ブロック(デフォルト)</translation>
<translation id="4314815835985389558">åŒæœŸã®ç®¡ç†</translation>
@@ -915,6 +940,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" /> ã«ã‚¢ã‚¯ã‚»ã‚¹ã—よã†ã¨ã—ã¾ã—ãŸãŒã€ã‚µãƒ¼ãƒãƒ¼ã‹ã‚‰æ示ã•ã‚ŒãŸè¨¼æ˜Žæ›¸ã¯ç™ºè¡Œå…ƒã«ã‚ˆã‚Šå–り消ã•ã‚Œã¦ã„ã¾ã™ã€‚ã“ã‚Œã¯ã€ã‚µãƒ¼ãƒãƒ¼ã‹ã‚‰æ示ã•ã‚ŒãŸã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£èªè¨¼æƒ…å ±ãŒä¿¡é ¼ã§ããªã„ã“ã¨ã‚’示ã—ã¦ãŠã‚Šã€æ‚ªæ„ã®ã‚るユーザーã¨é€šä¿¡ã—よã†ã¨ã—ã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
<translation id="4378154925671717803">電話</translation>
<translation id="4390472908992056574">ブリム</translation>
+<translation id="4406883609789734330">自動字幕起ã“ã—</translation>
<translation id="4406896451731180161">検索çµæžœ</translation>
<translation id="4408413947728134509">Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">å½ã®ã‚µã‚¤ãƒˆã§ãƒ‘スワードを入力ã—ã¾ã—ãŸã€‚<ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" />ã€<ph name="WEBSITE_3" /> ã®ã»ã‹ã€ã“ã®ãƒ‘スワードを使用ã—ã¦ã„るサイトã§ã€ãƒ‘スワードを今ã™ã変更ã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
@@ -927,7 +953,6 @@
<translation id="4435702339979719576">ãƒã‚¹ãƒˆã‚«ãƒ¼ãƒ‰</translation>
<translation id="443673843213245140">プロキシã®ä½¿ç”¨ã¯ç„¡åŠ¹ã§ã™ãŒã€ãƒ—ロキシã®è¨­å®šãŒæ˜Žç¤ºçš„ã«æŒ‡å®šã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
<translation id="4464826014807964867">組織ã®æƒ…報を使用ã—ã¦ã„るウェブサイト</translation>
-<translation id="4466881336512663640">フォームã®å¤‰æ›´å†…容ã¯ç ´æ£„ã•ã‚Œã¾ã™ã€‚続行ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ</translation>
<translation id="4476953670630786061">ã“ã®ãƒ•ã‚©ãƒ¼ãƒ ã¯å®‰å…¨ã§ã¯ãªã„ãŸã‚ã€è‡ªå‹•å…¥åŠ›ã‚’オフã«ã—ã¾ã—ãŸã€‚</translation>
<translation id="4477350412780666475">次ã®æ›²</translation>
<translation id="4482953324121162758">ã“ã®ã‚µã‚¤ãƒˆã¯ç¿»è¨³ã•ã‚Œã¾ã›ã‚“。</translation>
@@ -961,6 +986,7 @@
<translation id="4594403342090139922">削除ã®å–り消ã—(&amp;U)</translation>
<translation id="4597348597567598915">サイズ 8</translation>
<translation id="4600854749408232102">C6 / C5(å°ç­’)</translation>
+<translation id="4606870351894164739">インパクト</translation>
<translation id="4628948037717959914">写真</translation>
<translation id="4631649115723685955">キャッシュãƒãƒƒã‚¯ã‚’リンクã—ã¾ã—ãŸ</translation>
<translation id="4636930964841734540">情報</translation>
@@ -980,6 +1006,7 @@
<translation id="4691835149146451662">Architecture-A(å°ç­’)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">å´é¢</translation>
+<translation id="4702656508969495934">自動字幕起ã“ã—ãŒè¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚ç”»é¢åˆ‡ã‚Šæ›¿ãˆãƒœã‚¿ãƒ³ã§ãƒ•ã‚©ãƒ¼ã‚«ã‚¹ã§ãã¾ã™</translation>
<translation id="4708268264240856090">接続ãŒä¸­æ–­ã•ã‚Œã¾ã—ãŸ</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯è¨ºæ–­ãƒ„ールを実行ã™ã‚‹<ph name="END_LINK" /></translation>
@@ -993,6 +1020,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> ã®æ¤œç´¢å€™è£œ</translation>
<translation id="4742407542027196863">パスワードを管ç†â€¦</translation>
<translation id="4744603770635761495">実行ファイルã®ãƒ‘ス</translation>
+<translation id="4749011317274908093">シークレット モードã§ã™</translation>
<translation id="4750917950439032686">ãŠå®¢æ§˜ãŒã“ã®ã‚µã‚¤ãƒˆã«é€ä¿¡ã—ãŸæƒ…報(パスワードã€ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆ カード番å·ãªã©ï¼‰ãŒç¬¬ä¸‰è€…ã«è¦‹ã‚‰ã‚Œã‚‹ã“ã¨ã¯ã‚ã‚Šã¾ã›ã‚“。</translation>
<translation id="4756388243121344051">履歴(&amp;H)</translation>
<translation id="4758311279753947758">連絡先情報を追加</translation>
@@ -1022,6 +1050,8 @@
<translation id="4813512666221746211">ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ エラー</translation>
<translation id="4816492930507672669">ページサイズã«åˆã‚ã›ã‚‹</translation>
<translation id="4819347708020428563">デフォルト表示ã§ãƒ¡ãƒ¢ã‚’編集ã—ã¾ã™ã‹ï¼Ÿ</translation>
+<translation id="4825507807291741242">パワフル</translation>
+<translation id="4838327282952368871">ドリーミー</translation>
<translation id="484462545196658690">自動</translation>
<translation id="4850886885716139402">表示</translation>
<translation id="485316830061041779">ドイツ語</translation>
@@ -1158,18 +1188,21 @@
<translation id="5314967030527622926">ブックレット メーカー</translation>
<translation id="5316812925700871227">å時計回りã«å›žè»¢</translation>
<translation id="5317780077021120954">ä¿å­˜</translation>
+<translation id="5321288445143113935">最大化</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />ã€<ph name="MATCH_POSITION" />/<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">連絡作情報をé¸æŠž</translation>
<translation id="5327248766486351172">åå‰</translation>
<translation id="5329858041417644019">ã”使用ã®ãƒ–ラウザã¯ç®¡ç†ã•ã‚Œã¦ã„ã¾ã›ã‚“</translation>
<translation id="5332219387342487447">é…é€æ–¹æ³•</translation>
-<translation id="5333022057423422993">最近使用ã—ãŸãƒ‘スワードãŒãƒ‡ãƒ¼ã‚¿ä¾µå®³ã§æ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚アカウントをä¿è­·ã™ã‚‹ãŸã‚ã€ä¿å­˜ã—ãŸãƒ‘スワードを確èªã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
+<translation id="5333022057423422993">ãŸã£ãŸä»Šä½¿ç”¨ã—ãŸãƒ‘スワードãŒãƒ‡ãƒ¼ã‚¿ä¾µå®³ã§æ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚アカウントをä¿è­·ã™ã‚‹ãŸã‚ã€ä¿å­˜ã—ãŸãƒ‘スワードを確èªã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
<translation id="5334013548165032829">詳細ãªã‚·ã‚¹ãƒ†ãƒ ãƒ­ã‚°</translation>
+<translation id="5334145288572353250">ä½æ‰€ã‚’ä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="5340250774223869109">アプリケーションãŒãƒ–ロックã•ã‚Œã¾ã—ãŸ</translation>
<translation id="534295439873310000">NFC デãƒã‚¤ã‚¹</translation>
<translation id="5344579389779391559">ã“ã®ãƒšãƒ¼ã‚¸ã§ã¯èª²é‡‘ã•ã‚Œã‚‹æã‚ŒãŒã‚ã‚Šã¾ã™</translation>
<translation id="5355557959165512791"><ph name="SITE" /> ã¯è¨¼æ˜Žæ›¸ãŒå¤±åŠ¹ã—ã¦ã„ã‚‹ãŸã‚ã€ç¾åœ¨ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。通常ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ エラーやãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®æ”»æ’ƒã¯ä¸€æ™‚çš„ãªã‚‚ã®ã§ã™ã€‚ã—ã°ã‚‰ãã™ã‚‹ã¨ãƒšãƒ¼ã‚¸ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚</translation>
<translation id="536296301121032821">ãƒãƒªã‚·ãƒ¼è¨­å®šã‚’ä¿å­˜ã§ãã¾ã›ã‚“ã§ã—ãŸ</translation>
+<translation id="5363309033720083897">管ç†è€…ãŒè¨±å¯ã—ãŸã‚·ãƒªã‚¢ãƒ«ãƒãƒ¼ãƒˆ</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="5386426401304769735">ã“ã®ã‚µã‚¤ãƒˆã®è¨¼æ˜Žæ›¸ãƒã‚§ãƒ¼ãƒ³ã«ã¯ SHA-1 を使ã£ã¦ç½²åã•ã‚ŒãŸè¨¼æ˜Žæ›¸ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚</translation>
@@ -1178,6 +1211,7 @@
<translation id="5398772614898833570">広告ãŒãƒ–ロックã•ã‚Œã¾ã—ãŸ</translation>
<translation id="5400836586163650660">グレー</translation>
<translation id="540969355065856584">ã“ã®ã‚µãƒ¼ãƒãƒ¼ãŒ <ph name="DOMAIN" /> ã§ã‚ã‚‹ã“ã¨ã‚’確èªã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ã“ã®ã‚µãƒ¼ãƒãƒ¼ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£è¨¼æ˜Žæ›¸ã¯ç¾åœ¨æœ‰åŠ¹ã§ã¯ã‚ã‚Šã¾ã›ã‚“。設定ãŒä¸é©åˆ‡ã‹ã€æ‚ªæ„ã®ã‚るユーザーã«ã‚ˆã£ã¦æŽ¥ç¶šãŒå¦¨å®³ã•ã‚Œã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
+<translation id="541143247543991491">クラウド(システム全体)</translation>
<translation id="541416427766103491">スタッカー 4</translation>
<translation id="5421136146218899937">閲覧履歴データを削除...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> ãŒé€šçŸ¥ã‚’é€ä¿¡ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚</translation>
@@ -1191,6 +1225,7 @@
<translation id="5455374756549232013">ãƒãƒªã‚·ãƒ¼ã®ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—ãŒä¸é©åˆ‡ã§ã™</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" /> 件)}other{<ph name="CONTACT_PREVIEW" />(他 <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> 件)}}</translation>
+<translation id="5463625433003343978">デãƒã‚¤ã‚¹ã‚’検出ã—ã¦ã„ã¾ã™...</translation>
<translation id="5469868506864199649">イタリア語</translation>
<translation id="5470861586879999274">編集ã®ã‚„ã‚Šç›´ã—(&amp;R)</translation>
<translation id="5478437291406423475">B6 / C4(å°ç­’)</translation>
@@ -1240,7 +1275,6 @@
<translation id="5624120631404540903">パスワードを管ç†</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="563324245173044180">ä¸æ­£ã®å¯èƒ½æ€§ãŒã‚るコンテンツãŒãƒ–ロックã•ã‚Œã¾ã—ãŸã€‚</translation>
<translation id="5644090287519800334">1 é¢ã®ç”»åƒã® X 軸移動</translation>
@@ -1278,13 +1312,13 @@
<translation id="5784606427469807560">カードã®ç¢ºèªä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚インターãƒãƒƒãƒˆæŽ¥ç¶šã‚’確èªã—ã¦ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。</translation>
<translation id="5785756445106461925">加ãˆã¦ã€ã“ã®ãƒšãƒ¼ã‚¸ã«ã¯å®‰å…¨ã§ãªã„ä»–ã®ãƒªã‚½ãƒ¼ã‚¹ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚ã“ã®ãƒªã‚½ãƒ¼ã‚¹ã¯é€ä¿¡ä¸­ã«ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‹ã‚‰è¦‹ã‚‰ã‚Œã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€æ‚ªæ„ã®ã‚るユーザーã«ã‚ˆã£ã¦æ”¹å¤‰ã•ã‚Œãƒšãƒ¼ã‚¸ã®è¦‹ãŸç›®ãŒå¤‰ã‚ã‚‹å¯èƒ½æ€§ã‚‚ã‚ã‚Šã¾ã™ã€‚</translation>
<translation id="5786044859038896871">カード情報を入力ã—ã¾ã™ã‹ï¼Ÿ</translation>
-<translation id="578633867165174378">最近使用ã—ãŸãƒ‘スワードãŒãƒ‡ãƒ¼ã‚¿ä¾µå®³ã§æ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚ã“ã®ãƒ‘スワードを今ã™ã変更ã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
-<translation id="5798290721819630480">変更を破棄ã—ã¾ã™ã‹ï¼Ÿ</translation>
+<translation id="578633867165174378">ãŸã£ãŸä»Šä½¿ç”¨ã—ãŸãƒ‘スワードãŒãƒ‡ãƒ¼ã‚¿ä¾µå®³ã§æ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚ã“ã®ãƒ‘スワードを今ã™ã変更ã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" /> を入力ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="5804241973901381774">権é™</translation>
<translation id="5804427196348435412">NFC デãƒã‚¤ã‚¹ã®ä½¿ç”¨</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> ã¸ã®æŽ¥ç¶šã¯å¤ã„æš—å·ã‚¹ã‚¤ãƒ¼ãƒˆã«ã‚ˆã‚Šæš—å·åŒ–ã•ã‚Œã¦ã„ã¾ã™ã€‚</translation>
<translation id="5813119285467412249">追加ã®ã‚„ã‚Šç›´ã—(&amp;R)</translation>
+<translation id="5817918615728894473">ペア設定</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ãŠæ”¯æ‰•ã„ã®éš›ã¯ã“ã®ã‚«ãƒ¼ãƒ‰ã«è«‹æ±‚ãŒè¡Œã‚ã‚Œã¾ã™ãŒã€ã‚«ãƒ¼ãƒ‰ç•ªå·ã¯ã“ã®ã‚µã‚¤ãƒˆã¨å…±æœ‰ã•ã‚Œã¾ã›ã‚“。追加ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã¨ã—ã¦ã€ä¸€æ™‚ CVC コードãŒç”Ÿæˆã•ã‚Œã¾ã™ã€‚}other{ãŠæ”¯æ‰•ã„ã®éš›ã¯é¸æŠžã—ãŸã‚«ãƒ¼ãƒ‰ã«è«‹æ±‚ãŒè¡Œã‚ã‚Œã¾ã™ãŒã€ã‚«ãƒ¼ãƒ‰ç•ªå·ã¯ã“ã®ã‚µã‚¤ãƒˆã¨å…±æœ‰ã•ã‚Œã¾ã›ã‚“。追加ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã¨ã—ã¦ã€ä¸€æ™‚ CVC コードãŒç”Ÿæˆã•ã‚Œã¾ã™ã€‚}}</translation>
<translation id="5826507051599432481">一般å(CN)</translation>
<translation id="5838278095973806738">ã“ã®ã‚µã‚¤ãƒˆã§ã¯æ©Ÿå¯†æƒ…報(パスワードã€ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆ カードãªã©ï¼‰ã‚’入力ã—ãªã„ã§ãã ã•ã„。悪æ„ã®ã‚るユーザーã«æƒ…å ±ãŒç›—ã¾ã‚Œã‚‹æã‚ŒãŒã‚ã‚Šã¾ã™ã€‚</translation>
@@ -1292,6 +1326,7 @@
<translation id="5855253129151731373">ã“ã®ã‚µã‚¤ãƒˆã®ãƒ›ã‚¹ãƒˆå㯠<ph name="LOOKALIKE_DOMAIN" /> ã¨ä¼¼ã¦ã„るよã†ã§ã™ã€‚ä¸æ­£ãªãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒãƒ‰ãƒ¡ã‚¤ãƒ³åã®ã”ã一部を一目ã§ã¯ã‚ã‹ã‚‰ãªã„よã†ã«æ”¹å¤‰ã—ã¦ã‚µã‚¤ãƒˆã‚’å½è£…ã™ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
ã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒèª¤ã£ã¦è¡¨ç¤ºã•ã‚ŒãŸã¨æ€ã‚れる場åˆã¯ã€https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals ã‹ã‚‰å•é¡Œã‚’報告ã—ã¦ãã ã•ã„。</translation>
+<translation id="5860033963881614850">オフ</translation>
<translation id="5862579898803147654">スタッカー 8</translation>
<translation id="5863847714970149516">表示ã—よã†ã¨ã—ã¦ã„るページã§ã¯èª²é‡‘ã•ã‚Œã‚‹æã‚ŒãŒã‚ã‚Šã¾ã™</translation>
<translation id="5866257070973731571">電話番å·ã®è¿½åŠ </translation>
@@ -1308,6 +1343,7 @@
<translation id="5913377024445952699">ç”»é¢ã‚­ãƒ£ãƒ—ãƒãƒ£ãŒä¸€æ™‚åœæ­¢ã•ã‚Œã¾ã—ãŸ</translation>
<translation id="59174027418879706">有効</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 個ãŒä½¿ç”¨ä¸­}other{# 個ãŒä½¿ç”¨ä¸­}}</translation>
<translation id="5921185718311485855">オン</translation>
<translation id="5921639886840618607">カードを Google アカウントã«ä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="5922853866070715753">ã»ã¼å®Œäº†ã§ã™</translation>
@@ -1327,6 +1363,7 @@
<translation id="5989320800837274978">固定プロキシ サーãƒãƒ¼ã¨ .pac スクリプト URL ã®ã©ã¡ã‚‰ã‚‚指定ã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
<translation id="5992691462791905444">工学 Z 折り</translation>
<translation id="6000758707621254961">「<ph name="SEARCH_TEXT" />ã€ã«å¯¾ã™ã‚‹ <ph name="RESULT_COUNT" /> 件ã®æ¤œç´¢çµæžœ</translation>
+<translation id="6006484371116297560">クラシック</translation>
<translation id="6008122969617370890">N~1 ã®é †</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">パスワードã®ç¢ºèª</translation>
@@ -1348,6 +1385,7 @@
<translation id="6045164183059402045">é¢ä»˜ã‘テンプレート</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="6049004884579590341">全画é¢è¡¨ç¤ºã‚’終了ã™ã‚‹ã«ã¯ |<ph name="ACCELERATOR" />| キーを押ã—続ã‘ã¾ã™</translation>
<translation id="6049488691372270142">排紙</translation>
<translation id="6051221802930200923"><ph name="SITE" /> ã§ã¯è¨¼æ˜Žæ›¸ãƒ”ンニングãŒä½¿ç”¨ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€ç¾åœ¨ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。通常ã€ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ エラーやãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®æ”»æ’ƒã¯ä¸€æ™‚çš„ãªã‚‚ã®ã§ã™ã€‚ã—ã°ã‚‰ãã™ã‚‹ã¨ãƒšãƒ¼ã‚¸ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãるよã†ã«ãªã‚Šã¾ã™ã€‚</translation>
<translation id="6051898664905071243">ページ数:</translation>
@@ -1364,6 +1402,7 @@
<translation id="610911394827799129">ãŠä½¿ã„ã® Google アカウント㮠<ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> ã«ã€ä»–ã®å½¢å¼ã®é–²è¦§å±¥æ­´ãŒè¨˜éŒ²ã•ã‚Œã¦ã„ã‚‹å ´åˆãŒã‚ã‚Šã¾ã™</translation>
<translation id="6116338172782435947">クリップボードã«ã‚³ãƒ”ーã—ãŸãƒ†ã‚­ã‚¹ãƒˆã‚„ç”»åƒã¸ã®ã‚¢ã‚¯ã‚»ã‚¹</translation>
<translation id="6120179357481664955">UPI ID ã‚’ä¿å­˜ã—ã¾ã™ã‹ï¼Ÿ</translation>
+<translation id="6123290840358279103">仮想カードを表示</translation>
<translation id="6124432979022149706">Chrome Enterprise Connector</translation>
<translation id="6146055958333702838">ケーブルを確èªã—ã€ä½¿ç”¨ã—ã¦ã„ã‚‹ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ デãƒã‚¤ã‚¹ï¼ˆãƒ«ãƒ¼ã‚¿ãƒ¼ã€ãƒ¢ãƒ‡ãƒ ãªã©ï¼‰ã‚’
å†èµ·å‹•ã—ã¦ãã ã•ã„。</translation>
@@ -1400,6 +1439,7 @@
<translation id="6289939620939689042">ページã®è‰²</translation>
<translation id="6290238015253830360">ãŠã™ã™ã‚ã®è¨˜äº‹ãŒã“ã“ã«è¡¨ç¤ºã•ã‚Œã¾ã™</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome ã® Google アシスタントをåœæ­¢ã—ã¦ã„ã¾ã™</translation>
<translation id="6305205051461490394"><ph name="URL" /> ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。</translation>
<translation id="6312113039770857350">ウェブページã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ä¸å¯</translation>
@@ -1425,6 +1465,7 @@
<translation id="6390200185239044127">2 ã¤æŠ˜ã‚Šç›´è§’ Z 折り</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> ã‹ã‚‰ã“ã®å ´æ‰€ã¸ã®è²¼ã‚Šä»˜ã‘ã¯ç®¡ç†è€…ãŒè¨­å®šã—ãŸãƒãƒªã‚·ãƒ¼ã«ã‚ˆã£ã¦ãƒ–ロックã•ã‚Œã¦ã„ã¾ã™</translation>
+<translation id="6398765197997659313">全画é¢è¡¨ç¤ºã‚’終了</translation>
<translation id="6401136357288658127">ã“ã®ãƒãƒªã‚·ãƒ¼ã¯ã‚µãƒãƒ¼ãƒˆãŒçµ‚了ã—ãŸãŸã‚ã€ä»£ã‚ã‚Šã« <ph name="NEW_POLICY" /> ãƒãƒªã‚·ãƒ¼ã‚’使用ã—ã¦ãã ã•ã„。</translation>
<translation id="6404511346730675251">ブックマークを編集</translation>
<translation id="6406765186087300643">C0(å°ç­’)</translation>
@@ -1437,7 +1478,6 @@
<translation id="6428450836711225518">電話番å·ã®ç¢ºèª</translation>
<translation id="6433490469411711332">連絡先情報ã®ç·¨é›†</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ã§æŽ¥ç¶šãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚</translation>
-<translation id="6434309073475700221">破棄</translation>
<translation id="6440503408713884761">除外ã•ã‚Œã¾ã—ãŸ</translation>
<translation id="6443406338865242315">インストールã—ãŸæ‹¡å¼µæ©Ÿèƒ½ã¨ãƒ—ラグイン</translation>
<translation id="6446163441502663861">Kahu(å°ç­’)</translation>
@@ -1468,7 +1508,7 @@
<translation id="6579630537141957243">MIDI デãƒã‚¤ã‚¹ã‚’使用ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="6579990219486187401">ライトピンク</translation>
<translation id="6583674473685352014">B6(å°ç­’)</translation>
-<translation id="6587182488465657433">最近使用ã—ãŸãƒ‘スワードãŒãƒ‡ãƒ¼ã‚¿ä¾µå®³ã§æ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚アカウントをä¿è­·ã™ã‚‹ãŸã‚ã€ã“ã®ãƒ‘スワードを今ã™ã変更ã—ã€ä¿å­˜ã—ãŸãƒ‘スワードを確èªã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
+<translation id="6587182488465657433">ãŸã£ãŸä»Šä½¿ç”¨ã—ãŸãƒ‘スワードãŒãƒ‡ãƒ¼ã‚¿ä¾µå®³ã§æ¤œå‡ºã•ã‚Œã¾ã—ãŸã€‚アカウントをä¿è­·ã™ã‚‹ãŸã‚ã€ã“ã®ãƒ‘スワードを今ã™ã変更ã—ã€ä¿å­˜ã—ãŸãƒ‘スワードを確èªã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
<translation id="6587923378399804057">コピーã—ãŸãƒªãƒ³ã‚¯</translation>
<translation id="6591833882275308647">ã”使用㮠<ph name="DEVICE_TYPE" /> ã¯ç®¡ç†ã•ã‚Œã¦ã„ã¾ã›ã‚“</translation>
<translation id="6592952801936330159">サイトã®è¨­å®šã‚’管ç†ã™ã‚‹ãƒœã‚¿ãƒ³ã§ã™ã€‚Enter キーを押ã—ã¦ã€Chrome ã®è¨­å®šã§ã™ã¹ã¦ã®ã‚µã‚¤ãƒˆã«ä¿å­˜ã•ã‚Œã¦ã„る権é™ã¨ãƒ‡ãƒ¼ã‚¿ã‚’管ç†ã—ã¾ã™</translation>
@@ -1480,6 +1520,7 @@
<translation id="6624427990725312378">連絡先情報</translation>
<translation id="6626291197371920147">有効ãªã‚«ãƒ¼ãƒ‰ç•ªå·ã‚’追加</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> 検索</translation>
+<translation id="6630043285902923878">USB デãƒã‚¤ã‚¹ã‚’検出ã—ã¦ã„ã¾ã™...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">削除</translation>
@@ -1495,6 +1536,7 @@
<translation id="6671697161687535275">Chromium ã‹ã‚‰å€™è£œã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ</translation>
<translation id="6685834062052613830">ログアウトã—ã¦è¨­å®šã‚’完了ã—ã¦ãã ã•ã„</translation>
<translation id="6687335167692595844">リクエストã•ã‚ŒãŸãƒ•ã‚©ãƒ³ãƒˆã‚µã‚¤ã‚º</translation>
+<translation id="6688743156324860098">更新…</translation>
<translation id="6689249931105087298">相対的(黒点ã®è£œæ­£ã‚り)</translation>
<translation id="6689271823431384964">ログインã—ã¦ã„ã‚‹å ´åˆã¯ã€ãã® Google アカウントã«ã‚«ãƒ¼ãƒ‰ã‚’ä¿å­˜ã§ãã¾ã™ã€‚ã“ã®å‹•ä½œã¯è¨­å®šã§å¤‰æ›´ã§ãã¾ã™ã€‚カードå義人ã¯ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‹ã‚‰å–å¾—ã•ã‚Œã¾ã™ã€‚</translation>
<translation id="6698381487523150993">作æˆ:</translation>
@@ -1510,6 +1552,7 @@
<translation id="6744009308914054259">接続ã™ã‚‹ã¾ã§ã®é–“ã€[ダウンロード] ã«ç§»å‹•ã—ã¦ã‚ªãƒ•ãƒ©ã‚¤ãƒ³ã§è¨˜äº‹ã‚’読むã“ã¨ãŒã§ãã¾ã™ã€‚</translation>
<translation id="6753269504797312559">ãƒãƒªã‚·ãƒ¼ã®å€¤</translation>
<translation id="6757797048963528358">デãƒã‚¤ã‚¹ãŒã‚¹ãƒªãƒ¼ãƒ—状態ã§ã™ã€‚</translation>
+<translation id="6767985426384634228">ä½æ‰€ã‚’æ›´æ–°ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="6768213884286397650">ã¯ãŒã</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ãƒã‚¤ã‚ªãƒ¬ãƒƒãƒˆ</translation>
@@ -1532,6 +1575,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">ページを見やã™ãã™ã‚‹ãŸã‚ã€Chrome ã«ã‚ˆã£ã¦ç°¡æ˜“表示ã•ã‚Œã¦ã„ã¾ã™ã€‚Chrome ã«ã‚ˆã‚‹å…ƒã®ãƒšãƒ¼ã‚¸ã®å–å¾—ã¯ã€ä¿è­·ã•ã‚Œã¦ã„ãªã„接続を介ã—ã¦è¡Œã‚ã‚Œã¾ã—ãŸã€‚</translation>
<translation id="6891596781022320156">ãƒãƒªã‚·ãƒ¼ãƒ¬ãƒ™ãƒ«ãŒã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
+<translation id="6895143722905299846">仮想番å·:</translation>
<translation id="6895330447102777224">カードを確èªã—ã¾ã—ãŸ</translation>
<translation id="6897140037006041989">ユーザー エージェント</translation>
<translation id="6898699227549475383">組織(O)</translation>
@@ -1567,10 +1611,10 @@
<translation id="7004583254764674281">Windows Hello を使用ã—ã¦ã‚«ãƒ¼ãƒ‰ã‚’ã™ã°ã‚„ã確èªã™ã‚‹</translation>
<translation id="7006930604109697472">ã“ã®ã¾ã¾é€ä¿¡</translation>
<translation id="7012363358306927923">中国銀è¯</translation>
-<translation id="7012404007611495949">サイズ変更ã®è¨­å®š</translation>
<translation id="7014741021609395734">ズームレベル</translation>
<translation id="7016992613359344582">料金ã®è«‹æ±‚㯠1 回é™ã‚Šã®å ´åˆã‚‚ç¹°ã‚Šè¿”ã—è¡Œã‚れる場åˆã‚‚ã‚ã‚Šã€èª²é‡‘ã•ã‚ŒãŸã‹ã©ã†ã‹ã‚ã‹ã‚‰ãªã„ã“ã¨ã‚‚ã‚ã‚Šã¾ã™ã€‚</translation>
<translation id="7029809446516969842">パスワード</translation>
+<translation id="7030436163253143341">証明書ãŒç„¡åŠ¹ã§ã™</translation>
<translation id="7031646650991750659">インストールã—㟠Google Play アプリ</translation>
<translation id="7050187094878475250"><ph name="DOMAIN" /> ã«ã‚¢ã‚¯ã‚»ã‚¹ã—よã†ã¨ã—ã¾ã—ãŸãŒã€ã‚µãƒ¼ãƒãƒ¼ã«æ示ã•ã‚ŒãŸè¨¼æ˜Žæ›¸ã®æœ‰åŠ¹æœŸé™ãŒé•·ã™ãŽã¦ä¿¡é ¼æ€§ã‚’確èªã§ãã¾ã›ã‚“ã§ã—ãŸã€‚</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ç¾åœ¨ã€ã“ã®ã‚«ãƒ¼ãƒ‰ã¯ä¿å­˜ã§ãã¾ã›ã‚“}other{ç¾åœ¨ã€ã“れらã®ã‚«ãƒ¼ãƒ‰ã¯ä¿å­˜ã§ãã¾ã›ã‚“}}</translation>
@@ -1640,12 +1684,14 @@
<translation id="7300012071106347854">コãƒãƒ«ãƒˆãƒ–ルー</translation>
<translation id="7302712225291570345">「<ph name="TEXT" />ã€</translation>
<translation id="7304030187361489308">高ã‚</translation>
+<translation id="7305756307268530424">低速ã‹ã‚‰é–‹å§‹</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">接続ã«é–¢ã™ã‚‹ãƒ˜ãƒ«ãƒ—</translation>
<translation id="7323804146520582233">「<ph name="SECTION" />ã€ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã‚’éžè¡¨ç¤ºã«ã™ã‚‹</translation>
<translation id="733354035281974745">デãƒã‚¤ã‚¹ã®ãƒ­ãƒ¼ã‚«ãƒ« アカウントã®ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰</translation>
<translation id="7333654844024768166">å½ã®ã‚µã‚¤ãƒˆã§ãƒ‘スワードを入力ã—ã¾ã—ãŸã€‚<ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" />ã€<ph name="WEBSITE_3" /> ã®ã»ã‹ã€ã“ã®ãƒ‘スワードを使用ã—ã¦ã„るサイトã§ã€ãƒ‘スワードを今ã™ã変更ã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
<translation id="7334320624316649418">é †åºå¤‰æ›´ã®ã‚„ã‚Šç›´ã—(&amp;R)</translation>
+<translation id="7337248890521463931">表示ã™ã‚‹è¡Œæ•°ã‚’増やã™</translation>
<translation id="7337706099755338005">ç¾åœ¨ã®ãƒ—ラットフォームã§ã¯ã”利用ã„ãŸã ã‘ã¾ã›ã‚“。</translation>
<translation id="733923710415886693">サーãƒãƒ¼ã®è¨¼æ˜Žæ›¸ã¯ã€è¨¼æ˜Žæ›¸ã®é€æ˜Žæ€§ãƒãƒªã‚·ãƒ¼ã‚’介ã—ã¦å…¬é–‹ã•ã‚Œã¦ã„ã¾ã›ã‚“。</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1653,6 +1699,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">コマンドライン</translation>
<translation id="7359588939039777303">広告ãŒãƒ–ロックã•ã‚Œã¾ã—ãŸã€‚</translation>
+<translation id="7363096869660964304">ã‚らゆる場所ã«è¨˜éŒ²ãŒä¸€åˆ‡æ®‹ã‚‰ãªã„ã‚ã‘ã§ã¯ã‚ã‚Šã¾ã›ã‚“。シークレット モードを使ã£ã¦ã‚‚ã€é›‡ç”¨ä¸»ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆ サービス プロãƒã‚¤ãƒ€ã€è¨ªå•å…ˆã®ã‚¦ã‚§ãƒ–サイトã«é–²è¦§å†…容ãŒçŸ¥ã‚‰ã‚Œã‚‹å¯èƒ½æ€§ã¯ã‚ã‚Šã¾ã™ã€‚</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" /> ã§ã™ã€‚Tab キーã€Enter キーã®é †ã«æŠ¼ã—ã¦ã€Chrome ã®è¨­å®šã§ä½æ‰€ã‚’追加ã€ç®¡ç†ã—ã¾ã™</translation>
<translation id="7365849542400970216">デãƒã‚¤ã‚¹ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ–状態を知らã›ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="7372973238305370288">検索çµæžœ</translation>
@@ -1663,7 +1710,9 @@
<translation id="7378594059915113390">メディアã®æ“作</translation>
<translation id="7378627244592794276">ã„ã„ãˆ</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">対象外ã§ã™</translation>
<translation id="7390545607259442187">カードã®ç¢ºèª</translation>
+<translation id="7392089738299859607">ä½æ‰€ã‚’æ›´æ–°</translation>
<translation id="7399802613464275309">安全確èª</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">ã”使用㮠<ph name="DEVICE_NAME" /> ã¯ç®¡ç†ã•ã‚Œã¦ã„ã¾ã™</translation>
@@ -1678,6 +1727,7 @@
&lt;li&gt;ã“ã®ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã‚’パソコンã‹ã‚‰å®Œå…¨ã«å‰Šé™¤ã™ã‚‹æ–¹æ³•ã«ã¤ã„ã¦ã¯ã€&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome ヘルプセンター&lt;/a&gt;ã‚’ã”覧ãã ã•ã„。
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">ラブリー</translation>
<translation id="7416351320495623771">パスワードを管ç†â€¦</translation>
<translation id="7419106976560586862">プロフィール パス</translation>
<translation id="7437289804838430631">連絡先情報を追加</translation>
@@ -1693,7 +1743,7 @@
<translation id="7481312909269577407">進む</translation>
<translation id="7485870689360869515">データãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。</translation>
<translation id="7495528107193238112">ã“ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã¯ãƒ–ロックã•ã‚Œã¾ã—ãŸã€‚サイト所有者ã«é€£çµ¡ã—ã¦å•é¡Œã‚’解決ã—ã¦ãã ã•ã„。</translation>
-<translation id="7498234416455752244">編集を続ã‘ã‚‹</translation>
+<translation id="7498193950643227031">サイズãŒå¤‰æ›´ã•ã‚ŒãŸå ´åˆã€äºˆæœŸã—ãªã„動作をã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚<ph name="SETTINGS" />ã§ã‚¢ãƒ—リã®ã‚µã‚¤ã‚ºå¤‰æ›´ã‚’制é™ã§ãるよã†ã«ãªã‚Šã¾ã—ãŸã€‚</translation>
<translation id="7503664977220660814">å½ã®ã‚µã‚¤ãƒˆã§ãƒ‘スワードを入力ã—ã¾ã—ãŸã€‚<ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" /> ã®ã»ã‹ã€ã“ã®ãƒ‘スワードを使用ã—ã¦ã„るサイトã§ã€ä¿å­˜ã—ãŸãƒ‘スワードを今ã™ã確èªã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
<translation id="7508255263130623398">è¿”ã•ã‚ŒãŸãƒãƒªã‚·ãƒ¼ã®ãƒ‡ãƒã‚¤ã‚¹ ID ãŒç©ºã§ã‚ã‚‹ã‹ã€ç¾åœ¨ã®ãƒ‡ãƒã‚¤ã‚¹ ID ã¨ä¸€è‡´ã—ã¾ã›ã‚“</translation>
<translation id="7508870219247277067">アボカド グリーン</translation>
@@ -1713,6 +1763,7 @@
<translation id="7548892272833184391">接続エラーを解決ã™ã‚‹</translation>
<translation id="7549584377607005141">ã“ã®ã‚¦ã‚§ãƒ–ページを正ã—ã表示ã™ã‚‹ã«ã¯ã€å…ˆã»ã©å…¥åŠ›ã—ãŸãƒ‡ãƒ¼ã‚¿ãŒå¿…è¦ã§ã™ã€‚データã¯å†é€ä¿¡ã§ãã¾ã™ãŒã€ã“ã®ãƒšãƒ¼ã‚¸ã§å…ˆã»ã©è¡Œã£ãŸæ“作を繰り返ã™ã“ã¨ã«ãªã‚Šã¾ã™ã€‚</translation>
<translation id="7550637293666041147">ãŠå®¢æ§˜ã®ãƒ‡ãƒã‚¤ã‚¹ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼å㨠Chrome ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼å</translation>
+<translation id="755279583747225797">試用版ã¯æœ‰åŠ¹ã§ã™</translation>
<translation id="7552846755917812628">次ã®ã“ã¨ã‚’ãŠè©¦ã—ãã ã•ã„。</translation>
<translation id="7554475479213504905">å†èª­ã¿è¾¼ã¿ã—ã¦è¡¨ç¤º</translation>
<translation id="7554791636758816595">æ–°ã—ã„タブ</translation>
@@ -1731,7 +1782,6 @@
<translation id="7610193165460212391">値(<ph name="VALUE" />)ãŒç¯„囲外ã§ã™ã€‚</translation>
<translation id="7613889955535752492">有効期é™: <ph name="EXPIRATION_MONTH" /> / <ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" /> ã§ã™ã€‚Tab キーã€Enter キーã®é †ã«æŠ¼ã™ã¨ã€Chrome ã®è¨­å®šã§ãƒ‘スワードを表示ã€ç®¡ç†ã—ã¾ã™</translation>
-<translation id="7615602087246926389">別㮠Google アカウント パスワードを使ã£ã¦æš—å·åŒ–ã—ãŸãƒ‡ãƒ¼ã‚¿ãŒæ—¢ã«ã‚ã‚Šã¾ã™ã€‚パスワードを以下ã«å…¥åŠ›ã—ã¦ãã ã•ã„。</translation>
<translation id="7616645509853975347">管ç†è€…ã«ã‚ˆã‚Šã€ãŠä½¿ã„ã®ãƒ–ラウザ㧠Chrome Enterprise Connectors ãŒæœ‰åŠ¹åŒ–ã•ã‚Œã¦ã„ã¾ã™ã€‚ã“れらã®ã‚³ãƒã‚¯ã‚¿ã«ã¯ã€ä¸€éƒ¨ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ‡ãƒ¼ã‚¿ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒè¨±å¯ã•ã‚Œã¾ã™ã€‚</translation>
<translation id="7619838219691048931">最終シート</translation>
<translation id="762844065391966283">1 件ãšã¤</translation>
@@ -1796,13 +1846,12 @@
<translation id="782886543891417279">ã”利用㮠Wi-Fi(<ph name="WIFI_NAME" />)ã§ã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ãƒšãƒ¼ã‚¸ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ãŒå¿…è¦ãªå¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚</translation>
<translation id="7836231406687464395">Postfix(å°ç­’)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ãªã—}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">ファイル形å¼ãŒé–¢é€£ä»˜ã‘られãŸãƒ—ログラムã§ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é–‹ã</translation>
<translation id="7862185352068345852">ã“ã®ã‚µã‚¤ãƒˆã‚’離れã¾ã™ã‹ï¼Ÿ</translation>
<translation id="7865448901209910068">最高速度</translation>
<translation id="7874263914261512992">å½ã®ã‚µã‚¤ãƒˆã§ãƒ‘スワードを入力ã—ã¾ã—ãŸã€‚<ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" /> ã®ã»ã‹ã€ã“ã®ãƒ‘スワードを使用ã—ã¦ã„るサイトã§ã€ä¿å­˜ã—ãŸãƒ‘スワードを今ã™ã確èªã™ã‚‹ã“ã¨ã‚’ãŠã™ã™ã‚ã—ã¾ã™ã€‚</translation>
<translation id="7878562273885520351">パスワードãŒä¸æ­£ä½¿ç”¨ã•ã‚Œã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™</translation>
+<translation id="7880146494886811634">ä½æ‰€ã‚’ä¿å­˜</translation>
<translation id="7882421473871500483">茶</translation>
<translation id="7887683347370398519">CVC を確èªã—ã¦ã‹ã‚‰ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„</translation>
<translation id="7887885240995164102">ピクãƒãƒ£ãƒ¼ イン ピクãƒãƒ£ãƒ¼ã‚’開始</translation>
@@ -1810,6 +1859,7 @@
<translation id="7894280532028510793">タイプミスã§ãªã„å ´åˆã¯ã€<ph name="BEGIN_LINK" />ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯è¨ºæ–­ã‚’ãŠè©¦ã—ãã ã•ã„<ph name="END_LINK" />。</translation>
<translation id="7904208859782148177">C3(å°ç­’)</translation>
<translation id="7931318309563332511">ä¸æ˜Ž</translation>
+<translation id="793209273132572360">ä½æ‰€ã‚’æ›´æ–°ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="7932579305932748336">コーティング</translation>
<translation id="79338296614623784">有効ãªé›»è©±ç•ªå·ã‚’入力ã—ã¦ãã ã•ã„</translation>
<translation id="7934052535022478634">ãŠæ”¯æ‰•ã„ã®å®Œäº†</translation>
@@ -1880,6 +1930,7 @@
<translation id="8175796834047840627">ログインã—ã¦ã„ã‚‹å ´åˆã¯ã€ãã® Google アカウントã«ã‚«ãƒ¼ãƒ‰ã‚’ä¿å­˜ã§ãã¾ã™ã€‚ã“ã®å‹•ä½œã¯è¨­å®šã§å¤‰æ›´ã§ãã¾ã™ã€‚</translation>
<translation id="8176440868214972690">ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã®ç®¡ç†è€…ã¯ã€æ¬¡ã®ã‚¦ã‚§ãƒ–サイトã«è¨­å®šã‚„ãƒãƒªã‚·ãƒ¼ãªã©ã®æƒ…報をé€ä¿¡ã™ã‚‹ã‚ˆã†è¨­å®šã—ã¦ã„ã¾ã™ã€‚</translation>
<translation id="8184538546369750125">グローãƒãƒ«ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ï¼ˆ[許å¯])を使用</translation>
+<translation id="8193086767630290324">機密ã¨ã—ã¦æŒ‡å®šã•ã‚ŒãŸãƒ‡ãƒ¼ã‚¿ã«å¯¾ã™ã‚‹æ“作</translation>
<translation id="8194797478851900357">移動ã®å–り消ã—(&amp;U)</translation>
<translation id="8201077131113104583">ID「<ph name="EXTENSION_ID" />ã€ã®æ‹¡å¼µæ©Ÿèƒ½ã«å¯¾ã™ã‚‹ç„¡åŠ¹ãªæ›´æ–° URL ã§ã™ã€‚</translation>
<translation id="8202097416529803614">ã”注文概è¦</translation>
@@ -1902,6 +1953,7 @@
<translation id="8249296373107784235">中止</translation>
<translation id="8249320324621329438">å‰å›žã®å–å¾—:</translation>
<translation id="8253091569723639551">請求先ä½æ‰€ãŒå¿…è¦ã§ã™</translation>
+<translation id="8257387598443225809">ã“ã®ã‚¢ãƒ—リã¯ãƒ¢ãƒã‚¤ãƒ«å‘ã‘ã«è¨­è¨ˆã•ã‚Œã¦ã„ã¾ã™</translation>
<translation id="825929999321470778">ä¿å­˜ã—ãŸãƒ‘スワードをã™ã¹ã¦è¡¨ç¤º</translation>
<translation id="8261506727792406068">削除</translation>
<translation id="8262952874573525464">端綴ã˜ï¼ˆä¸‹ï¼‰</translation>
@@ -2026,7 +2078,6 @@
<translation id="8719528812645237045">多穴パンãƒï¼ˆä¸Šï¼‰</translation>
<translation id="8725066075913043281">ã‚„ã‚Šç›´ã—</translation>
<translation id="8726549941689275341">ページサイズ:</translation>
-<translation id="8728672262656704056">シークレット モードã§ã™</translation>
<translation id="8730621377337864115">完了</translation>
<translation id="8731544501227493793">パスワードを管ç†ã™ã‚‹ãƒœã‚¿ãƒ³ã§ã™ã€‚Enter キーを押ã™ã¨ Chrome ã®è¨­å®šã§ãƒ‘スワードを表示ã€ç®¡ç†ã—ã¾ã™</translation>
<translation id="8734529307927223492">ã“ã® <ph name="DEVICE_TYPE" /> 㯠<ph name="MANAGER" /> ã«ã‚ˆã£ã¦ç®¡ç†ã•ã‚Œã¦ã„ã¾ã™</translation>
@@ -2103,6 +2154,7 @@
<translation id="9020542370529661692">ã“ã®ãƒšãƒ¼ã‚¸ã¯<ph name="TARGET_LANGUAGE" />ã«ç¿»è¨³ã•ã‚Œã¦ã„ã¾ã™</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(無効)</translation>
+<translation id="9030265603405983977">モノクロ</translation>
<translation id="9035022520814077154">セキュリティ エラー</translation>
<translation id="9038649477754266430">予測サービスを使用ã—ã¦ãƒšãƒ¼ã‚¸ã‚’より迅速ã«èª­ã¿è¾¼ã‚€</translation>
<translation id="9039213469156557790">加ãˆã¦ã€ã“ã®ãƒšãƒ¼ã‚¸ã«ã¯å®‰å…¨ã§ãªã„ä»–ã®ãƒªã‚½ãƒ¼ã‚¹ãŒå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚ã“ã®ãƒªã‚½ãƒ¼ã‚¹ã¯é€ä¿¡ä¸­ã«ä»–ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‹ã‚‰è¦‹ã‚‰ã‚Œã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚ã¾ãŸã€æ‚ªæ„ã®ã‚るユーザーã«ã‚ˆã£ã¦æ”¹å¤‰ã•ã‚Œãƒšãƒ¼ã‚¸ã®å‹•ä½œãŒå¤‰ã‚ã‚‹å¯èƒ½æ€§ã‚‚ã‚ã‚Šã¾ã™ã€‚</translation>
@@ -2126,6 +2178,7 @@
<translation id="91108059142052966">管ç†è€…ã®ãƒãƒªã‚·ãƒ¼ã«ã‚ˆã£ã¦ã€æ©Ÿå¯†ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ãŒè¡¨ç¤ºã•ã‚Œã¦ã„ã‚‹ã¨ãã¯ã€<ph name="APPLICATION_TITLE" /> ã¨ã®ç”»é¢å…±æœ‰ãŒç„¡åŠ¹ã«ãªã‚Šã¾ã™</translation>
<translation id="9114524666733003316">カードを確èªã—ã¦ã„ã¾ã™â€¦</translation>
<translation id="9114581008513152754">ã“ã®ãƒ–ラウザã¯ã€ä¼šç¤¾ã¾ãŸã¯ãã®ä»–ã®çµ„ç¹”ã«ã‚ˆã£ã¦ç®¡ç†ã•ã‚Œã¦ã„ã¾ã›ã‚“。ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã§ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティã¯ã€Chrome 以外ã§ç®¡ç†ã•ã‚Œã¦ã„ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚<ph name="BEGIN_LINK" />詳細<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">フレッシュ</translation>
<translation id="9119042192571987207">アップロード済ã¿</translation>
<translation id="9128016270925453879">ãƒãƒªã‚·ãƒ¼ãŒèª­ã¿è¾¼ã¾ã‚Œã¾ã—ãŸ</translation>
<translation id="9128870381267983090">ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«æŽ¥ç¶šã™ã‚‹</translation>
@@ -2144,6 +2197,7 @@
<translation id="9170848237812810038">å–消(&amp;U)</translation>
<translation id="9171296965991013597">アプリを終了ã—ã¾ã™ã‹ï¼Ÿ</translation>
<translation id="9173282814238175921">1 ã¤ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆæ–°è¦ã‚·ãƒ¼ãƒˆï¼‰</translation>
+<translation id="9173995187295789444">Bluetooth デãƒã‚¤ã‚¹ã‚’スキャンã—ã¦ã„ã¾ã™...</translation>
<translation id="917450738466192189">サーãƒãƒ¼ã®è¨¼æ˜Žæ›¸ãŒç„¡åŠ¹ã§ã™ã€‚</translation>
<translation id="9174917557437862841">タブã®åˆ‡ã‚Šæ›¿ãˆãƒœã‚¿ãƒ³ã§ã™ã€‚Enter キーを押ã™ã¨ã“ã®ã‚¿ãƒ–ã«åˆ‡ã‚Šæ›¿ã‚ã‚Šã¾ã™</translation>
<translation id="9179703756951298733">Chrome ã®è¨­å®šã§ãŠæ”¯æ‰•ã„ã¨ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆ カード情報を管ç†ã™ã‚‹</translation>
diff --git a/chromium/components/strings/components_strings_ka.xtb b/chromium/components/strings/components_strings_ka.xtb
index dd20ec97e5f..a6471b2259a 100644
--- a/chromium/components/strings/components_strings_ka.xtb
+++ b/chromium/components/strings/components_strings_ka.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">თუ მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜áƒ, Chrome ფáƒáƒ áƒ›áƒ”ბის უფრრსწრáƒáƒ¤áƒáƒ“ შევსების მიზნით, თქვენი ბáƒáƒ áƒáƒ—ის áƒáƒ¡áƒšáƒ¡ áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ¨áƒ˜ შეინáƒáƒ®áƒáƒ•áƒ¡.</translation>
<translation id="1110994991967754504">áƒáƒ˜áƒ áƒ©áƒ˜áƒ”თ ნებáƒáƒ áƒ—ვáƒ: <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">გáƒáƒ“áƒáƒšáƒáƒ’ების &amp;მáƒáƒ¥áƒ›áƒ”დების გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ</translation>
+<translation id="1123753900084781868">áƒáƒ•áƒ¢áƒáƒ¡áƒ£áƒ‘ტიტრები áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ მიუწვდáƒáƒ›áƒ”ლიáƒ</translation>
<translation id="1125573121925420732">თქვენ შეიძლებრხშირáƒáƒ“ შეგხვდეთ გáƒáƒ¤áƒ áƒ—ხილებები, სáƒáƒœáƒáƒ› ვებსáƒáƒ˜áƒ¢áƒ”ბზე áƒáƒ  გáƒáƒ£áƒ›áƒ¯áƒáƒ‘ესდებრუსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბáƒ. ეს მáƒáƒšáƒ” უნდრმáƒáƒ’ვáƒáƒ áƒ“ეს.</translation>
<translation id="112840717907525620">წესის ქეში OK</translation>
<translation id="1130564665089811311">გვერდის თáƒáƒ áƒ’მნის ღილáƒáƒ™áƒ˜, áƒáƒ› გვერდის Google Translate-ით სáƒáƒ—áƒáƒ áƒ’მნáƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ Enter</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">თქვენი მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის სáƒáƒ®áƒ”ლი</translation>
<translation id="124116460088058876">სხვრენები</translation>
<translation id="1243027604378859286">áƒáƒ•áƒ¢áƒáƒ áƒ˜:</translation>
+<translation id="1246424317317450637">მუქი</translation>
<translation id="1250759482327835220">შემდგáƒáƒ›áƒ˜ გáƒáƒ“áƒáƒ®áƒ“ების დáƒáƒ¡áƒáƒ©áƒ¥áƒáƒ áƒ”ბლáƒáƒ“ შეგიძლიáƒáƒ— შეინáƒáƒ®áƒáƒ— თქვენი ბáƒáƒ áƒáƒ—ის მáƒáƒœáƒáƒªáƒ”მები, სáƒáƒ®áƒ”ლი დრბილინგის მისáƒáƒ›áƒáƒ áƒ—ი თქვენს Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (სინქრáƒáƒœáƒ˜áƒ–ებული)</translation>
<translation id="1256368399071562588">&lt;p&gt;თუ ვებსáƒáƒ˜áƒ¢áƒ˜, რáƒáƒ›áƒšáƒ˜áƒ¡ მáƒáƒœáƒáƒ®áƒ£áƒšáƒ”ბáƒáƒ¡áƒáƒª ცდილáƒáƒ‘თ, áƒáƒ  იხსნებáƒ, პირველ რიგში, ცáƒáƒ“ეთ შემდეგი:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">შეცვáƒáƒšáƒ”თ თქვენი პáƒáƒ áƒáƒšáƒ˜</translation>
<translation id="1484290072879560759">მიწáƒáƒ“ების მისáƒáƒ›áƒáƒ áƒ—ის áƒáƒ áƒ©áƒ”ვáƒ</translation>
<translation id="1492194039220927094">წესების გáƒáƒ“მáƒáƒ¢áƒáƒœáƒ:</translation>
+<translation id="1495677929897281669">ჩáƒáƒœáƒáƒ áƒ—ზე დáƒáƒ‘რუნებáƒ</translation>
<translation id="1501859676467574491">Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜ შენáƒáƒ®áƒ£áƒšáƒ˜ ბáƒáƒ áƒáƒ—ების ჩვენებáƒ</translation>
<translation id="1507202001669085618">&lt;p&gt;áƒáƒ› ტიპის შეცდáƒáƒ›áƒ˜áƒ¡ შესáƒáƒ®áƒ”ბ შეტყáƒáƒ‘ინებáƒáƒ¡ დáƒáƒ˜áƒœáƒáƒ®áƒáƒ•áƒ— იმ შემთხვევáƒáƒ¨áƒ˜, თუ ისეთ Wi-Fi პáƒáƒ áƒ¢áƒáƒšáƒ¡ იყენებთ, რáƒáƒ›áƒ”ლიც მáƒáƒ˜áƒ—ხáƒáƒ•áƒ¡ სისტემáƒáƒ¨áƒ˜ შესვლáƒáƒ¡ ინტერნეტ-კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜áƒ¡ უზრუნველსáƒáƒ§áƒáƒ¤áƒáƒ“.&lt;/p&gt;
&lt;p&gt;პრáƒáƒ‘ლემის მáƒáƒ¡áƒáƒ’ვáƒáƒ áƒ”ბლáƒáƒ“ დáƒáƒáƒ¬áƒ™áƒáƒžáƒ£áƒœáƒ”თ ღილáƒáƒ™áƒ–ე &lt;strong&gt;დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბáƒ&lt;/strong&gt; იმ გვერდზე, რáƒáƒ›áƒšáƒ˜áƒ¡ გáƒáƒ®áƒ¡áƒœáƒáƒ¡áƒáƒª ცდილáƒáƒ‘თ.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">ეს გვერდი იუწყებáƒ:</translation>
<translation id="153384715582417236">áƒáƒ› დრáƒáƒ˜áƒ¡áƒ—ვის სულ ეს áƒáƒ áƒ˜áƒ¡</translation>
<translation id="1536390784834419204">გვერდის თáƒáƒ áƒ’მნáƒ</translation>
+<translation id="1539840569003678498">მáƒáƒ®áƒ¡áƒ”ნებრგáƒáƒ˜áƒ’ზáƒáƒ•áƒœáƒ:</translation>
<translation id="154408704832528245">მიწáƒáƒ“ების მისáƒáƒ›áƒáƒ áƒ—ის áƒáƒ áƒ©áƒ”ვáƒ</translation>
<translation id="1549470594296187301">áƒáƒ› ფუნქციის გáƒáƒ›áƒáƒ¡áƒáƒ§áƒ”ნებლáƒáƒ“, JavaScript ჩáƒáƒ áƒ—ული უნდრიყáƒáƒ¡.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">ჯერ მáƒáƒ™áƒšáƒ” კიდე</translation>
<translation id="168693727862418163">წესების áƒáƒ› მნიშვნელáƒáƒ‘ის სქემის დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბრვერ მáƒáƒ®áƒ”რხდáƒ, áƒáƒ›áƒ˜áƒ¢áƒáƒ› ის უგულებელყáƒáƒ¤áƒ˜áƒšáƒ˜ იქნებáƒ.</translation>
<translation id="168841957122794586">სერვერის სერთიფიკáƒáƒ¢áƒ˜ შეიცáƒáƒ•áƒ¡ სუსტ კრიპტáƒáƒ’რáƒáƒ¤áƒ˜áƒ£áƒš გáƒáƒ¡áƒáƒ¦áƒ”ბს.</translation>
+<translation id="1696290444144917273">ვირტუáƒáƒšáƒ£áƒ áƒ˜ ბáƒáƒ áƒáƒ—ის დეტáƒáƒšáƒ”ბის ნáƒáƒ®áƒ•áƒ</translation>
<translation id="1697532407822776718">ყველáƒáƒ¤áƒ”რი დáƒáƒ§áƒ”ნებულიáƒ!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{ეს სერვერი ვერ áƒáƒ›áƒ¢áƒ™áƒ˜áƒªáƒ”ბს, რáƒáƒ› ის áƒáƒ áƒ˜áƒ¡ <ph name="DOMAIN" />; მისი უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბის სერტიფიკáƒáƒ¢áƒ˜, სáƒáƒ•áƒáƒ áƒáƒ£áƒ“áƒáƒ“, ხვáƒáƒšáƒ˜áƒœáƒ“ელიáƒ. áƒáƒ›áƒ˜áƒ¡ მიზეზი შეიძლებრიყáƒáƒ¡ áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜ კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ áƒáƒœ შესáƒáƒ«áƒšáƒáƒ, თქვენი კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜ თáƒáƒ•áƒ“áƒáƒ›áƒ¡áƒ®áƒ›áƒ”ლს ჰქáƒáƒœáƒ“ეს ხელში ჩáƒáƒ’დებული.}other{ეს სერვერი ვერ áƒáƒ›áƒ¢áƒ™áƒ˜áƒªáƒ”ბს, რáƒáƒ› ის áƒáƒ áƒ˜áƒ¡ <ph name="DOMAIN" />; მისი უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბის სერტიფიკáƒáƒ¢áƒ˜áƒ¡ ვáƒáƒ“áƒ, სáƒáƒ•áƒáƒ áƒáƒ£áƒ“áƒáƒ“, # დღის შემდეგ იწყებáƒ. áƒáƒ›áƒ˜áƒ¡ მიზეზი შეიძლებრიყáƒáƒ¡ áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜ კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ áƒáƒœ შესáƒáƒ«áƒšáƒáƒ, თქვენი კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜ თáƒáƒ•áƒ“áƒáƒ›áƒ¡áƒ®áƒ›áƒ”ლს ჰქáƒáƒœáƒ“ეს ხელში ჩáƒáƒ’დებული.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">იგნáƒáƒ áƒ˜áƒ áƒ”ბულიáƒ, რáƒáƒ“გáƒáƒœ <ph name="POLICY_NAME" />-ის მნიშვნელáƒáƒ‘რáƒáƒ  áƒáƒ áƒ˜áƒ¡ <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> ითხáƒáƒ•áƒ¡ თქვენს áƒáƒ“გილáƒáƒ‘რივ კáƒáƒ›áƒžáƒ˜áƒ£áƒ¢áƒ”რზე მáƒáƒœáƒáƒªáƒ”მების სáƒáƒ›áƒ£áƒ“áƒáƒ›áƒáƒ“ შენáƒáƒ®áƒ•áƒ˜áƒ¡ ნებáƒáƒ áƒ—ვáƒáƒ¡</translation>
<translation id="1713628304598226412">ლáƒáƒœáƒ’áƒáƒ áƒ˜ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">სáƒáƒ¤áƒáƒ¡áƒ¢áƒ ყუთი 3</translation>
<translation id="1718029547804390981">დáƒáƒ™áƒ£áƒ›áƒ”ნტი áƒáƒœáƒáƒ¢áƒ˜áƒ áƒ”ბისთვის მეტისმეტáƒáƒ“ დიდიáƒ</translation>
<translation id="1721424275792716183">* ველი áƒáƒ£áƒªáƒ˜áƒšáƒ”ბელიáƒ</translation>
+<translation id="1727613060316725209">სერთიფიკáƒáƒ¢áƒ˜ ძáƒáƒšáƒáƒ¨áƒ˜áƒ</translation>
<translation id="1727741090716970331">მიუთითეთ ბáƒáƒ áƒáƒ—ის სწáƒáƒ áƒ˜ ნáƒáƒ›áƒ”რი</translation>
<translation id="1728677426644403582">თქვენ áƒáƒ—ვáƒáƒšáƒ˜áƒ”რებთ ვებგვერდის წყáƒáƒ áƒáƒ¡</translation>
<translation id="173080396488393970">áƒáƒ› ტიპის ბáƒáƒ áƒáƒ—ი მხáƒáƒ áƒ“áƒáƒ£áƒ­áƒ”რელიáƒ</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />სცáƒáƒ“ეთ Windows-ის ქსელის დიáƒáƒ’ნáƒáƒ¡áƒ¢áƒ˜áƒ™áƒ˜áƒ¡ ხელსáƒáƒ¬áƒ§áƒáƒ¡ გáƒáƒ¨áƒ•áƒ”ბáƒ<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">სერვერმáƒ, რáƒáƒ›áƒ”ლზე გáƒáƒ“áƒáƒ¡áƒ•áƒšáƒáƒ¡áƒáƒª ცდილáƒáƒ‘თ (<ph name="ORIGIN" />), დáƒáƒáƒ§áƒ”ნრსáƒáƒ—áƒáƒ£áƒ áƒ˜, რáƒáƒ›áƒšáƒ˜áƒ¡áƒáƒ“მი ყველრმიმáƒáƒ áƒ—ვáƒáƒª სáƒáƒ­áƒ˜áƒ áƒáƒ”ბს წყáƒáƒ áƒáƒ¡ წესების გáƒáƒ›áƒáƒ§áƒ”ნებáƒáƒ¡. სáƒáƒ›áƒ¬áƒ£áƒ®áƒáƒ áƒáƒ“, სáƒáƒ—áƒáƒ£áƒ áƒ˜ áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒáƒ“ ფáƒáƒ áƒ›áƒ£áƒšáƒ˜áƒ áƒ”ბულიáƒ, რის გáƒáƒ›áƒáƒª ბრáƒáƒ£áƒ–ერი <ph name="SITE" />-თáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბულ თქვენს მáƒáƒ—ხáƒáƒ•áƒœáƒáƒ¡ ვერ áƒáƒ¡áƒ áƒ£áƒšáƒ”ბს. წყáƒáƒ áƒáƒ¡ წესების მეშვეáƒáƒ‘ით სáƒáƒ˜áƒ¢áƒ”ბის áƒáƒžáƒ”რáƒáƒ¢áƒáƒ áƒ”ბს შეუძლიáƒáƒ— áƒáƒ›áƒ თუ იმ სáƒáƒ˜áƒ¢áƒ˜áƒ¡ უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბისრდრსხვრმáƒáƒ®áƒáƒ¡áƒ˜áƒáƒ—ებლების კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">გთხáƒáƒ•áƒ— გáƒáƒœáƒáƒáƒ®áƒšáƒ”თ თქვენი სინქრ. პáƒáƒ áƒáƒšáƒ˜áƒ¡ ფრáƒáƒ–áƒ.</translation>
<translation id="1787142507584202372">áƒáƒ¥ გáƒáƒ›áƒáƒ©áƒœáƒ“ებრთქვენი გáƒáƒ®áƒ¡áƒœáƒ˜áƒšáƒ˜ ჩáƒáƒœáƒáƒ áƒ—ები</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, შესáƒáƒ«áƒšáƒ”ბელირრáƒáƒ›áƒ“ენიმე მáƒáƒ¥áƒ›áƒ”დებáƒ, დáƒáƒáƒ­áƒ˜áƒ áƒ”თ Tab-ს მáƒáƒ— სáƒáƒœáƒáƒ®áƒáƒ•áƒáƒ“</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">რეკლáƒáƒ›áƒ</translation>
<translation id="1919367280705858090">შეცდáƒáƒ›áƒ˜áƒ¡ შესáƒáƒ®áƒ”ბ კáƒáƒœáƒ™áƒ áƒ”ტულ შეტყáƒáƒ‘ინებებთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბული დáƒáƒ®áƒ›áƒáƒ áƒ”ბáƒ</translation>
<translation id="192020519938775529">{COUNT,plural, =0{áƒáƒ áƒªáƒ”რთი}=1{1 სáƒáƒ˜áƒ¢áƒ˜}other{# სáƒáƒ˜áƒ¢áƒ˜}}</translation>
+<translation id="1924727005275031552">სიáƒáƒ®áƒšáƒ”</translation>
<translation id="1945968466830820669">თქვენ შეიძლებრმáƒáƒ’პáƒáƒ áƒáƒœ პერსáƒáƒœáƒáƒšáƒ£áƒ áƒ˜ მáƒáƒœáƒáƒªáƒ”მები, áƒáƒœ დáƒáƒ™áƒáƒ áƒ’áƒáƒ— წვდáƒáƒ›áƒ თქვენი áƒáƒ áƒ’áƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡ áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ–ე. Chromium გირჩევთ, áƒáƒ®áƒšáƒáƒ•áƒ” შეცვáƒáƒšáƒáƒ— პáƒáƒ áƒáƒšáƒ˜.</translation>
<translation id="1947454675006758438">ზედრმáƒáƒ áƒ¯áƒ•áƒ”ნრნáƒáƒ¬áƒ˜áƒšáƒ˜áƒ¡ დáƒáƒ¡áƒ¢áƒ”პლერებáƒ</translation>
<translation id="1958218078413065209">თქვენი უმáƒáƒ¦áƒšáƒ”სი ქულáƒáƒ <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">ლáƒáƒœáƒ’áƒáƒ áƒ˜ 7</translation>
<translation id="204357726431741734">თქვენს Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜ შენáƒáƒ®áƒ£áƒšáƒ˜ პáƒáƒ áƒáƒšáƒ”ბის გáƒáƒ›áƒáƒ¡áƒáƒ§áƒ”ნებლáƒáƒ“ შედით სისტემáƒáƒ¨áƒ˜</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> გვერდები áƒáƒ  ითáƒáƒ áƒ’მნებáƒ.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{რáƒáƒªáƒ მáƒáƒ áƒ—ვის ეს სáƒáƒ¨áƒ£áƒáƒšáƒ”ბრჩáƒáƒ áƒ—ულირდრსტáƒáƒ¢áƒ£áƒ¡áƒ˜ áƒáƒ¥áƒ¢áƒ˜áƒ£áƒ áƒ˜áƒ, Chrome გáƒáƒœáƒ¡áƒáƒ–ღვრáƒáƒ•áƒ¡, áƒáƒ“áƒáƒ›áƒ˜áƒáƒœáƒ—რრáƒáƒ›áƒ”ლი ვრცელი ჯგუფის, áƒáƒœáƒ£ ე.წ. „კáƒáƒ°áƒáƒ áƒ¢áƒ˜áƒ¡â€œ, მსგáƒáƒ•áƒ¡áƒ˜áƒ თქვენი დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების ბáƒáƒšáƒáƒ“რáƒáƒ˜áƒœáƒ“ელი áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒ‘áƒ. რეკლáƒáƒ›áƒ˜áƒ¡ გáƒáƒœáƒ›áƒ—áƒáƒ•áƒ¡áƒ”ბლებს შეეძლებáƒáƒ— ჯგუფისთვის რეკლáƒáƒ›áƒ˜áƒ¡ áƒáƒ áƒ©áƒ”ვáƒ, ხáƒáƒšáƒ თქვენი დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒ‘რკáƒáƒœáƒ¤áƒ˜áƒ“ენციáƒáƒšáƒ£áƒ áƒáƒ“ შეინáƒáƒ®áƒ”ბრთქვენს მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე. თქვენი ჯგუფი ყáƒáƒ•áƒ”ლდღიურáƒáƒ“ გáƒáƒœáƒáƒ®áƒšáƒ“ებáƒ.}=1{რáƒáƒªáƒ მáƒáƒ áƒ—ვის ეს სáƒáƒ¨áƒ£áƒáƒšáƒ”ბრჩáƒáƒ áƒ—ულირდრსტáƒáƒ¢áƒ£áƒ¡áƒ˜ áƒáƒ¥áƒ¢áƒ˜áƒ£áƒ áƒ˜áƒ, Chrome გáƒáƒœáƒ¡áƒáƒ–ღვრáƒáƒ•áƒ¡, áƒáƒ“áƒáƒ›áƒ˜áƒáƒœáƒ—რრáƒáƒ›áƒ”ლი ვრცელი ჯგუფის, áƒáƒœáƒ£ ე.წ. „კáƒáƒ°áƒáƒ áƒ¢áƒ˜áƒ¡â€œ, მსგáƒáƒ•áƒ¡áƒ˜áƒ თქვენი დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების ბáƒáƒšáƒáƒ“რáƒáƒ˜áƒœáƒ“ელი áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒ‘áƒ. რეკლáƒáƒ›áƒ˜áƒ¡ გáƒáƒœáƒ›áƒ—áƒáƒ•áƒ¡áƒ”ბლებს შეეძლებáƒáƒ— ჯგუფისთვის რეკლáƒáƒ›áƒ˜áƒ¡ áƒáƒ áƒ©áƒ”ვáƒ, ხáƒáƒšáƒ თქვენი დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒ‘რკáƒáƒœáƒ¤áƒ˜áƒ“ენციáƒáƒšáƒ£áƒ áƒáƒ“ შეინáƒáƒ®áƒ”ბრთქვენს მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე. თქვენი ჯგუფი ყáƒáƒ•áƒ”ლდღიურáƒáƒ“ გáƒáƒœáƒáƒ®áƒšáƒ“ებáƒ.}other{რáƒáƒªáƒ მáƒáƒ áƒ—ვის ეს სáƒáƒ¨áƒ£áƒáƒšáƒ”ბრჩáƒáƒ áƒ—ულირდრსტáƒáƒ¢áƒ£áƒ¡áƒ˜ áƒáƒ¥áƒ¢áƒ˜áƒ£áƒ áƒ˜áƒ, Chrome გáƒáƒœáƒ¡áƒáƒ–ღვრáƒáƒ•áƒ¡, áƒáƒ“áƒáƒ›áƒ˜áƒáƒœáƒ—რრáƒáƒ›áƒ”ლი ვრცელი ჯგუფის, áƒáƒœáƒ£ ე.წ. „კáƒáƒ°áƒáƒ áƒ¢áƒ˜áƒ¡â€œ, მსგáƒáƒ•áƒ¡áƒ˜áƒ თქვენი დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების ბáƒáƒšáƒáƒ“რáƒáƒ˜áƒœáƒ“ელი áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒ‘áƒ. რეკლáƒáƒ›áƒ˜áƒ¡ გáƒáƒœáƒ›áƒ—áƒáƒ•áƒ¡áƒ”ბლებს შეეძლებáƒáƒ— ჯგუფისთვის რეკლáƒáƒ›áƒ˜áƒ¡ áƒáƒ áƒ©áƒ”ვáƒ, ხáƒáƒšáƒ თქვენი დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒ‘რკáƒáƒœáƒ¤áƒ˜áƒ“ენციáƒáƒšáƒ£áƒ áƒáƒ“ შეინáƒáƒ®áƒ”ბრთქვენს მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე. თქვენი ჯგუფი {NUM_DAYS} დღეში ერთხელ გáƒáƒœáƒáƒ®áƒšáƒ“ებáƒ.}}</translation>
<translation id="2053553514270667976">ZIP კáƒáƒ“ი</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 შეთáƒáƒ•áƒáƒ–ებáƒ}other{# შეთáƒáƒ•áƒáƒ–ებáƒ}}</translation>
<translation id="2071692954027939183">შეტყáƒáƒ‘ინებები áƒáƒ•áƒ¢áƒáƒ›áƒáƒ¢áƒ£áƒ áƒáƒ“ დáƒáƒ˜áƒ‘ლáƒáƒ™áƒ, რáƒáƒ“გáƒáƒœ, რáƒáƒ’áƒáƒ áƒª წესი, მáƒáƒ— მიღებáƒáƒ¡ კრძáƒáƒšáƒáƒ•áƒ— ხáƒáƒšáƒ›áƒ”</translation>
<translation id="2079545284768500474">მáƒáƒ¥áƒ›áƒ”დების გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ</translation>
<translation id="20817612488360358">დáƒáƒ§áƒ”ნებულირსისტემის პრáƒáƒ¥áƒ¡áƒ˜áƒ¡ პáƒáƒ áƒáƒ›áƒ”ტრების გáƒáƒ›áƒáƒ§áƒ”ნებáƒ, მáƒáƒ’რáƒáƒ› áƒáƒ¡áƒ”ვე მითითებულირპრáƒáƒ¥áƒ¡áƒ˜áƒ¡ áƒáƒ¨áƒ™áƒáƒ áƒ კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ.</translation>
<translation id="2082238445998314030">შედეგი <ph name="RESULT_NUMBER" /> / <ph name="TOTAL_RESULTS" />-დáƒáƒœ</translation>
+<translation id="2085876078937250610">შენáƒáƒ®áƒ•áƒâ€¦</translation>
<translation id="2088086323192747268">სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡ მáƒáƒ áƒ—ვის ღილáƒáƒ™áƒ˜, თქვენ მიერ სინქრáƒáƒœáƒ˜áƒ–ებული ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ Chrome-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ სáƒáƒ›áƒáƒ áƒ—áƒáƒ•áƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ Enter</translation>
<translation id="2091887806945687916">ხმáƒ</translation>
<translation id="2094505752054353250">დáƒáƒ›áƒ”ნის შეუსáƒáƒ‘áƒáƒ›áƒáƒ‘áƒ</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> სáƒáƒ­áƒ˜áƒ áƒáƒ”ბს მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის სáƒáƒ®áƒ”ლსრდრპáƒáƒ áƒáƒšáƒ¡.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, ძáƒáƒšáƒáƒ¨áƒ˜áƒ <ph name="EXPIRATION_DATE_ABBR" />-მდე</translation>
<translation id="2337852623177822836">პáƒáƒ áƒáƒ›áƒ”ტრს áƒáƒ™áƒáƒœáƒ¢áƒ áƒáƒšáƒ”ბს თქვენი áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ˜</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> დáƒáƒ¬áƒ§áƒ•áƒ˜áƒšáƒ”ბáƒáƒ¡ ითხáƒáƒ•áƒ¡</translation>
<translation id="2344028582131185878">áƒáƒ•áƒ¢áƒáƒ›áƒáƒ¢áƒ£áƒ áƒ˜ ჩáƒáƒ›áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვები</translation>
<translation id="2346319942568447007">თქვენ მიერ კáƒáƒžáƒ˜áƒ áƒ”ბული სურáƒáƒ—ი</translation>
<translation id="2354001756790975382">სხვრსáƒáƒœáƒ˜áƒ¨áƒœáƒ”ები</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">თáƒáƒ•áƒ“áƒáƒ›áƒ¡áƒ®áƒ›áƒ”ლებს შეუძლიáƒáƒ— იმ სურáƒáƒ—ების ნáƒáƒ®áƒ•áƒ, რáƒáƒ›áƒšáƒ”ბსáƒáƒª áƒáƒ› სáƒáƒ˜áƒ¢áƒ–ე áƒáƒ—ვáƒáƒšáƒ˜áƒ”რებთ, დრმáƒáƒ—ი შეცვლის მეშვეáƒáƒ‘ით, თქვენი შეცდáƒáƒ›áƒáƒ¨áƒ˜ შეყვáƒáƒœáƒ.</translation>
<translation id="2356070529366658676">მკითხე</translation>
<translation id="2357481397660644965">თქვენს მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ¡ მáƒáƒ áƒ—áƒáƒ•áƒ¡ <ph name="DEVICE_MANAGER" />, ხáƒáƒšáƒ თქვენს áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¡Â â€” <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{დღეზე ნáƒáƒ™áƒšáƒ”ბ დრáƒáƒ¨áƒ˜}=1{ერთ დღეში}other{{NUM_DAYS} დღეში}}</translation>
<translation id="2359629602545592467">რáƒáƒ›áƒ“ენიმე</translation>
<translation id="2359808026110333948">გáƒáƒ’რძელებáƒ</translation>
+<translation id="2359961752320758691">თქვენი ვირტუáƒáƒšáƒ£áƒ áƒ˜ ბáƒáƒ áƒáƒ—ის ნáƒáƒ›áƒ”რი გáƒáƒ›áƒáƒ§áƒ”ნებულიáƒ.</translation>
<translation id="2367567093518048410">დáƒáƒœáƒ”</translation>
<translation id="2372464001869762664">დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბის შემდეგ ბáƒáƒ áƒáƒ—ის მáƒáƒœáƒáƒªáƒ”მები, რáƒáƒ›áƒšáƒ”ბიც შენáƒáƒ®áƒ£áƒšáƒ˜áƒ თქვენს Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜, გáƒáƒ–იáƒáƒ áƒ“ებრáƒáƒ› სáƒáƒ˜áƒ¢áƒ—áƒáƒœ. CVC-ის პáƒáƒ•áƒœáƒ შეგიძლიáƒáƒ— თქვენი Plex áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ¡ მáƒáƒœáƒáƒªáƒ”მებში.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">გáƒáƒ’ზáƒáƒ•áƒœáƒ˜áƒ¡ ეს მეთáƒáƒ“ი მიუწვდáƒáƒ›áƒ”ლიáƒ. ცáƒáƒ“ეთ სხვრვáƒáƒ áƒ˜áƒáƒœáƒ¢áƒ˜.</translation>
<translation id="2396249848217231973">წáƒáƒ¨áƒšáƒ˜áƒ¡ &amp;მáƒáƒ¥áƒ›áƒ”დების გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">ძველი</translation>
<translation id="2413528052993050574">ეს სერვერი ვერ áƒáƒ›áƒ¢áƒ™áƒ˜áƒªáƒ”ბს რáƒáƒ› ის áƒáƒ áƒ˜áƒ¡ <ph name="DOMAIN" />; მისი უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბის სერთიფიკáƒáƒ¢áƒ˜ შესáƒáƒ«áƒšáƒáƒ გáƒáƒ£áƒ¥áƒ›áƒ”ბულიáƒ. ეს შეიძლებრიყáƒáƒ¡ გáƒáƒ›áƒáƒ¬áƒ•áƒ”ული áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜ კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ˜áƒ— áƒáƒœ თáƒáƒ•áƒ“áƒáƒ›áƒ¡áƒ®áƒ›áƒ”ლის მიერ თქვენი კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜áƒ¡ გáƒáƒ“áƒáƒ­áƒ áƒ˜áƒ—.</translation>
<translation id="2414886740292270097">მუქი</translation>
<translation id="2438874542388153331">áƒáƒ—ხმáƒáƒ’áƒáƒ“ გáƒáƒ®áƒ•áƒ áƒ”ტრმáƒáƒ áƒ¯áƒ•áƒœáƒ˜áƒ•</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">ქვედრმáƒáƒ áƒ¯áƒ•áƒ”ნრნáƒáƒ¬áƒ˜áƒšáƒ˜áƒ¡ დáƒáƒ¡áƒ¢áƒ”პლერებáƒ</translation>
<translation id="2523886232349826891">შეინáƒáƒ®áƒ”ბრმხáƒáƒšáƒáƒ“ áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე</translation>
<translation id="2524461107774643265">მიუთითეთ დáƒáƒ›áƒáƒ¢áƒ”ბითი ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ</translation>
-<translation id="2526590354069164005">სáƒáƒ›áƒ£áƒ¨áƒáƒ დáƒáƒ¤áƒ</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{დრ1 სხვáƒ}other{დრ# სხვáƒ}}</translation>
<translation id="2536110899380797252">მისáƒáƒ›áƒáƒ áƒ—ის დáƒáƒ›áƒáƒ¢áƒ”ბáƒ</translation>
<translation id="2539524384386349900">áƒáƒ›áƒáƒªáƒœáƒáƒ‘áƒ</translation>
+<translation id="2541219929084442027">ყველრინკáƒáƒ’ნიტრჩáƒáƒœáƒáƒ áƒ—ის დáƒáƒ®áƒ£áƒ áƒ•áƒ˜áƒ¡ შემდეგ, თქვენ მიერ ინკáƒáƒ’ნიტრჩáƒáƒœáƒáƒ áƒ—ების მეშვეáƒáƒ‘ით მáƒáƒœáƒáƒ®áƒ£áƒšáƒ”ბული გვერდები áƒáƒ  დáƒáƒ áƒ©áƒ”ბრთქვენი ბრáƒáƒ£áƒ–ერის ისტáƒáƒ áƒ˜áƒáƒ¨áƒ˜, ქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რების სáƒáƒªáƒáƒ•áƒ¨áƒ˜ დრáƒáƒ áƒª ძიების ისტáƒáƒ áƒ˜áƒáƒ¨áƒ˜. áƒáƒ›áƒ˜áƒ¡ მიუხედáƒáƒ•áƒáƒ“, თქვენ მიერ ჩáƒáƒ›áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ული ფáƒáƒ˜áƒšáƒ”ბი თუ შექმნილი სáƒáƒœáƒ˜áƒ¨áƒœáƒ”ები მáƒáƒ˜áƒœáƒª შეინáƒáƒ®áƒ”ბáƒ.</translation>
<translation id="2544644783021658368">ერთი დáƒáƒ™áƒ£áƒ›áƒ”ნტი</translation>
<translation id="254947805923345898">წესების მნიშვნელáƒáƒ‘რáƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜áƒ.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" />-მრáƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜ პáƒáƒ¡áƒ£áƒ®áƒ˜ გáƒáƒ›áƒáƒáƒ’ზáƒáƒ•áƒœáƒ.</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">Chrome-ის უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბის ყველáƒáƒ–ე ძლიერი ფუნქციებით სáƒáƒ áƒ’ებლáƒáƒ‘ისთვის <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ჩáƒáƒ áƒ—ეთ გáƒáƒ«áƒšáƒ˜áƒ”რებული დáƒáƒªáƒ•áƒ<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" />-ის სერვერის IP მისáƒáƒ›áƒáƒ áƒ—ი ვერ მáƒáƒ˜áƒ«áƒ”ბნáƒ.</translation>
<translation id="2639739919103226564">სტáƒáƒ¢áƒ£áƒ¡áƒ˜:</translation>
+<translation id="264810637653812429">თáƒáƒ•áƒ¡áƒ”ბáƒáƒ“ი მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ები ვერ მáƒáƒ˜áƒ«áƒ”ბნáƒ.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ თქვენი დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების ისტáƒáƒ áƒ˜áƒ˜áƒ¡, ქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რების, ქეშისრდრსხვრკáƒáƒœáƒ¢áƒ”ნტის გáƒáƒ¡áƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბლáƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ Tab, შემდეგ კი Enter-ს</translation>
<translation id="2650446666397867134">წვდáƒáƒ›áƒ ფáƒáƒ˜áƒšáƒ–ე áƒáƒ™áƒ áƒ«áƒáƒšáƒ£áƒšáƒ˜áƒ</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">ხელáƒáƒ®áƒšáƒ გáƒáƒ¨áƒ•áƒ”ბáƒ</translation>
<translation id="2803306138276472711">Google-ის უსáƒáƒ¤áƒ áƒ—ხრდáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების ფუნქციáƒáƒ› <ph name="BEGIN_LINK" />áƒáƒ¦áƒ›áƒáƒáƒ©áƒ˜áƒœáƒ სáƒáƒ–იáƒáƒœáƒ პრáƒáƒ’რáƒáƒ›áƒ<ph name="END_LINK" /> <ph name="SITE" />-ზე. ზáƒáƒ’ჯერ ნáƒáƒ áƒ›áƒáƒšáƒ£áƒ áƒ˜ დრუსáƒáƒ¤áƒ áƒ—ხრვებსáƒáƒ˜áƒ¢áƒ”ბი ინფიცირდებრსáƒáƒ–იáƒáƒœáƒ პრáƒáƒ’რáƒáƒ›áƒ”ბით.</translation>
<translation id="2807052079800581569">სურáƒáƒ—ის Y პáƒáƒ–იციáƒ</translation>
+<translation id="2820957248982571256">მიმდინáƒáƒ áƒ”áƒáƒ‘ს სკáƒáƒœáƒ˜áƒ áƒ”ბáƒ...</translation>
<translation id="2824775600643448204">მისáƒáƒ›áƒáƒ áƒ—ი დრძიების ზáƒáƒšáƒ˜</translation>
<translation id="2826760142808435982">კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜ დáƒáƒ¨áƒ˜áƒ¤áƒ áƒ£áƒšáƒ˜áƒ დრáƒáƒ•áƒ—ენტიფიცირებულირ<ph name="CIPHER" />-ის გáƒáƒ›áƒáƒ§áƒ”ნებით, იგი იყენებს <ph name="KX" />-ს, რáƒáƒ’áƒáƒ áƒª კáƒáƒ“ის გáƒáƒªáƒ•áƒšáƒ˜áƒ¡ მექáƒáƒœáƒ˜áƒ–მს.</translation>
<translation id="2835170189407361413">ფáƒáƒ áƒ›áƒ˜áƒ¡ გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒ</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">Invite (კáƒáƒœáƒ•áƒ”რტი)</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="2859806420264540918">áƒáƒ› სáƒáƒ˜áƒ¢áƒ–ე ნáƒáƒ©áƒ•áƒ”ნებირმáƒáƒ›áƒáƒ‘ეზრებელი áƒáƒœ შეცდáƒáƒ›áƒáƒ¨áƒ˜ შემყვáƒáƒœáƒ˜ რეკლáƒáƒ›áƒ.</translation>
+<translation id="287596039013813457">მეგáƒáƒ‘რული</translation>
+<translation id="2876489322757410363">გáƒáƒ áƒ” áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ— გáƒáƒ“áƒáƒ®áƒ“ის შემთხვევáƒáƒ¨áƒ˜, ინკáƒáƒ’ნიტრრეჟიმიდáƒáƒœ გáƒáƒ®áƒ•áƒáƒšáƒ—. გსურთ გáƒáƒ’რძელებáƒ?</translation>
<translation id="2878197950673342043">დáƒáƒ™áƒ”ცვრპáƒáƒ¡áƒ¢áƒ”რის ფáƒáƒ áƒ›áƒ˜áƒ—</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ფáƒáƒœáƒ¯áƒ áƒ˜áƒ¡ გáƒáƒœáƒšáƒáƒ’ებáƒ</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">C9 (კáƒáƒœáƒ•áƒ”რტი)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბის შემáƒáƒ¬áƒ›áƒ”ბის გáƒáƒ¡áƒáƒ¨áƒ•áƒ”ბáƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ Tab, შემდეგ Enter-ს</translation>
<translation id="3061707000357573562">ჩáƒáƒ¡áƒ¬áƒáƒ áƒ”ბის სერვისი</translation>
-<translation id="3064966200440839136">გáƒáƒ áƒ” áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ˜áƒ— გáƒáƒ“áƒáƒ®áƒ“ის შემთხვევáƒáƒ¨áƒ˜, ინკáƒáƒ’ნიტრრეჟიმიდáƒáƒœ გáƒáƒ›áƒáƒ¡áƒ•áƒšáƒ მáƒáƒ®áƒ“ებáƒ. გსურთ გáƒáƒ’რძელებáƒ?</translation>
<translation id="306573536155379004">თáƒáƒ›áƒáƒ¨áƒ˜ დáƒáƒ˜áƒ¬áƒ§áƒ.</translation>
<translation id="3080254622891793721">გრáƒáƒ¤áƒ˜áƒ™áƒ</translation>
<translation id="3086579638707268289">თქვენს áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒ‘áƒáƒ–ე ვებში მიმდინáƒáƒ áƒ”áƒáƒ‘ს მáƒáƒœáƒ˜áƒ¢áƒáƒ áƒ˜áƒœáƒ’ი</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">თქვენს áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¡ მáƒáƒ áƒ—áƒáƒ•áƒ¡ <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">áƒáƒ¦áƒ“გენáƒ</translation>
<translation id="3162559335345991374">Wi-Fi-მ, რáƒáƒ›áƒ”ლსáƒáƒª თქვენ იყენებთ, შეიძლებრმáƒáƒ˜áƒ—ხáƒáƒ•áƒáƒ¡ თქვენი სტუმრáƒáƒ‘რმის áƒáƒ•áƒ¢áƒáƒ áƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡ გვერდზე.</translation>
-<translation id="3167968892399408617">ყველრინკáƒáƒ’ნიტრჩáƒáƒœáƒáƒ áƒ—ის დáƒáƒ®áƒ£áƒ áƒ•áƒ˜áƒ¡ შემდეგ, თქვენ მიერ ინკáƒáƒ’ნიტრჩáƒáƒœáƒáƒ áƒ—ების მეშვეáƒáƒ‘ით მáƒáƒœáƒáƒ®áƒ£áƒšáƒ”ბული გვერდები áƒáƒ  დáƒáƒ áƒ©áƒ”ბრთქვენი ბრáƒáƒ£áƒ–ერის ისტáƒáƒ áƒ˜áƒáƒ¨áƒ˜, ქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რების სáƒáƒªáƒáƒ•áƒ¨áƒ˜ თუ ძიების ისტáƒáƒ áƒ˜áƒáƒ¨áƒ˜. თუმცáƒ, თქვენ მიერ ჩáƒáƒ›áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ული ფáƒáƒ˜áƒšáƒ”ბი თუ შექმნილი სáƒáƒœáƒ˜áƒ¨áƒœáƒ”ები მáƒáƒ˜áƒœáƒª შეინáƒáƒ®áƒ”ბáƒ.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">კუნძული</translation>
<translation id="3176929007561373547">შეáƒáƒ›áƒáƒ¬áƒ›áƒ”თ თქვენი პრáƒáƒ¥áƒ¡áƒ˜áƒ¡ პáƒáƒ áƒáƒ›áƒ”ტრები, áƒáƒœ დáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ“ით ქსელის áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ¡, რáƒáƒ—áƒ
@@ -593,10 +608,12 @@
<translation id="3229041911291329567">თქვენი მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ისრდრბრáƒáƒ£áƒ–ერის ვერსიების ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ</translation>
<translation id="323107829343500871">შეიყვáƒáƒœáƒ”თ <ph name="CREDIT_CARD" />-ის CVC</translation>
<translation id="3234666976984236645">áƒáƒ› სáƒáƒ˜áƒ¢áƒ–ე ყáƒáƒ•áƒ”ლთვის áƒáƒ¦áƒ›áƒáƒáƒ©áƒ˜áƒœáƒáƒ¡ მნიშვნელáƒáƒ•áƒáƒœáƒ˜ შინáƒáƒáƒ áƒ¡áƒ˜</translation>
+<translation id="3249845759089040423">სáƒáƒ¡áƒ˜áƒáƒ›áƒáƒ•áƒœáƒ</translation>
<translation id="3252266817569339921">ფრáƒáƒœáƒ’ული</translation>
<translation id="3266793032086590337">მნიშვნელáƒáƒ‘რ(კáƒáƒœáƒ¤áƒšáƒ˜áƒ¥áƒ¢áƒ¨áƒ˜)</translation>
<translation id="3268451620468152448">გáƒáƒ®áƒ¡áƒœáƒ˜áƒšáƒ˜ ჩáƒáƒœáƒáƒ áƒ—ები</translation>
<translation id="3270847123878663523">გáƒáƒ“áƒáƒšáƒáƒ’ების &amp;მáƒáƒ¥áƒ›áƒ”დების გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბáƒáƒ¡ ითხáƒáƒ•áƒ¡</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">თქვენმრáƒáƒ áƒ’áƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒáƒ› (<ph name="ENROLLMENT_DOMAIN" />) მითითებულ ვებსáƒáƒ˜áƒ¢áƒ”ბს გáƒáƒ£áƒ’ზáƒáƒ•áƒœáƒ გáƒáƒ áƒ™áƒ•áƒ”ული ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ, რáƒáƒ’áƒáƒ áƒ˜áƒªáƒáƒ პáƒáƒ áƒáƒ›áƒ”ტრები თუ წესები.</translation>
<translation id="3282497668470633863">ბáƒáƒ áƒáƒ—ზე სáƒáƒ®áƒ”ლის დáƒáƒ›áƒáƒ¢áƒ”ბáƒ</translation>
@@ -649,6 +666,7 @@
<translation id="3428151540071562330">„DnsOverHttpsTemplates“-ში სერვერების შáƒáƒ‘ლáƒáƒœáƒ”ბის რáƒáƒ›áƒ“ენიმე URI áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜áƒ დრáƒáƒ  იქნებრგáƒáƒ›áƒáƒ§áƒ”ნებული.</translation>
<translation id="3431636764301398940">ბáƒáƒ áƒáƒ—ის áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე შენáƒáƒ®áƒ•áƒ</translation>
<translation id="3432601291244612633">გვერდის დáƒáƒ®áƒ£áƒ áƒ•áƒ</translation>
+<translation id="3435738964857648380">უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბáƒ</translation>
<translation id="3435896845095436175">ჩáƒáƒ áƒ—ვáƒ</translation>
<translation id="3438829137925142401">თქვენს Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜ შენáƒáƒ®áƒ£áƒšáƒ˜ პáƒáƒ áƒáƒšáƒ”ბის გáƒáƒ›áƒáƒ§áƒ”ნებáƒ</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -691,7 +709,10 @@
<translation id="3584299510153766161">áƒáƒ áƒ›áƒáƒ’áƒáƒ“ გáƒáƒ®áƒ•áƒ áƒ”ტრქვემáƒáƒ—</translation>
<translation id="3586931643579894722">დეტáƒáƒšáƒ”ბის დáƒáƒ›áƒáƒšáƒ•áƒ</translation>
<translation id="3587738293690942763">შუáƒ</translation>
+<translation id="3590643883886679995">ინკáƒáƒ’ნიტრრეჟიმიდáƒáƒœ გáƒáƒ¡áƒ•áƒšáƒ˜áƒ¡ შემდეგ სისტემáƒáƒ¨áƒ˜ შესვლის მáƒáƒœáƒáƒªáƒ”მები áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე შეინáƒáƒ®áƒ”ბáƒ.</translation>
+<translation id="359126217934908072">თვე/წელი:</translation>
<translation id="3592413004129370115">Italian (კáƒáƒœáƒ•áƒ”რტი)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{თქვენი ჯგუფის გáƒáƒ“áƒáƒ§áƒ”ნებრნებისმიერ დრáƒáƒ¡ შეგიძლიáƒáƒ—. áƒáƒ®áƒáƒš ჯგუფში გáƒáƒ¬áƒ”ვრიáƒáƒœáƒ”ბს დáƒáƒáƒ®áƒšáƒáƒ”ბით ერთი დღე სჭირდებáƒ.}=1{თქვენი ჯგუფის გáƒáƒ“áƒáƒ§áƒ”ნებრნებისმიერ დრáƒáƒ¡ შეგიძლიáƒáƒ—. áƒáƒ®áƒáƒš ჯგუფში გáƒáƒ¬áƒ”ვრიáƒáƒœáƒ”ბს დáƒáƒáƒ®áƒšáƒáƒ”ბით ერთი დღე სჭირდებáƒ.}other{თქვენი ჯგუფის გáƒáƒ“áƒáƒ§áƒ”ნებრნებისმიერ დრáƒáƒ¡ შეგიძლიáƒáƒ—. áƒáƒ®áƒáƒš ჯგუფში გáƒáƒ¬áƒ”ვრიáƒáƒœáƒ”ბს დáƒáƒáƒ®áƒšáƒáƒ”ბით {NUM_DAYS} დღე სჭირდებáƒ.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ დáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜áƒ თქვენი áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ˜áƒ¡ მიერ</translation>
<translation id="3608932978122581043">მიწáƒáƒ“ების áƒáƒ áƒ˜áƒ”ნტáƒáƒªáƒ˜áƒ</translation>
@@ -700,13 +721,13 @@
<translation id="3615877443314183785">შეიყვáƒáƒœáƒ”თ მáƒáƒ¥áƒ›áƒ”დების ვáƒáƒ“ის გáƒáƒ¡áƒ•áƒšáƒ˜áƒ¡ სწáƒáƒ áƒ˜ თáƒáƒ áƒ˜áƒ¦áƒ˜</translation>
<translation id="36224234498066874">დáƒáƒ—. მáƒáƒœáƒáƒªáƒ”მების გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒâ€¦</translation>
<translation id="362276910939193118">სრული ისტáƒáƒ áƒ˜áƒ˜áƒ¡ ნáƒáƒ®áƒ•áƒ</translation>
-<translation id="3625635938337243871">ინკáƒáƒ’ნიტრრეჟიმიდáƒáƒœ გáƒáƒ¡áƒ•áƒšáƒ˜áƒ¡ შემდეგ სისტემáƒáƒ¨áƒ˜ შესვლის მáƒáƒœáƒáƒªáƒ”მები áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე შეინáƒáƒ®áƒ”ბáƒ.</translation>
<translation id="3630155396527302611">თუ ის უკვე მითითებულიáƒ, რáƒáƒ’áƒáƒ áƒª ქსელზე წვდáƒáƒ›áƒ˜áƒ¡ ნებáƒáƒ áƒ—ვის მქáƒáƒœáƒ” პრáƒáƒ’რáƒáƒ›áƒ, ცáƒáƒ“ეთ
მისი სიიდáƒáƒœ áƒáƒ›áƒáƒ¨áƒšáƒ დრხელáƒáƒ®áƒšáƒ დáƒáƒ›áƒáƒ¢áƒ”ბáƒ.</translation>
<translation id="3630699740441428070">თქვენი ქსელის კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜ კáƒáƒœáƒ¤áƒ˜áƒ’ურირებულირáƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ”ბის მიერ, რáƒáƒª სáƒáƒ¨áƒ£áƒáƒšáƒ”ბáƒáƒ¡ áƒáƒ«áƒšáƒ”ვთ, იხილáƒáƒœ თქვენი ქსელის ტრáƒáƒ¤áƒ˜áƒ™áƒ˜, მáƒáƒ— შáƒáƒ áƒ˜áƒ¡, თქვენ მიერ მáƒáƒœáƒáƒ®áƒ£áƒšáƒ”ბული ვებსáƒáƒ˜áƒ¢áƒ”ბი.</translation>
<translation id="3631244953324577188">ბიáƒáƒ›áƒ”ტრიული მáƒáƒœáƒáƒªáƒ”მები</translation>
<translation id="3633738897356909127">Chrome-ის გáƒáƒœáƒáƒ®áƒšáƒ”ბის ღილáƒáƒ™áƒ˜, Chrome-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ Chrome-ის გáƒáƒ¡áƒáƒáƒ®áƒšáƒ”ბლáƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ Enter</translation>
<translation id="3634530185120165534">ლáƒáƒœáƒ’áƒáƒ áƒ˜ 5</translation>
+<translation id="3637662659967048211">შეინáƒáƒ®áƒ”თ Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ:</translation>
<translation id="3650584904733503804">წáƒáƒ áƒ›áƒáƒ¢áƒ”ბული შემáƒáƒ¬áƒ›áƒ”ბáƒ</translation>
@@ -747,6 +768,7 @@
<translation id="3781428340399460090">მკვეთრი ვáƒáƒ áƒ“ისფერი</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ები</translation>
+<translation id="3787675388804467730">ვირტუáƒáƒšáƒ£áƒ áƒ˜ ბáƒáƒ áƒáƒ—ის ნáƒáƒ›áƒ”რი</translation>
<translation id="3787705759683870569">ვáƒáƒ“ის გáƒáƒ¡áƒ•áƒšáƒ˜áƒ¡ თáƒáƒ áƒ˜áƒ¦áƒ˜: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">ზáƒáƒ›áƒ 16</translation>
<translation id="3789841737615482174">ინსტáƒáƒšáƒáƒªáƒ˜áƒ</translation>
@@ -766,6 +788,7 @@
<translation id="3841184659773414994">ფáƒáƒ˜áƒšáƒ”ბის დáƒáƒ›áƒ›áƒ£áƒ¨áƒáƒ•áƒ”ბლები</translation>
<translation id="385051799172605136">უკáƒáƒœ</translation>
<translation id="3858027520442213535">გáƒáƒœáƒáƒ®áƒšáƒ”ბის თáƒáƒ áƒ˜áƒ¦áƒ˜ დრდრáƒ</translation>
+<translation id="3881478300875776315">ნáƒáƒ™áƒšáƒ”ბი ხáƒáƒ–ის ჩვენებáƒ</translation>
<translation id="3884278016824448484">კáƒáƒœáƒ¤áƒšáƒ˜áƒ¥áƒ¢áƒ£áƒ áƒ˜ მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის იდენტიფიკáƒáƒ¢áƒáƒ áƒ˜</translation>
<translation id="3885155851504623709">სáƒáƒ›áƒáƒ¥áƒáƒšáƒáƒ¥áƒ áƒáƒšáƒ¥áƒ˜</translation>
<translation id="388632593194507180">áƒáƒ¦áƒ›áƒáƒ©áƒ”ნილირმáƒáƒœáƒ˜áƒ¢áƒáƒ áƒ˜áƒœáƒ’ი</translation>
@@ -791,6 +814,7 @@
<translation id="397105322502079400">áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒáƒ‘ს…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> დáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜áƒ</translation>
<translation id="3973357910713125165">Chrome-ის უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბის შემáƒáƒ¬áƒ›áƒ”ბის გáƒáƒ¨áƒ•áƒ”ბის ღილáƒáƒ™áƒ˜, Chrome-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბის შემáƒáƒ¬áƒ›áƒ”ბის გáƒáƒ¡áƒáƒ¨áƒ•áƒ”ბáƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ Enter</translation>
+<translation id="3986705137476756801">პირდáƒáƒžáƒ˜áƒ áƒ˜ სუბტიტრების დრáƒáƒ”ბით გáƒáƒ›áƒáƒ áƒ—ვáƒ</translation>
<translation id="3987405730340719549">Chrome-მრდáƒáƒáƒ“გინáƒ, რáƒáƒ› ეს სáƒáƒ˜áƒ¢áƒ˜ შეიძლებრიყáƒáƒ¡ ყáƒáƒšáƒ‘ი áƒáƒœ თáƒáƒ¦áƒšáƒ˜áƒ—ური.
თუ თვლით, რáƒáƒ› ეს შეცდáƒáƒ›áƒáƒ, ეწვიეთ ვებგვერდს https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -882,13 +906,14 @@
<translation id="4275830172053184480">გáƒáƒ“áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ეთ თქვენი მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒ</translation>
<translation id="4277028893293644418">პáƒáƒ áƒáƒšáƒ˜áƒ¡ გáƒáƒ“áƒáƒ§áƒ”ნებáƒ</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ეს ბáƒáƒ áƒáƒ—ი შეინáƒáƒ®áƒ თქვენს Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜}other{ეს ბáƒáƒ áƒáƒ—ები შეინáƒáƒ®áƒ თქვენს Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜}}</translation>
+<translation id="4287885627794386150">áƒáƒ™áƒ›áƒáƒ§áƒáƒ¤áƒ˜áƒšáƒ”ბს სáƒáƒªáƒ“ელი ვერსიის მáƒáƒ—ხáƒáƒ•áƒœáƒ”ბს, მáƒáƒ’რáƒáƒ› გáƒáƒ£áƒáƒ¥áƒ¢áƒ˜áƒ£áƒ áƒ”ბელიáƒ</translation>
<translation id="4297502707443874121">ესკიზი გვერდისთვის <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">გáƒáƒ¨áƒšáƒ</translation>
<translation id="4300675098767811073">მრáƒáƒ•áƒšáƒáƒ“ გáƒáƒ®áƒ•áƒ áƒ”ტრმáƒáƒ áƒ¯áƒ•áƒœáƒ˜áƒ•</translation>
<translation id="4302514097724775343">სáƒáƒ—áƒáƒ›áƒáƒ¨áƒáƒ“ შეეხეთ დინáƒáƒ–áƒáƒ•áƒ áƒ¡</translation>
<translation id="4302965934281694568">Chou3 (კáƒáƒœáƒ•áƒ”რტი)</translation>
<translation id="4305666528087210886">თქვენს ფáƒáƒ˜áƒšáƒ–ე წვდáƒáƒ›áƒ ვერ მáƒáƒ®áƒ”რხდáƒ</translation>
-<translation id="4305817255990598646">გáƒáƒ“áƒáƒ áƒ—ვáƒ</translation>
+<translation id="4306529830550717874">გსურთ, შეინáƒáƒ®áƒáƒ— მისáƒáƒ›áƒáƒ áƒ—ი?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">დáƒáƒ‘ლáƒáƒ™áƒ•áƒ (ნáƒáƒ’ულისხმევი)</translation>
<translation id="4314815835985389558">სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡ მáƒáƒ áƒ—ვáƒ</translation>
@@ -915,6 +940,7 @@
<translation id="4377125064752653719">თქვენ სცáƒáƒ“ეთ <ph name="DOMAIN" />-თáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბáƒ, მáƒáƒ’რáƒáƒ› გáƒáƒ›áƒªáƒ”მმრგáƒáƒáƒ£áƒ¥áƒ›áƒ სერვერის მიერ წáƒáƒ áƒ›áƒáƒ“გენილი სერტიფიკáƒáƒ¢áƒ˜. ეს ნიშნáƒáƒ•áƒ¡, რáƒáƒ› áƒáƒ  უნდრენდáƒáƒ— სერვერის მიერ წáƒáƒ áƒ›áƒáƒ“გენილ მტკიცებულებებს. შესáƒáƒ«áƒšáƒáƒ, თქვენ áƒáƒ®áƒáƒ áƒªáƒ˜áƒ”ლებთ კáƒáƒ›áƒ£áƒœáƒ˜áƒ™áƒáƒªáƒ˜áƒáƒ¡ თáƒáƒ•áƒ“áƒáƒ›áƒ¡áƒ®áƒ›áƒ”ლთáƒáƒœ.</translation>
<translation id="4378154925671717803">ტელეფáƒáƒœáƒ˜</translation>
<translation id="4390472908992056574">კიდეების გáƒáƒ“áƒáƒ•áƒ¡áƒ”ბáƒ</translation>
+<translation id="4406883609789734330">áƒáƒ•áƒ¢áƒáƒ¡áƒ£áƒ‘ტიტრები</translation>
<translation id="4406896451731180161">ძიების შედეგები</translation>
<translation id="4408413947728134509">ქუქი-ჩáƒáƒœáƒáƒ¬áƒ”რები <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">თქვენ ეს-ესáƒáƒ შეიყვáƒáƒœáƒ”თ პáƒáƒ áƒáƒšáƒ˜ შეცდáƒáƒ›áƒáƒ¨áƒ˜ შემყვáƒáƒœ სáƒáƒ˜áƒ¢áƒ–ე. Chrome გირჩევთ, áƒáƒ®áƒšáƒáƒ•áƒ” გáƒáƒ“áƒáƒ®áƒ•áƒ˜áƒ“ეთ <ph name="WEBSITE_1" />-ზე, <ph name="WEBSITE_2" />-ზე, <ph name="WEBSITE_3" />-სრდრსხვრსáƒáƒ˜áƒ¢áƒ”ბზე, სáƒáƒ“áƒáƒª áƒáƒ› პáƒáƒ áƒáƒšáƒ¡ იყენებთ, შემდეგ კი შეცვáƒáƒšáƒáƒ— ის.</translation>
@@ -927,7 +953,6 @@
<translation id="4435702339979719576">ღირბáƒáƒ áƒáƒ—ი)</translation>
<translation id="443673843213245140">პრáƒáƒ¥áƒ¡áƒ˜áƒ¡ გáƒáƒ›áƒáƒ§áƒ”ნებრგáƒáƒ›áƒáƒ áƒ—ულიáƒ, მáƒáƒ’რáƒáƒ› მითითებულირპრáƒáƒ¥áƒ¡áƒ˜áƒ¡ დეტáƒáƒšáƒ£áƒ áƒ˜ კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ.</translation>
<translation id="4464826014807964867">ვებსáƒáƒ˜áƒ¢áƒ”ბი, რáƒáƒ›áƒšáƒ”ბსáƒáƒª თქვენი áƒáƒ áƒ’áƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡áƒ’áƒáƒœ მიღებული áƒáƒ¥áƒ•áƒ¡ გáƒáƒ áƒ™áƒ•áƒ”ული ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ</translation>
-<translation id="4466881336512663640">ფáƒáƒ áƒ›áƒáƒ¨áƒ˜ შეტáƒáƒœáƒ˜áƒšáƒ˜ ცვლილებები დáƒáƒ˜áƒ™áƒáƒ áƒ’ებáƒ. ნáƒáƒ›áƒ“ვილáƒáƒ“ გსურთ გáƒáƒ’რძელებáƒ?</translation>
<translation id="4476953670630786061">ეს ფáƒáƒ áƒ›áƒ áƒáƒ  áƒáƒ áƒ˜áƒ¡ დáƒáƒªáƒ£áƒšáƒ˜. áƒáƒ•áƒ¢áƒáƒ›áƒáƒ¢áƒ£áƒ áƒ˜ შევსებრგáƒáƒ›áƒáƒ˜áƒ áƒ—áƒ.</translation>
<translation id="4477350412780666475">შემდეგი ჩáƒáƒœáƒáƒ¬áƒ”რი</translation>
<translation id="4482953324121162758">ეს გვერდი áƒáƒ  ითáƒáƒ áƒ’მნებáƒ.</translation>
@@ -939,7 +964,7 @@
<translation id="4506176782989081258">შეცდáƒáƒ›áƒ დáƒáƒ›áƒáƒ¬áƒ›áƒ”ბისáƒáƒ¡: <ph name="VALIDATION_ERROR" /></translation>
<translation id="4506599922270137252">სისტემის áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ—áƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბáƒ</translation>
<translation id="450710068430902550">áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ—áƒáƒœ გáƒáƒ–იáƒáƒ áƒ”ბáƒ</translation>
-<translation id="4508814173490746936">Touch ID-ის გáƒáƒ›áƒáƒ§áƒ”ნებრვერ მáƒáƒ®áƒ”რხდáƒ</translation>
+<translation id="4508814173490746936">Touch ID-ს გáƒáƒ›áƒáƒ§áƒ”ნებრვერ მáƒáƒ®áƒ”რხდáƒ</translation>
<translation id="4509074745930862522"><ph name="TRANSLATE_FOCUSED_FRIENDLY_MATCH_TEXT" />, áƒáƒ› გვერდის Google Translate-ით სáƒáƒ—áƒáƒ áƒ’მნáƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ Tab, შემდეგ კი Enter-ს</translation>
<translation id="4510487217173779431">Chou4 (კáƒáƒœáƒ•áƒ”რტი)</translation>
<translation id="4515275063822566619">ბáƒáƒ áƒáƒ—ებისრდრმისáƒáƒ›áƒáƒ áƒ—ების შესáƒáƒ®áƒ”ბ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ მიღებულირChrome-იდáƒáƒœ დრთქვენი Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ“áƒáƒœ (<ph name="ACCOUNT_EMAIL" />). მáƒáƒ—ი მáƒáƒ áƒ—ვრშეგიძლიáƒáƒ— <ph name="BEGIN_LINK" />პáƒáƒ áƒáƒ›áƒ”ტრებში<ph name="END_LINK" />.</translation>
@@ -961,6 +986,7 @@
<translation id="4594403342090139922">წáƒáƒ¨áƒšáƒ˜áƒ¡ &amp;მáƒáƒ¥áƒ›áƒ”დების გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ</translation>
<translation id="4597348597567598915">ზáƒáƒ›áƒ 8</translation>
<translation id="4600854749408232102">C6/C5 (კáƒáƒœáƒ•áƒ”რტი)</translation>
+<translation id="4606870351894164739">გáƒáƒ•áƒšáƒ”ნის მქáƒáƒœáƒ”</translation>
<translation id="4628948037717959914">ფáƒáƒ¢áƒ</translation>
<translation id="4631649115723685955">ქეშბექი მიბმულიáƒ</translation>
<translation id="4636930964841734540">ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ</translation>
@@ -980,6 +1006,7 @@
<translation id="4691835149146451662">Architecture-A (კáƒáƒœáƒ•áƒ”რტი)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">გვერდითი</translation>
+<translation id="4702656508969495934">ნáƒáƒ©áƒ•áƒ”ნებირáƒáƒ•áƒ¢áƒáƒ¡áƒ£áƒ‘ტიტრი, ფáƒáƒ™áƒ£áƒ¡áƒ˜áƒ áƒ”ბისთვის გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნეთ ფáƒáƒœáƒ¯áƒ áƒ”ბის გáƒáƒ“áƒáƒ›áƒ áƒ—ველი</translation>
<translation id="4708268264240856090">თქვენი კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜ შეფერხდáƒ</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows-ის ქსელის დიáƒáƒ’ნáƒáƒ¡áƒ¢áƒ˜áƒ™áƒ˜áƒ¡ ხელსáƒáƒ¬áƒ§áƒáƒ¡ გáƒáƒ¨áƒ•áƒ”ბáƒ<ph name="END_LINK" /></translation>
@@ -993,6 +1020,7 @@
<translation id="4738601419177586157">„<ph name="TEXT" />“-ის ძიების შემáƒáƒ—áƒáƒ•áƒáƒ–ებáƒ</translation>
<translation id="4742407542027196863">პáƒáƒ áƒáƒšáƒ”ბის მáƒáƒ áƒ—ვáƒâ€¦</translation>
<translation id="4744603770635761495">შესრულებáƒáƒ“ი მისáƒáƒ›áƒáƒ áƒ—ი</translation>
+<translation id="4749011317274908093">თქვენ გáƒáƒ“áƒáƒ®áƒ•áƒ”დით ინკáƒáƒ’ნიტრრეჟიმზე</translation>
<translation id="4750917950439032686">თქვენი ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ (მáƒáƒ’áƒáƒšáƒ˜áƒ—áƒáƒ“, პáƒáƒ áƒáƒšáƒ”ბი áƒáƒœ სáƒáƒ™áƒ áƒ”დიტრბáƒáƒ áƒáƒ—ების ნáƒáƒ›áƒ áƒ”ბი) áƒáƒ› სáƒáƒ˜áƒ¢áƒ–ე კáƒáƒœáƒ¤áƒ˜áƒ“ენციáƒáƒšáƒ£áƒ áƒáƒ“ გáƒáƒ˜áƒ’ზáƒáƒ•áƒœáƒ”ბáƒ.</translation>
<translation id="4756388243121344051">&amp;ისტáƒáƒ áƒ˜áƒ</translation>
<translation id="4758311279753947758">სáƒáƒ™áƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ დáƒáƒ›áƒáƒ¢áƒ”ბáƒ</translation>
@@ -1022,6 +1050,8 @@
<translation id="4813512666221746211">ქსელის შეცდáƒáƒ›áƒ</translation>
<translation id="4816492930507672669">მáƒáƒáƒ áƒ’ეთ გვერდს</translation>
<translation id="4819347708020428563">გსურთ áƒáƒœáƒáƒ¢áƒáƒªáƒ˜áƒ”ბის რედáƒáƒ¥áƒ¢áƒ˜áƒ áƒ”ბრნáƒáƒ’ულისხმევ ხედში?</translation>
+<translation id="4825507807291741242">ძლიერი</translation>
+<translation id="4838327282952368871">áƒáƒ áƒáƒáƒ›áƒ¥áƒ•áƒ”ყნიური</translation>
<translation id="484462545196658690">áƒáƒ•áƒ¢áƒáƒ›áƒáƒ¢áƒ£áƒ áƒ˜</translation>
<translation id="4850886885716139402">გáƒáƒ“áƒáƒ®áƒ”დვáƒ</translation>
<translation id="485316830061041779">გერმáƒáƒœáƒ£áƒšáƒ˜</translation>
@@ -1158,6 +1188,7 @@
<translation id="5314967030527622926">ბუკლეტის შემქმნელი</translation>
<translation id="5316812925700871227">სáƒáƒáƒ—ის ისრის სáƒáƒ¬áƒ˜áƒœáƒáƒáƒ¦áƒ›áƒ“ეგáƒáƒ“ შემáƒáƒ¢áƒ áƒ˜áƒáƒšáƒ”ბáƒ</translation>
<translation id="5317780077021120954">შენáƒáƒ®áƒ•áƒ</translation>
+<translation id="5321288445143113935">გáƒáƒ¨áƒšáƒ˜áƒšáƒ˜</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> / <ph name="NUM_MATCHES" />-დáƒáƒœ</translation>
<translation id="5324080437450482387">სáƒáƒ™áƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ áƒáƒ áƒ©áƒ”ვáƒ</translation>
<translation id="5327248766486351172">სáƒáƒ®áƒ”ლი</translation>
@@ -1165,11 +1196,13 @@
<translation id="5332219387342487447">მიწáƒáƒ“ების მეთáƒáƒ“ი</translation>
<translation id="5333022057423422993">თქვენ მიერ áƒáƒ®áƒšáƒáƒ®áƒáƒœ გáƒáƒ›áƒáƒ§áƒ”ნებული პáƒáƒ áƒáƒšáƒ˜ Chrome-მრგáƒáƒŸáƒáƒœáƒ˜áƒš მáƒáƒœáƒáƒªáƒ”მებში იპáƒáƒ•áƒ. თქვენი áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ”ბის დáƒáƒªáƒ•áƒ˜áƒ¡ მიზნით, გირჩევთ, შეáƒáƒ›áƒáƒ¬áƒ›áƒáƒ— თქვენი შენáƒáƒ®áƒ£áƒšáƒ˜ პáƒáƒ áƒáƒšáƒ”ბი.</translation>
<translation id="5334013548165032829">სისტემის დეტáƒáƒšáƒ£áƒ áƒ˜ ჟურნáƒáƒšáƒ”ბი</translation>
+<translation id="5334145288572353250">გსურთ, შეინáƒáƒ®áƒáƒ— მისáƒáƒ›áƒáƒ áƒ—ი?</translation>
<translation id="5340250774223869109">áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ დáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜áƒ</translation>
<translation id="534295439873310000">NFC მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ები</translation>
<translation id="5344579389779391559">áƒáƒ› გვერდმრშეიძლებრდáƒáƒ’áƒáƒ™áƒ˜áƒ¡áƒ áƒáƒ— თáƒáƒœáƒ®áƒ˜áƒ¡ გáƒáƒ“áƒáƒ®áƒ“áƒ</translation>
<translation id="5355557959165512791"><ph name="SITE" />-ზე შესვლრáƒáƒ›áƒŸáƒáƒ›áƒáƒ“ ვერ მáƒáƒ®áƒ”რხდებáƒ, რáƒáƒ“გáƒáƒœ მისი სერტიფიკáƒáƒ¢áƒ˜ გáƒáƒ£áƒ¥áƒ›áƒ“áƒ. ქსელის შეცდáƒáƒ›áƒ”ბი დრმáƒáƒ¡áƒ–ე შეტევები, ჩვეულებრივ, დრáƒáƒ”ბითი მáƒáƒ•áƒšáƒ”ნებირდრშესáƒáƒ‘áƒáƒ›áƒ˜áƒ¡áƒáƒ“, ეს გვერდი შეიძლებრმáƒáƒ’ვიáƒáƒœáƒ”ბით áƒáƒ›áƒ£áƒ¨áƒáƒ•áƒ“ეს.</translation>
<translation id="536296301121032821">ვერ მáƒáƒ®áƒ”რხდრპáƒáƒšáƒ˜áƒ¢áƒ˜áƒ™áƒ˜áƒ¡ პáƒáƒ áƒáƒ›áƒ”ტრების შენáƒáƒ®áƒ•áƒ</translation>
+<translation id="5363309033720083897">თáƒáƒœáƒ›áƒ˜áƒ›áƒ“ევრული პáƒáƒ áƒ¢áƒ˜ დáƒáƒ¨áƒ•áƒ”ბულირთქვენი áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ˜áƒ¡ მიერ</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="5386426401304769735">áƒáƒ› სáƒáƒ˜áƒ¢áƒ˜áƒ¡ სერტიფიკáƒáƒ¢áƒ—რჯáƒáƒ­áƒ•áƒ˜ SHA-1-ის მეშვეáƒáƒ‘ით ხელმáƒáƒ¬áƒ”რილ სერტიფიკáƒáƒ¢áƒ¡ შეიცáƒáƒ•áƒ¡.</translation>
@@ -1178,6 +1211,7 @@
<translation id="5398772614898833570">რეკლáƒáƒ›áƒ დáƒáƒ˜áƒ‘ლáƒáƒ™áƒ</translation>
<translation id="5400836586163650660">ნáƒáƒªáƒ áƒ˜áƒ¡áƒ¤áƒ”რი</translation>
<translation id="540969355065856584">ეს სერვერი ვერ áƒáƒ›áƒ¢áƒ™áƒ˜áƒªáƒ”ბს, რáƒáƒ› ის áƒáƒ áƒ˜áƒ¡ <ph name="DOMAIN" />; მისი უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბის სერთიფიკáƒáƒ¢áƒ˜ áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜áƒ. ეს შეიძლებრიყáƒáƒ¡ გáƒáƒ›áƒáƒ¬áƒ•áƒ”ული áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜ კáƒáƒœáƒ¤áƒ˜áƒ’ურáƒáƒªáƒ˜áƒ˜áƒ— áƒáƒœ თáƒáƒ•áƒ“áƒáƒ›áƒ¡áƒ®áƒ›áƒ”ლის მიერ თქვენი კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜áƒ¡ ხელში ჩáƒáƒ’დებით.</translation>
+<translation id="541143247543991491">ღრუბელი (მთელი სისტემის მáƒáƒ¡áƒ¨áƒ¢áƒáƒ‘ით)</translation>
<translation id="541416427766103491">სტეკერი 4</translation>
<translation id="5421136146218899937">დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების მáƒáƒœáƒáƒªáƒ”მების გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒâ€¦</translation>
<translation id="5426179911063097041"><ph name="SITE" /> ითხáƒáƒ•áƒ¡ თქვენთვის შეტყáƒáƒ‘ინებების გáƒáƒ›áƒáƒ’ზáƒáƒ•áƒœáƒáƒ¡</translation>
@@ -1191,6 +1225,7 @@
<translation id="5455374756549232013">ცუდი წესის დრáƒáƒ˜áƒ¡ áƒáƒ¦áƒœáƒ˜áƒ¨áƒ•áƒœáƒ</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" /> სხვáƒ}other{<ph name="CONTACT_PREVIEW" /> დრ<ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> სხვáƒ}}</translation>
+<translation id="5463625433003343978">მიმდინáƒáƒ áƒ”áƒáƒ‘ს მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ების პáƒáƒ•áƒœáƒâ€¦</translation>
<translation id="5469868506864199649">იტáƒáƒšáƒ˜áƒ£áƒ áƒ˜</translation>
<translation id="5470861586879999274">რედáƒáƒ¥áƒ¢áƒ˜áƒ áƒ”ბის &amp;გáƒáƒ›áƒ”áƒáƒ áƒ”ბáƒ</translation>
<translation id="5478437291406423475">B6/C4 (კáƒáƒœáƒ•áƒ”რტი)</translation>
@@ -1240,7 +1275,6 @@
<translation id="5624120631404540903">პáƒáƒ áƒáƒšáƒ”ბის მáƒáƒ áƒ—ვáƒ</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="563324245173044180">შეცდáƒáƒ›áƒáƒ¨áƒ˜ შემყვáƒáƒœáƒ˜ კáƒáƒœáƒ¢áƒ”ნტი დáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜áƒ.</translation>
<translation id="5644090287519800334">მხáƒáƒ áƒ” 1 — სურáƒáƒ—ის წáƒáƒœáƒáƒªáƒ•áƒšáƒ”ბრX ღერძზე</translation>
@@ -1279,12 +1313,12 @@
<translation id="5785756445106461925">გáƒáƒ áƒ“რáƒáƒ›áƒ˜áƒ¡áƒ, ეს გვერდი შეიცáƒáƒ•áƒ¡ სხვრáƒáƒ áƒáƒ£áƒ¡áƒáƒ¤áƒ áƒ—ხრრესურსებს. áƒáƒ› რესურსების დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რებრგáƒáƒ“áƒáƒªáƒ”მისáƒáƒ¡ სხვრპირებს შეუძლიáƒáƒ—, ხáƒáƒšáƒ თáƒáƒ•áƒ“áƒáƒ›áƒ¡áƒ®áƒ›áƒ”ლს მáƒáƒ—ი მáƒáƒ“იფიკáƒáƒªáƒ˜áƒ გვერდის იერის შეცვლის მიზნით შეუძლიáƒ.</translation>
<translation id="5786044859038896871">გსურთ თქვენი ბáƒáƒ áƒáƒ—ის ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ შევსებáƒ?</translation>
<translation id="578633867165174378">თქვენ მიერ áƒáƒ®áƒšáƒáƒ®áƒáƒœ გáƒáƒ›áƒáƒ§áƒ”ნებული პáƒáƒ áƒáƒšáƒ˜ Chrome-მრგáƒáƒŸáƒáƒœáƒ˜áƒš მáƒáƒœáƒáƒªáƒ”მებში იპáƒáƒ•áƒ. გირჩევთ, áƒáƒ®áƒšáƒáƒ•áƒ” შეცვáƒáƒšáƒáƒ— ეს პáƒáƒ áƒáƒšáƒ˜.</translation>
-<translation id="5798290721819630480">გსურთ ცვლილებების გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ?</translation>
<translation id="5803412860119678065">გსურთ თქვენი <ph name="CARD_DETAIL" />-ის ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ შევსებáƒ?</translation>
<translation id="5804241973901381774">ნებáƒáƒ áƒ—ვები</translation>
<translation id="5804427196348435412">NFC მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ების გáƒáƒ›áƒáƒ§áƒ”ნებáƒ</translation>
<translation id="5810442152076338065">თქვენი კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜ <ph name="DOMAIN" />-თáƒáƒœ დáƒáƒ¨áƒ˜áƒ¤áƒ áƒ£áƒšáƒ˜áƒ შიფრთრმáƒáƒ«áƒ•áƒ”ლებული ნáƒáƒ™áƒ áƒ”ბით.</translation>
<translation id="5813119285467412249">დáƒáƒ›áƒáƒ¢áƒ”ბის &amp;გáƒáƒ›áƒ”áƒáƒ áƒ”ბáƒ</translation>
+<translation id="5817918615728894473">დáƒáƒ¬áƒ§áƒ•áƒ˜áƒšáƒ”ბáƒ</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{გáƒáƒ“áƒáƒ®áƒ“ისáƒáƒ¡ áƒáƒ› ბáƒáƒ áƒáƒ—იდáƒáƒœ თáƒáƒœáƒ®áƒ ჩáƒáƒ›áƒáƒ˜áƒ­áƒ áƒ”ბáƒ, თუმცრმისი ნáƒáƒ›áƒ“ვილი ნáƒáƒ›áƒ”რი áƒáƒ  გáƒáƒ–იáƒáƒ áƒ“ებრáƒáƒ› სáƒáƒ˜áƒ¢áƒ—áƒáƒœ. დáƒáƒ›áƒáƒ¢áƒ”ბითი უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბისთვის შეიქმნებრდრáƒáƒ”ბითი CVC.}other{გáƒáƒ“áƒáƒ®áƒ“ისáƒáƒ¡ თქვენ მიერ áƒáƒ áƒ©áƒ”ული ბáƒáƒ áƒáƒ—იდáƒáƒœ თáƒáƒœáƒ®áƒ ჩáƒáƒ›áƒáƒ˜áƒ­áƒ áƒ”ბáƒ, თუმცრმისი ნáƒáƒ›áƒ“ვილი ნáƒáƒ›áƒ”რი áƒáƒ  გáƒáƒ–იáƒáƒ áƒ“ებრáƒáƒ› სáƒáƒ˜áƒ¢áƒ—áƒáƒœ. დáƒáƒ›áƒáƒ¢áƒ”ბითი უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბისთვის შეიქმნებრდრáƒáƒ”ბითი CVC.}}</translation>
<translation id="5826507051599432481">სáƒáƒ”რთრსáƒáƒ®áƒ”ლი (CN)</translation>
<translation id="5838278095973806738">გირჩევთ, áƒáƒ  შეიყვáƒáƒœáƒáƒ— კáƒáƒœáƒ¤áƒ˜áƒ“ენციáƒáƒšáƒ£áƒ áƒ˜ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ (მáƒáƒ’áƒáƒšáƒ˜áƒ—áƒáƒ“, პáƒáƒ áƒáƒšáƒ”ბი áƒáƒœ სáƒáƒ™áƒ áƒ”დიტრბáƒáƒ áƒáƒ—ების მáƒáƒœáƒáƒªáƒ”მები) áƒáƒ› სáƒáƒ˜áƒ¢áƒ–ე, რáƒáƒ“გáƒáƒœ თáƒáƒ•áƒ“áƒáƒ›áƒ¡áƒ®áƒ›áƒ”ლებს მისი მáƒáƒžáƒáƒ áƒ•áƒ შეუძლიáƒáƒ—.</translation>
@@ -1292,6 +1326,7 @@
<translation id="5855253129151731373">áƒáƒ› სáƒáƒ˜áƒ¢áƒ˜áƒ¡ სერვერის სáƒáƒ®áƒ”ლი ჰგáƒáƒ•áƒ¡ <ph name="LOOKALIKE_DOMAIN" />-ს. თáƒáƒ•áƒ“áƒáƒ›áƒ¡áƒ®áƒ›áƒ”ლები ზáƒáƒ’ჯერ იმიტირებენ სáƒáƒ˜áƒ¢áƒ”ბს დáƒáƒ›áƒ”ნის სáƒáƒ®áƒ”ლში მცირე, რთულáƒáƒ“ შესáƒáƒ›áƒ©áƒœáƒ”ვი ცვლილებების შეტáƒáƒœáƒ˜áƒ—.
თუ თვლით, რáƒáƒ› ეს შეცდáƒáƒ›áƒáƒ, ეწვიეთ ვებგვერდს https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">გáƒáƒ›áƒáƒ áƒ—ვáƒ</translation>
<translation id="5862579898803147654">სტეკერი 8</translation>
<translation id="5863847714970149516">გვერდმáƒ, რáƒáƒ›áƒ”ლზე გáƒáƒ“áƒáƒ¡áƒ•áƒšáƒáƒ¡áƒáƒª áƒáƒžáƒ˜áƒ áƒ”ბთ, შეიძლებრდáƒáƒ’áƒáƒ™áƒ˜áƒ¡áƒ áƒáƒ— თáƒáƒœáƒ®áƒ˜áƒ¡ გáƒáƒ“áƒáƒ®áƒ“áƒ</translation>
<translation id="5866257070973731571">დáƒáƒáƒ›áƒáƒ¢áƒ”თ ტელეფáƒáƒœáƒ˜áƒ¡ ნáƒáƒ›áƒ”რი</translation>
@@ -1308,6 +1343,7 @@
<translation id="5913377024445952699">ეკრáƒáƒœáƒ˜áƒ¡ áƒáƒ¦áƒ‘ეჭდვრდáƒáƒžáƒáƒ£áƒ–დáƒ</translation>
<translation id="59174027418879706">ჩáƒáƒ áƒ—ული</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნებრ1}other{გáƒáƒ›áƒáƒ˜áƒ§áƒ”ნებრ#}}</translation>
<translation id="5921185718311485855">ჩáƒáƒ áƒ—ული</translation>
<translation id="5921639886840618607">გსურთ ბáƒáƒ áƒáƒ—ის შენáƒáƒ®áƒ•áƒ Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜?</translation>
<translation id="5922853866070715753">თითქმის მზáƒáƒ“áƒáƒ</translation>
@@ -1327,6 +1363,7 @@
<translation id="5989320800837274978">áƒáƒ  áƒáƒ áƒ˜áƒ¡ მითითებული áƒáƒ áƒª ფიქსირებული პრáƒáƒ¥áƒ¡áƒ˜ სერვერი, áƒáƒ áƒª .pac სკრიპტის URL.</translation>
<translation id="5992691462791905444">სáƒáƒ˜áƒœáƒŸáƒ˜áƒœáƒ áƒ დáƒáƒ™áƒ”ცვრZ-ის ფáƒáƒ áƒ›áƒ˜áƒ—</translation>
<translation id="6000758707621254961">მáƒáƒ—ხáƒáƒ•áƒœáƒáƒ–ე „<ph name="SEARCH_TEXT" />“ მáƒáƒ˜áƒ«áƒ”ბნრ<ph name="RESULT_COUNT" /> შედეგი</translation>
+<translation id="6006484371116297560">კლáƒáƒ¡áƒ˜áƒ™áƒ£áƒ áƒ˜</translation>
<translation id="6008122969617370890">მიმდევრáƒáƒ‘რN-დáƒáƒœ 1-მდე</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">შეáƒáƒ›áƒáƒ¬áƒ›áƒ”თ თქვენი პáƒáƒ áƒáƒšáƒ”ბი</translation>
@@ -1348,6 +1385,7 @@
<translation id="6045164183059402045">áƒáƒ¬áƒ§áƒáƒ‘ის შáƒáƒ‘ლáƒáƒœáƒ˜</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="6049004884579590341">სრულეკრáƒáƒœáƒ˜áƒáƒœáƒ˜ რეჟიმიდáƒáƒœ გáƒáƒ›áƒáƒ¡áƒáƒ¡áƒ•áƒšáƒ”ლáƒáƒ“ ხáƒáƒœáƒ’რძლივáƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ–ე |<ph name="ACCELERATOR" />|</translation>
<translation id="6049488691372270142">გვერდის მáƒáƒ¬áƒáƒ“ებáƒ</translation>
<translation id="6051221802930200923"><ph name="SITE" />-ზე შესვლრáƒáƒ›áƒŸáƒáƒ›áƒáƒ“ ვერ მáƒáƒ®áƒ”რხდებáƒ, რáƒáƒ“გáƒáƒœ ვებსáƒáƒ˜áƒ¢áƒ˜ იყენებს სერტიფიკáƒáƒ¢áƒ—რმიმáƒáƒ’რებáƒáƒ¡. ქსელის შეცდáƒáƒ›áƒ”ბი დრმáƒáƒ¡áƒ–ე შეტევები, ჩვეულებრივ, დრáƒáƒ”ბითი მáƒáƒ•áƒšáƒ”ნებირდრშესáƒáƒ‘áƒáƒ›áƒ˜áƒ¡áƒáƒ“, ეს გვერდი შეიძლებრმáƒáƒ’ვიáƒáƒœáƒ”ბით áƒáƒ›áƒ£áƒ¨áƒáƒ•áƒ“ეს.</translation>
<translation id="6051898664905071243">გვერდების რáƒáƒáƒ“ენáƒáƒ‘áƒ:</translation>
@@ -1364,6 +1402,7 @@
<translation id="610911394827799129">თქვენს Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜ შეიძლებრინáƒáƒ®áƒ”ბáƒáƒ“ეს სხვრტიპის დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რების ისტáƒáƒ áƒ˜áƒáƒª, რáƒáƒ›áƒ”ლიც ხელმისáƒáƒ¬áƒ•áƒ“áƒáƒ›áƒ˜áƒ მისáƒáƒ›áƒáƒ áƒ—ზე: <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">გáƒáƒªáƒ•áƒšáƒ˜áƒ¡ ბუფერში კáƒáƒžáƒ˜áƒ áƒ”ბული ტექსტისრდრსურáƒáƒ—ების ნáƒáƒ®áƒ•áƒ</translation>
<translation id="6120179357481664955">გსურთ თქვენი UPI ID-ს დáƒáƒ›áƒáƒ®áƒ¡áƒáƒ•áƒ áƒ”ბáƒ?</translation>
+<translation id="6123290840358279103">ვირტუáƒáƒšáƒ£áƒ áƒ˜ ბáƒáƒ áƒáƒ—ის ჩვენებáƒ</translation>
<translation id="6124432979022149706">Chrome Enterprise მáƒáƒ”რთებლები</translation>
<translation id="6146055958333702838">შეáƒáƒ›áƒáƒ¬áƒ›áƒ”თ კáƒáƒ‘ელები დრგáƒáƒ“áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ეთ ყველრრáƒáƒ£áƒ¢áƒ”რი, მáƒáƒ“ემი áƒáƒœ
სხვრქსელური მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒ, რáƒáƒ›áƒ”ლსáƒáƒª იყენებთ.</translation>
@@ -1400,6 +1439,7 @@
<translation id="6289939620939689042">გვერდის ფერი</translation>
<translation id="6290238015253830360">áƒáƒ¥ გáƒáƒ›áƒáƒ©áƒœáƒ“ებრთქვენთვის შემáƒáƒ—áƒáƒ•áƒáƒ–ებული სტáƒáƒ¢áƒ˜áƒ”ბი</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">ბáƒáƒ áƒáƒ—ის დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბის კáƒáƒ“ი (CVC):</translation>
<translation id="6302269476990306341">Google áƒáƒ¡áƒ˜áƒ¡áƒ¢áƒ”ნტი Chrome-ში წყვეტს მუშáƒáƒáƒ‘áƒáƒ¡</translation>
<translation id="6305205051461490394"><ph name="URL" /> მიუწვდáƒáƒ›áƒ”ლიáƒ.</translation>
<translation id="6312113039770857350">ვებგვერდი მიუწვდáƒáƒ›áƒ”ლიáƒ</translation>
@@ -1425,6 +1465,7 @@
<translation id="6390200185239044127">Z-ის ფáƒáƒ áƒ›áƒ˜áƒ— დáƒáƒ™áƒ”ცვრნáƒáƒ®áƒ”ვრáƒáƒ“</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" />-დáƒáƒœ áƒáƒ› მდებáƒáƒ áƒ”áƒáƒ‘áƒáƒ–ე ჩáƒáƒ¡áƒ›áƒ დáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜áƒ áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ˜áƒ¡ წესების მიხედვით</translation>
+<translation id="6398765197997659313">სრულეკრáƒáƒœáƒ˜áƒáƒœáƒ˜ რეჟიმიდáƒáƒœ გáƒáƒ›áƒáƒ¡áƒ•áƒšáƒ</translation>
<translation id="6401136357288658127">ეს წესები მáƒáƒ«áƒ•áƒ”ლდáƒ. სáƒáƒœáƒáƒªáƒ•áƒšáƒáƒ“ უნდრგáƒáƒ›áƒáƒ˜áƒ§áƒ”ნáƒáƒ— <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">სáƒáƒœáƒ˜áƒ¨áƒœáƒ˜áƒ¡ რედáƒáƒ¥áƒ¢áƒ˜áƒ áƒ”ბáƒ</translation>
<translation id="6406765186087300643">C0 (კáƒáƒœáƒ•áƒ”რტი)</translation>
@@ -1437,7 +1478,6 @@
<translation id="6428450836711225518">დáƒáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”თ თქვენი ტელეფáƒáƒœáƒ˜áƒ¡ ნáƒáƒ›áƒ”რი</translation>
<translation id="6433490469411711332">სáƒáƒ™áƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ რედáƒáƒ¥áƒ¢áƒ˜áƒ áƒ”ბáƒ</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" />-მრუáƒáƒ áƒ§áƒ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბáƒ.</translation>
-<translation id="6434309073475700221">გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ</translation>
<translation id="6440503408713884761">იგნáƒáƒ áƒ˜áƒ áƒ”ბული</translation>
<translation id="6443406338865242315">თქვენ მიერ დáƒáƒ˜áƒœáƒ¡áƒ¢áƒáƒšáƒ˜áƒ áƒ”ბული გáƒáƒ¤áƒáƒ áƒ—áƒáƒ”ბები დრდáƒáƒœáƒáƒ›áƒáƒ¢áƒ”ბი</translation>
<translation id="6446163441502663861">Kahu (კáƒáƒœáƒ•áƒ”რტი)</translation>
@@ -1480,6 +1520,7 @@
<translation id="6624427990725312378">სáƒáƒ™áƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ</translation>
<translation id="6626291197371920147">მიუთითეთ ბáƒáƒ áƒáƒ—ის სწáƒáƒ áƒ˜ ნáƒáƒ›áƒ”რი</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ძიებáƒ</translation>
+<translation id="6630043285902923878">მიმდინáƒáƒ áƒ”áƒáƒ‘ს USB მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ების პáƒáƒ•áƒœáƒâ€¦</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒ</translation>
@@ -1495,6 +1536,7 @@
<translation id="6671697161687535275">áƒáƒ›áƒáƒ˜áƒ¨áƒáƒšáƒáƒ¡ ფáƒáƒ áƒ›áƒ”ბისთვის გáƒáƒœáƒ™áƒ£áƒ—ვნილი შემáƒáƒ—áƒáƒ•áƒáƒ–ებრChromium-იდáƒáƒœ?</translation>
<translation id="6685834062052613830">გáƒáƒ›áƒáƒ“ით სისტემიდáƒáƒœ დრდáƒáƒáƒ¡áƒ áƒ£áƒšáƒ”თ მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის დáƒáƒ§áƒ”ნებáƒ</translation>
<translation id="6687335167692595844">შრიფტის ზáƒáƒ›áƒ მáƒáƒ—ხáƒáƒ•áƒœáƒ˜áƒšáƒ˜áƒ</translation>
+<translation id="6688743156324860098">გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒâ€¦</translation>
<translation id="6689249931105087298">ფáƒáƒ áƒ“áƒáƒ‘ითი, შáƒáƒ•áƒ˜ წერტილის შეკუმშვით</translation>
<translation id="6689271823431384964">თქვენს Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜ ბáƒáƒ áƒáƒ—ების შენáƒáƒ®áƒ•áƒáƒ¡ Chrome გთáƒáƒ•áƒáƒ–áƒáƒ‘თ, ვინáƒáƒ˜áƒ“áƒáƒœ შესული ხáƒáƒ áƒ— სისტემáƒáƒ¨áƒ˜. áƒáƒ› ქცევის შეცვლრშეგიძლიáƒáƒ— პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ. ბáƒáƒ áƒáƒ—ის მფლáƒáƒ‘ელის სáƒáƒ®áƒ”ლი მიღებულირთქვენი áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ“áƒáƒœ.</translation>
<translation id="6698381487523150993">შექმნილიáƒ:</translation>
@@ -1510,6 +1552,7 @@
<translation id="6744009308914054259">სáƒáƒœáƒáƒ› კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜áƒ¡ áƒáƒ¦áƒ“გენáƒáƒ¡ ელáƒáƒ“ებით, შეგიძლიáƒáƒ— გáƒáƒ“áƒáƒ®áƒ•áƒ˜áƒ“ეთ ჩáƒáƒ›áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვებზე დრწáƒáƒ˜áƒ™áƒ˜áƒ—ხáƒáƒ— სტáƒáƒ¢áƒ˜áƒ”ბი ხáƒáƒ–გáƒáƒ áƒ”შე რეჟიმში.</translation>
<translation id="6753269504797312559">წესის მნიშვნელáƒáƒ‘áƒ</translation>
<translation id="6757797048963528358">თქვენი მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘რძილის რეჟიმზე გáƒáƒ“áƒáƒ•áƒ˜áƒ“áƒ.</translation>
+<translation id="6767985426384634228">გსურთ, გáƒáƒœáƒáƒáƒ®áƒšáƒáƒ— მისáƒáƒ›áƒáƒ áƒ—ი?</translation>
<translation id="6768213884286397650">Hagaki (ღირბáƒáƒ áƒáƒ—ი)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">იისფერი</translation>
@@ -1532,6 +1575,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome-მრგáƒáƒáƒ›áƒáƒ áƒ¢áƒ˜áƒ•áƒ ეს გვერდი მისი წáƒáƒ™áƒ˜áƒ—ხვის გáƒáƒ¡áƒáƒ˜áƒáƒšáƒ”ბლáƒáƒ“. Chrome-მრთáƒáƒ•áƒ“áƒáƒžáƒ˜áƒ áƒ•áƒ”ლი გვერდი ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—რდáƒáƒ£áƒªáƒ•áƒ”ლი კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜áƒ¡ მეშვეáƒáƒ‘ით.</translation>
<translation id="6891596781022320156">წესის დáƒáƒœáƒ” áƒáƒ  áƒáƒ áƒ˜áƒ¡ მხáƒáƒ áƒ“áƒáƒ­áƒ”რილი.</translation>
+<translation id="6895143722905299846">ვირტუáƒáƒšáƒ£áƒ áƒ˜ ნáƒáƒ›áƒ”რი:</translation>
<translation id="6895330447102777224">თქვენი ბáƒáƒ áƒáƒ—ი დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ“áƒ</translation>
<translation id="6897140037006041989">მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის áƒáƒ’ენტი</translation>
<translation id="6898699227549475383">áƒáƒ áƒ’áƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ (O)</translation>
@@ -1567,10 +1611,10 @@
<translation id="7004583254764674281">Windows Hello-ს გáƒáƒ›áƒáƒ§áƒ”ნებრბáƒáƒ áƒáƒ—ების უფრრსწრáƒáƒ¤áƒáƒ“ დáƒáƒ¡áƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბლáƒáƒ“</translation>
<translation id="7006930604109697472">მáƒáƒ˜áƒœáƒª გáƒáƒ’ზáƒáƒ•áƒœáƒ</translation>
<translation id="7012363358306927923">ჩინეთის UnionPay</translation>
-<translation id="7012404007611495949">ზáƒáƒ›áƒ˜áƒ¡ შეცვლის პáƒáƒ áƒáƒ›áƒ”ტრები</translation>
<translation id="7014741021609395734">მáƒáƒ¡áƒ¨áƒ¢áƒáƒ‘ის დáƒáƒœáƒ”</translation>
<translation id="7016992613359344582">áƒáƒ¦áƒœáƒ˜áƒ¨áƒœáƒ£áƒšáƒ˜ გáƒáƒ“áƒáƒ®áƒ“ები შეიძლებრგáƒáƒœáƒ®áƒáƒ áƒªáƒ˜áƒ”ლდეს ერთჯერáƒáƒ“áƒáƒ“ áƒáƒœ პერიáƒáƒ“ულáƒáƒ“ დრáƒáƒ  იყáƒáƒ¡ áƒáƒ“ვილáƒáƒ“ შესáƒáƒ›áƒ©áƒœáƒ”ვი.</translation>
<translation id="7029809446516969842">პáƒáƒ áƒáƒšáƒ”ბი</translation>
+<translation id="7030436163253143341">სერთიფიკáƒáƒ¢áƒ˜ áƒáƒ  áƒáƒ áƒ˜áƒ¡ მáƒáƒ¥áƒ›áƒ”დი</translation>
<translation id="7031646650991750659">თქვენ მიერ დáƒáƒ˜áƒœáƒ¡áƒ¢áƒáƒšáƒ˜áƒ áƒ”ბული Google Play áƒáƒžáƒ”ბი</translation>
<translation id="7050187094878475250">თქვენ ცდილáƒáƒ‘დით <ph name="DOMAIN" />-თáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბáƒáƒ¡, მáƒáƒ’რáƒáƒ› სერვერის მიერ წáƒáƒ áƒ›áƒáƒ“გენილი სერთიფიკáƒáƒ¢áƒ˜áƒ¡ მáƒáƒ¥áƒ›áƒ”დების პერიáƒáƒ“ი ზედმეტáƒáƒ“ ხáƒáƒœáƒ’რძლივიáƒ, იმისáƒáƒ—ვის რáƒáƒ› სáƒáƒœáƒ“რიყáƒáƒ¡.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{áƒáƒ› ბáƒáƒ áƒáƒ—ის შენáƒáƒ®áƒ•áƒ áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ ვერ მáƒáƒ®áƒ”რხდებáƒ}other{áƒáƒ› ბáƒáƒ áƒáƒ—ების შენáƒáƒ®áƒ•áƒ áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ ვერ მáƒáƒ®áƒ”რხდებáƒ}}</translation>
@@ -1640,12 +1684,14 @@
<translation id="7300012071106347854">კáƒáƒ‘áƒáƒšáƒ¢áƒ˜áƒ¡áƒ¤áƒ”რი</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />“</translation>
<translation id="7304030187361489308">მáƒáƒ¦áƒáƒšáƒ˜</translation>
+<translation id="7305756307268530424">უფრრნელრგáƒáƒ¨áƒ•áƒ”ბáƒ</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">კáƒáƒ•áƒ¨áƒ˜áƒ áƒ—áƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბული დáƒáƒ®áƒ›áƒáƒ áƒ”ბáƒ</translation>
<translation id="7323804146520582233">სექციის „<ph name="SECTION" />“ დáƒáƒ›áƒáƒšáƒ•áƒ</translation>
<translation id="733354035281974745">მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის áƒáƒ“გილáƒáƒ‘რივი áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ¡ უგულებელყáƒáƒ¤áƒ</translation>
<translation id="7333654844024768166">თქვენ ეს-ესáƒáƒ შეიყვáƒáƒœáƒ”თ პáƒáƒ áƒáƒšáƒ˜ შეცდáƒáƒ›áƒáƒ¨áƒ˜ შემყვáƒáƒœ სáƒáƒ˜áƒ¢áƒ–ე. Chromium გირჩევთ, áƒáƒ®áƒšáƒáƒ•áƒ” გáƒáƒ“áƒáƒ®áƒ•áƒ˜áƒ“ეთ <ph name="WEBSITE_1" />-ზე, <ph name="WEBSITE_2" />-ზე, <ph name="WEBSITE_3" />-სრდრსხვრსáƒáƒ˜áƒ¢áƒ”ბზე, სáƒáƒ“áƒáƒª áƒáƒ› პáƒáƒ áƒáƒšáƒ¡ იყენებთ, შემდეგ კი შეცვáƒáƒšáƒáƒ— ის.</translation>
<translation id="7334320624316649418">გáƒáƒ“áƒáƒšáƒáƒ’ების &amp;გáƒáƒ›áƒ”áƒáƒ áƒ”ბáƒ</translation>
+<translation id="7337248890521463931">მეტი ხáƒáƒ–ის ჩვენებáƒ</translation>
<translation id="7337706099755338005">მიუწვდáƒáƒ›áƒ”ლირთქვენი პლáƒáƒ¢áƒ¤áƒáƒ áƒ›áƒ˜áƒ¡áƒ—ვის.</translation>
<translation id="733923710415886693">სერვერის სერტიფიკáƒáƒ¢áƒ˜áƒ¡ გáƒáƒ›áƒáƒ¥áƒ•áƒ”ყნებრსერტიფიკáƒáƒ¢áƒ—რგáƒáƒ›áƒ­áƒ•áƒ˜áƒ áƒ•áƒáƒšáƒáƒ‘ის შესáƒáƒ®áƒ”ბ წესების შესáƒáƒ‘áƒáƒ›áƒ˜áƒ¡áƒáƒ“ áƒáƒ  მáƒáƒ›áƒ®áƒ“áƒáƒ áƒ.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1653,6 +1699,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">ბრძáƒáƒœáƒ”ბის სტრიქáƒáƒœáƒ˜</translation>
<translation id="7359588939039777303">რეკლáƒáƒ›áƒ დáƒáƒ˜áƒ‘ლáƒáƒ™áƒ.</translation>
+<translation id="7363096869660964304">áƒáƒ›áƒ˜áƒ¡ მიუხედáƒáƒ•áƒáƒ“, თქვენ უჩინáƒáƒ áƒ˜ áƒáƒ  ხáƒáƒ áƒ—: ინკáƒáƒ’ნიტრრეჟიმით სáƒáƒ áƒ’ებლáƒáƒ‘რáƒáƒ  მáƒáƒšáƒáƒ•áƒ¡ თქვენ მიერ დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რებულს თქვენი დáƒáƒ›áƒ¡áƒáƒ¥áƒ›áƒ”ბლისგáƒáƒœ, ინტერნეტ სერვისის პრáƒáƒ•áƒáƒ˜áƒ“ერისგáƒáƒœ თუ თქვენ მიერ მáƒáƒœáƒáƒ®áƒ£áƒšáƒ”ბული ვებსáƒáƒ˜áƒ¢áƒ”ბისგáƒáƒœ.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, მისáƒáƒ›áƒáƒ áƒ—ების Chrome-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ დáƒáƒ¡áƒáƒ›áƒáƒ¢áƒ”ბლáƒáƒ“ დრსáƒáƒ›áƒáƒ áƒ—áƒáƒ•áƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ Tab, შემდეგ კი Enter-ს</translation>
<translation id="7365849542400970216">იცáƒáƒ“ეს თქვენ მიერ მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის გáƒáƒ›áƒáƒ§áƒ”ნების შესáƒáƒ®áƒ”ბ?</translation>
<translation id="7372973238305370288">ძიების შედეგი</translation>
@@ -1663,7 +1710,9 @@
<translation id="7378594059915113390">მედიის მáƒáƒ áƒ—ვის სáƒáƒ¨áƒ£áƒáƒšáƒ”ბები</translation>
<translation id="7378627244592794276">áƒáƒ áƒ</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">áƒáƒ  მიესáƒáƒ“áƒáƒ’ებáƒ</translation>
<translation id="7390545607259442187">დáƒáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”თ ბáƒáƒ áƒáƒ—ი</translation>
+<translation id="7392089738299859607">მისáƒáƒ›áƒáƒ áƒ—ის გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ</translation>
<translation id="7399802613464275309">უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბის შემáƒáƒ¬áƒ›áƒ”ბáƒ</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">თქვენი <ph name="DEVICE_NAME" /> მáƒáƒ áƒ—ულიáƒ</translation>
@@ -1678,6 +1727,7 @@
&lt;li&gt;ეწვიეთ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome-ის დáƒáƒ®áƒ›áƒáƒ áƒ”ბის ცენტრს&lt;/a&gt; დრშეიტყვეთ, სáƒáƒ›áƒ£áƒ“áƒáƒ›áƒáƒ“ რáƒáƒ’áƒáƒ  áƒáƒ›áƒáƒ¨áƒáƒšáƒáƒ— პრáƒáƒ’რáƒáƒ›áƒ£áƒšáƒ˜ უზრუნველყáƒáƒ¤áƒ თქვენი კáƒáƒ›áƒžáƒ˜áƒ£áƒ¢áƒ”რიდáƒáƒœ.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">სáƒáƒ§áƒ•áƒáƒ áƒ”ლი</translation>
<translation id="7416351320495623771">პáƒáƒ áƒáƒšáƒ”ბის მáƒáƒ áƒ—ვáƒâ€¦</translation>
<translation id="7419106976560586862">პრáƒáƒ¤áƒ˜áƒšáƒ˜áƒ¡ მისáƒáƒ›áƒáƒ áƒ—ი</translation>
<translation id="7437289804838430631">სáƒáƒ™áƒáƒœáƒ¢áƒáƒ¥áƒ¢áƒ ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ˜áƒ¡ დáƒáƒ›áƒáƒ¢áƒ”ბáƒ</translation>
@@ -1693,7 +1743,7 @@
<translation id="7481312909269577407">გáƒáƒ“áƒáƒ›áƒ˜áƒ¡áƒáƒ›áƒáƒ áƒ—ებáƒ</translation>
<translation id="7485870689360869515">მáƒáƒœáƒáƒªáƒ”მები ვერ მáƒáƒ˜áƒ«áƒ”ბნáƒ.</translation>
<translation id="7495528107193238112">ეს კáƒáƒœáƒ¢áƒ”ნტი დáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜áƒ. დáƒáƒ£áƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ“ით სáƒáƒ˜áƒ¢áƒ˜áƒ¡ მფლáƒáƒ‘ელს áƒáƒ› პრáƒáƒ‘ლემის მáƒáƒ¡áƒáƒ’ვáƒáƒ áƒ”ბლáƒáƒ“.</translation>
-<translation id="7498234416455752244">რედáƒáƒ¥áƒ¢áƒ˜áƒ áƒ”ბის გáƒáƒ’რძელებáƒ</translation>
+<translation id="7498193950643227031">ზáƒáƒ›áƒ˜áƒ¡ შეცვლáƒáƒ›, შესáƒáƒ«áƒšáƒáƒ, გáƒáƒ›áƒáƒ˜áƒ¬áƒ•áƒ˜áƒáƒ¡ მáƒáƒ£áƒšáƒáƒ“ნელი ქცევáƒ. áƒáƒžáƒ”ბის ზáƒáƒ›áƒ˜áƒ¡ შეცვლის შესáƒáƒ«áƒšáƒ”ბლáƒáƒ‘ის შეზღუდვისთვის მáƒáƒ˜áƒœáƒáƒ®áƒ£áƒšáƒ”თ <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">თქვენ ეს-ესáƒáƒ შეიყვáƒáƒœáƒ”თ პáƒáƒ áƒáƒšáƒ˜ შეცდáƒáƒ›áƒáƒ¨áƒ˜ შემყვáƒáƒœ სáƒáƒ˜áƒ¢áƒ–ე. Chromium გირჩევთ, შეáƒáƒ›áƒáƒ¬áƒ›áƒáƒ— შენáƒáƒ®áƒ£áƒšáƒ˜ პáƒáƒ áƒáƒšáƒ”ბი <ph name="WEBSITE_1" />-ისთვის, <ph name="WEBSITE_2" />-ისრდრსხვრსáƒáƒ˜áƒ¢áƒ”ბისთვის, სáƒáƒ“áƒáƒª áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ იმáƒáƒ•áƒ” პáƒáƒ áƒáƒšáƒ¡ იყენებთ.</translation>
<translation id="7508255263130623398">წესების დáƒáƒ‘რუნებული მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის ID ცáƒáƒ áƒ˜áƒ”ლირáƒáƒœ áƒáƒ›áƒŸáƒáƒ›áƒ˜áƒœáƒ“ელ მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის ID-ს áƒáƒ  ემთხვევáƒ</translation>
<translation id="7508870219247277067">áƒáƒ•áƒáƒ™áƒáƒ“áƒáƒ¡áƒ¤áƒ”რი</translation>
@@ -1713,6 +1763,7 @@
<translation id="7548892272833184391">კáƒáƒ•áƒ¨áƒ˜áƒ áƒ˜áƒ¡ შეცდáƒáƒ›áƒ”ბის áƒáƒ¦áƒ›áƒáƒ¤áƒ®áƒ•áƒ áƒ</translation>
<translation id="7549584377607005141">áƒáƒ› ვებგვერდის სწáƒáƒ áƒáƒ“ გáƒáƒ›áƒáƒ¡áƒáƒ©áƒ”ნáƒáƒ“ სáƒáƒ­áƒ˜áƒ áƒáƒ áƒáƒ“რე შეყვáƒáƒœáƒ˜áƒšáƒ˜ მáƒáƒœáƒáƒªáƒ”მები. შეგიძლიáƒáƒ— ხელáƒáƒ®áƒšáƒ გáƒáƒ’ზáƒáƒ•áƒœáƒáƒ— ეს მáƒáƒœáƒáƒªáƒ”მები, მáƒáƒ’რáƒáƒ› áƒáƒ› შემთხვევáƒáƒ¨áƒ˜ თქვენ გáƒáƒ˜áƒ›áƒ”áƒáƒ áƒ”ბთ áƒáƒ› გვერდის მიერ áƒáƒ“რე შესრულებულ მáƒáƒ¥áƒ›áƒ”დებებს.</translation>
<translation id="7550637293666041147">თქვენი მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ისრდრChrome-ის მáƒáƒ›áƒ®áƒ›áƒáƒ áƒ”ბლის სáƒáƒ®áƒ”ლები</translation>
+<translation id="755279583747225797">სáƒáƒªáƒ“ელი ვერსირáƒáƒ¥áƒ¢áƒ˜áƒ£áƒ áƒ˜áƒ</translation>
<translation id="7552846755917812628">ცáƒáƒ“ეთ შემდეგი:</translation>
<translation id="7554475479213504905">გáƒáƒ“áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვრდრმáƒáƒ˜áƒœáƒª ჩვენებáƒ</translation>
<translation id="7554791636758816595">áƒáƒ®áƒáƒšáƒ˜ ჩáƒáƒœáƒáƒ áƒ—ი</translation>
@@ -1731,7 +1782,6 @@
<translation id="7610193165460212391">მნიშვნელáƒáƒ‘რდიáƒáƒžáƒáƒ–áƒáƒœáƒ˜áƒ¡ გáƒáƒ áƒ”თáƒáƒ <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">მáƒáƒ¥áƒ›.: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ თქვენი პáƒáƒ áƒáƒšáƒ”ბის სáƒáƒœáƒáƒ®áƒáƒ•áƒáƒ“ დრსáƒáƒ›áƒáƒ áƒ—áƒáƒ•áƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ Tab, შემდეგ კი Enter-ს</translation>
-<translation id="7615602087246926389">თქვენ უკვე გáƒáƒ¥áƒ•áƒ— მáƒáƒœáƒáƒªáƒ”მები, რáƒáƒ›áƒšáƒ”ბიც დáƒáƒ¨áƒ˜áƒ¤áƒ áƒ£áƒšáƒ˜áƒ თქვენი Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ˜áƒ¡ პáƒáƒ áƒáƒšáƒ˜áƒ¡ სხვრვერსიის გáƒáƒ›áƒáƒ§áƒ”ნებით. გთხáƒáƒ•áƒ— შეიყვáƒáƒœáƒáƒ— იგი ქვემáƒáƒ—.</translation>
<translation id="7616645509853975347">თქვენმრáƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ›áƒ ჩáƒáƒ áƒ—რChrome Enterprise Connectors თქვენს ბრáƒáƒ£áƒ–ერში. áƒáƒ¦áƒœáƒ˜áƒ¨áƒœáƒ£áƒš მáƒáƒ”რთებლებს წვდáƒáƒ›áƒ áƒáƒ¥áƒ•áƒ¡ თქვენს გáƒáƒ áƒ™áƒ•áƒ”ულ მáƒáƒœáƒáƒªáƒ”მებზე.</translation>
<translation id="7619838219691048931">ბáƒáƒšáƒ ფურცელი</translation>
<translation id="762844065391966283">ერთ ჯერზე ერთი</translation>
@@ -1796,13 +1846,12 @@
<translation id="782886543891417279">Wi-Fi-მ, რáƒáƒ›áƒ”ლსáƒáƒª თქვენ იყენებთ (<ph name="WIFI_NAME" />) შეიძლებრმáƒáƒ˜áƒ—ხáƒáƒ•áƒáƒ¡ თქვენი სტუმრáƒáƒ‘რმის áƒáƒ•áƒ¢áƒáƒ áƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡ გვერდზე.</translation>
<translation id="7836231406687464395">Postfix (კáƒáƒœáƒ•áƒ”რტი)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{áƒáƒ áƒªáƒ”რთი}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">ფáƒáƒ˜áƒšáƒ”ბის ცნáƒáƒ‘ილი ტიპების მქáƒáƒœáƒ” ფáƒáƒ˜áƒšáƒ”ბის გáƒáƒ®áƒ¡áƒœáƒ.</translation>
<translation id="7862185352068345852">გსურთ სáƒáƒ˜áƒ¢áƒ˜áƒ“áƒáƒœ გáƒáƒ¡áƒ•áƒšáƒ?</translation>
<translation id="7865448901209910068">სáƒáƒ£áƒ™áƒ”თესრსიჩქáƒáƒ áƒ”</translation>
<translation id="7874263914261512992">თქვენ ეს-ესáƒáƒ შეიყვáƒáƒœáƒ”თ პáƒáƒ áƒáƒšáƒ˜ შეცდáƒáƒ›áƒáƒ¨áƒ˜ შემყვáƒáƒœ სáƒáƒ˜áƒ¢áƒ–ე. Chrome გირჩევთ, შეáƒáƒ›áƒáƒ¬áƒ›áƒáƒ— შენáƒáƒ®áƒ£áƒšáƒ˜ პáƒáƒ áƒáƒšáƒ”ბი <ph name="WEBSITE_1" />-ისთვის, <ph name="WEBSITE_2" />-ისრდრსხვრსáƒáƒ˜áƒ¢áƒ”ბისთვის, სáƒáƒ“áƒáƒª áƒáƒ›áƒŸáƒáƒ›áƒáƒ“ იმáƒáƒ•áƒ” პáƒáƒ áƒáƒšáƒ¡ იყენებთ.</translation>
<translation id="7878562273885520351">შესáƒáƒ«áƒšáƒáƒ თქვენს პáƒáƒ áƒáƒšáƒ¡ სáƒáƒ¤áƒ áƒ—ხე ემუქრებáƒáƒ“ეს</translation>
+<translation id="7880146494886811634">მისáƒáƒ›áƒáƒ áƒ—ის შენáƒáƒ®áƒ•áƒ</translation>
<translation id="7882421473871500483">ყáƒáƒ•áƒ˜áƒ¡áƒ¤áƒ”რი</translation>
<translation id="7887683347370398519">შეáƒáƒ›áƒáƒ¬áƒ›áƒ”თ თქვენი CVC დრხელáƒáƒ®áƒšáƒ სცáƒáƒ“ეთ</translation>
<translation id="7887885240995164102">რეჟიმში „გáƒáƒ›áƒáƒ¡áƒáƒ®áƒ£áƒšáƒ”ბრგáƒáƒ›áƒáƒ¡áƒáƒ®áƒ£áƒšáƒ”ბáƒáƒ¨áƒ˜â€œ შესვლáƒ</translation>
@@ -1810,6 +1859,7 @@
<translation id="7894280532028510793">თუ სწáƒáƒ áƒáƒ“ áƒáƒ áƒ˜áƒ¡ áƒáƒ™áƒ áƒ”ფილი, <ph name="BEGIN_LINK" />ცáƒáƒ“ეთ ქსელის დიáƒáƒ’ნáƒáƒ¡áƒ¢áƒ˜áƒ™áƒ<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (კáƒáƒœáƒ•áƒ”რტი)</translation>
<translation id="7931318309563332511">უცნáƒáƒ‘ი</translation>
+<translation id="793209273132572360">გსურთ მისáƒáƒ›áƒáƒ áƒ—ის გáƒáƒœáƒáƒ®áƒšáƒ”ბáƒ?</translation>
<translation id="7932579305932748336">ფენით დáƒáƒ¤áƒáƒ áƒ•áƒ</translation>
<translation id="79338296614623784">შეიყვáƒáƒœáƒ”თ სწáƒáƒ áƒ˜ ტელეფáƒáƒœáƒ˜áƒ¡ ნáƒáƒ›áƒ”რი</translation>
<translation id="7934052535022478634">გáƒáƒ“áƒáƒ®áƒ“რშესრულდáƒ</translation>
@@ -1880,6 +1930,7 @@
<translation id="8175796834047840627">თქვენს Google áƒáƒœáƒ’áƒáƒ áƒ˜áƒ¨áƒ¨áƒ˜ ბáƒáƒ áƒáƒ—ების შენáƒáƒ®áƒ•áƒáƒ¡ Chrome გთáƒáƒ•áƒáƒ–áƒáƒ‘თ, ვინáƒáƒ˜áƒ“áƒáƒœ შესული ხáƒáƒ áƒ— სისტემáƒáƒ¨áƒ˜. áƒáƒ› ქცევის შეცვლრშეგიძლიáƒáƒ— პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ.</translation>
<translation id="8176440868214972690">áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ის áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ›áƒ მითითებულ ვებსáƒáƒ˜áƒ¢áƒ”ბს გáƒáƒ£áƒ’ზáƒáƒ•áƒœáƒ გáƒáƒ áƒ™áƒ•áƒ”ული ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ, რáƒáƒ’áƒáƒ áƒ˜áƒªáƒáƒ პáƒáƒ áƒáƒ›áƒ”ტრები თუ წესები.</translation>
<translation id="8184538546369750125">გლáƒáƒ‘áƒáƒšáƒ£áƒ áƒ˜ ნáƒáƒ’ულისხმევის გáƒáƒ›áƒáƒ§áƒ”ნებრ(ნებáƒáƒ áƒ—ვáƒ)</translation>
+<translation id="8193086767630290324">კáƒáƒœáƒ¤áƒ˜áƒ“ენციáƒáƒšáƒ£áƒ áƒáƒ“ მáƒáƒœáƒ˜áƒ¨áƒœáƒ£áƒš მáƒáƒœáƒáƒªáƒ”მებთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბით გáƒáƒœáƒ®áƒáƒ áƒªáƒ˜áƒ”ლებული ქმედებები</translation>
<translation id="8194797478851900357">გáƒáƒ“áƒáƒ¢áƒáƒœáƒ˜áƒ¡ &amp;მáƒáƒ¥áƒ›áƒ”დების გáƒáƒ£áƒ¥áƒ›áƒ”ბáƒ</translation>
<translation id="8201077131113104583">URL-ის áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜ გáƒáƒœáƒáƒ®áƒšáƒ”ბრგáƒáƒœáƒ®áƒáƒ áƒªáƒ˜áƒ”ლდრID â€<ph name="EXTENSION_ID" />â€-ის მქáƒáƒœáƒ” გáƒáƒ¤áƒáƒ áƒ—áƒáƒ”ბისთვის.</translation>
<translation id="8202097416529803614">შეკვეთის რეზიუმე</translation>
@@ -1902,6 +1953,7 @@
<translation id="8249296373107784235">შეწყვეტáƒ</translation>
<translation id="8249320324621329438">ბáƒáƒšáƒáƒ¡ áƒáƒ›áƒáƒ™áƒ áƒ”ფილი:</translation>
<translation id="8253091569723639551">ბილინგის მისáƒáƒ›áƒáƒ áƒ—ი áƒáƒ£áƒªáƒ˜áƒšáƒ”ბელიáƒ</translation>
+<translation id="8257387598443225809">ეს áƒáƒžáƒ˜ შექმნილირმáƒáƒ‘ილურისთვის</translation>
<translation id="825929999321470778">ყველრშენáƒáƒ®áƒ£áƒšáƒ˜ პáƒáƒ áƒáƒšáƒ˜áƒ¡ ჩვენებáƒ</translation>
<translation id="8261506727792406068">წáƒáƒ¨áƒšáƒ</translation>
<translation id="8262952874573525464">კიდეების მიკერებრქვემáƒáƒ—</translation>
@@ -2025,7 +2077,6 @@
<translation id="8719528812645237045">მრáƒáƒ•áƒáƒšáƒáƒ“ გáƒáƒ®áƒ•áƒ áƒ”ტრზემáƒáƒ—</translation>
<translation id="8725066075913043281">ხელáƒáƒ®áƒšáƒ სცáƒáƒ“ეთ</translation>
<translation id="8726549941689275341">გვერდის ზáƒáƒ›áƒ:</translation>
-<translation id="8728672262656704056">თქვენ გáƒáƒ“áƒáƒ®áƒ•áƒ”დით ინკáƒáƒ’ნიტრრეჟიმზე</translation>
<translation id="8730621377337864115">მზáƒáƒ“áƒáƒ</translation>
<translation id="8731544501227493793">პáƒáƒ áƒáƒšáƒ”ბის მáƒáƒ áƒ—ვის ღილáƒáƒ™áƒ˜, Chrome-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ თქვენი პáƒáƒ áƒáƒšáƒ”ბის სáƒáƒœáƒáƒ®áƒáƒ•áƒáƒ“ დრსáƒáƒ›áƒáƒ áƒ—áƒáƒ•áƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ Enter</translation>
<translation id="8734529307927223492">თქვენი <ph name="DEVICE_TYPE" /> იმáƒáƒ áƒ—ებრ<ph name="MANAGER" />-ის მიერ</translation>
@@ -2102,10 +2153,11 @@
<translation id="9020542370529661692">ეს გვერდი გáƒáƒ“áƒáƒ—áƒáƒ áƒ’მნილირáƒáƒ› ენáƒáƒ–ე: <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜áƒ)</translation>
+<translation id="9030265603405983977">მáƒáƒœáƒáƒ¥áƒ áƒáƒ›áƒ£áƒšáƒ˜</translation>
<translation id="9035022520814077154">უსáƒáƒ¤áƒ áƒ—ხáƒáƒ”ბის შეცდáƒáƒ›áƒ</translation>
<translation id="9038649477754266430">გვერდების უფრრსწრáƒáƒ¤áƒáƒ“ ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვის მიზნით პრáƒáƒ’ნáƒáƒ–ირების სერვისის გáƒáƒ›áƒáƒ§áƒ”ნებáƒ</translation>
<translation id="9039213469156557790">გáƒáƒ áƒ“რáƒáƒ›áƒ˜áƒ¡áƒ, ეს გვერდი შეიცáƒáƒ•áƒ¡ სხვრáƒáƒ áƒáƒ£áƒ¡áƒáƒ¤áƒ áƒ—ხრრესურსებს. áƒáƒ› რესურსების დáƒáƒ—ვáƒáƒšáƒ˜áƒ”რებრგáƒáƒ“áƒáƒªáƒ”მისáƒáƒ¡ სხვრპირებს შეუძლიáƒáƒ—, ხáƒáƒšáƒ თáƒáƒ•áƒ“áƒáƒ›áƒ¡áƒ®áƒ›áƒ”ლს მáƒáƒ—ი მáƒáƒ“იფიკáƒáƒªáƒ˜áƒ გვერდის მუშáƒáƒáƒ‘ის შეცვლის მიზნით შეუძლიáƒ.</translation>
-<translation id="9044359186343685026">Touch ID-ის გáƒáƒ›áƒáƒ§áƒ”ნებáƒ</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>
@@ -2125,6 +2177,7 @@
<translation id="91108059142052966"><ph name="APPLICATION_TITLE" />-თáƒáƒœ ეკრáƒáƒœáƒ˜áƒ¡ გáƒáƒ–იáƒáƒ áƒ”ბრდáƒáƒ‘ლáƒáƒ™áƒ˜áƒšáƒ˜áƒ áƒáƒ“მინისტრáƒáƒ¢áƒáƒ áƒ˜áƒ¡ წესების მიხედვით, რáƒáƒªáƒ ხილულირკáƒáƒœáƒ¤áƒ˜áƒ“ენციáƒáƒšáƒ£áƒ áƒ˜ კáƒáƒœáƒ¢áƒ”ნტი</translation>
<translation id="9114524666733003316">მიმდინáƒáƒ áƒ”áƒáƒ‘ს ბáƒáƒ áƒáƒ—ის დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბáƒ...</translation>
<translation id="9114581008513152754">áƒáƒ› ბრáƒáƒ£áƒ–ერს áƒáƒ  მáƒáƒ áƒ—áƒáƒ•áƒ¡ კáƒáƒ›áƒžáƒáƒœáƒ˜áƒ თუ სხვრáƒáƒ áƒ’áƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ. áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ–ე áƒáƒ¥áƒ¢áƒ˜áƒ•áƒáƒ‘რშეიძლებრიმáƒáƒ áƒ—ებáƒáƒ“ეს Chrome-ს მიღმáƒ. <ph name="BEGIN_LINK" />შეიტყვეთ მეტი<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ნáƒáƒ áƒ©áƒ˜</translation>
<translation id="9119042192571987207">áƒáƒ¢áƒ•áƒ˜áƒ áƒ—ულიáƒ</translation>
<translation id="9128016270925453879">წესები ჩáƒáƒ˜áƒ¢áƒ•áƒ˜áƒ áƒ—áƒ</translation>
<translation id="9128870381267983090">ქსელთáƒáƒœ დáƒáƒ™áƒáƒ•áƒ¨áƒ˜áƒ áƒ”ბáƒ</translation>
@@ -2143,6 +2196,7 @@
<translation id="9170848237812810038">მáƒáƒ¥áƒ›áƒ”დების დáƒáƒ‘რ&amp;უნებáƒ</translation>
<translation id="9171296965991013597">გსურთ áƒáƒžáƒ˜áƒ“áƒáƒœ გáƒáƒ¡áƒ•áƒšáƒ?</translation>
<translation id="9173282814238175921">ერთი დáƒáƒ™áƒ£áƒ›áƒ”ნტი/áƒáƒ®áƒáƒšáƒ˜ ფურცელი</translation>
+<translation id="9173995187295789444">მიმდინáƒáƒ áƒ”áƒáƒ‘ს Bluetooth მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘ების სკáƒáƒœáƒ˜áƒ áƒ”ბáƒ...</translation>
<translation id="917450738466192189">სერვერის სერტიფიკáƒáƒ¢áƒ˜ áƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒ˜áƒ.</translation>
<translation id="9174917557437862841">ჩáƒáƒœáƒáƒ áƒ—ის გáƒáƒ“áƒáƒ áƒ—ვის ღილáƒáƒ™áƒ˜, áƒáƒ› ჩáƒáƒœáƒáƒ áƒ—ზე გáƒáƒ“áƒáƒ¡áƒáƒ áƒ—ველáƒáƒ“ დáƒáƒáƒ­áƒ˜áƒ áƒ”თ კლáƒáƒ•áƒ˜áƒ¨áƒ¡ „Enter“</translation>
<translation id="9179703756951298733">მáƒáƒ áƒ—ეთ სáƒáƒ’áƒáƒ“áƒáƒ®áƒ“რდრსáƒáƒ™áƒ áƒ”დიტრბáƒáƒ áƒáƒ—ების ინფáƒáƒ áƒ›áƒáƒªáƒ˜áƒ Chrome-ის პáƒáƒ áƒáƒ›áƒ”ტრებიდáƒáƒœ</translation>
diff --git a/chromium/components/strings/components_strings_kk.xtb b/chromium/components/strings/components_strings_kk.xtb
index fa8f983a39c..fac196f4f98 100644
--- a/chromium/components/strings/components_strings_kk.xtb
+++ b/chromium/components/strings/components_strings_kk.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">ÒšÒ±Ñбелгі қойылÑа, Chrome ныÑанды жылдамырақ толтыру үшін картаңыздың көшірмеÑін оÑÑ‹ құрылғыда Ñақтайды.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> үшін Ñ€Ò±Ò›Ñатты таңдаңыз</translation>
<translation id="1113869188872983271">&amp;Қайта ретке келтіру әрекетін болдырмау</translation>
+<translation id="1123753900084781868">Live Caption қазір қолжетімді емеÑ.</translation>
<translation id="1125573121925420732">Веб-Ñайттар қауіпÑіздік шарттарын өзгертіп жатқанда, еÑкертулер жиі шығуы мүмкін. Бұл көпке Ñозылмайды.</translation>
<translation id="112840717907525620">СаÑÑат кÑші жарамды</translation>
<translation id="1130564665089811311">"Бетті аудару" түймеÑÑ–. ОÑÑ‹ бетті Google Translate арқылы аудару үшін Enter пернеÑін баÑыңыз.</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Құрылғыңыздың атауы</translation>
<translation id="124116460088058876">ҚоÑымша тілдер</translation>
<translation id="1243027604378859286">Ðвторы:</translation>
+<translation id="1246424317317450637">Қалың</translation>
<translation id="1250759482327835220">КелеÑіде жылдамырақ төлеу үшін картаңызды, аты-жөніңізді және төлем мекенжайын Google еÑептік жазбаңызға Ñақтап қойыңыз.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (Ñинхрондалған)</translation>
<translation id="1256368399071562588">&lt;p&gt;Егер веб-Ñайт ашылмаÑа, қатені түзету үшін алдымен мына ақауларды жою қадамдарын жаÑаңыз:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">ÒšÒ±Ð¿Ð¸Ñ Ñөзді өзгерту</translation>
<translation id="1484290072879560759">Жөнелту мекенжайын таңдау</translation>
<translation id="1492194039220927094">Жаңа ÑаÑÑаттар туралы хабарландыру:</translation>
+<translation id="1495677929897281669">Қойындыға оралу</translation>
<translation id="1501859676467574491">Google еÑептік жазбаÑына Ñақталған карталар көрÑетілÑін</translation>
<translation id="1507202001669085618">&lt;p&gt;Интернетке кірерде еÑептік жазбаға кіру Ñұралатын Wi-Fi порталын пайдаланған кезде, оÑÑ‹ қате шығады.&lt;/p&gt;
&lt;p&gt;Қатені түзету үшін ашқыңыз келетін бетте &lt;strong&gt;ҚоÑылу&lt;/strong&gt; түймеÑін баÑыңыз.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Бұл беттегі Ñұрау</translation>
<translation id="153384715582417236">Әзірге бары оÑÑ‹</translation>
<translation id="1536390784834419204">Бетті аудару</translation>
+<translation id="1539840569003678498">ЕÑеп жіберілді:</translation>
<translation id="154408704832528245">Жеткізу мекенжайын таңдау</translation>
<translation id="1549470594296187301">Бұл мүмкіндікті пайдалану үшін JavaScript қоÑылуы керек.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">Ðлдымен қыÑқа беті</translation>
<translation id="168693727862418163">Бұл ÑаÑÑат мәні оÑÑ‹ Ñхемаға қатыÑÑ‚Ñ‹ текÑерілмеді және ол еленбейді.</translation>
<translation id="168841957122794586">Сервер Ñертификаты ÑенімÑіз криптографиÑлық кілтті қамтиды.</translation>
+<translation id="1696290444144917273">Виртуалды карта мәліметтерін көру</translation>
<translation id="1697532407822776718">Барлығын орнаттыңыз!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Бұл Ñервер өзінің <ph name="DOMAIN" /> екендігін дәлелдей алмады; оның қауіпÑіздік Ñертификаты ертеңнен баÑталатын ÑиÑқты. Бұл Ð´Ò±Ñ€Ñ‹Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñланбағаннан немеÑе зиÑнды бағдарламаның байланыÑқа кедергі келтіруінен болуы мүмкін.}other{Бұл Ñервер өзінің <ph name="DOMAIN" /> екендігін дәлелдей алмады; оның қауіпÑіздік Ñертификаты # күн өткеннен кейін баÑталатын ÑиÑқты. Бұл Ð´Ò±Ñ€Ñ‹Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñланбағаннан немеÑе зиÑнды бағдарламаның байланыÑқа кедергі келтіруінен болуы мүмкін.}}</translation>
<translation id="1710259589646384581">ОЖ</translation>
+<translation id="1711234383449478798">Еленбеді, Ñебебі <ph name="POLICY_NAME" /> ÑаÑÑатына <ph name="VALUE" /> мәні орнатылмаған.</translation>
<translation id="1712552549805331520"><ph name="URL" /> деректерді жергілікті компьютеріңізде біржола ÑақтағыÑÑ‹ келеді</translation>
<translation id="1713628304598226412">2-науа</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">3-ші пошта жәшігі</translation>
<translation id="1718029547804390981">ÐÐ½Ð½Ð¾Ñ‚Ð°Ñ†Ð¸Ñ Ò›Ð¾Ñуға құжат өлшемі өте үлкен.</translation>
<translation id="1721424275792716183">* Ó¨Ñ€Ñ–Ñ Ñ‚Ð¾Ð»Ñ‚Ñ‹Ñ€Ñ‹Ð»ÑƒÑ‹ қажет</translation>
+<translation id="1727613060316725209">Сертификат жарамды</translation>
<translation id="1727741090716970331">Ð”Ò±Ñ€Ñ‹Ñ ÐºÐ°Ñ€Ñ‚Ð° нөмірін енгізу</translation>
<translation id="1728677426644403582">Веббет дереккөзін көрудеÑіз</translation>
<translation id="173080396488393970">Картаның бұл түріне қолдау көрÑетілмейді</translation>
@@ -246,7 +253,6 @@
жол бермейді. Сайттың қауіпÑіздік параметрлері мен
баÑқа Ñипаттарын конфигурациÑлау үшін Ñайт операторлары түпнұÑқа ÑаÑÑаттарын қолдануы мүмкін.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Синхрондау Ò›Ò±Ð¿Ð¸Ñ Ñ„Ñ€Ð°Ð·Ð°Ñын жаңартыңыз.</translation>
<translation id="1787142507584202372">Ðшық қойынды оÑÑ‹ жерден шығады</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Бірнеше әрекет қолжетімді, оларды қарап шығу үшін Tab пернеÑін баÑыңыз.</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">Жарнамалар</translation>
<translation id="1919367280705858090">Ðрнайы қате туралы хабар арқылы көмек алу</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Жоқ}=1{1 Ñайт}other{# Ñайт}}</translation>
+<translation id="1924727005275031552">Жаңа</translation>
<translation id="1945968466830820669">Ұйымның еÑептік жазбаÑына кіре алмай қалуыңыз мүмкін немеÑе жеке деректеріңіз ұрлануы ықтимал. Chromium Ò›Ò±Ð¿Ð¸Ñ Ñөзіңізді қазір өзгертуге ÐºÐµÒ£ÐµÑ Ð±ÐµÑ€ÐµÐ´Ñ–.</translation>
<translation id="1947454675006758438">Жоғарғы оң жағын қапÑыру</translation>
<translation id="1958218078413065209">Ең жоғары ұпайыңыз: <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">7-науа</translation>
<translation id="204357726431741734">Google еÑептік жазбаңызда Ñақталған Ò›Ò±Ð¿Ð¸Ñ Ñөздерді пайдалану үшін кіру</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> тіліндегі беттер аударылмайды.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Бұл баÑқару Ñлементі қоÑулы болÑа, Chrome қызметі Ñоңғы браузерді қолдану мәліметіңіз барынша Ñай келетін адамдар тобын немеÑе "когортаны" анықтайды. Жарнама берушілер топ үшін жарнамаларды таңдай алады және браузерді қолдану мәліметі құрылғыда Ò›Ò±Ð¿Ð¸Ñ Ñақталады. Тобыңыз күн Ñайын жаңартылады.}=1{Бұл баÑқару Ñлементі қоÑулы болÑа, Chrome қызметі Ñоңғы браузерді қолдану мәліметіңіз барынша Ñай келетін адамдар тобын немеÑе "когортаны" анықтайды. Жарнама берушілер топ үшін жарнамаларды таңдай алады және браузерді қолдану мәліметі құрылғыда Ò›Ò±Ð¿Ð¸Ñ Ñақталады. Тобыңыз күн Ñайын жаңартылады.}other{Бұл баÑқару Ñлементі қоÑулы болÑа, Chrome қызметі Ñоңғы браузерді қолдану мәліметіңіз барынша Ñай келетін адамдар тобын немеÑе "когортаны" анықтайды. Жарнама берушілер топ үшін жарнамаларды таңдай алады және браузерді қолдану мәліметі құрылғыда Ò›Ò±Ð¿Ð¸Ñ Ñақталады. Тобыңыз әр {NUM_DAYS} күн Ñайын жаңартылады.}}</translation>
<translation id="2053553514270667976">Пошта индекÑÑ–</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 Ò±ÑыныÑ}other{# Ò±ÑыныÑ}}</translation>
<translation id="2071692954027939183">Сіз әдетте хабарландыруларға Ñ€Ò±Ò›Ñат бермейтін болғандықтан, олар автоматты түрде бөгелді.</translation>
<translation id="2079545284768500474">Қайтару</translation>
<translation id="20817612488360358">Жүйелік прокÑи параметрлері пайдалану үшін орнатылған, бірақ анық прокÑи конфигурациÑÑÑ‹ да көрÑетілген.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> ішінен <ph name="RESULT_NUMBER" /> нәтиже</translation>
+<translation id="2085876078937250610">Сақтау…</translation>
<translation id="2088086323192747268">"Синхрондауды баÑқару" түймеÑÑ–. Chrome параметрлеріне кіріп, Ñинхрондалатын ақпаратты баÑқару үшін Enter пернеÑін баÑыңыз.</translation>
<translation id="2091887806945687916">ДыбыÑ</translation>
<translation id="2094505752054353250">Домен ÑәйкеÑÑіздігі</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> пайдаланушы аты мен Ò›Ò±Ð¿Ð¸Ñ Ñөзді қажет етеді.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, жарамдылық мерзімі: <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Әкімші баÑқаратын параметр</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> Ñайты жұптаÑқыÑÑ‹ келеді</translation>
<translation id="2344028582131185878">Ðвтоматты жүктеулер</translation>
<translation id="2346319942568447007">Көшірілген Ñурет</translation>
<translation id="2354001756790975382">БаÑқа бетбелгілер</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">Шабуылдаушылар бұл Ñайтта көріп жатқан кеÑкіндеріңізді біліп, оларды өзгерту арқылы Ñізді алдауы мүмкін.</translation>
<translation id="2356070529366658676">Сұрау</translation>
<translation id="2357481397660644965">Құрылғыңызды <ph name="DEVICE_MANAGER" />, ал еÑептік жазбаңызды <ph name="ACCOUNT_MANAGER" /> баÑқарады.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Бір күннен аз уақыт ішінде}=1{Бір күнде}other{{NUM_DAYS} күннен кейін}}</translation>
<translation id="2359629602545592467">Бірнеше</translation>
<translation id="2359808026110333948">ЖалғаÑтыру</translation>
+<translation id="2359961752320758691">Виртуалды карта нөмірі қолданылды.</translation>
<translation id="2367567093518048410">Деңгей</translation>
<translation id="2372464001869762664">РаÑтағаннан кейін, Google еÑептік жазбаÑындағы карта мәліметтері оÑÑ‹ Ñайтқа беріледі. Plex еÑептік жазбаңыз туралы мәліметтерден CVC кодын тауып алыңыз.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">Бұл жөнелту әдіÑÑ– қолжетімді емеÑ. БаÑқа әдіÑÑ‚Ñ– қолданып көріңіз.</translation>
<translation id="2396249848217231973">&amp;Жоюды болдырмау</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">ЕÑкі</translation>
<translation id="2413528052993050574">Бұл Ñервер өзінің <ph name="DOMAIN" /> екенін дәлелдей алмады; оның қауіпÑіздік Ñертификаты қайтарып алынған болуы мүмкін. Бұл Ð´Ò±Ñ€Ñ‹Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñланбағаннан немеÑе зиÑнды бағдарламаның байланыÑқа кедергі келтіргенінен болуы мүмкін.</translation>
<translation id="2414886740292270097">Күңгірт</translation>
<translation id="2438874542388153331">Оң жағын төрт рет теÑу</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">Төменгі оң жағын қапÑыру</translation>
<translation id="2523886232349826891">Тек оÑÑ‹ құрылғыда Ñақталады</translation>
<translation id="2524461107774643265">ҚоÑымша ақпарат енгізу</translation>
-<translation id="2526590354069164005">Ð–Ò±Ð¼Ñ‹Ñ Ò¯Ñтелі</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{және тағы 1}other{және тағы #}}</translation>
<translation id="2536110899380797252">Мекенжай енгізу</translation>
<translation id="2539524384386349900">Ðнықтау</translation>
+<translation id="2541219929084442027">Барлық инкогнито қойындыÑын жапқан Ñоң, инкогнито қойындылары арқылы көрген беттер браузерді қолдану тарихында, cookie файлдарында немеÑе іздеу тарихында Ñақталмайды. Жүктеп алған файлдарыңыз немеÑе жаÑаған бетбелгілеріңіз Ñақталады.</translation>
<translation id="2544644783021658368">Жалғыз құжат</translation>
<translation id="254947805923345898">СаÑÑат мәні жарамÑыз.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> қате жауап жіберді.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Chrome-ның ең жоғарғы деңгейдегі қауіпÑіздігіне ие болу үшін <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />жақÑартылған қорғаныÑÑ‚Ñ‹<ph name="END_ENHANCED_PROTECTION_LINK" /> қоÑыңыз.</translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> Ñерверінің IP мекенжайын табу мүмкін емеÑ.</translation>
<translation id="2639739919103226564">Күйі:</translation>
+<translation id="264810637653812429">ҮйлеÑімді құрылғылар табылмады.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. Chrome параметрлерінде браузерді қолдану тарихын, cookie файлдарын, кÑшті және Ñ‚.б. өшіру үшін Tab, одан кейін Enter пернеÑін баÑыңыз.</translation>
<translation id="2650446666397867134">Файлға кіруге тыйым Ñалынған</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">Қайта Ñ–Ñке қоÑу</translation>
<translation id="2803306138276472711"><ph name="SITE" /> Ñайтында Google Safe Browsing жақында <ph name="BEGIN_LINK" />зиÑнды бағдарламаны анықтады<ph name="END_LINK" />. Қорғалған веб-Ñайттар да кейде зиÑнды бағдарламамен зақымдалады.</translation>
<translation id="2807052079800581569">КеÑкіннің Y бойынша орналаÑуы</translation>
+<translation id="2820957248982571256">Іздеуде...</translation>
<translation id="2824775600643448204">Мекенжайы және іздеу жолағы</translation>
<translation id="2826760142808435982">Ð‘Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ <ph name="CIPHER" /> көмегімен шифрланды және аутентификациÑланды, Ñонымен қатар кілт ауыÑтыру механизмі ретінде <ph name="KX" /> пайдаланады.</translation>
<translation id="2835170189407361413">ÐÑ‹Ñанды тазарту</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">Бұл Ñайтта мазалайтын немеÑе жалған ақпаратты жарнамалар көрÑетіледі.</translation>
+<translation id="287596039013813457">ÐÒ› ниетті</translation>
+<translation id="2876489322757410363">Сыртқы қолданба арқылы төлеу үшін инкогнито режимінен шығаÑыз. ЖалғаÑтыру керек пе?</translation>
<translation id="2878197950673342043">ПоÑтер тәрізді бүктеу</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Терезені орналаÑтыру</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome параметрлерінен қауіпÑіздік шараÑын Ñ–Ñке қоÑу үшін Tab, Ñодан кейін Enter пернеÑін баÑыңыз.</translation>
<translation id="3061707000357573562">Қызметті түзету</translation>
-<translation id="3064966200440839136">Сыртқы қолданба арқылы төлеу үшін инкогнито режимінен шығаÑыз. ЖалғаÑтыра береÑіз бе?</translation>
<translation id="306573536155379004">Ойын баÑталды.</translation>
<translation id="3080254622891793721">КеÑкін</translation>
<translation id="3086579638707268289">Интернеттегі әрекетіңіз қадағаланып жатыр</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">ЕÑептік жазбаңызды <ph name="MANAGER" /> баÑқарады.</translation>
<translation id="3157931365184549694">Қалпына келтіру</translation>
<translation id="3162559335345991374">Сіз пайдаланып жатқан Wi-Fi өзінің кіру бетіне өтуіңізді қажет етуі мүмкін.</translation>
-<translation id="3167968892399408617">ЖаÑырын қойындыларда көрген беттер барлық жаÑырын қойындыларды жапқаннан кейін браузер журналына, cookie файлдары қоймаÑына немеÑе іздеу тарихына тіркелмейді. Барлық жүктеген файлдарыңыз немеÑе жаÑаған бетбелгілеріңіз Ñақталады.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ðрал</translation>
<translation id="3176929007561373547">ПрокÑи Ñерверінің Ð¶Ò±Ð¼Ñ‹Ñ Ñ–Ñтеп жатқанын текÑеру үшін прокÑи параметрлерін
@@ -598,10 +613,12 @@
<translation id="3229041911291329567">Құрылғының және браузердің нұÑқаÑÑ‹ туралы ақпарат</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> картаÑының CVC кодын енгізіңіз</translation>
<translation id="3234666976984236645">Әрқашан оÑÑ‹ Ñайттағы маңызды мазмұнды анықтау</translation>
+<translation id="3249845759089040423">Заманауи</translation>
<translation id="3252266817569339921">француз</translation>
<translation id="3266793032086590337">Мән (қарама-қайшы)</translation>
<translation id="3268451620468152448">Ðшық қойындылар</translation>
<translation id="3270847123878663523">&amp;Қайта тәртіпке келтіруді болдырмау</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> Ñайты Ð±Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ð¾Ñ€Ð½Ð°Ñ‚Ò›Ñ‹ÑÑ‹ келеді</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Ұйымыңыз (<ph name="ENROLLMENT_DOMAIN" />) келеÑÑ– веб-Ñайттарға бірқатар ақпарат (мыÑалы, параметрлер немеÑе ÑаÑÑаттар) жіберді.</translation>
<translation id="3282497668470633863">Картада көрÑетілген атты енгізу</translation>
@@ -654,6 +671,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates Ñерверінің бір немеÑе бірнеше URI үлгіÑÑ– жарамÑыз және пайдаланылмайды.</translation>
<translation id="3431636764301398940">Карта мәліметтерін оÑÑ‹ құрылғыда Ñақтау</translation>
<translation id="3432601291244612633">Бетті жабу</translation>
+<translation id="3435738964857648380">ҚауіпÑіздік</translation>
<translation id="3435896845095436175">ҚоÑу</translation>
<translation id="3438829137925142401">Google еÑептік жазбаÑында Ñақталған Ò›Ò±Ð¿Ð¸Ñ Ñөздерді пайдалану</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -696,7 +714,10 @@
<translation id="3584299510153766161">Төменгі жағынан екі рет теÑу</translation>
<translation id="3586931643579894722">Мәліметтерді жаÑыру</translation>
<translation id="3587738293690942763">ОртаÑÑ‹</translation>
+<translation id="3590643883886679995">Сіз инкогнито режимінен шыққаннан кейін де, еÑептік жазбаға кіру деректері оÑÑ‹ құрылғыда Ñақталады.</translation>
+<translation id="359126217934908072">Ðйы/жылы:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Топ параметрлерін кез келген уақытта баÑтапқы күйге қайтара алаÑыз. Жаңа топқа қоÑылу шамамен бір күн алады.}=1{Топ параметрлерін кез келген уақытта баÑтапқы күйге қайтара алаÑыз. Жаңа топқа қоÑылу шамамен бір күн алады.}other{Топ параметрлерін кез келген уақытта баÑтапқы күйге қайтара алаÑыз. Жаңа топқа қоÑылу шамамен {NUM_DAYS} күн алады.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Қолданбаны әкімші бөгеген</translation>
<translation id="3608932978122581043">Беру бағыты</translation>
@@ -705,13 +726,13 @@
<translation id="3615877443314183785">Ð”Ò±Ñ€Ñ‹Ñ Ð¶Ð°Ñ€Ð°Ð¼Ð´Ñ‹Ð»Ñ‹Ò› мерзімін енгізіңіз</translation>
<translation id="36224234498066874">Шолу деректерін өшіру…</translation>
<translation id="362276910939193118">Тарихты толық көрÑету</translation>
-<translation id="3625635938337243871">Сіз инкогнито режимінен шыққаннан кейін де, еÑептік жазбаға кіру деректері оÑÑ‹ құрылғыда Ñақталады.</translation>
<translation id="3630155396527302611">Ол желіге кіруге Ñ€Ò±Ò›Ñат алған бағдарламалар тізімінде тұрÑа, оны
тізімнен өшіріп, қайта қоÑып көріңіз.</translation>
<translation id="3630699740441428070">Бұл құрылғының әкімшілері желі байланыÑын конфигурациÑлады. Сол арқылы олар желі трафигін, Ñоның ішінде Ñіз кіретін веб-Ñайттарды көре алады.</translation>
<translation id="3631244953324577188">Биометрика</translation>
<translation id="3633738897356909127">"Chrome-ды жаңарту" түймеÑÑ–, Chrome параметрлерінен Chrome-ды жаңарту үшін Enter пернеÑін баÑыңыз.</translation>
<translation id="3634530185120165534">5-науа</translation>
+<translation id="3637662659967048211">Google еÑептік жазбаÑына Ñақтау</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Қолданба:</translation>
<translation id="3650584904733503804">ТекÑеру Ñәтті аÑқталды</translation>
@@ -752,6 +773,7 @@
<translation id="3781428340399460090">Қою алқызыл</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth құрылғылары</translation>
+<translation id="3787675388804467730">Виртуалды карта нөмірі</translation>
<translation id="3787705759683870569">Жарамдылық мерзімі: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Өлшемі: 16</translation>
<translation id="3789841737615482174">Орнату</translation>
@@ -771,6 +793,7 @@
<translation id="3841184659773414994">Файл өңдегіштер</translation>
<translation id="385051799172605136">Ðртқа</translation>
<translation id="3858027520442213535">Күні мен уақытын жаңарту</translation>
+<translation id="3881478300875776315">Жолдарды азырақ көрÑету</translation>
<translation id="3884278016824448484">Мұндай құрылғы идентификаторы бұрыннан бар</translation>
<translation id="3885155851504623709">Округ</translation>
<translation id="388632593194507180">Бақыланып жатқаны анықталды</translation>
@@ -796,6 +819,7 @@
<translation id="397105322502079400">ЕÑептелуде…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> бөгелген</translation>
<translation id="3973357910713125165">Chrome қауіпÑіздік шараÑÑ‹ түймеÑін баÑыңыз. Chrome параметрлерінен қауіпÑіздік шараÑын Ñ–Ñке қоÑу үшін Enter пернеÑін баÑыңыз.</translation>
+<translation id="3986705137476756801">Live Caption функциÑÑын қазір өшіру</translation>
<translation id="3987405730340719549">Chrome бұл Ñайттың жалған немеÑе алаÑқтық болуы мүмкін екенін анықтады.
Бұл хабар қателікпен көрÑетілді деп ойлаÑаңыз, мына бетке өтіңіз: https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -892,13 +916,14 @@
<translation id="4275830172053184480">Құрылғыңызды қайта Ñ–Ñке қоÑу</translation>
<translation id="4277028893293644418">ÒšÒ±Ð¿Ð¸Ñ Ñөзді қайта орнату</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Бұл карта Google еÑептік жазбаңызда Ñақталды}other{Бұл карталар Google еÑептік жазбаңызда Ñақталды}}</translation>
+<translation id="4287885627794386150">Сынақ нұÑқаÑÑ‹ қолжетімді, бірақ Ñ–Ñке қоÑылмаған.</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> бетіне арналған нобай</translation>
<translation id="42981349822642051">Жаю</translation>
<translation id="4300675098767811073">Оң жақтан бірнеше рет теÑу</translation>
<translation id="4302514097724775343">Ойнау үшін динозаврды баÑыңыз.</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Файлға кіру мүмкін болмады</translation>
-<translation id="4305817255990598646">ÐуыÑу</translation>
+<translation id="4306529830550717874">Мекенжайды Ñақтау керек пе?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Бөгеу (әдепкі)</translation>
<translation id="4314815835985389558">Синхрондауды баÑқару</translation>
@@ -925,6 +950,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" /> доменіне қол жеткізуге әрекет еттіңіз, бірақ Ñервер Ò±Ñынған Ñертификатты оны шығарған орган қайтарып алды. Бұл Ñервер Ò±Ñынған қауіпÑіздік деректеріне Ñенуге болмайтынын білдіреді. ҚаÑкүнеммен байланыÑып жатқан болуыңыз мүмкін.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4390472908992056574">Жиек</translation>
+<translation id="4406883609789734330">Live Caption</translation>
<translation id="4406896451731180161">іздеу нәтижелері</translation>
<translation id="4408413947728134509">Cookie файлдары: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Жаңа ғана Ò›Ò±Ð¿Ð¸Ñ Ñөзіңізді жалған Ñайтқа енгіздіңіз. Chrome оÑÑ‹ Ò›Ò±Ð¿Ð¸Ñ Ñөз енгізілген <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> және тағы баÑқа Ñайттарға кіріп, оны дереу өзгертуге ÐºÐµÒ£ÐµÑ Ð±ÐµÑ€ÐµÐ´Ñ–.</translation>
@@ -937,7 +963,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">ПрокÑиді пайдалану өшірілген, бірақ айқын прокÑи конфигурациÑÑÑ‹ көрÑетілген.</translation>
<translation id="4464826014807964867">Ұйымыңыздан алынған ақпарат қамтылған веб-Ñайттар</translation>
-<translation id="4466881336512663640">Үлгідегі өзгеріÑтер жойылады. Шынымен жалғаÑтырғыңыз келе ме?</translation>
<translation id="4476953670630786061">Бұл үлгі қорғалмаған. Ðвтотолтыру өшірілді.</translation>
<translation id="4477350412780666475">КелеÑÑ– аудиотрек</translation>
<translation id="4482953324121162758">Бұл Ñайт аударылмайды.</translation>
@@ -971,6 +996,7 @@
<translation id="4594403342090139922">&amp;Жоюды болдырмау</translation>
<translation id="4597348597567598915">Өлшемі: 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Ó˜Ñерлі</translation>
<translation id="4628948037717959914">ФотоÑурет</translation>
<translation id="4631649115723685955">БайланыÑтырылған кешбÑк</translation>
<translation id="4636930964841734540">Ðқпарат</translation>
@@ -990,6 +1016,7 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Бүйірлік</translation>
+<translation id="4702656508969495934">Live Caption көрінеді, ерекшелеу үшін терезе ауыÑтырғышты пайдаланыңыз.</translation>
<translation id="4708268264240856090">Ð‘Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ò¯Ð·Ñ–Ð»Ð´Ñ–</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows Network Diagnostics құралын қоÑу<ph name="END_LINK" /></translation>
@@ -1003,6 +1030,7 @@
<translation id="4738601419177586157">Ò°Ñынылатын Ñұрау: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">ÒšÒ±Ð¿Ð¸Ñ Ñөздерді баÑқару...</translation>
<translation id="4744603770635761495">Орындалатын жол</translation>
+<translation id="4749011317274908093">Инкогнито режиміне өттіңіз</translation>
<translation id="4750917950439032686">Бұл Ñайтқа жіберілетін жеке ақпаратыңыз (мыÑалы, Ò›Ò±Ð¿Ð¸Ñ Ñөздер не неÑиелік карта нөмірлері) Ò›Ò±Ð¿Ð¸Ñ Ñақталады.</translation>
<translation id="4756388243121344051">&amp;Тарих</translation>
<translation id="4758311279753947758">Контакт ақпаратын қоÑу</translation>
@@ -1032,6 +1060,8 @@
<translation id="4813512666221746211">Желі қатеÑÑ–</translation>
<translation id="4816492930507672669">Бетке бейімдеу</translation>
<translation id="4819347708020428563">ÐннотациÑларды әдепкі көрініÑте өзгерту керек пе?</translation>
+<translation id="4825507807291741242">Қуатты</translation>
+<translation id="4838327282952368871">Ðрманшыл</translation>
<translation id="484462545196658690">Ðвто</translation>
<translation id="4850886885716139402">КөрініÑ</translation>
<translation id="485316830061041779">неміÑ</translation>
@@ -1168,6 +1198,7 @@
<translation id="5314967030527622926">Буклет жаÑағыш</translation>
<translation id="5316812925700871227">Сағат тілінің бағытына қарÑÑ‹ бұру</translation>
<translation id="5317780077021120954">Сақтау</translation>
+<translation id="5321288445143113935">Жайылған терезе</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" />/<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Ð‘Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ð°Ò›Ð¿Ð°Ñ€Ð°Ñ‚Ñ‹Ð½ таңдау</translation>
<translation id="5327248766486351172">ÐÑ‚Ñ‹</translation>
@@ -1175,11 +1206,13 @@
<translation id="5332219387342487447">Жеткізу әдіÑÑ–</translation>
<translation id="5333022057423422993">Chrome деректер қолды болған кезде пайдаланылған Ò›Ò±Ð¿Ð¸Ñ Ñөзді тапты. ЕÑептік жазбаларды қорғау үшін Ñақталған Ò›Ò±Ð¿Ð¸Ñ Ñөздерді текÑеруге ÐºÐµÒ£ÐµÑ Ð±ÐµÑ€ÐµÐ¼Ñ–Ð·.</translation>
<translation id="5334013548165032829">Жүйе журналдары туралы мәліметтер</translation>
+<translation id="5334145288572353250">Мекенжайды Ñақтау керек пе?</translation>
<translation id="5340250774223869109">Қолданба бөгелген</translation>
<translation id="534295439873310000">NFC функциÑÑÑ‹ бар құрылғылар</translation>
<translation id="5344579389779391559">Бетті ашÑаңыз, ақы алынуы мүмкін</translation>
<translation id="5355557959165512791">Қазір <ph name="SITE" /> Ñайтына кіре алмайÑыз, Ñебебі мұның Ñертификаты қайтарып алынды. Желі қателері мен шабуылдары әдетте уақытша болады, Ñондықтан бұл бет кейінірек Ð¶Ò±Ð¼Ñ‹Ñ Ñ–Ñтеуі мүмкін.</translation>
<translation id="536296301121032821">СаÑÑат параметрлерін Ñақтау ÑәтÑіз аÑқталды</translation>
+<translation id="5363309033720083897">Әкімші Ñ€Ò±Ò›Ñат еткен тізбекті порт</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="5386426401304769735">ОÑÑ‹ Ñайтқа арналған Ñертификат тізбегінде SHA-1 көмегімен қолтаңба қойылған Ñертификат бар.</translation>
@@ -1188,6 +1221,7 @@
<translation id="5398772614898833570">Жарнамалар бөгелді</translation>
<translation id="5400836586163650660">Сұр</translation>
<translation id="540969355065856584">Бұл Ñервер өзінің <ph name="DOMAIN" /> екенін дәлелдей алмады; оның қауіпÑіздік Ñертификаты әзірше жарамайды. Бұл Ð´Ò±Ñ€Ñ‹Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñланбағаннан немеÑе зиÑнды бағдарламаның байланыÑқа кедергі келтіргенінен болуы мүмкін.</translation>
+<translation id="541143247543991491">Бұлт (жүйелік)</translation>
<translation id="541416427766103491">4-жинаÑтырушы</translation>
<translation id="5421136146218899937">Шолу деректерін өшіру…</translation>
<translation id="5426179911063097041"><ph name="SITE" /> хабарландыру жіберуге Ñ€Ò±Ò›Ñат Ñұрады</translation>
@@ -1201,6 +1235,7 @@
<translation id="5455374756549232013">СаÑÑат уақыт белгіÑÑ– жарамÑыз</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" />}other{<ph name="CONTACT_PREVIEW" /> және тағы <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
+<translation id="5463625433003343978">Құрылғылар ізделуде...</translation>
<translation id="5469868506864199649">италиÑн</translation>
<translation id="5470861586879999274">&amp;Өзгерту әрекетін қайталау</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1250,7 +1285,6 @@
<translation id="5624120631404540903">ÒšÒ±Ð¿Ð¸Ñ Ñөздерді баÑқару</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="563324245173044180">Жалған мазмұн бөгелді.</translation>
<translation id="5644090287519800334">КеÑкіннің Ð¥ оÑÑ– бойынша 1-жағында Ñ‹Ò“Ñ‹Ñуы</translation>
@@ -1289,12 +1323,12 @@
<translation id="5785756445106461925">Сонымен қатар бұл бет баÑқа да қауіпті реÑурÑтарды қамтиды. Бұл реÑурÑтарды өту кезінде баÑқалар көре алады және беттің көрініÑіне Ó©Ð·Ð³ÐµÑ€Ñ–Ñ ÐµÐ½Ð³Ñ–Ð·Ñƒ мақÑатында оны шабуылшы өзгерте алады.</translation>
<translation id="5786044859038896871">Карта ақпаратын толтырғыңыз келе ме?</translation>
<translation id="578633867165174378">Chrome деректер қолды болған кезде пайдаланылған Ò›Ò±Ð¿Ð¸Ñ Ñөзді тапты. ÒšÒ±Ð¿Ð¸Ñ Ñөзді қазір өзгертуге ÐºÐµÒ£ÐµÑ Ð±ÐµÑ€ÐµÐ¼Ñ–Ð·.</translation>
-<translation id="5798290721819630480">ӨзгеріÑтер ÑақталмаÑын ба?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" /> картаÑының мәліметтерін толтырғыңыз келе ме?</translation>
<translation id="5804241973901381774">РұқÑаттар</translation>
<translation id="5804427196348435412">NFC функциÑÑÑ‹ бар құрылғыларды пайдалану</translation>
<translation id="5810442152076338065">Сіздің <ph name="DOMAIN" /> доменіне қоÑылуыңыз еÑкірген шифр жиынтығы арқылы шифрланған.</translation>
<translation id="5813119285467412249">&amp;ҚоÑуды қайта орындау</translation>
+<translation id="5817918615728894473">Жұптау</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Төлем оÑÑ‹ картадан алынады, бірақ оның нөмірі Ñайтқа белгіÑіз болады. ҚоÑымша қауіпÑіздік үшін уақытша CVC коды жаÑалады.}other{Төлем Ñіз таңдаған картадан алынады, бірақ оның нөмірі Ñайтқа белгіÑіз болады. ҚоÑымша қауіпÑіздік үшін уақытша CVC коды жаÑалады.}}</translation>
<translation id="5826507051599432481">Ортақ атау (CN)</translation>
<translation id="5838278095973806738">Шабуылдаушылар ұрлауы мүмкін болғандықтан, бұл Ñайтқа ешқандай маңызды ақпаратты (мыÑалы, Ò›Ò±Ð¿Ð¸Ñ Ñөздер не неÑиелік карталар) енгізбеңіз.</translation>
@@ -1302,6 +1336,7 @@
<translation id="5855253129151731373">Бұл Ñайттың хоÑÑ‚ атауы <ph name="LOOKALIKE_DOMAIN" /> атауына Ò±Ò›ÑаÑ. Кейде шабуылдаушылар белгілі бір Ñайттарды көшіріп, олардың домен атауын аздап өзгертіп қоÑды.
Бұл хабар қателікпен көрÑетілді деп ойлаÑаңыз, мына бетке өтіңіз: https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Өшірулі</translation>
<translation id="5862579898803147654">8-жинаÑтырушы</translation>
<translation id="5863847714970149516">Бұл бет Ñізден ақшалай ақы алуға тырыÑуы мүмкін</translation>
<translation id="5866257070973731571">Телефон нөмірін қоÑу</translation>
@@ -1318,6 +1353,7 @@
<translation id="5913377024445952699">Экранды Ñ‚Ò¯Ñіру кідіртілді</translation>
<translation id="59174027418879706">ҚоÑылған</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 пайдаланылуда}other{# пайдаланылуда}}</translation>
<translation id="5921185718311485855">ҚоÑулы</translation>
<translation id="5921639886840618607">Картаны Google еÑептік жазбаÑына Ñақтау қажет пе?</translation>
<translation id="5922853866070715753">ÐÑқтап қалдыңыз</translation>
@@ -1337,6 +1373,7 @@
<translation id="5989320800837274978">Бекітілген прокÑи Ñерверлері де, .pac Ñценарий URL мекенжайы да көрÑетілмеген.</translation>
<translation id="5992691462791905444">Z тәрізді етіп жиі бүктеу</translation>
<translation id="6000758707621254961">"<ph name="SEARCH_TEXT" />" Ñұрауы бойынша <ph name="RESULT_COUNT" /> нәтиже шықты</translation>
+<translation id="6006484371116297560">КлаÑÑикалық</translation>
<translation id="6008122969617370890">N баÑтап 1 дейінгі ретпен</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">ÒšÒ±Ð¿Ð¸Ñ Ñөздеріңізді текÑеріңіз</translation>
@@ -1358,6 +1395,7 @@
<translation id="6045164183059402045">Жолақтарды Ñ‚Ò¯Ñіру үлгіÑÑ–</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="6049004884579590341">Толық Ñкраннан шығу үшін |<ph name="ACCELERATOR" />| түймеÑін баÑып тұрыңыз</translation>
<translation id="6049488691372270142">Бетті беру</translation>
<translation id="6051221802930200923">Қазір <ph name="SITE" /> Ñайтына кіру мүмкін емеÑ, Ñебебі веб Ñайт Ñертификат бекітуді пайдаланады. Желі қателері мен шабуылдары әдетте уақытша болғандықтан, бұл бет кейінірек Ð¶Ò±Ð¼Ñ‹Ñ Ñ–Ñтеуі мүмкін.</translation>
<translation id="6051898664905071243">Бет Ñаны:</translation>
@@ -1374,6 +1412,7 @@
<translation id="610911394827799129"><ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> бетінде Google еÑептік жазбаÑымен шолу тарихының баÑқа да үлгілері болуы мүмкін.</translation>
<translation id="6116338172782435947">Буферге көшірілетін мәтіндер мен кеÑкіндерді көру</translation>
<translation id="6120179357481664955">UPI идентификаторы ÑақталÑын ба?</translation>
+<translation id="6123290840358279103">Виртуалды картаны көру</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Барлық кабельдерді текÑеріп, пайдаланып отырған кез
келген роутерлерді, модемдерді немеÑе баÑқа желі құрылғыларын қайта жүктеңіз.</translation>
@@ -1410,6 +1449,7 @@
<translation id="6289939620939689042">Бет Ñ‚Ò¯ÑÑ–</translation>
<translation id="6290238015253830360">Сізге Ò±Ñынылған мақалалар оÑÑ‹ жерге шығады.</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome браузеріндегі Google Assistant тоқтатылуда</translation>
<translation id="6305205051461490394"><ph name="URL" /> мекенжайына кіру мүмкін емеÑ.</translation>
<translation id="6312113039770857350">Веб-бет қол жетімді емеÑ</translation>
@@ -1435,6 +1475,7 @@
<translation id="6390200185239044127">Z тәрізді жартылай бүктеу</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> Ñайтынан оÑÑ‹ орынға қоюға әкімші ÑаÑÑатымен тыйым Ñалынған.</translation>
+<translation id="6398765197997659313">Толық Ñкраннан шығу</translation>
<translation id="6401136357288658127">Бұл ÑаÑÑат еÑкірді. Орнына <ph name="NEW_POLICY" /> ÑаÑÑатын пайдаланғаныңыз жөн.</translation>
<translation id="6404511346730675251">Бетбелгіні өзгерту</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1447,7 +1488,6 @@
<translation id="6428450836711225518">Телефон нөміріңізді раÑтаңыз</translation>
<translation id="6433490469411711332">Ð‘Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ð°Ò›Ð¿Ð°Ñ€Ð°Ñ‚Ñ‹Ð½ өңдеу</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> байланыÑтан Ð±Ð°Ñ Ñ‚Ð°Ñ€Ñ‚Ñ‚Ñ‹.</translation>
-<translation id="6434309073475700221">Тоқтату</translation>
<translation id="6440503408713884761">Еленбейді</translation>
<translation id="6443406338865242315">қай кеңейтімдер мен плагиндерді орнатқаныңызды;</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1490,6 +1530,7 @@
<translation id="6624427990725312378">Ð‘Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ð°Ò›Ð¿Ð°Ñ€Ð°Ñ‚Ñ‹</translation>
<translation id="6626291197371920147">Ð”Ò±Ñ€Ñ‹Ñ ÐºÐ°Ñ€Ñ‚Ð° нөмірін енгізу</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Search</translation>
+<translation id="6630043285902923878">USB құрылғылары ізделуде...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Тазалау</translation>
@@ -1505,6 +1546,7 @@
<translation id="6671697161687535275">Chromium жүйеÑінен ныÑан Ò±ÑыныÑын алып таÑтау керек пе?</translation>
<translation id="6685834062052613830">Жүйеден шығып, орнатуды аÑқтаңыз</translation>
<translation id="6687335167692595844">Қаріп өлшемі Ñұралды</translation>
+<translation id="6688743156324860098">Жаңарту…</translation>
<translation id="6689249931105087298">Қара нүктені Ñығуға қатыÑÑ‚Ñ‹</translation>
<translation id="6689271823431384964">Сіз еÑептік жазбаға кіргендіктен, Chrome браузері карталарыңызды Google еÑептік жазбаÑына Ñақтауды Ò±Ñынып отыр. Мұны "Параметрлер" бөлімінен өзгертуіңізге болады. Карта иеÑінің аты-жөнін еÑептік жазбаңыздан алынады.</translation>
<translation id="6698381487523150993">ЖаÑалған кезі:</translation>
@@ -1520,6 +1562,7 @@
<translation id="6744009308914054259">БайланыÑÑ‚Ñ‹Ò£ орнауын күткен кезде, офлайн режимдегі мақалаларды оқу үшін "Жүктеп алынғандар" бөліміне кіруіңізге болады.</translation>
<translation id="6753269504797312559">СаÑÑат мәні</translation>
<translation id="6757797048963528358">Құрылғы ұйқы күйіне өтті.</translation>
+<translation id="6767985426384634228">Мекенжайды жаңарту керек пе?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Ðқшыл күлгін</translation>
@@ -1542,6 +1585,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome бұл режимде беттің оқылуын жеңілдетті. Chrome браузерінде баÑтапқы бет қорғалмаған Ð±Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ð°Ñ€Ò›Ñ‹Ð»Ñ‹ алынды.</translation>
<translation id="6891596781022320156">СаÑÑат деңгейіне қолдау көрÑетілмеген.</translation>
+<translation id="6895143722905299846">Виртуалды нөмір:</translation>
<translation id="6895330447102777224">Картаңыз раÑталды</translation>
<translation id="6897140037006041989">Пайдаланушы агенті</translation>
<translation id="6898699227549475383">Ұйым (O)</translation>
@@ -1577,10 +1621,10 @@
<translation id="7004583254764674281">Карталарды жылдам раÑтау үшін Windows Hello функциÑÑын пайдалану</translation>
<translation id="7006930604109697472">Бәрібір жіберу</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Өлшемін өзгертудің параметрлері</translation>
<translation id="7014741021609395734">МаÑштабтау деңгейі</translation>
<translation id="7016992613359344582">Бұл ақылар Ñізге білдіртпей бір рет не қайта-қайта алынуы мүмкін.</translation>
<translation id="7029809446516969842">ÒšÒ±Ð¿Ð¸Ñ Ñөздер</translation>
+<translation id="7030436163253143341">Сертификат жарамÑыз</translation>
<translation id="7031646650991750659">Google Play-дің қай қолданбаларын орнатқаныңызды.</translation>
<translation id="7050187094878475250"><ph name="DOMAIN" /> доменіне қол жеткізуге әрекет еттіңіз, бірақ Ñервер Ñенімді болуы үшін жарамдылық мерзімі тым ұзақ болған Ñертификатты Ò±Ñынды.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Бұл карта қазір Ñақталмайды}other{Бұл карталар қазір Ñақталмайды}}</translation>
@@ -1650,12 +1694,14 @@
<translation id="7300012071106347854">Көкпеңбек</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Жоғары</translation>
+<translation id="7305756307268530424">БаÑуырақ жылдамдықпен баÑтау</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Ð‘Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ð°Ð½Ñ‹Ò›Ñ‚Ð°Ð¼Ð°ÑÑ‹</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" бөлімін жаÑыру</translation>
<translation id="733354035281974745">Құрылғының жергілікті еÑептік жазбаÑын қайта анықтау</translation>
<translation id="7333654844024768166">Жаңа ғана Ò›Ò±Ð¿Ð¸Ñ Ñөзіңізді жалған Ñайтқа енгіздіңіз. Chromium оÑÑ‹ Ò›Ò±Ð¿Ð¸Ñ Ñөз енгізілген <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> және баÑқа Ñайттарға кіріп, оны дереу өзгертуге ÐºÐµÒ£ÐµÑ Ð±ÐµÑ€ÐµÐ´Ñ–.</translation>
<translation id="7334320624316649418">&amp;Қайта ретке келтіруді қайталау</translation>
+<translation id="7337248890521463931">Жолдарды көбірек көрÑету</translation>
<translation id="7337706099755338005">Сіздің платформаңызда қолжетімді емеÑ.</translation>
<translation id="733923710415886693">Сервер Ñертификаты Сертификат айқындығы ÑаÑÑатымен ашылмады.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1663,6 +1709,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Пәрмен жолы</translation>
<translation id="7359588939039777303">Жарнамалар бөгелді.</translation>
+<translation id="7363096869660964304">Ðлайда бәрібір бақылауда болаÑыз. Инкогнито режиміне өткенмен, браузерді қолдану тарихын Ð¶Ò±Ð¼Ñ‹Ñ Ð±ÐµÑ€ÑƒÑˆÑ–Ò£Ñ–Ð·Ð´ÐµÐ½, интернет провайдеріңізден немеÑе Ñіз кірген веб-Ñайттардан жаÑыру мүмкін емеÑ.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />. Chrome параметрлеріне кіріп, мекенжайларды қоÑу және баÑқару үшін Tab, ÑоÑын Enter пернелерін баÑыңыз.</translation>
<translation id="7365849542400970216">Құрылғыны пайдалануыңыз туралы ақпарат қажет пе?</translation>
<translation id="7372973238305370288">іздеу нәтижеÑÑ–</translation>
@@ -1673,7 +1720,9 @@
<translation id="7378594059915113390">Медианы баÑқару Ñлементтері</translation>
<translation id="7378627244592794276">Жоқ</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ҚатыÑÑ‚Ñ‹ емеÑ</translation>
<translation id="7390545607259442187">Картаны раÑтау</translation>
+<translation id="7392089738299859607">Мекенжайды жаңарту</translation>
<translation id="7399802613464275309">ҚауіпÑіздік шараÑÑ‹</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> құрылғыңыз баÑқарылады</translation>
@@ -1688,6 +1737,7 @@
&lt;li&gt;&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome анықтамалық орталығына&lt;/a&gt; кіріп, компьютерден бағдарламалық құралды қалай біржола өшіруге болатынын көріңіз
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Сүйкімді</translation>
<translation id="7416351320495623771">ÒšÒ±Ð¿Ð¸Ñ Ñөздерді баÑқару...</translation>
<translation id="7419106976560586862">Профиль жолы</translation>
<translation id="7437289804838430631">Ð‘Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ð°Ò›Ð¿Ð°Ñ€Ð°Ñ‚Ñ‹Ð½ енгізу</translation>
@@ -1703,7 +1753,7 @@
<translation id="7481312909269577407">БаÑқаға жіберу</translation>
<translation id="7485870689360869515">Деректер табылмады.</translation>
<translation id="7495528107193238112">Бұл мазмұн бөгелген. МәÑелені шешу үшін Ñайт иеÑімен Ð±Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ð¾Ñ€Ð½Ð°Ñ‚Ñ‹Ò£Ñ‹Ð·.</translation>
-<translation id="7498234416455752244">Әрі қарай өзгерту</translation>
+<translation id="7498193950643227031">Өлшемін өзгертÑеңіз, Ð´Ò±Ñ€Ñ‹Ñ Ð¶Ò±Ð¼Ñ‹Ñ Ñ–Ñтемеуі мүмкін. Қолданбалардың өлшемін өзгертуді <ph name="SETTINGS" /> бөлімінен шектеуіңізге болады.</translation>
<translation id="7503664977220660814">Жаңа ғана Ò›Ò±Ð¿Ð¸Ñ Ñөзіңізді жалған Ñайтқа енгіздіңіз. Chromium оÑÑ‹ Ò›Ò±Ð¿Ð¸Ñ Ñөз пайдаланылатын <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> және баÑқа Ñайттар үшін Ñақталған Ò›Ò±Ð¿Ð¸Ñ Ñөздерді текÑеруді Ò±Ñынады.</translation>
<translation id="7508255263130623398">Қайтарылған құрылғының Ñервердегі идентификаторы Ð±Ð¾Ñ Ð½ÐµÐ¼ÐµÑе оның ағымдағы идентификаторына ÑÓ™Ð¹ÐºÐµÑ ÐºÐµÐ»Ð¼ÐµÐ¹Ð´Ñ–</translation>
<translation id="7508870219247277067">Қою жаÑыл</translation>
@@ -1723,6 +1773,7 @@
<translation id="7548892272833184391">Ð‘Ð°Ð¹Ð»Ð°Ð½Ñ‹Ñ Ò›Ð°Ñ‚ÐµÐ»ÐµÑ€Ñ–Ð½ түзету</translation>
<translation id="7549584377607005141">Бұл веб-бет Ð´Ò±Ñ€Ñ‹Ñ ÐºÓ©Ñ€Ñетілу мақÑатында бұрын енгізілген деректерді қажет етеді. Бұл деректерді қайта жібере алаÑыз, бірақ бұл арқылы оÑÑ‹ бетте бұрын орындалған кез келген әрекетті қайталайÑыз.</translation>
<translation id="7550637293666041147">Құрылғыңыздың пайдаланушы аты және Chrome браузеріңіздің пайдаланушы аты</translation>
+<translation id="755279583747225797">Сынақ нұÑқаÑÑ‹ Ñ–Ñке қоÑылған.</translation>
<translation id="7552846755917812628">КелеÑÑ– кеңеÑтерді орындап көріңіз:</translation>
<translation id="7554475479213504905">Қайта жүктеу және бәрібір көрÑету</translation>
<translation id="7554791636758816595">Жаңа қойынды</translation>
@@ -1741,7 +1792,6 @@
<translation id="7610193165460212391">Мән <ph name="VALUE" /> ауқымынан Ñ‚Ñ‹Ñ.</translation>
<translation id="7613889955535752492">Мерзімі бітеді: <ph name="EXPIRATION_MONTH" /> / <ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Chrome параметрлерінде Ò›Ò±Ð¿Ð¸Ñ Ñөздеріңізді көру және баÑқару үшін Tab, одан кейін Enter пернеÑін баÑыңыз.</translation>
-<translation id="7615602087246926389">Google еÑептік жазба Ò›Ò±Ð¿Ð¸Ñ Ñөзінің баÑқа нұÑқаÑын пайдалану арқылы шифрланған дерек Ñізде бұрыннан бар. Оны оÑÑ‹ жерге енгізіңіз.</translation>
<translation id="7616645509853975347">Әкімші браузердегі Chrome Enterprise Connectors қызметін қоÑÑ‚Ñ‹. Бұл коннекторлар кейбір деректеріңізді пайдалануы мүмкін.</translation>
<translation id="7619838219691048931">Соңғы парақ</translation>
<translation id="762844065391966283">Бір-бірден</translation>
@@ -1806,13 +1856,12 @@
<translation id="782886543891417279">Сіз пайдаланып жатқан Wi-Fi (<ph name="WIFI_NAME" />) желіÑÑ– оның кіру бетіне кіруіңізді талап етеді.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Жоқ}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Файл түрімен байланыÑÑ‚Ñ‹ файлдарды ашу.</translation>
<translation id="7862185352068345852">Сайттан шыққыңыз келе ме?</translation>
<translation id="7865448901209910068">Ең жақÑÑ‹ жылдамдық</translation>
<translation id="7874263914261512992">Жаңа ғана Ò›Ò±Ð¿Ð¸Ñ Ñөзіңізді жалған Ñайтқа енгіздіңіз. Chrome оÑÑ‹ Ò›Ò±Ð¿Ð¸Ñ Ñөз пайдаланылатын <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> және баÑқа Ñайттар үшін Ñақталған Ò›Ò±Ð¿Ð¸Ñ Ñөздерді текÑеруді Ò±Ñынады.</translation>
<translation id="7878562273885520351">ÒšÒ±Ð¿Ð¸Ñ Ñөзіңіз ұрланған болуы мүмкін</translation>
+<translation id="7880146494886811634">Мекенжайды Ñақтау</translation>
<translation id="7882421473871500483">Қоңыр</translation>
<translation id="7887683347370398519">CVC нөмірін енгізіп, әрекетті қайталаңыз</translation>
<translation id="7887885240995164102">"Суреттегі Ñурет" режиміне өту</translation>
@@ -1820,6 +1869,7 @@
<translation id="7894280532028510793">Ð”Ò±Ñ€Ñ‹Ñ Ð¶Ð°Ð·Ñ‹Ð»Ò“Ð°Ð½ болÑа, <ph name="BEGIN_LINK" />Network Diagnostics құралын Ñ–Ñке қоÑып көріңіз<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">БелгіÑіз</translation>
+<translation id="793209273132572360">Мекенжайды жаңарту керек пе?</translation>
<translation id="7932579305932748336">Қаптау</translation>
<translation id="79338296614623784">Ð”Ò±Ñ€Ñ‹Ñ Ñ‚ÐµÐ»ÐµÑ„Ð¾Ð½ нөмірін енгізіңіз</translation>
<translation id="7934052535022478634">Төлем жаÑалды.</translation>
@@ -1890,6 +1940,7 @@
<translation id="8175796834047840627">Сіз еÑептік жазбаға кіргендіктен, Chrome браузері карталарыңызды Google еÑептік жазбаÑына Ñақтауды Ò±Ñынып отыр. Мұны параметрлерге кіріп өзгертуіңізге болады.</translation>
<translation id="8176440868214972690">Бұл құрылғының әкімшіÑÑ– келеÑÑ– веб-Ñайттарға бірқатар ақпарат (мыÑалы, параметрлер немеÑе ÑаÑÑаттар) жіберді.</translation>
<translation id="8184538546369750125">Ғаламдық әдепкі параметрді пайдалану (Ñ€Ò±Ò›Ñат беру)</translation>
+<translation id="8193086767630290324">ÒšÒ±Ð¿Ð¸Ñ Ð´ÐµÐ¿ белгіленген деректер арқылы жаÑалған әрекеттер</translation>
<translation id="8194797478851900357">&amp;Жылжуды болдырмау</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" идентификаторы бар кеңейтім үшін жарамÑыз жаңарту URL мекенжайы.</translation>
<translation id="8202097416529803614">ТапÑырыÑÑ‚Ñ‹Ò£ жиынтық мәліметтері</translation>
@@ -1912,6 +1963,7 @@
<translation id="8249296373107784235">Доғару</translation>
<translation id="8249320324621329438">Соңғы алынғаны:</translation>
<translation id="8253091569723639551">Төлем мекенжайы қажет</translation>
+<translation id="8257387598443225809">Бұл қолданба мобильдік құрылғыға арналған</translation>
<translation id="825929999321470778">Барлық Ñақталған Ò›Ò±Ð¿Ð¸Ñ Ñөздерді көрÑету</translation>
<translation id="8261506727792406068">Жою</translation>
<translation id="8262952874573525464">Төменгі жиегін тігу</translation>
@@ -2035,7 +2087,6 @@
<translation id="8719528812645237045">Жоғарғы жағын бірнеше рет теÑу</translation>
<translation id="8725066075913043281">Әрекетті қайталау</translation>
<translation id="8726549941689275341">Бет өлшемі:</translation>
-<translation id="8728672262656704056">Инкогнито режиміне өттіңіз</translation>
<translation id="8730621377337864115">Дайын</translation>
<translation id="8731544501227493793">"ÒšÒ±Ð¿Ð¸Ñ Ñөздерді баÑқару" түймеÑÑ–. Chrome параметрлерінде Ò›Ò±Ð¿Ð¸Ñ Ñөздеріңізді көру және баÑқару үшін Enter пернеÑін баÑыңыз.</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> құрылғыңызды <ph name="MANAGER" /> баÑқарады</translation>
@@ -2112,6 +2163,7 @@
<translation id="9020542370529661692">Бұл бет <ph name="TARGET_LANGUAGE" /> тіліне аударылды</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(жарамÑыз)</translation>
+<translation id="9030265603405983977">Бір Ñ‚Ò¯ÑÑ‚Ñ–</translation>
<translation id="9035022520814077154">ҚауіпÑіздік қатеÑÑ–</translation>
<translation id="9038649477754266430">Беттерді жылдамырақ жүктеу үшін болжам қызметін пайдаланыңыз</translation>
<translation id="9039213469156557790">Сонымен қатар бұл бет баÑқа да қауіпті реÑурÑтарды қамтиды. Бұл реÑурÑтарды өту кезінде баÑқалар көре алады және беттің Ñ–Ñ-әрекетіне Ó©Ð·Ð³ÐµÑ€Ñ–Ñ ÐµÐ½Ð³Ñ–Ð·Ñƒ мақÑатында оны шабуылшы өзгерте алады.</translation>
@@ -2135,6 +2187,7 @@
<translation id="91108059142052966">ÒšÒ±Ð¿Ð¸Ñ Ð¼Ð°Ð·Ð¼Ò±Ð½ көрініп тұрÑа, әкімші ÑаÑÑаты <ph name="APPLICATION_TITLE" /> веб-Ñайтына Ñкранды көрÑетпейді.</translation>
<translation id="9114524666733003316">Карта раÑталуда...</translation>
<translation id="9114581008513152754">Бұл браузер ÐºÐ¾Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð½ÐµÐ¼ÐµÑе баÑқа ұйым арқылы баÑқарылмайды. Құрылғыдағы әрекет Chrome браузерінен Ñ‚Ñ‹Ñ Ð±Ð°Ñқарылуы мүмкін. <ph name="BEGIN_LINK" />Толығырақ<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Жаңа</translation>
<translation id="9119042192571987207">Жүктеп Ñалынды</translation>
<translation id="9128016270925453879">СаÑÑаттар жүктелді.</translation>
<translation id="9128870381267983090">Желіге қоÑылу</translation>
@@ -2153,6 +2206,7 @@
<translation id="9170848237812810038">&amp;Болдырмау</translation>
<translation id="9171296965991013597">Қолданба жабылÑын ба?</translation>
<translation id="9173282814238175921">Жалғыз құжат/жаңа парақ</translation>
+<translation id="9173995187295789444">Bluetooth құрылғыларын іздеуде...</translation>
<translation id="917450738466192189">Сервер Ñертификаты жарамÑыз.</translation>
<translation id="9174917557437862841">Қойынды ауыÑтыру түймеÑÑ–: оÑÑ‹ қойындыға ауыÑу үшін Enter пернеÑін баÑыңыз.</translation>
<translation id="9179703756951298733">Төлемдер мен неÑиелік карта туралы ақпаратты Chrome параметрлерінен баÑқарыңыз.</translation>
diff --git a/chromium/components/strings/components_strings_km.xtb b/chromium/components/strings/components_strings_km.xtb
index 0d71ba5cf2f..38c465deebf 100644
--- a/chromium/components/strings/components_strings_km.xtb
+++ b/chromium/components/strings/components_strings_km.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">ប្រសិនបើបានធីក Chrome នឹងផ្ទុកច្បាប់ចម្លងនៃកាážážšáž”ស់អ្នកនៅលើឧបករណáŸáž“áŸáŸ‡ážŸáž˜áŸ’រាប់ការបំពáŸáž‰áž”ែបបទឲ្យបានលឿនជាងមុន។</translation>
<translation id="1110994991967754504">ជ្រើសរើស​ការអនុញ្ញាážâ€‹ážŸáž˜áŸ’រាប់ <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">បកក្រោយការážáž˜áŸ’រៀបឡើងវិញ</translation>
+<translation id="1123753900084781868">មិន​អាចប្រើអក្សររážáŸ‹áž€áŸ’នុងពáŸáž›áž‡áž¶áž€áŸ‹ážŸáŸ’ដែងនៅពáŸáž›áž“áŸáŸ‡áž”ានទáŸ</translation>
<translation id="1125573121925420732">ការ​ព្រមាន​អាចកើážâ€‹áž˜áž¶áž“​​ជាធម្មážáž¶ ​ážážŽáŸˆâ€‹áž–áŸáž›â€‹â€‹áž‚áŸáž áž‘ំពáŸážšâ€‹áž’្វើ​បច្ចុប្បន្ន​ភាព​សុវážáŸ’ážáž·áž—ាព​របស់​វា។ វា​នឹង​ល្អ​ប្រសើរ​ឡើងវិញ​ក្នុង​ពáŸáž›â€‹áž†áž¶áž”់ៗ។</translation>
<translation id="112840717907525620">ស្ážáž¶áž“ភាពឃ្លាំងសម្ងាážáŸ‹áž‚ោលការណáŸáž˜áž¶áž“ភាពប្រក្រážáž¸</translation>
<translation id="1130564665089811311">ប៊ូážáž»áž„ "បកប្រែទំពáŸážš" ចុច "Enter" ដើម្បីបកប្រែទំពáŸážšáž“áŸáŸ‡ážŠáŸ„យប្រើ Google បកប្រែ</translation>
@@ -75,6 +76,7 @@
<translation id="1240347957665416060">ឈ្មោះឧបករណáŸâ€‹ážšáž”ស់អ្នក</translation>
<translation id="124116460088058876">ភាសា​ច្រើន​ទៀáž</translation>
<translation id="1243027604378859286">អ្នក​និពន្ធ៖</translation>
+<translation id="1246424317317450637">ដិáž</translation>
<translation id="1250759482327835220">ដើម្បី​បង់ប្រាក់​លឿន​ជាងនáŸáŸ‡â€‹áž“ៅពáŸáž›â€‹áž€áŸ’រោយ សូម​រក្សា​ទុកកាហឈ្មោះ និង​អាសយដ្ឋាន​ចáŸáž‰â€‹ážœáž·áž€áŸ’កយបážáŸ’រ​​ទៅក្នុង​គណនី Google របស់អ្នក។</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (បានធ្វើសមកាលកម្ម)</translation>
<translation id="1256368399071562588">&lt;p&gt;ប្រសិន​បើ​អ្នក​ព្យាយាមចូល​ទៅកាន់​គáŸáž áž‘ំពáŸážš ហើយ​វា​មិន​បើក។ ជាដំបូង សូមព្យាយាមដោះ​ស្រាយ​បញ្ហាដោយ​​ប្រើ​ជំហាន​នៃការដោះស្រាយបញ្ហា​ទាំងនáŸáŸ‡áŸ–&lt;/p&gt;
@@ -157,6 +159,7 @@
<translation id="1476595624592550506">ប្ដូរ​ពាក្យ​សម្ងាážáŸ‹â€‹ážšáž”ស់​អ្នក</translation>
<translation id="1484290072879560759">ជ្រើសរើសអាសយដ្ឋាន​ដឹក​ជញ្ជូន</translation>
<translation id="1492194039220927094">ការជំរុញ​គោលការណáŸáŸ–</translation>
+<translation id="1495677929897281669">ážáŸ’រឡប់ទៅ​ផ្ទាំងវិញ</translation>
<translation id="1501859676467574491">បង្ហាញកាážáž–ីគណនី Google របស់អ្នក</translation>
<translation id="1507202001669085618">&lt;p&gt;អ្នកនឹង​មើលឃើញ​បញ្ហានáŸáŸ‡ ប្រសិនបើ​អ្នកកំពុង​ប្រើច្រក​ចូល​ Wi-Fi ដែលអ្នក​ážáŸ’រូវážáŸ‚ចុះឈ្មោះចូល មុនពáŸáž›â€‹ážŠáŸ‚លអ្នកអាច​ភ្ជាប់អ៊ីន​ធឺណិážáŸ”&lt;/p&gt;
&lt;p&gt;ដើម្បី​ដោះ​ស្រាយ​បញ្ហានáŸáŸ‡ សូមចុច &lt;strong&gt;ភ្ជាប់&lt;/strong&gt; នៅលើ​ទំពáŸážšâ€‹ážŠáŸ‚ល​អ្នក​កំពុង​ព្យាយាម​បើក។&lt;/p&gt;</translation>
@@ -172,6 +175,7 @@
<translation id="1532118530259321453">ទំពáŸážšáž“áŸáŸ‡â€‹áž“ិយាយ​ážáž¶</translation>
<translation id="153384715582417236">មានážáŸ‚ប៉ុណ្ណឹងទáŸ</translation>
<translation id="1536390784834419204">បកប្រែ​ទំពáŸážš</translation>
+<translation id="1539840569003678498">បានផ្ញើ​របាយការណáŸáŸ–</translation>
<translation id="154408704832528245">ជ្រើសរើស​អាសយដ្ឋាន​ចែកចាយ</translation>
<translation id="1549470594296187301">ážáŸ’រូវបើកដំណើរការ JavaScript ដើម្បីប្រើលក្ážážŽáŸˆáž–ិសáŸážŸáž“áŸáŸ‡áŸ”</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -214,16 +218,19 @@
<translation id="1682696192498422849">គែមážáŸ’លី​មុនគáŸ</translation>
<translation id="168693727862418163">ážáž˜áŸ’លៃគោលការណáŸáž“áŸáŸ‡áž˜áž·áž“ážáŸ’រូវនឹងគំនូស​ážáž¶áž„របស់វាទ០ហើយនឹងមិនážáŸ’រូវបានអើពើទáŸáŸ”</translation>
<translation id="168841957122794586">វិញ្ញាបនបáŸážáŸ’រម៉ាស៊ីនមáŸáž•áŸ’ទុកសោគ្រីបážáŸ’សោយ។</translation>
+<translation id="1696290444144917273">មើលពáŸážáŸŒáž˜áž¶áž“លម្អិážâ€‹áž¢áŸ†áž–ីកាážáž“ិម្មិáž</translation>
<translation id="1697532407822776718">អ្នកážáŸ’រូវបានកំណážáŸ‹ážšáž½áž…អស់ហើយ!</translation>
<translation id="1703835215927279855">សំបុážáŸ’ážš</translation>
<translation id="1706954506755087368">{1,plural, =1{ម៉ាស៊ីនមáŸáž“áŸáŸ‡áž˜áž·áž“អាចបង្ហាញážáž¶ážœáž¶áž‡áž¶ <ph name="DOMAIN" /> áž‘áŸáŸ” វិញ្ញាបនបážáŸ’រសុវážáŸ’ážáž·áž—ាពរបស់វាážáŸ’រូវបានសន្មážážáž¶áž˜áž¶áž“សុពលភាពចាប់ពីážáŸ’ងៃស្អែកទៅ។ វាអាចបណ្ážáž¶áž›áž˜áž€áž–ីការកំណážáŸ‹ážšáž…នាសម្ពáŸáž“្ធážáž»ážŸ ឬអ្នកវាយប្រហារកំពុងរារាំងការážáž—្ជាប់របស់អ្នក។}other{ម៉ាស៊ីនមáŸáž“áŸáŸ‡áž˜áž·áž“អាចបង្ហាញážáž¶ážœáž¶áž‡áž¶ <ph name="DOMAIN" /> áž‘áŸáŸ” វិញ្ញាបនបážáŸ’រសុវážáŸ’ážáž·áž—ាពរបស់វាážáŸ’រូវបានសន្មážážáž¶áž˜áž¶áž“សុពលភាពក្នុងរយៈពáŸáž› # ážáŸ’ងៃបន្ទាប់។ វាអាចបណ្ážáž¶áž›áž˜áž€áž–ីការកំណážáŸ‹ážšáž…នាសម្ពáŸáž“្ធážáž»ážŸ ឬអ្នកវាយប្រហារកំពុងរារាំងការážáž—្ជាប់របស់អ្នក។}}</translation>
<translation id="1710259589646384581">ប្រពáŸáž“្ធប្រážáž·áž”ážáŸ’ážáž·áž€áž¶ážš</translation>
+<translation id="1711234383449478798">មិនអើពើ ដោយសារ <ph name="POLICY_NAME" /> មិនážáŸ’រូវបាន​កំណážáŸ‹áž‘ៅ <ph name="VALUE" /> áž‘áŸáŸ”</translation>
<translation id="1712552549805331520"><ph name="URL" /> ចង់​ផ្ទុក​ទិន្ននáŸáž™â€‹áž“ៅក្នុង​កុំព្យូទáŸážšâ€‹áž˜áž¼áž›ážŠáŸ’ឋាន​របស់អ្នក​ជាអចិន្ážáŸ’រៃយáŸ</translation>
<translation id="1713628304598226412">ទម្រទី 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">ប្រអប់​សំបុážáŸ’រទី 3</translation>
<translation id="1718029547804390981">ឯកសារធំពáŸáž€ មិន​អាចធ្វើចំណារបានទáŸ</translation>
<translation id="1721424275792716183">* ážáž˜áŸ’រូវឲ្យបំពáŸáž‰</translation>
+<translation id="1727613060316725209">វិញ្ញាបនបážáŸ’រ​មានសុពលភាព</translation>
<translation id="1727741090716970331">បញ្ចូល​លáŸážáž”ណ្ណដែល​​ážáŸ’រឹមážáŸ’រូវ</translation>
<translation id="1728677426644403582">អ្នក​កំពុងមើល​ប្រភព​របស់គáŸáž áž‘ំពáŸážš</translation>
<translation id="173080396488393970">មិនស្គាល់បណ្ណប្រភáŸáž‘áž“áŸáŸ‡áž‘áŸ</translation>
@@ -248,7 +255,6 @@
ážáž¶áž˜ážŸáŸ†ážŽáž¾ážšáž”ស់អ្នកសម្រាប់ <ph name="SITE" />។ ប្រážáž·áž”ážáŸ’ážáž·áž€ážšâ€‹áž‚áŸáž áž‘ំពáŸážšâ€‹áž¢áž¶áž…ប្រើ
គោលការណáŸâ€‹ážŠáž¾áž˜ ដើម្បីកំណážáŸ‹â€‹ážšáž…នាសម្ពáŸáž“្ធ​សុវážáŸ’ážáž·áž—ាព និង​លក្ážážŽážŸáž˜áŸ’áž”ážáŸ’ážáž·â€‹áž•áŸ’សáŸáž„ទៀážâ€‹ážŸáž˜áŸ’រាប់​គáŸáž áž‘ំពáŸážšâ€‹áŸ”</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">សូមធ្វើបច្ចុប្បន្នភាពឃ្លាសម្ងាážáŸ‹ážŸáž˜áž€áž˜áŸ’មរបស់អ្នក។</translation>
<translation id="1787142507584202372">ផ្ទាំង​ដែល​អ្នកបានបើកបង្ហាញ​នៅ​ទីនáŸáŸ‡</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, អាចធ្វើ​សកម្មភាព​បានច្រើន សូមចុច Tab ដើម្បីរុករក​សកម្មភាព​ទាំងនោះ</translation>
@@ -281,6 +287,7 @@
<translation id="1919345977826869612">ពាណិជ្ជកម្ម</translation>
<translation id="1919367280705858090">ទទួល​បានជំនួយដោយ​ប្រើ​​សារ​បញ្ហា​ជាក់លាក់មួយ</translation>
<translation id="192020519938775529">{COUNT,plural, =0{គ្មាន}=1{ទំពáŸážš 1}other{ទំពáŸážš #}}</translation>
+<translation id="1924727005275031552">ážáŸ’មី</translation>
<translation id="1945968466830820669">អ្នក​អាច​បាážáŸ‹áž”ង់​សិទ្ធិចូល​ប្រើ​គណនីរបស់​ស្ážáž¶áž”áŸáž“​អ្នក ឬ​ជួបប្រទះ​នឹង​ការលួចយក​អážáŸ’ážážŸáž‰áŸ’ញាណ។ Chromium សូមណែនាំ​ឱ្យប្ដូរ​ពាក្យសម្ងាážáŸ‹â€‹ážšáž”ស់អ្នក​ឥឡូវ​នáŸáŸ‡áŸ”</translation>
<translation id="1947454675006758438">កិប​ážáž¶áž„លើ​ផ្នែកážáž¶áž„ស្ដាំ</translation>
<translation id="1958218078413065209">ពិន្ទុ​ážáŸ’ពស់បំផុážâ€‹ážšáž”ស់អ្នកគឺ <ph name="SCORE" />។</translation>
@@ -303,12 +310,14 @@
<translation id="2042213636306070719">ទម្រទី 7</translation>
<translation id="204357726431741734">ចូលគណនី ដើម្បីប្រើ​ពាក្យសម្ងាážáŸ‹â€‹ážŠáŸ‚លរក្សាទុក​នៅក្នុងគណនី Google របស់អ្នក</translation>
<translation id="2053111141626950936">ទំពáŸážšáž‡áž¶ <ph name="LANGUAGE" /> នឹងមិនážáŸ’រូវ​បានបកប្រែទáŸáŸ”</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{នៅពáŸáž›áž”ើកការគ្រប់គ្រងនáŸáŸ‡ ហើយស្ážáž¶áž“ភាពកំពុងសកម្ម នោះ Chrome កំណážáŸ‹ážáž¶ážáž¾áž€áŸ’រុមមនុស្សមួយក្រុមធំ ឬ "ក្រុមមនុស្សដូចគ្នា" ណា ដែលសកម្មភាព​រុករក​ážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិážážáŸ’មីៗរបស់អ្នកស្រដៀងបំផុážáŸ” អ្នកផ្សាយ​ពាណិជ្ជកម្ម​អាចជ្រើសរើស​ការផ្សាយពាណិជ្ជកម្ម​សម្រាប់ក្រុម​នោះ ហើយសកម្មភាព​រុករក​ážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិážážšáž”ស់អ្នកážáŸ’រូវបានរក្សាជាលក្ážážŽáŸˆáž¯áž€áž‡áž“នៅលើឧបករណáŸážšáž”ស់អ្នក។ ក្រុមរបស់អ្នកážáŸ’រូវបានធ្វើបច្ចុប្បន្នភាពរៀងរាល់ážáŸ’ងៃ។}=1{នៅពáŸáž›áž”ើកការគ្រប់គ្រងនáŸáŸ‡ ហើយស្ážáž¶áž“ភាពកំពុងសកម្ម នោះ Chrome កំណážáŸ‹ážáž¶ážáž¾áž€áŸ’រុមមនុស្សមួយក្រុមធំ ឬ "ក្រុមមនុស្សដូចគ្នា" ណា ដែលសកម្មភាព​រុករក​ážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិážážáŸ’មីៗរបស់អ្នកស្រដៀងបំផុážáŸ” អ្នកផ្សាយ​ពាណិជ្ជកម្ម​អាចជ្រើសរើស​ការផ្សាយពាណិជ្ជកម្ម​សម្រាប់ក្រុម​នោះ ហើយសកម្មភាព​រុករក​ážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិážážšáž”ស់អ្នកážáŸ’រូវបានរក្សាជាលក្ážážŽáŸˆáž¯áž€áž‡áž“នៅលើឧបករណáŸážšáž”ស់អ្នក។ ក្រុមរបស់អ្នកážáŸ’រូវបានធ្វើបច្ចុប្បន្នភាពរៀងរាល់ážáŸ’ងៃ។}other{នៅពáŸáž›áž”ើកការគ្រប់គ្រងនáŸáŸ‡ ហើយស្ážáž¶áž“ភាពកំពុងសកម្ម នោះ Chrome កំណážáŸ‹ážáž¶ážáž¾áž€áŸ’រុមមនុស្សមួយក្រុមធំ ឬ "ក្រុមមនុស្សដូចគ្នា" ណា ដែលសកម្មភាព​រុករក​ážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិážážáŸ’មីៗរបស់អ្នកស្រដៀងបំផុážáŸ” អ្នកផ្សាយ​ពាណិជ្ជកម្ម​អាចជ្រើសរើស​ការផ្សាយពាណិជ្ជកម្ម​សម្រាប់ក្រុម​នោះ ហើយសកម្មភាព​រុករក​ážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិážážšáž”ស់អ្នកážáŸ’រូវបានរក្សាជាលក្ážážŽáŸˆáž¯áž€áž‡áž“នៅលើឧបករណáŸážšáž”ស់អ្នក។ ក្រុមរបស់អ្នកážáŸ’រូវបានធ្វើបច្ចុប្បន្នភាពរៀងរាល់ {NUM_DAYS} ážáŸ’ងៃ។}}</translation>
<translation id="2053553514270667976">áž›áŸážáž€áž¼ážŠážáŸ†áž”ន់</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{ការផ្ážáž›áŸ‹áž™áŸ„បល់ 1}other{ការផ្ážáž›áŸ‹áž™áŸ„បល់ #}}</translation>
<translation id="2071692954027939183">ការជូនដំណឹងážáŸ’រូវបានទប់ស្កាážáŸ‹ážŠáŸ„យស្វáŸáž™áž”្រវážáŸ’ážáž· ដោយសារជាធម្មážáž¶ អ្នកមិនអនុញ្ញាážáž€áž¶ážšáž‡áž¼áž“ដំណឹងទáŸ</translation>
<translation id="2079545284768500474">ážáŸ’រឡប់វិញ</translation>
<translation id="20817612488360358">ការកំណážáŸ‹áž”្រូកស៊ីប្រពáŸáž“្ធážáŸ’រូវបានកំណážáŸ‹ážŠáž¾áž˜áŸ’បីប្រើ ប៉ុន្ážáŸ‚ការកំណážáŸ‹áž”្រូកស៊ីជាក់លាក់កáŸážáŸ’រូវបានបញ្ជាក់ផងដែរ។</translation>
<translation id="2082238445998314030">លទ្ធផល <ph name="RESULT_NUMBER" /> នៃ <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">រក្សាទុក…</translation>
<translation id="2088086323192747268">គ្រប់គ្រងប៊ូážáž»áž„សម​កាល​កម្ម, ចុច "Enter" ដើម្បីគ្រប់គ្រងážáž¶áž–áŸážáŸŒáž˜áž¶áž“អ្វីដែលអ្នកធ្វើសមកាលកម្មនៅក្នុងការកំណážáŸ‹ Chrome</translation>
<translation id="2091887806945687916">សំឡáŸáž„</translation>
<translation id="2094505752054353250">ដែនមិនážáŸ’រូវគ្នា</translation>
@@ -381,6 +390,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> ážáž˜áŸ’រូវឲ្យមានឈ្មោះអ្នកប្រើ និងពាក្យសម្ងាážáŸ‹áŸ”</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" /> áž•áž»ážáž€áŸ†ážŽážáŸ‹áž“ៅážáŸ’ងៃទី <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">ការកំណážáŸ‹â€‹áž‚្រប់គ្រង​ដោយ​អ្នកគ្រប់គ្រង​របស់អ្នក</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ចង់ផ្គូផ្គង</translation>
<translation id="2344028582131185878">ទាញយកស្វáŸáž™áž”្រវážáŸ’ážáž·</translation>
<translation id="2346319942568447007">រូបភាព​ដែលអ្នក​បានចម្លង</translation>
<translation id="2354001756790975382">ចំណាំផ្សáŸáž„ទៀáž</translation>
@@ -388,8 +398,10 @@
<translation id="2355395290879513365">អ្នកវាយប្រហារអាចនឹងមើលឃើញរូបភាពដែលអ្នកកំពុងមើលនៅលើគáŸáž áž‘ំពáŸážšáž“áŸáŸ‡ និងបញ្ឆោážáž¢áŸ’នកដោយធ្វើការកែសម្រួលពួកវា។</translation>
<translation id="2356070529366658676">សួរ</translation>
<translation id="2357481397660644965">ឧបករណáŸâ€‹ážšáž”ស់អ្នក​ស្ážáž·ážáž€áŸ’រោមការគ្រប់គ្រង​របស់ <ph name="DEVICE_MANAGER" /> ហើយ​គណនី​របស់អ្នកស្ážáž·ážáž€áŸ’រោមការគ្រប់គ្រង​របស់ <ph name="ACCOUNT_MANAGER" />។</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ក្នុងរយៈពáŸáž›ážáž·áž…ជាងមួយážáŸ’ងៃ}=1{ក្នុងរយៈពáŸáž›áž˜áž½áž™ážáŸ’ងៃ}other{ក្នុងរយៈពáŸáž› {NUM_DAYS} ážáŸ’ងៃ}}</translation>
<translation id="2359629602545592467">ច្រើន</translation>
<translation id="2359808026110333948">បន្áž</translation>
+<translation id="2359961752320758691">áž›áŸážáž€áž¶ážâ€‹áž“ិម្មិážážšáž”ស់អ្នក​ážáŸ’រូវបាន​បំពáŸáž‰áž…ូល។</translation>
<translation id="2367567093518048410">កម្រិáž</translation>
<translation id="2372464001869762664">បន្ទាប់​ពីអ្នក​បញ្ជាក់​ហើយ áž–áŸážáŸŒáž˜áž¶áž“​លម្អិážâ€‹áž¢áŸ†áž–ី​កាážážŠáŸ‚ល​បានមកពីគណនី Google របស់អ្នក​នឹងážáŸ’រូវ​បាន​ចែករំលែក​ជាមួយ​គáŸáž áž‘ំពáŸážšâ€‹áž“áŸáŸ‡áŸ” រកមើល CVC នៅក្នុង​ពáŸážáŸŒáž˜áž¶áž“លម្អិážâ€‹áž¢áŸ†áž–ីគណនី Plex របស់អ្នក។</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -400,6 +412,7 @@
<translation id="239429038616798445">មិនមានមធ្យោបាយដឹកជញ្ជូនážáž¶áž˜áž”្រៃសណីយáŸáž“áŸáŸ‡áž‘áŸáŸ” សូមសាកល្បងមធ្យោបាយផ្សáŸáž„។</translation>
<translation id="2396249848217231973">បកក្រោយការលុប</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">ចាស់</translation>
<translation id="2413528052993050574">ម៉ាស៊ីនមáŸáž“áŸáŸ‡áž˜áž·áž“អាចបង្ហាញážáž¶ážœáž¶áž‡áž¶ <ph name="DOMAIN" /> ទ០វិញ្ញាបនបáŸážáŸ’រសុវážáŸ’ážáž·áž—ាពរបស់វា
អាចážáŸ’រូវបានបញ្ឈប់សុពលភាព។ áž“áŸáŸ‡áž¢áž¶áž…បណ្ážáž¶áž›áž˜áž€áž–ីការកំណážáŸ‹áž˜áž·áž“ážáŸ’រឹមážáŸ’រូវ ឬមានការស្ទាក់ការភ្ជាប់របស់អ្នកពីអ្នកវាយប្រហារ។</translation>
<translation id="2414886740292270097">áž„áž„áž¹áž</translation>
@@ -428,10 +441,10 @@
<translation id="2521385132275182522">កិប​ážáž¶áž„ក្រោម​ផ្នែកážáž¶áž„​ស្ដាំ</translation>
<translation id="2523886232349826891">បានរក្សាទុក​នៅលើážáŸ‚ឧបករណáŸáž“áŸáŸ‡â€‹áž”៉ុណ្ណោះ</translation>
<translation id="2524461107774643265">បញ្ចូល​ពáŸážáŸŒáž˜áž¶áž“​បន្ážáŸ‚ម</translation>
-<translation id="2526590354069164005">ដáŸážŸáŸážáž”</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{áž“áž·áž„ 1 ​ទៀáž}other{áž“áž·áž„ # ទៀáž}}</translation>
<translation id="2536110899380797252">បញ្ចូល​អាសយដ្ឋាន</translation>
<translation id="2539524384386349900">ស្វែងរក</translation>
+<translation id="2541219929084442027">ទំពáŸážšâ€‹ážŠáŸ‚លអ្នកមើល​នៅក្នុង​ផ្ទាំងឯកជន​នឹងមិនស្ážáž·ážáž“ៅក្នុង​ប្រវážáŸ’ážáž·ážšáž”ស់​កម្មវិធីរុករកážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិហកន្លែងផ្ទុក​ážáž¼áž‚ី ឬប្រវážáŸ’ážáž·â€‹ážŸáŸ’វែងរក​របស់អ្នកទ០បន្ទាប់ពីអ្នកបានបិទ​ផ្ទាំងឯកជន​ទាំងអស់​របស់អ្នក។ ឯកសារដែលអ្នក​ទាញយក ឬចំណាំ​ដែលអ្នកបង្កើážâ€‹áž“ឹងážáŸ’រូវបានរក្សាទុក។</translation>
<translation id="2544644783021658368">ឯកសារ​ážáŸ‚មួយ</translation>
<translation id="254947805923345898">ážáž˜áŸ’លៃ​របស់គោលការណáŸâ€‹áž‚្មានសុពលភាពទáŸáŸ”</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> បានផ្ញើការឆ្លើយážáž”ដែលមិនážáŸ’រឹមážáŸ’រូវ</translation>
@@ -451,6 +464,7 @@
<translation id="2629325967560697240">ដើម្បីទទួលបានកម្រិážážŸáž»ážœážáŸ’ážáž·áž—ាពážáŸ’ពស់បំផុážážšáž”ស់ Chrome <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />សូមបើកការការពារ​ដែលប្រសើរជាងមុន<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">រកមិន​ឃើញអាសយដ្ឋាន IP ម៉ាស៊ីនមáŸážšáž”ស់ <ph name="HOST_NAME" /> áž‘áŸáŸ”</translation>
<translation id="2639739919103226564">ស្ážáž¶áž“ភាព៖</translation>
+<translation id="264810637653812429">រកមិន​ឃើញ​ឧបករណáŸâ€‹ážŠáŸ‚ល​ážáŸ’រូវគ្នាទáŸáŸ”</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, ចុច "Tab" រួចចុច "Enter" ដើម្បីសម្អាážáž”្រវážáŸ’ážáž·â€‹ážšáž»áž€ážšáž€â€‹ážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិហážáž¼áž‚ី ឃ្លាំងផ្ទុកទិន្ននáŸáž™ážšáž”ស់អ្នក និងអ្វីៗជាច្រើនទៀážáž“ៅក្នុងការកំណážáŸ‹ Chrome</translation>
<translation id="2650446666397867134">ការចូលប្រើឯកសារážáŸ’រូវបានបដិសáŸáž’</translation>
@@ -497,6 +511,7 @@
<translation id="2799223571221894425">បើកដំណើរការឡើងវិញ</translation>
<translation id="2803306138276472711">ការរុករកសុវážáŸ’ážáž·áž—ាព Google <ph name="BEGIN_LINK" />បានរកឃើញមáŸážšáŸ„áž‚<ph name="END_LINK" /> នៅលើ <ph name="SITE" />កន្លងទៅážáŸ’មីៗនáŸáŸ‡áŸ” áž‚áŸáž áž‘ំពáŸážšážŠáŸ‚លជាធម្មážáž¶áž˜áž¶áž“សុវážáŸ’ážáž·áž—ាពអាចឆ្លងមáŸážšáŸ„គនៅពáŸáž›ážáŸ’លះ។</translation>
<translation id="2807052079800581569">ទីážáž¶áŸ†áž„​រូបភាព Y</translation>
+<translation id="2820957248982571256">កំពុងស្កáŸáž“...</translation>
<translation id="2824775600643448204">អាសយដ្ឋាន និងរបាស្វែងរក</translation>
<translation id="2826760142808435982">ការភ្ជាប់ážáŸ’រូវបានអ៊ីនគ្រីប និងសម្គាល់អážáŸ’ážážŸáž‰áŸ’ញាណ ដោយប្រើ <ph name="CIPHER" /> និងប្រើ <ph name="KX" /> ជាយន្ážáž€áž¶ážšáž•áŸ’ážáŸ„ះប្ážáž¼ážšážŸáŸ„។</translation>
<translation id="2835170189407361413">ជម្រះបែបបទ</translation>
@@ -504,6 +519,8 @@
<translation id="2850739647070081192">Invite (ស្រោម​សំបុážáŸ’ážš)</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="2859806420264540918">áž‚áŸáž áž‘ំពáŸážšâ€‹áž“áŸáŸ‡áž”ង្ហាញ​ការផ្សាយពាណិជ្ជកម្ម​ដែលនាំឱ្យយល់ច្រឡំ ឬរំážáž¶áž“។</translation>
+<translation id="287596039013813457">លក្ážážŽáŸˆâ€‹áž˜áž·ážáŸ’ážáž—ាព</translation>
+<translation id="2876489322757410363">កំពុង​ចាកចáŸáž‰áž–ី​មុážáž„ារ​ឯកជន ដើម្បីបង់ប្រាក់​ážáž¶áž˜ážšáž™áŸˆâ€‹áž€áž˜áŸ’មវិធី​ážáž¶áž„ក្រៅ។ បន្ážáž¬áž‘áŸ?</translation>
<translation id="2878197950673342043">áž”ážáŸ‹â€‹áž•áŸ’ទាំងរូបភាព</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ការដាក់​វិនដូ</translation>
@@ -553,7 +570,6 @@
<translation id="3060227939791841287">C9 (ស្រោម​សំបុážáŸ’ážš)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, ចុច Tab បន្ទាប់មក Enter ដើម្បីដំណើរការ​ការពិនិážáŸ’យ​សុវážáŸ’ážáž·áž—ាព​នៅក្នុង​ការកំណážáŸ‹ Chrome</translation>
<translation id="3061707000357573562">Patch Service</translation>
-<translation id="3064966200440839136">កំពុង​ចាកចáŸáž‰â€‹áž–ី​មុážáž„ារ​អនាមិក ដើម្បី​បង់ប្រាក់​ážáž¶áž˜ážšáž™áŸˆâ€‹áž€áž˜áŸ’មវិធី​ážáž¶áž„ក្រៅ។ បន្áž?</translation>
<translation id="306573536155379004">ហ្គáŸáž˜â€‹áž”ានចាប់ផ្ដើម។</translation>
<translation id="3080254622891793721">ក្រាហ្វិក</translation>
<translation id="3086579638707268289">សកម្មភាព​របស់អ្នក​នៅលើ​បណ្ដាញ​កំពុង​ážáŸ’រូវបាន​ឃ្លាំមើល</translation>
@@ -576,7 +592,6 @@
<translation id="315504272643575312">គណនី​របស់​អ្នក​ស្ážáž·ážáž€áŸ’រោម​ការគ្រប់គ្រង​របស់ <ph name="MANAGER" />។</translation>
<translation id="3157931365184549694">ស្ážáž¶ážš</translation>
<translation id="3162559335345991374">Wi-Fi ដែលអ្នកកំពុងប្រើអាចážáž˜áŸ’រូវឲ្យអ្នកទៅកាន់ទំពáŸážšáž…ុះឈ្មោះរបស់វា។</translation>
-<translation id="3167968892399408617">ទំពáŸážšážŠáŸ‚លអ្នកមើលនៅក្នុងផ្ទាំងអនាមិកនឹងមិននៅជាប់ប្រវážáŸ’ážáž·ážšáž»áž€ážšáž€ កន្លែងផ្ទុកážáž»áž€ážƒáž¸ ឬប្រវážáŸ’ážáž·ážŸáŸ’វែងរករបស់អ្នកទ០បន្ទាប់ពីអ្នកបិទផ្ទាំងអនាមិករបស់អ្នកទាំងអស់។ រាល់ឯកសារដែលអ្នកដោនឡូហឬចំណាំដែលអ្នកបង្កើážáž“ឹងážáŸ’រូវបានរក្សាទុក។</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">កោះ</translation>
<translation id="3176929007561373547">áž–áž·áž“áž·ážáŸ’យការកំណážáŸ‹áž”្រូកស៊ីរបស់អ្នក ឬទំនាក់ទំនងអ្នកគ្រប់គ្រងបណ្ážáž¶áž‰ážšáž”ស់អ្នកដើម្បី
@@ -602,10 +617,12 @@
<translation id="3229041911291329567">áž–áŸážáŸŒáž˜áž¶áž“កំណែ​អំពីឧបករណ០និងកម្មវិធីរុករក​ážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិážážšáž”ស់អ្នក</translation>
<translation id="323107829343500871">បញ្ចូល CVC សម្រាប់ <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">ážáŸ‚áž„ážáŸ‚ចាប់យកមាážáž·áž€áž¶ážŸáŸ†ážáž¶áž“់ជានិច្ចនៅលើគáŸáž áž‘ំពáŸážšáž“áŸáŸ‡</translation>
+<translation id="3249845759089040423">ទាន់​សមáŸáž™</translation>
<translation id="3252266817569339921">ភាសាបារាំង</translation>
<translation id="3266793032086590337">ážáž˜áŸ’លៃ (ជាន់គ្នា)</translation>
<translation id="3268451620468152448">បើកផ្ទាំង</translation>
<translation id="3270847123878663523">បកក្រោយការážáž˜áŸ’រៀបឡើងវិញ</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> ចង់ភ្ជាប់</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">ស្ážáž¶áž”áŸáž“របស់អ្នក <ph name="ENROLLMENT_DOMAIN" /> បានបញ្ជូនពáŸážáŸŒáž˜áž¶áž“មួយចំនួនទៅគáŸáž áž‘ំពáŸážšážáž¶áž„ក្រោមដូចជា ការកំណážáŸ‹ ឬគោលការណáŸáž‡áž¶ážŠáž¾áž˜áŸ”</translation>
<translation id="3282497668470633863">បញ្ចូលឈ្មោះលើកាáž</translation>
@@ -658,6 +675,7 @@
<translation id="3428151540071562330">URI ទម្រង់គំរូ​ម៉ាស៊ីនម០DnsOverHttpsTemplates មួយ ឬច្រើន​គឺ​មិន​ážáŸ’រឹមážáŸ’រូវ​ទ០ហើយនឹង​មិន​ážáŸ’រូវបាន​ប្រើប្រាស់​ឡើយ​។</translation>
<translation id="3431636764301398940">រក្សាទុកកាážáž“áŸáŸ‡áž‘ៅក្នុងឧបករណáŸáž“áŸáŸ‡</translation>
<translation id="3432601291244612633">បិទទំពáŸážš</translation>
+<translation id="3435738964857648380">សុវážáŸ’ážáž·áž—ាព</translation>
<translation id="3435896845095436175">បើកដំណើរការ</translation>
<translation id="3438829137925142401">ប្រើពាក្យសម្ងាážáŸ‹ážŠáŸ‚លរក្សាទុកនៅក្នុងគណនី​ Google របស់អ្នក</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -700,7 +718,10 @@
<translation id="3584299510153766161">ចោះ​ពីររន្ធ​ážáž¶áž„ក្រោម</translation>
<translation id="3586931643579894722">លាក់ពáŸážáŸŒáž˜áž¶áž“លំអិáž</translation>
<translation id="3587738293690942763">កណ្ážáž¶áž›</translation>
+<translation id="3590643883886679995">ទិន្ននáŸáž™â€‹ážŸáž˜áŸ’រាប់​ចូលគណនី​នឹងážáŸ’រូវបាន​រក្សាទុកនៅលើ​ឧបករណáŸáž“áŸáŸ‡ បន្ទាប់ពីអ្នក​ចាកចáŸáž‰áž–ី​មុážáž„ារឯកជន។</translation>
+<translation id="359126217934908072">ážáŸ‚/ឆ្នាំ៖</translation>
<translation id="3592413004129370115">Italian (ស្រោម​សំបុážáŸ’ážš)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{អ្នកអាច​កំណážáŸ‹â€‹áž€áŸ’រុមរបស់អ្នក​ឡើងវិញ​បានគ្រប់ពáŸáž›áŸ” ចំណាយពáŸáž›áž”្រហែលមួយážáŸ’ងៃ ដើម្បីចូលរួមក្រុមážáŸ’មី។}=1{អ្នកអាច​កំណážáŸ‹â€‹áž€áŸ’រុមរបស់អ្នក​ឡើងវិញ​បានគ្រប់ពáŸáž›áŸ” ចំណាយពáŸáž›áž”្រហែលមួយážáŸ’ងៃ ដើម្បីចូលរួមក្រុមážáŸ’មី។}other{អ្នកអាច​កំណážáŸ‹â€‹áž€áŸ’រុមរបស់អ្នក​ឡើងវិញ​បានគ្រប់ពáŸáž›áŸ” ចំណាយពáŸáž›áž”្រហែល {NUM_DAYS} ážáŸ’ងៃ ដើម្បីចូលរួមក្រុមážáŸ’មី។}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">កម្មវិធី​ដែលទប់ស្កាážáŸ‹â€‹ážŠáŸ„យ​អ្នកគ្រប់គ្រង​របស់អ្នក</translation>
<translation id="3608932978122581043">កំណážáŸ‹áž‘ិស</translation>
@@ -709,13 +730,13 @@
<translation id="3615877443314183785">បញ្ចូលកាលបរិច្ឆáŸáž‘áž•áž»ážáž€áŸ†ážŽážáŸ‹ážŠáŸ‚áž›ážáŸ’រឹមážáŸ’រូវ</translation>
<translation id="36224234498066874">សម្អាážâ€‹áž‘ិន្ននáŸáž™â€‹ážšáž»áž€ážšáž€...</translation>
<translation id="362276910939193118">បង្ហាញប្រវážáŸ’ážáž·áž–áŸáž‰áž›áŸáž‰</translation>
-<translation id="3625635938337243871">ទិន្ននáŸáž™â€‹ážŸáž˜áŸ’រាប់​ចូលគណនី​នឹងážáŸ’រូវបាន​រក្សាទុកនៅលើ​ឧបករណáŸáž“áŸáŸ‡ បន្ទាប់ពីអ្នក​ចាកចáŸáž‰áž–ី​មុážáž„ារ​ឯកជន។</translation>
<translation id="3630155396527302611">ប្រសិនបើវាážáŸ’រូវបានរាយជាកម្មវិធីដែលបានអនុញ្ញាážáž²áŸ’យចូលប្រើបណ្ážáž¶áž‰áž“áŸáŸ‡ážšáž½áž…ហើយ
សូមសាកល្បងយកវាចáŸáž‰áž–ីបញ្ជី ហើយបន្ážáŸ‚មវាម្ážáž„ទៀážáŸ”</translation>
<translation id="3630699740441428070">អ្នកគ្រប់គ្រង​ឧបករណáŸâ€‹áž“áŸáŸ‡â€‹áž”ានកំណážáŸ‹ážšáž…នាសម្ពáŸáž“្ធ​ការážáž—្ជាប់​បណ្ដាញ​របស់អ្នក ដែលសកម្មភាពនáŸáŸ‡áž¢áž¶áž…​អនុញ្ញាážáž±áŸ’យ​ពួកគáŸâ€‹áž˜áž¾áž›ážƒáž¾áž‰â€‹áž…រាចរណáŸáž”ណ្ដាញ​របស់អ្នក រួមទាំង​គáŸáž áž‘ំពáŸážšâ€‹ážŠáŸ‚លអ្នក​ចូលមើល​ផងដែរ​។</translation>
<translation id="3631244953324577188">ជីវមាážáŸ’ážš</translation>
<translation id="3633738897356909127">ប៊ូážáž»áž„ "ដំឡើងកំណែ Chrome" ចុច "Enter" ដើម្បីដំឡើងកំណែ Chrome ពីការកំណážáŸ‹ Chrome របស់អ្នក</translation>
<translation id="3634530185120165534">ទម្រទី 5</translation>
+<translation id="3637662659967048211">រក្សាទុក​នៅក្នុង​គណនី Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">កម្មវិធី៖</translation>
<translation id="3650584904733503804">ការពិនិážáŸ’យសុពលភាពបានជោគជáŸáž™</translation>
@@ -756,6 +777,7 @@
<translation id="3781428340399460090">ផ្កាឈូកចាស់</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">ឧបករណáŸâ€‹áž”៊្លូធូស</translation>
+<translation id="3787675388804467730">áž›áŸážáž€áž¶ážáž“ិម្មិáž</translation>
<translation id="3787705759683870569">áž•áž»ážáž€áŸ†ážŽážáŸ‹ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">ទំហំ 16</translation>
<translation id="3789841737615482174">ážáŸ†áž¡áž¾áž„</translation>
@@ -775,6 +797,7 @@
<translation id="3841184659773414994">ឧបករណáŸážŠáŸ„ះស្រាយឯកសារ</translation>
<translation id="385051799172605136">ážáž™áž€áŸ’រោយ</translation>
<translation id="3858027520442213535">ធ្វើបច្ចុប្បន្នភាពកាលបរិច្ឆáŸáž‘ និងម៉ោង</translation>
+<translation id="3881478300875776315">បង្ហាញបន្ទាážáŸ‹ážáž·áž…ជាងនáŸáŸ‡</translation>
<translation id="3884278016824448484">មានបញ្ហាជាមួយឧបករណáŸážŸáž˜áŸ’គាល់ឧបករណáŸ</translation>
<translation id="3885155851504623709">ážáŸ†áž”ន់រដ្ឋបាល</translation>
<translation id="388632593194507180">បានរកឃើញ​ការឃ្លាំមើល</translation>
@@ -800,6 +823,7 @@
<translation id="397105322502079400">កំពុងគណនា...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ážáŸ’រូវបានរារាំង</translation>
<translation id="3973357910713125165">ប៊ូážáž»áž„​ដំណើរការ​ការពិនិážáŸ’យ​សុវážáŸ’ážáž·áž—ាព Chrome, ចុច Enter ដើម្បី​ដំណើរការ​ការពិនិážáŸ’យ​សុវážáŸ’ážáž·áž—ាព​នៅក្នុង​ការកំណážáŸ‹ Chrome</translation>
+<translation id="3986705137476756801">បិទអក្សររážáŸ‹â€‹áž€áŸ’នុងពáŸáž›áž‡áž¶áž€áŸ‹ážŸáŸ’ដែង​ឥឡូវនáŸáŸ‡</translation>
<translation id="3987405730340719549">Chrome បាន​កំណážáŸ‹ážáž¶â€‹áž‚áŸáž áž‘ំពáŸážšáž“áŸáŸ‡â€‹áž”្រហែលជា​ក្លែងក្លាយ ឬ​បោកប្រាស់។
ប្រសិនបើ​អ្នកយល់ážáž¶ áž‚áŸáž áž‘ំពáŸážšáž“áŸáŸ‡áž˜áž¶áž“បញ្ហា សូម​ចូលទៅកាន់ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals។</translation>
@@ -896,13 +920,14 @@
<translation id="4275830172053184480">ចាប់ផ្ážáž¾áž˜áž§áž”ករណáŸážšáž”ស់អ្នកឡើងវិញ</translation>
<translation id="4277028893293644418">កំណážáŸ‹â€‹áž–ាក្យ​សម្ងាážáŸ‹â€‹áž¡áž¾áž„វិញ</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{បណ្ណនáŸáŸ‡â€‹ážáŸ’រូវបានរក្សាទុក​នៅក្នុងគណនី Google របស់អ្នក}other{បណ្ណទាំងនáŸáŸ‡â€‹ážáŸ’រូវបានរក្សាទុក​នៅក្នុងគណនី Google របស់អ្នក}}</translation>
+<translation id="4287885627794386150">អាច​សាកល្បងបាន ប៉ុន្ážáŸ‚​មិនដំណើរការទáŸ</translation>
<translation id="4297502707443874121">រូបភាព​ážáž¼áž…ៗសម្រាប់ទំពáŸážš <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">ពង្រីក</translation>
<translation id="4300675098767811073">ចោះ​ច្រើនរន្ធ​ážáž¶áž„ស្ដាំ</translation>
<translation id="4302514097724775343">ចុច "ដាយណូសáŸážš" ដើម្បីលáŸáž„</translation>
<translation id="4302965934281694568">Chou3 (ស្រោម​សំបុážáŸ’ážš)</translation>
<translation id="4305666528087210886">មិនអាចចូលប្រើ​ឯកសារ​របស់អ្នកបានទáŸ</translation>
-<translation id="4305817255990598646">ប្ដូរ​</translation>
+<translation id="4306529830550717874">រក្សាទុក​អាសយដ្ឋាន​ដែរទ�</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">រារាំង (លំនាំដើម)</translation>
<translation id="4314815835985389558">គ្រប់គ្រង​សមកាលកម្ម</translation>
@@ -929,6 +954,7 @@
<translation id="4377125064752653719">អ្នកបានព្យាយាមទៅកាន់ <ph name="DOMAIN" /> ប៉ុន្ážáŸ‚វិញ្ញាបនបáŸážáŸ’រដែលម៉ាស៊ីនមáŸáž”ានបង្ហាញážáŸ’រូវបានបញ្ឈប់សុពលភាពដោយអ្នកចáŸáž‰áž•áŸ’សាយរបស់វា។ វាមាននáŸáž™ážáž¶áž¢ážáŸ’ážážŸáž‰áŸ’ញាណសម្គាល់សុវážáŸ’ážáž·áž—ាពដែលម៉ាស៊ីនមáŸáž”ានបង្ហាញមិនអាចជឿជាក់បានទាំងស្រុងទáŸáŸ” អ្នកប្រហែលជាអាចកំពុងទំនាក់ទំនងជាមួយអ្នកវាយប្រហារ។</translation>
<translation id="4378154925671717803">ទូរសáŸáž–្ទ</translation>
<translation id="4390472908992056574">គែមážáž¶áž„លើ</translation>
+<translation id="4406883609789734330">អក្សររážáŸ‹â€‹áž€áŸ’នុងពáŸáž›â€‹áž‡áž¶áž€áŸ‹ážŸáŸ’ដែង</translation>
<translation id="4406896451731180161">លទ្ធផលស្វែងរក</translation>
<translation id="4408413947728134509">ážáž¼áž‚ី <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">អ្នកទើបážáŸ‚​បានបញ្ចូល​ពាក្យសម្ងាážáŸ‹â€‹ážšáž”ស់អ្នក​នៅលើ​គáŸáž áž‘ំពáŸážšáž”ញ្ឆោážáŸ” Chrome សូមណែនាំឱ្យ​ចូលទៅកាន់ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> áž“áž·áž„áž‚áŸáž áž‘ំពáŸážšâ€‹áž•áŸ’សáŸáž„ទៀហ​ដែល​អ្នកប្រើ​ពាក្យសម្ងាážáŸ‹â€‹áž“áŸáŸ‡ រួច​ប្ដូរ​វាឥឡូវនáŸáŸ‡áŸ”</translation>
@@ -942,7 +968,6 @@
<translation id="4435702339979719576">បណ្ណប្រៃសណីយáŸ)</translation>
<translation id="443673843213245140">ការប្រើប្រូកស៊ីážáŸ’រូវបានបិទដំណើរការ ប៉ុន្ážáŸ‚ការកំណážáŸ‹áž”្រូកស៊ីដែលច្បាស់លាស់ážáŸ’រូវបានបញ្ជាក់។</translation>
<translation id="4464826014807964867">áž‚áŸáž áž‘ំពáŸážšážŠáŸ‚លមានពáŸážáŸŒáž˜áž¶áž“ពីស្ážáž¶áž”áŸáž“របស់អ្នក</translation>
-<translation id="4466881336512663640">ការផ្លាស់ប្ដូរទម្រង់បែបបទ​នឹង​បាážáŸ‹áž”ង់។ ážáž¾áž¢áŸ’នកប្រាកដážáž¶â€‹áž…ង់បន្ážážŠáŸ‚ážšáž‘áŸ?</translation>
<translation id="4476953670630786061">ទម្រង់នáŸáŸ‡â€‹áž˜áž·áž“មានសុវážáŸ’ážáž·áž—ាពទáŸáŸ” មុážáž„ារបំពáŸáž‰ážŸáŸ’ážœáŸáž™áž”្រវážáŸ’ážáž·â€‹ážáŸ’រូវបានបិទ។</translation>
<translation id="4477350412780666475">សំនៀង​បន្ទាប់</translation>
<translation id="4482953324121162758">áž‚áŸáž áž‘ំពáŸážšáž“áŸáŸ‡â€‹áž“ឹង​មិនážáŸ’រូវ​បានបកប្រែទáŸáŸ”</translation>
@@ -976,6 +1001,7 @@
<translation id="4594403342090139922">បកក្រោយការលុប</translation>
<translation id="4597348597567598915">ទំហំ 8</translation>
<translation id="4600854749408232102">C6/C5 (ស្រោម​សំបុážáŸ’ážš)</translation>
+<translation id="4606870351894164739">ជះ​ឥទ្ធិពល​ážáŸ’លាំង</translation>
<translation id="4628948037717959914">រូបážáž</translation>
<translation id="4631649115723685955">បានភ្ជាប់​ការទទួល​បានប្រាក់​មកវិញ</translation>
<translation id="4636930964841734540">áž–áŸážáŸŒáž˜áž¶áž“</translation>
@@ -995,6 +1021,7 @@
<translation id="4691835149146451662">Architecture-A (ស្រោម​សំបុážáŸ’ážš)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">ចំហៀង</translation>
+<translation id="4702656508969495934">អាចមើលឃើញអក្សររážáŸ‹áž€áŸ’នុងពáŸáž›áž‡áž¶áž€áŸ‹ážŸáŸ’ដែង ប្រើប៊ូážáž»áž„ប្ដូរផ្ទាំងវិនដូដើម្បីផ្ដោáž</translation>
<translation id="4708268264240856090">ការážáž—្ជាប់របស់អ្នកមានការរំážáž¶áž“</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />កំពុងដំណើរការការវិភាគបណ្ážáž¶áž‰ Windows<ph name="END_LINK" /></translation>
@@ -1008,6 +1035,7 @@
<translation id="4738601419177586157">ការណែនាំ​ការស្វែងរក <ph name="TEXT" /></translation>
<translation id="4742407542027196863">គ្រប់គ្រង​ពាក្យ​សម្ងាážáŸ‹â€¦</translation>
<translation id="4744603770635761495">ផ្លូវដែលអាចប្រážáž·áž”ážáž·áŸ’ážáž€áž¶ážšáž”ាន</translation>
+<translation id="4749011317274908093">អ្នកបានចូល​មុážáž„ារ​ឯកជនហើយ</translation>
<translation id="4750917950439032686">áž–áŸážáŸŒáž˜áž¶áž“របស់អ្នក (ឧទារហរណáŸáŸ– ពាក្យសម្ងាážáŸ‹ ឬលáŸážáž€áž¶ážáž¥ážŽáž‘ាន) ស្ážáž·ážáž€áŸ’នុងលក្ážážŽáŸˆáž¯áž€áž‡áž“នៅពáŸáž›ážŠáŸ‚លវាážáŸ’រូវបានផ្ញើទៅគáŸáž áž‘ំពáŸážšáž“áŸáŸ‡áŸ”</translation>
<translation id="4756388243121344051">ប្រវážáŸ’ážáž·</translation>
<translation id="4758311279753947758">បន្ážáŸ‚មពáŸážáŸŒáž˜áž¶áž“ទំនាក់ទំនង</translation>
@@ -1037,6 +1065,8 @@
<translation id="4813512666221746211">កំហុសឆ្គងបណ្ážáž¶áž‰</translation>
<translation id="4816492930507672669">សមនឹងទំពáŸážš</translation>
<translation id="4819347708020428563">កែចំណារនៅក្នុងទិដ្ឋភាពលំនាំដើមឬ?</translation>
+<translation id="4825507807291741242">មាន​ឥទ្ធិពល​ážáŸ’លាំង</translation>
+<translation id="4838327282952368871">ដូចក្ដី​សុបិន</translation>
<translation id="484462545196658690">ស្វáŸáž™áž”្រវážáŸ’ážáž·</translation>
<translation id="4850886885716139402">មើល</translation>
<translation id="485316830061041779">ភាសាអាល្លឺម៉ង់</translation>
@@ -1173,6 +1203,7 @@
<translation id="5314967030527622926">ឧបករណáŸâ€‹áž’្វើកូន​សៀវភៅ</translation>
<translation id="5316812925700871227">បង្វិលបញ្ច្រាសទ្រនិចនាឡិកា</translation>
<translation id="5317780077021120954">រក្សាទុក</translation>
+<translation id="5321288445143113935">បានពង្រីកអážáž·áž”រមា</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> ក្នុង​ចំណោម <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">ជ្រើសរើស​ពáŸážáŸŒáž˜áž¶áž“​ទំនាក់ទំនង</translation>
<translation id="5327248766486351172">ឈ្មោះ</translation>
@@ -1180,11 +1211,13 @@
<translation id="5332219387342487447">វិធីសាស្រ្ážâ€‹áž“ៃការ​ដឹកជញ្ជូន</translation>
<translation id="5333022057423422993">Chrome បានរកឃើញ​ពាក្យសម្ងាážáŸ‹â€‹ážŠáŸ‚លអ្នកទើបážáŸ‚ប្រើ នៅក្នុង​ការបែកធ្លាយ​ទិន្ននáŸáž™áŸ” ដើម្បី​រក្សាសុវážáŸ’ážáž·áž—ាព​គណនីរបស់អ្នក យើងសូមណែនាំឱ្យ​ពិនិážáŸ’យមើល​ពាក្យសម្ងាážáŸ‹â€‹ážŠáŸ‚លអ្នកបានរក្សាទុក។</translation>
<translation id="5334013548165032829">កំណážáŸ‹áž áŸážáž»â€‹áž”្រពáŸáž“្ធលម្អិáž</translation>
+<translation id="5334145288572353250">រក្សាទុក​អាសយដ្ឋាន​ឬ?</translation>
<translation id="5340250774223869109">កម្មវិធី​ážáŸ’រូវបាន​ទប់ស្កាážáŸ‹</translation>
<translation id="534295439873310000">ឧបករណ០NFC</translation>
<translation id="5344579389779391559">ទំពáŸážšâ€‹áž“áŸáŸ‡â€‹áž¢áž¶áž…​នឹងព្យាយាម​គិážáž”្រាក់ពីអ្នក</translation>
<translation id="5355557959165512791">អ្នក​មិន​អាច​ចូលទៅ​កាន់ <ph name="SITE" /> ឥឡូវនáŸáŸ‡â€‹áž”ានទ០ដោយសារážáŸ‚វិញ្ញាបនបážáŸ’ររបស់វា​ážáŸ’រូវ​បានដក​ហូážáž áž¾áž™áŸ” ជាទូទៅបញ្ហា​បណ្ážáž¶áž‰ ឬ​ការវាយប្រហារ​​កើážâ€‹áž¡áž¾áž„​ជាបណ្ážáŸ„ះអាសន្ន ដូច្នáŸáŸ‡â€‹áž‘ំពáŸážšâ€‹áž“áŸáŸ‡â€‹áž“ឹងដំណើរការល្អឡើងវិញនៅពáŸáž›áž€áŸ’រោយ។</translation>
<translation id="536296301121032821">បានបរាជáŸáž™áž€áŸ’នុងការស្ážáž¶ážšáž€áž¶ážšáž€áŸ†ážŽážáŸ‹áž‚ោលការណáŸáž“áŸáŸ‡</translation>
+<translation id="5363309033720083897">​រន្ធស៊áŸážšáž¸ážŠáŸ‚លបានអនុញ្ញាážážŠáŸ„យអ្នកគ្រប់គ្រងរបស់អ្នក</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="5386426401304769735">ážáŸ’សែ​វិញ្ញាបនបážáŸ’រ​សម្រាប់​ទំពáŸážšâ€‹áž“áŸáŸ‡â€‹áž•áŸ’ទុក​វិញ្ញាបនបážáŸ’រ​មួយ​ដែល​ចុះហážáŸ’ážáž›áŸážáž¶â€‹ážŠáŸ„យប្រើ SHA-1 ។</translation>
@@ -1193,6 +1226,7 @@
<translation id="5398772614898833570">បាន​ទប់ស្កាážáŸ‹â€‹áž€áž¶ážšáž•áŸ’សាយពាណិជ្ជកម្ម</translation>
<translation id="5400836586163650660">ប្រផáŸáŸ‡</translation>
<translation id="540969355065856584">ម៉ាស៊ីនមáŸáž“áŸáŸ‡áž˜áž·áž“អាចបង្ហាញážáž¶ážœáž¶áž‡áž¶ <ph name="DOMAIN" /> នោះទ០វិញ្ញាបនបážáŸ’រសុវážáŸ’ážáž·áž—ាពរបស់វាមិនមានសុពលភាពទáŸáž“ៅពáŸáž›áž“áŸáŸ‡áŸ” វាអាចបណ្ážáž¶áž›áž˜áž€áž–ីការកំណážáŸ‹ážšáž…នាសម្ពáŸáž“្ធមិនážáŸ’រឹមážáŸ’រូវ ឬមានអ្នកវាយប្រហារកំពុងរារាំងការážáž—្ជាប់របស់អ្នក។</translation>
+<translation id="541143247543991491">ពពក (កម្រិážâ€‹áž”្រពáŸáž“្ធ)</translation>
<translation id="541416427766103491">ទម្រគំនរ​ទី 4</translation>
<translation id="5421136146218899937">ជម្រះទិន្ននáŸáž™ážšáž»áž€ážšáž€...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> ចង់​ផ្ញើ​ការជូន​ដំណឹងទៅអ្នក</translation>
@@ -1206,6 +1240,7 @@
<translation id="5455374756549232013">ážáŸ‚មពáŸáž›ážœáŸáž›áž¶áž‚ោលការណáŸáž˜áž·áž“ល្អ</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" /> ទៀáž}other{<ph name="CONTACT_PREVIEW" /> áž“áž·áž„ <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ទៀáž}}</translation>
+<translation id="5463625433003343978">កំពុង​ស្វែងរក​ឧបករណáŸ...</translation>
<translation id="5469868506864199649">ភាសាអ៊ីážáž¶áž›áž¸</translation>
<translation id="5470861586879999274">ធ្វើការកែប្រែវិញ</translation>
<translation id="5478437291406423475">B6/C4 (ស្រោម​សំបុážáŸ’ážš)</translation>
@@ -1255,7 +1290,6 @@
<translation id="5624120631404540903">គ្រប់គ្រងពាក្យសម្ងាážáŸ‹</translation>
<translation id="5629630648637658800">បានបរាជáŸáž™áž€áŸ’នុងដំណើរការការកំណážáŸ‹áž‚ោលការណáŸ</translation>
<translation id="5631439013527180824">សញ្ញាážáŸ†ážŽáž¶áž„ការគ្រប់គ្រងឧបករណáŸáž‚្មានសុពលភាព</translation>
-<translation id="5632627355679805402">ទិន្ននáŸáž™â€‹ážšáž”ស់អ្នក​ážáŸ’រូវបាន​អ៊ីនគ្រីប​ដោយប្រើ<ph name="BEGIN_LINK" />ពាក្យសម្ងាážáŸ‹ Google<ph name="END_LINK" /> របស់អ្នក នៅážáŸ’ងៃទី <ph name="TIME" />។ បញ្ចូល​ពាក្យសម្ងាážáŸ‹ ដើម្បី​ចាប់ផ្ដើម​ធ្វើ​សម​កាល​កម្ម។</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="5644090287519800334">ការប្ដូរ​រូបភាព X នៃចំហៀងទី 1</translation>
@@ -1294,12 +1328,12 @@
<translation id="5785756445106461925">ជាងនáŸáŸ‡áž‘ៅទៀហទំពáŸážšáž“áŸáŸ‡ážšáž¶áž”់បញ្ចូលធនធានផ្សáŸáž„ទៀážážŠáŸ‚លគ្មានសុវážáŸ’ážáž·áž—ាព។ ធនធានទាំងនáŸáŸ‡áž¢áž¶áž…ážáŸ’រូវបានមើលដោយអ្នកផ្សáŸáž„ទៀážážážŽáŸˆáž–áŸáž›áž†áŸ’លងកាážáŸ‹ និងអាចážáŸ’រូវបានកែសម្រួលដោយអ្នកវាយប្រហារដើម្បីប្ážáž¼ážšážšáž¼áž”រាងទំពáŸážšáŸ”</translation>
<translation id="5786044859038896871">ážáž¾áž¢áŸ’នកចង់បំពáŸáž‰áž–áŸážáŸŒáž˜áž¶áž“កាážážšáž”ស់អ្នកដែរទáŸ?</translation>
<translation id="578633867165174378">Chrome បានរកឃើញ​ពាក្យសម្ងាážáŸ‹â€‹ážŠáŸ‚លអ្នកទើបážáŸ‚ប្រើ នៅក្នុង​ការបែកធ្លាយ​ទិន្ននáŸáž™áŸ” យើង​សូមណែនាំឱ្យប្ដូរ​ពាក្យសម្ងាážáŸ‹áž“áŸáŸ‡â€‹áž¥áž¡áž¼ážœáž“áŸáŸ‡áŸ”</translation>
-<translation id="5798290721819630480">លុបចោល​ការផ្លាស់ប្ដូរ?</translation>
<translation id="5803412860119678065">ážáž¾áž¢áŸ’នកចង់បំពáŸáž‰ <ph name="CARD_DETAIL" /> របស់អ្នកដែរទáŸ?</translation>
<translation id="5804241973901381774">ការអនុញ្ញាáž</translation>
<translation id="5804427196348435412">ប្រើ​ឧបករណ០NFC</translation>
<translation id="5810442152076338065">ការážáž—្ជាប់របស់អ្នកទៅ <ph name="DOMAIN" /> ážáŸ’រូវបានអ៊ីនគ្រីបដោយប្រើឈុážážŸážšážŸáŸážšážŸáž˜áŸ’ងាážáŸ‹ážŠáŸ‚លគáŸáž›áŸ‚ងប្រើ។</translation>
<translation id="5813119285467412249">ធ្វើការបន្ážáŸ‚មឡើងវិញ</translation>
+<translation id="5817918615728894473">ផ្គូផ្គង</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{នឹងគិážáž”្រាក់ពីបណ្ណឥណទាន​នáŸáŸ‡â€‹ នៅពáŸáž›â€‹áž¢áŸ’នក​បង់ប្រាក់ ប៉ុន្ážáŸ‚​លáŸážâ€‹áž–áž·ážáž”្រាកដ​របស់វា​នឹងមិនážáŸ’រូវបាន​ចែករំលែក​ជាមួយ​គáŸáž áž‘ំពáŸážšâ€‹áž“áŸáŸ‡áž‘áŸáŸ” CVC បណ្ážáŸ„ះអាសន្ន​នឹងážáŸ’រូវបាន​បង្កើážâ€‹ សម្រាប់ការការពារសុវážáŸ’ážáž·áž—ាព​បន្ážáŸ‚ម។}other{នឹងគិážáž”្រាក់ពីបណ្ណឥណទាន​​ដែលអ្នក​ជ្រើសរើស​ នៅពáŸáž›â€‹áž¢áŸ’នក​បង់ប្រាក់ ប៉ុន្ážáŸ‚​លáŸážâ€‹áž–áž·ážáž”្រាកដ​របស់វា​នឹងមិនážáŸ’រូវបាន​ចែករំលែក​ជាមួយ​គáŸáž áž‘ំពáŸážšâ€‹áž“áŸáŸ‡áž‘áŸáŸ” CVC បណ្ážáŸ„ះអាសន្ន​នឹងážáŸ’រូវបាន​បង្កើážâ€‹ សម្រាប់​ការ​ការពារសុវážáŸ’ážáž·áž—ាព​បន្ážáŸ‚ម។}}</translation>
<translation id="5826507051599432481">ឈ្មោះទូទៅ (CN)</translation>
<translation id="5838278095973806738">អ្នកមិនគួរបញ្ចូលពáŸážáŸŒáž˜áž¶áž“សំážáž¶áž“់ៗនៅលើគáŸáž áž‘ំពáŸážšáž“áŸáŸ‡áž‘០(ឧទាហរណáŸáŸ– ពាក្យសម្ងាážáŸ‹ ឬកាážáž¥ážŽáž‘ាន) ពីព្រោះអ្នកវាយប្រហារអាចនឹងលួចវា។</translation>
@@ -1307,6 +1341,7 @@
<translation id="5855253129151731373">ឈ្មោះម៉ាស៊ីនរបស់​គáŸáž áž‘ំពáŸážšâ€‹áž“áŸáŸ‡â€‹ážŸáŸ’រដៀងគ្នា​នឹង <ph name="LOOKALIKE_DOMAIN" />។ ជួនកាល អ្នក​វាយប្រហារ​ក្លែងបន្លំជា​គáŸáž áž‘ំពáŸážšâ€‹áž•áŸ’សáŸáž„ៗ ដោយ​ធ្វើការ​ផ្លាស់ប្ដូរ​ážáž·áž…ážáž½áž…ដែលពិបាក​សម្គាល់​ចំពោះឈ្មោះដែន​។
ប្រសិនបើ​អ្នកយល់ážáž¶ ឈ្មោះដែននáŸáŸ‡áž˜áž¶áž“បញ្ហា សូម​ចូលទៅកាន់ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals។</translation>
+<translation id="5860033963881614850">បិទ</translation>
<translation id="5862579898803147654">ទម្រគំនរ​ទី 8</translation>
<translation id="5863847714970149516">ទំពáŸážšâ€‹ážáž¶áž„មុážâ€‹áž¢áž¶áž…​ព្យាយាម​គិážáž”្រាក់​ពីអ្នក</translation>
<translation id="5866257070973731571">បញ្ចូល​លáŸážâ€‹áž‘ូរសព្ទ</translation>
@@ -1323,6 +1358,7 @@
<translation id="5913377024445952699">បានផ្អាក​ការážážâ€‹áž¢áŸáž€áŸ’រង់</translation>
<translation id="59174027418879706">បានបើកដំណើរការ</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{បានប្រើ 1}other{បានប្រើ #}}</translation>
<translation id="5921185718311485855">បើក</translation>
<translation id="5921639886840618607">រក្សាទុក​កាážâ€‹áž‘ៅក្នុង​គណនី Google ?</translation>
<translation id="5922853866070715753">ជិážâ€‹ážšáž½áž…រាល់​ហើយ</translation>
@@ -1342,6 +1378,7 @@
<translation id="5989320800837274978">ទាំងម៉ាស៊ីនមáŸáž”្រូកស៊ីដែលážáŸážš áž“áž·áž„ URL ស្គ្រីបផáŸáž€áž˜áž·áž“ážáŸ’រូវបានបញ្ជាក់ទáŸáŸ”</translation>
<translation id="5992691462791905444">áž”ážáŸ‹â€‹áž‡áž¶áž¢áž€áŸ’សរ Z</translation>
<translation id="6000758707621254961">លទ្ធផល <ph name="RESULT_COUNT" /> សម្រាប់ '<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">ធម្មážáž¶</translation>
<translation id="6008122969617370890">លំដាប់លំដោយ N-to-1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">áž–áž·áž“áž·ážáŸ’យពាក្យសម្ងាážáŸ‹â€‹ážšáž”ស់អ្នក</translation>
@@ -1363,6 +1400,7 @@
<translation id="6045164183059402045">ទម្រង់គំរូ​ដែលបង្ážáŸ†áž›áž¾</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="6049004884579590341">សូមចុច |<ph name="ACCELERATOR" />| ឱ្យជាប់ ដើម្បីចáŸáž‰â€‹áž–ីមុážáž„ារ​ពáŸáž‰áž¢áŸáž€áŸ’រង់</translation>
<translation id="6049488691372270142">ការចែកចាយ​ទំពáŸážš</translation>
<translation id="6051221802930200923">អ្នក​មិន​អាច​ចូលទៅកាន់ <ph name="SITE" /> ឥឡូវនáŸáŸ‡â€‹áž”ានទ០ដោយសារážáŸ‚áž‚áŸáž áž‘ំពáŸážšáž“áŸáŸ‡â€‹áž”្រើ​ការážáŸ’ទាស់វិញ្ញាបនបážáŸ’រ។ ជាទូទៅបញ្ហា​បណ្ážáž¶áž‰ ឬ​ការវាយប្រហារ​កើážâ€‹áž¡áž¾áž„​ជាបណ្ážáŸ„ះអាសន្ន ដូច្នáŸáŸ‡â€‹áž‘ំពáŸážšâ€‹áž“áŸáŸ‡â€‹áž“ឹងដំណើរការល្អឡើងវិញនៅពáŸáž›áž€áŸ’រោយ។</translation>
<translation id="6051898664905071243">ចំនួន​ទំពáŸážšáŸ–</translation>
@@ -1379,6 +1417,7 @@
<translation id="610911394827799129">គណនី Google របស់អ្នកអាចមានទម្រង់ប្រវážáŸ’ážáž·ážšáž»áž€ážšáž€áž•áŸ’សáŸáž„ទៀážáž“ៅក្នុង <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> ។</translation>
<translation id="6116338172782435947">មើល​អážáŸ’ážáž”áž‘ និង​រូបភាព​ដែល​បានចម្លង​ទៅ​អង្គ​ចងចាំ</translation>
<translation id="6120179357481664955">ចងចាំ​លáŸážážŸáž˜áŸ’គាល់ UPI របស់អ្នក​ដែរទáŸâ€‹?</translation>
+<translation id="6123290840358279103">មើល​កាážáž“ិម្មិáž</translation>
<translation id="6124432979022149706">កម្មវិធីភ្ជាប់ Chrome Enterprise</translation>
<translation id="6146055958333702838">áž–áž·áž“áž·ážáŸ’áž™ážáŸ’សែបណ្ážáž¶áž‰ បិទបើករ៉ោážáž‘áŸážš ម៉ូឌែម ឬឧបករណáŸáž”ណ្ážáž¶áž‰áž•áŸ’សáŸáž„ទៀáž
ដែលអ្នកកំពុងប្រើប្រាស់។</translation>
@@ -1415,6 +1454,7 @@
<translation id="6289939620939689042">ពណ៌​ទំពáŸážš</translation>
<translation id="6290238015253830360">អážáŸ’ážáž”ទដែលបានផ្ážáž›áŸ‹áž™áŸ„បល់របស់អ្នកបង្ហាញនៅទីនáŸáŸ‡</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC៖</translation>
<translation id="6302269476990306341">ការបញ្ឈប់ Google ជំនួយការនៅក្នុង Chrome</translation>
<translation id="6305205051461490394"><ph name="URL" /> មិនអាចភ្ជាប់បានទáŸ</translation>
<translation id="6312113039770857350">áž‚áŸáž áž‘ំពáŸážšáž˜áž·áž“អាចប្រើបានទáŸ</translation>
@@ -1440,6 +1480,7 @@
<translation id="6390200185239044127">áž”ážáŸ‹â€‹áž‡áž¶áž¢áž€áŸ’សរ Z ពាក់កណ្ដាល</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">ការដាក់ចូលពី <ph name="ORIGIN_NAME" /> ទៅក្នុងទីážáž¶áŸ†áž„áž“áŸáŸ‡ážáŸ’រូវបានទប់ស្កាážáŸ‹ážŠáŸ„យគោលការណáŸážšáž”ស់អ្នកគ្រប់គ្រង</translation>
+<translation id="6398765197997659313">ចាកចáŸáž‰áž–ីអáŸáž€áŸ’រង់ពáŸáž‰</translation>
<translation id="6401136357288658127">គោលការណáŸáž“áŸáŸ‡â€‹ážáŸ’រូវបានបញ្ឈប់។ អ្នក​គួរážáŸ‚​ប្រើ​គោលការណ០<ph name="NEW_POLICY" /> ជំនួសវិញ។</translation>
<translation id="6404511346730675251">កែប្រែចំណាំ</translation>
<translation id="6406765186087300643">C0 (ស្រោម​សំបុážáŸ’ážš)</translation>
@@ -1452,7 +1493,6 @@
<translation id="6428450836711225518">ផ្ទៀងផ្ទាážáŸ‹â€‹áž›áŸážâ€‹áž‘ូរសព្ទ​របស់​អ្នក</translation>
<translation id="6433490469411711332">កែសម្រួលពáŸážáŸŒáž˜áž¶áž“ទំនាក់ទំនង</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> បានបដិសáŸáž’ក្នុងការážáž—្ជាប់</translation>
-<translation id="6434309073475700221">កម្ចាážáŸ‹</translation>
<translation id="6440503408713884761">មិនážáŸ’រូវបាន​អើពើ</translation>
<translation id="6443406338865242315">ážáž¶ážáž¾â€‹áž€áž˜áŸ’មវិធីបន្ážáŸ‚ម និងកម្មវិធី​ជំនួយណាážáŸ’លះដែលអ្នកបានដំឡើង</translation>
<translation id="6446163441502663861">Kahu (ស្រោម​សំបុážáŸ’ážš)</translation>
@@ -1495,6 +1535,7 @@
<translation id="6624427990725312378">áž–áŸážáŸŒáž˜áž¶áž“​ទំនាក់ទំនង</translation>
<translation id="6626291197371920147">បញ្ចូលលáŸážáž€áž¶ážáž²áŸ’យបានážáŸ’រឹមážáŸ’រូវ</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ស្វែងរក</translation>
+<translation id="6630043285902923878">កំពុងស្វែងរកឧបករណ០USB...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ជម្រះ</translation>
@@ -1510,6 +1551,7 @@
<translation id="6671697161687535275">យកការផ្ážáž›áŸ‹áž™áŸ„បល់ទម្រង់ចáŸáž‰áž–ី Chromium ឬ?</translation>
<translation id="6685834062052613830">ចាកចáŸáž‰ និងបញ្ចប់ការដំឡើង</translation>
<translation id="6687335167692595844">បានស្នើសុំ​ទំហំពុម្ពអក្សរ</translation>
+<translation id="6688743156324860098">ធ្វើបច្ចុប្បន្នភាព…</translation>
<translation id="6689249931105087298">ពាក់ពáŸáž“្ធនឹង​ការបង្ហាប់​ចំណុចážáŸ’មៅ</translation>
<translation id="6689271823431384964">Chrome ផ្ដល់ជូន​ជម្រើស​រក្សាទុកបណ្ណ​របស់អ្នក​នៅក្នុង​គណនី Google របស់អ្នក ដោយសារ​អ្នកចូល​គណនី។ អ្នកអាច​ប្ដូរសកម្មភាពនáŸáŸ‡â€‹áž”ាននៅក្នុង​ការកំណážáŸ‹áŸ” ឈ្មោះ​ម្ចាស់បណ្ណ​គឺបានមកពី​គណនី​របស់អ្នក។</translation>
<translation id="6698381487523150993">បានបង្កើážáŸ–</translation>
@@ -1525,6 +1567,7 @@
<translation id="6744009308914054259">អ្នក​អាចចូលទៅកាន់ការ​ទាញយក ដើម្បីអានអážáŸ’ážáž”ទដែល​អាច​អានបានពáŸáž›áž‚្មានអ៊ីនធឺណិហនៅពáŸáž›áž€áŸ†áž–ុងរង់ចាំការážáž—្ជាប់។</translation>
<translation id="6753269504797312559">ážáž˜áŸ’លៃគោលការណáŸ</translation>
<translation id="6757797048963528358">ឧបករណáŸážšáž”ស់អ្នកបានដáŸáž€áž áž¾áž™</translation>
+<translation id="6767985426384634228">ធ្វើបច្ចុប្បន្នភាព​អាសយដ្ឋាន​ឬ?</translation>
<translation id="6768213884286397650">Hagaki (បណ្ណប្រៃសណីយáŸ)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ស្វាយ</translation>
@@ -1547,6 +1590,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome បានសម្រួលទំពáŸážšáž“áŸáŸ‡ ដើម្បី​ឱ្យងាយស្រួលអានជាងមុន។ Chrome បានទាញយក​ទំពáŸážšážŠáž¾áž˜â€‹ážáž¶áž˜ážšáž™áŸˆáž€áž¶ážšážáž—្ជាប់ដែលគ្មានសុវážáŸ’ážáž·áž—ាព។</translation>
<translation id="6891596781022320156">កម្រិážáž‚ោលការណáŸáž˜áž·áž“ážáŸ’រូវបានគាំទ្រទáŸáŸ”</translation>
+<translation id="6895143722905299846">áž›áŸážáž€áž¶ážáž“ិម្មិážáŸ–</translation>
<translation id="6895330447102777224">កាážážšáž”ស់អ្នកបានបញ្ជាក់រួចហើយ</translation>
<translation id="6897140037006041989">ភ្នាក់ងារអ្នកប្រើ</translation>
<translation id="6898699227549475383">អង្គភាព (O)</translation>
@@ -1582,10 +1626,10 @@
<translation id="7004583254764674281">ប្រើ Windows Hello ដើម្បី​បញ្ជាក់​បណ្ណ​ឱ្យ​បាន​រហáŸážŸâ€‹áž‡áž¶áž„មុន</translation>
<translation id="7006930604109697472">មិនអីទ០ផ្ញើចុះ</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ការកំណážáŸ‹áž€áž¶ážšáž”្ដូរ​ទំហំ</translation>
<translation id="7014741021609395734">កម្រិážâ€‹áž–ង្រីកបង្រួម</translation>
<translation id="7016992613359344582">ការគិážáž”្រាក់ទាំងនáŸáŸ‡áž¢áž¶áž…ធ្វើឡើងម្ដង ឬច្រើន​ដង ហើយអាចនឹងមិនមាន​ការបញ្ជាក់ច្បាស់លាស់នោះទáŸáŸ”</translation>
<translation id="7029809446516969842">ពាក្យសម្ងាážáŸ‹</translation>
+<translation id="7030436163253143341">វិញ្ញាបនបážáŸ’រ​មិនមានសុពលភាពទáŸ</translation>
<translation id="7031646650991750659">ážáž¶ážáž¾áž€áž˜áŸ’មវិធី Google Play ណាážáŸ’លះដែលអ្នកបានដំឡើង</translation>
<translation id="7050187094878475250">អ្នកបានព្យាយាមចូលទៅ <ph name="DOMAIN" />, ប៉ុន្ážáŸ‚វិញ្ញាបនបážáŸ’រនៃម៉ាស៊ីនមáŸáž“áŸáŸ‡áž˜áž¶áž“សុពលភាពយូរពáŸáž€ážŠáŸ‚លមិនគួរឲ្យទុកចិážáŸ’ážáŸ”</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{មិនអាចរក្សាទុកបណ្ណនáŸáŸ‡áž”ានទáŸáž“ៅពáŸáž›áž“áŸáŸ‡}other{មិនអាចរក្សាទុកបណ្ណទាំងនáŸáŸ‡áž”ានទáŸáž“ៅពáŸáž›áž“áŸáŸ‡}}</translation>
@@ -1655,12 +1699,14 @@
<translation id="7300012071106347854">ážáŸ€ážœážáŸ’លា</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">ážáŸ’ពស់</translation>
+<translation id="7305756307268530424">ចាប់ផ្ដើម​ក្នុងល្បឿន​កាន់ážáŸ‚យឺáž</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">ជំនួយ​ការážáž—្ជាប់</translation>
<translation id="7323804146520582233">លាក់​ផ្នែក "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">ការលុបពីលើ​គណនី​មូលដ្ឋាន​ក្នុង​ឧបករណáŸ</translation>
<translation id="7333654844024768166">អ្នកទើបážáŸ‚​បានបញ្ចូល​ពាក្យសម្ងាážáŸ‹â€‹ážšáž”ស់អ្នក​នៅលើ​គáŸáž áž‘ំពáŸážšáž”ញ្ឆោážáŸ” Chromium សូមណែនាំឱ្យ​ចូលទៅកាន់ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> áž“áž·áž„áž‚áŸáž áž‘ំពáŸážšâ€‹áž•áŸ’សáŸáž„ទៀហ​ដែលអ្នកប្រើ​ពាក្យសម្ងាážáŸ‹â€‹áž“áŸáŸ‡ រួច​ប្ដូរ​វាឥឡូវនáŸáŸ‡áŸ”</translation>
<translation id="7334320624316649418">ធ្វើការážáž˜áŸ’រៀបឡើងវិញ</translation>
+<translation id="7337248890521463931">បង្ហាញបន្ទាážáŸ‹áž…្រើនជាងនáŸáŸ‡</translation>
<translation id="7337706099755338005">មិនមាន​នៅលើ​ប្រពáŸáž“្ធ​របស់អ្នក​ទáŸáŸ”</translation>
<translation id="733923710415886693">វិញ្ញាបនបážáŸ’រម៉ាស៊ីនមáŸáž˜áž·áž“ážáŸ’រូវបានបង្ហាញឲ្យដឹងážáž¶áž˜ážšáž™áŸˆáž‚ោលការណáŸážáž˜áŸ’លាភាពវិញ្ញាបនបážáŸ’រ។</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1668,6 +1714,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">អážáŸ’ážáž”ទបញ្ជា</translation>
<translation id="7359588939039777303">បាន​ទប់ស្កាážáŸ‹â€‹áž€áž¶ážšáž•áŸ’សាយ​ពាណិជ្ជកម្ម។</translation>
+<translation id="7363096869660964304">ប៉ុន្ážáŸ‚ áž‚áŸáž“ៅážáŸ‚​មើលឃើញអ្នក។ ការប្រើមុážáž„ារ​ឯកជន​មិនលាក់ការរុករក​របស់អ្នក​ពីនិយោជក​របស់អ្នក ក្រុមហ៊ុន​ផ្ដល់​សáŸážœáž¶áž€áž˜áŸ’ម​អ៊ីនធឺណិážâ€‹ážšáž”ស់អ្នក ឬគáŸáž áž‘ំពáŸážšâ€‹ážŠáŸ‚លអ្នកចូលមើលឡើយ។</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, ចុច "Tab" រួចចុច "Enter" ដើម្បីបញ្ចូល និងគ្រប់គ្រងអាសយដ្ឋាននៅក្នុងការកំណážáŸ‹ Chrome</translation>
<translation id="7365849542400970216">ដឹងអំពីការប្រើប្រាស់​ឧបករណáŸážšáž”ស់អ្នក​ហើយឬនៅ?</translation>
<translation id="7372973238305370288">លទ្ធផលស្វែងរក</translation>
@@ -1678,7 +1725,9 @@
<translation id="7378594059915113390">ការគ្រប់គ្រង​មáŸážŒáŸ€</translation>
<translation id="7378627244592794276">áž‘áŸ</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">មិនអាច​អនុវážáŸ’ážáž”ាន</translation>
<translation id="7390545607259442187">បញ្ជាក់កាáž</translation>
+<translation id="7392089738299859607">ធ្វើ​បច្ចុប្បន្នភាព​អាសយដ្ឋាន​</translation>
<translation id="7399802613464275309">ការពិនិážáŸ’យ​សុវážáŸ’ážáž·áž—ាព</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> របស់អ្នកážáŸ’រូវ​បានគ្រប់គ្រង</translation>
@@ -1693,6 +1742,7 @@
&lt;li&gt;សូមចូល​ទៅកាន់ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;មជ្ឈមណ្ឌល​ជំនួយ Chrome&lt;/a&gt; ដើម្បី​ស្វែង​យល់​ពី​របៀប​លុប​កម្មវិធីនáŸáŸ‡â€‹áž…áŸáž‰â€‹áž–ី​កុំព្យូទáŸážšâ€‹ážšáž”ស់អ្នក​ជាអចិន្ážáŸ’រៃយáŸ
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">គួរឱ្យ​ស្រឡាញ់</translation>
<translation id="7416351320495623771">គ្រប់គ្រង​ពាក្យ​សម្ងាážáŸ‹â€¦</translation>
<translation id="7419106976560586862">ផ្លូវទម្រង់</translation>
<translation id="7437289804838430631">បញ្ចូល​ពáŸážáŸŒáž˜áž¶áž“​ទំនាក់ទំនង</translation>
@@ -1708,7 +1758,7 @@
<translation id="7481312909269577407">ទៅមុáž</translation>
<translation id="7485870689360869515">គ្មានទិន្ននáŸáž™ážáŸ’រូវបានរកឃើញទáŸáŸ”</translation>
<translation id="7495528107193238112">ážáŸ’លឹមសារ​នáŸáŸ‡â€‹ážáŸ’រូវបាន​ទប់ស្កាážáŸ‹â€‹áŸ” សូមទាក់ទង​ម្ចាស់​គáŸáž áž‘ំពáŸážš ដើម្បី​ដោះស្រាយ​បញ្ហានáŸáŸ‡â€‹áŸ”</translation>
-<translation id="7498234416455752244">បន្ážâ€‹áž€áŸ‚សម្រួល</translation>
+<translation id="7498193950643227031">អាចដំណើរការážáž»ážŸáž”្រក្រážáž¸ ប្រសិនបើប្ដូរទំហំ។ ឥឡូវនáŸáŸ‡ អ្នកអាចដាក់កំហិážáž›áž‘្ធភាពប្ដូរទំហំកម្មវិធីនៅក្នុង <ph name="SETTINGS" /> បានហើយ។</translation>
<translation id="7503664977220660814">អ្នកទើបážáŸ‚​បានបញ្ចូល​ពាក្យសម្ងាážáŸ‹â€‹ážšáž”ស់អ្នក​នៅលើ​គáŸáž áž‘ំពáŸážšáž”ញ្ឆោážáŸ” Chromium សូមណែនាំឱ្យ​ពិនិážáŸ’យមើល​ពាក្យសម្ងាážáŸ‹â€‹ážŠáŸ‚លអ្នក​បានរក្សាទុក​សម្រាប់ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> និង​គáŸáž áž‘ំពáŸážšâ€‹áž•áŸ’សáŸáž„ទៀហដែលអ្នក​ប្រើ​ពាក្យសម្ងាážáŸ‹â€‹áž“áŸáŸ‡â€‹áž¥áž¡áž¼ážœáž“áŸáŸ‡â€‹áŸ”</translation>
<translation id="7508255263130623398">áž›áŸážážŸáž˜áŸ’គាល់ឧបករណáŸáž‚ោលការណáŸáž”្រគល់ážáŸ’រឡប់វិញគឺទទ០ឬមិនážáŸ’រូវគ្នាជាមួយលáŸážážŸáž˜áŸ’គាល់ឧបករណáŸáž”ច្ចុប្បន្ន</translation>
<translation id="7508870219247277067">បៃážáž„ážáŸ’ចី</translation>
@@ -1728,6 +1778,7 @@
<translation id="7548892272833184391">ដោះ​ស្រាយ​បញ្ហា​លើការážáž—្ជាប់</translation>
<translation id="7549584377607005141">áž‚áŸáž áž‘ំពáŸážšáž“áŸáŸ‡ážáž˜áŸ’រូវឲ្យមានទិន្ននáŸáž™ážŠáŸ‚លអ្នកបញ្ចូលពីមុនដើម្បីបង្ហាញឲ្យបានážáŸ’រឹមážáŸ’រូវ។ អ្នកអាចផ្ញើទិន្ននáŸáž™áž“áŸáŸ‡áž˜áŸ’ážáž„ទៀហប៉ុន្ážáŸ‚ការធ្វើដូច្នáŸáŸ‡ ធ្វើឲ្យសកម្មភាពសកម្មភាពណាមួួយដែលទំពáŸážšáž“áŸáŸ‡áž”ានប្រážáž·áž”ážáŸ’ážáž·áž€áž¶ážšáž€áž¾ážáž¡áž¾áž„សាជាážáŸ’មី។</translation>
<translation id="7550637293666041147">ឈ្មោះអ្នកប្រើប្រាស់ Chrome និង​ឈ្មោះអ្នកប្រើប្រាស់ឧបករណáŸâ€‹ážšáž”ស់អ្នក</translation>
+<translation id="755279583747225797">ការសាកល្បង​កំពុង​ដំណើរការ</translation>
<translation id="7552846755917812628">សាកល្បងធ្វើážáž¶áž˜áž‚ន្លឹះážáž¶áž„ក្រោម៖</translation>
<translation id="7554475479213504905">មិនអីទ០ផ្ទុកឡើងវិញ រួច​បង្ហាញចុះ</translation>
<translation id="7554791636758816595">ផ្ទាំងážáŸ’មី</translation>
@@ -1747,7 +1798,6 @@
<translation id="7610193165460212391">ážáž˜áŸ’លៃនៅក្រៅចន្លោះ <ph name="VALUE" />។</translation>
<translation id="7613889955535752492">áž•áž»ážáž€áŸ†ážŽážáŸ‹áŸ– <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ចុច "Tab" រួចចុច "Enter" ដើម្បីមើល និងគ្រប់គ្រងពាក្យសម្ងាážáŸ‹ážšáž”ស់អ្នកនៅក្នុងការកំណážáŸ‹ Chrome</translation>
-<translation id="7615602087246926389">អ្នកមានទិន្ននáŸáž™ážŠáŸ‚លបានអ៊ីនគ្រីប ដោយប្រើកំណែផ្សáŸáž„ទៀážáž“ៃពាក្យសម្ងាážáŸ‹áž‚ណនី Google របស់អ្នករួចហើយ។ សូមបញ្ចូលវាážáž¶áž„ក្រោម។</translation>
<translation id="7616645509853975347">អ្នកគ្រប់គ្រង​របស់អ្នក​បានបើក Chrome Enterprise Connectors នៅលើ​កម្មវិធីរុករក​ážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិážâ€‹ážšáž”ស់អ្នក​។ កម្មវិធីភ្ជាប់ទាំងនáŸáŸ‡áž˜áž¶áž“សិទ្ធិចូលប្រើ​ទិន្ននáŸáž™áž˜áž½áž™áž…ំនួនរបស់អ្នក។</translation>
<translation id="7619838219691048931">សន្លឹកបញ្ចប់</translation>
<translation id="762844065391966283">ម្ដងមួយៗ</translation>
@@ -1812,13 +1862,12 @@
<translation id="782886543891417279">Wi-Fi ដែលអ្នកកំពុងប្រើ (<ph name="WIFI_NAME" />) អាចážáž˜áŸ’រូវឲ្យអ្នកទៅកាន់ទំពáŸážšáž…ុះឈ្មោះរបស់វា។</translation>
<translation id="7836231406687464395">Postfix (ស្រោម​សំបុážáŸ’ážš)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{គ្មាន}=1{កម្មវិធី 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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">បើកឯកសារដោយប្រើភាពពាក់ពáŸáž“្ធនៃប្រភáŸáž‘ឯកសារ។</translation>
<translation id="7862185352068345852">ចាកចáŸáž‰áž–ី​ទំពáŸážš?</translation>
<translation id="7865448901209910068">ល្បឿន​ល្អបំផុáž</translation>
<translation id="7874263914261512992">អ្នកទើបážáŸ‚​បានបញ្ចូល​ពាក្យសម្ងាážáŸ‹â€‹ážšáž”ស់អ្នក​នៅលើ​គáŸáž áž‘ំពáŸážšáž”ញ្ឆោážáŸ” Chrome សូមណែនាំឱ្យ​ពិនិážáŸ’យមើល​ពាក្យសម្ងាážáŸ‹â€‹ážŠáŸ‚លអ្នក​បានរក្សាទុក​សម្រាប់ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> និង​គáŸáž áž‘ំពáŸážšâ€‹áž•áŸ’សáŸáž„ទៀហដែលអ្នក​ប្រើ​ពាក្យសម្ងាážáŸ‹â€‹áž“áŸáŸ‡â€‹áž¥áž¡áž¼ážœáž“áŸáŸ‡â€‹áŸ”</translation>
<translation id="7878562273885520351">ពាក្យសម្ងាážáŸ‹â€‹ážšáž”ស់អ្នក​អាចážáŸ’រូវ​បានគáŸáž›áž½áž…ប្រើ​</translation>
+<translation id="7880146494886811634">រក្សាទុក​អាសយដ្ឋាន</translation>
<translation id="7882421473871500483">ážáŸ’នោáž</translation>
<translation id="7887683347370398519">áž–áž·áž“áž·ážáŸ’យលáŸážáž€áž¼ážŠ CVC ហើយព្យាយាមម្ážáž„ទៀáž</translation>
<translation id="7887885240995164102">ចូលមុážáž„ារ​រូបក្នុងរូប</translation>
@@ -1826,6 +1875,7 @@
<translation id="7894280532028510793">ប្រសិនបើ​អក្ážážšáž¶ážœáž·ážšáž»áž‘្ធគឺážáŸ’រឹមážáŸ’រូវ <ph name="BEGIN_LINK" />សូមសាកល្បង​ដំណើរការ​ការវិភាគបណ្ដាញ<ph name="END_LINK" />។</translation>
<translation id="7904208859782148177">C3 (ស្រោម​សំបុážáŸ’ážš)</translation>
<translation id="7931318309563332511">មិនស្គាល់</translation>
+<translation id="793209273132572360">ធ្វើបច្ចុប្បន្នភាព​អាសយដ្ឋាន​ដែរទ�</translation>
<translation id="7932579305932748336">ស្រោប</translation>
<translation id="79338296614623784">បញ្ចូលលáŸážáž‘ូរសព្ទដែលážáŸ’រឹមážáŸ’រូវ</translation>
<translation id="7934052535022478634">ការបង់ប្រាក់​បានបញ្ចប់​ហើយ</translation>
@@ -1896,6 +1946,7 @@
<translation id="8175796834047840627">Chrome ផ្ដល់ជូន​ជម្រើស​រក្សាទុកបណ្ណរបស់អ្នកនៅ​ក្នុងគណនី Google របស់អ្នក ដោយសារ​អ្នកចូលគណនី។ អ្នកអាចប្ដូរសកម្មភាពនáŸáŸ‡â€‹áž”ាននៅក្នុងការកំណážáŸ‹áŸ”</translation>
<translation id="8176440868214972690">អ្នកគ្រប់គ្រងឧបករណáŸáž“áŸáŸ‡áž”ានបញ្ជូនពáŸážáŸŒáž˜áž¶áž“មួយចំនួនទៅគáŸáž áž‘ំពáŸážšážáž¶áž„ក្រោមដូចជា ការកំណážáŸ‹ ឬគោលការណáŸáž‡áž¶ážŠáž¾áž˜áŸ”</translation>
<translation id="8184538546369750125">ប្រើលំនាំដើមជាសកល (អនុញ្ញាáž)</translation>
+<translation id="8193086767630290324">សកម្មភាព​ដែលបានធ្វើឡើង ពាក់ពáŸáž“្ធនឹង​ទិន្ននáŸáž™ážŠáŸ‚លបាន​សម្គាល់ážáž¶â€‹áž‡áž¶áž€áž¶ážšážŸáž˜áŸ’ងាážáŸ‹</translation>
<translation id="8194797478851900357">បកក្រោយការផ្លាស់ទី</translation>
<translation id="8201077131113104583">URL បច្ចុប្បន្នភាពគ្មានសុពលភាពសម្រាប់កម្មវិធីបន្ážáŸ‚មដែលមានលáŸážážŸáž˜áŸ’គាល់ "<ph name="EXTENSION_ID" />"។</translation>
<translation id="8202097416529803614">សង្ážáŸáž”នៃការបញ្ជាទិញ</translation>
@@ -1918,6 +1969,7 @@
<translation id="8249296373107784235">បោះបង់</translation>
<translation id="8249320324621329438">បាននាំយកចុងក្រោយ៖</translation>
<translation id="8253091569723639551">ážáž˜áŸ’រូវឲ្យមានអាសយដ្ឋានបញ្ចូលវិក្កយបážáŸ’ážš</translation>
+<translation id="8257387598443225809">កម្មវិធីនáŸáŸ‡ážáŸ’រូវបានរចនាសម្រាប់ឧបករណáŸáž…áž›áŸáž</translation>
<translation id="825929999321470778">បង្ហាញ​ពាក្យ​សម្ងាážáŸ‹â€‹ážŠáŸ‚ល​បាន​រក្សាទុក​ទាំងអស់</translation>
<translation id="8261506727792406068">លុប</translation>
<translation id="8262952874573525464">ដáŸážšáž‚ែម​ážáž¶áž„ក្រោម</translation>
@@ -2041,7 +2093,6 @@
<translation id="8719528812645237045">ចោះ​ច្រើនរន្ធ​ážáž¶áž„លើ</translation>
<translation id="8725066075913043281">ព្យាយាមម្ážáž„ទៀáž</translation>
<translation id="8726549941689275341">ទំហំ​ទំពáŸážšáŸ–</translation>
-<translation id="8728672262656704056">អ្នកបានចូលមុážáž„ារឯកជន</translation>
<translation id="8730621377337864115">រួចរាល់</translation>
<translation id="8731544501227493793">ប៊ូážáž»áž„ "គ្រប់គ្រងពាក្យសម្ងាážáŸ‹" ចុច "Enter" ដើម្បីមើល និងគ្រប់គ្រងពាក្យសម្ងាážáŸ‹ážšáž”ស់អ្នកនៅក្នុងការកំណážáŸ‹ Chrome</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> របស់​អ្នក​ស្ážáž·ážáž€áŸ’រោម​ការគ្រប់គ្រង​របស់ <ph name="MANAGER" /></translation>
@@ -2118,6 +2169,7 @@
<translation id="9020542370529661692">áž‚áŸáž áž‘ំពáŸážšáž“áŸáŸ‡ážáŸ’រូវបានបកប្រែទៅ <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(គ្មាន​សុពល​ភាព)</translation>
+<translation id="9030265603405983977">មួយពណ៌</translation>
<translation id="9035022520814077154">កំហុសឆ្គងសុវážáŸ’ážáž·áž—ាព</translation>
<translation id="9038649477754266430">ប្រើសáŸážœáž¶áž€áž˜áŸ’មព្យាករណáŸážŠáž¾áž˜áŸ’បីដំណើរការទំពáŸážšážšáž áŸážŸáž‡áž¶áž„មុន</translation>
<translation id="9039213469156557790">ជាងនáŸáŸ‡áž‘ៅទៀហទំពáŸážšáž“áŸáŸ‡ážšáž¶áž”់បញ្ចូលធនធានផ្សáŸáž„ទៀážážŠáŸ‚លគ្មានសុវážáŸ’ážáž·áž—ាព។ ធនធានទាំងនáŸáŸ‡áž¢áž¶áž…ážáŸ’រូវបានមើលដោយអ្នកផ្សáŸáž„ទៀážážážŽáŸˆáž–áŸáž›áž†áŸ’លងកាážáŸ‹ និងអាចážáŸ’រូវបានកែសម្រួលដោយអ្នកវាយប្រហារដើម្បីប្ážáž¼ážšáž›áž€áŸ’ážážŽáŸˆážŸáž˜áŸ’áž”ážáž·áŸ’ážážšáž”ស់ទំពáŸážšáŸ”</translation>
@@ -2141,6 +2193,7 @@
<translation id="91108059142052966">គោលការណáŸâ€‹ážšáž”ស់អ្នកគ្រប់គ្រង​បិទការបង្ហាញអáŸáž€áŸ’រង់​ជាមួយ <ph name="APPLICATION_TITLE" /> នៅពáŸáž›áž¢áž¶áž…​មើលឃើញážáŸ’លឹមសារ​សម្ងាážáŸ‹</translation>
<translation id="9114524666733003316">កំពុង​បញ្ជាក់​បណ្ណ​ឥណទាន...</translation>
<translation id="9114581008513152754">កម្មវិធីរុករក​ážáž¶áž˜áž¢áŸŠáž¸áž“ធឺណិážâ€‹áž“áŸáŸ‡â€‹áž˜áž·áž“ស្ážáž·ážáž€áŸ’រោម​ការគ្រប់គ្រង​របស់ក្រុមហ៊ុន ឬ​ស្ážáž¶áž”áŸáž“ផ្សáŸáž„áž‘áŸâ€‹áŸ” សកម្មភាព​នៅលើឧបករណáŸáž“áŸáŸ‡â€‹áž¢áž¶áž…នឹងážáŸ’រូវបាន​គ្រប់គ្រងក្រៅពី Chrome។ <ph name="BEGIN_LINK" />ស្វែងយល់បន្ážáŸ‚ម<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ស្រស់ស្រាយ</translation>
<translation id="9119042192571987207">បាន​បង្ហោះ</translation>
<translation id="9128016270925453879">គោលការណáŸážáŸ’រូវបានផ្ទុក</translation>
<translation id="9128870381267983090">ភ្ជាប់ទៅបណ្ážáž¶áž‰</translation>
@@ -2159,6 +2212,7 @@
<translation id="9170848237812810038">បកក្រោយ</translation>
<translation id="9171296965991013597">ចាកចáŸáž‰â€‹áž–ីកម្មវិធី?</translation>
<translation id="9173282814238175921">ឯកសារ​ážáŸ‚មួយ/សន្លឹកážáŸ’មី</translation>
+<translation id="9173995187295789444">កំពុងស្កáŸáž“រកឧបករណáŸáž”៊្លូធូស...</translation>
<translation id="917450738466192189">វិញ្ញាបនបáŸážáŸ’រម៉ាស៊ីនមáŸáž‚្មានសុពលភាព។</translation>
<translation id="9174917557437862841">ចុច​ប៊ូážáž»áž„​ប្ដូរ រួចចុច "Enter" ដើម្បី​ប្ដូរ​ទៅ​ផ្ទាំងនáŸáŸ‡</translation>
<translation id="9179703756951298733">គ្រប់គ្រងការបង់ប្រាក់ áž“áž·áž„áž–áŸážáŸŒáž˜áž¶áž“អំពី​បណ្ណឥណទានរបស់អ្នក​នៅក្នុងការកំណážáŸ‹ Chrome</translation>
diff --git a/chromium/components/strings/components_strings_kn.xtb b/chromium/components/strings/components_strings_kn.xtb
index 9338eab389c..8f89c66a3be 100644
--- a/chromium/components/strings/components_strings_kn.xtb
+++ b/chromium/components/strings/components_strings_kn.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">ಪರಿಶೀಲಿಸಿದರೆ, ವೇಗವಾಗಿ ಫಾರà³à²®à³ ಭರà³à²¤à²¿ ಮಾಡಲೠChrome ಈ ಸಾಧನದಲà³à²²à²¿ ನಿಮà³à²® ಕಾರà³à²¡à³â€Œà²¨ ಪà³à²°à²¤à²¿à²¯à²¨à³à²¨à³ ಸಂಗà³à²°à²¹à²¿à²¸à³à²¤à³à²¤à²¦à³†.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> ಗಾಗಿ ಅನà³à²®à²¤à²¿à²¯à²¨à³à²¨à³ ಆಯà³à²•à³†à²®à²¾à²¡à²¿</translation>
<translation id="1113869188872983271">&amp;ಮರà³à²•à³à²°à²®à²—ೊಳಿಸà³à²µà³à²¦à²¨à³à²¨à³ ರದà³à²¦à³à²—ೊಳಿಸಿ</translation>
+<translation id="1123753900084781868">ಲೈವೠಕà³à²¯à²¾à²ªà³à²¶à²¨à³ ಸದà³à²¯à²•à³à²•à³† ಲಭà³à²¯à²µà²¿à²²à³à²²</translation>
<translation id="1125573121925420732">ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳೠತಮà³à²® ಸà³à²°à²•à³à²·à²¤à³†à²¯à²¨à³à²¨à³ ಅಪà³â€Œà²¡à³‡à²Ÿà³â€Œ ಮಾಡà³à²µà²¾à²—, ಸಾಮಾನà³à²¯à²µà²¾à²—ಿ ಎಚà³à²šà²°à²¿à²•à³†à²—ಳೠಕಾಣಿಸಿಕೊಳà³à²³à²¬à²¹à³à²¦à³. ಇದನà³à²¨à³ ಶೀಘà³à²°à²¦à²²à³à²²à³‡ ಸà³à²§à²¾à²°à²¿à²¸à²²à²¾à²—à³à²µà³à²¦à³.</translation>
<translation id="112840717907525620">ನೀತಿಯ ಕà³à²¯à²¾à²·à³ ಸರಿಯಾಗಿದೆ</translation>
<translation id="1130564665089811311">ಪà³à²Ÿ ಅನà³à²µà²¾à²¦à²¿à²¸à²¿ ಬಟನà³, ಈ ಪà³à²Ÿà²µà²¨à³à²¨à³ Google Translate ನೊಂದಿಗೆ ಅನà³à²µà²¾à²¦à²¿à²¸à²²à³ Enter ಒತà³à²¤à²¿à²°à²¿</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">ನಿಮà³à²® ಸಾಧನದ ಹೆಸರà³</translation>
<translation id="124116460088058876">ಹೆಚà³à²šà²¿à²¨ ಭಾಷೆಗಳà³</translation>
<translation id="1243027604378859286">ಲೇಖಕರà³:</translation>
+<translation id="1246424317317450637">ಬೋಲà³à²¡à³</translation>
<translation id="1250759482327835220">ಮà³à²‚ದಿನ ಬಾರಿ ವೇಗವಾಗಿ ಪಾವತಿಸಲà³, ನಿಮà³à²® ಕಾರà³à²¡à³, ಹೆಸರೠಮತà³à²¤à³ ಬಿಲà³à²²à²¿à²‚ಗೠವಿಳಾಸವನà³à²¨à³ ನಿಮà³à²® Google ಖಾತೆಯಲà³à²²à²¿ ಉಳಿಸಿ.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (ಸಿಂಕೠಮಾಡಲಾಗಿದೆ)</translation>
<translation id="1256368399071562588">&lt;p&gt;ನೀವೠವೆಬà³â€Œà²¸à³ˆà²Ÿà³ ಅನà³à²¨à³ ಭೇಟಿ ಮಾಡಲೠಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à³à²¤à³à²¤à²¿à²¦à³à²¦à²°à³† ಮತà³à²¤à³ ಅದೠತೆರೆಯದಿದà³à²¦à²°à³†, ಮೊದಲೠಈ ದೋಷ ನಿವಾರಕ ಕà³à²°à²®à²—ಳಿಂದ ಆ ದೋಷವನà³à²¨à³ ಸರಿಪಡಿಸಲೠಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¿:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">ನಿಮà³à²® ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅನà³à²¨à³ ಬದಲಾಯಿಸಿ</translation>
<translation id="1484290072879560759">ಶಿಪà³à²ªà²¿à²‚ಗೠವಿಳಾಸವನà³à²¨à³ ಆರಿಸಿ</translation>
<translation id="1492194039220927094">ಕಾರà³à²¯à²¨à³€à²¤à²¿à²—ಳನà³à²¨à³ ಪà³à²¶à³ ಮಾಡà³à²µ ಕà³à²°à²¿à²¯à³†:</translation>
+<translation id="1495677929897281669">ಟà³à²¯à²¾à²¬à³â€Œà²—ೆ ಮರಳಿ</translation>
<translation id="1501859676467574491">ನಿಮà³à²® Google ಖಾತೆಯಲà³à²²à²¿à²°à³à²µ ಕಾರà³à²¡à³â€Œà²—ಳನà³à²¨à³ ತೋರಿಸಿ</translation>
<translation id="1507202001669085618">&lt;p&gt;ನೀವೠಆನà³â€Œà²²à³ˆà²¨à³ ಪà³à²°à²µà³‡à²¶à²¿à²¸à³à²µ ಮೊದಲೠಸೈನà³â€Œ ಇನà³â€Œ ಮಾಡಬೇಕಾದ ವೈ-ಫೈ ಪೋರà³à²Ÿà²²à³ ಅನà³à²¨à³ ಬಳಸà³à²¤à³à²¤à²¿à²¦à³à²¦à²°à³† ಈ ದೋಷವನà³à²¨à³ ಕಾಣà³à²¤à³à²¤à³€à²°à²¿.&lt;/p&gt; &lt;p&gt;ನೀವೠತೆರೆಯಲೠಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à³à²¤à³à²¤à²¿à²°à³à²µ ಪà³à²Ÿà²¦à²²à³à²²à²¿ ದೋಷವನà³à²¨à³ ಸರಿಪಡಿಸಲೠ&lt;strong&gt;ಸಂಪರà³à²•à²¿à²¸à²¿&lt;/strong&gt; ಅನà³à²¨à³ ಕà³à²²à²¿à²•à³â€Œ ಮಾಡಿ.&lt;/p&gt;</translation>
<translation id="1513706915089223971">ಇತಿಹಾಸ ನಮೂದà³à²—ಳ ಪಟà³à²Ÿà²¿</translation>
@@ -170,6 +173,7 @@
<translation id="1532118530259321453">ಈ ಪà³à²Ÿà²µà³ ಹೀಗೆ ಹೇಳà³à²¤à³à²¤à²¦à³†</translation>
<translation id="153384715582417236">ಇದà³à²µà²°à³†à²—ೂ ಇಷà³à²Ÿà³‡</translation>
<translation id="1536390784834419204">ಪà³à²Ÿà²µà²¨à³à²¨à³ ಅನà³à²µà²¾à²¦à²¿à²¸à²¿</translation>
+<translation id="1539840569003678498">ವರದಿಯನà³à²¨à³ ಕಳà³à²¹à²¿à²¸à²²à²¾à²—ಿದೆ:</translation>
<translation id="154408704832528245">ವಿತರಣೆಯ ವಿಳಾಸಗಳನà³à²¨à³ ಆರಿಸಿ</translation>
<translation id="1549470594296187301">ಈ ವೈಶಿಷà³à²Ÿà³à²¯à²µà²¨à³à²¨à³ ಬಳಸಲೠJavaScript ಸಕà³à²°à²¿à²¯à²—ೊಳಿಸಬೇಕà³.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -212,16 +216,19 @@
<translation id="1682696192498422849">ಚಿಕà³à²• ಅಂಚೠಮೊದಲà³</translation>
<translation id="168693727862418163">ಈ ನೀತಿ ಮೌಲà³à²¯à²µà²¨à³à²¨à³ ಅದರ ರೂಪà³à²°à³‡à²·à³† ವಿರà³à²¦à³à²§ ಮೌಲà³à²¯à³€à²•à²°à²¿à²¸à²²à³ ವಿಫಲವಾಗಿದೆ ಮತà³à²¤à³ ಅದನà³à²¨à³ ನಿರà³à²²à²•à³à²·à²¿à²¸à²²à²¾à²—à³à²¤à³à²¤à²¦à³†.</translation>
<translation id="168841957122794586">ಸರà³à²µà²°à³ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²°à²µà³ ದà³à²°à³à²¬à²² ಕà³à²°à²¿à²ªà³à²Ÿà³‹à²—à³à²°à²¾à²«à²¿à²•à³ ಕೀಯನà³à²¨à³ ಹೊಂದಿದೆ.</translation>
+<translation id="1696290444144917273">ವರà³à²šà³à²µà²²à³ ಕಾರà³à²¡à³ ವಿವರಗಳನà³à²¨à³ ವೀಕà³à²·à²¿à²¸à²¿</translation>
<translation id="1697532407822776718">ನೀವೠಎಲà³à²² ರೀತಿಯಲà³à²²à²¿à²¯à³‚ ಸಿದà³à²§à²°à²¾à²—ಿರà³à²µà²¿à²°à²¿!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{ಈ ಸರà³à²µà²°à³ <ph name="DOMAIN" /> ; ಆಗಿದೆ ಎಂಬà³à²¦à²¨à³à²¨à³ ಸಾಬೀತà³à²ªà²¡à²¿à²¸à²²à³ ಸಾಧà³à²¯à²µà²¾à²—ಲಿಲà³à²²; ಅದರ ಸà³à²°à²•à³à²·à²¤à²¾ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²° ಬಹà³à²¶à²ƒ ನಾಳೆಯಿಂದ ಕಾರà³à²¯à²¨à²¿à²°à³à²µà²¹à²¿à²¸à²¬à²¹à³à²¦à³. ಇದೠತಪà³à²ªà³ ಕಾನà³à²«à²¿à²—ರೇಶನà³â€Œà²¨à²¿à²‚ದ ಅಥವಾ ಆಕà³à²°à²®à²£à²•à²¾à²°à²°à³ ನಿಮà³à²® ಸಂಪರà³à²•à²¦à²²à³à²²à²¿ ಒಳನà³à²¸à³à²³à²¿à²°à³à²µà³à²¦à²°à²¿à²‚ದ ಆಗಿರಬಹà³à²¦à³.}one{ಈ ಸರà³à²µà²°à³ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬà³à²¦à²¨à³à²¨à³ ಸಾಬೀತà³à²ªà²¡à²¿à²¸à²²à³ ಸಾಧà³à²¯à²µà²¾à²—ಲಿಲà³à²²; ಅದರ ಸà³à²°à²•à³à²·à²¤à²¾ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²° ಬಹà³à²¶à²ƒ ಭವಿಷà³à²¯à²¦à²²à³à²²à²¿ # ದಿನಗಳಲà³à²²à²¿ ಕಾರà³à²¯à²¨à²¿à²°à³à²µà²¹à²¿à²¸à²¬à²¹à³à²¦à³. ಇದೠತಪà³à²ªà³ ಕಾನà³à²«à²¿à²—ರೇಶನà³â€Œà²¨à²¿à²‚ದ ಅಥವಾ ಆಕà³à²°à²®à²£à²•à²¾à²°à²°à³ ನಿಮà³à²® ಸಂಪರà³à²•à²¦à²²à³à²²à²¿ ಒಳನà³à²¸à³à²³à²¿à²°à³à²µà³à²¦à²°à²¿à²‚ದ ಆಗಿರಬಹà³à²¦à³.}other{ಈ ಸರà³à²µà²°à³ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬà³à²¦à²¨à³à²¨à³ ಸಾಬೀತà³à²ªà²¡à²¿à²¸à²²à³ ಸಾಧà³à²¯à²µà²¾à²—ಲಿಲà³à²²; ಅದರ ಸà³à²°à²•à³à²·à²¤à²¾ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²° ಬಹà³à²¶à²ƒ ಭವಿಷà³à²¯à²¦à²²à³à²²à²¿ # ದಿನಗಳಲà³à²²à²¿ ಕಾರà³à²¯à²¨à²¿à²°à³à²µà²¹à²¿à²¸à²¬à²¹à³à²¦à³. ಇದೠತಪà³à²ªà³ ಕಾನà³à²«à²¿à²—ರೇಶನà³â€Œà²¨à²¿à²‚ದ ಅಥವಾ ಆಕà³à²°à²®à²£à²•à²¾à²°à²°à³ ನಿಮà³à²® ಸಂಪರà³à²•à²¦à²²à³à²²à²¿ ಒಳನà³à²¸à³à²³à²¿à²°à³à²µà³à²¦à²°à²¿à²‚ದ ಆಗಿರಬಹà³à²¦à³.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="VALUE" /> ಗೆ ಹೊಂದಿಸದ ಕಾರಣ, <ph name="POLICY_NAME" /> ಅನà³à²¨à³ ನಿರà³à²²à²•à³à²·à²¿à²¸à²²à²¾à²—ಿದೆ.</translation>
<translation id="1712552549805331520">ನಿಮà³à²® ಸà³à²¥à²³à³€à²¯ ಕಂಪà³à²¯à³‚ಟರà³â€Œà²¨à²²à³à²²à²¿ ಡೇಟಾವನà³à²¨à³ ಶಾಶà³à²µà²¤à²µà²¾à²—ಿ ಸಂಗà³à²°à²¹à²£à³† ಮಾಡಲೠ<ph name="URL" /> ಬಯಸà³à²¤à³à²¤à²¦à³†</translation>
<translation id="1713628304598226412">ಟà³à²°à³‡ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">ಮೇಲà³â€Œà²¬à²¾à²•à³à²¸à³ 3</translation>
<translation id="1718029547804390981">ಟಿಪà³à²ªà²£à²¿ ಮಾಡಲೠಡಾಕà³à²¯à³à²®à³†à²‚ಟà³â€Œ ತà³à²‚ಬಾ ದೊಡà³à²¡à²¦à²¾à²—ಿದೆ</translation>
<translation id="1721424275792716183">* ಈ ಫೀಲà³à²¡à³ ಅಗತà³à²¯à²µà²¿à²¦à³†</translation>
+<translation id="1727613060316725209">ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²° ಮಾನà³à²¯à²µà²¾à²—ಿದೆ</translation>
<translation id="1727741090716970331">ಮಾನà³à²¯à²µà²¾à²¦ ಕಾರà³à²¡à³ ಸಂಖà³à²¯à³†à²¯à²¨à³à²¨à³ ಸೇರಿಸಿ</translation>
<translation id="1728677426644403582">ನೀವೠವೆಬೠಪà³à²Ÿà²¦ ಮೂಲವನà³à²¨à³ ವೀಕà³à²·à²¿à²¸à³à²¤à³à²¤à²¿à²°à³à²µà²¿à²°à²¿</translation>
<translation id="173080396488393970">ಈ ರೀತಿಯ ಕಾರà³à²¡à³â€Œà²—ೆ ಬೆಂಬಲವಿಲà³à²²</translation>
@@ -244,7 +251,6 @@
ಹೆಡರೠಫೈಲೠವಿರೂಪಗೊಂಡಿದೆ, <ph name="SITE" /> ಅನà³à²¨à³ ಪà³à²°à²µà³‡à²¶à²¿à²¸à²²à³ ನಿಮà³à²® ವಿನಂತಿಯನà³à²¨à³
ಬà³à²°à³Œà²¸à²°à³ ಪೂರೈಸದಂತೆ ತಡೆಯà³à²¤à³à²¤à²¦à³†. ಸೈಟà³â€Œ ಒಂದಕà³à²•à²¾à²—ಿ ಸà³à²°à²•à³à²·à²¤à³† ಮತà³à²¤à³ ಇತರ ಗà³à²£à²²à²•à³à²·à²£à²—ಳನà³à²¨à³ ಕಾನà³à²«à²¿à²—ರೠಮಾಡಲೠಸೈಟೠಆಪರೇಟರà³â€Œà²—ಳೠಮೂಲ ಕಾರà³à²¯à²¨à³€à²¤à²¿à²—ಳನà³à²¨à³ ಬಳಸಬಹà³à²¦à³.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">ದಯವಿಟà³à²Ÿà³ ನಿಮà³à²® ಸಿಂಕೠಪಾಸà³â€Œà²«à³à²°à³‡à²¸à³ ಅನà³à²¨à³ ಅಪà³â€Œà²¡à³‡à²Ÿà³â€Œ ಮಾಡಿ.</translation>
<translation id="1787142507584202372">ನಿಮà³à²® ತೆರೆಯಲಾದ ಟà³à²¯à²¾à²¬à³â€Œà²—ಳೠಇಲà³à²²à²¿ ಗೋಚರಿಸà³à²¤à³à²¤à²¦à³†</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ಅನೇಕ ಕà³à²°à²¿à²¯à³†à²—ಳೠಲಭà³à²¯à²µà²¿à²µà³†. ಅವà³à²—ಳನà³à²¨à³ ಒಂದೊಂದಾಗಿ ನೋಡಲೠಟà³à²¯à²¾à²¬à³ ಒತà³à²¤à²¿</translation>
@@ -277,6 +283,7 @@
<translation id="1919345977826869612">ಜಾಹೀರಾತà³à²—ಳà³</translation>
<translation id="1919367280705858090">ನಿರà³à²¦à²¿à²·à³à²Ÿ ದೋಷ ಸಂದೇಶಕà³à²•à³† ಸಹಾಯ ಪಡೆಯಿರಿ</translation>
<translation id="192020519938775529">{COUNT,plural, =0{ಯಾವà³à²¦à³‚ ಇಲà³à²²}=1{1 ಸೈಟà³}one{# ಸೈಟà³â€Œà²—ಳà³}other{# ಸೈಟà³â€Œà²—ಳà³}}</translation>
+<translation id="1924727005275031552">ಹೊಸತà³</translation>
<translation id="1945968466830820669">ನಿಮà³à²® ಸಂಸà³à²¥à³†à²¯ ಖಾತೆಗೆ ನೀವೠಪà³à²°à²µà³†à³•à²¶à²µà²¨à³à²¨à³ ಕಳೆದà³à²•à³†à³‚ಳà³à²³à²¬à²¹à³à²¦à³ ಅಥವಾ ಗà³à²°à³à²¤à³ ಕಳà³à²³à²¤à²¨à²•à³à²•à³† ಒಳಗಾಗಬಹà³à²¦à³. ನಿಮà³à²® ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œ ಅನà³à²¨à³ ಇದೀಗ ಬದಲಾಯಿಸà³à²µà²‚ತೆ Chromium ಶಿಫಾರಸೠಮಾಡà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="1947454675006758438">ಮೇಲಿನ ಬಲಭಾಗದಲà³à²²à²¿ ಸà³à²Ÿà³‡à²ªà²²à³ ಹಾಕಿ</translation>
<translation id="1958218078413065209">ನಿಮà³à²® ಅತಿ ಹೆಚà³à²šà³ ಸà³à²•à³‹à²°à³ <ph name="SCORE" /> ಆಗಿದೆ.</translation>
@@ -299,12 +306,14 @@
<translation id="2042213636306070719">ಟà³à²°à³‡ 7</translation>
<translation id="204357726431741734">ನಿಮà³à²® Google ಖಾತೆಯಲà³à²²à²¿ ಉಳಿಸಲಾದ ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ಬಳಸಲೠಸೈನೠಇನೠಮಾಡಿ</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" />ಭಾಷೆಯಲà³à²²à²¿à²°à³à²µ ಪà³à²Ÿà²—ಳೠಅನà³à²µà²¾à²¦à²•à³à²•à³Šà²³à²ªà²¡à³à²µà³à²¦à²¿à²²à³à²².</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{ಈ ನಿಯಂತà³à²°à²£à²µà³ ಆನೠಆಗಿದà³à²¦à³ ಹಾಗೂ ಸà³à²¥à²¿à²¤à²¿à²¯à³ ಸಕà³à²°à²¿à²¯à²µà²¾à²—ಿದà³à²¦à²¾à²—, ಯಾವ ಜನರ ದೊಡà³à²¡ ಗà³à²‚ಪೠಅಥವಾ ಜನರ ತಂಡಕà³à²•à³† ನಿಮà³à²® ಇತà³à²¤à³€à²šà²¿à²¨ ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಚಟà³à²µà²Ÿà²¿à²•à³†à²¯à²¨à³à²¨à³ ಹೋಲà³à²¤à³à²¤à²¦à³† ಎಂದೠChrome ನಿರà³à²§à²°à²¿à²¸à³à²¤à³à²¤à²¦à³†. ಜಾಹೀರಾತà³à²¦à²¾à²°à²°à³ ಗà³à²‚ಪಿಗಾಗಿ ಜಾಹೀರಾತà³à²—ಳನà³à²¨à³ ಆಯà³à²•à³† ಮಾಡಬಹà³à²¦à³ ಹಾಗೂ ನಿಮà³à²® ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಚಟà³à²µà²Ÿà²¿à²•à³†à²¯à²¨à³à²¨à³ ನಿಮà³à²® ಸಾಧನದಲà³à²²à²¿ ಖಾಸಗಿಯಾಗಿ ಇರಿಸಲಾಗà³à²¤à³à²¤à²¦à³†. ನಿಮà³à²® ಗà³à²‚ಪನà³à²¨à³ ಪà³à²°à²¤à²¿à²¦à²¿à²¨ ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಲಾಗà³à²¤à³à²¤à²¦à³†.}=1{ಈ ನಿಯಂತà³à²°à²£à²µà³ ಆನೠಆಗಿದà³à²¦à³ ಹಾಗೂ ಸà³à²¥à²¿à²¤à²¿à²¯à³ ಸಕà³à²°à²¿à²¯à²µà²¾à²—ಿದà³à²¦à²¾à²—, ಯಾವ ಜನರ ದೊಡà³à²¡ ಗà³à²‚ಪೠಅಥವಾ ಜನರ ತಂಡಕà³à²•à³† ನಿಮà³à²® ಇತà³à²¤à³€à²šà²¿à²¨ ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಚಟà³à²µà²Ÿà²¿à²•à³†à²¯à²¨à³à²¨à³ ಹೋಲà³à²¤à³à²¤à²¦à³† ಎಂದೠChrome ನಿರà³à²§à²°à²¿à²¸à³à²¤à³à²¤à²¦à³†. ಜಾಹೀರಾತà³à²¦à²¾à²°à²°à³ ಗà³à²‚ಪಿಗಾಗಿ ಜಾಹೀರಾತà³à²—ಳನà³à²¨à³ ಆಯà³à²•à³† ಮಾಡಬಹà³à²¦à³ ಹಾಗೂ ನಿಮà³à²® ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಚಟà³à²µà²Ÿà²¿à²•à³†à²¯à²¨à³à²¨à³ ನಿಮà³à²® ಸಾಧನದಲà³à²²à²¿ ಖಾಸಗಿಯಾಗಿ ಇರಿಸಲಾಗà³à²¤à³à²¤à²¦à³†. ನಿಮà³à²® ಗà³à²‚ಪನà³à²¨à³ ಪà³à²°à²¤à²¿à²¦à²¿à²¨ ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಲಾಗà³à²¤à³à²¤à²¦à³†.}one{ಈ ನಿಯಂತà³à²°à²£à²µà³ ಆನೠಆಗಿದà³à²¦à³ ಹಾಗೂ ಸà³à²¥à²¿à²¤à²¿à²¯à³ ಸಕà³à²°à²¿à²¯à²µà²¾à²—ಿದà³à²¦à²¾à²—, ಯಾವ ಜನರ ದೊಡà³à²¡ ಗà³à²‚ಪೠಅಥವಾ ಜನರ ತಂಡಕà³à²•à³† ನಿಮà³à²® ಇತà³à²¤à³€à²šà²¿à²¨ ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಚಟà³à²µà²Ÿà²¿à²•à³†à²¯à²¨à³à²¨à³ ಹೋಲà³à²¤à³à²¤à²¦à³† ಎಂದೠChrome ನಿರà³à²§à²°à²¿à²¸à³à²¤à³à²¤à²¦à³†. ಜಾಹೀರಾತà³à²¦à²¾à²°à²°à³ ಗà³à²‚ಪಿಗಾಗಿ ಜಾಹೀರಾತà³à²—ಳನà³à²¨à³ ಆಯà³à²•à³† ಮಾಡಬಹà³à²¦à³ ಹಾಗೂ ನಿಮà³à²® ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಚಟà³à²µà²Ÿà²¿à²•à³†à²¯à²¨à³à²¨à³ ನಿಮà³à²® ಸಾಧನದಲà³à²²à²¿ ಖಾಸಗಿಯಾಗಿ ಇರಿಸಲಾಗà³à²¤à³à²¤à²¦à³†. ನಿಮà³à²® ಗà³à²‚ಪನà³à²¨à³ ಪà³à²°à²¤à²¿ {NUM_DAYS} ದಿನಗಳಿಗೆ ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಲಾಗà³à²¤à³à²¤à²¦à³†.}other{ಈ ನಿಯಂತà³à²°à²£à²µà³ ಆನೠಆಗಿದà³à²¦à³ ಹಾಗೂ ಸà³à²¥à²¿à²¤à²¿à²¯à³ ಸಕà³à²°à²¿à²¯à²µà²¾à²—ಿದà³à²¦à²¾à²—, ಯಾವ ಜನರ ದೊಡà³à²¡ ಗà³à²‚ಪೠಅಥವಾ ಜನರ ತಂಡಕà³à²•à³† ನಿಮà³à²® ಇತà³à²¤à³€à²šà²¿à²¨ ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಚಟà³à²µà²Ÿà²¿à²•à³†à²¯à²¨à³à²¨à³ ಹೋಲà³à²¤à³à²¤à²¦à³† ಎಂದೠChrome ನಿರà³à²§à²°à²¿à²¸à³à²¤à³à²¤à²¦à³†. ಜಾಹೀರಾತà³à²¦à²¾à²°à²°à³ ಗà³à²‚ಪಿಗಾಗಿ ಜಾಹೀರಾತà³à²—ಳನà³à²¨à³ ಆಯà³à²•à³† ಮಾಡಬಹà³à²¦à³ ಹಾಗೂ ನಿಮà³à²® ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಚಟà³à²µà²Ÿà²¿à²•à³†à²¯à²¨à³à²¨à³ ನಿಮà³à²® ಸಾಧನದಲà³à²²à²¿ ಖಾಸಗಿಯಾಗಿ ಇರಿಸಲಾಗà³à²¤à³à²¤à²¦à³†. ನಿಮà³à²® ಗà³à²‚ಪನà³à²¨à³ ಪà³à²°à²¤à²¿ {NUM_DAYS} ದಿನಗಳಿಗೆ ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಲಾಗà³à²¤à³à²¤à²¦à³†.}}</translation>
<translation id="2053553514270667976">ಪಿನೠಕೋಡà³</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ಸಲಹೆ}one{# ಸಲಹೆಗಳà³}other{# ಸಲಹೆಗಳà³}}</translation>
<translation id="2071692954027939183">ಅಧಿಸೂಚನೆಗಳನà³à²¨à³ ಸà³à²µà²¯à²‚ಚಾಲಿತವಾಗಿ ನಿರà³à²¬à²‚ಧಿಸಲಾಗಿದೆ à²à²•à³†à²‚ದರೆ ನೀವೠಸಾಮಾನà³à²¯à²µà²¾à²—ಿ ಅವà³à²—ಳನà³à²¨à³ ಅನà³à²®à²¤à²¿à²¸à³à²µà³à²¦à²¿à²²à³à²²</translation>
<translation id="2079545284768500474">ರದà³à²¦à³à²®à²¾à²¡à²¿</translation>
<translation id="20817612488360358">ಸಿಸà³à²Ÿà²‚ ಪà³à²°à²¾à²•à³à²¸à²¿ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳನà³à²¨à³ ಬಳಸಲೠಹೊಂದಿಸಲಾಗಿದೆ ಆದರೆ ಬಹಿರಂಗವಾದ ಪà³à²°à²¾à²•à³à²¸à²¿ ಕಾನà³à²«à²¿à²—ರೇಶನೠಅನà³à²¨à³ ಸಹ ನಿರà³à²¦à²¿à²·à³à²Ÿà²ªà²¡à²¿à²¸à²²à²¾à²—ಿದೆ.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> ರಲà³à²²à²¿ <ph name="RESULT_NUMBER" /> ಫಲಿತಾಂಶಗಳà³</translation>
+<translation id="2085876078937250610">ಉಳಿಸಿ…</translation>
<translation id="2088086323192747268">ಸಿಂಕೠಬಟನೠಅನà³à²¨à³ ನಿರà³à²µà²¹à²¿à²¸à²¿, Chrome ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿ ನೀವೠಯಾವ ಮಾಹಿತಿಯನà³à²¨à³ ಸಿಂಕೠಮಾಡà³à²¤à³à²¤à³€à²°à²¿ ಎಂಬà³à²¦à²¨à³à²¨à³ ನಿರà³à²µà²¹à²¿à²¸à²²à³ Enter ಒತà³à²¤à²¿</translation>
<translation id="2091887806945687916">ಶಬà³à²§</translation>
<translation id="2094505752054353250">ಡೊಮೇನೠಹೊಂದà³à²¤à³à²¤à²¿à²²à³à²²</translation>
@@ -377,6 +386,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> ಗೆ ಬಳಕೆದಾರರಹೆಸರೠಮತà³à²¤à³ ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅಗತà³à²¯à²µà²¿à²¦à³†.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" /> ದಿನಾಂಕದಂದೠಅವಧಿ ಮೀರà³à²¤à³à²¤à²¦à³†</translation>
<translation id="2337852623177822836">ನಿಮà³à²® ನಿರà³à²µà²¾à²¹à²•à²¦à²¿à²‚ದ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳನà³à²¨à³ ನಿಯಂತà³à²°à²¿à²¸à²²à²¾à²—ಿದೆ</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ಜೋಡಿಸಲೠಬಯಸà³à²¤à³à²¤à²¦à³†</translation>
<translation id="2344028582131185878">ಸà³à²µà²¯à²‚ಚಾಲಿತ ಡೌನà³â€Œà²²à³‹à²¡à³â€Œà²—ಳà³</translation>
<translation id="2346319942568447007">ನೀವೠನಕಲಿಸಿದ ಚಿತà³à²°</translation>
<translation id="2354001756790975382">ಇತರ ಬà³à²•à³â€Œà²®à²¾à²°à³à²•à³â€Œà²—ಳà³</translation>
@@ -384,8 +394,10 @@
<translation id="2355395290879513365">ಈ ಸೈಟà³â€Œà²¨à²²à³à²²à²¿ ನೀವೠನೋಡà³à²¤à³à²¤à²¿à²°à³à²µ ಚಿತà³à²°à²—ಳನà³à²¨à³ ವೀಕà³à²·à²¿à²¸à²²à³ ಮತà³à²¤à³ ಅವà³à²—ಳನà³à²¨à³ ಮಾರà³à²ªà²¡à²¿à²¸à³à²µ ಮೂಲಕ ನಿಮà³à²®à²¨à³à²¨à³ ವಂಚಿಸಲೠದಾಳಿಕೋರರಿಗೆ ಸಾಧà³à²¯à²µà²¾à²—à³à²¤à³à²¤à²¿à²°à²¬à²¹à³à²¦à³.</translation>
<translation id="2356070529366658676">ಕೇಳಿ</translation>
<translation id="2357481397660644965">ನಿಮà³à²® ಸಾಧನವನà³à²¨à³ <ph name="DEVICE_MANAGER" /> ಮೂಲಕ ನಿರà³à²µà²¹à²¿à²¸à²²à²¾à²—à³à²¤à³à²¤à²¿à²¦à³† ಮತà³à²¤à³ ನಿಮà³à²® ಖಾತೆಯನà³à²¨à³ <ph name="ACCOUNT_MANAGER" /> ಮೂಲಕ ನಿರà³à²µà²¹à²¿à²¸à²²à²¾à²—à³à²¤à³à²¤à²¿à²¦à³†.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ಒಂದಕà³à²•à²¿à²‚ತ ಕಡಿಮೆ ದಿನದಲà³à²²à²¿}=1{ಒಂದೠದಿನದಲà³à²²à²¿}one{{NUM_DAYS} ದಿನಗಳಲà³à²²à²¿}other{{NUM_DAYS} ದಿನಗಳಲà³à²²à²¿}}</translation>
<translation id="2359629602545592467">ಬಹà³</translation>
<translation id="2359808026110333948">ಮà³à²‚ದà³à²µà²°à³†à²¸à²¿</translation>
+<translation id="2359961752320758691">ನಿಮà³à²® ವರà³à²šà³à²µà²²à³ ಕಾರà³à²¡à³ ಸಂಖà³à²¯à³†à²¯à²¨à³à²¨à³ ಅನà³à²µà²¯à²¿à²¸à²²à²¾à²—ಿದೆ.</translation>
<translation id="2367567093518048410">ಹಂತ</translation>
<translation id="2372464001869762664">ನೀವೠಖಚಿತಪಡಿಸಿದ ನಂತರ, ನಿಮà³à²® Google ಖಾತೆಯಲà³à²²à²¿à²¨ ಕಾರà³à²¡à³ ವಿವರಗಳನà³à²¨à³ ಈ ಸೈಟೠಜೊತೆಗೆ ಹಂಚಿಕೊಳà³à²³à²²à²¾à²—à³à²¤à³à²¤à²¦à³†. ನಿಮà³à²® Plex ಖಾತೆಯ ವಿವರಗಳನà³à²¨à³ CVC ಯಲà³à²²à²¿ ಹà³à²¡à³à²•à²¿.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -396,6 +408,7 @@
<translation id="239429038616798445">ಈ ಶಿಪà³à²ªà²¿à²‚ಗೠವಿಧಾನ ಲಭà³à²¯à²µà²¿à²²à³à²². ಬೇರೊಂದೠವಿಧಾನವನà³à²¨à³ ಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¿.</translation>
<translation id="2396249848217231973">&amp;ಅಳಿಸà³à²µà³à²¦à²¨à³à²¨à³ ರದà³à²¦à³à²—ೊಳಿಸà³</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">ಹಳೆಯ</translation>
<translation id="2413528052993050574">ಈ ಸರà³à²µà²°à³ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬà³à²¦à²¨à³à²¨à³ ಸಾಬೀತà³à²ªà²¡à²¿à²¸à²²à³ ಸಾಧà³à²¯à²µà²¾à²—ಲಿಲà³à²²; ಅದರ ಸà³à²°à²•à³à²·à²¤à²¾ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²°à²µà²¨à³à²¨à³ ಹಿಂತೆಗೆದà³à²•à³Šà²³à³à²³à²²à²¾à²—ಿರಬಹà³à²¦à³. ಇದೠತಪà³à²ªà³ ಕಾನà³à²«à²¿à²—ರೇಶನà³â€Œà²¨à²¿à²‚ದ ಅಥವಾ ಆಕà³à²°à²®à²£à²•à²¾à²°à²°à³ ನಿಮà³à²® ಸಂಪರà³à²•à²¦à²²à³à²²à²¿ ಒಳನà³à²¸à³à²³à²¿à²°à³à²µà³à²¦à²°à²¿à²‚ದ ಆಗಿರಬಹà³à²¦à³.</translation>
<translation id="2414886740292270097">ಗಾಢ</translation>
<translation id="2438874542388153331">ಬಲಭಾಗದಲà³à²²à²¿ ನಾಲà³à²•à³ ತೂತà³à²—ಳನà³à²¨à³ ಮಾಡಿ</translation>
@@ -423,10 +436,10 @@
<translation id="2521385132275182522">ಕೆಳಗಿನ ಬಲಭಾಗದಲà³à²²à²¿ ಸà³à²Ÿà³‡à²ªà²²à³ ಹಾಕಿ</translation>
<translation id="2523886232349826891">ಈ ಸಾಧನದಲà³à²²à²¿ ಮಾತà³à²° ಉಳಿಸಲಾಗಿದೆ</translation>
<translation id="2524461107774643265">ಇನà³à²¨à²·à³à²Ÿà³ ಮಾಹಿತಿಯನà³à²¨à³ ಸೇರಿಸಿ</translation>
-<translation id="2526590354069164005">ಡೆಸà³à²•à³â€Œà²Ÿà²¾à²ªà³</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{ಮತà³à²¤à³ ಇನà³à²¨à³‚ 1}one{ಮತà³à²¤à³ ಇನà³à²¨à³‚ #}other{ಮತà³à²¤à³ ಇನà³à²¨à³‚ #}}</translation>
<translation id="2536110899380797252">ವಿಳಾಸವನà³à²¨à³ ಸೇರಿಸಿ</translation>
<translation id="2539524384386349900">ಪತà³à²¤à³† ಮಾಡà³</translation>
+<translation id="2541219929084442027">ನಿಮà³à²® ಎಲà³à²²à²¾ ಅಪರಿಚಿತ ಟà³à²¯à²¾à²¬à³â€Œà²—ಳನà³à²¨à³ ಮà³à²šà³à²šà²¿à²¦ ಬಳಿಕ ನೀವೠಅಜà³à²žà²¾à²¤ ಮೋಡà³â€Œà²¨à²²à³à²²à²¿ ವೀಕà³à²·à²¿à²¸à²¿à²¦ ಪà³à²Ÿà²—ಳೠಬà³à²°à³Œà²¸à²°à³ ಇತಿಹಾಸದಲà³à²²à²¿, ಕà³à²•à³€ ಸಂಗà³à²°à²¹à²¦à²²à³à²²à²¿ ಅಥವಾ ಹà³à²¡à³à²•à²¾à²Ÿ ಇತಿಹಾಸದಲà³à²²à²¿ ಉಳಿಯà³à²µà³à²¦à²¿à²²à³à²². ನೀವೠಡೌನà³â€Œà²²à³‹à²¡à³ ಮಾಡà³à²µ ಯಾವà³à²¦à³‡ ಫೈಲà³â€Œà²—ಳೠಇಲà³à²²à²µà³‡ ನೀವೠರಚಿಸà³à²µ ಯಾವà³à²¦à³‡ ಬà³à²•à³â€Œà²®à²¾à²°à³à²•à³â€Œà²—ಳನà³à²¨à³ ಹಾಗೆಯೇ ಇರಿಸಲಾಗà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="2544644783021658368">à²à²•à³ˆà²• ಡಾಕà³à²¯à³à²®à³†à²‚ಟà³</translation>
<translation id="254947805923345898">ಕಾರà³à²¯à²¨à³€à²¤à²¿à²¯ ಮೌಲà³à²¯à²µà³ ಮಾನà³à²¯à²µà²¾à²—ಿಲà³à²².</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ಅಮಾನà³à²¯ ಪà³à²°à²¤à²¿à²•à³à²°à²¿à²¯à³† ಕಳà³à²¹à²¿à²¸à²¿à²¦à³†.</translation>
@@ -446,6 +459,7 @@
<translation id="2629325967560697240">Chrome ನ ಉನà³à²¨à²¤ ಮಟà³à²Ÿà²¦ ಸà³à²°à²•à³à²·à²¤à³†à²¯à²¨à³à²¨à³ ಪಡೆಯಲà³, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ವರà³à²§à²¿à²¤ ಸà³à²°à²•à³à²·à²¤à³†à²¯à²¨à³à²¨à³ ಆನೠಮಾಡಿ<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> ನ ಸರà³à²µà²°à³ IP ವಿಳಾಸ ಕಂಡà³à²¬à²°à²²à²¿à²²à³à²².</translation>
<translation id="2639739919103226564">ಸà³à²¥à²¿à²¤à²¿: </translation>
+<translation id="264810637653812429">ಯಾವà³à²¦à³‡ ಹೊಂದಾಣಿಕೆಯಾಗà³à²µ ಸಾಧನಗಳೠಕಂಡà³à²¬à²‚ದಿಲà³à²².</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿ ನಿಮà³à²® ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಇತಿಹಾಸ, ಕà³à²•à³€à²—ಳà³, ಕà³à²¯à²¾à²·à³ ಮತà³à²¤à³ ಇನà³à²¨à²·à³à²Ÿà²¨à³à²¨à³ ತೆರವà³à²—ೊಳಿಸಲೠTab ಒತà³à²¤à²¿, ನಂತರ Enter ಒತà³à²¤à²¿</translation>
<translation id="2650446666397867134">ಫೈಲà³â€Œà²—ೆ ಪà³à²°à²µà³‡à²¶à²µà²¨à³à²¨à³ ನಿರಾಕರಿಸಲಾಗಿದೆ</translation>
@@ -490,6 +504,7 @@
<translation id="2799223571221894425">ಮರà³à²ªà³à²°à²¾à²°à²‚ಭಿಸà³</translation>
<translation id="2803306138276472711">Google ಸà³à²°à²•à³à²·à²¿à²¤ ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಇತà³à²¤à³€à²šà³†à²—ೆ <ph name="SITE" /> ನಲà³à²²à²¿ <ph name="BEGIN_LINK" />ಮಾಲà³â€Œà²µà³‡à²°à³ ಪತà³à²¤à³†à²¹à²šà³à²šà²¿à²¦à³†<ph name="END_LINK" />. ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳೠಸಾಮಾನà³à²¯à²µà²¾à²—ಿ ಸà³à²°à²•à³à²·à²¿à²¤à²µà²¾à²—ಿದà³à²¦à²°à³‚, ಕೆಲವೊಮà³à²®à³† ಮಾಲà³â€Œà²µà³‡à²°à³â€Œà²—ೆ ತà³à²¤à³à²¤à²¾à²—ಿರà³à²¤à³à²¤à²µà³†.</translation>
<translation id="2807052079800581569">ಚಿತà³à²° Y ಸà³à²¥à²¿à²¤à²¿</translation>
+<translation id="2820957248982571256">ಸà³à²•à³à²¯à²¾à²¨à³â€Œ ಮಾಡಲಾಗà³à²¤à³à²¤à²¿à²¦à³†â€¦</translation>
<translation id="2824775600643448204">ವಿಳಾಸ ಹಾಗೂ ಹà³à²¡à³à²•à²¾à²Ÿ ಪಟà³à²Ÿà²¿</translation>
<translation id="2826760142808435982"><ph name="CIPHER" /> ಬಳಸಿಕೊಂಡೠಸಂಪರà³à²•à²µà²¨à³à²¨à³ ಎನà³â€Œà²•à³à²°à²¿à²ªà³à²Ÿà³ ಮಾಡಲಾಗಿದೆ ಮತà³à²¤à³ ದೃಢೀಕರಿಸಲಾಗಿದೆ ಮತà³à²¤à³ <ph name="KX" /> ಅನà³à²¨à³ ಕೀ ವಿನಿಮಯ ಯಾಂತà³à²°à²¿à²•à²¤à³†à²¯à²‚ತೆ ಬಳಸà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="2835170189407361413">ಫಾರà³à²®à³ ತೆರವà³à²—ೊಳಿಸà³</translation>
@@ -497,6 +512,8 @@
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">ಅತಿಕà³à²°à²®à²£à²•à²¾à²°à²¿à²¯à²¾à²—ಿರà³à²µ ಅಥವಾ ತಪà³à²ªà³à²¦à²¾à²°à²¿à²—ೆಳೆಯà³à²µ ಜಾಹೀರಾತà³à²—ಳನà³à²¨à³ ಈ ಸೈಟೠತೋರಿಸà³à²¤à³à²¤à²¦à³†.</translation>
+<translation id="287596039013813457">ಸೌಹಾರà³à²¦</translation>
+<translation id="2876489322757410363">ಬಾಹà³à²¯ ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³â€Œâ€Œ ಮೂಲಕ ಪಾವತಿಸಲೠಅಜà³à²žà²¾à²¤ ಮೋಡà³â€Œâ€Œ ತೊರೆಯಲಾಗà³à²¤à³à²¤à²¿à²¦à³†. ಮà³à²‚ದà³à²µà²°à²¿à²¸à²¬à³‡à²•à³†?</translation>
<translation id="2878197950673342043">ಪೋಸà³à²Ÿà²°à³ ಮಾದರಿಯಲà³à²²à²¿ ಮಡಿಸಿ</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ವಿಂಡೋ ಪà³à²²à³‡à²¸à³â€Œà²®à³†à²‚ಟà³</translation>
@@ -546,7 +563,6 @@
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿ ಸà³à²°à²•à³à²·à²¤à³†à²¯ ಪರಿಶೀಲನೆಯನà³à²¨à³ ರನೠಮಾಡಲೠTab ಒತà³à²¤à²¿, ನಂತರ Enter ಒತà³à²¤à²¿</translation>
<translation id="3061707000357573562">ಪà³à²¯à²¾à²šà³ ಸೇವೆ</translation>
-<translation id="3064966200440839136">ಬಾಹà³à²¯ ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³â€Œâ€Œ ಮೂಲಕರ ಪಾವತಿಸಲೠಅದೃಶà³à²¯ ಮೋಡà³â€Œâ€Œ ತೊರೆಯಲಾಗà³à²¤à³à²¤à²¿à²¦à³†. ಮà³à²‚ದà³à²µà²°à²¿à²¸à³à²µà³à²¦à³‡?</translation>
<translation id="306573536155379004">ಗೇಮೠಪà³à²°à²¾à²°à²‚ಭವಾಗಿದೆ.</translation>
<translation id="3080254622891793721">ಗà³à²°à²¾à²«à²¿à²•à³</translation>
<translation id="3086579638707268289">ವೆಬà³â€Œà²¨à²²à³à²²à²¿à²¨ ನಿಮà³à²® ಚಟà³à²µà²Ÿà²¿à²•à³†à²¯à²¨à³à²¨à³ ಮೇಲà³à²µà²¿à²šà²¾à²°à²£à³† ಮಾಡಲಾಗà³à²¤à³à²¤à²¿à²¦à³†</translation>
@@ -569,7 +585,6 @@
<translation id="315504272643575312">ನಿಮà³à²® ಖಾತೆಯನà³à²¨à³ <ph name="MANAGER" /> ನಿರà³à²µà²¹à²¿à²¸à³à²¤à³à²¤à²¿à²¦à³†.</translation>
<translation id="3157931365184549694">ಮರà³à²¸à³à²¥à²¾à²ªà²¨à³†</translation>
<translation id="3162559335345991374">ನೀವೠಬಳಸà³à²¤à³à²¤à²¿à²°à³à²µ ವೈ-ಫೈನ ಲಾಗಿನೠಪà³à²Ÿà²•à³à²•à³† ನೀವೠಭೇಟಿ ನೀಡà³à²µ ಅಗತà³à²¯à²µà²¿à²¦à³†.</translation>
-<translation id="3167968892399408617">ನಿಮà³à²® ಎಲà³à²²à²¾ ಅಪರಿಚಿತ ಟà³à²¯à²¾à²¬à³â€Œà²—ಳನà³à²¨à³ ಮà³à²šà³à²šà²¿à²¦ ಬಳಿಕ ನೀವೠಅಜà³à²žà²¾à²¤ ಮೋಡà³â€Œà²¨à²²à³à²²à²¿ ವೀಕà³à²·à²¿à²¸à²¿à²¦ ಪà³à²Ÿà²—ಳೠಬà³à²°à³Œà²¸à²°à³ ಇತಿಹಾಸದಲà³à²²à²¿, ಕà³à²•à³€ ಸಂಗà³à²°à²¹à²¦à²²à³à²²à²¿ ಅಥವಾ ಹà³à²¡à³à²•à²¾à²Ÿ ಇತಿಹಾಸದಲà³à²²à²¿ ಉಳಿಯà³à²µà³à²¦à²¿à²²à³à²². ನೀವೠಡೌನà³â€Œà²²à³‹à²¡à³ ಮಾಡà³à²µ ಯಾವà³à²¦à³‡ ಫೈಲà³â€Œà²—ಳೠಇಲà³à²²à²µà³‡ ನೀವೠರಚಿಸà³à²µ ಯಾವà³à²¦à³‡ ಬà³à²•à³â€Œà²®à²¾à²°à³à²•à³â€Œà²—ಳನà³à²¨à³ ಹಾಗೆಯೇ ಇರಿಸಲಾಗà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">ದà³à²µà³€à²ª</translation>
<translation id="3176929007561373547">ಪà³à²°à²¾à²•à³à²¸à²¿ ಸರà³à²µà²°à³ ಕಾರà³à²¯à²µà²¨à²¿à²°à³à²µà²¹à²¿à²¸à³à²¤à³à²¤à²¿à²¦à³†à²¯à³‡ ಎಂಬà³à²¦à²¨à³à²¨à³ ಖಚಿತಪಡಿಸಿಕೊಳà³à²³à²²à³ ನಿಮà³à²® ಪà³à²°à²¾à²•à³à²¸à²¿ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳನà³à²¨à³ ಪರಿಶೀಲಿಸಿ ಮತà³à²¤à³ ನಿಮà³à²® ನೆಟà³â€Œà²µà²°à³à²•à³ ನಿರà³à²µà²¾à²¹à²•à²°à²¨à³à²¨à³ ಸಂಪರà³à²•à²¿à²¸à²¿. ನೀವೠಪà³à²°à²¾à²•à³à²¸à²¿ ಸರà³à²µà²°à³ ಅನà³à²¨à³ ಬಳಸà³à²¤à³à²¤à²¿à²²à³à²² ಎಂಬ ಅನà³à²®à²¾à²¨ ನಿಮಗಿದà³à²¦à²°à³†:
@@ -593,10 +608,12 @@
<translation id="3229041911291329567">ನಿಮà³à²® ಸಾಧನ ಮತà³à²¤à³ ಬà³à²°à³Œà²¸à²°à³ ಕà³à²°à²¿à²¤à³ ಆವೃತà³à²¤à²¿à²¯ ಮಾಹಿತಿ</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> ಗೆ CVC ಅನà³à²¨à³ ನಮೂದಿಸಿ</translation>
<translation id="3234666976984236645">ಈ ಸೈಟà³â€Œà²¨à²²à³à²²à²¿ ಯಾವಾಗೂ ಮà³à²–à³à²¯ ವಿಷಯವನà³à²¨à³ ಹà³à²¡à³à²•à²¿</translation>
+<translation id="3249845759089040423">ಗà³à²°à³‚ವಿ</translation>
<translation id="3252266817569339921">ಫà³à²°à³†à²‚ಚà³</translation>
<translation id="3266793032086590337">ಮೌಲà³à²¯ (ಸಂಘರà³à²· ಇರà³à²µà³à²¦à³)</translation>
<translation id="3268451620468152448">ತೆರೆದ ಟà³à²¯à²¾à²¬à³â€Œà²—ಳà³</translation>
<translation id="3270847123878663523">&amp;ಮರà³à²•à³à²°à²®à²—ೊಳಿಸà³à²µà³à²¦à²¨à³à²¨à³ ರದà³à²¦à³à²—ೊಳಿಸà³</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> ಸಂಪರà³à²•à²¿à²¸à²²à³ ಬಯಸà³à²¤à³à²¤à²¦à³†</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">ನಿಮà³à²® ಸಂಸà³à²¥à³† <ph name="ENROLLMENT_DOMAIN" />, ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳೠಅಥವಾ ಕಾರà³à²¯à²¨à³€à²¤à²¿à²—ಳಂತಹ ಕೆಲವೠಮಾಹಿತಿಯನà³à²¨à³ ಈ ಕೆಳಗಿನ ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳಿಗೆ ಕಳà³à²¹à²¿à²¸à²¿à²¦à³†.</translation>
<translation id="3282497668470633863">ಕಾರà³à²¡à³â€Œà²¨à²²à³à²²à²¿à²°à³à²µ ಹೆಸರನà³à²¨à³ ಸೇರಿಸಿ</translation>
@@ -649,6 +666,7 @@
<translation id="3428151540071562330">ಒಂದೠಅಥವಾ ಹೆಚà³à²šà²¿à²¨ DnsOverHttpsTemplates ಸರà³à²µà²°à³ ಟೆಂಪà³à²²à³‡à²Ÿà³ URI ಗಳೠಅಮಾನà³à²¯à²µà²¾à²—ಿವೆ ಮತà³à²¤à³ ಅವà³à²—ಳನà³à²¨à³ ಬಳಸಲಾಗà³à²µà³à²¦à²¿à²²à³à²².</translation>
<translation id="3431636764301398940">ಈ ಸಾಧನಕà³à²•à³† ಈ ಕಾರà³à²¡à³ ಉಳಿಸಿ</translation>
<translation id="3432601291244612633">ಪà³à²Ÿà²µà²¨à³à²¨à³ ಮà³à²šà³à²šà²¿à²°à²¿</translation>
+<translation id="3435738964857648380">ಭದà³à²°à²¤à³†</translation>
<translation id="3435896845095436175">ಸಕà³à²°à²¿à²¯à²—ೊಳಿಸà³</translation>
<translation id="3438829137925142401">ನಿಮà³à²® Google ಖಾತೆಯಲà³à²²à²¿ ಉಳಿಸಲಾಗಿರà³à²µ ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ಬಳಸಿ</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -691,7 +709,10 @@
<translation id="3584299510153766161">ಕೆಳಭಾಗದಲà³à²²à²¿ ಎರಡೠತೂತà³à²—ಳನà³à²¨à³ ಮಾಡಿ</translation>
<translation id="3586931643579894722">ವಿವರಗಳನà³à²¨à³ ಮರೆಮಾಡಿ</translation>
<translation id="3587738293690942763">ಮಧà³à²¯à²®</translation>
+<translation id="3590643883886679995">ನೀವೠಅಜà³à²žà²¾à²¤ ಮೋಡà³â€Œà²¨à²¿à²‚ದ ನಿರà³à²—ಮಿಸಿದ ಬಳಿಕ, ಸೈನೠಇನೠಡೇಟಾವನà³à²¨à³ ಈ ಸಾಧನದಲà³à²²à²¿ ಸಂಗà³à²°à²¹à²¿à²¸à²²à²¾à²—à³à²¤à³à²¤à²¦à³†.</translation>
+<translation id="359126217934908072">ತಿಂಗಳà³/ವರà³à²·:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{ನೀವೠಯಾವಾಗ ಬೇಕಾದರೂ ನಿಮà³à²® ಗà³à²‚ಪನà³à²¨à³ ರೀಸೆಟೠಮಾಡಬಹà³à²¦à³. ಹೊಸ ಗà³à²‚ಪಿಗೆ ಸೇರà³à²ªà²¡à³†à²—ೊಳà³à²³à²²à³ ಒಂದೠದಿನದ ಸಮಯವನà³à²¨à³ ತೆಗೆದà³à²•à³Šà²³à³à²³à³à²¤à³à²¤à²¦à³†.}=1{ನೀವೠಯಾವಾಗ ಬೇಕಾದರೂ ನಿಮà³à²® ಗà³à²‚ಪನà³à²¨à³ ರೀಸೆಟೠಮಾಡಬಹà³à²¦à³. ಹೊಸ ಗà³à²‚ಪಿಗೆ ಸೇರà³à²ªà²¡à³†à²—ೊಳà³à²³à²²à³ ಒಂದೠದಿನದ ಸಮಯವನà³à²¨à³ ತೆಗೆದà³à²•à³Šà²³à³à²³à³à²¤à³à²¤à²¦à³†.}one{ನೀವೠಯಾವಾಗ ಬೇಕಾದರೂ ನಿಮà³à²® ಗà³à²‚ಪನà³à²¨à³ ರೀಸೆಟೠಮಾಡಬಹà³à²¦à³. ಹೊಸ ಗà³à²‚ಪಿಗೆ ಸೇರà³à²ªà²¡à³†à²—ೊಳà³à²³à²²à³ {NUM_DAYS} ದಿನಗಳ ಸಮಯವನà³à²¨à³ ತೆಗೆದà³à²•à³Šà²³à³à²³à³à²¤à³à²¤à²¦à³†.}other{ನೀವೠಯಾವಾಗ ಬೇಕಾದರೂ ನಿಮà³à²® ಗà³à²‚ಪನà³à²¨à³ ರೀಸೆಟೠಮಾಡಬಹà³à²¦à³. ಹೊಸ ಗà³à²‚ಪಿಗೆ ಸೇರà³à²ªà²¡à³†à²—ೊಳà³à²³à²²à³ {NUM_DAYS} ದಿನಗಳ ಸಮಯವನà³à²¨à³ ತೆಗೆದà³à²•à³Šà²³à³à²³à³à²¤à³à²¤à²¦à³†.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">ನಿಮà³à²® ನಿರà³à²µà²¾à²¹à²•à²°à³ ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³ ಅನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಿದà³à²¦à²¾à²°à³†</translation>
<translation id="3608932978122581043">ಫೀಡೠಓರಿಯಂಟೇಶನà³</translation>
@@ -700,12 +721,12 @@
<translation id="3615877443314183785">ಮಾನà³à²¯à²µà²¾à²¦ ಅವಧಿ-ಮà³à²•à³à²¤à²¾à²¯ ದಿನಾಂಕವನà³à²¨à³ ನಮೂದಿಸಿ</translation>
<translation id="36224234498066874">ಬà³à²°à³Œà²¸à³ ಆಗà³à²¤à³à²¤à²¿à²°à³à²µ ಡೇಟಾವನà³à²¨à³ ತೆರವà³à²—ೊಳಿಸಿ...</translation>
<translation id="362276910939193118">ಪೂರà³à²£ ಇತಿಹಾಸ ತೋರಿಸಿ</translation>
-<translation id="3625635938337243871">ನೀವೠಅಜà³à²žà²¾à²¤ ಮೋಡà³â€Œà²¨à²¿à²‚ದ ನಿರà³à²—ಮಿಸಿದ ಬಳಿಕ, ಸೈನೠಇನೠಡೇಟಾವನà³à²¨à³ ಈ ಸಾಧನದಲà³à²²à²¿ ಸಂಗà³à²°à²¹à²¿à²¸à²²à²¾à²—à³à²¤à³à²¤à²¦à³†.</translation>
<translation id="3630155396527302611">ಒಂದೠವೇಳೆ ನೆಟà³â€Œà²µà²°à³à²•à³ ಪà³à²°à²µà³‡à²¶à²¿à²¸à²²à³ ಅನà³à²®à²¤à²¿à²¸à³à²µ ಒಂದೠಪà³à²°à³Šà²—à³à²°à²¾à²‚ನಂತೆ ಇದನà³à²¨à³ ಈಗಾಗಲೇ ಪಟà³à²Ÿà²¿ ಮಾಡಲಾಗಿದà³à²¦à²°à³†, ಅದನà³à²¨à³ ಪಟà³à²Ÿà²¿à²¯à²¿à²‚ದ ತೆಗೆಯಲೠಮತà³à²¤à³ ಪà³à²¨à²ƒ ಅದನà³à²¨à³ ಸೇರಿಸಲೠಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¿.</translation>
<translation id="3630699740441428070">ಈ ಸಾಧನದ ನಿರà³à²µà²¾à²¹à²•à²°à³ ನಿಮà³à²® ನೆಟà³â€Œà²µà²°à³à²•à³ ಕನೆಕà³à²·à²¨à³ ಅನà³à²¨à³ ಕಾನà³à²«à²¿à²—ರೠಮಾಡಿದà³à²¦à²¾à²°à³†, ಅದೠನೀವೠಭೇಟಿ ನೀಡà³à²µ ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳೂ ಸೇರಿದಂತೆ ನಿಮà³à²® ನೆಟà³â€Œà²µà²°à³à²•à³ ಟà³à²°à²¾à²«à²¿à²•à³ ಅನà³à²¨à³ ನೋಡಲೠಅನà³à²®à²¤à²¿à²¸à³à²¤à³à²¤à²¦à³†.</translation>
<translation id="3631244953324577188">ಬಯೋಮೆಟà³à²°à²¿à²•à³à²¸à³</translation>
<translation id="3633738897356909127">Chrome ಬಟನೠಅಪà³â€Œà²¡à³‡à²Ÿà³â€Œ ಮಾಡಿ, ನಿಮà³à²® Chrome ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಿಂದ Chrome ಅನà³à²¨à³ ಅಪà³â€Œà²¡à³‡à²Ÿà³â€Œ ಮಾಡಲೠEnter ಒತà³à²¤à²¿à²°à²¿</translation>
<translation id="3634530185120165534">ಟà³à²°à³‡ 5</translation>
+<translation id="3637662659967048211">Google ಖಾತೆಗೆ ಉಳಿಸಿ</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³:</translation>
<translation id="3650584904733503804">ಊರà³à²œà²¿à²¤à²—ೊಳಿಸà³à²µà²¿à²•à³†à²¯à³ ಯಶಸà³à²µà²¿à²¯à²¾à²—ಿದೆ</translation>
@@ -746,6 +767,7 @@
<translation id="3781428340399460090">ಗಾಢ ಗà³à²²à²¾à²¬à²¿</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">ಬà³à²²à³‚ಟೂತà³â€Œâ€Œ ಸಾಧನಗಳà³</translation>
+<translation id="3787675388804467730">ವರà³à²šà³à²µà²²à³ ಕಾರà³à²¡à³ ಸಂಖà³à²¯à³†</translation>
<translation id="3787705759683870569">ಅವಧಿ-ಮà³à²•à³à²¤à²¾à²¯ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">ಗಾತà³à²° 16</translation>
<translation id="3789841737615482174">ಇನà³â€Œà²¸à³à²Ÿà²¾à²²à³</translation>
@@ -765,6 +787,7 @@
<translation id="3841184659773414994">ಫೈಲೠಹà³à²¯à²¾à²‚ಡà³â€Œà²²à²°à³â€Œà²—ಳà³</translation>
<translation id="385051799172605136">ಹಿಂದೆ</translation>
<translation id="3858027520442213535">ದಿನಾಂಕ ಮತà³à²¤à³ ಸಮಯವನà³à²¨à³ ಅಪà³â€Œà²¡à³‡à²Ÿà³â€Œ ಮಾಡಿ</translation>
+<translation id="3881478300875776315">ಕೆಲವೇ ಸಾಲà³à²—ಳನà³à²¨à³ ತೋರಿಸಿ</translation>
<translation id="3884278016824448484">ಸಂಘರà³à²·à²—ೊಳà³à²³à³à²¤à³à²¤à²¿à²°à³à²µ ಸಾಧನ ಗà³à²°à³à²¤à²¿à²¸à³à²µà²¿à²•à³†</translation>
<translation id="3885155851504623709">ಪಾರಿಷà³</translation>
<translation id="388632593194507180">ನಿಗಾ ಇಡà³à²¤à³à²¤à²¿à²°à³à²µà³à²¦à²¨à³à²¨à³ ಪತà³à²¤à³†à²¹à²šà³à²šà²²à²¾à²—ಿದೆ</translation>
@@ -790,6 +813,7 @@
<translation id="397105322502079400">ಎಣಿಸಲಾಗà³à²¤à³à²¤à²¿à²¦à³†...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ಅನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಲಾಗಿದೆ</translation>
<translation id="3973357910713125165">Chrome ಸà³à²°à²•à³à²·à²¤à³†à²¯ ಪರಿಶೀಲನೆ ಬಟನೠರನೠಮಾಡಿ, Chrome ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿ ಸà³à²°à²•à³à²·à²¤à³†à²¯ ಪರಿಶೀಲನೆಯನà³à²¨à³ ರನೠಮಾಡಲೠEnter ಅನà³à²¨à³ ಒತà³à²¤à²¿à²°à²¿</translation>
+<translation id="3986705137476756801">ಈಗ ಲೈವೠಕà³à²¯à²¾à²ªà³à²¶à²¨à³ ಅನà³à²¨à³ ಆಫೠಮಾಡಿ</translation>
<translation id="3987405730340719549">ಇದೠನಕಲಿ ಅಥವಾ ವಂಚನೆಯ ಸೈಟೠಆಗಿರಬಹà³à²¦à³ ಎಂಬà³à²¦à²¨à³à²¨à³ Chrome ಪತà³à²¤à³†à²¹à²šà³à²šà²¿à²¦à³†.
ಇದನà³à²¨à³ ದೋಷದಿಂದಾಗಿ ತೋರಿಸಲಾಗಿದೆ ಎಂದೠನೀವೠಭಾವಿಸà³à²µà³à²¦à²¾à²¦à²°à³†, ದಯವಿಟà³à²Ÿà³ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals ಪà³à²Ÿà²•à³à²•à³† ಭೇಟಿ ನೀಡಿ.</translation>
@@ -881,13 +905,14 @@
<translation id="4275830172053184480">ನಿಮà³à²® ಸಾಧನವನà³à²¨à³ ಮರà³à²ªà³à²°à²¾à²°à²‚ಭಿಸಿ</translation>
<translation id="4277028893293644418">ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಮರà³à²¹à³Šà²‚ದಿಸಿ</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ಈ ಕಾರà³à²¡à³ ಅನà³à²¨à³ ನಿಮà³à²® Google ಖಾತೆಯಲà³à²²à²¿ ಉಳಿಸಲಾಗಿದೆ}one{ಈ ಕಾರà³à²¡à³â€Œà²—ಳನà³à²¨à³ ನಿಮà³à²® Google ಖಾತೆಯಲà³à²²à²¿ ಉಳಿಸಲಾಗಿದೆ}other{ಈ ಕಾರà³à²¡à³â€Œà²—ಳನà³à²¨à³ ನಿಮà³à²® Google ಖಾತೆಯಲà³à²²à²¿ ಉಳಿಸಲಾಗಿದೆ}}</translation>
+<translation id="4287885627794386150">ಪà³à²°à²¯à³‹à²—ಕà³à²•à³† ಅರà³à²¹à²µà²¾à²—ಿದೆ ಆದರೆ ಸಕà³à²°à²¿à²¯à²µà²¾à²—ಿರà³à²µà³à²¦à²¿à²²à³à²²</translation>
<translation id="4297502707443874121">ಪà³à²Ÿ <ph name="THUMBNAIL_PAGE" /> ರ ಥಂಬà³â€Œà²¨à³‡à²²à³</translation>
<translation id="42981349822642051">ವಿಸà³à²¤à²°à²¿à²¸à²¿</translation>
<translation id="4300675098767811073">ಬಲಭಾಗದಲà³à²²à²¿ ಅನೇಕ ತೂತà³à²—ಳನà³à²¨à³ ಮಾಡಿ</translation>
<translation id="4302514097724775343">ಆಡಲà³, ಡೈನೋ ಅನà³à²¨à³ ಟà³à²¯à²¾à²ªà³ ಮಾಡಿ</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">ನಿಮà³à²® ಫೈಲೠಅನà³à²¨à³ ಪà³à²°à²µà³‡à²¶à²¿à²¸à²²à³ ಸಾಧà³à²¯à²µà²¾à²—ಲಿಲà³à²²</translation>
-<translation id="4305817255990598646">ಬದಲಿಸಿ</translation>
+<translation id="4306529830550717874">ವಿಳಾಸವನà³à²¨à³ ಉಳಿಸಬೇಕೆ?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">ನಿರà³à²¬à²‚ಧಿಸೠ(ಡಿಫಾಲà³à²Ÿà³)</translation>
<translation id="4314815835985389558">ಸಿಂಕೠಅನà³à²¨à³ ನಿರà³à²µà²¹à²¿à²¸à²¿</translation>
@@ -914,6 +939,7 @@
<translation id="4377125064752653719">ನೀವೠ<ph name="DOMAIN" /> ಅನà³à²¨à³ ತಲà³à²ªà²²à³ ಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¿à²¦à²¿à²°à²¿, ಆದರೆ ಸರà³à²µà²°à³ ನೀಡಿದ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²°à²µà²¨à³à²¨à³ ಅದರ ನೀಡà³à²µà²µà²°à³ ಹಿಂತೆಗೆದà³à²•à³Šà²‚ಡಿದà³à²¦à²¾à²°à³†. ಇದರರà³à²¥ ಸರà³à²µà²°à³ ನೀಡಿದ ಸà³à²°à²•à³à²·à²¤à³† ರà³à²œà³à²µà²¾à²¤à³à²—ಳನà³à²¨à³ ಖಂಡಿತವಾಗಿ ನಂಬಲಾಗà³à²µà³à²¦à²¿à²²à³à²². ನೀವೠಆಕà³à²°à²®à²£à²•à²¾à²°à²°à³Šà²‚ದಿಗೆ ಸಂವಹಿಸà³à²¤à³à²¤à²¿à²°à²¬à²¹à³à²¦à³.</translation>
<translation id="4378154925671717803">ಫೋನà³</translation>
<translation id="4390472908992056574">ಅಂಚà³</translation>
+<translation id="4406883609789734330">ಲೈವೠಕà³à²¯à²¾à²ªà³à²¶à²¨à³</translation>
<translation id="4406896451731180161">ಹà³à²¡à³à²•à²¾à²Ÿà²¦ ಫಲಿತಾಂಶಗಳà³</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> ಕà³à²•à³€à²—ಳà³</translation>
<translation id="4414290883293381923">ವಂಚನೆ ಮಾಡà³à²µ ಸೈಟà³â€Œ ಒಂದರಲà³à²²à²¿, ನಿಮà³à²® ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅನà³à²¨à³ ಈಗಷà³à²Ÿà³‡ ನೀವೠನಮೂದಿಸಿದà³à²¦à³€à²°à²¿. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ಹಾಗೂ ಈ ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅನà³à²¨à³ ನೀವೠಯಾವ ಇತರ ಸೈಟà³â€Œà²—ಳಲà³à²²à²¿ ಬಳಸà³à²µà²¿à²°à³‹ ಅಲà³à²²à²¿ ಈಗಲೇ ಅದನà³à²¨à³ ಬದಲಾಯಿಸಬೇಕೆಂದೠChrome ನಿಮಗೆ ಶಿಫಾರಸೠಮಾಡà³à²¤à³à²¤à²¦à³†.</translation>
@@ -926,7 +952,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">ಪà³à²°à²¾à²•à³à²¸à²¿à²¯ ಬಳಕೆಯನà³à²¨à³ ನಿಷà³à²•à³à²°à²¿à²¯à²—ೊಳಿಸಲಾಗಿದೆ ಆದರೆ ಬಹಿರಂಗ ಪà³à²°à²¾à²•à³à²¸à²¿ ಕಾನà³à²«à²¿à²—ರೇಶನೠಅನà³à²¨à³ ನಿರà³à²¦à²¿à²·à³à²Ÿà²ªà²¡à²¿à²¸à²²à²¾à²—ಿದೆ.</translation>
<translation id="4464826014807964867">ನಿಮà³à²® ಸಂಸà³à²¥à³†à²¯à²¿à²‚ದ ಮಾಹಿತಿಯನà³à²¨à³ ಹೊಂದಿರà³à²µ ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳà³</translation>
-<translation id="4466881336512663640">ಫಾರà³à²®à³â€Œà²¨à²²à³à²²à²¿ ಮಾಡಿರà³à²µ ಬದಲಾವಣೆಗಳೠಕಳೆದೠಹೋಗà³à²¤à³à²¤à²µà³†. ನೀವೠಖಂಡಿತವಾಗಿಯೂ ಮà³à²‚ದà³à²µà²°à²¿à²¯à²²à³ ಬಯಸà³à²¤à³à²¤à³€à²°à²¾?</translation>
<translation id="4476953670630786061">ಈ ಫಾರà³à²®à³ ಸà³à²°à²•à³à²·à²¿à²¤à²µà²¾à²—ಿಲà³à²². ಸà³à²µà²¯à²‚ ಭರà³à²¤à²¿à²¯à²¨à³à²¨à³ ಆಫೠಮಾಡಲಾಗಿದೆ.</translation>
<translation id="4477350412780666475">ಮà³à²‚ದಿನ ಟà³à²°à³à²¯à²¾à²•à³</translation>
<translation id="4482953324121162758">ಈ ಸೈಟೠಅನà³à²µà²¾à²¦à²•à³à²•à³† ಒಳಪಡà³à²µà³à²¦à²¿à²²à³à²².</translation>
@@ -960,6 +985,7 @@
<translation id="4594403342090139922">&amp;ಅಳಿಸà³à²µà³à²¦à²¨à³à²¨à³ ರದà³à²¦à³à²—ೊಳಿಸಿ</translation>
<translation id="4597348597567598915">ಗಾತà³à²° 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">ಪರಿಣಾಮಕಾರಿ</translation>
<translation id="4628948037717959914">ಫೋಟೋ</translation>
<translation id="4631649115723685955">ಕà³à²¯à²¾à²¶à³â€Œà²¬à³à²¯à²¾à²•à³ ಲಿಂಕೠಮಾಡಲಾಗಿದೆ</translation>
<translation id="4636930964841734540">ಮಾಹಿತಿ</translation>
@@ -979,6 +1005,7 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">ಅಂಚà³</translation>
+<translation id="4702656508969495934">ಲೈವೠಕà³à²¯à²¾à²ªà³à²¶à²¨à³ ಗೋಚರಿಸà³à²¤à³à²¤à²¿à²¦à³†, ಫೋಕಸೠಮಾಡಲೠವಿಂಡೋ ಬದಲಾಯಿಸà³à²µà²¿à²•à³†à²¯à²¨à³à²¨à³ ಬಳಸಿ</translation>
<translation id="4708268264240856090">ನಿಮà³à²® ಸಂಪರà³à²•à²•à³à²•à³† ಅಡà³à²¡à²¿à²¯à²¾à²—ಿದೆ</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows ನೆಟà³â€Œà²µà²°à³à²•à³ ಡಯಾಗà³à²¨à²¾à²¸à³à²Ÿà²¿à²•à³à²¸à³ ರನೠಮಾಡಲಾಗà³à²¤à³à²¤à²¿à²¦à³†<ph name="END_LINK" /></translation>
@@ -992,6 +1019,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> ಹà³à²¡à³à²•à²¾à²Ÿ ಸಲಹೆ</translation>
<translation id="4742407542027196863">ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ನಿರà³à²µà²¹à²¿à²¸à²¿â€¦</translation>
<translation id="4744603770635761495">ಪà³à²°à²¦à²°à³à²¶à²¨à²—ೊಳà³à²³à³à²µà²‚ತಹ ಹಾದಿ</translation>
+<translation id="4749011317274908093">ನೀವೠಅಜà³à²žà²¾à²¤ ಮೋಡà³â€Œà²¨à²²à³à²²à²¿à²°à³à²µà²¿à²°à²¿</translation>
<translation id="4750917950439032686">ಈ ಸೈಟà³â€Œà²—ೆ ನಿಮà³à²® ಮಾಹಿತಿಯನà³à²¨à³ ಕಳà³à²¹à²¿à²¸à²¿à²¦à²¾à²— ಅದೠ(ಉದಾಹರಣೆಗೆ, ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳೠಅಥವಾ ಕà³à²°à³†à²¡à²¿à²Ÿà³ ಕಾರà³à²¡à³ ಸಂಖà³à²¯à³†à²—ಳà³) ಖಾಸಗಿಯಾಗಿರà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="4756388243121344051">&amp;ಇತಿಹಾಸ</translation>
<translation id="4758311279753947758">ಸಂಪರà³à²• ಮಾಹಿತಿಯನà³à²¨à³ ಸೇರಿಸಿ</translation>
@@ -1021,6 +1049,8 @@
<translation id="4813512666221746211">ನೆಟà³â€Œà²µà²°à³à²•à³ ದೋಷ</translation>
<translation id="4816492930507672669">ಪà³à²Ÿà²•à³à²•à³† ಹೊಂದಿಸà³</translation>
<translation id="4819347708020428563">ಡೀಫಾಲà³à²Ÿà³ ವೀಕà³à²·à²£à³†à²¯à²²à³à²²à²¿ ಟಿಪà³à²ªà²£à²¿à²—ಳನà³à²¨à³ ಎಡಿಟೠಮಾಡಬೇಕೆ?</translation>
+<translation id="4825507807291741242">ಪà³à²°à²¬à²²</translation>
+<translation id="4838327282952368871">ಕನಸà³</translation>
<translation id="484462545196658690">ಆಟೋ</translation>
<translation id="4850886885716139402">ವೀಕà³à²·à²£à³†</translation>
<translation id="485316830061041779">ಜರà³à²®à²¨à³</translation>
@@ -1157,6 +1187,7 @@
<translation id="5314967030527622926">ಬà³à²•à³â€Œà²²à³†à²Ÿà³ ಮೇಕರà³</translation>
<translation id="5316812925700871227">ಅಪà³à²°à²¦à²•à³à²·à²¿à²£à²µà²¾à²—ಿ ತಿರà³à²—ಿಸà³</translation>
<translation id="5317780077021120954">ಉಳಿಸà³</translation>
+<translation id="5321288445143113935">ಗರಿಷà³à² à²—ೊಳಿಸಲಾಗಿದೆ</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> ಗಳ <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">ಸಂಪರà³à²• ಮಾಹಿತಿ ಆಯà³à²•à³†à²®à²¾à²¡à²¿</translation>
<translation id="5327248766486351172">ಹೆಸರà³</translation>
@@ -1164,11 +1195,13 @@
<translation id="5332219387342487447">ಶಿಪà³à²ªà²¿à²‚ಗೠವಿಧಾನ</translation>
<translation id="5333022057423422993">ಡೇಟಾ ಉಲà³à²²à²‚ಘನೆಯಲà³à²²à²¿ ನೀವೠಬಳಸಿದ ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅನà³à²¨à³ Chrome ಪತà³à²¤à³†à²¹à²šà³à²šà²¿à²¦à³†. ನಿಮà³à²® ಖಾತೆಗಳನà³à²¨à³ ಸà³à²°à²•à³à²·à²¿à²¤à²µà²¾à²—ಿರಿಸಲà³, ನೀವೠಉಳಿಸಿದ ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ಪರಿಶೀಲಿಸಲೠನಾವೠಶಿಫಾರಸೠಮಾಡà³à²¤à³à²¤à³‡à²µà³†.</translation>
<translation id="5334013548165032829">ವಿವರವಾದ ಸಿಸà³à²Ÿà²‚ ಲಾಗà³â€Œà²—ಳà³</translation>
+<translation id="5334145288572353250">ವಿಳಾಸವನà³à²¨à³ ಉಳಿಸಬೇಕೆ?</translation>
<translation id="5340250774223869109">ಅಪà³à²²à²¿à²•à³‡à²¶à²¨à³ ಅನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಲಾಗಿದೆ</translation>
<translation id="534295439873310000">NFC ಸಾಧನಗಳà³</translation>
<translation id="5344579389779391559">ಈ ಪà³à²Ÿà²µà³ ನಿಮಗೆ ಶà³à²²à³à²• ವಿಧಿಸಲೠಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¬à²¹à³à²¦à³</translation>
<translation id="5355557959165512791">ಸದà³à²¯à²•à³à²•à³† ನೀವೠ<ph name="SITE" /> ಗೆ ಭೇಟಿ ನೀಡಲೠಸಾಧà³à²¯à²µà²¿à²²à³à²². à²à²•à³†à²‚ದರೆ ಇದರ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²°à²µà²¨à³à²¨à³ ಹಿಂಪಡೆದà³à²•à³Šà²³à³à²³à²²à²¾à²—ಿದೆ. ನೆಟà³â€Œà²µà²°à³à²•à³ ದೋಷಗಳೠಮತà³à²¤à³ ಆಕà³à²°à²®à²£à²—ಳೠತಾತà³à²•à²¾à²²à²¿à²•à²µà²¾à²—ಿರà³à²¤à³à²¤à²µà³†, ಹೀಗಾಗಿ ಈ ಪà³à²Ÿà²µà³ ಸà³à²µà²²à³à²ª ಸಮಯದ ನಂತರ ಕಾರà³à²¯à²¨à²¿à²°à³à²µà²¹à²¿à²¸à²¬à²¹à³à²¦à³.</translation>
<translation id="536296301121032821">ನೀತಿಯ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳನà³à²¨à³ ಸಂಗà³à²°à²¹à²¿à²¸à³à²µà²²à³à²²à²¿ ವಿಫಲವಾಗಿದೆ</translation>
+<translation id="5363309033720083897">ನಿಮà³à²® ನಿರà³à²µà²¾à²¹à²•à²°à³ ಸೀರಿಯಲೠಪೋರà³à²Ÿà³ ಅನà³à²¨à³ ಅನà³à²®à²¤à²¿à²¸à²¿à²¦à³à²¦à²¾à²°à³†</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="5386426401304769735">ಈ ಸೈಟà³â€Œà²—ೆ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²° ಸರಣಿಯೠSHA-1 ಬಳಸಿಕೊಂಡೠಸಹಿ ಮಾಡಲಾದ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²°à²µà²¨à³à²¨à³ ಒಳಗೊಂಡಿರà³à²¤à³à²¤à²¦à³†.</translation>
@@ -1177,6 +1210,7 @@
<translation id="5398772614898833570">ಜಾಹೀರಾತà³à²—ಳನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಲಾಗಿದೆ</translation>
<translation id="5400836586163650660">ಬೂದà³</translation>
<translation id="540969355065856584">ಈ ಸರà³à²µà²°à³ <ph name="DOMAIN" /> ಆಗಿದೆ ಎಂಬà³à²¦à²¨à³à²¨à³ ಸಾಬೀತà³à²ªà²¡à²¿à²¸à²²à³ ಸಾಧà³à²¯à²µà²¾à²—ಲಿಲà³à²²; ಈ ಸಮಯದಲà³à²²à²¿ ಅದರ ಸà³à²°à²•à³à²·à²¤à²¾ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²°à²µà³ ಮಾನà³à²¯à²µà²¾à²—ಿಲà³à²². ಇದೠತಪà³à²ªà³ ಕಾನà³à²«à²¿à²—ರೇಶನà³â€Œà²¨à²¿à²‚ದ ಅಥವಾ ಆಕà³à²°à²®à²£à²•à²¾à²°à²°à³ ನಿಮà³à²® ಸಂಪರà³à²•à²¦à²²à³à²²à²¿ ಒಳನà³à²¸à³à²³à²¿à²°à³à²µà³à²¦à²°à²¿à²‚ದ ಆಗಿರಬಹà³à²¦à³.</translation>
+<translation id="541143247543991491">ಕà³à²²à³Œà²¡à³ (ಸಿಸà³à²Ÿà²®à³â€Œà²¨à²¾à²¦à³à²¯à²‚ತ)</translation>
<translation id="541416427766103491">ಸà³à²Ÿà³à²¯à²¾à²•à²°à³ 4</translation>
<translation id="5421136146218899937">ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಡೇಟಾವನà³à²¨à³ ತೆರವà³à²—ೊಳಿಸಿ...</translation>
<translation id="5426179911063097041">ನಿಮಗೆ ಅಧಿಸೂಚನೆಗಳನà³à²¨à³ ಕಳà³à²¹à²¿à²¸à²²à³ <ph name="SITE" /> ಬಯಸà³à²¤à³à²¤à²¦à³†</translation>
@@ -1190,6 +1224,7 @@
<translation id="5455374756549232013">ತಪà³à²ªà²¾à²¦ ನೀತಿಯ ಸಮಯಸà³à²Ÿà³à²¯à²¾à²‚ಪà³</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" /> ಇನà³à²¨à²·à³à²Ÿà³}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="5463625433003343978">ಸಾಧನಗಳನà³à²¨à³ ಹà³à²¡à³à²•à²²à²¾à²—à³à²¤à³à²¤à²¿à²¦à³†...</translation>
<translation id="5469868506864199649">ಇಟಾಲಿಯನà³</translation>
<translation id="5470861586879999274">&amp;ಎಡಿಟೠಮಾಡà³à²µà³à²¦à²¨à³à²¨à³ ಪà³à²¨à²ƒ ಮಾಡà³</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1239,7 +1274,6 @@
<translation id="5624120631404540903">ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ನಿರà³à²µà²¹à²¿à²¸à²¿</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="563324245173044180">ವಂಚನೀಯ ವಿಷಯವನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಲಾಗಿದೆ.</translation>
<translation id="5644090287519800334">ಅಂಚೠ1 ಚಿತà³à²° X ಶಿಫà³à²Ÿà³</translation>
@@ -1278,12 +1312,12 @@
<translation id="5785756445106461925">ಅಲà³à²²à²¦à³‡, ಸà³à²°à²•à³à²·à²¿à²¤à²µà²²à³à²²à²¦ ಸಂಪನà³à²®à³‚ಲಗಳನà³à²¨à³ ಈ ಪà³à²Ÿ ಒಳಗೊಂಡಿದೆ. ಪà³à²°à²¯à²¾à²£à²¦ ಸಂದರà³à²­à²¦à²²à³à²²à²¿ ಈ ಸಂಪನà³à²®à³‚ಲಗಳನà³à²¨à³ ಇತರರೂ ವೀಕà³à²·à²¿à²¸à²¬à²¹à³à²¦à²¾à²—ಿದೆ ಮತà³à²¤à³ ಪà³à²Ÿà²¦ ನೋಟವೇ ಬದಲಾಗà³à²µà²‚ತೆ ಆಕà³à²°à²®à²£à²•à²¾à²°à²°à³ ಅದನà³à²¨à³ ತಿದà³à²¦à²¬à²¹à³à²¦à²¾à²—ಿದೆ.</translation>
<translation id="5786044859038896871">ನಿಮà³à²® ಕಾರà³à²¡à³ ಮಾಹಿತಿ ಭರà³à²¤à²¿ ಮಾಡಲೠನೀವೠಬಯಸà³à²µà²¿à²°à²¾?</translation>
<translation id="578633867165174378">ಡೇಟಾ ಉಲà³à²²à²‚ಘನೆಯಲà³à²²à²¿ ನೀವೠಬಳಸಿದ ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅನà³à²¨à³ Chrome ಪತà³à²¤à³†à²¹à²šà³à²šà²¿à²¦à³†. ಈಗಲೇ ಈ ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅನà³à²¨à³ ಬದಲಾಯಿಸಲೠನಾವೠಶಿಫಾರಸೠಮಾಡà³à²¤à³à²¤à³‡à²µà³†.</translation>
-<translation id="5798290721819630480">ಬದಲಾವಣೆಗಳನà³à²¨à³ ತà³à²¯à²œà²¿à²¸à³à²µà³à²¦à³‡?</translation>
<translation id="5803412860119678065">ನಿಮà³à²® <ph name="CARD_DETAIL" /> ಭರà³à²¤à²¿ ಮಾಡಲೠನೀವೠಬಯಸà³à²µà²¿à²°à²¾?</translation>
<translation id="5804241973901381774">ಅನà³à²®à²¤à²¿à²—ಳà³</translation>
<translation id="5804427196348435412">NFC ಸಾಧನಗಳನà³à²¨à³ ಬಳಸಿ</translation>
<translation id="5810442152076338065">ಬಳಕೆಯಲà³à²²à²¿à²²à³à²²à²¦ ಸೈಫರೠಸೂಟೠಬಳಸà³à²µ ಮೂಲಕ <ph name="DOMAIN" /> ಗೆ ನಿಮà³à²® ಸಂಪರà³à²•à²µà²¨à³à²¨à³ ಎನà³â€Œà²•à³à²°à²¿à²ªà³à²Ÿà³ ಮಾಡಲಾಗಿದೆ.</translation>
<translation id="5813119285467412249">&amp;ಸೇರಿಸà³à²µà³à²¦à²¨à³à²¨à³ ಮತà³à²¤à³†à²®à²¾à²¡à³</translation>
+<translation id="5817918615728894473">ಜೋಡಿಸà³</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ನೀವೠಪಾವತಿಸಿದಾಗ ಈ ಕಾರà³à²¡à³â€à²¨à²¿à²‚ದ ಹಣವನà³à²¨à³ ಕಡಿತಗೊಳಿಸಲಾಗà³à²¤à³à²¤à²¦à³†, ಆದರೆ ಈ ಕಾರà³à²¡à³â€à²¨ ನಿಜವಾದ ಸಂಖà³à²¯à³†à²¯à²¨à³à²¨à³ ಈ ಸೈಟà³â€â€à²¨à³Šà²‚ದಿಗೆ ಹಂಚಿಕೊಳà³à²³à³à²µà³à²¦à²¿à²²à³à²². ಹೆಚà³à²šà³à²µà²°à²¿ ಸà³à²°à²•à³à²·à²¤à³†à²—ಾಗಿ, ತಾತà³à²•à²¾à²²à²¿à²• CVC ಅನà³à²¨à³ ರಚಿಸಲಾಗà³à²¤à³à²¤à²¦à³†.}one{ನೀವೠಪಾವತಿಸà³à²µà²¾à²—, ನೀವೠಆಯà³à²•à³† ಮಾಡà³à²µ ಕಾರà³à²¡à³â€à²¨à²¿à²‚ದ ಹಣವನà³à²¨à³ ಕಡಿತಗೊಳಿಸಲಾಗà³à²¤à³à²¤à²¦à³†, ಆದರೆ ಈ ಕಾರà³à²¡à³â€à²¨ ನಿಜವಾದ ಸಂಖà³à²¯à³†à²¯à²¨à³à²¨à³ ಈ ಸೈಟà³â€â€à²¨à³Šà²‚ದಿಗೆ ಹಂಚಿಕೊಳà³à²³à³à²µà³à²¦à²¿à²²à³à²². ಹೆಚà³à²šà³à²µà²°à²¿ ಸà³à²°à²•à³à²·à²¤à³†à²—ಾಗಿ, ತಾತà³à²•à²¾à²²à²¿à²• CVC ಅನà³à²¨à³ ರಚಿಸಲಾಗà³à²¤à³à²¤à²¦à³†.}other{ನೀವೠಪಾವತಿಸà³à²µà²¾à²—, ನೀವೠಆಯà³à²•à³† ಮಾಡà³à²µ ಕಾರà³à²¡à³â€à²¨à²¿à²‚ದ ಹಣವನà³à²¨à³ ಕಡಿತಗೊಳಿಸಲಾಗà³à²¤à³à²¤à²¦à³†, ಆದರೆ ಈ ಕಾರà³à²¡à³â€à²¨ ನಿಜವಾದ ಸಂಖà³à²¯à³†à²¯à²¨à³à²¨à³ ಈ ಸೈಟà³â€â€à²¨à³Šà²‚ದಿಗೆ ಹಂಚಿಕೊಳà³à²³à³à²µà³à²¦à²¿à²²à³à²². ಹೆಚà³à²šà³à²µà²°à²¿ ಸà³à²°à²•à³à²·à²¤à³†à²—ಾಗಿ, ತಾತà³à²•à²¾à²²à²¿à²• CVC ಅನà³à²¨à³ ರಚಿಸಲಾಗà³à²¤à³à²¤à²¦à³†.}}</translation>
<translation id="5826507051599432481">ಸಾಮಾನà³à²¯ ಹೆಸರೠ(CN)</translation>
<translation id="5838278095973806738">ಈ ಸೈಟà³â€Œà²¨à²²à³à²²à²¿ ನೀವೠಯಾವà³à²¦à³‡ ಸೂಕà³à²·à³à²® ಮಾಹಿತಿಯನà³à²¨à³ (ಉದಾಹರಣೆಗೆ, ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳೠಅಥವಾ ಕà³à²°à³†à²¡à²¿à²Ÿà³ ಕಾರà³à²¡à³â€Œà²—ಳà³) ನಮೂದಿಸಬಾರದà³, à²à²•à³†à²‚ದರೆ ಅದೠದಾಳಿಕೋರರ ಮೂಲಕ ಕಳà³à²µà²¾à²—ಬಹà³à²¦à³.</translation>
@@ -1291,6 +1325,7 @@
<translation id="5855253129151731373">ಈ ಸೈಟà³â€Œà²¨ ಹೋಸà³à²Ÿà³ ಹೆಸರೠ<ph name="LOOKALIKE_DOMAIN" /> ಗೆ ಹೋಲà³à²¤à³à²¤à²¿à²¦à³†. ಡೊಮೇನà³â€Œ ಹೆಸರಿಗೆ ಸಣà³à²£ ಪà³à²°à²®à²¾à²£à²¦ ಅಥವಾ ಗà³à²°à³à²¤à²¿à²¸à²²à³ ಸಾಧà³à²¯à²µà²¾à²—ದ ರೀತಿಯಲà³à²²à²¿ ಬದಲಾವಣೆಗಳನà³à²¨à³ ಮಾಡà³à²µ ಮೂಲಕ ದಾಳಿಕೋರರೠಕೆಲವೊಮà³à²®à³† ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳನà³à²¨à³ ಅನà³à²•à²°à²£à³† ಮಾಡà³à²¤à³à²¤à²¾à²°à³†.
ಇದನà³à²¨à³ ದೋಷದಿಂದಾಗಿ ತೋರಿಸಲಾಗಿದೆ ಎಂದೠನೀವೠಭಾವಿಸà³à²µà³à²¦à²¾à²¦à²°à³†, ದಯವಿಟà³à²Ÿà³ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals ಪà³à²Ÿà²•à³à²•à³† ಭೇಟಿ ನೀಡಿ.</translation>
+<translation id="5860033963881614850">ಆಫà³</translation>
<translation id="5862579898803147654">ಸà³à²Ÿà³à²¯à²¾à²•à²°à³ 8</translation>
<translation id="5863847714970149516">ಮà³à²‚ದಿನ ಪà³à²Ÿà²µà³ ನಿಮಗೆ ಶà³à²²à³à²• ವಿಧಿಸಲೠಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¬à²¹à³à²¦à³</translation>
<translation id="5866257070973731571">ಫೋನೠಸಂಖà³à²¯à³†à²¯à²¨à³à²¨à³ ಸೇರಿಸಿ</translation>
@@ -1307,6 +1342,7 @@
<translation id="5913377024445952699">ಸà³à²•à³à²°à²¿à³•à²¨à³ ಕà³à²¯à²¾à²ªà³à²šà²°à³ ಅನà³à²¨à³ ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ</translation>
<translation id="59174027418879706">ಸಕà³à²°à²¿à²¯à²—ೊಳಿಸಲಾಗಿದೆ</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 ಬಳಕೆಯಲà³à²²à²¿à²¦à³†}one{# ಬಳಕೆಯಲà³à²²à²¿à²¦à³†}other{# ಬಳಕೆಯಲà³à²²à²¿à²¦à³†}}</translation>
<translation id="5921185718311485855">ಆನà³</translation>
<translation id="5921639886840618607">Google ಖಾತೆಯಲà³à²²à²¿ ಕಾರà³à²¡à³ ಅನà³à²¨à³ ಉಳಿಸಬೇಕೇ?</translation>
<translation id="5922853866070715753">ಬಹà³à²¤à³‡à²• ಮà³à²—ಿದಿದೆ</translation>
@@ -1326,6 +1362,7 @@
<translation id="5989320800837274978">ಹೊಂದಿಸಿದ ಪà³à²°à²¾à²•à³à²¸à²¿ ಸರà³à²µà²°à³â€Œà²—ಳೠಆಗಲಿ ಅಥವಾ .pac ಸà³à²•à³à²°à²¿à²ªà³à²Ÿà³ URL ಅನà³à²¨à³ ನಿರà³à²¦à²¿à²·à³à²Ÿà²ªà²¡à²¿à²¸à²¿à²²à³à²².</translation>
<translation id="5992691462791905444">ಇಂಜಿನಿಯರಿಂಗೠà²à³†à²¡à³ ಮಾದರಿಯಲà³à²²à²¿ ಮಡಿಸಿ</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' ಗಾಗಿ <ph name="RESULT_COUNT" /> ಫಲಿತಾಂಶಗಳà³</translation>
+<translation id="6006484371116297560">ಕà³à²²à²¾à²¸à²¿à²•à³</translation>
<translation id="6008122969617370890">N-ಇಂದ-1 ಆರà³à²¡à²°à³</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">ನಿಮà³à²® ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ಪರಿಶೀಲಿಸಿ</translation>
@@ -1347,6 +1384,7 @@
<translation id="6045164183059402045">ಅಳವಡಿಕೆ ಟೆಂಪà³à²²à³‡à²Ÿà³</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="6049004884579590341">ಪೂರà³à²£à²ªà²°à²¦à³†à²¯à²¿à²‚ದ ನಿರà³à²—ಮಿಸಲೠ<ph name="ACCELERATOR" /> ಅನà³à²¨à³ ಒತà³à²¤à²¿ ಹಿಡಿದà³à²•à³Šà²³à³à²³à²¿</translation>
<translation id="6049488691372270142">ಪà³à²Ÿ ವಿತರಣೆ</translation>
<translation id="6051221802930200923">ನೀವೠಸದà³à²¯à²•à³à²•à³† <ph name="SITE" /> ಗೆ ಭೇಟಿ ನೀಡಲೠಸಾಧà³à²¯à²µà²¿à²²à³à²². à²à²•à³†à²‚ದರೆ, ವೆಬà³â€Œà²¸à³ˆà²Ÿà³ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²° ಪಿನೠಮಾಡà³à²µà²¿à²•à³†à²¯à²¨à³à²¨à³ ಬಳಸà³à²¤à³à²¤à²¦à³†. ನೆಟà³â€Œà²µà²°à³à²•à³ ದೋಷಗಳೠಮತà³à²¤à³ ಆಕà³à²°à²®à²£à²—ಳೠತಾತà³à²•à²¾à²²à²¿à²•à²µà²¾à²—ಿರà³à²¤à³à²¤à²µà³†, ಹೀಗಾಗಿ ಈ ಪà³à²Ÿà²µà³ ಸà³à²µà²²à³à²ª ಸಮಯದ ನಂತರ ಕಾರà³à²¯ ನಿರà³à²µà²¹à²¿à²¸à²¬à²¹à³à²¦à³.</translation>
<translation id="6051898664905071243">ಪà³à²Ÿ ಎಣಿಕೆ:</translation>
@@ -1363,6 +1401,7 @@
<translation id="610911394827799129">ನಿಮà³à²® Google ಖಾತೆಯೠ<ph name="BEGIN_LINK" />history.google.com<ph name="END_LINK" /> ನಲà³à²²à²¿ ಇತರ ವಿಧಗಳ ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಇತಿಹಾಸವನà³à²¨à³ ಹೊಂದಿರಬಹà³à²¦à³</translation>
<translation id="6116338172782435947">ಕà³à²²à²¿à²ªà³â€Œà²¬à³‹à²°à³à²¡à³â€Œà²—ೆ ನಕಲಿಸಿರà³à²µ ಪಠà³à²¯ ಮತà³à²¤à³ ಚಿತà³à²°à²—ಳನà³à²¨à³ ನೋಡಿ</translation>
<translation id="6120179357481664955">ನಿಮà³à²® UPI à²à²¡à²¿ ನೆನಪಿದೆಯೇ?</translation>
+<translation id="6123290840358279103">ವರà³à²šà³à²µà²²à³ ಕಾರà³à²¡à³ ವೀಕà³à²·à²¿à²¸à²¿</translation>
<translation id="6124432979022149706">Chrome ಎಂಟರà³â€Œà²ªà³à²°à³ˆà²¸à³ ಕನೆಕà³à²Ÿà²°à³â€Œà²—ಳà³</translation>
<translation id="6146055958333702838">ಯಾವà³à²¦à³‡ ಕೇಬಲà³â€Œà²—ಳನà³à²¨à³ ಪರಿಶೀಲಿಸಿ. ನೀವೠಬಳಸà³à²¤à³à²¤à²¿à²°à²¬à²¹à³à²¦à²¾à²¦ ಯಾವà³à²¦à³‡ ರೂಟರà³â€Œà²—ಳà³, ಮೋಡೆಮà³â€Œà²—ಳೠಅಥವಾ ಇತರ ನೆಟà³â€Œà²µà²°à³à²•à³ ಸಾಧನಗಳನà³à²¨à³ ರೀಬೂಟೠಮಾಡಿ.</translation>
<translation id="614940544461990577">ಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¿:</translation>
@@ -1398,6 +1437,7 @@
<translation id="6289939620939689042">ಪà³à²Ÿà²¦ ಬಣà³à²£</translation>
<translation id="6290238015253830360">ನೀವೠಸಲಹೆ ನೀಡಿರà³à²µ ಲೇಖನಗಳೠಇಲà³à²²à²¿ ಕಾಣಿಸಿಕೊಳà³à²³à³à²¤à³à²¤à²µà³†</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome ನಲà³à²²à²¿à²¨ Google ಅಸಿಸà³à²Ÿà³†à²‚ಟೠನಿಲà³à²²à³à²¤à³à²¤à²¿à²¦à³†</translation>
<translation id="6305205051461490394"><ph name="URL" /> ತಲà³à²ªà²²à²¾à²—à³à²µà³à²¦à²¿à²²à³à²².</translation>
<translation id="6312113039770857350">ವೆಬà³â€Œà²ªà³à²Ÿ ಲಭà³à²¯à²µà²¿à²²à³à²²</translation>
@@ -1423,6 +1463,7 @@
<translation id="6390200185239044127">ಅರà³à²§ à²à³†à²¡à³ ಮಾದರಿಯಲà³à²²à²¿ ಮಡಿಸಿ</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">ನಿರà³à²µà²¾à²¹à²•à²° ನೀತಿಯà³, <ph name="ORIGIN_NAME" /> ನಿಂದ ಈ ಸà³à²¥à²³à²•à³à²•à³† ಪೇಸà³à²Ÿà³ ಮಾಡà³à²µà³à²¦à²¨à³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಿದೆ</translation>
+<translation id="6398765197997659313">ಪೂರà³à²£à²ªà²°à²¦à³†à²¯à²¿à²‚ದ ನಿರà³à²—ಮಿಸಿ</translation>
<translation id="6401136357288658127">ಈ ಕಾರà³à²¯à²¨à³€à²¤à²¿à²¯à²¨à³à²¨à³ ತಡೆಹಿಡಿಯಲಾಗಿದೆ. ಇದರ ಬದಲಿಗೆ, ನೀವೠ<ph name="NEW_POLICY" /> ಕಾರà³à²¯à²¨à³€à²¤à²¿à²¯à²¨à³à²¨à³ ಬಳಸಬೇಕà³.</translation>
<translation id="6404511346730675251">ಬà³à²•à³â€Œà²®à²¾à²°à³à²•à³â€Œà²—ಳನà³à²¨à³ ಎಡಿಟೠಮಾಡಿ</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1435,7 +1476,6 @@
<translation id="6428450836711225518">ನಿಮà³à²® ದೂರವಾಣಿ ಸಂಖà³à²¯à³†à²¯à²¨à³à²¨à³ ದೃಢೀಕರಿಸಿ</translation>
<translation id="6433490469411711332">ಸಂಪರà³à²• ಮಾಹಿತಿ ಎಡಿಟೠಮಾಡಿ</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ಸಂಪರà³à²•à²—ೊಳà³à²³à²²à³ ನಿರಾಕರಿಸಿದೆ.</translation>
-<translation id="6434309073475700221">ತಿರಸà³à²•à²°à²¿à²¸à²¿</translation>
<translation id="6440503408713884761">ನಿರà³à²²à²•à³à²·à²¿à²¸à²²à²¾à²—ಿದೆ</translation>
<translation id="6443406338865242315">ನೀವೠಇನà³â€Œà²¸à³à²Ÿà²¾à²²à³ ಮಾಡಿರà³à²µ ವಿಸà³à²¤à²°à²£à³†à²—ಳೠಮತà³à²¤à³ ಪà³à²²à²—à³â€Œà²‡à²¨à³â€Œà²—ಳà³</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1478,6 +1518,7 @@
<translation id="6624427990725312378">ಸಂಪರà³à²• ಮಾಹಿತಿ</translation>
<translation id="6626291197371920147">ಮಾನà³à²¯à²µà²¾à²¦ ಕಾರà³à²¡à³ ಸಂಖà³à²¯à³†à²¯à²¨à³à²¨à³ ಸೇರಿಸಿ</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ಹà³à²¡à³à²•à²¾à²Ÿ</translation>
+<translation id="6630043285902923878">USB ಸಾಧನಗಳನà³à²¨à³ ಹà³à²¡à³à²•à²²à²¾à²—à³à²¤à³à²¤à²¿à²¦à³†...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ತೆರವà³à²—ೊಳಿಸಿ</translation>
@@ -1493,6 +1534,7 @@
<translation id="6671697161687535275">Chromium ನಿಂದ ಫಾರà³à²®à³ ಸಲಹೆಯನà³à²¨à³ ತೆಗೆದà³à²¹à²¾à²•à³à²µà³à²¦à³‡?</translation>
<translation id="6685834062052613830">ಸೈನà³â€Œ ಔಟà³â€Œ ಮಾಡಿ ಹಾಗೂ ಸೆಟಪೠಪೂರà³à²£à²—ೊಳಿಸಿ</translation>
<translation id="6687335167692595844">ವಿನಂತಿಸಲಾದ ಫಾಂಟೠಗಾತà³à²°</translation>
+<translation id="6688743156324860098">ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಿ…</translation>
<translation id="6689249931105087298">ಕಪà³à²ªà³ ಬಿಂದೠಕಂಪà³à²°à³†à²¶à³à²¶à²¨à³â€Œà²—ೆ ಸಂಬಂಧಿಸಿದ</translation>
<translation id="6689271823431384964">ನೀವೠಸೈನೠಇನೠಮಾಡಿರà³à²µ ಕಾರಣದಿಂದಾಗಿ, ನಿಮà³à²® Google ಖಾತೆಯಲà³à²²à²¿ ನಿಮà³à²® ಕಾರà³à²¡à³â€Œà²—ಳನà³à²¨à³ ಉಳಿಸಲೠChrome ಅವಕಾಶ ನೀಡà³à²¤à³à²¤à²¿à²¦à³†. ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿ ನೀವೠಈ ವರà³à²¤à²¨à³†à²¯à²¨à³à²¨à³ ಬದಲಿಸಬಹà³à²¦à³. ಕಾರà³à²¡à³ ಹೋಲà³à²¡à²°à³ ಹೆಸರೠನಿಮà³à²® ಖಾತೆಯಿಂದ ಬರà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="6698381487523150993">ರಚಿಸಲಾಗಿದೆ:</translation>
@@ -1508,6 +1550,7 @@
<translation id="6744009308914054259">ಸಂಪರà³à²•à²•à³à²•à²¾à²—ಿ ನಿರೀಕà³à²·à²¿à²¸à³à²¤à³à²¤à²¿à²°à³à²µà²¾à²—, ಆಫà³â€Œà²²à³ˆà²¨à³ ​​ಲೇಖನಗಳನà³à²¨à³ ಓದಲೠನೀವೠಡೌನà³â€Œà²²à³‹à²¡à³â€Œà²—ಳಿಗೆ ಭೇಟಿ ನೀಡಬಹà³à²¦à³.</translation>
<translation id="6753269504797312559">ನೀತಿ ಮೌಲà³à²¯</translation>
<translation id="6757797048963528358">ನಿಮà³à²® ಸಾಧನವೠನಿದà³à²°à²¾à²µà²¸à³à²¥à³†à²—ೆ ಹೋಗಿದೆ.</translation>
+<translation id="6767985426384634228">ವಿಳಾಸ ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಬೇಕೇ?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ನೇರಳೆ</translation>
@@ -1530,6 +1573,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">ಓದà³à²µà³à²¦à²¨à³à²¨à³ ಸà³à²²à²­à²—ೊಳಿಸಲà³, Chrome ಈ ಪà³à²Ÿà²µà²¨à³à²¨à³ ಸರಳೀಕರಿಸಿದೆ. Chrome, ಅಸà³à²°à²•à³à²·à²¿à²¤ ಸಂಪರà³à²•à²¦ ಮೂಲಕ ಮೂಲ ಪà³à²Ÿà²µà²¨à³à²¨à³ ಪಡೆದà³à²•à³Šà²‚ಡಿದೆ.</translation>
<translation id="6891596781022320156">ನೀತಿಯ ಮಟà³à²Ÿà²µà³ ಬೆಂಬಲಿತವಾಗಿಲà³à²².</translation>
+<translation id="6895143722905299846">ವರà³à²šà³à²µà²²à³ ಸಂಖà³à²¯à³†:</translation>
<translation id="6895330447102777224">ನಿಮà³à²® ಕಾರà³à²¡à³ ಅನà³à²¨à³ ದೃಢೀಕರಿಸಲಾಗಿದೆ</translation>
<translation id="6897140037006041989">ಬಳಕೆದಾರರ à²à²œà³†à²‚ಟà³</translation>
<translation id="6898699227549475383">ಸಂಸà³à²¥à³† (O)</translation>
@@ -1565,10 +1609,10 @@
<translation id="7004583254764674281">ಕಾರà³à²¡à³â€Œà²—ಳನà³à²¨à³ ವೇಗವಾಗಿ ದೃಢೀಕರಿಸಲೠWindows Hello ಬಳಸಿ</translation>
<translation id="7006930604109697472">ಹೇಗಾದರೂ ಕಳà³à²¹à²¿à²¸à²¿</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ಮರà³à²—ಾತà³à²°à²—ೊಳಿಸà³à²µ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳà³</translation>
<translation id="7014741021609395734">à²à³‚ಮೠಮಟà³à²Ÿ</translation>
<translation id="7016992613359344582">ಇವà³à²—ಳೠಒಂದೠಬಾರಿ ಪಾವತಿಸà³à²µà²‚ತಹ ಶà³à²²à³à²•à²—ಳಾಗಿರಬಹà³à²¦à³, ಮರà³à²•à²³à²¿à²¸à³à²µ ಶà³à²²à³à²•à²—ಳಾಗಿರಬಹà³à²¦à³ ಅಥವಾ ಸà³à²ªà²·à³à²Ÿà²µà²¾à²—ಿಲà³à²²à²¦à³‡ ಇರಬಹà³à²¦à³.</translation>
<translation id="7029809446516969842">ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳà³</translation>
+<translation id="7030436163253143341">ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²° ಮಾನà³à²¯à²µà²¾à²—ಿಲà³à²²</translation>
<translation id="7031646650991750659">ನೀವೠಇನà³â€Œà²¸à³à²Ÿà²¾à²²à³ ಮಾಡಿರà³à²µ Google Play ಆà³à²¯à²ªà³â€Œà²—ಳà³</translation>
<translation id="7050187094878475250">ನೀವೠ<ph name="DOMAIN" /> ಅನà³à²¨à³ ತಲà³à²ªà²²à³ ಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¿à²°à³à²µà²¿à²°à²¿, ಆದರೆ ಸರà³à²µà²°à³ ವಿಶà³à²µà²¾à²¸à²¾à²°à³à²¹à²µà²¾à²—ಿರಲೠತà³à²‚ಬ ಉದà³à²¦à²µà²¾à²¦ ವಾಯಿದೆ ಅವಧಿಯನà³à²¨à³ ಹೊಂದಿರà³à²µ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²°à²µà²¨à³à²¨à³ ಸಲà³à²²à²¿à²¸à²¿à²¦à³†.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ಇದೀಗ ಈ ಕಾರà³à²¡à³ ಅನà³à²¨à³ ಉಳಿಸಲೠಸಾಧà³à²¯à²µà²¿à²²à³à²²}one{ಇದೀಗ ಈ ಕಾರà³à²¡à³â€Œà²—ಳನà³à²¨à³ ಉಳಿಸಲೠಸಾಧà³à²¯à²µà²¿à²²à³à²²}other{ಇದೀಗ ಈ ಕಾರà³à²¡à³â€Œà²—ಳನà³à²¨à³ ಉಳಿಸಲೠಸಾಧà³à²¯à²µà²¿à²²à³à²²}}</translation>
@@ -1638,12 +1682,14 @@
<translation id="7300012071106347854">ಕೋಬಾಲà³à²Ÿà³ ನೀಲಿ</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">ಅಧಿಕ</translation>
+<translation id="7305756307268530424">ನಿಧಾನವಾಗಿ ಪà³à²°à²¾à²°à²‚ಭಿಸಿ</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">ಸಂಪರà³à²• ಸಹಾಯ</translation>
<translation id="7323804146520582233">ಈ "<ph name="SECTION" />" ವಿಭಾಗವನà³à²¨à³ ಮರೆಮಾಡಿ</translation>
<translation id="733354035281974745">ಸಾಧನದ ಸà³à²¥à²³à³€à²¯ ಖಾತೆಯೠಅತಿಕà³à²°à²®à²¿à²¸à²¿à²¦à³†</translation>
<translation id="7333654844024768166">ವಂಚನೆ ಮಾಡà³à²µ ಸೈಟà³â€Œ ಒಂದರಲà³à²²à²¿, ನಿಮà³à²® ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅನà³à²¨à³ ಈಗಷà³à²Ÿà³‡ ನೀವೠನಮೂದಿಸಿದà³à²¦à³€à²°à²¿. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ಹಾಗೂ ಈ ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅನà³à²¨à³ ನೀವೠಯಾವ ಇತರ ಸೈಟà³â€Œà²—ಳಲà³à²²à²¿ ಬಳಸà³à²µà²¿à²°à³‹ ಅಲà³à²²à²¿ ಈಗಲೇ ಅದನà³à²¨à³ ಬದಲಾಯಿಸಬೇಕೆಂದೠChromium ನಿಮಗೆ ಶಿಫಾರಸೠಮಾಡà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="7334320624316649418">&amp;ಮರà³à²•à³à²°à²®à²—ೊಳಿಸà³à²µà³à²¦à²¨à³à²¨à³ ಮತà³à²¤à³†à²®à²¾à²¡à³</translation>
+<translation id="7337248890521463931">ಇನà³à²¨à²·à³à²Ÿà³ ಸಾಲà³à²—ಳನà³à²¨à³ ತೋರಿಸಿ</translation>
<translation id="7337706099755338005">ನಿಮà³à²® ಪà³à²²à²¾à²Ÿà³â€Œà²«à²¾à²°à³à²®à³â€Œà²¨à²²à³à²²à²¿ ಲಭà³à²¯à²µà²¿à²²à³à²².</translation>
<translation id="733923710415886693">ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²° ಪಾರದರà³à²¶à²•à²¤à³†à²¯ ಮೂಲಕ ಸರà³à²µà²°à³ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²°à²µà²¨à³à²¨à³ ಬಹಿರಂಗಪಡಿಸಲಾಗಿಲà³à²².</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1651,6 +1697,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">ಕಮಾಂಡೠಸಾಲà³</translation>
<translation id="7359588939039777303">ಜಾಹೀರಾತà³à²—ಳನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಲಾಗಿದೆ.</translation>
+<translation id="7363096869660964304">ಆದಾಗà³à²¯à³‚, ನೀವೠಕಾಣಿಸಿಕೊಳà³à²³à²¦à³‡ ಇರಲೠಸಾಧà³à²¯à²µà²¿à²²à³à²². ಅಜà³à²žà²¾à²¤à²µà²¾à²—ಿ ಹೋಗà³à²µà³à²¦à²°à²¿à²‚ದ ನಿಮà³à²® ಉದà³à²¯à³‹à²—ದಾತರà³, ನಿಮà³à²® ಇಂಟರà³à²¨à³†à²Ÿà³ ಸೇವಾ ಪೂರೈಕೆದಾರರೠಇಲà³à²²à²µà³‡ ನೀವೠಭೇಟಿ ನೀಡà³à²µ ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳಿಂದ ನಿಮà³à²® ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಅನà³à²¨à³ ಮರೆಮಾಡಲಾಗà³à²µà³à²¦à²¿à²²à³à²².</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿ ವಿಳಾಸಗಳನà³à²¨à³ ಸೇರಿಸಲೠಮತà³à²¤à³ ನಿರà³à²µà²¹à²¿à²¸à²²à³ Tab ಒತà³à²¤à²¿, ನಂತರ Enter ಒತà³à²¤à²¿</translation>
<translation id="7365849542400970216">ನಿಮà³à²® ಸಾಧನದ ಬಳಕೆಯ ಕà³à²°à²¿à²¤à³ ತಿಳಿಯಲೠಬಳಸà³à²µà²¿à²°à²¾?</translation>
<translation id="7372973238305370288">ಹà³à²¡à³à²•à²¾à²Ÿ ಫಲಿತಾಂಶ</translation>
@@ -1661,7 +1708,9 @@
<translation id="7378594059915113390">ಮೀಡಿಯಾ ನಿಯಂತà³à²°à²£à²—ಳà³</translation>
<translation id="7378627244592794276">ಬೇಡ</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ಅನà³à²µà²¯à²¿à²¸à³à²µà³à²¦à²¿à²²à³à²²</translation>
<translation id="7390545607259442187">ಕಾರà³à²¡à³ ಅನà³à²¨à³ ದೃಢೀಕರಿಸಿ</translation>
+<translation id="7392089738299859607">ವಿಳಾಸವನà³à²¨à³ ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಿ</translation>
<translation id="7399802613464275309">ಸà³à²°à²•à³à²·à²¤à³†à²¯ ಪರಿಶೀಲನೆ</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">ನಿಮà³à²® <ph name="DEVICE_NAME" /> ಸಾಧನವನà³à²¨à³ ನಿರà³à²µà²¹à²¿à²¸à²²à²¾à²—ಿದೆ</translation>
@@ -1675,6 +1724,7 @@
&lt;li&gt; &lt;strong&gt;ಅನà³à²µà²¯à²¿à²¸à²¿&lt;/strong&gt; ಕà³à²²à²¿à²•à³ ಮಾಡಿ, ನಂತರ &lt;strong&gt;ಸರಿ&lt;/strong&gt; ಕà³à²²à²¿à²•à³ ಮಾಡಿ
&lt;li&gt;ನಿಮà³à²® ಕಂಪà³à²¯à³‚ಟರà³â€Œà²¨à²¿à²‚ದ ಸಾಫà³à²Ÿà³â€Œà²µà³‡à²°à³ ಅನà³à²¨à³ ಶಾಶà³à²µà²¤à²µà²¾à²—ಿ ತೆಗೆದà³à²¹à²¾à²•à³à²µà³à²¦à³ ಹೇಗೆ ಎಂದೠತಿಳಿದà³à²•à³Šà²³à³à²³à²²à³ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome ಸಹಾಯ ಕೇಂದà³à²°à²•à³à²•à³†&lt;/a&gt; ಭೇಟಿ ನೀಡಿ &lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">ಸà³à²‚ದರ</translation>
<translation id="7416351320495623771">ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ನಿರà³à²µà²¹à²¿à²¸à²¿â€¦</translation>
<translation id="7419106976560586862">ಪà³à²°à³Šà²«à³ˆà²²à³ ಹಾದಿ</translation>
<translation id="7437289804838430631">ಸಂಪರà³à²• ಮಾಹಿತಿಯನà³à²¨à³ ಸೇರಿಸà³</translation>
@@ -1690,7 +1740,7 @@
<translation id="7481312909269577407">ಫಾರà³à²µà²°à³à²¡à³</translation>
<translation id="7485870689360869515">ಯಾವà³à²¦à³‡ ಡೇಟಾ ಕಂಡà³à²¬à²‚ದಿಲà³à²².</translation>
<translation id="7495528107193238112">ಈ ವಿಷಯವನà³à²¨à³ ನಿರà³à²¬à²‚ಧಿಸಲಾಗಿದೆ. ಸಮಸà³à²¯à³†à²¯à²¨à³à²¨à³ ಪರಿಹರಿಸಲೠಸೈಟೠಮಾಲೀಕರನà³à²¨à³ ಸಂಪರà³à²•à²¿à²¸à²¿.</translation>
-<translation id="7498234416455752244">ಎಡಿಟà³â€Œ ಮಾಡà³à²¤à³à²¤à²¿à²°à²¿</translation>
+<translation id="7498193950643227031">ಮರà³à²—ಾತà³à²°à²—ೊಳಿಸಿದರೆ ಇದೠಅನಿರೀಕà³à²·à²¿à²¤à²µà²¾à²—ಿ ವರà³à²¤à²¿à²¸à²¬à²¹à³à²¦à³. <ph name="SETTINGS" /> ನಲà³à²²à²¿ ಆà³à²¯à²ªà³â€Œà²—ಳನà³à²¨à³ ಮರà³à²—ಾತà³à²°à²—ೊಳಿಸà³à²µ ಸಾಮರà³à²¥à³à²¯à²µà²¨à³à²¨à³ ನೀವೠಈಗ ಮಿತಿಗೊಳಿಸಬಹà³à²¦à³.</translation>
<translation id="7503664977220660814">ವಂಚನೆ ಮಾಡà³à²µ ಸೈಟà³â€Œà²¨à²²à³à²²à²¿, ನಿಮà³à²® ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅನà³à²¨à³ ಈಗಷà³à²Ÿà³‡ ನೀವೠನಮೂದಿಸಿದà³à²¦à³€à²°à²¿. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ಮತà³à²¤à³ ಈ ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಬಳಸà³à²µ ಇತರ ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳಲà³à²²à²¿ ನಿಮà³à²® ಉಳಿಸಿದ ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ಈಗಲೇ ಪರಿಶೀಲಿಸà³à²µà²‚ತೆ Chromium ಶಿಫಾರಸೠಮಾಡà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="7508255263130623398">ಹಿಂತಿರà³à²—ಿಸಲಾದ ನೀತಿಯ ಸಾಧನ à²à²¡à²¿ ಖಾಲಿ ಇದೆ ಅಥವಾ ಪà³à²°à²¸à³à²¤à³à²¤ ಸಾಧನ à²à²¡à²¿à²—ೆ ಹೊಂದಾಣಿಕೆಯಾಗà³à²µà³à²¦à²¿à²²à³à²²</translation>
<translation id="7508870219247277067">ಅವಕಾಡೊ ಹಸಿರà³</translation>
@@ -1710,6 +1760,7 @@
<translation id="7548892272833184391">ಸಂಪರà³à²• ದೋಷಗಳನà³à²¨à³ ಸರಿಪಡಿಸಿ</translation>
<translation id="7549584377607005141">ಈ ವೆಬà³â€Œà²ªà³à²Ÿà²µà³ ಸರಿಯಾಗಿ ಪà³à²°à²¦à²°à³à²¶à²¨à²—ೊಳà³à²³à²²à³ ಈ ಮೊದಲೠನೀವೠನಮೂದಿಸಿದ ಡೇಟಾದ ಅಗತà³à²¯à²µà²¿à²¦à³†. ನೀವೠಈ ಡೇಟಾವನà³à²¨à³ ಮತà³à²¤à³† ಕಳà³à²¹à²¿à²¸à²¬à²¹à³à²¦à³, ಆದರೆ ಹಾಗೆ ಮಾಡà³à²µà³à²¦à²°à²¿à²‚ದ ಈ ಪà³à²Ÿà²µà³ ಈ ಮೊದಲೠಪೂರೈಸಿದ ಯಾವà³à²¦à³‡ ಕà³à²°à²¿à²¯à³†à²¯à²¨à³à²¨à³ ನೀವೠಪà³à²¨à²°à²¾à²µà²°à³à²¤à²¿à²¸à³à²¤à³à²¤à³€à²°à²¿.</translation>
<translation id="7550637293666041147">ನಿಮà³à²® ಸಾಧನದ ಬಳಕೆದಾರರ ಹೆಸರೠಮತà³à²¤à³ Chrome ಬಳಕೆದಾರರ ಹೆಸರà³</translation>
+<translation id="755279583747225797">ಪà³à²°à²¯à³‹à²—ವೠಸಕà³à²°à²¿à²¯à²µà²¾à²—ಿದೆ</translation>
<translation id="7552846755917812628">ಕೆಳಗಿನ ಸಲಹೆಗಳನà³à²¨à³ ಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¿:</translation>
<translation id="7554475479213504905">ಹೇಗಿದà³à²¦à²°à³‚ ಮರà³à²²à³‹à²¡à³ ಮಾಡಿ ಮತà³à²¤à³ ತೋರಿಸಿ</translation>
<translation id="7554791636758816595">ಹೊಸ ಟà³à²¯à²¾à²¬à³</translation>
@@ -1728,7 +1779,6 @@
<translation id="7610193165460212391">ಮೌಲà³à²¯à²µà³ ವà³à²¯à²¾à²ªà³à²¤à²¿à²¯à²¿à²‚ದ <ph name="VALUE" /> ಹೊರಗಿದೆ.</translation>
<translation id="7613889955535752492">ಅವಧಿ ಮೀರà³à²µ ಸಮಯ: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿ ನಿಮà³à²® ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ವೀಕà³à²·à²¿à²¸à²²à³ ಮತà³à²¤à³ ನಿರà³à²µà²¹à²¿à²¸à²²à³ Tab ಒತà³à²¤à²¿, ನಂತರ Enter ಒತà³à²¤à²¿à²°à²¿</translation>
-<translation id="7615602087246926389">ನಿಮà³à²® Google ಖಾತೆಯ ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²¨ ಬೇರೆ ಆವೃತà³à²¤à²¿à²¯à²¨à³à²¨à³ ಬಳಸಿಕೊಂಡೠಎನà³â€Œà²•à³à²°à²¿à²ªà³à²Ÿà³ ಮಾಡಲಾದ ಡೇಟಾವನà³à²¨à³ ನೀವೠಈಗಾಗಲೇ ಹೊಂದಿರà³à²µà²¿à²°à²¿. ದಯವಿಟà³à²Ÿà³ ಕೆಳಗೆ ಇದನà³à²¨à³ ನಮೂದಿಸಿ.</translation>
<translation id="7616645509853975347">ನಿಮà³à²® ನಿರà³à²µà²¾à²¹à²•à²°à³ ನಿಮà³à²® ಬà³à²°à³Œà²¸à²°à³â€Œà²¨à²²à³à²²à²¿ Chrome Enterprise ಕನೆಕà³à²Ÿà²°à³â€Œà²—ಳನà³à²¨à³ ಆನೠಮಾಡಿದà³à²¦à²¾à²°à³†. ನಿಮà³à²® ಕೆಲವೊಂದೠಡೇಟಾಕà³à²•à³† ಈ ಕನೆಕà³à²Ÿà²°à³â€Œà²—ಳೠಪà³à²°à²µà³‡à²¶ ಹೊಂದಿರà³à²¤à³à²¤à²µà³†.</translation>
<translation id="7619838219691048931">ಕೊನೆಯ ಶೀಟà³</translation>
<translation id="762844065391966283">ಒಂದೠಬಾರಿಗೆ ಒಂದà³</translation>
@@ -1793,13 +1843,12 @@
<translation id="782886543891417279">ನೀವೠಬಳಸà³à²¤à³à²¤à²¿à²°à³à²µ ವೈ-ಫೈ (<ph name="WIFI_NAME" />) ಅದರ ಲಾಗಿನೠಪà³à²Ÿà²•à³à²•à³† ನೀವೠಭೇಟಿ ನೀಡà³à²µ ಅಗತà³à²¯à²µà²¿à²¦à³†.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ಒಂದೂ ಇಲà³à²²}=1{1 ಆà³à²¯à²ªà³ (<ph name="EXAMPLE_APP_1" />)}=2{2 ಆà³à²¯à²ªà³â€Œà²—ಳೠ(<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# ಆà³à²¯à²ªà³â€Œà²—ಳೠ(<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# ಆà³à²¯à²ªà³â€Œà²—ಳೠ(<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">ಆದರೆ, ನೀವೠಅದೃಶà³à²¯à²°à²¾à²—ಿರà³à²µà³à²¦à²¿à²²à³à²². ಅಜà³à²žà²¾à²¤à²µà²¾à²—ಿ ಹೋಗà³à²µà³à²¦à²°à²¿à²‚ದ ನಿಮà³à²® ಉದà³à²¯à³‹à²—ದಾತರà³, ನಿಮà³à²® ಇಂಟರà³à²¨à³†à²Ÿà³ ಸೇವಾ ಪೂರೈಕೆದಾರರೠಇಲà³à²²à²µà³‡ ನೀವೠಭೇಟಿ ನೀಡà³à²µ ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳಿಂದ ನಿಮà³à²® ಬà³à²°à³Œà²¸à²¿à²‚ಗೠಮರೆ ಮಾಡಲಾಗà³à²µà³à²¦à²¿à²²à³à²².</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ಫೈಲà³â€Œà²—ಳ ಪà³à²°à²•à²¾à²°à²¦ ಸಂಯೋಜನೆಗಳ ಜೊತೆಗೆ ಫೈಲà³â€Œà²—ಳನà³à²¨à³ ತೆರೆಯಿರಿ.</translation>
<translation id="7862185352068345852">ಸೈಟà³â€Œ ಅನà³à²¨à³ ತೊರೆಯà³à²µà³à²¦à³‡?</translation>
<translation id="7865448901209910068">ಉತà³à²¤à²® ವೇಗ</translation>
<translation id="7874263914261512992">ವಂಚನೆ ಮಾಡà³à²µ ಸೈಟà³â€Œà²¨à²²à³à²²à²¿, ನಿಮà³à²® ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಅನà³à²¨à³ ಈಗಷà³à²Ÿà³‡ ನೀವೠನಮೂದಿಸಿದà³à²¦à³€à²°à²¿. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ಮತà³à²¤à³ ಈ ಪಾಸà³â€Œà²µà²°à³à²¡à³ ಬಳಸà³à²µ ಇತರ ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳಲà³à²²à²¿ ನಿಮà³à²® ಉಳಿಸಿದ ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ಈಗಲೇ ಪರಿಶೀಲಿಸà³à²µà²‚ತೆ Chrome ಶಿಫಾರಸೠಮಾಡà³à²¤à³à²¤à²¦à³†.</translation>
<translation id="7878562273885520351">ನಿಮà³à²® ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œ ಅನà³à²¨à³ ಸà³à²²à²­à²µà²¾à²—ಿ ಪತà³à²¤à³† ಮಾಡಬಹà³à²¦à³</translation>
+<translation id="7880146494886811634">ವಿಳಾಸವನà³à²¨à³ ಉಳಿಸಬೇಕೆ</translation>
<translation id="7882421473871500483">ಕಂದà³</translation>
<translation id="7887683347370398519">ನಿಮà³à²® CVC ಅನà³à²¨à³ ಪರಿಶೀಲಿಸಿ ಹಾಗೂ ಮತà³à²¤à³† ಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¿</translation>
<translation id="7887885240995164102">ಚಿತà³à²°à²¦à²²à³à²²à²¿ ಚಿತà³à²° ಮೋಡà³â€Œà²—ೆ ಪà³à²°à²µà³‡à²¶à²¿à²¸à²¿</translation>
@@ -1807,6 +1856,7 @@
<translation id="7894280532028510793">ಕಾಗà³à²£à²¿à²¤ ಸರಿಯಾಗಿದà³à²¦à²°à³†, <ph name="BEGIN_LINK" />ನೆಟà³â€Œà²µà²°à³à²•à³ ಡಯಾಗà³à²¨à²¾à²¸à³à²Ÿà²¿à²•à³à²¸à³â€Œâ€Œ ರನೠಮಾಡಿ ನೋಡಿ<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">ಅಪರಿಚಿತ</translation>
+<translation id="793209273132572360">ವಿಳಾಸವನà³à²¨à³ ಅಪà³â€Œà²¡à³‡à²Ÿà³ ಮಾಡಬೇಕೆ?</translation>
<translation id="7932579305932748336">ಹಚà³à²šà³</translation>
<translation id="79338296614623784">ಮಾನà³à²¯à²µà²¾à²¦ ಫೋನೠಸಂಖà³à²¯à³†à²¯à²¨à³à²¨à³ ನಮೂದಿಸಿ</translation>
<translation id="7934052535022478634">ಪಾವತಿ ಪೂರà³à²£à²—ೊಂಡಿದೆ</translation>
@@ -1877,6 +1927,7 @@
<translation id="8175796834047840627">ನೀವೠಸೈನೠಇನೠಮಾಡಿರà³à²µ ಕಾರಣದಿಂದಾಗಿ, ನಿಮà³à²® Google ಖಾತೆಯಲà³à²²à²¿ ನಿಮà³à²® ಕಾರà³à²¡à³â€Œà²—ಳನà³à²¨à³ ಉಳಿಸಲೠChrome ಅವಕಾಶ ನೀಡà³à²¤à³à²¤à²¿à²¦à³†. ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿ ನೀವೠಈ ವರà³à²¤à²¨à³†à²¯à²¨à³à²¨à³ ಬದಲಿಸಬಹà³à²¦à³.</translation>
<translation id="8176440868214972690">ಈ ಸಾಧನದ ನಿರà³à²µà²¾à²¹à²•à²°à³ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳೠಅಥವಾ ಕಾರà³à²¯à²¨à³€à²¤à²¿à²—ಳಂತಹ ಕೆಲವೠಮಾಹಿತಿಯನà³à²¨à³ ಈ ಕೆಳಗಿನ ವೆಬà³â€Œà²¸à³ˆà²Ÿà³â€Œà²—ಳಿಗೆ ಕಳà³à²¹à²¿à²¸à²¿à²¦à³à²¦à²¾à²°à³†.</translation>
<translation id="8184538546369750125">ಜಾಗತಿಕ ಡಿಫಾಲà³à²Ÿà³ ಬಳಸಿ (ಅನà³à²®à²¤à²¿à²¸à²¿)</translation>
+<translation id="8193086767630290324">ಡೇಟಾದೊಂದಿಗೆ ತೆಗೆದà³à²•à³Šà²‚ಡ ಕà³à²°à²®à²—ಳನà³à²¨à³ ಗೌಪà³à²¯à²µà³†à²‚ದೠಫà³à²²à³à²¯à²¾à²—ೠಮಾಡಲಾಗಿದೆ</translation>
<translation id="8194797478851900357">&amp;ಸರಿಸà³à²µà³à²¦à²¨à³à²¨à³ ರದà³à²¦à³à²—ೊಳಿಸà³</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" ಜೊತೆಗಿನ ವಿಸà³à²¤à²°à²£à³†à²—ೆ ಅಮಾನà³à²¯à²µà²¾à²¦ ಅಪà³â€Œà²¡à³‡à²Ÿà³â€Œâ€Œ URL.</translation>
<translation id="8202097416529803614">ಆರà³à²¡à²°à³ ಸಾರಾಂಶ</translation>
@@ -1899,6 +1950,7 @@
<translation id="8249296373107784235">ನಿಷà³à²«à²²à²—ೊಳಿಸà³</translation>
<translation id="8249320324621329438">ಕಳೆದ ಬಾರಿ ಪಡೆದಿರà³à²µà³à²¦à³:</translation>
<translation id="8253091569723639551">ಬಿಲà³à²²à²¿à²‚ಗೠವಿಳಾಸ ಅಗತà³à²¯à²µà²¿à²¦à³†</translation>
+<translation id="8257387598443225809">ಈ ಆà³à²¯à²ªà³ ಅನà³à²¨à³ ಮೊಬೈಲà³â€Œà²—ಾಗಿ ವಿನà³à²¯à²¾à²¸à²—ೊಳಿಸಲಾಗಿದೆ</translation>
<translation id="825929999321470778">ಉಳಿಸಿದ ಎಲà³à²² ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ ತೋರಿಸಿ</translation>
<translation id="8261506727792406068">ಅಳಿಸಿ</translation>
<translation id="8262952874573525464">ಕೆಳಭಾಗದ ಅಂಚನà³à²¨à³ ಹೊಲಿಯಿರಿ</translation>
@@ -2023,7 +2075,6 @@
<translation id="8719528812645237045">ಮೇಲà³à²­à²¾à²—ದಲà³à²²à²¿ ಅನೇಕ ತೂತà³à²—ಳನà³à²¨à³ ಮಾಡಿ</translation>
<translation id="8725066075913043281">ಮತà³à²¤à³† ಪà³à²°à²¯à²¤à³à²¨à²¿à²¸à²¿</translation>
<translation id="8726549941689275341">ಪà³à²Ÿà²¦ ಗಾತà³à²°:</translation>
-<translation id="8728672262656704056">ನೀವೠಅದೃಶà³à²¯à²°à²¾à²—ಿರà³à²µà²¿à²°à²¿</translation>
<translation id="8730621377337864115">ಮà³à²—ಿದಿದೆ</translation>
<translation id="8731544501227493793">ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳ ಬಟನೠಅನà³à²¨à³ ನಿರà³à²µà²¹à²¿à²¸à²¿, ನಿಮà³à²® ಪಾಸà³â€Œà²µà²°à³à²¡à³â€Œà²—ಳನà³à²¨à³ Chrome ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿ ವೀಕà³à²·à²¿à²¸à²²à³ ಮತà³à²¤à³ ನಿರà³à²µà²¹à²¿à²¸à²²à³ ಎಂಟರೠಒತà³à²¤à²¿à²°à²¿</translation>
<translation id="8734529307927223492">ನಿಮà³à²® <ph name="DEVICE_TYPE" /> ಸಾಧನವನà³à²¨à³ <ph name="MANAGER" /> ನಿರà³à²µà²¹à²¿à²¸à³à²¤à³à²¤à²¦à³†</translation>
@@ -2100,6 +2151,7 @@
<translation id="9020542370529661692">ಈ ಪà³à²Ÿà²µà²¨à³à²¨à³ <ph name="TARGET_LANGUAGE" /> ಗೆ ಅನà³à²µà²¾à²¦à²¿à²¸à²²à²¾à²—ಿದೆ</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ಅಮಾನà³à²¯)</translation>
+<translation id="9030265603405983977">ಮೊನೊಕà³à²°à³‹à²®à³</translation>
<translation id="9035022520814077154">ಭದà³à²°à²¤à²¾ ದೋಷ</translation>
<translation id="9038649477754266430">ಪà³à²Ÿà²—ಳನà³à²¨à³ ಹೆಚà³à²šà³ ವೇಗವಾಗಿ ಲೋಡೠಮಾಡಲೠಮà³à²¨à³à²¨à³‹à²Ÿà²—ಳನà³à²¨à³ ಬಳಸಿ</translation>
<translation id="9039213469156557790">ಅಲà³à²²à²¦à³‡, ಸà³à²°à²•à³à²·à²¿à²¤à²µà²²à³à²²à²¦ ಸಂಪನà³à²®à³‚ಲಗಳನà³à²¨à³ ಈ ಪà³à²Ÿ ಹೊಂದಿದೆ. ಸà³à²¥à²¿à²¤à³à²¯à²‚ತರಗೊಳà³à²³à³à²µ ಸಂದರà³à²­à²¦à²²à³à²²à²¿ ಈ ಸಂಪನà³à²®à³‚ಲಗಳನà³à²¨à³ ಇತರರೂ ವೀಕà³à²·à²¿à²¸à²¬à²¹à³à²¦à²¾à²—ಿದೆ ಮತà³à²¤à³ ಪà³à²Ÿà²¦ ಹೊರನೋಟವೇ ಬದಲಾಗà³à²µà²‚ತೆ ಆಕà³à²°à²®à²£à²•à²¾à²°à²°à³ ಅದನà³à²¨à³ ತಿದà³à²¦à²¬à²¹à³à²¦à²¾à²—ಿದೆ.</translation>
@@ -2123,6 +2175,7 @@
<translation id="91108059142052966">ನಿರà³à²µà²¾à²¹à²•à²° ನೀತಿಯ ಪà³à²°à²•à²¾à²° ಗೌಪà³à²¯ ವಿಷಯ ಗೋಚರಿಸà³à²¤à³à²¤à²¿à²°à³à²µà²¾à²— <ph name="APPLICATION_TITLE" /> ಜೊತೆ ಸà³à²•à³à²°à³€à²¨à³â€Œâ€Œ ಹಂಚಿಕೊಳà³à²³à³à²µà³à²¦à²¨à³à²¨à³ ನಿಷà³à²•à³à²°à²¿à²¯à²—ೊಳಿಸಲಾಗà³à²¤à³à²¤à²¦à³†</translation>
<translation id="9114524666733003316">ಕಾರà³à²¡à³â€Œ ದೃಢೀಕರಿಸಲಾಗà³à²¤à³à²¤à²¿à²¦à³†...</translation>
<translation id="9114581008513152754">ಈ ಬà³à²°à³Œà²¸à²°à³ ಅನà³à²¨à³ ಕಂಪನಿ ಅಥವಾ ಇತರ ಸಂಸà³à²¥à³†à²¯à³ ನಿರà³à²µà²¹à²¿à²¸à³à²¤à³à²¤à²¿à²²à³à²². ಈ ಸಾಧನದಲà³à²²à²¿à²¨ ಚಟà³à²µà²Ÿà²¿à²•à³†à²¯à²¨à³à²¨à³ Chrome ನಿಂದ ಹೊರಗೆ ನಿರà³à²µà²¹à²¿à²¸à²¬à²¹à³à²¦à³. <ph name="BEGIN_LINK" />ಇನà³à²¨à²·à³à²Ÿà³ ತಿಳಿಯಿರಿ<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ಹೊಸದà³</translation>
<translation id="9119042192571987207">ಅಪà³â€Œà²²à³‹à²¡à³ ಮಾಡಲಾಗಿದೆ</translation>
<translation id="9128016270925453879">ನೀತಿಗಳನà³à²¨à³ ಲೋಡೠಮಾಡಲಾಗಿದೆ</translation>
<translation id="9128870381267983090">ನೆಟà³â€Œà²µà²°à³à²•à³â€Œà²—ೆ ಸಂಪರà³à²•à²¿à²¸à³</translation>
@@ -2141,6 +2194,7 @@
<translation id="9170848237812810038">&amp;ರದà³à²¦à³à²®à²¾à²¡à³</translation>
<translation id="9171296965991013597">ಅಪà³à²²à²¿à²•à³†à³•à²¶à²¨à³ ಅನà³à²¨à³ ತà³à²¯à²œà²¿à²¸à²¬à³‡à²•à³†?</translation>
<translation id="9173282814238175921">à²à²•à³ˆà²• ಡಾಕà³à²¯à³à²®à³†à²‚ಟà³/ಹೊಸ ಶೀಟà³</translation>
+<translation id="9173995187295789444">ಬà³à²²à³‚ಟೂತೠಸಾಧನಳನà³à²¨à³ ಹà³à²¡à³à²•à³à²µà³à²¦à²•à³à²•à²¾à²—ಿ ಸà³à²•à³à²¯à²¾à²¨à³ ಮಾಡಲಾಗà³à²¤à³à²¤à²¿à²¦à³†...</translation>
<translation id="917450738466192189">ಸರà³à²µà²°à³â€Œà²¨ ಪà³à²°à²®à²¾à²£à²ªà²¤à³à²°à²µà³ ಅಮಾನà³à²¯à²µà²¾à²—ಿದೆ.</translation>
<translation id="9174917557437862841">ಟà³à²¯à²¾à²¬à³ ಬದಲಿಸà³à²µ ಬಟನà³, ಈ ಟà³à²¯à²¾à²¬à³â€Œà²—ೆ ಬದಲಾಯಿಸಲೠEnter ಒತà³à²¤à²¿à²°à²¿</translation>
<translation id="9179703756951298733">Chrome ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳಲà³à²²à²¿ ನಿಮà³à²® ಪಾವತಿಗಳೠಮತà³à²¤à³ ಕà³à²°à³†à²¡à²¿à²Ÿà³ ಕಾರà³à²¡à³ ಮಾಹಿತಿಯನà³à²¨à³ ನಿರà³à²µà²¹à²¿à²¸à²¿</translation>
diff --git a/chromium/components/strings/components_strings_ko.xtb b/chromium/components/strings/components_strings_ko.xtb
index 4dbd6851c04..02853478109 100644
--- a/chromium/components/strings/components_strings_ko.xtb
+++ b/chromium/components/strings/components_strings_ko.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">ì„ íƒí•˜ë©´ Chromeì—ì„œ ì–‘ì‹ì„ ë” ë¹ ë¥´ê²Œ 입력할 수 있ë„ë¡ ì´ ê¸°ê¸°ì— ì¹´ë“œ ì‚¬ë³¸ì„ ì €ìž¥í•©ë‹ˆë‹¤.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> ê¶Œí•œì„ ì„ íƒí•©ë‹ˆë‹¤</translation>
<translation id="1113869188872983271">재정렬 실행 취소(&amp;U)</translation>
+<translation id="1123753900084781868">현재 실시간 ìžë§‰ì„ 사용할 수 없습니다.</translation>
<translation id="1125573121925420732">웹사ì´íŠ¸ì—ì„œ ë³´ì•ˆì„ ì—…ë°ì´íŠ¸í•˜ëŠ” ë™ì•ˆì—는 경고가 ìžì£¼ ë°œìƒí•  수 있습니다. 곧 ê°œì„ ë  ê²ƒìž…ë‹ˆë‹¤.</translation>
<translation id="112840717907525620">ì •ì±… ìºì‹œ 확ì¸</translation>
<translation id="1130564665089811311">페ì´ì§€ 번역 버튼, Google 번역으로 ì´ íŽ˜ì´ì§€ë¥¼ 번역하려면 Enter 누르기</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">기기 ì´ë¦„</translation>
<translation id="124116460088058876">다른 언어</translation>
<translation id="1243027604378859286">작성ìž:</translation>
+<translation id="1246424317317450637">굵게</translation>
<translation id="1250759482327835220">다ìŒë²ˆì— ë” ë¹ ë¥´ê²Œ 결제할 수 있ë„ë¡ Google ê³„ì •ì— ì¹´ë“œ, ì´ë¦„, 청구서 수신 주소를 저장하세요.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" />(ë™ê¸°í™”ë¨)</translation>
<translation id="1256368399071562588">&lt;p&gt;웹사ì´íŠ¸ë¥¼ 방문하려고 í•˜ëŠ”ë° ì—´ë¦¬ì§€ 않으면 ìš°ì„  ì´ ë¬¸ì œí•´ê²° ë‹¨ê³„ì— ë”°ë¼ ì˜¤ë¥˜ë¥¼ í•´ê²°í•´ 보세요.&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">비밀번호 변경</translation>
<translation id="1484290072879560759">배송지 주소 ì„ íƒ</translation>
<translation id="1492194039220927094">정책 푸시:</translation>
+<translation id="1495677929897281669">탭으로 ëŒì•„가기</translation>
<translation id="1501859676467574491">Google ê³„ì •ì— ì €ìž¥ëœ ì¹´ë“œ 표시</translation>
<translation id="1507202001669085618">&lt;p&gt;온ë¼ì¸ì— ì ‘ì†í•˜ê¸° 위해 로그ì¸í•´ì•¼ 하는 Wi-Fi í¬í„¸ì„ 사용하면 ì´ ì˜¤ë¥˜ê°€ 표시ë©ë‹ˆë‹¤.&lt;/p&gt;
&lt;p&gt;오류를 수정하려면 열려는 페ì´ì§€ì—ì„œ &lt;strong&gt;ì—°ê²°&lt;/strong&gt;ì„ í´ë¦­í•˜ì„¸ìš”.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">ì´ íŽ˜ì´ì§€ ë‚´ìš©:</translation>
<translation id="153384715582417236">새 콘í…츠 ì—†ìŒ</translation>
<translation id="1536390784834419204">페ì´ì§€ 번역</translation>
+<translation id="1539840569003678498">보고 날짜:</translation>
<translation id="154408704832528245">배달 주소 ì„ íƒ</translation>
<translation id="1549470594296187301">ì´ ê¸°ëŠ¥ì„ ì´ìš©í•˜ë ¤ë©´ ìžë°”스í¬ë¦½íŠ¸ë¥¼ 사용하ë„ë¡ ì„¤ì •í•´ì•¼ 합니다.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">ì§§ì€ ìª½ 먼저</translation>
<translation id="168693727862418163">ì´ ì •ì±… ê°’ì€ ìŠ¤í‚¤ë§ˆì— ëŒ€í•´ ìœ íš¨ì„±ì´ í™•ì¸ë˜ì§€ 않았으므로 무시ë©ë‹ˆë‹¤.</translation>
<translation id="168841957122794586">서버 ì¸ì¦ì„œì— ì•ˆì „ì„±ì´ ë‚®ì€ ì•”í˜¸í™” 키가 í¬í•¨ë˜ì–´ 있습니다.</translation>
+<translation id="1696290444144917273">ê°€ìƒ ì¹´ë“œ 세부정보 보기</translation>
<translation id="1697532407822776718">설정 완료</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{ì„œë²„ì˜ ë³´ì•ˆ ì¸ì¦ì„œê°€ ë‚´ì¼ ë°œíš¨ë  ì˜ˆì •ì´ë©° ì´ì— ë”°ë¼ <ph name="DOMAIN" />ìž„ì„ ìž…ì¦í•  수 없습니다. 서버를 잘못 설정했거나 불법 사용ìžê°€ ì—°ê²°ì„ ê°€ë¡œì±„ê³  있기 ë•Œë¬¸ì¼ ìˆ˜ 있습니다.}other{ì„œë²„ì˜ ë³´ì•ˆ ì¸ì¦ì„œê°€ #ì¼ í›„ ë°œíš¨ë  ì˜ˆì •ì´ë©° ì´ì— ë”°ë¼ <ph name="DOMAIN" />ìž„ì„ ìž…ì¦í•  수 없습니다. 서버를 잘못 설정했거나 불법 사용ìžê°€ ì—°ê²°ì„ ê°€ë¡œì±„ê³  있기 ë•Œë¬¸ì¼ ìˆ˜ 있습니다.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> ì •ì±…ì´ <ph name="VALUE" /> 값으로 설정ë˜ì–´ 있지 ì•Šì•„ 무시ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
<translation id="1712552549805331520"><ph name="URL" />ì—ì„œ 로컬 ì»´í“¨í„°ì— ë°ì´í„°ë¥¼ ì˜êµ¬ 저장하려고 합니다</translation>
<translation id="1713628304598226412">íŠ¸ë ˆì´ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">ë©”ì¼ë°•ìŠ¤ 3</translation>
<translation id="1718029547804390981">문서가 너무 커서 주ì„ì„ ë‹¬ 수 없습니다.</translation>
<translation id="1721424275792716183">* 필수 입력란</translation>
+<translation id="1727613060316725209">ì¸ì¦ì„œê°€ 유효함</translation>
<translation id="1727741090716970331">유효한 카드 번호 추가</translation>
<translation id="1728677426644403582">웹페ì´ì§€ 소스를 보는 중</translation>
<translation id="173080396488393970">ì´ ìœ í˜•ì˜ ì¹´ë“œëŠ” 지ì›ë˜ì§€ 않습니다.</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Windows ë„¤íŠ¸ì›Œí¬ ì§„ë‹¨ í”„ë¡œê·¸ëž¨ì„ ì‹¤í–‰<ph name="END_LINK" />í•´ 보세요.</translation>
<translation id="1772163372082567643">ëŒ€ìƒ ì„œë²„ì¸ <ph name="ORIGIN" />ì—ì„œ í—¤ë”를 설정하여 서버로 전송ë˜ëŠ” 모든 ìš”ì²­ì— ì¶œì²˜ ì •ì±…ì„ ì ìš©í•˜ë„ë¡ ìš”ì²­í–ˆìŠµë‹ˆë‹¤. 하지만 í—¤ë”ì˜ í˜•ì‹ì´ 잘못ë˜ì–´ 브ë¼ìš°ì €ì—ì„œ <ph name="SITE" />ì— ê´€í•œ ìš”ì²­ì„ ì²˜ë¦¬í•  수 없습니다. 사ì´íŠ¸ ìš´ì˜ìžëŠ” 출처 ì •ì±…ì„ ì‚¬ìš©í•´ 사ì´íŠ¸ì˜ 보안 ë° ê¸°íƒ€ ì†ì„±ì„ 구성할 수 있습니다.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">ë™ê¸°í™” 암호를 ì—…ë°ì´íŠ¸í•˜ì„¸ìš”.</translation>
<translation id="1787142507584202372">열린 íƒ­ì´ ì—¬ê¸°ì— í‘œì‹œë©ë‹ˆë‹¤.</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, 여러 ìž‘ì—… ì´ìš© 가능, Tabì„ ëˆŒëŸ¬ ìž‘ì—… 둘러보기</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">ê´‘ê³ </translation>
<translation id="1919367280705858090">특정 오류 ë©”ì‹œì§€ì— ê´€í•œ ë„ì›€ë§ ë³´ê¸°</translation>
<translation id="192020519938775529">{COUNT,plural, =0{ì—†ìŒ}=1{사ì´íŠ¸ 1ê°œ}other{사ì´íŠ¸ #ê°œ}}</translation>
+<translation id="1924727005275031552">새로운 주소</translation>
<translation id="1945968466830820669">ì¡°ì§ì˜ ê³„ì •ì— ì•¡ì„¸ìŠ¤í•  수 없게 ë˜ê±°ë‚˜ ì‹ ì› ë„ìš©ì´ ë°œìƒí•  ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤. 지금 비밀번호를 변경하는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤.</translation>
<translation id="1947454675006758438">오른쪽 ìƒë‹¨ 스테ì´í”Œ</translation>
<translation id="1958218078413065209">최고 ì ìˆ˜ëŠ” <ph name="SCORE" />ì ìž…니다.</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">íŠ¸ë ˆì´ 7</translation>
<translation id="204357726431741734">Google ê³„ì •ì— ì €ìž¥ëœ ë¹„ë°€ë²ˆí˜¸ë¥¼ 사용하여 로그ì¸</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" />ë¡œ ëœ íŽ˜ì´ì§€ë¥¼ 번역하지 않습니다.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{ì´ ì»¨íŠ¸ë¡¤ì´ ì‚¬ìš© 설정ë˜ì–´ 있고 무료 ì²´í—˜ì´ ì œê³µë˜ëŠ” 경우 Chromeì´ ê¸°ê¸° 사용ìžì˜ 최근 íƒìƒ‰ 활ë™ê³¼ 가장 유사한 ëŒ€ê·œëª¨ì˜ ì‚¬ìš©ìž ê·¸ë£¹, 즉 'ë™ì§ˆ 집단'ì„ ê²°ì •í•©ë‹ˆë‹¤. 광고주는 해당 ê·¸ë£¹ì— ê²Œìž¬í•  광고를 ì„ íƒí•  수 있으며 íƒìƒ‰ 활ë™ì€ ì‚¬ìš©ìž ê¸°ê¸°ì—ì„œ 비공개로 유지ë©ë‹ˆë‹¤. ê·¸ë£¹ì€ ë§¤ì¼ ì—…ë°ì´íŠ¸ë©ë‹ˆë‹¤.}=1{ì´ ì»¨íŠ¸ë¡¤ì´ ì‚¬ìš© 설정ë˜ì–´ 있고 무료 ì²´í—˜ì´ ì œê³µë˜ëŠ” 경우 Chromeì´ ê¸°ê¸° 사용ìžì˜ 최근 íƒìƒ‰ 활ë™ê³¼ 가장 유사한 ëŒ€ê·œëª¨ì˜ ì‚¬ìš©ìž ê·¸ë£¹, 즉 'ë™ì§ˆ 집단'ì„ ê²°ì •í•©ë‹ˆë‹¤. 광고주는 해당 ê·¸ë£¹ì— ê²Œìž¬í•  광고를 ì„ íƒí•  수 있으며 íƒìƒ‰ 활ë™ì€ ì‚¬ìš©ìž ê¸°ê¸°ì—ì„œ 비공개로 유지ë©ë‹ˆë‹¤. ê·¸ë£¹ì€ ë§¤ì¼ ì—…ë°ì´íŠ¸ë©ë‹ˆë‹¤.}other{ì´ ì»¨íŠ¸ë¡¤ì´ ì‚¬ìš© 설정ë˜ì–´ 있고 무료 ì²´í—˜ì´ ì œê³µë˜ëŠ” 경우 Chromeì´ ê¸°ê¸° 사용ìžì˜ 최근 íƒìƒ‰ 활ë™ê³¼ 가장 유사한 ëŒ€ê·œëª¨ì˜ ì‚¬ìš©ìž ê·¸ë£¹, 즉 'ë™ì§ˆ 집단'ì„ ê²°ì •í•©ë‹ˆë‹¤. 광고주는 해당 ê·¸ë£¹ì— ê²Œìž¬í•  광고를 ì„ íƒí•  수 있으며 íƒìƒ‰ 활ë™ì€ ì‚¬ìš©ìž ê¸°ê¸°ì—ì„œ 비공개로 유지ë©ë‹ˆë‹¤. ê·¸ë£¹ì€ {NUM_DAYS}ì¼ë§ˆë‹¤ ì—…ë°ì´íŠ¸ë©ë‹ˆë‹¤.}}</translation>
<translation id="2053553514270667976">우편번호</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{제안 1개}other{제안 #개}}</translation>
<translation id="2071692954027939183">ì•Œë¦¼ì„ í‰ì†Œì— 허용하지 않았기 ë•Œë¬¸ì— ì•Œë¦¼ì´ ìžë™ìœ¼ë¡œ 차단ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
<translation id="2079545284768500474">실행취소</translation>
<translation id="20817612488360358">시스템 프ë¡ì‹œ ì„¤ì •ì´ ì‚¬ìš©í•˜ë„ë¡ ì„¤ì •ë˜ì—ˆì§€ë§Œ ëª…ì‹œì  í”„ë¡ì‹œ ì„¤ì •ë„ ì§€ì •ë˜ì–´ 있습니다.</translation>
<translation id="2082238445998314030">전체 결과 <ph name="TOTAL_RESULTS" />개 중 <ph name="RESULT_NUMBER" />개</translation>
+<translation id="2085876078937250610">저장…</translation>
<translation id="2088086323192747268">ë™ê¸°í™” 관리 버튼, Enter를 눌러 Chrome 설정ì—ì„œ ë‚´ê°€ ë™ê¸°í™”하는 ì •ë³´ 관리</translation>
<translation id="2091887806945687916">소리</translation>
<translation id="2094505752054353250">ë„ë©”ì¸ì´ ì¼ì¹˜í•˜ì§€ ì•ŠìŒ</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" />ì— ì‚¬ìš©ìž ì´ë¦„ê³¼ 비밀번호를 입력해야 합니다.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, 만료ì¼: <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">관리ìžê°€ 제어하는 설정</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" />ì—ì„œ 페어ë§í•˜ë ¤ê³  함</translation>
<translation id="2344028582131185878">ìžë™ 다운로드</translation>
<translation id="2346319942568447007">복사한 ì´ë¯¸ì§€</translation>
<translation id="2354001756790975382">기타 ë¶ë§ˆí¬</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">공격ìžëŠ” 사용ìžê°€ ì´ ì‚¬ì´íŠ¸ì—ì„œ ë³´ê³  있는 ì´ë¯¸ì§€ë¥¼ ë³¼ 수 있으며 ì´ë¯¸ì§€ë¥¼ 수정하여 사용ìžë¥¼ ì†ì¼ 수 있습니다.</translation>
<translation id="2356070529366658676">확ì¸</translation>
<translation id="2357481397660644965">ë‚´ 기기는 <ph name="DEVICE_MANAGER" />ì—ì„œ 관리하며 ë‚´ ê³„ì •ì€ <ph name="ACCOUNT_MANAGER" />ì—ì„œ 관리합니다.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{1ì¼ ì´ë‚´}=1{1ì¼ í›„}other{{NUM_DAYS}ì¼ í›„}}</translation>
<translation id="2359629602545592467">복수</translation>
<translation id="2359808026110333948">계ì†</translation>
+<translation id="2359961752320758691">ê°€ìƒ ì¹´ë“œ 번호가 ì ìš©ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
<translation id="2367567093518048410">수준</translation>
<translation id="2372464001869762664">카드를 확ì¸í•˜ë©´ Google ê³„ì •ì˜ ì¹´ë“œ 세부정보가 ì´ ì‚¬ì´íŠ¸ì™€ 공유ë©ë‹ˆë‹¤. Plex 계정 세부정보ì—ì„œ CVC를 확ì¸í•˜ì„¸ìš”.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">사용할 수 없는 배송 방법입니다. 다른 ë°©ë²•ì„ ì„ íƒí•˜ì„¸ìš”.</translation>
<translation id="2396249848217231973">삭제 실행 취소(&amp;U)</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">ì´ì „</translation>
<translation id="2413528052993050574">ì´ ì„œë²„ê°€ <ph name="DOMAIN" />ìž„ì„ ìž…ì¦í•  수 없으며 ì„œë²„ì˜ ë³´ì•ˆ ì¸ì¦ì„œê°€ ì·¨ì†Œë  ìˆ˜ 있습니다. 서버를 잘못 설정했거나 불법 사용ìžê°€ ì—°ê²°ì„ ê°€ë¡œì±„ê³  있기 ë•Œë¬¸ì¼ ìˆ˜ 있습니다.</translation>
<translation id="2414886740292270097">어둡게</translation>
<translation id="2438874542388153331">오른쪽 4공 펀칭</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">오른쪽 하단 스테ì´í”Œ</translation>
<translation id="2523886232349826891">ì´ ê¸°ê¸°ì—만 저장ë¨</translation>
<translation id="2524461107774643265">ìžì„¸í•œ ì •ë³´ 추가</translation>
-<translation id="2526590354069164005">ë°ìŠ¤í¬í†±</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{외 1개}other{외 #개}}</translation>
<translation id="2536110899380797252">주소 추가</translation>
<translation id="2539524384386349900">ê°ì§€</translation>
+<translation id="2541219929084442027">ì‹œí¬ë¦¿ íƒ­ì„ ëª¨ë‘ ë‹«ìœ¼ë©´ ì‹œí¬ë¦¿ 탭ì—ì„œ 보는 페ì´ì§€ëŠ” 브ë¼ìš°ì €ì˜ 방문 기ë¡, 쿠키 저장소, 검색 ê¸°ë¡ ì–´ë””ì—ë„ ë‚¨ì§€ 않습니다. 단, 다운로드한 파ì¼ì´ë‚˜ ìƒì„±í•œ ë¶ë§ˆí¬ëŠ” 유지ë©ë‹ˆë‹¤.</translation>
<translation id="2544644783021658368">ë‹¨ì¼ ë¬¸ì„œ</translation>
<translation id="254947805923345898">ì •ì±… ê°’ì´ ìœ íš¨í•˜ì§€ 않습니다.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" />ì—ì„œ ìž˜ëª»ëœ ì‘ë‹µì„ ì „ì†¡í–ˆìŠµë‹ˆë‹¤.</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">Chromeì—ì„œ 가장 강력한 보안 ê¸°ëŠ¥ì„ ì‚¬ìš©í•˜ë ¤ë©´ <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />í–¥ìƒëœ 보호 모드를 사용 설정<ph name="END_ENHANCED_PROTECTION_LINK" />하세요.</translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" />ì˜ ì„œë²„ IP 주소를 ì°¾ì„ ìˆ˜ 없습니다.</translation>
<translation id="2639739919103226564">ìƒíƒœ:</translation>
+<translation id="264810637653812429">호환ë˜ëŠ” 기기가 없습니다.</translation>
<translation id="2649204054376361687"><ph name="COUNTRY" />, <ph name="CITY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome 설정ì—ì„œ 방문 기ë¡, 쿠키, ìºì‹œ ë“±ì„ ì‚­ì œí•˜ë ¤ë©´ Tabì„ ëˆ„ë¥¸ ë‹¤ìŒ Enter 누르기</translation>
<translation id="2650446666397867134">íŒŒì¼ ì•¡ì„¸ìŠ¤ 거부ë¨</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">다시 시작</translation>
<translation id="2803306138276472711">최근 Google 세ì´í”„ 브ë¼ìš°ì§•ì´ <ph name="SITE" />ì—ì„œ <ph name="BEGIN_LINK" />멀웨어를 ê°ì§€<ph name="END_LINK" />했습니다. í‰ì†Œì— 안전한 웹사ì´íŠ¸ë„ ë©€ì›¨ì–´ì— ê°ì—¼ë  때가 있습니다.</translation>
<translation id="2807052079800581569">ì´ë¯¸ì§€ Y 위치</translation>
+<translation id="2820957248982571256">검색 중...</translation>
<translation id="2824775600643448204">주소창 ë° ê²€ìƒ‰ì°½</translation>
<translation id="2826760142808435982">ì´ ì—°ê²°ì€ <ph name="CIPHER" />ì„(를) 사용하여 암호화ë˜ê³  ì¸ì¦ë˜ë©° <ph name="KX" />ì„(를) 키 êµí™˜ 매커니즘으로 사용합니다.</translation>
<translation id="2835170189407361413">ì„œì‹ ì§€ìš°ê¸°</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">Invite(봉투)</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="2859806420264540918">ì´ ì‚¬ì´íŠ¸ì—서는 ë°©í•´ê°€ ë˜ê±°ë‚˜ 사용ìžë¥¼ 현혹하는 광고를 표시합니다.</translation>
+<translation id="287596039013813457">친근함</translation>
+<translation id="2876489322757410363">ì‹œí¬ë¦¿ 모드를 종료하고 외부 애플리케ì´ì…˜ì—ì„œ 결제합니다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="2878197950673342043">í¬ìŠ¤í„° í´ë“œ</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">창 배치</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">C9(봉투)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Tabê³¼ Enter 키를 차례로 눌러 Chrome 설정ì—ì„œ 안전 í™•ì¸ ì‹¤í–‰</translation>
<translation id="3061707000357573562">서비스 패치</translation>
-<translation id="3064966200440839136">ì‹œí¬ë¦¿ 모드를 종료하고 외부 애플리케ì´ì…˜ì—ì„œ 결제합니다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="306573536155379004">ê²Œìž„ì´ ì‹œìž‘ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
<translation id="3080254622891793721">그래픽</translation>
<translation id="3086579638707268289">웹ìƒì˜ 활ë™ì´ 모니터ë§ë˜ê³  있ìŒ</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">ë‚´ ê³„ì •ì€ <ph name="MANAGER" />ì—ì„œ 관리합니다.</translation>
<translation id="3157931365184549694">복구</translation>
<translation id="3162559335345991374">사용 ì¤‘ì¸ Wi-Fiì—ì„œ ë¡œê·¸ì¸ íŽ˜ì´ì§€ ë°©ë¬¸ì„ ìš”ì²­í•  수 있습니다.</translation>
-<translation id="3167968892399408617">ì‹œí¬ë¦¿ íƒ­ì„ ëª¨ë‘ ë‹«ìœ¼ë©´ ì‹œí¬ë¦¿ 탭ì—ì„œ 보는 페ì´ì§€ëŠ” 브ë¼ìš°ì €ì˜ 방문 기ë¡, 쿠키 저장소, 검색 ê¸°ë¡ ì–´ë””ì—ë„ ë‚¨ì§€ 않습니다. 단, 다운로드한 파ì¼ì´ë‚˜ ìƒì„±í•œ ë¶ë§ˆí¬ëŠ” 유지ë©ë‹ˆë‹¤.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">섬</translation>
<translation id="3176929007561373547">프ë¡ì‹œ ì„¤ì •ì„ í™•ì¸í•˜ê±°ë‚˜ ë„¤íŠ¸ì›Œí¬ ê´€ë¦¬ìžì—게 문ì˜í•˜ì—¬
@@ -593,10 +608,12 @@
<translation id="3229041911291329567">기기와 브ë¼ìš°ì €ì— 관한 버전 ì •ë³´</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> ì¹´ë“œì˜ CVC를 입력하세요.</translation>
<translation id="3234666976984236645">ì´ ì‚¬ì´íŠ¸ì—ì„œ 중요한 콘í…츠 í•­ìƒ ê°ì§€</translation>
+<translation id="3249845759089040423">그루브</translation>
<translation id="3252266817569339921">프랑스어</translation>
<translation id="3266793032086590337">ê°’(충ëŒ)</translation>
<translation id="3268451620468152448">열린 탭</translation>
<translation id="3270847123878663523">재정렬 실행 취소(&amp;U)</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" />ì—ì„œ 연결하려고 함</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552"><ph name="ENROLLMENT_DOMAIN" /> ì¡°ì§ì—ì„œ ë‹¤ìŒ ì›¹ì‚¬ì´íŠ¸ë¡œ 설정 ë˜ëŠ” ì •ì±…ê³¼ ê°™ì€ ì •ë³´ë¥¼ 전송했습니다.</translation>
<translation id="3282497668470633863">ì¹´ë“œ ëª…ì˜ ì¶”ê°€</translation>
@@ -649,6 +666,7 @@
<translation id="3428151540071562330">하나 ì´ìƒì˜ DnsOverHttpsTemplates 서버 템플릿 URIê°€ 유효하지 ì•Šì•„ 앞으로 사용ë˜ì§€ 않습니다.</translation>
<translation id="3431636764301398940">ê¸°ê¸°ì— ì¹´ë“œ 저장</translation>
<translation id="3432601291244612633">페ì´ì§€ 닫기</translation>
+<translation id="3435738964857648380">보안</translation>
<translation id="3435896845095436175">사용</translation>
<translation id="3438829137925142401">Google ê³„ì •ì— ì €ìž¥ëœ ë¹„ë°€ë²ˆí˜¸ 사용</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -691,7 +709,10 @@
<translation id="3584299510153766161">하단 2공 펀칭</translation>
<translation id="3586931643579894722">세부정보 숨기기</translation>
<translation id="3587738293690942763">보통</translation>
+<translation id="3590643883886679995">ì‹œí¬ë¦¿ 모드를 종료한 후 ë¡œê·¸ì¸ ë°ì´í„°ê°€ ê¸°ê¸°ì— ì €ìž¥ë©ë‹ˆë‹¤.</translation>
+<translation id="359126217934908072">ì›”/ì—°ë„:</translation>
<translation id="3592413004129370115">Italian(봉투)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{언제든지 ê·¸ë£¹ì„ ìž¬ì„¤ì •í•  수 있습니다. 새 ê·¸ë£¹ì— ì°¸ì—¬í•˜ëŠ” ë° í•˜ë£¨ ì •ë„ê°€ 소요ë©ë‹ˆë‹¤.}=1{언제든지 ê·¸ë£¹ì„ ìž¬ì„¤ì •í•  수 있습니다. 새 ê·¸ë£¹ì— ì°¸ì—¬í•˜ëŠ” ë° í•˜ë£¨ ì •ë„ê°€ 소요ë©ë‹ˆë‹¤.}other{언제든지 ê·¸ë£¹ì„ ìž¬ì„¤ì •í•  수 있습니다. 새 ê·¸ë£¹ì— ì°¸ì—¬í•˜ëŠ” ë° {NUM_DAYS}ì¼ì´ 소요ë©ë‹ˆë‹¤.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">관리ìžê°€ 차단한 애플리케ì´ì…˜</translation>
<translation id="3608932978122581043">ì¢…ì´ ê³µê¸‰ ë°©í–¥</translation>
@@ -700,13 +721,13 @@
<translation id="3615877443314183785">올바른 만료ì¼ì„ 입력하세요.</translation>
<translation id="36224234498066874">ì¸í„°ë„· 사용 ê¸°ë¡ ì‚­ì œ...</translation>
<translation id="362276910939193118">방문 ê¸°ë¡ ì „ì²´ 보기</translation>
-<translation id="3625635938337243871">ë¡œê·¸ì¸ ë°ì´í„°ëŠ” ì‹œí¬ë¦¿ 모드를 종료한 후ì—ë„ ê¸°ê¸°ì— ì €ìž¥ë©ë‹ˆë‹¤.</translation>
<translation id="3630155396527302611">ì´ë¯¸ ë„¤íŠ¸ì›Œí¬ ì•¡ì„¸ìŠ¤ê°€ í—ˆìš©ëœ í”„ë¡œê·¸ëž¨ìœ¼ë¡œ ë˜ì–´ 있는 경우
목ë¡ì—ì„œ 삭제한 ë’¤ 다시 추가합니다.</translation>
<translation id="3630699740441428070">ì´ ê¸°ê¸°ì˜ ê´€ë¦¬ìžê°€ ë„¤íŠ¸ì›Œí¬ ì—°ê²°ì„ êµ¬ì„±í–ˆìœ¼ë©°, ì´ë¥¼ 통해 ë‚´ê°€ 방문한 웹사ì´íŠ¸ë¥¼ í¬í•¨í•œ ë„¤íŠ¸ì›Œí¬ íŠ¸ëž˜í”½ì„ ê´€ë¦¬ìžê°€ 확ì¸í•  수 있습니다.</translation>
<translation id="3631244953324577188">ìƒì²´ ì¸ì‹</translation>
<translation id="3633738897356909127">Chrome ì—…ë°ì´íŠ¸ 버튼, Chrome 설정ì—ì„œ Chromeì„ ì—…ë°ì´íŠ¸í•˜ë ¤ë©´ Enter 누르기</translation>
<translation id="3634530185120165534">íŠ¸ë ˆì´ 5</translation>
+<translation id="3637662659967048211">Google ê³„ì •ì— ì €ìž¥</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">애플리케ì´ì…˜:</translation>
<translation id="3650584904733503804">유효성 검사 성공</translation>
@@ -747,6 +768,7 @@
<translation id="3781428340399460090">진한 분í™ìƒ‰</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">블루투스 장치</translation>
+<translation id="3787675388804467730">ê°€ìƒ ì¹´ë“œ 번호</translation>
<translation id="3787705759683870569">만료: <ph name="EXPIRATION_YEAR" />년 <ph name="EXPIRATION_MONTH" />월</translation>
<translation id="3789155188480882154">í¬ê¸° 16</translation>
<translation id="3789841737615482174">설치</translation>
@@ -766,6 +788,7 @@
<translation id="3841184659773414994">íŒŒì¼ í•¸ë“¤ëŸ¬</translation>
<translation id="385051799172605136">뒤로</translation>
<translation id="3858027520442213535">시간과 날짜 ì—…ë°ì´íŠ¸</translation>
+<translation id="3881478300875776315">ìžë§‰ 접기</translation>
<translation id="3884278016824448484">기기 ì‹ë³„ìž ì¶©ëŒ</translation>
<translation id="3885155851504623709">êµêµ¬</translation>
<translation id="388632593194507180">ëª¨ë‹ˆí„°ë§ ê°ì§€ë¨</translation>
@@ -791,6 +814,7 @@
<translation id="397105322502079400">계산 중...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" />ì´(ê°€) 차단ë¨</translation>
<translation id="3973357910713125165">Chrome 안전 í™•ì¸ ì‹¤í–‰ 버튼, Enter 키를 눌러 Chrome 설정ì—ì„œ 안전 í™•ì¸ ì‹¤í–‰</translation>
+<translation id="3986705137476756801">지금 실시간 ìžë§‰ 사용 중지하기</translation>
<translation id="3987405730340719549">Chromeì—ì„œ ì´ ì‚¬ì´íŠ¸ê°€ 허위 ë˜ëŠ” 사기성 사ì´íŠ¸ì¼ 수 있다고 íŒë‹¨í–ˆìŠµë‹ˆë‹¤.
ì´ ë©”ì‹œì§€ê°€ 실수로 표시ë˜ì—ˆë‹¤ê³  ìƒê°ëœë‹¤ë©´ ë‹¤ìŒ íŽ˜ì´ì§€ë¥¼ 방문해 주시기 ë°”ëžë‹ˆë‹¤. https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -882,13 +906,14 @@
<translation id="4275830172053184480">기기 다시 시작</translation>
<translation id="4277028893293644418">비밀번호 재설정</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ë‹¤ìŒ ì¹´ë“œê°€ Google ê³„ì •ì— ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.}other{ë‹¤ìŒ ì¹´ë“œê°€ Google ê³„ì •ì— ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.}}</translation>
+<translation id="4287885627794386150">무료 ì²´í—˜ì„ ì´ìš©í•  수 있으나 활성화ë˜ì–´ 있지 ì•ŠìŒ</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> 페ì´ì§€ 미리보기 ì´ë¯¸ì§€</translation>
<translation id="42981349822642051">펼치기</translation>
<translation id="4300675098767811073">오른쪽 다공 펀칭</translation>
<translation id="4302514097724775343">플레ì´í•˜ë ¤ë©´ ê³µë£¡ì„ íƒ­í•˜ì„¸ìš”.</translation>
<translation id="4302965934281694568">Chou3(봉투)</translation>
<translation id="4305666528087210886">파ì¼ì— 액세스할 수 ì—†ìŒ</translation>
-<translation id="4305817255990598646">전환</translation>
+<translation id="4306529830550717874">주소를 저장하시겠습니까?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">차단(기본값)</translation>
<translation id="4314815835985389558">ë™ê¸°í™” 관리</translation>
@@ -915,6 +940,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" />ì— ì ‘ì†í•˜ë ¤ 했으나 발행기관ì—ì„œ 서버가 전달한 ì¸ì¦ì„œë¥¼ í기했습니다. ì´ëŠ” 서버가 제시한 보안 ìžê²©ì¦ëª… 정보를 신뢰할 수 ì—†ìŒì„ ì˜ë¯¸í•©ë‹ˆë‹¤. 사용ìžëŠ” 현재 공격ìžì™€ 통신 ì¤‘ì¼ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤.</translation>
<translation id="4378154925671717803">전화기</translation>
<translation id="4390472908992056574">브림</translation>
+<translation id="4406883609789734330">실시간 ìžë§‰</translation>
<translation id="4406896451731180161">검색결과</translation>
<translation id="4408413947728134509">쿠키 <ph name="NUM_COOKIES" />개</translation>
<translation id="4414290883293381923">사기성 사ì´íŠ¸ì— 비밀번호를 입력했습니다. 지금 바로 <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> 등 ë™ì¼í•œ 비밀번호를 사용한 사ì´íŠ¸ë¡œ ì´ë™í•˜ì—¬ 비밀번호를 변경하시기 ë°”ëžë‹ˆë‹¤.</translation>
@@ -927,7 +953,6 @@
<translation id="4435702339979719576">엽서)</translation>
<translation id="443673843213245140">프ë¡ì‹œ ì‚¬ìš©ì€ ì¤‘ì§€ë˜ì—ˆì§€ë§Œ ëª…ì‹œì  í”„ë¡ì‹œ ì„¤ì •ì´ ì§€ì •ë˜ì–´ 있습니다.</translation>
<translation id="4464826014807964867">ì¡°ì§ì˜ ì •ë³´ê°€ í¬í•¨ëœ 웹사ì´íŠ¸</translation>
-<translation id="4466881336512663640">ì–‘ì‹ì—ì„œ 변경한 ì‚¬í•­ì´ ì‚­ì œë©ë‹ˆë‹¤. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="4476953670630786061">안전하지 ì•Šì€ ì–‘ì‹ìž…니다. ìžë™ ì™„ì„±ì´ ì‚¬ìš© 중지ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
<translation id="4477350412780666475">ë‹¤ìŒ íŠ¸ëž™</translation>
<translation id="4482953324121162758">ì´ ì‚¬ì´íŠ¸ëŠ” 번역ë˜ì§€ 않습니다.</translation>
@@ -961,6 +986,7 @@
<translation id="4594403342090139922">삭제 실행 취소(&amp;U)</translation>
<translation id="4597348597567598915">í¬ê¸° 8</translation>
<translation id="4600854749408232102">C6/C5(봉투)</translation>
+<translation id="4606870351894164739">강렬함</translation>
<translation id="4628948037717959914">사진</translation>
<translation id="4631649115723685955">ìºì‹œë°± ì—°ê²°ë¨</translation>
<translation id="4636930964841734540">ì •ë³´</translation>
@@ -980,6 +1006,7 @@
<translation id="4691835149146451662">Architecture-A(봉투)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">사ì´ë“œ</translation>
+<translation id="4702656508969495934">실시간 ìžë§‰ 표시, ì°½ 전환 ë„구를 사용하여 í¬ì»¤ìŠ¤ 설정</translation>
<translation id="4708268264240856090">ì—°ê²°ì´ ëŠê¹€</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows ë„¤íŠ¸ì›Œí¬ ì§„ë‹¨ 프로그램 실행<ph name="END_LINK" /></translation>
@@ -993,6 +1020,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> 추천 검색어</translation>
<translation id="4742407542027196863">비밀번호 관리...</translation>
<translation id="4744603770635761495">실행 가능 경로</translation>
+<translation id="4749011317274908093">ì‹œí¬ë¦¿ 모드로 전환ë¨</translation>
<translation id="4750917950439032686">비밀번호나 ì‹ ìš©ì¹´ë“œ 번호 ë“±ì˜ ì •ë³´ëŠ” 비공개 ìƒíƒœë¡œ ì´ ì‚¬ì´íŠ¸ì— 전송ë©ë‹ˆë‹¤.</translation>
<translation id="4756388243121344051">방문 기ë¡(&amp;H)</translation>
<translation id="4758311279753947758">ì—°ë½ì²˜ ì •ë³´ 추가</translation>
@@ -1022,6 +1050,8 @@
<translation id="4813512666221746211">ë„¤íŠ¸ì›Œí¬ ì˜¤ë¥˜</translation>
<translation id="4816492930507672669">페ì´ì§€ 맞춤</translation>
<translation id="4819347708020428563">기본 ë·°ì—ì„œ 주ì„ì„ ìˆ˜ì •í• ê¹Œìš”?</translation>
+<translation id="4825507807291741242">강력함</translation>
+<translation id="4838327282952368871">꿈</translation>
<translation id="484462545196658690">ìžë™</translation>
<translation id="4850886885716139402">보기</translation>
<translation id="485316830061041779">ë…ì¼ì–´</translation>
@@ -1158,6 +1188,7 @@
<translation id="5314967030527622926">ì†Œì±…ìž ì œìž‘ê¸°</translation>
<translation id="5316812925700871227">반시계 방향으로 회전</translation>
<translation id="5317780077021120954">저장</translation>
+<translation id="5321288445143113935">최대화</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" />/<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">ì—°ë½ì²˜ ì •ë³´ ì„ íƒ</translation>
<translation id="5327248766486351172">ì´ë¦„</translation>
@@ -1165,11 +1196,13 @@
<translation id="5332219387342487447">배송 방법</translation>
<translation id="5333022057423422993">방금 사용한 비밀번호가 ì •ë³´ 유출로 ì¸í•´ ë…¸ì¶œëœ ê²ƒìœ¼ë¡œ 확ì¸ë©ë‹ˆë‹¤. ê³„ì •ì„ ë³´í˜¸í•˜ë ¤ë©´ ì €ìž¥ëœ ë¹„ë°€ë²ˆí˜¸ë¥¼ 확ì¸í•´ 보시기 ë°”ëžë‹ˆë‹¤.</translation>
<translation id="5334013548165032829">세부 시스템 로그</translation>
+<translation id="5334145288572353250">주소를 저장하시겠습니까?</translation>
<translation id="5340250774223869109">애플리케ì´ì…˜ì´ 차단ë¨</translation>
<translation id="534295439873310000">NFC 기기</translation>
<translation id="5344579389779391559">ì´ íŽ˜ì´ì§€ì—ì„œ ê¸ˆì•¡ì„ ì²­êµ¬í•  수 있습니다.</translation>
<translation id="5355557959165512791">ì¸ì¦ì„œê°€ 취소ë˜ì—ˆê¸° ë•Œë¬¸ì— í˜„ìž¬ <ph name="SITE" />ì— ë°©ë¬¸í•  수 없습니다. ë„¤íŠ¸ì›Œí¬ ì˜¤ë¥˜ì™€ ê³µê²©ì€ ëŒ€ë¶€ë¶„ ì¼ì‹œì ì´ë¯€ë¡œ ë‚˜ì¤‘ì— ì´ íŽ˜ì´ì§€ê°€ ì •ìƒì ìœ¼ë¡œ ìž‘ë™í•  수 있습니다.</translation>
<translation id="536296301121032821">정책 설정 저장 실패</translation>
+<translation id="5363309033720083897">관리ìžê°€ 허용한 ì§ë ¬ í¬íŠ¸</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="5386426401304769735">ì´ ì‚¬ì´íŠ¸ì˜ ì¸ì¦ì„œ ì²´ì¸ì€ SHA-1ì„ ì‚¬ìš©í•˜ì—¬ ì„œëª…ëœ ì¸ì¦ì„œë¥¼ í¬í•¨í•©ë‹ˆë‹¤.</translation>
@@ -1178,6 +1211,7 @@
<translation id="5398772614898833570">ê´‘ê³  차단ë¨</translation>
<translation id="5400836586163650660">그레ì´</translation>
<translation id="540969355065856584">ì´ ì„œë²„ê°€ <ph name="DOMAIN" />ìž„ì„ ìž…ì¦í•  수 없습니다. ì„œë²„ì˜ ë³´ì•ˆ ì¸ì¦ì„œê°€ 현재 유효하지 않습니다. 서버를 잘못 설정했거나 공격ìžê°€ ì—°ê²°ì„ ê°€ë¡œì±„ê³  있기 ë•Œë¬¸ì¼ ìˆ˜ 있습니다.</translation>
+<translation id="541143247543991491">í´ë¼ìš°ë“œ(시스템 ì „ì²´)</translation>
<translation id="541416427766103491">스태커 4</translation>
<translation id="5421136146218899937">ì¸í„°ë„· 사용 ê¸°ë¡ ì‚­ì œ...</translation>
<translation id="5426179911063097041"><ph name="SITE" />ì—ì„œ ì•Œë¦¼ì„ ë³´ë‚´ë ¤ê³  합니다.</translation>
@@ -1191,6 +1225,7 @@
<translation id="5455374756549232013">ìž˜ëª»ëœ ì •ì±… 타임스탬프</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" />개}other{<ph name="CONTACT_PREVIEW" /> 외 <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />개}}</translation>
+<translation id="5463625433003343978">기기를 찾는 중...</translation>
<translation id="5469868506864199649">ì´íƒˆë¦¬ì•„ì–´</translation>
<translation id="5470861586879999274">수정 다시 실행(&amp;R)</translation>
<translation id="5478437291406423475">B6/C4(봉투)</translation>
@@ -1240,7 +1275,6 @@
<translation id="5624120631404540903">비밀번호 관리</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="563324245173044180">사기성 콘í…츠 차단ë¨</translation>
<translation id="5644090287519800334">첫 번째 ë©´ ì´ë¯¸ì§€ X 시프트</translation>
@@ -1279,12 +1313,12 @@
<translation id="5785756445106461925">ë˜í•œ ì´ íŽ˜ì´ì§€ì—는 안전하지 ì•Šì€ ë‹¤ë¥¸ 리소스가 í¬í•¨ë˜ì–´ 있습니다. ì´ëŸ¬í•œ 리소스는 전송 ì¤‘ì— ë‹¤ë¥¸ ì‚¬ëžŒì´ ë³¼ 수 있으며 페ì´ì§€ì˜ ëª¨ì–‘ì„ ë³€ê²½í•˜ê¸° 위해 공격ìžê°€ 수정할 수 있습니다.</translation>
<translation id="5786044859038896871">카드 정보를 입력하시겠습니까?</translation>
<translation id="578633867165174378">방금 사용한 비밀번호가 ì •ë³´ 유출로 ì¸í•´ ë…¸ì¶œëœ ê²ƒìœ¼ë¡œ 확ì¸ë©ë‹ˆë‹¤. 지금 바로 비밀번호를 변경하시기 ë°”ëžë‹ˆë‹¤.</translation>
-<translation id="5798290721819630480">ë³€ê²½ì‚¬í•­ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" />ì„(를) 입력하시겠습니까?</translation>
<translation id="5804241973901381774">권한</translation>
<translation id="5804427196348435412">NFC 기기 사용</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" />ì— ëŒ€í•œ ì—°ê²°ì´ ë” ì´ìƒ 사용ë˜ì§€ 않는 암호화 ê¸°ìˆ ì„ ì‚¬ìš©í•˜ì—¬ 암호화ë©ë‹ˆë‹¤.</translation>
<translation id="5813119285467412249">추가 다시 실행(&amp;R)</translation>
+<translation id="5817918615728894473">페어ë§</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{결제하면 ì´ ì¹´ë“œë¡œ 청구ë˜ì§€ë§Œ 실제 ì¹´ë“œ 번호는 사ì´íŠ¸ì™€ 공유ë˜ì§€ 않습니다. 보안 강화를 위해 ìž„ì‹œ CVCê°€ ìƒì„±ë©ë‹ˆë‹¤.}other{결제하면 ì„ íƒí•œ 카드로 청구ë˜ì§€ë§Œ 실제 ì¹´ë“œ 번호는 사ì´íŠ¸ì™€ 공유ë˜ì§€ 않습니다. 보안 강화를 위해 ìž„ì‹œ CVCê°€ ìƒì„±ë©ë‹ˆë‹¤.}}</translation>
<translation id="5826507051599432481">ì¼ë°˜ ì´ë¦„(CN)</translation>
<translation id="5838278095973806738">ì´ ì‚¬ì´íŠ¸ì— 입력하는 비밀번호나 ì‹ ìš©ì¹´ë“œ 번호 ë“±ì˜ ì •ë³´ê°€ 공격ìžì— ì˜í•´ ë„ìš©ë  ìˆ˜ 있습니다.</translation>
@@ -1292,6 +1326,7 @@
<translation id="5855253129151731373">사ì´íŠ¸ì˜ 호스트 ì´ë¦„ì´ <ph name="LOOKALIKE_DOMAIN" />ê³¼(와) 유사합니다. ì¼ë¶€ 공격ìžëŠ” ë„ë©”ì¸ ì´ë¦„ì„ ì•Œì•„ì±„ê¸° 어려울 ì •ë„ë¡œ 약간 변경하여 다른 사ì´íŠ¸ë¥¼ 모방합니다.
ì´ ë©”ì‹œì§€ê°€ 실수로 표시ë˜ì—ˆë‹¤ê³  ìƒê°ëœë‹¤ë©´ ë‹¤ìŒ íŽ˜ì´ì§€ë¥¼ 방문해 주시기 ë°”ëžë‹ˆë‹¤. https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">사용 안함</translation>
<translation id="5862579898803147654">스태커 8</translation>
<translation id="5863847714970149516">방문하려는 페ì´ì§€ì—ì„œ ê¸ˆì•¡ì„ ì²­êµ¬í•  수 있습니다.</translation>
<translation id="5866257070973731571">전화번호 추가</translation>
@@ -1308,6 +1343,7 @@
<translation id="5913377024445952699">화면 캡처가 ì¼ì‹œì¤‘지ë¨</translation>
<translation id="59174027418879706">사용 가능</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1개 사용 중}other{#개 사용 중}}</translation>
<translation id="5921185718311485855">사용</translation>
<translation id="5921639886840618607">카드를 Google ê³„ì •ì— ì €ìž¥í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="5922853866070715753">ê±°ì˜ ì™„ë£Œë˜ì—ˆìŠµë‹ˆë‹¤</translation>
@@ -1327,6 +1363,7 @@
<translation id="5989320800837274978">ê³ ì • 프ë¡ì‹œ 서버와 .pac 스í¬ë¦½íŠ¸ URLì´ ëª¨ë‘ ì§€ì •ë˜ì§€ 않았습니다.</translation>
<translation id="5992691462791905444">ì—”ì§€ë‹ˆì–´ë§ Z í´ë“œ</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' 검색결과 <ph name="RESULT_COUNT" />개</translation>
+<translation id="6006484371116297560">기본</translation>
<translation id="6008122969617370890">N-to-1 순서</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">비밀번호 확ì¸</translation>
@@ -1348,6 +1385,7 @@
<translation id="6045164183059402045">ì ìš© 템플릿</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="6049004884579590341">ì „ì²´í™”ë©´ì„ ì¢…ë£Œí•˜ë ¤ë©´ |<ph name="ACCELERATOR" />|ì„(를) 길게 누르기</translation>
<translation id="6049488691372270142">페ì´ì§€ 제공</translation>
<translation id="6051221802930200923">현재 <ph name="SITE" />ì—ì„œ ì¸ì¦ì„œ ê³ ì •ì„ ì‚¬ìš©í•˜ê¸° ë•Œë¬¸ì— ë°©ë¬¸í•  수 없습니다. ë„¤íŠ¸ì›Œí¬ ì˜¤ë¥˜ì™€ ê³µê²©ì€ ëŒ€ë¶€ë¶„ ì¼ì‹œì ì´ë¯€ë¡œ ë‚˜ì¤‘ì— ì´ íŽ˜ì´ì§€ê°€ ì •ìƒì ìœ¼ë¡œ ìž‘ë™í•  수 있습니다.</translation>
<translation id="6051898664905071243">페ì´ì§€ 수:</translation>
@@ -1364,6 +1402,7 @@
<translation id="610911394827799129">Google ê³„ì •ì˜ ë‚´ 활ë™(<ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />)ì—는 ì¸í„°ë„· 방문 기ë¡ì´ 다른 형ì‹ìœ¼ë¡œ 남아 ìžˆì„ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤</translation>
<translation id="6116338172782435947">í´ë¦½ë³´ë“œì— ë³µì‚¬ëœ í…스트 ë° ì´ë¯¸ì§€ë¥¼ 확ì¸í•©ë‹ˆë‹¤.</translation>
<translation id="6120179357481664955">UPI ID를 저장하시겠습니까?</translation>
+<translation id="6123290840358279103">ê°€ìƒ ì¹´ë“œ 보기</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">ì¼€ì´ë¸”ì„ í™•ì¸í•˜ê³  사용 ì¤‘ì¸ ë¼ìš°í„°, 모뎀 ë˜ëŠ” 기타 ë„¤íŠ¸ì›Œí¬ ê¸°ê¸°ë¥¼
재부팅하시기 ë°”ëžë‹ˆë‹¤.</translation>
@@ -1400,6 +1439,7 @@
<translation id="6289939620939689042">페ì´ì§€ 색ìƒ</translation>
<translation id="6290238015253830360">추천 콘í…츠가 ì—¬ê¸°ì— í‘œì‹œë©ë‹ˆë‹¤.</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chromeì˜ Google 어시스턴트 중지하는 중</translation>
<translation id="6305205051461490394"><ph name="URL" />ì— ì—°ê²°í•  수 없습니다.</translation>
<translation id="6312113039770857350">웹페ì´ì§€ë¥¼ 사용할 수 ì—†ìŒ</translation>
@@ -1425,6 +1465,7 @@
<translation id="6390200185239044127">Z í´ë“œ 하프</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">ê´€ë¦¬ìž ì •ì±…ì— ì˜í•´ <ph name="ORIGIN_NAME" />ì—ì„œ ì´ ìœ„ì¹˜ë¡œ 붙여넣는 ìž‘ì—…ì´ ì°¨ë‹¨ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
+<translation id="6398765197997659313">전체화면 닫기</translation>
<translation id="6401136357288658127">ì§€ì› ì¤‘ë‹¨ëœ ì •ì±…ìž…ë‹ˆë‹¤. <ph name="NEW_POLICY" /> ì •ì±…ì„ ëŒ€ì‹  사용해야 합니다.</translation>
<translation id="6404511346730675251">ë¶ë§ˆí¬ 수정</translation>
<translation id="6406765186087300643">C0(봉투)</translation>
@@ -1437,7 +1478,6 @@
<translation id="6428450836711225518">전화번호 ì¸ì¦</translation>
<translation id="6433490469411711332">ì—°ë½ì²˜ ì •ë³´ 수정</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" />ì—ì„œ ì—°ê²°ì„ ê±°ë¶€í–ˆìŠµë‹ˆë‹¤.</translation>
-<translation id="6434309073475700221">삭제</translation>
<translation id="6440503408713884761">무시ë¨</translation>
<translation id="6443406338865242315">ë‚´ê°€ 설치한 확장 프로그램 ë° í”ŒëŸ¬ê·¸ì¸</translation>
<translation id="6446163441502663861">Kahu(봉투)</translation>
@@ -1480,6 +1520,7 @@
<translation id="6624427990725312378">ì—°ë½ì²˜ ì •ë³´</translation>
<translation id="6626291197371920147">유효한 카드 번호 추가</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> 검색</translation>
+<translation id="6630043285902923878">USB 기기를 찾는 중...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">삭제</translation>
@@ -1495,6 +1536,7 @@
<translation id="6671697161687535275">Chromiumì—ì„œ ìžë™ì™„성 항목 ì¶”ì²œì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="6685834062052613830">로그아웃 후 설정 완료</translation>
<translation id="6687335167692595844">글꼴 í¬ê¸° 요청ë¨</translation>
+<translation id="6688743156324860098">ì—…ë°ì´íŠ¸â€¦</translation>
<translation id="6689249931105087298">ìƒëŒ€ì ì´ë©° í‘ì  ë³´ì • í¬í•¨</translation>
<translation id="6689271823431384964">Google ê³„ì •ì— ë¡œê·¸ì¸ë˜ì–´ 있기 ë•Œë¬¸ì— Chromeì—ì„œ ê³„ì •ì— ì¹´ë“œë¥¼ 저장할지 묻는 메시지가 표시ë©ë‹ˆë‹¤. 설정ì—ì„œ ì´ ë™ìž‘ì„ ë³€ê²½í•  수 있습니다. ì¹´ë“œ ì†Œì§€ìž ì´ë¦„ì€ ê³„ì •ì—ì„œ 가져온 것입니다.</translation>
<translation id="6698381487523150993">ìƒì„±ë¨:</translation>
@@ -1510,6 +1552,7 @@
<translation id="6744009308914054259">ì—°ê²°ì„ ê¸°ë‹¤ë¦¬ëŠ” ë™ì•ˆ 다운로드ì—ì„œ 오프ë¼ì¸ 기사를 ì½ì„ 수 있습니다.</translation>
<translation id="6753269504797312559">ì •ì±… ê°’</translation>
<translation id="6757797048963528358">기기가 절전 모드 ìƒíƒœìž…니다.</translation>
+<translation id="6767985426384634228">주소를 ì—…ë°ì´íŠ¸í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="6768213884286397650">Hagaki(엽서)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ë³´ë¼ìƒ‰</translation>
@@ -1532,6 +1575,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chromeì—ì„œ 페ì´ì§€ë¥¼ ì½ê¸° 쉽ë„ë¡ ê°„ì†Œí™”í–ˆìŠµë‹ˆë‹¤. Chromeì—ì„œ 안전하지 ì•Šì€ ì—°ê²°ì„ í†µí•´ ì›ë³¸ 페ì´ì§€ë¥¼ 가져왔습니다.</translation>
<translation id="6891596781022320156">ì •ì±… ìˆ˜ì¤€ì´ ì§€ì›ë˜ì§€ 않습니다.</translation>
+<translation id="6895143722905299846">ê°€ìƒ ë²ˆí˜¸:</translation>
<translation id="6895330447102777224">카드가 확ì¸ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
<translation id="6897140037006041989">ì‚¬ìš©ìž ì—ì´ì „트</translation>
<translation id="6898699227549475383">ì¡°ì§(O)</translation>
@@ -1567,10 +1611,10 @@
<translation id="7004583254764674281">Windows Hello를 사용하여 빠르게 ì¹´ë“œ 확ì¸</translation>
<translation id="7006930604109697472">무시하고 보내기</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">í¬ê¸° ì¡°ì ˆ 설정</translation>
<translation id="7014741021609395734">확대/축소 수준</translation>
<translation id="7016992613359344582">ì´ëŸ¬í•œ 금액 청구는 ì¼íšŒì„±ì´ê±°ë‚˜ 반복ì ì¼ 수 있으며 불분명한 ë°©ì‹ìœ¼ë¡œ ì´ë£¨ì–´ì§ˆ ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤.</translation>
<translation id="7029809446516969842">비밀번호</translation>
+<translation id="7030436163253143341">ì¸ì¦ì„œê°€ 올바르지 ì•ŠìŒ</translation>
<translation id="7031646650991750659">내가 설치한 Google Play 앱</translation>
<translation id="7050187094878475250"><ph name="DOMAIN" />ì— ì ‘ì†í•˜ë ¤ê³  했지만 서버가 제시한 ì¸ì¦ì„œì˜ 유효 ê¸°ê°„ì´ ë„ˆë¬´ 길어서 신뢰할 수 없습니다.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ì§€ê¸ˆì€ ì´ ì¹´ë“œë¥¼ 저장할 수 없습니다.}other{ì§€ê¸ˆì€ ì´ ì¹´ë“œë¥¼ 저장할 수 없습니다.}}</translation>
@@ -1640,12 +1684,14 @@
<translation id="7300012071106347854">코발트 녹색</translation>
<translation id="7302712225291570345">‘<ph name="TEXT" />’</translation>
<translation id="7304030187361489308">높ìŒ</translation>
+<translation id="7305756307268530424">ëŠë¦° ì†ë„ë¡œ 시작</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">ì—°ê²° ë„움ë§</translation>
<translation id="7323804146520582233">‘<ph name="SECTION" />’ 섹션 숨기기</translation>
<translation id="733354035281974745">기기 로컬 계정 재정ì˜</translation>
<translation id="7333654844024768166">사기성 사ì´íŠ¸ì— 비밀번호를 입력했습니다. 지금 바로 <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> 등 ë™ì¼í•œ 비밀번호를 사용한 사ì´íŠ¸ë¡œ ì´ë™í•˜ì—¬ 비밀번호를 변경하시기 ë°”ëžë‹ˆë‹¤.</translation>
<translation id="7334320624316649418">재정렬 다시 실행(&amp;R)</translation>
+<translation id="7337248890521463931">ìžë§‰ 펼치기</translation>
<translation id="7337706099755338005">사용 ì¤‘ì¸ í”Œëž«í¼ì—서는 제공ë˜ì§€ 않습니다.</translation>
<translation id="733923710415886693">서버 ì¸ì¦ì„œê°€ ì¸ì¦ì„œ 투명성 ì •ì±…ì„ ì‚¬ìš©í•˜ì—¬ 공개ë˜ì§€ 않았습니다.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1653,6 +1699,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">명령줄</translation>
<translation id="7359588939039777303">ê´‘ê³ ê°€ 차단ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
+<translation id="7363096869660964304">하지만 í”ì ì´ 아예 남지 않는 ê²ƒì€ ì•„ë‹™ë‹ˆë‹¤. ì‹œí¬ë¦¿ 모드로 íƒìƒ‰í•´ë„ 회사, ì¸í„°ë„· 서비스 제공업체 ë˜ëŠ” 방문한 웹사ì´íŠ¸ì— ì €ìž¥ëœ í”ì ê¹Œì§€ 없앨 수는 없습니다.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Tabì„ ëˆ„ë¥¸ ë‹¤ìŒ Enter를 눌러 Chrome 설정ì—ì„œ 주소 추가 ë° ê´€ë¦¬</translation>
<translation id="7365849542400970216">기기 사용 여부를 웹사ì´íŠ¸ì— 알리시겠습니까?</translation>
<translation id="7372973238305370288">검색결과</translation>
@@ -1663,7 +1710,9 @@
<translation id="7378594059915113390">미디어 컨트롤</translation>
<translation id="7378627244592794276">안함</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">해당 사항 ì—†ìŒ</translation>
<translation id="7390545607259442187">ì¹´ë“œ 확ì¸</translation>
+<translation id="7392089738299859607">주소 ì—…ë°ì´íŠ¸</translation>
<translation id="7399802613464275309">안전 확ì¸</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> 기기는 관리 ëŒ€ìƒ ê¸°ê¸°ìž…ë‹ˆë‹¤</translation>
@@ -1677,6 +1726,7 @@
&lt;li&gt;&lt;strong&gt;ì ìš©&lt;/strong&gt;ì„ í´ë¦­í•œ ë‹¤ìŒ &lt;strong&gt;확ì¸&lt;/strong&gt;ì„ í´ë¦­í•©ë‹ˆë‹¤.
&lt;li&gt;&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome ê³ ê°ì„¼í„°&lt;/a&gt;를 방문하여 컴퓨터ì—ì„œ 소프트웨어를 ì˜êµ¬ì ìœ¼ë¡œ 삭제하는 ë°©ë²•ì„ ì•Œì•„ë³´ì„¸ìš”. &lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">사랑스러움</translation>
<translation id="7416351320495623771">비밀번호 관리...</translation>
<translation id="7419106976560586862">프로필 경로</translation>
<translation id="7437289804838430631">ì—°ë½ì²˜ ì •ë³´ 추가</translation>
@@ -1692,7 +1742,7 @@
<translation id="7481312909269577407">앞으로</translation>
<translation id="7485870689360869515">ë°ì´í„° ì—†ìŒ</translation>
<translation id="7495528107193238112">ì´ ì½˜í…츠는 차단ë˜ì–´ 있습니다. 문제를 해결하려면 사ì´íŠ¸ 소유ìžì—게 문ì˜í•˜ì„¸ìš”.</translation>
-<translation id="7498234416455752244">ê³„ì† ìˆ˜ì •</translation>
+<translation id="7498193950643227031">앱 í¬ê¸°ë¥¼ 조절하면 예ìƒì¹˜ 못한 ë™ìž‘ì´ ë°œìƒí•  수 있습니다. ì´ì œ <ph name="SETTINGS" />ì—ì„œ 앱 í¬ê¸° ì¡°ì ˆ ê¸°ëŠ¥ì„ ì œí•œí•  수 있습니다.</translation>
<translation id="7503664977220660814">사기성 사ì´íŠ¸ì— 비밀번호를 입력했습니다. 지금 바로 <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> 등 ë™ì¼í•œ 비밀번호를 사용한 사ì´íŠ¸ì— ì €ìž¥ëœ ë¹„ë°€ë²ˆí˜¸ë¥¼ 확ì¸í•˜ëŠ” ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤.</translation>
<translation id="7508255263130623398">ë°˜í™˜ëœ ì •ì±… 기기 IDê°€ 비었거나 현재 기기 ID와 ì¼ì¹˜í•˜ì§€ ì•ŠìŒ</translation>
<translation id="7508870219247277067">ì•„ë³´ì¹´ë„ ë…¹ìƒ‰</translation>
@@ -1712,6 +1762,7 @@
<translation id="7548892272833184391">연결 문제해결</translation>
<translation id="7549584377607005141">ì´ ì›¹íŽ˜ì´ì§€ë¥¼ 제대로 표시하려면 ì´ì „ì— ìž…ë ¥í•œ ë°ì´í„°ê°€ 필요합니다. ì´ ë°ì´í„°ë¥¼ 다시 보낼 수 있지만 ì´ ê²½ìš° 해당 페ì´ì§€ì—ì„œ ì´ì „ì— ìˆ˜í–‰í•œ ìž‘ì—…ì´ ë°˜ë³µë©ë‹ˆë‹¤.</translation>
<translation id="7550637293666041147">기기 ì‚¬ìš©ìž ì´ë¦„ ë° Chrome ì‚¬ìš©ìž ì´ë¦„</translation>
+<translation id="755279583747225797">무료 ì²´í—˜ì´ í™œì„±í™”ë¨</translation>
<translation id="7552846755917812628">ë‹¤ìŒ ë„움ë§ì„ 확ì¸í•´ 보세요.</translation>
<translation id="7554475479213504905">무시하고 새로고침 ë° í‘œì‹œ</translation>
<translation id="7554791636758816595">새 탭</translation>
@@ -1730,7 +1781,6 @@
<translation id="7610193165460212391">ê°’(<ph name="VALUE" />)ì´ ë²”ìœ„ë¥¼ 벗어났습니다.</translation>
<translation id="7613889955535752492">만료ì¼: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome 설정ì—ì„œ 비밀번호를 확ì¸í•˜ê³  관리하려면 Tabì„ ëˆ„ë¥¸ ë‹¤ìŒ Enter 누르기</translation>
-<translation id="7615602087246926389">다른 Google 계정 비밀번호 ë²„ì „ì„ ì‚¬ìš©í•˜ì—¬ ì•”í˜¸í™”ëœ ë°ì´í„°ê°€ ì´ë¯¸ 있습니다. ì•„ëž˜ì— ì•”í˜¸ë¥¼ 입력하시기 ë°”ëžë‹ˆë‹¤.</translation>
<translation id="7616645509853975347">관리ìžê°€ 브ë¼ìš°ì €ì— Chrome Enterprise 커넥터를 사용 설정했습니다. 커넥터가 ë‚´ ë°ì´í„° 중 ì¼ë¶€ì— 액세스할 수 있습니다.</translation>
<translation id="7619838219691048931">엔드 시트</translation>
<translation id="762844065391966283">í•œ ë²ˆì— í•˜ë‚˜ì”©</translation>
@@ -1795,13 +1845,12 @@
<translation id="782886543891417279">사용 ì¤‘ì¸ Wi-Fi(<ph name="WIFI_NAME" />)ì—ì„œ ë¡œê·¸ì¸ íŽ˜ì´ì§€ ë°©ë¬¸ì„ ìš”ì²­í•  수 있습니다.</translation>
<translation id="7836231406687464395">Postfix(봉투)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ì—†ìŒ}=1{앱 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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">íŒŒì¼ í˜•ì‹ ì—°ê²°ì´ ìžˆëŠ” 파ì¼ì„ 엽니다.</translation>
<translation id="7862185352068345852">사ì´íŠ¸ì—ì„œ 나가시겠습니까?</translation>
<translation id="7865448901209910068">최고 ì†ë„</translation>
<translation id="7874263914261512992">사기성 사ì´íŠ¸ì— 비밀번호를 입력했습니다. 지금 바로 <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> 등 ë™ì¼í•œ 비밀번호를 사용한 사ì´íŠ¸ì— ì €ìž¥ëœ ë¹„ë°€ë²ˆí˜¸ë¥¼ 확ì¸í•˜ëŠ” ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤.</translation>
<translation id="7878562273885520351">비밀번호가 ë„ìš©ë  ìˆ˜ë„ ìžˆìŒ</translation>
+<translation id="7880146494886811634">주소 저장</translation>
<translation id="7882421473871500483">갈색</translation>
<translation id="7887683347370398519">CVC를 확ì¸í•œ 후 다시 ì‹œë„하세요.</translation>
<translation id="7887885240995164102">PIP 모드 시작</translation>
@@ -1809,6 +1858,7 @@
<translation id="7894280532028510793">ì² ìžê°€ 올바르다면 <ph name="BEGIN_LINK" />ë„¤íŠ¸ì›Œí¬ ì§„ë‹¨ì„ ì‹¤í–‰<ph name="END_LINK" />í•´ 보세요.</translation>
<translation id="7904208859782148177">C3(봉투)</translation>
<translation id="7931318309563332511">ì•Œ 수 ì—†ìŒ</translation>
+<translation id="793209273132572360">주소를 ì—…ë°ì´íŠ¸í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="7932579305932748336">코팅</translation>
<translation id="79338296614623784">올바른 전화번호를 입력하세요.</translation>
<translation id="7934052535022478634">결제 완료</translation>
@@ -1879,6 +1929,7 @@
<translation id="8175796834047840627">로그ì¸ë˜ì–´ 있는 경우 Chromeì—ì„œ Google ê³„ì •ì— ì¹´ë“œë¥¼ 저장할지 묻는 메시지가 표시ë©ë‹ˆë‹¤. 설정ì—ì„œ ì´ ë™ìž‘ì„ ë³€ê²½í•  수 있습니다.</translation>
<translation id="8176440868214972690">기기 관리ìžê°€ ë‹¤ìŒ ì›¹ì‚¬ì´íŠ¸ë¡œ 설정 ë˜ëŠ” ì •ì±…ê³¼ ê°™ì€ ì •ë³´ë¥¼ 전송했습니다.</translation>
<translation id="8184538546369750125">전체 기본값 사용(허용)</translation>
+<translation id="8193086767630290324">기밀로 í‘œì‹œëœ ë°ì´í„°ì— 대한 ìž‘ì—…</translation>
<translation id="8194797478851900357">ì´ë™ 실행 취소(&amp;U)</translation>
<translation id="8201077131113104583">IDê°€ '<ph name="EXTENSION_ID" />'ì¸ í™•ìž¥ í”„ë¡œê·¸ëž¨ì— ëŒ€í•œ ìž˜ëª»ëœ ì—…ë°ì´íŠ¸ URL</translation>
<translation id="8202097416529803614">주문 요약</translation>
@@ -1901,6 +1952,7 @@
<translation id="8249296373107784235">중단</translation>
<translation id="8249320324621329438">마지막으로 가져온 시간:</translation>
<translation id="8253091569723639551">청구지 주소 필요</translation>
+<translation id="8257387598443225809">모바ì¼ìš© 앱</translation>
<translation id="825929999321470778">ì €ìž¥ëœ ë¹„ë°€ë²ˆí˜¸ ëª¨ë‘ í‘œì‹œ</translation>
<translation id="8261506727792406068">삭제</translation>
<translation id="8262952874573525464">하단 ì—지 스티치</translation>
@@ -2024,7 +2076,6 @@
<translation id="8719528812645237045">ìƒë‹¨ 다공 펀칭</translation>
<translation id="8725066075913043281">다시 ì‹œë„하세요</translation>
<translation id="8726549941689275341">페ì´ì§€ í¬ê¸°:</translation>
-<translation id="8728672262656704056">ì‹œí¬ë¦¿ 모드로 전환ë¨</translation>
<translation id="8730621377337864115">완료</translation>
<translation id="8731544501227493793">비밀번호 관리 버튼, Chrome 설정ì—ì„œ 비밀번호를 확ì¸í•˜ê³  관리하려면 Enter 누르기</translation>
<translation id="8734529307927223492">ë‚´ <ph name="DEVICE_TYPE" />ì€(는) <ph name="MANAGER" />ì—ì„œ 관리합니다</translation>
@@ -2101,6 +2152,7 @@
<translation id="9020542370529661692">ì´ íŽ˜ì´ì§€ëŠ” <ph name="TARGET_LANGUAGE" />ë¡œ 번역ë˜ì—ˆìŠµë‹ˆë‹¤.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(유효하지 ì•ŠìŒ)</translation>
+<translation id="9030265603405983977">í‘ë°±</translation>
<translation id="9035022520814077154">보안 오류</translation>
<translation id="9038649477754266430">빠른 페ì´ì§€ 로드를 위해 ì˜ˆìƒ ê²€ìƒ‰ì–´ 서비스 사용</translation>
<translation id="9039213469156557790">ë˜í•œ ì´ íŽ˜ì´ì§€ì—는 안전하지 ì•Šì€ ë‹¤ë¥¸ 리소스가 í¬í•¨ë˜ì–´ 있습니다. ì´ëŸ¬í•œ 리소스는 전송 ì¤‘ì— ë‹¤ë¥¸ ì‚¬ëžŒì´ ë³¼ 수 있으며 페ì´ì§€ì˜ ìž‘ë™ì„ 변경하기 위해 공격ìžê°€ 수정할 수 있습니다.</translation>
@@ -2124,6 +2176,7 @@
<translation id="91108059142052966">ê´€ë¦¬ìž ì •ì±…ì— ë”°ë¼ ê¸°ë°€ 콘í…츠가 ë³´ì¼ ë•Œ <ph name="APPLICATION_TITLE" />ê³¼(와)ì˜ í™”ë©´ 공유가 중지ë©ë‹ˆë‹¤.</translation>
<translation id="9114524666733003316">ì¹´ë“œ í™•ì¸ ì¤‘...</translation>
<translation id="9114581008513152754">ì´ ë¸Œë¼ìš°ì €ëŠ” 회사 ë˜ëŠ” 다른 ì¡°ì§ì—ì„œ 관리하지 않습니다. ì´ ê¸°ê¸°ì˜ í™œë™ì€ Chrome 외부ì—ì„œë„ ê´€ë¦¬í•  수 있습니다. <ph name="BEGIN_LINK" />ìžì„¸ížˆ 알아보기<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ìƒê¸°</translation>
<translation id="9119042192571987207">업로드ë¨</translation>
<translation id="9128016270925453879">ì •ì±… 로드ë¨</translation>
<translation id="9128870381267983090">네트워í¬ì— ì—°ê²°</translation>
@@ -2142,6 +2195,7 @@
<translation id="9170848237812810038">실행 취소(&amp;U)</translation>
<translation id="9171296965991013597">ì•±ì„ ì¢…ë£Œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?</translation>
<translation id="9173282814238175921">ë‹¨ì¼ ë¬¸ì„œ/새 시트</translation>
+<translation id="9173995187295789444">블루투스 기기 검색 중...</translation>
<translation id="917450738466192189">ì„œë²„ì˜ ì¸ì¦ì„œê°€ 유효하지 않습니다.</translation>
<translation id="9174917557437862841">탭 전환 버튼, ì´ íƒ­ìœ¼ë¡œ 전환하려면 Enter를 누르세요</translation>
<translation id="9179703756951298733">Chrome 설정ì—ì„œ ê²°ì œ ë° ì‹ ìš©ì¹´ë“œ 정보를 관리하세요.</translation>
diff --git a/chromium/components/strings/components_strings_ky.xtb b/chromium/components/strings/components_strings_ky.xtb
index 5609c42b355..7aaac4ea600 100644
--- a/chromium/components/strings/components_strings_ky.xtb
+++ b/chromium/components/strings/components_strings_ky.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Эгер белгиленÑе, форманы тезирÑÑк толтуруу үчүн Chrome картаңыздын көчүрмөÑүн ушул түзмөккө Ñактайт.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> урукÑатын тандоо</translation>
<translation id="1113869188872983271">Иреттештирүүнү &amp;жаÑабоо</translation>
+<translation id="1123753900084781868">Ыкчам коштомо жазуулар учурда жеткиликтүү ÑмеÑ</translation>
<translation id="1125573121925420732">ВебÑайттардын коопÑуздук шарттары жаңыртылып жатканда, ÑÑкертүүлөр көп жолу көрүнүшү мүмкүн. Бул убактылуу көрүнүш.</translation>
<translation id="112840717907525620">СаÑÑат кеши OK</translation>
<translation id="1130564665089811311">Баракты которуу баÑкычы, бул баракты Google Котормочу менен которуу үчүн, Enter баÑкычын баÑыңыз</translation>
@@ -66,7 +67,7 @@
<translation id="1206967143813997005">Баштапкы колтамга начар</translation>
<translation id="1209206284964581585">Ðзырынча жашыруу</translation>
<translation id="121201262018556460"><ph name="DOMAIN" /> доменин ачканга аракет кылдыңыз, бирок Ñервер чабал ачкычты камтыган таÑтыктаманы Ñунуштады. Башкача айтканда, зыÑнкеч чабуулчу жеке ачкычты бузгандыктан, Ñервер Ñиз күтүп жаткан Ñервер болбой калышы мүмкүн (балким, чабуулчу менен байланышып жатаÑыз).</translation>
-<translation id="1219129156119358924">Тутумдун коопÑуздугу</translation>
+<translation id="1219129156119358924">СиÑтеманын коопÑуздугу</translation>
<translation id="1227224963052638717">БелгиÑиз ÑаÑÑат.</translation>
<translation id="1228893227497259893">Туура ÑÐ¼ÐµÑ Ð¾Ð±ÑŠÐµÐºÑ‚ аныктагыч</translation>
<translation id="1232569758102978740">ÐÑ‚Ñ‹ жок</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Түзмөгүңүздүн аталышы</translation>
<translation id="124116460088058876">Дагы тилдер</translation>
<translation id="1243027604378859286">Ðвтор:</translation>
+<translation id="1246424317317450637">Жоон</translation>
<translation id="1250759482327835220">Кийинки жолу тезирÑÑк төлөө үчүн картаңызды, аты-жөнүңүздү жана ÑÑептешүү дарегин Google аккаунтуңузга Ñактап коюңуз.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (шайкештирилген)</translation>
<translation id="1256368399071562588">&lt;p&gt;Эгер вебÑайтты ачууга аракет кылганда ал ачылбай жатÑа, каталарды оңдоо боюнча төмөнкүдөй аракеттерди аткарып көрүңүз:&lt;/p&gt;
@@ -156,8 +158,9 @@
<translation id="1476595624592550506">СырÑөзүңүздү өзгөртүңүз</translation>
<translation id="1484290072879560759">Жөнөтүү дарегин тандоо</translation>
<translation id="1492194039220927094">СаÑÑаттарды колдонуу:</translation>
+<translation id="1495677929897281669">Өтмөккө кайтуу</translation>
<translation id="1501859676467574491">Google аккаунтуңуздагы карталарды көрÑÓ©Ñ‚Ò¯Ò¯</translation>
-<translation id="1507202001669085618">&lt;p&gt;Бул ката Интернетке туташуудан мурда кирүүнү талап кылган Wi-Fi порталын колдонгондо көрÑөтүлөт.&lt;/p&gt;
+<translation id="1507202001669085618">&lt;p&gt;Бул ката Интернетке туташуудан мурда кирүүнү талап кылган Wi-Fi порталын колдонгондо көрүнөт.&lt;/p&gt;
&lt;p&gt;Катаны оңдоо үчүн ачууга аракет кылып жаткан барактан &lt;strong&gt;Туташуу&lt;/strong&gt; дегенди чыкылдатыңыз.&lt;/p&gt;</translation>
<translation id="1513706915089223971">Таржымалдагы жазуулардын тизмеÑи</translation>
<translation id="1517433312004943670">Телефон номери талап кылынат</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Бул баракча мындай дейт:</translation>
<translation id="153384715582417236">Ðзырынча ушул Ñле</translation>
<translation id="1536390784834419204">Баракты которуу</translation>
+<translation id="1539840569003678498">Кабар жөнөтүлдү:</translation>
<translation id="154408704832528245">Жеткирүү дарегин тандоо</translation>
<translation id="1549470594296187301">Бул функциÑны пайдалануу үчүн JavaScript иштетилиши керек.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">Биринчи туураÑÑ‹ боюнча</translation>
<translation id="168693727862418163">Бул ÑаÑÑаттын мааниÑи ÑхемаÑына дал келбей калды, андыктан Ñтибарга алынбайт.</translation>
<translation id="168841957122794586">Сервердин таÑтыктамаÑында чабал криптографиÑлык ачкыч камтылган.</translation>
+<translation id="1696290444144917273">Виртуалдык картанын чоо-жайын көрүү</translation>
<translation id="1697532407822776718">Баары даÑÑ€!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Бул Ñервер <ph name="DOMAIN" /> Ñкенин далилдей алган жок. Ðнын коопÑуздук таÑтыктамаÑÑ‹ Ñртең күчүнө кирет. Мындай көйгөй Ñервердин туура ÑÐ¼ÐµÑ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñланышы менен шартталышы мүмкүн же кимдир-бирөө ортодон дайын-даректериңизди кармап калганга аракет кылып жатат.}other{Бул Ñервер <ph name="DOMAIN" /> Ñкенин далилдей алган жок. Ðнын коопÑуздук таÑтыктамаÑÑ‹ # күндөн кийин күчүнө кирет. Мындай көйгөй Ñервердин туура ÑÐ¼ÐµÑ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñланышы менен шартталышы мүмкүн же кимдир-бирөө ортодон дайын-даректериңизди кармап калганга аракет кылып жатат.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Четке кагылды, анткени <ph name="POLICY_NAME" /> <ph name="VALUE" /> деп коюлган ÑмеÑ.</translation>
<translation id="1712552549805331520"><ph name="URL" /> компьютериңизге дайындарды биротоло Ñактаганы жатат</translation>
<translation id="1713628304598226412">2-түпкүч</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">3-Ñлектрондук каттар кутуÑу</translation>
<translation id="1718029547804390981">Документ Ó©Ñ‚Ó© чоң, андыктан ÐÐ½Ð½Ð¾Ñ‚Ð°Ñ†Ð¸Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð¸Ð½Ð´Ðµ түзөтүүгө болбойт.</translation>
<translation id="1721424275792716183">* Бул талаа милдеттүү түрдө толтурулушу керек</translation>
+<translation id="1727613060316725209">ТаÑтыктама жарамдуу</translation>
<translation id="1727741090716970331">Жарактуу карточканын номерин кошуу</translation>
<translation id="1728677426644403582">Сиз Интернет барагынын кодун көрүп жатаÑыз</translation>
<translation id="173080396488393970">Мындай карточка колдоого алынбайт</translation>
@@ -246,7 +253,6 @@
аткара албайт. Баштапкы ÑаÑÑаттар
Ñайттын операторлору тарабынан Ñайттын коопÑуздугун жана башка каÑиеттерин конфигурациÑлоо үчүн колдонулат.</translation>
<translation id="1778646502362731194">JIS B0 (1030mm x 1456mm)</translation>
-<translation id="1783075131180517613">Шайкештештирүү ÐºÑƒÐ¿ÑƒÑ Ñөз айкашыңызды жаңыртыңыз.</translation>
<translation id="1787142507584202372">Ðчылган өтмөктөр бул жерде көрүнөт</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, бир нече аракет жеткиликтүү, Tab баÑкычын баÑып, аларды карап чыгыңыз</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">Жарнамалар</translation>
<translation id="1919367280705858090">Белгилүү бир каталар боюнча жардам алуу</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Бирөө да жок}=1{1 Ñайт}other{# Ñайт}}</translation>
+<translation id="1924727005275031552">Жаңы</translation>
<translation id="1945968466830820669">Кимдир бирөө Ñиздин жеке дайындарыңызга же уюмуңуздун аккаунтуна кирип алган окшойт. Chromium ÑÑ‹Ñ€Ñөзүңүздү азыр өзгөртүүнү Ñунуштайт.</translation>
<translation id="1947454675006758438">Жогорку оң жагын илмек менен бекитүү</translation>
<translation id="1958218078413065209">Эң көп алган упайыңыз: <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">7-түпкүч</translation>
<translation id="204357726431741734">Google аккаунтуңузда Ñакталган ÑÑ‹Ñ€Ñөздөрдү колдонуу үчүн аккаунтуңузга кириңиз</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> тилиндеги барактар которулбайт.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Бул көзөмөлдөө каражаты күйүк жана абалы жигердүү болгондо, Chrome акыркы көргөн вебÑайттарыңыз адамдардын кайÑÑ‹ чоң тобуна же "когортаÑына" ÑÒ£ ылайыктуу Ñкенин аныктайт. Жарнамачылар ал топ үчүн жарнамаларды тандай алат жана көргөн вебÑайттарыңыз түзмөгүңүздө ÐºÑƒÐ¿ÑƒÑ Ñакталат. Тобуңуз күн Ñайын жаңыртылып турат.}=1{Бул көзөмөлдөө каражаты күйүк жана абалы жигердүү болгондо, Chrome акыркы көргөн вебÑайттарыңыз адамдардын кайÑÑ‹ чоң тобуна же "когортаÑына" ÑÒ£ ылайыктуу Ñкенин аныктайт. Жарнамачылар ал топ үчүн жарнамаларды тандай алат жана көргөн вебÑайттарыңыз түзмөгүңүздө ÐºÑƒÐ¿ÑƒÑ Ñакталат. Тобуңуз күн Ñайын жаңыртылып турат.}other{Бул көзөмөлдөө каражаты күйүк жана абалы жигердүү болгондо, Chrome акыркы көргөн вебÑайттарыңыз адамдардын кайÑÑ‹ чоң тобуна же "когортаÑына" ÑÒ£ ылайыктуу Ñкенин аныктайт. Жарнамачылар ал топ үчүн жарнамаларды тандай алат жана көргөн вебÑайттарыңыз түзмөгүңүздө ÐºÑƒÐ¿ÑƒÑ Ñакталат. Тобуңуз {NUM_DAYS} күн Ñайын жаңыртылып турат.}}</translation>
<translation id="2053553514270667976">Почта индекÑи</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 Ñунуш}other{# Ñунуш}}</translation>
<translation id="2071692954027939183">Билдирмелер автоматтык түрдө бөгөттөлдү, анткени, адатта, аларга урукÑат бербейÑиз</translation>
<translation id="2079545284768500474">Кайтаруу</translation>
-<translation id="20817612488360358">Тутумдун прокÑи жөндөөлөрү коюлду жана ошону менен катар, айкын прокÑи конфигурайиÑÑÑ‹ да белгиленди.</translation>
+<translation id="20817612488360358">СиÑтеманын прокÑи жөндөөлөрү коюлду жана ошону менен катар, айкын прокÑи конфигурайиÑÑÑ‹ да белгиленди.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> ичинен <ph name="RESULT_NUMBER" /> натыйжа</translation>
+<translation id="2085876078937250610">Сактоо…</translation>
<translation id="2088086323192747268">Шайкештирүүнү башкаруу баÑкычы, Chrome жөндөөлөрүнөн шайкештирилген маалыматты башкаруу үчүн Enter баÑкычын баÑыңыз</translation>
<translation id="2091887806945687916">Үн</translation>
<translation id="2094505752054353250">Домен дал келбейт</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> домени колдонуучунун атын жана ÑÑ‹Ñ€Ñөзүн талап кылып жатат.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, мөөнөтү <ph name="EXPIRATION_DATE_ABBR" /> бүтөт</translation>
<translation id="2337852623177822836">Жөндөөнү админиÑтраторуңуз башкарат</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> жупташканы жатат</translation>
<translation id="2344028582131185878">Ðвтоматтык жүктөп алуулар</translation>
<translation id="2346319942568447007">Сиз көчүргөн Ñүрөт</translation>
<translation id="2354001756790975382">Башка кыÑтармалар</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">Сиз бул Ñайтта көрүп жаткан Ñүрөттөрдү чабуулчулар да көрүп алып, Ñүрөттөрдү өзгөртүп, Ñизди алдашы да мүмкүн.</translation>
<translation id="2356070529366658676">Сураңыз</translation>
<translation id="2357481397660644965">Түзмөгүңүздү <ph name="DEVICE_MANAGER" /> жана аккаунтуңузду <ph name="ACCOUNT_MANAGER" /> башкарууда.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{1 күнгө жетпеген убакытта}=1{1 күндөн кийин}other{{NUM_DAYS} күндөн кийин}}</translation>
<translation id="2359629602545592467">Бир нече</translation>
<translation id="2359808026110333948">Улантуу</translation>
+<translation id="2359961752320758691">Виртуалдык картаңыздын номери колдонулду.</translation>
<translation id="2367567093518048410">ДеңгÑÑли</translation>
<translation id="2372464001869762664">ЫраÑтаганыңыздан кийин Google аккаунтуңуздагы карточканын чоо-жайы бул Ñайтка жөнөтүлөт. Plex аккаунтуңуздун чоо-жайынан CVC кодун табыңыз.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">Жөнөтүүнүн мындай ыкмаÑÑ‹ мүмкүн ÑмеÑ. Башка ыкманы байкап көрүңүз.</translation>
<translation id="2396249848217231973">Жок кылууну &amp;жаÑабоо</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">ЭÑки</translation>
<translation id="2413528052993050574">Бул Ñервер <ph name="DOMAIN" /> Ñкендигин далилдей алган жок; Ñебеби анын коопÑуздук таÑтыктамаÑÑ‹ жокко чыгарылган окшойт. Мындай көйгөй туура ÑÐ¼ÐµÑ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð¼ÐµÐ½ÐµÐ½ шартталышы мүмкүн же туташууңузга чабуулчу кийлигишип жатат.</translation>
<translation id="2414886740292270097">Кочкул</translation>
<translation id="2438874542388153331">Оң жагын төрт жолу тешүү</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">Төмөнк оң жагын илмек менен бекитүү</translation>
<translation id="2523886232349826891">Ушул түзмөккө гана Ñакталды</translation>
<translation id="2524461107774643265">Көбүрөөк маалымат кошуу</translation>
-<translation id="2526590354069164005">Иштакта</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{жана дагы 1}other{жана дагы #}}</translation>
<translation id="2536110899380797252">Дарегин кошуу</translation>
<translation id="2539524384386349900">Ðныктоо</translation>
+<translation id="2541219929084442027">Бардык жашыруун өтмөктөрүңүз жабылгандан кийин, аларда каралган барактар Ñерепчиңиздин таржымалында, cookie файлдарынын Ñактагычында же издөө таржымалында калбайт. Бирок жүктөлүп алынган файлдар же түзүлгөн кыÑтармалар Ñакталып кала берет.</translation>
<translation id="2544644783021658368">Жалгыз документ</translation>
<translation id="254947805923345898">СаÑÑаттын мааниÑи туура ÑÐ¼ÐµÑ ÐºÓ©Ñ€Ñөтүлдү.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> Ñайты жаракÑыз жооп жөнөттү.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Chrome’ду жогорку деңгÑÑлде коопÑуздандыруу үчүн <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />өркүндөтүлгөн коргоону күйгүзүңүз<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> Ñерверинин IP дареги табылбай койду.</translation>
<translation id="2639739919103226564">СтатуÑ:</translation>
+<translation id="264810637653812429">Шайкеш түзмөктөр табылган жок.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. Chrome жөндөөлөрүнөн көрүлгөн вебÑайттарды, cookie файлдарын, кештерди жана башкаларды тазалоо үчүн, Tab, андан Ñоң Enter баÑкычын баÑыңыз</translation>
<translation id="2650446666397867134">Файлды колдонуу мүмкүнчүлүгү четке кагылды</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">Кайра ишке киргизүү</translation>
<translation id="2803306138276472711">Google КоопÑуз Серепчи жакында <ph name="SITE" /> Ñайтынан <ph name="BEGIN_LINK" />кеÑепеттүү программа<ph name="END_LINK" /> тапты. КÑÑде коопÑуз вебÑайттар кеÑепеттүү программалардан жабыркап калышат.</translation>
<translation id="2807052079800581569">Y Ñүрөтүнүн абалы</translation>
+<translation id="2820957248982571256">Скандалууда…</translation>
<translation id="2824775600643448204">Дарек жана издөө тилкеÑи</translation>
<translation id="2826760142808435982">Бул туташуу <ph name="CIPHER" /> аркылуу шифрленип, аныктыгы текшерилген жана муну <ph name="KX" /> алмаштыруу механизми катары колдонот.</translation>
<translation id="2835170189407361413">Форманы тазалоо</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Invite (Конверт)</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="2859806420264540918">Бул Ñайт тажатма же адаштыруучу жарнамаларды көрÑөтүп жатат.</translation>
+<translation id="287596039013813457">Ынак</translation>
+<translation id="2876489322757410363">Тышкы колдонмо аркылуу төлөө үчүн жашыруун режимден чыкканы жатаÑыз. Уланта береÑизби?</translation>
<translation id="2878197950673342043">ПоÑтер формаÑында бүктөө</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Терезени жайгаштыруу</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (Конверт)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome жөндөөлөрүнөн коопÑуздукту текшерүү үчүн Tab, андан кийин Enter баÑкычын баÑыңыз</translation>
<translation id="3061707000357573562">Оңдоо кызматы</translation>
-<translation id="3064966200440839136">Тышкы колдонмо аркылуу төлөө үчүн жашыруун режимден чыкканы жатаÑыз. Уланта берелиби?</translation>
<translation id="306573536155379004">Оюн башталды.</translation>
<translation id="3080254622891793721">Графика</translation>
<translation id="3086579638707268289">Интернеттеги аракеттериңиз көзөмөлдөнүүдө</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">Ðккаунтуңуз <ph name="MANAGER" /> тарабынан башкарылууда.</translation>
<translation id="3157931365184549694">Калыбына келтирүү</translation>
<translation id="3162559335345991374">Сиз колдонуп жаткан Wi-Fi башкы кирүү барагына өтүшүңүздү талап кылышы мүмкүн.</translation>
-<translation id="3167968892399408617">Бардык жашыруун өтмөктөрүңүз жабылгандан кийин, аларда каралган беттер Ñерептөө таржымалында, куки-файлдарынын Ñактагычында же издөө таржымалында калбайт. Бирок жүктөлүп алынган файлдар же кыÑтарылган вебÑайттар Ñакталып кала берет.</translation>
<translation id="3169472444629675720">Ðныктоо</translation>
<translation id="3174168572213147020">Ðрал</translation>
<translation id="3176929007561373547">ПрокÑи Ñерверинин иштеп жатканын такташ үчүн, прокÑи жөндөөлөрүңүздү
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">Түзмөгүңүздүн жана Ñерепчиңиздин верÑиÑÑÑ‹ тууралуу маалымат</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> карточкаңыз үчүн CVC кодун киргизиңиз</translation>
<translation id="3234666976984236645">Бул Ñайттагы маанилүү мазмун ар дайым аныкталÑын</translation>
+<translation id="3249845759089040423">Көркөм</translation>
<translation id="3252266817569339921">Французча</translation>
<translation id="3266793032086590337">Маани (карама-каршы)</translation>
<translation id="3268451620468152448">Ðчык өтмөктөр</translation>
<translation id="3270847123878663523">Иреттештирүүнү &amp;жаÑабоо</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> туташканы жатат</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552"><ph name="ENROLLMENT_DOMAIN" /> уюмуңуз жөндөөлөр же ÑаÑÑаттар ÑÑ‹Ñктуу айрым маалыматты төмөндөгү вебÑайттарга жөнөттү.</translation>
<translation id="3282497668470633863">Картадагы Ñ‹Ñымды кошуу</translation>
@@ -655,6 +672,7 @@
<translation id="3428151540071562330">Бир же бир нече DnsOverHttpsTemplates Ñерверлериндеги URI даректеринин үлгүлөрү жаракÑыз жана колдонулбайт.</translation>
<translation id="3431636764301398940">Бул карточка ушул түзмөктө ÑакталÑын</translation>
<translation id="3432601291244612633">Баракты жабуу</translation>
+<translation id="3435738964857648380">КоопÑуздук</translation>
<translation id="3435896845095436175">Иштетүү</translation>
<translation id="3438829137925142401">Google аккаунтуңузда Ñакталган ÑÑ‹Ñ€Ñөздөрдү колдонуңуз</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -696,7 +714,10 @@
<translation id="3584299510153766161">Төмөн жагын бир нече жолу тешүү</translation>
<translation id="3586931643579894722">Чоо-жайын жашыруу</translation>
<translation id="3587738293690942763">Орто</translation>
+<translation id="3590643883886679995">Жашыруун режимден чыккандан кийин, аккаунтка кирүү дайындары бул түзмөктө Ñакталат.</translation>
+<translation id="359126217934908072">Ðй/Жыл:</translation>
<translation id="3592413004129370115">Italian (Конверт)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Тобуңузду каалаган убакта баштапкы абалга келтирÑеңиз болот. Жаңы топко кошулуу үчүн 1 күндөй убакыт кетет.}=1{Тобуңузду каалаган убакта баштапкы абалга келтирÑеңиз болот. Жаңы топко кошулуу үчүн 1 күндөй убакыт кетет.}other{Тобуңузду каалаган убакта баштапкы абалга келтирÑеңиз болот. Жаңы топко кошулуу үчүн {NUM_DAYS} күндөй убакыт кетет.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Колдонмо админиÑтраторуңуз тарабынан бөгөттөлдү</translation>
<translation id="3608932978122581043">Түрмөктүн багыты</translation>
@@ -705,13 +726,13 @@
<translation id="3615877443314183785">Мөөнөтү аÑктоочу күндү туура киргизиңиз</translation>
<translation id="36224234498066874">Серептөө дайындарын тазалоо…</translation>
<translation id="362276910939193118">Толук таржымалды көрÑÓ©Ñ‚Ò¯Ò¯</translation>
-<translation id="3625635938337243871">Жашыруун режимден чыккандан кийин, аккаунтка кирүү дайындары бул түзмөктө Ñакталат.</translation>
<translation id="3630155396527302611">Эгер ал тармакка кире алган программа катары мурунтан Ñле тизмеленген
болÑо, аны тизмеден алып Ñалып, кайра кошуп көрүңүз.</translation>
<translation id="3630699740441428070">Бул түзмөктүн админиÑтраторлору тармакка туташууну конфигурациÑлап коюшту. Эми алар тармактагы трафикти, анын ичинде Ñиз кирген вебÑайттарды көрө алышат.</translation>
<translation id="3631244953324577188">Биометрика</translation>
<translation id="3633738897356909127">Chrome'ду жаңыртуу баÑкычы. Chrome жөндөөлөрүңүздөн Chrome'ду жаңыртуу үчүн, Enter баÑкычын баÑыңыз</translation>
<translation id="3634530185120165534">5-түпкүч</translation>
+<translation id="3637662659967048211">Google аккаунтка Ñактоо</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Колдонмо:</translation>
<translation id="3650584904733503804">Жарактуулугу ийгиликтүү текшерилди</translation>
@@ -752,6 +773,7 @@
<translation id="3781428340399460090">Ðчык кызгылтым</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth түзмөктөрү</translation>
+<translation id="3787675388804467730">Виртуалдык картанын номери</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> мөөнөтү аÑктайт</translation>
<translation id="3789155188480882154">Өлчөмү: 16</translation>
<translation id="3789841737615482174">Орнотуу</translation>
@@ -771,6 +793,7 @@
<translation id="3841184659773414994">Файл иштеткичтер</translation>
<translation id="385051799172605136">Ðртка</translation>
<translation id="3858027520442213535">Күн менен убакытты жаңыртуу</translation>
+<translation id="3881478300875776315">Ðзыраак көрÑÓ©Ñ‚Ò¯Ò¯</translation>
<translation id="3884278016824448484">Түзмөктүн далдаштыргычтары дал келбей кагылышууда</translation>
<translation id="3885155851504623709">ПÑриш</translation>
<translation id="388632593194507180">Көзөмөлдөө аныкталды</translation>
@@ -796,6 +819,7 @@
<translation id="397105322502079400">ЭÑептелүүдө…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> Ñайты бөгөттөлгөн</translation>
<translation id="3973357910713125165">Chrome'дун коопÑуздугун текшерүү баÑкычы, Chrome жөндөөлөрүнөн коопÑуздукту текшерүү үчүн Enter баÑкычын баÑыңыз</translation>
+<translation id="3986705137476756801">Ыкчам коштомо жазууларды азырынча өчүрүү</translation>
<translation id="3987405730340719549">Chrome бул жалган Ñайт болушу мүмкүн Ñкенин аныктады.
Эгер бул жаңылыш көрÑөтүлүп жатат деп ойлоÑоңуз, https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals баракчаÑына баш багыңыз.</translation>
@@ -892,13 +916,14 @@
<translation id="4275830172053184480">Түзмөктү өчүрүп күйгүзүү</translation>
<translation id="4277028893293644418">СырÑөздү өзгөртүү</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Бул карта Google аккаунтуңузга Ñакталды}other{Бул карталар Google аккаунтуңузга Ñакталды}}</translation>
+<translation id="4287885627794386150">Сыноо үчүн жарактуу, бирок жигердүү ÑмеÑ</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> барагынын ÑÑкизи</translation>
<translation id="42981349822642051">Жайып көрÑÓ©Ñ‚Ò¯Ò¯</translation>
<translation id="4300675098767811073">Оң жагын бир нече жолу тешүү</translation>
<translation id="4302514097724775343">Ойноп баштоо үчүн динозаврды таптап коюңуз</translation>
<translation id="4302965934281694568">Chou3 (Конверт)</translation>
<translation id="4305666528087210886">Файл ачылбай койду</translation>
-<translation id="4305817255990598646">Которулуу</translation>
+<translation id="4306529830550717874">Дарек ÑакталÑынбы?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Бөгөттөө (демейки)</translation>
<translation id="4314815835985389558">Шайкештирүүнү башкаруу</translation>
@@ -925,6 +950,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" /> жетүүгө аракет кылдыңыз, бирок Ñервердин таÑтыктамаÑын аны чыгарган жак жокко чыгарды. Демек, Ñервердин далдаштырма дайындарына таптакыр ишенбешиңиз керек, Ñебеби ал зыÑнкеч чабуулчу болушу да мүмкүн.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4390472908992056574">Кыр</translation>
+<translation id="4406883609789734330">Ыкчам коштомо жазуулар</translation>
<translation id="4406896451731180161">издөө натыйжалары</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> куки</translation>
<translation id="4414290883293381923">СырÑөзүңүздү жаңы Ñле адаштыруучу Ñайтта киргиздиңиз. Chrome ушул ÑÑ‹Ñ€Ñөздү колдонгон <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> жана башка Ñайттарга өтүп, аны азыр өзгөртүүнү Ñунуштайт.</translation>
@@ -937,7 +963,6 @@
<translation id="4435702339979719576">Ðчык кат)</translation>
<translation id="443673843213245140">ПрокÑи пайдалануу мүмкүнчүлүгү өчүрүлгөнү менен, ачык-айкын прокÑи конфигурациÑÑÑ‹ белгиленген.</translation>
<translation id="4464826014807964867">Уюмуңуздан маалымат алган вебÑайттар</translation>
-<translation id="4466881336512663640">Формага киргизилген өзгөрүүлөр Ñакталбайт. Чын Ñле уланткыңыз келеби?</translation>
<translation id="4476953670630786061">Бул форма кооптуу. Ðвтоматтык түрдө толтуруу функциÑÑÑ‹ өчүрүлдү.</translation>
<translation id="4477350412780666475">Кийинки трек</translation>
<translation id="4482953324121162758">Бул Ñайт которулбайт.</translation>
@@ -971,6 +996,7 @@
<translation id="4594403342090139922">Жок кылууну &amp;жаÑабоо</translation>
<translation id="4597348597567598915">Өлчөмү: 8</translation>
<translation id="4600854749408232102">C6/C5 (Конверт)</translation>
+<translation id="4606870351894164739">ТааÑирлүү</translation>
<translation id="4628948037717959914">Сүрөт</translation>
<translation id="4631649115723685955">КешбÑк байланыштырылды</translation>
<translation id="4636930964841734540">Маалымат</translation>
@@ -990,6 +1016,7 @@
<translation id="4691835149146451662">Architecture-A (Конверт)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Каптал</translation>
+<translation id="4702656508969495934">Ыкчам коштомо жазуулар көрүнүп турат, фокуÑтоо үчүн терезелерди которуштургучту колдонуңуз</translation>
<translation id="4708268264240856090">Туташууңуз үзгүлтүккө учурады</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows Тармак мүчүлүштүгүн аныктоону иштетиңиз<ph name="END_LINK" /></translation>
@@ -1003,6 +1030,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> издөө Ñунушу</translation>
<translation id="4742407542027196863">СырÑөздөрдү башкаруу…</translation>
<translation id="4744603770635761495">Ðткарылуучу жол</translation>
+<translation id="4749011317274908093">Жашыруун режимге өттүңүз</translation>
<translation id="4750917950439032686">Бул Ñайтка жөнөтүлүп жаткан маалымат (миÑалы, ÑÑ‹Ñ€Ñөздөр же наÑÑ‹Ñ ÐºÐ°Ñ€Ñ‚Ð¾Ñ‡ÐºÐ°Ñынын номерлери) ÐºÑƒÐ¿ÑƒÑ Ð±Ð¾Ð»ÑƒÐ¿ Ñаналат.</translation>
<translation id="4756388243121344051">&amp;Таржымал</translation>
<translation id="4758311279753947758">Байланыш маалыматын кошуу</translation>
@@ -1032,6 +1060,8 @@
<translation id="4813512666221746211">Тармактык ката</translation>
<translation id="4816492930507672669">Баракка чактоо</translation>
<translation id="4819347708020428563">ÐнаннотациÑларды демейки көрүнүштө түзөтөÑүзбү?</translation>
+<translation id="4825507807291741242">Күчтүү</translation>
+<translation id="4838327282952368871">КыÑлкеч</translation>
<translation id="484462545196658690">Ðвто</translation>
<translation id="4850886885716139402">Көрүнүш</translation>
<translation id="485316830061041779">ÐемиÑче</translation>
@@ -1168,6 +1198,7 @@
<translation id="5314967030527622926">Буклет жаÑагыч</translation>
<translation id="5316812925700871227">Сааттын жебеÑине каршы айландыруу</translation>
<translation id="5317780077021120954">Сактоо</translation>
+<translation id="5321288445143113935">МакÑималдаштырылган</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> ичинен <ph name="MATCH_POSITION" /> дал келүү</translation>
<translation id="5324080437450482387">Байланыш маалыматын тандоо</translation>
<translation id="5327248766486351172">ÐÑ‚Ñ‹:</translation>
@@ -1175,11 +1206,13 @@
<translation id="5332219387342487447">Жөнөтүү ыкмаÑÑ‹</translation>
<translation id="5333022057423422993">Chrome жаңы Ñле колдонгон ÑÑ‹Ñ€Ñөзүңүздү кимдир бирөө билип алганын аныктады. Ðккаунттарыңызды коопÑуздандыруу үчүн Ñакталган ÑÑ‹Ñ€Ñөздөрүңүздү текшерүүнү Ñунуштайбыз.</translation>
<translation id="5334013548165032829">Чоо-жайы көрÑөтүлгөн тутум таржымалдары</translation>
+<translation id="5334145288572353250">Дарек ÑакталÑынбы?</translation>
<translation id="5340250774223869109">Колдонмо бөгөттөлдү</translation>
<translation id="534295439873310000">NFC түзмөктөрү</translation>
<translation id="5344579389779391559">Бул баракта акы алынышы мүмкүн</translation>
<translation id="5355557959165512791">ТаÑтыктамаÑÑ‹ жоюлгандыктан, <ph name="SITE" /> Ñайтына азыр кире албайÑыз. Ðдатта тармактагы каталар жана чабуулдар убактылуу көрүнүш болгондуктан, бул баракча кийинчерÑÑк иштеп калышы мүмкүн.</translation>
<translation id="536296301121032821">СаÑÑат жөндөөлөрү Ñакталбай калды</translation>
+<translation id="5363309033720083897">ÐдминиÑтраторуңуз урукÑат берген ÑериÑлык порттор</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="5386426401304769735">Бул Ñайттын таÑтыктамалар чынжырында SHA-1 алгоритми менен кол коюлган таÑтыктама камтылган.</translation>
@@ -1188,6 +1221,7 @@
<translation id="5398772614898833570">Жарнамалар бөгөттөлдү</translation>
<translation id="5400836586163650660">Боз</translation>
<translation id="540969355065856584">Бул Ñервер <ph name="DOMAIN" /> Ñкендигин далилдей алган жок; азыркы учурда анын коопÑуздук таÑтыктамаÑÑ‹ жарактуу ÑмеÑ. Бул туура ÑÐ¼ÐµÑ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñлоодон болушу мүмкүн же чабуулчу туташууңузга тоÑкоол болууда.</translation>
+<translation id="541143247543991491">Булут (жалпы тутумдук)</translation>
<translation id="541416427766103491">4-төшөгүч</translation>
<translation id="5421136146218899937">Серептөө дайындарын тазалап Ñалуу…</translation>
<translation id="5426179911063097041"><ph name="SITE" /> Ñизге билдирмелерди жөнөткөнү жатат</translation>
@@ -1201,6 +1235,7 @@
<translation id="5455374756549232013">Ðачар ÑаÑÑаттын убакыт белгиÑи</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" /> байланыш}other{<ph name="CONTACT_PREVIEW" /> жана дагы <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> байланыш}}</translation>
+<translation id="5463625433003343978">Түзмөктөр изделүүдө…</translation>
<translation id="5469868506864199649">ИталиÑнча</translation>
<translation id="5470861586879999274">Түзөтүүнү &amp;кайталоо</translation>
<translation id="5478437291406423475">B6/C4 (Конверт)</translation>
@@ -1237,7 +1272,7 @@
<translation id="5580958916614886209">Мөөнөтү аÑктоочу айды текшерип, кайталап көрүңүз</translation>
<translation id="5586446728396275693">Сакталган даректер жок</translation>
<translation id="5593349413089863479">Туташуу кооптуураак</translation>
-<translation id="5595485650161345191">Даректи түзөтүү</translation>
+<translation id="5595485650161345191">Даректи өзгөртүү</translation>
<translation id="5598944008576757369">Төлөм ыкмаÑын тандоо</translation>
<translation id="560412284261940334">Башкаруу колдоого алынбайт</translation>
<translation id="5605670050355397069">Ledger</translation>
@@ -1250,7 +1285,6 @@
<translation id="5624120631404540903">СырÑөздөрдү башкаруу</translation>
<translation id="5629630648637658800">СаÑÑат жөндөөлөрү жүктөлбөй калды.</translation>
<translation id="5631439013527180824">Түзмөктү башкаргычуу белгиÑи</translation>
-<translation id="5632627355679805402">Дайын-даректериңиз <ph name="BEGIN_LINK" />Google ÑÑ‹Ñ€Ñөзүңүз<ph name="END_LINK" /> менен <ph name="TIME" /> шифрленген. Шайкештирип баштоо үчүн, ÑÑ‹Ñ€Ñөзүңүздү киргизиңиз.</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="5644090287519800334">1-тараптын X Ñүрөтүн жылдыруу</translation>
@@ -1289,12 +1323,12 @@
<translation id="5785756445106461925">Ðндан тышкары, бул бетте башка кооптуу булактар бар. Өткөрүү учурунда аларды башка колдонуучулар көрө алышат, ошону менен катар, беттин көрүнүшүн өзгөртүү үчүн аларды чабуулчулар бурмалап коюшу мүмкүн.</translation>
<translation id="5786044859038896871">Карточкаңыздын маалыматын толтураÑызбы?</translation>
<translation id="578633867165174378">Chrome жаңы Ñле колдонгон ÑÑ‹Ñ€Ñөзүңүздү кимдир бирөө билип алганын аныктады. Бул ÑÑ‹Ñ€Ñөздү азыр өзгөртүүнү Ñунуштайбыз.</translation>
-<translation id="5798290721819630480">Өзгөрүүлөр жоюлÑунбу?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" /> толтураÑызбы?</translation>
<translation id="5804241973901381774">УрукÑаттар</translation>
<translation id="5804427196348435412">NFC түзмөктөрүн колдонуу</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> менен туташууңуз ÑÑкирген шифр топтому менен шифрленген.</translation>
<translation id="5813119285467412249">Кошууну &amp;кайталоо</translation>
+<translation id="5817918615728894473">Байланыштыруу</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Төлөм ушул картадан өндүрүлөт, бирок анын номери бул Ñайт менен бөлүшүлбөйт. Кошумча коопÑуздук үчүн убактылуу CVC түзүлөт.}other{Төлөм Ñиз тандаган картадан өндүрүлөт, бирок анын номери бул Ñайт менен бөлүшүлбөйт. Кошумча коопÑуздук үчүн убактылуу CVC түзүлөт.}}</translation>
<translation id="5826507051599432481">Жалпы ат (ЖÐ)</translation>
<translation id="5838278095973806738">Бул Ñайтка Ñч кандай жеке маалымат киргизилбеши керек (миÑалы, ÑÑ‹Ñ€Ñөздөр же наÑÑ‹Ñ ÐºÐ°Ñ€Ñ‚Ð¾Ñ‡ÐºÐ°Ð»Ð°Ñ€Ñ‹Ð½Ñ‹Ð½ номерлери), Ñебеби аны чабуулчулар уурдап алышы мүмкүн.</translation>
@@ -1302,6 +1336,7 @@
<translation id="5855253129151731373">Бул Ñайттагы түйүндүн аталышы <ph name="LOOKALIKE_DOMAIN" /> Ñайтына окшош көрүнүшү мүмкүн. Чабуулчулар кÑÑ Ð±Ð¸Ñ€ учурларда домендин аталышына кичинекей, көзгө көрүнбөгөн өзгөртүүлөрдү киргизип, Ñайттарды туурашат.
Эгер бул жаңылыш көрÑөтүлүп жатат деп ойлоÑоңуз, https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals баракчаÑына баш багыңыз.</translation>
+<translation id="5860033963881614850">Өчүк</translation>
<translation id="5862579898803147654">8-төшөгүч</translation>
<translation id="5863847714970149516">Кийинки баракка Ó©Ñ‚Ñөңүз, акы алынышы мүмкүн</translation>
<translation id="5866257070973731571">Телефон номерин кошуу</translation>
@@ -1318,6 +1353,7 @@
<translation id="5913377024445952699">Экранды тартуу тындырылды</translation>
<translation id="59174027418879706">Иштетилген</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 колдонулууда}other{# колдонулууда}}</translation>
<translation id="5921185718311485855">Күйүк</translation>
<translation id="5921639886840618607">Карта Google аккаунтуңузда ÑакталÑынбы?</translation>
<translation id="5922853866070715753">Бүткөнү калды</translation>
@@ -1337,6 +1373,7 @@
<translation id="5989320800837274978">Бекитилген прокÑи Ñерверлер да, .pac Ñкрипттин URL'и да көрÑөтүлгөн жок.</translation>
<translation id="5992691462791905444">Инженердик Z формаÑында бүктөө</translation>
<translation id="6000758707621254961">"<ph name="SEARCH_TEXT" />" Ñурамы боюнча <ph name="RESULT_COUNT" /> жыйынтык табылды</translation>
+<translation id="6006484371116297560">КлаÑÑикалык тема</translation>
<translation id="6008122969617370890">N–1 ирети</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">СырÑөздөрүңүздү текшериңиз</translation>
@@ -1358,6 +1395,7 @@
<translation id="6045164183059402045">Ð’Ñ‘Ñ€Ñтканын үлгүÑÒ¯</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="6049004884579590341">Толук Ñкандан чыгуу үчүн |<ph name="ACCELERATOR" />| баÑкычын баÑып, кармап туруңуз</translation>
<translation id="6049488691372270142">Баракты жеткирүү</translation>
<translation id="6051221802930200923">ВебÑайт таÑтыктама бекиткичин колдонуп жаткандыктан азыр <ph name="SITE" /> Ñайтына Ó©Ñ‚Ó© албайÑыз. Ðдатта тармактагы каталар жана чабуулдар убактылуу көрүнүш болгондуктан, бул баракча кийинчерÑÑк иштеп калышы мүмкүн.</translation>
<translation id="6051898664905071243">Барактардын Ñаны:</translation>
@@ -1374,6 +1412,7 @@
<translation id="610911394827799129">Google аккаунтуңуздун Ñерептөө таржымалынын башка түрлөрү <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> дарегинде болушу мүмкүн.</translation>
<translation id="6116338172782435947">Ðлмашуу буферине көчүрүлгөн текÑтти жана Ñүрөттөрдү көрүү</translation>
<translation id="6120179357481664955">UPI идентификаторуңуз ÑакталÑынбы?</translation>
+<translation id="6123290840358279103">Виртуалдык картаны көрүү</translation>
<translation id="6124432979022149706">Chrome Enterprise туташтыргычтары</translation>
<translation id="6146055958333702838">Колдонулуп жаткан кабелдерди текшерип, роутер, модем жана башка
тармак түзмөктөрүн өчүрүп-күйгүзүңүз.</translation>
@@ -1410,6 +1449,7 @@
<translation id="6289939620939689042">Барактын Ñ‚Ò¯ÑÒ¯</translation>
<translation id="6290238015253830360">Сунушталган макалалар ушул жерде көрүнөт</translation>
<translation id="6293309776179964942">JIS B5 (182mm x 257mm)</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome'догу Google Жардамчы токтотулууда</translation>
<translation id="6305205051461490394"><ph name="URL" /> Ñайты жеткиликÑиз.</translation>
<translation id="6312113039770857350">Веб-баракча жеткиликтүү ÑмеÑ</translation>
@@ -1435,6 +1475,7 @@
<translation id="6390200185239044127">Жарымынан Z формаÑында бүктөө</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> cайтынан бул жерге чаптоо аракети админиÑтратордун ÑаÑÑатына ылайык бөгөттөлгөн</translation>
+<translation id="6398765197997659313">Толук Ñкран режиминен чыгуу</translation>
<translation id="6401136357288658127">Бул ÑаÑÑат жоюлган. Ðнын ордуна <ph name="NEW_POLICY" /> ÑаÑÑатын колдонуңуз.</translation>
<translation id="6404511346730675251">КыÑтарманы түзөтүү</translation>
<translation id="6406765186087300643">C0 (Конверт)</translation>
@@ -1447,7 +1488,6 @@
<translation id="6428450836711225518">Телефон номериңизди ыраÑтаңыз</translation>
<translation id="6433490469411711332">Байланыш маалыматын түзөтүү</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> Ñайты туташуудан баш тартты.</translation>
-<translation id="6434309073475700221">Жарактан чыгаруу</translation>
<translation id="6440503408713884761">Этибарга алынган жок</translation>
<translation id="6443406338865242315">КайÑÑ‹ кеңейтүүлөрдү жана плагиндерди орнотуп алдыңыз</translation>
<translation id="6446163441502663861">Kahu (Конверт)</translation>
@@ -1490,6 +1530,7 @@
<translation id="6624427990725312378">Байланыш маалыматы</translation>
<translation id="6626291197371920147">Жарактуу карточканын номерин кошуңуз</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Издөө</translation>
+<translation id="6630043285902923878">USB түзмөктөрү изделүүдө…</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="663260587451432563">JIS B4 (257mm x 364mm)</translation>
<translation id="6643016212128521049">Тазалоо</translation>
@@ -1505,6 +1546,7 @@
<translation id="6671697161687535275">Форма Ñунушу Chromium'дан алынып ÑалынÑынбы?</translation>
<translation id="6685834062052613830">Каттоо ÑÑебинен чыгып, жөндөөнү аÑгына чыгарыңыз</translation>
<translation id="6687335167692595844">Ðриптин өлчөмү Ñуралды</translation>
+<translation id="6688743156324860098">Жаңыртуу…</translation>
<translation id="6689249931105087298">Кара чекит кыÑууÑуна тийиштүү</translation>
<translation id="6689271823431384964">Ðккаунтуңузга кирип турганыңыздан улам, Chrome карталарыңызды Google аккаунтуңузга Ñактап коюуну Ñунуштап жатат. Бул параметрди жөндөөлөргө өтүп, өзгөртүп койÑоңуз болот. Картанын ÑÑÑи – аккаунттун ÑÑÑи болуп ÑÑептелет.</translation>
<translation id="6698381487523150993">Түзүлгөн:</translation>
@@ -1520,6 +1562,7 @@
<translation id="6744009308914054259">Интернет байланышын күткөнчө, Жүктөлүп алынган файлдарды ачып, макалаларды оффлайнда окуп туруңуз.</translation>
<translation id="6753269504797312559">СаÑÑат мааниÑи</translation>
<translation id="6757797048963528358">Түзмөгүңүз уктап калды.</translation>
+<translation id="6767985426384634228">Дарек жаңыртылÑынбы?</translation>
<translation id="6768213884286397650">Hagaki (Ðчык кат)</translation>
<translation id="6775759552199460396">JIS B2 (515mm x 728mm)</translation>
<translation id="67862343314499040">Кызгылт көк</translation>
@@ -1542,6 +1585,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome бул баракты окууну жеңилдетүү үчүн жөнөкөйлөттү Chrome кооптуу туташуу аркылуу түпнуÑка баракты алды.</translation>
<translation id="6891596781022320156">СаÑÑат деңгÑÑли колдоого алынбайт.</translation>
+<translation id="6895143722905299846">Виртуалдык номер:</translation>
<translation id="6895330447102777224">Карточкаңыз текшерилди</translation>
<translation id="6897140037006041989">Колдонуучунун агенти</translation>
<translation id="6898699227549475383">Уюм (У)</translation>
@@ -1577,10 +1621,10 @@
<translation id="7004583254764674281">Карталарды тезирÑÑк ыраÑтоо үчүн Windows Hello функциÑÑын колдонуу</translation>
<translation id="7006930604109697472">Баары бир жөнөтүлÑүн</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Өлчөмүн өзгөртүү боюнча жөндөөлөр</translation>
<translation id="7014741021609395734">Чоңойтуп/кичирейтүү деңгÑÑли</translation>
<translation id="7016992613359344582">Ðлар бир жолу төлөнүүчү же кайталануучу төлөмдөр болушу мүмкүн, бирок алар ачык көрүнбөйт.</translation>
<translation id="7029809446516969842">СырÑөздөр</translation>
+<translation id="7030436163253143341">ТаÑтыктама жарамдуу ÑмеÑ</translation>
<translation id="7031646650991750659">КайÑÑ‹ Google Play колдонмолорун орнотуп алдыңыз</translation>
<translation id="7050187094878475250"><ph name="DOMAIN" /> доменине кирүүгө аракет кылдыңыз, бирок Ñервер ишенимдүү болушу үчүн жарактуу мөөнөтү Ó©Ñ‚Ó© узун урукÑаттама берди.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Бул картаны азыр Ñактап коюуга болбойт}other{Бул карталарды азыр Ñактап коюуга болбойт}}</translation>
@@ -1650,12 +1694,14 @@
<translation id="7300012071106347854">Кочкул көк</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Бийик</translation>
+<translation id="7305756307268530424">Жайдан баштоо</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Туташуу боюнча жардам алуу</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" бөлүгүн жашыруу</translation>
<translation id="733354035281974745">Түзмөктөгү аккаунтту өзгөртүү</translation>
<translation id="7333654844024768166">СырÑөзүңүздү жаңы Ñле адаштыруучу Ñайтта киргиздиңиз. Chromium ушул ÑÑ‹Ñ€Ñөздү колдонгон <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> жана башка Ñайттарга өтүп, аны азыр өзгөртүүнү Ñунуштайт.</translation>
<translation id="7334320624316649418">Иреттештирүүнү &amp;кайталоо</translation>
+<translation id="7337248890521463931">Көбүрөөк көрÑÓ©Ñ‚Ò¯Ò¯</translation>
<translation id="7337706099755338005">Сиздин платформада жеткиликÑиз.</translation>
<translation id="733923710415886693">Сервердин таÑтыктамаÑÑ‹ "ТаÑтыктаманын тунуктук ÑаÑÑаты" аркылуу ачыкка чыгарылган ÑмеÑ.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1663,6 +1709,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Буйрук Ñабы</translation>
<translation id="7359588939039777303">Жарнамалар бөгөттөлдү.</translation>
+<translation id="7363096869660964304">ОшентÑе да, Ñиз көрүнбөй калбайÑыз. Жашыруун режимге Ó©Ñ‚Ò¯Ò¯ менен, көргөн вебÑайттарыңызды иш берүүчүңүздөн, Интернет кызматын жабдуучудан же баш баккан вебÑайттарыңыздан жашыра албайÑыз.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome жөндөөлөрүнөн даректерди кошуу жана башкаруу үчүн Tab, андан Ñоң Enter баÑкычын баÑыңыз</translation>
<translation id="7365849542400970216">Түзмөгүңүз колдонулган учур Ñайттарга билдирилÑинби?</translation>
<translation id="7372973238305370288">издөө натыйжаÑÑ‹</translation>
@@ -1673,7 +1720,9 @@
<translation id="7378594059915113390">Медианы башкаруу Ñлементтери</translation>
<translation id="7378627244592794276">Жок</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Колдонулбайт</translation>
<translation id="7390545607259442187">Карточканы текшерүү</translation>
+<translation id="7392089738299859607">Даректи жаңыртуу</translation>
<translation id="7399802613464275309">КоопÑуздукту текшерүү</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> түзмөгүңүз башкарылып жатат</translation>
@@ -1688,6 +1737,7 @@
&lt;li&gt;Программаны компьютериңизден биротоло алып Ñалуунун жолун билип алуу үчүн &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome’дун жардам борборуна&lt;/a&gt; баш багыңыз
&lt;ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Cүйкүмдүү</translation>
<translation id="7416351320495623771">СырÑөздөрдү башкаруу…</translation>
<translation id="7419106976560586862">Профиль жолу</translation>
<translation id="7437289804838430631">Байланыш маалыматын кошуу</translation>
@@ -1703,7 +1753,7 @@
<translation id="7481312909269577407">Багыттоо</translation>
<translation id="7485870689360869515">Дайындар табылган жок.</translation>
<translation id="7495528107193238112">Бул мазмун бөгөттөлгөн. Көйгөйдү чечүү үчүн Ñайттын ÑÑÑине байланышыңыз.</translation>
-<translation id="7498234416455752244">Түзөтүүнү улантуу</translation>
+<translation id="7498193950643227031">Эгер өлчөмүн өзгөртÑөңүз, туура ÑÐ¼ÐµÑ Ð¸ÑˆÑ‚ÐµÑˆÐ¸ мүмкүн. Эми колдонмолордун өлчөмүн өзгөртүүгө <ph name="SETTINGS" /> аркылуу чектөө койÑоңуз болот.</translation>
<translation id="7503664977220660814">СырÑөзүңүздү жаңы Ñле адаштыруучу Ñайтта киргиздиңиз. Chromium <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> жана башка Ñайттарда колдонгон ушул жана Ñакталган ÑÑ‹Ñ€Ñөздөрүңүздү текшерүүнү Ñунуштайт.</translation>
<translation id="7508255263130623398">Кайтарылган ÑаÑÑат түзмөгүнүн id'Ñи бош же учурдагы түзмөктүн id'Ñине дал келбейт</translation>
<translation id="7508870219247277067">Жашыл (авокадо)</translation>
@@ -1723,6 +1773,7 @@
<translation id="7548892272833184391">Интернетке туташуудагы каталарды оңдоо</translation>
<translation id="7549584377607005141">Бул веб-баракча туура ачылышы үчүн мурун киргизилген дайындар талап кылынат. Дайындарды кайра жиберÑеңиз болот, бирок анда бул баракчада буга чейин жаÑалган аракеттерди кайталап калаÑыз.</translation>
<translation id="7550637293666041147">Түзмөктөгү колдонуучу атыңыз жана Chrome'догу колдонуучу атыңыз</translation>
+<translation id="755279583747225797">Сыноо жигердүү</translation>
<translation id="7552846755917812628">Төмөнкү кеңештерди пайдаланып көрүңүз:</translation>
<translation id="7554475479213504905">Баары бир кайра жүктөп, көрÑÓ©Ñ‚Ò¯Ò¯</translation>
<translation id="7554791636758816595">Жаңы өтмөк</translation>
@@ -1741,7 +1792,6 @@
<translation id="7610193165460212391">Маани <ph name="VALUE" /> аралыгынан чыгып кетти.</translation>
<translation id="7613889955535752492">Мөөнөтү бүтөт: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Chrome'дун жөндөөлөрүнө өтүп, ÑÑ‹Ñ€Ñөздөрдү көрүү жана башкаруу үчүн, Tab, андан Ñоң Enter баÑкычтарын баÑыңыз</translation>
-<translation id="7615602087246926389">Дайын-даректериңизди Google Ðккаунтуңуздун башка верÑиÑÑынын ÑÑ‹Ñ€Ñөзүн колдонуп шифрлеп коюптурÑуз. Ðны төмөнкүгө киргизиңиз.</translation>
<translation id="7616645509853975347">ÐдминиÑтраторуңуз Ñерепчиңизде Chrome Enterprise туташтыргычтарын иштетти. Бул туташтыргычтардын айрым маалыматыңызга кирүү мүмкүнчүлүктөрү бар.</translation>
<translation id="7619838219691048931">Ðкыркы барак</translation>
<translation id="762844065391966283">Бир-бирден</translation>
@@ -1806,13 +1856,12 @@
<translation id="782886543891417279">Сиз колдонуп жаткан Wi-Fi (<ph name="WIFI_NAME" />), башкы кирүү барагына өтүшүңүздү талап кылышы мүмкүн.</translation>
<translation id="7836231406687464395">Postfix (Конверт)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Эч бири}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Файлары түрлөрүнө жараша ачуу.</translation>
<translation id="7862185352068345852">Сайттан чыгаÑызбы?</translation>
<translation id="7865448901209910068">Мыкты ылдамдык</translation>
<translation id="7874263914261512992">СырÑөзүңүздү жаңы Ñле адаштыруучу Ñайтта киргиздиңиз. Chrome <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> жана башка Ñайттарда колдонгон ушул жана Ñакталган ÑÑ‹Ñ€Ñөздөрүңүздү азыр текшерүүнү Ñунуштайт.</translation>
<translation id="7878562273885520351">СырÑөзүңүздү башка адамдар бузуп кирген окшойт</translation>
+<translation id="7880146494886811634">Даректи Ñактоо</translation>
<translation id="7882421473871500483">Күрөң</translation>
<translation id="7887683347370398519">CVC'иңизди текшерип, кайталап көрүңүз</translation>
<translation id="7887885240995164102">Сүрөт ичиндеги Ñүрөт режимине кирүү</translation>
@@ -1820,6 +1869,7 @@
<translation id="7894280532028510793">Эгер туура жазылÑа, <ph name="BEGIN_LINK" />Тармактагы мүчүлүштүктөрдү аныктоону<ph name="END_LINK" /> иштетип көрүңүз.</translation>
<translation id="7904208859782148177">C3 (Конверт)</translation>
<translation id="7931318309563332511">БелгиÑиз</translation>
+<translation id="793209273132572360">Дарек жаңыртылÑынбы?</translation>
<translation id="7932579305932748336">Пальто</translation>
<translation id="79338296614623784">Жарактуу телефон номерин киргизиңиз</translation>
<translation id="7934052535022478634">Төлөм аткарылды</translation>
@@ -1890,6 +1940,7 @@
<translation id="8175796834047840627">Ðккаунтуңузга кирип турганыңыздан улам, Chrome карталарыңызды Google аккаунтуңузга Ñактап коюуну Ñунуштап жатат. Бул параметрди жөндөөлөргө өтүп, өзгөртүп койÑоңуз болот.</translation>
<translation id="8176440868214972690">Бул түзмөктүн админиÑтратору жөндөөлөр же ÑаÑÑаттар ÑÑ‹Ñктуу айрым маалыматты төмөндөгү вебÑайттарга жөнөттү.</translation>
<translation id="8184538546369750125">Дүйнөлүк демейки жөндөөнү колдонуу (УрукÑат берүү)</translation>
+<translation id="8193086767630290324">ÐšÑƒÐ¿ÑƒÑ Ð¼Ð°Ð°Ð»Ñ‹Ð¼Ð°Ñ‚ колдонулган аракеттер</translation>
<translation id="8194797478851900357">Жылдырууну &amp;жаÑабоо</translation>
<translation id="8201077131113104583">ID "<ph name="EXTENSION_ID" />" кеңейтүүÑÒ¯ үчүн жаракÑыз жаңыртуу URL.</translation>
<translation id="8202097416529803614">Буйрутманын корутундуÑу</translation>
@@ -1912,6 +1963,7 @@
<translation id="8249296373107784235">Токтотуу</translation>
<translation id="8249320324621329438">Ðкыркы алынган:</translation>
<translation id="8253091569723639551">Төлөмдүн дареги талап кылынат</translation>
+<translation id="8257387598443225809">Бул колдонмо мобилдик түзмөк үчүн түзүлгөн</translation>
<translation id="825929999321470778">Бардык Ñакталган ÑÑ‹Ñ€Ñөздөрдү көрÑÓ©Ñ‚Ò¯Ò¯</translation>
<translation id="8261506727792406068">Жок кылуу</translation>
<translation id="8262952874573525464">Төмөнкү четин жамоо</translation>
@@ -1984,7 +2036,7 @@
<translation id="8511402995811232419">Cookie файлдарын башкаруу</translation>
<translation id="8522552481199248698">Chrome Google аккаунтуңуздун коопÑуздугун коргоп, ÑÑ‹Ñ€Ñөзүңүздү өзгөртүүгө жардам берет.</translation>
<translation id="8530813470445476232">Chrome'дун жөндөөлөрүнө өтүп, Ñерептөө таржымалын, cookie файлдарын, кÑштерди жана башкаларды өчүрүңүз</translation>
-<translation id="8533619373899488139">Бөгөттөлгөн URL'дерди жана тутум админиÑтраторуңуз ишке киргизген ÑаÑÑаттарды көрүү үчүн, &lt;strong&gt;chrome://policy&lt;/strong&gt; дарегине кириңиз.</translation>
+<translation id="8533619373899488139">Бөгөттөлгөн URL'дерди жана тутум админиÑтраторуңуз ишке киргизген ÑаÑÑаттарды көрүү үчүн &lt;strong&gt;chrome://policy&lt;/strong&gt; дарегине кириңиз.</translation>
<translation id="8541158209346794904">Bluetooth түзмөгү</translation>
<translation id="8542014550340843547">Төмөнкү жагын үч жолу тешүү</translation>
<translation id="8543181531796978784"><ph name="BEGIN_ERROR_LINK" />Ðныкталган көйгөйдү кабарлаÑаңыз<ph name="END_ERROR_LINK" /> болот, же жеке дайын-даректериңиз зыÑнга учурап калат деп коркпоÑоңуз, <ph name="BEGIN_LINK" />бул кооптуу Ñайтка кире<ph name="END_LINK" /> бериңиз.</translation>
@@ -2035,7 +2087,6 @@
<translation id="8719528812645237045">Муштум менен өйдө жакка Ñки жолу уруу</translation>
<translation id="8725066075913043281">Кайра аракет кылып көрүү</translation>
<translation id="8726549941689275341">Барактын өлчөмү:</translation>
-<translation id="8728672262656704056">Жашыруун кирдиңиз</translation>
<translation id="8730621377337864115">Бүттү</translation>
<translation id="8731544501227493793">СырÑөздөрдү башкаруу баÑкычы. Chrome'дун жөндөөлөрүнө өтүп, ÑÑ‹Ñ€Ñөздөрдү көрүү жана башкаруу үчүн, Enter баÑкычын баÑыңыз</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> түзмөгүңүз <ph name="MANAGER" /> тарабынан башкарылууда</translation>
@@ -2112,6 +2163,7 @@
<translation id="9020542370529661692">Бул бет <ph name="TARGET_LANGUAGE" /> тилине которулду</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ЖаракÑыз)</translation>
+<translation id="9030265603405983977">Монохром</translation>
<translation id="9035022520814077154">КоопÑуздук катаÑÑ‹</translation>
<translation id="9038649477754266430">Барактарды тезирÑÑк жүктөө үчүн алдын ала айтуу кызматын колдонуңуз</translation>
<translation id="9039213469156557790">Ðндан тышкары, бул бетте башка кооптуу булактар бар. Өткөрүү учурунда аларды башка колдонуучулар көрө алышат, ошону менен катар, беттин иш-аракетин өзгөртүү үчүн аларды чабуулчулар бурмалап коюшу мүмкүн.</translation>
@@ -2135,6 +2187,7 @@
<translation id="91108059142052966">ÐšÑƒÐ¿ÑƒÑ Ð½ÐµÑ€Ñелер көрүнүп турганда ÐдминиÑтратордун ÑаÑÑатына ылайык Ñкранды <ph name="APPLICATION_TITLE" /> менен бөлүшүүгө болбойт</translation>
<translation id="9114524666733003316">Карта текшерилүүдө…</translation>
<translation id="9114581008513152754">Бул Ñерепчи компаниÑңыз же башка уюм тарабынан башкарылбайт. Бул түзмөктө аткарылган аракеттер Chrome'дон тышкары башкарылышы мүмкүн. <ph name="BEGIN_LINK" />Кеңири маалымат<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Жаңы</translation>
<translation id="9119042192571987207">Жүктөлүп берилди</translation>
<translation id="9128016270925453879">СаÑÑаттар жүктөлдү</translation>
<translation id="9128870381267983090">Тармакка туташуу</translation>
@@ -2153,6 +2206,7 @@
<translation id="9170848237812810038">&amp;Кайтаруу</translation>
<translation id="9171296965991013597">Колдонмодон чыгаÑызбы?</translation>
<translation id="9173282814238175921">Жалгыз документ/Жаңы барак</translation>
+<translation id="9173995187295789444">Bluetooth түзмөктөрү изделип жатат...</translation>
<translation id="917450738466192189">Сервер таÑтыктамаÑÑ‹ жаракÑыз.</translation>
<translation id="9174917557437862841">"Өтмөктү которуштургуч" баÑкычы. Бул өтмөккө которулуу үчүн, "Enter" баÑкычын баÑыңыз.</translation>
<translation id="9179703756951298733">Chrome'дун жөндөөлөрүнө өтүп, төлөмдөрүңүздү жана наÑÑ‹Ñ ÐºÐ°Ñ€Ñ‚Ð°Ò£Ñ‹Ð·Ð´Ñ‹Ð½ маалыматын башкарыңыз</translation>
@@ -2185,7 +2239,7 @@
<translation id="985956168329721395">Prc-32K</translation>
<translation id="987264212798334818">Жалпы</translation>
<translation id="988159990683914416">Иштеп чыгуучунун курамаÑÑ‹</translation>
-<translation id="989988560359834682">Даректи түзөтүү</translation>
+<translation id="989988560359834682">Даректи өзгөртүү</translation>
<translation id="992115559265932548"><ph name="MICROSOFT_ACTIVE_DIRECTORY" /></translation>
<translation id="992256792861109788">Кызгылтым</translation>
<translation id="992432478773561401">"<ph name="SOFTWARE_NAME" />" программаÑÑ‹ компьютериңизде же тармагыңызда туура орнотулган ÑмеÑ:
diff --git a/chromium/components/strings/components_strings_lo.xtb b/chromium/components/strings/components_strings_lo.xtb
index ad3c91b157d..d3821f99296 100644
--- a/chromium/components/strings/components_strings_lo.xtb
+++ b/chromium/components/strings/components_strings_lo.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">ຖ້າ​à»àº²àºâ€‹àº•àº´àºâ€‹à»€àº­àº»àº²â€‹à»àº¥à»‰àº§, Chrome ຈະ​ຮັàºâ€‹àºªàº²â€‹àºªàº³â€‹à»€àº™àº»àº²â€‹àº‚ອງ​ບັດ​ຂອງ​ທ່ານ​ຢູ່​ເທິງ​ອຸ​ປະ​àºàº­àº™â€‹àº™àºµà»‰ ເພື່ອ​àºàº²àº™â€‹àº›àº°â€‹àºàº­àºšâ€‹à»àºšàºšâ€‹àºŸàº­àº¡â€‹à»ƒàº«à»‰â€‹à»„ວ​ຂຶ້ນ.</translation>
<translation id="1110994991967754504">ເລືອàºàºàº²àº™àº­àº°àº™àº¸àºàº²àº”ສຳລັບ <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">ປ່ຽນ​àºàº±àºšâ€‹àº„ືນຄà»àº²àºªàº±à»ˆàº‡àºˆàº±àº”ລà»àº²àº”ັບຄືນ</translation>
+<translation id="1123753900084781868">ຄຳບັນàºàº²àºàºªàº»àº”ບà»à»ˆàºªàº²àº¡àº²àº”ໃຊ້ໄດ້ໃນຕອນນີ້</translation>
<translation id="1125573121925420732">ອາດຈະເຫັນຄຳເຕືອນເລື້ອàºà»†à»ƒàº™àº‚ະນະທີ່ເວັບໄຊອັບເດດຄວາມປອດໄພຂອງພວàºàº¡àº±àº™. ສິ່ງນີ້ຈະດີຂຶ້ນໃນໄວໆນີ້.</translation>
<translation id="112840717907525620">à»àº„ຊ໌ນະໂàºàºšàº²àºà»ƒàºŠà»‰à»„ດ້</translation>
<translation id="1130564665089811311">ປຸ່ມà»àº›à»œà»‰àº², àºàº»àº” Enter ເພື່ອà»àº›à»œà»‰àº²àº™àºµà»‰àº”້ວຠGoogle à»àº›àºžàº²àºªàº²</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">ຊື່ອຸປະàºàº­àº™àº‚ອງທ່ານ</translation>
<translation id="124116460088058876">ພາສາເພີ່ມເຕີມ</translation>
<translation id="1243027604378859286">ຜູ້ຂຽນ:</translation>
+<translation id="1246424317317450637">ໂຕເຂັ້ມ</translation>
<translation id="1250759482327835220">ເພື່ອຈ່າàºà»„ດ້ໄວàºàº§à»ˆàº²à»ƒàº™àº„ັ້ງຕà»à»ˆà»„ປ, àºàº°àº¥àº¸àº™àº²àºšàº±àº™àº—ຶàºàºšàº±àº” à»àº¥àº° ທີ່ຢູ່ຮຽàºà»€àºàº±àºšà»€àº‡àº´àº™àº‚ອງທ່ານໄວ້ໃນບັນຊີ Google ຂອງທ່ານ.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (ຊິ້ງຂà»à»‰àº¡àº¹àº™à»àº¥à»‰àº§)</translation>
<translation id="1256368399071562588">&lt;p&gt;ຖ້າທ່ານພະàºàº²àºàº²à»€àº‚ົ້າເບິ່ງເວັບໄຊ à»àº¥àº° ມັນບà»à»ˆà»€àº›àºµàº”ຂຶ້ນມາ, àºà»ˆàº­àº™àº­àº·à»ˆàº™àºàº°àº¥àº¸àº™àº²àº¥àº­àº‡à»àºà»‰à»„ຂຂà»à»‰àºœàº´àº”ພາດດ້ວàºàº‚ັ້ນຕອນà»àºà»‰à»„ຂບັນຫາເຫຼົ່ານີ້:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">ປ່ຽນລະຫັດຜ່ານຂອງທ່ານ</translation>
<translation id="1484290072879560759">ເລືອàºàº—ີ່ຢູ່àºàº²àº™àºˆàº±àº”ສົ່ງ</translation>
<translation id="1492194039220927094">àºàº²àº™à»àºˆà»‰àº‡à»€àº•àº·àº­àº™àº™àº°à»‚àºàºšàº²àº:</translation>
+<translation id="1495677929897281669">àºàº±àºšàº„ືນຫາà»àº–ບ</translation>
<translation id="1501859676467574491">ສະà»àº”ງບັດຈາàºàºšàº±àº™àºŠàºµ Google ຂອງທ່ານ</translation>
<translation id="1507202001669085618">&lt;p&gt;ທ່ານຈະເຫັນຂà»à»‰àºœàº´àº”ພາດນີ້ຖ້າທ່ານàºàº³àº¥àº±àº‡à»ƒàºŠà»‰à»œà»‰àº²à»€àº§àº±àºš Wi-Fi ບ່ອນທີ່ທ່ານຈຳເປັນຕ້ອງເຂົ້າສູ່ລະບົບàºà»ˆàº­àº™àº—ີ່ທ່ານຈະສາມາດອອນລາàºà»„ດ້.&lt;/p&gt;
&lt;p&gt;ເພື່ອà»àºà»‰à»„ຂຂà»à»‰àºœàº´àº”ພາດ, àºàº°àº¥àº¸àº™àº²àº„ລິຠ&lt;strong&gt;ເຊື່ອມຕà»à»ˆ&lt;/strong&gt; ຢູ່ໃນໜ້າທີ່ທ່ານàºàº³àº¥àº±àº‡àºžàº°àºàº²àºàº²àº¡à»€àº›àºµàº”.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">ໜ້ານີ້ບອàº</translation>
<translation id="153384715582417236">à»àº»àº”à»àº¥à»‰àº§àºªàº³àº¥àº±àºšàº•àº­àº™àº™àºµà»‰</translation>
<translation id="1536390784834419204">à»àº›à»œà»‰àº²</translation>
+<translation id="1539840569003678498">ສົ່ງລາàºàº‡àº²àº™à»àº¥à»‰àº§:</translation>
<translation id="154408704832528245">ເລືອàºàº—ີ່ຢູ່ອຸປະàºàº­àº™</translation>
<translation id="1549470594296187301">ຕ້ອງເປີດໃຊ້ງານ JavaScript ເພື່ອໃຊ້ຄຸນສົມບັດໃຊ້ງານນີ້.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">ດ້ານຂອບສັ້ນàºà»ˆàº­àº™</translation>
<translation id="168693727862418163">àºàº§àº”ຮັບຮອງຄ່ານະໂàºàºšàº²àºàº™àºµà»‰àº—ຽບàºàº±àºšàº®àº¹àºšà»àºšàºšàº‚ອງມັນບà»à»ˆàºªàº³à»€àº¥àº±àº” à»àº¥àº° ຈະຖືàºàº¥àº°à»€àº¥àºµàº.</translation>
<translation id="168841957122794586">ໃບຢັ້ງຢືນເຊີບເວີມີລະຫັດ cryptographic ທີ່ອ່ອນ.</translation>
+<translation id="1696290444144917273">ເບິ່ງລາàºàº¥àº°àº­àº½àº”ບັດສະເà»àº·àº­àº™</translation>
<translation id="1697532407822776718">ທ່ານຕັ້ງຮຽບຮ້ອàºà»àº»àº”à»àº¥à»‰àº§!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{ເຊີບ​ເວີ​ນີ້​ບà»à»ˆâ€‹àºªàº²â€‹àº¡àº²àº”​ພິ​ສູດ​ໄດ້​ວ່າ​ມັນ​à»àº¡à»ˆàº™ <ph name="DOMAIN" />;ໃບ​ຢັ້ງ​ຢືນ​ຄວາມ​ປອດ​ໄພ​ຂອງ​ທ່ານ​à»àº¡à»ˆàº™â€‹àº„າດ​ວ່າ​ຈະຕັ້ງ​à»àº•à»ˆâ€‹àº¡àº·à»‰â€‹àº­àº·à»ˆàº™â€‹à»„ປ. ອັນນີ້ອາດຈະເຮັດໃຫ້ເàºàºµàº”ມີàºàº²àº™àºàº³àº™àº»àº”ຄ່າຄ່າຜິດ ຫຼື ຜູ້ໂຈມຕີອາດຈະດັàºàºªàº°àºàº±àº”àºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆàº‚ອງທ່ານ.}other{ເຊີບ​ເວີ​ນີ້​ບà»à»ˆâ€‹àºªàº²â€‹àº¡àº²àº”​ພິ​ສູດ​ໄດ້​ວ່າ​ມັນ​à»àº¡à»ˆàº™ <ph name="DOMAIN" />; ໃບ​ຢັ້ງ​ຢືນ​ຄວາມ​ປອດ​ໄພ​ຂອງ​ທ່ານ​à»àº¡à»ˆàº™â€‹àº„າດ​ວ່າ​ຈະ​ຕັ້ງ​à»àº•à»ˆ # ວັນ​ໃນ​ອະ​ນາ​ຄົດ. ອັນນີ້ອາດຈະເຮັດໃຫ້ເàºàºµàº”ມີàºàº²àº™àºàº³àº™àº»àº”ຄ່າຄ່າຜິດ ຫຼື ຜູ້ໂຈມຕີອາດຈະດັàºàºªàº°àºàº±àº”àºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆàº‚ອງທ່ານ.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">ບà»à»ˆàºªàº»àº™à»ƒàºˆà»àº¥à»‰àº§à»€àº™àº·à»ˆàº­àº‡àºˆàº²àºàºšà»à»ˆà»„ດ້ຕັ້ງ <ph name="POLICY_NAME" /> ໃຫ້ເປັນ <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> ຕ້ອງàºàº²àº™à»€àºàº±àºšàº‚à»à»‰àº¡àº¹àº™à»„ວ້ໃນຄອມພິວເຕີສະເພາະບ່ອນຂອງທ່ານຢ່າງຖາວອນ</translation>
<translation id="1713628304598226412">ຖາດ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">àºà»ˆàº­àº‡àºˆàº»àº”à»àº²àº 3</translation>
<translation id="1718029547804390981">ເອàºàº°àºªàº²àº™à»ƒàº«àºà»ˆà»€àºàºµàº™àº—ີ່ຈະຂຽນຄຳອະທິບາàºàº„ວາມເຫັນໄດ້</translation>
<translation id="1721424275792716183">* ຊ່ອງໃ່ສ່ຂà»à»‰àº¡àº¹àº™àº—ີ່ຕ້ອງຕື່ມຂà»à»‰àº¡àº¹àº™</translation>
+<translation id="1727613060316725209">ໃບຮັບຮອງຖືàºàº•à»‰àº­àº‡</translation>
<translation id="1727741090716970331">ເພີ່ມເລàºàºšàº±àº”ທີ່ຖືàºàº•à»‰àº­àº‡</translation>
<translation id="1728677426644403582">ທ່ານàºàº³àº¥àº±àº‡à»€àºšàº´à»ˆàº‡à»àº«àº¼à»ˆàº‡àº—ີ່ມາຂອງໜ້າເວັບ</translation>
<translation id="173080396488393970">ບà»à»ˆàº®àº­àº‡àº®àº±àºšàº›àº°à»€àºžàº”ບັດນີ້</translation>
@@ -246,7 +253,6 @@
ຄຳຂà»àº‚ອງທ່ານສຳລັບ <ph name="SITE" /> ບà»à»ˆà»„ດ້. ນະໂàºàºšàº²àºàº•àº»à»‰àº™àº—າງສາມາດໃຊ້ໄດ້ໂດàº
ຜູ້ໃຫ້ບà»àº¥àº´àºàº²àº™à»€àº§àº±àºšà»„ຊເພື່ອàºàº³àº™àº»àº”ຄ່າຄວາມປອດໄພ à»àº¥àº° ຄຸນລັàºàºªàº°àº™àº°àº­àº·à»ˆàº™à»†àºªàº³àº¥àº±àºšà»€àº§àº±àºšà»„ຊ.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">àºàº°àº¥àº¸àº™àº²àº­àº±àºšà»€àº”ດວະລີຜ່ານຊິງຄ໌ຂອງທ່ານ.</translation>
<translation id="1787142507584202372">à»àº–ບທີ່ເປີດຢູ່ຂອງທ່ານປາàºàº»àº”ຢູ່ບ່ອນນີ້</translation>
<translation id="1791429645902722292">ລັອàºâ€‹àº­àº±àº”​ສະ​ລິ​àºàº° Google</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ມີຫຼາàºàº„ຳສັ່ງພ້ອມໃຫ້ນຳໃຊ້, àºàº»àº” Tab ເພື່ອເບິ່ງພວàºàº¡àº±àº™</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">ໂຄສະນາ</translation>
<translation id="1919367280705858090">ຂà»àº„ວາມຊ່ວàºà»€àº«àº¼àº·àº­à»€àº¥àº·à»ˆàº­àº‡àº‚à»à»‰àº„ວາມສະà»àº”ງຂà»à»‰àºœàº´àº”ພາດສະເພາະ</translation>
<translation id="192020519938775529">{COUNT,plural, =0{ບà»à»ˆàº¡àºµ}=1{1 ເວັບໄຊ}other{# ເວັບໄຊ}}</translation>
+<translation id="1924727005275031552">ໃà»à»ˆ</translation>
<translation id="1945968466830820669">ທ່ານອາດຈະສູນເສàºàºàº²àº™à»€àº‚ົ້າເຖິງບັນຊີຂອງອົງàºàº²àº™àº‚ອງທ່ານ ຫຼື ປະສົບàºàº±àºšàºàº²àº™àº¥àº±àºà»ƒàºŠà»‰àº•àº»àº§àº•àº»àº™.</translation>
<translation id="1947454675006758438">ໜີບàºàº°àº«àº¼àº±àºšà»€àºŸàºµàº¢àº¹à»ˆà»€àº—ິງສຸດເບື້ອງຂວາ</translation>
<translation id="1958218078413065209">ຄະà»àº™àº™àºªàº¹àº‡àºªàº¸àº”ຂອງທ່ານà»àº¡à»ˆàº™ <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">ຖາດ 7</translation>
<translation id="204357726431741734">ເຂົ້າສູ່ລະບົບເພື່ອໃຊ້ລະຫັດຜ່ານທີ່ບັນທຶàºà»„ວ້ໃນບັນຊີ Google ຂອງທ່ານ</translation>
<translation id="2053111141626950936">ລະບົບຈະບà»à»ˆà»àº›à»œà»‰àº²à»€àº›àº±àº™ <ph name="LANGUAGE" />.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{ເມື່ອເປີດàºàº²àº™àº„ວບຄຸມນີ້ à»àº¥àº° ສະຖານະເປັນà»àºšàºšà»€àº›àºµàº”ໃຊ້ຢູ່, Chrome ຈະàºàº³àº™àº»àº”ວ່າàºàº¸à»ˆàº¡àº„ົນຂະໜາດໃຫàºà»ˆàºàº¸à»ˆàº¡à»ƒàº” ຫຼື "àºàº¸à»ˆàº¡àº›àº°àºŠàº²àºàº­àº™àº•àº²àº¡àº®àº¸à»ˆàº™" ໃດທີ່ຄ້າàºàºàº±àºšàºàº²àº™à»€àº„ື່ອນໄຫວàºàº²àº™àº—່ອງເວັບຫຼ້າສຸດຂອງທ່ານ. ຜູ້ລົງໂຄສະນາສາມາດເລືອàºà»‚ຄສະນາສຳລັບàºàº¸à»ˆàº¡à»„ດ້ à»àº¥àº° àºàº²àº™à»€àº„ື່ອນໄຫວàºàº²àº™àº—່ອງເວັບຂອງທ່ານຈະຖືàºàºˆàº±àº”ເàºàº±àºšà»„ວ້ເປັນສ່ວນຕົວຢູ່ອຸປະàºàº­àº™àº‚ອງທ່ານ. àºàº¸à»ˆàº¡àº‚ອງທ່ານມີàºàº²àº™àº­àº±àºšà»€àº”ດທຸàºàº¡àº·à»‰.}=1{ເມື່ອເປີດàºàº²àº™àº„ວບຄຸມນີ້ à»àº¥àº° ສະຖານະເປັນà»àºšàºšà»€àº›àºµàº”ໃຊ້ຢູ່, Chrome ຈະàºàº³àº™àº»àº”ວ່າàºàº¸à»ˆàº¡àº„ົນຂະໜາດໃຫàºà»ˆàºàº¸à»ˆàº¡à»ƒàº” ຫຼື "àºàº¸à»ˆàº¡àº›àº°àºŠàº²àºàº­àº™àº•àº²àº¡àº®àº¸à»ˆàº™" ໃດທີ່ຄ້າàºàºàº±àºšàºàº²àº™à»€àº„ື່ອນໄຫວàºàº²àº™àº—່ອງເວັບຫຼ້າສຸດຂອງທ່ານ. ຜູ້ລົງໂຄສະນາສາມາດເລືອàºà»‚ຄສະນາສຳລັບàºàº¸à»ˆàº¡à»„ດ້ à»àº¥àº° àºàº²àº™à»€àº„ື່ອນໄຫວàºàº²àº™àº—່ອງເວັບຂອງທ່ານຈະຖືàºàºˆàº±àº”ເàºàº±àºšà»„ວ້ເປັນສ່ວນຕົວຢູ່ອຸປະàºàº­àº™àº‚ອງທ່ານ. àºàº¸à»ˆàº¡àº‚ອງທ່ານມີàºàº²àº™àº­àº±àºšà»€àº”ດທຸàºàº¡àº·à»‰.}other{ເມື່ອເປີດàºàº²àº™àº„ວບຄຸມນີ້ à»àº¥àº° ສະຖານະເປັນà»àºšàºšà»€àº›àºµàº”ໃຊ້ຢູ່, Chrome ຈະàºàº³àº™àº»àº”ວ່າàºàº¸à»ˆàº¡àº„ົນຂະໜາດໃຫàºà»ˆàºàº¸à»ˆàº¡à»ƒàº” ຫຼື "àºàº¸à»ˆàº¡àº›àº°àºŠàº²àºàº­àº™àº•àº²àº¡àº®àº¸à»ˆàº™" ໃດທີ່ຄ້າàºàºàº±àºšàºàº²àº™à»€àº„ື່ອນໄຫວàºàº²àº™àº—່ອງເວັບຫຼ້າສຸດຂອງທ່ານ. ຜູ້ລົງໂຄສະນາສາມາດເລືອàºà»‚ຄສະນາສຳລັບàºàº¸à»ˆàº¡à»„ດ້ à»àº¥àº° àºàº²àº™à»€àº„ື່ອນໄຫວàºàº²àº™àº—່ອງເວັບຂອງທ່ານຈະຖືàºàºˆàº±àº”ເàºàº±àºšà»„ວ້ເປັນສ່ວນຕົວຢູ່ອຸປະàºàº­àº™àº‚ອງທ່ານ. àºàº¸à»ˆàº¡àº‚ອງທ່ານມີàºàº²àº™àº­àº±àºšà»€àº”ດທຸຠ{NUM_DAYS} ມື້.}}</translation>
<translation id="2053553514270667976">ລະ​ຫັດ​ຊິບ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ຄຳ​à»àº™àº°àº™àº³}other{# ຄຳ​à»àº™àº°àº™àº³}}</translation>
<translation id="2071692954027939183">àºàº²àº™à»àºˆà»‰àº‡à»€àº•àº·àº­àº™àº–ືàºàºšàº¥àº±àº­àºà»„ວ້ອັດຕະໂນມັດເນື່ອງຈາàºàº—່ານບà»à»ˆàº­àº°àº™àº¸àºàº²àº”ພວàºàº¡àº±àº™</translation>
<translation id="2079545284768500474">ບà»à»ˆà»€àº®àº±àº”</translation>
<translation id="20817612488360358">àºàº²àº™àº•àº±à»‰àº‡àº„່າພຣັອàºàºŠàºµàº¥àº°àºšàº»àºšàº–ືàºàº•àº±à»‰àº‡à»ƒàº«à»‰àº–ືàºàº™à»àº²à»ƒàºŠà»‰ à»àº•à»ˆàºàº²àº™àº›àº±àºšàº•àº±à»‰àº‡àº„່າພຣັອàºàºŠàºµàº—ີ່ຈະà»àºˆà»‰àº‡à»„ດ້ຖືàºàº¥àº°àºšàº¸â€‹à»àºˆà»‰àº‡àº™à»àº²àº­àºµàº.</translation>
<translation id="2082238445998314030">ຜົນຮັບ <ph name="RESULT_NUMBER" /> ຈາຠ<ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">ບັນທຶàºâ€¦</translation>
<translation id="2088086323192747268">ຈັດàºàº²àº™àº›àº¸à»ˆàº¡àºŠàº´à»‰àº‡àº‚à»à»‰àº¡àº¹àº™, àºàº»àº” Enter ເພື່ອຈັດàºàº²àº™àº§à»ˆàº²àº‚à»à»‰àº¡àº¹àº™à»ƒàº”ທີ່ທ່ານຈະຊິ້ງຂà»à»‰àº¡àº¹àº™à»ƒàº™àºàº²àº™àº•àº±à»‰àº‡àº„່າ Chrome</translation>
<translation id="2091887806945687916">ສຽງ</translation>
<translation id="2094505752054353250">ໂດເມນບà»à»ˆà»€àº‚ົ້າຄູ່àºàº±àº™</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> ຈຳເປັນຕ້ອງມີຊື່ຜູ້ໃຊ້ à»àº¥àº°àº¥àº°àº«àº±àº”ຜ່ານ.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, à»àº»àº”ອາàºàº¸à»ƒàº™àº§àº±àº™àº—ີ <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">àºàº²àº™àº•àº±à»‰àº‡àº„່າທີ່ຄວບຄຸມໂດàºàºœàº¹à»‰à»€àºšàº´à»ˆàº‡à»àºàº‡àº¥àº°àºšàº»àºšàº‚ອງທ່ານ</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ຕ້ອງàºàº²àº™àºˆàº±àºšàº„ູ່</translation>
<translation id="2344028582131185878">ດາວ​ໂຫຼດ​ອັດ​ຕະ​ໂນ​ມັດ</translation>
<translation id="2346319942568447007">ຮູບພາບທີ່ທ່ານສຳເນົາ</translation>
<translation id="2354001756790975382">ບຸàºàº¡àº²àºàºªà»Œàº­àº·à»ˆàº™à»†</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">ຜູ້ໂຈມຕີອາດຈະສາມາດເຫັນຮູບພາບທີ່ທ່ານàºàº³àº¥àº±àº‡à»€àºšàº´à»ˆàº‡àº¢àº¹à»ˆà»ƒàº™à»€àº§àº±àºšà»„ຊນີ້ à»àº¥àº° ຫຼອàºàº¥àº§àº‡àº—່ານໂດàºàºàº²àº™àº”ັດà»àº›àº‡àº®àº¹àºšàºžàº²àºšà»€àº«àº¼àº»à»ˆàº²àº™àº±à»‰àº™.</translation>
<translation id="2356070529366658676">ຖາມ</translation>
<translation id="2357481397660644965">ອຸປະàºàº­àº™àº‚ອງທ່ານຖືàºàºˆàº±àº”àºàº²àº™à»‚ດຠ<ph name="DEVICE_MANAGER" /> à»àº¥àº° ບັນຊີຂອງທ່ານຖືàºàºˆàº±àº”àºàº²àº™à»‚ດຠ<ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ໃນໜ້ອàºàºàº§à»ˆàº²à»œàº¶à»ˆàº‡àº¡àº·à»‰}=1{ໃນໜຶ່ງມື້}other{ໃນ {NUM_DAYS} ມື້}}</translation>
<translation id="2359629602545592467">ຫຼາàºàºªàº°àºàº¸àº™à»€àº‡àº´àº™</translation>
<translation id="2359808026110333948">ສືບຕà»à»ˆ</translation>
+<translation id="2359961752320758691">ນຳໃຊ້à»àº²àºà»€àº¥àºàºšàº±àº”ສະເà»àº·àº­àº™àº‚ອງທ່ານà»àº¥à»‰àº§.</translation>
<translation id="2367567093518048410">ລະ​ດັບ</translation>
<translation id="2372464001869762664">ຫຼັງຈາàºàº—ີ່ທ່ານຢືນຢັນ, ລະບົບຈະà»àºšà»ˆàº‡àº›àº±àº™àº¥àº²àºàº¥àº°àº­àº½àº”ບັດຈາàºàºšàº±àº™àºŠàºµ Google ຂອງທ່ານàºàº±àºšà»€àº§àº±àºšà»„ຊນີ້. ຊອàºàº«àº² CVC ໃນລາàºàº¥àº°àº­àº½àº”ບັນຊີ Plex ຂອງທ່ານ.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">ວິທີàºàº²àº™àºˆàº±àº”ສົ່ງນີ້ບà»à»ˆàºªàº²àº¡àº²àº”ໃຊ້ໄດ້. ລອງວິທີອື່ນ.</translation>
<translation id="2396249848217231973">ປ່ຽນ​àºàº±àºšâ€‹àº„ືນຄà»àº²àºªàº±à»ˆàº‡àº¥àº¶àºš</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">ເàºàº»à»ˆàº²</translation>
<translation id="2413528052993050574">ເຊີບເວີນີ້ບà»à»ˆàºªàº²àº¡àº²àº”ພິສູດໄດ້ວ່າ ມັນà»àº¡à»ˆàº™ <ph name="DOMAIN" />; ໃບຢັ້ງຢືນຄວາມປອດໄພຂອງມັນອາດຈະຖືàºàº–ອນຄືນà»àº¥à»‰àº§. ອັນນີ້ອາດຈະເຮັດໃຫ້ເàºàºµàº”ມີàºàº²àº™àº›àº±àºšàº•àº±à»‰àº‡àº„່າຜິດ ຫຼືຜູ້ໂຈມຕີອາດຈະດັàºà»€àº­àº»àº²àºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆàº‚ອງທ່ານ.</translation>
<translation id="2414886740292270097">ມືດ</translation>
<translation id="2438874542388153331">ເຈາະຮູຢູ່ເບື້ອງຂວາສີ່ຮູ</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">ໜີບàºàº°àº«àº¼àº±àºšà»€àºŸàºµàº¢àº¹à»ˆàº¥àº¸à»ˆàº¡àºªàº¸àº”ເບື້ອງຂວາ</translation>
<translation id="2523886232349826891">ບັນທຶàºà»„ວ້ໃນອຸປະàºàº­àº™àº™àºµà»‰à»€àº—ົ່ານັ້ນ</translation>
<translation id="2524461107774643265">ເພີ່ມຂà»à»‰àº¡àº¹àº™à»€àºžàºµà»ˆàº¡à»€àº•àºµàº¡</translation>
-<translation id="2526590354069164005">ເດັສທັອບ</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{à»àº¥àº° ອີຠ1 ລາàºàºàº²àº™}other{à»àº¥àº° ອີຠ# ລາàºàºàº²àº™}}</translation>
<translation id="2536110899380797252">ເພີ່ມທີ່ຢູ່</translation>
<translation id="2539524384386349900">àºàº§àº”ຫາ</translation>
+<translation id="2541219929084442027">ໜ້າເວັບທີ່ທ່ານເບິ່ງໃນà»àº–ບ​ບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™àºˆàº°àºšà»à»ˆàº›àº²àºàº»àº”ໃນປະຫວັດຂອງໂປຣà»àºàº£àº¡àº—່ອງເວັບຂອງທ່ານ, àºàº²àº™àºˆàº±àº”ເàºàº±àºšàº„ຸàºàºàºµà»‰ ຫຼື ປະ​ຫວັດ​àºàº²àº™â€‹àºŠàº­àºàº«àº²àº«àº¼àº±àº‡àºˆàº²àºàº—ີ່ທ່ານປິດà»àº–ບ​ບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™àº—ັງà»àº»àº”ຂອງທ່ານໄວ້. ໄຟລ໌ໃດàºà»àº•àº²àº¡àº—ີ່ທ່ານດາວໂຫຼດ ຫຼື ບຸàºàº¡àº²àºàº—ີ່ທ່ານສ້າງຈະຖືàºà»€àºàº±àºšà»„ວ້.</translation>
<translation id="2544644783021658368">ເອàºàº°àºªàº²àº™àº”ຽວ</translation>
<translation id="254947805923345898">ຄ່ານະໂàºàºšàº²àºàºšà»à»ˆàº–ືàºàº•à»‰àº­àº‡.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ໄດ້ສົ່ງຄຳຕອບທີ່ບà»à»ˆàº–ືàºàº•à»‰àº­àº‡.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">ເພື່ອຮັບຄວາມປອດໄພລະດັບສູງສຸດຂອງ Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />àºàº°àº¥àº¸àº™àº²à»€àº›àºµàº”àºàº²àº™àº›àº»àºàº›à»‰àº­àº‡àº—ີ່ປັບປຸງດີຂຶ້ນà»àº¥à»‰àº§<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">ບà»à»ˆàºªàº²àº¡àº²àº”ຊອàºà»€àº«àº±àº™àº—ີ່ຢູ່ IP ເຊີບເວີຂອງ <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">ສະ​ຖາ​ນະ​</translation>
+<translation id="264810637653812429">ບà»à»ˆàºžàº»àºšàº­àº¸àº›àº°àºàº­àº™àº—ີ່ເຂົ້າàºàº±àº™à»„ດ້.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, àºàº»àº”à»àº–ບ ຈາàºàº™àº±à»‰àº™àºàº»àº” Enter ເພື່ອລຶບປະຫວັດàºàº²àº™àº—່ອງເວັບຂອງທ່ານ, ຄຸàºàºàºµà»‰, à»àº„ສ à»àº¥àº° ອື່ນໆອີàºà»ƒàº™àºàº²àº™àº•àº±à»‰àº‡àº„່າ Chrome</translation>
<translation id="2650446666397867134">àºàº²àº™â€‹à»€àº‚ົ້າ​ຫາໄຟລ​໌​ຖືàºâ€‹àº›àº°â€‹àº•àº´â€‹à»€àºªàº”</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">ເລີ່ມເປີດໃຊ້ໃà»à»ˆ</translation>
<translation id="2803306138276472711">ເມື່ອບà»à»ˆàº”ົນມານີ້ Google Safe Browsing <ph name="BEGIN_LINK" />ໄດ້àºàº§àº”ພົບມາລà»àº§<ph name="END_LINK" /> ຢູ່ເທິງ <ph name="SITE" />. ເວັບໄຊທ໌ທີ່ປົàºàºàº°àº•àº´àº¡àºµàº„ວາມປອດໄພບາງຄັ້ງຈະຕິດມາລà»àº§.</translation>
<translation id="2807052079800581569">ຕຳà»à»œà»ˆàº‡àº®àº¹àºšàºžàº²àºšàº•àº²àº¡à»àºàº™ Y</translation>
+<translation id="2820957248982571256">àºàº³àº¥àº±àº‡àºªàº°à»àºàº™â€¦</translation>
<translation id="2824775600643448204">à»àº–ບ​ທີ່​ຢູ່​ à»àº¥àº°â€‹àº„ົ້ນ​ຫາ</translation>
<translation id="2826760142808435982">àºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆàº¡àºµàº¥àº°àº«àº±àº” à»àº¥àº°à»„ດ້ຮັບຮອງà»àº¥à»‰àº§àº”້ວàºàºàº²àº™à»ƒàºŠà»‰ <ph name="CIPHER" /> à»àº¥àº°à»ƒàºŠà»‰ <ph name="KX" /> ເປັນàºàº»àº™à»„àºà»àº¥àºàº›à»ˆàº½àº™àº›àº¸à»ˆàº¡.</translation>
<translation id="2835170189407361413">ລຶບà»àºšàºšàºŸàº­àº¡</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Invite (ຊອງຈົດà»àº²àº)</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="2859806420264540918">ເວັບໄຊນີ້ສະà»àº”ງໂຄສະນາທີ່ລົບàºàº§àº™ ຫຼື ຫຼອàºàº¥àº§àº‡.</translation>
+<translation id="287596039013813457">ເປັນມິດ</translation>
+<translation id="2876489322757410363">àºàº³àº¥àº±àº‡àº­àº­àºàºˆàº²àºà»‚à»àº”ບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™à»€àºžàº·à»ˆàº­àºˆà»ˆàº²àºàºœà»ˆàº²àº™à»àº­àº±àºšàºžàº¥àº´à»€àº„ຊັນພາàºàº™àº­àº ສືບຕà»à»ˆàºšà»?</translation>
<translation id="2878197950673342043">ພັບà»àºšàºšà»‚ປສເຕີ</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ຕຳà»à»œà»ˆàº‡à»œà»‰àº²àºˆà»</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (ຊອງຈົດà»àº²àº)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, àºàº»àº” Tab ຈາàºàº™àº±à»‰àº™àºàº»àº” Enter ເພືີ່ອເປີດໃຊ້àºàº²àº™àºàº§àº”ສອບຄວາມປອດໄພໃນàºàº²àº™àº•àº±à»‰àº‡àº„່າ Chrome</translation>
<translation id="3061707000357573562">àºàº²àº™àºšà»àº¥àº´àºàº²àº™à»àºà»‰àºšàº±àº™àº«àº²</translation>
-<translation id="3064966200440839136">àºàº³àº¥àº±àº‡àº­àº­àºàºˆàº²àºà»‚à»àº”ບà»à»ˆà»€àºœàºµàºàº•àº»àº™àº•àº»àº§à»€àºžàº·à»ˆàº­àºˆà»ˆàº²àºàºœà»ˆàº²àº™à»àº­àº±àºšàºžàº¥àº´à»€àº„ຊັນພາàºàº™àº­àº. ສືບຕà»à»ˆàºšà»?</translation>
<translation id="306573536155379004">ເລີ່ມເàºàº¡à»àº¥à»‰àº§.</translation>
<translation id="3080254622891793721">àºàº£àº²àºšàºŸàº´àº</translation>
<translation id="3086579638707268289">àºàº³àº¥àº±àº‡àº¡àºµàºàº²àº™àº•àº´àº”ຕາມເບິ່ງàºàº²àº™à»€àº„ື່ອນໄຫວຂອງທ່ານໃນເວັບ</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">ບັນຊີຂອງທ່ານຖືàºàºˆàº±àº”àºàº²àº™à»‚ດຠ<ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">ເອົາຄືນມາ</translation>
<translation id="3162559335345991374">Wi-Fi ທີ່​ທ່ານ​àºàº³â€‹àº¥àº±àº‡â€‹à»ƒàºŠà»‰â€‹àº­àº²àº”​ຈະ​ຕ້ອງ​àºàº²àº™â€‹à»ƒàº«à»‰â€‹àº—່ານ​ເຂົ້າ​ເບິ່ງ​ໜ້າ​ເຂົ້າ​ສູ່ລະ​ບົບ​ຂອງ​ມັນ.</translation>
-<translation id="3167968892399408617">ໜ້າເວັບທີ່ທ່ານເບິ່ງໃນà»àº–ບບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™àºˆàº°àºšà»à»ˆàº›àº²àºàº»àº”ຢູ່ໃນປະຫວັດໂປຣà»àºàº£àº¡àº—່ອງເວັບ, ຄຸàºàºàºµà»‰ ຫຼືປະຫວັດàºàº²àº™àºŠàº­àºàº«àº²àº‚ອງທ່ານ ຫຼັງຈາàºàº—ີ່ທ່ານໄດ້ປິດທຸàºà»àº–ບບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™àº‚ອງທ່ານà»àº¥à»‰àº§. ທຸàºà»„ຟລ໌ທີ່ທ່ານດາວໂຫຼດ ຫຼືບຸàºàº¡àº²àºàº—ີ່ທ່ານສ້າງຂຶ້ນຈະຖືàºà»€àºàº±àºšàº®àº±àºàºªàº²à»„ວ້.</translation>
<translation id="3169472444629675720">ຄົ້ນຫາ</translation>
<translation id="3174168572213147020">ເàºàº²àº°</translation>
<translation id="3176929007561373547">àºàº§àº”ເບິ່ງàºàº²àº™àº•àº±à»‰àº‡àº„່າພຣັອàºàºŠàºµàº‚ອງທ່ານ ຫຼືຕິດຕà»à»ˆàº«àº²àºœàº¹à»‰à»€àºšàº´à»ˆàº‡à»àºàº‡àº¥àº°àºšàº»àºšà»€àº„ືອຂ່າàºàº‚ອງທ່ານເພື່ອ
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">ຂà»à»‰àº¡àº¹àº™à»€àº§àºµàºŠàº±àº™àºà»ˆàº½àº§àºàº±àºšàº­àº¸àº›àº°àºàº­àº™ à»àº¥àº° ໂປຣà»àºàº£àº¡àº—່ອງເວັບຂອງທ່ານ</translation>
<translation id="323107829343500871">ປ້ອນ CVC ສຳລັບ <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">àºàº§àº”​ຫາ​ເນື້ອ​ໃນ​ສຳ​ຄັນ​ຢູ່​ເທິງ​ເວັບ​ໄຊ​ທ໌​ນີ້​ທຸàºâ€‹àº„ັ້ງ</translation>
+<translation id="3249845759089040423">àºàº£àº¹àºŸàºµ</translation>
<translation id="3252266817569339921">ພາສາàºàº£àº±à»ˆàº‡</translation>
<translation id="3266793032086590337">ຄ່າ (ຂັດà»àºà»ˆàº‡)</translation>
<translation id="3268451620468152448">ເປີດ​à»àº–ບ</translation>
<translation id="3270847123878663523">ປ່ຽນ​àºàº±àºšâ€‹àº„ືນຄà»àº²àºªàº±à»ˆàº‡àºˆàº±àº”ລà»àº²àº”ັບຄືນ</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> ຕ້ອງàºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆ</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">ອົງàºàº²àº™àº‚ອງທ່ານ, <ph name="ENROLLMENT_DOMAIN" />, ໄດ້ສົ່ງຂà»à»‰àº¡àº¹àº™àºˆàº³àº™àº§àº™à»œàº¶à»ˆàº‡à»„ປໃຫ້ເວັບໄຊຕà»à»ˆà»„ປນີ້à»àº¥à»‰àº§ ເຊັ່ນ: àºàº²àº™àº•àº±à»‰àº‡àº„່າ ຫຼື ນະໂàºàºšàº²àº.</translation>
<translation id="3282497668470633863">ເພີ່ມຊື່ໃນບັດ</translation>
@@ -655,6 +672,7 @@
<translation id="3428151540071562330">ໜຶ່ງ ຫຼື ຫຼາຠURI ຂອງà»àº¡à»ˆà»àºšàºšà»€àºŠàºµàºšà»€àº§àºµ DnsOverHttpsTemplates ບà»à»ˆàº–ືàºàº•à»‰àº­àº‡ à»àº¥àº° ຈະບà»à»ˆàº–ືàºàº™àº³à»ƒàºŠà»‰.</translation>
<translation id="3431636764301398940">ບັນທຶàºàºšàº±àº”ນີ້ໃສ່ອຸປະàºàº­àº™àº™àºµà»‰</translation>
<translation id="3432601291244612633">ປິດໜ້າ</translation>
+<translation id="3435738964857648380">ຄວາມ​ປອດ​ໄພ</translation>
<translation id="3435896845095436175">ເປີດໃຊ້ງານ</translation>
<translation id="3438829137925142401">ໃຊ້ລະຫັດຜ່ານທີ່ບັນທຶàºà»„ວ້ໃນບັນຊີ Google ຂອງທ່ານ</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@
<translation id="3584299510153766161">ເຈາະຮູຢູ່ລຸ່ມສຸດສອງຮູ</translation>
<translation id="3586931643579894722">ເຊື່ອງ​ລາàºâ€‹àº¥àº°â€‹àº­àº½àº”</translation>
<translation id="3587738293690942763">ເຄິ່ງàºàº²àº‡</translation>
+<translation id="3590643883886679995">ລະບົບຈະເàºàº±àºšàº‚à»à»‰àº¡àº¹àº™à»€àº‚ົ້າສູ່ລະບົບໄວ້ໃນອຸປະàºàº­àº™àº™àºµà»‰àº«àº¼àº±àº‡àºˆàº²àºàº—ີ່ທ່ານອອàºàºˆàº²àºà»‚à»àº”ບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™à»àº¥à»‰àº§.</translation>
+<translation id="359126217934908072">ເດືອນ/ປີ:</translation>
<translation id="3592413004129370115">Italian (ຊອງຈົດà»àº²àº)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{ທ່ານສາມາດຣີເຊັດàºàº¸à»ˆàº¡àº‚ອງທ່ານຕອນໃດàºà»à»„ດ້. ມັນໃຊ້ເວລາປະມານໜຶ່ງມື້ເພື່ອເຂົ້າຮ່ວມàºàº¸à»ˆàº¡à»ƒà»à»ˆ.}=1{ທ່ານສາມາດຣີເຊັດàºàº¸à»ˆàº¡àº‚ອງທ່ານຕອນໃດàºà»à»„ດ້. ມັນໃຊ້ເວລາປະມານໜຶ່ງມື້ເພື່ອເຂົ້າຮ່ວມàºàº¸à»ˆàº¡à»ƒà»à»ˆ.}other{ທ່ານສາມາດຣີເຊັດàºàº¸à»ˆàº¡àº‚ອງທ່ານຕອນໃດàºà»à»„ດ້. ມັນໃຊ້ເວລາປະມານ {NUM_DAYS} ມື້ເພື່ອເຂົ້າຮ່ວມàºàº¸à»ˆàº¡à»ƒà»à»ˆ.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">ຜູ້ເບິ່ງà»àºàº‡àº¥àº°àºšàº»àºšàº‚ອງທ່ານໄດ້ບລັອàºà»àº­àº±àºšàºžàº¥àº´à»€àº„ຊັນ</translation>
<translation id="3608932978122581043">ປ້ອນເຈ້àºàº•àº²àº¡àº—ິດທາງ</translation>
@@ -706,13 +727,13 @@
<translation id="3615877443314183785">ປ້ອນວັນທີà»àº»àº”ອາàºàº¸àº—ີ່ຖືàºàº•à»‰àº­àº‡</translation>
<translation id="36224234498066874">ລຶບລ້າງຂà»à»‰àº¡àº¹àº™àºàº²àº™àº—່ອງເວັບ...</translation>
<translation id="362276910939193118">ສະ​à»àº”ງ​ປະຫວັດທັງà»àº»àº”</translation>
-<translation id="3625635938337243871">ລະບົບຈະເàºàº±àºšàº‚à»à»‰àº¡àº¹àº™àºàº²àº™à»€àº‚ົ້າສູ່ລະບົບໄວ້ໃນອຸປະàºàº­àº™àº™àºµà»‰àº«àº¼àº±àº‡àºˆàº²àºàº—ີ່ທ່ານອອàºàºˆàº²àºà»‚à»àº”ບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™.</translation>
<translation id="3630155396527302611">ຖ້າວ່າມັນຢູ່ໃນລາàºàºàº²àº™à»€àº›àº±àº™à»‚ປຣà»àºàº£àº¡àº—ີ່ໄດ້ຮັບອະນຸàºàº²àº”ໃຫ້ເຂົ້າຫາເຄືອຂ່າàºà»„ດ້, ໃຫ້ລອງ
ລຶບມັນອອàºà»„ປຈາàºàº¥àº²àºàºàº²àº™ à»àº¥à»‰àº§à»€àºžàºµà»ˆàº¡àº¡àº±àº™à»ƒàºªà»ˆàº„ືນໃà»à»ˆ.</translation>
<translation id="3630699740441428070">ຜູ້ເບິ່ງà»àºàº‡àº¥àº°àºšàº»àºšàº‚ອງອຸປະàºàº­àº™àº™àºµà»‰à»„ດ້ຕັ້ງຄ່າàºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆà»€àº„ືອຂ່າàºàº‚ອງທ່ານ, ເຊິ່ງອາດຈະອະນຸàºàº²àº”ໃຫ້ພວàºàº¡àº±àº™à»€àº«àº±àº™àºàº²àº™àº®àº±àºšàºªàº»à»ˆàº‡àº‚à»à»‰àº¡àº¹àº™à»ƒàº™à»€àº„ືອຂ່າàºàº‚ອງທ່ານ, ຮວມທັງເວັບໄຊທີ່ທ່ານເຂົ້າເບິ່ງ.</translation>
<translation id="3631244953324577188">ຂà»à»‰àº¡àº¹àº™àºŠàºµàº§àº°àº¡àº´àº•àº´</translation>
<translation id="3633738897356909127">ປຸ່ມອັບເດດ Chrome, àºàº»àº” Enter ເພື່ອອັບເດດ Chrome ຈາàºàºàº²àº™àº•àº±à»‰àº‡àº„່າ Chrome ຂອງທ່ານ</translation>
<translation id="3634530185120165534">ຖາດ 5</translation>
+<translation id="3637662659967048211">ບັນທຶàºà»„ປໃສ່ບັນຊີ Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">à»àº­àº±àºšàºžàº¥àº´à»€àº„ຊັນ:</translation>
<translation id="3650584904733503804">àºàº²àº™àº®àº±àºšàº®àº­àº‡àºªà»àº²â€‹à»€àº¥àº±àº”</translation>
@@ -753,6 +774,7 @@
<translation id="3781428340399460090">ສີ​ບົວ​ເຂັ້ມ</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">ອຸປະàºàº­àº™ Bluetooth</translation>
+<translation id="3787675388804467730">à»àº²àºà»€àº¥àºàºšàº±àº”ສະເà»àº·àº­àº™</translation>
<translation id="3787705759683870569">à»àº»àº”ອາàºàº¸ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">ຂະໜາດ 16</translation>
<translation id="3789841737615482174">​ຕິດ​ຕັ້ງ</translation>
@@ -772,6 +794,7 @@
<translation id="3841184659773414994">ຕົວຈັດàºàº²àº™à»„ຟລ໌</translation>
<translation id="385051799172605136">àºàº±àºšâ€‹àº„ືນ​</translation>
<translation id="3858027520442213535">ອັບ​ເດດ​ວັນ​ທີ à»àº¥àº°â€‹à»€àº§â€‹àº¥àº²</translation>
+<translation id="3881478300875776315">ສະà»àº”ງà»àº–ວໜ້ອàºàº¥àº»àº‡</translation>
<translation id="3884278016824448484">ຕົວລະບຸອຸປະàºàº­àº™àº—ີ່ຂັດàºàº±àº™</translation>
<translation id="3885155851504623709">ຕາà»àºªàº‡</translation>
<translation id="388632593194507180">àºàº§àº”ພົບàºàº²àº™àº•àº´àº”ຕາມເບິ່ງ</translation>
@@ -797,6 +820,7 @@
<translation id="397105322502079400">àºà»àº²àº¥àº±àº‡àº„ິດ​ໄລ່...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ຖືàºàºšàº¥àº±àº­àºà»„ວ້</translation>
<translation id="3973357910713125165">ເປີດໃຊ້àºàº§àº”ສອບຄວາມປອດໄພ Chrome, àºàº»àº” Enter ເພື່ອເປີດໃຊ້àºàº²àº™àºàº§àº”ສອບຄວາມປອດໄພໃນ Chrome</translation>
+<translation id="3986705137476756801">ປິດຄຳບັນàºàº²àºàºªàº»àº”ສຳລັບຕອນນີ້</translation>
<translation id="3987405730340719549">Chrome ໄດ້àºàº³àº™àº»àº”ວ່າເວັບໄຊນີ້ອາດຈະເປັນເວັບໄຊປອມ ຫຼື ຫຼອàºàº¥àº§àº‡.
ຖ້າທ່ານເຊື່ອວ່າມີàºàº²àº™àºªàº°à»àº”ງສິ່ງນີ້ຢ່າງຜິດພາດ àºàº°àº¥àº¸àº™àº²à»€àº‚ົ້າຫາ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@
<translation id="4275830172053184480">ເລີ່ມຕົ້ນອຸປະàºàº­àº™àº‚ອງທ່ານໃà»à»ˆ</translation>
<translation id="4277028893293644418">ຣີເຊັດລະຫັດຜ່ານ</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ບັນທຶàºàºšàº±àº”ນີ້ໄວ້ໃນບັນຊີ Google ຂອງທ່ານà»àº¥à»‰àº§}other{ບັນທຶàºàºšàº±àº”ເຫຼົ່ານີ້ໄວ້ໃນບັນຊີ Google ຂອງທ່ານà»àº¥à»‰àº§}}</translation>
+<translation id="4287885627794386150">ມີສິດສຳລັບàºàº²àº™àº—ົດລອງໃຊ້à»àº•à»ˆàºšà»à»ˆà»„ດ້ເປີດໃຊ້</translation>
<translation id="4297502707443874121">ຮູບຕົວຢ່າງສຳລັບໜ້າ <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">ຂະ​ຫàºàº²àº</translation>
<translation id="4300675098767811073">ເຈາະຮູເບື້ອງຂວາຫຼາàºàº®àº¹</translation>
<translation id="4302514097724775343">à»àº•àº° dino ເພື່ອຫຼິ້ນ</translation>
<translation id="4302965934281694568">Chou3 (ຊອງຈົດà»àº²àº)</translation>
<translation id="4305666528087210886">ບà»à»ˆàºªàº²àº¡àº²àº”ເຂົ້າເຖິງໄຟລ໌ຂອງທ່ານໄດ້</translation>
-<translation id="4305817255990598646">ປ່ຽນ</translation>
+<translation id="4306529830550717874">ບັນທຶàºàº—ີ່ຢູ່ບà»?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">ບລັອຠ(ຄ່າເລີ່ມຕົ້ນ)</translation>
<translation id="4314815835985389558">ຈັດàºàº²àº™àºàº²àº™àºŠàº´à»‰àº‡àº‚à»à»‰àº¡àº¹àº™</translation>
@@ -926,6 +951,7 @@
<translation id="4377125064752653719">ທ່ານພະàºàº²àºàº²àº¡à»€àº‚ົ້າຫາ <ph name="DOMAIN" />, à»àº•à»ˆà»ƒàºšàº¢àº±à»‰àº‡àº¢àº·àº™àº—ີ່ເຊີບເວີນà»àº²àºªàº°à»€à»œàºµàº™àº±à»‰àº™àº–ືàºàºœàº¹à»‰àº­àº­àºà»ƒàº«à»‰àº–ອນຄືນà»àº¥à»‰àº§. ນີ້à»àº²àºàº„ວາມວ່າ ໃບຢັ້ງຢືນຄວາມປອດໄພທີ່ເຊີບເວີນà»àº²àºªàº°à»€à»œàºµàº™àº±à»‰àº™àºšà»à»ˆà»€àºŠàº·à»ˆàº­àº–ືໄດ້ທັງà»àº»àº”. ທ່ານອາດຈະàºà»àº²àº¥àº±àº‡àºªàº·à»ˆàºªàº²àº™àºàº±àºšàº•àº»àº§à»‚ຈມຕີຢູ່.</translation>
<translation id="4378154925671717803">ໂທລະ​ສັບ</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">ຄຳບັນàºàº²àºàºªàº»àº”</translation>
<translation id="4406896451731180161">ຜົນ​àºàº²àº™â€‹àº„ົ້ນ​ຫາ</translation>
<translation id="4408413947728134509">ຄຸàºàºàºµà»‰ <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">ທ່ານຫາàºà»àº›à»‰àº­àº™àº¥àº°àº«àº±àº”ຜ່ານຂອງທ່ານໃສ່ເວັບໄຊຫຼອàºàº¥àº§àº‡. Chrome ຂà»à»àº™àº°àº™àº³à»ƒàº«à»‰à»„ປທີ່ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> à»àº¥àº° ເວັບໄຊອື່ນໆທີ່ທ່ານໃຊ້ລະຫັດຜ່ານນີ້ à»àº¥à»‰àº§àº›à»ˆàº½àº™àº¡àº±àº™àº•àº­àº™àº™àºµà»‰à»€àº¥àºµàº.</translation>
@@ -938,7 +964,6 @@
<translation id="4435702339979719576">ໂພສàºàº²àº”)</translation>
<translation id="443673843213245140">àºàº²àº™à»ƒàºŠà»‰àºžàº£àº±àº­àºàºŠàºµàº›àº´àº”ໃຊ້ງານà»àº¥à»‰àº§ à»àº•à»ˆàºàº²àº™àº›àº±àºšàº•àº±à»‰àº‡àºžàº£àº±àº­àºàºŠàºµàºˆàº°à»àºˆà»‰àº‡à»„ດ້ຮັບàºàº²àº™àº¥àº°àºšàº¸.</translation>
<translation id="4464826014807964867">ເວັບໄຊພ້ອມຂà»à»‰àº¡àº¹àº™àºˆàº²àºàº­àº»àº‡àºàº²àº™àº‚ອງທ່ານ</translation>
-<translation id="4466881336512663640">àºàº²àº™àº›à»ˆàº½àº™à»àº›àº‡à»ƒàº™à»àºšàºšàºŸàº­àº¡àºˆàº°à»€àºªàºà»„ປ. ທ່ານà»àº™à»ˆà»ƒàºˆàºšà»à»ˆàº§à»ˆàº²àº—່ານຕ້ອງàºàº²àº™àºªàº·àºšàº•à»à»ˆ?</translation>
<translation id="4476953670630786061">à»àºšàºšàºŸàº­àº¡àºšà»à»ˆàº›àº­àº”ໄພ. ລະບົບໄດ້ປິດàºàº²àº™àº•àº·à»ˆàº¡àº‚à»à»‰àº¡àº¹àº™àº­àº±àº”ຕະໂນມັດà»àº¥à»‰àº§.</translation>
<translation id="4477350412780666475">ເພງຕà»à»ˆà»„ປ</translation>
<translation id="4482953324121162758">ລະບົບຈະບà»à»ˆà»àº›à»€àº§àº±àºšà»„ຊນີ້.</translation>
@@ -972,6 +997,7 @@
<translation id="4594403342090139922">ປ່ຽນ​àºàº±àºšâ€‹àº„ືນຄà»àº²àºªàº±à»ˆàº‡àº¥àº¶àºš</translation>
<translation id="4597348597567598915">ຂະໜາດ 8</translation>
<translation id="4600854749408232102">C6/C5 (ຊອງຈົດà»àº²àº)</translation>
+<translation id="4606870351894164739">ມີຜົນàºàº°àº—ົບ</translation>
<translation id="4628948037717959914">ຮູບຖ່າàº</translation>
<translation id="4631649115723685955">ເຊື່ອມໂàºàº‡à»€àº‡àº´àº™àº„ືນà»àº¥à»‰àº§</translation>
<translation id="4636930964841734540">ຂà»à»‰â€‹àº¡àº¹àº™</translation>
@@ -991,6 +1017,7 @@
<translation id="4691835149146451662">Architecture-A (ຊອງຈົດà»àº²àº)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">ດ້ານຂ້າງ</translation>
+<translation id="4702656508969495934">ສະà»àº”ງຄຳບັນàºàº²àºàºªàº»àº”à»àº¥à»‰àº§, ໃຊ້ປຸ່ມສະຫຼັບໜ້າຈà»à»€àºžàº·à»ˆàº­à»‚ຟàºàº±àºª</translation>
<translation id="4708268264240856090">àºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆàº‚ອງທ່ານຖືàºàº‚ັດຈັງຫວະ</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />àºàº³àº¥àº±àº‡à»€àº›àºµàº”ໃຊ້ Windows Network Diagnostics<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@
<translation id="4738601419177586157">àºàº²àº™à»àº™àº°àº™àº³àºàº²àº™àºŠàº­àºàº«àº² <ph name="TEXT" /></translation>
<translation id="4742407542027196863">ຈັດàºàº²àº™àº¥àº°àº«àº±àº”ຜ່ານ...</translation>
<translation id="4744603770635761495">ຊ່ອງ​ທາງ​ທີ່ປະ​ຕິ​ບັດໄດ້</translation>
+<translation id="4749011317274908093">ທ່ານເຂົ້າໃຊ້ໂà»àº”ບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™à»àº¥à»‰àº§</translation>
<translation id="4750917950439032686">ຂà»à»‰àº¡àº¹àº™àº‚ອງທ່ານ (ຕົວຢ່າງ: ລະຫັດຜ່ານ ຫຼື ເລàºàºšàº±àº”ເຄຣດິດ) à»àº¡à»ˆàº™à»€àº›àº±àº™àº„ວາມລັບເມື່ອມັນຖືàºàºªàº»à»ˆàº‡àº«àº²à»€àº§àº±àºšà»„ຊນີ້.</translation>
<translation id="4756388243121344051">ປະຫວັດ</translation>
<translation id="4758311279753947758">ເພີ່ມຂà»à»‰àº¡àº¹àº™àº•àº´àº”ຕà»à»ˆ</translation>
@@ -1033,6 +1061,8 @@
<translation id="4813512666221746211">ເຄືອຂ່າàºàºœàº´àº”ພາດ</translation>
<translation id="4816492930507672669">ຈັດພà»àº”ີàºàº±àºšàº«àº™à»‰àº²</translation>
<translation id="4819347708020428563">à»àºà»‰à»„ຂຄຳອະທິບາàºàº„ວາມເຫັນໃນມຸມມອງເລີ່ມຕົ້ນບà»?</translation>
+<translation id="4825507807291741242">ຊົງພະລັງ</translation>
+<translation id="4838327282952368871">ຊວນàºàº±àº™</translation>
<translation id="484462545196658690">ອັດຕະໂນມັດ</translation>
<translation id="4850886885716139402">ເບິ່ງ</translation>
<translation id="485316830061041779">ພາສາເຢàºàº¥àº°àº¡àº±àº™</translation>
@@ -1169,6 +1199,7 @@
<translation id="5314967030527622926">ເຄື່ອງສ້າງປຶ້ມນ້ອàº</translation>
<translation id="5316812925700871227">à»àº¸àº™â€‹â€‹àº—ວນ​ເຂັມ​ໂມງ</translation>
<translation id="5317780077021120954">ບັນທຶàº</translation>
+<translation id="5321288445143113935">ຂະຫàºàº²àºà»€àº•àº±àº¡à»àº¥à»‰àº§</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> ໃນ <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">ເລືອàºàº‚à»à»‰àº¡àº¹àº™àº•àº´àº”ຕà»à»ˆ</translation>
<translation id="5327248766486351172">ຊື່</translation>
@@ -1176,11 +1207,13 @@
<translation id="5332219387342487447">ວິທີàºàº²àº™àºˆàº±àº”ສົ່ງ</translation>
<translation id="5333022057423422993">Chrome ພົບລະຫັດຜ່ານທີ່ທ່ານຫາàºà»à»ƒàºŠà»‰à»„ປນັ້ນໃນàºàº²àº™àº®àº»à»ˆàº§à»„ຫຼຂà»à»‰àº¡àº¹àº™. ເພື່ອຮັàºàºªàº²àº„ວາມປອດໄພບັນຊີຂອງທ່ານ, ພວàºà»€àº®àº»àº²à»àº™àº°àº™àº³à»ƒàº«à»‰àº—່ານàºàº§àº”ສອບລະຫັດຜ່ານທີ່ທ່ານບັນທຶàºà»„ວ້.</translation>
<translation id="5334013548165032829">ບັນທຶàºàº¥àº°àºšàº»àºšàº¥àº°àº­àº½àº”</translation>
+<translation id="5334145288572353250">ບັນທຶàºàº—ີ່ຢູ່ບà»?</translation>
<translation id="5340250774223869109">à»àº­àº±àºšàºžàº¥àº´à»€àº„ຊັນຖືàºàºšàº¥àº±àº­àºà»„ວ້</translation>
<translation id="534295439873310000">ອຸປະàºàº­àº™ NFC</translation>
<translation id="5344579389779391559">ໜ້ານີ້ອາດຈະພະàºàº²àºàº²àº¡àº®àº½àºà»€àºàº±àºšà»€àº‡àº´àº™àº™àº³àº—່ານ</translation>
<translation id="5355557959165512791">ທ່ານບà»à»ˆàºªàº²àº¡àº²àº”ເຂົ້າເບິ່ງ <ph name="SITE" /> ໄດ້ໃນຂະນະນີ້ ເພາະວ່າໃບຢັ້ງຢືນຂອງມັນໄດ້ຖືàºàº–ອນຄືນà»àº¥à»‰àº§. ໂດàºàº›àº»àºàºàº°àº•àº´à»àº¥à»‰àº§ ຂà»à»‰àºœàº´àº”ພາດ à»àº¥àº° àºàº²àº™à»‚ຈມຕີທາງເຄືອຂ່າàºà»àº¡à»ˆàº™àºŠàº»à»ˆàº§àº„າວເທົ່ານັ້ນ, ສະນັ້ນ ໜ້ານີ້ອາດຈະໃຊ້ໄດ້ໃນພາàºàº«àº¼àº±àº‡.</translation>
<translation id="536296301121032821">ເàºàº±àºšàº®àº±àºàºªàº²àºàº²àº™àº•àº±à»‰àº‡àº„່ານະໂàºàºšàº²àºàºšà»à»ˆàºªà»àº²à»€àº¥àº±àº”</translation>
+<translation id="5363309033720083897">ຜອດຊີຣຽວທີ່ອະນຸàºàº²àº”ໂດàºàºœàº¹à»‰à»€àºšàº´à»ˆàº‡à»àºàº‡àº¥àº°àºšàº»àºšàº‚ອງທ່ານ</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="5386426401304769735">ຕ່ອງໂສ້ໃບຮັບຮອງສຳລັບເວັບໄຊນີ້ປະàºàº­àºšàº¡àºµà»ƒàºšàº®àº±àºšàº®àº­àº‡àº—ີ່ເຊັນຊື່ໂດàºà»ƒàºŠà»‰ SHA-1.</translation>
@@ -1189,6 +1222,7 @@
<translation id="5398772614898833570">ບລັອàºà»‚ຄສະນາໄວ້à»àº¥à»‰àº§</translation>
<translation id="5400836586163650660">ສີເທົາ</translation>
<translation id="540969355065856584">ເຊີບເວີນີ້ບà»à»ˆàºªàº²àº¡àº²àº”ພິສູດໄດ້ວ່າ ມັນà»àº¡à»ˆàº™ <ph name="DOMAIN" />; ໃບຢັ້ງຢືນຄວາມປອດໄພຂອງມັນໃຊ້​ບà»à»ˆâ€‹à»„ດ້​ໃນ​ເວ​ລາ​ນີ້. ອັນນີ້ອາດຈະເຮັດໃຫ້ເàºàºµàº”ມີàºàº²àº™àº›àº±àºšàº•àº±à»‰àº‡àº„່າຜິດ ຫຼືຜູ້ໂຈມຕີອາດຈະດັàºà»€àº­àº»àº²àºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆàº‚ອງທ່ານ.</translation>
+<translation id="541143247543991491">ຄລາວ (ທົ່ວລະບົບ)</translation>
<translation id="541416427766103491">ສະà»àº•àº±àºà»€àºàºµà»‰ 4</translation>
<translation id="5421136146218899937">ລຶບຂà»à»‰àº¡àº¹àº™àºàº²àº™àº—່ອງເນັດ...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> ຕ້ອງàºàº²àº™àºªàº»à»ˆàº‡àºàº²àº™à»àºˆà»‰àº‡à»€àº•àº·àº­àº™à»ƒàº«à»‰àº—່ານ</translation>
@@ -1202,6 +1236,7 @@
<translation id="5455374756549232013">ສະà»àº•àº±àº¡à»€àº§àº¥àº²àº™àº°â€‹à»‚àºâ€‹àºšàº²àºâ€‹àºšà»à»ˆâ€‹àº”ີ</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" /> ທີ່ຢູ່}other{<ph name="CONTACT_PREVIEW" /> à»àº¥àº° ອີຠ<ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ທີ່ຢູ່}}</translation>
+<translation id="5463625433003343978">àºàº³àº¥àº±àº‡àºŠàº­àºàº«àº²àº­àº¸àº›àº°àºàº­àº™â€¦</translation>
<translation id="5469868506864199649">ພາສາອີຕາລີ</translation>
<translation id="5470861586879999274">ເຮັດຄືນຄà»àº²àºªàº±à»ˆàº‡à»àºà»‰à»„ຂ</translation>
<translation id="5478437291406423475">B6/C4 (ຊອງຈົດà»àº²àº)</translation>
@@ -1251,7 +1286,6 @@
<translation id="5624120631404540903">ຈັດàºàº²àº™àº¥àº°â€‹àº«àº±àº”​ຜ່ານ​</translation>
<translation id="5629630648637658800">ໂຫຼດàºàº²àº™àº•àº±à»‰àº‡àº„່ານະໂàºàºšàº²àºàºšà»à»ˆàºªà»àº²à»€àº¥àº±àº”</translation>
<translation id="5631439013527180824">àºàº²à»àº²àºàº„ຸ້ມຄອງອຸປະàºàº­àº™à»ƒàºŠà»‰àºšà»à»ˆà»„ດ້</translation>
-<translation id="5632627355679805402">ຂà»à»‰àº¡àº¹àº™àº‚ອງທ່ານຖືàºà»€àº‚ົ້າລະຫັດໄວ້ດ້ວຠ<ph name="BEGIN_LINK" />ລະຫັດຜ່ານ Google<ph name="END_LINK" /> ຂອງທ່ານມາຮອດ <ph name="TIME" />. ປ້ອນມັນເພື່ອເລີ່ມàºàº²àº™àºŠàº´à»‰àº‡àº‚à»à»‰àº¡àº¹àº™.</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="5644090287519800334">ປ່ຽນຕຳà»à»œà»ˆàº‡àº®àº¹àºšàºžàº²àºšàº”້ານ 1 ຕາມà»àºàº™ X</translation>
@@ -1290,12 +1324,12 @@
<translation id="5785756445106461925">ນອàºâ€‹àºˆàº²àºàº™àº±à»‰àº™, ໜ້ານີ້ມີຂà»à»‰àº¡àº¹àº™àº­àº·à»ˆàº™àº—ີ່ບà»à»ˆàº›àº­àº”ໄພນà»àº². ຜູ້ອື່ນສາມາດເບິ່ງຂà»à»‰àº¡àº¹àº™àº™àºµà»‰à»„ດ້ໃນຂະນະທີ່ສົ່ງໄປ à»àº¥àº°àºœàº¹à»‰à»‚ຈມຕີສາມາດດັດà»àº›àº‡à»„ດ້ ເພື່ອປ່ຽນໜ້າ​ຕາຂອງໜ້າ.</translation>
<translation id="5786044859038896871">ທ່ານຕ້ອງàºàº²àº™àº•àº·à»ˆàº¡àº‚à»à»‰àº¡àº¹àº™àºšàº±àº”ຂອງທ່ານບà»?</translation>
<translation id="578633867165174378">Chrome ພົບລະຫັດຜ່ານທີ່ທ່ານຫາàºà»à»ƒàºŠà»‰à»„ປນັ້ນໃນàºàº²àº™àº®àº»à»ˆàº§à»„ຫຼຂà»à»‰àº¡àº¹àº™. ພວàºà»€àº®àº»àº²à»àº™àº°àº™àº³à»ƒàº«à»‰àº›à»ˆàº½àº™àº¥àº°àº«àº±àº”ຜ່ານດຽວນີ້.</translation>
-<translation id="5798290721819630480">àºàº»àºà»€àº¥àºµàºàºàº²àº™à»àºà»‰à»„ຂບà»?</translation>
<translation id="5803412860119678065">ທ່ານຕ້ອງàºàº²àº™àº•àº·à»ˆàº¡àº‚à»à»‰àº¡àº¹àº™ <ph name="CARD_DETAIL" /> ຂອງທ່ານບà»?</translation>
<translation id="5804241973901381774">àºàº²àº™â€‹àº­àº°â€‹àº™àº¸â€‹àºàº²àº”</translation>
<translation id="5804427196348435412">ໃຊ້ອຸປະàºàº­àº™ NFC</translation>
<translation id="5810442152076338065">àºàº²àº™â€‹à»€àºŠàº·à»ˆàº­àº¡â€‹àº•à»à»ˆâ€‹àº‚ອງ​ທ່ານ​àºàº±àºš <ph name="DOMAIN" /> ຖືàºâ€‹à»€àº‚ົ້າ​ລະ​ຫັດ​ດ້ວàºâ€‹àºàº²àº™â€‹à»ƒàºªà»ˆâ€‹àºŠàº¸àº”​ລະ​ຫັດ​ລັບ​ຫຼ້າ​ສະ​ໄà».</translation>
<translation id="5813119285467412249">​ເຮັດ​ຄືນ​ຄຳ​ສັ່ງ​ເພີ່ມ</translation>
+<translation id="5817918615728894473">ຈັບ​ຄູ່</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ລະບົບຈະຮຽàºà»€àºàº±àºšà»€àº‡àº´àº™àº™àº³àºšàº±àº”ນີ້ໃນເວລາທີ່ທ່ານຈ່າàº, à»àº•à»ˆàºˆàº°àºšà»à»ˆà»àºšà»ˆàº‡àº›àº±àº™à»àº²àºà»€àº¥àºàºˆàº´àº‡àº‚ອງບັດàºàº±àºšà»€àº§àº±àºšà»„ຊນີ້. ລະບົບຈະສ້າງ CVC ຊົ່ວຄາວຂຶ້ນມາເພື່ອຄວາມປອດໄພເພີ່ມເຕີມ.}other{ລະບົບຈະຮຽàºà»€àºàº±àºšà»€àº‡àº´àº™àº™àº³àºšàº±àº”ທີ່ທ່ານເລືອàºà»ƒàº™à»€àº§àº¥àº²àº—ີ່ທ່ານຈ່າàº, à»àº•à»ˆàºˆàº°àºšà»à»ˆà»àºšà»ˆàº‡àº›àº±àº™à»àº²àºà»€àº¥àºàºˆàº´àº‡àº‚ອງບັດàºàº±àºšà»€àº§àº±àºšà»„ຊນີ້. ລະບົບຈະສ້າງ CVC ຊົ່ວຄາວຂຶ້ນມາເພື່ອຄວາມປອດໄພເພີ່ມເຕີມ.}}</translation>
<translation id="5826507051599432481">ຊື່ທົ່ວໄປ (CN)</translation>
<translation id="5838278095973806738">ທ່ານບà»à»ˆàº„ວນປ້ອນຂà»à»‰àº¡àº¹àº™àº—ີ່ອ່ອນໄຫວໃດໆໃສ່ເວັບໄຊນີ້ (ຕົວຢ່າງ: ລະຫັດຜ່ານ ຫຼື ເລàºàºšàº±àº”ເຄຣດິດ), ເພາະວ່າມັນອາດຈະຖືàºàº¥àº±àºà»‚ດàºàºœàº¹à»‰à»‚ຈມຕີໄດ້.</translation>
@@ -1303,6 +1337,7 @@
<translation id="5855253129151731373">ຊື່ໂຮສຂອງເວັບໄຊນີ້ປາàºàº»àº”ວ່າຄ້າàºàº„ືàºàº±àºš <ph name="LOOKALIKE_DOMAIN" />. ບາງຄັ້ງຜູ້ໂຈມຕີປອມເປັນເວັບໄຊຕ່າງໆໂດàºàºàº²àº™à»€àº®àº±àº”àºàº²àº™àº›à»ˆàº½àº™à»àº›àº‡àº™à»‰àº­àºà»†àº—ີ່ເບິ່ງເຫັນໄດ້àºàº²àºàº•à»à»ˆàºàº±àºšàºŠàº·à»ˆà»‚ດເມນ.
ຖ້າທ່ານເຊື່ອວ່າມີàºàº²àº™àºªàº°à»àº”ງສິ່ງນີ້ຢ່າງຜິດພາດ àºàº°àº¥àº¸àº™àº²à»€àº‚ົ້າຫາ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">ປິດ</translation>
<translation id="5862579898803147654">ສະà»àº•àº±àºà»€àºàºµà»‰ 8</translation>
<translation id="5863847714970149516">ໜ້າທີ່ຈະໄປຫາອາດຈະພະàºàº²àºàº²àº¡à»€àºàº±àºšà»€àº‡àº´àº™àº™àº³àº—່ານ</translation>
<translation id="5866257070973731571">ເພີ່ມເບີໂທລະສັບ</translation>
@@ -1319,6 +1354,7 @@
<translation id="5913377024445952699">ຢຸດàºàº²àº™àº–່າàºàº®àº¹àºšà»œà»‰àº²àºˆà»à»„ວ້ຊົ່ວຄາວà»àº¥à»‰àº§</translation>
<translation id="59174027418879706">ເປີດໃຊ້ງານà»àº¥à»‰àº§</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 ໃຊ້ຢູ່}other{# ໃຊ້ຢູ່}}</translation>
<translation id="5921185718311485855">ເປີດ</translation>
<translation id="5921639886840618607">ບັນທຶàºàºšàº±àº”ໄວ້ໃນບັນຊີ Google ບà»?</translation>
<translation id="5922853866070715753">ເàºàº·àº­àºšàºªàº³à»€àº¥àº±àº”à»àº¥à»‰àº§</translation>
@@ -1338,6 +1374,7 @@
<translation id="5989320800837274978">ບà»à»ˆà»„ດ້àºà»àº²àº™àº»àº”ທັງເຊີບເວີພຣັອàºàºŠàºµàº—ີ່àºà»àº²àº™àº»àº”ໄວ້ ຫຼື URL ຕົວຂຽນ .pac.</translation>
<translation id="5992691462791905444">ພັບທົບà»àºšàºš Engineering ຮູບໂຕ Z</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> ຜົນàºàº²àº™àºŠàº­àºàº«àº²àºªàº³àº¥àº±àºš '<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">ຄລາສສິàº</translation>
<translation id="6008122969617370890">ລຳດັບ N ເຖິງ 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">àºàº§àº”ເບິ່ງລະຫັດຜ່ານຂອງທ່ານ</translation>
@@ -1359,6 +1396,7 @@
<translation id="6045164183059402045">à»àº¡à»ˆà»àºšàºšàºàº²àº™àºˆàº±àº”ຮຽງໜ້າàºà»ˆàº­àº™àºžàº´àº¡</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="6049004884579590341">àºàº»àº” |<ph name="ACCELERATOR" />| ຄ້າງໄວ້ເພື່ອອອàºàºˆàº²àºà»œà»‰àº²àºˆà»à»€àº•àº±àº¡</translation>
<translation id="6049488691372270142">ໜ້າທີ່ສະà»àº”ງ</translation>
<translation id="6051221802930200923">ທ່ານບà»à»ˆàºªàº²àº¡àº²àº”ເຂົ້າເບິ່ງ <ph name="SITE" /> ໄດ້ໃນຂະນະນີ້ ເພາະວ່າເວັບໄຊນີ້ໃຊ້àºàº²àº™àº›àº±àºà»àº¸àº”ໃບຢັ້ງຢືນ. ໂດàºàº›àº»àºàºàº°àº•àº´à»àº¥à»‰àº§ ຂà»à»‰àºœàº´àº”ພາດ à»àº¥àº° àºàº²àº™à»‚ຈມຕີທາງເຄືອຂ່າàºà»àº¡à»ˆàº™àºŠàº»à»ˆàº§àº„າວເທົ່ານັ້ນ, ສະນັ້ນ ໜ້ານີ້ອາດຈະໃຊ້ໄດ້ໃນພາàºàº«àº¼àº±àº‡.</translation>
<translation id="6051898664905071243">ຈຳນວນໜ້າ:</translation>
@@ -1375,6 +1413,7 @@
<translation id="610911394827799129">ບັນຊີ Google ຂອງທ່ານອາດຈະມີປະຫວັດàºàº²àº™àº—່ອງເວັບຮູບà»àºšàºšàº­àº·à»ˆàº™àº¢àº¹à»ˆ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
<translation id="6116338172782435947">ເຫັນຂà»à»‰àº„ວາມ à»àº¥àº° ຮູບພາບທີ່ສຳເນົາໄວ້ໃນຄລິບບອດ</translation>
<translation id="6120179357481664955">ຈື່ UPI ID ຂອງທ່ານໄວ້ບ�</translation>
+<translation id="6123290840358279103">ເບິ່ງບັດສະເà»àº·àº­àº™</translation>
<translation id="6124432979022149706">ເຄື່ອງມືເຊື່ອມຕà»à»ˆ Chrome Enterprise</translation>
<translation id="6146055958333702838">àºàº§àº”ເບິ່ງສາàºà»„ຟ à»àº¥àº°àº›àº´àº”ເປີດເຣົາເຕີ, ໂມເດັມ, ຫຼືອຸປະàºàº­àº™à»€àº„ືອຂ່າàº
ທີ່ທ່ານອາດàºàº³àº¥àº±àº‡à»ƒàºŠà»‰àº¢àº¹à»ˆàº„ືນໃà»à»ˆ.</translation>
@@ -1411,6 +1450,7 @@
<translation id="6289939620939689042">ສີໜ້າເຈ້àº</translation>
<translation id="6290238015253830360">ບົດຄວາມທີ່à»àº™àº°àº™àº³àº‚ອງທ່ານຈະປາàºàº»àº”ຢູ່ບ່ອນນີ້</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">àºàº³àº¥àº±àº‡àº¢àº¸àº”ຜູ້ຊ່ວຠGoogle ໃນ Chrome</translation>
<translation id="6305205051461490394"><ph name="URL" /> ບà»à»ˆàºªàº²àº¡àº²àº”ເຂົ້າເຖິງໄດ້</translation>
<translation id="6312113039770857350">ບà»à»ˆâ€‹àº¡àºµâ€‹à»œà»‰àº²â€‹à»€àº§àº±àºšâ€‹àº¢àº¹à»ˆ</translation>
@@ -1436,6 +1476,7 @@
<translation id="6390200185239044127">ພັບເຄິ່ງà»àºšàºšà»‚ຕ Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">ນະໂàºàºšàº²àºàº‚ອງຜູ້ເບິ່ງà»àºàº‡àº¥àº°àºšàº»àºšàºšàº¥àº±àº­àºàºàº²àº™àº§àº²àº‡àºˆàº²àº <ph name="ORIGIN_NAME" /> ໃສ່ຕຳà»à»œà»ˆàº‡àº™àºµà»‰à»„ວ້</translation>
+<translation id="6398765197997659313">ອອàºàºˆàº²àºà»€àº•àº±àº¡à»œà»‰àº²àºˆà»</translation>
<translation id="6401136357288658127">ເຊົາຮອງຮັບນະໂàºàºšàº²àºàº™àºµà»‰à»àº¥à»‰àº§. ທ່ານຄວນໃຊ້ນະໂàºàºšàº²àº <ph name="NEW_POLICY" /> ນີ້à»àº—ນ.</translation>
<translation id="6404511346730675251">à»àºà»‰â€‹à»„ຂບຸàºàº¡àº²àºàºªà»Œ</translation>
<translation id="6406765186087300643">C0 (ຊອງຈົດà»àº²àº)</translation>
@@ -1448,7 +1489,6 @@
<translation id="6428450836711225518">ຢັ້ງຢືນເບີໂທລະສັບຂອງທ່ານ</translation>
<translation id="6433490469411711332">à»àºà»‰à»„ຂຂà»à»‰àº¡àº¹àº™àº¥àº²àºàºŠàº·à»ˆàºœàº¹à»‰àº•àº´àº”ຕà»à»ˆ</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ໄດ້ປະຕິເສດàºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆ.</translation>
-<translation id="6434309073475700221">àºà»àº²àºˆàº±àº”ຖິ້ມ</translation>
<translation id="6440503408713884761">ລະເລີàº</translation>
<translation id="6443406338865242315">ສ່ວນຂະຫàºàº²àº à»àº¥àº° ປລັàºàº­àº´àº™àº—ີ່ທ່ານຕິດຕັ້ງ</translation>
<translation id="6446163441502663861">Kahu (ຊອງຈົດà»àº²àº)</translation>
@@ -1491,6 +1531,7 @@
<translation id="6624427990725312378">ຂà»à»‰àº¡àº¹àº™àº•àº´àº”ຕà»à»ˆ</translation>
<translation id="6626291197371920147">ເພີ່ມເລàºàºšàº±àº”ທີ່ຖືàºàº•à»‰àº­àº‡</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ຊອàºàº«àº²</translation>
+<translation id="6630043285902923878">àºàº³àº¥àº±àº‡àºŠàº­àºàº«àº²àº­àº¸àº›àº°àºàº­àº™ USB...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ລຶບ</translation>
@@ -1506,6 +1547,7 @@
<translation id="6671697161687535275">ເອົາ​àºàº²àº™â€‹à»àº™àº°â€‹àº™àº³â€‹à»àºšàºšâ€‹àºŸàº­àº¡â€‹àº­àº­àºâ€‹â€‹àºˆàº²àº Chromium ບà»?</translation>
<translation id="6685834062052613830">ອອàºàºˆàº²àºàº¥àº°àºšàº»àºš à»àº¥àº° ສຳເລັດàºàº²àº™àº•àº±à»‰àº‡àº„່າ</translation>
<translation id="6687335167692595844">ຂà»àº‚ະໜາດຟອນà»àº¥à»‰àº§</translation>
+<translation id="6688743156324860098">ອັບເດດ…</translation>
<translation id="6689249931105087298">ສຳພັນàºàº±àºšàºàº²àº™àºšàºµàºšàºˆàº¸àº”ສີດຳ</translation>
<translation id="6689271823431384964">Chrome àºàº³àº¥àº±àº‡àºªàº°à»€à»œàºµàºšàº±àº™àº—ຶàºàºšàº±àº”ຂອງທ່ານໄວ້ໃນບັນຊີ Google ຂອງທ່ານ ເພາະວ່າທ່ານເຂົ້າສູ່ລະບົບຢູ່. ທ່ານສາມາດປ່ຽນພຶດຕິàºàº³àº™àºµà»‰à»„ດ້ໃນàºàº²àº™àº•àº±à»‰àº‡àº„່າ. ຊື່ຜູ້ຖືບັດມາຈາàºàºšàº±àº™àºŠàºµàº‚ອງທ່ານ.</translation>
<translation id="6698381487523150993">ສ້າງຂຶ້ນà»àº¥à»‰àº§:</translation>
@@ -1521,6 +1563,7 @@
<translation id="6744009308914054259">ໃນຂະນະທີ່ລà»àº–້າàºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆ, ທ່ານສາມາດເຂົ້າຫາàºàº²àº™àº”າວໂຫຼດເພື່ອອ່ານບົດຄວາມອອບລາàºà»„ດ້.</translation>
<translation id="6753269504797312559">ຄ່າ​​ນະ​ໂàºâ€‹àºšàº²àº</translation>
<translation id="6757797048963528358">ອຸປະàºàº­àº™àº‚ອງທ່ານໄດ້ເຂົ້າສູ່ໂà»àº”ນອນຫຼັບà»àº¥à»‰àº§.</translation>
+<translation id="6767985426384634228">ອັບເດດທີ່ຢູ່ບ�</translation>
<translation id="6768213884286397650">Hagaki (ໂພສàºàº²àº”)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ສີມ່ວງ</translation>
@@ -1543,6 +1586,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome ໄດ້ເຮັດໃຫ້ໜ້ານີ້ອ່ານໄດ້ງ່າàºàº‚ຶ້ນ. Chrome àºàº¹à»‰àº„ືນໜ້າຕົ້ນສະບັບຜ່ານàºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆàº—ີ່ບà»à»ˆàº›àº­àº”ໄພ.</translation>
<translation id="6891596781022320156">ລະດັບນະໂàºàºšàº²àºàºšà»à»ˆàº–ືàºàº®àº­àº‡àº®àº±àºš.</translation>
+<translation id="6895143722905299846">à»àº²àºà»€àº¥àºàºªàº°à»€à»àº·àº­àº™:</translation>
<translation id="6895330447102777224">ຢືນຢັນບັດຂອງທ່ານà»àº¥à»‰àº§</translation>
<translation id="6897140037006041989">ຕົວà»àº—ນຜູ້ໃຊ້</translation>
<translation id="6898699227549475383">ອົງàºàº²àº™àºˆàº±àº”ຕັ້ງ (O)</translation>
@@ -1578,10 +1622,10 @@
<translation id="7004583254764674281">ໃຊ້ Windows Hello ເພື່ອຢືນຢັນບັດໄດ້ໄວຂຶ້ນ</translation>
<translation id="7006930604109697472">ຢືນຢັນàºàº²àº™àºªàº»à»ˆàº‡</translation>
<translation id="7012363358306927923">UnionPay ປະເທດ​ຈີນ</translation>
-<translation id="7012404007611495949">àºàº²àº™àº•àº±à»‰àº‡àº„່າàºàº²àº™àº›àº±àºšàº‚ະໜາດ</translation>
<translation id="7014741021609395734">ລະດັບàºàº²àº™àºŠàº¹àº¡</translation>
<translation id="7016992613359344582">àºàº²àº™à»€àºàº±àºšà»€àº‡àº´àº™à»€àº«àº¼àº»à»ˆàº²àº™àºµà»‰àº­àº²àº”ຈະເàºàº±àºšàº„ັ້ງດຽວ ຫຼື ເປັນປະຈຳຫຼາàºàº„ັ້ງ à»àº¥àº° ອາດຈະບà»à»ˆà»€àº«àº±àº™à»„ດ້ຈະà»àºˆà»‰àº‡.</translation>
<translation id="7029809446516969842">ລະ​ຫັດ​ຜ່ານ</translation>
+<translation id="7030436163253143341">ໃບຮັບຮອງບà»à»ˆàº–ືàºàº•à»‰àº­àº‡</translation>
<translation id="7031646650991750659">à»àº­àº±àºš Google Play ໃດທີ່ທ່ານຕິດຕັ້ງà»àº¥à»‰àº§</translation>
<translation id="7050187094878475250">ທ່ານ​ພະ​àºàº²â€‹àºàº²àº¡â€‹àº—ີ່​ຈະ​ບັນ​ລຸ <ph name="DOMAIN" />, à»àº•à»ˆâ€‹à»€àºŠàºµàºšâ€‹à»€àº§àºµâ€‹à»„ດ້​ນຳ​ສະ​ເໜີ​ໃບ​ຢັ້ງ​ຢືນ​ທີ່​ມີ​ໄລ​àºàº°â€‹àº„ວາມ​ສາ​ມາດ​ນຳ​ໃຊ້​ໄດ້​àºàº²àº§â€‹à»€àºàºµàº™â€‹à»„ປ​ທີ່​ຈະ​ເຊື່ອ​ຖື​ໄດ້.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ບà»à»ˆàºªàº²àº¡àº²àº”ບັນທຶàºàºšàº±àº”ນີ້ໄວ້ໄດ້ໃນຕອນນີ້}other{ບà»à»ˆàºªàº²àº¡àº²àº”ບັນທຶàºàºšàº±àº”ເຫຼົ່ານີ້ໄວ້ໄດ້ໃນຕອນນີ້}}</translation>
@@ -1651,12 +1695,14 @@
<translation id="7300012071106347854">ສີ​ຟ້າ​ໂàºâ€‹àºšàº²â€‹àº¥â€‹àº—໌</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">ສູງ</translation>
+<translation id="7305756307268530424">ເລີ່ມຊ້າລົງ</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">ຄວາມຊ່ວàºà»€àº«àº¼àº·àº­àºà»ˆàº½àº§àºàº±àºšàºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆ</translation>
<translation id="7323804146520582233">ເຊື່ອງຂà»à»‰ "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">ລົບລ້າງບັນຊີພາàºà»ƒàº™àº­àº¸àº›àº°àºàº­àº™</translation>
<translation id="7333654844024768166">ທ່ານຫາàºà»àº›à»‰àº­àº™àº¥àº°àº«àº±àº”ຜ່ານຂອງທ່ານໃສ່ເວັບໄຊຫຼອàºàº¥àº§àº‡. Chromium ຂà»à»àº™àº°àº™àº³à»ƒàº«à»‰à»„ປທີ່ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> à»àº¥àº° ເວັບໄຊອື່ນໆທີ່ທ່ານໃຊ້ລະຫັດຜ່ານນີ້ à»àº¥à»‰àº§àº›à»ˆàº½àº™àº¡àº±àº™àº•àº­àº™àº™àºµà»‰à»€àº¥àºµàº.</translation>
<translation id="7334320624316649418">ເຮັດຄືນຄà»àº²àºªàº±à»ˆàº‡àºˆàº±àº”ລà»àº²àº”ັບຄືນ</translation>
+<translation id="7337248890521463931">ສະà»àº”ງà»àº–ວເພີ່ມເຕີມ</translation>
<translation id="7337706099755338005">ບà»à»ˆàºªàº²àº¡àº²àº”ໃຊ້ໄດ້ໃນà»àºžàº¥àº±àº”ຟອມຂອງທ່ານ.</translation>
<translation id="733923710415886693">ໃບຢັ້ງຢືນຂອງເຊີບເວີບà»à»ˆàº–ືàºà»€àº›àºµàº”ເຜີàºàºœà»ˆàº²àº™àº™àº°à»‚àºàºšàº²àºàº„ວາມໂປ່ງໃສຂອງໃບຢັ້ງຢືນ.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1664,6 +1710,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">à»àº–ວຄà»àº²àºªàº±à»ˆàº‡</translation>
<translation id="7359588939039777303">ບລັອàºà»‚ຄສະນາໄວ້à»àº¥à»‰àº§.</translation>
+<translation id="7363096869660964304">à»àº™àº§à»ƒàº”àºà»àº•àº²àº¡, ທ່ານຈະບà»à»ˆàº«àº²àºà»„ປໃສ. àºàº²àº™à»ƒàºŠà»‰à»‚à»àº”ບà»à»ˆà»€àº›àºµàº”ເຜີàºàº•àº»àº§àº•àº»àº™àºˆàº°àºšà»à»ˆà»€àºŠàº·à»ˆàº­àº‡àºàº²àº™àº—່ອງເວັບຂອງທ່ານຈາàºàº™àº²àºàºˆà»‰àº²àº‡, ຜູ້ໃຫ້ບà»àº¥àº´àºàº²àº™àº­àº´àº™à»€àº•àºµà»€àº™àº±àº” ຫຼື ເວັບໄຊທີ່ທ່ານເຂົ້າເບິ່ງ.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, àºàº»àº” Tab ຈາàºàº™àº±à»‰àº™àºàº»àº” Enter ເພື່ອເພີ່ມ à»àº¥àº° ຈັດàºàº²àº™àº—ີ່ຢູ່ໃນàºàº²àº™àº•àº±à»‰àº‡àº„່າ Chrome</translation>
<translation id="7365849542400970216">ຮູ້ຈັàºàºàº²àº™àº™àº³à»ƒàºŠà»‰àº­àº¸àº›àº°àºàº­àº™àº‚ອງທ່ານບà»?</translation>
<translation id="7372973238305370288">ຜົນ​àºàº²àº™àº„ົ້ນ​ຫາ</translation>
@@ -1674,7 +1721,9 @@
<translation id="7378594059915113390">àºàº²àº™àº„ວບຄຸມສື່</translation>
<translation id="7378627244592794276">ບà»à»ˆà»àº¡à»ˆàº™</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ບà»à»ˆàºà»ˆàº½àº§àº‚້ອງ</translation>
<translation id="7390545607259442187">ຢືນຢັນບັດ</translation>
+<translation id="7392089738299859607">ອັບເດດທີ່ຢູ່</translation>
<translation id="7399802613464275309">àºàº§àº”ສອບຄວາມປອດໄພ</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">ມີàºàº²àº™àºˆàº±àº”àºàº²àº™ <ph name="DEVICE_NAME" /> ຂອງທ່ານ</translation>
@@ -1689,6 +1738,7 @@
&lt;li&gt;ເຂົ້າເບິ່ງ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;ສູນຊ່ວàºà»€àº«àº¼àº·àº­ Chrome&lt;/a&gt; ເພື່ອຮຽນຮູ້ວິທີລຶບຊອບà»àº§àº­àº­àºàºˆàº²àºàº„ອມພິວເຕີຂອງທ່ານຢ່າງຖາວອນ
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">ໜ້າຮັàº</translation>
<translation id="7416351320495623771">ຈັດàºàº²àº™àº¥àº°àº«àº±àº”ຜ່ານ...</translation>
<translation id="7419106976560586862">ຊ່ອງທາງໂປຣໄຟລ໌</translation>
<translation id="7437289804838430631">ເພີ່ມຂà»à»‰àº¡àº¹àº™àº•àº´àº”ຕà»à»ˆ</translation>
@@ -1704,7 +1754,7 @@
<translation id="7481312909269577407">ສົ່ງຕà»à»ˆ</translation>
<translation id="7485870689360869515">ບà»à»ˆàºžàº»àºšàº‚à»à»‰â€‹àº¡àº¹àº™â€‹.</translation>
<translation id="7495528107193238112">ເນື້ອຫານີ້ຖືàºàºšàº¥àº±àº­àºà»„ວ້. ຕິດຕà»à»ˆà»€àºˆàº»à»‰àº²àº‚ອງເວັບໄຊເພື່ອà»àºà»‰à»„ຂບັນຫາ.</translation>
-<translation id="7498234416455752244">ສືບຕà»à»ˆà»àºà»‰à»„ຂ</translation>
+<translation id="7498193950643227031">ມັນອາດເຮັດວຽàºàºœàº´àº”ຈາàºàº—ີ່ຄາດໄວ້ຫາàºàº–ືàºàº›àº±àºšàº‚ະໜາດ. ຕອນນີ້ທ່ານສາມາດຈຳàºàº±àº”ຄວາມສາມາດໃນàºàº²àº™àº›àº±àºšàº‚ະໜາດà»àº­àº±àºšà»„ດ້à»àº¥à»‰àº§à»ƒàº™ <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">ທ່ານຫາàºà»àº›à»‰àº­àº™àº¥àº°àº«àº±àº”ຜ່ານຂອງທ່ານໃສ່ເວັບໄຊຫຼອàºàº¥àº§àº‡. Chromium ຂà»à»àº™àº°àº™àº³à»ƒàº«à»‰àºàº§àº”ເບິ່ງລະຫັດຜ່ານທີ່ທ່ານບັນທຶàºà»„ວ້ສຳລັບ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> à»àº¥àº° ເວັບໄຊອື່ນໆທີ່ທ່ານໃຊ້ລະຫັດຜ່ານນີ້ໃນຕອນນີ້ເລີàº.</translation>
<translation id="7508255263130623398">id ອຸປະàºàº­àº™àº™àº°à»‚àºàºšàº²àºàº«àº§à»ˆàº²àº‡à»€àº›àº»à»ˆàº² ຫຼື ບà»à»ˆàºàº»àº‡àºàº±àºš id ອຸປະàºàº­àº™àº›àº±àº”ຈຸບັນ</translation>
<translation id="7508870219247277067">ສີ​ຂຽວ​ອາ​ໂວ​àºàº²â€‹à»‚ດ</translation>
@@ -1724,6 +1774,7 @@
<translation id="7548892272833184391">à»àºà»‰à»„ຂຂà»à»‰àºœàº´àº”ພາດຂອງàºàº²àº™à»€àºŠàº·à»ˆàº­àº¡àº•à»à»ˆ</translation>
<translation id="7549584377607005141">ເວັບໄຊທ໌ນີ້ຕ້ອງàºàº²àº™àº‚à»à»‰àº¡àº¹àº™àº—ີ່ທ່ານປ້ອນà»àº•à»ˆàº«àº»àº§àº—ີ ເພື່ອໃຫ້ສະà»àº”ງຂຶ້ນຢ່າງຖືàºàº•à»‰àº­àº‡. ທ່ານສາມາດສົ່ງຂà»à»‰àº¡àº¹àº™àº™àºµà»‰à»„ດ້ອີàº, à»àº•à»ˆà»‚ດàºàºàº²àº™à»€àº®àº±àº”à»àº™àº§àº™àº±à»‰àº™ ທ່ານອາດຈະເຮັດàºàº²àº™àºàº°àº—à»àº²à»ƒàº”ໜຶ່ງຊà»à»‰àº²àº„ືນໜ້ານີ້ທີ່ໄດ້ເຮັດຜ່ານມາà»àº¥à»‰àº§.</translation>
<translation id="7550637293666041147">ຊື່ຜູ້ໃຊ້ອຸປະàºàº­àº™ à»àº¥àº° ຊື່ຜູ້ໃຊ້ Chrome ຂອງທ່ານ</translation>
+<translation id="755279583747225797">ເປີດໃຊ້àºàº²àº™àº—ົດລອງໃຊ້ຢູ່</translation>
<translation id="7552846755917812628">ລອງຄຳà»àº™àº°àº™àº³àº•à»à»ˆà»„ປນີ້:</translation>
<translation id="7554475479213504905">ໂຫຼດໃà»à»ˆ à»àº¥àº° ຢືນຢັນສະà»àº”ງ</translation>
<translation id="7554791636758816595">à»àº–ບ​ໃຫມ່</translation>
@@ -1742,7 +1793,6 @@
<translation id="7610193165460212391">ຄ່າຢູ່ນອàºà»€àº‚ດ <ph name="VALUE" /> .</translation>
<translation id="7613889955535752492">à»àº»àº”ອາàºàº¸: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, àºàº»àº”à»àº–ບ ຈາàºàº™àº±à»‰àº™àºàº»àº” Enter ເພື່ອເບິ່ງ à»àº¥àº° ຈັດàºàº²àº™àº¥àº°àº«àº±àº”ຜ່ານຂອງທ່ານໃນàºàº²àº™àº•àº±à»‰àº‡àº„່າ Chrome</translation>
-<translation id="7615602087246926389">ທ່ານມີຂà»à»‰àº¡àº¹àº™àº—ີ່ໃສ່ລະຫັດໂດàºàºàº²àº™à»ƒàºŠà»‰àº¥àº°àº«àº±àº”ຜ່ານບັນຊີ Google ຂອງທ່ານ​ໃນລຸ້ນຕ່າງàºàº±àº™. àºàº°àº¥àº¸àº™àº²àº›à»‰àº­àº™àº¡àº±àº™à»€àº‚ົ້າຢູ່ລຸ່ມນີ້.</translation>
<translation id="7616645509853975347">ຜູ້ເບິ່ງà»àºàº‡àº¥àº°àºšàº»àºšàº‚ອງທ່ານໄດ້ເປີດ Chrome Enterprise Connectors ໃນໂປຣà»àºàº£àº¡àº—່ອງເວັບຂອງທ່ານà»àº¥à»‰àº§. ເຄື່ອງມືເຊື່ອມຕà»à»ˆà»€àº«àº¼àº»à»ˆàº²àº™àºµà»‰àº¡àºµàºªàº´àº”ເຂົ້າເຖິງບາງຂà»à»‰àº¡àº¹àº™àº‚ອງທ່ານໄດ້.</translation>
<translation id="7619838219691048931">à»àºœà»ˆàº™àº§àº½àºàºªàº¸àº”ທ້າàº</translation>
<translation id="762844065391966283">ເທື່ອລະລາàºàºàº²àº™</translation>
@@ -1807,13 +1857,12 @@
<translation id="782886543891417279">Wi-Fi ທີ່​ທ່ານ​àºàº³â€‹àº¥àº±àº‡â€‹à»ƒàºŠà»‰â€‹àº¢àº¹à»ˆ (<ph name="WIFI_NAME" />) ອາດ​ຈະ​ຕ້ອງ​àºàº²àº™â€‹à»ƒàº«à»‰â€‹àº—່ານ​ເຂົ້າ​ຫາໜ້າລັອàºàº­àº´àº™â€‹à»€àº‚ົ້າ​​ລະ​ບົບ​ຂອງ​ມັນ.</translation>
<translation id="7836231406687464395">Postfix (ຊອງຈົດà»àº²àº)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ບà»à»ˆàº¡àºµ}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ເປີດໄຟລ໌ດ້ວàºàºàº²àº™à»€àºŠàº·à»ˆàº­àº¡à»‚àºàº‡àº›àº°à»€àºžàº”ໄຟລ໌.</translation>
<translation id="7862185352068345852">ອອàºàºˆàº²àºà»€àº§àº±àºšà»„ຊບà»?</translation>
<translation id="7865448901209910068">ຄວາມໄວດີສຸດ</translation>
<translation id="7874263914261512992">ທ່ານຫາàºà»àº›à»‰àº­àº™àº¥àº°àº«àº±àº”ຜ່ານຂອງທ່ານໃສ່ເວັບໄຊຫຼອàºàº¥àº§àº‡. Chrome ຂà»à»àº™àº°àº™àº³à»ƒàº«à»‰àºàº§àº”ເບິ່ງລະຫັດຜ່ານທີ່ທ່ານບັນທຶàºà»„ວ້ສຳລັບ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> à»àº¥àº° ເວັບໄຊອື່ນໆທີ່ທ່ານໃຊ້ລະຫັດຜ່ານນີ້ໃນຕອນນີ້ເລີàº.</translation>
<translation id="7878562273885520351">ອາດຈະມີàºàº²àº™àº¥àº±àºà»ƒàºŠà»‰àº¥àº°àº«àº±àº”ຜ່ານຂອງທ່ານ</translation>
+<translation id="7880146494886811634">ບັນທຶàºàº—ີ່ຢູ່</translation>
<translation id="7882421473871500483">ສີນ້ຳຕານ</translation>
<translation id="7887683347370398519">àºàº§àº”​ເບິ່ງ CVC ຂອງ​ທ່ານ à»àº¥àº°â€‹àº¥àº­àº‡â€‹à»ƒà»à»ˆâ€‹àº­àºµàº</translation>
<translation id="7887885240995164102">ເຂົ້າໂà»àº”ສະà»àº”ງຜົນຊ້ອນàºàº±àº™</translation>
@@ -1821,6 +1870,7 @@
<translation id="7894280532028510793">ຖ້າàºàº²àº™àºªàº°àºàº»àº”ຄຳຖືàºàº•à»‰àº­àº‡, <ph name="BEGIN_LINK" />ລອງເປີດໃຊ້ Network Diagnostics<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (ຊອງຈົດà»àº²àº)</translation>
<translation id="7931318309563332511">ບà»à»ˆàº®àº¹à»‰àºˆàº±àº</translation>
+<translation id="793209273132572360">ອັບເດດທີ່ຢູ່ບ�</translation>
<translation id="7932579305932748336">ເຄືອບ</translation>
<translation id="79338296614623784">ປ້ອນເບີໂທລະສັບທີ່ຖືàºàº•à»‰àº­àº‡</translation>
<translation id="7934052535022478634">àºàº²àº™àºŠà»àº²àº¥àº°à»€àº‡àº´àº™àºªàº³à»€àº¥àº±àº”à»àº¥à»‰àº§</translation>
@@ -1891,6 +1941,7 @@
<translation id="8175796834047840627">Chrome àºàº³àº¥àº±àº‡àºªàº°à»€à»œàºµàºšàº±àº™àº—ຶàºàºšàº±àº”ຂອງທ່ານໄວ້ໃນບັນຊີ Google ຂອງທ່ານ ເພາະວ່າທ່ານເຂົ້າສູ່ລະບົບຢູ່. ທ່ານສາມາດປ່ຽນລັàºàºªàº°àº™àº°àºàº²àº™àº™à»àº²à»ƒàºŠà»‰àº™àºµà»‰à»„ດ້ໃນàºàº²àº™àº•àº±à»‰àº‡àº„່າ.</translation>
<translation id="8176440868214972690">ຜູ້ເບິ່ງà»àºàº‡àº¥àº°àºšàº»àºšàº‚ອງອຸປະàºàº­àº™àº™àºµà»‰à»„ດ້ສົ່ງຂà»à»‰àº¡àº¹àº™àºˆàº³àº™àº§àº™à»œàº¶à»ˆàº‡à»„ປໃຫ້ເວັບໄຊຕà»à»ˆà»„ປນີ້à»àº¥à»‰àº§ ເຊັ່ນ: àºàº²àº™àº•àº±à»‰àº‡àº„່າ ຫຼື ນະໂàºàºšàº²àº.</translation>
<translation id="8184538546369750125">ໃຊ້ຄ່າມາດຕະຖານທົ່ວ​ໂລຠ(ອະນຸàºàº²àº”​)</translation>
+<translation id="8193086767630290324">ຄຳສັ່ງທີ່ໃຊ້àºàº±àºšàº‚à»à»‰àº¡àº¹àº™à»àº¡à»ˆàº™àº–ືàºà»àº²àºàº—ຸງວ່າເປັນຄວາມລັບ</translation>
<translation id="8194797478851900357">ປ່ຽນ​àºàº±àºšâ€‹àº„ືນຄà»àº²àºªàº±à»ˆàº‡àºà»‰àº²àº</translation>
<translation id="8201077131113104583">URL ອັບ​ເດດ​ໃຊ້​ບà»à»ˆâ€‹à»„ດ້​ສຳ​ລັບ​ສ່ວນ​ຂະ​ຫàºàº²àºâ€‹àºàº±àºš ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">ສະຫຼຸບຄຳສັ່ງຊື້</translation>
@@ -1913,6 +1964,7 @@
<translation id="8249296373107784235">àºàº»àºà»€àº¥àºµàº</translation>
<translation id="8249320324621329438">ເອົາຄັ້ງສຸດທ້າàº:</translation>
<translation id="8253091569723639551">ຈຳເປັນຕ້ອງມີທີ່ຢູ່ຮຽàºà»€àºàº±àºšà»€àº‡àº´àº™</translation>
+<translation id="8257387598443225809">à»àº­àº±àºšàº™àºµà»‰àº–ືàºàº­àº­àºà»àºšàºšàº¡àº²àºªàº³àº¥àº±àºšàº¡àº·àº–ື</translation>
<translation id="825929999321470778">ສະà»àº”ງລະຫັດຜ່ານທີ່ບັນທຶàºà»„ວ້ທັງà»àº»àº”</translation>
<translation id="8261506727792406068">ລຶບ</translation>
<translation id="8262952874573525464">ຫàºàº´àºšàº‚ອບລຸ່ມສຸດ</translation>
@@ -2036,7 +2088,6 @@
<translation id="8719528812645237045">ເຈາະຮູຢູ່ເທິງສຸດຫຼາàºàº®àº¹</translation>
<translation id="8725066075913043281">ລອງໃà»à»ˆàº­àºµàº</translation>
<translation id="8726549941689275341">ຂະຫນາດຫນ້າ:</translation>
-<translation id="8728672262656704056">ທ່ານໄດ້ເຂົ້າສູ່ໂà»àº” incognito à»àº¥à»‰àº§</translation>
<translation id="8730621377337864115">ສà»àº²à»€àº¥àº±àº”</translation>
<translation id="8731544501227493793">ປຸ່ມຈັດàºàº²àº™àº¥àº°àº«àº±àº”ຜ່ານ, àºàº»àº” Enter ເພື່ອເບິ່ງ à»àº¥àº° ຈັດàºàº²àº™àº¥àº°àº«àº±àº”ຜ່ານຂອງທ່ານໃນàºàº²àº™àº•àº±à»‰àº‡àº„່າ Chrome</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> ຂອງທ່ານຖືàºàºˆàº±àº”àºàº²àº™à»‚ດຠ<ph name="MANAGER" /></translation>
@@ -2113,6 +2164,7 @@
<translation id="9020542370529661692">ໜ້ານີ້ຖືàºà»‚ອນໄປຫາ <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ໃຊ້ບà»à»ˆà»„ດ້)</translation>
+<translation id="9030265603405983977">ຂາວດຳ</translation>
<translation id="9035022520814077154">ຄວາມປອດໄພຂັດຂ້ອງ</translation>
<translation id="9038649477754266430">ໃຊ້àºàº²àº™àºšà»àº¥àº´àºàº²àº™àº„າດເດົາເພື່ອໂຫຼດໜ້າຕ່າງໆໃຫ້ໄດ້ໄວຂຶ້ນ</translation>
<translation id="9039213469156557790">ນອàºâ€‹àºˆàº²àºàº™àº±à»‰àº™, ໜ້ານີ້ມີຂà»à»‰àº¡àº¹àº™àº­àº·à»ˆàº™àº—ີ່ບà»à»ˆàº›àº­àº”ໄພນà»àº². ຜູ້ອື່ນສາມາດເບິ່ງຂà»à»‰àº¡àº¹àº™àº™àºµà»‰à»„ດ້ໃນຂະນະທີ່ສົ່ງໄປ à»àº¥àº°àºœàº¹à»‰à»‚ຈມຕີສາມາດດັດà»àº›àº‡à»„ດ້ ເພື່ອປ່ຽນພຶດຕິàºà»àº²àº‚ອງໜ້າ.</translation>
@@ -2136,6 +2188,7 @@
<translation id="91108059142052966">ນະໂàºàºšàº²àºàº‚ອງຜູ້ເບິ່ງà»àºàº‡àº¥àº°àºšàº»àºšàº›àº´àº”àºàº²àº™àº™àº³à»ƒàºŠà»‰àºàº²àº™à»àºšà»ˆàº‡àº›àº±àº™à»œà»‰àº²àºˆà»àºàº±àºš <ph name="APPLICATION_TITLE" /> ເມື່ອມີເນື້ອຫາສະà»àº”ງຢູ່</translation>
<translation id="9114524666733003316">àºàº³àº¥àº±àº‡àº¢àº·àº™àº¢àº±àº™àºšàº±àº”...</translation>
<translation id="9114581008513152754">ໂປຣà»àºàº£àº¡àº—່ອງເວັບນີ້ບà»à»ˆà»„ດ້ຖືàºàºˆàº±àº”àºàº²àº™à»‚ດàºàºšà»àº¥àº´àºªàº±àº” ຫຼື ອົງàºàº²àº™àºˆàº±àº”ຕັ້ງອື່ນ. àºàº²àº™à»€àº„ື່ອນໄຫວໃນອຸປະàºàº­àº™àº™àºµà»‰àº­àº²àº”ຈະຖືàºàºˆàº±àº”àºàº²àº™àº¢àº¹à»ˆàº™àº­àº Chrome ໄດ້. <ph name="BEGIN_LINK" />ສຶàºàºªàº²à»€àºžàºµà»ˆàº¡à»€àº•àºµàº¡<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ສົດໃà»à»ˆ</translation>
<translation id="9119042192571987207">ອັບໂຫລດà»àº¥à»‰àº§</translation>
<translation id="9128016270925453879">ໂຫຼດນະໂàºàºšàº²àºà»àº¥à»‰àº§</translation>
<translation id="9128870381267983090">ເຊື່ອມ​ຕà»à»ˆàºàº±àºšâ€‹à»€àº„ືອ​ຂ່າàº</translation>
@@ -2154,6 +2207,7 @@
<translation id="9170848237812810038">ບà»à»ˆà»€àº®àº±àº”</translation>
<translation id="9171296965991013597">ອອàºàºˆàº²àºà»àº­àº±àºšàºšà»?</translation>
<translation id="9173282814238175921">ເອàºàº°àºªàº²àº™àº”ຽວ/à»àºœà»ˆàº™àº§àº½àºà»ƒà»à»ˆ</translation>
+<translation id="9173995187295789444">àºàº³àº¥àº±àº‡àºªàº°à»àºàº™àº«àº²àº­àº¸àº›àº°àºàº­àº™ Bluetooth...</translation>
<translation id="917450738466192189">ໃບຢັ້ງຢືນຂອງເຊີບເວີໃຊ້ບà»à»ˆà»„ດ້.</translation>
<translation id="9174917557437862841">à»àº•àº°àº›àº¸à»ˆàº¡àºªàº°àº«àº¼àº±àºš, àºàº»àº” Enter ເພື່ອປ່ຽນເປັນà»àº–ບນີ້</translation>
<translation id="9179703756951298733">ຈັດàºàº²àº™àºàº²àº™àºˆà»ˆàº²àºà»€àº‡àº´àº™ à»àº¥àº° ຂà»à»‰àº¡àº¹àº™àºšàº±àº”ເຄຣດິດຂອງທ່ານໃນàºàº²àº™àº•àº±à»‰àº‡àº„່າ Chrome</translation>
diff --git a/chromium/components/strings/components_strings_lt.xtb b/chromium/components/strings/components_strings_lt.xtb
index d09ca35624b..2d25e3096a8 100644
--- a/chromium/components/strings/components_strings_lt.xtb
+++ b/chromium/components/strings/components_strings_lt.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Jei pažymÄ—ta, „Chrome“ iÅ¡saugos kortelÄ—s kopijÄ… įrenginyje, kad galÄ—tumÄ—te greiÄiau užpildyti formas.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" />: pasirinkite leidimÄ…</translation>
<translation id="1113869188872983271">&amp;Anuliuoti pertvarkymÄ…</translation>
+<translation id="1123753900084781868">Subtitrų realiuoju laiku funkcija dabar nepasiekiama</translation>
<translation id="1125573121925420732">Kol atnaujinami svetainių saugos nustatymai, gali būti dažnai rodomi įspėjimai. Netrukus tai turėtų būti išspręsta.</translation>
<translation id="112840717907525620">Gera politikos talpykla</translation>
<translation id="1130564665089811311">Mygtukas „Versti puslapį“, paspauskite „Enter“, kad Å¡is puslapis bÅ«tų verÄiamas naudojant „Google“ vertÄ—jÄ…</translation>
@@ -74,6 +75,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="1240347957665416060">Įrenginio pavadinimas</translation>
<translation id="124116460088058876">Daugiau kalbų</translation>
<translation id="1243027604378859286">Autorius:</translation>
+<translation id="1246424317317450637">Pusjuodis</translation>
<translation id="1250759482327835220">Kad kitÄ… kartÄ… galÄ—tumÄ—te greiÄiau atlikti mokÄ—jimÄ…, iÅ¡saugokite kortelÄ™, vardÄ… bei pavardÄ™ ir atsiskaitymo adresÄ… „Google“ paskyroje.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sinchronizuota)</translation>
<translation id="1256368399071562588">&lt;p&gt;Jei bandote apsilankyti svetainÄ—je, bet nepavyksta jos atidaryti, pirma pabandykite iÅ¡taisyti klaidÄ… atlikdami toliau nurodytus trikÄių Å¡alinimo veiksmus.&lt;/p&gt;
@@ -156,6 +158,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="1476595624592550506">Pakeiskite slaptažodį</translation>
<translation id="1484290072879560759">Pasirinkti pristatymo adresÄ…</translation>
<translation id="1492194039220927094">Politikos gavimas:</translation>
+<translation id="1495677929897281669">Atgal į skirtuką</translation>
<translation id="1501859676467574491">Rodyti korteles iš „Google“ paskyros</translation>
<translation id="1507202001669085618">&lt;p&gt;Ši klaida rodoma, jei naudojate „Wi-Fi“ portalą, prie kurio reikia prisijungti, kad galėtumėte naudotis internetu.&lt;/p&gt;
&lt;p&gt;Kad ištaisytumėte šią klaidą, puslapyje, kurį bandote atidaryti, spustelėkite &lt;strong&gt;Prisijungti&lt;/strong&gt;.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="1532118530259321453">Å iame puslapyje nurodyta:</translation>
<translation id="153384715582417236">Kol kas tiek</translation>
<translation id="1536390784834419204">Versti puslapį</translation>
+<translation id="1539840569003678498">Ataskaita išsiųsta:</translation>
<translation id="154408704832528245">Pasirinkti pristatymo adresÄ…</translation>
<translation id="1549470594296187301">Norint naudoti šią funkciją, reikia įgalinti „JavaScript“.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="1682696192498422849">Pirmiau trumpasis kraštas</translation>
<translation id="168693727862418163">Å ios politikos vertÄ—s nepavyko patvirtinti pagal schemÄ… ir jos bus nepaisoma.</translation>
<translation id="168841957122794586">Serverio sertifikate yra nesudÄ—tingas kriptografinis raktas.</translation>
+<translation id="1696290444144917273">Peržiūrėkite išsamią virtualios kortelės informaciją</translation>
<translation id="1697532407822776718">Viskas nustatyta!</translation>
<translation id="1703835215927279855">Laiškas</translation>
<translation id="1706954506755087368">{1,plural, =1{Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikatas įsigalios nuo rytojaus. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užpuoliko.}one{Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikatas įsigalios po # dienos. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užpuoliko.}few{Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikatas įsigalios po # dienų. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užpuoliko.}many{Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikatas įsigalios po # dienos. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užpuoliko.}other{Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikatas įsigalios po # dienų. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užpuoliko.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Nepaisoma, nes politikos „<ph name="POLICY_NAME" />“ parinktis nenustatyta į „<ph name="VALUE" />“.</translation>
<translation id="1712552549805331520"><ph name="URL" /> prašo leidimo nuolat saugoti duomenis vietiniame kompiuteryje</translation>
<translation id="1713628304598226412">2 dÄ—klas</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">3 pašto dėžutė</translation>
<translation id="1718029547804390981">Dokumentas per didelis, kad būtų galima komentuoti</translation>
<translation id="1721424275792716183">* Būtina užpildyti lauką</translation>
+<translation id="1727613060316725209">Sertifikatas galioja</translation>
<translation id="1727741090716970331">Tinkamo kortelÄ—s numerio pridÄ—jimas</translation>
<translation id="1728677426644403582">Peržiūrite tinklalapio šaltinį</translation>
<translation id="173080396488393970">Å io tipo kortelÄ— nepalaikoma</translation>
@@ -246,7 +253,6 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<ph name="SITE" /> užklausos. Pradinę politiką gali naudoti
svetainių operatoriai, siekdami konfigūruoti svetainės saugą ir kitas nuosavybes.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Atnaujinkite sinchronizavimo slaptafrazÄ™.</translation>
<translation id="1787142507584202372">Atidaryti skirtukai bus rodomi Äia</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, galimi keli veiksmai, paspauskite skirtukÄ…, norÄ—dami juos perjungti</translation>
@@ -279,6 +285,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="1919345977826869612">Skelbimai</translation>
<translation id="1919367280705858090">Gaukite pagalbos dėl konkretaus klaidos pranešimo</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Nėra}=1{1 svetainė}one{# svetainė}few{# svetainės}many{# svetainės}other{# svetainių}}</translation>
+<translation id="1924727005275031552">Naujas</translation>
<translation id="1945968466830820669">Galite prarasti prieigą prie organizacijos paskyros arba gali būti pavogta tapatybė. „Chromium“ rekomenduoja pakeisti slaptažodį dabar.</translation>
<translation id="1947454675006758438">Sankabėlė viršuje dešinėje</translation>
<translation id="1958218078413065209">Jūsų didžiausias rezultatas yra <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="2042213636306070719">7 dÄ—klas</translation>
<translation id="204357726431741734">Prisijunkite, kad galėtumėte naudoti „Google“ paskyroje išsaugotus slaptažodžius</translation>
<translation id="2053111141626950936">Puslapiai, paraÅ¡yti <ph name="LANGUAGE" />, verÄiami nebus.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Kai Å¡is valdiklis įjungtas ir bÅ«sena aktyvi, „Chrome“ nustato, į kuriÄ… didelÄ™ žmonių grupÄ™ panaÅ¡iausia jÅ«sų pastaroji narÅ¡ymo veikla. Reklamuotojai gali pasirinkti grupÄ—s skelbimus, o jÅ«sų narÅ¡ymo veikla saugoma privaÄiai jÅ«sų įrenginyje. GrupÄ— atnaujinama kiekvienÄ… dienÄ….}=1{Kai Å¡is valdiklis įjungtas ir bÅ«sena aktyvi, „Chrome“ nustato, į kuriÄ… didelÄ™ žmonių grupÄ™ panaÅ¡iausia jÅ«sų pastaroji narÅ¡ymo veikla. Reklamuotojai gali pasirinkti grupÄ—s skelbimus, o jÅ«sų narÅ¡ymo veikla saugoma privaÄiai jÅ«sų įrenginyje. GrupÄ— atnaujinama kiekvienÄ… dienÄ….}one{Kai Å¡is valdiklis įjungtas ir bÅ«sena aktyvi, „Chrome“ nustato, į kuriÄ… didelÄ™ žmonių grupÄ™ panaÅ¡iausia jÅ«sų pastaroji narÅ¡ymo veikla. Reklamuotojai gali pasirinkti grupÄ—s skelbimus, o jÅ«sų narÅ¡ymo veikla saugoma privaÄiai jÅ«sų įrenginyje. GrupÄ— atnaujinama kas {NUM_DAYS} dienÄ….}few{Kai Å¡is valdiklis įjungtas ir bÅ«sena aktyvi, „Chrome“ nustato, į kuriÄ… didelÄ™ žmonių grupÄ™ panaÅ¡iausia jÅ«sų pastaroji narÅ¡ymo veikla. Reklamuotojai gali pasirinkti grupÄ—s skelbimus, o jÅ«sų narÅ¡ymo veikla saugoma privaÄiai jÅ«sų įrenginyje. GrupÄ— atnaujinama kas {NUM_DAYS} dienas.}many{Kai Å¡is valdiklis įjungtas ir bÅ«sena aktyvi, „Chrome“ nustato, į kuriÄ… didelÄ™ žmonių grupÄ™ panaÅ¡iausia jÅ«sų pastaroji narÅ¡ymo veikla. Reklamuotojai gali pasirinkti grupÄ—s skelbimus, o jÅ«sų narÅ¡ymo veikla saugoma privaÄiai jÅ«sų įrenginyje. GrupÄ— atnaujinama kas {NUM_DAYS} dienos.}other{Kai Å¡is valdiklis įjungtas ir bÅ«sena aktyvi, „Chrome“ nustato, į kuriÄ… didelÄ™ žmonių grupÄ™ panaÅ¡iausia jÅ«sų pastaroji narÅ¡ymo veikla. Reklamuotojai gali pasirinkti grupÄ—s skelbimus, o jÅ«sų narÅ¡ymo veikla saugoma privaÄiai jÅ«sų įrenginyje. GrupÄ— atnaujinama kas {NUM_DAYS} dienų.}}</translation>
<translation id="2053553514270667976">Pašto kodas</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 pasiūlymas}one{# pasiūlymas}few{# pasiūlymai}many{# pasiūlymo}other{# pasiūlymų}}</translation>
<translation id="2071692954027939183">Pranešimai automatiškai užblokuoti, nes įprastai jų neleidžiate</translation>
<translation id="2079545284768500474">Anuliuoti</translation>
<translation id="20817612488360358">Sistemos įgaliotojo serverio nustatymai nustatyti kaip naudotini, bet taip pat nurodyta tiksli įgaliotojo serverio konfigūracija.</translation>
<translation id="2082238445998314030">Rezultatų: <ph name="RESULT_NUMBER" /> iš <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Išsaugoti…</translation>
<translation id="2088086323192747268">Mygtukas „Tvarkyti sinchronizavimą“; paspauskite „Enter“, jei norite tvarkyti sinchronizuojamą informaciją „Chrome“ nustatymuose</translation>
<translation id="2091887806945687916">Garsas</translation>
<translation id="2094505752054353250">Domeno neatitikimas</translation>
@@ -379,6 +388,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="2317259163369394535"><ph name="DOMAIN" /> būtina įvesti naudotojo vardą ir slaptažodį.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, baigia galioti <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">NustatymÄ… valdo administratorius</translation>
+<translation id="2340263603246777781">Svetainė <ph name="ORIGIN" /> nori būti susieta su</translation>
<translation id="2344028582131185878">Automatiniai atsisiuntimai</translation>
<translation id="2346319942568447007">Nukopijuotas vaizdas</translation>
<translation id="2354001756790975382">Kitos žymės</translation>
@@ -386,8 +396,10 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="2355395290879513365">Užpuolikai galbūt galės matyti, kuriuos šios svetainės vaizdus peržiūrite, ir juos pakeis siekdami jus suklaidinti.</translation>
<translation id="2356070529366658676">Paklausti</translation>
<translation id="2357481397660644965">Jūsų įrenginį valdo <ph name="DEVICE_MANAGER" />, o paskyrą – <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Mažiau nei per dieną}=1{Per dieną}one{Per {NUM_DAYS} dieną}few{Per {NUM_DAYS} dienas}many{Per {NUM_DAYS} dienos}other{Per {NUM_DAYS} dienų}}</translation>
<translation id="2359629602545592467">Kelios</translation>
<translation id="2359808026110333948">Tęskite</translation>
+<translation id="2359961752320758691">Virtualios kortelÄ—s numeris pritaikytas.</translation>
<translation id="2367567093518048410">Lygis</translation>
<translation id="2372464001869762664">Kai patvirtinsite, „Google“ paskyroje nurodyta išsami kortelės informacija bus bendrinama su šia svetaine. Raskite kortelės saugos kodą (CVC) „Plex“ paskyros išsamios informacijos skiltyje.</translation>
<translation id="2380886658946992094">Teisinis</translation>
@@ -398,6 +410,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="239429038616798445">Å is pristatymo metodas nepasiekiamas. IÅ¡bandykite kitÄ… metodÄ….</translation>
<translation id="2396249848217231973">&amp;Anuliuoti ištrynimą</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Senas</translation>
<translation id="2413528052993050574">Šiam serveriui nepavyko patvirtinti, kad tai yra <ph name="DOMAIN" />; jo saugos sertifikatas gali būti atšauktas. Taip gali nutikti dėl netinkamos konfigūracijos ar dėl ryšį pertraukusio užgrobėjo.</translation>
<translation id="2414886740292270097">Tamsi</translation>
<translation id="2438874542388153331">Keturios skylės dešinėje</translation>
@@ -425,10 +438,10 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="2521385132275182522">SankabÄ—lÄ— apaÄioje deÅ¡inÄ—je</translation>
<translation id="2523886232349826891">Išsaugota tik šiame įrenginyje</translation>
<translation id="2524461107774643265">Daugiau informacijos pridÄ—jimas</translation>
-<translation id="2526590354069164005">Darbalaukis</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{ir dar 1}one{ir dar #}few{ir dar #}many{ir dar #}other{ir dar #}}</translation>
<translation id="2536110899380797252">PridÄ—ti adresÄ…</translation>
<translation id="2539524384386349900">Aptikti</translation>
+<translation id="2541219929084442027">Puslapiai, kuriuos peržiūrite inkognito skirtukuose, nebus rodomi naršyklės istorijoje, slapukų saugykloje ar paieškos istorijoje, kai uždarysite visus inkognito skirtukus. Visi atsisiųsti failai ar sukurtos žymės išliks.</translation>
<translation id="2544644783021658368">Vienas dokumentas</translation>
<translation id="254947805923345898">Politikos vertÄ— netinkama.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> išsiuntė netinkamą atsaką.</translation>
@@ -448,6 +461,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="2629325967560697240">Jei norite, kad bÅ«tų užtikrinta aukÅ¡Äiausio lygio „Chrome“ sauga, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />įjunkite sustiprintÄ… apsaugÄ…<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Nepavyko rasti <ph name="HOST_NAME" /> serverio IP adreso.</translation>
<translation id="2639739919103226564">BÅ«sena:</translation>
+<translation id="264810637653812429">Nerasta jokių suderinamų įrenginių.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, paspauskite tabuliavimo klavišą, tada – „Enter“, kad būtų išvalyta naršymo istorija, slapukai, talpyklė ir kt. „Chrome“ nustatymuose</translation>
<translation id="2650446666397867134">Prieiga prie failo atmesta</translation>
@@ -494,6 +508,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<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="2807052079800581569">Vaizdo Y padÄ—tis</translation>
+<translation id="2820957248982571256">Nuskaitoma...</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>
@@ -501,6 +516,8 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="2850739647070081192">„Invite“ (vokas)</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="2859806420264540918">Å ioje svetainÄ—je rodomi nepageidaujami arba klaidinantys skelbimai.</translation>
+<translation id="287596039013813457">Draugiška</translation>
+<translation id="2876489322757410363">Išjungiate inkognito režimą, kad galėtumėte sumokėti naudodami išorinę programą. Tęsti?</translation>
<translation id="2878197950673342043">Perlenkimas į keturias dalis</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Lango padÄ—ties nustatymas</translation>
@@ -550,7 +567,6 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="3060227939791841287">C9 (vokas)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, paspauskite tabuliavimo klavišą, tada – „Enter“, kad paleistumėte Saugos patikrą „Chrome“ nustatymuose</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>
<translation id="306573536155379004">Žaidimas prasidėjo.</translation>
<translation id="3080254622891793721">Grafiniai elementai</translation>
<translation id="3086579638707268289">Jūsų veikla žiniatinklyje stebima</translation>
@@ -573,7 +589,6 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="315504272643575312">Jūsų paskyrą tvarko <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Atkurti</translation>
<translation id="3162559335345991374">Naudojant šį „Wi-Fi“ tinklą gali būti prašoma apsilankyti prisijungimo puslapyje.</translation>
-<translation id="3167968892399408617">Puslapiai, kuriuos peržiūrite inkognito skirtukų lapuose, nebus rodomi naršyklės istorijoje, slapukų saugykloje ar paieškos istorijoje, kai uždarysite visus inkognito skirtukų lapus. Visi atsisiųsti failai ar sukurtos žymės išliks.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Sala</translation>
<translation id="3176929007561373547">Patikrinkite tarpinio serverio nustatymus arba susisiekite su tinklo
@@ -600,10 +615,12 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<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="3249845759089040423">Klasiška</translation>
<translation id="3252266817569339921">Prancūzų</translation>
<translation id="3266793032086590337">VertÄ— (nesuderinama)</translation>
<translation id="3268451620468152448">Atidaryti skirtukai</translation>
<translation id="3270847123878663523">&amp;Anuliuoti pertvarkymÄ…</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> nori prisijungti</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Jūsų organizacija (<ph name="ENROLLMENT_DOMAIN" />) nusiuntė tam tikros informacijos, pvz., informacijos apie nustatymus ar politikos nuostatas, toliau nurodytoms svetainėms.</translation>
<translation id="3282497668470633863">Ant kortelÄ—s pateikto vardo pridÄ—jimas</translation>
@@ -656,6 +673,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="3428151540071562330">Vienas arba keli „DnsOverHttpsTemplates“ serverio šablono URI yra netinkami ir nebus naudojami.</translation>
<translation id="3431636764301398940">Išsaugoti šią kortelę šiame įrenginyje</translation>
<translation id="3432601291244612633">Uždaryti puslapį</translation>
+<translation id="3435738964857648380">Sauga</translation>
<translation id="3435896845095436175">Įgalinti</translation>
<translation id="3438829137925142401">Naudoti „Google“ paskyroje išsaugotus slaptažodžius</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -698,7 +716,10 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="3584299510153766161">Dvi skylÄ—s apaÄioje</translation>
<translation id="3586931643579894722">Slėpti išsamią informaciją</translation>
<translation id="3587738293690942763">Vidurys</translation>
+<translation id="3590643883886679995">Prisijungimo duomenys bus saugomi šiame įrenginyje, kai išjungsite inkognito režimą.</translation>
+<translation id="359126217934908072">MÄ—nuo ir (arba) metai:</translation>
<translation id="3592413004129370115">„Italian“ (vokas)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Grupę bet kuriuo metu galite nustatyti iš naujo. Prisijungimas prie naujos grupės užtruks maždaug dieną.}=1{Grupę bet kuriuo metu galite nustatyti iš naujo. Prisijungimas prie naujos grupės užtruks maždaug dieną.}one{Grupę bet kuriuo metu galite nustatyti iš naujo. Prisijungimas prie naujos grupės užtruks {NUM_DAYS} dieną.}few{Grupę bet kuriuo metu galite nustatyti iš naujo. Prisijungimas prie naujos grupės užtruks {NUM_DAYS} dienas.}many{Grupę bet kuriuo metu galite nustatyti iš naujo. Prisijungimas prie naujos grupės užtruks {NUM_DAYS} dienos.}other{Grupę bet kuriuo metu galite nustatyti iš naujo. Prisijungimas prie naujos grupės užtruks {NUM_DAYS} dienų.}}</translation>
<translation id="3600246354004376029">„<ph name="TITLE" />“, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Programą užblokavo administratorius</translation>
<translation id="3608932978122581043">Pateikti orientacijÄ…</translation>
@@ -707,13 +728,13 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="3615877443314183785">Įveskite tinkamą galiojimo laiko pabaigos datą</translation>
<translation id="36224234498066874">Išvalyti naršymo duomenis...</translation>
<translation id="362276910939193118">Rodyti visÄ… istorijÄ…</translation>
-<translation id="3625635938337243871">Prisijungimo duomenys bus saugomi šiame įrenginyje, kai išjungsite inkognito režimą.</translation>
<translation id="3630155396527302611">Jei ji nurodyta kaip programa, kuriai leidžiama pasiekti tinklą, pabandykite
ją pašalinti iš sąrašo ir vėl pridėti.</translation>
<translation id="3630699740441428070">Šio įrenginio administratoriai sukonfigūravo jūsų tinklo ryšį, per kurį gali peržiūrėti jūsų tinklo srautą, įskaitant lankomas svetaines.</translation>
<translation id="3631244953324577188">BiometrinÄ—s sistemos</translation>
<translation id="3633738897356909127">Mygtukas „Atnaujinti „Chrome“, paspauskite „Enter“, kad „Chrome“ nustatymuose būtų atnaujinta naršyklė „Chrome“</translation>
<translation id="3634530185120165534">5 dÄ—klas</translation>
+<translation id="3637662659967048211">Išsaugojimas „Google“ paskyroje</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Programa:</translation>
<translation id="3650584904733503804">Tikrinimas sÄ—kmingas</translation>
@@ -754,6 +775,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="3781428340399460090">Ryškiai rausva</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">„Bluetooth“ įrenginiai</translation>
+<translation id="3787675388804467730">Virtualios kortelÄ—s numeris</translation>
<translation id="3787705759683870569">Galiojimo laikas baigiasi <ph name="EXPIRATION_MONTH" /> / <ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Dydis: 16</translation>
<translation id="3789841737615482174">Įdiegti</translation>
@@ -773,6 +795,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="3841184659773414994">Failų doroklės</translation>
<translation id="385051799172605136">Atgal</translation>
<translation id="3858027520442213535">Atnaujinti datÄ… ir laikÄ…</translation>
+<translation id="3881478300875776315">Rodyti mažiau eiluÄių</translation>
<translation id="3884278016824448484">Nesuderinamas įrenginio identifikatorius</translation>
<translation id="3885155851504623709">Parapija</translation>
<translation id="388632593194507180">Aptiktas stebÄ—jimas</translation>
@@ -798,6 +821,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="397105322502079400">SkaiÄiuojama...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> užblokuota.</translation>
<translation id="3973357910713125165">Paleiskite „Chrome“ Saugos patikros mygtuką, paspausdami „Enter“ paleiskite Saugos patikrą „Chrome“ nustatymuose</translation>
+<translation id="3986705137476756801">Kol kas išjungti subtitrų realiuoju laiku funkciją</translation>
<translation id="3987405730340719549">„Chrome“ nustatė, kad ši svetainė gali būti suklastota ar apgavikiška.
Jei manote, kad šis pranešimas rodomas per klaidą, apsilankykite adresu https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -894,13 +918,14 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="4275830172053184480">Iš naujo paleisti įrenginį</translation>
<translation id="4277028893293644418">Iš naujo nustatyti slaptažodį</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="4287885627794386150">Galima naudoti bandomÄ…jÄ… versijÄ…, bet ji nÄ—ra aktyvi</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> puslapio miniatiūra</translation>
<translation id="42981349822642051">IÅ¡skleisti</translation>
<translation id="4300675098767811073">Kelios skylės dešinėje</translation>
<translation id="4302514097724775343">Palieskite dinozaurÄ…, kad paleistumÄ—te</translation>
<translation id="4302965934281694568">„Chou3“ (vokas)</translation>
<translation id="4305666528087210886">Nepavyko pasiekti failo</translation>
-<translation id="4305817255990598646">Perjungti</translation>
+<translation id="4306529830550717874">IÅ¡saugoti adresÄ…?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Užblokuoti (numatytoji parinktis)</translation>
<translation id="4314815835985389558">Sinchronizavimo tvarkymas</translation>
@@ -927,6 +952,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="4377125064752653719">Bandėte pasiekti svetainę „<ph name="DOMAIN" />“, bet sertifikatą, kurį pateikė serveris, anuliavo jo išdavėjas. Tai reiškia, kad saugos kredencialais, kuriuos pateikė serveris, visiškai negalima pasitikėti. Galbūt bendraujate su užpuoliku.</translation>
<translation id="4378154925671717803">Telefonas</translation>
<translation id="4390472908992056574">Kraštas</translation>
+<translation id="4406883609789734330">Subtitrai realiuoju laiku</translation>
<translation id="4406896451731180161">paieškos rezultatai</translation>
<translation id="4408413947728134509">Slapukai <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Ką tik savo slaptažodį įvedėte apgaulingoje svetainėje. „Chrome“ rekomenduoja dabar apsilankyti <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ir kitose svetainėse, kuriose naudojate šį slaptažodį, ir jį pakeisti.</translation>
@@ -939,7 +965,6 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="4435702339979719576">Atvirukas</translation>
<translation id="443673843213245140">Įgaliotojo serverio naudojimas neleidžiamas, bet nurodyta aiški įgaliotojo serverio konfigūracija.</translation>
<translation id="4464826014807964867">Svetainės, kuriose yra informacijos iš jūsų organizacijos</translation>
-<translation id="4466881336512663640">Formos pakeitimai bus prarasti. Ar tikrai norite tęsti?</translation>
<translation id="4476953670630786061">Ši forma nesaugi. Automatinis pildymas išjungtas.</translation>
<translation id="4477350412780666475">Kitas takelis</translation>
<translation id="4482953324121162758">Å i svetainÄ— nebus verÄiama.</translation>
@@ -973,6 +998,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="4594403342090139922">&amp;Anuliuoti ištrynimą</translation>
<translation id="4597348597567598915">Dydis: 8</translation>
<translation id="4600854749408232102">C6 / C5 (vokas)</translation>
+<translation id="4606870351894164739">Įtakinga</translation>
<translation id="4628948037717959914">Nuotrauka</translation>
<translation id="4631649115723685955">Grynųjų grąžinimas susietas</translation>
<translation id="4636930964841734540">Informacija</translation>
@@ -992,6 +1018,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="4691835149146451662">„Architecture-A“ (vokas)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Å onas</translation>
+<translation id="4702656508969495934">Matomi subtitrai realiuoju laiku; naudokite langų perjungiklį, kad suaktyvintumėte juos</translation>
<translation id="4708268264240856090">Ryšys nutrauktas</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Paleistas įrankis „Windows Network Diagnostics“<ph name="END_LINK" />.</translation>
@@ -1005,6 +1032,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="4738601419177586157">„<ph name="TEXT" />“ paieškos pasiūlymas</translation>
<translation id="4742407542027196863">Tvarkyti slaptažodžius…</translation>
<translation id="4744603770635761495">Vykdomasis kelias</translation>
+<translation id="4749011317274908093">Veikia inkognito režimas</translation>
<translation id="4750917950439032686">Ä® Å¡iÄ… svetainÄ™ siunÄiama informacija (pvz., slaptažodžiai arba kredito kortelių numeriai) yra privati.</translation>
<translation id="4756388243121344051">&amp;Istorija</translation>
<translation id="4758311279753947758">PridÄ—ti kontaktinÄ™ informacijÄ…</translation>
@@ -1034,6 +1062,8 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="4813512666221746211">Tinklo klaida</translation>
<translation id="4816492930507672669">Pritaikyti pagal puslapį</translation>
<translation id="4819347708020428563">Redaguoti komentarus numatytajame rodinyje?</translation>
+<translation id="4825507807291741242">Veiksminga</translation>
+<translation id="4838327282952368871">Svajinga</translation>
<translation id="484462545196658690">Automatiškai</translation>
<translation id="4850886885716139402">Žiūrėti</translation>
<translation id="485316830061041779">VokieÄių</translation>
@@ -1170,6 +1200,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="5314967030527622926">Lankstinukų rengyklė</translation>
<translation id="5316812925700871227">Pasukti prieš laikrodžio rodyklę</translation>
<translation id="5317780077021120954">IÅ¡saugoti</translation>
+<translation id="5321288445143113935">Padidintas</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> iš <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Pasirinkti kontaktinÄ™ informacijÄ…</translation>
<translation id="5327248766486351172">Pavadinimas</translation>
@@ -1177,11 +1208,13 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="5332219387342487447">Pristatymo metodas</translation>
<translation id="5333022057423422993">„Chrome“ aptiko, kad slaptažodis, kurį ką tik naudojote, buvo atskleistas įvykus duomenų saugos pažeidimui. Kad galėtumėte apsaugoti paskyras, rekomenduojame patikrinti išsaugotus slaptažodžius.</translation>
<translation id="5334013548165032829">Išsamūs sistemos žurnalai</translation>
+<translation id="5334145288572353250">IÅ¡saugoti adresÄ…?</translation>
<translation id="5340250774223869109">Programa užblokuota</translation>
<translation id="534295439873310000">ALR įrenginiai</translation>
<translation id="5344579389779391559">Šiame puslapyje gali būti bandoma jus apmokestinti</translation>
<translation id="5355557959165512791">Negalite dabar apsilankyti svetainėje <ph name="SITE" />, nes jos sertifikatas buvo anuliuotas. Tinklo klaidos ir užpuolimai dažniausiai yra laikini, todėl šis puslapis vėliau tikriausiai veiks.</translation>
<translation id="536296301121032821">Išsaugant politikos nustatymus įvyko klaida</translation>
+<translation id="5363309033720083897">Administratorius leidžia naudoti nuoseklųjį prievadą</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="5386426401304769735">Šios svetainės sertifikatų grandinėje yra sertifikatas, pasirašytas naudojant SHA-1.</translation>
@@ -1190,6 +1223,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="5398772614898833570">Skelbimai užblokuoti</translation>
<translation id="5400836586163650660">Pilka spalva</translation>
<translation id="540969355065856584">Šiam serveriui nepavyko patvirtinti, kad jis yra <ph name="DOMAIN" />; šiuo metu jo saugos sertifikatas negalioja. Tai gali būti dėl netinkamos konfigūracijos arba dėl ryšį pertraukusio užgrobėjo.</translation>
+<translation id="541143247543991491">Debesis (visa sistema)</translation>
<translation id="541416427766103491">4 dÄ—tuvÄ—</translation>
<translation id="5421136146218899937">Išvalyti naršymo duomenis...</translation>
<translation id="5426179911063097041">Svetainė <ph name="SITE" /> nori siųsti jums pranešimus</translation>
@@ -1203,6 +1237,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="5455374756549232013">Bloga politikos laiko žymė</translation>
<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="5463625433003343978">Ieškoma įrenginių...</translation>
<translation id="5469868506864199649">Italų</translation>
<translation id="5470861586879999274">&amp;Redaguoti dar kartÄ…</translation>
<translation id="5478437291406423475">B6 / C4 (vokas)</translation>
@@ -1252,7 +1287,6 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="5624120631404540903">Tvarkyti slaptažodžius</translation>
<translation id="5629630648637658800">Įkeliant politikos nustatymus įvyko klaida</translation>
<translation id="5631439013527180824">Netinkamas įrenginio tvarkymo prieigos raktas</translation>
-<translation id="5632627355679805402">Nuo <ph name="TIME" /> duomenys užšifruoti naudojant <ph name="BEGIN_LINK" />„Google“ slaptažodį<ph name="END_LINK" />. Įveskite jį, kad pradėtumėte sinchronizuoti.</translation>
<translation id="5633066919399395251">Šiuo metu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> užpuolikai gali jūsų kompiuteryje bandyti įdiegti pavojingas programas, kurios vagia arba ištrina informaciją (pvz., nuotraukas, slaptažodžius, pranešimus ir kredito kortelių duomenis). <ph name="BEGIN_LEARN_MORE_LINK" />Sužinokite daugiau<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Klaidinantis turinys užblokuotas.</translation>
<translation id="5644090287519800334">1 pusė: sukti vaizdą pagal X ašį</translation>
@@ -1291,12 +1325,12 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="5785756445106461925">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 išvaizdą.</translation>
<translation id="5786044859038896871">Ar norite, kad būtų įvesta jūsų kredito kortelės informacija?</translation>
<translation id="578633867165174378">„Chrome“ aptiko, kad slaptažodis, kurį ką tik naudojote, buvo atskleistas įvykus duomenų saugos pažeidimui. Rekomenduojame dabar pakeisti šį slaptažodį.</translation>
-<translation id="5798290721819630480">Atmesti pakeitimus?</translation>
<translation id="5803412860119678065">Ar norite, kad būtų įvesta <ph name="CARD_DETAIL" /> informacija?</translation>
<translation id="5804241973901381774">Leidimai</translation>
<translation id="5804427196348435412">Naudoti ALR įrenginius</translation>
<translation id="5810442152076338065">Ryšys su <ph name="DOMAIN" /> užšifruotas naudojant pasenusį šifravimo paketą.</translation>
<translation id="5813119285467412249">&amp;PridÄ—ti dar kartÄ…</translation>
+<translation id="5817918615728894473">Susieti</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Ši kortelė bus apmokestinama mokant, bet jos tikrasis numeris nebus bendrinamas su šia svetaine. Siekiant užtikrinti papildomą apsaugą, bus sugeneruotas laikinas kortelės saugos kodas (CVC).}one{Jūsų pasirinktos kortelės bus apmokestinamos mokant, bet jų tikrieji numeriai nebus bendrinami su šia svetaine. Siekiant užtikrinti papildomą apsaugą, bus sugeneruotas laikinas kortelės saugos kodas (CVC).}few{Jūsų pasirinktos kortelės bus apmokestinamos mokant, bet jų tikrieji numeriai nebus bendrinami su šia svetaine. Siekiant užtikrinti papildomą apsaugą, bus sugeneruotas laikinas kortelės saugos kodas (CVC).}many{Jūsų pasirinktos kortelės bus apmokestinamos mokant, bet jų tikrieji numeriai nebus bendrinami su šia svetaine. Siekiant užtikrinti papildomą apsaugą, bus sugeneruotas laikinas kortelės saugos kodas (CVC).}other{Jūsų pasirinktos kortelės bus apmokestinamos mokant, bet jų tikrieji numeriai nebus bendrinami su šia svetaine. Siekiant užtikrinti papildomą apsaugą, bus sugeneruotas laikinas kortelės saugos kodas (CVC).}}</translation>
<translation id="5826507051599432481">Bendrasis vardas (angl. „Common Name“) (CN)</translation>
<translation id="5838278095973806738">Šioje svetainėje neturėtumėte pateikti neskelbtinos informacijos (pvz., slaptažodžių ar kredito kortelių numerių), nes ją gali pavogti užpuolikai.</translation>
@@ -1304,6 +1338,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="5855253129151731373">Šios svetainės prieglobos serverio pavadinimas panašus į <ph name="LOOKALIKE_DOMAIN" />. Kartais užpuolėjai kurdami svetainių kopijas atlieka nedidelių, sunkiai pastebimų domeno pavadinimio pakeitimų.
Jei manote, kad šis pranešimas rodomas per klaidą, apsilankykite adresu https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">IÅ¡jungta</translation>
<translation id="5862579898803147654">8 dÄ—tuvÄ—</translation>
<translation id="5863847714970149516">Toliau pateiktame puslapyje gali būti bandoma jus apmokestinti</translation>
<translation id="5866257070973731571">Telefono numerio pridÄ—jimas</translation>
@@ -1320,6 +1355,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="5913377024445952699">Ekrano fiksavimas pristabdytas</translation>
<translation id="59174027418879706">Įjungta</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{Naudojamas 1 slapukas}one{Naudojamas # slapukas}few{Naudojami # slapukai}many{Naudojama # slapuko}other{Naudojama # slapukų}}</translation>
<translation id="5921185718311485855">Įjungta</translation>
<translation id="5921639886840618607">Išsaugoti kortelę „Google“ paskyroje?</translation>
<translation id="5922853866070715753">Beveik atlikta</translation>
@@ -1339,6 +1375,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="5989320800837274978">Nenurodyti nei fiksuoti įgaliotieji serveriai, nei .pac scenarijaus URL.</translation>
<translation id="5992691462791905444">Neproporcingas Z formos perlenkimas</translation>
<translation id="6000758707621254961">Rezultatų pagal užklausą „<ph name="SEARCH_TEXT" />“: <ph name="RESULT_COUNT" /></translation>
+<translation id="6006484371116297560">KlasikinÄ—</translation>
<translation id="6008122969617370890">Tvarka: nuo N iki 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Patikrinkite slaptažodžius</translation>
@@ -1360,6 +1397,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="6045164183059402045">Paskyrimo Å¡ablonas</translation>
<translation id="6047233362582046994">Jei suprantate, kokia rizika gali kilti jūsų saugai, galite <ph name="BEGIN_LINK" />apsilankyti šioje svetainėje<ph name="END_LINK" />, kol iš jos dar nepašalintos kenkėjiškos programos.</translation>
<translation id="6047927260846328439">Šiuo turiniu gali būti bandoma apgaule priversti jus įdiegti programinę įrangą arba atskleisti asmens informaciją. <ph name="BEGIN_LINK" />Rodyti vis tiek<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Paspauskite ir palaikykite |<ph name="ACCELERATOR" />|, kad išeitumėte iš viso ekrano režimo.</translation>
<translation id="6049488691372270142">Puslapių teikimas</translation>
<translation id="6051221802930200923">Šiuo metu negalite apsilankyti <ph name="SITE" />, nes svetainėje naudojamas sertifikatų prisegimas. Tinklo klaidos ir užpuolimai dažniausiai yra laikini, todėl šis puslapis vėliau tikriausiai veiks.</translation>
<translation id="6051898664905071243">Puslapių skaiÄius:</translation>
@@ -1376,6 +1414,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<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>
<translation id="6116338172782435947">Peržiūrėti tekstą ir vaizdus, nukopijuotus į iškarpinę</translation>
<translation id="6120179357481664955">Prisiminti UPI ID?</translation>
+<translation id="6123290840358279103">Žr. virtualią kortelę</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Patikrinkite laidus ir iš naujo paleiskite maršruto parinktuvus, modemus ar kitus
naudojamus tinklo įrenginius.</translation>
@@ -1412,6 +1451,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="6289939620939689042">Puslapio spalva</translation>
<translation id="6290238015253830360">JÅ«sų pasiÅ«lyti straipsniai rodomi Äia</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">KortelÄ—s patvirtinimo kodas CVC:</translation>
<translation id="6302269476990306341">„Google“ padėjėjas sistemoje „Chrome“ sustabdomas</translation>
<translation id="6305205051461490394"><ph name="URL" /> nepasiekiama.</translation>
<translation id="6312113039770857350">Tinklalapis nepasiekiamas</translation>
@@ -1437,6 +1477,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="6390200185239044127">Z formos perlenkimas pusiau</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Pagal administratoriaus politiką galimybė įklijuoti iš <ph name="ORIGIN_NAME" /> į šią vietą blokuojama</translation>
+<translation id="6398765197997659313">Išeiti iš viso ekrano režimo</translation>
<translation id="6401136357288658127">Ši politika nebenaudojama. Vietoj jos turėtumėte naudoti politiką „<ph name="NEW_POLICY" />“.</translation>
<translation id="6404511346730675251">Redaguoti žymę</translation>
<translation id="6406765186087300643">C0 (vokas)</translation>
@@ -1449,7 +1490,6 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="6428450836711225518">Patvirtinkite savo telefono numerį</translation>
<translation id="6433490469411711332">KontaktinÄ—s informacijos redagavimas</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> atsisakÄ— prisijungti.</translation>
-<translation id="6434309073475700221">IÅ¡mesti</translation>
<translation id="6440503408713884761">Nepaisoma</translation>
<translation id="6443406338865242315">Kuriuos plėtinius ir papildinius įdiegėte</translation>
<translation id="6446163441502663861">„Kahu“ (vokas)</translation>
@@ -1492,6 +1532,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="6624427990725312378">KontaktinÄ— informacija</translation>
<translation id="6626291197371920147">GaliojanÄios kortelÄ—s numerio pridÄ—jimas</translation>
<translation id="6628463337424475685">„<ph name="ENGINE" />“ paieška</translation>
+<translation id="6630043285902923878">Ieškoma USB įrenginių...</translation>
<translation id="6630809736994426279">Šiuo metu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> užpuolikai gali jūsų „Mac“ įrenginyje bandyti įdiegti pavojingas programas, kurios vagia arba ištrina informaciją (pvz., nuotraukas, slaptažodžius, pranešimus ir kredito kortelių duomenis). <ph name="BEGIN_LEARN_MORE_LINK" />Sužinokite daugiau<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">IÅ¡valyti</translation>
@@ -1507,6 +1548,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="6671697161687535275">Pašalinti formos pasiūlymą iš „Chromium“?</translation>
<translation id="6685834062052613830">Atsijunkite ir užbaikite sąranką</translation>
<translation id="6687335167692595844">Reikia nurodyti šrifto dydį</translation>
+<translation id="6688743156324860098">Atnaujinti…</translation>
<translation id="6689249931105087298">Santykinis su juodų taškų sutankinimu</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="6698381487523150993">Sukurta:</translation>
@@ -1522,6 +1564,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="6744009308914054259">Laukdami ryšio galite apsilankyti skiltyje „Atsisiuntimai“ ir perskaityti neprisijungus pasiekiamus straipsnius.</translation>
<translation id="6753269504797312559">Politikos vertÄ—</translation>
<translation id="6757797048963528358">Įjungta įrenginio miego būsena.</translation>
+<translation id="6767985426384634228">Atnaujinti adresÄ…?</translation>
<translation id="6768213884286397650">„Hagaki“ (atvirukas)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">VioletinÄ—</translation>
@@ -1544,6 +1587,7 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">„Chrome“ supaprastino šį puslapį, kad bÅ«tų paprasÄiau skaityti. „Chrome“ gavo pradinį puslapį prisijungusi nesaugiu ryÅ¡iu.</translation>
<translation id="6891596781022320156">Politikos lygis nepalaikomas.</translation>
+<translation id="6895143722905299846">Virtualus numeris:</translation>
<translation id="6895330447102777224">KortelÄ— patvirtinta</translation>
<translation id="6897140037006041989">Naudotojo atstovas</translation>
<translation id="6898699227549475383">Organizacija (O)</translation>
@@ -1579,10 +1623,10 @@ Kitu atveju tai bus užblokuota pagal jūsų privatumo nustatymus. Taip turinys,
<translation id="7004583254764674281">Su „Windows Hello“ korteles patvirtinsite greiÄiau</translation>
<translation id="7006930604109697472">Vis tiek siųsti</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Dydžio keitimo nustatymai</translation>
<translation id="7014741021609395734">Mastelio keitimo lygis</translation>
<translation id="7016992613359344582">Å ie mokesÄiai gali bÅ«ti vienkartiniai arba pasikartojantys ir gali bÅ«ti neaiÅ¡kÅ«s.</translation>
<translation id="7029809446516969842">Slaptažodžiai</translation>
+<translation id="7030436163253143341">Sertifikatas negalioja</translation>
<translation id="7031646650991750659">Kurias „Google Play“ programas įdiegėte</translation>
<translation id="7050187094878475250">Bandėte pasiekti <ph name="DOMAIN" />, bet serveris pateikė sertifikatą, kurio galiojimo laikotarpis per ilgas, kad būtų patikimas.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Šiuo metu šios kortelės išsaugoti negalima}one{Šiuo metu šių kortelių išsaugoti negalima}few{Šiuo metu šių kortelių išsaugoti negalima}many{Šiuo metu šių kortelių išsaugoti negalima}other{Šiuo metu šių kortelių išsaugoti negalima}}</translation>
@@ -1652,12 +1696,14 @@ Papildoma išsami informacija:
<translation id="7300012071106347854">Kobalto mÄ—lyna</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />“</translation>
<translation id="7304030187361489308">Aukštas</translation>
+<translation id="7305756307268530424">PradÄ—ti lÄ—Äiau</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Su ryšiu susijusi pagalba</translation>
<translation id="7323804146520582233">Slėpti skiltį „<ph name="SECTION" />“</translation>
<translation id="733354035281974745">Įrenginio vietos paskyros nepaisymas</translation>
<translation id="7333654844024768166">Ką tik savo slaptažodį įvedėte apgaulingoje svetainėje. „Chromium“ rekomenduoja dabar apsilankyti <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ir kitose svetainėse, kuriose naudojate šį slaptažodį, ir jį pakeisti.</translation>
<translation id="7334320624316649418">&amp;Pertvarkyti dar kartÄ…</translation>
+<translation id="7337248890521463931">Rodyti daugiau eiluÄių</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>
@@ -1665,6 +1711,7 @@ Papildoma išsami informacija:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Komandos eilutÄ—</translation>
<translation id="7359588939039777303">Skelbimai užblokuoti.</translation>
+<translation id="7363096869660964304">TaÄiau nesate nematomi. Ä®jungus inkognito režimÄ…, narÅ¡ymo veiksmai vis tiek matomi darbdaviui, interneto paslaugų teikÄ—jui ar svetainÄ—ms, kuriose lankotÄ—s.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />; paspauskite tabuliavimo klavišą, tada „Enter“, jei norite pridėti ir tvarkyti adresus „Chrome“ nustatymuose</translation>
<translation id="7365849542400970216">Leisti žinoti, kada naudojamas įrenginys?</translation>
<translation id="7372973238305370288">paieškos rezultatas</translation>
@@ -1675,7 +1722,9 @@ Papildoma išsami informacija:
<translation id="7378594059915113390">Medijos valdikliai</translation>
<translation id="7378627244592794276">Ne</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Netaikoma</translation>
<translation id="7390545607259442187">KortelÄ—s patvirtinimas</translation>
+<translation id="7392089738299859607">Adreso atnaujinimas</translation>
<translation id="7399802613464275309">Saugos patikra</translation>
<translation id="7400418766976504921">URL adresas</translation>
<translation id="7403591733719184120">Jūsų „<ph name="DEVICE_NAME" />“ tvarkomas</translation>
@@ -1690,6 +1739,7 @@ Papildoma išsami informacija:
&lt;li&gt;Apsilankykite &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;„Chrome“ pagalbos centre&lt;/a&gt;, kad sužinotumėte, kaip visam laikui pašalinti programinę įrangą iš kompiuterio.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Puiku</translation>
<translation id="7416351320495623771">Tvarkyti slaptažodžius…</translation>
<translation id="7419106976560586862">Profilio kelias</translation>
<translation id="7437289804838430631">PridÄ—ti kontaktinÄ™ informacijÄ…</translation>
@@ -1705,7 +1755,7 @@ Papildoma išsami informacija:
<translation id="7481312909269577407">Persiųsti</translation>
<translation id="7485870689360869515">Nerasta jokių duomenų.</translation>
<translation id="7495528107193238112">Šis turinys užblokuotas. Susisiekite su svetainės savininku, kad išspręstų problemą.</translation>
-<translation id="7498234416455752244">Toliau redaguoti</translation>
+<translation id="7498193950643227031">Pakeitus dydį ji gali veikti netinkamai. Dabar galite apriboti galimybę keisti programų dydį skiltyje „<ph name="SETTINGS" />“.</translation>
<translation id="7503664977220660814">Ką tik savo slaptažodį įvedėte apgaulingoje svetainėje. „Chromium“ rekomenduoja patikrinti išsaugotus <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ir kitų svetainių, kuriose dabar naudojate šį slaptažodį, slaptažodžius.</translation>
<translation id="7508255263130623398">Sugrąžinto politikos įrenginio ID nenurodytas arba neatitinka dabartinio įrenginio ID</translation>
<translation id="7508870219247277067">Avokado žalia</translation>
@@ -1725,6 +1775,7 @@ Papildoma išsami informacija:
<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="755279583747225797">Bandomoji versija aktyvi</translation>
<translation id="7552846755917812628">IÅ¡bandykite toliau pateiktus patarimus.</translation>
<translation id="7554475479213504905">Įkelti iš naujo ir vis tiek rodyti</translation>
<translation id="7554791636758816595">Naujas skirtukas</translation>
@@ -1743,7 +1794,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, paspauskite tabuliavimo klavišą, tada – „Enter“, kad galėtumėte peržiūrėti ir valdyti slaptažodžius „Chrome“ nustatymuose</translation>
-<translation id="7615602087246926389">Jau turite duomenų, kurie šifruojami naudojant kitos versijos „Google“ paskyros slaptažodį. Įveskite juos toliau.</translation>
<translation id="7616645509853975347">Administratorius įjungė „Chrome Enterprise Connectors“ jūsų naršyklėje. Naudojant šias jungtis galima pasiekti kai kuriuos jūsų duomenis.</translation>
<translation id="7619838219691048931">Galinis lapas</translation>
<translation id="762844065391966283">Po vienÄ…</translation>
@@ -1808,13 +1858,12 @@ Papildoma išsami informacija:
<translation id="782886543891417279">Naudojant šį „Wi-Fi“ tinklą („<ph name="WIFI_NAME" />“) gali būti prašoma apsilankyti prisijungimo puslapyje.</translation>
<translation id="7836231406687464395">„Postfix“ (vokas)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Nėra}=1{1 programa („<ph name="EXAMPLE_APP_1" />“)}=2{2 programos („<ph name="EXAMPLE_APP_1" />“, „<ph name="EXAMPLE_APP_2" />“)}one{# programa („<ph name="EXAMPLE_APP_1" />“, „<ph name="EXAMPLE_APP_2" />“ <ph name="AND_MORE" />)}few{# programos („<ph name="EXAMPLE_APP_1" />“, „<ph name="EXAMPLE_APP_2" />“ <ph name="AND_MORE" />)}many{# programos („<ph name="EXAMPLE_APP_1" />“, „<ph name="EXAMPLE_APP_2" />“ <ph name="AND_MORE" />)}other{# programų („<ph name="EXAMPLE_APP_1" />“, „<ph name="EXAMPLE_APP_2" />“ <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">TaÄiau nesate nematomi. Ä®jungus inkognito režimÄ…, narÅ¡ymo veiksmai vis tiek matomi darbdaviui, interneto paslaugų teikÄ—jui ar svetainÄ—ms, kuriose lankotÄ—s.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Atidaryti failus su failo tipo susiejimais.</translation>
<translation id="7862185352068345852">Išeiti iš svetainės?</translation>
<translation id="7865448901209910068">Geriausias greitis</translation>
<translation id="7874263914261512992">Ką tik savo slaptažodį įvedėte apgaulingoje svetainėje. „Chrome“ rekomenduoja patikrinti išsaugotus <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ir kitų svetainių, kuriose dabar naudojate šį slaptažodį, slaptažodžius.</translation>
<translation id="7878562273885520351">Jūsų slaptažodis gali būti pažeistas</translation>
+<translation id="7880146494886811634">Adreso išsaugojimas</translation>
<translation id="7882421473871500483">Ruda</translation>
<translation id="7887683347370398519">Patikrinkite kortelÄ—s saugos kodÄ… (CVC) ir bandykite dar kartÄ…</translation>
<translation id="7887885240995164102">Įeiti į vaizdo vaizde režimą</translation>
@@ -1822,6 +1871,7 @@ Papildoma išsami informacija:
<translation id="7894280532028510793">Jei parašyta tinkamai, <ph name="BEGIN_LINK" />pabandykite paleisti tinklo diagnostiką<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (vokas)</translation>
<translation id="7931318309563332511">Nežinoma</translation>
+<translation id="793209273132572360">Atnaujinti adresÄ…?</translation>
<translation id="7932579305932748336">Danga</translation>
<translation id="79338296614623784">Įveskite tinkamą telefono numerį</translation>
<translation id="7934052535022478634">MokÄ—jimas atliktas</translation>
@@ -1892,6 +1942,7 @@ Papildoma išsami informacija:
<translation id="8175796834047840627">„Chrome“ siūlo išsaugoti korteles „Google“ paskyroje, nes esate prisijungę. Šią elgseną galite pakeisti nustatymuose.</translation>
<translation id="8176440868214972690">Šio įrenginio administratorius nusiuntė tam tikros informacijos, pvz., informacijos apie nustatymus ar politikos nuostatas, toliau nurodytoms svetainėms.</translation>
<translation id="8184538546369750125">Naudoti visuotinį numatytąjį nustatymą (leisti)</translation>
+<translation id="8193086767630290324">Veiksmai, atlikti su duomenimis, kurie pažymėti kaip konfidencialūs</translation>
<translation id="8194797478851900357">&amp;Anuliuoti perkÄ—limÄ…</translation>
<translation id="8201077131113104583">Netinkamas plėtinio, kurio ID „<ph name="EXTENSION_ID" />“, atnaujinimo URL.</translation>
<translation id="8202097416529803614">Užsakymo suvestinė</translation>
@@ -1914,6 +1965,7 @@ Papildoma išsami informacija:
<translation id="8249296373107784235">Nutraukti</translation>
<translation id="8249320324621329438">Paskutinį kartą gauta:</translation>
<translation id="8253091569723639551">BÅ«tina pateikti atsiskaitymo adresÄ…</translation>
+<translation id="8257387598443225809">Ši programa sukurta mobiliesiems įrenginiams</translation>
<translation id="825929999321470778">Rodyti visus išsaugotus slaptažodžius</translation>
<translation id="8261506727792406068">IÅ¡trinti</translation>
<translation id="8262952874573525464">KraÅ¡tų sukabinimas apaÄioje</translation>
@@ -2038,7 +2090,6 @@ Papildoma išsami informacija:
<translation id="8719528812645237045">Kelios skylės viršuje</translation>
<translation id="8725066075913043281">Bandyti dar kartÄ…</translation>
<translation id="8726549941689275341">Puslapio dydis:</translation>
-<translation id="8728672262656704056">Veikia inkognito režimas</translation>
<translation id="8730621377337864115">Atlikta</translation>
<translation id="8731544501227493793">Mygtukas „Tvarkyti slaptažodžius“, paspauskite „Enter“, jei norite peržiūrėti ir tvarkyti slaptažodžius „Chrome“ nustatymuose</translation>
<translation id="8734529307927223492">Jūsų „<ph name="DEVICE_TYPE" />“ tvarko <ph name="MANAGER" /></translation>
@@ -2115,6 +2166,7 @@ Papildoma išsami informacija:
<translation id="9020542370529661692">Šis puslapis išverstas į <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(netinkamas)</translation>
+<translation id="9030265603405983977">Vienspalvis</translation>
<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>
@@ -2138,6 +2190,7 @@ Papildoma išsami informacija:
<translation id="91108059142052966">Pagal administratoriaus politiką ekrano bendrinimas su „<ph name="APPLICATION_TITLE" />“ išjungiamas, kai matomas konfidencialus turinys</translation>
<translation id="9114524666733003316">KortelÄ— patvirtinama...</translation>
<translation id="9114581008513152754">Š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="9117930699067497412">Šviežia</translation>
<translation id="9119042192571987207">Įkelta</translation>
<translation id="9128016270925453879">Politika įkelta</translation>
<translation id="9128870381267983090">Prisijungti prie tinklo</translation>
@@ -2156,6 +2209,7 @@ Papildoma išsami informacija:
<translation id="9170848237812810038">&amp;Atšaukti</translation>
<translation id="9171296965991013597">Išeiti iš programos?</translation>
<translation id="9173282814238175921">Vienas dokumentas / naujas lapas</translation>
+<translation id="9173995187295789444">Nuskaitoma ieškant „Bluetooth“ įrenginių...</translation>
<translation id="917450738466192189">Serverio sertifikatas negalioja.</translation>
<translation id="9174917557437862841">Skirtuko perjungimo mygtukas; paspauskite „Enter“, kad perjungtumėte į šį skirtuką</translation>
<translation id="9179703756951298733">Tvarkykite mokėjimų ir kredito kortelės informaciją „Chrome“ nustatymuose</translation>
diff --git a/chromium/components/strings/components_strings_lv.xtb b/chromium/components/strings/components_strings_lv.xtb
index b9d26306fc5..eb5966d3bb0 100644
--- a/chromium/components/strings/components_strings_lv.xtb
+++ b/chromium/components/strings/components_strings_lv.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Atlasiet atļauju: <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Atsaukt pÄrkÄrtoÅ¡anu</translation>
+<translation id="1123753900084781868">Subtitri reÄllaikÄ paÅ¡laik nav pieejami.</translation>
<translation id="1125573121925420732">TÄ«mekļa vietņu droÅ¡Ä«bas atjauninÄjumu laikÄ bieži var tikt rÄdÄ«ti brÄ«dinÄjumi. DrÄ«zumÄ tas tiks labots.</translation>
<translation id="112840717907525620">Politikas keÅ¡atmiņa ir labÄ stÄvoklÄ«.</translation>
<translation id="1130564665089811311">Poga “Tulkot lapuâ€. Lai pÄrtulkotu Å¡o lapu, izmantojot Google tulkotÄju, nospiediet ievadÄ«Å¡anas taustiņu.</translation>
@@ -74,6 +75,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="1240347957665416060">Jūsu ierīces nosaukums</translation>
<translation id="124116460088058876">Citas valodas…</translation>
<translation id="1243027604378859286">Autors:</translation>
+<translation id="1246424317317450637">Treknraksts</translation>
<translation id="1250759482327835220">Lai nÄkamreiz veiktu maksÄjumu ÄtrÄk, saglabÄjiet kartes datus, vÄrdu un norÄ“Ä·inu adresi savÄ Google kontÄ.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (veikta sinhronizÄcija)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ja, mÄ“Ä£inot apmeklÄ“t vietni, tÄ netiek atvÄ“rta, vispirms izmÄ“Ä£iniet tÄlÄk norÄdÄ«tÄs problÄ“mu novÄ“rÅ¡anas darbÄ«bas.&lt;/p&gt;
@@ -156,6 +158,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="1476595624592550506">Paroles maiņa</translation>
<translation id="1484290072879560759">Izvēlēties nosūtīšanas adresi</translation>
<translation id="1492194039220927094">Politiku informatīvie ziņojumi:</translation>
+<translation id="1495677929897281669">Atgriezties cilnē</translation>
<translation id="1501859676467574491">RÄdÄ« kartes no mana Google konta</translation>
<translation id="1507202001669085618">&lt;p&gt;Å is kļūdas ziņojums tiek rÄdÄ«ts, ja izmantojat Wi-Fi portÄlu, kurÄ ir jÄpierakstÄs, lai varÄ“tu pÄriet tieÅ¡saistÄ“.&lt;/p&gt;
&lt;p&gt;Lai novÄ“rstu Å¡o kļūdu, lapÄ, kuru mÄ“Ä£inÄt atvÄ“rt, noklikÅ¡Ä·iniet uz &lt;strong&gt;Izveidot savienojumu&lt;/strong&gt;.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="1532118530259321453">Å ajÄ lapÄ ir rakstÄ«ts</translation>
<translation id="153384715582417236">PagaidÄm tas arÄ« viss!</translation>
<translation id="1536390784834419204">Tulkot lapu</translation>
+<translation id="1539840569003678498">PÄrskata nosÅ«tÄ«Å¡anas laiks:</translation>
<translation id="154408704832528245">IzvÄ“lÄ“ties piegÄdes adresi</translation>
<translation id="1549470594296187301">Lai izmantotu Å¡o funkciju, ir jÄbÅ«t iespÄ“jotai valodai JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="1682696192498422849">Vispirms Ä«sÄkÄ mala</translation>
<translation id="168693727862418163">Å o politikas vÄ“rtÄ«bu neizdevÄs apstiprinÄt, izmantojot tÄs shÄ“mu, un tÄ tiks ignorÄ“ta.</translation>
<translation id="168841957122794586">Servera sertifikÄts ietver vÄju kriptogrÄfisko atslÄ“gu.</translation>
+<translation id="1696290444144917273">SkatÄ«t virtuÄlÄs kartÄ«tes informÄciju</translation>
<translation id="1697532407822776718">Gatavs!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Å is serveris nevarÄ“ja pierÄdÄ«t, ka ir <ph name="DOMAIN" />; Å¡Ä·iet, ka tÄ droÅ¡Ä«bas sertifikÄts sÄks darboties rÄ«t. Å Ä« problÄ“ma var rasties nepareizas konfigurÄcijas dēļ vai tÄdēļ, ka kÄds uzbrucÄ“js ir pÄrtvÄ“ris jÅ«su savienojumu.}zero{Å is serveris nevarÄ“ja pierÄdÄ«t, ka ir <ph name="DOMAIN" />; Å¡Ä·iet, ka tÄ droÅ¡Ä«bas sertifikÄts sÄks darboties pÄ“c # dienÄm. Å Ä« problÄ“ma var rasties nepareizas konfigurÄcijas dēļ vai tÄdēļ, ka kÄds uzbrucÄ“js ir pÄrtvÄ“ris jÅ«su savienojumu.}one{Å is serveris nevarÄ“ja pierÄdÄ«t, ka ir <ph name="DOMAIN" />; Å¡Ä·iet, ka tÄ droÅ¡Ä«bas sertifikÄts sÄks darboties pÄ“c # dienas. Å Ä« problÄ“ma var rasties nepareizas konfigurÄcijas dēļ vai tÄdēļ, ka kÄds uzbrucÄ“js ir pÄrtvÄ“ris jÅ«su savienojumu.}other{Å is serveris nevarÄ“ja pierÄdÄ«t, ka ir <ph name="DOMAIN" />; Å¡Ä·iet, ka tÄ droÅ¡Ä«bas sertifikÄts sÄks darboties pÄ“c # dienÄm. Å Ä« problÄ“ma var rasties nepareizas konfigurÄcijas dēļ vai tÄdēļ, ka kÄds uzbrucÄ“js ir pÄrtvÄ“ris jÅ«su savienojumu.}}</translation>
<translation id="1710259589646384581">OperÄ“tÄjsistÄ“ma</translation>
+<translation id="1711234383449478798">IgnorÄ“ta, jo politikai “<ph name="POLICY_NAME" />†nav iestatÄ«ta vÄ“rtÄ«ba “<ph name="VALUE" />â€.</translation>
<translation id="1712552549805331520">VietnÄ“ <ph name="URL" /> tika pieprasÄ«ta atļauja pastÄvÄ«gi glabÄt datus lokÄlajÄ datorÄ.</translation>
<translation id="1713628304598226412">2. paplÄte</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">3. pastkaste</translation>
<translation id="1718029547804390981">Dokuments ir pÄrÄk liels, tÄdēļ tam nevar pievienot piezÄ«mes</translation>
<translation id="1721424275792716183">* ObligÄts lauks</translation>
+<translation id="1727613060316725209">SertifikÄts ir derÄ«gs</translation>
<translation id="1727741090716970331">Derīga kartes numura pievienošana</translation>
<translation id="1728677426644403582">JÅ«s skatÄt tÄ«mekļa lapas avotu.</translation>
<translation id="173080396488393970">Šis kartes veids netiek atbalstīts</translation>
@@ -246,7 +253,6 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
jūsu pieprasījumu vietnei <ph name="SITE" />. Vietņu operatori var izmantot
izcelsmes politikas, lai konfigurētu drošību un citus vietnes rekvizītus.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Atjauniniet savu sinhronizÄcijas ieejas frÄzi.</translation>
<translation id="1787142507584202372">Å eit tiks parÄdÄ«tas jÅ«su atvÄ“rtÄs cilnes</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ir pieejamas vairÄkas darbÄ«bas. Lai pÄ“c kÄrtas pÄrietu starp Å¡Ä«m darbÄ«bÄm, nospiediet tabulÄ“Å¡anas taustiņu.</translation>
@@ -279,6 +285,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="1919345977826869612">ReklÄmas</translation>
<translation id="1919367280705858090">Palīdzība par konkrētu kļūdas ziņojumu</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Nav}=1{1 vietne}zero{# vietnes}one{# vietne}other{# vietnes}}</translation>
+<translation id="1924727005275031552">JaunÄ</translation>
<translation id="1945968466830820669">Varat zaudÄ“t piekļuvi savam organizÄcijas kontam, vai jÅ«su identitÄte var tikt nozagta. Chromium iesaka nekavÄ“joties nomainÄ«t paroli.</translation>
<translation id="1947454675006758438">Skavojums augÅ¡Ä“jÄ labajÄ malÄ</translation>
<translation id="1958218078413065209">JÅ«su vislabÄkais rezultÄts ir <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="2042213636306070719">7. paplÄte</translation>
<translation id="204357726431741734">Pierakstieties, lai izmantotu savÄ Google kontÄ saglabÄtÄs paroles.</translation>
<translation id="2053111141626950936">Lapas netiks tulkotas no Å¡Ä«s valodas: <ph name="LANGUAGE" /></translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Ja Å¡Ä« vadÄ«kla ir ieslÄ“gta un statuss ir aktÄ«vs, pÄrlÅ«kÄ Chrome tiek noteikts, kurai lielai lietotÄju grupai jeb kohortai jÅ«su nesenÄs pÄrlÅ«koÅ¡anas darbÄ«bas lÄ«dzinÄs visvairÄk. ReklÄmdevÄ“ji var atlasÄ«t grupai atbilstoÅ¡as reklÄmas, bet jÅ«su pÄrlÅ«koÅ¡anas darbÄ«bas tiek privÄti glabÄtas jÅ«su ierÄ«cÄ“. JÅ«su grupas dati tiek atjauninÄti katru dienu.}=1{Ja Å¡Ä« vadÄ«kla ir ieslÄ“gta un statuss ir aktÄ«vs, pÄrlÅ«kÄ Chrome tiek noteikts, kurai lielai lietotÄju grupai jeb kohortai jÅ«su nesenÄs pÄrlÅ«koÅ¡anas darbÄ«bas lÄ«dzinÄs visvairÄk. ReklÄmdevÄ“ji var atlasÄ«t grupai atbilstoÅ¡as reklÄmas, bet jÅ«su pÄrlÅ«koÅ¡anas darbÄ«bas tiek privÄti glabÄtas jÅ«su ierÄ«cÄ“. JÅ«su grupas dati tiek atjauninÄti katru dienu.}zero{Ja Å¡Ä« vadÄ«kla ir ieslÄ“gta un statuss ir aktÄ«vs, pÄrlÅ«kÄ Chrome tiek noteikts, kurai lielai lietotÄju grupai jeb kohortai jÅ«su nesenÄs pÄrlÅ«koÅ¡anas darbÄ«bas lÄ«dzinÄs visvairÄk. ReklÄmdevÄ“ji var atlasÄ«t grupai atbilstoÅ¡as reklÄmas, bet jÅ«su pÄrlÅ«koÅ¡anas darbÄ«bas tiek privÄti glabÄtas jÅ«su ierÄ«cÄ“. JÅ«su grupas dati tiek atjauninÄti ik pÄ“c {NUM_DAYS} dienÄm.}one{Ja Å¡Ä« vadÄ«kla ir ieslÄ“gta un statuss ir aktÄ«vs, pÄrlÅ«kÄ Chrome tiek noteikts, kurai lielai lietotÄju grupai jeb kohortai jÅ«su nesenÄs pÄrlÅ«koÅ¡anas darbÄ«bas lÄ«dzinÄs visvairÄk. ReklÄmdevÄ“ji var atlasÄ«t grupai atbilstoÅ¡as reklÄmas, bet jÅ«su pÄrlÅ«koÅ¡anas darbÄ«bas tiek privÄti glabÄtas jÅ«su ierÄ«cÄ“. JÅ«su grupas dati tiek atjauninÄti ik pÄ“c {NUM_DAYS} dienÄm.}other{Ja Å¡Ä« vadÄ«kla ir ieslÄ“gta un statuss ir aktÄ«vs, pÄrlÅ«kÄ Chrome tiek noteikts, kurai lielai lietotÄju grupai jeb kohortai jÅ«su nesenÄs pÄrlÅ«koÅ¡anas darbÄ«bas lÄ«dzinÄs visvairÄk. ReklÄmdevÄ“ji var atlasÄ«t grupai atbilstoÅ¡as reklÄmas, bet jÅ«su pÄrlÅ«koÅ¡anas darbÄ«bas tiek privÄti glabÄtas jÅ«su ierÄ«cÄ“. JÅ«su grupas dati tiek atjauninÄti ik pÄ“c {NUM_DAYS} dienÄm.}}</translation>
<translation id="2053553514270667976">Pasta indekss</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ieteikums}zero{# ieteikumi}one{# ieteikums}other{# ieteikumi}}</translation>
<translation id="2071692954027939183">Paziņojumi tika automÄtiski bloÄ·Ä“ti, jo jÅ«s tos parasti neatļaujat.</translation>
<translation id="2079545284768500474">Atsaukt</translation>
<translation id="20817612488360358">Ir iestatÄ«ta datora starpniekserveru iestatÄ«jumu lietoÅ¡ana, bet ir norÄdÄ«ta arÄ« atklÄta starpniekservera konfigurÄcija.</translation>
<translation id="2082238445998314030"><ph name="RESULT_NUMBER" />. rezultÄts no <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">SaglabÄt…</translation>
<translation id="2088086323192747268">Poga “PÄrvaldÄ«t sinhronizÄcijuâ€: nospiediet ievadÄ«Å¡anas taustiņu, lai Chrome iestatÄ«jumos pÄrvaldÄ«tu, kÄda informÄcija tiek sinhronizÄ“ta.</translation>
<translation id="2091887806945687916">SignÄls</translation>
<translation id="2094505752054353250">Domēni nesaskan</translation>
@@ -379,6 +388,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="2317259163369394535">VietnÄ“ <ph name="DOMAIN" /> ir jÄievada lietotÄjvÄrds un parole.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, derīguma termiņš: <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Iestatījumu kontrolē jūsu administrators</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> vÄ“las savienot pÄrÄ«</translation>
<translation id="2344028582131185878">AutomÄtiskÄs lejupielÄdes</translation>
<translation id="2346319942568447007">Kopētais attēls</translation>
<translation id="2354001756790975382">Citas grÄmatzÄ«mes</translation>
@@ -386,8 +396,10 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="2355395290879513365">UzbrucÄ“ji var skatÄ«t attÄ“lus, kurus skatÄt Å¡ajÄ vietnÄ“, un apmÄnÄ«t jÅ«s, pÄrveidojot Å¡os attÄ“lus.</translation>
<translation id="2356070529366658676">VaicÄt</translation>
<translation id="2357481397660644965">JÅ«su ierÄ«ci pÄrvalda <ph name="DEVICE_MANAGER" />, un jÅ«su kontu pÄrvalda <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{PÄ“c nepilnas dienas}=1{PÄ“c vienas dienas}zero{PÄ“c {NUM_DAYS} dienÄm}one{PÄ“c {NUM_DAYS} dienas}other{PÄ“c {NUM_DAYS} dienÄm}}</translation>
<translation id="2359629602545592467">VairÄkas</translation>
<translation id="2359808026110333948">TurpinÄt</translation>
+<translation id="2359961752320758691">Tika lietots jÅ«su virtuÄlÄs kartes numurs.</translation>
<translation id="2367567093518048410">LÄ«menis</translation>
<translation id="2372464001869762664">PÄ“c apstiprinÄÅ¡anas kartes informÄcija no Google konta tiks kopÄ«gota ar Å¡o vietni. Atrodiet CVC kodu sava Plex konta informÄcijÄ.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="239429038616798445">Šis nosūtīšanas veids nav pieejams. Izmēģiniet citu veidu.</translation>
<translation id="2396249848217231973">&amp;Atsaukt dzēšanu</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">VecÄ</translation>
<translation id="2413528052993050574">Å is serveris nevarÄ“ja pierÄdÄ«t, ka Å¡Ä« ir vietne <ph name="DOMAIN" />; tÄs droÅ¡Ä«bas sertifikÄts, iespÄ“jams, ir atsaukts. IespÄ“jams, tas ir nepareizas konfigurÄcijas dēļ vai arÄ« kÄds ir ļaunprÄtÄ«gi izmantojis jÅ«su savienojumu.</translation>
<translation id="2414886740292270097">Tumšs</translation>
<translation id="2438874542388153331">ÄŒetri caurumi labajÄ pusÄ“</translation>
@@ -425,10 +438,10 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="2521385132275182522">Skavojums apakÅ¡Ä“jÄ labajÄ malÄ</translation>
<translation id="2523886232349826891">Tiks saglabÄta tikai Å¡ajÄ ierÄ«cÄ“</translation>
<translation id="2524461107774643265">Papildu informÄcijas pievienoÅ¡ana</translation>
-<translation id="2526590354069164005">Darbvirsma</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{un vēl 1}zero{un vēl #}one{un vēl #}other{un vēl #}}</translation>
<translation id="2536110899380797252">Pievienot adresi</translation>
<translation id="2539524384386349900">Noteikt</translation>
+<translation id="2541219929084442027">Lapas, ko skatÄt inkognito cilnÄ“s, nebÅ«s redzamas pÄrlÅ«ka vÄ“sturÄ“, sÄ«kfailu krÄtuvÄ“ vai meklÄ“Å¡anas vÄ“sturÄ“, kad aizvÄ“rsiet visas inkognito cilnes. TomÄ“r tiks saglabÄti visi lejupielÄdÄ“tie faili un izveidotÄs grÄmatzÄ«mes.</translation>
<translation id="2544644783021658368">Viens dokuments</translation>
<translation id="254947805923345898">Politikas vērtība nav derīga.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> nosūtīja nederīgu atbildi.</translation>
@@ -448,6 +461,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="2629325967560697240">Lai pÄrlÅ«kprogrammÄ Chrome izmantotu visaugstÄko droÅ¡Ä«bas lÄ«meni, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ieslÄ“dziet uzlaboto aizsardzÄ«bu<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Nevarēja atrast vietnes <ph name="HOST_NAME" /> servera IP adresi.</translation>
<translation id="2639739919103226564">Statuss:</translation>
+<translation id="264810637653812429">Netika atrasta neviena saderīga ierīce.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. Lai notÄ«rÄ«tu jÅ«su pÄrlÅ«koÅ¡anas vÄ“sturi, sÄ«kfailus, keÅ¡atmiņu un citus datus Chrome iestatÄ«jumos, nospiediet tabulÄ“Å¡anas taustiņu un pÄ“c tam — ievadÄ«Å¡anas taustiņu.</translation>
<translation id="2650446666397867134">Piekļuve failam tika noraidīta.</translation>
@@ -492,6 +506,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<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="2807052079800581569">Attēla pozīcija uz Y ass</translation>
+<translation id="2820957248982571256">Notiek meklēšana...</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>
@@ -499,6 +514,8 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="2850739647070081192">Invite (aploksne)</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="2859806420264540918">Å ajÄ vietnÄ“ tiek rÄdÄ«tas traucÄ“joÅ¡as vai maldinoÅ¡as reklÄmas.</translation>
+<translation id="287596039013813457">Draudzīga</translation>
+<translation id="2876489322757410363">Ja maksÄÅ¡anai tiks izmantota ÄrÄ“ja lietojumprogramma, tiks aizvÄ“rts inkognito režīms. Vai turpinÄt?</translation>
<translation id="2878197950673342043">PlakÄta locÄ«jums</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Logu izvietošana</translation>
@@ -548,7 +565,6 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="3060227939791841287">C9 (aploksne)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />: lai Chrome iestatÄ«jumos veiktu droÅ¡Ä«bas pÄrbaudi, nospiediet tabulÄ“Å¡anas taustiņu un pÄ“c tam — ievadÄ«Å¡anas taustiņu.</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>
<translation id="306573536155379004">SpÄ“le sÄkta.</translation>
<translation id="3080254622891793721">Grafika</translation>
<translation id="3086579638707268289">Jūsu darbības tīmeklī tiek uzraudzītas</translation>
@@ -571,7 +587,6 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="315504272643575312">JÅ«su kontu pÄrvalda <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Atjaunot</translation>
<translation id="3162559335345991374">IespÄ“jams, izmantotajÄ Wi-Fi tÄ«klÄ tiks pieprasÄ«ts apmeklÄ“t pieteikÅ¡anÄs lapu.</translation>
-<translation id="3167968892399408617">Lapas, ko skatÄt inkognito režīma cilnÄ“s, nebÅ«s redzamas pÄrlÅ«ka vÄ“sturÄ“, sÄ«kfailu krÄtuvÄ“ vai meklÄ“Å¡anas vÄ“sturÄ“, kad aizvÄ“rsiet visas inkognito režīma cilnes. TomÄ“r tiks saglabÄti visi lejupielÄdÄ“tie faili un izveidotÄs grÄmatzÄ«mes.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Sala</translation>
<translation id="3176929007561373547">PÄrbaudiet starpniekservera iestatÄ«jumus vai sazinieties ar tÄ«kla administratoru, lai
@@ -597,10 +612,12 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<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="3249845759089040423">Moderna</translation>
<translation id="3252266817569339921">FranÄu valoda</translation>
<translation id="3266793032086590337">Vērtība (konfliktē)</translation>
<translation id="3268451620468152448">AtvÄ“rtÄs cilnes</translation>
<translation id="3270847123878663523">&amp;PÄrkÄrtoÅ¡anas atsaukÅ¡ana</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> vēlas izveidot savienojumu</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">JÅ«su organizÄcija (<ph name="ENROLLMENT_DOMAIN" />) ir nosÅ«tÄ«jusi informÄciju, piemÄ“ram, iestatÄ«jumus vai politikas, uz tÄlÄk norÄdÄ«tajÄm vietnÄ“m.</translation>
<translation id="3282497668470633863">Pievienot vÄrdu un uzvÄrdu uz kartes</translation>
@@ -653,6 +670,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="3428151540071562330">Viens vai vairÄki DnsOverHttpsTemplates servera veidņu identifikatori URI nav derÄ«gi un netiks izmantoti.</translation>
<translation id="3431636764301398940">SaglabÄt Å¡o karti Å¡ajÄ ierÄ«cÄ“</translation>
<translation id="3432601291244612633">Aizvērt lapu</translation>
+<translation id="3435738964857648380">Drošība</translation>
<translation id="3435896845095436175">Iespējot</translation>
<translation id="3438829137925142401">JÅ«su Google kontÄ glabÄto paroļu izmantoÅ¡ana</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -695,7 +713,10 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="3584299510153766161">Divi caurumi apakÅ¡daļÄ</translation>
<translation id="3586931643579894722">Slēpt detaļas</translation>
<translation id="3587738293690942763">vidējais</translation>
+<translation id="3590643883886679995">PÄ“c tam, kad iziesiet no inkognito režīma, pierakstÄ«Å¡anÄs dati tiks glabÄti Å¡ajÄ ierÄ«cÄ“.</translation>
+<translation id="359126217934908072">MÄ“nesis/gads:</translation>
<translation id="3592413004129370115">Italian (aploksne)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{JebkurÄ laikÄ varat atiestatÄ«t grupu. PievienoÅ¡anÄs jaunai grupai var ilgt aptuveni dienu.}=1{JebkurÄ laikÄ varat atiestatÄ«t grupu. PievienoÅ¡anÄs jaunai grupai var ilgt aptuveni dienu.}zero{JebkurÄ laikÄ varat atiestatÄ«t grupu. PievienoÅ¡anÄs jaunai grupai var ilgt {NUM_DAYS} dienas.}one{JebkurÄ laikÄ varat atiestatÄ«t grupu. PievienoÅ¡anÄs jaunai grupai var ilgt {NUM_DAYS} dienu.}other{JebkurÄ laikÄ varat atiestatÄ«t grupu. PievienoÅ¡anÄs jaunai grupai var ilgt {NUM_DAYS} dienas.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Lietojumprogrammu bloķēja jūsu administrators</translation>
<translation id="3608932978122581043">Padeves virziens</translation>
@@ -704,12 +725,12 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="3615877443314183785">Ievadiet derīgu datumu</translation>
<translation id="36224234498066874">DzÄ“st pÄrlÅ«koÅ¡anas datus...</translation>
<translation id="362276910939193118">RÄdÄ«t pilnu vÄ“sturi</translation>
-<translation id="3625635938337243871">PÄ“c tam, kad iziesiet no inkognito režīma, pierakstÄ«Å¡anÄs dati tiks glabÄti Å¡ajÄ ierÄ«cÄ“.</translation>
<translation id="3630155396527302611">Ja tÄ jau ir norÄdÄ«ta kÄ programma, kurai ir atļauts piekļūt tÄ«klam, noņemiet to no saraksta un pievienojiet vÄ“lreiz.</translation>
<translation id="3630699740441428070">Å Ä«s ierÄ«ces administratori ir konfigurÄ“juÅ¡i jÅ«su tÄ«kla savienojumu, tÄpÄ“c viņi, iespÄ“jams, var skatÄ«t jÅ«su tÄ«kla datplÅ«smu, tostarp apmeklÄ“tÄs vietnes.</translation>
<translation id="3631244953324577188">Biometrija</translation>
<translation id="3633738897356909127">Poga “AtjauninÄt Chromeâ€. Lai Chrome iestatÄ«jumos atjauninÄtu pÄrlÅ«kprogrammu Chrome, nospiediet ievadÄ«Å¡anas taustiņu.</translation>
<translation id="3634530185120165534">5. paplÄte</translation>
+<translation id="3637662659967048211">SaglabÄÅ¡ana Google kontÄ</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Lietojumprogramma:</translation>
<translation id="3650584904733503804">ValidÄcija bija veiksmÄ«ga.</translation>
@@ -750,6 +771,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="3781428340399460090">Spilgti rozÄ</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth ierīces</translation>
+<translation id="3787675388804467730">VirtuÄlÄs kartes numurs</translation>
<translation id="3787705759683870569">Derīguma termiņš: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">16. izmērs</translation>
<translation id="3789841737615482174">Instalēt</translation>
@@ -769,6 +791,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="3841184659773414994">Failu apdarinÄtÄji</translation>
<translation id="385051799172605136">Atpakaļ</translation>
<translation id="3858027520442213535">AtjauninÄt datumu un laiku</translation>
+<translation id="3881478300875776315">RÄdÄ«t mazÄk rindu</translation>
<translation id="3884278016824448484">Ierīces identifikators rada konfliktu.</translation>
<translation id="3885155851504623709">Pagasts</translation>
<translation id="388632593194507180">KonstatÄ“ta pÄrraudzÄ«ba</translation>
@@ -794,6 +817,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="397105322502079400">Aprēķina...</translation>
<translation id="3973234410852337861">Vietne <ph name="HOST_NAME" /> ir bloÄ·Ä“ta</translation>
<translation id="3973357910713125165">Poga “Veikt Chrome droÅ¡Ä«bas pÄrbaudiâ€. Lai Chrome iestatÄ«jumos veiktu droÅ¡Ä«bas pÄrbaudi, nospiediet ievadÄ«Å¡anas taustiņu.</translation>
+<translation id="3986705137476756801">PagaidÄm izslÄ“gt subtitrus reÄllaikÄ</translation>
<translation id="3987405730340719549">PÄrlÅ«ks Chrome ir konstatÄ“jis, ka Å¡Ä« vietne varÄ“tu bÅ«t viltota vai krÄpnieciska.
Ja uzskatÄt, ka tas tiek parÄdÄ«ts kļūdas dēļ, lÅ«dzu, apmeklÄ“jiet vietni https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -890,13 +914,14 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="4275830172053184480">Ierīces restartēšana</translation>
<translation id="4277028893293644418">Atiestatīt paroli</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="4287885627794386150">Varat piedalÄ«ties izmÄ“Ä£inÄjumÄ, taÄu tas nav aktÄ«vs</translation>
<translation id="4297502707443874121">Lappuses numur <ph name="THUMBNAIL_PAGE" /> sīktēls</translation>
<translation id="42981349822642051">Izvērst</translation>
<translation id="4300675098767811073">VairÄki caurumi labajÄ pusÄ“</translation>
<translation id="4302514097724775343">Lai spēlētu, pieskarieties dinozauram</translation>
<translation id="4302965934281694568">Chou3 (aploksne)</translation>
<translation id="4305666528087210886">Jūsu failam nevarēja piekļūt</translation>
-<translation id="4305817255990598646">PÄriet</translation>
+<translation id="4306529830550717874">Vai saglabÄt adresi?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloķēt (pēc noklusējuma)</translation>
<translation id="4314815835985389558">SinhronizÄcijas pÄrvaldÄ«ba</translation>
@@ -923,6 +948,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="4377125064752653719">JÅ«s mÄ“Ä£inÄjÄt sasniegt <ph name="DOMAIN" />, bet izdevÄ“js atsauca servera uzrÄdÄ«to sertifikÄtu. Tas nozÄ«mÄ“, ka servera uzrÄdÄ«tie droÅ¡Ä«bas akreditÄcijas dati itin nemaz nav uzticami. IespÄ“jams, jÅ«s sazinÄties ar uzbrucÄ“ju.</translation>
<translation id="4378154925671717803">TÄlrunis</translation>
<translation id="4390472908992056574">Apmale</translation>
+<translation id="4406883609789734330">Subtitri reÄllaikÄ</translation>
<translation id="4406896451731180161">meklÄ“Å¡anas rezultÄti</translation>
<translation id="4408413947728134509">SÄ«kfaili <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">JÅ«s tikko ievadÄ«jÄt savu paroli maldinoÅ¡Ä vietnÄ“. Chrome ieteikums: tÅ«lÄ«t apmeklÄ“jiet vietni <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> un <ph name="WEBSITE_3" />, kÄ arÄ« citas vietnes, kurÄs izmantojat Å¡o paroli, un nomainiet to.</translation>
@@ -935,7 +961,6 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<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="4464826014807964867">Vietnes ar informÄciju no jÅ«su organizÄcijas</translation>
-<translation id="4466881336512663640">Veidlapas izmaiņas tiks zaudÄ“tas. Vai tieÅ¡Äm vÄ“laties turpinÄt?</translation>
<translation id="4476953670630786061">Å Ä« veidlapa nav droÅ¡a. AutomÄtiskÄ aizpilde ir izslÄ“gta.</translation>
<translation id="4477350412780666475">NÄkamais ieraksts</translation>
<translation id="4482953324121162758">Å Ä« vietne netiks tulkota.</translation>
@@ -953,7 +978,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="4515275063822566619">Kartes un adreses tiek iegÅ«tas no Chrome un jÅ«su Google konta (<ph name="ACCOUNT_EMAIL" />). Varat tÄs pÄrvaldÄ«t <ph name="BEGIN_LINK" />iestatÄ«jumos<ph name="END_LINK" />.</translation>
<translation id="4517607026994743406">Comm-10 (aploksne)</translation>
<translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> mm (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">InformÄcija</translation>
+<translation id="4522570452068850558">Dati</translation>
<translation id="4524138615196389145">TurpmÄk, izmantojot WebAuthn, apstipriniet kartes ÄtrÄk</translation>
<translation id="4524805452350978254">PÄrvaldÄ«t kartÄ«tes</translation>
<translation id="4542971377163063093">6. paplÄte</translation>
@@ -969,6 +994,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<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="4606870351894164739">PamanÄma</translation>
<translation id="4628948037717959914">Fotoattēls</translation>
<translation id="4631649115723685955">Saistīta skaidras naudas atmaksa</translation>
<translation id="4636930964841734540">InformÄcija</translation>
@@ -988,6 +1014,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="4691835149146451662">Architecture-A (aploksne)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">sÄnu</translation>
+<translation id="4702656508969495934">Subtitri reÄllaikÄ ir redzami. Lai izceltu, izmantojiet logu pÄrslÄ“dzÄ“ju.</translation>
<translation id="4708268264240856090">Savienojums tika pÄrtraukts</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Palaist Windows tīkla diagnostiku<ph name="END_LINK" /></translation>
@@ -1001,6 +1028,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="4738601419177586157">MeklÄ“Å¡anas ieteikums vaicÄjumam “<ph name="TEXT" />â€</translation>
<translation id="4742407542027196863">PÄrvaldÄ«t paroles…</translation>
<translation id="4744603770635761495">IzpildÄms ceļš</translation>
+<translation id="4749011317274908093">Jūs esat atvēris inkognito režīmu</translation>
<translation id="4750917950439032686">JÅ«su informÄcija (piemÄ“ram, paroles vai kredÄ«tkarÅ¡u numuri) ir privÄta, kad tÄ tiek nosÅ«tÄ«ta uz Å¡o vietni.</translation>
<translation id="4756388243121344051">VÄ“sture</translation>
<translation id="4758311279753947758">Pievienot kontaktinformÄciju</translation>
@@ -1030,6 +1058,8 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="4813512666221746211">Tīkla kļūda</translation>
<translation id="4816492930507672669">IetilpinÄt lapÄ</translation>
<translation id="4819347708020428563">Vai vÄ“laties rediģēt piezÄ«mes noklusÄ“juma skatÄ?</translation>
+<translation id="4825507807291741242">Efektīva</translation>
+<translation id="4838327282952368871">Mierīga</translation>
<translation id="484462545196658690">Autom.</translation>
<translation id="4850886885716139402">Skatīt</translation>
<translation id="485316830061041779">VÄcu valoda</translation>
@@ -1166,6 +1196,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="5314967030527622926">Bukletu veidotÄjs</translation>
<translation id="5316812925700871227">Pagriezt pretÄ“ji pulksteņrÄdÄ«tÄju kustÄ«bas virzienam</translation>
<translation id="5317780077021120954">SaglabÄt</translation>
+<translation id="5321288445143113935">Maksimizēta</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" />. no <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">IzvÄ“lÄ“ties kontaktinformÄciju</translation>
<translation id="5327248766486351172">Nosaukums</translation>
@@ -1173,11 +1204,13 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="5332219387342487447">PiegÄdes veids</translation>
<translation id="5333022057423422993">PÄrlÅ«kÄ Chrome tika konstatÄ“ts, ka nupat izmantotÄ parole ir atklÄta datu pÄrkÄpuma dēļ. Lai aizsargÄtu kontus, ieteicams pÄrbaudÄ«t saglabÄtÄs paroles.</translation>
<translation id="5334013548165032829">SistÄ“mas žurnÄli ar detalizÄ“tu informÄciju</translation>
+<translation id="5334145288572353250">Vai saglabÄt adresi?</translation>
<translation id="5340250774223869109">Lietojumprogramma ir bloÄ·Ä“ta</translation>
<translation id="534295439873310000">NFC ierīces</translation>
<translation id="5344579389779391559">Å ajÄ lapÄ var tikt mÄ“Ä£inÄts pieprasÄ«t naudu</translation>
<translation id="5355557959165512791">PaÅ¡laik nevarat apmeklÄ“t vietni <ph name="SITE" />, jo tÄs sertifikÄts ir atsaukts. TÄ kÄ tÄ«kla kļūdas un uzbrukumi parasti ir Ä«slaicÄ«gi, visticamÄk, Å¡Ä« lapa vÄ“lÄk darbosies.</translation>
<translation id="536296301121032821">NeizdevÄs saglabÄt politikas iestatÄ«jumus.</translation>
+<translation id="5363309033720083897">SeriÄlais ports, ko atļÄva jÅ«su administrators.</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="5386426401304769735">Å Ä«s vietnes sertifikÄtu Ä·Ä“dÄ“ ir iekļauts sertifikÄts, kas ir parakstÄ«ts, izmantojot SHA-1.</translation>
@@ -1186,6 +1219,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="5398772614898833570">ReklÄmu rÄdÄ«Å¡ana bloÄ·Ä“ta</translation>
<translation id="5400836586163650660">Pelēka</translation>
<translation id="540969355065856584">Å is serveris nevarÄ“ja pierÄdÄ«t, ka Å¡Ä« ir vietne <ph name="DOMAIN" />; tÄ droÅ¡Ä«bas sertifikÄts Å¡obrÄ«d nav derÄ«gs. IespÄ“jams, tas ir nepareizas konfigurÄcijas dēļ vai arÄ« kÄds ļaunprÄtÄ«gi izmanto jÅ«su savienojumu.</translation>
+<translation id="541143247543991491">MÄkonis (visÄ sistÄ“mÄ)</translation>
<translation id="541416427766103491">4. izvades vieta</translation>
<translation id="5421136146218899937">NotÄ«rÄ«t pÄrlÅ«koÅ¡anas datus</translation>
<translation id="5426179911063097041">No vietnes <ph name="SITE" /> tiek mÄ“Ä£inÄts nosÅ«tÄ«t paziņojumus.</translation>
@@ -1199,6 +1233,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="5455374756549232013">Politikas laikspiedols nav derīgs.</translation>
<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="5463625433003343978">Notiek ierÄ«Äu meklÄ“Å¡ana…</translation>
<translation id="5469868506864199649">ItÄļu valoda</translation>
<translation id="5470861586879999274">&amp;Atcelt labojuma atsaukšanu</translation>
<translation id="5478437291406423475">B6/C4 (aploksne)</translation>
@@ -1248,7 +1283,6 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="5624120631404540903">PÄrvaldÄ«t paroles</translation>
<translation id="5629630648637658800">NeizdevÄs ielÄdÄ“t politikas iestatÄ«jumus.</translation>
<translation id="5631439013527180824">IerÄ«ces pÄrvaldÄ«bas marÄ·ieris nav derÄ«gs.</translation>
-<translation id="5632627355679805402">JÅ«su dati tika Å¡ifrÄ“ti, izmantojot jÅ«su <ph name="BEGIN_LINK" />Google paroli<ph name="END_LINK" />, no Å¡Äda datuma: <ph name="TIME" />. Ievadiet paroli, lai sÄktu sinhronizÄciju.</translation>
<translation id="5633066919399395251">UzbrucÄ“ji vietnÄ“ <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> var mÄ“Ä£inÄt jÅ«su datorÄ instalÄ“t bÄ«stamas programmas, kas zog vai izdzÄ“Å¡ informÄciju (piemÄ“ram, fotoattÄ“lus, paroles, ziņojumus un kredÄ«tkarÅ¡u datus). <ph name="BEGIN_LEARN_MORE_LINK" />Uzziniet vairÄk<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="563324245173044180">Bloķēts maldinošs saturs</translation>
<translation id="5644090287519800334">1. puses attēla nobīde uz X ass</translation>
@@ -1287,12 +1321,12 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="5785756445106461925">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 izskatu.</translation>
<translation id="5786044859038896871">Vai vÄ“laties aizpildÄ«t laukus ar kartes informÄciju?</translation>
<translation id="578633867165174378">PÄrlÅ«kÄ Chrome tika konstatÄ“ts, ka nupat izmantotÄ parole ir atklÄta datu pÄrkÄpuma dēļ. Ieteicams nekavÄ“joties nomainÄ«t Å¡o paroli.</translation>
-<translation id="5798290721819630480">Vai atmest izmaiņas?</translation>
<translation id="5803412860119678065">Vai vÄ“laties aizpildÄ«t lauku ar informÄciju “<ph name="CARD_DETAIL" />â€?</translation>
<translation id="5804241973901381774">Atļaujas</translation>
<translation id="5804427196348435412">izmantot NFC ierīces</translation>
<translation id="5810442152076338065">Savienojums ar domēnu <ph name="DOMAIN" /> ir šifrēts, izmantojot novecojušu šifra komplektu.</translation>
<translation id="5813119285467412249">&amp;Pievienošanas atsaukuma atcelšana</translation>
+<translation id="5817918615728894473">Savienot pÄrÄ«</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Kad veiksiet maksÄjumus, no Å¡Ä«s kartes tiks iekasÄ“ta maksa, taÄu kartes Ä«stais numurs netiks kopÄ«gots ar Å¡o vietni. Papildu droÅ¡Ä«bai tiks Ä£enerÄ“ts pagaidu CVC.}zero{Kad veiksiet maksÄjumus, no atlasÄ«tÄs kartes tiks iekasÄ“ta maksa, taÄu kartes Ä«stais numurs netiks kopÄ«gots ar Å¡o vietni. Papildu droÅ¡Ä«bai tiks Ä£enerÄ“ts pagaidu CVC.}one{Kad veiksiet maksÄjumus, no atlasÄ«tÄs kartes tiks iekasÄ“ta maksa, taÄu kartes Ä«stais numurs netiks kopÄ«gots ar Å¡o vietni. Papildu droÅ¡Ä«bai tiks Ä£enerÄ“ts pagaidu CVC.}other{Kad veiksiet maksÄjumus, no atlasÄ«tÄs kartes tiks iekasÄ“ta maksa, taÄu kartes Ä«stais numurs netiks kopÄ«gots ar Å¡o vietni. Papildu droÅ¡Ä«bai tiks Ä£enerÄ“ts pagaidu CVC.}}</translation>
<translation id="5826507051599432481">Kopējais nosaukums (CN)</translation>
<translation id="5838278095973806738">Neievadiet Å¡ajÄ vietnÄ“ sensitÄ«vu informÄciju (piemÄ“ram, paroles vai kredÄ«tkartes), jo to var nozagt uzbrucÄ“ji.</translation>
@@ -1300,6 +1334,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="5855253129151731373">Å Ä«s vietnes saimniekdatora nosaukums izskatÄs lÄ«dzÄ«gs vietnei <ph name="LOOKALIKE_DOMAIN" />. UzbrucÄ“ji dažkÄrt atdarina vietnes, veicot nelielas un grÅ«ti pamanÄmas izmaiņas domÄ“na nosaukumÄ.
Ja uzskatÄt, ka tas tiek parÄdÄ«ts kļūdas dēļ, lÅ«dzu, apmeklÄ“jiet vietni https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Izsl.</translation>
<translation id="5862579898803147654">8. izvades vieta</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>
@@ -1316,6 +1351,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="5913377024445952699">EkrÄnuzņēmumu izveide ir pÄrtraukta</translation>
<translation id="59174027418879706">Iespējots</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 tiek lietots}zero{# tiek lietoti}one{# tiek lietots}other{# tiek lietoti}}</translation>
<translation id="5921185718311485855">Iesl.</translation>
<translation id="5921639886840618607">Vai saglabÄt kartes datus Google kontÄ?</translation>
<translation id="5922853866070715753">Gandrīz pabeigts</translation>
@@ -1335,6 +1371,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="5989320800837274978">Nav norÄdÄ«ti nedz fiksÄ“ti starpniekserveri, nedz .pac skripta URL.</translation>
<translation id="5992691462791905444">Inženierijas Z-veida locījums</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> rezultÄti vaicÄjumam “<ph name="SEARCH_TEXT" />â€</translation>
+<translation id="6006484371116297560">Klasiskais motīvs</translation>
<translation id="6008122969617370890">Secība: no N līdz 1.</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Paroļu pÄrbaude</translation>
@@ -1356,6 +1393,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="6045164183059402045">Izvietojuma veidne</translation>
<translation id="6047233362582046994">Ja apzinÄties droÅ¡Ä«bas risku, varat arÄ« <ph name="BEGIN_LINK" />apmeklÄ“t Å¡o vietni<ph name="END_LINK" />, pirms ir noņemtas kaitÄ«gÄs lietotnes.</translation>
<translation id="6047927260846328439">Ar Å¡o saturu jÅ«s var maldinÄt un panÄkt, ka instalÄ“jat programmatÅ«ru vai atklÄjat personas informÄciju. <ph name="BEGIN_LINK" />TÄpat rÄdÄ«t<ph name="END_LINK" />.</translation>
+<translation id="6049004884579590341">Nospiediet un turiet |<ph name="ACCELERATOR" />|, lai izietu no pilnekrÄna režīma.</translation>
<translation id="6049488691372270142">Lapu izvade</translation>
<translation id="6051221802930200923">PaÅ¡laik nevarat apmeklÄ“t vietni <ph name="SITE" />, jo tajÄ tiek izmantota sertifikÄtu piesprauÅ¡ana. TÄ kÄ tÄ«kla kļūdas un uzbrukumi parasti ir Ä«slaicÄ«gi, visticamÄk, Å¡Ä« lapa vÄ“lÄk darbosies.</translation>
<translation id="6051898664905071243">Lappušu skaits:</translation>
@@ -1372,6 +1410,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<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>
<translation id="6116338172782435947">Skatīt starpliktuvē kopēto tekstu un attēlus</translation>
<translation id="6120179357481664955">Vai iegaumēt jūsu UPI ID?</translation>
+<translation id="6123290840358279103">SkatÄ«t virtuÄlo karti</translation>
<translation id="6124432979022149706">Chrome Enterprise savienotÄji</translation>
<translation id="6146055958333702838">PÄrbaudiet vadus un atkÄrtoti palaidiet marÅ¡rutÄ“tÄjus, modemus vai citas
izmantotÄs tÄ«kla ierÄ«ces.</translation>
@@ -1408,6 +1447,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="6289939620939689042">Lapas krÄsa</translation>
<translation id="6290238015253830360">Ieteiktie raksti tiek parÄdÄ«ti Å¡eit</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Tiek pÄrtraukta Google asistenta darbÄ«ba pÄrlÅ«kprogrammÄ Chrome.</translation>
<translation id="6305205051461490394">Vietne <ph name="URL" /> nav sasniedzama.</translation>
<translation id="6312113039770857350">Tīmekļa lapa nav pieejama</translation>
@@ -1433,6 +1473,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="6390200185239044127">Z-veida locījums uz pusēm</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">SaskaÅ†Ä ar administratora iestatÄ«to politiku ielÄ«mÄ“Å¡ana no <ph name="ORIGIN_NAME" /> ir bloÄ·Ä“ta Å¡ajÄ atraÅ¡anÄs vietÄ.</translation>
+<translation id="6398765197997659313">Iziet no pilnekrÄna režīma</translation>
<translation id="6401136357288658127">Å Ä« politika ir novecojusi. TÄs vietÄ jums vajadzÄ“tu izmantot <ph name="NEW_POLICY" /> politiku.</translation>
<translation id="6404511346730675251">Rediģēt grÄmatzÄ«mi</translation>
<translation id="6406765186087300643">C0 (aploksne)</translation>
@@ -1445,7 +1486,6 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="6428450836711225518">VerificÄ“jiet savu tÄlruņa numuru</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="6440503408713884761">Ignorēts</translation>
<translation id="6443406338865242315">Kurus paplaÅ¡inÄjumus un spraudņus esat instalÄ“jis</translation>
<translation id="6446163441502663861">Kahu (aploksne)</translation>
@@ -1488,6 +1528,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="6624427990725312378">KontaktinformÄcija</translation>
<translation id="6626291197371920147">Derīga kartes numura pievienošana</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> meklēšana</translation>
+<translation id="6630043285902923878">Notiek USB ierÄ«Äu meklÄ“Å¡ana...</translation>
<translation id="6630809736994426279">UzbrucÄ“ji vietnÄ“ <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> var mÄ“Ä£inÄt jÅ«su Mac datorÄ instalÄ“t bÄ«stamas programmas, kas zog vai izdzÄ“Å¡ informÄciju (piemÄ“ram, fotoattÄ“lus, paroles, ziņojumus un kredÄ«tkarÅ¡u datus). <ph name="BEGIN_LEARN_MORE_LINK" />Uzziniet vairÄk<ph name="END_LEARN_MORE_LINK" />.</translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Notīrīt</translation>
@@ -1503,6 +1544,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<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="6687335167692595844">Tika pieprasīts fonta lielums</translation>
+<translation id="6688743156324860098">AtjauninÄt…</translation>
<translation id="6689249931105087298">Relatīva, ar melno punktu saspieš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="6698381487523150993">Izveidots:</translation>
@@ -1518,6 +1560,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="6744009308914054259">KamÄ“r tiek gaidÄ«ts savienojums, varat apmeklÄ“t LejupielÄdes, lai lasÄ«tu rakstu bezsaistÄ“.</translation>
<translation id="6753269504797312559">Politikas vērtība</translation>
<translation id="6757797048963528358">IerÄ«ce tika pÄrslÄ“gta miega režīmÄ.</translation>
+<translation id="6767985426384634228">Vai atjauninÄt adresi?</translation>
<translation id="6768213884286397650">Hagaki (pastkarte)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violeta</translation>
@@ -1540,6 +1583,7 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" />: <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome vienkÄrÅ¡oja Å¡o lapu, lai atvieglotu lasÄ«Å¡anu. Chrome izguva sÄkotnÄ“jo lapu, izmantojot nedroÅ¡u savienojumu.</translation>
<translation id="6891596781022320156">Politikas līmenis netiek atbalstīts.</translation>
+<translation id="6895143722905299846">VirtuÄlais numurs:</translation>
<translation id="6895330447102777224">Karte ir apstiprinÄta</translation>
<translation id="6897140037006041989">LietotÄja aÄ£ents</translation>
<translation id="6898699227549475383">OrganizÄcija (O)</translation>
@@ -1575,10 +1619,10 @@ PretÄ“jÄ gadÄ«jumÄ Å¡Ä« iespÄ“ja bÅ«tu liegta saskaÅ†Ä ar jÅ«su konfidenciali
<translation id="7004583254764674281">Izmantot Windows Hello, lai ÄtrÄk apstiprinÄtu kartes</translation>
<translation id="7006930604109697472">Tomēr sūtīt</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Lieluma maiņas iestatījumi</translation>
<translation id="7014741021609395734">TÄlummaiņas lÄ«menis</translation>
<translation id="7016992613359344582">Å ie naudas pieprasÄ«jumi var bÅ«t vienreizÄ“ji vai atkÄrtoti, un tie var nebÅ«t uzreiz pamanÄmi.</translation>
<translation id="7029809446516969842">Paroles</translation>
+<translation id="7030436163253143341">SertifikÄts nav derÄ«gs</translation>
<translation id="7031646650991750659">Kuras Google Play lietotnes esat instalējis</translation>
<translation id="7050187094878475250">JÅ«s mÄ“Ä£inÄjÄt sasniegt domÄ“nu <ph name="DOMAIN" />, bet serveris uzrÄdÄ«ja sertifikÄtu, kura derÄ«guma periods ir pÄrÄk ilgs, lai bÅ«tu uzticams.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Å o karti paÅ¡laik nevar saglabÄt}zero{PaÅ¡laik nevar saglabÄt Å¡Ä«s kartes}one{PaÅ¡laik nevar saglabÄt Å¡Ä«s kartes}other{PaÅ¡laik nevar saglabÄt Å¡Ä«s kartes}}</translation>
@@ -1648,19 +1692,22 @@ Papildu informÄcija:
<translation id="7300012071106347854">Kobalta zila</translation>
<translation id="7302712225291570345">“<ph name="TEXT" />â€</translation>
<translation id="7304030187361489308">Augsts</translation>
+<translation id="7305756307268530424">SÄkt lÄ“nÄk</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Savienojuma palīdzība</translation>
<translation id="7323804146520582233">PaslÄ“pt sadaļu “<ph name="SECTION" />â€</translation>
<translation id="733354035281974745">IerÄ«ces lokÄlÄ konta ignorÄ“Å¡ana</translation>
<translation id="7333654844024768166">JÅ«s tikko ievadÄ«jÄt savu paroli maldinoÅ¡Ä vietnÄ“. Chromium ieteikums: tÅ«lÄ«t apmeklÄ“jiet vietni <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> un <ph name="WEBSITE_3" />, kÄ arÄ« citas vietnes, kurÄs izmantojat Å¡o paroli, un nomainiet to.</translation>
<translation id="7334320624316649418">&amp;Atcelt pÄrkÄrtoÅ¡anas atsaukÅ¡anu</translation>
+<translation id="7337248890521463931">RÄdÄ«t vairÄk rindu</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="733923710415886693">Servera sertifikÄts netika atklÄts, izmantojot sertifikÄta pÄrredzamÄ«bu.</translation>
<translation id="734600844861828519">11x15</translation>
<translation id="7346048084945669753">Ir saistīts:</translation>
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Komandrinda</translation>
<translation id="7359588939039777303">ReklÄmu rÄdÄ«Å¡ana ir bloÄ·Ä“ta.</translation>
+<translation id="7363096869660964304">TomÄ“r jÅ«s neesat neredzams. Izmantojot inkognito režīmu, jÅ«su pÄrlÅ«koÅ¡anas darbÄ«bas netiek slÄ“ptas no jÅ«su darba devÄ“ja, interneta pakalpojumu sniedzÄ“ja vai apmeklÄ“tajÄm vietnÄ“m.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />: nospiediet tabulÄ“Å¡anas taustiņu un pÄ“c tam — ievadÄ«Å¡anas taustiņu, lai Chrome iestatÄ«jumos pievienotu un pÄrvaldÄ«tu adreses.</translation>
<translation id="7365849542400970216">Vai rÄdÄ«t, kad jÅ«s lietojat ierÄ«ci?</translation>
<translation id="7372973238305370288">meklÄ“Å¡anas rezultÄts</translation>
@@ -1671,7 +1718,9 @@ Papildu informÄcija:
<translation id="7378594059915113390">Multivides vadīklas</translation>
<translation id="7378627244592794276">NÄ“</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Nav piemērojams</translation>
<translation id="7390545607259442187">Kartes apstiprinÄÅ¡ana</translation>
+<translation id="7392089738299859607">Adreses atjauninÄÅ¡ana</translation>
<translation id="7399802613464275309">DroÅ¡Ä«bas pÄrbaude</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">JÅ«su <ph name="DEVICE_NAME" /> ierÄ«ce tiek pÄrvaldÄ«ta</translation>
@@ -1686,6 +1735,7 @@ Papildu informÄcija:
&lt;li&gt;ApmeklÄ“jiet &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome palÄ«dzÄ«bas centru&lt;/a&gt;, lai uzzinÄtu, kÄ neatgriezeniski noņemt programmatÅ«ru no datora.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Glīta</translation>
<translation id="7416351320495623771">PÄrvaldÄ«t paroles…</translation>
<translation id="7419106976560586862">Profila ceļš</translation>
<translation id="7437289804838430631">Pievienot kontaktinformÄciju</translation>
@@ -1701,7 +1751,7 @@ Papildu informÄcija:
<translation id="7481312909269577407">PÄrsÅ«tÄ«t</translation>
<translation id="7485870689360869515">Dati netika atrasti.</translation>
<translation id="7495528107193238112">Šis saturs ir bloķēts. Lai novērstu problēmu, sazinieties ar vietnes īpašnieku.</translation>
-<translation id="7498234416455752244">TurpinÄt rediģēšanu</translation>
+<translation id="7498193950643227031">Ja tiks mainÄ«ts lielums, lietotne var darboties neparedzÄ“tÄ veidÄ. Tagad sadaÄ¼Ä <ph name="SETTINGS" /> varat ierobežot spÄ“ju mainÄ«t lietotņu lielumu.</translation>
<translation id="7503664977220660814">JÅ«s tikko ievadÄ«jÄt savu paroli maldinoÅ¡Ä vietnÄ“. Chromium ieteikums: tÅ«lÄ«t pÄrbaudiet saglabÄtÄs paroles vietnÄ“ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, kÄ arÄ« citÄs vietnÄ“s, kurÄs izmantojat Å¡o paroli.</translation>
<translation id="7508255263130623398">Atgrieztais politikas ierīces ID ir tukšs vai neatbilst pašreizējam ierīces ID.</translation>
<translation id="7508870219247277067">Avokado zaļa</translation>
@@ -1721,6 +1771,7 @@ Papildu informÄcija:
<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="755279583747225797">IzmÄ“Ä£inÄjums ir aktÄ«vs</translation>
<translation id="7552846755917812628">Izmantojiet tÄlÄk sniegtos padomus.</translation>
<translation id="7554475479213504905">Tik un tÄ atkÄrtoti ielÄdÄ“t un parÄdÄ«t</translation>
<translation id="7554791636758816595">Jauna cilne</translation>
@@ -1739,7 +1790,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Lai skatÄ«tu un pÄrvaldÄ«tu savas paroles Chrome iestatÄ«jumos, nospiediet tabulÄ“Å¡anas taustiņu un pÄ“c tam — ievadÄ«Å¡anas taustiņu.</translation>
-<translation id="7615602087246926389">Jums jau ir dati, kas šifrēti, izmantojot citu Google konta paroles versiju. Ievadiet to šeit.</translation>
<translation id="7616645509853975347">Administrators ir ieslÄ“dzis savienotÄju kolekciju Chrome Enterprise Connectors jÅ«su pÄrlÅ«kÄ. Å ie savienotÄji var piekļūt daļai jÅ«su datu.</translation>
<translation id="7619838219691048931">Beigu lapa</translation>
<translation id="762844065391966283">Pa vienam</translation>
@@ -1804,13 +1854,12 @@ Papildu informÄcija:
<translation id="782886543891417279">IespÄ“jams, izmantotajÄ Wi-Fi tÄ«klÄ (<ph name="WIFI_NAME" />) tiks pieprasÄ«ts apmeklÄ“t pieteikÅ¡anÄs lapu.</translation>
<translation id="7836231406687464395">Postfix (aploksne)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Nav}=1{1 lietotne (<ph name="EXAMPLE_APP_1" />)}=2{2 lietotnes (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}zero{# lietotnes (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}one{# lietotne (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}other{# lietotnes (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">TomÄ“r jÅ«s neesat neredzams. PÄrlÅ«kojot inkognito režīmÄ, jÅ«su pÄrlÅ«koÅ¡anas darbÄ«bas netiek slÄ“ptas no jÅ«su darba devÄ“ja, interneta pakalpojumu sniedzÄ“ja vai apmeklÄ“tajÄm vietnÄ“m.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Atvērt failus ar noteikta faila tipa saistību.</translation>
<translation id="7862185352068345852">Vai aizvērt vietni?</translation>
<translation id="7865448901209910068">OptimÄlais Ätrums</translation>
<translation id="7874263914261512992">JÅ«s tikko ievadÄ«jÄt savu paroli maldinoÅ¡Ä vietnÄ“. Chrome ieteikums: tÅ«lÄ«t pÄrbaudiet saglabÄtÄs paroles vietnÄ“ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, kÄ arÄ« citÄs vietnÄ“s, kurÄs izmantojat Å¡o paroli.</translation>
<translation id="7878562273885520351">Iespējams, jūsu parole ir apdraudēta</translation>
+<translation id="7880146494886811634">Adreses saglabÄÅ¡ana</translation>
<translation id="7882421473871500483">Brūna</translation>
<translation id="7887683347370398519">PÄrbaudiet CVC kodu un mÄ“Ä£iniet vÄ“lreiz.</translation>
<translation id="7887885240995164102">AtvÄ“rt režīmu “attÄ“ls attÄ“lÄâ€</translation>
@@ -1818,6 +1867,7 @@ Papildu informÄcija:
<translation id="7894280532028510793">Ja nav pareizrakstības kļūdu, <ph name="BEGIN_LINK" />mēģiniet palaist tīkla diagnostiku<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (aploksne)</translation>
<translation id="7931318309563332511">NezinÄma</translation>
+<translation id="793209273132572360">Vai atjauninÄt adresi?</translation>
<translation id="7932579305932748336">PÄrklÄjums</translation>
<translation id="79338296614623784">Ievadiet derÄ«gu tÄlruņa numuru</translation>
<translation id="7934052535022478634">MaksÄjums pabeigts</translation>
@@ -1888,6 +1938,7 @@ Papildu informÄcija:
<translation id="8175796834047840627">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.</translation>
<translation id="8176440868214972690">Å Ä«s ierÄ«ces administrators ir nosÅ«tÄ«jis informÄciju, piemÄ“ram, iestatÄ«jumus vai politikas, uz tÄlÄk norÄdÄ«tajÄm vietnÄ“m.</translation>
<translation id="8184538546369750125">Izmantot globÄlo noklusÄ“jumu (Atļaut)</translation>
+<translation id="8193086767630290324">DarbÄ«bas ar datiem, kas atzÄ«mÄ“ti kÄ konfidenciÄli</translation>
<translation id="8194797478851900357">&amp;PÄrvietoÅ¡anas atsaukÅ¡ana</translation>
<translation id="8201077131113104583">NederÄ«gs atjauninÄÅ¡anas URL paplaÅ¡inÄjumam ar ID “<ph name="EXTENSION_ID" />â€.</translation>
<translation id="8202097416529803614">Pasūtījuma kopsavilkums</translation>
@@ -1910,6 +1961,7 @@ Papildu informÄcija:
<translation id="8249296373107784235">PriekÅ¡laikus pÄrtraukt</translation>
<translation id="8249320324621329438">PÄ“dÄ“jÄs pirmsielÄdes laiks:</translation>
<translation id="8253091569723639551">JÄnorÄda norÄ“Ä·inu adrese.</translation>
+<translation id="8257387598443225809">Å Ä« lietotne ir paredzÄ“ta mobilajÄm ierÄ«cÄ“m</translation>
<translation id="825929999321470778">RÄdÄ«t visas saglabÄtÄs paroles</translation>
<translation id="8261506727792406068">Dzēst</translation>
<translation id="8262952874573525464">Malu saÅ¡uvums apakÅ¡daļÄ</translation>
@@ -2034,7 +2086,6 @@ Papildu informÄcija:
<translation id="8719528812645237045">VairÄki caurumi augÅ¡daļÄ</translation>
<translation id="8725066075913043281">MÄ“Ä£inÄt vÄ“lreiz</translation>
<translation id="8726549941689275341">Lapas lielums:</translation>
-<translation id="8728672262656704056">Jūs esat atvēris inkognito režīmu</translation>
<translation id="8730621377337864115">Gatavs</translation>
<translation id="8731544501227493793">Poga “PÄrvaldÄ«t parolesâ€. Lai skatÄ«tu un pÄrvaldÄ«tu paroles Chrome iestatÄ«jumos, nospiediet ievadÄ«Å¡anas taustiņu.</translation>
<translation id="8734529307927223492">JÅ«su <ph name="DEVICE_TYPE" /> ierÄ«ci pÄrvalda <ph name="MANAGER" /></translation>
@@ -2100,7 +2151,7 @@ Papildu informÄcija:
<translation id="8989148748219918422"><ph name="ORGANIZATION" /> [<ph name="COUNTRY" />]</translation>
<translation id="899688752321268742">Vietne <ph name="URL" /> vÄ“las zinÄt, kad jÅ«s aktÄ«vi lietojat Å¡o ierÄ«ci</translation>
<translation id="8996941253935762404">Vietnē, kura tiks atvērta, ir kaitīgas programmas</translation>
-<translation id="8997023839087525404">Serveris uzrÄdÄ«ja sertifikÄtu, kas netika publiski atklÄts, izmantojot Certificate Transparency politiku. Å Ä« ir prasÄ«ba noteiktiem sertifikÄtiem, lai nodroÅ¡inÄtu to uzticamÄ«bu un aizsardzÄ«bu pret uzbrucÄ“jiem.</translation>
+<translation id="8997023839087525404">Serveris uzrÄdÄ«ja sertifikÄtu, kas netika publiski atklÄts, izmantojot sertifikÄta pÄrredzamÄ«bas politiku. Å Ä« ir prasÄ«ba noteiktiem sertifikÄtiem, lai nodroÅ¡inÄtu to uzticamÄ«bu un aizsardzÄ«bu pret uzbrucÄ“jiem.</translation>
<translation id="9001074447101275817">Starpniekserveris <ph name="DOMAIN" /> pieprasa lietotÄjvÄrdu un paroli.</translation>
<translation id="9001963517402879850">Leciet!</translation>
<translation id="9004367719664099443">Notiek VR sesija</translation>
@@ -2111,6 +2162,7 @@ Papildu informÄcija:
<translation id="9020542370529661692">Å Ä« lapa ir tulkota <ph name="TARGET_LANGUAGE" /> valodÄ.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(nederīgs)</translation>
+<translation id="9030265603405983977">VienkrÄsaina</translation>
<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>
@@ -2134,6 +2186,7 @@ Papildu informÄcija:
<translation id="91108059142052966">SaskaÅ†Ä ar administratora iestatÄ«to politiku ekrÄna kopÄ«goÅ¡ana ar lietojumprogrammu <ph name="APPLICATION_TITLE" /> tiek atspÄ“jota, kad ir redzams konfidenciÄls saturs.</translation>
<translation id="9114524666733003316">Notiek kartes apstiprinÄÅ¡ana...</translation>
<translation id="9114581008513152754">Å 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="9117930699067497412">Dzīvīga</translation>
<translation id="9119042192571987207">AugÅ¡upielÄdÄ“ts</translation>
<translation id="9128016270925453879">Politikas ir ielÄdÄ“tas</translation>
<translation id="9128870381267983090">Izveidot savienojumu ar tīklu</translation>
@@ -2152,6 +2205,7 @@ Papildu informÄcija:
<translation id="9170848237812810038">&amp;Atsaukt</translation>
<translation id="9171296965991013597">Vai aizvērt lietotni?</translation>
<translation id="9173282814238175921">Viens dokuments/jauna lapa</translation>
+<translation id="9173995187295789444">Notiek Bluetooth ierÄ«Äu meklÄ“Å¡ana...</translation>
<translation id="917450738466192189">Servera sertifikÄts ir nederÄ«gs.</translation>
<translation id="9174917557437862841">Ciļņu pÄrslÄ“gÅ¡anas poga. Nospiediet ievadÄ«Å¡anas taustiņu, lai pÄrslÄ“gtu Å¡o cilni.</translation>
<translation id="9179703756951298733">PÄrvaldiet savu maksÄjumu un kredÄ«tkarÅ¡u informÄciju Chrome iestatÄ«jumos.</translation>
diff --git a/chromium/components/strings/components_strings_mk.xtb b/chromium/components/strings/components_strings_mk.xtb
index 61bd8217f71..59eb6c34058 100644
--- a/chromium/components/strings/components_strings_mk.xtb
+++ b/chromium/components/strings/components_strings_mk.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Доколку е избрано, Chrome ќе меморира копија од вашата картичка на уредов за побрзо пополнување на формуларот.</translation>
<translation id="1110994991967754504">Изберете дозвола за <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Врати преуредување</translation>
+<translation id="1123753900084781868">„ÐвтоматÑки титлови“ не е доÑтапна во моментов</translation>
<translation id="1125573121925420732">Предупредувањата Ñе вообичаени додека веб-Ñајтовите ја ажурираат Ñвојата безбедноÑÑ‚. Очекувајте тоа да Ñе подобри наÑкоро.</translation>
<translation id="112840717907525620">Кешот на политиката е во ред</translation>
<translation id="1130564665089811311">Копче „Преведи ја Ñтраницата“, притиÑнете Enter за да ја преведете Ñтраницава Ñо „Преведи на Google“</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Има на уредот</translation>
<translation id="124116460088058876">Повеќе јазици</translation>
<translation id="1243027604378859286">Ðвтор:</translation>
+<translation id="1246424317317450637">Болд</translation>
<translation id="1250759482327835220">За да платите побрзо Ñледниот пат, зачувајте ја картичката, името и адреÑата за наплата на вашата Ñметка на Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" /> и <ph name="TYPE_2" /> (Ñинхронизирани)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ðко Ñе обидувате да поÑетите веб-Ñајт, а тој не Ñе отвора, прво обидете Ñе да ја поправите грешката Ñо овие чекори за отÑтранување грешки:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Променете ја лозинката</translation>
<translation id="1484290072879560759">Изберете адреÑа за иÑпорака</translation>
<translation id="1492194039220927094">Туркање на правилата:</translation>
+<translation id="1495677929897281669">Ðазад на картичката</translation>
<translation id="1501859676467574491">Прикажувај картички од Ñметката на Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Грешкава ќе ја видите ако кориÑтите Wi-Fi портал каде што мора да Ñе најавите пред да може да отидете онлајн.&lt;/p&gt;
&lt;p&gt;За да ја поправите грешката, кликнете &lt;strong&gt;Поврзи&lt;/strong&gt; на Ñтраницата што Ñе обидувате да ја отворите.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Оваа Ñтраница вели</translation>
<translation id="153384715582417236">Тоа е ÑÑ Ð·Ð°Ñега</translation>
<translation id="1536390784834419204">Преведи ја Ñтраницата</translation>
+<translation id="1539840569003678498">Извештајот е иÑпратен на:</translation>
<translation id="154408704832528245">Изберете адреÑа за доÑтава</translation>
<translation id="1549470594296187301">За да Ñе кориÑти функцијава, мора да биде овозможено JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">Прво краткиот раб</translation>
<translation id="168693727862418163">ВредноÑта на правилото не може да Ñе потврди Ñпоред неговата шема и ќе биде игнорирана.</translation>
<translation id="168841957122794586">Сертификатот на Ñерверот Ñодржи Ñлаб криптографÑки клуч.</translation>
+<translation id="1696290444144917273">Прегледајте ги деталите од виртуелната картичка</translation>
<translation id="1697532407822776718">Подготвени Ñте.</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Серверот не може да докаже дека е <ph name="DOMAIN" />; неговиот безбедноÑен Ñертификат наводно е утрешен. Тоа можеби Ñе должи на погрешна конфигурација или на напаѓач што ја преÑретнува вашата врÑка.}one{Серверот не може да докаже дека е <ph name="DOMAIN" />; неговиот безбедноÑен Ñертификат наводно е поÑле # ден во иднината. Тоа можеби Ñе должи на погрешна конфигурација или на напаѓач што ја преÑретнува вашата врÑка.}other{Серверот не може да докаже дека е <ph name="DOMAIN" />; неговиот безбедноÑен Ñертификат наводно е поÑле # дена во иднината. Тоа можеби Ñе должи на погрешна конфигурација или на напаѓач што ја преÑретнува вашата врÑка.}}</translation>
<translation id="1710259589646384581">ОС</translation>
+<translation id="1711234383449478798">Игнорирано бидејќи <ph name="POLICY_NAME" /> не е поÑтавено на <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> Ñака трајно да Ñкладира податоци на вашиот локален компјутер</translation>
<translation id="1713628304598226412">Фиока 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">ПоштенÑко Ñандаче 3</translation>
<translation id="1718029547804390981">Документот е премногу голем за да Ñе Ñтави прибелешка</translation>
<translation id="1721424275792716183">* Полето е задолжително</translation>
+<translation id="1727613060316725209">Сертификатот е важечки</translation>
<translation id="1727741090716970331">Додајте важечки број на картичка</translation>
<translation id="1728677426644403582">Го гледате кодот на веб-Ñтраницата</translation>
<translation id="173080396488393970">Овој тип картичка не е поддржан</translation>
@@ -246,7 +253,6 @@
вашето барање за <ph name="SITE" />. Операторите на Ñајтови може да ги кориÑтат правилата за потекло
за конфигурирање на безбедноÑта и другите ÑвојÑтва за Ñајтот.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Ðжурирајте ја вашата лозинка за Ñинхронизирање.</translation>
<translation id="1787142507584202372">Отворените картички Ñе појавуваат тука</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, доÑтапни Ñе повеќе дејÑтва, притиÑкајте Tab за да ги менувате</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">Реклами</translation>
<translation id="1919367280705858090">Добивање помош околу конкретна порака за грешка</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ðиту еден}=1{1 Ñајт}one{# Ñајт}other{# Ñајтови}}</translation>
+<translation id="1924727005275031552">Ðово</translation>
<translation id="1945968466830820669">Може да го изгубите приÑтапот до Ñметката на вашата организација или да ви го украдат идентитетот. Chromium препорачува да ја Ñмените лозинката веднаш.</translation>
<translation id="1947454675006758438">Спојување горе деÑно</translation>
<translation id="1958218078413065209">Вашиот најдобар резултат е <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">Фиока 7</translation>
<translation id="204357726431741734">Ðајавете Ñе за да кориÑтите лозинки зачувани во вашата Ñметка на Google</translation>
<translation id="2053111141626950936">Страниците на <ph name="LANGUAGE" /> нема да Ñе преведуваат.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Кога оваа контрола е вклучена и ÑтатуÑот е активен, Chrome одредува Ñо која голема група на луѓе или „кохортата“ е најÑлична вашата неодамнешна активноÑÑ‚ од прелиÑтувањето. ОглаÑувачите може да избираат реклами за групата, а вашата активноÑÑ‚ од прелиÑтувањето оÑтанува приватна на вашиот уред. Групата Ñе ажурира Ñекој ден.}=1{Кога оваа контрола е вклучена и ÑтатуÑот е активен, Chrome одредува Ñо која голема група на луѓе или „кохортата“ е најÑлична вашата неодамнешна активноÑÑ‚ од прелиÑтувањето. ОглаÑувачите може да избираат реклами за групата, а вашата активноÑÑ‚ од прелиÑтувањето оÑтанува приватна на вашиот уред. Групата Ñе ажурира Ñекој ден.}one{Кога оваа контрола е вклучена и ÑтатуÑот е активен, Chrome одредува Ñо која голема група на луѓе или „кохортата“ е најÑлична вашата неодамнешна активноÑÑ‚ од прелиÑтувањето. ОглаÑувачите може да избираат реклами за групата, а вашата активноÑÑ‚ од прелиÑтувањето оÑтанува приватна на вашиот уред. Групата Ñе ажурира Ñекој {NUM_DAYS} ден.}other{Кога оваа контрола е вклучена и ÑтатуÑот е активен, Chrome одредува Ñо која голема група на луѓе или „кохортата“ е најÑлична вашата неодамнешна активноÑÑ‚ од прелиÑтувањето. ОглаÑувачите може да избираат реклами за групата, а вашата активноÑÑ‚ од прелиÑтувањето оÑтанува приватна на вашиот уред. Групата Ñе ажурира Ñекои {NUM_DAYS} дена.}}</translation>
<translation id="2053553514270667976">ПоштенÑки број</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 предлог}one{# предлог}other{# предлози}}</translation>
<translation id="2071692954027939183">ИзвеÑтувањата беа блокирани автоматÑки бидејќи обично не ги дозволувате</translation>
<translation id="2079545284768500474">Врати</translation>
<translation id="20817612488360358">ПоÑтавките на прокÑи на ÑиÑтемот Ñе поÑтавени да Ñе кориÑтат, но назначена е и јаÑна конфигурација на прокÑи.</translation>
<translation id="2082238445998314030">Резултат <ph name="RESULT_NUMBER" /> од <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Зачувајте…</translation>
<translation id="2088086323192747268">Копче „Управувај Ñо Ñинхронизирањето“, притиÑнете Enter за да управувате Ñо податоците коишто Ñе Ñинхронизираат во поÑтавките за Chrome</translation>
<translation id="2091887806945687916">Звук</translation>
<translation id="2094505752054353250">ÐеÑовпаѓање на домени</translation>
@@ -372,13 +381,14 @@
<translation id="2293443924986248631">Кога е вклучено, Ñајтовите не може да кориÑтат колачиња што ве Ñледат на интернет. Функциите на некои Ñајтови може да не функционираат.</translation>
<translation id="2295290966866883927">URL-адреÑите од Ñтраниците што ги поÑетувате Ñе иÑпраќаат до Google Cloud или трети Ñтрани за анализа. Ðа пример, можеби ќе Ñе Ñкенираат за да Ñе откријат небезбедни веб-Ñајтови.</translation>
<translation id="2297722699537546652">B5 (плик)</translation>
-<translation id="2298855485018661510">Копче „Управувај Ñо колачињата“, притиÑнете Enter за да управувате Ñо претпочитаните вредноÑти за колачиња во поÑтавките за Chrome</translation>
+<translation id="2298855485018661510">Копче „Управувај Ñо колачињата“, притиÑнете Enter за да управувате Ñо поÑтавките за колачиња во поÑтавките на Chrome</translation>
<translation id="2300306941146563769">Ðе е прикачен</translation>
<translation id="2310021320168182093">Chou 2 (плик)</translation>
<translation id="2316887270356262533">Ќе оÑлободи помалку од 1 MB. Ðекои Ñајтови може да Ñе вчитуваат побавно при вашата Ñледна поÑета.</translation>
<translation id="2317259163369394535"><ph name="DOMAIN" /> бара кориÑничко име и лозинка.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, иÑтекува на <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">ПоÑтавка што ја контролира админиÑтраторот</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> Ñака да Ñе Ñпари</translation>
<translation id="2344028582131185878">ÐвтоматÑки преземања</translation>
<translation id="2346319942568447007">Сликата што ја копиравте</translation>
<translation id="2354001756790975382">Други обележувачи</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">Ðапаѓачите можеби ќе можат да ги видат Ñликите што ги гледате на Ñајтов и да ве измамат Ñо тоа што ќе ги модифицираат.</translation>
<translation id="2356070529366658676">Прашај</translation>
<translation id="2357481397660644965"><ph name="DEVICE_MANAGER" /> управува Ñо уредот, а <ph name="ACCOUNT_MANAGER" /> управува Ñо Ñметката.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{За помалку од еден ден}=1{За еден ден}one{За {NUM_DAYS} ден}other{За {NUM_DAYS} дена}}</translation>
<translation id="2359629602545592467">Повеќе</translation>
<translation id="2359808026110333948">Продолжи</translation>
+<translation id="2359961752320758691">Бројот на виртуелната картичка е применет.</translation>
<translation id="2367567093518048410">Ðиво</translation>
<translation id="2372464001869762664">Откако ќе потврдите, деталите за картичката од вашата Ñметка на Google ќе Ñе Ñподелат Ñо Ñајтов. Ðајдете го CVC во деталите за Ñметката на Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">Овој метод на иÑпорака не е доÑтапен. Изберете друг.</translation>
<translation id="2396249848217231973">&amp;Врати бришење</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Старата</translation>
<translation id="2413528052993050574">Серверот не може да докаже дека е <ph name="DOMAIN" />; можеби неговиот безбедноÑен Ñертификат е повлечен. Тоа може да Ñе должи на погрешна конфигурација или на напаѓач што го преÑретнува поврзувањето.</translation>
<translation id="2414886740292270097">Темна</translation>
<translation id="2438874542388153331">Четири дупки деÑно</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">Спојување долу деÑно</translation>
<translation id="2523886232349826891">Зачувано Ñамо на овој уред</translation>
<translation id="2524461107774643265">Додајте повеќе информации</translation>
-<translation id="2526590354069164005">ДеÑктоп</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{и уште 1}one{и уште #}other{и уште #}}</translation>
<translation id="2536110899380797252">Додајте адреÑа</translation>
<translation id="2539524384386349900">Откриј</translation>
+<translation id="2541219929084442027">Страниците што ги гледате во картичките „Инкогнито“ нема да Ñе задржат во иÑторијата на прелиÑтувачот, во колачињата или во иÑторијата на пребарување откако ќе ги затворите Ñите ваши картички „Инкогнито“. Сите преземени датотеки или Ñоздадени обележувачи ќе Ñе задржат.</translation>
<translation id="2544644783021658368">Еден документ</translation>
<translation id="254947805923345898">ВредноÑта на правилото не е важечка.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> иÑпрати неважечки одговор.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">За да го добиете навиÑокото ниво на безбедноÑÑ‚ на Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />вклучете ја „Подобрената заштита“<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">IP-адреÑата за Ñерверот на <ph name="HOST_NAME" /> не може да Ñе најде.</translation>
<translation id="2639739919103226564">СтатуÑ:</translation>
+<translation id="264810637653812429">Ðе Ñе најдени компатибилни уреди.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, притиÑнете Tab, а потоа Enter за да ги избришете иÑторијата на прелиÑтувањето, колачињата, кешот и други работи во поÑтавките за Chrome</translation>
<translation id="2650446666397867134">ПриÑтапот до датотеката беше одбиен</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">РеÑтартирај</translation>
<translation id="2803306138276472711">Google Safe Browsing неодамна <ph name="BEGIN_LINK" />откри злонамерен Ñофтвер<ph name="END_LINK" /> на <ph name="SITE" />. Веб-локациите што обично Ñе безбедни, некогаш Ñе инфицираат Ñо злонамерен Ñофтвер.</translation>
<translation id="2807052079800581569">Позиција на Ñликата Y</translation>
+<translation id="2820957248982571256">Се Ñкенира…</translation>
<translation id="2824775600643448204">Лента за адреÑа и за пребарување</translation>
<translation id="2826760142808435982">Поврзувањето е шифрирано и автентицирано Ñо употреба на <ph name="CIPHER" /> и кориÑти <ph name="KX" /> како клучен механизам за размена.</translation>
<translation id="2835170189407361413">ИÑчиÑти формулар</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Invite (плик)</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="2859806420264540918">Сајтов прикажува нападни или лажни реклами.</translation>
+<translation id="287596039013813457">ПријателÑки</translation>
+<translation id="2876489322757410363">Ќе излезете од режимот „Инкогнито“ за да платите преку надворешна апликација. Дали Ñакате да продолжите?</translation>
<translation id="2878197950673342043">Превиткување поÑтер</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ПоÑтавување прозорец</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (плик)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, притиÑнете Tab, а потоа Enter за да извршите безбедноÑна проверка во поÑтавките за Chrome</translation>
<translation id="3061707000357573562">УÑлуга за поправање грешки</translation>
-<translation id="3064966200440839136">Ќе го напуштите режимот „Инкогнито“ за да платите преку надворешна апликација. Ќе продолжите?</translation>
<translation id="306573536155379004">Играта започна.</translation>
<translation id="3080254622891793721">Графика</translation>
<translation id="3086579638707268289">Вашата активноÑÑ‚ на интернет е под надзор</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312"><ph name="MANAGER" /> управува Ñо вашата Ñметка.</translation>
<translation id="3157931365184549694">Обнови</translation>
<translation id="3162559335345991374">Wi-Fi што го кориÑтите може да бара да ја поÑетите Ñтраницата за најавување.</translation>
-<translation id="3167968892399408617">Страниците што ги гледате во инкогнито-картичките нема да Ñе задржат во иÑторијата на прелиÑтувачот, во продавницата на колачиња или во иÑторијата на пребарување откако ќе ги затворите Ñите ваши инкогнито-картички. Сите преземени датотеки или Ñоздадени обележувачи ќе Ñе задржат.</translation>
<translation id="3169472444629675720">Откриј</translation>
<translation id="3174168572213147020">ОÑтров</translation>
<translation id="3176929007561373547">Проверете ги поÑтавките на прокÑи или контактирајте Ñо админиÑтраторот
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">Информации за верзијата за уредот и прелиÑтувачот</translation>
<translation id="323107829343500871">ВнеÑете го CVC за <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Секогаш откривај важна Ñодржина на оваа локација</translation>
+<translation id="3249845759089040423">Модерен</translation>
<translation id="3252266817569339921">француÑки</translation>
<translation id="3266793032086590337">ВредноÑÑ‚ (конфликт)</translation>
<translation id="3268451620468152448">Отворени картички</translation>
<translation id="3270847123878663523">&amp;Врати Преуредување</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> Ñака да Ñе поврзе</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Вашата организација, <ph name="ENROLLMENT_DOMAIN" />, иÑпратила одредени информации на Ñледниве веб-Ñајтови, како поÑтавки или правила.</translation>
<translation id="3282497668470633863">Додајте име на картичка</translation>
@@ -655,6 +672,7 @@
<translation id="3428151540071562330">Една или повеќе од шаблонÑките URI на Ñерверот DnsOverHttpsTemplates Ñе неважечки и нема да Ñе кориÑтат.</translation>
<translation id="3431636764301398940">Зачувај ја картичкава на уредов</translation>
<translation id="3432601291244612633">Затвори ја Ñтраницата</translation>
+<translation id="3435738964857648380">БезбедноÑÑ‚</translation>
<translation id="3435896845095436175">Овозможи</translation>
<translation id="3438829137925142401">КориÑтете лозинки зачувани во вашата Ñметка на Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@
<translation id="3584299510153766161">Две дупки долу</translation>
<translation id="3586931643579894722">Сокриј детали</translation>
<translation id="3587738293690942763">Средна</translation>
+<translation id="3590643883886679995">Податоците за најавување ќе Ñе Ñкладираат во уредов откако ќе излезете од режимот „Инкогнито“.</translation>
+<translation id="359126217934908072">МеÑец/година:</translation>
<translation id="3592413004129370115">Italian (плик)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Може да ја реÑтирате групата во Ñекое време. Потребен е околу еден ден за да Ñе придружите на нова група.}=1{Може да ја реÑтирате групата во Ñекое време. Потребен е околу еден ден за да Ñе придружите на нова група.}one{Може да ја реÑтирате групата во Ñекое време. Потребен е околу {NUM_DAYS} ден за да Ñе придружите на нова група.}other{Може да ја реÑтирате групата во Ñекое време. Потребни Ñе околу {NUM_DAYS} дена за да Ñе придружите на нова група.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">ÐдминиÑтраторот ја блокирал апликацијата</translation>
<translation id="3608932978122581043">Одржи ја ориентацијата</translation>
@@ -706,13 +727,13 @@
<translation id="3615877443314183785">ВнеÑете важечки датум на иÑтекување</translation>
<translation id="36224234498066874">ИÑчиÑти податоци…</translation>
<translation id="362276910939193118">Покажи целоÑна иÑторија</translation>
-<translation id="3625635938337243871">Податоците за најавување ќе Ñе Ñкладираат во уредов откако ќе излезете од режимот „Инкогнито“.</translation>
<translation id="3630155396527302611">Доколку веќе е на ÑпиÑокот Ñо програми на кои им е дозволен приÑтап до мрежата, обидете Ñе
да го отÑтраните од ÑпиÑокот и да го додадете повторно.</translation>
<translation id="3630699740441428070">ÐдминиÑтраторите на уредов ја конфигурирале мрежната врÑка, што може да им дозволи да го гледаат мрежниот Ñообраќај, вклучително и кои веб-Ñајтови ги поÑетувате.</translation>
<translation id="3631244953324577188">Биометрика</translation>
<translation id="3633738897356909127">Копче „Ðжурирај го Chrome“, притиÑнете Enter за да го ажурирате Chrome од поÑтавките за Chrome</translation>
<translation id="3634530185120165534">Фиока 5</translation>
+<translation id="3637662659967048211">Зачувајте во Ñметката на Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Ðпликација:</translation>
<translation id="3650584904733503804">Потврдувањето е уÑпешно</translation>
@@ -753,6 +774,7 @@
<translation id="3781428340399460090">Впечатливо розова</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Уреди Ñо Bluetooth</translation>
+<translation id="3787675388804467730">Број на виртуелна картичка</translation>
<translation id="3787705759683870569">ИÑтекува на <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Големина 16</translation>
<translation id="3789841737615482174">ИнÑталирај</translation>
@@ -772,6 +794,7 @@
<translation id="3841184659773414994">Ракувачи Ñо датотеки</translation>
<translation id="385051799172605136">Ðазад</translation>
<translation id="3858027520442213535">Ðжурирај датум и време</translation>
+<translation id="3881478300875776315">Прикажи помалку редови</translation>
<translation id="3884278016824448484">Идентификувач на конфликтен уред</translation>
<translation id="3885155851504623709">Парохија</translation>
<translation id="388632593194507180">Откриен е надзор</translation>
@@ -797,6 +820,7 @@
<translation id="397105322502079400">Се преÑметува…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> е блокиран</translation>
<translation id="3973357910713125165">Копче „Изврши безбедноÑна проверка во Chrome“, притиÑнете Enter за да извршите безбедноÑна проверка во поÑтавките за Chrome</translation>
+<translation id="3986705137476756801">ИÑклучете ја „ÐвтоматÑки титлови“ заÑега</translation>
<translation id="3987405730340719549">Chrome утврди дека Ñајтов може да е лажен или измамнички.
Ðко Ñметате дека ова ви Ñе прикажува по грешка, одете на https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@
<translation id="4275830172053184480">РеÑтартирај го уредот</translation>
<translation id="4277028893293644418">РеÑетирај ја лозинката</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Картичкава е зачувана во вашата Ñметка на Google}one{Картичкиве Ñе зачувани во вашата Ñметка на Google}other{Картичкиве Ñе зачувани во вашата Ñметка на Google}}</translation>
+<translation id="4287885627794386150">Подобно за пробен период, но не е активно</translation>
<translation id="4297502707443874121">Сликичка за Ñтраницата <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Прошири</translation>
<translation id="4300675098767811073">Повеќе дупки деÑно</translation>
<translation id="4302514097724775343">Допрете го диноÑауруÑот за да играте</translation>
<translation id="4302965934281694568">Chou3 (плик)</translation>
<translation id="4305666528087210886">Ðе може да Ñе приÑтапи до вашата датотека</translation>
-<translation id="4305817255990598646">Префрли</translation>
+<translation id="4306529830550717874">Да Ñе зачува адреÑата?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Блокирај (Ñтандардно)</translation>
<translation id="4314815835985389558">Управувајте Ñо Ñинхронизацијата</translation>
@@ -926,6 +951,7 @@
<translation id="4377125064752653719">Се обидовте да го добиете <ph name="DOMAIN" />, но издавачот го повлекол Ñертификатот што го претÑтавил Ñерверот. Тоа значи дека воопшто не треба да верувате во акредитациите за безбедноÑÑ‚ кои ги претÑтавил Ñерверот. Можеби комуницирате Ñо напаѓач.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4390472908992056574">Раб</translation>
+<translation id="4406883609789734330">ÐвтоматÑки титлови</translation>
<translation id="4406896451731180161">резултати од пребарувањето</translation>
<translation id="4408413947728134509">Колачиња <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Тукушто ја внеÑовте Ñвојата лозинка на измамнички Ñајт. Chrome препорачува да одите на <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> и на други Ñајтови каде што ја кориÑтите лозинкава и да ја промените веднаш.</translation>
@@ -938,7 +964,6 @@
<translation id="4435702339979719576">Разгледница)</translation>
<translation id="443673843213245140">Оневозможена е употребата на прокÑи, но одредена е опширна конфигурација на прокÑи.</translation>
<translation id="4464826014807964867">Веб-Ñајтови Ñо информации од вашата организација</translation>
-<translation id="4466881336512663640">Промените на формуларот ќе Ñе изгубат. Сигурно Ñакате да продолжите?</translation>
<translation id="4476953670630786061">Формуларов не е безбеден. ÐвтоматÑкото пополнување е иÑклучено.</translation>
<translation id="4477350412780666475">Следна пеÑна</translation>
<translation id="4482953324121162758">Сајтов нема да Ñе преведе.</translation>
@@ -972,6 +997,7 @@
<translation id="4594403342090139922">&amp;Врати бришење</translation>
<translation id="4597348597567598915">Големина 8</translation>
<translation id="4600854749408232102">C6/C5 (плик)</translation>
+<translation id="4606870351894164739">Забележителен</translation>
<translation id="4628948037717959914">Фотографија</translation>
<translation id="4631649115723685955">Со поврат на готовина</translation>
<translation id="4636930964841734540">Информации</translation>
@@ -991,6 +1017,7 @@
<translation id="4691835149146451662">Architecture-A (плик)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Странична</translation>
+<translation id="4702656508969495934">„ÐвтоматÑки титлови“ е видлива, кориÑтете префрлач на прозорци за да фокуÑирате</translation>
<translation id="4708268264240856090">Ð’Ñ€Ñката беше прекината</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />да извршите дијагноÑтика на мрежата на Windows<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@
<translation id="4738601419177586157">Предлог за пребарување: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Управувајте Ñо лозинките…</translation>
<translation id="4744603770635761495">Извршна патека</translation>
+<translation id="4749011317274908093">Влеговте во режим „Инкогнито“</translation>
<translation id="4750917950439032686">Вашите информации (на пример, лозинките или броевите на кредитните картички) Ñе приватни кога Ñе иÑпраќаат на овој Ñајт.</translation>
<translation id="4756388243121344051">&amp;ИÑторија</translation>
<translation id="4758311279753947758">Додај информации за контакт</translation>
@@ -1033,6 +1061,8 @@
<translation id="4813512666221746211">Грешка на мрежа</translation>
<translation id="4816492930507672669">Скрој во Ñтраница</translation>
<translation id="4819347708020428563">Сакате ли да ги измените прибелешките во Ñтандарден приказ?</translation>
+<translation id="4825507807291741242">Моќен</translation>
+<translation id="4838327282952368871">Ðереален</translation>
<translation id="484462545196658690">ÐвтоматÑки</translation>
<translation id="4850886885716139402">Приказ</translation>
<translation id="485316830061041779">германÑки</translation>
@@ -1169,6 +1199,7 @@
<translation id="5314967030527622926">Производител на брошури</translation>
<translation id="5316812925700871227">Ротирај налево</translation>
<translation id="5317780077021120954">Зачувај</translation>
+<translation id="5321288445143113935">МакÑимизирана</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> од <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Изберете информации за контакт</translation>
<translation id="5327248766486351172">Име</translation>
@@ -1176,11 +1207,13 @@
<translation id="5332219387342487447">Метод на иÑпорака</translation>
<translation id="5333022057423422993">Chrome ја најде лозинката која штотуку ја употребивте меѓу лозинките откриени при упад во податоците. За да ги заштитите Ñметките, препорачуваме да ги проверите зачуваните лозинки.</translation>
<translation id="5334013548165032829">Детални ÑиÑтемÑки дневници</translation>
+<translation id="5334145288572353250">Да Ñе зачува адреÑата?</translation>
<translation id="5340250774223869109">Ðпликацијата е блокирана</translation>
<translation id="534295439873310000">NFC-уреди</translation>
<translation id="5344579389779391559">Страницава можеби ќе Ñе обиде да ви наплати пари</translation>
<translation id="5355557959165512791">Ðе може да го поÑетите <ph name="SITE" /> во моментов затоа што неговиот Ñертификат е повлечен. Грешките на мрежата и нападите обично Ñе привремени, така што Ñтраницава веројатно ќе работи подоцна.</translation>
<translation id="536296301121032821">Ðе уÑпеа да Ñкладира поÑтавки за правило</translation>
+<translation id="5363309033720083897">СериÑка порта што ја дозволил вашиот админиÑтратор</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="5386426401304769735">Синџирот Ñо Ñертификати за Ñајтов Ñодржи Ñертификат потпишан Ñо SHA-1.</translation>
@@ -1189,6 +1222,7 @@
<translation id="5398772614898833570">Рекламите Ñе блокирани</translation>
<translation id="5400836586163650660">Сива</translation>
<translation id="540969355065856584">Серверот не може да докаже дека е <ph name="DOMAIN" />; неговиот безбедноÑен Ñертификат не е важечки во моментов. Тоа може да Ñе должи на погрешна конфигурација или на напаѓач што го преÑретнува поврзувањето.</translation>
+<translation id="541143247543991491">Облак (на целиот ÑиÑтем)</translation>
<translation id="541416427766103491">Фиока за Ñкладирање 4</translation>
<translation id="5421136146218899937">ИÑчиÑти податоци од прелиÑтување…</translation>
<translation id="5426179911063097041"><ph name="SITE" /> Ñака да ви иÑпраќа извеÑтувања</translation>
@@ -1202,6 +1236,7 @@
<translation id="5455374756549232013">Лош временÑки печат на правилата</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" />}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="5463625433003343978">Се бараат уреди…</translation>
<translation id="5469868506864199649">италијанÑки</translation>
<translation id="5470861586879999274">&amp;Повтори уредување</translation>
<translation id="5478437291406423475">B6/C4 (плик)</translation>
@@ -1251,7 +1286,6 @@
<translation id="5624120631404540903">Управувај Ñо лозинки</translation>
<translation id="5629630648637658800">Ðе уÑпеаја да Ñе вчитаат поÑтавките за политика</translation>
<translation id="5631439013527180824">Ðевалиден токен за управување Ñо уреди</translation>
-<translation id="5632627355679805402">Податоците Ñе шифрирани Ñо вашата <ph name="BEGIN_LINK" />лозинка за Google<ph name="END_LINK" /> почнувајќи од <ph name="TIME" />. ВнеÑете ја за да започне Ñинхронизацијата.</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="5644090287519800334">Промена на Ñтраната 1 на Ñликата X</translation>
@@ -1290,12 +1324,12 @@
<translation id="5785756445106461925">Понатаму, Ñтраницава опфаќа други реÑурÑи што не Ñе безбедни. Ðив може да ги гледаат други лица при преноÑот и може да ги менува напаѓач за да го Ñмени изгледот на Ñтраницата.</translation>
<translation id="5786044859038896871">Дали Ñакате да ги пополните информациите од картичката?</translation>
<translation id="578633867165174378">Chrome ја најде лозинката која штотуку ја употребивте меѓу лозинките откриени при упад во податоците. Ви препорачуваме веднаш да ја промените.</translation>
-<translation id="5798290721819630480">Дали да Ñе отфрлат промените?</translation>
<translation id="5803412860119678065">Дали Ñакате да пополните <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Дозволи</translation>
<translation id="5804427196348435412">КориÑти NFC-уреди</translation>
<translation id="5810442152076338065">Поврзувањето Ñо <ph name="DOMAIN" /> е шифрирано Ñо кориÑтење заÑтарена група шифри.</translation>
<translation id="5813119285467412249">&amp;Повтори додавање</translation>
+<translation id="5817918615728894473">Спари</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Кога плаќате, ќе Ñе наплати од оваа картичка, но нејзиниот виÑтинÑки број нема да Ñе Ñподели Ñо Ñајтов. За дополнителна безбедноÑÑ‚, ќе Ñе Ñоздаде привремен CVC.}one{Кога плаќате, ќе Ñе наплати од картичката што ќе ја изберете, но нејзиниот виÑтинÑки број нема да Ñе Ñподели Ñо Ñајтов. За дополнителна безбедноÑÑ‚, ќе Ñе Ñоздаде привремен CVC.}other{Кога плаќате, ќе Ñе наплати од картичката што ќе ја изберете, но нејзиниот виÑтинÑки број нема да Ñе Ñподели Ñо Ñајтов. За дополнителна безбедноÑÑ‚, ќе Ñе Ñоздаде привремен CVC.}}</translation>
<translation id="5826507051599432481">ЧеÑто име (CN)</translation>
<translation id="5838278095973806738">Ðе треба да внеÑувате чувÑтвителни информации на овој Ñајт (на пример, лозинки или кредитни картички), затоа што може да ги украдат напаѓачи.</translation>
@@ -1303,6 +1337,7 @@
<translation id="5855253129151731373">Името на хоÑтот на Ñајтов изгледа Ñлично Ñо <ph name="LOOKALIKE_DOMAIN" />. Ðапаѓачите понекогаш имитираат Ñајтови, така што вршат мали, тешко забележливи промени во името на доменот.
Ðко Ñметате дека ова ви Ñе прикажува по грешка, одете на https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">ИÑклучено</translation>
<translation id="5862579898803147654">Фиока за Ñкладирање 8</translation>
<translation id="5863847714970149516">Страницата што ќе Ñе појави може да Ñе обиде да ви наплати пари</translation>
<translation id="5866257070973731571">Додајте телефонÑки број</translation>
@@ -1319,6 +1354,7 @@
<translation id="5913377024445952699">Снимањето на екранот е паузирано</translation>
<translation id="59174027418879706">Овозможено</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 е во употреба}one{# е во употреба}other{# Ñе во употреба}}</translation>
<translation id="5921185718311485855">Вклучено</translation>
<translation id="5921639886840618607">Да Ñе зачува картичката на Ñметката на Google?</translation>
<translation id="5922853866070715753">РечиÑи готово</translation>
@@ -1338,6 +1374,7 @@
<translation id="5989320800837274978">Ðе Ñе наведени ниту прокÑи-Ñервери ниту URL на Ñкрипта .pac.</translation>
<translation id="5992691462791905444">ИнженерÑко Z-превиткување</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> резултати за „<ph name="SEARCH_TEXT" />“</translation>
+<translation id="6006484371116297560">КлаÑична</translation>
<translation id="6008122969617370890">РедоÑлед N-до-1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Проверете ги лозинките</translation>
@@ -1359,6 +1396,7 @@
<translation id="6045164183059402045">Шаблон за лепење</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="6049004884579590341">ПритиÑнете и задржете |<ph name="ACCELERATOR" />| за да излезете од цел екран</translation>
<translation id="6049488691372270142">ИÑпечатена Ñтраница</translation>
<translation id="6051221802930200923">Ðе може да го поÑетите <ph name="SITE" /> во моментов затоа што веб-Ñајтот кориÑти закачување Ñертификати. Грешките на мрежата и нападите обично Ñе привремени, така што Ñтраницава веројатно ќе работи подоцна.</translation>
<translation id="6051898664905071243">Број на Ñтраници:</translation>
@@ -1375,6 +1413,7 @@
<translation id="610911394827799129">Вашата Ñметка на Google можеби има други видови иÑторија на прелиÑтување на <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
<translation id="6116338172782435947">гледа текÑÑ‚ и Ñлики копирани на привремената меморија</translation>
<translation id="6120179357481664955">Да Ñе запомни ID за UPI?</translation>
+<translation id="6123290840358279103">Прикажи ја виртуелната картичка</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Проверете ги каблите и реÑтартирајте ги рутерите, модемите или другите мрежни
уреди што ги кориÑтите.</translation>
@@ -1411,6 +1450,7 @@
<translation id="6289939620939689042">Боја на Ñтраницата</translation>
<translation id="6290238015253830360">Предложените Ñтатии ќе Ñе појавуваат тука</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Се запира „Помошникот на Google“ во Chrome</translation>
<translation id="6305205051461490394"><ph name="URL" /> е недоÑтапна.</translation>
<translation id="6312113039770857350">Веб-Ñтраницата не е доÑтапна</translation>
@@ -1436,6 +1476,7 @@
<translation id="6390200185239044127">Z-превиткување на половина</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Лепењето од <ph name="ORIGIN_NAME" /> на локацијава е блокирано Ñо правило на админиÑтраторот</translation>
+<translation id="6398765197997659313">Излези од цел екран</translation>
<translation id="6401136357288658127">Правилово е неподдржано. ÐамеÑто него, треба да го кориÑтите правилото <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Измени обележувач</translation>
<translation id="6406765186087300643">C0 (плик)</translation>
@@ -1448,7 +1489,6 @@
<translation id="6428450836711225518">Потврдете го телефонÑкиот број</translation>
<translation id="6433490469411711332">Уредете ги информациите за контакт</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> одби да Ñе поврзе.</translation>
-<translation id="6434309073475700221">Отфрли</translation>
<translation id="6440503408713884761">Игнориран</translation>
<translation id="6443406338865242315">кои екÑтензии и приклучоци ги имате инÑталирано</translation>
<translation id="6446163441502663861">Kahu (плик)</translation>
@@ -1491,6 +1531,7 @@
<translation id="6624427990725312378">Информации за контакт</translation>
<translation id="6626291197371920147">Додајте валиден број на картичка</translation>
<translation id="6628463337424475685">Пребарување на <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Се бараат USB-уреди…</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ИÑчиÑти</translation>
@@ -1506,6 +1547,7 @@
<translation id="6671697161687535275">Да Ñе отÑтранат предлозите за формулари од Chromium?</translation>
<translation id="6685834062052613830">Одјавете Ñе и завршете го поÑтавувањето</translation>
<translation id="6687335167692595844">Побарана е големина на фонтот</translation>
+<translation id="6688743156324860098">Ðжурирајте…</translation>
<translation id="6689249931105087298">Релативна, Ñо компреÑија на црни точки</translation>
<translation id="6689271823431384964">Chrome нуди да ви ги зачува картичките во вашата Ñметка на Google бидејќи Ñте најавени. Ваквото однеÑување може да го Ñмените во поÑтавки. Името на ÑопÑтвеникот на картичката доаѓа од Ñметката.</translation>
<translation id="6698381487523150993">Создадено:</translation>
@@ -1521,6 +1563,7 @@
<translation id="6744009308914054259">Додека чекате врÑка, може да одите во „Преземања“ за да ги прочитате офлајн Ñтатиите.</translation>
<translation id="6753269504797312559">ВредноÑÑ‚ на политика</translation>
<translation id="6757797048963528358">Уредот е во режим на Ñпиење.</translation>
+<translation id="6767985426384634228">Да Ñе ажурира адреÑата?</translation>
<translation id="6768213884286397650">Hagaki (разгледница)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Виолетова</translation>
@@ -1543,6 +1586,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome ја поедноÑтави Ñтраницава за да биде полеÑна за читање. Chrome ја презеде оригиналната Ñтраница преку небезбедна врÑка.</translation>
<translation id="6891596781022320156">Ðивото на политика не е поддржано.</translation>
+<translation id="6895143722905299846">Виртуелен број:</translation>
<translation id="6895330447102777224">Вашата картичка е потврдена</translation>
<translation id="6897140037006041989">КориÑнички агент</translation>
<translation id="6898699227549475383">Организација (O)</translation>
@@ -1578,10 +1622,10 @@
<translation id="7004583254764674281">КориÑтете Windows Hello за побрзо потврдување на картичките</translation>
<translation id="7006930604109697472">Сепак иÑпрати</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ПоÑтавки за промена на големината</translation>
<translation id="7014741021609395734">Ðиво на зумирање</translation>
<translation id="7016992613359344582">Овие трошоци може да бидат еднократни или повторливи и може нема да бидат очигледни.</translation>
<translation id="7029809446516969842">Лозинки</translation>
+<translation id="7030436163253143341">Сертификатот е неважечки</translation>
<translation id="7031646650991750659">кои апликации од Google Play Ñте ги инÑталирале</translation>
<translation id="7050187094878475250">Се обидовте да Ñтигнете до <ph name="DOMAIN" />, но Ñерверот прикажа Ñертификат Ñо период на важноÑÑ‚ што е премногу долг за да му Ñе верува.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Картичкава не може да Ñе зачува во моментов}one{Картичкиве не може да Ñе зачуваат во моментов}other{Картичкиве не може да Ñе зачуваат во моментов}}</translation>
@@ -1651,12 +1695,14 @@
<translation id="7300012071106347854">Сина како кобалт</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />“</translation>
<translation id="7304030187361489308">ВиÑок</translation>
+<translation id="7305756307268530424">Стартувај побавно</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Помош за поврзување</translation>
<translation id="7323804146520582233">Сокриј го делот „<ph name="SECTION" />“</translation>
<translation id="733354035281974745">Отфрлање на локалната Ñметка на уредот</translation>
<translation id="7333654844024768166">Тукушто ја внеÑовте Ñвојата лозинка на измамнички Ñајт. Chromium препорачува да одите на <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> и на други Ñајтови каде што ја кориÑтите лозинкава и да ја промените веднаш.</translation>
<translation id="7334320624316649418">&amp;Повтори преуредување</translation>
+<translation id="7337248890521463931">Прикажи повеќе редови</translation>
<translation id="7337706099755338005">Ðе е доÑтапен на вашата платформа.</translation>
<translation id="733923710415886693">Сертификатот на Ñерверот не е откриен преку ТранÑпарентноÑÑ‚ на Ñертификати.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1664,6 +1710,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Командна линија</translation>
<translation id="7359588939039777303">Рекламите Ñе блокирани.</translation>
+<translation id="7363096869660964304">Сепак, не Ñте невидливи. Режимот „Инкогнито“ не го Ñокрива вашето прелиÑтување од работодавецот, интернет-операторот, ниту од веб-Ñајтовите што ги поÑетувате.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, притиÑнете Tab, па Enter за да додавате и да управувате Ñо адреÑи во поÑтавките за Chrome</translation>
<translation id="7365849542400970216">Да Ñе знае кориÑтењето на уредот?</translation>
<translation id="7372973238305370288">резултат од пребарувањето</translation>
@@ -1674,7 +1721,9 @@
<translation id="7378594059915113390">Контроли за аудиовизуелни медиуми</translation>
<translation id="7378627244592794276">Ðе</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ðе е применливо</translation>
<translation id="7390545607259442187">Потврдете ја картичката</translation>
+<translation id="7392089738299859607">Ðжурирајте ја адреÑата</translation>
<translation id="7399802613464275309">Проверка на безбедноÑта</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Вашиот <ph name="DEVICE_NAME" /> е управуван</translation>
@@ -1689,6 +1738,7 @@
&lt;li&gt;ПоÑетете го &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Центарот за помош на Chrome&lt;/a&gt; за да дознаете како трајно да го отÑтраните Ñофтверот од компјутерот
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Убав</translation>
<translation id="7416351320495623771">Управувајте Ñо лозинките…</translation>
<translation id="7419106976560586862">Патека на профилот</translation>
<translation id="7437289804838430631">Додајте информации за контакт</translation>
@@ -1704,7 +1754,7 @@
<translation id="7481312909269577407">Ðапред</translation>
<translation id="7485870689360869515">Ðе Ñе пронајдени податоци.</translation>
<translation id="7495528107193238112">Содржинава е блокирана. Контактирајте Ñо ÑопÑтвеникот на Ñајтот за поправка на проблемот.</translation>
-<translation id="7498234416455752244">Продолжете да изменувате</translation>
+<translation id="7498193950643227031">Може да Ñе однеÑува неочекувано ако Ñе промени големината. Сега може да ја ограничите ÑпоÑобноÑта за менување големина на апликациите во <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Тукушто ја внеÑовте Ñвојата лозинка на измамнички Ñајт. Chromium препорачува веднаш да ги проверите зачуваните лозинки за <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> и другите Ñајтови каде што ја кориÑтите лозинкава.</translation>
<translation id="7508255263130623398">Вратениот id на уредот на правилото е празен или не ÑоодветÑтвува Ñо тековниот id на уредот</translation>
<translation id="7508870219247277067">Зелена како авокадо</translation>
@@ -1724,6 +1774,7 @@
<translation id="7548892272833184391">Поправање грешки при поврзувањето</translation>
<translation id="7549584377607005141">Веб-Ñтраницава бара податоци кои Ñте ги внеле претходно за правилно да Ñе прикаже. Може повторно да ги иÑпратите податоците, но Ñо тоа ќе ги повторите Ñите дејÑтва што претходно ги извршила Ñтраницата.</translation>
<translation id="7550637293666041147">КориÑничкото име на вашиот уред и кориÑничкото име на Chrome</translation>
+<translation id="755279583747225797">Пробната верзија е активна</translation>
<translation id="7552846755917812628">ИÑпробајте ги Ñледните Ñовети:</translation>
<translation id="7554475479213504905">Вчитај повторно и Ñепак прикажи</translation>
<translation id="7554791636758816595">Ðова картичка</translation>
@@ -1742,7 +1793,6 @@
<translation id="7610193165460212391">ВредноÑта е надвор од опÑегот <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">ИÑтекува: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, притиÑнете Tab, а потоа Enter за да ги прегледувате и да управувате Ñо вашите лозинки во поÑтавките за Chrome</translation>
-<translation id="7615602087246926389">Веќе имате податоци кои Ñе шифрирани Ñо различна верзија на лозинката на вашата Ñметка на Google. ВнеÑете ја подолу.</translation>
<translation id="7616645509853975347">ÐдминиÑтраторот вклучил Chrome Enterprise Connectors на вашиот прелиÑтувач. Овие конектори имаат приÑтап до дел од вашите податоци.</translation>
<translation id="7619838219691048931">Краен лиÑÑ‚</translation>
<translation id="762844065391966283">Еден по еден</translation>
@@ -1807,13 +1857,12 @@
<translation id="782886543891417279">Wi-Fi што го кориÑтите (<ph name="WIFI_NAME" />) може да бара да ја поÑетите Ñтраницата за најавување.</translation>
<translation id="7836231406687464395">Postfix (плик)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ðишто}=1{1 апликација (<ph name="EXAMPLE_APP_1" />)}=2{2 апликации (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# апликација (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# апликации (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Ðо, не Ñте невидливи. Инкогнито не го Ñокрива вашето прелиÑтување од работодавецот, интернет операторот или веб-Ñајтовите што ги поÑетувате.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Отворајте датотеки Ñо аÑоцијации за тип датотека.</translation>
<translation id="7862185352068345852">Да Ñе напушти ли Ñајтот?</translation>
<translation id="7865448901209910068">Ðајдобра брзина</translation>
<translation id="7874263914261512992">Тукушто ја внеÑовте Ñвојата лозинка на измамнички Ñајт. Chrome препорачува веднаш да ги проверите зачуваните лозинки за <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> и другите Ñајтови каде што ја кориÑтите лозинкава.</translation>
<translation id="7878562273885520351">Можно е да ви е компромитирана лозинката</translation>
+<translation id="7880146494886811634">Зачувајте ја адреÑата</translation>
<translation id="7882421473871500483">Кафеава</translation>
<translation id="7887683347370398519">Проверете го КВК и обидете Ñе повторно.</translation>
<translation id="7887885240995164102">Влези во „Слика во Ñлика“</translation>
@@ -1821,6 +1870,7 @@
<translation id="7894280532028510793">Ðко правопиÑот е точен, <ph name="BEGIN_LINK" />извршете дијагноÑтика на мрежата<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (плик)</translation>
<translation id="7931318309563332511">Ðепознат</translation>
+<translation id="793209273132572360">Да Ñе ажурира адреÑата?</translation>
<translation id="7932579305932748336">Омот</translation>
<translation id="79338296614623784">ВнеÑете важечки телефонÑки број</translation>
<translation id="7934052535022478634">Плаќањето е завршено</translation>
@@ -1831,7 +1881,7 @@
<translation id="7938958445268990899">Сертификатот на Ñерверот ÑÑ ÑƒÑˆÑ‚Ðµ не е важечки.</translation>
<translation id="7942349550061667556">Црвена</translation>
<translation id="7947285636476623132">Проверете ја годината на иÑтекување и обидете Ñе повторно</translation>
-<translation id="7950027195171824198">Управувајте Ñо претпочитаните вредноÑти за колачиња во поÑтавките за Chrome</translation>
+<translation id="7950027195171824198">Управувајте Ñо поÑтавките за колачиња во поÑтавките на Chrome</translation>
<translation id="7951415247503192394">(32-бита)</translation>
<translation id="7953569069500808819">Шиење на работ горе</translation>
<translation id="7956713633345437162">Мобилни обележувачи</translation>
@@ -1891,6 +1941,7 @@
<translation id="8175796834047840627">Chrome нуди да ви ги зачува картичките во вашата Ñметка на Google бидејќи Ñте најавени. Ваквото однеÑување може да го Ñмените во поÑтавки.</translation>
<translation id="8176440868214972690">ÐдминиÑтраторот на уредов иÑпратил одредени информации на Ñледниве веб-Ñајтови, како поÑтавки или правила.</translation>
<translation id="8184538546369750125">КориÑти глобална Ñтандардна поÑтавка (Дозволи)</translation>
+<translation id="8193086767630290324">ДејÑтвата преземени Ñо податоци означени како доверливи</translation>
<translation id="8194797478851900357">&amp;Врати премеÑтување</translation>
<translation id="8201077131113104583">Ðеважечка URL на ажурирање за наÑтавката Ñо ИД „<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Краток преглед на нарачка</translation>
@@ -1913,6 +1964,7 @@
<translation id="8249296373107784235">Прекини</translation>
<translation id="8249320324621329438">ПоÑледно земено:</translation>
<translation id="8253091569723639551">ÐдреÑата за наплата е задолжителна</translation>
+<translation id="8257387598443225809">Ðпликацијава е дизајнирана за мобилен</translation>
<translation id="825929999321470778">Прикажи ги Ñите зачувани лозинки</translation>
<translation id="8261506727792406068">Избриши</translation>
<translation id="8262952874573525464">Шиење на работ долу</translation>
@@ -1961,7 +2013,7 @@
<ph name="DEBUG_INFO" /></translation>
<translation id="8424582179843326029"><ph name="FIRST_LABEL" /> <ph name="SECOND_LABEL" /> <ph name="THIRD_LABEL" /></translation>
<translation id="8428213095426709021">ПоÑтавки</translation>
-<translation id="8431194080598727332"><ph name="MANAGE_COOKIES_FOCUSED_FRIENDLY_MATCH_TEXT" />, притиÑнете Tab, па Enter за да управувате Ñо претпочитаните вредноÑти за колачиња во поÑтавките за Chrome</translation>
+<translation id="8431194080598727332"><ph name="MANAGE_COOKIES_FOCUSED_FRIENDLY_MATCH_TEXT" />, притиÑнете Tab, па Enter за да управувате Ñо поÑтавките за колачиња во поÑтавките на Chrome</translation>
<translation id="8433057134996913067">Ова ќе ве одјави од повеќето веб-Ñајтови.</translation>
<translation id="8437238597147034694">&amp;Врати премеÑтување</translation>
<translation id="8438786541497918448">Да Ñе кориÑтат камерата и микрофонот?</translation>
@@ -2036,7 +2088,6 @@
<translation id="8719528812645237045">Повеќе дупки горе</translation>
<translation id="8725066075913043281">Обидете Ñе повторно</translation>
<translation id="8726549941689275341">Големина на Ñтраницата:</translation>
-<translation id="8728672262656704056">Се наоѓате во режим инкогнито</translation>
<translation id="8730621377337864115">Готово</translation>
<translation id="8731544501227493793">Копче „Управувајте Ñо лозинките“, притиÑнете Enter за да ги прегледувате и да управувате Ñо вашите лозинки во поÑтавките за Chrome</translation>
<translation id="8734529307927223492"><ph name="MANAGER" /> управува Ñо вашиот <ph name="DEVICE_TYPE" /></translation>
@@ -2113,6 +2164,7 @@
<translation id="9020542370529661692">Страницава е преведена на <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Ðеважечки)</translation>
+<translation id="9030265603405983977">МонохроматÑки</translation>
<translation id="9035022520814077154">БезбедноÑна грешка</translation>
<translation id="9038649477754266430">КориÑтете уÑлуга за предвидување за да ги вчитате Ñтраниците побрзо</translation>
<translation id="9039213469156557790">Понатаму, Ñтраницава опфаќа други реÑурÑи што не Ñе безбедни. Ðив може да ги гледаат други лица при преноÑот и може да ги менува напаѓач за да го Ñмени однеÑувањето на Ñтраницата.</translation>
@@ -2136,6 +2188,7 @@
<translation id="91108059142052966">Политиката на админиÑтраторот оневозможува Ñподелување екран Ñо <ph name="APPLICATION_TITLE" /> кога Ñе видливи доверливи Ñодржини</translation>
<translation id="9114524666733003316">Се потврдува картичката…</translation>
<translation id="9114581008513152754">ПрелиÑтувачов не е управуван од компанија или друга организација. ÐктивноÑта на уредов можеби Ñе управува надвор од Chrome. <ph name="BEGIN_LINK" />Дознајте повеќе<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Свеж</translation>
<translation id="9119042192571987207">Прикачен</translation>
<translation id="9128016270925453879">Правилата Ñе вчитани</translation>
<translation id="9128870381267983090">Поврзете Ñе на мрежа</translation>
@@ -2154,6 +2207,7 @@
<translation id="9170848237812810038">&amp;Врати</translation>
<translation id="9171296965991013597">Дали да Ñе излезе од апликацијата?</translation>
<translation id="9173282814238175921">Еден документ/нов лиÑÑ‚</translation>
+<translation id="9173995187295789444">Скенира за уреди Ñо Bluetooth…</translation>
<translation id="917450738466192189">Сертификатот на Ñерверот е неважечки.</translation>
<translation id="9174917557437862841">Копче за префрлање помеѓу картички, притиÑнете Enter за да Ñе префрлите во картичкава</translation>
<translation id="9179703756951298733">Управувајте Ñо плаќањата и податоците за кредитните картички во поÑтавките за Chrome</translation>
diff --git a/chromium/components/strings/components_strings_ml.xtb b/chromium/components/strings/components_strings_ml.xtb
index c6412e06709..ffa10037d21 100644
--- a/chromium/components/strings/components_strings_ml.xtb
+++ b/chromium/components/strings/components_strings_ml.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">പരിശോധിചàµà´šàµ†à´™àµà´•à´¿àµ½, വേഗതേറിയ ഫോം പൂരിപàµà´ªà´¿à´•àµà´•à´²à´¿à´¨à´¾à´¯à´¿ à´ˆ ഉപകരണതàµà´¤à´¿àµ½ നിങàµà´™à´³àµà´Ÿàµ† കാർഡിനàµà´±àµ† ഒരൠപകർപàµà´ªàµ Chrome സംഭരികàµà´•àµà´‚.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> à´Žà´¨àµà´¨à´¤à´¿à´¨àµâ€à´±àµ† à´…à´¨àµà´®à´¤à´¿ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•</translation>
<translation id="1113869188872983271">&amp;à´ªàµà´¨à´ƒà´•àµà´°à´®àµ€à´•à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤àµ പഴയപടിയാകàµà´•àµà´•</translation>
+<translation id="1123753900084781868">തതàµà´¸à´®à´¯ à´•àµà´¯à´¾à´ªàµà´·àµ» ഇപàµà´ªàµ‹àµ¾ ലഭàµà´¯à´®à´²àµà´²</translation>
<translation id="1125573121925420732">വെബàµâ€Œà´¸àµˆà´±àµà´±àµà´•àµ¾ അവയàµà´Ÿàµ† à´¸àµà´°à´•àµà´· à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´¨àµà´¨ സമയതàµà´¤àµ പൊതàµà´µàµ† à´®àµà´¨àµà´¨à´±à´¿à´¯à´¿à´ªàµà´ªàµà´•àµ¾ കാണിചàµà´šàµ‡à´•àµà´•à´¾à´‚. ഇതൠതാമസിയാതെ മെചàµà´šà´ªàµà´ªàµ†à´Ÿàµà´‚.</translation>
<translation id="112840717907525620">നയ കാഷെ ശരി</translation>
<translation id="1130564665089811311">'പേജൠവിവർതàµà´¤à´¨à´‚ ചെയàµà´¯àµà´•' ബടàµà´Ÿàµº, Google Translate ഉപയോഗിചàµà´šàµ à´ˆ പേജൠവിവർതàµà´¤à´¨à´‚ ചെയàµà´¯à´¾àµ» 'Enter' അമർതàµà´¤àµà´•</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">നിങàµà´™à´³àµà´Ÿàµ† ഉപകരണതàµà´¤à´¿àµ»àµà´±àµ† പേരàµ</translation>
<translation id="124116460088058876">കൂടàµà´¤àµ½ ഭാഷകൾ</translation>
<translation id="1243027604378859286">രചയിതാവàµ:</translation>
+<translation id="1246424317317450637">ബോളàµâ€à´¡àµ</translation>
<translation id="1250759482327835220">à´…à´Ÿàµà´¤àµà´¤ à´ªàµà´°à´¾à´µà´¶àµà´¯à´‚ കൂടàµà´¤àµ½ വേഗതàµà´¤à´¿àµ½ പണമടയàµà´•àµà´•à´¾àµ», നിങàµà´™à´³àµà´Ÿàµ† Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ കാർഡàµ, പേരàµ, ബിലàµà´²à´¿à´‚ഗൠവിലാസം à´Žà´¨àµà´¨à´¿à´µ സംരകàµà´·à´¿à´•àµà´•àµà´•.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (സമനàµà´µà´¯à´¿à´ªàµà´ªà´¿à´šàµà´šàµ)</translation>
<translation id="1256368399071562588">&lt;p&gt;നിങàµà´™à´³àµŠà´°àµ വെബàµâ€Œà´¸àµˆà´±àµà´±àµ സനàµà´¦àµ¼à´¶à´¿à´•àµà´•à´¾àµ» à´¶àµà´°à´®à´¿à´•àµà´•àµà´•à´¯àµà´‚ അതൠതàµà´±à´•àµà´•à´¾à´¤à´¿à´°à´¿à´•àµà´•àµà´•à´¯àµà´®à´¾à´£àµ†à´™àµà´•à´¿àµ½, ഇനിപàµà´ªà´±à´¯àµà´¨àµà´¨ à´Ÿàµà´°à´¬à´¿à´³àµâ€à´·àµ‚à´Ÿàµà´Ÿà´¿à´‚ഗൠഘടàµà´Ÿà´™àµà´™àµ¾ ഉപയോഗിചàµà´šàµ, à´ªàµà´°à´¶àµà´¨à´‚ പരിഹരികàµà´•à´¾àµ» à´¶àµà´°à´®à´¿à´•àµà´•àµà´•:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">നിങàµà´™à´³àµà´Ÿàµ† പാസàµâ€Œà´µàµ‡à´¡àµ മാറàµà´±àµà´•</translation>
<translation id="1484290072879560759">à´·à´¿à´ªàµà´ªà´¿à´‚ഗൠവിലാസം തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•</translation>
<translation id="1492194039220927094">നയങàµà´™àµ¾ à´ªàµà´·àµ ചെയàµà´¯àµ½:</translation>
+<translation id="1495677929897281669">ടാബിലേകàµà´•àµ മടങàµà´™àµà´•</translation>
<translation id="1501859676467574491">നിങàµà´™à´³àµà´Ÿàµ† Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ നിനàµà´¨àµ കാർഡàµà´•àµ¾ കാണികàµà´•àµà´•</translation>
<translation id="1507202001669085618">&lt;p&gt;ഓൺലൈൻ ആകàµà´¨àµà´¨à´¤à´¿à´¨àµ സൈൻ ഇൻ ചെയàµà´¯àµ‡à´£àµà´Ÿà´¿ വരàµà´¨àµà´¨ ഒരൠവൈഫൈ പോർടàµà´Ÿà´²à´¾à´£àµ നിങàµà´™àµ¾ ഉപയോഗികàµà´•àµà´¨àµà´¨à´¤àµ†à´™àµà´•à´¿àµ½, നിങàµà´™àµ¾ à´ˆ പിശകൠകാണàµà´‚.&lt;/p&gt;
&lt;p&gt;പിശകൠപരിഹരികàµà´•à´¾àµ», നിങàµà´™àµ¾ à´¤àµà´±à´•àµà´•à´¾àµ» à´¶àµà´°à´®à´¿à´•àµà´•àµà´¨àµà´¨ പേജിൽ &lt;strong&gt;കണകàµâ€Œà´±àµà´±àµ ചെയàµà´¯àµà´•&lt;/strong&gt; à´•àµà´²à´¿à´•àµà´•àµ ചെയàµà´¯àµà´•.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">à´ˆ പേജൠപറയàµà´¨àµà´¨à´¤àµ:</translation>
<translation id="153384715582417236">ഇപàµà´ªàµ‹àµ¾ ഇതàµà´°à´®à´¾à´¤àµà´°à´‚ ലഭàµà´¯à´‚</translation>
<translation id="1536390784834419204">പേജൠവിവർതàµà´¤à´¨à´‚ ചെയàµà´¯àµà´•</translation>
+<translation id="1539840569003678498">റിപàµà´ªàµ‡à´¾àµ¼à´Ÿàµà´Ÿàµ അയചàµà´šàµ:</translation>
<translation id="154408704832528245">ഡെലിവറി നൽകേണàµà´Ÿ വിലാസം തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•</translation>
<translation id="1549470594296187301">à´ˆ ഫീചàµà´šàµ¼ ഉപയോഗികàµà´•à´¾àµ» JavaScript à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´•àµà´·à´®à´®à´¾à´•àµà´•à´¿à´¯à´¿à´°à´¿à´•àµà´•à´£à´‚.</translation>
<translation id="155039086686388498">à´Žà´žàµà´šà´¿à´¨àµ€à´¯à´±à´¿à´‚à´—àµ-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">നീളം à´•àµà´±à´žàµà´ž അരികൠആദàµà´¯à´‚</translation>
<translation id="168693727862418163">à´ˆ നയ മൂലàµà´¯à´‚ അതിനàµà´±àµ† à´¸àµâ€Œà´•àµ€à´®à´¯àµà´®à´¾à´¯à´¿ സാധൂകരികàµà´•à´¾àµ» കഴിയാതàµà´¤à´¤à´¿à´¨à´¾àµ½ അതൠഅവഗണികàµà´•à´ªàµà´ªàµ†à´Ÿàµà´‚.</translation>
<translation id="168841957122794586">സെർവർ സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±à´¿àµ½ ഒരൠദàµàµ¼à´¬à´²à´®à´¾à´¯ ഗൂഢഭാഷ കീ ഉൾപàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµ.</translation>
+<translation id="1696290444144917273">വെർചàµà´µàµ½ കാർഡൠവിശദാംശങàµà´™àµ¾ കാണàµà´•</translation>
<translation id="1697532407822776718">à´Žà´²àµà´²à´¾à´‚ സജàµà´œà´®à´¾à´¯à´¿à´•àµà´•à´´à´¿à´žàµà´žàµ!</translation>
<translation id="1703835215927279855">ലെറàµà´±àµ¼</translation>
<translation id="1706954506755087368">{1,plural, =1{à´ˆ സെർവറിനൠഇതൠ<ph name="DOMAIN" /> ആണെനàµà´¨àµ തെളിയികàµà´•à´¾à´¨à´¾à´¯à´¿à´²àµà´²; അതിനàµà´±àµ† à´¸àµà´°à´•àµà´·à´¾ സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ ഇനàµà´¨à´²àµ† à´®àµà´¤àµ½ സാധàµà´µà´²àµà´². തെറàµà´±à´¾à´¯ കോൺഫിഗറേഷൻ കാരണമോ ഒരൠആകàµà´°à´®à´£à´•à´¾à´°à´¿ നിങàµà´™à´³àµà´Ÿàµ† കണകàµà´·à´¨àµ† തടസàµà´¸à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´¨àµà´¨à´¤àµ കൊണàµà´Ÿàµ‹ ആയിരികàµà´•à´¾à´‚ ഇതൠസംഭവിചàµà´šà´¤àµ.}other{à´ˆ സെർവറിനൠഇതൠ<ph name="DOMAIN" /> ആണെനàµà´¨àµ തെളിയികàµà´•à´¾à´¨à´¾à´¯à´¿à´²àµà´²; അതിനàµà´±àµ† à´¸àµà´°à´•àµà´·à´¾ സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ # ദിവസം à´®àµà´¤àµ½ സാധàµà´µà´¾à´¯à´¿à´°à´¿à´•àµà´•à´¿à´²àµà´². തെറàµà´±à´¾à´¯ കോൺഫിഗറേഷൻ കാരണമോ ഒരൠആകàµà´°à´®à´£à´•à´¾à´°à´¿ നിങàµà´™à´³àµà´Ÿàµ† കണകàµà´·à´¨àµ† തടസàµà´¸à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´¨àµà´¨à´¤àµ കൊണàµà´Ÿàµ‹ ആയിരികàµà´•à´¾à´‚ ഇതൠസംഭവിചàµà´šà´¤àµ.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> à´Žà´¨àµà´¨à´¤àµ <ph name="VALUE" /> ആയി സജàµà´œàµ€à´•à´°à´¿à´šàµà´šà´¿à´Ÿàµà´Ÿà´¿à´²àµà´²à´¾à´¤àµà´¤à´¤à´¿à´¨à´¾àµ½ അവഗണിചàµà´šàµ.</translation>
<translation id="1712552549805331520">നിങàµà´™à´³àµà´Ÿàµ† ലോകàµà´•àµ½ à´•à´®àµà´ªàµà´¯àµ‚à´Ÿàµà´Ÿà´±à´¿à´²àµâ€ ശാശàµà´µà´¤à´®à´¾à´¯à´¿ ഡാറàµà´± സംഭരികàµà´•à´¾à´¨àµâ€ <ph name="URL" /> ആഗàµà´°à´¹à´¿à´•àµà´•àµà´¨àµà´¨àµ</translation>
<translation id="1713628304598226412">à´Ÿàµà´°àµ‡ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">മെയിൽബോകàµà´¸àµ 3</translation>
<translation id="1718029547804390981">അനോടàµà´Ÿàµ‡à´±àµà´±àµ ചെയàµà´¯à´¾à´¨à´¾à´µàµà´¨àµà´¨à´¤à´¿à´²àµà´‚ വളരെ വലàµà´¤à´¾à´£àµ à´ˆ ഡോകàµà´¯àµà´®àµ†àµ»àµà´±àµ</translation>
<translation id="1721424275792716183">* ഫീൽഡൠആവശàµà´¯à´®à´¾à´£àµ</translation>
+<translation id="1727613060316725209">സാധàµà´¤à´¯àµà´³àµà´³ സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±à´¾à´£àµ</translation>
<translation id="1727741090716970331">സാധàµà´µà´¾à´¯ കാർഡൠനമàµà´ªàµ¼ ചേർകàµà´•àµà´•</translation>
<translation id="1728677426644403582">നിങàµà´™àµ¾ ഒരൠവെബൠപേജിനàµà´±àµ† ഉറവിടമാണൠകാണàµà´¨àµà´¨à´¤àµ</translation>
<translation id="173080396488393970">ഇതàµà´¤à´°à´¤àµà´¤à´¿à´²àµà´³àµà´³ കാർഡൠഅനàµà´¯àµ‹à´œàµà´¯à´®à´²àµà´²</translation>
@@ -245,7 +252,6 @@
ശരിയായ രീതിയിൽ തലകàµà´•àµ†à´Ÿàµà´Ÿàµ സജàµà´œàµ€à´•à´°à´¿à´•àµà´•à´¾à´¤àµà´¤à´¤à´¿à´¨à´¾àµ½,
<ph name="SITE" /> à´Žà´¨àµà´¨à´¤à´¿à´¨àµà´³àµà´³ നിങàµà´™à´³àµà´Ÿàµ† à´…à´­àµà´¯àµ¼à´¤àµà´¥à´¨ പൂർതàµà´¤àµ€à´•à´°à´¿à´•àµà´•à´¾àµ» à´¬àµà´°àµ—സറിനൠകഴിയàµà´¨àµà´¨à´¿à´²àµà´². ഒരൠസൈറàµà´±à´¿à´¨àµà´±àµ† à´¸àµà´°à´•àµà´·à´¯àµà´‚ മറàµà´±àµ à´ªàµà´°àµ‹à´ªàµà´ªàµ¼à´Ÿàµà´Ÿà´¿à´•à´³àµà´‚ കോൺഫിഗർ ചെയàµà´¯à´¾àµ» സൈറàµà´±àµ à´“à´ªàµà´ªà´±àµ‡à´±àµà´±àµ¼à´®à´¾àµ¼à´•àµà´•àµ ഉറവിട നയങàµà´™àµ¾ ഉപയോഗികàµà´•à´¾à´¨à´¾à´µàµà´‚.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">നിങàµà´™à´³àµà´Ÿàµ† സമനàµà´µà´¯ പാസàµâ€Œà´«àµà´°àµ‡à´¸àµ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´•.</translation>
<translation id="1787142507584202372">നിങàµà´™àµ¾ നിലവിൽ à´¤àµà´±à´¨àµà´¨à´¿à´Ÿàµà´Ÿàµà´³àµà´³ ടാബàµà´•àµ¾ ഇവിടെ ദൃശàµà´¯à´®à´¾à´•àµà´‚</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, à´’à´¨àµà´¨à´¿à´²à´§à´¿à´•à´‚ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´™àµà´™àµ¾ ലഭàµà´¯à´®à´¾à´£àµ, à´’à´¨àµà´¨à´¿àµ½ നിനàµà´¨àµ മറàµà´±àµŠà´¨àµà´¨à´¿à´²àµ‡à´•àµà´•àµ മാറാൻ 'Tab' അമർതàµà´¤àµà´•</translation>
@@ -278,6 +284,7 @@
<translation id="1919345977826869612">പരസàµà´¯à´™àµà´™à´³àµâ€</translation>
<translation id="1919367280705858090">നിർദàµà´¦à´¿à´·àµà´Ÿ പിശകൠസനàµà´¦àµ‡à´¶à´µàµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´Ÿàµ സഹായം നേടàµà´•</translation>
<translation id="192020519938775529">{COUNT,plural, =0{à´’à´¨àµà´¨àµà´®à´¿à´²àµà´²}=1{ഒരൠസൈറàµà´±àµ}other{# സൈറàµà´±àµà´•àµ¾}}</translation>
+<translation id="1924727005275031552">à´ªàµà´¤à´¿à´¯à´µ</translation>
<translation id="1945968466830820669">നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´¥à´¾à´ªà´¨à´¤àµà´¤à´¿à´¨àµà´±àµ† à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿à´²àµ‡à´•àµà´•àµà´³àµà´³ ആകàµâ€Œà´¸à´¸àµ നഷàµâ€Œà´Ÿà´®à´¾à´•à´¾à´¨àµ‹ à´à´¡à´¨àµâ€à´±à´¿à´±àµà´±à´¿ മോഷàµà´Ÿà´¿à´•àµà´•à´ªàµà´ªàµ†à´Ÿà´¾à´¨àµ‹ സാധàµà´¯à´¤à´¯àµà´£àµà´Ÿàµ. ഇപàµà´ªàµ‹àµ¾ തനàµà´¨àµ† പാസàµâ€à´µàµ‡à´¡àµ മാറàµà´±à´¾àµ» Chromium à´¶àµà´ªà´¾àµ¼à´¶ ചെയàµà´¯àµà´¨àµà´¨àµ.</translation>
<translation id="1947454675006758438">à´®àµà´•à´³à´¿àµ½ വലതàµà´µà´¶à´¤àµà´¤àµ à´¸àµâ€Œà´±àµà´±àµ‡à´ªàµà´ªà´¿àµ¾ ചെയàµà´¯àµà´•</translation>
<translation id="1958218078413065209">നിങàµà´™à´³àµà´Ÿàµ† à´à´±àµà´±à´µàµà´‚ ഉയർനàµà´¨ à´¸àµà´•àµ‹àµ¼ <ph name="SCORE" /> ആണàµ.</translation>
@@ -300,12 +307,14 @@
<translation id="2042213636306070719">à´Ÿàµà´°àµ‡ 7</translation>
<translation id="204357726431741734">നിങàµà´™à´³àµà´Ÿàµ† Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ സംരകàµà´·à´¿à´šàµà´šà´¿à´Ÿàµà´Ÿàµà´³àµà´³ പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ ഉപയോഗികàµà´•à´¾àµ» സൈൻ ഇൻ ചെയàµà´¯àµà´•</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> ഭാഷയിലàµà´³àµà´³ പേജàµà´•àµ¾ വിവർതàµà´¤à´¨à´‚ ചെയàµà´¯à´¿à´²àµà´².</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{à´ˆ നിയനàµà´¤àµà´°à´£à´‚ ഓണായിരികàµà´•àµà´•à´¯àµà´‚ നില 'സജീവം' ആയിരികàµà´•àµà´•à´¯àµà´‚ ആണെങàµà´•à´¿àµ½, നിങàµà´™à´³àµà´Ÿàµ† à´…à´Ÿàµà´¤àµà´¤à´¿à´Ÿàµ†à´¯àµà´³àµà´³ à´¬àµà´°àµ—സിംഗൠആകàµà´±àµà´±à´¿à´µà´¿à´±àµà´±à´¿à´¯àµà´®à´¾à´¯à´¿ à´à´±àµà´±à´µàµà´‚ സാമàµà´¯à´®àµà´³àµà´³ ആളàµà´•à´³àµà´Ÿàµ† à´—àµà´°àµ‚à´ªàµà´ªàµ à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ "സമാന വിഭാഗതàµà´¤à´¿àµ½à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´µàµ¼" à´à´¤à´¾à´£àµ à´Žà´¨àµà´¨àµ Chrome നിർണàµà´£à´¯à´¿à´•àµà´•àµà´¨àµà´¨àµ. പരസàµà´¯à´¦à´¾à´¤à´¾à´•àµà´•àµ¾à´•àµà´•àµ à´—àµà´°àµ‚à´ªàµà´ªà´¿à´¨àµ† കാണികàµà´•à´¾àµ» പരസàµà´¯à´™àµà´™àµ¾ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•à´¾à´¨àµà´‚ നിങàµà´™à´³àµà´Ÿàµ† à´¬àµà´°àµ—സിംഗൠആകàµà´±àµà´±à´¿à´µà´¿à´±àµà´±à´¿ ഉപകരണതàµà´¤à´¿àµ½ à´¸àµà´µà´•à´¾à´°àµà´¯à´®à´¾à´¯à´¿ സൂകàµà´·à´¿à´•àµà´•à´¾à´¨àµà´®à´¾à´•àµà´‚. നിങàµà´™à´³àµà´Ÿàµ† à´—àµà´°àµ‚à´ªàµà´ªàµ à´Žà´²àµà´²à´¾ ദിവസവàµà´‚ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´¨àµà´¨àµ.}=1{à´ˆ നിയനàµà´¤àµà´°à´£à´‚ ഓണായിരികàµà´•àµà´•à´¯àµà´‚ നില 'സജീവം' ആയിരികàµà´•àµà´•à´¯àµà´‚ ആണെങàµà´•à´¿àµ½, നിങàµà´™à´³àµà´Ÿàµ† à´…à´Ÿàµà´¤àµà´¤à´¿à´Ÿàµ†à´¯àµà´³àµà´³ à´¬àµà´°àµ—സിംഗൠആകàµà´±àµà´±à´¿à´µà´¿à´±àµà´±à´¿à´¯àµà´®à´¾à´¯à´¿ à´à´±àµà´±à´µàµà´‚ സാമàµà´¯à´®àµà´³àµà´³ ആളàµà´•à´³àµà´Ÿàµ† à´—àµà´°àµ‚à´ªàµà´ªàµ à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ "സമാന വിഭാഗതàµà´¤à´¿àµ½à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´µàµ¼" à´à´¤à´¾à´£àµ à´Žà´¨àµà´¨àµ Chrome നിർണàµà´£à´¯à´¿à´•àµà´•àµà´¨àµà´¨àµ. പരസàµà´¯à´¦à´¾à´¤à´¾à´•àµà´•àµ¾à´•àµà´•àµ à´—àµà´°àµ‚à´ªàµà´ªà´¿à´¨àµ† കാണികàµà´•à´¾àµ» പരസàµà´¯à´™àµà´™àµ¾ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•à´¾à´¨àµà´‚ നിങàµà´™à´³àµà´Ÿàµ† à´¬àµà´°àµ—സിംഗൠആകàµà´±àµà´±à´¿à´µà´¿à´±àµà´±à´¿ ഉപകരണതàµà´¤à´¿àµ½ à´¸àµà´µà´•à´¾à´°àµà´¯à´®à´¾à´¯à´¿ സൂകàµà´·à´¿à´•àµà´•à´¾à´¨àµà´®à´¾à´•àµà´‚. നിങàµà´™à´³àµà´Ÿàµ† à´—àµà´°àµ‚à´ªàµà´ªàµ à´Žà´²àµà´²à´¾ ദിവസവàµà´‚ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´¨àµà´¨àµ.}other{à´ˆ നിയനàµà´¤àµà´°à´£à´‚ ഓണായിരികàµà´•àµà´•à´¯àµà´‚ നില 'സജീവം' ആയിരികàµà´•àµà´•à´¯àµà´‚ ആണെങàµà´•à´¿àµ½, നിങàµà´™à´³àµà´Ÿàµ† à´…à´Ÿàµà´¤àµà´¤à´¿à´Ÿàµ†à´¯àµà´³àµà´³ à´¬àµà´°àµ—സിംഗൠആകàµà´±àµà´±à´¿à´µà´¿à´±àµà´±à´¿à´¯àµà´®à´¾à´¯à´¿ à´à´±àµà´±à´µàµà´‚ സാമàµà´¯à´®àµà´³àµà´³ ആളàµà´•à´³àµà´Ÿàµ† à´—àµà´°àµ‚à´ªàµà´ªàµ à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ "സമാന വിഭാഗതàµà´¤à´¿àµ½à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´µàµ¼" à´à´¤à´¾à´£àµ à´Žà´¨àµà´¨àµ Chrome നിർണàµà´£à´¯à´¿à´•àµà´•àµà´¨àµà´¨àµ. പരസàµà´¯à´¦à´¾à´¤à´¾à´•àµà´•àµ¾à´•àµà´•àµ à´—àµà´°àµ‚à´ªàµà´ªà´¿à´¨àµ† കാണികàµà´•à´¾àµ» പരസàµà´¯à´™àµà´™àµ¾ തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•à´¾à´¨àµà´‚ നിങàµà´™à´³àµà´Ÿàµ† à´¬àµà´°àµ—സിംഗൠആകàµà´±àµà´±à´¿à´µà´¿à´±àµà´±à´¿ ഉപകരണതàµà´¤à´¿àµ½ à´¸àµà´µà´•à´¾à´°àµà´¯à´®à´¾à´¯à´¿ സൂകàµà´·à´¿à´•àµà´•à´¾à´¨àµà´®à´¾à´•àµà´‚. നിങàµà´™à´³àµà´Ÿàµ† à´—àµà´°àµ‚à´ªàµà´ªàµ ഓരോ {NUM_DAYS} ദിവസം കൂടàµà´®àµà´ªàµ‹à´´àµà´‚ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´¨àµà´¨àµ.}}</translation>
<translation id="2053553514270667976">തപാൽ കോഡàµ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{ഒരൠനിർദàµà´¦àµ‡à´¶à´‚}other{# നിർദàµà´¦àµ‡à´¶à´™àµà´™àµ¾}}</translation>
<translation id="2071692954027939183">നിങàµà´™àµ¾ സാധാരണയായി അറിയിപàµà´ªàµà´•àµ¾ à´…à´¨àµà´µà´¦à´¿à´•àµà´•à´¾à´¤àµà´¤à´¤à´¿à´¨à´¾àµ½ à´…à´µ à´¸àµà´µà´¯à´®àµ‡à´µ à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ</translation>
<translation id="2079545284768500474">പഴയപടിയാകàµà´•àµà´•</translation>
<translation id="20817612488360358">സിസàµà´±àµà´±à´‚ à´ªàµà´°àµ‹à´•àµâ€Œà´¸à´¿ à´•àµà´°à´®àµ€à´•à´°à´£à´‚ ഉപയോഗികàµà´•àµà´¨àµà´¨à´¤à´¿à´¨à´¾à´¯à´¿ സജàµà´œà´®à´¾à´•àµà´•à´¿, പകàµà´·àµ† ഒരൠസàµâ€Œà´ªà´·àµâ€Œà´Ÿà´®à´¾à´¯ à´ªàµà´°àµ‹à´•àµâ€Œà´¸à´¿ കോൺഫിഗറേഷനàµà´‚ അതോടൊപàµà´ªà´‚ നിർദàµà´¦àµ‡à´¶à´¿à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ.</translation>
<translation id="2082238445998314030"><ph name="RESULT_NUMBER" /> / <ph name="TOTAL_RESULTS" /> ഫലം</translation>
+<translation id="2085876078937250610">സംരകàµà´·à´¿à´•àµà´•àµà´•â€¦</translation>
<translation id="2088086323192747268">സമനàµà´µà´¯à´¿à´ªàµà´ªà´¿à´•àµà´•àµ½ ബടàµà´Ÿàµº മാനേജൠചെയàµà´¯àµà´•, Chrome à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ നിങàµà´™àµ¾ സമനàµà´µà´¯à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨ വിവരങàµà´™àµ¾ മാനേജൠചെയàµà´¯à´¾àµ» 'Enter' അമർതàµà´¤àµà´•</translation>
<translation id="2091887806945687916">ശബàµâ€Œà´¦à´‚</translation>
<translation id="2094505752054353250">ഡൊമെയàµâ€Œàµ» പൊരàµà´¤àµà´¤à´®à´¿à´²àµà´²à´¾à´¯àµâ€Œà´®</translation>
@@ -378,6 +387,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> ഡൊമെയàµâ€Œà´¨àµ ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´µàµà´‚ പാസàµâ€Œà´µàµ‡à´¡àµà´‚ ആവശàµà´¯à´®à´¾à´£àµ.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" />-നൠകാലഹരണപàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµ</translation>
<translation id="2337852623177822836">à´•àµà´°à´®àµ€à´•à´°à´£à´‚ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤àµ നിങàµà´™à´³àµà´Ÿàµ† à´…à´¡àµâ€Œà´®à´¿à´¨à´¿à´¸àµâ€Œà´Ÿàµà´°àµ‡à´±àµà´±à´±à´¾à´£àµ</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ജോടിയാകàµà´•à´¾àµ» താൽപàµà´ªà´°àµà´¯à´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµ</translation>
<translation id="2344028582131185878">യാനàµà´¤àµà´°à´¿à´• ഡൗൺലോഡàµà´•àµ¾</translation>
<translation id="2346319942568447007">നിങàµà´™àµ¾ പകർതàµà´¤à´¿à´¯ à´šà´¿à´¤àµà´°à´‚</translation>
<translation id="2354001756790975382">മറàµà´±àµ à´¬àµà´•àµâ€Œà´®à´¾à´°àµâ€à´•àµà´•àµà´•à´³àµâ€</translation>
@@ -385,8 +395,10 @@
<translation id="2355395290879513365">നിങàµà´™àµ¾ à´ˆ സൈറàµà´±à´¿àµ½ തിരയàµà´¨àµà´¨ à´šà´¿à´¤àµà´°à´™àµà´™àµ¾ കാണാനàµà´‚ അവയിൽ മാറàµà´±à´‚ വരàµà´¤àµà´¤à´¿ നിങàµà´™à´³àµ† കബളിപàµà´ªà´¿à´•àµà´•à´¾à´¨àµà´‚ à´…à´•àµà´°à´®à´•à´¾à´°à´¿à´•àµ¾à´•àµà´•àµ à´•à´´à´¿à´žàµà´žàµ‡à´•àµà´•à´¾à´‚.</translation>
<translation id="2356070529366658676">ചോദികàµà´•àµà´•</translation>
<translation id="2357481397660644965">നിങàµà´™à´³àµà´Ÿàµ† ഉപകരണം <ph name="DEVICE_MANAGER" />-ഉം à´…à´•àµà´•àµ—à´£àµà´Ÿàµ <ph name="ACCOUNT_MANAGER" />-ഉം മാനേജൠചെയàµà´¯àµà´¨àµà´¨àµ.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ഒരൠദിവസതàµà´¤à´¿àµ½ à´•àµà´±à´µàµ സമയതàµà´¤à´¿à´¨àµà´³àµà´³à´¿àµ½}=1{ഒരൠദിവസതàµà´¤à´¿à´¨àµà´³àµà´³à´¿àµ½}other{{NUM_DAYS} ദിവസതàµà´¤à´¿à´¨àµà´³àµà´³à´¿àµ½}}</translation>
<translation id="2359629602545592467">à´’à´¨àµà´¨à´¿à´²à´§à´¿à´•à´‚</translation>
<translation id="2359808026110333948">à´¤àµà´Ÿà´°àµà´•</translation>
+<translation id="2359961752320758691">നിങàµà´™à´³àµà´Ÿàµ† വെർചàµà´µàµ½ കാർഡൠനമàµà´ªàµ¼ ഉപയോഗിചàµà´šàµ.</translation>
<translation id="2367567093518048410">നില</translation>
<translation id="2372464001869762664">à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´šàµà´šàµ à´•à´´à´¿à´žàµà´žà´¾àµ½, നിങàµà´™à´³àµà´Ÿàµ† Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ നിനàµà´¨àµà´³àµà´³ കാർഡൠവിശദാംശങàµà´™àµ¾ à´ˆ സൈറàµà´±àµà´®à´¾à´¯à´¿ പങàµà´•à´¿à´Ÿàµà´‚. നിങàµà´™à´³àµà´Ÿàµ† Plex à´…à´•àµà´•àµ—à´£àµà´Ÿàµ വിശദാംശങàµà´™à´³à´¿àµ½ CVC à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´•.</translation>
<translation id="2380886658946992094">നിയമപരം</translation>
@@ -397,6 +409,7 @@
<translation id="239429038616798445">à´ˆ à´·à´¿à´ªàµà´ªà´¿à´‚ഗൠരീതി ലഭàµà´¯à´®à´²àµà´². മറàµà´±àµŠà´°àµ രീതി പരീകàµà´·à´¿à´•àµà´•àµà´•.</translation>
<translation id="2396249848217231973">&amp;ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµ½ പഴയപടിയാകàµà´•àµà´•</translation>
<translation id="2410754574180102685">സർകàµà´•à´¾àµ¼-നിയമപരം</translation>
+<translation id="2413155254802890957">പഴയവ</translation>
<translation id="2413528052993050574">à´ˆ സെർവറിനൠഅതൠ<ph name="DOMAIN" /> ആണെനàµà´¨àµ തെളിയികàµà´•à´¾à´¨à´¾à´¯à´¿à´²àµà´²; സെർവറിനàµà´±àµ† à´¸àµà´°à´•àµà´·à´¾ സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ റദàµà´¦à´¾à´•àµà´•à´¿à´¯à´¿à´°à´¿à´•àµà´•à´¾à´‚. തെറàµà´±à´¾à´¯ കോൺഫിഗറേഷൻ കാരണമോ ഒരൠഅകàµà´°à´®à´£à´•à´¾à´°à´¿ നിങàµà´™à´³àµà´Ÿàµ† കണകàµà´·à´¨àµ† തടസàµà´¸à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´¨àµà´¨à´¤àµ കൊണàµà´Ÿàµ‹ ആയിരികàµà´•à´¾à´‚ ഇതൠസംഭവിചàµà´šà´¤àµ.</translation>
<translation id="2414886740292270097">ഇരàµà´£àµà´Ÿà´¤àµ</translation>
<translation id="2438874542388153331">വലതàµà´µà´¶à´¤àµà´¤àµ നാലൠതവണ പഞàµà´šàµ ചെയàµà´¯àµà´•</translation>
@@ -424,10 +437,10 @@
<translation id="2521385132275182522">താഴെ വലതàµà´µà´¶à´¤àµà´¤àµ à´¸àµâ€Œà´±àµà´±àµ‡à´ªàµà´ªà´¿àµ¾ ചെയàµà´¯àµà´•</translation>
<translation id="2523886232349826891">à´ˆ ഉപകരണതàµà´¤à´¿àµ½ മാതàµà´°à´‚ സംരകàµà´·à´¿à´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´‚</translation>
<translation id="2524461107774643265">കൂടàµà´¤àµ½ വിവരങàµà´™àµ¾ ചേർകàµà´•àµà´•</translation>
-<translation id="2526590354069164005">ഡെസàµà´•àµâ€Œà´Ÿàµ‹à´ªàµà´ªàµ</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{à´Žà´¨àµà´¨à´¤àµà´‚ മറàµà´±àµŠà´°àµ†à´£àµà´£à´µàµà´‚}other{à´Žà´¨àµà´¨à´¤àµà´‚ മറàµà´±àµ # à´Žà´£àµà´£à´µàµà´‚}}</translation>
<translation id="2536110899380797252">വിലാസം ചേർകàµà´•àµà´•</translation>
<translation id="2539524384386349900">à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´•</translation>
+<translation id="2541219929084442027">അദൃശàµà´¯ ടാബàµà´•à´³à´¿àµ½ നിങàµà´™àµ¾ കാണàµà´¨àµà´¨ പേജàµà´•àµ¾, അദൃശàµà´¯ ടാബàµà´•à´³àµ†à´²àµà´²à´¾à´‚ à´…à´Ÿà´šàµà´š ശേഷം നിങàµà´™à´³àµà´Ÿàµ† à´¬àµà´°àµ—സിംഗൠചരിതàµà´°à´¤àµà´¤à´¿à´²àµ‹ à´•àµà´•àµà´•à´¿ à´¸àµà´±àµà´±àµ‹à´±à´¿à´²àµ‹ തിരയൽ à´šà´°à´¿à´¤àµà´°à´¤àµà´¤à´¿à´²àµ‹ നിലനിൽകàµà´•à´¿à´²àµà´². നിങàµà´™àµ¾ ഡൗൺലോഡൠചെയàµà´¤ ഫയലàµà´•à´³àµ‹ സൃഷàµà´Ÿà´¿à´šàµà´š à´¬àµà´•àµà´•àµâ€Œà´®à´¾àµ¼à´•àµà´•àµà´•à´³àµ‹ സംരകàµà´·à´¿à´•àµà´•àµà´‚.</translation>
<translation id="2544644783021658368">സിംഗിൾ ഡോകàµà´¯àµà´®àµ†à´¨àµà´±àµ</translation>
<translation id="254947805923345898">നയതàµà´¤à´¿àµ»àµà´±àµ† മൂലàµà´¯à´‚ അസാധàµà´µà´¾à´£àµ.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> അസാധàµà´µà´¾à´¯ ഒരൠപàµà´°à´¤à´¿à´•à´°à´£à´‚ അയചàµà´šàµ.</translation>
@@ -447,6 +460,7 @@
<translation id="2629325967560697240">Chrome-à´¨àµà´±àµ† à´à´±àµà´±à´µàµà´‚ ഉയർനàµà´¨ à´¸àµà´°à´•àµà´· നേടാൻ, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />മെചàµà´šà´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿à´¯ പരിരകàµà´· ഓണാകàµà´•àµà´•<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" />-à´¨àµâ€à´±àµ† സെർവർ IP വിലാസം à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¾à´¨à´¾à´¯à´¿à´²àµà´².</translation>
<translation id="2639739919103226564">നില:</translation>
+<translation id="264810637653812429">à´…à´¨àµà´¯àµ‹à´œàµà´¯à´®à´¾à´¯ ഉപകരണങàµà´™à´³àµŠà´¨àµà´¨àµà´‚ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¿à´¯à´¿à´²àµà´².</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ നിങàµà´™à´³àµà´Ÿàµ† à´¬àµà´°àµ—സിംഗൠചരിതàµà´°à´µàµà´‚ à´•àµà´•àµà´•à´¿à´•à´³àµà´‚ കാഷെയàµà´‚ മറàµà´±àµà´‚ മായàµà´•àµà´•à´¾àµ» 'Tab' അമർതàµà´¤àµà´•, à´¤àµà´Ÿàµ¼à´¨àµà´¨àµ 'Enter' അമർതàµà´¤àµà´•</translation>
<translation id="2650446666397867134">ഫയലിലേകàµà´•àµà´³àµà´³ ആകàµâ€Œà´¸à´¸àµ നിരസിചàµà´šàµ</translation>
@@ -474,7 +488,7 @@
<translation id="2715612312510870559"><ph name="UPDATE_CREDIT_CARD_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ നിങàµà´™à´³àµà´Ÿàµ† പേയàµâ€Œà´®àµ†à´¨àµà´±àµà´•à´³àµà´‚ à´•àµà´°àµ†à´¡à´¿à´±àµà´±àµ കാർഡൠവിവരങàµà´™à´³àµà´‚ മാനേജൠചെയàµà´¯à´¾àµ» 'Tab' അമർതàµà´¤àµà´•, à´¤àµà´Ÿàµ¼à´¨àµà´¨àµ 'Enter' അമർതàµà´¤àµà´•</translation>
<translation id="2721148159707890343">à´…à´­àµà´¯àµ¼à´¤àµà´¥à´¨ വിജയിചàµà´šàµ</translation>
<translation id="272451190272506600">പണമട‌യàµâ€Œà´•àµà´•à´¾àµ» സെൻസറിൽ à´¸àµâ€Œà´ªàµ¼à´¶à´¿à´•àµà´•àµà´•</translation>
-<translation id="2728127805433021124">ഒരൠദàµàµ¼à´¬àµà´¬à´² സിഗàµâ€Œà´¨àµ‡à´šàµà´šàµ¼ അൽഗോരിതം ഉപയോഗിചàµà´šàµ സെർവറിനàµà´±àµ† സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ സൈൻ ചെയàµâ€Œà´¤àµ.</translation>
+<translation id="2728127805433021124">ഒരൠദàµàµ¼à´¬àµà´¬à´² സിഗàµâ€Œà´¨àµ‡à´šàµà´šàµ¼ ആൽഗരിതം ഉപയോഗിചàµà´šàµ സെർവറിനàµà´±àµ† സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ സൈൻ ചെയàµâ€Œà´¤àµ.</translation>
<translation id="2730326759066348565"><ph name="BEGIN_LINK" />കണകàµâ€Œà´±àµà´±à´¿à´µà´¿à´±àµà´±à´¿ ഡയഗണോസàµâ€Œà´±àµà´±à´¿à´•àµâ€Œà´¸àµ റൺ ചെയàµà´¯àµà´¨àµà´¨àµ<ph name="END_LINK" /></translation>
<translation id="2734544361860335147">à´ˆ ഫീചàµà´šà´±àµà´•àµ¾ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´•àµà´·à´®à´®à´¾à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´²àµ‚ടെ, നിങàµà´™à´³àµà´Ÿàµ† à´¬àµà´°àµ—സർ ഡാറàµà´± നഷàµâ€Œà´Ÿà´®à´¾à´•àµà´•à´¯àµ‹ à´¸àµà´°à´•àµà´·à´¯àµâ€Œà´•àµà´•àµ‹ à´¸àµà´µà´•à´¾à´°àµà´¯à´¤à´¯àµâ€Œà´•àµà´•àµ‹ ഭീഷണി ഉയരàµà´•à´¯àµ‹ ചെയàµâ€Œà´¤àµ‡à´•àµà´•à´¾à´‚. à´ˆ à´¬àµà´°àµ—സറിനàµà´±àµ† à´Žà´²àµà´²à´¾ ഉപയോകàµà´¤à´¾à´•àµà´•àµ¾à´•àµà´•àµà´‚ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´•àµà´·à´®à´®à´¾à´•àµà´•à´¿à´¯ ഫീചàµà´šà´±àµà´•àµ¾ ബാധകമാണàµ.</translation>
<translation id="2738330467931008676">പികàµà´•à´ªàµà´ªàµ വിലാസം തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•</translation>
@@ -491,6 +505,7 @@
<translation id="2799223571221894425">വീണàµà´Ÿàµà´‚ സമാരംഭികàµà´•àµà´•</translation>
<translation id="2803306138276472711"><ph name="SITE" /> à´Žà´¨àµà´¨à´¤à´¿àµ½ Google à´¸àµà´°à´•àµà´·à´¿à´¤ à´¬àµà´°àµ—സിംഗൠഈയിടെ <ph name="BEGIN_LINK" />മാൽവെയർ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¿<ph name="END_LINK" />. സാധാരണ നിലയിൽ à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´¾à´¯ വെബàµà´¸àµˆà´±àµà´±àµà´•à´³à´¿àµ½ ചിലപàµà´ªàµ‹àµ¾ മാൽവെയർ ഉണàµà´Ÿà´¾à´¯àµ‡à´•àµà´•à´¾à´‚.</translation>
<translation id="2807052079800581569">à´šà´¿à´¤àµà´°à´‚ Y à´¸àµà´¥à´¾à´¨à´‚</translation>
+<translation id="2820957248982571256">à´¸àµâ€Œà´•à´¾àµ» ചെയàµà´¯àµà´¨àµà´¨àµ...</translation>
<translation id="2824775600643448204">വിലാസവàµà´‚ തിരയൽ ബാറàµà´‚</translation>
<translation id="2826760142808435982"><ph name="CIPHER" /> ഉപയോഗിചàµà´šàµ കണകàµà´·àµ» എൻകàµà´°à´¿à´ªàµâ€Œà´±àµà´±àµà´šàµ†à´¯àµâ€Œà´¤àµ à´ªàµà´°à´¾à´®à´¾à´£àµ€à´•à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ, à´’à´ªàµà´ªà´‚ à´ªàµà´°à´§à´¾à´¨ à´Žà´•àµâ€Œà´¸àµ‡à´žàµà´šàµ മെകàµà´•à´¾à´¨à´¿à´¸à´®à´¾à´¯à´¿ <ph name="KX" /> ഉപയോഗികàµà´•àµà´¨àµà´¨àµ.</translation>
<translation id="2835170189407361413">ഫോം മായàµâ€Œà´•àµà´•àµà´•</translation>
@@ -498,6 +513,8 @@
<translation id="2850739647070081192">à´•àµà´·à´£à´‚ (എൻവലപàµà´ªàµ)</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="2859806420264540918">à´ˆ സൈറàµà´±àµ, അനാവശàµà´¯à´®àµ‹ തെറàµà´±à´¿à´¦àµà´§à´°à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨à´¤àµ‹ ആയ പരസàµà´¯à´™àµà´™àµ¾ കാണികàµà´•àµà´¨àµà´¨àµ.</translation>
+<translation id="287596039013813457">സൗഹാർദàµà´¦à´ªà´°à´‚</translation>
+<translation id="2876489322757410363">ബാഹàµà´¯ ആപàµà´ªàµ വഴി പണമടയàµâ€Œà´•àµà´•à´¾àµ» അദൃശàµà´¯ മോഡിൽ നിനàµà´¨àµ à´ªàµà´±à´¤àµà´¤àµà´•à´Ÿà´•àµà´•àµà´¨àµà´¨àµ. à´¤àµà´Ÿà´°à´£àµ‹?</translation>
<translation id="2878197950673342043">പോസàµâ€Œà´±àµà´±àµ¼ മടകàµà´•àµ</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">വിൻഡോ à´ªàµà´²àµ†à´¯àµâ€Œà´¸àµâ€Œà´®àµ†à´¨àµà´±àµ</translation>
@@ -547,7 +564,6 @@
<translation id="3060227939791841287">C9 (എൻവലപàµà´ªàµ)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ à´¸àµà´°à´•àµà´·à´¾ പരിശോധന റൺ ചെയàµà´¯à´¾àµ» Tab അമർതàµà´¤à´¿à´¯ ശേഷം Enter അമർതàµà´¤àµà´•</translation>
<translation id="3061707000357573562">പാചàµà´šàµ സേവനം</translation>
-<translation id="3064966200440839136">ബാഹàµà´¯ ആപàµà´ªàµ വഴി പണമടയàµâ€Œà´•àµà´•à´¾àµ» അദൃശàµà´¯ മോഡൠഒഴിവാകàµà´•àµà´¨àµà´¨àµ. à´¤àµà´Ÿà´°à´£àµ‹?</translation>
<translation id="306573536155379004">ഗെയിം ആരംഭിചàµà´šàµ.</translation>
<translation id="3080254622891793721">à´—àµà´°à´¾à´«à´¿à´•àµ</translation>
<translation id="3086579638707268289">വെബിലàµà´³àµà´³ നിങàµà´™à´³àµà´Ÿàµ† ആകàµà´±àµà´±à´¿à´µà´¿à´±àµà´±à´¿ നിരീകàµà´·à´£à´¤àµà´¤à´¿à´²à´¾à´£àµ</translation>
@@ -570,7 +586,6 @@
<translation id="315504272643575312">നിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿàµ മാനേജൠചെയàµà´¯àµà´¨àµà´¨à´¤àµ <ph name="MANAGER" /> ആണàµ.</translation>
<translation id="3157931365184549694">à´ªàµà´¨à´ƒà´¸àµà´¥à´¾à´ªà´¿à´•àµà´•àµà´•</translation>
<translation id="3162559335345991374">നിങàµà´™àµ¾ ഉപയോഗികàµà´•àµà´¨àµà´¨ Wi-Fi അതിനàµà´±àµ† ലോഗിൻ പേജൠസനàµà´¦àµ¼à´¶à´¿à´•àµà´•à´¾àµ» നിങàµà´™à´³àµ‹à´Ÿàµ ആവശàµà´¯à´ªàµà´ªàµ†à´Ÿà´¾à´‚.</translation>
-<translation id="3167968892399408617">അദൃശàµà´¯ ടാബàµà´•à´³à´¿àµ½ നിങàµà´™àµ¾ കാണàµà´¨àµà´¨ പേജàµà´•àµ¾, അദൃശàµà´¯ ടാബàµà´•àµ¾ à´Žà´²àµà´²à´¾à´‚ à´…à´Ÿà´šàµà´šà´¤à´¿à´¨àµà´¶àµ‡à´·à´‚ à´¬àµà´°àµ—സർ à´šà´°à´¿à´¤àµà´°à´¤àµà´¤à´¿à´²àµ‹ à´•àµà´•àµà´•à´¿ à´¸àµà´±àµà´±àµ‹à´±à´¿à´²àµ‹ തിരയൽ à´šà´°à´¿à´¤àµà´°à´¤àµà´¤à´¿à´²àµ‹ ഉണàµà´Ÿà´¾à´•à´¿à´²àµà´². നിങàµà´™àµ¾ ഡൗൺലോഡൠചെയàµà´¯àµà´¨àµà´¨ ഫയലàµà´•à´³àµ‹ സൃഷàµâ€Œà´Ÿà´¿à´•àµà´•àµà´¨àµà´¨ à´¬àµà´•àµà´•àµâ€Œà´®à´¾àµ¼à´•àµà´•àµà´•à´³àµ‹ à´Žà´²àµà´²à´¾à´‚ സൂകàµà´·à´¿à´•àµà´•àµà´‚.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">à´à´²à´¨àµâ€à´¡àµ</translation>
<translation id="3176929007561373547">à´ªàµà´°àµ‹à´•àµâ€Œà´¸à´¿ സെർവർ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´•àµà´•àµà´¨àµà´¨àµà´µàµ†à´¨àµà´¨àµ ഉറപàµà´ªà´¾à´•àµà´•à´¾àµ»
@@ -595,10 +610,12 @@
<translation id="3229041911291329567">നിങàµà´™à´³àµà´Ÿàµ† ഉപകരണതàµà´¤àµ†à´¯àµà´‚ à´¬àµà´°àµ—സറിനെയàµà´‚ à´•àµà´±à´¿à´šàµà´šàµà´³àµà´³ പതിപàµà´ªàµ വിവരങàµà´™àµ¾</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" />-à´¨àµâ€à´±àµ† CVC നൽകàµà´•</translation>
<translation id="3234666976984236645">à´ˆ സൈറàµà´±à´¿àµ½ à´Žà´ªàµà´ªàµ‹à´´àµà´‚ à´ªàµà´°à´§à´¾à´¨ ഉളàµà´³à´Ÿà´•àµà´•à´‚ à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´•</translation>
+<translation id="3249845759089040423">à´—àµà´°àµ‚വി</translation>
<translation id="3252266817569339921">à´«àµà´°à´žàµà´šàµ</translation>
<translation id="3266793032086590337">മൂലàµà´¯à´‚ (വൈരàµà´¦àµà´§àµà´¯à´‚)</translation>
<translation id="3268451620468152448">à´“à´ªàµà´ªàµº ടാബàµà´•àµ¾</translation>
<translation id="3270847123878663523">&amp;à´ªàµà´¨à´ƒà´•àµà´°à´®àµ€à´•à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤àµ പഴയപടിയാകàµà´•àµà´•</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> കണകàµâ€Œà´±àµà´±àµà´šàµ†à´¯àµà´¯à´¾àµ» താൽപàµà´ªà´°àµà´¯à´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµ</translation>
<translation id="3274521967729236597">പാ-കായàµ</translation>
<translation id="3282085321714087552">നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´¥à´¾à´ªà´¨à´‚, <ph name="ENROLLMENT_DOMAIN" />, à´•àµà´°à´®àµ€à´•à´°à´£à´®àµ‹ നയങàµà´™à´³àµ‹ പോലàµà´³àµà´³ à´šà´¿à´² വിവരങàµà´™àµ¾ ഇനിപàµà´ªà´±à´¯àµà´¨àµà´¨ വെബàµâ€Œà´¸àµˆà´±àµà´±àµà´•à´³à´¿à´²àµ‡à´•àµà´•àµ അയചàµà´šàµ.</translation>
<translation id="3282497668470633863">കാർഡിൽ പേരൠചേർകàµà´•àµà´•</translation>
@@ -641,7 +658,7 @@
<translation id="3402261774528610252">à´ˆ സൈറàµà´±àµ ലോഡൠചെയàµà´¯à´¾àµ» ഉപയോഗിചàµà´š കണകàµà´·àµ» ഉപയോഗിചàµà´šà´¤àµ TLS 1.0 à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ TLS 1.1 പതിപàµà´ªà´¾à´£àµ, ഇവ അവസാനിപàµà´ªà´¿à´šàµà´šà´¤àµà´‚ ഭാവിയിൽ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´°à´¹à´¿à´¤à´®à´¾à´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨à´¤àµà´‚ ആണàµ. à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´°à´¹à´¿à´¤à´‚ ആയികàµà´•à´´à´¿à´žàµà´žà´¾àµ½, à´ˆ സൈറàµà´±àµ ലോഡൠചെയàµà´¯àµà´¨àµà´¨à´¤à´¿àµ½ നിനàµà´¨àµ ഉപയോകàµà´¤à´¾à´•àµà´•à´³àµ† തടയàµà´‚. TLS 1.2 à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ അതിനൠശേഷമàµà´³àµà´³ പതിപàµà´ªàµ സെർവർ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´•àµà´·à´®à´®à´¾à´•àµà´•à´£à´‚.</translation>
<translation id="3409896703495473338">à´¸àµà´°à´•àµà´·à´¾ à´•àµà´°à´®àµ€à´•à´°à´£à´‚ മാനേജൠചെയàµà´¯àµà´•</translation>
<translation id="3414952576877147120">വലàµà´ªàµà´ªà´‚:</translation>
-<translation id="3417660076059365994">നിങàµà´™àµ¾ à´…à´ªàµâ€Œà´²àµ‹à´¡àµ ചെയàµà´¯àµà´¨àµà´¨ ഫയലàµà´•àµ¾ വിശകലനം ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿à´¨àµ Google à´•àµà´²àµ—ഡിലേകàµà´•àµ‹ മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿à´•àµ¾à´•àµà´•àµ‹ അയയàµà´•àµà´•àµà´¨àµà´¨àµ. ഉദാഹരണതàµà´¤à´¿à´¨àµ, സെൻസിറàµà´±àµ€à´µà´¾à´¯à´¿à´Ÿàµà´Ÿàµà´³àµà´³ à´µàµà´¯à´•àµà´¤à´¿à´ªà´°à´®à´¾à´¯ ഡാറàµà´±à´¯àµ‹ മാൽവേറോ ഉണàµà´Ÿàµ‹à´¯àµ†à´¨àµà´¨à´±à´¿à´¯à´¾àµ» à´…à´µ à´¸àµâ€Œà´•à´¾àµ» ചെയàµâ€Œà´¤àµ‡à´•àµà´•à´¾à´‚.</translation>
+<translation id="3417660076059365994">നിങàµà´™àµ¾ à´…à´ªàµâ€Œà´²àµ‹à´¡àµ ചെയàµà´¯àµà´¨àµà´¨ ഫയലàµà´•àµ¾ വിശകലനം ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿à´¨àµ Google à´•àµà´²àµ—ഡിലേകàµà´•àµ‹ മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿à´•àµ¾à´•àµà´•àµ‹ അയയàµà´•àµà´•àµà´¨àµà´¨àµ. ഉദാഹരണതàµà´¤à´¿à´¨àµ, സെൻസിറàµà´±àµ€à´µà´¾à´¯à´¿à´Ÿàµà´Ÿàµà´³àµà´³ à´µàµà´¯à´•àµà´¤à´¿à´ªà´°à´®à´¾à´¯ ഡാറàµà´±à´¯àµ‹ മാൽവെയറോ ഉണàµà´Ÿàµ‹à´¯àµ†à´¨àµà´¨à´±à´¿à´¯à´¾àµ» à´…à´µ à´¸àµâ€Œà´•à´¾àµ» ചെയàµâ€Œà´¤àµ‡à´•àµà´•à´¾à´‚.</translation>
<translation id="3422248202833853650">ഇടം സൃഷàµâ€Œà´Ÿà´¿à´•àµà´•à´¾àµ» മറàµà´±àµ à´ªàµà´°àµ‹à´—àµà´°à´¾à´®àµà´•à´³à´¿àµ½ നിനàµà´¨àµ à´ªàµà´±à´¤àµà´¤àµà´•à´Ÿà´•àµà´•àµà´¨àµà´¨à´¤àµ പരീകàµà´·à´¿à´•àµà´•àµ‚.</translation>
<translation id="3422472998109090673"><ph name="HOST_NAME" /> നിലവിൽ ലഭàµà´¯à´®à´²àµà´².</translation>
<translation id="3423742043356668186">സിസàµà´±àµà´±à´‚ à´µàµà´¯à´•àµà´¤à´®à´¾à´•àµà´•à´¿à´¯à´¤àµ</translation>
@@ -651,6 +668,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates സെർവർ ടെംപàµà´²àµ‡à´±àµà´±àµ URI-കളിൽ à´’à´¨àµà´¨àµ‹ അതിലധികമോ അസാധàµà´µà´¾à´£àµ, à´…à´µ ഉപയോഗികàµà´•à´¿à´²àµà´².</translation>
<translation id="3431636764301398940">à´ˆ ഉപകരണതàµà´¤à´¿à´²àµ‡à´•àµà´•àµ à´ˆ കാർഡൠസംരകàµà´·à´¿à´•àµà´•àµà´•</translation>
<translation id="3432601291244612633">പേജൠഅടയàµà´•àµà´•àµà´•</translation>
+<translation id="3435738964857648380">à´¸àµà´°à´•àµà´·</translation>
<translation id="3435896845095436175">തയàµà´¯à´¾à´±à´¾à´•àµà´•àµà´•</translation>
<translation id="3438829137925142401">നിങàµà´™à´³àµà´Ÿàµ† Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ സംരകàµà´·à´¿à´šàµà´šà´¿à´Ÿàµà´Ÿàµà´³àµà´³ പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ ഉപയോഗികàµà´•àµà´•</translation>
<translation id="3443726618221119081">à´œàµà´±àµ‹-à´•àµ-കായàµ</translation>
@@ -693,7 +711,10 @@
<translation id="3584299510153766161">താഴെ ഇരടàµà´Ÿ പഞàµà´šàµ ചെയàµà´¯àµà´•</translation>
<translation id="3586931643579894722">വിശദാംശങàµà´™àµ¾ മറയàµâ€Œà´•àµà´•àµà´•â€â€Œ</translation>
<translation id="3587738293690942763">മദàµà´§àµà´¯à´‚</translation>
+<translation id="3590643883886679995">നിങàµà´™àµ¾ അദൃശàµà´¯ മോഡിൽ നിനàµà´¨àµ à´ªàµà´±à´¤àµà´¤àµà´•à´Ÿà´¨àµà´¨ ശേഷം സൈൻ ഇൻ ഡാറàµà´± à´ˆ ഉപകരണതàµà´¤à´¿àµ½ സംഭരികàµà´•àµà´‚.</translation>
+<translation id="359126217934908072">മാസം/വർഷം:</translation>
<translation id="3592413004129370115">ഇറàµà´±à´¾à´²à´¿à´¯àµ» (എൻവലപàµà´ªàµ)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{നിങàµà´™à´³àµà´Ÿàµ† à´—àµà´°àµ‚à´ªàµà´ªàµ à´à´¤àµà´¸à´®à´¯à´¤àµà´¤àµà´‚ റീസെറàµà´±àµ ചെയàµà´¯à´¾à´‚. à´ªàµà´¤à´¿à´¯ à´—àµà´°àµ‚à´ªàµà´ªà´¿àµ½ ചേരാൻ ഒരൠദിവസമെടàµà´•àµà´•àµà´‚.}=1{നിങàµà´™à´³àµà´Ÿàµ† à´—àµà´°àµ‚à´ªàµà´ªàµ à´à´¤àµà´¸à´®à´¯à´¤àµà´¤àµà´‚ റീസെറàµà´±àµ ചെയàµà´¯à´¾à´‚. à´ªàµà´¤à´¿à´¯ à´—àµà´°àµ‚à´ªàµà´ªà´¿àµ½ ചേരാൻ ഒരൠദിവസമെടàµà´•àµà´•àµà´‚.}other{നിങàµà´™à´³àµà´Ÿàµ† à´—àµà´°àµ‚à´ªàµà´ªàµ à´à´¤àµà´¸à´®à´¯à´¤àµà´¤àµà´‚ റീസെറàµà´±àµ ചെയàµà´¯à´¾à´‚. à´ªàµà´¤à´¿à´¯ à´—àµà´°àµ‚à´ªàµà´ªà´¿àµ½ ചേരാൻ {NUM_DAYS} ദിവസമെടàµà´•àµà´•àµà´‚.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">ആപàµà´ªàµ നിങàµà´™à´³àµà´Ÿàµ† à´…à´¡àµâ€Œà´®à´¿àµ» à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµâ€Œà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ</translation>
<translation id="3608932978122581043">ഓറിയനàµà´±àµ‡à´·àµ» ഫീഡൠചെയàµà´¯àµà´•</translation>
@@ -702,13 +723,13 @@
<translation id="3615877443314183785">കാലഹരണപàµà´ªàµ†à´Ÿàµà´¨àµà´¨ ശരിയായ തീയതി നലàµâ€à´•àµà´•</translation>
<translation id="36224234498066874">à´¬àµà´°àµŒà´¸à´¿à´‚ഗൠഡാറàµà´± മായàµâ€Œà´•àµà´•àµà´•...</translation>
<translation id="362276910939193118">à´®àµà´´àµà´µà´¨àµâ€ à´šà´°à´¿à´¤àµà´°à´µàµà´‚ കാണികàµà´•àµà´•</translation>
-<translation id="3625635938337243871">നിങàµà´™àµ¾ അദൃശàµà´¯ മോഡിൽ നിനàµà´¨àµ à´ªàµà´±à´¤àµà´¤àµà´•à´Ÿà´¨àµà´¨ ശേഷം സൈൻ ഇൻ ഡാറàµà´± à´ˆ ഉപകരണതàµà´¤à´¿àµ½ സംഭരികàµà´•àµà´‚.</translation>
<translation id="3630155396527302611">ഇതിനെ നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµ ആകàµâ€Œà´¸à´¸àµ ചെയàµà´¯à´¾àµ» à´…à´¨àµà´®à´¤à´¿à´¯àµà´³àµà´³ ഒരൠപàµà´°àµ‹à´—àµà´°à´¾à´®à´¾à´¯à´¿ നിലവിൽ ലിസàµà´±àµà´±àµ ചെയàµâ€Œà´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ†à´™àµà´•à´¿àµ½,
അതിനെ ലിസàµà´±àµà´±à´¿àµ½ നിനàµà´¨àµ നീകàµà´•à´‚ചെയàµâ€Œà´¤àµ, വീണàµà´Ÿàµà´‚ ചേർകàµà´•à´¾àµ» à´¶àµà´°à´®à´¿à´•àµà´•àµà´•.</translation>
<translation id="3630699740441428070">à´ˆ ഉപകരണതàµà´¤à´¿à´¨àµà´±àµ† à´…à´¡àµâ€Œà´®à´¿àµ»à´®à´¾àµ¼ നിങàµà´™à´³àµà´Ÿàµ† നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµ കണകàµà´·àµ» കോൺഫിഗർ ചെയàµâ€Œà´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ, നിങàµà´™àµ¾ സനàµà´¦àµ¼à´¶à´¿à´•àµà´•àµà´¨àµà´¨ വെബàµâ€Œà´¸àµˆà´±àµà´±àµà´•àµ¾ ഉൾപàµà´ªàµ†à´Ÿàµ†à´¯àµà´³àµà´³ നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµ à´Ÿàµà´°à´¾à´«à´¿à´•àµ കാണാൻ ഇതൠഅവരെ à´…à´¨àµà´µà´¦à´¿à´šàµà´šàµ‡à´•àµà´•à´¾à´‚.</translation>
<translation id="3631244953324577188">ബയോമെടàµà´°à´¿à´•àµâ€Œà´¸àµ</translation>
<translation id="3633738897356909127">'Chrome à´…à´ªàµà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´•' ബടàµà´Ÿàµº, നിങàµà´™à´³àµà´Ÿàµ† Chrome à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ Chrome à´…à´ªàµà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯à´¾àµ» 'Enter' അമർതàµà´¤àµà´•</translation>
<translation id="3634530185120165534">à´Ÿàµà´°àµ‡ 5</translation>
+<translation id="3637662659967048211">Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ സംരകàµà´·à´¿à´•àµà´•àµà´•</translation>
<translation id="3640766068866876100">സൂചിക-4x6-Ext</translation>
<translation id="3642638418806704195">ആപàµà´ªàµ:</translation>
<translation id="3650584904733503804">മൂലàµà´¯à´¨à´¿àµ¼à´£àµà´£à´¯à´‚ വിജയകരം</translation>
@@ -749,6 +770,7 @@
<translation id="3781428340399460090">ഹോടàµà´Ÿàµ പിങàµà´•àµ</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth ഉപകരണങàµà´™àµ¾</translation>
+<translation id="3787675388804467730">വെർചàµà´µàµ½ കാർഡൠനമàµà´ªàµ¼</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" />-ൽ അവസാനികàµà´•àµà´¨àµà´¨àµ</translation>
<translation id="3789155188480882154">വലàµà´ªàµà´ªà´‚ 16</translation>
<translation id="3789841737615482174">ഇനàµâ€à´¸àµà´±àµà´±à´¾àµ¾ ചെയàµà´¯àµà´•</translation>
@@ -768,6 +790,7 @@
<translation id="3841184659773414994">ഫയൽ കൈകാരàµà´¯à´‚ ചെയàµà´¯àµà´¨àµà´¨ സംവിധാനം</translation>
<translation id="385051799172605136">പിനàµà´¨àµ‹à´Ÿàµà´Ÿàµ</translation>
<translation id="3858027520442213535">തീയതിയàµà´‚ സമയവàµà´‚ à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´•</translation>
+<translation id="3881478300875776315">à´•àµà´±à´šàµà´šàµ വരികൾ മാതàµà´°à´‚ കാണികàµà´•àµà´•</translation>
<translation id="3884278016824448484">വിരàµà´¦àµà´§ ഉപകരണ à´à´¡à´¨àµà´±à´¿à´«à´¯àµ¼</translation>
<translation id="3885155851504623709">പാരിഷàµ</translation>
<translation id="388632593194507180">നിരീകàµà´·à´£à´‚ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¿</translation>
@@ -793,6 +816,7 @@
<translation id="397105322502079400">കണകàµà´•à´¾à´•àµà´•àµà´¨àµà´¨àµ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> à´¬àµà´²àµ‹à´•àµà´•àµà´šàµ†à´¯àµâ€Œà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ</translation>
<translation id="3973357910713125165">Chrome à´¸àµà´°à´•àµà´·à´¾ പരിശോധന റൺ ചെയàµà´¯àµà´• ബടàµà´Ÿàµº, Chrome à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ à´¸àµà´°à´•àµà´·à´¾ പരിശോധന റൺ ചെയàµà´¯à´¾àµ» Enter അമർതàµà´¤àµà´•</translation>
+<translation id="3986705137476756801">തൽസമയ à´•àµà´¯à´¾à´ªàµà´·àµ» ഇപàµà´ªàµ‹à´´à´¤àµà´¤àµ‡à´•àµà´•àµ ഓഫാകàµà´•àµà´•</translation>
<translation id="3987405730340719549">à´ˆ സൈറàµà´±àµ à´µàµà´¯à´¾à´œà´®àµ‹ വഞàµà´šà´¨à´¾à´ªà´°à´®àµ‹ ആകാമെനàµà´¨àµ Chrome നിർണàµà´£à´¯à´¿à´šàµà´šàµ.
ഇതൠപിശകിനാൽ കാണിചàµà´šà´¤à´¾à´£àµ†à´¨àµà´¨àµ നിങàµà´™àµ¾ വിശàµà´µà´¸à´¿à´•àµà´•àµà´¨àµà´¨àµà´µàµ†à´™àµà´•à´¿àµ½, https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals സനàµà´¦àµ¼à´¶à´¿à´•àµà´•àµà´•.</translation>
@@ -887,13 +911,14 @@
<translation id="4275830172053184480">നിങàµà´™à´³àµà´Ÿàµ† ഉപകരണം à´ªàµà´¨à´°à´¾à´°à´‚à´­à´¿à´•àµà´•àµà´•</translation>
<translation id="4277028893293644418">പാസàµâ€Œà´µàµ‡à´¡àµ റീസെറàµà´±àµ ചെയàµà´¯àµà´•</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{à´ˆ കാർഡൠനിങàµà´™à´³àµà´Ÿàµ† Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ സംരകàµà´·à´¿à´šàµà´šàµ}other{à´ˆ കാർഡàµà´•àµ¾ നിങàµà´™à´³àµà´Ÿàµ† Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ സംരകàµà´·à´¿à´šàµà´šàµ}}</translation>
+<translation id="4287885627794386150">à´Ÿàµà´°à´¯à´²à´¿à´¨àµ യോഗàµà´¯à´¤à´¯àµà´£àµà´Ÿàµ, à´Žà´¨àµà´¨à´¾àµ½ സജീവമലàµà´²</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" />-ാം പേജിനàµà´³àµà´³ ലഘàµà´šà´¿à´¤àµà´°à´‚</translation>
<translation id="42981349822642051">വികസിപàµà´ªà´¿à´•àµà´•àµà´•</translation>
<translation id="4300675098767811073">വലതàµà´µà´¶à´¤àµà´¤àµ à´’à´¨àµà´¨à´¿à´²à´§à´¿à´•à´‚ പഞàµà´šàµà´•àµ¾ ചെയàµà´¯àµà´•</translation>
<translation id="4302514097724775343">കളികàµà´•à´¾àµ» ദിനോസറിൽ ടാപàµà´ªàµ ചെയàµà´¯àµà´•</translation>
<translation id="4302965934281694568">Chou3 (എൻവലപàµà´ªàµ)</translation>
<translation id="4305666528087210886">നിങàµà´™à´³àµà´Ÿàµ† ഫയൽ ആകàµâ€Œà´¸à´¸àµ ചെയàµà´¯à´¾à´¨à´¾à´¯à´¿à´²àµà´²</translation>
-<translation id="4305817255990598646">à´¸àµà´µà´¿à´šàµà´šàµ ചെയàµà´¯àµà´•</translation>
+<translation id="4306529830550717874">വിലാസം സംരകàµà´·à´¿à´•àµà´•à´£àµ‹?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµà´¯àµà´• (ഡിഫോൾടàµà´Ÿàµ)</translation>
<translation id="4314815835985389558">സമനàµà´µà´¯à´¿à´ªàµà´ªà´¿à´•àµà´•àµ½ മാനേജൠചെയàµà´¯àµà´•</translation>
@@ -920,6 +945,7 @@
<translation id="4377125064752653719">നിങàµà´™à´³àµâ€â€Œ <ph name="DOMAIN" /> à´Žà´¨àµà´¨à´¤à´¿à´²àµâ€â€Œ à´Žà´¤àµà´¤à´¾à´¨àµâ€â€Œ à´¶àµà´°à´®à´¿à´šàµà´šàµ, പകàµà´·àµ‡ സെരàµâ€â€Œà´µà´°àµâ€â€Œ നൽകിയ സരàµâ€â€Œà´Ÿàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ അതൠനലàµâ€â€Œà´•à´¿à´¯ ആളàµâ€â€Œ അസാധàµà´µà´¾à´•àµà´•à´¿. സെരàµâ€â€Œà´µà´°àµâ€â€Œ നലàµâ€â€Œà´•à´¿à´¯ à´¸àµà´°à´•àµà´·à´¾ à´•àµà´°àµ†à´¡à´¨àµâ€â€Œà´·àµà´¯à´²àµà´•à´³àµâ€â€Œ തികചàµà´šàµà´‚ വിശàµà´µà´¾â€à´¸à´¯àµ‹à´—àµà´¯à´®à´²àµà´² à´Žà´¨àµà´¨à´¾à´£àµ ഇതിനരàµâ€â€Œà´¤àµà´¥à´‚. നിങàµà´™à´³àµâ€â€Œ ഒരൠആകàµà´°à´®à´£à´•à´¾à´°à´¿à´¯àµà´®à´¾à´¯à´¿à´Ÿàµà´Ÿà´¾à´•à´¾à´‚ ആശയവിനിമയം നടതàµà´¤àµà´¨àµà´¨à´¤àµ.</translation>
<translation id="4378154925671717803">ഫോൺ</translation>
<translation id="4390472908992056574">à´¬àµà´°à´¿à´‚</translation>
+<translation id="4406883609789734330">തതàµà´¸à´®à´¯ à´•àµà´¯à´¾à´ªàµà´·àµ»</translation>
<translation id="4406896451731180161">തിരയൽ ഫലങàµà´™àµ¾</translation>
<translation id="4408413947728134509">à´•àµà´•àµà´•à´¿à´•àµ¾ <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">വഞàµà´šà´¨à´¾à´ªà´°à´®à´¾à´¯ സൈറàµà´±à´¿àµ½ നിങàµà´™àµ¾ ഇപàµà´ªàµ‹àµ¾ പാസàµâ€à´µàµ‡à´¡àµ നൽകി. നിങàµà´™àµ¾ à´ˆ പാസàµâ€Œà´µàµ‡à´¡àµ ഉപയോഗികàµà´•àµà´¨àµà´¨ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> à´Žà´¨àµà´¨à´¿à´µà´¯à´¿à´²àµ‡à´•àµà´•àµà´‚ മറàµà´±àµ സൈറàµà´±àµà´•à´³à´¿à´²àµ‡à´•àµà´•àµà´‚ പോയി, ഇപàµà´ªàµ‹àµ¾ തനàµà´¨àµ† അതൠമാറàµà´±à´¾àµ» Chrome à´¶àµà´ªà´¾àµ¼à´¶ ചെയàµà´¯àµà´¨àµà´¨àµ.</translation>
@@ -932,7 +958,6 @@
<translation id="4435702339979719576">പോസàµâ€Œà´±àµà´±àµâ€Œ കാർഡàµ)</translation>
<translation id="443673843213245140">à´ªàµà´°àµ‹à´•àµâ€Œà´¸à´¿ ഉപയോഗം à´…à´ªàµà´°à´¾à´ªàµâ€Œà´¤à´®à´¾à´•àµà´•à´¿ പകàµà´·àµ† ഒരൠവàµà´¯à´•àµà´¤à´®à´¾à´¯ à´ªàµà´°àµ‹à´•àµâ€Œà´¸à´¿ കോൺഫിഗറേഷൻ നിർദàµà´¦àµ‡à´¶à´¿à´šàµà´šàµ.</translation>
<translation id="4464826014807964867">നിങàµà´™à´³àµà´Ÿàµ† à´¸àµà´¥à´¾à´ªà´¨à´¤àµà´¤à´¿àµ½ നിനàµà´¨àµà´³àµà´³ വിവരങàµà´™àµ¾ à´…à´Ÿà´™àµà´™à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨ വെബàµà´¸àµˆà´±àµà´±àµà´•àµ¾</translation>
-<translation id="4466881336512663640">ഫോം മാറàµà´±à´™àµà´™àµ¾ നഷàµâ€Œà´Ÿà´®à´¾à´•àµà´‚. à´¤àµà´Ÿà´°à´£à´®àµ†à´¨àµà´¨àµ നിങàµà´™àµ¾à´•àµà´•àµ തീർചàµà´šà´¯à´¾à´£àµ‹?</translation>
<translation id="4476953670630786061">à´ˆ ഫോം à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´²àµà´². à´¸àµà´µà´¯à´®àµ‡à´µ പൂരിപàµà´ªà´¿à´•àµà´•àµ½ ഓഫാകàµà´•à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ.</translation>
<translation id="4477350412780666475">à´…à´Ÿàµà´¤àµà´¤ à´Ÿàµà´°à´¾à´•àµà´•àµ</translation>
<translation id="4482953324121162758">à´ˆ സൈറàµà´±àµ വിവർതàµà´¤à´¨à´‚ ചെയàµà´¯à´ªàµà´ªàµ†à´Ÿà´¿à´²àµà´².</translation>
@@ -966,6 +991,7 @@
<translation id="4594403342090139922">&amp;ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´¨àµà´¨à´¤àµ പഴയപടിയാകàµà´•àµà´•</translation>
<translation id="4597348597567598915">വലàµà´ªàµà´ªà´‚ 8</translation>
<translation id="4600854749408232102">C6/C5 (എൻവലപàµà´ªàµ)</translation>
+<translation id="4606870351894164739">ഫലപàµà´°à´¦à´®à´¾à´¯à´¤àµ</translation>
<translation id="4628948037717959914">ഫോടàµà´Ÿàµ‹</translation>
<translation id="4631649115723685955">à´•àµà´¯à´¾à´·àµ ബാകàµà´•àµ ലിങàµà´•àµ ചെയàµâ€Œà´¤àµ</translation>
<translation id="4636930964841734540">വിവരം</translation>
@@ -985,6 +1011,7 @@
<translation id="4691835149146451662">ആരàµâ€à´•àµà´•à´¿à´Ÿàµ†à´•àµà´šàµà´šà´°àµâ€-A (എൻവലപàµà´ªàµ)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">സൈഡàµ</translation>
+<translation id="4702656508969495934">തതàµà´¸à´®à´¯ à´•àµà´¯à´¾à´ªàµà´·àµ» ദൃശàµà´¯à´®à´¾à´£àµ, ഫോകàµà´•à´¸àµ ചെയàµà´¯à´¾àµ» വിൻഡോ à´¸àµà´µà´¿à´šàµà´šàµ¼ ഉപയോഗികàµà´•àµà´•</translation>
<translation id="4708268264240856090">നിങàµà´™à´³àµà´Ÿàµ† കണകàµà´·àµ» തടസàµà´¸à´ªàµà´ªàµ†à´Ÿàµà´Ÿàµ</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµ ഡയഗണോസàµâ€Œà´±àµà´±à´¿à´•àµâ€Œà´¸àµ റൺ ചെയàµà´¯àµà´¨àµà´¨àµ<ph name="END_LINK" /></translation>
@@ -998,6 +1025,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> തിരയൽ നിർദàµà´¦àµ‡à´¶à´‚</translation>
<translation id="4742407542027196863">പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ മാനേജൠചെയàµà´¯àµà´•â€¦</translation>
<translation id="4744603770635761495">നിരàµâ€à´µàµà´µà´¹à´¿à´•àµà´•à´¾à´µàµà´¨àµà´¨ പാത</translation>
+<translation id="4749011317274908093">നിങàµà´™àµ¾ അദൃശàµà´¯ മോഡിലാണàµ</translation>
<translation id="4750917950439032686">നിങàµà´™à´³àµà´Ÿàµ† വിവരങàµà´™àµ¾ (ഉദാഹരണതàµà´¤à´¿à´¨àµ, പാസàµâ€Œà´µàµ‡à´¡àµà´•à´³àµ‹ à´•àµà´°àµ†à´¡à´¿à´±àµà´±àµ കാർഡൠനമàµà´ªà´±àµà´•à´³àµ‹) à´ˆ സൈറàµà´±à´¿à´²àµ‡à´•àµà´•àµ അയചàµà´šàµ à´•à´´à´¿à´žàµà´žà´¾àµ½ പിനàµà´¨àµ†à´¯à´¤àµ à´¸àµà´µà´•à´¾à´°àµà´¯à´®à´¾à´¯à´¿à´°à´¿à´•àµà´•àµà´‚.</translation>
<translation id="4756388243121344051">&amp;à´šà´°à´¿à´¤àµà´°à´‚</translation>
<translation id="4758311279753947758">കോൺടാകàµà´±àµà´±àµ വിവരങàµà´™àµ¾ ചേർകàµà´•àµà´•</translation>
@@ -1027,6 +1055,8 @@
<translation id="4813512666221746211">നെറàµà´±àµâ€Œà´µà´°àµâ€à´•àµà´•àµ പിശകàµ</translation>
<translation id="4816492930507672669">പേജിനൠയàµà´•àµà´¤à´®à´¾à´•àµà´•àµà´•</translation>
<translation id="4819347708020428563">ഡിഫോൾടàµà´Ÿàµ കാഴàµâ€Œà´šà´¯à´¿àµ½ à´•àµà´±à´¿à´ªàµà´ªàµà´•àµ¾ à´Žà´¡à´¿à´±àµà´±àµ ചെയàµà´¯à´£àµ‹?</translation>
+<translation id="4825507807291741242">ശകàµà´¤à´®à´¾à´¯à´¤àµ</translation>
+<translation id="4838327282952368871">മനോരാജàµà´¯à´¤àµà´¤à´¿àµ½ à´®àµà´´àµà´•à´¿à´¯à´¤àµ</translation>
<translation id="484462545196658690">à´¸àµà´µà´¯à´®àµ‡à´µ</translation>
<translation id="4850886885716139402">കാണàµà´•</translation>
<translation id="485316830061041779">ജരàµâ€à´®àµà´®à´¨àµâ€</translation>
@@ -1163,6 +1193,7 @@
<translation id="5314967030527622926">à´¬àµà´•àµà´•àµâ€Œà´²àµ†à´±àµà´±àµ മേകàµà´•àµ¼</translation>
<translation id="5316812925700871227">എതിർ ഘടികാരദിശയിൽ തിരികàµà´•àµà´•</translation>
<translation id="5317780077021120954">സംരകàµà´·à´¿à´•àµà´•àµà´•</translation>
+<translation id="5321288445143113935">പരമാവധി വലàµà´¤à´¾à´•àµà´•à´¿à´¯à´¤àµ</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> / <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">കോണàµâ€à´Ÿà´¾à´•àµà´±àµà´±àµ വിവരം തിരഞàµà´žàµ†à´Ÿàµà´•àµà´•àµà´•</translation>
<translation id="5327248766486351172">പേരàµ</translation>
@@ -1170,11 +1201,13 @@
<translation id="5332219387342487447">à´·à´¿à´ªàµà´ªà´¿à´‚ഗൠരീതി</translation>
<translation id="5333022057423422993">Chrome, നിങàµà´™àµ¾ ഇപàµà´ªàµ‹àµ¾ ഉപയോഗിചàµà´š പാസàµâ€Œà´µàµ‡à´¡àµ ഡാറàµà´±à´¾ ലംഘനതàµà´¤à´¿àµ½ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ. à´…à´•àµà´•àµ—à´£àµà´Ÿàµà´•àµ¾ à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´¾à´•àµà´•à´¾àµ», നിങàµà´™à´³àµà´Ÿàµ† സംരകàµà´·à´¿à´šàµà´š പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ പരിശോധികàµà´•à´¾àµ» à´žà´™àµà´™àµ¾ നിർദàµà´¦àµ‡à´¶à´¿à´•àµà´•àµà´¨àµà´¨àµ.</translation>
<translation id="5334013548165032829">വിശദമായ സിസàµâ€Œà´±àµà´±à´‚ ലോഗàµà´•àµ¾</translation>
+<translation id="5334145288572353250">വിലാസം സംരകàµà´·à´¿à´•àµà´•à´£àµ‹?</translation>
<translation id="5340250774223869109">ആപàµà´ªàµ à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµâ€Œà´¤àµ</translation>
<translation id="534295439873310000">NFC ഉപകരണങàµà´™àµ¾</translation>
<translation id="5344579389779391559">à´ˆ പേജൠനിങàµà´™à´³à´¿à´²àµâ€ നിനàµà´¨àµ പണം ഈടാകàµà´•à´¾à´¨à´¿à´Ÿà´¯àµà´£àµà´Ÿàµ</translation>
<translation id="5355557959165512791">സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ റദàµà´¦à´¾à´•àµà´•à´¿à´¯à´¤à´¿à´¨à´¾àµ½ നിങàµà´™àµ¾à´•àµà´•à´¿à´ªàµà´ªàµ‹àµ¾ <ph name="SITE" /> സനàµà´¦àµ¼à´¶à´¿à´•àµà´•à´¾à´¨à´¾à´•à´¿à´²àµà´². നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµ പിശകàµà´•à´³àµà´‚ ആകàµà´°à´®à´£à´™àµà´™à´³àµà´‚ സാധാരണ താൽകàµà´•à´¾à´²à´¿à´•à´®à´¾à´¯à´¿à´°à´¿à´•àµà´•àµà´‚, അതിനാൽ à´ˆ പേജൠമികàµà´•à´µà´¾à´±àµà´‚ പിനàµà´¨àµ€à´Ÿàµ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´•àµà´•àµà´‚.</translation>
<translation id="536296301121032821">നയ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™àµ¾ സംഭരികàµà´•àµà´¨àµà´¨à´¤à´¿àµ½ പരാജയപàµà´ªàµ†à´Ÿàµà´Ÿàµ</translation>
+<translation id="5363309033720083897">നിങàµà´™à´³àµà´Ÿàµ† à´…à´¡àµà´®à´¿àµ» à´…à´¨àµà´µà´¦à´¿à´šàµà´šà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨ സീരിയൽ പോർടàµà´Ÿàµ</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="5386426401304769735">à´ˆ സൈറàµà´±à´¿à´¨àµà´±àµ† സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ ചെയിനിൽ SHA-1 ഉപയോഗിചàµà´šàµ സൈൻ ചെയàµâ€Œà´¤ ഒരൠസർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ à´…à´Ÿà´™àµà´™à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ.</translation>
@@ -1183,6 +1216,7 @@
<translation id="5398772614898833570">പരസàµà´¯à´™àµà´™àµ¾ à´¬àµà´²àµ‹à´•àµà´•àµà´šàµ†à´¯àµâ€Œà´¤àµ</translation>
<translation id="5400836586163650660">ചാരനിറം</translation>
<translation id="540969355065856584">à´ˆ സെർവറിനൠഅതൠ<ph name="DOMAIN" /> ആണെനàµà´¨àµ തെളിയികàµà´•à´¾à´¨à´¾à´¯à´¿à´²àµà´²; അതിനàµà´±àµ† à´¸àµà´°à´•àµà´· സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±à´¿à´¨àµ ഇപàµà´ªàµ‹àµ¾ സാധàµà´¤à´¯àµà´³àµà´³à´¤à´²àµà´². തെറàµà´±à´¾à´¯ കോൺഫിഗറേഷൻ കാരണമോ ഒരൠആകàµà´°à´®à´£à´•à´¾à´°à´¿ നിങàµà´™à´³àµà´Ÿàµ† കണകàµà´·à´¨àµ† തടസàµà´¸à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´¨àµà´¨à´¤àµ കൊണàµà´Ÿàµ‹ ആയിരികàµà´•à´¾à´‚ ഇതൠസംഭവിചàµà´šà´¤àµ.</translation>
+<translation id="541143247543991491">à´•àµà´²àµ—ഡൠ(സിസàµâ€Œà´±àµà´±à´¤àµà´¤à´¿à´²àµà´Ÿà´¨àµ€à´³à´‚)</translation>
<translation id="541416427766103491">à´¸àµà´±àµà´±à´¾à´•àµà´•àµ¼ 4</translation>
<translation id="5421136146218899937">à´¬àµà´°àµ—സിംഗൠഡാറàµà´± മായàµâ€Œà´•àµà´•àµà´•...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> നിങàµà´™àµ¾à´•àµà´•àµ അറിയിപàµà´ªàµà´•àµ¾ അയയàµâ€Œà´•àµà´•à´¾àµ» ആഗàµà´°à´¹à´¿à´•àµà´•àµà´¨àµà´¨àµ</translation>
@@ -1196,6 +1230,7 @@
<translation id="5455374756549232013">മോശം നയ ടൈംസàµà´±àµà´±à´¾à´®àµà´ªàµ</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" /> à´Žà´£àµà´£à´µàµà´‚}other{<ph name="CONTACT_PREVIEW" /> à´Žà´¨àµà´¨à´¤àµà´‚ മറàµà´±àµ <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> à´Žà´£àµà´£à´µàµà´‚}}</translation>
+<translation id="5463625433003343978">ഉപകരണങàµà´™àµ¾ à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´¨àµà´¨àµ...</translation>
<translation id="5469868506864199649">ഇറàµà´±à´¾à´²à´¿à´¯à´¨àµâ€</translation>
<translation id="5470861586879999274">&amp;à´Žà´¡à´¿à´±àµà´±àµà´šàµ†à´¯àµà´¯àµà´¨àµà´¨à´¤àµ വീണàµà´Ÿàµà´‚ ചെയàµà´¯àµà´•</translation>
<translation id="5478437291406423475">B6/C4 (എൻവലപàµà´ªàµ)</translation>
@@ -1245,7 +1280,6 @@
<translation id="5624120631404540903">പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ നിയനàµà´¤àµà´°à´¿à´•àµà´•àµà´•</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="563324245173044180">തെറàµà´±à´¿à´¦àµà´§à´°à´¿à´ªàµà´ªà´¿à´•àµà´•àµà´¨àµà´¨ ഉളàµà´³à´Ÿà´•àµà´•à´‚ à´¬àµà´²àµ‹à´•àµà´•àµà´šàµ†à´¯àµâ€Œà´¤àµ.</translation>
<translation id="5644090287519800334">സൈഡൠ1 à´šà´¿à´¤àµà´°à´‚ X à´·à´¿à´«àµà´±àµà´±àµ</translation>
@@ -1284,12 +1318,12 @@
<translation id="5785756445106461925">കൂടാതെ, à´ˆ പേജിൽ à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´²àµà´²à´¾à´¤àµà´¤ മറàµà´±àµ ഉറവിടങàµà´™àµ¾ ഉൾപàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµ. à´ˆ ഉറവിടങàµà´™àµ¾ കൈമാറàµà´¨àµà´¨à´¤à´¿à´¨à´¿à´Ÿàµ† മറàµà´±àµà´³àµà´³à´µàµ¼à´•àµà´•àµ കാണാനàµà´‚ പേജിനàµà´±àµ† രൂപം മാറàµà´±àµà´¨àµà´¨ തരതàµà´¤à´¿àµ½ ഒരൠആകàµà´°à´®à´£à´•à´¾à´°à´¿à´¯àµâ€Œà´•àµà´•àµ പരിഷàµâ€Œà´•àµà´•à´°à´¿à´•àµà´•à´¾à´¨àµà´®à´¾à´¯àµ‡à´•àµà´•àµà´‚.</translation>
<translation id="5786044859038896871">നിങàµà´™à´³àµà´Ÿàµ† കാർഡൠവിവരം പൂരിപàµà´ªà´¿à´•àµà´•à´£àµ‹?</translation>
<translation id="578633867165174378">Chrome, നിങàµà´™àµ¾ ഇപàµà´ªàµ‹àµ¾ ഉപയോഗിചàµà´š പാസàµâ€Œà´µàµ‡à´¡àµ ഡാറàµà´±à´¾ ലംഘനതàµà´¤à´¿àµ½ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ. à´ˆ പാസàµâ€Œà´µàµ‡à´¡àµ ഇപàµà´ªàµ‹àµ¾ തനàµà´¨àµ† മാറàµà´±à´¾àµ» à´žà´™àµà´™àµ¾ നിർദàµà´¦àµ‡à´¶à´¿à´•àµà´•àµà´¨àµà´¨àµ.</translation>
-<translation id="5798290721819630480">മാറàµà´±à´™àµà´™àµ¾ നിരസികàµà´•à´£àµ‹?</translation>
<translation id="5803412860119678065">നിങàµà´™à´³àµà´Ÿàµ† <ph name="CARD_DETAIL" /> പൂരിപàµà´ªà´¿à´•àµà´•à´£àµ‹?</translation>
<translation id="5804241973901381774">à´…à´¨àµà´®à´¤à´¿à´•àµ¾</translation>
<translation id="5804427196348435412">NFC ഉപകരണങàµà´™àµ¾ ഉപയോഗികàµà´•àµà´•</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> à´Žà´¨àµà´¨à´¤à´¿à´²àµ‡à´•àµà´•àµà´³àµà´³ നിങàµà´™à´³àµà´Ÿàµ† കണകàµà´·àµ» കാലഹരണപàµà´ªàµ†à´Ÿàµà´Ÿ സൈഫർ à´¸àµà´¯àµ‚à´Ÿàµà´Ÿàµ ഉപയോഗിചàµà´šàµ എൻകàµà´°à´¿à´ªàµà´±àµà´±àµà´šàµ†à´¯àµâ€Œà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ.</translation>
<translation id="5813119285467412249">&amp;ചേർതàµà´¤à´¤àµ വീണàµà´Ÿàµà´‚ ചെയàµà´¯àµà´•</translation>
+<translation id="5817918615728894473">ജോടിയാകàµà´•àµà´•</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{നിങàµà´™àµ¾ പണമടയàµà´•àµà´•àµà´®àµà´ªàµ‹àµ¾ à´ˆ കാർഡിൽ നിനàµà´¨àµ നിരകàµà´•àµ ഈടാകàµà´•àµà´‚, à´Žà´¨àµà´¨à´¾àµ½ à´ˆ സൈറàµà´±àµà´®à´¾à´¯à´¿ അതിനàµà´±àµ† യഥാർതàµà´¥ നമàµà´ªàµ¼ പങàµà´•à´¿à´Ÿà´¿à´²àµà´². അധിക à´¸àµà´°à´•àµà´·à´¯àµà´•àµà´•àµ താൽകàµà´•à´¾à´²à´¿à´•à´®à´¾à´¯ ഒരൠCVC സൃഷàµà´Ÿà´¿à´•àµà´•àµà´‚.}other{നിങàµà´™àµ¾ പണമടയàµà´•àµà´•àµà´®àµà´ªàµ‹àµ¾, നിങàµà´™àµ¾ തിരഞàµà´žàµ†à´Ÿàµà´¤àµà´¤ കാർഡിൽ നിനàµà´¨àµ നിരകàµà´•àµ ഈടാകàµà´•àµà´‚, à´Žà´¨àµà´¨à´¾àµ½ à´ˆ സൈറàµà´±àµà´®à´¾à´¯à´¿ അതിനàµà´±àµ† യഥാർതàµà´¥ നമàµà´ªàµ¼ പങàµà´•à´¿à´Ÿà´¿à´²àµà´². അധിക à´¸àµà´°à´•àµà´·à´¯àµà´•àµà´•àµ താൽകàµà´•à´¾à´²à´¿à´•à´®à´¾à´¯ ഒരൠCVC സൃഷàµà´Ÿà´¿à´•àµà´•àµà´‚.}}</translation>
<translation id="5826507051599432481">പൊതàµà´µà´¾à´¯ പേരൠ(CN)</translation>
<translation id="5838278095973806738">à´…à´•àµà´°à´®à´•à´¾à´°à´¿à´•àµ¾ മോഷàµâ€Œà´Ÿà´¿à´•àµà´•à´¾àµ» സാധàµà´¯à´¤à´¯àµà´³àµà´³à´¤à´¿à´¨à´¾àµ½ à´ˆ സൈറàµà´±à´¿àµ½ നിങàµà´™à´³àµà´Ÿàµ† രഹസàµà´¯ വിവരങàµà´™à´³àµŠà´¨àµà´¨àµà´‚ (ഉദാഹരണതàµà´¤à´¿à´¨àµ, പാസàµâ€Œà´µàµ‡à´¡àµà´•à´³àµ‹ à´•àµà´°àµ†à´¡à´¿à´±àµà´±àµ കാർഡàµà´•à´³àµ‹ പോലàµà´³àµà´³à´µ) നൽകരàµà´¤àµ.</translation>
@@ -1297,6 +1331,7 @@
<translation id="5855253129151731373">à´ˆ സൈറàµà´±à´¿à´¨àµà´±àµ† ഹോസàµà´±àµà´±àµ നാമം <ph name="LOOKALIKE_DOMAIN" /> à´Žà´¨àµà´¨à´¤à´¿à´¨àµà´±àµ† പേരിനൠസമാനമായി തോനàµà´¨àµà´¨àµà´¨àµ. ഡൊമെയàµàµ» നാമതàµà´¤à´¿àµ½ ചിലപàµà´ªàµ‹àµ¾ ചെറàµà´¤àµà´‚ കാണാൻ à´¬àµà´¦àµà´§à´¿à´®àµà´Ÿàµà´Ÿàµà´³àµà´³à´¤àµà´®à´¾à´¯ മാറàµà´±à´™àµà´™àµ¾ വരàµà´¤àµà´¤à´¿, ആകàµà´°à´®à´£à´•à´¾à´°à´¿à´•àµ¾ സൈറàµà´±àµà´•à´³àµà´Ÿàµ† à´…à´¨àµà´•à´°à´£ രൂപം സൃഷàµâ€Œà´Ÿà´¿à´•àµà´•à´¾à´±àµà´£àµà´Ÿàµ.
ഇതൠപിശകിനാൽ കാണിചàµà´šà´¤à´¾à´£àµ†à´¨àµà´¨àµ നിങàµà´™àµ¾ വിശàµà´µà´¸à´¿à´•àµà´•àµà´¨àµà´¨àµà´µàµ†à´™àµà´•à´¿àµ½, https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals സനàµà´¦àµ¼à´¶à´¿à´•àµà´•àµà´•.</translation>
+<translation id="5860033963881614850">ഓഫാകàµà´•àµà´•</translation>
<translation id="5862579898803147654">à´¸àµà´±àµà´±à´¾à´•àµà´•àµ¼ 8</translation>
<translation id="5863847714970149516">à´®àµà´®àµà´ªàµ‹à´Ÿàµà´Ÿàµà´³àµà´³ പേജൠനിങàµà´™à´³à´¿àµ½ നിനàµà´¨àµ പണമീടാകàµà´•à´¾àµ» à´¶àµà´°à´®à´¿à´šàµà´šàµ‡à´•àµà´•à´¾à´‚</translation>
<translation id="5866257070973731571">ഫോണàµâ€ നമàµà´ªà´°àµâ€ ചേരàµâ€à´•àµà´•àµà´•</translation>
@@ -1313,6 +1348,7 @@
<translation id="5913377024445952699">à´¸àµâ€Œà´•àµà´°àµ€àµ» à´•àµà´¯à´¾à´ªàµâ€Œà´šàµ¼ താൽകàµà´•à´¾à´²à´¿à´•à´®à´¾à´¯à´¿ നിർതàµà´¤à´¿</translation>
<translation id="59174027418879706">à´ªàµà´°à´¾à´ªàµà´¤à´®à´¾à´•àµà´•à´¿</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{ഒരെണàµà´£à´‚ ഉപയോഗതàµà´¤à´¿à´²àµà´£àµà´Ÿàµ}other{# à´Žà´£àµà´£à´‚ ഉപയോഗതàµà´¤à´¿à´²àµà´£àµà´Ÿàµ}}</translation>
<translation id="5921185718311485855">ഓണാണàµ</translation>
<translation id="5921639886840618607">Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ കാർഡൠസംരകàµà´·à´¿à´•àµà´•à´£àµ‹?</translation>
<translation id="5922853866070715753">à´à´¤à´¾à´£àµà´Ÿàµ പൂർതàµà´¤à´¿à´¯à´¾à´¯à´¿</translation>
@@ -1332,6 +1368,7 @@
<translation id="5989320800837274978">ഒരൠസàµà´¥à´¿à´°à´®à´¾à´¯ à´ªàµà´°àµ‹à´•àµà´¸à´¿ സെർവർ à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ ഒരൠ.pac à´¸àµâ€Œà´•àµà´°à´¿à´ªàµà´±àµà´±àµ URL à´µàµà´¯à´•àµà´¤à´®à´¾à´•àµà´•à´¿à´¯à´¿à´Ÿàµà´Ÿà´¿à´²àµà´².</translation>
<translation id="5992691462791905444">à´Žà´žàµà´šà´¿à´¨àµ€à´¯à´±à´¿à´‚ഗൠZ-മടകàµà´•àµ</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' à´Žà´¨àµà´¨à´¤à´¿à´¨à´¾à´¯à´¿ <ph name="RESULT_COUNT" /> ഫലങàµà´™à´³àµâ€</translation>
+<translation id="6006484371116297560">à´•àµà´²à´¾à´¸à´¿à´•àµ</translation>
<translation id="6008122969617370890">N-1 à´•àµà´°à´®à´¤àµà´¤à´¿àµ½</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">നിങàµà´™à´³àµà´Ÿàµ† പാസàµâ€à´µàµ‡à´¡àµà´•àµ¾ പരിശോധികàµà´•àµà´•</translation>
@@ -1353,6 +1390,7 @@
<translation id="6045164183059402045">ഇംപോസിഷൻ ടെംപàµà´²àµ‡à´±àµà´±àµ</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="6049004884579590341">പൂർണàµà´£ à´¸àµâ€Œà´•àµà´°àµ€à´¨à´¿àµ½ നിനàµà´¨àµ à´ªàµà´±à´¤àµà´¤àµà´•à´Ÿà´•àµà´•à´¾àµ», |<ph name="ACCELERATOR" />| അമർതàµà´¤à´¿à´ªàµà´ªà´¿à´Ÿà´¿à´•àµà´•àµà´•â€Œ</translation>
<translation id="6049488691372270142">പേജൠഡെലിവറി</translation>
<translation id="6051221802930200923"><ph name="SITE" /> à´Žà´¨àµà´¨ വെബàµâ€Œà´¸àµˆà´±àµà´±àµ സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ പിനàµà´¨à´¿à´‚ഗൠഉപയോഗികàµà´•àµà´¨àµà´¨à´¤à´¿à´¨à´¾àµ½ നിങàµà´™àµ¾à´•àµà´•à´¿à´ªàµà´ªàµ‹àµ¾ അതൠസനàµà´¦àµ¼à´¶à´¿à´•àµà´•à´¾à´¨à´¾à´•à´¿à´²àµà´². നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµ പിശകàµà´•à´³àµà´‚ ആകàµà´°à´®à´£à´™àµà´™à´³àµà´‚ സാധാരണയായി താൽകàµà´•à´¾à´²à´¿à´•à´®à´¾à´¯à´¿à´°à´¿à´•àµà´•àµà´‚, അതിനാൽ à´ˆ പേജൠമികàµà´•à´µà´¾à´±àµà´‚ പിനàµà´¨àµ€à´Ÿàµ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´•àµà´•àµà´‚.</translation>
<translation id="6051898664905071243">പേജിനàµà´±àµ† à´Žà´£àµà´£à´‚:</translation>
@@ -1369,6 +1407,7 @@
<translation id="610911394827799129">നിങàµà´™à´³àµà´Ÿàµ† Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿à´¨àµ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> à´Žà´¨àµà´¨à´¤à´¿àµ½ മറàµà´±àµ തരതàµà´¤à´¿à´²àµà´³àµà´³ à´¬àµà´°àµ—സിംഗൠചരിതàµà´°à´®àµà´£àµà´Ÿà´¾à´¯à´¿à´°à´¿à´•àµà´•à´¾à´‚.</translation>
<translation id="6116338172782435947">à´•àµà´²à´¿à´ªàµà´ªàµâ€Œà´¬àµ‹àµ¼à´¡à´¿à´²àµ‡à´•àµà´•àµ പകർതàµà´¤à´¿à´¯à´¿à´Ÿàµà´Ÿàµà´³àµà´³ ടെകàµâ€Œà´¸àµà´±àµà´±àµà´‚ à´šà´¿à´¤àµà´°à´™àµà´™à´³àµà´‚ കാണàµà´•</translation>
<translation id="6120179357481664955">നിങàµà´™à´³àµà´Ÿàµ† UPI à´à´¡à´¿ ഓർമàµà´®à´¯àµà´£àµà´Ÿàµ‹?</translation>
+<translation id="6123290840358279103">വെർചàµà´µàµ½ കാർഡൠകാണàµà´•</translation>
<translation id="6124432979022149706">Chrome à´Žà´¨àµà´±àµ¼à´ªàµà´°àµˆà´¸àµ കണകàµà´±àµà´±à´±àµà´•àµ¾</translation>
<translation id="6146055958333702838">à´Žà´²àµà´²à´¾ കേബിളàµà´•à´³àµà´‚ പരിശോധികàµà´•àµà´• à´’à´ªàµà´ªà´‚ à´à´¤àµ†à´™àµà´•à´¿à´²àµà´‚ റൂടàµà´Ÿà´±àµà´•àµ¾, മോഡങàµà´™àµ¾ നിങàµà´™àµ¾ ഉപയോഗികàµà´•à´¾à´¨à´¿à´Ÿà´¯àµà´³àµà´³
മറàµà´±àµ നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµ ഉപകരണങàµà´™àµ¾ à´Žà´¨àµà´¨à´¿à´µ റീബൂടàµà´Ÿàµ ചെയàµà´¯àµà´•.</translation>
@@ -1405,6 +1444,7 @@
<translation id="6289939620939689042">പേജിനàµà´±àµ† നിറം</translation>
<translation id="6290238015253830360">നിങàµà´™à´³àµà´Ÿàµ† നിർദàµà´¦àµ‡à´¶à´¿à´šàµà´š ലേഖനങàµà´™àµ¾ ഇവിടെ ദൃശàµà´¯à´®à´¾à´•àµà´‚</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome à´¸àµà´µà´®àµ‡à´§à´¯à´¾ പൂരിപàµà´ªà´¿à´•àµà´•àµ½ നിർതàµà´¤àµà´¨àµà´¨à´¤à´¿à´²àµ† Google അസിസàµâ€Œà´±àµà´±à´¨àµà´±àµ സാനàµà´¨à´¿à´§àµà´¯à´‚</translation>
<translation id="6305205051461490394"><ph name="URL" /> ലഭàµà´¯à´®à´²àµà´².</translation>
<translation id="6312113039770857350">വെബàµà´ªàµ‡à´œàµ ലഭàµà´¯à´®à´²àµà´²</translation>
@@ -1430,6 +1470,7 @@
<translation id="6390200185239044127">പകàµà´¤à´¿ Z-മടകàµà´•àµ</translation>
<translation id="6390662030813198813">à´Žà´žàµà´šà´¿à´¨àµ€à´¯à´±à´¿à´‚à´—àµ-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> -ൽ നിനàµà´¨àµ à´ˆ ലൊകàµà´•àµ‡à´·à´¨à´¿àµ½ à´’à´Ÿàµà´Ÿà´¿à´•àµà´•àµà´¨àµà´¨à´¤àµ നിങàµà´™à´³àµà´Ÿàµ† à´…à´¡àµâ€Œà´®à´¿àµ» നയം à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ</translation>
+<translation id="6398765197997659313">പൂരàµâ€à´£àµà´£ à´¸àµà´•àµà´°àµ€à´¨à´¿à´²àµâ€ നിനàµà´¨àµ à´ªàµà´±à´¤àµà´¤àµà´•à´Ÿà´•àµà´•àµà´•</translation>
<translation id="6401136357288658127">à´ˆ നയം അവസാനിപàµà´ªà´¿à´šàµà´šàµ. പകരം <ph name="NEW_POLICY" /> നയം ഉപയോഗികàµà´•à´£à´‚.</translation>
<translation id="6404511346730675251">à´¬àµà´•àµà´•àµâ€Œà´®à´¾àµ¼à´•àµà´•àµ à´Žà´¡à´¿à´±àµà´±àµ ചെയàµà´¯àµà´•</translation>
<translation id="6406765186087300643">C0 (എൻവലപàµà´ªàµ)</translation>
@@ -1442,7 +1483,6 @@
<translation id="6428450836711225518">നിങàµà´™à´³àµà´Ÿàµ† ഫോൺ നമàµà´ªàµ¼ പരിശോധിചàµà´šàµà´±à´ªàµà´ªà´¿à´•àµà´•àµà´•</translation>
<translation id="6433490469411711332">കോൺടാകàµâ€Œà´±àµà´±àµ വിവരം à´Žà´¡à´¿à´±àµà´±àµ ചെയàµà´¯àµà´•</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> കണകàµâ€Œà´±àµà´±àµà´šàµ†à´¯àµà´¯àµ½ നിരസിചàµà´šàµ.</translation>
-<translation id="6434309073475700221">നിരാകരികàµà´•àµà´•</translation>
<translation id="6440503408713884761">അവഗണിചàµà´šàµ</translation>
<translation id="6443406338865242315">à´à´¤àµŠà´•àµà´•àµ† വിപàµà´²àµ€à´•à´°à´£à´™àµà´™à´³àµà´‚ à´ªàµà´²à´—à´¿à´¨àµà´•à´³àµà´‚ നിങàµà´™àµ¾ ഇൻസàµâ€Œà´±àµà´±à´¾àµ¾ ചെയàµà´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ à´Žà´¨àµà´¨à´¤àµ</translation>
<translation id="6446163441502663861">കഹൠ(എൻവലപàµà´ªàµ)</translation>
@@ -1485,6 +1525,7 @@
<translation id="6624427990725312378">കോണàµâ€à´Ÿà´¾à´•àµà´±àµà´±àµ വിവരം</translation>
<translation id="6626291197371920147">ശരിയായ കാർഡൠനമàµà´ªàµ¼ ചേർകàµà´•àµà´•</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> തിരയൽ</translation>
+<translation id="6630043285902923878">USB ഉപകരണങàµà´™àµ¾ à´•à´£àµà´Ÿàµ†à´¤àµà´¤àµà´¨àµà´¨àµ...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">മായàµâ€Œà´•àµà´•àµà´•</translation>
@@ -1500,6 +1541,7 @@
<translation id="6671697161687535275">Chromium-à´¤àµà´¤à´¿àµ½ നിനàµà´¨àµ ഫോം നിർദàµà´¦àµ‡à´¶à´‚ നീകàµà´•à´‚ചെയàµà´¯à´£àµ‹?</translation>
<translation id="6685834062052613830">സൈൻ ഔടàµà´Ÿàµ ചെയàµâ€Œà´¤àµ, സജàµà´œà´®à´¾à´•àµà´•àµ½ പൂർതàµà´¤à´¿à´¯à´¾à´•àµà´•àµà´•</translation>
<translation id="6687335167692595844">à´…à´­àµà´¯àµ¼à´¤àµà´¥à´¿à´šàµà´š ഫോണàµà´Ÿàµ വലàµà´ªàµà´ªà´‚</translation>
+<translation id="6688743156324860098">à´…à´ªàµà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´•â€¦</translation>
<translation id="6689249931105087298">à´¬àµà´²à´¾à´•àµà´•àµ പോയിനàµà´±àµ à´•à´‚à´ªàµà´°à´·à´¨àµ‹à´Ÿàµ കൂടിയ റിലേറàµà´±àµ€à´µàµ</translation>
<translation id="6689271823431384964">നിങàµà´™àµ¾ സൈൻ ഇൻ ചെയàµâ€Œà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨à´¾à´²à´¾à´£àµ നിങàµà´™à´³àµà´Ÿàµ† Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ കാർഡàµà´•àµ¾ സംരകàµà´·à´¿à´•àµà´•à´¾à´®àµ†à´¨àµà´¨àµ Chrome വാഗàµâ€Œà´¦à´¾à´¨à´‚ ചെയàµà´¯àµà´¨àµà´¨à´¤àµ. à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ à´ˆ രീതി മാറàµà´±à´¾à´¨à´¾à´•àµà´‚. കാർഡàµà´Ÿà´®à´¯àµà´Ÿàµ† പേരൠനിങàµà´™à´³àµà´Ÿàµ† à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿àµ½ നിനàµà´¨àµà´®à´¾à´£àµ വനàµà´¨à´¤àµ.</translation>
<translation id="6698381487523150993">സൃഷàµà´Ÿà´¿à´šàµà´šàµ:</translation>
@@ -1515,6 +1557,7 @@
<translation id="6744009308914054259">കണകàµâ€Œà´·à´¨à´¾à´¯à´¿ കാതàµà´¤à´¿à´°à´¿à´•àµà´•àµà´®àµà´ªàµ‹àµ¾, à´“à´«àµâ€Œà´²àµˆàµ» ലേഖനങàµà´™àµ¾ വായികàµà´•à´¾à´¨à´¾à´¯à´¿ നിങàµà´™àµ¾à´•àµà´•àµ ഡൗൺലോഡàµà´•àµ¾ സനàµà´¦àµ¼à´¶à´¿à´•àµà´•à´¾à´‚.</translation>
<translation id="6753269504797312559">നയ മൂലàµà´¯à´‚</translation>
<translation id="6757797048963528358">നിങàµà´™à´³àµà´Ÿàµ† ഉപകരണം à´¸àµà´²àµ€à´ªàµà´ªàµ മോഡിലായി</translation>
+<translation id="6767985426384634228">വിലാസം à´…à´ªàµà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯à´£àµ‹?</translation>
<translation id="6768213884286397650">ഹഗാകàµà´•à´¿ (പോസàµâ€Œà´±àµà´±àµâ€Œà´•à´¾àµ¼à´¡àµ)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">വയലറàµà´±àµ</translation>
@@ -1524,7 +1567,7 @@
<translation id="6794951432696553238">Windows Hello ഉപയോഗിചàµà´šàµ നിങàµà´™à´³àµà´Ÿàµ† കാർഡàµà´•àµ¾ ഇപàµà´ªàµ‡à´¾àµ¾ à´®àµà´¤àµ½ വേഗതàµà´¤à´¿àµ½ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•àµà´•</translation>
<translation id="681021252041861472">ഇതൠപൂരിപàµà´ªà´¿à´•àµà´•àµ‡à´£àµà´Ÿà´¤àµà´£àµà´Ÿàµ</translation>
<translation id="6810899417690483278">ഇഷàµâ€Œà´Ÿà´¾à´¨àµà´¸àµƒà´¤à´®à´¾à´•àµà´•àµ½ à´à´¡à´¿</translation>
-<translation id="6825578344716086703">നിങàµà´™àµ¾ <ph name="DOMAIN" /> à´Žà´¨àµà´¨à´¤à´¿àµ½ à´Žà´¤àµà´¤à´¾àµ» à´¶àµà´°à´®à´¿à´šàµà´šàµ, പകàµà´·àµ‡ ഒരൠദàµàµ¼à´¬à´²à´®à´¾à´¯ സിഗàµâ€Œà´¨àµ‡à´šàµà´šàµ¼ അൽഗരിതം ഉപയോഗിചàµà´šàµ à´’à´ªàµà´ªà´¿à´Ÿàµà´Ÿ ഒരൠസർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ സെർവർ നൽകി. ഇതിനർതàµà´¥à´‚ സെർവർ നൽകിയ à´¸àµà´°à´•àµà´·à´¾ à´•àµà´°àµ†à´¡àµ»à´·àµà´¯à´²àµà´•àµ¾ à´µàµà´¯à´¾à´œà´®à´¾à´•à´¾à´®àµ†à´¨àµà´¨àµà´‚ നിങàµà´™àµ¾ ഉദàµà´¦àµ‡à´¶à´¿à´šàµà´š സെർവർ ആയിരികàµà´•à´¿à´²àµà´² à´Žà´¨àµà´¨àµà´®à´¾à´£àµ (നിങàµà´™àµ¾ ആകàµà´°à´®à´£à´•à´¾à´°à´¿à´¯àµà´®à´¾à´¯à´¿à´Ÿàµà´Ÿà´¾à´•à´¾à´‚ ആശയവിനിമയം നടതàµà´¤àµà´¨àµà´¨à´¤àµ).</translation>
+<translation id="6825578344716086703">നിങàµà´™àµ¾ <ph name="DOMAIN" /> à´Žà´¨àµà´¨à´¤à´¿àµ½ à´Žà´¤àµà´¤à´¾àµ» à´¶àµà´°à´®à´¿à´šàµà´šàµ, പകàµà´·àµ‡ ഒരൠദàµàµ¼à´¬à´²à´®à´¾à´¯ സിഗàµâ€Œà´¨àµ‡à´šàµà´šàµ¼ ആൽഗരിതം ഉപയോഗിചàµà´šàµ à´’à´ªàµà´ªà´¿à´Ÿàµà´Ÿ ഒരൠസർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ സെർവർ നൽകി. ഇതിനർതàµà´¥à´‚ സെർവർ നൽകിയ à´¸àµà´°à´•àµà´·à´¾ à´•àµà´°àµ†à´¡àµ»à´·àµà´¯à´²àµà´•àµ¾ à´µàµà´¯à´¾à´œà´®à´¾à´•à´¾à´®àµ†à´¨àµà´¨àµà´‚ നിങàµà´™àµ¾ ഉദàµà´¦àµ‡à´¶à´¿à´šàµà´š സെർവർ ആയിരികàµà´•à´¿à´²àµà´² à´Žà´¨àµà´¨àµà´®à´¾à´£àµ (നിങàµà´™àµ¾ ആകàµà´°à´®à´£à´•à´¾à´°à´¿à´¯àµà´®à´¾à´¯à´¿à´Ÿàµà´Ÿà´¾à´•à´¾à´‚ ആശയവിനിമയം നടതàµà´¤àµà´¨àµà´¨à´¤àµ).</translation>
<translation id="6826993739343257035">AR à´…à´¨àµà´µà´¦à´¿à´•àµà´•à´£àµ‹?</translation>
<translation id="6831043979455480757">Translate</translation>
<translation id="6839929833149231406">à´à´°à´¿à´¯</translation>
@@ -1537,6 +1580,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">വായന à´Žà´³àµà´ªàµà´ªà´®à´¾à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ Chrome à´ˆ പേജൠലളിതമാകàµà´•à´¿. à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´²àµà´²à´¾à´¤àµà´¤ കണകàµà´·à´¨à´¿à´²àµ‚ടെ Chrome ഒറിജിനൽ പേജൠവീണàµà´Ÿàµ†à´Ÿàµà´¤àµà´¤àµ.</translation>
<translation id="6891596781022320156">നയ നില പിനàµà´¤àµà´£à´¯àµà´•àµà´•àµà´¨àµà´¨à´¿à´²àµà´².</translation>
+<translation id="6895143722905299846">വെർചàµà´µàµ½ നമàµà´ªàµ¼:</translation>
<translation id="6895330447102777224">നിങàµà´™à´³àµà´Ÿàµ† കാർഡൠസàµà´¥à´¿à´°àµ€à´•à´°à´¿à´šàµà´šàµ</translation>
<translation id="6897140037006041989">ഉപയോകàµà´¤àµƒ à´à´œà´¨àµâ€à´±àµ</translation>
<translation id="6898699227549475383">à´“à´°àµâ€â€Œà´—നൈസേഷനàµâ€â€Œ (O)</translation>
@@ -1565,17 +1609,17 @@
<translation id="6975012522936652259">വഞàµà´šà´¨à´¾à´ªà´°à´®à´¾à´¯ സൈറàµà´±à´¿àµ½ നിങàµà´™àµ¾ ഇപàµà´ªàµ‹àµ¾ പാസàµâ€à´µàµ‡à´¡àµ നൽകി. നിങàµà´™àµ¾ à´ˆ പാസàµâ€Œà´µàµ‡à´¡àµ ഉപയോഗികàµà´•àµà´¨àµà´¨ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, മറàµà´±àµ സൈറàµà´±àµà´•àµ¾ à´Žà´¨àµà´¨à´¿à´µà´¯à´¿à´²àµ‡à´•àµà´•àµ പോയി, ഇപàµà´ªàµ‹àµ¾ തനàµà´¨àµ† അതൠമാറàµà´±à´¾àµ» Chromium à´¶àµà´ªà´¾àµ¼à´¶ ചെയàµà´¯àµà´¨àµà´¨àµ.</translation>
<translation id="6979158407327259162">Google Drive</translation>
<translation id="6979440798594660689">à´®àµà´¯àµ‚à´Ÿàµà´Ÿàµ ചെയàµà´¯àµà´• (ഡിഫോൾടàµà´Ÿàµ)</translation>
-<translation id="6979983982287291980">നിങàµà´™àµ¾ ഡൗൺലോഡൠചെയàµà´¯àµà´¨àµà´¨ ഫയലàµà´•àµ¾ വിശകലനം ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿à´¨àµ Google à´•àµà´²àµ—ഡിലേകàµà´•àµ‹ മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿à´•àµ¾à´•àµà´•àµ‹ അയയàµà´•àµà´•àµà´¨àµà´¨àµ. ഉദാഹരണതàµà´¤à´¿à´¨àµ, സെൻസിറàµà´±àµ€à´µà´¾à´¯à´¿à´Ÿàµà´Ÿàµà´³àµà´³ à´µàµà´¯à´•àµà´¤à´¿à´ªà´°à´®à´¾à´¯ ഡാറàµà´±à´¯àµ‹ മാൽവേറോ ഉണàµà´Ÿàµ‹à´¯àµ†à´¨àµà´¨à´±à´¿à´¯à´¾àµ» à´…à´µ à´¸àµâ€Œà´•à´¾àµ» ചെയàµâ€Œà´¤àµ‡à´•àµà´•à´¾à´‚.</translation>
+<translation id="6979983982287291980">നിങàµà´™àµ¾ ഡൗൺലോഡൠചെയàµà´¯àµà´¨àµà´¨ ഫയലàµà´•àµ¾ വിശകലനം ചെയàµà´¯àµà´¨àµà´¨à´¤à´¿à´¨àµ Google à´•àµà´²àµ—ഡിലേകàµà´•àµ‹ മൂനàµà´¨à´¾à´‚ à´•à´•àµà´·à´¿à´•àµ¾à´•àµà´•àµ‹ അയയàµà´•àµà´•àµà´¨àµà´¨àµ. ഉദാഹരണതàµà´¤à´¿à´¨àµ, സെൻസിറàµà´±àµ€à´µà´¾à´¯à´¿à´Ÿàµà´Ÿàµà´³àµà´³ à´µàµà´¯à´•àµà´¤à´¿à´ªà´°à´®à´¾à´¯ ഡാറàµà´±à´¯àµ‹ മാൽവെയറോ ഉണàµà´Ÿàµ‹à´¯àµ†à´¨àµà´¨à´±à´¿à´¯à´¾àµ» à´…à´µ à´¸àµâ€Œà´•à´¾àµ» ചെയàµâ€Œà´¤àµ‡à´•àµà´•à´¾à´‚.</translation>
<translation id="6989763994942163495">വിപàµà´²à´®à´¾à´¯ à´•àµà´°à´®àµ€à´•à´°à´£à´™àµà´™àµ¾ കാണികàµà´•àµà´•...</translation>
<translation id="6993898126790112050">6x9 (എൻവലപàµà´ªàµ)</translation>
<translation id="6996312675313362352"><ph name="ORIGINAL_LANGUAGE" /> à´Žà´²àµà´²à´¾à´¯àµâ€Œà´ªàµà´ªàµ‹à´´àµà´‚ വിവർതàµà´¤à´¨à´‚ ചെയàµà´¯àµà´•</translation>
<translation id="7004583254764674281">കാർഡàµà´•àµ¾ വേഗതàµà´¤à´¿àµ½ à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•à´¾àµ» Windows Hello ഉപയോഗികàµà´•àµà´•</translation>
<translation id="7006930604109697472">à´Žà´¨àµà´¤à´¾à´¯à´¾à´²àµà´‚ അയയàµâ€Œà´•àµà´•àµà´•</translation>
<translation id="7012363358306927923">ചൈന UnionPay</translation>
-<translation id="7012404007611495949">വലàµà´ªàµà´ªà´‚ മാറàµà´±àµ½ à´•àµà´°à´®àµ€à´•à´°à´£à´‚</translation>
<translation id="7014741021609395734">സൂം നില</translation>
<translation id="7016992613359344582">à´ˆ നിരകàµà´•àµà´•àµ¾ à´’à´±àµà´±à´¤àµà´¤à´µà´£ à´…à´Ÿà´¯àµà´•àµà´•àµà´¨àµà´¨à´¤àµ‹ à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ ആവർതàµà´¤à´¿à´•àµà´•àµà´¨àµà´¨à´µà´¯àµ‹ ആവാം, à´’à´ªàµà´ªà´‚ à´µàµà´¯à´•àµà´¤à´®à´²àµà´²à´¾à´¯à´¿à´°à´¿à´•àµà´•à´¾à´‚.</translation>
<translation id="7029809446516969842">പാസàµâ€Œà´µàµ‡à´¡àµà´•à´³àµâ€</translation>
+<translation id="7030436163253143341">സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ അസാധàµà´µà´¾à´£àµ</translation>
<translation id="7031646650991750659">à´à´¤àµ†à´¾à´•àµà´•àµ† Google Play ആപàµà´ªàµà´•àµ¾ നിങàµà´™àµ¾ ഇൻസàµà´±àµà´±à´¾àµ¾ ചെയàµâ€à´¤à´¿à´Ÿàµà´Ÿàµà´£àµà´Ÿàµ à´Žà´¨àµà´¨à´¤àµ</translation>
<translation id="7050187094878475250">നിങàµà´™àµ¾ <ph name="DOMAIN" /> à´Žà´¨àµà´¨à´¤à´¿à´²àµ†à´¤àµà´¤à´¾àµ» à´¶àµà´°à´®à´¿à´šàµà´šàµ, à´Žà´¨àµà´¨à´¾àµ½ തീരെ വിശàµà´µà´¾à´¸à´¯àµ‹à´—àµà´¯à´®à´²àµà´²à´¾à´¤àµà´¤ ഒരൠകാലാവധിയàµà´³àµà´³ സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±à´¾à´£àµ സെർവർ കാണികàµà´•àµà´¨àµà´¨à´¤àµ.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{à´ˆ കാർഡൠഇപàµà´ªàµ‹àµ¾ സംരകàµà´·à´¿à´•àµà´•à´¾à´¨à´¾à´µà´¿à´²àµà´²}other{à´ˆ കാർഡàµà´•àµ¾ ഇപàµà´ªàµ‹àµ¾ സംരകàµà´·à´¿à´•àµà´•à´¾à´¨à´¾à´µà´¿à´²àµà´²}}</translation>
@@ -1645,12 +1689,14 @@
<translation id="7300012071106347854">കൊബാൾടàµà´Ÿàµ നീല</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">ഉയർനàµà´¨à´¤àµ</translation>
+<translation id="7305756307268530424">à´•àµà´±à´žàµà´ž വേഗതയിൽ ആരംഭികàµà´•àµà´•</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">കണകàµà´·àµ» സഹായം</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" വിഭാഗം മറയàµà´•àµà´•àµà´•</translation>
<translation id="733354035281974745">ഉപകരണ ലോകàµà´•àµ½ à´…à´•àµà´•àµ—à´£àµà´Ÿàµ അസാധàµà´µà´¾à´•àµà´•àµà´•</translation>
<translation id="7333654844024768166">വഞàµà´šà´¨à´¾à´ªà´°à´®à´¾à´¯ സൈറàµà´±à´¿àµ½ നിങàµà´™àµ¾ ഇപàµà´ªàµ‹àµ¾ പാസàµâ€à´µàµ‡à´¡àµ നൽകി. നിങàµà´™àµ¾ à´ˆ പാസàµâ€Œà´µàµ‡à´¡àµ ഉപയോഗികàµà´•àµà´¨àµà´¨ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> à´Žà´¨àµà´¨à´¿à´µà´¯à´¿à´²àµ‡à´•àµà´•àµà´‚ മറàµà´±àµ സൈറàµà´±àµà´•à´³à´¿à´²àµ‡à´•àµà´•àµà´‚ പോയി, ഇപàµà´ªàµ‹àµ¾ തനàµà´¨àµ† അതൠമാറàµà´±à´¾àµ» Chromium à´¶àµà´ªà´¾àµ¼à´¶ ചെയàµà´¯àµà´¨àµà´¨àµ.</translation>
<translation id="7334320624316649418">&amp;à´ªàµà´¨à´ƒà´•àµà´°à´®àµ€à´•à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤àµ വീണàµà´Ÿàµà´‚ ചെയàµà´¯àµà´•</translation>
+<translation id="7337248890521463931">കൂടàµà´¤àµ½ വരികൾ കാണികàµà´•àµà´•</translation>
<translation id="7337706099755338005">നിങàµà´™à´³àµà´Ÿàµ† à´ªàµà´²à´¾à´±àµà´±àµâ€Œà´«àµ‹à´®à´¿àµ½ ലഭàµà´¯à´®à´²àµà´².</translation>
<translation id="733923710415886693">സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ à´¸àµà´¤à´¾à´°àµà´¯à´¤à´¯à´¿à´²àµ‚ടെ സെർവറàµà´Ÿàµ† സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ വെളിപàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¿à´¯à´¿à´Ÿàµà´Ÿà´¿à´²àµà´².</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1658,6 +1704,7 @@
<translation id="7349430561505560861">A4-അധികം</translation>
<translation id="7353601530677266744">കമാനàµâ€à´¡àµ ലൈനàµâ€â€Œ</translation>
<translation id="7359588939039777303">പരസàµà´¯à´™àµà´™àµ¾ à´¬àµà´²àµ‹à´•àµà´•àµà´šàµ†à´¯àµâ€Œà´¤àµ.</translation>
+<translation id="7363096869660964304">à´Žà´¨àµà´¨à´¿à´°àµà´¨àµà´¨à´¾à´²àµà´‚, നിങàµà´™àµ¾ അദൃശàµà´¯à´®à´¾à´¯à´¿à´°à´¿à´•àµà´•à´¿à´²àµà´². അദൃശàµà´¯ മോഡിലായിരികàµà´•àµà´®àµà´ªàµ‹àµ¾ നിങàµà´™à´³àµà´Ÿàµ† à´¬àµà´°àµ—സിംഗൠചരിതàµà´°à´‚ നിങàµà´™à´³àµà´Ÿàµ† തൊഴിൽദാതാവിൽ നിനàµà´¨àµ‹ ഇനàµà´±à´°àµâ€à´¨àµ†à´±àµà´±àµ സേവന ദാതാവിൽ നിനàµà´¨àµ‹ സനàµà´¦àµ¼à´¶à´¿à´•àµà´•àµà´¨àµà´¨ വെബàµâ€Œà´¸àµˆà´±àµà´±àµà´•à´³à´¿àµ½ നിനàµà´¨àµ‹ മറയàµâ€Œà´•àµà´•àµà´¨àµà´¨à´¿à´²àµà´².</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ വിലാസങàµà´™àµ¾ ചേർകàµà´•à´¾à´¨àµà´‚ മാനേജൠചെയàµà´¯à´¾à´¨àµà´‚ 'Tab' അമർതàµà´¤à´¿à´¯ ശേഷം 'Enter' അമർതàµà´¤àµà´•</translation>
<translation id="7365849542400970216">നിങàµà´™à´³àµà´Ÿàµ† ഉപകരണതàµà´¤à´¿à´¨àµà´±àµ† ഉപയോഗം അറിയണോ?</translation>
<translation id="7372973238305370288">തിരയൽ ഫലം</translation>
@@ -1668,7 +1715,9 @@
<translation id="7378594059915113390">മീഡിയ നിയനàµà´¤àµà´°à´£à´™àµà´™àµ¾</translation>
<translation id="7378627244592794276">വേണàµà´Ÿ</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ബാധകമലàµà´²</translation>
<translation id="7390545607259442187">കാർഡൠസàµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•àµà´•</translation>
+<translation id="7392089738299859607">വിലാസം à´…à´ªàµà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯àµà´•</translation>
<translation id="7399802613464275309">à´¸àµà´°à´•àµà´·à´¾ പരിശോധന</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">നിങàµà´™à´³àµà´Ÿàµ† <ph name="DEVICE_NAME" /> മാനേജൠചെയàµà´¯à´ªàµà´ªàµ†à´Ÿàµà´Ÿà´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ</translation>
@@ -1681,6 +1730,7 @@
നിങàµà´™à´³àµà´Ÿàµ† à´•à´®àµà´ªàµà´¯àµ‚à´Ÿàµà´Ÿà´±à´¿àµ½ നിനàµà´¨àµ à´Žà´™àµà´™à´¨àµ†à´¯à´¾à´£àµ സോഫàµà´±àµà´±àµâ€Œà´µàµ†à´¯àµ¼ ശാശàµà´µà´¤à´®à´¾à´¯à´¿ നീകàµà´•à´‚ചെയàµà´¯àµà´¨àµà´¨à´¤àµ à´Žà´¨àµà´¨à´±à´¿à´¯à´¾àµ» &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome സഹായ കേനàµà´¦àµà´°à´‚&lt;/a&gt; സനàµà´¦àµ¼à´¶à´¿à´•àµà´•àµà´• &lt;/ol&gt;</translation>
<translation id="741007362987735528">വിസàµâ€Œà´¤àµƒà´¤-ഫോർമാറàµà´±àµ</translation>
+<translation id="7410471291937727359">മനോഹരമായതàµ</translation>
<translation id="7416351320495623771">പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ മാനേജൠചെയàµà´¯àµà´•â€¦</translation>
<translation id="7419106976560586862">à´ªàµà´°àµŠà´«àµˆàµ½ പാത</translation>
<translation id="7437289804838430631">ബനàµà´§à´ªàµà´ªàµ†à´Ÿà´¾à´¨àµà´³àµà´³ വിവരങàµà´™àµ¾ ചേർകàµà´•àµà´•</translation>
@@ -1696,7 +1746,7 @@
<translation id="7481312909269577407">à´®àµà´¨àµà´¨àµ‹à´Ÿàµà´Ÿàµ</translation>
<translation id="7485870689360869515">ഡാറàµà´±à´•à´³àµŠà´¨àµà´¨àµà´‚ à´•à´£àµà´Ÿàµ†à´¤àµà´¤à´¿à´¯à´¿à´²àµà´².</translation>
<translation id="7495528107193238112">à´ˆ ഉളàµà´³à´Ÿà´•àµà´•à´‚ à´¬àµà´²àµ‹à´•àµà´•àµ ചെയàµâ€Œà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ. à´ªàµà´°à´¶àµâ€Œà´¨à´‚ പരിഹരികàµà´•à´¾àµ» സൈറàµà´±à´¿à´¨àµà´±àµ† ഉടമയàµà´®à´¾à´¯à´¿ ബനàµà´§à´ªàµà´ªàµ†à´Ÿàµà´•.</translation>
-<translation id="7498234416455752244">à´Žà´¡à´¿à´±àµà´±àµ ചെയàµà´¯àµà´¨àµà´¨à´¤àµ à´¤àµà´Ÿà´°àµà´•</translation>
+<translation id="7498193950643227031">വലàµà´ªàµà´ªà´‚ മാറàµà´±à´¿à´¯à´¾àµ½ അതൠഅപàµà´°à´¤àµ€à´•àµà´·à´¿à´¤à´®à´¾à´¯ രീതിയിൽ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´šàµà´šàµ‡à´•àµà´•à´¾à´‚. ആപàµà´ªàµà´•à´³àµà´Ÿàµ† വലàµà´ªàµà´ªà´‚ മാറàµà´±à´¾à´¨àµà´³àµà´³ ശേഷി നിങàµà´™àµ¾à´•àµà´•àµ ഇപàµà´ªàµ‹àµ¾ <ph name="SETTINGS" /> à´Žà´¨àµà´¨à´¤à´¿àµ½ പരിമിതപàµà´ªàµ†à´Ÿàµà´¤àµà´¤à´¾à´‚.</translation>
<translation id="7503664977220660814">വഞàµà´šà´¨à´¾à´ªà´°à´®à´¾à´¯ സൈറàµà´±à´¿àµ½ നിങàµà´™àµ¾ ഇപàµà´ªàµ‹àµ¾ പാസàµâ€à´µàµ‡à´¡àµ നൽകി. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, കൂടാതെ നിങàµà´™àµ¾ ഇപàµà´ªàµ‹àµ¾ à´ˆ പാസàµâ€Œà´µàµ‡à´¡àµ ഉപയോഗികàµà´•àµà´¨àµà´¨ മറàµà´±àµ സൈറàµà´±àµà´•àµ¾ à´Žà´¨àµà´¨à´¿à´µà´¯àµâ€Œà´•àµà´•à´¾à´¯à´¿ നിങàµà´™à´³àµà´Ÿàµ† സംരകàµà´·à´¿à´šàµà´š പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ പരിശോധികàµà´•à´¾àµ» Chromium നിർദàµà´¦àµ‡à´¶à´¿à´•àµà´•àµà´¨àµà´¨àµ.</translation>
<translation id="7508255263130623398">നൽകിയ നയ ഉപകരണ à´à´¡à´¿ ശൂനàµà´¯à´®à´¾à´£àµ à´…à´²àµà´²àµ†à´™àµà´•à´¿àµ½ നിലവിലെ ഉപകരണ à´à´¡à´¿à´¯àµà´®à´¾à´¯à´¿ യോജികàµà´•àµà´¨àµà´¨à´¿à´²àµà´²</translation>
<translation id="7508870219247277067">അവകàµà´•à´¾à´¡àµ‹ പചàµà´š</translation>
@@ -1716,6 +1766,7 @@
<translation id="7548892272833184391">കണകàµà´·àµ» പിശകàµà´•àµ¾ പരിഹരികàµà´•àµà´•</translation>
<translation id="7549584377607005141">ശരിയായി à´ªàµà´°à´¦àµ¼à´¶à´¿à´ªàµà´ªà´¿à´•àµà´•à´¾àµ» à´ˆ വെബàµâ€Œ പേജിനൠനിങàµà´™àµ¾ à´®àµà´®àµà´ªàµ നൽകിയ ഡാറàµà´± ആവശàµà´¯à´®à´¾à´£àµ. നിങàµà´™àµ¾à´•àµà´•àµ à´ˆ ഡാറàµà´± വീണàµà´Ÿàµà´‚ അയയàµâ€Œà´•àµà´•à´¾à´¨à´¾à´•àµà´®àµ†à´™àµà´•à´¿à´²àµà´‚, à´…à´™àµà´™à´¨àµ† ചെയàµà´¯àµà´¨àµà´¨à´¤àµ à´ˆ പേജിൽ à´®àµà´®àµà´ªàµ ചെയàµâ€Œà´¤ à´à´¤àµ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´µàµà´‚ നിങàµà´™àµ¾à´•àµà´•àµ ആവർതàµà´¤à´¿à´•àµà´•àµ‡à´£àµà´Ÿà´¤à´¾à´¯à´¿ വരàµà´‚.</translation>
<translation id="7550637293666041147">നിങàµà´™à´³àµà´Ÿàµ† ഉപകരണതàµà´¤à´¿à´¨àµà´±àµ† ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´µàµà´‚ Chrome ഉപയോകàµà´¤àµƒà´¨à´¾à´®à´µàµà´‚</translation>
+<translation id="755279583747225797">à´Ÿàµà´°à´¯àµ½ സജീവമാണàµ</translation>
<translation id="7552846755917812628">ഇനിപàµà´ªà´±à´¯àµà´¨àµà´¨ à´¨àµà´±àµà´™àµà´™àµà´•àµ¾ പരീകàµà´·à´¿à´•àµà´•àµ‚:</translation>
<translation id="7554475479213504905">റീലോഡൠചെയàµâ€Œà´¤àµ, à´Žà´¨àµà´¤à´¾à´¯à´¾à´²àµà´‚ കാണികàµà´•àµà´•</translation>
<translation id="7554791636758816595">à´ªàµà´¤à´¿à´¯ ടാബàµ</translation>
@@ -1734,7 +1785,6 @@
<translation id="7610193165460212391">മൂലàµà´¯à´‚ പരിധികàµà´•àµ à´ªàµà´±à´¤àµà´¤à´¾à´£àµ <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">കാലഹരണപàµà´ªàµ†à´Ÿàµà´¨àµà´¨à´¤àµ: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ കാണാനàµà´‚ മാനേജൠചെയàµà´¯à´¾à´¨àµà´‚ 'Tab' അമർതàµà´¤àµà´•, à´¤àµà´Ÿàµ¼à´¨àµà´¨àµ 'Enter' അമർതàµà´¤àµà´•</translation>
-<translation id="7615602087246926389">Google à´…à´•àµà´•àµ—à´£àµà´Ÿàµ പാസàµâ€Œà´µàµ‡à´¡à´¿à´¨àµà´±àµ† à´µàµà´¯à´¤àµà´¯à´¸àµà´¤ പതിപàµà´ªàµ ഉപയോഗിചàµà´šàµ എൻകàµà´°à´¿à´ªàµà´±àµà´±àµ ചെയàµà´¤ ഡേറàµà´± ഇപàµà´ªàµ‹àµ¾ തനàµà´¨àµ† നിങàµà´™à´³àµà´Ÿàµ† കൈവശമàµà´£àµà´Ÿàµ. à´† പാസàµâ€Œà´µàµ‡à´¡àµ താഴെ നൽകàµà´•.</translation>
<translation id="7616645509853975347">à´…à´¡àµâ€Œà´®à´¿àµ» നിങàµà´™à´³àµà´Ÿàµ† à´¬àµà´°àµ—സറിൽ Chrome Enterprise Connectors ഓണാകàµà´•à´¿à´¯à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ. à´ˆ കണകàµâ€Œà´±àµà´±à´±àµà´•àµ¾à´•àµà´•àµ നിങàµà´™à´³àµà´Ÿàµ† à´šà´¿à´² ഡാറàµà´±à´¯à´¿à´²àµ‡à´•àµà´•àµ ആകàµâ€Œà´¸à´¸àµ ഉണàµà´Ÿàµ.</translation>
<translation id="7619838219691048931">അവസാന ഷീറàµà´±àµ</translation>
<translation id="762844065391966283">ഒരൠസമയം à´’à´¨àµà´¨àµ</translation>
@@ -1799,13 +1849,12 @@
<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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ഫയൽ തര അസോസിയേഷനàµà´•àµ¾ ഉളàµà´³ ഫയലàµà´•àµ¾ à´¤àµà´±à´•àµà´•àµà´•.</translation>
<translation id="7862185352068345852">സൈറàµà´±àµ വിടണോ?</translation>
<translation id="7865448901209910068">à´à´±àµà´±à´µàµà´‚ മികചàµà´š വേഗത</translation>
<translation id="7874263914261512992">വഞàµà´šà´¨à´¾à´ªà´°à´®à´¾à´¯ സൈറàµà´±à´¿àµ½ നിങàµà´™àµ¾ ഇപàµà´ªàµ‹àµ¾ പാസàµâ€à´µàµ‡à´¡àµ നൽകി. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, കൂടാതെ നിങàµà´™àµ¾ ഇപàµà´ªàµ‹àµ¾ à´ˆ പാസàµâ€Œà´µàµ‡à´¡àµ ഉപയോഗികàµà´•àµà´¨àµà´¨ മറàµà´±àµ സൈറàµà´±àµà´•àµ¾ à´Žà´¨àµà´¨à´¿à´µà´¯àµâ€Œà´•àµà´•à´¾à´¯à´¿ നിങàµà´™à´³àµà´Ÿàµ† സംരകàµà´·à´¿à´šàµà´š പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ പരിശോധികàµà´•à´¾àµ» Chrome നിർദàµà´¦àµ‡à´¶à´¿à´•àµà´•àµà´¨àµà´¨àµ.</translation>
<translation id="7878562273885520351">നിങàµà´™à´³àµà´Ÿàµ† പാസàµâ€à´µàµ‡à´¡àµ അപഹരികàµà´•à´ªàµà´ªàµ†à´Ÿàµà´Ÿàµ‡à´•àµà´•à´¾à´‚</translation>
+<translation id="7880146494886811634">വിലാസം സംരകàµà´·à´¿à´•àµà´•àµà´•</translation>
<translation id="7882421473871500483">തവിടàµà´Ÿàµ നിറം</translation>
<translation id="7887683347370398519">നിങàµà´™à´³àµà´Ÿàµ† CVC പരിശോധിചàµà´šàµ വീണàµà´Ÿàµà´‚ à´¶àµà´°à´®à´¿à´•àµà´•àµà´•</translation>
<translation id="7887885240995164102">à´šà´¿à´¤àµà´°à´¤àµà´¤à´¿à´¨àµà´³àµà´³à´¿à´²àµ† à´šà´¿à´¤àµà´°à´¤àµà´¤à´¿à´²àµ‡à´•àµà´•àµ à´ªàµà´°à´µàµ‡à´¶à´¿à´•àµà´•àµà´•</translation>
@@ -1813,6 +1862,7 @@
<translation id="7894280532028510793">à´…à´•àµà´·à´°à´™àµà´™àµ¾ ശരിയാണെങàµà´•à´¿àµ½ <ph name="BEGIN_LINK" /> നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•àµ ഡയഗണോസàµâ€Œà´±àµà´±à´¿à´•àµâ€Œà´¸àµ റൺ ചെയàµâ€Œà´¤àµà´¨àµ‹à´•àµà´•àµ‚<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (എൻവലപàµà´ªàµ)</translation>
<translation id="7931318309563332511">അറിഞàµà´žàµà´•àµ‚ടാതàµà´¤à´¤àµ</translation>
+<translation id="793209273132572360">വിലാസം à´…à´ªàµà´¡àµ‡à´±àµà´±àµ ചെയàµà´¯à´£àµ‹?</translation>
<translation id="7932579305932748336">കോടàµà´Ÿàµ</translation>
<translation id="79338296614623784">ശരിയായ ഒരൠഫോൺ നമàµà´ªàµ¼ നൽകàµà´•</translation>
<translation id="7934052535022478634">പേയàµâ€Œà´®àµ†à´¨àµà´±àµ പൂർതàµà´¤à´¿à´¯à´¾à´¯à´¿</translation>
@@ -1883,6 +1933,7 @@
<translation id="8175796834047840627">സൈൻ ഇൻ ചെയàµâ€Œà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨à´¾àµ½ നിങàµà´™à´³àµà´Ÿàµ† Google à´…à´•àµà´•àµ—à´£àµà´Ÿà´¿à´²àµ‡à´•àµà´•àµ കാർഡàµà´•àµ¾ സംരകàµà´·à´¿à´•àµà´•à´¾à´®àµ†à´¨àµà´¨àµ Chrome വാഗàµâ€Œà´¦à´¾à´¨à´‚ ചെയàµà´¯àµà´¨àµà´¨àµ. à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ à´ˆ രീതി മാറàµà´±à´¾à´¨à´¾à´•àµà´‚.</translation>
<translation id="8176440868214972690">à´ˆ ഉപകരണതàµà´¤à´¿à´¨àµà´±àµ† à´…à´¡àµà´®à´¿àµ», à´•àµà´°à´®àµ€à´•à´°à´£à´®àµ‹ നയങàµà´™à´³àµ‹ പോലàµà´³àµà´³ à´šà´¿à´² വിവരങàµà´™àµ¾ ഇനിപàµà´ªà´±à´¯àµà´¨àµà´¨ വെബàµâ€Œà´¸àµˆà´±àµà´±àµà´•à´³à´¿à´²àµ‡à´•àµà´•àµ അയചàµà´šàµ.</translation>
<translation id="8184538546369750125">ആഗോള ഡിഫോൾടàµà´Ÿàµ ഉപയോഗികàµà´•àµà´• (à´…à´¨àµà´µà´¦à´¿à´•àµà´•àµà´•)</translation>
+<translation id="8193086767630290324">രഹസàµà´¯à´¾à´¤àµà´®à´•à´‚ à´Žà´¨àµà´¨àµ à´«àµà´²à´¾à´—ൠചെയàµà´¤ ഡാറàµà´± ഉപയോഗിചàµà´šàµà´³àµà´³ à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´™àµà´™àµ¾</translation>
<translation id="8194797478851900357">&amp;നീകàµà´•àµà´¨àµà´¨à´¤àµ പഴയപടിയാകàµà´•àµà´•</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" à´Žà´¨àµà´¨ à´à´¡à´¿à´¯àµà´³àµà´³ വിപàµà´²àµ€à´•à´°à´£à´¤àµà´¤à´¿à´¨àµà´±àµ† à´…à´ªàµâ€Œà´¡àµ‡à´±àµà´±àµ URL അസാധàµà´µà´¾à´£àµ.</translation>
<translation id="8202097416529803614">ഓർഡർ സംഗàµà´°à´¹à´‚</translation>
@@ -1905,6 +1956,7 @@
<translation id="8249296373107784235">ഉപേകàµà´·à´¿à´•àµà´•àµà´•</translation>
<translation id="8249320324621329438">അവസാനം ലഭàµà´¯à´®à´¾à´¯à´¤àµ:</translation>
<translation id="8253091569723639551">ബിലàµà´²à´¿à´‚ഗൠവിലാസം ആവശàµà´¯à´®à´¾à´£àµ</translation>
+<translation id="8257387598443225809">à´ˆ ആപàµà´ªàµ മൊബൈലിനായി രൂപകൽപàµà´ªà´¨ ചെയàµà´¤à´¿à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ</translation>
<translation id="825929999321470778">സംരകàµà´·à´¿à´šàµà´š à´Žà´²àµà´²à´¾ പാസàµâ€Œà´µàµ‡à´¡àµà´•à´³àµà´‚ കാണികàµà´•àµà´•</translation>
<translation id="8261506727792406068">ഇലàµà´²à´¾à´¤à´¾à´•àµà´•àµà´•</translation>
<translation id="8262952874573525464">താഴെ അരികൠകൂടàµà´Ÿà´¿à´šàµà´šàµ‡àµ¼à´•àµà´•àµ½</translation>
@@ -2028,7 +2080,6 @@
<translation id="8719528812645237045">à´®àµà´•à´³à´¿àµ½ à´’à´¨àµà´¨à´¿à´²à´§à´¿à´•à´‚ പഞàµà´šàµ ചെയàµà´¯àµà´•</translation>
<translation id="8725066075913043281">വീണàµà´Ÿàµà´‚ à´¶àµà´°à´®à´¿à´•àµà´•àµà´•</translation>
<translation id="8726549941689275341">പേജിനàµà´±àµ† വലàµà´ªàµà´ªà´‚:</translation>
-<translation id="8728672262656704056">നിങàµà´™àµ¾ അദൃശàµà´¯ വിൻഡോയിലാണàµ</translation>
<translation id="8730621377337864115">പൂർതàµà´¤à´¿à´¯à´¾à´•àµà´•à´¿</translation>
<translation id="8731544501227493793">'പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ മാനേജൠചെയàµà´¯àµà´•' ബടàµà´Ÿàµº, Chrome à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ നിങàµà´™à´³àµà´Ÿàµ† പാസàµâ€Œà´µàµ‡à´¡àµà´•àµ¾ കാണാനàµà´‚ മാനേജൠചെയàµà´¯à´¾à´¨àµà´‚ 'Enter' അമർതàµà´¤àµà´•</translation>
<translation id="8734529307927223492">നിങàµà´™à´³àµà´Ÿàµ† <ph name="DEVICE_TYPE" /> മാനേജൠചെയàµà´¯àµà´¨àµà´¨à´¤àµ <ph name="MANAGER" /> ആണàµ</translation>
@@ -2105,6 +2156,7 @@
<translation id="9020542370529661692">à´ˆ പേജൠ<ph name="TARGET_LANGUAGE" />-ലേകàµà´•àµ വിവർതàµà´¤à´¨à´‚ ചെയàµâ€Œà´¤àµ</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(അസാധàµà´µà´¾à´£àµ)</translation>
+<translation id="9030265603405983977">മോണോകàµà´°àµ‹à´‚</translation>
<translation id="9035022520814077154">à´¸àµà´°à´•àµà´·à´¾ പിശകàµ</translation>
<translation id="9038649477754266430">പേജàµà´•àµ¾ കൂടàµà´¤àµ½ വേഗതàµà´¤à´¿àµ½ ലോഡൠചെയàµà´¯à´¾àµ» ഒരൠപàµà´°à´µà´šà´¨ സേവനം ഉപയോഗികàµà´•àµà´•</translation>
<translation id="9039213469156557790">à´ˆ പേജിൽ à´¸àµà´°à´•àµà´·à´¿à´¤à´®à´²àµà´²à´¾à´¤àµà´¤ മറàµà´±àµ ഉറവിടങàµà´™àµ¾ ഉൾപàµà´ªàµ†à´Ÿàµà´¨àµà´¨àµ. à´ˆ ഉറവിടങàµà´™àµ¾ കൈമാറàµà´¨àµà´¨à´¤à´¿à´¨à´¿à´Ÿàµ† മറàµà´±àµà´³àµà´³à´µàµ¼à´•àµà´•àµ കാണാനàµà´‚ പേജിനàµà´±àµ† à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´°àµ€à´¤à´¿ മാറàµà´±àµà´¨àµà´¨ തരതàµà´¤à´¿àµ½ ഒരൠആകàµà´°à´®à´£à´•à´¾à´°à´¿à´¯àµâ€Œà´•àµà´•àµ പരിഷàµâ€Œà´•àµà´•à´°à´¿à´•àµà´•à´¾à´¨àµà´®à´¾à´¯àµ‡à´•àµà´•àµà´‚.</translation>
@@ -2128,6 +2180,7 @@
<translation id="91108059142052966">രഹസàµà´¯à´¾à´¤àµà´®à´•à´®à´¾à´¯ ഉളàµà´³à´Ÿà´•àµà´•à´‚ ദൃശàµà´¯à´®à´¾à´•àµà´®àµà´ªàµ‹àµ¾ <ph name="APPLICATION_TITLE" /> à´Žà´¨àµà´¨à´¤àµà´®à´¾à´¯à´¿ à´¸àµà´•àµà´°àµ€àµ» പങàµà´•à´¿à´Ÿàµà´¨àµà´¨à´¤àµ à´…à´¡àµâ€Œà´®à´¿àµ» നയം à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¨à´°à´¹à´¿à´¤à´®à´¾à´•àµà´•àµà´¨àµà´¨àµ</translation>
<translation id="9114524666733003316">കാർഡൠസàµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•àµà´¨àµà´¨àµ...</translation>
<translation id="9114581008513152754">à´•à´®àµà´ªà´¨à´¿à´¯àµ‹ മറàµà´±àµ‡à´¤àµ†à´™àµà´•à´¿à´²àµà´‚ à´¸àµà´¥à´¾à´ªà´¨à´®àµ‹ മാനേജൠചെയàµà´¯àµà´¨àµà´¨à´¤à´²àµà´² à´ˆ à´¬àµà´°àµ—സർ. à´ˆ ഉപകരണതàµà´¤à´¿à´²àµ† ആകàµâ€Œà´±àµà´±à´¿à´µà´¿à´±àµà´±à´¿ Chrome-നൠപàµà´±à´¤àµà´¤àµ മാനേജൠചെയàµà´¤àµ‡à´•àµà´•à´¾à´‚. <ph name="BEGIN_LINK" />കൂടàµà´¤à´²à´±à´¿à´¯àµà´•<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">à´ªàµà´¤à´¿à´¯à´¤àµ</translation>
<translation id="9119042192571987207">à´…à´ªàµâ€Œà´²àµ‹à´¡àµ ചെയàµà´¤àµ</translation>
<translation id="9128016270925453879">നയങàµà´™àµ¾ ലോഡൠചെയàµà´¤àµ</translation>
<translation id="9128870381267983090">നെറàµà´±àµâ€Œà´µàµ¼à´•àµà´•à´¿à´²àµ‡à´•àµà´•àµ കണകàµà´±àµà´±àµ ചെയàµà´¯àµà´•</translation>
@@ -2146,6 +2199,7 @@
<translation id="9170848237812810038">â€&amp;പൂരàµâ€à´µà´¾à´µà´¸àµà´¥à´¯à´¿à´²à´¾à´•àµà´•àµà´•</translation>
<translation id="9171296965991013597">ആപàµà´ªàµ വിടണോ?</translation>
<translation id="9173282814238175921">സിംഗിൾ ഡോകàµà´¯àµà´®àµ†à´¨àµà´±àµ/à´ªàµà´¤à´¿à´¯ ഷീറàµà´±àµ</translation>
+<translation id="9173995187295789444">Bluetooth ഉപകരണങàµà´™àµ¾à´•àµà´•à´¾à´¯à´¿ à´¸àµâ€Œà´•à´¾àµ» ചെയàµà´¯àµà´¨àµà´¨àµ...</translation>
<translation id="917450738466192189">സെർവറിനàµà´±àµ† സർടàµà´Ÿà´¿à´«à´¿à´•àµà´•à´±àµà´±àµ അസാധàµà´µà´¾à´£àµ.</translation>
<translation id="9174917557437862841">ടാബൠമാറാനàµà´³àµà´³ ബടàµà´Ÿàµº, à´ˆ ടാബിലേകàµà´•àµ മാറാൻ എൻàµà´±àµ¼ അമർതàµà´¤àµà´•</translation>
<translation id="9179703756951298733">Chrome à´•àµà´°à´®àµ€à´•à´°à´£à´¤àµà´¤à´¿àµ½ നിങàµà´™à´³àµà´Ÿàµ† പേയàµâ€Œà´®àµ†à´¨àµà´±àµà´•à´³àµà´‚ à´•àµà´°àµ†à´¡à´¿à´±àµà´±àµ കാർഡൠവിവരങàµà´™à´³àµà´‚ മാനേജൠചെയàµà´¯àµà´•</translation>
diff --git a/chromium/components/strings/components_strings_mn.xtb b/chromium/components/strings/components_strings_mn.xtb
index 2b80ec09cb5..366830f2c2a 100644
--- a/chromium/components/strings/components_strings_mn.xtb
+++ b/chromium/components/strings/components_strings_mn.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">СонгоÑон тохиолдолд Chrome нь илүү хурдан бөглөдөг болгох зорилгоор таны картын хуулбарыг ÑÐ½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶ дÑÑÑ€ хадгалах болно.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" />-д зөвшөөрөл Ñонгох</translation>
<translation id="1113869188872983271">&amp; Дахин ÑÑ€ÑмбÑлÑÑ… үйлдлийг буцаах</translation>
+<translation id="1123753900084781868">Шууд тайлбар Ñг одоо боломжгүй байна</translation>
<translation id="1125573121925420732">ВебÑайт аюулгүй байдлаа шинÑчлÑÑ… үед анхааруулга гарч ирж болзошгүй. Үүнийг удахгүй Ñайжруулах болно.</translation>
<translation id="112840717907525620">Тохиргооны кÑш болж байна</translation>
<translation id="1130564665089811311">Ð¥ÑƒÑƒÐ´Ð°Ñ Ð¾Ñ€Ñ‡ÑƒÑƒÐ»Ð°Ñ… товч, ÑÐ½Ñ Ñ…ÑƒÑƒÐ´Ñыг Google Орчуулагчаар орчуулахын тулд Enter дарна уу</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Таны төхөөрөмжийн нÑÑ€</translation>
<translation id="124116460088058876">БуÑад Ñ…Ñл</translation>
<translation id="1243027604378859286">Зохиогч:</translation>
+<translation id="1246424317317450637">Тод</translation>
<translation id="1250759482327835220">Дараагийн удаа төлбөрөө хурдан төлөхийн тулд Google БүртгÑлдÑÑ ÐºÐ°Ñ€Ñ‚, нÑÑ€ болон тооцооны хаÑгаа хадгална уу.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (Ñинк хийÑÑн)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ð¥ÑÑ€Ñв та вебÑайтад зочлохоор оролдох үед нÑÑгдÑхгүй байвал ÑдгÑÑÑ€ аÑуудал шийдÑÑ… алхмыг дагаж алдааг заÑахаар оролдоно уу:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Ðууц үгÑÑ Ó©Ó©Ñ€Ñ‡Ð¸Ð»Ð½Ó© Ò¯Ò¯</translation>
<translation id="1484290072879560759">ТÑÑвÑрлÑлтийн хаÑг Ñонгох</translation>
<translation id="1492194039220927094">Удирдамжийн Ñ…ÑÑ€ÑгжүүлÑлт:</translation>
+<translation id="1495677929897281669">Таб руу буцах</translation>
<translation id="1501859676467574491">Google БүртгÑлÑÑÑÑÑ ÐºÐ°Ñ€Ñ‚ харуулах</translation>
<translation id="1507202001669085618">&lt;p&gt;Ð¥ÑÑ€Ñв та онлайн болохооÑоо өмнө нÑвтрÑÑ… шаардлагатай Wi-Fi портал ашиглаж байгаа бол Ñ‚ÑƒÑ Ð°Ð»Ð´Ð°Ð°Ð³ харах болно.&lt;/p&gt;
&lt;p&gt;Ðлдааг заÑахын тулд нÑÑхийг оролдож буй нүүр хуудаÑны &lt;strong&gt;Холбогдох&lt;/strong&gt; гÑÑнийг товшино уу.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Ð­Ð½Ñ Ñ…ÑƒÑƒÐ´Ð°Ñ Ñ…ÑлÑхдÑÑ</translation>
<translation id="153384715582417236">ДууÑлаа</translation>
<translation id="1536390784834419204">ХуудÑыг орчуулах</translation>
+<translation id="1539840569003678498">Тайланг илгÑÑÑÑн:</translation>
<translation id="154408704832528245">ХүргÑлтийн хаÑг Ñонгох</translation>
<translation id="1549470594296187301">JavaScript ÑÐ½Ñ Ð¾Ð½Ñ†Ð»Ð¾Ð³Ð¸Ð¹Ð³ ашиглахын тулд идÑвхжÑÑн байх Ñ‘Ñтой.</translation>
<translation id="155039086686388498">ИнженерчлÑл-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">ЭхлÑÑд богино зах</translation>
<translation id="168693727862418163">Ð­Ð½Ñ Ð±Ð¾Ð´Ð»Ð¾Ð³Ñ‹Ð½ утгыг ÑхемтÑй нь тулгаж баталж чадаагүй тул үүнийг үл Ñ…ÑÑ€ÑгÑÑнÑ.</translation>
<translation id="168841957122794586">Серверийн гÑрчилгÑÑний криптограф түлхүүр нь аюулгүй байдлын хувьд Ñул байна.</translation>
+<translation id="1696290444144917273">Виртуал картын дÑлгÑÑ€Ñнгүйг үзÑÑ…</translation>
<translation id="1697532407822776718">Тохируулга дууÑÑан</translation>
<translation id="1703835215927279855">Захидал</translation>
<translation id="1706954506755087368">{1,plural, =1{Ð­Ð½Ñ Ñервер нь <ph name="DOMAIN" /> гÑдгÑÑ Ð±Ð°Ñ‚Ð°Ð»Ð³Ð°Ð°Ð¶ÑƒÑƒÐ»Ð¶ чадÑангүй; Ñерверийн аюулгүй байдлын Ñертификат Ð¼Ð°Ñ€Ð³Ð°Ð°ÑˆÐ½Ð°Ð°Ñ ÑÑ…ÑлнÑ. Ð­Ð½Ñ Ð½ÑŒ буруу тохируулÑнааÑ, ÑÑвÑл халдагч ÑтгÑÑд таны холболтод Ñаад учруулÑÐ½Ð°Ð°Ñ Ð±Ð¾Ð»Ñон байж болзошгүй.}other{Ð­Ð½Ñ Ñервер нь <ph name="DOMAIN" /> гÑдгÑÑ Ð±Ð°Ñ‚Ð°Ð»Ð³Ð°Ð°Ð¶ÑƒÑƒÐ»Ð¶ чадÑангүй; Ñерверийн аюулгүй байдлын Ñертификат # Ñ…Ð¾Ð½Ð¾Ð³Ð¾Ð¾Ñ Ñ…Ò¯Ñ‡Ð¸Ð½Ñ‚Ñй болно. Ð­Ð½Ñ Ð½ÑŒ буруу тохируулÑнааÑ, ÑÑвÑл халдагч ÑтгÑÑд таны холболтод Ñаад учруулÑÐ½Ð°Ð°Ñ Ð±Ð¾Ð»Ñон байж болзошгүй.}}</translation>
<translation id="1710259589646384581">Үйлдлийн ÑиÑтем</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" />-г <ph name="VALUE" /> гÑж тохируулаагүй тул үл Ñ…ÑÑ€ÑгÑÑÑн.</translation>
<translation id="1712552549805331520"><ph name="URL" /> таны дотоод компьютерт өгөгдлийг бүрмөÑөн хадгалах Ñ…Ò¯ÑÑлтÑй байна</translation>
<translation id="1713628304598226412">Гарах цааÑны тавиур 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Шуудангийн хайрцаг 3</translation>
<translation id="1718029547804390981">Документ дÑÑÑ€ Ñ‚ÑмдÑглÑгÑÑ Ñ…Ð¸Ð¹Ñ…Ñд Ñ…ÑÑ‚ том байна</translation>
<translation id="1721424275792716183">* Талбарыг бөглөх шаардлагатай</translation>
+<translation id="1727613060316725209">ГÑрчилгÑÑ Ñ…Ò¯Ñ‡Ð¸Ð½Ñ‚Ñй байна</translation>
<translation id="1727741090716970331">ХүчинтÑй картын дугаар оруулах</translation>
<translation id="1728677426644403582">Та веб хуудаÑны ÑÑ… Ñурвалжийг харж байна.</translation>
<translation id="173080396488393970">Ð­Ð½Ñ Ñ‚Ó©Ñ€Ð»Ð¸Ð¹Ð½ аппыг дÑмждÑггүй</translation>
@@ -246,7 +253,6 @@
<ph name="SITE" />-д зочлох таны Ñ…Ò¯ÑÑлтийг гүйцÑтгÑÑ…Ñд хөтчид Ñаад болж байна. ҮндÑÑн удирдамжийг
Ñайтад зориулж аюулгүй байдал болон буÑад шинж чанарыг тохируулахад Ñайтын оператор ашиглаж болно.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Та өөрийн тохиргоо хийдÑг нууц үгийг шинÑчлÑÐ½Ñ Ò¯Ò¯.</translation>
<translation id="1787142507584202372">Таны нÑÑлттÑй таб Ñнд харагдана</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, олон үйлдÑл хийх боломжтой, үйлдÑл хооронд шилжихийн тулд Таб дÑÑÑ€ дарна уу</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">Зар</translation>
<translation id="1919367280705858090">Тодорхой алдаатай меÑÑежÑÑÑ€ туÑламж авах</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Байхгүй}=1{1 Ñайт}other{# Ñайт}}</translation>
+<translation id="1924727005275031552">ШинÑ</translation>
<translation id="1945968466830820669">Та байгууллагынхаа бүртгÑлд хандах Ñрх ÑÑвÑл нууц үгÑÑ Ð±ÑƒÑдад алдаж болзошгүй. Chromium-Ñ Ñ‚Ð°Ð½Ñ‹Ð³ нууц үгÑÑ Ó©Ó©Ñ€Ñ‡Ð»Ó©Ñ…Ð¸Ð¹Ð³ зөвлөж байна.</translation>
<translation id="1947454675006758438">Баруун дÑÑд буланд үдÑÑ…</translation>
<translation id="1958218078413065209">Таны хамгийн өндөр оноо <ph name="SCORE" /> байна.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">Гарах цааÑны тавиур 7</translation>
<translation id="204357726431741734">Google БүртгÑлдÑÑ Ñ…Ð°Ð´Ð³Ð°Ð»Ñан нууц үгÑийг ашиглахын тулд нÑвтрÑÑ…</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> Ñ…Ñл дÑÑрх хуудÑыг орчуулахгүй.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Ð­Ð½Ñ Ñ…Ñналт аÑаалттай бөгөөд төлөв нь идÑвхтÑй үед Chrome таны ÑаÑхны хөтчийн үйл ажиллагаа аль том Ñ…ÑмжÑÑний бүлÑг хүн ÑÑвÑл "нÑг үеийнхÑн"-Ñ‚Ñй хамгийн Ñ‚Ó©ÑÑ‚Ñй болохыг тодорхойлно. Сурталчлагчид бүлÑгт зориулж зар Ñонгох боломжтой бөгөөд хөтчийн үйл ажиллагааг таны төхөөрөмж дÑÑÑ€ хувийн байлгадаг. Таны бүлгийг өдөр тутам шинÑчилдÑг.}=1{Ð­Ð½Ñ Ñ…Ñналт аÑаалттай бөгөөд төлөв нь идÑвхтÑй үед Chrome таны ÑаÑхны хөтчийн үйл ажиллагаа аль том Ñ…ÑмжÑÑний бүлÑг хүн ÑÑвÑл "нÑг үеийнхÑн"-Ñ‚Ñй хамгийн Ñ‚Ó©ÑÑ‚Ñй болохыг тодорхойлно. Сурталчлагчид бүлÑгт зориулж зар Ñонгох боломжтой бөгөөд хөтчийн үйл ажиллагааг таны төхөөрөмж дÑÑÑ€ хувийн байлгадаг. Таны бүлгийг өдөр тутам шинÑчилдÑг.}other{Ð­Ð½Ñ Ñ…Ñналт аÑаалттай бөгөөд төлөв нь идÑвхтÑй үед Chrome таны ÑаÑхны хөтчийн үйл ажиллагаа аль том Ñ…ÑмжÑÑний бүлÑг хүн ÑÑвÑл "нÑг үеийнхÑн"-Ñ‚Ñй хамгийн Ñ‚Ó©ÑÑ‚Ñй болохыг тодорхойлно. Сурталчлагчид бүлÑгт зориулж зар Ñонгох боломжтой бөгөөд хөтчийн үйл ажиллагааг таны төхөөрөмж дÑÑÑ€ хувийн байлгадаг. Таны бүлгийг {NUM_DAYS} өдөр тутам шинÑчилдÑг.}}</translation>
<translation id="2053553514270667976">Зип Код</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 зөвлөмж}other{# зөвлөмж}}</translation>
<translation id="2071692954027939183">Та мÑдÑгдлийг ихÑвчлÑн зөвшөөрдөггүй тул Ñ‚ÑдгÑÑрийг автоматаар блоклоÑон</translation>
<translation id="2079545284768500474">Буцаах</translation>
<translation id="20817612488360358">СиÑтемийн прокÑи-гийн тохиргоонуудыг ашиглахаар ÑуулгаÑан Ñ…Ñдий ч прокÑи-гийн нарийн тохиргоог зааж өгÑөн байна.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" />-ын <ph name="RESULT_NUMBER" /> илÑрц байна</translation>
+<translation id="2085876078937250610">Хадгалах…</translation>
<translation id="2088086323192747268">Синк хийхийг удирдах товч. Chrome-н тохиргоонд Ñмар мÑдÑÑлÑл Ñинк хийхÑÑ ÑƒÐ´Ð¸Ñ€Ð´Ð°Ñ…Ñ‹Ð½ тулд Enter дÑÑÑ€ дарна уу</translation>
<translation id="2091887806945687916">Дуу</translation>
<translation id="2094505752054353250">ДомÑйн нÑÑ€ нийцÑхгүй байна</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> Ñ…ÑÑ€ÑглÑгчийн нÑÑ€, нууц үгийг шаардаж байна.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" />-д дууÑна</translation>
<translation id="2337852623177822836">Тохируулгыг таны админиÑтратор Ñ…Ñнадаг</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> холбогдох Ñ…Ò¯ÑÑлтÑй байна</translation>
<translation id="2344028582131185878">Ðвтоматаар татаж авах</translation>
<translation id="2346319942568447007">Таны хуулÑан зураг</translation>
<translation id="2354001756790975382">БуÑад хайлтын жагÑаалтууд</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">Халдагч таны ÑÐ½Ñ ÑÐ°Ð¹Ñ‚Ð°Ð°Ñ Ñ…Ð°Ñ€Ð¶ буй зургийг харах бөгөөд Ñ‚ÑдгÑÑрийг өөрчлөх замаар таныг хуурч болзошгүй.</translation>
<translation id="2356070529366658676">ÐÑуух</translation>
<translation id="2357481397660644965">Таны төхөөрөмжийг <ph name="DEVICE_MANAGER" />, харин бүртгÑлийг тань <ph name="ACCOUNT_MANAGER" /> удирддаг.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{1 Ó©Ð´Ñ€Ó©Ó©Ñ Ð±Ð°Ð³Ð° хугацааны дараа}=1{1 өдрийн дараа}other{{NUM_DAYS} өдрийн дараа}}</translation>
<translation id="2359629602545592467">Олон</translation>
<translation id="2359808026110333948">Цааш</translation>
+<translation id="2359961752320758691">Таны виртуал картын дугаарыг автоматаар бөглөлөө.</translation>
<translation id="2367567093518048410">Түвшин</translation>
<translation id="2372464001869762664">Таныг баталгаажуулÑны дараа таны Google бүртгÑлÑÑÑ ÐºÐ°Ñ€Ñ‚Ñ‹Ð½ дÑлгÑÑ€Ñнгүй мÑдÑÑллийг ÑÐ½Ñ Ñайтад хуваалцах болно. Plex бүртгÑлийн дÑлгÑÑ€Ñнгүй мÑдÑÑллÑÑÑÑÑ ÐšÐ°Ñ€Ñ‚ баталгаажуулалтын кодыг олно уу.</translation>
<translation id="2380886658946992094">Хууль Ñ‘Ñны</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">ХүргÑлтийн ÑÐ½Ñ Ð°Ñ€Ð³Ð° боломжгүй тул Ó©Ó©Ñ€ арга Ñонгоно уу.</translation>
<translation id="2396249848217231973">УÑтгах үйлдлийг буцаах</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Хуучин</translation>
<translation id="2413528052993050574">Ð­Ð½Ñ Ñервер нь <ph name="DOMAIN" />-аа баталж чадÑангүй; хамгаалалтын Ñертификат хүчингүй болÑон байж болзошгүй. Ð­Ð½Ñ Ð½ÑŒ тохиргоо буруу хийгдÑÑнÑÑÑ ÑÑвÑл халдагч таны холболтон Ñаад учруулж байж болох юм.</translation>
<translation id="2414886740292270097">Хар</translation>
<translation id="2438874542388153331">Баруун ирмÑг дагуу дөрвөн нүх цоолох</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">Баруун доод буланд үдÑÑ…</translation>
<translation id="2523886232349826891">Зөвхөн ÑÐ½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶ дÑÑÑ€ хадгалÑан</translation>
<translation id="2524461107774643265">ДÑлгÑÑ€Ñнгүй мÑдÑÑлÑл нÑмÑÑ…</translation>
-<translation id="2526590354069164005">ДеÑктоп</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{болон буÑад 1}other{болон буÑад #}}</translation>
<translation id="2536110899380797252">ХаÑг нÑмÑÑ…</translation>
<translation id="2539524384386349900">ИлрүүлÑÑ…</translation>
+<translation id="2541219929084442027">Таныг бүх Ðууцлалтай табаа хааÑны дараагаар таны Ðууцлалтай табуудад үзÑÑн хуудаÑнууд таны хөтчийн түүх, күүкиний дÑлгүүр ÑÑвÑл хайлтын түүхÑд үлдÑхгүй. Таны татÑан аливаа файл ÑÑвÑл Ò¯Ò¯ÑгÑÑÑн хавчуургыг хадгална.</translation>
<translation id="2544644783021658368">Дан документ</translation>
<translation id="254947805923345898">Удирдамжийн утга хүчингүй байна.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> хүчингүй хариу илгÑÑÑÑн байна.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Chrome-н хамгийн дÑÑд түвшний аюулгүй байдлыг авахын тулд <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ÑайжруулÑан хамгаалалтыг аÑаана уу<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" />-н Ñерверийн IP хаÑг олдÑонгүй.</translation>
<translation id="2639739919103226564">СтатуÑ:</translation>
+<translation id="264810637653812429">Тохирох төхөөрөмж олдÑонгүй.</translation>
<translation id="2649204054376361687"><ph name="CITY" /> , <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome-н тохиргоон дÑÑÑ€ хөтчийн түүх, күүки, завÑрын Ñанах ой болон буÑад зүйлийг арилгахын тулд ÑхлÑÑд Таб дÑÑÑ€, дараа нь Enter дарна уу</translation>
<translation id="2650446666397867134">Файл руу нÑвтрÑÑ… үйлдÑл таÑлагдÑан.</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">Дахин ÑхлүүлÑÑ…</translation>
<translation id="2803306138276472711"><ph name="SITE" />-д <ph name="BEGIN_LINK" />вируÑ<ph name="END_LINK" /> байгааг Google-ийн Ðюулгүй Хайлт олж ирлрүүллÑÑ. ИхÑвчлÑн аюулгүй байдаг веб Ñайтууд заримдаа вируÑд өртөх тохиолдол байдаг.</translation>
<translation id="2807052079800581569">Y Ñ‚ÑнхлÑгийн дагуу зургийн байршил</translation>
+<translation id="2820957248982571256">Шалгаж байна...</translation>
<translation id="2824775600643448204">ХаÑг ба хайлтын цонх</translation>
<translation id="2826760142808435982">ЭнÑÑ…Ò¯Ò¯ холболтыг <ph name="CIPHER" /> ашиглаж шифрлÑж таниулÑан бөгөөд ÑÐ½Ñ Ð½ÑŒ түлхүүр Ñолилцох механизмын дагуу <ph name="KX" />-ыг ашигладаг.</translation>
<translation id="2835170189407361413">МаÑгтыг цÑвÑрлÑÑ…</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Урилга (Дугтуй)</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="2859806420264540918">Ð­Ð½Ñ Ñайт төвөгтÑй ÑÑвÑл хуурамч зар харуулдаг.</translation>
+<translation id="287596039013813457">ÐÓ©Ñ…Ó©Ñ€Ñөг</translation>
+<translation id="2876489322757410363">Гадны аппликÑйшнÑÑÑ€ төлбөр төлөхийн тулд Ðууцлалтай Ð³Ð¾Ñ€Ð¸Ð¼Ð¾Ð¾Ñ Ð³Ð°Ñ€Ñ‡ байна. ҮргÑлжлүүлÑÑ… Ò¯Ò¯?</translation>
<translation id="2878197950673342043">ПоÑтерын нугалаа</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Цонх байршуулалт</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (Дугтуй)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />. Chrome-н тохиргоо Ñ…ÑÑÑгт Ðюулгүй байдлын шалгалтыг ажиллуулахын тулд Tab, дараа нь Enter дÑÑÑ€ дарна уу</translation>
<translation id="3061707000357573562">Patch үйлчилгÑÑ</translation>
-<translation id="3064966200440839136">Гадаад апп-Ñ€ төлбөр хийхийн тулд нууцлалын Ð³Ð¾Ñ€Ð¸Ð¼Ð¾Ð¾Ñ Ð³Ð°Ñ€Ð°Ñ… гÑж байна. ҮргÑлжлүүлÑÑ… Ò¯Ò¯?</translation>
<translation id="306573536155379004">Тоглоом ÑÑ…ÑллÑÑ.</translation>
<translation id="3080254622891793721">График</translation>
<translation id="3086579638707268289">Веб дÑÑрх таны үйл ажиллагааг Ñ…Ñнаж байна</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">Таны бүртгÑлийг <ph name="MANAGER" /> удирддаг.</translation>
<translation id="3157931365184549694">Дахин ÑÑргÑÑÑ…</translation>
<translation id="3162559335345991374">Таны ашиглаж буй Wi-Fi ÑүлжÑÑ Ñ‚Ð°Ð½Ñ‹Ð³ нÑвтрÑÑ… хуудаÑÑ‚ орохыг шаардах магадлалтай.</translation>
-<translation id="3167968892399408617">Ðууцлалын табад хардаг чихтÑй хуудÑыг хааÑан үед таны хөтчийн түүх, күүки дÑлгүүр, хайлтын түүхÑнд харагдахгүй. Таны татÑан файл болон Ò¯Ò¯ÑгÑÑÑн хавчуургыг хадгалах болно.</translation>
<translation id="3169472444629675720">Олох</translation>
<translation id="3174168572213147020">Ðрал</translation>
<translation id="3176929007561373547">ПрокÑи тохиргоогоо шалгана уу. ЭÑвÑл ÑүлжÑÑний админтайгаа холбогдож 
@@ -600,10 +615,12 @@
<translation id="3229041911291329567">Таны төхөөрөмж болон хөтчийн хувилбарын талаарх мÑдÑÑлÑл</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" />-н карт баталгаажуулалтын кодыг оруулна уу</translation>
<translation id="3234666976984236645">Чухал агуулга бүхий мÑдÑÑллийг үргÑлж илрүүлÑÑ…</translation>
+<translation id="3249845759089040423">ДÑгжин</translation>
<translation id="3252266817569339921">Франц</translation>
<translation id="3266793032086590337">Утга (зөрчил)</translation>
<translation id="3268451620468152448">Цонхнуудыг нÑÑÑ…</translation>
<translation id="3270847123878663523">&amp; Дахин ÑÑ€ÑмбÑлÑÑ… үйлдлийг буцаах</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> холбогдох Ñ…Ò¯ÑÑлтÑй байна</translation>
<translation id="3274521967729236597">Па-Кай</translation>
<translation id="3282085321714087552">Танай байгууллага, <ph name="ENROLLMENT_DOMAIN" /> дараах вебÑайтууд руу тохиргоо ÑÑвÑл бодлого зÑÑ€Ñг зарим мÑдÑÑллийг илгÑÑÑÑн.</translation>
<translation id="3282497668470633863">Картанд нÑÑ€ нÑмÑÑ…</translation>
@@ -656,6 +673,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates Ñерверийн загварын нÑг буюу түүнÑÑÑ Ð¾Ð»Ð¾Ð½ URI нь буруу байгаа бөгөөд Ñ‚Ñднийг ашиглахгүй.</translation>
<translation id="3431636764301398940">Ð­Ð½Ñ ÐºÐ°Ñ€Ñ‚Ñ‹Ð³ ÑÐ½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶Ð¸Ð´ хадгалах</translation>
<translation id="3432601291244612633">ХуудÑыг хаах</translation>
+<translation id="3435738964857648380">Ðууцлал</translation>
<translation id="3435896845095436175">ИдÑвхжүүл</translation>
<translation id="3438829137925142401">Google БүртгÑлдÑÑ Ñ…Ð°Ð´Ð³Ð°Ð»Ñан нууц үгÑÑÑ Ð°ÑˆÐ¸Ð³Ð»Ð°Ñ…</translation>
<translation id="3443726618221119081">Жууро-Ку-Кай</translation>
@@ -698,7 +716,10 @@
<translation id="3584299510153766161">Доод буланд хоёр нүх цоолох</translation>
<translation id="3586931643579894722">ДÑлгÑÑ€Ñнгүй мÑдÑÑлийг нуух</translation>
<translation id="3587738293690942763">Дунд</translation>
+<translation id="3590643883886679995">Таныг Ðууцлалтай Ð³Ð¾Ñ€Ð¸Ð¼Ð¾Ð¾Ñ Ð³Ð°Ñ€Ñны дараа нÑвтрÑÑ… өгөгдлийг ÑÐ½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶ дÑÑÑ€ хадгална.</translation>
+<translation id="359126217934908072">Сар/Жил:</translation>
<translation id="3592413004129370115">Итали (Дугтуй)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Та бүлгÑÑ Ñ…Ò¯ÑÑÑн үедÑÑ ÑˆÐ¸Ð½ÑчлÑÑ… боломжтой. Ð¨Ð¸Ð½Ñ Ð±Ò¯Ð»Ñгт нÑгдÑÑ…Ñд ойролцоогоор 1 өдөр зарцуулдаг.}=1{Та бүлгÑÑ Ñ…Ò¯ÑÑÑн үедÑÑ ÑˆÐ¸Ð½ÑчлÑÑ… боломжтой. Ð¨Ð¸Ð½Ñ Ð±Ò¯Ð»Ñгт нÑгдÑÑ…Ñд ойролцоогоор 1 өдөр зарцуулдаг.}other{Та бүлгÑÑ Ñ…Ò¯ÑÑÑн үедÑÑ ÑˆÐ¸Ð½ÑчлÑÑ… боломжтой. Ð¨Ð¸Ð½Ñ Ð±Ò¯Ð»Ñгт нÑгдÑÑ…Ñд ойролцоогоор {NUM_DAYS} өдөр зарцуулдаг.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">ÐдминиÑтратор аппликÑйшнийг блоклоÑон</translation>
<translation id="3608932978122581043">ЧиглÑлийг заах</translation>
@@ -707,13 +728,13 @@
<translation id="3615877443314183785">ДууÑах огноог зөв оруулна уу</translation>
<translation id="36224234498066874">Хайлтын өгөгдлийг уÑтгах...</translation>
<translation id="362276910939193118">Түүхийг бүрнÑÑÑ€ нь харуул</translation>
-<translation id="3625635938337243871">Таныг нууцлалын Ð³Ð¾Ñ€Ð¸Ð¼Ð¾Ð¾Ñ Ð³Ð°Ñ€Ñны дараа нÑвтрÑÑ… өгөгдлийг ÑÐ½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶ дÑÑÑ€ хадгална.</translation>
<translation id="3630155396527302611">Ð¥ÑÑ€Ñв ÑÐ½Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼ нь ÑүлжÑÑнд нÑвтрÑÑ… зөвшөөрөлтÑй программын
жагÑаалтад орÑон бол жагÑÐ°Ð°Ð»Ñ‚Ð°Ð°Ñ ÑƒÑтгаад, дахин нÑÐ¼Ð½Ñ Ò¯Ò¯.</translation>
<translation id="3630699740441428070">Ð­Ð½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶Ð¸Ð¹Ð½ админиÑтраторууд таны зочилдог веб Ñайтуудыг оруулаад ÑүлжÑÑний ачааллыг тань харах боломжтойгоор ÑүлжÑÑний холболтыг тохируулÑан байна.</translation>
<translation id="3631244953324577188">Биометр</translation>
<translation id="3633738897356909127">Chrome-г шинÑчлÑÑ… товч, Chrome-н тохиргоонооÑоо Chrome-г шинÑчлÑхийн тулд Enter дарна уу</translation>
<translation id="3634530185120165534">Гарах цааÑны тавиур 5</translation>
+<translation id="3637662659967048211">Google БүртгÑлд хадгалах</translation>
<translation id="3640766068866876100">ИндекÑ-4x6-Ext</translation>
<translation id="3642638418806704195">ÐппликÑйшн:</translation>
<translation id="3650584904733503804">Баталгаажуулалтын амжилттай боллоо</translation>
@@ -754,6 +775,7 @@
<translation id="3781428340399460090">Тод Ñгаан</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth төхөөрөмжүүд</translation>
+<translation id="3787675388804467730">Виртуал картын дугаар</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" />-д дууÑна</translation>
<translation id="3789155188480882154">Ð¥ÑмжÑÑ 16</translation>
<translation id="3789841737615482174">Суулгах</translation>
@@ -773,6 +795,7 @@
<translation id="3841184659773414994">Файл хариуцагчид</translation>
<translation id="385051799172605136">Буцах</translation>
<translation id="3858027520442213535">Огноо болон цагийг шинÑчлÑÑ…</translation>
+<translation id="3881478300875776315">Ðрай цөөн мөр харуулах</translation>
<translation id="3884278016824448484">ЗөрчилдөөнтÑй төхөөрөмж танигч</translation>
<translation id="3885155851504623709">Тойрог</translation>
<translation id="388632593194507180">Ð¥Ñналтыг илрүүллÑÑ</translation>
@@ -798,6 +821,7 @@
<translation id="397105322502079400">Тооцоолж байна ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" />-г блоклоÑон байна</translation>
<translation id="3973357910713125165">Chrome-н Ðюулгүй байдлын шалгалтыг ажиллуулах товчлуур. Chrome-н тохиргоо Ñ…ÑÑÑгт Ðюулгүй байдлын шалгалтыг ажиллуулахын тулд Enter дÑÑÑ€ дарна уу</translation>
+<translation id="3986705137476756801">Одоохондоо Шууд тайлбарыг унтраах</translation>
<translation id="3987405730340719549">Ð­Ð½Ñ Ñайт нь хуурамч ÑÑвÑл залилангийн шинжтÑй байж болно гÑж Chrome тодорхойлÑон.
Ð¥ÑÑ€Ñв та үүнийг харуулÑан нь алдаа гÑж үзÑж байвал https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals-Ñ€ зочлоорой.</translation>
@@ -894,13 +918,14 @@
<translation id="4275830172053184480">Төхөөрөмжийг дахин Ñхлүүл</translation>
<translation id="4277028893293644418">Ðууц үгийг шинÑчлÑÑ…</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Ð­Ð½Ñ ÐºÐ°Ñ€Ñ‚Ñ‹Ð³ таны Google БүртгÑлд хадгаллаа}other{ЭдгÑÑÑ€ картыг таны Google БүртгÑлд хадгаллаа}}</translation>
+<translation id="4287885627794386150">Туршилтын ÑрхтÑй Ñ…Ñдий ч идÑвхгүй байна</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> хуудаÑны өнгөц зураг</translation>
<translation id="42981349822642051">Өргөтгөх</translation>
<translation id="4300675098767811073">Баруун ирмÑг дагуу олон нүх цоолох</translation>
<translation id="4302514097724775343">Тоглохын тулд диног товшино уу</translation>
<translation id="4302965934281694568">Chou3 (Дугтуй)</translation>
<translation id="4305666528087210886">Таны файлд хандаж чадÑангүй</translation>
-<translation id="4305817255990598646">СÑлгÑÑ…</translation>
+<translation id="4306529830550717874">ХаÑгийг хадгалах уу?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Блоклох (өгөгдмөл)</translation>
<translation id="4314815835985389558">Синк хийхийг удирдах</translation>
@@ -927,6 +952,7 @@
<translation id="4377125064752653719">Та <ph name="DOMAIN" />-тай холбогдох оролдлого хийÑÑн Ñ…Ñдий ч СерверÑÑÑ Ó©Ð³Ñөн гÑрчилгÑÑг гаргагч ÑтгÑÑдÑÑÑ Ñ†ÑƒÑ†Ð°Ð»Ñан байна. Ð­Ð½Ñ Ð½ÑŒ Ñерверийн аюулгүй байдлын найдвартай ÑÑÑÑ…Ñд огт итгÑÑ… Ñ…ÑÑ€Ñггүй гÑÑÑн үг юм. Та халдагчтай харилцаж байж болно.</translation>
<translation id="4378154925671717803">УтаÑ</translation>
<translation id="4390472908992056574">ХүрÑÑ</translation>
+<translation id="4406883609789734330">Шууд тайлбар</translation>
<translation id="4406896451731180161">Хайлтын үр дүн</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> күүки</translation>
<translation id="4414290883293381923">Та дөнгөж ÑÐ°Ñ ÑÑжигтÑй Ñайтад нууц үгÑÑ Ð¾Ñ€ÑƒÑƒÐ»Ð»Ð°Ð°. Таны ÑÐ½Ñ Ð½ÑƒÑƒÑ† үгийг ашигладаг <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> болон буÑад Ñайт руу очиж, түүнийг одоо өөрчлөхийг Chrome зөвлөж байна.</translation>
@@ -939,7 +965,6 @@
<translation id="4435702339979719576">Ил захидал)</translation>
<translation id="443673843213245140">Орлон ашиглах Ñрхийг хааÑан байгаа боловч тодорхой түвшинд орлон ашиглах тохиргоог туÑгаÑан байна.</translation>
<translation id="4464826014807964867">Танай байгууллагын мÑдÑÑлÑлтÑй вебÑайтууд</translation>
-<translation id="4466881336512663640">МаÑгтын өөрчлөлтийг хадгалахгүй. Та үргÑлжлүүлÑÑ… Ò¯Ò¯?</translation>
<translation id="4476953670630786061">Ð­Ð½Ñ Ð¼Ð°Ñгт аюултай байна. Ðвтоматаар бөглөх Ñ…ÑÑгийг унтрааÑан байна.</translation>
<translation id="4477350412780666475">Дараагийн бичлÑг</translation>
<translation id="4482953324121162758">Ð­Ð½Ñ Ñайтыг орчуулахгүй.</translation>
@@ -973,6 +998,7 @@
<translation id="4594403342090139922">УÑтгах үйлдлийг буцаах</translation>
<translation id="4597348597567598915">Ð¥ÑмжÑÑ 8</translation>
<translation id="4600854749408232102">C6/C5 (Дугтуй)</translation>
+<translation id="4606870351894164739">ÐөлөөтÑй</translation>
<translation id="4628948037717959914">Зураг</translation>
<translation id="4631649115723685955">БÑлÑн мөнгө олгох маÑгтыг холбоÑон</translation>
<translation id="4636930964841734540">ÐœÑдÑÑлÑл</translation>
@@ -992,6 +1018,7 @@
<translation id="4691835149146451662">Ðрхитектур-A (Дугтуй)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Хажуугийн</translation>
+<translation id="4702656508969495934">Шууд тайлбар харагдаж байна. Сонгохын тулд цонх шилжүүлÑгчийг ашиглана уу</translation>
<translation id="4708268264240856090">Таны холболт таÑарлаа</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows ÑүлжÑÑний оношилгоог ажиллуулж байна<ph name="END_LINK" /></translation>
@@ -1005,6 +1032,7 @@
<translation id="4738601419177586157"><ph name="TEXT" />-н хайлтын зөвлөмж</translation>
<translation id="4742407542027196863">Ðууц үгийг удирдах...</translation>
<translation id="4744603770635761495">ГүйцÑтгÑÑ… боломжтой зам</translation>
+<translation id="4749011317274908093">Та Ðууцлалтай горимд шилжлÑÑ</translation>
<translation id="4750917950439032686">Таны мÑдÑÑллийг (нууц үг, кредит картын дугаар зÑÑ€Ñг) ÑÐ½Ñ Ñайтад нууцлалтайгаар илгÑÑнÑ.</translation>
<translation id="4756388243121344051">&amp; Түүх</translation>
<translation id="4758311279753947758">Харилцагчийн мÑдÑÑлÑл нÑмÑÑ…</translation>
@@ -1034,6 +1062,8 @@
<translation id="4813512666221746211">СүлжÑÑний алдаа</translation>
<translation id="4816492930507672669">ХуудÑанд тааруулах</translation>
<translation id="4819347708020428563">ТÑмдÑглÑгÑÑг өгөгдмөлөөр харахаар заÑах уу?</translation>
+<translation id="4825507807291741242">ХүчирхÑг</translation>
+<translation id="4838327282952368871">Зүүд шиг</translation>
<translation id="484462545196658690">Ðвтомат</translation>
<translation id="4850886885716139402">Харах</translation>
<translation id="485316830061041779">Герман</translation>
@@ -1170,6 +1200,7 @@
<translation id="5314967030527622926">Товхимол бÑлдÑгч</translation>
<translation id="5316812925700871227">Цагийн зүүний ÑÑÑ€Ñг ÑргүүлÑÑ…</translation>
<translation id="5317780077021120954">Хадгалах</translation>
+<translation id="5321288445143113935">ТомруулÑан</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" />-Ñ <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">Холбоо барих мÑдÑÑлÑл Ñонгох</translation>
<translation id="5327248766486351172">ÐÑÑ€</translation>
@@ -1177,11 +1208,13 @@
<translation id="5332219387342487447">ХүргÑлтийн арга</translation>
<translation id="5333022057423422993">Chrome таны дөнгөж ÑÐ°Ñ Ð°ÑˆÐ¸Ð³Ð»Ð°Ñан нууц үгийг өгөгдлийн Ð·Ó©Ñ€Ñ‡Ð»Ó©Ó©Ñ Ð¾Ð»Ð»Ð¾Ð¾. БүртгÑлүүдÑÑ Ñ…Ð°Ð¼Ð³Ð°Ð°Ð»Ð°Ñ…Ñ‹Ð½ тулд бид таныг хадгалÑан нууц үгнүүдÑÑ ÑˆÐ°Ð»Ð³Ð°Ñ…Ñ‹Ð³ зөвлөж байна.</translation>
<translation id="5334013548165032829">СиÑтемийн дÑлгÑÑ€Ñнгүй лог</translation>
+<translation id="5334145288572353250">ХаÑгийг хадгалах уу?</translation>
<translation id="5340250774223869109">ÐппликÑйшнийг блоклоÑон</translation>
<translation id="534295439873310000">NFC төхөөрөмжүүд</translation>
<translation id="5344579389779391559">Ð­Ð½Ñ Ñ…ÑƒÑƒÐ´Ð°Ñ Ñ‚Ð°Ð½Ð´ төлбөр ногдуулахаар оролдож болзошгүй</translation>
<translation id="5355557959165512791"><ph name="SITE" />-н Ñертификат хүчингүй болÑон тул Ñ‚ÑƒÑ Ñайтад одоогоор зочлох боломжгүй байна. СүлжÑÑний алдаа, халдлага нь ихÑвчлÑн түр зуурынх байдаг тул ÑÐ½Ñ Ñ…ÑƒÑƒÐ´Ð°Ñ ÑƒÐ´Ð°Ñ…Ð³Ò¯Ð¹ Ñ…Ñвийн ажиллана.</translation>
<translation id="536296301121032821">бодлогын тохиргоог хадгалах үйлдÑл амжилтгүй болÑон байна.</translation>
+<translation id="5363309033720083897">Танай админиÑтраторын зөвшөөрÑөн цуваа порт</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="5386426401304769735">Ð­Ð½Ñ Ñайтын Ñертификатын Ñ…ÑлхÑÑ Ð½ÑŒ SHA-1-г ашиглан баталгаажуулÑан байна.</translation>
@@ -1190,6 +1223,7 @@
<translation id="5398772614898833570">Зарыг блоклоÑон</translation>
<translation id="5400836586163650660">Саарал</translation>
<translation id="540969355065856584">Ð­Ð½Ñ Ñервер нь <ph name="DOMAIN" /> гÑдгÑÑ Ð±Ð°Ñ‚Ð°Ð»Ð¶ чадÑангүй. Учир нь Ñерверийн аюулгүй байдлын гÑрчилгÑÑ Ð½ÑŒ одоогоор хүчин төгөлдөр Ð±ÑƒÑ Ð±Ð°Ð¹Ð½Ð°. Ð­Ð½Ñ Ð°Ð»Ð´Ð°Ð° нь тохиргоо буруу хийгдÑÑнÑÑÑ, ÑÑвÑл халдагч таны холболтонд Ñаад учруулж Ð±Ð°Ð¹Ð³Ð°Ð°Ð³Ð°Ð°Ñ ÑˆÐ°Ð»Ñ‚Ð³Ð°Ð°Ð»Ð¶ болзошгүй.</translation>
+<translation id="541143247543991491">Үүл (ÑиÑтем даÑар)</translation>
<translation id="541416427766103491">Гарах цааÑыг зÑÑ€ÑгцүүлÑÑ… тавцан 4</translation>
<translation id="5421136146218899937">Хайлт хийÑÑн тухай мÑдÑÑллийг арилгах...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> танд мÑдÑгдÑл илгÑÑÑ… Ñ…Ò¯ÑÑлтÑй байна</translation>
@@ -1203,6 +1237,7 @@
<translation id="5455374756549232013">Журмын кодлол Ñул байна</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" />}other{<ph name="CONTACT_PREVIEW" /> болон буÑад <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
+<translation id="5463625433003343978">Төхөөрөмжүүдийг хайж байна...</translation>
<translation id="5469868506864199649">Итали Ñ…Ñл</translation>
<translation id="5470861586879999274">&amp; ЗаÑварлах үйлдлийг дахин хийх</translation>
<translation id="5478437291406423475">B6/C4 (Дугтуй)</translation>
@@ -1252,7 +1287,6 @@
<translation id="5624120631404540903">Ðууц үгийг удирдах</translation>
<translation id="5629630648637658800">Тохиргоог ачаалж чадÑангүй.</translation>
<translation id="5631439013527180824">Хүчин төгөлдөр Ð±ÑƒÑ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶Ð¸Ð¹Ð½ удирдлагын Ñ‚ÑмдÑглÑгÑÑ</translation>
-<translation id="5632627355679805402">Таны өгөгдлийг таны <ph name="BEGIN_LINK" />Google нууц үгтÑй<ph name="END_LINK" /> <ph name="TIME" />-Ñ ÑхлÑн шифрлÑÑÑн байна. Синкийг ÑхлүүлÑхийн тулд үүнийг оруулна уу.</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="5644090287519800334">ХуудаÑны нүүрÑн тал дÑÑÑ€ X Ñ‚ÑнхлÑгийн дагуу зураг шилжүүлÑÑ…</translation>
@@ -1291,12 +1325,12 @@
<translation id="5785756445106461925">Цаашилбал, ÑÐ½Ñ Ñ…ÑƒÑƒÐ´Ð°Ñ Ð½ÑŒ аюултай буÑад Ò¯Ò¯ÑвÑрүүдийг агуулж байна. Ийм төрлийн Ò¯Ò¯ÑвÑрүүдийг дамжуулж байх Ñвцад буÑад Ñ…Ò¯Ð¼Ò¯Ò¯Ñ Ñ…Ð°Ñ€Ð°Ñ…, мөн халдагч нар хууÑанд нөлөөлөхүйц байдлаар өөрчилж болдог.</translation>
<translation id="5786044859038896871">Картын мÑдÑÑллÑÑ Ð±Ó©Ð³Ð»Ó©Ñ… Ò¯Ò¯?</translation>
<translation id="578633867165174378">Chrome таны дөнгөж ÑÐ°Ñ Ð°ÑˆÐ¸Ð³Ð»Ð°Ñан нууц үгийг өгөгдлийн Ð·Ó©Ñ€Ñ‡Ð»Ó©Ó©Ñ Ð¾Ð»Ð»Ð¾Ð¾. Бид ÑÐ½Ñ Ð½ÑƒÑƒÑ† үгийг одоо өөрчлөхийг зөвлөж байна.</translation>
-<translation id="5798290721819630480">Өөрчлөлтийг болих уу?</translation>
<translation id="5803412860119678065">Та <ph name="CARD_DETAIL" />-г бөглөх үү?</translation>
<translation id="5804241973901381774">Зөвшөөрлүүд</translation>
<translation id="5804427196348435412">NFC төхөөрөмжүүдийг ашиглах</translation>
<translation id="5810442152076338065">Таны <ph name="DOMAIN" />-тай холбогдох холболтыг хоцрогдÑон шифр ашиглан шифрлÑÑÑн байна.</translation>
<translation id="5813119285467412249">&amp; ÐÑмÑÑ… үйлдлийг дахин хийх</translation>
+<translation id="5817918615728894473">Холбох</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Таныг төлбөр төлөх үед төлбөрийг ÑÐ½Ñ ÐºÐ°Ñ€Ñ‚Ð°Ð°Ñ Ñуутгах боловч жинхÑÐ½Ñ Ð´ÑƒÐ³Ð°Ð°Ñ€Ñ‹Ð³ нь ÑÐ½Ñ Ñайттай хуваалцахгүй. ÐÑмÑлт хамгаалалтын үүднÑÑÑ ÐºÐ°Ñ€Ñ‚ баталгаажуулалтын түр зуурын код Ò¯Ò¯cгÑÑ… болно.}other{Таныг төлбөр төлөх үед таны Ñонгох ÐºÐ°Ñ€Ñ‚Ð°Ð°Ñ Ñ‚Ó©Ð»Ð±Ó©Ñ€Ð¸Ð¹Ð³ Ñуутгах боловч жинхÑÐ½Ñ Ð´ÑƒÐ³Ð°Ð°Ñ€Ñ‹Ð³ нь ÑÐ½Ñ Ñайттай хуваалцахгүй. ÐÑмÑлт хамгаалалтын үүднÑÑÑ ÐºÐ°Ñ€Ñ‚ баталгаажуулалтын түр зуурын код Ò¯Ò¯cгÑÑ… болно.}}</translation>
<translation id="5826507051599432481">ТүгÑÑмÑл нÑÑ€ (CN)</translation>
<translation id="5838278095973806738">Ð­Ð½Ñ Ñайтын мÑдÑÑллийг халдагч ÑтгÑÑд хулгайлж болзошгүй тул чухал мÑдÑÑллÑÑ Ð±Ò¯Ò¯ оруулна уу (жишÑÑ Ð½ÑŒ нууц үг, кредит карт зÑÑ€Ñг).</translation>
@@ -1304,6 +1338,7 @@
<translation id="5855253129151731373">Ð­Ð½Ñ Ñайтын хоÑтны нÑÑ€ <ph name="LOOKALIKE_DOMAIN" />-тай Ñ‚Ó©ÑÑ‚Ñй байна. Халдагч ÑтгÑÑдүүд заримдаа харахад Ñ…Ñцүү, бага зÑргийн өөрчлөлтийг домайн нÑрд оруулах замаар Ñайтыг дуурайдаг.
Ð¥ÑÑ€Ñв та үүнийг харуулÑан нь алдаа гÑж үзÑж байвал https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals-Ñ€ зочлоорой.</translation>
+<translation id="5860033963881614850">ИдÑвхгүй байна</translation>
<translation id="5862579898803147654">Гарах цааÑыг зÑÑ€ÑгцүүлÑÑ… тавцан 8</translation>
<translation id="5863847714970149516">Дараагийн Ñ…ÑƒÑƒÐ´Ð°Ñ Ñ‚Ð°Ð½Ð´ төлбөр ногдуулж болзошгүй</translation>
<translation id="5866257070973731571">УтаÑны дугаар нÑмÑÑ…</translation>
@@ -1320,6 +1355,7 @@
<translation id="5913377024445952699">ДÑлгÑцийн зураг авахыг түр зогÑооÑон</translation>
<translation id="59174027418879706">ИдÑвхжÑÑн</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1-г ашиглаж байгаа}other{# ашиглаж байгаа}}</translation>
<translation id="5921185718311485855">ÐÑаалттай</translation>
<translation id="5921639886840618607">Картыг Google Account-д хадгалах уу?</translation>
<translation id="5922853866070715753">Бараг дууÑлаа</translation>
@@ -1339,6 +1375,7 @@
<translation id="5989320800837274978">ПрокÑи Ñерверүүд болон а.pac бичвÑрийн холбооÑын аль алиныг нь зааж өгөөгүй байна.</translation>
<translation id="5992691462791905444">ИнженерчлÑлийн Z-нугалаа</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />'-н <ph name="RESULT_COUNT" /> илÑрц</translation>
+<translation id="6006484371116297560">Сонгодог</translation>
<translation id="6008122969617370890">N-Ñ 1 хүртÑлх дараалал</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Ðууц үгÑÑ ÑˆÐ°Ð»Ð³Ð°Ñ…</translation>
@@ -1360,6 +1397,7 @@
<translation id="6045164183059402045">Байршуулах загвар</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="6049004884579590341">БүтÑн дÑлгÑцÑÑÑ Ð³Ð°Ñ€Ð°Ñ… бол |<ph name="ACCELERATOR" />|-г удаан дарна уу</translation>
<translation id="6049488691372270142">ЦааÑны гаралт</translation>
<translation id="6051221802930200923"><ph name="SITE" /> нь Ñертификат баталгаажуулалтыг ашигладаг тул Ñ‚ÑƒÑ Ð²ÐµÐ±Ñайтад одоогоор зочлох боломжгүй байна. СүлжÑÑний алдаа, халдлага нь ихÑвчлÑн түр зуурынх байдаг тул ÑÐ½Ñ Ñ…ÑƒÑƒÐ´Ð°Ñ ÑƒÐ´Ð°Ñ…Ð³Ò¯Ð¹ Ñ…Ñвийн ажиллана.</translation>
<translation id="6051898664905071243">ХуудаÑны тоо:</translation>
@@ -1376,6 +1414,7 @@
<translation id="610911394827799129">Таны Google БүртгÑл <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />-д хайлтын түүхийн Ó©Ó©Ñ€ Ñ…ÑлбÑртÑй байж болзошгүй</translation>
<translation id="6116338172782435947">Түр Ñанах ойд хуулÑан текÑÑ‚, зургийг харах</translation>
<translation id="6120179357481664955">UPI ID-гаа Ñанаж байна уу?</translation>
+<translation id="6123290840358279103">Виртуал картыг харах</translation>
<translation id="6124432979022149706">Chrome байгууллагын холбогч</translation>
<translation id="6146055958333702838">Ðшиглаж байгаа кабелаа шалгаÑны дараагаар рутер, модем ÑÑвÑл буÑад ÑүлжÑÑний төхөөрөмжөө дахин ачааллана уу.</translation>
<translation id="614940544461990577">Оролдож үзÑÑ…:</translation>
@@ -1411,6 +1450,7 @@
<translation id="6289939620939689042">ХуудаÑны өнгө</translation>
<translation id="6290238015253830360">Таны Ñанал болгоÑон нийтлÑл Ñнд харагдана</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome-н Google ТуÑлахыг зогÑоож байна</translation>
<translation id="6305205051461490394"><ph name="URL" />-г ашиглах боломжгүй байна.</translation>
<translation id="6312113039770857350">Веб Ñ…ÑƒÑƒÐ´Ð°Ñ Ð±Ð¾Ð»Ð¾Ð¼Ð¶Ð³Ò¯Ð¹ байна</translation>
@@ -1436,6 +1476,7 @@
<translation id="6390200185239044127">Ð¥Ð°Ð³Ð°Ñ Z-нугалаа</translation>
<translation id="6390662030813198813">ИнженерчлÑл-E</translation>
<translation id="6393956493820063117">ÐдминиÑтраторын бодлогын дагуу <ph name="ORIGIN_NAME" />-Ñ ÑÐ½Ñ Ð±Ð°Ð¹Ñ€ÑˆÐ¸Ð» руу буулгахыг блоклоÑон</translation>
+<translation id="6398765197997659313">ДÑлгÑц дүүрÑн харах Ð³Ð¾Ñ€Ð¸Ð¼Ð¾Ð¾Ñ Ð³Ð°Ñ€Ð°Ñ…</translation>
<translation id="6401136357288658127">Ð­Ð½Ñ ÑƒÐ´Ð¸Ñ€Ð´Ð°Ð¼Ð¶Ð¸Ð¹Ð³ зогÑооÑон байна. Та оронд нь <ph name="NEW_POLICY" /> удирдамжийг ашиглавал зохино.</translation>
<translation id="6404511346730675251">ХадгалагдÑан хуудÑыг заÑах</translation>
<translation id="6406765186087300643">C0 (Дугтуй)</translation>
@@ -1448,7 +1489,6 @@
<translation id="6428450836711225518">УтаÑны дугаараа баталгаажуулах</translation>
<translation id="6433490469411711332">Харилцагчийн мÑдÑÑллийг заÑах</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> нь Ñ…Ð¾Ð»Ð±Ð¾Ð³Ð´Ð¾Ñ…Ð¾Ð¾Ñ Ñ‚Ð°Ñ‚Ð³Ð°Ð»Ð·Ð»Ð°Ð°.</translation>
-<translation id="6434309073475700221">Ð¥ÑÑ€ÑгÑÑхгүй байх</translation>
<translation id="6440503408713884761">ХаагдÑан</translation>
<translation id="6443406338865242315">Таны Ñмар өргөтгөл болон залгааÑыг ÑуулгаÑан болох</translation>
<translation id="6446163441502663861">Каху (Дугтуй)</translation>
@@ -1491,6 +1531,7 @@
<translation id="6624427990725312378">Харилцагчийн мÑдÑÑлÑл</translation>
<translation id="6626291197371920147">ХүчинтÑй картын дугаар оруулах</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Хайх</translation>
+<translation id="6630043285902923878">USB төхөөрөмжүүдийг хайж байна...</translation>
<translation id="6630809736994426279">Таны зураг, нууц үг, меÑÑеж, кредит карт зÑÑ€Ñг мÑдÑÑллийг хулгайлах ÑÑвÑл уÑтгах аюултай программыг таны Mac компьютер дÑÑÑ€ Ñуулгаж болзошгүй халдагчид <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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ЦÑвÑрлÑÑ…</translation>
@@ -1506,6 +1547,7 @@
<translation id="6671697161687535275">МаÑгтын зөвлөмжийг Chromium-Ñ ÑƒÑтгах уу?</translation>
<translation id="6685834062052613830">БүртгÑлÑÑÑ Ð³Ð°Ñ€Ñ‡, тохиргоог дууÑгах</translation>
<translation id="6687335167692595844">Фонтын Ñ…ÑмжÑÑг шаардÑан</translation>
+<translation id="6688743156324860098">ШинÑчлÑх…</translation>
<translation id="6689249931105087298">Хар цÑгийн шахалттай харьцангуй</translation>
<translation id="6689271823431384964">Та нÑвтÑÑ€ÑÑн тул Chrome таны картыг таны Google бүртгÑлд хадгалахыг Ñанал болгож байна. Та ÑÐ½Ñ Ð°Ð¶Ð¸Ð»Ð»Ð°Ñ… төлөвийг тохиргоонд өөрчилж болно. Карт ÑзÑмшигчийн нÑÑ€ таны бүртгÑлÑÑÑ Ð³Ð°Ñ€Ð°Ð»Ñ‚Ð°Ð¹.</translation>
<translation id="6698381487523150993">Ò®Ò¯ÑгÑÑÑн:</translation>
@@ -1521,6 +1563,7 @@
<translation id="6744009308914054259">Холболтыг хүлÑÑÑ… Ñвцад та офлайн нийтлÑлүүдийг уншихын тулд татаж авÑан Ñ…ÑÑÑгт зочлох боломжтой.</translation>
<translation id="6753269504797312559">Тохиргооны утга</translation>
<translation id="6757797048963528358">Таны төхөөрөмж идÑвхгүй болÑон байна.</translation>
+<translation id="6767985426384634228">ХаÑгийг шинÑчлÑÑ… Ò¯Ò¯?</translation>
<translation id="6768213884286397650">Хагаки (Ил захидал)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Ðил Ñ…Ó©Ñ… Ñгаан</translation>
@@ -1543,6 +1586,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome нь ÑÐ½Ñ Ñ…ÑƒÑƒÐ´Ñыг уншихад илүү амар болгож Ñ…ÑлбаршуулÑан. Chrome нь аюултай холболтоор ÑÑ… хуудÑыг ÑÑргÑÑÑÑн.</translation>
<translation id="6891596781022320156">Ð­Ð½Ñ Ð¶ÑƒÑ€Ð¼Ñ‹Ð½ түвшинг дÑмжÑÑгүй байна.</translation>
+<translation id="6895143722905299846">Виртуал дугаар:</translation>
<translation id="6895330447102777224">Таны картыг баталгаажуулÑан байна</translation>
<translation id="6897140037006041989">Ð¥ÑÑ€ÑглÑгчийн төлөөлөгч</translation>
<translation id="6898699227549475383">Байгууллага (O)</translation>
@@ -1578,10 +1622,10 @@
<translation id="7004583254764674281">Картуудыг илүү хурдан баталгаажуулахын тулд Windows Hello-г ашиглах</translation>
<translation id="7006930604109697472">Ямар ч байÑан илгÑÑÑ…</translation>
<translation id="7012363358306927923">Ð¥Ñтадын UnionPay</translation>
-<translation id="7012404007611495949">Ð¥ÑмжÑÑг өөрчлөх тохиргоо</translation>
<translation id="7014741021609395734">Томруулалтын түвшин</translation>
<translation id="7016992613359344582">ЭдгÑÑÑ€ тодорхойгүй төлбөрийг танд нÑг удаа, ÑÑвÑл Ñ…Ñд Ñ…ÑдÑн удаа ногдуулж болзошгүй.</translation>
<translation id="7029809446516969842">Ðууц үг</translation>
+<translation id="7030436163253143341">ГÑрчилгÑÑ Ñ…Ò¯Ñ‡Ð¸Ð½Ð³Ò¯Ð¹ байна</translation>
<translation id="7031646650991750659">Таны Google Play-н Ñмар апп ÑуулгаÑан болох</translation>
<translation id="7050187094878475250">Та <ph name="DOMAIN" />-д хандах оролдлого хийÑÑн боловч ÑерверÑÑÑ Ñ‚Ð°Ð½Ñ‹ оруулÑан гÑрчилгÑÑний хугацаа хүчин төгөлдөр гÑж үзÑÑ… Ñ…ÑƒÐ³Ð°Ñ†Ð°Ð°Ð½Ð°Ð°Ñ Ñ…ÑÑ‚Ñрхий урт хугацаанд хүчинтÑй байна гÑж үзÑÑн байна.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Ð­Ð½Ñ ÐºÐ°Ñ€Ñ‚Ñ‹Ð³ одоогоор хадгалах боломжгүй байна}other{ЭдгÑÑÑ€ картыг одоогоор хадгалах боломжгүй байна}}</translation>
@@ -1651,12 +1695,14 @@
<translation id="7300012071106347854">Кобальт хөх</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">ДÑÑд</translation>
+<translation id="7305756307268530424">Илүү удаанаар ÑхлүүлÑÑ…</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Холболтын туÑламж</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" Ñ…ÑÑгийг нуух</translation>
<translation id="733354035281974745">Төхөөрөмжийн дотоод бүртгÑлийг дарж бичих</translation>
<translation id="7333654844024768166">Та дөнгөж ÑÐ°Ñ ÑÑжигтÑй Ñайтад нууц үгÑÑ Ð¾Ñ€ÑƒÑƒÐ»Ð»Ð°Ð°. Таны ÑÐ½Ñ Ð½ÑƒÑƒÑ† үгийг ашигладаг <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> болон буÑад Ñайт руу очиж, түүнийг одоо өөрчлөхийг Chromium зөвлөж байна.</translation>
<translation id="7334320624316649418">&amp; Дахин ÑÑ€ÑмбÑлÑÑ… үйлдлийг дахин хийх</translation>
+<translation id="7337248890521463931">Илүү олон мөр харуулах</translation>
<translation id="7337706099755338005">Таны платформд боломжгүй.</translation>
<translation id="733923710415886693">Серверийн Ñертификатыг Сертификатын ил тод байдлаар ил тод болгоогүй.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1664,6 +1710,7 @@
<translation id="7349430561505560861">A4-ÐÑмÑлт</translation>
<translation id="7353601530677266744">Тушаалын мөр</translation>
<translation id="7359588939039777303">Зарыг блоклоÑон.</translation>
+<translation id="7363096869660964304">ГÑхдÑÑ Ñ‚Ð° харагдаж байгаа. Ðууцлалтай горимд орÑноор таны үзÑлтийг ажил олгогч, интернÑÑ‚ үйлчилгÑÑ Ð½Ð¸Ð¹Ð»Ò¯Ò¯Ð»Ñгч ÑÑвÑл зочилÑон вебÑÐ°Ð¹Ñ‚Ð°Ð°Ñ Ñ‚Ð°Ð½ÑŒ нуухгүй.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />. Chrome-н тохиргоонд хаÑг нÑмÑÑ… болон удирдахын тулд Tab, дараа нь Enter дÑÑÑ€ дарна уу</translation>
<translation id="7365849542400970216">Төхөөрөмжийн ашиглалтаа мÑдÑÑ… Ò¯Ò¯?</translation>
<translation id="7372973238305370288">хайлтын үр дүн</translation>
@@ -1674,7 +1721,9 @@
<translation id="7378594059915113390">Медиа Ñ…Ñналт</translation>
<translation id="7378627244592794276">Үгүй</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Тохирохгүй</translation>
<translation id="7390545607259442187">Карт баталгаажуулах</translation>
+<translation id="7392089738299859607">ХаÑгийг шинÑчлÑÑ…</translation>
<translation id="7399802613464275309">Ðюулгүй байдлын шалгалт</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Таны <ph name="DEVICE_NAME" />-г удирдаж байна</translation>
@@ -1689,6 +1738,7 @@
&lt;li&gt;Ð¢ÑƒÑ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼ хангамжийг компьютерÑÑÑÑÑ Ñ…ÑрхÑн бүрмөÑөн уÑтгах талаар мÑдÑж авахын тулд &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome-н туÑламжийн төвд&lt;/a&gt;-д зочилно уу
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Өргөн-Формат</translation>
+<translation id="7410471291937727359">Хайр татам</translation>
<translation id="7416351320495623771">Ðууц үгийг удирдах...</translation>
<translation id="7419106976560586862">Профайлын зам</translation>
<translation id="7437289804838430631">Харилцагчийн мÑдÑÑлÑл нÑмÑÑ…</translation>
@@ -1704,7 +1754,7 @@
<translation id="7481312909269577407">Forward</translation>
<translation id="7485870689360869515">ÐœÑдÑÑлÑл байхгүй байна.</translation>
<translation id="7495528107193238112">Ð­Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ½Ñ‚Ñ‹Ð³ блоклоÑон байна. ÐÑуудлыг шийдвÑрлÑхийн тулд Ñайтын өмчлөгчтÑй холбогдоно уу.</translation>
-<translation id="7498234416455752244">ҮргÑлжлүүлÑн заÑах</translation>
+<translation id="7498193950643227031">Ð¥ÑмжÑÑг өөрчилÑөн тохиолдолд ÑÐ½Ñ Ð½ÑŒ тооцоолоогүй байдлаар ажиллаж болзошгүй. Та одоо <ph name="SETTINGS" /> Ñ…ÑÑÑгт аппуудын Ñ…ÑмжÑÑг өөрчлөх чадамжийг Ñ…Ñзгаарлах боломжтой.</translation>
<translation id="7503664977220660814">Та дөнгөж ÑÐ°Ñ ÑÑжигтÑй Ñайтад нууц үгÑÑ Ð¾Ñ€ÑƒÑƒÐ»Ð»Ð°Ð°. Таны ÑÐ½Ñ Ð½ÑƒÑƒÑ† үгийг ашигладаг <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> болон буÑад Ñайтын хувьд хадгалÑан нууц үгÑÑÑ Ð¾Ð´Ð¾Ð¾ шалгахыг Chromium зөвлөж байна.</translation>
<translation id="7508255263130623398">БуцааÑан удирдамжийн төхөөрөмжийн id хооÑон, ÑÑвÑл одоогийн төхөөрөмжийн id-тай тохирохгүй байна</translation>
<translation id="7508870219247277067">Ðвокадо ногоон</translation>
@@ -1724,6 +1774,7 @@
<translation id="7548892272833184391">Холболтын алдааг заÑах</translation>
<translation id="7549584377607005141">Ð­Ð½Ñ Ð²ÐµÐ± Ñ…ÑƒÑƒÐ´Ð°Ñ Ð½ÑŒ зохих Ñ…ÑмжÑÑнд гарахын тулд таны өмнө оруулÑан мÑдÑÑллийг шаардаж байна. Та ÑÐ½Ñ Ó©Ð³Ó©Ð³Ð´Ð»Ð¸Ð¹Ð³ дахин илгÑÑж болно, гÑхдÑÑ Ò¯Ò¯Ð½Ð¸Ð¹Ð³ хийÑнÑÑÑ€ÑÑ Ñ‚Ð° ÑÐ½Ñ Ñ…ÑƒÑƒÐ´Ð°Ñны өмнө нь хийж байÑан үйлдлийг давтах Ñ…ÑÑ€ÑгтÑй болно.</translation>
<translation id="7550637293666041147">Таны төхөөрөмжийн Ñ…ÑÑ€ÑглÑгчийн нÑÑ€ болон Chrome Ñ…ÑÑ€ÑглÑгчийн нÑÑ€</translation>
+<translation id="755279583747225797">Туршилт идÑвхтÑй байна</translation>
<translation id="7552846755917812628">Дараах зөвлөгөөг дагана уу:</translation>
<translation id="7554475479213504905">Ямартай ч дахин ачаалж, харуулах</translation>
<translation id="7554791636758816595">Ð¨Ð¸Ð½Ñ Ñ‚Ð°Ð±</translation>
@@ -1742,7 +1793,6 @@
<translation id="7610193165460212391">Утга нь <ph name="VALUE" /> хамрах хүрÑÑнÑÑÑ Ð³Ð°Ñ€Ñан байна.</translation>
<translation id="7613889955535752492">ДууÑах: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome-н тохиргоонд нууц үгÑÑ Ñ…Ð°Ñ€Ð°Ñ… болон удирдахын тулд ÑхлÑÑд Таб дÑÑÑ€, дараа нь Enter дарна уу</translation>
-<translation id="7615602087246926389">Танд Google-ийн данÑны Ó©Ó©Ñ€ нууц үгийг ашиглан кодлоÑон өгөгдөл байна. Доор үүнийг оруулна уу.</translation>
<translation id="7616645509853975347">Таны админиÑтратор таны хөтөч дÑÑÑ€ Chrome Enterprise Connectors-г аÑааÑан байна. ЭдгÑÑÑ€ холбогч нь таны зарим өгөгдөлд хандах ÑрхтÑй.</translation>
<translation id="7619838219691048931">ТөгÑгөлийн Ñ…Ò¯ÑнÑгт</translation>
<translation id="762844065391966283">ÐÑг удаад нÑг</translation>
@@ -1807,13 +1857,12 @@
<translation id="782886543891417279">Таны ашиглаж буй Wi-Fi (<ph name="WIFI_NAME" />) ÑүлжÑÑ Ñ‚Ð°Ð½Ñ‹Ð³ нÑвтрÑÑ… хуудаÑÑ‚ орохыг шаардах магадлалтай.</translation>
<translation id="7836231406687464395">Postfix (Дугтуй)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Байхгүй}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Файлын төрлийн холбоотой байдлаар файлуудыг нÑÑÑ….</translation>
<translation id="7862185352068345852">Сайтыг орхих уу?</translation>
<translation id="7865448901209910068">Хамгийн оновчтой хурд</translation>
<translation id="7874263914261512992">Та дөнгөж ÑÐ°Ñ ÑÑжигтÑй Ñайтад нууц үгÑÑ Ð¾Ñ€ÑƒÑƒÐ»Ð»Ð°Ð°. Таны ÑÐ½Ñ Ð½ÑƒÑƒÑ† үгийг ашигладаг <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> болон буÑад Ñайтын хувьд хадгалÑан нууц үгÑÑÑ Ð¾Ð´Ð¾Ð¾ шалгахыг Chrome зөвлөж байна.</translation>
<translation id="7878562273885520351">Таны нууц үгийг хулгайлÑан байна</translation>
+<translation id="7880146494886811634">ХаÑгийг хадгалах</translation>
<translation id="7882421473871500483">Бор</translation>
<translation id="7887683347370398519">CVC-гÑÑ ÑˆÐ°Ð»Ð³Ð°Ð°Ð´ дахин оролдоно уу</translation>
<translation id="7887885240995164102">ДÑлгÑц доторх дÑлгÑц горимд орох</translation>
@@ -1821,6 +1870,7 @@
<translation id="7894280532028510793">Ð¥ÑÑ€Ñв алдаагүй, зөв бичÑÑн бол <ph name="BEGIN_LINK" />СүлжÑÑний оношилгоог ажиллуулж Ò¯Ð·Ð½Ñ Ò¯Ò¯<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Дугтуй)</translation>
<translation id="7931318309563332511">Тодорхойгүй</translation>
+<translation id="793209273132572360">ХаÑгийг шинÑчлÑÑ… Ò¯Ò¯?</translation>
<translation id="7932579305932748336">Хамгаалалтын өнгөлгөө хийх</translation>
<translation id="79338296614623784">Зөв утаÑны дугаар оруулна уу</translation>
<translation id="7934052535022478634">Төлбөрийг хийж дууÑлаа</translation>
@@ -1891,6 +1941,7 @@
<translation id="8175796834047840627">Та нÑвтÑÑ€ÑÑн тул Chrome таны картыг таны Google БүртгÑлд хадгалахыг Ñанал болгож байна. Та ÑÐ½Ñ Ð°Ð¶Ð¸Ð»Ð»Ð°Ñ… төлөвийг тохиргоонд өөрчилж болно.</translation>
<translation id="8176440868214972690">Ð­Ð½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶Ð¸Ð¹Ð½ админиÑтратор дараах вебÑайтууд руу тохиргоо ÑÑвÑл бодлого зÑÑ€Ñг зарим мÑдÑÑллийг илгÑÑÑÑн.</translation>
<translation id="8184538546369750125">Ерөнхий анхдагч Ñ…ÑлбÑрийг ашиглах (зөвшөөрөх)</translation>
+<translation id="8193086767630290324">ӨгөгдөлтÑй хийÑÑн үйлдлийг нууцлалтай гÑж дарцаглаÑан</translation>
<translation id="8194797478851900357">&amp; Зөөвөрлөх үйлдлийг буцаах</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" ID-тай өргөтгөлийн шинÑчлÑÑ… хүчингүй URL.</translation>
<translation id="8202097416529803614">Захиалгын хураангуй</translation>
@@ -1913,6 +1964,7 @@
<translation id="8249296373107784235">Цуцлах</translation>
<translation id="8249320324621329438">Хамгийн Ñүүлд ÑÑргÑÑгдÑÑн:</translation>
<translation id="8253091569723639551">Тооцооны хаÑг шаардлагатай</translation>
+<translation id="8257387598443225809">Ð­Ð½Ñ Ð°Ð¿Ð¿ нь мобайлд зориулагдÑан</translation>
<translation id="825929999321470778">Бүх хадгалÑан нууц үгийг харуулах</translation>
<translation id="8261506727792406068">УÑтгах</translation>
<translation id="8262952874573525464">Доод ирмÑгийг нь нийлүүлж үдÑÑ…</translation>
@@ -2036,7 +2088,6 @@
<translation id="8719528812645237045">ДÑÑд буланд олон нүх цоолох</translation>
<translation id="8725066075913043281">Дахин оролдож Ò¯Ð·Ð½Ñ Ò¯Ò¯.</translation>
<translation id="8726549941689275341">ХуудаÑны Ñ…ÑмжÑÑ:</translation>
-<translation id="8728672262656704056">Та нууцлалын горимд шилжлÑÑ</translation>
<translation id="8730621377337864115">хийÑÑн</translation>
<translation id="8731544501227493793">Ðууц үг удирдах товч, Chrome-н тохиргоон дÑÑÑ€ нууц үгÑÑ Ñ…Ð°Ñ€Ð°Ñ…, удирдахын тулд Enter дарна уу</translation>
<translation id="8734529307927223492">Таны <ph name="DEVICE_TYPE" />-г <ph name="MANAGER" /> удирддаг</translation>
@@ -2113,6 +2164,7 @@
<translation id="9020542370529661692">Ð­Ð½Ñ Ñ…ÑƒÑƒÐ´Ñыг <ph name="TARGET_LANGUAGE" /> руу хөрвүүлÑÑн байна.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Хүчингүй)</translation>
+<translation id="9030265603405983977">Дан өнгөтÑй</translation>
<translation id="9035022520814077154">Ðюулгүй байдлын алдаа</translation>
<translation id="9038649477754266430">ХуудÑуудыг илүү хурдан ачааллахын тулд таамаглалын үйлчилгÑÑг ашиглана уу</translation>
<translation id="9039213469156557790">Цаашилбал, ÑÐ½Ñ Ñ…ÑƒÑƒÐ´Ð°Ñ Ð½ÑŒ аюултай буÑад Ò¯Ò¯ÑвÑÑ€ агуулж байна. Ийм төрлийн Ò¯Ò¯ÑвÑрийг дамжуулж байх Ñвцад буÑад Ñ…Ò¯Ð¼Ò¯Ò¯Ñ Ñ…Ð°Ñ€Ð°Ñ…, мөн халдагчийн хуудаÑны функцийг өөрчлөх Ñ…ÑÑ€ÑгÑÑл болж болзошгүй.</translation>
@@ -2136,6 +2188,7 @@
<translation id="91108059142052966">ÐдминиÑтраторын бодлого нь нууцлалтай контент харагдах үед <ph name="APPLICATION_TITLE" />-тай дÑлгÑц хуваалцахыг идÑвхгүй болгоно</translation>
<translation id="9114524666733003316">Картыг баталгаажуулж байна...</translation>
<translation id="9114581008513152754">Ð­Ð½Ñ Ñ…Ó©Ñ‚Ñ‡Ð¸Ð¹Ð³ компани ÑÑвÑл буÑад Ð±Ð°Ð¹Ð³ÑƒÑƒÐ»Ð»Ð°Ð³Ð°Ð°Ñ ÑƒÐ´Ð¸Ñ€Ð´Ð´Ð°Ð³Ð³Ò¯Ð¹. Ð­Ð½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶ дÑÑрх үйл ажиллагааг Chrome-Ñ Ð³Ð°Ð´ÑƒÑƒÑ€ удирддаг байж болзошгүй. <ph name="BEGIN_LINK" />ÐÑмÑлт мÑдÑÑлÑл авах<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ШинÑÑ…Ñн</translation>
<translation id="9119042192571987207">БайршуулÑан</translation>
<translation id="9128016270925453879">Бодлогуудыг ачаалÑан</translation>
<translation id="9128870381267983090">СүлжÑÑнд холбогдох</translation>
@@ -2154,6 +2207,7 @@
<translation id="9170848237812810038">&amp; Буцаах</translation>
<translation id="9171296965991013597">Ðппыг орхих уу?</translation>
<translation id="9173282814238175921">Дан документ/Ð¨Ð¸Ð½Ñ Ñ…Ò¯ÑнÑгт</translation>
+<translation id="9173995187295789444">Bluetooth төхөөрөмжүүдийг хайж байна...</translation>
<translation id="917450738466192189">Серверийн гÑрчилгÑÑ Ñ…Ò¯Ñ‡Ð¸Ð½Ð³Ò¯Ð¹ байна.</translation>
<translation id="9174917557437862841">Таб ÑÑлгÑÑ… товчлуур, ÑÐ½Ñ Ñ‚Ð°Ð± руу ÑÑлгÑхийн тулд Enter дÑÑÑ€ дарна уу</translation>
<translation id="9179703756951298733">Chrome-н тохиргоон дÑÑÑ€ÑÑÑ Ñ‚Ó©Ð»Ð±Ó©Ñ€, зÑÑлийн картын мÑдÑÑллÑÑ ÑƒÐ´Ð¸Ñ€Ð´Ð°Ñ…</translation>
diff --git a/chromium/components/strings/components_strings_mr.xtb b/chromium/components/strings/components_strings_mr.xtb
index 141bd9e1871..241b744c0e3 100644
--- a/chromium/components/strings/components_strings_mr.xtb
+++ b/chromium/components/strings/components_strings_mr.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">चेक केलà¥à¤¯à¤¾à¤¸, अधिक जलद फॉरà¥à¤® भरणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤µà¤° Chrome तà¥à¤®à¤šà¥à¤¯à¤¾ कारà¥à¤¡à¤šà¥€ à¤à¤• पà¥à¤°à¤¤ संचयित करेल.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> ची परवानगी निवडा</translation>
<translation id="1113869188872983271">&amp;पà¥à¤¨à¤°à¥à¤•à¥à¤°à¤®à¤¿à¤¤ करा पूरà¥à¤µà¤µà¤¤ करा</translation>
+<translation id="1123753900084781868">आता लाइवà¥à¤¹ कॅपà¥à¤¶à¤¨ उपलबà¥à¤§ नाही</translation>
<translation id="1125573121925420732">वेबसाइट तà¥à¤¯à¤¾à¤‚ची सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾ अपडेट करत असताना चेतावणà¥à¤¯à¤¾ सामानà¥à¤¯ असू शकतात. यात लवकरच सà¥à¤§à¤¾à¤°à¤£à¤¾ वà¥à¤¹à¤¾à¤µà¥€.</translation>
<translation id="112840717907525620">धोरण कॅशे ठीक</translation>
<translation id="1130564665089811311">पेजचे भाषांतर करा बटण, Google Translate वापरून या पेजचे भाषांतर करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ Enter दाबा</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">तà¥à¤®à¤šà¥à¤¯à¤¾ डिवà¥à¤¹à¤¾à¤‡à¤¸à¤šà¥‡ नाव</translation>
<translation id="124116460088058876">आणखी भाषा...</translation>
<translation id="1243027604378859286">लेखक:</translation>
+<translation id="1246424317317450637">ठळक</translation>
<translation id="1250759482327835220">पà¥à¤¢à¥€à¤² वेळेस जलद पेमेंट करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€, तà¥à¤®à¤šà¥à¤¯à¤¾ Google खातà¥à¤¯à¤¾à¤µà¤° तà¥à¤®à¤šà¥‡ कारà¥à¤¡ आणि बिलिंग पतà¥à¤¤à¤¾ सेवà¥à¤¹ करा.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (सिंक केलेले)</translation>
<translation id="1256368399071562588">&lt;p&gt;जर तà¥à¤®à¥à¤¹à¥€ à¤à¤–ादà¥à¤¯à¤¾ वेबसाइटला भेट देणà¥à¤¯à¤¾à¤šà¤¾ पà¥à¤°à¤¯à¤¤à¥à¤¨ केला आणि ती उघडली नाही, तर सगळà¥à¤¯à¤¾à¤¤ आधी टà¥à¤°à¤¬à¤²à¤¶à¥‚टिंग सà¥à¤Ÿà¥‡à¤ªà¥à¤¸à¤¦à¥à¤§à¤¾à¤°à¥‡ या à¤à¤°à¤°à¤µà¤° उपाय काढणà¥à¤¯à¤¾à¤šà¤¾ पà¥à¤°à¤¯à¤¤à¥à¤¨ करा:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">तà¥à¤®à¤šà¤¾ पासवरà¥à¤¡ बदला</translation>
<translation id="1484290072879560759">पाठवणà¥à¤¯à¤¾à¤šà¤¾ पतà¥à¤¤à¤¾ निवडा</translation>
<translation id="1492194039220927094">धोरणे पà¥à¤¢à¥‡ ढकला:</translation>
+<translation id="1495677929897281669">टॅबवर परत</translation>
<translation id="1501859676467574491">तà¥à¤®à¤šà¥à¤¯à¤¾ Google खातà¥à¤¯à¤¾à¤µà¤°à¥€à¤² कारà¥à¤¡à¥‡ दाखवा</translation>
<translation id="1507202001669085618">&lt;p&gt;ऑनलाइन येणà¥à¤¯à¤¾à¤ªà¥‚रà¥à¤µà¥€ तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ साइन इन करावे लागेल अशी वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾ असलेले वाय-फाय पोरà¥à¤Ÿà¤² वापरत असलà¥à¤¯à¤¾à¤¸ तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ ही à¤à¤°à¤° दिसून येईल.&lt;/p&gt;
&lt;p&gt;à¤à¤°à¤° निघून जाणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€, तà¥à¤®à¥à¤¹à¥€ उघडणà¥à¤¯à¤¾à¤šà¤¾ पà¥à¤°à¤¯à¤¤à¥à¤¨ करत असलेलà¥à¤¯à¤¾ पेजवर &lt;strong&gt;कनेकà¥à¤Ÿ&lt;/strong&gt; वर कà¥à¤²à¤¿à¤• करा.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">या पेजचे मà¥à¤¹à¤£à¤£à¥‡ हे आहे की</translation>
<translation id="153384715582417236">सधà¥à¤¯à¤¾ इतकेच</translation>
<translation id="1536390784834419204">पेजचे भाषांतर करायचे आहे</translation>
+<translation id="1539840569003678498">अहवाल पाठवला:</translation>
<translation id="154408704832528245">वितरणाचा पतà¥à¤¤à¤¾ निवडा</translation>
<translation id="1549470594296187301">हे वैशिषà¥â€à¤Ÿà¥à¤¯ वापरणà¥â€à¤¯à¤¾à¤¸à¤¾à¤ à¥€ JavaScript सकà¥à¤·à¤® करणे आवशà¥â€à¤¯à¤• आहे.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">शॉरà¥à¤Ÿ à¤à¤œ पà¥à¤°à¤¥à¤®</translation>
<translation id="168693727862418163">हे धोरण मूलà¥à¤¯ तà¥à¤¯à¤¾à¤šà¥à¤¯à¤¾ सà¥à¤•à¥€à¤®à¤¾à¤¸à¥‹à¤¬à¤¤ पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤ करता आले नाही आणि तà¥à¤¯à¤¾à¤šà¥à¤¯à¤¾à¤•à¤¡à¥‡ दà¥à¤°à¥à¤²à¤•à¥à¤· केले जाईल.</translation>
<translation id="168841957122794586">सरà¥à¤µà¥à¤¹à¤° सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿà¤®à¤§à¥à¤¯à¥‡ à¤à¤• कमकà¥à¤µà¤¤ कà¥à¤°à¤¿à¤ªà¥à¤Ÿà¥‹à¤—à¥à¤°à¤¾à¤«à¤¿à¤• की आहे.</translation>
+<translation id="1696290444144917273">वà¥à¤¹à¤°à¥à¤šà¥à¤¯à¥à¤…ल कारà¥à¤¡à¤šà¥‡ तपशील पहा</translation>
<translation id="1697532407822776718">तà¥à¤®à¥à¤¹à¥€ पूरà¥à¤£à¤ªà¤£à¥‡ तयार आहात!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{हा सरà¥à¤µà¥à¤¹à¤° हे <ph name="DOMAIN" /> असलà¥à¤¯à¤¾à¤šà¥‡ सिदà¥à¤§ करू शकला नाही; तà¥à¤¯à¤¾à¤šà¥‡ सà¥à¤°à¤•à¥à¤·à¤¾ सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ उदà¥à¤¯à¤¾à¤ªà¤¾à¤¸à¥‚न मानले जाईल. हे कदाचित à¤à¤•à¤¾ चà¥à¤•à¥€à¤šà¥à¤¯à¤¾ कॉंफिगरेशनमà¥à¤³à¥‡ किंवा हलà¥à¤²à¥‡à¤–ोराने तà¥à¤®à¤šà¥‡ कनेकà¥à¤¶à¤¨ इंटरसेपà¥à¤Ÿ केलà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ à¤à¤¾à¤²à¥‡ असू शकते.}other{हा सरà¥à¤µà¥à¤¹à¤° हे <ph name="DOMAIN" /> असलà¥à¤¯à¤¾à¤šà¥‡ सिदà¥à¤§ करू शकला नाही; तà¥à¤¯à¤¾à¤šà¥‡ सà¥à¤°à¤•à¥à¤·à¤¾ सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ पà¥à¤¢à¥€à¤² # दिवसांपासून मानले जाईल. हे कदाचित à¤à¤•à¤¾ चà¥à¤•à¥€à¤šà¥à¤¯à¤¾ कॉंफिगरेशनमà¥à¤³à¥‡ किंवा हलà¥à¤²à¥‡à¤–ोराने तà¥à¤®à¤šà¥‡ कनेकà¥à¤¶à¤¨ इंटरसेपà¥à¤Ÿ केलà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ à¤à¤¾à¤²à¥‡ असू शकते.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> हे <ph name="VALUE" /> वर सेट न केलà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ दà¥à¤°à¥à¤²à¤•à¥à¤·à¤¿à¤¤ केले.</translation>
<translation id="1712552549805331520"><ph name="URL" /> ला तà¥à¤®à¤šà¥à¤¯à¤¾ सà¥à¤¥à¤¾à¤¨à¤¿à¤• काà¤à¤ªà¥à¤¯à¥à¤Ÿà¤°à¤µà¤° डेटा कायमचा सà¥à¤Ÿà¥‹à¤…र करायचा आहे</translation>
<translation id="1713628304598226412">टà¥à¤°à¥‡ २</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">मेलबॉकà¥à¤¸ ३</translation>
<translation id="1718029547804390981">भाषà¥à¤¯ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ दसà¥à¤¤à¤à¤µà¤œ खूपच मोठे आहे</translation>
<translation id="1721424275792716183">* फीलà¥à¤¡ आवशà¥à¤¯à¤• आहे</translation>
+<translation id="1727613060316725209">सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ योगà¥à¤¯ आहे</translation>
<translation id="1727741090716970331">वैध कारà¥à¤¡ नंबर जोडा</translation>
<translation id="1728677426644403582">तà¥à¤®à¥à¤¹à¥€ वेब पेजचा सà¥à¤°à¥‹à¤¤ पाहत आहात</translation>
<translation id="173080396488393970">या पà¥à¤°à¤•à¤¾à¤°à¤šà¥à¤¯à¤¾ कारà¥à¤¡à¤²à¤¾ सहायà¥à¤¯ नाही</translation>
@@ -246,14 +253,13 @@
तà¥à¤®à¤šà¥à¤¯à¤¾ <ph name="SITE" /> साठीचà¥à¤¯à¤¾ विनंतीची पूरà¥à¤¤à¤¤à¤¾ करणà¥à¤¯à¤¾à¤ªà¤¾à¤¸à¥‚न रोखले जात आहे. साइटची सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾
आणि इतर मालमतà¥à¤¤à¤¾ काà¤à¤«à¤¿à¤—र करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ साइट ऑपरेटरकडून मूळ धोरणे वापरली जाऊ शकतात.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">कृपया तà¥à¤®à¤šà¥‡ सिंक केलेली सांकेतिक पासफà¥à¤°à¥‡à¤œ अपडेट करा.</translation>
<translation id="1787142507584202372">तà¥à¤®à¤šà¥‡ खà¥à¤²à¥‡ टॅब येथे दिसतात</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, à¤à¤•à¤¾à¤¹à¥‚न अधिक कृती उपलबà¥à¤§ आहेत, पà¥à¤°à¤¤à¥à¤¯à¥‡à¤•à¤¾à¤µà¤° जाणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ टॅब दाबा</translation>
<translation id="1800473098294731951">B9</translation>
<translation id="1803264062614276815">कारà¥à¤¡à¤§à¤¾à¤°à¤•à¤¾à¤šà¥‡ नाव</translation>
<translation id="1807246157184219062">फिकट</translation>
-<translation id="1807528111851433570">पतà¥à¤°à¤• सà¥à¤°à¥‚ करा</translation>
+<translation id="1807528111851433570">शीट सà¥à¤°à¥‚ करा</translation>
<translation id="1812527064848182527">लॅंडसà¥à¤•à¥‡à¤ª</translation>
<translation id="1814698615734239189">हे ॲप मोबाइल डिवà¥à¤¹à¤¾à¤‡à¤¸à¤¸à¤¾à¤ à¥€ डिà¤à¤¾à¤‡à¤¨ केलेले आहे. ते कंपॅटिबिलिटी मोडमधà¥à¤¯à¥‡ रन होत आहे. आकार बदलणà¥à¤¯à¤¾à¤²à¤¾ अनà¥à¤®à¤¤à¥€ दिलà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ ॲप पà¥à¤¨à¥à¤¹à¤¾ सà¥à¤°à¥‚ होणà¥à¤¯à¤¾à¤šà¥à¤¯à¤¾ समावेशासह समसà¥à¤¯à¤¾ येऊ शकतात.</translation>
<translation id="1821930232296380041">अवैध विनंती किंवा विनंती मापदंड</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">जाहिराती</translation>
<translation id="1919367280705858090">विशिषà¥à¤Ÿ à¤à¤°à¤° मेसेजचà¥à¤¯à¤¾ बाबतीत मदत मिळवा</translation>
<translation id="192020519938775529">{COUNT,plural, =0{काहीही नाही}=1{1 साइट}other{# साइट}}</translation>
+<translation id="1924727005275031552">नवीन</translation>
<translation id="1945968466830820669">तà¥à¤®à¥à¤¹à¥€ तà¥à¤®à¤šà¥à¤¯à¤¾ संसà¥à¤¥à¥‡à¤šà¥à¤¯à¤¾ खातà¥à¤¯à¤¾à¤šà¤¾ ॲकà¥à¤¸à¥‡à¤¸ गमावू शकता किंवा तà¥à¤®à¤šà¥€ संवेदनशील माहिती चोरीला जाऊ शकते. Chromium तà¥à¤®à¤šà¤¾ पासवरà¥à¤¡ लगेच बदलणà¥à¤¯à¤¾à¤šà¥€ शिफारस करत आहे.</translation>
<translation id="1947454675006758438">सà¥à¤Ÿà¥‡à¤ªà¤² टॉप राइट</translation>
<translation id="1958218078413065209">तà¥à¤®à¤šà¤¾ सरà¥à¤µà¥‹à¤šà¥à¤š सà¥à¤•à¥‹à¤…र <ph name="SCORE" /> आहे.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">टà¥à¤°à¥‡ ७</translation>
<translation id="204357726431741734">तà¥à¤®à¤šà¥à¤¯à¤¾ Google खाते मधà¥à¤¯à¥‡ सेवà¥à¤¹ केलेले पासवरà¥à¤¡ वापरणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ साइन इन करा</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" />मधील पेज भाषांतरीत केले जाणार नाहीत.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{When this control is on and the status is active, Chrome determines which large group of people, or "cohort," your recent browsing activity is most similar to. Advertisers can select ads for the group and your browsing activity is kept private on your device. Your group is updated every day.}=1{हे नियंतà¥à¤°à¤£ सà¥à¤°à¥‚ असते आणि तà¥à¤¯à¤¾à¤šà¥‡ सà¥à¤Ÿà¥‡à¤Ÿà¤¸ अâ€à¥…कà¥à¤Ÿà¤¿à¤µà¥à¤¹ असते तेवà¥à¤¹à¤¾, तà¥à¤®à¤šà¥€ अलीकडील बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग अâ€à¥…कà¥à¤Ÿà¤¿à¤µà¥à¤¹à¤¿à¤Ÿà¥€ ही लोकांचà¥à¤¯à¤¾ कोणतà¥à¤¯à¤¾ मोठà¥à¤¯à¤¾ गटासारखी किंवा "समूह" यासारखी आहे हे Chrome निशà¥à¤šà¤¿à¤¤ करते. जाहिरातदार हे गटासाठी जाहिराती निवडू शकतात आणि तà¥à¤®à¤šà¥€ बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग अâ€à¥…कà¥à¤Ÿà¤¿à¤µà¥à¤¹à¤¿à¤Ÿà¥€ तà¥à¤®à¤šà¥à¤¯à¤¾ डिवà¥à¤¹à¤¾à¤‡à¤¸à¤µà¤° खाजगी ठेवली जाते. तà¥à¤®à¤šà¤¾ गट दररोज अपडेट केला जातो.}other{हे नियंतà¥à¤°à¤£ सà¥à¤°à¥‚ असते आणि तà¥à¤¯à¤¾à¤šà¥‡ सà¥à¤Ÿà¥‡à¤Ÿà¤¸ अâ€à¥…कà¥à¤Ÿà¤¿à¤µà¥à¤¹ असते तेवà¥à¤¹à¤¾, तà¥à¤®à¤šà¥€ अलीकडील बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग अâ€à¥…कà¥à¤Ÿà¤¿à¤µà¥à¤¹à¤¿à¤Ÿà¥€ ही लोकांचà¥à¤¯à¤¾ कोणतà¥à¤¯à¤¾ मोठà¥à¤¯à¤¾ गटासारखी किंवा "समूह" यासारखी आहे हे Chrome निशà¥à¤šà¤¿à¤¤ करते. जाहिरातदार हे गटासाठी जाहिराती निवडू शकतात आणि तà¥à¤®à¤šà¥€ बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग अâ€à¥…कà¥à¤Ÿà¤¿à¤µà¥à¤¹à¤¿à¤Ÿà¥€ तà¥à¤®à¤šà¥à¤¯à¤¾ डिवà¥à¤¹à¤¾à¤‡à¤¸à¤µà¤° खाजगी ठेवली जाते. तà¥à¤®à¤šà¤¾ गट दर {NUM_DAYS} दिवसांनी अपडेट केला जातो.}}</translation>
<translation id="2053553514270667976">पिनकोड</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 सूचना}other{# सूचना}}</translation>
<translation id="2071692954027939183">सूचना आपोआप बà¥à¤²à¥‰à¤• केलà¥à¤¯à¤¾ होतà¥à¤¯à¤¾ कारण तà¥à¤®à¥à¤¹à¥€ सहसा तà¥à¤¯à¤¾à¤‚ना अनà¥à¤®à¤¤à¥€ देत नाही</translation>
<translation id="2079545284768500474">पहिलà¥à¤¯à¤¾à¤¸à¤¾à¤°à¤–े करा</translation>
<translation id="20817612488360358">सिसà¥à¤Ÿà¤® पà¥à¤°à¥‰à¤•à¥à¤¸à¥€ सेटिंगà¥à¤œ वापरणà¥â€à¤¯à¤¾à¤¸ सेट करणà¥â€à¤¯à¤¾à¤¤ आलà¥à¤¯à¤¾ परंतॠà¤à¤• सà¥à¤¸à¥à¤ªà¤·à¥â€à¤Ÿ पà¥à¤°à¥‰à¤•à¥à¤¸à¥€ कॉंफिगरेशन देखील निरà¥à¤¦à¤¿à¤·à¥â€à¤Ÿ करणà¥â€à¤¯à¤¾à¤¤ आले.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> पैकी <ph name="RESULT_NUMBER" /> परिणाम</translation>
+<translation id="2085876078937250610">सेवà¥à¤¹ करा…</translation>
<translation id="2088086323192747268">सिंक वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करा बटण, Chrome सेटिंगà¥à¤œà¤®à¤§à¥à¤¯à¥‡ तà¥à¤®à¥à¤¹à¥€ कोणती माहिती सिंक करता ते वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ à¤à¤‚टर दाबा</translation>
<translation id="2091887806945687916">धà¥à¤µà¤¨à¥€</translation>
<translation id="2094505752054353250">डोमेन जà¥à¤³à¤¤ नाही</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> साठी वापरकरà¥à¤¤à¤¾ नाव आणि पासवरà¥à¤¡ आवशà¥à¤¯à¤• आहेत.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" /> रोजी à¤à¤•à¥à¤¸à¥à¤ªà¤¾à¤¯à¤° होईल</translation>
<translation id="2337852623177822836">सेटिंग तà¥à¤®à¤šà¥à¤¯à¤¾ ॲडमिनिसà¥à¤Ÿà¥à¤°à¥‡à¤Ÿà¤°à¤¨à¥‡ नियंतà¥à¤°à¤¿à¤¤ केलेले आहे</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> जोडू इचà¥à¤›à¤¿à¤¤à¥‡</translation>
<translation id="2344028582131185878">सà¥à¤µà¤¯à¤‚चलित डाउनलोड</translation>
<translation id="2346319942568447007">तà¥à¤®à¥à¤¹à¥€ कॉपी केलेली इमेज</translation>
<translation id="2354001756790975382">इतर बà¥à¤•à¤®à¤¾à¤°à¥à¤•</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">तà¥à¤®à¥à¤¹à¥€ या साइटवर पाहत असलेलà¥à¤¯à¤¾ इमेज पाहणà¥à¤¯à¤¾à¤¸ आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¥‡ सकà¥à¤·à¤® असू शकतात आणि तà¥à¤¯à¤¾à¤¤ सà¥à¤§à¤¾à¤°à¤£à¤¾ करून तà¥à¤®à¤šà¥€ फसवणूक करू शकतात.</translation>
<translation id="2356070529366658676">विचारा</translation>
<translation id="2357481397660644965">तà¥à¤®à¤šà¥‡ डिवà¥à¤¹à¤¾à¤‡à¤¸ <ph name="DEVICE_MANAGER" /> दà¥à¤µà¤¾à¤°à¥‡ आणि खाते <ph name="ACCOUNT_MANAGER" /> दà¥à¤µà¤¾à¤°à¥‡ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ केले आहे.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{In less than a day}=1{à¤à¤•à¤¾ दिवसामधà¥à¤¯à¥‡}other{{NUM_DAYS} दिवसांमधà¥à¤¯à¥‡}}</translation>
<translation id="2359629602545592467">अनेक</translation>
<translation id="2359808026110333948">सà¥à¤°à¥‚ ठेवा</translation>
+<translation id="2359961752320758691">तà¥à¤®à¤šà¤¾ वà¥à¤¹à¤°à¥à¤šà¥à¤¯à¥à¤…ल कारà¥à¤¡ नंबर वापरला आहे.</translation>
<translation id="2367567093518048410">दरà¥à¤œà¤¾</translation>
<translation id="2372464001869762664">तà¥à¤®à¥à¤¹à¥€ कंफरà¥à¤® केलà¥à¤¯à¤¾à¤¨à¤‚तर, तà¥à¤®à¤šà¥à¤¯à¤¾ Google खातà¥à¤¯à¤¾à¤®à¤§à¥€à¤² कारà¥à¤¡ तपशील या साइटसोबत शेअर केले जातील. तà¥à¤®à¤šà¥à¤¯à¤¾ Plex खाते तपशीलांमधà¥à¤¯à¥‡ CVC शोधा.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">ही शिपिंग पदà¥à¤§à¤¤ उपलबà¥à¤§ नाही. वेगळी पदà¥à¤§à¤¤ वापरून पहा.</translation>
<translation id="2396249848217231973">&amp;हटवा पूरà¥à¤µà¤µà¤¤ करा</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">जà¥à¤¨à¤¾</translation>
<translation id="2413528052993050574">हा सरà¥à¤µà¥à¤¹à¤° हे <ph name="DOMAIN" /> असलà¥à¤¯à¤¾à¤šà¥‡ सिदà¥à¤§ करू शकला नाही; तà¥à¤¯à¤¾à¤šà¥‡ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾ सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ कदाचित रदà¥à¤¦ केले असू शकते. हे कदाचित à¤à¤•à¤¾ चà¥à¤•à¥€à¤šà¥à¤¯à¤¾ कॉंफिगरेशनमà¥à¤³à¥‡ किंवा हलà¥à¤²à¥‡à¤–ोराने तà¥à¤®à¤šà¥‡ कनेकà¥à¤¶à¤¨ इंटरसेपà¥à¤Ÿ केलà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ à¤à¤¾à¤²à¥‡ असू शकते.</translation>
<translation id="2414886740292270097">गडद</translation>
<translation id="2438874542388153331">कà¥à¤µà¤¾à¤¡ पंच राइट</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">सà¥à¤Ÿà¥‡à¤ªà¤² बॉटम राइट</translation>
<translation id="2523886232349826891">फकà¥à¤¤ या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤µà¤° सेवà¥à¤¹ केले जाईल</translation>
<translation id="2524461107774643265">अधिक माहिती जोडा</translation>
-<translation id="2526590354069164005">डेसà¥à¤•à¤Ÿà¥‰à¤ª</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{आणि आणखी à¤à¤•}other{आणि आणखी #}}</translation>
<translation id="2536110899380797252">पतà¥à¤¤à¤¾ जोडा</translation>
<translation id="2539524384386349900">शोधा</translation>
+<translation id="2541219929084442027">तà¥à¤®à¥à¤¹à¥€ गà¥à¤ªà¥à¤¤ मोडमधà¥à¤¯à¥‡ पाहिलेली पेज तà¥à¤®à¤šà¥‡ सरà¥à¤µ गà¥à¤ªà¥à¤¤ टॅब बंद केलà¥à¤¯à¤¾à¤¨à¤‚तर तà¥à¤®à¤šà¤¾ बà¥à¤°à¤¾à¤‰à¤à¤° इतिहास, कà¥à¤•à¥€ सà¥à¤Ÿà¥‹à¤…र किंवा शोध इतिहास यांमधà¥à¤¯à¥‡ राहणार नाहीत. तà¥à¤®à¥à¤¹à¥€ डाउनलोड करता तà¥à¤¯à¤¾ कोणतà¥à¤¯à¤¾à¤¹à¥€ फाइल किंवा तà¥à¤®à¥à¤¹à¥€ तयार केलेले बà¥à¤•à¤®à¤¾à¤°à¥à¤• ठेवले जातील.</translation>
<translation id="2544644783021658368">à¤à¤• दसà¥à¤¤à¤à¤µà¤œ</translation>
<translation id="254947805923345898">धोरण मूलà¥à¤¯ वैध नाही.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> नी à¤à¤• चà¥à¤•à¥€à¤šà¥‡ पà¥à¤°à¤¤à¤¿à¤¸à¤¾à¤¦ पाठविला.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Chrome ची सरà¥à¤µà¥‹à¤¤à¥à¤¤à¤® सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾ मिळवणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />सà¥à¤§à¤¾à¤°à¤¿à¤¤ केलेली सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾ सà¥à¤°à¥‚ करा<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> चा सरà¥à¤µà¥à¤¹à¤° आयपी ॲडà¥à¤°à¥‡à¤¸ सापडला नाही.</translation>
<translation id="2639739919103226564">सà¥à¤¥à¤¿à¤¤à¥€:</translation>
+<translation id="264810637653812429">कोणतीही कंपॅटिबल डिवà¥à¤¹à¤¾à¤‡à¤¸ आढळली नाहीत.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome सेटिंगà¥à¤œà¤®à¤§à¥€à¤² तà¥à¤®à¤šà¤¾ बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग इतिहास, कà¥à¤•à¥€, कॅशे आणि आणखी बरेच काही साफ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ टॅब आणि तà¥à¤¯à¤¾à¤¨à¤‚तर à¤à¤‚टर दाबा</translation>
<translation id="2650446666397867134">फाइलवरील ॲकà¥à¤¸à¥‡à¤¸ नाकारणà¥à¤¯à¤¾à¤¤ आला</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">पà¥à¤¨à¥à¤¹à¤¾ लाà¤à¤š करा</translation>
<translation id="2803306138276472711">Google सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚गला अलीकडे <ph name="SITE" /> वर <ph name="BEGIN_LINK" />मालवेअर आढळले आहे<ph name="END_LINK" />. सामानà¥à¤¯à¤¤à¤ƒ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ असलेलà¥à¤¯à¤¾ वेबसाइट काहीवेळा मालवेअरमà¥à¤³à¥‡ संकà¥à¤°à¤®à¤¿à¤¤ à¤à¤¾à¤²à¥‡à¤²à¥à¤¯à¤¾ असतात.</translation>
<translation id="2807052079800581569">इमेज Y सà¥à¤¥à¤¿à¤¤à¥€</translation>
+<translation id="2820957248982571256">सà¥à¤•à¥…न होत आहे...</translation>
<translation id="2824775600643448204">पतà¥à¤¤à¤¾ आणि शोध बार</translation>
<translation id="2826760142808435982">कनेकà¥à¤¶à¤¨ <ph name="CIPHER" /> वापरून आणि महतà¥à¤¤à¥à¤µà¤¾à¤šà¥‡ à¤à¤•à¥à¤¸à¥à¤šà¥‡à¤‚ज तंतà¥à¤° मà¥à¤¹à¤£à¥‚न <ph name="KX" /> वापर à¤à¤‚कà¥à¤°à¤¿à¤ªà¥à¤Ÿ आणि ऑथेंटिकेट केले आहे.</translation>
<translation id="2835170189407361413">फॉरà¥à¤® कà¥à¤²à¤¿à¤…र करा</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">ही साइट अनाहूत किंवा दिशाभूल करणाऱà¥à¤¯à¤¾ जाहिराती दाखवते.</translation>
+<translation id="287596039013813457">मैतà¥à¤°à¥€à¤ªà¥‚रà¥à¤£</translation>
+<translation id="2876489322757410363">बाहà¥à¤¯ ॲपà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨à¤®à¤¾à¤°à¥à¤«à¤¤ पेमेंट करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ गà¥à¤ªà¥à¤¤ मोडमधून बाहेर पडत आहे. पà¥à¤¢à¥‡ सà¥à¤°à¥‚ ठेवायचे आहे का?</translation>
<translation id="2878197950673342043">पोसà¥à¤Ÿà¤° फोलà¥à¤¡</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">विंडो सà¥à¤¥à¤¾à¤¨ नियोजन</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome सेटिंगà¥à¤œà¤®à¤§à¥à¤¯à¥‡ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾ तपासणी रन करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ टॅब, तà¥à¤¯à¤¾à¤¨à¤‚तर à¤à¤‚टर दाबा</translation>
<translation id="3061707000357573562">पॅच सेवा</translation>
-<translation id="3064966200440839136">बाहà¥à¤¯ ॲपà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ दà¥à¤µà¤¾à¤°à¥‡ पेमेंट देणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ गà¥à¤ªà¥à¤¤ मोड सोडत आहे. सà¥à¤°à¥‚ ठेवायचे?</translation>
<translation id="306573536155379004">गेमला सà¥à¤°à¥à¤µà¤¾à¤¤ à¤à¤¾à¤²à¥€.</translation>
<translation id="3080254622891793721">गà¥à¤°à¤¾à¤«à¤¿à¤•</translation>
<translation id="3086579638707268289">वेबवरील तà¥à¤®à¤šà¥à¤¯à¤¾ ॲकà¥à¤Ÿà¤¿à¤µà¥à¤¹à¤¿à¤Ÿà¥€à¤šà¥‡ नियंतà¥à¤°à¤£ केले जात आहे</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">तà¥à¤®à¤šà¥‡ खाते <ph name="MANAGER" /> दà¥à¤µà¤¾à¤°à¥‡ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ केले आहे.</translation>
<translation id="3157931365184549694">पà¥à¤¨à¤°à¥à¤¸à¤‚चयित करा</translation>
<translation id="3162559335345991374">तà¥à¤®à¥à¤¹à¥€ वापरत असलेलà¥à¤¯à¤¾ वाय-फाय चà¥à¤¯à¤¾ लॉग इन पेजला तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ भेट देणà¥à¤¯à¤¾à¤šà¥€ आवशà¥à¤¯à¤•à¤¤à¤¾ असू शकते.</translation>
-<translation id="3167968892399408617">गà¥à¤ªà¥à¤¤ मोडमधà¥â€à¤¯à¥‡ तà¥à¤®à¥à¤¹à¥€ पाहता ती पृषà¥â€à¤ à¥‡ तà¥à¤®à¥à¤¹à¥€ तà¥à¤®à¤šà¥‡ सरà¥à¤µ गà¥à¤ªà¥à¤¤ टॅब बंद केलà¥â€à¤¯à¤¾à¤¨à¤‚तर तà¥à¤®à¤šà¤¾ बà¥à¤°à¤¾à¤‰à¤à¤° इतिहास, कà¥à¤•à¥€ सà¥à¤Ÿà¥‹à¤…र किंवा शोध इतिहासामधà¥â€à¤¯à¥‡ असणार नाहीत. तà¥à¤®à¥à¤¹à¥€ डाउनलोड करता तà¥à¤¯à¤¾ कोणतà¥à¤¯à¤¾à¤¹à¥€ फाइल किंवा तà¥à¤®à¥à¤¹à¥€ केलेले बà¥à¤•à¤®à¤¾à¤°à¥à¤• ठेवले जातील.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">बेट</translation>
<translation id="3176929007561373547">पà¥à¤°à¥‰à¤•à¥à¤¸à¥€ सरà¥à¤µà¥à¤¹à¤° कारà¥à¤¯ करत आहे हे निशà¥à¤šà¤¿à¤¤ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ तà¥à¤®à¤šà¥à¤¯à¤¾ पà¥à¤°à¥‰à¤•à¥à¤¸à¥€ सेटिंगà¥à¤œ तपासा
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">तà¥à¤®à¤šà¥à¤¯à¤¾ डिवà¥à¤¹à¤¾à¤‡à¤¸ आणि बà¥à¤°à¤¾à¤‰à¤à¤°à¤µà¤¿à¤·à¤¯à¥€ आवृतà¥à¤¤à¥€ माहिती</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> साठी CVC पà¥à¤°à¤µà¤¿à¤·à¥â€à¤Ÿ करा</translation>
<translation id="3234666976984236645">नेहमी या साइटवर महतà¥à¤¤à¥à¤µà¤¾à¤šà¤¾ आशय शोधा</translation>
+<translation id="3249845759089040423">आधà¥à¤¨à¤¿à¤•</translation>
<translation id="3252266817569339921">फà¥à¤°à¥‡à¤‚च</translation>
<translation id="3266793032086590337">मूलà¥à¤¯ (परसà¥à¤ªà¤°à¤µà¤¿à¤°à¥‹à¤§à¥€)</translation>
<translation id="3268451620468152448">उघडे Tabs</translation>
<translation id="3270847123878663523">&amp;पà¥à¤¨à¤°à¥à¤•à¥à¤°à¤®à¤¿à¤¤ करा पूरà¥à¤µà¤µà¤¤ करा</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> कनेकà¥à¤Ÿ करू इचà¥à¤›à¤¿à¤¤à¥‡</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">तà¥à¤®à¤šà¥à¤¯à¤¾ संसà¥à¤¥à¥‡à¤¨à¥‡ <ph name="ENROLLMENT_DOMAIN" /> खालील वेबसाइटना सेटिंगà¥à¤œ किंवा धोरणे यांसारखी काही माहिती पाठवली आहे.</translation>
<translation id="3282497668470633863">कारà¥à¤¡à¤µà¤° नाव जोडा</translation>
@@ -617,7 +634,7 @@
<translation id="3329013043687509092">संपृकà¥à¤¤à¤¤à¤¾</translation>
<translation id="3338095232262050444">सà¥à¤°à¤•à¥à¤·à¤¿à¤¤</translation>
<translation id="3355823806454867987">पà¥à¤°à¥‰à¤•à¥à¤¸à¥€ सेटिंगà¥à¤œ बदला...</translation>
-<translation id="3360103848165129075">पेमेंट हà¤à¤¡à¤²à¤° पतà¥à¤°à¤•</translation>
+<translation id="3360103848165129075">पेमेंट हà¤à¤¡à¤²à¤° शीट</translation>
<translation id="3361596688432910856">Chrome पà¥à¤¢à¥€à¤² माहिती <ph name="BEGIN_EMPHASIS" />सेवà¥à¤¹ करणार नाही<ph name="END_EMPHASIS" />:
<ph name="BEGIN_LIST" />
<ph name="LIST_ITEM" />तà¥à¤®à¤šà¤¾ बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग इतिहास
@@ -655,6 +672,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates चे à¤à¤•à¤¾à¤¹à¥‚न अधिक सरà¥à¤µà¥à¤¹à¤° टेमà¥à¤ªà¤²à¥‡à¤Ÿ URI चà¥à¤•à¥€à¤šà¥‡ आहेत आणि ते वापरले जाणार नाहीत.</translation>
<translation id="3431636764301398940">या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤µà¤° हे कारà¥à¤¡ सेवà¥à¤¹ करा</translation>
<translation id="3432601291244612633">पेज बंद करा</translation>
+<translation id="3435738964857648380">सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾</translation>
<translation id="3435896845095436175">सà¥à¤°à¥‚ करा</translation>
<translation id="3438829137925142401">तà¥à¤®à¤šà¥à¤¯à¤¾ Google खाते मधà¥à¤¯à¥‡ सेवà¥à¤¹ केलेले पासवरà¥à¤¡ वापरा</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -696,7 +714,10 @@
<translation id="3584299510153766161">डà¥à¤¯à¥à¤…ल पंच बॉटम</translation>
<translation id="3586931643579894722">तपशील लपवा</translation>
<translation id="3587738293690942763">मधà¥à¤¯</translation>
+<translation id="3590643883886679995">तà¥à¤®à¥à¤¹à¥€ गà¥à¤ªà¥à¤¤ मोडमधून बाहेर पडलà¥à¤¯à¤¾à¤¨à¤‚तर साइन-इन डेटा या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤µà¤° सेवà¥à¤¹ केला जाईल.</translation>
+<translation id="359126217934908072">महिना/वरà¥à¤·:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{You can reset your group at any time. It takes about a day to join a new group.}=1{तà¥à¤®à¥à¤¹à¥€ तà¥à¤®à¤šà¤¾ गट कधीही रीसेट करू शकता. नवीन गटामधà¥à¤¯à¥‡ सामील होणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ à¤à¤• दिवस लागू शकतो.}other{तà¥à¤®à¥à¤¹à¥€ तà¥à¤®à¤šà¤¾ गट कधीही रीसेट करू शकता. नवीन गटामधà¥à¤¯à¥‡ सामील होणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ {NUM_DAYS} दिवस लागू शकतात.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">तà¥à¤®à¤šà¥à¤¯à¤¾ अâ€à¥…डमिनिसà¥à¤Ÿà¥à¤°à¥‡à¤Ÿà¤°à¤¨à¥‡ अâ€à¥…पà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ बà¥à¤²à¥‰à¤• केले आहे</translation>
<translation id="3608932978122581043">ओरिà¤à¤‚टेशन फीड करा</translation>
@@ -705,13 +726,13 @@
<translation id="3615877443314183785">वैध समापà¥à¤¤à¥€ दिनांक à¤à¤‚टर करा</translation>
<translation id="36224234498066874">बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग डेटा साफ करा...</translation>
<translation id="362276910939193118">पूरà¥à¤£ इतिहास दरà¥à¤¶à¤µà¤¾</translation>
-<translation id="3625635938337243871">तà¥à¤®à¥à¤¹à¥€ गà¥à¤ªà¥à¤¤ मोडमधून बाहेर पडलà¥à¤¯à¤¾à¤¨à¤‚तर साइन इन डेटा या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤µà¤° सà¥à¤Ÿà¥‹à¤…र केला जाईल.</translation>
<translation id="3630155396527302611">नेटवरà¥à¤• ॲकà¥à¤¸à¥‡à¤¸ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ परवानगी दिलेला पà¥à¤°à¥‹à¤—à¥à¤°à¤¾à¤® मà¥à¤¹à¤£à¥‚न तो आधीपासून सूचीबदà¥à¤§ केला असलà¥à¤¯à¤¾à¤¸
तो सूचीमधून काढा आणि पà¥à¤¨à¥à¤¹à¤¾ जोडून पहा.</translation>
<translation id="3630699740441428070">या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤šà¥à¤¯à¤¾ अâ€à¥…डमिनिसà¥à¤Ÿà¥à¤°à¥‡à¤Ÿà¤°à¤¨à¥€ तà¥à¤®à¤šà¥‡ नेटवरà¥à¤• कनेकà¥à¤¶à¤¨ कॉंफिगर केले आहे, जà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ तà¥à¤¯à¤¾à¤‚ना तà¥à¤®à¥à¤¹à¥€ भेट देत असलेलà¥à¤¯à¤¾ वेबसाइटसह, तà¥à¤®à¤šà¥‡ नेटवरà¥à¤• टà¥à¤°à¥…फिक पाहता येते.</translation>
<translation id="3631244953324577188">बायोमेटà¥à¤°à¤¿à¤•</translation>
<translation id="3633738897356909127">Chrome अपडेट करा बटण, तà¥à¤®à¤šà¥à¤¯à¤¾ Chrome सेटिंगà¥à¤œà¤®à¤§à¥‚न Chrome अपडेट करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ à¤à¤‚टर दाबा</translation>
<translation id="3634530185120165534">टà¥à¤°à¥‡ ५</translation>
+<translation id="3637662659967048211">Google खाते मधà¥à¤¯à¥‡ सेवà¥à¤¹ करा</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">ॲपà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨:</translation>
<translation id="3650584904733503804">पà¥à¤°à¤®à¤¾à¤£à¥€à¤•à¤°à¤£ यशसà¥à¤µà¥€</translation>
@@ -752,6 +773,7 @@
<translation id="3781428340399460090">गडद गà¥à¤²à¤¾à¤¬à¥€</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">बà¥à¤²à¥‚टूथ डिवà¥à¤¹à¤¾à¤‡à¤¸</translation>
+<translation id="3787675388804467730">वà¥à¤¹à¤°à¥à¤šà¥à¤¯à¥à¤…ल कारà¥à¤¡ नंबर</translation>
<translation id="3787705759683870569">समापà¥à¤¤ होते: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">आकार १६</translation>
<translation id="3789841737615482174">सà¥à¤¥à¤¾à¤ªà¤¨à¤¾ करा</translation>
@@ -771,6 +793,7 @@
<translation id="3841184659773414994">फाइल हà¤à¤¡à¤²à¤°</translation>
<translation id="385051799172605136">मागील</translation>
<translation id="3858027520442213535">तारीख आणि वेळ अपडेट करा</translation>
+<translation id="3881478300875776315">कमी रेषा दाखवा</translation>
<translation id="3884278016824448484">संघरà¥à¤· करणारा डिवà¥à¤¹à¤¾à¤‡à¤¸ अभिजà¥à¤žà¤¾à¤ªà¤•</translation>
<translation id="3885155851504623709">परगणा</translation>
<translation id="388632593194507180">परीकà¥à¤·à¤£ आढळले</translation>
@@ -788,7 +811,7 @@
<translation id="3949601375789751990">तà¥à¤®à¤šà¤¾ बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग इतिहास येथे दिसतो</translation>
<translation id="3949870428812919180">सेवà¥à¤¹ केलेलà¥à¤¯à¤¾ पेमेंट पदà¥à¤§à¤¤à¥€ नाहीत</translation>
<translation id="3950820424414687140">साइन इन करा</translation>
-<translation id="3961148744525529027">पेमेंट हà¤à¤¡à¤²à¤° पतà¥à¤°à¤• अरà¥à¤§à¥‡ उघडलेले आहे</translation>
+<translation id="3961148744525529027">पेमेंट हà¤à¤¡à¤²à¤° शीट अरà¥à¤§à¥‡ उघडलेले आहे</translation>
<translation id="3962859241508114581">मागील टà¥à¤°à¥…क</translation>
<translation id="3963721102035795474">वाचक मोड</translation>
<translation id="3963837677003247395">मॅनà¥â€à¤¯à¥à¤…ली सà¥à¤°à¥‚ ठेवायचे आहे का?</translation>
@@ -796,6 +819,7 @@
<translation id="397105322502079400">गणना करत आहे...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> अवरोधित केले आहे</translation>
<translation id="3973357910713125165">Chrome सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾ तपासणी रन करा बटण, Chrome सेटिंगà¥à¤œà¤®à¤§à¥à¤¯à¥‡ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾ तपासणी रन करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ à¤à¤‚टर दाबा</translation>
+<translation id="3986705137476756801">आतापà¥à¤°à¤¤à¥‡ लाइवà¥à¤¹ कॅपà¥à¤¶à¤¨ बंद करा</translation>
<translation id="3987405730340719549">ही साइट बनावटी किंवा कपटपूरà¥à¤£ असू शकते असे Chrome ने निरà¥à¤§à¤¾à¤°à¤¿à¤¤ केले आहे.
हे चà¥à¤•à¥‚न दाखवले गेले आहे असे तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ वाटत असलà¥à¤¯à¤¾à¤¸, कृपया https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals ला भेट दà¥à¤¯à¤¾.</translation>
@@ -892,13 +916,14 @@
<translation id="4275830172053184480">तà¥à¤®à¤šà¤¾ डिवà¥à¤¹à¤¾à¤‡à¤¸ रीसà¥à¤Ÿà¤¾à¤°à¥à¤Ÿ करा</translation>
<translation id="4277028893293644418">पासवरà¥à¤¡ रीसेट करा</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{हे कारà¥à¤¡ तà¥à¤®à¤šà¥à¤¯à¤¾ Google खातà¥à¤¯à¤¾à¤¤ सेवà¥à¤¹ केले गेले}other{ही कारà¥à¤¡à¥‡ तà¥à¤®à¤šà¥à¤¯à¤¾ Google खातà¥à¤¯à¤¾à¤¤ सेवà¥à¤¹ केली गेली}}</translation>
+<translation id="4287885627794386150">चाचणीसाठी पातà¥à¤° आहे पण ॲकà¥à¤Ÿà¤¿à¤µà¥à¤¹ नाही</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> पेजची थंबनेल</translation>
<translation id="42981349822642051">विसà¥à¤¤à¥ƒà¤¤ करा</translation>
<translation id="4300675098767811073">मलà¥à¤Ÿà¤¿à¤ªà¤² पंच राइट</translation>
<translation id="4302514097724775343">खेळणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ डायनासोरवर टॅप करा</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">तà¥à¤®à¤šà¥€ फाइल अâ€à¥…कà¥à¤¸à¥‡à¤¸ करता आली नाही</translation>
-<translation id="4305817255990598646">सà¥à¤µà¤¿à¤š</translation>
+<translation id="4306529830550717874">पतà¥à¤¤à¤¾ सेवà¥à¤¹ करायचा आहे का?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">अवरोधित करा (डीफॉलà¥à¤Ÿ)</translation>
<translation id="4314815835985389558">सिंक वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करा</translation>
@@ -925,6 +950,7 @@
<translation id="4377125064752653719">तà¥à¤®à¥à¤¹à¥€ <ph name="DOMAIN" /> वर पोहोचणà¥à¤¯à¤¾à¤šà¤¾ पà¥à¤°à¤¯à¤¤à¥à¤¨ केला, परंतॠसरà¥à¤µà¥à¤¹à¤°à¤¨à¥‡ सादर केलेले पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° तà¥à¤¯à¤¾à¤šà¥à¤¯à¤¾ जारीकरà¥à¤¤à¥à¤¯à¤¾à¤¦à¥à¤µà¤¾à¤°à¥‡ मागे घेतले गेले आहे. याचा अरà¥à¤¥ सरà¥à¤µà¥à¤¹à¤°à¤¨à¥‡ सादर केलेलà¥à¤¯à¤¾ सà¥à¤°à¤•à¥à¤·à¤¾ कà¥à¤°à¥‡à¤¡à¥‡à¤‚शियलवर अजिबात विशà¥à¤µà¤¾à¤¸ ठेवला जाऊ नये. तà¥à¤®à¥à¤¹à¥€ कदाचित आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¥à¤¯à¤¾à¤¶à¥€ संवाद पà¥à¤°à¤‡à¤‚सà¥à¤Ÿà¥‰à¤² करत आहात.</translation>
<translation id="4378154925671717803">फोन</translation>
<translation id="4390472908992056574">बà¥à¤°à¤¿à¤®</translation>
+<translation id="4406883609789734330">लाइवà¥à¤¹ कॅपà¥à¤¶à¤¨</translation>
<translation id="4406896451731180161">शोध परिणाम</translation>
<translation id="4408413947728134509">कà¥à¤•à¥€à¤œ <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">तà¥à¤®à¥à¤¹à¥€ आताच à¤à¤•à¤¾ फसवà¥à¤¯à¤¾ साइटवर तà¥à¤®à¤šà¤¾ पासवरà¥à¤¡ à¤à¤‚टर केला आहे. तà¥à¤®à¥à¤¹à¥€ हा पासवरà¥à¤¡ जेथे वापरता अशा <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> आणि इतर साइटवर जाणà¥à¤¯à¤¾à¤šà¥€ व तो आता बदलणà¥à¤¯à¤¾à¤šà¥€ Chrome शिफारस करते.</translation>
@@ -937,7 +963,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">पà¥à¤°à¥‰à¤•à¥à¤¸à¥€à¤šà¤¾ वापर अकà¥à¤·à¤® करणà¥â€à¤¯à¤¾à¤¤ आला आहे पण à¤à¤• सà¥à¤¸à¥à¤ªà¤·à¥â€à¤Ÿ पà¥à¤°à¥‰à¤•à¥à¤¸à¥€ कॉनà¥â€à¤«à¤¿à¤—रेशन निरà¥à¤¦à¤¿à¤·à¥â€à¤Ÿ करणà¥â€à¤¯à¤¾à¤¤ आले आहे.</translation>
<translation id="4464826014807964867">तà¥à¤®à¤šà¥à¤¯à¤¾ संसà¥à¤¥à¥‡à¤šà¥€ माहिती असलेलà¥à¤¯à¤¾ वेबसाइट</translation>
-<translation id="4466881336512663640">फॉरà¥à¤® बदल गमावतील. तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ नकà¥à¤•à¥€ पà¥à¤¢à¥‡ सà¥à¤°à¥‚ ठेवायचे आहे?</translation>
<translation id="4476953670630786061">हा फॉरà¥à¤® सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नाही. ऑटोफिल बंद केले आहे.</translation>
<translation id="4477350412780666475">पà¥à¤¢à¥€à¤² टà¥à¤°à¥…क</translation>
<translation id="4482953324121162758">या साइटचे भाषांतर केले जाणार नाही.</translation>
@@ -971,6 +996,7 @@
<translation id="4594403342090139922">&amp;हटवा पूरà¥à¤µà¤µà¤¤ करा</translation>
<translation id="4597348597567598915">आकार ८</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">परिणामकारक</translation>
<translation id="4628948037717959914">फोटो</translation>
<translation id="4631649115723685955">कॅशबॅक लिंक केला</translation>
<translation id="4636930964841734540">माहिती</translation>
@@ -990,6 +1016,7 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">साइड</translation>
+<translation id="4702656508969495934">लाइवà¥à¤¹ कॅपà¥à¤¶à¤¨ दिसत आहे, फोकस करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ विंडो सà¥à¤µà¤¿à¤šà¤° वापरा</translation>
<translation id="4708268264240856090">आपलà¥à¤¯à¤¾ कनेकà¥à¤¶à¤¨à¤®à¤§à¥à¤¯à¥‡ वà¥à¤¯à¤¤à¥à¤¯à¤¯ आला</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows नेटवरà¥à¤• निदान चालविणे<ph name="END_LINK" /></translation>
@@ -1003,6 +1030,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> शोध सूचना</translation>
<translation id="4742407542027196863">पासवरà¥à¤¡ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करा…</translation>
<translation id="4744603770635761495">कारà¥à¤¯à¤µà¤¾à¤¹à¥€à¤¯à¥‹à¤—à¥à¤¯ पथ</translation>
+<translation id="4749011317274908093">तà¥à¤®à¥à¤¹à¥€ गà¥à¤ªà¥à¤¤ मोडमधà¥à¤¯à¥‡ आहात</translation>
<translation id="4750917950439032686">तà¥à¤®à¤šà¥€ माहिती (उदाहरणारà¥à¤¥, पासवरà¥à¤¡ किंवा कà¥à¤°à¥‡à¤¡à¤¿à¤Ÿ कारà¥à¤¡ कà¥à¤°à¤®à¤¾à¤‚क) या साइटवर पाठविली जाते तेवà¥à¤¹à¤¾ ती खाजगी राहते.</translation>
<translation id="4756388243121344051">&amp;इतिहास</translation>
<translation id="4758311279753947758">संपरà¥à¤• माहिती जोडा</translation>
@@ -1032,6 +1060,8 @@
<translation id="4813512666221746211">नेटवरà¥à¤• à¤à¤°à¤°</translation>
<translation id="4816492930507672669">पृषà¥â€à¤ à¤¾à¤¨à¥à¤°à¥à¤ª करा</translation>
<translation id="4819347708020428563">भाषà¥à¤¯à¥‡ डीफॉलà¥à¤Ÿ वà¥à¤¹à¥à¤¯à¥‚मधà¥à¤¯à¥‡ संपादित करायची आहेत का?</translation>
+<translation id="4825507807291741242">पà¥à¤°à¤­à¤¾à¤µà¥€</translation>
+<translation id="4838327282952368871">सà¥à¤µà¤ªà¥à¤¨à¤µà¤¤</translation>
<translation id="484462545196658690">ऑटो</translation>
<translation id="4850886885716139402">पहा</translation>
<translation id="485316830061041779">जरà¥à¤®à¤¨</translation>
@@ -1128,7 +1158,7 @@
<translation id="5171045022955879922">URL शोधा किंवा टाइप करा</translation>
<translation id="5171689220826475070">Fanfold-European</translation>
<translation id="5172758083709347301">मशीन</translation>
-<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> मधà¥à¤¯à¥‡ नाही? या à¤à¤°à¤°à¤šà¤¾ अहवाल नोंदवा</translation>
+<translation id="5179510805599951267"><ph name="ORIGINAL_LANGUAGE" /> मधà¥à¤¯à¥‡ नाही? ही à¤à¤°à¤° नोंदवा</translation>
<translation id="5190835502935405962">बà¥à¤•à¤®à¤¾à¤°à¥à¤• बार</translation>
<translation id="519422657042045905">भाषà¥à¤¯ उपलबà¥à¤§ नाही</translation>
<translation id="5201306358585911203">या पेजवरील à¤à¤‚बेड केलेलà¥â€à¤¯à¤¾ पेजचे मà¥à¤¹à¤£à¤£à¥‡ हे आहे की</translation>
@@ -1164,10 +1194,11 @@
<translation id="5306593769196050043">दोनà¥à¤¹à¥€ पतà¥à¤°à¤•à¥‡</translation>
<translation id="5307166000025436103">ओके</translation>
<translation id="5308380583665731573">कनेकà¥â€à¤Ÿ करा</translation>
-<translation id="5308689395849655368">कà¥à¤°à¥…श अहवाल अकà¥à¤·à¤® केला गेला आहे.</translation>
+<translation id="5308689395849655368">कà¥à¤°à¥…श अहवाल बंद केला आहे.</translation>
<translation id="5314967030527622926">बà¥à¤•à¤²à¥‡à¤Ÿ मेकर</translation>
<translation id="5316812925700871227">घडà¥à¤¯à¤¾à¤³à¤¾à¤šà¥à¤¯à¤¾ विरà¥à¤¦à¥à¤§ दिशेने फिरवा</translation>
<translation id="5317780077021120954">सेवà¥à¤¹ करा</translation>
+<translation id="5321288445143113935">वाढवलेले</translation>
<translation id="5323105697514565458"><ph name="NUM_MATCHES" /> पैकी <ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">संपरà¥à¤• माहिती निवडा</translation>
<translation id="5327248766486351172">नाव</translation>
@@ -1175,11 +1206,13 @@
<translation id="5332219387342487447">पाठविणà¥â€à¤¯à¤¾à¤šà¥€ पदà¥à¤§à¤¤</translation>
<translation id="5333022057423422993">Chrome ला तà¥à¤®à¥à¤¹à¥€ नà¥à¤•à¤¤à¤¾à¤š डेटा भंगामधà¥à¤¯à¥‡ वापरलेला पासवरà¥à¤¡ आढळळा आहे. तà¥à¤®à¤šà¥€ खाती सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€, आमà¥à¤¹à¥€ तà¥à¤®à¤šà¥‡ सेवà¥à¤¹ केलेले पासवरà¥à¤¡ तपासणà¥à¤¯à¤¾à¤šà¥€ शिफारस करतो.</translation>
<translation id="5334013548165032829">तपशीलवार सिसà¥à¤Ÿà¤® लॉग</translation>
+<translation id="5334145288572353250">पतà¥à¤¤à¤¾ सेवà¥à¤¹ करायचा आहे का?</translation>
<translation id="5340250774223869109">अâ€à¥…पà¥à¤²à¤¿à¤•à¥‡à¤¶à¤¨ बà¥à¤²à¥‰à¤• केले आहे</translation>
<translation id="534295439873310000">NFC डिवà¥à¤¹à¤¾à¤‡à¤¸</translation>
<translation id="5344579389779391559">या पेजवर कदाचित तà¥à¤®à¤šà¥à¤¯à¤¾à¤•à¤¡à¥‚न शà¥à¤²à¥à¤• आकारले जाऊ शकते</translation>
<translation id="5355557959165512791">तà¥à¤®à¥à¤¹à¥€ आतà¥à¤¤à¤¾ <ph name="SITE" /> ला भेट देऊ शकत नाही कारण तिचे सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ काढून टाकले आहे. नेटवरà¥à¤• à¤à¤°à¤° आणि आकà¥à¤°à¤®à¤£ शकà¥à¤¯à¤¤à¥‹ तातà¥à¤ªà¥à¤°à¤¤à¥€ असतात, तà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ हे पेज नंतर पाहता येईल.</translation>
<translation id="536296301121032821">धोरण सेटिंगà¥à¤œ संचयित करणà¥à¤¯à¤¾à¤¤ अयशसà¥à¤µà¥€</translation>
+<translation id="5363309033720083897">तà¥à¤®à¤šà¥à¤¯à¤¾ अâ€à¥…डमिनिसà¥à¤Ÿà¥à¤°à¥‡à¤Ÿà¤°à¤¨à¥‡ अनà¥à¤®à¤¤à¥€ दिलेला सिरीअल पोरà¥à¤Ÿ</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="5386426401304769735">या साइटसाठी असलेलà¥à¤¯à¤¾ सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ शà¥à¤°à¥ƒà¤‚खलेत SHA-1 वापरून सà¥à¤µà¤¾à¤•à¥à¤·à¤°à¥€ केलेले सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ असते.</translation>
@@ -1188,6 +1221,7 @@
<translation id="5398772614898833570">जाहिराती बà¥à¤²à¥‰à¤• केलà¥à¤¯à¤¾</translation>
<translation id="5400836586163650660">राखाडी</translation>
<translation id="540969355065856584">हा सरà¥à¤µà¥à¤¹à¤° <ph name="DOMAIN" /> असलà¥à¤¯à¤¾à¤šà¥‡ सिदà¥à¤§ करू शकला नाही; तà¥à¤¯à¤¾à¤šà¥‡ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾ सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ यावेळी वैध नाही. हे कदाचित चà¥à¤•à¥€à¤šà¥à¤¯à¤¾ कॉंफिगरेशनमà¥à¤³à¥‡ किंवा हलà¥à¤²à¥‡à¤–ोर तà¥à¤®à¤šà¥‡ कनेकà¥à¤¶à¤¨ इंटरसेपà¥à¤Ÿ करत असलà¥â€à¤¯à¤¾à¤®à¥à¤³à¥‡ होऊ शकते.</translation>
+<translation id="541143247543991491">कà¥à¤²à¤¾à¤‰à¤¡ (संपूरà¥à¤£ सिसà¥à¤Ÿà¤®à¤®à¤§à¥€à¤²)</translation>
<translation id="541416427766103491">सà¥à¤Ÿà¥…कर ४</translation>
<translation id="5421136146218899937">बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग डेटा साफ करा...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> ला तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ सूचना पाठवायची आहे</translation>
@@ -1201,6 +1235,7 @@
<translation id="5455374756549232013">खराब धोरण टाइमसà¥à¤Ÿà¤à¤ª</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" /> आणखी}other{<ph name="CONTACT_PREVIEW" /> आणि <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> आणखी}}</translation>
+<translation id="5463625433003343978">डिवà¥à¤¹à¤¾à¤‡à¤¸ शोधत आहे…</translation>
<translation id="5469868506864199649">इटालियन</translation>
<translation id="5470861586879999274">&amp;संपादित करा पà¥à¤¨à¥à¤¹à¤¾ करा</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)B6/C4 (Envelope)</translation>
@@ -1250,7 +1285,6 @@
<translation id="5624120631404540903">पासवरà¥à¤¡ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करा</translation>
<translation id="5629630648637658800">धोरण सेटिंगà¥à¤œ लोड करणà¥à¤¯à¤¾à¤¤ अयशसà¥à¤µà¥€</translation>
<translation id="5631439013527180824">चà¥à¤•à¥€à¤šà¥‡ डिवà¥à¤¹à¤¾à¤‡à¤¸ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ टोकन</translation>
-<translation id="5632627355679805402">तà¥à¤®à¤šà¤¾ डेटा तà¥à¤®à¤šà¥à¤¯à¤¾ <ph name="BEGIN_LINK" />Google पासवरà¥à¤¡ <ph name="END_LINK" /> ने <ph name="TIME" /> वाजता à¤à¤‚कà¥à¤°à¤¿à¤ªà¥à¤Ÿ केला गेला होता. सिंक सà¥à¤°à¥‚ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ तो à¤à¤‚टर करा.</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="5644090287519800334">साइड १ इमेज X शिफà¥à¤Ÿ</translation>
@@ -1289,12 +1323,12 @@
<translation id="5785756445106461925">पà¥à¤¢à¥‡, या पृषà¥à¤ à¤¾à¤¤ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नसलेली इतर संसाधने समाविषà¥à¤Ÿ आहेत. ही संसाधने संकà¥à¤°à¤®à¤£à¤¾à¤¤ असताना इतरांदà¥à¤µà¤¾à¤°à¥‡ पाहिली जाऊ शकतात आणि पृषà¥à¤ à¤¾à¤šà¥‡ सà¥à¤µà¤°à¥‚प बदलणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¥à¤¯à¤¾à¤¦à¥à¤µà¤¾à¤°à¥‡ सà¥à¤§à¤¾à¤°à¤¿à¤¤ केली जाऊ शकतात.</translation>
<translation id="5786044859038896871">तà¥à¤®à¥à¤¹à¥€ तà¥à¤®à¤šà¥€ कारà¥à¤¡ माहिती भरू इचà¥à¤›à¤¿à¤¤ आहात?</translation>
<translation id="578633867165174378">Chrome ला तà¥à¤®à¥à¤¹à¥€ नà¥à¤•à¤¤à¤¾à¤š डेटा भंगामधà¥à¤¯à¥‡ वापरलेला पासवरà¥à¤¡ आढळळा आहे. आमà¥à¤¹à¥€ हा पासवरà¥à¤¡ आताच बदलणà¥à¤¯à¤¾à¤šà¥€ शिफारस करतो.</translation>
-<translation id="5798290721819630480">बदल टाकून दà¥à¤¯à¤¾à¤¯à¤šà¥‡?</translation>
<translation id="5803412860119678065">तà¥à¤®à¥à¤¹à¥€ तà¥à¤®à¤šà¥‡ <ph name="CARD_DETAIL" /> भरू इचà¥à¤›à¤¿à¤¤ आहात?</translation>
<translation id="5804241973901381774">परवानगà¥à¤¯à¤¾</translation>
<translation id="5804427196348435412">NFC डिवà¥à¤¹à¤¾à¤‡à¤¸ वापरा</translation>
<translation id="5810442152076338065">तà¥à¤®à¤šà¥‡ <ph name="DOMAIN" /> वरील कनेकà¥à¤¶à¤¨ ऑबà¥à¤¸à¥‹à¤²à¥€à¤Ÿ सायफर सूट वापरून à¤à¤‚कà¥à¤°à¤¿à¤ªà¥à¤Ÿ केलेले आहे.</translation>
<translation id="5813119285467412249">&amp;जोडा पà¥à¤¨à¥à¤¹à¤¾ करा</translation>
+<translation id="5817918615728894473">जोडा</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{तà¥à¤®à¥à¤¹à¥€ पेमेंट केलà¥à¤¯à¤¾à¤µà¤° या कारà¥à¤¡à¤µà¤° शà¥à¤²à¥à¤• आकारले जाईल पण तà¥à¤¯à¤¾à¤šà¤¾ वासà¥à¤¤à¤µà¤¿à¤• नंबर या साइटशी शेअर केला जाणार नाही. अतिरिकà¥à¤¤ सà¥à¤°à¤•à¥à¤·à¥‡à¤¸à¤¾à¤ à¥€, CVC जनरेट केले जाईल.}other{तà¥à¤®à¥à¤¹à¥€ पेमेंट केलà¥à¤¯à¤¾à¤µà¤° निवडलेलà¥à¤¯à¤¾ कारà¥à¤¡à¤µà¤° शà¥à¤²à¥à¤• आकारले जाईल पण तà¥à¤¯à¤¾à¤šà¤¾ वासà¥à¤¤à¤µà¤¿à¤• नंबर या साइटशी शेअर केला जाणार नाही. अतिरिकà¥à¤¤ सà¥à¤°à¤•à¥à¤·à¥‡à¤¸à¤¾à¤ à¥€, CVC जनरेट केले जाईल.}}</translation>
<translation id="5826507051599432481">सामानà¥à¤¯ नाव (CN)</translation>
<translation id="5838278095973806738">या साइटवर कोणतीही संवेदनशील माहिती (उदाहरणारà¥à¤¥, पासवरà¥à¤¡ किंवा कà¥à¤°à¥‡à¤¡à¤¿à¤Ÿ कारà¥à¤¡) à¤à¤‚टर करू नका, कारण आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¥‡ ती चोरू शकतात.</translation>
@@ -1302,6 +1336,7 @@
<translation id="5855253129151731373">या साइटचे होसà¥à¤Ÿ नाव <ph name="LOOKALIKE_DOMAIN" /> सारखे दिसत आहे. हलà¥à¤²à¥‡à¤–ोर कधीकधी डोमेन नेममधà¥à¤¯à¥‡ सूकà¥à¤·à¥à¤®, पाहणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ कठीण असणारे बदल करून साइटची नकà¥à¤•à¤² करतात.
हे चà¥à¤•à¥‚न दाखवले गेले आहे असे तà¥à¤®à¥à¤¹à¤¾à¤²à¤¾ वाटत असलà¥à¤¯à¤¾à¤¸, कृपया https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals ला भेट दà¥à¤¯à¤¾.</translation>
+<translation id="5860033963881614850">बंद</translation>
<translation id="5862579898803147654">सà¥à¤Ÿà¥…कर ८</translation>
<translation id="5863847714970149516">पà¥à¤¢à¥€à¤² पेजवर तà¥à¤®à¤šà¥à¤¯à¤¾à¤•à¤¡à¥‚न शà¥à¤²à¥à¤• आकारले जाऊ शकते</translation>
<translation id="5866257070973731571">फोन नंबर जोडा</translation>
@@ -1318,6 +1353,7 @@
<translation id="5913377024445952699">सà¥â€à¤•à¥à¤°à¥€à¤¨ कॅपà¥â€à¤šà¤° थांबवले आहे</translation>
<translation id="59174027418879706">सकà¥à¤·à¤®</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 वापरात आहे}other{# वापरात आहेत}}</translation>
<translation id="5921185718311485855">सà¥à¤°à¥‚ करा</translation>
<translation id="5921639886840618607">Google खातà¥à¤¯à¤¾à¤¤ कारà¥à¤¡ सेवà¥à¤¹ करायचे?</translation>
<translation id="5922853866070715753">जवळजवळ पूरà¥à¤£ à¤à¤¾à¤²à¥‡</translation>
@@ -1337,6 +1373,7 @@
<translation id="5989320800837274978">निशà¥à¤šà¤¿à¤¤ पà¥à¤°à¥‰à¤•à¥â€à¤¸à¥€ सरà¥à¤µà¥à¤¹à¤° किंवा .pac सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ URL देखील निरà¥à¤¦à¤¿à¤·à¥â€à¤Ÿ केलेली नाही.</translation>
<translation id="5992691462791905444">इंजिनीयरिंग Z-फोलà¥à¤¡</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' साठी <ph name="RESULT_COUNT" /> परिणाम</translation>
+<translation id="6006484371116297560">कà¥à¤²à¤¾à¤¸à¤¿à¤•</translation>
<translation id="6008122969617370890">à¤à¤¨ ते १ कà¥à¤°à¤®</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">तà¥à¤®à¤šà¥‡ पासवरà¥à¤¡ तपासा</translation>
@@ -1358,6 +1395,7 @@
<translation id="6045164183059402045">लागू करणà¥à¤¯à¤¾à¤šà¥‡ टेमà¥à¤ªà¤²à¥‡à¤Ÿ</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="6049004884579590341">पूरà¥à¤£ सà¥à¤•à¥à¤°à¥€à¤¨à¤®à¤§à¥‚न बाहेर येणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ |<ph name="ACCELERATOR" />| दाबा आणि धरून ठेवा</translation>
<translation id="6049488691372270142">पेज वितरण</translation>
<translation id="6051221802930200923">ही वेबसाइट सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ पिनिंग वापरत असलà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ तà¥à¤®à¥à¤¹à¥€ आतà¥à¤¤à¤¾ <ph name="SITE" /> पाहू शकणार नाही. नेटवरà¥à¤• à¤à¤°à¤° आणि आकà¥à¤°à¤®à¤£ शकà¥à¤¯à¤¤à¥‹ तातà¥à¤ªà¥à¤°à¤¤à¥€ असतात, तà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ हे पेज नंतर पाहता येईल.</translation>
<translation id="6051898664905071243">पेजची संखà¥à¤¯à¤¾:</translation>
@@ -1374,6 +1412,7 @@
<translation id="610911394827799129">तà¥à¤®à¤šà¥à¤¯à¤¾ Google खातà¥à¤¯à¤¾à¤®à¤§à¥à¤¯à¥‡ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> वर बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग इतिहासाची अनà¥à¤¯ सà¥à¤µà¤°à¥‚पे असू शकतात.</translation>
<translation id="6116338172782435947">कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡à¤µà¤° कॉपी केलेला मजकूर आणि इमेज पहा</translation>
<translation id="6120179357481664955">तà¥à¤®à¤šà¤¾ UPI आयडी लकà¥à¤·à¤¾à¤¤ ठेवायचा आहे का?</translation>
+<translation id="6123290840358279103">वà¥à¤¹à¤°à¥à¤šà¥à¤¯à¥à¤…ल कारà¥à¤¡ पहा</translation>
<translation id="6124432979022149706">Chrome à¤à¤‚टरपà¥à¤°à¤¾à¤‡à¤ कनेकà¥à¤Ÿà¤°</translation>
<translation id="6146055958333702838">कोणतà¥à¤¯à¤¾à¤¹à¥€ केबल तपासा आणि कोणतेही राउटर, मोडेम किंवा तà¥à¤®à¥à¤¹à¥€
वापरत असलेले
@@ -1411,6 +1450,7 @@
<translation id="6289939620939689042">पेजचा रंग</translation>
<translation id="6290238015253830360">तà¥à¤®à¥à¤¹à¥€ सà¥à¤šà¤µà¤¿à¤²à¥‡à¤²à¥‡ लेख येथे दिसतील</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome मधील Google असिसà¥à¤Ÿà¤‚ट थांबत आहे</translation>
<translation id="6305205051461490394"><ph name="URL" /> आवाकà¥à¤¯à¤¾à¤¬à¤¾à¤¹à¥‡à¤° आहे.</translation>
<translation id="6312113039770857350">वेबपेज उपलबà¥à¤§ नाही</translation>
@@ -1436,6 +1476,7 @@
<translation id="6390200185239044127">Z-फोलà¥à¤¡ हाफ</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">अâ€à¥…डमिनिसà¥à¤Ÿà¥à¤°à¥‡à¤Ÿà¤° धोरणादà¥à¤µà¤¾à¤°à¥‡ <ph name="ORIGIN_NAME" /> वरून या सà¥à¤¥à¤¾à¤¨à¤¾à¤µà¤° पेसà¥à¤Ÿ करणे बà¥à¤²à¥‰à¤• केले आहे</translation>
+<translation id="6398765197997659313">पूरà¥à¤£ सà¥à¤•à¥à¤°à¥€à¤¨à¤®à¤§à¥‚न निरà¥à¤—मन करा</translation>
<translation id="6401136357288658127">हे धोरण कालबाहà¥à¤¯ à¤à¤¾à¤²à¥‡ आहे. तà¥à¤®à¥à¤¹à¥€ तà¥à¤¯à¤¾à¤à¤µà¤œà¥€ <ph name="NEW_POLICY" /> धोरण वापरले पाहिजे.</translation>
<translation id="6404511346730675251">बà¥à¤•à¤®à¤¾à¤°à¥à¤• संपादित करा</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1448,7 +1489,6 @@
<translation id="6428450836711225518">तà¥à¤®à¤šà¥à¤¯à¤¾ फोन नंबरची पडताळणी करा</translation>
<translation id="6433490469411711332">संपरà¥à¤• माहिती संपादित करा</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> नी कनेकà¥à¤Ÿ करणà¥à¤¯à¤¾à¤¸ नकार दिला.</translation>
-<translation id="6434309073475700221">टाकून दà¥à¤¯à¤¾</translation>
<translation id="6440503408713884761">दà¥à¤°à¥à¤²à¤•à¥à¤· केले</translation>
<translation id="6443406338865242315">तà¥à¤®à¥à¤¹à¥€ कोणती à¤à¤•à¥à¤¸à¥à¤Ÿà¥‡à¤‚शन आणि पà¥à¤²à¤—-इन इंसà¥à¤Ÿà¥‰à¤² केली आहेत</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1491,6 +1531,7 @@
<translation id="6624427990725312378">संपरà¥à¤• माहिती</translation>
<translation id="6626291197371920147">वैध कारà¥à¤¡ नंबर जोडा</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> शोध</translation>
+<translation id="6630043285902923878">USB डिवà¥à¤¹à¤¾à¤‡à¤¸ शोधत आहे…</translation>
<translation id="6630809736994426279">सधà¥à¤¯à¤¾ <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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">साफ करा</translation>
@@ -1506,6 +1547,7 @@
<translation id="6671697161687535275">Chromium वरून फॉरà¥à¤® सूचना काढून टाकायचà¥à¤¯à¤¾?</translation>
<translation id="6685834062052613830">साइन आउट करा आणि सेटअप पूरà¥à¤£ करा</translation>
<translation id="6687335167692595844">विनंती केलेलà¥à¤¯à¤¾ फॉंटचा आकार</translation>
+<translation id="6688743156324860098">अपडेट करा…</translation>
<translation id="6689249931105087298">काळà¥à¤¯à¤¾ पॉइंटचà¥à¤¯à¤¾ काà¤à¤ªà¥à¤°à¥‡à¤¶à¤¨à¤¶à¥€ संबंंधित</translation>
<translation id="6689271823431384964">तà¥à¤®à¥à¤¹à¥€ साइन इन केले असलà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ Chrome तà¥à¤®à¤šà¥à¤¯à¤¾ Google खातà¥à¤¯à¤¾à¤®à¤§à¥à¤¯à¥‡ तà¥à¤®à¤šà¥€ कारà¥à¤¡à¥‡ सेवà¥à¤¹ करत आहे. तà¥à¤®à¥â€à¤¹à¥€ हे वरà¥à¤¤à¤¨ सेटिंगà¥â€à¤œà¤®à¤§à¥â€à¤¯à¥‡ बदलू शकता. कारà¥à¤¡à¤§à¤¾à¤°à¤•à¤¾à¤šà¥‡ नाव तà¥à¤®à¤šà¥à¤¯à¤¾ खातà¥à¤¯à¤¾à¤®à¤§à¥‚न घेतले जाते.</translation>
<translation id="6698381487523150993">तयार केलेले:</translation>
@@ -1521,6 +1563,7 @@
<translation id="6744009308914054259">कनेकà¥à¤¶à¤¨à¤šà¥€ वाट पाहत असताना, तà¥à¤®à¥à¤¹à¥€ ऑफलाइन लेख वाचणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ डाउनलोडवर जाऊ शकता.</translation>
<translation id="6753269504797312559">धोरण मूलà¥à¤¯</translation>
<translation id="6757797048963528358">तà¥à¤®à¤šà¥‡ डिवà¥à¤¹à¤¾à¤‡à¤¸ निषà¥à¤•à¥à¤°à¥€à¤¯ à¤à¤¾à¤²à¥‡.</translation>
+<translation id="6767985426384634228">पतà¥à¤¤à¤¾ अपडेट करायचा आहे का?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">जांभळा</translation>
@@ -1543,6 +1586,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">हे पेज वाचणे सोपे करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ Chrome ने ते सà¥à¤²à¤­ केले आहे. Chrome ने मूळ पेज असà¥à¤°à¤•à¥à¤·à¤¿à¤¤ कनेकà¥à¤¶à¤¨à¤µà¤°à¥‚न पà¥à¤¨à¥à¤¹à¤¾ मिळवले आहे.</translation>
<translation id="6891596781022320156">धोरण सà¥à¤¤à¤° समरà¥à¤¥à¤¿à¤¤ नाही.</translation>
+<translation id="6895143722905299846">वà¥à¤¹à¤°à¥à¤šà¥à¤¯à¥à¤…ल नंबर:</translation>
<translation id="6895330447102777224">आपलà¥à¤¯à¤¾ कारà¥à¤¡à¤šà¥€ पà¥à¤·à¥à¤Ÿà¥€ केली</translation>
<translation id="6897140037006041989">वापरकरà¥à¤¤à¤¾ à¤à¤œà¤‚ट</translation>
<translation id="6898699227549475383">संसà¥à¤¥à¤¾à¤¤à¥à¤®à¤• (O)</translation>
@@ -1578,10 +1622,10 @@
<translation id="7004583254764674281">कारà¥à¤¡à¤¾à¤‚ची जलद खातà¥à¤°à¥€ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ Windows Hello वापरा</translation>
<translation id="7006930604109697472">तरीही पाठवा</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">आकार बदलणà¥à¤¯à¤¾à¤šà¥€ सेटिंगà¥à¤œ</translation>
<translation id="7014741021609395734">à¤à¥‚म करणà¥à¤¯à¤¾à¤šà¥€ पातळी</translation>
<translation id="7016992613359344582">हे शà¥à¤²à¥à¤• à¤à¤•à¤¾à¤š वेळी दà¥à¤¯à¤¾à¤¯à¤šà¥‡ किंवा आवरà¥à¤¤à¥€ असू शकतात आणि सà¥à¤ªà¤·à¥à¤Ÿ नसू शकतात.</translation>
<translation id="7029809446516969842">पासवरà¥à¤¡</translation>
+<translation id="7030436163253143341">सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ चà¥à¤•à¥€à¤šà¥‡ आहे</translation>
<translation id="7031646650991750659">तà¥à¤®à¥à¤¹à¥€ कोणती Google Play ॲपà¥à¤¸ इंसà¥à¤Ÿà¥‰à¤² केली आहेत</translation>
<translation id="7050187094878475250">तà¥à¤®à¥à¤¹à¥€ <ph name="DOMAIN" /> वर पोहोचणà¥à¤¯à¤¾à¤šà¤¾ पà¥à¤°à¤¯à¤¤à¥à¤¨ केला, परंतॠसरà¥à¤µà¥à¤¹à¤°à¤¨à¥‡ à¤à¤• सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ सादर केले आहे जà¥à¤¯à¤¾à¤šà¤¾ वैधता कालावधी हा विशà¥à¤µà¤¾à¤¸à¤¾à¤°à¥à¤¹à¤¤à¥‡à¤¸à¤¾à¤ à¥€ खूप मोठा आहे.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{हे कारà¥à¤¡ आतà¥à¤¤à¤¾ सेवà¥à¤¹ केले जाऊ शकत नाही}other{ही कारà¥à¤¡à¥‡Â à¤†à¤¤à¥à¤¤à¤¾ सेवà¥à¤¹ केली जाऊ शकत नाहीत}}</translation>
@@ -1634,7 +1678,7 @@
<translation id="7220786058474068424">पà¥à¤°à¤•à¥à¤°à¤¿à¤¯à¤¾ करत आहे</translation>
<translation id="7221855153210829124">सूचना दरà¥à¤¶à¤µà¤¾</translation>
<translation id="7229659723041939809">तà¥à¤®à¥à¤¹à¥€ आताच à¤à¤•à¤¾ फसवà¥à¤¯à¤¾ साइटवर तà¥à¤®à¤šà¤¾ पासवरà¥à¤¡ à¤à¤‚टर केला. तà¥à¤®à¥à¤¹à¥€ हा पासवरà¥à¤¡ आता जेथे वापरता अशा <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> आणि इतर साइटसाठी तà¥à¤®à¤šà¥‡ सेवà¥à¤¹ केलेले पासवरà¥à¤¡ तपासणà¥à¤¯à¤¾à¤šà¥€ Chrome शिफारस करते.</translation>
-<translation id="7233592378249864828">खातà¥à¤°à¥€ केलेले पतà¥à¤°à¤• पà¥à¤°à¤¿à¤‚ट करा</translation>
+<translation id="7233592378249864828">खातà¥à¤°à¥€ केलेले शीट पà¥à¤°à¤¿à¤‚ट करा</translation>
<translation id="7238585580608191973">SHA-256 बोटाचा ठसा</translation>
<translation id="7240120331469437312">सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ विषय वैकलà¥à¤ªà¤¿à¤• नाव</translation>
<translation id="7243010569062352439"><ph name="PASSWORDS" />; <ph name="SIGNIN_DATA" /></translation>
@@ -1651,12 +1695,14 @@
<translation id="7300012071106347854">गडद निळा</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">उचà¥à¤š</translation>
+<translation id="7305756307268530424">धीमà¥à¤¯à¤¾ गतीने सà¥à¤°à¥‚ करा</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">कनेकà¥à¤¶à¤¨ मदत</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" विभाग लपवा</translation>
<translation id="733354035281974745">डिवà¥à¤¹à¤¾à¤‡à¤¸à¤šà¥‡ सà¥à¤¥à¤¾à¤¨à¤¿à¤• खाते ओवà¥à¤¹à¤°à¤°à¤¾à¤‡à¤¡ करा</translation>
<translation id="7333654844024768166">तà¥à¤®à¥à¤¹à¥€ आताच à¤à¤•à¤¾ फसवà¥à¤¯à¤¾ साइटवर तà¥à¤®à¤šà¤¾ पासवरà¥à¤¡ à¤à¤‚टर केला आहे. तà¥à¤®à¥à¤¹à¥€ हा पासवरà¥à¤¡ जेथे वापरता अशा <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> आणि इतर साइटवर जाणà¥à¤¯à¤¾à¤šà¥€ व तो आता बदलणà¥à¤¯à¤¾à¤šà¥€ Chromium शिफारस करते.</translation>
<translation id="7334320624316649418">&amp;पà¥à¤¨à¤°à¥à¤•à¥à¤°à¤®à¤¿à¤¤ करा पà¥à¤¨à¥à¤¹à¤¾ करा</translation>
+<translation id="7337248890521463931">आणखी रेषा दाखवा</translation>
<translation id="7337706099755338005">तà¥à¤®à¤šà¥à¤¯à¤¾ पà¥à¤²à¥…टफॉरà¥à¤®à¤µà¤° उपलबà¥à¤§ नाही.</translation>
<translation id="733923710415886693">सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ पारदरà¥à¤¶à¤•à¤¤à¥‡à¤…ंतरà¥à¤—त सरà¥à¤µà¥à¤¹à¤°à¤šà¥‡ सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ उघड केले नाही.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1664,6 +1710,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">कमांड लाइन</translation>
<translation id="7359588939039777303">जाहिराती बà¥à¤²à¥‰à¤• केलà¥à¤¯à¤¾.</translation>
+<translation id="7363096869660964304">मातà¥à¤°, तà¥à¤®à¥à¤¹à¥€ अदृशà¥à¤¯ नाही. गà¥à¤ªà¥à¤¤ मोडमधà¥à¤¯à¥‡ तà¥à¤®à¤šà¥‡ बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग हे तà¥à¤®à¤šà¤¾ नियोकà¥à¤¤à¤¾, तà¥à¤®à¤šà¤¾ इंटरनेट सेवा पà¥à¤°à¤µà¤ à¤¾à¤¦à¤¾à¤° किंवा तà¥à¤®à¥à¤¹à¥€ भेट देता तà¥à¤¯à¤¾ वेबसाइटपासून लपत नाही.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome सेटिंगà¥à¤œà¤®à¤§à¥à¤¯à¥‡ ॲडà¥à¤°à¥‡à¤¸ जोडणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ आणि वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ टॅब व तà¥à¤¯à¤¾à¤¨à¤‚तर à¤à¤‚टर दाबा</translation>
<translation id="7365849542400970216">तà¥à¤®à¤šà¥à¤¯à¤¾ डिवà¥à¤¹à¤¾à¤‡à¤¸à¤šà¤¾ वापर माहीत आहे का?</translation>
<translation id="7372973238305370288">शोध परिणाम</translation>
@@ -1674,7 +1721,9 @@
<translation id="7378594059915113390">मीडिया नियंतà¥à¤°à¤£à¥‡</translation>
<translation id="7378627244592794276">नाही</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">लागू नाही</translation>
<translation id="7390545607259442187">कारà¥à¤¡à¤šà¥€ पà¥à¤·à¥à¤Ÿà¥€ करा</translation>
+<translation id="7392089738299859607">पतà¥à¤¤à¤¾ अपडेट करा</translation>
<translation id="7399802613464275309">सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾ तपासणी</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">तà¥à¤®à¤šà¥‡ <ph name="DEVICE_NAME" /> वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ केले आहे</translation>
@@ -1689,6 +1738,7 @@
&lt;li&gt;तà¥à¤®à¤šà¥à¤¯à¤¾ कॉंपà¥à¤¯à¥à¤Ÿà¤°à¤µà¤°à¥‚न सॉफà¥à¤Ÿà¤µà¥‡à¤…र कायमसà¥à¤µà¤°à¥‚पी कसे काढून टाकावे याबाबत शिकणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome मदत केंदà¥à¤°&lt;/a&gt; ला भेट दà¥à¤¯à¤¾.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">सà¥à¤‚दर</translation>
<translation id="7416351320495623771">पासवरà¥à¤¡ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करा…</translation>
<translation id="7419106976560586862">पà¥à¤°à¥‹à¤«à¤¾à¤‡à¤² पथ</translation>
<translation id="7437289804838430631">संपरà¥à¤• माहिती जोडा</translation>
@@ -1704,7 +1754,7 @@
<translation id="7481312909269577407">पà¥à¤¢à¥€à¤²</translation>
<translation id="7485870689360869515">डेटा आढळला नाही.</translation>
<translation id="7495528107193238112">हा आशय बà¥à¤²à¥‰à¤• केला गेला आहे. समसà¥à¤¯à¥‡à¤šà¥‡ निराकरण करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ साइटचà¥à¤¯à¤¾ मालकाशी संपरà¥à¤• साधा.</translation>
-<translation id="7498234416455752244">संपादन सà¥à¤°à¥‚ ठेवा</translation>
+<translation id="7498193950643227031">आकार बदललà¥à¤¯à¤¾à¤¸, ते अनपेकà¥à¤·à¤¿à¤¤à¤ªà¤£à¥‡ काम करू शकते. तà¥à¤®à¥à¤¹à¥€ आता अâ€à¥…पà¥à¤¸à¤šà¤¾ आकार बदलणà¥à¤¯à¤¾à¤šà¥€ कà¥à¤·à¤®à¤¤à¤¾ <ph name="SETTINGS" /> मधà¥à¤¯à¥‡ मरà¥à¤¯à¤¾à¤¦à¤¿à¤¤ करू शकता.</translation>
<translation id="7503664977220660814">तà¥à¤®à¥à¤¹à¥€ आताच à¤à¤•à¤¾ फसवà¥à¤¯à¤¾ साइटवर तà¥à¤®à¤šà¤¾ पासवरà¥à¤¡ à¤à¤‚टर केला. तà¥à¤®à¥à¤¹à¥€ हा पासवरà¥à¤¡ आता जेथे वापरता अशा <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> आणि इतर साइटसाठी तà¥à¤®à¤šà¥‡ सेवà¥à¤¹ केलेले पासवरà¥à¤¡ तपासणà¥à¤¯à¤¾à¤šà¥€ Chromium शिफारस करते.</translation>
<translation id="7508255263130623398">परत केलेला धोरण डिवà¥à¤¹à¤¾à¤‡à¤¸ आयडी रिकà¥à¤¤ आहे किंवा वरà¥à¤¤à¤®à¤¾à¤¨ डिवà¥à¤¹à¤¾à¤‡à¤¸ आयडी शी जà¥à¤³à¤¤ नाही</translation>
<translation id="7508870219247277067">हिरवे पिवळे</translation>
@@ -1724,6 +1774,7 @@
<translation id="7548892272833184391">कनेकà¥à¤¶à¤¨ à¤à¤°à¤° दà¥à¤°à¥à¤¸à¥à¤¤ करा</translation>
<translation id="7549584377607005141">हे वेबपेज योगà¥à¤¯à¤°à¤¿à¤¤à¥€à¤¨à¥‡ पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ केले जाणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ तà¥à¤®à¥à¤¹à¥€ पूरà¥à¤µà¥€ à¤à¤‚टर केलेला डेटा आवशà¥à¤¯à¤• आहे. तà¥à¤®à¥à¤¹à¥€ हा डेटा पà¥à¤¨à¥à¤¹à¤¾ पाठवू शकता, परंतॠअसे केलà¥à¤¯à¤¾à¤¨à¥‡ या पेजने मागे केलेली कोणतà¥à¤¯à¤¾à¤¹à¥€ कà¥à¤°à¤¿à¤¯à¥‡à¤šà¥€ पà¥à¤¨à¤°à¤¾à¤µà¥ƒà¤¤à¥à¤¤à¥€ तà¥à¤®à¥à¤¹à¥€ कराल.</translation>
<translation id="7550637293666041147">तà¥à¤®à¤šà¥à¤¯à¤¾ डिवà¥à¤¹à¤¾à¤‡à¤¸à¤šà¥‡ वापरकरà¥à¤¤à¤¾ नाव आणि Chrome चे वापरकरà¥à¤¤à¤¾ नाव</translation>
+<translation id="755279583747225797">चाचणी ॲकà¥à¤Ÿà¤¿à¤µà¥à¤¹ आहे</translation>
<translation id="7552846755917812628">खालील टिपा वापरून पहा:</translation>
<translation id="7554475479213504905">रीलोड करा आणि तरीही दाखवा</translation>
<translation id="7554791636758816595">नवीन टॅब</translation>
@@ -1742,9 +1793,8 @@
<translation id="7610193165460212391">मूलà¥à¤¯ <ph name="VALUE" /> शà¥à¤°à¥‡à¤£à¥€à¤šà¥à¤¯à¤¾ बाहेर आहे.</translation>
<translation id="7613889955535752492">कालबाहà¥à¤¯: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome सेटिंगà¥à¤œà¤®à¤§à¥à¤¯à¥‡ तà¥à¤®à¤šà¥‡ पासवरà¥à¤¡ पाहाणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ आणि वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ टॅब आणि तà¥à¤¯à¤¾à¤¨à¤‚तर à¤à¤‚टर दाबा</translation>
-<translation id="7615602087246926389">तà¥à¤®à¤šà¥à¤¯à¤¾à¤•à¤¡à¥‡ आधीपासूनच डेटा आहे जो तà¥à¤®à¤šà¥à¤¯à¤¾ Google खाते पासवरà¥à¤¡à¤šà¥€ विभिनà¥à¤¨ आवृतà¥à¤¤à¥€ वापरà¥à¤¨ à¤à¤‚कà¥à¤°à¤¿à¤ªà¥à¤¶à¤¨ करणà¥â€à¤¯à¤¾à¤¤ आला आहे. कृपया तो खाली à¤à¤‚टर करा.</translation>
<translation id="7616645509853975347">तà¥à¤®à¤šà¥à¤¯à¤¾ अâ€à¥…डमिनिसà¥à¤Ÿà¥à¤°à¥‡à¤Ÿà¤°à¤¨à¥‡ तà¥à¤®à¤šà¥à¤¯à¤¾ बà¥à¤°à¤¾à¤‰à¤à¤°à¤µà¤° Chrome à¤à¤‚टरपà¥à¤°à¤¾à¤‡à¤ कनेकà¥à¤Ÿà¤°à¥à¤¸ सà¥à¤°à¥‚ केली आहेत. या कनेकà¥à¤Ÿà¤°à¤¨à¤¾ तà¥à¤®à¤šà¥à¤¯à¤¾ काही डेटाचा अâ€à¥…कà¥à¤¸à¥‡à¤¸ आहे.</translation>
-<translation id="7619838219691048931">शेवटचे पतà¥à¤°à¤•</translation>
+<translation id="7619838219691048931">शेवटचे शीट</translation>
<translation id="762844065391966283">à¤à¤•à¤¾ वेळी à¤à¤•</translation>
<translation id="7633909222644580952">परफॉरà¥à¤®à¤‚स डेटा आणि कà¥à¤°à¥…श अहवाल</translation>
<translation id="7637571805876720304">Chromium वरून कà¥à¤°à¥‡à¤¡à¤¿à¤Ÿ कारà¥à¤¡ काढून टाकायचे?</translation>
@@ -1753,7 +1803,7 @@
<translation id="7639968568612851608">गडद राखाडी</translation>
<translation id="7647206758853451655">पà¥à¤°à¤¿à¤‚टची गà¥à¤£à¤µà¤¤à¥à¤¤à¤¾</translation>
<translation id="7648992873808071793">या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤µà¤° फाइल संचयित करा</translation>
-<translation id="7653957176542370971">पेमेंट हà¤à¤¡à¤²à¤° पतà¥à¤°à¤• बंद केलेले आहे</translation>
+<translation id="7653957176542370971">पेमेंट हà¤à¤¡à¤²à¤° शीट बंद केलेले आहे</translation>
<translation id="7654909834015434372">तà¥à¤®à¥à¤¹à¥€ भाषà¥à¤¯à¥‡ संपादित करता तेवà¥à¤¹à¤¾ हा दसà¥à¤¤à¤à¤µà¤œ तà¥à¤¯à¤¾à¤šà¥à¤¯à¤¾ मूळ रोटेशनवर परत येईल</translation>
<translation id="765676359832457558">पà¥à¤°à¤—त सेटिंगà¥à¤œ लपवा...</translation>
<translation id="7658239707568436148">रदà¥à¤¦ करा</translation>
@@ -1807,13 +1857,12 @@
<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>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">फाइल पà¥à¤°à¤•à¤¾à¤°à¤¾à¤šà¥‡ सहयोगी वापरून फाइल उघडा.</translation>
<translation id="7862185352068345852">साइट सोडायची?</translation>
<translation id="7865448901209910068">सरà¥à¤µà¥‹à¤¤à¥à¤¤à¤® गती</translation>
<translation id="7874263914261512992">तà¥à¤®à¥à¤¹à¥€ आताच à¤à¤•à¤¾ फसवà¥à¤¯à¤¾ साइटवर तà¥à¤®à¤šà¤¾ पासवरà¥à¤¡ à¤à¤‚टर केला. तà¥à¤®à¥à¤¹à¥€ हा पासवरà¥à¤¡ आता जेथे वापरता अशा <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> आणि इतर साइटसाठी तà¥à¤®à¤šà¥‡ सेवà¥à¤¹ केलेले पासवरà¥à¤¡ तपासणà¥à¤¯à¤¾à¤šà¥€ Chrome शिफारस करते.</translation>
<translation id="7878562273885520351">तà¥à¤®à¤šà¥à¤¯à¤¾ पासवरà¥à¤¡à¤¶à¥€ तडजोड होत असलà¥à¤¯à¤¾à¤šà¥€ शकà¥à¤¯à¤¤à¤¾ आहे</translation>
+<translation id="7880146494886811634">पतà¥à¤¤à¤¾ सेवà¥à¤¹ करा</translation>
<translation id="7882421473871500483">तपकिरी</translation>
<translation id="7887683347370398519">तà¥à¤®à¤šà¥‡ CVC तपासा आणि पà¥à¤¨à¥à¤¹à¤¾ पà¥à¤°à¤¯à¤¤à¥à¤¨ करा</translation>
<translation id="7887885240995164102">चितà¥à¤°à¤¾à¤¤-चितà¥à¤° à¤à¤‚टर करा</translation>
@@ -1821,6 +1870,7 @@
<translation id="7894280532028510793">शबà¥à¤¦à¤²à¥‡à¤–न योगà¥à¤¯ असलà¥à¤¯à¤¾à¤¸, <ph name="BEGIN_LINK" />नेटवरà¥à¤• निदान रन करून पाहा<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">अनोळखी</translation>
+<translation id="793209273132572360">पतà¥à¤¤à¤¾ अपडेट करायचा आहे का?</translation>
<translation id="7932579305932748336">कोट</translation>
<translation id="79338296614623784">वैध फोन नंबर à¤à¤‚टर करा</translation>
<translation id="7934052535022478634">पेमेंट पूरà¥à¤£ à¤à¤¾à¤²à¥‡</translation>
@@ -1891,6 +1941,7 @@
<translation id="8175796834047840627">तà¥à¤®à¥à¤¹à¥€ साइन इन केले असलà¥à¤¯à¤¾à¤®à¥à¤³à¥‡ Chrome तà¥à¤®à¤šà¥à¤¯à¤¾ Google खातà¥à¤¯à¤¾à¤®à¤§à¥à¤¯à¥‡ तà¥à¤®à¤šà¥€ कारà¥à¤¡à¥‡ सेवà¥à¤¹ करत आहे. तà¥à¤®à¥â€à¤¹à¥€ हे वरà¥à¤¤à¤¨ सेटिंगà¥â€à¤œà¤®à¤§à¥â€à¤¯à¥‡ बदलू शकता.</translation>
<translation id="8176440868214972690">या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤šà¥à¤¯à¤¾ अâ€à¥…डमिनिसà¥à¤Ÿà¥à¤°à¥‡à¤Ÿà¤°à¤¨à¥‡ खालील वेबसाइटना सेटिंगà¥à¤œ किंवा धोरणे यांसारखी काही माहिती पाठवली आहे.</translation>
<translation id="8184538546369750125">सारà¥à¤µà¤¤à¥à¤°à¤¿à¤• डीफॉलà¥â€à¤Ÿ वापरा (अनà¥à¤®à¤¤à¥€ दà¥à¤¯à¤¾)</translation>
+<translation id="8193086767630290324">डेटाशी संबंधित कृती गोपनीय मà¥à¤¹à¤£à¥‚न फà¥à¤²à¥…ग केलà¥à¤¯à¤¾</translation>
<translation id="8194797478851900357">&amp;हलवा पूरà¥à¤µà¤µà¤¤ करा</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />"असलेलà¥à¤¯à¤¾ à¤à¤•à¥à¤¸à¥à¤Ÿà¥‡à¤‚शनसाठी अवैध अपडेट URL.</translation>
<translation id="8202097416529803614">ऑरà¥à¤¡à¤° सारांश</translation>
@@ -1913,6 +1964,7 @@
<translation id="8249296373107784235">रदà¥à¤¦ करा</translation>
<translation id="8249320324621329438">अंतिम पà¥à¤°à¤¾à¤ªà¥à¤¤ केलेले:</translation>
<translation id="8253091569723639551">बिलिंग पतà¥à¤¤à¤¾ आवशà¥à¤¯à¤• आहे</translation>
+<translation id="8257387598443225809">हे ॲप मोबाइलसाठी डिà¤à¤¾à¤‡à¤¨ केले आहे</translation>
<translation id="825929999321470778">सेवà¥à¤¹ केलेले सरà¥à¤µ पासवरà¥à¤¡ दाखवा</translation>
<translation id="8261506727792406068">हटवा</translation>
<translation id="8262952874573525464">à¤à¤œ सà¥à¤Ÿà¤¿à¤š बॉटम</translation>
@@ -1921,7 +1973,7 @@
<translation id="8267698848189296333"><ph name="USERNAME" /> मà¥à¤¹à¤£à¥‚न साइन इन करीत आहे</translation>
<translation id="8269242089528251720">वेगळे दसà¥à¤¤à¤à¤µà¤œ/संकलित केलेलà¥à¤¯à¤¾ पà¥à¤°à¤¤à¥€</translation>
<translation id="8275952078857499577">या साइटचे भाषांतर करणे ऑफर करू नका</translation>
-<translation id="8277900682056760511">पेमेंट हà¤à¤¡à¤²à¤° पतà¥à¤°à¤• उघडलेले आहे</translation>
+<translation id="8277900682056760511">पेमेंट हà¤à¤¡à¤²à¤° शीट उघडलेले आहे</translation>
<translation id="8281084378435768645">Large-Photo</translation>
<translation id="8282947398454257691">तà¥à¤®à¤šà¤¾ अननà¥à¤¯ डिवà¥à¤¹à¤¾à¤‡à¤¸ अभिजà¥à¤žà¤¾à¤ªà¤• जाणून घà¥à¤¯à¤¾</translation>
<translation id="8284769179630993263">Chrome सेटिंगà¥à¤œà¤®à¤§à¥à¤¯à¥‡ तà¥à¤®à¤šà¥‡ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ बà¥à¤°à¤¾à¤‰à¤à¤¿à¤‚ग आणि आणखी बरेच काही वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करा</translation>
@@ -1988,7 +2040,7 @@
<translation id="8533619373899488139">तà¥à¤®à¤šà¥à¤¯à¤¾ सिसà¥à¤Ÿà¤® अâ€à¥…डमिनिसà¥à¤Ÿà¥à¤°à¥‡à¤Ÿà¤°à¤¦à¥à¤µà¤¾à¤°à¥‡ बà¥à¤²à¥‰à¤• केलेलà¥à¤¯à¤¾ URL आणि लागू केलेली इतर धोरणे पाहणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ &lt;strong&gt;chrome://policy&lt;/strong&gt; ला भेट दà¥à¤¯à¤¾.</translation>
<translation id="8541158209346794904">बà¥à¤²à¥‚टूथ डिवà¥â€à¤¹à¤¾à¤‡à¤¸</translation>
<translation id="8542014550340843547">टà¥à¤°à¤¿à¤ªà¤² सà¥à¤Ÿà¥‡à¤ªà¤² बॉटम</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="8543181531796978784">तà¥à¤®à¥à¤¹à¥€ <ph name="BEGIN_ERROR_LINK" />ओळखणà¥â€à¤¯à¤¾à¤šà¥à¤¯à¤¾ समसà¥â€à¤¯à¥‡à¤šà¥€ तकà¥à¤°à¤¾à¤°<ph name="END_ERROR_LINK" /> करू शकता किंवा तà¥à¤®à¤šà¥à¤¯à¤¾ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¥‡à¤¸ असणारà¥â€à¤¯à¤¾ जोखमींची पूरà¥à¤£ जाणीव ठेवून <ph name="BEGIN_LINK" />या असà¥à¤°à¤•à¥à¤·à¤¿à¤¤ साइटला भेट दà¥à¤¯à¤¾<ph name="END_LINK" />.</translation>
<translation id="8557066899867184262">CVV तà¥à¤®à¤šà¥à¤¯à¤¾ कारà¥à¤¡à¤¾à¤šà¥à¤¯à¤¾ मागील बाजूस दिलेला असतो.</translation>
<translation id="8558485628462305855">ऑगमेंटेड रीअâ€à¥…लिटी आशय पाहणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€, ARCore अपडेट करा</translation>
<translation id="8559762987265718583">आपलà¥à¤¯à¤¾ डिवà¥à¤¹à¤¾à¤‡à¤¸à¤šà¥€ तारीख आणि वेळ (<ph name="DATE_AND_TIME" />) चà¥à¤•à¥€à¤šà¥€ असलà¥à¤¯à¤¾à¤¨à¥‡ <ph name="BEGIN_BOLD" /><ph name="DOMAIN" /><ph name="END_BOLD" /> सह खाजगी कनेकà¥à¤¶à¤¨ इंसà¥à¤Ÿà¥‰à¤² केले जाऊ शकले नाही.</translation>
@@ -2036,7 +2088,6 @@
<translation id="8719528812645237045">मलà¥à¤Ÿà¤¿à¤ªà¤² पंच बॉटम</translation>
<translation id="8725066075913043281">पà¥à¤¨à¥à¤¹à¤¾ पà¥à¤°à¤¯à¤¤à¥à¤¨ करा</translation>
<translation id="8726549941689275341">पेजचा आकार:</translation>
-<translation id="8728672262656704056">तà¥à¤®à¥à¤¹à¥€ गà¥à¤ªà¥à¤¤ मोडमधà¥à¤¯à¥‡ आहात</translation>
<translation id="8730621377337864115">पूरà¥à¤£ à¤à¤¾à¤²à¥‡</translation>
<translation id="8731544501227493793">पासवरà¥à¤¡ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करा बटण, पाहणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ Enter दाबा आणि Chrome सेटिंगà¥à¤œà¤®à¤§à¥à¤¯à¥‡ तà¥à¤®à¤šà¥‡ पासवरà¥à¤¡ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ करा</translation>
<translation id="8734529307927223492">तà¥à¤®à¤šà¥‡ <ph name="DEVICE_TYPE" /> <ph name="MANAGER" /> दà¥à¤µà¤¾à¤°à¥‡ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ केले आहे</translation>
@@ -2113,6 +2164,7 @@
<translation id="9020542370529661692">हे पृषà¥à¤  <ph name="TARGET_LANGUAGE" /> मधà¥à¤¯à¥‡ भाषांतरित केले गेले आहे.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(चà¥à¤•à¥€à¤šà¥‡)</translation>
+<translation id="9030265603405983977">मोनोकà¥à¤°à¥‹à¤®</translation>
<translation id="9035022520814077154">सà¥à¤°à¤•à¥à¤·à¤¿à¤¤à¤¤à¤¾ à¤à¤°à¤°</translation>
<translation id="9038649477754266430">पेज अधिक जलदपणे लोड करणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ पूरà¥à¤µà¤¾à¤¨à¥à¤®à¤¾à¤¨ सेवेचा वापर करा</translation>
<translation id="9039213469156557790">पà¥à¤¢à¥‡, या पृषà¥à¤ à¤¾à¤¤ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नसलेली इतर संसाधने समाविषà¥à¤Ÿ आहेत. ही संसाधने संकà¥à¤°à¤®à¤£à¤¾à¤¤ असताना इतरांदà¥à¤µà¤¾à¤°à¥‡ पाहिली जाऊ शकतात आणि पृषà¥à¤ à¤¾à¤šà¥‡ वरà¥à¤¤à¤¨ बदलणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¥à¤¯à¤¾à¤¦à¥à¤µà¤¾à¤°à¥‡ सà¥à¤§à¤¾à¤°à¤¿à¤¤ केली जाऊ शकतात.</translation>
@@ -2136,6 +2188,7 @@
<translation id="91108059142052966">गोपनीय आशय दृशà¥à¤¯à¤®à¤¾à¤¨ असेल तेवà¥à¤¹à¤¾ अâ€à¥…डमिनिसà¥à¤Ÿà¥à¤°à¥‡à¤Ÿà¤° धोरण हे <ph name="APPLICATION_TITLE" /> सोबत सà¥à¤•à¥à¤°à¥€à¤¨ शेअरिंग बंद करते</translation>
<translation id="9114524666733003316">कारà¥à¤¡à¤šà¥€ निशà¥à¤šà¤¿à¤¤à¥€ करत आहे...</translation>
<translation id="9114581008513152754">हा बà¥à¤°à¤¾à¤‰à¤à¤° कंपनी किंवा इतर संसà¥à¤¥à¥‡à¤¦à¥à¤µà¤¾à¤°à¥‡ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ केला जात नाही. या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤µà¤°à¥€à¤² अâ€à¥…कà¥à¤Ÿà¤¿à¤µà¥à¤¹à¤¿à¤Ÿà¥€ Chrome चà¥à¤¯à¤¾ बाहेर वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¿à¤¤ केलेली असू शकते. <ph name="BEGIN_LINK" />अधिक जाणून घà¥à¤¯à¤¾<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">नवीन</translation>
<translation id="9119042192571987207">अपलोड केला</translation>
<translation id="9128016270925453879">धोरणे लोड केलेली आहेत</translation>
<translation id="9128870381267983090">नेटवरà¥à¤•à¤¶à¥€ कनेकà¥à¤Ÿ करा</translation>
@@ -2153,7 +2206,8 @@
<translation id="9169931577761441333"><ph name="APP_NAME" /> ला होम सà¥à¤•à¥à¤°à¥€à¤¨à¤µà¤° जोडा</translation>
<translation id="9170848237812810038">&amp;पूरà¥à¤µà¤µà¤¤ करा</translation>
<translation id="9171296965991013597">ॲप सोडायचे?</translation>
-<translation id="9173282814238175921">à¤à¤• दसà¥à¤¤à¤à¤µà¤œ/नवीन पतà¥à¤°à¤•</translation>
+<translation id="9173282814238175921">à¤à¤• दसà¥à¤¤à¤à¤µà¤œ/नवीन शीट</translation>
+<translation id="9173995187295789444">बà¥à¤²à¥‚टूथ डिवà¥à¤¹à¤¾à¤‡à¤¸à¤¸à¤¾à¤ à¥€ सà¥à¤•à¥…न करत आहे...</translation>
<translation id="917450738466192189">सरà¥à¤µà¥à¤¹à¤°à¤šà¥‡ सरà¥à¤Ÿà¤¿à¤«à¤¿à¤•à¥‡à¤Ÿ चà¥à¤•à¥€à¤šà¥‡ आहे.</translation>
<translation id="9174917557437862841">टॅब सà¥à¤µà¤¿à¤š बटण, या टॅबवर जाणà¥à¤¯à¤¾à¤¸à¤¾à¤ à¥€ à¤à¤‚टर दाबा</translation>
<translation id="9179703756951298733">Chrome सेटिंगà¥à¤œà¤®à¤§à¥à¤¯à¥‡ तà¥à¤®à¤šà¥€ पेमेंट आणि कà¥à¤°à¥‡à¤¡à¤¿à¤Ÿ कारà¥à¤¡ यांची माहिती वà¥â€à¤¯à¤µà¤¸à¥â€à¤¥à¤¾à¤ªà¤¿à¤¤ करा</translation>
diff --git a/chromium/components/strings/components_strings_ms.xtb b/chromium/components/strings/components_strings_ms.xtb
index fe55c68c055..409fa4f0592 100644
--- a/chromium/components/strings/components_strings_ms.xtb
+++ b/chromium/components/strings/components_strings_ms.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Jika ditandai, Chrome akan menyimpan salinan kad anda pada peranti ini untuk pengisian borang yang lebih cepat.</translation>
<translation id="1110994991967754504">Pilih kebenaran untuk <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Buat asal susun semula</translation>
+<translation id="1123753900084781868">Sari Kata Langsung tidak tersedia sekarang</translation>
<translation id="1125573121925420732">Amaran mungkin biasa dipaparkan semasa tapak web mengemas kini keselamatannya. Ini akan diperbaik tidak lama lagi.</translation>
<translation id="112840717907525620">Cache dasar OK</translation>
<translation id="1130564665089811311">Butang terjemah halaman, tekan Enter untuk menterjemah halaman ini dengan Google Terjemah</translation>
@@ -74,6 +75,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="1240347957665416060">Nama peranti anda</translation>
<translation id="124116460088058876">Lagi bahasa</translation>
<translation id="1243027604378859286">Pengarang:</translation>
+<translation id="1246424317317450637">Huruf tebal</translation>
<translation id="1250759482327835220">Untuk membayar dengan lebih cepat selepas ini, simpan kad, nama dan alamat pengebilan anda ke Akaun Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (disegerakkan)</translation>
<translation id="1256368399071562588">&lt;p&gt;Jika anda cuba melawati tapak web tetapi tapak itu tidak dibuka, cuba selesaikan ralat tersebut dengan langkah penyelesaian masalah berikut terlebih dahulu:&lt;/p&gt;
@@ -156,6 +158,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="1476595624592550506">Tukar kata laluan anda</translation>
<translation id="1484290072879560759">Pilih Alamat Pengiriman</translation>
<translation id="1492194039220927094">Penolakan dasar:</translation>
+<translation id="1495677929897281669">Kembali ke tab</translation>
<translation id="1501859676467574491">Tunjukkan kad daripada Akaun Google anda</translation>
<translation id="1507202001669085618">&lt;p&gt;Anda akan melihat ralat ini jika menggunakan portal Wi-Fi yang menghendaki anda untuk log masuk sebelum boleh masuk dalam talian.&lt;/p&gt;
&lt;p&gt;Untuk membetulkan ralat itu, klik &lt;strong&gt;Sambung&lt;/strong&gt; pada halaman yang cuba dibuka.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="1532118530259321453">Halaman ini menyatakan</translation>
<translation id="153384715582417236">Itu sahaja buat masa ini</translation>
<translation id="1536390784834419204">Terjemahkan halaman</translation>
+<translation id="1539840569003678498">Laporan dihantar:</translation>
<translation id="154408704832528245">Pilih Alamat Penghantaran</translation>
<translation id="1549470594296187301">JavaScript mesti didayakan untuk menggunakan ciri ini.</translation>
<translation id="155039086686388498">Kejuruteraan-D</translation>
@@ -213,16 +217,19 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="1682696192498422849">Sisi pendek dahulu</translation>
<translation id="168693727862418163">Nilai dasar ini gagal disahkan dengan skemanya dan akan diabaikan.</translation>
<translation id="168841957122794586">Sijil pelayan mengandungi kunci kriptografi yang lemah.</translation>
+<translation id="1696290444144917273">Lihat butiran kad maya</translation>
<translation id="1697532407822776718">Anda telah bersedia!</translation>
<translation id="1703835215927279855">Surat</translation>
<translation id="1706954506755087368">{1,plural, =1{Pelayan ini tidak dapat membuktikan bahawa itu <ph name="DOMAIN" />;sijil keselamatannya sepatutnya bermula esok. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang yang memintas sambungan anda.}other{Pelayan ini tidak dapat membuktikan bahawa itu <ph name="DOMAIN" />; sijil keselamatannya sepatutnya bermula # hari lagi. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang yang memintas sambungan anda.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Diabaikan kerana <ph name="POLICY_NAME" /> tidak ditetapkan kepada <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> mahu menyimpan data pada komputer setempat anda secara kekal</translation>
<translation id="1713628304598226412">Dulang 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Peti mel 3</translation>
<translation id="1718029547804390981">Dokumen terlalu besar untuk dianotasikan</translation>
<translation id="1721424275792716183">* Medan perlu diisi</translation>
+<translation id="1727613060316725209">Sijil sah</translation>
<translation id="1727741090716970331">Tambahkan Nombor Kad yang Sah</translation>
<translation id="1728677426644403582">Anda sedang melihat sumber halaman web</translation>
<translation id="173080396488393970">Jenis kad ini tidak disokong</translation>
@@ -246,7 +253,6 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
permintaan anda untuk <ph name="SITE" />. Dasar asal boleh digunakan oleh
pengendali tapak untuk mengkonfigurasi keselamatan dan sifat lain bagi tapak.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Sila kemas kini frasa laluan segerak anda.</translation>
<translation id="1787142507584202372">Tab yang dibuka dipaparkan di sini</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, pelbagai tindakan tersedia, tekan Tab untuk pergi ke setiap tindakan</translation>
@@ -279,6 +285,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="1919345977826869612">Iklan</translation>
<translation id="1919367280705858090">Dapatkan bantuan berkaitan mesej ralat tertentu</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Tiada}=1{1 tapak}other{# tapak}}</translation>
+<translation id="1924727005275031552">Baharu</translation>
<translation id="1945968466830820669">Anda boleh kehilangan akses kepada akaun organisasi anda atau mengalami kecurian identiti. Chromium mengesyorkan supaya kata laluan anda ditukar sekarang.</translation>
<translation id="1947454675006758438">Kokot atas sebelah kanan</translation>
<translation id="1958218078413065209">Markah tertinggi anda ialah <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="2042213636306070719">Dulang 7</translation>
<translation id="204357726431741734">Log masuk untuk menggunakan kata laluan yang disimpan dalam Akaun Google anda</translation>
<translation id="2053111141626950936">Halaman dalam <ph name="LANGUAGE" /> tidak akan diterjemah.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Apabila kawalan ini dihidupkan dan status adalah aktif, Chrome akan menentukan kumpulan besar orang, atau "kohort" yang paling serupa dengan aktiviti penyemakan imbas anda baru-baru ini. Pengiklan boleh memilih iklan untuk kumpulan itu dan aktiviti penyemakan imbas anda dipastikan tertutup pada peranti anda. Kumpulan anda dikemas kini setiap hari.}=1{Apabila kawalan ini dihidupkan dan status adalah aktif, Chrome akan menentukan kumpulan besar orang, atau "kohort" yang paling serupa dengan aktiviti penyemakan imbas anda baru-baru ini. Pengiklan boleh memilih iklan untuk kumpulan itu dan aktiviti penyemakan imbas anda dipastikan tertutup pada peranti anda. Kumpulan anda dikemas kini setiap hari.}other{Apabila kawalan ini dihidupkan dan status adalah aktif, Chrome akan menentukan kumpulan besar orang, atau "kohort" yang paling serupa dengan aktiviti penyemakan imbas anda baru-baru ini. Pengiklan boleh memilih iklan untuk kumpulan itu dan aktiviti penyemakan imbas anda dipastikan tertutup pada peranti anda. Kumpulan anda dikemas kini setiap {NUM_DAYS} hari.}}</translation>
<translation id="2053553514270667976">Poskod</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 cadangan}other{# cadangan}}</translation>
<translation id="2071692954027939183">Pemberitahuan disekat secara automatik kerana biasanya anda tidak membenarkan pemberitahuan</translation>
<translation id="2079545284768500474">Buat asal</translation>
<translation id="20817612488360358">Tetapan proksi sistem telah sedia untuk digunakan tetapi konfigurasi proksi jelas juga telah ditentukan.</translation>
<translation id="2082238445998314030">Hasil carian <ph name="RESULT_NUMBER" /> daripada <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Simpan…</translation>
<translation id="2088086323192747268">Butang urus penyegerakan, tekan Enter untuk mengurus maklumat yang anda segerakkan dalam tetapan Chrome</translation>
<translation id="2091887806945687916">Bunyi</translation>
<translation id="2094505752054353250">Domain tidak padan</translation>
@@ -379,6 +388,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="2317259163369394535"><ph name="DOMAIN" /> memerlukan nama pengguna dan kata laluan.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, tamat tempoh pada <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Tetapan dikawal oleh pentadbir anda</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> mahu digandingkan</translation>
<translation id="2344028582131185878">Muat Turun Automatik</translation>
<translation id="2346319942568447007">Imej yang anda salin</translation>
<translation id="2354001756790975382">Penanda halaman lain</translation>
@@ -386,8 +396,10 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="2355395290879513365">Penyerang mungkin dapat melihat imej yang anda lihat di tapak ini dan menipu anda dengan mengubah suainya.</translation>
<translation id="2356070529366658676">Tanya</translation>
<translation id="2357481397660644965">Peranti anda diurus oleh <ph name="DEVICE_MANAGER" /> dan akaun anda diurus oleh <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Dalam masa kurang daripada sehari}=1{Dalam masa sehari}other{Dalam masa {NUM_DAYS} hari}}</translation>
<translation id="2359629602545592467">Berbilang</translation>
<translation id="2359808026110333948">Teruskan</translation>
+<translation id="2359961752320758691">Nombor kad maya anda digunakan.</translation>
<translation id="2367567093518048410">Tahap</translation>
<translation id="2372464001869762664">Selepas anda membuat pengesahan, butiran kad daripada Akaun Google anda akan dikongsi dengan laman ini. Cari nombor CVC dalam butiran Akaun Plex anda.</translation>
<translation id="2380886658946992094">Perundangan</translation>
@@ -398,6 +410,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="239429038616798445">Kaedah penghantaran ini tidak tersedia. Cuba kaedah lain.</translation>
<translation id="2396249848217231973">&amp;Buat asal pemadaman</translation>
<translation id="2410754574180102685">Kerajaan-Perundangan</translation>
+<translation id="2413155254802890957">Lama</translation>
<translation id="2413528052993050574">Pelayan ini tidak dapat membuktikan bahawa domainnya ialah <ph name="DOMAIN" />; sijil keselamatannya mungkin dibatalkan. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang yang memintasi sambungan anda.</translation>
<translation id="2414886740292270097">Gelap</translation>
<translation id="2438874542388153331">Empat tebukan kanan</translation>
@@ -425,10 +438,10 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="2521385132275182522">Kokot bawah sebelah kanan</translation>
<translation id="2523886232349826891">Disimpan pada peranti ini sahaja</translation>
<translation id="2524461107774643265">Tambahkan Maklumat Lanjut</translation>
-<translation id="2526590354069164005">Desktop</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{dan 1 lagi}other{dan # lagi}}</translation>
<translation id="2536110899380797252">Tambahkan Alamat</translation>
<translation id="2539524384386349900">Kesan</translation>
+<translation id="2541219929084442027">Halaman yang anda lihat dalam tab Inkognito tidak akan kekal dalam sejarah, simpanan kuki atau sejarah carian penyemak imbas anda selepas anda menutup semua tab Inkognito anda. Sebarang fail yang anda muat turun atau penanda halaman yang anda buat akan disimpan.</translation>
<translation id="2544644783021658368">Satu dokumen</translation>
<translation id="254947805923345898">Nilai dasar tidak sah.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> menghantar balasan yang tidak sah.</translation>
@@ -448,6 +461,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="2629325967560697240">Untuk mendapatkan tahap keselamatan tertinggi Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />hidupkan perlindungan dipertingkatkan<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Alamat IP pelayan <ph name="HOST_NAME" /> tidak ditemui.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Tiada peranti yang serasi ditemui.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, tekan Tab kemudian Enter untuk Mengosongkan sejarah penyemakan imbas, kuki, cache dan pelbagai lagi dalam tetapan Chrome</translation>
<translation id="2650446666397867134">Akses ke fail dinafikan</translation>
@@ -494,6 +508,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<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="2807052079800581569">Kedudukan Y imej</translation>
+<translation id="2820957248982571256">Mengimbas…</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>
@@ -501,6 +516,8 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="2850739647070081192">Jemputan (Sampul Surat)</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="2859806420264540918">Tapak ini menyiarkan iklan yang mengganggu atau mengelirukan.</translation>
+<translation id="287596039013813457">Mesra</translation>
+<translation id="2876489322757410363">Meninggalkan mod Inkognito untuk membuat bayaran melalui aplikasi luar. Teruskan?</translation>
<translation id="2878197950673342043">Lipatan poster</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Peletakan tetingkap</translation>
@@ -550,7 +567,6 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="3060227939791841287">C9 (Sampul Surat)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, tekan Tab kemudian Enter untuk menjalankan Semakan Keselamatan dalam tetapan Chrome</translation>
<translation id="3061707000357573562">Perkhidmatan Tampung</translation>
-<translation id="3064966200440839136">Meninggalkan mod inkognito untuk membayar melalui aplikasi luar. Teruskan?</translation>
<translation id="306573536155379004">Permainan dimulakan.</translation>
<translation id="3080254622891793721">Grafik</translation>
<translation id="3086579638707268289">Aktiviti anda di web sedang dipantau</translation>
@@ -573,7 +589,6 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="315504272643575312">Akaun anda diurus oleh <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Pulihkan</translation>
<translation id="3162559335345991374">Wi-Fi yang anda gunakan mungkin memerlukan anda untuk melawat halaman log masuknya.</translation>
-<translation id="3167968892399408617">Halaman yang anda lihat dalam tab inkognito tidak akan kekal dalam sejarah, simpanan kuki atau sejarah carian penyemak imbas anda selepas anda menutup semua tab inkognito anda. Sebarang fail yang anda muat turun atau penanda halaman yang anda buat akan disimpan.</translation>
<translation id="3169472444629675720">Temui</translation>
<translation id="3174168572213147020">Pulau</translation>
<translation id="3176929007561373547">Semak tetapan proksi anda atau hubungi pentadbir rangkaian anda untuk
@@ -599,10 +614,12 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<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="3249845759089040423">Groovy</translation>
<translation id="3252266817569339921">Bahasa Perancis</translation>
<translation id="3266793032086590337">Nilai (konflik)</translation>
<translation id="3268451620468152448">Tab Terbuka</translation>
<translation id="3270847123878663523">&amp;Buat asal Susun semula</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> ingin menyambung</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Organisasi anda, <ph name="ENROLLMENT_DOMAIN" />, telah menghantar beberapa maklumat, seperti tetapan atau dasar ke laman web berikut.</translation>
<translation id="3282497668470633863">Tambahkan nama pada kad</translation>
@@ -655,6 +672,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="3428151540071562330">Satu atau beberapa URI templat pelayan DnsOverHttpsTemplates URI tidak sah dan tidak akan digunakan.</translation>
<translation id="3431636764301398940">Simpan kad ini pada peranti ini</translation>
<translation id="3432601291244612633">Tutup halaman</translation>
+<translation id="3435738964857648380">Keselamatan</translation>
<translation id="3435896845095436175">Dayakan</translation>
<translation id="3438829137925142401">Gunakan kata laluan yang disimpan dalam Akaun Google anda</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="3584299510153766161">Dua tebukan bawah</translation>
<translation id="3586931643579894722">Sembunyikan butiran</translation>
<translation id="3587738293690942763">Tengah</translation>
+<translation id="3590643883886679995">Data log masuk akan disimpan pada peranti ini selepas anda keluar daripada mod Inkognito.</translation>
+<translation id="359126217934908072">Bulan/Tahun:</translation>
<translation id="3592413004129370115">Itali (Sampul Surat)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Anda boleh menetapkan semula kumpulan anda pada bila-bila masa. Proses menyertai kumpulan baharu mengambil masa kira-kira sehari.}=1{Anda boleh menetapkan semula kumpulan anda pada bila-bila masa. Proses menyertai kumpulan baharu mengambil masa kira-kira sehari.}other{Anda boleh menetapkan semula kumpulan anda pada bila-bila masa. Proses menyertai kumpulan baharu mengambil masa kira-kira {NUM_DAYS} hari.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplikasi disekat oleh pentadbir anda</translation>
<translation id="3608932978122581043">Orientasi suapan</translation>
@@ -706,7 +727,6 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="3615877443314183785">Masukkan tarikh tamat tempoh yang sah</translation>
<translation id="36224234498066874">Kosongkan Data Semakan Imbas...</translation>
<translation id="362276910939193118">Paparkan Sejarah Penuh</translation>
-<translation id="3625635938337243871">Data log masuk akan disimpan pada peranti ini selepas anda keluar daripada mod inkognito.</translation>
<translation id="3630155396527302611">Jika apl telah disenaraikan sebagai atur cara yang dibenarkan untuk mengakses
rangkaian, cuba alihkannya keluar daripada senarai dan tambahkannya  
semula.</translation>
@@ -714,6 +734,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="3631244953324577188">Biometrik</translation>
<translation id="3633738897356909127">Butang Kemas Kini Chrome, tekan Enter untuk mengemas kini Chrome daripada tetapan Chrome anda</translation>
<translation id="3634530185120165534">Dulang 5</translation>
+<translation id="3637662659967048211">Simpan pada Akaun Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplikasi:</translation>
<translation id="3650584904733503804">Pengesahan berjaya</translation>
@@ -754,6 +775,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="3781428340399460090">Merah Jambu Hangat</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Peranti Bluetooth</translation>
+<translation id="3787675388804467730">Nombor kad maya</translation>
<translation id="3787705759683870569">Tamat tempoh pada <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Saiz 16</translation>
<translation id="3789841737615482174">Pasang</translation>
@@ -773,6 +795,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="3841184659773414994">Pengendali Fail</translation>
<translation id="385051799172605136">Kembali</translation>
<translation id="3858027520442213535">Kemas kini tarikh dan masa</translation>
+<translation id="3881478300875776315">Tunjukkan kurang baris</translation>
<translation id="3884278016824448484">Pengecam peranti bercanggah</translation>
<translation id="3885155851504623709">Mukim</translation>
<translation id="388632593194507180">Pemantauan Dikesan</translation>
@@ -798,6 +821,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="397105322502079400">Mengira...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> disekat</translation>
<translation id="3973357910713125165">Butang Jalankan Semakan Keselamatan Chrome, tekan Enter untuk menjalankan Semakan Keselamatan dalam tetapan Chrome</translation>
+<translation id="3986705137476756801">Matikan Sari Kata Langsung buat masa ini</translation>
<translation id="3987405730340719549">Chrome telah menentukan bahawa tapak ini mungkin palsu atau merupakan suatu penipuan.
Jika anda percaya amaran ini tersilap ditunjukkan, sila lawati https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -894,13 +918,14 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="4275830172053184480">Mulakan semula peranti anda</translation>
<translation id="4277028893293644418">Tetapkan semula kata laluan</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="4287885627794386150">Layak untuk percubaan tetapi tidak aktif</translation>
<translation id="4297502707443874121">Lakaran kecil untuk halaman <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Kembangkan</translation>
<translation id="4300675098767811073">Berbilang tebukan kanan</translation>
<translation id="4302514097724775343">Ketik dinosaur itu untuk bermain</translation>
<translation id="4302965934281694568">Chou3 (Sampul Surat)</translation>
<translation id="4305666528087210886">Fail anda tidak dapat diakses</translation>
-<translation id="4305817255990598646">Tukar</translation>
+<translation id="4306529830550717874">Simpan alamat?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Sekat (lalai)</translation>
<translation id="4314815835985389558">Urus penyegerakan</translation>
@@ -927,6 +952,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="4377125064752653719">Anda cuba untuk mencapai <ph name="DOMAIN" />, tetapi sijil yang diberi pelayan telah dibatalkan oleh pengeluarnya. Ini bermakna bahawa bukti kelayakan keselamatan yang diberi pelayan sememangnya tidak harus dipercayai. Anda mungkin berkomunikasi dengan penyerang.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Bertepi</translation>
+<translation id="4406883609789734330">Sari Kata Langsung</translation>
<translation id="4406896451731180161">hasil carian</translation>
<translation id="4408413947728134509">Kuki <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Anda baru sahaja memasukkan kata laluan pada tapak yang menipu. Chrome mengesyorkan supaya anda pergi ke <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> serta tapak lain yang anda gunakan kata laluan ini dan menukar kata laluan ini sekarang.</translation>
@@ -939,7 +965,6 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="4435702339979719576">Poskad)</translation>
<translation id="443673843213245140">Penggunaan proksi dilumpuhkan tetapi konfigurasi proksi yang jelas dinyatakan.</translation>
<translation id="4464826014807964867">Laman web yang mempunyai maklumat daripada organisasi anda</translation>
-<translation id="4466881336512663640">Perubahan borang akan hilang. Adakah anda pasti mahu meneruskan?</translation>
<translation id="4476953670630786061">Borang ini tidak selamat. Autolengkap telah dimatikan.</translation>
<translation id="4477350412780666475">Lagu Seterusnya</translation>
<translation id="4482953324121162758">Tapak ini tidak akan diterjemah.</translation>
@@ -973,6 +998,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="4594403342090139922">&amp;Buat asal Pemadaman</translation>
<translation id="4597348597567598915">Saiz 8</translation>
<translation id="4600854749408232102">C6/C5 (Sampul Surat)</translation>
+<translation id="4606870351894164739">Memberi kesan</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Pulangan tunai dipautkan</translation>
<translation id="4636930964841734540">Maklumat</translation>
@@ -992,6 +1018,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="4691835149146451662">Seni Bina-A (Sampul Surat)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Sisi</translation>
+<translation id="4702656508969495934">Sari Kata Langsung dapat dilihat, gunakan penukar tetingkap untuk memfokus</translation>
<translation id="4708268264240856090">Sambungan anda tergendala</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Jalankan Diagnostik Rangkaian Windows<ph name="END_LINK" /></translation>
@@ -1005,6 +1032,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="4738601419177586157">Cadangan carian <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Urus kata laluan…</translation>
<translation id="4744603770635761495">Laluan Boleh Laku</translation>
+<translation id="4749011317274908093">Anda menggunakan mod Inkognito</translation>
<translation id="4750917950439032686">Maklumat anda (contohnya, kata laluan atau nombor kad kredit) adalah berciri peribadi apabila dihantar ke tapak ini.</translation>
<translation id="4756388243121344051">&amp;Sejarah</translation>
<translation id="4758311279753947758">Tambahkan maklumat hubungan</translation>
@@ -1034,6 +1062,8 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="4813512666221746211">Ralat rangkaian</translation>
<translation id="4816492930507672669">Muat halaman</translation>
<translation id="4819347708020428563">Edit anotasi dalam paparan lalai?</translation>
+<translation id="4825507807291741242">Berkuasa</translation>
+<translation id="4838327282952368871">Berangan</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">Lihat</translation>
<translation id="485316830061041779">Bahasa Jerman</translation>
@@ -1170,6 +1200,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="5314967030527622926">Pembuat buku kecil</translation>
<translation id="5316812925700871227">Putar lawan arah jam</translation>
<translation id="5317780077021120954">Simpan</translation>
+<translation id="5321288445143113935">Dimaksimumkan</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> daripada <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Pilih Maklumat Hubungan</translation>
<translation id="5327248766486351172">Nama</translation>
@@ -1177,11 +1208,13 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="5332219387342487447">Kaedah Penghantaran</translation>
<translation id="5333022057423422993">Chrome menemukan kata laluan yang baru sahaja anda gunakan dalam pelanggaran data. Untuk melindungi akaun anda, kami mengesyorkan agar anda menyemak kata laluan anda yang disimpan.</translation>
<translation id="5334013548165032829">Log sistem terperinci</translation>
+<translation id="5334145288572353250">Simpan Alamat?</translation>
<translation id="5340250774223869109">Aplikasi disekat</translation>
<translation id="534295439873310000">Peranti NFC</translation>
<translation id="5344579389779391559">Halaman ini mungkin cuba mengenakan bayaran kepada anda</translation>
<translation id="5355557959165512791">Anda tidak boleh melawati <ph name="SITE" /> sekarang kerana sijil tapak ini telah ditarik balik. Ralat dan serangan rangkaian biasanya bersifat sementara. Oleh sebab itu, halaman ini mungkin akan berfungsi semula kemudian.</translation>
<translation id="536296301121032821">Gagal menyimpan tetapan dasar</translation>
+<translation id="5363309033720083897">Port bersiri yang dibenarkan oleh pentadbir anda</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="5386426401304769735">Rantaian sijil untuk tapak ini mengandungi sijil yang ditandatangani menggunakan SHA-1.</translation>
@@ -1190,6 +1223,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="5398772614898833570">Iklan disekat</translation>
<translation id="5400836586163650660">Kelabu</translation>
<translation id="540969355065856584">Pelayan ini tidak dapat membuktikan bahawa pelayan adalah <ph name="DOMAIN" />; sijil keselamatan pelayan tidak sah pada masa ini. Ini mungkin disebabkan oleh kesilapan konfigurasi atau penyerang memintas sambungan anda.</translation>
+<translation id="541143247543991491">Awan (seluruh sistem)</translation>
<translation id="541416427766103491">Petak 4</translation>
<translation id="5421136146218899937">Kosongkan data semakan imbas...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> mahu menghantar pemberitahuan kepada anda</translation>
@@ -1203,6 +1237,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="5455374756549232013">Cap waktu dasar tidak elok</translation>
<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="5463625433003343978">Mencari peranti...</translation>
<translation id="5469868506864199649">Bahasa Itali</translation>
<translation id="5470861586879999274">&amp;Buat semula edit</translation>
<translation id="5478437291406423475">B6/C4 (Sampul Surat)</translation>
@@ -1252,7 +1287,6 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="5624120631404540903">Urus kata laluan</translation>
<translation id="5629630648637658800">Gagal memuatkan tetapan dasar</translation>
<translation id="5631439013527180824">Token pengurusan peranti tidak sah</translation>
-<translation id="5632627355679805402">Data anda disulitkan dengan <ph name="BEGIN_LINK" />kata laluan Google<ph name="END_LINK" /> anda pada <ph name="TIME" />. Masukkan kata laluan itu untuk memulakan penyegerakan.</translation>
<translation id="5633066919399395251">Penyerang yang sedang berada di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mungkin cuba memasang atur cara berbahaya pada komputer anda. Atur cara tersebut boleh mencuri atau memadamkan maklumat anda (contohnya, foto, kata laluan, mesej dan kad kredit). <ph name="BEGIN_LEARN_MORE_LINK" />Ketahui lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Kandungan mengelirukan disekat.</translation>
<translation id="5644090287519800334">Anjakan X sisi 1 imej</translation>
@@ -1291,12 +1325,12 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="5785756445106461925">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 penampilan halaman.</translation>
<translation id="5786044859038896871">Adakah anda ingin mengisi maklumat kad anda?</translation>
<translation id="578633867165174378">Chrome menemukan kata laluan yang baru sahaja anda gunakan dalam pelanggaran data. Chrome mengesyorkan agar anda menukar kata laluan ini sekarang.</translation>
-<translation id="5798290721819630480">Buang perubahan?</translation>
<translation id="5803412860119678065">Adakah anda ingin mengisi <ph name="CARD_DETAIL" /> anda?</translation>
<translation id="5804241973901381774">Kebenaran</translation>
<translation id="5804427196348435412">Gunakan peranti NFC</translation>
<translation id="5810442152076338065">Sambungan anda ke <ph name="DOMAIN" /> disulitkan menggunakan suit sifer yang sudah usang.</translation>
<translation id="5813119285467412249">&amp;Buat Semula Tambahkan</translation>
+<translation id="5817918615728894473">Gandingkan</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Kad ini akan dikenakan bayaran apabila anda membuat pembayaran, tetapi nombor sebenar kad tidak akan dikongsi dengan tapak ini. Untuk mendapatkan keselamatan tambahan, CVC sementara akan dijana.}other{Kad yang anda pilih akan dikenakan bayaran apabila anda membuat pembayaran, tetapi nombor sebenar kad tidak akan dikongsi dengan tapak ini. Untuk mendapatkan keselamatan tambahan, CVC sementara akan dijana.}}</translation>
<translation id="5826507051599432481">Nama Biasa (CN)</translation>
<translation id="5838278095973806738">Anda tidak seharusnya memasukkan sebarang maklumat sensitif pada tapak ini (contohnya, kata laluan atau maklumat kad kredit) kerana maklumat ini boleh dicuri oleh penyerang.</translation>
@@ -1304,6 +1338,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="5855253129151731373">Nama hos tapak ini kelihatan serupa dengan <ph name="LOOKALIKE_DOMAIN" />. Kadangkala penyerang meniru tapak dengan membuat perubahan kecil yang sukar dilihat pada nama domain.
Jika anda percaya amaran ini tersilap ditunjukkan, sila lawati https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Dimatikan</translation>
<translation id="5862579898803147654">Petak 8</translation>
<translation id="5863847714970149516">Halaman yang seterusnya mungkin cuba mengenakan bayaran kepada anda</translation>
<translation id="5866257070973731571">Tambahkan Nombor Telefon</translation>
@@ -1320,6 +1355,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="5913377024445952699">Tangkapan skrin dijeda</translation>
<translation id="59174027418879706">Didayakan</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 sedang digunakan}other{# sedang digunakan}}</translation>
<translation id="5921185718311485855">Hidup</translation>
<translation id="5921639886840618607">Simpan kad ke Akaun Google?</translation>
<translation id="5922853866070715753">Hampir selesai</translation>
@@ -1339,6 +1375,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="5989320800837274978">Pelayan proksi tetap begitu juga URL skrip .pac, kedua-duanya tidak ditetapkan.</translation>
<translation id="5992691462791905444">Lipatan Z kejuruteraan</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> hasil carian untuk '<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">Klasik</translation>
<translation id="6008122969617370890">Susunan N-ke-1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Semak kata laluan anda</translation>
@@ -1360,6 +1397,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="6045164183059402045">Templat pengenaan</translation>
<translation id="6047233362582046994">Jika anda memahami risiko terhadap keselamatan anda, anda boleh <ph name="BEGIN_LINK" />melawat tapak ini<ph name="END_LINK" /> sebelum program yang berbahaya ini dialih keluar.</translation>
<translation id="6047927260846328439">Kandungan ini mungkin menggunakan tipu muslihat supaya anda memasang perisian atau mendedahkan maklumat peribadi. <ph name="BEGIN_LINK" />Tunjukkan juga<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Tekan dan tahan |<ph name="ACCELERATOR" />| untuk keluar daripada skrin penuh</translation>
<translation id="6049488691372270142">Penghantaran halaman</translation>
<translation id="6051221802930200923">Anda tidak boleh melawati <ph name="SITE" /> sekarang kerana tapak web ini menggunakan penyematan sijil. Ralat dan serangan rangkaian biasanya bersifat sementara. Oleh sebab itu, halaman ini mungkin akan berfungsi semula kemudian.</translation>
<translation id="6051898664905071243">Kiraan halaman:</translation>
@@ -1376,6 +1414,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<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>
<translation id="6116338172782435947">Lihat teks dan imej yang disalin ke papan keratan</translation>
<translation id="6120179357481664955">Ingat ID UPI anda?</translation>
+<translation id="6123290840358279103">Lihat kad maya</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Periksa mana-mana kabel dan but semula mana-mana penghala, modem atau peranti
rangkaian lain yang mungkin anda gunakan.</translation>
@@ -1412,6 +1451,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="6289939620939689042">Warna Halaman</translation>
<translation id="6290238015253830360">Artikel cadangan anda dipaparkan di sini</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google Assistant dalam Chrome berhenti</translation>
<translation id="6305205051461490394"><ph name="URL" /> tidak dapat dicapai.</translation>
<translation id="6312113039770857350">Halaman web tidak tersedia</translation>
@@ -1437,6 +1477,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="6390200185239044127">Lipat dua Z</translation>
<translation id="6390662030813198813">Kejuruteraan-E</translation>
<translation id="6393956493820063117">Penampalan daripada <ph name="ORIGIN_NAME" /> pada lokasi ini disekat oleh dasar pentadbir</translation>
+<translation id="6398765197997659313">Keluar daripada skrin penuh</translation>
<translation id="6401136357288658127">Dasar ini telah ditamatkan. Anda harus menggunakan dasar <ph name="NEW_POLICY" /> sebagai ganti.</translation>
<translation id="6404511346730675251">Edit penanda halaman</translation>
<translation id="6406765186087300643">C0 (Sampul Surat)</translation>
@@ -1449,7 +1490,6 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="6428450836711225518">Sahkan nombor telefon anda</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="6440503408713884761">Diabaikan</translation>
<translation id="6443406338865242315">Sambungan dan pemalam yang telah anda pasang</translation>
<translation id="6446163441502663861">Kahu (Sampul Surat)</translation>
@@ -1492,6 +1532,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="6624427990725312378">Maklumat Hubungan</translation>
<translation id="6626291197371920147">Tambahkan nombor kad yang sah</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Carian</translation>
+<translation id="6630043285902923878">Mencari peranti USB...</translation>
<translation id="6630809736994426279">Penyerang yang sedang berada di <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mungkin cuba memasang atur cara berbahaya pada komputer Mac anda. Atur cara tersebut boleh mencuri atau memadamkan maklumat anda (contohnya, foto, kata laluan, mesej dan kad kredit). <ph name="BEGIN_LEARN_MORE_LINK" />Ketahui lebih lanjut<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Kosongkan</translation>
@@ -1507,6 +1548,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="6671697161687535275">Alih keluar cadangan borang daripada Chromium?</translation>
<translation id="6685834062052613830">Log keluar dan selesaikan persediaan</translation>
<translation id="6687335167692595844">Saiz fon diminta</translation>
+<translation id="6688743156324860098">Kemas kini…</translation>
<translation id="6689249931105087298">Relatif dengan mampatan mata hitam</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="6698381487523150993">Dicipta:</translation>
@@ -1522,6 +1564,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="6744009308914054259">Sementara menunggu sambungan, anda boleh melawati Muat turun untuk membaca artikel luar talian.</translation>
<translation id="6753269504797312559">Nilai dasar</translation>
<translation id="6757797048963528358">Peranti anda tidak aktif.</translation>
+<translation id="6767985426384634228">Kemas Kini Alamat?</translation>
<translation id="6768213884286397650">Hagaki (Poskad)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Ungu Lembayung</translation>
@@ -1544,6 +1587,7 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome meringkaskan halaman ini untuk memudahkan pembacaan. Chrome mengambil halaman asal melalui sambungan tidak selamat.</translation>
<translation id="6891596781022320156">Tahap dasar tidak disokong.</translation>
+<translation id="6895143722905299846">Nombor maya:</translation>
<translation id="6895330447102777224">Kad anda telah disahkan</translation>
<translation id="6897140037006041989">Ejen Pengguna</translation>
<translation id="6898699227549475383">Organisasi (O)</translation>
@@ -1579,10 +1623,10 @@ Jika tidak, ini akan disekat oleh tetapan privasi anda. Kebenaran ini akan membo
<translation id="7004583254764674281">Gunakan Windows Hello untuk mengesahkan kad dengan lebih cepat</translation>
<translation id="7006930604109697472">Hantar sahaja</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Tetapan Pengubahan Saiz</translation>
<translation id="7014741021609395734">Tahap zum</translation>
<translation id="7016992613359344582">Caj ini mungkin caj sekali atau caj berulang dan mungkin tidak ketara.</translation>
<translation id="7029809446516969842">Kata laluan</translation>
+<translation id="7030436163253143341">Sijil tidak sah</translation>
<translation id="7031646650991750659">Apl Google Play yang telah anda pasang</translation>
<translation id="7050187094878475250">Anda cuba untuk mencapai <ph name="DOMAIN" />, tetapi pelayan memberikan sijil yang tempoh sahnya terlalu panjang untuk boleh dipercayai.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Kad ini tidak dapat disimpan sekarang}other{Kad ini tidak dapat disimpan sekarang}}</translation>
@@ -1652,12 +1696,14 @@ Butiran tambahan:
<translation id="7300012071106347854">Biru Kobalt</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Tinggi</translation>
+<translation id="7305756307268530424">Mulakan lebih perlahan</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Bantuan Sambungan</translation>
<translation id="7323804146520582233">Sembunyikan bahagian "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Pembatalan akaun setempat peranti</translation>
<translation id="7333654844024768166">Anda baru sahaja memasukkan kata laluan pada tapak yang menipu. Chromium mengesyorkan supaya anda pergi ke <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> serta tapak lain yang anda gunakan kata laluan ini dan menukar kata laluan ini sekarang.</translation>
<translation id="7334320624316649418">&amp;Buat semula susun semula</translation>
+<translation id="7337248890521463931">Tunjukkan lagi baris</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>
@@ -1665,6 +1711,7 @@ Butiran tambahan:
<translation id="7349430561505560861">A4-Ekstra</translation>
<translation id="7353601530677266744">Baris Perintah</translation>
<translation id="7359588939039777303">Iklan disekat.</translation>
+<translation id="7363096869660964304">Walau bagaimanapun, anda tidak halimunan. Apabila anda menggunakan mod Inkognito, penyemakan imbas anda tidak akan disembunyikan daripada majikan anda, penyedia perkhidmatan Internet anda atau laman web yang anda lawati.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, tekan Tab kemudian Enter untuk menambah dan mengurus alamat dalam tetapan Chrome</translation>
<translation id="7365849542400970216">Tahu penggunaan peranti anda?</translation>
<translation id="7372973238305370288">hasil carian</translation>
@@ -1675,7 +1722,9 @@ Butiran tambahan:
<translation id="7378594059915113390">Kawalan Media</translation>
<translation id="7378627244592794276">Tidak</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Tidak berkenaan</translation>
<translation id="7390545607259442187">Sahkan Kad</translation>
+<translation id="7392089738299859607">Kemas Kini Alamat</translation>
<translation id="7399802613464275309">Semakan Keselamatan</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> anda diurus</translation>
@@ -1690,6 +1739,7 @@ Butiran tambahan:
&lt;li&gt;Lawati &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Pusat bantuan Chrome&lt;/a&gt; untuk mengetahui cara mengalih keluar perisian itu daripada komputer anda secara kekal
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Format-Lebar</translation>
+<translation id="7410471291937727359">Comel</translation>
<translation id="7416351320495623771">Urus Kata Laluan…</translation>
<translation id="7419106976560586862">Laluan Profil</translation>
<translation id="7437289804838430631">Tambahkan Maklumat Hubungan</translation>
@@ -1705,7 +1755,7 @@ Butiran tambahan:
<translation id="7481312909269577407">Majukan</translation>
<translation id="7485870689360869515">Tiada data dijumpai.</translation>
<translation id="7495528107193238112">Kandungan ini disekat. Hubungi pemilik tapak untuk menyelesaikan isu ini.</translation>
-<translation id="7498234416455752244">Teruskan mengedit</translation>
+<translation id="7498193950643227031">Apl mungkin menunjukkan gelagat yang tidak dijangka jika diubah saiz. Kini anda boleh mengehadkan keupayaan untuk mengubah saiz apl dalam <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Anda baru sahaja memasukkan kata laluan pada tapak yang menipu. Chromium mengesyorkan penyemakan kata laluan anda yang disimpan untuk <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> dan tapak lain yang menggunakan kata laluan ini sekarang.</translation>
<translation id="7508255263130623398">Id peranti yang dikembalikan kosong atau tidak sepadan dengan id peranti semasa</translation>
<translation id="7508870219247277067">Hijau Avokado</translation>
@@ -1725,6 +1775,7 @@ Butiran tambahan:
<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="755279583747225797">Percubaan aktif</translation>
<translation id="7552846755917812628">Cuba petua berikut:</translation>
<translation id="7554475479213504905">Muatkan semula dan tunjukkan juga</translation>
<translation id="7554791636758816595">Tab Baharu</translation>
@@ -1743,7 +1794,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, tekan Tab kemudian Enter untuk melihat dan mengurus kata laluan anda dalam tetapan Chrome</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="7616645509853975347">Pentadbir anda telah menghidupkan Chrome Enterprise Connectors pada penyemak imbas anda. Penyambung ini boleh mengakses sesetengah data anda.</translation>
<translation id="7619838219691048931">Helaian akhir</translation>
<translation id="762844065391966283">Satu demi satu</translation>
@@ -1808,13 +1858,12 @@ Butiran tambahan:
<translation id="782886543891417279">Wi-Fi yang anda gunakan (<ph name="WIFI_NAME" />) mungkin memerlukan anda melawat halaman log masuknya.</translation>
<translation id="7836231406687464395">Postfix (Sampul Surat)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Tiada}=1{1 apl (<ph name="EXAMPLE_APP_1" />)}=2{2 apl (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# apl (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Walau bagaimanapun, anda tidak halimunan. Apabila anda menggunakan mod inkognito, penyemakan imbas anda tidak akan disembunyikan daripada majikan anda, penyedia perkhidmatan Internet anda atau tapak web yang anda lawati.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Membuka fail dengan perkaitan jenis fail.</translation>
<translation id="7862185352068345852">Tinggalkan tapak?</translation>
<translation id="7865448901209910068">Kelajuan terbaik</translation>
<translation id="7874263914261512992">Anda baru sahaja memasukkan kata laluan pada tapak yang menipu. Chrome mengesyorkan penyemakan kata laluan anda yang disimpan untuk <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> dan tapak lain yang menggunakan kata laluan ini sekarang.</translation>
<translation id="7878562273885520351">Kata laluan anda mungkin terjejas</translation>
+<translation id="7880146494886811634">Simpan Alamat</translation>
<translation id="7882421473871500483">Coklat</translation>
<translation id="7887683347370398519">Semak CVC anda dan cuba lagi</translation>
<translation id="7887885240995164102">Akses mod gambar dalam gambar</translation>
@@ -1822,6 +1871,7 @@ Butiran tambahan:
<translation id="7894280532028510793">Jika ejaan sudah betul, <ph name="BEGIN_LINK" />cuba jalankan Diagnostik Rangkaian<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Sampul Surat)</translation>
<translation id="7931318309563332511">Tidak diketahui</translation>
+<translation id="793209273132572360">Kemas kini alamat?</translation>
<translation id="7932579305932748336">Kot</translation>
<translation id="79338296614623784">Masukkan nombor telefon yang sah</translation>
<translation id="7934052535022478634">Pembayaran selesai</translation>
@@ -1892,6 +1942,7 @@ Butiran tambahan:
<translation id="8175796834047840627">Chrome menawarkan penyimpanan kad dalam Akaun Google anda kerana anda log masuk. Anda boleh menukar gelagat ini dalam tetapan.</translation>
<translation id="8176440868214972690">Pentadbir peranti ini telah menghantar beberapa maklumat, seperti tetapan atau dasar ke laman web berikut.</translation>
<translation id="8184538546369750125">Gunakan lalai global (Benarkan)</translation>
+<translation id="8193086767630290324">Tindakan yang diambil dengan data yang dibenderakan sebagai sulit</translation>
<translation id="8194797478851900357">&amp;Buat Asal Pindahkan</translation>
<translation id="8201077131113104583">URL kemas kini tidak sah untuk sambungan dengan ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Ringkasan pesanan</translation>
@@ -1914,6 +1965,7 @@ Butiran tambahan:
<translation id="8249296373107784235">Henti paksa</translation>
<translation id="8249320324621329438">Diambil kali terakhir:</translation>
<translation id="8253091569723639551">Alamat pengebilan diperlukan</translation>
+<translation id="8257387598443225809">Apl ini direka bentuk untuk peranti mudah alih</translation>
<translation id="825929999321470778">Tunjukkan Semua Kata Laluan yang Disimpan</translation>
<translation id="8261506727792406068">Padam</translation>
<translation id="8262952874573525464">Jahitan tepi bawah</translation>
@@ -2038,7 +2090,6 @@ Butiran tambahan:
<translation id="8719528812645237045">Berbilang tebukan atas</translation>
<translation id="8725066075913043281">Cuba lagi</translation>
<translation id="8726549941689275341">Saiz halaman:</translation>
-<translation id="8728672262656704056">Anda menggunakan mod inkognito</translation>
<translation id="8730621377337864115">Selesai</translation>
<translation id="8731544501227493793">Urus butang kata laluan, tekan Enter untuk melihat dan mengurus kata laluan anda dalam tetapan Chrome</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> anda diurus oleh <ph name="MANAGER" /></translation>
@@ -2115,6 +2166,7 @@ Butiran tambahan:
<translation id="9020542370529661692">Halaman ini telah diterjemahkan kepada <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Tidak sah)</translation>
+<translation id="9030265603405983977">Monokrom</translation>
<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>
@@ -2138,6 +2190,7 @@ Butiran tambahan:
<translation id="91108059142052966">Dasar pentadbir melumpuhkan perkongsian skrin dengan <ph name="APPLICATION_TITLE" /> apabila kandungan sulit kelihatan</translation>
<translation id="9114524666733003316">Mengesahkan kad...</translation>
<translation id="9114581008513152754">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="9117930699067497412">Baharu</translation>
<translation id="9119042192571987207">Dimuat naik</translation>
<translation id="9128016270925453879">Dasar dimuatkan</translation>
<translation id="9128870381267983090">Sambung ke rangkaian</translation>
@@ -2156,6 +2209,7 @@ Butiran tambahan:
<translation id="9170848237812810038">&amp;Buat asal</translation>
<translation id="9171296965991013597">Tinggalkan apl?</translation>
<translation id="9173282814238175921">Satu dokumen/Helaian baharu</translation>
+<translation id="9173995187295789444">Mengimbas peranti Bluetooth...</translation>
<translation id="917450738466192189">Sijil pelayan tidak sah.</translation>
<translation id="9174917557437862841">Butang peralihan tab, tekan Enter untuk beralih ke tab ini</translation>
<translation id="9179703756951298733">Urus maklumat pembayaran dan kad kredit anda dalam tetapan Chrome</translation>
diff --git a/chromium/components/strings/components_strings_my.xtb b/chromium/components/strings/components_strings_my.xtb
index 13f0c14ab85..ec72cc6506d 100644
--- a/chromium/components/strings/components_strings_my.xtb
+++ b/chromium/components/strings/components_strings_my.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">အမှန်á€á€¼á€…်ထားပါကአအမြန်ဖြည့်နိုင်ရန်အá€á€½á€€á€º Chrome သည် သင့်ကဒ်á မိá€á€¹á€‘ူá€á€…်စောင်အား ဤစက်ကိရိယာပေါ်á€á€½á€„် သိမ်းထားလိမ့်မည်á‹</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> အá€á€½á€€á€º á€á€½á€„့်ပြုá€á€»á€€á€ºá€™á€»á€¬á€¸ ရွေးပါ</translation>
<translation id="1113869188872983271">&amp;ပြန်စီစဉ်ကို ပြန်လုပ်ရန်</translation>
+<translation id="1123753900084781868">'á€á€­á€¯á€€á€ºá€›á€­á€¯á€€á€ºá€…ာá€á€”်း' ကို ယá€á€¯á€™á€›á€”ိုင်ပါ</translation>
<translation id="1125573121925420732">á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€€ áŽá€„်းá€á€­á€¯á€·á လုံá€á€¼á€¯á€¶á€›á€±á€¸á€€á€­á€¯ အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€žá€Šá€·á€ºá€¡á€á€« သá€á€­á€•á€±á€¸á€á€»á€€á€ºá€™á€»á€¬á€¸ ထုá€á€ºá€•á€¼á€”်á€á€¼á€„်းသည် လုပ်ရိုးလုပ်စဉ်ပင်ဖြစ်သည်ዠáŽá€„်းသည် မကြာá€á€„် á€á€­á€¯á€¸á€á€€á€ºá€™á€¾á€¯á€›á€¾á€­á€œá€¬á€”ိုင်ပါသည်á‹</translation>
<translation id="112840717907525620">ပေါ်လစီ ကက်ရှ်အိုကေ</translation>
<translation id="1130564665089811311">စာမျက်နှာဘာသာပြန်ရန်á€á€œá€¯á€á€ºáŠ ဤစာမျက်နှာကို Google Translate ဖြင့်ဘာသာပြန်ရန် Enter နှိပ်ပါ</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">သင့်စက်á အမည်</translation>
<translation id="124116460088058876">နောက်ထပ် ဘာသာစကားများ</translation>
<translation id="1243027604378859286">စာရေးသူ-</translation>
+<translation id="1246424317317450637">စာလုံးထူ</translation>
<translation id="1250759482327835220">နောင်á€á€½á€„် မြန်ဆန်စွာပေးá€á€»á€±á€”ိုင်ရန် သင်áကá€á€ºáŠ အမည်နှင့် ငွေá€á€±á€¬á€„်းá€á€¶á€œá€½á€¾á€¬á€•á€­á€¯á€·á€›á€”် လိပ်စာကို သင့် Google အကောင့်á€á€½á€„် သိမ်းပါá‹</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />አ<ph name="TYPE_2" /> (စင့်á€á€ºá€œá€¯á€•á€ºá€‘ားသည်)</translation>
<translation id="1256368399071562588">&lt;p&gt;သင်သည် á€á€˜á€ºá€†á€­á€¯á€€á€ºá€žá€­á€¯á€· á€á€„်ကြည့်သည့်အá€á€« áŽá€„်းက ပွင့်မလာလျှင် အောက်ပါ အမှားရှာဖွေဖြေရှင်းá€á€¼á€„်း အဆင့်များဖြင့် အမှားအယွင်းများကို ဖြေရှင်းကြည့်ပါ−&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">သင်áစကားá€á€¾á€€á€ºá€€á€­á€¯ ပြောင်းပါ</translation>
<translation id="1484290072879560759">ပစ္စည်းပို့ရမည့်လိပ်စာ ရွေးရန်</translation>
<translation id="1492194039220927094">မူá€á€«á€’များ ထည့်သွင်းရန်-</translation>
+<translation id="1495677929897281669">á€á€˜á€ºá€žá€­á€¯á€· ပြန်သွားရန်</translation>
<translation id="1501859676467574491">သင့် Google အကောင့်မှ ကá€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ပြရန်</translation>
<translation id="1507202001669085618">&lt;p&gt;အွန်လိုင်း မရရှိမီ လက်မှá€á€ºá€‘ိုးá€á€„်ရသည့် Wi-Fi ပေါ်á€á€šá€ºá€€á€­á€¯ အသုံးပြုသည့်အá€á€« ဤအမှားကို á€á€½á€±á€·á€›á€•á€«á€™á€Šá€ºá‹&lt;/p&gt;
&lt;p&gt;ထိုအမှားအယွင်းကို ဖြေရှင်းရန် သင်ဖွင့်ရန် ကြိုးစားနေသည့် စာမျက်နှာá€á€½á€„် &lt;strong&gt;á€á€»á€­á€á€ºá€†á€€á€ºá€›á€”်&lt;/strong&gt; ကို နှိပ်ပါá‹&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">ဤစာမျက်နှာက ဆိုထားသည်မှာ</translation>
<translation id="153384715582417236">ယá€á€¯á€¡á€á€½á€€á€ºá€á€±á€¬á€· ဒီလောက်ပါပဲ</translation>
<translation id="1536390784834419204">စာမျက်နှာကို ဘာသာပြန်ရန်</translation>
+<translation id="1539840569003678498">အစီရင်á€á€¶á€…ာ ပို့ပြီးပြီ-</translation>
<translation id="154408704832528245">ပေးပို့ရမည့်လိပ်စာ ရွေးရန်</translation>
<translation id="1549470594296187301">ဤလုပ်ဆောင်á€á€»á€€á€ºá€¡á€¬á€¸ ပြုလုပ်နိုင်ရန် JavaScript အား ဖွင့်ထားရမည်ဖြစ်áá‹</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -214,16 +218,19 @@
<translation id="1682696192498422849">á€á€­á€¯á€žá€Šá€·á€ºá€¡á€”ားနှင့် စá€á€„်ရန်</translation>
<translation id="168693727862418163">ဤမူá€á€«á€’သည် áŽá€„်းá စီမံá€á€»á€€á€ºá€”ှင့်á€á€­á€¯á€€á€ºá အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ အá€á€Šá€ºá€•á€¼á€¯áမရသောကြောင့် လျစ်လျူရှုသွားပါမည်á‹</translation>
<translation id="168841957122794586">ဆာဗာ အသိမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€ºá€á€½á€„် အားနည်းသည့် ကုဒ်ရေးá€á€¼á€„်းကီး ပါá€á€„်နေသည်!</translation>
+<translation id="1696290444144917273">ပကá€á€­á€¡á€žá€½á€„်ကá€á€º အသေးစိá€á€ºá€€á€­á€¯ ကြည့်ရန်</translation>
<translation id="1697532407822776718">သင်သည် အားလုံးကို သá€á€ºá€™á€¾á€á€ºá€•á€¼á€®á€¸á€žá€½á€¬á€¸á€•á€¼á€®!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{ဤဆာဗာက áŽá€„်းသည် <ph name="DOMAIN" /> ဖြစ်ကြောင်း သက်သေထူမပြနိုင်ပါአáŽá€„်းá လုံá€á€¼á€¯á€¶á€›á€±á€¸ လက်မှá€á€ºá€™á€¾á€¬ နက်ဖြန်á€á€½á€„် စá€á€„်မည်ዠစီဖွဲ့မှုလွဲမှားနေá သို့မဟုá€á€º သင့်á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€€á€­á€¯ ကြားဖြá€á€ºá€šá€°á€á€²á€·á€žá€Šá€·á€º á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€žá€°á€€á€¼á€±á€¬á€„့် ထိုသို့ ဖြစ်လာနိုင်á€á€²á€·á€•á€«á€žá€Šá€ºá‹}other{ဤဆာဗာက áŽá€„်းမှာ <ph name="DOMAIN" /> ဖြစ်ကြောင်း သက်သေထူမပြနိုင်ပါአáŽá€„်းá လုံá€á€¼á€¯á€¶á€›á€±á€¸ လက်မှá€á€ºá€™á€¾á€¬ အနာဂá€á€º # ရက်á€á€½á€„် စá€á€„်ပါမည်ዠစီဖွဲ့မှုလွဲမှားနေá သို့မဟုá€á€º သင့်á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€€á€­á€¯ ကြားဖြá€á€ºá€šá€°á€á€²á€·á€žá€Šá€·á€º á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€žá€°á€€á€¼á€±á€¬á€„့် ထိုသို့ ဖြစ်လာနိုင်á€á€²á€·á€•á€«á€žá€Šá€ºá‹}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> ကို <ph name="VALUE" /> အဖြစ် သá€á€ºá€™á€¾á€á€ºá€‘ားသောကြောင့် လျစ်လျူရှုလိုက်သည်á‹</translation>
<translation id="1712552549805331520"><ph name="URL" /> သည် ဒေá€á€¬á€™á€»á€¬á€¸á€€á€­á€¯ သင့်ကွန်ရက်အá€á€½á€„်းရှိ ကွန်ပျူá€á€¬á€á€½á€„် အမြဲá€á€™á€ºá€¸á€žá€­á€¯á€œá€¾á€±á€¬á€„်လိုသည်</translation>
<translation id="1713628304598226412">ဗန်း á‚</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">စာá€á€­á€¯á€€á€ºá€•á€¯á€¶á€¸ áƒ</translation>
<translation id="1718029547804390981">မှá€á€ºá€á€™á€ºá€¸á€–ိုင်သည် မှá€á€ºá€á€»á€€á€ºá€•á€±á€¸á€›á€”်အá€á€½á€€á€º အလွန်ကြီးနေပါသည်</translation>
<translation id="1721424275792716183">* ပြထားသော အကွက်ကို ဖြည့်ရန်လိုသည်</translation>
+<translation id="1727613060316725209">အသိအမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€º မှန်ကန်သည်</translation>
<translation id="1727741090716970331">မှန်ကန်သည့် ကá€á€ºá€”ံပါá€á€ºá€€á€­á€¯ ထည့်ပါ</translation>
<translation id="1728677426644403582">á€á€˜á€ºá€…ာမျက်နှာá အရင်းအမြစ်á€á€…်á€á€¯á€€á€­á€¯ သင်ကြည့်ရှုနေá€á€¼á€„်းဖြစ်သည်</translation>
<translation id="173080396488393970">ဤကဒ်အမျိုးအစားကို လက်မá€á€¶á€•á€«</translation>
@@ -248,7 +255,6 @@
သင်áá€á€±á€¬á€„်းဆိုá€á€»á€€á€ºá€€á€­á€¯ မဖြည့်ဆည်းနိုင်ပါዠá€á€˜á€ºá€†á€­á€¯á€€á€ºá€á€…်á€á€¯á€¡á€á€½á€€á€º လုံá€á€¼á€¯á€¶á€›á€±á€¸á€”ှင့် အá€á€¼á€¬á€¸á€žá€á€ºá€™á€¾á€á€ºá€á€»á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯
စီစဉ်သá€á€ºá€™á€¾á€á€ºá€›á€”် á€á€˜á€ºá€†á€­á€¯á€€á€º အော်ပရေá€á€¬á€™á€»á€¬á€¸á€€ ရင်းမြစ် မူá€á€«á€’များကို အသုံးပြုနိုင်ပါသည်á‹</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">ကျေးဇူးပြုပြီး သင်á စင့်က် စကားစုá€á€¾á€€á€ºá€€á€­á€¯ မွမ်းမံပါá‹</translation>
<translation id="1787142507584202372">သင်ဖွင့်ထားသည့်á€á€˜á€ºá€™á€»á€¬á€¸ ဤနေရာá€á€½á€„် ပေါ်ပါမည်</translation>
<translation id="1791429645902722292">Google ကစမá€á€ºá€žá€±á€¬á€·á€á€á€º</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />አလုပ်ဆောင်á€á€»á€€á€º အများအပြား ရရှိနိုင်သည်አáŽá€„်းá€á€­á€¯á€·á€€á€­á€¯á€•á€á€ºá€€á€¼á€Šá€·á€ºá€›á€”် Tab နှိပ်ပါ</translation>
@@ -281,6 +287,7 @@
<translation id="1919345977826869612">ကြော်ငြာများ</translation>
<translation id="1919367280705858090">မှားယွင်းကြောင်း မက်ဆေ့ဂျ်အá€á€»á€­á€¯á€·á€¡á€á€½á€€á€º အကူအညီ ရယူရန်</translation>
<translation id="192020519938775529">{COUNT,plural, =0{á€á€…်á€á€¯á€™á€»á€¾á€™á€›á€¾á€­á€•á€«}=1{á€á€˜á€ºá€†á€­á€¯á€€á€º á á€á€¯}other{á€á€˜á€ºá€†á€­á€¯á€€á€º # á€á€¯}}</translation>
+<translation id="1924727005275031552">အသစ်</translation>
<translation id="1945968466830820669">သင်သည် သင့်အဖွဲ့အစည်းá အကောင့်ကို အသုံးပြုá€á€½á€„့် ဆုံးရှုံးနိုင်သည် သို့မဟုá€á€º အထောက်အထား အá€á€­á€¯á€¸á€á€¶á€›á€”ိုင်သည်ዠသင့်စကားá€á€¾á€€á€ºá€€á€­á€¯ ယá€á€¯á€•á€„်ပြောင်းလဲရန် Chromium က အကြံပြုပါသည်á‹</translation>
<translation id="1947454675006758438">ညာဘက်ထိပ်á€á€½á€„် á€á€»á€¯á€•á€ºá€…က်ဖြင့် á€á€»á€¯á€•á€ºá€›á€”်</translation>
<translation id="1958218078413065209">သင်á အမြင့်ဆုံးရမှá€á€ºá€™á€¾á€¬ <ph name="SCORE" /> ဖြစ်သည်á‹</translation>
@@ -303,12 +310,14 @@
<translation id="2042213636306070719">ဗန်း á‡</translation>
<translation id="204357726431741734">သင့် Google Account á€á€½á€„် သိမ်းထားသောစကားá€á€¾á€€á€ºá€™á€»á€¬á€¸ အသုံးပြုရန် လက်မှá€á€ºá€‘ိုးá€á€„်ပါ</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> ဘာသာဖြင့် စာမျက်နှာများကို ဘာသာပြန်မည် မဟုá€á€ºá€•á€«á‹</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{ဤထိန်းá€á€»á€¯á€•á€ºá€™á€¾á€¯á€€á€­á€¯ ဖွင့်ထားပြီး သုံးနေသည့် အá€á€¼á€±á€¡á€”ေပြသောအá€á€« Chrome သည် သင်áမကြာသေးမီက ကြည့်ရှုá€á€¼á€„်းများနှင့် အနီးစပ်ဆုံးá€á€°á€žá€±á€¬ လူအဖွဲ့ကြီး (သို့) “á€á€…်á€á€»á€­á€”်á€á€Šá€ºá€¸á€¡á€á€°á€á€€á€½ လုပ်ဆောင်á€á€¼á€„်း†ကို သá€á€ºá€™á€¾á€á€ºá€žá€Šá€ºá‹ ကြော်ငြာရှင်များက အဖွဲ့အá€á€½á€€á€º ကြော်ငြာများကို ရွေးနိုင်ပြီး သင်áကြည့်ရှုá€á€¼á€„်းများကို သင့်စက်á€á€½á€„် သီးသန့်ထားရှိသည်ዠသင့်အဖွဲ့ကို နေ့စဉ် အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€žá€Šá€ºá‹}=1{ဤထိန်းá€á€»á€¯á€•á€ºá€™á€¾á€¯á€€á€­á€¯ ဖွင့်ထားပြီး သုံးနေသည့် အá€á€¼á€±á€¡á€”ေပြသောအá€á€« Chrome သည် သင်áမကြာသေးမီက ကြည့်ရှုá€á€¼á€„်းများနှင့် အနီးစပ်ဆုံးá€á€°á€žá€±á€¬ လူအဖွဲ့ကြီး (သို့) “á€á€…်á€á€»á€­á€”်á€á€Šá€ºá€¸á€¡á€á€°á€á€€á€½ လုပ်ဆောင်á€á€¼á€„်း†ကို သá€á€ºá€™á€¾á€á€ºá€žá€Šá€ºá‹ ကြော်ငြာရှင်များက အဖွဲ့အá€á€½á€€á€º ကြော်ငြာများကို ရွေးနိုင်ပြီး သင်áကြည့်ရှုá€á€¼á€„်းများကို သင့်စက်á€á€½á€„် သီးသန့်ထားရှိသည်ዠသင့်အဖွဲ့ကို နေ့စဉ် အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€žá€Šá€ºá‹}other{ဤထိန်းá€á€»á€¯á€•á€ºá€™á€¾á€¯á€€á€­á€¯ ဖွင့်ထားပြီး သုံးနေသည့် အá€á€¼á€±á€¡á€”ေပြသောအá€á€« Chrome သည် သင်áမကြာသေးမီက ကြည့်ရှုá€á€¼á€„်းများနှင့် အနီးစပ်ဆုံးá€á€°á€žá€±á€¬ လူအဖွဲ့ကြီး (သို့) “á€á€…်á€á€»á€­á€”်á€á€Šá€ºá€¸á€¡á€á€°á€á€€á€½ လုပ်ဆောင်á€á€¼á€„်း†ကို သá€á€ºá€™á€¾á€á€ºá€žá€Šá€ºá‹ ကြော်ငြာရှင်များက အဖွဲ့အá€á€½á€€á€º ကြော်ငြာများကို ရွေးနိုင်ပြီး သင်áကြည့်ရှုá€á€¼á€„်းများကို သင့်စက်á€á€½á€„် သီးသန့်ထားရှိသည်ዠသင့်အဖွဲ့ကို {NUM_DAYS} ရက်á€á€…်ကြိမ် အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€žá€Šá€ºá‹}}</translation>
<translation id="2053553514270667976">ဇစ်ကုဒ်</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{အကြံပြုá€á€»á€€á€º á á€á€¯}other{အကြံပြုá€á€»á€€á€º # á€á€¯}}</translation>
<translation id="2071692954027939183">အကြောင်းကြားá€á€»á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ သင်က á€á€½á€„့်ပြုလေ့မရှိသဖြင့် áŽá€„်းá€á€­á€¯á€·á€€á€­á€¯ အလိုအလျောက် ပိá€á€ºá€‘ားသည်</translation>
<translation id="2079545284768500474">á€á€…်ဆင့်နောက်ပြန်ရန်</translation>
<translation id="20817612488360358">စနစ် ပရောက်စီ ဆက်á€á€„်များကို အသုံးပြုရန် သá€á€ºá€™á€¾á€á€º ပေးထားသော်လည်း အထူး ဖေါ်ပြပေးထားသည့် ပရောက်စီ စီစဉ်ဖွဲ့စည်းမှု á€á€…်á€á€¯á€€á€­á€¯á€•á€« ဖေါ်ပြပေးထားသည်á‹</translation>
<translation id="2082238445998314030">အဖြေ <ph name="RESULT_NUMBER" /> / <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">သိမ်းရန်…</translation>
<translation id="2088086323192747268">စင့်á€á€ºá€œá€¯á€•á€ºá€á€¼á€„်းကို စီမံရန် á€á€œá€¯á€á€ºáŠ Chrome ဆက်á€á€„်များá€á€½á€„် သင်စင့်á€á€ºá€œá€¯á€•á€ºá€žá€±á€¬ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ စီမံရန် Enter နှိပ်ပါ</translation>
<translation id="2091887806945687916">အသံ</translation>
<translation id="2094505752054353250">ဒိုမိန်း မá€á€­á€¯á€€á€ºá€†á€­á€¯á€„်မှု</translation>
@@ -381,6 +390,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> အá€á€½á€€á€º အသုံးပြုသူအမည် နှင့် စကားá€á€¾á€€á€º လိုအပ်ပါသည်á‹</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />አ<ph name="EXPIRATION_DATE_ABBR" /> á€á€½á€„် သက်á€á€™á€ºá€¸á€€á€¯á€”်မည်</translation>
<translation id="2337852623177822836">သင်á စီမံá€á€”့်á€á€½á€²á€žá€°á€€ ထိန်းá€á€»á€¯á€•á€ºá€‘ားသော ဆက်á€á€„်</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> သည် á€á€½á€²á€á€»á€­á€á€ºá€œá€­á€¯á€•á€«á€žá€Šá€º</translation>
<translation id="2344028582131185878">အလိုအလျောက် ဒေါင်းလုဒ်များ</translation>
<translation id="2346319942568447007">သင်မိá€á€¹á€á€°á€€á€°á€¸á€‘ားသော ပုံ</translation>
<translation id="2354001756790975382">အá€á€¼á€¬á€¸ စာညှပ်များ</translation>
@@ -388,8 +398,10 @@
<translation id="2355395290879513365">á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€žá€°á€™á€»á€¬á€¸á€€ ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€á€½á€„် သင်ကြည့်နေသော ပုံများကို မြင်နိုင်á áŽá€„်းá€á€­á€¯á€·á€€á€­á€¯ ပြင်ဆင်á€á€¼á€„်းဖြင့် သင့်ကို လှည့်စားနိုင်ပါသည်á‹</translation>
<translation id="2356070529366658676">မေး</translation>
<translation id="2357481397660644965">သင့်စက်ပစ္စည်းကို <ph name="DEVICE_MANAGER" /> က စီမံá€á€”့်á€á€½á€²á€•á€¼á€®á€¸ သင့်အကောင့်ကို <ph name="ACCOUNT_MANAGER" /> က စီမံá€á€”့်á€á€½á€²á€žá€Šá€ºá‹</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{á€á€…်ရက်မပြည့်မီ}=1{á€á€…်ရက်အကြာá€á€½á€„်}other{{NUM_DAYS} ရက်အကြာá€á€½á€„်}}</translation>
<translation id="2359629602545592467">များစွာ</translation>
<translation id="2359808026110333948">ဆက်လုပ်ရန်</translation>
+<translation id="2359961752320758691">သင့်ပကá€á€­á€¡á€žá€½á€„်ကá€á€º နံပါá€á€ºá€€á€­á€¯ သုံးထားသည်á‹</translation>
<translation id="2367567093518048410">အဆင့်</translation>
<translation id="2372464001869762664">အá€á€Šá€ºá€•á€¼á€¯á€•á€¼á€®á€¸á€”ောက် သင်á Google Account မှ ကá€á€ºá€¡á€žá€±á€¸á€…ိá€á€º အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€¡á€¬á€¸ မျှá€á€±á€žá€½á€¬á€¸á€•á€«á€™á€Šá€ºá‹ သင်á 'Plex အကောင့်' အသေးစိá€á€ºá€á€½á€„် CVC နံပါá€á€ºá€€á€­á€¯ ရှာပါá‹</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -400,6 +412,7 @@
<translation id="239429038616798445">ဤပစ္စည်းပို့á€á€¼á€„်းနည်းလမ်းသည် မရနိုင်ပါዠအá€á€¼á€¬á€¸á€”ည်းလမ်းá€á€…်á€á€¯á€€á€­á€¯ ရွေးပါá‹</translation>
<translation id="2396249848217231973">&amp;ဖျက်မှုကို ပြန်လုပ်ရန်</translation>
<translation id="2410754574180102685">အစိုးရရုံးသုံး Legal စာရွက်</translation>
+<translation id="2413155254802890957">အဟောင်း</translation>
<translation id="2413528052993050574">ဒီဆာဗာက <ph name="DOMAIN" /> ဖြစ်á€á€¬á€€á€­á€¯ သက်သေထူ မပြနိုင်á€á€²á€·á€•á€«áŠ áŽá€„်းá လုံá€á€¼á€¯á€¶á€›á€±á€¸ လက်မှá€á€ºá€€á€­á€¯ ရုပ်သိမ်းá€á€²á€·á€á€¬ ဖြစ်နိုင်သည်ዠဖွဲ့စည်းစီစဉ်မှု အမှားကြောင့် သို့မဟုá€á€º á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€œá€­á€¯á€žá€°á€€ သင်á á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€€á€­á€¯ ကြားဖြá€á€ºá€šá€°á€”ေá ထိုသို့ ဖြစ်လာနိုင်á€á€²á€·á€•á€«á€žá€Šá€ºá‹</translation>
<translation id="2414886740292270097">အမှောင်</translation>
<translation id="2438874542388153331">ညာဘက်á€á€½á€„် လေးá€á€»á€€á€ºá€–ောက်ရန်</translation>
@@ -427,10 +440,10 @@
<translation id="2521385132275182522">ညာဘက်အောက်á€á€¼á€±á€á€½á€„် á€á€»á€¯á€•á€ºá€…က်ဖြင့် á€á€»á€¯á€•á€ºá€›á€”်</translation>
<translation id="2523886232349826891">ဤစက်á€á€½á€„်သာ သိမ်းထားသည်</translation>
<translation id="2524461107774643265">နောက်ထပ် အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ထည့်á€á€¼á€„်း</translation>
-<translation id="2526590354069164005">ဒက်စက်á€á€±á€¬á€·</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{နှင့် နောက်ထပ် á á€á€¯}other{နှင့် နောက်ထပ် # á€á€¯}}</translation>
<translation id="2536110899380797252">လိပ်စာထည့်ရန်</translation>
<translation id="2539524384386349900">ရှာကြည့်ရန်</translation>
+<translation id="2541219929084442027">ရုပ်ဖျက်á€á€˜á€ºá€™á€»á€¬á€¸á€á€½á€„် ကြည့်ရှုသည့် စာမျက်နှာများသည် သင့်ရုပ်ဖျက်á€á€˜á€ºá€¡á€¬á€¸á€œá€¯á€¶á€¸á€€á€­á€¯ ပိá€á€ºá€œá€­á€¯á€€á€ºá€•á€¼á€®á€¸á€”ောက်á€á€½á€„် သင့်ဘရောင်ဇာá မှá€á€ºá€á€™á€ºá€¸áŠ ကွá€á€ºá€€á€®á€¸á€žá€­á€¯á€œá€¾á€±á€¬á€„်မှု သို့မဟုá€á€º ရှာဖွေမှá€á€ºá€á€™á€ºá€¸á€á€½á€„် ရှိá€á€±á€¬á€·á€™á€Šá€ºá€™á€Ÿá€¯á€á€ºá€•á€«á‹ သင်ဒေါင်းလုဒ်လုပ်သောဖိုင်များ သို့မဟုá€á€º သင်ပြုလုပ်ထားသော စာညှပ်များ အားလုံးကို သိမ်းထားပါမည်á‹</translation>
<translation id="2544644783021658368">စာရွက်စာá€á€™á€ºá€¸ á€á€…်á€á€¯á€á€Šá€ºá€¸</translation>
<translation id="254947805923345898">မူá€á€«á€’á€á€”်ဖိုး မမှန်ကန်ပါá‹</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> သည်မမှန်ကန်သည့် á€á€¯á€¶á€·á€•á€¼á€”်မှုကို ပို့á€á€²á€·á€•á€«á€žá€Šá€ºá‹</translation>
@@ -450,6 +463,7 @@
<translation id="2629325967560697240">Chrome á အမြင့်ဆုံးလုံá€á€¼á€¯á€¶á€›á€±á€¸ ရရှိရန် <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />အဆင့်မြှင့်á€á€„်ထားသော ကာကွယ်မှုကို ဖွင့်ပါ<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> á ဆာဗာ IP လိပ်စာကို မá€á€½á€±á€·á€•á€«á‹</translation>
<translation id="2639739919103226564">အá€á€¼á€±á€¡á€”ေ:</translation>
+<translation id="264810637653812429">ကိုက်ညီမှုရှိသည့် စက်ပစ္စည်းများ မá€á€½á€±á€·á€•á€«á‹</translation>
<translation id="2649204054376361687"><ph name="CITY" />አ<ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />አChrome ဆက်á€á€„်များရှိ သင့်ကြည့်ရှုá€á€¼á€„်းမှá€á€ºá€á€™á€ºá€¸áŠ ကွá€á€ºá€€á€®á€¸á€™á€»á€¬á€¸áŠ ကက်ရှ်နှင့် အá€á€¼á€¬á€¸á€¡á€›á€¬á€™á€»á€¬á€¸á€€á€­á€¯ ရှင်းရန် Tab နှိပ်ပြီးနောက် Enter နှိပ်ပါ</translation>
<translation id="2650446666397867134">ဖိုင်အား ရယူမှု ငြင်းပယ်á€á€¶á€á€²á€·á€›</translation>
@@ -496,6 +510,7 @@
<translation id="2799223571221894425">ပြန်လည်ဖွင့်á€á€„်ရန်</translation>
<translation id="2803306138276472711">Google á လုံá€á€¼á€¯á€¶á€…ွာ ရှာကြည့်မှုသည် မကြာမီá€á€¯á€”်းက <ph name="BEGIN_LINK" />အန္á€á€›á€¬á€šá€ºá€á€²<ph name="END_LINK" /> ကို <ph name="SITE" />မှာ ရှာá€á€½á€±á€·á€á€²á€·á€žá€Šá€ºá‹ ပုံမှန်မအားဖြင့် လုံá€á€¼á€¯á€¶á€€á€¼á€žá€Šá€ºá€· á€á€€á€ºá€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€™á€¾á€¬ ရံဖန်ရံá€á€«á€á€½á€„် အန္á€á€›á€¬á€šá€ºá€á€²á€–ြင့် ကူးစက်á€á€¶á€› á€á€á€ºá€žá€Šá€ºá‹</translation>
<translation id="2807052079800581569">ပုံ ဒေါင်လိုက်အနေအထား</translation>
+<translation id="2820957248982571256">ရှာဖွေနေသည်...</translation>
<translation id="2824775600643448204">လိပ်စာ နှင့် ရှာဖွေရေး ဘား</translation>
<translation id="2826760142808435982">á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€€á€­á€¯ လုံá€á€¼á€¯á€¶á€¡á€±á€¬á€„် ပြုလုပ်ထားပြီး စစ်မှန်ကြောင်းအá€á€Šá€ºá€•á€¼á€¯á€›á€¬áŒ <ph name="CIPHER" /> နှင့် <ph name="KX" /> ကိုကီးပြောင်းလဲမှု စက်ယန္á€á€›á€¬á€¸á€¡á€–ြစ် အသုံးပြုထားပါသည်á‹</translation>
<translation id="2835170189407361413">ပုံစံ ရှင်းမည်</translation>
@@ -503,6 +518,8 @@
<translation id="2850739647070081192">ဖိá€á€ºá€…ာ (စာအိá€á€º)</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="2859806420264540918">ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€€ စိá€á€ºá€¡á€”ှောင့်အယှက်ဖြစ်စေသော (သို့) အထင်အမြင်မှားစေသော ကြော်ငြာများကို ပြသည်á‹</translation>
+<translation id="287596039013813457">နှစ်လိုဖွယ်</translation>
+<translation id="2876489322757410363">ပြင်ပအပလီကေးရှင်းဖြင့် ငွေပေးá€á€»á€±á€›á€”် ရုပ်ဖျက်မုဒ်မှ ထွက်နေသည်ዠရှေ့ဆက်မလားá‹</translation>
<translation id="2878197950673342043">ပိုစá€á€¬á€•á€¯á€¶ á€á€±á€«á€€á€ºá€›á€”်</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">á€á€„်းဒိုး နေရာá€á€»á€‘ားမှု</translation>
@@ -554,7 +571,6 @@
<translation id="3060227939791841287">C9 (စာအိá€á€º)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />አChrome ဆက်á€á€„်များá€á€½á€„် ‘လုံá€á€¼á€¯á€¶á€›á€±á€¸ စစ်ဆေးမှု’ လုပ်ဆောင်ရန် ‘á€á€˜á€ºá€á€œá€¯á€á€ºâ€™ ပြီးနောက် Enter နှိပ်ပါ</translation>
<translation id="3061707000357573562">ပြင်ဆင်á€á€¼á€„်း á€á€”်ဆောင်မှု</translation>
-<translation id="3064966200440839136">ပြင်ပအပလီကေးရှင်းဖြင့် ငွေပေးá€á€»á€±á€›á€”် ရုပ်ဖျက်မုဒ်မှ ထွက်နေသည်ዠရှေ့ဆက် လိုပါသလားá‹</translation>
<translation id="306573536155379004">ဂိမ်းစá€á€„်ပါပြီá‹</translation>
<translation id="3080254622891793721">ဂရပ်ဖစ်</translation>
<translation id="3086579638707268289">á€á€˜á€ºá€•á€±á€«á€ºá€á€½á€„် သင့်လုပ်ဆောင်á€á€»á€€á€ºá€€á€­á€¯ စောင့်ကြည့်နေပါသည်</translation>
@@ -577,7 +593,6 @@
<translation id="315504272643575312">သင့်အကောင့်ကို <ph name="MANAGER" /> က စီမံá€á€”့်á€á€½á€²á€žá€Šá€ºá‹</translation>
<translation id="3157931365184549694">ပြန်လည်ဖေါ်ထုá€á€ºá€›á€”်</translation>
<translation id="3162559335345991374">သင်အသုံးပြုနေသော Wi-Fi á login စာမျက်နှာသို့ သင်သွားရောက်ကြည့်ရှုရန် လိုမည်á‹</translation>
-<translation id="3167968892399408617">သင်ရုပ်ဖျက်á€á€˜á€ºá€™á€»á€¬á€¸á€á€½á€„် ကြည့်ရှုသည့် စာမျက်နှာများသည် áŽá€„်းကိုသင်ပိá€á€ºá€œá€­á€¯á€€á€ºá€•á€¼á€®á€¸á€”ောက်á€á€½á€„် သင့်ဘရောက်ဇာá မှá€á€ºá€á€™á€ºá€¸áŠ ကွá€á€ºá€€á€®á€…á€á€­á€¯á€¸áŠ သို့မဟုá€á€º ရှာဖွေမှုမှá€á€ºá€á€™á€ºá€¸á€á€½á€„် ရှိá€á€±á€¬á€·á€™á€Šá€ºá€™á€Ÿá€¯á€á€ºá€•á€«á‹ သင်ဒေါင်းလုဒ်လုပ်သည့်ဖိုင်များ သို့မဟုá€á€º သင်ဖန်á€á€®á€¸á€á€²á€·á€žá€Šá€·á€º စာညှပ်များကို သိမ်းထားမည်ဖြစ်သည်á‹</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">ကျွန်း</translation>
<translation id="3176929007561373547">ဤပရော့စီဆာဗာအလုပ်လုပ်ကြောင်း သေá€á€»á€¬á€™á€¾á€¯á€›á€¾á€­á€…ေရန် သင့်ပရော့စီဆက်á€á€„်ကို စစ်ဆေးပါ သို့မဟုá€á€º သင့်ကွန်ယက်စီမံá€á€”့်á€á€½á€²á€žá€°á€€á€­á€¯ ဆက်သွယ်ပါዠအကယ်áသင်မယုံကြည်လျှင် ပရော့စီဆာဗာကို အသုံးပြုသင့်သည် − <ph name="PLATFORM_TEXT" /></translation>
@@ -600,10 +615,12 @@
<translation id="3229041911291329567">သင့်စက်နှင့် ဘရောင်ဇာအကြောင်း ဗားရှင်းအá€á€»á€€á€ºá€¡á€œá€€á€º</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> အá€á€½á€€á€º CVC ကို ထည့်ပါ</translation>
<translation id="3234666976984236645">ဤအင်á€á€¬á€”က်စာမျက်နှာ‌ပေါ်á€á€½á€„် အရေးကြီး‌သော မာá€á€­á€€á€¬á€™á€»á€¬á€¸á€€á€­á€¯ အစဉ် ထောက်လှမ်းပါ</translation>
+<translation id="3249845759089040423">မိမိမိုက်မိုက်</translation>
<translation id="3252266817569339921">ပြင်သစ်</translation>
<translation id="3266793032086590337">á€á€”်ဖိုး (ကွဲလွဲသည်)</translation>
<translation id="3268451620468152448">á€á€²á€˜á€ºá€™á€»á€¬á€¸ ဖွင့်ရန်</translation>
<translation id="3270847123878663523">&amp;ပြန်စီမှုကို á€á€…်ဆင့်နောက်ပြန်ရန်</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> သည် á€á€»á€­á€á€ºá€†á€€á€ºá€œá€­á€¯á€•á€«á€žá€Šá€º</translation>
<translation id="3274521967729236597">ပါကိုင်</translation>
<translation id="3282085321714087552">သင့်အဖွဲ့အစည်း <ph name="ENROLLMENT_DOMAIN" /> သည် ဆက်á€á€„်များ (သို့) မူá€á€«á€’များကဲ့သို့ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€¡á€á€»á€­á€¯á€·á€€á€­á€¯ အောက်ပါá€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€žá€­á€¯á€· ပို့လိုက်သည်á‹</translation>
<translation id="3282497668470633863">ကá€á€ºá€•á€±á€«á€ºá€›á€¾á€­ အမည်ကို ထည့်ပါ</translation>
@@ -656,6 +673,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates ဆာဗာ နမူနာပုံစံ URI များအနက် á€á€…်á€á€¯á€”ှင့်အထက် မှားနေသဖြင့် အသုံးပြုမည်မဟုá€á€ºá€•á€«á‹</translation>
<translation id="3431636764301398940">ဤကဒ်ကို ဤစက်ပစ္စည်းá€á€½á€„် သိမ်းရန်</translation>
<translation id="3432601291244612633">စာမျက်နှာကို ပိá€á€ºá€›á€”်</translation>
+<translation id="3435738964857648380">လုံá€á€¼á€¯á€¶á€›á€±á€¸</translation>
<translation id="3435896845095436175">ဖွင့်ပေးရန်</translation>
<translation id="3438829137925142401">သင်á Google Account á€á€½á€„် သိမ်းထားသော စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ သုံးရန်</translation>
<translation id="3443726618221119081">ဂျူရို ကုကိုင်</translation>
@@ -697,7 +715,10 @@
<translation id="3584299510153766161">အောက်á€á€¼á€±á€á€½á€„် နှစ်á€á€»á€€á€ºá€–ောက်ရန်</translation>
<translation id="3586931643579894722">အသေးစိá€á€ºá€™á€»á€¬á€¸ á€á€¾á€€á€ºá€‘ားရန်</translation>
<translation id="3587738293690942763">အလယ်အလá€á€º</translation>
+<translation id="3590643883886679995">ရုပ်ဖျက်မုဒ်မှ ထွက်ပြီးသောအá€á€« လက်မှá€á€ºá€‘ိုးá€á€„်á€á€¼á€„်းဆိုင်ရာ ဒေá€á€¬á€€á€­á€¯ ဤစက်á€á€½á€„် သိမ်းထားပါမည်á‹</translation>
+<translation id="359126217934908072">လ/နှစ်-</translation>
<translation id="3592413004129370115">အီá€á€œá€® (စာအိá€á€º)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{သင့်အဖွဲ့ကို အá€á€»á€­á€”်မရွေး ပြင်ဆင်သá€á€ºá€™á€¾á€á€ºá€”ိုင်သည်ዠအဖွဲ့သစ်á€á€½á€„်ပါá€á€„်ရန် á€á€…်ရက် ကြာမြင့်သည်á‹}=1{သင့်အဖွဲ့ကို အá€á€»á€­á€”်မရွေး ပြင်ဆင်သá€á€ºá€™á€¾á€á€ºá€”ိုင်သည်ዠအဖွဲ့သစ်á€á€½á€„်ပါá€á€„်ရန် á€á€…်ရက် ကြာမြင့်သည်á‹}other{သင့်အဖွဲ့ကို အá€á€»á€­á€”်မရွေး ပြင်ဆင်သá€á€ºá€™á€¾á€á€ºá€”ိုင်သည်ዠအဖွဲ့သစ်á€á€½á€„်ပါá€á€„်ရန် {NUM_DAYS} ရက် ကြာမြင့်သည်á‹}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />አ<ph name="DOMAIN" />አ<ph name="TIME" /></translation>
<translation id="3603507503523709">သင့်စီမံá€á€”့်á€á€½á€²á€žá€°á€€ ပိá€á€ºá€‘ားသည့် အပလီကေးရှင်း</translation>
<translation id="3608932978122581043">ဖိဒ်အနေအထား</translation>
@@ -706,12 +727,12 @@
<translation id="3615877443314183785">မှန်ကန်သည့် ကုန်ဆုံးမည့်ရက်ကို ထည့်ပါ</translation>
<translation id="36224234498066874">ဖွင့်ကြည့်ထားသည့် ဒေá€á€¬á€™á€»á€¬á€¸á€€á€­á€¯ ရှင်းလင်းရန်...</translation>
<translation id="362276910939193118">မှá€á€ºá€á€™á€ºá€¸ အပြည့် ပြရန်</translation>
-<translation id="3625635938337243871">ရုပ်ဖျက်မုဒ်မှထွက်ပြီးသောအá€á€« လက်မှá€á€ºá€‘ိုးá€á€„်á€á€¼á€„်းဆိုင်ရာ ဒေá€á€¬á€€á€­á€¯ ဤစက်á€á€½á€„် သိမ်းထားပါမည်á‹</translation>
<translation id="3630155396527302611">áŽá€„်းကို ကွန်ရက်အသုံးပြုသည့် ပရိုဂရမ်အဖြစ် စာရင်းထည့်သွင်းပြီးဖြစ်လျှင်አစာရင်းမှ ဖယ်ရှားပြီး ထပ်မံထည့်သွင်းကြည့်ပါá‹</translation>
<translation id="3630699740441428070">ဤစက်ကိုစီမံá€á€”့်á€á€½á€²á€žá€°á€™á€»á€¬á€¸á€žá€Šá€º သင်á€á€„်ကြည့်á€á€²á€·á€žá€±á€¬ á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€¡á€•á€«á€¡á€á€„် ကွန်ရက်ဒေá€á€¬ စီးဆင်းမှုအား ကြည့်á€á€½á€„့်ရစေရန် သင့်ကွန်ရက်á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€€á€­á€¯ စီစဉ်သá€á€ºá€™á€¾á€á€ºá€‘ားသည်á‹</translation>
<translation id="3631244953324577188">ဇီá€á€™á€€á€ºá€‘ရစ် အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸</translation>
<translation id="3633738897356909127">Chrome အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€›á€”်á€á€œá€¯á€á€ºáŠ သင့် Chrome ဆက်á€á€„်များမှá€á€…်ဆင့် Chrome ကို အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€›á€”် Enter နှိပ်ပါ</translation>
<translation id="3634530185120165534">ဗန်း á…</translation>
+<translation id="3637662659967048211">Google Account á€á€½á€„် သိမ်းပါ</translation>
<translation id="3640766068866876100">အညွှန်း-á„xá†-နောက်ဆက်á€á€½á€²</translation>
<translation id="3642638418806704195">အပလီကေးရှင်း-</translation>
<translation id="3650584904733503804">အောင်မြင်စွာ အá€á€Šá€ºá€•á€¼á€¯á€•á€¼á€®á€¸</translation>
@@ -752,6 +773,7 @@
<translation id="3781428340399460090">ပန်းရင့်ရောင်</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">ဘလူးá€á€°á€¸á€žá€ºá€…က်ပစ္စည်းများ</translation>
+<translation id="3787675388804467730">ပကá€á€­á€¡á€žá€½á€„် ကá€á€ºá€”ံပါá€á€º</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> á€á€½á€„် ကုန်ဆုံးမည်</translation>
<translation id="3789155188480882154">အရွယ်အစား áá†</translation>
<translation id="3789841737615482174">á€á€•á€ºá€†á€„်ရန်</translation>
@@ -771,6 +793,7 @@
<translation id="3841184659773414994">ဖိုင်စီမံသူများ</translation>
<translation id="385051799172605136">နောက်သို့</translation>
<translation id="3858027520442213535">ရက်စွဲ နှင့် အá€á€»á€­á€”်ကို မွမ်းမံပါ</translation>
+<translation id="3881478300875776315">စာကြောင်းလျှော့áပြရန်</translation>
<translation id="3884278016824448484">စက်ပစ္စည်း မည်သူမည်á€á€«á€–ြစ်ကြောင်း အသိမှá€á€ºá€•á€¼á€¯á€žá€° ရှုပ်ထွေးနေ</translation>
<translation id="3885155851504623709">နယ်​မြေ</translation>
<translation id="388632593194507180">စောင့်ကြည့်နေကြောင်း á€á€½á€±á€·á€›á€¾á€­á€‘ားသည်</translation>
@@ -796,6 +819,7 @@
<translation id="397105322502079400">á€á€½á€€á€ºá€á€»á€€á€ºá€”ေ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ကိုပိá€á€ºá€†á€­á€¯á€·á€‘ားသည်</translation>
<translation id="3973357910713125165">‘Chrome လုံá€á€¼á€¯á€¶á€›á€±á€¸ စစ်ဆေးမှု’ á€á€œá€¯á€á€ºá€€á€­á€¯ လုပ်ဆောင်ပါአChrome ဆက်á€á€„်များá€á€½á€„် ‘လုံá€á€¼á€¯á€¶á€›á€±á€¸ စစ်ဆေးမှု’ လုပ်ဆောင်ရန် Enter နှိပ်ပါ</translation>
+<translation id="3986705137476756801">'á€á€­á€¯á€€á€ºá€›á€­á€¯á€€á€ºá€…ာá€á€”်း' ကို ယá€á€¯ ပိá€á€ºá€›á€”်</translation>
<translation id="3987405730340719549">ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€žá€Šá€º အá€á€¯ သို့မဟုá€á€º လှည့်ဖြားမှု ဖြစ်နိုင်သည်ဟု Chrome က သá€á€ºá€™á€¾á€á€ºá€œá€­á€¯á€€á€ºá€žá€Šá€ºá‹
áŽá€„်းကို မှားယွင်းပြီး ပြသည်ဟု ယုံကြည်ပါက https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals သို့á€á€„်ကြည့်ပါá‹</translation>
@@ -893,13 +917,14 @@
<translation id="4275830172053184480">သင့်စက်ပစ္စည်းကို ပြန်လည် အစပြုပါ</translation>
<translation id="4277028893293644418">စကားá€á€¾á€€á€º ပြင်ဆင်သá€á€ºá€™á€¾á€á€ºá€›á€”်</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ဤကá€á€ºá€€á€­á€¯ သင်á Google အကောင့်á€á€½á€„် သိမ်းပြီးပါပြီ}other{ဤကá€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ သင်á Google အကောင့်á€á€½á€„် သိမ်းပြီးပါပြီ}}</translation>
+<translation id="4287885627794386150">အစမ်းသုံးရန် အကျုံးá€á€„်သော်လည်း သုံးမနေပါ</translation>
<translation id="4297502707443874121">စာမျက်နှာ <ph name="THUMBNAIL_PAGE" /> အá€á€½á€€á€º ပုံသေး</translation>
<translation id="42981349822642051">á€á€­á€¯á€¸á€á€»á€²á€·</translation>
<translation id="4300675098767811073">ညာဘက်á€á€½á€„် အများအပြားဖောက်ရန်</translation>
<translation id="4302514097724775343">ကစားရန် ဒိုင်နိုကိုá€á€­á€¯á€·á€•á€«</translation>
<translation id="4302965934281694568">Chou3 (စာအိá€á€º)</translation>
<translation id="4305666528087210886">သင့်ဖိုင်ကို သုံးáမရနိုင်ပါ</translation>
-<translation id="4305817255990598646">á€á€œá€¯á€á€º</translation>
+<translation id="4306529830550717874">လိပ်စာ သိမ်းမလားá‹</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">ပိá€á€ºá€†á€­á€¯á€·á€›á€”် (မူရင်း)</translation>
<translation id="4314815835985389558">စင့်á€á€ºá€€á€­á€¯ စီမံရန်</translation>
@@ -926,6 +951,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" /> သို့ရောက်ရှိရန် သင်á€á€»á€‰á€ºá€¸á€€á€•á€ºá€á€²á€·á€žá€Šá€ºáŠ သို့သော် ဆာဗာမှပြသသည့် အသိမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€ºá€¡á€¬á€¸ áŽá€„်းáလျှောက်á€á€„်သူမှ ရုá€á€ºá€žá€­á€™á€ºá€¸á€œá€­á€¯á€€á€ºá€žá€Šá€ºá‹ ဆိုလိုသည်မှာ ဆာဗာမှ ပြသသည့် လုံá€á€¼á€¯á€¶á€›á€±á€¸á€œá€»á€¾á€­á€¯á€·á€á€€á€º အá€á€»á€€á€ºá€™á€»á€¬á€¸á€™á€¾á€¬ လုံးá€á€™á€šá€¯á€¶á€€á€¼á€Šá€ºá€žá€„့်ပါዠသင်သည် á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€žá€°á€”ှင့်သာ ဆက်သွယ်ပါလိမ့်မည်á‹</translation>
<translation id="4378154925671717803">ဖုန်း</translation>
<translation id="4390472908992056574">အစွန်အနား</translation>
+<translation id="4406883609789734330">á€á€­á€¯á€€á€ºá€›á€­á€¯á€€á€ºá€…ာá€á€”်း</translation>
<translation id="4406896451731180161">ရှာဖွေမှု ရလဒ်များ</translation>
<translation id="4408413947728134509">ကွá€á€ºá€€á€®á€¸á€™á€»á€¬á€¸ <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">လှည့်ဖြားá€á€á€ºá€žá€±á€¬ á€á€˜á€ºá€†á€­á€¯á€€á€ºá€á€…်á€á€¯á€á€½á€„် သင့်စကားá€á€¾á€€á€ºá€€á€­á€¯ ထည့်လိုက်ပါသည်ዠ<ph name="WEBSITE_1" />አ<ph name="WEBSITE_2" />አ<ph name="WEBSITE_3" /> နှင့် ဤစကားá€á€¾á€€á€ºá€¡á€žá€¯á€¶á€¸á€•á€¼á€¯á€žá€Šá€·á€º အá€á€¼á€¬á€¸á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€žá€­á€¯á€·á€žá€½á€¬á€¸á€•á€¼á€®á€¸ áŽá€„်းကိုပြောင်းရန် Chrome က အကြံပြုပါသည်á‹</translation>
@@ -938,7 +964,6 @@
<translation id="4435702339979719576">ပို့စ်ကá€á€º)</translation>
<translation id="443673843213245140">ပရောက်စီ သုံးရန်ပိá€á€ºá€‘ားသော်လည်း á€á€­á€€á€»á€žá€Šá€ºá€· ပရောက်စီ စီစဉ်ဖွဲ့စည်းမှုကို သá€á€ºá€™á€¾á€á€ºá€‘ားသည်á‹</translation>
<translation id="4464826014807964867">သင့်အဖွဲ့အစည်းမှ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€•á€«á€á€„်သော á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸</translation>
-<translation id="4466881336512663640">ပုံစံ အပြောင်းအလဲများကို သိမ်းမည်မဟုá€á€ºá€•á€«á‹ ရှေ့ဆက်လိုသည်မှာ သေá€á€»á€¬á€žá€œá€¬á€¸á‹</translation>
<translation id="4476953670630786061">ဤဖောင်သည် မလုံá€á€¼á€¯á€¶á€•á€«á‹ 'အော်á€á€­á€¯á€–ြည့်' ကို ပိá€á€ºá€œá€­á€¯á€€á€ºá€•á€«á€•á€¼á€®á‹</translation>
<translation id="4477350412780666475">နောက်á€á€…်ပုဒ်</translation>
<translation id="4482953324121162758">ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€€á€­á€¯ ဘာသာပြန်မည် မဟုá€á€ºá€•á€«á‹</translation>
@@ -972,6 +997,7 @@
<translation id="4594403342090139922">&amp;ဖျက်မှုကို ပြန်လုပ်ရန်</translation>
<translation id="4597348597567598915">အရွယ်အစား áˆ</translation>
<translation id="4600854749408232102">C6/C5 (စာအိá€á€º)</translation>
+<translation id="4606870351894164739">အကျိုးသက်ရောက်မှု</translation>
<translation id="4628948037717959914">ဓာá€á€ºá€•á€¯á€¶</translation>
<translation id="4631649115723685955">ငွေပြန်ပေးá€á€¼á€„်းကို လင့်á€á€ºá€á€»á€­á€á€ºá€‘ားသည်</translation>
<translation id="4636930964841734540">အá€á€»á€€á€ºá€¡á€œá€€á€º</translation>
@@ -991,6 +1017,7 @@
<translation id="4691835149146451662">Architecture-A (စာအိá€á€º)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">ဘေး</translation>
+<translation id="4702656508969495934">'á€á€­á€¯á€€á€ºá€›á€­á€¯á€€á€ºá€…ာá€á€”်း' မြင်ရသည်አအထူးဖော်ပြရန် á€á€„်းဒိုးပြောင်းá€á€œá€¯á€á€º သုံးပါ</translation>
<translation id="4708268264240856090">သင့်á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯ ကြားá€á€„်စွá€á€ºá€–က်á€á€¼á€„်း á€á€¶á€á€²á€·á€›á€•á€«á€žá€Šá€º</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />á€á€„်းဒိုးကွန်ရက်ပြဿနာရှာဖွေမှု ပြုလုပ်ပါ<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> ရှာဖွေမှု အကြံပြုá€á€»á€€á€º</translation>
<translation id="4742407542027196863">စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸ စီမံရန်…</translation>
<translation id="4744603770635761495">အကောင်ထည်ဖော်နိုင်သည့် လမ်းကြောင်း</translation>
+<translation id="4749011317274908093">ရုပ်ဖျက်မုဒ်ကို သုံးနေပါသည်</translation>
<translation id="4750917950439032686">သင့်အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸ (ဥပမာ - စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸ သို့မဟုá€á€º á€á€›á€€á€ºá€á€…်ကá€á€ºá€”ံပါá€á€ºá€™á€»á€¬á€¸) ကို ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€žá€­á€¯á€· ပို့á€á€»á€­á€”်á€á€½á€„် လျှို့á€á€¾á€€á€ºá€žá€®á€¸á€žá€”့်အဖြစ် ထားရှိပါသည်á‹</translation>
<translation id="4756388243121344051">မှá€á€ºá€á€™á€ºá€¸</translation>
<translation id="4758311279753947758">ဆက်သွယ်ရန်အá€á€»á€€á€ºá€¡á€œá€€á€º ထည့်ရန်</translation>
@@ -1033,6 +1061,8 @@
<translation id="4813512666221746211">ကွန်ရက် ပြဿနာ</translation>
<translation id="4816492930507672669">စာမျက်နှာ ကွက်á€á€­ လုပ်ပေးရန်</translation>
<translation id="4819347708020428563">မှá€á€ºá€á€»á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ မူရင်းမြင်ကွင်းá€á€½á€„် á€á€Šá€ºá€¸á€–ြá€á€ºá€™á€œá€¬á€¸á‹</translation>
+<translation id="4825507807291741242">စွမ်းအားပြည့်</translation>
+<translation id="4838327282952368871">အိပ်မက်ဆန်ဆန်</translation>
<translation id="484462545196658690">အော်á€á€­á€¯</translation>
<translation id="4850886885716139402">မြင်ကွင်း</translation>
<translation id="485316830061041779">ဂျာမန်</translation>
@@ -1169,6 +1199,7 @@
<translation id="5314967030527622926">စာစောင် ပြုလုပ်စနစ်</translation>
<translation id="5316812925700871227">လက်á€á€²á€›á€…် လှည့်ရန်</translation>
<translation id="5317780077021120954">သိမ်းရန်</translation>
+<translation id="5321288445143113935">á€á€»á€²á€·á€‘ားသည်</translation>
<translation id="5323105697514565458"><ph name="NUM_MATCHES" /> အနက်မှ <ph name="FRIENDLY_MATCH_TEXT" />አ<ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">အဆက်အသွယ်အá€á€»á€€á€ºá€¡á€œá€€á€º ရွေးရန်</translation>
<translation id="5327248766486351172">အမည်</translation>
@@ -1176,11 +1207,13 @@
<translation id="5332219387342487447">ပစ္စည်းပို့ရန် နည်းလမ်း</translation>
<translation id="5333022057423422993">သင်သုံးလိုက်သောစကားá€á€¾á€€á€ºá€€á€­á€¯ ဒေá€á€¬á€€á€»á€­á€¯á€¸á€•á€±á€«á€€á€ºá€™á€¾á€¯á€á€½á€„် Chrome က á€á€½á€±á€·á€›á€¾á€­á€‘ားသည်ዠသင့်အကောင့်များ လုံá€á€¼á€¯á€¶á€…ေရန်အá€á€½á€€á€º သိမ်းထားသောစကားá€á€¾á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ စစ်ဆေးရန် အကြံပြုပါသည်á‹</translation>
<translation id="5334013548165032829">အသေးစိá€á€º စနစ် မှá€á€ºá€á€™á€ºá€¸á€™á€»á€¬á€¸</translation>
+<translation id="5334145288572353250">လိပ်စာ သိမ်းမလားá‹</translation>
<translation id="5340250774223869109">အပလီကေးရှင်းကို ပိá€á€ºá€‘ားသည်</translation>
<translation id="534295439873310000">NFC စက်များ</translation>
<translation id="5344579389779391559">ဤစာမျက်နှာသည် သင့်ထံမှ ငွေကောက်á€á€¶á€”ိုင်သည်</translation>
<translation id="5355557959165512791"><ph name="SITE" /> á အသိအမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€ºá€€á€­á€¯ ရုပ်သိမ်းထားသောကြောင့် áŽá€„်းအား လောလောဆယ် ဖွင့်áမရပါዠကွန်ရက်အမှားအယွင်းများနှင့် á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€™á€¾á€¯á€™á€»á€¬á€¸á€™á€¾á€¬ ပုံမှန်အားဖြင့် á€á€á€á€¬á€žá€¬ ဖြစ်သည့်အá€á€½á€€á€º ဤစာမျက်နှာကို နောက်ပိုင်းá€á€½á€„် ပြန်ဖွင့်áရနိုင်ပါသည်á‹</translation>
<translation id="536296301121032821">ပေါ်လစီ ကြိုá€á€„်á€á€»á€­á€”်ညှိá€á€»á€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ သိုလှောင်á€á€¼á€„်း မအောင်မြင်ပါ</translation>
+<translation id="5363309033720083897">သင့်စီမံá€á€”့်á€á€½á€²á€žá€°á€€ á€á€½á€„့်ပြုသော အစဉ်လိုက်ပို့á€á€º</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="5386426401304769735">ဤဆိုက်အá€á€½á€€á€º အသိအမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€ºá€€á€½á€„်းဆက်á€á€½á€„် SHA-1 ကို အသုံးပြုá လက်မှá€á€ºá€‘ိုးထားသည့် အသိအမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€ºá€á€…်စောင် ပါá€á€„်ပါသည်á‹</translation>
@@ -1189,6 +1222,7 @@
<translation id="5398772614898833570">ကြော်ငြာများကို ပိá€á€ºá€œá€­á€¯á€€á€ºá€•á€«á€•á€¼á€®</translation>
<translation id="5400836586163650660">မီးá€á€­á€¯á€¸</translation>
<translation id="540969355065856584">ဤဆာဗာသည် <ph name="DOMAIN" /> ဖြစ်ကြောင်း သက်သေမပြနိုင်ပါ; áŽá€„်းáလုံá€á€¼á€¯á€¶á€›á€±á€¸ အသိမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€ºá€žá€Šá€º ယá€á€¯á€¡á€á€»á€­á€”်á€á€½á€„် á€á€›á€¬á€¸á€™á€á€„်ပါዠဖွဲ့စည်းမှု အမှားကြောင့် သို့မဟုá€á€º á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€œá€­á€¯á€žá€°á€€ သင်áá€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€€á€­á€¯ ကြားဖြá€á€ºá€šá€°á€”ေá ထိုသို့ဖြစ်လာနိုင်á€á€²á€·á€•á€«á€žá€Šá€ºá‹</translation>
+<translation id="541143247543991491">Cloud (စနစ်á€á€…်á€á€¯á€œá€¯á€¶á€¸)</translation>
<translation id="541416427766103491">စီထည့်သည့်ပုံး á„</translation>
<translation id="5421136146218899937">ဘရောင်ဇာ ဒေá€á€¬á€€á€­á€¯ ရှင်းရန်...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> သည် သင့်ထံသို့ အကြောင်းကြားá€á€»á€€á€ºá€™á€»á€¬á€¸ ပို့လိုသည်</translation>
@@ -1202,6 +1236,7 @@
<translation id="5455374756549232013">ညံ့ဖျင်းသည့် မူá€á€«á€’ အá€á€»á€­á€”်ဖော်ပြá€á€»á€€á€º</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" />}other{<ph name="CONTACT_PREVIEW" /> နှင့် နောက်ထပ် <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
+<translation id="5463625433003343978">စက်များ ရှာနေသည်...</translation>
<translation id="5469868506864199649">အီá€á€œá€®</translation>
<translation id="5470861586879999274">&amp;á€á€Šá€ºá€¸á€–ြá€á€ºá€™á€¾á€¯ ပြန်လုပ်ရန်</translation>
<translation id="5478437291406423475">B6/C4 (စာအိá€á€º)</translation>
@@ -1251,7 +1286,6 @@
<translation id="5624120631404540903">စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ စီမံကွပ်ကဲရန်</translation>
<translation id="5629630648637658800">မူá€á€«á€’ ဆက်á€á€„်များကို á€á€„် မပေးနိုင်á€á€²á€·</translation>
<translation id="5631439013527180824">ကိရိယာ စီမံကွပ်ကဲရေး á€á€­á€¯á€€á€„် မမှန်</translation>
-<translation id="5632627355679805402">သင့်ဒေá€á€¬á€™á€»á€¬á€¸á€€á€­á€¯ သင်á <ph name="BEGIN_LINK" />Google စကားá€á€¾á€€á€º<ph name="END_LINK" />ဖြင့် <ph name="TIME" /> á€á€½á€„် အသွင်á€á€¾á€€á€ºá€‘ားပါသည်ዠစင့်á€á€ºá€…လုပ်ရန် áŽá€„်းကိုထည့်ပါá‹</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="5644090287519800334">ဘေး á ပုံ အလျားလိုက် အရွှေ့</translation>
@@ -1290,12 +1324,12 @@
<translation id="5785756445106461925">ထပ်မံáአဤစာမျက်နှာá€á€½á€„် လုံá€á€¼á€¯á€¶á€™á€¾á€¯ မရှိသော အá€á€¼á€¬á€¸á€™á€¾á€®á€„ြမ်းထားမှုများ ပါá€á€„်သည်ዠဤမှီငြမ်းထားမှုများအား ကြားကာလá€á€½á€„် အá€á€¼á€¬á€¸á€žá€°á€™á€»á€¬á€¸á€™á€¾ ကြည့်နိုင်ပြီး စာမျက်နှာá အသွင်အပြင်ကို ပြောင်းလဲရန် á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€žá€°á€™á€¾ ပြုပြင်နိုင်သည်á‹</translation>
<translation id="5786044859038896871">သင့်ကဒ်အá€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯ ဖြည့်သွင်းလိုပါသလားá‹</translation>
<translation id="578633867165174378">သင်သုံးလိုက်သောစကားá€á€¾á€€á€ºá€€á€­á€¯ ဒေá€á€¬á€€á€»á€­á€¯á€¸á€•á€±á€«á€€á€ºá€™á€¾á€¯á€á€½á€„် Chrome က á€á€½á€±á€·á€›á€¾á€­á€‘ားသည်ዠဤစကားá€á€¾á€€á€ºá€€á€­á€¯ ယá€á€¯á€•á€¼á€±á€¬á€„်းရန် အကြံပြုပါသည်á‹</translation>
-<translation id="5798290721819630480">အပြောင်းအလဲများ ဖယ်ပစ်မလားá‹</translation>
<translation id="5803412860119678065">သင့် <ph name="CARD_DETAIL" /> ကို ဖြည့်သွင်းလိုပါသလားá‹</translation>
<translation id="5804241973901381774">á€á€½á€„့်ပြုá€á€»á€€á€ºá€™á€»á€¬á€¸</translation>
<translation id="5804427196348435412">NFC စက်များ အသုံးပြုပါ</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> သို့ á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€¡á€¬á€¸ obsolete cipher suite á€á€…်á€á€¯ သုံးá လျှို့á€á€¾á€€á€ºá€¡á€žá€½á€„်ပြောင်းá€á€²á€·áá‹</translation>
<translation id="5813119285467412249">&amp;ထည့်ပေးမှု ပြန်လုပ်ရန်</translation>
+<translation id="5817918615728894473">á€á€½á€²á€á€»á€­á€á€ºá€•á€«</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ငွေပေးá€á€»á€±á€žá€Šá€·á€ºá€¡á€á€« ဤကá€á€ºá€€á€­á€¯ အသုံးပြုမည်ဖြစ်သော်လည်း áŽá€„်းáနံပါá€á€ºá€¡á€…စ်ကို ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€¡á€¬á€¸ မျှá€á€±á€™á€Šá€ºá€™á€Ÿá€¯á€á€ºá€•á€«á‹ အပိုဆောင်းလုံá€á€¼á€¯á€¶á€›á€±á€¸á€¡á€á€½á€€á€º ယာယီ CVC ကို ပြုလုပ်ပါမည်á‹}other{ငွေပေးá€á€»á€±á€žá€Šá€·á€ºá€¡á€á€« သင်ရွေးá€á€»á€šá€ºá€žá€Šá€·á€ºá€€á€á€ºá€€á€­á€¯ အသုံးပြုမည်ဖြစ်သော်လည်း áŽá€„်းáနံပါá€á€ºá€¡á€…စ်ကို ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€¡á€¬á€¸ မျှá€á€±á€™á€Šá€ºá€™á€Ÿá€¯á€á€ºá€•á€«á‹ အပိုဆောင်းလုံá€á€¼á€¯á€¶á€›á€±á€¸á€¡á€á€½á€€á€º ယာယီ CVC ကို ပြုလုပ်ပါမည်á‹}}</translation>
<translation id="5826507051599432481">á€á€°á€”ေသည့် အမည် (CN)</translation>
<translation id="5838278095973806738">á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€žá€°á€™á€»á€¬á€¸á€€ á€á€­á€¯á€¸á€šá€°á€”ိုင်သောကြောင့် ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá€á€½á€„် အရေးကြီးသော မည်သည့်အá€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯á€™á€»á€¾ မဖြည့်ပါနှင့် (ဥပမာ - စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸ သို့မဟုá€á€º á€á€›á€€á€ºá€’စ်ကá€á€º)á‹</translation>
@@ -1303,6 +1337,7 @@
<translation id="5855253129151731373">ဤá€á€˜á€ºá€†á€­á€¯á€€á€ºá အင်á€á€¬á€”က်လက်á€á€¶á€á€”်ဆောင်ပေးသူအမည်သည် <ph name="LOOKALIKE_DOMAIN" /> နှင့် ဆင်á€á€°á€žá€Šá€ºá‹ á€á€…်á€á€«á€á€…်ရံ á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€žá€°á€™á€»á€¬á€¸á€žá€Šá€º á€á€˜á€ºá€†á€­á€¯á€€á€ºá€¡á€…စ်ကို á€á€¯á€•á€›á€”် ဒိုမိန်းအမည်များအá€á€½á€„်း မြင်ရန်á€á€²á€šá€‰á€ºá€¸á€•á€¼á€®á€¸ သေးငယ်သည့် ပြောင်းလဲမှုများပြုကြသည်á‹
áŽá€„်းကို မှားယွင်းပြီး ပြသည်ဟု ယုံကြည်ပါက https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals သို့á€á€„်ကြည့်ပါá‹</translation>
+<translation id="5860033963881614850">ပိá€á€ºá€‘ား</translation>
<translation id="5862579898803147654">စီထည့်သည့်ပုံး áˆ</translation>
<translation id="5863847714970149516">ယá€á€¯á€–ွင့်á€á€±á€¬á€·á€™á€Šá€·á€º စာမျက်နှာသည် သင့်ထံမှ ငွေကောက်á€á€¶á€”ိုင်ပါသည်</translation>
<translation id="5866257070973731571">ဖုန်းနံပါá€á€º ထည့်á€á€¼á€„်း</translation>
@@ -1319,6 +1354,7 @@
<translation id="5913377024445952699">ဖန်သားပြင်ရိုက်ယူမှုကို á€á€á€›á€•á€ºá€œá€­á€¯á€€á€ºá€žá€Šá€º</translation>
<translation id="59174027418879706">ဖွင့်ထားသည်</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{á á€á€¯ အသုံးပြုနေသည်}other{# á€á€¯ အသုံးပြုနေသည်}}</translation>
<translation id="5921185718311485855">ဖွင့်ထားသည်</translation>
<translation id="5921639886840618607">ကá€á€ºá€€á€­á€¯ Google အကောင့်သို့ သိမ်းလိုပါသလားá‹</translation>
<translation id="5922853866070715753">ပြီးလုနီးပါပြီ</translation>
@@ -1338,6 +1374,7 @@
<translation id="5989320800837274978">သá€á€ºá€™á€¾á€á€º ပရောက်စီ ဆာဗာကိုáŽá€„်း .pac စာá€á€”်း URLကိုáŽá€„်း ဖေါ်ပြမပေးထားပါá‹</translation>
<translation id="5992691462791905444">အင်ဂျင်နီယာ Z ပုံစံ စာရွက်á€á€±á€«á€€á€ºá€›á€”်</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' အá€á€½á€€á€º ရလဒ် <ph name="RESULT_COUNT" /> á€á€¯</translation>
+<translation id="6006484371116297560">ဂန္ထá€á€„်</translation>
<translation id="6008122969617370890">N မှ á သို့ အစီအစဉ်</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">သင့်စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸ စစ်ဆေးá€á€¼á€„်း</translation>
@@ -1359,6 +1396,7 @@
<translation id="6045164183059402045">သá€á€ºá€™á€¾á€á€ºá€á€»á€€á€º နမူနာ ပုံစံ</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="6049004884579590341">မျက်နှာပြင်အပြည့်ဖွင့်á€á€¼á€„်းမှ ထွက်ရန် <ph name="ACCELERATOR" /> ကို နှိပ်ထားပါ</translation>
<translation id="6049488691372270142">စာမျက်နှာ ပေးပို့မှု</translation>
<translation id="6051221802930200923"><ph name="SITE" /> သည် အသိအမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€ºá€á€¯á€•á€á€¼á€„်းအား á€á€¯á€á€¶á€€á€¬á€€á€½á€šá€ºá€žá€Šá€·á€ºá€…နစ်ကို အသုံးပြုထားသောကြောင့် áŽá€„်းအား လောလောဆယ် ဖွင့်áမရပါዠကွန်ရက်အမှားအယွင်းများနှင့် á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€™á€¾á€¯á€™á€»á€¬á€¸á€™á€¾á€¬ ပုံမှန်အားဖြင့် á€á€á€á€¬á€žá€¬ ဖြစ်သည့်အá€á€½á€€á€º ဤစာမျက်နှာကို နောက်ပိုင်းá€á€½á€„် ပြန်ဖွင့်áရနိုင်ပါသည်á‹</translation>
<translation id="6051898664905071243">စာမျက်နှာအရေအá€á€½á€€á€º-</translation>
@@ -1375,6 +1413,7 @@
<translation id="610911394827799129">သင်á Google အကောင့်က ဖွင့်ကြည့်ထားသော မှá€á€ºá€á€™á€ºá€¸á€žá€Šá€º <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> á€á€½á€„် အá€á€¼á€¬á€¸á€•á€¯á€¶á€…ံများဖြင့် ရှိနေနိုင်ပါသည်</translation>
<translation id="6116338172782435947">ကလစ်ဘုá€á€ºá€žá€­á€¯á€· မိá€á€¹á€á€°á€€á€°á€¸á€‘ားသည့် စာသားနှင့် ပုံများအား ကြည့်ရန်</translation>
<translation id="6120179357481664955">သင့် UPI ID ကို မှá€á€ºá€™á€­á€•á€«á€žá€œá€¬á€¸á‹</translation>
+<translation id="6123290840358279103">ပကá€á€­á€¡á€žá€½á€„်ကá€á€º ကြည့်ရန်</translation>
<translation id="6124432979022149706">Chrome လုပ်ငန်းသုံး á€á€»á€­á€á€ºá€†á€€á€ºá€žá€Šá€ºá€·á€€á€­á€›á€­á€šá€¬á€™á€»á€¬á€¸</translation>
<translation id="6146055958333702838">သင်အသုံးပြုနေသည့် ရောက်á€á€¬á€™á€»á€¬á€¸áŠ မိုဒမ်းများአသို့မဟုá€á€º အá€á€¼á€¬á€¸á€€á€½á€”်ယက်စက်ပစ္စည်းများနှင့် ကြိုးများကို စစ်ဆေးပါá‹</translation>
<translation id="614940544461990577">စမ်းကြည့်ပါ −</translation>
@@ -1410,6 +1449,7 @@
<translation id="6289939620939689042">စာမျက်နှာ အရောင်</translation>
<translation id="6290238015253830360">သင်အကြံပြုထားသည့် ဆောင်းပါးများ ဤနေရာá€á€½á€„် ပေါ်ပါမည်</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC-</translation>
<translation id="6302269476990306341">Chrome အá€á€½á€„်းရှိ Google Assistant ရပ်á€á€”့်နေသည်</translation>
<translation id="6305205051461490394"><ph name="URL" /> ကိုဆက်သွယ်áမရနိုင်ပါá‹</translation>
<translation id="6312113039770857350">á€á€˜á€ºá€…ာမျက်နှာ မရှိ</translation>
@@ -1435,6 +1475,7 @@
<translation id="6390200185239044127">Z ပုံစံ á€á€…်á€á€€á€ºá€á€±á€«á€€á€ºá€›á€”်</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> မှ ဤနေရာသို့ ကူးထည့်á€á€¼á€„်းကို စီမံá€á€”့်á€á€½á€²á€žá€°á€™á€°á€á€«á€’က ပိá€á€ºá€‘ားသည်</translation>
+<translation id="6398765197997659313">မျက်နှာပြင် အပြည့်မှ ထွက်ရန်</translation>
<translation id="6401136357288658127">ဤမူá€á€«á€’ကို ဆက်မသုံးá€á€±á€¬á€·á€•á€«á‹ áŽá€„်းအစား <ph name="NEW_POLICY" /> မူá€á€«á€’ကို အသုံးပြုရပါမည်á‹</translation>
<translation id="6404511346730675251">စာညှပ် á€á€Šá€ºá€¸á€–ြá€á€ºá€›á€”်</translation>
<translation id="6406765186087300643">C0 (စာအိá€á€º)</translation>
@@ -1447,7 +1488,6 @@
<translation id="6428450836711225518">သင်áဖုန်းနံပါá€á€ºá€€á€­á€¯ အá€á€Šá€ºá€•á€¼á€¯á€•á€«</translation>
<translation id="6433490469411711332">အဆက်အသွယ်အá€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯ á€á€Šá€ºá€¸á€–ြá€á€ºá€•á€«</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> သည်á€á€»á€­á€á€ºá€†á€€á€ºá€›á€”် ငြင်းပယ်á€á€²á€·á€žá€Šá€ºá‹</translation>
-<translation id="6434309073475700221">စွန့်ပစ်ရန်</translation>
<translation id="6440503408713884761">လျစ်လျူရှုထားသည်</translation>
<translation id="6443406338865242315">သင်ထည့်သွင်းထားသည့် နောက်ဆက်á€á€½á€²á€”ှင့် ပလá€á€ºá€¡á€„်များ</translation>
<translation id="6446163441502663861">Kahu (စာအိá€á€º)</translation>
@@ -1490,6 +1530,7 @@
<translation id="6624427990725312378">အဆက်အသွယ် အá€á€»á€€á€ºá€¡á€œá€€á€º</translation>
<translation id="6626291197371920147">မှန်ကန်သည့် ကá€á€ºá€”ံပါá€á€ºá€€á€­á€¯ ထည့်ပါ</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ရှာဖွေမှု</translation>
+<translation id="6630043285902923878">USB စက်များ ရှာနေသည်...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ရှင်းရန်</translation>
@@ -1505,6 +1546,7 @@
<translation id="6671697161687535275">Chromium ထဲမှ ပုံစံအကြံပြုá€á€»á€€á€ºá€€á€­á€¯ ဖယ်ရှားရမလားá‹</translation>
<translation id="6685834062052613830">ထွက်ပြီး စနစ်ထည့်သွင်းမှု ပြီးမြောက်စေပါ</translation>
<translation id="6687335167692595844">ဖောင့်အရွယ်အစား á€á€±á€¬á€„်းဆိုထားသည်</translation>
+<translation id="6688743156324860098">အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€›á€”်…</translation>
<translation id="6689249931105087298">အနက်ရောင်အမှá€á€º အá€á€»á€­á€¯á€„့်နှင့် အညီ</translation>
<translation id="6689271823431384964">လက်မှá€á€ºá€‘ိုးá€á€„်ထားသဖြင့် သင်áကá€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ သင့် Google အကောင့်á€á€½á€„် သိမ်းရန် Chrome က ကမ်းလှမ်းထားပါသည်ዠဤလုပ်ဆောင်ပုံကို ဆက်á€á€„်များá€á€½á€„် ပြောင်းနိုင်သည်ዠကá€á€ºá€€á€­á€¯á€„်ဆောင်သူ အမည်ကို သင့်အကောင့်မှ ရရှိပါသည်á‹</translation>
<translation id="6698381487523150993">ဖန်á€á€®á€¸á€á€²á€·:</translation>
@@ -1520,6 +1562,7 @@
<translation id="6744009308914054259">á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€€á€­á€¯ စောင့်နေစဉ် အော့ဖ်လိုင်းဆောင်းပါးများကို ဖá€á€ºá€›á€”် 'ဒေါင်းလုဒ်များ' သို့ သွားနိုင်သည်á‹</translation>
<translation id="6753269504797312559">ပေါ်လစီá€á€”်ဖိုး</translation>
<translation id="6757797048963528358">သင့်စက်ပစ္စည်း အိပ်ပျော်သွားပါသည်á‹</translation>
+<translation id="6767985426384634228">လိပ်စာ အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€™á€œá€¬á€¸á‹</translation>
<translation id="6768213884286397650">ဟာဂကိ (ပို့စ်ကá€á€º)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">á€á€›á€™á€ºá€¸á€•á€¼á€¬</translation>
@@ -1542,6 +1585,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">ဤစာမျက်နှာကို ပိုမိုလွယ်ကူစွာဖá€á€ºá€”ိုင်ရန် Chrome က ရိုးရှင်းအောင်ပြုလုပ်ထားသည်ዠChrome သည် မူရင်းစာမျက်နှာကို လုံá€á€¼á€¯á€¶á€™á€¾á€¯á€™á€›á€¾á€­á€žá€Šá€ºá€· á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€™á€¾á€á€…်ဆင့် ရယူထားသည်á‹</translation>
<translation id="6891596781022320156">မူá€á€«á€’ အဆင့်ကို ပံ့ပိုးမထားပါá‹</translation>
+<translation id="6895143722905299846">ပကá€á€­á€¡á€žá€½á€„် နံပါá€á€º-</translation>
<translation id="6895330447102777224">သင့်ကဒ်ကို အá€á€Šá€ºá€•á€¼á€¯á€•á€¼á€®á€¸á€•á€«á€•á€¼á€®</translation>
<translation id="6897140037006041989">အသုံးပြုသူ ကိုယ်စားလှယ်</translation>
<translation id="6898699227549475383">အဖွဲ့အစည်း (O)</translation>
@@ -1577,10 +1621,10 @@
<translation id="7004583254764674281">ကá€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ပိုမိုမြန်ဆန်စွာ အá€á€Šá€ºá€•á€¼á€¯á€”ိုင်ရန် Windows Hello ကို အသုံးပြုပါ</translation>
<translation id="7006930604109697472">မည်သို့ပင်ဖြစ်စေ ပို့ရန်</translation>
<translation id="7012363358306927923">á€á€›á€¯á€á€º UnionPay</translation>
-<translation id="7012404007611495949">အရွယ်အစားပြန်ပြုပြင်ရန် ဆက်á€á€„်များ</translation>
<translation id="7014741021609395734">ဇူးမ်အဆင့်</translation>
<translation id="7016992613359344582">ဤငွေကောက်á€á€¶á€™á€¾á€¯á€™á€»á€¬á€¸á€žá€Šá€º á€á€…်á€á€»á€­á€”်á€á€…်á€á€«á€á€Šá€ºá€¸ ဖြစ်နိုင်သလို ထပ်á€á€œá€²á€œá€²á€€á€±á€¬á€€á€ºá€á€¶á€™á€¾á€¯á€œá€Šá€ºá€¸ ဖြစ်နိုင်ပြီး သိသာမှုမရှိနိုင်ပါá‹</translation>
<translation id="7029809446516969842">စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸</translation>
+<translation id="7030436163253143341">အသိအမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€º မမှန်ကန်ပါ</translation>
<translation id="7031646650991750659">မည်သည့် Google Play အက်ပ်များကို သင်ထည့်သွင်းထားပါသလဲ</translation>
<translation id="7050187094878475250">သင် <ph name="DOMAIN" /> သို့ ရောက်ရန် ကြိုးပမ်းá€á€²á€·á€žá€±á€¬á€ºá€œá€Šá€ºá€¸áŠ ယုံကြည်နိုင်ရန်အလို့ငှာ ကာလလွန်စွာကြာမြင့်သော á€á€½á€„့်ပြုကာလပါသည့် အသိအမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€ºá€á€…်á€á€¯á€¡á€¬á€¸ ဆာဗာမှ ပြသá€á€²á€·á€žá€Šá€ºá‹</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ဤကá€á€ºá€€á€­á€¯ ယá€á€¯á€žá€­á€™á€ºá€¸á မရပါ}other{ဤကá€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ယá€á€¯á€žá€­á€™á€ºá€¸á မရပါ}}</translation>
@@ -1651,12 +1695,14 @@
<translation id="7300012071106347854">ကိုဗော့အပြာ</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">မြင့်သော</translation>
+<translation id="7305756307268530424">ဂိမ်းအနှေး စá€á€„်ရန်</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯ အကူအညီ</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" ကá€á€¹á€á€€á€­á€¯ á€á€¾á€€á€ºá€›á€”်</translation>
<translation id="733354035281974745">ကိရိယာá€á€½á€„်း အကောင့်ကို အစားထိုးရန်</translation>
<translation id="7333654844024768166">လှည့်ဖြားá€á€á€ºá€žá€±á€¬ á€á€˜á€ºá€†á€­á€¯á€€á€ºá€á€…်á€á€¯á€á€½á€„် သင့်စကားá€á€¾á€€á€ºá€€á€­á€¯ ထည့်လိုက်ပါသည်ዠ<ph name="WEBSITE_1" />አ<ph name="WEBSITE_2" />አ<ph name="WEBSITE_3" /> နှင့် ဤစကားá€á€¾á€€á€ºá€¡á€žá€¯á€¶á€¸á€•á€¼á€¯á€žá€Šá€·á€º အá€á€¼á€¬á€¸á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€žá€­á€¯á€·á€žá€½á€¬á€¸á€•á€¼á€®á€¸ áŽá€„်းကိုပြောင်းရန် Chromium က အကြံပြုပါသည်á‹</translation>
<translation id="7334320624316649418">&amp;ပြန်စီမှုကို ပြန်လုပ်ရန်</translation>
+<translation id="7337248890521463931">စာကြောင်းပိုပြရန်</translation>
<translation id="7337706099755338005">သင်အသုံးပြုနေသည့်စနစ်အá€á€½á€€á€º မရနိုင်ပါá‹</translation>
<translation id="733923710415886693">ဆာဗာáအသိအမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€ºá€€á€­á€¯ အသိအမှá€á€ºá€•á€¼á€¯á€œá€€á€ºá€™á€¾á€á€ºá€•á€½á€„့်လင်းမြင်သာရှိမှုမှá€á€…်ဆင့် ဖော်ပြထားá€á€¼á€„်း မရှိပါá‹</translation>
<translation id="734600844861828519">ááxáá…</translation>
@@ -1664,6 +1710,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">ညွှန်ကြားá€á€»á€€á€º လိုင်း</translation>
<translation id="7359588939039777303">ကြော်ငြာများကို ပိá€á€ºá€œá€­á€¯á€€á€ºá€•á€«á€•á€¼á€®á‹</translation>
+<translation id="7363096869660964304">သို့သော် သင့်ကိုမြင်ရနိုင်သည်ዠရုပ်ဖျက်မုဒ်သုံးá€á€¼á€„်းဖြင့် သင့်အလုပ်ရှင်አအင်á€á€¬á€”က်á€á€”်ဆောင်မှုပေးသူ (သို့) á€á€„်ကြည့်သော á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€‘ံမှ သင်áကြည့်ရှုမှုကို ဖျောက်ထားáမရပါá‹</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />አChrome ဆက်á€á€„်များá€á€½á€„် လိပ်စာများ ထည့်ရန်နှင့် စီမံရန် ‘á€á€˜á€ºá€á€œá€¯á€á€ºâ€™ နှိပ်ပြီးနောက် Enter နှိပ်ပါ</translation>
<translation id="7365849542400970216">သင်á ကိရိယာအသုံးပြုမှုကို သိသလားá‹</translation>
<translation id="7372973238305370288">ရှာဖွေá€á€¼á€„်းရလာဒ်</translation>
@@ -1674,7 +1721,9 @@
<translation id="7378594059915113390">မီဒီယာ ထိန်းá€á€»á€¯á€•á€ºá€™á€¾á€¯á€™á€»á€¬á€¸</translation>
<translation id="7378627244592794276">မဟုá€á€ºá€•á€«</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">မသက်ဆိုင်ပါ</translation>
<translation id="7390545607259442187">ကဒ်ကို အá€á€Šá€ºá€•á€¼á€¯á€•á€«</translation>
+<translation id="7392089738299859607">လိပ်စာ အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€•á€«</translation>
<translation id="7399802613464275309">လုံá€á€¼á€¯á€¶á€›á€±á€¸ စစ်ဆေးမှု</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">သင်á <ph name="DEVICE_NAME" /> ကို စီမံá€á€”့်á€á€½á€²á€‘ားပါသည်</translation>
@@ -1689,6 +1738,7 @@
&lt;li&gt;&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome ကူညီရေးရာ ဌာန&lt;/a&gt; သို့á€á€„်ပြီး သင့်ကွန်ပျူá€á€¬á€‘ဲမှနေá ဆော့ဖ်á€á€²á€€á€­á€¯ မည်ကဲ့သို့ အပြီးအပိုင် ဖယ်ရှားနိုင်ကြောင်း လေ့လာပါ
&lt;/ol&gt;</translation>
<translation id="741007362987735528">အကျယ် ပုံစံ</translation>
+<translation id="7410471291937727359">á€á€»á€…်စဖွယ်</translation>
<translation id="7416351320495623771">စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸ စီမံရန်…</translation>
<translation id="7419106976560586862">ပရိုဖိုင် လမ်းကြောင်း</translation>
<translation id="7437289804838430631">အဆက်အသွယ် အá€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯ ထည့်ရန်</translation>
@@ -1704,7 +1754,7 @@
<translation id="7481312909269577407">ရှေ့သို့</translation>
<translation id="7485870689360869515">ဒေá€á€¬ မá€á€½á€±á€·á€›á€•á€«á‹</translation>
<translation id="7495528107193238112">ဤအကြောင်းအရာကို ပိá€á€ºá€‘ားသည်ዠပြဿနာကို ဖြေရှင်းရန် á€á€˜á€ºá€†á€­á€¯á€€á€ºá€•á€­á€¯á€„်ရှင်ကို ဆက်သွယ်ပါá‹</translation>
-<translation id="7498234416455752244">ဆက်လက်á€á€Šá€ºá€¸á€–ြá€á€ºá€›á€”်</translation>
+<translation id="7498193950643227031">အရွယ်အစားပြန်ပြင်လျှင် မျှော်လင့်မထားသည့် အမှားအယွင်းများ ရှိနိုင်သည်ዠ<ph name="SETTINGS" /> á€á€½á€„် အက်ပ်များ အရွယ်အစားပြန်ပြင်နိုင်မှုကို ကန့်သá€á€ºá€”ိုင်ပါပြီá‹</translation>
<translation id="7503664977220660814">လှည့်ဖြားá€á€á€ºá€žá€±á€¬ á€á€˜á€ºá€†á€­á€¯á€€á€ºá€á€…်á€á€¯á€á€½á€„် သင့်စကားá€á€¾á€€á€ºá€€á€­á€¯ ထည့်လိုက်ပါသည်ዠယá€á€¯ ဤစကားá€á€¾á€€á€ºá€€á€­á€¯ သင်အသုံးပြုထားသည့် <ph name="WEBSITE_1" />አ<ph name="WEBSITE_2" /> နှင့် အá€á€¼á€¬á€¸á€žá€±á€¬á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€¡á€á€½á€€á€º သင်သိမ်းဆည်းထားသည့် စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ စစ်ဆေးရန် Chromium က အကြံပြုသည်á‹</translation>
<translation id="7508255263130623398">ပစ္စည်းပြန်ပို့နိုင်သည့် မူá€á€«á€’ဆိုင်ရာကိရိယာအိုင်ဒီသည် ကွက်လပ်ဖြစ်နေပါသည် သို့မဟုá€á€º လက်ရှိကိရိယာအိုင်ဒီနှင့် ကိုက်ညီမှုမရှိပါ</translation>
<translation id="7508870219247277067">ထောပá€á€ºá€žá€®á€¸á€…ိမ်း</translation>
@@ -1724,6 +1774,7 @@
<translation id="7548892272833184391">á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯ အမှားများကို ပြုပြင်ရန်</translation>
<translation id="7549584377607005141">á€á€€á€ºá€˜á€ºá€…ာမျက်နှာသည် မှန်ကန်စွာ ဖော်ပြနိုင်ရန် သင်စောစောပိုင်းá€á€½á€„် ရိုက်ထည့်ထားသည့် အá€á€»á€€á€ºá€œá€€á€ºá€™á€»á€¬á€¸á€œá€­á€¯á€¡á€•á€ºá€•á€«á€žá€Šá€ºá‹ သင်ဤအá€á€»á€€á€ºá€œá€€á€ºá€€á€­á€¯ ပြန်လည် ပို့နိုင်ပါသည်አသို့သော် ဤသို့ပြုလုပ်á€á€¼á€„်းအားဖြင့် ဤစာမျက်နှာမှ ယá€á€„်လုပ်ဆောင်á€á€²á€·á€žá€Šá€·á€º အá€á€­á€¯á€„်းပြန်လည် လုပ်ဆောင်မည် ဖြစ်သည်á‹</translation>
<translation id="7550637293666041147">သင်á စက်အသုံးပြုသူအမည်နှင့် Chrome အသုံးပြုသူအမည်</translation>
+<translation id="755279583747225797">အစမ်းသုံးနေသည်</translation>
<translation id="7552846755917812628">အောက်ပါ နည်းလမ်းများကို စမ်းကြည့်ပါ−</translation>
<translation id="7554475479213504905">မည်သို့ပင်ဖြစ်စေ ပြန်လည်စá€á€„်ပြီး ပြရန်</translation>
<translation id="7554791636758816595">á€á€˜á€º အသစ်</translation>
@@ -1742,7 +1793,6 @@
<translation id="7610193165460212391">á€á€”်ဖိုးမှာ ဘောင် အပြင်မှာ ရှိနေ<ph name="VALUE" />á‹</translation>
<translation id="7613889955535752492">ကုန်ဆုံးရက် − <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />አChrome ဆက်á€á€„်များရှိ သင့်စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ကြည့်ရှုရန်နှင့် စီမံရန် Tab နှိပ်ပြီးနောက် Enter နှိပ်ပါ</translation>
-<translation id="7615602087246926389">Google အကောင့်လျှို့á€á€¾á€€á€ºá€…ကားလုံး အá€á€¼á€¬á€¸á€—ားရှင်းဖြင့် လုံá€á€¼á€¯á€¶á€¡á€±á€¬á€„်ပြုလုပ်ထားသည့် ဒေá€á€¬á€™á€»á€¬á€¸á€žá€„့်á€á€½á€„် ရှိပြီးဖြစ်သည်ዠကျေးဇူးပြုá áŽá€„်းအားအောက်á€á€½á€„်ဖြည့်ပါá‹</translation>
<translation id="7616645509853975347">သင်áစီမံá€á€”့်á€á€½á€²á€žá€°á€€ သင့်ဘရောင်ဇာá€á€½á€„် Chrome Enterprise Connectors ကို ဖွင့်ထားသည်ዠဤá€á€»á€­á€á€ºá€†á€€á€ºá€…နစ်များက သင့်ဒေá€á€¬á€¡á€á€»á€­á€¯á€·á€€á€­á€¯ á€á€„်သုံးá€á€½á€„့်ရှိသည်á‹</translation>
<translation id="7619838219691048931">အဆုံးသá€á€º စာမျက်နှာ</translation>
<translation id="762844065391966283">á€á€…်ကြိမ်လျှင် á€á€…်á€á€¯</translation>
@@ -1807,13 +1857,12 @@
<translation id="782886543891417279">သင်အသုံးပြုနေသော Wi-Fi ( <ph name="WIFI_NAME" /> ) á login စာမျက်နှာသို့ သင်သွားရောက်ကြည့်ရှုရန် လိုမည်á‹</translation>
<translation id="7836231406687464395">Postfix (စာအိá€á€º)</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>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ဖိုင်များကို ဖိုင်အမျိုးအစား ဆက်နွှယ်မှုများဖြင့် ဖွင့်လိုသည်á‹</translation>
<translation id="7862185352068345852">á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€¾ ထွက်လိုပါသလားá‹</translation>
<translation id="7865448901209910068">အကောင်းဆုံးမြန်နှုန်း</translation>
<translation id="7874263914261512992">လှည့်ဖြားá€á€á€ºá€žá€±á€¬ á€á€˜á€ºá€†á€­á€¯á€€á€ºá€á€…်á€á€¯á€á€½á€„် သင့်စကားá€á€¾á€€á€ºá€€á€­á€¯ ထည့်လိုက်ပါသည်ዠယá€á€¯ ဤစကားá€á€¾á€€á€ºá€€á€­á€¯ သင်အသုံးပြုထားသည့် <ph name="WEBSITE_1" />አ<ph name="WEBSITE_2" /> နှင့် အá€á€¼á€¬á€¸á€žá€±á€¬á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€¡á€á€½á€€á€º သင်သိမ်းဆည်းထားသည့် စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ စစ်ဆေးရန် Chrome က အကြံပြုသည်á‹</translation>
<translation id="7878562273885520351">သင့်စကားá€á€¾á€€á€º အá€á€­á€¯á€¸á€á€¶á€‘ားရနိုင်သည်</translation>
+<translation id="7880146494886811634">လိပ်စာ သိမ်းပါ</translation>
<translation id="7882421473871500483">အညို</translation>
<translation id="7887683347370398519">သင့် CVC အားစစ်ဆေးပြီး ထပ်မံကြိုးစားပါ</translation>
<translation id="7887885240995164102">á€á€…်á€á€¯á€•á€±á€«á€ºá€á€…်á€á€¯á€‘ပ်á ဖွင့်သည့်မုဒ်သို့ á€á€„်ရန်</translation>
@@ -1821,6 +1870,7 @@
<translation id="7894280532028510793">စာလုံးပေါင်း မှန်ကန်ပါက <ph name="BEGIN_LINK" />ကွန်ရက် အမှားရှာဖွေမှုများပြုလုပ်ရန် ကြိုးစားကြည့်ပါ<ph name="END_LINK" />á‹</translation>
<translation id="7904208859782148177">C3 (စာအိá€á€º)</translation>
<translation id="7931318309563332511">အမျိုးအမည်မသိ</translation>
+<translation id="793209273132572360">လိပ်စာ အပ်ဒိá€á€ºá€œá€¯á€•á€ºá€™á€œá€¬á€¸á‹</translation>
<translation id="7932579305932748336">အလွှာအုပ်ရန်</translation>
<translation id="79338296614623784">မှန်ကန်သောဖုန်းနံပါá€á€ºá€€á€­á€¯ ထည့်ပါ</translation>
<translation id="7934052535022478634">ငွေပေးá€á€»á€±á€™á€¾á€¯ ပြီးစီးပါပြီ</translation>
@@ -1891,6 +1941,7 @@
<translation id="8175796834047840627">လက်မှá€á€ºá€‘ိုးá€á€„်ထားသဖြင့် သင်á ကá€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ သင့် Google အကောင့်á€á€½á€„် သိမ်းရန် Chrome က ကမ်းလှမ်းထားပါသည်ዠဤလုပ်ဆောင်ပုံကို ဆက်á€á€„်များá€á€½á€„် ပြောင်းနိုင်သည်á‹</translation>
<translation id="8176440868214972690">ဤစက်စီမံá€á€”့်á€á€½á€²á€žá€°á€žá€Šá€º ဆက်á€á€„်များ (သို့) မူá€á€«á€’များကဲ့သို့ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€¡á€á€»á€­á€¯á€·á€€á€­á€¯ အောက်ပါá€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€žá€­á€¯á€· ပို့လိုက်သည်á‹</translation>
<translation id="8184538546369750125">အထွေထွေ ပုံသေကို သုံးရန် (á€á€½á€„့်ပြုရန်)</translation>
+<translation id="8193086767630290324">လျှို့á€á€¾á€€á€ºá€¡á€–ြစ် အလံပြထားသော ဒေá€á€¬á€¡á€á€½á€€á€º လုပ်ဆောင်á€á€»á€€á€ºá€™á€»á€¬á€¸</translation>
<translation id="8194797478851900357">&amp;ရွေ့ရှားမှုကို á€á€…်ဆင့်နောက်ပြန်ရန်</translation>
<translation id="8201077131113104583">ID "<ph name="EXTENSION_ID" />" á€á€­á€¯á€¸á€á€»á€²á€·á€œá€­á€¯á€„်းအá€á€½á€€á€º အဆင့်မြှင့်ထားသော URL သည် သုံးမရပါá‹</translation>
<translation id="8202097416529803614">မှာယူမှု စုစုပေါင်း</translation>
@@ -1913,6 +1964,7 @@
<translation id="8249296373107784235">မလုပ်á€á€±á€¬á€·á€•á€«</translation>
<translation id="8249320324621329438">နောက်ဆုံး ရယူá€á€²á€·:</translation>
<translation id="8253091569723639551">ငွေá€á€±á€¬á€„်းá€á€¶á€œá€½á€¾á€¬á€•á€­á€¯á€·á€›á€”် လိပ်စာ လိုအပ်ပါသည်</translation>
+<translation id="8257387598443225809">ဤအက်ပ်ကို မိုဘိုင်းအá€á€½á€€á€º ထုá€á€ºá€œá€¯á€•á€ºá€‘ားသည်</translation>
<translation id="825929999321470778">သိမ်းထားသော စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸á€œá€¯á€¶á€¸á€€á€­á€¯ ပြá€á€¼á€„်း</translation>
<translation id="8261506727792406068">ဖျက်ရန်</translation>
<translation id="8262952874573525464">အောက်á€á€¼á€±á€¡á€…ွန်းá€á€½á€„် အပ်á€á€»á€Šá€ºá€–ြင့်á€á€»á€¯á€•á€ºá€›á€”်</translation>
@@ -2036,7 +2088,6 @@
<translation id="8719528812645237045">ထိပ်á€á€½á€„် အများအပြားဖောက်ရန်</translation>
<translation id="8725066075913043281">ထပ် စမ်းကြည့်ရန်</translation>
<translation id="8726549941689275341">စာမျက်နှာ အရွယ်အစား-</translation>
-<translation id="8728672262656704056">ရုပ်ဖျက်မုဒ်ကို သုံးနေပါသည်</translation>
<translation id="8730621377337864115">ပြီးပါပြီ</translation>
<translation id="8731544501227493793">စကားá€á€¾á€€á€ºá€…ီမံရန်á€á€œá€¯á€á€ºáŠ သင့်စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ Chrome ဆက်á€á€„်များá€á€½á€„် ကြည့်ရှုရန်နှင့် စီမံရန် Enter နှိပ်ပါ</translation>
<translation id="8734529307927223492">သင်á <ph name="DEVICE_TYPE" /> ကို <ph name="MANAGER" /> က စီမံá€á€”့်á€á€½á€²á€žá€Šá€º</translation>
@@ -2113,6 +2164,7 @@
<translation id="9020542370529661692">ဒီစာမျက်နှာကို <ph name="TARGET_LANGUAGE" />သို့ ဘာသာပြန်ပေးá€á€²á€·á€žá€Šá€ºá‹</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(မမှန်ပါ)</translation>
+<translation id="9030265603405983977">အဖြူအမည်း</translation>
<translation id="9035022520814077154">လုံá€á€¼á€¯á€¶á€™á€¾á€¯ အမှား</translation>
<translation id="9038649477754266430">စာမျက်နှာများကို ပိုမိုမြန်ဆန်စွာ ဖွင့်နိုင်ရန် ကြိုá€á€„်á€á€”့်မှန်းá€á€¼á€„်း á€á€”်ဆောင်မှုကို အသုံးပြုပါ</translation>
<translation id="9039213469156557790">ထပ်မံáአဤစာမျက်နှာá€á€½á€„် လုံá€á€¼á€¯á€¶á€™á€¾á€¯ မရှိသော အá€á€¼á€¬á€¸á€™á€¾á€®á€„ြမ်းထားမှုများ ပါá€á€„်သည်ዠဤမှီငြမ်းထားမှုများအား ကြားကာလá€á€½á€„် အá€á€¼á€¬á€¸á€žá€°á€™á€»á€¬á€¸á€™á€¾ ကြည့်နိုင်ပြီး စာမျက်နှာá အမူအကျင့်ကို ပြောင်းလဲရန် á€á€­á€¯á€€á€ºá€á€­á€¯á€€á€ºá€žá€°á€™á€¾ ပြုပြင်နိုင်သည်á‹</translation>
@@ -2136,6 +2188,7 @@
<translation id="91108059142052966">လျှို့á€á€¾á€€á€ºá€¡á€€á€¼á€±á€¬á€„်းအရာများကို မြင်နိုင်á€á€»á€­á€”်á€á€½á€„် <ph name="APPLICATION_TITLE" /> အား မျက်နှာပြင်မျှá€á€±á€á€¼á€„်းကို စီမံá€á€”့်á€á€½á€²á€žá€°á€™á€°á€á€«á€’က ပိá€á€ºá€‘ားသည်</translation>
<translation id="9114524666733003316">ကá€á€º အá€á€Šá€ºá€•á€¼á€¯á€”ေသည်...</translation>
<translation id="9114581008513152754">ဤဘရောင်ဇာကို ကုမ္ပá€á€® သို့မဟုá€á€º အá€á€¼á€¬á€¸á€¡á€–ွဲ့အစည်းက စီမံá€á€”့်á€á€½á€²á€™á€‘ားပါዠဤစက်ပေါ်ရှိ လုပ်ဆောင်á€á€»á€€á€ºá€€á€­á€¯ Chrome ပြင်ပမှ စီမံá€á€”့်á€á€½á€²á€‘ားá€á€¼á€„်း ဖြစ်နိုင်သည်ዠ<ph name="BEGIN_LINK" />ပိုမိုလေ့လာရန်<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">လန်းလန်းဆန်းဆန်း</translation>
<translation id="9119042192571987207">အပ်လုဒ်လုပ်ပြီးပြီ</translation>
<translation id="9128016270925453879">မူá€á€«á€’များကို ဖွင့်လိုက်သည်</translation>
<translation id="9128870381267983090">ကွန်ယက်သို့ á€á€»á€­á€á€ºá€†á€€á€ºá€•á€«</translation>
@@ -2154,6 +2207,7 @@
<translation id="9170848237812810038">&amp;á€á€…်ဆင့်နောက်ပြန်ရန်</translation>
<translation id="9171296965991013597">အက်ပ်မှ ထွက်လိုပါသလားá‹</translation>
<translation id="9173282814238175921">စာရွက်စာá€á€™á€ºá€¸á€á€…်á€á€¯á€á€Šá€ºá€¸/စာမျက်နှာ အသစ်</translation>
+<translation id="9173995187295789444">ဘလူးá€á€¯á€žá€º စက်များ ရှာနေသည်…</translation>
<translation id="917450738466192189">ဆာဗာ လက်မှá€á€ºá€™á€¾á€¬ မမှန်ကန်ပါá‹</translation>
<translation id="9174917557437862841">ပြောင်းရန်á€á€œá€¯á€á€ºá€€á€­á€¯ á€á€­á€¯á€·á€•á€«áŠ ဤá€á€˜á€ºá€žá€­á€¯á€· ပြောင်းရန် Enter ကို နှိပ်ပါ</translation>
<translation id="9179703756951298733">သင်á ငွေပေးá€á€»á€±á€™á€¾á€¯á€™á€»á€¬á€¸á€”ှင့် á€á€›á€€á€ºá€’စ်ကá€á€ºá€¡á€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯ Chrome ဆက်á€á€„်များá€á€½á€„် စီမံပါ</translation>
diff --git a/chromium/components/strings/components_strings_ne.xtb b/chromium/components/strings/components_strings_ne.xtb
index bffaf3cfae9..140e7a3da63 100644
--- a/chromium/components/strings/components_strings_ne.xtb
+++ b/chromium/components/strings/components_strings_ne.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">यदि जाà¤à¤š गरिà¤à¤®à¤¾, छिटो फाराम भरà¥à¤¨à¤•à¥‹ लागि Chrome ले यस यनà¥à¤¤à¥à¤°à¤®à¤¾ तपाईà¤à¤•à¥‹ कारà¥à¤¡à¤•à¥‹ पà¥à¤°à¤¤à¤¿à¤²à¤¿à¤ªà¤¿ भणà¥à¤¡à¤¾à¤°à¤£ गरà¥à¤›à¥¤</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> का अनà¥à¤®à¤¤à¤¿à¤¹à¤°à¥‚ चयन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="1113869188872983271">कà¥à¤°à¤® परिवरà¥à¤¤à¤¨ &amp;पूरà¥à¤µà¤µà¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="1123753900084781868">यस बखत लाइभ कà¥à¤¯à¤¾à¤ªà¥à¤¸à¤¨ उपलबà¥à¤§ छैन</translation>
<translation id="1125573121925420732">वेबसाइटहरूले आफà¥à¤¨à¥‹ सà¥à¤°à¤•à¥à¤·à¤¾ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾ अदà¥à¤¯à¤¾à¤µà¤§à¤¿à¤• गरà¥à¤¦à¤¾ चेतावनी दिनॠसामानà¥à¤¯ हà¥à¤¨ सकà¥à¤›à¥¤ यसलाई चाà¤à¤¡à¥ˆ सà¥à¤§à¤¾à¤° गरà¥à¤¨à¥ परà¥à¤›à¥¤</translation>
<translation id="112840717907525620">नीति कà¥à¤¯à¤¾à¤¸ ठिक छ</translation>
<translation id="1130564665089811311">'पृषà¥à¤  अनà¥à¤µà¤¾à¤¦ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥' नामक बटन, Google अनà¥à¤µà¤¾à¤¦à¤• पà¥à¤°à¤¯à¥‹à¤— गरी यो पृषà¥à¤  अनà¥à¤µà¤¾à¤¦ गरà¥à¤¨ Enter थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">तपाईंको डिभाइसको नाम</translation>
<translation id="124116460088058876">थप भाषाहरू</translation>
<translation id="1243027604378859286">लेखक:</translation>
+<translation id="1246424317317450637">बोलà¥à¤¡</translation>
<translation id="1250759482327835220">अरà¥à¤•à¥‹ पटक अठछिटो भà¥à¤•à¥à¤¤à¤¾à¤¨à¥€ गरà¥à¤¨ आफà¥à¤¨à¥‹ Google खातामा आफà¥à¤¨à¥‹ कारà¥à¤¡, नाम र बिलिङ ठेगाना सेभ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (सिंक गरिà¤à¤•à¤¾)</translation>
<translation id="1256368399071562588">&lt;p&gt;तपाईं कà¥à¤¨à¥ˆ वेबसाइटमा जान खोजà¥à¤¦à¤¾ उकà¥à¤¤ साइट नखà¥à¤²à¥‡à¤•à¥‹ खणà¥à¤¡à¤®à¤¾ सरà¥à¤µà¤ªà¥à¤°à¤¥à¤® समसà¥à¤¯à¤¾ निवारणका यी चरणहरूको पà¥à¤°à¤¯à¥‹à¤— गरी तà¥à¤°à¥à¤Ÿà¤¿à¤•à¥‹ समाधान गरà¥à¤¨à¥‡ पà¥à¤°à¤¯à¤¾à¤¸ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">आफà¥à¤¨à¥‹ पासवरà¥à¤¡ बदलà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="1484290072879560759">ढà¥à¤µà¤¾à¤¨à¥€à¤•à¥‹ ठेगाना छनौट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="1492194039220927094">नीतिहरू लागू गरà¥à¤¨à¥‡ कारà¥à¤¯:</translation>
+<translation id="1495677929897281669">टà¥à¤¯à¤¾à¤¬à¤®à¤¾ फरà¥à¤•à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="1501859676467574491">आफà¥à¤¨à¥‹ Google खाताका कारà¥à¤¡à¤¹à¤°à¥‚ देखाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="1507202001669085618">&lt;p&gt;तपाईं अनलाइन हà¥à¤¨à¥ पूरà¥à¤µ साइन इन गरà¥à¤¨ परà¥à¤¨à¥‡à¤®à¤¾ Wi-Fi पोरà¥à¤Ÿà¤² पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ खणà¥à¤¡à¤®à¤¾ तपाईंले यो तà¥à¤°à¥à¤Ÿà¤¿ देखà¥à¤¹à¥à¤¨à¥‡ छ।&lt;/p&gt;
&lt;p&gt;तà¥à¤°à¥à¤Ÿà¤¿ समाधान गरà¥à¤¨, तपाईंले खोलà¥à¤¨à¥‡ पà¥à¤°à¤¯à¤¾à¤¸ गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ पृषà¥à¤ à¤®à¤¾ &lt;strong&gt;कनेकà¥à¤Ÿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥&lt;/strong&gt; मा कà¥à¤²à¤¿à¤• गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥â€Œà¥¤&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">यो पृषà¥à¤ à¤²à¥‡ यसो भनà¥à¤›</translation>
<translation id="153384715582417236">अहिलेलाई यति मातà¥à¤°!</translation>
<translation id="1536390784834419204">यो पृषà¥à¤  अनà¥à¤µà¤¾à¤¦ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="1539840569003678498">रिपोरà¥à¤Ÿ पठाइà¤à¤•à¥‹ मिति र समय:</translation>
<translation id="154408704832528245">डेलिभरी गरà¥à¤¨à¥‡ ठेगाना छनौट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="1549470594296187301">यो सà¥à¤µà¤¿à¤§à¤¾ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨ JavaScript सकà¥à¤°à¤¿à¤¯ गरà¥à¤¨à¥à¤ªà¤°à¥à¤›à¥¤</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">पहिले छोटो किनारा</translation>
<translation id="168693727862418163">यो नीतिको मान यसको सà¥à¤•à¤¿à¤®à¤¾à¤¸à¤à¤— मिलेन। तà¥à¤¯à¤¸à¤•à¤¾à¤°à¤£ यसलाई बेवासà¥à¤¤à¤¾ गरिने छ।</translation>
<translation id="168841957122794586">सरà¥à¤­à¤° पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤°à¤²à¥‡ कमजोर कà¥à¤°à¤¿à¤ªà¥à¤Ÿà¥‹à¤—à¥à¤°à¤¾à¤«à¤¿à¤• कà¥à¤žà¥à¤œà¥€ समावेश गरà¥à¤›à¥¤</translation>
+<translation id="1696290444144917273">भरà¥à¤šà¥à¤…ल कारà¥à¤¡à¤•à¤¾ विवरण हेरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="1697532407822776718">तपाईंहरू सबैले सेट हà¥à¤¨à¤­à¤¯à¥‹!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{ यो सरà¥à¤­à¤°à¤²à¥‡ यो <ph name="DOMAIN" /> हो भनेर पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤ गरà¥à¤¨ सकेन; यसको सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤°à¤²à¤¾à¤ˆ भोलिबाट मानिनà¥à¤›à¥¤ गलत कनà¥à¤«à¤¿à¤—à¥à¤°à¥‡à¤¸à¤¨ वा कà¥à¤¨à¥ˆ आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤²à¥‡ तपाईà¤à¤•à¥‹ जडानमा अवरोध गरिरहेको कारणले यसो भà¤à¤•à¥‹ हà¥à¤¨ सकà¥à¤›à¥¤}other{ यो सरà¥à¤­à¤°à¤²à¥‡ यो <ph name="DOMAIN" /> हो भनेर पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤ गरà¥à¤¨ सकेन; यसको सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤°à¤²à¤¾à¤ˆ # दिनबाट शà¥à¤°à¥‚ हà¥à¤¨à¥à¤› भनेर मानिनà¥à¤›à¥¤ गलत कनà¥à¤«à¤¿à¤—à¥à¤°à¥‡à¤¸à¤¨ वा कà¥à¤¨à¥ˆ आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤²à¥‡ तपाईà¤à¤•à¥‹ जडानमा अवरोध गरिरहेको कारणले यसो भà¤à¤•à¥‹ हà¥à¤¨ सकà¥à¤›à¥¤}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> अनà¥à¤¤à¤°à¥à¤—त <ph name="VALUE" /> सेट नगरिà¤à¤•à¥‹ हà¥à¤¨à¤¾à¤²à¥‡ सो नीति बेवासà¥à¤¤à¤¾ गरिà¤à¤•à¥‹ छ।</translation>
<translation id="1712552549805331520"><ph name="URL" /> तपाईंको सà¥à¤¥à¤¾à¤¨à¥€à¤¯ कमà¥à¤ªà¥à¤¯à¥à¤Ÿà¤°à¤®à¤¾ सà¥à¤¥à¤¾à¤¯à¥€ रूपमा डेटा भणà¥à¤¡à¤¾à¤°à¤£ गरà¥à¤¨ चाहनà¥à¤›</translation>
<translation id="1713628304598226412">टà¥à¤°à¥‡ २</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">मेलबकà¥à¤¸ ३</translation>
<translation id="1718029547804390981">कागजात à¤à¤¨à¥‹à¤Ÿà¥‡à¤¸à¤¨ गरà¥à¤¨à¥ˆ नमिलà¥à¤¨à¥‡ गरी ठà¥à¤²à¥‹ छ</translation>
<translation id="1721424275792716183">* कà¥à¤·à¥‡à¤¤à¥à¤° आवशà¥à¤¯à¤• छ</translation>
+<translation id="1727613060316725209">पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° वैध छ</translation>
<translation id="1727741090716970331">कारà¥à¤¡à¤•à¥‹ मानà¥à¤¯ नमà¥à¤¬à¤° थपà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="1728677426644403582">तपाईं à¤à¤‰à¤Ÿà¤¾ वेब पृषà¥à¤ à¤•à¥‹ सà¥à¤°à¥‹à¤¤ हेरà¥à¤¦à¥ˆ हà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›</translation>
<translation id="173080396488393970">यस पà¥à¤°à¤•à¤¾à¤°à¤•à¥‹ कारà¥à¤¡à¤²à¤¾à¤ˆ समरà¥à¤¥à¤¨ छैन</translation>
@@ -246,7 +253,6 @@
<ph name="SITE" /> का सनà¥à¤¦à¤°à¥à¤­à¤®à¤¾ तपाईंले गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ अनà¥à¤°à¥‹à¤§ पूरा गरà¥à¤¨ दिà¤à¤¦à¥ˆà¤¨à¥¤ साइटका सञà¥à¤šà¤¾à¤²à¤•à¤¹à¤°à¥‚ कà¥à¤¨à¥ˆ साइटको सà¥à¤°à¤•à¥à¤·à¤¾ र
अनà¥à¤¯ विशेषता कनà¥à¤«à¤¿à¤—र गरà¥à¤¨à¥‡ पà¥à¤°à¤¯à¥‹à¤œà¤¨à¤•à¤¾ लागि मूल नीतिहरू पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨ सकà¥à¤›à¤¨à¥à¥¤</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">कृपया तपाइà¤à¤•à¥‹ समकà¥à¤°à¤®à¤£ पासफà¥à¤°à¥‡à¤œ अपडेट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
<translation id="1787142507584202372">तपाईंका खà¥à¤²à¤¾ टà¥à¤¯à¤¾à¤¬à¤¹à¤°à¥‚ यहाठदेखा परà¥à¤›à¤¨à¥</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, à¤à¤•à¤­à¤¨à¥à¤¦à¤¾ बढी कारà¥à¤¯ गरà¥à¤¨ सकिनà¥à¤›, à¤à¤• à¤à¤• गरी पà¥à¤°à¤¤à¥à¤¯à¥‡à¤• कारà¥à¤¯ गरà¥à¤¨ Tab थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">विजà¥à¤žà¤¾à¤ªà¤¨à¤¹à¤°à¥‚</translation>
<translation id="1919367280705858090">निरà¥à¤¦à¤¿à¤·à¥à¤Ÿ तà¥à¤°à¥à¤Ÿà¤¿à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ सनà¥à¤¦à¥‡à¤¶à¤®à¤¾à¤°à¥à¤«à¤¤ मदà¥à¤¦à¤¤ पà¥à¤°à¤¾à¤ªà¥à¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
<translation id="192020519938775529">{COUNT,plural, =0{कà¥à¤¨à¥ˆ पनि होइन}=1{१ साइट}other{# साइटहरू}}</translation>
+<translation id="1924727005275031552">नयाà¤</translation>
<translation id="1945968466830820669">तपाईं आफà¥à¤¨à¥‹ सङà¥à¤—ठनको खातामाथिको पहà¥à¤à¤š गà¥à¤®à¤¾à¤‰à¤¨ सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤› वा तपाईंको पहिचान चोरी हà¥à¤¨ सकà¥à¤›à¥¤ Chromium तपाईंलाई आफà¥à¤¨à¥‹ पासवरà¥à¤¡ अहिले नै परिवरà¥à¤¤à¤¨ गरà¥à¤¨ सिफारिस गरà¥à¤›à¥¤</translation>
<translation id="1947454675006758438">सिरानको दायाà¤à¤ªà¤Ÿà¥à¤Ÿà¤¿ सà¥à¤Ÿà¤¿à¤š</translation>
<translation id="1958218078413065209">तपाईंले लà¥à¤¯à¤¾à¤‰à¤¨à¥à¤­à¤à¤•à¥‹ अधिकतम अङà¥à¤• <ph name="SCORE" /> हो।</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">टà¥à¤°à¥‡ ७</translation>
<translation id="204357726431741734">आफà¥à¤¨à¥‹ Google खातामा सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरिà¤à¤•à¤¾ पासवरà¥à¤¡à¤¹à¤°à¥‚ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨ साइन इन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> भाषाका पृषà¥à¤ à¤¹à¤°à¥‚ अनà¥à¤µà¤¾à¤¦ गरिने छैननà¥à¥¤</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{यो सेटिङ अन र यसको सà¥à¤¥à¤¿à¤¤à¤¿ सकà¥à¤°à¤¿à¤¯ भà¤à¤•à¥‹ खणà¥à¤¡à¤®à¤¾ Chrome ले मानà¥à¤›à¥‡à¤¹à¤°à¥‚को ठà¥à¤²à¥‹ समूह वा "साà¤à¤¾ गà¥à¤£ भà¤à¤•à¤¾ मानà¥à¤›à¥‡à¤¹à¤°à¥‚को समूह" मधà¥à¤¯à¥‡ कà¥à¤¨à¤¸à¤à¤— तपाईंले बà¥à¤°à¤¾à¤‰à¤œà¤° पà¥à¤°à¤¯à¥‹à¤— गरी हालसालै गरà¥à¤¨à¥à¤­à¤à¤•à¤¾ कà¥à¤°à¤¿à¤¯à¤¾à¤•à¤²à¤¾à¤ª सबैभनà¥à¤¦à¤¾ बढी मिलà¥à¤›à¤¨à¥ भनà¥à¤¨à¥‡ कà¥à¤°à¤¾ निरà¥à¤§à¤¾à¤°à¤£ गरà¥à¤›à¥¤ विजà¥à¤žà¤¾à¤ªà¤¨à¤¦à¤¾à¤¤à¤¾à¤¹à¤°à¥‚ उकà¥à¤¤ समूहमा आफूले देखाउन चाहेका विजà¥à¤žà¤¾à¤ªà¤¨à¤¹à¤°à¥‚ छनौट गरà¥à¤¨ सकà¥à¤›à¤¨à¥ र तपाईंले बà¥à¤°à¤¾à¤‰à¤œà¤° पà¥à¤°à¤¯à¥‹à¤— गरी गरà¥à¤¨à¥à¤­à¤à¤•à¤¾ कà¥à¤°à¤¿à¤¯à¤¾à¤•à¤²à¤¾à¤ª तपाईंको डिभाइसमा गोपà¥à¤¯ राखिनà¥à¤›à¤¨à¥à¥¤ तपाईंको समूह हरेक दिन अपडेट गरिनà¥à¤›à¥¤}=1{यो सेटिङ अन र यसको सà¥à¤¥à¤¿à¤¤à¤¿ सकà¥à¤°à¤¿à¤¯ भà¤à¤•à¥‹ खणà¥à¤¡à¤®à¤¾ Chrome ले मानà¥à¤›à¥‡à¤¹à¤°à¥‚को ठà¥à¤²à¥‹ समूह वा "साà¤à¤¾ गà¥à¤£ भà¤à¤•à¤¾ मानà¥à¤›à¥‡à¤¹à¤°à¥‚को समूह" मधà¥à¤¯à¥‡ कà¥à¤¨à¤¸à¤à¤— तपाईंले बà¥à¤°à¤¾à¤‰à¤œà¤° पà¥à¤°à¤¯à¥‹à¤— गरी हालसालै गरà¥à¤¨à¥à¤­à¤à¤•à¤¾ कà¥à¤°à¤¿à¤¯à¤¾à¤•à¤²à¤¾à¤ª सबैभनà¥à¤¦à¤¾ बढी मिलà¥à¤›à¤¨à¥ भनà¥à¤¨à¥‡ कà¥à¤°à¤¾ निरà¥à¤§à¤¾à¤°à¤£ गरà¥à¤›à¥¤ विजà¥à¤žà¤¾à¤ªà¤¨à¤¦à¤¾à¤¤à¤¾à¤¹à¤°à¥‚ उकà¥à¤¤ समूहमा आफूले देखाउन चाहेका विजà¥à¤žà¤¾à¤ªà¤¨à¤¹à¤°à¥‚ छनौट गरà¥à¤¨ सकà¥à¤›à¤¨à¥ र तपाईंले बà¥à¤°à¤¾à¤‰à¤œà¤° पà¥à¤°à¤¯à¥‹à¤— गरी गरà¥à¤¨à¥à¤­à¤à¤•à¤¾ कà¥à¤°à¤¿à¤¯à¤¾à¤•à¤²à¤¾à¤ª तपाईंको डिभाइसमा गोपà¥à¤¯ राखिनà¥à¤›à¤¨à¥à¥¤ तपाईंको समूह हरेक दिन अपडेट गरिनà¥à¤›à¥¤}other{यो सेटिङ अन र यसको सà¥à¤¥à¤¿à¤¤à¤¿ सकà¥à¤°à¤¿à¤¯ भà¤à¤•à¥‹ खणà¥à¤¡à¤®à¤¾ Chrome ले मानà¥à¤›à¥‡à¤¹à¤°à¥‚को ठà¥à¤²à¥‹ समूह वा "साà¤à¤¾ गà¥à¤£ भà¤à¤•à¤¾ मानà¥à¤›à¥‡à¤¹à¤°à¥‚को समूह" मधà¥à¤¯à¥‡ कà¥à¤¨à¤¸à¤à¤— तपाईंले बà¥à¤°à¤¾à¤‰à¤œà¤° पà¥à¤°à¤¯à¥‹à¤— गरी हालसालै गरà¥à¤¨à¥à¤­à¤à¤•à¤¾ कà¥à¤°à¤¿à¤¯à¤¾à¤•à¤²à¤¾à¤ª सबैभनà¥à¤¦à¤¾ बढी मिलà¥à¤›à¤¨à¥ भनà¥à¤¨à¥‡ कà¥à¤°à¤¾ निरà¥à¤§à¤¾à¤°à¤£ गरà¥à¤›à¥¤ विजà¥à¤žà¤¾à¤ªà¤¨à¤¦à¤¾à¤¤à¤¾à¤¹à¤°à¥‚ उकà¥à¤¤ समूहमा आफूले देखाउन चाहेका विजà¥à¤žà¤¾à¤ªà¤¨à¤¹à¤°à¥‚ छनौट गरà¥à¤¨ सकà¥à¤›à¤¨à¥ र तपाईंले बà¥à¤°à¤¾à¤‰à¤œà¤° पà¥à¤°à¤¯à¥‹à¤— गरी गरà¥à¤¨à¥à¤­à¤à¤•à¤¾ कà¥à¤°à¤¿à¤¯à¤¾à¤•à¤²à¤¾à¤ª तपाईंको डिभाइसमा गोपà¥à¤¯ राखिनà¥à¤›à¤¨à¥à¥¤ तपाईंको समूह हरेक {NUM_DAYS} दिनमा अपडेट गरिनà¥à¤›à¥¤}}</translation>
<translation id="2053553514270667976">जिप कोड</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{१ सà¥à¤à¤¾à¤µ}other{# सà¥à¤à¤¾à¤µà¤¹à¤°à¥‚}}</translation>
<translation id="2071692954027939183">तपाईं सामानà¥à¤¯à¤¤à¤¯à¤¾ सूचनाहरू देखाउने अनà¥à¤®à¤¤à¤¿ दिनà¥à¤¹à¥à¤¨à¥à¤¨à¥¤ तà¥à¤¯à¤¸à¥ˆà¤²à¥‡ सूचनाहरू सà¥à¤µà¤¤à¤ƒ बà¥à¤²à¤• गरिà¤à¤•à¤¾ छनà¥</translation>
<translation id="2079545284768500474">अनà¥à¤¡à¥‚ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="20817612488360358">पà¥à¤°à¤£à¤¾à¤²à¥€ पà¥à¤°à¥‹à¤•à¥à¤¸à¥€ सेटिङहरू पà¥à¤°à¤¯à¥‹à¤—का लागि सेट छनॠतर à¤à¤‰à¤Ÿà¤¾ सà¥à¤ªà¤·à¥à¤Ÿ पà¥à¤°à¥‹à¤•à¥à¤¸à¥€ कनà¥à¤«à¤¿à¤—रेसन पनि निरà¥à¤¦à¤¿à¤·à¥à¤Ÿ गरिà¤à¤•à¥‹ छ।</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> को <ph name="RESULT_NUMBER" /> परिणाम</translation>
+<translation id="2085876078937250610">सेभ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥â€¦</translation>
<translation id="2088086323192747268">'सिंक गरà¥à¤¨à¥‡ सà¥à¤µà¤¿à¤§à¤¾ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥' नामक बटन, Chrome का सेटिङमा गई के कसà¥à¤¤à¤¾ जानकारी सिंक गरà¥à¤¨à¥‡ भनà¥à¤¨à¥‡ कà¥à¤°à¤¾ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤¨ Enter थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="2091887806945687916">आवाज</translation>
<translation id="2094505752054353250">डोमेन बेमेल</translation>
@@ -379,15 +388,18 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> लाई à¤à¤•-पटके टेकà¥à¤¸à¥à¤Ÿ मà¥à¤¯à¤¾à¤¸à¥‡à¤œ र पासवरà¥à¤¡ आवशà¥à¤¯à¤• हà¥à¤¨à¥à¤›à¥¤</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" /> मा मà¥à¤¯à¤¾à¤¦ समापà¥à¤¤ हà¥à¤¨à¥à¤›</translation>
<translation id="2337852623177822836">तपाईंको पà¥à¤°à¤¶à¤¾à¤¸à¤•à¤²à¥‡ नियनà¥à¤¤à¥à¤°à¤£ गरेको सेटिङ</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> जोडा बनाउन चाहनà¥à¤›</translation>
<translation id="2344028582131185878">सà¥à¤µà¤šà¤¾à¤²à¤¿à¤¤ डाउनलोडहरू</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>
-<translation id="2355395290879513365">आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤¹à¤°à¥‚ले यस साइटमा तपाईà¤à¤²à¥‡ हेरिरहनà¥à¤­à¤à¤•à¤¾ छविहरू हेरà¥à¤¨ र तिनीहरूलाई परिमारà¥à¤œà¤¨ गरी तपाईà¤à¤²à¤¾à¤ˆ धोका दिन सकà¥à¤›à¤¨à¥à¥¤</translation>
+<translation id="2355395290879513365">आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤¹à¤°à¥‚ले यस साइटमा तपाईà¤à¤²à¥‡ हेरिरहनà¥à¤­à¤à¤•à¤¾ फोटो हेरà¥à¤¨ र तिनीहरूलाई परिमारà¥à¤œà¤¨ गरी तपाईà¤à¤²à¤¾à¤ˆ धोका दिन सकà¥à¤›à¤¨à¥à¥¤</translation>
<translation id="2356070529366658676">सोधà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="2357481397660644965"><ph name="DEVICE_MANAGER" /> ले तपाईंको यनà¥à¤¤à¥à¤° वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤› र <ph name="ACCOUNT_MANAGER" /> ले तपाईंको खाता वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤›à¥¤</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{à¤à¤• दिनभनà¥à¤¦à¤¾ कम समयमै}=1{à¤à¤• दिनभितà¥à¤°}other{{NUM_DAYS} दिनभितà¥à¤°}}</translation>
<translation id="2359629602545592467">बहॠमà¥à¤¦à¥à¤°à¤¾à¤¹à¤°à¥‚</translation>
<translation id="2359808026110333948">जारी राखà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="2359961752320758691">तपाईंको भरà¥à¤šà¥à¤…ल कारà¥à¤¡ नमà¥à¤¬à¤° अटोफिल गरिà¤à¤•à¥‹ छ।</translation>
<translation id="2367567093518048410">चरण</translation>
<translation id="2372464001869762664">तपाईंले पà¥à¤·à¥à¤Ÿà¤¿ गरिसकेपछि तपाईंको Google खातामा रहेका कारà¥à¤¡à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ विवरणहरू यो साइटसà¤à¤— सेयर गरिने छनà¥à¥¤ तपाईं आफà¥à¤¨à¥‹ Plex खातासमà¥à¤¬à¤¨à¥à¤§à¥€ विवरणहरूमा गई CVC हेरà¥à¤¨ सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›à¥¤</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">ढà¥à¤µà¤¾à¤¨à¥€à¤•à¥‹ यो विधि उपलबà¥à¤§ छैन। फरक विधि चयन गरà¥à¤¨à¥‡ पà¥à¤°à¤¯à¤¾à¤¸ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
<translation id="2396249848217231973">मेटाइलाई &amp;पूरà¥à¤µà¤µà¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">पà¥à¤°à¤¾à¤¨à¥‹</translation>
<translation id="2413528052993050574">यो सरà¥à¤­à¤°à¤²à¥‡ यो <ph name="DOMAIN" /> को भनि पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤ गरà¥à¤¨ सकेन; यसको सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤°à¤²à¤¾à¤ˆ रदà¥à¤¦ गरिà¤à¤•à¥‹ हà¥à¤¨ सकà¥à¤›à¥¤ यो कà¥à¤¨à¥ˆ à¤à¤‰à¤Ÿà¤¾ मिसकनà¥à¤«à¤¿à¤—रेसन वा कà¥à¤¨à¥ˆ आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤²à¥‡ तपाईंको जडानमा गरेको हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ªà¤•à¥‹ कारणले गरà¥à¤¦à¤¾ भà¤à¤•à¥‹ हà¥à¤¨ सकà¥à¤›à¥¤</translation>
<translation id="2414886740292270097">अà¤à¤§à¥à¤¯à¤¾à¤°à¥‹</translation>
<translation id="2438874542388153331">दायाà¤à¤¤à¤¿à¤° चार पà¥à¤µà¤¾à¤²</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">फेदको दायाà¤à¤ªà¤Ÿà¥à¤Ÿà¤¿ सà¥à¤Ÿà¤¿à¤š</translation>
<translation id="2523886232349826891">यो डिभाइसमा भने यस कारà¥à¤¡à¤²à¤¾à¤ˆ अà¤à¥ˆ पनि सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरिनà¥à¤›</translation>
<translation id="2524461107774643265">थप जानकारी थपà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
-<translation id="2526590354069164005">डेसà¥à¤•à¤Ÿà¤ª</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{र थप १}other{र थप #}}</translation>
<translation id="2536110899380797252">ठेगाना थपà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="2539524384386349900">पतà¥à¤¤à¤¾ लगाउनà¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="2541219929084442027">तपाईंले आफà¥à¤¨à¤¾ सबै इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ टà¥à¤¯à¤¾à¤¬à¤¹à¤°à¥‚ बनà¥à¤¦ गरेपछि तपाईंले ती इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ टà¥à¤¯à¤¾à¤¬à¤®à¤¾ हेरà¥à¤¨à¥‡ पेजहरू तपाईंको बà¥à¤°à¤¾à¤œà¤‰à¤°à¤•à¥‹ इतिहास, कà¥à¤•à¥€ सà¥à¤Ÿà¥‹à¤° वा खोजको इतिहासमा भणà¥à¤¡à¤¾à¤°à¤£ हà¥à¤¨à¥‡ छैननà¥à¥¤ तपाईंले डाउनलोड गरà¥à¤¨à¥‡ कà¥à¤¨à¥ˆ फाइल वा बनाउने कà¥à¤¨à¥ˆ बà¥à¤•à¤®à¤¾à¤°à¥à¤• भने भणà¥à¤¡à¤¾à¤°à¤£ गरिने छ।</translation>
<translation id="2544644783021658368">à¤à¤‰à¤Ÿà¤¾ कागजात</translation>
<translation id="254947805923345898">नीतिको मान मानà¥à¤¯ छैन।</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ले अमानà¥à¤¯ पà¥à¤°à¤¤à¤¿à¤•à¥à¤°à¤¿à¤¯à¤¾ पठायो।</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Chrome को सबैभनà¥à¤¦à¤¾ उचà¥à¤š सà¥à¤¤à¤°à¤•à¥‹ सà¥à¤°à¤•à¥à¤·à¤¾ सà¥à¤µà¤¿à¤§à¤¾ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨ <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />परिषà¥à¤•à¥ƒà¤¤ सà¥à¤°à¤•à¥à¤·à¤¾<ph name="END_ENHANCED_PROTECTION_LINK" /> अन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> को सरà¥à¤­à¤°à¤•à¥‹ IP à¤à¤¡à¥à¤°à¥‡à¤¸ फेला पारà¥à¤¨ सकिà¤à¤¨à¥¤</translation>
<translation id="2639739919103226564">सà¥à¤¥à¤¿à¤¤à¤¿:</translation>
+<translation id="264810637653812429">कà¥à¤¨à¥ˆ पनि मिलà¥à¤¦à¥‹à¤œà¥à¤²à¥à¤¦à¥‹ यनà¥à¤¤à¥à¤° फेला परेन।</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome का सेटिङमा गई आफà¥à¤¨à¥‹ बà¥à¤°à¤¾à¤‰à¤œà¤¿à¤™ इतिहास, कà¥à¤•à¥€, कà¥à¤¯à¤¾à¤¸ तथा अनà¥à¤¯ डेटा हटाउन Tab थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ अनि Enter थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="2650446666397867134">फाइलमा पहà¥à¤à¤š असà¥à¤µà¥€à¤•à¤¾à¤° गरियो</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">पà¥à¤¨: सà¥à¤°à¥à¤µà¤¾à¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="2803306138276472711">Google सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ बà¥à¤°à¤¾à¤‰à¤œà¤¿à¥à¤²à¥‡ हालै <ph name="SITE" /> मा <ph name="BEGIN_LINK" />मालवेयर पतà¥à¤¤à¤¾<ph name="END_LINK" /> लगायो। सामनà¥à¤¯à¤¤à¤¯à¤¾ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ भनिà¤à¤•à¤¾ वेबसाइटहरू कहिलेकाहीठमालवेयरदà¥à¤µà¤¾à¤°à¤¾ संकà¥à¤°à¤®à¤¿à¤¤ हà¥à¤¨à¥à¤›à¤¨à¥à¥¤</translation>
<translation id="2807052079800581569">छविको Y सà¥à¤¥à¤¾à¤¨</translation>
+<translation id="2820957248982571256">सà¥à¤•à¥à¤¯à¤¾à¤¨ गरà¥à¤¦à¥ˆ...</translation>
<translation id="2824775600643448204">ठेगाना र खोज पटà¥à¤Ÿà¥€</translation>
<translation id="2826760142808435982">यो जडान गà¥à¤ªà¥à¤¤à¤²à¥‡à¤– गरिà¤à¤•à¥‹ र <ph name="CIPHER" /> पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¦à¥ˆ पà¥à¤°à¤®à¤¾à¤£à¥€à¤•à¤°à¤£ गरिà¤à¤•à¥‹ छ र कà¥à¤žà¥à¤œà¥€ साटà¥à¤¨à¥‡ पà¥à¤°à¤•à¥à¤°à¤¿à¤¯à¤¾à¤•à¥‹ रूपमा <ph name="KX" /> पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤›à¥¤</translation>
<translation id="2835170189407361413">फारम खालि गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">यो साइटले हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ªà¤•à¤¾à¤°à¥€ वा भà¥à¤°à¤¾à¤®à¤• विजà¥à¤žà¤¾à¤ªà¤¨à¤¹à¤°à¥‚ देखाउà¤à¤›à¥¤</translation>
+<translation id="287596039013813457">मैतà¥à¤°à¥€à¤ªà¥‚रà¥à¤£</translation>
+<translation id="2876489322757410363">कà¥à¤¨à¥ˆ बाहà¥à¤¯ à¤à¤ªà¤®à¤¾à¤°à¥à¤«à¤¤ भà¥à¤•à¥à¤¤à¤¾à¤¨à¥€ गरà¥à¤¨ इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोडबाट बाहिरिà¤à¤¦à¥ˆ हà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›à¥¤ जारी राखà¥à¤¨à¥‡ हो?</translation>
<translation id="2878197950673342043">पोसà¥à¤Ÿà¤° फोलà¥à¤¡</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">विनà¥à¤¡à¥‹ रहने सà¥à¤¥à¤¾à¤¨</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome को सेटिङमा गई सà¥à¤°à¤•à¥à¤·à¤¾ जाà¤à¤š गरà¥à¤¨ Tab अनि Enter थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3061707000357573562">पà¥à¤¯à¤¾à¤šà¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ सेवा</translation>
-<translation id="3064966200440839136">कà¥à¤¨à¥ˆ बाहà¥à¤¯ अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—मारà¥à¤«à¤¤ भà¥à¤•à¥à¤¤à¤¾à¤¨à¥€ गरà¥à¤¨à¤•à¤¾ लागि इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोडलाई छाडिà¤à¤¦à¥ˆ । जारी राखà¥à¤¨à¥‡ हो?</translation>
<translation id="306573536155379004">गेम सà¥à¤°à¥ भà¤à¤•à¥‹ छ।</translation>
<translation id="3080254622891793721">गà¥à¤°à¤¾à¤«à¤¿à¤•</translation>
<translation id="3086579638707268289">वेबको तपाईंको कà¥à¤°à¤¿à¤¯à¤¾à¤•à¤²à¤¾à¤ªà¤•à¥‹ निगरानी गरिà¤à¤¦à¥ˆ छ</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312"><ph name="MANAGER" /> ले तपाईंको खाता वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤›à¥¤</translation>
<translation id="3157931365184549694">पà¥à¤¨: भणà¥à¤¡à¤¾à¤°à¤£</translation>
<translation id="3162559335345991374">तपाईà¤à¤²à¥‡ पà¥à¤°à¤¯à¥‹à¤— गरिरहनॠभà¤à¤•à¥‹ Wi-Fi लाई तपाईà¤à¤²à¥‡ यसको लगइन पृषà¥à¤ à¤•à¥‹ भà¥à¤°à¤®à¤£ गरà¥à¤¨ आवशà¥à¤¯à¤•à¤¤à¤¾ हà¥à¤¨ सकà¥à¤›à¥¤</translation>
-<translation id="3167968892399408617">तपाईंले आफà¥à¤¨à¤¾ सबै इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ टà¥à¤¯à¤¾à¤¬à¤¹à¤°à¥‚ बनà¥à¤¦ गरे पछि इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ टà¥à¤¯à¤¾à¤¬à¤®à¤¾ हेरेका पृषà¥à¤ à¤¹à¤°à¥‚ तपाईंको बà¥à¤°à¤¾à¤œà¤‰à¤° इतिहास, कà¥à¤•à¥€ सà¥à¤Ÿà¥‹à¤° वा खोज इतिहासमा बसà¥à¤¨à¥‡ छैननà¥à¥¤ तपाईंले डाउनलोड गरà¥à¤¨à¥ भà¤à¤•à¤¾ फाइल वा सिरà¥à¤œà¤¨à¤¾ गरà¥à¤¨à¥à¤­à¤à¤•à¤¾ पà¥à¤¸à¥à¤¤à¤• चिनà¥à¤¹à¤¹à¤°à¥‚ भने राखिने छनà¥à¥¤</translation>
<translation id="3169472444629675720">पतà¥à¤¤à¤¾ लगाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3174168572213147020">टापà¥</translation>
<translation id="3176929007561373547">पà¥à¤°à¥‹à¤•à¥à¤¸à¥€ सरà¥à¤­à¤°à¤²à¥‡ काम गरिरहेको निशà¥à¤šà¤¿à¤¤ गरà¥à¤¨ तपाईंको पà¥à¤°à¥‹à¤•à¥à¤¸à¥€ सेटिङहरू जाà¤à¤šà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ वा तपाईंको नेटवरà¥à¤• पà¥à¤°à¤¶à¤¾à¤¸à¤•à¤²à¤¾à¤ˆ समà¥à¤ªà¤°à¥à¤• गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤ यदि तपाईंलाई तपाईंले पà¥à¤°à¥‹à¤•à¥à¤¸à¥€ सरà¥à¤­à¤° पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥ परà¥à¤¦à¤› भनà¥à¤¨à¥‡ विशà¥à¤µà¤¾à¤¸ छैन भने: <ph name="PLATFORM_TEXT" /></translation>
@@ -596,10 +611,12 @@
<translation id="3229041911291329567">तपाईंको यनà¥à¤¤à¥à¤° र बà¥à¤°à¤¾à¤‰à¤œà¤°à¤•à¥‹ संसà¥à¤•à¤°à¤£à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ जानकारी</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> को CVC पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3234666976984236645">सधैं यस साइटमा महतà¥à¤µà¤ªà¥‚रà¥à¤£ सामगà¥à¤°à¥€ पतà¥à¤¤à¤¾ लगाउनà¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="3249845759089040423">सानदार</translation>
<translation id="3252266817569339921">फà¥à¤°à¥‡à¤¨à¥à¤š</translation>
<translation id="3266793032086590337">मान (बेमेल)</translation>
<translation id="3268451620468152448">टà¥à¤¯à¤¾à¤¬à¤¹à¤°à¥‚ खोलà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3270847123878663523">कà¥à¤°à¤® परिवरà¥à¤¤à¤¨ &amp;पूरà¥à¤µà¤µà¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> जडान गरà¥à¤¨ चाहनà¥à¤›</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">तपाईंको सङà¥à¤—ठन <ph name="ENROLLMENT_DOMAIN" /> ले निमà¥à¤¨ वेबसाइटहरूमा सेटिङ वा नीतिहरू जसà¥à¤¤à¤¾ केही जानकारी पठाà¤à¤•à¥‹ छ।</translation>
<translation id="3282497668470633863">कारà¥à¤¡à¤®à¤¾ रहेको नाम थपà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -652,6 +669,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates सरà¥à¤­à¤°à¤•à¤¾ टेमà¥à¤ªà¥à¤²à¥‡à¤Ÿà¤•à¤¾ à¤à¤• वा सोभनà¥à¤¦à¤¾ बढी URI हरू अमानà¥à¤¯ भà¤à¤•à¤¾à¤²à¥‡ तिनको पà¥à¤°à¤¯à¥‹à¤— गरिने छैन।</translation>
<translation id="3431636764301398940">यस कारà¥à¤¡à¤²à¤¾à¤ˆ यस यनà¥à¤¤à¥à¤°à¤®à¤¾ सेभ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3432601291244612633">पृषà¥à¤  बनà¥à¤¦ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="3435738964857648380">सà¥à¤°à¤•à¥à¤·à¤¾</translation>
<translation id="3435896845095436175">सकà¥à¤·à¤® बनाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3438829137925142401">आफà¥à¤¨à¥‹ Google खातामा सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरिà¤à¤•à¤¾ पासवरà¥à¤¡à¤¹à¤°à¥‚ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -694,7 +712,10 @@
<translation id="3584299510153766161">फेदमा दà¥à¤ˆ पà¥à¤µà¤¾à¤²</translation>
<translation id="3586931643579894722">विवरणहरू लà¥à¤•à¤¾à¤‰à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3587738293690942763">मधà¥à¤¯ भाग</translation>
+<translation id="3590643883886679995">तपाईं इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोडबाट बाहिरिà¤à¤ªà¤›à¤¿ साइन इन गरà¥à¤¨ चाहिने डेटा यो डिभाइसमा भणà¥à¤¡à¤¾à¤°à¤£ गरिने छ।</translation>
+<translation id="359126217934908072">महिना/साल:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{तपाईं जà¥à¤¨à¤¸à¥à¤•à¥ˆ बेला आफà¥à¤¨à¥‹ समूह रिसेट गरà¥à¤¨ सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›à¥¤ नयाठसमूहमा सामेल हà¥à¤¨ à¤à¤¨à¥à¤¡à¥ˆ à¤à¤• दिन लागà¥à¤›à¥¤}=1{तपाईं जà¥à¤¨à¤¸à¥à¤•à¥ˆ बेला आफà¥à¤¨à¥‹ समूह रिसेट गरà¥à¤¨ सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›à¥¤ नयाठसमूहमा सामेल हà¥à¤¨ à¤à¤¨à¥à¤¡à¥ˆ à¤à¤• दिन लागà¥à¤›à¥¤}other{तपाईं जà¥à¤¨à¤¸à¥à¤•à¥ˆ बेला आफà¥à¤¨à¥‹ समूह रिसेट गरà¥à¤¨ सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›à¥¤ नयाठसमूहमा सामेल हà¥à¤¨ à¤à¤¨à¥à¤¡à¥ˆ {NUM_DAYS} दिन लागà¥à¤›à¥¤}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">तपाईंका पà¥à¤°à¤¶à¤¾à¤¸à¤•à¤²à¥‡ रोक लगाउनà¥à¤­à¤à¤•à¥‹ à¤à¤ª</translation>
<translation id="3608932978122581043">अभिमà¥à¤–ीकरण फिड गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -703,13 +724,13 @@
<translation id="3615877443314183785">मà¥à¤¯à¤¾à¤¦ सकिने मानà¥à¤¯ मिति पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="36224234498066874">बà¥à¤°à¤¾à¤‰à¤œà¤¿à¤™à¤•à¥‹ डेटा मेटाउनà¥à¤¹à¥‹à¤¸à¥...</translation>
<translation id="362276910939193118">पूरà¥à¤£ इतिहास देखाउनà¥à¤¹à¥‹à¤¸à¥</translation>
-<translation id="3625635938337243871">तपाईं इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोडबाट बाहिरिà¤à¤ªà¤›à¤¿ साइन इन गरà¥à¤¨ पà¥à¤°à¤¯à¥‹à¤— गरिà¤à¤•à¥‹ डेटा यो डिभाइसमा भणà¥à¤¡à¤¾à¤°à¤£ गरिने छ।</translation>
<translation id="3630155396527302611">यदि यसलाई नेटवरà¥à¤•à¤®à¤¾ पहà¥à¤à¤š गरà¥à¤¨à¥‡ अनà¥à¤®à¤¤à¤¿ भà¤à¤•à¥‹ पà¥à¤°à¥‹à¤—à¥à¤°à¤¾à¤®à¤•à¥‹ रूपमा पहिले नै सूचीबदà¥à¤§ गरिà¤à¤•à¥‹ छ भने यसलाई
सूचीबाट हटाà¤à¤° फेरि थपà¥à¤¨à¥‡ पà¥à¤°à¤¯à¤¾à¤¸ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
<translation id="3630699740441428070">यो डिभाइसका à¤à¤¡à¥à¤®à¤¿à¤¨à¤¹à¤°à¥‚ले तपाईंले हेरà¥à¤¨à¥‡ वेबसाइटलगायत तपाईंको नेटवरà¥à¤• टà¥à¤°à¤¾à¤«à¤¿à¤• हेरà¥à¤¨ पाउने गरी तपाईंको नेटवरà¥à¤• कनेकà¥à¤¸à¤¨ कनà¥à¤«à¤¿à¤—र गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ छ।</translation>
<translation id="3631244953324577188">बायोमेटà¥à¤°à¤¿à¤•à¥à¤¸</translation>
<translation id="3633738897356909127">'Chrome अपडेट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥' नामक बटन, आफà¥à¤¨à¥‹ Chrome का सेटिङमा गई Chrome अपडेट गरà¥à¤¨ Enter थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3634530185120165534">टà¥à¤°à¥‡ ५</translation>
+<translation id="3637662659967048211">Google खातामा सेभ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">à¤à¤ª:</translation>
<translation id="3650584904733503804">पà¥à¤°à¤®à¤¾à¤£à¥€à¤•à¤°à¤£ सफल भयो</translation>
@@ -750,6 +771,7 @@
<translation id="3781428340399460090">गाढा गà¥à¤²à¤¾à¤¬à¥€</translation>
<translation id="3783418713923659662">मासà¥à¤Ÿà¤°à¤•à¤¾à¤°à¥à¤¡</translation>
<translation id="3784372983762739446">बà¥à¤²à¥à¤Ÿà¥à¤¥ उपकरणहरू</translation>
+<translation id="3787675388804467730">भरà¥à¤šà¥à¤…ल कारà¥à¤¡ नमà¥à¤¬à¤°</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> मा मà¥à¤¯à¤¾à¤¦ सकिनà¥à¤›</translation>
<translation id="3789155188480882154">आकार १६</translation>
<translation id="3789841737615482174">सà¥à¤¥à¤¾à¤ªà¤¨à¤¾ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -769,6 +791,7 @@
<translation id="3841184659773414994">फाइल हà¥à¤¯à¤¾à¤¨à¥à¤¡à¥à¤²à¤°à¤¹à¤°à¥‚</translation>
<translation id="385051799172605136">पछाडि जानà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3858027520442213535">मिति र समय अपडेट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="3881478300875776315">कम हरफ देखाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3884278016824448484">विभेदातà¥à¤®à¤• यनà¥à¤¤à¥à¤° पहिचानकरà¥à¤¤à¤¾</translation>
<translation id="3885155851504623709">पà¥à¤¯à¤¾à¤°à¤¿à¤¸</translation>
<translation id="388632593194507180">निगरानी भइरहेको कà¥à¤°à¤¾ पतà¥à¤¤à¤¾ लागà¥à¤¯à¥‹</translation>
@@ -794,6 +817,7 @@
<translation id="397105322502079400">हिसाब गरà¥à¤¦à¥ˆ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> माथि रोक लगाइà¤à¤•à¥‹ छ।</translation>
<translation id="3973357910713125165">Chrome को सà¥à¤°à¤•à¥à¤·à¤¾ जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ नामक बटन, Chrome को सेटिङमा गई सà¥à¤°à¤•à¥à¤·à¤¾ जाà¤à¤š गरà¥à¤¨ Enter थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="3986705137476756801">अहिलेका लागि लाइभ कà¥à¤¯à¤¾à¤ªà¥à¤¸à¤¨ अफ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="3987405730340719549">Chrome ले यो साइट नकà¥à¤•à¤²à¥€ वा छलपूरà¥à¤£ हà¥à¤¨ सकà¥à¤› भनà¥à¤¨à¥‡ कà¥à¤°à¤¾ पतà¥à¤¤à¤¾ लगाà¤à¤•à¥‹ छ।
तपाईंलाई यो तà¥à¤°à¥à¤Ÿà¤¿à¤µà¤¶ देखाइà¤à¤•à¥‹ हो जसà¥à¤¤à¥‹ लागà¥à¤› भने कृपया https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals मा जानà¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
@@ -889,13 +913,14 @@
<translation id="4275830172053184480">आफà¥à¤¨à¥‹ यनà¥à¤¤à¥à¤°à¤²à¤¾à¤ˆ फेरि सà¥à¤°à¥ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4277028893293644418">पासवरà¥à¤¡ रिसेट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{यो कारà¥à¤¡à¤²à¤¾à¤ˆ तपाईंको Google खातामा सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरिà¤à¤•à¥‹ छ।}other{यी कारà¥à¤¡à¤¹à¤°à¥‚लाई तपाईंको Google खातामा सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरिà¤à¤•à¥‹ छ}}</translation>
+<translation id="4287885627794386150">टà¥à¤°à¤¾à¤¯à¤² पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨ सकिनà¥à¤› तर यो सकà¥à¤°à¤¿à¤¯ छैन</translation>
<translation id="4297502707443874121">पृषà¥à¤  <ph name="THUMBNAIL_PAGE" /> को थमà¥à¤¬à¤¨à¥‡à¤²</translation>
<translation id="42981349822642051">विसà¥à¤¤à¥ƒà¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4300675098767811073">दायाà¤à¤ªà¤Ÿà¥à¤Ÿà¤¿ à¤à¤•à¤­à¤¨à¥à¤¦à¤¾ बढी पà¥à¤µà¤¾à¤²</translation>
<translation id="4302514097724775343">पà¥à¤²à¥‡ गरà¥à¤¨ dino मा टà¥à¤¯à¤¾à¤ª गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">तपाईंको फाइल हेरà¥à¤¨ र पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨ सकिà¤à¤¨</translation>
-<translation id="4305817255990598646">सà¥à¤µà¤¿à¤š</translation>
+<translation id="4306529830550717874">ठेगाना सेभ गरà¥à¤¨à¥‡ हो?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">रोक लगाउनà¥à¤¹à¥‹à¤¸à¥ (डिफलà¥à¤Ÿ मान)</translation>
<translation id="4314815835985389558">सिंक वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -922,6 +947,7 @@
<translation id="4377125064752653719">तपाइà¤à¤²à¥‡ <ph name="DOMAIN" /> मा पà¥à¤—à¥à¤¨à¥‡ परà¥à¤¯à¤¾à¤¸ गरà¥à¤¨à¥à¤­à¤¯à¥‹, तर सरà¥à¤­à¤°à¤²à¥‡ पà¥à¤°à¤¸à¥à¤¤à¥à¤¤ गरेको पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° तà¥à¤¯à¤¸à¤•à¥‹ जारीकरà¥à¤¤à¤¾à¤¦à¥à¤µà¤¾à¤°à¤¾ रिभोक गरिà¤à¤•à¥‹ छ। यसको अरà¥à¤¥ सरà¥à¤­à¤°à¤²à¥‡ पà¥à¤°à¤¸à¥à¤¤à¥à¤¤ गरेको सà¥à¤°à¤•à¥à¤·à¤¾ पतà¥à¤¯à¤¾à¤°à¤ªà¤¤à¥à¤°à¤¹à¤°à¥‚ विशà¥à¤µà¤¾à¤¸ गरिनà¥à¤¹à¥à¤¨à¥à¤¨à¥¤ तपाइठà¤à¤• आकà¥à¤°à¤®à¤£à¤•à¤°à¥à¤¤à¤¾ सà¤à¤— सञà¥à¤šà¤¾à¤° गरिरहनà¥à¤­à¤à¤•à¥‹ हà¥à¤¨ सकà¥à¤›à¥¤</translation>
<translation id="4378154925671717803">फोन</translation>
<translation id="4390472908992056574">बिट</translation>
+<translation id="4406883609789734330">लाइभ कà¥à¤¯à¤¾à¤ªà¥à¤¸à¤¨</translation>
<translation id="4406896451731180161">खोजका परिणाम</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> कà¥à¤•à¥€à¤¹à¤°à¥‚</translation>
<translation id="4414290883293381923">तपाईंले भरà¥à¤–रै कà¥à¤¨à¥ˆ भà¥à¤°à¤¾à¤®à¤• साइटमा आफà¥à¤¨à¥‹ पासवरà¥à¤¡ पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ छ। Chrome ले <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> <ph name="WEBSITE_3" />, र तपाईंले यो पासवरà¥à¤¡ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥‡ अनà¥à¤¯ साइटहरूमा गई आफà¥à¤¨à¥‹ पासवरà¥à¤¡ अहिले नै बदलà¥à¤¨ सिफारिस गरà¥à¤›à¥¤</translation>
@@ -929,12 +955,11 @@
<translation id="4424024547088906515">यो सरà¥à¤­à¤°à¤²à¥‡ यो <ph name="DOMAIN" /> को भनि पà¥à¤°à¤®à¤¾à¤£à¤¿à¤¤ गरà¥à¤¨ सकेन; यसको सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤°à¤²à¤¾à¤ˆ Chrome ले विशà¥à¤µà¤¾à¤¸ गरà¥à¤¦à¥ˆà¤¨à¥¤ यो कà¥à¤¨à¥ˆ à¤à¤‰à¤Ÿà¤¾ मिसकनà¥à¤«à¤¿à¤—रेसन वा कà¥à¤¨à¥ˆ आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤²à¥‡ तपाईंको जडानमा गरेको हसà¥à¤¤à¤•à¥à¤·à¥‡à¤ªà¤•à¥‹ कारणले गरà¥à¤¦à¤¾ भà¤à¤•à¥‹ हà¥à¤¨ सकà¥à¤›à¥¤</translation>
<translation id="443121186588148776">कà¥à¤°à¤®à¤¿à¤• पोरà¥à¤Ÿ</translation>
<translation id="4432688616882109544"><ph name="HOST_NAME" /> ले तपाईà¤à¤•à¥‹ लग इन समà¥à¤¬à¤¨à¥à¤§à¥€ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° सà¥à¤µà¥€à¤•à¤¾à¤° गरेन वा कà¥à¤¨à¥ˆ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° पà¥à¤°à¤¦à¤¾à¤¨ गरिà¤à¤•à¥ˆ थिà¤à¤¨à¥¤</translation>
-<translation id="4432792777822557199"><ph name="SOURCE_LANGUAGE" /> मा रहेका पृषà¥à¤ à¤¹à¤°à¥‚लाई अब उपà¥à¤°à¤¾à¤¨à¥à¤¤ <ph name="TARGET_LANGUAGE" /> मा अनà¥à¤µà¤¾à¤¦ गरिनेछ</translation>
+<translation id="4432792777822557199"><ph name="SOURCE_LANGUAGE" /> मा रहेका पृषà¥à¤ à¤¹à¤°à¥‚लाई अब उपà¥à¤°à¤¾à¤¨à¥à¤¤ <ph name="TARGET_LANGUAGE" /> मा अनà¥à¤µà¤¾à¤¦ गरिने छ</translation>
<translation id="4434045419905280838">पपअप तथा रिडिरेकà¥à¤Ÿà¤¹à¤°à¥‚</translation>
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">पà¥à¤°à¥‹à¤•à¥à¤¸à¥€à¤•à¥‹ पà¥à¤°à¤¯à¥‹à¤— असकà¥à¤·à¤® गरिà¤à¤•à¥‹ छ तर à¤à¤• सà¥à¤¸à¥à¤ªà¤·à¥à¤Ÿ पà¥à¤°à¥‹à¤•à¥à¤¸à¥€ विनà¥à¤¯à¤¾à¤¸ तोकिà¤à¤•à¥‹ छ।</translation>
<translation id="4464826014807964867">तपाईंको सङà¥à¤—ठनले पà¥à¤°à¤¦à¤¾à¤¨ गरेको जानकारी भà¤à¤•à¤¾ वेबसाइटहरू</translation>
-<translation id="4466881336512663640">फारममा गरिà¤à¤•à¤¾ परिवरà¥à¤¤à¤¨à¤¹à¤°à¥‚ हराउने छनà¥à¥¤ तपाईंले जारी राखà¥à¤¨ खोजà¥à¤¨à¥à¤­à¤à¤•à¥ˆ हो?</translation>
<translation id="4476953670630786061">यो फारम सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ छैन। अटोफिल सà¥à¤µà¤¿à¤§à¤¾ अफ गरिà¤à¤•à¥‹ छ।</translation>
<translation id="4477350412780666475">अरà¥à¤•à¥‹ टà¥à¤°à¥à¤¯à¤¾à¤•</translation>
<translation id="4482953324121162758">यो साइटको अनà¥à¤µà¤¾à¤¦ गरिने छैन।</translation>
@@ -968,6 +993,7 @@
<translation id="4594403342090139922">मेटाइलाई &amp;पूरà¥à¤µà¤µà¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4597348597567598915">आकार ८</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">पà¥à¤°à¤­à¤¾à¤µà¤¶à¤¾à¤²à¥€</translation>
<translation id="4628948037717959914">तसà¥à¤¬à¤¿à¤°</translation>
<translation id="4631649115723685955">यो कारà¥à¤¡à¤®à¤¾à¤°à¥à¤«à¤¤ भà¥à¤•à¥à¤¤à¤¾à¤¨à¥€ गरà¥à¤¦à¤¾ कà¥à¤¯à¤¾à¤¸à¤¬à¥à¤¯à¤¾à¤• पाइनà¥à¤›</translation>
<translation id="4636930964841734540">जानकारी</translation>
@@ -987,6 +1013,7 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">सतह</translation>
+<translation id="4702656508969495934">लाइभ कà¥à¤¯à¤¾à¤ªà¥à¤¸à¤¨ देखिइरहेको छ, फोकस सारेर अरà¥à¤•à¥‹ डायलगमा लैजान विनà¥à¤¡à¥‹ सà¥à¤µà¤¿à¤šà¤° पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4708268264240856090">तपाईंको जडानमा अवरोध भयो</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows नेटवरà¥à¤• समà¥à¤¬à¤¨à¥à¤§à¥€ निदान चलाà¤à¤° हेरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥<ph name="END_LINK" /></translation>
@@ -1000,6 +1027,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> को खोजसमà¥à¤¬à¤¨à¥à¤§à¥€ सà¥à¤à¤¾à¤µ</translation>
<translation id="4742407542027196863">पासवरà¥à¤¡à¤¹à¤°à¥‚को वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥â€¦</translation>
<translation id="4744603770635761495">कारà¥à¤¯à¤¾à¤¨à¥à¤µà¤¯à¤¨à¤¯à¥‹à¤—à¥à¤¯ मारà¥à¤—</translation>
+<translation id="4749011317274908093">तपाईं इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोडमा जानà¥à¤­à¤à¤•à¥‹ छ</translation>
<translation id="4750917950439032686">यस साइटमा तपाईà¤à¤•à¥‹ जानकारी (उदाहरणका लागि पासवरà¥à¤¡ वा कà¥à¤°à¥‡à¤¡à¤¿à¤Ÿ कारà¥à¤¡à¤•à¥‹ नमà¥à¤¬à¤°) पठाउà¤à¤¦à¤¾ तà¥à¤¯à¥‹ निजी रहनà¥à¤›à¥¤</translation>
<translation id="4756388243121344051">&amp;इतिहास</translation>
<translation id="4758311279753947758">समà¥à¤ªà¤°à¥à¤• बारे जानकारी थपà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -1029,6 +1057,8 @@
<translation id="4813512666221746211">सञà¥à¤œà¤¾à¤² तà¥à¤°à¥à¤Ÿà¤¿</translation>
<translation id="4816492930507672669">पृषà¥à¤ à¤®à¤¾ अटाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="4819347708020428563">à¤à¤¨à¥‹à¤Ÿà¥‡à¤¸à¤¨à¤¹à¤°à¥‚ डिफलà¥à¤Ÿ भà¥à¤¯à¥‚मा समà¥à¤ªà¤¾à¤¦à¤¨ गरà¥à¤¨à¥‡ हो?</translation>
+<translation id="4825507807291741242">शकà¥à¤¤à¤¿à¤¶à¤¾à¤²à¥€</translation>
+<translation id="4838327282952368871">सà¥à¤µà¤ªà¥à¤¨à¤¿à¤²</translation>
<translation id="484462545196658690">सà¥à¤µà¤¤à¤ƒ</translation>
<translation id="4850886885716139402">हेरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="485316830061041779">जरà¥à¤®à¤¨</translation>
@@ -1165,6 +1195,7 @@
<translation id="5314967030527622926">पà¥à¤¸à¥à¤¤à¤¿à¤•à¤¾ निरà¥à¤®à¤¾à¤¤à¤¾</translation>
<translation id="5316812925700871227">घडीको विपरीत दिशामा घà¥à¤®à¤¾à¤‰à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="5317780077021120954">बचत गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="5321288445143113935">ठà¥à¤²à¥‹ पारिà¤à¤•à¥‹</translation>
<translation id="5323105697514565458"><ph name="NUM_MATCHES" /> मधà¥à¤¯à¥‡ <ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">समà¥à¤ªà¤°à¥à¤•à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ जानकारी छनौट गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="5327248766486351172">नाम</translation>
@@ -1172,11 +1203,13 @@
<translation id="5332219387342487447">ढà¥à¤µà¤¾à¤¨à¥€à¤•à¥‹ विधि</translation>
<translation id="5333022057423422993">Chrome ले तपाईंले भरà¥à¤–रै पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ पासवरà¥à¤¡ डेटा चोरीको घटनामा खà¥à¤²à¤¾à¤¸à¤¾ गरिà¤à¤•à¥‹ पतà¥à¤¤à¤¾ लगायो। हामी तपाईंलाई अहिले नै आफूले सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरेका पासवरà¥à¤¡à¤¹à¤°à¥‚ जाà¤à¤š गरेर आफà¥à¤¨à¤¾ खाता सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ राखà¥à¤¨ सिफारिस गरà¥à¤›à¥Œà¤à¥¤</translation>
<translation id="5334013548165032829">पà¥à¤°à¤£à¤¾à¤²à¥€à¤•à¤¾ विसà¥à¤¤à¥ƒà¤¤ लगहरू</translation>
+<translation id="5334145288572353250">ठेगाना सेभ गरà¥à¤¨à¥‡ हो?</translation>
<translation id="5340250774223869109">à¤à¤ªà¤®à¤¾à¤¥à¤¿ रोक लगाइà¤à¤•à¥‹ छ</translation>
<translation id="534295439873310000">NFC यनà¥à¤¤à¥à¤°à¤¹à¤°à¥‚</translation>
<translation id="5344579389779391559">यो पृषà¥à¤ à¤²à¥‡ तपाईंलाई पैसा तिराउने पà¥à¤°à¤¯à¤¾à¤¸ गरà¥à¤¨ सकà¥à¤›</translation>
<translation id="5355557959165512791">यो साइटको पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° खारेज गरिà¤à¤•à¥‹ हà¥à¤¨à¤¾à¤²à¥‡ तपाईं अहिले नै <ph name="SITE" /> मा जान सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤¨à¥¤ नेटवरà¥à¤•à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ तà¥à¤°à¥à¤Ÿà¤¿ र आकà¥à¤°à¤®à¤£à¤¹à¤°à¥‚ सामानà¥à¤¯à¤¤à¤¯à¤¾ असà¥à¤¥à¤¾à¤¯à¥€ हà¥à¤¨à¥à¤›à¤¨à¥, तà¥à¤¯à¤¸à¥ˆà¤²à¥‡ यो पृषà¥à¤ à¤²à¥‡ पछि समà¥à¤­à¤µà¤¤à¤ƒ काम गरà¥à¤¨à¤¸à¤•à¥à¤¨à¥‡à¤›à¥¤</translation>
<translation id="536296301121032821">नीति सेटिङहरू भणà¥à¤¡à¤¾à¤°à¤£ गरà¥à¤¨ असफल भयो</translation>
+<translation id="5363309033720083897">तपाईंका à¤à¤¡à¥à¤®à¤¿à¤¨à¤²à¥‡ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥‡ अनà¥à¤®à¤¤à¤¿ दिनà¥à¤­à¤à¤•à¥‹ सिरियल पोरà¥à¤Ÿ</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="5386426401304769735">यस साइटको पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° शà¥à¤°à¥ƒà¤‚खलामा SHA-१ पà¥à¤°à¤¯à¥‹à¤— गरी हसà¥à¤¤à¤¾à¤•à¥à¤·à¤° गरिà¤à¤•à¥‹ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° समावेश छ।</translation>
@@ -1185,6 +1218,7 @@
<translation id="5398772614898833570">विजà¥à¤žà¤¾à¤ªà¤¨à¤¹à¤°à¥‚माथि रोक लगाइयो</translation>
<translation id="5400836586163650660">खरानी रङà¥à¤—</translation>
<translation id="540969355065856584">यो सरà¥à¤­à¤°à¤²à¥‡ <ph name="DOMAIN" /> हो भने साबित गरà¥à¤¨ सकेन; यस समयमा यसको सà¥à¤°à¤•à¥à¤·à¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° मानà¥à¤¯ छैन। यो कनà¥à¤«à¤¿à¤—à¥à¤°à¥‡à¤¸à¤¨ गलत भà¤à¤° वा à¤à¤‰à¤Ÿà¤¾ आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤²à¥‡ तपाईà¤à¤•à¥‹ जडान रोकेर भà¤à¤•à¥‹ हà¥à¤¨à¥ सकà¥à¤›à¥¤</translation>
+<translation id="541143247543991491">कà¥à¤²à¤¾à¤‰à¤¡ (पà¥à¤°à¤£à¤¾à¤²à¥€à¤µà¥à¤¯à¤¾à¤ªà¥€)</translation>
<translation id="541416427766103491">सà¥à¤Ÿà¥à¤¯à¤¾à¤•à¤° ४</translation>
<translation id="5421136146218899937">बà¥à¤°à¤¾à¤‰à¤œà¤¿à¤™ डाटा खाली गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> तपाईंलाई सूचनाहरू पठाउन चाहनà¥à¤›</translation>
@@ -1198,6 +1232,7 @@
<translation id="5455374756549232013">खराब नीति टाइमसà¥à¤Ÿà¥à¤¯à¤¾à¤®à¥à¤ª</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" />}other{<ph name="CONTACT_PREVIEW" /> र थप <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
+<translation id="5463625433003343978">यनà¥à¤¤à¥à¤°à¤¹à¤°à¥‚ पतà¥à¤¤à¤¾ लगाइà¤à¤¦à¥ˆ छ...</translation>
<translation id="5469868506864199649">इटालियन</translation>
<translation id="5470861586879999274">समà¥à¤ªà¤¾à¤¦à¤¨ &amp;पà¥à¤¨: गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1247,7 +1282,6 @@
<translation id="5624120631404540903">पासवरà¥à¤¡à¤¹à¤°à¥‚ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</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="563324245173044180">भà¥à¤°à¤¾à¤®à¤• सामगà¥à¤°à¥€à¤®à¤¾à¤¥à¤¿ रोक लगाइयो।</translation>
<translation id="5644090287519800334">सतह १ मा रहेको छविको X सिफà¥à¤Ÿ</translation>
@@ -1286,12 +1320,12 @@
<translation id="5785756445106461925">यसबाहेक, यस पृषà¥à¤ à¤²à¥‡ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नभà¤à¤•à¤¾ अनà¥à¤¯ संसाधनहरू समावेश गरà¥à¤›à¥¤ यी सà¥à¤°à¥‹à¤¤à¤¹à¤°à¥‚ टà¥à¤°à¤¾à¤¨à¥à¤œà¤¿à¤Ÿà¤®à¤¾ भà¤à¤•à¥‹ बेला अनà¥à¤¯à¤²à¥‡ हेरà¥à¤¨ सकà¥à¤›à¤¨à¥, र पृषà¥à¤ à¤•à¥‹ दृशà¥à¤¯ परिवरà¥à¤¤à¤¨ गरà¥à¤¨ कà¥à¤¨à¥ˆ आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤¦à¥à¤µà¤¾à¤°à¤¾ परिमारà¥à¤œà¤¨ गरà¥à¤¨ सकिनà¥à¤›à¥¤</translation>
<translation id="5786044859038896871">तपाईं आफà¥à¤¨à¥‹ कारà¥à¤¡ समà¥à¤¬à¤¨à¥à¤§à¥€ जानकारी भरà¥à¤¨ चाहनà¥à¤¹à¥à¤¨à¥à¤›?</translation>
<translation id="578633867165174378">Chrome ले तपाईंले भरà¥à¤–रै पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ पासवरà¥à¤¡ डेटा चोरीको घटनामा खà¥à¤²à¤¾à¤¸à¤¾ गरिà¤à¤•à¥‹ पतà¥à¤¤à¤¾ लगायो। हामी तपाईंलाई अहिले नै यो पासवरà¥à¤¡ बदलà¥à¤¨ सिफारिस गरà¥à¤›à¥Œà¤à¥¤</translation>
-<translation id="5798290721819630480">परिवरà¥à¤¤à¤¨à¤¹à¤°à¥‚ खारेज गरà¥à¤¨à¥‡ हो?</translation>
<translation id="5803412860119678065">तपाईं आफà¥à¤¨à¥‹ <ph name="CARD_DETAIL" /> समà¥à¤¬à¤¨à¥à¤§à¥€ जानकारी भरà¥à¤¨ चाहनà¥à¤¹à¥à¤¨à¥à¤›?</translation>
<translation id="5804241973901381774">अनà¥à¤®à¤¤à¤¿à¤¹à¤°à¥‚</translation>
<translation id="5804427196348435412">NFC यनà¥à¤¤à¥à¤°à¤¹à¤°à¥‚ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="5810442152076338065">तपाईà¤à¤•à¥‹ <ph name="DOMAIN" />सà¤à¤—को जडान पà¥à¤°à¤¾à¤¨à¥‹ साइफर सà¥à¤Ÿ पà¥à¤°à¤¯à¥‹à¤— गरेर इनà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ गरिà¤à¤•à¥‹ छ।</translation>
<translation id="5813119285467412249">थपà¥à¤¨à¥‡ कारà¥à¤¯ &amp;पà¥à¤¨: गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="5817918615728894473">जोडा बनाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{तपाईंले भà¥à¤•à¥à¤¤à¤¾à¤¨à¥€ गरà¥à¤¦à¤¾ यो कारà¥à¤¡à¤¬à¤¾à¤Ÿ पैसा काटिने छ तर यसको वासà¥à¤¤à¤µà¤¿à¤• नमà¥à¤¬à¤° भने यो साइटसà¤à¤— आदान पà¥à¤°à¤¦à¤¾à¤¨ गरिने छैन। अतिरिकà¥à¤¤ सà¥à¤°à¤•à¥à¤·à¤¾à¤•à¤¾ लागि à¤à¤‰à¤Ÿà¤¾ असà¥à¤¥à¤¾à¤¯à¥€ CVC सिरà¥à¤œà¤¨à¤¾ गरिने छ।}other{तपाईंले भà¥à¤•à¥à¤¤à¤¾à¤¨à¥€ गरà¥à¤¦à¤¾ तपाईंले चयन गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ कारà¥à¤¡à¤¬à¤¾à¤Ÿ पैसा काटिने छ तर यसको वासà¥à¤¤à¤µà¤¿à¤• नमà¥à¤¬à¤° भने यो साइटसà¤à¤— आदान पà¥à¤°à¤¦à¤¾à¤¨ गरिने छैन। अतिरिकà¥à¤¤ सà¥à¤°à¤•à¥à¤·à¤¾à¤•à¤¾ लागि à¤à¤‰à¤Ÿà¤¾ असà¥à¤¥à¤¾à¤¯à¥€ CVC सिरà¥à¤œà¤¨à¤¾ गरिने छ।}}</translation>
<translation id="5826507051599432481">साà¤à¤¾ नाम (CN)</translation>
<translation id="5838278095973806738">आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤¹à¤°à¥‚ले चोरी गरà¥à¤¨ सकà¥à¤¨à¥‡ हà¥à¤¨à¤¾à¤²à¥‡ तपाईà¤à¤²à¥‡ यस साइटमा कà¥à¤¨à¥ˆ संवेदनशील जानकारी (उदाहरणका लागि पासवरà¥à¤¡ वा कà¥à¤°à¥‡à¤¡à¤¿à¤Ÿ कारà¥à¤¡) पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ गरà¥à¤¨à¥ हà¥à¤à¤¦à¥ˆà¤¨à¥¤</translation>
@@ -1299,6 +1333,7 @@
<translation id="5855253129151731373">यो साइटको होसà¥à¤Ÿà¤¨à¤¾à¤® <ph name="LOOKALIKE_DOMAIN" /> जसà¥à¤¤à¥ˆ देखिनà¥à¤›à¥¤ आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤¹à¤°à¥‚ले कहिलेकाहीठडोमेनको नाममा ससाना, सà¥à¤ªà¤·à¥à¤Ÿ नदेखिने परिवरà¥à¤¤à¤¨à¤¹à¤°à¥‚ गरी नकà¥à¤•à¤²à¥€ साइट सिरà¥à¤œà¤¨à¤¾ गरà¥à¤¨ सकà¥à¤›à¤¨à¥à¥¤
तपाईंलाई यो तà¥à¤°à¥à¤Ÿà¤¿à¤µà¤¶ देखाइà¤à¤•à¥‹ हो जसà¥à¤¤à¥‹ लागà¥à¤› भने कृपया https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals मा जानà¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
+<translation id="5860033963881614850">बनà¥à¤¦</translation>
<translation id="5862579898803147654">सà¥à¤Ÿà¥à¤¯à¤¾à¤•à¤° ८</translation>
<translation id="5863847714970149516">अगाडि आउने पृषà¥à¤ à¤²à¥‡ तपाईंलाई पैसा तिराउने पà¥à¤°à¤¯à¤¾à¤¸ गरà¥à¤¨ सकà¥à¤›</translation>
<translation id="5866257070973731571">फोन नमà¥à¤¬à¤° थपà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -1315,6 +1350,7 @@
<translation id="5913377024445952699">सà¥à¤•à¥à¤°à¤¿à¤¨ कà¥à¤¯à¤¾à¤ªà¥à¤šà¤° गरà¥à¤¨à¥‡ सà¥à¤µà¤¿à¤§à¤¾ पज गरियो</translation>
<translation id="59174027418879706">सकà¥à¤·à¤® गरिà¤à¤•à¥‹</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{१ पà¥à¤°à¤¯à¥‹à¤—मा छ}other{# पà¥à¤°à¤¯à¥‹à¤—मा छनà¥}}</translation>
<translation id="5921185718311485855">सकà¥à¤°à¤¿à¤¯ छ</translation>
<translation id="5921639886840618607">कारà¥à¤¡à¤²à¤¾à¤ˆ Google खातामा सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरà¥à¤¨à¥‡ हो?</translation>
<translation id="5922853866070715753">लगभग सकियो</translation>
@@ -1334,6 +1370,7 @@
<translation id="5989320800837274978">न त निशà¥à¤šà¤¿à¤¤ पà¥à¤°à¥‹à¤•à¥à¤¸à¥€ सरà¥à¤­à¤°à¤¹à¤°à¥‚ न त .पà¥à¤¯à¤¾à¤• सà¥à¤•à¥à¤°à¤¿à¤ªà¥à¤Ÿ यà¥à¤†à¤°à¤à¤²à¤¹à¤°à¥‚ तोकिà¤à¤•à¤¾ छनà¥à¥¤</translation>
<translation id="5992691462791905444">इनà¥à¤œà¤¿à¤¨à¤¿à¤¯à¤°à¤¿à¤™ जेड फोलà¥à¤¡</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' मधà¥à¤¯à¥‡ <ph name="RESULT_COUNT" /></translation>
+<translation id="6006484371116297560">कà¥à¤²à¤¾à¤¸à¤¿à¤•</translation>
<translation id="6008122969617370890">N देखि १ समà¥à¤®à¤•à¥‹ कà¥à¤°à¤®</translation>
<translation id="6008256403891681546">जेसिबी</translation>
<translation id="6014801569448771146">आफà¥à¤¨à¤¾ पासवरà¥à¤¡à¤¹à¤°à¥‚को जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -1355,6 +1392,7 @@
<translation id="6045164183059402045">इमà¥à¤ªà¥‹à¤œà¤¿à¤¸à¤¨ टेमà¥à¤ªà¥à¤²à¥‡à¤Ÿ</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="6049004884579590341">पूरà¥à¤£ सà¥à¤•à¥à¤°à¤¿à¤¨à¤¬à¤¾à¤Ÿ बाहिरिन |<ph name="ACCELERATOR" />| थिचिराखà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6049488691372270142">पृषà¥à¤ à¤•à¥‹ डेलिभरी</translation>
<translation id="6051221802930200923">उकà¥à¤¤ वेबसाइटले पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤°à¤•à¥‹ पिनिङ सà¥à¤°à¤•à¥à¤·à¤¾ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤•à¥‹ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥‡ हà¥à¤¨à¤¾à¤²à¥‡ तपाईं अहिले नै <ph name="SITE" /> मा जान सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤¨à¥¤ नेटवरà¥à¤•à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ तà¥à¤°à¥à¤Ÿà¤¿ र आकà¥à¤°à¤®à¤£à¤¹à¤°à¥‚ सामानà¥à¤¯à¤¤à¤¯à¤¾ असà¥à¤¥à¤¾à¤¯à¥€ हà¥à¤¨à¥à¤›à¤¨à¥, तà¥à¤¯à¤¸à¥ˆà¤²à¥‡ यो पृषà¥à¤ à¤²à¥‡ पछि समà¥à¤­à¤µà¤¤à¤ƒ काम गरà¥à¤¨à¤¸à¤•à¥à¤¨à¥‡à¤›à¥¤</translation>
<translation id="6051898664905071243">पेजको सङà¥à¤–à¥à¤¯à¤¾:</translation>
@@ -1369,8 +1407,9 @@
<translation id="6106989379647458772"><ph name="PAGE" /> को वेबपृषà¥à¤  असà¥à¤¥à¤¾à¤¯à¥€ रूपमा बनà¥à¤¦ भà¤à¤•à¥‹ हà¥à¤¨ सकà¥à¤› वा तà¥à¤¯à¥‹ सà¥à¤¥à¤¾à¤¯à¥€ रूपमा à¤à¤‰à¤Ÿà¤¾ नयाठवेब ठेगानामा सरेको हà¥à¤¨ सकà¥à¤›à¥¤</translation>
<translation id="6107012941649240045">लाई जारी गरिà¤à¤•à¥‹</translation>
<translation id="610911394827799129">तपाईंको Google खाताको <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> मा बà¥à¤°à¤¾à¤‰à¤œà¤¿à¤™ इतिहासका अनà¥à¤¯ ढाà¤à¤šà¤¾à¤¹à¤°à¥‚ रहेका हà¥à¤¨à¤¸à¤•à¥à¤›à¤¨à¥à¥¤</translation>
-<translation id="6116338172782435947">कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡à¤®à¤¾ पà¥à¤°à¤¤à¤¿à¤²à¤¿à¤ªà¤¿ गरिà¤à¤•à¤¾ पाठ र छविहरू हेरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="6116338172782435947">कà¥à¤²à¤¿à¤ªà¤¬à¥‹à¤°à¥à¤¡à¤®à¤¾ पà¥à¤°à¤¤à¤¿à¤²à¤¿à¤ªà¤¿ गरिà¤à¤•à¤¾ पाठ र फोटो हेरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6120179357481664955">आफà¥à¤¨à¥‹ UPI ID समà¥à¤à¤¨à¥‡ हो?</translation>
+<translation id="6123290840358279103">भरà¥à¤šà¥à¤…ल कारà¥à¤¡ हेरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6124432979022149706">Chrome Enterprise का कनेकà¥à¤Ÿà¤°à¤¹à¤°à¥‚</translation>
<translation id="6146055958333702838">तपाइà¤à¤²à¥‡ पà¥à¤°à¤¯à¥‹à¤— गरिेहेको कà¥à¤¨à¥ˆ पनि केबà¥à¤²à¤¹à¤°à¥‚ जाà¤à¤šà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ र कà¥à¤¨à¥ˆ पनि राउटरहरू, मोडेमहरू, वा अनà¥à¤¯
नेटवरà¥à¤• यनà¥à¤¤à¥à¤°à¤¹à¤°à¥‚ रिबà¥à¤Ÿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
@@ -1407,6 +1446,7 @@
<translation id="6289939620939689042">पृषà¥à¤ à¤•à¥‹ रङ</translation>
<translation id="6290238015253830360">तपाईंका सà¥à¤à¤¾à¤µ गरिà¤à¤•à¤¾ लेखहरू यहाठदेखिनà¥à¤›à¤¨à¥</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome को Google सहायक रोकिà¤à¤¦à¥ˆ छ</translation>
<translation id="6305205051461490394"><ph name="URL" /> पहà¥à¤à¤š गरà¥à¤¨ सकिà¤à¤¦à¥ˆà¤¨à¥¤</translation>
<translation id="6312113039770857350">वेबपृषà¥à¤  उपलबà¥à¤§ छैन</translation>
@@ -1432,6 +1472,7 @@
<translation id="6390200185239044127">आधा जेड फोलà¥à¤¡</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">à¤à¤¡à¥à¤®à¤¿à¤¨à¤²à¥‡ <ph name="ORIGIN_NAME" /> बाट कपी गरी यो सà¥à¤¥à¤¾à¤¨à¤®à¤¾ पेसà¥à¤Ÿ गरà¥à¤¨ रोक लगाउनà¥à¤­à¤à¤•à¥‹ छ</translation>
+<translation id="6398765197997659313">पूरà¥à¤£ सà¥à¤•à¥à¤°à¤¿à¤¨à¤²à¤¾à¤ˆ हटाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6401136357288658127">यो नीति चलà¥à¤¤à¥€à¤¬à¤¾à¤Ÿ हटाइà¤à¤•à¥‹ छ। तपाईंले यसको साटो <ph name="NEW_POLICY" /> नीति पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥ परà¥à¤›à¥¤</translation>
<translation id="6404511346730675251">बà¥à¤•à¤®à¤¾à¤°à¥à¤• समà¥à¤ªà¤¾à¤¦à¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1444,7 +1485,6 @@
<translation id="6428450836711225518">आफà¥à¤¨à¥‹ फोन नमà¥à¤¬à¤°à¤•à¥‹ पà¥à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6433490469411711332">समà¥à¤ªà¤°à¥à¤• समà¥à¤¬à¤¨à¥à¤§à¥€ जानकारीलाई समà¥à¤ªà¤¾à¤¦à¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ले जडान गरà¥à¤¨ असà¥à¤µà¥€à¤•à¤¾à¤° गरà¥à¤¯à¥‹à¥¤</translation>
-<translation id="6434309073475700221">तà¥à¤¯à¤¾à¤—à¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6440503408713884761">उपेकà¥à¤·à¤¿à¤¤</translation>
<translation id="6443406338865242315">तपाईंले सà¥à¤¥à¤¾à¤ªà¤¨à¤¾ गरà¥à¤¨à¥à¤­à¤à¤•à¤¾ विसà¥à¤¤à¤¾à¤° र पà¥à¤²à¤—इनहरू</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1487,6 +1527,7 @@
<translation id="6624427990725312378">समà¥à¤ªà¤°à¥à¤•à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ जानकारी</translation>
<translation id="6626291197371920147">कारà¥à¤¡à¤•à¥‹ मानà¥à¤¯ नमà¥à¤¬à¤° थपà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> खोज</translation>
+<translation id="6630043285902923878">USB यनà¥à¤¤à¥à¤°à¤¹à¤°à¥‚ खोजिà¤à¤¦à¥ˆ छनà¥...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">खालि गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -1502,6 +1543,7 @@
<translation id="6671697161687535275">Chromium बाट फारम सà¥à¤à¤¾à¤µ हटाउने हो?</translation>
<translation id="6685834062052613830">साइन आउट गरेर सेटअपलाई समà¥à¤ªà¤¨à¥à¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="6687335167692595844">फनà¥à¤Ÿà¤•à¥‹ अनà¥à¤°à¥‹à¤§ गरिà¤à¤•à¥‹ आकार</translation>
+<translation id="6688743156324860098">बदलà¥à¤¨à¥à¤¹à¥‹à¤¸à¥â€¦</translation>
<translation id="6689249931105087298">कालो बिनà¥à¤¦à¥à¤•à¥‹ कमà¥à¤ªà¥à¤°à¥‡à¤¸à¤¨à¤¸à¤à¤— सापेकà¥à¤·</translation>
<translation id="6689271823431384964">तपाईं साइन इन हà¥à¤¨à¥à¤­à¤à¤•à¤¾à¤²à¥‡ Chrome ले तपाईंको Google खातामा तपाईंका कारà¥à¤¡à¤¹à¤°à¥‚ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरिदिने पà¥à¤°à¤¸à¥à¤¤à¤¾à¤µ गरà¥à¤¦à¥ˆ छ। तपाईं सेटिङहरूमा गई उकà¥à¤¤ वà¥à¤¯à¤µà¤¹à¤¾à¤° परिवरà¥à¤¤à¤¨ गरà¥à¤¨ सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›à¥¤ कारà¥à¤¡à¤µà¤¾à¤¹à¤•à¤•à¥‹ नामका रूपमा तपाईंको खातामा भà¤à¤•à¥‹ नाम पà¥à¤°à¤¯à¥‹à¤— गरिनà¥à¤›à¥¤</translation>
<translation id="6698381487523150993">सिरà¥à¤œà¤¨à¤¾ गरिà¤à¤•à¥‹:</translation>
@@ -1517,6 +1559,7 @@
<translation id="6744009308914054259">इनà¥à¤Ÿà¤°à¤¨à¥‡à¤Ÿà¤•à¥‹ पà¥à¤°à¤¤à¥€à¤•à¥à¤·à¤¾ गरà¥à¤¦à¤¾ गरà¥à¤¦à¥ˆ तपाईं अफलाइन लेखहरू पढà¥à¤¨ डाउनलोडहरू नामक फोलà¥à¤¡à¤°à¤®à¤¾ जान सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›à¥¤</translation>
<translation id="6753269504797312559">नीति मूलà¥à¤¯</translation>
<translation id="6757797048963528358">तपाईंको यनà¥à¤¤à¥à¤° शयन अवसà¥à¤¥à¤¾à¤®à¤¾ गयो।</translation>
+<translation id="6767985426384634228">ठेगाना बदलà¥à¤¨à¥‡ हो?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">हलà¥à¤•à¤¾ निलो</translation>
@@ -1539,6 +1582,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome ले यो पृषà¥à¤  पढà¥à¤¨ अठसजिलो बनाउन यसलाई सरलीकृत गरà¥â€à¤¯à¥‹à¥¤ Chrome ले à¤à¤‰à¤Ÿà¤¾ असà¥à¤°à¤•à¥à¤·à¤¿à¤¤ इनà¥à¤Ÿà¤°à¤¨à¥‡à¤Ÿà¤®à¤¾à¤°à¥à¤«à¤¤ मूल पृषà¥à¤  पà¥à¤¨à¤ƒ पà¥à¤°à¤¾à¤ªà¥à¤¤ गरà¥â€à¤¯à¥‹à¥¤</translation>
<translation id="6891596781022320156">नीति तह समरà¥à¤¥à¤¿à¤¤ छैन।</translation>
+<translation id="6895143722905299846">भरà¥à¤šà¥à¤…ल कारà¥à¤¡ नमà¥à¤¬à¤°:</translation>
<translation id="6895330447102777224">तपाईंको कारà¥à¤¡à¤•à¥‹ पà¥à¤·à¥à¤Ÿà¤¿ भयो</translation>
<translation id="6897140037006041989">पà¥à¤°à¤¯à¥‹à¤—करà¥à¤¤à¤¾ à¤à¤œà¥‡à¤¨à¥à¤Ÿ</translation>
<translation id="6898699227549475383">संगठन (सं)</translation>
@@ -1574,10 +1618,10 @@
<translation id="7004583254764674281">कारà¥à¤¡à¤¹à¤°à¥‚ अठछिटो पà¥à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨ Windows Hello पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7006930604109697472">जे भठपनि पठाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7012363358306927923">चीन UnionPay</translation>
-<translation id="7012404007611495949">आकार बदलà¥à¤¨à¥‡à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ सेटिङ</translation>
<translation id="7014741021609395734">जà¥à¤®à¤•à¥‹ सà¥à¤¤à¤°</translation>
<translation id="7016992613359344582">यी शà¥à¤²à¥à¤•à¤¹à¤°à¥‚ à¤à¤• पटक तिरे पà¥à¤—à¥à¤¨à¥‡ वा बारमà¥à¤¬à¤¾à¤° तिरà¥à¤¨à¥ परà¥à¤¨à¥‡ हà¥à¤¨ सकà¥à¤›à¤¨à¥ र यस समà¥à¤¬à¤¨à¥à¤§à¤®à¤¾ सà¥à¤ªà¤·à¥à¤Ÿà¤¤à¤¾ नहà¥à¤¨ पनि सकà¥à¤›à¥¤</translation>
<translation id="7029809446516969842">पासवरà¥à¤¡à¤¹à¤°à¥‚</translation>
+<translation id="7030436163253143341">पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° वैध छैन</translation>
<translation id="7031646650991750659">तपाईंले सà¥à¤¥à¤¾à¤ªà¤¨à¤¾ गरà¥à¤¨à¥à¤­à¤à¤•à¤¾ Google Play à¤à¤ªà¤¹à¤°à¥‚</translation>
<translation id="7050187094878475250">तपाईं <ph name="DOMAIN" /> मा पà¥à¤—à¥à¤¨ पà¥à¤°à¤¯à¤¾à¤¸ गरà¥à¤¨à¥à¤­à¤¯à¥‹, तर सरà¥à¤­à¤°à¤²à¥‡ à¤à¤‰à¤Ÿà¤¾ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° पà¥à¤°à¤¸à¥à¤¤à¥à¤¤ गरà¥à¤¦à¤› जसको वैधानिकता अवधि भरोसा योगà¥à¤¯ हà¥à¤¨ निकै लामो छ।</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{यो कारà¥à¤¡ अहिले सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरà¥à¤¨ सकिà¤à¤¦à¥ˆà¤¨}other{यी कारà¥à¤¡à¤¹à¤°à¥‚ अहिले सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरà¥à¤¨ सकिà¤à¤¦à¥ˆà¤¨}}</translation>
@@ -1647,12 +1691,14 @@
<translation id="7300012071106347854">कोबालà¥à¤Ÿ निलो</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">उचà¥à¤š</translation>
+<translation id="7305756307268530424">अठसà¥à¤¸à¥à¤¤ गतिमा सà¥à¤°à¥ गरियोसà¥</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">जडानसमà¥à¤¬à¤¨à¥à¤§à¥€ मदà¥à¤¦à¤¤</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" खणà¥à¤¡ लà¥à¤•à¤¾à¤‡à¤¯à¥‹à¤¸à¥</translation>
<translation id="733354035281974745">डिभाइसका सà¥à¤¥à¤¾à¤¨à¥€à¤¯ खाताको ओभरराइड</translation>
<translation id="7333654844024768166">तपाईंले भरà¥à¤–रै कà¥à¤¨à¥ˆ भà¥à¤°à¤¾à¤®à¤• साइटमा आफà¥à¤¨à¥‹ पासवरà¥à¤¡ पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ छ। Chromium ले <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> र तपाईंले यो पासवरà¥à¤¡ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥‡ अनà¥à¤¯ साइटहरूमा गई तपाईंको पासवरà¥à¤¡ अहिले नै बदलà¥à¤¨ सिफारिस गरà¥à¤›à¥¤</translation>
<translation id="7334320624316649418">कà¥à¤°à¤® परिवरà¥à¤¤à¤¨ &amp;पà¥à¤¨: गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="7337248890521463931">थप हरफ देखाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7337706099755338005">तपाईंको पà¥à¤²à¥‡à¤Ÿà¤«à¤°à¥à¤®à¤®à¤¾ उपलबà¥à¤§ छैन।</translation>
<translation id="733923710415886693">पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤°à¤•à¥‹ पारदरà¥à¤¶à¤¿à¤¤à¤¾ नीति मारà¥à¤«à¤¤ सरà¥à¤­à¤°à¤•à¥‹ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤°à¤•à¥‹ खà¥à¤²à¤¾à¤¸à¤¾ भà¤à¤¨à¥¤</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1660,6 +1706,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">आदेश रेखा</translation>
<translation id="7359588939039777303">विजà¥à¤žà¤¾à¤ªà¤¨à¤¹à¤°à¥‚माथि रोक लगाइयो।</translation>
+<translation id="7363096869660964304">तथापि, तपाईंले गरà¥à¤¨à¥à¤­à¤à¤•à¤¾ सबै कà¥à¤°à¤¿à¤¯à¤¾à¤•à¤²à¤¾à¤ª कसैले देखà¥à¤¨ सकà¥à¤¦à¥ˆà¤¨ भनà¥à¤¨à¥‡ हà¥à¤à¤¦à¥ˆà¤¨à¥¤ तपाईंले इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोड पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤­à¤¯à¥‹ भने तपाईं आफà¥à¤¨à¥‹ रोजगारदाता, इनà¥à¤Ÿà¤°à¤¨à¥‡à¤Ÿ सेवा पà¥à¤°à¤¦à¤¾à¤¯à¤• वा आफूले पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥‡ वेबसाइटहरूसà¤à¤— आफà¥à¤¨à¥‹ बà¥à¤°à¤¾à¤‰à¤œà¤¿à¤™ इतिहास लà¥à¤•à¤¾à¤‰à¤¨ सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤¨à¥¤</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome का सेटिङमा गई ठेगानाहरू थपà¥à¤¨ तथा वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤¨ Tab थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ अनि Enter थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7365849542400970216">तपाईंलाई आफà¥à¤¨à¥‹ यनà¥à¤¤à¥à¤°à¤²à¥‡ के काम गरà¥à¤› भनà¥à¤¨à¥‡ कà¥à¤°à¤¾ थाहा छ?</translation>
<translation id="7372973238305370288">खोजको परिणाम</translation>
@@ -1670,7 +1717,9 @@
<translation id="7378594059915113390">मिडियासमà¥à¤¬à¤¨à¥à¤§à¥€ नियनà¥à¤¤à¥à¤°à¤£à¤¹à¤°à¥‚</translation>
<translation id="7378627244592794276">होइन</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">लागू नहà¥à¤¨à¥‡</translation>
<translation id="7390545607259442187">कारà¥à¤¡à¤•à¥‹ पà¥à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="7392089738299859607">ठेगाना परिवरà¥à¤¤à¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7399802613464275309">सà¥à¤°à¤•à¥à¤·à¤¾ जाà¤à¤š</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">तपाईंको <ph name="DEVICE_NAME" /> वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¿à¤¤ छ</translation>
@@ -1685,6 +1734,7 @@
&lt;li&gt;सफà¥à¤Ÿà¤µà¥‡à¤¯à¤°à¤²à¤¾à¤ˆ आफà¥à¤¨à¥‹ कमà¥à¤ªà¥à¤¯à¥à¤Ÿà¤°à¤¬à¤¾à¤Ÿ सदाका लागि हटाउने तरिकाबारे जानà¥à¤¨ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome को मदà¥à¤¦à¤¤ केनà¥à¤¦à¥à¤°&lt;/a&gt; मा जानà¥à¤¹à¥‹à¤¸à¥à¥¤
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">सà¥à¤¨à¥à¤¦à¤°</translation>
<translation id="7416351320495623771">पासवरà¥à¤¡à¤¹à¤°à¥‚को वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥â€¦</translation>
<translation id="7419106976560586862">पà¥à¤°à¥‹à¤«à¤¾à¤‡à¤² मारà¥à¤—</translation>
<translation id="7437289804838430631">समà¥à¤ªà¤°à¥à¤•à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ जानकारी थपà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -1700,7 +1750,7 @@
<translation id="7481312909269577407">अगाडि</translation>
<translation id="7485870689360869515">कà¥à¤¨à¥ˆà¤ªà¤¨à¤¿ डाटा भेटिà¤à¤¨à¥¤</translation>
<translation id="7495528107193238112">यो सामगà¥à¤°à¥€à¤²à¤¾à¤ˆ रोक लगाइà¤à¤•à¥‹ छ। यो समसà¥à¤¯à¤¾ समाधान गरà¥à¤¨ उकà¥à¤¤ साइटका मालिकसà¤à¤— समà¥à¤ªà¤°à¥à¤• गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
-<translation id="7498234416455752244">समà¥à¤ªà¤¾à¤¦à¤¨ गरिरहनà¥à¤¹à¥‹à¤¸à¥</translation>
+<translation id="7498193950643227031">तपाईंले à¤à¤ªà¤•à¥‹ आकार बदलà¥à¤¨à¥à¤­à¤¯à¥‹ भने à¤à¤ªà¤²à¥‡ अपà¥à¤°à¤¤à¥à¤¯à¤¾à¤¶à¤¿à¤¤ वà¥à¤¯à¤µà¤¹à¤¾à¤° देखाउन सकà¥à¤›à¥¤ तपाईं अब <ph name="SETTINGS" /> मा गई à¤à¤ªà¤•à¥‹ आकार बदलà¥à¤¨à¥‡ सà¥à¤µà¤¿à¤§à¤¾ सीमित पारà¥à¤¨ सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›à¥¤</translation>
<translation id="7503664977220660814">तपाईंले भरà¥à¤–रै कà¥à¤¨à¥ˆ भà¥à¤°à¤¾à¤®à¤• साइटमा आफà¥à¤¨à¥‹ पासवरà¥à¤¡ पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ छ। Chromium तपाईंलाई अहिले नै <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> र तपाईंले हाल यो पासवरà¥à¤¡ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥‡ अनà¥à¤¯ साइटका सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरिà¤à¤•à¤¾ पासवरà¥à¤¡à¤¹à¤°à¥‚को जाà¤à¤š गरà¥à¤¨ सिफारिस गरà¥à¤›à¥¤</translation>
<translation id="7508255263130623398">फिरà¥à¤¤à¤¾ गरिà¤à¤•à¥‹ नीति समà¥à¤¬à¤¨à¥à¤§à¥€ यनà¥à¤¤à¥à¤° खाली छ वा हालको यनà¥à¤¤à¥à¤°à¤•à¥‹ id सà¤à¤— मेल खाà¤à¤¦à¥ˆà¤¨</translation>
<translation id="7508870219247277067">गाढा हरियो</translation>
@@ -1720,6 +1770,7 @@
<translation id="7548892272833184391">जडानसमà¥à¤¬à¤¨à¥à¤§à¥€ तà¥à¤°à¥à¤Ÿà¤¿à¤¹à¤°à¥‚ ठिक गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7549584377607005141">यो वेबपृषà¥à¤  ठीकसà¤à¤— पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ हà¥à¤¨à¤•à¥‹ लागि यस वेबपृषà¥à¤ à¤²à¤¾à¤ˆ तपाइà¤à¤²à¥‡ पहिले पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿ गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ लगत आवशà¥à¤¯à¤• छ। तपाइà¤à¤²à¥‡ यो लगत फेरि पठाउन सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›, तर यसो गरà¥à¤¨à¤¾à¤²à¥‡ यस पृषà¥à¤ à¤²à¥‡ पहिले पà¥à¤°à¤¦à¤¦à¤°à¥à¤¶à¤¨ गरेको कà¥à¤¨à¥ˆ पनि कारà¥à¤¯ तपाइà¤à¤²à¥‡ फेरि गरà¥à¤¨à¥à¤¹à¥à¤¨à¥‡à¤›à¥¤</translation>
<translation id="7550637293666041147">तपाईंको डिभाइसको यà¥à¤œà¤°à¤¨à¥‡à¤® र Chrome को यà¥à¤œà¤°à¤¨à¥‡à¤®</translation>
+<translation id="755279583747225797">टà¥à¤°à¤¾à¤¯à¤² सकà¥à¤°à¤¿à¤¯ छ</translation>
<translation id="7552846755917812628">निमà¥à¤¨ सà¥à¤à¤¾à¤µà¤¹à¤°à¥‚को पालना गरी हेरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥:</translation>
<translation id="7554475479213504905">जे भठपनि पà¥à¤¨à¤ƒ लोड गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ र देखाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7554791636758816595">नयाठटà¥à¤¯à¤¾à¤¬</translation>
@@ -1738,7 +1789,6 @@
<translation id="7610193165460212391">परिमाण दायरा <ph name="VALUE" /> भनà¥à¤¦à¤¾ बाहिर छ।</translation>
<translation id="7613889955535752492">मà¥à¤¯à¤¾à¤¦ सकिने मिति <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome का सेटिङमा गई आफà¥à¤¨à¤¾ पासवरà¥à¤¡à¤¹à¤°à¥‚ हेरà¥à¤¨ तथा वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¿à¤¤ गरà¥à¤¨ Tab थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ अनि Enter थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
-<translation id="7615602087246926389">तपाईंसà¤à¤— पहिले नै डाटा छ जà¥à¤¨à¤²à¤¾à¤ˆ तपाईंको Google खाता पासवरà¥à¤¡à¤•à¥‹ फरक संसà¥à¤•à¤°à¤£à¤¦à¥à¤µà¤¾à¤°à¤¾ गà¥à¤ªà¥à¤¤à¥€à¤•à¤°à¤£ गरिà¤à¤•à¥‹ छ। कृपया यसलाई तल पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
<translation id="7616645509853975347">तपाईंका à¤à¤¡à¥à¤®à¤¿à¤¨à¤²à¥‡ तपाईंको बà¥à¤°à¤¾à¤‰à¤œà¤°à¤®à¤¾ Chrome Enterprise Connectors अन गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ छ। यी कनेकà¥à¤Ÿà¤°à¤²à¥‡ तपाईंका केही डेटा पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨ सकà¥à¤›à¤¨à¥à¥¤</translation>
<translation id="7619838219691048931">अनà¥à¤¤à¤¿à¤® पाना</translation>
<translation id="762844065391966283">à¤à¤• पटकमा à¤à¤‰à¤Ÿà¤¾</translation>
@@ -1803,13 +1853,12 @@
<translation id="782886543891417279">तपाईà¤à¤²à¥‡ पà¥à¤°à¤¯à¥‹à¤— गरिरहनॠभà¤à¤•à¥‹ Wi-Fi (<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>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">समà¥à¤¬à¤¨à¥à¤§à¤¿à¤¤ फाइल हà¥à¤¯à¤¾à¤¨à¥à¤¡à¥à¤²à¤° पà¥à¤°à¤¯à¥‹à¤— गरेर फाइलहरू खोलà¥à¤¨à¥à¤¹à¥‹à¤¸à¥à¥¤</translation>
<translation id="7862185352068345852">साइट छाडà¥à¤¨à¥‡ हो?</translation>
<translation id="7865448901209910068">उतà¥à¤•à¥ƒà¤·à¥à¤Ÿ गति</translation>
<translation id="7874263914261512992">तपाईंले भरà¥à¤–रै कà¥à¤¨à¥ˆ भà¥à¤°à¤¾à¤®à¤• साइटमा आफà¥à¤¨à¥‹ पासवरà¥à¤¡ पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤­à¤à¤•à¥‹ छ। Chrome तपाईंलाई अहिले नै <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> र तपाईंले हाल यो पासवरà¥à¤¡ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥‡ अनà¥à¤¯ साइटका सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरिà¤à¤•à¤¾ पासवरà¥à¤¡à¤¹à¤°à¥‚को जाà¤à¤š गरà¥à¤¨ सिफारिस गरà¥à¤›à¥¤</translation>
<translation id="7878562273885520351">तपाईंको पासवरà¥à¤¡ जोखिममा परà¥à¤¨ सकà¥à¤›</translation>
+<translation id="7880146494886811634">ठेगाना सेभ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7882421473871500483">खैरो</translation>
<translation id="7887683347370398519">तपाईà¤à¤•à¥‹ CVC जाà¤à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ र फेरि पà¥à¤°à¤¯à¤¾à¤¸ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7887885240995164102">picture-in-picture मोडमा पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥â€Œ</translation>
@@ -1817,6 +1866,7 @@
<translation id="7894280532028510793">हिजà¥à¤œà¥‡ सही छ भने <ph name="BEGIN_LINK" />'नेटवरà¥à¤•à¤•à¤¾ डाइगोनà¥à¤¸à¥à¤Ÿà¤¿à¤•à¥à¤¸' चलाà¤à¤° हेरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥<ph name="END_LINK" />।</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">अजà¥à¤žà¤¾à¤¤</translation>
+<translation id="793209273132572360">ठेगाना बदलà¥à¤¨à¥‡ हो?</translation>
<translation id="7932579305932748336">कोट</translation>
<translation id="79338296614623784">मानà¥à¤¯ फोन नमà¥à¤¬à¤° पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="7934052535022478634">भà¥à¤•à¥à¤¤à¤¾à¤¨à¥€ गरà¥à¤¨à¥‡ कारà¥à¤¯ पूरा भयो</translation>
@@ -1887,6 +1937,7 @@
<translation id="8175796834047840627">तपाईं साइन इन हà¥à¤¨à¥à¤­à¤à¤•à¤¾à¤²à¥‡ Chrome ले तपाईंको Google खातामा तपाईंका कारà¥à¤¡à¤¹à¤°à¥‚ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरिदिने पà¥à¤°à¤¸à¥à¤¤à¤¾à¤µ गरà¥à¤¦à¥ˆ छ। तपाईं सेटिङहरूमा गई उकà¥à¤¤ वà¥à¤¯à¤µà¤¹à¤¾à¤° परिवरà¥à¤¤à¤¨ गरà¥à¤¨ सकà¥à¤¨à¥à¤¹à¥à¤¨à¥à¤›à¥¤</translation>
<translation id="8176440868214972690">यो डिभाइसका à¤à¤¡à¥à¤®à¤¿à¤¨à¤²à¥‡ निमà¥à¤¨ वेबसाइटहरूमा सेटिङ वा नीतिहरू जसà¥à¤¤à¤¾ केही जानकारी पठाउनà¥à¤­à¤à¤•à¥‹ छ।</translation>
<translation id="8184538546369750125">विशà¥à¤µà¤µà¥à¤¯à¤¾à¤ªà¥€ डिफलà¥à¤Ÿ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥ (अनà¥à¤®à¤¤à¤¿ दिनà¥à¤¹à¥‹à¤¸à¥)</translation>
+<translation id="8193086767630290324">गोपà¥à¤¯ डेटाका रूपमा फà¥à¤²à¥à¤¯à¤¾à¤— गरिà¤à¤•à¥‹ डेटा पà¥à¤°à¤¯à¥‹à¤— गरी गरिà¤à¤•à¤¾ कारबाहीहरू</translation>
<translation id="8194797478851900357">सारà¥à¤¨à¥‡ कारà¥à¤¯à¤²à¤¾à¤ˆ &amp;पूरà¥à¤µà¤µà¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8201077131113104583">ID "<ph name="EXTENSION_ID" />" भà¤à¤•à¥‹ विसà¥à¤¤à¤¾à¤°à¤•à¤¾ लागि अवैध अदà¥à¤¯à¤¾à¤µà¤§à¤¿à¤• URL</translation>
<translation id="8202097416529803614">अरà¥à¤¡à¤°à¤•à¥‹ सारांश</translation>
@@ -1909,6 +1960,7 @@
<translation id="8249296373107784235">रदà¥à¤¦ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8249320324621329438">पछिलà¥à¤²à¥‹ पटक लà¥à¤¯à¤¾à¤‡à¤à¤•à¥‹:</translation>
<translation id="8253091569723639551">बिल पठाउने ठेगाना आवशà¥à¤¯à¤• छ</translation>
+<translation id="8257387598443225809">यो à¤à¤ª मोबाइलमा चलाउने पà¥à¤°à¤¯à¥‹à¤œà¤¨à¤²à¥‡ बनाइà¤à¤•à¥‹ हो</translation>
<translation id="825929999321470778">सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ गरिà¤à¤•à¤¾ सबै पासवरà¥à¤¡à¤¹à¤°à¥‚ देखाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8261506727792406068">मेटà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8262952874573525464">फेदको किनारमा सà¥à¤Ÿà¤¿à¤š</translation>
@@ -2032,7 +2084,6 @@
<translation id="8719528812645237045">सिरानमा à¤à¤•à¤­à¤¨à¥à¤¦à¤¾ बढी पà¥à¤µà¤¾à¤²</translation>
<translation id="8725066075913043281">पà¥à¤¨: पà¥à¤°à¤¯à¤¾à¤¸ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8726549941689275341">पेजको आकार:</translation>
-<translation id="8728672262656704056">तपाईं इनà¥à¤•à¥‹à¤—à¥à¤¨à¤¿à¤Ÿà¥‹ मोडमामा जानà¥à¤­à¤à¤•à¥‹ छ</translation>
<translation id="8730621377337864115">गरियो</translation>
<translation id="8731544501227493793">'पासवरà¥à¤¡à¤¹à¤°à¥‚ वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¿à¤¤ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥' नामक बटन, Chrome का सेटिङमा गई आफà¥à¤¨à¤¾ पासवरà¥à¤¡à¤¹à¤°à¥‚ हेरà¥à¤¨ तथा वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¿à¤¤ गरà¥à¤¨ Enter थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="8734529307927223492"><ph name="MANAGER" /> ले तपाईंको <ph name="DEVICE_TYPE" /> वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤›</translation>
@@ -2109,6 +2160,7 @@
<translation id="9020542370529661692">यो पृषà¥à¤ à¤²à¤¾à¤ˆ <ph name="TARGET_LANGUAGE" /> मा अनà¥à¤µà¤¾à¤¦ गरिà¤à¤•à¥‹ छ</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(अमानà¥à¤¯)</translation>
+<translation id="9030265603405983977">शà¥à¤¯à¤¾à¤®à¤¶à¥à¤µà¥‡à¤¤</translation>
<translation id="9035022520814077154">सà¥à¤°à¤•à¥à¤·à¤¾ तà¥à¤°à¥à¤Ÿà¥€</translation>
<translation id="9038649477754266430">पृषà¥à¤ à¤¹à¤°à¥‚लाई अठछिटो लोड गरà¥à¤¨à¤•à¤¾ लागि पूरà¥à¤µà¤¾à¤¨à¥à¤®à¤¾à¤¨ सेवा पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="9039213469156557790">यसबाहेक, यस पृषà¥à¤ à¤²à¥‡ सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ नभà¤à¤•à¤¾ अनà¥à¤¯ संसाधनहरू समावेश गरà¥à¤›à¥¤ यी सà¥à¤°à¥‹à¤¤à¤¹à¤°à¥‚ टà¥à¤°à¤¾à¤¨à¥à¤œà¤¿à¤Ÿà¤®à¤¾ भà¤à¤•à¥‹ बेला अनà¥à¤¯à¤²à¥‡ हेरà¥à¤¨ सकà¥à¤›à¤¨à¥, र पृषà¥à¤ à¤•à¥‹ वà¥à¤¯à¤µà¤¹à¤¾à¤° परिवरà¥à¤¤à¤¨ गरà¥à¤¨ कà¥à¤¨à¥ˆ आकà¥à¤°à¤®à¤£à¤•à¤¾à¤°à¥€à¤¦à¥à¤µà¤¾à¤°à¤¾ परिमारà¥à¤œà¤¨ गरà¥à¤¨ सकिनà¥à¤›à¥¤</translation>
@@ -2132,6 +2184,7 @@
<translation id="91108059142052966">तपाईंको सà¥à¤•à¥à¤°à¤¿à¤¨à¤®à¤¾ गोपà¥à¤¯ सामगà¥à¤°à¥€ देखिà¤à¤•à¤¾ बेला à¤à¤¡à¥à¤®à¤¿à¤¨à¤²à¥‡ तोकà¥à¤¨à¥à¤­à¤à¤•à¥‹ नीतिअनà¥à¤¸à¤¾à¤° <ph name="APPLICATION_TITLE" /> सà¤à¤— सà¥à¤•à¥à¤°à¤¿à¤¨ सेयर गरà¥à¤¨à¥‡ सà¥à¤µà¤¿à¤§à¤¾ अफ गरिनà¥à¤›</translation>
<translation id="9114524666733003316">कारà¥à¤¡à¤•à¥‹ पà¥à¤·à¥à¤Ÿà¤¿ गरà¥à¤¦à¥ˆ...</translation>
<translation id="9114581008513152754">कà¥à¤¨à¥ˆ कमà¥à¤ªà¤¨à¥€ वा अनà¥à¤¯ सङà¥à¤—ठनले यो बà¥à¤°à¤¾à¤‰à¤œà¤° वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤¦à¥ˆà¤¨à¥¤ यो डिभाइसका कà¥à¤°à¤¿à¤¯à¤¾à¤•à¤²à¤¾à¤ª Chrome बाहिरबाट वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤¨ सकिनà¥à¤›à¥¤ <ph name="BEGIN_LINK" />थप जानà¥à¤¨à¥à¤¹à¥‹à¤¸à¥<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ताजा</translation>
<translation id="9119042192571987207">अपलोड गरिà¤à¤•à¥‹</translation>
<translation id="9128016270925453879">नीतिहरू लोड गरिà¤à¤•à¤¾ छनà¥</translation>
<translation id="9128870381267983090">नेटवरà¥à¤•à¤®à¤¾ कनेकà¥à¤Ÿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -2150,6 +2203,7 @@
<translation id="9170848237812810038">&amp;पूरà¥à¤µà¤¸à¥à¤¥à¤¿à¤¤à¤¿à¤®à¤¾ फरà¥à¤•à¤¾à¤‰à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="9171296965991013597">à¤à¤ª छोडà¥à¤¨à¥‡ हो?</translation>
<translation id="9173282814238175921">à¤à¤‰à¤Ÿà¤¾ कागजात/नयाठपाना</translation>
+<translation id="9173995187295789444">बà¥à¤²à¥à¤Ÿà¥à¤¥ यनà¥à¤¤à¥à¤°à¤¹à¤°à¥‚ छनॠकि भनी जाà¤à¤š गरà¥à¤¦à¥ˆ...</translation>
<translation id="917450738466192189">सरà¥à¤­à¤°à¤•à¥‹ पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° अमानà¥à¤¯ छ।</translation>
<translation id="9174917557437862841">टà¥à¤¯à¤¾à¤¬ बदलà¥à¤¨à¥‡ बटन, यो टà¥à¤¯à¤¾à¤¬à¤®à¤¾ जान Enter थिचà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="9179703756951298733">Chrome बà¥à¤°à¤¾à¤‰à¤œà¤°à¤•à¤¾ सेटिङमा गई आफà¥à¤¨à¤¾ भà¥à¤•à¥à¤¤à¤¾à¤¨à¥€ र कà¥à¤°à¥‡à¤¡à¤¿à¤Ÿ कारà¥à¤¡à¤¸à¤®à¥à¤¬à¤¨à¥à¤§à¥€ जानकारी वà¥à¤¯à¤µà¤¸à¥à¤¥à¤¾à¤ªà¤¨ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
@@ -2161,7 +2215,7 @@
<translation id="9207861905230894330">लेख थपà¥à¤¨ असफल भयो।</translation>
<translation id="9213433120051936369">आफूले चाहेअनà¥à¤¸à¤¾à¤°à¤•à¥‹ रूप बनाउनà¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="9215416866750762878">कà¥à¤¨à¥ˆ अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—ले Chrome लाई सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ रूपमा यो साइटमा जडान हà¥à¤¨à¤¬à¤¾à¤Ÿ रोकिरहेको छ</translation>
-<translation id="9219103736887031265">छविहरू</translation>
+<translation id="9219103736887031265">फोटो</translation>
<translation id="933712198907837967">डाइनरà¥à¤¸ कà¥à¤²à¤¬</translation>
<translation id="935608979562296692">फारम खाली गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥</translation>
<translation id="936474030629450166">Super-B</translation>
diff --git a/chromium/components/strings/components_strings_nl.xtb b/chromium/components/strings/components_strings_nl.xtb
index c7639bc865b..da9198c67ec 100644
--- a/chromium/components/strings/components_strings_nl.xtb
+++ b/chromium/components/strings/components_strings_nl.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Rechten selecteren voor <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Volgorde wijzigen ongedaan maken</translation>
+<translation id="1123753900084781868">Live ondertiteling is momenteel niet beschikbaar</translation>
<translation id="1125573121925420732">Wanneer de beveiliging van websites wordt geüpdatet, worden vaak waarschuwingen weergegeven. Dit wordt binnenkort verbeterd.</translation>
<translation id="112840717907525620">Cachegeheugen van beleid is OK</translation>
<translation id="1130564665089811311">Knop 'Pagina vertalen'. Druk op Enter om deze pagina te vertalen met Google Translate.</translation>
@@ -74,6 +75,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="1240347957665416060">De naam van je apparaat</translation>
<translation id="124116460088058876">Meer talen</translation>
<translation id="1243027604378859286">Auteur:</translation>
+<translation id="1246424317317450637">Vet</translation>
<translation id="1250759482327835220">Sla je pas, naam en factuuradres op in je Google-account zodat je de volgende keer sneller kunt betalen.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (gesynchroniseerd)</translation>
<translation id="1256368399071562588">&lt;p&gt;Als je een website wilt bezoeken en deze niet wordt geopend, kun je eerst zelf proberen het probleem op te lossen aan de hand van de volgende stappen:&lt;/p&gt;
@@ -154,6 +156,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="1476595624592550506">Je wachtwoord wijzigen</translation>
<translation id="1484290072879560759">Verzendadres kiezen</translation>
<translation id="1492194039220927094">Pushen van beleid:</translation>
+<translation id="1495677929897281669">Terug naar tabblad</translation>
<translation id="1501859676467574491">Passen uit je Google-account tonen</translation>
<translation id="1507202001669085618">&lt;p&gt;J​e ​zi​et​ d​ez​e ​fo​ut​ a​ls​ j​e ​ee​n ​wi​fi​-p​or​ta​l ​ge​br​ui​kt​ w​aa​ro​p ​je​ m​oe​t ​in​lo​gg​en​ v​oo​rd​at​ j​e ​on​li​ne​ k​un​t ​ga​an​.&lt;/p&gt;
&lt;p&gt;​K​li​k ​op​ &lt;​st​ro​ng​&gt;V​er​bi​nd​in​g ​ma​ke​n&lt;​/s​tr​on​g&gt;​ o​p ​de​ p​ag​in​a ​di​e ​je​ p​ro​be​er​t ​te​ o​pe​ne​n ​om​ d​ez​e ​fo​ut​ o​p ​te​ l​os​se​n.​&lt;/p&gt;</translation>
@@ -169,6 +172,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="1532118530259321453">Deze pagina meldt het volgende</translation>
<translation id="153384715582417236">Dat is voorlopig alles</translation>
<translation id="1536390784834419204">Pagina vertalen</translation>
+<translation id="1539840569003678498">Melding gestuurd:</translation>
<translation id="154408704832528245">Afleveradres kiezen</translation>
<translation id="1549470594296187301">JavaScript moet aanstaan om deze functie te kunnen gebruiken.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -211,16 +215,19 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="1682696192498422849">Korte zijde eerst</translation>
<translation id="168693727862418163">Deze beleidswaarde kan niet worden gevalideerd op basis van het bijbehorende schema en wordt genegeerd.</translation>
<translation id="168841957122794586">Het servercertificaat bevat een zwakke cryptografische sleutel.</translation>
+<translation id="1696290444144917273">Gegevens van virtuele kaart bekijken</translation>
<translation id="1697532407822776718">Je bent nu klaar!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Deze server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. Het bijbehorende beveiligingscertificaat is zogenaamd van morgen. Dit kan worden veroorzaakt door een verkeerde configuratie of een aanvaller die je verbinding onderschept.}other{Deze server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. Het bijbehorende beveiligingscertificaat is zogenaamd van # dagen in de toekomst. Dit kan worden veroorzaakt door een verkeerde configuratie of een aanvaller die je verbinding onderschept.}}</translation>
<translation id="1710259589646384581">Besturingssysteem</translation>
+<translation id="1711234383449478798">Genegeerd omdat <ph name="POLICY_NAME" /> niet is ingesteld op <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> vraagt toestemming om permanent gegevens op je lokale computer op te slaan</translation>
<translation id="1713628304598226412">Lade 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Mailbox 3</translation>
<translation id="1718029547804390981">Document is te groot om aantekeningen te maken</translation>
<translation id="1721424275792716183">* Verplicht veld</translation>
+<translation id="1727613060316725209">Certificaat is geldig</translation>
<translation id="1727741090716970331">Een geldig kaartnummer toevoegen</translation>
<translation id="1728677426644403582">Je bekijkt de bron van een webpagina</translation>
<translation id="173080396488393970">Dit type pas wordt niet ondersteund</translation>
@@ -241,7 +248,6 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="1772163372082567643">Voor de server waar je naartoe gaat (<ph name="ORIGIN" />), is een header ingesteld
die vereist dat een herkomstbeleid wordt toegepast op alle verzoeken aan de server. De header heeft echter een verkeerde indeling, waardoor de browser je verzoek voor <ph name="SITE" /> niet kan uitvoeren. Herkomstbeleidsregels kunnen worden gebruikt door site-operators om beveiliging en andere eigenschappen voor een site te configureren.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Update je wachtwoordzin voor synchronisatie.</translation>
<translation id="1787142507584202372">Je geopende tabbladen zie je hier</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, er zijn meerdere acties beschikbaar, druk op 'Tab' om erdoorheen te bladeren</translation>
@@ -274,6 +280,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="1919345977826869612">Advertenties</translation>
<translation id="1919367280705858090">Hulp bij een specifieke foutmelding</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Geen}=1{1 site}other{# sites}}</translation>
+<translation id="1924727005275031552">Nieuw</translation>
<translation id="1945968466830820669">Je kunt de toegang tot het account van je organisatie kwijtraken of slachtoffer worden van identiteitsdiefstal. Chromium raadt je aan je wachtwoord nu te wijzigen.</translation>
<translation id="1947454675006758438">Nietje rechtsboven</translation>
<translation id="1958218078413065209">Je hoogste score is <ph name="SCORE" />.</translation>
@@ -296,12 +303,14 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="2042213636306070719">Lade 7</translation>
<translation id="204357726431741734">Inloggen om wachtwoorden te gebruiken die zijn opgeslagen in je Google-account</translation>
<translation id="2053111141626950936">Pagina's in het <ph name="LANGUAGE" /> worden niet vertaald.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Als dit bedieningselement aanstaat en de status actief is, bepaalt Chrome op welke grote groep mensen (ook wel een cohort genoemd) je recente browse-activiteit het meest lijkt. Adverteerders kunnen advertenties voor de groep selecteren en je browse-activiteit blijft privé op je apparaat. Je groep wordt elke dag geüpdatet.}=1{Als dit bedieningselement aanstaat en de status actief is, bepaalt Chrome op welke grote groep mensen (ook wel een cohort genoemd) je recente browse-activiteit het meest lijkt. Adverteerders kunnen advertenties voor de groep selecteren en je browse-activiteit blijft privé op je apparaat. Je groep wordt elke dag geüpdatet.}other{Als dit bedieningselement aanstaat en de status actief is, bepaalt Chrome op welke grote groep mensen (ook wel een cohort genoemd) je recente browse-activiteit het meest lijkt. Adverteerders kunnen advertenties voor de groep selecteren en je browse-activiteit blijft privé op je apparaat. Je groep wordt elke {NUM_DAYS} dagen geüpdatet.}}</translation>
<translation id="2053553514270667976">Postcode</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 suggestie}other{# suggesties}}</translation>
<translation id="2071692954027939183">Meldingen zijn automatisch geblokkeerd omdat je deze doorgaans niet toestaat</translation>
<translation id="2079545284768500474">Ongedaan maken</translation>
<translation id="20817612488360358">De proxyinstellingen van het systeem moeten worden gebruikt, maar er is ook een expliciete proxyconfiguratie opgegeven.</translation>
<translation id="2082238445998314030">Resultaat <ph name="RESULT_NUMBER" /> van <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Opslaan…</translation>
<translation id="2088086323192747268">Knop Synchronisatie beheren, druk op Enter om de informatie die je synchroniseert te beheren in de Chrome-instellingen</translation>
<translation id="2091887806945687916">Geluid</translation>
<translation id="2094505752054353250">Domeinen komen niet overeen</translation>
@@ -374,6 +383,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="2317259163369394535">Voor <ph name="DOMAIN" /> zijn een gebruikersnaam en een wachtwoord vereist.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, verloopt op <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Instelling beheerd door je beheerder</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> wil koppelen</translation>
<translation id="2344028582131185878">Automatische downloads</translation>
<translation id="2346319942568447007">Afbeelding die je hebt gekopieerd</translation>
<translation id="2354001756790975382">Andere bookmarks</translation>
@@ -381,8 +391,10 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="2355395290879513365">Aanvallers kunnen mogelijk de afbeeldingen zien die je op deze site bekijkt en je misleiden door de afbeeldingen aan te passen.</translation>
<translation id="2356070529366658676">Vragen</translation>
<translation id="2357481397660644965">Je apparaat wordt beheerd door <ph name="DEVICE_MANAGER" /> en je account wordt beheerd door <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Over minder dan 1 dag}=1{Over 1 dag}other{Over {NUM_DAYS} dagen}}</translation>
<translation id="2359629602545592467">Meerdere</translation>
<translation id="2359808026110333948">Doorgaan</translation>
+<translation id="2359961752320758691">Je virtuele kaartnummer is toegepast.</translation>
<translation id="2367567093518048410">Niveau</translation>
<translation id="2372464001869762664">Nadat je hebt bevestigd, worden de kaartgegevens uit je Google-account gedeeld met deze site. Je vindt de CVC in de details van je Plex-account.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -393,6 +405,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="239429038616798445">Deze verzendmethode is niet beschikbaar. Kies een andere methode.</translation>
<translation id="2396249848217231973">&amp;Verwijderen ongedaan maken</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Oud</translation>
<translation id="2413528052993050574">De server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. Het beveiligingscertificaat van de server is mogelijk ingetrokken. Dit kan worden veroorzaakt door een verkeerde configuratie of een aanvaller die je verbinding onderschept.</translation>
<translation id="2414886740292270097">Donker</translation>
<translation id="2438874542388153331">Vier perforaties rechts</translation>
@@ -420,10 +433,10 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="2521385132275182522">Nietje rechtsonder</translation>
<translation id="2523886232349826891">Alleen opgeslagen op dit apparaat</translation>
<translation id="2524461107774643265">Meer informatie toevoegen</translation>
-<translation id="2526590354069164005">Bureaublad</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{en nog 1}other{en nog #}}</translation>
<translation id="2536110899380797252">Adres toevoegen</translation>
<translation id="2539524384386349900">Detecteren</translation>
+<translation id="2541219929084442027">De pagina's die je op incognitotabbladen bekijkt, worden niet bewaard in je browsergeschiedenis, cookie-opslag of zoekgeschiedenis nadat je al je incognitotabbladen hebt gesloten. Alle bestanden die je hebt gedownload of bookmarks die je hebt gemaakt, blijven behouden.</translation>
<translation id="2544644783021658368">Eén document</translation>
<translation id="254947805923345898">Beleidswaarde is ongeldig.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> heeft een ongeldige reactie verzonden.</translation>
@@ -443,6 +456,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="2629325967560697240"><ph name="BEGIN_ENHANCED_PROTECTION_LINK" />Zet de geoptimaliseerde beveiliging aan<ph name="END_ENHANCED_PROTECTION_LINK" /> om het hoogste beveiligingsniveau van Chrome te gebruiken</translation>
<translation id="2634124572758952069">Het IP-adres van de server van <ph name="HOST_NAME" /> kan niet worden gevonden.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Geen geschikte apparaten gevonden.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. Druk op Tab en vervolgens op Enter om je browsegeschiedenis, cookies, cache en meer te wissen in de Chrome-instellingen.</translation>
<translation id="2650446666397867134">Toegang tot het bestand is geweigerd</translation>
@@ -487,6 +501,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<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="2807052079800581569">Y-positie van afbeelding</translation>
+<translation id="2820957248982571256">Scannen…</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>
@@ -494,6 +509,8 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="2850739647070081192">Invite (envelop)</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="2859806420264540918">Site toont opdringerige of misleidende advertenties.</translation>
+<translation id="287596039013813457">Vriendelijk</translation>
+<translation id="2876489322757410363">Je verlaat de incognitomodus om te betalen via een externe app. Doorgaan?</translation>
<translation id="2878197950673342043">Kruisvouw</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Vensterplaatsing</translation>
@@ -543,7 +560,6 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="3060227939791841287">C9 (envelop)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, druk op Tab en daarna op Enter om de veiligheidscheck uit te voeren in de Chrome-instellingen</translation>
<translation id="3061707000357573562">Patchservice</translation>
-<translation id="3064966200440839136">Je verlaat de incognitomodus om te betalen via een externe app. Doorgaan?</translation>
<translation id="306573536155379004">Game gestart.</translation>
<translation id="3080254622891793721">Afbeelding</translation>
<translation id="3086579638707268289">Je activiteit op internet wordt in de gaten gehouden</translation>
@@ -566,7 +582,6 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="315504272643575312">Je account wordt beheerd door <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Herstellen</translation>
<translation id="3162559335345991374">Het is mogelijk dat je de inlogpagina moet bezoeken van het wifi-netwerk dat je gebruikt.</translation>
-<translation id="3167968892399408617">De pagina's die je op incognitotabbladen bekijkt, worden niet bewaard in je browsergeschiedenis, cookie-opslag of zoekgeschiedenis nadat je al je incognitotabbladen hebt gesloten. Alle bestanden die je hebt gedownload of bookmarks die je hebt gemaakt, blijven behouden.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Eiland</translation>
<translation id="3176929007561373547">Controleer je proxyinstellingen of neem contact op met je netwerkbeheerder om te controleren of de proxyserver werkt. Als je denkt dat je geen proxyserver zou moeten gebruiken: <ph name="PLATFORM_TEXT" /></translation>
@@ -589,10 +604,12 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<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="3249845759089040423">Groovy</translation>
<translation id="3252266817569339921">Frans</translation>
<translation id="3266793032086590337">Waarde (conflict)</translation>
<translation id="3268451620468152448">Geopende tabbladen</translation>
<translation id="3270847123878663523">&amp;Volgorde wijzigen ongedaan maken</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> wil verbinding maken</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Je organisatie, <ph name="ENROLLMENT_DOMAIN" />, heeft bepaalde gegevens gestuurd naar de volgende websites, zoals instellingen of beleidsregels.</translation>
<translation id="3282497668470633863">Naam op pas toevoegen</translation>
@@ -645,6 +662,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="3428151540071562330">Een of meer van de servertemplate-URI's voor DnsOverHttpsTemplates zijn ongeldig en worden niet gebruikt.</translation>
<translation id="3431636764301398940">Deze creditcard opslaan op dit apparaat</translation>
<translation id="3432601291244612633">Pagina sluiten</translation>
+<translation id="3435738964857648380">Beveiliging</translation>
<translation id="3435896845095436175">Aanzetten</translation>
<translation id="3438829137925142401">Wachtwoorden gebruiken die zijn opgeslagen in je Google-account</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -686,7 +704,10 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="3584299510153766161">Twee perforaties onder</translation>
<translation id="3586931643579894722">Details verbergen</translation>
<translation id="3587738293690942763">Midden</translation>
+<translation id="3590643883886679995">Nadat je de incognitomodus hebt afgesloten, worden de inloggegevens opgeslagen op dit apparaat.</translation>
+<translation id="359126217934908072">Maand/jaar:</translation>
<translation id="3592413004129370115">Italian (envelop)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Je kunt je groep op elk moment resetten. Het duurt ongeveer 1 dag om aan een nieuwe groep deel te nemen.}=1{Je kunt je groep op elk moment resetten. Het duurt ongeveer 1 dag om aan een nieuwe groep deel te nemen.}other{Je kunt je groep op elk moment resetten. Het duurt {NUM_DAYS} dagen om aan een nieuwe groep deel te nemen.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">App geblokkeerd door je beheerder</translation>
<translation id="3608932978122581043">Invoerrichting</translation>
@@ -695,12 +716,12 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="3615877443314183785">Geef een geldige vervaldatum op</translation>
<translation id="36224234498066874">Browsegegevens wissen</translation>
<translation id="362276910939193118">Volledige geschiedenis tonen</translation>
-<translation id="3625635938337243871">Nadat je de incognitomodus hebt afgesloten, worden de inloggegevens opgeslagen op dit apparaat.</translation>
<translation id="3630155396527302611">Als dit programma al wordt vermeld als een programma dat toegang heeft tot het netwerk, kun je proberen het uit de lijst te verwijderen en het opnieuw toe te voegen.</translation>
<translation id="3630699740441428070">De beheerders van dit apparaat hebben je netwerkverbinding ingesteld, waardoor ze mogelijk je netwerkverkeer kunnen bekijken, zoals welke websites je bezoekt.</translation>
<translation id="3631244953324577188">Biometrische systemen</translation>
<translation id="3633738897356909127">Knop 'Chrome updaten'. Druk op Enter om Chrome te updaten via de instellingen van Chrome.</translation>
<translation id="3634530185120165534">Lade 5</translation>
+<translation id="3637662659967048211">Opslaan in Google-account</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">App:</translation>
<translation id="3650584904733503804">Validatie geslaagd</translation>
@@ -741,6 +762,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="3781428340399460090">Felroze</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth-apparaten</translation>
+<translation id="3787675388804467730">Virtueel kaartnummer</translation>
<translation id="3787705759683870569">Verloopt: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Grootte 16</translation>
<translation id="3789841737615482174">Installeren</translation>
@@ -760,6 +782,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="3841184659773414994">Bestandshandlers</translation>
<translation id="385051799172605136">Terug</translation>
<translation id="3858027520442213535">Datum en tijd updaten</translation>
+<translation id="3881478300875776315">Minder regels tonen</translation>
<translation id="3884278016824448484">Conflicterende apparaat-ID's</translation>
<translation id="3885155851504623709">Parochie</translation>
<translation id="388632593194507180">Controle gedetecteerd</translation>
@@ -785,6 +808,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="397105322502079400">Berekenen...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> wordt geblokkeerd</translation>
<translation id="3973357910713125165">Knop Chrome-veiligheidscheck uitvoeren, druk op Enter om de veiligheidscheck uit te voeren in de Chrome-instellingen</translation>
+<translation id="3986705137476756801">Live ondertiteling nu uitzetten</translation>
<translation id="3987405730340719549">Chrome heeft vastgesteld dat deze site mogelijk nep of bedrieglijk is.
Als je denkt dat deze waarschuwing onterecht is, ga je naar https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -881,13 +905,14 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="4275830172053184480">Je apparaat opnieuw opstarten</translation>
<translation id="4277028893293644418">Wachtwoord opnieuw instellen</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="4287885627794386150">Komt in aanmerking voor proef maar is niet actief</translation>
<translation id="4297502707443874121">Miniatuur voor pagina <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Uitvouwen</translation>
<translation id="4300675098767811073">Meerdere perforaties rechts</translation>
<translation id="4302514097724775343">Tik op de dino om te spelen</translation>
<translation id="4302965934281694568">Chou3 (envelop)</translation>
<translation id="4305666528087210886">Je bestand kan niet worden geopend</translation>
-<translation id="4305817255990598646">Overschakelen</translation>
+<translation id="4306529830550717874">Adres opslaan?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokkeren (standaard)</translation>
<translation id="4314815835985389558">Synchronisatie beheren</translation>
@@ -914,6 +939,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="4377125064752653719">Je probeert <ph name="DOMAIN" /> te bereiken, maar het certificaat dat de server heeft geretourneerd, is ingetrokken door de uitgever. Dat betekent dat de veiligheidsgaranties die de server heeft geretourneerd, absoluut niet kunnen worden vertrouwd. Het kan zijn dat je met een hacker aan het communiceren bent.</translation>
<translation id="4378154925671717803">Telefoon</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Live ondertiteling</translation>
<translation id="4406896451731180161">zoekresultaten</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> cookies</translation>
<translation id="4414290883293381923">Je hebt zojuist je wachtwoord opgegeven op een misleidende site. Chrome raadt je aan naar <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> en andere sites te gaan waarop je dit wachtwoord hebt gebruikt en je wachtwoord nu te wijzigen.</translation>
@@ -926,7 +952,6 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="4435702339979719576">Briefkaart</translation>
<translation id="443673843213245140">Er kan geen proxy worden gebruikt, maar er is wel een expliciete proxyconfiguratie opgegeven.</translation>
<translation id="4464826014807964867">Websites met gegevens van je organisatie</translation>
-<translation id="4466881336512663640">Hiermee gaan formulierwijzigingen verloren. Weet je zeker dat je wilt doorgaan?</translation>
<translation id="4476953670630786061">Dit formulier is niet beveiligd. Automatisch invullen staat uit.</translation>
<translation id="4477350412780666475">Volgend nummer</translation>
<translation id="4482953324121162758">Deze site wordt niet vertaald.</translation>
@@ -960,6 +985,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="4594403342090139922">&amp;Verwijderen ongedaan maken</translation>
<translation id="4597348597567598915">Grootte 8</translation>
<translation id="4600854749408232102">C6/C5 (envelop)</translation>
+<translation id="4606870351894164739">Grote impact</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Cashback gekoppeld</translation>
<translation id="4636930964841734540">Info</translation>
@@ -979,6 +1005,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="4691835149146451662">Architecture-A (envelop)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Team</translation>
+<translation id="4702656508969495934">Live ondertiteling zichtbaar. Gebruik de knop Vensters schakelen om hier de focus op te plaatsen.</translation>
<translation id="4708268264240856090">Je verbinding is onderbroken</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows Netwerkcontrole uitvoeren<ph name="END_LINK" /></translation>
@@ -992,6 +1019,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="4738601419177586157">Zoeksuggestie: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Wachtwoorden beheren…</translation>
<translation id="4744603770635761495">Uitvoerbaar pad</translation>
+<translation id="4749011317274908093">Je bent incognito</translation>
<translation id="4750917950439032686">Je gegevens (zoals wachtwoorden of creditcardnummers) zijn privé wanneer ze worden verzonden naar deze site.</translation>
<translation id="4756388243121344051">Gesc&amp;hiedenis</translation>
<translation id="4758311279753947758">Contactgegevens toevoegen</translation>
@@ -1019,6 +1047,8 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="4813512666221746211">Netwerkfout</translation>
<translation id="4816492930507672669">Aanpassen aan pagina</translation>
<translation id="4819347708020428563">Annotaties bewerken in standaardweergave?</translation>
+<translation id="4825507807291741242">Krachtig</translation>
+<translation id="4838327282952368871">Dromerig</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">Weergave</translation>
<translation id="485316830061041779">Duits</translation>
@@ -1155,6 +1185,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="5314967030527622926">Boekjesmaker</translation>
<translation id="5316812925700871227">Linksom draaien</translation>
<translation id="5317780077021120954">Opslaan</translation>
+<translation id="5321288445143113935">Gemaximaliseerd</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> van <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Contactgegevens kiezen</translation>
<translation id="5327248766486351172">Naam</translation>
@@ -1162,11 +1193,13 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="5332219387342487447">Verzendmethode</translation>
<translation id="5333022057423422993">Chrome heeft het wachtwoord dat je net hebt gebruikt, gevonden bij een gegevenslek. We raden je aan je opgeslagen wachtwoorden te checken om je accounts te beveiligen.</translation>
<translation id="5334013548165032829">Gedetailleerde systeemlogboeken</translation>
+<translation id="5334145288572353250">Adres opslaan?</translation>
<translation id="5340250774223869109">App is geblokkeerd</translation>
<translation id="534295439873310000">NFC-apparaten</translation>
<translation id="5344579389779391559">Deze pagina brengt je mogelijk kosten in rekening</translation>
<translation id="5355557959165512791">Je kunt <ph name="SITE" /> momenteel niet bezoeken, omdat het bijbehorende certificaat is ingetrokken. Netwerkfouten en aanvallen zijn doorgaans tijdelijk, dus deze pagina werkt later waarschijnlijk correct.</translation>
<translation id="536296301121032821">Opslaan van beleidsinstellingen is mislukt</translation>
+<translation id="5363309033720083897">Seriële poort toegestaan door je beheerder</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="5386426401304769735">De certificaatketen voor deze site bevat een certificaat dat is ondertekend met SHA-1.</translation>
@@ -1175,6 +1208,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="5398772614898833570">Advertenties geblokkeerd</translation>
<translation id="5400836586163650660">Grijs</translation>
<translation id="540969355065856584">Deze server kan niet bewijzen dat dit <ph name="DOMAIN" /> is. Het beveiligingscertificaat is momenteel niet geldig. Dit kan worden veroorzaakt door een verkeerde configuratie of een aanvaller die je verbinding onderschept.</translation>
+<translation id="541143247543991491">Cloud (systeembreed)</translation>
<translation id="541416427766103491">Stapeleenheid 4</translation>
<translation id="5421136146218899937">Browsegegevens wissen</translation>
<translation id="5426179911063097041"><ph name="SITE" /> wil meldingen sturen</translation>
@@ -1188,6 +1222,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="5455374756549232013">Onjuist tijdstempel van beleid</translation>
<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="5463625433003343978">Apparaten zoeken...</translation>
<translation id="5469868506864199649">Italiaans</translation>
<translation id="5470861586879999274">&amp;Opnieuw bewerken</translation>
<translation id="5478437291406423475">B6/C4 (envelop)</translation>
@@ -1237,7 +1272,6 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="5624120631404540903">Wachtwoorden beheren</translation>
<translation id="5629630648637658800">Laden van beleidsinstellingen is mislukt</translation>
<translation id="5631439013527180824">Ongeldige token voor apparaatbeheer</translation>
-<translation id="5632627355679805402">Je gegevens zijn vanaf <ph name="TIME" /> versleuteld met je <ph name="BEGIN_LINK" />Google-wachtwoord<ph name="END_LINK" />. Geef het wachtwoord op om de synchronisatie te starten.</translation>
<translation id="5633066919399395251">Cybercriminelen op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> proberen mogelijk gevaarlijke programma's op je computer te installeren waarmee je gegevens kunnen worden gestolen of verwijderd (bijvoorbeeld foto's, wachtwoorden, berichten en creditcardgegevens). <ph name="BEGIN_LEARN_MORE_LINK" />Meer informatie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Misleidende content geblokkeerd.</translation>
<translation id="5644090287519800334">Beeldverschuiving X van zijde 1</translation>
@@ -1276,12 +1310,12 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="5785756445106461925">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 uiterlijk van de pagina aan te passen.</translation>
<translation id="5786044859038896871">Wil je de gegevens van je creditcard laten invullen?</translation>
<translation id="578633867165174378">Chrome heeft het wachtwoord dat je net hebt gebruikt, gevonden bij een gegevenslek. We raden je aan dit wachtwoord nu te wijzigen.</translation>
-<translation id="5798290721819630480">Wijzigingen niet opslaan?</translation>
<translation id="5803412860119678065">Wil je de gegevens van je <ph name="CARD_DETAIL" /> laten invullen?</translation>
<translation id="5804241973901381774">Rechten</translation>
<translation id="5804427196348435412">NFC-apparaten gebruiken</translation>
<translation id="5810442152076338065">Je verbinding met <ph name="DOMAIN" /> is versleuteld via een verouderde Cipher Suite.</translation>
<translation id="5813119285467412249">&amp;Opnieuw toevoegen</translation>
+<translation id="5817918615728894473">Koppelen</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{De kosten worden verrekend met deze kaart als je betaalt, maar het echte nummer van de kaart wordt niet met deze site gedeeld. Voor extra beveiliging wordt een tijdelijke CVC gegenereerd.}other{De kosten worden verrekend met de geselecteerde kaart als je betaalt, maar het echte nummer van de kaart wordt niet met deze site gedeeld. Voor extra beveiliging wordt een tijdelijke CVC gegenereerd.}}</translation>
<translation id="5826507051599432481">Algemene naam (CN)</translation>
<translation id="5838278095973806738">Geef geen gevoelige gegevens op op deze site (zoals wachtwoorden of creditcards), want deze kunnen worden gestolen door cybercriminelen.</translation>
@@ -1289,6 +1323,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="5855253129151731373">De hostnaam van deze site lijkt op <ph name="LOOKALIKE_DOMAIN" />. Aanvallers maken sites soms na door kleine wijzigingen in de domeinnaam aan te brengen die je moeilijk kunt zien.
Als je denkt dat deze waarschuwing onterecht is, ga je naar https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Uit</translation>
<translation id="5862579898803147654">Stapeleenheid 8</translation>
<translation id="5863847714970149516">De komende pagina probeert misschien kosten in rekening te brengen</translation>
<translation id="5866257070973731571">Telefoonnummer toevoegen</translation>
@@ -1305,6 +1340,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="5913377024445952699">Schermopname onderbroken</translation>
<translation id="59174027418879706">Aangezet</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 in gebruik}other{# in gebruik}}</translation>
<translation id="5921185718311485855">Aan</translation>
<translation id="5921639886840618607">Pas opslaan in Google-account?</translation>
<translation id="5922853866070715753">Bijna klaar</translation>
@@ -1324,6 +1360,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="5989320800837274978">Er worden geen vaste proxyservers en geen pac-script-URL gespecificeerd.</translation>
<translation id="5992691462791905444">Zizagvouw 2-slag oneven center</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultaten voor '<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">Klassiek</translation>
<translation id="6008122969617370890">Volgorde: van N naar 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Je wachtwoorden controleren</translation>
@@ -1345,6 +1382,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="6045164183059402045">Plaatsingstemplate</translation>
<translation id="6047233362582046994">Als je de beveiligingsrisico's begrijpt, kun je <ph name="BEGIN_LINK" />deze site bezoeken<ph name="END_LINK" /> voordat de schadelijke apps zijn verwijderd.</translation>
<translation id="6047927260846328439">Deze content probeert je mogelijk te misleiden om software te installeren of persoonlijke informatie openbaar te maken. <ph name="BEGIN_LINK" />Toch tonen<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Houd |<ph name="ACCELERATOR" />| ingedrukt om volledig scherm af te sluiten</translation>
<translation id="6049488691372270142">Pagina-uitvoer</translation>
<translation id="6051221802930200923">Je kunt <ph name="SITE" /> momenteel niet bezoeken, omdat de website gebruikmaakt van certificaatpinning. Netwerkfouten en aanvallen zijn doorgaans tijdelijk, dus deze pagina werkt later waarschijnlijk correct.</translation>
<translation id="6051898664905071243">Aantal pagina's:</translation>
@@ -1361,6 +1399,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<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>
<translation id="6116338172782435947">Tekst en afbeeldingen bekijken die naar het klembord zijn gekopieerd</translation>
<translation id="6120179357481664955">Weet je je UPI-ID nog?</translation>
+<translation id="6123290840358279103">Virtuele kaart bekijken</translation>
<translation id="6124432979022149706">Chrome Enterprise-connectors</translation>
<translation id="6146055958333702838">Controleer alle kabels en start alle routers, modems of andere netwerkapparaten die je gebruikt, opnieuw op.</translation>
<translation id="614940544461990577">Probeer dit eens:</translation>
@@ -1396,6 +1435,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="6289939620939689042">Paginakleur</translation>
<translation id="6290238015253830360">Je voorgestelde artikelen zie je hier</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">De Google Assistent in Chrome wordt gestopt</translation>
<translation id="6305205051461490394"><ph name="URL" /> is niet bereikbaar.</translation>
<translation id="6312113039770857350">Webpagina niet beschikbaar</translation>
@@ -1421,6 +1461,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="6390200185239044127">Zigzag kruisvouw</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Plakken van <ph name="ORIGIN_NAME" /> naar deze locatie is geblokkeerd op basis van beheerdersbeleid</translation>
+<translation id="6398765197997659313">Volledig scherm sluiten</translation>
<translation id="6401136357288658127">Dit beleid is beëindigd. Gebruik in plaats daarvan dit beleid: <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Bookmark bewerken</translation>
<translation id="6406765186087300643">C0 (envelop)</translation>
@@ -1433,7 +1474,6 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="6428450836711225518">Je telefoonnummer verifiëren</translation>
<translation id="6433490469411711332">Contactgegevens bewerken</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> heeft de verbinding geweigerd.</translation>
-<translation id="6434309073475700221">Verwijderen</translation>
<translation id="6440503408713884761">Genegeerd</translation>
<translation id="6443406338865242315">Welke extensies en plug-ins je hebt geïnstalleerd</translation>
<translation id="6446163441502663861">Kahu (envelop)</translation>
@@ -1476,6 +1516,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="6624427990725312378">Contactgegevens</translation>
<translation id="6626291197371920147">Een geldig kaartnummer toevoegen</translation>
<translation id="6628463337424475685">Zoeken via <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Zoeken naar USB-apparaten...</translation>
<translation id="6630809736994426279">Cybercriminelen op <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> proberen mogelijk gevaarlijke programma's op je Mac te installeren waarmee je gegevens kunnen worden gestolen of verwijderd (bijvoorbeeld foto's, wachtwoorden, berichten en creditcardgegevens). <ph name="BEGIN_LEARN_MORE_LINK" />Meer informatie<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Wissen</translation>
@@ -1491,6 +1532,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="6671697161687535275">Formuliersuggestie verwijderen uit Chromium?</translation>
<translation id="6685834062052613830">Uitloggen en configuratie voltooien</translation>
<translation id="6687335167692595844">Lettergrootte aangevraagd</translation>
+<translation id="6688743156324860098">Updaten…</translation>
<translation id="6689249931105087298">Relatief met zwartpuntcompressie</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="6698381487523150993">Gemaakt:</translation>
@@ -1506,6 +1548,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="6744009308914054259">Terwijl je op een verbinding wacht, kun je naar Downloads gaan om offline artikelen te lezen.</translation>
<translation id="6753269504797312559">Beleidswaarde</translation>
<translation id="6757797048963528358">De slaapstand van je apparaat is geactiveerd.</translation>
+<translation id="6767985426384634228">Adres updaten?</translation>
<translation id="6768213884286397650">Hagaki (briefkaart)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violet</translation>
@@ -1528,6 +1571,7 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome heeft deze pagina vereenvoudigd om deze beter leesbaar te maken. Chrome heeft de originele pagina opgehaald via een niet-beveiligde verbinding.</translation>
<translation id="6891596781022320156">Beleidsniveau wordt niet ondersteund.</translation>
+<translation id="6895143722905299846">Virtueel nummer:</translation>
<translation id="6895330447102777224">Je creditcard is bevestigd</translation>
<translation id="6897140037006041989">User-agent</translation>
<translation id="6898699227549475383">Organisatie (O)</translation>
@@ -1563,10 +1607,10 @@ Anders wordt dit geblokkeerd door je privacyinstellingen. Hierdoor werkt de cont
<translation id="7004583254764674281">Gebruik Windows Hello om kaarten sneller te bevestigen</translation>
<translation id="7006930604109697472">Toch sturen</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Instellingen voor formaataanpassing</translation>
<translation id="7014741021609395734">Zoomniveau</translation>
<translation id="7016992613359344582">Dit kunnen eenmalige of terugkerende kosten zijn die misschien niet duidelijk worden aangegeven.</translation>
<translation id="7029809446516969842">Wachtwoorden</translation>
+<translation id="7030436163253143341">Certificaat is niet geldig</translation>
<translation id="7031646650991750659">Welke Google Play-apps je hebt geïnstalleerd</translation>
<translation id="7050187094878475250">Je hebt geprobeerd <ph name="DOMAIN" /> te bereiken, maar de server heeft een certificaat gepresenteerd waarvan de geldigheidsperiode te lang is om betrouwbaar te zijn.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Deze pas kan nu niet worden opgeslagen}other{Deze passen kunnen nu niet worden opgeslagen}}</translation>
@@ -1636,12 +1680,14 @@ Aanvullende informatie:
<translation id="7300012071106347854">Kobaltblauw</translation>
<translation id="7302712225291570345">'<ph name="TEXT" />'</translation>
<translation id="7304030187361489308">Hoog</translation>
+<translation id="7305756307268530424">Langzamer starten</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Hulp bij verbinding maken</translation>
<translation id="7323804146520582233">Het gedeelte '<ph name="SECTION" />' verbergen</translation>
<translation id="733354035281974745">Lokaal account op apparaat overschrijven</translation>
<translation id="7333654844024768166">Je hebt zojuist je wachtwoord opgegeven op een misleidende site. Chromium raadt je aan naar <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> en andere sites te gaan waarop je dit wachtwoord hebt gebruikt en je wachtwoord nu te wijzigen.</translation>
<translation id="7334320624316649418">&amp;Opnieuw volgorde wijzigen</translation>
+<translation id="7337248890521463931">Meer regels tonen</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>
@@ -1649,6 +1695,7 @@ Aanvullende informatie:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Opdrachtregel</translation>
<translation id="7359588939039777303">Advertenties geblokkeerd.</translation>
+<translation id="7363096869660964304">Je bent echter niet onzichtbaar. Als je incognito bent, wordt je browsegeschiedenis niet verborgen voor je werkgever, je internetprovider of de websites die je bezoekt.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, druk op Tab en daarna op Enter om adressen toe te voegen en te beheren in de Chrome-instellingen</translation>
<translation id="7365849542400970216">Laten weten wanneer je dit apparaat gebruikt?</translation>
<translation id="7372973238305370288">zoekresultaat</translation>
@@ -1659,7 +1706,9 @@ Aanvullende informatie:
<translation id="7378594059915113390">Mediabediening</translation>
<translation id="7378627244592794276">Nee</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Niet van toepassing</translation>
<translation id="7390545607259442187">Creditcard bevestigen</translation>
+<translation id="7392089738299859607">Adres updaten</translation>
<translation id="7399802613464275309">Veiligheidscheck</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Je <ph name="DEVICE_NAME" /> wordt beheerd</translation>
@@ -1674,6 +1723,7 @@ Aanvullende informatie:
&lt;li&gt;Ga naar het &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Helpcentrum van Chrome&lt;/a&gt; voor meer informatie over hoe je de software definitief van je computer kunt verwijderen
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Mooi</translation>
<translation id="7416351320495623771">Wachtwoorden beheren…</translation>
<translation id="7419106976560586862">Profielpad</translation>
<translation id="7437289804838430631">Contactgegevens toevoegen</translation>
@@ -1689,7 +1739,7 @@ Aanvullende informatie:
<translation id="7481312909269577407">Vooruit</translation>
<translation id="7485870689360869515">Geen gegevens gevonden.</translation>
<translation id="7495528107193238112">Deze content is geblokkeerd. Neem contact op met de site-eigenaar om het probleem op te lossen.</translation>
-<translation id="7498234416455752244">Doorgaan met bewerken</translation>
+<translation id="7498193950643227031">Er kan onverwacht gedrag optreden als het formaat wordt aangepast. Je kunt de mogelijkheid om het formaat van apps aan te passen nu beperken in <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Je hebt zojuist je wachtwoord opgegeven op een misleidende site. Chromium raadt je aan je opgeslagen wachtwoorden voor <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> en andere sites waarop je dit wachtwoord gebruikt, nu te checken.</translation>
<translation id="7508255263130623398">Geretourneerde apparaat-ID voor beleid is leeg of komt niet overeen met de huidige apparaat-ID</translation>
<translation id="7508870219247277067">Avocadogroen</translation>
@@ -1709,6 +1759,7 @@ Aanvullende informatie:
<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="755279583747225797">Proef is actief</translation>
<translation id="7552846755917812628">Probeer de volgende tips:</translation>
<translation id="7554475479213504905">Opnieuw laden en toch tonen</translation>
<translation id="7554791636758816595">Nieuw tabblad</translation>
@@ -1727,7 +1778,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Druk op Tab en vervolgens op Enter om je wachtwoorden te beheren in de Chrome-instellingen.</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="7616645509853975347">Je beheerder heeft Chrome Enterprise Connectors voor je browser ingesteld. Deze connectors hebben toegang tot sommige van je gegevens.</translation>
<translation id="7619838219691048931">Eindblad</translation>
<translation id="762844065391966283">Eén tegelijk</translation>
@@ -1792,13 +1842,12 @@ Aanvullende informatie:
<translation id="782886543891417279">Het is mogelijk dat je de inlogpagina moet bezoeken van het wifi-netwerk (<ph name="WIFI_NAME" />) dat je gebruikt.</translation>
<translation id="7836231406687464395">Postfix (envelop)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Geen}=1{1 app (<ph name="EXAMPLE_APP_1" />)}=2{2 apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Je bent echter niet onzichtbaar. Als je incognito bent, wordt je browsegeschiedenis niet verborgen voor je werkgever, je internetprovider of de websites die je bezoekt.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Bestanden met bestandstypeassociaties openen.</translation>
<translation id="7862185352068345852">Site verlaten?</translation>
<translation id="7865448901209910068">Beste snelheid</translation>
<translation id="7874263914261512992">Je hebt zojuist je wachtwoord opgegeven op een misleidende site. Chrome raadt je aan je opgeslagen wachtwoorden voor <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> en andere sites waarop je dit wachtwoord gebruikt, nu te checken.</translation>
<translation id="7878562273885520351">Je wachtwoord is mogelijk gehackt</translation>
+<translation id="7880146494886811634">Adres opslaan</translation>
<translation id="7882421473871500483">Bruin</translation>
<translation id="7887683347370398519">Controleer je CVC-code en probeer het opnieuw</translation>
<translation id="7887885240995164102">Scherm-in-scherm openen</translation>
@@ -1806,6 +1855,7 @@ Aanvullende informatie:
<translation id="7894280532028510793">Als de spelling klopt, <ph name="BEGIN_LINK" />voer je een netwerkcontrole uit<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (envelop)</translation>
<translation id="7931318309563332511">Onbekend</translation>
+<translation id="793209273132572360">Adres updaten?</translation>
<translation id="7932579305932748336">Coaten</translation>
<translation id="79338296614623784">Geef een geldig telefoonnummer op</translation>
<translation id="7934052535022478634">Betaling voltooid</translation>
@@ -1876,6 +1926,7 @@ Aanvullende informatie:
<translation id="8175796834047840627">Chrome biedt aan je passen in je Google-account op te slaan omdat je bent ingelogd. Je kunt dit wijzigen in de instellingen.</translation>
<translation id="8176440868214972690">De beheerder van dit apparaat heeft bepaalde gegevens gestuurd naar de volgende websites, zoals instellingen of beleidsregels.</translation>
<translation id="8184538546369750125">Algemene standaardinstelling gebruiken (Toestaan)</translation>
+<translation id="8193086767630290324">Acties ondernomen met gegevens die zijn gemarkeerd als vertrouwelijk</translation>
<translation id="8194797478851900357">&amp;Verplaatsen ongedaan maken</translation>
<translation id="8201077131113104583">Ongeldige update-URL voor de extensie met de ID '<ph name="EXTENSION_ID" />'.</translation>
<translation id="8202097416529803614">Besteloverzicht</translation>
@@ -1898,6 +1949,7 @@ Aanvullende informatie:
<translation id="8249296373107784235">Annuleren</translation>
<translation id="8249320324621329438">Laatst opgehaald:</translation>
<translation id="8253091569723639551">Factuuradres vereist</translation>
+<translation id="8257387598443225809">Deze app is ontworpen voor mobiel</translation>
<translation id="825929999321470778">Alle opgeslagen wachtwoorden tonen</translation>
<translation id="8261506727792406068">Verwijderen</translation>
<translation id="8262952874573525464">Inbinden met nietjes onder</translation>
@@ -2019,7 +2071,6 @@ Aanvullende informatie:
<translation id="8719528812645237045">Meerdere perforaties boven</translation>
<translation id="8725066075913043281">Opnieuw proberen</translation>
<translation id="8726549941689275341">Paginagrootte:</translation>
-<translation id="8728672262656704056">Je bent incognito</translation>
<translation id="8730621377337864115">Klaar</translation>
<translation id="8731544501227493793">Knop 'Wachtwoorden beheren'. Druk op Enter om je wachtwoorden te bekijken en te beheren in de Chrome-instellingen.</translation>
<translation id="8734529307927223492">Je <ph name="DEVICE_TYPE" /> wordt beheerd door <ph name="MANAGER" /></translation>
@@ -2096,6 +2147,7 @@ Aanvullende informatie:
<translation id="9020542370529661692">Deze pagina is vertaald naar het <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Ongeldig)</translation>
+<translation id="9030265603405983977">Monochroom</translation>
<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>
@@ -2119,6 +2171,7 @@ Aanvullende informatie:
<translation id="91108059142052966">Op basis van het beheerdersbeleid wordt scherm delen met <ph name="APPLICATION_TITLE" /> uitgezet als er vertrouwelijke content zichtbaar is</translation>
<translation id="9114524666733003316">Creditcard bevestigen...</translation>
<translation id="9114581008513152754">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="9117930699067497412">Nieuw</translation>
<translation id="9119042192571987207">Geüpload</translation>
<translation id="9128016270925453879">Beleid is geladen</translation>
<translation id="9128870381267983090">Verbinding maken met netwerk</translation>
@@ -2137,6 +2190,7 @@ Aanvullende informatie:
<translation id="9170848237812810038">&amp;Ongedaan maken</translation>
<translation id="9171296965991013597">App verlaten?</translation>
<translation id="9173282814238175921">Eén document/nieuw blad</translation>
+<translation id="9173995187295789444">Scannen naar Bluetooth-apparaten...</translation>
<translation id="917450738466192189">Het servercertificaat is ongeldig.</translation>
<translation id="9174917557437862841">Schakelknop voor tabbladen, druk op Enter om naar dit tabblad te schakelen</translation>
<translation id="9179703756951298733">Je betalingen en creditcardgegevens beheren in de Chrome-instellingen</translation>
diff --git a/chromium/components/strings/components_strings_no.xtb b/chromium/components/strings/components_strings_no.xtb
index a46cba1f3cf..a3250109e95 100644
--- a/chromium/components/strings/components_strings_no.xtb
+++ b/chromium/components/strings/components_strings_no.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Velg tillatelse for <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Angre omorganiseringen</translation>
+<translation id="1123753900084781868">Direkteteksting er ikke tilgjengelig akkurat nå</translation>
<translation id="1125573121925420732">Det kan hende du ser mange advarsler mens nettstedene oppdaterer sikkerheten sin. Dette forbedres snart.</translation>
<translation id="112840717907525620">Bufferen for enhetsinnstillinger er OK</translation>
<translation id="1130564665089811311">Knappen «Oversett siden» – trykk på Enter for å oversette denne siden med Google Oversetter</translation>
@@ -74,6 +75,7 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="1240347957665416060">Navnet på enheten din</translation>
<translation id="124116460088058876">Flere språk</translation>
<translation id="1243027604378859286">Forfatter:</translation>
+<translation id="1246424317317450637">Fet</translation>
<translation id="1250759482327835220">For å betale raskere neste gang, lagre kortet og faktureringsadressen i Google-kontoen din.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" /> og <ph name="TYPE_2" /> (synkronisert)</translation>
<translation id="1256368399071562588">&lt;p&gt;Hvis du prøver å gå til et nettsted og det ikke åpnes, bør du først prøve å løse feilen med disse feilsøkingstrinnene:&lt;/p&gt;
@@ -156,6 +158,7 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="1476595624592550506">Endre passordet</translation>
<translation id="1484290072879560759">Velg leveringsadresse</translation>
<translation id="1492194039220927094">Push-levering av regler:</translation>
+<translation id="1495677929897281669">Tilbake til fanen</translation>
<translation id="1501859676467574491">Vis kredittkort fra Google-kontoen din</translation>
<translation id="1507202001669085618">&lt;p&gt;Du ser denne feilmeldingen hvis du bruker en Wi-Fi-portal hvor du må logge på før du kommer deg på nettet.&lt;/p&gt;
&lt;p&gt;For å fikse feilen, klikk på &lt;strong&gt;Koble til&lt;/strong&gt; på siden du prøver å åpne.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="1532118530259321453">På denne siden står det</translation>
<translation id="153384715582417236">Det var alt for denne gangen</translation>
<translation id="1536390784834419204">Oversett siden</translation>
+<translation id="1539840569003678498">Rapporten er sendt:</translation>
<translation id="154408704832528245">Velg leveringsadresse</translation>
<translation id="1549470594296187301">Denne funksjonen kan ikke brukes når JavaScript er slått av.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="1682696192498422849">Kortsiden først</translation>
<translation id="168693727862418163">Denne regelverdien kunne ikke valideres mot oppsettet og blir derfor ignorert.</translation>
<translation id="168841957122794586">Tjenersertifikatet inneholder en svak kryptografisk nøkkel.</translation>
+<translation id="1696290444144917273">Se virtuelle kortopplysninger</translation>
<translation id="1697532407822776718">Da er alt klart!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />, ettersom sikkerhetssertifikatet ser ut til å være fra i morgen. Dette kan skyldes en feilkonfigurasjon eller at en angriper avskjærer tilkoblingen mellom deg og nettstedet.}other{Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />, ettersom sikkerhetssertifikatet ser ut til å være fra # dager frem i tid. Dette kan skyldes en feilkonfigurasjon eller at en angriper avskjærer tilkoblingen mellom deg og nettstedet.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Ignorert fordi <ph name="POLICY_NAME" /> ikke er satt til <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> ber om å lagre data permanent på datamaskinen din</translation>
<translation id="1713628304598226412">Skuff 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Postkasse 3</translation>
<translation id="1718029547804390981">Dokumentet er for stort til å annoteres</translation>
<translation id="1721424275792716183">* Feltet er obligatorisk</translation>
+<translation id="1727613060316725209">Sertifikatet er gyldig</translation>
<translation id="1727741090716970331">Legg til et gyldig kortnummer</translation>
<translation id="1728677426644403582">Du ser på kildekoden for en nettside</translation>
<translation id="173080396488393970">Denne korttypen støttes ikke</translation>
@@ -246,7 +253,6 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
forespørselen din til <ph name="SITE" />. Nettstedsoperatører kan bruke
opphavsregler til å konfigurere sikkerhet og andre egenskaper for nettsteder.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Oppdater passordfrasen for synkronisering.</translation>
<translation id="1787142507584202372">De åpne fanene dine vises her</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" /> – flere handlinger er tilgjengelige. Trykk på Tab for å bla gjennom dem</translation>
@@ -279,6 +285,7 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="1919345977826869612">Annonser</translation>
<translation id="1919367280705858090">FÃ¥ hjelp med spesifikke feilmeldinger</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ingen}=1{1 nettsted}other{# nettsteder}}</translation>
+<translation id="1924727005275031552">Ny</translation>
<translation id="1945968466830820669">Du kan miste tilgangen til organisasjonskontoen din eller bli utsatt for identitetstyveri. Chromium anbefaler at du endrer passordet ditt nå.</translation>
<translation id="1947454675006758438">Stift oppe til høyre</translation>
<translation id="1958218078413065209">Poengrekorden din er <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="2042213636306070719">Skuff 7</translation>
<translation id="204357726431741734">Logg på for å bruke passord som er lagret i Google-kontoen din</translation>
<translation id="2053111141626950936">Sider på <ph name="LANGUAGE" /> oversettes ikke.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Når denne kontrollen er på og statusen er aktiv, bestemmer Chrome hvilken stor gruppe mennesker, eller "kohort", den siste nettleseraktiviteten din ligner mest på. Annonsører kan velge annonser for gruppen, og nettlesingsaktiviteten din holdes privat på enheten din. Gruppen din oppdateres hver dag.}=1{Når denne kontrollen er på og statusen er aktiv, bestemmer Chrome hvilken stor gruppe mennesker, eller "kohort", den siste nettleseraktiviteten din ligner mest på. Annonsører kan velge annonser for gruppen, og nettlesingsaktiviteten din holdes privat på enheten din. Gruppen din oppdateres hver dag.}other{Når denne kontrollen er på og statusen er aktiv, bestemmer Chrome hvilken stor gruppe mennesker, eller "kohort", den siste nettleseraktiviteten din ligner mest på. Annonsører kan velge annonser for gruppen, og nettlesingsaktiviteten din holdes privat på enheten din. Gruppen oppdateres hver {NUM_DAYS}. dag.}}</translation>
<translation id="2053553514270667976">Postnummer</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 forslag}other{# forslag}}</translation>
<translation id="2071692954027939183">Varsler ble blokkert automatisk fordi du vanligvis ikke tillater dem</translation>
<translation id="2079545284768500474">Angre</translation>
<translation id="20817612488360358">Innstillinger for systemmellomtjener er stilt inn på å brukes, men en uttrykkelig mellomtjenerkonfigurasjon er også angitt.</translation>
<translation id="2082238445998314030">Resultat <ph name="RESULT_NUMBER" /> av <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Lagre …</translation>
<translation id="2088086323192747268">Knappen «Administrer synkronisering» – trykk på Enter for å administrere hvilken informasjon du synkroniserer, i Chrome-innstillingene</translation>
<translation id="2091887806945687916">Lyd</translation>
<translation id="2094505752054353250">Domenene samsvarer ikke</translation>
@@ -379,6 +388,7 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="2317259163369394535"><ph name="DOMAIN" /> krever brukernavn og passord.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" /> – utløper <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Innstillingen kontrolleres av administratoren din</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> vil koble til</translation>
<translation id="2344028582131185878">Automatiske nedlastinger</translation>
<translation id="2346319942568447007">Bildet du kopierte</translation>
<translation id="2354001756790975382">Andre bokmerker</translation>
@@ -386,8 +396,10 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="2355395290879513365">Angripere kan kanskje se bildene du ser på dette nettstedet, og lure deg ved å endre dem.</translation>
<translation id="2356070529366658676">Spør</translation>
<translation id="2357481397660644965">Enheten administreres av <ph name="DEVICE_MANAGER" />, og kontoen administreres av <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Om mindre enn én dag}=1{Om én dag}other{Om {NUM_DAYS} dager}}</translation>
<translation id="2359629602545592467">Flere</translation>
<translation id="2359808026110333948">Fortsett</translation>
+<translation id="2359961752320758691">Det virtuelle kortnummeret ditt ble fylt ut.</translation>
<translation id="2367567093518048410">Nivå</translation>
<translation id="2372464001869762664">NÃ¥r du har bekreftet verifiseringskoden, deles kortopplysningene fra Google-kontoen din med dette nettstedet. Du finner verifiseringskoden i Plex-kontoopplysningene.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="239429038616798445">Denne leveringsmetoden er ikke tilgjengelig. Prøv en annen metode.</translation>
<translation id="2396249848217231973">&amp;Angre slettingen</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Gamle</translation>
<translation id="2413528052993050574">Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />. Tjenerens sikkerhetssertifikat kan være trukket tilbake. Dette kan være forårsaket av en feilkonfigurering eller en angriper som avskjærer tilkoblingen din.</translation>
<translation id="2414886740292270097">Mørk</translation>
<translation id="2438874542388153331">Fire hull høyre</translation>
@@ -425,10 +438,10 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="2521385132275182522">Stift nede til høyre</translation>
<translation id="2523886232349826891">Kun lagret på denne enheten</translation>
<translation id="2524461107774643265">Legg til mer informasjon</translation>
-<translation id="2526590354069164005">Skrivebordet</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{og 1 til}other{og # til}}</translation>
<translation id="2536110899380797252">Legg til adresse</translation>
<translation id="2539524384386349900">Oppdag</translation>
+<translation id="2541219929084442027">Sider du åpner i inkognitofaner, blir ikke værende i nettleserloggen, lageret for informasjonskapsler eller søkeloggen etter at du har lukket alle inkognitofanene. Filer du laster ned eller bokmerker du oppretter, blir lagret.</translation>
<translation id="2544644783021658368">Enkeltdokument</translation>
<translation id="254947805923345898">Regelverdien er ikke gyldig.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> sendte et ugyldig svar.</translation>
@@ -448,6 +461,7 @@ I motsatt fall blir dette blokkert av personverninnstillingene. Dette gjør at i
<translation id="2629325967560697240">For å få det høyeste sikkerhetsnivået som Chrome tilbyr, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />slå på økt beskyttelse<ph name="END_ENHANCED_PROTECTION_LINK" />.</translation>
<translation id="2634124572758952069">Fant ikke IP-adressen til tjeneren for <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Fant ingen kompatible enheter.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" /> – trykk på Tab og deretter på Enter for å tømme nettleserloggen, slette informasjonskapsler, tømme bufferen med mer i Chrome-innstillingene</translation>
<translation id="2650446666397867134">Tilgang til filen ble nektet</translation>
@@ -494,6 +508,7 @@ brukere av denne nettleseren.</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="2807052079800581569">Y-posisjon for bilde</translation>
+<translation id="2820957248982571256">Skanner …</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>
@@ -501,6 +516,8 @@ brukere av denne nettleseren.</translation>
<translation id="2850739647070081192">Invite (konvolutt)</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="2859806420264540918">Dette nettstedet viser forstyrrende eller villedende annonser.</translation>
+<translation id="287596039013813457">Vennskapelig</translation>
+<translation id="2876489322757410363">Går ut av Inkognitomodus for å betale via en ekstern app. Vil du fortsette?</translation>
<translation id="2878197950673342043">Kryssfals</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Vindusplassering</translation>
@@ -550,7 +567,6 @@ brukere av denne nettleseren.</translation>
<translation id="3060227939791841287">C9 (konvolutt)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" /> – trykk på Tab og deretter på Enter for å kjøre en sikkerhetssjekk i Chrome-innstillingene</translation>
<translation id="3061707000357573562">Feilrettingstjeneste</translation>
-<translation id="3064966200440839136">Går ut av inkognitomodus for å betale via en ekstern app. Vil du fortsette?</translation>
<translation id="306573536155379004">Spillet er startet.</translation>
<translation id="3080254622891793721">Grafikk</translation>
<translation id="3086579638707268289">Aktiviteten din på nettet overvåkes</translation>
@@ -573,7 +589,6 @@ brukere av denne nettleseren.</translation>
<translation id="315504272643575312">Kontoen din administreres av <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Gjenopprett</translation>
<translation id="3162559335345991374">Det kan hende at Wi-Fi-nettverket du bruker, krever at du besøker en påloggingsside.</translation>
-<translation id="3167968892399408617">Sider du går til i inkognitofaner, blir ikke værende i nettleserloggen, lageret for informasjonskapsler eller søkeloggen etter at du har lukket alle inkognitofanene. Filer du laster ned eller bokmerker du oppretter, blir lagret.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Øy</translation>
<translation id="3176929007561373547">Sjekk innstillingene for proxy-tjeneren eller kontakt nettverksadministratoren
@@ -599,10 +614,12 @@ brukere av denne nettleseren.</translation>
<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="3249845759089040423">Groovy</translation>
<translation id="3252266817569339921">Fransk</translation>
<translation id="3266793032086590337">Verdi (konflikt)</translation>
<translation id="3268451620468152448">Ã…pne faner</translation>
<translation id="3270847123878663523">&amp;Angre omorganiseringen</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> vil koble til</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Organisasjonen din, <ph name="ENROLLMENT_DOMAIN" />, har sendt noe informasjon til de følgende nettstedene, for eksempel innstillinger eller retningslinjer.</translation>
<translation id="3282497668470633863">Legg til navnet på kortet</translation>
@@ -655,6 +672,7 @@ brukere av denne nettleseren.</translation>
<translation id="3428151540071562330">Én eller flere av URI-ene for DnsOverHttpsTemplates-tjenermaler er ugyldige og blir ikke brukt.</translation>
<translation id="3431636764301398940">Lagre dette kortet på denne enheten</translation>
<translation id="3432601291244612633">Lukk siden</translation>
+<translation id="3435738964857648380">Sikkerhet</translation>
<translation id="3435896845095436175">Slå på</translation>
<translation id="3438829137925142401">Bruk passord som er lagret i Google-kontoen din</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ brukere av denne nettleseren.</translation>
<translation id="3584299510153766161">To hull bunn</translation>
<translation id="3586931643579894722">Skjul detaljer</translation>
<translation id="3587738293690942763">Midtre</translation>
+<translation id="3590643883886679995">Påloggingsdata blir lagret på denne enheten når du går ut av Inkognitomodus.</translation>
+<translation id="359126217934908072">MÃ¥ned/Ã¥r:</translation>
<translation id="3592413004129370115">Italian (konvolutt)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Du kan tilbakestille gruppen din når som helst. Det tar omtrent én dag å bli med i en ny gruppe.}=1{Du kan tilbakestille gruppen din når som helst. Det tar omtrent én dag å bli med i en ny gruppe.}other{Du kan tilbakestille gruppen din når som helst. Det tar omtrent {NUM_DAYS} dager å bli med i en ny gruppe.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Programmet er blokkert av administratoren din</translation>
<translation id="3608932978122581043">Feed-retning</translation>
@@ -706,13 +727,13 @@ brukere av denne nettleseren.</translation>
<translation id="3615877443314183785">Angi en gyldig utløpsdato</translation>
<translation id="36224234498066874">Slett nettleserdata</translation>
<translation id="362276910939193118">Vis fullstendig logg</translation>
-<translation id="3625635938337243871">Påloggingsdata blir lagret på denne enheten når du går ut av Inkognitomodus.</translation>
<translation id="3630155396527302611">Hvis programmet allerede har fått tillatelse til å bruke nettverket, kan du prøve
å fjerne det fra listen og så legge det til på nytt.</translation>
<translation id="3630699740441428070">Administratorene for denne enheten har konfigurert nettverkstilkoblingen din, noe som betyr at de kanskje kan se nettverkstrafikken din, inkludert hvilke nettsteder du besøker.</translation>
<translation id="3631244953324577188">Biometri</translation>
<translation id="3633738897356909127">Knappen «Oppdater Chrome» – trykk på Enter for å oppdatere Chrome fra Chrome-innstillingene</translation>
<translation id="3634530185120165534">Skuff 5</translation>
+<translation id="3637662659967048211">Lagre i Google-kontoen</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Program:</translation>
<translation id="3650584904733503804">Valideringen var vellykket</translation>
@@ -753,6 +774,7 @@ brukere av denne nettleseren.</translation>
<translation id="3781428340399460090">Knallrosa</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth-enheter</translation>
+<translation id="3787675388804467730">Virtuelt kortnummer</translation>
<translation id="3787705759683870569">Utløper <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Størrelse 16</translation>
<translation id="3789841737615482174">Installer</translation>
@@ -772,6 +794,7 @@ brukere av denne nettleseren.</translation>
<translation id="3841184659773414994">Filbehandlere</translation>
<translation id="385051799172605136">Tilbake</translation>
<translation id="3858027520442213535">Oppdater dato og klokkeslett</translation>
+<translation id="3881478300875776315">Vis færre linjer</translation>
<translation id="3884278016824448484">Motstridende enhetsidentifikator</translation>
<translation id="3885155851504623709">Sogn</translation>
<translation id="388632593194507180">Overvåking er oppdaget</translation>
@@ -797,6 +820,7 @@ brukere av denne nettleseren.</translation>
<translation id="397105322502079400">Beregner …</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> er blokkert</translation>
<translation id="3973357910713125165">Knappen Kjør Chrome-sikkerhetssjekk – trykk på Enter for å kjøre en sikkerhetssjekk i Chrome-innstillingene</translation>
+<translation id="3986705137476756801">Slå av Direkteteksting inntil videre</translation>
<translation id="3987405730340719549">Chrome har funnet ut at dette nettstedet kan være falskt eller prøve å svindle deg.
Hvis du mener at dette er en feil, kan du gå til https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@ brukere av denne nettleseren.</translation>
<translation id="4275830172053184480">Start enheten din på nytt</translation>
<translation id="4277028893293644418">Tilbakestill passordet</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="4287885627794386150">Kvalifisert for utprøving, men ikke aktiv</translation>
<translation id="4297502707443874121">Miniatyrbilde for side <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Vis</translation>
<translation id="4300675098767811073">Flere hull høyre</translation>
<translation id="4302514097724775343">Trykk på dinosauren for å spille</translation>
<translation id="4302965934281694568">Chou3 (konvolutt)</translation>
<translation id="4305666528087210886">Kunne ikke åpne filen</translation>
-<translation id="4305817255990598646">Bytt</translation>
+<translation id="4306529830550717874">Vil du lagre adressen?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokkér (standard)</translation>
<translation id="4314815835985389558">Administrer synkronisering</translation>
@@ -926,6 +951,7 @@ brukere av denne nettleseren.</translation>
<translation id="4377125064752653719">Du forsøkte å gå til <ph name="DOMAIN" />, men sertifikatet tjeneren presenterte har blitt trukket tilbake av utstederen. Dette innebærer at sikkerhetsinformasjonen tjeneren presenterte ikke er klarert. Det kan hende at du kommuniserer med en angriper.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Rand</translation>
+<translation id="4406883609789734330">Direkteteksting</translation>
<translation id="4406896451731180161">søkeresultater</translation>
<translation id="4408413947728134509">Informasjonskapsler <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Du har nettopp skrevet inn passordet ditt på et villedende nettsted. Chrome anbefaler at du går til <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> og andre nettsteder der du bruker dette passordet, og endrer det nå.</translation>
@@ -938,7 +964,6 @@ brukere av denne nettleseren.</translation>
<translation id="4435702339979719576">postkort)</translation>
<translation id="443673843213245140">Bruk av proxy-tjener er deaktivert, men det er angitt en uttrykkelig proxy-tjenerkonfigurasjon.</translation>
<translation id="4464826014807964867">Nettsteder med informasjon fra organisasjonen din</translation>
-<translation id="4466881336512663640">Endringer i skjemaet går tapt. Er du sikker på at du vil fortsette?</translation>
<translation id="4476953670630786061">Dette skjemaet er ikke sikkert. Autofyll er slått av.</translation>
<translation id="4477350412780666475">Neste spor</translation>
<translation id="4482953324121162758">Dette nettstedet oversettes ikke.</translation>
@@ -972,6 +997,7 @@ brukere av denne nettleseren.</translation>
<translation id="4594403342090139922">&amp;Angre slettingen</translation>
<translation id="4597348597567598915">Størrelse 8</translation>
<translation id="4600854749408232102">C6/C5 (konvolutt)</translation>
+<translation id="4606870351894164739">Virkningsfull</translation>
<translation id="4628948037717959914">Bilde</translation>
<translation id="4631649115723685955">Penger tilbake er tilknyttet</translation>
<translation id="4636930964841734540">Info</translation>
@@ -991,6 +1017,7 @@ brukere av denne nettleseren.</translation>
<translation id="4691835149146451662">Architecture-A (konvolutt)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Side</translation>
+<translation id="4702656508969495934">Direkteteksting er synlig – bruk vindusbytteren for å fokusere</translation>
<translation id="4708268264240856090">Tilkoblingen ble avbrutt</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Kjør Windows Nettverksdiagnose<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ brukere av denne nettleseren.</translation>
<translation id="4738601419177586157">Søkeforslag for <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Administrer passord…</translation>
<translation id="4744603770635761495">Kjørbar sti</translation>
+<translation id="4749011317274908093">NÃ¥ er du inkognito</translation>
<translation id="4750917950439032686">Informasjonen din (for eksempel passord eller kredittkortnumre) er privat når den sendes til dette nettstedet.</translation>
<translation id="4756388243121344051">&amp;Logg</translation>
<translation id="4758311279753947758">Legg til kontaktinformasjon</translation>
@@ -1033,6 +1061,8 @@ brukere av denne nettleseren.</translation>
<translation id="4813512666221746211">Nettverksfeil</translation>
<translation id="4816492930507672669">Tilpass til siden</translation>
<translation id="4819347708020428563">Vil du redigere annoteringer i standardvisningen?</translation>
+<translation id="4825507807291741242">Kraftfull</translation>
+<translation id="4838327282952368871">Drømmende</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">Visning</translation>
<translation id="485316830061041779">Tysk</translation>
@@ -1169,6 +1199,7 @@ brukere av denne nettleseren.</translation>
<translation id="5314967030527622926">Heftemaker</translation>
<translation id="5316812925700871227">Rotér mot klokken</translation>
<translation id="5317780077021120954">Lagre</translation>
+<translation id="5321288445143113935">Maksimert</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> av <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Velg kontaktinformasjon</translation>
<translation id="5327248766486351172">Navn</translation>
@@ -1176,11 +1207,13 @@ brukere av denne nettleseren.</translation>
<translation id="5332219387342487447">Leveringsmetode</translation>
<translation id="5333022057423422993">Chrome har funnet passordet du nettopp brukte, i et databrudd. For å sikre kontoene dine anbefaler vi at du sjekker de lagrede passordene dine.</translation>
<translation id="5334013548165032829">Detaljerte systemlogger</translation>
+<translation id="5334145288572353250">Lagre adresse?</translation>
<translation id="5340250774223869109">Programmet er blokkert</translation>
<translation id="534295439873310000">NFC-enheter</translation>
<translation id="5344579389779391559">Denne siden kan prøve å belaste deg for penger</translation>
<translation id="5355557959165512791">Du kan ikke gå til <ph name="SITE" /> akkurat nå, siden sertifikatet for nettstedet er trukket tilbake. Nettverksfeil- og angrep er vanligvis midlertidige, så denne siden fungerer sannsynligvis senere.</translation>
<translation id="536296301121032821">Kunne ikke lagre angivelsen for enhetsinnstillinger</translation>
+<translation id="5363309033720083897">Den serielle porten tillates av administratoren din</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="5386426401304769735">Sertifikatkjeden for dette nettstedet inneholder et sertifikat som er signert med SHA-1.</translation>
@@ -1189,6 +1222,7 @@ brukere av denne nettleseren.</translation>
<translation id="5398772614898833570">Annonser er blokkert</translation>
<translation id="5400836586163650660">Grå</translation>
<translation id="540969355065856584">Denne tjeneren kunne ikke bevise at den er <ph name="DOMAIN" />. Sikkerhetssertifikatet til tjeneren er ikke gyldig for øyeblikket. Dette kan være forårsaket av en feilkonfigurasjon eller en angriper som lytter på tilkoblingen din.</translation>
+<translation id="541143247543991491">Nettsky (hele systemet)</translation>
<translation id="541416427766103491">Hylle 4</translation>
<translation id="5421136146218899937">Slett nettleserdata</translation>
<translation id="5426179911063097041"><ph name="SITE" /> vil sende deg varsler</translation>
@@ -1202,6 +1236,7 @@ brukere av denne nettleseren.</translation>
<translation id="5455374756549232013">Feil tidsstempel for enhetsinnstillinger</translation>
<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="5463625433003343978">Finner enheter …</translation>
<translation id="5469868506864199649">Italiensk</translation>
<translation id="5470861586879999274">&amp;Endre likevel</translation>
<translation id="5478437291406423475">B6/C4 (konvolutt)</translation>
@@ -1251,7 +1286,6 @@ brukere av denne nettleseren.</translation>
<translation id="5624120631404540903">Administrer passord</translation>
<translation id="5629630648637658800">Kunne ikke laste in angivelsen for enhetsinnstillinger</translation>
<translation id="5631439013527180824">Ugyldig token for enhetsadministrering</translation>
-<translation id="5632627355679805402">Dataene dine har blitt kryptert med <ph name="BEGIN_LINK" />Google-passordet<ph name="END_LINK" /> ditt siden <ph name="TIME" />. Skriv det inn for å starte synkroniseringen.</translation>
<translation id="5633066919399395251">Angripere som er på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, kan prøve å installere farlige programmer på datamaskinen du bruker, for å stjele eller slette informasjonen din (for eksempel bilder, passord, meldinger og kredittkortinformasjon). <ph name="BEGIN_LEARN_MORE_LINK" />Finn ut mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Villedende innhold er blokkert.</translation>
<translation id="5644090287519800334">X-forskyvning av bilde på side 1</translation>
@@ -1290,12 +1324,12 @@ brukere av denne nettleseren.</translation>
<translation id="5785756445106461925">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å utseendet til siden.</translation>
<translation id="5786044859038896871">Vil du fylle ut kortinformasjonen?</translation>
<translation id="578633867165174378">Chrome har funnet passordet du nettopp brukte, i et databrudd. Vi anbefaler at du endrer dette passordet nå.</translation>
-<translation id="5798290721819630480">Vil du forkaste endringene?</translation>
<translation id="5803412860119678065">Vil du fylle ut informasjonen knyttet til <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Tillatelser</translation>
<translation id="5804427196348435412">Bruk NFC-enheter</translation>
<translation id="5810442152076338065">Tilkoblingen til <ph name="DOMAIN" /> er kryptert med en foreldet chifferserie.</translation>
<translation id="5813119285467412249">&amp;Legg til likevel</translation>
+<translation id="5817918615728894473">Koble sammen</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Dette kortet blir belastet når du betaler, men det egentlige kortnummeret deles ikke med dette nettstedet. En midlertidig CVC-kode blir generert for ekstra sikkerhet.}other{Kortet du velger, blir belastet når du betaler, men det egentlige kortnummeret deles ikke med dette nettstedet. En midlertidig CVC-kode blir generert for ekstra sikkerhet.}}</translation>
<translation id="5826507051599432481">Vanlig navn (CN)</translation>
<translation id="5838278095973806738">Du bør ikke oppgi sensitiv informasjon på dette nettstedet (for eksempel passord eller kredittkort) fordi den kan bli stjålet av angripere.</translation>
@@ -1303,6 +1337,7 @@ brukere av denne nettleseren.</translation>
<translation id="5855253129151731373">Vertsnavnet til dette nettstedet ligner på <ph name="LOOKALIKE_DOMAIN" />. Noen ganger etterligner angripere nettsteder ved å gjøre små endringer i domenenavnet som er vanskelige å se.
Hvis du mener at dette er en feil, kan du gå til https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Av</translation>
<translation id="5862579898803147654">Hylle 8</translation>
<translation id="5863847714970149516">Den neste siden kan prøve å belaste deg for penger</translation>
<translation id="5866257070973731571">Legg til telefonnummer</translation>
@@ -1319,6 +1354,7 @@ brukere av denne nettleseren.</translation>
<translation id="5913377024445952699">Skjermopptaket er satt på pause</translation>
<translation id="59174027418879706">Aktivert</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 er i bruk}other{# er i bruk}}</translation>
<translation id="5921185718311485855">PÃ¥</translation>
<translation id="5921639886840618607">Vil du lagre kortet i Google-kontoen?</translation>
<translation id="5922853866070715753">Nesten ferdig</translation>
@@ -1338,6 +1374,7 @@ brukere av denne nettleseren.</translation>
<translation id="5989320800837274978">Verken statiske proxytjenere eller en nettadresse med .pac-skript er angitt.</translation>
<translation id="5992691462791905444">Ingeniør-Z-fals</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultater for «<ph name="SEARCH_TEXT" />»</translation>
+<translation id="6006484371116297560">Klassisk</translation>
<translation id="6008122969617370890">N-til-1-rekkefølge</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Kontrollér passordene dine</translation>
@@ -1359,6 +1396,7 @@ brukere av denne nettleseren.</translation>
<translation id="6045164183059402045">Imposisjonsmal</translation>
<translation id="6047233362582046994">Hvis du forstår sikkerhetsrisikoen, kan du <ph name="BEGIN_LINK" />gå til dette nettstedet<ph name="END_LINK" /> før de skadelige appene er fjernet.</translation>
<translation id="6047927260846328439">Dette innholdet kan prøve å lure deg til å installere programvare eller oppgi personopplysninger. <ph name="BEGIN_LINK" />Vis det likevel<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Trykk og hold på |<ph name="ACCELERATOR" />| for å avslutte fullskjerm</translation>
<translation id="6049488691372270142">Sidelevering</translation>
<translation id="6051221802930200923">Du kan ikke gå til <ph name="SITE" /> akkurat nå, siden nettstedet bruker sertifikatfesting. Nettverksfeil og -angrep er vanligvis midlertidige, så denne siden fungerer sannsynligvis senere.</translation>
<translation id="6051898664905071243">Antall sider:</translation>
@@ -1375,6 +1413,7 @@ brukere av denne nettleseren.</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>
<translation id="6116338172782435947">Se tekst og bilder som er kopiert til utklippstavlen</translation>
<translation id="6120179357481664955">Husker du UPI-ID-en din?</translation>
+<translation id="6123290840358279103">Se virtuelt kort</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Sjekk alle kabler, og start rutere, modemer eller andre nettverksenheter
du bruker, på nytt.</translation>
@@ -1411,6 +1450,7 @@ brukere av denne nettleseren.</translation>
<translation id="6289939620939689042">Sidefarge</translation>
<translation id="6290238015253830360">De foreslåtte artiklene dine vises her</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Stopper Google-assistenten i Chrome</translation>
<translation id="6305205051461490394"><ph name="URL" /> er ikke tilgjengelig.</translation>
<translation id="6312113039770857350">Nettsiden er ikke tilgjengelig</translation>
@@ -1436,6 +1476,7 @@ brukere av denne nettleseren.</translation>
<translation id="6390200185239044127">Halv Z-fals</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Innliming fra <ph name="ORIGIN_NAME" /> på denne plasseringen er blokkert av en administratorregel</translation>
+<translation id="6398765197997659313">Avslutt fullskjerm</translation>
<translation id="6401136357288658127">Denne regelen er avviklet. Du bør bruke den nye regelen <ph name="NEW_POLICY" /> i stedet.</translation>
<translation id="6404511346730675251">Rediger bokmerket</translation>
<translation id="6406765186087300643">C0 (konvolutt)</translation>
@@ -1448,7 +1489,6 @@ brukere av denne nettleseren.</translation>
<translation id="6428450836711225518">Bekreft telefonnummeret ditt</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="6440503408713884761">Ignorert</translation>
<translation id="6443406338865242315">hvilke utvidelser og programtillegg du har installert</translation>
<translation id="6446163441502663861">Kahu (konvolutt)</translation>
@@ -1491,6 +1531,7 @@ brukere av denne nettleseren.</translation>
<translation id="6624427990725312378">Kontaktinformasjon</translation>
<translation id="6626291197371920147">Legg til et gyldig kortnummer</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Søk</translation>
+<translation id="6630043285902923878">Finner USB-enheter …</translation>
<translation id="6630809736994426279">Angripere som er på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, kan prøve å installere farlige programmer på Macen du bruker, for å stjele eller slette informasjonen din (for eksempel bilder, passord, meldinger og kredittkortinformasjon). <ph name="BEGIN_LEARN_MORE_LINK" />Finn ut mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Tøm</translation>
@@ -1506,6 +1547,7 @@ brukere av denne nettleseren.</translation>
<translation id="6671697161687535275">Vil du fjerne forslaget fra Chromium?</translation>
<translation id="6685834062052613830">Logg av og fullfør konfigurasjonen</translation>
<translation id="6687335167692595844">Forespurt skriftstørrelse</translation>
+<translation id="6688743156324860098">Oppdater …</translation>
<translation id="6689249931105087298">Relativ med svartpunktkomprimering</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="6698381487523150993">Opprettet:</translation>
@@ -1521,6 +1563,7 @@ brukere av denne nettleseren.</translation>
<translation id="6744009308914054259">Mens du venter på å koble til, kan du gå til Nedlastinger for å lese artikler uten nett.</translation>
<translation id="6753269504797312559">Retningslinjeverdi</translation>
<translation id="6757797048963528358">Enheten din gikk inn i hvilemodus.</translation>
+<translation id="6767985426384634228">Oppdatere adresse?</translation>
<translation id="6768213884286397650">Hagaki (postkort)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Fiolett</translation>
@@ -1543,6 +1586,7 @@ brukere av denne nettleseren.</translation>
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome har forenklet denne siden for å gjøre den lettere å lese. Chrome hentet den opprinnelige siden via en usikker forbindelse.</translation>
<translation id="6891596781022320156">Innstillingsnivået støttes ikke.</translation>
+<translation id="6895143722905299846">Virtuelt nummer:</translation>
<translation id="6895330447102777224">Kortet ditt er bekreftet</translation>
<translation id="6897140037006041989">Brukeragent</translation>
<translation id="6898699227549475383">Organisasjon (O)</translation>
@@ -1578,10 +1622,10 @@ brukere av denne nettleseren.</translation>
<translation id="7004583254764674281">Bruk Windows Hello til å bekrefte kort raskere</translation>
<translation id="7006930604109697472">Send likevel</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Innstillinger for størrelsesendring</translation>
<translation id="7014741021609395734">Zoomnivå</translation>
<translation id="7016992613359344582">Disse belastningene kan skje én gang eller være gjentakende, og det er ikke sikkert de er åpenbare.</translation>
<translation id="7029809446516969842">Passord</translation>
+<translation id="7030436163253143341">Sertifikatet er ikke gyldig</translation>
<translation id="7031646650991750659">hvilke Google Play-apper du har installert</translation>
<translation id="7050187094878475250">Du prøvde å nå <ph name="DOMAIN" />. Tjeneren presenterte et sertifikat som har en gyldighetsperiode som er for lang til å være pålitelig.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Kan ikke lagre dette kortet akkurat nå}other{Kan ikke lagre disse kortene akkurat nå}}</translation>
@@ -1650,12 +1694,14 @@ brukere av denne nettleseren.</translation>
<translation id="7300012071106347854">Koboltblå</translation>
<translation id="7302712225291570345">«<ph name="TEXT" />»</translation>
<translation id="7304030187361489308">Høyt</translation>
+<translation id="7305756307268530424">Start tregere</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Tilkoblingshjelp</translation>
<translation id="7323804146520582233">Skjul «<ph name="SECTION" />»-delen</translation>
<translation id="733354035281974745">Overstyrt av lokal konto på enheten</translation>
<translation id="7333654844024768166">Du har nettopp skrevet inn passordet ditt på et villedende nettsted. Chromium anbefaler at du går til <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> og andre nettsteder der du bruker dette passordet, og endrer det nå.</translation>
<translation id="7334320624316649418">&amp;Omorganiser likevel</translation>
+<translation id="7337248890521463931">Vis flere linjer</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>
@@ -1663,6 +1709,7 @@ brukere av denne nettleseren.</translation>
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Kommandolinje </translation>
<translation id="7359588939039777303">Annonser er blokkert.</translation>
+<translation id="7363096869660964304">Du er imidlertid ikke usynlig. Inkognitomodus skjuler ikke surfingen din for arbeidsgiveren din, internettleverandøren din eller nettstedene du besøker.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" /> – trykk på Tab og deretter på Enter for å legge til og administrere adresser i Chrome-innstillingene</translation>
<translation id="7365849542400970216">Kan nettstedet få vite når enheten er i bruk?</translation>
<translation id="7372973238305370288">søkeresultat</translation>
@@ -1673,7 +1720,9 @@ brukere av denne nettleseren.</translation>
<translation id="7378594059915113390">Mediekontroller</translation>
<translation id="7378627244592794276">Nei takk</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ikke relevant</translation>
<translation id="7390545607259442187">Bekreft kortet</translation>
+<translation id="7392089738299859607">Oppdater adresse</translation>
<translation id="7399802613464275309">Sikkerhetssjekk</translation>
<translation id="7400418766976504921">Nettadresse</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> administreres</translation>
@@ -1688,6 +1737,7 @@ brukere av denne nettleseren.</translation>
&lt;li&gt;Gå til &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;brukerstøtten for Chrome&lt;/a&gt; for å finne ut hvordan du fjerner programvaren fra datamaskinen permanent.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Nydelig</translation>
<translation id="7416351320495623771">Administrer passord…</translation>
<translation id="7419106976560586862">Profilbane</translation>
<translation id="7437289804838430631">Legg til kontaktinformasjon</translation>
@@ -1703,7 +1753,7 @@ brukere av denne nettleseren.</translation>
<translation id="7481312909269577407">Frem</translation>
<translation id="7485870689360869515">Ingen data ble funnet.</translation>
<translation id="7495528107193238112">Dette innholdet er blokkert. Kontakt nettstedseieren for å løse problemet.</translation>
-<translation id="7498234416455752244">Fortsett å endre</translation>
+<translation id="7498193950643227031">Hvis du endrer størrelsen på appen, kan det medføre uventet oppførsel. Du kan nå begrense muligheten til å endre størrelse på apper i <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Du har nettopp skrevet inn passordet ditt på et villedende nettsted. Chromium anbefaler at du sjekker de lagrede passordene dine for <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> og andre nettsteder der du bruker dette passordet, nå.</translation>
<translation id="7508255263130623398">Den returnerte enhets-ID-en for regelen er tom eller samsvarer ikke med den faktiske enhets-ID-en</translation>
<translation id="7508870219247277067">Avokadogrønn</translation>
@@ -1723,6 +1773,7 @@ brukere av denne nettleseren.</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="755279583747225797">Utprøving er aktiv</translation>
<translation id="7552846755917812628">Prøv følgende tips:</translation>
<translation id="7554475479213504905">Last inn på nytt og vis likevel</translation>
<translation id="7554791636758816595">Ny fane</translation>
@@ -1741,7 +1792,6 @@ brukere av denne nettleseren.</translation>
<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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" /> – trykk på Tab og deretter på Enter for å se og administrere passord i Chrome-innstillingene</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="7616645509853975347">Administratoren har slått på Chrome Enterprise Connectors i nettleseren din. Disse koblingene har tilgang til noen av dataene dine.</translation>
<translation id="7619838219691048931">Sluttark</translation>
<translation id="762844065391966283">Enkeltvis</translation>
@@ -1806,13 +1856,12 @@ brukere av denne nettleseren.</translation>
<translation id="782886543891417279">Det kan hende at Wi-Fi-nettverket du bruker (<ph name="WIFI_NAME" />), krever at du besøker en påloggingsside.</translation>
<translation id="7836231406687464395">Postfix (konvolutt)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ingen}=1{1 app (<ph name="EXAMPLE_APP_1" />)}=2{2 apper (<ph name="EXAMPLE_APP_1" /> og <ph name="EXAMPLE_APP_2" />)}other{# apper (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Du er imidlertid ikke usynlig. Inkognitomodus skjuler ikke surfingen din for arbeidsgiveren din, Internett-leverandøren eller nettstedene du besøker.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Ã…pne filer med filtypeassosiasjoner.</translation>
<translation id="7862185352068345852">Vil du forlate nettstedet?</translation>
<translation id="7865448901209910068">Beste hastighet</translation>
<translation id="7874263914261512992">Du har nettopp skrevet inn passordet ditt på et villedende nettsted. Chrome anbefaler at du sjekker de lagrede passordene dine for <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> og andre nettsteder der du bruker dette passordet, nå.</translation>
<translation id="7878562273885520351">Passordet ditt kan være kompromittert</translation>
+<translation id="7880146494886811634">Lagre adresse</translation>
<translation id="7882421473871500483">Brun</translation>
<translation id="7887683347370398519">Kontrollér CVC-koden din, og prøv igjen.</translation>
<translation id="7887885240995164102">Start bilde-i-bilde</translation>
@@ -1820,6 +1869,7 @@ brukere av denne nettleseren.</translation>
<translation id="7894280532028510793">Hvis stavemåten er korrekt, kan du <ph name="BEGIN_LINK" />prøve å kjøre Nettverksdiagnose<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (konvolutt)</translation>
<translation id="7931318309563332511">Ukjent</translation>
+<translation id="793209273132572360">Vil du oppdatere adressen?</translation>
<translation id="7932579305932748336">Belegg</translation>
<translation id="79338296614623784">Angi et gyldig telefonnummer</translation>
<translation id="7934052535022478634">Betalingen er fullført</translation>
@@ -1890,6 +1940,7 @@ brukere av denne nettleseren.</translation>
<translation id="8175796834047840627">Chrome tilbyr å lagre kort i Google-kontoen din fordi du er logget på. Du kan endre dette i innstillingene.</translation>
<translation id="8176440868214972690">Enhetsadministratoren har sendt noe informasjon til de følgende nettstedene, for eksempel innstillinger eller retningslinjer.</translation>
<translation id="8184538546369750125">Bruk global standardinnstilling (Tillat)</translation>
+<translation id="8193086767630290324">handlinger som utføres med data som er merket som konfidensielle</translation>
<translation id="8194797478851900357">&amp;Angre flyttingen</translation>
<translation id="8201077131113104583">Ugyldig oppdaterings-URL for utvidelse med ID «<ph name="EXTENSION_ID" />».</translation>
<translation id="8202097416529803614">Bestillingssammendrag</translation>
@@ -1912,6 +1963,7 @@ brukere av denne nettleseren.</translation>
<translation id="8249296373107784235">Avbryt</translation>
<translation id="8249320324621329438">Sist hentet:</translation>
<translation id="8253091569723639551">Fakturaadresse er obligatorisk</translation>
+<translation id="8257387598443225809">Denne appen er designet for mobil</translation>
<translation id="825929999321470778">Vis alle lagrede passord</translation>
<translation id="8261506727792406068">Slett</translation>
<translation id="8262952874573525464">Kantstifting bunn</translation>
@@ -2035,7 +2087,6 @@ Mer informasjon:
<translation id="8719528812645237045">Flere hull topp</translation>
<translation id="8725066075913043281">Prøv igjen</translation>
<translation id="8726549941689275341">Sidestørrelse:</translation>
-<translation id="8728672262656704056">Du er nå i inkognitomodus</translation>
<translation id="8730621377337864115">Ferdig</translation>
<translation id="8731544501227493793">Knappen «Administrer passord» – trykk på Enter for å se og administrere passord i Chrome-innstillingene</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> administreres av <ph name="MANAGER" /></translation>
@@ -2112,6 +2163,7 @@ Mer informasjon:
<translation id="9020542370529661692">Denne siden har blitt oversatt til <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Ugyldig)</translation>
+<translation id="9030265603405983977">Ensfarget</translation>
<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>
@@ -2135,6 +2187,7 @@ Mer informasjon:
<translation id="91108059142052966">En administratorregel deaktiverer skjermdeling med <ph name="APPLICATION_TITLE" /> når konfidensielt innhold er synlig</translation>
<translation id="9114524666733003316">Bekrefter kortet …</translation>
<translation id="9114581008513152754">Denne nettleseren administreres ikke av et selskap eller en annen organisasjon. Aktiviteten på denne enheten kan bli administrert utenfor Chrome. <ph name="BEGIN_LINK" />Finn ut mer<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Frisk</translation>
<translation id="9119042192571987207">Opplastet</translation>
<translation id="9128016270925453879">Regler er lastet inn</translation>
<translation id="9128870381267983090">Koble til nettverk</translation>
@@ -2153,6 +2206,7 @@ Mer informasjon:
<translation id="9170848237812810038">&amp;Angre</translation>
<translation id="9171296965991013597">Vil du gå ut av appen?</translation>
<translation id="9173282814238175921">Enkeltdokument / nytt ark</translation>
+<translation id="9173995187295789444">Skanner etter Bluetooth-enheter …</translation>
<translation id="917450738466192189">Tjenerens sertifikat er ugyldig.</translation>
<translation id="9174917557437862841">Knappen for å bytte fane – trykk på Enter for å bytte til denne fanen</translation>
<translation id="9179703756951298733">Administrer betalingene og kredittkortopplysningene dine i Chrome-innstillingene</translation>
diff --git a/chromium/components/strings/components_strings_or.xtb b/chromium/components/strings/components_strings_or.xtb
index 6322170f361..9efa5cdccc3 100644
--- a/chromium/components/strings/components_strings_or.xtb
+++ b/chromium/components/strings/components_strings_or.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">ଯଦି ଯାଞà­à¬š କରାଯାଇଛି, ତେବେ ଦà­à¬°à­à¬¤à¬¤à¬° ଭାବେ ଫରà­à¬® ପୂରଣ ପାଇଠChrome ଆପଣଙà­à¬• କାରà­à¬¡à¬° à¬à¬• କପି à¬à¬¹à¬¿ ଡିଭାଇସà­â€Œà¬°à­‡ ଷà­à¬Ÿà­‹à¬°à­ କରିବ।</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" />ପାଇଠଅନà­à¬®à¬¤à¬¿ ଚୟନ କରନà­à¬¤à­</translation>
<translation id="1113869188872983271">&amp;ପà­à¬¨à¬ƒà¬•à­à¬°à¬®à¬•à­ ପୂରà­à¬¬à¬¬à¬¤à­â€Œ କରନà­à¬¤à­</translation>
+<translation id="1123753900084781868">ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ ଲାଇଭୠକà­à­Ÿà¬¾à¬ªà¬¸à¬¨à­ ଉପଲବà­à¬§ ନାହିà¬</translation>
<translation id="1125573121925420732">ଯେତେବେଳେ ୱେବà­â€à¬¸à¬¾à¬‡à¬Ÿà­â€à¬—à­à­œà¬¿à¬• ସେମାନଙà­à¬•à¬° ସà­à¬°à¬•à­à¬·à¬¾ ଅପà­â€Œà¬¡à­‡à¬Ÿà­â€ କରନà­à¬¤à¬¿, ସେତେବେଳେ ସାଧାରଣତଃ ଚେତାବନୀ ଆସିପାରେ। à¬à¬¥à¬¿à¬°à­‡ ଶୀଘà­à¬° ଉନà­à¬¨à¬¤à¬¿ ହେବା ଉଚିତà­â€à¥¤</translation>
<translation id="112840717907525620">ନୀତି କେଚà­â€ ଠିକୠଅଛି</translation>
<translation id="1130564665089811311">"ପୃଷà­à¬ à¬¾ ଅନà­à¬¬à¬¾à¬¦ କରନà­à¬¤à­" ବଟନà­, Google Translate ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରି à¬à¬¹à¬¿ ପୃଷà­à¬ à¬¾à¬•à­ ଅନà­à¬¬à¬¾à¬¦ କରିବା ପାଇଠEnter ଦବାନà­à¬¤à­</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">ଆପଣଙà­à¬• ଡିଭାଇସà­â€Œà¬° ନାମ</translation>
<translation id="124116460088058876">ଅନେକ ଭାଷା</translation>
<translation id="1243027604378859286">ଲେଖକ:</translation>
+<translation id="1246424317317450637">ବୋଲà­à¬¡</translation>
<translation id="1250759482327835220">ପରବରà­à¬¤à­à¬¤à­€ ସମୟରେ, ପୈଠ କରିବାର ପà­à¬°à¬•à­à¬°à¬¿à­Ÿà¬¾à¬•à­ ଦà­à¬°à­à¬¤à¬¤à¬° କରିବା ପାଇଠଆପଣଙà­à¬•à¬° Google ଆକାଉଣà­à¬Ÿà¬°à­‡ ଆପଣଙà­à¬• କାରà­à¬¡ ଓ ବିଲିଂ ଠିକଣା ସେଭୠକରନà­à¬¤à­à¥¤</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (ସିଙà­à¬•à­ କରାଯାଇଛି)</translation>
<translation id="1256368399071562588">&lt;p&gt;ଯଦି ଆପଣ କୌଣସି ୱେବà­â€Œà¬¸à¬¾à¬‡à¬Ÿà­â€Œà¬•à­ ଖୋଲିବାକୠଚାହà­à¬à¬›à¬¨à­à¬¤à¬¿ à¬à¬¬à¬‚ à¬à¬¹à¬¾ ଖୋଲà­à¬¨à¬¾à¬¹à¬¿à¬, ତେବେ ପà­à¬°à¬¥à¬®à­‡ ନିମà­à¬¨à¬°à­‡ ଦିଆଯାଇଥିବା ସମସà­à­Ÿà¬¾ ନିବାରଣ ସୋପାନ ସାହାଯà­à­Ÿà¬°à­‡ ତà­à¬°à­à¬Ÿà¬¿à¬° ସମାଧାନ କରନà­à¬¤à­:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">ଆପଣଙà­à¬• ପାସà­â€Œà­±à¬¾à¬°à­à¬¡ ପରିବରà­à¬¤à­à¬¤à¬¨ କରନà­à¬¤à­</translation>
<translation id="1484290072879560759">ସିପିଂ ଠିକଣା ବାଛନà­à¬¤à­</translation>
<translation id="1492194039220927094">ନୀତିଗà­à­œà¬¿à¬• ପà­à¬¸à­â€Œ କରନà­à¬¤à­:</translation>
+<translation id="1495677929897281669">ଟାବà­â€Œà¬•à­ ଫେରନà­à¬¤à­</translation>
<translation id="1501859676467574491">ଆପଣଙà­à¬•à¬° Google Accountରୠକାରà­à¬¡ ଦେଖାନà­à¬¤à­</translation>
<translation id="1507202001669085618">&lt;p&gt;ଆପଣ ଯଦି କୌଣସି ୱାଇ-ଫାଇ ପୋରà­à¬Ÿà¬¾à¬²à­ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରà­à¬›à¬¨à­à¬¤à¬¿, ଯେଉà¬à¬ à¬¿ ଆପଣଙà­à¬•à­ ଅନà­â€Œà¬²à¬¾à¬‡à¬¨à­ ହେବା ପାଇଠସାଇନୠଇନୠକରିବାକୠହà­à¬, ତାହେଲେ ଆପଣ à¬à¬¹à¬¿ ତà­à¬°à­à¬Ÿà¬¿à¬•à­ ଦେଖିବେ।&lt;/p&gt;
&lt;p&gt;ତà­à¬°à­à¬Ÿà¬¿ ସମାଧାନ କରିବାକà­, ଆପଣ ଖୋଲିବାକୠଚେଷà­à¬Ÿà¬¾ କରà­à¬¥à¬¿à¬¬à¬¾ ପୃଷà­à¬ à¬¾à¬°à­‡ &lt;strong&gt;ସଂଯୋଗ କରନà­à¬¤à­&lt;/strong&gt;ରେ କà­à¬²à¬¿à¬•à­ କରନà­à¬¤à­à¥¤&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">à¬à¬¹à¬¿ ପୃଷà­à¬ à¬¾ à¬à¬¹à¬¾ କà­à¬¹à­‡</translation>
<translation id="153384715582417236">ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ ପାଇଠà¬à¬¤à¬¿à¬•à¬¿</translation>
<translation id="1536390784834419204">ପୃଷà­à¬ à¬¾à¬•à­ ଅନà­à¬¬à¬¾à¬¦ କରନà­à¬¤à­</translation>
+<translation id="1539840569003678498">ରିପୋରà­à¬Ÿ ପଠାଯାଇଛି:</translation>
<translation id="154408704832528245">ଡେଲିଭରୀ ଠିକଣା ବାଛନà­à¬¤à­</translation>
<translation id="1549470594296187301">à¬à¬¹à¬¿ ବୈଶିଷà­à¬Ÿà­à­Ÿà¬•à­ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରିବା ପାଇଠନିଶà­à¬šà¬¿à¬¤à¬°à­‚ପେ JavaScriptକୠସକà­à¬·à¬® କରାଯିବା ଉଚିତ।</translation>
<translation id="155039086686388498">ଇଞà­à¬œà¬¿à¬¨à¬¿à­Ÿà¬°à¬¿à¬‚-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">ପà­à¬°à¬¥à¬®à­‡ ଛୋଟ à¬à¬¡à¬œà­</translation>
<translation id="168693727862418163">à¬à¬¹à¬¿ ନୀତିର ମୂଲà­à­Ÿ à¬à¬¹à¬¾à¬° ସà­à¬•à¬¿à¬®à¬¾ ଅନà­à¬¯à¬¾à­Ÿà­€ ବୈଧ ହେବାରେ ବିଫଳ ହୋଇଛି à¬à¬¬à¬‚ à¬à¬¹à¬¾à¬•à­ ଅଣଦେଖା କରାଯିବ।</translation>
<translation id="168841957122794586">ସରà­à¬­à¬°à­ ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­â€â€à¬°à­‡ ଗୋଟିଠଦà­à¬°à­à¬¬à¬³ କà­à¬°à¬¿à¬ªà­à¬Ÿà­‹à¬—à­à¬°à¬¾à¬«à¬¿à¬•à­ କୀ ଅଛି।</translation>
+<translation id="1696290444144917273">ଭରà­à¬šà­à¬†à¬²à­ କାରà­à¬¡ ବିବରଣୀ ଦେଖନà­à¬¤à­</translation>
<translation id="1697532407822776718">ଆପଣ ପୂରା ପà­à¬°à¬¸à­à¬¤à­à¬¤ ଅଛନà­à¬¤à¬¿!</translation>
<translation id="1703835215927279855">ଲେଟରà­</translation>
<translation id="1706954506755087368">{1,plural, =1{à¬à¬¹à¬¿ ସରà­à¬­à¬°à­â€Œ ପà­à¬°à¬®à¬¾à¬£ କରିପାରିଲା ନାହିଠଯେ à¬à¬¹à¬¾ <ph name="DOMAIN" /> ଅଟେ; à¬à¬¹à¬¾à¬° ସà­à¬°à¬•à­à¬·à¬¾ ସରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­â€ ଆସନà­à¬¤à¬¾à¬•à¬¾à¬²à¬¿à¬ à¬¾à¬°à­ ସà­à­±à­€à¬•à¬¾à¬° କରାଯିବ। à¬à¬¹à¬¾ ହà­à¬à¬¤ à¬à¬• ଭà­à¬²à­ କନଫିଗà­â€â€à¬°à­‡à¬¸à¬¨à­ କିମà­à¬¬à¬¾ ଜଣେ ଆକà­à¬°à¬®à¬£à¬•à¬¾à¬°à­€ ଆପଣଙà­à¬•à¬° ସଂଯୋଗକୠପà­à¬°à¬¤à¬¿à¬°à­‹à¬§ କରà­à¬¥à¬¿à¬¬à¬¾ କାରଣରୠହୋଇପାରେ।}other{à¬à¬¹à¬¿ ସରà­à¬­à¬°à­â€Œ ପà­à¬°à¬®à¬¾à¬£ କରିପାରିଲା ନାହିଠଯେ à¬à¬¹à¬¾ <ph name="DOMAIN" /> ଅଟେ; à¬à¬¹à¬¾à¬° ସà­à¬°à¬•à­à¬·à¬¾ ସରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­â€ ଭବିଷà­à­Ÿà¬¤à¬°à­‡ # ଦିନଠାରୠସà­à­±à­€à¬•à¬¾à¬° କରାଯିବ। à¬à¬¹à¬¾ ହà­à¬à¬¤ à¬à¬• ଭà­à¬²à­ କନଫିଗà­â€â€à¬°à­‡à¬¸à¬¨à­ କିମà­à¬¬à¬¾ ଜଣେ ଆକà­à¬°à¬®à¬£à¬•à¬¾à¬°à­€ ଆପଣଙà­à¬•à¬° ସଂଯୋଗକୠପà­à¬°à¬¤à¬¿à¬°à­‹à¬§ କରà­à¬¥à¬¿à¬¬à¬¾ କାରଣରୠହୋଇପାରେ।}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> <ph name="VALUE" />ରେ ସେଟୠହୋଇନଥିବା ଯୋଗà­à¬ ଅଣଦେଖା କରାଯାଇଛି।</translation>
<translation id="1712552549805331520"><ph name="URL" /> ସà­à¬¥à¬¾à­Ÿà­€à¬°à­‚ପେ ଆପଣଙà­à¬•à¬° ସà­à¬¥à¬¾à¬¨à­€à­Ÿ କମà­à¬ªà­à­Ÿà­à¬Ÿà¬°à­â€Œà¬°à­‡ ଡାଟା ଷà­à¬Ÿà­‹à¬°à­ କରିବାକୠଚାହà­à¬à¬›à¬¿</translation>
<translation id="1713628304598226412">ଟà­à¬°à­‡ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">ମେଲବକà­à¬¸ 3</translation>
<translation id="1718029547804390981">ଅଂଶୀଦାର ହେବା ପାଇଠଡକà­à­Ÿà­à¬®à­‡à¬£à­à¬Ÿ ବହà­à¬¤ ବଡ଼ ଅଟେ</translation>
<translation id="1721424275792716183">* ଫିଲà­à¬¡ ଆବଶà­à­Ÿà¬• ଅଟେ</translation>
+<translation id="1727613060316725209">ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà¬Ÿà¬¿ ବୈଧ ଅଟେ</translation>
<translation id="1727741090716970331">ବୈଧ କାରà­à¬¡ ନମà­à¬¬à¬° ଯୋଗ କରନà­à¬¤à­</translation>
<translation id="1728677426644403582">ଆପଣ à¬à¬• ୱେବୠପୃଷà­à¬ à¬¾à¬° ଉତà­à¬¸ ଦେଖà­à¬›à¬¨à­à¬¤à¬¿</translation>
<translation id="173080396488393970">à¬à¬¹à¬¿ ପà­à¬°à¬•à¬¾à¬° କାରà­à¬¡ ସମରà­à¬¥à¬¿à¬¤ ନà­à¬¹à­‡à¬</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />ୱିଣà­à¬¡à­‹ ନେଟà­â€Œà­±à¬°à­à¬• ଡାଇଗà­à¬¨à­‹à¬·à­à¬Ÿà¬¿à¬•à­à¬¸ ଚଲେଇବାକୠଚେଷà­à¬Ÿà¬¾ କରନà­à¬¤à­<ph name="END_LINK" />।</translation>
<translation id="1772163372082567643">ଆପଣ ଯାଉଥିବା <ph name="ORIGIN" /> ସରà­à¬­à¬°à­, ଗୋଟିଠହେଡରୠସେଟୠକରିଛି, ଯାହା à¬à¬¹à¬¿ ସରà­à¬­à¬°à¬•à­ କରାଯାଇଥିବା ସମସà­à¬¤ ଅନà­à¬°à­‹à¬§à¬°à­‡ à¬à¬• ମୂଳ ନୀତି ଲାଗୠକରାଯିବା ଆବଶà­à­Ÿà¬• କରà­à¬›à¬¿à¥¤ କିନà­à¬¤à­ ହେଡରଟି ତà­à¬°à­à¬Ÿà¬¿à¬ªà­‚ରà­à¬£à­à¬£ ଅଟେ, ଯାହା <ph name="SITE" /> ପାଇଠଆପଣଙà­à¬• ଅନà­à¬°à­‹à¬§ ପୂରଣ କରିବାରୠବà­à¬°à¬¾à¬‰à¬œà¬°à¬•à­ ପà­à¬°à¬¤à¬¿à¬°à­‹à¬§ କରେ। କୌଣସି ସାଇଟର ସà­à¬°à¬•à­à¬·à¬¾ à¬à¬¬à¬‚ ଅନà­à­Ÿ ପà­à¬°à­‹à¬ªà¬°à­à¬Ÿà¬¿à¬—à­à¬¡à¬¼à¬¿à¬• କନଫିଗରୠକରିବାକୠସାଇଟୠଅପରେଟରମାନଙà­à¬• ଦà­à­±à¬¾à¬°à¬¾ ମୂଳ ନୀତିଗà­à­œà¬¿à¬• ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରାଯାଇପାରିବ।</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">ଦୟାକରି ଆପଣଙà­à¬•à¬° ସିଙà­à¬•à­ ପାସଫà­à¬°à­‡à¬œà­ ଅପà­â€Œà¬¡à­‡à¬Ÿà­â€Œ କରନà­à¬¤à­à¥¤</translation>
<translation id="1787142507584202372">ଆପଣଙà­à¬•à¬° ଖୋଲାଥିବା ଟାବà­â€Œà¬—à­à¬¡à¬¼à¬¿à¬• à¬à¬ à¬¾à¬°à­‡ ଦେଖାଯିବ</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, à¬à¬•à¬¾à¬§à¬¿à¬• କାରà­à¬¯à­à­Ÿ ଉପଲବà­à¬§ ଅଛି, ସେଗà­à¬¡à¬¼à¬¿à¬•à­ ଗୋଟିଠଗୋଟିଠକରି ଦେଖିବା ପାଇଠTab ଦବାନà­à¬¤à­</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">ବିଜà­à¬žà¬¾à¬ªà¬¨</translation>
<translation id="1919367280705858090">କୌଣସି à¬à¬• ନିରà­à¬¦à­à¬¦à¬¿à¬·à­à¬Ÿ ତà­à¬°à­à¬Ÿà¬¿ ମେସେଜୠବିଷୟରେ ସାହାଯà­à­Ÿ ପାଆନà­à¬¤à­</translation>
<translation id="192020519938775529">{COUNT,plural, =0{କୌଣସିଟି ନà­à¬¹à­‡à¬}=1{1ଟି ସାଇଟà­}other{#ଟି ସାଇଟà­}}</translation>
+<translation id="1924727005275031552">ନୂଆ</translation>
<translation id="1945968466830820669">ଆପଣ ଆପଣଙà­à¬• ସଂସà­à¬¥à¬¾à¬° ଆକାଉଣà­à¬Ÿà¬•à­ ଆକà­à¬¸à­‡à¬¸à­ ହରାଇବେ କିମà­à¬¬à¬¾ ଆପଣଙà­à¬•à¬° ବà­à­Ÿà¬•à­à¬¤à¬¿à¬—ତ ସୂଚନା ଚୋରି ହେବାର ଅନà­à¬­à¬¬ କରିପାରନà­à¬¤à¬¿à¥¤ Chromium ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ ଆପଣଙà­à¬•à¬° ପାସà­â€à­±à¬¾à¬°à­à¬¡ କୠବଦଳାଇବା ପାଇଠସà­à¬ªà¬¾à¬°à¬¿à¬¶à­ କରà­à¬›à¬¿à¥¤</translation>
<translation id="1947454675006758438">ଉପର ପଟରେ ଷà­à¬Ÿà¬¾à¬ªà¬²à­</translation>
<translation id="1958218078413065209">ଆପଣଙà­à¬•à¬° ସରà­à¬¬à¬¾à¬§à¬¿à¬• ସà­à¬•à­‹à¬°à­ ହେଉଛି <ph name="SCORE" />।</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">ଟà­à¬°à­‡ 7</translation>
<translation id="204357726431741734">ଆପଣଙà­à¬• Google ଆକାଉଣà­à¬Ÿà¬°à­‡ ସେଭୠକରାଯାଇଥିବା ପାସୱାରà­à¬¡à¬—à­à­œà¬¿à¬• ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରିବାକୠସାଇନୠଇନୠକରନà­à¬¤à­</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" />ରେ ଥିବା ପୃଷà­à¬ à¬¾à¬—à­à­œà¬¿à¬• ଅନà­à¬¬à¬¾à¬¦ କରାଯିବ ନାହିà¬à¥¤</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{à¬à¬¹à¬¿ ନିୟନà­à¬¤à­à¬°à¬£ ଚାଲୠଥିଲେ à¬à¬¬à¬‚ ସà­à¬¥à¬¿à¬¤à¬¿ ସକà­à¬°à¬¿à­Ÿ ଥିଲେ, ଆପଣଙà­à¬•à¬° ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨à¬° ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚ କାରà­à¬¯à­à­Ÿà¬•à¬³à¬¾à¬ª ଲୋକମାନଙà­à¬•à¬° କେଉଠବଡ଼ ଗୋଷà­à¬ à­€ କିମà­à¬¬à¬¾ "ଦଳ" ସହ ସବà­à¬ à¬¾à¬°à­ ଅଧିକ ସମାନ ଅଟେ ତାହା Chrome ନିରà­à¬¦à­à¬§à¬¾à¬°à¬£ କରେ। ବିଜà­à¬žà¬¾à¬ªà¬¨à¬¦à¬¾à¬¤à¬¾à¬®à¬¾à¬¨à­‡ ଗୋଷà­à¬ à­€ ପାଇଠବିଜà­à¬žà¬¾à¬ªà¬¨à¬—à­à­œà¬¿à¬• ବାଛିପାରିବେ à¬à¬¬à¬‚ ଆପଣଙà­à¬• ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚ କାରà­à¬¯à­à­Ÿà¬•à¬³à¬¾à¬ª ଆପଣଙà­à¬• ଡିଭାଇସରେ ବà­à­Ÿà¬•à­à¬¤à¬¿à¬—ତ ରଖାଯାà¬à¥¤ ଆପଣଙà­à¬• ଗୋଷà­à¬ à­€à¬•à­ ପà­à¬°à¬¤à¬¿à¬¦à¬¿à¬¨ ଅପଡେଟୠକରାଯାà¬à¥¤}=1{à¬à¬¹à¬¿ ନିୟନà­à¬¤à­à¬°à¬£ ଚାଲୠଥିଲେ à¬à¬¬à¬‚ ସà­à¬¥à¬¿à¬¤à¬¿ ସକà­à¬°à¬¿à­Ÿ ଥିଲେ, ଆପଣଙà­à¬•à¬° ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨à¬° ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚ କାରà­à¬¯à­à­Ÿà¬•à¬³à¬¾à¬ª ଲୋକମାନଙà­à¬•à¬° କେଉଠବଡ଼ ଗୋଷà­à¬ à­€ କିମà­à¬¬à¬¾ "ଦଳ" ସହ ସବà­à¬ à¬¾à¬°à­ ଅଧିକ ସମାନ ଅଟେ ତାହା Chrome ନିରà­à¬¦à­à¬§à¬¾à¬°à¬£ କରେ। ବିଜà­à¬žà¬¾à¬ªà¬¨à¬¦à¬¾à¬¤à¬¾à¬®à¬¾à¬¨à­‡ ଗୋଷà­à¬ à­€ ପାଇଠବିଜà­à¬žà¬¾à¬ªà¬¨à¬—à­à­œà¬¿à¬• ବାଛିପାରିବେ à¬à¬¬à¬‚ ଆପଣଙà­à¬• ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚ କାରà­à¬¯à­à­Ÿà¬•à¬³à¬¾à¬ª ଆପଣଙà­à¬• ଡିଭାଇସରେ ବà­à­Ÿà¬•à­à¬¤à¬¿à¬—ତ ରଖାଯାà¬à¥¤ ଆପଣଙà­à¬• ଗୋଷà­à¬ à­€à¬•à­ ପà­à¬°à¬¤à¬¿à¬¦à¬¿à¬¨ ଅପଡେଟୠକରାଯାà¬à¥¤}other{à¬à¬¹à¬¿ ନିୟନà­à¬¤à­à¬°à¬£ ଚାଲୠଥିଲେ à¬à¬¬à¬‚ ସà­à¬¥à¬¿à¬¤à¬¿ ସକà­à¬°à¬¿à­Ÿ ଥିଲେ, ଆପଣଙà­à¬•à¬° ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨à¬° ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚ କାରà­à¬¯à­à­Ÿà¬•à¬³à¬¾à¬ª ଲୋକମାନଙà­à¬•à¬° କେଉଠବଡ଼ ଗୋଷà­à¬ à­€ କିମà­à¬¬à¬¾ "ଦଳ" ସହ ସବà­à¬ à¬¾à¬°à­ ଅଧିକ ସମାନ ଅଟେ ତାହା Chrome ନିରà­à¬¦à­à¬§à¬¾à¬°à¬£ କରେ। ବିଜà­à¬žà¬¾à¬ªà¬¨à¬¦à¬¾à¬¤à¬¾à¬®à¬¾à¬¨à­‡ ଗୋଷà­à¬ à­€ ପାଇଠବିଜà­à¬žà¬¾à¬ªà¬¨à¬—à­à­œà¬¿à¬• ବାଛିପାରିବେ à¬à¬¬à¬‚ ଆପଣଙà­à¬• ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚ କାରà­à¬¯à­à­Ÿà¬•à¬³à¬¾à¬ª ଆପଣଙà­à¬• ଡିଭାଇସରେ ବà­à­Ÿà¬•à­à¬¤à¬¿à¬—ତ ରଖାଯାà¬à¥¤ ଆପଣଙà­à¬• ଗୋଷà­à¬ à­€à¬•à­ ପà­à¬°à¬¤à¬¿ {NUM_DAYS} ଦିନରେ ଅପଡେଟୠକରାଯାà¬à¥¤}}</translation>
<translation id="2053553514270667976">ZIP କୋଡà­</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1ଟି ପରାମରà­à¬¶}other{#ଟି ପରାମରà­à¬¶}}</translation>
<translation id="2071692954027939183">ଆପଣ ସାଧାରଣତଃ ବିଜà­à¬žà¬ªà­à¬¤à¬¿à¬—à­à­œà¬¿à¬•à­ ଅନà­à¬®à¬¤à¬¿ ଦେଉନଥିବା ଯୋଗà­à¬ ସେଗà­à­œà¬¿à¬•à­ ସà­à­±à¬šà¬¾à¬³à¬¿à¬¤ ଭାବରେ ବà­à¬²à¬•à­ କରାଯାଇଛି</translation>
<translation id="2079545284768500474">ପୂରà­à¬¬à¬¬à¬¤à­</translation>
<translation id="20817612488360358">ସିଷà­à¬Ÿà¬®à­ ପà­à¬°à¬•à­à¬¸à¬¿ ସେଟିଂସୠବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରିବା ପାଇଠପà­à¬°à¬¸à­à¬¤à­à¬¤ ଅଛି କିନà­à¬¤à­ à¬à¬• ସà­à¬¨à¬¿à¬°à­à¬¦à­à¬¦à¬¿à¬·à­à¬Ÿ ପà­à¬°à¬•à­à¬¸à¬¿ କନà­â€Œà¬«à¬¿à¬—à­â€Œà¬°à­‡à¬¸à¬¨à­ ମଧà­à­Ÿ ନିରà­à¬¦à­à¬¦à¬¿à¬·à­à¬Ÿ କରାଯାଇଛି।</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" />ର <ph name="RESULT_NUMBER" />ଟି ଫଳାଫଳ</translation>
+<translation id="2085876078937250610">ସେଭୠକରନà­à¬¤à­â€¦</translation>
<translation id="2088086323192747268">'ସିଙà­à¬•à­ ପରିଚାଳନା କରନà­à¬¤à­' ବଟନà­, Chrome ସେଟିଂସରେ ଆପଣ କେଉଠସୂଚନା ସିଙà­à¬•à­ କରନà­à¬¤à¬¿ ତାହା ପରିଚାଳନା କରିବାକୠEnter ଦବାନà­à¬¤à­</translation>
<translation id="2091887806945687916">ଧà­à­±à¬¨à¬¿</translation>
<translation id="2094505752054353250">ଡୋମେନୠମେଳ ଖାଉ ନାହିà¬</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> à¬à¬• ଉପଯୋଗକରà­à¬¤à­à¬¤à¬¾ ନାମ ଓ ପାସà­â€à­±à¬°à­à¬¡ ଆବଶà­à­Ÿà¬• କରେ।</translation>
<translation id="2330137317877982892"><ph name="EXPIRATION_DATE_ABBR" />ରେ <ph name="CREDIT_CARD" />ର ମିଆଦ ସମାପà­à¬¤ ହେଉଛି</translation>
<translation id="2337852623177822836">ଆପଣଙà­à¬•à¬° ବà­à­Ÿà¬¬à¬¸à­à¬¥à¬¾à¬ªà¬•à¬™à­à¬• ଦà­à¬¬à¬¾à¬°à¬¾ ସେଟିଂ ନିୟନà­à¬¤à­à¬°à¬£ କରାଯାଇଛି</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ପେୟାରୠକରିବାକୠଚାହà­à¬à¬›à¬¿</translation>
<translation id="2344028582131185878">ସà­à­±à¬šà¬¾à¬³à¬¿à¬¤ ଡାଉନà­â€Œà¬²à­‹à¬¡à­â€Œà¬—à­à­œà¬¿à¬•</translation>
<translation id="2346319942568447007">ଆପଣ ଯେଉଠଛବି କପି କରିଥିଲେ</translation>
<translation id="2354001756790975382">ଅନà­à­Ÿ ବà­à¬•à¬®à¬¾à¬°à­à¬•à¬¸à­</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">ଆପଣ à¬à¬¹à¬¿ ସାଇଟà­â€Œà¬°à­‡ ଦେଖà­à¬¥à¬¿à¬¬à¬¾ ଛବିଗà­à­œà¬¿à¬•à­ ଆକà­à¬°à¬®à¬£à¬•à¬¾à¬°à­€ ଦେଖିବାରେ ସକà­à¬·à¬® ହୋâ€à¬‡à¬ªà¬¾à¬°à­‡ à¬à¬¬à¬‚ ସେଗà­à­œà¬¿à¬•à­ ସଂଶୋଧନ କରି ଆପଣଙà­à¬• ସହିତ ଛଳନା କରିପାରେ।</translation>
<translation id="2356070529366658676">ପଚାରନà­à¬¤à­</translation>
<translation id="2357481397660644965">ଆପଣଙà­à¬•à¬° ଡିଭାଇସୠ<ph name="DEVICE_MANAGER" /> ଦà­à­±à¬¾à¬°à¬¾ ପରିଚାଳିତ ହେଉଛି à¬à¬¬à¬‚ ଆପଣଙà­à¬•à¬° ଆକାଉଣà­à¬Ÿ <ph name="ACCOUNT_MANAGER" /> ଦà­à­±à¬¾à¬°à¬¾ ପରିଚାଳିତ ହେଉଛି।</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ଗୋଟିଠଦିନରୠକମୠସମୟରେ}=1{ଗୋଟିଠଦିନରେ}other{{NUM_DAYS} ଦିନରେ}}</translation>
<translation id="2359629602545592467">à¬à¬•à¬¾à¬§à¬¿à¬•</translation>
<translation id="2359808026110333948">ଜାରି ରଖନà­à¬¤à­</translation>
+<translation id="2359961752320758691">ଆପଣଙà­à¬• ଭରà­à¬šà­à¬†à¬²à­ କାରà­à¬¡ ନମà­à¬¬à¬° ଲାଗୠକରାଯାଇଛି।</translation>
<translation id="2367567093518048410">ସà­à¬¤à¬°</translation>
<translation id="2372464001869762664">ଆପଣ ସà­à¬¨à¬¿à¬¶à­à¬šà¬¿à¬¤ କରିବା ପରେ, ଆପଣଙà­à¬• Google ଆକାଉଣà­à¬Ÿà¬°à­ କାରà­à¬¡ ବିବରଣୀ à¬à¬¹à¬¿ ସାଇଟୠସହ ସେୟାରୠକରାଯିବ। ଆପଣଙà­à¬• Plex ଆକାଉଣà­à¬Ÿ ବିବରଣୀରେ CVC ଖୋଜନà­à¬¤à­à¥¤</translation>
<translation id="2380886658946992094">ଆଇନ</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">ପଠାଇବାର à¬à¬¹à¬¿ ପଦà­à¬§à¬¤à¬¿ ଉପଲବà­à¬§ ନାହିà¬à¥¤ ଅନà­à­Ÿ à¬à¬• ପଦà­à¬§à¬¤à¬¿ ଚେଷà­à¬Ÿà¬¾ କରନà­à¬¤à­à¥¤</translation>
<translation id="2396249848217231973">&amp;ଡିଲିଟà­â€Œà¬•à­ ପୂରà­à¬¬à¬¬à¬¤à­ କରନà­à¬¤à­</translation>
<translation id="2410754574180102685">ସରକାରୀ-ଆଇନ</translation>
+<translation id="2413155254802890957">ପà­à¬°à­à¬£à¬¾</translation>
<translation id="2413528052993050574">à¬à¬¹à¬¿ ସରà­à¬­à¬°à­ à¬à¬¹à¬¾ ପà­à¬°à¬®à¬¾à¬£ କରିପାରିଲା ନାହିଠଯେ, à¬à¬¹à¬¾ à¬à¬• <ph name="DOMAIN" /> ଅଟେ; à¬à¬¹à¬¾à¬° ସà­à¬°à¬•à­à¬·à¬¾ ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­ ପà­à¬°à¬¤à­à­Ÿà¬¾à¬¹à¬¾à¬° କରାଯାଇଥାଇପାରେ। à¬à¬¹à¬¾ à¬à¬• ଭà­à¬²à­ କନଫିଗà­â€à¬°à­‡à¬¸à¬¨à­ କିମà­à¬¬à¬¾ ଜଣେ ଆକà­à¬°à¬®à¬£à¬•à¬¾à¬°à­€ ଆପଣଙà­à¬•à¬° ସଂଯୋଗକୠପà­à¬°à¬¤à¬¿à¬°à­‹à¬§ କରà­à¬¥à¬¿à¬¬à¬¾ କାରଣରୠହୋଇପାରେ।</translation>
<translation id="2414886740292270097">ଗାà­</translation>
<translation id="2438874542388153331">ଡାହାଣ ପଟରେ ଚାରୋଟି ପଞà­à¬šà­</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">ତଳ ଡାହାଣ ପଟରେ ଷà­à¬Ÿà¬¾à¬ªà¬²à­</translation>
<translation id="2523886232349826891">କେବଳ à¬à¬¹à¬¿ ଡିଭାଇସà­â€à¬°à­‡ ସେଭୠକରାଯାଇଛି</translation>
<translation id="2524461107774643265">ଅଧିକ ସୂଚନା ଯୋଗ କରନà­à¬¤à­</translation>
-<translation id="2526590354069164005">ଡେସà­à¬•à¬Ÿà¬ªà­</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{à¬à¬¬à¬‚ ଅଧିକ 1ଟି}other{à¬à¬¬à¬‚ ଅଧିକ #ଟି}}</translation>
<translation id="2536110899380797252">ଠିକଣା ଯୋଗ କରନà­à¬¤à­</translation>
<translation id="2539524384386349900">ଚିହà­à¬¨à¬Ÿ କରନà­à¬¤à­</translation>
+<translation id="2541219929084442027">ଆପଣଙà­à¬•à¬° ସମସà­à¬¤ ଇନକଗà­à¬¨à¬¿à¬Ÿà­‹ ଟାବକୠଆପଣ ବନà­à¬¦ କରିଦେବା ପରେ, ଇନକଗà­à¬¨à¬¿à¬Ÿà­‹ ଟାବରେ ଆପଣ ଦେଖà­à¬¥à¬¿à¬¬à¬¾ ପୃଷà­à¬ à¬¾à¬—à­à¬¡à¬¼à¬¿à¬• ଆପଣଙà­à¬• ବà­à¬°à¬¾à¬‰à¬œà¬°à¬° ଇତିହାସ, କà­à¬•à­€ ଷà­à¬Ÿà­‹à¬°à­ କିମà­à¬¬à¬¾ ସନà­à¬§à¬¾à¬¨ ଇତିହାସରେ ରହିବ ନାହିà¬à¥¤ ଆପଣ ଡାଉନଲୋଡୠକରିଥିବା ଯେ କୌଣସି ଫାଇଲୠକିମà­à¬¬à¬¾ ତିଆରି କରିଥିବା ବà­à¬•à¬®à¬¾à¬°à­à¬•à¬—à­à¬¡à¬¼à¬¿à¬•à­ ରଖାଯିବ।</translation>
<translation id="2544644783021658368">ଗୋଟିଠଡକà­à­Ÿà­à¬®à­‡à¬£à­à¬Ÿ</translation>
<translation id="254947805923345898">ନୀତିର ମୂଲà­à­Ÿ ବୈଧ ନà­à¬¹à­‡à¬à¥¤</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> à¬à¬• ଅବୈଧ ପà­à¬°à¬¤à¬¿à¬•à­à¬°à¬¿à­Ÿà¬¾ ପଠାଇଲା।</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">Chromeର ସରà­à¬¬à­‹à¬šà­à¬š ସà­à¬¤à¬°à¬° ସà­à¬°à¬•à­à¬·à¬¾ ପାଇବାକà­, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ଉନà­à¬¨à¬¤ ସà­à¬°à¬•à­à¬·à¬¾ ଚାଲୠକରନà­à¬¤à­<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" />ର ସରà­à¬­à¬°à­ IP ଠିକଣା ମିଳିଲା ନାହିà¬à¥¤</translation>
<translation id="2639739919103226564">ସà­à¬¥à¬¿à¬¤à¬¿:</translation>
+<translation id="264810637653812429">କୌଣସି ସମତà­à¬²à­à­Ÿ ଡିଭାଇସୠମିଳିଲା ନାହିà¬à¥¤</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ସେଟିଂସରେ ଆପଣଙà­à¬• ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚ ଇତିହାସ, କà­à¬•à­€, କà­à­Ÿà¬¾à¬¶à­ à¬à¬¬à¬‚ ଆହà­à¬°à¬¿ ଅନେକ କିଛି ଖାଲି କରିବାକୠTab କରି Enter ଦବାନà­à¬¤à­</translation>
<translation id="2650446666397867134">ଫାଇଲà­â€Œà¬Ÿà¬¿à¬•à­ ଆକà­â€Œà¬¸à­‡à¬¸à­ ଦେବାକୠମନା କରି ଦିଆଯାଇଥିଲା</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">ପà­à¬£à¬¿ ଲଞà­à¬š କରନà­à¬¤à­</translation>
<translation id="2803306138276472711">Google ନିରାପଦ ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚, ନିକଟରେ <ph name="SITE" />ରେ <ph name="BEGIN_LINK" />ମାଲà­â€Œà­±à­‡à¬°à­ ଚିହà­à¬¨à¬Ÿ କରିଛି<ph name="END_LINK" />। ସାଧାରଣତଃ ସà­à¬°à¬•à­à¬·à¬¿à¬¤ ରହà­à¬¥à¬¿à¬¬à¬¾ ୱେବà­â€Œà¬¸à¬¾à¬‡à¬Ÿà­â€Œà¬—à­à¬¡à¬¼à¬¿à¬• ବେଳେବେଳେ ମାଲà­â€Œà­±à­‡à¬°à­ ଦà­à­±à¬¾à¬°à¬¾ ସଂକà­à¬°à¬®à¬¿à¬¤ ହୋଇଥାନà­à¬¤à¬¿à¥¤</translation>
<translation id="2807052079800581569">ଛବିର Y ସà­à¬¥à¬¾à¬¨</translation>
+<translation id="2820957248982571256">ସà­à¬•à¬¾à¬¨à­â€Œ କରà­à¬›à¬¿...</translation>
<translation id="2824775600643448204">ଠିକଣା à¬à¬¬à¬‚ ସନà­à¬§à¬¾à¬¨ ବାରà­</translation>
<translation id="2826760142808435982">ମà­à¬–à­à­Ÿ ଅଦଳ ବଦଳ କୌଶଳ <ph name="CIPHER" />ର ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରି à¬à¬¬à¬‚ <ph name="KX" />ର ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରି ସଂଯୋଗକୠà¬à¬¨à­â€Œà¬•à­à¬°à¬¾à¬‡à¬ªà­à¬Ÿ କରାଯାଇଛି à¬à¬¬à¬‚ ପà­à¬°à¬®à¬¾à¬£à¬¿à¬•à¬°à¬£ କରାଯାଇଛି।</translation>
<translation id="2835170189407361413">ଫରà­à¬® ଖାଲି କରନà­à¬¤à­</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">ନିମନà­à¬¤à­à¬°à¬£ କରନà­à¬¤à­ (à¬à¬¨à¬­à¬²à¬ªà­)</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="2859806420264540918">à¬à¬¹à¬¿ ସାଇଟୠଅନଧିକାର ପà­à¬°à¬¬à­‡à¬¶ କରିଥିବା କିମà­à¬¬à¬¾ ବିଭà­à¬°à¬¾à¬¨à­à¬¤à¬¿à¬•à¬° ବିଜà­à¬žà¬¾à¬ªà¬¨ ପà­à¬°à¬¦à¬°à­à¬¶à¬¨ କରà­à¬›à¬¿à¥¤</translation>
+<translation id="287596039013813457">ବନà­à¬§à­à¬¤à­à¬µà¬ªà­‚ରà­à¬£à­à¬£</translation>
+<translation id="2876489322757410363">à¬à¬• à¬à¬•à­à¬¸à¬Ÿà¬°à­à¬¨à¬²à­ ଆପà­à¬²à¬¿à¬•à­‡à¬¸à¬¨à­ ମାଧà­à­Ÿà¬®à¬°à­‡ ପେମେଣà­à¬Ÿ କରିବାକୠଇନକଗà­à¬¨à¬¿à¬Ÿà­‹ ମୋଡରୠବାହାରି ଯାଉଛନà­à¬¤à¬¿à¥¤ ଜାରି ରଖିବେ?</translation>
<translation id="2878197950673342043">ପୋଷà­à¬Ÿà¬°à­ ଫୋଲà­à¬¡</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ୱିଣà­à¬¡à­‹ ପà­à¬²à­‡à¬¸à¬®à­‡à¬£à­à¬Ÿ</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">C9 (à¬à¬¨à¬­à¬²à¬ªà­)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ସେଟିଂସରେ ସà­à¬°à¬•à­à¬·à¬¾ ଯାଞà­à¬š ଚଲାଇବାକୠTab କରି Enter କୀ'କୠଦବାନà­à¬¤à­</translation>
<translation id="3061707000357573562">ପà­à­Ÿà¬¾à¬šà­ ସେବା</translation>
-<translation id="3064966200440839136">à¬à¬• à¬à¬•à­à¬¸à¬Ÿà¬°à­à¬¨à¬²à­â€Œ ଆପà­à¬²à¬¿à¬•à­‡à¬¸à¬¨à­â€Œ ମାଧà­à­Ÿà¬®à¬°à­‡ ଦେୟ ଦେବାକୠଇନà­â€Œà¬•à¬—à­à¬¨à¬¿à¬Ÿà­‹ ମୋଡà­â€Œ ଛାଡà­à¬›à¬¨à­à¬¤à¬¿à¥¤ ଜାରି ରଖିବେ?</translation>
<translation id="306573536155379004">ଗେମୠଆରମà­à¬­ ହୋଇଛି।</translation>
<translation id="3080254622891793721">ଗà­à¬°à¬¾à¬«à¬¿à¬•à­</translation>
<translation id="3086579638707268289">ୱେବà­â€â€à¬°à­‡ ଆପଣଙà­à¬•à¬° କାରà­à¬¯à­à­Ÿà¬•à¬³à¬¾à¬ªà¬•à­ ନିରୀକà­à¬·à¬£ କରାଯାଉଛି</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">ଆପଣଙà­à¬• ଆକାଉଣà­à¬Ÿ <ph name="MANAGER" /> ଦà­à­±à¬¾à¬°à¬¾ ପରିଚାଳିତ ହେଉଛି।</translation>
<translation id="3157931365184549694">ପà­à¬¨à¬ƒà¬¸à¬‚ରକà­à¬·à¬£ କରନà­à¬¤à­</translation>
<translation id="3162559335345991374">ଆପଣ ଯେଉଠୱାଇ-ଫାଇ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରà­à¬›à¬¨à­à¬¤à¬¿, ଆପଣଙà­à¬•à­ à¬à¬¹à¬¾à¬° ଲଗୠଇନୠପୃଷà­à¬ à¬¾à¬•à­ ଯିବାର ଆବଶà­à­Ÿà¬•à¬¤à¬¾ ହୋଇପାରେ।</translation>
-<translation id="3167968892399408617">ଆପଣ ଆପଣଙà­à¬•à¬° ସମସà­à¬¤ ଇନà­â€Œà¬•à¬—à­â€Œà¬¨à¬¿à¬Ÿà­‹ ଟାବà­â€Œâ€Œà¬—à­à¬¡à¬¼à¬¿à¬•à­ ବନà­à¬¦ କରିଦେବା ପରେ, ଇନà­â€Œà¬•à¬—à­â€Œà¬¨à¬¿à¬Ÿà­‹ ଟାବà­â€Œà¬°à­‡ ଆପଣଙà­à¬• ଦà­à­±à¬¾à¬°à¬¾ ଦେଖାଯାଇଥିବା ପୃଷà­à¬ à¬¾à¬—à­à¬¡à¬¼à¬¿à¬•, ଆପଣଙà­à¬•à¬° ବà­à¬°à¬¾à¬‰à¬œà¬°à­â€Œà¬° ଇତିବୃତà­à¬¤à¬¿, କà­à¬•à¬¿ ଷà­à¬Ÿà­‹à¬°à­ କିମà­à¬¬à¬¾ ସନà­à¬§à¬¾à¬¨ ଇତିବୃତà­à¬¤à¬¿à¬°à­‡ ରହିବ ନାହିà¬à¥¤ ଆପଣ ଡାଉନà­â€Œà¬²à­‹à¬¡à­ କରିଥିବା କୌଣସି ଫାଇଲୠକିମà­à¬¬à¬¾ ଆପଣ ତିଆରି କରିଥିବା ବà­à¬•à­â€Œà¬®à¬¾à¬°à­à¬•à¬—à­à¬¡à¬¼à¬¿à¬• ରଖାଯିବ।</translation>
<translation id="3169472444629675720">ଖୋଜି ପାଆନà­à¬¤à­</translation>
<translation id="3174168572213147020">ଦà­à­±à­€à¬ª</translation>
<translation id="3176929007561373547">ପà­à¬°à¬•à­à¬¸à¬¿ ସରà­à¬­à¬° କାରà­à¬¯à­à­Ÿà¬•à­à¬·à¬® ଥିବା ନିଶà­à¬šà¬¿à¬¤ କରିବାକୠଆପଣଙà­à¬•à¬° ପà­à¬°à¬•à­à¬¸à¬¿ ସେଟିଂସୠଯାଞà­à¬š କରନà­à¬¤à­ କିମà­à¬¬à¬¾ ନିଜର ନେଟà­â€Œà­±à¬°à­à¬• ବà­à­Ÿà¬¬à¬¸à­à¬¥à¬¾à¬ªà¬•à¬™à­à¬• ସହିତ ଯୋଗାଯୋଗ କରନà­à¬¤à­à¥¤ ଯଦି à¬à¬• ପà­à¬°à¬•à­à¬¸à¬¿ ସରà­à¬­à¬° ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରିବାକୠଆପଣ ଉଚିତୠମନେକରà­à¬¨à¬¾à¬¹à¬¾à¬¨à­à¬¤à¬¿:
@@ -591,10 +606,12 @@
<translation id="3229041911291329567">ଆପଣଙà­à¬•à¬° ଡିଭାଇସୠà¬à¬¬à¬‚ ବà­à¬°à¬¾à¬‰à¬œà¬°à­ ସଂସà­à¬•à¬°à¬£ ବିଷୟରେ ସୂଚନା</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> ପାଇଠCVC ଲେଖନà­à¬¤à­</translation>
<translation id="3234666976984236645">ସରà­à¬¬à¬¦à¬¾ à¬à¬¹à¬¿ ସାଇଟà­â€â€à¬°à­‡ ଗà­à¬°à­à¬¤à­à­±à¬ªà­‚ରà­à¬£à­à¬£ ବିଷୟବସà­à¬¤à­ ଚିହà­à¬¨à¬Ÿ କରେ</translation>
+<translation id="3249845759089040423">ଗà­à¬°à­à¬­à¬¿</translation>
<translation id="3252266817569339921">ଫà­à¬°à­‡à¬žà­à¬š</translation>
<translation id="3266793032086590337">ମୂଲà­à­Ÿ (ବିବାଦରେ ଅଛି)</translation>
<translation id="3268451620468152448">ଖୋଲାଥିବା ଟାବà­â€Œà¬—à­à¬¡à¬¼à¬¿à¬•</translation>
<translation id="3270847123878663523">ପà­à¬¨à¬ƒà¬•à­à¬°à¬®à¬•à­ &amp;ପୂରà­à¬¬à¬¬à¬¤à­ କରନà­à¬¤à­</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> ସଂଯୋଗ ହେବାକୠଚାହà­à¬à¬›à¬¿</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">ଆପଣଙà­à¬• ସଂସà­à¬¥à¬¾, <ph name="ENROLLMENT_DOMAIN" />, ନିମà­à¬¨à­‹à¬•à­à¬¤ ୱେବସାଇଟଗà­à­œà¬¿à¬•à­ ସେଟିଂସୠକିମà­à¬¬à¬¾ ନୀତିଗà­à­œà¬¿à¬• ପରି କିଛି ସୂଚନା ପଠାଇଛି।</translation>
<translation id="3282497668470633863">କାରà­à¬¡à¬°à­‡ ନାମକୠଯୋଗ କରନà­à¬¤à­</translation>
@@ -647,6 +664,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates ସରà­à¬­à¬°à­ ଟେମà­à¬ªà¬²à­‡à¬Ÿà­â€à¬° à¬à¬• କିମà­à¬¬à¬¾ à¬à¬•à¬¾à¬§à¬¿à¬• URI ଅବୈଧ ଅଟେ à¬à¬¬à¬‚ à¬à¬¹à¬¾ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରାଯିବ ନାହିà¬à¥¤</translation>
<translation id="3431636764301398940">à¬à¬¹à¬¿ ଡିଭାଇସà­â€Œà¬°à­‡ କାରà­à¬¡à¬Ÿà¬¿à¬•à­ ସେଭୠକରନà­à¬¤à­</translation>
<translation id="3432601291244612633">ପୃଷà­à¬ à¬¾à¬•à­ ବନà­à¬¦ କରନà­à¬¤à­</translation>
+<translation id="3435738964857648380">ସà­à¬°à¬•à­à¬·à¬¾</translation>
<translation id="3435896845095436175">ସକà­à¬·à¬® କରନà­à¬¤à­</translation>
<translation id="3438829137925142401">ଆପଣଙà­à¬• Google ଆକାଉଣà­à¬Ÿà¬°à­‡ ସେଭୠକରାଯାଇଥିବା ପାସୱାରà­à¬¡à¬—à­à­œà¬¿à¬• ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରନà­à¬¤à­</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -689,7 +707,10 @@
<translation id="3584299510153766161">ତଳ ପଟରେ ଦà­à¬‡à¬Ÿà¬¿ ପଞà­à¬šà­</translation>
<translation id="3586931643579894722">ବିବରଣୀଗà­à­œà¬¿à¬• ଲà­à¬šà¬¾à¬¨à­à¬¤à­</translation>
<translation id="3587738293690942763">ମଧà­à­Ÿà¬®</translation>
+<translation id="3590643883886679995">ଆପଣ ଇନକଗà­à¬¨à¬¿à¬Ÿà­‹ ମୋଡରୠବାହାରି ଯିବା ପରେ ସାଇନà­-ଇନୠଡାଟା à¬à¬¹à¬¿ ଡିଭାଇସରେ ଷà­à¬Ÿà­‹à¬°à­ କରାଯିବ।</translation>
+<translation id="359126217934908072">ମାସ/ବରà­à¬·:</translation>
<translation id="3592413004129370115">ଇଟାଲିଆନୠ(à¬à¬¨à¬­à¬²à¬ªà­)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{ଆପଣ ଯେ କୌଣସି ସମୟରେ ଆପଣଙà­à¬• ଗୋଷà­à¬ à­€ ରିସେଟୠକରିପାରିବେ। à¬à¬• ନୂଆ ଗୋଷà­à¬ à­€à¬°à­‡ ଯୋଗ ଦେବା ପାଇଠଗୋଟିଠଦିନ ସମୟ ଲାଗିଥାà¬à¥¤}=1{ଆପଣ ଯେ କୌଣସି ସମୟରେ ଆପଣଙà­à¬• ଗୋଷà­à¬ à­€ ରିସେଟୠକରିପାରିବେ। à¬à¬• ନୂଆ ଗୋଷà­à¬ à­€à¬°à­‡ ଯୋଗ ଦେବା ପାଇଠଗୋଟିଠଦିନ ସମୟ ଲାଗିଥାà¬à¥¤}other{ଆପଣ ଯେ କୌଣସି ସମୟରେ ଆପଣଙà­à¬• ଗୋଷà­à¬ à­€ ରିସେଟୠକରିପାରିବେ। à¬à¬• ନୂଆ ଗୋଷà­à¬ à­€à¬°à­‡ ଯୋଗ ଦେବା ପାଇଠ{NUM_DAYS} ଦିନ ସମୟ ଲାଗିଥାà¬à¥¤}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">ଆପଣଙà­à¬• ଆଡମିନିଷà­à¬Ÿà­à¬°à­‡à¬Ÿà¬°à¬™à­à¬• ଦà­à­±à¬¾à¬°à¬¾ ଆପà­à¬²à¬¿à¬•à­‡à¬¸à¬¨à­ ବà­à¬²à¬•à­ କରାଯାଇଛି</translation>
<translation id="3608932978122581043">ଫିଡୠଓରିà¬à¬£à­à¬Ÿà­‡à¬¸à¬¨à­</translation>
@@ -698,12 +719,12 @@
<translation id="3615877443314183785">ଗୋଟିଠବୈଧ ମିଆଦ ଶେଷ ହେଉଥିବା ତାରିଖ ଲେଖନà­à¬¤à­</translation>
<translation id="36224234498066874">ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚ ଡାଟା ଖାଲି କରନà­à¬¤à­...</translation>
<translation id="362276910939193118">ସମà­à¬ªà­‚ରà­à¬£à­à¬£ ଇତିବୃତà­à¬¤à¬¿ ଦେଖାନà­à¬¤à­</translation>
-<translation id="3625635938337243871">ଆପଣ ଇନକଗà­à¬¨à¬¿à¬Ÿà­‹ ମୋଡରୠବାହାରି ଯିବା ପରେ ସାଇନà­-ଇନୠଡାଟା à¬à¬¹à¬¿ ଡିଭାଇସରେ ଷà­à¬Ÿà­‹à¬°à­ ହୋଇଯିବ।</translation>
<translation id="3630155396527302611">ଯଦି à¬à¬¹à¬¾à¬•à­ ନେଟà­â€à­±à¬¾à¬°à­à¬•à¬•à­ ଆକà­à¬¸à­‡à¬¸à­ କରିବା ପାଇଠଅନà­à¬®à¬¤à¬¿ ଦିଆଯାଇଥିବା ଗୋଟିଠପà­à¬°à­‹à¬—à­à¬°à¬¾à¬®à­ ଭାବେ ପୂରà­à¬¬à¬°à­ ତାଲିକାଭà­à¬•à­à¬¤ କରାଯାଇଥାà¬, ତେବେ ତାଲିକାରୠà¬à¬¹à¬¾à¬•à­ କାà­à¬¿, ପୂନରà­à¬¬à¬¾à¬° ଯୋଗ କରିବା ପାଇଠଚେଷà­à¬Ÿà¬¾ କରନà­à¬¤à­à¥¤</translation>
<translation id="3630699740441428070">à¬à¬¹à¬¿ ଡିଭାଇସର ଆଡମିନିଷà­à¬Ÿà­à¬°à­‡à¬Ÿà¬°à¬®à¬¾à¬¨à­‡ ଆପଣଙà­à¬• ନେଟୱାରà­à¬• ସଂଯୋଗ କନଫିଗରୠକରିଛନà­à¬¤à¬¿, ଯାହା ଆପଣ ଭିଜିଟୠକରିଥିବା ୱେବସାଇଟଗà­à­œà¬¿à¬• ସମେତ, ଆପଣଙà­à¬• ନେଟୱାରà­à¬• ଟà­à¬°à¬¾à¬«à¬¿à¬•à¬•à­ ଦେଖିବା ପାଇଠସେମାନଙà­à¬•à­ ଅନà­à¬®à¬¤à¬¿ ଦେଇପାରେ।</translation>
<translation id="3631244953324577188">ବାୟୋମେଟà­à¬°à¬¿à¬•à­à¬¸</translation>
<translation id="3633738897356909127">"Chrome ଅପଡେଟୠକରନà­à¬¤à­" ବଟନà­, ଆପଣଙà­à¬• Chrome ସେଟିଂସରୠChrome ଅପଡେଟୠକରିବାକୠEnter ଦବାନà­à¬¤à­</translation>
<translation id="3634530185120165534">ଟà­à¬°à­‡ 5</translation>
+<translation id="3637662659967048211">Google ଆକାଉଣà­à¬Ÿà¬°à­‡ ସେଭୠକରନà­à¬¤à­</translation>
<translation id="3640766068866876100">ସୂଚୀ-4x6-Ext</translation>
<translation id="3642638418806704195">ଆପà­à¬²à¬¿à¬•à­‡à¬¸à¬¨à­:</translation>
<translation id="3650584904733503804">ବୈଧକରଣ ସଫଳ ହେଲା</translation>
@@ -744,6 +765,7 @@
<translation id="3781428340399460090">ଅତà­à­Ÿà¬§à¬¿à¬• ଗୋଲାପି</translation>
<translation id="3783418713923659662">MasterCard</translation>
<translation id="3784372983762739446">ବà­à¬²à­à¬Ÿà­à¬¥à­ ଡିଭାଇସଗà­à­œà¬¿à¬•</translation>
+<translation id="3787675388804467730">ଭରà­à¬šà­à¬†à¬²à­ କାରà­à¬¡ ନମà­à¬¬à¬°</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" />ରେ ମିଆଦ ସମାପà­à¬¤ ହେବ</translation>
<translation id="3789155188480882154">ଆକାର 16</translation>
<translation id="3789841737615482174">ସଂସà­à¬¥à¬¾à¬ªà¬¨</translation>
@@ -763,6 +785,7 @@
<translation id="3841184659773414994">ଫାଇଲୠହà­à­Ÿà¬¾à¬£à­à¬¡à¬²à¬°à¬—à­à­œà¬¿à¬•</translation>
<translation id="385051799172605136">ପଛକà­</translation>
<translation id="3858027520442213535">ତାରିଖ ଓ ସମୟ ଅପà­â€Œà¬¡à­‡à¬Ÿà­â€Œ କରନà­à¬¤à­</translation>
+<translation id="3881478300875776315">କମୠଲାଇନୠଦେଖାନà­à¬¤à­</translation>
<translation id="3884278016824448484">ପରସà­à¬ªà¬° ବିରୋଧୀ ଡିଭାଇସୠଚିହà­à¬¨à¬Ÿà¬•à¬¾à¬°à­€</translation>
<translation id="3885155851504623709">ପାରିସà­</translation>
<translation id="388632593194507180">ନିରୀକà­à¬·à¬£ କରାଯାଉଥିବା ଚିହà­à¬¨à¬Ÿ କରାଯାଇଛି</translation>
@@ -788,6 +811,7 @@
<translation id="397105322502079400">ଗଣନା କରାଯାଉଛି…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" />କୠବà­à¬²à¬•à­ କରାଯାଇଛି</translation>
<translation id="3973357910713125165">"Chrome ସà­à¬°à¬•à­à¬·à¬¾ ଯାଞà­à¬š ଚଲାନà­à¬¤à­" ବଟନà­, Chrome ସେଟିଂସରେ ସà­à¬°à¬•à­à¬·à¬¾ ଯାଞà­à¬š ଚଲାଇବାକୠEnter କୀ'କୠଦବାନà­à¬¤à­</translation>
+<translation id="3986705137476756801">ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ ପାଇଠଲାଇଭୠକà­à­Ÿà¬¾à¬ªà­à¬¸à¬¨à­ ବନà­à¬¦ କରନà­à¬¤à­</translation>
<translation id="3987405730340719549">Chrome ନିରà­à¬¦à­à¬§à¬¾à¬°à¬¿à¬¤ କରିଛି ଯେ à¬à¬¹à¬¿ ସାଇଟୠନକଲି କିମà­à¬¬à¬¾ ପà­à¬°à¬¤à¬¾à¬°à¬£à¬¾à¬®à­‚ଳକ ହୋଇପାରେ।
ଯଦି ଆପଣ ବିଶà­à­±à¬¾à¬¸ କରà­à¬›à¬¨à­à¬¤à¬¿, à¬à¬¹à¬¾ ତà­à¬°à­‚ଟିରେ ଦେଖାଯାଇଛି, ତେବେ ଦୟାକରି https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appealsକୠଯାଆନà­à¬¤à­à¥¤</translation>
@@ -879,13 +903,14 @@
<translation id="4275830172053184480">ଆପଣଙà­à¬•à¬° ଡିଭାଇସà­â€Œ ରିଷà­à¬Ÿà¬¾à¬°à­à¬Ÿ କରନà­à¬¤à­</translation>
<translation id="4277028893293644418">ପାସà­â€Œà­±à¬°à­à¬¡ ରିସେଟୠକରନà­à¬¤à­</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{à¬à¬¹à¬¿ କାରà­à¬¡ ଆପଣଙà­à¬• Google ଆକାଉଣà­à¬Ÿà¬°à­‡ ସେଭୠକରିଦିଆଯାଇଛି}other{à¬à¬¹à¬¿ କାରà­à¬¡à¬—à­à¬¡à¬¼à¬¿à¬•à­ ଆପଣଙà­à¬• Google ଆକାଉଣà­à¬Ÿà¬°à­‡ ସେଭୠକରିଦିଆଯାଇଛି}}</translation>
+<translation id="4287885627794386150">ଟà­à¬°à¬¾à¬à¬²à­ ପାଇଠଯୋଗà­à­Ÿ କିନà­à¬¤à­ ସକà­à¬°à¬¿à­Ÿ ନà­à¬¹à­‡à¬</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> ପୃଷà­à¬ à¬¾ ପାଇଠଥମà­à¬¬à¬¨à­‡à¬²à­</translation>
<translation id="42981349822642051">ପà­à¬°à¬¸à¬¾à¬°à¬£ କରନà­à¬¤à­</translation>
<translation id="4300675098767811073">ଡାହାଣ ପଟରେ à¬à¬•à¬¾à¬§à¬¿à¬• ପଞà­à¬šà­</translation>
<translation id="4302514097724775343">ଖେଳିବା ପାଇଠଡାଇନୋସରରେ ଟାପୠକରନà­à¬¤à­</translation>
<translation id="4302965934281694568">Chou3 (à¬à¬¨à¬­à¬²à¬ªà­)</translation>
<translation id="4305666528087210886">ଆପଣଙà­à¬• ଫାଇଲକୠଆକà­à¬¸à­‡à¬¸à­ କରାଯାଇପାରିଲା ନାହିà¬</translation>
-<translation id="4305817255990598646">ସà­à­±à¬¿à¬šà­ କରନà­à¬¤à­</translation>
+<translation id="4306529830550717874">ଠିକଣା ସେଭୠକରିବେ?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">ବà­à¬²à¬•à­ କରନà­à¬¤à­ (ଡିଫଲà­à¬Ÿ)</translation>
<translation id="4314815835985389558">ସିଙà­à¬• ପରିଚାଳନା କରନà­à¬¤à­</translation>
@@ -912,6 +937,7 @@
<translation id="4377125064752653719">ଆପଣ <ph name="DOMAIN" />ରେ ପହଞà­à¬šà¬¿à¬¬à¬¾à¬•à­ ଚେଷà­à¬Ÿà¬¾ କରିଥିଲେ, କିନà­à¬¤à­ ସରà­à¬­à¬°à­ ଉପସà­à¬¥à¬¾à¬ªà¬¨à¬¾ କରିଥିବା ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­, ତାହାର ଜାରିକରà­à¬¤à­à¬¤à¬¾à¬™à­à¬• ଦà­à­±à¬¾à¬°à¬¾ ପà­à¬°à¬¤à­à­Ÿà¬¾à¬–à­à­Ÿà¬¾à¬¨ କରିଦିଆଯାଇଛି। à¬à¬¹à¬¾à¬° ଅରà­à¬¥ ହେଉଛି, ସରà­à¬­à¬°à­ ଉପସà­à¬¥à¬¾à¬ªà¬¨à¬¾ କରà­à¬¥à¬¿à¬¬à¬¾ ସà­à¬°à¬•à­à¬·à¬¾ କà­à¬°à­‡à¬¡à­‡à¬¨à­â€à¬¸à¬¿à¬†à¬²à­ ଉପରେ ସମà­à¬ªà­‚ରà­à¬£à­à¬£ ଭାବେ ବିଶà­à¬µà¬¾à¬¸ କରିବା ଉଚିତ ନà­à¬¹à­‡à¬à¥¤ ଆପଣ ଜଣେ ଆକà­à¬°à¬®à¬£à¬•à¬¾à¬°à­€à¬™à­à¬• ସହ କଥା କରà­à¬¥à¬¾à¬‡à¬ªà¬¾à¬°à¬¨à­à¬¤à¬¿à¥¤</translation>
<translation id="4378154925671717803">ଫୋନà­</translation>
<translation id="4390472908992056574">ବà­à¬°à¬¿à¬®à­</translation>
+<translation id="4406883609789734330">ଲାଇଭୠକà­à­Ÿà¬¾à¬ªà¬¸à¬¨à­</translation>
<translation id="4406896451731180161">ସନà­à¬§à¬¾à¬¨ ପରିଣାମ</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" />ଟି କà­à¬•à­€</translation>
<translation id="4414290883293381923">ଆପଣ à¬à¬¬à­‡ à¬à¬• ପà­à¬°à¬¤à¬¾à¬°à¬£à¬¾à¬®à­‚ଳକ ସାଇଟରେ ଆପଣଙà­à¬•à¬° ପାସୱାରà­à¬¡ ଲେଖିଛନà­à¬¤à¬¿à¥¤ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> à¬à¬¬à¬‚ à¬à¬¹à¬¿ ପାସୱାରà­à¬¡à¬•à­ ଆପଣ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରà­à¬¥à¬¿à¬¬à¬¾ ଅନà­à­Ÿ ସାଇଟଗà­à­œà¬¿à¬•à­ ଯାଇ à¬à¬¹à¬¾à¬•à­ ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ ପରିବରà­à¬¤à­à¬¤à¬¨ କରିବା ପାଇଠChrome ସà­à¬ªà¬¾à¬°à¬¿à¬¶ କରେ।</translation>
@@ -924,7 +950,6 @@
<translation id="4435702339979719576">ପୋଷà­à¬Ÿà¬•à¬¾à¬°à­à¬¡)</translation>
<translation id="443673843213245140">à¬à¬• ପà­à¬°à­‹à¬•à­à¬¸à¬¿à¬° ବà­à­Ÿà¬¬à¬¹à¬¾à¬° ଅକà­à¬·à¬® କରାଯାଇଛି କିନà­à¬¤à­ à¬à¬• ସà­à¬¨à¬¿à¬°à­à¬¦à­à¬¦à¬¿à¬·à­à¬Ÿ ପà­à¬°à¬•à­à¬¸à¬¿ କନà­â€Œà¬«à¬¿à¬—à­â€Œà¬°à­‡à¬¸à¬¨à­ ନିରà­à¬¦à­à¬¦à¬¿à¬·à­à¬Ÿ କରାଯାଇଛି।</translation>
<translation id="4464826014807964867">ଆପଣଙà­à¬• ସଂସà­à¬¥à¬¾ ଦà­à­±à¬¾à¬°à¬¾ ପà­à¬°à¬¦à¬¾à¬¨ କରାଯାଇଥିବା ସୂଚନା ଥିବା ୱେବସାଇଟଗà­à­œà¬¿à¬•</translation>
-<translation id="4466881336512663640">ଫରà­à¬®à¬°à­‡ ହେଉଥିବା ପରିବରà­à¬¤à­à¬¤à¬¨à¬—à­à­œà¬¿à¬• ରହିବ ନାହିà¬à¥¤ ଆପଣ କ’ଣ ନିଶà­à¬šà¬¿à¬¤ ଯେ ଆପଣ ଜାରି ରଖିବାକୠଚାହà­à¬à¬›à¬¨à­à¬¤à¬¿?</translation>
<translation id="4476953670630786061">à¬à¬¹à¬¿ ଫରà­à¬® ସà­à¬°à¬•à­à¬·à¬¿à¬¤ ନà­à¬¹à­‡à¬à¥¤ ସà­à­±à¬¤à¬ƒà¬ªà­‚ରଣକୠବନà­à¬¦ କରାଯାଇଛି।</translation>
<translation id="4477350412780666475">ପରବରà­à¬¤à­à¬¤à­€ ଟà­à¬°à¬¾à¬•à­</translation>
<translation id="4482953324121162758">à¬à¬¹à¬¿ ସାଇଟà­â€Œà¬•à­ ଅନà­à¬¬à¬¾à¬¦ କରାଯିବ ନାହିà¬à¥¤</translation>
@@ -958,6 +983,7 @@
<translation id="4594403342090139922">&amp;ଡିଲିଟà­â€Œà¬•à­ ପୂରà­à¬¬à¬¬à¬¤à­ କରନà­à¬¤à­</translation>
<translation id="4597348597567598915">ଆକାର 8</translation>
<translation id="4600854749408232102">C6/C5 (à¬à¬¨à¬­à¬²à¬ªà­)</translation>
+<translation id="4606870351894164739">ପà­à¬°à¬­à¬¾à¬¬à¬¶à¬¾à¬³à­€</translation>
<translation id="4628948037717959914">ଫଟୋ</translation>
<translation id="4631649115723685955">କà­à­Ÿà¬¾à¬¸à¬¬à­à­Ÿà¬¾à¬•à­ ଲିଙà­à¬•à­ କରାଯାଇଛି</translation>
<translation id="4636930964841734540">ସୂଚନା</translation>
@@ -977,6 +1003,7 @@
<translation id="4691835149146451662">ଆରà­à¬•à¬¿à¬Ÿà­‡à¬•à­â€Œà¬šà¬°à­-A (à¬à¬¨à¬­à¬²à¬ªà­)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">ସାଇଡà­</translation>
+<translation id="4702656508969495934">ଲାଇଭୠକà­à­Ÿà¬¾à¬ªà¬¸à¬¨à­ ଦୃଶà­à­Ÿà¬®à¬¾à¬¨ ହେଉଛି, ଫୋକସୠକରିବା ପାଇଠୱିଣà­à¬¡à­‹ ସà­à­±à¬¿à¬šà¬°à­ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରନà­à¬¤à­</translation>
<translation id="4708268264240856090">ଆପଣଙà­à¬•à¬° ସଂଯୋଗରେ ବà­à­Ÿà¬¾à¬˜à¬¾à¬¤ ହୋâ€à¬‡à¬¥à¬¿à¬²à¬¾</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />ଚାଲà­à¬¥à¬¿à¬¬à¬¾ ୱିଣà­à¬¡à­‹ ନେଟà­â€Œà­±à¬°à­à¬• ଡାଇଗà­à¬¨à­‹à¬·à­à¬Ÿà¬¿à¬•à­à¬¸<ph name="END_LINK" /></translation>
@@ -990,6 +1017,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> ସନà­à¬§à¬¾à¬¨ ପà­à¬°à¬¸à­à¬¤à¬¾à¬¬</translation>
<translation id="4742407542027196863">ପାସà­â€Œà­±à¬°à­à¬¡à¬—à­à¬¡à¬¼à¬¿à¬•à­ ପରିଚାଳିତ କରନà­à¬¤à­â€¦</translation>
<translation id="4744603770635761495">à¬à¬•à­â€Œà¬œà¬¿à¬•à­à­Ÿà­à¬Ÿà­‡à¬¬à¬²à­ ପାଥà­</translation>
+<translation id="4749011317274908093">ଆପଣ ଇନକଗà­à¬¨à¬¿à¬Ÿà­‹ ମୋଡକୠଚାଲି ଯାଇଛନà­à¬¤à¬¿</translation>
<translation id="4750917950439032686">ଅପଣଙà­à¬•à¬° ସୂଚନା (ଉଦାହରଣ ସà­à­±à¬°à­‚ପ, ପାସà­â€à­±à¬°à­à¬¡ କିମà­à¬¬à¬¾ କà­à¬°à­‡à¬¡à¬¿à¬Ÿà­ କାରà­à¬¡ ନମà­à¬¬à¬°) à¬à¬¹à¬¿ ସାଇଟà­â€à¬•à­ ଯେତେବେଳେ ପଠାଯାà¬, ସେତେବେଳେ ବà­à­Ÿà¬•à­à¬¤à¬¿à¬—ତ ଥାà¬à¥¤</translation>
<translation id="4756388243121344051">&amp;ଇତିବୃତà­à¬¤à¬¿</translation>
<translation id="4758311279753947758">ଯୋଗାଯୋଗ ସୂଚନା ଯୋଗ କରନà­à¬¤à­</translation>
@@ -1019,6 +1047,8 @@
<translation id="4813512666221746211">ନେଟà­â€Œà­±à¬°à­à¬• ତà­à¬°à­à¬Ÿà¬¿</translation>
<translation id="4816492930507672669">ପୃଷà­à¬ à¬¾à¬°à­‡ ଖାପ ଖà­à¬†à¬¨à­à¬¤à­</translation>
<translation id="4819347708020428563">ଡିଫଲà­à¬Ÿ ଭà­à­Ÿà­à¬°à­‡ à¬à¬¨à­‹à¬Ÿà­‡à¬¸à¬¨à¬—à­à­œà¬¿à¬•à­ à¬à¬¡à¬¿à¬Ÿà­ କରିବେ?</translation>
+<translation id="4825507807291741242">ଶକà­à¬¤à¬¿à¬¶à¬¾à¬³à­€</translation>
+<translation id="4838327282952368871">ଡà­à¬°à¬¿à¬®à¬¿</translation>
<translation id="484462545196658690">ସà­à­±à¬¤à¬ƒ</translation>
<translation id="4850886885716139402">ଦେଖନà­à¬¤à­</translation>
<translation id="485316830061041779">ଜରà­à¬®à¬¾à¬¨à­</translation>
@@ -1155,6 +1185,7 @@
<translation id="5314967030527622926">ବà­à¬•à­â€Œà¬²à­‡à¬Ÿà­ ମାରà­à¬•à¬°à­</translation>
<translation id="5316812925700871227">ଡାହାଣରୠବାମକୠଘୂରାନà­à¬¤à­</translation>
<translation id="5317780077021120954">ସଞà­à¬šà­Ÿ</translation>
+<translation id="5321288445143113935">ବଡ଼ କରାଯାଇଛି</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> ମଧà­à­Ÿà¬°à­‡ <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">ଯୋଗାଯୋଗ ସୂଚନା ଚୟନ କରନà­à¬¤à­</translation>
<translation id="5327248766486351172">ନାମ</translation>
@@ -1162,11 +1193,13 @@
<translation id="5332219387342487447">ସିପିଂ ପଦà­à¬§à¬¤à¬¿</translation>
<translation id="5333022057423422993">ଆପଣ à¬à¬• ଡାଟା ଉଲà­à¬²à¬™à­à¬˜à¬¨à¬°à­‡ à¬à¬¬à­‡ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରିଥିବା ପାସୱାରà­à¬¡ Chromeକୠମିଳିଛି। ଆପଣଙà­à¬• ଆକାଉଣà­à¬Ÿà¬—à­à­œà¬¿à¬•à­ ସà­à¬°à¬•à­à¬·à¬¿à¬¤ ରଖିବା ପାଇà¬, ଆପଣଙà­à¬• ସେଭୠକରାଯାଇଥିବା ପାସୱାରà­à¬¡à¬—à­à­œà¬¿à¬•à­ ଯାଞà­à¬š କରିବାକୠଆମେ ସà­à¬ªà¬¾à¬°à¬¿à¬¶ କରà­à¥¤</translation>
<translation id="5334013548165032829">ବିସà­à¬¤à­ƒà¬¤ ବିବରଣୀ ସହ ସିଷà­à¬Ÿà¬®à­ ଲଗà­â€Œà¬—à­à­œà¬¿à¬•</translation>
+<translation id="5334145288572353250">ଠିକଣା ସେଭୠକରିବେ?</translation>
<translation id="5340250774223869109">ଆପà­à¬²à¬¿à¬•à­‡à¬¸à¬¨à­ ବà­à¬²à¬•à­ କରାଯାଇଛି</translation>
<translation id="534295439873310000">NFC ଡିଭାଇସà­â€Œà¬—à­à­œà¬¿à¬•</translation>
<translation id="5344579389779391559">à¬à¬¹à¬¿ ପୃଷà­à¬ à¬¾ ଆପଣଙà­à¬• ଠାରୠଶà­à¬³à­à¬• ନେବା ପାଇଠଚେଷà­à¬Ÿà¬¾ କରିପାରେ</translation>
<translation id="5355557959165512791">ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨, ଆପଣ <ph name="SITE" />କୠଯାଇପାରିବେ ନାହିଠକାରଣ à¬à¬¹à¬¾à¬° ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­â€Œ ପà­à¬°à¬¤à­à­Ÿà¬¾à¬¹à¬¾à¬° କରିନିଆଯାଇଛି। ସାଧାରଣତଃ ନେଟà­â€à­±à¬°à­à¬• ତà­à¬°à­à¬Ÿà¬¿ à¬à¬¬à¬‚ ଆକà­à¬°à¬®à¬£ ଅସà­à¬¥à¬¾à­Ÿà­€ ଅଟେ, ତେଣୠସମà­à¬­à¬¬à¬¤à¬ƒ à¬à¬¹à¬¿ ପୃଷà­à¬ à¬¾ ପରେ କାରà­à¬¯à­à­Ÿ କରିବ।</translation>
<translation id="536296301121032821">ନୀତି ସେଟିଂସୠଷà­à¬Ÿà­‹à¬°à­ କରିବାରେ ବିଫଳ ହେଲା</translation>
+<translation id="5363309033720083897">ଆପଣଙà­à¬• ଆଡମିନିଷà­à¬Ÿà­à¬°à­‡à¬Ÿà¬°à¬™à­à¬• ଦà­à­±à¬¾à¬°à¬¾ ସିରିଅଲୠପୋରà­à¬Ÿà¬•à­ ଅନà­à¬®à¬¤à¬¿ ଦିଆଯାଇଛି</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="5386426401304769735">à¬à¬¹à¬¿ ସାଇଟà­â€Œ ପାଇଠଥିବା ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­â€Œ ଶୃଙà­à¬–ଳାରେ SHA-1ର ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରି ଦସà­à¬¤à¬–ତ କରାଯାଇଥିବା ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­â€Œ ଅଛି।</translation>
@@ -1175,6 +1208,7 @@
<translation id="5398772614898833570">ବିଜà­à¬žà¬¾à¬ªà¬¨à¬—à­à­œà¬¿à¬• ଅବରୋଧ ହୋâ€à¬‡à¬›à¬¿</translation>
<translation id="5400836586163650660">ଧୂସର</translation>
<translation id="540969355065856584">à¬à¬¹à¬¿ ସରà­à¬­à¬°à­, à¬à¬¹à¬¾ <ph name="DOMAIN" /> ବୋଲି ପà­à¬°à¬®à¬¾à¬£à¬¿à¬¤ କରିପାରିଲା ନାହିà¬; à¬à¬¹à¬¿ ସମୟରେ à¬à¬¹à¬¾à¬° ସà­à¬°à¬•à­à¬·à¬¾ ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­ ବୈଧ ନà­à¬¹à­‡à¬à¥¤ à¬à¬¹à¬¾ ହà­à¬à¬¤ à¬à¬• ଭà­à¬²à­ କନଫିଗà­â€â€à¬°à­‡à¬¸à¬¨à­ କିମà­à¬¬à¬¾ ଜଣେ ଆକà­à¬°à¬®à¬£à¬•à¬¾à¬°à­€ ଆପଣଙà­à¬•à¬° ସଂଯୋଗକୠପà­à¬°à¬¤à¬¿à¬°à­‹à¬§ କରà­à¬¥à¬¿à¬¬à¬¾ କାରଣରୠହୋଇପାରେ।</translation>
+<translation id="541143247543991491">କà­à¬²à¬¾à¬‰à¬¡à­ (ସମଗà­à¬°-ସିଷà­à¬Ÿà¬®à¬°à­‡)</translation>
<translation id="541416427766103491">ଷà­à¬Ÿà¬¾à¬•à¬°à­ 4</translation>
<translation id="5421136146218899937">ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚ ଡାଟା ଖାଲି କରନà­à¬¤à­...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> ଆପଣଙà­à¬•à­ ବିଜà­à¬žà¬ªà­à¬¤à¬¿ ପଠାଇବାକୠଚାହà­à¬à¬›à¬¿</translation>
@@ -1188,6 +1222,7 @@
<translation id="5455374756549232013">ଖରାପ 'ନୀତି ଟାଇମà­â€Œà¬·à­à¬Ÿà¬¾à¬®à­à¬ªà­'</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" />ଜଣ}other{<ph name="CONTACT_PREVIEW" /> à¬à¬¬à¬‚ ଅଧିକ <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />ଜଣ}}</translation>
+<translation id="5463625433003343978">ଡିଭାଇସୠଖୋଜାଯାଉଛି…</translation>
<translation id="5469868506864199649">ଇଟାଲିୟାନà­</translation>
<translation id="5470861586879999274">&amp;ରି-ଡୠà¬à¬¡à¬¿à¬Ÿà­ କରନà­à¬¤à­</translation>
<translation id="5478437291406423475">B6/C4 (à¬à¬¨à¬­à¬²à¬ªà­)</translation>
@@ -1237,7 +1272,6 @@
<translation id="5624120631404540903">ପାସà­â€Œà­±à¬°à­à¬¡à¬—à­à¬¡à¬¼à¬¿à¬•à­ ପରିଚାଳନା କରନà­à¬¤à­</translation>
<translation id="5629630648637658800">ନୀତି ସେଟିଂସୠଲୋଡà­â€ କରିବାରେ ବିଫଳ ହେଲା</translation>
<translation id="5631439013527180824">ଅବୈଧ ଡିଭାଇସୠପରିଚାଳନା ଟୋକନà­</translation>
-<translation id="5632627355679805402">ଆପଣଙà­à¬•à¬° ଡାଟା <ph name="BEGIN_LINK" />Google ପାସà­â€Œà­±à¬°à­à¬¡<ph name="END_LINK" /> ସହିତ <ph name="TIME" />ରେ à¬à¬¨à­â€à¬•à­à¬°à¬¿à¬ªà­à¬Ÿ କରାଯାଇଥିଲା। ସିଙà­à¬•à­ ଆରମà­à¬­ କରିବାକୠà¬à¬¹à¬¾à¬•à­ ଲେଖନà­à¬¤à­à¥¤</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="5644090287519800334">ସାଇଡୠ1 ଇମେଜୠX ସିଫà­à¬Ÿ</translation>
@@ -1276,12 +1310,12 @@
<translation id="5785756445106461925">ସେ ଯାହା ହେଉ, à¬à¬¹à¬¿ ପୃଷà­à¬ à¬¾ ସେହି ଅନà­à­Ÿ ଉତà­à¬¸à¬—à­à¬¡à¬¿à¬• ଅନà­à¬¤à¬°à­à¬­à­‚କà­à¬¤ କରେ ଯେଉà¬à¬—à­à¬¡à¬¿à¬• ସà­à¬°à¬•à­à¬·à¬¿à¬¤ ନà­à¬¹à­‡à¬ । ପରିବହନରେ ଥିବାବେଳେ à¬à¬¹à¬¿ ଉତà­à¬¸à¬—à­à¬¡à¬¿à¬•à­ ଅନà­à­Ÿà¬®à¬¾à¬¨à­‡ ଦେଖିପାରିବେ, ତଥା ପୃଷà­à¬ à¬¾à¬Ÿà¬¿à¬° ରୂପ ବା ଆଚରଣ ପରିବରà­à¬¤à­à¬¤à¬¨ କରିବା ଲାଗି à¬à¬• ଆକà­à¬°à¬®à¬£à¬•à¬¾à¬°à­€à¬™à­à¬• ଦà­à¬µà¬¾à¬°à¬¾ ରୂପାନà­à¬¤à¬°à¬¿à¬¤ କରାଯାଇପାରିବ।</translation>
<translation id="5786044859038896871">ଆପଣଙà­à¬•à¬° କାରà­à¬¡ ସୂଚନାକୠଆପଣ ପà­à¬°à¬£ କରିବାକୠଚାହାନà­à¬¤à¬¿ କି?</translation>
<translation id="578633867165174378">ଆପଣ à¬à¬• ଡାଟା ଉଲà­à¬²à¬™à­à¬˜à¬¨à¬°à­‡ à¬à¬¬à­‡ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରିଥିବା ପାସୱାରà­à¬¡ Chromeକୠମିଳିଛି। à¬à¬¹à¬¿ ପାସୱାରà­à¬¡à¬•à­ ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ ପରିବରà­à¬¤à­à¬¤à¬¨ କରିବା ପାଇଠଆମେ ସà­à¬ªà¬¾à¬°à¬¿à¬¶ କରà­à¬›à­à¥¤</translation>
-<translation id="5798290721819630480">ପରିବରà­à¬¤à­à¬¤à¬¨à¬—à­à­œà¬¿à¬•à­ ଖାରଜ କରିବେ?</translation>
<translation id="5803412860119678065">ଆପଣ ନିଜର <ph name="CARD_DETAIL" />କୠପà­à¬°à¬£ କରିବାକୠଚାହାନà­à¬¤à¬¿ କି?</translation>
<translation id="5804241973901381774">ଅନà­à¬®à¬¤à¬¿à¬—à­à¬¡à¬¼à¬¿à¬•</translation>
<translation id="5804427196348435412">NFC ଡିଭାଇସà­â€Œà¬—à­à­œà¬¿à¬•à­ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରନà­à¬¤à­</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> ସହ ଆପଣଙà­à¬• ସଂଯୋଗ à¬à¬• ଅପà­à¬°à¬šà¬³à¬¿à¬¤ ସାଇଫରୠସà­à¬‡à¬Ÿà­ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରି à¬à¬¨à­â€à¬•à­à¬°à¬¿à¬ªà­à¬Ÿ କରାଯାଇଛି।</translation>
<translation id="5813119285467412249">&amp;ଯୋଗ କରିବା ପà­à¬¨à¬ƒà¬¬à¬¤à­ କରନà­à¬¤à­</translation>
+<translation id="5817918615728894473">ପେୟାରୠକରନà­à¬¤à­</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ଆପଣ ପେମେଣà­à¬Ÿ କଲେ à¬à¬¹à¬¿ କାରà­à¬¡ ଚାରà­à¬œ ହୋଇଯିବ, କିନà­à¬¤à­ à¬à¬¹à¬¾à¬° ପà­à¬°à¬•à­ƒà¬¤ ନମà­à¬¬à¬° à¬à¬¹à¬¿ ସାଇଟà­â€Œà¬°à­‡ ସେୟାରୠକରାଯିବ ନାହିà¬à¥¤ ଅତିରିକà­à¬¤ ସà­à¬°à¬•à­à¬·à¬¾ ପାଇà¬, à¬à¬• ଅସà­à¬¥à¬¾à­Ÿà­€ CVC ସୃଷà­à¬Ÿà¬¿ କରାଯିବ।}other{ଆପଣ ପେମେଣà­à¬Ÿ କଲେ ଆପଣ ବାଛିଥିବା କାରà­à¬¡ ଚାରà­à¬œ ହୋଇଯିବ, କିନà­à¬¤à­ à¬à¬¹à¬¾à¬° ପà­à¬°à¬•à­ƒà¬¤ ନମà­à¬¬à¬° à¬à¬¹à¬¿ ସାଇଟà­â€Œà¬°à­‡ ସେୟାରୠକରାଯିବ ନାହିà¬à¥¤ ଅତିରିକà­à¬¤ ସà­à¬°à¬•à­à¬·à¬¾ ପାଇà¬, à¬à¬• ଅସà­à¬¥à¬¾à­Ÿà­€ CVC ସୃଷà­à¬Ÿà¬¿ କରାଯିବ।}}</translation>
<translation id="5826507051599432481">ସାଧାରଣ ନାମ (CN)</translation>
<translation id="5838278095973806738">à¬à¬¹à¬¿ ସାଇଟà­â€Œà¬°à­‡ କୌଣସି ସମà­à¬¬à­‡à¬¦à¬¨à¬¶à­€à¬³ ସୂଚନା (ଉଦାହରଣ ସà­à­±à¬°à­‚ପ, ପାସà­â€Œà­±à¬°à­à¬¡ କିମà­à¬¬à¬¾ କà­à¬°à­‡à¬¡à¬¿à¬Ÿà­â€Œ କାରà­à¬¡) ଲେଖିବା ଉଚିତ ନà­à¬¹à­‡à¬ କାରଣ à¬à¬¹à¬¾ ଆକà­à¬°à¬®à¬£à¬•à¬¾à¬°à­€à¬®à¬¾à¬¨à¬™à­à¬• ଦà­à­±à¬¾à¬°à¬¾ ଚୋରୀ ହୋâ€à¬‡à¬¯à¬¾à¬‡à¬ªà¬¾à¬°à­‡à¥¤</translation>
@@ -1289,6 +1323,7 @@
<translation id="5855253129151731373">à¬à¬¹à¬¿ ସାଇଟà­â€à¬° ହୋଷà­à¬Ÿà¬¨à¬¾à¬® <ph name="LOOKALIKE_DOMAIN" /> ସହ ସମାନ ଥିବା ପରି ଜଣାଯାଉଛି। ଆକà­à¬°à¬®à¬£à¬•à¬¾à¬°à­€à¬®à¬¾à¬¨à­‡ ବେଳେବେଳେ ଡୋମେନୠନାମରେ ସହଜରେ ଦେଖା ଯାଉନଥିବା, ଛୋଟ ପରିବରà­à¬¤à­à¬¤à¬¨ କରି ସାଇଟà­â€à¬—à­à­œà¬¿à¬•à¬° ନକଲ କରିଥାନà­à¬¤à¬¿à¥¤
ଯଦି ଆପଣ ବିଶà­à­±à¬¾à¬¸ କରà­à¬›à¬¨à­à¬¤à¬¿, à¬à¬¹à¬¾ ତà­à¬°à­‚ଟିରେ ଦେଖାଯାଇଛି, ତେବେ ଦୟାକରି https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appealsକୠଯାଆନà­à¬¤à­à¥¤</translation>
+<translation id="5860033963881614850">ବନà­à¬¦ ଅଛି</translation>
<translation id="5862579898803147654">ଷà­à¬Ÿà¬¾à¬•à¬°à­ 8</translation>
<translation id="5863847714970149516">ଆଗରେ ଆସà­à¬¥à¬¿à¬¬à¬¾ ପୃଷà­à¬ à¬¾ ଆପଣଙà­à¬• ଠାରୠଶà­à¬³à­à¬• ନେବା ପାଇଠଚେଷà­à¬Ÿà¬¾ କରିପାରେ</translation>
<translation id="5866257070973731571">ଫୋନୠନମà­à¬¬à¬° ଯୋଗ କରନà­à¬¤à­</translation>
@@ -1305,6 +1340,7 @@
<translation id="5913377024445952699">ସà­à¬•à­à¬°à¬¿à¬¨à­ କà­à­Ÿà¬¾à¬ªà¬šà¬°à­ ବିରତ କରାଯାଇଛି</translation>
<translation id="59174027418879706">ସାମରà­à¬¥à­à­Ÿ ହୋଇଛି</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1ଟି ବà­à­Ÿà¬¬à¬¹à¬¾à¬°à¬°à­‡ ଅଛି}other{#ଟି ବà­à­Ÿà¬¬à¬¹à¬¾à¬°à¬°à­‡ ଅଛି}}</translation>
<translation id="5921185718311485855">ଚାଲୠଅଛି</translation>
<translation id="5921639886840618607">Google ଆକାଉଣà­à¬Ÿà¬°à­‡ କାରà­à¬¡ ସେଭà­â€Œ କରିବେ?</translation>
<translation id="5922853866070715753">ପà­à¬°à¬¾à­Ÿ ହୋଇଗଲାଣି!</translation>
@@ -1324,6 +1360,7 @@
<translation id="5989320800837274978">ନା ସà­à¬¥à¬¿à¬° ପà­à¬°à¬•à­à¬¸à¬¿ ସରà­à¬­à¬°à­â€Œà¬—à­à¬¡à¬¼à¬¿à¬•à­ ନା à¬à¬• .pac ସà­à¬•à­à¬°à¬¿à¬ªà­à¬Ÿ URL ନିରà­à¬¦à­à¬¦à¬¿à¬·à­à¬Ÿ କରାଯାଇଛି।</translation>
<translation id="5992691462791905444">ଇଞà­à¬œà¬¿à¬¨à¬¿à­Ÿà¬°à¬¿à¬‚ Z-ଫୋଲà­à¬¡</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' ପାଇଠ<ph name="RESULT_COUNT" />ଟି ପରିଣାମ</translation>
+<translation id="6006484371116297560">କà­à¬²à¬¾à¬¸à¬¿à¬•à­</translation>
<translation id="6008122969617370890">N-ରà­-1 ଅରà­à¬¡à¬°à­</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">ଆପଣଙà­à¬•à¬° ପାସà­â€Œà­±à¬¾à¬°à­à¬¡à­ ଯାଞà­à¬š କରନà­à¬¤à­</translation>
@@ -1345,6 +1382,7 @@
<translation id="6045164183059402045">ଇମà­à¬ªà­‹à¬œà¬¿à¬¸à¬¨à­ ଟେମà­à¬ªà¬²à­‡à¬Ÿà­</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="6049004884579590341">ପୂରà­à¬£à­à¬£ ସà­à¬•à­à¬°à¬¿à¬¨à­â€Œà¬°à­ ପà­à¬°à¬¸à­à¬¥à¬¾à¬¨ କରିବାକୠ|<ph name="ACCELERATOR" />|କୠଦବାଇ ଧରନà­à¬¤à­</translation>
<translation id="6049488691372270142">ପୃଷà­à¬ à¬¾ ଡେଲିଭେରୀ</translation>
<translation id="6051221802930200923">ଆପଣ ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ <ph name="SITE" />କୠଯାଇପାରିବେ ନାହିà¬, କାରଣ à¬à¬¹à¬¿ ୱେବà­â€Œà¬¸à¬¾à¬‡à¬Ÿà­ ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­ ପିନିଂ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରà­à¬›à¬¿à¥¤ ନେଟà­â€à­±à¬°à­à¬• ତà­à¬°à­à¬Ÿà¬¿ à¬à¬¬à¬‚ ଆକà­à¬°à¬®à¬£ ସାଧାରଣତଃ ଅସà­à¬¥à¬¾à­Ÿà­€ ଅଟେ, ତେଣୠସମà­à¬­à¬¬à¬¤à¬ƒ à¬à¬¹à¬¿ ପୃଷà­à¬ à¬¾ ପରେ କାରà­à¬¯à­à­Ÿ କରିବ।</translation>
<translation id="6051898664905071243">ପୃଷà­à¬ à¬¾ ସଂଖà­à­Ÿà¬¾:</translation>
@@ -1361,6 +1399,7 @@
<translation id="610911394827799129"><ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />ରେ ହà­à¬à¬¤ ଆପଣଙà­à¬• Google ଆକାଉଣà­à¬Ÿà¬° ଅନà­à­Ÿà¬¾à¬¨à­à­Ÿ ଧରଣର ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚ ଇତିବୃତà­à¬¤à¬¿ ଥାଇପାରେ</translation>
<translation id="6116338172782435947">କà­à¬²à¬¿à¬ªà­â€Œà¬¬à­‹à¬°à­à¬¡à¬•à­ କପି ହୋâ€à¬‡à¬¥à¬¿à¬¬à¬¾ ଟେକà­à¬¸à¬Ÿà­â€ à¬à¬¬à¬‚ ଛବିଗà­à­œà¬¿à¬•à­ ଦେଖନà­à¬¤à­</translation>
<translation id="6120179357481664955">ଆପଣଙà­à¬•à¬° UPI ID ମନେ ଅଛି?</translation>
+<translation id="6123290840358279103">ଭରà­à¬šà­à¬†à¬²à­ କାରà­à¬¡ ଦେଖନà­à¬¤à­</translation>
<translation id="6124432979022149706">Chrome à¬à¬£à­à¬Ÿà¬°à¬ªà­à¬°à¬¾à¬‡à¬œà­ କନେକà­à¬Ÿà¬°à¬—à­à­œà¬¿à¬•</translation>
<translation id="6146055958333702838">ଯେକୌଣସି କେବଲà­â€Œ ଯାଞà­à¬š କରନà­à¬¤à­ à¬à¬¬à¬‚ ଆପଣଙà­à¬• ଦà­à­±à¬¾à¬°à¬¾ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରାଯାଉଥିବା ଯେକୌଣସି ରାଉଟରà­â€Œ, ମୋଡେମà­â€ କିମà­à¬¬à¬¾ ଅନà­à­Ÿ ରାଉଟରà­â€Œ ରିବà­à¬Ÿà­â€Œ କରନà­à¬¤à­à¥¤</translation>
<translation id="614940544461990577">à¬à¬¹à¬¾à¬•à­ ପରଖନà­à¬¤à­:</translation>
@@ -1396,6 +1435,7 @@
<translation id="6289939620939689042">ପୃଷà­à¬ à¬¾à¬° ରଙà­à¬—</translation>
<translation id="6290238015253830360">ଆପଣଙà­à¬• ଦà­à­±à¬¾à¬°à¬¾ ପରାମରà­à¬¶à¬¿à¬¤ ନିବନà­à¬§à¬—à­à­œà¬¿à¬• à¬à¬ à¬¾à¬°à­‡ ଦେଖାଯାà¬</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chromeରେ Google ଆସିଷà­à¬Ÿà¬¾à¬£à­à¬Ÿ ବନà­à¬¦ କରାଯାଇଛି</translation>
<translation id="6305205051461490394"><ph name="URL" />ରେ ପହଞà­à¬šà¬¿ ହେଉନାହିà¬à¥¤</translation>
<translation id="6312113039770857350">ୱେବୠପୃଷà­à¬ à¬¾ ଉପଲବà­à¬§ ନାହିà¬</translation>
@@ -1421,6 +1461,7 @@
<translation id="6390200185239044127">ଅଧା Z-ଫୋଲà­à¬¡</translation>
<translation id="6390662030813198813">ଇଞà­à¬œà¬¿à¬¨à¬¿à­Ÿà¬°à¬¿à¬‚-E</translation>
<translation id="6393956493820063117">ଆଡମିନିଷà­à¬Ÿà­à¬°à­‡à¬Ÿà¬°à­ ନୀତି ଦà­à­±à¬¾à¬°à¬¾ <ph name="ORIGIN_NAME" />ରୠà¬à¬¹à¬¿ ଲୋକେସନକୠପେଷà­à¬Ÿ କରିବା ବà­à¬²à¬•à­ କରାଯାଇଛି</translation>
+<translation id="6398765197997659313">ପୂରà­à¬£à­à¬£ ସà­à¬•à­à¬°à¬¿à¬¨à­â€Œà¬°à­ ପà­à¬°à¬¸à­à¬¥à¬¾à¬¨ କରନà­à¬¤à­</translation>
<translation id="6401136357288658127">à¬à¬¹à¬¿ ନୀତିକୠଅଗà­à¬°à¬¾à¬¹à­à­Ÿ କରାଯାଇଛି। à¬à¬¹à¬¾ ପରିବରà­à¬¤à­à¬¤à­‡ ଆପଣ <ph name="NEW_POLICY" /> ନୀତି ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରିବା ଉଚିତ।</translation>
<translation id="6404511346730675251">ବà­à¬•à­â€à¬®à¬¾à¬°à­à¬• à¬à¬¡à¬¿à¬Ÿà­ କରନà­à¬¤à­</translation>
<translation id="6406765186087300643">C0 (à¬à¬¨à¬­à¬²à¬ªà­)</translation>
@@ -1433,7 +1474,6 @@
<translation id="6428450836711225518">ଆପଣଙà­à¬• ଫୋନୠନମà­à¬¬à¬° ଯାଞà­à¬š କରନà­à¬¤à­</translation>
<translation id="6433490469411711332">ଯୋଗାଯୋଗ ସୂଚନା à¬à¬¡à¬¿à¬Ÿà­â€ କରନà­à¬¤à­</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ସଂଯୋଗ କରିବାକୠଅସà­à­±à­€à¬•à¬¾à¬° କରିଛନà­à¬¤à¬¿à¥¤</translation>
-<translation id="6434309073475700221">ବରà­à¬œà¬¿à¬¤ କରନà­à¬¤à­</translation>
<translation id="6440503408713884761">ଅଣଦେଖା କରାଗଲା</translation>
<translation id="6443406338865242315">ଆପଣ କେଉଠà¬à¬•à­à¬¸à¬Ÿà­‡à¬¨à¬¸à¬¨à­ à¬à¬¬à¬‚ ପà­à¬²à¬—ଇନଗà­à­œà¬¿à¬• ଇନଷà­à¬Ÿà¬²à­ କରିଛନà­à¬¤à¬¿</translation>
<translation id="6446163441502663861">କାହୠ(à¬à¬¨à¬­à¬²à¬ªà­)</translation>
@@ -1476,6 +1516,7 @@
<translation id="6624427990725312378">ଯୋଗାଯୋଗ ସୂଚନା</translation>
<translation id="6626291197371920147">ବୈଧ କାରà­à¬¡à­ ନମà­à¬¬à¬° ଯୋଗ କରନà­à¬¤à­</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ସନà­à¬§à¬¾à¬¨</translation>
+<translation id="6630043285902923878">USB ଡିଭାଇସଗà­à¬¡à¬¼à¬¿à¬•à­ ଖୋଜାଯାଉଛି...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ଖାଲି କରନà­à¬¤à­</translation>
@@ -1491,6 +1532,7 @@
<translation id="6671697161687535275">Chromiumରୠପରାମରà­à¬¶à¬°à­ କାà­à¬¿ ଦେବେ?</translation>
<translation id="6685834062052613830">ସାଇନà­â€Œ ଆଉଟà­â€Œ କରନà­à¬¤à­ à¬à¬¬à¬‚ ସେଟà­â€Œà¬…ପà­â€Œ ସମà­à¬ªà­‚ରà­à¬£à­à¬£ କରନà­à¬¤à­</translation>
<translation id="6687335167692595844">ଅନà­à¬°à­‹à¬§ କରାଯାଇଥିବା ଫଣà­à¬Ÿ ଆକାର</translation>
+<translation id="6688743156324860098">ଅପଡେଟୠକରନà­à¬¤à­â€¦</translation>
<translation id="6689249931105087298">ବà­à¬²à¬¾à¬•à­ ପà¬à¬£à­à¬Ÿ କମà­à¬ªà­à¬°à­‡à¬¸à¬¨à­ ସହିତ ରିଲେଟିଭà­</translation>
<translation id="6689271823431384964">ଆପଣ ସାଇନୠଇନୠକରିଥିବା ଯୋଗà­à¬ ଆପଣଙà­à¬•à¬° Google ଆକାଉଣà­à¬Ÿà¬°à­‡ ଆପଣଙà­à¬• କାରà­à¬¡à¬—à­à­œà¬¿à¬• ସେଭୠକରିବାକୠChrome ଅଫରୠଦେଉଛି। ଆପଣ ସେଟିଂସà­â€Œà¬°à­‡ à¬à¬¹à¬¿ ଆଚରଣ ପରିବରà­à¬¤à­à¬¤à¬¨ କରିପାରିବେ। ଆପଣଙà­à¬• ଆକାଉଣà­à¬Ÿà¬°à­ କାରà­à¬¡ ଧାରକଙà­à¬• ନାମ ଆସିଛି।</translation>
<translation id="6698381487523150993">ସୃଷà­à¬Ÿà¬¿à¬¹à­‡à¬²à¬¾:</translation>
@@ -1506,6 +1548,7 @@
<translation id="6744009308914054259">ଗୋଟିଠସଂଯୋଗ ପାଇଠଅପେକà­à¬·à¬¾ କରà­à¬¥à¬¿à¬¬à¬¾ ସମୟରେ, ଅଫà­â€Œà¬²à¬¾à¬‡à¬¨à­ ଆରà­à¬Ÿà¬¿à¬•à¬²à­â€à¬—à­à¬¡à¬¿à¬•à­ ପà­à¬¿à¬¬à¬¾à¬•à­ ଆପଣ ଡାଉନà­â€Œà¬²à­‹à¬¡à­â€Œà¬—à­à­œà¬¿à¬•à­ ଯାଇପାରିବେ।</translation>
<translation id="6753269504797312559">ନୀତି ମୂଲà­à­Ÿ</translation>
<translation id="6757797048963528358">ଆପଣଙà­à¬•à¬° ଡିଭାଇସୠନିଷà­à¬•à­à¬°à¬¿à­Ÿ ହୋâ€à¬‡à¬¯à¬¾à¬‡à¬›à¬¿à¥¤</translation>
+<translation id="6767985426384634228">ଠିକଣା ଅପଡ଼େଟୠକରିବେ?</translation>
<translation id="6768213884286397650">ହାଗାକି (ପୋଷà­à¬Ÿà¬•à¬¾à¬°à­à¬¡)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ବାଇଗଣୀ</translation>
@@ -1528,6 +1571,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /><ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">à¬à¬¹à¬¿ ପୃଷà­à¬ à¬¾à¬Ÿà¬¿ ପଢ଼ିବାକୠସହଜ କରିବା ପାଇଠChrome à¬à¬¹à¬¾à¬•à­ ସରଳୀକୃତ କରିଛି। Chrome à¬à¬• ଅସà­à¬°à¬•à­à¬·à¬¿à¬¤ ସଂଯୋଗ ମାଧà­à­Ÿà¬®à¬°à­‡ ଅରିଜିନାଲ ପୃଷà­à¬ à¬¾à¬•à­ ପà­à¬¨à¬°à­à¬¦à­à¬§à¬¾à¬° କରିଛି।</translation>
<translation id="6891596781022320156">ନୀତି ସà­à¬¤à¬° ସମରà­à¬¥à¬¿à¬¤ ନà­à¬¹à­‡à¬à¥¤</translation>
+<translation id="6895143722905299846">ଭରà­à¬šà­à¬†à¬²à­ ନମà­à¬¬à¬°:</translation>
<translation id="6895330447102777224">ଆପଣଙà­à¬• କାରà­à¬¡ ସà­à¬¨à¬¿à¬¶à­à¬šà¬¿à¬¤ କରାଯାଇଛି</translation>
<translation id="6897140037006041989">ଉପଯୋଗକରà­à¬¤à­à¬¤à¬¾ à¬à¬œà­‡à¬£à­à¬Ÿ</translation>
<translation id="6898699227549475383">ସଂସà­à¬¥à¬¾ (O)</translation>
@@ -1563,10 +1607,10 @@
<translation id="7004583254764674281">କାରà­à¬¡à¬—à­à­œà¬¿à¬•à­ ଅତି ଶୀଘà­à¬° ସà­à¬¨à¬¿à¬¶à­à¬šà¬¿à¬¤ କରିବା ପାଇଠWindows Hello ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରନà­à¬¤à­</translation>
<translation id="7006930604109697472">ଯେ କୌଣସି ଭାବେ ପଠାନà­à¬¤à­</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ସେଟିଂସୠରିସାଇଜୠକରନà­à¬¤à­</translation>
<translation id="7014741021609395734">ଜà­à¬®à­ ସà­à¬¤à¬°</translation>
<translation id="7016992613359344582">à¬à¬¹à¬¿ ଶà­à¬³à­à¬•à¬—à­à­œà¬¿à¬• ଗୋଟିଠଥର କିମà­à¬¬à¬¾ ବାରମà­à¬¬à¬¾à¬° ଲାଗୠହୋâ€à¬‡à¬ªà¬¾à¬°à­‡ à¬à¬¬à¬‚ ସà­à¬ªà¬·à­à¬Ÿ ଭାବରେ ଲାଗୠହୋâ€à¬‡à¬¨à¬ªà¬¾à¬°à­‡à¥¤</translation>
<translation id="7029809446516969842">ପାସୱାରà­à¬¡à¬—à­à¬¡à¬¿à¬•</translation>
+<translation id="7030436163253143341">ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà¬Ÿà¬¿ ବୈଧ ନà­à¬¹à­‡à¬</translation>
<translation id="7031646650991750659">ଆପଣ କେଉଠGoogle Play ଆପà­à¬¸ ଇନଷà­à¬Ÿà¬²à­ କରିଛନà­à¬¤à¬¿</translation>
<translation id="7050187094878475250">ଆପଣଙ <ph name="DOMAIN" />ରେ ପହଞà­à¬šà¬¿à¬¬à¬¾à¬•à­ ପà­à¬°à­Ÿà¬¾à¬¸ କରିଛନà­à¬¤à¬¿, କିନà­à¬¤à­ ବିଶà­à¬µà¬¾à¬¸à¬¯à­‹à¬—à­à­Ÿ ହେବା ପାଇଠସରà­à¬­à¬° ଉପସà­à¬¥à¬¾à¬ªà¬¨ କରିଥିବା ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­â€Œà¬° ବୈଧତା ସମୟ ଅବଧି ଅଧିକ ଲମà­à¬¬à¬¾à¥¤</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{à¬à¬¹à¬¿ କାରà­à¬¡ ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ ସମୟରେ ସେଭୠକରାଯାଇପାରିବ ନାହିà¬}other{à¬à¬¹à¬¿ କାରà­à¬¡à¬—à­à¬¡à¬¼à¬¿à¬• ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ ସମୟରେ ସେଭୠକରାଯାଇପାରିବ ନାହିà¬}}</translation>
@@ -1636,12 +1680,14 @@
<translation id="7300012071106347854">କୋବାଲà­à¬Ÿ ନୀଳ</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">ଉଚà­à¬š</translation>
+<translation id="7305756307268530424">ଧୀର ଗତିରେ ଆରମà­à¬­ କରନà­à¬¤à­</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">ସଂଯୋଗ ସହାୟତା</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" ବିଭାଗ ଲà­à¬šà¬¾à¬¨à­à¬¤à­</translation>
<translation id="733354035281974745">ସà­à¬¥à¬¾à¬¨à­€à­Ÿ ଡିଭାଇସୠଆକାଉଣà­à¬Ÿ ଓଭରà­â€Œà¬°à¬¾à¬‡à¬¡à­</translation>
<translation id="7333654844024768166">ଆପଣ à¬à¬¬à­‡ à¬à¬• ପà­à¬°à¬¤à¬¾à¬°à¬£à¬¾à¬®à­‚ଳକ ସାଇଟରେ ଆପଣଙà­à¬•à¬° ପାସୱାରà­à¬¡ ଲେଖିଛନà­à¬¤à¬¿à¥¤ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> à¬à¬¬à¬‚ à¬à¬¹à¬¿ ପାସୱାରà­à¬¡à¬•à­ ଆପଣ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରà­à¬¥à¬¿à¬¬à¬¾ ଅନà­à­Ÿ ସାଇଟଗà­à­œà¬¿à¬•à­ ଯାଇ à¬à¬¹à¬¾à¬•à­ ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ ପରିବରà­à¬¤à­à¬¤à¬¨ କରିବା ପାଇଠChromium ସà­à¬ªà¬¾à¬°à¬¿à¬¶ କରେ।</translation>
<translation id="7334320624316649418">&amp;ରି-ଡà­à¬•à­ ପà­à¬¨à¬ƒà¬•à­à¬°à¬®à¬°à­‡ ରଖନà­à¬¤à­</translation>
+<translation id="7337248890521463931">ଅଧିକ ଲାଇନୠଦେଖାନà­à¬¤à­</translation>
<translation id="7337706099755338005">ଆପଣଙà­à¬•à¬° ପà­à¬²à¬¾à¬Ÿà­â€Œà¬«à¬°à­à¬®à¬°à­‡ ଉପଲବà­à¬§ ନାହିà¬à¥¤</translation>
<translation id="733923710415886693">ସରà­à¬­à¬°à­â€à¬° ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­, ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­ ସà­à¬µà¬šà­à¬›à¬¤à¬¾ ମାଧà­à­Ÿà¬®à¬°à­‡ ପà­à¬°à¬•à¬¾à¬¶ କରାଯାଇନାହିà¬à¥¤</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1649,6 +1695,7 @@
<translation id="7349430561505560861">A4-ଅତିରିକà­à¬¤</translation>
<translation id="7353601530677266744">କମାଣà­à¬¡ ଲାଇନà­â€Œ</translation>
<translation id="7359588939039777303">ବିଜà­à¬žà¬¾à¬ªà¬¨à¬—à­à­œà¬¿à¬• ବà­à¬²à¬•à­ କରାଯାଇଛି।</translation>
+<translation id="7363096869660964304">କିନà­à¬¤à­, ଆପଣ ଅଦୃଶà­à­Ÿ ନà­à¬¹à¬à¬¨à­à¬¤à¬¿à¥¤ ଇନକଗà­à¬¨à¬¿à¬Ÿà­‹ ମୋଡକୠବà­à­Ÿà¬¬à¬¹à¬¾à¬° କଲେ à¬à¬¹à¬¾ ଆପଣଙà­à¬•à¬° ନିଯà­à¬•à­à¬¤à¬¿à¬•à¬¾à¬°à­€, ଇଣà­à¬Ÿà¬°à¬¨à­‡à¬Ÿà­ ସେବା ପà­à¬°à¬¦à¬¾à¬¨à¬•à¬¾à¬°à­€ କିମà­à¬¬à¬¾ ଆପଣ ଭିଜିଟୠକରିଥିବା ୱେବସାଇଟଗà­à­œà¬¿à¬•à¬ à¬¾à¬°à­ ଆପଣଙà­à¬• ବà­à¬°à¬¾à¬‰à¬œà¬¿à¬‚କୠଲà­à¬šà¬¾à¬‡à¬¬ ନାହିà¬à¥¤</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ସେଟିଂସରେ ଠିକଣାଗà­à­œà¬¿à¬•à­ ଯୋଗ କରି ପରିଚାଳନା କରିବାକୠTab କରି Enter ଦବାନà­à¬¤à­</translation>
<translation id="7365849542400970216">ଆପଣଙà­à¬• ଡିଭାଇସର ବà­à­Ÿà¬¬à¬¹à¬¾à¬° ବିଷୟରେ ଜାଣିବାକୠଦେବେ କି?</translation>
<translation id="7372973238305370288">ସନà­à¬§à¬¾à¬¨ ଫଳାଫଳ</translation>
@@ -1659,7 +1706,9 @@
<translation id="7378594059915113390">ମିଡିଆକୠନିୟନà­à¬¤à­à¬°à¬£ କରà­à¬›à¬¿</translation>
<translation id="7378627244592794276">ନାହିà¬</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ପà­à¬°à¬¯à­à¬œà­à­Ÿ ନà­à¬¹à­‡à¬</translation>
<translation id="7390545607259442187">କାରà­à¬¡ ସà­à¬¨à¬¿à¬¶à­à¬šà¬¿à¬¤ କରନà­à¬¤à­</translation>
+<translation id="7392089738299859607">ଠିକଣା ଅପଡେଟୠକରନà­à¬¤à­</translation>
<translation id="7399802613464275309">ସà­à¬°à¬•à­à¬·à¬¾ ଯାଞà­à¬š</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">ଆପଣଙà­à¬•à¬° <ph name="DEVICE_NAME" />କୠପରିଚାଳନା କରାଯାà¬</translation>
@@ -1674,6 +1723,7 @@
&lt;li&gt;ଆପଣଙà­à¬•à¬° କମà­à¬ªà­à­Ÿà­à¬Ÿà¬°à­â€Œà¬°à­ ସà­à¬¥à¬¾à­Ÿà­€à¬°à­‚ପେ ସଫà­à¬Ÿà­±à­‡à¬°à­ କିପରି କାଢ଼ିବେ ତାହା ଜାଣିବାକୠ&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome ସାହାଯà­à­Ÿ କେନà­à¬¦à­à¬°&lt;/a&gt;କୠଯାଆନà­à¬¤à­
&lt;/ol&gt;</translation>
<translation id="741007362987735528">ୱାଇଡà­-ଫରà­à¬®à¬¾à¬Ÿà­</translation>
+<translation id="7410471291937727359">ଲଭଲି</translation>
<translation id="7416351320495623771">ପାସà­â€Œà­±à¬°à­à¬¡à¬—à­à¬¡à¬¼à¬¿à¬•à­ ପରିଚାଳିତ କରନà­à¬¤à­â€¦</translation>
<translation id="7419106976560586862">ପà­à¬°à­‹à¬«à¬¾à¬‡à¬²à­ ପଥ</translation>
<translation id="7437289804838430631">ଯୋଗାଯୋଗ ସୂଚନା ଯୋଗ କରନà­à¬¤à­</translation>
@@ -1689,7 +1739,7 @@
<translation id="7481312909269577407">ଅଗà­à¬°à¬—ତି</translation>
<translation id="7485870689360869515">କୌଣସି ଡାଟା ମିଳିଲା ନାହିà¬à¥¤</translation>
<translation id="7495528107193238112">à¬à¬¹à¬¿ ବିଷୟବସà­à¬¤à­à¬•à­ ବà­à¬²à¬•à­ କରାଯାଇଛି। ସମସà­à­Ÿà¬¾à¬° ସମାଧାନ କରିବାକୠସାଇଟର ମାଲିକଙà­à¬• ସହ ଯୋଗାଯୋଗ କରନà­à¬¤à­à¥¤</translation>
-<translation id="7498234416455752244">à¬à¬¡à¬¿à¬Ÿà¬¿à¬‚ ଜାରି ରଖନà­à¬¤à­</translation>
+<translation id="7498193950643227031">ଯଦି ଆକାର ପରିବରà­à¬¤à­à¬¤à¬¨ କରାଯାଠତେବେ à¬à¬¹à¬¾ ଅପà­à¬°à¬¤à­à­Ÿà¬¾à¬¶à¬¿à¬¤ ଭାବେ କାମ କରିପାରେ। ଆପଣ ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ <ph name="SETTINGS" />ରେ ଆପଗà­à¬¡à¬¼à¬¿à¬•à¬° ଆକାର ପରିବରà­à¬¤à­à¬¤à¬¨ କରିବାର କà­à¬·à¬®à¬¤à¬¾à¬•à­ ସୀମିତ କରିପାରିବେ।</translation>
<translation id="7503664977220660814">ଆପଣ à¬à¬¬à­‡ à¬à¬• ପà­à¬°à¬¤à¬¾à¬°à¬£à¬¾à¬®à­‚ଳକ ସାଇଟରେ ଆପଣଙà­à¬• ପାସୱାରà­à¬¡ ଲେଖିଛନà­à¬¤à¬¿à¥¤ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> à¬à¬¬à¬‚ ଆପଣ ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ à¬à¬¹à¬¿ ପାସୱାରà­à¬¡ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରିଥିବା ଅନà­à­Ÿ ସାଇଟଗà­à¬¡à¬¼à¬¿à¬• ପାଇଠChromium ଆପଣଙà­à¬•à¬° ସେଭୠକରାଯାଇଥିବା ପାସୱାରà­à¬¡à¬—à­à¬¡à¬¼à¬¿à¬•à­ ଯାଞà­à¬š କରିବାକୠସà­à¬ªà¬¾à¬°à¬¿à¬¶ କରେ।</translation>
<translation id="7508255263130623398">ଫେରସà­à¬¤ ନୀତି ଡିଭାଇସୠid ଖାଲି ଅଛି କିମà­à¬¬à¬¾ ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨à¬° ଡିଭାଇସୠid ସହିତ ମେଳ ହେଉନାହିà¬</translation>
<translation id="7508870219247277067">ଆଭୋକାଡୋ ସବà­à¬œ</translation>
@@ -1709,6 +1759,7 @@
<translation id="7548892272833184391">ସଂଯୋଗ ସମସà­à­Ÿà¬¾à¬—à­à¬¡à¬¼à¬¿à¬•à¬° ସମାଧାନ କରନà­à¬¤à­</translation>
<translation id="7549584377607005141">à¬à¬¹à¬¿ ୱେବà­â€à¬ªà­ƒà¬·à­à¬ à¬¾à¬•à­ ସଠିକୠଭାବରେ ପà­à¬°à¬¦à¬°à­à¬¶à¬¨ କରିବା ପାଇଠଆପଣଙà­à¬• ଦà­à­±à¬¾à¬°à¬¾ ପୂରà­à¬¬à¬°à­ ଲେଖାଯାଇଥିବା ଡାଟାର ଆବଶà­à­Ÿà¬•à¬¤à¬¾ ଅଛି। ଆପଣ à¬à¬¹à¬¿ ଡାଟା ପà­à¬£à¬¿ ପଠାଇପାରିବେ, କିନà­à¬¤à­ à¬à¬ªà¬°à¬¿ କରିବା ଦà­à­±à¬¾à¬°à¬¾ ଆପଣ à¬à¬¹à¬¿ ପୃଷà­à¬ à¬¾à¬°à­‡ ପୂରà­à¬¬à¬°à­ କରିଥିବା କୌଣସି କାରà­à¬¯à­à­Ÿà¬•à­ ପà­à¬£à¬¿ କରିପାରିବେ।</translation>
<translation id="7550637293666041147">ଆପଣଙà­à¬•à¬° ଡିଭାଇସୠଉପଯୋଗକରà­à¬¤à­à¬¤à¬¾à¬¨à¬¾à¬® à¬à¬¬à¬‚ Chrome ଉପଯୋଗକରà­à¬¤à­à¬¤à¬¾à¬¨à¬¾à¬®</translation>
+<translation id="755279583747225797">ଟà­à¬°à¬¾à¬à¬²à­ ସକà­à¬°à¬¿à­Ÿ ଅଛି</translation>
<translation id="7552846755917812628">ନିମà­à¬¨à­‹à¬•à­à¬¤ ପରାମରà­à¬¶à¬—à­à¬¡à¬¼à¬¿à¬• ଚେଷà­à¬Ÿà¬¾ କରିଦେଖନà­à¬¤à­:</translation>
<translation id="7554475479213504905">ପà­à¬£à¬¿ ଲୋଡୠକରି ଯେ କୌଣସି ମତେ ଦେଖାନà­à¬¤à­</translation>
<translation id="7554791636758816595">ନୂତନ ଟà­à­Ÿà¬¾à¬¬à­</translation>
@@ -1727,7 +1778,6 @@
<translation id="7610193165460212391">ମୂଲà­à­Ÿ <ph name="VALUE" /> ପରିସୀମା ବାହାରେ ଅଛି।</translation>
<translation id="7613889955535752492">ସମୟ ଅବଧିର ସମାପà­à¬¤à¬¿: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ଆପଣଙà­à¬• Chrome ସେଟିଂସରୠଆପଣଙà­à¬• ପାସାୱାରà­à¬¡à¬—à­à­œà¬¿à¬•à­ ଦେଖିବା à¬à¬¬à¬‚ ପରିଚାଳନା କରିବାକୠTab କରି Enter ଦବାନà­à¬¤à­</translation>
-<translation id="7615602087246926389">ଆପଣଙà­à¬• ପାଖରେ ପୂରà­à¬¬à¬°à­ ଡାଟା ଅଛି ଯାହା ଆପଣଙà­à¬•à¬° Google ଆକାଉଣà­à¬Ÿ ପାସà­â€Œà­±à¬°à­à¬¡à¬° ଭିନà­à¬¨ ସଂସà­à¬•à¬°à¬£ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରି à¬à¬¨à­â€Œà¬•à­à¬°à¬¿à¬ªà­à¬Ÿ କରାଯାଇଛି। ଦୟାକରି ନିମà­à¬¨à¬°à­‡ à¬à¬¹à¬¾à¬•à­ ଲେଖନà­à¬¤à­à¥¤</translation>
<translation id="7616645509853975347">ଆପଣଙà­à¬• ଆଡମିନିଷà­à¬Ÿà­à¬°à­‡à¬Ÿà¬°à­ ଆପଣଙà­à¬• ବà­à¬°à¬¾à¬‰à¬œà¬°à¬°à­‡ Chrome Enterprise Connectors ଚାଲୠକରିଛନà­à¬¤à¬¿à¥¤ à¬à¬¹à¬¿ କନେକà­à¬Ÿà¬°à¬—à­à­œà¬¿à¬• ପାଖରେ ଆପଣଙà­à¬•à¬° କିଛି ଡାଟାକୠଆକà­à¬¸à­‡à¬¸à­ ଅଛି।</translation>
<translation id="7619838219691048931">ଶେଷ ସିଟà­</translation>
<translation id="762844065391966283">ଥରକେ ଗୋଟିà¬</translation>
@@ -1792,13 +1842,12 @@
<translation id="782886543891417279">ଆପଣ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରà­à¬¥à¬¿à¬¬à¬¾ ୱାଇଫାଇ (<ph name="WIFI_NAME" />) ପାଇà¬, ଆପଣଙà­à¬•à­ ହà­à¬à¬¤ à¬à¬¹à¬¾à¬° ଲଗà­â€Œà¬‡à¬¨à­ ପୃଷà­à¬ à¬¾à¬•à­ ଯିବାର ଆବଶà­à­Ÿà¬•à¬¤à¬¾ ଅଛି।</translation>
<translation id="7836231406687464395">Postfix (à¬à¬¨à¬­à¬²à¬ªà­)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{କିଛିନାହିà¬}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ଫାଇଲୠପà­à¬°à¬•à¬¾à¬° ଆସୋସିà¬à¬¸à¬¨à­ ସାହାଯà­à¬¯à¬°à­‡ ଫାଇଲଗà­à­œà¬¿à¬•à­ ଖୋଲନà­à¬¤à­à¥¤</translation>
<translation id="7862185352068345852">ସାଇଟୠଛାଡ଼ିବେ?</translation>
<translation id="7865448901209910068">ଉତà­à¬¤à¬® ବେଗ</translation>
<translation id="7874263914261512992">ଆପଣ à¬à¬¬à­‡ à¬à¬• ପà­à¬°à¬¤à¬¾à¬°à¬£à¬¾à¬®à­‚ଳକ ସାଇଟରେ ଆପଣଙà­à¬• ପାସୱାରà­à¬¡ ଲେଖିଛନà­à¬¤à¬¿à¥¤ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> à¬à¬¬à¬‚ ଆପଣ ବରà­à¬¤à­à¬¤à¬®à¬¾à¬¨ à¬à¬¹à¬¿ ପାସୱାରà­à¬¡ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରିଥିବା ଅନà­à­Ÿ ସାଇଟଗà­à¬¡à¬¼à¬¿à¬• ପାଇଠChrome ଆପଣଙà­à¬•à¬° ସେଭୠକରାଯାଇଥିବା ପାସୱାରà­à¬¡à¬—à­à¬¡à¬¼à¬¿à¬•à­ ଯାଞà­à¬š କରିବାକୠସà­à¬ªà¬¾à¬°à¬¿à¬¶ କରେ।</translation>
<translation id="7878562273885520351">ଆପଣଙà­à¬•à¬° ପାସà­â€Œà­±à¬°à­à¬¡à¬°à­‡ ହେରà­â€à¬«à­‡à¬°à­â€Œ କରାଯାଇଥାଇପାରେ</translation>
+<translation id="7880146494886811634">ଠିକଣା ସେଭୠକରନà­à¬¤à­</translation>
<translation id="7882421473871500483">ବାଦାମୀ</translation>
<translation id="7887683347370398519">ଆପଣଙà­à¬•à¬° CVC ଯାଞà­à¬š କରନà­à¬¤à­ à¬à¬¬à¬‚ ପà­à¬£à¬¿ ଚେଷà­à¬Ÿà¬¾ କରନà­à¬¤à­</translation>
<translation id="7887885240995164102">ପିକଚରà­-ଇନà­-ପିକଚରୠଲେଖନà­à¬¤à­</translation>
@@ -1806,6 +1855,7 @@
<translation id="7894280532028510793">ଯଦି ବନାନ ସଠିକୠଅଛି, ତେବେ <ph name="BEGIN_LINK" />ନେଟୱାରà­à¬• ଡାà¬à¬—à­à¬¨à­‹à¬·à­à¬Ÿà¬¿à¬•à­à¬¸ ଚଲାଇବାକୠଚେଷà­à¬Ÿà¬¾ କରନà­à¬¤à­<ph name="END_LINK" />।</translation>
<translation id="7904208859782148177">C3 (à¬à¬¨à¬­à¬²à¬ªà­)</translation>
<translation id="7931318309563332511">ଅଜଣା</translation>
+<translation id="793209273132572360">ଠିକଣା ଅପଡ଼େଟୠକରିବେ?</translation>
<translation id="7932579305932748336">କୋଟà­</translation>
<translation id="79338296614623784">à¬à¬• ବୈଧ ଫୋନୠନମà­à¬µà¬°à­ ଲେଖନà­à¬¤à­</translation>
<translation id="7934052535022478634">ଦେୟ ସମà­à¬ªà­‚ରà­à¬£à­à¬£ ହୋଇଛି</translation>
@@ -1876,6 +1926,7 @@
<translation id="8175796834047840627">ଆପଣଙà­à¬•à¬° Google ଆକାଉଣà­à¬Ÿà¬°à­‡ ଆପଣଙà­à¬• କାରà­à¬¡à¬—à­à­œà¬¿à¬• ସେଭà­â€ କରିବାକୠChrome ଅଫରà­â€ ଦେଉଛି କାରଣ ଆପଣ ସାଇନà­â€ ଇନà­â€ କରିଛନà­à¬¤à¬¿à¥¤ ଆପଣ ସେଟିଂସà­â€Œà¬°à­‡ à¬à¬¹à¬¿ ଆଚରଣର ପରିବରà­à¬¤à­à¬¤à¬¨ କରିପାରିବେ।</translation>
<translation id="8176440868214972690">à¬à¬¹à¬¿ ଡିଭାଇସର ଆଡମିନିଷà­à¬Ÿà­à¬°à­‡à¬Ÿà¬°à­ ନିମà­à¬¨à­‹à¬•à­à¬¤ ୱେବସାଇଟଗà­à­œà¬¿à¬•à­ ସେଟିଂସୠକିମà­à¬¬à¬¾ ନୀତିଗà­à­œà¬¿à¬• ପରି କିଛି ସୂଚନା ପଠାଇଛନà­à¬¤à¬¿à¥¤</translation>
<translation id="8184538546369750125">ବିଶà­à­±à¬¾à¬¬à­à­Ÿà¬¾à¬ªà­€ ଡିଫଳà­à¬Ÿ ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରନà­à¬¤à­ (ଅନà­à¬®à¬¤à¬¿ ଦ)</translation>
+<translation id="8193086767630290324">ଗୋପନୀୟ ଭାବରେ ଫà­à¬²à¬¾à¬—ୠକରାଯାଇଥିବା ଡାଟା ପାଇଠନିଆଯାଇଥିବା ପଦକà­à¬·à­‡à¬ª</translation>
<translation id="8194797478851900357">&amp;ଘà­à¬žà­à¬šà¬¾à¬¨à­à¬¤à­à¬•à­ ପୂରà­à¬¬à¬¬à¬¤à­â€ କରନà­à¬¤à­</translation>
<translation id="8201077131113104583">ID "<ph name="EXTENSION_ID" />" ସହିତ à¬à¬•à­à¬¸à¬Ÿà­‡à¬¨à­â€Œà¬¸à¬¨à­ ପାଇଠଅବୈଧ ଅପà­â€Œà¬¡à­‡à¬Ÿà­ ହୋଇଥିବା URL</translation>
<translation id="8202097416529803614">ଅରà­à¬¡à¬° ସାରାଶଂ</translation>
@@ -1898,6 +1949,7 @@
<translation id="8249296373107784235">ବନà­à¬¦ କରନà­à¬¤à­</translation>
<translation id="8249320324621329438">ଶେଷଥର ପà­à¬°à¬¾à¬ªà­à¬¤ କରାଯାଇଥିବା:</translation>
<translation id="8253091569723639551">ବିଲିଂ ଠିକଣା ଆବଶà­à­Ÿà¬•</translation>
+<translation id="8257387598443225809">à¬à¬¹à¬¿ ଆପକୠମୋବାଇଲ ପାଇଠଡିଜାଇନୠକରାଯାଇଛି</translation>
<translation id="825929999321470778">ସେଭୠଥିବା ସମସà­à¬¤ ପାସà­â€Œà­±à¬°à­à¬¡ ଦେଖାନà­à¬¤à­</translation>
<translation id="8261506727792406068">ବିଲୋପ</translation>
<translation id="8262952874573525464">ତଳ ପଟରେ à¬à¬œà­ ଷà­à¬Ÿà¬¿à¬šà­</translation>
@@ -2021,7 +2073,6 @@
<translation id="8719528812645237045">ଉପର ପଟରେ à¬à¬•à¬¾à¬§à¬¿à¬• ପଞà­à¬šà­</translation>
<translation id="8725066075913043281">ପà­à¬£à¬¿ ଚେଷà­à¬Ÿà¬¾ କରନà­à¬¤à­</translation>
<translation id="8726549941689275341">ପୃଷà­à¬ à¬¾à¬° ଆକାର:</translation>
-<translation id="8728672262656704056">ଆପଣ ଇନà­â€à¬•à¬—à­à¬¨à¬¿à¬Ÿà­‹ ହୋâ€à¬‡à¬¯à¬¾à¬‡à¬›à¬¨à­à¬¤à¬¿</translation>
<translation id="8730621377337864115">ସମାପà­à¬¤ ହୋଇଛି</translation>
<translation id="8731544501227493793">"ପାସୱାରà­à¬¡à¬—à­à¬¡à¬¼à¬¿à¬•à­ ପରିଚାଳନା କରନà­à¬¤à­" ବଟନà­, Chrome ସେଟିଂସରେ ପାସୱାରà­à¬¡à¬—à­à¬¡à¬¼à¬¿à¬•à­ ଦେଖିବା à¬à¬¬à¬‚ ପରିଚାଳନା କରିବା ପାଇଠEnter ଦବାନà­à¬¤à­</translation>
<translation id="8734529307927223492">ଆପଣଙà­à¬•à¬° <ph name="DEVICE_TYPE" />, <ph name="MANAGER" /> ଦà­à¬µà¬¾à¬°à¬¾ ପରିଚାଳିତ ହେଉଛି</translation>
@@ -2098,6 +2149,7 @@
<translation id="9020542370529661692">à¬à¬¹à¬¿ ପୃଷà­à¬ à¬¾ <ph name="TARGET_LANGUAGE" />ରେ ଅନà­à¬¬à¬¾à¬¦ କରାଯାଇଛି</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ଅବୈଧ)</translation>
+<translation id="9030265603405983977">ମୋନୋକà­à¬°à­‹à¬®à­</translation>
<translation id="9035022520814077154">ସà­à¬°à¬•à­à¬·à¬¾ ତà­à¬°à­à¬Ÿà¬¿</translation>
<translation id="9038649477754266430">ପୃଷà­à¬ à¬¾à¬—à­à­œà¬¿à¬•à­ ଅଧିକ ଶୀଘà­à¬° ଲୋଡà­â€Œ କରିବାକୠà¬à¬• ପୂରà­à¬¬à¬¾à¬¨à­à¬®à¬¾à¬¨ ସେବା ବà­à­Ÿà¬¬à¬¹à¬¾à¬° କରନà­à¬¤à­</translation>
<translation id="9039213469156557790">ସେ ଯାହା ହେଉ, à¬à¬¹à¬¿ ପୃଷà­à¬ à¬¾à¬Ÿà¬¿ ସେହି ଅନà­à­Ÿ ଉତà­à¬¸à¬—à­à¬¡à¬¿à¬• ଅନà­à¬¤à¬°à­à¬­à­‚କà­à¬¤ କରେ ଯେଉà¬à¬—à­à¬¡à¬¿à¬• ସà­à¬°à¬•à­à¬·à¬¿à¬¤ ନà­à¬¹à­‡à¬à¥¤ ଗମନାଗମନ ସମୟରେ à¬à¬¹à¬¿ ଉତà­à¬¸à¬—à­à¬¡à¬¿à¬• ଅନà­à­Ÿà¬®à¬¾à¬¨à¬™à­à¬• ଦà­à¬µà¬¾à¬°à¬¾ ପରିଦୃଷà­à¬Ÿ ହୋଇ ପାରିବ, ତଥା ପୃଷà­à¬ à¬¾à¬Ÿà¬¿à¬° ରୂପ ବା ଆଚରଣ ପରିବରà­à¬¤à­à¬¤à¬¨ କରିବାକୠà¬à¬• ଆକà­à¬°à¬®à¬£à¬•à¬¾à¬°à­€à¬™à­à¬• ଦà­à¬µà¬¾à¬°à¬¾ ରୂପାନà­à¬¤à¬°à¬¿à¬¤ କରାଯାଇ ପାରିବ।</translation>
@@ -2121,6 +2173,7 @@
<translation id="91108059142052966">ଯେତେବେଳେ ଗୋପନୀୟ ବିଷୟବସà­à¬¤à­ ଦୃଶà­à­Ÿà¬®à¬¾à¬¨ ହà­à¬, ଆଡମିନିଷà­à¬Ÿà­à¬°à­‡à¬Ÿà¬°à­ ନୀତି <ph name="APPLICATION_TITLE" /> ସହିତ ସà­à¬•à­à¬°à¬¿à¬¨à­ ସେୟାରିଂକୠଅକà­à¬·à¬® କରିଥାà¬</translation>
<translation id="9114524666733003316">କାରà­à¬¡ ସà­à¬¨à¬¿à¬¶à­à¬šà¬¿à¬¤ କରାଯାଉଛି...</translation>
<translation id="9114581008513152754">à¬à¬¹à¬¿ ବà­à¬°à¬¾à¬‰à¬œà¬°à­ à¬à¬• କମà­à¬ªà¬¾à¬¨à­€ କିମà­à¬¬à¬¾ ଅନà­à­Ÿ ସଂସà­à¬¥à¬¾ ଦà­à­±à¬¾à¬°à¬¾ ପରିଚାଳିତ ହେଉନାହିà¬à¥¤ à¬à¬¹à¬¿ ଡିଭାଇସରେ କରାଯାଉଥିବା କାରà­à¬¯à­à­Ÿà¬•à¬³à¬¾à¬ªà¬•à­ Chromeର ବାହାରେ ପରିଚାଳନା କରାଯାଇପାରେ। <ph name="BEGIN_LINK" />ଅଧିକ ଜାଣନà­à¬¤à­<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ଫà­à¬°à­‡à¬¸à­</translation>
<translation id="9119042192571987207">ଅପଲୋଡୠକରାଯାଇଛି</translation>
<translation id="9128016270925453879">ନୀତିଗà­à­œà¬¿à¬• ଲୋଡୠହୋଇଛି</translation>
<translation id="9128870381267983090">ନେଟà­â€Œà­±à¬°à­à¬• ସହ ସଂଯୋଗ କରନà­à¬¤à­</translation>
@@ -2139,6 +2192,7 @@
<translation id="9170848237812810038">&amp;ପୂରà­à¬¬à¬¬à¬¤à­</translation>
<translation id="9171296965991013597">ଆପà­â€Œ ଛାଡିବେ?</translation>
<translation id="9173282814238175921">ଗୋଟିଠଡକà­à­Ÿà­à¬®à­‡à¬£à­à¬Ÿ/ନୂଆ ସିଟà­</translation>
+<translation id="9173995187295789444">ବà­à¬²à­à¬Ÿà­à¬¥à­â€ ଡିଭାଇସà­â€Œ ପାଇଠସà­à¬•à¬¾à¬¨à­ ହେଉଛି...</translation>
<translation id="917450738466192189">ସରà­à¬­à¬°à­â€à¬° ସାରà­à¬Ÿà¬¿à¬«à¬¿à¬•à­‡à¬Ÿà­ ଅବୈଧ ଅଟେ।</translation>
<translation id="9174917557437862841">ଟାବୠସà­à­±à¬¿à¬šà­ କରିବାର ବଟନà­, à¬à¬¹à¬¿ ଟାବà­â€à¬•à­ ସà­à­±à¬¿à¬šà­ କରିବା ପାଇଠà¬à¬£à­à¬Ÿà¬°à­ ଦବାନà­à¬¤à­</translation>
<translation id="9179703756951298733">Chrome ସେଟିଂସରେ ଆପଣଙà­à¬•à¬° ପେମେଣà­à¬Ÿ à¬à¬¬à¬‚ କà­à¬°à­‡à¬¡à¬¿à¬Ÿà­ କାରà­à¬¡ ସୂଚନା ପରିଚାଳନା କରନà­à¬¤à­</translation>
diff --git a/chromium/components/strings/components_strings_pa.xtb b/chromium/components/strings/components_strings_pa.xtb
index c926c8d1867..a63207ef0d9 100644
--- a/chromium/components/strings/components_strings_pa.xtb
+++ b/chromium/components/strings/components_strings_pa.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">ਜੇਕਰ ਸਹੀ ਦਾ ਨਿਸ਼ਾਨ ਲਗਾਇਆ ਹੈ, ਤਾਂ Chrome ਤੇਜ਼ੀ ਨਾਲ ਫ਼ਾਰਮ ਭਰਨ ਲਈ ਇਸ ਡੀਵਾਈਸ 'ਤੇ ਤà©à©à¨¹à¨¾à¨¡à©‡ ਕਾਰਡ ਦੀ ਇੱਕ ਕਾਪੀ ਸਟੋਰ ਕਰੇਗਾ।</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> ਲਈ ਇਜਾਜ਼ਤ ਚà©à¨£à©‹</translation>
<translation id="1113869188872983271">&amp;ਦà©à¨¬à¨¾à¨°à¨¾ ਕà©à¨°à¨® ਦੇਣ ਨੂੰ ਅਨਡੂ ਕਰੋ</translation>
+<translation id="1123753900084781868">ਲਾਈਵ ਸà©à¨°à¨–ੀਆਂ ਫ਼ਿਲਹਾਲ ਉਪਲਬਧ ਨਹੀਂ ਹਨ</translation>
<translation id="1125573121925420732">ਵੈੱਬਸਾਈਟਾਂ ਵੱਲੋਂ ਉਹਨਾਂ ਦੀ ਸà©à¨°à©±à¨–ਿਆ ਅੱਪਡੇਟ ਕਰਨ ਵੇਲੇ ਚਿਤਾਵਨੀਆਂ ਦਾ ਦਿੱਸਣਾ ਆਮ ਹੈ। ਇਹ ਜਲਦ ਹੀ ਦਿੱਸਣੀਆਂ ਬੰਦ ਹੋ ਜਾਣਗੀਆਂ।</translation>
<translation id="112840717907525620">ਨੀਤੀ ਕੈਸ਼ੇ OK</translation>
<translation id="1130564665089811311">'ਪੰਨੇ ਦਾ ਅਨà©à¨µà¨¾à¨¦ ਕਰੋ' ਬਟਨ, Google Translate ਨਾਲ ਇਸ ਪੰਨੇ ਦਾ ਅਨà©à¨µà¨¾à¨¦ ਕਰਨ ਲਈ Enter ਦਬਾਓ</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">ਤà©à¨¹à¨¾à¨¡à©‡ ਡੀਵਾਈਸ ਦਾ ਨਾਮ</translation>
<translation id="124116460088058876">ਹੋਰ ਭਾਸ਼ਾਵਾਂ</translation>
<translation id="1243027604378859286">ਲੇਖਕ:</translation>
+<translation id="1246424317317450637">ਗੂੜà©à¨¹à¨¾</translation>
<translation id="1250759482327835220">ਅਗਲੀ ਵਾਰ ਵਧੇਰੇ ਤੇਜ਼ੀ ਨਾਲ ਭà©à¨—ਤਾਨ ਕਰਨ ਲਈ, ਆਪਣੇ 'Google ਖਾਤੇ' ਵਿੱਚ ਆਪਣਾ ਕਾਰਡ, ਨਾਮ ਅਤੇ ਬਿਲਿੰਗ ਪਤਾ ਰੱਖਿਅਤ ਕਰੋ।</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (ਸਮਕਾਲੀਕਿਰਤ ਕੀਤੇ ਗà¨)</translation>
<translation id="1256368399071562588">&lt;p&gt;ਜੇਕਰ ਤà©à¨¸à©€à¨‚ ਇੱਕ ਵੈੱਬਸਾਈਟ 'ਤੇ ਜਾਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰਦੇ ਹੋ ਅਤੇ ਉਹ ਨਹੀਂ ਖà©à©±à¨²à©à¨¹à¨¦à©€, ਤਾਂ ਪਹਿਲਾਂ ਇਹਨਾਂ ਸਮੱਸਿਆ-ਨਿਪਟਾਰਾ ਪੜਾਵਾਂ ਨਾਲ ਗੜਬੜ ਠੀਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">ਆਪਣਾ ਪਾਸਵਰਡ ਬਦਲੋ</translation>
<translation id="1484290072879560759">ਸ਼ਿਪਿੰਗ ਪਤਾ ਚà©à¨£à©‹</translation>
<translation id="1492194039220927094">ਨੀਤੀਆਂ ਦਾ ਅਮਲੀਕਰਨ:</translation>
+<translation id="1495677929897281669">ਟੈਬ 'ਤੇ ਵਾਪਸ ਜਾਓ</translation>
<translation id="1501859676467574491">ਤà©à¨¹à¨¾à¨¡à©‡ Google ਖਾਤੇ ਤੋਂ ਕਾਰਡ ਦਿਖਾਓ</translation>
<translation id="1507202001669085618">&lt;p&gt;ਜੇਕਰ ਤà©à¨¸à©€à¨‚ ਵਾਈ-ਫਾਈ ਪੋਰਟਲ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੇ ਹੋ ਤਾਂ ਤà©à¨¹à¨¾à¨¨à©‚à©° ਇਹ ਗੜਬੜ ਦਿਖਾਈ ਦੇਵੇਗੀ ਜਿੱਥੇ ਤà©à¨¹à¨¾à¨¨à©‚à©° ਆਨਲਾਈਨ ਹੋਣ ਤੋਂ ਪਹਿਲਾਂ ਸਾਈਨ-ਇਨ ਕਰਨਾ ਪਵੇਗਾ।&lt;/p&gt;
&lt;p&gt;ਗੜਬੜ ਠੀਕ ਕਰਨ ਲਈ, ਜਿਸ ਪੰਨੇ ਨੂੰ ਤà©à¨¸à©€à¨‚ ਖੋਲà©à¨¹à¨£ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਹੇ ਹੋ ਉਸ 'ਤੇ &lt;strong&gt;ਕਨੈਕਟ ਕਰੋ&lt;/strong&gt; 'ਤੇ ਕਲਿੱਕ ਕਰੋ।&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">ਇਸ ਪੰਨੇ ਦੇ ਮà©à¨¤à¨¾à¨¬à¨•</translation>
<translation id="153384715582417236">ਹà©à¨£ ਲਈ ਬੱਸ ਇੰਨਾ ਹੀ</translation>
<translation id="1536390784834419204">ਪੰਨੇ ਦਾ ਅਨà©à¨µà¨¾à¨¦ ਕਰੋ</translation>
+<translation id="1539840569003678498">ਰਿਪੋਰਟ ਭੇਜੀ ਗਈ:</translation>
<translation id="154408704832528245">ਡਿਲੀਵਰੀ ਪਤਾ ਚà©à¨£à©‹</translation>
<translation id="1549470594296187301">ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਵਰਤਣ ਲਈ JavaScript ਨੂੰ ਸਮਰੱਥ ਬਣਾਇਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ।</translation>
<translation id="155039086686388498">ਇੰਜੀਨੀਅਰਿੰਗ-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">ਪਹਿਲਾਂ ਛੋਟੇ ਕਿਨਾਰੇ ਵਾਲੇ</translation>
<translation id="168693727862418163">ਇਸ ਨੀਤੀ ਮà©à©±à¨² ਨੂੰ ਇਸਦੀ ਸਕੀਮ ਨਾਲ ਪà©à¨°à¨®à¨¾à¨£à¨¿à¨¤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ ਅਤੇ ਇਸ ਨੂੰ ਅਣਡਿੱਠ ਕਰ ਦਿੱਤਾ ਜਾਵੇਗਾ।</translation>
<translation id="168841957122794586">ਸਰਵਰ ਸਰਟੀਫਿਕੇਟ ਵਿੱਚ ਇੱਕ ਕਮਜ਼ੋਰ ਕà©à¨°à¨¾à¨ˆà¨ªà¨Ÿà©‹à¨—à©à¨°à¨¾à¨«à¨¿à¨• ਕà©à©°à¨œà©€ ਹੈ।</translation>
+<translation id="1696290444144917273">ਆਭਾਸੀ ਕਾਰਡ ਸੰਬੰਧੀ ਵੇਰਵੇ ਦੇਖੋ</translation>
<translation id="1697532407822776718">ਤà©à¨¸à©€à¨‚ ਸਾਰਾ ਸੈਟ ਕਰ ਲਿਆ ਹੈ!</translation>
<translation id="1703835215927279855">ਚਿੱਠੀ</translation>
<translation id="1706954506755087368">{1,plural, =1{ਇਹ ਸਰਵਰ ਇਹ ਸਿੱਧ ਨਹੀਂ ਕਰ ਸਕਿਆ ਕਿ ਇਹ <ph name="DOMAIN" />ਹੈ; ਇਸਦਾ ਸà©à¨°à©±à¨–ਿਆ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਭਵਿੱਖ ਵਿੱਚ ਕੱਲà©à¨¹ ਤੋਂ ਅਨà©à¨®à¨¾à¨¨à¨¿à¨¤ ਤੌਰ ਤੇ ਹੈ। ਇਸ ਦਾ ਕਾਰਨ ਕੋਈ ਗਲਤ ਸੰਰੂਪਣ ਜਾਂ ਕਿਸੇ ਹਮਲਾਵਰ ਵੱਲੋਂ ਤà©à¨¹à¨¾à¨¡à©‡ ਕਨੈਕਸ਼ਨ ਨੂੰ ਰਾਹ ਵਿੱਚ ਰੋਕਣਾ ਹੋ ਸਕਦਾ ਹੈ।}one{ਇਹ ਸਰਵਰ ਇਹ ਸਿੱਧ ਨਹੀਂ ਕਰ ਸਕਿਆ ਕਿ ਇਹ <ph name="DOMAIN" /> ਹੈ; ਇਸਦਾ ਸà©à¨°à©±à¨–ਿਆ ਸਰਟੀਫਿਕੇਟ ਭਵਿੱਖ ਵਿੱਚ # ਦਿਨਾਂ ਤੋਂ ਅਨà©à¨®à¨¾à¨¨à¨¿à¨¤ ਤੌਰ ਤੇ ਹੈ। ਇਸ ਦਾ ਕਾਰਨ ਕੋਈ ਗਲਤ ਸੰਰੂਪਣ ਜਾਂ ਕਿਸੇ ਹਮਲਾਵਰ ਵੱਲੋਂ ਤà©à¨¹à¨¾à¨¡à©‡ ਕਨੈਕਸ਼ਨ ਨੂੰ ਰਾਹ ਵਿੱਚ ਰੋਕਣਾ ਹੋ ਸਕਦਾ ਹੈ।}other{ਇਹ ਸਰਵਰ ਇਹ ਸਿੱਧ ਨਹੀਂ ਕਰ ਸਕਿਆ ਕਿ ਇਹ <ph name="DOMAIN" /> ਹੈ; ਇਸਦਾ ਸà©à¨°à©±à¨–ਿਆ ਸਰਟੀਫਿਕੇਟ ਭਵਿੱਖ ਵਿੱਚ # ਦਿਨਾਂ ਤੋਂ ਅਨà©à¨®à¨¾à¨¨à¨¿à¨¤ ਤੌਰ ਤੇ ਹੈ। ਇਸ ਦਾ ਕਾਰਨ ਕੋਈ ਗਲਤ ਸੰਰੂਪਣ ਜਾਂ ਕਿਸੇ ਹਮਲਾਵਰ ਵੱਲੋਂ ਤà©à¨¹à¨¾à¨¡à©‡ ਕਨੈਕਸ਼ਨ ਨੂੰ ਰਾਹ ਵਿੱਚ ਰੋਕਣਾ ਹੋ ਸਕਦਾ ਹੈ।}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">ਅਣਡਿੱਠ ਕੀਤਾ ਗਿਆ ਕਿਉਂਕਿ <ph name="POLICY_NAME" /> <ph name="VALUE" /> 'ਤੇ ਸੈੱਟ ਨਹੀਂ ਹੈ।</translation>
<translation id="1712552549805331520"><ph name="URL" /> ਦੀ ਤà©à¨¹à¨¾à¨¡à©‡ ਸਥਾਨਕ ਕੰਪਿਊਟਰ 'ਤੇ ਸਥਾਈ ਤੌਰ 'ਤੇ ਡਾਟਾ ਸਟੋਰ ਕਰਨ ਦੀ ਇੱਛਾ ਹੈ</translation>
<translation id="1713628304598226412">ਟà©à¨°à©‡à¨… 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">ਮੇਲਬਾਕਸ 3</translation>
<translation id="1718029547804390981">ਦਸਤਾਵੇਜ਼ ਵੱਡਾ ਹੋਣ ਕਰਕੇ à¨à¨¨à©‹à¨Ÿà©‡à¨¶à¨¨ ਉਪਲਬਧ ਨਹੀਂ ਹੈ</translation>
<translation id="1721424275792716183">* ਖੇਤਰ ਲੋੜੀਂਦਾ ਹੈ</translation>
+<translation id="1727613060316725209">ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਵੈਧ ਹੈ</translation>
<translation id="1727741090716970331">ਵੈਧ ਕਾਰਡ ਨੰਬਰ ਸ਼ਾਮਲ ਕਰੋ</translation>
<translation id="1728677426644403582">ਤà©à¨¸à©€à¨‚ ਕਿਸੇ ਵੈੱਬ ਪੰਨੇ ਦੇ ਸਰੋਤ ਨੂੰ ਵੇਖ ਰਹੇ ਹੋ</translation>
<translation id="173080396488393970">ਇਸ ਤਰà©à¨¹à¨¾à¨‚ ਦਾ ਕਾਰਡ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Windows ਨੈੱਟਵਰਕ ਤਸ਼ਖੀਸਾਂ ਨੂੰ ਚਲਾਉਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ<ph name="END_LINK" />।</translation>
<translation id="1772163372082567643">ਜਿਸ ਸਰਵਰ 'ਤੇ ਤà©à¨¸à©€à¨‚ ਜਾ ਰਹੇ ਹੋ, <ph name="ORIGIN" />, ਉਸਨੇ ਇੱਕ ਸਿਰਲੇਖ ਸੈੱਟ ਕੀਤਾ ਹੈ ਜਿਸ ਵਿੱਚ ਇਹ ਚੀਜ਼ ਲੋੜੀਂਦੀ ਹੈ ਕਿ ਮੂਲ ਨੀਤੀ ਨੂੰ ਇਸ 'ਤੇ ਕੀਤੀਆਂ ਗਈਆਂ ਸਾਰੀਆਂ ਬੇਨਤੀਆਂ 'ਤੇ ਲਾਗੂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਪਰ ਸਿਰਲੇਖ ਨà©à¨•à¨¸à¨¦à¨¾à¨° ਹੈ, ਜੋ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨° ਨੂੰ <ph name="SITE" /> ਲਈ ਤà©à¨¹à¨¾à¨¡à©€ ਬੇਨਤੀ ਨੂੰ ਪੂਰਾ ਕਰਨ ਤੋਂ ਰੋਕਦਾ ਹੈ। ਮੂਲ ਸੰਬੰਧੀ ਨੀਤੀਆਂ ਨੂੰ ਕਿਸੇ ਸਾਈਟ ਦੀ ਸà©à¨°à©±à¨–ਿਆ ਅਤੇ ਹੋਰ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦਾ ਸੰਰੂਪਣ ਕਰਨ ਲਈ ਸਾਈਟ ਓਪਰੇਟਰਾਂ ਵੱਲੋਂ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ।</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">ਕਿਰਪਾ ਕਰਕੇ ਆਪਣਾ ਸਿੰਕ ਪਾਸਫਰੇਜ਼ ਅੱਪਡੇਟ ਕਰੋ।</translation>
<translation id="1787142507584202372">ਤà©à¨¹à¨¾à¨¡à©‡ ਖà©à©±à¨²à©à¨¹à©‡ ਟੈਬ ਇੱਥੇ ਵਿਖਾਈ ਦੇਣਗੇ</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ਇੱਕ ਤੋਂ ਵੱਧ ਕਾਰਵਾਈਆਂ ਉਪਲਬਧ ਹਨ, ਉਹਨਾਂ ਵਿੱਚ ਚੱਕਰ ਲਗਾਉਣ ਲਈ Tab ਦਬਾਓ</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">ਵਿਗਿਆਪਨ</translation>
<translation id="1919367280705858090">ਇੱਕ ਖਾਸ ਗੜਬੜ-ਸà©à¨¨à©‡à¨¹à¨¾ ਸੰਬੰਧੀ ਮਦਦ ਪà©à¨°à¨¾à¨ªà¨¤ ਕਰੋ</translation>
<translation id="192020519938775529">{COUNT,plural, =0{ਕੋਈ ਨਹੀਂ}=1{1 ਸਾਈਟ}other{# ਸਾਈਟਾਂ}}</translation>
+<translation id="1924727005275031552">ਨਵਾਂ</translation>
<translation id="1945968466830820669">ਤà©à¨¸à©€à¨‚ ਆਪਣੀ ਸੰਸਥਾ ਦੇ ਖਾਤੇ 'ਤੇ ਪਹà©à©°à¨š ਗà©à¨† ਸਕਦੇ ਹੋ ਜਾਂ ਤà©à¨¹à¨¾à¨¡à©€ ਪਛਾਣ ਚੋਰੀ ਹੋ ਸਕਦੀ ਹੈ। Chromium ਵੱਲੋਂ ਹà©à¨£à©‡ ਤà©à¨¹à¨¾à¨¡à¨¾ ਪਾਸਵਰਡ ਬਦਲਣ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।</translation>
<translation id="1947454675006758438">ਉੱਪਰ ਸੱਜੇ ਪਾਸੇ ਪਿੰਨ</translation>
<translation id="1958218078413065209">ਤà©à¨¹à¨¾à¨¡à¨¾ ਸਭ ਤੋਂ ਵੱਧ ਸਕੋਰ <ph name="SCORE" /> ਹੈ।</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">ਟà©à¨°à©‡à¨… 7</translation>
<translation id="204357726431741734">ਆਪਣੇ Google ਖਾਤੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤੇ ਪਾਸਵਰਡ ਵਰਤਣ ਲਈ ਸਾਈਨ-ਇਨ ਕਰੋ</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> ਭਾਸ਼ਾ ਵਾਲੇ ਪੰਨਿਆਂ ਦਾ ਅਨà©à¨µà¨¾à¨¦ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{ਇਸ ਕੰਟਰੋਲ ਦੇ ਚਾਲੂ ਹੋਣ ਅਤੇ ਸਥਿਤੀ ਦੇ ਕਿਰਿਆਸ਼ੀਲ ਹੋਣ 'ਤੇ, Chrome ਨਿਰਧਾਰਿਤ ਕਰਦਾ ਹੈ ਤà©à¨¹à¨¾à¨¡à©€ ਹਾਲੀਆ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਸਰਗਰਮੀ ਸਭ ਤੋਂ ਜ਼ਿਆਦਾ ਲੋਕਾਂ ਦੇ ਕਿਹੜੇ ਵੱਡੇ ਗਰà©à©±à¨ª ਜਾਂ "ਸਮਗà©à¨£" ਦੇ ਸਮਾਨ ਹੈ। ਵਿਗਿਆਪਨਦਾਤੇ ਗਰà©à©±à¨ª ਲਈ ਵਿਗਿਆਪਨਾਂ ਨੂੰ ਚà©à¨£ ਸਕਦੇ ਹਨ ਅਤੇ ਤà©à¨¹à¨¾à¨¡à©‡ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਇਤਿਹਾਸ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ ਡੀਵਾਈਸ 'ਤੇ ਨਿੱਜੀ ਰੱਖਿਆ ਜਾਂਦਾ ਹੈ। ਤà©à¨¹à¨¾à¨¡à©‡ ਗਰà©à©±à¨ª ਨੂੰ ਹਰ ਰੋਜ਼ ਅੱਪਡੇਟ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।}=1{ਇਸ ਕੰਟਰੋਲ ਦੇ ਚਾਲੂ ਹੋਣ ਅਤੇ ਸਥਿਤੀ ਦੇ ਕਿਰਿਆਸ਼ੀਲ ਹੋਣ 'ਤੇ, Chrome ਨਿਰਧਾਰਿਤ ਕਰਦਾ ਹੈ ਤà©à¨¹à¨¾à¨¡à©€ ਹਾਲੀਆ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਸਰਗਰਮੀ ਸਭ ਤੋਂ ਜ਼ਿਆਦਾ ਲੋਕਾਂ ਦੇ ਕਿਹੜੇ ਵੱਡੇ ਗਰà©à©±à¨ª ਜਾਂ "ਸਮਗà©à¨£" ਦੇ ਸਮਾਨ ਹੈ। ਵਿਗਿਆਪਨਦਾਤੇ ਗਰà©à©±à¨ª ਲਈ ਵਿਗਿਆਪਨਾਂ ਨੂੰ ਚà©à¨£ ਸਕਦੇ ਹਨ ਅਤੇ ਤà©à¨¹à¨¾à¨¡à©‡ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਇਤਿਹਾਸ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ ਡੀਵਾਈਸ 'ਤੇ ਨਿੱਜੀ ਰੱਖਿਆ ਜਾਂਦਾ ਹੈ। ਤà©à¨¹à¨¾à¨¡à©‡ ਗਰà©à©±à¨ª ਨੂੰ ਹਰ ਰੋਜ਼ ਅੱਪਡੇਟ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।}other{ਇਸ ਕੰਟਰੋਲ ਦੇ ਚਾਲੂ ਹੋਣ ਅਤੇ ਸਥਿਤੀ ਦੇ ਕਿਰਿਆਸ਼ੀਲ ਹੋਣ 'ਤੇ, Chrome ਨਿਰਧਾਰਿਤ ਕਰਦਾ ਹੈ ਤà©à¨¹à¨¾à¨¡à©€ ਹਾਲੀਆ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਸਰਗਰਮੀ ਸਭ ਤੋਂ ਜ਼ਿਆਦਾ ਲੋਕਾਂ ਦੇ ਕਿਹੜੇ ਵੱਡੇ ਗਰà©à©±à¨ª ਜਾਂ "ਸਮਗà©à¨£" ਦੇ ਸਮਾਨ ਹੈ। ਵਿਗਿਆਪਨਦਾਤੇ ਗਰà©à©±à¨ª ਲਈ ਵਿਗਿਆਪਨਾਂ ਨੂੰ ਚà©à¨£ ਸਕਦੇ ਹਨ ਅਤੇ ਤà©à¨¹à¨¾à¨¡à©‡ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਇਤਿਹਾਸ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ ਡੀਵਾਈਸ 'ਤੇ ਨਿੱਜੀ ਰੱਖਿਆ ਜਾਂਦਾ ਹੈ। ਤà©à¨¹à¨¾à¨¡à©‡ ਗਰà©à©±à¨ª ਨੂੰ ਹਰ {NUM_DAYS} ਦਿਨਾਂ ਬਾਅਦ ਅੱਪਡੇਟ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।}}</translation>
<translation id="2053553514270667976">ਜ਼ਿਪ ਕੋਡ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ਸà©à¨à¨¾à¨…}one{# ਸà©à¨à¨¾à¨…}other{ # ਸà©à¨à¨¾à¨…}}</translation>
<translation id="2071692954027939183">ਸੂਚਨਾਵਾਂ ਸਵੈਚਲਿਤ ਤੌਰ 'ਤੇ ਬਲਾਕ ਕੀਤੀਆਂ ਗਈਆਂ ਕਿਉਂਕਿ ਤà©à¨¸à©€à¨‚ ਆਮ ਤੌਰ 'ਤੇ ਉਹਨਾਂ ਨੂੰ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੰਦੇ ਹੋ</translation>
<translation id="2079545284768500474">ਅਣਕੀਤਾ ਕਰੋ</translation>
<translation id="20817612488360358">ਸਿਸਟਮ ਪà©à¨°à©Œà¨•à¨¸à©€ ਸੈਟਿੰਗਾਂ ਵਰਤੇ ਜਾਣ ਲਈ ਸੈੱਟ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ ਪਰ ਇੱਕ ਸਪਸ਼ਟ ਪà©à¨°à©Œà¨•à¨¸à©€ ਸੰਰੂਪਿਤ ਵੀ ਨਿਸ਼ਚਿਤ ਹੈ।</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> ਦਾ <ph name="RESULT_NUMBER" /> ਨਤੀਜਾ</translation>
+<translation id="2085876078937250610">ਰੱਖਿਅਤ ਕਰੋ…</translation>
<translation id="2088086323192747268">'ਸਮਕਾਲੀਕਰਨ' ਬਟਨ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ ਕਰੋ, Chrome ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਤà©à¨¸à©€à¨‚ ਜਿਹੜੀ ਜਾਣਕਾਰੀ ਦਾ ਸਮਕਾਲੀਕਰਨ ਕਰਦੇ ਹੋ, ਉਸਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ ਕਰਨ ਲਈ Enter ਦਬਾਓ</translation>
<translation id="2091887806945687916">ਧà©à¨¨à©€</translation>
<translation id="2094505752054353250">ਡੋਮੇਨ ਮਿਸਮੈਚ</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> ਨੂੰ ਇੱਕ ਵਰਤੋਂਕਾਰ ਨਾਮ ਅਤੇ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ।</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, ਮਿਆਦ <ph name="EXPIRATION_DATE_ABBR" /> ਨੂੰ ਸਮਾਪਤ ਹੋਵੇਗੀ</translation>
<translation id="2337852623177822836">ਸੈਟਿੰਗ ਤà©à¨¹à¨¾à¨¡à©‡ ਪà©à¨°à¨¶à¨¾à¨¸à¨• ਵੱਲੋਂ ਕੰਟਰੋਲ ਕੀਤੀ ਗਈ</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ਜੋੜਾਬੱਧ ਕਰਨਾ ਚਾਹà©à©°à¨¦à©€ ਹੈ</translation>
<translation id="2344028582131185878">ਆਟੋਮੈਟਿਕ ਡਾਊਨਲੋਡਸ</translation>
<translation id="2346319942568447007">ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਕਾਪੀ ਕੀਤਾ ਚਿੱਤਰ</translation>
<translation id="2354001756790975382">ਹੋਰ ਬà©à©±à¨•à¨®à¨¾à¨°à¨•</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਇਸ ਸਾਈਟ 'ਤੇ ਵੇਖੇ ਜਾ ਰਹੇ ਚਿੱਤਰਾਂ ਨੂੰ ਹਮਲਾਵਰ ਵੀ ਦੇਖਣ ਦੇ ਯੋਗ ਹੋਣ ਅਤੇ ਉਹਨਾਂ ਚਿੱਤਰਾਂ ਨੂੰ ਸੋਧ ਕੇ ਉਹ ਤà©à¨¹à¨¾à¨¨à©‚à©° ਧੋਖਾ ਦੇ ਸਕਦੇ ਹਨ।</translation>
<translation id="2356070529366658676">ਪà©à©±à¨›à©‹</translation>
<translation id="2357481397660644965">ਤà©à¨¹à¨¾à¨¡à©‡ ਡੀਵਾਈਸ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ <ph name="DEVICE_MANAGER" /> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਅਤੇ ਤà©à¨¹à¨¾à¨¡à©‡ ਖਾਤੇ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ <ph name="ACCOUNT_MANAGER" /> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ਇੱਕ ਦਿਨ ਤੋਂ ਘੱਟ ਸਮੇਂ ਵਿੱਚ}=1{ਇੱਕ ਦਿਨ ਵਿੱਚ}other{{NUM_DAYS} ਦਿਨਾਂ ਵਿੱਚ}}</translation>
<translation id="2359629602545592467">ਇੱਕ ਤੋਂ ਵਧੇਰੇ</translation>
<translation id="2359808026110333948">ਜਾਰੀ ਰੱਖੋ</translation>
+<translation id="2359961752320758691">ਤà©à¨¹à¨¾à¨¡à¨¾ ਆਭਾਸੀ ਕਾਰਡ ਨੰਬਰ ਲਾਗੂ ਕੀਤਾ ਗਿਆ ਹੈ।</translation>
<translation id="2367567093518048410">ਪੱਧਰ</translation>
<translation id="2372464001869762664">ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਤਸਦੀਕ ਕੀਤੇ ਜਾਣ ਤੋਂ ਬਾਅਦ, ਤà©à¨¹à¨¾à¨¡à©‡ Google ਖਾਤੇ ਤੋਂ ਕਾਰਡ ਦੇ ਵੇਰਵੇ ਇਸ ਸਾਈਟ ਨਾਲ ਸਾਂà¨à©‡ ਕੀਤੇ ਜਾਣਗੇ। CVC ਨੂੰ ਆਪਣੇ Plex ਖਾਤੇ ਦੇ ਵੇਰਵਿਆਂ ਵਿੱਚ ਲੱਭੋ।</translation>
<translation id="2380886658946992094">ਕਨੂੰਨੀ</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">ਇਹ ਸ਼ਿਪਿੰਗ ਵਿਧੀ ਉਪਲਬਧ ਨਹੀਂ ਹੈ। ਕੋਈ ਵੱਖਰੀ ਵਿਧੀ ਅਜ਼ਮਾਓ।</translation>
<translation id="2396249848217231973">&amp;ਮਿਟਾਠਗਠਨੂੰ ਅਣਕੀਤਾ ਕਰੋ</translation>
<translation id="2410754574180102685">ਸਰਕਾਰੀ-ਕਨੂੰਨੀ</translation>
+<translation id="2413155254802890957">ਪà©à¨°à¨¾à¨£à¨¾</translation>
<translation id="2413528052993050574">ਇਹ ਸਰਵਰ ਇਹ ਸਿੱਧ ਨਹੀਂ ਕਰ ਸਕਿਆ ਕਿ ਇਹ <ph name="DOMAIN" /> ਹੈ; ਇਸਦਾ ਸà©à¨°à©±à¨–ਿਆ ਸਰਟੀਫਿਕੇਟ ਰੱਦ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। ਇਸ ਦਾ ਕਾਰਨ ਗਲਤ ਸੰਰੂਪਣ ਹੋ ਸਕਦਾ ਹੈ ਜਾਂ ਕੋਈ ਹਮਲਾਵਰ ਤà©à¨¹à¨¾à¨¡à©‡ ਕਨੈਕਸ਼ਨ ਦੇ ਰਾਹ ਨੂੰ ਰੋਕ ਰਿਹਾ ਹੈ।</translation>
<translation id="2414886740292270097">ਡਾਰਕ</translation>
<translation id="2438874542388153331">ਸੱਜੇ ਪਾਸੇ ਚਾਰ ਮੋਰੀਆਂ</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">ਹੇਠਾਂ ਸੱਜੇ ਪਾਸੇ ਪਿੰਨ</translation>
<translation id="2523886232349826891">ਸਿਰਫ਼ ਇਸ ਡੀਵਾਈਸ 'ਤੇ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ</translation>
<translation id="2524461107774643265">ਹੋਰ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਕਰੋ</translation>
-<translation id="2526590354069164005">ਡੈਸਕਟਾਪ</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{ਅਤੇ 1 ਹੋਰ}one{ਅਤੇ # ਹੋਰ}other{ਅਤੇ # ਹੋਰ}}</translation>
<translation id="2536110899380797252">ਪਤਾ ਸ਼ਾਮਲ ਕਰੋ</translation>
<translation id="2539524384386349900">ਪਤਾ ਲਗਾਓ</translation>
+<translation id="2541219929084442027">ਜੋ ਪੰਨੇ ਤà©à¨¸à©€à¨‚ ਇਨਕੋਗਨਿਟੋ ਟੈਬਾਂ ਵਿੱਚ ਦੇਖਦੇ ਹੋ, ਉਹ ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਆਪਣੀਆਂ ਸਾਰੀਆਂ ਇਨਕੋਗਨਿਟੋ ਟੈਬਾਂ ਬੰਦ ਕਰਨ ਤੋਂ ਬਾਅਦ ਤà©à¨¹à¨¾à¨¡à©‡ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨° ਦੇ ਇਤਿਹਾਸ, ਕà©à¨•à©€ ਸਟੋਰ ਜਾਂ ਖੋਜ ਇਤਿਹਾਸ ਵਿੱਚ ਨਹੀਂ ਰਹਿਣਗੇ। ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਕੋਈ ਵੀ ਫ਼ਾਈਲਾਂ ਅਤੇ ਬਣਾਠਬà©à©±à¨•à¨®à¨¾à¨°à¨• ਬਰਕਰਾਰ ਰਹਿਣਗੇ।</translation>
<translation id="2544644783021658368">ਇਕਹਿਰਾ ਦਸਤਾਵੇਜ਼</translation>
<translation id="254947805923345898">ਨੀਤੀ ਦਾ ਮà©à©±à¨² ਵੈਧ ਨਹੀਂ ਹੈ।</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ਨੇ ਇੱਕ ਅਵੈਧ ਪà©à¨°à¨¤à¨¿à¨•à¨¿à¨°à¨¿à¨† ਭੇਜੀ।</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">Chrome ਦੀ ਉੱਚਤਮ ਪੱਧਰ ਦੀ ਸà©à¨°à©±à¨–ਿਆ ਪà©à¨°à¨¾à¨ªà¨¤ ਕਰਨ ਲਈ, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ਵਿਸਤà©à¨°à¨¿à¨¤ ਸà©à¨°à©±à¨–ਿਆ ਨੂੰ ਚਾਲੂ ਕਰੋ<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> ਦਾ ਸਰਵਰ IP ਪਤਾ ਨਹੀਂ ਲੱਭਿਆ।</translation>
<translation id="2639739919103226564">ਸਥਿਤੀ:</translation>
+<translation id="264810637653812429">ਕੋਈ ਅਨà©à¨°à©‚ਪ ਡੀਵਾਈਸ ਨਹੀਂ ਮਿਲੇ।</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Tab ਦਬਾਓ, ਫਿਰ Chrome ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਆਪਣੇ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਇਤਿਹਾਸ, ਕà©à¨•à©€à¨œà¨¼, ਕੈਸ਼ੇ ਅਤੇ ਹੋਰ ਬਹà©à¨¤ ਕà©à¨ ਨੂੰ ਕਲੀਅਰ ਕਰਨ ਲਈ Enter ਦਬਾਓ</translation>
<translation id="2650446666397867134">ਫਾਈਲ ਤੱਕ ਪਹà©à©°à¨š ਅਸਵੀਕਾਰ ਕਰ ਦਿੱਤੀ ਗਈ ਸੀ</translation>
@@ -489,6 +503,7 @@
<translation id="2799223571221894425">ਰੀਲੌਂਚ ਕਰੋ</translation>
<translation id="2803306138276472711">Google ਸà©à¨°à©±à¨–ਿਅਤ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਨੇ <ph name="SITE" /> 'ਤੇ ਹà©à¨£à©‡ ਹੀ<ph name="BEGIN_LINK" /> ਮਲਵੇਅਰ ਖੋਜਿਆ<ph name="END_LINK" /> ਸੀ। ਜੋ ਵੈੱਬਸਾਈਟਾਂ ਆਮ ਤੌਰ ਤੇ ਸà©à¨°à©±à¨–ਿਅਤ ਹà©à©°à¨¦à©€à¨†à¨‚ ਹਨ, ਉਹ ਵੀ ਕਦੇ-ਕਦੇ ਮਲਵੇਅਰ ਨਾਲ ਸੰਕà©à¨°à¨®à¨¿à¨¤ ਹੋ ਜਾਂਦੀਆਂ ਹਨ।</translation>
<translation id="2807052079800581569">ਚਿੱਤਰ Y ਸਥਿਤੀ</translation>
+<translation id="2820957248982571256">ਸਕੈਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ...</translation>
<translation id="2824775600643448204">ਪਤਾ ਅਤੇ ਖੋਜ ਬਾਰ</translation>
<translation id="2826760142808435982">ਕਨੈਕਸ਼ਨ <ph name="CIPHER" /> ਵਰਤਦੇ ਹੋਠà¨à¨¨à¨•à©à¨°à¨¿à¨ªà¨Ÿ ਅਤੇ ਪà©à¨°à¨®à¨¾à¨£à¨¿à¨¤ ਕੀਤਾ ਗਿਆ ਹੈ ਅਤੇ ਇਹ <ph name="KX" /> ਨੂੰ ਮà©à©±à¨– à¨à¨•à¨¸à¨šà©‡à¨‚ਜ ਬਣਤਰ ਦੇ ਤੌਰ 'ਤੇ ਵਰਤਦਾ ਹੈ।</translation>
<translation id="2835170189407361413">ਫ਼ਾਰਮ ਹਟਾਓ</translation>
@@ -496,6 +511,8 @@
<translation id="2850739647070081192">ਸੱਦਾ (ਲਿਫ਼ਾਫ਼ਾ)</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="2859806420264540918">ਇਹ ਸਾਈਟ ਦਖਲਅੰਦਾਜ਼ੀ ਜਾਂ ਗà©à¨®à¨°à¨¾à¨¹ ਕਰਨ ਵਾਲੇ ਵਿਗਿਆਪਨ ਦਿਖਾਉਂਦੀ ਹੈ।</translation>
+<translation id="287596039013813457">ਦੋਸਤਾਨਾ</translation>
+<translation id="2876489322757410363">ਕਿਸੇ ਬਾਹਰੀ à¨à¨ªà¨²à©€à¨•à©‡à¨¸à¨¼à¨¨ ਰਾਹੀਂ ਭà©à¨—ਤਾਨ ਕਰਨ ਲਈ ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਤੋਂ ਬਾਹਰ ਜਾਇਆ ਜਾ ਰਿਹਾ ਹੈ। ਕੀ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?</translation>
<translation id="2878197950673342043">ਪੋਸਟਰ ਰੂਪੀ ਤਹਿ</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ਵਿੰਡੋ ਪਲੇਸਮੈਂਟ</translation>
@@ -545,7 +562,6 @@
<translation id="3060227939791841287">C9 (ਲਿਫ਼ਾਫ਼ਾ)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, ਟੈਬ ਨੂੰ ਦਬਾਓ ਫਿਰ Chrome ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਸà©à¨°à©±à¨–ਿਆ ਜਾਂਚ ਚਲਾਉਣ ਲਈ Enter ਦਬਾਓ</translation>
<translation id="3061707000357573562">ਪੈਚ ਸੇਵਾ</translation>
-<translation id="3064966200440839136">ਕਿਸੇ ਬਾਹਰੀ à¨à¨ªà¨²à©€à¨•à©‡à¨¸à¨¼à¨¨ ਰਾਹੀਂ ਭà©à¨—ਤਾਨ ਕਰਨ ਲਈ ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਤੋਂ ਬਾਹਰ ਜਾਇਆ ਜਾ ਰਿਹਾ ਹੈ। ਜਾਰੀ ਰੱਖੀà¨?</translation>
<translation id="306573536155379004">ਗੇਮ ਸ਼à©à¨°à©‚ ਕੀਤੀ ਗਈ।</translation>
<translation id="3080254622891793721">ਗà©à¨°à¨¾à¨«à¨¼à¨¿à¨•</translation>
<translation id="3086579638707268289">ਵੈੱਬ 'ਤੇ ਤà©à¨¹à¨¾à¨¡à©€ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ</translation>
@@ -568,7 +584,6 @@
<translation id="315504272643575312">ਤà©à¨¹à¨¾à¨¡à¨¾ ਖਾਤਾ <ph name="MANAGER" /> ਵੱਲੋਂ ਪà©à¨°à¨¬à©°à¨§à¨¿à¨¤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।</translation>
<translation id="3157931365184549694">ਰੀਸਟੋਰ ਕਰੋ</translation>
<translation id="3162559335345991374">ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਵਰਤਿਆ ਜਾ ਰਿਹਾ ਵਾਈ-ਫਾਈ ਇਹ ਚਾਹ ਸਕਦਾ ਹੈ ਕਿ ਤà©à¨¸à©€à¨‚ ਇਸਦੇ ਲੌਗ-ਇਨ ਪੰਨੇ 'ਤੇ ਜਾਓ।</translation>
-<translation id="3167968892399408617">ਜੋ ਪੰਨੇ ਤà©à¨¸à©€à¨‚ ਇਨਕੋਗਨਿਟੋ ਟੈਬਾਂ ਵਿੱਚ ਦੇਖਦੇ ਹੋ, ਉਹ ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਆਪਣੀਆਂ ਸਾਰੀਆਂ ਇਨਕੋਗਨਿਟੋ ਟੈਬਾਂ ਬੰਦ ਕਰਨ ਤੋਂ ਬਾਅਦ ਤà©à¨¹à¨¾à¨¡à©‡ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨° ਦੇ ਇਤਿਹਾਸ, ਕà©à¨•à©€ ਸਟੋਰ ਜਾਂ ਖੋਜ ਇਤਿਹਾਸ ਵਿੱਚ ਨਹੀਂ ਰਹਿਣਗੇ। ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਡਾਊਨਲੋਡ ਕੀਤੀਆਂ ਕੋਈ ਵੀ ਫ਼ਾਈਲਾਂ ਅਤੇ ਬਣਾਠਬà©à©±à¨•à¨®à¨¾à¨°à¨• ਬਰਕਰਾਰ ਰਹਿਣਗੇ।</translation>
<translation id="3169472444629675720">ਖੋਜੋ</translation>
<translation id="3174168572213147020">ਟਾਪੂ</translation>
<translation id="3176929007561373547">ਪà©à¨°à©Œà¨•à¨¸à©€ ਸਰਵਰ ਕੰਮ ਕਰ ਰਿਹਾ ਹੈ ਇਹ ਪੱਕਾ ਕਰੋ ਕਰਨ ਲਈ ਆਪਣੀਆਂ ਪà©à¨°à©Œà¨•à¨¸à©€ ਸੈਟਿੰਗਾਂ ਦੀ ਜਾਂਚ ਕਰੋ ਜਾਂ ਆਪਣੇ ਨੈੱਟਵਰਕ ਪà©à¨°à¨¸à¨¼à¨¾à¨¸à¨• ਨੂੰ ਸੰਪਰਕ ਕਰੋ, ਜੇਕਰ ਤà©à¨¸à©€à¨‚ ਪੱਕਾ ਨਹੀਂ ਕਰਦੇ ਤਾਂ ਤà©à¨¹à¨¾à¨¨à©‚à©° ਇੱਕ ਪà©à¨°à©Œà¨•à¨¸à©€ ਸਰਵਰ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਚਾਹੀਦੀ ਹੈ:
@@ -592,10 +607,12 @@
<translation id="3229041911291329567">ਤà©à¨¹à¨¾à¨¡à©‡ ਡੀਵਾਈਸ ਅਤੇ ਬà©à¨°à¨¾à¨Šà©›à¨° ਦੇ ਵਰਜਨ ਬਾਰੇ ਜਾਣਕਾਰੀ</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> ਦਾ CVC ਦਾਖਲ ਕਰੋ</translation>
<translation id="3234666976984236645">ਇਸ ਸਾਈਟ 'ਤੇ ਹਮੇਸ਼ਾਂ ਆਯਾਤ ਸਮੱਗਰੀ ਖੋਜੋ</translation>
+<translation id="3249845759089040423">ਗਰੂਵੀ</translation>
<translation id="3252266817569339921">ਫਰੈਂਚ</translation>
<translation id="3266793032086590337">ਮà©à©±à¨² (ਵਿਵਾਦ)</translation>
<translation id="3268451620468152448">ਟੈਬਸ ਖੋਲà©à¨¹à©‹</translation>
<translation id="3270847123878663523">&amp;ਦà©à¨¬à¨¾à¨°à¨¾ ਕà©à¨°à¨® ਦੇਣ ਨੂੰ ਅਨਡੂ ਕਰੋ</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> ਕਨੈਕਟ ਹੋਣਾ ਚਾਹà©à©°à¨¦à©€ ਹੈ</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">ਤà©à¨¹à¨¾à¨¡à©€ ਸੰਸਥਾ, <ph name="ENROLLMENT_DOMAIN" />, ਨੇ ਅੱਗੇ ਦਿੱਤੀਆਂ ਵੈੱਬਸਾਈਟਾਂ ਨੂੰ ਕà©à¨ ਜਾਣਕਾਰੀ ਭੇਜੀ ਹੈ, ਜਿਵੇਂ ਸੈਟਿੰਗਾਂ ਜਾਂ ਨੀਤੀਆਂ।</translation>
<translation id="3282497668470633863">ਕਾਰਡ 'ਤੇ ਨਾਮ ਸ਼ਾਮਲ ਕਰੋ</translation>
@@ -648,6 +665,7 @@
<translation id="3428151540071562330">ਇੱਕ ਜਾਂ ਇੱਕ ਤੋਂ ਵੱਧ DnsOverHttpsTemplates ਸਰਵਰ ਟੈਮਪਲੇਟ URI ਅਵੈਧ ਹਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕੀਤੀ ਜਾਵੇਗੀ।</translation>
<translation id="3431636764301398940">ਇਸ ਕਾਰਡ ਨੂੰ ਇਸ ਡੀਵਾਈਸ 'ਤੇ ਰੱਖਿਅਤ ਕਰੋ</translation>
<translation id="3432601291244612633">ਪੰਨਾ ਬੰਦ ਕਰੋ</translation>
+<translation id="3435738964857648380">ਸà©à¨°à©±à¨–ਿਆ</translation>
<translation id="3435896845095436175">ਚਾਲੂ ਕਰੋ</translation>
<translation id="3438829137925142401">ਆਪਣੇ Google ਖਾਤੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤੇ ਪਾਸਵਰਡ ਵਰਤੋ</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -690,21 +708,24 @@
<translation id="3584299510153766161">ਹੇਠਾਂ ਦੋ ਮੋਰੀਆਂ</translation>
<translation id="3586931643579894722">ਵੇਰਵੇ ਲà©à¨•à¨¾à¨“</translation>
<translation id="3587738293690942763">ਵਿਚਕਾਰ</translation>
+<translation id="3590643883886679995">ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਤੋਂ ਬਾਹਰ ਨਿਕਲਣ ਦੇ ਬਾਅਦ ਸਾਈਨ-ਇਨ ਡਾਟਾ ਇਸ ਡੀਵਾਈਸ 'ਤੇ ਸਟੋਰ ਕੀਤਾ ਜਾਵੇਗਾ।</translation>
+<translation id="359126217934908072">ਮਹੀਨਾ/ਸਾਲ:</translation>
<translation id="3592413004129370115">ਇਤਾਲਵੀ (ਲਿਫ਼ਾਫ਼ਾ)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{ਤà©à¨¸à©€à¨‚ ਕਿਸੇ ਵੀ ਸਮੇਂ ਆਪਣਾ ਗਰà©à©±à¨ª ਰੀਸੈੱਟ ਕਰ ਸਕਦੇ ਹੋ। ਇੱਕ ਨਵੇਂ ਗਰà©à©±à¨ª ਵਿੱਚ ਸ਼ਾਮਲ ਹੋਣ ਲਈ ਲਗਭਗ ਇੱਕ ਦਿਨ ਦਾ ਸਮਾਂ ਲੱਗਦਾ ਹੈ।}=1{ਤà©à¨¸à©€à¨‚ ਕਿਸੇ ਵੀ ਸਮੇਂ ਆਪਣਾ ਗਰà©à©±à¨ª ਰੀਸੈੱਟ ਕਰ ਸਕਦੇ ਹੋ। ਇੱਕ ਨਵੇਂ ਗਰà©à©±à¨ª ਵਿੱਚ ਸ਼ਾਮਲ ਹੋਣ ਲਈ ਲਗਭਗ ਇੱਕ ਦਿਨ ਦਾ ਸਮਾਂ ਲੱਗਦਾ ਹੈ।}other{ਤà©à¨¸à©€à¨‚ ਕਿਸੇ ਵੀ ਸਮੇਂ ਆਪਣਾ ਗਰà©à©±à¨ª ਰੀਸੈੱਟ ਕਰ ਸਕਦੇ ਹੋ। ਇੱਕ ਨਵੇਂ ਗਰà©à©±à¨ª ਵਿੱਚ ਸ਼ਾਮਲ ਹੋਣ ਲਈ ਲਗਭਗ {NUM_DAYS} ਦਿਨਾਂ ਦਾ ਸਮਾਂ ਲੱਗਦਾ ਹੈ।}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">à¨à¨ªà¨²à©€à¨•à©‡à¨¸à¨¼à¨¨ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ ਪà©à¨°à¨¸à¨¼à¨¾à¨¸à¨• ਵੱਲੋਂ ਬਲਾਕ ਕੀਤਾ ਗਿਆ</translation>
<translation id="3608932978122581043">ਦਿਸ਼ਾਮਾਨ ਫ਼ੀਡ ਕਰੋ</translation>
<translation id="3614103345592970299">ਆਕਾਰ 2</translation>
<translation id="361438452008624280">ਸੂਚੀ ਇੰਦਰਾਜ "<ph name="LANGUAGE_ID" />": ਅਗਿਆਤ ਜਾਂ ਅਸਮਰਥਿਤ ਭਾਸ਼ਾ।</translation>
<translation id="3615877443314183785">ਕੋਈ ਵੈਧ ਮਿਆਦ ਸਮਾਪਤੀ ਮਿਤੀ ਦਾਖਲ ਕਰੋ</translation>
-<translation id="36224234498066874">ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਡਾਟਾ ਸਾਫ਼ ਕਰੋ...</translation>
+<translation id="36224234498066874">ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਡਾਟਾ ਕਲੀਅਰ ਕਰੋ...</translation>
<translation id="362276910939193118">ਪੂਰਾ ਇਤਿਹਾਸ ਦਿਖਾਓ</translation>
-<translation id="3625635938337243871">ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਤੋਂ ਬਾਹਰ ਨਿਕਲਣ ਦੇ ਬਾਅਦ ਸਾਈਨ-ਇਨ ਡਾਟਾ ਇਸ ਡੀਵਾਈਸ 'ਤੇ ਸਟੋਰ ਕੀਤਾ ਜਾਵੇਗਾ।</translation>
<translation id="3630155396527302611">ਜੇਕਰ ਇਸ ਨੂੰ ਪਹਿਲਾਂ ਹੀ ਨੈੱਟਵਰਕ 'ਤੇ ਪਹà©à©°à¨š ਦੀ ਮਨਜ਼ੂਰੀ ਵਾਲੇ ਇੱਕ ਪà©à¨°à©‹à¨—ਰਾਮ ਦੇ ਤੌਰ 'ਤੇ ਸੂਚੀਬੱਧ ਕੀਤਾ ਗਿਆ ਹੈ, ਇਸ ਨੂੰ ਸੂਚੀ ਵਿੱਚ ਹਟਾਉਣ ਅਤੇ ਦà©à¨¬à¨¾à¨°à¨¾ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</translation>
<translation id="3630699740441428070">ਇਸ ਡੀਵਾਈਸ ਦੇ ਪà©à¨°à¨¶à¨¾à¨¸à¨•à¨¾à¨‚ ਨੇ ਤà©à¨¹à¨¾à¨¡à©‡ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨ ਦਾ ਸੰਰੂਪਣ ਕੀਤਾ ਹੈ, ਜਿਸ ਨਾਲ ਸ਼ਾਇਦ ਉਹ ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਦੇਖੀਆਂ ਜਾਂਦੀਆਂ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤà©à¨¹à¨¾à¨¡à©‡ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਨੂੰ ਦੇਖ ਸਕਦੇ ਹਨ।</translation>
<translation id="3631244953324577188">ਬਾਇਓਮੈਟà©à¨°à¨¿à¨•</translation>
<translation id="3633738897356909127">'Chrome ਅੱਪਡੇਟ ਕਰੋ' ਬਟਨ, ਆਪਣੀਆਂ Chrome ਸੈਟਿੰਗਾਂ ਤੋਂ Chrome ਅੱਪਡੇਟ ਕਰਨ ਲਈ Enter ਦਬਾਓ</translation>
<translation id="3634530185120165534">ਟà©à¨°à©‡à¨… 5</translation>
+<translation id="3637662659967048211">Google ਖਾਤੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੋ</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">à¨à¨ªà¨²à©€à¨•à©‡à¨¶à¨¨:</translation>
<translation id="3650584904733503804">ਪà©à¨°à¨®à¨¾à¨£à©€à¨•à¨°à¨¨ ਸਫਲ</translation>
@@ -745,6 +766,7 @@
<translation id="3781428340399460090">ਗੂੜà©à¨¹à¨¾ ਗà©à¨²à¨¾à¨¬à©€</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">ਬਲੂਟà©à©±à¨¥ ਡੀਵਾਈਸਾਂ</translation>
+<translation id="3787675388804467730">ਆਭਾਸੀ ਕਾਰਡ ਨੰਬਰ</translation>
<translation id="3787705759683870569">ਮਿਆਦ ਸਮਾਪਤੀ ਦੀ ਮਿਤੀ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">ਆਕਾਰ 16</translation>
<translation id="3789841737615482174">ਸਥਾਪਤ ਕਰੋ</translation>
@@ -764,6 +786,7 @@
<translation id="3841184659773414994">ਫ਼ਾਈਲ ਹੈਂਡਲਰ</translation>
<translation id="385051799172605136">ਪਿੱਛੇ</translation>
<translation id="3858027520442213535">ਤਾਰੀਖ ਅਤੇ ਸਮਾਂ ਅੱਪਡੇਟ ਕਰੋ</translation>
+<translation id="3881478300875776315">ਘੱਟ ਲਾਈਨਾਂ ਦਿਖਾਓ</translation>
<translation id="3884278016824448484">ਵਿਪਰੀਤ ਡੀਵਾਈਸ ਪਛਾਣਕਰਤਾ</translation>
<translation id="3885155851504623709">ਪੈਰਿਸ਼</translation>
<translation id="388632593194507180">ਨਿਗਰਾਨੀ ਦਾ ਪਤਾ ਲੱਗਿਆ</translation>
@@ -789,6 +812,7 @@
<translation id="397105322502079400">ਅਨà©à¨®à¨¾à¨¨ ਲਗਾ ਰਿਹਾ ਹੈ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ਨੂੰ ਬਲੌਕ ਕੀਤਾ ਗਿਆ ਹੈ</translation>
<translation id="3973357910713125165">'Chrome ਸà©à¨°à©±à¨–ਿਆ ਜਾਂਚ' ਬਟਨ ਚਲਾਓ, Chrome ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਸà©à¨°à©±à¨–ਿਆ ਜਾਂਚ ਚਲਾਉਣ ਲਈ Enter ਦਬਾਓ</translation>
+<translation id="3986705137476756801">ਫ਼ਿਲਹਾਲ ਲਈ ਲਾਈਵ ਸà©à¨°à¨–ੀਆਂ ਬੰਦ ਕਰੋ</translation>
<translation id="3987405730340719549">Chrome ਨੇ ਨਿਰਧਾਰਤ ਕੀਤਾ ਹੈ ਕਿ ਇਹ ਸਾਈਟ ਨਕਲੀ ਜਾਂ ਧੋਖਾਧੜੀ ਵਾਲੀ ਹੋ ਸਕਦੀ ਹੈ।
ਜੇ ਤà©à¨¹à¨¾à¨¨à©‚à©° ਲੱਗਦਾ ਹੈ ਕਿ ਇਹ ਗਲਤੀ ਨਾਲ ਦਿਖਾਇਆ ਗਿਆ ਹੈ ਤਾਂ ਕਿਰਪਾ ਕਰਕੇ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals 'ਤੇ ਜਾਓ।</translation>
@@ -880,13 +904,14 @@
<translation id="4275830172053184480">ਆਪਣੀ ਡੀਵਾਈਸ ਨੂੰ ਮà©à©œ-ਸ਼à©à¨°à©‚ ਕਰੋ</translation>
<translation id="4277028893293644418">ਪਾਸਵਰਡ ਰੀਸੈੱਟ ਕਰੋ</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{ਇਸ ਕਾਰਡ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ Google ਖਾਤੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ ਹੈ}one{ਇਸ ਕਾਰਡ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ Google ਖਾਤੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ ਹੈ}other{ਇਹਨਾਂ ਕਾਰਡਾਂ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ Google ਖਾਤੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ ਹੈ}}</translation>
+<translation id="4287885627794386150">ਪਰਖ ਲਈ ਯੋਗ ਹੈ, ਪਰ ਕਿਰਿਆਸ਼ੀਲ ਨਹੀਂ ਹੈ</translation>
<translation id="4297502707443874121">ਪੰਨਾ <ph name="THUMBNAIL_PAGE" /> ਲਈ ਲਘੂ-ਚਿੱਤਰ</translation>
<translation id="42981349822642051">ਵਿਸਤਾਰ ਕਰੋ</translation>
<translation id="4300675098767811073">ਸੱਜੇ ਪਾਸੇ ਇੱਕ ਤੋਂ ਵੱਧ ਮੋਰੀਆਂ</translation>
<translation id="4302514097724775343">ਖੇਡਣ ਲਈ ਡਾਇਨਾਸੌਰ 'ਤੇ ਟੈਪ ਕਰੋ</translation>
<translation id="4302965934281694568">Chou3 (ਲਿਫ਼ਾਫ਼ਾ)</translation>
<translation id="4305666528087210886">ਤà©à¨¹à¨¾à¨¡à©€ ਫ਼ਾਈਲ 'ਤੇ ਪਹà©à©°à¨š ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ</translation>
-<translation id="4305817255990598646">ਸਵਿੱਚ ਕਰੋ</translation>
+<translation id="4306529830550717874">ਕੀ ਤà©à¨¸à©€à¨‚ ਪਤਾ ਰੱਖਿਅਤ ਕਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">ਬਲਾਕ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)</translation>
<translation id="4314815835985389558">ਸਮਕਾਲੀਕਰਨ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ ਕਰੋ</translation>
@@ -913,6 +938,7 @@
<translation id="4377125064752653719">ਤà©à¨¸à©€à¨‚ <ph name="DOMAIN" />, ਤੱਕ ਪਹà©à©°à¨šà¨£ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ, ਪਰ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਜੋ ਸਰਵਰ ਨੇ ਪੇਸ਼ ਕੀਤਾ ਹੈ, ਉਹ ਜਾਰੀਕਰਤਾ ਵੱਲੋਂ ਰੱਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਇਹ ਹੈ ਕਿ ਸਰਵਰ ਵੱਲੋਂ ਪੇਸ਼ ਕੀਤੇ ਗਠਸà©à¨°à©±à¨–ਿਆ ਕà©à¨°à©€à¨¡à©ˆà¨‚ਸ਼ੀਅਲ 'ਤੇ ਬਿਲਕà©à¨² ਵੀ ਭਰੋਸਾ ਨਹੀਂ ਕੀਤਾ ਜਾਣਾ ਚਾਹੀਦਾ। ਸ਼ਾਇਦ ਤà©à¨¸à©€à¨‚ ਇੱਕ ਹਮਲਾਵਰ ਨਾਲ ਸੰਚਾਰ ਕਰ ਰਹੇ ਹੋ।</translation>
<translation id="4378154925671717803">ਫ਼ੋਨ</translation>
<translation id="4390472908992056574">ਬà©à¨°à¨¿à¨®</translation>
+<translation id="4406883609789734330">ਲਾਈਵ ਸà©à¨°à¨–ੀਆਂ</translation>
<translation id="4406896451731180161">ਖੋਜ ਨਤੀਜੇ</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> ਕà©à¨•à©€à©›</translation>
<translation id="4414290883293381923">ਤà©à¨¸à©€à¨‚ ਹà©à¨£à©‡-ਹà©à¨£à©‡ ਕਿਸੇ ਭਰਮਪੂਰਨ ਸਾਈਟ 'ਤੇ ਆਪਣਾ ਪਾਸਵਰਡ ਦਾਖਲ ਕੀਤਾ ਹੈ। Chrome ਵੱਲੋਂ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ਅਤੇ ਉਹਨਾਂ ਹੋਰ ਸਾਈਟਾਂ 'ਤੇ ਜਾ ਕੇ ਹà©à¨£à©‡ ਆਪਣਾ ਪਾਸਵਰਡ ਬਦਲਣ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਜਿੱਥੇ ਤà©à¨¸à©€à¨‚ ਆਪਣਾ ਪਾਸਵਰਡ ਵਰਤਿਆ ਹੈ।</translation>
@@ -925,7 +951,6 @@
<translation id="4435702339979719576">ਪੋਸਟਕਾਰਡ)</translation>
<translation id="443673843213245140">ਇੱਕ ਪà©à¨°à©Œà¨•à¨¸à©€ ਦੀ ਵਰਤੋਂ ਅਸਮਰਥਿਤ ਹੈ ਪਰੰਤੂ ਇੱਕ ਸਪਸ਼ਟ ਪà©à¨°à©Œà¨•à¨¸à©€ ਕੌਂਫਿਗਰੇਸ਼ਨ ਨਿਸ਼ਚਿਤ ਹੈ।</translation>
<translation id="4464826014807964867">ਵੈੱਬਸਾਈਟਾਂ ਜਿਨà©à¨¹à¨¾à¨‚ ਵਿੱਚ ਤà©à¨¹à¨¾à¨¡à©€ ਸੰਸਥਾ ਵੱਲੋਂ ਜਾਣਕਾਰੀ ਮà©à¨¹à©±à¨ˆà¨† ਕਰਵਾਈ ਗਈ ਹੈ</translation>
-<translation id="4466881336512663640">ਫ਼ਾਰਮ ਤਬਦੀਲੀਆਂ ਗà©à¨†à¨š ਜਾਣਗੀਆਂ। ਕੀ ਤà©à¨¸à©€à¨‚ ਪੱਕਾ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
<translation id="4476953670630786061">ਇਹ ਫ਼ਾਰਮ ਸà©à¨°à©±à¨–ਿਅਤ ਨਹੀਂ ਹੈ। ਆਟੋਫਿਲ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ।</translation>
<translation id="4477350412780666475">ਅਗਲਾ ਟਰੈਕ</translation>
<translation id="4482953324121162758">ਇਸ ਸਾਈਟ ਦਾ ਅਨà©à¨µà¨¾à¨¦ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</translation>
@@ -959,6 +984,7 @@
<translation id="4594403342090139922">&amp;ਮਿਟਾਠਗਠਨੂੰ ਅਣਕੀਤਾ ਕਰੋ</translation>
<translation id="4597348597567598915">ਆਕਾਰ 8</translation>
<translation id="4600854749408232102">C6/C5 (ਲਿਫ਼ਾਫ਼ਾ)</translation>
+<translation id="4606870351894164739">ਅਸਰਦਾਰ</translation>
<translation id="4628948037717959914">ਫ਼ੋਟੋ</translation>
<translation id="4631649115723685955">ਕੈਸ਼ਬੈਕ ਨੂੰ ਲਿੰਕ ਕੀਤਾ ਗਿਆ</translation>
<translation id="4636930964841734540">ਜਾਣਕਾਰੀ</translation>
@@ -978,6 +1004,7 @@
<translation id="4691835149146451662">Architecture-A (ਲਿਫ਼ਾਫ਼ਾ)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">ਪਾਸਾ</translation>
+<translation id="4702656508969495934">ਲਾਈਵ ਸà©à¨°à¨–ੀਆਂ ਦਿਖਣਯੋਗ ਹਨ, ਫੋਕਸ ਕਰਨ ਲਈ ਵਿੰਡੋ ਸਵਿੱਚਰ ਦੀ ਵਰਤੋਂ ਕਰੋ</translation>
<translation id="4708268264240856090">ਤà©à¨¹à¨¾à¨¡à©‡ ਕਨੈਕਸ਼ਨ ਵਿੱਚ ਰà©à¨•à¨¾à¨µà¨Ÿ ਆਈ ਸੀ</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows ਨੈੱਟਵਰਕ ਤਸ਼ਖੀਸ ਚਲਾਇਆ ਜਾ ਰਿਹਾ ਹੈ<ph name="END_LINK" /></translation>
@@ -991,6 +1018,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> ਖੋਜ ਸà©à¨à¨¾à¨…</translation>
<translation id="4742407542027196863">ਪਾਸਵਰਡਾਂ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ ਕਰੋ…</translation>
<translation id="4744603770635761495">à¨à¨—ਜੀਕਿਊਟੇਬਲ ਪਾਥ</translation>
+<translation id="4749011317274908093">ਤà©à¨¸à©€à¨‚ ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਵਿੱਚ ਚਲੇ ਗਠਹੋ</translation>
<translation id="4750917950439032686">ਤà©à¨¹à¨¾à¨¡à©€ ਜਾਣਕਾਰੀ (ਉਦਾਹਰਨ ਲਈ, ਪਾਸਵਰਡ ਜਾਂ ਕà©à¨°à©ˆà¨¡à¨¿à¨Ÿ ਕਾਰਡ ਨੰਬਰ) ਨਿੱਜੀ ਹੈ ਜਦੋਂ ਉਸਨੂੰ ਇਸ ਸਾਈਟ 'ਤੇ ਭੇਜਿਆ ਜਾਂਦਾ ਹੈ।</translation>
<translation id="4756388243121344051">&amp;ਇਤਿਹਾਸ</translation>
<translation id="4758311279753947758">ਸੰਪਰਕ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਕਰੋ</translation>
@@ -1020,6 +1048,8 @@
<translation id="4813512666221746211">ਨੈੱਟਵਰਕ ਗੜਬੜ</translation>
<translation id="4816492930507672669">ਸਫ਼ੇ ਤੇ ਫਿਟ</translation>
<translation id="4819347708020428563">ਕੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਦà©à¨°à¨¿à¨¸à¨¼ ਵਿੱਚ à¨à¨¨à©‹à¨Ÿà©‡à¨¶à¨¨à¨¾à¨‚ ਦਾ ਸੰਪਾਦਨ ਕਰਨਾ ਹੈ?</translation>
+<translation id="4825507807291741242">ਸ਼ਕਤੀਸ਼ਾਲੀ</translation>
+<translation id="4838327282952368871">ਸà©à¨ªà¨¨à¨®à¨ˆ</translation>
<translation id="484462545196658690">ਸਵੈ</translation>
<translation id="4850886885716139402">ਦੇਖੋ</translation>
<translation id="485316830061041779">ਜਰਮਨ</translation>
@@ -1156,6 +1186,7 @@
<translation id="5314967030527622926">ਬà©à©±à¨•à¨²à©ˆà©±à¨Ÿ ਮੇਕਰ</translation>
<translation id="5316812925700871227">ਕਾਉਂਟਰਕਲੌਕਵਾਈਜ ਰੋਟੇਟ ਕਰੋ</translation>
<translation id="5317780077021120954">ਰੱਖਿਅਤ ਕਰੋ</translation>
+<translation id="5321288445143113935">ਵੱਡੀ ਕੀਤੀ ਗਈ</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> ਵਿੱਚੋਂ <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">ਸੰਪਰਕ ਜਾਣਕਾਰੀ ਚà©à¨£à©‹</translation>
<translation id="5327248766486351172">ਨਾਮ</translation>
@@ -1163,11 +1194,13 @@
<translation id="5332219387342487447">ਸ਼ਿਪਿੰਗ ਵਿਧੀ</translation>
<translation id="5333022057423422993">Chrome ਨੂੰ ਉਹ ਪਾਸਵਰਡ ਮਿਲਿਆ ਹੈ ਜਿਸਦੀ ਵਰਤੋਂ ਤà©à¨¸à©€à¨‚ ਹà©à¨£à©‡-ਹà©à¨£à©‡ ਡਾਟਾ ਉਲੰਘਣਾ ਵਿੱਚ ਕੀਤੀ ਹੈ। ਤà©à¨¹à¨¾à¨¡à©‡ ਖਾਤਿਆਂ ਨੂੰ ਸà©à¨°à©±à¨–ਿਅਤ ਕਰਨ ਲਈ, ਅਸੀਂ ਤà©à¨¹à¨¾à¨¡à©‡ ਰੱਖਿਅਤ ਕੀਤੇ ਪਾਸਵਰਡਾਂ ਦੀ ਜਾਂਚ ਕਰਨ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕਰਦੇ ਹਾਂ।</translation>
<translation id="5334013548165032829">ਵੇਰਵੇ ਸਹਿਤ ਸਿਸਟਮ ਲੌਗ</translation>
+<translation id="5334145288572353250">ਕੀ ਪਤਾ ਰੱਖਿਅਤ ਕਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
<translation id="5340250774223869109">à¨à¨ªà¨²à©€à¨•à©‡à¨¶à¨¨ ਨੂੰ ਬਲਾਕ ਕੀਤਾ ਗਿਆ</translation>
<translation id="534295439873310000">NFC ਡੀਵਾਈਸਾਂ</translation>
<translation id="5344579389779391559">ਸ਼ਾਇਦ ਇਸ ਪੰਨੇ 'ਤੇ ਤà©à¨¹à¨¾à¨¡à©‡ ਤੋਂ ਖਰਚਾ ਲਿਆ ਜਾਵੇ</translation>
<translation id="5355557959165512791">ਤà©à¨¸à©€à¨‚ ਇਸ ਵੇਲੇ <ph name="SITE" /> 'ਤੇ ਨਹੀਂ ਜਾ ਸਕਦੇ ਹੋ, ਕਿਉਂਕਿ ਇਸਦਾ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਰੱਦ ਕੀਤਾ ਗਿਆ ਹੈ। ਨੈੱਟਵਰਕ ਗੜਬੜੀਆਂ ਅਤੇ ਹਮਲੇ ਆਮ ਤੌਰ 'ਤੇ ਅਸਥਾਈ ਹà©à©°à¨¦à©‡ ਹਨ, ਇਸਲਈ ਇਹ ਪੰਨਾ ਸ਼ਾਇਦ ਬਾਅਦ ਵਿੱਚ ਠੀਕ ਢੰਗ ਨਾਲ ਕੰਮ ਕਰੇਗਾ।</translation>
<translation id="536296301121032821">ਨੀਤੀ ਸੈਟਿੰਗਾਂ ਸਟੋਰ ਕਰਨ ਵਿੱਚ ਅਸਫਲ</translation>
+<translation id="5363309033720083897">ਤà©à¨¹à¨¾à¨¡à©‡ ਪà©à¨°à¨¸à¨¼à¨¾à¨¸à¨• ਵੱਲੋਂ ਇਜਾਜ਼ਤਸ਼à©à¨¦à¨¾ ਸੀਰੀਅਲ ਪੋਰਟ</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="5386426401304769735">ਇਸ ਸਾਈਟ ਲਈ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਲੜੀ ਵਿੱਚ SHA-1 ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਹਸਤਾਖਰ ਕੀਤਾ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਸ਼ਾਮਲ ਹੈ।</translation>
@@ -1176,6 +1209,7 @@
<translation id="5398772614898833570">ਵਿਗਿਆਪਨ ਬਲੌਕ ਕੀਤੇ ਗà¨</translation>
<translation id="5400836586163650660">ਸਲੇਟੀ</translation>
<translation id="540969355065856584">ਇਹ ਸਰਵਰ ਇਹ ਸਾਬਤ ਨਹੀਂ ਕਰ ਸਕਿਆ ਕਿ ਇਹ <ph name="DOMAIN" /> ਹੈ; ਇਸਦਾ ਸà©à¨°à©±à¨–ਿਆ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਇਸ ਸਮੇਂ ਵੈਧ ਨਹੀਂ ਹੈ। ਇਹ ਇੱਕ ਗਲਤ ਸੰਰੂਪਣ ਕਾਰਨ ਹੋ ਸਕਦਾ ਹੈ ਜਾਂ ਕੋਈ ਹਮਲਾਵਰ ਤà©à¨¹à¨¾à¨¡à©‡ ਕਨੈਕਸ਼ਨ ਨੂੰ ਰਾਹ ਵਿੱਚ ਰੋਕ ਰਿਹਾ ਹੈ।</translation>
+<translation id="541143247543991491">ਕਲਾਊਡ (ਸਿਸਟਮ-ਵਿਆਪਕ)</translation>
<translation id="541416427766103491">ਸਟੈਕਰ 4</translation>
<translation id="5421136146218899937">ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਡਾਟਾ ਹਟਾਓ</translation>
<translation id="5426179911063097041"><ph name="SITE" /> ਤà©à¨¹à¨¾à¨¨à©‚à©° ਸੂਚਨਾਵਾਂ ਭੇਜਣਾ ਚਾਹà©à©°à¨¦à©€ ਹੈ।</translation>
@@ -1189,6 +1223,7 @@
<translation id="5455374756549232013">ਖ਼ਰਾਬ ਨੀਤੀ ਟਾਈਮਸਟੈਂਪ</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" /> ਹੋਰ}other{<ph name="CONTACT_PREVIEW" /> ਅਤੇ <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ਹੋਰ}}</translation>
+<translation id="5463625433003343978">ਡੀਵਾਈਸ ਲੱਭੇ ਜਾ ਰਹੇ ਹਨ...</translation>
<translation id="5469868506864199649">ਇਤਾਲਵੀ</translation>
<translation id="5470861586879999274">ਸੰਪਾਦਨ ਕਰਕੇ &amp;ਮà©à©œ-ਓਹੀ ਕਰੋ</translation>
<translation id="5478437291406423475">B6/C4 (ਲਿਫ਼ਾਫ਼ਾ)</translation>
@@ -1238,7 +1273,6 @@
<translation id="5624120631404540903">ਪਾਸਵਰਡ ਵਿਵਸਥਿਤ ਕਰੋ</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="563324245173044180">ਭਰਮਪੂਰਨ ਸਮੱਗਰੀ ਬਲਾਕ ਕੀਤੀ ਗਈ।</translation>
<translation id="5644090287519800334">ਸਾਈਡ 1 ਚਿੱਤਰ X ਸ਼ਿਫਟ</translation>
@@ -1277,12 +1311,12 @@
<translation id="5785756445106461925">ਅੱਗੇ, ਇਸ ਸਫ਼ੇ ਵਿੱਚ ਦੂਜੇ ਸà©à¨°à©‹à¨¤ ਸ਼ਾਮਲ ਹਨ, ਜੋ ਸà©à¨°à©±à¨–ਿਅਤ ਨਹੀਂ ਹਨ। ਇਹ ਸà©à¨°à©‹à¨¤ ਟà©à¨°à¨¾à¨‚ਜਿਟ ਵਿੱਚ ਹੋਣ ਵੇਲੇ ਦੂਜਿਆਂ ਵੱਲੋਂ ਦੇਖੇ ਜਾ ਸਕਦੇ ਹਨ ਅਤੇ ਸਫ਼ੇ ਦੇ ਰੂਪ ਨੂੰ ਬਦਲਣ ਲਈ ਇੱਕ ਹਮਲਾਵਰ ਵੱਲੋਂ ਸੰਸ਼ੋਧਿਤ ਕੀਤੇ ਜਾ ਸਕਦੇ ਹਨ।</translation>
<translation id="5786044859038896871">ਕੀ ਤà©à¨¸à©€à¨‚ ਆਪਣੀ ਕਾਰਡ ਜਾਣਕਾਰੀ ਭਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
<translation id="578633867165174378">Chrome ਨੂੰ ਉਹ ਪਾਸਵਰਡ ਮਿਲਿਆ ਹੈ ਜਿਸਦੀ ਵਰਤੋਂ ਤà©à¨¸à©€à¨‚ ਹà©à¨£à©‡-ਹà©à¨£à©‡ ਡਾਟਾ ਉਲੰਘਣਾ ਵਿੱਚ ਕੀਤੀ ਹੈ। ਅਸੀਂ ਇਸ ਪਾਸਵਰਡ ਨੂੰ ਹà©à¨£à©‡ ਬਦਲਣ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕਰਦੇ ਹਾਂ।</translation>
-<translation id="5798290721819630480">ਕੀ ਤਬਦੀਲੀਆਂ ਨੂੰ ਖਾਰਜ ਕਰਨਾ ਹੈ?</translation>
<translation id="5803412860119678065">ਕੀ ਤà©à¨¸à©€à¨‚ ਆਪਣਾ <ph name="CARD_DETAIL" /> ਭਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
<translation id="5804241973901381774">ਅਨà©à¨®à¨¤à©€à¨†à¨‚</translation>
<translation id="5804427196348435412">NFC ਡੀਵਾਈਸ ਵਰਤੋ</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> ਵਿੱਚ ਤà©à¨¹à¨¾à¨¡à¨¾ ਕਨੈਕਸ਼ਨ ਕਿਸੇ ਪà©à¨°à¨¾à¨£à¨¾ ਸਿਫ਼ਰ ਸੂਟ ਦਾ ਉਪਯੋਗ ਕਰਕੇ à¨à¨¨à¨•à©à¨°à¨¿à¨ªà¨Ÿ ਕੀਤਾ ਗਿਆ ਹੈ।</translation>
<translation id="5813119285467412249">&amp;ਜੋੜੋ ਨੂੰ ਰੀਡੂ ਕਰੋ</translation>
+<translation id="5817918615728894473">ਜੋੜਾ</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਭà©à¨—ਤਾਨ ਕਰਨ 'ਤੇ ਇਸ ਕਾਰਡ ਤੋਂ ਖਰਚਾ ਲਿਆ ਜਾਵੇਗਾ, ਪਰ ਇਸਦਾ ਅਸਲੀ ਨੰਬਰ ਇਸ ਸਾਈਟ ਨਾਲ ਸਾਂà¨à¨¾ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ। ਵਾਧੂ ਸà©à¨°à©±à¨–ਿਆ ਲਈ, ਅਸਥਾਈ CVC ਸਿਰਜਿਆ ਜਾਵੇਗਾ।}one{ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਭà©à¨—ਤਾਨ ਕਰਨ 'ਤੇ ਚà©à¨£à©‡ ਹੋਠਕਾਰਡ ਤੋਂ ਖਰਚਾ ਲਿਆ ਜਾਵੇਗਾ, ਪਰ ਇਸਦਾ ਅਸਲੀ ਨੰਬਰ ਇਸ ਸਾਈਟ ਨਾਲ ਸਾਂà¨à¨¾ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ। ਵਾਧੂ ਸà©à¨°à©±à¨–ਿਆ ਲਈ, ਅਸਥਾਈ CVC ਸਿਰਜਿਆ ਜਾਵੇਗਾ।}other{ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਭà©à¨—ਤਾਨ ਕਰਨ 'ਤੇ ਚà©à¨£à©‡ ਹੋਠਕਾਰਡਾਂ ਤੋਂ ਖਰਚਾ ਲਿਆ ਜਾਵੇਗਾ, ਪਰ ਇਹਨਾਂ ਦਾ ਅਸਲੀ ਨੰਬਰ ਇਸ ਸਾਈਟ ਨਾਲ ਸਾਂà¨à¨¾ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ। ਵਾਧੂ ਸà©à¨°à©±à¨–ਿਆ ਲਈ, ਅਸਥਾਈ CVC ਸਿਰਜਿਆ ਜਾਵੇਗਾ।}}</translation>
<translation id="5826507051599432481">ਆਮ ਨਾਮ (CN)</translation>
<translation id="5838278095973806738">ਤà©à¨¹à¨¾à¨¨à©‚à©° ਇਸ ਸਾਈਟ 'ਤੇ ਕੋਈ ਵੀ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ (ਉਦਾਹਰਨ ਲਈ, ਪਾਸਵਰਡਾਂ ਜਾਂ ਕà©à¨°à©ˆà¨¡à¨¿à¨Ÿ ਕਾਰਡਾਂ) ਨੂੰ ਦਾਖਲ ਨਹੀਂ ਕਰਨਾ ਚਾਹੀਦਾ ਹੈ, ਕਿਉਂਕਿ ਹਮਲਾਵਰ ਉਸਨੂੰ ਚੋਰੀ ਕਰ ਸਕਦੇ ਹਨ।</translation>
@@ -1290,6 +1324,7 @@
<translation id="5855253129151731373">ਇਸ ਸਾਈਟ ਦਾ ਹੋਸਟਨਾਮ <ph name="LOOKALIKE_DOMAIN" /> ਵਰਗਾ ਲੱਗਦਾ ਹੈ। ਹਮਲਾਵਰ ਕਦੇ-ਕਦਾਈਂ ਡੋਮੇਨ ਨਾਮ ਵਿੱਚ ਮà©à¨¸à¨¼à¨•à¨² ਨਾਲ ਪਤਾ ਲੱਗਣ ਵਾਲੀਆਂ ਨਿੱਕੀਆਂ ਤਬਦੀਲੀਆਂ ਕਰਕੇ ਸਾਈਟਾਂ ਦੀ ਨਕਲ ਤਿਆਰ ਕਰਦੇ ਹਨ।
ਜੇ ਤà©à¨¹à¨¾à¨¨à©‚à©° ਲੱਗਦਾ ਹੈ ਕਿ ਇਹ ਗਲਤੀ ਨਾਲ ਦਿਖਾਇਆ ਗਿਆ ਹੈ ਤਾਂ ਕਿਰਪਾ ਕਰਕੇ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals 'ਤੇ ਜਾਓ।</translation>
+<translation id="5860033963881614850">ਬੰਦ ਕਰੋ</translation>
<translation id="5862579898803147654">ਸਟੈਕਰ 8</translation>
<translation id="5863847714970149516">ਅਗਲੇ ਪੰਨੇ 'ਤੇ ਜਾਣ ਨਾਲ ਤà©à¨¹à¨¾à¨¡à©‡ ਤੋਂ ਖਰਚਾ ਲਿਆ ਜਾ ਸਕਦਾ ਹੈ</translation>
<translation id="5866257070973731571">ਫ਼ੋਨ ਨੰਬਰ ਸ਼ਾਮਲ ਕਰੋ</translation>
@@ -1306,6 +1341,7 @@
<translation id="5913377024445952699">ਸਕà©à¨°à©€à¨¨ ਕੈਪਚਰ ਕਰਨਾ ਰੋਕਿਆ ਗਿਆ</translation>
<translation id="59174027418879706">ਸਮਰਥਿਤ</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 ਵਰਤੋਂ ਵਿੱਚ ਹੈ}one{# ਵਰਤੋਂ ਵਿੱਚ ਹਨ}other{# ਵਰਤੋਂ ਵਿੱਚ ਹਨ}}</translation>
<translation id="5921185718311485855">ਚਾਲੂ</translation>
<translation id="5921639886840618607">ਕੀ ਕਾਰਡ ਨੂੰ Google ਖਾਤੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?</translation>
<translation id="5922853866070715753">ਲਗਭਗ ਹੋ ਗਿਆ</translation>
@@ -1325,6 +1361,7 @@
<translation id="5989320800837274978">ਨਾ ਤਾਂ ਸਥਿਰ ਪà©à¨°à©Œà¨•à¨¸à©€ ਸਰਵਰ ਨਾ ਹੀ .pac ਸਕà©à¨°à¨¿à¨ªà¨Ÿ URL ਨਿਰਦਿਸ਼ਟ ਕੀਤੇ ਗਠਹਨ।</translation>
<translation id="5992691462791905444">ਇੰਜੀਨੀਅਰਿੰਗ Z-ਤਹਿ</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' ਲਈ <ph name="RESULT_COUNT" /> ਨਤੀਜੇ</translation>
+<translation id="6006484371116297560">ਕਲਾਸਿਕ</translation>
<translation id="6008122969617370890">N-ਤੋਂ-1 ਕà©à¨°à¨®</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">ਆਪਣੇ ਪਾਸਵਰਡਾਂ ਦੀ ਜਾਂਚ ਕਰੋ</translation>
@@ -1346,6 +1383,7 @@
<translation id="6045164183059402045">ਇੰਮਪੋਜ਼ਿਸ਼ਨ ਟੈਮਪਲੇਟ</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="6049004884579590341">ਪੂਰੀ ਸਕà©à¨°à©€à¨¨ ਤੋਂ ਬਾਹਰ ਜਾਣ ਲਈ |<ph name="ACCELERATOR" />| ਨੂੰ ਦਬਾਈ ਰੱਖੋ</translation>
<translation id="6049488691372270142">ਪੰਨਾ ਡਿਲੀਵਰੀ</translation>
<translation id="6051221802930200923">ਤà©à¨¸à©€à¨‚ ਇਸ ਵੇਲੇ <ph name="SITE" /> 'ਤੇ ਨਹੀਂ ਜਾ ਸਕਦੇ, ਕਿਉਂਕਿ ਵੈੱਬਸਾਈਟ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਪਿੰਨਿੰਗ ਦੀ ਵਰਤੋਂ ਕਰਦੀ ਹੈ।ਨੈੱਟਵਰਕ ਗੜਬੜੀਆਂ ਅਤੇ ਹਮਲੇ ਆਮ ਤੌਰ 'ਤੇ ਅਸਥਾਈ ਹà©à©°à¨¦à©‡ ਹਨ, ਇਸਲਈ ਇਹ ਪੰਨਾ ਸ਼ਾਇਦ ਬਾਅਦ ਵਿੱਚ ਠੀਕ ਢੰਗ ਨਾਲ ਕੰਮ ਕਰੇਗਾ।</translation>
<translation id="6051898664905071243">ਪੰਨਾ ਗਿਣਤੀ:</translation>
@@ -1362,6 +1400,7 @@
<translation id="610911394827799129">ਤà©à¨¹à¨¾à¨¡à©‡ Google ਖਾਤੇ ਵਿੱਚ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> 'ਤੇ ਬà©à¨°à¨¾à¨Šà©›à¨¿à©°à¨— ਇਤਿਹਾਸ ਦੀਆਂ ਹੋਰ ਕਿਸਮਾਂ ਹੋ ਸਕਦੀਆਂ ਹਨ।</translation>
<translation id="6116338172782435947">ਕਲਿੱਪਬੋਰਡ 'ਤੇ ਕਾਪੀ ਕੀਤੀ ਲਿਖਤ ਅਤੇ ਚਿੱਤਰਾਂ ਨੂੰ ਦੇਖੋ</translation>
<translation id="6120179357481664955">ਕੀ ਤà©à¨¹à¨¾à¨¨à©‚à©° ਆਪਣੀ UPI ਆਈਡੀ ਯਾਦ ਹੈ?</translation>
+<translation id="6123290840358279103">ਆਭਾਸੀ ਕਾਰਡ ਦੇਖੋ</translation>
<translation id="6124432979022149706">Chrome à¨à¨‚ਟਰਪà©à¨°à¨¾à¨ˆà¨œà¨¼ ਕਨੈਕਟਰ</translation>
<translation id="6146055958333702838">ਸਾਰੀਆਂ ਕੇਬਲਾਂ ਦੀ ਜਾਂਚ ਕਰੋ ਅਤੇ ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਵਰਤੇ ਜਾਣ ਵਾਲੇ ਕੋਈ ਵੀ ਰੂਟਰਾਂ, ਮਾਡਮਾਂ ਅਤੇ ਹੋਰ ਡੀਵਾਈਸਾਂ ਨੂੰ ਰੀਬੂਟ ਕਰੋ।</translation>
<translation id="614940544461990577">ਅਜ਼ਮਾਓ:</translation>
@@ -1397,7 +1436,8 @@
<translation id="6289939620939689042">ਪੰਨੇ ਦਾ ਰੰਗ</translation>
<translation id="6290238015253830360">ਤà©à¨¹à¨¾à¨¡à©‡ ਸà©à¨à¨¾à¨ ਗਠਲੇਖ ਇੱਥੇ ਦਿਖਾਈ ਦੇਣਗੇ</translation>
<translation id="6293309776179964942">JIS B5</translation>
-<translation id="6302269476990306341">Chrome ਵਿੱਚ 'Google ਅਸਿਸਟੈਂਟ' ਨੂੰ ਬੰਦ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ</translation>
+<translation id="6295618774959045776">CVC:</translation>
+<translation id="6302269476990306341">Chrome ਵਿੱਚ Google Assistant ਨੂੰ ਬੰਦ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ</translation>
<translation id="6305205051461490394"><ph name="URL" /> ਪਹà©à©°à¨šà¨¯à©‹à¨— ਨਹੀਂ ਹੈ।</translation>
<translation id="6312113039770857350">ਵੈਬਸਫ਼ਾ ਉਪਲਬਧ ਨਹੀਂ ਹੈ</translation>
<translation id="6321917430147971392">ਆਪਣੀਆਂ DNS ਸੈਟਿੰਗਾਂ ਦੀ ਜਾਂਚ ਕਰੋ</translation>
@@ -1422,6 +1462,7 @@
<translation id="6390200185239044127">ਅੱਧੀ Z-ਤਹਿ</translation>
<translation id="6390662030813198813">ਇੰਜੀਨੀਅਰਿੰਗ-E</translation>
<translation id="6393956493820063117">ਪà©à¨°à¨¸à¨¼à¨¾à¨¸à¨• ਨੀਤੀ ਵੱਲੋਂ <ph name="ORIGIN_NAME" /> ਤੋਂ ਇਸ ਟਿਕਾਣੇ 'ਤੇ ਪੇਸਟ ਕਰਨ ਦੀ ਸà©à¨µà¨¿à¨§à¨¾ ਨੂੰ ਬਲਾਕ ਕੀਤਾ ਗਿਆ ਹੈ</translation>
+<translation id="6398765197997659313">ਪੂਰੀ ਸਕà©à¨°à©€à¨¨ ਤੋਂ ਬਾਹਰ ਜਾਓ</translation>
<translation id="6401136357288658127">ਇਹ ਨੀਤੀ ਨਾਪਸੰਦ ਕੀਤੀ ਗਈ। ਤà©à¨¹à¨¾à¨¨à©‚à©° ਇਸਦੀ ਬਜਾਠ<ph name="NEW_POLICY" /> ਨੀਤੀ ਵਰਤਣੀ ਚਾਹੀਦੀ ਹੈ।</translation>
<translation id="6404511346730675251">ਬà©à©±à¨•à¨®à¨¾à¨°à¨• ਸੰਪਾਦਿਤ ਕਰੋ</translation>
<translation id="6406765186087300643">C0 (ਲਿਫ਼ਾਫ਼ਾ)</translation>
@@ -1434,7 +1475,6 @@
<translation id="6428450836711225518">ਆਪਣੇ ਫ਼ੋਨ ਨੰਬਰ ਦੀ ਪà©à¨¸à¨¼à¨Ÿà©€ ਕਰੋ</translation>
<translation id="6433490469411711332">ਸੰਪਰਕ ਜਾਣਕਾਰੀ ਦਾ ਸੰਪਾਦਨ ਕਰੋ</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ਨੇ ਕਨੈਕਟ ਹੋਣ ਤੋਂ ਇਨਕਾਰ ਕੀਤਾ।</translation>
-<translation id="6434309073475700221">ਬਰਖਾਸਤ</translation>
<translation id="6440503408713884761">ਅਣਡਿੱਠ ਕੀਤਾ ਗਿਆ</translation>
<translation id="6443406338865242315">ਤà©à¨¸à©€à¨‚ ਕਿਹੜੀਆਂ à¨à¨•à¨¸à¨Ÿà©ˆà¨‚ਸ਼ਨਾਂ ਅਤੇ ਪਲੱਗਇਨ ਸਥਾਪਤ ਕੀਤੇ ਹੋਠਹਨ</translation>
<translation id="6446163441502663861">Kahu (ਲਿਫ਼ਾਫ਼ਾ)</translation>
@@ -1477,6 +1517,7 @@
<translation id="6624427990725312378">ਸੰਪਰਕ ਜਾਣਕਾਰੀ</translation>
<translation id="6626291197371920147">ਵੈਧ ਕਾਰਡ ਨੰਬਰ ਸ਼ਾਮਲ ਕਰੋ</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ਖੋਜ</translation>
+<translation id="6630043285902923878">USB ਡੀਵਾਈਸ ਲੱਭੇ ਜਾ ਰਹੇ ਹਨ...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ਹਟਾਓ</translation>
@@ -1492,6 +1533,7 @@
<translation id="6671697161687535275">ਕੀ Chromium ਤੋਂ ਫ਼ਾਰਮ ਸੰਬੰਧੀ ਸà©à¨à¨¾à¨… ਨੂੰ ਮਿਟਾਉਣਾ ਹੈ?</translation>
<translation id="6685834062052613830">ਸਾਈਨ-ਆਊਟ ਕਰੋ ਅਤੇ ਸਥਾਪਨਾ ਨੂੰ ਪੂਰਾ ਕਰੋ</translation>
<translation id="6687335167692595844">ਫ਼ੌਂਟ ਆਕਾਰ ਲਈ ਬੇਨਤੀ ਕੀਤੀ ਗਈ</translation>
+<translation id="6688743156324860098">ਅੱਪਡੇਟ ਕਰੋ…</translation>
<translation id="6689249931105087298">ਕਾਲੇ ਬਿੰਦੂ ਨਪੀੜਨ ਨਾਲ ਸੰਬੰਧਿਤ</translation>
<translation id="6689271823431384964">ਤà©à¨¹à¨¾à¨¡à©‡ ਸਾਈਨ-ਇਨ ਹੋਣ ਕਰਕੇ Chrome ਤà©à¨¹à¨¾à¨¡à©‡ ਕਾਰਡਾਂ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ Google ਖਾਤੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨ ਦੀ ਪੇਸ਼ਕਸ਼ ਕਰ ਰਿਹਾ ਹੈ। ਤà©à¨¸à©€à¨‚ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਸ ਵਤੀਰੇ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ। ਕਾਰਡਧਾਰਕ ਦੇ ਨਾਮ ਦੀ ਜਾਣਕਾਰੀ ਤà©à¨¹à¨¾à¨¡à©‡ ਖਾਤੇ ਤੋਂ ਮਿਲਦੀ ਹੈ।</translation>
<translation id="6698381487523150993">ਬਣਾਇਆ:</translation>
@@ -1507,6 +1549,7 @@
<translation id="6744009308914054259">ਕਨੈਕਸ਼ਨ ਦੀ ਉਡੀਕ ਕਰਨ ਵੇਲੇ, ਆਫ਼ਲਾਈਨ ਲੇਖ ਪੜà©à¨¹à¨¨ ਲਈ ਤà©à¨¸à©€à¨‚ ਡਾਊਨਲੋਡ 'ਤੇ ਜਾ ਸਕਦੇ ਹੋ।</translation>
<translation id="6753269504797312559">ਨੀਤੀ ਦਾ ਮà©à©±à¨²</translation>
<translation id="6757797048963528358">ਤà©à¨¹à¨¾à¨¡à©€ ਡੀਵਾਈਸ ਸਲੀਪ ਵਿੱਚ ਚਲੀ ਗਈ।</translation>
+<translation id="6767985426384634228">ਕੀ ਪਤਾ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੋ?</translation>
<translation id="6768213884286397650">Hagaki (ਪੋਸਟਕਾਰਡ)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ਬੈਂਗਣੀ</translation>
@@ -1529,6 +1572,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome ਨੇ ਇਸ ਪੰਨੇ ਨੂੰ ਪੜà©à¨¹à¨¨ ਵਿੱਚ ਵਧੇਰੇ ਆਸਾਨ ਬਣਾਉਣ ਲਈ ਸਰਲੀਕਿਰਤ ਕੀਤਾ। Chrome ਨੇ ਕਿਸੇ ਅਸà©à¨°à©±à¨–ਿਅਤ ਕਨੈਕਸ਼ਨ 'ਤੇ ਮੂਲ ਪੰਨੇ ਨੂੰ ਮà©à©œ-ਪà©à¨°à¨¾à¨ªà¨¤ ਕੀਤਾ।</translation>
<translation id="6891596781022320156">ਨੀਤੀ ਪੱਧਰ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ।</translation>
+<translation id="6895143722905299846">ਆਭਾਸੀ ਨੰਬਰ:</translation>
<translation id="6895330447102777224">ਤà©à¨¹à¨¾à¨¡à©‡ ਕਾਰਡ ਦੀ ਪà©à¨¸à¨¼à¨Ÿà©€ ਹੋ ਗਈ ਹੈ</translation>
<translation id="6897140037006041989">ਵਰਤੋਂਕਾਰ à¨à¨œà©°à¨Ÿ</translation>
<translation id="6898699227549475383">ਕੰਪਨੀ (O)</translation>
@@ -1564,10 +1608,10 @@
<translation id="7004583254764674281">ਕਾਰਡਾਂ ਦੀ ਤੇਜ਼ੀ ਨਾਲ ਤਸਦੀਕ ਕਰਨ ਲਈ Windows Hello ਵਰਤੋ</translation>
<translation id="7006930604109697472">ਫੇਰ ਵੀ ਭੇਜੋ</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ਸੈਟਿੰਗਾਂ ਦਾ ਆਕਾਰ ਬਦਲੋ</translation>
<translation id="7014741021609395734">ਜ਼ੂਮ ਪੱਧਰ</translation>
<translation id="7016992613359344582">ਇਹ ਖਰਚੇ ਇੱਕ-ਵਾਰ ਜਾਂ ਵਾਰ-ਵਾਰ ਲਠਜਾ ਸਕਦੇ ਹਨ ਅਤੇ ਸ਼ਾਇਦ ਇਨà©à¨¹à¨¾à¨‚ ਬਾਰੇ ਸਪੱਸ਼ਟ ਜਾਣਕਾਰੀ ਨਾ ਦਿੱਤੀ ਜਾਵੇ।</translation>
<translation id="7029809446516969842">ਪਾਸਵਰਡ</translation>
+<translation id="7030436163253143341">ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਵੈਧ ਨਹੀਂ ਹੈ</translation>
<translation id="7031646650991750659">ਤà©à¨¸à©€à¨‚ ਕਿਹੜੀਆਂ Google Play à¨à¨ªà¨¾à¨‚ ਸਥਾਪਤ ਕੀਤੀਆਂ ਹੋਈਆਂ ਹਨ</translation>
<translation id="7050187094878475250">ਤà©à¨¸à©€à¨‚ <ph name="DOMAIN" /> ਤੱਕ ਪਹà©à©°à¨šà¨£ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ, ਪਰ ਸਰਵਰ ਨੇ ਇੱਕ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਪੇਸ਼ ਕੀਤਾ, ਜਿਸਦੀ ਪà©à¨°à¨®à¨¾à¨£à¨¿à¨•à¨¤à¨¾ ਮਿਆਦ ਭਰੋਸੇਯੋਗ ਹੋਣ ਲਈ ਬਹà©à¨¤ ਜ਼ਿਆਦਾ ਲੰਮੀ ਹੈ।</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ਇਸ ਕਾਰਡ ਨੂੰ ਫਿਲਹਾਲ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ}one{ਇਸ ਕਾਰਡ ਨੂੰ ਫਿਲਹਾਲ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ}other{ਇਹਨਾਂ ਕਾਰਡਾਂ ਨੂੰ ਫਿਲਹਾਲ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ}}</translation>
@@ -1637,12 +1681,14 @@
<translation id="7300012071106347854">ਕੋਬਾਲਟ ਨੀਲਾ</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">ਵੱਧ</translation>
+<translation id="7305756307268530424">ਹੌਲੀ-ਹੌਲੀ ਸ਼à©à¨°à©‚ ਕਰੋ</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">ਕਨੈਕਸ਼ਨ ਸੰਬੰਧੀ ਮਦਦ</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" ਸੈਕਸ਼ਨ ਲà©à¨•à¨¾à¨“</translation>
<translation id="733354035281974745">ਡੀਵਾਈਸ ਦੇ ਸਥਾਨਕ ਖਾਤੇ ਨੂੰ ਓਵਰਰਾਈਡ</translation>
<translation id="7333654844024768166">ਤà©à¨¸à©€à¨‚ ਹà©à¨£à©‡-ਹà©à¨£à©‡ ਕਿਸੇ ਭਰਮਪੂਰਨ ਸਾਈਟ 'ਤੇ ਆਪਣਾ ਪਾਸਵਰਡ ਦਾਖਲ ਕੀਤਾ ਹੈ। Chromium ਵੱਲੋਂ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ਅਤੇ ਉਹਨਾਂ ਹੋਰ ਸਾਈਟਾਂ 'ਤੇ ਜਾ ਕੇ ਹà©à¨£à©‡ ਆਪਣਾ ਪਾਸਵਰਡ ਬਦਲਣ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ, ਜਿੱਥੇ ਤà©à¨¸à©€à¨‚ ਆਪਣਾ ਪਾਸਵਰਡ ਵਰਤਿਆ ਹੈ।</translation>
<translation id="7334320624316649418">&amp;ਦà©à¨¬à¨¾à¨°à¨¾ ਕà©à¨°à¨® ਦੇਣ ਨੂੰ ਰੀਡੂ ਕਰੋ</translation>
+<translation id="7337248890521463931">ਹੋਰ ਲਾਈਨਾਂ ਦਿਖਾਓ</translation>
<translation id="7337706099755338005">ਤà©à¨¹à¨¾à¨¡à©‡ ਪਲੇਟਫਾਰਮ 'ਤੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।</translation>
<translation id="733923710415886693">ਸਰਵਰ ਦੇ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਦਾ ਖà©à¨²à¨¾à¨¸à¨¾ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਪਾਰਦਰਸ਼ਤਾ ਰਾਹੀਂ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਸੀ।</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1650,6 +1696,7 @@
<translation id="7349430561505560861">A4-ਵਾਧੂ</translation>
<translation id="7353601530677266744">ਕਮਾਂਡ ਲਾਈਨ</translation>
<translation id="7359588939039777303">ਵਿਗਿਆਪਨ ਬਲੌਕ ਕੀਤੇ ਗà¨à¥¤</translation>
+<translation id="7363096869660964304">ਹਾਲਾਂਕਿ, ਤà©à¨¸à©€à¨‚ ਅਦਿੱਖ ਨਹੀਂ ਹà©à©°à¨¦à©‡ ਹੋ। ਇਨਕੋਗਨਿਟੋ ਮੋਡ ਵਰਤਣ 'ਤੇ ਤà©à¨¹à¨¾à¨¡à©€ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਤà©à¨¹à¨¾à¨¡à©‡ ਰà©à¨œà¨¼à¨—ਾਰਦਾਤਾ, ਤà©à¨¹à¨¾à¨¡à©‡ ਇੰਟਰਨੈੱਟ ਸੇਵਾ ਪà©à¨°à¨¦à¨¾à¨¨à¨• ਜਾਂ ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਦੇਖੀਆਂ ਵੈੱਬਸਾਈਟਾਂ ਤੋਂ ਨਹੀਂ ਲà©à¨•à©€ ਰਹਿੰਦੀ ਹੈ।</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Tab ਦਬਾਓ, ਫਿਰ Chrome ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਪਤੇ ਸ਼ਾਮਲ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ ਕਰਨ ਲਈ Enter ਦਬਾਓ</translation>
<translation id="7365849542400970216">ਕੀ ਤà©à¨¸à©€à¨‚ ਆਪਣੇ ਡੀਵਾਈਸ ਦੀ ਵਰਤੋਂ ਬਾਰੇ ਜਾਣਦੇ ਹੋ?</translation>
<translation id="7372973238305370288">ਖੋਜ ਨਤੀਜਾ</translation>
@@ -1660,7 +1707,9 @@
<translation id="7378594059915113390">ਮੀਡੀਆ ਕੰਟਰੋਲ</translation>
<translation id="7378627244592794276">ਨੋਪ</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ਲਾਗੂ ਨਹੀਂ</translation>
<translation id="7390545607259442187">ਕਾਰਡ ਦੀ ਪà©à¨¸à¨¼à¨Ÿà©€ ਕਰੋ</translation>
+<translation id="7392089738299859607">ਪਤਾ ਅੱਪਡੇਟ ਕਰੋ</translation>
<translation id="7399802613464275309">ਸà©à¨°à©±à¨–ਿਆ ਜਾਂਚ</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">ਤà©à¨¹à¨¾à¨¡à¨¾ <ph name="DEVICE_NAME" /> ਪà©à¨°à¨¬à©°à¨§à¨¿à¨¤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ</translation>
@@ -1675,6 +1724,7 @@
&lt;li&gt;ਆਪਣੇ ਕੰਪਿਊਟਰ ਤੋਂ ਸਥਾਈ ਤੌਰ 'ਤੇ ਸਾਫ਼ਟਵੇਅਰ ਕਿਵੇਂ ਹਟਾਇਆ ਜਾਵੇ ਇਹ ਜਾਣਨ ਲਈ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome ਮਦਦ ਕੇਂਦਰ&lt;/a&gt; 'ਤੇ ਜਾਓ
&lt;/ol&gt;</translation>
<translation id="741007362987735528">ਚੌੜਾ-ਫਾਰਮੈਟ</translation>
+<translation id="7410471291937727359">ਪਿਆਰਾ</translation>
<translation id="7416351320495623771">ਪਾਸਵਰਡਾਂ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ ਕਰੋ…</translation>
<translation id="7419106976560586862">ਪà©à¨°à©‹à¨«à¨¾à¨ˆà¨² ਪਾਥ</translation>
<translation id="7437289804838430631">ਸੰਪਰਕ ਜਾਣਕਾਰੀ ਸ਼ਾਮਲ ਕਰੋ</translation>
@@ -1690,7 +1740,7 @@
<translation id="7481312909269577407">ਅੱਗੇ ਭੇਜੋ</translation>
<translation id="7485870689360869515">ਕੋਈ ਡਾਟਾ ਨਹੀਂ ਮਿਲਿਆ।</translation>
<translation id="7495528107193238112">ਇਹ ਸਮੱਗਰੀ ਬਲਾਕ ਕੀਤੀ ਗਈ ਹੈ। ਸਮੱਸਿਆ ਨੂੰ ਠੀਕ ਕਰਨ ਲਈ ਸਾਈਟ ਦੇ ਮਾਲਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।</translation>
-<translation id="7498234416455752244">ਸੰਪਾਦਨ ਕਰਦੇ ਰਹੋ</translation>
+<translation id="7498193950643227031">ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਆਕਾਰ ਬਦਲੇ ਜਾਣ 'ਤੇ ਇਹ ਅਣਕਿਆਸੇ ਢੰਗ ਨਾਲ ਕੰਮ ਕਰੇ। ਤà©à¨¸à©€à¨‚ ਹà©à¨£ <ph name="SETTINGS" /> ਵਿੱਚ à¨à¨ªà¨¾à¨‚ ਦਾ ਆਕਾਰ ਬਦਲਣ ਦੀ ਸਮਰੱਥਾ ਨੂੰ ਸੀਮਤ ਕਰ ਸਕਦੇ ਹੋ।</translation>
<translation id="7503664977220660814">ਤà©à¨¸à©€à¨‚ ਹà©à¨£à©‡-ਹà©à¨£à©‡ ਕਿਸੇ ਭਰਮਪੂਰਨ ਸਾਈਟ 'ਤੇ ਆਪਣਾ ਪਾਸਵਰਡ ਦਾਖਲ ਕੀਤਾ ਹੈ। Chromium ਵੱਲੋਂ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ਅਤੇ ਉਹਨਾਂ ਹੋਰ ਸਾਈਟਾਂ 'ਤੇ ਆਪਣੇ ਰੱਖਿਅਤ ਪਾਸਵਰਡਾਂ ਨੂੰ ਜਾਂਚਣ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਜਿੱਥੇ ਹà©à¨£ ਤà©à¨¸à©€à¨‚ ਇਹ ਪਾਸਵਰਡ ਵਰਤਦੇ ਹੋ।</translation>
<translation id="7508255263130623398">ਵਾਪਸੀ ਸੰਬੰਧੀ ਨੀਤੀ ਡੀਵਾਈਸ ਆਈ.ਡੀ. ਖਾਲੀ ਹੈ ਜਾਂ ਵਰਤਮਾਨ ਡੀਵਾਈਸ ਆਈ.ਡੀ. ਨਾਲ ਮੇਲ ਨਹੀਂ ਖਾਂਦੀ ਹੈ</translation>
<translation id="7508870219247277067">à¨à¨µà©‹à¨•à¨¾à¨¡à©‹ ਹਰਾ</translation>
@@ -1710,6 +1760,7 @@
<translation id="7548892272833184391">ਕਨੈਕਸ਼ਨ ਸੰਬੰਧੀ ਗੜਬੜੀਆਂ ਠੀਕ ਕਰੋ</translation>
<translation id="7549584377607005141">ਇਸ ਵੈੱਬ-ਪੰਨੇ ਲਈ ਉਹ ਡਾਟਾ ਲੋੜੀਂਦਾ ਹੈ ਜੋ ਤà©à¨¸à©€à¨‚ ਡਿਸਪਲੇ ਕਰਨ ਲਈ ਪਹਿਲਾਂ ਦਰਜ ਕੀਤਾ ਸੀ। ਤà©à¨¸à©€à¨‚ ਇਹ ਡਾਟਾ ਦà©à¨¬à¨¾à¨°à¨¾ ਭੇਜ ਸਕਦੇ ਹੋ, ਪਰ ਅਜਿਹਾ ਕਰਕੇ ਤà©à¨¸à©€à¨‚ à¨à¨•à¨¶à¨¨ ਨੂੰ ਦà©à¨¹à¨°à¨¾à¨“ਗੇ ਜੋ ਇਸ ਪੰਨੇ ਵੱਲੋਂ ਪਹਿਲਾਂ ਵੀ ਕਾਰਗà©à¨œà¨¼à¨¾à¨°à©€ ਕੀਤੀ ਗਈ ਹੈ।</translation>
<translation id="7550637293666041147">ਤà©à¨¹à¨¾à¨¡à©‡ ਡੀਵਾਈਸ ਦਾ ਵਰਤੋਂਕਾਰ ਨਾਮ ਅਤੇ Chrome ਵਰਤੋਂਕਾਰ ਨਾਮ</translation>
+<translation id="755279583747225797">ਪਰਖ ਕਿਰਿਆਸ਼ੀਲ ਹੈ</translation>
<translation id="7552846755917812628">ਅੱਗੇ ਦਿੱਤੇ ਨà©à¨•à¨¤à¨¿à¨†à¨‚ ਨੂੰ ਅਜ਼ਮਾਓ:</translation>
<translation id="7554475479213504905">ਰੀਲੋਡ ਕਰੋ ਅਤੇ ਫਿਰ ਵੀ ਦਿਖਾਓ</translation>
<translation id="7554791636758816595">ਨਵੀਂ ਟੈਬ</translation>
@@ -1728,7 +1779,6 @@
<translation id="7610193165460212391">ਵੈਲਯੂ <ph name="VALUE" /> ਰੇਂਜ ਤੋਂ ਬਾਹਰ ਹੈ।</translation>
<translation id="7613889955535752492">ਮਿਆਦ ਸਮਾਪਤ: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Tab ਦਬਾਓ, ਫਿਰ Chrome ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਆਪਣੇ ਪਾਸਵਰਡਾਂ ਨੂੰ ਦੇਖਣ ਅਤੇ ਉਹਨਾਂ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ ਕਰਨ ਲਈ Enter ਦਬਾਓ</translation>
-<translation id="7615602087246926389">ਤà©à¨¹à¨¾à¨¡à©‡ ਕੋਲ ਪਹਿਲਾਂ ਹੀ ਉਹ ਡਾਟਾ ਹੈ ਜੋ ਤà©à¨¹à¨¾à¨¡à©‡ Google ਖਾਤਾ ਪਾਸਵਰਡ ਦਾ ਇੱਕ ਵੱਖ ਵਰਜਨ ਵਰਤਦੇ ਹੋਠਇਨਕà©à¨°à¨¿à¨ªà¨Ÿ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਇਸਨੂੰ ਹੇਠਾਂ ਦਰਜ ਕਰੋ।</translation>
<translation id="7616645509853975347">ਤà©à¨¹à¨¾à¨¡à©‡ ਪà©à¨°à¨¸à¨¼à¨¾à¨¸à¨• ਨੇ ਤà©à¨¹à¨¾à¨¡à©‡ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨° 'ਤੇ Chrome Enterprise Connectors ਨੂੰ ਚਾਲੂ ਕੀਤਾ। ਇਹਨਾਂ ਕਨੈਕਟਰਾਂ ਦੀ ਤà©à¨¹à¨¾à¨¡à©‡ ਕà©à¨ ਡਾਟੇ ਤੱਕ ਪਹà©à©°à¨š ਹੈ।</translation>
<translation id="7619838219691048931">ਆਖਰੀ ਸ਼ੀਟ</translation>
<translation id="762844065391966283">ਇੱਕ ਸਮੇਂ ਵਿੱਚ ਇੱਕ</translation>
@@ -1793,13 +1843,12 @@
<translation id="782886543891417279">ਤà©à¨¹à¨¾à¨¡à©‡ ਵੱਲੋਂ ਵਰਤਿਆ ਜਾ ਰਿਹਾ ਵਾਈ-ਫਾਈ (<ph name="WIFI_NAME" />) ਇਹ ਚਾਹ ਸਕਦਾ ਹੈ ਕਿ ਤà©à¨¸à©€à¨‚ ਇਸਦੇ ਲੌਗ-ਇਨ ਪੰਨੇ 'ਤੇ ਜਾਓ।</translation>
<translation id="7836231406687464395">Postfix (ਲਿਫ਼ਾਫ਼ਾ)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ਕੋਈ ਨਹੀਂ}=1{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">ਜਦਕਿ, ਤà©à¨¸à©€à¨‚ ਅੱਖੋਂ ਓਹਲੇ ਨਹੀਂ ਹੋ। incognito ਵਿੱਚ ਜਾਣਾ ਤà©à¨¹à¨¾à¨¡à©€ ਬà©à¨°à¨¾à¨Šà¨œà¨¼à¨¿à©°à¨— ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ ਰੋਜ਼ਗਾਰਦਾਤੇ, ਤà©à¨¹à¨¾à¨¡à©‡ ਇੰਟਰਨੈੱਟ ਸੇਵਾ ਪà©à¨°à¨¦à¨¾à¨¤à©‡, ਜਾਂ ਜਿਨà©à¨¹à¨¾à¨‚ ਵੈੱਬਸਾਈਟਾਂ 'ਤੇ ਤà©à¨¸à©€à¨‚ ਜਾਂਦੇ ਹੋ ਉਹਨਾਂ ਤੋਂ ਨਹੀਂ ਲà©à¨•à¨¾à¨‰à¨‚ਦਾ ਹੈ।</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ਫ਼ਾਈਲ ਦੀ ਕਿਸਮ ਅਸੋਸੀà¨à¨¶à¨¨à¨¾à¨‚ ਨਾਲ ਫ਼ਾਈਲਾਂ ਖੋਲà©à¨¹à©‹à¥¤</translation>
<translation id="7862185352068345852">ਕੀ ਸਾਈਟ ਛੱਡਣੀ ਹੈ?</translation>
<translation id="7865448901209910068">ਬਿਹਤਰੀਨ ਗਤੀ</translation>
<translation id="7874263914261512992">ਤà©à¨¸à©€à¨‚ ਹà©à¨£à©‡-ਹà©à¨£à©‡ ਕਿਸੇ ਭਰਮਪੂਰਨ ਸਾਈਟ 'ਤੇ ਆਪਣਾ ਪਾਸਵਰਡ ਦਾਖਲ ਕੀਤਾ ਹੈ। Chrome ਵੱਲੋਂ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ਅਤੇ ਉਹਨਾਂ ਹੋਰ ਸਾਈਟਾਂ 'ਤੇ ਆਪਣੇ ਰੱਖਿਅਤ ਪਾਸਵਰਡਾਂ ਨੂੰ ਜਾਂਚਣ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ ਜਿੱਥੇ ਹà©à¨£ ਤà©à¨¸à©€à¨‚ ਇਹ ਪਾਸਵਰਡ ਵਰਤਦੇ ਹੋ।</translation>
<translation id="7878562273885520351">ਸ਼ਾਇਦ ਤà©à¨¹à¨¾à¨¡à©‡ ਪਾਸਵਰਡ ਨਾਲ ਛੇੜਛਾੜ ਹੋਈ</translation>
+<translation id="7880146494886811634">ਪਤਾ ਰੱਖਿਅਤ ਕਰੋ</translation>
<translation id="7882421473871500483">ਭੂਰਾ</translation>
<translation id="7887683347370398519">ਆਪਣੇ CVC ਦੀ ਜਾਂਚ ਕਰੋ ਅਤੇ ਦà©à¨¬à¨¾à¨°à¨¾ ਕੋਸ਼ਿਸ਼ ਕਰੋ</translation>
<translation id="7887885240995164102">ਤਸਵੀਰ-ਵਿੱਚ-ਤਸਵੀਰ ਦਾਖਲ ਕਰੋ</translation>
@@ -1807,6 +1856,7 @@
<translation id="7894280532028510793">ਜੇ ਸ਼ਬਦ-ਜੋੜ ਸਹੀ ਹੈ, ਤਾਂ <ph name="BEGIN_LINK" />ਨੈੱਟਵਰਕ ਤਸ਼ਖੀਸਾਂ ਨੂੰ ਚਲਾ ਕੇ ਦੇਖੋ<ph name="END_LINK" />।</translation>
<translation id="7904208859782148177">C3 (ਲਿਫ਼ਾਫ਼ਾ)</translation>
<translation id="7931318309563332511">ਅਗਿਆਤ</translation>
+<translation id="793209273132572360">ਕੀ ਪਤਾ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹà©à©°à¨¦à©‡ ਹੈ?</translation>
<translation id="7932579305932748336">ਕੋਟ</translation>
<translation id="79338296614623784">ਕੋਈ ਵੈਧ ਫ਼ੋਨ ਨੰਬਰ ਦਾਖਲ ਕਰੋ</translation>
<translation id="7934052535022478634">ਭà©à¨—ਤਾਨ ਪੂਰਾ ਹੋਇਆ</translation>
@@ -1877,6 +1927,7 @@
<translation id="8175796834047840627">ਤà©à¨¹à¨¾à¨¡à©‡ ਸਾਈਨ-ਇਨ ਹੋਣ ਕਰਕੇ Chrome ਤà©à¨¹à¨¾à¨¡à©‡ ਕਾਰਡਾਂ ਨੂੰ ਤà©à¨¹à¨¾à¨¡à©‡ Google ਖਾਤੇ ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨ ਦੀ ਪੇਸ਼ਕਸ਼ ਕਰ ਰਿਹਾ ਹੈ। ਤà©à¨¸à©€à¨‚ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਸ ਵਤੀਰੇ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।</translation>
<translation id="8176440868214972690">ਇਸ ਡੀਵਾਈਸ ਦੇ ਪà©à¨°à¨¶à¨¾à¨¸à¨• ਨੇ ਅੱਗੇ ਦਿੱਤੀਆਂ ਵੈੱਬਸਾਈਟਾਂ ਨੂੰ ਕà©à¨ ਜਾਣਕਾਰੀ ਭੇਜੀ ਹੈ, ਜਿਵੇਂ ਸੈਟਿੰਗਾਂ ਜਾਂ ਨੀਤੀਆਂ।</translation>
<translation id="8184538546369750125">ਗਲੋਬਲ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈਟਿੰਗ ਵਰਤੋ (ਇਜਾਜ਼ਤ ਦਿਓ)</translation>
+<translation id="8193086767630290324">ਗà©à¨ªà¨¤ ਤੌਰ 'ਤੇ ਫਲੈਗ ਕੀਤੇ ਗਠਡਾਟਾ 'ਤੇ ਕਾਰਵਾਈ ਕੀਤੀ ਗਈ</translation>
<translation id="8194797478851900357">&amp;ਮੂਵ ਨੂੰ ਅਨਡੂ ਕਰੋ</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" ਨਾਲ à¨à¨•à¨¸à¨Ÿà©ˆà¨‚ਸ਼ਨ ਲਈ ਅਵੈਧ ਅੱਪਡੇਟ URL</translation>
<translation id="8202097416529803614">ਆਰਡਰ ਸਾਰਾਂਸ਼</translation>
@@ -1899,6 +1950,7 @@
<translation id="8249296373107784235">ਰੋਕੋ</translation>
<translation id="8249320324621329438">ਪਿਛਲੀ ਵਾਰ ਪà©à¨°à¨¾à¨ªà¨¤ ਕੀਤੇ:</translation>
<translation id="8253091569723639551">ਬਿਲਿੰਗ ਪਤਾ ਲੋੜੀਂਦਾ ਹੈ</translation>
+<translation id="8257387598443225809">ਇਹ à¨à¨ª ਮੋਬਾਈਲ ਲਈ ਤਿਆਰ ਕੀਤੀ ਗਈ ਹੈ</translation>
<translation id="825929999321470778">ਸਾਰੇ ਰੱਖਿਅਤ ਕੀਤੇ ਪਾਸਵਰਡ ਦਿਖਾਓ</translation>
<translation id="8261506727792406068">ਮਿਟਾਓ</translation>
<translation id="8262952874573525464">ਹੇਠਾਂ ਕਿਨਾਰੇ ਤੋਂ ਸਿਲਾਈ</translation>
@@ -2022,7 +2074,6 @@
<translation id="8719528812645237045">ਉੱਪਰ ਇੱਕ ਤੋਂ ਵੱਧ ਮੋਰੀਆਂ</translation>
<translation id="8725066075913043281">ਦà©à¨¬à¨¾à¨°à¨¾ ਕੋਸ਼ਿਸ਼ ਕਰੋ</translation>
<translation id="8726549941689275341">ਪੰਨੇ ਦਾ ਆਕਾਰ:</translation>
-<translation id="8728672262656704056">ਤà©à¨¸à©€à¨‚ ਗà©à©°à¨®à¨¨à¨¾à¨® ਮੋਡ ਵਿੱਚ ਚਲੇ ਗਠਹੋ</translation>
<translation id="8730621377337864115">ਹੋ ਗਿਆ</translation>
<translation id="8731544501227493793">'ਪਾਸਵਰਡ ਬਟਨ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ ਕਰੋ' ਬਟਨ, Chrome ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਆਪਣੇ ਪਾਸਵਰਡ ਦੇਖਣ ਅਤੇ ਉਹਨਾਂ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ ਕਰਨ ਲਈ Enter ਦਬਾਓ</translation>
<translation id="8734529307927223492">ਤà©à¨¹à¨¾à¨¡à©‡ <ph name="DEVICE_TYPE" /> ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ <ph name="MANAGER" /> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ</translation>
@@ -2099,6 +2150,7 @@
<translation id="9020542370529661692">ਇਸ ਸਫ਼ੇ ਦਾ ਅਨà©à¨µà¨¾à¨¦ <ph name="TARGET_LANGUAGE" /> ਵਿੱਚ ਕੀਤਾ ਗਿਆ ਹੈ।</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ਅਵੈਧ)</translation>
+<translation id="9030265603405983977">ਮੋਨੋਕਰੋਮ</translation>
<translation id="9035022520814077154">ਸà©à¨°à©±à¨–ਿਆ ਗੜਬੜ</translation>
<translation id="9038649477754266430">ਪੰਨਿਆਂ ਨੂੰ ਵਧੇਰੇ ਤੇਜ਼ੀ ਨਾਲ ਲੋਡ ਕਰਨ ਲਈ ਅਨà©à¨®à¨¾à¨¨ ਸੇਵਾ ਦੀ ਵਰਤੋਂ ਕਰੋ</translation>
<translation id="9039213469156557790">ਅੱਗੇ, ਇਸ ਸਫ਼ੇ ਵਿੱਚ ਦੂਜੇ ਸà©à¨°à©‹à¨¤ ਸ਼ਾਮਲ ਹਨ, ਜੋ ਸà©à¨°à©±à¨–ਿਅਤ ਨਹੀਂ ਹਨ। ਇਹ ਸà©à¨°à©‹à¨¤ ਟà©à¨°à¨¾à¨‚ਜਿਟ ਵਿੱਚ ਹੋਣ ਵੇਲੇ ਦੂਜਿਆਂ ਵੱਲੋਂ ਦੇਖੇ ਜਾ ਸਕਦੇ ਹਨ ਅਤੇ ਸਫ਼ੇ ਦੇ ਵਿਹਾਰ ਨੂੰ ਬਦਲਣ ਲਈ ਇੱਕ ਹਮਲਾਵਰ ਵੱਲੋਂ ਸੰਸ਼ੋਧਿਤ ਕੀਤੇ ਜਾ ਸਕਦੇ ਹਨ।</translation>
@@ -2122,6 +2174,7 @@
<translation id="91108059142052966">ਗà©à¨ªà¨¤ ਸਮੱਗਰੀ ਦੇ ਦਿਖਣਯੋਗ ਹੋਣ 'ਤੇ ਪà©à¨°à¨¸à¨¼à¨¾à¨¸à¨• ਨੀਤੀ <ph name="APPLICATION_TITLE" /> ਨਾਲ ਸਕà©à¨°à©€à¨¨ ਸਾਂà¨à¨¾à¨•à¨°à¨¨ ਬੰਦ ਕਰ ਦਿੰਦੀ ਹੈ</translation>
<translation id="9114524666733003316">ਕਾਰਡ ਦੀ ਪà©à¨¸à¨¼à¨Ÿà©€ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ...</translation>
<translation id="9114581008513152754">ਇਹ ਬà©à¨°à¨¾à¨Šà©›à¨° ਕਿਸੇ ਕੰਪਨੀ ਜਾਂ ਹੋਰ ਸੰਸਥਾ ਵੱਲੋਂ ਪà©à¨°à¨¬à©°à¨§à¨¿à¨¤ ਨਹੀਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਸ ਡੀਵਾਈਸ ਦੀ ਸਰਗਰਮੀ ਨੂੰ Chrome ਦੇ ਬਾਹਰ ਪà©à¨°à¨¬à©°à¨§à¨¿à¨¤ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। <ph name="BEGIN_LINK" />ਹੋਰ ਜਾਣੋ<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ਤਾਜ਼ਾ</translation>
<translation id="9119042192571987207">ਅੱਪਲੋਡ ਕੀਤੀ ਗਈ</translation>
<translation id="9128016270925453879">ਨੀਤੀਆਂ ਲੋਡ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ</translation>
<translation id="9128870381267983090">ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕਰੋ</translation>
@@ -2140,6 +2193,7 @@
<translation id="9170848237812810038">&amp;ਅਨਡੂ</translation>
<translation id="9171296965991013597">ਕੀ à¨à¨ª ਛੱਡਣੀ ਹੈ?</translation>
<translation id="9173282814238175921">ਇਕਹਿਰਾ ਦਸਤਾਵੇਜ਼/ਨਵੀਂ ਸ਼ੀਟ</translation>
+<translation id="9173995187295789444">ਬਲੂਟà©à©±à¨¥ ਡੀਵਾਈਸਾਂ ਲਈ ਸਕੈਨ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ...</translation>
<translation id="917450738466192189">ਸਰਵਰ ਦਾ ਪà©à¨°à¨®à¨¾à¨£-ਪੱਤਰ ਅਵੈਧ ਹੈ।</translation>
<translation id="9174917557437862841">ਟੈਬ ਬਦਲਣ ਦਾ ਬਟਨ, ਇਸ ਟੈਬ 'ਤੇ ਜਾਣ ਲਈ à¨à¨‚ਟਰ ਦਬਾਓ</translation>
<translation id="9179703756951298733">Chrome ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਆਪਣੇ ਭà©à¨—ਤਾਨਾਂ ਅਤੇ ਕà©à¨°à©ˆà¨¡à¨¿à¨Ÿ ਕਾਰਡ ਸੰਬੰਧੀ ਜਾਣਕਾਰੀ ਦਾ ਪà©à¨°à¨¬à©°à¨§à¨¨ ਕਰੋ</translation>
diff --git a/chromium/components/strings/components_strings_pl.xtb b/chromium/components/strings/components_strings_pl.xtb
index 6a8586bc3cc..b03b3f712eb 100644
--- a/chromium/components/strings/components_strings_pl.xtb
+++ b/chromium/components/strings/components_strings_pl.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Po zaznaczeniu tej opcji Chrome będzie zapisywać kopię danych karty na tym urządzeniu, by szybciej wypełniać formularze.</translation>
<translation id="1110994991967754504">Wybierz uprawnienia dla: <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Cofnij zmianę kolejności</translation>
+<translation id="1123753900084781868">Napisy na żywo nie są teraz dostępne</translation>
<translation id="1125573121925420732">Ostrzeżenia mogą pojawiać się często, dopóki strony internetowe nie zaktualizują swoich zabezpieczeń. Wkrótce powinno się to poprawić.</translation>
<translation id="112840717907525620">Pamięć podręczna zasad: OK</translation>
<translation id="1130564665089811311">Przycisk tłumaczenia strony. Naciśnij Enter, by Tłumacz Google przetłumaczył tę stronę.</translation>
@@ -74,6 +75,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="1240347957665416060">Nazwa urzÄ…dzenia</translation>
<translation id="124116460088058876">Więcej języków</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Pogrubienie</translation>
<translation id="1250759482327835220">Aby następnym razem zapłacić szybciej, zapisz kartę oraz imię, nazwisko i adres rozliczeniowy na swoim koncie Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (zsynchronizowane)</translation>
<translation id="1256368399071562588">&lt;p&gt;Jeśli nie udaje się otworzyć strony, spróbuj wykonać najpierw te czynności, aby rozwiązać problem:&lt;/p&gt;
@@ -156,6 +158,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="1476595624592550506">Zmień hasło</translation>
<translation id="1484290072879560759">Wybierz adres wysyłki</translation>
<translation id="1492194039220927094">Przekazywanie zasad w trybie push:</translation>
+<translation id="1495677929897281669">Wróć do karty</translation>
<translation id="1501859676467574491">Pokaż karty z konta Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Ten komunikat pojawia się, jeśli do połączenia z internetem wymagane jest zalogowanie się w portalu Wi-Fi.&lt;/p&gt;
&lt;p&gt;Aby naprawić błąd, kliknij &lt;strong&gt;Połącz&lt;/strong&gt; na stronie, którą chcesz otworzyć.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="1532118530259321453">Komunikat z bieżącej strony</translation>
<translation id="153384715582417236">Na razie to wszystko</translation>
<translation id="1536390784834419204">Przetłumacz stronę</translation>
+<translation id="1539840569003678498">Wysłanie raportu:</translation>
<translation id="154408704832528245">Wybierz adres dostawy</translation>
<translation id="1549470594296187301">Aby można było korzystać z tej funkcji, musi być włączony JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="1682696192498422849">Najpierw krótsza krawędź</translation>
<translation id="168693727862418163">Nie udało się zweryfikować tej wartości zasady względem jej schematu. Będzie ona ignorowana.</translation>
<translation id="168841957122794586">Certyfikat serwera ma słaby klucz kryptograficzny.</translation>
+<translation id="1696290444144917273">Zobacz dane karty wirtualnej</translation>
<translation id="1697532407822776718">Wszystko gotowe.</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Ten serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa przypuszczalnie zacznie obowiązywać od jutra. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia.}few{Ten serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa przypuszczalnie zacznie obowiązywać za # dni. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia.}many{Ten serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa przypuszczalnie zacznie obowiązywać za # dni. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia.}other{Ten serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa przypuszczalnie zacznie obowiązywać za # dnia. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia.}}</translation>
<translation id="1710259589646384581">System operacyjny</translation>
+<translation id="1711234383449478798">Zignorowano, ponieważ zasada <ph name="POLICY_NAME" /> nie została ustawiona na <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> chce na stałe przechowywać dane na Twoim komputerze lokalnym</translation>
<translation id="1713628304598226412">Taca 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Zestaw tac odbiorczych 3</translation>
<translation id="1718029547804390981">Dokument jest za duży i nie można dodawać do niego adnotacji</translation>
<translation id="1721424275792716183">* Pole jest wymagane</translation>
+<translation id="1727613060316725209">Certyfikat jest ważny</translation>
<translation id="1727741090716970331">Dodaj prawidłowy numer karty</translation>
<translation id="1728677426644403582">Przeglądasz źródło strony internetowej</translation>
<translation id="173080396488393970">Ten typ karty nie jest obsługiwany</translation>
@@ -242,7 +249,6 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Uruchom DiagnostykÄ™ sieci systemu Windows<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">Serwer <ph name="ORIGIN" />, z którym chcesz się połączyć, ma ustawiony nagłówek z wymaganiem, by do wszystkich kierowanych do niego żądań stosować zasadę dotyczącą źródła. Jednak ten nagłówek ma nieprawidłowy format, przez co przeglądarka nie może zrealizować Twojego żądania dotyczącego strony <ph name="SITE" />. Zasady dotyczące źródła mogą stosować operatorzy stron internetowych, by skonfigurować zabezpieczenia i inne właściwości strony.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Zaktualizuj swoje hasło synchronizacji.</translation>
<translation id="1787142507584202372">Tutaj pojawiajÄ… siÄ™ otwarte karty</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Dostępnych jest wiele czynności. Naciskaj Tab, by się między nimi przełączać.</translation>
@@ -275,6 +281,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="1919345977826869612">Reklamy</translation>
<translation id="1919367280705858090">Uzyskiwanie pomocy w przypadku konkretnego komunikatu o błędzie</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Brak}=1{1 witryna}few{# witryny}many{# witryn}other{# witryny}}</translation>
+<translation id="1924727005275031552">Nowy</translation>
<translation id="1945968466830820669">Możesz stracić dostęp do swojego konta organizacji lub paść ofiarą kradzieży tożsamości. Chromium zaleca natychmiastową zmianę hasła.</translation>
<translation id="1947454675006758438">Zszywka w prawym górnym rogu</translation>
<translation id="1958218078413065209">Twój najwyższy wynik to: <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="2042213636306070719">Taca 7</translation>
<translation id="204357726431741734">Zaloguj się, by używać haseł zapisanych na Twoim koncie Google</translation>
<translation id="2053111141626950936">Strony w tym języku (<ph name="LANGUAGE" />) nie będą tłumaczone.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Gdy ta opcja jest włączona i ma stan aktywny, Chrome znajduje dużą grupę osób (kohortę), której aktywność związana z przeglądaniem jest najbardziej podobna do Twojej. Reklamodawcy mogą wybierać reklamy dla grupy, a Twoja aktywność związana z przeglądaniem pozostaje prywatna i jest przechowywana tylko na Twoim urządzeniu. Grupa, do której należysz, jest codziennie aktualizowana.}=1{Gdy ta opcja jest włączona i ma stan aktywny, Chrome znajduje dużą grupę osób (kohortę), której aktywność związana z przeglądaniem jest najbardziej podobna do Twojej. Reklamodawcy mogą wybierać reklamy dla grupy, a Twoja aktywność związana z przeglądaniem pozostaje prywatna i jest przechowywana tylko na Twoim urządzeniu. Grupa, do której należysz, jest codziennie aktualizowana.}few{Gdy ta opcja jest włączona i ma stan aktywny, Chrome znajduje dużą grupę osób (kohortę), której aktywność związana z przeglądaniem jest najbardziej podobna do Twojej. Reklamodawcy mogą wybierać reklamy dla grupy, a Twoja aktywność związana z przeglądaniem pozostaje prywatna i jest przechowywana tylko na Twoim urządzeniu. Grupa, do której należysz, jest aktualizowana co {NUM_DAYS} dni.}many{Gdy ta opcja jest włączona i ma stan aktywny, Chrome znajduje dużą grupę osób (kohortę), której aktywność związana z przeglądaniem jest najbardziej podobna do Twojej. Reklamodawcy mogą wybierać reklamy dla grupy, a Twoja aktywność związana z przeglądaniem pozostaje prywatna i jest przechowywana tylko na Twoim urządzeniu. Grupa, do której należysz, jest aktualizowana co {NUM_DAYS} dni.}other{Gdy ta opcja jest włączona i ma stan aktywny, Chrome znajduje dużą grupę osób (kohortę), której aktywność związana z przeglądaniem jest najbardziej podobna do Twojej. Reklamodawcy mogą wybierać reklamy dla grupy, a Twoja aktywność związana z przeglądaniem pozostaje prywatna i jest przechowywana tylko na Twoim urządzeniu. Grupa, do której należysz, jest aktualizowana co {NUM_DAYS} dnia.}}</translation>
<translation id="2053553514270667976">Kod pocztowy</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 podpowiedź}few{# podpowiedzi}many{# podpowiedzi}other{# podpowiedzi}}</translation>
<translation id="2071692954027939183">Powiadomienia zostały automatycznie zablokowane, bo zazwyczaj na nie nie zezwalasz</translation>
<translation id="2079545284768500474">Cofnij</translation>
<translation id="20817612488360358">Skonfigurowano używanie systemowych ustawień proxy, ale podano też jawną konfigurację proxy.</translation>
<translation id="2082238445998314030">Wynik <ph name="RESULT_NUMBER" /> z <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Zapisz…</translation>
<translation id="2088086323192747268">Przycisk zarządzania synchronizacją; aby zarządzać w ustawieniach Chrome danymi, które mają być synchronizowane, naciśnij Enter</translation>
<translation id="2091887806945687916">Dźwięk</translation>
<translation id="2094505752054353250">Niewłaściwa domena</translation>
@@ -375,6 +384,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="2317259163369394535"><ph name="DOMAIN" /> wymaga nazwy użytkownika i hasła.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, ważna do <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Ustawienie kontrolowane przez administratora</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> chce się sparować</translation>
<translation id="2344028582131185878">Pobieranie automatyczne</translation>
<translation id="2346319942568447007">Skopiowany obraz</translation>
<translation id="2354001756790975382">Inne zakładki</translation>
@@ -382,8 +392,10 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="2355395290879513365">Osoby dokonujące ataków mogą widzieć te same obrazy w witrynie co Ty i zmodyfikować je, by Cię oszukać.</translation>
<translation id="2356070529366658676">Pytaj</translation>
<translation id="2357481397660644965">Twoim urządzeniem zarządza <ph name="DEVICE_MANAGER" />, a Twoim kontem – <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Za mniej niż 1 dzień}=1{Za 1 dzień}few{Za {NUM_DAYS} dni}many{Za {NUM_DAYS} dni}other{Za {NUM_DAYS} dnia}}</translation>
<translation id="2359629602545592467">Różne</translation>
<translation id="2359808026110333948">Dalej</translation>
+<translation id="2359961752320758691">Zastosowano numer karty wirtualnej.</translation>
<translation id="2367567093518048410">Poziom</translation>
<translation id="2372464001869762664">Po potwierdzeniu dane karty z Twojego konta Google zostaną udostępnione tej stronie. Znajdź kod CVC w szczegółach konta Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="239429038616798445">Ta metoda wysyłki jest niedostępna. Wybierz inną.</translation>
<translation id="2396249848217231973">&amp;Cofnij usunięcie</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Stary</translation>
<translation id="2413528052993050574">Ten serwer nie mógł udowodnić, że należy do <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa mógł zostać odwołany. Może to być spowodowane błędną konfiguracją lub przechwyceniem połączenia przez atakującego.</translation>
<translation id="2414886740292270097">Ciemny</translation>
<translation id="2438874542388153331">Cztery otwory po prawej</translation>
@@ -421,10 +434,10 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="2521385132275182522">Zszywka w prawym dolnym rogu</translation>
<translation id="2523886232349826891">Zapisana tylko na tym urzÄ…dzeniu</translation>
<translation id="2524461107774643265">Dodaj więcej informacji</translation>
-<translation id="2526590354069164005">Pulpit</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{i jeszcze 1}few{i jeszcze #}many{i jeszcze #}other{i jeszcze #}}</translation>
<translation id="2536110899380797252">Dodaj adres</translation>
<translation id="2539524384386349900">Wykrywaj</translation>
+<translation id="2541219929084442027">Po zamknięciu wszystkich kart incognito wyświetlane na nich strony nie pozostawią żadnych śladów w historii przeglądarki, magazynie plików cookie ani historii wyszukiwania. Pobrane pliki i utworzone zakładki zostaną jednak zachowane.</translation>
<translation id="2544644783021658368">Pojedynczy dokument</translation>
<translation id="254947805923345898">Wartość zasady jest nieprawidłowa.</translation>
<translation id="255002559098805027">Serwer <ph name="HOST_NAME" /> wysłał nieprawidłową odpowiedź.</translation>
@@ -444,6 +457,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="2629325967560697240">Aby korzystać z najwyższego poziomu zabezpieczeń Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />włącz silniejszą ochronę<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Nie udało się znaleźć adresu IP serwera ze stroną <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Stan:</translation>
+<translation id="264810637653812429">Nie znaleziono zgodnych urządzeń.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. Naciśnij Tab, a potem Enter, by wyczyścić historię przeglądania, pliki cookie, pamięć podręczną i inne dane w ustawieniach Chrome.</translation>
<translation id="2650446666397867134">Odmówiono dostępu do pliku</translation>
@@ -490,6 +504,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<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="2807052079800581569">Pozycja Y obrazu</translation>
+<translation id="2820957248982571256">Skanuję…</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>
@@ -497,6 +512,8 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="2850739647070081192">Invite (koperta)</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="2859806420264540918">Na tej stronie wyświetlają się uciążliwe lub wprowadzające w błąd reklamy.</translation>
+<translation id="287596039013813457">Przyjazny</translation>
+<translation id="2876489322757410363">Opuszczasz tryb incognito, aby zapłacić w aplikacji zewnętrznej. Czy chcesz kontynuować?</translation>
<translation id="2878197950673342043">Składanie krzyżowe</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Rozmieszczenie okien</translation>
@@ -546,7 +563,6 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="3060227939791841287">C9 (koperta)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />; aby uruchomić kontrolę zabezpieczeń w ustawieniach Chrome, naciśnij Tab, a potem Enter</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>
<translation id="306573536155379004">Gra się rozpoczęła.</translation>
<translation id="3080254622891793721">Grafika</translation>
<translation id="3086579638707268289">Twoja aktywność w internecie jest monitorowana</translation>
@@ -569,7 +585,6 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="315504272643575312">Tym kontem zarzÄ…dza <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Przywróć</translation>
<translation id="3162559335345991374">Sieć Wi-Fi, której używasz, może wymagać otwarcia strony logowania.</translation>
-<translation id="3167968892399408617">Po zamknięciu wszystkich kart incognito wyświetlane na nich strony nie pozostawią żadnych śladów w historii przeglądarki, magazynie plików cookie ani historii wyszukiwania. Pobrane pliki i utworzone zakładki zostaną jednak zachowane.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Wyspa</translation>
<translation id="3176929007561373547">Sprawdź ustawienia serwera proxy lub skontaktuj się z administratorem sieci,
@@ -595,10 +610,12 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<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="3249845759089040423">Dynamiczny</translation>
<translation id="3252266817569339921">Francuski</translation>
<translation id="3266793032086590337">Wartość (konflikt)</translation>
<translation id="3268451620468152448">Otwarte karty</translation>
<translation id="3270847123878663523">&amp;Cofnij zmianę kolejności</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> chce się połączyć</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Twoja organizacja, <ph name="ENROLLMENT_DOMAIN" />, wysłała do tych witryn pewne informacje, takie jak ustawienia lub zasady.</translation>
<translation id="3282497668470633863">Dodaj imiÄ™ i nazwisko na karcie</translation>
@@ -651,6 +668,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="3428151540071562330">Co najmniej jeden identyfikator URI szablonu serwera DnsOverHttpsTemplates jest nieprawidłowy i nie zostanie użyty.</translation>
<translation id="3431636764301398940">Zapisz tÄ™ kartÄ™ na tym urzÄ…dzeniu</translation>
<translation id="3432601291244612633">Zamknij stronÄ™</translation>
+<translation id="3435738964857648380">Bezpieczeństwo</translation>
<translation id="3435896845095436175">WÅ‚Ä…cz</translation>
<translation id="3438829137925142401">Użyj haseł zapisanych na koncie Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -693,7 +711,10 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="3584299510153766161">Dwa otwory na dole</translation>
<translation id="3586931643579894722">Ukryj szczegóły</translation>
<translation id="3587738293690942763">Åšredni</translation>
+<translation id="3590643883886679995">Dane logowania pozostaną zapisane na tym urządzeniu po wyjściu z trybu incognito.</translation>
+<translation id="359126217934908072">MiesiÄ…c/rok:</translation>
<translation id="3592413004129370115">Italian (koperta)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Możesz zresetować grupę w dowolnym momencie. Dołączenie do nowej grupy trwa około 1 dnia.}=1{Możesz zresetować grupę w dowolnym momencie. Dołączenie do nowej grupy trwa około 1 dnia.}few{Możesz zresetować grupę w dowolnym momencie. Dołączenie do nowej grupy trwa około {NUM_DAYS} dni.}many{Możesz zresetować grupę w dowolnym momencie. Dołączenie do nowej grupy trwa około {NUM_DAYS} dni.}other{Możesz zresetować grupę w dowolnym momencie. Dołączenie do nowej grupy trwa około {NUM_DAYS} dnia.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplikacja zablokowana przez administratora</translation>
<translation id="3608932978122581043">Orientacja podajnika</translation>
@@ -702,13 +723,13 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="3615877443314183785">Wpisz prawidłową datę ważności</translation>
<translation id="36224234498066874">Wyczyść dane przeglądania...</translation>
<translation id="362276910939193118">Wyświetl całą historię</translation>
-<translation id="3625635938337243871">Dane logowania będą przechowywane na tym urządzeniu po wyjściu z trybu incognito.</translation>
<translation id="3630155396527302611">Jeśli ten program jest już na liście programów mogących korzystać z sieci,
spróbuj go z niej usunąć i dodać ponownie.</translation>
<translation id="3630699740441428070">Administratorzy tego urządzenia, którzy skonfigurowali używane przez Ciebie połączenie sieciowe, mogą zobaczyć Twój ruch sieciowy, w tym strony, na które wchodzisz.</translation>
<translation id="3631244953324577188">Biometria</translation>
<translation id="3633738897356909127">Przycisk aktualizacji Chrome. Naciśnij Enter, by zaktualizować przeglądarkę Chrome z poziomu jej ustawień.</translation>
<translation id="3634530185120165534">Taca 5</translation>
+<translation id="3637662659967048211">Zapisz na koncie Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplikacja:</translation>
<translation id="3650584904733503804">Weryfikacja powiodła się</translation>
@@ -749,6 +770,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="3781428340399460090">Ciepłoróżowy</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Lista urządzeń</translation>
+<translation id="3787675388804467730">Numer karty wirtualnej</translation>
<translation id="3787705759683870569">Wygasa: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Rozmiar 16</translation>
<translation id="3789841737615482174">Zainstaluj</translation>
@@ -768,6 +790,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="3841184659773414994">Moduły obsługi plików</translation>
<translation id="385051799172605136">Wstecz</translation>
<translation id="3858027520442213535">Zaktualizuj datÄ™ i godzinÄ™</translation>
+<translation id="3881478300875776315">Pokaż mniej wierszy</translation>
<translation id="3884278016824448484">Konflikt identyfikatorów urządzeń</translation>
<translation id="3885155851504623709">Parafia</translation>
<translation id="388632593194507180">Wykryto monitorowanie</translation>
@@ -793,6 +816,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="397105322502079400">Obliczanie...</translation>
<translation id="3973234410852337861">Strona <ph name="HOST_NAME" /> jest zablokowana</translation>
<translation id="3973357910713125165">Przycisk Uruchom kontrolę zabezpieczeń Chrome; aby uruchomić kontrolę zabezpieczeń w ustawieniach Chrome, naciśnij Enter</translation>
+<translation id="3986705137476756801">Na razie wyłącz napisy na żywo</translation>
<translation id="3987405730340719549">Według Chrome ta strona może być fałszywa.
Jeśli uważasz, że ten komunikat pojawił się w wyniku pomyłki, wejdź na https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals</translation>
@@ -884,13 +908,14 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="4275830172053184480">Zrestartuj urzÄ…dzenie</translation>
<translation id="4277028893293644418">Resetuj hasło</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="4287885627794386150">Kwalifikuje się do wersji próbnej, ale nie jest ona aktywna</translation>
<translation id="4297502707443874121">Miniatura strony <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Rozwiń</translation>
<translation id="4300675098767811073">Wiele otworów z prawej strony</translation>
<translation id="4302514097724775343">Kliknij dinozaura, by zacząć grać</translation>
<translation id="4302965934281694568">Chou3 (koperta)</translation>
<translation id="4305666528087210886">Nie udało się uzyskać dostępu do pliku</translation>
-<translation id="4305817255990598646">Przełącz</translation>
+<translation id="4306529830550717874">Zapisać adres?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokuj (domyślnie)</translation>
<translation id="4314815835985389558">ZarzÄ…dzanie synchronizacjÄ…</translation>
@@ -917,6 +942,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="4377125064752653719">Próbujesz wejść na <ph name="DOMAIN" />, ale serwer przedstawił certyfikat unieważniony przez wystawcę. Oznacza to, że dane uwierzytelniające podane przez serwer są zupełnie niewiarygodne. Możliwe, że komunikujesz się z intruzem.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Krawędź</translation>
+<translation id="4406883609789734330">Napisy na żywo</translation>
<translation id="4406896451731180161">wyniki wyszukiwania</translation>
<translation id="4408413947728134509">Pliki cookie (<ph name="NUM_COOKIES" />)</translation>
<translation id="4414290883293381923">Przed chwilą wpisano hasło na stronie wprowadzającej w błąd. Chrome zaleca, by natychmiast zmienić je na <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> i innych stronach, na których go używasz.</translation>
@@ -929,7 +955,6 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="4435702339979719576">pocztówka)</translation>
<translation id="443673843213245140">Korzystanie z serwera proxy jest wyłączone, ale podano konfigurację proxy.</translation>
<translation id="4464826014807964867">Witryny z informacjami od Twojej organizacji</translation>
-<translation id="4466881336512663640">Zmiany w formularzu zostaną utracone. Na pewno chcesz kontynuować?</translation>
<translation id="4476953670630786061">Ten formularz nie jest bezpieczny. Autouzupełnianie zostało wyłączone.</translation>
<translation id="4477350412780666475">Następny utwór</translation>
<translation id="4482953324121162758">Ta strona nie będzie tłumaczona.</translation>
@@ -963,6 +988,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="4594403342090139922">&amp;Cofnij usunięcie</translation>
<translation id="4597348597567598915">Rozmiar 8</translation>
<translation id="4600854749408232102">C6/C5 (koperta)</translation>
+<translation id="4606870351894164739">Wyrazisty</translation>
<translation id="4628948037717959914">Zdjęcie</translation>
<translation id="4631649115723685955">Połączone ze zwrotem za zakupy</translation>
<translation id="4636930964841734540">Informacje</translation>
@@ -982,6 +1008,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="4691835149146451662">Architecture-A (koperta)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Strona</translation>
+<translation id="4702656508969495934">Napisy na żywo są widoczne. Użyj przełącznika okien, aby zaznaczyć.</translation>
<translation id="4708268264240856090">Połączenie zostało przerwane</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Uruchom DiagnostykÄ™ sieci systemu Windows<ph name="END_LINK" /></translation>
@@ -995,6 +1022,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="4738601419177586157">Propozycja wyszukiwania: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Zarządzaj hasłami…</translation>
<translation id="4744603770635761495">Ścieżka pliku wykonywalnego</translation>
+<translation id="4749011317274908093">Jesteś w trybie incognito</translation>
<translation id="4750917950439032686">Informacje, które wysyłasz tej witrynie (na przykład hasła lub numery kart kredytowych), pozostają prywatne.</translation>
<translation id="4756388243121344051">&amp;Historia</translation>
<translation id="4758311279753947758">Dodaj dane kontaktowe</translation>
@@ -1024,6 +1052,8 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="4813512666221746211">BÅ‚Ä…d sieci</translation>
<translation id="4816492930507672669">Dopasuj do strony</translation>
<translation id="4819347708020428563">Czy chcesz edytować adnotacje w widoku domyślnym?</translation>
+<translation id="4825507807291741242">Intensywny</translation>
+<translation id="4838327282952368871">Uroczy</translation>
<translation id="484462545196658690">Automatycznie</translation>
<translation id="4850886885716139402">Widok</translation>
<translation id="485316830061041779">Niemiecki</translation>
@@ -1160,6 +1190,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="5314967030527622926">Tworzenie broszur</translation>
<translation id="5316812925700871227">Obróć w lewo</translation>
<translation id="5317780077021120954">Zapisz</translation>
+<translation id="5321288445143113935">Zmaksymalizowana</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> z <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Wybierz dane kontaktowe</translation>
<translation id="5327248766486351172">Nazwa</translation>
@@ -1167,11 +1198,13 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="5332219387342487447">Metoda wysyłki</translation>
<translation id="5333022057423422993">Przeglądarka Chrome znalazła użyte właśnie hasło w naruszeniu bezpieczeństwa danych. W trosce o bezpieczeństwo Twoich kont zalecamy jak najszybsze sprawdzenie zapisanych haseł.</translation>
<translation id="5334013548165032829">Szczegółowe dzienniki systemowe</translation>
+<translation id="5334145288572353250">Zapisać adres?</translation>
<translation id="5340250774223869109">Aplikacja jest zablokowana</translation>
<translation id="534295439873310000">Urządzenia z funkcją NFC</translation>
<translation id="5344579389779391559">Ta strona może próbować obciążyć Cię płatnością</translation>
<translation id="5355557959165512791">Nie możesz teraz otworzyć strony <ph name="SITE" />, bo jej certyfikat został unieważniony. Błędy sieci i ataki są zazwyczaj przejściowe, więc prawdopodobnie strona będzie wkrótce działać.</translation>
<translation id="536296301121032821">Zapisanie ustawień zasady nie powiodło się</translation>
+<translation id="5363309033720083897">Port szeregowy, na który zezwala administrator</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="5386426401304769735">ÅaÅ„cuch certyfikatów tej witryny zawiera certyfikat podpisany za pomocÄ… SHA-1.</translation>
@@ -1180,6 +1213,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="5398772614898833570">Reklamy zostały zablokowane</translation>
<translation id="5400836586163650660">Szary</translation>
<translation id="540969355065856584">Ten serwer nie może udowodnić, że należy do domeny <ph name="DOMAIN" />. Jego certyfikat bezpieczeństwa nie jest obecnie ważny. Może to być spowodowane nieprawidłową konfiguracją lub przechwyceniem połączenia przez atakującego.</translation>
+<translation id="541143247543991491">Chmura (cały system)</translation>
<translation id="541416427766103491">Układarka 4</translation>
<translation id="5421136146218899937">Wyczyść dane przeglądania...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> chce wysyłać Ci powiadomienia</translation>
@@ -1193,6 +1227,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="5455374756549232013">Nieprawidłowy czas zasady</translation>
<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="5463625433003343978">Szukam urządzeń...</translation>
<translation id="5469868506864199649">WÅ‚oski</translation>
<translation id="5470861586879999274">&amp;Ponów edycję</translation>
<translation id="5478437291406423475">B6/C4 (koperta)</translation>
@@ -1242,7 +1277,6 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="5624120631404540903">Zarządzaj hasłami</translation>
<translation id="5629630648637658800">Åadowanie ustawieÅ„ zasady nie powiodÅ‚o siÄ™</translation>
<translation id="5631439013527180824">Nieprawidłowy token zarządzania urządzeniem</translation>
-<translation id="5632627355679805402">Twoje dane zostały zaszyfrowane <ph name="BEGIN_LINK" />hasłem Google<ph name="END_LINK" /> w dniu <ph name="TIME" />. Wpisz to hasło, by rozpocząć synchronizację.</translation>
<translation id="5633066919399395251">Osoby obecnie atakujące stronę <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogą próbować zainstalować na Twoim komputerze niebezpieczne programy, które wykradają lub usuwają informacje (na przykład zdjęcia, 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="563324245173044180">Zablokowano treści wprowadzające w błąd.</translation>
<translation id="5644090287519800334">Strona 1 – przesunięcie obrazu wzdłuż osi X</translation>
@@ -1281,12 +1315,12 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="5785756445106461925">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ć wygląd strony.</translation>
<translation id="5786044859038896871">Chcesz wpisać dane swojej karty?</translation>
<translation id="578633867165174378">Przeglądarka Chrome znalazła użyte właśnie hasło w naruszeniu bezpieczeństwa danych. Zalecamy jak najszybszą zmianę tego hasła.</translation>
-<translation id="5798290721819630480">Odrzucić zmiany?</translation>
<translation id="5803412860119678065">Chcesz wpisać dane swojej karty (<ph name="CARD_DETAIL" />)?</translation>
<translation id="5804241973901381774">Uprawnienia</translation>
<translation id="5804427196348435412">Korzystać z urządzeń NFC</translation>
<translation id="5810442152076338065">Połączenie z <ph name="DOMAIN" /> jest szyfrowane przy użyciu przestarzałego zestawu szyfrów.</translation>
<translation id="5813119285467412249">&amp;Ponów dodanie</translation>
+<translation id="5817918615728894473">Sparuj</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Gdy zapłacisz, karta zostanie obciążona, ale dana strona nie pozna jej rzeczywistego numeru. Jako dodatkowe zabezpieczenie zostanie wygenerowany tymczasowy kod CVC.}few{Gdy zapłacisz, wybrana karta zostanie obciążona, ale dana strona nie pozna jej rzeczywistego numeru. Jako dodatkowe zabezpieczenie zostanie wygenerowany tymczasowy kod CVC.}many{Gdy zapłacisz, wybrana karta zostanie obciążona, ale dana strona nie pozna jej rzeczywistego numeru. Jako dodatkowe zabezpieczenie zostanie wygenerowany tymczasowy kod CVC.}other{Gdy zapłacisz, wybrana karta zostanie obciążona, ale dana strona nie pozna jej rzeczywistego numeru. Jako dodatkowe zabezpieczenie zostanie wygenerowany tymczasowy kod CVC.}}</translation>
<translation id="5826507051599432481">Nazwa pospolita (CN)</translation>
<translation id="5838278095973806738">Nie podawaj żadnych informacji poufnych (takich jak hasła czy dane kart kredytowych) w tej witrynie, bo osoby atakujące będą mogły je wykraść.</translation>
@@ -1294,6 +1328,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="5855253129151731373">Nazwa hosta tej witryny jest podobna do <ph name="LOOKALIKE_DOMAIN" />. Złośliwe strony czasami podszywają się pod inne, wprowadzając niewielkie i trudne do zauważenia zmiany w nazwie domeny.
Jeśli uważasz, że ten komunikat pojawił się w wyniku pomyłki, wejdź na https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals</translation>
+<translation id="5860033963881614850">Wyłączone</translation>
<translation id="5862579898803147654">Układarka 8</translation>
<translation id="5863847714970149516">Otwierana strona może próbować obciążyć Cię płatnością</translation>
<translation id="5866257070973731571">Dodaj numer telefonu</translation>
@@ -1310,6 +1345,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="5913377024445952699">Przechwytywanie ekranu zostało wstrzymane</translation>
<translation id="59174027418879706">WÅ‚Ä…czony</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{W użyciu: 1}few{W użyciu: #}many{W użyciu: #}other{W użyciu: #}}</translation>
<translation id="5921185718311485855">włączono</translation>
<translation id="5921639886840618607">Zapisać kartę na koncie Google?</translation>
<translation id="5922853866070715753">Prawie gotowe</translation>
@@ -1329,6 +1365,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="5989320800837274978">Nie określono ani stałych serwerów proxy, ani adresu URL skryptu PAC.</translation>
<translation id="5992691462791905444">Składanie typu Z</translation>
<translation id="6000758707621254961">Wyniki wyszukiwania dla zapytania „<ph name="SEARCH_TEXT" />â€: <ph name="RESULT_COUNT" /></translation>
+<translation id="6006484371116297560">Klasyczny</translation>
<translation id="6008122969617370890">Kolejność od N do 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Sprawdź swoje hasła</translation>
@@ -1350,6 +1387,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="6045164183059402045">Szablon impozycji</translation>
<translation id="6047233362582046994">Jeśli rozumiesz zagrożenie, możesz <ph name="BEGIN_LINK" />wejść na tę stronę<ph name="END_LINK" />, zanim szkodliwe aplikacje zostaną usunięte.</translation>
<translation id="6047927260846328439">Te treści mogą próbować podstępem nakłonić Cię do zainstalowania oprogramowania lub ujawnienia danych osobowych. <ph name="BEGIN_LINK" />Wyświetl mimo to<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Naciśnij i przytrzymaj |<ph name="ACCELERATOR" />|, by zamknąć pełny ekran</translation>
<translation id="6049488691372270142">Podawanie stron</translation>
<translation id="6051221802930200923">Nie możesz teraz otworzyć strony <ph name="SITE" />, ponieważ stosuje ona przypinanie certyfikatów. Błędy sieciowe i ataki są zazwyczaj tymczasowe, więc prawdopodobnie strona będzie dostępna później.</translation>
<translation id="6051898664905071243">Liczba stron:</translation>
@@ -1366,6 +1404,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<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>
<translation id="6116338172782435947">Mieć dostęp do tekstu i obrazów skopiowanych do schowka</translation>
<translation id="6120179357481664955">Zapamiętać Twój identyfikator UPI?</translation>
+<translation id="6123290840358279103">Zobacz kartÄ™ wirtualnÄ…</translation>
<translation id="6124432979022149706">Oprogramowanie sprzęgające Chrome Enterprise</translation>
<translation id="6146055958333702838">Sprawdź wszystkie kable i uruchom ponownie wszelkie używane routery, modemy
i inne urzÄ…dzenia sieciowe.</translation>
@@ -1402,6 +1441,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="6289939620939689042">Kolor strony</translation>
<translation id="6290238015253830360">Tutaj wyświetlą się proponowane artykuły</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">Kod CVC:</translation>
<translation id="6302269476990306341">Wyłączam Asystenta Google w Chrome</translation>
<translation id="6305205051461490394">Strona <ph name="URL" /> jest nieosiÄ…galna.</translation>
<translation id="6312113039770857350">Strona internetowa jest niedostępna</translation>
@@ -1427,6 +1467,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="6390200185239044127">Składanie w połowie, a następnie składanie typu Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Zasady administratora uniemożliwiają wklejanie tu informacji z <ph name="ORIGIN_NAME" /></translation>
+<translation id="6398765197997659313">Zamknij pełny ekran</translation>
<translation id="6401136357288658127">Ta zasada została wycofana. Zalecamy używanie zasady <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Edytuj zakładkę</translation>
<translation id="6406765186087300643">C0 (koperta)</translation>
@@ -1439,7 +1480,6 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="6428450836711225518">Weryfikowanie numeru telefonu</translation>
<translation id="6433490469411711332">Edytuj dane kontaktowe</translation>
<translation id="6433595998831338502">Serwer <ph name="HOST_NAME" /> odrzucił połączenie.</translation>
-<translation id="6434309073475700221">Odrzuć</translation>
<translation id="6440503408713884761">Ignorowany</translation>
<translation id="6443406338865242315">Zainstalowane przez Ciebie rozszerzenia i wtyczki</translation>
<translation id="6446163441502663861">Kahu (koperta)</translation>
@@ -1482,6 +1522,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="6624427990725312378">Dane kontaktowe</translation>
<translation id="6626291197371920147">Dodaj prawidłowy numer karty</translation>
<translation id="6628463337424475685">Wyszukiwarka <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Szukam urządzeń USB...</translation>
<translation id="6630809736994426279">Osoby obecnie atakujące stronę <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mogą próbować zainstalować na Twoim komputerze Mac niebezpieczne programy wykradające lub usuwające informacje (na przykład zdjęcia, 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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Wyczyść</translation>
@@ -1497,6 +1538,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="6671697161687535275">Usunąć tę podpowiedź do formularza z Chromium?</translation>
<translation id="6685834062052613830">Wyloguj się i dokończ konfigurację</translation>
<translation id="6687335167692595844">Zażądano rozmiaru czcionki</translation>
+<translation id="6688743156324860098">Zmień…</translation>
<translation id="6689249931105087298">Względna z kompresją punktu czerni</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="6698381487523150993">Utworzono:</translation>
@@ -1512,6 +1554,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="6744009308914054259">Dopóki nie masz połączenia, możesz poczytać artykuły offline z Pobranych plików.</translation>
<translation id="6753269504797312559">Wartość zasady</translation>
<translation id="6757797048963528358">Twoje urządzenie przeszło w tryb uśpienia.</translation>
+<translation id="6767985426384634228">Zmienić adres?</translation>
<translation id="6768213884286397650">Hagaki (pocztówka)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Fioletowy</translation>
@@ -1534,6 +1577,7 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Strona została uproszczona przez Chrome, by było ją łatwiej przeczytać. Przeglądarka Chrome pobrała oryginalną stronę przez niezabezpieczone połączenie.</translation>
<translation id="6891596781022320156">Ten poziom zasad nie jest obsługiwany.</translation>
+<translation id="6895143722905299846">Numer wirtualny:</translation>
<translation id="6895330447102777224">Karta została potwierdzona</translation>
<translation id="6897140037006041989">Klient</translation>
<translation id="6898699227549475383">Organizacja (O)</translation>
@@ -1569,10 +1613,10 @@ Jeśli się nie zgodzisz, zostaną one zablokowane ze względu na Twoje ustawien
<translation id="7004583254764674281">Używaj Windows Hello, by szybciej potwierdzać karty</translation>
<translation id="7006930604109697472">Wyślij mimo wszystko</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Ustawienia zmiany rozmiaru</translation>
<translation id="7014741021609395734">Poziom powiększenia</translation>
<translation id="7016992613359344582">Może to być opłata jednorazowa lub cykliczna, a informacje o niej mogą nie być wyraźnie podane.</translation>
<translation id="7029809446516969842">Hasła</translation>
+<translation id="7030436163253143341">Certyfikat jest nieważny</translation>
<translation id="7031646650991750659">Zainstalowane przez Ciebie aplikacje z Google Play</translation>
<translation id="7050187094878475250">Próbujesz połączyć się z domeną <ph name="DOMAIN" />, ale serwer przedstawił certyfikat, którego okres ważności jest za długi, by był wiarygodny.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Nie można teraz zapisać tej karty}few{Nie można teraz zapisać tych kart}many{Nie można teraz zapisać tych kart}other{Nie można teraz zapisać tych kart}}</translation>
@@ -1642,12 +1686,14 @@ Dodatkowe informacje:
<translation id="7300012071106347854">Niebieski kobalt</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />â€</translation>
<translation id="7304030187361489308">Wysoki</translation>
+<translation id="7305756307268530424">Rozpocznij wolniej</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Pomoc dotycząca połączeń</translation>
<translation id="7323804146520582233">Ukryj sekcjÄ™ „<ph name="SECTION" />â€</translation>
<translation id="733354035281974745">ZastÄ…pienie przez konto lokalne na urzÄ…dzeniu</translation>
<translation id="7333654844024768166">Przed chwilą wpisano hasło na stronie wprowadzającej w błąd. Chromium zaleca, by natychmiast zmienić je na <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> i innych stronach, na których go używasz.</translation>
<translation id="7334320624316649418">&amp;Ponów zmianę kolejności</translation>
+<translation id="7337248890521463931">Pokaż więcej wierszy</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>
@@ -1655,6 +1701,7 @@ Dodatkowe informacje:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Wiersz poleceń</translation>
<translation id="7359588939039777303">Reklamy zostały zablokowane.</translation>
+<translation id="7363096869660964304">To jednak nie znaczy, że Cię nie widać. Nawet gdy przejdziesz w tryb incognito, Twój pracodawca, dostawca usług internetowych czy webmasterzy stron, na które wchodzisz, mogą dowiedzieć się, co przeglądasz.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />; aby dodać adresy i zarządzać nimi w ustawieniach Chrome, naciśnij Tab, a potem Enter</translation>
<translation id="7365849542400970216">Czy strony mogą sprawdzać, kiedy używasz urządzenia?</translation>
<translation id="7372973238305370288">wynik wyszukiwania</translation>
@@ -1665,7 +1712,9 @@ Dodatkowe informacje:
<translation id="7378594059915113390">Sterowanie multimediami</translation>
<translation id="7378627244592794276">Nie</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Nie dotyczy</translation>
<translation id="7390545607259442187">Potwierdź kartę</translation>
+<translation id="7392089738299859607">Zmień adres</translation>
<translation id="7399802613464275309">Kontrola zabezpieczeń</translation>
<translation id="7400418766976504921">Adres URL</translation>
<translation id="7403591733719184120">Twoje urzÄ…dzenie <ph name="DEVICE_NAME" /> jest zarzÄ…dzane</translation>
@@ -1680,6 +1729,7 @@ Dodatkowe informacje:
&lt;li&gt;W &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centrum pomocy Chrome&lt;/a&gt; dowiesz się, jak trwale usunąć to oprogramowanie z komputera.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Romantyczny</translation>
<translation id="7416351320495623771">Zarządzaj hasłami…</translation>
<translation id="7419106976560586862">Ścieżka profilu</translation>
<translation id="7437289804838430631">Dodaj dane kontaktowe</translation>
@@ -1695,7 +1745,7 @@ Dodatkowe informacje:
<translation id="7481312909269577407">Dalej</translation>
<translation id="7485870689360869515">Nie znaleziono danych.</translation>
<translation id="7495528107193238112">Ta zawartość jest zablokowana. Aby rozwiązać problem, skontaktuj się z właścicielem witryny.</translation>
-<translation id="7498234416455752244">Edytuj dalej</translation>
+<translation id="7498193950643227031">Po zmianie rozmiaru aplikacja może działać w nieoczekiwany sposób. Możesz teraz ograniczyć zmianę rozmiaru aplikacji. Aby to zrobić, otwórz <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Przed chwilą wpisano hasło na stronie wprowadzającej w błąd. Chromium zaleca, by sprawdzić zapisane hasła do witryn <ph name="WEBSITE_1" /> i <ph name="WEBSITE_2" /> oraz do innych stron, na których używasz tego hasła.</translation>
<translation id="7508255263130623398">Zwrócony identyfikator urządzenia dla zasad jest pusty lub nie pasuje do bieżącego identyfikatora urządzenia</translation>
<translation id="7508870219247277067">Zielony awokado</translation>
@@ -1715,6 +1765,7 @@ Dodatkowe informacje:
<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="755279583747225797">Wersja próbna jest aktywna</translation>
<translation id="7552846755917812628">Skorzystaj z tych wskazówek:</translation>
<translation id="7554475479213504905">Załaduj ponownie i pokaż mimo to</translation>
<translation id="7554791636758816595">Nowa karta</translation>
@@ -1733,7 +1784,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Naciśnij Tab, a potem Enter, by wyświetlić hasła i zarządzać nimi w ustawieniach Chrome.</translation>
-<translation id="7615602087246926389">Masz już dane zaszyfrowane przy użyciu innej wersji hasła konta Google. Wpisz je poniżej.</translation>
<translation id="7616645509853975347">Administrator włączył w przeglądarce oprogramowanie sprzęgające Chrome Enterprise. Może ono mieć dostęp do niektórych Twoich danych.</translation>
<translation id="7619838219691048931">Arkusz końcowy</translation>
<translation id="762844065391966283">Pojedynczo</translation>
@@ -1798,13 +1848,12 @@ Dodatkowe informacje:
<translation id="782886543891417279">Sieć Wi-Fi (<ph name="WIFI_NAME" />), której używasz, może wymagać otwarcia strony logowania.</translation>
<translation id="7836231406687464395">Postfix (koperta)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Brak}=1{Jedna aplikacja (<ph name="EXAMPLE_APP_1" />)}=2{Dwie aplikacje (<ph name="EXAMPLE_APP_1" /> i <ph name="EXAMPLE_APP_2" />)}few{# aplikacje (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}many{# aplikacji (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}other{# aplikacji (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">To jednak nie znaczy, że Cię nie widać. Nawet gdy przejdziesz w tryb incognito, Twój pracodawca, dostawca usług internetowych czy webmasterzy stron, na które wchodzisz, mogą dowiedzieć się, co przeglądasz.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Otwierać pliki skojarzone z określonym typem plików.</translation>
<translation id="7862185352068345852">Opuścić stronę?</translation>
<translation id="7865448901209910068">Optymalna szybkość</translation>
<translation id="7874263914261512992">Przed chwilą wpisano hasło na stronie wprowadzającej w błąd. Chrome zaleca, by sprawdzić zapisane hasła do witryn <ph name="WEBSITE_1" /> i <ph name="WEBSITE_2" /> oraz do innych stron, na których używasz tego hasła.</translation>
<translation id="7878562273885520351">Ktoś mógł poznać Twoje hasło</translation>
+<translation id="7880146494886811634">Zapisz adres</translation>
<translation id="7882421473871500483">BrÄ…zowy</translation>
<translation id="7887683347370398519">Sprawdź kod CVC i spróbuj ponownie</translation>
<translation id="7887885240995164102">Włącz obraz w obrazie</translation>
@@ -1812,6 +1861,7 @@ Dodatkowe informacje:
<translation id="7894280532028510793">Jeśli pisownia jest poprawna, <ph name="BEGIN_LINK" />uruchom Diagnostykę sieci<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (koperta)</translation>
<translation id="7931318309563332511">Nieznany</translation>
+<translation id="793209273132572360">Zaktualizować adres?</translation>
<translation id="7932579305932748336">Powłoka</translation>
<translation id="79338296614623784">Wpisz prawidłowy numer telefonu</translation>
<translation id="7934052535022478634">Płatność została zrealizowana</translation>
@@ -1882,6 +1932,7 @@ Dodatkowe informacje:
<translation id="8175796834047840627">Jako zalogowany użytkownik możesz zapisać karty na Twoim koncie Google w Chrome. Możesz to zmienić w ustawieniach.</translation>
<translation id="8176440868214972690">Administrator tego urządzenia wysłał do tych witryn pewne informacje, takie jak ustawienia lub zasady.</translation>
<translation id="8184538546369750125">Użyj globalnej wartości domyślnej (Zezwalaj)</translation>
+<translation id="8193086767630290324">Wykonane działania dotyczące danych oznaczonych jako poufne</translation>
<translation id="8194797478851900357">&amp;Cofnij przeniesienie</translation>
<translation id="8201077131113104583">NieprawidÅ‚owy URL aktualizowania dla rozszerzenia o identyfikatorze „<ph name="EXTENSION_ID" />â€.</translation>
<translation id="8202097416529803614">Podsumowanie zamówienia</translation>
@@ -1904,6 +1955,7 @@ Dodatkowe informacje:
<translation id="8249296373107784235">Przerwij</translation>
<translation id="8249320324621329438">Ostatnie pobieranie:</translation>
<translation id="8253091569723639551">Wymagany jest adres rozliczeniowy</translation>
+<translation id="8257387598443225809">Ta aplikacja jest przeznaczona na urzÄ…dzenia mobilne</translation>
<translation id="825929999321470778">Pokaż wszystkie zapisane hasła</translation>
<translation id="8261506727792406068">Usuń</translation>
<translation id="8262952874573525464">Zszywanie wzdłuż dolnej krawędzi</translation>
@@ -2027,7 +2079,6 @@ Dodatkowe informacje:
<translation id="8719528812645237045">Wiele otworów u góry</translation>
<translation id="8725066075913043281">Spróbuj ponownie</translation>
<translation id="8726549941689275341">Rozmiar strony:</translation>
-<translation id="8728672262656704056">JesteÅ› w trybie incognito</translation>
<translation id="8730621377337864115">Gotowe</translation>
<translation id="8731544501227493793">Przycisk zarządzania hasłami. Naciśnij Enter, by wyświetlić hasła i zarządzać nimi w ustawieniach Chrome.</translation>
<translation id="8734529307927223492">Twoim urzÄ…dzeniem <ph name="DEVICE_TYPE" /> zarzÄ…dza <ph name="MANAGER" /></translation>
@@ -2104,6 +2155,7 @@ Dodatkowe informacje:
<translation id="9020542370529661692">Ta strona została przetłumaczona na <ph name="TARGET_LANGUAGE" />.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Nieważny)</translation>
+<translation id="9030265603405983977">Monochromatyczny</translation>
<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>
@@ -2127,6 +2179,7 @@ Dodatkowe informacje:
<translation id="91108059142052966">Zgodnie z polityką administratora udostępnianie ekranu w aplikacji <ph name="APPLICATION_TITLE" /> zostanie wyłączone, gdy wyświetlą się treści poufne</translation>
<translation id="9114524666733003316">Sprawdzam kartę…</translation>
<translation id="9114581008513152754">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="9117930699067497412">Świeży</translation>
<translation id="9119042192571987207">Przesłano</translation>
<translation id="9128016270925453879">Zasady zostały załadowane</translation>
<translation id="9128870381267983090">Połącz z siecią</translation>
@@ -2145,6 +2198,7 @@ Dodatkowe informacje:
<translation id="9170848237812810038">&amp;Cofnij</translation>
<translation id="9171296965991013597">Zamknąć aplikację?</translation>
<translation id="9173282814238175921">Pojedynczy dokument / Nowy arkusz</translation>
+<translation id="9173995187295789444">Skanuję w poszukiwaniu urządzeń Bluetooth…</translation>
<translation id="917450738466192189">Certyfikat serwera jest nieprawidłowy.</translation>
<translation id="9174917557437862841">Przycisk przełączania kart, naciśnij Enter, by przełączyć na tę kartę</translation>
<translation id="9179703756951298733">Zarządzaj płatnościami i kartami kredytowymi w ustawieniach Chrome</translation>
diff --git a/chromium/components/strings/components_strings_pt-BR.xtb b/chromium/components/strings/components_strings_pt-BR.xtb
index a7107145a31..84fd8823674 100644
--- a/chromium/components/strings/components_strings_pt-BR.xtb
+++ b/chromium/components/strings/components_strings_pt-BR.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Selecione uma permissão para <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Desfazer reordenar</translation>
+<translation id="1123753900084781868">A "Legenda instantânea" não está disponível no momento</translation>
<translation id="1125573121925420732">Avisos podem ser comuns enquanto os sites atualizam a segurança. Isso deve melhorar em breve.</translation>
<translation id="112840717907525620">Cache da política OK</translation>
<translation id="1130564665089811311">Botão "Traduzir página". Pressione "Enter" para traduzir a página com o Google Tradutor</translation>
@@ -74,6 +75,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="1240347957665416060">O nome do seu dispositivo</translation>
<translation id="124116460088058876">Mais idiomas</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Negrito</translation>
<translation id="1250759482327835220">Para agilizar o pagamento na próxima vez, salve o cartão, seu nome e o endereço de faturamento na sua Conta do Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sincronizados)</translation>
<translation id="1256368399071562588">&lt;p&gt;Se você tentar visitar um site e ele não abrir, primeiro tente corrigir o erro com estas etapas de solução de problemas:&lt;/p&gt;
@@ -156,6 +158,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="1476595624592550506">Mude sua senha</translation>
<translation id="1484290072879560759">Escolher endereço de entrega</translation>
<translation id="1492194039220927094">Push de políticas:</translation>
+<translation id="1495677929897281669">Voltar à guia</translation>
<translation id="1501859676467574491">Mostre os cartões salvos na Conta do Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Você verá esse erro se estiver usando um portal Wi-Fi em que precise fazer login para poder se conectar.&lt;/p&gt;
&lt;p&gt;Para corrigir o erro, clique em &lt;strong&gt;Conectar&lt;/strong&gt; na página que você está tentando abrir.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="1532118530259321453">Essa página diz</translation>
<translation id="153384715582417236">Isso é tudo por enquanto</translation>
<translation id="1536390784834419204">Traduzir página</translation>
+<translation id="1539840569003678498">Relatório enviado:</translation>
<translation id="154408704832528245">Escolher endereço de entrega</translation>
<translation id="1549470594296187301">O JavaScript deve ser ativado para usar este recurso.</translation>
<translation id="155039086686388498">Engineering D</translation>
@@ -213,16 +217,19 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="1682696192498422849">Borda menor primeiro</translation>
<translation id="168693727862418163">Houve uma falha na validação do valor da política em relação ao esquema, e ele será ignorado.</translation>
<translation id="168841957122794586">O certificado do servidor contém uma chave de criptografia fraca.</translation>
+<translation id="1696290444144917273">Ver detalhes do cartão virtual</translation>
<translation id="1697532407822776718">Pronto.</translation>
<translation id="1703835215927279855">Carta</translation>
<translation id="1706954506755087368">{1,plural, =1{Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança dele está com a data de amanhã. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.}one{Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança dele está com uma data de # dias depois de hoje. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.}other{Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança dele está com uma data de # dias depois de hoje. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.}}</translation>
<translation id="1710259589646384581">SO</translation>
+<translation id="1711234383449478798">Ignorada porque a política <ph name="POLICY_NAME" /> não está definida como <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> quer armazenar dados no computador local</translation>
<translation id="1713628304598226412">Bandeja 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Caixa de e-mails 3</translation>
<translation id="1718029547804390981">O documento é grande demais para receber anotações</translation>
<translation id="1721424275792716183">* Campo obrigatório</translation>
+<translation id="1727613060316725209">O certificado é válido</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>
<translation id="173080396488393970">Esse tipo de cartão não é aceito</translation>
@@ -242,7 +249,6 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Tente executar o Diagnóstico de Rede do Windows<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">O servidor que você acessará, <ph name="ORIGIN" />, definiu um cabeçalho solicitando que uma política de origem seja aplicada a todas as solicitações feitas a ele. No entanto, o cabeçalho está incorreto, o que impede que o navegador faça a solicitação para <ph name="SITE" />. Políticas de origem podem ser usadas por operadores para configurar a segurança e outras propriedades de um site.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Favor atualizar sua senha de sincronização.</translation>
<translation id="1787142507584202372">Suas guias abertas são exibidas aqui</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Várias ações disponíveis. Pressione "Tab" para alternar entre elas</translation>
@@ -275,6 +281,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="1919345977826869612">Anúncios</translation>
<translation id="1919367280705858090">Receber ajuda com uma mensagem de erro específica</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Nenhum}=1{1 site}one{# site}other{# sites}}</translation>
+<translation id="1924727005275031552">Novo</translation>
<translation id="1945968466830820669">Você pode perder o acesso à conta da sua organização ou sofrer roubo de identidade. O Chromium recomenda que você altere sua senha agora.</translation>
<translation id="1947454675006758438">Grampo na parte superior direita</translation>
<translation id="1958218078413065209">Sua maior pontuação é de <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="2042213636306070719">Bandeja 7</translation>
<translation id="204357726431741734">Faça login para usar as senhas salvas na sua Conta do Google</translation>
<translation id="2053111141626950936">Páginas em <ph name="LANGUAGE" /> não serão traduzidas.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Quando este controle estiver ligado e o status estiver ativo, o Chrome determinará com qual grupo grande de pessoas, ou "coorte", sua atividade de navegação se parece mais. Os anunciantes podem selecionar anúncios para o grupo e sua atividade de navegação será armazenada no dispositivo de forma particular. Seu grupo é atualizado todos os dias.}=1{Quando este controle estiver ligado e o status estiver ativo, o Chrome determinará com qual grupo grande de pessoas, ou "coorte", sua atividade de navegação se parece mais. Os anunciantes podem selecionar anúncios para o grupo e sua atividade de navegação será armazenada no dispositivo de forma particular. Seu grupo é atualizado todos os dias.}one{Quando este controle estiver ligado e o status estiver ativo, o Chrome determinará com qual grupo grande de pessoas, ou "coorte", sua atividade de navegação se parece mais. Os anunciantes podem selecionar anúncios para o grupo e sua atividade de navegação será armazenada no dispositivo de forma particular. Seu grupo é atualizado a cada {NUM_DAYS} dia.}other{Quando este controle estiver ligado e o status estiver ativo, o Chrome determinará com qual grupo grande de pessoas, ou "coorte", sua atividade de navegação se parece mais. Os anunciantes podem selecionar anúncios para o grupo e sua atividade de navegação será armazenada no dispositivo de forma particular. Seu grupo é atualizado a cada {NUM_DAYS} dias.}}</translation>
<translation id="2053553514270667976">CEP</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugestão}one{# sugestão}other{# sugestões}}</translation>
<translation id="2071692954027939183">As notificações foram bloqueadas automaticamente porque você não costuma permiti-las</translation>
<translation id="2079545284768500474">Desfazer</translation>
<translation id="20817612488360358">As configurações de proxy do sistema são definidas para serem utilizadas, mas uma configuração explícita de proxy também foi especificada.</translation>
<translation id="2082238445998314030">Resultado <ph name="RESULT_NUMBER" /> de <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Salvar…</translation>
<translation id="2088086323192747268">Botão "Gerenciar sincronização". Pressione "Enter" para gerenciar quais informações são sincronizadas nas configurações do Chrome</translation>
<translation id="2091887806945687916">Som</translation>
<translation id="2094505752054353250">Incompatibilidade de domínio</translation>
@@ -375,6 +384,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="2317259163369394535"><ph name="DOMAIN" /> exige um nome de usuário e uma senha.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, expira em <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Configuração controlada pelo administrador</translation>
+<translation id="2340263603246777781">O <ph name="ORIGIN" /> deseja realizar o pareamento</translation>
<translation id="2344028582131185878">Downloads automáticos</translation>
<translation id="2346319942568447007">Imagem que você copiou</translation>
<translation id="2354001756790975382">Outros favoritos</translation>
@@ -382,8 +392,10 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="2355395290879513365">É possível que invasores consigam ver as imagens que você está olhando nesse site e as modifiquem para enganar você.</translation>
<translation id="2356070529366658676">Perguntar</translation>
<translation id="2357481397660644965">Seu dispositivo é gerenciado por <ph name="DEVICE_MANAGER" />, e sua conta é gerenciada por <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Em menos de um dia}=1{Em um dia}one{Em {NUM_DAYS} dia}other{Em {NUM_DAYS} dias}}</translation>
<translation id="2359629602545592467">Várias</translation>
<translation id="2359808026110333948">Continuar</translation>
+<translation id="2359961752320758691">O número do seu cartão virtual foi aplicado.</translation>
<translation id="2367567093518048410">Nível</translation>
<translation id="2372464001869762664">Depois da confirmação, os detalhes do cartão da sua Conta do Google serão compartilhados com este site. Veja o CVC nos detalhes da sua Conta do Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="239429038616798445">Esse método de envio não está disponível. Tente um método diferente.</translation>
<translation id="2396249848217231973">&amp;Desfazer exclusão</translation>
<translation id="2410754574180102685">Ofício 2</translation>
+<translation id="2413155254802890957">Antigo</translation>
<translation id="2413528052993050574">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança pode ter sido revogado. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.</translation>
<translation id="2414886740292270097">Escuro</translation>
<translation id="2438874542388153331">Perfuração quádrupla no lado direito</translation>
@@ -421,10 +434,10 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="2521385132275182522">Grampo na parte inferior direita</translation>
<translation id="2523886232349826891">Salvo apenas neste dispositivo</translation>
<translation id="2524461107774643265">Adicione Mais Informações</translation>
-<translation id="2526590354069164005">Ãrea de trabalho</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{e mais 1}one{e mais #}other{e mais #}}</translation>
<translation id="2536110899380797252">Adicionar Endereço</translation>
<translation id="2539524384386349900">Detectar</translation>
+<translation id="2541219929084442027">As páginas que você acessa em guias anônimas não permanecem no histórico do navegador, no armazenamento de cookies ou no histórico de pesquisa depois que as guias são fechadas. Os downloads de arquivos ou favoritos criados são mantidos.</translation>
<translation id="2544644783021658368">Documento avulso</translation>
<translation id="254947805923345898">O valor da política não é válido.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> enviou uma resposta inválida.</translation>
@@ -444,6 +457,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="2629325967560697240">Para usar o nível mais alto de segurança do Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ative a proteção reforçada<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Não foi possível encontrar o endereço IP do servidor de <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Nenhum dispositivo compatível encontrado.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. Pressione "Tab" e depois "Enter" para limpar o histórico de navegação, cookies, cache e muito mais nas configurações do Chrome</translation>
<translation id="2650446666397867134">O acesso ao arquivo foi negado</translation>
@@ -488,6 +502,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<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="2807052079800581569">Posição da imagem Y</translation>
+<translation id="2820957248982571256">Verificando...</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>
@@ -495,6 +510,8 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="2850739647070081192">Convite (Envelope)</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="2859806420264540918">Neste site, há exibição de anúncios invasivos ou enganosos</translation>
+<translation id="287596039013813457">Amigável</translation>
+<translation id="2876489322757410363">Saindo do modo de navegação anônima para pagar usando um aplicativo externo. Continuar?</translation>
<translation id="2878197950673342043">Dobra em cruz sanfona</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Posicionamento de janelas</translation>
@@ -544,7 +561,6 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />. Pressione "Tab" e depois "Enter" para executar a confirmação de segurança nas configurações do Chrome</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>
<translation id="306573536155379004">Jogo iniciado.</translation>
<translation id="3080254622891793721">Gráfico</translation>
<translation id="3086579638707268289">Sua atividade na Web está sendo monitorada</translation>
@@ -567,7 +583,6 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="315504272643575312">Sua conta é gerenciada por <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Restaurar</translation>
<translation id="3162559335345991374">O Wi-Fi que você está usando pode exigir a visita a uma página de login.</translation>
-<translation id="3167968892399408617">Quando você está no modo invisível, as páginas que você visita não aparecem no seu histórico de navegação e de pesquisa, nem armazenam arquivos "cookies". Mas os downloads e os favoritos continuam funcionando normalmente.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ilha</translation>
<translation id="3176929007561373547">Verifique suas configurações de proxy ou entre em contato com o administrador de rede para
@@ -593,10 +608,12 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<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="3249845759089040423">Maravilhoso</translation>
<translation id="3252266817569339921">Francês</translation>
<translation id="3266793032086590337">Valor (conflitante)</translation>
<translation id="3268451620468152448">Guias abertas</translation>
<translation id="3270847123878663523">&amp;Desfazer reordenar</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> deseja se conectar</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Sua organização, <ph name="ENROLLMENT_DOMAIN" />, enviou algumas informações, como configurações ou políticas, aos sites a seguir.</translation>
<translation id="3282497668470633863">Adicionar nome (como consta no cartão)</translation>
@@ -649,6 +666,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="3428151540071562330">Um ou mais dos URIs de modelo de servidor da DnsOverHttpsTemplates é inválido e não será usado.</translation>
<translation id="3431636764301398940">Salvar este cartão neste dispositivo</translation>
<translation id="3432601291244612633">Fechar página</translation>
+<translation id="3435738964857648380">Segurança</translation>
<translation id="3435896845095436175">Ativar</translation>
<translation id="3438829137925142401">Usar senhas salvas na sua Conta do Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -691,7 +709,10 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="3584299510153766161">Perfuração dupla na parte inferior</translation>
<translation id="3586931643579894722">Ocultar detalhes</translation>
<translation id="3587738293690942763">Meio</translation>
+<translation id="3590643883886679995">Depois que você sair do modo de navegação anônima, os dados de login serão armazenados no dispositivo.</translation>
+<translation id="359126217934908072">Mês/ano:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Você pode redefinir o grupo a qualquer momento. Leva cerca de um dia para fazer parte de um novo grupo.}=1{Você pode redefinir o grupo a qualquer momento. Leva cerca de um dia para fazer parte de um novo grupo.}one{Você pode redefinir o grupo a qualquer momento. Leva {NUM_DAYS} dia para fazer parte de um novo grupo.}other{Você pode redefinir o grupo a qualquer momento. Leva {NUM_DAYS} dias para fazer parte de um novo grupo.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplicativo bloqueado pelo administrador</translation>
<translation id="3608932978122581043">Fornecer orientação</translation>
@@ -700,13 +721,13 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="3615877443314183785">Informe uma data de validade válida</translation>
<translation id="36224234498066874">Limpar dados de navegação...</translation>
<translation id="362276910939193118">Mostrar histórico completo</translation>
-<translation id="3625635938337243871">Depois que você sair do modo de navegação anônima, os dados de login serão armazenados neste dispositivo.</translation>
<translation id="3630155396527302611">Se ele já estiver listado como um programa que tem permissão para acessar a rede, tente
removê-lo da lista e adicioná-lo novamente.</translation>
<translation id="3630699740441428070">Os administradores deste dispositivo configuraram sua conexão de rede. Dessa forma, eles podem ver o tráfego da rede, incluindo os sites que você visita.</translation>
<translation id="3631244953324577188">Biometria</translation>
<translation id="3633738897356909127">Botão "Atualizar o Chrome". Pressione "Enter" para atualizar o Chrome pelas configurações dele</translation>
<translation id="3634530185120165534">Bandeja 5</translation>
+<translation id="3637662659967048211">Salvar na Conta do Google</translation>
<translation id="3640766068866876100">102 mm × 152 mm</translation>
<translation id="3642638418806704195">Aplicativo:</translation>
<translation id="3650584904733503804">Validação bem-sucedida</translation>
@@ -747,6 +768,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="3781428340399460090">Rosa-escuro</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Dispositivos Bluetooth</translation>
+<translation id="3787675388804467730">Número do cartão virtual</translation>
<translation id="3787705759683870569">Validade: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Tamanho 16</translation>
<translation id="3789841737615482174">Instalar</translation>
@@ -766,6 +788,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="3841184659773414994">Gerenciadores de arquivos</translation>
<translation id="385051799172605136">Voltar</translation>
<translation id="3858027520442213535">Atualizar data e hora</translation>
+<translation id="3881478300875776315">Mostrar menos linhas</translation>
<translation id="3884278016824448484">Identificador de dispositivo em conflito</translation>
<translation id="3885155851504623709">Município</translation>
<translation id="388632593194507180">Monitoramento detectado</translation>
@@ -791,6 +814,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="397105322502079400">Calculando...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> está bloqueado</translation>
<translation id="3973357910713125165">Botão "Executar a confirmação de segurança do Chrome". Pressione "Enter" para executar a confirmação de segurança nas configurações do Chrome</translation>
+<translation id="3986705137476756801">Desativar "Legenda instantânea" por enquanto</translation>
<translation id="3987405730340719549">O Chrome determinou que este site pode ser falso ou fraudulento.
Se você acha que essa mensagem foi mostrada por engano, acesse https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals (em inglês).</translation>
@@ -882,13 +906,14 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="4275830172053184480">Reiniciar seu dispositivo</translation>
<translation id="4277028893293644418">Redefinir senha</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="4287885627794386150">Qualificado para testes, mas inativo</translation>
<translation id="4297502707443874121">Miniatura da página <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Expandir</translation>
<translation id="4300675098767811073">Perfuração múltipla do lado direito</translation>
<translation id="4302514097724775343">Toque no dinossauro para jogar</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Não foi possível acessar seu arquivo</translation>
-<translation id="4305817255990598646">Alternar</translation>
+<translation id="4306529830550717874">Salvar endereço?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloquear (padrão)</translation>
<translation id="4314815835985389558">Gerenciar sincronização</translation>
@@ -915,6 +940,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="4377125064752653719">Você tentou acessar <ph name="DOMAIN" />, mas o certificado que o servidor apresentou foi revogado pelo seu emissor. Isso significa que as credenciais de segurança que o servidor apresentou não são nem um pouco seguras. Talvez você esteja se comunicando com um invasor.</translation>
<translation id="4378154925671717803">Telefone</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Legenda instantânea</translation>
<translation id="4406896451731180161">resultados da pesquisa</translation>
<translation id="4408413947728134509">Cookies: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Você acabou de digitar sua senha em um site suspeito. O Chrome recomenda acessar <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> e outros sites em que você usa essa senha para mudá-la agora mesmo.</translation>
@@ -927,7 +953,6 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<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="4464826014807964867">Sites com informações da sua organização</translation>
-<translation id="4466881336512663640">As alterações no formulário serão perdidas. Tem certeza de que quer continuar?</translation>
<translation id="4476953670630786061">Este formulário não é seguro. O preenchimento automático foi desativado.</translation>
<translation id="4477350412780666475">Próxima faixa</translation>
<translation id="4482953324121162758">Este site não será traduzido.</translation>
@@ -961,6 +986,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="4594403342090139922">&amp;Desfazer exclusão</translation>
<translation id="4597348597567598915">Tamanho 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Impactante</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Reembolso vinculado</translation>
<translation id="4636930964841734540">Informações</translation>
@@ -980,6 +1006,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="4691835149146451662">Arch A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Lado</translation>
+<translation id="4702656508969495934">Legenda instantânea visível. Use o seletor de janelas para definir o foco</translation>
<translation id="4708268264240856090">A conexão foi interrompida</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Executar o Diagnóstico de Rede do Windows<ph name="END_LINK" /></translation>
@@ -993,6 +1020,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="4738601419177586157">Sugestão de pesquisa: <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Gerenciar senhas…</translation>
<translation id="4744603770635761495">Caminho do executável</translation>
+<translation id="4749011317274908093">Você entrou no modo de navegação anônima</translation>
<translation id="4750917950439032686">Suas informações (por exemplo, senhas ou números de cartão de crédito) permanecem privadas quando são enviadas para esse site.</translation>
<translation id="4756388243121344051">&amp;Histórico</translation>
<translation id="4758311279753947758">Adicionar dados de contato</translation>
@@ -1022,6 +1050,8 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="4813512666221746211">Erro na rede</translation>
<translation id="4816492930507672669">Ajustar à página</translation>
<translation id="4819347708020428563">Editar anotações na visualização padrão?</translation>
+<translation id="4825507807291741242">Intenso</translation>
+<translation id="4838327282952368871">Sonho</translation>
<translation id="484462545196658690">Automática</translation>
<translation id="4850886885716139402">Visualizar</translation>
<translation id="485316830061041779">Alemão</translation>
@@ -1158,6 +1188,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="5314967030527622926">Criador de folhetos</translation>
<translation id="5316812925700871227">Girar no sentido anti-horário</translation>
<translation id="5317780077021120954">Salvar</translation>
+<translation id="5321288445143113935">Maximizado</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> de <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Escolher informações de contato</translation>
<translation id="5327248766486351172">Nome</translation>
@@ -1165,11 +1196,13 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="5332219387342487447">Forma de envio</translation>
<translation id="5333022057423422993">A senha que você acabou de usar foi encontrada pelo Chrome em uma violação de dados. Para proteger suas contas, recomendamos verificar as senhas salvas.</translation>
<translation id="5334013548165032829">Registros detalhados do sistema</translation>
+<translation id="5334145288572353250">Salvar endereço?</translation>
<translation id="5340250774223869109">O aplicativo foi bloqueado</translation>
<translation id="534295439873310000">Dispositivos NFC</translation>
<translation id="5344579389779391559">Esta página pode tentar cobrar pagamento em dinheiro</translation>
<translation id="5355557959165512791">Não é possível acessar <ph name="SITE" /> neste momento, porque o certificado dele foi revogado. Como os ataques e erros de rede são geralmente temporários, esta página provavelmente funcionará mais tarde.</translation>
<translation id="536296301121032821">Falha ao armazenar as configurações da política</translation>
+<translation id="5363309033720083897">Porta serial permitida pelo administrador</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="5386426401304769735">A cadeia de certificados desse site contém um certificado assinado usando SHA-1.</translation>
@@ -1178,6 +1211,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="5398772614898833570">Anúncios bloqueados</translation>
<translation id="5400836586163650660">Cinza</translation>
<translation id="540969355065856584">Este servidor não conseguiu provar que é <ph name="DOMAIN" />. O certificado de segurança dele não é válido no momento. Isso pode ser causado por uma configuração incorreta ou pela interceptação da sua conexão por um invasor.</translation>
+<translation id="541143247543991491">Nuvem (todo o sistema)</translation>
<translation id="541416427766103491">Empilhador 4</translation>
<translation id="5421136146218899937">Limpar dados de navegação...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> quer enviar notificações a você</translation>
@@ -1191,6 +1225,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="5455374756549232013">Carimbo de data/hora da política inválido</translation>
<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="5463625433003343978">Localizando dispositivos…</translation>
<translation id="5469868506864199649">Italiano</translation>
<translation id="5470861586879999274">&amp;Refazer editar</translation>
<translation id="5478437291406423475">Envelope 125 mm x 324 mm</translation>
@@ -1240,7 +1275,6 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="5624120631404540903">Gerenciar senhas</translation>
<translation id="5629630648637658800">Falha ao carregar as configurações da política</translation>
<translation id="5631439013527180824">Token de gerenciamento de dispositivo inválido</translation>
-<translation id="5632627355679805402">Seus dados foram criptografados com sua <ph name="BEGIN_LINK" />senha do Google<ph name="END_LINK" /> a partir de <ph name="TIME" />. Digite-a para iniciar a sincronização.</translation>
<translation id="5633066919399395251">Invasores que estão em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> no momento podem tentar instalar programas perigosos no seu computador e roubar ou excluir suas informações (por exemplo, fotos, senhas, mensagens e cartões de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Conteúdo enganoso bloqueado.</translation>
<translation id="5644090287519800334">Mudança X no lado 1 da imagem</translation>
@@ -1279,12 +1313,12 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="5785756445106461925">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="5786044859038896871">Quer preencher as informações do cartão?</translation>
<translation id="578633867165174378">A senha que você acabou de usar foi encontrada pelo Chrome em uma violação de dados. Recomendamos mudá-la agora mesmo.</translation>
-<translation id="5798290721819630480">Descartar alterações?</translation>
<translation id="5803412860119678065">Quer preencher as informações do seu cartão <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Permissões</translation>
<translation id="5804427196348435412">Usar dispositivos NFC</translation>
<translation id="5810442152076338065">Sua conexão com <ph name="DOMAIN" /> está criptografada com um pacote de criptografia obsoleto.</translation>
<translation id="5813119285467412249">&amp;Refazer adicionar</translation>
+<translation id="5817918615728894473">Parear</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Ao fazer o pagamento, a cobrança é feita neste cartão sem compartilhar o número dele com o site. Para mais segurança, um CVC temporário será gerado.}one{Ao fazer o pagamento, a cobrança é feita no cartão selecionado sem compartilhar o número dele com o site. Para mais segurança, um CVC temporário será gerado.}other{Ao fazer o pagamento, a cobrança é feita nos cartões selecionados sem compartilhar os números deles com o site. Para mais segurança, um CVC temporário será gerado.}}</translation>
<translation id="5826507051599432481">Nome comum (CN)</translation>
<translation id="5838278095973806738">É recomendado não fornecer informações confidencial a esse site (por exemplo, senhas ou cartões de crédito), porque elas podem ser roubadas por invasores.</translation>
@@ -1292,6 +1326,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="5855253129151731373">O nome do host deste site é parecido com o de <ph name="LOOKALIKE_DOMAIN" />. Às vezes, os invasores imitam sites, fazendo modificações quase imperceptíveis no nome de domínio.
Se você acha que essa mensagem foi mostrada por engano, acesse https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals (em inglês).</translation>
+<translation id="5860033963881614850">Desativado</translation>
<translation id="5862579898803147654">Empilhador 8</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>
@@ -1308,6 +1343,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="5913377024445952699">Captura de tela pausada</translation>
<translation id="59174027418879706">Ativado</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 em uso}one{# em uso}other{# em uso}}</translation>
<translation id="5921185718311485855">ativado</translation>
<translation id="5921639886840618607">Salvar cartão na Conta do Google?</translation>
<translation id="5922853866070715753">Quase pronto</translation>
@@ -1327,6 +1363,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="5989320800837274978">Nem os servidores proxy fixos nem o URL de script .pac foram especificados.</translation>
<translation id="5992691462791905444">Dobra sanfona</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultados para "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Clássico</translation>
<translation id="6008122969617370890">Ordem N a 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Verificar suas senhas</translation>
@@ -1348,6 +1385,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="6045164183059402045">Modelo de imposição</translation>
<translation id="6047233362582046994">Se você conhece os riscos para sua segurança, pode <ph name="BEGIN_LINK" />visitar este site<ph name="END_LINK" /> antes de os apps prejudiciais serem removidos.</translation>
<translation id="6047927260846328439">Este conteúdo pode tentar enganar você para que instale um software ou revele informações pessoais. <ph name="BEGIN_LINK" />Mostrar mesmo assim<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Toque em |<ph name="ACCELERATOR" />| e mantenha essa tecla pressionada para sair do modo tela cheia</translation>
<translation id="6049488691372270142">Entrega de página</translation>
<translation id="6051221802930200923">Não é possível acessar <ph name="SITE" /> no momento, porque o site usa bloqueio de certificados. Como os ataques e erros de rede são geralmente temporários, esta pagina provavelmente funcionará mais tarde.</translation>
<translation id="6051898664905071243">Contagem de páginas:</translation>
@@ -1364,6 +1402,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<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>
<translation id="6116338172782435947">Ver os textos e imagens copiados para a área de transferência</translation>
<translation id="6120179357481664955">Lembrar código da UPI?</translation>
+<translation id="6123290840358279103">Ver cartão virtual</translation>
<translation id="6124432979022149706">Conectores do Chrome Enterprise</translation>
<translation id="6146055958333702838">Verifique todos os cabos e reinicie todos os roteadores, modens ou outros
dispositivos de rede que você estiver usando.</translation>
@@ -1400,6 +1439,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="6289939620939689042">Cor da página</translation>
<translation id="6290238015253830360">Os artigos sugeridos aparecerão aqui</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Parando o Google Assistente no Chrome</translation>
<translation id="6305205051461490394">Não é possível acessar <ph name="URL" />.</translation>
<translation id="6312113039770857350">Página da Web não disponível</translation>
@@ -1425,6 +1465,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="6390200185239044127">Dobra sanfona simples</translation>
<translation id="6390662030813198813">Engineering E</translation>
<translation id="6393956493820063117">A política do administrador bloqueou a opção de colar conteúdo de <ph name="ORIGIN_NAME" /> neste local</translation>
+<translation id="6398765197997659313">Sair do modo tela cheia</translation>
<translation id="6401136357288658127">Essa política está obsoleta. Use a política <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Editar favorito</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1437,7 +1478,6 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="6428450836711225518">Verificar seu número de telefone</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="6440503408713884761">Ignorada</translation>
<translation id="6443406338865242315">quais extensões e plug-ins você instalou;</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1480,6 +1520,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="6624427990725312378">Informações de Contato</translation>
<translation id="6626291197371920147">Adicionar número de cartão de crédito válido</translation>
<translation id="6628463337424475685">Pesquisa do <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Procurando dispositivos USB…</translation>
<translation id="6630809736994426279">Invasores presentes no momento em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> podem tentar instalar programas perigosos no seu Mac e roubar ou excluir suas informações (por exemplo, fotos, senhas, mensagens e cartões de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Limpar</translation>
@@ -1495,6 +1536,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="6671697161687535275">Remover sugestão de formulário do Chromium?</translation>
<translation id="6685834062052613830">Saia e conclua a configuração</translation>
<translation id="6687335167692595844">Tamanho da fonte solicitado</translation>
+<translation id="6688743156324860098">Atualizar…</translation>
<translation id="6689249931105087298">Relativa com compressão de pontos pretos</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="6698381487523150993">Criado em:</translation>
@@ -1510,6 +1552,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="6744009308914054259">Enquanto espera por uma conexão, acesse "Downloads" para ler artigos off-line.</translation>
<translation id="6753269504797312559">Valor da política</translation>
<translation id="6757797048963528358">O dispositivo entrou em modo de suspensão.</translation>
+<translation id="6767985426384634228">Atualizar endereço?</translation>
<translation id="6768213884286397650">Hagaki (Postal)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violeta</translation>
@@ -1532,6 +1575,7 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">O Chrome simplificou esta página para facilitar a leitura. A página original foi recuperada por uma conexão não segura.</translation>
<translation id="6891596781022320156">O nível da política não é suportado.</translation>
+<translation id="6895143722905299846">Número virtual:</translation>
<translation id="6895330447102777224">Seu cartão foi confirmado</translation>
<translation id="6897140037006041989">Agente do usuário</translation>
<translation id="6898699227549475383">O (Organização)</translation>
@@ -1567,10 +1611,10 @@ Se não fizer isso, a permissão será bloqueada pelas configurações de privac
<translation id="7004583254764674281">Use o Windows Hello para confirmar o uso de cartões mais rapidamente</translation>
<translation id="7006930604109697472">Enviar mesmo assim</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Configurações de redimensionamento</translation>
<translation id="7014741021609395734">Nível de zoom</translation>
<translation id="7016992613359344582">Essas cobranças podem ser únicas ou recorrentes e talvez não sejam óbvias.</translation>
<translation id="7029809446516969842">Senhas</translation>
+<translation id="7030436163253143341">O certificado não é válido</translation>
<translation id="7031646650991750659">quais apps do Google Play estão instalados.</translation>
<translation id="7050187094878475250">Você tentou acessar <ph name="DOMAIN" />, mas o servidor apresentou um certificado cujo período de validade é extremamente longo, o que não é confiável.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Não é possível salvar esse cartão no momento}one{Não é possível salvar esse cartão no momento}other{Não é possível salvar esses cartões no momento}}</translation>
@@ -1640,12 +1684,14 @@ Mais detalhes:
<translation id="7300012071106347854">Azul-cobalto</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Alto</translation>
+<translation id="7305756307268530424">Iniciar mais devagar</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Ajuda de conexão</translation>
<translation id="7323804146520582233">Ocultar a seção "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Substituição de conta local do dispositivo</translation>
<translation id="7333654844024768166">Você acabou de digitar sua senha em um site suspeito. O Chromium recomenda acessar <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> e outros sites em que você usa essa senha para mudá-la agora mesmo.</translation>
<translation id="7334320624316649418">&amp;Refazer reordenar</translation>
+<translation id="7337248890521463931">Mostrar mais linhas</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>
@@ -1653,6 +1699,7 @@ Mais detalhes:
<translation id="7349430561505560861">A4 Extra</translation>
<translation id="7353601530677266744">Linha de comando</translation>
<translation id="7359588939039777303">Anúncios bloqueados.</translation>
+<translation id="7363096869660964304">No entanto, você não fica invisível. Entrar no modo de navegação anônima não oculta a navegação do seu empregador, do provedor de acesso à Internet ou dos sites acessados.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />. Pressione "Tab" e "Enter" para adicionar e gerenciar endereços nas configurações do Chrome</translation>
<translation id="7365849542400970216">Saber quando o dispositivo está sendo usado?</translation>
<translation id="7372973238305370288">resultado da pesquisa</translation>
@@ -1663,7 +1710,9 @@ Mais detalhes:
<translation id="7378594059915113390">Controles de mídia</translation>
<translation id="7378627244592794276">Não</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Não aplicável</translation>
<translation id="7390545607259442187">Confirmar cartão</translation>
+<translation id="7392089738299859607">Atualizar endereço</translation>
<translation id="7399802613464275309">Confirmação de segurança</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Seu <ph name="DEVICE_NAME" /> é gerenciado</translation>
@@ -1678,6 +1727,7 @@ Mais detalhes:
&lt;li&gt;Visite a &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Central de Ajuda do Chrome&lt;/a&gt; para saber como remover permanentemente o software do seu computador
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Formato largo</translation>
+<translation id="7410471291937727359">Adorável</translation>
<translation id="7416351320495623771">Gerenciar senhas…</translation>
<translation id="7419106976560586862">Caminho de perfil</translation>
<translation id="7437289804838430631">Adicionar Informações de Contato</translation>
@@ -1693,7 +1743,7 @@ Mais detalhes:
<translation id="7481312909269577407">Avançar</translation>
<translation id="7485870689360869515">Nenhum dado encontrado</translation>
<translation id="7495528107193238112">Este conteúdo está bloqueado. Entre em contato com o proprietário do site para corrigir o problema.</translation>
-<translation id="7498234416455752244">Continuar editando</translation>
+<translation id="7498193950643227031">Pode apresentar comportamento inesperado caso seja redimensionado. Em "<ph name="SETTINGS" />", agora é possível limitar o recurso de redimensionamento de apps.</translation>
<translation id="7503664977220660814">Você acabou de digitar sua senha em um site suspeito. O Chromium recomenda que você verifique agora suas senhas salvas para <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> e outros sites em que você usa essa senha.</translation>
<translation id="7508255263130623398">O código do dispositivo da política retornado está em branco ou não corresponde ao código do dispositivo atual</translation>
<translation id="7508870219247277067">Verde-abacate</translation>
@@ -1713,6 +1763,7 @@ Mais detalhes:
<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="755279583747225797">O teste está ativo</translation>
<translation id="7552846755917812628">Tente seguir estas dicas:</translation>
<translation id="7554475479213504905">Atualizar e mostrar mesmo assim</translation>
<translation id="7554791636758816595">Nova guia</translation>
@@ -1731,7 +1782,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Pressione "Tab" e depois "Enter" para ver e gerenciar suas senhas nas configurações do Chrome</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="7616645509853975347">O administrador ativou os Chrome Enterprise Connectors no seu navegador. Esses conectores têm acesso a alguns dos seus dados.</translation>
<translation id="7619838219691048931">Última página</translation>
<translation id="762844065391966283">Um de cada vez</translation>
@@ -1796,13 +1846,12 @@ Mais detalhes:
<translation id="782886543891417279">O Wi-Fi que você está usando (<ph name="WIFI_NAME" />) pode exigir a visita a uma página de login.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Nenhum}=1{1 app (<ph name="EXAMPLE_APP_1" />)}=2{2 apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# app (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}other{# apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">O modo invisível NÃO oculta seus dados de navegação. Seu empregador, seu provedor de Internet e os websites visitados continuam tendo acesso a essas informações.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Abrir arquivos com associações a tipos de arquivo.</translation>
<translation id="7862185352068345852">Sair do site?</translation>
<translation id="7865448901209910068">Melhor velocidade</translation>
<translation id="7874263914261512992">Você acabou de digitar sua senha em um site suspeito. O Chrome recomenda que você verifique agora suas senhas salvas para <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> e outros sites em que você usa essa senha.</translation>
<translation id="7878562273885520351">Sua senha pode estar comprometida</translation>
+<translation id="7880146494886811634">Salvar endereço</translation>
<translation id="7882421473871500483">Marrom</translation>
<translation id="7887683347370398519">Verifique seu CVC e tente novamente</translation>
<translation id="7887885240995164102">Entrar no modo picture-in-picture</translation>
@@ -1810,6 +1859,7 @@ Mais detalhes:
<translation id="7894280532028510793">Se o endereço estiver correto, <ph name="BEGIN_LINK" />tente executar o Diagnóstico de Rede<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Desconhecido</translation>
+<translation id="793209273132572360">Atualizar endereço?</translation>
<translation id="7932579305932748336">Revestir</translation>
<translation id="79338296614623784">Informe um número de telefone válido</translation>
<translation id="7934052535022478634">Pagamento concluído</translation>
@@ -1880,6 +1930,7 @@ Mais detalhes:
<translation id="8175796834047840627">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.</translation>
<translation id="8176440868214972690">O administrador do dispositivo enviou algumas informações, como configurações ou políticas, aos sites a seguir.</translation>
<translation id="8184538546369750125">Usar padrão global (Permitir)</translation>
+<translation id="8193086767630290324">Ações realizadas em dados marcados como confidenciais</translation>
<translation id="8194797478851900357">&amp;Desfazer mover</translation>
<translation id="8201077131113104583">URL de atualização inválido para extensão com ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Resumo do pedido</translation>
@@ -1902,6 +1953,7 @@ Mais detalhes:
<translation id="8249296373107784235">Cancelar</translation>
<translation id="8249320324621329438">Última busca:</translation>
<translation id="8253091569723639551">Endereço de faturamento necessário</translation>
+<translation id="8257387598443225809">Esse app foi feito para dispositivos móveis</translation>
<translation id="825929999321470778">Mostrar todas as senhas salvas</translation>
<translation id="8261506727792406068">Excluir</translation>
<translation id="8262952874573525464">Costura na parte inferior</translation>
@@ -2026,7 +2078,6 @@ Mais detalhes:
<translation id="8719528812645237045">Perfuração múltipla na parte superior</translation>
<translation id="8725066075913043281">Tentar novamente</translation>
<translation id="8726549941689275341">Tamanho da página:</translation>
-<translation id="8728672262656704056">Você está navegando sem deixar rastros</translation>
<translation id="8730621377337864115">Concluído</translation>
<translation id="8731544501227493793">Botão "Gerenciar senhas". Pressione "Enter" para ver e gerenciar suas senhas nas configurações do Chrome</translation>
<translation id="8734529307927223492">Seu <ph name="DEVICE_TYPE" /> é gerenciado por <ph name="MANAGER" /></translation>
@@ -2103,6 +2154,7 @@ Mais detalhes:
<translation id="9020542370529661692">Esta página foi traduzida para <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(inválido)</translation>
+<translation id="9030265603405983977">Monocromático</translation>
<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>
@@ -2127,6 +2179,7 @@ incomuns e incorretas. Isso pode acontecer quando um invasor está fingindo ser
<translation id="91108059142052966">A política do administrador desativará o compartilhamento de tela com <ph name="APPLICATION_TITLE" /> quando houver conteúdo confidencial visível</translation>
<translation id="9114524666733003316">Confirmando cartão…</translation>
<translation id="9114581008513152754">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="9117930699067497412">Revigorado</translation>
<translation id="9119042192571987207">Enviado</translation>
<translation id="9128016270925453879">As políticas foram carregadas</translation>
<translation id="9128870381267983090">Conectar à rede</translation>
@@ -2145,6 +2198,7 @@ incomuns e incorretas. Isso pode acontecer quando um invasor está fingindo ser
<translation id="9170848237812810038">&amp;Desfazer</translation>
<translation id="9171296965991013597">Sair do app?</translation>
<translation id="9173282814238175921">Documento avulso/Nova página</translation>
+<translation id="9173995187295789444">Procurando dispositivos Bluetooth…</translation>
<translation id="917450738466192189">O certificado do servidor é inválido.</translation>
<translation id="9174917557437862841">Botão de alternância de guia. Pressione Enter para alternar para esta guia</translation>
<translation id="9179703756951298733">Gerencie seus pagamentos e suas informações de cartão de crédito nas configurações do Chrome</translation>
diff --git a/chromium/components/strings/components_strings_pt-PT.xtb b/chromium/components/strings/components_strings_pt-PT.xtb
index e72021e9494..44bf12fe8a7 100644
--- a/chromium/components/strings/components_strings_pt-PT.xtb
+++ b/chromium/components/strings/components_strings_pt-PT.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Se marcada, o Chrome armazena uma cópia do seu cartão neste dispositivo para preencher formulários mais rapidamente.</translation>
<translation id="1110994991967754504">Selecionar autorização para <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Anular reordenação</translation>
+<translation id="1123753900084781868">As Legendas instantâneas não estão disponíveis neste momento.</translation>
<translation id="1125573121925420732">Pode ser frequente a apresentação de avisos enquanto os Websites atualizam a respetiva segurança. Esta situação deve melhorar brevemente.</translation>
<translation id="112840717907525620">Cache da política OK</translation>
<translation id="1130564665089811311">Botão Traduzir página; prima Enter para traduzir esta página com o Google Tradutor.</translation>
@@ -74,6 +75,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="1240347957665416060">O nome do dispositivo</translation>
<translation id="124116460088058876">Mais idiomas</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Negrito</translation>
<translation id="1250759482327835220">Para pagar mais rapidamente da próxima vez, guarde o cartão, o nome e o endereço de faturação na sua Conta Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sincronizados)</translation>
<translation id="1256368399071562588">&lt;p&gt;Se tentar aceder a um Website e este não abrir, primeiro, tente corrigir o erro com estes passos de resolução de problemas:&lt;/p&gt;
@@ -156,6 +158,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="1476595624592550506">Altere a palavra-passe</translation>
<translation id="1484290072879560759">Escolher morada para envio</translation>
<translation id="1492194039220927094">Push das políticas:</translation>
+<translation id="1495677929897281669">Voltar ao separador</translation>
<translation id="1501859676467574491">Mostrar cartões da sua Conta Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Este erro é apresentado se estiver a utilizar um portal Wi-Fi que requer que inicie sessão para poder aceder à Internet.&lt;/p&gt;
&lt;p&gt;Para corrigir o erro, clique em &lt;strong&gt;Ligar&lt;/strong&gt; na página que está a tentar abrir.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="1532118530259321453">Esta página diz</translation>
<translation id="153384715582417236">É tudo por agora</translation>
<translation id="1536390784834419204">Traduzir página</translation>
+<translation id="1539840569003678498">Denúncia enviada:</translation>
<translation id="154408704832528245">Escolher endereço de entrega</translation>
<translation id="1549470594296187301">É necessário ativar o JavaScript para utilizar esta funcionalidade.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="1682696192498422849">Margem estreita primeiro</translation>
<translation id="168693727862418163">Ocorreu um erro na validação desta política em relação ao respetivo esquema e a mesma será ignorada.</translation>
<translation id="168841957122794586">O certificado do servidor contém uma chave criptográfica fraca.</translation>
+<translation id="1696290444144917273">Veja detalhes do cartão virtual</translation>
<translation id="1697532407822776718">O processo está concluído!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Este servidor não conseguiu provar que é <ph name="DOMAIN" />; o seu certificado de segurança é supostamente de amanhã. Isto pode ser o resultado de uma configuração incorreta ou de um invasor a intercetar a sua ligação.}other{Este servidor não conseguiu provar que é <ph name="DOMAIN" />; a data do seu certificado de segurança é supostamente daqui a # dias. Isto pode ser o resultado de uma configuração incorreta ou de um invasor a intercetar a sua ligação.}}</translation>
<translation id="1710259589646384581">SO</translation>
+<translation id="1711234383449478798">Ignorada porque a política <ph name="POLICY_NAME" /> não está definida como <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> pretende armazenar permanentemente os dados no seu computador local.</translation>
<translation id="1713628304598226412">Tabuleiro 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Caixa de correio 3</translation>
<translation id="1718029547804390981">O documento é demasiado grande para ser anotado.</translation>
<translation id="1721424275792716183">* Campo de preenchimento obrigatório</translation>
+<translation id="1727613060316725209">O certificado é válido</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>
<translation id="173080396488393970">Este tipo de cartão não é suportado</translation>
@@ -246,7 +253,6 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
o seu pedido para <ph name="SITE" />. As políticas de origem podem ser utilizadas
pelos operadores de sites para configurar a segurança e outras propriedades de um site.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Atualize a frase de acesso de sincronização.</translation>
<translation id="1787142507584202372">Os separadores abertos aparecem aqui</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, estão disponíveis várias ações, prima Tab para as percorrer.</translation>
@@ -279,6 +285,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="1919345977826869612">Anúncios</translation>
<translation id="1919367280705858090">Obter ajuda relativamente a uma mensagem de erro específica</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Nenhum}=1{1 site}other{# sites}}</translation>
+<translation id="1924727005275031552">Novo</translation>
<translation id="1945968466830820669">Pode perder o acesso à conta da sua entidade ou ser vítima de roubo de identidade. O Chromium recomenda a alteração da palavra-passe agora.</translation>
<translation id="1947454675006758438">Agrafo na parte superior direita</translation>
<translation id="1958218078413065209">A sua pontuação mais alta é <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="2042213636306070719">Tabuleiro 7</translation>
<translation id="204357726431741734">Iniciar sessão para utilizar palavras-passe guardadas na sua Conta Google</translation>
<translation id="2053111141626950936">As páginas em <ph name="LANGUAGE" /> não serão traduzidas.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Quando este controlo está ativado e o estado está ativo, o Chrome determina a que grupo alargado de pessoas, ou "coorte", a sua atividade de navegação recente é mais semelhante. Os anunciantes podem selecionar anúncios para o grupo e a sua atividade de navegação permanece privada no seu dispositivo. O seu grupo é atualizado todos os dias.}=1{Quando este controlo está ativado e o estado está ativo, o Chrome determina a que grupo alargado de pessoas, ou "coorte", a sua atividade de navegação recente é mais semelhante. Os anunciantes podem selecionar anúncios para o grupo e a sua atividade de navegação permanece privada no seu dispositivo. O seu grupo é atualizado todos os dias.}other{Quando este controlo está ativado e o estado está ativo, o Chrome determina a que grupo alargado de pessoas, ou "coorte", a sua atividade de navegação recente é mais semelhante. Os anunciantes podem selecionar anúncios para o grupo e a sua atividade de navegação permanece privada no seu dispositivo. O seu grupo é atualizado a cada {NUM_DAYS} dias.}}</translation>
<translation id="2053553514270667976">Código postal</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugestão}other{# sugestões}}</translation>
<translation id="2071692954027939183">As notificações foram automaticamente bloqueadas porque, geralmente, não as permite.</translation>
<translation id="2079545284768500474">Anular</translation>
<translation id="20817612488360358">As definições de proxy do sistema estão definidas para serem utilizadas, mas também está especificada uma configuração de proxy explícita.</translation>
<translation id="2082238445998314030">Resultado <ph name="RESULT_NUMBER" /> de <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Guardar…</translation>
<translation id="2088086323192747268">Botão Gerir sincronização. Prima Enter para gerir as informações que sincroniza nas Definições do Chrome.</translation>
<translation id="2091887806945687916">Som</translation>
<translation id="2094505752054353250">Falta de correspondência de domínio</translation>
@@ -379,6 +388,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="2317259163369394535">O domínio <ph name="DOMAIN" /> requer um nome de utilizador e uma palavra-passe.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, expira a <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Definição controlada pelo gestor</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> pretende sincronizar</translation>
<translation id="2344028582131185878">Transferências automáticas</translation>
<translation id="2346319942568447007">Imagem que copiou</translation>
<translation id="2354001756790975382">Outros marcadores</translation>
@@ -386,8 +396,10 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="2355395290879513365">Os atacantes podem ver as imagens que está a visualizar neste site e enganá-lo ao modificá-las.</translation>
<translation id="2356070529366658676">Perguntar</translation>
<translation id="2357481397660644965">O seu dispositivo é gerido por <ph name="DEVICE_MANAGER" /> e a sua conta é gerida por <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Em menos de 1 dia}=1{Dentro de 1 dia}other{Dentro de {NUM_DAYS} dias}}</translation>
<translation id="2359629602545592467">Várias</translation>
<translation id="2359808026110333948">Continuar</translation>
+<translation id="2359961752320758691">O número do seu cartão virtual foi aplicado.</translation>
<translation id="2367567093518048410">Nível</translation>
<translation id="2372464001869762664">Depois de confirmar, os detalhes do cartão da sua Conta Google são partilhados com este site. Procure o CVC nos seus detalhes da conta Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="239429038616798445">Este método de envio não está disponível. Experimente um método diferente.</translation>
<translation id="2396249848217231973">&amp;Anular eliminação</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Antigo</translation>
<translation id="2413528052993050574">Este servidor não conseguiu provar que é o domínio <ph name="DOMAIN" />; o respetivo certificado de segurança poderá ser revogado. Isto pode ser o resultado de uma configuração incorreta ou de um invasor a intercetar a sua ligação.</translation>
<translation id="2414886740292270097">Escuro</translation>
<translation id="2438874542388153331">Perfuração quádrupla à direita</translation>
@@ -425,10 +438,10 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="2521385132275182522">Agrafar parte inferior direita</translation>
<translation id="2523886232349826891">Guardado apenas neste dispositivo.</translation>
<translation id="2524461107774643265">Adicionar mais informações</translation>
-<translation id="2526590354069164005">Ambiente de trabalho</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{e mais 1}other{e mais #}}</translation>
<translation id="2536110899380797252">Adicionar endereço</translation>
<translation id="2539524384386349900">Detetar</translation>
+<translation id="2541219929084442027">As páginas que visualizar em separadores de navegação anónima não são memorizadas no histórico do navegador, no armazenamento de cookies ou no histórico de pesquisas depois de fechar todos os separadores de navegação anónima. Todos os ficheiros transferidos ou os marcadores criados são guardados.</translation>
<translation id="2544644783021658368">Documento único</translation>
<translation id="254947805923345898">O valor da política não é válido.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> enviou uma resposta inválida.</translation>
@@ -448,6 +461,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="2629325967560697240">Para obter o nível de segurança mais elevado do Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ative a proteção melhorada<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Não foi possível encontrar o endereço IP do servidor de <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Estado:</translation>
+<translation id="264810637653812429">Não foram encontrados dispositivos compatíveis.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, prima Tab e, em seguida, Enter para limpar o seu histórico de navegação, cookies, cache e muito mais nas Definições do Chrome.</translation>
<translation id="2650446666397867134">O acesso ao ficheiro foi negado</translation>
@@ -494,6 +508,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<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="2807052079800581569">Posição Y da imagem</translation>
+<translation id="2820957248982571256">A analisar...</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>
@@ -501,6 +516,8 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">Este site apresenta anúncios intrusivos ou enganadores.</translation>
+<translation id="287596039013813457">Amigável</translation>
+<translation id="2876489322757410363">Está a sair do Modo de navegação anónima para pagar através de uma aplicação externa. Pretende continuar?</translation>
<translation id="2878197950673342043">Dobra cruzada</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Posicionamento de janelas</translation>
@@ -550,7 +567,6 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, prima Tab e, em seguida, Enter para executar a verificação de segurança nas Definições do Chrome.</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>
<translation id="306573536155379004">Jogo iniciado.</translation>
<translation id="3080254622891793721">Gráfico</translation>
<translation id="3086579638707268289">A sua atividade na Web está a ser monitorizada</translation>
@@ -573,7 +589,6 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="315504272643575312">A sua conta é gerida por <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Restaurar</translation>
<translation id="3162559335345991374">A rede Wi-Fi que está a utilizar pode exigir que visite a respetiva página de início de sessão.</translation>
-<translation id="3167968892399408617">As páginas que visualizar em separadores de navegação anónima não são memorizadas no histórico do navegador, no armazenamento de cookies ou no histórico de pesquisas depois de fechar todos os separadores de navegação anónima. Todos os ficheiros transferidos ou os marcadores criados são guardados.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ilha</translation>
<translation id="3176929007561373547">Verifique as definições de proxy ou contacte o gestor de rede para
@@ -599,10 +614,12 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<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="3249845759089040423">Descontraído</translation>
<translation id="3252266817569339921">Francês</translation>
<translation id="3266793032086590337">Valor (em conflito)</translation>
<translation id="3268451620468152448">Abrir Separadores</translation>
<translation id="3270847123878663523">&amp;Anular reordenação</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> pretende estabelecer ligação</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">A sua entidade, <ph name="ENROLLMENT_DOMAIN" />, enviou algumas informações para os seguintes Websites, como definições ou políticas.</translation>
<translation id="3282497668470633863">Adicionar nome no cartão</translation>
@@ -655,6 +672,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="3428151540071562330">Um ou mais URIs de modelos do servidor DnsOverHttpsTemplates são inválidos e não serão utilizados.</translation>
<translation id="3431636764301398940">Guardar este cartão neste dispositivo</translation>
<translation id="3432601291244612633">Fechar página</translation>
+<translation id="3435738964857648380">Segurança</translation>
<translation id="3435896845095436175">Ativar</translation>
<translation id="3438829137925142401">Utilizar palavras-passe guardadas na sua Conta Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="3584299510153766161">Perfuração dupla na parte inferior</translation>
<translation id="3586931643579894722">Ocultar detalhes</translation>
<translation id="3587738293690942763">Central</translation>
+<translation id="3590643883886679995">Os dados de início de sessão são armazenados neste dispositivo depois de sair do Modo de navegação anónima.</translation>
+<translation id="359126217934908072">Mês/ano:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Pode repor o grupo em qualquer altura. A adesão a um novo grupo demora cerca de um dia.}=1{Pode repor o grupo em qualquer altura. A adesão a um novo grupo demora cerca de um dia.}other{Pode repor o grupo em qualquer altura. A adesão a um novo grupo demora cerca de {NUM_DAYS} dias.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">App bloqueada pelo seu administrador</translation>
<translation id="3608932978122581043">Guiar a orientação</translation>
@@ -706,13 +727,13 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="3615877443314183785">Introduza uma data de expiração válida</translation>
<translation id="36224234498066874">Limpar dados de navegação...</translation>
<translation id="362276910939193118">Mostrar histórico completo</translation>
-<translation id="3625635938337243871">Os dados de início de sessão são armazenados neste dispositivo depois de sair do Modo de navegação anónima.</translation>
<translation id="3630155396527302611">Se já estiver indicado na lista como sendo um programa com permissão para aceder à rede, experimente
removê-lo da lista e adicioná-lo novamente.</translation>
<translation id="3630699740441428070">Os administradores deste dispositivo configuraram a ligação de rede, que lhes pode permitir ver o tráfego de rede, incluindo os Websites visitados por si.</translation>
<translation id="3631244953324577188">Biometria</translation>
<translation id="3633738897356909127">Botão Atualizar Chrome; prima Enter para atualizar o Chrome nas Definições do Chrome.</translation>
<translation id="3634530185120165534">Tabuleiro 5</translation>
+<translation id="3637662659967048211">Guardar na Conta Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplicação:</translation>
<translation id="3650584904733503804">Validação com êxito</translation>
@@ -753,6 +774,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="3781428340399460090">Rosa choque</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Dispositivos Bluetooth</translation>
+<translation id="3787675388804467730">Número de cartão virtual</translation>
<translation id="3787705759683870569">Expira a <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Tamanho 16</translation>
<translation id="3789841737615482174">Instalar</translation>
@@ -772,6 +794,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="3841184659773414994">Controladores de ficheiros</translation>
<translation id="385051799172605136">Anterior</translation>
<translation id="3858027520442213535">Atualizar a data e a hora</translation>
+<translation id="3881478300875776315">Mostrar menos linhas</translation>
<translation id="3884278016824448484">Identificador do dispositivo em conflito</translation>
<translation id="3885155851504623709">Freguesia</translation>
<translation id="388632593194507180">Monitorização detetada</translation>
@@ -797,6 +820,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="397105322502079400">A calcular...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> está bloqueado</translation>
<translation id="3973357910713125165">Botão Executar verificação de segurança do Chrome, prima Enter para executar a verificação de segurança nas Definições do Chrome.</translation>
+<translation id="3986705137476756801">Desativar as Legendas instantâneas por agora</translation>
<translation id="3987405730340719549">O Chrome determinou que este site pode ser falso ou fraudulento.
Se acha que se trata de um erro, aceda a https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="4275830172053184480">Reiniciar o dispositivo</translation>
<translation id="4277028893293644418">Repor palavra-passe</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="4287885627794386150">Elegível para avaliação, mas não ativa</translation>
<translation id="4297502707443874121">Miniatura da página <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Expandir</translation>
<translation id="4300675098767811073">Perfuração múltipla à direita</translation>
<translation id="4302514097724775343">Toque no dinossauro para jogar.</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Não foi possível aceder ao seu ficheiro</translation>
-<translation id="4305817255990598646">Mudar</translation>
+<translation id="4306529830550717874">Pretende guardar o endereço?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloquear (predefinição)</translation>
<translation id="4314815835985389558">Gerir sincronização</translation>
@@ -926,6 +951,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="4377125064752653719">Tentou aceder a <ph name="DOMAIN" />, mas o certificado que o servidor apresentou foi revogado pelo emissor. Isto significa que as credenciais de segurança apresentadas pelo servidor não deverão, em circunstância alguma, ser consideradas fidedignas. Pode estar a comunicar com um utilizador mal intencionado.</translation>
<translation id="4378154925671717803">Telemóvel</translation>
<translation id="4390472908992056574">Borda</translation>
+<translation id="4406883609789734330">Legendas instantâneas</translation>
<translation id="4406896451731180161">resultados da pesquisa</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Acabou de introduzir a sua palavra-passe num site fraudulento. O Chrome recomenda que aceda a <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> e outros sites em que utilize esta palavra-passe e a altere agora.</translation>
@@ -938,7 +964,6 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<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="4464826014807964867">Websites com informações sobre a sua entidade</translation>
-<translation id="4466881336512663640">As alterações ao formulário serão perdidas. Tem a certeza de que pretende continuar?</translation>
<translation id="4476953670630786061">Este formulário não é seguro. O preenchimento automático foi desativado.</translation>
<translation id="4477350412780666475">Faixa seguinte</translation>
<translation id="4482953324121162758">Este site não será traduzido.</translation>
@@ -972,6 +997,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="4594403342090139922">&amp;Anular eliminação</translation>
<translation id="4597348597567598915">Tamanho 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Impactante</translation>
<translation id="4628948037717959914">Fotografia</translation>
<translation id="4631649115723685955">Reembolso associado</translation>
<translation id="4636930964841734540">Informações</translation>
@@ -991,6 +1017,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Lado</translation>
+<translation id="4702656508969495934">Legendas instantâneas visíveis, utilize o comutador de janelas para focar</translation>
<translation id="4708268264240856090">A ligação foi interrompida</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Executar o Diagnóstico de rede do Windows<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="4738601419177586157">Sugestão de pesquisa de <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Gerir palavras-passe…</translation>
<translation id="4744603770635761495">Caminho do Executável</translation>
+<translation id="4749011317274908093">Está na Navegação anónima</translation>
<translation id="4750917950439032686">As suas informações (por exemplo, palavras-passe ou números de cartões de crédito) são privadas quando são enviadas para este site.</translation>
<translation id="4756388243121344051">&amp;Histórico</translation>
<translation id="4758311279753947758">Adicionar informações de contacto</translation>
@@ -1033,6 +1061,8 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="4813512666221746211">Erro de rede</translation>
<translation id="4816492930507672669">Ajustar à página</translation>
<translation id="4819347708020428563">Pretende editar anotações na vista predefinida?</translation>
+<translation id="4825507807291741242">Potente</translation>
+<translation id="4838327282952368871">Sonhador</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">Ver</translation>
<translation id="485316830061041779">Alemão</translation>
@@ -1169,6 +1199,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="5314967030527622926">Criador de folhetos</translation>
<translation id="5316812925700871227">Rodar para a esquerda</translation>
<translation id="5317780077021120954">Guardar</translation>
+<translation id="5321288445143113935">Maximizada</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> de <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Escolher informações de contacto</translation>
<translation id="5327248766486351172">Nome</translation>
@@ -1176,11 +1207,13 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="5332219387342487447">Método de envio</translation>
<translation id="5333022057423422993">O Chrome encontrou a palavra-passe que acabou de utilizar numa violação de dados. Para proteger as suas contas, recomendamos que verifique as suas palavras-passe guardadas.</translation>
<translation id="5334013548165032829">Registos de sistema detalhados</translation>
+<translation id="5334145288572353250">Pretende guardar o endereço?</translation>
<translation id="5340250774223869109">A app está bloqueada</translation>
<translation id="534295439873310000">Dispositivos NFC</translation>
<translation id="5344579389779391559">Esta página pode tentar cobrar-lhe dinheiro</translation>
<translation id="5355557959165512791">Não pode visitar <ph name="SITE" /> neste momento, porque o certificado foi revogado. Os erros de rede e os ataques são geralmente temporários, pelo que esta página deverá funcionar mais tarde.</translation>
<translation id="536296301121032821">Falha ao armazenar as definições da política</translation>
+<translation id="5363309033720083897">Porta de série permitida pelo seu administrador</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="5386426401304769735">A cadeia de certificados inclui um certificado assinado através de SHA-1.</translation>
@@ -1189,6 +1222,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="5398772614898833570">Anúncios bloqueados</translation>
<translation id="5400836586163650660">Cinzento</translation>
<translation id="540969355065856584">Este servidor não conseguiu provar que é <ph name="DOMAIN" />; de momento, o respetivo certificado de segurança não é válido. Isto pode ser provocado por uma configuração incorreta ou por um atacante que esteja a intercetar a sua ligação.</translation>
+<translation id="541143247543991491">Nuvem (em todo o sistema)</translation>
<translation id="541416427766103491">Empilhador 4</translation>
<translation id="5421136146218899937">Limpar dados de navegação...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> pretende enviar-lhe notificações.</translation>
@@ -1202,6 +1236,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="5455374756549232013">Carimbo de data/hora da política incorreto</translation>
<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="5463625433003343978">A localizar dispositivos…</translation>
<translation id="5469868506864199649">Italiano</translation>
<translation id="5470861586879999274">&amp;Refazer edição</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1251,7 +1286,6 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="5624120631404540903">Gerir palavras-passe</translation>
<translation id="5629630648637658800">Falha ao carregar as definições da política</translation>
<translation id="5631439013527180824">Token de gestão do dispositivo inválido</translation>
-<translation id="5632627355679805402">Os dados foram encriptados com a sua <ph name="BEGIN_LINK" />palavra-passe do Google<ph name="END_LINK" /> à(s) <ph name="TIME" />. Introduza a mesma para iniciar a sincronização.</translation>
<translation id="5633066919399395251">Os atacantes atualmente em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> podem tentar instalar programas perigosos no seu computador que roubem ou eliminem as suas informações (por exemplo, fotos, palavras-passe, mensagens e cartões de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Conteúdo fraudulento bloqueado.</translation>
<translation id="5644090287519800334">Turno X da imagem 1 lateral</translation>
@@ -1290,12 +1324,12 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="5785756445106461925">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 aspeto da página.</translation>
<translation id="5786044859038896871">Pretende preencher as informações do cartão?</translation>
<translation id="578633867165174378">O Chrome encontrou a palavra-passe que acabou de utilizar numa violação de dados. Recomendamos que altere agora esta palavra-passe.</translation>
-<translation id="5798290721819630480">Pretende rejeitar as alterações?</translation>
<translation id="5803412860119678065">Pretende preencher o seu cartão <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Permissões</translation>
<translation id="5804427196348435412">Utilizar dispositivos NFC</translation>
<translation id="5810442152076338065">A sua ligação a <ph name="DOMAIN" /> está encriptada através de um conjunto de cifras obsoleto.</translation>
<translation id="5813119285467412249">&amp;Refazer adição</translation>
+<translation id="5817918615728894473">Sincronizar</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Será efetuada uma cobrança neste cartão quando pagar, mas o respetivo número verdadeiro não será partilhado com este site. Como medida de segurança adicional, será gerado um CVC temporário.}other{Será efetuada uma cobrança no cartão que selecionar quando pagar, mas o respetivo número verdadeiro não será partilhado com este site. Como medida de segurança adicional, será gerado um CVC temporário.}}</translation>
<translation id="5826507051599432481">Nome comum (CN)</translation>
<translation id="5838278095973806738">Não deve introduzir informações confidenciais neste site (por exemplo, palavras-passe ou números de cartões de crédito), porque podem ser roubadas por atacantes.</translation>
@@ -1303,6 +1337,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="5855253129151731373">O nome de anfitrião deste site é semelhante a <ph name="LOOKALIKE_DOMAIN" />. Por vezes, os infratores imitam sites ao efetuarem alterações pequenas e difíceis de detetar no nome do domínio.
Se acha que se trata de um erro, aceda a https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Desativado</translation>
<translation id="5862579898803147654">Empilhador 8</translation>
<translation id="5863847714970149516">A próxima página pode tentar cobrar-lhe dinheiro</translation>
<translation id="5866257070973731571">Adicionar número de telefone</translation>
@@ -1319,6 +1354,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="5913377024445952699">Captura de ecrã em pausa</translation>
<translation id="59174027418879706">Ativada</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 em utilização}other{# em utilização}}</translation>
<translation id="5921185718311485855">Ativado</translation>
<translation id="5921639886840618607">Pretende guardar o cartão na Conta Google?</translation>
<translation id="5922853866070715753">Estamos quase a terminar</translation>
@@ -1338,6 +1374,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="5989320800837274978">Não foram especificados servidores proxy fixos nem um URL de script .pac.</translation>
<translation id="5992691462791905444">Dobra em Z vertical com margem superior</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultados para "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Clássico</translation>
<translation id="6008122969617370890">Ordem de N para 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Verifique as suas palavras-passe</translation>
@@ -1359,6 +1396,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="6045164183059402045">Modelo de imposição</translation>
<translation id="6047233362582046994">Se compreende os riscos para a sua segurança, pode <ph name="BEGIN_LINK" />visitar este site<ph name="END_LINK" /> antes de as aplicações prejudiciais terem sido removidas.</translation>
<translation id="6047927260846328439">Este conteúdo pode tentar enganá-lo de forma a que instale software ou revele informações pessoais. <ph name="BEGIN_LINK" />Mostrar mesmo assim<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Prima |<ph name="ACCELERATOR" />| sem soltar para sair do modo de ecrã inteiro.</translation>
<translation id="6049488691372270142">Fornecimento da página</translation>
<translation id="6051221802930200923">Não pode visitar <ph name="SITE" /> neste momento, porque o Website utiliza a afixação de certificados. Os erros de rede e os ataques são geralmente temporários, pelo que esta página deverá funcionar mais tarde.</translation>
<translation id="6051898664905071243">Número de páginas:</translation>
@@ -1375,6 +1413,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<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>
<translation id="6116338172782435947">Ver o texto e as imagens copiados para a área de transferência</translation>
<translation id="6120179357481664955">Lembra-se do seu ID do UPI?</translation>
+<translation id="6123290840358279103">Ver cartão virtual</translation>
<translation id="6124432979022149706">Conetores do Chrome Enterprise</translation>
<translation id="6146055958333702838">Verifique os cabos e reinicie todos os routers, modems ou outros
dispositivos de rede que possa estar a utilizar.</translation>
@@ -1411,6 +1450,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="6289939620939689042">Cor da página</translation>
<translation id="6290238015253830360">Os seus artigos sugeridos são apresentados aqui</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">Código de segurança:</translation>
<translation id="6302269476990306341">Paragem do Assistente Google no Chrome</translation>
<translation id="6305205051461490394"><ph name="URL" /> está inacessível.</translation>
<translation id="6312113039770857350">Página Web não disponível</translation>
@@ -1436,6 +1476,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="6390200185239044127">Dobrar metade em Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">A ação de colar a partir de <ph name="ORIGIN_NAME" /> nesta localização está bloqueada por uma política do administrador.</translation>
+<translation id="6398765197997659313">Sair do modo de ecrã inteiro</translation>
<translation id="6401136357288658127">Esta política foi descontinuada. Deverá optar por utilizar a política <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Editar marcador</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1448,7 +1489,6 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="6428450836711225518">Valide o seu número de telefone</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="6440503408713884761">Ignorado</translation>
<translation id="6443406338865242315">As extensões e os plug-ins que instalou.</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1491,6 +1531,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="6624427990725312378">Informações de contacto</translation>
<translation id="6626291197371920147">Adicionar número de cartão válido</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Pesquisar</translation>
+<translation id="6630043285902923878">A procurar dispositivos USB…</translation>
<translation id="6630809736994426279">Os atacantes atualmente em <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> podem tentar instalar programas perigosos no seu Mac que roubam ou eliminam as suas informações (por exemplo, fotos, palavras-passe, mensagens e cartões de crédito). <ph name="BEGIN_LEARN_MORE_LINK" />Saiba mais<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Limpar</translation>
@@ -1506,6 +1547,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="6671697161687535275">Remover a sugestão do formulário do Chromium?</translation>
<translation id="6685834062052613830">Termine sessão e conclua a configuração</translation>
<translation id="6687335167692595844">Tamanho do tipo de letra solicitado</translation>
+<translation id="6688743156324860098">Atualizar…</translation>
<translation id="6689249931105087298">Relativa com compressão do ponto preto</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="6698381487523150993">Criado:</translation>
@@ -1521,6 +1563,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="6744009308914054259">Enquanto aguarda uma ligação, pode visitar a secção Transferências para ler artigos offline.</translation>
<translation id="6753269504797312559">Valor da política</translation>
<translation id="6757797048963528358">O dispositivo entrou em suspensão.</translation>
+<translation id="6767985426384634228">Pretende atualizar o endereço?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violeta</translation>
@@ -1543,6 +1586,7 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">O Chrome simplificou esta página para facilitar a leitura. O Chrome obteve a página original através de uma ligação insegura.</translation>
<translation id="6891596781022320156">O nível da política não é suportado.</translation>
+<translation id="6895143722905299846">Número virtual:</translation>
<translation id="6895330447102777224">O seu cartão foi confirmado</translation>
<translation id="6897140037006041989">Agente do utilizador</translation>
<translation id="6898699227549475383">Organização (O)</translation>
@@ -1578,10 +1622,10 @@ Se não permitir, isto será bloqueado pelas suas definições de privacidade. I
<translation id="7004583254764674281">Utilizar o Windows Hello para confirmar os cartões mais rapidamente</translation>
<translation id="7006930604109697472">Enviar mesmo assim</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Definições de redimensionamento</translation>
<translation id="7014741021609395734">Nível de zoom</translation>
<translation id="7016992613359344582">Estas cobranças podem ser únicas ou recorrentes e podem não ser óbvias.</translation>
<translation id="7029809446516969842">Palavras-passe</translation>
+<translation id="7030436163253143341">O certificado não é válido</translation>
<translation id="7031646650991750659">As apps do Google Play que instalou.</translation>
<translation id="7050187094878475250">Tentou aceder a <ph name="DOMAIN" />, mas o servidor apresentou um certificado cujo período de validade é demasiado longo para ser fidedigno.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{De momento, não é possível guardar este cartão.}other{De momento, não é possível guardar estes cartões.}}</translation>
@@ -1651,12 +1695,14 @@ Detalhes adicionais:
<translation id="7300012071106347854">Azul cobalto</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Alta</translation>
+<translation id="7305756307268530424">Iniciar mais lentamente</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Ajuda para estabelecer ligação</translation>
<translation id="7323804146520582233">Ocultar a secção "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Substituição da conta local do dispositivo</translation>
<translation id="7333654844024768166">Acabou de introduzir a sua palavra-passe num site fraudulento. O Chromium recomenda que aceda a <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> e outros sites em que utilize esta palavra-passe e a altere agora.</translation>
<translation id="7334320624316649418">&amp;Refazer reordenação</translation>
+<translation id="7337248890521463931">Mostrar mais linhas</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>
@@ -1664,6 +1710,7 @@ Detalhes adicionais:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Linha de comandos</translation>
<translation id="7359588939039777303">Anúncios bloqueados.</translation>
+<translation id="7363096869660964304">No entanto, a navegação não é invisível. Passar para a Navegação anónima não oculta a navegação do empregador, do fornecedor de serviços de Internet nem dos Websites que visitar.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, prima Tab e, em seguida, Enter para adicionar e gerir endereços nas Definições do Chrome.</translation>
<translation id="7365849542400970216">Sabe qual é a utilização do seu dispositivo?</translation>
<translation id="7372973238305370288">resultado da pesquisa</translation>
@@ -1674,7 +1721,9 @@ Detalhes adicionais:
<translation id="7378594059915113390">Controlos de multimédia</translation>
<translation id="7378627244592794276">Não</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Não aplicável</translation>
<translation id="7390545607259442187">Confirmar cartão</translation>
+<translation id="7392089738299859607">Atualize o endereço</translation>
<translation id="7399802613464275309">Verificação de segurança</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">O seu <ph name="DEVICE_NAME" /> é gerido</translation>
@@ -1688,6 +1737,7 @@ Detalhes adicionais:
&lt;li&gt;Clique em &lt;strong&gt;Aplicar&lt;/strong&gt; e, de seguida, em &lt;strong&gt;OK&lt;/strong&gt;.
&lt;li&gt;Visite o &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centro de Ajuda do Chrome&lt;/a&gt; para saber como remover permanentemente o software do computador. &lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Adorável</translation>
<translation id="7416351320495623771">Gerir palavras-passe…</translation>
<translation id="7419106976560586862">Caminho do Perfil</translation>
<translation id="7437289804838430631">Adicionar informações de contacto</translation>
@@ -1703,7 +1753,7 @@ Detalhes adicionais:
<translation id="7481312909269577407">Avançar</translation>
<translation id="7485870689360869515">Não foram encontrados dados.</translation>
<translation id="7495528107193238112">Este conteúdo está bloqueado. Contacte o proprietário do site para corrigir o problema.</translation>
-<translation id="7498234416455752244">Continuar a editar</translation>
+<translation id="7498193950643227031">Em caso de redimensionamento, pode ter um comportamento inesperado. Já pode limitar a capacidade de redimensionar apps nas <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Acabou de introduzir a sua palavra-passe num site fraudulento. O Chromium recomenda que verifique agora as palavras-passe guardadas para <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> e outros sites em que utilize esta palavra-passe.</translation>
<translation id="7508255263130623398">O ID do dispositivo da política devolvido está vazio ou não corresponde ao ID do dispositivo atual</translation>
<translation id="7508870219247277067">Verde abacate</translation>
@@ -1723,6 +1773,7 @@ Detalhes adicionais:
<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="755279583747225797">A avaliação está ativa</translation>
<translation id="7552846755917812628">Experimente as sugestões seguintes:</translation>
<translation id="7554475479213504905">Atualizar e mostrar mesmo assim</translation>
<translation id="7554791636758816595">Novo separador</translation>
@@ -1741,7 +1792,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, prima Tab e, em seguida, Enter para ver e gerir as suas palavras-passe nas Definições do Chrome.</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="7616645509853975347">O seu administrador ativou os Chrome Enterprise Connectors no navegador. Estes conetores têm acesso a alguns dos seus dados.</translation>
<translation id="7619838219691048931">Folha final</translation>
<translation id="762844065391966283">Um item de cada vez</translation>
@@ -1806,13 +1856,12 @@ Detalhes adicionais:
<translation id="782886543891417279">A rede Wi-Fi que está a utilizar (<ph name="WIFI_NAME" />) pode exigir que visite a respetiva página de início de sessão.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Nenhuma}=1{1 aplicação (<ph name="EXAMPLE_APP_1" />)}=2{2 aplicações (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# aplicações (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">No entanto, a navegação não é invisível. Passar para o modo de navegação anónima não oculta a navegação do empregador ou do fornecedor de serviços de Internet, nem dos Sites que visitar.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Abra ficheiros com associações de tipos de ficheiros.</translation>
<translation id="7862185352068345852">Pretende sair do site?</translation>
<translation id="7865448901209910068">A melhor velocidade</translation>
<translation id="7874263914261512992">Acabou de introduzir a sua palavra-passe num site fraudulento. O Chrome recomenda que verifique agora as palavras-passe guardadas para <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> e outros sites em que utilize esta palavra-passe.</translation>
<translation id="7878562273885520351">A palavra-passe pode estar comprometida</translation>
+<translation id="7880146494886811634">Guarde o endereço</translation>
<translation id="7882421473871500483">Castanho</translation>
<translation id="7887683347370398519">Verifique o Código de Segurança/CVC e tente novamente</translation>
<translation id="7887885240995164102">Entrar no modo ecrã no ecrã</translation>
@@ -1820,6 +1869,7 @@ Detalhes adicionais:
<translation id="7894280532028510793">Se a ortografia estiver correta, <ph name="BEGIN_LINK" />experimente executar o Diagnóstico de rede<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Desconhecido</translation>
+<translation id="793209273132572360">Pretende atualizar o endereço?</translation>
<translation id="7932579305932748336">Revestir</translation>
<translation id="79338296614623784">Introduza um número de telefone válido</translation>
<translation id="7934052535022478634">Pagamento concluído</translation>
@@ -1890,6 +1940,7 @@ Detalhes adicionais:
<translation id="8175796834047840627">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.</translation>
<translation id="8176440868214972690">O administrador deste serviço enviou algumas informações para os seguintes Websites, como definições ou políticas.</translation>
<translation id="8184538546369750125">Utilizar predefinição global (Permitir)</translation>
+<translation id="8193086767630290324">Ações tomadas com dados sinalizados como confidenciais</translation>
<translation id="8194797478851900357">&amp;Anular movimentação</translation>
<translation id="8201077131113104583">Atualizar URL inválido para a extensão com o ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Resumo da encomenda</translation>
@@ -1912,6 +1963,7 @@ Detalhes adicionais:
<translation id="8249296373107784235">Abortar</translation>
<translation id="8249320324621329438">Última obtenção:</translation>
<translation id="8253091569723639551">É necessário um endereço de faturação</translation>
+<translation id="8257387598443225809">Esta app foi concebida para dispositivos móveis</translation>
<translation id="825929999321470778">Mostrar todas as palavras-passe guardadas</translation>
<translation id="8261506727792406068">Eliminar</translation>
<translation id="8262952874573525464">Coser extremidade inferior</translation>
@@ -2036,7 +2088,6 @@ Detalhes adicionais:
<translation id="8719528812645237045">Perfuração múltipla na parte superior</translation>
<translation id="8725066075913043281">Tentar novamente</translation>
<translation id="8726549941689275341">Tamanho das páginas:</translation>
-<translation id="8728672262656704056">Está anónimo</translation>
<translation id="8730621377337864115">Concluído</translation>
<translation id="8731544501227493793">Botão Gerir palavras-passe; prima Enter para ver e gerir as suas palavras-passes nas Definições do Chrome.</translation>
<translation id="8734529307927223492">O seu <ph name="DEVICE_TYPE" /> é gerido por <ph name="MANAGER" /></translation>
@@ -2113,6 +2164,7 @@ Detalhes adicionais:
<translation id="9020542370529661692">Esta página foi traduzida para <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Inválido)</translation>
+<translation id="9030265603405983977">Monocromático</translation>
<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>
@@ -2136,6 +2188,7 @@ Detalhes adicionais:
<translation id="91108059142052966">A política do administrador desativa a partilha de ecrã com <ph name="APPLICATION_TITLE" /> quando existe conteúdo confidencial visível.</translation>
<translation id="9114524666733003316">A confirmar o cartão…</translation>
<translation id="9114581008513152754">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="9117930699067497412">Moderno</translation>
<translation id="9119042192571987207">Carregado</translation>
<translation id="9128016270925453879">As políticas foram carregadas.</translation>
<translation id="9128870381267983090">Ligar à rede</translation>
@@ -2154,6 +2207,7 @@ Detalhes adicionais:
<translation id="9170848237812810038">An&amp;ular</translation>
<translation id="9171296965991013597">Pretende sair da aplicação?</translation>
<translation id="9173282814238175921">Documento único/Nova folha</translation>
+<translation id="9173995187295789444">A procurar dispositivos Bluetooth…</translation>
<translation id="917450738466192189">O certificado do servidor é inválido.</translation>
<translation id="9174917557437862841">Botão de mudança de separador: prima Enter para mudar para este separador.</translation>
<translation id="9179703756951298733">Efetue a gestão das informações de cartões de crédito e pagamentos nas definições do Chrome.</translation>
diff --git a/chromium/components/strings/components_strings_ro.xtb b/chromium/components/strings/components_strings_ro.xtb
index e3d276721ce..209ea418883 100644
--- a/chromium/components/strings/components_strings_ro.xtb
+++ b/chromium/components/strings/components_strings_ro.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Dacă este bifată opțiunea, Chrome va stoca o copie a cardului pe dispozitiv pentru a completa formularul mai rapid.</translation>
<translation id="1110994991967754504">Selectează permisiunea pentru <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Anulați reordonarea</translation>
+<translation id="1123753900084781868">Funcția Subtitrări live nu este disponibilă în acest moment</translation>
<translation id="1125573121925420732">Este posibil să apară frecvent avertismente pe durata actualizării setărilor de securitate ale site-urilor. Acest aspect va fi îmbunătățit în curând.</translation>
<translation id="112840717907525620">Memoria cache pentru politică este OK</translation>
<translation id="1130564665089811311">Butonul Tradu pagina, apasă pe Enter pentru a traduce această pagină cu Google Traducere</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Numele dispozitivului tău</translation>
<translation id="124116460088058876">Mai multe limbi</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Aldin</translation>
<translation id="1250759482327835220">Pentru a plăti mai rapid data viitoare, salvează cardul, numele și adresa de facturare în Contul Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sincronizate)</translation>
<translation id="1256368399071562588">&lt;p&gt;Dacă încerci să vizitezi un site, iar acesta nu se deschide, mai întâi încearcă să remediezi eroarea urmând acești pași:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Schimbă parola</translation>
<translation id="1484290072879560759">Alege adresa de expediere</translation>
<translation id="1492194039220927094">Notificări pentru politici:</translation>
+<translation id="1495677929897281669">Înpoi la filă</translation>
<translation id="1501859676467574491">Arată cardurile din Contul Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Această eroare se va afișa dacă folosești un portal Wi-Fi la care trebuie să te conectezi înainte de a putea fi online.&lt;/p&gt;
&lt;p&gt;Pentru a remedia eroarea, dă clic pe &lt;strong&gt;Conectează-te&lt;/strong&gt;, în pagina pe care încerci să o deschizi.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Această pagină afișează mesajul</translation>
<translation id="153384715582417236">Asta este tot</translation>
<translation id="1536390784834419204">Tradu pagina</translation>
+<translation id="1539840569003678498">Raportul a fost trimis:</translation>
<translation id="154408704832528245">Alege adresa de livrare</translation>
<translation id="1549470594296187301">Trebuie să activezi JavaScript pentru a folosi această funcție.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">Cu latura scurtă înainte</translation>
<translation id="168693727862418163">Valoarea politicii nu s-a validat în raport cu schema și va fi ignorată.</translation>
<translation id="168841957122794586">Certificatul de server conține o cheie criptografică slabă.</translation>
+<translation id="1696290444144917273">Vezi detaliile cardului virtual</translation>
<translation id="1697532407822776718">Ești gata!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Acest server nu a putut dovedi că este <ph name="DOMAIN" />. Data de emitere a certificatului său de securitate este mâine. Cauza poate fi o eroare de configurare sau interceptarea conexiunii de către un atacator.}few{Acest server nu a putut dovedi că este <ph name="DOMAIN" />. Data de emitere a certificatului său de securitate este în viitor, peste # zile. Cauza poate fi o eroare de configurare sau interceptarea conexiunii de către un atacator.}other{Acest server nu a putut dovedi că este <ph name="DOMAIN" />. Data de emitere a certificatului său de securitate este în viitor, peste # de zile. Cauza poate fi o eroare de configurare sau interceptarea conexiunii de către un atacator.}}</translation>
<translation id="1710259589646384581">Sistem de operare</translation>
+<translation id="1711234383449478798">Ignorată deoarece politica <ph name="POLICY_NAME" /> nu este setată la <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> dorește să stocheze permanent date pe computer</translation>
<translation id="1713628304598226412">Tava 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Căsuța de e-mail 3</translation>
<translation id="1718029547804390981">Documentul este prea mare pentru a face adnotări</translation>
<translation id="1721424275792716183">* Câmp obligatoriu</translation>
+<translation id="1727613060316725209">Certificatul este valid</translation>
<translation id="1727741090716970331">Adaugă un număr de card valid</translation>
<translation id="1728677426644403582">Se afișează sursa unei pagini web</translation>
<translation id="173080396488393970">Acest tip de card nu este acceptat</translation>
@@ -246,7 +253,6 @@
solicitarea pentru <ph name="SITE" />. Politicile de origine pot fi folosite de
operatorii de site pentru a configura securitatea și alte proprietăți ale site-ului.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Actualizează expresia de acces pentru sincronizare.</translation>
<translation id="1787142507584202372">Filele deschise sunt afișate aici</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, sunt disponibile mai multe acțiuni, apasă pe Tab pentru a le răsfoi</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">Anunțuri</translation>
<translation id="1919367280705858090">Obține ajutor în privința unui anumit mesaj de eroare</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Niciunul}=1{1 site}few{# site-uri}other{# de site-uri}}</translation>
+<translation id="1924727005275031552">Nou</translation>
<translation id="1945968466830820669">Este posibil să pierzi accesul la contul organizației sau să fii victima unui furt de identitate. Chromium îți recomandă să îți schimbi acum parola.</translation>
<translation id="1947454675006758438">Capsare în dreapta sus</translation>
<translation id="1958218078413065209">Cel mai mare scor al tău este de <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">Tava 7</translation>
<translation id="204357726431741734">Conectează-te pentru a folosi parolele salvate în Contul Google</translation>
<translation id="2053111141626950936">Paginile în <ph name="LANGUAGE" /> nu vor fi traduse.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Când opțiunea este activată și starea este Activă, Chrome stabilește un grup mare de utilizatori cu care se aseamănă cel mai mult activitatea ta de navigare recentă. Advertiserii pot selecta anunțuri pentru grup și activitatea ta de navigare este păstrată privată pe dispozitivul tău. Grupul este actualizat în fiecare zi.}=1{Când opțiunea este activată și starea este Activă, Chrome stabilește un grup mare de utilizatori cu care se aseamănă cel mai mult activitatea ta de navigare recentă. Advertiserii pot selecta anunțuri pentru grup și activitatea ta de navigare este păstrată privată pe dispozitivul tău. Grupul este actualizat în fiecare zi.}few{Când opțiunea este activată și starea este Activă, Chrome stabilește un grup mare de utilizatori cu care se aseamănă cel mai mult activitatea ta de navigare recentă. Advertiserii pot selecta anunțuri pentru grup și activitatea ta de navigare este păstrată privată pe dispozitivul tău. Grupul este actualizat o dată la {NUM_DAYS} zile.}other{Când opțiunea este activată și starea este Activă, Chrome stabilește un grup mare de utilizatori cu care se aseamănă cel mai mult activitatea ta de navigare recentă. Advertiserii pot selecta anunțuri pentru grup și activitatea ta de navigare este păstrată privată pe dispozitivul tău. Grupul este actualizat o dată la {NUM_DAYS} de zile.}}</translation>
<translation id="2053553514270667976">Cod zip</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugestie}few{# sugestii}other{# de sugestii}}</translation>
<translation id="2071692954027939183">Notificările au fost blocate automat deoarece nu le permiți de obicei</translation>
<translation id="2079545284768500474">Anulează</translation>
<translation id="20817612488360358">Setările proxy de sistem sunt setate pentru a fi utilizate, dar o configurație explicită pentru proxy este, de asemenea, specificată.</translation>
<translation id="2082238445998314030">Rezultatul <ph name="RESULT_NUMBER" /> din <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Salvează…</translation>
<translation id="2088086323192747268">Butonul Gestionează sincronizarea, apasă pe Enter pentru a gestiona informațiile de sincronizat din setările Chrome</translation>
<translation id="2091887806945687916">Sunet</translation>
<translation id="2094505752054353250">Nepotrivire domeniu</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> necesită un nume de utilizator și o parolă.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, expiră pe <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Setare controlată de administrator</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> dorește să se asocieze</translation>
<translation id="2344028582131185878">Descărcări automate</translation>
<translation id="2346319942568447007">Imaginea copiată de tine</translation>
<translation id="2354001756790975382">Alte marcaje</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">Este posibil ca atacatorii să poată vedea imaginile la care te uiți pe acest site și să te păcălească prin modificarea lor.</translation>
<translation id="2356070529366658676">Întreabă-mă</translation>
<translation id="2357481397660644965">Dispozitivul este gestionat de <ph name="DEVICE_MANAGER" />, iar contul tău este gestionat de <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{În mai puțin de o zi}=1{Peste o zi}few{Peste {NUM_DAYS} zile}other{Peste {NUM_DAYS} de zile}}</translation>
<translation id="2359629602545592467">Mai multe</translation>
<translation id="2359808026110333948">Continuă</translation>
+<translation id="2359961752320758691">Numărul de card virtual a fost completat.</translation>
<translation id="2367567093518048410">Nivel</translation>
<translation id="2372464001869762664">După ce confirmi, acest site va avea acces la detaliile cardului tău din Contul Google. Caută codul CVC în detaliile contului Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">Această metodă de expediere nu este disponibilă. Încearcă altă metodă.</translation>
<translation id="2396249848217231973">&amp;Anulați ștergerea</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Veche</translation>
<translation id="2413528052993050574">Acest server nu a putut dovedi că este <ph name="DOMAIN" />; este posibil ca certificatul său de securitate să fie revocat. Cauza poate fi o configurare greșită sau interceptarea conexiunii de către un atacator.</translation>
<translation id="2414886740292270097">ÃŽntunecat</translation>
<translation id="2438874542388153331">Perforare cvadruplă în dreapta</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">Capsare în dreapta jos</translation>
<translation id="2523886232349826891">Salvat numai pe acest dispozitiv</translation>
<translation id="2524461107774643265">Adaugă mai multe informații</translation>
-<translation id="2526590354069164005">Desktop</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{și încă una}few{și încă #}other{și încă #}}</translation>
<translation id="2536110899380797252">Adaugă o adresă</translation>
<translation id="2539524384386349900">Detectează</translation>
+<translation id="2541219929084442027">Paginile pe care le accesezi în filele incognito nu vor fi înregistrate în istoricul browserului, nu vor stoca cookie-uri și nu vor rămâne în istoricul căutărilor după ce închizi toate filele incognito. Fișierele descărcate și marcajele create vor fi păstrate.</translation>
<translation id="2544644783021658368">Un document</translation>
<translation id="254947805923345898">Valoarea politicii nu este validă.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> a trimis un răspuns nevalid.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Pentru a beneficia de cel mai înalt nivel de securitate, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />activează protecția îmbunătățită<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Nu s-a găsit adresa IP pentru serverul <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Stare:</translation>
+<translation id="264810637653812429">Nu s-au găsit dispozitive compatibile.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, apasă pe Tab, apoi pe Enter pentru a șterge istoricul de navigare, cookie-urile, memoria cache și altele din setările Chrome</translation>
<translation id="2650446666397867134">Accesul la fișier a fost refuzat</translation>
@@ -492,6 +506,7 @@
<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="2807052079800581569">Poziția Y a imaginii</translation>
+<translation id="2820957248982571256">Se scanează...</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>
@@ -499,6 +514,8 @@
<translation id="2850739647070081192">Invite (Plic)</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="2859806420264540918">Acest site afișează anunțuri deranjante sau înșelătoare.</translation>
+<translation id="287596039013813457">Amical</translation>
+<translation id="2876489322757410363">Vei părăsi modul incognito pentru a plăti folosind o aplicație externă. Continui?</translation>
<translation id="2878197950673342043">ÃŽndoire de tip afiÈ™</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Poziționarea ferestrelor</translation>
@@ -548,7 +565,6 @@
<translation id="3060227939791841287">C9 (Plic)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, apasă pe Tab, apoi pe Enter pentru a rula verificarea de siguranță în setările Chrome</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>
<translation id="306573536155379004">Jocul a început.</translation>
<translation id="3080254622891793721">Grafică</translation>
<translation id="3086579638707268289">Activitatea ta de pe web este monitorizată</translation>
@@ -571,7 +587,6 @@
<translation id="315504272643575312">Contul tău este administrat de <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Restabilește</translation>
<translation id="3162559335345991374">Rețeaua Wi-Fi pe care o folosești poate solicita accesarea paginii de conectare.</translation>
-<translation id="3167968892399408617">Paginile pe care le accesezi în filele incognito nu vor fi înregistrate în istoricul browserului, nu vor stoca cookie-uri și nu vor rămâne în istoricul de căutare după ce închizi toate filele incognito. Fișierele descărcate și marcajele create vor fi păstrate.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Insulă</translation>
<translation id="3176929007561373547">Verifică setările de proxy sau contactează administratorul de rețea
@@ -597,10 +612,12 @@
<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="3249845759089040423">Șic</translation>
<translation id="3252266817569339921">Franceză</translation>
<translation id="3266793032086590337">Valoare (conflictuală)</translation>
<translation id="3268451620468152448">File deschise</translation>
<translation id="3270847123878663523">&amp;Anulați reordonarea</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> dorește să se conecteze</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Organizația ta, <ph name="ENROLLMENT_DOMAIN" />, a trimis câteva informații următoarelor site-uri, cum ar fi setări sau politici.</translation>
<translation id="3282497668470633863">Adaugă numele de pe card</translation>
@@ -653,6 +670,7 @@
<translation id="3428151540071562330">Una sau mai multe dintre adresele URI pentru șabloanele de server DnsOverHttpsTemplates este nevalidă și nu va fi folosită.</translation>
<translation id="3431636764301398940">Salvează cardul pe acest dispozitiv</translation>
<translation id="3432601291244612633">ÃŽnchide pagina</translation>
+<translation id="3435738964857648380">Securitate</translation>
<translation id="3435896845095436175">Activează</translation>
<translation id="3438829137925142401">Folosește parolele salvate în Contul tău Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -695,7 +713,10 @@
<translation id="3584299510153766161">Perforare dublă în partea de jos</translation>
<translation id="3586931643579894722">Ascunde detaliile</translation>
<translation id="3587738293690942763">Central</translation>
+<translation id="3590643883886679995">Datele de conectare vor fi stocate pe acest dispozitiv după ce ieși din modul incognito.</translation>
+<translation id="359126217934908072">Luna / anul:</translation>
<translation id="3592413004129370115">Italian (Plic)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Poți reseta oricând grupul. Durează aproximativ o zi să te alături unui alt grup.}=1{Poți reseta oricând grupul. Durează aproximativ o zi să te alături unui alt grup.}few{Poți reseta oricând grupul. Durează aproximativ {NUM_DAYS} zile să te alături unui alt grup.}other{Poți reseta oricând grupul. Durează aproximativ {NUM_DAYS} de zile să te alături unui alt grup.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplicația a fost blocată de administrator</translation>
<translation id="3608932978122581043">Orientarea alimentării</translation>
@@ -704,13 +725,13 @@
<translation id="3615877443314183785">Introdu o dată de expirare validă</translation>
<translation id="36224234498066874">Șterge datele de navigare...</translation>
<translation id="362276910939193118">Afișează întregul istoric</translation>
-<translation id="3625635938337243871">Datele de conectare vor fi stocate pe acest dispozitiv după ce ieși din modul incognito.</translation>
<translation id="3630155396527302611">Dacă este deja inclus ca program căruia i se permite să acceseze rețeaua, încearcă
să îl elimini din listă și să îl adaugi din nou.</translation>
<translation id="3630699740441428070">Administratorii acestui dispozitiv au configurat conexiunea la rețea, ceea ce le poate permite să vadă traficul de rețea, inclusiv site-urile pe care le accesezi.</translation>
<translation id="3631244953324577188">Sisteme biometrice</translation>
<translation id="3633738897356909127">Butonul Actualizează Chrome, apasă pe Enter pentru a actualiza Chrome din setările Chrome</translation>
<translation id="3634530185120165534">Tava 5</translation>
+<translation id="3637662659967048211">Salvează în Contul Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplicație:</translation>
<translation id="3650584904733503804">Validarea a reușit</translation>
@@ -751,6 +772,7 @@
<translation id="3781428340399460090">Roz aprins</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Dispozitive Bluetooth</translation>
+<translation id="3787675388804467730">Numărul cardului virtual</translation>
<translation id="3787705759683870569">Expiră în <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Mărimea 16</translation>
<translation id="3789841737615482174">Instalează</translation>
@@ -770,6 +792,7 @@
<translation id="3841184659773414994">Handlere pentru fișiere</translation>
<translation id="385051799172605136">ÃŽnapoi</translation>
<translation id="3858027520442213535">Actualizează data și ora</translation>
+<translation id="3881478300875776315">Afișează mai puține rânduri</translation>
<translation id="3884278016824448484">Identificator de gadget în conflict</translation>
<translation id="3885155851504623709">Parohie</translation>
<translation id="388632593194507180">S-a detectat monitorizarea</translation>
@@ -795,6 +818,7 @@
<translation id="397105322502079400">Se calculează...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> este blocat</translation>
<translation id="3973357910713125165">Butonul Rulează verificarea de siguranță pentru Chrome, apasă pe Enter pentru a rula verificarea de siguranță în setările Chrome</translation>
+<translation id="3986705137476756801">Dezactivează Subtitrările live pentru moment</translation>
<translation id="3987405730340719549">Chrome a identificat acest site ca fiind potențial fals sau fraudulos.
În cazul în care consideri că este o greșeală, accesează https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -891,13 +915,14 @@
<translation id="4275830172053184480">Reporniți gadgetul</translation>
<translation id="4277028893293644418">Resetează parola</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="4287885627794386150">Eligibil pentru versiunea de încercare, dar inactiv</translation>
<translation id="4297502707443874121">Miniatură pentru pagina <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Extinde</translation>
<translation id="4300675098767811073">Perforare multiplă în dreapta</translation>
<translation id="4302514097724775343">Atinge dinozaurul ca să joci</translation>
<translation id="4302965934281694568">Chou3 (Plic)</translation>
<translation id="4305666528087210886">Fișierul nu a putut fi accesat</translation>
-<translation id="4305817255990598646">Comută</translation>
+<translation id="4306529830550717874">Salvezi adresa?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blochează (în mod prestabilit)</translation>
<translation id="4314815835985389558">Gestionează sincronizarea</translation>
@@ -924,6 +949,7 @@
<translation id="4377125064752653719">Ați încercat să accesați <ph name="DOMAIN" />, dar certificatul furnizat de server a fost revocat de emitentul său. Aceasta înseamnă că acreditările de securitate furnizate de server nu sunt deloc de încredere. Este posibil să comunicați cu un atacator.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Bordură</translation>
+<translation id="4406883609789734330">Subtitrări live</translation>
<translation id="4406896451731180161">rezultate ale căutării</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> cookie-uri</translation>
<translation id="4414290883293381923">Ai introdus parola pe un site înșelător. Chrome recomandă să accesezi <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> și alte site-uri pe care folosești această parolă și să o schimbi acum.</translation>
@@ -936,7 +962,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="4464826014807964867">Site-uri cu informații de la organizația ta</translation>
-<translation id="4466881336512663640">Modificările aduse formularului se vor pierde. Sigur dorești să continui?</translation>
<translation id="4476953670630786061">Acest formular nu este sigur. Completarea automată a fost dezactivată.</translation>
<translation id="4477350412780666475">Melodia următoare</translation>
<translation id="4482953324121162758">Acest site nu va fi tradus.</translation>
@@ -970,6 +995,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="4606870351894164739">De impact</translation>
<translation id="4628948037717959914">Fotografie</translation>
<translation id="4631649115723685955">Ofertă cu returnare de bani</translation>
<translation id="4636930964841734540">Informații</translation>
@@ -989,6 +1015,7 @@
<translation id="4691835149146451662">Architecture-A (Plic)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Lateral</translation>
+<translation id="4702656508969495934">Subtitrări live vizibile, folosește comutatorul de ferestre pentru a focaliza</translation>
<translation id="4708268264240856090">Conexiunea a fost întreruptă</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />să rulezi Diagnostice rețea Windows<ph name="END_LINK" />;</translation>
@@ -1002,6 +1029,7 @@
<translation id="4738601419177586157">Sugestie de căutare <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Gestionează parolele…</translation>
<translation id="4744603770635761495">Cale executabilă</translation>
+<translation id="4749011317274908093">Ai trecut în modul incognito</translation>
<translation id="4750917950439032686">Informațiile tale (de exemplu, parolele și numerele cardurilor de credit) sunt private când sunt trimise la acest site.</translation>
<translation id="4756388243121344051">&amp;Istoric</translation>
<translation id="4758311279753947758">Adaugă informații de contact</translation>
@@ -1031,6 +1059,8 @@
<translation id="4813512666221746211">Eroare de rețea</translation>
<translation id="4816492930507672669">Încadrați în pagină</translation>
<translation id="4819347708020428563">Editezi adnotările în afișarea prestabilită?</translation>
+<translation id="4825507807291741242">Puternic</translation>
+<translation id="4838327282952368871">Visare</translation>
<translation id="484462545196658690">Automat</translation>
<translation id="4850886885716139402">Afișează</translation>
<translation id="485316830061041779">Germană</translation>
@@ -1167,6 +1197,7 @@
<translation id="5314967030527622926">Broșator</translation>
<translation id="5316812925700871227">Rotește în sens invers acelor de ceasornic</translation>
<translation id="5317780077021120954">Salvează</translation>
+<translation id="5321288445143113935">Maximizată</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> din <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Alege informațiile de contact</translation>
<translation id="5327248766486351172">Nume</translation>
@@ -1174,11 +1205,13 @@
<translation id="5332219387342487447">Metoda de expediere</translation>
<translation id="5333022057423422993">Chrome a găsit parola pe care tocmai ai folosit-o într-o încălcare a securității datelor. Pentru a-ți securiza conturile, verifică parolele salvate.</translation>
<translation id="5334013548165032829">Jurnale de sistem detaliate</translation>
+<translation id="5334145288572353250">Salvezi adresa?</translation>
<translation id="5340250774223869109">Aplicația a fost blocată</translation>
<translation id="534295439873310000">Dispozitive NFC</translation>
<translation id="5344579389779391559">Această pagină poate să genereze costuri</translation>
<translation id="5355557959165512791">Nu poți accesa <ph name="SITE" /> acum, deoarece certificatul său a fost revocat. Erorile de rețea și atacurile sunt de obicei temporare și probabil că această pagină va funcționa mai târziu.</translation>
<translation id="536296301121032821">Setările pentru politică nu au putut fi stocate</translation>
+<translation id="5363309033720083897">Port serial permis de administrator</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="5386426401304769735">Lanțul de certificate pentru acest site conține un certificat semnat folosind SHA-1.</translation>
@@ -1187,6 +1220,7 @@
<translation id="5398772614898833570">Anunțurile au fost blocate</translation>
<translation id="5400836586163650660">Gri</translation>
<translation id="540969355065856584">Acest server nu a putut dovedi că este <ph name="DOMAIN" />; momentan, certificatul de securitate nu este valid. Cauza poate fi o configurare greșită sau interceptarea conexiunii de un atacator.</translation>
+<translation id="541143247543991491">Cloud (la nivel de sistem)</translation>
<translation id="541416427766103491">Receptorul de hârtie 4</translation>
<translation id="5421136146218899937">Șterge datele de navigare...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> dorește să îți trimită notificări</translation>
@@ -1200,6 +1234,7 @@
<translation id="5455374756549232013">Marcaj temporal greșit pentru politică</translation>
<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="5463625433003343978">Se caută dispozitive...</translation>
<translation id="5469868506864199649">Italiană</translation>
<translation id="5470861586879999274">&amp;Repetați editarea</translation>
<translation id="5478437291406423475">B6/C4 (Plic)</translation>
@@ -1249,7 +1284,6 @@
<translation id="5624120631404540903">Gestionați parolele</translation>
<translation id="5629630648637658800">Setările pentru politică nu au putut fi încărcate</translation>
<translation id="5631439013527180824">Indicativ nevalid pentru gestionarea gadgetului</translation>
-<translation id="5632627355679805402">Datele au fost criptate cu <ph name="BEGIN_LINK" />parola Google<ph name="END_LINK" /> începând cu <ph name="TIME" />. Introdu parola pentru a începe sincronizarea.</translation>
<translation id="5633066919399395251">Atacatorii de pe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> pot încerca să instaleze programe periculoase pe computerul tău, care să îți fure sau să îți șteargă informațiile (de exemplu, fotografii, 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="563324245173044180">Conținutul înșelător a fost blocat.</translation>
<translation id="5644090287519800334">Deplasarea poziției X a imaginii de pe fața 1</translation>
@@ -1288,12 +1322,12 @@
<translation id="5785756445106461925">Î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 aspectul paginii.</translation>
<translation id="5786044859038896871">Dorești să completezi datele cardului de credit?</translation>
<translation id="578633867165174378">Chrome a găsit parola pe care tocmai ai folosit-o într-o încălcare a securității datelor. Îți recomandăm să schimbi acum parola.</translation>
-<translation id="5798290721819630480">Renunți la modificări?</translation>
<translation id="5803412860119678065">Dorești să completezi datele <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Permisiuni</translation>
<translation id="5804427196348435412">Folosește dispozitive NFC</translation>
<translation id="5810442152076338065">Conexiunea la <ph name="DOMAIN" /> este criptată folosind o suită de codificare învechită.</translation>
<translation id="5813119285467412249">&amp;Repetați adăugarea</translation>
+<translation id="5817918615728894473">Asociază</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Cardul va fi debitat când plătești, dar numărul său real nu va fi trimis acestui site. Pentru un plus de securitate, va fi generat un cod CVC temporar.}few{Cardul pe care îl selectezi va fi debitat când plătești, dar numărul său real nu va fi trimis acestui site. Pentru un plus de securitate, va fi generat un cod CVC temporar.}other{Cardul pe care îl selectezi va fi debitat când plătești, dar numărul său real nu va fi trimis acestui site. Pentru un plus de securitate, va fi generat un cod CVC temporar.}}</translation>
<translation id="5826507051599432481">Nume comun (CN)</translation>
<translation id="5838278095973806738">Nu ar trebui să introduci informații sensibile pe acest site (de exemplu, parole sau carduri de credit), deoarece ar putea fi furate de atacatori.</translation>
@@ -1301,6 +1335,7 @@
<translation id="5855253129151731373">Numele de gazdă al acestui site este similar cu cel al site-ului <ph name="LOOKALIKE_DOMAIN" />. Uneori, atacatorii imită site-uri aducând modificări mici, greu de observat, numelui de domeniu.
În cazul în care consideri că este o greșeală, accesează https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Dezactivat</translation>
<translation id="5862579898803147654">Receptorul de hârtie 8</translation>
<translation id="5863847714970149516">Următoarea pagină poate să genereze costuri</translation>
<translation id="5866257070973731571">Adaugă un număr de telefon</translation>
@@ -1317,6 +1352,7 @@
<translation id="5913377024445952699">Funcție de realizare a capturilor întreruptă</translation>
<translation id="59174027418879706">Activat</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 în uz}few{# în uz}other{# în uz}}</translation>
<translation id="5921185718311485855">activate</translation>
<translation id="5921639886840618607">Salvezi cardul în Contul Google?</translation>
<translation id="5922853866070715753">Aproape finalizat</translation>
@@ -1336,6 +1372,7 @@
<translation id="5989320800837274978">Nu sunt specificate nici servere proxy fixe și nici o adresă URL pentru scripturi .pac.</translation>
<translation id="5992691462791905444">Îndoire în Z pentru inginerie</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> rezultate pentru „<ph name="SEARCH_TEXT" />â€</translation>
+<translation id="6006484371116297560">Tema clasică</translation>
<translation id="6008122969617370890">ÃŽn ordinea de la N-la-1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Verifică-ți parolele</translation>
@@ -1357,6 +1394,7 @@
<translation id="6045164183059402045">Șablon de impunere</translation>
<translation id="6047233362582046994">Dacă îți asumi riscurile de securitate, poți să <ph name="BEGIN_LINK" />accesezi acest site<ph name="END_LINK" /> înainte ca aplicațiile dăunătoare să fie eliminate.</translation>
<translation id="6047927260846328439">Acest conținut ar putea încerca să te păcălească să instalezi software sau să dezvălui informații cu caracter personal. <ph name="BEGIN_LINK" />Afișează oricum<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Pentru a ieși din ecranul complet, apasă lung |<ph name="ACCELERATOR" />|</translation>
<translation id="6049488691372270142">Scoaterea paginilor</translation>
<translation id="6051221802930200923">Nu poți accesa <ph name="SITE" /> acum, deoarece site-ul folosește fixarea certificatelor. Erorile de rețea și atacurile sunt de obicei temporare și probabil că această pagină va funcționa mai târziu.</translation>
<translation id="6051898664905071243">Numărul de pagini:</translation>
@@ -1373,6 +1411,7 @@
<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>
<translation id="6116338172782435947">să afișeze textul și imaginile copiate în clipboard</translation>
<translation id="6120179357481664955">Îți amintești ID-ul UPI?</translation>
+<translation id="6123290840358279103">Vezi cardul virtual</translation>
<translation id="6124432979022149706">Conectori Chrome Enterprise</translation>
<translation id="6146055958333702838">Verifică toate cablurile și repornește routerele, modemurile sau alte
dispozitive de rețea pe care le folosești.</translation>
@@ -1409,6 +1448,7 @@
<translation id="6289939620939689042">Culoarea paginii</translation>
<translation id="6290238015253830360">Articolele sugerate apar aici</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Asistentul Google în Chrome se oprește</translation>
<translation id="6305205051461490394">Adresa URL <ph name="URL" /> nu poate fi accesată.</translation>
<translation id="6312113039770857350">Pagina web nu este disponibilă</translation>
@@ -1434,6 +1474,7 @@
<translation id="6390200185239044127">Îndoire în Z la jumătate</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Inserarea de pe <ph name="ORIGIN_NAME" /> în această locație a fost blocată de politica implementată de administrator</translation>
+<translation id="6398765197997659313">Ieși din ecranul complet</translation>
<translation id="6401136357288658127">Această politică este învechită. Ar trebui să folosești politica <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Modifică marcajul</translation>
<translation id="6406765186087300643">C0 (Plic)</translation>
@@ -1446,7 +1487,6 @@
<translation id="6428450836711225518">Confirmă numărul de telefon</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="6440503408713884761">Ignorat</translation>
<translation id="6443406338865242315">extensiile și pluginurile instalate,</translation>
<translation id="6446163441502663861">Kahu (Plic)</translation>
@@ -1489,6 +1529,7 @@
<translation id="6624427990725312378">Informații de contact</translation>
<translation id="6626291197371920147">Adaugă un număr de card valid</translation>
<translation id="6628463337424475685">Căutare <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Se caută dispozitive USB...</translation>
<translation id="6630809736994426279">Atacatorii de pe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> pot încerca să instaleze programe periculoase pe computerul tău Mac, care să îți fure sau să îți șteargă informațiile (de exemplu, fotografii, 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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Șterge</translation>
@@ -1504,6 +1545,7 @@
<translation id="6671697161687535275">Elimini sugestia pentru formular din Chromium?</translation>
<translation id="6685834062052613830">Deconectează-te și finalizează configurarea</translation>
<translation id="6687335167692595844">Dimensiunea fontului solicitată</translation>
+<translation id="6688743156324860098">Actualizează…</translation>
<translation id="6689249931105087298">Relativă cu comprimarea punctelor negre</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="6698381487523150993">Creat:</translation>
@@ -1519,6 +1561,7 @@
<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="6753269504797312559">Valoarea politicii</translation>
<translation id="6757797048963528358">Dispozitivul este inactiv.</translation>
+<translation id="6767985426384634228">Actualizezi adresa?</translation>
<translation id="6768213884286397650">Hagaki (Carte poștală)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violet</translation>
@@ -1541,6 +1584,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome a simplificat această pagină pentru a fi mai ușor de citit. Chrome a preluat pagina originală printr-o conexiune nesigură.</translation>
<translation id="6891596781022320156">Nivelul politicii nu este acceptat.</translation>
+<translation id="6895143722905299846">Număr virtual:</translation>
<translation id="6895330447102777224">Cardul tău este confirmat</translation>
<translation id="6897140037006041989">User Agent</translation>
<translation id="6898699227549475383">Organizația (O)</translation>
@@ -1576,10 +1620,10 @@
<translation id="7004583254764674281">Folosește Windows Hello ca să confirmi mai repede cardurile</translation>
<translation id="7006930604109697472">Trimite oricum</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Setări pentru redimensionare</translation>
<translation id="7014741021609395734">Nivel de zoom</translation>
<translation id="7016992613359344582">Aceste costuri pot fi unice sau recurente și ascunse.</translation>
<translation id="7029809446516969842">Parole</translation>
+<translation id="7030436163253143341">Certificatul nu este valid</translation>
<translation id="7031646650991750659">aplicațiile Google Play instalate.</translation>
<translation id="7050187094878475250">Ai încercat să accesezi <ph name="DOMAIN" />, dar serverul a prezentat un certificat a cărui perioadă de validitate este prea lungă pentru a fi de încredere.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Momentan cardul nu poate fi salvat}few{Momentan cardurile nu pot fi salvate}other{Momentan cardurile nu pot fi salvate}}</translation>
@@ -1649,12 +1693,14 @@ Detalii suplimentare:
<translation id="7300012071106347854">Albastru cobalt</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />â€</translation>
<translation id="7304030187361489308">Înaltă</translation>
+<translation id="7305756307268530424">Pornește mai lent</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Ajutor pentru conectare</translation>
<translation id="7323804146520582233">Ascunde secÈ›iunea „<ph name="SECTION" />â€</translation>
<translation id="733354035281974745">Modificarea contului local al dispozitivului</translation>
<translation id="7333654844024768166">Ai introdus parola pe un site înșelător. Chromium recomandă să accesezi <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> și alte site-uri pe care folosești această parolă și să o schimbi acum.</translation>
<translation id="7334320624316649418">&amp;Repetați reordonarea</translation>
+<translation id="7337248890521463931">Afișează mai multe rânduri</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>
@@ -1662,6 +1708,7 @@ Detalii suplimentare:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Linie de comandă</translation>
<translation id="7359588939039777303">Anunțurile au fost blocate.</translation>
+<translation id="7363096869660964304">Cu toate acestea, nu ești invizibil(ă). Trecerea în modul incognito nu ascunde activitatea de navigare față de angajator, față de furnizorul de servicii de internet sau față de site-urile pe care le accesezi.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, apasă pe Tab, apoi pe Enter pentru a adăuga și a gestiona adrese din setările Chrome</translation>
<translation id="7365849542400970216">Permiți detectarea folosirii dispozitivului?</translation>
<translation id="7372973238305370288">rezultat al căutării</translation>
@@ -1672,7 +1719,9 @@ Detalii suplimentare:
<translation id="7378594059915113390">Comenzi media</translation>
<translation id="7378627244592794276">Nu</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Nu se aplică</translation>
<translation id="7390545607259442187">Confirmă cardul</translation>
+<translation id="7392089738299859607">Actualizează adresa</translation>
<translation id="7399802613464275309">Verificare de siguranță</translation>
<translation id="7400418766976504921">Adresă URL</translation>
<translation id="7403591733719184120">Dispozitivul <ph name="DEVICE_NAME" /> este gestionat</translation>
@@ -1687,6 +1736,7 @@ Detalii suplimentare:
&lt;li&gt;Accesează &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Centrul de ajutor Chrome&lt;/a&gt; pentru a afla cum poți să elimini definitiv software-ul de pe computer
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Format-Larg</translation>
+<translation id="7410471291937727359">Adorabil</translation>
<translation id="7416351320495623771">Gestionează parolele…</translation>
<translation id="7419106976560586862">Calea profilului</translation>
<translation id="7437289804838430631">Adaugă informații de contact</translation>
@@ -1702,7 +1752,7 @@ Detalii suplimentare:
<translation id="7481312909269577407">ÃŽnainte</translation>
<translation id="7485870689360869515">Nu s-au găsit date.</translation>
<translation id="7495528107193238112">Acest conținut este blocat. Contactează proprietarul site-ului pentru a remedia problema.</translation>
-<translation id="7498234416455752244">Continuați editarea</translation>
+<translation id="7498193950643227031">Se poate comporta într-un mod neașteptat dacă este redimensionată. Acum poți limita posibilitatea de a redimensiona aplicații în <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Ai introdus parola pe un site înșelător. Chromium recomandă să verifici acum parolele salvate pentru <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> și alte site-uri pe care folosești această parolă.</translation>
<translation id="7508255263130623398">ID-ul de dispozitiv returnat pentru politică este gol sau nu corespunde cu ID-ul de dispozitiv actual</translation>
<translation id="7508870219247277067">Verde avocado</translation>
@@ -1722,6 +1772,7 @@ Detalii suplimentare:
<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="755279583747225797">Versiunea de încercare este activă</translation>
<translation id="7552846755917812628">Încearcă următoarele sfaturi:</translation>
<translation id="7554475479213504905">Reîncarcă și afișează oricum</translation>
<translation id="7554791636758816595">Filă nouă</translation>
@@ -1740,7 +1791,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, apasă pe Tab, apoi pe Enter pentru a vedea și a gestiona parolele din setările Chrome</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="7616645509853975347">Administratorul a activat Chrome Enterprise Connectors în browser. Acești conectori au acces la o parte din datele tale.</translation>
<translation id="7619838219691048931">Foaia finală</translation>
<translation id="762844065391966283">Câte unul</translation>
@@ -1805,13 +1855,12 @@ Detalii suplimentare:
<translation id="782886543891417279">Rețeaua Wi-Fi pe care o folosești (<ph name="WIFI_NAME" />) poate solicita accesarea paginii de conectare.</translation>
<translation id="7836231406687464395">Postfix (Plic)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Niciuna}=1{O aplicație (<ph name="EXAMPLE_APP_1" />)}=2{Două aplicații (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}few{# aplicații (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# de aplicații (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Cu toate acestea, nu ești invizibil(ă). Trecerea în modul incognito nu ascunde activitatea de navigare față de angajator, față de furnizorul de servicii de internet sau față de site-urile pe care le accesezi.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">să deschidă fișiere cu asocieri între tipurile de fișiere.</translation>
<translation id="7862185352068345852">Ieși de pe site?</translation>
<translation id="7865448901209910068">Viteza optimă</translation>
<translation id="7874263914261512992">Ai introdus parola pe un site înșelător. Chrome recomandă să verifici acum parolele salvate pentru <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> și alte site-uri pe care folosești această parolă.</translation>
<translation id="7878562273885520351">Este posibil ca parola să fie compromisă</translation>
+<translation id="7880146494886811634">Salvează adresa</translation>
<translation id="7882421473871500483">Maro</translation>
<translation id="7887683347370398519">Verifică codul CVC și încearcă din nou</translation>
<translation id="7887885240995164102">Intră în modul picture-in-picture</translation>
@@ -1819,6 +1868,7 @@ Detalii suplimentare:
<translation id="7894280532028510793">Dacă scrierea este corectă, <ph name="BEGIN_LINK" />încearcă să rulezi Diagnosticarea rețelei<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Plic)</translation>
<translation id="7931318309563332511">Necunoscută</translation>
+<translation id="793209273132572360">Actualizezi adresa?</translation>
<translation id="7932579305932748336">Acoperire</translation>
<translation id="79338296614623784">Introdu un număr de telefon valid</translation>
<translation id="7934052535022478634">Plată efectuată</translation>
@@ -1889,6 +1939,7 @@ Detalii suplimentare:
<translation id="8175796834047840627">Chrome oferă salvarea cardurilor în Contul Google pentru că te-ai conectat. Poți schimba acest comportament în setări.</translation>
<translation id="8176440868214972690">Administratorul dispozitivului a trimis câteva informații următoarelor site-uri, cum ar fi setări sau politici.</translation>
<translation id="8184538546369750125">Utilizați setarea prestabilită la nivel global (Permiteți)</translation>
+<translation id="8193086767630290324">Acțiuni realizate cu datele marcate drept confidențiale</translation>
<translation id="8194797478851900357">&amp;Anulați mutarea</translation>
<translation id="8201077131113104583">Adresa URL pentru actualizarea extensiei cu ID-ul „<ph name="EXTENSION_ID" />†nu este validă.</translation>
<translation id="8202097416529803614">Rezumatul comenzii</translation>
@@ -1911,6 +1962,7 @@ Detalii suplimentare:
<translation id="8249296373107784235">Abandonați</translation>
<translation id="8249320324621329438">Ultima preluare:</translation>
<translation id="8253091569723639551">Adresa de facturare este obligatorie</translation>
+<translation id="8257387598443225809">Aplicația este creată pentru dispozitive mobile</translation>
<translation id="825929999321470778">Afișează toate parolele salvate</translation>
<translation id="8261506727792406068">Șterge</translation>
<translation id="8262952874573525464">Broșare pe marginea de jos</translation>
@@ -1977,7 +2029,7 @@ Detalii suplimentare:
<translation id="8490137692873530638">Receptorul de hârtie 10</translation>
<translation id="8498891568109133222"><ph name="HOST_NAME" /> a răspuns prea târziu.</translation>
<translation id="8503559462189395349">Parole Chrome</translation>
-<translation id="8503813439785031346">Nume utilizator</translation>
+<translation id="8503813439785031346">Nume de utilizator</translation>
<translation id="8507227106804027148">Linie de comandă</translation>
<translation id="8508648098325802031">Pictograma Căutare</translation>
<translation id="8511402995811232419">Gestionează cookie-urile</translation>
@@ -2035,7 +2087,6 @@ Detalii suplimentare:
<translation id="8719528812645237045">Perforare multiplă în partea de sus</translation>
<translation id="8725066075913043281">Încearcă din nou</translation>
<translation id="8726549941689275341">Dimensiunea paginii:</translation>
-<translation id="8728672262656704056">Ai trecut în modul incognito</translation>
<translation id="8730621377337864115">Terminat</translation>
<translation id="8731544501227493793">Butonul Gestionează parolele, apasă pe Enter pentru a vedea și a gestiona parolele în setările Chrome</translation>
<translation id="8734529307927223492">Dispozitivul <ph name="DEVICE_TYPE" /> este gestionat de <ph name="MANAGER" /></translation>
@@ -2112,6 +2163,7 @@ Detalii suplimentare:
<translation id="9020542370529661692">Această pagină a fost tradusă în <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Nevalid)</translation>
+<translation id="9030265603405983977">Monocromatic</translation>
<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>
@@ -2135,6 +2187,7 @@ Detalii suplimentare:
<translation id="91108059142052966">Politica implementată de administrator dezactivează permiterea accesului la ecran pentru <ph name="APPLICATION_TITLE" /> atunci când este vizibil conținut confidențial</translation>
<translation id="9114524666733003316">Se confirmă cardul…</translation>
<translation id="9114581008513152754">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="9117930699067497412">Prospețime</translation>
<translation id="9119042192571987207">Încărcat</translation>
<translation id="9128016270925453879">Politicile s-au încărcat</translation>
<translation id="9128870381267983090">Conectați-vă la rețea</translation>
@@ -2153,6 +2206,7 @@ Detalii suplimentare:
<translation id="9170848237812810038">&amp;Anulează</translation>
<translation id="9171296965991013597">Ieși din aplicație?</translation>
<translation id="9173282814238175921">Un document/Foaie nouă</translation>
+<translation id="9173995187295789444">Se caută dispozitive Bluetooth...</translation>
<translation id="917450738466192189">Certificatul serverului nu este valid.</translation>
<translation id="9174917557437862841">Butonul Comută între file, apasă pe Enter pentru a comuta la această filă</translation>
<translation id="9179703756951298733">Gestionează informațiile despre plăți și carduri de credit din setările Chrome</translation>
diff --git a/chromium/components/strings/components_strings_ru.xtb b/chromium/components/strings/components_strings_ru.xtb
index 9c2b3d5e791..da312a0e9e0 100644
--- a/chromium/components/strings/components_strings_ru.xtb
+++ b/chromium/components/strings/components_strings_ru.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">ЕÑли флажок уÑтановлен, Chrome будет хранить на Ñтом уÑтройÑтве данные карты Ð´Ð»Ñ Ð±Ñ‹Ñтрого Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñ„Ð¾Ñ€Ð¼.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" />: выберите разрешение</translation>
<translation id="1113869188872983271">&amp;Отменить изменение порÑдка</translation>
+<translation id="1123753900084781868">ÐвтоматичеÑкие Ñубтитры ÑÐµÐ¹Ñ‡Ð°Ñ Ð½ÐµÐ´Ð¾Ñтупны.</translation>
<translation id="1125573121925420732">Пока на Ñайтах обновлÑÑŽÑ‚ÑÑ Ñертификаты безопаÑноÑти, Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð¾ могут поÑвлÑÑ‚ÑŒÑÑ Ñ‡Ð°Ñ‰Ðµ обычного.</translation>
<translation id="112840717907525620">В кеше политики ошибок не найдено</translation>
<translation id="1130564665089811311">Кнопка перевода Ñтраницы. Чтобы Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Google Переводчика ознакомитьÑÑ Ñ ÐµÐµ Ñодержанием, нажмите Ввод.</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Ðазвание вашего уÑтройÑтва</translation>
<translation id="124116460088058876">Другие Ñзыки</translation>
<translation id="1243027604378859286">Ðвтор:</translation>
+<translation id="1246424317317450637">Полужирный</translation>
<translation id="1250759482327835220">Чтобы уÑкорить процеÑÑ Ð¾Ð¿Ð»Ð°Ñ‚Ñ‹ в будущем, Ñохраните карту, Ñвое Ð¸Ð¼Ñ Ð¸ платежный Ð°Ð´Ñ€ÐµÑ Ð² аккаунте Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (данные ÑинхронизируютÑÑ)</translation>
<translation id="1256368399071562588">&lt;p&gt;ЕÑли Ñайт не открываетÑÑ, выполните Ñледующие дейÑтвиÑ:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Смените пароль</translation>
<translation id="1484290072879560759">Выбрать Ð°Ð´Ñ€ÐµÑ Ð´Ð¾Ñтавки поÑылок</translation>
<translation id="1492194039220927094">Обновление правил:</translation>
+<translation id="1495677929897281669">ВернутьÑÑ Ð½Ð° вкладку</translation>
<translation id="1501859676467574491">Показывать банковÑкие карты, Ñохраненные в аккаунте Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Эта ошибка может возникать при иÑпользовании портала Wi-Fi, Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ð¼ требуетÑÑ Ð²Ñ‹Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÑŒ вход.&lt;/p&gt;
&lt;p&gt;Чтобы уÑтранить проблему, нажмите &lt;strong&gt;ПодключитьÑÑ&lt;/strong&gt; на нужной веб-Ñтранице.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Подтвердите дейÑтвие</translation>
<translation id="153384715582417236">Пока Ñто вÑÑ‘</translation>
<translation id="1536390784834419204">ПеревеÑти Ñтраницу</translation>
+<translation id="1539840569003678498">Отчет отправлен:</translation>
<translation id="154408704832528245">Выбрать Ð°Ð´Ñ€ÐµÑ Ð´Ð¾Ñтавки</translation>
<translation id="1549470594296187301">Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтой функции необходимо включить JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">ÐÐ°Ñ‡Ð¸Ð½Ð°Ñ Ñ ÐºÐ¾Ñ€Ð¾Ñ‚ÐºÐ¾Ð³Ð¾ краÑ</translation>
<translation id="168693727862418163">Такое значение правила не предуÑмотрено и будет проигнорировано.</translation>
<translation id="168841957122794586">Сертификат Ñервера Ñодержит ненадежный криптографичеÑкий ключ.</translation>
+<translation id="1696290444144917273">Показать реквизиты виртуальной карты</translation>
<translation id="1697532407822776718">Готово!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Ðе удалоÑÑŒ подтвердить, что Ñто Ñервер <ph name="DOMAIN" />. Его Ñертификат безопаÑноÑти вÑтупит в Ñилу завтра. Возможно, Ñервер наÑтроен неправильно или кто-то пытаетÑÑ Ð¿ÐµÑ€ÐµÑ…Ð²Ð°Ñ‚Ð¸Ñ‚ÑŒ ваши данные.}one{Ðе удалоÑÑŒ подтвердить, что Ñто Ñервер <ph name="DOMAIN" />. Его Ñертификат безопаÑноÑти вÑтупит в Ñилу через # день. Возможно, Ñервер наÑтроен неправильно или кто-то пытаетÑÑ Ð¿ÐµÑ€ÐµÑ…Ð²Ð°Ñ‚Ð¸Ñ‚ÑŒ ваши данные.}few{Ðе удалоÑÑŒ подтвердить, что Ñто Ñервер <ph name="DOMAIN" />. Его Ñертификат безопаÑноÑти вÑтупит в Ñилу через # днÑ. Возможно, Ñервер наÑтроен неправильно или кто-то пытаетÑÑ Ð¿ÐµÑ€ÐµÑ…Ð²Ð°Ñ‚Ð¸Ñ‚ÑŒ ваши данные.}many{Ðе удалоÑÑŒ подтвердить, что Ñто Ñервер <ph name="DOMAIN" />. Его Ñертификат безопаÑноÑти вÑтупит в Ñилу через # дней. Возможно, Ñервер наÑтроен неправильно или кто-то пытаетÑÑ Ð¿ÐµÑ€ÐµÑ…Ð²Ð°Ñ‚Ð¸Ñ‚ÑŒ ваши данные.}other{Ðе удалоÑÑŒ подтвердить, что Ñто Ñервер <ph name="DOMAIN" />. Его Ñертификат безопаÑноÑти вÑтупит в Ñилу через # днÑ. Возможно, Ñервер наÑтроен неправильно или кто-то пытаетÑÑ Ð¿ÐµÑ€ÐµÑ…Ð²Ð°Ñ‚Ð¸Ñ‚ÑŒ ваши данные.}}</translation>
<translation id="1710259589646384581">ОС</translation>
+<translation id="1711234383449478798">ИгнорируетÑÑ, так как Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð° <ph name="POLICY_NAME" /> не уÑтановлено нужное значение (<ph name="VALUE" />).</translation>
<translation id="1712552549805331520">Сайт <ph name="URL" /> запрашивает разрешение на поÑтоÑнное хранение данных на вашем компьютере.</translation>
<translation id="1713628304598226412">Лоток 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Почтовый Ñщик 3</translation>
<translation id="1718029547804390981">ÐедоÑтупно, так как документ Ñлишком большой</translation>
<translation id="1721424275792716183">*ОбÑзательное поле</translation>
+<translation id="1727613060316725209">ДейÑтвительный Ñертификат</translation>
<translation id="1727741090716970331">Введите правильный номер карты</translation>
<translation id="1728677426644403582">Ð’Ñ‹ проÑматриваете код Ñтраницы</translation>
<translation id="173080396488393970">Этот тип карты не поддерживаетÑÑ.</translation>
@@ -242,13 +249,12 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Выполните диагноÑтику Ñети в Windows<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">Сервер <ph name="ORIGIN" />, на который вы переходите, уÑтановил заголовок, требующий применÑÑ‚ÑŒ правило иÑточника ко вÑем запроÑам. Однако из-за неверного формата заголовка браузер не может выполнить ваш Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð»Ñ Ñайта <ph name="SITE" />. Правила в отношении иÑточников позволÑÑŽÑ‚ операторам наÑтраивать параметры безопаÑноÑти и другие ÑвойÑтва Ñайтов.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Обновите кодовую фразу Ð´Ð»Ñ Ñинхронизации.</translation>
<translation id="1787142507584202372">ЗдеÑÑŒ поÑвÑÑ‚ÑÑ Ð¾Ñ‚ÐºÑ€Ñ‹Ñ‚Ñ‹Ðµ вкладки.</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Возможны разные дейÑтвиÑ. Ðажимайте Tab Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ ними.</translation>
<translation id="1800473098294731951">B9</translation>
<translation id="1803264062614276815">Владелец карты</translation>
-<translation id="1807246157184219062">Светлый</translation>
+<translation id="1807246157184219062">СветлаÑ</translation>
<translation id="1807528111851433570">Первый лиÑÑ‚</translation>
<translation id="1812527064848182527">Ð³Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾Ñ€Ð¸ÐµÐ½Ñ‚Ð°Ñ†Ð¸Ñ</translation>
<translation id="1814698615734239189">Это приложение предназначено Ð´Ð»Ñ Ð¼Ð¾Ð±Ð¸Ð»ÑŒÐ½Ñ‹Ñ… уÑтройÑтв. Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ð¾Ð½Ð¾ работает в режиме ÑовмеÑтимоÑти. ЕÑли вы разрешите изменÑÑ‚ÑŒ размер окна, Ñто может привеÑти к ошибкам, в том чиÑле к перезапуÑку приложениÑ.</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">Реклама</translation>
<translation id="1919367280705858090">Как уÑтранить определенные виды ошибок</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ðет}=1{1 Ñайт}one{# Ñайт}few{# Ñайта}many{# Ñайтов}other{# Ñайта}}</translation>
+<translation id="1924727005275031552">Ðовый</translation>
<translation id="1945968466830820669">Возможно, кто-то пытаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ доÑтуп к вашим личным данным или корпоративному аккаунту. Рекомендуем немедленно Ñменить пароль.</translation>
<translation id="1947454675006758438">Скоба в правом верхнем углу</translation>
<translation id="1958218078413065209">Ваш лучший результат: <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">Лоток 7</translation>
<translation id="204357726431741734">Войти, чтобы иÑпользовать пароли, Ñохраненные в аккаунте Google</translation>
<translation id="2053111141626950936">Страницы на Ñтом Ñзыке (<ph name="LANGUAGE" />) не будут переводитьÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{ЕÑли Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð° и активирована, Chrome определÑет по вашим недавним дейÑтвиÑм в браузере, к какой группе людей (когорте) Ð²Ð°Ñ Ð¾Ñ‚Ð½ÐµÑти. Рекламодатели могут выбрать объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой группы. Данные о ваших дейÑтвиÑÑ… в браузере хранÑÑ‚ÑÑ Ð½Ð° уÑтройÑтве и доÑтупны только вам. Группа обновлÑетÑÑ ÐµÐ¶ÐµÐ´Ð½ÐµÐ²Ð½Ð¾.}=1{ЕÑли Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð° и активирована, Chrome определÑет по вашим недавним дейÑтвиÑм в браузере, к какой группе людей (когорте) Ð²Ð°Ñ Ð¾Ñ‚Ð½ÐµÑти. Рекламодатели могут выбрать объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой группы. Данные о ваших дейÑтвиÑÑ… в браузере хранÑÑ‚ÑÑ Ð½Ð° уÑтройÑтве и доÑтупны только вам. Группа обновлÑетÑÑ ÐµÐ¶ÐµÐ´Ð½ÐµÐ²Ð½Ð¾.}one{ЕÑли Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð° и активирована, Chrome определÑет по вашим недавним дейÑтвиÑм в браузере, к какой группе людей (когорте) Ð²Ð°Ñ Ð¾Ñ‚Ð½ÐµÑти. Рекламодатели могут выбрать объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой группы. Данные о ваших дейÑтвиÑÑ… в браузере хранÑÑ‚ÑÑ Ð½Ð° уÑтройÑтве и доÑтупны только вам. Группа обновлÑетÑÑ ÐºÐ°Ð¶Ð´Ñ‹Ðµ {NUM_DAYS} день.}few{ЕÑли Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð° и активирована, Chrome определÑет по вашим недавним дейÑтвиÑм в браузере, к какой группе людей (когорте) Ð²Ð°Ñ Ð¾Ñ‚Ð½ÐµÑти. Рекламодатели могут выбрать объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой группы. Данные о ваших дейÑтвиÑÑ… в браузере хранÑÑ‚ÑÑ Ð½Ð° уÑтройÑтве и доÑтупны только вам. Группа обновлÑетÑÑ ÐºÐ°Ð¶Ð´Ñ‹Ðµ {NUM_DAYS} днÑ.}many{ЕÑли Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð° и активирована, Chrome определÑет по вашим недавним дейÑтвиÑм в браузере, к какой группе людей (когорте) Ð²Ð°Ñ Ð¾Ñ‚Ð½ÐµÑти. Рекламодатели могут выбрать объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой группы. Данные о ваших дейÑтвиÑÑ… в браузере хранÑÑ‚ÑÑ Ð½Ð° уÑтройÑтве и доÑтупны только вам. Группа обновлÑетÑÑ ÐºÐ°Ð¶Ð´Ñ‹Ðµ {NUM_DAYS} дней.}other{ЕÑли Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð° и активирована, Chrome определÑет по вашим недавним дейÑтвиÑм в браузере, к какой группе людей (когорте) Ð²Ð°Ñ Ð¾Ñ‚Ð½ÐµÑти. Рекламодатели могут выбрать объÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой группы. Данные о ваших дейÑтвиÑÑ… в браузере хранÑÑ‚ÑÑ Ð½Ð° уÑтройÑтве и доÑтупны только вам. Группа обновлÑетÑÑ ÐºÐ°Ð¶Ð´Ñ‹Ðµ {NUM_DAYS} днÑ.}}</translation>
<translation id="2053553514270667976">Почтовый индекÑ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 вариант}one{# вариант}few{# варианта}many{# вариантов}other{# варианта}}</translation>
<translation id="2071692954027939183">Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²Ð°Ð½Ñ‹ автоматичеÑки, потому что вы обычно запрещаете их показ.</translation>
<translation id="2079545284768500474">Отмена</translation>
<translation id="20817612488360358">Включены ÑиÑтемные наÑтройки прокÑи-Ñервера, но при Ñтом его ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð·Ð°Ð´Ð°Ð½Ð° Ñвным образом.</translation>
<translation id="2082238445998314030">Результат <ph name="RESULT_NUMBER" />, вÑего <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Сохранить</translation>
<translation id="2088086323192747268">Кнопка "ÐаÑтройки Ñинхронизации". Ðажмите Ввод, чтобы открыть наÑтройки Chrome и указать, ÐºÐ°ÐºÐ°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° ÑинхронизироватьÑÑ.</translation>
<translation id="2091887806945687916">Звук</translation>
<translation id="2094505752054353250">ÐеÑоответÑтвие домена</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535">Ð”Ð»Ñ Ð´Ð¾Ñтупа к домену <ph name="DOMAIN" /> необходимо указать Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ пароль.</translation>
<translation id="2330137317877982892">Карта <ph name="CREDIT_CARD" />, дейÑтвует до <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Эта наÑтройка управлÑетÑÑ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором</translation>
+<translation id="2340263603246777781">Сайт <ph name="ORIGIN" /> запрашивает подключение</translation>
<translation id="2344028582131185878">ÐвтоматичеÑÐºÐ°Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ°</translation>
<translation id="2346319942568447007">Скопированное изображение</translation>
<translation id="2354001756790975382">Другие закладки</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">Злоумышленники могут видеть изображениÑ, которые видны вам, и изменÑÑ‚ÑŒ их в целÑÑ… мошенничеÑтва.</translation>
<translation id="2356070529366658676">Спрашивать</translation>
<translation id="2357481397660644965">Вашим уÑтройÑтвом управлÑет <ph name="DEVICE_MANAGER" />, а аккаунтом – <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Меньше чем через 1 день}=1{Через 1 день}one{Через {NUM_DAYS} день}few{Через {NUM_DAYS} днÑ}many{Через {NUM_DAYS} дней}other{Через {NUM_DAYS} днÑ}}</translation>
<translation id="2359629602545592467">ÐеÑколько</translation>
<translation id="2359808026110333948">Продолжить</translation>
+<translation id="2359961752320758691">Применен номер виртуальной карты.</translation>
<translation id="2367567093518048410">Уровень</translation>
<translation id="2372464001869762664">ПоÑле Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ Ñ€ÐµÐºÐ²Ð¸Ð·Ð¸Ñ‚Ñ‹ карты из аккаунта Google будут переданы Ñтому Ñайту. CVC-код можно найти в данных Ñчета Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,8 +406,9 @@
<translation id="239429038616798445">Этот ÑпоÑоб доÑтавки недоÑтупен. Выберите другой.</translation>
<translation id="2396249848217231973">&amp;Отменить удаление</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Старый</translation>
<translation id="2413528052993050574">Ðе удалоÑÑŒ подтвердить, что Ñто Ñервер <ph name="DOMAIN" />. Его Ñертификат безопаÑноÑти может быть отозван. Возможно, Ñервер наÑтроен неправильно или кто-то пытаетÑÑ Ð¿ÐµÑ€ÐµÑ…Ð²Ð°Ñ‚Ð¸Ñ‚ÑŒ ваши данные.</translation>
-<translation id="2414886740292270097">Темный</translation>
+<translation id="2414886740292270097">ТемнаÑ</translation>
<translation id="2438874542388153331">Четыре отверÑÑ‚Ð¸Ñ Ñправа</translation>
<translation id="245044156129055925">Ð’Ñ‹ только что ввели пароль на поддельном Ñайте. Браузер Chromium рекомендует Ñменить пароль прÑмо ÑейчаÑ.</translation>
<translation id="2463739503403862330">Заполнить</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">Скоба в правом нижнем углу</translation>
<translation id="2523886232349826891">Карта будет Ñохранена только на Ñтом уÑтройÑтве</translation>
<translation id="2524461107774643265">Укажите дополнительную информацию</translation>
-<translation id="2526590354069164005">Рабочий Ñтол</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{и ещё 1}one{и ещё #}few{и ещё #}many{и ещё #}other{и ещё #}}</translation>
<translation id="2536110899380797252">Добавить адреÑ</translation>
<translation id="2539524384386349900">ОпределÑÑ‚ÑŒ</translation>
+<translation id="2541219929084442027">Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñтраницах, открытых в режиме инкогнито, не ÑохранÑетÑÑ. Это каÑаетÑÑ Ñ„Ð°Ð¹Ð»Ð¾Ð² cookie, а также иÑтории браузера или поиÑка. ПоÑле того как вы закроете Ñти вкладки, оÑтанутÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ñкачанные файлы и добавленные закладки.</translation>
<translation id="2544644783021658368">Один документ</translation>
<translation id="254947805923345898">ÐедопуÑтимое значение правила.</translation>
<translation id="255002559098805027">Сайт <ph name="HOST_NAME" /> отправил недейÑтвительный ответ.</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">Чтобы браузер Chrome Ñтал макÑимально безопаÑным, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />включите режим "Ð£Ð»ÑƒÑ‡ÑˆÐµÐ½Ð½Ð°Ñ Ð·Ð°Ñ‰Ð¸Ñ‚Ð°"<ph name="END_ENHANCED_PROTECTION_LINK" />.</translation>
<translation id="2634124572758952069">Ðе удалоÑÑŒ найти IP-Ð°Ð´Ñ€ÐµÑ Ñервера <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">СоÑтоÑние:</translation>
+<translation id="264810637653812429">СовмеÑтимые уÑтройÑтва не найдены.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />. Ðажмите Tab и затем Ввод, чтобы открыть наÑтройки Chrome и удалить иÑторию браузера, файлы cookie, кеш и прочее.</translation>
<translation id="2650446666397867134">ДоÑтуп к файлу запрещен</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">ПерезапуÑтить</translation>
<translation id="2803306138276472711">СиÑтема Google по проверке безопаÑноÑти Ñайтов недавно обнаружила на <ph name="SITE" /> <ph name="BEGIN_LINK" />вредоноÑное ПО<ph name="END_LINK" />. Будьте внимательны, иногда даже на безопаÑных Ñайтах поÑвлÑÑŽÑ‚ÑÑ Ð²Ð¸Ñ€ÑƒÑÑ‹.</translation>
<translation id="2807052079800581569">Положение Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾ оÑи Y</translation>
+<translation id="2820957248982571256">ПоиÑк…</translation>
<translation id="2824775600643448204">ÐдреÑÐ½Ð°Ñ Ñтрока и Ñтрока поиÑка</translation>
<translation id="2826760142808435982">Соединение зашифровано и проверено Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ <ph name="CIPHER" />. Ð’ качеÑтве механизма обмена ключами иÑпользуетÑÑ <ph name="KX" />.</translation>
<translation id="2835170189407361413">ОчиÑтить форму</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">Invite (конверт)</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="2859806420264540918">Этот Ñайт показывает навÑзчивую или вводÑщую в заблуждение рекламу.</translation>
+<translation id="287596039013813457">Дружелюбный</translation>
+<translation id="2876489322757410363">Вы выйдете из режима инкогнито, чтобы выполнить оплату во внешнем приложении. Продолжить?</translation>
<translation id="2878197950673342043">Ð”Ð²Ð¾Ð¹Ð½Ð°Ñ Ð¿ÐµÑ€Ð¿ÐµÐ½Ð´Ð¸ÐºÑƒÐ»ÑÑ€Ð½Ð°Ñ Ñ„Ð°Ð»ÑŒÑ†Ð¾Ð²ÐºÐ°</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Размещение окон</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">C9 (конверт)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />. Ðажмите Tab и затем Ввод, чтобы запуÑтить проверку безопаÑноÑти в наÑтройках Chrome</translation>
<translation id="3061707000357573562">ИÑправление ÑервиÑа</translation>
-<translation id="3064966200440839136">Ð’Ñ‹ выйдете из режима инкогнито, чтобы произвеÑти оплату во внешнем приложении. Продолжить?</translation>
<translation id="306573536155379004">Игра началаÑÑŒ.</translation>
<translation id="3080254622891793721">ИзображениÑ</translation>
<translation id="3086579638707268289">Ваши дейÑÑ‚Ð²Ð¸Ñ Ð² Интернете отÑлеживаютÑÑ</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">Вашим аккаунтом управлÑет <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">ВоÑÑтановить</translation>
<translation id="3162559335345991374">Возможно, вам нужно перейти на Ñтраницу входа Ñети Wi-Fi.</translation>
-<translation id="3167968892399408617">Страницы, открытые в Ñтом окне, не оÑтанутÑÑ Ð² иÑтории браузера или поиÑка. Они не оÑтавÑÑ‚ на компьютере Ñледов, таких как файлы cookie, поÑле того как вы закроете вÑе вкладки инкогнито. Скачанные вами файлы и добавленные закладки будут Ñохранены.</translation>
<translation id="3169472444629675720">Рекомендации</translation>
<translation id="3174168572213147020">ОÑтров</translation>
<translation id="3176929007561373547">Проверьте наÑтройки прокÑи-Ñервера или попроÑите админиÑтратора
@@ -592,10 +607,12 @@
<translation id="3229041911291329567">ВерÑÐ¸Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ уÑтройÑтва и браузера</translation>
<translation id="323107829343500871">Введите CVC-код карты <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Ð’Ñегда находить важный контент на Ñтом Ñайте</translation>
+<translation id="3249845759089040423">Яркий</translation>
<translation id="3252266817569339921">ФранцузÑкий</translation>
<translation id="3266793032086590337">Значение (конфликтующее)</translation>
<translation id="3268451620468152448">Вкладки</translation>
<translation id="3270847123878663523">&amp;Отменить изменение порÑдка</translation>
+<translation id="3271648667212143903">Сайт <ph name="ORIGIN" /> запрашивает подключение</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Ваша Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ (<ph name="ENROLLMENT_DOMAIN" />) отправила на Ñледующие веб-Ñайты некоторые данные, такие как наÑтройки и правила.</translation>
<translation id="3282497668470633863">Укажите Ð¸Ð¼Ñ Ð²Ð»Ð°Ð´ÐµÐ»ÑŒÑ†Ð° карты</translation>
@@ -648,6 +665,7 @@
<translation id="3428151540071562330">Один или неÑколько Ñерверных шаблонов URI DnsOverHttpsTemplates недейÑтвительны и не будут иÑпользоватьÑÑ.</translation>
<translation id="3431636764301398940">Сохранить карту на Ñтом уÑтройÑтве</translation>
<translation id="3432601291244612633">Закрыть Ñтраницу</translation>
+<translation id="3435738964857648380">БезопаÑноÑÑ‚ÑŒ</translation>
<translation id="3435896845095436175">Включить</translation>
<translation id="3438829137925142401">ИÑпользовать пароли, Ñохраненные в аккаунте Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -690,7 +708,10 @@
<translation id="3584299510153766161">Два отверÑÑ‚Ð¸Ñ Ñнизу</translation>
<translation id="3586931643579894722">Скрыть подробноÑти</translation>
<translation id="3587738293690942763">Середина</translation>
+<translation id="3590643883886679995">ПоÑле выхода из режима инкогнито учетные данные ÑохранÑÑ‚ÑÑ Ð½Ð° уÑтройÑтве.</translation>
+<translation id="359126217934908072">МеÑÑц/год:</translation>
<translation id="3592413004129370115">Italian (конверт)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Ð’Ñ‹ можете в любое Ð²Ñ€ÐµÐ¼Ñ ÑброÑить наÑтройки группы. Чтобы приÑоединитьÑÑ Ðº другой группе, потребуетÑÑ Ð¿Ñ€Ð¸Ð¼ÐµÑ€Ð½Ð¾ 1 день.}=1{Ð’Ñ‹ можете в любое Ð²Ñ€ÐµÐ¼Ñ ÑброÑить наÑтройки группы. Чтобы приÑоединитьÑÑ Ðº другой группе, потребуетÑÑ Ð¿Ñ€Ð¸Ð¼ÐµÑ€Ð½Ð¾ 1 день.}one{Ð’Ñ‹ можете в любое Ð²Ñ€ÐµÐ¼Ñ ÑброÑить наÑтройки группы. Чтобы приÑоединитьÑÑ Ðº другой группе, потребуетÑÑ Ð¿Ñ€Ð¸Ð¼ÐµÑ€Ð½Ð¾ {NUM_DAYS} день.}few{Ð’Ñ‹ можете в любое Ð²Ñ€ÐµÐ¼Ñ ÑброÑить наÑтройки группы. Чтобы приÑоединитьÑÑ Ðº другой группе, потребуетÑÑ Ð¿Ñ€Ð¸Ð¼ÐµÑ€Ð½Ð¾ {NUM_DAYS} днÑ.}many{Ð’Ñ‹ можете в любое Ð²Ñ€ÐµÐ¼Ñ ÑброÑить наÑтройки группы. Чтобы приÑоединитьÑÑ Ðº другой группе, потребуетÑÑ Ð¿Ñ€Ð¸Ð¼ÐµÑ€Ð½Ð¾ {NUM_DAYS} дней.}other{Ð’Ñ‹ можете в любое Ð²Ñ€ÐµÐ¼Ñ ÑброÑить наÑтройки группы. Чтобы приÑоединитьÑÑ Ðº другой группе, потребуетÑÑ Ð¾ÐºÐ¾Ð»Ð¾ {NUM_DAYS} днÑ.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Приложение заблокировано админиÑтратором</translation>
<translation id="3608932978122581043">Задать ориентацию</translation>
@@ -699,13 +720,13 @@
<translation id="3615877443314183785">Укажите правильный Ñрок дейÑтвиÑ.</translation>
<translation id="36224234498066874">ОчиÑтить иÑторию...</translation>
<translation id="362276910939193118">Показать вÑÑŽ иÑторию</translation>
-<translation id="3625635938337243871">ПоÑле выхода из режима инкогнито учетные данные ÑохранÑÑ‚ÑÑ Ð½Ð° уÑтройÑтве.</translation>
<translation id="3630155396527302611">ЕÑли программа входит в ÑпиÑок тех, которым разрешен доÑтуп к Ñети,
удалите ее из ÑпиÑка и добавьте туда Ñнова.</translation>
<translation id="3630699740441428070">ÐдминиÑтраторы Ñтого уÑтройÑтва наÑтроили подключение к Интернету так, чтобы видеть ваш Ñетевой трафик, в том чиÑле Ñайты, которые вы поÑещаете.</translation>
<translation id="3631244953324577188">БиометриÑ</translation>
<translation id="3633738897356909127">Кнопка "Обновить Chrome". Ðажмите Ввод, чтобы обновить Chrome.</translation>
<translation id="3634530185120165534">Лоток 5</translation>
+<translation id="3637662659967048211">Сохранить в аккаунте Google?</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Приложение:</translation>
<translation id="3650584904733503804">Проверка выполнена уÑпешно</translation>
@@ -746,6 +767,7 @@
<translation id="3781428340399460090">Ярко-розовый</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">УÑтройÑтва Bluetooth</translation>
+<translation id="3787675388804467730">Ðомер виртуальной карты</translation>
<translation id="3787705759683870569">Срок дейÑтвиÑ: до <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Размер: 16</translation>
<translation id="3789841737615482174">УÑтановить</translation>
@@ -765,6 +787,7 @@
<translation id="3841184659773414994">Обработчики файлов</translation>
<translation id="385051799172605136">Ðазад</translation>
<translation id="3858027520442213535">Обновить дату и времÑ</translation>
+<translation id="3881478300875776315">Показать меньше Ñтрок</translation>
<translation id="3884278016824448484">Конфликт идентификаторов уÑтройÑтв</translation>
<translation id="3885155851504623709">Округ</translation>
<translation id="388632593194507180">Соединение отÑлеживаетÑÑ</translation>
@@ -790,6 +813,7 @@
<translation id="397105322502079400">ВычиÑление…</translation>
<translation id="3973234410852337861">Сайт <ph name="HOST_NAME" /> заблокирован</translation>
<translation id="3973357910713125165">Кнопка запуÑка проверки безопаÑноÑти. Ðажмите Ввод, чтобы запуÑтить проверку безопаÑноÑти в наÑтройках Chrome</translation>
+<translation id="3986705137476756801">Отключить автоматичеÑкие Ñубтитры</translation>
<translation id="3987405730340719549">Браузер Chrome определил, что Ñтот Ñайт может оказатьÑÑ Ð¿Ð¾Ð´Ð´ÐµÐ»ÑŒÐ½Ñ‹Ð¼ или мошенничеÑким.
ЕÑли вы думаете, что Ñто Ñообщение показано по ошибке, заполните форму на Ñтранице https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -881,13 +905,14 @@
<translation id="4275830172053184480">ПерезапуÑк уÑтройÑтва</translation>
<translation id="4277028893293644418">СброÑить пароль</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Карта Ñохранена в аккаунте Google.}one{Карты Ñохранены в аккаунте Google.}few{Карты Ñохранены в аккаунте Google.}many{Карты Ñохранены в аккаунте Google.}other{Карты Ñохранены в аккаунте Google.}}</translation>
+<translation id="4287885627794386150">ÐŸÑ€Ð¾Ð±Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð´Ð¾Ñтупна, но не активирована</translation>
<translation id="4297502707443874121">Уменьшенное изображение Ñтраницы <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Развернуть</translation>
<translation id="4300675098767811073">ÐеÑколько отверÑтий Ñправа</translation>
<translation id="4302514097724775343">Чтобы начать игру, нажмите на динозаврика.</translation>
<translation id="4302965934281694568">Chou3 (конверт)</translation>
<translation id="4305666528087210886">Ðе удалоÑÑŒ получить доÑтуп к файлу</translation>
-<translation id="4305817255990598646">ПереключитьÑÑ</translation>
+<translation id="4306529830550717874">Сохранить адреÑ?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Блокировать (по умолчанию)</translation>
<translation id="4314815835985389558">ÐаÑтройки Ñинхронизации</translation>
@@ -914,6 +939,7 @@
<translation id="4377125064752653719">Ð’Ñ‹ попыталиÑÑŒ перейти на Ñайт <ph name="DOMAIN" />, однако Ñертификат, предоÑтавленный Ñервером, был отозван издателем. Это означает, что учетные данные безопаÑноÑти, предоÑтавленные Ñервером, не заÑлуживают довериÑ. Возможно, вы имеете дело Ñо злоумышленниками.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4390472908992056574">ПолÑ</translation>
+<translation id="4406883609789734330">ÐвтоматичеÑкие Ñубтитры</translation>
<translation id="4406896451731180161">Результаты поиÑка</translation>
<translation id="4408413947728134509">ÐаÑтройки файлов cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Ð’Ñ‹ только что ввели пароль на поддельном Ñайте. Рекомендуем немедленно Ñменить пароль Ð´Ð»Ñ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> и других Ñайтов, на которых вы иÑпользуете Ñтот пароль.</translation>
@@ -926,7 +952,6 @@
<translation id="4435702339979719576">Открытка</translation>
<translation id="443673843213245140">ПрокÑи-Ñервер отключен, но при Ñтом его ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð·Ð°Ð´Ð°Ð½Ð° Ñвным образом.</translation>
<translation id="4464826014807964867">Веб-Ñайты Ñо ÑведениÑми от вашей организации</translation>
-<translation id="4466881336512663640">ВнеÑенные в форму Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ðµ ÑохранÑÑ‚ÑÑ. Продолжить?</translation>
<translation id="4476953670630786061">Это Ð½ÐµÐ·Ð°Ñ‰Ð¸Ñ‰ÐµÐ½Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð¼Ð°. Ðвтозаполнение отключено.</translation>
<translation id="4477350412780666475">Следующий трек</translation>
<translation id="4482953324121162758">Этот Ñайт не будет переводитьÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки.</translation>
@@ -944,7 +969,7 @@
<translation id="4515275063822566619">Это карты и адреÑа, указанные в Chrome и вашем аккаунте Google (<ph name="ACCOUNT_EMAIL" />). Ð’Ñ‹ можете изменить их на Ñтранице <ph name="BEGIN_LINK" />ÐаÑтройки<ph name="END_LINK" />.</translation>
<translation id="4517607026994743406">Comm-10 (конверт)</translation>
<translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> мм (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">Подробнее</translation>
+<translation id="4522570452068850558">Детали</translation>
<translation id="4524138615196389145">Подтверждайте карты быÑтрее Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ WebAuthn</translation>
<translation id="4524805452350978254">Изменить</translation>
<translation id="4542971377163063093">Лоток 6</translation>
@@ -960,6 +985,7 @@
<translation id="4594403342090139922">&amp;Отменить удаление</translation>
<translation id="4597348597567598915">Размер: 8</translation>
<translation id="4600854749408232102">C6/C5 (конверт)</translation>
+<translation id="4606870351894164739">Эффектный</translation>
<translation id="4628948037717959914">Фото</translation>
<translation id="4631649115723685955">С кешбÑком</translation>
<translation id="4636930964841734540">ИнформациÑ</translation>
@@ -979,6 +1005,7 @@
<translation id="4691835149146451662">Architecture-A (конверт)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Сторона</translation>
+<translation id="4702656508969495934">ПоказываютÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑкие Ñубтитры. Чтобы открыть их, иÑпользуйте переключатель окон.</translation>
<translation id="4708268264240856090">Соединение прервано</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Выполните диагноÑтику Ñети в Windows<ph name="END_LINK" /></translation>
@@ -992,6 +1019,7 @@
<translation id="4738601419177586157">ПодÑказка при поиÑке "<ph name="TEXT" />"</translation>
<translation id="4742407542027196863">Управление паролÑми</translation>
<translation id="4744603770635761495">Путь к иÑполнÑемому файлу</translation>
+<translation id="4749011317274908093">Режим инкогнито</translation>
<translation id="4750917950439032686">ИнформациÑ, которую вы Ñообщаете Ñтому Ñайту (например, пароли и номера банковÑких карт), защищена.</translation>
<translation id="4756388243121344051">&amp;ИÑториÑ</translation>
<translation id="4758311279753947758">Добавить контактные данные</translation>
@@ -1021,6 +1049,8 @@
<translation id="4813512666221746211">Ошибка Ñети</translation>
<translation id="4816492930507672669">По размеру Ñтраницы</translation>
<translation id="4819347708020428563">Изменить заметки в режиме по умолчанию?</translation>
+<translation id="4825507807291741242">Мощный</translation>
+<translation id="4838327282952368871">Сказочный</translation>
<translation id="484462545196658690">Выбрать автоматичеÑки</translation>
<translation id="4850886885716139402">ПоÑмотреть</translation>
<translation id="485316830061041779">Ðемецкий</translation>
@@ -1157,6 +1187,7 @@
<translation id="5314967030527622926">Изготовление буклета</translation>
<translation id="5316812925700871227">Повернуть против чаÑовой Ñтрелки</translation>
<translation id="5317780077021120954">Сохранить</translation>
+<translation id="5321288445143113935">Развернутое окно</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> из <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Выбрать контактные данные</translation>
<translation id="5327248766486351172">ИмÑ</translation>
@@ -1164,11 +1195,13 @@
<translation id="5332219387342487447">СпоÑоб доÑтавки</translation>
<translation id="5333022057423422993">Пароль, который вы только что иÑпользовали, был раÑкрыт в результате утечки данных. Чтобы защитить Ñвои аккаунты, проверьте надежноÑÑ‚ÑŒ Ñохраненных паролей.</translation>
<translation id="5334013548165032829">Подробные ÑиÑтемные журналы.</translation>
+<translation id="5334145288572353250">Сохранить адреÑ?</translation>
<translation id="5340250774223869109">Приложение заблокировано</translation>
<translation id="534295439873310000">УÑтройÑтва Ñ NFC</translation>
<translation id="5344579389779391559">ЕÑли вы откроете Ñту Ñтраницу, Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ Ñчета могут быть ÑпиÑаны ÑредÑтва</translation>
<translation id="5355557959165512791">Сертификат веб-Ñайта <ph name="SITE" /> отозван. Открыть Ñайт в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÐ»ÑŒÐ·Ñ. Сбой мог быть вызван Ñетевой ошибкой или дейÑтвиÑми злоумышленников. Скорее вÑего, Ñайт заработает через некоторое времÑ.</translation>
<translation id="536296301121032821">Ðе удалоÑÑŒ Ñохранить наÑтройки политики</translation>
+<translation id="5363309033720083897">ПоÑледовательный порт разрешен админиÑтратором</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="5386426401304769735">Ð’ цепочке Ñертификатов Ñтого Ñайта еÑÑ‚ÑŒ Ñертификат, подпиÑанный Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ алгоритма SHA-1.</translation>
@@ -1177,6 +1210,7 @@
<translation id="5398772614898833570">Реклама заблокирована</translation>
<translation id="5400836586163650660">Серый</translation>
<translation id="540969355065856584">Ðе удалоÑÑŒ подтвердить, что Ñто Ñервер <ph name="DOMAIN" />. Его Ñертификат безопаÑноÑти может быть недейÑтвителен в наÑтоÑщее времÑ. Возможно, Ñервер наÑтроен неправильно или кто-то пытаетÑÑ Ð¿ÐµÑ€ÐµÑ…Ð²Ð°Ñ‚Ð¸Ñ‚ÑŒ ваши данные.</translation>
+<translation id="541143247543991491">Облако (ÑиÑтемное)</translation>
<translation id="541416427766103491">Укладчик 4</translation>
<translation id="5421136146218899937">ОчиÑтить иÑторию...</translation>
<translation id="5426179911063097041">С Ñайта <ph name="SITE" /> поÑтупил Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° отправку уведомлений.</translation>
@@ -1190,6 +1224,7 @@
<translation id="5455374756549232013">ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð¼ÐµÑ‚ÐºÐ° политики</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" /> контакт}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="5463625433003343978">ПоиÑк уÑтройÑтв…</translation>
<translation id="5469868506864199649">ИтальÑнÑкий</translation>
<translation id="5470861586879999274">&amp;Повторить изменениÑ</translation>
<translation id="5478437291406423475">B6/C4 (конверт)</translation>
@@ -1239,7 +1274,6 @@
<translation id="5624120631404540903">ÐаÑтройки паролей</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="563324245173044180">МошенничеÑкий контент заблокирован</translation>
<translation id="5644090287519800334">Смещение изображений на лицевой Ñтороне по оÑи X</translation>
@@ -1278,12 +1312,12 @@
<translation id="5785756445106461925">Обратите внимание, что на Ñтранице обнаружен небезопаÑный контент. Возможно, при передаче реÑурÑÑ‹ проÑматриваютÑÑ Ñ‚Ñ€ÐµÑ‚ÑŒÐ¸Ð¼Ð¸ лицами, а злоумышленники могут получить доÑтуп к Ñтранице и изменить ее поведение или внешний вид.</translation>
<translation id="5786044859038896871">Заполнить данные банковÑкой карты?</translation>
<translation id="578633867165174378">Пароль, который вы только что иÑпользовали, был раÑкрыт в результате утечки данных. Советуем изменить его прÑмо ÑейчаÑ.</translation>
-<translation id="5798290721819630480">Отменить изменениÑ?</translation>
<translation id="5803412860119678065">Заполнить данные банковÑкой карты <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">РазрешениÑ</translation>
<translation id="5804427196348435412">ИÑпользование уÑтройÑтв Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸ÐµÐ¹ NFC</translation>
<translation id="5810442152076338065">Соединение Ñ <ph name="DOMAIN" /> зашифровано Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ уÑтаревшего набора шифров.</translation>
<translation id="5813119285467412249">&amp;Повторить добавление</translation>
+<translation id="5817918615728894473">Подключить</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{При оплате ÑредÑтва будут ÑпиÑаны Ñ Ñтой карты, но ее наÑтоÑщий номер не Ñтанет извеÑтен Ñтому Ñайту. Ð”Ð»Ñ Ð¾Ð±ÐµÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ безопаÑноÑти будет Ñоздан временный CVC-код.}one{При оплате ÑредÑтва будут ÑпиÑаны Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ карты, но ее наÑтоÑщий номер не Ñтанет извеÑтен Ñтому Ñайту. Ð”Ð»Ñ Ð¾Ð±ÐµÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ безопаÑноÑти будет Ñоздан временный CVC-код.}few{При оплате ÑредÑтва будут ÑпиÑаны Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ карты, но ее наÑтоÑщий номер не Ñтанет извеÑтен Ñтому Ñайту. Ð”Ð»Ñ Ð¾Ð±ÐµÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ безопаÑноÑти будет Ñоздан временный CVC-код.}many{При оплате ÑредÑтва будут ÑпиÑаны Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ карты, но ее наÑтоÑщий номер не Ñтанет извеÑтен Ñтому Ñайту. Ð”Ð»Ñ Ð¾Ð±ÐµÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ безопаÑноÑти будет Ñоздан временный CVC-код.}other{При оплате ÑредÑтва будут ÑпиÑаны Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¹ карты, но ее наÑтоÑщий номер не Ñтанет извеÑтен Ñтому Ñайту. Ð”Ð»Ñ Ð¾Ð±ÐµÑÐ¿ÐµÑ‡ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð¹ безопаÑноÑти будет Ñоздан временный CVC-код.}}</translation>
<translation id="5826507051599432481">Общее Ð¸Ð¼Ñ (CN)</translation>
<translation id="5838278095973806738">Ðе Ñообщайте Ñтому Ñайту конфиденциальную информацию (например, пароли и номера банковÑких карт). К ней могут получить доÑтуп злоумышленники.</translation>
@@ -1291,6 +1325,7 @@
<translation id="5855253129151731373">Ð˜Ð¼Ñ Ñ…Ð¾Ñта Ñтого Ñайта похоже на <ph name="LOOKALIKE_DOMAIN" />. Иногда злоумышленники Ñоздают копии Ñайтов, Ñлегка изменÑÑ Ð´Ð¾Ð¼ÐµÐ½Ð½Ð¾Ðµ имÑ.
ЕÑли вы думаете, что Ñто Ñообщение показано по ошибке, заполните форму на Ñтранице https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">ВЫКЛ</translation>
<translation id="5862579898803147654">Укладчик 8</translation>
<translation id="5863847714970149516">При открытии Ñтой Ñтраницы Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ Ñчета могут быть ÑпиÑаны ÑредÑтва</translation>
<translation id="5866257070973731571">Добавьте номер телефона</translation>
@@ -1307,6 +1342,7 @@
<translation id="5913377024445952699">Съемка Ñкрана приоÑтановлена</translation>
<translation id="59174027418879706">Включено</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{ИÑпользуетÑÑ 1 файл cookie}one{ИÑпользуетÑÑ # файл cookie}few{ИÑпользуетÑÑ # файла cookie}many{ИÑпользуетÑÑ # файлов cookie}other{ИÑпользуетÑÑ # файла cookie}}</translation>
<translation id="5921185718311485855">ВКЛ</translation>
<translation id="5921639886840618607">Сохранить карту в аккаунте Google?</translation>
<translation id="5922853866070715753">Почти готово…</translation>
@@ -1326,6 +1362,7 @@
<translation id="5989320800837274978">Ðи фикÑированные прокÑи-Ñерверы, ни URL PAC-Ñкриптов не указаны.</translation>
<translation id="5992691462791905444">Ð£ÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ð°Ñ Ñ„Ð°Ð»ÑŒÑ†Ð¾Ð²ÐºÐ° гармошкой</translation>
<translation id="6000758707621254961">КоличеÑтво результатов поиÑка по запроÑу "<ph name="SEARCH_TEXT" />": <ph name="RESULT_COUNT" /></translation>
+<translation id="6006484371116297560">КлаÑÑичеÑкаÑ</translation>
<translation id="6008122969617370890">Ð’ порÑдке от N до 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Проверьте Ñвои пароли</translation>
@@ -1347,6 +1384,7 @@
<translation id="6045164183059402045">Шаблон ÑпуÑка полоÑ</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="6049004884579590341">Чтобы выйти из полноÑкранного режима, нажмите и удерживайте клавишу |<ph name="ACCELERATOR" />|</translation>
<translation id="6049488691372270142">Выдача Ñтраниц</translation>
<translation id="6051221802930200923">Веб-Ñайт <ph name="SITE" /> иÑпользует механизм Certificate Pinning, поÑтому на нем могла произойти подмена Ñертификата. Открыть Ñайт в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½ÐµÐ»ÑŒÐ·Ñ. Сбой мог быть вызван Ñетевой ошибкой или дейÑтвиÑми злоумышленников. Скорее вÑего, Ñайт заработает через некоторое времÑ.</translation>
<translation id="6051898664905071243">КоличеÑтво Ñтраниц:</translation>
@@ -1363,6 +1401,7 @@
<translation id="610911394827799129">Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ других ваших дейÑтвиÑÑ… в Интернете может также хранитьÑÑ Ð½Ð° Ñтранице <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
<translation id="6116338172782435947">ПроÑмотр текÑта и изображений, Ñкопированных в буфер обмена</translation>
<translation id="6120179357481664955">Запомнить идентификатор UPI?</translation>
+<translation id="6123290840358279103">ПоÑмотреть виртуальную карту</translation>
<translation id="6124432979022149706">Коннекторы Chrome Enterprise</translation>
<translation id="6146055958333702838">Проверьте Ñоединение кабелей, перезагрузите маршрутизаторы, модемы и другие
Ñетевые уÑтройÑтва.</translation>
@@ -1399,6 +1438,7 @@
<translation id="6289939620939689042">Цвет Ñтраницы</translation>
<translation id="6290238015253830360">ЗдеÑÑŒ поÑвÑÑ‚ÑÑ Ñ€ÐµÐºÐ¾Ð¼ÐµÐ½Ð´ÑƒÐµÐ¼Ñ‹Ðµ Ñтатьи.</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">Код CVC:</translation>
<translation id="6302269476990306341">Google ÐÑÑиÑтент в Chrome отключитÑÑ</translation>
<translation id="6305205051461490394">Сайт <ph name="URL" /> недоÑтупен.</translation>
<translation id="6312113039770857350">Ðе удалоÑÑŒ открыть веб-Ñтраницу</translation>
@@ -1424,6 +1464,7 @@
<translation id="6390200185239044127">Фальцовка гармошкой</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">ÐдминиÑтратор запретил вÑтавлÑÑ‚ÑŒ Ñюда контент Ñо Ñтраницы <ph name="ORIGIN_NAME" />.</translation>
+<translation id="6398765197997659313">Обычный режим</translation>
<translation id="6401136357288658127">Правило уÑтарело. ИÑпользуйте <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Изменить закладку</translation>
<translation id="6406765186087300643">C0 (конверт)</translation>
@@ -1436,7 +1477,6 @@
<translation id="6428450836711225518">Подтвердите номер телефона</translation>
<translation id="6433490469411711332">Изменить контактную информацию</translation>
<translation id="6433595998831338502">Сайт <ph name="HOST_NAME" /> не позволÑет уÑтановить Ñоединение.</translation>
-<translation id="6434309073475700221">Закрыть</translation>
<translation id="6440503408713884761">ПропуÑкаетÑÑ</translation>
<translation id="6443406338865242315">УÑтановленные раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð¸ плагины.</translation>
<translation id="6446163441502663861">Kahu (конверт)</translation>
@@ -1479,6 +1519,7 @@
<translation id="6624427990725312378">ÐšÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ</translation>
<translation id="6626291197371920147">Введите номер дейÑтвующей карты</translation>
<translation id="6628463337424475685">ПоиÑк <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">ПоиÑк USB-уÑтройÑтв…</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Удалить</translation>
@@ -1494,6 +1535,7 @@
<translation id="6671697161687535275">Удалить подÑказку из Chromium?</translation>
<translation id="6685834062052613830">Выйдите из аккаунта и завершите наÑтройку</translation>
<translation id="6687335167692595844">Размер шрифта запрошен</translation>
+<translation id="6688743156324860098">Изменить</translation>
<translation id="6689249931105087298">ОтноÑительный Ñо Ñжатием точки черного цвета</translation>
<translation id="6689271823431384964">Chrome предлагает вам Ñохранить карты в аккаунте Google, поÑкольку вы вошли в ÑиÑтему. Этот параметр можно изменить в разделе наÑтроек. Ð˜Ð¼Ñ Ð²Ð»Ð°Ð´ÐµÐ»ÑŒÑ†Ð° карты взÑто из вашего аккаунта.</translation>
<translation id="6698381487523150993">Создано:</translation>
@@ -1509,6 +1551,7 @@
<translation id="6744009308914054259">Ð’ ожидании Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð²Ñ‹ можете открыть Ñкачанные файлы и почитать Ñтатьи офлайн.</translation>
<translation id="6753269504797312559">Значение правила</translation>
<translation id="6757797048963528358">УÑтройÑтво находитÑÑ Ð² ÑпÑщем режиме.</translation>
+<translation id="6767985426384634228">Изменить адреÑ?</translation>
<translation id="6768213884286397650">Hagaki (открытка)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Фиолетовый</translation>
@@ -1531,6 +1574,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" />, <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Браузер Chrome упроÑтил вид Ñтраницы, чтобы ее было удобнее читать. ИÑÑ…Ð¾Ð´Ð½Ð°Ñ Ñтраница была получена Ñ Ð¸Ñпользованием незащищенного ÑоединениÑ.</translation>
<translation id="6891596781022320156">Значение правила не поддерживаетÑÑ.</translation>
+<translation id="6895143722905299846">Ðомер карты:</translation>
<translation id="6895330447102777224">Ваша карта подтверждена</translation>
<translation id="6897140037006041989">User Agent</translation>
<translation id="6898699227549475383">ÐžÑ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ (O)</translation>
@@ -1566,10 +1610,10 @@
<translation id="7004583254764674281">ИÑпользовать Windows Hello Ð´Ð»Ñ Ð±Ñ‹Ñтрого Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ ÐºÐ°Ñ€Ñ‚</translation>
<translation id="7006930604109697472">Ð’Ñе равно отправить</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ÐаÑтройки Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·Ð¼ÐµÑ€Ð°</translation>
<translation id="7014741021609395734">МаÑштаб</translation>
<translation id="7016992613359344582">СпиÑание может быть разовым или повторÑющимÑÑ Ð±ÐµÐ· каких-либо уведомлений.</translation>
<translation id="7029809446516969842">Пароли</translation>
+<translation id="7030436163253143341">ÐедейÑтвительный Ñертификат</translation>
<translation id="7031646650991750659">ПриложениÑ, уÑтановленные из Google Play.</translation>
<translation id="7050187094878475250">Ð’Ñ‹ попыталиÑÑŒ перейти на Ñайт <ph name="DOMAIN" />, но Ñервер предоÑтавил не заÑлуживающий Ð´Ð¾Ð²ÐµÑ€Ð¸Ñ Ñертификат Ñо Ñлишком долгим Ñроком дейÑтвиÑ.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ñохранить Ñту карту нельзÑ.}one{Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ñохранить Ñти карты нельзÑ.}few{Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ñохранить Ñти карты нельзÑ.}many{Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ñохранить Ñти карты нельзÑ.}other{Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ñохранить Ñти карты нельзÑ.}}</translation>
@@ -1639,12 +1683,14 @@
<translation id="7300012071106347854">Синий (кобальт)</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Ð’Ñ‹Ñокий</translation>
+<translation id="7305756307268530424">ЗапуÑтить медленнее</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">УÑтранение ошибок при подключении к Интернету</translation>
<translation id="7323804146520582233">Скрыть раздел "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Приоритет локального аккаунта на уÑтройÑтве</translation>
<translation id="7333654844024768166">Ð’Ñ‹ только что ввели пароль на поддельном Ñайте. Рекомендуем немедленно Ñменить пароль Ð´Ð»Ñ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> и других Ñайтов, на которых вы иÑпользуете Ñтот пароль.</translation>
<translation id="7334320624316649418">&amp;Повторить изменение порÑдка</translation>
+<translation id="7337248890521463931">Показать больше Ñтрок</translation>
<translation id="7337706099755338005">ÐедоÑтупно на вашей платформе.</translation>
<translation id="733923710415886693">Сертификат Ñервера не проходил проверку.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1652,6 +1698,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">ÐšÐ¾Ð¼Ð°Ð½Ð´Ð½Ð°Ñ Ñтрока</translation>
<translation id="7359588939039777303">Реклама заблокирована.</translation>
+<translation id="7363096869660964304">Тем не менее ваши дейÑÑ‚Ð²Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ видны работодателю и интернет-провайдеру, а также доÑтупны веб-Ñайтам, которые вы поÑещаете.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />. Ðажмите Tab, а затем – Ввод, чтобы добавить и изменить адреÑа в наÑтройках Chrome.</translation>
<translation id="7365849542400970216">ПредоÑтавить информацию об иÑпользовании уÑтройÑтва?</translation>
<translation id="7372973238305370288">результат поиÑка</translation>
@@ -1662,7 +1709,9 @@
<translation id="7378594059915113390">Элементы ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¼ÐµÐ´Ð¸Ð°Ñ„Ð°Ð¹Ð»Ð°Ð¼Ð¸</translation>
<translation id="7378627244592794276">Ðет</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ðеприменимо</translation>
<translation id="7390545607259442187">Подтвердите карту</translation>
+<translation id="7392089738299859607">Изменить адреÑ</translation>
<translation id="7399802613464275309">Проверка безопаÑноÑти</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Это уÑтройÑтво <ph name="DEVICE_NAME" /> управлÑетÑÑ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтратором</translation>
@@ -1677,6 +1726,7 @@
&lt;li&gt;О том, как удалить ПО Ñ ÐºÐ¾Ð¼Ð¿ÑŒÑŽÑ‚ÐµÑ€Ð°, читайте в &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Справочном центре Chrome&lt;/a&gt;.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Симпатичный</translation>
<translation id="7416351320495623771">Управление паролÑми</translation>
<translation id="7419106976560586862">Путь к профилю</translation>
<translation id="7437289804838430631">Добавить контактные данные</translation>
@@ -1692,7 +1742,7 @@
<translation id="7481312909269577407">Вперед</translation>
<translation id="7485870689360869515">Данные не найдены.</translation>
<translation id="7495528107193238112">Этот контент заблокирован. Чтобы уÑтранить неполадку, ÑвÑжитеÑÑŒ Ñ Ð²Ð»Ð°Ð´ÐµÐ»ÑŒÑ†ÐµÐ¼ Ñайта.</translation>
-<translation id="7498234416455752244">Продолжить редактирование</translation>
+<translation id="7498193950643227031">ÐŸÑ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ работать некорректно в Ñлучае Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð°Ñштаба изображениÑ. Теперь в разделе "<ph name="SETTINGS" />" можно запретить такое изменение.</translation>
<translation id="7503664977220660814">Ð’Ñ‹ только что ввели пароль на поддельном Ñайте. Рекомендуем проверить Ñохраненные пароли Ð´Ð»Ñ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> и других Ñайтов, на которых вы иÑпользуете Ñтот пароль.</translation>
<translation id="7508255263130623398">Возвращенный идентификатор уÑтройÑтва пуÑÑ‚ или не ÑоответÑтвует имеющемуÑÑ</translation>
<translation id="7508870219247277067">Зеленый (авокадо)</translation>
@@ -1712,6 +1762,7 @@
<translation id="7548892272833184391">Как уÑтранить ошибки при подключении к Интернету</translation>
<translation id="7549584377607005141">Ð”Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ð³Ð¾ Ð¾Ñ‚Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð²ÐµÐ±-Ñтраницы требуютÑÑ Ð²Ð²ÐµÐ´ÐµÐ½Ð½Ñ‹Ðµ ранее данные. Их можно отправить повторно, но в Ñтом Ñлучае вÑе дейÑÑ‚Ð²Ð¸Ñ Ð½Ð° Ñтранице будут выполнены Ñнова.</translation>
<translation id="7550637293666041147">Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÑтройÑтва и браузера Chrome</translation>
+<translation id="755279583747225797">ÐŸÑ€Ð¾Ð±Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð°</translation>
<translation id="7552846755917812628">Попробуйте Ñделать Ñледующее:</translation>
<translation id="7554475479213504905">Ð’Ñе равно показать (Ñтраница будет обновлена)</translation>
<translation id="7554791636758816595">ÐÐ¾Ð²Ð°Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ°</translation>
@@ -1730,7 +1781,6 @@
<translation id="7610193165460212391">Значение <ph name="VALUE" /> лежит за пределами разрешенного диапазона.</translation>
<translation id="7613889955535752492">Срок дейÑтвиÑ: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />. Ðажмите Tab и затем Ввод, чтобы перейти к управлению паролÑми в наÑтройках Chrome.</translation>
-<translation id="7615602087246926389">У Ð²Ð°Ñ ÑƒÐ¶Ðµ еÑÑ‚ÑŒ данные, зашифрованные Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¹ верÑией Ð¿Ð°Ñ€Ð¾Ð»Ñ Ðº аккаунту Google. Введите Ñтот пароль ниже.</translation>
<translation id="7616645509853975347">ÐдминиÑтратор включил в браузере коннекторы Chrome Enterprise Connectors. У них еÑÑ‚ÑŒ доÑтуп к некоторым вашим данным.</translation>
<translation id="7619838219691048931">ПоÑледний лиÑÑ‚</translation>
<translation id="762844065391966283">По одному объекту</translation>
@@ -1795,13 +1845,12 @@
<translation id="782886543891417279">Возможно, вам нужно перейти на Ñтраницу входа Ñети Wi-Fi (<ph name="WIFI_NAME" />).</translation>
<translation id="7836231406687464395">Postfix (конверт)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ðет}=1{1 приложение (<ph name="EXAMPLE_APP_1" />)}=2{2 Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# приложение (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}few{# Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}many{# приложений (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}other{# Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Тем не менее ваши дейÑÑ‚Ð²Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ видны ÑиÑтемному админиÑтратору и интернет-провайдеру, а также доÑтупны веб-Ñайтам, которые вы поÑещаете.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Открытие файлов Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑопоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð¾Ð² файлов</translation>
<translation id="7862185352068345852">Закрыть Ñайт?</translation>
<translation id="7865448901209910068">Ð›ÑƒÑ‡ÑˆÐ°Ñ ÑкороÑÑ‚ÑŒ</translation>
<translation id="7874263914261512992">Ð’Ñ‹ только что ввели пароль на поддельном Ñайте. Рекомендуем проверить Ñохраненные пароли Ð´Ð»Ñ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> и других Ñайтов, на которых вы иÑпользуете Ñтот пароль.</translation>
<translation id="7878562273885520351">Злоумышленники могли узнать ваш пароль</translation>
+<translation id="7880146494886811634">Сохранить адреÑ</translation>
<translation id="7882421473871500483">Коричневый</translation>
<translation id="7887683347370398519">Проверьте CVC-код и повторите попытку</translation>
<translation id="7887885240995164102">Включить режим "Картинка в картинке"</translation>
@@ -1809,6 +1858,7 @@
<translation id="7894280532028510793">ЕÑли вÑе правильно, <ph name="BEGIN_LINK" />выполните диагноÑтику Ñети<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (конверт)</translation>
<translation id="7931318309563332511">ÐеизвеÑтно</translation>
+<translation id="793209273132572360">Обновить адреÑ?</translation>
<translation id="7932579305932748336">Покрытие</translation>
<translation id="79338296614623784">Укажите дейÑтвительный номер телефона.</translation>
<translation id="7934052535022478634">Платеж обработан</translation>
@@ -1879,6 +1929,7 @@
<translation id="8175796834047840627">Chrome предлагает вам Ñохранить карты в аккаунте Google, поÑкольку вы вошли в ÑиÑтему. Этот параметр можно изменить в разделе наÑтроек.</translation>
<translation id="8176440868214972690">ÐдминиÑтратор уÑтройÑтва отправил на Ñледующие веб-Ñайты некоторые данные, такие как наÑтройки и правила.</translation>
<translation id="8184538546369750125">ИÑпользовать глобальный параметр по умолчанию (разрешать)</translation>
+<translation id="8193086767630290324">ДейÑÑ‚Ð²Ð¸Ñ Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸, помеченными как конфиденциальные.</translation>
<translation id="8194797478851900357">&amp;Отменить перемещение</translation>
<translation id="8201077131113104583">ÐедейÑтвительный URL Ð´Ð»Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ñ€Ð°ÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼ <ph name="EXTENSION_ID" />.</translation>
<translation id="8202097416529803614">Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ заказе</translation>
@@ -1901,6 +1952,7 @@
<translation id="8249296373107784235">Отмена</translation>
<translation id="8249320324621329438">Ð’Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ñледней загрузки:</translation>
<translation id="8253091569723639551">Ðеобходимо указать платежный адреÑ</translation>
+<translation id="8257387598443225809">Это приложение Ð´Ð»Ñ Ð¼Ð¾Ð±Ð¸Ð»ÑŒÐ½Ñ‹Ñ… уÑтройÑтв</translation>
<translation id="825929999321470778">Показать вÑе Ñохраненные пароли</translation>
<translation id="8261506727792406068">Удалить</translation>
<translation id="8262952874573525464">Скобы по нижнему краю</translation>
@@ -2024,7 +2076,6 @@
<translation id="8719528812645237045">ÐеÑколько отверÑтий Ñверху</translation>
<translation id="8725066075913043281">Повторить попытку</translation>
<translation id="8726549941689275341">Размер Ñтраницы:</translation>
-<translation id="8728672262656704056">Вы перешли в режим инкогнито</translation>
<translation id="8730621377337864115">Готово</translation>
<translation id="8731544501227493793">Кнопка "Управление паролÑми". Ðажмите Ввод, чтобы перейти к управлению паролÑми в наÑтройках Chrome.</translation>
<translation id="8734529307927223492">Вашим уÑтройÑтвом <ph name="DEVICE_TYPE" /> управлÑет <ph name="MANAGER" /></translation>
@@ -2101,6 +2152,7 @@
<translation id="9020542370529661692">Эта Ñтраница переведена на <ph name="TARGET_LANGUAGE" />.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(недейÑтвительный)</translation>
+<translation id="9030265603405983977">Монохромный</translation>
<translation id="9035022520814077154">Ошибка безопаÑноÑти</translation>
<translation id="9038649477754266430">ИÑпользовать подÑказки Ð´Ð»Ñ ÑƒÑÐºÐ¾Ñ€ÐµÐ½Ð¸Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ Ñтраниц</translation>
<translation id="9039213469156557790">Обратите внимание, что на Ñтранице обнаружен небезопаÑный контент. Возможно, при передаче реÑурÑÑ‹ проÑматриваютÑÑ Ñ‚Ñ€ÐµÑ‚ÑŒÐ¸Ð¼Ð¸ лицами, а злоумышленники могут получить доÑтуп к Ñтранице и изменить ее поведение.</translation>
@@ -2124,6 +2176,7 @@
<translation id="91108059142052966">ÐдминиÑтратор запретил демонÑтрацию Ñкрана Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ <ph name="APPLICATION_TITLE" />, когда видны конфиденциальные данные.</translation>
<translation id="9114524666733003316">Подтверждение карты...</translation>
<translation id="9114581008513152754">ÐšÐ¾Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ðµ управлÑет Ñтим браузером. ДейÑтвиÑми на Ñтом уÑтройÑтве можно управлÑÑ‚ÑŒ вне браузера Chrome. <ph name="BEGIN_LINK" />Подробнее…<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Свежий</translation>
<translation id="9119042192571987207">Загружен</translation>
<translation id="9128016270925453879">Правила загружены</translation>
<translation id="9128870381267983090">ПодключитеÑÑŒ к Ñети</translation>
@@ -2142,6 +2195,7 @@
<translation id="9170848237812810038">&amp;Отменить</translation>
<translation id="9171296965991013597">Закрыть приложение?</translation>
<translation id="9173282814238175921">Один документ/новый лиÑÑ‚</translation>
+<translation id="9173995187295789444">ПоиÑк уÑтройÑтв Bluetooth…</translation>
<translation id="917450738466192189">Сертификат Ñервера недейÑтвителен</translation>
<translation id="9174917557437862841">Кнопка Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¼ÐµÐ¶Ð´Ñƒ вкладками. Чтобы переключитьÑÑ Ð½Ð° Ñту вкладку, нажмите клавишу "Ввод".</translation>
<translation id="9179703756951298733">Обновить данные о ÑпоÑобах оплаты и банковÑких картах в наÑтройках Chrome</translation>
diff --git a/chromium/components/strings/components_strings_si.xtb b/chromium/components/strings/components_strings_si.xtb
index a6bbf44c1f9..cfd90767f50 100644
--- a/chromium/components/strings/components_strings_si.xtb
+++ b/chromium/components/strings/components_strings_si.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">පරීක්ෂ෠කළේනම්, වේගවත් ආකෘති පිරවීම සඳහ෠Chrome ඔබේ කà·à¶©à·Šà¶´à¶­à·š පිටපතක් මෙම උපà·à¶‚ගයෙහි ගබඩ෠කරනු ඇත.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> සඳහ෠අවසරය තà·à¶»à¶±à·Šà¶±</translation>
<translation id="1113869188872983271">යළි ඇණවුම් කිරීම &amp;පසුගමනය කරන්න</translation>
+<translation id="1123753900084781868">මේ මොහොතේ සජීවී සිරස්තලය ලබ෠ගත නොහà·à¶š</translation>
<translation id="1125573121925420732">වෙබ් අඩවි ඔවුන්ගේ ආරක්ෂà·à·€ යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන අතරතුර අනතුරු ඇඟවීම් පොදු දෙයක් විය à·„à·à¶š. මෙය ඉක්මනින් à·€à·à¶©à·’ දියුණු විය යුතුය.</translation>
<translation id="112840717907525620">ප්â€à¶»à¶­à·’පත්ති තà·à·€à¶šà·à¶½à·’ක මතකය හරි</translation>
<translation id="1130564665089811311">පිටුව පරිවර්තනය කරන්න බොත්තම, Google පරිවර්තනය සමඟ මෙම පිටුව පරිවර්තනය කිරීමට Enter ඔබන්න</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">ඔබේ උපà·à¶‚ගයේ නම</translation>
<translation id="124116460088058876">තවත් භà·à·‚à·</translation>
<translation id="1243027604378859286">කර්තෘ:</translation>
+<translation id="1246424317317450637">තද</translation>
<translation id="1250759482327835220">ඊළඟ වතà·à·€à·š ඉක්මනින් ගෙවීමට, ඔබගේ Google ගිණුමට ඔබගේ කà·à¶©à·Šà¶´à¶­, නම සහ බිල්පත් ලිපිනය සුරකින්න.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (සමමුහුර්තයි)</translation>
<translation id="1256368399071562588">&lt;p&gt;ඔබ වෙබ් අඩවියකට පිවිසීමට උත්සà·à·„ කරන විට එය විවෘත නොවේ නම්, පළමුව මෙම දà·à·‚à·à·€à·šà¶šà·Šà·‚ණ පියවර සමඟින් දà·à·‚ය නිරà·à¶šà¶»à¶«à¶º කිරීමට උත්සà·à·„ කරන්න:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">ඔබේ මුරපදය වෙනස් කරන්න</translation>
<translation id="1484290072879560759">නà·à·€à·Šà¶œà¶­ කිරීමේ ලිපිනය තà·à¶»à·à¶œà¶±à·Šà¶±</translation>
<translation id="1492194039220927094">ප්â€à¶»à¶­à·’පත්ති පුෂ්:</translation>
+<translation id="1495677929897281669">ආපසු පටිත්ත වෙත</translation>
<translation id="1501859676467574491">ඔබේ Google ගිණුමෙන් කà·à¶©à·Šà¶´à¶­à·Š පෙන්වන්න</translation>
<translation id="1507202001669085618">&lt;p&gt;ඔබ සබà·à¶³à·’ වීමට à·„à·à¶šà·’ වීමට පෙර පුරනය වීමට අවà·à·Šâ€à¶º වන Wi-Fi ද්වà·à¶»à¶ºà¶šà·Š භà·à·€à·’ත෠කරන්නේ නම් ඔබ මෙම දà·à·‚ය දකිනු ඇත.&lt;/p&gt;
&lt;p&gt;දà·à·‚ය නිරà·à¶šà¶»à¶«à¶º කිරීම සඳහà·, ඔබ විවෘත කිරීමට උත්සà·à·„ කරන පිටුවෙහි &lt;strong&gt;සබඳින්න&lt;/strong&gt; ක්ලික් කරන්න.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">මෙම පිටුව කියයි</translation>
<translation id="153384715582417236">දà·à¶±à¶§ එපමණයි</translation>
<translation id="1536390784834419204">පිටුව පරිවර්තනය කරන්න</translation>
+<translation id="1539840569003678498">à·€à·à¶»à·Šà¶­à·à·€ යවන ලදි:</translation>
<translation id="154408704832528245">බෙද෠හà·à¶»à·“මේ ලිපිනය තà·à¶»à·à¶œà¶±à·Šà¶±</translation>
<translation id="1549470594296187301">මෙම විà·à·šà·‚à·à¶‚ගය භà·à·€à·’ත කිරීමට ජà·à·€à·à·ƒà·Šà¶šà·Šâ€à¶»à·’ප්ට් සබල කළ යුතුය.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">පළමුව කෙටි දà·à¶»à¶º</translation>
<translation id="168693727862418163">මෙම ප්â€à¶»à¶­à·’පත්ති අගය එහි නිරූපණයට අනුව වලංගු කිරීමට අසමත් වූ බà·à·€à·’න් නොසලක෠හරිනු ලà·à¶¶à·š.</translation>
<translation id="168841957122794586">සේවà·à¶¯à·à¶ºà¶š සහතිකයේ දුර්වල ගුප්තලේඛන යතුරක් අඩංගුය!</translation>
+<translation id="1696290444144917273">අතථ්â€à¶º කà·à¶©à·Šà¶´à¶­à·Š විස්තර බලන්න</translation>
<translation id="1697532407822776718">ඔබ මුළුමනින් සුදà·à¶±à¶¸à·Šà¶º!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{මෙම සේවà·à¶¯à·à¶ºà¶šà¶ºà¶§ එය <ph name="DOMAIN" /> බව සනà·à¶® කළ නොහà·à¶šà·’ විය; එහි ආරක්ෂණ සහතිකය හෙට සිට විය à·„à·à¶šà·’ය. මෙය à·€à·à¶»à¶¯à·’ වින්â€à¶ºà·à·ƒ කිරීමක් හ෠ප්â€à¶»à·„à·à¶»à¶šà¶ºà¶šà·” ඔබගේ සබà·à¶³à·”මට බà·à¶°à· කිරීමක් නිස෠විය à·„à·à¶šà·’ය.}one{මෙම සේවà·à¶¯à·à¶ºà¶šà¶ºà¶§ එය <ph name="DOMAIN" /> බව සනà·à¶® කළ නොහà·à¶šà·’ විය; එහි ආරක්ෂණ සහතිකය අනà·à¶œà¶­à¶ºà·šà¶¯à·“ දින #ක් සිට විය à·„à·à¶šà·’ය. මෙය à·€à·à¶»à¶¯à·’ වින්â€à¶ºà·à·ƒ කිරීමක් හ෠ප්â€à¶»à·„à·à¶»à¶šà¶ºà¶šà·” ඔබගේ සබà·à¶³à·”මට බà·à¶°à· කිරීමක් නිස෠විය à·„à·à¶šà·’ය.}other{මෙම සේවà·à¶¯à·à¶ºà¶šà¶ºà¶§ එය <ph name="DOMAIN" />බව සනà·à¶® කළ නොහà·à¶šà·’ විය; එහි ආරක්ෂණ සහතිකය අනà·à¶œà¶­à¶ºà·šà¶¯à·“ දින #ක් සිට විය à·„à·à¶šà·’ය. මෙය à·€à·à¶»à¶¯à·’ වින්â€à¶ºà·à·ƒ කිරීමක් හ෠ප්â€à¶»à·„à·à¶»à¶šà¶ºà¶šà·” ඔබගේ සබà·à¶³à·”මට බà·à¶°à· කිරීමක් නිස෠විය à·„à·à¶šà·’ය.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> <ph name="VALUE" /> වෙත සකස෠නà·à¶­à·’ නිස෠නොසලක෠හරින ලදි.</translation>
<translation id="1712552549805331520"><ph name="URL" /> හට ස්ථිරව දත්ත ඔබේ ස්ථà·à¶±à·“ය පරිගණකයේ ගබඩ෠කිරීමට අවà·à·Šâ€à¶ºà¶ºà·’.</translation>
<translation id="1713628304598226412">බඳුන 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">තà·à¶´à·à¶½à·Š පෙට්ටිය 3</translation>
<translation id="1718029547804390981">ලේඛනය අනුසටහන් කිරීමට විà·à·à¶½ à·€à·à¶©à·’යි</translation>
<translation id="1721424275792716183">* ක්ෂේත්â€à¶»à¶º අවà·à·Šâ€à¶ºà¶ºà·’</translation>
+<translation id="1727613060316725209">සහතිකය වලංගුය</translation>
<translation id="1727741090716970331">වලංගු කà·à¶©à·Šà¶´à¶­à·Š අංකයක් එක් කරන්න</translation>
<translation id="1728677426644403582">ඔබ වෙබ් පිටුවක මූලà·à·à·Šâ€à¶»à¶º බලමින් සිටී</translation>
<translation id="173080396488393970">මෙම කà·à¶©à·Šà¶´à¶­à·Š වර්ගය සහà·à¶º නොදක්වයි</translation>
@@ -246,7 +253,6 @@
<ph name="SITE" /> සඳහ෠වන ඔබේ ඉල්ලීම ඉටු කිරීමෙන් වළක්වයි. වෙබ් අඩවියක් සඳහ෠ආරක්â€à·‚à·à·€ සහ වෙනත් ලක්â€à·‚ණ
වින්â€à¶ºà·à·ƒ කිරීමට වෙබ් අඩවිය ක්â€à¶»à·’ය෠කරවන්නන් විසින් මූලà·à¶»à¶¸à·Šà¶· ප්â€à¶»à¶­à·’පත්ති භà·à·€à·’ත කරනු ලà·à¶¶à·’ය à·„à·à¶š.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">කරුණà·à¶šà¶» ඔබගේ සමමුහුර්ත කරන රහස්පදය යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන්න.</translation>
<translation id="1787142507584202372">ඔබේ විවෘත කළ පටිති මෙහි දිස් වේ</translation>
<translation id="1791429645902722292">Google ස්මà·à¶§à·Š අගුල</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, බහුවිධ ක්â€à¶»à·’යà·à¶¸à·à¶»à·Šà¶œ ලබ෠ගත à·„à·à¶šà·’ය, ඒව෠හරහ෠චක්â€à¶»à·“ය කිරීමට Tab ඔබන්න</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">වෙළඳ දà·à¶±à·Šà·€à·“ම්</translation>
<translation id="1919367280705858090">නිà·à·Šà¶ à·’ත දà·à·‚ පණිවිඩයක් සමඟ උදවු ලබ෠ගන්න</translation>
<translation id="192020519938775529">{COUNT,plural, =0{කිසිවක් නà·à¶­}=1{1 අඩවියක්}one{අඩවි #ක්}other{අඩවි #ක්}}</translation>
+<translation id="1924727005275031552">නව</translation>
<translation id="1945968466830820669">ඔබට ඔබේ සංවිධà·à¶±à¶ºà·š ගිණුමට ප්â€à¶»à·€à·šà·à¶º අහිමි වීමට හ෠අනන්â€à¶ºà¶­à· සොරකමක් අත්විඳීමට සිදු විය à·„à·à¶šà·’ය. දà·à¶±à·Š ඔබේ මුරපදය වෙනස් කිරීම සඳහ෠Chromium නිර්දේ෠කරයි.</translation>
<translation id="1947454675006758438">ඉහළ දකුණ ස්ටේපල් කරන්න</translation>
<translation id="1958218078413065209">ඔබගේ ඉහළම ලකුණු <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">බඳුන 7</translation>
<translation id="204357726431741734">ඔබේ Google ගිණුම තුළ සුරà·à¶šà·“ ඇති මුරපද භà·à·€à·’ත කිරීමට පුරන්න</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> හි පිටු පරිවර්තන නොකෙරේ</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{මෙම පà·à¶½à¶±à¶º ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶š සහ තත්ත්වය සක්â€à¶»à·’යව ඇති විට, ඔබගේ මෑත බ්â€à¶»à·€à·”ස් කිරීමේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸ වඩà·à¶­à·Šà¶¸ සමà·à¶± වන්නේ කුමන විà·à·à¶½ පුද්ගලයන් සමූහයකටද, නà·à¶­à·„ොත් “කණ්ඩà·à¶ºà¶¸à¶šà¶§à¶¯â€ යන්න Chrome තීරණය කරයි. වෙළඳ ප්â€à¶»à¶ à·à¶»à¶šà¶ºà¶±à·Šà¶§ සමූහය සඳහ෠වෙළඳ දà·à¶±à·Šà·€à·“ම් තà·à¶»à· ගත à·„à·à¶šà·’ අතර ඔබගේ බ්â€à¶»à·€à·”ස් කිරීමේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à·Š ඔබගේ උපà·à¶‚ගයේ පුද්ගලිකව තබ෠ගà·à¶±à·š. ඔබගේ සමූහය සෑම දිනකම යà·à·€à¶­à·Šà¶šà·à¶½à·“න වේ.}=1{මෙම පà·à¶½à¶±à¶º ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶š සහ තත්ත්වය සක්â€à¶»à·’යව ඇති විට, ඔබගේ මෑත බ්â€à¶»à·€à·”ස් කිරීමේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸ වඩà·à¶­à·Šà¶¸ සමà·à¶± වන්නේ කුමන විà·à·à¶½ පුද්ගලයන් සමූහයකටද, නà·à¶­à·„ොත් “කණ්ඩà·à¶ºà¶¸à¶šà¶§à¶¯â€ යන්න Chrome තීරණය කරයි. වෙළඳ ප්â€à¶»à¶ à·à¶»à¶šà¶ºà¶±à·Šà¶§ සමූහය සඳහ෠වෙළඳ දà·à¶±à·Šà·€à·“ම් තà·à¶»à· ගත à·„à·à¶šà·’ අතර ඔබගේ බ්â€à¶»à·€à·”ස් කිරීමේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à·Š ඔබගේ උපà·à¶‚ගයේ පුද්ගලිකව තබ෠ගà·à¶±à·š. ඔබගේ සමූහය සෑම දිනකම යà·à·€à¶­à·Šà¶šà·à¶½à·“න වේ.}one{මෙම පà·à¶½à¶±à¶º ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶š සහ තත්ත්වය සක්â€à¶»à·’යව ඇති විට, ඔබගේ මෑත බ්â€à¶»à·€à·”ස් කිරීමේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸ වඩà·à¶­à·Šà¶¸ සමà·à¶± වන්නේ කුමන විà·à·à¶½ පුද්ගලයන් සමූහයකටද, නà·à¶­à·„ොත් “කණ්ඩà·à¶ºà¶¸à¶šà¶§à¶¯â€ යන්න Chrome තීරණය කරයි. වෙළඳ ප්â€à¶»à¶ à·à¶»à¶šà¶ºà¶±à·Šà¶§ සමූහය සඳහ෠වෙළඳ දà·à¶±à·Šà·€à·“ම් තà·à¶»à· ගත à·„à·à¶šà·’ අතර ඔබගේ බ්â€à¶»à·€à·”ස් කිරීමේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à·Š ඔබගේ උපà·à¶‚ගයේ පුද්ගලිකව තබ෠ගà·à¶±à·š. ඔබගේ සමූහය සෑම දින {NUM_DAYS}කම යà·à·€à¶­à·Šà¶šà·à¶½à·“න වේ.}other{මෙම පà·à¶½à¶±à¶º ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶š සහ තත්ත්වය සක්â€à¶»à·’යව ඇති විට, ඔබගේ මෑත බ්â€à¶»à·€à·”ස් කිරීමේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸ වඩà·à¶­à·Šà¶¸ සමà·à¶± වන්නේ කුමන විà·à·à¶½ පුද්ගලයන් සමූහයකටද, නà·à¶­à·„ොත් “කණ්ඩà·à¶ºà¶¸à¶šà¶§à¶¯â€ යන්න Chrome තීරණය කරයි. වෙළඳ ප්â€à¶»à¶ à·à¶»à¶šà¶ºà¶±à·Šà¶§ සමූහය සඳහ෠වෙළඳ දà·à¶±à·Šà·€à·“ම් තà·à¶»à· ගත à·„à·à¶šà·’ අතර ඔබගේ බ්â€à¶»à·€à·”ස් කිරීමේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à·Š ඔබගේ උපà·à¶‚ගයේ පුද්ගලිකව තබ෠ගà·à¶±à·š. ඔබගේ සමූහය සෑම දින {NUM_DAYS}කම යà·à·€à¶­à·Šà¶šà·à¶½à·“න වේ.}}</translation>
<translation id="2053553514270667976">ZIP කේතය</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{යà·à¶¢à¶±à· 1}one{යà·à¶¢à¶±à· #}other{යà·à¶¢à¶±à· #}}</translation>
<translation id="2071692954027939183">ඔබ à·ƒà·à¶¸à·à¶±à·Šâ€à¶ºà¶ºà·™à¶±à·Š ඒවà·à¶§ ඉඩ නොදෙන නිස෠දà·à¶±à·”ම්දීම් ස්වයංක්â€à¶»à·’යව අවහිර කරන ලදි</translation>
<translation id="2079545284768500474">පසුගමනය</translation>
<translation id="20817612488360358">පද්ධති ප්â€à¶»à·œà¶šà·Šà·ƒà·’ පසුතල සකස෠ඇත්තේ භà·à·€à·’ත෠කිරීමට වන නමුත් සවිස්තර ප්â€à¶»à·œà¶šà·Šà·ƒà·’ වින්â€à¶ºà·à·ƒà¶šà¶»à¶«à¶ºà¶¯ නිà·à·Šà¶ à·’තව දක්ව෠තිබේ.</translation>
<translation id="2082238445998314030">ප්â€à¶»à¶­à·’ඵල <ph name="TOTAL_RESULTS" /> කින් <ph name="RESULT_NUMBER" /></translation>
+<translation id="2085876078937250610">සුරකින්න…</translation>
<translation id="2088086323192747268">සමමුහුර්ත කිරීම කළමනà·à¶šà¶»à¶«à¶º කරන්න බොත්තම, Chrome à·ƒà·à¶šà·ƒà·“ම් තුළ ඔබ සමමුමුහුර්ත කරන්නේ කුමන තොරතුරුද යන්න කළමනà·à¶šà¶»à¶«à¶º කිරීමට Enter ඔබන්න</translation>
<translation id="2091887806945687916">හඬ</translation>
<translation id="2094505752054353250">වසම් නොගà·à¶½à¶´à·š</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> හට පරිà·à·“ලක නà·à¶¸à¶ºà¶šà·Š සහ මුරපදයක් අවà·à·Šâ€à¶ºà¶ºà·’.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, <ph name="EXPIRATION_DATE_ABBR" /> දින කල් ඉකුත් වේ</translation>
<translation id="2337852623177822836">à·ƒà·à¶šà·ƒà·“ම ඔබේ පරිපà·à¶½à¶š විසින් පà·à¶½à¶±à¶º කරයි</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> හට යුගල වීමට අවà·à·Šâ€à¶ºà¶ºà·’</translation>
<translation id="2344028582131185878">ස්වයංක්â€à¶»à·“ය බà·à¶œà·à¶±à·“ම්</translation>
<translation id="2346319942568447007">ඔබ පිටපත් කළ රූපය</translation>
<translation id="2354001756790975382">වෙනත් පිටු සලකුණු</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">ප්â€à¶»à·„à·à¶»à¶šà¶ºà¶±à·Šà¶§ ඔබ මෙම වෙබ් අඩවියේදී සොයන රූප දà·à¶š ඒව෠විකරණය කිරීමෙන් ඔබව රà·à·€à¶§à·“මට à·„à·à¶šà·’ වනු ඇත.</translation>
<translation id="2356070529366658676">විමසන්න</translation>
<translation id="2357481397660644965">ඔබගේ උපà·à¶‚ගය <ph name="DEVICE_MANAGER" /> විසින් කළමනà·à¶šà¶»à¶«à¶º කරන අතර ඔබගේ ගිණුම <ph name="ACCOUNT_MANAGER" /> විසින් කළමනà·à¶šà¶»à¶«à¶º කෙරේ.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{දිනකට වඩ෠අඩු කà·à¶½à¶ºà¶šà·’න්}=1{දිනකින්}one{දින {NUM_DAYS}කින්}other{දින {NUM_DAYS}කින්}}</translation>
<translation id="2359629602545592467">බහුවිධ</translation>
<translation id="2359808026110333948">කරගෙන යන්න</translation>
+<translation id="2359961752320758691">ඔබගේ අථත්â€à¶º කà·à¶©à·Šà¶´à¶­à·Š අංකය යොදනු ලà·à¶¶à·š.</translation>
<translation id="2367567093518048410">මට්ටම</translation>
<translation id="2372464001869762664">ඔබ තහවුරු කළ පසු, ඔබගේ Google ගිණුමෙන් කà·à¶©à·Šà¶´à¶­à·Š විස්තර මෙම අඩවිය සමඟ බෙද෠ගනු ඇත. ඔබගේ Plex ගිණුම් විස්තර තුළ CVC සොය෠ගන්න.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">මෙම නà·à·€à·Šà¶œà¶­ කිරීමේ ක්â€à¶»à¶¸à¶º ලබ෠ගත නොහà·à¶šà·’ය. වෙනත් ක්â€à¶»à¶¸à¶ºà¶šà·Š උත්සà·à·„ කරන්න.</translation>
<translation id="2396249848217231973">මà·à¶šà·“ම &amp;පසුගමනය කරන්න</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">පà·à¶»à¶«à·’</translation>
<translation id="2413528052993050574">මෙම සේවà·à¶¯à·à¶ºà¶šà¶ºà¶§ එය <ph name="DOMAIN" /> බව සනà·à¶® කිරීමට නොහà·à¶šà·’ විය; එහි ආරක්ෂණ සහතිකය අහà·à·ƒà·’ කර තිබිය à·„à·à¶šà·’ය. මෙය à·€à·à¶»à¶¯à·’ වින්â€à¶ºà·à·ƒ කිරීමක් හ෠ප්â€à¶»à·„à·à¶»à¶šà¶ºà¶šà·” ඔබගේ සබà·à¶³à·”මට බà·à¶°à· කිරීමක් නිස෠විය à·„à·à¶šà·’ය.</translation>
<translation id="2414886740292270097">අඳුරු</translation>
<translation id="2438874542388153331">දකුණට සිවු වරක් අනින්න</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">පහළ දකුණ ස්ටේපල් කරන්න</translation>
<translation id="2523886232349826891">මෙම උපà·à¶‚ගයෙහි පමණක් සුරà·à¶šà·’ණි</translation>
<translation id="2524461107774643265">à·€à·à¶©à·’දුර තොරතුරු එක් කරන්න</translation>
-<translation id="2526590354069164005">ඩෙස්ක්ටොප්</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{සහ තව 1 ක්}one{සහ තව #ක්}other{සහ තව #ක්}}</translation>
<translation id="2536110899380797252">ලිපිනය එක් කරන්න</translation>
<translation id="2539524384386349900">හඳුනà·à¶œà¶±à·Šà¶±</translation>
+<translation id="2541219929084442027">ඔබ ඔබගේ සියලු අප්â€à¶»à¶šà¶§ ටà·à¶¶ à·€à·à·ƒà·– පසු අප්â€à¶»à¶šà¶§ ටà·à¶¶à·€à¶½ ඔබ බà·à¶½à·– පිටු ඔබගේ බ්â€à¶»à·€à·”සරයෙහි ඉතිහà·à·ƒà¶º, කුකී ගබඩà·à·€ හ෠සෙවීම් ඉතිහà·à·ƒà¶º අවට නොරà·à¶³à·™à¶±à·” ඇත. ඔබ බà·à¶œà¶­à·Š ඕනෑම ගොනුවක් හ෠ඔබ à·ƒà·à¶¯à¶± පිටුසන් තබ෠ගනු ඇත.</translation>
<translation id="2544644783021658368">තනි ලේඛනය</translation>
<translation id="254947805923345898">ප්â€à¶»à¶­à·’පත්ති අගය වලංගු නොවේ.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> වලංගු නොවන ප්â€à¶»à¶­à·’චà·à¶»à¶ºà¶šà·Š එවීය.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Chrome à·„à·’ ඉහළම ආරක්ෂà·à·€ ලබ෠ගà·à¶±à·“මට, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />à·€à·à¶©à·’ දියුණු කළ ආරක්ෂà·à·€ ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶š කරන්න<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> සේවà·à¶¯à·à¶ºà¶šà¶ºà·š IP ලිපිනය සොය෠ගත නොහà·à¶šà·’ විය.</translation>
<translation id="2639739919103226564">තත්වය:</translation>
+<translation id="264810637653812429">ගà·à·…පෙන උපà·à¶‚ග හමු නොවිණි.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome à·ƒà·à¶šà·ƒà·“ම් තුළ ඔබගේ බ්â€à¶»à·€à·”ස් කිරීමේ ඉතිහà·à·ƒà¶º, කුකි, à·„à·à¶¹à·’ලිය සහ තවත් දේ හිස් කිරීමට, Tab ඔබ෠අනතුරුව Enter ඔබන්න</translation>
<translation id="2650446666397867134">ගොනුවට පිවිසුම ප්â€à¶»à¶­à·’ක්à·à·šà¶´ විය</translation>
@@ -492,6 +506,7 @@
<translation id="2799223571221894425">නà·à·€à¶­ දියත් කරන්න</translation>
<translation id="2803306138276472711">Google සුරක්ෂිත පිරික්සුම විසින් මෑතකදී <ph name="BEGIN_LINK" />අනිෂ්ට මෘදුකà·à¶‚ගයක්<ph name="END_LINK" /> <ph name="SITE" /> මත සොය෠ගà·à¶±à·’ණි. à·ƒà·à¶¸à·à¶±à·Šâ€à¶º යෙන් සුරක්ෂිත වෙබ් අඩවි ඇතà·à¶¸à·Š විට අනිෂ්ට මෘදුකà·à¶‚ගවලින් ආසà·à¶¯à¶±à¶º වී තිබිය à·„à·à¶š.</translation>
<translation id="2807052079800581569">රූපය Y ස්ථà·à¶±à¶º</translation>
+<translation id="2820957248982571256">ස්කෑන් කරමින්...</translation>
<translation id="2824775600643448204">ලිපිනය සහ සෙවීම් බà·à¶»à·Š එක</translation>
<translation id="2826760142808435982">සම්බන්ධතà·à·€à¶º සංකේතනය කර <ph name="CIPHER" /> භà·à·€à·’තයෙන් සත්â€à¶ºà·à¶´à¶±à¶º කර ඇති අතර කේත හුවමà·à¶»à·” ක්â€à¶»à¶¸à·€à·šà¶¯à¶º ලෙස <ph name="KX" /> භà·à·€à·’ත෠කරයි.</translation>
<translation id="2835170189407361413">පà·à¶»à·Šà¶¸à¶º හිස් කරන්න</translation>
@@ -499,6 +514,8 @@
<translation id="2850739647070081192">Invite (ලියුම් කවරය)</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="2859806420264540918">මෙම වෙබ් අඩවිය ආක්â€à¶»à¶¸à¶«à·’ක හ෠නොමඟ යවන දà·à¶±à·Šà·€à·“ම් පෙන්වයි.</translation>
+<translation id="287596039013813457">මිත්â€à¶»</translation>
+<translation id="2876489322757410363">බà·à·„ිර යෙදුමක් හරහ෠ගෙවීමට අප්â€à¶»à·ƒà·’ද්ධ ප්â€à¶»à¶šà·à¶»à¶º à·„à·à¶» යමින්. ඉදිරියට යන්නද?</translation>
<translation id="2878197950673342043">පà·à·ƒà·Šà¶§à¶» නà·à¶¸à·“ම</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">කවුළු තà·à¶¶à·“ම</translation>
@@ -548,7 +565,6 @@
<translation id="3060227939791841287">C9 (ලියුම් කවරය)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome à·ƒà·à¶šà·ƒà·“ම් තුළ ආරක්ෂක පරීක්ෂà·à·€ ධà·à·€à¶±à¶º කිරීමට Tab ඔබ෠අනතුරුව Enter ඔබන්න</translation>
<translation id="3061707000357573562">පà·à¶ à·Š සේවà·à·€</translation>
-<translation id="3064966200440839136">බà·à·„ිර යෙදුමක් හරහ෠ගෙවීමට අප්â€à¶»à¶šà¶§ ප්â€à¶»à¶šà·à¶»à¶º à·„à·à¶» යමින්. දිගටම කරගෙන යන්නද?</translation>
<translation id="306573536155379004">ක්â€à¶»à·“ඩà·à·€ ඇරඹිණි.</translation>
<translation id="3080254622891793721">චිත්â€à¶»à¶š</translation>
<translation id="3086579638707268289">වෙබය මත ඔබේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸ නිරීක්â€à·‚ණ කෙරේ</translation>
@@ -571,7 +587,6 @@
<translation id="315504272643575312">ඔබගේ ගිණුම <ph name="MANAGER" /> විසින් කළමනà·à¶šà¶»à¶«à¶º කෙරේ.</translation>
<translation id="3157931365184549694">ප්â€à¶»à¶­à·’à·ƒà·à¶°à¶±à¶º</translation>
<translation id="3162559335345991374">ඔබ භà·à·€à·’ත෠කරන Wi-Fi මගින් ඔබ එහි පුරනය වීමේ පිටුවට පිවිසීමට අවà·à·Šâ€à¶º විය à·„à·à¶š.</translation>
-<translation id="3167968892399408617">ඔබ ඔබගේ සියලු අප්â€à¶»à¶šà¶§ ටà·à¶¶ à·€à·à·ƒà·– පසු අප්â€à¶»à¶šà¶§ ටà·à¶¶à·€à¶½ ඔබ බà·à¶½à·– පිටු ඔබගේ බ්â€à¶»à·€à·”සරයෙහි ඉතිහà·à·ƒà¶º, කුකී ගබඩà·à·€, හ෠සෙවීම් ඉතිහà·à·ƒà¶º අවට නොරà·à¶³à·™à¶±à·” ඇත. ඔබ බà·à¶œà¶­à·Š ඕනෑම ගොනුවක් හ෠ඔබ à·ƒà·à¶¯à¶± පිටුසන් තබ෠ගනු ඇත.</translation>
<translation id="3169472444629675720">අනà·à·€à¶»à¶«à¶º</translation>
<translation id="3174168572213147020">දූපත</translation>
<translation id="3176929007561373547">ඔබේ ප්â€à¶»à·œà¶šà·Šà·ƒà·’ à·ƒà·à¶šà·ƒà·“ම් පරීක්ෂ෠කරන්න, නà·à¶­à·„ොත් ප්â€à¶»à·œà¶šà·Šà·ƒà·’ සේවà·à¶¯à·à¶ºà¶šà¶º ක්â€à¶»à·’ය෠කරන්නේදà·à¶ºà·’
@@ -597,10 +612,12 @@
<translation id="3229041911291329567">ඔබේ උපà·à¶‚ගය සහ බ්â€à¶»à·€à·”සරය පිළිබඳ අනුවà·à¶¯ තොරතුරු</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> සඳහ෠CVC ඇතුළු කරන්න</translation>
<translation id="3234666976984236645">මෙම අඩවිය මත à·€à·à¶¯à¶œà¶­à·Š අන්තර්ගත සෑම වඉටම හඳුනà·à¶œà¶±à·Šà¶±</translation>
+<translation id="3249845759089040423">විනà·à¶¯à¶¢à¶±à¶š</translation>
<translation id="3252266817569339921">ප්â€à¶»à¶‚à·</translation>
<translation id="3266793032086590337">අගය (ගà·à¶§à·”ම්කà·à¶»à·“)</translation>
<translation id="3268451620468152448">ටà·à¶¶ විවෘත කරන්න</translation>
<translation id="3270847123878663523">යළි ඇණවුම් කිරීම &amp;පසුගමනය කරන්න</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> හට සම්බන්ධ වීමට අවà·à·Šâ€à¶ºà¶ºà·’</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">ඔබගේ සංවිධà·à¶±à¶º, <ph name="ENROLLMENT_DOMAIN" />, à·ƒà·à¶šà·ƒà·“ම් හ෠ප්â€à¶»à¶­à·’පත්ති à·€à·à¶±à·’, යම් තොරතුරු පහත සඳහන් වෙබ් අඩවි වෙත යව෠ඇත.</translation>
<translation id="3282497668470633863">කà·à¶©à·Šà¶´à¶­à·™à·„à·’ නම එක් කරන්න</translation>
@@ -653,6 +670,7 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates සේවà·à¶¯à·à¶ºà¶š අච්චු URI-වලින් එකක් à·„à· à·€à·à¶©à·’ ගණනක් අවලංගු බà·à·€à·’න් භà·à·€à·’ත නොකෙරේ.</translation>
<translation id="3431636764301398940">මෙම උපà·à¶‚ගයට මෙම කà·à¶©à·Šà¶´à¶­ සුරකින්න</translation>
<translation id="3432601291244612633">පිටුව වසන්න</translation>
+<translation id="3435738964857648380">ආරක්ෂක</translation>
<translation id="3435896845095436175">සක්â€à¶»à·’ය කරන්න</translation>
<translation id="3438829137925142401">ඔබේ Google ගිණුම තුළ සුරà·à¶šà·’ මුරපද භà·à·€à·’ත කරන්න</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -695,7 +713,10 @@
<translation id="3584299510153766161">පහළට දෙවරක් අනින්න</translation>
<translation id="3586931643579894722">විස්තර සඟවන්න</translation>
<translation id="3587738293690942763">මà·à¶¯</translation>
+<translation id="3590643883886679995">ඔබ අප්â€à¶»à·ƒà·’ද්ධ ප්â€à¶»à¶šà·à¶»à¶ºà·™à¶±à·Š පිට වූ පසු පුරන දත්ත මෙම උපà·à¶‚ගය තුළ ගබඩ෠කරනු ඇත.</translation>
+<translation id="359126217934908072">මà·à·ƒà¶º/වසර:</translation>
<translation id="3592413004129370115">Italian (ලියුම් කවරය)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{ඔබට ඕනෑම වේලà·à·€à¶š ඔබගේ සමූහය යළි à·ƒà·à¶šà·ƒà·’ය à·„à·à¶šà·’ය. නව සමූහයකට එක් වීමට දිනක් පමණ ගත වේ.}=1{ඔබට ඕනෑම වේලà·à·€à¶š ඔබගේ සමූහය යළි à·ƒà·à¶šà·ƒà·’ය à·„à·à¶šà·’ය. නව සමූහයකට එක් වීමට දිනක් පමණ ගත වේ.}one{ඔබට ඕනෑම වේලà·à·€à¶š ඔබගේ සමූහය යළි à·ƒà·à¶šà·ƒà·’ය à·„à·à¶šà·’ය. නව සමූහයකට එක් වීමට දින {NUM_DAYS}ක් ගත වේ.}other{ඔබට ඕනෑම වේලà·à·€à¶š ඔබගේ සමූහය යළි à·ƒà·à¶šà·ƒà·’ය à·„à·à¶šà·’ය. නව සමූහයකට එක් වීමට දින {NUM_DAYS}ක් ගත වේ.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">ඔබේ පරිපà·à¶½à¶šà¶ºà· යෙදුම අවහිර කර ඇත</translation>
<translation id="3608932978122581043">පà·à·‚ණ දිà·à·à¶±à¶­à·’ය</translation>
@@ -704,13 +725,13 @@
<translation id="3615877443314183785">වලංගු කල් ඉකුත් වීමේ දිනයක් ඇතුළු කරන්න</translation>
<translation id="36224234498066874">බ්â€à¶»à·€à·”ස් කිරීමේ දත්ත හිස් කරන්න...</translation>
<translation id="362276910939193118">පූර්ණ ඉතිහà·à·ƒà¶º පෙන්වන්න</translation>
-<translation id="3625635938337243871">ඔබ අප්â€à¶»à·ƒà·’ද්ධ ප්â€à¶»à¶šà·à¶»à¶ºà·™à¶±à·Š පිට වූ පසු පුරනය-වීමේ දත්ත මෙම උපà·à¶‚ගය තුළ ගබඩ෠කරනු ඇත.</translation>
<translation id="3630155396527302611">එය දà·à¶±à¶§à¶¸à¶­à·Š ජà·à¶½à¶ºà¶§ ප්â€à¶»à·€à·šà· විය à·„à·à¶šà·’ ක්â€à¶»à¶¸à¶½à·šà¶›à¶ºà¶šà·Š ලෙස ලà·à¶ºà·’ස්තුගත කර තිබේ නම්, එය
ලà·à¶ºà·’ස්තුවෙන් ඉවත් කර නà·à·€à¶­ එක් කිරීමට උත්සà·à·„ කරන්න.</translation>
<translation id="3630699740441428070">මෙම උපà·à¶‚ගයේ පරිපà·à¶½à¶šà¶ºà·’න් ඔබගේ ජà·à¶½ සම්බන්ධතà·à·€ වින්â€à¶ºà·à·ƒ කර ඇති අතර, එමඟින් ඔබ පිවිසෙන වෙබ් අඩවි ඇතුළුව ඔබේ ජà·à¶½ තදබදය බà·à¶½à·“මට ඔවුන්ට ඉඩ දෙනු ඇත.</translation>
<translation id="3631244953324577188">ජෛවමිතික</translation>
<translation id="3633738897356909127">Chrome යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන්න බොත්තම, ඔබගේ Chrome à·ƒà·à¶šà·ƒà·“ම් වෙතින් Chrome යà·à·€à¶­à·Šà¶šà·à¶½à·“න කිරීමට Enter ඔබන්න</translation>
<translation id="3634530185120165534">බඳුන 5</translation>
+<translation id="3637662659967048211">Google ගිණුමට සුරකින්න</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">යෙදුම:</translation>
<translation id="3650584904733503804">වලංගුකරණය à·ƒà·à¶»à·Šà¶®à¶šà¶ºà·’</translation>
@@ -751,6 +772,7 @@
<translation id="3781428340399460090">උණුසුම් රà·à·ƒ</translation>
<translation id="3783418713923659662">මà·à·ƒà·Šà¶§à¶»à·Šà¶šà·à¶©à·Š</translation>
<translation id="3784372983762739446">බ්ලූටූත් උපà·à¶‚ග</translation>
+<translation id="3787675388804467730">අතථ්â€à¶º කà·à¶©à·Šà¶´à¶­à·Š අංකය</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> කල් ඉකුත් වේ</translation>
<translation id="3789155188480882154">ප්â€à¶»à¶¸à·à¶«à¶º 16</translation>
<translation id="3789841737615482174">ස්ථà·à¶´à¶±à¶º</translation>
@@ -770,6 +792,7 @@
<translation id="3841184659773414994">ගොනු හසුරුවන්නන්</translation>
<translation id="385051799172605136">ආපසු</translation>
<translation id="3858027520442213535">දිනය සහ වේලà·à·€ යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන්න</translation>
+<translation id="3881478300875776315">පේළි අඩුවෙන් පෙන්වන්න</translation>
<translation id="3884278016824448484">උපà·à¶‚ගය හඳුන෠ගà·à¶±à·“ම ප්â€à¶»à¶­à·’විරුද්ධයි</translation>
<translation id="3885155851504623709">කà·à¶»à¶½à¶º</translation>
<translation id="388632593194507180">අධීක්ෂණය අනà·à·€à¶»à¶«à¶º විය</translation>
@@ -795,6 +818,7 @@
<translation id="397105322502079400">ගණනය කරමින්...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> අවහිර කර ඇත</translation>
<translation id="3973357910713125165">Chrome ආරක්ෂක පරීක්ෂà·à·€ ධà·à·€à¶±à¶º කරන්න බොත්තම, Chrome à·ƒà·à¶šà·ƒà·“ම් තුළ ආරක්ෂක පරීක්ෂà·à·€ ධà·à·€à¶±à¶º කිරීමට Enter ඔබන්න</translation>
+<translation id="3986705137476756801">දà·à¶±à¶§ සජීවී සිරස්තල ක්â€à¶»à·’ය෠විරහිත කරන්න</translation>
<translation id="3987405730340719549">මෙම වෙබ් අඩවිය ව්â€à¶ºà·à¶¢ හ෠වංචනික විය à·„à·à¶šà·’ බව Chrome තීරණ කර ඇත.
මෙය à·€à·à¶»à¶¯à·“මකින් පෙන්නුම් කෙරෙන බව ඔබ විà·à·Šà·€à·à·ƒ කරන්නේ නම් https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals වෙත පà·à¶¸à·’ණෙන්න.</translation>
@@ -888,13 +912,14 @@
<translation id="4275830172053184480">ඔබේ උපà·à¶‚ගය නà·à·€à¶­ අරඹන්න</translation>
<translation id="4277028893293644418">මුරපදය යළි සකසන්න</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{මෙම කà·à¶©à·Šà¶´à¶­ ඔබගේ Google ගිණුම තුළ සුරà·à¶šà·“ ඇත}one{මෙම කà·à¶©à·Šà¶´à¶­à·Š ඔබගේ Google ගිණුම තුළ සුරà·à¶šà·“ ඇත}other{මෙම කà·à¶©à·Šà¶´à¶­à·Š ඔබගේ Google ගිණුම තුළ සුරà·à¶šà·“ ඇත}}</translation>
+<translation id="4287885627794386150">අත්හද෠බà·à¶½à·“ම සඳහ෠සුදුසු නමුත් සක්â€à¶»à·’ය නà·à¶­</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> පිටුව සඳහ෠සිඟිති රුව</translation>
<translation id="42981349822642051">දිගහරින්න</translation>
<translation id="4300675098767811073">දකුණට බොහ෠වරක් අනින්න</translation>
<translation id="4302514097724775343">à·€à·à¶¯à¶±à¶º කිරීමට ඩයින෠තට්ටු කරන්න</translation>
<translation id="4302965934281694568">Chou3 (ලියුම් කවරය)</translation>
<translation id="4305666528087210886">ඔබගේ ගොනුවට පිවිසීමට නොහà·à¶šà·’ විය.</translation>
-<translation id="4305817255990598646">ස්විචය</translation>
+<translation id="4306529830550717874">ලිපිනය සුරකින්නද?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">අවහිර කරන්න (පෙරනිමි)</translation>
<translation id="4314815835985389558">සමමුහුර්තය කළමනà·à¶šà¶»à¶«à¶º</translation>
@@ -921,6 +946,7 @@
<translation id="4377125064752653719">ඔබ <ph name="DOMAIN" /> වෙත ළඟà·à·€à·“මට උත්සà·à·„ දරන ලදි, නමුත් එම සර්වරය විසින් ඉදිරිපත් කළ සහතිකය එය නිකුත් කරන්න෠විසින් අවලංගු කර ඇත. මෙයින් අදහස් වන්නේ සර්වරය ඉදිරිපත් කළ ආරක්ෂිත à·ƒà·à¶šà·Šà·‚à·’ කිසිසේත් විà·à·Šà·€à·à·ƒ නොකළ යුතු බවයි. ඔබ සම්බන්ධ වී සිටින්නේ වෙබ් ප්â€à¶»à·„à·à¶»à¶šà¶ºà·™à¶šà·” සමඟ වීමට ඉඩ ඇත.</translation>
<translation id="4378154925671717803">දුරකථනය</translation>
<translation id="4390472908992056574">ගà·à¶§à·Šà¶§</translation>
+<translation id="4406883609789734330">සජීවී සිරස්තලය</translation>
<translation id="4406896451731180161">සෙවීම් ප්â€à¶»à¶­à·’ඵල</translation>
<translation id="4408413947728134509">කුකීස් <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">ඔබ මේ දà·à¶±à·Š වංචනික අඩවියක ඔබේ මුරපදය ඇතුළු කළà·. Chrome <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />, සහ ඔබ මෙම මුරපදය භà·à·€à·’ත කරන වෙනත් වෙබ් අඩවිවලට ගොස් එය දà·à¶±à·Š වෙනස් කිරීම නිර්දේ෠කරයි.</translation>
@@ -933,7 +959,6 @@
<translation id="4435702339979719576">තà·à¶´à·à¶½à·Š පත)</translation>
<translation id="443673843213245140">ප්â€à¶»à·œà¶šà·Šà·ƒà·’යක භà·à·€à·’තය අබල කර ඇති නමුත් ප්â€à¶»à¶šà·à·à·’ත ප්â€à¶»à·œà¶šà·Šà·ƒà·’ වින්â€à¶ºà·à·ƒà¶šà¶»à¶«à¶ºà¶šà·Š නිà·à·Šà¶ à¶º කර ඇත.</translation>
<translation id="4464826014807964867">ඔබේ සංවිධà·à¶±à¶º වෙතින් වන තොරතුරු සහිත වෙබ් අඩවි</translation>
-<translation id="4466881336512663640">පà·à¶»à¶¸à¶ºà·š වෙනස්කම් අහිමි වෙයි. ඔබට ඉදිරියට යà·à¶ºà·”තු බව ඔබට තහවුරුද?</translation>
<translation id="4476953670630786061">මෙම පà·à¶»à¶¸à¶º ආරක්ෂිත නොවේ. ස්වයං පිරවුම ක්â€à¶»à·’යà·à·€à·’රහිත කර ඇත.</translation>
<translation id="4477350412780666475">ඊළඟ ඛණ්ඩය</translation>
<translation id="4482953324121162758">මෙම වෙබ් අඩවිය පරිවර්තන නොකෙරේ.</translation>
@@ -967,6 +992,7 @@
<translation id="4594403342090139922">මà·à¶šà·“ම &amp;පසුගමනය කරන්න</translation>
<translation id="4597348597567598915">ප්â€à¶»à¶¸à·à¶«à¶º 8</translation>
<translation id="4600854749408232102">C6/C5 (ලියුම් කවරය)</translation>
+<translation id="4606870351894164739">බලපෑමක් ඇති කරන</translation>
<translation id="4628948037717959914">ඡà·à¶ºà·à¶»à·–පය</translation>
<translation id="4631649115723685955">මුදල් ආපසු දීම සබà·à¶³à·’ කරන ලදි</translation>
<translation id="4636930964841734540">තතු</translation>
@@ -986,6 +1012,7 @@
<translation id="4691835149146451662">Architecture-A (ලියුම් කවරය)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">පà·à¶­à·Šà¶­</translation>
+<translation id="4702656508969495934">සජීවී සිරස්තල දෘà·à·Šâ€à¶ºà¶¸à·à¶± වේ, නà·à¶·à·’ගත කිරීමට කවුළු මà·à¶»à·” කරන්න෠භà·à·€à·’ත කරන්න</translation>
<translation id="4708268264240856090">ඔබේ සබà·à¶³à·”මට බà·à¶°à· ඇති විය</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows ජà·à¶½ දà·à·‚හරණ ධà·à·€à¶±à¶º කරමින්<ph name="END_LINK" /></translation>
@@ -999,6 +1026,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> සෙවුම් යà·à¶¢à¶±à·à·€</translation>
<translation id="4742407542027196863">මුරපද කළමනà·à¶šà¶»à¶«à¶º කරන්න…</translation>
<translation id="4744603770635761495">විධà·à¶±à¶œà¶­à¶šà·…à·„à·à¶šà·’ මඟ</translation>
+<translation id="4749011317274908093">ඔබ අප්â€à¶»à·ƒà·’ද්ධව ඇත</translation>
<translation id="4750917950439032686">ඔබගේ තොරතුරු (උදà·à·„රණයක් ලෙස, මුරපද හ෠ණය කà·à¶©à·Šà¶´à¶­à·Š අංක) මෙම අඩවිය වෙත යවන විට රහසිගත වේ.</translation>
<translation id="4756388243121344051">&amp;ඉතිහà·à·ƒà¶º</translation>
<translation id="4758311279753947758">සම්බන්ධත෠තතු එක් කරන්න</translation>
@@ -1028,6 +1056,8 @@
<translation id="4813512666221746211">ජà·à¶½ දà·à·‚යකි</translation>
<translation id="4816492930507672669">පිටුව වෙත සවි කරන්න</translation>
<translation id="4819347708020428563">පෙරනිමි දසුන තුළ අනුසටහන් සංස්කරණය කරන්නද?</translation>
+<translation id="4825507807291741242">à·à¶šà·Šà¶­à·’සම්පන්න</translation>
+<translation id="4838327282952368871">සිහිනමය</translation>
<translation id="484462545196658690">ස්වයං</translation>
<translation id="4850886885716139402">දසුන</translation>
<translation id="485316830061041779">ජර්මà·à¶±à·”</translation>
@@ -1164,6 +1194,7 @@
<translation id="5314967030527622926">පුස්තික෠සà·à¶¯à¶±à·Šà¶±à·</translation>
<translation id="5316812925700871227">දක්ෂිණà·à·€à¶»à·Šà¶­à·€ කරකවන්න</translation>
<translation id="5317780077021120954">සුරකින්න</translation>
+<translation id="5321288445143113935">විà·à·à¶½ කරන ලදි</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" />න් <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">සම්බන්ධත෠තතු තà·à¶»à·à¶œà¶±à·Šà¶±</translation>
<translation id="5327248766486351172">නම</translation>
@@ -1171,11 +1202,13 @@
<translation id="5332219387342487447">නà·à·€à·Šà¶œà¶­ කිරීමේ ක්â€à¶»à¶¸à¶º</translation>
<translation id="5333022057423422993">කඩ කිරීමකදී ඔබ භà·à·€à·’ත කළ මුරපදය Chrome හට හමු විය. ඔබගේ ගිණුම් සුරක්ෂිත කිරීමට, ඔබගේ සුරකින ලද මුරපද පරීක්ෂ෠කිරීමට අපි නිර්දේ෠කරමු.</translation>
<translation id="5334013548165032829">විස්තරà·à¶­à·Šà¶¸à¶š පද්ධති ලොග</translation>
+<translation id="5334145288572353250">ලිපිනය සුරකින්නද?</translation>
<translation id="5340250774223869109">යෙදුම අවහිර කර ඇත</translation>
<translation id="534295439873310000">NFC උපà·à¶‚ග</translation>
<translation id="5344579389779391559">මෙම පිටුව ඔබේ මුදල මà·à¶»à·” කිරීමට උත්සà·à·„ කළ à·„à·à¶š</translation>
<translation id="5355557959165512791">ඔබට මේ දà·à¶±à·Š <ph name="SITE" /> වෙත එහි සහතිකය අහà·à·ƒà·’ කර ඇති බà·à·€à·’න් පිවිසිය නොහà·à¶š. ජà·à¶½ දà·à·‚ සහ ප්â€à¶»à·„à·à¶» à·ƒà·à¶¸à·à¶±à·Šâ€à¶ºà¶ºà·™à¶±à·Š තà·à·€à¶šà·à¶½à·’කය, එනිස෠මෙම පිටුව සමහර විට පසුව à·€à·à¶© කරනු ඇත.</translation>
<translation id="536296301121032821">ප්â€à¶»à¶­à·’පත්ති à·ƒà·à¶šà·ƒà·”ම් ගබඩ෠කිරීමට අසමත් විය</translation>
+<translation id="5363309033720083897">ඔබගේ පරිපà·à¶½à¶š විසින් ඉඩ දෙන අනුක්â€à¶»à¶¸à·’ක තොට</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="5386426401304769735">සහතික දà·à¶¸à¶ºà·™à·„à·’ SHA-1 භà·à·€à·’තයෙන් අත්සන් කළ සහතිකයක් අඩංගුය.</translation>
@@ -1184,6 +1217,7 @@
<translation id="5398772614898833570">වෙළඳ දà·à¶±à·Šà·€à·“ම් අවහිරයි</translation>
<translation id="5400836586163650660">අළු</translation>
<translation id="540969355065856584">මෙම සේවà·à¶¯à·à¶ºà¶šà¶ºà¶§ එය <ph name="DOMAIN" /> බව සනà·à¶® කිරීමට නොහà·à¶šà·’ විය; එහි ආරක්ෂණ සහතිකය මෙම අවස්ථවේ වලංගු නà·à¶­. මෙය à·€à·à¶»à¶¯à·’ වින්â€à¶ºà·à·ƒ කිරීමක් හ෠ප්â€à¶»à·„à·à¶»à¶šà¶ºà¶šà·” ඔබගේ සබà·à¶³à·”මට බà·à¶°à· කිරීමක් නිස෠විය à·„à·à¶šà·’ය.</translation>
+<translation id="541143247543991491">ක්ලවුඩ් (පද්ධතිය පුරà·)</translation>
<translation id="541416427766103491">අට්ටිය 4</translation>
<translation id="5421136146218899937">පිරික්සුම් දත්ත හිස් කරන්න...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> හට ඔබට දà·à¶±à·”ම්දීම් එවීමට අවà·à·Šâ€à¶ºà¶ºà·’</translation>
@@ -1197,6 +1231,7 @@
<translation id="5455374756549232013">දූà·à·’ත ප්â€à¶»à¶­à·’පත්ති කà·à¶½ මුද්â€à¶»à·</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" />}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="5463625433003343978">උපà·à¶‚ග සොයමින්...</translation>
<translation id="5469868506864199649">ඉතà·à¶½à·’</translation>
<translation id="5470861586879999274">සංස්කරණය &amp;යළි කරන්න</translation>
<translation id="5478437291406423475">B6/C4 (ලියුම් කවරය)</translation>
@@ -1246,7 +1281,6 @@
<translation id="5624120631404540903">මුරපද පà·à¶½à¶±à¶º</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="563324245173044180">රà·à·€à¶§à·’ලිකà·à¶»à·“ අන්තර්ගතය අවහිරයි.</translation>
<translation id="5644090287519800334">පà·à¶­à·Šà¶­ 1 රූප X à·€à·à¶© මුරය</translation>
@@ -1285,12 +1319,12 @@
<translation id="5785756445106461925">තවද, මෙම පිටුවේ ආරක්ෂිත නොවන වෙනත් සම්පත් ඇත. එම සම්පත් හුවමà·à¶»à·”à·€ අතරතුර â€à¶…නෙක් අයටත් බà·à¶½à·’ය à·„à·à¶šà·’ අතර, පිටුවේ පෙනුම වෙනස් වන අයුරින් වෙනස් කිරීමට වෙබ් ප්â€à¶»à·„à·à¶»à¶šà¶ºà·™à¶šà·”ට à·„à·à¶šà·’ය.</translation>
<translation id="5786044859038896871">ඔබට ඔබේ කà·à¶©à·Šà¶´à¶­à·Š තොරතුරු පිරවීමට අවà·à·Šâ€à¶ºà¶¯?</translation>
<translation id="578633867165174378">කඩ කිරීමකදී ඔබ භà·à·€à·’ත කළ මුරපදය Chrome හට හමු විය. මෙම මුරපදය දà·à¶±à·Š වෙනස් කිරීමට අපි නිර්දේ෠කරමු.</translation>
-<translation id="5798290721819630480">වෙනස් කිරීම් ඉවත ලන්නද?</translation>
<translation id="5803412860119678065">ඔබට ඔබේ <ph name="CARD_DETAIL" /> පිරවීමට අවà·à·Šâ€à¶ºà¶¯?</translation>
<translation id="5804241973901381774">අවසර</translation>
<translation id="5804427196348435412">NFC උපà·à¶‚ග භà·à·€à·’ත කරන්න</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> වෙත ඔබේ සබà·à¶³à·”ම සංකේතනය කර ඇත්තේ පà·à¶»à¶«à·’ cipher suite භà·à·€à·’තයෙනි.</translation>
<translation id="5813119285467412249">එක් කිරීම &amp;යළි කරන්න</translation>
+<translation id="5817918615728894473">යුගල කරන්න</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ඔබ ගෙවන විට මෙම කà·à¶©à·Šà¶´à¶­à·™à¶±à·Š අය කරනු ලà·à¶¶à·š, නමුත් මෙම වෙබ් අඩවිය සමඟ මෙහි à·ƒà·à¶¶à·‘ අංකය බෙද෠නොගà·à¶±à·š. අමතර ආරක්â€à·‚à·à·€ සඳහනà·, තà·à·€à¶šà·à¶½à·’ක CVC එකක් ජනන කෙරේ.}one{ඔබ ගෙවන විට ඔබ තà·à¶»à· ගන්න෠කà·à¶©à·Šà¶´à¶­à·™à¶±à·Š අය කරනු ලà·à¶¶à·š, නමුත් මෙම වෙබ් අඩවිය සමඟ මෙහි à·ƒà·à¶¶à·‘ අංකය බෙද෠නොගà·à¶±à·š. අමතර ආරක්â€à·‚à·à·€ සඳහනà·, තà·à·€à¶šà·à¶½à·’ක CVC එකක් ජනන කෙරේ.}other{ඔබ ගෙවන විට ඔබ තà·à¶»à· ගන්න෠කà·à¶©à·Šà¶´à¶­à·™à¶±à·Š අය කරනු ලà·à¶¶à·š, නමුත් මෙම වෙබ් අඩවිය සමඟ මෙහි à·ƒà·à¶¶à·‘ අංකය බෙද෠නොගà·à¶±à·š. අමතර ආරක්â€à·‚à·à·€ සඳහනà·, තà·à·€à¶šà·à¶½à·’ක CVC එකක් ජනන කෙරේ.}}</translation>
<translation id="5826507051599432481">පොදු නම (CN)</translation>
<translation id="5838278095973806738">ප්â€à¶»à·„à·à¶»à¶šà¶ºà·’න් විසින් සොරකම් කළ à·„à·à¶šà·’ නිස෠ඔබ මෙම අඩවිය මත සංවේදී තොරතුරු ඇතුළු නොකළ යුතුය (උදà·à·„රණයක් ලෙස, මුරපද හ෠ණය කà·à¶©à·Šà¶´à¶­à·Š).</translation>
@@ -1298,6 +1332,7 @@
<translation id="5855253129151731373">මෙම වෙබ් අඩවියේ ධà·à¶»à¶š නම <ph name="LOOKALIKE_DOMAIN" /> ට සමà·à¶± බව පෙනේ. ප්â€à¶»à·„à·à¶»à¶šà¶ºà·’න් සමහර විට වසම් නà·à¶¸à¶ºà¶§ කුඩà·, බà·à¶½à·“මට අපහසු වෙනස්කම් කිරීමෙන් වෙබ් අඩවි අනුකà·à¶» කරති.
මෙය à·€à·à¶»à¶¯à·“මකින් පෙන්නුම් කෙරෙන බව ඔබ විà·à·Šà·€à·à·ƒ කරන්නේ නම් https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals වෙත පà·à¶¸à·’ණෙන්න.</translation>
+<translation id="5860033963881614850">අක්â€à¶»à·“ය</translation>
<translation id="5862579898803147654">අට්ටිය 8</translation>
<translation id="5863847714970149516">ඉදිරියෙන් ඇති පිටුව ඔබගෙන් මුදල් අය කිරීමට උත්සà·à·„ කරනු ඇත</translation>
<translation id="5866257070973731571">දුරකථන අංකය එක් කරන්න</translation>
@@ -1314,6 +1349,7 @@
<translation id="5913377024445952699">තිර ග්â€à¶»à·„ණය විරà·à¶¸ කරන ලදි</translation>
<translation id="59174027418879706">සබලයි</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1ක් භà·à·€à·’තයේ ඇත}one{#ක් භà·à·€à·’තයේ ඇත}other{#ක් භà·à·€à·’තයේ ඇත}}</translation>
<translation id="5921185718311485855">ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶šà¶ºà·’</translation>
<translation id="5921639886840618607">කà·à¶©à·Šà¶´à¶­ Google ගිණුමට සුරකින්නද?</translation>
<translation id="5922853866070715753">මුළුමනින්ම පà·à·„à·š නිමයි</translation>
@@ -1333,6 +1369,7 @@
<translation id="5989320800837274978">ස්ථිර ප්â€à¶»à·œà¶šà·Šà·ƒà·’ සේවà·à¶¯à·à¶ºà¶š à·„à· .pac ස්ක්â€à¶»à·’ප්ට ලිපින සඳහන් කර නොමà·à¶­.</translation>
<translation id="5992691462791905444">ඉංජිනේරු විද්â€à¶ºà· Z-නà·à¶¸à·“ම</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' සඳහ෠ප්â€à¶»à¶­à·’ඵල <ph name="RESULT_COUNT" />ක්</translation>
+<translation id="6006484371116297560">පà·à¶»à¶«à·’</translation>
<translation id="6008122969617370890">N-සිට-1 පිළිවෙළ</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">ඔබේ මුරපද පරීක්â€à·‚෠කරන්න</translation>
@@ -1354,6 +1391,7 @@
<translation id="6045164183059402045">පà·à¶±à·€à·“ම් අච්චුව</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="6049004884579590341">පූර්ණ තිරයෙන් පිටවීමට |<ph name="ACCELERATOR" />| ඔබà·à¶œà·™à¶± සිටින්න</translation>
<translation id="6049488691372270142">පිටු බෙද෠හà·à¶»à·“ම</translation>
<translation id="6051221802930200923">වෙබ් අඩවිය සහතික ඇමිණීම් භà·à·€à·’ත෠කරන නිස෠ඔබට මේ දà·à¶±à·Š <ph name="SITE" /> වෙත පිවිසිය නොහà·à¶š. ජà·à¶½ දà·à·‚ සහ ප්â€à¶»à·„à·à¶» à·ƒà·à¶¸à·à¶±à·Šâ€à¶ºà¶ºà·™à¶±à·Š තà·à·€à¶šà·à¶½à·’කය, එනිස෠මෙම පිටුව සමහර විට පසුව à·€à·à¶© කරනු ඇත.</translation>
<translation id="6051898664905071243">පිටු ගණන:</translation>
@@ -1370,6 +1408,7 @@
<translation id="610911394827799129">ඔබේ Google ගිණුමට <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> හිදී බ්â€à¶»à·€à·”ස් කිරීමේ ඉතිහà·à·ƒà¶ºà·š වෙනත් ආකà·à¶»à¶ºà¶±à·Š තිබිය à·„à·à¶š</translation>
<translation id="6116338172782435947">පසුරු පුවරුවට පිටපත් කළ පෙළ සහ රූප බලන්න</translation>
<translation id="6120179357481664955">ඔබේ UPI à·„à·à¶³à·”නුම මතකද?</translation>
+<translation id="6123290840358279103">අථත්â€à¶º කà·à¶©à·Šà¶´à¶­ බලන්න</translation>
<translation id="6124432979022149706">Chrome ව්â€à¶ºà·€à·ƒà·à¶º සම්බන්ධක</translation>
<translation id="6146055958333702838">කිනම් හ෠කේබල පරීක්ෂ෠කර කිනම් හ෠රවුටර, මොඩම හ෠ඔබ භà·à·€à·’ත කරමින් සිටිය à·„à·à¶šà·’
වෙනත් ජà·à¶½ උපà·à¶‚ග යළි පණ ගන්වන්න.</translation>
@@ -1406,6 +1445,7 @@
<translation id="6289939620939689042">පිටුවේ වර්ණය</translation>
<translation id="6290238015253830360">ඔබේ යà·à¶¢à·’ත ලිපි මෙහි දිස්වනු ඇත</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome à·„à·’ Google සහà·à¶ºà¶š නà·à·€à¶­à·™à¶ºà·’</translation>
<translation id="6305205051461490394"><ph name="URL" /> වෙත ළඟ෠විය නොහà·à¶šà·’ය.</translation>
<translation id="6312113039770857350">වෙබ් පිටුව ලබ෠ගත නොහà·à¶šà·’ය</translation>
@@ -1431,6 +1471,7 @@
<translation id="6390200185239044127">භà·à¶œà¶ºà¶§ Z-නà·à¶¸à·“ම</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">පරිපà·à¶½à¶š ප්â€à¶»à¶­à·’පත්තිය මගින් මෙම ස්ථà·à¶±à¶ºà¶§ <ph name="ORIGIN_NAME" /> වෙතින් ඇලවීම අවහිර කර ඇත</translation>
+<translation id="6398765197997659313">සම්පුර්ණ තිරයෙන් ඉවත් වන්න</translation>
<translation id="6401136357288658127">මෙම ප්â€à¶»à¶­à·’පත්තිය අත්හරින ලදි. ඒ වෙනුවට ඔබ <ph name="NEW_POLICY" /> ප්â€à¶»à¶­à·’පත්තිය භà·à·€à·’ත කළ යුතු ය.</translation>
<translation id="6404511346730675251">පිටු සලකුණ සංස්කරණය කරන්න</translation>
<translation id="6406765186087300643">C0 (ලියුම් කවරය)</translation>
@@ -1443,7 +1484,6 @@
<translation id="6428450836711225518">ඔබේ දුරකථන අංකය සත්â€à¶ºà·à¶´à¶± කරන්න</translation>
<translation id="6433490469411711332">සම්බන්ධත෠තොරතුරු සංස්කරණය</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> සබà·à¶³à·“ම ප්â€à¶»à¶­à·’ක්ෂේප කරන ලදී.</translation>
-<translation id="6434309073475700221">ඉවත ලන්න</translation>
<translation id="6440503408713884761">නොතà·à¶šà·–</translation>
<translation id="6443406338865242315">ඔබ ස්ථà·à¶´à¶± කර ඇති දිගු සහ පේනු මෘදුකà·à¶‚ග</translation>
<translation id="6446163441502663861">Kahu (ලියුම් කවරය)</translation>
@@ -1486,6 +1526,7 @@
<translation id="6624427990725312378">සම්බන්ධත෠තතු</translation>
<translation id="6626291197371920147">වලංගු කà·à¶©à·Šà¶´à¶­à·Š අංකය එක් කරන්න</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> සෙවීම</translation>
+<translation id="6630043285902923878">USB උපà·à¶‚ග සොයමින්...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">මකන්න</translation>
@@ -1501,6 +1542,7 @@
<translation id="6671697161687535275">Chromium වෙතින් පà·à¶»à¶¸ යà·à¶¢à¶±à· ඉවත් කරන්නද?</translation>
<translation id="6685834062052613830">වරන්න සහ පිහිටුවීම සම්පූර්ණ කරන්න</translation>
<translation id="6687335167692595844">අකුරු ප්â€à¶»à¶¸à·à¶«à¶º ඉල්ලුවà·</translation>
+<translation id="6688743156324860098">යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන්න…</translation>
<translation id="6689249931105087298">කළු ලක්â€à·‚à·Šâ€à¶º සම්පීඩනයට අදà·à·…</translation>
<translation id="6689271823431384964">ඔබ පුරනය වී සිටින බà·à·€à·’න් Chrome ඔබට ඔබේ කà·à¶©à·Šà¶´à¶­à·Š ඔබේ Google ගිණුමට සුරà·à¶šà·“ම පිරිනමයි. ඔබට මෙම à·„à·à·ƒà·’රීම à·ƒà·à¶šà·ƒà·“ම් තුළ වෙනස් කළ à·„à·à¶š. කà·à¶©à·Šà¶´à¶­à·Š හිමිකරුගේ නම ඔබේ ගිණුමෙන් ලà·à¶¶à·š.</translation>
<translation id="6698381487523150993">නිර්මිත:</translation>
@@ -1516,6 +1558,7 @@
<translation id="6744009308914054259">සම්බන්ධතà·à·€à¶ºà¶šà·Š සඳහ෠රà·à¶³à·“ සිටින විට, ඔබට නොබà·à¶³à·’ ලිපි කියවීමට බà·à¶œà·à¶±à·“ම් වෙත යà·à¶¸à¶§ à·„à·à¶šà·’ය.</translation>
<translation id="6753269504797312559">ප්â€à¶»à¶­à·’පත්ති අගය</translation>
<translation id="6757797048963528358">ඔබගේ උපà·à¶‚ගය නින්දට ගියේය.</translation>
+<translation id="6767985426384634228">ලිපිනය යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන්නද?</translation>
<translation id="6768213884286397650">Hagaki (තà·à¶´à·à¶½à·Š පත)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ජම්බූල</translation>
@@ -1538,6 +1581,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">මෙය කියවීමට පහසු කිරීමට Chrome මෙම පිටුව සරල කළà·. Chrome අනà·à¶»à¶šà·Šâ€à·‚ිත සම්බන්ධතà·à·€à¶šà·Š ඔස්සේ මූලික පිටුව ලබ෠ගත්තà·.</translation>
<translation id="6891596781022320156">ප්â€à¶»à¶­à·’පත්ති මට්ටම උපකà·à¶» නොකරයි.</translation>
+<translation id="6895143722905299846">අතථ්â€à¶º අංකය:</translation>
<translation id="6895330447102777224">ඔබේ කà·à¶©à·Šà¶´à¶­ තහවුරු කර ඇත</translation>
<translation id="6897140037006041989">භà·à·€à·’ත නියà·à¶¢à·’ත</translation>
<translation id="6898699227549475383">සංවිධà·à¶±à¶º (O)</translation>
@@ -1573,10 +1617,10 @@
<translation id="7004583254764674281">කà·à¶©à·Šà¶´à¶­à·Š වඩ෠වේගයෙන් තහවුරු කිරීමට Windows Hello භà·à·€à·’ත කරන්න</translation>
<translation id="7006930604109697472">කෙසේ වුවත් යවන්න</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">à·ƒà·à¶šà·ƒà·“ම් ප්â€à¶»à¶­à·’ප්â€à¶»à¶¸à·à¶« කරන්න</translation>
<translation id="7014741021609395734">විà·à·à¶½à¶± මට්ටම</translation>
<translation id="7016992613359344582">මෙම අය කිරීම් එක්-වර හ෠ප්â€à¶»à¶­à·Šâ€à¶ºà·à·€à¶»à·Šà¶­ විය à·„à·à¶šà·’ අතර, පà·à·„à·à¶¯à·’ලි නොවිය à·„à·à¶š.</translation>
<translation id="7029809446516969842">මුරපද</translation>
+<translation id="7030436163253143341">සහතිකය වලංගු නà·à¶­</translation>
<translation id="7031646650991750659">ඔබ ස්ථà·à¶´à¶± කර ඇති Google Play යෙදුම් මොනවà·à¶¯</translation>
<translation id="7050187094878475250">ඔබ <ph name="DOMAIN" /> වෙත ළඟ෠කිරීමට උත්සà·à·„ නමුත්, සේවà·à¶¯à·à¶ºà¶šà¶ºà· වලංගු කà·à¶½à¶º විà·à·Šà·€à·à·ƒà·€à¶±à·Šà¶­ වීමට දිග à·€à·à¶©à·’ සහතිකයක් ඉදිරිපත් කළà·.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{මෙම කà·à¶©à·Šà¶´à¶­ දà·à¶±à¶§ සුරà·à¶šà·’ය නොහà·à¶š}one{මෙම කà·à¶©à·Šà¶´à¶­à·Š දà·à¶±à¶§ සුරà·à¶šà·’ය නොහà·à¶š}other{මෙම කà·à¶©à·Šà¶´à¶­à·Š දà·à¶±à¶§ සුරà·à¶šà·’ය නොහà·à¶š}}</translation>
@@ -1646,12 +1690,14 @@
<translation id="7300012071106347854">කà·à¶¶à·œà¶½à·Šà¶§à·Š නිල්</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">à·€à·à¶©à·’</translation>
+<translation id="7305756307268530424">වඩ෠මන්දගà·à¶¸à·“à·€ අරඹන්න</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">සම්බන්ධත෠උපකà·à¶»à¶º</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" කොටස සඟවන්න</translation>
<translation id="733354035281974745">උපà·à¶‚ග අභ්â€à¶ºà¶±à·Šà¶­à¶» ගිණුම් ප්â€à¶»à¶­à·’ක්â€à·‚ේපය</translation>
<translation id="7333654844024768166">ඔබ මේ දà·à¶±à·Š වංචනික අඩවියක ඔබේ මුරපදය ඇතුළු කළà·. Chromium <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />, සහ ඔබ මෙම මුරපදය භà·à·€à·’ත කරන වෙනත් වෙබ් අඩවිවලට ගොස් එය දà·à¶±à·Š වෙනස් කිරීම නිර්දේ෠කරයි.</translation>
<translation id="7334320624316649418">යළි ඇනවුම් කිරීම &amp;යළි කරන්න</translation>
+<translation id="7337248890521463931">තවත් පේළි පෙන්වන්න</translation>
<translation id="7337706099755338005">ඔබේ වේදිකà·à·€ මත නොතිබේ.</translation>
<translation id="733923710415886693">සහතික පà·à¶»à¶¯à·˜à·à·Šâ€à¶ºà¶­à·à·€ හරහ෠සේවà·à¶¯à·à¶ºà¶šà¶ºà·š සහතිකය අනà·à·€à¶»à¶«à¶º නොකෙරේ.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1659,6 +1705,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">විධà·à¶± පේළිය</translation>
<translation id="7359588939039777303">වෙළඳ දà·à¶±à·Šà·€à·“ම් අවහිරයි.</translation>
+<translation id="7363096869660964304">කෙසේ වුවත්, ඔබ අදෘà·à·Šâ€à¶ºà¶¸à·à¶± නොවේ. අප්â€à¶»à¶šà¶§ වීම ඔබගේ බ්â€à¶»à·€à·”ස් කිරීම ඔබගේ සේවà·à¶ºà·à¶¢à¶š, ඔබගේ අන්තර්ජà·à¶½ සේව෠සà·à¶´à¶ºà·”ම්කරු හ෠ඔබ පිවිසි වෙබ් අඩවි වෙතින් නොසඟවයි.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome à·ƒà·à¶šà·ƒà·“ම් තුළ ලිපින එක් කිරීමට සහ කළමනà·à¶šà¶»à¶«à¶º කිරීමට Tab ඔබ෠අනතුරුව Enter ඔබන්න</translation>
<translation id="7365849542400970216">ඔබගේ උපà·à¶‚ග භà·à·€à·’තය දන්නේද?</translation>
<translation id="7372973238305370288">සෙවුම් ප්â€à¶»à¶®à·’පල</translation>
@@ -1669,7 +1716,9 @@
<translation id="7378594059915113390">මà·à¶°à·Šâ€à¶º පà·à¶½à¶š</translation>
<translation id="7378627244592794276">නà·à·„à·</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">අදà·à·… නොවේ</translation>
<translation id="7390545607259442187">කà·à¶©à·Šà¶´à¶­ තහවුරු කිරීම</translation>
+<translation id="7392089738299859607">ලිපිනය යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන්න</translation>
<translation id="7399802613464275309">ආරක්ෂක පරීක්ෂà·à·€</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">ඔබේ <ph name="DEVICE_NAME" /> කළමන෠කෙරේ</translation>
@@ -1684,6 +1733,7 @@
&lt;li&gt;ඔබේ පරිගණකයෙන් මෘදුකà·à¶‚ගය ස්ථිරවම ඉවත් කරන ආකà·à¶»à¶º ඉගෙන ගà·à¶±à·“මට &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome උදවු මධ්â€à¶ºà·ƒà·Šà¶®à·à¶±à¶º&lt;/a&gt; කර෠පිවිසෙන්න
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">ආදරණීය</translation>
<translation id="7416351320495623771">මුරපද කළමනà·à¶šà¶»à¶«à¶º කරන්න...</translation>
<translation id="7419106976560586862">පà·à¶­à·’කඩ මඟ</translation>
<translation id="7437289804838430631">සම්බන්ධත෠තතු එක් කරන්න</translation>
@@ -1699,7 +1749,7 @@
<translation id="7481312909269577407">ඉදිරියට යන්න</translation>
<translation id="7485870689360869515">දත්ත කිසිවක් හමු නොවිනි</translation>
<translation id="7495528107193238112">මෙම අන්තර්ගතය අවහිර කර ඇත. ගà·à¶§à¶½à·”à·€ නිවà·à¶»à¶¯à·’ කිරීමට අඩවි හිමිකරු අමතන්න</translation>
-<translation id="7498234416455752244">දිගටම සංස්කරණ කරන්න</translation>
+<translation id="7498193950643227031">ප්â€à¶»à¶­à·’ප්â€à¶»à¶¸à·à¶« කළහොත් එය අනපේක්ෂිත ලෙස à·„à·à·ƒà·’රිය à·„à·à¶šà·’ය. ඔබට දà·à¶±à·Š <ph name="SETTINGS" /> තුළ යෙදුම් ප්â€à¶»à¶­à·’ප්â€à¶»à¶¸à·à¶« කිරීමේ à·„à·à¶šà·’යà·à·€ සීම෠කළ à·„à·à¶šà·’ය.</translation>
<translation id="7503664977220660814">ඔබ මේ දà·à¶±à·Š වංචනික අඩවියක ඔබේ මුරපදය ඇතුළු කළà·. Chromium <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, සහ ඔබ දà·à¶±à¶§ මෙම මුරපදය භà·à·€à·’ත කරන වෙනත් වෙබ් අඩවි සඳහ෠ඔබේ සුරà·à¶šà·’ මුරපද පරීක්â€à·‚෠කිරීම නිර්දේ෠කරයි.</translation>
<translation id="7508255263130623398">ආපසු ලබ෠දුන් ප්â€à¶»à¶­à·’පත්ති උපà·à¶‚ග id හිස් හ෠වත්මන් උපà·à¶‚ග id හ෠නොගà·à·…පෙයි</translation>
<translation id="7508870219247277067">අලිගà·à¶§ පේර කොළ</translation>
@@ -1719,6 +1769,7 @@
<translation id="7548892272833184391">සබà·à¶³à·”ම දà·à·‚ නිරà·à¶šà¶»à¶«à¶º කරන්න</translation>
<translation id="7549584377607005141">මෙම වෙබ් පිටුව නිසි ලෙස දර්à·à¶±à¶º කිරීම සඳහ෠ඔබ පෙර ඇතුළත් කළ දත්ත අවà·à·Šâ€à¶º වේ. ඔබට මෙම දත්ත නà·à·€à¶­à¶­à·Š යà·à·€à·’ය à·„à·à¶šà·’ නමුත් එසේ කිරීමෙන් මෙම පිටුව මඟින් පෙරදී සිදු වූ ක්â€à¶»à·’යà·à·€ නà·à·€à¶­à¶­à·Š සිදු වනු ඇත.</translation>
<translation id="7550637293666041147">ඔබේ උපà·à¶‚ග පරිà·à·“ලක නà·à¶¸à¶º සහ Chrome පරිà·à·“ලක නà·à¶¸à¶º</translation>
+<translation id="755279583747225797">අත්හද෠බà·à¶½à·“ම සක්â€à¶»à·’යයි</translation>
<translation id="7552846755917812628">පහත ඉඟි උත්සà·à·„ කරන්න:</translation>
<translation id="7554475479213504905">කෙසේ වූවත් නà·à·€à¶­ පූරණ කර පෙන්වන්න</translation>
<translation id="7554791636758816595">නව ටà·à¶¶à¶º</translation>
@@ -1737,7 +1788,6 @@
<translation id="7610193165460212391">අගය <ph name="VALUE" /> පරà·à·ƒà¶ºà·™à¶±à·Š බà·à·„à·à¶»à·€ ඇත.</translation>
<translation id="7613889955535752492">කල් ඉකුත් වීම: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome à·ƒà·à¶šà·ƒà·“ම් තුළ ඔබගේ මුරපද බà·à¶½à·“මට සහ කළමනà·à¶šà¶»à¶«à¶º කිරීමට Tab ඔබ෠අනතුරුව Enter ඔබන්න</translation>
-<translation id="7615602087246926389">Google Account රහස්වචනය වෙනත් අනුවà·à¶¯à¶ºà¶šà·Š භà·à·€à·’ත෠කරමින් සංකේතනය කළ දත්ත ඔබට දà·à¶±à¶§à¶¸à¶­à·Š තිබේ. කරුණà·à¶šà¶» එය පහත ඇතුළු කරන්න.</translation>
<translation id="7616645509853975347">ඔබේ පරිපà·à¶½à¶š ඔබේ බ්â€à¶»à·€à·Šà·ƒà¶»à¶ºà·š Chrome Enterprise Connectors ක්â€à¶»à·’යà·à¶­à·Šà¶¸à¶š කර ඇත. මෙම සම්බන්ධකවලට ඔබේ දත්ත සමහරක් වෙත ප්â€à¶»à·€à·šà·à¶º තිබේ.</translation>
<translation id="7619838219691048931">අවසන් පත්â€à¶»à¶º</translation>
<translation id="762844065391966283">එක් වරකට එකක්</translation>
@@ -1802,13 +1852,12 @@
<translation id="782886543891417279">ඔබ භà·à·€à·’ත෠කරන Wi-Fi (<ph name="WIFI_NAME" />) මගින් ඔබ එහි පුරනය වීමේ පිටුවට පිවිසීමට අවà·à·Šâ€à¶º විය à·„à·à¶š.</translation>
<translation id="7836231406687464395">Postfix (ලියුම් කවරය)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{කිසිවක් නà·à¶­}=1{1 යෙදුමක් (<ph name="EXAMPLE_APP_1" />)}=2{යෙදුම් 2ක් (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{යෙදුම් #ක් (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{යෙදුම් #ක් (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">කෙසේ වුවත්, ඔබ අදෘà·à·Šâ€à¶ºà¶¸à·à¶± නොවේ. අප්â€à¶»à¶šà¶§ වීම ඔබගේ පිරික්සීම ඔබගේ සේවà·à¶ºà·à¶¢à¶š, ඔබගේ අන්තර්ජà·à¶½ සේව෠සà·à¶´à¶ºà·”ම්කරු, හ෠ඔබ පිවිසි වෙබ් අඩවි වෙතින් නොසඟවයි.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ගොනු වර්ග සංගම් සහිත ගොනු විවෘත කරන්න.</translation>
<translation id="7862185352068345852">අඩවියෙන් ඉවත් වන්න ද?</translation>
<translation id="7865448901209910068">හොඳම වේගය</translation>
<translation id="7874263914261512992">ඔබ මේ දà·à¶±à·Š වංචනික අඩවියක ඔබේ මුරපදය ඇතුළු කළà·. Chrome <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, සහ ඔබ දà·à¶±à¶§ මෙම මුරපදය භà·à·€à·’ත කරන වෙනත් වෙබ් අඩවි සඳහ෠ඔබේ සුරà·à¶šà·’ මුරපද පරීක්â€à·‚෠කිරීම නිර්දේ෠කරයි.</translation>
<translation id="7878562273885520351">ඔබේ මුරපදය අන් සතු වී තිබිය à·„à·à¶šà·’ය</translation>
+<translation id="7880146494886811634">ලිපිනය සුරකින්න</translation>
<translation id="7882421473871500483">දුඹුරු</translation>
<translation id="7887683347370398519">ඔබේ CVC පරීක්ෂ෠කර නà·à·€à¶­ උත්සà·à·„ කරන්න</translation>
<translation id="7887885240995164102">පින්තූරය-තුළ-පින්තූරයට ඇතුළු වන්න</translation>
@@ -1816,6 +1865,7 @@
<translation id="7894280532028510793">අක්ෂර වින්â€à¶ºà·à·ƒà¶º නිවà·à¶»à¶¯à·’ නම්, <ph name="BEGIN_LINK" />ජà·à¶½ දà·à·‚ නිර්ණ ධà·à·€à¶±à¶º කිරීම උත්සà·à·„ කරන්න<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (ලියුම් කවරය)</translation>
<translation id="7931318309563332511">නොදනී</translation>
+<translation id="793209273132572360">ලිපිනය යà·à·€à¶­à·Šà¶šà·à¶½à·“න කරන්නද?</translation>
<translation id="7932579305932748336">කබà·à¶º</translation>
<translation id="79338296614623784">වලංගු දුරකථන අංකයක් ඇතුළු කරන්න</translation>
<translation id="7934052535022478634">ගෙවීම සම්පූර්ණයි</translation>
@@ -1886,6 +1936,7 @@
<translation id="8175796834047840627">ඔබ පුරනය වී සිටින බà·à·€à·’න් Chrome ඔබට ඔබේ කà·à¶©à·Šà¶´à¶­à·Š ඔබේ Google ගිණුමට සුරà·à¶šà·“ම පිරිනමයි. ඔබට මෙම à·„à·à·ƒà·’රීම à·ƒà·à¶šà·ƒà·“ම් තුළ වෙනස් කළ à·„à·à¶š.</translation>
<translation id="8176440868214972690">à·ƒà·à¶šà·ƒà·“ම් හ෠ප්â€à¶»à¶­à·’පත්ති à·€à·à¶±à·’, පහත සඳහන් වෙබ් අඩවි වෙත මෙම උපà·à¶‚ගයේ පරිපà·à¶½à¶š යම් තොරතුරු යව෠ඇත.</translation>
<translation id="8184538546369750125">ගà·à¶½à·“ය පෙරනිමිය භà·à·€à·’ත෠කරන්න (අවසර)</translation>
+<translation id="8193086767630290324">රහසිගත ලෙස ලකුණු කළ දත්ත සම්බන්ධව ගත් ක්â€à¶»à·’යà·</translation>
<translation id="8194797478851900357">ගෙන යà·à¶¸ &amp;පසුගමනය කරන්න</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" ID සමඟ à·€à·à¶»à¶¯à·’ යà·à·€à¶­à·Š ලිපිනයක්.</translation>
<translation id="8202097416529803614">ඇණවුම් à·ƒà·à¶»à·à¶‚à·à¶º</translation>
@@ -1908,6 +1959,7 @@
<translation id="8249296373107784235">අහà·à·ƒà·’ කරන්න</translation>
<translation id="8249320324621329438">ලබà·à¶œà¶­à·Š අවසන් වර:</translation>
<translation id="8253091569723639551">බිල්ගත කිරීමේ ලිපිනය අවà·à·Šâ€à¶ºà¶ºà·’</translation>
+<translation id="8257387598443225809">මෙම යෙදුම ජංගම සඳහ෠සà·à¶½à·ƒà·”ම් කර ඇත.</translation>
<translation id="825929999321470778">සුරà·à¶šà·’ මුරපද සියල්ල පෙන්වන්න</translation>
<translation id="8261506727792406068">මකන්න</translation>
<translation id="8262952874573525464">පහළ දà·à¶»à¶º මසන්න</translation>
@@ -2031,7 +2083,6 @@
<translation id="8719528812645237045">ඉහළට ඇනීම් බොහොමයක්</translation>
<translation id="8725066075913043281">නà·à·€à¶­ උත්සහ කරන්න</translation>
<translation id="8726549941689275341">පිටු තරම:</translation>
-<translation id="8728672262656704056">ඔබ අප්â€à¶»à·ƒà·’ද්ධව ගොස් ඇත</translation>
<translation id="8730621377337864115">අවසන්</translation>
<translation id="8731544501227493793">මුරපද කළමනà·à¶šà¶»à¶«à¶º කරන්න බොත්තම, ඔබගේ මුරපද Chrome à·ƒà·à¶šà·ƒà·“ම් තුළ බà·à¶½à·“මට සහ කළමනà·à¶šà¶»à¶«à¶º කිරීමට Enter ඔබන්න</translation>
<translation id="8734529307927223492">ඔබගේ <ph name="DEVICE_TYPE" /> <ph name="MANAGER" /> විසින් කළමනà·à¶šà¶»à¶«à¶º කෙරේ</translation>
@@ -2108,6 +2159,7 @@
<translation id="9020542370529661692">මෙම පිටුව <ph name="TARGET_LANGUAGE" /> ට පරිවර්තනය වී ඇත</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(අවලංගුයි)</translation>
+<translation id="9030265603405983977">මොනොක්â€à¶»à·à¶¸à·Š</translation>
<translation id="9035022520814077154">ආරක්ෂක දà·à·‚ය</translation>
<translation id="9038649477754266430">වඩ෠ඉක්මනින් පිටු පූරණය කිරීමට පුරà·à¶šà¶®à¶± සේවà·à·€à¶šà·Š භà·à·€à·’ත කරන්න</translation>
<translation id="9039213469156557790">තවද, මෙම පිටුවේ ආරක්ෂිත නොවන වෙනත් සම්පත් ඇත. එම සම්පත් හුවමà·à¶»à·”à·€ අතරතුර â€à¶…නෙක් අයටත් බà·à¶½à·’ය à·„à·à¶šà·’ අතර, පිටුවේ à·„à·à·ƒà·’රීම වෙනස් වන අයුරින් වෙනස් කිරීමට වෙබ් ප්â€à¶»à·„à·à¶»à¶šà¶ºà·™à¶šà·”ට à·„à·à¶šà·’ය.</translation>
@@ -2131,6 +2183,7 @@
<translation id="91108059142052966">රහසිගත අන්තර්ගතය දෘà·à·Šâ€à¶ºà¶¸à·à¶± විට පරිපà·à¶½à¶š ප්â€à¶»à¶­à·’පත්තිය <ph name="APPLICATION_TITLE" /> සමග තිරය බෙද෠ගà·à¶±à·“ම අබල කරයි</translation>
<translation id="9114524666733003316">කà·à¶©à·Šà¶´à¶­ තහවුරු කරමින්...</translation>
<translation id="9114581008513152754">මෙම බ්â€à¶»à·€à·”සරය සමà·à¶œà¶¸à¶šà·’න් හ෠වෙනත් සංවිධà·à¶±à¶ºà¶šà·’න් කළමනà·à¶šà¶»à¶«à¶º නොකරයි. මෙම උපà·à¶‚ගයේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à·Š Chrome වලින් පිටත ඇතà·à¶¸à·Š විට කළමනà·à¶šà¶»à¶«à¶º කළ à·„à·à¶šà·’ය. <ph name="BEGIN_LINK" />තව දà·à¶± ගන්න<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">නà·à·€à·”ම්</translation>
<translation id="9119042192571987207">උඩුගත කළà·</translation>
<translation id="9128016270925453879">ප්â€à¶»à¶­à·’පත්ති පූරණය කර ඇත</translation>
<translation id="9128870381267983090">ජà·à¶½à¶ºà¶§ සබඳ වන්න</translation>
@@ -2149,6 +2202,7 @@
<translation id="9170848237812810038">&amp;පසුගමනය</translation>
<translation id="9171296965991013597">යෙදුම à·„à·à¶» යන්න ද?</translation>
<translation id="9173282814238175921">තනි ලේඛනය/නව පත්â€à¶»à¶º</translation>
+<translation id="9173995187295789444">බ්ලූටූත් උපà·à¶‚ග සඳහ෠ස්කෑන් කරමින්...</translation>
<translation id="917450738466192189">සේව෠සහතිකය වලංගු නà·à¶­.</translation>
<translation id="9174917557437862841">පටිත්ත මà·à¶»à·” කිරීමේ බොත්තම, මෙම පටිත්තට මà·à¶»à·” වීමට Enter ඔබන්න</translation>
<translation id="9179703756951298733">Chrome à·ƒà·à¶šà·ƒà·“ම් තුළ ඔබගේ ගෙවීම් සහ ණය කà·à¶©à·Šà¶´à¶­à·Š තතු කළමනà·à¶šà¶»à¶«à¶º කරන්න</translation>
diff --git a/chromium/components/strings/components_strings_sk.xtb b/chromium/components/strings/components_strings_sk.xtb
index aff16e293e7..d45d3496749 100644
--- a/chromium/components/strings/components_strings_sk.xtb
+++ b/chromium/components/strings/components_strings_sk.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Vyberte povolenie pre <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Vrátiť späť zmenu poradia</translation>
+<translation id="1123753900084781868">Živý prepis momentálne nie je k dispozícii</translation>
<translation id="1125573121925420732">Kým weby aktualizujú svoje zabezpeÄenie, môžu sa Äasto zobrazovaÅ¥ upozornenia. ÄŒoskoro by sa to malo zlepÅ¡iÅ¥.</translation>
<translation id="112840717907525620">Vyrovnávacia pamäť pravidla je v poriadku</translation>
<translation id="1130564665089811311">TlaÄidlo PreložiÅ¥ stránku. Po stlaÄení klávesa Enter PrekladaÄ Google túto stránku preloží.</translation>
@@ -74,6 +75,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="1240347957665416060">Názov vášho zariadenia</translation>
<translation id="124116460088058876">Ďalšie jazyky</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">TuÄné</translation>
<translation id="1250759482327835220">Ak chcete nabudúce zaplatiÅ¥ rýchlejÅ¡ie, uložte si kartu, meno a fakturaÄnú adresu do úÄtu Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (synchronizované)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ak chcete navÅ¡tíviÅ¥ urÄitý web, ale neotvorí sa, najprv skúste opraviÅ¥ chybu pomocou týchto krokov na rieÅ¡enie problémov:&lt;/p&gt;
@@ -156,6 +158,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="1476595624592550506">Zmeňte heslo</translation>
<translation id="1484290072879560759">Zvoliť dodaciu adresu</translation>
<translation id="1492194039220927094">Odosielanie pravidiel:</translation>
+<translation id="1495677929897281669">Späť na kartu</translation>
<translation id="1501859676467574491">ZobraziÅ¥ karty z vášho úÄtu Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Táto chyba sa zobrazí, keÄ používate portál Wi-Fi, ktorý podmieňuje prístup k internetu prihlásením.&lt;/p&gt;
&lt;p&gt;Ak ju chcete odstrániť, kliknite na možnosť &lt;strong&gt;Pripojiť&lt;/strong&gt; na stránke, ktorú sa pokúšate otvoriť.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="1532118530259321453">Táto stránka hovorí</translation>
<translation id="153384715582417236">To je zatiaľ všetko</translation>
<translation id="1536390784834419204">Preložiť stránku</translation>
+<translation id="1539840569003678498">Hlásenie bolo odoslané:</translation>
<translation id="154408704832528245">ZvoliÅ¥ adresu doruÄenia</translation>
<translation id="1549470594296187301">Ak chcete použiť túto funkciu, musíte povoliť JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="1682696192498422849">Napred krátkym okrajom</translation>
<translation id="168693727862418163">Túto hodnotu pravidla sa nepodarilo v jeho schéme overiť a bude ignorovaná.</translation>
<translation id="168841957122794586">Certifikát servera obsahuje slabý kryptografický kľúÄ.</translation>
+<translation id="1696290444144917273">Zobraziť podrobnosti virtuálnej karty</translation>
<translation id="1697532407822776718">Všetko je nastavené!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Tomuto serveru sa nepodarilo dokázaÅ¥, že ide o doménu <ph name="DOMAIN" />; jej certifikát by mal zaÄaÅ¥ platiÅ¥ od zajtra. Môže to byÅ¥ následok nesprávnej konfigurácie alebo napadnutia vášho pripojenia útoÄníkom.}few{Tomuto serveru sa nepodarilo dokázaÅ¥, že ide o doménu <ph name="DOMAIN" />; jej certifikát by mal zaÄaÅ¥ platiÅ¥ o # dni. Môže to byÅ¥ následok nesprávnej konfigurácie alebo napadnutia vášho pripojenia útoÄníkom.}many{Tomuto serveru sa nepodarilo dokázaÅ¥, že ide o doménu <ph name="DOMAIN" />; jej certifikát by mal zaÄaÅ¥ platiÅ¥ o # dňa. Môže to byÅ¥ následok nesprávnej konfigurácie alebo napadnutia vášho pripojenia útoÄníkom.}other{Tomuto serveru sa nepodarilo dokázaÅ¥, že ide o doménu <ph name="DOMAIN" />; jej certifikát by mal zaÄaÅ¥ platiÅ¥ o # dní. Môže to byÅ¥ následok nesprávnej konfigurácie alebo napadnutia vášho pripojenia útoÄníkom.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Ignorované, pretože pravidlo <ph name="POLICY_NAME" /> nie je nastavené na <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> chce natrvalo ukladaÅ¥ dáta v miestnom poÄítaÄi</translation>
<translation id="1713628304598226412">Priehradka Ä. 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">PoÅ¡tová schránka Ä. 3</translation>
<translation id="1718029547804390981">Dokument nie je možné anotovať, pretože je príliš veľký</translation>
<translation id="1721424275792716183">* Toto pole je povinné</translation>
+<translation id="1727613060316725209">Certifikát je platný</translation>
<translation id="1727741090716970331">Pridanie platného Äísla karty</translation>
<translation id="1728677426644403582">Prezeráte si zdrojový kód webovej stránky</translation>
<translation id="173080396488393970">Tento typ karty nie je podporovaný</translation>
@@ -242,7 +249,6 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />Skúste spustiť nástroj Diagnostika siete systému Windows<ph name="END_LINK" />.</translation>
<translation id="1772163372082567643">Server <ph name="ORIGIN" />, na ktorý prechádzate, nastavil hlaviÄku, ktorá požaduje, aby sa na vÅ¡etky požiadavky odoslané na server vzÅ¥ahovalo pravidlo pre zdroj. HlaviÄka má vÅ¡ak nesprávny tvar a prehliadaÄ preto nemôže vaÅ¡ej požiadavke pre web <ph name="SITE" /> vyhovieÅ¥. Pomocou pravidiel pre zdroj môžu operátori webu nakonfigurovaÅ¥ zabezpeÄenie a ÄalÅ¡ie vlastnosti webu.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Aktualizujte prístupovú frázu na synchronizáciu.</translation>
<translation id="1787142507584202372">Tu sa zobrazia otvorené karty</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, k dispozícii je viac akcií, stlaÄením klávesa Tab po nich prechádzajte</translation>
@@ -275,6 +281,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="1919345977826869612">Reklamy</translation>
<translation id="1919367280705858090">Pomoc s konkrétnym chybovým hlásením</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Žiadne}=1{1 web}few{# weby}many{# webu}other{# webov}}</translation>
+<translation id="1924727005275031552">Nové</translation>
<translation id="1945968466830820669">Môžete stratiÅ¥ prístup do úÄtu svojej organizácie alebo vám niekto môže ukradnúť totožnosÅ¥. Chromium odporúÄa, aby ste si ihneÄ zmenili heslo.</translation>
<translation id="1947454675006758438">Zošiť spinkou vpravo hore</translation>
<translation id="1958218078413065209">Vaše najvyššie skóre je <ph name="SCORE" />.</translation>
@@ -297,12 +304,14 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="2042213636306070719">Priehradka Ä. 7</translation>
<translation id="204357726431741734">PrihlásiÅ¥ sa a používaÅ¥ heslá uložené vo vaÅ¡om úÄte Google</translation>
<translation id="2053111141626950936">Stránky v jazyku <ph name="LANGUAGE" /> nebudú prekladané.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{KeÄ je tento ovládací prvok zapnutý a stav je aktívny, Chrome stanoví, ktorej veľkej skupine ľudí („kohorte“) je vaÅ¡a nedávna aktivita prehliadania najviac podobná. Inzerenti môžu pre túto skupinu vybraÅ¥ reklamy a vaÅ¡a aktivita prehliadania zostane uchovaná v súkromí vo vaÅ¡om zariadení. Skupina sa aktualizuje každý deň.}=1{KeÄ je tento ovládací prvok zapnutý a stav je aktívny, Chrome stanoví, ktorej veľkej skupine ľudí („kohorte“) je vaÅ¡a nedávna aktivita prehliadania najviac podobná. Inzerenti môžu pre túto skupinu vybraÅ¥ reklamy a vaÅ¡a aktivita prehliadania zostane uchovaná v súkromí vo vaÅ¡om zariadení. Skupina sa aktualizuje každý deň.}few{KeÄ je tento ovládací prvok zapnutý a stav je aktívny, Chrome stanoví, ktorej veľkej skupine ľudí („kohorte“) je vaÅ¡a nedávna aktivita prehliadania najviac podobná. Inzerenti môžu pre túto skupinu vybraÅ¥ reklamy a vaÅ¡a aktivita prehliadania zostane uchovaná v súkromí vo vaÅ¡om zariadení. Skupina sa aktualizuje každé {NUM_DAYS} dni.}many{KeÄ je tento ovládací prvok zapnutý a stav je aktívny, Chrome stanoví, ktorej veľkej skupine ľudí („kohorte“) je vaÅ¡a nedávna aktivita prehliadania najviac podobná. Inzerenti môžu pre túto skupinu vybraÅ¥ reklamy a vaÅ¡a aktivita prehliadania zostane uchovaná v súkromí vo vaÅ¡om zariadení. Skupina sa aktualizuje každého {NUM_DAYS} dňa.}other{KeÄ je tento ovládací prvok zapnutý a stav je aktívny, Chrome stanoví, ktorej veľkej skupine ľudí („kohorte“) je vaÅ¡a nedávna aktivita prehliadania najviac podobná. Inzerenti môžu pre túto skupinu vybraÅ¥ reklamy a vaÅ¡a aktivita prehliadania zostane uchovaná v súkromí vo vaÅ¡om zariadení. Skupina sa aktualizuje každých {NUM_DAYS} dní.}}</translation>
<translation id="2053553514270667976">PSČ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 návrh}few{# návrhy}many{# návrhu}other{# návrhov}}</translation>
<translation id="2071692954027939183">Upozornenia boli automaticky blokované, pretože ich zvyÄajne nepovoľujete</translation>
<translation id="2079545284768500474">Späť</translation>
<translation id="20817612488360358">Používanie systémových nastavení servera proxy je nastavené, avÅ¡ak je urÄená aj explicitná konfigurácia servera proxy.</translation>
<translation id="2082238445998314030">Výsledok <ph name="RESULT_NUMBER" /> z <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Uložiť…</translation>
<translation id="2088086323192747268">TlaÄidlo SpravovaÅ¥ synchronizáciu. StlaÄením klávesa Enter môžete v nastaveniach Chromu spravovaÅ¥, aké údaje sa synchronizujú.</translation>
<translation id="2091887806945687916">Zvuk</translation>
<translation id="2094505752054353250">Domény sa nezhodujú</translation>
@@ -375,6 +384,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="2317259163369394535">Doména <ph name="DOMAIN" /> vyžaduje používateľské meno a heslo.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, platí do <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Nastavenie ovládané správcom</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> žiada o spárovanie</translation>
<translation id="2344028582131185878">Automatické sťahovania</translation>
<translation id="2346319942568447007">Skopírovaný obrázok</translation>
<translation id="2354001756790975382">Ostatné</translation>
@@ -382,8 +392,10 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="2355395290879513365">ÚtoÄníci môžu vidieÅ¥ obrázky, ktoré si prehliadate na tomto webe, a môžu vás napadnúť tým, že ich podvodným spôsobom upravia.</translation>
<translation id="2356070529366658676">Opýtať sa</translation>
<translation id="2357481397660644965">VaÅ¡e zariadenie spravuje <ph name="DEVICE_MANAGER" /> a váš úÄet spravuje <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{O menej ako deň}=1{O deň}few{O {NUM_DAYS} dni}many{O {NUM_DAYS} dňa}other{O {NUM_DAYS} dní}}</translation>
<translation id="2359629602545592467">Viaceré</translation>
<translation id="2359808026110333948">PokraÄovaÅ¥</translation>
+<translation id="2359961752320758691">Číslo vašej virtuálnej karty sa používa.</translation>
<translation id="2367567093518048410">Úroveň</translation>
<translation id="2372464001869762664">Po potvrdení sa budú podrobnosti karty z vášho úÄtu Google zdieľaÅ¥ s týmto webom. V údajoch úÄtu Plex nájdite overovací kód karty.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="239429038616798445">Tento spôsob dodania nie je k dispozícii. Skúste inú možnosť.</translation>
<translation id="2396249848217231973">&amp;Vrátiť späť odstránenie</translation>
<translation id="2410754574180102685">Vládny právny dokument</translation>
+<translation id="2413155254802890957">Staré</translation>
<translation id="2413528052993050574">Server nedokáže overiÅ¥, Äi ide o doménu <ph name="DOMAIN" />, jej bezpeÄnostný certifikát bol zrejme zruÅ¡ený. Môže to byÅ¥ spôsobené nesprávnou konfiguráciou alebo tým, že vaÅ¡e pripojenie zachytil útoÄník.</translation>
<translation id="2414886740292270097">Tmavý režim</translation>
<translation id="2438874542388153331">Å tyri dierky vpravo</translation>
@@ -421,10 +434,10 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="2521385132275182522">Zošiť spinkou vpravo dolu</translation>
<translation id="2523886232349826891">Uložené iba na tomto zariadení</translation>
<translation id="2524461107774643265">Pridanie Äalších informácií</translation>
-<translation id="2526590354069164005">Pracovná plocha</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{a 1 ÄalÅ¡ia}few{a # ÄalÅ¡ie}many{and # more}other{a # Äalších}}</translation>
<translation id="2536110899380797252">Pridať adresu</translation>
<translation id="2539524384386349900">Rozpoznávať</translation>
+<translation id="2541219929084442027">KeÄ zavriete vÅ¡etky karty inkognito, po stránkach, ktoré ste na nich zobrazili, nezostane v histórii prehliadania, ukladacom priestore súborov cookie a histórii vyhľadávania ani stopa. VÅ¡etky stiahnuté súbory a vytvorené záložky zostanú zachované.</translation>
<translation id="2544644783021658368">Jeden dokument</translation>
<translation id="254947805923345898">Hodnota pravidla je neplatná.</translation>
<translation id="255002559098805027">Web <ph name="HOST_NAME" /> odoslal neplatnú odpoveÄ.</translation>
@@ -444,6 +457,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="2629325967560697240">Ak chcete získaÅ¥ najvyšší stupeň zabezpeÄenia Chromu, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />zapnite rozšírenú ochranu<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Adresu IP servera <ph name="HOST_NAME" /> sa nepodarilo nájsť.</translation>
<translation id="2639739919103226564">Stav:</translation>
+<translation id="264810637653812429">Nenašli sa žiadne kompatibilné zariadenia.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, postupným stlaÄením klávesov Tab a Enter vymažete v nastaveniach Chromu históriu prehliadania, súbory cookie, vyrovnávaciu pamäť a ÄalÅ¡ie položky</translation>
<translation id="2650446666397867134">Prístup k súboru bol odmietnutý</translation>
@@ -488,6 +502,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<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="2807052079800581569">Poloha obrázka na osi Y</translation>
+<translation id="2820957248982571256">Prebieha vyhľadávanie...</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>
@@ -495,6 +510,8 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="2850739647070081192">Invite (obálka)</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="2859806420264540918">Tento web zobrazuje obťažujúce alebo zavádzajúce reklamy.</translation>
+<translation id="287596039013813457">Milé</translation>
+<translation id="2876489322757410363">Ak zaplatíte pomocou externej aplikácie, opustíte režim inkognito. Chcete pokraÄovaÅ¥?</translation>
<translation id="2878197950673342043">Plagátový záhyb</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Umiestnenie okna</translation>
@@ -544,7 +561,6 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="3060227939791841287">C9 (obálka)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, ak chcete spustiÅ¥ kontrolu bezpeÄnosti v nastaveniach Chromu, stlaÄte Tab a potom Enter</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>
<translation id="306573536155379004">Hra bola spustená.</translation>
<translation id="3080254622891793721">Grafika</translation>
<translation id="3086579638707268289">Vaša aktivita na internete je sledovaná</translation>
@@ -567,7 +583,6 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="315504272643575312">Váš úÄet spravuje <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Obnoviť</translation>
<translation id="3162559335345991374">Sieť Wi‑Fi, ktorú používate, môže vyžadovať, aby ste navštívili jej prihlasovaciu stránku</translation>
-<translation id="3167968892399408617">KeÄ zavriete vÅ¡etky karty inkognito, po stránkach, ktoré ste na nich zobrazili, nezostane v histórii prehliadania, úložisku súborov cookie a histórii vyhľadávania ani stopa. VÅ¡etky stiahnuté súbory a vytvorené záložky zostanú zachované.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ostrov</translation>
<translation id="3176929007561373547">Skontrolujte nastavenia proxy servera alebo kontaktujte správcu siete a požiadajte ho, aby skontroloval, Äi proxy server funguje. Ak sa domnievate, že by ste nemali používaÅ¥ proxy server: <ph name="PLATFORM_TEXT" /></translation>
@@ -590,10 +605,12 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<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="3249845759089040423">Štýlové</translation>
<translation id="3252266817569339921">Francúzština</translation>
<translation id="3266793032086590337">Hodnota (konflikt)</translation>
<translation id="3268451620468152448">Otvorené karty</translation>
<translation id="3270847123878663523">&amp;Vrátiť späť zmenu poradia</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> žiada o pripojenie</translation>
<translation id="3274521967729236597">Pa‑Kai</translation>
<translation id="3282085321714087552">Vaša organizácia, <ph name="ENROLLMENT_DOMAIN" />, odoslala na nasledujúce weby nejaké informácie, napríklad nastavenia alebo pravidlá.</translation>
<translation id="3282497668470633863">Pridanie mena na karte</translation>
@@ -646,6 +663,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="3428151540071562330">Minimálne jeden identifikátor URI šablón servera DnsOverHttpsTemplates je neplatný a nebude použitý.</translation>
<translation id="3431636764301398940">Uložiť túto kartu na zariadení</translation>
<translation id="3432601291244612633">Zavrieť stránku</translation>
+<translation id="3435738964857648380">BezpeÄnosÅ¥</translation>
<translation id="3435896845095436175">Aktivovať</translation>
<translation id="3438829137925142401">PoužiÅ¥ heslá uložené vo vaÅ¡om úÄte Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -688,7 +706,10 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="3584299510153766161">Dve dierky dole</translation>
<translation id="3586931643579894722">Skryť podrobnosti</translation>
<translation id="3587738293690942763">Stred</translation>
+<translation id="3590643883886679995">KeÄ opustíte režim inkognito, prihlasovacie údaje sa budú ukladaÅ¥ v tomto zariadení.</translation>
+<translation id="359126217934908072">Mesiac a rok:</translation>
<translation id="3592413004129370115">Italian (obálka)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Skupinu môžete kedykoľvek resetovať. Pripojenie k novej skupine trvá približne deň.}=1{Skupinu môžete kedykoľvek resetovať. Pripojenie k novej skupine trvá približne deň.}few{Skupinu môžete kedykoľvek resetovať. Pripojenie k novej skupine trvá približne {NUM_DAYS} dni.}many{Skupinu môžete kedykoľvek resetovať. Pripojenie k novej skupine trvá približne {NUM_DAYS} dňa.}other{Skupinu môžete kedykoľvek resetovať. Pripojenie k novej skupine trvá približne {NUM_DAYS} dní.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplikácia bola zablokovaná vaším správcom</translation>
<translation id="3608932978122581043">Orientácia zásobníka</translation>
@@ -697,12 +718,12 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="3615877443314183785">Zadajte správny dátum vypršania platnosti</translation>
<translation id="36224234498066874">Vymazať dáta prehliadania...</translation>
<translation id="362276910939193118">Zobraziť celú históriu</translation>
-<translation id="3625635938337243871">KeÄ opustíte režim inkognito, budú prihlasovacie údaje uložené v tomto zariadení.</translation>
<translation id="3630155396527302611">Ak je už uvedený ako program s prístupom k sieti, skúste ho odstrániť zo zoznamu a znova ho pridať.</translation>
<translation id="3630699740441428070">Správcovia tohto zariadenia nakonfigurovali vaÅ¡e pripojenie k sieti, vÄaka Äomu môžu vidieÅ¥ vaÅ¡u sieÅ¥ovú premávku vrátane webov, ktoré navÅ¡tívite.</translation>
<translation id="3631244953324577188">Biometria</translation>
<translation id="3633738897356909127">TlaÄidlo AktualizovaÅ¥ Chrome. StlaÄením tlaÄidla Enter aktualizujete Chrome v jeho nastaveniach.</translation>
<translation id="3634530185120165534">Priehradka Ä. 5</translation>
+<translation id="3637662659967048211">Uloženie do úÄtu Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplikácia:</translation>
<translation id="3650584904733503804">Overenie bolo úspešné</translation>
@@ -743,6 +764,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="3781428340399460090">Jasnoružová</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Zariadenia Bluetooth</translation>
+<translation id="3787675388804467730">Číslo virtuálnej karty</translation>
<translation id="3787705759683870569">Platnosť vyprší <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Veľkosť 16</translation>
<translation id="3789841737615482174">Inštalovať</translation>
@@ -762,6 +784,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="3841184659773414994">Obslužné nástroje súborov</translation>
<translation id="385051799172605136">Späť</translation>
<translation id="3858027520442213535">AktualizovaÅ¥ dátum a Äas</translation>
+<translation id="3881478300875776315">Zobraziť menej riadkov</translation>
<translation id="3884278016824448484">Kolidujúci identifikátor zariadenia</translation>
<translation id="3885155851504623709">Farnosť</translation>
<translation id="388632593194507180">Bolo rozpoznané monitorovanie</translation>
@@ -787,6 +810,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="397105322502079400">Prebieha výpoÄet...</translation>
<translation id="3973234410852337861">Web <ph name="HOST_NAME" /> je zablokovaný</translation>
<translation id="3973357910713125165">TlaÄidlo na spustenie kontroly bezpeÄnosti Chromu. StlaÄením klávesa Enter spustíte kontrolu bezpeÄnosti v nastaveniach Chromu.</translation>
+<translation id="3986705137476756801">Zapnúť zatiaľ živý prepis</translation>
<translation id="3987405730340719549">Chrome urÄil, že tento web môže byÅ¥ faloÅ¡ný alebo podvodný.
Ak sa domnievate, že toto upozornenie sa zobrazuje omylom, prejdite na https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -878,13 +902,14 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="4275830172053184480">Reštart zariadenia</translation>
<translation id="4277028893293644418">Obnoviť heslo</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="4287885627794386150">Vhodné pre skúšobné obdobie, ale neaktívne</translation>
<translation id="4297502707443874121">Miniatúra stránky <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Rozbaliť</translation>
<translation id="4300675098767811073">Viacero dierok vpravo</translation>
<translation id="4302514097724775343">Ak chcete hrať, klepnite na dinosaura</translation>
<translation id="4302965934281694568">Chou3 (obálka)</translation>
<translation id="4305666528087210886">Súbor sa nepodarilo otvoriť</translation>
-<translation id="4305817255990598646">Prepnúť</translation>
+<translation id="4306529830550717874">Chcete adresu uložiť?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokovať (predvolené)</translation>
<translation id="4314815835985389558">Správa synchronizácie</translation>
@@ -911,6 +936,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="4377125064752653719">Pokúsili ste sa o prístup na stránky <ph name="DOMAIN" />, avÅ¡ak certifikát poskytnutý serverom bol vydavateľom zruÅ¡ený. Znamená to, že povereniam zabezpeÄenia, ktoré predložil server, sa celkom nedá dôverovaÅ¥. Je možné, že komunikujete s útoÄníkom.</translation>
<translation id="4378154925671717803">Telefón</translation>
<translation id="4390472908992056574">Okraj</translation>
+<translation id="4406883609789734330">Živý prepis</translation>
<translation id="4406896451731180161">výsledky vyhľadávania</translation>
<translation id="4408413947728134509">Súbory cookie: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Práve ste zadali svoje heslo na podvodnom webe. Chrome odporúÄa, aby ste preÅ¡li na <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> a ÄalÅ¡ie weby, kde používate toto heslo, a ihneÄ ho zmenili.</translation>
@@ -923,7 +949,6 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<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="4464826014807964867">Weby s informáciami od vašej organizácie</translation>
-<translation id="4466881336512663640">Zmeny formulára sa odstránia. Naozaj chcete pokraÄovaÅ¥?</translation>
<translation id="4476953670630786061">Tento formulár nie je zabezpeÄený. Automatické dopĺňanie bolo vypnuté.</translation>
<translation id="4477350412780666475">Ďalšia stopa</translation>
<translation id="4482953324121162758">Tento web nebude preložený.</translation>
@@ -957,6 +982,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<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="4606870351894164739">ÚÄinné</translation>
<translation id="4628948037717959914">Fotografia</translation>
<translation id="4631649115723685955">Funkcia Cashback je prepojená</translation>
<translation id="4636930964841734540">Informácie</translation>
@@ -976,6 +1002,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="4691835149146451662">Architecture-A (obálka)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Strana</translation>
+<translation id="4702656508969495934">Živý prepis je viditeľný, oznaÄíte prepínaÄom okien</translation>
<translation id="4708268264240856090">Pripojenie bolo prerušené</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Spustiť nástroj Diagnostika siete systému Windows<ph name="END_LINK" /></translation>
@@ -989,6 +1016,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="4738601419177586157">Návrh vyhľadávania <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Spravovať heslá…</translation>
<translation id="4744603770635761495">Spustiteľná cesta</translation>
+<translation id="4749011317274908093">Ste v režime inkognito</translation>
<translation id="4750917950439032686">VaÅ¡e údaje, napríklad heslá alebo Äísla kreditných kariet, sú pri odosielaní na tento web utajené.</translation>
<translation id="4756388243121344051">&amp;História</translation>
<translation id="4758311279753947758">Pridať kontaktné údaje</translation>
@@ -1018,6 +1046,8 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="4813512666221746211">Chyba siete</translation>
<translation id="4816492930507672669">Prispôsobiť stránke</translation>
<translation id="4819347708020428563">Chcete upraviť poznámky v predvolenom zobrazení?</translation>
+<translation id="4825507807291741242">Pôsobivé</translation>
+<translation id="4838327282952368871">Rozprávkové</translation>
<translation id="484462545196658690">Automaticky</translation>
<translation id="4850886885716139402">Zobraziť</translation>
<translation id="485316830061041779">NemÄina</translation>
@@ -1154,6 +1184,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="5314967030527622926">Nástroj na vytvorenie bookletu</translation>
<translation id="5316812925700871227">OtoÄiÅ¥ proti smeru hodinových ruÄiÄiek</translation>
<translation id="5317780077021120954">Uložiť</translation>
+<translation id="5321288445143113935">Maximalizované</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> z <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Vybrať kontaktné informácie</translation>
<translation id="5327248766486351172">Názov</translation>
@@ -1161,11 +1192,13 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="5332219387342487447">Spôsob dodania</translation>
<translation id="5333022057423422993">Chrome naÅ¡iel heslo, ktoré ste práve použili, v zozname hesiel odhalených pri poruÅ¡ení ochrany údajov. V rámci zabezpeÄenia úÄtov vám odporúÄame skontrolovaÅ¥ uložené heslá.</translation>
<translation id="5334013548165032829">Podrobné denníky systému</translation>
+<translation id="5334145288572353250">Chcete adresu uložiť?</translation>
<translation id="5340250774223869109">Aplikácia je blokovaná</translation>
<translation id="534295439873310000">Zariadenia NFC</translation>
<translation id="5344579389779391559">Táto stránka sa vám môže pokúsiÅ¥ úÄtovaÅ¥ poplatky</translation>
<translation id="5355557959165512791">Web <ph name="SITE" /> momentálne nemôžete navÅ¡tíviÅ¥, pretože tento certifikát bol odvolaný. Chyby siete a útoky sú zvyÄajne doÄasné, takže by táto stránka mala neskôr pravdepodobne fungovaÅ¥.</translation>
<translation id="536296301121032821">Nastavenia pravidla sa nepodarilo uložiť</translation>
+<translation id="5363309033720083897">Sériový port povolený vaším správcom</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="5386426401304769735">Reťazec certifikátu pre tento web obsahuje certifikát podpísaný pomocou funkcie SHA-1.</translation>
@@ -1174,6 +1207,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="5398772614898833570">Reklamy sú blokované</translation>
<translation id="5400836586163650660">Sivá</translation>
<translation id="540969355065856584">Server nedokáže overiÅ¥, Äi ide o doménu <ph name="DOMAIN" /> – jej bezpeÄnostný certifikát je momentálne neplatný. Môže to byÅ¥ spôsobené nesprávnou konfiguráciou alebo tým, že vaÅ¡e pripojenie napadol útoÄník.</translation>
+<translation id="541143247543991491">Cloud (celý systém)</translation>
<translation id="541416427766103491">OdkladaÄ Ä. 4</translation>
<translation id="5421136146218899937">Vymazať dáta prehliadania…</translation>
<translation id="5426179911063097041">Web <ph name="SITE" /> vám chce posielať upozornenia</translation>
@@ -1187,6 +1221,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="5455374756549232013">Chybná Äasová peÄiatka pravidla</translation>
<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="5463625433003343978">Hľadajú sa zariadenia…</translation>
<translation id="5469868506864199649">TalianÄina</translation>
<translation id="5470861586879999274">&amp;Znova upraviť</translation>
<translation id="5478437291406423475">B6/C4 (obálka)</translation>
@@ -1236,7 +1271,6 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="5624120631404540903">Správa hesiel</translation>
<translation id="5629630648637658800">Nastavenia pravidla sa nepodarilo naÄítaÅ¥</translation>
<translation id="5631439013527180824">Neplatný token správy zariadenia</translation>
-<translation id="5632627355679805402">Údaje boli <ph name="TIME" /> zašifrované vaším <ph name="BEGIN_LINK" />heslom Google<ph name="END_LINK" />. Synchronizácia sa spustí po jeho zadaní.</translation>
<translation id="5633066919399395251">ÚtoÄníci na webe <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> sa môžu pokúsiÅ¥ nainÅ¡talovaÅ¥ nebezpeÄné programy vo vaÅ¡om poÄítaÄi, 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>
<translation id="563324245173044180">Klamlivý obsah bol zablokovaný.</translation>
<translation id="5644090287519800334">Posun obrázka strany Ä. 1 na osi X</translation>
@@ -1275,12 +1309,12 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="5785756445106461925">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 vzhľad stránky.</translation>
<translation id="5786044859038896871">Chcete vyplniť informácie o karte?</translation>
<translation id="578633867165174378">Chrome naÅ¡iel heslo, ktoré ste práve použili, v zozname hesiel odhalených pri poruÅ¡ení ochrany údajov. OdporúÄame, aby ste si ho okamžite zmenili.</translation>
-<translation id="5798290721819630480">Chcete zahodiť zmeny?</translation>
<translation id="5803412860119678065">Chcete vyplniť informácie o karte <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Povolenia</translation>
<translation id="5804427196348435412">Používať zariadenia s technológiou NFC</translation>
<translation id="5810442152076338065">Vaše pripojenie k doméne <ph name="DOMAIN" /> je šifrované pomocou zastaranej šifrovacej súpravy.</translation>
<translation id="5813119285467412249">&amp;Znova pridať</translation>
+<translation id="5817918615728894473">Párovať</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Na túto kartu sa pri platbe zaúÄtuje poplatok, ale jej skutoÄné Äíslo sa nebude s týmto webom zdieľaÅ¥. Na zaistenie dodatoÄného zabezpeÄenia bude vygenerovaný doÄasný overovací kód karty.}few{Na kartu, ktorú vyberiete, sa pri platbe zaúÄtuje poplatok, ale jej skutoÄné Äíslo sa nebude s týmto webom zdieľaÅ¥. Na zaistenie dodatoÄného zabezpeÄenia bude vygenerovaný doÄasný overovací kód karty.}many{Na kartu, ktorú vyberiete, sa pri platbe zaúÄtuje poplatok, ale jej skutoÄné Äíslo sa nebude s týmto webom zdieľaÅ¥. Na zaistenie dodatoÄného zabezpeÄenia bude vygenerovaný doÄasný overovací kód karty.}other{Na kartu, ktorú vyberiete, sa pri platbe zaúÄtuje poplatok, ale jej skutoÄné Äíslo sa nebude s týmto webom zdieľaÅ¥. Na zaistenie dodatoÄného zabezpeÄenia bude vygenerovaný doÄasný overovací kód karty.}}</translation>
<translation id="5826507051599432481">Bežný názov (CN)</translation>
<translation id="5838278095973806738">Na tomto webe by ste nemali zadávaÅ¥ citlivé údaje, napríklad heslá alebo kreditné karty, pretože by ich mohli ukradnúť útoÄníci.</translation>
@@ -1288,6 +1322,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="5855253129151731373">Zdá sa, že názov hostiteľa tohto webu sa podobá doméne <ph name="LOOKALIKE_DOMAIN" />. ÚtoÄníci niekedy weby napodobňujú tak, že v názve domény vykonajú drobné, Å¥ažko odhaliteľné zmeny.
Ak sa domnievate, že toto upozornenie sa zobrazuje omylom, prejdite na https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Vypnuté</translation>
<translation id="5862579898803147654">OdkladaÄ Ä. 8</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>
@@ -1304,6 +1339,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="5913377024445952699">Snímanie obrazovky bolo pozastavené</translation>
<translation id="59174027418879706">Povolené</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{Používa sa 1}few{Používajú sa #}many{Používa sa #}other{Používa sa #}}</translation>
<translation id="5921185718311485855">zapnuté</translation>
<translation id="5921639886840618607">Chcete uložiÅ¥ kartu do úÄtu Google?</translation>
<translation id="5922853866070715753">Takmer dokonÄené</translation>
@@ -1323,6 +1359,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="5989320800837274978">Nie sú urÄené pevne dané servery proxy ani skript PAC webovej adresy.</translation>
<translation id="5992691462791905444">Inžiniersky záhyb v tvare písmena Z</translation>
<translation id="6000758707621254961">Viacero výsledkov (<ph name="RESULT_COUNT" />) pre hľadaný výraz „<ph name="SEARCH_TEXT" />“</translation>
+<translation id="6006484371116297560">Klasický</translation>
<translation id="6008122969617370890">Poradie N až 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Kontrola hesiel</translation>
@@ -1344,6 +1381,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="6045164183059402045">Šablóna zavedenia</translation>
<translation id="6047233362582046994">Ak si uvedomujete bezpeÄnostné riziko, môžete <ph name="BEGIN_LINK" />tento web navÅ¡tíviÅ¥<ph name="END_LINK" /> eÅ¡te skôr, ako budú Å¡kodlivé aplikácie odstránené.</translation>
<translation id="6047927260846328439">Tento obsah sa vás môže podvodom pokúsiÅ¥ presvedÄiÅ¥, aby ste si nainÅ¡talovali softvér alebo poskytli osobné informácie. <ph name="BEGIN_LINK" />Napriek tomu zobraziÅ¥<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Pridržaním klávesa |<ph name="ACCELERATOR" />| ukonÄite režim celej obrazovky</translation>
<translation id="6049488691372270142">DoruÄenie strany</translation>
<translation id="6051221802930200923">Web <ph name="SITE" /> momentálne nemôžete navÅ¡tíviÅ¥, pretože používa pripínanie certifikátov. Chyby siete a útoky sú zvyÄajne doÄasné, takže by táto stránka mala neskôr pravdepodobne fungovaÅ¥.</translation>
<translation id="6051898664905071243">PoÄet strán:</translation>
@@ -1360,6 +1398,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<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>
<translation id="6116338172782435947">Prístup k textu a obrázkom skopírovaným do schránky</translation>
<translation id="6120179357481664955">Chcete uložiť svoj identifikátor UPI?</translation>
+<translation id="6123290840358279103">Zobraziť virtuálnu kartu</translation>
<translation id="6124432979022149706">Konektory Chrome Enterprise</translation>
<translation id="6146055958333702838">Skontrolujte vÅ¡etky káble a reÅ¡tartujte vÅ¡etky používané smerovaÄe, modemy alebo iné sieÅ¥ové zariadenia.</translation>
<translation id="614940544461990577">Vyskúšajte:</translation>
@@ -1395,6 +1434,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="6289939620939689042">Farba stránky</translation>
<translation id="6290238015253830360">Tu sa zobrazia vaÅ¡e navrhované Älánky</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Zastavuje sa Asistent Google v Chrome</translation>
<translation id="6305205051461490394">Web <ph name="URL" /> je nedostupný.</translation>
<translation id="6312113039770857350">Webová stránka nie je k dispozícii</translation>
@@ -1420,6 +1460,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="6390200185239044127">Záhyb v tvare písmena Z v polovici</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Prilepenie zo zdroja <ph name="ORIGIN_NAME" /> na toto miesto je blokované pravidlami správcu</translation>
+<translation id="6398765197997659313">UkonÄiÅ¥ zobrazenie na celú obrazovku</translation>
<translation id="6401136357288658127">Podpora tohto pravidla bola ukonÄená. Namiesto neho použite pravidlo <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Upraviť záložku</translation>
<translation id="6406765186087300643">C0 (obálka)</translation>
@@ -1432,7 +1473,6 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="6428450836711225518">Overenie telefónneho Äísla</translation>
<translation id="6433490469411711332">Úprava kontaktných informácií</translation>
<translation id="6433595998831338502">Web <ph name="HOST_NAME" /> zamietol pripojenie.</translation>
-<translation id="6434309073475700221">Zahodiť</translation>
<translation id="6440503408713884761">Ignorované</translation>
<translation id="6443406338865242315">Ktoré rozšírenia a doplnky máte nainštalované</translation>
<translation id="6446163441502663861">Kahu (obálka)</translation>
@@ -1475,6 +1515,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<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="6630043285902923878">Hľadajú sa zariadenia USB…</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>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Vymazať</translation>
@@ -1490,6 +1531,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<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="6687335167692595844">Bola vyžiadaná veľkosť písma</translation>
+<translation id="6688743156324860098">Aktualizovať…</translation>
<translation id="6689249931105087298">Relatívne s kompresiou Äierneho bodu</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="6698381487523150993">Vytvorené:</translation>
@@ -1505,6 +1547,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<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="6753269504797312559">Hodnota pravidla</translation>
<translation id="6757797048963528358">Vaše zariadenie prešlo do režimu spánku.</translation>
+<translation id="6767985426384634228">Chcete adresu aktualizovať?</translation>
<translation id="6768213884286397650">Hagaki (pohľadnica)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Fialová</translation>
@@ -1527,6 +1570,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome zjednoduÅ¡il túto stránku, aby sa dala ľahÅ¡ie preÄítaÅ¥. Chrome naÄítal pôvodnú stránku cez nezabezpeÄené pripojenie.</translation>
<translation id="6891596781022320156">Úroveň pravidla nie je podporovaná.</translation>
+<translation id="6895143722905299846">Virtuálne Äíslo:</translation>
<translation id="6895330447102777224">Vaša karta je overená</translation>
<translation id="6897140037006041989">Používateľský agent</translation>
<translation id="6898699227549475383">Organizácia (O)</translation>
@@ -1562,10 +1606,10 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="7004583254764674281">Potvrdzujte karty rýchlejšie pomocou služby Windows Hello</translation>
<translation id="7006930604109697472">Aj tak odoslať</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Nastavenia zmeny veľkosti</translation>
<translation id="7014741021609395734">Úroveň lupy</translation>
<translation id="7016992613359344582">Tieto poplatky môžu byť jednorazové alebo opakované a nemusia byť predvídateľné.</translation>
<translation id="7029809446516969842">Heslá</translation>
+<translation id="7030436163253143341">Certifikát je neplatný</translation>
<translation id="7031646650991750659">Ktoré aplikácie Google Play máte nainštalované.</translation>
<translation id="7050187094878475250">Pokúsili ste sa prejsť do domény <ph name="DOMAIN" />, ale server udelil certifikát, ktorého obdobie platnosti je príliš dlhé, a preto nie je dôveryhodný</translation>
<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>
@@ -1635,12 +1679,14 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="7300012071106347854">Kobaltová modrá</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />“</translation>
<translation id="7304030187361489308">Vysoký</translation>
+<translation id="7305756307268530424">Pomalšie</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Pomocník s pripojením</translation>
<translation id="7323804146520582233">Skryť sekciu <ph name="SECTION" /></translation>
<translation id="733354035281974745">Prekonanie miestneho úÄtu zariadenia</translation>
<translation id="7333654844024768166">Práve ste zadali svoje heslo na podvodnom webe. Chromium odporúÄa, aby ste preÅ¡li na <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> a ÄalÅ¡ie weby, kde používate toto heslo, a ihneÄ ho zmenili.</translation>
<translation id="7334320624316649418">&amp;Znova zmeniť poradie</translation>
+<translation id="7337248890521463931">Zobraziť viac riadkov</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>
@@ -1648,6 +1694,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Príkazový riadok</translation>
<translation id="7359588939039777303">Reklamy sú blokované.</translation>
+<translation id="7363096869660964304">Nie ste však neviditeľný/-á. Prejdením do režimu inkognito neskryjete svoje prehliadanie pred zamestnávateľom, poskytovateľom internetových služieb ani pred navštívenými webmi.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, postupným stlaÄením klávesov Tab a Enter môžete v nastaveniach Chromu pridávaÅ¥ a spravovaÅ¥ adresy</translation>
<translation id="7365849542400970216">PovoliÅ¥ zistiÅ¥, Äi používate svoje zariadenie?</translation>
<translation id="7372973238305370288">výsledok vyhľadávania</translation>
@@ -1658,7 +1705,9 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="7378594059915113390">Ovládacie prvky médií</translation>
<translation id="7378627244592794276">Nie</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Nedá sa použiť</translation>
<translation id="7390545607259442187">Overenie karty</translation>
+<translation id="7392089738299859607">Aktualizácia adresy</translation>
<translation id="7399802613464275309">Kontrola bezpeÄnosti</translation>
<translation id="7400418766976504921">Webová adresa</translation>
<translation id="7403591733719184120">Zariadenie <ph name="DEVICE_NAME" /> je spravované</translation>
@@ -1673,6 +1722,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
&lt;li&gt;ÄŽalÅ¡ie informácie o tom, ako natrvalo odstrániÅ¥ softvér z poÄítaÄa, nájdete v &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;centre pomoci Chromu&lt;/a&gt;.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Široký formát</translation>
+<translation id="7410471291937727359">Krásne</translation>
<translation id="7416351320495623771">Spravovať heslá…</translation>
<translation id="7419106976560586862">Cesta profilu</translation>
<translation id="7437289804838430631">Pridať kontaktné informácie</translation>
@@ -1688,7 +1738,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="7481312909269577407">Dopredu</translation>
<translation id="7485870689360869515">Nenašli sa žiadne údaje.</translation>
<translation id="7495528107193238112">Tento obsah je blokovaný. Kontaktujte vlastníka webu a požiadajte ho odstránenie daného problému.</translation>
-<translation id="7498234416455752244">PokraÄovaÅ¥ v úprave</translation>
+<translation id="7498193950643227031">Po zmene veľkosti sa môže správaÅ¥ neoÄakávane. V sekcii <ph name="SETTINGS" /> teraz môžete obmedziÅ¥ možnosÅ¥ meniÅ¥ veľkosÅ¥ aplikácii.</translation>
<translation id="7503664977220660814">Práve ste zadali svoje heslo na podvodnom webe. Chromium odporúÄa, aby ste skontrolovali svoje uložené heslá pre <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> a ÄalÅ¡ie weby, na ktorých ho momentálne používate.</translation>
<translation id="7508255263130623398">Identifikátor zariadenia vráteného v rámci záruky je prázdny alebo sa nezhoduje s identifikátorom aktuálneho zariadenia</translation>
<translation id="7508870219247277067">Žltozelená</translation>
@@ -1708,6 +1758,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<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="755279583747225797">Skúšobné obdobie je aktívne</translation>
<translation id="7552846755917812628">Vyskúšajte nasledujúce tipy:</translation>
<translation id="7554475479213504905">Znova naÄítaÅ¥ a aj tak zobraziÅ¥</translation>
<translation id="7554791636758816595">Nová karta</translation>
@@ -1726,7 +1777,6 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, postupným stlaÄením klávesov Tab a Enter môžete zobraziÅ¥ a spravovaÅ¥ heslá v nastaveniach Chromu</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="7616645509853975347">Správca vypol vo vaÅ¡om prehliadaÄi Chrome Enterprise Connectors. Tieto konektory majú prístup k niektorým vaÅ¡im údajom.</translation>
<translation id="7619838219691048931">Koncový hárok</translation>
<translation id="762844065391966283">Jednotlivo</translation>
@@ -1791,13 +1841,12 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="782886543891417279">Sieť Wi‑Fi (<ph name="WIFI_NAME" />), ktorú používate, môže vyžadovať, aby ste navštívili jej prihlasovaciu stránku</translation>
<translation id="7836231406687464395">Postfix (obálka)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Žiadne}=1{1 aplikácia (<ph name="EXAMPLE_APP_1" />)}=2{2 aplikácie (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}few{# aplikácie (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}many{# apps (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# aplikácií (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Nie ste však neviditeľný/-á. Prejdením do režimu inkognito neskryjete svoje prehliadanie pred zamestnávateľom, poskytovateľom internetových služieb ani pred navštívenými webmi.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Otvárať súbory so spojenými typmi súborov.</translation>
<translation id="7862185352068345852">Chcete odísť z tohto webu?</translation>
<translation id="7865448901209910068">Najlepšia rýchlosť</translation>
<translation id="7874263914261512992">Práve ste zadali svoje heslo na podvodnom webe. Chrome odporúÄa, aby ste skontrolovali svoje uložené heslá pre <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> a ÄalÅ¡ie weby, na ktorých ho momentálne používate.</translation>
<translation id="7878562273885520351">Vaše heslo mohlo byť napadnuté</translation>
+<translation id="7880146494886811634">Uloženie adresy</translation>
<translation id="7882421473871500483">Hnedá</translation>
<translation id="7887683347370398519">Skontrolujte svoj kód CVC a skúste to znova</translation>
<translation id="7887885240995164102">Spustiť obraz v obraze</translation>
@@ -1805,6 +1854,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="7894280532028510793">Ak je pravopis správny, <ph name="BEGIN_LINK" />skúste spustiť nástroj Network Diagnostics<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (obálka)</translation>
<translation id="7931318309563332511">Neznámy</translation>
+<translation id="793209273132572360">Chcete aktualizovať adresu?</translation>
<translation id="7932579305932748336">Naniesť povrchovú vrstvu</translation>
<translation id="79338296614623784">Zadajte platné telefónne Äíslo</translation>
<translation id="7934052535022478634">Platba sa uskutoÄnila</translation>
@@ -1875,6 +1925,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="8175796834047840627">Chrome poskytuje možnosÅ¥ uložiÅ¥ karty v úÄte Google, pretože ste sa prihlásili. Toto správanie môžete zmeniÅ¥ v nastaveniach.</translation>
<translation id="8176440868214972690">Správca tohto zariadenia odoslal na nasledujúce weby nejaké informácie, napríklad nastavenia alebo pravidlá.</translation>
<translation id="8184538546369750125">Použiť predvolené všeobecné nastavenie (Povoliť)</translation>
+<translation id="8193086767630290324">Akcie vykonané s údajmi oznaÄenými ako dôvernými</translation>
<translation id="8194797478851900357">&amp;Vrátiť späť presunutie</translation>
<translation id="8201077131113104583">Neplatná webová adresa aktualizácie pre rozšírenie s ID <ph name="EXTENSION_ID" />.</translation>
<translation id="8202097416529803614">Súhrn objednávky</translation>
@@ -1897,6 +1948,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="8249296373107784235">Prerušiť</translation>
<translation id="8249320324621329438">Naposledy naÄítané:</translation>
<translation id="8253091569723639551">FakturaÄná adresa je povinná</translation>
+<translation id="8257387598443225809">Táto aplikácia je urÄená pre mobilné zariadenia</translation>
<translation id="825929999321470778">Zobraziť všetky uložené heslá</translation>
<translation id="8261506727792406068">Odstrániť</translation>
<translation id="8262952874573525464">Zošiť hrebeňovou väzbou dole</translation>
@@ -2021,7 +2073,6 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="8719528812645237045">Viacero dierok hore</translation>
<translation id="8725066075913043281">Skúsiť znova</translation>
<translation id="8726549941689275341">Veľkosť strany:</translation>
-<translation id="8728672262656704056">Ste v režime inkognito</translation>
<translation id="8730621377337864115">Hotovo</translation>
<translation id="8731544501227493793">TlaÄidlo SpravovaÅ¥ heslá. StlaÄením klávesa Enter môžete heslá zobraziÅ¥ a spravovaÅ¥ v nastaveniach Chromu.</translation>
<translation id="8734529307927223492">Vaše zariadenie <ph name="DEVICE_TYPE" /> spravuje <ph name="MANAGER" /></translation>
@@ -2098,6 +2149,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="9020542370529661692">Táto stránka bola preložená do jazyka <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Neplatný)</translation>
+<translation id="9030265603405983977">ÄŒiernobiele</translation>
<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>
@@ -2121,6 +2173,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="91108059142052966">KeÄ je viditeľný dôverný obsah, pravidlá správcu deaktivujú zdieľanie obrazovky pomocou aplikácie <ph name="APPLICATION_TITLE" /></translation>
<translation id="9114524666733003316">Overuje sa karta…</translation>
<translation id="9114581008513152754">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="9117930699067497412">Príjemné</translation>
<translation id="9119042192571987207">Nahrané</translation>
<translation id="9128016270925453879">NaÄítavajú sa pravidlá</translation>
<translation id="9128870381267983090">Pripojiť k sieti</translation>
@@ -2139,6 +2192,7 @@ Ich používanie by bolo inak blokované vašimi nastaveniami ochrany súkromia.
<translation id="9170848237812810038">&amp;Naspäť</translation>
<translation id="9171296965991013597">Opustiť aplikáciu?</translation>
<translation id="9173282814238175921">Jeden dokument alebo nový hárok</translation>
+<translation id="9173995187295789444">Vyhľadávajú sa zariadenia Bluetooth...</translation>
<translation id="917450738466192189">Certifikát servera je neplatný.</translation>
<translation id="9174917557437862841">TlaÄidlo na prepnutie karty, stlaÄením klávesa Enter prepnite na túto kartu</translation>
<translation id="9179703756951298733">Spravovať platby a informácie o kreditných kartách v nastaveniach Chromu</translation>
diff --git a/chromium/components/strings/components_strings_sl.xtb b/chromium/components/strings/components_strings_sl.xtb
index 60a3e253b2b..51b8c60bad0 100644
--- a/chromium/components/strings/components_strings_sl.xtb
+++ b/chromium/components/strings/components_strings_sl.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Če je izbrana ta možnost, bo shranil kopijo kartice v tej napravi za hitrejše izpolnjevanje obrazcev.</translation>
<translation id="1110994991967754504">Izbira dovoljenja za: <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Razveljavi razvrstitev</translation>
+<translation id="1123753900084781868">Samodejni podnapisi trenutno niso na voljo</translation>
<translation id="1125573121925420732">Medtem ko spletne strani posodabljajo varnost, se lahko opozorila pogosto prikažejo. To se bo kmalu izboljšalo.</translation>
<translation id="112840717907525620">Predpomnilnik pravilnika ustrezen</translation>
<translation id="1130564665089811311">Gumb za prevajanje strani, pritisnite Enter, Äe želite prevesti to stran z Google Prevajalnikom</translation>
@@ -74,6 +75,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="1240347957665416060">Ime vaše naprave</translation>
<translation id="124116460088058876">VeÄ jezikov</translation>
<translation id="1243027604378859286">Avtor:</translation>
+<translation id="1246424317317450637">Krepko</translation>
<translation id="1250759482327835220">ÄŒe želite naslednjiÄ hitreje plaÄati, shranite kartico, ime in naslov za izstavitev raÄuna v Google RaÄunu.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sinhronizirano)</translation>
<translation id="1256368399071562588">&lt;p&gt;Če poskušate obiskati spletno mesto in se ne odpre, napako najprej poskusite odpraviti s tem postopkom za odpravljanje težav:&lt;/p&gt;
@@ -156,6 +158,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="1476595624592550506">Spremenite geslo</translation>
<translation id="1484290072879560759">Izbira naslova za pošiljanje</translation>
<translation id="1492194039220927094">Potiskanje pravilnikov:</translation>
+<translation id="1495677929897281669">Nazaj na zavihek</translation>
<translation id="1501859676467574491">Prikaz kartic iz Google RaÄuna</translation>
<translation id="1507202001669085618">&lt;p&gt;Ta napaka se prikaže, Äe uporabljate portal Wi-Fi, ki pred uporabo spleta zahteva prijavo.&lt;/p&gt;
&lt;p&gt;Napravo odpravite tako, da na strani, ki jo poskušate odpreti, kliknete &lt;strong&gt;Poveži&lt;/strong&gt;.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="1532118530259321453">Ta stran sporoÄa:</translation>
<translation id="153384715582417236">To je vse za zdaj</translation>
<translation id="1536390784834419204">Prevedi stran</translation>
+<translation id="1539840569003678498">Poslano poroÄilo:</translation>
<translation id="154408704832528245">Izbira naslova za dostavo</translation>
<translation id="1549470594296187301">ÄŒe želite uporabljati to funkcijo, mora biti omogoÄen JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="1682696192498422849">Najprej kratki rob</translation>
<translation id="168693727862418163">Preverjanje vrednosti tega pravilnika v skladu z njegovo shemo ni uspelo in bo prezrta.</translation>
<translation id="168841957122794586">Potrdilo strežnika vsebuje Å¡ibek Å¡ifrirni kljuÄ.</translation>
+<translation id="1696290444144917273">Ogled podrobnosti navidezne kartice</translation>
<translation id="1697532407822776718">Pripravljeni ste.</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Strežniku ni uspelo dokazati, da je domena <ph name="DOMAIN" />; njegovo varnostno potrdilo naj bi imelo jutriÅ¡nji datum. Razlog za to je lahko napaÄna konfiguracija ali napadalÄevo prestrezanje povezave.}one{Strežniku ni uspelo dokazati, da je domena <ph name="DOMAIN" />; njegovo varnostno potrdilo naj bi imelo datum v prihodnosti – # dan od danes. Razlog za to je lahko napaÄna konfiguracija ali napadalÄevo prestrezanje povezave.}two{Strežniku ni uspelo dokazati, da je domena <ph name="DOMAIN" />; njegovo varnostno potrdilo naj bi imelo datum v prihodnosti – # dneva od danes. Razlog za to je lahko napaÄna konfiguracija ali napadalÄevo prestrezanje povezave.}few{Strežniku ni uspelo dokazati, da je domena <ph name="DOMAIN" />; njegovo varnostno potrdilo naj bi imelo datum v prihodnosti – # dni od danes. Razlog za to je lahko napaÄna konfiguracija ali napadalÄevo prestrezanje povezave.}other{Strežniku ni uspelo dokazati, dokazati, da je domena <ph name="DOMAIN" />; njegovo varnostno potrdilo naj bi imelo datum v prihodnosti – # dni od danes. Razlog za to je lahko napaÄna konfiguracija ali napadalÄevo prestrezanje povezave.}}</translation>
<translation id="1710259589646384581">Operacijski sistem</translation>
+<translation id="1711234383449478798">Prezrto, ker pravilnik <ph name="POLICY_NAME" /> ni nastavljen na vrednost <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> želi trajno shraniti podatke v lokalnem raÄunalniku</translation>
<translation id="1713628304598226412">Pladenj 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Nabiralnik 3</translation>
<translation id="1718029547804390981">Dokument je prevelik, da bi mu dodali pripise</translation>
<translation id="1721424275792716183">*Polje je obvezno</translation>
+<translation id="1727613060316725209">Potrdilo je veljavno</translation>
<translation id="1727741090716970331">Dodajanje veljavne Å¡tevilke kartice</translation>
<translation id="1728677426644403582">Ogledujete si izvorno kodo spletne strani</translation>
<translation id="173080396488393970">Ta vrsta kartice ni podprta</translation>
@@ -246,7 +253,6 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
izpolniti vaše zahteve za <ph name="SITE" />. Pravilnike izvora lahko uporabljajo
ponudniki spletnih mest zaradi konfiguriranja varnosti in drugih lastnosti spletnega mesta.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Posodobite geslo za sinhronizacijo.</translation>
<translation id="1787142507584202372">Tu so prikazani odprti zavihki</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, na voljo je veÄ dejanj, pritisnite tabulatorko, Äe želite krožiti po njih</translation>
@@ -279,6 +285,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="1919345977826869612">Oglasi</translation>
<translation id="1919367280705858090">PomoÄ pri doloÄenem sporoÄilu o napaki</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Brez}=1{1 spletno mesto}one{# spletno mesto}two{# spletni mesti}few{# spletna mesta}other{# spletnih mest}}</translation>
+<translation id="1924727005275031552">Novo</translation>
<translation id="1945968466830820669">Izgubite lahko dostop do raÄuna za organizacijo ali postanete žrtev kraje identitete. Chromium priporoÄa, da spremenite geslo.</translation>
<translation id="1947454675006758438">Spenjanje zgoraj desno</translation>
<translation id="1958218078413065209">Vaš najboljši rezultat je <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="2042213636306070719">Pladenj 7</translation>
<translation id="204357726431741734">Prijavite se, Äe želite uporabljati gesla, shranjena v raÄunu Google</translation>
<translation id="2053111141626950936">Strani v jeziku <ph name="LANGUAGE" /> ne bodo prevedene.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{ÄŒe je ta kontrolnik vklopljen in stanje aktivno, Chrome doloÄi, kateri veliki skupini oseb ali »kohorti« je vaÅ¡a nedavna dejavnost brskanja najbolj podobna. Izdajatelji lahko izberejo oglase za skupino in vaÅ¡a dejavnost brskanja je zasebna v napravi. Skupina se posodobi vsak dan.}=1{ÄŒe je ta kontrolnik vklopljen in stanje aktivno, Chrome doloÄi, kateri veliki skupini oseb ali »kohorti« je vaÅ¡a nedavna dejavnost brskanja najbolj podobna. Izdajatelji lahko izberejo oglase za skupino in vaÅ¡a dejavnost brskanja je zasebna v napravi. Skupina se posodobi vsak dan.}one{ÄŒe je ta kontrolnik vklopljen in stanje aktivno, Chrome doloÄi, kateri veliki skupini oseb ali »kohorti« je vaÅ¡a nedavna dejavnost brskanja najbolj podobna. Izdajatelji lahko izberejo oglase za skupino in vaÅ¡a dejavnost brskanja je zasebna v napravi. Skupina se posodobi vsak {NUM_DAYS} dan.}two{ÄŒe je ta kontrolnik vklopljen in stanje aktivno, Chrome doloÄi, kateri veliki skupini oseb ali »kohorti« je vaÅ¡a nedavna dejavnost brskanja najbolj podobna. Izdajatelji lahko izberejo oglase za skupino in vaÅ¡a dejavnost brskanja je zasebna v napravi. Skupina se posodobi vsak {NUM_DAYS} dneva.}few{ÄŒe je ta kontrolnik vklopljen in stanje aktivno, Chrome doloÄi, kateri veliki skupini oseb ali »kohorti« je vaÅ¡a nedavna dejavnost brskanja najbolj podobna. Izdajatelji lahko izberejo oglase za skupino in vaÅ¡a dejavnost brskanja je zasebna v napravi. Skupina se posodobi vsak {NUM_DAYS} dni.}other{ÄŒe je ta kontrolnik vklopljen in stanje aktivno, Chrome doloÄi, kateri veliki skupini oseb ali »kohorti« je vaÅ¡a nedavna dejavnost brskanja najbolj podobna. Izdajatelji lahko izberejo oglase za skupino in vaÅ¡a dejavnost brskanja je zasebna v napravi. Skupina se posodobi vsak {NUM_DAYS} dni.}}</translation>
<translation id="2053553514270667976">Poštna številka</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 predlog}one{# predlog}two{# predloga}few{# predlogi}other{# predlogov}}</translation>
<translation id="2071692954027939183">Obvestila so bila samodejno blokirana, ker jih obiÄajno ne dovolite.</translation>
<translation id="2079545284768500474">Razveljavi</translation>
<translation id="20817612488360358">Za uporabo so nastavljene sistemske nastavitve strežnika proxy, vendar je navedena tudi izrecna konfiguracija proxyja.</translation>
<translation id="2082238445998314030"><ph name="RESULT_NUMBER" />. rezultat od <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Shrani …</translation>
<translation id="2088086323192747268">Gumb za upravljanje sinhronizacije, pritisnite Enter, Äe želite upravljati, kateri podatki se sinhronizirajo v Chromovih nastavitvah.</translation>
<translation id="2091887806945687916">Zvok</translation>
<translation id="2094505752054353250">Neujemanje domen</translation>
@@ -379,6 +388,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="2317259163369394535">Domena <ph name="DOMAIN" /> zahteva uporabniško ime in geslo.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, poteÄe <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Nastavitev nadzira vaš skrbnik</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> želi izvesti seznanitev</translation>
<translation id="2344028582131185878">Samodejni prenosi</translation>
<translation id="2346319942568447007">Slika, ki ste jo kopirali</translation>
<translation id="2354001756790975382">Drugi zaznamki</translation>
@@ -386,8 +396,10 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="2355395290879513365">Napadalci morda vidijo slike, ki si jih ogledujete na tem spletnem mestu, in vas ukanijo, tako da jih spremenijo.</translation>
<translation id="2356070529366658676">Vprašaj</translation>
<translation id="2357481397660644965">VaÅ¡o napravo upravlja domena <ph name="DEVICE_MANAGER" /> in vaÅ¡ raÄun upravlja domena <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ÄŒez manj kot en dan}=1{ÄŒez en dan}one{ÄŒez {NUM_DAYS} dan}two{ÄŒez {NUM_DAYS} dneva}few{ÄŒez {NUM_DAYS} dni}other{ÄŒez {NUM_DAYS} dni}}</translation>
<translation id="2359629602545592467">VeÄ valut</translation>
<translation id="2359808026110333948">Naprej</translation>
+<translation id="2359961752320758691">Å tevilka virtualne kartice je uporabljena.</translation>
<translation id="2367567093518048410">Raven</translation>
<translation id="2372464001869762664">Ko potrdite, bodo temu spletnemu mestu razkriti podatki o kartici iz raÄuna Google. Med podatki za raÄun Plex poiÅ¡Äite kodo CVC.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="239429038616798445">Ta naÄin poÅ¡iljanja ni na voljo. Poskusite uporabiti drugega.</translation>
<translation id="2396249848217231973">&amp;Razveljavi izbris</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Staro</translation>
<translation id="2413528052993050574">Strežniku ni uspelo dokazati, da je <ph name="DOMAIN" />; njegovo varnostno potrdilo je bilo morda preklicano. Razlog za to je lahko napaÄna konfiguracija ali napadalÄevo prestrezanje povezave.</translation>
<translation id="2414886740292270097">Temno</translation>
<translation id="2438874542388153331">ÄŒetverno luknjanje na desni</translation>
@@ -425,10 +438,10 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="2521385132275182522">Spenjanje spodaj desno</translation>
<translation id="2523886232349826891">Shranjena samo v tej napravi</translation>
<translation id="2524461107774643265">Dodajanje veÄ podatkov</translation>
-<translation id="2526590354069164005">Namizje</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{in Å¡e 1}one{in Å¡e #}two{in Å¡e #}few{in Å¡e #}other{in Å¡e #}}</translation>
<translation id="2536110899380797252">Dodaj naslov</translation>
<translation id="2539524384386349900">Zaznava</translation>
+<translation id="2541219929084442027">Strani, ki si jih ogledujete na anonimnih zavihkih, se ne bodo ohranile v zgodovini brskalnika, hrambi piškotkov ali zgodovini iskanja, ko boste zaprli vse anonimne zavihke. Datoteke, ki jih prenesete, ali zaznamki, ki jih ustvarite, se bodo ohranili.</translation>
<translation id="2544644783021658368">Enojni dokument</translation>
<translation id="254947805923345898">Vrednost pravilnika ni veljavna.</translation>
<translation id="255002559098805027">Spletno mesto <ph name="HOST_NAME" /> je poslalo neveljaven odgovor.</translation>
@@ -448,6 +461,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="2629325967560697240">ÄŒe želite imeti Chromovo najveÄjo raven varnosti, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />vklopite izboljÅ¡ano zaÅ¡Äito<ph name="END_ENHANCED_PROTECTION_LINK" />.</translation>
<translation id="2634124572758952069">Naslova IP strežnika <ph name="HOST_NAME" /> ni bilo mogoÄe najti.</translation>
<translation id="2639739919103226564">Stanje:</translation>
+<translation id="264810637653812429">Najdena ni bila nobena združljiva naprava.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite tabulatorko, nato Enter, Äe želite izbrisati zgodovino brskanja, piÅ¡kotke, predpomnilnik in drugo v Chromovih nastavitvah</translation>
<translation id="2650446666397867134">Dostop do datoteke je bil zavrnjen</translation>
@@ -494,6 +508,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<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="2807052079800581569">Položaj Y slike</translation>
+<translation id="2820957248982571256">Iskanje ...</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>
@@ -501,6 +516,8 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">To spletno mesto prikazuje vsiljive ali zavajajoÄe oglase.</translation>
+<translation id="287596039013813457">Prijateljsko</translation>
+<translation id="2876489322757410363">Zaradi plaÄila v zunanji aplikaciji boste zapustili anonimni naÄin. Želite nadaljevati?</translation>
<translation id="2878197950673342043">Prepogibanje v obliki plakata</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Postavitev oken</translation>
@@ -550,7 +567,6 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite tabulatorko, nato Enter, Äe želite v nastavitvah Chroma zagnati varnostno preverjanje</translation>
<translation id="3061707000357573562">Storitev za popravke</translation>
-<translation id="3064966200440839136">Zaradi plaÄila v zunanji aplikaciji boste zapustili anonimni naÄin. Želite nadaljevati?</translation>
<translation id="306573536155379004">Igra se je zaÄela.</translation>
<translation id="3080254622891793721">GrafiÄni elementi</translation>
<translation id="3086579638707268289">Vaša dejavnost v spletu je nadzorovana</translation>
@@ -573,7 +589,6 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="315504272643575312">VaÅ¡ raÄun upravlja <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Obnovi</translation>
<translation id="3162559335345991374">Omrežje Wi-Fi, ki ga uporabljate, morda zahteva, da obiÅ¡Äete stran za prijavo.</translation>
-<translation id="3167968892399408617">Strani, ki si jih ogledujete na anonimnih zavihkih, se ne bodo ohranile v zgodovini brskalnika, hrambi piškotkov ali zgodovini iskanja, ko boste zaprli vse anonimne zavihke. Datoteke, ki jih prenesete, ali zaznamki, ki jih ustvarite, se bodo ohranili.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Otok</translation>
<translation id="3176929007561373547">Preverite nastavitve strežnika proxy ali se obrnite na skrbnika omrežja in
@@ -599,10 +614,12 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<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="3249845759089040423">Razgibano</translation>
<translation id="3252266817569339921">francoÅ¡Äina</translation>
<translation id="3266793032086590337">Vrednost (v sporu)</translation>
<translation id="3268451620468152448">Odprti zavihki</translation>
<translation id="3270847123878663523">&amp;Razveljavi razvrstitev</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> se želi povezati</translation>
<translation id="3274521967729236597">Pa Kai</translation>
<translation id="3282085321714087552">Vaša organizacija, <ph name="ENROLLMENT_DOMAIN" />, je poslala nekatere podatke, kot so nastavitve ali pravilniki, na ta spletna mesta.</translation>
<translation id="3282497668470633863">Dodajanje imena na kartico</translation>
@@ -655,6 +672,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="3428151540071562330">Eden ali veÄ URI-jev strežniÅ¡kih predlog pravilnika DnsOverHttpsTemplates je neveljaven in ne bo uporabljen.</translation>
<translation id="3431636764301398940">Shrani to kartico v tej napravi</translation>
<translation id="3432601291244612633">Zapri stran</translation>
+<translation id="3435738964857648380">Varnost</translation>
<translation id="3435896845095436175">OmogoÄi</translation>
<translation id="3438829137925142401">Uporabite gesla, shranjena v raÄunu Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="3584299510153766161">Dvojno luknjanje spodaj</translation>
<translation id="3586931643579894722">Skrij podrobnosti</translation>
<translation id="3587738293690942763">Srednje</translation>
+<translation id="3590643883886679995">Podatki za prijavo se bodo shranili v tej napravi, ko zaprete anonimni naÄin.</translation>
+<translation id="359126217934908072">Mesec/leto:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Skupino lahko kadar koli ponastavite. Pridružitev novi skupini traja približno en dan.}=1{Skupino lahko kadar koli ponastavite. Pridružitev novi skupini traja približno en dan.}one{Skupino lahko kadar koli ponastavite. Pridružitev novi skupini traja približno {NUM_DAYS} dan.}two{Skupino lahko kadar koli ponastavite. Pridružitev novi skupini traja približno {NUM_DAYS} dneva.}few{Skupino lahko kadar koli ponastavite. Pridružitev novi skupini traja približno {NUM_DAYS} dni.}other{Skupino lahko kadar koli ponastavite. Pridružitev novi skupini traja približno {NUM_DAYS} dni.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplikacijo je blokiral skrbnik</translation>
<translation id="3608932978122581043">Usmerjenost podajanja</translation>
@@ -706,13 +727,13 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="3615877443314183785">Vnesite veljaven datum poteka veljavnosti</translation>
<translation id="36224234498066874">Izbriši podatke brskanja ...</translation>
<translation id="362276910939193118">Prikaži celotno zgodovino</translation>
-<translation id="3625635938337243871">Podatki za prijavo se bodo shranili v tej napravi, ko zaprete anonimni naÄin.</translation>
<translation id="3630155396527302611">Če je že na seznamu programov, ki jim je dovoljen dostop do omrežja, ga poskusite
odstraniti s seznama in znova dodati.</translation>
<translation id="3630699740441428070">Skrbniki te naprave so konfigurirali vaÅ¡o omrežno povezavo, tako da si lahko morda ogledajo vaÅ¡ omrežni promet, vkljuÄno s tem, katera spletna mesta obiÅ¡Äete.</translation>
<translation id="3631244953324577188">Biometrika</translation>
<translation id="3633738897356909127">Gumb za posodobitev Chroma, pritisnite Enter, Äe želite posodobiti Chrome v Chromovih nastavitvah</translation>
<translation id="3634530185120165534">Pladenj 5</translation>
+<translation id="3637662659967048211">Shranjevanje v raÄun Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Program:</translation>
<translation id="3650584904733503804">Preverjanje veljavnosti uspešno</translation>
@@ -753,6 +774,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="3781428340399460090">Živo rožnata</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Naprave Bluetooth</translation>
+<translation id="3787675388804467730">Å tevilka navidezne kartice</translation>
<translation id="3787705759683870569">PoteÄe: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Velikost 16</translation>
<translation id="3789841737615482174">Namesti</translation>
@@ -772,6 +794,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="3841184659773414994">Rutine za obravnavo datotek</translation>
<translation id="385051799172605136">Nazaj</translation>
<translation id="3858027520442213535">Posodobi datum in uro</translation>
+<translation id="3881478300875776315">Pokaži manj vrstic</translation>
<translation id="3884278016824448484">Identifikator naprave je v sporu</translation>
<translation id="3885155851504623709">Župnija</translation>
<translation id="388632593194507180">Zaznano je nadzorovanje</translation>
@@ -797,6 +820,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="397105322502079400">IzraÄunavanje …</translation>
<translation id="3973234410852337861">Spletno mesto <ph name="HOST_NAME" /> je blokirano</translation>
<translation id="3973357910713125165">Gumb za zagon varnostnega preverjanja v Chromu, pritisnite Enter, Äe želite v nastavitvah Chroma zagnati varnostno preverjanje</translation>
+<translation id="3986705137476756801">Izklop samodejnih podnapisov za zdaj</translation>
<translation id="3987405730340719549">Chrome je ugotovil, da je to spletno mesto morda lažno ali goljufivo.
ÄŒe menite, da je opozorilo prikazano pomotoma, obiÅ¡Äite https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="4275830172053184480">Znova zaženite napravo.</translation>
<translation id="4277028893293644418">Ponastavi geslo</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="4287885627794386150">Ustrezno za preizkus, vendar ni aktivno.</translation>
<translation id="4297502707443874121">SliÄica za stran <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Razširi</translation>
<translation id="4300675098767811073">VeÄkratno luknjanje na desni</translation>
<translation id="4302514097724775343">Če želite igrati, se dotaknite dinozavra.</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Ni bilo mogoÄe dostopati do datoteke</translation>
-<translation id="4305817255990598646">Preklopi</translation>
+<translation id="4306529830550717874">Želite shraniti naslov?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokira (privzeto)</translation>
<translation id="4314815835985389558">Upravljanje sinhronizacije</translation>
@@ -926,6 +951,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="4377125064752653719">Poskusili ste dostopati do domene <ph name="DOMAIN" />, vendar je izdajatelj preklical potrdilo, ki ga je poslal strežnik. To pomeni, da varnostnim poverilnicam, ki jih je poslal strežnik, nikakor ne smete zaupati. Morda komunicirate z napadalcem.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Polna podlaga</translation>
+<translation id="4406883609789734330">Samodejni podnapisi</translation>
<translation id="4406896451731180161">rezultati iskanja</translation>
<translation id="4408413947728134509">Piškotki <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Pravkar ste vnesli geslo na zavajajoÄem spletnem mestu. Chrome priporoÄa, da obiÅ¡Äete <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ter druga spletna mesta, na katerih uporabljate to geslo, in ga takoj spremenite.</translation>
@@ -938,7 +964,6 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<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="4464826014807964867">Spletna mesta s podatki vaše organizacije</translation>
-<translation id="4466881336512663640">Spremembe obrazca bodo izgubljene. Ali ste prepriÄani, da želite nadaljevati?</translation>
<translation id="4476953670630786061">Ta obrazec ni varen. Samodejno izpolnjevanje je izklopljeno.</translation>
<translation id="4477350412780666475">Naslednja skladba</translation>
<translation id="4482953324121162758">To spletno mesto ne bo prevedeno.</translation>
@@ -972,6 +997,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="4594403342090139922">&amp;Razveljavi izbris</translation>
<translation id="4597348597567598915">Velikost 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">IzstopajoÄe</translation>
<translation id="4628948037717959914">Fotografija</translation>
<translation id="4631649115723685955">VkljuÄuje vraÄilo gotovine</translation>
<translation id="4636930964841734540">Informacije</translation>
@@ -991,6 +1017,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Stran</translation>
+<translation id="4702656508969495934">Samodejni podnapisi so vidni, za preklapljanje uporabite izbirnik oken</translation>
<translation id="4708268264240856090">Povezava je bila prekinjena</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Izvajanje orodja Omrežna diagnostika Windows<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="4738601419177586157">Predlog za iskanje poizvedbe <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Upravljaj gesla …</translation>
<translation id="4744603770635761495">Pot do izvedljive datoteke</translation>
+<translation id="4749011317274908093">Uporabljate anonimni naÄin</translation>
<translation id="4750917950439032686">Vaši podatki (npr. gesla ali številke kreditnih kartic) so zasebni, kadar so poslani temu spletnemu mestu.</translation>
<translation id="4756388243121344051">&amp;Zgodovina</translation>
<translation id="4758311279753947758">Dodaj podatke za stik</translation>
@@ -1033,6 +1061,8 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="4813512666221746211">Napaka v omrežju</translation>
<translation id="4816492930507672669">Prilagodi strani</translation>
<translation id="4819347708020428563">Želite urejati pripise v privzetem pogledu?</translation>
+<translation id="4825507807291741242">Zmogljivo</translation>
+<translation id="4838327282952368871">Zasanjano</translation>
<translation id="484462545196658690">Samodejno</translation>
<translation id="4850886885716139402">Pogled</translation>
<translation id="485316830061041779">nemÅ¡Äina</translation>
@@ -1169,6 +1199,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="5314967030527622926">Orodje za izdelavo knjižic</translation>
<translation id="5316812925700871227">Sukanje v nasprotni smeri urnega kazalca</translation>
<translation id="5317780077021120954">Shrani</translation>
+<translation id="5321288445143113935">PoveÄano</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> od <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Izbira podatkov za stik</translation>
<translation id="5327248766486351172">Ime</translation>
@@ -1176,11 +1207,13 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="5332219387342487447">NaÄin poÅ¡iljanja</translation>
<translation id="5333022057423422993">Chrome je geslo, ki ste ga pravkar uporabili, naÅ¡el v podatkovni krÅ¡itvi. Zaradi zavarovanja raÄunov priporoÄamo, da preverite shranjena gesla.</translation>
<translation id="5334013548165032829">Podrobni sistemski dnevniki</translation>
+<translation id="5334145288572353250">Želite shraniti naslov?</translation>
<translation id="5340250774223869109">Aplikacija je blokirana</translation>
<translation id="534295439873310000">Naprave s tehnologijo NFC</translation>
<translation id="5344579389779391559">Ta stran vam bo morda poskusila kaj zaraÄunati</translation>
<translation id="5355557959165512791">Spletnega mesta <ph name="SITE" /> trenutno ni mogoÄe obiskati, saj je to potrdilo preklicano. Napake omrežja in napadi na omrežje so obiÄajno zaÄasni, zato bo ta stran verjetno delovala pozneje.</translation>
<translation id="536296301121032821">Nastavitev pravilnika ni bilo mogoÄe shraniti</translation>
+<translation id="5363309033720083897">Serijska vrata, ki jih dovoli skrbnik</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="5386426401304769735">Veriga potrdil za to spletno mesto vsebuje potrdilo, podpisano z algoritmom SHA-1.</translation>
@@ -1189,6 +1222,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="5398772614898833570">Oglasi blokirani</translation>
<translation id="5400836586163650660">Siva</translation>
<translation id="540969355065856584">Strežniku ni uspelo dokazati, da je <ph name="DOMAIN" />; njegovo varnostno potrdilo trenutno ni veljavno. Razlog za to je lahko napaÄna konfiguracija ali napadalÄevo prestrezanje povezave.</translation>
+<translation id="541143247543991491">Oblak (za celotni sistem)</translation>
<translation id="541416427766103491">Zlagalnik 4</translation>
<translation id="5421136146218899937">Izbriši podatke brskanja ...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> vam želi pošiljati obvestila</translation>
@@ -1202,6 +1236,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="5455374756549232013">NapaÄen Äasovni žig pravilnika</translation>
<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="5463625433003343978">Iskanje naprav …</translation>
<translation id="5469868506864199649">italijanÅ¡Äina</translation>
<translation id="5470861586879999274">&amp;Uveljavi urejanje</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1251,7 +1286,6 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="5624120631404540903">Upravljanje gesel</translation>
<translation id="5629630648637658800">Nastavitev pravilnika ni bilo mogoÄe naložiti</translation>
<translation id="5631439013527180824">Neveljaven žeton za upravljanje naprave</translation>
-<translation id="5632627355679805402">VaÅ¡i podatki so bili ob <ph name="TIME" /> Å¡ifrirani z vaÅ¡im <ph name="BEGIN_LINK" />geslom za Google<ph name="END_LINK" />. ÄŒe želite zaÄeti sinhronizacijo, ga vnesite.</translation>
<translation id="5633066919399395251">Napadalci na spletnem mestu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> lahko poskusijo v vaÅ¡em raÄunalniku namestiti nevarne programe, ki kradejo ali briÅ¡ejo podatke (na primer fotografije, gesla, sporoÄila in podatke kreditnih kartic). <ph name="BEGIN_LEARN_MORE_LINK" />VeÄ o tem<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">ZavajajoÄa vsebina blokirana.</translation>
<translation id="5644090287519800334">Pomik slike na 1. strani v X</translation>
@@ -1290,12 +1324,12 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="5785756445106461925">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 videz strani.</translation>
<translation id="5786044859038896871">Ali želite izpolniti podatke kreditne kartice?</translation>
<translation id="578633867165174378">Chrome je geslo, ki ste ga pravkar uporabili, naÅ¡el v podatkovni krÅ¡itvi. PriporoÄamo, da ga takoj spremenite.</translation>
-<translation id="5798290721819630480">Želite zavreÄi spremembe?</translation>
<translation id="5803412860119678065">Ali želite izpolniti podatke za kartico <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Dovoljenja</translation>
<translation id="5804427196348435412">Uporaba naprav s tehnologijo NFC</translation>
<translation id="5810442152076338065">Povezava z domeno <ph name="DOMAIN" /> je Å¡ifrirana z zastarelo Å¡ifrirno zbirko.</translation>
<translation id="5813119285467412249">&amp;Uveljavi dodajanje</translation>
+<translation id="5817918615728894473">Seznani</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Ta kartica bo bremenjena ob plaÄilu, vendar temu spletnemu mestu ne bo razkrita njena prava Å¡tevilka. Zaradi dodatne varnosti bo ustvarjena zaÄasna Å¡tevilka CVC.}one{Izbrana kartica bo bremenjena ob plaÄilu, vendar njena prava Å¡tevilka ne bo razkrita temu spletnemu mestu. Zaradi dodatne varnosti bo ustvarjena zaÄasna Å¡tevilka CVC.}two{Izbrana kartica bo bremenjena ob plaÄilu, vendar njena prava Å¡tevilka ne bo razkrita temu spletnemu mestu. Zaradi dodatne varnosti bo ustvarjena zaÄasna Å¡tevilka CVC.}few{Izbrana kartica bo bremenjena ob plaÄilu, vendar njena prava Å¡tevilka ne bo razkrita temu spletnemu mestu. Zaradi dodatne varnosti bo ustvarjena zaÄasna Å¡tevilka CVC.}other{Izbrana kartica bo bremenjena ob plaÄilu, vendar njena prava Å¡tevilka ne bo razkrita temu spletnemu mestu. Zaradi dodatne varnosti bo ustvarjena zaÄasna Å¡tevilka CVC.}}</translation>
<translation id="5826507051599432481">ObiÄajno ime (CN)</translation>
<translation id="5838278095973806738">Na tem spletnem mestu ne vnaÅ¡ajte obÄutljivih informacij (npr. gesel ali Å¡tevilk kreditnih kartic), ker jih lahko ukradejo napadalci.</translation>
@@ -1303,6 +1337,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="5855253129151731373">Ime gostitelja tega spletnega mesta je podobno imenu <ph name="LOOKALIKE_DOMAIN" />. Napadalci vÄasih poskuÅ¡ajo posnemati spletna mesta, tako da skoraj neopazno spremenijo ime domene.
ÄŒe menite, da je opozorilo prikazano pomotoma, obiÅ¡Äite https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Izklopljeno</translation>
<translation id="5862579898803147654">Zlagalnik 8</translation>
<translation id="5863847714970149516">Stran, ki se bo odprla, vam bo morda poskusila kaj zaraÄunati</translation>
<translation id="5866257070973731571">Dodajanje telefonske Å¡tevilke</translation>
@@ -1319,6 +1354,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="5913377024445952699">ZaÄasno zaustavljeno zajemanje slike zaslona</translation>
<translation id="59174027418879706">OmogoÄeno</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 v uporabi}one{# v uporabi}two{# v uporabi}few{# v uporabi}other{# v uporabi}}</translation>
<translation id="5921185718311485855">Vklopljeno</translation>
<translation id="5921639886840618607">Ali želite kartico shraniti v Google RaÄun?</translation>
<translation id="5922853866070715753">Skoraj konÄano</translation>
@@ -1338,6 +1374,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="5989320800837274978">DoloÄeni niso ne stalni strežniki proxy ne URL skripta .pac.</translation>
<translation id="5992691462791905444">Prepogibanje v obliki harmonike z dvema zgiboma</translation>
<translation id="6000758707621254961">Rezultati za »<ph name="SEARCH_TEXT" />« (<ph name="RESULT_COUNT" />)</translation>
+<translation id="6006484371116297560">KlasiÄna</translation>
<translation id="6008122969617370890">Vrstni red N–1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Preverite gesla</translation>
@@ -1359,6 +1396,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="6045164183059402045">Predloga za razvrstitev strani za tiskanje</translation>
<translation id="6047233362582046994">ÄŒe se zavedate varnostnega tveganja, lahko <ph name="BEGIN_LINK" />obiÅ¡Äete to spletno mesto<ph name="END_LINK" />, preden bodo Å¡kodljive aplikacije odstranjene.</translation>
<translation id="6047927260846328439">Ta vsebina vas morda poskuša zavesti, da namestite programsko opremo ali razkrijete osebne podatke. <ph name="BEGIN_LINK" />Vseeno prikaži<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Pridržite |<ph name="ACCELERATOR" />| za zapiranje celozaslonskega naÄina</translation>
<translation id="6049488691372270142">Dostava strani</translation>
<translation id="6051221802930200923">Spletnega mesta <ph name="SITE" /> trenutno ni mogoÄe obiskati, ker uporablja pripenjanje potrdil. Napake omrežja in napadi na omrežje so obiÄajno zaÄasni, zato bo ta stran verjetno delovala pozneje.</translation>
<translation id="6051898664905071243">Å tevilo strani:</translation>
@@ -1375,6 +1413,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<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>
<translation id="6116338172782435947">ogled besedila in slik, kopiranih v odložiÅ¡Äe</translation>
<translation id="6120179357481664955">Si želite zapomniti ID za UPI?</translation>
+<translation id="6123290840358279103">Ogled navidezne kartice</translation>
<translation id="6124432979022149706">PrikljuÄki za Chrome za podjetja</translation>
<translation id="6146055958333702838">Preverite kable in znova zaženite usmerjevalnike, modeme ali druge omrežne
naprave, ki jih uporabljate.</translation>
@@ -1411,6 +1450,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="6289939620939689042">Barva strani</translation>
<translation id="6290238015253830360">Tu so prikazani predlagani Älanki</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">PomoÄnik Google v Chromu se ustavlja</translation>
<translation id="6305205051461490394">Naslov <ph name="URL" /> je nedosegljiv.</translation>
<translation id="6312113039770857350">Spletna stran ni na voljo</translation>
@@ -1436,6 +1476,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="6390200185239044127">Cikcakasto prepogibanje napol</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Lepljenje iz vira <ph name="ORIGIN_NAME" /> na to mesto je blokiral pravilnik skrbnika.</translation>
+<translation id="6398765197997659313">Izhod iz celozaslonskega naÄina</translation>
<translation id="6401136357288658127">Ta pravilnik je zastarel. Uporabite pravilnik <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Uredi zaznamek</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1448,7 +1489,6 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="6428450836711225518">Preverjanje telefonske Å¡tevilke</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="6440503408713884761">Prezrto</translation>
<translation id="6443406338865242315">Katere razÅ¡iritve in vtiÄnike ste namestili</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1491,6 +1531,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="6624427990725312378">Podatki o stiku</translation>
<translation id="6626291197371920147">Dodajanje veljavne Å¡tevilke kartice</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Iskanje</translation>
+<translation id="6630043285902923878">Iskanje naprav USB …</translation>
<translation id="6630809736994426279">Napadalci, ki so trenutno na spletnem mestu <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" />, lahko poskusijo v vaÅ¡em raÄunalniku Mac namestiti nevarne programe, ki kradejo ali briÅ¡ejo podatke (na primer fotografije, gesla, sporoÄila in podatke kreditnih kartic). <ph name="BEGIN_LEARN_MORE_LINK" />VeÄ o tem<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Izbriši</translation>
@@ -1506,6 +1547,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="6671697161687535275">Želite predlog obrazca odstraniti iz Chromiuma?</translation>
<translation id="6685834062052613830">Odjavite se in dokonÄajte nastavitev</translation>
<translation id="6687335167692595844">Zahtevana je velikost besedila</translation>
+<translation id="6688743156324860098">Posodobi …</translation>
<translation id="6689249931105087298">Relativno s stiskanjem Ärnih pik</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="6698381487523150993">Ustvarjeno:</translation>
@@ -1521,6 +1563,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="6744009308914054259">Med Äakanjem na povezavo lahko berete Älanke za branje brez povezave med prenosi.</translation>
<translation id="6753269504797312559">Vrednost pravilnika</translation>
<translation id="6757797048963528358">Naprava je preklopila v stanje pripravljenosti.</translation>
+<translation id="6767985426384634228">Želite posodobiti naslov?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">VijoliÄnomodra</translation>
@@ -1543,6 +1586,7 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome je prilagodil to stran za lažje branje. Chrome je prenesel izvirno stran prek povezave, ki ni varna.</translation>
<translation id="6891596781022320156">Raven pravilnika ni podprta.</translation>
+<translation id="6895143722905299846">Navidezna Å¡tevilka:</translation>
<translation id="6895330447102777224">Kartica je potrjena.</translation>
<translation id="6897140037006041989">Uporabnikov posrednik</translation>
<translation id="6898699227549475383">Organizacija (O)</translation>
@@ -1578,10 +1622,10 @@ V nasprotnem primeru bodo to blokirale nastavitve zasebnosti. S tem bo vsebina,
<translation id="7004583254764674281">Uporabite Windows Hello za hitrejše potrjevanje kartic</translation>
<translation id="7006930604109697472">Vseeno pošlji</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Spremeni velikost nastavitev</translation>
<translation id="7014741021609395734">Stopnja poveÄave</translation>
<translation id="7016992613359344582">Te bremenitve so lahko enkratne ali ponavljajoÄe se in morda niso oÄitne.</translation>
<translation id="7029809446516969842">Gesla</translation>
+<translation id="7030436163253143341">Potrdilo ni veljavno</translation>
<translation id="7031646650991750659">Katere aplikacije iz Googla Play ste namestili</translation>
<translation id="7050187094878475250">Poskusili ste odpreti <ph name="DOMAIN" />, vendar je strežnik uporabil potrdilo, ki ima predolgo obdobje veljavnosti, da bi bilo verodostojno.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Te kartice trenutno ni mogoÄe shraniti}one{Teh kartic trenutno ni mogoÄe shraniti}two{Teh kartic trenutno ni mogoÄe shraniti}few{Teh kartic trenutno ni mogoÄe shraniti}other{Teh kartic trenutno ni mogoÄe shraniti}}</translation>
@@ -1651,12 +1695,14 @@ Dodatne podrobnosti:
<translation id="7300012071106347854">Kobaltovo modra</translation>
<translation id="7302712225291570345">»<ph name="TEXT" />«</translation>
<translation id="7304030187361489308">Visoka</translation>
+<translation id="7305756307268530424">ZaÄni poÄasneje</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">PomoÄ pri povezavi</translation>
<translation id="7323804146520582233">Skrij razdelek »<ph name="SECTION" />«</translation>
<translation id="733354035281974745">Preglasitev lokalnega raÄuna v napravi</translation>
<translation id="7333654844024768166">Pravkar ste vnesli geslo na zavajajoÄem spletnem mestu. Chromium priporoÄa, da obiÅ¡Äete <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ter druga spletna mesta, na katerih uporabljate to geslo, in ga takoj spremenite.</translation>
<translation id="7334320624316649418">&amp;Uveljavi razvrstitev</translation>
+<translation id="7337248890521463931">Pokaži veÄ vrstic</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>
@@ -1664,6 +1710,7 @@ Dodatne podrobnosti:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Ukazna vrstica</translation>
<translation id="7359588939039777303">Oglasi blokirani.</translation>
+<translation id="7363096869660964304">Kljub temu pa niste nevidni. Z uporabo anonimnega naÄina svojega brskanja ne skrijete pred delodajalcem, ponudnikom internetnih storitev ali spletnimi mesti, ki jih obiÅ¡Äete.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite tabulatorko, nato Enter, Äe želite dodati in upravljati naslove v Chromovih nastavitvah.</translation>
<translation id="7365849542400970216">Poznate podatke o uporabi naprave?</translation>
<translation id="7372973238305370288">rezultat iskanja</translation>
@@ -1674,7 +1721,9 @@ Dodatne podrobnosti:
<translation id="7378594059915113390">Kontrolniki predstavnosti</translation>
<translation id="7378627244592794276">Ne</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Se ne uporablja</translation>
<translation id="7390545607259442187">Potrditev kartice</translation>
+<translation id="7392089738299859607">Posodobitev naslova</translation>
<translation id="7399802613464275309">Varnostno preverjanje</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Naprava <ph name="DEVICE_NAME" /> je upravljana</translation>
@@ -1689,6 +1738,7 @@ Dodatne podrobnosti:
&lt;li&gt;ObiÅ¡Äite &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;center za pomoÄ za Chrome&lt;/a&gt; Äe želite izvedeti, kako programsko opremo trajno odstranite iz raÄunalnika.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Ljubko</translation>
<translation id="7416351320495623771">Upravljaj gesla …</translation>
<translation id="7419106976560586862">Pot profila</translation>
<translation id="7437289804838430631">Dodaj podatke o stiku</translation>
@@ -1704,7 +1754,7 @@ Dodatne podrobnosti:
<translation id="7481312909269577407">Naprej</translation>
<translation id="7485870689360869515">Ni podatkov.</translation>
<translation id="7495528107193238112">Ta vsebina je blokirana. Obrnite se na lastnika spletnega mesta, da odpravi težavo.</translation>
-<translation id="7498234416455752244">Nadaljuj urejanje</translation>
+<translation id="7498193950643227031">S spreminjanjem velikosti lahko pride do nepriÄakovanega delovanja. Tukaj lahko zdaj omejite zmožnost spreminjanja velikosti aplikacij: <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Pravkar ste vnesli geslo na zavajajoÄem spletnem mestu. Chromium priporoÄa, da takoj preverite shranjena gesla za <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> in druga spletna mesta, na katerih uporabljate to geslo.</translation>
<translation id="7508255263130623398">Vrnjen ID naprave pravilnika je prazen ali se ne ujema s trenutnim ID-jem naprave</translation>
<translation id="7508870219247277067">Avokadovo zelena</translation>
@@ -1724,6 +1774,7 @@ Dodatne podrobnosti:
<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="755279583747225797">Preizkus je aktiven.</translation>
<translation id="7552846755917812628">Poskusite te nasvete:</translation>
<translation id="7554475479213504905">Vseeno znova naloži in pokaži</translation>
<translation id="7554791636758816595">Nov zavihek</translation>
@@ -1742,7 +1793,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite tabulatorko, nato Enter, Äe si želite ogledati in upravljati gesla v Chromovih nastavitvah</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="7616645509853975347">Skrbnik je v brskalniku vklopil prikljuÄke Chrome Enterprise Connectors. Ti prikljuÄki imajo dostop do nekaterih vaÅ¡ih podatkov.</translation>
<translation id="7619838219691048931">KonÄni list</translation>
<translation id="762844065391966283">Posamezno</translation>
@@ -1807,13 +1857,12 @@ Dodatne podrobnosti:
<translation id="782886543891417279">Omrežje Wi-Fi, ki ga uporabljate (<ph name="WIFI_NAME" />), morda zahteva, da obiÅ¡Äete stran za prijavo.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Brez}=1{1 aplikacija (<ph name="EXAMPLE_APP_1" />)}=2{2 aplikaciji (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# aplikacija (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}two{# aplikaciji (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}few{# aplikacije (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# aplikacij (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Kljub temu pa niste nevidni. Z uporabo anonimnega naÄina svojega brskanja ne skrijete pred delodajalcem, ponudnikom internetnih storitev ali spletnimi mesti, ki jih obiÅ¡Äete.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">odpirati datoteke s povezavami z vrstami datotek.</translation>
<translation id="7862185352068345852">Želite zapustiti spletno mesto?</translation>
<translation id="7865448901209910068">Najboljša hitrost</translation>
<translation id="7874263914261512992">Pravkar ste vnesli geslo na zavajajoÄem spletnem mestu. Chrome priporoÄa, da takoj preverite shranjena gesla za <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> in druga spletna mesta, na katerih uporabljate to geslo.</translation>
<translation id="7878562273885520351">Geslo je morda ogroženo</translation>
+<translation id="7880146494886811634">Shranjevanje naslova</translation>
<translation id="7882421473871500483">Rjava</translation>
<translation id="7887683347370398519">Preverite CVC in poskusite znova</translation>
<translation id="7887885240995164102">Odpri naÄin slike v sliki</translation>
@@ -1821,6 +1870,7 @@ Dodatne podrobnosti:
<translation id="7894280532028510793">ÄŒe je Ärkovanje pravilno, <ph name="BEGIN_LINK" />poskuÅ¡ajte zagnati orodje za omrežno diagnostiko<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Neznano</translation>
+<translation id="793209273132572360">Želite posodobiti naslov?</translation>
<translation id="7932579305932748336">Prevleka</translation>
<translation id="79338296614623784">Vnesite veljavno telefonsko Å¡tevilko</translation>
<translation id="7934052535022478634">PlaÄilo je dokonÄano</translation>
@@ -1891,6 +1941,7 @@ Dodatne podrobnosti:
<translation id="8175796834047840627">Chrome ponuja shranjevanje kartic v raÄun Google, ker ste prijavljeni. To lahko spremenite v nastavitvah.</translation>
<translation id="8176440868214972690">Skrbnik te naprave je poslal nekatere podatke, kot so nastavitve ali pravilniki, na ta spletna mesta.</translation>
<translation id="8184538546369750125">Uporabi globalno privzeto (Dovoli)</translation>
+<translation id="8193086767630290324">Izvedena dejanja s podatki, ki so oznaÄeni kot zaupni.</translation>
<translation id="8194797478851900357">&amp;Razveljavi premik</translation>
<translation id="8201077131113104583">Neveljaven posodobitveni URL za razširitev z ID-jem »<ph name="EXTENSION_ID" />«.</translation>
<translation id="8202097416529803614">Povzetek naroÄila</translation>
@@ -1913,6 +1964,7 @@ Dodatne podrobnosti:
<translation id="8249296373107784235">Prekini</translation>
<translation id="8249320324621329438">Nazadnje preneseno:</translation>
<translation id="8253091569723639551">Naslov za izstavitev raÄuna je obvezen</translation>
+<translation id="8257387598443225809">Ta aplikacija je zasnovana za mobilne naprave</translation>
<translation id="825929999321470778">Prikaz vseh shranjenih gesel</translation>
<translation id="8261506727792406068">Izbriši</translation>
<translation id="8262952874573525464">Robni Å¡iv spodaj</translation>
@@ -2036,7 +2088,6 @@ Dodatne podrobnosti:
<translation id="8719528812645237045">VeÄkratno luknjanje zgoraj</translation>
<translation id="8725066075913043281">Poskusite znova</translation>
<translation id="8726549941689275341">Velikost strani:</translation>
-<translation id="8728672262656704056">Uporabljate anonimni naÄin</translation>
<translation id="8730621377337864115">KonÄano</translation>
<translation id="8731544501227493793">Gumb za upravljanje gesel, pritisnite Enter, Äe si želite ogledati in upravljati gesla v Chromovih nastavitvah</translation>
<translation id="8734529307927223492">Vašo napravo <ph name="DEVICE_TYPE" /> upravlja domena <ph name="MANAGER" /></translation>
@@ -2113,6 +2164,7 @@ Dodatne podrobnosti:
<translation id="9020542370529661692">Ta stran je prevedena v jezik <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(neveljavno)</translation>
+<translation id="9030265603405983977">Enobarvno</translation>
<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>
@@ -2136,6 +2188,7 @@ Dodatne podrobnosti:
<translation id="91108059142052966">Pravilnik skrbnika onemogoÄa deljenje zaslona z aplikacijo <ph name="APPLICATION_TITLE" />, Äe je vidna zaupna vsebina.</translation>
<translation id="9114524666733003316">Potrjevanje kartice …</translation>
<translation id="9114581008513152754">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="9117930699067497412">Sveže</translation>
<translation id="9119042192571987207">Naloženo</translation>
<translation id="9128016270925453879">Pravilniki so naloženi</translation>
<translation id="9128870381267983090">Vzpostavi povezavo z omrežjem</translation>
@@ -2154,6 +2207,7 @@ Dodatne podrobnosti:
<translation id="9170848237812810038">&amp;Razveljavi</translation>
<translation id="9171296965991013597">Želite zapustiti aplikacijo?</translation>
<translation id="9173282814238175921">Enojni dokument/nov list</translation>
+<translation id="9173995187295789444">Iskanje naprav Bluetooth ...</translation>
<translation id="917450738466192189">Potrdilo strežnika ni veljavno.</translation>
<translation id="9174917557437862841">Gumb za preklop zavihkov, pritisnite Enter, Äe želite preklopiti na ta zavihek</translation>
<translation id="9179703756951298733">Upravljanje plaÄil in podatkov o kreditnih karticah v nastavitvah v Chromu</translation>
diff --git a/chromium/components/strings/components_strings_sq.xtb b/chromium/components/strings/components_strings_sq.xtb
index d2e95d528f0..bf411e5bb09 100644
--- a/chromium/components/strings/components_strings_sq.xtb
+++ b/chromium/components/strings/components_strings_sq.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Nëse zgjidhet, Chrome do të ruajë një kopje të kartës tënde në këtë pajisje për një plotësim më të shpejtë të formularit.</translation>
<translation id="1110994991967754504">Përzgjidh autorizimin për <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Zhbëj rirenditjen</translation>
+<translation id="1123753900084781868">"Titrat në çast" nuk ofrohen për momentin</translation>
<translation id="1125573121925420732">Paralajmërimet mund të jenë të zakonshme ndërkohë që sajtet e uebit përditësojnë sigurinë e tyre. Kjo duhet të përmirësohet së shpejti.</translation>
<translation id="112840717907525620">Memoria specifike e politikës është në rregull</translation>
<translation id="1130564665089811311">Butoni "Përkthe faqen", shtyp "Enter" për ta përkthyer këtë faqe me "Përkthe me Google"</translation>
@@ -74,6 +75,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="1240347957665416060">Emri i pajisjes sate</translation>
<translation id="124116460088058876">Gjuhë të tjera</translation>
<translation id="1243027604378859286">Autori:</translation>
+<translation id="1246424317317450637">Të trashësuara</translation>
<translation id="1250759482327835220">Për të paguar më shpejt herën tjetër, ruaje kartën, emrin dhe adresën tënde të faturimit në "Llogarinë tënde të Google".</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sinkronizuar)</translation>
<translation id="1256368399071562588">&lt;p&gt;Nëse përpiqesh të vizitosh një sajt uebi dhe ai nuk hapet, provo në fillim të rregullosh gabimin me këto hapa për zgjidhjen e problemeve:&lt;/p&gt;
@@ -156,6 +158,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="1476595624592550506">Ndrysho fjalëkalimin</translation>
<translation id="1484290072879560759">Zgjidh adresën e dërgimit</translation>
<translation id="1492194039220927094">Politikat e detyruara:</translation>
+<translation id="1495677929897281669">Kthehu te skeda</translation>
<translation id="1501859676467574491">Shfaq kartat nga "Llogaria jote e Google"</translation>
<translation id="1507202001669085618">&lt;p&gt;Do të shikosh këtë gabim nëse përdor një portal Wi-Fi ku duhet të identifikohesh përpara se të hysh në linjë.&lt;/p&gt;
&lt;p&gt;Për të rregulluar gabimin, kliko te &lt;strong&gt;Lidhu&lt;/strong&gt; në faqen që po përpiqesh të hapësh.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="1532118530259321453">Kjo faqe thotë</translation>
<translation id="153384715582417236">Kaq ishte për momentin</translation>
<translation id="1536390784834419204">Përkthe faqen</translation>
+<translation id="1539840569003678498">Raporti u dërgua:</translation>
<translation id="154408704832528245">Zgjidh adresën e dorëzimit</translation>
<translation id="1549470594296187301">Duhet të aktivizohet JavaScript për të përdorur këtë funksion.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="1682696192498422849">Ana e shkurtër në fillim</translation>
<translation id="168693727862418163">Vërtetimi i kësaj vlere të politikës kundrejt skemës së saj dështoi dhe do të shpërfillet.</translation>
<translation id="168841957122794586">Certifikata e serverit përmban një çelës të dobët kriptografik.</translation>
+<translation id="1696290444144917273">Shiko detajet e kartës virtuale</translation>
<translation id="1697532407822776718">Je gati!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Ky server nuk mund të vërtetonte se është <ph name="DOMAIN" />; certifikata e tij e sigurisë supozohet se është nga dita e nesërme. Kjo mund të jetë shkaktuar nga një konfigurim i gabuar ose nga ndërhyrja e një sulmuesi në lidhjen tënde.}other{ky server nuk mund të vërtetonte se është <ph name="DOMAIN" />; certifikata e tij e sigurisë supozohet se është nga # ditë në të ardhmen. Kjo mund të jetë shkaktuar nga një konfigurim i gabuar ose nga ndërhyrja e një sulmuesi në lidhjen tënde.}}</translation>
<translation id="1710259589646384581">Sistemi operativ</translation>
+<translation id="1711234383449478798">U shpërfill sepse <ph name="POLICY_NAME" /> nuk është caktuar si "<ph name="VALUE" />".</translation>
<translation id="1712552549805331520"><ph name="URL" /> kërkon të ruajë të dhëna në mënyrë të përhershme në kompjuterin tënd lokal</translation>
<translation id="1713628304598226412">Tabakaja 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Kutia postare 3</translation>
<translation id="1718029547804390981">Dokumenti është shumë i madh për t'u shënuar</translation>
<translation id="1721424275792716183">* Fusha është e detyrueshme</translation>
+<translation id="1727613060316725209">Certifikata është e vlefshme</translation>
<translation id="1727741090716970331">Shto numër të vlefshëm karte</translation>
<translation id="1728677426644403582">Po shikon burimin e një faqe uebi</translation>
<translation id="173080396488393970">Kjo lloj karte nuk mbështetet</translation>
@@ -245,7 +252,6 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
titulli është formuar gabimisht, gjë që e parandalon përmbushjen e
kërkesës sate për <ph name="SITE" />. Politikat e origjinës mund të përdoren nga operatorët e sajtit për të konfiguruar karakteristikat e sigurisë dhe karakteristika të tjera për një sajt.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Përditëso frazën e kalimit për sinkronizimin.</translation>
<translation id="1787142507584202372">Skedat e tua të hapura shfaqen këtu</translation>
<translation id="1791429645902722292">Smart Lock-u i Google</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ofrohen shumë veprime, shtyp "Tab" për të kaluar në cikël mes tyre</translation>
@@ -278,6 +284,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="1919345977826869612">Reklamat</translation>
<translation id="1919367280705858090">Merr ndihmë për një mesazh specifik gabimi</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Asnjë}=1{1 sajt}other{# sajte}}</translation>
+<translation id="1924727005275031552">I ri</translation>
<translation id="1945968466830820669">Mund të humbasësh qasjen në llogarinë e organizatës ose mund të pësosh vjedhje të identitetit. Chromium rekomandon që ta ndryshosh fjalëkalimin tani.</translation>
<translation id="1947454675006758438">Kapje me tel lart djathtas</translation>
<translation id="1958218078413065209">Rezultati yt maksimal është <ph name="SCORE" />.</translation>
@@ -300,12 +307,14 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="2042213636306070719">Tabakaja 7</translation>
<translation id="204357726431741734">Identifikohu për të përdorur fjalëkalimet e ruajtura në "Llogarinë tënde të Google"</translation>
<translation id="2053111141626950936">Faqet në <ph name="LANGUAGE" /> nuk do të përkthehen.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Kur ky kontroll është aktiv dhe statusi është aktiv, Chrome përcakton se me cilin grup të madh personash (kohortë) është më i ngjashëm aktiviteti yt i shfletimit së fundi. Reklamuesit mund të zgjedhin reklamat për grupin dhe aktiviteti yt i shfletimit mbahet privat në pajisjen tënde. Grupi yt përditësohet çdo ditë.}=1{Kur ky kontroll është aktiv dhe statusi është aktiv, Chrome përcakton se me cilin grup të madh personash (kohortë) është më i ngjashëm aktiviteti yt i shfletimit së fundi. Reklamuesit mund të zgjedhin reklamat për grupin dhe aktiviteti yt i shfletimit mbahet privat në pajisjen tënde. Grupi yt përditësohet çdo ditë.}other{Kur ky kontroll është aktiv dhe statusi është aktiv, Chrome përcakton se me cilin grup të madh personash (kohortë) është më i ngjashëm aktiviteti yt i shfletimit së fundi. Reklamuesit mund të zgjedhin reklamat për grupin dhe aktiviteti yt i shfletimit mbahet privat në pajisjen tënde. Grupi yt përditësohet çdo {NUM_DAYS} ditë.}}</translation>
<translation id="2053553514270667976">Kodi postar</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 sugjerim}other{# sugjerime}}</translation>
<translation id="2071692954027939183">Njoftimet bllokohen automatikisht sepse ti zakonisht nuk i lejon ato</translation>
<translation id="2079545284768500474">Zhbëj</translation>
<translation id="20817612488360358">Cilësimet e përfaqësuesit të sistemit janë caktuar që të përdoren, por është specifikuar po ashtu një konfigurim i qartë i përfaqësuesit.</translation>
<translation id="2082238445998314030">Rezultati <ph name="RESULT_NUMBER" /> nga <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Ruaj…</translation>
<translation id="2088086323192747268">Butoni "Menaxho sinkronizimin". Shtyp "Enter" për të menaxhuar se çfarë informacionesh sinkronizon ti te cilësimet e Chrome</translation>
<translation id="2091887806945687916">Tingulli</translation>
<translation id="2094505752054353250">Mospërputhje domeni</translation>
@@ -378,6 +387,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="2317259163369394535"><ph name="DOMAIN" /> kërkon një emër përdoruesi dhe një fjalëkalim.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, skadon më <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Cilësim i kontrolluar nga administratori yt</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> dëshiron të çiftohet</translation>
<translation id="2344028582131185878">Shkarkimet automatike</translation>
<translation id="2346319942568447007">Imazhi që kopjove</translation>
<translation id="2354001756790975382">Faqeshënues të tjerë</translation>
@@ -385,8 +395,10 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="2355395290879513365">Sulmuesit mund të arrijnë t'i shikojnë imazhet që po shikon në këtë sajt dhe të të mashtrojnë duke i modifikuar ato.</translation>
<translation id="2356070529366658676">Pyet</translation>
<translation id="2357481397660644965">Pajisja jote menaxhohet nga <ph name="DEVICE_MANAGER" /> dhe llogaria jote menaxhohet nga <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Për më pak se një ditë}=1{Për një ditë}other{Për {NUM_DAYS} ditë}}</translation>
<translation id="2359629602545592467">Disa</translation>
<translation id="2359808026110333948">Vazhdo</translation>
+<translation id="2359961752320758691">Zbatohet numri yt i kartës virtuale.</translation>
<translation id="2367567093518048410">Niveli</translation>
<translation id="2372464001869762664">Pasi t'i konfirmosh, detajet e kartës nga "Llogaria jote e Google" do të ndahen me këtë sajt. Gjej kodin CVC në të dhënat e llogarisë Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -397,6 +409,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="239429038616798445">Kjo mënyrë dërgimi nuk ofrohet. Provo një mënyrë tjetër.</translation>
<translation id="2396249848217231973">&amp;Zhbëje fshirjen</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">I vjetër</translation>
<translation id="2413528052993050574">Ky server nuk mund të dëshmonte se është <ph name="DOMAIN" />; certifikata e tij e sigurisë mund të jetë e revokuar. Kjo mund të shkaktohet nga një konfigurim i pasaktë ose nga ndërhyrja e një sulmuesi në lidhjen tënde.</translation>
<translation id="2414886740292270097">E errët</translation>
<translation id="2438874542388153331">Katër shpime djathtas</translation>
@@ -424,10 +437,10 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="2521385132275182522">Kapje me tel poshtë djathtas</translation>
<translation id="2523886232349826891">Ruajtur vetëm në këtë pajisje</translation>
<translation id="2524461107774643265">Shto më shumë informacion</translation>
-<translation id="2526590354069164005">Desktopi</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{dhe 1 tjetër}other{dhe # të tjera}}</translation>
<translation id="2536110899380797252">Shto adresë</translation>
<translation id="2539524384386349900">Zbulo</translation>
+<translation id="2541219929084442027">Faqet që shikon në skedat "e fshehta" nuk do të ruhen në historikun e shfletuesit tënd, vendin e ruajtjes të kukive apo historikun e kërkimeve pasi ke mbyllur të gjitha skedat e tua "të fshehta". Çdo skedar që shkarkon apo faqeshënues që krijon do të mbahet.</translation>
<translation id="2544644783021658368">Një dokument i vetëm</translation>
<translation id="254947805923345898">Vlera e politikës nuk është e vlefshme.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> dërgoi një përgjigje të pavlefshme.</translation>
@@ -447,6 +460,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="2629325967560697240">Për të marrë nivelin më të lartë të sigurisë së Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />aktivizo mbrojtjen e përmirësuar<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Adresa e IP-së së serverit të <ph name="HOST_NAME" /> nuk mund të gjendej.</translation>
<translation id="2639739919103226564">Statusi:</translation>
+<translation id="264810637653812429">Nuk u gjetën pajisje të përputhshme.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, shtyp "Tab", më pas "Enter" për të pastruar historikun e shfletimit, kukit, memorien specifike etj. te cilësimet e Chrome</translation>
<translation id="2650446666397867134">Qasja te skedari u refuzua</translation>
@@ -491,6 +505,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="2799223571221894425">Nis sërish</translation>
<translation id="2803306138276472711">Kohët e fundit "Shfletimi i sigurt me Google" <ph name="BEGIN_LINK" />zbuloi softuerin keqdashës<ph name="END_LINK" /> në <ph name="SITE" />. Faqet që zakonisht janë të sigurta ndonjëherë infektohen me softuerë keqdashës.</translation>
<translation id="2807052079800581569">Pozicioni i imazhit në boshtin Y</translation>
+<translation id="2820957248982571256">Po skanon...</translation>
<translation id="2824775600643448204">Shiriti i adresës dhe i kërkimit</translation>
<translation id="2826760142808435982">Lidhja është e enkriptuar dhe e vërtetuar me <ph name="CIPHER" /> dhe përdor <ph name="KX" /> si mekanizëm kryesor shkëmbimi.</translation>
<translation id="2835170189407361413">Pastro formularin</translation>
@@ -498,6 +513,8 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="2850739647070081192">Invite (Zarf)</translation>
<translation id="2856444702002559011">Sulmuesit mund të përpiqen të vjedhin informacionet e tua nga <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (për shembull, fjalëkalimet, mesazhet ose kartat e kreditit). <ph name="BEGIN_LEARN_MORE_LINK" />Mëso më shumë<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Ky sajt shfaq reklama ndërhyrëse ose mashtruese.</translation>
+<translation id="287596039013813457">Miqësor</translation>
+<translation id="2876489322757410363">Po del nga modaliteti "i fshehtë" për të paguar nëpërmjet një aplikacioni të jashtëm. Të vazhdohet?</translation>
<translation id="2878197950673342043">Palosje posteri</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Vendosja e dritareve</translation>
@@ -547,7 +564,6 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="3060227939791841287">C9 (Zarf)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, shtyp "Tab", më pas "Enter" për të ekzekutuar "Kontrollin e sigurisë" në cilësimet e Chrome</translation>
<translation id="3061707000357573562">Shërbimi i korrigjimit</translation>
-<translation id="3064966200440839136">Po del nga modaliteti "i fshehur" për të paguar nëpërmjet një aplikacioni të jashtëm. Do të vazhdosh?</translation>
<translation id="306573536155379004">Loja filloi.</translation>
<translation id="3080254622891793721">Grafika</translation>
<translation id="3086579638707268289">Aktiviteti yt në ueb po monitorohet</translation>
@@ -570,7 +586,6 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="315504272643575312">Llogaria jote menaxhohet nga <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Restauro</translation>
<translation id="3162559335345991374">Lidhja Wi-Fi që po përdor mund të të kërkojë që të vizitosh faqen e saj të identifikimit.</translation>
-<translation id="3167968892399408617">Faqet që shikon në skedat "e fshehta" nuk do të ruhen në historikun e shfletuesit tënd, vendin e ruajtjes të kukive apo historikun e kërkimeve pasi të kesh mbyllur të gjitha skedat e tua "të fshehta". Çdo skedar që shkarkon ose faqeshënues që krijon do të mbahet.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ishulli</translation>
<translation id="3176929007561373547">Kontrollo cilësimet e përfaqësuesit ose kontakto me administratorin e rrjetit
@@ -596,10 +611,12 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="3229041911291329567">Informacioni i versionit rreth pajisjes dhe shfletuesit tënd</translation>
<translation id="323107829343500871">Shkruaj kodin CVC për <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Zbulo gjithmonë përmbajtje të rëndësishme në këtë sajt</translation>
+<translation id="3249845759089040423">Moderne</translation>
<translation id="3252266817569339921">Frëngjisht</translation>
<translation id="3266793032086590337">Vlera (konflikt)</translation>
<translation id="3268451620468152448">Hap skedat</translation>
<translation id="3270847123878663523">&amp;Zhbëj rirenditjen</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> dëshiron që të lidhet</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Organizata jote, <ph name="ENROLLMENT_DOMAIN" />, ka dërguar disa informacione te sajtet e mëposhtme të uebit, si p.sh. cilësime ose politika.</translation>
<translation id="3282497668470633863">Shto emrin në kartë</translation>
@@ -652,6 +669,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="3428151540071562330">Një ose disa nga URI-të e shablloneve të serverit DnsOverHttpsTemplates janë të pavlefshme dhe nuk do të përdoren.</translation>
<translation id="3431636764301398940">Ruaje këtë kartë në këtë pajisje</translation>
<translation id="3432601291244612633">Mbyll faqen</translation>
+<translation id="3435738964857648380">Siguria</translation>
<translation id="3435896845095436175">Aktivizo</translation>
<translation id="3438829137925142401">Përdor fjalëkalimet e ruajtura në "Llogarinë tënde të Google"</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -694,7 +712,10 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="3584299510153766161">Dy shpime poshtë</translation>
<translation id="3586931643579894722">Fshih detajet</translation>
<translation id="3587738293690942763">Mesatar</translation>
+<translation id="3590643883886679995">Të dhënat e identifikimit do të ruhen në këtë pajisje pasi të dalësh nga modaliteti "i fshehtë".</translation>
+<translation id="359126217934908072">Muaji/viti:</translation>
<translation id="3592413004129370115">Italian (Zarf)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Mund ta rivendosësh grupin tënd në çdo kohë. Duhet rreth një ditë për t'u bashkuar në një grup të ri.}=1{Mund ta rivendosësh grupin tënd në çdo kohë. Duhet rreth një ditë për t'u bashkuar në një grup të ri.}other{Mund ta rivendosësh grupin tënd në çdo kohë. Duhen {NUM_DAYS} ditë për t'u bashkuar në një grup të ri.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Aplikacioni u bllokua nga administratori yt</translation>
<translation id="3608932978122581043">Orientimi i furnizimit</translation>
@@ -703,13 +724,13 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="3615877443314183785">Fut një datë të vlefshme skadimi</translation>
<translation id="36224234498066874">Pastro të dhënat e shfletimit...</translation>
<translation id="362276910939193118">Shfaq historikun e plotë</translation>
-<translation id="3625635938337243871">Të dhënat e identifikimit do të ruhen në këtë pajisje pasi të dalësh nga modaliteti "I fshehtë".</translation>
<translation id="3630155396527302611">Nëse tashmë është i listuar si program që lejohet të ketë qasje te rrjeti,
provo që ta heqësh nga lista dhe ta shtosh përsëri.</translation>
<translation id="3630699740441428070">Lidhjen e rrjetit tënd e kanë konfiguruar administratorët e kësaj pajisjeje, gjë që mund t'u lejojë atyre të shikojnë trafikun e rrjetit tënd, duke përfshirë edhe cilat faqe interneti viziton.</translation>
<translation id="3631244953324577188">Sistemet biometrike</translation>
<translation id="3633738897356909127">Butoni "Përditëso Chrome", shtyp "Enter" për të përditësuar Chrome nga cilësimet e Chrome</translation>
<translation id="3634530185120165534">Tabakaja 5</translation>
+<translation id="3637662659967048211">Ruaje në "Llogarinë e Google"</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplikacioni:</translation>
<translation id="3650584904733503804">Vlerësimi është i suksesshëm</translation>
@@ -750,6 +771,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="3781428340399460090">Rozë e ndezur</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Pajisjet me Bluetooth</translation>
+<translation id="3787675388804467730">Numri i kartës virtuale</translation>
<translation id="3787705759683870569">Skadon më <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Madhësia 16</translation>
<translation id="3789841737615482174">Instalo</translation>
@@ -769,6 +791,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="3841184659773414994">Përpunuesit e skedarëve</translation>
<translation id="385051799172605136">Prapa</translation>
<translation id="3858027520442213535">Përditëso datën dhe kohën</translation>
+<translation id="3881478300875776315">Shfaq më pak rreshta</translation>
<translation id="3884278016824448484">Identifikuesi i pajisjes bie në konflikt</translation>
<translation id="3885155851504623709">Famullia</translation>
<translation id="388632593194507180">U zbulua monitorim</translation>
@@ -794,6 +817,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="397105322502079400">Po llogarit...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> është bllokuar</translation>
<translation id="3973357910713125165">Ekzekuto butonin e "Kontrollit të sigurisë" të Chrome, shtyp "Enter" për të ekzekutuar "Kontrollin e sigurisë" te cilësimet e Chrome</translation>
+<translation id="3986705137476756801">Çaktivizo "Titrat në çast" për momentin</translation>
<translation id="3987405730340719549">Chrome ka përcaktuar se ky sajt mund të jetë i rremë ose mashtrues.
Nëse beson se kjo është shfaqur gabimisht, vizito https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -888,13 +912,14 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="4275830172053184480">Rinise pajisjen</translation>
<translation id="4277028893293644418">Rivendos fjalëkalimin</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Kjo kartë është ruajtur në "Llogarinë tënde të Google"}other{Këto karta janë ruajtur në "Llogarinë tënde të Google"}}</translation>
+<translation id="4287885627794386150">Ka të drejtë për provë, por nuk është aktiv</translation>
<translation id="4297502707443874121">Miniatura për faqen <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Zgjero</translation>
<translation id="4300675098767811073">Shumë shpime djathtas</translation>
<translation id="4302514097724775343">Trokit te dinozauri për të luajtur</translation>
<translation id="4302965934281694568">Chou3 (Zarf)</translation>
<translation id="4305666528087210886">Qasja te skedari ishte e pamundur</translation>
-<translation id="4305817255990598646">Ndërro</translation>
+<translation id="4306529830550717874">Të ruhet adresa?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blloko (parazgjedhja)</translation>
<translation id="4314815835985389558">Menaxho sinkronizimin</translation>
@@ -921,6 +946,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="4377125064752653719">U përpoqe të arrije domenin <ph name="DOMAIN" />, por certifikata që paraqiti serveri është revokuar nga lëshuesi i saj. Kjo do të thotë se kredencialet e sigurisë që paraqiti serveri nuk duhet të besohen në mënyrë absolute. Mund të jesh duke komunikuar me ndonjë sulmues.</translation>
<translation id="4378154925671717803">Telefoni</translation>
<translation id="4390472908992056574">Buza</translation>
+<translation id="4406883609789734330">Titra në çast</translation>
<translation id="4406896451731180161">rezultatet e kërkimit</translation>
<translation id="4408413947728134509">Kukit <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Sapo fute fjalëkalimin tënd në një sajt mashtrues. Chrome rekomandon që të shkosh te <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> dhe sajte të tjera ku e përdor këtë fjalëkalim dhe ta ndryshosh atë tani.</translation>
@@ -933,7 +959,6 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Përdorimi i një përfaqësuesi është i çaktivizuar, por është specifikuar një konfigurim i qartë përfaqësuesi.</translation>
<translation id="4464826014807964867">Sajtet e uebit me informacione nga organizata jote</translation>
-<translation id="4466881336512663640">Ndryshimet në formular do të humbasin. Je i sigurt se dëshiron të vazhdosh?</translation>
<translation id="4476953670630786061">Ky formular nuk është i sigurt. Plotësimi automatik është çaktivizuar.</translation>
<translation id="4477350412780666475">Kënga tjetër</translation>
<translation id="4482953324121162758">Ky sajt nuk do të përkthehet.</translation>
@@ -967,6 +992,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="4594403342090139922">&amp;Zhbëje fshirjen</translation>
<translation id="4597348597567598915">Madhësia 8</translation>
<translation id="4600854749408232102">C6/C5 (Zarf)</translation>
+<translation id="4606870351894164739">Me impakt</translation>
<translation id="4628948037717959914">Fotografia</translation>
<translation id="4631649115723685955">Oferta e kthimit të parave është e lidhur</translation>
<translation id="4636930964841734540">Informacion</translation>
@@ -986,6 +1012,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="4691835149146451662">Architecture-A (Zarf)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Ana</translation>
+<translation id="4702656508969495934">"Titrat në çast" janë të dukshëm. Përdor shkëmbyesin e dritareve për t'i fokusuar</translation>
<translation id="4708268264240856090">Lidhja jote u ndërpre</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Po ekzekuton diagnostikimin e rrjetit të Windows<ph name="END_LINK" /></translation>
@@ -999,6 +1026,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="4738601419177586157">Sugjerim kërkimi për <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Menaxho fjalëkalimet…</translation>
<translation id="4744603770635761495">Shtegu i ekzekutueshëm</translation>
+<translation id="4749011317274908093">Ke kaluar në modalitetin "e fshehtë"</translation>
<translation id="4750917950439032686">Informacionet e tua (p.sh. fjalëkalimet ose numrat e kartave të kreditit) janë private kur dërgohen në këtë sajt.</translation>
<translation id="4756388243121344051">&amp;Historiku</translation>
<translation id="4758311279753947758">Shto informacionet e kontaktit</translation>
@@ -1028,6 +1056,8 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="4813512666221746211">Gabim në rrjet</translation>
<translation id="4816492930507672669">Përshtate me faqen</translation>
<translation id="4819347708020428563">Të redaktohen shënimet në pamjen e parazgjedhur?</translation>
+<translation id="4825507807291741242">I fuqishëm</translation>
+<translation id="4838327282952368871">Si në ëndërr</translation>
<translation id="484462545196658690">Automatike</translation>
<translation id="4850886885716139402">Pamja</translation>
<translation id="485316830061041779">Gjermanisht</translation>
@@ -1164,6 +1194,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="5314967030527622926">Krijuesi i broshurës</translation>
<translation id="5316812925700871227">Rrotullo në drejtim të kundërt të akrepave të orës</translation>
<translation id="5317780077021120954">Ruaj</translation>
+<translation id="5321288445143113935">I maksimizuar</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> nga <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Zgjidh informacionet e kontaktit</translation>
<translation id="5327248766486351172">Emri</translation>
@@ -1171,11 +1202,13 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="5332219387342487447">Mënyra e dërgimit</translation>
<translation id="5333022057423422993">Chrome e gjeti fjalëkalimin që sapo përdore në një nxjerrje të paautorizuar të të dhënave. Për t'i siguruar llogaritë e tua, ne rekomandojmë të kontrollosh fjalëkalimet e tua të ruajtura.</translation>
<translation id="5334013548165032829">Evidencat e detajuara të sistemit</translation>
+<translation id="5334145288572353250">Të ruhet adresa?</translation>
<translation id="5340250774223869109">Aplikacioni është bllokuar</translation>
<translation id="534295439873310000">Pajisjet me NFC</translation>
<translation id="5344579389779391559">Kjo faqe mund të përpiqet të të tarifojë në para</translation>
<translation id="5355557959165512791">Nuk mund ta vizitosh <ph name="SITE" /> tani, sepse certifikata e tij është revokuar. Gabimet dhe sulmet në rrjet zakonisht janë të përkohshme, prandaj kjo faqe ndoshta do të punojë më vonë.</translation>
<translation id="536296301121032821">Dështoi në ruajtjen e cilësimeve të politikës.</translation>
+<translation id="5363309033720083897">Porta seriale e lejuar nga administratori yt</translation>
<translation id="5371425731340848620">Përditëso kartën</translation>
<translation id="5377026284221673050">"Ora jote është prapa" ose "Ora jote është përpara" ose "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
<translation id="5386426401304769735">Zinxhiri i certifikatës për këtë sajt përmban një certifikatë të nënshkruar me SHA-1.</translation>
@@ -1184,6 +1217,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="5398772614898833570">Reklamat janë të bllokuara</translation>
<translation id="5400836586163650660">Gri</translation>
<translation id="540969355065856584">Ky server nuk mund të provojë se është <ph name="DOMAIN" />; certifikata e tij e sigurisë është e pavlefshme në këtë moment. Kjo mund të shkaktohet për shkak të konfigurimit të pasaktë ose në rast të ndërhyrjes së ndonjë sulmuesi në lidhjen tënde.</translation>
+<translation id="541143247543991491">Reja kompjuterike (gjithë sistemi)</translation>
<translation id="541416427766103491">Stivuesi 4</translation>
<translation id="5421136146218899937">Pastro të dhënat e shfletimit...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> dëshiron të të dërgojë njoftime</translation>
@@ -1197,6 +1231,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="5455374756549232013">Vulë kohore politike e gabuar</translation>
<translation id="5457113250005438886">E pavlefshme</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> dhe <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> tjetër}other{<ph name="CONTACT_PREVIEW" /> dhe <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> të tjerë}}</translation>
+<translation id="5463625433003343978">Po gjen pajisje...</translation>
<translation id="5469868506864199649">Italisht</translation>
<translation id="5470861586879999274">&amp;Ribëj redaktimin</translation>
<translation id="5478437291406423475">B6/C4 (Zarf)</translation>
@@ -1246,7 +1281,6 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="5624120631404540903">Menaxho fjalëkalimet</translation>
<translation id="5629630648637658800">Dështoi në ngarkimin e cilësimeve të politikës</translation>
<translation id="5631439013527180824">Shenjë e pavlefshme e menaxhimit të pajisjes</translation>
-<translation id="5632627355679805402">Të dhënat e tua janë enkriptuar me <ph name="BEGIN_LINK" />fjalëkalimin tënd të Google<ph name="END_LINK" /> në <ph name="TIME" />. Fute atë për të nisur sinkronizimin.</translation>
<translation id="5633066919399395251">Sulmuesit aktualisht në <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mund të tentojnë të instalojnë programe të rrezikshme që vjedhin ose fshijnë informacionin tënd (për shembull, fotografi, fjalëkalime, mesazhe dhe karta krediti). <ph name="BEGIN_LEARN_MORE_LINK" />Mëso më shumë<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">U bllokua një përmbajtje mashtruese.</translation>
<translation id="5644090287519800334">Zhvendosja e imazhit në boshtin X në anën 1</translation>
@@ -1285,12 +1319,12 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="5785756445106461925">Për më tepër, kjo faqe përfshin burime të tjera që nuk janë të sigurta. Këto burime mund të shikohen nga të tjerët kur janë në procesin e kalimit dhe mund të modifikohen nga ndonjë sulmues për të ndryshuar pamjen e faqes.</translation>
<translation id="5786044859038896871">Dëshiron që të plotësosh informacionet e kartës?</translation>
<translation id="578633867165174378">Chrome e gjeti fjalëkalimin që sapo përdore në një nxjerrje të paautorizuar të të dhënave. Ne rekomandojmë ta ndryshosh këtë fjalëkalim tani.</translation>
-<translation id="5798290721819630480">Të injorohen ndryshimet?</translation>
<translation id="5803412860119678065">Dëshiron që të plotësosh informacionet për <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Lejet</translation>
<translation id="5804427196348435412">Përdor pajisjet me NFC</translation>
<translation id="5810442152076338065">Lidhja jote me <ph name="DOMAIN" /> është enkriptuar duke përdorur një paketë të vjetër shifrimi.</translation>
<translation id="5813119285467412249">&amp;Ribëje shtimin</translation>
+<translation id="5817918615728894473">Çifto</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Kjo kartë do të tarifohet kur të paguash, por numri i saj i vërtetë nuk do të ndahet me këtë sajt. Për më shumë siguri, do të krijohet një kod CVC i përkohshëm.}other{Karta që zgjedh do të tarifohet kur të paguash, por numri i saj i vërtetë nuk do të ndahet me këtë sajt. Për më shumë siguri, do të krijohet një kod CVC i përkohshëm.}}</translation>
<translation id="5826507051599432481">Emri i zakonshëm (CN)</translation>
<translation id="5838278095973806738">Nuk duhet të futësh asnjë informacion delikat në këtë sajt (p.sh. fjalëkalimet ose karta krediti) pasi mund të vidhet nga sulmuesit.</translation>
@@ -1298,6 +1332,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="5855253129151731373">Emri i këtij domeni duket i ngjashëm me <ph name="LOOKALIKE_DOMAIN" />. Sulmuesit ndonjëherë i imitojnë sajtet duke bërë tek emri i domenit ndryshime të vogla që janë të vështira për t'u dalluar.
Nëse beson se kjo është shfaqur gabimisht, vizito https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Çaktivizuar</translation>
<translation id="5862579898803147654">Stivuesi 8</translation>
<translation id="5863847714970149516">Faqja në vijim mund të përpiqet të të tarifojë në para</translation>
<translation id="5866257070973731571">Shto numër telefoni</translation>
@@ -1314,6 +1349,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="5913377024445952699">Regjistrimi i ekranit u vendos në pauzë</translation>
<translation id="59174027418879706">Aktivizuar</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 në përdorim}other{# në përdorim}}</translation>
<translation id="5921185718311485855">Aktive</translation>
<translation id="5921639886840618607">Të ruhet karta te "Llogaria e Google"?</translation>
<translation id="5922853866070715753">Pothuajse mbaroi</translation>
@@ -1329,10 +1365,11 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="5979084224081478209">Kontrollo fjalëkalimet</translation>
<translation id="5980920751713728343">Index-3x5</translation>
<translation id="5984570616552610254">Lagështia e dhomës</translation>
-<translation id="598637245381783098">Aplikacioni i pagesës nuk mund të hapet</translation>
+<translation id="598637245381783098">Aplikacioni për pagesat nuk mund të hapet</translation>
<translation id="5989320800837274978">Nuk janë specifikuar serverë përfaqësues fiksë dhe as ndonjë URL e skriptit .pac.</translation>
<translation id="5992691462791905444">Palosje inxhinierike Z</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> rezultate për "<ph name="SEARCH_TEXT" />"</translation>
+<translation id="6006484371116297560">Klasike</translation>
<translation id="6008122969617370890">Renditja N deri në 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Kontrollo fjalëkalimet e tua</translation>
@@ -1354,6 +1391,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="6045164183059402045">Shablloni i vendosjes</translation>
<translation id="6047233362582046994">Nëse i kupton rreziqet për sigurinë tënde, mund <ph name="BEGIN_LINK" />ta vizitosh këtë sajt<ph name="END_LINK" /> para se të jenë hequr aplikacionet e dëmshme.</translation>
<translation id="6047927260846328439">Kjo përmbajtje mund të përpiqet të të mashtrojë që të instalosh softuerë ose të zbulosh informacionet e tua personale. <ph name="BEGIN_LINK" />Shfaqe gjithsesi<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Shtyp dhe mbaj shtypur |<ph name="ACCELERATOR" />| për të dalë nga ekrani i plotë</translation>
<translation id="6049488691372270142">Dorëzimi i faqes</translation>
<translation id="6051221802930200923">Nuk mund ta vizitosh <ph name="SITE" /> në këtë moment sepse sajti i uebit përdor gozhdimin e certifikatës. Gabimet dhe sulmet e rrjetit janë zakonisht të përkohshme, prandaj kjo faqe ndoshta do të funksionojë më vonë.</translation>
<translation id="6051898664905071243">Numri i faqeve:</translation>
@@ -1370,6 +1408,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="610911394827799129">Llogaria jote e Google mund të ketë forma të tjera të historikut të shfletimit në <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">Shiko tekstin dhe imazhet e kopjuara te kujtesa e fragmenteve</translation>
<translation id="6120179357481664955">Të kujtohet ID-ja e UPI?</translation>
+<translation id="6123290840358279103">Shiko kartën vrituale</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Kontrollo kabllot dhe rindiz router-it, modemët ose pajisjet e tjera të rrjetit që mund të jesh duke përdorur.</translation>
<translation id="614940544461990577">Provo:</translation>
@@ -1405,6 +1444,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="6289939620939689042">Ngjyra e faqes</translation>
<translation id="6290238015253830360">Artikujt e tu të sugjeruar shfaqen këtu</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">"Asistenti i Google" në Chrome po ndalon</translation>
<translation id="6305205051461490394"><ph name="URL" /> është i paarritshëm.</translation>
<translation id="6312113039770857350">Faqja e uebit nuk është e disponueshme</translation>
@@ -1430,6 +1470,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="6390200185239044127">Palosje Z në gjysmë</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Ngjitja nga <ph name="ORIGIN_NAME" /> te kjo vendndodhje është bllokuar nga politika e administratorit</translation>
+<translation id="6398765197997659313">Dil nga ekrani i plotë</translation>
<translation id="6401136357288658127">Kjo politikë është e vjetruar. Duhet të përdorësh politikën <ph name="NEW_POLICY" /> më mirë.</translation>
<translation id="6404511346730675251">Redakto faqeshënuesin</translation>
<translation id="6406765186087300643">C0 (Zarf)</translation>
@@ -1442,7 +1483,6 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="6428450836711225518">Verifiko numrin e telefonit</translation>
<translation id="6433490469411711332">Redakto informacionin e kontaktit</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> e refuzoi lidhjen.</translation>
-<translation id="6434309073475700221">Hidhe</translation>
<translation id="6440503408713884761">Shpërfillur</translation>
<translation id="6443406338865242315">Cilat shtesa dhe përbërës shtesë ke instaluar</translation>
<translation id="6446163441502663861">Kahu (Zarf)</translation>
@@ -1485,6 +1525,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="6624427990725312378">Informacionet e kontaktit</translation>
<translation id="6626291197371920147">Shto numër të vlefshëm karte</translation>
<translation id="6628463337424475685">Kërkimi me <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Po gjen pajisjet USB...</translation>
<translation id="6630809736994426279">Sulmuesit aktualisht në <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> mund të tentojnë të instalojnë programe të rrezikshme në kompjuterin tënd Mac, që vjedhin ose fshijnë informacionin tënd (për shembull, fotografi, fjalëkalime, mesazhe dhe karta krediti). <ph name="BEGIN_LEARN_MORE_LINK" />Mëso më shumë<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Pastro</translation>
@@ -1500,6 +1541,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="6671697161687535275">Të hiqet sugjerimi i formularit nga Chromium?</translation>
<translation id="6685834062052613830">Dil dhe përfundo konfigurimin</translation>
<translation id="6687335167692595844">Kërkohet madhësia e fontit</translation>
+<translation id="6688743156324860098">Përditëso…</translation>
<translation id="6689249931105087298">Relative me ngjeshjen e pikës së zezë</translation>
<translation id="6689271823431384964">Chrome po ofron që të ruash kartat e tua në "Llogarinë tënde të Google" sepse je identifikuar. Mund ta ndryshosh këtë sjellje te cilësimet. Emri i mbajtësit të kartës vjen nga llogaria jote.</translation>
<translation id="6698381487523150993">Krijuar:</translation>
@@ -1515,6 +1557,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="6744009308914054259">Ndërkohë që pret për një lidhje, mund të vizitosh "Shkarkimet" për të lexuar artikuj jashtë linje.</translation>
<translation id="6753269504797312559">Vlera e politikës</translation>
<translation id="6757797048963528358">Pajisja jote kaloi në gjumë.</translation>
+<translation id="6767985426384634228">Të përditësohet adresa?</translation>
<translation id="6768213884286397650">Hagaki (Kartolinë)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Vjollcë</translation>
@@ -1537,6 +1580,7 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome e ka thjeshtuar këtë faqe për ta bërë më të lehtë për t'u lexuar. Chrome e mori faqen origjinale nëpërmjet një lidhjeje të pasigurt.</translation>
<translation id="6891596781022320156">Niveli i politikës nuk mbështetet.</translation>
+<translation id="6895143722905299846">Numri virtual:</translation>
<translation id="6895330447102777224">Karta jote është konfirmuar</translation>
<translation id="6897140037006041989">Agjenti i përdoruesit</translation>
<translation id="6898699227549475383">Organizata (O)</translation>
@@ -1572,10 +1616,10 @@ Ndryshe kjo do të bllokohet nga cilësimet e tua të privatësisë. Kjo do ta l
<translation id="7004583254764674281">Përdor Windows Hello për t'i konfirmuar kartat më shpejt</translation>
<translation id="7006930604109697472">Dërgoje gjithsesi</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Cilësimet e ndryshimit të përmasave</translation>
<translation id="7014741021609395734">Niveli i zmadhimit</translation>
<translation id="7016992613359344582">Këto tarifa mund të jenë vetëm për një rast ose dhe të përsëritura, gjë që mund të mos jetë menjëherë e qartë.</translation>
<translation id="7029809446516969842">Fjalëkalimet</translation>
+<translation id="7030436163253143341">Certifikata nuk është e vlefshme</translation>
<translation id="7031646650991750659">Cilat aplikacione të Google Play ke instaluar</translation>
<translation id="7050187094878475250">Tentove të arrije <ph name="DOMAIN" />, por serveri paraqiti një certifikatë, periudha e vlefshmërisë së të cilës është tepër e gjatë dhe nuk mund të jetë e besueshme.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Kjo kartë nuk mund të ruhet për momentin}other{Këto karta nuk mund të ruhen për momentin}}</translation>
@@ -1645,12 +1689,14 @@ Detaje shtesë:
<translation id="7300012071106347854">Blu kobalti</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">I lartë</translation>
+<translation id="7305756307268530424">Fillo më ngadalë</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Ndihma e lidhjes</translation>
<translation id="7323804146520582233">Fshihe seksionin "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Anulimi i llogarisë lokale të pajisjes</translation>
<translation id="7333654844024768166">Sapo fute fjalëkalimin tënd në një sajt mashtrues. Chromium rekomandon që të shkosh te <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> dhe sajte të tjera ku e përdor këtë fjalëkalim dhe ta ndryshosh atë tani.</translation>
<translation id="7334320624316649418">&amp;Ribëj renditjen</translation>
+<translation id="7337248890521463931">Shfaq më shumë radhë</translation>
<translation id="7337706099755338005">Nuk ofrohet në këtë platformë.</translation>
<translation id="733923710415886693">Certifikata e serverit nuk është zbuluar përmes "Transparencës së certifikatave".</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1658,6 +1704,7 @@ Detaje shtesë:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Linja e komandave</translation>
<translation id="7359588939039777303">Reklamat janë të bllokuara.</translation>
+<translation id="7363096869660964304">Sidoqoftë, ti nuk je i padukshëm. Kalimi në modalitetin "e fshehtë" nuk e fsheh shfletimin tënd nga punëdhënësi yt, ofruesi i shërbimit të internetit apo sajtet e uebit që viziton.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />. Shtyp "Tab" dhe më pas "Enter" për të shtuar dhe menaxhuar adresat te cilësimet e Chrome</translation>
<translation id="7365849542400970216">Të dinë përdorimin e pajisjes sate?</translation>
<translation id="7372973238305370288">rezultati i kërkimit</translation>
@@ -1668,7 +1715,9 @@ Detaje shtesë:
<translation id="7378594059915113390">Kontrollet e klipeve media</translation>
<translation id="7378627244592794276">Jo</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Nuk është i zbatueshëm</translation>
<translation id="7390545607259442187">Konfirmo kartën</translation>
+<translation id="7392089738299859607">Përditëso adresën</translation>
<translation id="7399802613464275309">Kontrolli i sigurisë</translation>
<translation id="7400418766976504921">URL-ja</translation>
<translation id="7403591733719184120">Pajisja jote <ph name="DEVICE_NAME" /> është e menaxhuar</translation>
@@ -1683,6 +1732,7 @@ Detaje shtesë:
&lt;li&gt;Vizito &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Qendrën e ndihmës së Chrome&lt;/a&gt; për të mësuar se si të heqësh përgjithmonë softuerin nga kompjuteri yt
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">I këndshëm</translation>
<translation id="7416351320495623771">Menaxho fjalëkalimet…</translation>
<translation id="7419106976560586862">Shtegu i profilit</translation>
<translation id="7437289804838430631">Shto informacionet e kontaktit</translation>
@@ -1698,7 +1748,7 @@ Detaje shtesë:
<translation id="7481312909269577407">Përpara</translation>
<translation id="7485870689360869515">Nuk u gjetën të dhëna.</translation>
<translation id="7495528107193238112">Kjo përmbajtje është bllokuar. Kontakto me zotëruesin e sajtit për të rregulluar problemin.</translation>
-<translation id="7498234416455752244">Vazhdo redaktimin</translation>
+<translation id="7498193950643227031">Mund të shfaqë sjellje të papritura nëse ndryshohen përmasat. Tani mund ta kufizosh aftësinë për ndryshimin e përmasave të aplikacioneve te <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Sapo e fute fjalëkalimin tënd në një sajt mashtrues. Chromium të rekomandon t'i kontrollosh fjalëkalimet e tua të ruajtura për <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> dhe sajte të tjera ku e përdor këtë fjalëkalim tani.</translation>
<translation id="7508255263130623398">ID-ja e kthyer e pajisjes së politikës është bosh ose nuk përputhet me ID-në e pajisjes aktuale</translation>
<translation id="7508870219247277067">Jeshile avokadoje</translation>
@@ -1718,6 +1768,7 @@ Detaje shtesë:
<translation id="7548892272833184391">Rregullo gabimet në lidhje</translation>
<translation id="7549584377607005141">Që të shfaqet si duhet, kjo faqe uebi kërkon të dhëna që i ke futur më herët. Mund t'i dërgosh përsëri këto të dhëna, por duke bërë këtë, do të përsëritësh çdo veprim që ka kryer më parë kjo faqe.</translation>
<translation id="7550637293666041147">Emri i përdoruesit të pajisjes dhe emri i përdoruesit të Chrome</translation>
+<translation id="755279583747225797">Prova është aktive</translation>
<translation id="7552846755917812628">Provo këshillat e mëposhtme:</translation>
<translation id="7554475479213504905">Ringarkoje dhe shfaqe gjithsesi</translation>
<translation id="7554791636758816595">Skedë e re</translation>
@@ -1736,7 +1787,6 @@ Detaje shtesë:
<translation id="7610193165460212391">Vlera është jashtë gamës <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Data e skadimit: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, shtyp "Tab", më pas "Enter" për të shikuar dhe menaxhuar fjalëkalimet e tua te cilësimet e Chrome</translation>
-<translation id="7615602087246926389">Ke tashmë të dhëna që janë të enkriptuara me një version të ndryshëm të fjalëkalimit tënd të Llogarisë Google. Futi ato më poshtë.</translation>
<translation id="7616645509853975347">Administratori yt ka aktivizuar Chrome Enterprise Connectors në shfletuesin tënd. Këta bashkues kanë qasje te disa nga të dhënat e tua.</translation>
<translation id="7619838219691048931">Fleta e fundit</translation>
<translation id="762844065391966283">Një nga një</translation>
@@ -1801,13 +1851,12 @@ Detaje shtesë:
<translation id="782886543891417279">Lidhja Wi-Fi që po përdor (<ph name="WIFI_NAME" />) mund të kërkojë që të vizitosh faqen e saj të lidhjes.</translation>
<translation id="7836231406687464395">Postfix (Zarf)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Asnjë}=1{1 aplikacion (<ph name="EXAMPLE_APP_1" />)}=2{2 aplikacione (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# aplikacione (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Sidoqoftë, ti nuk je i padukshëm. Kalimi në modalitetin "e fshehtë" nuk e fsheh shfletimin tënd nga punëdhënësi yt, ofruesi i shërbimit të internetit apo sajtet e uebit që viziton.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Të hapë skedarët me lidhjet e llojeve të skedarëve.</translation>
<translation id="7862185352068345852">Dëshiron të largohesh nga sajti?</translation>
<translation id="7865448901209910068">Shpejtësia më e mirë</translation>
<translation id="7874263914261512992">Sapo e fute fjalëkalimin tënd në një sajt mashtrues. Chrome të rekomandon të kontrollosh fjalëkalimet e tua të ruajtura për <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> dhe sajte të tjera ku e përdor këtë fjalëkalim tani.</translation>
<translation id="7878562273885520351">Fjalëkalimet e tua mund të jenë kompromentuar</translation>
+<translation id="7880146494886811634">Ruaj adresën</translation>
<translation id="7882421473871500483">Kafe</translation>
<translation id="7887683347370398519">Kontrollo CVC-në tënde dhe provo përsëri</translation>
<translation id="7887885240995164102">Hyr në veçorinë "figurë brenda figurës"</translation>
@@ -1815,6 +1864,7 @@ Detaje shtesë:
<translation id="7894280532028510793">Nëse nuk ka ndonjë gabim drejtshkrimor, <ph name="BEGIN_LINK" />provo të ekzekutosh "Diagnostikimin e rrjetit"<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Zarf)</translation>
<translation id="7931318309563332511">E panjohur</translation>
+<translation id="793209273132572360">Të përditësohet adresa?</translation>
<translation id="7932579305932748336">Veshje</translation>
<translation id="79338296614623784">Fut një numër të vlefshëm telefoni</translation>
<translation id="7934052535022478634">Pagesa përfundoi</translation>
@@ -1885,6 +1935,7 @@ Detaje shtesë:
<translation id="8175796834047840627">Chrome po ofron që të ruash kartat e tua në "Llogarinë tënde të Google" sepse je identifikuar. Mund ta ndryshosh këtë sjellje te cilësimet.</translation>
<translation id="8176440868214972690">Administratori i kësaj pajisjeje ka dërguar disa informacione te sajtet e mëposhtme të uebit, si p.sh. cilësime ose politika.</translation>
<translation id="8184538546369750125">Përdor parazgjedhjen globale (Lejo)</translation>
+<translation id="8193086767630290324">Veprimet e kryera me të dhënat e raportuara si konfidenciale</translation>
<translation id="8194797478851900357">&amp;Zhbëj zhvendosjen</translation>
<translation id="8201077131113104583">URL e pavlefshme përditësimi për shtesën me ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Përmbledhja e porosisë</translation>
@@ -1907,6 +1958,7 @@ Detaje shtesë:
<translation id="8249296373107784235">Ndërprite</translation>
<translation id="8249320324621329438">Marrja e fundit:</translation>
<translation id="8253091569723639551">Adresa e faturimit është e detyrueshme</translation>
+<translation id="8257387598443225809">Ky aplikacion është projektuar për celular</translation>
<translation id="825929999321470778">Shfaq të gjitha fjalëkalimet e ruajtura</translation>
<translation id="8261506727792406068">Fshi</translation>
<translation id="8262952874573525464">Qepje anësore poshtë</translation>
@@ -2030,7 +2082,6 @@ Detaje shtesë:
<translation id="8719528812645237045">Shumë shpime lart</translation>
<translation id="8725066075913043281">Provo sërish</translation>
<translation id="8726549941689275341">Madhësia e faqes:</translation>
-<translation id="8728672262656704056">Ke kaluar në modalitetin "e fshehtë"</translation>
<translation id="8730621377337864115">U krye</translation>
<translation id="8731544501227493793">Menaxho butonin e fjalëkalimeve, shtyp "Enter" për të parë dhe menaxhuar fjalëkalimet e tua në cilësimet e Chrome</translation>
<translation id="8734529307927223492">Pajisja jote <ph name="DEVICE_TYPE" /> menaxhohet nga <ph name="MANAGER" /></translation>
@@ -2107,6 +2158,7 @@ Detaje shtesë:
<translation id="9020542370529661692">Kjo faqe është përkthyer në <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(E pavlefshme)</translation>
+<translation id="9030265603405983977">Monokrom</translation>
<translation id="9035022520814077154">Gabim i sigurisë</translation>
<translation id="9038649477754266430">Përdor një shërbim parashikimi për t'i ngarkuar faqet më shpejt</translation>
<translation id="9039213469156557790">Për më tepër, kjo faqe përfshin burime të tjera që nuk janë të sigurta. Këto burime mund të shikohen nga të tjerët kur janë në procesin e kalimit dhe mund të modifikohen nga ndonjë sulmues për të ndryshuar sjelljen e faqes.</translation>
@@ -2130,6 +2182,7 @@ Detaje shtesë:
<translation id="91108059142052966">Politika e administratorit çaktivizon ndarjen e ekranit me <ph name="APPLICATION_TITLE" /> kur përmbajtja konfidenciale është e dukshme</translation>
<translation id="9114524666733003316">Karta po konfirmohet…</translation>
<translation id="9114581008513152754">Ky shfletues nuk menaxhohet nga një kompani ose organizatë tjetër. Aktiviteti në këtë pajisje mund të menaxhohet jashtë Chrome. <ph name="BEGIN_LINK" />Mëso më shumë<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">I freskët</translation>
<translation id="9119042192571987207">Ngarkuar</translation>
<translation id="9128016270925453879">Politikat janë ngarkuar</translation>
<translation id="9128870381267983090">Lidhu me rrjetin</translation>
@@ -2148,6 +2201,7 @@ Detaje shtesë:
<translation id="9170848237812810038">&amp;Zhbëj</translation>
<translation id="9171296965991013597">Dëshiron të dalësh nga aplikacioni?</translation>
<translation id="9173282814238175921">Një dokument i vetëm/fletë e re</translation>
+<translation id="9173995187295789444">Po skanon për pajisje Bluetooth...</translation>
<translation id="917450738466192189">Certifikata e serverit është e pavlefshme.</translation>
<translation id="9174917557437862841">Butoni i ndërrimit të skedës, shtyp "Enter" për të kaluar te kjo skedë</translation>
<translation id="9179703756951298733">Menaxho informacionet e pagesave dhe të kartës së kreditit te cilësimet e Chrome</translation>
diff --git a/chromium/components/strings/components_strings_sr-Latn.xtb b/chromium/components/strings/components_strings_sr-Latn.xtb
index 9a1f68b3627..41426f193aa 100644
--- a/chromium/components/strings/components_strings_sr-Latn.xtb
+++ b/chromium/components/strings/components_strings_sr-Latn.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Ako oznaÄite ovu opciju, Chrome cÌe skladiÅ¡titi kopiju kartice na ovom ureÄ‘aju radi bržeg popunjavanja obrazaca.</translation>
<translation id="1110994991967754504">Izaberite dozvolu: <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Opozovi promenu redosleda</translation>
+<translation id="1123753900084781868">Titl uživo trenutno nije dostupan</translation>
<translation id="1125573121925420732">Upozorenja mogu Äesto da se prikazuju dok veb-sajtovi ažuriraju bezbednost. To bi uskoro trebalo da se poboljÅ¡a.</translation>
<translation id="112840717907525620">Keš smernica je u redu</translation>
<translation id="1130564665089811311">Dugme Prevedi stranicu, pritisnite Enter da biste preveli ovu stranicu pomocÌu Google prevodioca</translation>
@@ -74,6 +75,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="1240347957665416060">Naziv uređaja</translation>
<translation id="124116460088058876">Još jezika</translation>
<translation id="1243027604378859286">Autor:</translation>
+<translation id="1246424317317450637">Podebljano</translation>
<translation id="1250759482327835220">Da biste sledecÌi put platili brže, saÄuvajte karticu, ime i adresu za obraÄun na Google nalogu.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sinhronizovano)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ako posetite veb-sajt i on se ne otvori, prvo probajte da otklonite greÅ¡ku pomocÌu ovih koraka za reÅ¡avanje problema:&lt;/p&gt;
@@ -156,6 +158,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="1476595624592550506">Promenite lozinku</translation>
<translation id="1484290072879560759">Odaberite adresu za isporuku</translation>
<translation id="1492194039220927094">Slanje smernica:</translation>
+<translation id="1495677929897281669">Nazad na karticu</translation>
<translation id="1501859676467574491">Prikazuj kartice sa mog Google naloga</translation>
<translation id="1507202001669085618">&lt;p&gt;Ova greška se prikazuje ako koristite WiFi portal na kome morate da se prijavite da biste se povezali na internet.&lt;/p&gt;
&lt;p&gt;Da biste otklonili tu grešku, kliknite na &lt;strong&gt;Poveži se&lt;/strong&gt; na stranici koju pokušavate da otvorite.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="1532118530259321453">Ova stranica navodi:</translation>
<translation id="153384715582417236">To je sve za sada</translation>
<translation id="1536390784834419204">Prevedi stranicu</translation>
+<translation id="1539840569003678498">Prijava je poslata:</translation>
<translation id="154408704832528245">Odaberite adresu za dostavu</translation>
<translation id="1549470594296187301">JavaScript mora da bude omogucÌen da biste koristili ovu funkciju.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="1682696192498422849">Prvo kratka ivica</translation>
<translation id="168693727862418163">Validacija Å¡eme ove vrednosti za smernice nije uspela i zanemaricÌe se.</translation>
<translation id="168841957122794586">Sertifikat servera sadrži slab kriptografski kljuÄ.</translation>
+<translation id="1696290444144917273">Pogledajte podatke o virtuelnoj kartici</translation>
<translation id="1697532407822776718">Spremni ste!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Ovaj server ne može da dokaže da je <ph name="DOMAIN" />; datum njegovog bezbednosnog sertifikata je navodno sutraÅ¡nji. Uzrok tome je možda pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vezu.}one{Ovaj server ne može da dokaže da je <ph name="DOMAIN" />; njegov bezbednosni sertifikat je navodno datiran u buducÌnosti (za # dan). Uzrok tome je možda pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vezu.}few{Ovaj server ne može da dokaže da je <ph name="DOMAIN" />; njegov bezbednosni sertifikat je navodno datiran u buducÌnosti (za # dana). Uzrok tome je možda pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vezu.}other{Ovaj server ne može da dokaže da je <ph name="DOMAIN" />; njegov bezbednosni sertifikat je navodno datiran u buducÌnosti (za # dana). Uzrok tome je možda pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vezu.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Zanemareno jer <ph name="POLICY_NAME" /> nema vrednost <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> želi trajno da skladiÅ¡ti podatke na lokalnom raÄunaru</translation>
<translation id="1713628304598226412">2. fioka</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">3. poÅ¡tansko sanduÄe</translation>
<translation id="1718029547804390981">Dokument je isuviše veliki da biste mu dodali napomene</translation>
<translation id="1721424275792716183">* Polje je obavezno</translation>
+<translation id="1727613060316725209">Sertifikat je važecÌi</translation>
<translation id="1727741090716970331">Dodajte važecÌi broj kartice</translation>
<translation id="1728677426644403582">Pregledate izvor veb-stranice.</translation>
<translation id="173080396488393970">Ovaj tip kartice nije podržan</translation>
@@ -246,7 +253,6 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
zahtev za <ph name="SITE" />. PomocÌu smernica za poreklo
operatori sajtova mogu da konfigurišu bezbednost i druga svojstva za sajt.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Ažuriraj pristupnu frazu za sinhronizaciju</translation>
<translation id="1787142507584202372">Otvorene kartice se pojavljuju ovde</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, dostupno je više radnji, pritisnite Tab da biste ih pregledali</translation>
@@ -279,6 +285,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="1919345977826869612">Oglasi</translation>
<translation id="1919367280705858090">Potražite pomocÌ u vezi sa odreÄ‘enom porukom o greÅ¡ci</translation>
<translation id="192020519938775529">{COUNT,plural, =0{None}=1{1 sajt}one{# sajt}few{# sajta}other{# sajtova}}</translation>
+<translation id="1924727005275031552">Novo</translation>
<translation id="1945968466830820669">Mogli biste da izgubite pristup nalogu za organizaciju ili bi moglo da doÄ‘e do kraÄ‘e identiteta. Chromium vam preporuÄuje da odmah promenite lozinku.</translation>
<translation id="1947454675006758438">Spajanje u gornjem desnom uglu</translation>
<translation id="1958218078413065209">Vaš najviši rezultat je <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="2042213636306070719">7. fioka</translation>
<translation id="204357726431741734">Prijavite se da biste koristili lozinke saÄuvane na Google nalogu</translation>
<translation id="2053111141626950936">Stranice na jeziku <ph name="LANGUAGE" /> necÌe biti prevedene.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Kada je ova kontrola ukljuÄena i status je aktivan, Chrome odreÄ‘uje veliku grupu ljudi, ili kohortu, kojoj su vaÅ¡e nedavne aktivnosti pregledanja najsliÄnije. OglaÅ¡avaÄi mogu da biraju oglase za grupu i vaÅ¡e aktivnosti pregledanja ostaju privatne na ureÄ‘aju. Grupa se ažurira svakog dana.}=1{Kada je ova kontrola ukljuÄena i status je aktivan, Chrome odreÄ‘uje veliku grupu ljudi, ili kohortu, kojoj su vaÅ¡e nedavne aktivnosti pregledanja najsliÄnije. OglaÅ¡avaÄi mogu da biraju oglase za grupu i vaÅ¡e aktivnosti pregledanja ostaju privatne na ureÄ‘aju. Grupa se ažurira svakog dana.}one{Kada je ova kontrola ukljuÄena i status je aktivan, Chrome odreÄ‘uje veliku grupu ljudi, ili kohortu, kojoj su vaÅ¡e nedavne aktivnosti pregledanja najsliÄnije. OglaÅ¡avaÄi mogu da biraju oglase za grupu i vaÅ¡e aktivnosti pregledanja ostaju privatne na ureÄ‘aju. Grupa se ažurira na {NUM_DAYS} dan.}few{Kada je ova kontrola ukljuÄena i status je aktivan, Chrome odreÄ‘uje veliku grupu ljudi, ili kohortu, kojoj su vaÅ¡e nedavne aktivnosti pregledanja najsliÄnije. OglaÅ¡avaÄi mogu da biraju oglase za grupu i vaÅ¡e aktivnosti pregledanja ostaju privatne na ureÄ‘aju. Grupa se ažurira na {NUM_DAYS} dana.}other{Kada je ova kontrola ukljuÄena i status je aktivan, Chrome odreÄ‘uje veliku grupu ljudi, ili kohortu, kojoj su vaÅ¡e nedavne aktivnosti pregledanja najsliÄnije. OglaÅ¡avaÄi mogu da biraju oglase za grupu i vaÅ¡e aktivnosti pregledanja ostaju privatne na ureÄ‘aju. Grupa se ažurira na {NUM_DAYS} dana.}}</translation>
<translation id="2053553514270667976">Poštanski broj</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 predlog}one{# predlog}few{# predloga}other{# predloga}}</translation>
<translation id="2071692954027939183">ObaveÅ¡tenja su automatski blokirana jer ih obiÄno ne dozvoljavate</translation>
<translation id="2079545284768500474">Opozovi</translation>
<translation id="20817612488360358">Podešeno je da se koriste sistemska podešavanja proksija, ali je navedena eksplicitna konfiguracija proksija.</translation>
<translation id="2082238445998314030"><ph name="RESULT_NUMBER" />. od <ph name="TOTAL_RESULTS" /> rezultata</translation>
+<translation id="2085876078937250610">SaÄuvaj…</translation>
<translation id="2088086323192747268">Dugme Upravljajte sinhronizacijom, pritisnite Enter da biste upravljali time koje informacije sinhronizujete u podešavanjima Chrome-a</translation>
<translation id="2091887806945687916">Zvuk</translation>
<translation id="2094505752054353250">Domeni se ne podudaraju</translation>
@@ -379,6 +388,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="2317259163369394535"><ph name="DOMAIN" /> zahteva korisniÄko ime i lozinku.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, istiÄe <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Podešavanje kontroliše administrator</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> želi da se upari</translation>
<translation id="2344028582131185878">Automatska preuzimanja</translation>
<translation id="2346319942568447007">Kopirana slika</translation>
<translation id="2354001756790975382">Ostali obeleživaÄi</translation>
@@ -386,8 +396,10 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="2355395290879513365">NapadaÄi cÌe mocÌi da vide slike koje gledate na ovom sajtu i da ih izmene kako bi vas prevarili.</translation>
<translation id="2356070529366658676">Pitaj</translation>
<translation id="2357481397660644965">Uređajem upravlja <ph name="DEVICE_MANAGER" />, a nalogom <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Za manje od jednog dana}=1{Za jedan dan}one{Za {NUM_DAYS} dan}few{Za {NUM_DAYS} dana}other{Za {NUM_DAYS} dana}}</translation>
<translation id="2359629602545592467">Više</translation>
<translation id="2359808026110333948">Nastavite</translation>
+<translation id="2359961752320758691">Broj virtuelne kartice je primenjen.</translation>
<translation id="2367567093518048410">Nivo</translation>
<translation id="2372464001869762664">Kada budete potvrdili, podaci o kartici sa Google naloga cÌe se deliti sa ovim sajtom. PronaÄ‘ite CVC u detaljima o Plex nalogu.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="239429038616798445">Ovaj naÄin slanja nije dostupan. Isprobajte neki drugi naÄin.</translation>
<translation id="2396249848217231973">&amp;Opozovi brisanje</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Staro</translation>
<translation id="2413528052993050574">Ovaj server ne može da dokaže da je <ph name="DOMAIN" />; njegov bezbednosni sertifikat cÌe možda biti opozvan. Uzrok tome je možda pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vezu.</translation>
<translation id="2414886740292270097">Tamna</translation>
<translation id="2438874542388153331">Četvorostruko bušenje na desnoj strani</translation>
@@ -425,10 +438,10 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="2521385132275182522">Spajanje u donjem desnom uglu</translation>
<translation id="2523886232349826891">SaÄuvano je samo na ovom ureÄ‘aju</translation>
<translation id="2524461107774643265">Dodajte još informacija</translation>
-<translation id="2526590354069164005">Radna površina</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{i još 1}one{i još #}few{i još #}other{i još #}}</translation>
<translation id="2536110899380797252">Dodaj adresu</translation>
<translation id="2539524384386349900">Otkrij</translation>
+<translation id="2541219929084442027">Stranice koje pregledate na karticama bez arhiviranja se necÌe zadržavati u istoriji pregledaÄa, skladiÅ¡tu kolaÄicÌa ili istoriji pretrage kada zatvorite sve kartice bez arhiviranja. SaÄuvacÌemo sve preuzete fajlove ili napravljene obeleživaÄe.</translation>
<translation id="2544644783021658368">Jedan dokument</translation>
<translation id="254947805923345898">Vrednost smernica nije važecÌa.</translation>
<translation id="255002559098805027">Host <ph name="HOST_NAME" /> je poslao nevažecÌi odgovor.</translation>
@@ -448,6 +461,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="2629325967560697240">Da biste dobili najviÅ¡i nivo zaÅ¡tite u Chrome-u, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />ukljuÄite poboljÅ¡anu zaÅ¡titu<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Nismo uspeli da pronađemo IP adresu servera hosta <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Nije pronađen nijedan kompatibilan uređaj.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, pa Enter da biste obrisali istoriju pregledanja, kolaÄicÌe, keÅ¡ i drugo u podeÅ¡avanjima Chrome-a</translation>
<translation id="2650446666397867134">Pristup datoteci je odbijen</translation>
@@ -494,6 +508,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="2799223571221894425">Ponovo pokreni</translation>
<translation id="2803306138276472711">Google bezbedno pregledanje je nedavno <ph name="BEGIN_LINK" />otkrilo malver<ph name="END_LINK" /> na <ph name="SITE" />. Veb-sajtovi koji su obiÄno bezbedni se ponekad zaraze malverom.</translation>
<translation id="2807052079800581569">Pozicija slike na Y osi</translation>
+<translation id="2820957248982571256">Skenira se...</translation>
<translation id="2824775600643448204">Traka za adresu i pretragu</translation>
<translation id="2826760142808435982">Veza je Å¡ifrovana i njena autentiÄnost je potvrÄ‘ena pomocÌu <ph name="CIPHER" /> i koristi <ph name="KX" /> kao mehanizam za razmenu Å¡ifara.</translation>
<translation id="2835170189407361413">Obriši obrazac</translation>
@@ -501,6 +516,8 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="2850739647070081192">Invite (koverat)</translation>
<translation id="2856444702002559011">NapadaÄi možda pokuÅ¡avaju da ukradu informacije sa <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (na primer, lozinke, poruke ili kreditne kartice). <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte viÅ¡e<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Ovaj sajt prikazuje oglase koji ometaju aktivnosti ili obmanjujucÌe oglase.</translation>
+<translation id="287596039013813457">Prijateljski</translation>
+<translation id="2876489322757410363">NapusticÌete režim bez arhiviranja da biste platili u spoljnoj aplikaciji. Želite li da nastavite?</translation>
<translation id="2878197950673342043">Presavijanje u obliku postera</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Postavljanje prozora</translation>
@@ -550,7 +567,6 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="3060227939791841287">C9 (koverat)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, pa Enter da biste pokrenuli bezbednosnu proveru u Chrome podešavanjima</translation>
<translation id="3061707000357573562">Usluga krpljenja</translation>
-<translation id="3064966200440839136">NapusticÌete režim bez arhiviranja da biste platili u spoljnoj aplikaciji. Želite li da nastavite?</translation>
<translation id="306573536155379004">Igra je pokrenuta.</translation>
<translation id="3080254622891793721">Slika</translation>
<translation id="3086579638707268289">Vaše aktivnosti na vebu se prate</translation>
@@ -573,7 +589,6 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="315504272643575312">Vašim nalogom upravlja <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Ponovo otvori</translation>
<translation id="3162559335345991374">WiFi mreža koju koristite cÌe možda zahtevati da posetite stranicu za prijavljivanje.</translation>
-<translation id="3167968892399408617">Stranice koje pregledate na karticama bez arhiviranja se necÌe zadržavati u istoriji pregledaÄa, skladiÅ¡tu kolaÄicÌa ili istoriji pretrage kada zatvorite sve kartice bez arhiviranja. SaÄuvacÌemo sve preuzete datoteke ili napravljene obeleživaÄe.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ostrvo</translation>
<translation id="3176929007561373547">Proverite podešavanja proksija ili kontaktirajte administratora mreže da
@@ -599,10 +614,12 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="3229041911291329567">Informacije o verziji za ureÄ‘aj i pregledaÄ</translation>
<translation id="323107829343500871">Unesite CVC za karticu <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Uvek otkrivaj važan sadržaj na ovom sajtu</translation>
+<translation id="3249845759089040423">Hipi</translation>
<translation id="3252266817569339921">francuski</translation>
<translation id="3266793032086590337">Vrednost (neusaglašena)</translation>
<translation id="3268451620468152448">Otvorene kartice</translation>
<translation id="3270847123878663523">&amp;Opozovi promenu redosleda</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> želi da se poveže</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">VaÅ¡a organizacija, <ph name="ENROLLMENT_DOMAIN" />, poslala je odreÄ‘ene podatke sledecÌim veb-sajtovima, poput podeÅ¡avanja ili smernica.</translation>
<translation id="3282497668470633863">Dodajte ime na kartici</translation>
@@ -655,6 +672,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="3428151540071562330">Jedan ili viÅ¡e URI-ja Å¡ablona DnsOverHttpsTemplates servera su nevažecÌi i necÌe se koristiti.</translation>
<translation id="3431636764301398940">SaÄuvaj ovu karticu na ovom ureÄ‘aju</translation>
<translation id="3432601291244612633">Zatvori stranicu</translation>
+<translation id="3435738964857648380">Bezbednost</translation>
<translation id="3435896845095436175">OmogucÌi</translation>
<translation id="3438829137925142401">Koristite lozinke saÄuvane na Google nalogu</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="3584299510153766161">Dvostruko bušenje na dnu</translation>
<translation id="3586931643579894722">Sakrij detalje</translation>
<translation id="3587738293690942763">Srednje</translation>
+<translation id="3590643883886679995">Podaci o prijavljivanju se Äuvaju na ovom ureÄ‘aju kada izaÄ‘ete iz režima bez arhiviranja.</translation>
+<translation id="359126217934908072">Mesec/godina:</translation>
<translation id="3592413004129370115">Italian (koverat)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Grupu možete da resetujete u bilo kom trenutku. Pridruživanje novoj grupi traje otprilike jedan dan.}=1{Grupu možete da resetujete u bilo kom trenutku. Pridruživanje novoj grupi traje otprilike jedan dan.}one{Grupu možete da resetujete u bilo kom trenutku. Pridruživanje novoj grupi traje otprilike {NUM_DAYS} dan.}few{Grupu možete da resetujete u bilo kom trenutku. Pridruživanje novoj grupi traje otprilike {NUM_DAYS} dana.}other{Grupu možete da resetujete u bilo kom trenutku. Pridruživanje novoj grupi traje otprilike {NUM_DAYS} dana.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Administrator blokira aplikaciju</translation>
<translation id="3608932978122581043">Smer unosa</translation>
@@ -706,13 +727,13 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="3615877443314183785">Unesite važecÌi datum isteka</translation>
<translation id="36224234498066874">Obriši podatke pregledanja...</translation>
<translation id="362276910939193118">Prikaži kompletnu istoriju</translation>
-<translation id="3625635938337243871">Podaci o prijavljivanju se Äuvaju na ovom ureÄ‘aju kada izaÄ‘ete iz režima bez arhiviranja.</translation>
<translation id="3630155396527302611">Ako je vecÌ naveden kao program kome je dozvoljen pristup mreži, pokuÅ¡ajte da ga
uklonite sa liste i da ga ponovo dodate.</translation>
<translation id="3630699740441428070">Administratori ovog ureÄ‘aja su konfigurisali mrežnu vezu, Å¡to može da im omogucÌi da vide mrežni saobracÌaj, ukljuÄujucÌi veb-sajtove koje posecÌujete.</translation>
<translation id="3631244953324577188">Biometrija</translation>
<translation id="3633738897356909127">Dugme Ažuriraj Chrome, pritisnite Enter da biste ažurirali Chrome iz podešavanja Chrome-a</translation>
<translation id="3634530185120165534">5. fioka</translation>
+<translation id="3637662659967048211">SaÄuvajte na Google nalogu</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Aplikacija:</translation>
<translation id="3650584904733503804">Potvrda valjanosti je uspela</translation>
@@ -753,6 +774,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="3781428340399460090">Jarkoroze</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth uređaji</translation>
+<translation id="3787675388804467730">Broj virtuelne kartice</translation>
<translation id="3787705759683870569">IstiÄe <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">VeliÄina 16</translation>
<translation id="3789841737615482174">Instaliraj</translation>
@@ -772,6 +794,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="3841184659773414994">ObraÄ‘ivaÄi fajlova</translation>
<translation id="385051799172605136">Nazad</translation>
<translation id="3858027520442213535">Ažurirajte datum i vreme</translation>
+<translation id="3881478300875776315">Prikaži manje redova</translation>
<translation id="3884278016824448484">Neusaglašeni identifikator uređaja</translation>
<translation id="3885155851504623709">Parohija</translation>
<translation id="388632593194507180">Otkriveno je pracÌenje</translation>
@@ -797,6 +820,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="397105322502079400">IzraÄunavanje...</translation>
<translation id="3973234410852337861">Host <ph name="HOST_NAME" /> je blokiran</translation>
<translation id="3973357910713125165">Dugme Pokrenite Chrome bezbednosnu proveru, pritisnite Enter da biste pokrenuli bezbednosnu proveru u Chrome podešavanjima</translation>
+<translation id="3986705137476756801">IskljuÄi Titl uživo za sada</translation>
<translation id="3987405730340719549">Chrome je utvrdio da je ovaj sajt možda lažan ili služi za prevaru.
Ako mislite da se ovo prikazuje greškom, posetite https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="4275830172053184480">Ponovno pokretanje uređaja</translation>
<translation id="4277028893293644418">Resetujte lozinku</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Ova kartica je saÄuvana na Google nalogu}one{Ove kartice su saÄuvane na Google nalogu}few{Ove kartice su saÄuvane na Google nalogu}other{Ove kartice su saÄuvane na Google nalogu}}</translation>
+<translation id="4287885627794386150">Ispunjava uslove za probu, ali nije aktivno</translation>
<translation id="4297502707443874121">SliÄica za <ph name="THUMBNAIL_PAGE" />. stranicu</translation>
<translation id="42981349822642051">Proširite</translation>
<translation id="4300675098767811073">Višestruko bušenje na desnoj strani</translation>
<translation id="4302514097724775343">Dodirnite dinosaurusa da biste igrali</translation>
<translation id="4302965934281694568">Chou3 (koverat)</translation>
<translation id="4305666528087210886">Pristup datoteci nije uspeo</translation>
-<translation id="4305817255990598646">Pređi</translation>
+<translation id="4306529830550717874">Želite da saÄuvate adresu?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blokiraj (podrazumevano)</translation>
<translation id="4314815835985389558">Upravljajte sinhronizacijom</translation>
@@ -926,6 +951,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="4377125064752653719">PokuÅ¡ali ste da kontaktirate <ph name="DOMAIN" />, ali je izdavaÄ opozvao sertifikat koji je server naveo. To znaÄi da nikako ne treba imati poverenja u bezbednosne akreditive koje je server naveo. MogucÌe je da komunicirate sa napadaÄem.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Obod</translation>
+<translation id="4406883609789734330">Titl uživo</translation>
<translation id="4406896451731180161">rezultati pretrage</translation>
<translation id="4408413947728134509">KolaÄicÌi (<ph name="NUM_COOKIES" />)</translation>
<translation id="4414290883293381923">Upravo ste uneli lozinku na obmanjujucÌem sajtu. Chrome vam preporuÄuje da odete na <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> i na druge sajtove gde koristite ovu lozinku i da je odmah promenite.</translation>
@@ -938,7 +964,6 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="4435702339979719576">razglednica)</translation>
<translation id="443673843213245140">KoriÅ¡cÌenje proksija je onemogucÌeno, ali je navedena eksplicitna konfiguracija proksija.</translation>
<translation id="4464826014807964867">Veb-sajtovi sa podacima iz vaše organizacije</translation>
-<translation id="4466881336512663640">Promene obrasca se necÌe saÄuvati. Želite li stvarno da nastavite?</translation>
<translation id="4476953670630786061">Ovaj obrazac nije bezbedan. Automatsko popunjavanje je iskljuÄeno.</translation>
<translation id="4477350412780666475">SledecÌa pesma</translation>
<translation id="4482953324121162758">Ovaj sajt necÌe biti preveden.</translation>
@@ -972,6 +997,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="4594403342090139922">&amp;Opozovi brisanje</translation>
<translation id="4597348597567598915">VeliÄina 8</translation>
<translation id="4600854749408232102">C6/C5 (koverat)</translation>
+<translation id="4606870351894164739">UpeÄatljivo</translation>
<translation id="4628948037717959914">Slika</translation>
<translation id="4631649115723685955">Povezan je povracÌaj gotovine</translation>
<translation id="4636930964841734540">Informacije</translation>
@@ -991,6 +1017,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="4691835149146451662">Architecture-A (koverat)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Strana</translation>
+<translation id="4702656508969495934">Vidi se titl uživo. Koristite dugme za promenu prozora da biste fokusirali</translation>
<translation id="4708268264240856090">Veza je prekinuta</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />da pokrenete Windows dijagnostiku mreže<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="4738601419177586157">Predlog za pretragu <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Upravljaj lozinkama...</translation>
<translation id="4744603770635761495">Putanja izvršne datoteke</translation>
+<translation id="4749011317274908093">Prešli ste na režim bez arhiviranja</translation>
<translation id="4750917950439032686">Informacije (na primer, lozinke ili brojevi kreditnih kartica) su privatne kada se Å¡alju ovom sajtu.</translation>
<translation id="4756388243121344051">&amp;Istorija</translation>
<translation id="4758311279753947758">Dodaj kontakt informacije</translation>
@@ -1033,6 +1061,8 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="4813512666221746211">Greška na mreži</translation>
<translation id="4816492930507672669">Uklopi u stranicu</translation>
<translation id="4819347708020428563">Želite li da izmenite komentare u podrazumevanom prikazu?</translation>
+<translation id="4825507807291741242">MocÌno</translation>
+<translation id="4838327282952368871">ÄŒarobno</translation>
<translation id="484462545196658690">Automatski</translation>
<translation id="4850886885716139402">Prikaz</translation>
<translation id="485316830061041779">nemaÄki</translation>
@@ -1169,6 +1199,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="5314967030527622926">Alat za pravljenje brošure</translation>
<translation id="5316812925700871227">Okrenite u smeru suprotnom od kazaljke na satu</translation>
<translation id="5317780077021120954">SaÄuvaj</translation>
+<translation id="5321288445143113935">Maksimalno uvecÌano</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" />. od <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Odaberite kontakt informacije</translation>
<translation id="5327248766486351172">Naziv</translation>
@@ -1176,11 +1207,13 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="5332219387342487447">NaÄin isporuke</translation>
<translation id="5333022057423422993">Chrome je pronaÅ¡ao lozinku koju ste upravo koristili pri povredi podataka. Da biste zaÅ¡titili naloge, preporuÄujemo vam da proverite saÄuvane lozinke.</translation>
<translation id="5334013548165032829">Detaljne evidencije sistema</translation>
+<translation id="5334145288572353250">Želite da saÄuvate adresu?</translation>
<translation id="5340250774223869109">Aplikacija je blokirana</translation>
<translation id="534295439873310000">NFC uređaji</translation>
<translation id="5344579389779391559">Ova stranica može da pokuša da vam nešto naplati</translation>
<translation id="5355557959165512791">Trenutno ne možete da posetite <ph name="SITE" /> jer je njegov sertifikat opozvan. GreÅ¡ke i napadi na mreži su obiÄno privremeni, pa cÌe ova stranica verovatno funkcionisati kasnije.</translation>
<translation id="536296301121032821">Skladištenje podešavanja smernica nije uspelo</translation>
+<translation id="5363309033720083897">Administrator je dozvolio serijski port</translation>
<translation id="5371425731340848620">Ažurirajte karticu</translation>
<translation id="5377026284221673050">„Sat kasni“ ili „Sat žuri“ ili „&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;“</translation>
<translation id="5386426401304769735">Lanac sertifikata za ovaj sajt sadrži sertifikat potpisan pomocÌu algoritma SHA-1.</translation>
@@ -1189,6 +1222,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="5398772614898833570">Oglasi su blokirani</translation>
<translation id="5400836586163650660">Siva</translation>
<translation id="540969355065856584">Ovaj server ne može da dokaže da je <ph name="DOMAIN" />; njegov bezbednosni sertifikat trenutno nije važecÌi. Uzrok tome je možda pogreÅ¡na konfiguracija ili napadaÄ koji je prekinuo vezu.</translation>
+<translation id="541143247543991491">Klaud (na nivou sistema)</translation>
<translation id="541416427766103491">4. pregrada za slaganje</translation>
<translation id="5421136146218899937">Obriši podatke pregledanja...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> želi da vam šalje obaveštenja</translation>
@@ -1202,6 +1236,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="5455374756549232013">Neispravna vremenska oznaka smernica</translation>
<translation id="5457113250005438886">NevažecÌ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="5463625433003343978">Traže se uređaji…</translation>
<translation id="5469868506864199649">italijanski</translation>
<translation id="5470861586879999274">&amp;Ponovi izmenu</translation>
<translation id="5478437291406423475">B6/C4 (koverat)</translation>
@@ -1251,7 +1286,6 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="5624120631404540903">Upravljaj lozinkama</translation>
<translation id="5629630648637658800">UÄitavanje podeÅ¡avanja smernica nije uspelo</translation>
<translation id="5631439013527180824">NevažecÌi token za upravljanje ureÄ‘ajima</translation>
-<translation id="5632627355679805402">Podaci su Å¡ifrovani pomocÌu <ph name="BEGIN_LINK" />Google lozinke<ph name="END_LINK" /> (<ph name="TIME" />). Unesite je da biste zapoÄeli sinhronizaciju.</translation>
<translation id="5633066919399395251">NapadaÄi na <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> cÌe možda pokuÅ¡ati da instaliraju opasne programe na raÄunaru koji kradu ili briÅ¡u informacije (na primer, slike, lozinke, poruke i brojeve kreditnih kartica). <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte viÅ¡e<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">ObmanjujucÌi sadržaj je blokiran.</translation>
<translation id="5644090287519800334">Pomeranje slike 1. strane po X osi</translation>
@@ -1290,12 +1324,12 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="5785756445106461925">Pored toga, ova stranica sadrži i druge resurse koji nisu bezbedni. Ove resurse mogu da vide i drugi dok su u prolazu i napadaÄ može da ih izmeni kako bi promenio izgled stranice.</translation>
<translation id="5786044859038896871">Želite li da popunite informacije o kartici?</translation>
<translation id="578633867165174378">Chrome je pronaÅ¡ao lozinku koju ste upravo koristili pri povredi podataka. PreporuÄujemo vam da odmah promenite tu lozinku.</translation>
-<translation id="5798290721819630480">Želite li da odbacite promene?</translation>
<translation id="5803412860119678065">Želite li da popunite podacima <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Dozvole</translation>
<translation id="5804427196348435412">koristi NFC uređaje</translation>
<translation id="5810442152076338065">Veza sa domenom <ph name="DOMAIN" /> je Å¡ifrovana pomocÌu zastarelog paketa za Å¡ifrovanje.</translation>
<translation id="5813119285467412249">&amp;Ponovi dodavanje</translation>
+<translation id="5817918615728894473">Upari</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Sa ove kartice cÌe vam biti naplacÌeno kada platite, ali njen pravi broj se necÌe deliti sa ovim sajtom. GenerisacÌe se privremeni CVC kao dodatna mera bezbednosti.}one{Sa kartice koju izaberete bicÌe vam naplacÌeno kada platite, ali njen pravi broj se necÌe deliti sa ovim sajtom. GenerisacÌe se privremeni CVC kao dodatna mera bezbednosti.}few{Sa kartice koju izaberete bicÌe vam naplacÌeno kada platite, ali njen pravi broj se necÌe deliti sa ovim sajtom. GenerisacÌe se privremeni CVC kao dodatna mera bezbednosti.}other{Sa kartice koju izaberete bicÌe vam naplacÌeno kada platite, ali njen pravi broj se necÌe deliti sa ovim sajtom. GenerisacÌe se privremeni CVC kao dodatna mera bezbednosti.}}</translation>
<translation id="5826507051599432481">Opšte ime (CN)</translation>
<translation id="5838278095973806738">Nemojte da unosite osetljive informacije na ovom sajtu (na primer, lozinke ili kreditne kartice) jer napadaÄi mogu da ih ukradu.</translation>
@@ -1303,6 +1337,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="5855253129151731373">Ime hosta ovog sajta deluje sliÄno kao <ph name="LOOKALIKE_DOMAIN" />. NapadaÄi ponekad imitiraju sajtove tako Å¡to neznatno i skoro neprimetno izmene ime domena.
Ako mislite da se ovo prikazuje greškom, posetite https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">IskljuÄeno</translation>
<translation id="5862579898803147654">8. pregrada za slaganje</translation>
<translation id="5863847714970149516">SledecÌa stranica može da pokuÅ¡a da vam neÅ¡to naplati</translation>
<translation id="5866257070973731571">Dodajte broj telefona</translation>
@@ -1319,6 +1354,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="5913377024445952699">Snimanje ekrana je pauzirano</translation>
<translation id="59174027418879706">OmogucÌeno</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{Koristi se 1}one{Koristi se #}few{Koriste se #}other{Koristi se #}}</translation>
<translation id="5921185718311485855">UkljuÄeno</translation>
<translation id="5921639886840618607">Želite li da saÄuvate karticu na Google nalogu?</translation>
<translation id="5922853866070715753">Skoro je gotovo</translation>
@@ -1338,6 +1374,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="5989320800837274978">Nisu navedeni ni fiksni proksi serveri niti URL adresa .pac skripte.</translation>
<translation id="5992691462791905444">Presavijanje u obliku polu-harmonike</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> rezultata za „<ph name="SEARCH_TEXT" />“</translation>
+<translation id="6006484371116297560">KlasiÄna</translation>
<translation id="6008122969617370890">Redosled od n do 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Proverite lozinke</translation>
@@ -1359,6 +1396,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="6045164183059402045">Å ablon rasporeda stranice</translation>
<translation id="6047233362582046994">Ako razumete bezbednosne rizike, možete da <ph name="BEGIN_LINK" />posetite ovaj sajt<ph name="END_LINK" /> pre nego što uklonimo štetne aplikacije.</translation>
<translation id="6047927260846328439">Ovaj sadržaj cÌe pokuÅ¡ati da vas prevari da instalirate softver ili otkrijete liÄne podatke. <ph name="BEGIN_LINK" />Ipak prikaži<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Pritisnite i zadržite |<ph name="ACCELERATOR" />| da biste izašli iz režima celog ekrana</translation>
<translation id="6049488691372270142">Isporuka stranica</translation>
<translation id="6051221802930200923">Trenutno ne možete da posetite <ph name="SITE" /> jer veb-sajt koristi proveru sertifikata. GreÅ¡ke i napadi na mreži su obiÄno privremeni, pa cÌe ova stranica verovatno funkcionisati kasnije.</translation>
<translation id="6051898664905071243">Broj stranica:</translation>
@@ -1375,6 +1413,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="610911394827799129">Google nalog može da ima druge oblike istorije pregledanja na <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
<translation id="6116338172782435947">da vidi tekst i slike koji su kopirani u privremenu memoriju</translation>
<translation id="6120179357481664955">Želite da saÄuvate ID za UPI?</translation>
+<translation id="6123290840358279103">Prikaži virtuelnu karticu</translation>
<translation id="6124432979022149706">PrikljuÄci za Chrome za preduzecÌa</translation>
<translation id="6146055958333702838">Proverite sve kablove i restartujte sve rutere, modeme ili druge mrežne uređaje koje možda koristite.</translation>
<translation id="614940544461990577">Pokušajte:</translation>
@@ -1410,6 +1449,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="6289939620939689042">Boja stranice</translation>
<translation id="6290238015253830360">Predloženi Älanci se prikazuju ovde</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google pomocÌnik u Chrome-u se zaustavlja</translation>
<translation id="6305205051461490394">URL <ph name="URL" /> nije dostupan.</translation>
<translation id="6312113039770857350">Veb-stranica nije dostupna</translation>
@@ -1435,6 +1475,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="6390200185239044127">Presavijanje polovine u obliku slova Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Smernice za administratore blokiraju nalepljivanje sa <ph name="ORIGIN_NAME" /> na ovu lokaciju</translation>
+<translation id="6398765197997659313">Izađi iz režima celog ekrana</translation>
<translation id="6401136357288658127">Ove smernice su zastarele. Umesto njih treba da koristite nove smernice <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Izmena obeleživaÄa</translation>
<translation id="6406765186087300643">C0 (koverat)</translation>
@@ -1447,7 +1488,6 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="6428450836711225518">Verifikujte broj telefona</translation>
<translation id="6433490469411711332">Izmenite kontakt informacije</translation>
<translation id="6433595998831338502">Host <ph name="HOST_NAME" /> je odbio povezivanje.</translation>
-<translation id="6434309073475700221">Odbaci</translation>
<translation id="6440503408713884761">Zanemareno</translation>
<translation id="6443406338865242315">dodatke i dodatne komponenta koje ste instalirali</translation>
<translation id="6446163441502663861">Kahu (koverat)</translation>
@@ -1490,6 +1530,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="6624427990725312378">Kontakt informacije</translation>
<translation id="6626291197371920147">Dodajte važecÌi broj kartice</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> pretraga</translation>
+<translation id="6630043285902923878">Traže se USB uređaji…</translation>
<translation id="6630809736994426279">NapadaÄi koji su trenutno na <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> cÌe možda pokuÅ¡ati da instaliraju opasne programe na Mac-u koji kradu ili briÅ¡u podatke (na primer, slike, lozinke, poruke i brojeve kreditnih kartica). <ph name="BEGIN_LEARN_MORE_LINK" />Saznajte viÅ¡e<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Obriši</translation>
@@ -1505,6 +1546,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="6671697161687535275">Želite li da uklonite predlog iz Chromium-a?</translation>
<translation id="6685834062052613830">Odjavite se i dovršite podešavanje</translation>
<translation id="6687335167692595844">Zatražena je veliÄina fonta</translation>
+<translation id="6688743156324860098">Ažurirajte…</translation>
<translation id="6689249931105087298">Relativno sa kompresijom crnih taÄaka</translation>
<translation id="6689271823431384964">Chrome vam nudi Äuvanje kartica na Google nalogu zato Å¡to ste prijavljeni. To možete da promenite u podeÅ¡avanjima. Ime vlasnika kartice smo uzeli sa naloga.</translation>
<translation id="6698381487523150993">Napravljeno:</translation>
@@ -1520,6 +1562,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="6744009308914054259">Dok Äekate na vezu, posetite Preuzimanja i Äitajte oflajn Älanke.</translation>
<translation id="6753269504797312559">Vrednost smernica</translation>
<translation id="6757797048963528358">Uređaj je prešao u režim spavanja.</translation>
+<translation id="6767985426384634228">Želite da ažurirate adresu?</translation>
<translation id="6768213884286397650">Hagaki (razglednica)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">LjubiÄasta</translation>
@@ -1542,6 +1585,7 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome je pojednostavio ovu stranicu radi lakÅ¡eg Äitanja. Chrome je preuzeo originalnu stranicu preko nebezbedne veze.</translation>
<translation id="6891596781022320156">Nivo smernica nije podržan.</translation>
+<translation id="6895143722905299846">Virtuelni broj:</translation>
<translation id="6895330447102777224">Kartica je potvrđena</translation>
<translation id="6897140037006041989">KorisniÄki agent</translation>
<translation id="6898699227549475383">Organizacija (O)</translation>
@@ -1577,10 +1621,10 @@ To inaÄe blokiraju podeÅ¡avanja privatnosti. To omogucÌava da sadržaj sa koji
<translation id="7004583254764674281">Koristite Windows Hello za bržu potvrdu kartica</translation>
<translation id="7006930604109697472">Ipak pošalji</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">PodeÅ¡avanja promene veliÄine</translation>
<translation id="7014741021609395734">Nivo zumiranja</translation>
<translation id="7016992613359344582">Te naplate mogu da budu jednokratne ili periodiÄne i možda nisu odmah vidljive.</translation>
<translation id="7029809446516969842">Lozinke</translation>
+<translation id="7030436163253143341">Sertifikat nije važecÌi</translation>
<translation id="7031646650991750659">Google Play koje aplikacije ste instalirali</translation>
<translation id="7050187094878475250">PokuÅ¡ali ste da posetite <ph name="DOMAIN" />, ali je server predstavio sertifikat sa periodom važenja koji je predugaÄak da bi bio pouzdan.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Ova kartica trenutno ne može da se saÄuva}one{Ove kartice trenutno ne mogu da se saÄuvaju}few{Ove kartice trenutno ne mogu da se saÄuvaju}other{Ove kartice trenutno ne mogu da se saÄuvaju}}</translation>
@@ -1650,12 +1694,14 @@ Dodatni detalji:
<translation id="7300012071106347854">Kobaltnoplava</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />“</translation>
<translation id="7304030187361489308">Visok</translation>
+<translation id="7305756307268530424">PoÄnite sporije</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">PomocÌ pri povezivanju</translation>
<translation id="7323804146520582233">Sakrijte odeljak <ph name="SECTION" /></translation>
<translation id="733354035281974745">Zamena lokalnog naloga na uređaju</translation>
<translation id="7333654844024768166">Upravo ste uneli lozinku na obmanjujucÌem sajtu. Chromium vam preporuÄuje da odete na <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> i na druge sajtove gde koristite ovu lozinku i da je odmah promenite.</translation>
<translation id="7334320624316649418">&amp;Ponovi promenu redosleda</translation>
+<translation id="7337248890521463931">Prikaži više redova</translation>
<translation id="7337706099755338005">Nije dostupno na vašoj platformi.</translation>
<translation id="733923710415886693">Sertifikat servera nije otkriven pomocÌu Transparentnosti sertifikata.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1663,6 +1709,7 @@ Dodatni detalji:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Komandna linija</translation>
<translation id="7359588939039777303">Oglasi su blokirani.</translation>
+<translation id="7363096869660964304">MeÄ‘utim, niste nevidljivi. Prelaskom u režim bez arhiviranja necÌete sakriti pregledanje od poslodavca, internet provajdera ili veb-sajtova koje posecÌujete.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, pa Enter da biste dodali adrese i upravljali njima u podešavanjima Chrome-a</translation>
<translation id="7365849542400970216">DozvolicÌete sajtu da zna kada koristite ureÄ‘aj?</translation>
<translation id="7372973238305370288">rezultat pretrage</translation>
@@ -1673,7 +1720,9 @@ Dodatni detalji:
<translation id="7378594059915113390">Kontrole za medije</translation>
<translation id="7378627244592794276">Ne</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Nije primenjivo</translation>
<translation id="7390545607259442187">Potvrdite karticu</translation>
+<translation id="7392089738299859607">Ažurirajte adresu</translation>
<translation id="7399802613464275309">Bezbednosna provera</translation>
<translation id="7400418766976504921">URL adresa</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" />-om se upravlja</translation>
@@ -1688,6 +1737,7 @@ Dodatni detalji:
&lt;li&gt;Posetite &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome centar za pomocÌ&lt;/a&gt; da biste saznali kako da trajno uklonite softver sa raÄunara
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Divno</translation>
<translation id="7416351320495623771">Upravljaj lozinkama...</translation>
<translation id="7419106976560586862">Putanja profila</translation>
<translation id="7437289804838430631">Dodaj kontakt informacije</translation>
@@ -1703,7 +1753,7 @@ Dodatni detalji:
<translation id="7481312909269577407">Prosledi</translation>
<translation id="7485870689360869515">Nisu pronađeni podaci.</translation>
<translation id="7495528107193238112">Ovaj sadržaj je blokiran. Obratite se vlasniku sajta da biste rešili problem.</translation>
-<translation id="7498234416455752244">Nastavite sa izmenama</translation>
+<translation id="7498193950643227031">Može da se ponaÅ¡a neoÄekivano ako se promeni veliÄina. Sada možete da ograniÄite mogucÌnost za menjanje veliÄine aplikacija u <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Upravo ste uneli lozinku na obmanjujucÌem sajtu. Chromium vam preporuÄuje da proverite saÄuvane lozinke za <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> i druge sajtove na kojima trenutno koristite ovu lozinku.</translation>
<translation id="7508255263130623398">VracÌeni ID ureÄ‘aja za smernice je prazan ili se ne podudara sa aktuelnim ID-om ureÄ‘aja</translation>
<translation id="7508870219247277067">Zelenožuta</translation>
@@ -1723,6 +1773,7 @@ Dodatni detalji:
<translation id="7548892272833184391">Otklonite greške pri povezivanju</translation>
<translation id="7549584377607005141">Ova veb-stranica zahteva podatke koje ste uneli ranije da bi se pravilno prikazala. Možete ponovo da poÅ¡aljete te podatke, ali ako to uradite, ponovicÌete bilo koju radnju koju je ova stranica prethodno obavila.</translation>
<translation id="7550637293666041147">KorisniÄko ime ureÄ‘aja i korisniÄko ime za Chrome</translation>
+<translation id="755279583747225797">Proba je aktivna</translation>
<translation id="7552846755917812628">Isprobajte sledecÌe savete:</translation>
<translation id="7554475479213504905">Ipak ponovo uÄitaj i prikaži</translation>
<translation id="7554791636758816595">Nova kartica</translation>
@@ -1741,7 +1792,6 @@ Dodatni detalji:
<translation id="7610193165460212391">Vrednost je izvan opsega <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">IstiÄe: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, pritisnite Tab, pa Enter da biste pregledali lozinke i upravljali njima u podešavanjima Chrome-a</translation>
-<translation id="7615602087246926389">VecÌ imate podatke koji su Å¡ifrovani pomocÌu druge verzije lozinke za Google nalog. Unesite je u nastavku.</translation>
<translation id="7616645509853975347">Administrator je ukljuÄio Chrome Enterprise Connectors u pregledaÄu. Ovi prikljuÄci imaju pristup nekim vaÅ¡im podacima.</translation>
<translation id="7619838219691048931">Poslednji list</translation>
<translation id="762844065391966283">PojedinaÄno</translation>
@@ -1806,13 +1856,12 @@ Dodatni detalji:
<translation id="782886543891417279">WiFi mreža koju koristite (<ph name="WIFI_NAME" />) cÌe možda zahtevati da posetite stranicu za prijavljivanje.</translation>
<translation id="7836231406687464395">Postfix (koverat)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Nijedna}=1{1 aplikacija (<ph name="EXAMPLE_APP_1" />)}=2{2 aplikacije (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# aplikacija (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}few{# aplikacije (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# aplikacija (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Ali, niste nevidljivi. Prelaskom u režim bez arhiviranja necÌete sakriti pregledanje od poslodavca, internet provajdera ili veb-sajtova koje posecÌujete.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Otvara fajlove sa povezanim tipovima fajlova.</translation>
<translation id="7862185352068345852">Želite li da napustite sajt?</translation>
<translation id="7865448901209910068">Najbolja brzina</translation>
<translation id="7874263914261512992">Upravo ste uneli lozinku na obmanjujucÌem sajtu. Chrome vam preporuÄuje da proverite saÄuvane lozinke za <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> i druge sajtove na kojima trenutno koristite ovu lozinku.</translation>
<translation id="7878562273885520351">Lozinka je možda kompromitovana</translation>
+<translation id="7880146494886811634">SaÄuvajte adresu</translation>
<translation id="7882421473871500483">Braon</translation>
<translation id="7887683347370398519">Proverite CVC i pokušajte ponovo</translation>
<translation id="7887885240995164102">Pokreni režim slike u slici</translation>
@@ -1820,6 +1869,7 @@ Dodatni detalji:
<translation id="7894280532028510793">Ako nema grešaka, <ph name="BEGIN_LINK" />pokrenite dijagnostiku mreže<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (koverat)</translation>
<translation id="7931318309563332511">Nepoznato</translation>
+<translation id="793209273132572360">Želite da ažurirate adresu?</translation>
<translation id="7932579305932748336">Omot</translation>
<translation id="79338296614623784">Unesite važecÌi broj telefona</translation>
<translation id="7934052535022478634">PlacÌanje je dovrÅ¡eno</translation>
@@ -1890,6 +1940,7 @@ Dodatni detalji:
<translation id="8175796834047840627">Chrome vam nudi Äuvanje kartica na Google nalogu zato Å¡to ste prijavljeni. To možete da promenite u podeÅ¡avanjima.</translation>
<translation id="8176440868214972690">Administrator ovog ureÄ‘aja je poslao odreÄ‘ene podatke sledecÌim veb-sajtovima, poput podeÅ¡avanja ili smernica.</translation>
<translation id="8184538546369750125">Koristi globalnu podrazumevanu vrednost (Dozvoli)</translation>
+<translation id="8193086767630290324">Radnje sa podacima koji su oznaÄeni kao poverljivi</translation>
<translation id="8194797478851900357">&amp;Opozovi premeštanje</translation>
<translation id="8201077131113104583">NevažecÌi URL za ažuriranje za dodatak sa ID-om „<ph name="EXTENSION_ID" />“.</translation>
<translation id="8202097416529803614">Rezime porudžbine</translation>
@@ -1912,6 +1963,7 @@ Dodatni detalji:
<translation id="8249296373107784235">Otkaži</translation>
<translation id="8249320324621329438">Poslednje uÄitano:</translation>
<translation id="8253091569723639551">Adresa za obraÄun je obavezna</translation>
+<translation id="8257387598443225809">Ova aplikacija je dizajnirana za mobilne uređaje</translation>
<translation id="825929999321470778">Prikaži sve saÄuvane lozinke</translation>
<translation id="8261506727792406068">Izbriši</translation>
<translation id="8262952874573525464">Spajanje ivica Å¡avom na dnu</translation>
@@ -2036,7 +2088,6 @@ Dodatni detalji:
<translation id="8719528812645237045">Višestruko bušenje na vrhu</translation>
<translation id="8725066075913043281">Probajte ponovo</translation>
<translation id="8726549941689275341">VeliÄina stranice:</translation>
-<translation id="8728672262656704056">Prešli ste u režim Bez arhiviranja</translation>
<translation id="8730621377337864115">Gotovo</translation>
<translation id="8731544501227493793">Dugme Upravljaj lozinkama, pritisnite Enter da biste pregledali lozinke i upravljali njima u podešavanjima Chrome-a</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" />-om upravlja <ph name="MANAGER" /></translation>
@@ -2113,6 +2164,7 @@ Dodatni detalji:
<translation id="9020542370529661692">Ova stranica je prevedena na <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(NevažecÌe)</translation>
+<translation id="9030265603405983977">Monohromatsko</translation>
<translation id="9035022520814077154">Bezbednosna greška</translation>
<translation id="9038649477754266430">Koristite uslugu predviÄ‘anja da biste brže uÄitavali stranice</translation>
<translation id="9039213469156557790">Pored toga, ova stranica sadrži i druge resurse koji nisu bezbedni. Ove resurse mogu da vide i drugi dok su u prolazu i napadaÄ može da ih izmeni kako bi promenio ponaÅ¡anje stranice.</translation>
@@ -2136,6 +2188,7 @@ Dodatni detalji:
<translation id="91108059142052966">Smernice za administratore onemogucÌavaju deljenje sadržaja ekrana sa aplikacijom <ph name="APPLICATION_TITLE" /> kada je vidljiv poverljivi sadržaj</translation>
<translation id="9114524666733003316">Kartica se potvrđuje...</translation>
<translation id="9114581008513152754">Ovim pregledaÄem ne upravlja kompanija niti druga organizacija. Aktivnostima na ovom ureÄ‘aju se možda upravlja van Chrome-a. <ph name="BEGIN_LINK" />Saznajte viÅ¡e<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Sveže</translation>
<translation id="9119042192571987207">Otpremljeno</translation>
<translation id="9128016270925453879">Smernice su uÄitane</translation>
<translation id="9128870381267983090">Povezivanje sa mrežom</translation>
@@ -2154,6 +2207,7 @@ Dodatni detalji:
<translation id="9170848237812810038">&amp;Opozovi</translation>
<translation id="9171296965991013597">Želite li da izađete iz aplikacije?</translation>
<translation id="9173282814238175921">Jedan dokument/novi list</translation>
+<translation id="9173995187295789444">Traže se Bluetooth uređaji...</translation>
<translation id="917450738466192189">Sertifikat servera je nevažecÌi.</translation>
<translation id="9174917557437862841">Dugme za promenu kartice, pritisnite Enter da biste prešli na tu karticu</translation>
<translation id="9179703756951298733">Upravljajte placÌanjima i informacijama o kreditnim karticama u podeÅ¡avanjima Chrome-a</translation>
diff --git a/chromium/components/strings/components_strings_sr.xtb b/chromium/components/strings/components_strings_sr.xtb
index 38e75acc935..d9eeb50c257 100644
--- a/chromium/components/strings/components_strings_sr.xtb
+++ b/chromium/components/strings/components_strings_sr.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Ðко означите ову опцију, Chrome ће Ñкладиштити копију картице на овом уређају ради бржег попуњавања образаца.</translation>
<translation id="1110994991967754504">Изаберите дозволу: <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Опозови промену редоÑледа</translation>
+<translation id="1123753900084781868">Титл уживо тренутно није доÑтупан</translation>
<translation id="1125573121925420732">Упозорења могу чеÑто да Ñе приказују док веб-Ñајтови ажурирају безбедноÑÑ‚. То би уÑкоро требало да Ñе побољша.</translation>
<translation id="112840717907525620">Кеш Ñмерница је у реду</translation>
<translation id="1130564665089811311">Дугме Преведи Ñтраницу, притиÑните Enter да биÑте превели ову Ñтраницу помоћу Google преводиоца</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Ðазив уређаја</translation>
<translation id="124116460088058876">Још језика</translation>
<translation id="1243027604378859286">Aутор:</translation>
+<translation id="1246424317317450637">Подебљано</translation>
<translation id="1250759482327835220">Да биÑте Ñледећи пут платили брже, Ñачувајте картицу, име и адреÑу за обрачун на Google налогу.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (Ñинхронизовано)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ðко поÑетите веб-Ñајт и он Ñе не отвори, прво пробајте да отклоните грешку помоћу ових корака за решавање проблема:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Промените лозинку</translation>
<translation id="1484290072879560759">Одаберите адреÑу за иÑпоруку</translation>
<translation id="1492194039220927094">Слање Ñмерница:</translation>
+<translation id="1495677929897281669">Ðазад на картицу</translation>
<translation id="1501859676467574491">Приказуј картице Ñа мог Google налога</translation>
<translation id="1507202001669085618">&lt;p&gt;Ова грешка Ñе приказује ако кориÑтите WiFi портал на коме морате да Ñе пријавите да биÑте Ñе повезали на интернет.&lt;/p&gt;
&lt;p&gt;Да биÑте отклонили ту грешку, кликните на &lt;strong&gt;Повежи Ñе&lt;/strong&gt; на Ñтраници коју покушавате да отворите.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">Ова Ñтраница наводи:</translation>
<translation id="153384715582417236">То је Ñве за Ñада</translation>
<translation id="1536390784834419204">Преведи Ñтраницу</translation>
+<translation id="1539840569003678498">Пријава је поÑлата:</translation>
<translation id="154408704832528245">Одаберите адреÑу за доÑтаву</translation>
<translation id="1549470594296187301">JavaScript мора да буде омогућен да биÑте кориÑтили ову функцију.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">Прво кратка ивица</translation>
<translation id="168693727862418163">Валидација шеме ове вредноÑти за Ñмернице није уÑпела и занемариће Ñе.</translation>
<translation id="168841957122794586">Сертификат Ñервера Ñадржи Ñлаб криптографÑки кључ.</translation>
+<translation id="1696290444144917273">Погледајте податке о виртуелној картици</translation>
<translation id="1697532407822776718">Спремни Ñте!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Овај Ñервер не може да докаже да је <ph name="DOMAIN" />; датум његовог безбедноÑног Ñертификата је наводно Ñутрашњи. Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.}one{Овај Ñервер не може да докаже да је <ph name="DOMAIN" />; његов безбедноÑни Ñертификат је наводно датиран у будућноÑти (за # дан). Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.}few{Овај Ñервер не може да докаже да је <ph name="DOMAIN" />; његов безбедноÑни Ñертификат је наводно датиран у будућноÑти (за # дана). Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.}other{Овај Ñервер не може да докаже да је <ph name="DOMAIN" />; његов безбедноÑни Ñертификат је наводно датиран у будућноÑти (за # дана). Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.}}</translation>
<translation id="1710259589646384581">ОС</translation>
+<translation id="1711234383449478798">Занемарено јер <ph name="POLICY_NAME" /> нема вредноÑÑ‚ <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> жели трајно да Ñкладишти податке на локалном рачунару</translation>
<translation id="1713628304598226412">2. фиока</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">3. поштанÑко Ñандуче</translation>
<translation id="1718029547804390981">Документ је иÑувише велики да биÑте му додали напомене</translation>
<translation id="1721424275792716183">* Поље је обавезно</translation>
+<translation id="1727613060316725209">Сертификат је важећи</translation>
<translation id="1727741090716970331">Додајте важећи број картице</translation>
<translation id="1728677426644403582">Прегледате извор веб-Ñтранице.</translation>
<translation id="173080396488393970">Овај тип картице није подржан</translation>
@@ -246,7 +253,6 @@
захтев за <ph name="SITE" />. Помоћу Ñмерница за порекло
оператори Ñајтова могу да конфигуришу безбедноÑÑ‚ и друга ÑвојÑтва за Ñајт.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Ðжурирај приÑтупну фразу за Ñинхронизацију</translation>
<translation id="1787142507584202372">Отворене картице Ñе појављују овде</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, доÑтупно је више радњи, притиÑните Tab да биÑте их прегледали</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">ОглаÑи</translation>
<translation id="1919367280705858090">Потражите помоћ у вези Ñа одређеном поруком о грешци</translation>
<translation id="192020519938775529">{COUNT,plural, =0{None}=1{1 Ñајт}one{# Ñајт}few{# Ñајта}other{# Ñајтова}}</translation>
+<translation id="1924727005275031552">Ðово</translation>
<translation id="1945968466830820669">Могли биÑте да изгубите приÑтуп налогу за организацију или би могло да дође до крађе идентитета. Chromium вам препоручује да одмах промените лозинку.</translation>
<translation id="1947454675006758438">Спајање у горњем деÑном углу</translation>
<translation id="1958218078413065209">Ваш највиши резултат је <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">7. фиока</translation>
<translation id="204357726431741734">Пријавите Ñе да биÑте кориÑтили лозинке Ñачуване на Google налогу</translation>
<translation id="2053111141626950936">Странице на језику <ph name="LANGUAGE" /> неће бити преведене.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Када је ова контрола укључена и ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ˜Ðµ активан, Chrome одређује велику групу људи, или кохорту, којој Ñу ваше недавне активноÑти прегледања најÑличније. Оглашавачи могу да бирају оглаÑе за групу и ваше активноÑти прегледања оÑтају приватне на уређају. Група Ñе ажурира Ñваког дана.}=1{Када је ова контрола укључена и ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ˜Ðµ активан, Chrome одређује велику групу људи, или кохорту, којој Ñу ваше недавне активноÑти прегледања најÑличније. Оглашавачи могу да бирају оглаÑе за групу и ваше активноÑти прегледања оÑтају приватне на уређају. Група Ñе ажурира Ñваког дана.}one{Када је ова контрола укључена и ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ˜Ðµ активан, Chrome одређује велику групу људи, или кохорту, којој Ñу ваше недавне активноÑти прегледања најÑличније. Оглашавачи могу да бирају оглаÑе за групу и ваше активноÑти прегледања оÑтају приватне на уређају. Група Ñе ажурира на {NUM_DAYS} дан.}few{Када је ова контрола укључена и ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ˜Ðµ активан, Chrome одређује велику групу људи, или кохорту, којој Ñу ваше недавне активноÑти прегледања најÑличније. Оглашавачи могу да бирају оглаÑе за групу и ваше активноÑти прегледања оÑтају приватне на уређају. Група Ñе ажурира на {NUM_DAYS} дана.}other{Када је ова контрола укључена и ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ˜Ðµ активан, Chrome одређује велику групу људи, или кохорту, којој Ñу ваше недавне активноÑти прегледања најÑличније. Оглашавачи могу да бирају оглаÑе за групу и ваше активноÑти прегледања оÑтају приватне на уређају. Група Ñе ажурира на {NUM_DAYS} дана.}}</translation>
<translation id="2053553514270667976">ПоштанÑки број</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 предлог}one{# предлог}few{# предлога}other{# предлога}}</translation>
<translation id="2071692954027939183">Обавештења Ñу аутоматÑки блокирана јер их обично не дозвољавате</translation>
<translation id="2079545284768500474">Опозови</translation>
<translation id="20817612488360358">Подешено је да Ñе кориÑте ÑиÑтемÑка подешавања прокÑија, али је наведена екÑплицитна конфигурација прокÑија.</translation>
<translation id="2082238445998314030"><ph name="RESULT_NUMBER" />. од <ph name="TOTAL_RESULTS" /> резултата</translation>
+<translation id="2085876078937250610">Сачувај…</translation>
<translation id="2088086323192747268">Дугме Управљајте Ñинхронизацијом, притиÑните Enter да биÑте управљали тиме које информације Ñинхронизујете у подешавањима Chrome-а</translation>
<translation id="2091887806945687916">Звук</translation>
<translation id="2094505752054353250">Домени Ñе не подударају</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> захтева кориÑничко име и лозинку.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, иÑтиче <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Подешавање контролише админиÑтратор</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> жели да Ñе упари</translation>
<translation id="2344028582131185878">ÐутоматÑка преузимања</translation>
<translation id="2346319942568447007">Копирана Ñлика</translation>
<translation id="2354001756790975382">ОÑтали обележивачи</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">Ðападачи ће моћи да виде Ñлике које гледате на овом Ñајту и да их измене како би Ð²Ð°Ñ Ð¿Ñ€ÐµÐ²Ð°Ñ€Ð¸Ð»Ð¸.</translation>
<translation id="2356070529366658676">Питај</translation>
<translation id="2357481397660644965">Уређајем управља <ph name="DEVICE_MANAGER" />, а налогом <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{За мање од једног дана}=1{За један дан}one{За {NUM_DAYS} дан}few{За {NUM_DAYS} дана}other{За {NUM_DAYS} дана}}</translation>
<translation id="2359629602545592467">Више</translation>
<translation id="2359808026110333948">ÐаÑтавите</translation>
+<translation id="2359961752320758691">Број виртуелне картице је примењен.</translation>
<translation id="2367567093518048410">Ðиво</translation>
<translation id="2372464001869762664">Када будете потврдили, подаци о картици Ñа Google налога ће Ñе делити Ñа овим Ñајтом. Пронађите CVC у детаљима о Plex налогу.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">Овај начин Ñлања није доÑтупан. ИÑпробајте неки други начин.</translation>
<translation id="2396249848217231973">&amp;Опозови бриÑање</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Старо</translation>
<translation id="2413528052993050574">Овај Ñервер не може да докаже да је <ph name="DOMAIN" />; његов безбедноÑни Ñертификат ће можда бити опозван. Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.</translation>
<translation id="2414886740292270097">Тамнa</translation>
<translation id="2438874542388153331">ЧетвороÑтруко бушење на деÑној Ñтрани</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">Спајање у доњем деÑном углу</translation>
<translation id="2523886232349826891">Сачувано је Ñамо на овом уређају</translation>
<translation id="2524461107774643265">Додајте још информација</translation>
-<translation id="2526590354069164005">Радна површина</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{и још 1}one{и још #}few{и још #}other{и још #}}</translation>
<translation id="2536110899380797252">Додај адреÑу</translation>
<translation id="2539524384386349900">Откриј</translation>
+<translation id="2541219929084442027">Странице које прегледате на картицама без архивирања Ñе неће задржавати у иÑторији прегледача, Ñкладишту колачића или иÑторији претраге када затворите Ñве картице без архивирања. Сачуваћемо Ñве преузете фајлове или направљене обележиваче.</translation>
<translation id="2544644783021658368">Један документ</translation>
<translation id="254947805923345898">ВредноÑÑ‚ Ñмерница није важећа.</translation>
<translation id="255002559098805027">ХоÑÑ‚ <ph name="HOST_NAME" /> је поÑлао неважећи одговор.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Да биÑте добили највиши ниво заштите у Chrome-у, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />укључите побољшану заштиту<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">ÐиÑмо уÑпели да пронађемо IP адреÑу Ñервера хоÑта <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">СтатуÑ:</translation>
+<translation id="264810637653812429">Ðије пронађен ниједан компатибилан уређај.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, притиÑните Tab, па Enter да биÑте обриÑали иÑторију прегледања, колачиће, кеш и друго у подешавањима Chrome-а</translation>
<translation id="2650446666397867134">ПриÑтуп датотеци је одбијен</translation>
@@ -494,6 +508,7 @@
<translation id="2799223571221894425">Поново покрени</translation>
<translation id="2803306138276472711">Google безбедно прегледање је недавно <ph name="BEGIN_LINK" />открило малвер<ph name="END_LINK" /> на <ph name="SITE" />. Веб-Ñајтови који Ñу обично безбедни Ñе понекад заразе малвером.</translation>
<translation id="2807052079800581569">Позиција Ñлике на Y оÑи</translation>
+<translation id="2820957248982571256">Скенира Ñе...</translation>
<translation id="2824775600643448204">Трака за адреÑу и претрагу</translation>
<translation id="2826760142808435982">Веза је шифрована и њена аутентичноÑÑ‚ је потврђена помоћу <ph name="CIPHER" /> и кориÑти <ph name="KX" /> као механизам за размену шифара.</translation>
<translation id="2835170189407361413">Обриши образац</translation>
@@ -501,6 +516,8 @@
<translation id="2850739647070081192">Invite (коверат)</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="2859806420264540918">Овај Ñајт приказује оглаÑе који ометају активноÑти или обмањујуће оглаÑе.</translation>
+<translation id="287596039013813457">ПријатељÑки</translation>
+<translation id="2876489322757410363">ÐапуÑтићете режим без архивирања да биÑте платили у Ñпољној апликацији. Желите ли да наÑтавите?</translation>
<translation id="2878197950673342043">ПреÑавијање у облику поÑтера</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ПоÑтављање прозора</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (коверат)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, притиÑните Tab, па Enter да биÑте покренули безбедноÑну проверу у Chrome подешавањима</translation>
<translation id="3061707000357573562">УÑлуга крпљења</translation>
-<translation id="3064966200440839136">ÐапуÑтићете режим без архивирања да биÑте платили у Ñпољној апликацији. Желите ли да наÑтавите?</translation>
<translation id="306573536155379004">Игра је покренута.</translation>
<translation id="3080254622891793721">Слика</translation>
<translation id="3086579638707268289">Ваше активноÑти на вебу Ñе прате</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312">Вашим налогом управља <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Поново отвори</translation>
<translation id="3162559335345991374">WiFi мрежа коју кориÑтите ће можда захтевати да поÑетите Ñтраницу за пријављивање.</translation>
-<translation id="3167968892399408617">Странице које прегледате на картицама без архивирања Ñе неће задржавати у иÑторији прегледача, Ñкладишту колачића или иÑторији претраге када затворите Ñве картице без архивирања. Сачуваћемо Ñве преузете датотеке или направљене обележиваче.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">ОÑтрво</translation>
<translation id="3176929007561373547">Проверите подешавања прокÑија или контактирајте админиÑтратора мреже да
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">Информације о верзији за уређај и прегледач</translation>
<translation id="323107829343500871">УнеÑите CVC за картицу <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Увек откривај важан Ñадржај на овом Ñајту</translation>
+<translation id="3249845759089040423">Хипи</translation>
<translation id="3252266817569339921">француÑки</translation>
<translation id="3266793032086590337">ВредноÑÑ‚ (неуÑаглашена)</translation>
<translation id="3268451620468152448">Отворене картице</translation>
<translation id="3270847123878663523">&amp;Опозови промену редоÑледа</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> жели да Ñе повеже</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Ваша организација, <ph name="ENROLLMENT_DOMAIN" />, поÑлала је одређене податке Ñледећим веб-Ñајтовима, попут подешавања или Ñмерница.</translation>
<translation id="3282497668470633863">Додајте име на картици</translation>
@@ -655,6 +672,7 @@
<translation id="3428151540071562330">Један или више URI-ја шаблона DnsOverHttpsTemplates Ñервера Ñу неважећи и неће Ñе кориÑтити.</translation>
<translation id="3431636764301398940">Сачувај ову картицу на овом уређају</translation>
<translation id="3432601291244612633">Затвори Ñтраницу</translation>
+<translation id="3435738964857648380">БезбедноÑÑ‚</translation>
<translation id="3435896845095436175">Омогући</translation>
<translation id="3438829137925142401">КориÑтите лозинке Ñачуване на Google налогу</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@
<translation id="3584299510153766161">ДвоÑтруко бушење на дну</translation>
<translation id="3586931643579894722">Сакриј детаље</translation>
<translation id="3587738293690942763">Средње</translation>
+<translation id="3590643883886679995">Подаци о пријављивању Ñе чувају на овом уређају када изађете из режима без архивирања.</translation>
+<translation id="359126217934908072">МеÑец/година:</translation>
<translation id="3592413004129370115">Italian (коверат)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Групу можете да реÑетујете у било ком тренутку. Придруживање новој групи траје отприлике један дан.}=1{Групу можете да реÑетујете у било ком тренутку. Придруживање новој групи траје отприлике један дан.}one{Групу можете да реÑетујете у било ком тренутку. Придруживање новој групи траје отприлике {NUM_DAYS} дан.}few{Групу можете да реÑетујете у било ком тренутку. Придруживање новој групи траје отприлике {NUM_DAYS} дана.}other{Групу можете да реÑетујете у било ком тренутку. Придруживање новој групи траје отприлике {NUM_DAYS} дана.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">ÐдминиÑтратор блокира апликацију</translation>
<translation id="3608932978122581043">Смер уноÑа</translation>
@@ -706,13 +727,13 @@
<translation id="3615877443314183785">УнеÑите важећи датум иÑтека</translation>
<translation id="36224234498066874">Обриши податке прегледања...</translation>
<translation id="362276910939193118">Прикажи комплетну иÑторију</translation>
-<translation id="3625635938337243871">Подаци о пријављивању Ñе чувају на овом уређају када изађете из режима без архивирања.</translation>
<translation id="3630155396527302611">Ðко је већ наведен као програм коме је дозвољен приÑтуп мрежи, покушајте да га
уклоните Ñа лиÑте и да га поново додате.</translation>
<translation id="3630699740441428070">ÐдминиÑтратори овог уређаја Ñу конфигуриÑали мрежну везу, што може да им омогући да виде мрежни Ñаобраћај, укључујући веб-Ñајтове које поÑећујете.</translation>
<translation id="3631244953324577188">Биометрија</translation>
<translation id="3633738897356909127">Дугме Ðжурирај Chrome, притиÑните Enter да биÑте ажурирали Chrome из подешавања Chrome-а</translation>
<translation id="3634530185120165534">5. фиока</translation>
+<translation id="3637662659967048211">Сачувајте на Google налогу</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Ðпликација:</translation>
<translation id="3650584904733503804">Потврда ваљаноÑти је уÑпела</translation>
@@ -753,6 +774,7 @@
<translation id="3781428340399460090">Јаркорозе</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth уређаји</translation>
+<translation id="3787675388804467730">Број виртуелне картице</translation>
<translation id="3787705759683870569">ИÑтиче <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Величина 16</translation>
<translation id="3789841737615482174">ИнÑталирај</translation>
@@ -772,6 +794,7 @@
<translation id="3841184659773414994">Обрађивачи фајлова</translation>
<translation id="385051799172605136">Ðазад</translation>
<translation id="3858027520442213535">Ðжурирајте датум и време</translation>
+<translation id="3881478300875776315">Прикажи мање редова</translation>
<translation id="3884278016824448484">ÐеуÑаглашени идентификатор уређаја</translation>
<translation id="3885155851504623709">Парохија</translation>
<translation id="388632593194507180">Откривено је праћење</translation>
@@ -797,6 +820,7 @@
<translation id="397105322502079400">Израчунавање...</translation>
<translation id="3973234410852337861">ХоÑÑ‚ <ph name="HOST_NAME" /> је блокиран</translation>
<translation id="3973357910713125165">Дугме Покрените Chrome безбедноÑну проверу, притиÑните Enter да биÑте покренули безбедноÑну проверу у Chrome подешавањима</translation>
+<translation id="3986705137476756801">ИÑкључи Титл уживо за Ñада</translation>
<translation id="3987405730340719549">Chrome је утврдио да је овај Ñајт можда лажан или Ñлужи за превару.
Ðко миÑлите да Ñе ово приказује грешком, поÑетите https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@
<translation id="4275830172053184480">Поновно покретање уређаја</translation>
<translation id="4277028893293644418">РеÑетујте лозинку</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Ова картица је Ñачувана на Google налогу}one{Ове картице Ñу Ñачуване на Google налогу}few{Ове картице Ñу Ñачуване на Google налогу}other{Ове картице Ñу Ñачуване на Google налогу}}</translation>
+<translation id="4287885627794386150">ИÑпуњава уÑлове за пробу, али није активно</translation>
<translation id="4297502707443874121">Сличица за <ph name="THUMBNAIL_PAGE" />. Ñтраницу</translation>
<translation id="42981349822642051">Проширите</translation>
<translation id="4300675098767811073">ВишеÑтруко бушење на деÑној Ñтрани</translation>
<translation id="4302514097724775343">Додирните диноÑауруÑа да биÑте играли</translation>
<translation id="4302965934281694568">Chou3 (коверат)</translation>
<translation id="4305666528087210886">ПриÑтуп датотеци није уÑпео</translation>
-<translation id="4305817255990598646">Пређи</translation>
+<translation id="4306529830550717874">Желите да Ñачувате адреÑу?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Блокирај (подразумевано)</translation>
<translation id="4314815835985389558">Управљајте Ñинхронизацијом</translation>
@@ -926,6 +951,7 @@
<translation id="4377125064752653719">Покушали Ñте да контактирате <ph name="DOMAIN" />, али је издавач опозвао Ñертификат који је Ñервер навео. То значи да никако не треба имати поверења у безбедноÑне акредитиве које је Ñервер навео. Могуће је да комуницирате Ñа нападачем.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4390472908992056574">Обод</translation>
+<translation id="4406883609789734330">Титл уживо</translation>
<translation id="4406896451731180161">резултати претраге</translation>
<translation id="4408413947728134509">Колачићи (<ph name="NUM_COOKIES" />)</translation>
<translation id="4414290883293381923">Управо Ñте унели лозинку на обмањујућем Ñајту. Chrome вам препоручује да одете на <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> и на друге Ñајтове где кориÑтите ову лозинку и да је одмах промените.</translation>
@@ -938,7 +964,6 @@
<translation id="4435702339979719576">разгледница)</translation>
<translation id="443673843213245140">Коришћење прокÑија је онемогућено, али је наведена екÑплицитна конфигурација прокÑија.</translation>
<translation id="4464826014807964867">Веб-Ñајтови Ñа подацима из ваше организације</translation>
-<translation id="4466881336512663640">Промене обраÑца Ñе неће Ñачувати. Желите ли Ñтварно да наÑтавите?</translation>
<translation id="4476953670630786061">Овај образац није безбедан. ÐутоматÑко попуњавање је иÑкључено.</translation>
<translation id="4477350412780666475">Следећа пеÑма</translation>
<translation id="4482953324121162758">Овај Ñајт неће бити преведен.</translation>
@@ -972,6 +997,7 @@
<translation id="4594403342090139922">&amp;Опозови бриÑање</translation>
<translation id="4597348597567598915">Величина 8</translation>
<translation id="4600854749408232102">C6/C5 (коверат)</translation>
+<translation id="4606870351894164739">Упечатљиво</translation>
<translation id="4628948037717959914">Слика</translation>
<translation id="4631649115723685955">Повезан је повраћај готовине</translation>
<translation id="4636930964841734540">Информације</translation>
@@ -991,6 +1017,7 @@
<translation id="4691835149146451662">Architecture-A (коверат)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Страна</translation>
+<translation id="4702656508969495934">Види Ñе титл уживо. КориÑтите дугме за промену прозора да биÑте фокуÑирали</translation>
<translation id="4708268264240856090">Веза је прекинута</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />да покренете Windows дијагноÑтику мреже<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@
<translation id="4738601419177586157">Предлог за претрагу <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Управљај лозинкама...</translation>
<translation id="4744603770635761495">Путања извршне датотеке</translation>
+<translation id="4749011317274908093">Прешли Ñте на режим без архивирања</translation>
<translation id="4750917950439032686">Информације (на пример, лозинке или бројеви кредитних картица) Ñу приватне када Ñе шаљу овом Ñајту.</translation>
<translation id="4756388243121344051">&amp;ИÑторија</translation>
<translation id="4758311279753947758">Додај контакт информације</translation>
@@ -1033,6 +1061,8 @@
<translation id="4813512666221746211">Грешка на мрежи</translation>
<translation id="4816492930507672669">Уклопи у Ñтраницу</translation>
<translation id="4819347708020428563">Желите ли да измените коментаре у подразумеваном приказу?</translation>
+<translation id="4825507807291741242">Моћно</translation>
+<translation id="4838327282952368871">Чаробно</translation>
<translation id="484462545196658690">ÐутоматÑки</translation>
<translation id="4850886885716139402">Приказ</translation>
<translation id="485316830061041779">немачки</translation>
@@ -1169,6 +1199,7 @@
<translation id="5314967030527622926">Ðлат за прављење брошуре</translation>
<translation id="5316812925700871227">Окрените у Ñмеру Ñупротном од казаљке на Ñату</translation>
<translation id="5317780077021120954">Сачувај</translation>
+<translation id="5321288445143113935">МакÑимално увећано</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" />. од <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Одаберите контакт информације</translation>
<translation id="5327248766486351172">Ðазив</translation>
@@ -1176,11 +1207,13 @@
<translation id="5332219387342487447">Ðачин иÑпоруке</translation>
<translation id="5333022057423422993">Chrome је пронашао лозинку коју Ñте управо кориÑтили при повреди података. Да биÑте заштитили налоге, препоручујемо вам да проверите Ñачуване лозинке.</translation>
<translation id="5334013548165032829">Детаљне евиденције ÑиÑтема</translation>
+<translation id="5334145288572353250">Желите да Ñачувате адреÑу?</translation>
<translation id="5340250774223869109">Ðпликација је блокирана</translation>
<translation id="534295439873310000">NFC уређаји</translation>
<translation id="5344579389779391559">Ова Ñтраница може да покуша да вам нешто наплати</translation>
<translation id="5355557959165512791">Тренутно не можете да поÑетите <ph name="SITE" /> јер је његов Ñертификат опозван. Грешке и напади на мрежи Ñу обично привремени, па ће ова Ñтраница вероватно функциониÑати каÑније.</translation>
<translation id="536296301121032821">Складиштење подешавања Ñмерница није уÑпело</translation>
+<translation id="5363309033720083897">ÐдминиÑтратор је дозволио ÑеријÑки порт</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="5386426401304769735">Ланац Ñертификата за овај Ñајт Ñадржи Ñертификат потпиÑан помоћу алгоритма SHA-1.</translation>
@@ -1189,6 +1222,7 @@
<translation id="5398772614898833570">ОглаÑи Ñу блокирани</translation>
<translation id="5400836586163650660">Сива</translation>
<translation id="540969355065856584">Овај Ñервер не може да докаже да је <ph name="DOMAIN" />; његов безбедноÑни Ñертификат тренутно није важећи. Узрок томе је можда погрешна конфигурација или нападач који је прекинуо везу.</translation>
+<translation id="541143247543991491">Клауд (на нивоу ÑиÑтема)</translation>
<translation id="541416427766103491">4. преграда за Ñлагање</translation>
<translation id="5421136146218899937">Обриши податке прегледања...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> жели да вам шаље обавештења</translation>
@@ -1202,6 +1236,7 @@
<translation id="5455374756549232013">ÐеиÑправна временÑка ознака Ñмерница</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" />}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="5463625433003343978">Траже Ñе уређаји…</translation>
<translation id="5469868506864199649">италијанÑки</translation>
<translation id="5470861586879999274">&amp;Понови измену</translation>
<translation id="5478437291406423475">B6/C4 (коверат)</translation>
@@ -1251,7 +1286,6 @@
<translation id="5624120631404540903">Управљај лозинкама</translation>
<translation id="5629630648637658800">Учитавање подешавања Ñмерница није уÑпело</translation>
<translation id="5631439013527180824">Ðеважећи токен за управљање уређајима</translation>
-<translation id="5632627355679805402">Подаци Ñу шифровани помоћу <ph name="BEGIN_LINK" />Google лозинке<ph name="END_LINK" /> (<ph name="TIME" />). УнеÑите је да биÑте започели Ñинхронизацију.</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="5644090287519800334">Померање Ñлике 1. Ñтране по X оÑи</translation>
@@ -1290,12 +1324,12 @@
<translation id="5785756445106461925">Поред тога, ова Ñтраница Ñадржи и друге реÑурÑе који ниÑу безбедни. Ове реÑурÑе могу да виде и други док Ñу у пролазу и нападач може да их измени како би променио изглед Ñтранице.</translation>
<translation id="5786044859038896871">Желите ли да попуните информације о картици?</translation>
<translation id="578633867165174378">Chrome је пронашао лозинку коју Ñте управо кориÑтили при повреди података. Препоручујемо вам да одмах промените ту лозинку.</translation>
-<translation id="5798290721819630480">Желите ли да одбаците промене?</translation>
<translation id="5803412860119678065">Желите ли да попуните подацима <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Дозволе</translation>
<translation id="5804427196348435412">кориÑти NFC уређаје</translation>
<translation id="5810442152076338065">Веза Ñа доменом <ph name="DOMAIN" /> је шифрована помоћу заÑтарелог пакета за шифровање.</translation>
<translation id="5813119285467412249">&amp;Понови додавање</translation>
+<translation id="5817918615728894473">Упари</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Са ове картице ће вам бити наплаћено када платите, али њен прави број Ñе неће делити Ñа овим Ñајтом. ГенериÑаће Ñе привремени CVC као додатна мера безбедноÑти.}one{Са картице коју изаберете биће вам наплаћено када платите, али њен прави број Ñе неће делити Ñа овим Ñајтом. ГенериÑаће Ñе привремени CVC као додатна мера безбедноÑти.}few{Са картице коју изаберете биће вам наплаћено када платите, али њен прави број Ñе неће делити Ñа овим Ñајтом. ГенериÑаће Ñе привремени CVC као додатна мера безбедноÑти.}other{Са картице коју изаберете биће вам наплаћено када платите, али њен прави број Ñе неће делити Ñа овим Ñајтом. ГенериÑаће Ñе привремени CVC као додатна мера безбедноÑти.}}</translation>
<translation id="5826507051599432481">Опште име (CN)</translation>
<translation id="5838278095973806738">Ðемојте да уноÑите оÑетљиве информације на овом Ñајту (на пример, лозинке или кредитне картице) јер нападачи могу да их украду.</translation>
@@ -1303,6 +1337,7 @@
<translation id="5855253129151731373">Име хоÑта овог Ñајта делује Ñлично као <ph name="LOOKALIKE_DOMAIN" />. Ðападачи понекад имитирају Ñајтове тако што незнатно и Ñкоро неприметно измене име домена.
Ðко миÑлите да Ñе ово приказује грешком, поÑетите https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">ИÑкључено</translation>
<translation id="5862579898803147654">8. преграда за Ñлагање</translation>
<translation id="5863847714970149516">Следећа Ñтраница може да покуша да вам нешто наплати</translation>
<translation id="5866257070973731571">Додајте број телефона</translation>
@@ -1319,6 +1354,7 @@
<translation id="5913377024445952699">Снимање екрана је паузирано</translation>
<translation id="59174027418879706">Омогућено</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{КориÑти Ñе 1}one{КориÑти Ñе #}few{КориÑте Ñе #}other{КориÑти Ñе #}}</translation>
<translation id="5921185718311485855">Укључено</translation>
<translation id="5921639886840618607">Желите ли да Ñачувате картицу на Google налогу?</translation>
<translation id="5922853866070715753">Скоро је готово</translation>
@@ -1338,6 +1374,7 @@
<translation id="5989320800837274978">ÐиÑу наведени ни фикÑни прокÑи Ñервери нити URL адреÑа .pac Ñкрипте.</translation>
<translation id="5992691462791905444">ПреÑавијање у облику полу-хармонике</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> резултата за „<ph name="SEARCH_TEXT" />“</translation>
+<translation id="6006484371116297560">КлаÑична</translation>
<translation id="6008122969617370890">РедоÑлед од n до 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Проверите лозинке</translation>
@@ -1359,6 +1396,7 @@
<translation id="6045164183059402045">Шаблон раÑпореда Ñтранице</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="6049004884579590341">ПритиÑните и задржите |<ph name="ACCELERATOR" />| да биÑте изашли из режима целог екрана</translation>
<translation id="6049488691372270142">ИÑпорука Ñтраница</translation>
<translation id="6051221802930200923">Тренутно не можете да поÑетите <ph name="SITE" /> јер веб-Ñајт кориÑти проверу Ñертификата. Грешке и напади на мрежи Ñу обично привремени, па ће ова Ñтраница вероватно функциониÑати каÑније.</translation>
<translation id="6051898664905071243">Број Ñтраница:</translation>
@@ -1375,6 +1413,7 @@
<translation id="610911394827799129">Google налог може да има друге облике иÑторије прегледања на <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
<translation id="6116338172782435947">да види текÑÑ‚ и Ñлике који Ñу копирани у привремену меморију</translation>
<translation id="6120179357481664955">Желите да Ñачувате ИД за UPI?</translation>
+<translation id="6123290840358279103">Прикажи виртуелну картицу</translation>
<translation id="6124432979022149706">Прикључци за Chrome за предузећа</translation>
<translation id="6146055958333702838">Проверите Ñве каблове и реÑтартујте Ñве рутере, модеме или друге мрежне уређаје које можда кориÑтите.</translation>
<translation id="614940544461990577">Покушајте:</translation>
@@ -1410,6 +1449,7 @@
<translation id="6289939620939689042">Боја Ñтранице</translation>
<translation id="6290238015253830360">Предложени чланци Ñе приказују овде</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google помоћник у Chrome-у Ñе зауÑтавља</translation>
<translation id="6305205051461490394">URL <ph name="URL" /> није доÑтупан.</translation>
<translation id="6312113039770857350">Веб-Ñтраница није доÑтупна</translation>
@@ -1435,6 +1475,7 @@
<translation id="6390200185239044127">ПреÑавијање половине у облику Ñлова Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Смернице за админиÑтраторе блокирају налепљивање Ñа <ph name="ORIGIN_NAME" /> на ову локацију</translation>
+<translation id="6398765197997659313">Изађи из режима целог екрана</translation>
<translation id="6401136357288658127">Ове Ñмернице Ñу заÑтареле. УмеÑто њих треба да кориÑтите нове Ñмернице <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Измена обележивача</translation>
<translation id="6406765186087300643">C0 (коверат)</translation>
@@ -1447,7 +1488,6 @@
<translation id="6428450836711225518">Верификујте број телефона</translation>
<translation id="6433490469411711332">Измените контакт информације</translation>
<translation id="6433595998831338502">ХоÑÑ‚ <ph name="HOST_NAME" /> је одбио повезивање.</translation>
-<translation id="6434309073475700221">Одбаци</translation>
<translation id="6440503408713884761">Занемарено</translation>
<translation id="6443406338865242315">додатке и додатне компонента које Ñте инÑталирали</translation>
<translation id="6446163441502663861">Kahu (коверат)</translation>
@@ -1490,6 +1530,7 @@
<translation id="6624427990725312378">Контакт информације</translation>
<translation id="6626291197371920147">Додајте важећи број картице</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> претрага</translation>
+<translation id="6630043285902923878">Траже Ñе USB уређаји…</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Обриши</translation>
@@ -1505,6 +1546,7 @@
<translation id="6671697161687535275">Желите ли да уклоните предлог из Chromium-а?</translation>
<translation id="6685834062052613830">Одјавите Ñе и довршите подешавање</translation>
<translation id="6687335167692595844">Затражена је величина фонта</translation>
+<translation id="6688743156324860098">Ðжурирајте…</translation>
<translation id="6689249931105087298">Релативно Ñа компреÑијом црних тачака</translation>
<translation id="6689271823431384964">Chrome вам нуди чување картица на Google налогу зато што Ñте пријављени. То можете да промените у подешавањима. Име влаÑника картице Ñмо узели Ñа налога.</translation>
<translation id="6698381487523150993">Ðаправљено:</translation>
@@ -1520,6 +1562,7 @@
<translation id="6744009308914054259">Док чекате на везу, поÑетите Преузимања и читајте офлајн чланке.</translation>
<translation id="6753269504797312559">ВредноÑÑ‚ Ñмерница</translation>
<translation id="6757797048963528358">Уређај је прешао у режим Ñпавања.</translation>
+<translation id="6767985426384634228">Желите да ажурирате адреÑу?</translation>
<translation id="6768213884286397650">Hagaki (разгледница)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ЉубичаÑта</translation>
@@ -1542,6 +1585,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome је поједноÑтавио ову Ñтраницу ради лакшег читања. Chrome је преузео оригиналну Ñтраницу преко небезбедне везе.</translation>
<translation id="6891596781022320156">Ðиво Ñмерница није подржан.</translation>
+<translation id="6895143722905299846">Виртуелни број:</translation>
<translation id="6895330447102777224">Картица је потврђена</translation>
<translation id="6897140037006041989">КориÑнички агент</translation>
<translation id="6898699227549475383">Организација (O)</translation>
@@ -1577,10 +1621,10 @@
<translation id="7004583254764674281">КориÑтите Windows Hello за бржу потврду картица</translation>
<translation id="7006930604109697472">Ипак пошаљи</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Подешавања промене величине</translation>
<translation id="7014741021609395734">Ðиво зумирања</translation>
<translation id="7016992613359344582">Те наплате могу да буду једнократне или периодичне и можда ниÑу одмах видљиве.</translation>
<translation id="7029809446516969842">Лозинке</translation>
+<translation id="7030436163253143341">Сертификат није важећи</translation>
<translation id="7031646650991750659">Google Play које апликације Ñте инÑталирали</translation>
<translation id="7050187094878475250">Покушали Ñте да поÑетите <ph name="DOMAIN" />, али је Ñервер предÑтавио Ñертификат Ñа периодом важења који је предугачак да би био поуздан.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Ова картица тренутно не може да Ñе Ñачува}one{Ове картице тренутно не могу да Ñе Ñачувају}few{Ове картице тренутно не могу да Ñе Ñачувају}other{Ове картице тренутно не могу да Ñе Ñачувају}}</translation>
@@ -1650,12 +1694,14 @@
<translation id="7300012071106347854">Кобалтноплава</translation>
<translation id="7302712225291570345">„<ph name="TEXT" />“</translation>
<translation id="7304030187361489308">ВиÑок</translation>
+<translation id="7305756307268530424">Почните Ñпорије</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Помоћ при повезивању</translation>
<translation id="7323804146520582233">Сакријте одељак <ph name="SECTION" /></translation>
<translation id="733354035281974745">Замена локалног налога на уређају</translation>
<translation id="7333654844024768166">Управо Ñте унели лозинку на обмањујућем Ñајту. Chromium вам препоручује да одете на <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> и на друге Ñајтове где кориÑтите ову лозинку и да је одмах промените.</translation>
<translation id="7334320624316649418">&amp;Понови промену редоÑледа</translation>
+<translation id="7337248890521463931">Прикажи више редова</translation>
<translation id="7337706099755338005">Ðије доÑтупно на вашој платформи.</translation>
<translation id="733923710415886693">Сертификат Ñервера није откривен помоћу ТранÑпарентноÑти Ñертификата.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1663,6 +1709,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Командна линија</translation>
<translation id="7359588939039777303">ОглаÑи Ñу блокирани.</translation>
+<translation id="7363096869660964304">Међутим, ниÑте невидљиви. ПрелаÑком у режим без архивирања нећете Ñакрити прегледање од поÑлодавца, интернет провајдера или веб-Ñајтова које поÑећујете.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, притиÑните Tab, па Enter да биÑте додали адреÑе и управљали њима у подешавањима Chrome-а</translation>
<translation id="7365849542400970216">Дозволићете Ñајту да зна када кориÑтите уређај?</translation>
<translation id="7372973238305370288">резултат претраге</translation>
@@ -1673,7 +1720,9 @@
<translation id="7378594059915113390">Контроле за медије</translation>
<translation id="7378627244592794276">Ðе</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ðије примењиво</translation>
<translation id="7390545607259442187">Потврдите картицу</translation>
+<translation id="7392089738299859607">Ðжурирајте адреÑу</translation>
<translation id="7399802613464275309">БезбедноÑна провера</translation>
<translation id="7400418766976504921">URL адреÑа</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" />-ом Ñе управља</translation>
@@ -1688,6 +1737,7 @@
&lt;li&gt;ПоÑетите &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome центар за помоћ&lt;/a&gt; да биÑте Ñазнали како да трајно уклоните Ñофтвер Ñа рачунара
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Дивно</translation>
<translation id="7416351320495623771">Управљај лозинкама...</translation>
<translation id="7419106976560586862">Путања профила</translation>
<translation id="7437289804838430631">Додај контакт информације</translation>
@@ -1703,7 +1753,7 @@
<translation id="7481312909269577407">ПроÑледи</translation>
<translation id="7485870689360869515">ÐиÑу пронађени подаци.</translation>
<translation id="7495528107193238112">Овај Ñадржај је блокиран. Обратите Ñе влаÑнику Ñајта да биÑте решили проблем.</translation>
-<translation id="7498234416455752244">ÐаÑтавите Ñа изменама</translation>
+<translation id="7498193950643227031">Може да Ñе понаша неочекивано ако Ñе промени величина. Сада можете да ограничите могућноÑÑ‚ за мењање величине апликација у <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Управо Ñте унели лозинку на обмањујућем Ñајту. Chromium вам препоручује да проверите Ñачуване лозинке за <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> и друге Ñајтове на којима тренутно кориÑтите ову лозинку.</translation>
<translation id="7508255263130623398">Враћени ИД уређаја за Ñмернице је празан или Ñе не подудара Ñа актуелним ИД-ом уређаја</translation>
<translation id="7508870219247277067">Зеленожута</translation>
@@ -1723,6 +1773,7 @@
<translation id="7548892272833184391">Отклоните грешке при повезивању</translation>
<translation id="7549584377607005141">Ова веб-Ñтраница захтева податке које Ñте унели раније да би Ñе правилно приказала. Можете поново да пошаљете те податке, али ако то урадите, поновићете било коју радњу коју је ова Ñтраница претходно обавила.</translation>
<translation id="7550637293666041147">КориÑничко име уређаја и кориÑничко име за Chrome</translation>
+<translation id="755279583747225797">Проба је активна</translation>
<translation id="7552846755917812628">ИÑпробајте Ñледеће Ñавете:</translation>
<translation id="7554475479213504905">Ипак поново учитај и прикажи</translation>
<translation id="7554791636758816595">Ðова картица</translation>
@@ -1741,7 +1792,6 @@
<translation id="7610193165460212391">ВредноÑÑ‚ је изван опÑега <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">ИÑтиче: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, притиÑните Tab, па Enter да биÑте прегледали лозинке и управљали њима у подешавањима Chrome-а</translation>
-<translation id="7615602087246926389">Већ имате податке који Ñу шифровани помоћу друге верзије лозинке за Google налог. УнеÑите је у наÑтавку.</translation>
<translation id="7616645509853975347">ÐдминиÑтратор је укључио Chrome Enterprise Connectors у прегледачу. Ови прикључци имају приÑтуп неким вашим подацима.</translation>
<translation id="7619838219691048931">ПоÑледњи лиÑÑ‚</translation>
<translation id="762844065391966283">Појединачно</translation>
@@ -1806,13 +1856,12 @@
<translation id="782886543891417279">WiFi мрежа коју кориÑтите (<ph name="WIFI_NAME" />) ће можда захтевати да поÑетите Ñтраницу за пријављивање.</translation>
<translation id="7836231406687464395">Postfix (коверат)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ðиједна}=1{1 апликација (<ph name="EXAMPLE_APP_1" />)}=2{2 апликације (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# апликација (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}few{# апликације (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# апликација (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Ðли, ниÑте невидљиви. ПрелаÑком у режим без архивирања нећете Ñакрити прегледање од поÑлодавца, интернет провајдера или веб-Ñајтова које поÑећујете.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Отвара фајлове Ñа повезаним типовима фајлова.</translation>
<translation id="7862185352068345852">Желите ли да напуÑтите Ñајт?</translation>
<translation id="7865448901209910068">Ðајбоља брзина</translation>
<translation id="7874263914261512992">Управо Ñте унели лозинку на обмањујућем Ñајту. Chrome вам препоручује да проверите Ñачуване лозинке за <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> и друге Ñајтове на којима тренутно кориÑтите ову лозинку.</translation>
<translation id="7878562273885520351">Лозинка је можда компромитована</translation>
+<translation id="7880146494886811634">Сачувајте адреÑу</translation>
<translation id="7882421473871500483">Браон</translation>
<translation id="7887683347370398519">Проверите CVC и покушајте поново</translation>
<translation id="7887885240995164102">Покрени режим Ñлике у Ñлици</translation>
@@ -1820,6 +1869,7 @@
<translation id="7894280532028510793">Ðко нема грешака, <ph name="BEGIN_LINK" />покрените дијагноÑтику мреже<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (коверат)</translation>
<translation id="7931318309563332511">Ðепознато</translation>
+<translation id="793209273132572360">Желите да ажурирате адреÑу?</translation>
<translation id="7932579305932748336">Омот</translation>
<translation id="79338296614623784">УнеÑите важећи број телефона</translation>
<translation id="7934052535022478634">Плаћање је довршено</translation>
@@ -1890,6 +1940,7 @@
<translation id="8175796834047840627">Chrome вам нуди чување картица на Google налогу зато што Ñте пријављени. То можете да промените у подешавањима.</translation>
<translation id="8176440868214972690">ÐдминиÑтратор овог уређаја је поÑлао одређене податке Ñледећим веб-Ñајтовима, попут подешавања или Ñмерница.</translation>
<translation id="8184538546369750125">КориÑти глобалну подразумевану вредноÑÑ‚ (Дозволи)</translation>
+<translation id="8193086767630290324">Радње Ñа подацима који Ñу означени као поверљиви</translation>
<translation id="8194797478851900357">&amp;Опозови премештање</translation>
<translation id="8201077131113104583">Ðеважећи URL за ажурирање за додатак Ñа ИД-ом „<ph name="EXTENSION_ID" />“.</translation>
<translation id="8202097416529803614">Резиме поруџбине</translation>
@@ -1912,6 +1963,7 @@
<translation id="8249296373107784235">Откажи</translation>
<translation id="8249320324621329438">ПоÑледње учитано:</translation>
<translation id="8253091569723639551">ÐдреÑа за обрачун је обавезна</translation>
+<translation id="8257387598443225809">Ова апликација је дизајнирана за мобилне уређаје</translation>
<translation id="825929999321470778">Прикажи Ñве Ñачуване лозинке</translation>
<translation id="8261506727792406068">Избриши</translation>
<translation id="8262952874573525464">Спајање ивица шавом на дну</translation>
@@ -2036,7 +2088,6 @@
<translation id="8719528812645237045">ВишеÑтруко бушење на врху</translation>
<translation id="8725066075913043281">Пробајте поново</translation>
<translation id="8726549941689275341">Величина Ñтранице:</translation>
-<translation id="8728672262656704056">Прешли Ñте у режим Без архивирања</translation>
<translation id="8730621377337864115">Готово</translation>
<translation id="8731544501227493793">Дугме Управљај лозинкама, притиÑните Enter да биÑте прегледали лозинке и управљали њима у подешавањима Chrome-а</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" />-ом управља <ph name="MANAGER" /></translation>
@@ -2113,6 +2164,7 @@
<translation id="9020542370529661692">Ова Ñтраница је преведена на <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Ðеважеће)</translation>
+<translation id="9030265603405983977">МонохроматÑко</translation>
<translation id="9035022520814077154">БезбедноÑна грешка</translation>
<translation id="9038649477754266430">КориÑтите уÑлугу предвиђања да биÑте брже учитавали Ñтранице</translation>
<translation id="9039213469156557790">Поред тога, ова Ñтраница Ñадржи и друге реÑурÑе који ниÑу безбедни. Ове реÑурÑе могу да виде и други док Ñу у пролазу и нападач може да их измени како би променио понашање Ñтранице.</translation>
@@ -2136,6 +2188,7 @@
<translation id="91108059142052966">Смернице за админиÑтраторе онемогућавају дељење Ñадржаја екрана Ñа апликацијом <ph name="APPLICATION_TITLE" /> када је видљив поверљиви Ñадржај</translation>
<translation id="9114524666733003316">Картица Ñе потврђује...</translation>
<translation id="9114581008513152754">Овим прегледачем не управља компанија нити друга организација. ÐктивноÑтима на овом уређају Ñе можда управља ван Chrome-а. <ph name="BEGIN_LINK" />Сазнајте више<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Свеже</translation>
<translation id="9119042192571987207">Отпремљено</translation>
<translation id="9128016270925453879">Смернице Ñу учитане</translation>
<translation id="9128870381267983090">Повезивање Ñа мрежом</translation>
@@ -2154,6 +2207,7 @@
<translation id="9170848237812810038">&amp;Опозови</translation>
<translation id="9171296965991013597">Желите ли да изађете из апликације?</translation>
<translation id="9173282814238175921">Један документ/нови лиÑÑ‚</translation>
+<translation id="9173995187295789444">Траже Ñе Bluetooth уређаји...</translation>
<translation id="917450738466192189">Сертификат Ñервера је неважећи.</translation>
<translation id="9174917557437862841">Дугме за промену картице, притиÑните Enter да биÑте прешли на ту картицу</translation>
<translation id="9179703756951298733">Управљајте плаћањима и информацијама о кредитним картицама у подешавањима Chrome-а</translation>
diff --git a/chromium/components/strings/components_strings_sv.xtb b/chromium/components/strings/components_strings_sv.xtb
index 28e34be824a..51ade83baa1 100644
--- a/chromium/components/strings/components_strings_sv.xtb
+++ b/chromium/components/strings/components_strings_sv.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Välj behörighet för <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Ångra Ändra ordning</translation>
+<translation id="1123753900084781868">Live Caption är inte tillgängligt just nu</translation>
<translation id="1125573121925420732">Varningar kan förekomma medan en webbplats uppdaterar säkerheten. Detta förbättras inom kort.</translation>
<translation id="112840717907525620">Cacheminnet för policyn är OK</translation>
<translation id="1130564665089811311">Knappen Översätt sida, tryck på Retur om du vill översätta sidan med Google Översätt</translation>
@@ -74,6 +75,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="1240347957665416060">Ditt enhetsnamn</translation>
<translation id="124116460088058876">Fler språk</translation>
<translation id="1243027604378859286">Författare:</translation>
+<translation id="1246424317317450637">Fet</translation>
<translation id="1250759482327835220">Spara kortet, faktureringsadressen och ditt namn i Google-kontot så går det snabbare att betala nästa gång.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (synkroniserade)</translation>
<translation id="1256368399071562588">&lt;p&gt;Om det inte går att öppna en webbplats testar du först att åtgärda felet med hjälp av dessa felsökningssteg:&lt;/p&gt;
@@ -156,6 +158,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="1476595624592550506">Ändra lösenordet</translation>
<translation id="1484290072879560759">Välj leveransadress</translation>
<translation id="1492194039220927094">Skicka principer:</translation>
+<translation id="1495677929897281669">Tillbaka till flik</translation>
<translation id="1501859676467574491">Visa kort från ditt Google-konto</translation>
<translation id="1507202001669085618">&lt;p&gt;Felmeddelandet visas om du använder en wifi-portal där du måste logga in innan du kommer ut på internet.&lt;/p&gt;
&lt;p&gt;Åtgärda problemet genom att klicka på &lt;strong&gt;Anslut&lt;/strong&gt; på sidan du försöker öppna.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<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>
<translation id="1536390784834419204">Översätt sidan</translation>
+<translation id="1539840569003678498">Rapporten skickades:</translation>
<translation id="154408704832528245">Välj leveransadress</translation>
<translation id="1549470594296187301">JavaScript måste aktiveras för att du ska kunna använda den här funktionen.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="1682696192498422849">Kortsidan först</translation>
<translation id="168693727862418163">Principen ignoreras eftersom den inte gick att validera mot schemat.</translation>
<translation id="168841957122794586">Servercertifikatet innehåller en svag kryptografisk nyckel.</translation>
+<translation id="1696290444144917273">Visa kortuppgifter</translation>
<translation id="1697532407822776718">Färdigt!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Det gick inte att bevisa att serverns identitet är <ph name="DOMAIN" /> eftersom dess säkerhetscertifikat uppges börja gälla i morgon. Det kan bero på att servern är felkonfigurerad eller att anslutningen har blivit kapad.}other{Det gick inte att bevisa att serverns identitet är <ph name="DOMAIN" /> eftersom dess säkerhetscertifikat uppges börja gälla om # dagar. Det kan bero på att servern är felkonfigurerad eller att anslutningen har blivit kapad.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Ignoreras eftersom <ph name="POLICY_NAME" /> inte har ställts in på <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> vill lagra data permanent på din lokala dator</translation>
<translation id="1713628304598226412">Fack 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Postfack 3</translation>
<translation id="1718029547804390981">Det går inte att annotera det här dokumentet eftersom det är för stort</translation>
<translation id="1721424275792716183">* Fältet är obligatoriskt</translation>
+<translation id="1727613060316725209">Certifikatet är giltigt</translation>
<translation id="1727741090716970331">Lägg till ett giltigt kortnummer</translation>
<translation id="1728677426644403582">Du visar källkoden till en webbsida</translation>
<translation id="173080396488393970">Denna korttyp stöds inte</translation>
@@ -246,7 +253,6 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
om <ph name="SITE" /> i webbläsaren. Ursprungsprinciper kan användas av
webbplatsoperatörer för att konfigurera säkerhetsfunktioner och andra funktioner för webbplatser.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Uppdatera lösenfrasen för synkroniseringen.</translation>
<translation id="1787142507584202372">Öppna flikar visas här</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, flera åtgärder tillgängliga, byt mellan dem med Tabb</translation>
@@ -279,6 +285,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="1919345977826869612">Annonser</translation>
<translation id="1919367280705858090">Få hjälp med ett specifikt felmeddelande</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ingen}=1{1 webbplats}other{# webbplatser}}</translation>
+<translation id="1924727005275031552">Ny</translation>
<translation id="1945968466830820669">Du kan förlora åtkomsten till organisationens konto eller bli utsatt för identitetsstöld. Du rekommenderas att ändra lösenordet nu.</translation>
<translation id="1947454675006758438">Häfta uppe till höger</translation>
<translation id="1958218078413065209">Ditt rekord är <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="2042213636306070719">Fack 7</translation>
<translation id="204357726431741734">Logga in om du vill använda lösenord som har sparats i Google-kontot</translation>
<translation id="2053111141626950936">Sidor på <ph name="LANGUAGE" /> översätts inte.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{När den här inställningen är på och statusen är Aktiv fastställer Chrome vilken grupp, eller kohort, som du tillhör utifrån din senaste webbaktivitet. Annonsörer kan välja annonser för denna grupp och din webbhistorik förblir privat på enheten. Grupptillhörigheten uppdateras dagligen.}=1{När den här inställningen är på och statusen är Aktiv fastställer Chrome vilken grupp, eller kohort, som du tillhör utifrån din senaste webbaktivitet. Annonsörer kan välja annonser för denna grupp och din webbhistorik förblir privat på enheten. Grupptillhörigheten uppdateras dagligen.}other{När den här inställningen är på och statusen är Aktiv fastställer Chrome vilken grupp, eller kohort, som du tillhör utifrån din senaste webbaktivitet. Annonsörer kan välja annonser för denna grupp och din webbhistorik förblir privat på enheten. Grupptillhörigheten uppdateras med {NUM_DAYS} dagars mellanrum.}}</translation>
<translation id="2053553514270667976">ZIP</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 förslag}other{# förslag}}</translation>
<translation id="2071692954027939183">Aviseringar blockerades automatiskt eftersom du vanligtvis inte tillåter dem</translation>
<translation id="2079545284768500474">Ã…ngra</translation>
<translation id="20817612488360358">Datorns proxyinställningar är inställda på att användas, men det finns också en explicit proxykonfiguration.</translation>
<translation id="2082238445998314030">Resultat <ph name="RESULT_NUMBER" /> av <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Spara …</translation>
<translation id="2088086323192747268">Knappen Hantera synkronisering, tryck på Retur om du vill hantera vilken information som synkroniseras i inställningarna för Chrome</translation>
<translation id="2091887806945687916">Ljud</translation>
<translation id="2094505752054353250">Domänen matchar inte</translation>
@@ -379,6 +388,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="2317259163369394535"><ph name="DOMAIN" /> kräver användarnamn och lösenord.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" /> upphör att gälla den <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Inställningen styrs av administratören</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> vill kopplas</translation>
<translation id="2344028582131185878">Automatiska nedladdningar</translation>
<translation id="2346319942568447007">Bilden som du kopierade</translation>
<translation id="2354001756790975382">Övriga bokmärken</translation>
@@ -386,8 +396,10 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="2355395290879513365">Det är möjligt att hackare kan se vilka bilder du visar på den här webbplatsen och att de försöker lura dig genom att modifiera dem.</translation>
<translation id="2356070529366658676">Fråga</translation>
<translation id="2357481397660644965">Enheten hanteras av <ph name="DEVICE_MANAGER" /> och kontot hanteras av <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Om mindre än ett dygn}=1{Om ett dygn}other{Om {NUM_DAYS} dygn}}</translation>
<translation id="2359629602545592467">Flera</translation>
<translation id="2359808026110333948">Fortsätt</translation>
+<translation id="2359961752320758691">Ditt virtuella kortnummer tillämpas.</translation>
<translation id="2367567093518048410">Nivå</translation>
<translation id="2372464001869762664">När du bekräftar delas kortuppgifter från ditt Google-konto med webbplatsen. Du hittar CVC-koden i Plex-kontouppgifterna.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="239429038616798445">Det här fraktalternativet är inte tillgängligt. Testa ett annat alternativ.</translation>
<translation id="2396249848217231973">&amp;Ã…ngra Ta bort</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Tidigare</translation>
<translation id="2413528052993050574">Servern kunde inte bevisa att den är <ph name="DOMAIN" /> eftersom dess säkerhetscertifikat kan ha återkallats. Detta kan orsakas av en felaktig konfigurering eller att någon spärrar anslutningen.</translation>
<translation id="2414886740292270097">Mörk</translation>
<translation id="2438874542388153331">Fyra hål till höger</translation>
@@ -425,10 +438,10 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="2521385132275182522">Häfta nere till höger</translation>
<translation id="2523886232349826891">Endast sparat på den här enheten</translation>
<translation id="2524461107774643265">Lägg till mer information</translation>
-<translation id="2526590354069164005">Skrivbord</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{och 1 till}other{och # till}}</translation>
<translation id="2536110899380797252">Lägg till adress</translation>
<translation id="2539524384386349900">Identifiera</translation>
+<translation id="2541219929084442027">Sidor som visas på flikar i inkognitoläget försvinner från webbhistoriken, från dina cookies och från sökhistoriken när alla inkognitoflikar har stängts. Alla filer som du laddar ned eller bokmärken som du skapar sparas.</translation>
<translation id="2544644783021658368">Enkelt dokument</translation>
<translation id="254947805923345898">Principens värde är inte giltigt.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> skickade ett ogiltigt svar.</translation>
@@ -448,6 +461,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="2629325967560697240"><ph name="BEGIN_ENHANCED_PROTECTION_LINK" />Aktivera Förbättrat skydd<ph name="END_ENHANCED_PROTECTION_LINK" /> för att få Chromes högsta säkerhetsnivå</translation>
<translation id="2634124572758952069">Det gick inte att hitta IP-adressen till servern på <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Status:</translation>
+<translation id="264810637653812429">Inga kompatibla enheter hittades.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, tryck på Tabb och sedan på Retur om du vill rensa webbhistorik, cookies, cacheminne och annat i inställningarna för Chrome</translation>
<translation id="2650446666397867134">Ã…tkomst till filen nekades</translation>
@@ -494,6 +508,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<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="2807052079800581569">Bild Y – position</translation>
+<translation id="2820957248982571256">Söker …</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>
@@ -501,6 +516,8 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="2850739647070081192">Invite (kuvert)</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="2859806420264540918">Påträngande eller vilseledande annonser visas på den här webbplatsen.</translation>
+<translation id="287596039013813457">Vänlig</translation>
+<translation id="2876489322757410363">Om du betalar i ett externt program sker inte det i inkognitoläge. Vill du fortsätta?</translation>
<translation id="2878197950673342043">Korsfalsning</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Fönsterplacering</translation>
@@ -550,7 +567,6 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="3060227939791841287">C9 (kuvert)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, tryck på Tabb och sedan på Retur om du vill köra säkerhetskontrollen i inställningarna för Chrome</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>
<translation id="306573536155379004">Spelet har startats.</translation>
<translation id="3080254622891793721">Bild</translation>
<translation id="3086579638707268289">Din aktivitet på webben övervakas</translation>
@@ -573,7 +589,6 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="315504272643575312">Kontot hanteras av <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Återställ</translation>
<translation id="3162559335345991374">wifi-nätverket du använder kanske kräver att du besöker dess inloggningssida.</translation>
-<translation id="3167968892399408617">Sidor som visas på flikar i inkognitoläget försvinner från webbhistoriken, från dina cookies och från sökhistoriken när alla inkognitoflikar har stängts. Alla filer som du laddar ned eller bokmärken som du skapar sparas.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ö</translation>
<translation id="3176929007561373547">Kontrollera dina proxyinställningar eller kontakta nätverksadministratören om du vill
@@ -599,10 +614,12 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<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="3249845759089040423">Tuff</translation>
<translation id="3252266817569339921">franska</translation>
<translation id="3266793032086590337">Värde (konflikt)</translation>
<translation id="3268451620468152448">Öppna flikar</translation>
<translation id="3270847123878663523">&amp;Ångra Ändra ordning</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> vill ansluta</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Organisationen <ph name="ENROLLMENT_DOMAIN" /> har skickat en del information, t.ex. inställningar eller principer, till följande webbplatser.</translation>
<translation id="3282497668470633863">Lägg till namnet på kortet</translation>
@@ -655,6 +672,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="3428151540071562330">Minst en av URI:erna i servermallen för DnsOverHttpsTemplates är ogiltig och kommer inte att användas.</translation>
<translation id="3431636764301398940">Spara kortet på enheten</translation>
<translation id="3432601291244612633">Stäng sidan</translation>
+<translation id="3435738964857648380">Säkerhet</translation>
<translation id="3435896845095436175">Aktivera</translation>
<translation id="3438829137925142401">Använd lösenord som har sparats i Google-kontot</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="3584299510153766161">Två hål längst ned</translation>
<translation id="3586931643579894722">Dölj detaljerad information</translation>
<translation id="3587738293690942763">Mellan</translation>
+<translation id="3590643883886679995">Inloggningsuppgifterna sparas på enheten när du har avslutat inkognitoläget.</translation>
+<translation id="359126217934908072">MÃ¥nad/Ã¥r:</translation>
<translation id="3592413004129370115">Italian (kuvert)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Du kan återställa grupptillhörigheten när som helst. Det tar ungefär ett dygn att bli med i en ny grupp.}=1{Du kan återställa grupptillhörigheten när som helst. Det tar ungefär ett dygn att bli med i en ny grupp.}other{Du kan återställa grupptillhörigheten när som helst. Det tar {NUM_DAYS} dygn att bli med i en ny grupp.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Appen blockeras av administratören</translation>
<translation id="3608932978122581043">Ställa in riktning</translation>
@@ -706,13 +727,13 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="3615877443314183785">Ange ett giltigt utgångsdatum</translation>
<translation id="36224234498066874">Rensa webbinformation ...</translation>
<translation id="362276910939193118">Visa fullständig historik</translation>
-<translation id="3625635938337243871">Inloggningsuppgifterna sparas på enheten när du har avslutat inkognitoläget.</translation>
<translation id="3630155396527302611">Om den redan finns med på listan över program som har tillgång till nätverket
kan du prova att ta bort den från listan och sedan lägga till den igen.</translation>
<translation id="3630699740441428070">Enhetens administratörer har konfigurerat nätverksanslutningen. Det innebär att de kan se din nätverkstrafik, inklusive vilka webbplatser du besöker.</translation>
<translation id="3631244953324577188">Biometri</translation>
<translation id="3633738897356909127">Knappen Uppdatera Chrome, tryck på retur om du vill uppdatera Chrome i inställningarna för Chrome</translation>
<translation id="3634530185120165534">Fack 5</translation>
+<translation id="3637662659967048211">Spara i Google-kontot</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Program:</translation>
<translation id="3650584904733503804">Valideringen har genomförts</translation>
@@ -753,6 +774,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="3781428340399460090">Cerise</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth-enheter</translation>
+<translation id="3787675388804467730">Virtuellt kort</translation>
<translation id="3787705759683870569">Utgångsdatum: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Storlek 16</translation>
<translation id="3789841737615482174">Installera</translation>
@@ -772,6 +794,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="3841184659773414994">Filhanterare</translation>
<translation id="385051799172605136">Föregående</translation>
<translation id="3858027520442213535">Uppdatera datum och tid</translation>
+<translation id="3881478300875776315">Visa färre rader</translation>
<translation id="3884278016824448484">Motstridiga enhetsidentifierare</translation>
<translation id="3885155851504623709">Församling</translation>
<translation id="388632593194507180">Övervakning har upptäckts</translation>
@@ -797,6 +820,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="397105322502079400">Beräknar ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> har blockerats</translation>
<translation id="3973357910713125165">Knappen Kör säkerhetskontroll i Chrome, tryck på Retur om du vill köra säkerhetskontrollen i inställningarna för Chrome</translation>
+<translation id="3986705137476756801">Inaktivera Live Caption tills vidare</translation>
<translation id="3987405730340719549">Den här webbplatsen har fastställts som potentiellt falsk eller bedräglig av Chrome.
Besök https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals om du anser att detta är felaktigt.</translation>
@@ -893,13 +917,14 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="4275830172053184480">Starta om enheten</translation>
<translation id="4277028893293644418">Återställ lösenord</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="4287885627794386150">Behörig för provperiod, men inte aktiv</translation>
<translation id="4297502707443874121">Miniatyr för sidan <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Expandera</translation>
<translation id="4300675098767811073">Flera hål till höger</translation>
<translation id="4302514097724775343">Tryck på dinon för att spela</translation>
<translation id="4302965934281694568">Chou3 (kuvert)</translation>
<translation id="4305666528087210886">Ingen åtkomst till filen</translation>
-<translation id="4305817255990598646">Byt</translation>
+<translation id="4306529830550717874">Vill du spara adressen?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Blockera (standard)</translation>
<translation id="4314815835985389558">Hantera synkronisering</translation>
@@ -926,6 +951,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="4377125064752653719">Du försökte öppna <ph name="DOMAIN" />, men servern visade ett certifikat som har återkallats av utfärdaren. Det innebär att säkerhetsuppgifterna som servern visar inte är absolut tillförlitliga. Du kanske kommunicerar med en skadlig server.</translation>
<translation id="4378154925671717803">Mobil</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Live Caption</translation>
<translation id="4406896451731180161">sökresultat</translation>
<translation id="4408413947728134509">Cookies <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Du angav just ditt lösenord på en bedräglig webbplats. Vi rekommenderar att du besöker <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> och andra webbplatser där du använder lösenordet och ändrar det nu.</translation>
@@ -938,7 +964,6 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="4435702339979719576">vykort)</translation>
<translation id="443673843213245140">Användning av proxy är inaktiverad men en explicit proxykonfiguration har angetts.</translation>
<translation id="4464826014807964867">Webbplatser med information från organisationen</translation>
-<translation id="4466881336512663640">Ändringar i formuläret ändras inte. Vill du fortsätta?</translation>
<translation id="4476953670630786061">Det här formuläret är inte säkert. Autofyll har inaktiverats.</translation>
<translation id="4477350412780666475">Nästa spår</translation>
<translation id="4482953324121162758">Den här webbplatsen översätts inte.</translation>
@@ -956,7 +981,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="4515275063822566619">Kort och adresser har hämtats från Chrome och ditt Google-konto (<ph name="ACCOUNT_EMAIL" />). Du hanterar dessa under <ph name="BEGIN_LINK" />Inställningar<ph name="END_LINK" />.</translation>
<translation id="4517607026994743406">Comm-10 (kuvert)</translation>
<translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> mm (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">Info</translation>
+<translation id="4522570452068850558">Detaljer</translation>
<translation id="4524138615196389145">Verifiera kreditkort snabbare genom att använda WebAuthn från och med nu</translation>
<translation id="4524805452350978254">Hantera kort</translation>
<translation id="4542971377163063093">Fack 6</translation>
@@ -972,6 +997,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="4594403342090139922">&amp;Ã…ngra Ta bort</translation>
<translation id="4597348597567598915">Storlek 8</translation>
<translation id="4600854749408232102">C6/C5 (kuvert)</translation>
+<translation id="4606870351894164739">Effektiv</translation>
<translation id="4628948037717959914">Foto</translation>
<translation id="4631649115723685955">Cashback länkad</translation>
<translation id="4636930964841734540">Info</translation>
@@ -991,6 +1017,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="4691835149146451662">Architecture-A (kuvert)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Sida</translation>
+<translation id="4702656508969495934">Live Caption visas. Använd fönsterbyte för att ändra fokus</translation>
<translation id="4708268264240856090">Anslutningen avbröts</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" /> köra nätverksdiagnostik för Windows<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="4738601419177586157">Sökförslag för <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Hantera lösenord …</translation>
<translation id="4744603770635761495">Sökväg till körbar fil</translation>
+<translation id="4749011317274908093">Du surfar inkognito</translation>
<translation id="4750917950439032686">Dina uppgifter (till exempel lösenord eller kreditkortsnummer) är privata när de skickas till den här webbplatsen.</translation>
<translation id="4756388243121344051">&amp;Historik</translation>
<translation id="4758311279753947758">Lägg till kontaktuppgifter</translation>
@@ -1033,6 +1061,8 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="4813512666221746211">Nätverksfel</translation>
<translation id="4816492930507672669">Anpassa till sida</translation>
<translation id="4819347708020428563">Vill du redigera kommentarer i standardvyn?</translation>
+<translation id="4825507807291741242">Kraftfull</translation>
+<translation id="4838327282952368871">Drömsk</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">Visa</translation>
<translation id="485316830061041779">tyska</translation>
@@ -1169,6 +1199,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="5314967030527622926">Broschyrenhet</translation>
<translation id="5316812925700871227">Rotera moturs</translation>
<translation id="5317780077021120954">Spara</translation>
+<translation id="5321288445143113935">Maximerat</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> av <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Välj kontaktuppgifter</translation>
<translation id="5327248766486351172">Namn</translation>
@@ -1176,11 +1207,13 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="5332219387342487447">Fraktmetod</translation>
<translation id="5333022057423422993">Chrome upptäckte att lösenordet som du precis använde har läckt ut vid ett dataintrång. Vi rekommenderar att du kontrollerar dina sparade lösenord för att skydda dina konton.</translation>
<translation id="5334013548165032829">Detaljerade systemloggar</translation>
+<translation id="5334145288572353250">Vill du spara adressen?</translation>
<translation id="5340250774223869109">Appen blockeras</translation>
<translation id="534295439873310000">NFC-enheter</translation>
<translation id="5344579389779391559">Den här sidan kan försöka debitera dig</translation>
<translation id="5355557959165512791">Det går inte att besöka <ph name="SITE" /> just nu eftersom dess certifikat har återkallats. Nätverksfel och attacker är ofta tillfälliga, så sidan kommer förmodligen att fungera senare.</translation>
<translation id="536296301121032821">Det gick inte att spara policyinställningarna</translation>
+<translation id="5363309033720083897">Serieporten tillåts av administratören</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="5386426401304769735">Certifikatkedjan för den här webbplatsen innehåller ett certifikat som signerades med SHA-1.</translation>
@@ -1189,6 +1222,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="5398772614898833570">Annonser blockeras</translation>
<translation id="5400836586163650660">Grå</translation>
<translation id="540969355065856584">Servern kunde inte bevisa att det är <ph name="DOMAIN" />. Dess säkerhetscertifikat är inte giltigt för närvarande. Detta kan bero på en felaktig konfiguration eller att någon kapat din anslutning.</translation>
+<translation id="541143247543991491">Cloud (för hela systemet)</translation>
<translation id="541416427766103491">Utmatningsfack 4</translation>
<translation id="5421136146218899937">Ta bort webbinformation...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> vill skicka aviseringar</translation>
@@ -1202,6 +1236,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="5455374756549232013">Felaktig tidsstämpel för policy</translation>
<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="5463625433003343978">Letar efter enheter …</translation>
<translation id="5469868506864199649">italienska</translation>
<translation id="5470861586879999274">&amp;Gör om Redigera</translation>
<translation id="5478437291406423475">B6/C4 (kuvert)</translation>
@@ -1251,7 +1286,6 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="5624120631404540903">Hantera lösenord</translation>
<translation id="5629630648637658800">Det gick inte att läsa in policyinställningarna</translation>
<translation id="5631439013527180824">Ogiltig enhetshanteringstoken</translation>
-<translation id="5632627355679805402">Din data krypterades med det <ph name="BEGIN_LINK" />Google-lösenord<ph name="END_LINK" /> du hade den <ph name="TIME" />. Ange det om du vill starta synkroniseringen.</translation>
<translation id="5633066919399395251">Angripare på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kan försöka installera skadliga program som stjäl eller raderar information (t.ex. foton, lösenord, meddelanden och kreditkortsuppgifter) på datorn. <ph name="BEGIN_LEARN_MORE_LINK" />Läs mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Bedrägligt innehåll har blockerats.</translation>
<translation id="5644090287519800334">Sida 1 bild X – byte</translation>
@@ -1290,12 +1324,12 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="5785756445106461925">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 utseende.</translation>
<translation id="5786044859038896871">Vill du att kortuppgifterna ska fyllas i?</translation>
<translation id="578633867165174378">Chrome upptäckte att lösenordet som du precis använde har läckt ut vid ett dataintrång. Vi rekommenderar att du byter det här lösenordet nu.</translation>
-<translation id="5798290721819630480">Vill du ignorera ändringarna?</translation>
<translation id="5803412860119678065">Vill du att uppgifterna om <ph name="CARD_DETAIL" /> ska fyllas i?</translation>
<translation id="5804241973901381774">Behörigheter</translation>
<translation id="5804427196348435412">Använd NFC-enheter</translation>
<translation id="5810442152076338065">Anslutningen till <ph name="DOMAIN" /> är krypterad med en gammal krypteringssvit.</translation>
<translation id="5813119285467412249">&amp;Gör om Lägg till</translation>
+<translation id="5817918615728894473">Koppla</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Det här kortet debiteras när du betalar, men kortnumret delas inte med webbplatsen. En tillfällig CVC-kod skapas som en extra säkerhetsåtgärd.}other{Det valda kortet debiteras när du betalar, men kortnumret delas inte med webbplatsen. En tillfällig CVC-kod skapas som en extra säkerhetsåtgärd.}}</translation>
<translation id="5826507051599432481">Vanligt namn (CN)</translation>
<translation id="5838278095973806738">Du bör inte ange några känsliga uppgifter på den här webbplatsen (till exempel lösenord eller kreditkortsuppgifter) eftersom hackare kan stjäla dem.</translation>
@@ -1303,6 +1337,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="5855253129151731373">Webbplatsens värdnamn liknar <ph name="LOOKALIKE_DOMAIN" />. Ibland försöker hackare efterlikna webbplatser genom att göra små, svårupptäckta ändringar i domännamnet.
Besök https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals om du anser att detta är felaktigt.</translation>
+<translation id="5860033963881614850">Av</translation>
<translation id="5862579898803147654">Utmatningsfack 8</translation>
<translation id="5863847714970149516">Sidan du är på väg till kan försöka debitera dig</translation>
<translation id="5866257070973731571">Ange telefonnummer</translation>
@@ -1319,6 +1354,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="5913377024445952699">Skärmbild/skärminspelning har pausats</translation>
<translation id="59174027418879706">Aktiverad</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 används}other{# används}}</translation>
<translation id="5921185718311485855">PÃ¥</translation>
<translation id="5921639886840618607">Vill du spara kortet i Google-kontot?</translation>
<translation id="5922853866070715753">Nästan klart</translation>
@@ -1338,6 +1374,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="5989320800837274978">Varken fasta proxyservrar eller en webbadress med PAC-skript har angetts.</translation>
<translation id="5992691462791905444">Förskjuten Z-falsning</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> resultat för <ph name="SEARCH_TEXT" /></translation>
+<translation id="6006484371116297560">Klassiskt</translation>
<translation id="6008122969617370890">N till 1-ordning</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Kontrollera lösenorden</translation>
@@ -1359,6 +1396,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="6045164183059402045">Utskjutningsmall</translation>
<translation id="6047233362582046994">Om du är medveten om säkerhetsriskerna kan du <ph name="BEGIN_LINK" />besöka webbplatsen<ph name="END_LINK" /> innan de skadliga apparna har tagits bort.</translation>
<translation id="6047927260846328439">Sidan kan ha till syfte att försöka lura dig att installera programvara eller avslöja personliga uppgifter. <ph name="BEGIN_LINK" />Visa ändå<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Avsluta helskärmsläget genom att trycka på |<ph name="ACCELERATOR" />| och hålla kvar</translation>
<translation id="6049488691372270142">Sidvisning</translation>
<translation id="6051221802930200923">Du kan inte besöka <ph name="SITE" /> just nu eftersom tekniken att fästa certifikat används på webbplatsen. Nätverksfel och attacker är ofta tillfälliga, så sidan kommer förmodligen att fungera senare.</translation>
<translation id="6051898664905071243">Sidantal:</translation>
@@ -1375,6 +1413,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<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>
<translation id="6116338172782435947">Tillgång till text och bilder som kopierats till Urklipp</translation>
<translation id="6120179357481664955">Vill du spara UPI-id?</translation>
+<translation id="6123290840358279103">Visa virtuellt kort</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Kontrollera kablar och starta om routrar, modem och andra nätverksenheter
som används.</translation>
@@ -1411,6 +1450,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="6289939620939689042">Sidfärg</translation>
<translation id="6290238015253830360">Rekommenderade artiklar visas här</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google-assistenten i Chrome stoppas</translation>
<translation id="6305205051461490394"><ph name="URL" /> kan inte nås.</translation>
<translation id="6312113039770857350">Webbsidan är inte tillgänglig</translation>
@@ -1436,6 +1476,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="6390200185239044127">Halv Z-falsning</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Möjligheten att klistra in från <ph name="ORIGIN_NAME" /> här blockeras av administratörspolicyn</translation>
+<translation id="6398765197997659313">Avsluta helskärmsläge</translation>
<translation id="6401136357288658127">Den här principen är utfasad. Använd principen <ph name="NEW_POLICY" /> i stället.</translation>
<translation id="6404511346730675251">Redigera bokmärke</translation>
<translation id="6406765186087300643">C0 (kuvert)</translation>
@@ -1448,7 +1489,6 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="6428450836711225518">Bekräfta ditt telefonnummer</translation>
<translation id="6433490469411711332">Redigera kontaktuppgifter</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> avvisade anslutningen.</translation>
-<translation id="6434309073475700221">Släng</translation>
<translation id="6440503408713884761">Ignoreras</translation>
<translation id="6443406338865242315">Vilka tillägg och pluginprogram som du har installerat</translation>
<translation id="6446163441502663861">Kahu (kuvert)</translation>
@@ -1491,6 +1531,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="6624427990725312378">Kontaktuppgifter</translation>
<translation id="6626291197371920147">Lägg till ett giltigt kortnummer</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Sök</translation>
+<translation id="6630043285902923878">Söker efter USB-enheter …</translation>
<translation id="6630809736994426279">Angripare på <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> kan försöka installera skadliga program som stjäl eller raderar information (t.ex. foton, lösenord, meddelanden och kreditkortsuppgifter) på din Mac. <ph name="BEGIN_LEARN_MORE_LINK" />Läs mer<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Rensa</translation>
@@ -1506,6 +1547,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<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="6687335167692595844">Teckenstorlek begärd</translation>
+<translation id="6688743156324860098">Uppdatera …</translation>
<translation id="6689249931105087298">Relativ med svartpunktskomprimering</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="6698381487523150993">Skapad av:</translation>
@@ -1521,6 +1563,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="6744009308914054259">Du kan öppna Nedladdningar och läsa artiklar offline medan du väntar på anslutningen.</translation>
<translation id="6753269504797312559">Policyvärde</translation>
<translation id="6757797048963528358">Enheten gick i viloläge.</translation>
+<translation id="6767985426384634228">Vill du uppdatera adressen?</translation>
<translation id="6768213884286397650">Hagaki (vykort)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Violett</translation>
@@ -1543,6 +1586,7 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" />, <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome har förenklat sidan så att den ska bli lättare att läsa. Chrome hämtade den ursprungliga sidan via en osäker anslutning.</translation>
<translation id="6891596781022320156">Policynivån stöds inte.</translation>
+<translation id="6895143722905299846">Kortnummer:</translation>
<translation id="6895330447102777224">Kortet har bekräftats</translation>
<translation id="6897140037006041989">Användaragent</translation>
<translation id="6898699227549475383">Organisation (O)</translation>
@@ -1578,10 +1622,10 @@ Annars blockeras detta av sekretessinställningarna. Om du tillåter detta kan i
<translation id="7004583254764674281">Verifiera kreditkort snabbare med Windows Hello</translation>
<translation id="7006930604109697472">Skicka ändå</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Inställningar för storleksanpassning</translation>
<translation id="7014741021609395734">Zoomnivå</translation>
<translation id="7016992613359344582">Debiteringen kan göras en gång eller återkommande och det behöver inte framgå tydligt att detta händer.</translation>
<translation id="7029809446516969842">Lösenord</translation>
+<translation id="7030436163253143341">Certifikatet är ogiltigt</translation>
<translation id="7031646650991750659">Vilka appar från Google Play som du har installerat</translation>
<translation id="7050187094878475250">Du försökte nå <ph name="DOMAIN" />, men servern svarade med ett certifikat vars giltighetstid är för lång för att det ska vara trovärdigt.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Det går inte att lägga till det här kortet just nu}other{Det går inte att lägga till de här korten just nu}}</translation>
@@ -1651,12 +1695,14 @@ Mer information.
<translation id="7300012071106347854">Koboltblå</translation>
<translation id="7302712225291570345"><ph name="TEXT" /></translation>
<translation id="7304030187361489308">Hög</translation>
+<translation id="7305756307268530424">Starta långsammare</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Anslutningshjälp</translation>
<translation id="7323804146520582233">Dölj avsnittet <ph name="SECTION" /></translation>
<translation id="733354035281974745">Åsidosätt enhetens lokala konto</translation>
<translation id="7333654844024768166">Du angav just ditt lösenord på en bedräglig webbplats. Vi rekommenderar att du besöker <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> och andra webbplatser där du använder lösenordet och ändrar det nu.</translation>
<translation id="7334320624316649418">&amp;Gör om Ändra ordning</translation>
+<translation id="7337248890521463931">Visa fler rader</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>
@@ -1664,6 +1710,7 @@ Mer information.
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Kommandorad</translation>
<translation id="7359588939039777303">Annonser blockeras.</translation>
+<translation id="7363096869660964304">Men du är inte osynlig. Inkognitoläget döljer inte webbhistoriken för din arbetsgivare, internetleverantören eller webbplatserna du besöker.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, tryck på Tabb och sedan på Retur om du vill lägga till och hantera adresser i inställningarna för Chrome</translation>
<translation id="7365849542400970216">Vill du låta webbplatsen veta om du använder enheten aktivt?</translation>
<translation id="7372973238305370288">sökresultat</translation>
@@ -1674,7 +1721,9 @@ Mer information.
<translation id="7378594059915113390">Mediereglage</translation>
<translation id="7378627244592794276">Nej</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ej tillämpligt</translation>
<translation id="7390545607259442187">Bekräfta kort</translation>
+<translation id="7392089738299859607">Uppdatera adressen</translation>
<translation id="7399802613464275309">Säkerhetskontroll</translation>
<translation id="7400418766976504921">Webbadress</translation>
<translation id="7403591733719184120">Din <ph name="DEVICE_NAME" /> hanteras</translation>
@@ -1689,6 +1738,7 @@ Mer information.
&lt;li&gt;Besök &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;hjälpcentret för Chrome&lt;/a&gt; om du vill veta mer om hur du tar bort programvaran från datorn permanent
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Ljuvlig</translation>
<translation id="7416351320495623771">Hantera lösenord …</translation>
<translation id="7419106976560586862">Profilsökväg</translation>
<translation id="7437289804838430631">Lägg till kontaktuppgifter</translation>
@@ -1704,7 +1754,7 @@ Mer information.
<translation id="7481312909269577407">Framåt</translation>
<translation id="7485870689360869515">Ingen data hittades.</translation>
<translation id="7495528107193238112">Det här innehållet har blockerats. Kontakta webbplatsägaren om du vill åtgärda problemet.</translation>
-<translation id="7498234416455752244">Fortsätt redigera</translation>
+<translation id="7498193950643227031">Appen kanske inte fungerar som väntat om du ändrar storleken. Nu kan du begränsa möjligheten att ändra storlek på appar i <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Du angav just ditt lösenord på en bedräglig webbplats. Chromium rekommenderar att du kontrollerar dina sparade lösenord för <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> och andra webbplatser där du använder lösenordet nu.</translation>
<translation id="7508255263130623398">Enhets-id för returnerad princip är tomt eller matchar inte nuvarande enhets-id</translation>
<translation id="7508870219247277067">Avokadogrön</translation>
@@ -1724,6 +1774,7 @@ Mer information.
<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="755279583747225797">Provperioden är aktiv</translation>
<translation id="7552846755917812628">Testa följande tips:</translation>
<translation id="7554475479213504905">Läs in igen och visa ändå</translation>
<translation id="7554791636758816595">Ny flik</translation>
@@ -1742,7 +1793,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, tryck på Tabb och sedan på Retur om du vill visa och hantera lösenord i inställningarna för Chrome</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="7616645509853975347">Administratören har aktiverat Chrome Enterprise Connectors i din webbläsare. Dessa funktioner har åtkomst till en del av din data.</translation>
<translation id="7619838219691048931">Sista ark</translation>
<translation id="762844065391966283">Ett objekt i taget</translation>
@@ -1807,13 +1857,12 @@ Mer information.
<translation id="782886543891417279">wifi-nätverket du använder (<ph name="WIFI_NAME" />) kanske kräver att du besöker dess inloggningssida.</translation>
<translation id="7836231406687464395">Postfix (kuvert)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Inga}=1{1 app (<ph name="EXAMPLE_APP_1" />)}=2{2 appar (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# appar (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Men du är inte osynlig. Inkognitoläget döljer inte webbhistoriken för din arbetsgivare, internetleverantören eller webbplatserna du besöker.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Öppna filer med kopplad filhanterare.</translation>
<translation id="7862185352068345852">Vill du lämna webbplatsen?</translation>
<translation id="7865448901209910068">Bästa hastighet</translation>
<translation id="7874263914261512992">Du angav just ditt lösenord på en bedräglig webbplats. Chrome rekommenderar att du kontrollerar dina sparade lösenord för <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> och andra webbplatser där du använder lösenordet nu.</translation>
<translation id="7878562273885520351">Lösenordet kan vara utsatt för risk</translation>
+<translation id="7880146494886811634">Spara adressen</translation>
<translation id="7882421473871500483">Brun</translation>
<translation id="7887683347370398519">Kontrollera CVC-koden och försök igen</translation>
<translation id="7887885240995164102">Öppna bild-i-bild-läge</translation>
@@ -1821,6 +1870,7 @@ Mer information.
<translation id="7894280532028510793">Om stavningen är rätt <ph name="BEGIN_LINK" />testar du att köra nätverksdiagnostik<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (kuvert)</translation>
<translation id="7931318309563332511">okänt</translation>
+<translation id="793209273132572360">Vill du uppdatera adressen?</translation>
<translation id="7932579305932748336">Beläggning</translation>
<translation id="79338296614623784">Ange ett giltigt telefonnummer</translation>
<translation id="7934052535022478634">Betalningen är slutförd</translation>
@@ -1891,6 +1941,7 @@ Mer information.
<translation id="8175796834047840627">Du erbjuds av Chrome att spara dina kort i Google-kontot eftersom du är inloggad. Du kan ändra detta i inställningarna.</translation>
<translation id="8176440868214972690">Administratören för enheten har skickat en del information, t.ex. inställningar eller principer, till följande webbplatser.</translation>
<translation id="8184538546369750125">Använd global standardinställning (Tillåt)</translation>
+<translation id="8193086767630290324">Åtgärder som gjorts med data som markerats som konfidentiell</translation>
<translation id="8194797478851900357">&amp;Ã…ngra Flytta</translation>
<translation id="8201077131113104583">Ogiltig webbadress för uppdatering för tillägg med id <ph name="EXTENSION_ID" />.</translation>
<translation id="8202097416529803614">Beställningsöversikt</translation>
@@ -1913,6 +1964,7 @@ Mer information.
<translation id="8249296373107784235">Avbryt</translation>
<translation id="8249320324621329438">Senast hämtad:</translation>
<translation id="8253091569723639551">En faktureringsadress måste anges</translation>
+<translation id="8257387598443225809">Den här appen har utformats för mobila enheter</translation>
<translation id="825929999321470778">Visa alla sparade lösenord</translation>
<translation id="8261506727792406068">Radera</translation>
<translation id="8262952874573525464">Kanthäftning längst ned</translation>
@@ -2037,7 +2089,6 @@ Mer information:
<translation id="8719528812645237045">Flera hål högst upp</translation>
<translation id="8725066075913043281">Försök igen</translation>
<translation id="8726549941689275341">Sidstorlek:</translation>
-<translation id="8728672262656704056">Du surfar inkognito</translation>
<translation id="8730621377337864115">Klart</translation>
<translation id="8731544501227493793">Knappen Hantera lösenord, tryck på Retur om du vill visa och hantera lösenord i inställningarna för Chrome</translation>
<translation id="8734529307927223492">Din <ph name="DEVICE_TYPE" /> hanteras av <ph name="MANAGER" /></translation>
@@ -2114,6 +2165,7 @@ Mer information:
<translation id="9020542370529661692">Den här sidan har översatts till <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Ogiltigt)</translation>
+<translation id="9030265603405983977">Monokrom</translation>
<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>
@@ -2137,6 +2189,7 @@ Mer information:
<translation id="91108059142052966">Administratören har angett en princip som inaktiverar skärmdelning med <ph name="APPLICATION_TITLE" /> när konfidentiellt innehåll visas på skärmen</translation>
<translation id="9114524666733003316">Kortet kontrolleras …</translation>
<translation id="9114581008513152754">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="9117930699067497412">Fräsch</translation>
<translation id="9119042192571987207">Uppladdad</translation>
<translation id="9128016270925453879">Policyer har lästs in</translation>
<translation id="9128870381267983090">Anslut till ett nätverk</translation>
@@ -2155,6 +2208,7 @@ Mer information:
<translation id="9170848237812810038">&amp;Ã…ngra</translation>
<translation id="9171296965991013597">Vill du lämna appen?</translation>
<translation id="9173282814238175921">Enkelt dokument/nytt ark</translation>
+<translation id="9173995187295789444">Söker efter Bluetooth-enheter …</translation>
<translation id="917450738466192189">Servercertifikatet är ogiltigt.</translation>
<translation id="9174917557437862841">Knapp som byter flik. Tryck på Retur om du vill byta till den här fliken</translation>
<translation id="9179703756951298733">Hantera dina betalnings- och kreditkortsuppgifter i inställningarna för Chrome</translation>
diff --git a/chromium/components/strings/components_strings_sw.xtb b/chromium/components/strings/components_strings_sw.xtb
index e7d09452bd9..3f7749a6615 100644
--- a/chromium/components/strings/components_strings_sw.xtb
+++ b/chromium/components/strings/components_strings_sw.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Ikiteuliwa, Chrome itahifadhi nakala ya kadi yako kwenye kifaa hiki kwa ajili ya kujaza fomu haraka.</translation>
<translation id="1110994991967754504">Chagua ruhusa ya <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">Tendua kupanga upya</translation>
+<translation id="1123753900084781868">Kipengele cha Manukuu Papo Hapo hakipatikani wakati huu</translation>
<translation id="1125573121925420732">Huenda onyo zikawa nyingi wakati tovuti zinasasisha usalama. Hali hii itaboreshwa hivi karibuni.</translation>
<translation id="112840717907525620">Akiba ya sera ni SAWA</translation>
<translation id="1130564665089811311">Kitufe cha 'Tafsiri ukurasa', bonyeza 'Enter' ili utafsiri ukurasa huu kwa kutumia Google Tafsiri</translation>
@@ -74,6 +75,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="1240347957665416060">Jina la kifaa chako</translation>
<translation id="124116460088058876">Lugha zaidi</translation>
<translation id="1243027604378859286">Mwandishi:</translation>
+<translation id="1246424317317450637">Herufi nzito</translation>
<translation id="1250759482327835220">Ili ulipe kwa haraka wakati ujao, hifadhi anwani ya kutuma bili, jina na maelezo ya kadi yako kwenye Akaunti yako ya Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (zimesawazishwa)</translation>
<translation id="1256368399071562588">&lt;p&gt;Ukijaribu kutembelea tovuti na haifunguki, jaribu kwanza kurekebisha hitilafu kwa kutumia hatua hizi za utatuzi:&lt;/p&gt;
@@ -156,6 +158,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="1476595624592550506">Badilisha nenosiri lako</translation>
<translation id="1484290072879560759">Chagua Anwani ya Mahali Bidhaa Zitakapopelekwa</translation>
<translation id="1492194039220927094">Sera zinaweza kutumwa:</translation>
+<translation id="1495677929897281669">Rudi kwenye kichupo</translation>
<translation id="1501859676467574491">Onyesha kadi kutoka Akaunti yako ya Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Utaona hitilafu hii kama unatumia mtandao wa Wi-Fi ambapo unatakiwa kuingia katika akaunti kabla ya kwenda mtandaoni.&lt;/p&gt;
&lt;p&gt;Ili urekebishe hitilafu, bofya &lt;strong&gt;Unganisha&lt;/strong&gt; kwenye ukurasa unaojaribu kufungua.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="1532118530259321453">Ukurasa huu unasema</translation>
<translation id="153384715582417236">Hakuna maudhui mengine kwa sasa</translation>
<translation id="1536390784834419204">Tafsiri ukurasa</translation>
+<translation id="1539840569003678498">Ripoti imetumwa:</translation>
<translation id="154408704832528245">Chagua Mahali Bidhaa Itakapopelekwa</translation>
<translation id="1549470594296187301">Lazima JavaScript iwashwe ili utumie kipengele hiki.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="1682696192498422849">Pembe fupi kwanza</translation>
<translation id="168693727862418163">Thamani ya sera hii imeshindwa kuthibitishwa kwenye taratibu yake na itapuuzwa.</translation>
<translation id="168841957122794586">Cheti cha seva kina kitufe dhaifu cha kifichua msimbo.</translation>
+<translation id="1696290444144917273">Angalia maelezo ya kadi pepe</translation>
<translation id="1697532407822776718">Mko tayari nyote!</translation>
<translation id="1703835215927279855">Barua</translation>
<translation id="1706954506755087368">{1,plural, =1{Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; cheti chake cha usalama kitakwisha muda kuanzia kesho. Hii inaweza kusababishwa na usanidi usiofaa au mvamizi kuingilia muunganisho wako.}other{Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; cheti chake cha usalama kitakwisha muda kuanzia siku # zijazo. Hii inaweza kusababishwa na usanidi usiofaa au mvamizi kuingilia muunganisho wako.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Imepuuzwa kwa sababu <ph name="POLICY_NAME" /> haijawekwa kuwa <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> inataka kuhifadhi kabisa data kwenye kompyuta yako ya karibu</translation>
<translation id="1713628304598226412">Trei ya pili</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Kikasha cha barua cha tatu</translation>
<translation id="1718029547804390981">Huwezi kuweka vidokezo kwenye hati kwa kuwa ni kubwa mno</translation>
<translation id="1721424275792716183">* Unahitaji kujaza sehemu hii</translation>
+<translation id="1727613060316725209">Cheti ni sahihi</translation>
<translation id="1727741090716970331">Ongeza Nambari Sahihi ya Kadi</translation>
<translation id="1728677426644403582">Unaangalia chanzo cha ukurasa wa wavuti</translation>
<translation id="173080396488393970">Aina hii ya kadi haitumiki</translation>
@@ -245,7 +252,6 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
mada si sahihi, hali inayozuia kivinjari kisitekeleze
ombi lako la <ph name="SITE" />. Sera za asili zinaweza kutumiwa na wahudumu wa tovuti kuweka mipangilio ya usalama na sifa nyingine za tovuti.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Tafadhali sasisha kaulisiri yako iliyolandanishwa.</translation>
<translation id="1787142507584202372">Vichupo vyako vilivyo wazi huonekana hapa</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, vitendo vingi vinapatikana, bonyeza 'Tab' ili uvipitie</translation>
@@ -278,6 +284,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="1919345977826869612">Matangazo</translation>
<translation id="1919367280705858090">Pata usaidizi kwa kutumia ujumbe mahususi kuhusu hitilafu</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Hamna}=1{Tovuti 1}other{Tovuti #}}</translation>
+<translation id="1924727005275031552">Mpya</translation>
<translation id="1945968466830820669">Unaweza kupoteza uwezo wa kufikia akaunti ya shirika lako au kuibiwa utambulisho. Chromium inapendekeza ubadilishe nenosiri lako sasa.</translation>
<translation id="1947454675006758438">Bana juu kulia</translation>
<translation id="1958218078413065209">Alama yako ya juu zaidi ni <ph name="SCORE" />.</translation>
@@ -300,12 +307,14 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="2042213636306070719">Trei ya saba</translation>
<translation id="204357726431741734">Ingia katika akaunti ili utumie manenosiri uliyohifadhi kwenye Akaunti yako ya Google</translation>
<translation id="2053111141626950936">Haitatafsiri kurasa za <ph name="LANGUAGE" />.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Wakati kidhibiti hiki kimewashwa na teknolojia hii inatumika, Chrome hubaini kikundi kikubwa cha watu, au “kundiâ€, ambalo shughuli zako za kuvinjari za hivi majuzi zinafanana nalo kwa ukaribu zaidi. Watangazaji wanaweza kuchagua matangazo kwa ajili ya kikundi hicho na shughuli zako za kuvinjari huwekwa kwa faragha kwenye kifaa chako. Kikundi chako husasishwa kila siku.}=1{Wakati kidhibiti hiki kimewashwa na teknolojia hii inatumika, Chrome hubaini kikundi kikubwa cha watu, au “kundiâ€, ambalo shughuli zako za kuvinjari za hivi majuzi zinafanana nalo kwa ukaribu zaidi. Watangazaji wanaweza kuchagua matangazo kwa ajili ya kikundi hicho na shughuli zako za kuvinjari huwekwa kwa faragha kwenye kifaa chako. Kikundi chako husasishwa kila siku.}other{Wakati kidhibiti hiki kimewashwa na teknolojia hii inatumika, Chrome hubaini kikundi kikubwa cha watu, au “kundiâ€, ambalo shughuli zako za kuvinjari za hivi majuzi zinafanana nalo kwa ukaribu zaidi. Watangazaji wanaweza kuchagua matangazo kwa ajili ya kikundi hicho na shughuli zako za kuvinjari huwekwa kwa faragha kwenye kifaa chako. Kikundi chako husasishwa kila baada ya siku {NUM_DAYS}.}}</translation>
<translation id="2053553514270667976">Msimbo wa eneo</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{Pendekezo 1}other{Mapendekezo #}}</translation>
<translation id="2071692954027939183">Arifa zimezuiwa kiotomatiki kwa sababu kwa kawaida huziruhusu</translation>
<translation id="2079545284768500474">Tendua</translation>
<translation id="20817612488360358">Mipangilio ya mfumo ya proksi imewekwa ili kutumiwa lakini usanidi dhahiri wa proksi pia umebainishwa.</translation>
<translation id="2082238445998314030">Tokeo <ph name="RESULT_NUMBER" /> kati ya <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Hifadhi…</translation>
<translation id="2088086323192747268">Kitufe cha 'Dhibiti usawazishaji', bonyeza 'Enter' ili udhibiti maelezo unayosawazisha katika mipangilio ya Chrome</translation>
<translation id="2091887806945687916">Sauti</translation>
<translation id="2094505752054353250">Kitolingana kwa kikoa</translation>
@@ -378,6 +387,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="2317259163369394535"><ph name="DOMAIN" /> inahitaji jina la mtumiaji na nenosiri.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, muda wa matumizi utakwisha <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Mipangilio inadhibitiwa na msimamizi wako</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> inataka kuoanisha</translation>
<translation id="2344028582131185878">Upakuaji wa Kiotomatiki</translation>
<translation id="2346319942568447007">Picha uliyonakili</translation>
<translation id="2354001756790975382">Alamisho zingine</translation>
@@ -385,8 +395,10 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="2355395290879513365">Wavamizi wanaweza kuona picha unazoangalia kwenye tovuti hii na wakuhadae kwa kuzibadilisha.</translation>
<translation id="2356070529366658676">Uliza</translation>
<translation id="2357481397660644965">Kifaa chako kinadhibitiwa na <ph name="DEVICE_MANAGER" /> na akaunti yako inadhibitiwa na <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Katika muda wa chini ya siku moja}=1{Baada ya siku moja}other{Baada ya siku {NUM_DAYS}}}</translation>
<translation id="2359629602545592467">Nyingi</translation>
<translation id="2359808026110333948">Endelea</translation>
+<translation id="2359961752320758691">Nambari yako ya kadi pepe imewekwa.</translation>
<translation id="2367567093518048410">Kiwango</translation>
<translation id="2372464001869762664">Ukishathibitisha, maelezo ya kadi kutoka Akaunti yako ya Google yatashirikiwa na tovuti hii. Pata CVC katika maelezo ya Akaunti yako ya Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -397,6 +409,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="239429038616798445">Mbinu hii ya usafirishaji haipatikani. Jaribu mbinu tofauti.</translation>
<translation id="2396249848217231973">Tendua kufuta</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Ya zamani</translation>
<translation id="2413528052993050574">Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; huenda cheti chake cha usalama kimebatilishwa. Hii inaweza kusababishwa na usanidi usiofaa au mvamizi kuingilia muunganisho wako.</translation>
<translation id="2414886740292270097">Giza</translation>
<translation id="2438874542388153331">Toboa mara nne kulia</translation>
@@ -424,10 +437,10 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="2521385132275182522">Bana chini kulia</translation>
<translation id="2523886232349826891">Imehifadhiwa kwenye kifaa hiki pekee</translation>
<translation id="2524461107774643265">Ongeza Maelezo Zaidi</translation>
-<translation id="2526590354069164005">Eneo-kazi</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{na lingine 1}other{na mengine #}}</translation>
<translation id="2536110899380797252">Ongeza Anwani</translation>
<translation id="2539524384386349900">Gundua</translation>
+<translation id="2541219929084442027">Kurasa unazoziangalia katika vichupo fiche hazitaendelea kuwepo katika historia ya kivinjari, hifadhi ya vidakuzi au historia yako ya utafutaji ukishafunga vichupo vyako vyote fiche. Faili zozote unazopakua au alamisho unazoweka hazitafutwa.</translation>
<translation id="2544644783021658368">Hati moja</translation>
<translation id="254947805923345898">Thamani ya sera si sahihi.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> imetuma jibu ambalo si sahihi.</translation>
@@ -447,6 +460,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="2629325967560697240">Ili upate kiwango cha juu zaidi cha usalama kutoka Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />washa kipengele cha ulinzi wa kiwango cha juu<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Haikupata anwani ya IP ya seva ya <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Hali:</translation>
+<translation id="264810637653812429">Haikupata vifaa vyovyote vinavyooana.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, bonyeza 'Tab' kisha 'Enter' ili ufute historia yako ya kuvinjari, vidakuzi, akiba na zaidi katika mipangilio ya Chrome</translation>
<translation id="2650446666397867134">Ufikivu katika faili umekataliwa</translation>
@@ -493,6 +507,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<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="2807052079800581569">Mkao wa Picha ya Y</translation>
+<translation id="2820957248982571256">Inatafuta...</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>
@@ -500,6 +515,8 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="2850739647070081192">Invite (Bahasha)</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="2859806420264540918">Tovuti inaonyesha matangazo yanayopotosha au yanayokatiza huduma.</translation>
+<translation id="287596039013813457">Friendly</translation>
+<translation id="2876489322757410363">Inafunga hali fiche ili kulipa kupitia programu ya nje. Ungependa kuendelea?</translation>
<translation id="2878197950673342043">Mkunjo wa bango</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Kuonyesha dirisha</translation>
@@ -549,7 +566,6 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="3060227939791841287">C9 (Bahasha)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, bonyeza kichupo cha 'Tab' kisha 'Enter' ili ufanye Ukaguzi wa Usalama katika mipangilio ya Chrome</translation>
<translation id="3061707000357573562">Huduma ya Kurekebisha</translation>
-<translation id="3064966200440839136">Inaacha hali fiche ili kulipa kupitia programu ya nje. Je, ungependa kuendelea?</translation>
<translation id="306573536155379004">Mchezo umeanza.</translation>
<translation id="3080254622891793721">Picha</translation>
<translation id="3086579638707268289">Shughuli yako kwenye tovuti inafuatiliwa</translation>
@@ -572,7 +588,6 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="315504272643575312">Akaunti yako inadhibitiwa na <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Rejesha</translation>
<translation id="3162559335345991374">Wi-Fi unayotumia inaweza kukuhitaji kutembelea ukurasa wake wa kuingia katika akaunti.</translation>
-<translation id="3167968892399408617">Kurasa unazoziangalia katika vichupo fiche hazitaendelea kuwepo katika historia ya kivinjari, hifadhi ya vidakuzi, au historia yako ya utafutaji ukishafunga vichupo vyako vyote fiche. Faili zozote unazopakua au alamisho unazounda hazitafutwa.</translation>
<translation id="3169472444629675720">Gundua</translation>
<translation id="3174168572213147020">Kisiwa</translation>
<translation id="3176929007561373547">Angalia mipangilio yako ya seva mbadala au wasiliana na msimamizi wako wa mtandao ili
@@ -598,10 +613,12 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<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="3249845759089040423">Groovy</translation>
<translation id="3252266817569339921">Kifaransa</translation>
<translation id="3266793032086590337">Thamani (inakinzana)</translation>
<translation id="3268451620468152448">Fungua Vichupo</translation>
<translation id="3270847123878663523">Tendua Kupanga upya</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> inataka kuunganisha</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Shirika lako, <ph name="ENROLLMENT_DOMAIN" />, limetuma maelezo fulani kwenye tovuti zifuatazo, kama vile mipangilio au sera.</translation>
<translation id="3282497668470633863">Ongeza jina kwenye kadi</translation>
@@ -654,6 +671,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="3428151540071562330">URI moja au zaidi ya violezo vya seva ya DnsOverHttpsTemplates si sahihi na haitatumika.</translation>
<translation id="3431636764301398940">Hifadhi kadi hii kwenye kifaa hiki</translation>
<translation id="3432601291244612633">Funga ukurasa</translation>
+<translation id="3435738964857648380">Usalama</translation>
<translation id="3435896845095436175">Washa</translation>
<translation id="3438829137925142401">Tumia manenosiri uliyohifadhi kwenye Akaunti yako ya Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -696,7 +714,10 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="3584299510153766161">Toboa chini mara mbili</translation>
<translation id="3586931643579894722">Ficha maelezo</translation>
<translation id="3587738293690942763">Katikati</translation>
+<translation id="3590643883886679995">Ukifunga hali fiche, data ya kuingia katika akaunti itahifadhiwa kwenye kifaa hiki.</translation>
+<translation id="359126217934908072">Mwezi/Mwaka:</translation>
<translation id="3592413004129370115">Italian (Bahasha)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Unaweza kubadilisha kikundi chako wakati wowote. Inachukua takriban siku moja kujiunga na kikundi kipya.}=1{Unaweza kubadilisha kikundi chako wakati wowote. Inachukua takriban siku moja kujiunga na kikundi kipya.}other{Unaweza kubadilisha kikundi chako wakati wowote. Inachukua siku {NUM_DAYS} kujiunga na kikundi kipya.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Programu imezuiwa na msimamizi wako</translation>
<translation id="3608932978122581043">Weka mkao</translation>
@@ -705,13 +726,13 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="3615877443314183785">Andika tarehe sahihi ya kuisha kwa muda wa matumizi</translation>
<translation id="36224234498066874">Futa Data ya Kuvinjari...</translation>
<translation id="362276910939193118">Onyesha Historia Kamili</translation>
-<translation id="3625635938337243871">Ukifunga hali fiche, data ya kuingia katika akaunti itahifadhiwa kwenye kifaa hiki.</translation>
<translation id="3630155396527302611">Ikiwa tayari imeorodheshwa kuwa programu inayoruhusiwa kufikia mtandao, jaribu
kuiondoa kwenye orodha kisha uiongeze tena.</translation>
<translation id="3630699740441428070">Wasimamizi wa kifaa hiki wameweka mipangilio kwenye muunganisho wa mtandao wako. Huenda hatua hii ikawaruhusu waone trafiki ya mtandao wako, ikiwa ni pamoja na tovuti unazotembelea.</translation>
<translation id="3631244953324577188">Bayometriki</translation>
<translation id="3633738897356909127">Kitufe cha 'Sasisha Chrome', bonyeza 'Enter' ili usasishe Chrome katika mipangilio yako ya Chrome</translation>
<translation id="3634530185120165534">Trei ya tano</translation>
+<translation id="3637662659967048211">Hifadhi kwenye Akaunti ya Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Programu:</translation>
<translation id="3650584904733503804">Uhalalishaji umefanikiwa</translation>
@@ -752,6 +773,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="3781428340399460090">Waridi Inayong'aa</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Vifaa vya Bluetooth</translation>
+<translation id="3787675388804467730">Nambari ya kadi pepe</translation>
<translation id="3787705759683870569">Muda wa matumizi utakwisha <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Ukubwa wa 16</translation>
<translation id="3789841737615482174">Sakinisha</translation>
@@ -771,6 +793,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="3841184659773414994">Vidhibiti vya Faili</translation>
<translation id="385051799172605136">Rudi nyuma</translation>
<translation id="3858027520442213535">Sasisha tarehe na saa</translation>
+<translation id="3881478300875776315">Onyesha mistari michache</translation>
<translation id="3884278016824448484">Kitambulisho cha kifaa kinachokinzana</translation>
<translation id="3885155851504623709">Parokia</translation>
<translation id="388632593194507180">Tukio la Ufuatiliaji Limetambuliwa</translation>
@@ -796,6 +819,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="397105322502079400">Inakokotoa...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> imezuiwa.</translation>
<translation id="3973357910713125165">Kitufe cha kufanya Ukaguzi wa Usalama kwenye Chrome, bonyeza 'Enter' ili ufanye Ukaguzi wa Usalama katika mipangilio ya Chrome</translation>
+<translation id="3986705137476756801">Zima kipengele cha Manukuu Papo Hapo kwa sasa</translation>
<translation id="3987405730340719549">Chrome imebaini kwamba huenda tovuti hii ni bandia au laghai.
Ikiwa unaamini kuwa taarifa hii imeonyeshwa kimakosa, tembelea https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -892,13 +916,14 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="4275830172053184480">Washa upya kifaa chako</translation>
<translation id="4277028893293644418">Badilisha nenosiri</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="4287885627794386150">Umetimiza masharti ya kutumia jaribio lakini hujaanza kulitumia</translation>
<translation id="4297502707443874121">Kijipicha cha ukurasa wa <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Panua</translation>
<translation id="4300675098767811073">Toboa mara kadhaa kulia</translation>
<translation id="4302514097724775343">Gusa dinosau ili ucheze</translation>
<translation id="4302965934281694568">Chou3 (Bahasha)</translation>
<translation id="4305666528087210886">Imeshindwa kufikia faili yako</translation>
-<translation id="4305817255990598646">Badilisha</translation>
+<translation id="4306529830550717874">Ungependa kuhifadhi anwani?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Zuia (chaguomsingi)</translation>
<translation id="4314815835985389558">Dhibiti usawazishaji</translation>
@@ -925,6 +950,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="4377125064752653719">Ulijaribu kufikia <ph name="DOMAIN" />, lakini cheti kilichowasilishwa na seva kimebatilishwa na mtoaji wacho. Huku ni kumaanisha kuwa stakabadhi za usalama zilizowasilishwa na seva hii hazifai kuaminiwa kabisa. Huenda ukawa unawasiliana na mshabulizi.</translation>
<translation id="4378154925671717803">Simu</translation>
<translation id="4390472908992056574">Pomoni</translation>
+<translation id="4406883609789734330">Manukuu Papo Hapo</translation>
<translation id="4406896451731180161">matokeo ya utafutaji</translation>
<translation id="4408413947728134509">Vidakuzi <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Umeweka nenosiri lako kwenye tovuti inayotiliwa shaka. Chrome inapendekeza uende kwenye <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> na tovuti nyingine unakotumia nenosiri hili na ulibadilishe sasa.</translation>
@@ -937,7 +963,6 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="4435702339979719576">Kad ya Posta)</translation>
<translation id="443673843213245140">Matumizi ya proksi yamelemazwa lakini usanidi wa proksi wazi umebainishwa.</translation>
<translation id="4464826014807964867">Tovuti zenye maelezo kutoka kwa shirika lako</translation>
-<translation id="4466881336512663640">Haitahifadhi mabadiliko uliyofanya kwenye fomu. Je, una uhakika unataka kuendelea?</translation>
<translation id="4476953670630786061">Fomu hii si salama. Kipengele cha kujaza kiotomatiki kimezimwa.</translation>
<translation id="4477350412780666475">Wimbo Unaofuata</translation>
<translation id="4482953324121162758">Haitatafsiri tovuti hii.</translation>
@@ -971,6 +996,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="4594403342090139922">Tendua Kufuta</translation>
<translation id="4597348597567598915">Ukubwa wa 8</translation>
<translation id="4600854749408232102">C6/C5 (Bahasha)</translation>
+<translation id="4606870351894164739">Impactful</translation>
<translation id="4628948037717959914">Picha</translation>
<translation id="4631649115723685955">Inajumuisha tuzo ya pesa</translation>
<translation id="4636930964841734540">Maelezo</translation>
@@ -990,6 +1016,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="4691835149146451662">Architecture-A (Bahasha)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Upande</translation>
+<translation id="4702656508969495934">Kiputo cha Manukuu Papo Hapo kinaonekana, tumia kibadilishaji dirisha ili uangazie kiputo</translation>
<translation id="4708268264240856090">Muunganisho wako umekatizwa</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Kuendesha Zana ya Windows ya Kuchunguza Mtandao<ph name="END_LINK" /></translation>
@@ -1003,6 +1030,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="4738601419177586157">Pendekezo la utafutajI la <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Dhibiti manenosiri…</translation>
<translation id="4744603770635761495">Njia Tekelezi</translation>
+<translation id="4749011317274908093">Unavinjari katika hali fiche</translation>
<translation id="4750917950439032686">Maelezo yako (kwa mfano, manenosiri, au nambari za kadi za mikopo) ni ya faragha yanapotumwa kwenye tovuti hii.</translation>
<translation id="4756388243121344051">&amp;Historia</translation>
<translation id="4758311279753947758">Ongeza maelezo ya mawasiliano</translation>
@@ -1032,6 +1060,8 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="4813512666221746211">Hitilafu ya mtandao</translation>
<translation id="4816492930507672669">Sawazisha kwenye ukurasa</translation>
<translation id="4819347708020428563">Ungependa kubadilisha vidokezo katika mwonekano chaguomsingi?</translation>
+<translation id="4825507807291741242">Powerful</translation>
+<translation id="4838327282952368871">Dreamy</translation>
<translation id="484462545196658690">Otomatiki</translation>
<translation id="4850886885716139402">Mwonekano</translation>
<translation id="485316830061041779">Kijerumani</translation>
@@ -1168,6 +1198,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="5314967030527622926">Kialamishi cha kijitabu</translation>
<translation id="5316812925700871227">Zungusha kinyume cha mwendo wa saa</translation>
<translation id="5317780077021120954">Hifadhi</translation>
+<translation id="5321288445143113935">Iliyopanuliwa</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> kati ya <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Chagua Maelezo ya Mawasiliano</translation>
<translation id="5327248766486351172">Jina</translation>
@@ -1175,11 +1206,13 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="5332219387342487447">Mbinu ya Usafirishaji</translation>
<translation id="5333022057423422993">Chrome imepata nenosiri ambalo umeweka sasa hivi kwenye tukio la ufichuzi haramu wa data. Ili uimarishe usalama wa akaunti zako, tunapendekeza ukague manenosiri uliyoyahifadhi.</translation>
<translation id="5334013548165032829">Kumbukumbu za mfumo za kina</translation>
+<translation id="5334145288572353250">Ungependa Kuhifadhi Anwani?</translation>
<translation id="5340250774223869109">Programu imezuiwa</translation>
<translation id="534295439873310000">Vifaa vya NFC</translation>
<translation id="5344579389779391559">Ukurasa huu huenda ukajaribu kukutoza pesa</translation>
<translation id="5355557959165512791">Huwezi kutembelea <ph name="SITE" /> sasa hivi kwa sababu cheti chake kimebatilishwa. Hitilafu na uvamizi wa mtandao kwa kawaida huwa wa muda, kwa hivyo huenda ukurasa huu utafanya kazi baadaye.</translation>
<translation id="536296301121032821">Imeshindwa kuhifadhi mipangilio ya sera</translation>
+<translation id="5363309033720083897">Mlango huu wa kuchomeka vifaa unaruhusiwa na msimamizi wako</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="5386426401304769735">Msururu wa cheti wa tovuti hii una cheti kilichotiwa sahihi kwa kutumia SHA-1.</translation>
@@ -1188,6 +1221,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="5398772614898833570">Matangazo yamezuiwa</translation>
<translation id="5400836586163650660">Kijivu</translation>
<translation id="540969355065856584">Seva hii haikuweza kuthibitisha kuwa ni <ph name="DOMAIN" />; cheti chake cha usalama si sahihi kwa sasa. Hii inaweza kusababishwa na usanidi usiofaa au mvamizi kuingilia muunganisho wako.</translation>
+<translation id="541143247543991491">Wingu (mfumo mzima)</translation>
<translation id="541416427766103491">Tupio la kutoa la printa la nne</translation>
<translation id="5421136146218899937">Futa data ya kuvinjari...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> inataka kukutumia arifa</translation>
@@ -1201,6 +1235,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="5455374756549232013">Muhuri wa muda wa sera mbaya</translation>
<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="5463625433003343978">Inatafuta vifaa...</translation>
<translation id="5469868506864199649">Kiitaliano</translation>
<translation id="5470861586879999274">Rudia kuhariri</translation>
<translation id="5478437291406423475">B6/C4 (Bahasha)</translation>
@@ -1250,7 +1285,6 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="5624120631404540903">Dhibiti manenosiri</translation>
<translation id="5629630648637658800">Imeshindwa kupakia mipangilio ya sera</translation>
<translation id="5631439013527180824">Ishara ya usimamizi wa kifaa batili</translation>
-<translation id="5632627355679805402">Data yako imesimbwa kwa kutumia <ph name="BEGIN_LINK" />Nenosiri la Google<ph name="END_LINK" /> kufikia <ph name="TIME" />. Liweke ili uanze kusawazisha.</translation>
<translation id="5633066919399395251">Wavamizi ambao sasa wako kwenye <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> huenda wakajaribu kusakinisha programu hatari kwenye kompyuta yako ambazo zinaiba au kufuta maelezo yako (kwa mfano, picha, manenosiri, ujumbe na kadi za mikopo). <ph name="BEGIN_LEARN_MORE_LINK" />Pata maelezo zaidi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Maudhui ya udanganyifu yamezuiwa.</translation>
<translation id="5644090287519800334">Ugeuzaji wa upande wa kwanza wa picha ya X</translation>
@@ -1289,12 +1323,12 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="5785756445106461925">Mbali na hayo, ukurasa huu una rasilimali nyingine zisizo salama. Rasilimali hizi zinaweza kuangaliwa na watu wengine wanaosafiri, na zinaweza kurekebishwa na mvamizi kubadilisha mwonekano wa ukurasa.</translation>
<translation id="5786044859038896871">Ungependa kujaza maelezo ya kadi yako?</translation>
<translation id="578633867165174378">Chrome imepata nenosiri ambalo umeweka sasa hivi kwenye tukio la ufichuzi haramu wa data. Tunapendekeza ubadilishe nenosiri hili sasa.</translation>
-<translation id="5798290721819630480">Ungependa kufuta mabadiliko uliyoyafanya?</translation>
<translation id="5803412860119678065">Ungependa kujaza maelezo ya <ph name="CARD_DETAIL" /> yako?</translation>
<translation id="5804241973901381774">Idhini</translation>
<translation id="5804427196348435412">Kutumia vifaa vya NFC</translation>
<translation id="5810442152076338065">Muunganisho wako kwenye <ph name="DOMAIN" /> umesimbwa kwa njia fiche kwa kutumia mipangilio ya kriptografia ya zamani.</translation>
<translation id="5813119285467412249">Rudia Kuongeza</translation>
+<translation id="5817918615728894473">Oanisha</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Kadi hii itatozwa utakapolipa, lakini nambari yake halisi haitashirikiwa na tovuti hii. Kwa usalama zaidi, tutatengeneza CVC ya muda mfupi.}other{Kadi unayochagua itatozwa utakapolipa lakini, nambari yake halisi haitashirikiwa na tovuti hii. Kwa usalama zaidi, tutatengeneza CVC ya muda mfupi.}}</translation>
<translation id="5826507051599432481">Jina la Kawaida (CN)</translation>
<translation id="5838278095973806738">Hupaswi kuweka maelezo nyeti kwenye tovuti hii (kwa mfano, manenosiri au kadi za mikopo), kwa sababu wavamizi wanaweza kuyaiba.</translation>
@@ -1302,6 +1336,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="5855253129151731373">Jina la tovuti hii linafafana na la <ph name="LOOKALIKE_DOMAIN" />. Wakati mwingine, wadukuzi huiga tovuti kwa kufanya mabadiliko madogo kwenye jina la kikoa ambayo si rahisi kuonekana.
Ikiwa unaamini kuwa taarifa hii imeonyeshwa kimakosa, tembelea https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Kimezimwa</translation>
<translation id="5862579898803147654">Tupio la kutoa la printa la nane</translation>
<translation id="5863847714970149516">Huenda ukurasa unaofuata ukajaribu kukutoza pesa</translation>
<translation id="5866257070973731571">Ongeza Nambari ya Simu</translation>
@@ -1318,6 +1353,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="5913377024445952699">Kipengele cha kupiga picha ya skrini kimesitishwa</translation>
<translation id="59174027418879706">Imewezeshwa</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 kinatumika}other{ # vinatumika}}</translation>
<translation id="5921185718311485855">Imewashwa</translation>
<translation id="5921639886840618607">Ungependa kuhifadhi kadi kwenye Akaunti ya Google?</translation>
<translation id="5922853866070715753">Unakaribia kumaliza</translation>
@@ -1337,6 +1373,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="5989320800837274978">Siyo seva proksi za kudumu wala URL ya hati ya .pac zimebainishwa.</translation>
<translation id="5992691462791905444">Mkunjo wa Z wa uhandisi</translation>
<translation id="6000758707621254961">Matokeo <ph name="RESULT_COUNT" /> ya '<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">Kawaida</translation>
<translation id="6008122969617370890">Mpangilio wa N hadi moja</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Kagua manenosiri yako</translation>
@@ -1358,6 +1395,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="6045164183059402045">Kiolezo cha kuweka karatasi</translation>
<translation id="6047233362582046994">Ikiwa unaelewa hatari kwa usalama wako, unaweza <ph name="BEGIN_LINK" />kuitembelea tovuti hii<ph name="END_LINK" /> kabla programu hasidi hazijaondolewa.</translation>
<translation id="6047927260846328439">Maudhui haya yanaweza kukuhadaa kusakinisha programu au kuonyesha maelezo yako ya binafsi. <ph name="BEGIN_LINK" />Onyesha tu<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Bonyeza na ushikilie |<ph name="ACCELERATOR" />| ili uondoke katika hali ya skrini nzima</translation>
<translation id="6049488691372270142">Utumaji wa ukurasa</translation>
<translation id="6051221802930200923">Huwezi kutembelea <ph name="SITE" /> sasa hivi kwa sababu tovuti hii inatumia ubandikaji cheti. Hitilafu na uvamizi wa mtandao kwa kawaida huwa vya muda, kwa hivyo ukurasa huu huenda utafanya kazi baadaye.</translation>
<translation id="6051898664905071243">Idadi ya kurasa:</translation>
@@ -1374,6 +1412,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<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>
<translation id="6116338172782435947">Kuona maandishi na picha zilizonakiliwa kwenye ubao wa kunakili</translation>
<translation id="6120179357481664955">Ungependa kukumbuka kitambulisho chako cha UPI?</translation>
+<translation id="6123290840358279103">Angalia kadi pepe</translation>
<translation id="6124432979022149706">Viunganishi vya Chrome Enterprise</translation>
<translation id="6146055958333702838">Angalia kebo zozote na uwashe tena kisambaza data, modemu, au vifaa vingine vyovyote vya
mtandao ambavyo huenda unavitumia.</translation>
@@ -1410,6 +1449,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="6289939620939689042">Rangi ya Ukurasa</translation>
<translation id="6290238015253830360">Makala unayopendekezewa yataonekana hapa</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Programu ya Mratibu wa Google katika Chrome inaacha kufanya kazi</translation>
<translation id="6305205051461490394"><ph name="URL" /> haiwezi kufikiwa.</translation>
<translation id="6312113039770857350">Ukurasa wa wavuti haupatikani</translation>
@@ -1435,6 +1475,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="6390200185239044127">Mkunjo wa Z nusu</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Sera ya msimamizi imezuia kubandika hapa kutoka <ph name="ORIGIN_NAME" /></translation>
+<translation id="6398765197997659313">Ondoka kwenye Skrini nzima</translation>
<translation id="6401136357288658127">Sera hii imeacha kuendesha huduma. Ni sharti utumie sera ya <ph name="NEW_POLICY" /> badala yake.</translation>
<translation id="6404511346730675251">Badilisha alamisho</translation>
<translation id="6406765186087300643">C0 (Bahasha)</translation>
@@ -1447,7 +1488,6 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="6428450836711225518">Thibitisha nambari yako ya simu</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="6440503408713884761">Imepuuzwa</translation>
<translation id="6443406338865242315">Viendelezi au programu jalizi ulizosakinisha</translation>
<translation id="6446163441502663861">Kahu (Bahasha)</translation>
@@ -1490,6 +1530,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="6624427990725312378">Maelezo ya Mawasiliano</translation>
<translation id="6626291197371920147">Ongeza nambari sahihi ya kadi</translation>
<translation id="6628463337424475685">Utafutaji wa <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Inatafuta vifaa vya USB...</translation>
<translation id="6630809736994426279">Wavamizi ambao sasa wako kwenye <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> huenda wakajaribu kusakinisha programu hatari kwenye Mac yako ambazo zinaiba au kufuta maelezo yako (kwa mfano, picha, manenosiri, ujumbe na kadi za mikopo). <ph name="BEGIN_LEARN_MORE_LINK" />Pata maelezo zaidi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Futa</translation>
@@ -1505,6 +1546,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="6671697161687535275">Je, ungependa kuondoa pendekezo la fomu kwenye Chromium?</translation>
<translation id="6685834062052613830">Ondoka na ukamilishe kuweka mipangilio</translation>
<translation id="6687335167692595844">Imeomba ukubwa wa fonti</translation>
+<translation id="6688743156324860098">Sasisha…</translation>
<translation id="6689249931105087298">Ya kiwango cha kati yenye sehemu nyeusi iliyobanwa</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="6698381487523150993">Imeundwa</translation>
@@ -1520,6 +1562,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="6744009308914054259">Wakati unasubiri muunganisho, unaweza kutembelea Vipakuliwa ili usome makala yaliyo nje ya mtandao.</translation>
<translation id="6753269504797312559">Thamani ya sera</translation>
<translation id="6757797048963528358">Kifaa chako kiko katika hali tuli.</translation>
+<translation id="6767985426384634228">Ungependa Kusasisha Anwani?</translation>
<translation id="6768213884286397650">Hagaki (Kadi ya Posta)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Zambarau iliyokolea</translation>
@@ -1542,6 +1585,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome imerahisisha ukurasa huu ili usomeke kwa urahisi. Chrome imerejesha ukurasa halisi kupitia muunganisho usio salama.</translation>
<translation id="6891596781022320156">Kiwango cha sera hakitumiki.</translation>
+<translation id="6895143722905299846">Nambari pepe:</translation>
<translation id="6895330447102777224">Kadi yako imethibitishwa</translation>
<translation id="6897140037006041989">Programu ya Mtumiaji</translation>
<translation id="6898699227549475383">Shirika (O)</translation>
@@ -1577,10 +1621,10 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="7004583254764674281">Tumia Windows Hello ili uthibitishe kadi kwa haraka zaidi</translation>
<translation id="7006930604109697472">Tuma tu</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Mipangilio ya Kubadilisha Ukubwa</translation>
<translation id="7014741021609395734">Kiwango cha ukuzaji</translation>
<translation id="7016992613359344582">Gharama hizi zinaweza kuwa za mara moja au za kujirudia na huenda zisiwe za moja kwa moja.</translation>
<translation id="7029809446516969842">Manenosiri</translation>
+<translation id="7030436163253143341">Cheti si sahihi</translation>
<translation id="7031646650991750659">Programu za Google Play ambazo umesakinisha</translation>
<translation id="7050187094878475250">Ulijaribu kufikia <ph name="DOMAIN" />, lakini seva ikawasilisha cheti ambacho muda wake sahihi ni mrefu sana wa kuweza kuaminika.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Huwezi kuhifadhi kadi hii sasa hivi}other{Huwezi kuhifadhi kadi hizi sasa hivi}}</translation>
@@ -1648,12 +1692,14 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="7300012071106347854">Nili Iliyoiva</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Juu</translation>
+<translation id="7305756307268530424">Anza polepole</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Usaidizi kuhusu Muunganisho</translation>
<translation id="7323804146520582233">Ficha sehemu ya "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Futa akaunti ya ndani ya kifaa</translation>
<translation id="7333654844024768166">Umeweka nenosiri lako kwenye tovuti inayotiliwa shaka. Chromium inapendekeza uende kwenye <ph name="WEBSITE_1" />,<ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> na tovuti nyingine unakotumia nenosiri hili na ulibadilishe sasa.</translation>
<translation id="7334320624316649418">Rudia Kupanga Upya</translation>
+<translation id="7337248890521463931">Onyesha mistari zaidi</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>
@@ -1661,6 +1707,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Mbinu ya Amri</translation>
<translation id="7359588939039777303">Matangazo yamezuiwa.</translation>
+<translation id="7363096869660964304">Hata hivyo, bado unaweza kuonekana. Kuvinjari katika Hali fiche hakufichi shughuli zako za kuvinjari zisionekane na mwajiri, mtoa huduma wako wa intaneti au tovuti unazotembelea.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, bonyeza 'Tab' kisha 'Enter' ili uweke na udhibiti anwani katika mipangilio ya Chrome</translation>
<translation id="7365849542400970216">Ungependa ifahamu wakati unatumia kifaa chako?</translation>
<translation id="7372973238305370288">matokeo ya utafutaji</translation>
@@ -1671,7 +1718,9 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="7378594059915113390">Vidhibiti vya Maudhui</translation>
<translation id="7378627244592794276">La</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Haitumiki</translation>
<translation id="7390545607259442187">Thibitisha Kadi</translation>
+<translation id="7392089738299859607">Sasisha Anwani</translation>
<translation id="7399802613464275309">Angalizo la Usalama</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">Kifaa chako cha <ph name="DEVICE_NAME" /> kinadhibitiwa</translation>
@@ -1686,6 +1735,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
&lt;li&gt;Tembelea &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Kituo cha usaidizi wa Chrome&lt;/a&gt; ili upate maelezo zaidi kuhusu jinsi ya kuondoa kabisa programu kwenye kompyuta yako
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Lovely</translation>
<translation id="7416351320495623771">Dhibiti Manenosiri…</translation>
<translation id="7419106976560586862">Kijia cha Maelezo mafupi</translation>
<translation id="7437289804838430631">Ongeza Maelezo ya Mawasiliano</translation>
@@ -1701,7 +1751,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="7481312909269577407">Mbele</translation>
<translation id="7485870689360869515">Hakuna data iliyopatikana.</translation>
<translation id="7495528107193238112">Maudhui haya yamezuiwa. Wasiliana na mmiliki wa tovuti ili asuluhishe tatizo.</translation>
-<translation id="7498234416455752244">Endelea kubadilisha</translation>
+<translation id="7498193950643227031">Huenda isifanye kazi vizuri ukubwa wake ukibadilishwa. Sasa unaweza kuzuia ukubwa wa programu usibadilishwe katika <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Umeweka nenosiri lako kwenye tovuti inayotiliwa shaka. Chromium inapendekeza ukague manenosiri uliyohifadhi kwenye <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> na tovuti nyingine unakotumia nenosiri hili kwa sasa.</translation>
<translation id="7508255263130623398">Kitambulisho cha sera ya kifaa kilichorejeshwa hakina kitu au hakilingani na kitambulisho cha kifaa kilichopo</translation>
<translation id="7508870219247277067">Kijani cha Parachichi</translation>
@@ -1721,6 +1771,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<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="755279583747225797">Jaribio linatumika</translation>
<translation id="7552846755917812628">Jaribu vidokezo vinavyofuata:</translation>
<translation id="7554475479213504905">Pakia upya na uonyeshe hata hivyo</translation>
<translation id="7554791636758816595">Kichupo Kipya</translation>
@@ -1739,7 +1790,6 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, bonyeza 'Tab' kisha 'Enter' ili uangalie na udhibiti manenosiri yako katika mipangilio ya Chrome</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="7616645509853975347">Msimamizi wako amewasha Viunganishi vya Chrome Enterprise kwenye kivinjari chako. Viunganishi hivi vina uwezo wa kufikia baadhi ya data yako.</translation>
<translation id="7619838219691048931">Laha la mwisho</translation>
<translation id="762844065391966283">Moja kwa wakati mmoja</translation>
@@ -1804,13 +1854,12 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="782886543891417279">Wi-Fi unayotumia (<ph name="WIFI_NAME" />) inaweza kukuhitaji kutembelea ukurasa wake wa kuingia katika akaunti.</translation>
<translation id="7836231406687464395">Postfix (Bahasha)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Hamna}=1{Programu 1 (<ph name="EXAMPLE_APP_1" />)}=2{Programu 2 (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{Programu # (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Hata hivyo, huonekani. Kuvinjari katika hali fiche hakufichi kuvinjari kwako kusionekane na mwajiri, mtoaji huduma wako wa intaneti, au tovuti unazotembelea.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Kufungua faili zenye uhusiano wa aina ya faili.</translation>
<translation id="7862185352068345852">Ungependa kufunga tovuti?</translation>
<translation id="7865448901209910068">Kasi bora zaidi</translation>
<translation id="7874263914261512992">Umeweka nenosiri lako kwenye tovuti inayotiliwa shaka. Chrome inapendekeza ukague manenosiri uliyohifadhi kwenye <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> na tovuti nyingine unakotumia nenosiri hili kwa sasa.</translation>
<translation id="7878562273885520351">Huenda nenosiri lako limetambulika</translation>
+<translation id="7880146494886811634">Hifadhi Anwani</translation>
<translation id="7882421473871500483">Kahawia</translation>
<translation id="7887683347370398519">Angalia CVC yako na ujaribu tena</translation>
<translation id="7887885240995164102">Washa hali ya picha ndani ya picha</translation>
@@ -1818,6 +1867,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="7894280532028510793">Iwapo hakuna kosa la hijai, <ph name="BEGIN_LINK" />jaribu kutekeleza Uchunguzi wa Mtandao<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Bahasha)</translation>
<translation id="7931318309563332511">Haijulikani</translation>
+<translation id="793209273132572360">Ungependa kusasisha anwani?</translation>
<translation id="7932579305932748336">Koleza</translation>
<translation id="79338296614623784">Andika nambari sahihi ya simu</translation>
<translation id="7934052535022478634">Malipo yamekamilika</translation>
@@ -1888,6 +1938,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="8175796834047840627">Chrome ina huduma ya kuhifadhi kadi zako kwenye Akaunti yako ya Google kwa sababu umeingia katika akaunti. Unaweza kubadilisha hali hii katika mipangilio.</translation>
<translation id="8176440868214972690">Msimamizi wa kifaa hiki ametuma maelezo fulani kwenye tovuti zifuatazo, kama vile mipangilio au sera.</translation>
<translation id="8184538546369750125">Tumia chaguomsingi la duniani (Ruhusu)</translation>
+<translation id="8193086767630290324">Hatua zilizochukuliwa kwenye data iliyotiwa alama kuwa ni ya siri</translation>
<translation id="8194797478851900357">Tendua hatua</translation>
<translation id="8201077131113104583">URL ya sasisho si sahihi kwa kiendelezi chenye Kitambulisho "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Muhtasari wa agizo</translation>
@@ -1910,6 +1961,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="8249296373107784235">Ghairi</translation>
<translation id="8249320324621329438">Iliyoletwa mwisho:</translation>
<translation id="8253091569723639551">Anwani ya kutuma bili sharti iandikwe</translation>
+<translation id="8257387598443225809">Programu hii imeundwa kwa ajili ya vifaa vya mkononi</translation>
<translation id="825929999321470778">Onyesha Manenosiri Yote Yaliyohifadhiwa</translation>
<translation id="8261506727792406068">Futa</translation>
<translation id="8262952874573525464">Shona ncha ya chini</translation>
@@ -2032,7 +2084,6 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="8719528812645237045">Toboa mara nyingi juu</translation>
<translation id="8725066075913043281">Jaribu tena</translation>
<translation id="8726549941689275341">Ukubwa wa kurasa:</translation>
-<translation id="8728672262656704056">Unavinjari katika hali fiche</translation>
<translation id="8730621377337864115">Nimemaliza</translation>
<translation id="8731544501227493793">Kitufe cha 'Dhibiti manenosiri', bonyeza 'Enter' ili uangalie na udhibiti manenosiri yako katika mipangilio ya Chrome</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> yako inadhibitiwa na <ph name="MANAGER" /></translation>
@@ -2109,6 +2160,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="9020542370529661692">Ukurasa huu umetafsiriwa kwenda <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Si sahihi)</translation>
+<translation id="9030265603405983977">Monochrome</translation>
<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>
@@ -2132,6 +2184,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="91108059142052966">Sera ya msimamizi huzuia kushiriki skrini na <ph name="APPLICATION_TITLE" /> wakati maudhui ya siri yanaonekana</translation>
<translation id="9114524666733003316">Inathibitisha kadi…</translation>
<translation id="9114581008513152754">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="9117930699067497412">Fresh</translation>
<translation id="9119042192571987207">Imepakiwa</translation>
<translation id="9128016270925453879">Sera zimepakiwa</translation>
<translation id="9128870381267983090">Unganisha kwenye mtandao</translation>
@@ -2150,6 +2203,7 @@ Usipoiruhusu, itazuiwa na mipangilio yako ya faragha. Hali hii itaruhusu maudhui
<translation id="9170848237812810038">&amp;Tendua</translation>
<translation id="9171296965991013597">Ungependa kufunga programu?</translation>
<translation id="9173282814238175921">Hati moja/Laha jipya</translation>
+<translation id="9173995187295789444">Inatafuta vifaa vya Bluetooth...</translation>
<translation id="917450738466192189">Cheti cha seva ni batili.</translation>
<translation id="9174917557437862841">Kitufe cha kubadilisha kichupo, bonyeza Enter ili uende kwenye kichupo hiki</translation>
<translation id="9179703756951298733">Dhibiti maelezo yako ya malipo na ya kadi ya mikopo katika mipangilio ya Chrome</translation>
diff --git a/chromium/components/strings/components_strings_ta.xtb b/chromium/components/strings/components_strings_ta.xtb
index 027181858c9..538b153a8c6 100644
--- a/chromium/components/strings/components_strings_ta.xtb
+++ b/chromium/components/strings/components_strings_ta.xtb
@@ -39,13 +39,14 @@
<translation id="1107591249535594099">இத௠தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¾à®²à¯, விரைவாக படிவஙà¯à®•à®³à¯ˆ நிரபà¯à®ªà¯à®µà®¤à®±à¯à®•à®¾à®•, Chrome இநà¯à®¤ காரà¯à®Ÿà®¿à®©à¯ பிரதியை சாதனதà¯à®¤à®¿à®²à¯ சேமிகà¯à®•à¯à®®à¯.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" />கà¯à®•à®¾à®© அனà¯à®®à®¤à®¿à®¯à¯ˆà®¤à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•à®µà¯à®®à¯</translation>
<translation id="1113869188872983271">&amp;மறà¯à®µà®°à®¿à®šà¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ˆà®šà¯ செயலà¯à®¤à®µà®¿à®°à¯</translation>
+<translation id="1123753900084781868">'உடனடி வசனமà¯' à®…à®®à¯à®šà®®à¯ இபà¯à®ªà¯‹à®¤à¯ இலà¯à®²à¯ˆ</translation>
<translation id="1125573121925420732">இணையதளஙà¯à®•à®³à¯ தஙà¯à®•à®³à¯ பாதà¯à®•à®¾à®ªà¯à®ªà¯ˆà®ªà¯ பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®•à¯à®®à¯ போதà¯, எசà¯à®šà®°à®¿à®•à¯à®•à¯ˆà®•à®³à¯ˆà®•à¯ காணà¯à®ªà®¿à®ªà¯à®ªà®¤à¯ வழகà¯à®•à®®à¯ தானà¯. இநà¯à®¤ நிலை விரைவில௠மேமà¯à®ªà®Ÿà¯à®®à¯.</translation>
<translation id="112840717907525620">கொளà¯à®•à¯ˆ தறà¯à®•à®¾à®²à®¿à®• சேமிபà¯à®ªà¯ சரியாக உளà¯à®³à®¤à¯</translation>
<translation id="1130564665089811311">’பகà¯à®•à®¤à¯à®¤à¯ˆ மொழிபெயரà¯â€™ படà¯à®Ÿà®©à¯, Google Translate மூலம௠இநà¯à®¤à®ªà¯ பகà¯à®•à®¤à¯à®¤à¯ˆ மொழிபெயரà¯à®•à¯à®• Enter விசையை à®…à®´à¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
<translation id="1131264053432022307">நீஙà¯à®•à®³à¯ நகலெடà¯à®¤à¯à®¤ படமà¯</translation>
<translation id="1150979032973867961">இத௠<ph name="DOMAIN" /> தான௠எனà¯à®ªà®¤à¯ˆ இநà¯à®¤à®šà¯ சேவையகம௠உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà®¿à®²à¯à®²à¯ˆ; இதன௠பாதà¯à®•à®¾à®ªà¯à®ªà¯à®šà¯ சானà¯à®±à®¿à®¤à®´à¯ˆ உஙà¯à®•à®³à¯ கமà¯à®ªà¯à®¯à¯‚டà¯à®Ÿà®°à®¿à®©à¯ ஆபà¯à®°à¯‡à®Ÿà¯à®Ÿà®¿à®™à¯ சிஸà¯à®Ÿà®®à¯ நமà¯à®ªà®µà®¿à®²à¯à®²à¯ˆ. இத௠தவறான உளà¯à®³à®®à¯ˆà®µà®¾à®²à¯ à®à®±à¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯ அலà¯à®²à®¤à¯ தீஙà¯à®•à®¿à®´à¯ˆà®ªà¯à®ªà®µà®°à¯ உஙà¯à®•à®³à¯ இணைபà¯à®ªà®¿à®²à¯ கà¯à®±à¯à®•à¯à®•à®¿à®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯.</translation>
<translation id="1151972924205500581">கடவà¯à®šà¯à®šà¯Šà®²à¯ தேவை</translation>
-<translation id="1156303062776767266">அகக௠கோபà¯à®ªà¯ அலà¯à®²à®¤à¯ பகிரபà¯à®ªà®Ÿà¯à®Ÿ கோபà¯à®ªà¯ˆà®ªà¯ பாரà¯à®•à¯à®•à®¿à®±à¯€à®°à¯à®•à®³à¯</translation>
+<translation id="1156303062776767266">அகக௠கோபà¯à®ªà¯ அலà¯à®²à®¤à¯ பகிரபà¯à®ªà®Ÿà¯à®Ÿ ஃபைலைப௠பாரà¯à®•à¯à®•à®¿à®±à¯€à®°à¯à®•à®³à¯</translation>
<translation id="1158211211994409885"><ph name="HOST_NAME" /> எதிரà¯à®ªà®¾à®°à®¾à®¤ விதமாக இணைபà¯à®ªà¯ˆ நிறà¯à®¤à¯à®¤à®¿à®¯à®¤à¯.</translation>
<translation id="115926840831309955">உஙà¯à®•à®³à¯ CVCயைச௠சரிபாரà¯à®¤à¯à®¤à¯ மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®²à®µà¯à®®à¯ அலà¯à®²à®¤à¯ காலாவதித௠தேதியை மாறà¯à®±à®µà¯à®®à¯</translation>
<translation id="1161325031994447685">வைஃபையà¯à®Ÿà®©à¯ மீணà¯à®Ÿà¯à®®à¯ இணைதà¯à®¤à®²à¯</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">உஙà¯à®•à®³à¯ சாதனப௠பெயரà¯</translation>
<translation id="124116460088058876">மேலà¯à®®à¯ மொழிகளà¯</translation>
<translation id="1243027604378859286">உரà¯à®µà®¾à®•à¯à®•à®¿à®¯à®µà®°à¯:</translation>
+<translation id="1246424317317450637">தடிதà¯à®¤</translation>
<translation id="1250759482327835220">அடà¯à®¤à¯à®¤ à®®à¯à®±à¯ˆ விரைவாகப௠பணம௠செலà¯à®¤à¯à®¤, உஙà¯à®•à®³à¯ காரà¯à®Ÿà®¿à®©à¯ பெயரையà¯à®®à¯ பிலà¯à®²à®¿à®™à¯ à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®¯à¯à®®à¯ உஙà¯à®•à®³à¯ Google கணகà¯à®•à®¿à®²à¯ சேமிகà¯à®•à®µà¯à®®à¯.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (ஒதà¯à®¤à®¿à®šà¯ˆà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®©)</translation>
<translation id="1256368399071562588">&lt;p&gt;இணையதளதà¯à®¤à¯ˆà®ªà¯ பாரà¯à®•à¯à®• à®®à¯à®¯à®²à¯à®®à¯à®ªà¯‹à®¤à¯ அத௠திறகà¯à®•à®µà®¿à®²à¯à®²à¯ˆ எனிலà¯, à®®à¯à®¤à®²à®¿à®²à¯ இநà¯à®¤à®ªà¯ பிழையறிநà¯à®¤à¯ திரà¯à®¤à¯à®¤à¯à®¤à®²à¯ படிகளைப௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿, பிழையைச௠சரிசெயà¯à®¯ à®®à¯à®¯à®²à®µà¯à®®à¯:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">உஙà¯à®•à®³à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மாறà¯à®±à¯à®•</translation>
<translation id="1484290072879560759">ஷிபà¯à®ªà®¿à®™à¯ à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®¤à¯ தேரà¯à®µà¯ செயà¯</translation>
<translation id="1492194039220927094">கொளà¯à®•à¯ˆà®•à®³à¯ பà¯à®·à¯:</translation>
+<translation id="1495677929897281669">தாவலà¯à®•à¯à®•à¯à®¤à¯ திரà¯à®®à¯à®ªà¯</translation>
<translation id="1501859676467574491">எனத௠Google கணகà¯à®•à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ காரà¯à®Ÿà¯à®•à®³à¯ˆà®•à¯ காணà¯à®ªà®¿</translation>
<translation id="1507202001669085618">&lt;p&gt;சில வைஃபை போரà¯à®Ÿà¯à®Ÿà®²à¯à®•à®³à®¿à®²à¯, இணையதà¯à®¤à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ à®®à¯à®©à¯à®ªà¯ நீஙà¯à®•à®³à¯ உளà¯à®¨à¯à®´à¯ˆà®¯ வேணà¯à®Ÿà®¿à®¯à®¿à®°à¯à®•à¯à®•à¯à®®à¯. அதà¯à®ªà¯‹à®©à¯à®± போரà¯à®Ÿà¯à®Ÿà®²à¯à®•à®³à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®©à®¾à®²à¯, இநà¯à®¤à®ªà¯ பிழையைப௠பாரà¯à®ªà¯à®ªà¯€à®°à¯à®•à®³à¯.&lt;/p&gt;
&lt;p&gt;பிழையைச௠சரிசெயà¯à®¯, நீஙà¯à®•à®³à¯ திறகà¯à®• à®®à¯à®¯à®²à¯à®®à¯ பகà¯à®•à®¤à¯à®¤à®¿à®²à¯ உளà¯à®³ &lt;strong&gt;இணை&lt;/strong&gt; எனà¯à®ªà®¤à¯ˆà®•à¯ கிளிக௠செயà¯à®¯à®µà¯à®®à¯.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">இநà¯à®¤à®ªà¯ பகà¯à®•à®®à¯ தெரிவிபà¯à®ªà®¤à¯:</translation>
<translation id="153384715582417236">அவà¯à®µà®³à®µà¯ தானà¯!</translation>
<translation id="1536390784834419204">பகà¯à®•à®¤à¯à®¤à¯ˆ மொழிபெயரà¯</translation>
+<translation id="1539840569003678498">அறிகà¯à®•à¯ˆ அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯:</translation>
<translation id="154408704832528245">டெலிவரி à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®¤à¯ தேரà¯à®µà¯ செயà¯</translation>
<translation id="1549470594296187301">இநà¯à®¤ à®…à®®à¯à®šà®¤à¯à®¤à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ JavaScript இயகà¯à®•à®ªà¯à®ªà®Ÿ வேணà¯à®Ÿà¯à®®à¯.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">கà¯à®±à¯à®•à®¿à®¯ ஓரம௠மà¯à®¤à®²à®¿à®²à¯</translation>
<translation id="168693727862418163">இநà¯à®¤à®•à¯ கொளà¯à®•à¯ˆ அதன௠திடà¯à®Ÿà®ªà¯à®ªà®£à®¿à®¤à¯ தரவà¯à®•à¯à®•à¯ எதிராக மதிபà¯à®ªà¯€à®Ÿà¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà®¾à®¤à®¤à®¾à®²à¯ பà¯à®±à®•à¯à®•à®£à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.</translation>
<translation id="168841957122794586">சேவையக சானà¯à®±à®¿à®¤à®´à®¿à®²à¯ வலà¯à®µà®±à¯à®± கà¯à®±à®¿à®¯à¯€à®Ÿà¯à®Ÿà®¾à®•à¯à®• விசை இரà¯à®•à¯à®•à®¿à®±à®¤à¯.</translation>
+<translation id="1696290444144917273">விரà¯à®šà¯à®šà¯à®µà®²à¯ காரà¯à®Ÿà¯ விவரஙà¯à®•à®³à¯ˆà®•à¯ காடà¯à®Ÿà¯à®®à¯</translation>
<translation id="1697532407822776718">எலà¯à®²à®¾à®µà®±à¯à®±à¯ˆà®¯à¯à®®à¯ அமைதà¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà¯€à®°à¯à®•à®³à¯!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{இநà¯à®¤à®šà¯ சேவையகம௠தான௠<ph name="DOMAIN" /> எனà¯à®ªà®¤à¯ˆ நிரூபிகà¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ; இதன௠பாதà¯à®•à®¾à®ªà¯à®ªà¯à®šà¯ சானà¯à®±à®¿à®¤à®´à¯ நாளை à®®à¯à®¤à®²à¯‡ செலà¯à®²à¯à®ªà®Ÿà®¿à®¯à®¾à®•à¯à®®à¯. இத௠தவறான உளà¯à®³à®®à¯ˆà®µà®¾à®²à¯ à®à®±à¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯ அலà¯à®²à®¤à¯ தீஙà¯à®•à®¿à®´à¯ˆà®ªà¯à®ªà®µà®°à¯ உஙà¯à®•à®³à¯ இணைபà¯à®ªà®¿à®²à¯ கà¯à®±à¯à®•à¯à®•à®¿à®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯.}other{இநà¯à®¤à®šà¯ சேவையகம௠தான௠<ph name="DOMAIN" /> எனà¯à®ªà®¤à¯ˆ நிரூபிகà¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ; இதன௠பாதà¯à®•à®¾à®ªà¯à®ªà¯à®šà¯ சானà¯à®±à®¿à®¤à®´à¯ எதிரà¯à®•à®¾à®²à®¤à¯à®¤à®¿à®²à¯ # நாடà¯à®•à®³à®¿à®²à¯ à®à®±à¯à®±à¯à®•à¯à®•à¯Šà®³à¯à®³à®ªà¯à®ªà®Ÿà¯à®®à¯. இத௠தவறான உளà¯à®³à®®à¯ˆà®µà®¾à®²à¯ à®à®±à¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯ அலà¯à®²à®¤à¯ தீஙà¯à®•à®¿à®´à¯ˆà®ªà¯à®ªà®µà®°à¯ உஙà¯à®•à®³à¯ இணைபà¯à®ªà®¿à®²à¯ கà¯à®±à¯à®•à¯à®•à®¿à®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="VALUE" /> என <ph name="POLICY_NAME" /> அமைகà¯à®•à®ªà¯à®ªà®Ÿà®¾à®¤à®¤à®¾à®²à¯ நிராகரிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.</translation>
<translation id="1712552549805331520">உஙà¯à®•à®³à¯ கமà¯à®ªà¯à®¯à¯‚டà¯à®Ÿà®°à®¿à®²à¯ தரவை நிரநà¯à®¤à®°à®®à®¾à®•à®šà¯ சேமிகà¯à®• <ph name="URL" /> விரà¯à®®à¯à®ªà¯à®•à®¿à®±à®¤à¯</translation>
<translation id="1713628304598226412">தடà¯à®Ÿà¯ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">அஞà¯à®šà®²à¯ பெடà¯à®Ÿà®¿ 3</translation>
<translation id="1718029547804390981">ஆவணம௠மிகப௠பெரிதாக இரà¯à®ªà¯à®ªà®¤à®¾à®²à¯ அதில௠விரிவà¯à®°à¯ˆà®¯à¯ˆà®šà¯ சேரà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯</translation>
<translation id="1721424275792716183">* அவசியமான பà¯à®²à®®à¯</translation>
+<translation id="1727613060316725209">சானà¯à®±à®¿à®¤à®´à¯ சரியானதà¯</translation>
<translation id="1727741090716970331">சரியான காரà¯à®Ÿà¯ எணà¯à®£à¯ˆà®šà¯ சேரà¯à®•à¯à®•à®µà¯à®®à¯</translation>
<translation id="1728677426644403582">இணையப௠பகà¯à®•à®¤à¯à®¤à®¿à®©à¯ மூலதà¯à®¤à¯ˆà®ªà¯ பாரà¯à®•à¯à®•à®¿à®±à¯€à®°à¯à®•à®³à¯</translation>
<translation id="173080396488393970">இநà¯à®¤à®•à¯ காரà¯à®Ÿà¯ வகை ஆதரிகà¯à®•à®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ</translation>
@@ -246,7 +253,6 @@
<ph name="SITE" /> தளதà¯à®¤à®¿à®±à¯à®•à®¾à®© உஙà¯à®•à®³à¯ கோரிகà¯à®•à¯ˆà®¯à¯ˆ நிறைவà¯à®šà¯†à®¯à¯à®¯ à®®à¯à®Ÿà®¿à®¯à®¾à®¤ வகையில௠உலாவி தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. இணையதள ஆபà¯à®°à¯‡à®Ÿà¯à®Ÿà®°à¯à®•à®³à¯ இணையதளதà¯à®¤à®¿à®±à¯à®•à®¾à®© பாதà¯à®•à®¾à®ªà¯à®ªà¯ˆà®¯à¯à®®à¯ மறà¯à®± பணà¯à®ªà¯à®•à®³à¯ˆà®¯à¯à®®à¯ உளà¯à®³à®®à¯ˆà®•à¯à®•
அசல௠கொளà¯à®•à¯ˆà®•à®³à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à®¾à®®à¯.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">உஙà¯à®•à®³à®¿à®©à¯ ஒதà¯à®¤à®¿à®šà¯ˆ சொறà¯à®±à¯Šà®Ÿà®°à¯ˆà®ªà¯ பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®•à®µà¯à®®à¯.</translation>
<translation id="1787142507584202372">உஙà¯à®•à®³à¯ தாவலà¯à®•à®³à¯ இஙà¯à®•à¯‡ தோனà¯à®±à¯à®®à¯</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, ஒனà¯à®±à¯à®•à¯à®•à¯à®®à¯ மேறà¯à®ªà®Ÿà¯à®Ÿ செயலà¯à®•à®³à¯ உளà¯à®³à®©, அவறà¯à®±à®¿à®²à¯ ஒனà¯à®±à¯ˆà®¤à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®• Tab விசையை à®…à®´à¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
@@ -273,12 +279,13 @@
<translation id="1902576642799138955">செலà¯à®²à¯à®ªà®Ÿà®¿à®•à¯ காலமà¯</translation>
<translation id="1908217026282415406">கேமரா உபயோகம௠&amp; நகரà¯à®µà¯</translation>
<translation id="191374271204266022">JSON ஆக நகலெடà¯</translation>
-<translation id="1914326953223720820">ஜிப௠கோபà¯à®ªà¯à®•à®³à¯ˆà®¤à¯ திறகà¯à®•à¯à®®à¯ சேவை</translation>
+<translation id="1914326953223720820">ஜிப௠ஃபைலà¯à®•à®³à¯ˆà®¤à¯ திறகà¯à®•à¯à®®à¯ சேவை</translation>
<translation id="1915697529809968049">CVCகà¯à®•à¯à®ªà¯ பதிலாக Touch IDயைப௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà®¾?</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="1924727005275031552">பà¯à®¤à®¿à®¯ à®®à¯à®•à®µà®°à®¿</translation>
<translation id="1945968466830820669">உஙà¯à®•à®³à¯ நிறà¯à®µà®©à®¤à¯à®¤à®¿à®©à¯ கணகà¯à®•à®¿à®±à¯à®•à®¾à®© அணà¯à®•à®²à¯ˆ நீஙà¯à®•à®³à¯ இழகà¯à®•à®•à¯à®•à¯‚டà¯à®®à¯ அலà¯à®²à®¤à¯ அடையாளத௠திரà¯à®Ÿà¯à®Ÿà¯ˆ எதிரà¯à®•à¯Šà®³à¯à®³à®•à¯à®•à¯‚டà¯à®®à¯. இபà¯à®ªà¯‹à®¤à¯‡ உஙà¯à®•à®³à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மாறà¯à®±à¯à®®à¯à®ªà®Ÿà®¿ Chromium பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®¿à®±à®¤à¯.</translation>
<translation id="1947454675006758438">ஸà¯à®Ÿà¯‡à®ªà¯à®ªà®¿à®²à¯ டாப௠ரைடà¯</translation>
<translation id="1958218078413065209">உஙà¯à®•à®³à¯ அதிகபடà¯à®š ஸà¯à®•à¯‹à®°à¯: <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">தடà¯à®Ÿà¯ 7</translation>
<translation id="204357726431741734">உஙà¯à®•à®³à¯ Google கணகà¯à®•à®¿à®²à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³ கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ உளà¯à®¨à¯à®´à¯ˆà®•</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> மொழியில௠உளà¯à®³ பகà¯à®•à®™à¯à®•à®³à¯ மொழிபெயரà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà®¾à®¤à¯.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{இநà¯à®¤à®•à¯ கடà¯à®Ÿà¯à®ªà¯à®ªà®¾à®Ÿà¯ இயகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯ ‘செயலில௠உளà¯à®³à®¤à¯â€™ எனà¯à®± நிலையில௠இரà¯à®¨à¯à®¤à®¾à®²à¯ உஙà¯à®•à®³à¯ சமீபதà¯à®¤à®¿à®¯ உலாவல௠செயலà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®±à¯à®•à¯ மிகவà¯à®®à¯ பொரà¯à®¨à¯à®¤à®•à¯à®•à¯‚டிய பெரிய கà¯à®´à¯ அலà¯à®²à®¤à¯ “கà¯à®´à¯à®µà®¿à®©à®°à¯ˆâ€ Chrome அறிநà¯à®¤à¯à®•à¯Šà®³à¯à®³à¯à®®à¯. விளமà¯à®ªà®°à®¤à®¾à®°à®°à¯à®•à®³à¯ கà¯à®´à¯à®µà®¿à®±à¯à®•à®¾à®© விளமà¯à®ªà®°à®™à¯à®•à®³à¯ˆà®¤à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•à®²à®¾à®®à¯. மேலà¯à®®à¯ உஙà¯à®•à®³à¯ உலாவல௠செயலà¯à®ªà®¾à®Ÿà¯ உஙà¯à®•à®³à¯ சாதனதà¯à®¤à®¿à®²à¯ தனிபà¯à®ªà®Ÿà¯à®Ÿ à®®à¯à®±à¯ˆà®¯à®¿à®²à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯. தினமà¯à®®à¯ உஙà¯à®•à®³à¯ கà¯à®´à¯ பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.}=1{இநà¯à®¤à®•à¯ கடà¯à®Ÿà¯à®ªà¯à®ªà®¾à®Ÿà¯ இயகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯ ‘செயலில௠உளà¯à®³à®¤à¯â€™ எனà¯à®± நிலையில௠இரà¯à®¨à¯à®¤à®¾à®²à¯ உஙà¯à®•à®³à¯ சமீபதà¯à®¤à®¿à®¯ உலாவல௠செயலà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®±à¯à®•à¯ மிகவà¯à®®à¯ பொரà¯à®¨à¯à®¤à®•à¯à®•à¯‚டிய பெரிய கà¯à®´à¯ அலà¯à®²à®¤à¯ “கà¯à®´à¯à®µà®¿à®©à®°à¯ˆâ€ Chrome அறிநà¯à®¤à¯à®•à¯Šà®³à¯à®³à¯à®®à¯. விளமà¯à®ªà®°à®¤à®¾à®°à®°à¯à®•à®³à¯ கà¯à®´à¯à®µà®¿à®±à¯à®•à®¾à®© விளமà¯à®ªà®°à®™à¯à®•à®³à¯ˆà®¤à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•à®²à®¾à®®à¯. மேலà¯à®®à¯ உஙà¯à®•à®³à¯ உலாவல௠செயலà¯à®ªà®¾à®Ÿà¯ உஙà¯à®•à®³à¯ சாதனதà¯à®¤à®¿à®²à¯ தனிபà¯à®ªà®Ÿà¯à®Ÿ à®®à¯à®±à¯ˆà®¯à®¿à®²à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯. தினமà¯à®®à¯ உஙà¯à®•à®³à¯ கà¯à®´à¯ பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.}other{இநà¯à®¤à®•à¯ கடà¯à®Ÿà¯à®ªà¯à®ªà®¾à®Ÿà¯ இயகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯ ‘செயலில௠உளà¯à®³à®¤à¯â€™ எனà¯à®± நிலையில௠இரà¯à®¨à¯à®¤à®¾à®²à¯ உஙà¯à®•à®³à¯ சமீபதà¯à®¤à®¿à®¯ உலாவல௠செயலà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®±à¯à®•à¯ மிகவà¯à®®à¯ பொரà¯à®¨à¯à®¤à®•à¯à®•à¯‚டிய பெரிய கà¯à®´à¯ அலà¯à®²à®¤à¯ “கà¯à®´à¯à®µà®¿à®©à®°à¯ˆâ€ Chrome அறிநà¯à®¤à¯à®•à¯Šà®³à¯à®³à¯à®®à¯. விளமà¯à®ªà®°à®¤à®¾à®°à®°à¯à®•à®³à¯ கà¯à®´à¯à®µà®¿à®±à¯à®•à®¾à®© விளமà¯à®ªà®°à®™à¯à®•à®³à¯ˆà®¤à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•à®²à®¾à®®à¯. மேலà¯à®®à¯ உஙà¯à®•à®³à¯ உலாவல௠செயலà¯à®ªà®¾à®Ÿà¯ உஙà¯à®•à®³à¯ சாதனதà¯à®¤à®¿à®²à¯ தனிபà¯à®ªà®Ÿà¯à®Ÿ à®®à¯à®±à¯ˆà®¯à®¿à®²à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯. {NUM_DAYS} நாடà¯à®•à®³à¯à®•à¯à®•à¯ à®’à®°à¯à®®à¯à®±à¯ˆ உஙà¯à®•à®³à¯ கà¯à®´à¯ பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.}}</translation>
<translation id="2053553514270667976">ஜிப௠கà¯à®±à®¿à®¯à¯€à®Ÿà¯</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 பரிநà¯à®¤à¯à®°à¯ˆ}other{# பரிநà¯à®¤à¯à®°à¯ˆà®•à®³à¯}}</translation>
<translation id="2071692954027939183">வழகà¯à®•à®®à®¾à®• நீஙà¯à®•à®³à¯ அறிவிபà¯à®ªà¯à®•à®³à¯ˆ அனà¯à®®à®¤à®¿à®ªà¯à®ªà®¤à®¿à®²à¯à®²à¯ˆ எனà¯à®ªà®¤à®¾à®²à¯ அவை தானாகவே தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®©</translation>
<translation id="2079545284768500474">செயலà¯à®¤à®µà®¿à®°à¯</translation>
<translation id="20817612488360358">கணினி பà¯à®°à®¾à®•à¯à®¸à®¿ அமைபà¯à®ªà¯à®•à®³à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ அமைகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. வெளிபà¯à®ªà®Ÿà¯ˆà®¯à®¾à®© பà¯à®°à®¾à®•à¯à®¸à®¿ உளà¯à®³à®®à¯ˆà®µà¯à®®à¯ கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> à®®à¯à®Ÿà®¿à®µà¯à®•à®³à®¿à®²à¯ <ph name="RESULT_NUMBER" />வத௠மà¯à®Ÿà®¿à®µà¯</translation>
+<translation id="2085876078937250610">சேமி…</translation>
<translation id="2088086323192747268">ஒதà¯à®¤à®¿à®šà¯ˆà®µà¯ˆ நிரà¯à®µà®•à®¿à®ªà¯à®ªà®¤à®±à¯à®•à®¾à®© படà¯à®Ÿà®©à¯. எநà¯à®¤à¯†à®¨à¯à®¤à®¤à¯ தகவலà¯à®•à®³à¯ˆ ஒதà¯à®¤à®¿à®šà¯ˆà®•à¯à®• வேணà¯à®Ÿà¯à®®à¯ எனà¯à®ªà®¤à¯ˆ Chrome அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ நிரà¯à®µà®•à®¿à®•à¯à®•, Enter விசையை à®…à®´à¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
<translation id="2091887806945687916">ஒலி</translation>
<translation id="2094505752054353250">டொமைன௠பொரà¯à®¨à¯à®¤à®µà®¿à®²à¯à®²à¯ˆ</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" />கà¯à®•à¯à®ªà¯ பயனரà¯à®ªà¯†à®¯à®°à¯à®®à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯à®®à¯ தேவை.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, காலாவதித௠தேதி - <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">அமைபà¯à®ªà¯ˆ உஙà¯à®•à®³à¯ நிரà¯à®µà®¾à®•à®¿ கடà¯à®Ÿà¯à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•à®¿à®±à®¾à®°à¯</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> இணைய விரà¯à®®à¯à®ªà¯à®•à®¿à®±à®¤à¯</translation>
<translation id="2344028582131185878">தானியகà¯à®•à®ªà¯ பதிவிறகà¯à®•à®™à¯à®•à®³à¯</translation>
<translation id="2346319942568447007">நீஙà¯à®•à®³à¯ நகலெடà¯à®¤à¯à®¤à®ªà¯ படமà¯</translation>
<translation id="2354001756790975382">பிற பà¯à®•à¯à®®à®¾à®°à¯à®•à¯à®¸à¯</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">இநà¯à®¤à®¤à¯ தளதà¯à®¤à®¿à®²à¯ நீஙà¯à®•à®³à¯ பாரà¯à®¤à¯à®¤à¯à®•à¯ கொணà¯à®Ÿà®¿à®°à¯à®•à¯à®•à¯à®®à¯ படஙà¯à®•à®³à¯ˆ தீஙà¯à®•à®¿à®´à¯ˆà®ªà¯à®ªà®µà®°à¯à®•à®³à¯à®®à¯ பாரà¯à®¤à¯à®¤à¯, அவறà¯à®±à¯ˆ மாறà¯à®±à®¿à®¯à®®à¯ˆà®¤à¯à®¤à¯ உஙà¯à®•à®³à¯ˆ à®à®®à®¾à®±à¯à®±à®•à¯à®•à¯‚டà¯à®®à¯.</translation>
<translation id="2356070529366658676">கேளà¯</translation>
<translation id="2357481397660644965">உஙà¯à®•à®³à¯ சாதனதà¯à®¤à¯ˆ <ph name="DEVICE_MANAGER" /> நிரà¯à®µà®•à®¿à®•à¯à®•à®¿à®±à®¤à¯, கணகà¯à®•à¯ˆ <ph name="ACCOUNT_MANAGER" /> நிரà¯à®µà®•à®¿à®•à¯à®•à®¿à®±à®¤à¯.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ஒர௠நாளà¯à®•à¯à®•à¯à®³à¯}=1{ஒர௠நாளிலà¯}other{{NUM_DAYS} நாடà¯à®•à®³à®¿à®²à¯}}</translation>
<translation id="2359629602545592467">பல</translation>
<translation id="2359808026110333948">தொடரà¯à®•</translation>
+<translation id="2359961752320758691">உஙà¯à®•à®³à¯ விரà¯à®šà¯à®šà¯à®µà®²à¯ காரà¯à®Ÿà¯ எண௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.</translation>
<translation id="2367567093518048410">நிலை</translation>
<translation id="2372464001869762664">நீஙà¯à®•à®³à¯ உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®¯ பிறகà¯, உஙà¯à®•à®³à¯ Google கணகà¯à®•à®¿à®²à®¿à®°à¯à®•à¯à®•à¯à®®à¯ காரà¯à®Ÿà¯ விவரஙà¯à®•à®³à¯ இநà¯à®¤à®¤à¯ தளதà¯à®¤à¯à®Ÿà®©à¯ பகிரபà¯à®ªà®Ÿà¯à®®à¯. உஙà¯à®•à®³à¯ Plex கணகà¯à®•à¯ விவரஙà¯à®•à®³à®¿à®²à¯ CVCயைக௠கணà¯à®Ÿà®±à®¿à®¯à®µà¯à®®à¯.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">இநà¯à®¤ ஷிபà¯à®ªà®¿à®™à¯ à®®à¯à®±à¯ˆ இலà¯à®²à¯ˆ. வேற௠மà¯à®±à¯ˆà®¯à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®ªà¯ பாரà¯à®•à¯à®•à®µà¯à®®à¯.</translation>
<translation id="2396249848217231973">&amp;நீகà¯à®•à¯à®¤à®²à¯ˆà®šà¯ செயலà¯à®¤à®µà®¿à®°à¯</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">பழைய à®®à¯à®•à®µà®°à®¿</translation>
<translation id="2413528052993050574">இத௠<ph name="DOMAIN" /> தான௠எனà¯à®ªà®¤à¯ˆ இநà¯à®¤à®šà¯ சேவையகம௠உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà®¿à®²à¯à®²à¯ˆ; இதன௠பாதà¯à®•à®¾à®ªà¯à®ªà¯à®šà¯ சானà¯à®±à®¿à®¤à®´à¯ திரà¯à®®à¯à®ªà®ªà¯à®ªà¯†à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯. இத௠தவறான உளà¯à®³à®®à¯ˆà®µà®¾à®²à¯ à®à®±à¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯ அலà¯à®²à®¤à¯ தீஙà¯à®•à®¿à®´à¯ˆà®ªà¯à®ªà®µà®°à¯ உஙà¯à®•à®³à¯ இணைபà¯à®ªà®¿à®²à¯ கà¯à®±à¯à®•à¯à®•à®¿à®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯.</translation>
<translation id="2414886740292270097">அடரà¯</translation>
<translation id="2438874542388153331">கà¯à®µà®¾à®Ÿà¯ பஞà¯à®šà¯ ரைடà¯</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">ஸà¯à®Ÿà¯‡à®ªà¯à®ªà®¿à®²à¯ பாடà¯à®Ÿà®®à¯ ரைடà¯</translation>
<translation id="2523886232349826891">இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ மடà¯à®Ÿà¯à®®à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯</translation>
<translation id="2524461107774643265">மேலà¯à®®à¯ தகவலைச௠சேரà¯à®•à¯à®•à®µà¯à®®à¯</translation>
-<translation id="2526590354069164005">டெஸà¯à®•à¯à®Ÿà®¾à®ªà¯</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{மேலà¯à®®à¯ ஒனà¯à®±à¯}other{மேலà¯à®®à¯ #}}</translation>
<translation id="2536110899380797252">à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®šà¯ சேரà¯</translation>
<translation id="2539524384386349900">கணà¯à®Ÿà®±à®¿</translation>
+<translation id="2541219929084442027">உஙà¯à®•à®³à¯ மறைநிலைத௠தாவலà¯à®•à®³à¯ அனைதà¯à®¤à¯ˆà®¯à¯à®®à¯ மூடிய பிறக௠அவறà¯à®±à®¿à®²à¯ நீஙà¯à®•à®³à¯ பாரà¯à®¤à¯à®¤ பகà¯à®•à®™à¯à®•à®³à¯ உலாவியில௠இதà¯à®µà®°à¯ˆ பாரà¯à®¤à¯à®¤à®µà®±à¯à®±à®¿à®²à¯‹ கà¯à®•à¯à®•à¯€ சேமிபà¯à®ªà®•à®¤à¯à®¤à®¿à®²à¯‹ இதà¯à®µà®°à¯ˆ தேடியவறà¯à®±à®¿à®²à¯‹ இரà¯à®•à¯à®•à®¾à®¤à¯. நீஙà¯à®•à®³à¯ பதிவிறகà¯à®•à®¿à®¯ ஃபைலà¯à®•à®³à¯ அலà¯à®²à®¤à¯ உரà¯à®µà®¾à®•à¯à®•à®¿à®¯ பà¯à®•à¯à®®à®¾à®°à¯à®•à¯à®•à¯à®•à®³à¯ அபà¯à®ªà®Ÿà®¿à®¯à¯‡ இரà¯à®•à¯à®•à¯à®®à¯.</translation>
<translation id="2544644783021658368">à®’à®±à¯à®±à¯ˆ ஆவணமà¯</translation>
<translation id="254947805923345898">கொளà¯à®•à¯ˆà®¯à®¿à®©à¯ மதிபà¯à®ªà¯ சரியானதிலà¯à®²à¯ˆ.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> தவறான பதிலை அனà¯à®ªà¯à®ªà®¿à®¯à®¤à¯.</translation>
@@ -448,9 +461,10 @@
<translation id="2629325967560697240">Chromeமின௠அதிகபடà¯à®šà®ªà¯ பாதà¯à®•à®¾à®ªà¯à®ªà¯ˆà®ªà¯ பெற, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />மேமà¯à®ªà®Ÿà¯à®Ÿ பாதà¯à®•à®¾à®ªà¯à®ªà¯ˆ இயகà¯à®•à®µà¯à®®à¯<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> இன௠சேவையக IP à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®•à¯ கணà¯à®Ÿà®±à®¿à®¯ à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ.</translation>
<translation id="2639739919103226564">நிலை:</translation>
+<translation id="264810637653812429">இணகà¯à®•à®®à®¾à®© சாதனஙà¯à®•à®³à¯ இலà¯à®²à¯ˆ.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ உலாவல௠வரலாறà¯, கà¯à®•à¯à®•à¯€à®•à®³à¯, தறà¯à®•à®¾à®²à®¿à®•à®šà¯ சேமிபà¯à®ªà¯ மறà¯à®±à¯à®®à¯ பலவறà¯à®±à¯ˆ அழிகà¯à®• Tab விசையை à®…à®´à¯à®¤à¯à®¤à®¿à®¯ பிறக௠Enter விசையை à®…à®´à¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
-<translation id="2650446666397867134">கோபà¯à®ªà®¿à®±à¯à®•à®¾à®© அணà¯à®•à®²à¯ மறà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
+<translation id="2650446666397867134">ஃபைலà¯à®•à¯à®•à®¾à®© அணà¯à®•à®²à¯ மறà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="2653659639078652383">சமரà¯à®ªà¯à®ªà®¿</translation>
<translation id="2660779039299703961">நிகழà¯à®µà¯</translation>
<translation id="2664887757054927933">{COUNT,plural, =0{எதà¯à®µà¯à®®à®¿à®²à¯à®²à¯ˆ}=1{ஒர௠கடவà¯à®šà¯à®šà¯Šà®²à¯ (டொமைனà¯à®•à®³à¯: <ph name="DOMAIN_LIST" />)}=2{2 கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ (டொமைனà¯à®•à®³à¯: <ph name="DOMAIN_LIST" />)}other{# கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ (டொமைனà¯à®•à®³à¯: <ph name="DOMAIN_LIST" />)}}</translation>
@@ -492,6 +506,7 @@
<translation id="2799223571221894425">மீணà¯à®Ÿà¯à®®à¯ தொடஙà¯à®•à¯</translation>
<translation id="2803306138276472711">Google பாதà¯à®•à®¾à®ªà¯à®ªà¯ உலாவலானத௠சமீபதà¯à®¤à®¿à®²à¯ <ph name="SITE" /> இல௠<ph name="BEGIN_LINK" />மாலà¯à®µà¯‡à®°à¯ உளà¯à®³à®¤à¯ˆà®•à¯ கணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿à®¤à¯à®¤à®¤à¯<ph name="END_LINK" />. இயலà¯à®ªà®¾à®•à®µà¯‡ பாதà¯à®•à®¾à®ªà¯à®ªà®¾à®• இரà¯à®•à¯à®•à¯à®®à¯ இணையதளஙà¯à®•à®³à¯à®®à¯ சில சமயஙà¯à®•à®³à®¿à®²à¯ மாலà¯à®µà¯‡à®°à®¿à®©à®¾à®²à¯ பாதிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à¯à®®à¯.</translation>
<translation id="2807052079800581569">இமேஜ௠Y நிலை</translation>
+<translation id="2820957248982571256">ஸà¯à®•à¯‡à®©à¯ செயà¯à®•à®¿à®±à®¤à¯...</translation>
<translation id="2824775600643448204">à®®à¯à®•à®µà®°à®¿ மறà¯à®±à¯à®®à¯ தேடல௠படà¯à®Ÿà®¿</translation>
<translation id="2826760142808435982">இநà¯à®¤ இணைபà¯à®ªà¯ <ph name="CIPHER" /> à®à®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿ எனà¯à®•à¯à®°à®¿à®ªà¯à®Ÿà¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà¯ à®…à®™à¯à®•à¯€à®•à®°à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯, ஒர௠மà¯à®•à¯à®•à®¿à®¯ பரிமாறà¯à®± செயலà¯à®®à¯à®±à¯ˆà®¯à®¾à®• <ph name="KX" /> à®à®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®•à®¿à®±à®¤à¯.</translation>
<translation id="2835170189407361413">படிவதà¯à®¤à¯ˆ அழி</translation>
@@ -499,6 +514,8 @@
<translation id="2850739647070081192">Invite (எனà¯à®µà®²à®ªà¯)</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="2859806420264540918">கà¯à®±à¯à®•à¯à®•à®¿à®Ÿà¯à®®à¯ அலà¯à®²à®¤à¯ தவறாக வழிநடதà¯à®¤à¯à®®à¯ விளமà¯à®ªà®°à®™à¯à®•à®³à¯ˆ இநà¯à®¤à®¤à¯ தளம௠காணà¯à®ªà®¿à®•à¯à®•à®¿à®±à®¤à¯.</translation>
+<translation id="287596039013813457">ஃபà¯à®°à®£à¯à®Ÿà¯à®²à®¿</translation>
+<translation id="2876489322757410363">மூனà¯à®±à®¾à®®à¯ தரபà¯à®ªà¯ ஆபà¯à®¸à®¿à®©à¯ மூலம௠பணதà¯à®¤à¯ˆà®šà¯ செலà¯à®¤à¯à®¤, மறைநிலைப௠பயனà¯à®®à¯à®±à¯ˆà®¯à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ வெளியேறà¯à®•à®¿à®±à®¤à¯. தொடரவா?</translation>
<translation id="2878197950673342043">போஸà¯à®Ÿà®°à¯ ஃபோலà¯à®Ÿà¯</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">சாளரதà¯à®¤à¯ˆà®•à¯ காடà¯à®Ÿà¯à®®à®¿à®Ÿà®®à¯</translation>
@@ -548,7 +565,6 @@
<translation id="3060227939791841287">C9 (எனà¯à®µà®²à®ªà¯)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />. Chrome அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ பாதà¯à®•à®¾à®ªà¯à®ªà¯à®šà¯ சரிபாரà¯à®ªà¯à®ªà¯ˆ இயகà¯à®•, Tab விசையை à®…à®´à¯à®¤à¯à®¤à®¿à®µà®¿à®Ÿà¯à®Ÿà¯ Enter விசையை à®…à®´à¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
<translation id="3061707000357573562">பேடà¯à®šà¯ சேவை</translation>
-<translation id="3064966200440839136">வெளிபà¯à®ªà¯à®± ஆபà¯à®¸à®¿à®©à¯ மூலம௠பணதà¯à®¤à¯ˆ செலà¯à®¤à¯à®¤, மறைநிலையிலிரà¯à®¨à¯à®¤à¯ வெளியேறà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à¯. தொடரவா?</translation>
<translation id="306573536155379004">கேம௠தொடஙà¯à®•à®¿à®¯à®¤à¯.</translation>
<translation id="3080254622891793721">கிராஃபிகà¯</translation>
<translation id="3086579638707268289">உஙà¯à®•à®³à®¿à®©à¯ இணையச௠செயலà¯à®ªà®¾à®Ÿà¯ கணà¯à®•à®¾à®£à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯</translation>
@@ -571,7 +587,6 @@
<translation id="315504272643575312">உஙà¯à®•à®³à¯ கணகà¯à®•à¯ˆ <ph name="MANAGER" /> நிரà¯à®µà®•à®¿à®•à¯à®•à®¿à®±à®¤à¯.</translation>
<translation id="3157931365184549694">மீடà¯à®Ÿà®®à¯ˆ</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>
@@ -594,10 +609,12 @@
<translation id="3229041911291329567">உஙà¯à®•à®³à¯ சாதனம௠மறà¯à®±à¯à®®à¯ உலாவியின௠பதிபà¯à®ªà¯à®¤à¯ தகவலà¯</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> இன௠CVC எணà¯à®£à¯ˆ உளà¯à®³à®¿à®Ÿà®µà¯à®®à¯</translation>
<translation id="3234666976984236645">இநà¯à®¤à®¤à¯ தளதà¯à®¤à®¿à®©à¯ à®®à¯à®•à¯à®•à®¿à®¯ உளà¯à®³à®Ÿà®•à¯à®•à®¤à¯à®¤à¯ˆ எபà¯à®ªà¯‹à®¤à¯à®®à¯ இயகà¯à®•à®µà¯à®®à¯</translation>
+<translation id="3249845759089040423">கà¯à®°à¯‚வி</translation>
<translation id="3252266817569339921">பிரெஞà¯à®šà¯</translation>
<translation id="3266793032086590337">மதிபà¯à®ªà¯ (à®®à¯à®°à®£à¯à®ªà®¾à®Ÿà¯)</translation>
<translation id="3268451620468152448">திறநà¯à®¤ ததà¯à®¤à®²à¯à®•à®³à¯</translation>
<translation id="3270847123878663523">&amp;மறà¯à®µà®°à®¿à®šà¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ˆà®šà¯ செயலà¯à®¤à®µà®¿à®°à¯</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> இணைய விரà¯à®®à¯à®ªà¯à®•à®¿à®±à®¤à¯</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">அமைபà¯à®ªà¯à®•à®³à¯, கொளà¯à®•à¯ˆà®•à®³à¯ போனà¯à®± சில தகவலà¯à®•à®³à¯ˆ உஙà¯à®•à®³à¯ நிறà¯à®µà®©à®®à¯ <ph name="ENROLLMENT_DOMAIN" /> பினà¯à®µà®°à¯à®®à¯ இணையதளஙà¯à®•à®³à¯à®•à¯à®•à¯ அனà¯à®ªà¯à®ªà®¿à®¯à¯à®³à¯à®³à®¤à¯.</translation>
<translation id="3282497668470633863">காரà¯à®Ÿà®¿à®²à¯à®³à¯à®³ பெயரைச௠சேரà¯à®•à¯à®•à®µà¯à®®à¯</translation>
@@ -640,7 +657,7 @@
<translation id="3402261774528610252">இநà¯à®¤à®¤à¯ தளதà¯à®¤à¯ˆ à®à®±à¯à®±à¯à®µà®¤à®±à¯à®•à¯à®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿ இணைபà¯à®ªà¯ TLS 1.0 அலà¯à®²à®¤à¯ TLS 1.1 பதிபà¯à®ªà¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®¯à®¤à¯, இவை நிறà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯‹à®Ÿà¯ விரைவில௠மà¯à®Ÿà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯. à®®à¯à®Ÿà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®µà¯à®Ÿà®©à¯ பயனரà¯à®•à®³à®¾à®²à¯ இநà¯à®¤à®¤à¯ தளதà¯à®¤à¯ˆ à®à®±à¯à®± à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯. சேவையகம௠TLS 1.2 அலà¯à®²à®¤à¯ அதறà¯à®•à¯à®ªà¯ பிநà¯à®¤à¯ˆà®¯ பதிபà¯à®ªà¯ˆ இயகà¯à®• வேணà¯à®Ÿà¯à®®à¯.</translation>
<translation id="3409896703495473338">பாதà¯à®•à®¾à®ªà¯à®ªà¯ அமைபà¯à®ªà¯à®•à®³à¯ˆ நிரà¯à®µà®•à®¿à®¯à¯à®™à¯à®•à®³à¯</translation>
<translation id="3414952576877147120">அளவà¯:</translation>
-<translation id="3417660076059365994">நீஙà¯à®•à®³à¯ பதிவேறà¯à®±à¯à®®à¯/இணைகà¯à®•à¯à®®à¯ கோபà¯à®ªà¯à®•à®³à¯ Google கிளவà¯à®Ÿà¯à®•à¯à®•à¯‹ மூனà¯à®±à®¾à®®à¯ தரபà¯à®ªà®¿à®©à®°à¯à®•à¯à®•à¯‹ ஆயà¯à®µà¯à®•à¯à®•à®¾à®• அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®®à¯. எடà¯à®¤à¯à®¤à¯à®•à¯à®•à®¾à®Ÿà¯à®Ÿà®¾à®•, பாதà¯à®•à®¾à®•à¯à®• வேணà¯à®Ÿà®¿à®¯ தரவோ மாலà¯à®µà¯‡à®°à¯‹ உளà¯à®³à®¤à®¾ எனà¯à®±à¯ கணà¯à®Ÿà®±à®¿à®µà®¤à®±à¯à®•à®¾à®• அவை ஸà¯à®•à¯‡à®©à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà®²à®¾à®®à¯.</translation>
+<translation id="3417660076059365994">நீஙà¯à®•à®³à¯ பதிவேறà¯à®±à¯à®®à¯/இணைகà¯à®•à¯à®®à¯ ஃபைலà¯à®•à®³à¯ Google கிளவà¯à®Ÿà¯à®•à¯à®•à¯‹ மூனà¯à®±à®¾à®®à¯ தரபà¯à®ªà®¿à®©à®°à¯à®•à¯à®•à¯‹ ஆயà¯à®µà¯à®•à¯à®•à®¾à®• அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®®à¯. எடà¯à®¤à¯à®¤à¯à®•à¯à®•à®¾à®Ÿà¯à®Ÿà®¾à®•, பாதà¯à®•à®¾à®•à¯à®• வேணà¯à®Ÿà®¿à®¯ தரவோ மாலà¯à®µà¯‡à®°à¯‹ உளà¯à®³à®¤à®¾ எனà¯à®±à¯ கணà¯à®Ÿà®±à®¿à®µà®¤à®±à¯à®•à®¾à®• அவை ஸà¯à®•à¯‡à®©à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà®²à®¾à®®à¯.</translation>
<translation id="3422248202833853650">பிற நிரலà¯à®•à®³à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ வெளியேறி, நினைவகதà¯à®¤à¯ˆà®•à¯ காலியாகà¯à®•à®µà¯à®®à¯.</translation>
<translation id="3422472998109090673"><ph name="HOST_NAME" />à®à®¤à¯ தறà¯à®ªà¯‹à®¤à¯ அணà¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ.</translation>
<translation id="3423742043356668186">சிஸà¯à®Ÿà®®à¯ அமைதà¯à®¤à®¤à¯</translation>
@@ -650,6 +667,7 @@
<translation id="3428151540071562330">ஒனà¯à®±à¯ அலà¯à®²à®¤à¯ அதறà¯à®•à¯ மேறà¯à®ªà®Ÿà¯à®Ÿ DnsOverHttpsTemplates சேவையக டெமà¯à®ªà¯à®³à¯‡à®Ÿà¯ URIகள௠தவறாக உளà¯à®³à®©. அவை பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà®¾à®¤à¯.</translation>
<translation id="3431636764301398940">இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ காரà¯à®Ÿà¯ˆà®šà¯ சேமி</translation>
<translation id="3432601291244612633">பகà¯à®•à®¤à¯à®¤à¯ˆ மூடà¯à®•</translation>
+<translation id="3435738964857648380">பாதà¯à®•à®¾à®ªà¯à®ªà¯</translation>
<translation id="3435896845095436175">இயகà¯à®•à¯</translation>
<translation id="3438829137925142401">உஙà¯à®•à®³à¯ Google கணகà¯à®•à®¿à®²à¯ சேமிதà¯à®¤ கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯à®®à¯</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -691,7 +709,10 @@
<translation id="3584299510153766161">டூயல௠பஞà¯à®šà¯ பாடà¯à®Ÿà®®à¯</translation>
<translation id="3586931643579894722">விவரஙà¯à®•à®³à¯ˆ மறை</translation>
<translation id="3587738293690942763">நடà¯à®µà®¿à®²à¯à®³à¯à®³à®¤à¯</translation>
+<translation id="3590643883886679995">மறைநிலைப௠பயனà¯à®®à¯à®±à¯ˆà®¯à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ வெளியேறிய பிறக௠உளà¯à®¨à¯à®´à¯ˆà®µà¯à®¤à¯ தரவ௠இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.</translation>
+<translation id="359126217934908072">மாதமà¯/ஆணà¯à®Ÿà¯:</translation>
<translation id="3592413004129370115">Italian (எனà¯à®µà®²à®ªà¯)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{எபà¯à®ªà¯‹à®¤à¯ வேணà¯à®Ÿà¯à®®à®¾à®©à®¾à®²à¯à®®à¯ உஙà¯à®•à®³à¯ கà¯à®´à¯à®µà¯ˆ மீடà¯à®Ÿà®®à¯ˆà®•à¯à®•à®²à®¾à®®à¯. பà¯à®¤à®¿à®¯ கà¯à®´à¯à®µà®¿à®²à¯ சேர ஒர௠நாள௠ஆகà¯à®®à¯.}=1{எபà¯à®ªà¯‹à®¤à¯ வேணà¯à®Ÿà¯à®®à®¾à®©à®¾à®²à¯à®®à¯ உஙà¯à®•à®³à¯ கà¯à®´à¯à®µà¯ˆ மீடà¯à®Ÿà®®à¯ˆà®•à¯à®•à®²à®¾à®®à¯. பà¯à®¤à®¿à®¯ கà¯à®´à¯à®µà®¿à®²à¯ சேர ஒர௠நாள௠ஆகà¯à®®à¯.}other{எபà¯à®ªà¯‹à®¤à¯ வேணà¯à®Ÿà¯à®®à®¾à®©à®¾à®²à¯à®®à¯ உஙà¯à®•à®³à¯ கà¯à®´à¯à®µà¯ˆ மீடà¯à®Ÿà®®à¯ˆà®•à¯à®•à®²à®¾à®®à¯. பà¯à®¤à®¿à®¯ கà¯à®´à¯à®µà®¿à®²à¯ சேர {NUM_DAYS} நாடà¯à®•à®³à¯ ஆகà¯à®®à¯.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">உஙà¯à®•à®³à¯ நிரà¯à®µà®¾à®•à®¿ ஆபà¯à®¸à¯ˆà®¤à¯ தடà¯à®¤à¯à®¤à¯à®³à¯à®³à®¾à®°à¯</translation>
<translation id="3608932978122581043">உடà¯à®šà¯†à®²à¯à®¤à¯à®¤à¯à®®à¯ திசையமைபà¯à®ªà¯</translation>
@@ -700,13 +721,13 @@
<translation id="3615877443314183785">சரியான காலாவதித௠தேதியை உளà¯à®³à®¿à®Ÿà®µà¯à®®à¯</translation>
<translation id="36224234498066874">உலாவிய தரவை அழி...</translation>
<translation id="362276910939193118">à®®à¯à®´à¯ வரலாறà¯à®±à¯ˆà®¯à¯à®®à¯ காணà¯à®ªà®¿</translation>
-<translation id="3625635938337243871">மறைநிலைப௠பயனà¯à®®à¯à®±à¯ˆà®¯à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ வெளியேறிய பிறக௠உளà¯à®¨à¯à®´à¯ˆà®µà¯à®¤à¯ தரவ௠இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.</translation>
<translation id="3630155396527302611">இத௠நெடà¯à®µà¯Šà®°à¯à®•à¯à®•à¯ˆ அணà¯à®•à¯à®µà®¤à®±à¯à®•à¯ அனà¯à®®à®¤à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ நிரலாக à®à®±à¯à®•à®©à®µà¯‡ படà¯à®Ÿà®¿à®¯à®²à®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®¨à¯à®¤à®¾à®²à¯,
இதைப௠படà¯à®Ÿà®¿à®¯à®²à®¿à®²à¯ இரà¯à®¨à¯à®¤à¯ அகறà¯à®±à®¿, மீணà¯à®Ÿà¯à®®à¯ சேரà¯à®ªà¯à®ªà®¤à®±à¯à®•à¯ à®®à¯à®¯à®²à®µà¯à®®à¯.</translation>
<translation id="3630699740441428070">உஙà¯à®•à®³à¯ நெடà¯à®µà¯Šà®°à¯à®•à¯ இணைபà¯à®ªà¯ˆ இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®©à¯ நிரà¯à®µà®¾à®•à®¿à®•à®³à¯ உளà¯à®³à®®à¯ˆà®¤à¯à®¤à¯à®³à¯à®³à®©à®°à¯. இதனால௠நீஙà¯à®•à®³à¯ எநà¯à®¤ இணையதளஙà¯à®•à®³à¯à®•à¯à®•à¯à®šà¯ செலà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à¯ எனà¯à®± விவரம௠உடà¯à®ªà®Ÿ உஙà¯à®•à®³à¯ நெடà¯à®µà¯Šà®°à¯à®•à¯ டிராஃபிகà¯à®•à¯à®•à®³à¯ˆà®¯à¯à®®à¯ அவரà¯à®•à®³à®¾à®²à¯ பாரà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à¯à®®à¯.</translation>
<translation id="3631244953324577188">பயோமெடà¯à®°à®¿à®•à¯à®¸à¯</translation>
<translation id="3633738897356909127">’Chromeமைப௠பà¯à®¤à¯à®ªà¯à®ªà®¿â€™ படà¯à®Ÿà®©à¯, Chrome அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ Chromeமைப௠பà¯à®¤à¯à®ªà¯à®ªà®¿à®•à¯à®• Enter விசையை à®…à®´à¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
<translation id="3634530185120165534">தடà¯à®Ÿà¯ 5</translation>
+<translation id="3637662659967048211">Google கணகà¯à®•à®¿à®²à¯ சேமிதà¯à®¤à®²à¯</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">ஆபà¯à®¸à¯:</translation>
<translation id="3650584904733503804">சரிபாரà¯à®ªà¯à®ªà¯ வெறà¯à®±à®¿</translation>
@@ -747,6 +768,7 @@
<translation id="3781428340399460090">ஹாட௠பிஙà¯à®•à¯</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">பà¯à®³à¯‚டூத௠சாதனஙà¯à®•à®³à¯</translation>
+<translation id="3787675388804467730">விரà¯à®šà¯à®šà¯à®µà®²à¯ காரà¯à®Ÿà¯ எணà¯</translation>
<translation id="3787705759683870569">காலாவதி: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">அளவà¯: 16</translation>
<translation id="3789841737615482174">நிறà¯à®µà¯à®•</translation>
@@ -766,6 +788,7 @@
<translation id="3841184659773414994">ஃபைல௠ஹேணà¯à®Ÿà¯à®²à®°à¯à®•à®³à¯</translation>
<translation id="385051799172605136">திரà¯à®®à¯à®ªà¯</translation>
<translation id="3858027520442213535">தேதியையà¯à®®à¯ நேரதà¯à®¤à¯ˆà®¯à¯à®®à¯ பà¯à®¤à¯à®ªà¯à®ªà®¿</translation>
+<translation id="3881478300875776315">கà¯à®±à¯ˆà®µà®¾à®© வரிகளைக௠காடà¯à®Ÿà¯à®®à¯</translation>
<translation id="3884278016824448484">à®®à¯à®°à®£à¯à®ªà®¾à®Ÿà®¾à®© சாதன அடையாளஙà¯à®•à®¾à®Ÿà¯à®Ÿà®¿</translation>
<translation id="3885155851504623709">வடà¯à®Ÿà®¾à®°à®®à¯</translation>
<translation id="388632593194507180">கணà¯à®•à®¾à®£à®¿à®ªà¯à®ªà¯ கணà¯à®Ÿà®±à®¿à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
@@ -791,6 +814,7 @@
<translation id="397105322502079400">கணகà¯à®•à®¿à®Ÿà¯à®•à®¿à®±à®¤à¯...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯</translation>
<translation id="3973357910713125165">Chrome பாதà¯à®•à®¾à®ªà¯à®ªà¯à®šà¯ சரிபாரà¯à®ªà¯à®ªà¯ˆ இயகà¯à®•à¯à®®à¯ படà¯à®Ÿà®©à¯. Chrome அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ பாதà¯à®•à®¾à®ªà¯à®ªà¯à®šà¯ சரிபாரà¯à®ªà¯à®ªà¯ˆ இயகà¯à®•, Enter விசையை à®…à®´à¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
+<translation id="3986705137476756801">'உடனடி வசனமà¯' à®…à®®à¯à®šà®¤à¯à®¤à¯ˆà®¤à¯ தறà¯à®ªà¯‹à®¤à¯ˆà®•à¯à®•à¯ à®®à¯à®Ÿà®•à¯à®•à¯à®®à¯</translation>
<translation id="3987405730340719549">இநà¯à®¤ இணையதளம௠பொயà¯à®¯à®¾à®©à®¤à®¾à®•à®µà¯‹ மோசடியானதாகவோ இரà¯à®•à¯à®•à®•à¯à®•à¯‚டà¯à®®à¯ எனà¯à®±à¯ Chrome கணà¯à®Ÿà®±à®¿à®¨à¯à®¤à¯à®³à¯à®³à®¤à¯.
பிழையாக இத௠காடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯ எனà¯à®±à¯ நீஙà¯à®•à®³à¯ கரà¯à®¤à®¿à®©à®¾à®²à¯ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals எனà¯à®ªà®¤à®±à¯à®•à¯à®šà¯ செலà¯à®²à®µà¯à®®à¯.</translation>
@@ -887,13 +911,14 @@
<translation id="4275830172053184480">உஙà¯à®•à®³à¯ சாதனதà¯à®¤à¯ˆ மீணà¯à®Ÿà¯à®®à¯ தொடஙà¯à®•à®µà¯à®®à¯</translation>
<translation id="4277028893293644418">கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ மீடà¯à®Ÿà®®à¯ˆ</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{இநà¯à®¤à®•à¯ காரà¯à®Ÿà¯ உஙà¯à®•à®³à¯ Google கணகà¯à®•à®¿à®²à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯}other{இநà¯à®¤à®•à¯ காரà¯à®Ÿà¯à®•à®³à¯ உஙà¯à®•à®³à¯ Google கணகà¯à®•à®¿à®²à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®©}}</translation>
+<translation id="4287885627794386150">சோதனைகà¯à®•à¯à®¤à¯ தகà¯à®¤à®¿à®ªà¯†à®±à¯à®±à¯à®³à¯à®³à®¤à¯. ஆனால௠செயலில௠இலà¯à®²à¯ˆ</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> பகà¯à®•à®¤à¯à®¤à®¿à®©à¯ சிற௠படமà¯</translation>
<translation id="42981349822642051">விரி</translation>
<translation id="4300675098767811073">மலà¯à®Ÿà®¿à®ªà¯à®ªà®¿à®²à¯ பஞà¯à®šà¯ ரைடà¯</translation>
<translation id="4302514097724775343">விளையாட டைனோசரைத௠தடà¯à®Ÿà¯à®™à¯à®•à®³à¯</translation>
<translation id="4302965934281694568">Chou3 (எனà¯à®µà®²à®ªà¯)</translation>
-<translation id="4305666528087210886">உஙà¯à®•à®³à¯ கோபà¯à®ªà®¿à®©à¯ˆ அணà¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ</translation>
-<translation id="4305817255990598646">மாறà¯</translation>
+<translation id="4305666528087210886">உஙà¯à®•à®³à¯ ஃபைலை அணà¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ</translation>
+<translation id="4306529830550717874">à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®šà¯ சேமிகà¯à®•à®µà®¾?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">தட௠(இயலà¯à®ªà¯)</translation>
<translation id="4314815835985389558">ஒதà¯à®¤à®¿à®šà¯ˆà®µà¯ˆ நிரà¯à®µà®•à®¿à®•à¯à®•à¯à®®à¯ பகà¯à®•à®®à¯</translation>
@@ -920,6 +945,7 @@
<translation id="4377125064752653719"><ph name="DOMAIN" /> ஠அடைய à®®à¯à®¯à®±à¯à®šà®¿ செயà¯à®¤à¯€à®°à¯à®•à®³à¯. ஆனால௠சேவையகம௠வழஙà¯à®•à®¿à®¯ சானà¯à®±à®¿à®¤à®´à®¾à®©à®¤à¯ அதன௠வழஙà¯à®•à¯à®¨à®°à®¾à®²à¯ நிராகரிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯. அதாவதà¯, சேவையகம௠வழஙà¯à®•à®¿à®¯ பாதà¯à®•à®¾à®ªà¯à®ªà¯ நமà¯à®ªà®¿à®•à¯à®•à¯ˆà®šà¯à®šà®¾à®©à¯à®±à¯à®•à®³à¯ˆ நிசà¯à®šà®¯à®®à®¾à®• எகà¯à®•à®¾à®°à®£à®¤à¯à®¤à¯ˆà®•à¯à®•à¯Šà®£à¯à®Ÿà¯à®®à¯ நமà¯à®ªà®•à¯à®•à¯‚டாதà¯. போலியான ஒனà¯à®±à¯à®Ÿà®©à¯ நீஙà¯à®•à®³à¯ தகவல௠பரிமாறà¯à®±à®®à¯ செயà¯à®¤à¯à®•à¯Šà®£à¯à®Ÿà®¿à®°à¯à®•à¯à®•à®•à¯à®•à¯‚டà¯à®®à¯.</translation>
<translation id="4378154925671717803">மொபைலà¯</translation>
<translation id="4390472908992056574">பிரிமà¯</translation>
+<translation id="4406883609789734330">உடனடி வசனமà¯</translation>
<translation id="4406896451731180161">தேடல௠மà¯à®Ÿà®¿à®µà¯à®•à®³à¯</translation>
<translation id="4408413947728134509">கà¯à®•à¯à®•à¯€à®•à®³à¯ (<ph name="NUM_COOKIES" />)</translation>
<translation id="4414290883293381923">மோசடி செயà¯à®¯à¯à®®à¯ தளதà¯à®¤à®¿à®²à¯ உஙà¯à®•à®³à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ உளà¯à®³à®¿à®Ÿà¯à®Ÿà¯à®³à¯à®³à¯€à®°à¯à®•à®³à¯. இநà¯à®¤à®•à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ஆகியவறà¯à®±à¯à®•à¯à®•à¯à®®à¯ பிற தளஙà¯à®•à®³à¯à®•à¯à®•à¯à®®à¯ செனà¯à®±à¯ இதை இபà¯à®ªà¯‹à®¤à¯‡ மாறà¯à®±à¯à®®à¯à®ªà®Ÿà®¿ Chrome பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®¿à®±à®¤à¯.</translation>
@@ -932,7 +958,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">பà¯à®°à®¾à®•à¯à®¸à®¿ பயனà¯à®ªà®¾à®Ÿà¯ à®®à¯à®Ÿà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. ஆனால௠வெளிபà¯à®ªà®Ÿà¯ˆà®¯à®¾à®© பà¯à®°à®¾à®•à¯à®¸à®¿ உளà¯à®³à®®à¯ˆà®µà¯ கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯.</translation>
<translation id="4464826014807964867">உஙà¯à®•à®³à¯ நிறà¯à®µà®©à®®à¯ வழஙà¯à®•à®¿à®¯ தகவலà¯à®•à®³à¯ˆà®•à¯ கொணà¯à®Ÿ இணையதளஙà¯à®•à®³à¯</translation>
-<translation id="4466881336512663640">படிவதà¯à®¤à®¿à®²à¯ செயà¯à®¤ மாறà¯à®±à®™à¯à®•à®³à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà®¾à®¤à¯. நிசà¯à®šà®¯à®®à®¾à®•à®¤à¯ தொடர விரà¯à®®à¯à®ªà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à®¾?</translation>
<translation id="4476953670630786061">இநà¯à®¤à®ªà¯ படிவம௠பாதà¯à®•à®¾à®ªà¯à®ªà®¾à®©à®¤à®²à¯à®². ’தனà¯à®©à®¿à®°à®ªà¯à®ªà®¿â€™ à®…à®®à¯à®šà®®à¯ à®®à¯à®Ÿà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯.</translation>
<translation id="4477350412780666475">அடà¯à®¤à¯à®¤ டிராகà¯</translation>
<translation id="4482953324121162758">இநà¯à®¤à®¤à¯ தளம௠மொழிபெயரà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà®¾à®¤à¯.</translation>
@@ -966,6 +991,7 @@
<translation id="4594403342090139922">&amp;நீகà¯à®•à¯à®¤à®²à¯ˆà®šà¯ செயலà¯à®¤à®µà®¿à®°à¯</translation>
<translation id="4597348597567598915">அளவà¯: 8</translation>
<translation id="4600854749408232102">C6/C5 (எனà¯à®µà®²à®ªà¯)</translation>
+<translation id="4606870351894164739">இமà¯à®ªà¯‡à®•à¯à®Ÿà¯à®ƒà®ªà¯à®²à¯</translation>
<translation id="4628948037717959914">படமà¯</translation>
<translation id="4631649115723685955">கேஷà¯à®ªà¯‡à®•à¯ ஆஃபர௠உளà¯à®³à®¤à¯</translation>
<translation id="4636930964841734540">தகவலà¯</translation>
@@ -985,6 +1011,7 @@
<translation id="4691835149146451662">Architecture-A (எனà¯à®µà®²à®ªà¯)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">சைடà¯</translation>
+<translation id="4702656508969495934">உடனடி வசனம௠காடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯, ஃபோகஸ௠செயà¯à®¯ சாளர மாறà¯à®±à®¿à®¯à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯à®®à¯</translation>
<translation id="4708268264240856090">உஙà¯à®•à®³à¯ இணைபà¯à®ªà®¿à®²à¯ தடஙà¯à®•à®²à¯ à®à®±à¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows நெடà¯à®µà¯Šà®°à¯à®•à¯ டயகà¯à®©à®¾à®¸à¯à®Ÿà®¿à®•à¯à®¸à¯ கரà¯à®µà®¿à®¯à¯ˆ இயகà¯à®•à®µà¯à®®à¯<ph name="END_LINK" /></translation>
@@ -998,6 +1025,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> தேடல௠பரிநà¯à®¤à¯à®°à¯ˆ</translation>
<translation id="4742407542027196863">கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆ நிரà¯à®µà®•à®¿â€¦</translation>
<translation id="4744603770635761495">இயகà¯à®•à®¨à®¿à®°à®²à¯ பாதை</translation>
+<translation id="4749011317274908093">மறைநிலையில௠உளà¯à®³à¯€à®°à¯à®•à®³à¯</translation>
<translation id="4750917950439032686">உஙà¯à®•à®³à¯ தகவலை (எடà¯à®¤à¯à®¤à¯à®•à¯à®•à®¾à®Ÿà¯à®Ÿà¯: கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ அலà¯à®²à®¤à¯ கிரெடிட௠காரà¯à®Ÿà¯ எணà¯à®•à®³à¯) இநà¯à®¤à®¤à¯ தளதà¯à®¤à®¿à®±à¯à®•à¯ அனà¯à®ªà¯à®ªà¯à®®à¯ போதà¯, தனிபà¯à®ªà®Ÿà¯à®Ÿà®¤à®¾à®• இரà¯à®•à¯à®•à¯à®®à¯.</translation>
<translation id="4756388243121344051">&amp;வரலாறà¯</translation>
<translation id="4758311279753947758">தொடரà¯à®ªà¯à®¤à¯ தகவலைச௠சேரà¯</translation>
@@ -1009,7 +1037,7 @@
இவை இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ சேமிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯:
<ph name="END_BOLD" />
<ph name="BEGIN_LIST" />
- <ph name="LIST_ITEM" />இநà¯à®¤à®šà¯ சாளரதà¯à®¤à®¿à®²à¯ நீஙà¯à®•à®³à¯ பதிவிறகà¯à®•à¯à®®à¯ கோபà¯à®ªà¯à®•à®³à¯
+ <ph name="LIST_ITEM" />இநà¯à®¤à®šà¯ சாளரதà¯à®¤à®¿à®²à¯ நீஙà¯à®•à®³à¯ பதிவிறகà¯à®•à¯à®®à¯ ஃபைலà¯à®•à®³à¯
<ph name="END_LIST" /></translation>
<translation id="4771973620359291008">அறியபà¯à®ªà®Ÿà®¾à®¤ பிழை à®à®±à¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯.</translation>
<translation id="477945296921629067">{NUM_POPUPS,plural, =1{பாபà¯-அப௠தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯}other{# பாபà¯-அபà¯à®•à®³à¯ தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®©}}</translation>
@@ -1027,6 +1055,8 @@
<translation id="4813512666221746211">நெடà¯à®µà¯Šà®°à¯à®•à¯ பிழை</translation>
<translation id="4816492930507672669">பகà¯à®•à®¤à¯à®¤à®¿à®²à¯ பொரà¯à®¤à¯à®¤à¯</translation>
<translation id="4819347708020428563">இயலà¯à®ªà¯à®•à¯ காடà¯à®šà®¿à®¯à®¿à®²à¯ விரிவà¯à®°à¯ˆà®•à®³à¯ˆà®¤à¯ திரà¯à®¤à¯à®¤à®µà®¾?</translation>
+<translation id="4825507807291741242">பவரà¯à®ƒà®ªà¯à®²à¯</translation>
+<translation id="4838327282952368871">டà¯à®°à¯€à®®à®¿</translation>
<translation id="484462545196658690">தானியஙà¯à®•à¯</translation>
<translation id="4850886885716139402">காடà¯à®šà®¿</translation>
<translation id="485316830061041779">ஜெரà¯à®®à®©à¯</translation>
@@ -1086,7 +1116,7 @@
<translation id="5045550434625856497">தவறான கடவà¯à®šà¯à®šà¯Šà®²à¯</translation>
<translation id="5056549851600133418">உஙà¯à®•à®³à¯à®•à¯à®•à®¾à®© செயà¯à®¤à®¿à®•à¯ கடà¯à®Ÿà¯à®°à¯ˆà®•à®³à¯</translation>
<translation id="5061227663725596739"><ph name="LOOKALIKE_DOMAIN" />à®à®•à¯ கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à®¾?</translation>
-<translation id="5066056036849835175">பிரிணà¯à®Ÿà®¿à®™à¯ வரலாறà¯</translation>
+<translation id="5066056036849835175">இதà¯à®µà®°à¯ˆà®¯à®¾à®© பிரிணà¯à®Ÿà®¿à®™à¯ செயலà¯à®•à®³à¯</translation>
<translation id="5068524481479508725">A10</translation>
<translation id="5068778127327928576">{NUM_COOKIES,plural, =1{(ஒனà¯à®±à¯ பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®²à¯ உளà¯à®³à®¤à¯)}other{(# பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà®¿à®²à¯ உளà¯à®³à®©)}}</translation>
<translation id="5070335125961472645"><ph name="BEGIN_LINK" />பà¯à®°à®¾à®•à¯à®¸à®¿ à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®šà¯ சரிபாரà¯à®¤à¯à®¤à®²à¯<ph name="END_LINK" /></translation>
@@ -1163,6 +1193,7 @@
<translation id="5314967030527622926">பà¯à®•à¯à®²à¯†à®Ÿà¯ மேகà¯à®•à®°à¯</translation>
<translation id="5316812925700871227">கடிகார எதிரà¯à®¤à¯à®¤à®¿à®šà¯ˆà®¯à®¿à®²à¯ சà¯à®´à®±à¯à®±à¯</translation>
<translation id="5317780077021120954">சேமி</translation>
+<translation id="5321288445143113935">பெரிதாகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> இல௠<ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">தொடரà¯à®ªà¯à®¤à¯ தகவலைத௠தேரà¯à®µà¯ செயà¯</translation>
<translation id="5327248766486351172">பெயரà¯</translation>
@@ -1170,11 +1201,13 @@
<translation id="5332219387342487447">ஷிபà¯à®ªà®¿à®™à¯ à®®à¯à®±à¯ˆ</translation>
<translation id="5333022057423422993">நீஙà¯à®•à®³à¯ தறà¯à®ªà¯‹à®¤à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®¯ கடவà¯à®šà¯à®šà¯Šà®²à¯, தரவ௠மீறலà¯à®•à¯à®•à¯ உடà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ என Chrome கணà¯à®Ÿà®±à®¿à®¨à¯à®¤à¯à®³à¯à®³à®¤à¯. கணகà¯à®•à¯à®•à®³à¯ˆà®ªà¯ பாதà¯à®•à®¾à®•à¯à®•, சேமிதà¯à®¤ கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆà®šà¯ சரிபாரà¯à®•à¯à®•à®µà¯à®®à¯.</translation>
<translation id="5334013548165032829">விரிவான சிஸà¯à®Ÿà®®à¯ பதிவà¯à®•à®³à¯</translation>
+<translation id="5334145288572353250">à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®šà¯ சேமிகà¯à®•à®µà®¾?</translation>
<translation id="5340250774223869109">ஆபà¯à®¸à¯ தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯</translation>
<translation id="534295439873310000">NFC சாதனஙà¯à®•à®³à¯</translation>
<translation id="5344579389779391559">இநà¯à®¤à®ªà¯ பகà¯à®•à®®à¯ உஙà¯à®•à®³à®¿à®Ÿà®®à®¿à®°à¯à®¨à¯à®¤à¯ கடà¯à®Ÿà®£à®®à¯ வசூலிகà¯à®•à®²à®¾à®®à¯</translation>
<translation id="5355557959165512791"><ph name="SITE" /> தளதà¯à®¤à®¿à®©à¯ சானà¯à®±à®¿à®¤à®´à¯ ரதà¯à®¤à¯à®šà¯†à®¯à¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à®¾à®²à¯, தறà¯à®ªà¯‹à®¤à¯ அதைப௠பாரà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯. பொதà¯à®µà®¾à®• நெடà¯à®µà¯Šà®°à¯à®•à¯ பிழைகளà¯à®®à¯ பாதிபà¯à®ªà¯à®•à®³à¯à®®à¯ தறà¯à®•à®¾à®²à®¿à®•à®®à®¾à®©à®µà¯ˆ எனà¯à®ªà®¤à®¾à®²à¯, இநà¯à®¤à®ªà¯ பகà¯à®•à®®à¯ பினà¯à®©à®°à¯ சரியாகச௠செயலà¯à®ªà®Ÿà®•à¯à®•à¯‚டà¯à®®à¯.</translation>
<translation id="536296301121032821">கொளà¯à®•à¯ˆ அமைபà¯à®ªà¯à®•à®³à¯ˆà®šà¯ சேமிபà¯à®ªà®¤à®¿à®²à¯ தோலà¯à®µà®¿</translation>
+<translation id="5363309033720083897">உஙà¯à®•à®³à¯ நிரà¯à®µà®¾à®•à®¿ அனà¯à®®à®¤à®¿à®¤à¯à®¤à¯à®³à¯à®³ சீரியல௠போரà¯à®Ÿà¯</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="5386426401304769735">இநà¯à®¤à®šà¯ சானà¯à®±à®¿à®¤à®´à¯ சஙà¯à®•à®¿à®²à®¿à®¯à®¿à®²à¯, SHA-1à®à®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿ கையொபà¯à®ªà®®à®¿à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿ சானà¯à®±à®¿à®¤à®´à¯ உளà¯à®³à®¤à¯.</translation>
@@ -1183,6 +1216,7 @@
<translation id="5398772614898833570">விளமà¯à®ªà®°à®™à¯à®•à®³à¯ தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®©</translation>
<translation id="5400836586163650660">கிரே</translation>
<translation id="540969355065856584"><ph name="DOMAIN" /> டொமைனை, சேவையகம௠உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà®¿à®²à¯à®²à¯ˆ; அதறà¯à®•à®¾à®© காரணஙà¯à®•à®³à¯: இதன௠பாதà¯à®•à®¾à®ªà¯à®ªà¯à®šà¯ சானà¯à®±à®¿à®¤à®´à¯ தறà¯à®ªà¯‹à®¤à¯ செலà¯à®²à¯à®ªà®Ÿà®¿à®¯à®¾à®©à®¤à®²à¯à®². இத௠தவறான உளà¯à®³à®®à¯ˆà®µà®¿à®©à®¾à®²à¯ à®à®±à¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯ அலà¯à®²à®¤à¯ தீஙà¯à®•à®¿à®´à¯ˆà®ªà¯à®ªà®µà®°à¯ உஙà¯à®•à®³à¯ இணைபà¯à®ªà®¿à®²à¯ கà¯à®±à¯à®•à¯à®•à®¿à®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯.</translation>
+<translation id="541143247543991491">கிளவà¯à®Ÿà¯ (சிஸà¯à®Ÿà®®à¯-à®®à¯à®´à¯à®µà®¤à¯à®®à¯)</translation>
<translation id="541416427766103491">ஸà¯à®Ÿà¯‡à®•à¯à®•à®°à¯ 4</translation>
<translation id="5421136146218899937">உலாவிய தரவை அழி...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> உஙà¯à®•à®³à¯à®•à¯à®•à¯ அறிவிபà¯à®ªà¯à®•à®³à¯ˆ அனà¯à®ªà¯à®ª விரà¯à®®à¯à®ªà¯à®•à®¿à®±à®¤à¯</translation>
@@ -1196,6 +1230,7 @@
<translation id="5455374756549232013">தவறான கொளà¯à®•à¯ˆ நேரமà¯à®¤à¯à®¤à®¿à®°à¯ˆ</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" />}other{<ph name="CONTACT_PREVIEW" />, மேலà¯à®®à¯ <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
+<translation id="5463625433003343978">சாதனஙà¯à®•à®³à¯ˆà®¤à¯ தேடà¯à®•à®¿à®±à®¤à¯...</translation>
<translation id="5469868506864199649">இதà¯à®¤à®¾à®²à®¿à®¯à®©à¯</translation>
<translation id="5470861586879999274">&amp;மீணà¯à®Ÿà¯à®®à¯ திரà¯à®¤à¯à®¤à¯</translation>
<translation id="5478437291406423475">B6/C4 (எனà¯à®µà®²à®ªà¯)</translation>
@@ -1245,7 +1280,6 @@
<translation id="5624120631404540903">கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆ நிரà¯à®µà®•à®¿</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="563324245173044180">à®à®®à®¾à®±à¯à®±à®¤à¯à®¤à®•à¯à®• உளà¯à®³à®Ÿà®•à¯à®•à®®à¯ தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.</translation>
<translation id="5644090287519800334">சைட௠1 இமேஜ௠X ஷிஃபà¯à®Ÿà¯</translation>
@@ -1284,12 +1318,12 @@
<translation id="5785756445106461925">மேலà¯à®®à¯, பாதà¯à®•à®¾à®ªà¯à®ªà®±à¯à®± பிற ஆதாரஙà¯à®•à®³à¯ இநà¯à®¤à®ªà¯ பகà¯à®•à®¤à¯à®¤à®¿à®²à¯ உளà¯à®³à®©. இநà¯à®¤ ஆதாரஙà¯à®•à®³à¯ˆ டà¯à®°à®¾à®©à¯à®¸à®¿à®Ÿà¯à®Ÿà®¿à®²à¯ இரà¯à®•à¯à®•à¯à®®à¯à®ªà¯‹à®¤à¯à®®à¯ பிறர௠பாரà¯à®µà¯ˆà®¯à®¿à®Ÿà®²à®¾à®®à¯, மேலà¯à®®à¯ பகà¯à®•à®¤à¯à®¤à®¿à®©à¯ தோறà¯à®±à®¤à¯à®¤à¯ˆ மாறà¯à®±, தீஙà¯à®•à®¿à®´à¯ˆà®ªà¯à®ªà®µà®°à¯ அதை மாறà¯à®±à®¿à®¯à®®à¯ˆà®•à¯à®•à®²à®¾à®®à¯.</translation>
<translation id="5786044859038896871">காரà¯à®Ÿà¯ தகவலை நிரபà¯à®ª விரà¯à®®à¯à®ªà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à®¾?</translation>
<translation id="578633867165174378">நீஙà¯à®•à®³à¯ தறà¯à®ªà¯‹à®¤à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®¯ கடவà¯à®šà¯à®šà¯Šà®²à¯, தரவ௠மீறலà¯à®•à¯à®•à¯ உடà¯à®ªà®Ÿà¯à®Ÿà®¤à¯ என Chrome கணà¯à®Ÿà®±à®¿à®¨à¯à®¤à¯à®³à¯à®³à®¤à¯. இநà¯à®¤à®•à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ இபà¯à®ªà¯‹à®¤à¯‡ மாறà¯à®±à®µà¯à®®à¯.</translation>
-<translation id="5798290721819630480">மாறà¯à®±à®™à¯à®•à®³à¯ˆ நிராகரிகà¯à®•à®µà®¾?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" />஠நிரபà¯à®ª விரà¯à®®à¯à®ªà¯à®•à®¿à®±à¯€à®°à¯à®•à®³à®¾?</translation>
<translation id="5804241973901381774">அனà¯à®®à®¤à®¿à®•à®³à¯</translation>
<translation id="5804427196348435412">NFC சாதனஙà¯à®•à®³à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®µà®¤à®±à¯à®•à®¾à®© அனà¯à®®à®¤à®¿</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" />கà¯à®•à®¾à®© உஙà¯à®•à®³à¯ இணைபà¯à®ªà¯, நடைமà¯à®±à¯ˆà®¯à®¿à®²à¯ இலà¯à®²à®¾à®¤ சைபர௠சூடà¯à®Ÿà¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿ எனà¯à®•à¯à®°à®¿à®ªà¯à®Ÿà¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯.</translation>
<translation id="5813119285467412249">&amp;சேரà¯à®¤à¯à®¤à®²à¯ˆ மீணà¯à®Ÿà¯à®®à¯ செயà¯</translation>
+<translation id="5817918615728894473">இணை</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{நீஙà¯à®•à®³à¯ பணம௠செலà¯à®¤à¯à®¤à¯à®®à¯à®ªà¯‹à®¤à¯ இநà¯à®¤à®•à¯ காரà¯à®Ÿà®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ கடà¯à®Ÿà®£à®®à¯ வசூலிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯, ஆனால௠காரà¯à®Ÿà®¿à®©à¯ எண௠இநà¯à®¤à®¤à¯ தளதà¯à®¤à¯à®Ÿà®©à¯ பகிரபà¯à®ªà®Ÿà®¾à®¤à¯. கூடà¯à®¤à®²à¯ பாதà¯à®•à®¾à®ªà¯à®ªà®¿à®±à¯à®•à®¾à®•, தறà¯à®•à®¾à®²à®¿à®• CVC ஒனà¯à®±à¯ உரà¯à®µà®¾à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.}other{பணம௠செலà¯à®¤à¯à®¤à¯à®®à¯à®ªà¯‹à®¤à¯ நீஙà¯à®•à®³à¯ தேரà¯à®¨à¯à®¤à¯†à®Ÿà¯à®•à¯à®•à¯à®®à¯ காரà¯à®Ÿà®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ கடà¯à®Ÿà®£à®®à¯ வசூலிகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯, ஆனால௠காரà¯à®Ÿà®¿à®©à¯ எண௠இநà¯à®¤à®¤à¯ தளதà¯à®¤à¯à®Ÿà®©à¯ பகிரபà¯à®ªà®Ÿà®¾à®¤à¯. கூடà¯à®¤à®²à¯ பாதà¯à®•à®¾à®ªà¯à®ªà®¿à®±à¯à®•à®¾à®•, தறà¯à®•à®¾à®²à®¿à®• CVC ஒனà¯à®±à¯ உரà¯à®µà®¾à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯.}}</translation>
<translation id="5826507051599432481">பொதà¯à®µà®¾à®© பெயர௠(CN)</translation>
<translation id="5838278095973806738">தீஙà¯à®•à®¿à®´à¯ˆà®ªà¯à®ªà®µà®°à¯à®•à®³à¯ திரà¯à®Ÿà®¿à®µà®¿à®Ÿà®²à®¾à®®à¯ எனà¯à®ªà®¤à®¾à®²à¯, இநà¯à®¤à®¤à¯ தளதà¯à®¤à®¿à®²à¯ à®®à¯à®•à¯à®•à®¿à®¯à®¤à¯ தகவலை (எடà¯à®¤à¯à®¤à¯à®•à¯à®•à®¾à®Ÿà¯à®Ÿà¯: கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ அலà¯à®²à®¤à¯ கிரெடிட௠காரà¯à®Ÿà¯à®•à®³à¯) உளà¯à®³à®¿à®Ÿ வேணà¯à®Ÿà®¾à®®à¯.</translation>
@@ -1297,6 +1331,7 @@
<translation id="5855253129151731373">இநà¯à®¤à®¤à¯ தளதà¯à®¤à®¿à®©à¯ ஹோஸà¯à®Ÿà¯à®ªà¯†à®¯à®°à¯à®®à¯ <ph name="LOOKALIKE_DOMAIN" /> எனà¯à®± தளதà¯à®¤à®¿à®©à¯ பெயரà¯à®®à¯ ஒரே மாதிரியாக இரà¯à®ªà¯à®ªà®¤à¯ போல௠தெரிகிறதà¯. தீஙà¯à®•à®¿à®´à¯ˆà®ªà¯à®ªà®µà®°à¯à®•à®³à¯ சில நேரஙà¯à®•à®³à®¿à®²à¯ கணà¯à®Ÿà¯à®ªà®¿à®Ÿà®¿à®•à¯à®•à®µà¯‡ à®®à¯à®Ÿà®¿à®¯à®¾à®¤ அளவிறà¯à®•à¯ டொமைனின௠பெயரை சிறித௠மாறà¯à®±à®¿ போலியான தளஙà¯à®•à®³à¯ˆ உரà¯à®µà®¾à®•à¯à®•à¯à®µà®¾à®°à¯à®•à®³à¯.
பிழையாக இத௠காடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯ எனà¯à®±à¯ நீஙà¯à®•à®³à¯ கரà¯à®¤à®¿à®©à®¾à®²à¯ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals எனà¯à®ªà®¤à®±à¯à®•à¯à®šà¯ செலà¯à®²à®µà¯à®®à¯.</translation>
+<translation id="5860033963881614850">ஆஃபà¯</translation>
<translation id="5862579898803147654">ஸà¯à®Ÿà¯‡à®•à¯à®•à®°à¯ 8</translation>
<translation id="5863847714970149516">அடà¯à®¤à¯à®¤ பகà¯à®•à®¤à¯à®¤à®¿à®²à¯ உஙà¯à®•à®³à®¿à®Ÿà®®à®¿à®°à¯à®¨à¯à®¤à¯ கடà¯à®Ÿà®£à®®à¯ வசூலிகà¯à®•à®ªà¯à®ªà®Ÿà®²à®¾à®®à¯</translation>
<translation id="5866257070973731571">மொபைல௠எணà¯à®£à¯ˆà®šà¯ சேரà¯à®•à¯à®•à®µà¯à®®à¯</translation>
@@ -1313,6 +1348,7 @@
<translation id="5913377024445952699">ஸà¯à®•à®¿à®°à¯€à®©à¯à®·à®¾à®Ÿà¯ எடà¯à®ªà¯à®ªà®¤à¯ இடைநிறà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="59174027418879706">இயகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{ஒர௠கà¯à®•à¯à®•à¯€ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯}other{# கà¯à®•à¯à®•à¯€à®•à®³à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•à®¿à®©à¯à®±à®©}}</translation>
<translation id="5921185718311485855">இயகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯</translation>
<translation id="5921639886840618607">Google கணகà¯à®•à®¿à®²à¯ காரà¯à®Ÿà¯ˆà®šà¯ சேமிகà¯à®•à®µà®¾?</translation>
<translation id="5922853866070715753">கிடà¯à®Ÿà®¤à¯à®¤à®Ÿà¯à®Ÿ à®®à¯à®Ÿà®¿à®¨à¯à®¤à¯à®µà®¿à®Ÿà¯à®Ÿà®¤à¯</translation>
@@ -1332,6 +1368,7 @@
<translation id="5989320800837274978">பà¯à®°à®¾à®•à¯à®¸à®¿ சேவையகம௠சரிசெயà¯à®¯à®ªà¯à®ªà®Ÿà®µà¯à®®à¯ இலà¯à®²à¯ˆ .pac ஸà¯à®•à®¿à®°à®¿à®ªà¯à®Ÿà¯ URL கà¯à®±à®¿à®ªà¯à®ªà®¿à®Ÿà®ªà¯à®ªà®Ÿà®µà¯à®®à®¿à®²à¯à®²à¯ˆ.</translation>
<translation id="5992691462791905444">இனà¯à®œà®¿à®©à®¿à®¯à®°à®¿à®™à¯ Z-ஃபோலà¯à®Ÿà¯</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />'கà¯à®•à¯ <ph name="RESULT_COUNT" /> à®®à¯à®Ÿà®¿à®µà¯à®•à®³à¯ உளà¯à®³à®©</translation>
+<translation id="6006484371116297560">கிளாசிகà¯</translation>
<translation id="6008122969617370890">பினà¯à®©à¯‹à®•à¯à®•à®¿à®¯ வரிசை</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆà®šà¯ சோதிதà¯à®¤à¯à®ªà¯ பாரà¯à®•à¯à®•à®µà¯à®®à¯</translation>
@@ -1353,6 +1390,7 @@
<translation id="6045164183059402045">இமà¯à®ªà¯à®ªà¯Šà®šà®¿à®·à®©à¯ டெமà¯à®ªà¯à®³à¯‡à®Ÿà¯</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="6049004884579590341">à®®à¯à®´à¯à®¤à¯ திரையிலிரà¯à®¨à¯à®¤à¯ வெளியேற, |<ph name="ACCELERATOR" />| எனà¯à®ªà®¤à¯ˆ à®…à®´à¯à®¤à¯à®¤à®¿à®ªà¯ பிடிதà¯à®¤à®¿à®°à¯à®•à¯à®•à®µà¯à®®à¯</translation>
<translation id="6049488691372270142">பகà¯à®• டெலிவரி</translation>
<translation id="6051221802930200923"><ph name="SITE" /> தளமானத௠சரà¯à®Ÿà®¿à®ƒà®ªà®¿à®•à¯‡à®Ÿà¯ பினà¯à®©à®¿à®™à¯à®•à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®µà®¤à®¾à®²à¯, தறà¯à®ªà¯‹à®¤à¯ அதைப௠பாரà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯. பொதà¯à®µà®¾à®• நெடà¯à®µà¯Šà®°à¯à®•à¯ பிழைகளà¯à®®à¯ பாதிபà¯à®ªà¯à®•à®³à¯à®®à¯ தறà¯à®•à®¾à®²à®¿à®•à®®à®¾à®©à®µà¯ˆ எனà¯à®ªà®¤à®¾à®²à¯, இநà¯à®¤à®ªà¯ பகà¯à®•à®®à¯ பினà¯à®©à®°à¯ சரியாகச௠செயலà¯à®ªà®Ÿà®•à¯à®•à¯‚டà¯à®®à¯.</translation>
<translation id="6051898664905071243">பகà¯à®• எணà¯à®£à®¿à®•à¯à®•à¯ˆ:</translation>
@@ -1369,6 +1407,7 @@
<translation id="610911394827799129"><ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> எனà¯à®± à®®à¯à®•à®µà®°à®¿à®¯à®¿à®²à¯, உஙà¯à®•à®³à¯ Google கணகà¯à®•à®¿à®±à¯à®•à®¾à®© பிற வகை உலாவல௠வரலாறà¯à®®à¯ இரà¯à®•à¯à®•à®•à¯à®•à¯‚டà¯à®®à¯</translation>
<translation id="6116338172782435947">கிளிபà¯à®ªà¯‹à®°à¯à®Ÿà¯à®•à¯à®•à¯ நகலெடà¯à®¤à¯à®¤ உரையையà¯à®®à¯ படஙà¯à®•à®³à¯ˆà®¯à¯à®®à¯ பாரà¯à®•à¯à®• விரà¯à®®à¯à®ªà¯à®•à®¿à®±à®¤à¯</translation>
<translation id="6120179357481664955">உஙà¯à®•à®³à¯ UPI à®à®Ÿà®¿à®¯à¯ˆà®šà¯ சேமிகà¯à®•à®µà®¾?</translation>
+<translation id="6123290840358279103">விரà¯à®šà¯à®šà¯à®µà®²à¯ காரà¯à®Ÿà¯ˆà®•à¯ காடà¯à®Ÿà¯</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">கேபிளà¯à®•à®³à¯ˆà®šà¯ சரிபாரà¯à®¤à¯à®¤à¯, நீஙà¯à®•à®³à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®•à¯à®•à¯‚டிய ரூடà¯à®Ÿà®°à¯à®•à®³à¯, மோடமà¯à®•à®³à¯ அலà¯à®²à®¤à¯ பிற நெடà¯à®µà¯Šà®°à¯à®•à¯ சாதனஙà¯à®•à®³à¯ˆ மறà¯à®¤à¯Šà®Ÿà®•à¯à®•à®®à¯ செயà¯à®¯à®µà¯à®®à¯.</translation>
<translation id="614940544461990577">இவறà¯à®±à¯ˆà®šà¯ செயà¯à®¤à¯ பாரà¯à®•à¯à®•à®µà¯à®®à¯:</translation>
@@ -1404,6 +1443,7 @@
<translation id="6289939620939689042">பகà¯à®• வணà¯à®£à®®à¯</translation>
<translation id="6290238015253830360">நீஙà¯à®•à®³à¯ பரிநà¯à®¤à¯à®°à¯ˆà®¤à¯à®¤ கடà¯à®Ÿà¯à®°à¯ˆà®•à®³à¯ இஙà¯à®•à¯‡ தோனà¯à®±à¯à®®à¯</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">’Chromeமில௠Google அசிஸà¯à®Ÿà®£à¯à®Ÿà¯â€™ நிறà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯</translation>
<translation id="6305205051461490394"><ph name="URL" />஠அடையமà¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ.</translation>
<translation id="6312113039770857350">இணையபà¯à®ªà®•à¯à®•à®®à¯ கிடைகà¯à®•à®µà®¿à®²à¯à®²à¯ˆ</translation>
@@ -1429,6 +1469,7 @@
<translation id="6390200185239044127">Z-ஃபோலà¯à®Ÿà¯ ஹாஃபà¯</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> எனà¯à®± தளதà¯à®¤à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ நகலெடà¯à®¤à¯à®¤à¯ இஙà¯à®•à¯‡ ஒடà¯à®Ÿà¯à®µà®¤à¯ நிரà¯à®µà®¾à®•à®•à¯ கொளà¯à®•à¯ˆà®¯à®¿à®©à¯à®ªà®Ÿà®¿ தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯</translation>
+<translation id="6398765197997659313">à®®à¯à®´à¯à®¤à¯à®¤à®¿à®°à¯ˆà®¯à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ வெளியேறà¯</translation>
<translation id="6401136357288658127">இத௠நிறà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®Ÿ கொளà¯à®•à¯ˆ. இதறà¯à®•à¯à®ªà¯ பதிலாக <ph name="NEW_POLICY" /> கொளà¯à®•à¯ˆà®¯à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ வேணà¯à®Ÿà¯à®®à¯.</translation>
<translation id="6404511346730675251">பà¯à®•à¯à®®à®¾à®°à¯à®•à¯à®•à®³à¯ˆà®¤à¯ திரà¯à®¤à¯à®¤à¯</translation>
<translation id="6406765186087300643">C0 (எனà¯à®µà®²à®ªà¯)</translation>
@@ -1441,7 +1482,6 @@
<translation id="6428450836711225518">மொபைல௠எணà¯à®£à¯ˆà®šà¯ சரிபாரà¯à®¤à¯à®¤à®²à¯</translation>
<translation id="6433490469411711332">தொடரà¯à®ªà¯à®¤à¯ தகவலை மாறà¯à®±à¯</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> இணைகà¯à®• மறà¯à®¤à¯à®¤à®¤à¯.</translation>
-<translation id="6434309073475700221">நிராகரி</translation>
<translation id="6440503408713884761">பà¯à®±à®•à¯à®•à®£à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="6443406338865242315">நீஙà¯à®•à®³à¯ நிறà¯à®µà®¿à®¯à¯à®³à¯à®³ நீடà¯à®Ÿà®¿à®ªà¯à®ªà¯à®•à®³à¯à®®à¯ செரà¯à®•à¯à®¨à®¿à®°à®²à¯à®•à®³à¯à®®à¯</translation>
<translation id="6446163441502663861">Kahu (எனà¯à®µà®²à®ªà¯)</translation>
@@ -1484,6 +1524,7 @@
<translation id="6624427990725312378">தொடரà¯à®ªà¯à®¤à¯ தகவலà¯</translation>
<translation id="6626291197371920147">சரியான காரà¯à®Ÿà¯ எணà¯à®£à¯ˆà®šà¯ சேரà¯à®•à¯à®•à®µà¯à®®à¯</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> தேடலà¯</translation>
+<translation id="6630043285902923878">USB சாதனஙà¯à®•à®³à¯ˆà®¤à¯ தேடà¯à®•à®¿à®±à®¤à¯...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">அழி</translation>
@@ -1499,6 +1540,7 @@
<translation id="6671697161687535275">Chromium இலிரà¯à®¨à¯à®¤à¯ படிவப௠பரிநà¯à®¤à¯à®°à¯ˆà®¯à¯ˆ அகறà¯à®±à®µà®¾?</translation>
<translation id="6685834062052613830">வெளியேறி, அமைபà¯à®ªà¯ˆ à®®à¯à®Ÿà®¿à®•à¯à®•à®µà¯à®®à¯</translation>
<translation id="6687335167692595844">கோரபà¯à®ªà®Ÿà¯à®Ÿ எழà¯à®¤à¯à®¤à¯à®°à¯ அளவà¯</translation>
+<translation id="6688743156324860098">மாறà¯à®±à¯â€¦</translation>
<translation id="6689249931105087298">கறà¯à®ªà¯à®ªà¯à®ªà¯ பà¯à®³à¯à®³à®¿à®šà¯ சà¯à®°à¯à®•à¯à®•à®¤à¯à®¤à¯à®Ÿà®©à¯ சாரà¯à®ªà¯à®Ÿà¯ˆà®¯à®¤à¯</translation>
<translation id="6689271823431384964">நீஙà¯à®•à®³à¯ உளà¯à®¨à¯à®´à¯ˆà®¨à¯à®¤à¯à®³à¯à®³à®¤à®¾à®²à¯ Google கணகà¯à®•à®¿à®²à¯ உஙà¯à®•à®³à¯ காரà¯à®Ÿà¯ விவரஙà¯à®•à®³à¯ˆà®šà¯ சேமிகà¯à®•à¯à®®à¯ விரà¯à®ªà¯à®ªà®¤à¯à®¤à¯ˆ Chrome வழஙà¯à®•à¯à®•à®¿à®±à®¤à¯. இதை நீஙà¯à®•à®³à¯ அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ மாறà¯à®±à®²à®¾à®®à¯. காரà¯à®Ÿà¯ உரிமையாளரின௠பெயர௠உஙà¯à®•à®³à¯ கணகà¯à®•à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ பெறபà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯.</translation>
<translation id="6698381487523150993">உரà¯à®µà®¾à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯:</translation>
@@ -1514,6 +1556,7 @@
<translation id="6744009308914054259">இணைபà¯à®ªà¯à®•à¯à®•à®¾à®•à®•à¯ காதà¯à®¤à®¿à®°à¯à®•à¯à®•à¯à®®à¯à®ªà¯‹à®¤à¯ ​​ஆஃபà¯à®²à¯ˆà®©à¯ கடà¯à®Ÿà¯à®°à¯ˆà®•à®³à¯ˆà®ªà¯ படிகà¯à®•, ‘பதிவிறகà¯à®•à®™à¯à®•à®³à¯â€™ எனà¯à®ªà®¤à¯ˆà®ªà¯ பாரà¯à®•à¯à®•à®µà¯à®®à¯.</translation>
<translation id="6753269504797312559">கொளà¯à®•à¯ˆ மதிபà¯à®ªà¯</translation>
<translation id="6757797048963528358">உஙà¯à®•à®³à¯ சாதனம௠உறகà¯à®•à®¨à®¿à®²à¯ˆà®•à¯à®•à¯à®šà¯ செனà¯à®±à®¤à¯.</translation>
+<translation id="6767985426384634228">à®®à¯à®•à®µà®°à®¿à®¯à¯ˆ மாறà¯à®±à®µà®¾?</translation>
<translation id="6768213884286397650">Hagaki (போஸà¯à®Ÿà¯à®•à®¾à®°à¯à®Ÿà¯)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ஊதா</translation>
@@ -1536,6 +1579,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">சà¯à®²à®ªà®®à®¾à®•à®ªà¯ படிபà¯à®ªà®¤à®±à¯à®•à¯ à®à®±à¯à®±à®µà®•à¯ˆà®¯à®¿à®²à¯ Chrome இநà¯à®¤à®ªà¯ பகà¯à®•à®¤à¯à®¤à¯ˆ எளிதாகà¯à®•à®¿à®¯à¯à®³à¯à®³à®¤à¯. பாதà¯à®•à®¾à®ªà¯à®ªà®±à¯à®± இணைபà¯à®ªà®¿à®©à¯ மூலம௠அசல௠பகà¯à®•à®¤à¯à®¤à¯ˆ Chrome மீடà¯à®Ÿà¯†à®Ÿà¯à®¤à¯à®¤à®¤à¯.</translation>
<translation id="6891596781022320156">கொளà¯à®•à¯ˆà®¯à®¿à®©à¯ நிலை ஆதரிகà¯à®•à®ªà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ.</translation>
+<translation id="6895143722905299846">விரà¯à®šà¯à®šà¯à®µà®²à¯ எணà¯:</translation>
<translation id="6895330447102777224">காரà¯à®Ÿà¯ உறà¯à®¤à®¿à®šà¯†à®¯à¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="6897140037006041989">பயனர௠à®à®œà¯†à®£à¯à®Ÿà¯</translation>
<translation id="6898699227549475383">நிறà¯à®µà®©à®®à¯ (O)</translation>
@@ -1564,17 +1608,17 @@
<translation id="6975012522936652259">மோசடி செயà¯à®¯à¯à®®à¯ இணையதளதà¯à®¤à®¿à®²à¯ உஙà¯à®•à®³à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ உளà¯à®³à®¿à®Ÿà¯à®Ÿà¯à®³à¯à®³à¯€à®°à¯à®•à®³à¯. இநà¯à®¤à®•à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿ உளà¯à®¨à¯à®´à¯ˆà®¯à¯à®®à¯ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> மறà¯à®±à¯à®®à¯ பிற தளஙà¯à®•à®³à¯à®•à¯à®•à¯à®šà¯ செனà¯à®±à¯ இதை இபà¯à®ªà¯‹à®¤à¯‡ மாறà¯à®±à¯à®®à®¾à®±à¯ Chromium பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®¿à®±à®¤à¯.</translation>
<translation id="6979158407327259162">Google Drive</translation>
<translation id="6979440798594660689">à®®à¯à®Ÿà®•à¯à®•à¯ (இயலà¯à®ªà¯)</translation>
-<translation id="6979983982287291980">நீஙà¯à®•à®³à¯ பதிவிறகà¯à®•à¯à®®à¯ கோபà¯à®ªà¯à®•à®³à¯ Google கிளவà¯à®Ÿà¯à®•à¯à®•à¯‹ மூனà¯à®±à®¾à®®à¯ தரபà¯à®ªà®¿à®©à®°à¯à®•à¯à®•à¯‹ ஆயà¯à®µà¯à®•à¯à®•à®¾à®• அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®®à¯. எடà¯à®¤à¯à®¤à¯à®•à¯à®•à®¾à®Ÿà¯à®Ÿà®¾à®•, பாதà¯à®•à®¾à®•à¯à®• வேணà¯à®Ÿà®¿à®¯ தரவோ மாலà¯à®µà¯‡à®°à¯‹ உளà¯à®³à®¤à®¾ எனà¯à®±à¯ கணà¯à®Ÿà®±à®¿à®µà®¤à®±à¯à®•à®¾à®• அவை ஸà¯à®•à¯‡à®©à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà®²à®¾à®®à¯.</translation>
+<translation id="6979983982287291980">நீஙà¯à®•à®³à¯ பதிவிறகà¯à®•à¯à®®à¯ ஃபைலà¯à®•à®³à¯ Google கிளவà¯à®Ÿà¯à®•à¯à®•à¯‹ மூனà¯à®±à®¾à®®à¯ தரபà¯à®ªà®¿à®©à®°à¯à®•à¯à®•à¯‹ ஆயà¯à®µà¯à®•à¯à®•à®¾à®• அனà¯à®ªà¯à®ªà®ªà¯à®ªà®Ÿà¯à®®à¯. எடà¯à®¤à¯à®¤à¯à®•à¯à®•à®¾à®Ÿà¯à®Ÿà®¾à®•, பாதà¯à®•à®¾à®•à¯à®• வேணà¯à®Ÿà®¿à®¯ தரவோ மாலà¯à®µà¯‡à®°à¯‹ உளà¯à®³à®¤à®¾ எனà¯à®±à¯ கணà¯à®Ÿà®±à®¿à®µà®¤à®±à¯à®•à®¾à®• அவை ஸà¯à®•à¯‡à®©à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà®²à®¾à®®à¯.</translation>
<translation id="6989763994942163495">மேமà¯à®ªà®Ÿà¯à®Ÿ அமைபà¯à®ªà¯à®•à®³à¯ˆà®•à¯ காணà¯à®ªà®¿...</translation>
<translation id="6993898126790112050">6x9 (எனà¯à®µà®²à®ªà¯)</translation>
<translation id="6996312675313362352"><ph name="ORIGINAL_LANGUAGE" /> மொழியிலிரà¯à®¨à¯à®¤à¯ எபà¯à®ªà¯‹à®¤à¯à®®à¯ மொழிபெயரà¯</translation>
<translation id="7004583254764674281">காரà¯à®Ÿà¯à®•à®³à¯ˆ மேலà¯à®®à¯ விரைவாக உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤ Windows Helloவைப௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
<translation id="7006930604109697472">பரவாயிலà¯à®²à¯ˆ அனà¯à®ªà¯à®ªà¯</translation>
<translation id="7012363358306927923">சீனா UnionPay</translation>
-<translation id="7012404007611495949">அளவை மாறà¯à®±à¯à®µà®¤à®±à¯à®•à®¾à®© அமைபà¯à®ªà¯à®•à®³à¯</translation>
<translation id="7014741021609395734">ஜூம௠நிலை</translation>
<translation id="7016992613359344582">இநà¯à®¤à®•à¯ கடà¯à®Ÿà®£à®™à¯à®•à®³à¯ à®’à®°à¯à®®à¯à®±à¯ˆ அலà¯à®²à®¤à¯ தொடரà¯à®¨à¯à®¤à¯ வசூலிகà¯à®•à®ªà¯à®ªà®Ÿà®²à®¾à®®à¯, அவை வெளிபà¯à®ªà®Ÿà¯ˆà®¯à®¾à®•à®¤à¯ தெரிவிகà¯à®•à®ªà¯à®ªà®Ÿà®¾à®®à®²à¯ இரà¯à®•à¯à®•à®²à®¾à®®à¯.</translation>
<translation id="7029809446516969842">கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯</translation>
+<translation id="7030436163253143341">தவறான சானà¯à®±à®¿à®¤à®´à¯</translation>
<translation id="7031646650991750659">நீஙà¯à®•à®³à¯ நிறà¯à®µà®¿à®¯à¯à®³à¯à®³ Google Play ஆபà¯à®¸à¯</translation>
<translation id="7050187094878475250"><ph name="DOMAIN" />஠அடைய à®®à¯à®¯à®±à¯à®šà®¿à®¤à¯à®¤à¯à®³à¯à®³à¯€à®°à¯à®•à®³à¯, சேவையகம௠வழஙà¯à®•à®¿à®¯ சானà¯à®±à®¿à®¤à®´à¯ நமà¯à®ªà¯à®µà®¤à®±à¯à®•à¯ சாதà¯à®¤à®¿à®¯à®®à®±à¯à®± நீணà¯à®Ÿ செலà¯à®²à¯à®ªà®Ÿà®¿à®•à¯à®•à®¾à®²à®¤à¯à®¤à¯ˆà®•à¯ கொணà¯à®Ÿà¯à®³à¯à®³à®¤à¯.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{இநà¯à®¤à®•à¯ காரà¯à®Ÿà¯ˆ இபà¯à®ªà¯‹à®¤à¯ சேமிகà¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ}other{இநà¯à®¤à®•à¯ காரà¯à®Ÿà¯à®•à®³à¯ˆ இபà¯à®ªà¯‹à®¤à¯ சேமிகà¯à®• à®®à¯à®Ÿà®¿à®¯à®µà®¿à®²à¯à®²à¯ˆ}}</translation>
@@ -1644,12 +1688,14 @@
<translation id="7300012071106347854">அடர௠நீலமà¯</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">அதிகமானதà¯</translation>
+<translation id="7305756307268530424">மெதà¯à®µà®¾à®© வேகதà¯à®¤à®¿à®²à¯ தொடஙà¯à®•à¯</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">இணைபà¯à®ªà®¿à®±à¯à®•à®¾à®© உதவி</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" பிரிவை மறைகà¯à®•à¯à®®à¯</translation>
<translation id="733354035281974745">சாதனதà¯à®¤à®¿à®©à¯ அகக௠கணகà¯à®•à®¿à®²à¯ மீறிச௠செயலà¯à®ªà®Ÿà¯à®¤à®²à¯</translation>
<translation id="7333654844024768166">மோசடி செயà¯à®¯à¯à®®à¯ தளதà¯à®¤à®¿à®²à¯ உஙà¯à®•à®³à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ உளà¯à®³à®¿à®Ÿà¯à®Ÿà¯à®³à¯à®³à¯€à®°à¯à®•à®³à¯. இநà¯à®¤à®•à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ஆகியவறà¯à®±à¯à®•à¯à®•à¯à®®à¯ பிற தளஙà¯à®•à®³à¯à®•à¯à®•à¯à®®à¯ செனà¯à®±à¯ இதை இபà¯à®ªà¯‹à®¤à¯‡ மாறà¯à®±à¯à®®à¯à®ªà®Ÿà®¿ Chromium பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®¿à®±à®¤à¯.</translation>
<translation id="7334320624316649418">&amp;மறà¯à®µà®°à®¿à®šà¯ˆà®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à¯ˆ மீணà¯à®Ÿà¯à®®à¯ செயà¯</translation>
+<translation id="7337248890521463931">மேலà¯à®®à¯ வரிகளைக௠காடà¯à®Ÿà¯à®®à¯</translation>
<translation id="7337706099755338005">உஙà¯à®•à®³à¯ இயஙà¯à®•à¯à®¤à®³à®¤à¯à®¤à®¿à®²à¯ இலà¯à®²à¯ˆ.</translation>
<translation id="733923710415886693">சானà¯à®±à®¿à®¤à®´à¯ வெளிபà¯à®ªà®Ÿà¯ˆà®¤à¯à®¤à®©à¯à®®à¯ˆ மூலம௠சேவையகதà¯à®¤à®¿à®©à¯ சானà¯à®±à®¿à®¤à®´à¯ வெளியிடபà¯à®ªà®Ÿà®µà®¿à®²à¯à®²à¯ˆ.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1657,17 +1703,20 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">கடà¯à®Ÿà®³à¯ˆ வரி</translation>
<translation id="7359588939039777303">விளமà¯à®ªà®°à®™à¯à®•à®³à¯ தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®©.</translation>
+<translation id="7363096869660964304">இரà¯à®ªà¯à®ªà®¿à®©à¯à®®à¯ உஙà¯à®•à®³à¯ செயலà¯à®ªà®¾à®Ÿà¯à®•à®³à¯ மறைகà¯à®•à®ªà¯à®ªà®Ÿà®¾à®¤à¯. மறைநிலைப௠பயனà¯à®®à¯à®±à¯ˆà®¯à®¿à®²à¯ உலாவினாலà¯à®®à¯ அதà¯à®•à¯à®±à®¿à®¤à¯à®¤ தகவலà¯à®•à®³à¯ˆ உஙà¯à®•à®³à¯ நிறà¯à®µà®©à®®à¯, இணையச௠சேவை வழஙà¯à®•à¯à®¨à®°à¯, நீஙà¯à®•à®³à¯ பாரà¯à®µà¯ˆà®¯à®¿à®Ÿà¯à®®à¯ இணையதளம௠போனà¯à®±à®µà®±à¯à®±à®¾à®²à¯ அறிநà¯à®¤à¯à®•à¯Šà®³à¯à®³ à®®à¯à®Ÿà®¿à®¯à¯à®®à¯.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />. Chrome அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ இணைய à®®à¯à®•à®µà®°à®¿à®•à®³à¯ˆà®šà¯ சேரà¯à®•à¯à®•à®µà¯à®®à¯ நிரà¯à®µà®•à®¿à®•à¯à®•à®µà¯à®®à¯ Tab விசையை à®…à®´à¯à®¤à¯à®¤à®¿à®µà®¿à®Ÿà¯à®Ÿà¯ Enter விசையை à®…à®´à¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
<translation id="7365849542400970216">சாதனதà¯à®¤à®¿à®²à¯ நீஙà¯à®•à®³à¯ செயலில௠இரà¯à®ªà¯à®ªà®¤à¯ˆ அறிநà¯à®¤à¯à®•à¯Šà®³à¯à®³à®µà®¾?</translation>
<translation id="7372973238305370288">தேடல௠மà¯à®Ÿà®¿à®µà¯</translation>
<translation id="7374733840632556089">உஙà¯à®•à®³à®¾à®²à¯‹ வேறொரà¯à®µà®°à®¾à®²à¯‹ உஙà¯à®•à®³à¯ சாதனதà¯à®¤à®¿à®²à¯ நிறà¯à®µà®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³ சானà¯à®±à®¿à®¤à®´à¯‡ இநà¯à®¤à®šà¯ சிகà¯à®•à®²à¯à®•à¯à®•à¯à®•à¯ காரணம௠ஆகà¯à®®à¯. இத௠நெடà¯à®µà¯Šà®°à¯à®•à¯à®•à¯à®•à®³à¯ˆà®•à¯ கணà¯à®•à®¾à®£à®¿à®ªà¯à®ªà®¤à®±à¯à®•à¯à®®à¯ அவறà¯à®±à®¿à®²à¯ கà¯à®±à¯à®•à¯à®•à®¿à®Ÿà¯à®µà®¤à®±à¯à®•à¯à®®à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®®à¯ சானà¯à®±à®¿à®¤à®´à¯ ஆகà¯à®®à¯, எனவே இதை Chrome நமà¯à®ªà®µà®¿à®²à¯à®²à¯ˆ. பளà¯à®³à®¿ அலà¯à®²à®¤à¯ நிறà¯à®µà®© நெடà¯à®µà¯Šà®°à¯à®•à¯ போனà¯à®±à®¤à¯ˆà®•à¯ கணà¯à®•à®¾à®£à®¿à®•à¯à®• வேணà¯à®Ÿà®¿à®¯ நியாயமான சூழலà¯à®•à®³à¯ இரà¯à®•à¯à®•à¯à®®à¯†à®©à®¿à®©à¯à®®à¯, உஙà¯à®•à®³à®¾à®²à¯ தடà¯à®•à¯à®• à®®à¯à®Ÿà®¿à®¯à®¾à®¤à®ªà¯‹à®¤à¯à®®à¯ இத௠நிகழà¯à®•à®¿à®±à®¤à¯ எனà¯à®ªà®¤à¯ˆ நீஙà¯à®•à®³à¯ அறிய வேணà¯à®Ÿà¯à®®à¯†à®© Chrome விரà¯à®®à¯à®ªà¯à®•à®¿à®±à®¤à¯. இணையதà¯à®¤à¯ˆ அணà¯à®•à®•à¯à®•à¯‚டிய எநà¯à®¤ உலாவியà¯à®®à¯ ஆபà¯à®¸à¯à®®à¯ கணà¯à®•à®¾à®£à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà®•à¯à®•à¯‚டà¯à®®à¯.</translation>
<translation id="7375818412732305729">கோபà¯à®ªà¯ இணைகà¯à®•à®ªà¯à®ªà®Ÿà¯à®®à¯à®ªà¯‹à®¤à¯</translation>
-<translation id="7376551888419889433">பாதà¯à®•à®¾à®ªà¯à®ªà¯ தொடரà¯à®ªà®¾à®© நிகழà¯à®µà¯à®•à®³à¯ˆ Chrome Enterprise Connectors கொடியிடà¯à®®à¯à®ªà¯‹à®¤à¯ அநà¯à®¤ நிகழà¯à®µà¯à®•à®³à¯ பறà¯à®±à®¿à®¯ தரவ௠உஙà¯à®•à®³à¯ நிரà¯à®µà®¾à®•à®¿à®¯à¯à®Ÿà®©à¯ பகிரபà¯à®ªà®Ÿà¯à®®à¯. Chromeமில௠நீஙà¯à®•à®³à¯ பாரà¯à®µà¯ˆà®¯à®¿à®Ÿà¯à®®à¯ பகà¯à®•à®™à¯à®•à®³à®¿à®©à¯ URLகளà¯, கோபà¯à®ªà®¿à®©à¯ பெயரà¯à®•à®³à¯/தரவà¯à®¤à¯à®¤à®•à®µà®²à¯ மறà¯à®±à¯à®®à¯ உஙà¯à®•à®³à¯ சாதனதà¯à®¤à®¿à®²à¯à®®à¯ Chromeமிலà¯à®®à¯ உளà¯à®¨à¯à®´à¯ˆà®¯à®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ பயனரà¯à®ªà¯†à®¯à®°à¯ ஆகியவை இதில௠அடஙà¯à®•à®•à¯à®•à¯‚டà¯à®®à¯.</translation>
+<translation id="7376551888419889433">பாதà¯à®•à®¾à®ªà¯à®ªà¯ தொடரà¯à®ªà®¾à®© நிகழà¯à®µà¯à®•à®³à¯ˆ Chrome Enterprise Connectors கொடியிடà¯à®®à¯à®ªà¯‹à®¤à¯ அநà¯à®¤ நிகழà¯à®µà¯à®•à®³à¯ பறà¯à®±à®¿à®¯ தரவ௠உஙà¯à®•à®³à¯ நிரà¯à®µà®¾à®•à®¿à®¯à¯à®Ÿà®©à¯ பகிரபà¯à®ªà®Ÿà¯à®®à¯. Chromeமில௠நீஙà¯à®•à®³à¯ பாரà¯à®µà¯ˆà®¯à®¿à®Ÿà¯à®®à¯ பகà¯à®•à®™à¯à®•à®³à®¿à®©à¯ URLகளà¯, ஃபைலின௠பெயரà¯à®•à®³à¯/தரவà¯à®¤à¯à®¤à®•à®µà®²à¯ மறà¯à®±à¯à®®à¯ உஙà¯à®•à®³à¯ சாதனதà¯à®¤à®¿à®²à¯à®®à¯ Chromeமிலà¯à®®à¯ உளà¯à®¨à¯à®´à¯ˆà®¯à®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ பயனரà¯à®ªà¯†à®¯à®°à¯ ஆகியவை இதில௠அடஙà¯à®•à®•à¯à®•à¯‚டà¯à®®à¯.</translation>
<translation id="7377249249140280793"><ph name="RELATIVE_DATE" /> - <ph name="FULL_DATE" /></translation>
<translation id="7378594059915113390">மீடியா கடà¯à®Ÿà¯à®ªà¯à®ªà®¾à®Ÿà¯à®•à®³à¯</translation>
<translation id="7378627244592794276">வேணà¯à®Ÿà®¾à®®à¯</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">பொரà¯à®¨à¯à®¤à®¾à®¤à¯</translation>
<translation id="7390545607259442187">காரà¯à®Ÿà¯ˆ உறà¯à®¤à®¿à®šà¯†à®¯à¯</translation>
+<translation id="7392089738299859607">à®®à¯à®•à®µà®°à®¿à®¯à¯ˆ மாறà¯à®±à¯à®™à¯à®•à®³à¯</translation>
<translation id="7399802613464275309">பாதà¯à®•à®¾à®ªà¯à®ªà¯à®šà¯ சரிபாரà¯à®ªà¯à®ªà¯</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">உஙà¯à®•à®³à¯ <ph name="DEVICE_NAME" /> சாதனம௠நிரà¯à®µà®•à®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯</translation>
@@ -1682,6 +1731,7 @@
&lt;li&gt;உஙà¯à®•à®³à¯ கமà¯à®ªà¯à®¯à¯‚டà¯à®Ÿà®°à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ மெனà¯à®ªà¯Šà®°à¯à®³à¯ˆ நிரநà¯à®¤à®°à®®à®¾à®• அகறà¯à®±à¯à®µà®¤à¯ எபà¯à®ªà®Ÿà®¿ எனà¯à®ªà®¤à¯ˆ அறிய, &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome உதவி மையமà¯&lt;/a&gt; எனà¯à®ªà®¤à®±à¯à®•à¯à®šà¯ செலà¯à®²à®µà¯à®®à¯
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">லவà¯à®²à®¿</translation>
<translation id="7416351320495623771">கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆ நிரà¯à®µà®•à®¿â€¦</translation>
<translation id="7419106976560586862">சà¯à®¯à®µà®¿à®µà®°à®ªà¯ பாதை</translation>
<translation id="7437289804838430631">தொடரà¯à®ªà¯à®¤à¯ தகவலைச௠சேரà¯</translation>
@@ -1697,7 +1747,7 @@
<translation id="7481312909269577407">அடà¯à®¤à¯à®¤ பகà¯à®•à®®à¯</translation>
<translation id="7485870689360869515">தரவ௠எதà¯à®µà¯à®®à¯ இலà¯à®²à¯ˆ.</translation>
<translation id="7495528107193238112">இநà¯à®¤ உளà¯à®³à®Ÿà®•à¯à®•à®®à¯ தடà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà¯à®³à¯à®³à®¤à¯. இநà¯à®¤à®šà¯ சிகà¯à®•à®²à¯ˆà®šà¯ சரிசெயà¯à®¯, தளதà¯à®¤à®¿à®©à¯ உரிமையாளரைத௠தொடரà¯à®ªà¯à®•à¯Šà®³à¯à®³à®µà¯à®®à¯.</translation>
-<translation id="7498234416455752244">திரà¯à®¤à¯à®¤à¯à®µà®¤à¯ˆà®¤à¯ தொடரà¯à®•</translation>
+<translation id="7498193950643227031">அளவ௠மாறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà®¾à®²à¯ இத௠சரியாகச௠செயலà¯à®ªà®Ÿà®¾à®®à®²à¯ போககà¯à®•à¯‚டà¯à®®à¯. ஆபà¯à®¸à¯ காடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®®à¯ அளவைத௠தறà¯à®ªà¯‹à®¤à¯ <ph name="SETTINGS" /> இல௠கடà¯à®Ÿà¯à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à®²à®¾à®®à¯.</translation>
<translation id="7503664977220660814">மோசடி செயà¯à®¯à¯à®®à¯ தளதà¯à®¤à®¿à®²à¯ உஙà¯à®•à®³à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ உளà¯à®³à®¿à®Ÿà¯à®Ÿà¯à®³à¯à®³à¯€à®°à¯à®•à®³à¯. இநà¯à®¤à®•à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />மறà¯à®±à¯à®®à¯ பிற தளஙà¯à®•à®³à¯à®•à¯à®•à¯à®šà¯ செனà¯à®±à¯ à®…à®™à¯à®•à¯ சேமிதà¯à®¤à¯à®³à¯à®³ கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆà®šà¯ சரிபாரà¯à®•à¯à®•à¯à®®à¯à®ªà®Ÿà®¿ Chromium பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®¿à®±à®¤à¯.</translation>
<translation id="7508255263130623398">கிடைதà¯à®¤ பாலிசி சாதன à®à®Ÿà®¿ காலியாக உளà¯à®³à®¤à¯ அலà¯à®²à®¤à¯ தறà¯à®ªà¯‹à®¤à¯ˆà®¯ சாதன à®à®Ÿà®¿à®¯à¯à®Ÿà®©à¯ பொரà¯à®¨à¯à®¤à®µà®¿à®²à¯à®²à¯ˆ</translation>
<translation id="7508870219247277067">அவகாடோ பசà¯à®šà¯ˆ</translation>
@@ -1717,6 +1767,7 @@
<translation id="7548892272833184391">இணைபà¯à®ªà¯à®ªà¯ பிழைகளைச௠சரிசெயà¯à®¯à®µà¯à®®à¯</translation>
<translation id="7549584377607005141">சரியாக காணà¯à®ªà®¿à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®µà®¤à®±à¯à®•à¯ நீஙà¯à®•à®³à¯ à®à®±à¯à®•à®©à®µà¯‡ உளà¯à®³à®¿à®Ÿà¯à®Ÿ தரவ௠இநà¯à®¤ இணையபà¯à®ªà®•à¯à®•à®¤à¯à®¤à®¿à®±à¯à®•à¯ தேவைபà¯à®ªà®Ÿà¯à®•à®¿à®±à®¤à¯. இநà¯à®¤ தரவை நீஙà¯à®•à®³à¯ மீணà¯à®Ÿà¯à®®à¯ அனà¯à®ªà¯à®ªà®²à®¾à®®à¯, ஆனால௠அவà¯à®µà®¾à®±à¯ செயà¯à®µà®¤à®©à®¾à®²à¯ இநà¯à®¤à®ªà¯ பகà¯à®•à®®à¯ à®à®±à¯à®•à®©à®µà¯‡ செயறà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®¯ எலà¯à®²à®¾à®šà¯ செயலையà¯à®®à¯ மீணà¯à®Ÿà¯à®®à¯ செயà¯à®µà¯€à®°à¯à®•à®³à¯.</translation>
<translation id="7550637293666041147">உஙà¯à®•à®³à¯ சாதன மறà¯à®±à¯à®®à¯ Chrome பயனரà¯à®ªà¯†à®¯à®°à¯</translation>
+<translation id="755279583747225797">சோதனை செயலில௠உளà¯à®³à®¤à¯</translation>
<translation id="7552846755917812628">பினà¯à®µà®°à¯à®®à¯ உதவிக௠கà¯à®±à®¿à®ªà¯à®ªà¯à®•à®³à¯ˆà®šà¯ செயà¯à®¤à¯ பாரà¯à®•à¯à®•à®µà¯à®®à¯:</translation>
<translation id="7554475479213504905">பரவாயிலà¯à®²à¯ˆ, ரெஃபà¯à®°à¯†à®·à¯ செயà¯à®¤à¯ காடà¯à®Ÿà¯</translation>
<translation id="7554791636758816595">பà¯à®¤à®¿à®¯ தாவலà¯</translation>
@@ -1735,7 +1786,6 @@
<translation id="7610193165460212391"><ph name="VALUE" /> எனà¯à®± மதிபà¯à®ªà¯ வரமà¯à®ªà¯ˆ மீறியà¯à®³à¯à®³à®¤à¯.</translation>
<translation id="7613889955535752492">காலாவதியாவதà¯: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ உஙà¯à®•à®³à¯ கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆà®ªà¯ பாரà¯à®•à¯à®•à®µà¯à®®à¯ நிரà¯à®µà®•à®¿à®•à¯à®•à®µà¯à®®à¯ Tab விசையை à®…à®´à¯à®¤à¯à®¤à®¿à®¯ பிறக௠Enter விசையை à®…à®´à¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
-<translation id="7615602087246926389">உஙà¯à®•à®³à¯ Google கணகà¯à®•à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à®¿à®©à¯ மறà¯à®±à¯Šà®°à¯ பதிபà¯à®ªà¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿ கà¯à®±à®¿à®¯à®¾à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿ தரவ௠உஙà¯à®•à®³à®¿à®Ÿà®®à¯ à®à®±à¯à®•à®©à®µà¯‡ உளà¯à®³à®¤à¯. கீழே அதை உளà¯à®³à®¿à®Ÿà¯à®•.</translation>
<translation id="7616645509853975347">உஙà¯à®•à®³à¯ உலாவியில௠Chrome Enterprise Connectorsஸை நிரà¯à®µà®¾à®•à®¿ இயகà¯à®•à®¿à®¯à¯à®³à¯à®³à®¾à®°à¯. இநà¯à®¤à®•à¯ கனெகà¯à®Ÿà®°à¯à®•à®³à®¾à®²à¯ உஙà¯à®•à®³à®¿à®©à¯ தரவ௠சிலவறà¯à®±à¯ˆ அணà¯à®• à®®à¯à®Ÿà®¿à®¯à¯à®®à¯.</translation>
<translation id="7619838219691048931">இறà¯à®¤à®¿à®¤à¯ தாளà¯</translation>
<translation id="762844065391966283">ஒர௠நேரதà¯à®¤à®¿à®²à¯ ஒனà¯à®±à¯ மடà¯à®Ÿà¯à®®à¯</translation>
@@ -1745,7 +1795,7 @@
<translation id="7638605456503525968">சீரியல௠போரà¯à®Ÿà¯à®Ÿà¯à®•à®³à¯</translation>
<translation id="7639968568612851608">அடரà¯à®¨à¯à®¤ சாமà¯à®ªà®²à¯</translation>
<translation id="7647206758853451655">அசà¯à®šà®¿à®©à¯ தரமà¯</translation>
-<translation id="7648992873808071793">இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ கோபà¯à®ªà¯à®•à®³à¯ˆà®šà¯ சேமிகà¯à®•à¯à®®à¯</translation>
+<translation id="7648992873808071793">இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®²à¯ ஃபைலà¯à®•à®³à¯ˆà®šà¯ சேமிகà¯à®•à¯à®®à¯</translation>
<translation id="7653957176542370971">பேமெணà¯à®Ÿà¯ ஹேணà¯à®Ÿà¯à®²à®°à¯ ஷீட௠மூடியà¯à®³à¯à®³à®¤à¯</translation>
<translation id="7654909834015434372">விரிவà¯à®°à¯ˆà®•à®³à¯ˆà®¤à¯ திரà¯à®¤à¯à®¤à®¿à®©à®¾à®²à¯ இநà¯à®¤ ஆவணம௠தனத௠அசல௠நிலைகà¯à®•à¯ மாறà¯à®®à¯</translation>
<translation id="765676359832457558">மேமà¯à®ªà®Ÿà¯à®Ÿ அமைபà¯à®ªà¯à®•à®³à¯ˆ மறை...</translation>
@@ -1800,13 +1850,12 @@
<translation id="782886543891417279">நீஙà¯à®•à®³à¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®¿à®•à¯ கொணà¯à®Ÿà®¿à®°à¯à®•à¯à®•à¯à®®à¯ (<ph name="WIFI_NAME" />) வைஃபை, அதன௠உளà¯à®¨à¯à®´à¯ˆà®µà¯à®ªà¯ பகà¯à®•à®¤à¯à®¤à¯ˆ நீஙà¯à®•à®³à¯ பாரà¯à®•à¯à®•à®•à¯ கோரலாமà¯.</translation>
<translation id="7836231406687464395">Postfix (எனà¯à®µà®²à®ªà¯)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{எதà¯à®µà¯à®®à®¿à®²à¯à®²à¯ˆ}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">கோபà¯à®ªà¯ வகையà¯à®Ÿà®©à¯ தொடரà¯à®ªà¯à®Ÿà¯ˆà®¯ கோபà¯à®ªà¯à®•à®³à¯ˆà®¤à¯ திறதà¯à®¤à®²à¯.</translation>
<translation id="7862185352068345852">தளதà¯à®¤à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ வெளியேறவா?</translation>
<translation id="7865448901209910068">சிறநà¯à®¤ வேகமà¯</translation>
<translation id="7874263914261512992">மோசடி செயà¯à®¯à¯à®®à¯ தளதà¯à®¤à®¿à®²à¯ உஙà¯à®•à®³à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆ உளà¯à®³à®¿à®Ÿà¯à®Ÿà¯à®³à¯à®³à¯€à®°à¯à®•à®³à¯. இநà¯à®¤à®•à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯à®²à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> மறà¯à®±à¯à®®à¯ பிற தளஙà¯à®•à®³à¯à®•à¯à®•à¯à®šà¯ செனà¯à®±à¯ à®…à®™à¯à®•à¯ சேமிதà¯à®¤à¯à®³à¯à®³ கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆà®šà¯ சரிபாரà¯à®•à¯à®•à¯à®®à¯à®ªà®Ÿà®¿ Chrome பரிநà¯à®¤à¯à®°à¯ˆà®•à¯à®•à®¿à®±à®¤à¯.</translation>
<translation id="7878562273885520351">உஙà¯à®•à®³à¯ கடவà¯à®šà¯à®šà¯Šà®²à¯ திரà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à®²à®¾à®®à¯</translation>
+<translation id="7880146494886811634">à®®à¯à®•à®µà®°à®¿à®¯à¯ˆà®šà¯ சேமியà¯à®™à¯à®•à®³à¯</translation>
<translation id="7882421473871500483">பழà¯à®ªà¯à®ªà¯</translation>
<translation id="7887683347370398519">CVCà®à®šà¯ சோதிதà¯à®¤à¯, மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à®µà¯à®®à¯</translation>
<translation id="7887885240995164102">பிகà¯à®šà¯à®šà®°à¯-இனà¯-பிகà¯à®šà¯à®šà®°à¯ பயனà¯à®®à¯à®±à¯ˆà®•à¯à®•à¯ செலà¯</translation>
@@ -1814,6 +1863,7 @@
<translation id="7894280532028510793">எழà¯à®¤à¯à®¤à¯à®ªà¯à®ªà®¿à®´à¯ˆ இலà¯à®²à¯ˆà®¯à¯†à®©à®¿à®²à¯ <ph name="BEGIN_LINK" />நெடà¯à®µà¯Šà®°à¯à®•à¯ சரிபாரà¯à®ªà¯à®ªà¯ˆ இயகà¯à®•à®¿à®ªà¯ பாரà¯à®•à¯à®•à®µà¯à®®à¯<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (எனà¯à®µà®²à®ªà¯)</translation>
<translation id="7931318309563332511">தெரியவிலà¯à®²à¯ˆ</translation>
+<translation id="793209273132572360">à®®à¯à®•à®µà®°à®¿à®¯à¯ˆ மாறà¯à®±à®µà®¾?</translation>
<translation id="7932579305932748336">கோடà¯</translation>
<translation id="79338296614623784">சரியான ஃபோன௠எணà¯à®£à¯ˆ உளà¯à®³à®¿à®Ÿà®µà¯à®®à¯</translation>
<translation id="7934052535022478634">பேமெணà¯à®Ÿà¯ நிறைவடைநà¯à®¤à®¤à¯</translation>
@@ -1884,6 +1934,7 @@
<translation id="8175796834047840627">உஙà¯à®•à®³à¯ Google கணகà¯à®•à®¿à®²à¯ உளà¯à®¨à¯à®´à¯ˆà®¨à¯à®¤à®¿à®°à¯à®ªà¯à®ªà®¤à®¾à®²à¯ Chrome உஙà¯à®•à®³à¯ காரà¯à®Ÿà¯à®•à®³à¯ˆ இநà¯à®¤à®•à¯ கணகà¯à®•à®¿à®²à¯ சேமிபà¯à®ªà®¤à®±à¯à®•à¯à®•à¯ கோரà¯à®•à®¿à®±à®¤à¯. இதை அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ மாறà¯à®±à®²à®¾à®®à¯.</translation>
<translation id="8176440868214972690">அமைபà¯à®ªà¯à®•à®³à¯, கொளà¯à®•à¯ˆà®•à®³à¯ போனà¯à®± சில தகவலà¯à®•à®³à¯ˆ இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®©à¯ நிரà¯à®µà®¾à®•à®¿ பினà¯à®µà®°à¯à®®à¯ இணையதளஙà¯à®•à®³à¯à®•à¯à®•à¯ அனà¯à®ªà¯à®ªà®¿à®¯à¯à®³à¯à®³à®¾à®°à¯.</translation>
<translation id="8184538546369750125">à®®à¯à®´à¯à®®à¯ˆà®¯à®¾à®© இயலà¯à®ªà¯à®¨à®¿à®²à¯ˆà®¯à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯ (அனà¯à®®à®¤à®¿)</translation>
+<translation id="8193086767630290324">ரகசியமானத௠எனக௠கொடியிடபà¯à®ªà®Ÿà¯à®Ÿ தரவில௠மேறà¯à®•à¯Šà®³à¯à®³à®ªà¯à®ªà®Ÿà¯à®Ÿ செயலà¯à®•à®³à¯</translation>
<translation id="8194797478851900357">&amp;நகரà¯à®¤à¯à®¤à®²à¯ˆà®šà¯ செயலà¯à®¤à®µà®¿à®°à¯</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" à®à®Ÿà®¿à®¯à¯à®Ÿà®©à¯ கூடிய நீடà¯à®Ÿà®¿à®ªà¯à®ªà®¿à®±à¯à®•à®¾à®© தவறான பà¯à®¤à¯à®ªà¯à®ªà®¿à®ªà¯à®ªà¯ URL.</translation>
<translation id="8202097416529803614">ஆரà¯à®Ÿà®°à¯ பறà¯à®±à®¿à®¯ சà¯à®°à¯à®•à¯à®•à®µà®¿à®µà®°à®®à¯</translation>
@@ -1906,6 +1957,7 @@
<translation id="8249296373107784235">கைவிடà¯</translation>
<translation id="8249320324621329438">கடைசியாக எடà¯à®¤à¯à®¤à®¤à¯:</translation>
<translation id="8253091569723639551">பிலà¯à®²à®¿à®™à¯ à®®à¯à®•à®µà®°à®¿ தேவை</translation>
+<translation id="8257387598443225809">இநà¯à®¤ ஆபà¯à®¸à¯, மொபைலà¯à®•à¯à®•à®¾à®• வடிவமைகà¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="825929999321470778">சேமிதà¯à®¤ எலà¯à®²à®¾à®•à¯ கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆà®¯à¯à®®à¯ காடà¯à®Ÿà¯</translation>
<translation id="8261506727792406068">நீகà¯à®•à¯</translation>
<translation id="8262952874573525464">எடà¯à®œà¯ ஸà¯à®Ÿà®¿à®Ÿà¯à®šà¯ பாடà¯à®Ÿà®®à¯</translation>
@@ -2029,7 +2081,6 @@
<translation id="8719528812645237045">மலà¯à®Ÿà®¿à®ªà¯à®ªà®¿à®²à¯ பஞà¯à®šà¯ டாபà¯</translation>
<translation id="8725066075913043281">மீணà¯à®Ÿà¯à®®à¯ à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à®µà¯à®®à¯</translation>
<translation id="8726549941689275341">பகà¯à®• அளவà¯:</translation>
-<translation id="8728672262656704056">மறைநிலைகà¯à®•à¯à®šà¯ செனà¯à®±à¯à®µà®¿à®Ÿà¯à®Ÿà¯€à®°à¯à®•à®³à¯</translation>
<translation id="8730621377337864115">à®®à¯à®Ÿà®¿à®¨à¯à®¤à®¤à¯</translation>
<translation id="8731544501227493793">’கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆ நிரà¯à®µà®•à®¿â€™ படà¯à®Ÿà®©à¯, Chrome அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ கடவà¯à®šà¯à®šà¯Šà®±à¯à®•à®³à¯ˆà®ªà¯ பாரà¯à®•à¯à®•à®µà¯à®®à¯ நிரà¯à®µà®•à®¿à®•à¯à®•à®µà¯à®®à¯ Enter விசையை à®…à®´à¯à®¤à¯à®¤à¯à®™à¯à®•à®³à¯</translation>
<translation id="8734529307927223492">உஙà¯à®•à®³à¯ <ph name="DEVICE_TYPE" /> சாதனதà¯à®¤à¯ˆ <ph name="MANAGER" /> நிரà¯à®µà®•à®¿à®•à¯à®•à®¿à®±à®¤à¯</translation>
@@ -2088,7 +2139,7 @@
<translation id="8968766641738584599">காரà¯à®Ÿà¯ˆà®šà¯ சேமி</translation>
<translation id="8971063699422889582">சேவையகச௠சானà¯à®±à®¿à®¤à®´à¯ காலாவதியானதà¯.</translation>
<translation id="8975012916872825179">இதில௠ஃபோன௠எணà¯à®•à®³à¯, மினà¯à®©à®žà¯à®šà®²à¯ à®®à¯à®•à®µà®°à®¿à®•à®³à¯, ஷிபà¯à®ªà®¿à®™à¯ à®®à¯à®•à®µà®°à®¿à®•à®³à¯ போனà¯à®± தகவலà¯à®•à®³à¯ உளà¯à®³à®Ÿà®™à¯à®•à¯à®®à¯</translation>
-<translation id="8975263830901772334">நீஙà¯à®•à®³à¯ அசà¯à®šà®¿à®Ÿà¯à®®à¯ கோபà¯à®ªà¯à®•à®³à®¿à®©à¯ பெயரà¯à®•à®³à¯</translation>
+<translation id="8975263830901772334">நீஙà¯à®•à®³à¯ அசà¯à®šà®¿à®Ÿà¯à®®à¯ ஃபைலà¯à®•à®³à®¿à®©à¯ பெயரà¯à®•à®³à¯</translation>
<translation id="8978053250194585037">சமீபதà¯à®¤à®¿à®²à¯ Google பாதà¯à®•à®¾à®ªà¯à®ªà®¾à®© உலாவலானத௠<ph name="SITE" /> தளதà¯à®¤à®¿à®²à¯ <ph name="BEGIN_LINK" />ஃபிஷிஙà¯à®•à¯ˆà®•à¯ கணà¯à®Ÿà®±à®¿à®¨à¯à®¤à®¤à¯<ph name="END_LINK" />. ஃபிஷிங௠தளஙà¯à®•à®³à¯ பிற இணையதளஙà¯à®•à®³à¯ˆà®ªà¯ போல௠காணà¯à®ªà®¿à®¤à¯à®¤à¯, உஙà¯à®•à®³à¯ˆ à®à®®à®¾à®±à¯à®± à®®à¯à®¯à®±à¯à®šà®¿à®•à¯à®•à®•à¯à®•à¯‚டà¯à®®à¯.</translation>
<translation id="8983003182662520383">Google Payவைப௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®®à¯ கடà¯à®Ÿà®£ à®®à¯à®±à¯ˆà®•à®³à¯à®®à¯ à®®à¯à®•à®µà®°à®¿à®•à®³à¯à®®à¯</translation>
<translation id="8987927404178983737">மாதமà¯</translation>
@@ -2106,6 +2157,7 @@
<translation id="9020542370529661692">இநà¯à®¤à®ªà¯ பகà¯à®•à®®à¯ <ph name="TARGET_LANGUAGE" /> கà¯à®•à¯ மொழிபெயரà¯à®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(தவறானதà¯)</translation>
+<translation id="9030265603405983977">மோனோகà¯à®°à¯‹à®®à¯</translation>
<translation id="9035022520814077154">பாதà¯à®•à®¾à®ªà¯à®ªà¯à®ªà¯ பிழை</translation>
<translation id="9038649477754266430">பகà¯à®•à®™à¯à®•à®³à¯ˆ இனà¯à®©à¯à®®à¯ விரைவாக à®à®±à¯à®±, யூக சேவையைப௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®µà¯à®®à¯</translation>
<translation id="9039213469156557790">மேலà¯à®®à¯, பாதà¯à®•à®¾à®ªà¯à®ªà®±à¯à®± பிற ஆதாரஙà¯à®•à®³à¯ இநà¯à®¤à®ªà¯ பகà¯à®•à®¤à¯à®¤à®¿à®²à¯ உளà¯à®³à®©. இநà¯à®¤ ஆதாரஙà¯à®•à®³à¯ˆ டà¯à®°à®¾à®©à¯à®¸à®¿à®Ÿà¯à®Ÿà®¿à®²à¯ இரà¯à®•à¯à®•à¯à®®à¯à®ªà¯‹à®¤à¯à®®à¯ பிறர௠பாரà¯à®µà¯ˆà®¯à®¿à®Ÿà®²à®¾à®®à¯, மேலà¯à®®à¯ பகà¯à®•à®¤à¯à®¤à®¿à®©à¯ செயலà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ˆ மாறà¯à®±, தீஙà¯à®•à®¿à®´à¯ˆà®ªà¯à®ªà®µà®°à¯ அதை மாறà¯à®±à®¿à®¯à®®à¯ˆà®•à¯à®•à®²à®¾à®®à¯.</translation>
@@ -2130,6 +2182,7 @@
<translation id="91108059142052966">ரகசியமான உளà¯à®³à®Ÿà®•à¯à®•à®®à¯ காடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à®¾à®²à¯ <ph name="APPLICATION_TITLE" /> உடன௠திரையைப௠பகிரà¯à®µà®¤à¯ˆ நிரà¯à®µà®¾à®•à®•à¯ கொளà¯à®•à¯ˆ à®®à¯à®Ÿà®•à¯à®•à®¿à®¯à®¤à¯</translation>
<translation id="9114524666733003316">காரà¯à®Ÿà¯ˆ உறà¯à®¤à®¿à®šà¯†à®¯à¯à®•à®¿à®±à®¤à¯...</translation>
<translation id="9114581008513152754">இநà¯à®¤ உலாவியை ஒர௠நிறà¯à®µà®©à®®à¯‹ பிற அமைபà¯à®ªà¯‹ நிரà¯à®µà®•à®¿à®•à¯à®•à®µà®¿à®²à¯à®²à¯ˆ. இநà¯à®¤à®šà¯ சாதனதà¯à®¤à®¿à®©à¯ செயலà¯à®ªà®¾à®Ÿà¯à®•à®³à¯ˆ Chromeà®®à¯à®•à¯à®•à¯ வெளியிலிரà¯à®¨à¯à®¤à¯ நிரà¯à®µà®•à®¿à®•à¯à®•à®²à®¾à®®à¯. <ph name="BEGIN_LINK" />மேலà¯à®®à¯ அறிக<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">ஃபà¯à®°à®·à¯</translation>
<translation id="9119042192571987207">பதிவேறà¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation>
<translation id="9128016270925453879">கொளà¯à®•à¯ˆà®•à®³à¯ à®à®±à¯à®±à®ªà¯à®ªà®Ÿà¯à®Ÿà®©</translation>
<translation id="9128870381267983090">நெடà¯à®µà¯Šà®°à¯à®•à¯à®•à¯à®Ÿà®©à¯ இணையவà¯à®®à¯</translation>
@@ -2148,6 +2201,7 @@
<translation id="9170848237812810038">&amp;செயலà¯à®¤à®µà®¿à®°à¯</translation>
<translation id="9171296965991013597">ஆபà¯à®¸à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ வெளியேறவா?</translation>
<translation id="9173282814238175921">à®’à®±à¯à®±à¯ˆ ஆவணமà¯/பà¯à®¤à®¿à®¯ தாளà¯</translation>
+<translation id="9173995187295789444">பà¯à®³à¯‚டூத௠சாதனஙà¯à®•à®³à¯ˆ ஸà¯à®•à¯‡à®©à¯ செயà¯à®•à®¿à®±à®¤à¯...</translation>
<translation id="917450738466192189">சேவையகச௠சானà¯à®±à®¿à®¤à®´à¯ செலà¯à®²à¯à®ªà®Ÿà®¿à®¯à®¾à®©à®¤à®²à¯à®².</translation>
<translation id="9174917557437862841">இநà¯à®¤à®¤à¯ தாவலà¯à®•à¯à®•à¯ மாற, ’தாவலà¯â€™ மாறà¯à®± படà¯à®Ÿà®©à¯ˆà®¤à¯ தடà¯à®Ÿà®¿, ‘எணà¯à®Ÿà®°à¯â€™ படà¯à®Ÿà®©à¯ˆ à®…à®´à¯à®¤à¯à®¤à®µà¯à®®à¯</translation>
<translation id="9179703756951298733">Chrome அமைபà¯à®ªà¯à®•à®³à®¿à®²à¯ உஙà¯à®•à®³à¯ பேமெணà¯à®Ÿà¯à®•à®³à¯, கிரெடிட௠காரà¯à®Ÿà¯ கà¯à®±à®¿à®¤à¯à®¤ தகவலை நிரà¯à®µà®•à®¿à®¤à¯à®¤à®²à¯</translation>
diff --git a/chromium/components/strings/components_strings_te.xtb b/chromium/components/strings/components_strings_te.xtb
index 7651eefeea0..12f1a9254e4 100644
--- a/chromium/components/strings/components_strings_te.xtb
+++ b/chromium/components/strings/components_strings_te.xtb
@@ -17,9 +17,9 @@
<translation id="1036348656032585052">ఆఫౠచేయి</translation>
<translation id="1038106730571050514">సూచనలనౠచూపà±</translation>
<translation id="1038842779957582377">తెలియని పేరà±</translation>
-<translation id="1041998700806130099">జాబౠషీటౠసందేశం</translation>
+<translation id="1041998700806130099">జాబౠషీటౠమెసేజà±â€Œ</translation>
<translation id="1048785276086539861">మీరౠఅదనపౠగమనికలనౠఎడిటౠచేసినపà±à°ªà±à°¡à±, à°ˆ డాకà±à°¯à±à°®à±†à°‚టౠసింగిలౠపేజీ వీకà±à°·à°£à°•à± తిరిగి వసà±à°¤à±à°‚ది</translation>
-<translation id="1050038467049342496">ఇతర à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°²à°¨à± మూసివేయండి</translation>
+<translation id="1050038467049342496">ఇతర యాపà±â€Œà°²à°¨à± మూసివేయండి</translation>
<translation id="1055184225775184556">&amp;జోడించడానà±à°¨à°¿ à°°à°¦à±à°¦à± చేయి</translation>
<translation id="1056898198331236512">హెచà±à°šà°°à°¿à°•</translation>
<translation id="1058479211578257048">కారà±à°¡à±â€Œà°²à± సేవౠచేయబడà±à°¤à±à°¨à±à°¨à°¾à°¯à°¿...</translation>
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">à°Žà°‚à°šà±à°•à±à°¨à±à°¨à°Ÿà±à°²à°¯à°¿à°¤à±‡, Chrome వేగవంతమైన ఫారమౠపూరింపౠకోసం à°ˆ పరికరంలో మీ కారà±à°¡à± కాపీని నిలà±à°µ చేసà±à°¤à±à°‚ది.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> కోసం à°…à°¨à±à°®à°¤à°¿à°¨à°¿ à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿</translation>
<translation id="1113869188872983271">&amp;మళà±à°²à±€ à°•à±à°°à°®à°‚ చేయడానà±à°¨à°¿ à°°à°¦à±à°¦à± చేయి</translation>
+<translation id="1123753900084781868">à°ªà±à°°à°¸à±à°¤à±à°¤à°¾à°¨à°¿à°•à°¿ లైవౠకà±à°¯à°¾à°ªà±à°·à°¨à± à°…à°‚à°¦à±à°¬à°¾à°Ÿà±à°²à±‹ లేదà±</translation>
<translation id="1125573121925420732">వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°² యొకà±à°• à°­à°¦à±à°°à°¤à°¨à± à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేసà±à°¤à±à°¨à±à°¨à°ªà±à°ªà±à°¡à± హెచà±à°šà°°à°¿à°•à°²à± కనిపించడం సాధారణమే. ఇది à°¤à±à°µà°°à°²à±‹à°¨à±‡ మెరà±à°—à±à°ªà°°à°šà°¬à°¡à±à°¤à±à°‚ది.</translation>
<translation id="112840717907525620">విధాన కాషౠసరిపోయింది</translation>
<translation id="1130564665089811311">'పేజీని à°…à°¨à±à°µà°¦à°¿à°‚à°šà±' బటనà±, à°ˆ పేజీని Google Translateతో à°…à°¨à±à°µà°¦à°¿à°‚చేందà±à°•à± 'Enter' నొకà±à°•à°‚à°¡à°¿</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">మీ పరికరం పేరà±</translation>
<translation id="124116460088058876">మరినà±à°¨à°¿ భాషలà±</translation>
<translation id="1243027604378859286">రచయిత:</translation>
+<translation id="1246424317317450637">బోలà±à°¡à±</translation>
<translation id="1250759482327835220">తరà±à°µà°¾à°¤à°¿à°¸à°¾à°°à°¿ మరింత వేగంగా చెలà±à°²à°¿à°‚చడానికి, మీ కారà±à°¡à±, పేరౠమరియౠబిలà±à°²à°¿à°‚à°—à± à°šà°¿à°°à±à°¨à°¾à°®à°¾à°¨à± మీ Google ఖాతాకౠసేవౠచేయండి.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (సమకాలీకరించబడà±à°¡à°¾à°¯à°¿)</translation>
<translation id="1256368399071562588">&lt;p&gt;మీరౠà°à°¦à±ˆà°¨à°¾ వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°¨à± తెరవడానికి à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚చినపà±à°ªà±à°¡à±, అది తెరవబడకà±à°‚టే, à°®à±à°‚à°¦à±à°—à°¾ à°ˆ సమసà±à°¯ నివారణ à°ªà±à°°à°•à±à°°à°¿à°¯ దశలనౠఉపయోగించి à°Žà°°à±à°°à°°à±â€Œà°¨à± పరిషà±à°•à°°à°¿à°‚చడానికి à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚à°šà°‚à°¡à°¿:&lt;/p&gt;
@@ -82,7 +84,7 @@
&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="1267173982554786072"><ph name="BEGIN_BOLD" />
à°ˆ పరికరంలో సేవౠఅవà±à°µà°¨à°¿ యాకà±à°Ÿà°¿à°µà°¿à°Ÿà±€:
@@ -148,7 +150,7 @@
<translation id="1453974140256777690">మీరౠపేసà±à°Ÿà± చేసిన లేదా జోడించిన టెకà±à°¸à±à°Ÿà± Google à°•à±à°²à±Œà°¡à± లేదా థరà±à°¡à± పారà±à°Ÿà±€à°²à°•à± విశà±à°²à±‡à°·à°£ కోసం పంపబడà±à°¤à±à°‚ది. ఉదాహరణకà±, ఇది à°¸à±à°¨à±à°¨à°¿à°¤à°®à±†à±–à°¨ à°µà±à°¯à°•à±à°¤à°¿à°—à°¤ సమాచారం కోసం à°¸à±à°•à°¾à°¨à± చేయబడవచà±à°šà±.</translation>
<translation id="1455413310270022028">ఎరేజరà±</translation>
<translation id="1462245070427461050">JIS B9</translation>
-<translation id="1462951478840426066">మీ à°•à°‚à°ªà±à°¯à±‚à°Ÿà°°à±â€Œà°²à±‹à°¨à°¿ ఫాంటà±â€Œà°²à°¨à± ఉపయోగించండి, తదà±à°µà°¾à°°à°¾ మీరౠఅధిక నాణà±à°¯à°¤ à°—à°² కంటెంటà±â€Œà°¨à± à°•à±à°°à°¿à°¯à±‡à°Ÿà± చేయవచà±à°šà±</translation>
+<translation id="1462951478840426066">మీ à°•à°‚à°ªà±à°¯à±‚à°Ÿà°°à±â€Œà°²à±‹à°¨à°¿ ఫాంటà±â€Œà°²à°¨à± ఉపయోగించండి, తదà±à°µà°¾à°°à°¾ మీరౠఅధిక à°•à±à°µà°¾à°²à°¿à°Ÿà±€ à°—à°² కంటెంటà±â€Œà°¨à± à°•à±à°°à°¿à°¯à±‡à°Ÿà± చేయవచà±à°šà±</translation>
<translation id="1463543813647160932">5x7</translation>
<translation id="1467432559032391204">à°Žà°¡à°®</translation>
<translation id="1468653229182955856"><ph name="EMBEDDED_ORIGIN" /> నౠ<ph name="TOP_ORIGIN" />కౠకొనసాగేలా చేయడానికి మీకౠకావాలà±à°¸à°¿à°¨ కోడౠ<ph name="ONE_TIME_CODE" /></translation>
@@ -158,6 +160,7 @@
<translation id="1476595624592550506">మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± మారà±à°šà°‚à°¡à°¿</translation>
<translation id="1484290072879560759">à°·à°¿à°ªà±à°ªà°¿à°‚à°—à± à°šà°¿à°°à±à°¨à°¾à°®à°¾à°¨à± à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿</translation>
<translation id="1492194039220927094">విధానాలనౠపà±à°·à± చేయి:</translation>
+<translation id="1495677929897281669">తిరిగి à°Ÿà±à°¯à°¾à°¬à±â€Œà°•à± వెళà±à°²à±</translation>
<translation id="1501859676467574491">మీ Google ఖాతా à°¨à±à°‚à°¡à°¿ కారà±à°¡à±â€Œà°²à°¨à± చూపండి</translation>
<translation id="1507202001669085618">&lt;p&gt;ఆనà±â€Œà°²à±ˆà°¨à±â€Œà°•à± వెళà±à°²à°¡à°‚ కంటే à°®à±à°‚దౠసైనౠఇనౠచేయాలà±à°¸à°¿à°¨ అవసరం ఉనà±à°¨ Wi-Fi పోరà±à°Ÿà°²à±â€Œà°¨à± మీరౠఉపయోగిసà±à°¤à±à°¨à±à°¨à°Ÿà±à°²à°¯à°¿à°¤à±‡ మీకౠఈ à°Žà°°à±à°°à°°à± కనిపిసà±à°¤à±à°‚ది.&lt;/p&gt;
&lt;p&gt;à°Žà°°à±à°°à°°à±â€Œà°¨à± పరిషà±à°•à°°à°¿à°‚చడానికి, మీరౠతెరవాలనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨ పేజీలో &lt;strong&gt;కనెకà±à°Ÿà± చేయి&lt;/strong&gt;ని నొకà±à°•à°‚à°¡à°¿.&lt;/p&gt;</translation>
@@ -173,6 +176,7 @@
<translation id="1532118530259321453">à°ˆ పేజీ ఇలా చెబà±à°¤à±‹à°‚ది</translation>
<translation id="153384715582417236">ఇపà±à°ªà°Ÿà°¿à°•à°¿ ఇంతే</translation>
<translation id="1536390784834419204">పేజీని à°…à°¨à±à°µà°¾à°¦à°‚ చేయి</translation>
+<translation id="1539840569003678498">రిపోరà±à°Ÿà± పంపబడింది:</translation>
<translation id="154408704832528245">బటà±à°µà°¾à°¡à°¾ à°šà°¿à°°à±à°¨à°¾à°®à°¾à°¨à± à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿</translation>
<translation id="1549470594296187301">à°ˆ ఫీచరà±â€Œà°¨à± ఉపయోగించడానికి జావాసà±à°•à±à°°à°¿à°ªà±à°Ÿà± తపà±à°ªà°¨à°¿à°¸à°°à°¿à°—à°¾ à°ªà±à°°à°¾à°°à°‚భించాలి.</translation>
<translation id="155039086686388498">ఇంజనీరింగà±-D</translation>
@@ -215,16 +219,19 @@
<translation id="1682696192498422849">పేజీని à°…à°¡à±à°¡à°‚à°—à°¾ తిపà±à°ªà°¿ à°ªà±à°°à°¿à°‚టౠచేయి</translation>
<translation id="168693727862418163">à°ˆ పాలసీ విలà±à°µ దాని à°¸à±à°•à±€à°®à°¾à°•à± à°µà±à°¯à°¤à°¿à°°à±‡à°•à°‚à°—à°¾ వాలిడేటౠచేయడంలో విఫలమైంది, కాబటà±à°Ÿà°¿ విసà±à°®à°°à°¿à°‚చబడà±à°¤à±à°‚ది.</translation>
<translation id="168841957122794586">సరà±à°µà°°à± à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ బలహీన à°•à±à°°à°¿à°ªà±à°Ÿà±‹à°—à±à°°à°¾à°«à°¿à°•à± కీని కలిగి ఉంది.</translation>
+<translation id="1696290444144917273">వరà±à°šà±à°µà°²à± కారà±à°¡à± వివరాలనౠచూడండి</translation>
<translation id="1697532407822776718">మీరౠసిదà±à°§à°‚à°—à°¾ ఉనà±à°¨à°¾à°°à±!</translation>
<translation id="1703835215927279855">లెటరà±</translation>
<translation id="1706954506755087368">{1,plural, =1{à°ˆ సరà±à°µà°°à± ఇది <ph name="DOMAIN" /> అని నిరూపించలేకపోయింది; దీని à°­à°¦à±à°°à°¤à°¾ à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ రేపటిది కావచà±à°šà±. తపà±à°ªà±à°—à°¾ కానà±à°«à°¿à°—రౠచేసినందà±à°¨ లేదా దాడిచేసేవారౠమీ కనెకà±à°·à°¨à±â€Œà°•à± అంతరాయం కలిగించినందà±à°¨ ఇలా జరిగి ఉండవచà±à°šà±.}other{à°ˆ సరà±à°µà°°à± ఇది <ph name="DOMAIN" /> అని నిరూపించలేకపోయింది; దీని à°­à°¦à±à°°à°¤à°¾ à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ భవిషà±à°¯à°¤à±à°¤à±à°²à±‹ # రోజà±à°² తదà±à°ªà°°à°¿à°¦à°¿ కావచà±à°šà±. తపà±à°ªà±à°—à°¾ కానà±à°«à°¿à°—రౠచేసినందà±à°¨ లేదా దాడిచేసేవారౠమీ కనెకà±à°·à°¨à±â€Œà°•à± అంతరాయం కలిగించినందà±à°¨ ఇలా జరిగి ఉండవచà±à°šà±.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> <ph name="VALUE" />కౠసెటౠచేయబడనందà±à°¨ విసà±à°®à°°à°¿à°‚చబడింది.</translation>
<translation id="1712552549805331520">మీ à°¸à±à°¥à°¾à°¨à°¿à°• à°•à°‚à°ªà±à°¯à±‚à°Ÿà°°à±â€Œà°²à±‹ <ph name="URL" /> శాశà±à°µà°¤à°‚à°—à°¾ డేటానౠనిలà±à°µ చేయాలనà±à°•à±à°‚టోంది</translation>
<translation id="1713628304598226412">à°Ÿà±à°°à±‡ 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">మెయిలà±â€Œà°¬à°¾à°•à±à°¸à± 3</translation>
<translation id="1718029547804390981">పతà±à°°à°‚ అదనపౠగమనికలనౠజోడించడానికి వీలౠలేకà±à°‚à°¡à°¾ చాలా అధిక పరిమాణంలో ఉంది</translation>
<translation id="1721424275792716183">* అవసరమైన ఫీలà±à°¡à±</translation>
+<translation id="1727613060316725209">సరà±à°Ÿà°¿à°«à°¿à°•à±†à°Ÿà± చెలà±à°²à±à°¬à°¾à°Ÿà± à°…à°µà±à°¤à±à°‚ది</translation>
<translation id="1727741090716970331">చెలà±à°²à±à°¬à°¾à°Ÿà°¯à±à°¯à±‡ కారà±à°¡à± నంబరà±â€Œà°¨à± జోడించండి</translation>
<translation id="1728677426644403582">మీరౠవెబౠపేజీ యొకà±à°• మూలాధారానà±à°¨à°¿ వీకà±à°·à°¿à°¸à±à°¤à±à°¨à±à°¨à°¾à°°à±</translation>
<translation id="173080396488393970">à°ˆ రకమైన కారà±à°¡à±â€Œà°•à°¿ మదà±à°¦à°¤à± లేదà±</translation>
@@ -248,7 +255,6 @@
à°¬à±à°°à±Œà°œà°°à± పూరà±à°¤à°¿ చేయలేకపోతోంది. à°­à°¦à±à°°à°¤à°¨à±, సైటౠఇతర à°ªà±à°°à°¾à°ªà°°à±à°Ÿà±€â€Œà°²à°¨à±
కానà±à°«à°¿à°—రౠచేయడానికి సైటౠఆపరేటరà±â€Œà°²à± ఆరిజినౠపాలసీలనౠఉపయోగించవచà±à°šà±.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">దయచేసి మీ సింకà±â€Œ ర‌హ‌సà±à°¯ ప‌ద‌బంధానà±à°¨à°¿ à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేయండి.</translation>
<translation id="1787142507584202372">మీ తెరవబడిన à°Ÿà±à°¯à°¾à°¬à±â€Œà°²à± ఇకà±à°•à°¡ కనిపిసà±à°¤à°¾à°¯à°¿</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, పలౠచరà±à°¯à°²à± à°…à°‚à°¦à±à°¬à°¾à°Ÿà±à°²à±‹ ఉనà±à°¨à°¾à°¯à°¿, వాటిలో దేనిని అయినా à°Žà°‚à°šà±à°•à±‹à°µà°¡à°¾à°¨à°¿à°•à°¿ 'Tab'నౠనొకà±à°•à°‚à°¡à°¿</translation>
@@ -279,8 +285,9 @@
<translation id="1915697529809968049">CVCà°•à°¿ బదà±à°²à±à°—à°¾ Touch IDని ఉపయోగించాలా?</translation>
<translation id="1916770123977586577">à°ˆ సైటౠవిషయంలో మీరౠఅపà±â€Œà°¡à±‡à°Ÿà± చేసిన సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°¨à± వరà±à°¤à°¿à°‚పజేయడానికి, à°ˆ పేజీని మళà±à°²à±€ లోడౠచేయండి</translation>
<translation id="1919345977826869612">యాడà±à°¸à±</translation>
-<translation id="1919367280705858090">నిరà±à°¦à°¿à°·à±à°Ÿ à°Žà°°à±à°°à°°à± సందేశానికి సంబంధించిన సహాయం పొందండి</translation>
+<translation id="1919367280705858090">నిరà±à°¦à°¿à°·à±à°Ÿ à°Žà°°à±à°°à°°à± మెసేజà±â€Œà°•à± సంబంధించిన సహాయం పొందండి</translation>
<translation id="192020519938775529">{COUNT,plural, =0{à°à°®à±€ లేవà±}=1{1 సైటà±}other{# సైటà±â€Œà°²à±}}</translation>
+<translation id="1924727005275031552">కొతà±à°¤</translation>
<translation id="1945968466830820669">మీరౠమీ సంసà±à°¥ ఖాతాకౠయాకà±à°¸à±†à°¸à±â€Œà°¨à± కోలà±à°ªà±‹à°µà°šà±à°šà±. లేదా à°—à±à°°à±à°¤à°¿à°‚పౠస‌మాచారం చౌరà±à°¯à°¾à°¨à°¿à°•à°¿ à°—à±à°°à°¿à°•à°¾à°µà°šà±à°šà±. Chromium మీరౠఇపà±à°ªà±à°¡à±‡ మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± మారà±à°šà°¾à°²à±à°¸à°¿à°‚దిగా సిఫారà±à°¸à± చేసà±à°¤à±‹à°‚ది.</translation>
<translation id="1947454675006758438">à°•à±à°¡à°¿à°µà±ˆà°ªà± à°Žà°—à±à°µ భాగంలో à°¸à±à°Ÿà±‡à°ªà±à°²à±</translation>
<translation id="1958218078413065209">మీ à°…à°¤à±à°¯à°§à°¿à°• à°¸à±à°•à±‹à°°à± <ph name="SCORE" />.</translation>
@@ -303,12 +310,14 @@
<translation id="2042213636306070719">à°Ÿà±à°°à±‡ 7</translation>
<translation id="204357726431741734">మీ Google ఖాతాలో సేవౠచేయబడిన పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à°¨à± ఉపయోగించడానికి సైనౠఇనౠచేయండి</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> భాషలో ఉనà±à°¨ పేజీలౠఅనà±à°µà°¦à°¿à°‚చబడవà±.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{à°ˆ à°•à°‚à°Ÿà±à°°à±‹à°²à± ఆనà±â€Œà°²à±‹ ఉనà±à°¨à°ªà±à°ªà±à°¡à±, అలాగే యాకà±à°Ÿà°¿à°µà±â€Œà°—à°¾ ఉనà±à°¨à°ªà±à°ªà±à°¡à±, మీ ఇటీవలి à°¬à±à°°à±Œà°œà°¿à°‚గౠయాకà±à°Ÿà°¿à°µà°¿à°Ÿà±€ ఠపెదà±à°¦ à°µà±à°¯à°•à±à°¤à±à°² à°—à±à°°à±‚పౠలేదా “ఒకే రకమైన యూజరà±â€Œà°² à°—à±à°°à±‚à°ªà±"తో పోలి ఉందని Chrome నిరà±à°£à°¯à°¿à°¸à±à°¤à±à°‚ది. à°…à°¡à±à°µà°°à±à°Ÿà°¯à°¿à°œà°°à±â€Œà°²à± à°ˆ à°—à±à°°à±‚à°ªà±â€Œà°•à± యాడà±â€Œà°²à°¨à± à°Žà°‚à°šà±à°•à±‹à°µà°šà±à°šà±, అలాగే మీ à°¬à±à°°à±Œà°œà°¿à°‚గౠయాకà±à°Ÿà°¿à°µà°¿à°Ÿà±€ à°ˆ పరికరంలో à°ªà±à°°à±ˆà°µà±‡à°Ÿà±â€Œà°—à°¾ ఉంచబడà±à°¤à±à°‚ది. మీ à°—à±à°°à±‚పౠపà±à°°à°¤à°¿ రోజౠఅపà±â€Œà°¡à±‡à°Ÿà± చేయబడà±à°¤à±à°‚ది.}=1{à°ˆ à°•à°‚à°Ÿà±à°°à±‹à°²à± ఆనà±â€Œà°²à±‹ ఉనà±à°¨à°ªà±à°ªà±à°¡à±, అలాగే యాకà±à°Ÿà°¿à°µà±â€Œà°—à°¾ ఉనà±à°¨à°ªà±à°ªà±à°¡à±, మీ ఇటీవలి à°¬à±à°°à±Œà°œà°¿à°‚గౠయాకà±à°Ÿà°¿à°µà°¿à°Ÿà±€ ఠపెదà±à°¦ à°µà±à°¯à°•à±à°¤à±à°² à°—à±à°°à±‚పౠలేదా “ఒకే రకమైన యూజరà±â€Œà°² à°—à±à°°à±‚à°ªà±"తో పోలి ఉందని Chrome నిరà±à°£à°¯à°¿à°¸à±à°¤à±à°‚ది. à°…à°¡à±à°µà°°à±à°Ÿà°¯à°¿à°œà°°à±â€Œà°²à± à°ˆ à°—à±à°°à±‚à°ªà±â€Œà°•à± యాడà±â€Œà°²à°¨à± à°Žà°‚à°šà±à°•à±‹à°µà°šà±à°šà±, అలాగే మీ à°¬à±à°°à±Œà°œà°¿à°‚గౠయాకà±à°Ÿà°¿à°µà°¿à°Ÿà±€ à°ˆ పరికరంలో à°ªà±à°°à±ˆà°µà±‡à°Ÿà±â€Œà°—à°¾ ఉంచబడà±à°¤à±à°‚ది. మీ à°—à±à°°à±‚పౠపà±à°°à°¤à°¿ రోజౠఅపà±â€Œà°¡à±‡à°Ÿà± చేయబడà±à°¤à±à°‚ది.}other{à°ˆ à°•à°‚à°Ÿà±à°°à±‹à°²à± ఆనà±â€Œà°²à±‹ ఉనà±à°¨à°ªà±à°ªà±à°¡à±, అలాగే యాకà±à°Ÿà°¿à°µà±â€Œà°—à°¾ ఉనà±à°¨à°ªà±à°ªà±à°¡à±, మీ ఇటీవలి à°¬à±à°°à±Œà°œà°¿à°‚గౠయాకà±à°Ÿà°¿à°µà°¿à°Ÿà±€ ఠపెదà±à°¦ à°µà±à°¯à°•à±à°¤à±à°² à°—à±à°°à±‚పౠలేదా “ఒకే రకమైన యూజరà±â€Œà°² à°—à±à°°à±‚à°ªà±"తో పోలి ఉందని Chrome నిరà±à°£à°¯à°¿à°¸à±à°¤à±à°‚ది. à°…à°¡à±à°µà°°à±à°Ÿà°¯à°¿à°œà°°à±â€Œà°²à± à°ˆ à°—à±à°°à±‚à°ªà±â€Œà°•à± యాడà±â€Œà°²à°¨à± à°Žà°‚à°šà±à°•à±‹à°µà°šà±à°šà±, అలాగే మీ à°¬à±à°°à±Œà°œà°¿à°‚గౠయాకà±à°Ÿà°¿à°µà°¿à°Ÿà±€ à°ˆ పరికరంలో à°ªà±à°°à±ˆà°µà±‡à°Ÿà±â€Œà°—à°¾ ఉంచబడà±à°¤à±à°‚ది. మీ à°—à±à°°à±‚పౠపà±à°°à°¤à°¿ {NUM_DAYS} రోజà±à°²à°•à± à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేయబడà±à°¤à±à°‚ది.}}</translation>
<translation id="2053553514270667976">జిపౠకోడà±</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 సూచన}other{# సూచనలà±}}</translation>
<translation id="2071692954027939183">మీరౠసాధారణంగా వాటిని à°…à°¨à±à°®à°¤à°¿à°‚చనందà±à°¨ నోటిఫికేషనà±â€Œà°²à± ఆటోమేటికà±â€Œà°—à°¾ à°¬à±à°²à°¾à°•à± చేయబడà±à°¡à°¾à°¯à°¿</translation>
<translation id="2079545284768500474">à°šà°°à±à°¯ à°°à°¦à±à°¦à±</translation>
<translation id="20817612488360358">సిసà±à°Ÿà°®à± à°ªà±à°°à°¾à°•à±à°¸à±€ సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à± ఉపయోగించడానికి సెటౠచేయబడà±à°¡à°¾à°¯à°¿ కానీ à°¸à±à°ªà°·à±à°Ÿà°®à±ˆà°¨ à°ªà±à°°à°¾à°•à±à°¸à±€ కానà±à°«à°¿à°—రేషనౠకూడా పేరà±à°•à±Šà°¨à°¬à°¡à°¿à°‚ది.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" />లో <ph name="RESULT_NUMBER" />వ ఫలితం</translation>
+<translation id="2085876078937250610">సేవౠచేయి…</translation>
<translation id="2088086323192747268">'సింకà±â€Œà°¨à± మేనేజౠచేయి' బటనà±, Chrome సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹ మీరౠఠసమాచారానà±à°¨à°¿ సింకౠచేయాలనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à±‹ మేనేజౠచేయడానికి 'Enter'నౠనొకà±à°•à°‚à°¡à°¿</translation>
<translation id="2091887806945687916">à°§à±à°µà°¨à°¿</translation>
<translation id="2094505752054353250">డొమైనౠసరిపోలలేదà±</translation>
@@ -330,12 +339,12 @@
<translation id="2129079103035905234">మోషనౠసెనà±à°¸à°¾à°°à±â€Œà°²à±</translation>
<translation id="2130448033692577677">DnsOverHttpsMode విధానానà±à°¨à°¿ సెటౠచేయని కారణంగా, మీరౠపేరà±à°•à±Šà°¨à±à°¨ టెంపà±à°²à±‡à°Ÿà±â€Œà°²à°¨à± వరà±à°¤à°¿à°‚పజేయడం వీలà±à°•à°¾à°•à°ªà±‹à°µà°šà±à°šà±.</translation>
<translation id="213826338245044447">మొబైలౠబà±à°•à±â€Œà°®à°¾à°°à±à°•à±â€Œà°²à±</translation>
-<translation id="214556005048008348">చెలà±à°²à°¿à°‚à°ªà±à°¨à± à°°à°¦à±à°¦à± చేయి</translation>
+<translation id="214556005048008348">పేమెంటà±â€Œà°¨à± à°°à°¦à±à°¦à± చేయి</translation>
<translation id="2147827593068025794">à°¬à±à°¯à°¾à°•à±â€Œà°—à±à°°à±Œà°‚డౠసింకà±</translation>
<translation id="2148613324460538318">కారà±à°¡à±â€Œà°¨à°¿ జోడించà±</translation>
<translation id="2149968176347646218">కనెకà±à°·à°¨à± à°¸à±à°°à°•à±à°·à°¿à°¤à°‚à°—à°¾ లేదà±</translation>
<translation id="2154054054215849342">సింకà±â€Œ మీ డొమైనà±â€Œà°•à± à°…à°‚à°¦à±à°¬à°¾à°Ÿà±à°²à±‹ లేదà±</translation>
-<translation id="2154484045852737596">కారà±à°¡à±â€Œà°¨à± సవరించండి</translation>
+<translation id="2154484045852737596">కారà±à°¡à±â€Œà°¨à± ఎడిటౠచేయండి</translation>
<translation id="2161656808144014275">వచనం</translation>
<translation id="2164510882479075877"><ph name="HOST_NAME" />లో à°…à°•à±à°·à°° దోషం ఉందేమో చెకౠచేయండి.</translation>
<translation id="2166049586286450108">పూరà±à°¤à°¿ నిరà±à°µà°¾à°¹à°• యాకà±à°¸à±†à°¸à±</translation>
@@ -381,6 +390,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" />కౠవినియోగదారౠపేరౠమరియౠపాసà±â€Œà°µà°°à±à°¡à± అవసరం.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, à°—à°¡à±à°µà± <ph name="EXPIRATION_DATE_ABBR" />à°¨ à°®à±à°—à±à°¸à±à°¤à±à°‚ది</translation>
<translation id="2337852623177822836">సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°¨à± మీ నిరà±à°µà°¾à°¹à°•à±à°²à± నియంతà±à°°à°¿à°¸à±à°¤à±à°¨à±à°¨à°¾à°°à±</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> దీనితో జత చేయాలనà±à°•à±à°‚టోంది</translation>
<translation id="2344028582131185878">ఆటోమేటికౠడౌనà±â€Œà°²à±‹à°¡à±â€Œà°²à±</translation>
<translation id="2346319942568447007">మీరౠకాపీ చేసిన à°šà°¿à°¤à±à°°à°‚</translation>
<translation id="2354001756790975382">ఇతర à°¬à±à°•à±â€Œà°®à°¾à°°à±à°•à±â€Œà°²à±</translation>
@@ -388,8 +398,10 @@
<translation id="2355395290879513365">దాడికి పాలà±à°ªà°¡à±‡à°µà°¾à°°à± à°ˆ సైటà±â€Œà°²à±‹ మీరౠచూసà±à°¤à±à°¨à±à°¨ à°šà°¿à°¤à±à°°à°¾à°²à°¨à± చూడగలరà±, వాటిని సవరించడం à°¦à±à°µà°¾à°°à°¾ మిమà±à°®à°²à±à°¨à°¿ మోసగించవచà±à°šà±.</translation>
<translation id="2356070529366658676">à°…à°¡à±à°—à±</translation>
<translation id="2357481397660644965"><ph name="DEVICE_MANAGER" /> మీ పరికరానà±à°¨à°¿ మేనేజౠచేసà±à°¤à±‹à°‚ది, <ph name="ACCOUNT_MANAGER" /> మీ ఖాతానౠమేనేజౠచేసà±à°¤à±‹à°‚ది.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{రోజౠకంటే తకà±à°•à±à°µà°²à±‹}=1{రోజà±à°²à±‹}other{{NUM_DAYS} రోజà±à°²à±à°²à±‹}}</translation>
<translation id="2359629602545592467">అనేకం</translation>
<translation id="2359808026110333948">కొనసాగించà±</translation>
+<translation id="2359961752320758691">మీ వరà±à°šà±à°µà°²à± కారà±à°¡à± నంబరౠవరà±à°¤à°¿à°‚చబడింది.</translation>
<translation id="2367567093518048410">à°¸à±à°¥à°¾à°¯à°¿</translation>
<translation id="2372464001869762664">మీరౠనిరà±à°§à°¾à°°à°¿à°‚à°šà°¿à°¨ తరà±à°µà°¾à°¤, మీ Google ఖాతా à°¨à±à°‚à°¡à°¿ కారà±à°¡à± వివరాలౠఈ సైటà±â€Œà°¤à±‹ షేరౠచేయబడతాయి. CVCనౠమీ Plex ఖాతా వివరాలలో à°•à°¨à±à°—ొనండి.</translation>
<translation id="2380886658946992094">à°šà°Ÿà±à°Ÿà°ªà°°à°‚</translation>
@@ -400,6 +412,7 @@
<translation id="239429038616798445">à°ˆ రవాణా పదà±à°§à°¤à°¿ à°…à°‚à°¦à±à°¬à°¾à°Ÿà±à°²à±‹ లేదà±. వేరే పదà±à°§à°¤à°¿à°¨à°¿ à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚à°šà°‚à°¡à°¿.</translation>
<translation id="2396249848217231973">&amp;తొలగించడానà±à°¨à°¿ à°°à°¦à±à°¦à± చేయి</translation>
<translation id="2410754574180102685">à°ªà±à°°à°­à±à°¤à±à°µà°‚-à°¨à±à°¯à°¾à°¯ సంబంధిత</translation>
+<translation id="2413155254802890957">పాతది</translation>
<translation id="2413528052993050574">à°ˆ సరà±à°µà°°à± <ph name="DOMAIN" /> అని నిరూపించà±à°•à±‹à°²à±‡à°•à°ªà±‹à°¯à°¿à°‚ది; దీని à°­à°¦à±à°°à°¤à°¾ à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ ఉపసంహరించబడి ఉండవచà±à°šà±. ఇది తపà±à°ªà±à°—à°¾ కానà±à°«à°¿à°—రౠచేయడం వలన లేదా దాడిచేసే à°µà±à°¯à°•à±à°¤à°¿ మీ కనెకà±à°·à°¨à±â€Œà°•à± అంతరాయం కలిగించడం వలన జరిగి ఉండవచà±à°šà±.</translation>
<translation id="2414886740292270097">à°®à±à°¦à±à°°à±</translation>
<translation id="2438874542388153331">à°•à±à°¡à°¿à°µà±ˆà°ªà± నాలà±à°—à± à°°à°‚à°§à±à°°à°¾à°²à±</translation>
@@ -427,10 +440,10 @@
<translation id="2521385132275182522">à°•à±à°¡à°¿à°µà±ˆà°ªà± దిగà±à°µ భాగంలో à°¸à±à°Ÿà±‡à°ªà±à°²à±</translation>
<translation id="2523886232349826891">à°ˆ పరికరంలో మాతà±à°°à°®à±‡ సేవౠచేయబడి ఉంటà±à°‚ది</translation>
<translation id="2524461107774643265">మరింత సమాచారానà±à°¨à°¿ జోడించండి</translation>
-<translation id="2526590354069164005">డెసà±à°•à±â€Œà°Ÿà°¾à°ªà±</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{మరియౠమరో 1}other{మరియౠమరో #}}</translation>
<translation id="2536110899380797252">à°šà°¿à°°à±à°¨à°¾à°®à°¾à°¨à± జోడించà±</translation>
<translation id="2539524384386349900">à°—à±à°°à±à°¤à°¿à°‚à°šà±</translation>
+<translation id="2541219929084442027">మీ à°…à°œà±à°žà°¾à°¤ à°Ÿà±à°¯à°¾à°¬à±â€Œà°²à± à°…à°¨à±à°¨à°¿à°‚టినీ మూసివేసిన తరà±à°µà°¾à°¤ మీ à°¬à±à°°à±Œà°œà°°à± హిసà±à°Ÿà°°à±€, à°•à±à°•à±à°•à±€ à°¸à±à°Ÿà±‹à°°à± లేదా సెరà±à°šà± హిసà±à°Ÿà°°à±€à°²à±‹ మీరౠఅజà±à°žà°¾à°¤ à°Ÿà±à°¯à°¾à°¬à±â€Œà°²à°²à±‹ వీకà±à°·à°¿à°‚à°šà°¿à°¨ పేజీలౠఉంచబడవà±. అయితే, మీరౠడౌనà±â€Œà°²à±‹à°¡à± చేసే à°à°µà±ˆà°¨à°¾ ఫైళà±à°²à± లేదా మీరౠకà±à°°à°¿à°¯à±‡à°Ÿà± చేసే à°à°µà±ˆà°¨à°¾ à°¬à±à°•à±â€Œà°®à°¾à°°à±à°•à±â€Œà°²à± అలాగే ఉంచబడతాయి.</translation>
<translation id="2544644783021658368">à°’à°• డాకà±à°¯à±à°®à±†à°‚à°Ÿà±</translation>
<translation id="254947805923345898">విధానం విలà±à°µ చెలà±à°²à±à°¬à°¾à°Ÿà± కాదà±.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> చెలà±à°²à°¨à°¿ à°ªà±à°°à°¤à°¿à°¸à±à°ªà°‚దననౠపంపింది.</translation>
@@ -450,6 +463,7 @@
<translation id="2629325967560697240">Chrome à°…à°¤à±à°¯à°§à°¿à°• à°¸à±à°¥à°¾à°¯à°¿ à°°à°•à±à°·à°£à°¨à± పొందడానికి, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />మెరà±à°—à±à°ªà°°à°¿à°šà°¿à°¨ ఫీచరà±â€Œà°²à°¨à± ఆనౠచేయండి<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> యొకà±à°• సరà±à°µà°°à± IP à°šà°¿à°°à±à°¨à°¾à°®à°¾ à°•à°¨à±à°—ొనబడలేదà±.</translation>
<translation id="2639739919103226564">à°¸à±à°¥à°¿à°¤à°¿: </translation>
+<translation id="264810637653812429">à°…à°¨à±à°•à±‚à°² పరికరాలౠà°à°µà±€ à°•à°¨à±à°—ొనబడలేదà±.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹ మీ à°¬à±à°°à±Œà°œà°¿à°‚గౠహిసà±à°Ÿà°°à±€, à°•à±à°•à±à°•à±€à°²à±, కాషౠఇంకా మరినà±à°¨à°¿à°‚టిని à°•à±à°²à°¿à°¯à°°à± చేయడానికి 'Tab'నౠనొకà±à°•à°¿, ఆపై 'Enter'నౠనొకà±à°•à°‚à°¡à°¿</translation>
<translation id="2650446666397867134">ఫైలà±â€Œà°•à± యాకà±à°¸à±†à°¸à± తిరసà±à°•à°°à°¿à°‚చబడింది</translation>
@@ -457,7 +471,7 @@
<translation id="2660779039299703961">ఈవెంటà±</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="2666092431469916601">పైన</translation>
-<translation id="2666117266261740852">ఇతర à°Ÿà±à°¯à°¾à°¬à±â€Œà°²à± లేదా à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°²à°¨à± మూసివేయండి</translation>
+<translation id="2666117266261740852">ఇతర à°Ÿà±à°¯à°¾à°¬à±â€Œà°²à± లేదా యాపà±â€Œà°²à°¨à± మూసివేయండి</translation>
<translation id="2672201172023654893">మీ à°¬à±à°°à±Œà°œà°°à± మేనేజౠచేయబడలేదà±.</translation>
<translation id="2674170444375937751">మీ à°šà°°à°¿à°¤à±à°° à°¨à±à°‚à°¡à°¿ à°ˆ పేజీలనౠతొలగించదలిచారా?</translation>
<translation id="2674804415323431591">సూచనలనౠదాచà±</translation>
@@ -494,13 +508,16 @@
<translation id="2799223571221894425">మళà±à°²à±€ à°ªà±à°°à°¾à°°à°‚à°­à°¿à°‚à°šà±</translation>
<translation id="2803306138276472711">Google à°¸à±à°°à°•à±à°·à°¿à°¤ à°¬à±à°°à±Œà°œà°¿à°‚గౠఇటీవల <ph name="SITE" />లో <ph name="BEGIN_LINK" />మాలà±à°µà±‡à°°à±â€Œà°¨à± à°—à±à°°à±à°¤à°¿à°‚చింది<ph name="END_LINK" />. సాధారణంగా à°¸à±à°°à°•à±à°·à°¿à°¤à°®à±ˆà°¨ వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œâ€Œà°²à°•à± కూడా కొనà±à°¨à°¿à°¸à°¾à°°à±à°²à± మాలà±à°µà±‡à°°à± సోకà±à°¤à±à°‚ది.</translation>
<translation id="2807052079800581569">à°šà°¿à°¤à±à°°à°‚ యొకà±à°• Y కోఆరà±à°¡à°¿à°¨à±‡à°Ÿà±</translation>
+<translation id="2820957248982571256">à°¸à±à°•à°¾à°¨à± చేసà±à°¤à±‹à°‚ది...</translation>
<translation id="2824775600643448204">à°šà°¿à°°à±à°¨à°¾à°®à°¾ మరియౠశోధన బారà±</translation>
<translation id="2826760142808435982"><ph name="CIPHER" />నౠఉపయోగించి కనెకà±à°·à°¨à± à°Žà°¨à±â€Œà°•à±à°°à°¿à°ªà±à°Ÿà± చేయ‌బ‌డింది, à°ªà±à°°à°¾à°®à°¾à°£à±€à°•à°°à°¿à°‚చబడింది మరియౠ<ph name="KX" />నౠకీలకమైన పరివరà±à°¤à°¨ విధానంగా ఉపయోగిసà±à°¤à±à°‚ది.</translation>
<translation id="2835170189407361413">ఫారమà±â€Œà°¨à± à°•à±à°²à°¿à°¯à°°à± చేయి</translation>
<translation id="2839501879576190149">à°®à±à°‚à°¦à±à°¨à±à°¨ సైటౠనకిలీది</translation>
<translation id="2850739647070081192">ఆహà±à°µà°¾à°¨à°‚ (à°Žà°¨à±à°µà°²à°ªà±)</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="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="2859806420264540918">à°ˆ సైటౠఅనà±à°šà°¿à°¤à°®à±ˆà°¨ లేదా తపà±à°ªà±à°¦à°¾à°°à°¿ పటà±à°Ÿà°¿à°‚చే à°ªà±à°°à°•à°Ÿà°¨à°²à°¨à± చూపà±à°¤à±à°‚ది.</translation>
+<translation id="287596039013813457">à°¸à±à°¨à±‡à°¹à°ªà±‚à°°à±à°µà°•à°®à±ˆà°¨à°¦à°¿</translation>
+<translation id="2876489322757410363">వెలà±à°ªà°²à°¿ à°…à°ªà±à°²à°¿à°•à±‡à°·à°¨à± à°¦à±à°µà°¾à°°à°¾ చెలà±à°²à°¿à°‚చడానికి à°…à°œà±à°žà°¾à°¤ మోడౠనà±à°‚à°¡à°¿ నిషà±à°•à±à°°à°®à°¿à°¸à±à°¤à±‹à°‚ది. కొనసాగించాలా?</translation>
<translation id="2878197950673342043">పోసà±à°Ÿà°°à± ఫోలà±à°¡à±</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">విండో à°¸à±à°¥à°²à°‚</translation>
@@ -540,7 +557,7 @@
<translation id="3005723025932146533">సేవౠచేయబడిన కాపీని చూపà±</translation>
<translation id="3008447029300691911"><ph name="CREDIT_CARD" /> కారà±à°¡à± CVCని నమోదౠచేయండి. మీరౠనిరà±à°§à°¾à°°à°¿à°‚à°šà°¿à°¨ తరà±à°µà°¾à°¤, మీ కారà±à°¡à± వివరాలౠఈ సైటà±â€Œà°¤à±‹ షేరౠచేయబడతాయి.</translation>
<translation id="3010559122411665027">జాబితా నమోదౠ"<ph name="ENTRY_INDEX" />": <ph name="ERROR" /></translation>
-<translation id="301521992641321250">à°¸à±à°µà°¯à°‚చాలకంగా à°¬à±à°²à°¾à°•à± చేయబడింది</translation>
+<translation id="301521992641321250">ఆటోమేటికà±â€Œà°—à°¾ à°¬à±à°²à°¾à°•à± చేయబడింది</translation>
<translation id="3016780570757425217">మీ à°¸à±à°¥à°¾à°¨à°¾à°¨à±à°¨à°¿ తెలà±à°¸à±à°•à±‹à°µà°¾à°²à°¨à±à°•à±à°‚టోంది</translation>
<translation id="3017086357773116182"><ph name="REMOVE_SUGGESTION_SUFFIX" />, సూచననౠతీసివేయడానికి Tabనౠనొకà±à°•à°¿, ఆపై à°Žà°‚à°Ÿà°°à±â€Œà°¨à± నొకà±à°•à°‚à°¡à°¿.</translation>
<translation id="3023071826883856138">You4 (à°Žà°¨à±à°µà°²à°ªà±)</translation>
@@ -550,7 +567,6 @@
<translation id="3060227939791841287">C9 (à°Žà°¨à±à°µà°²à°ªà±)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹ à°­à°¦à±à°°à°¤à°¾ తనిఖీని రనౠచేయడానికి Tabనౠనొకà±à°•à°¿ ఆపై 'Enter'నౠనొకà±à°•à°‚à°¡à°¿</translation>
<translation id="3061707000357573562">à°ªà±à°¯à°¾à°šà± సేవ</translation>
-<translation id="3064966200440839136">బాహà±à°¯ à°…à°ªà±à°²à°¿à°•à±‡à°·à°¨à±â€Œ à°¦à±à°µà°¾à°°à°¾ చెలà±à°²à°¿à°‚చడానికి à°…à°œà±à°žà°¾à°¤ మోడౠనà±à°‚à°¡à°¿ నిషà±à°•à±à°°à°®à°¿à°¸à±à°¤à±‹à°‚ది. కొనసాగించాలా?</translation>
<translation id="306573536155379004">గేమౠపà±à°°à°¾à°°à°‚భమైంది.</translation>
<translation id="3080254622891793721">à°—à±à°°à°¾à°«à°¿à°•à±</translation>
<translation id="3086579638707268289">వెబà±â€Œà°²à±‹ మీ కారà±à°¯à°•à°²à°¾à°ªà°‚ పరà±à°¯à°µà±‡à°•à±à°·à°¿à°‚చబడà±à°¤à±‹à°‚ది</translation>
@@ -573,7 +589,6 @@
<translation id="315504272643575312"><ph name="MANAGER" /> మీ ఖాతానౠమేనేజౠచేసà±à°¤à±‹à°‚ది.</translation>
<translation id="3157931365184549694">à°ªà±à°¨à°°à±à°¦à±à°§à°°à°¿à°‚à°šà±</translation>
<translation id="3162559335345991374">మీరౠఉపయోగిసà±à°¤à±à°¨à±à°¨ Wi-Fià°•à°¿ మీరౠదాని లాగినౠపేజీని సందరà±à°¶à°¿à°‚à°šà°¡à°‚ అవసరం.</translation>
-<translation id="3167968892399408617">మీరౠఅజà±à°žà°¾à°¤ à°Ÿà±à°¯à°¾à°¬à±â€Œà°²à±à°²à±‹ వీకà±à°·à°¿à°‚à°šà°¿à°¨ పేజీలà±- మీ à°…à°¨à±à°¨à°¿ à°…à°œà±à°žà°¾à°¤ à°Ÿà±à°¯à°¾à°¬à±â€Œà°²à°¨à± మూసివేసిన అనంతరం- మీ à°¬à±à°°à±Œà°œà°°à± à°šà°°à°¿à°¤à±à°°, à°•à±à°•à±à°•à±€ à°¸à±à°Ÿà±‹à°°à± లేదా శోధన à°šà°°à°¿à°¤à±à°°à°²à±‹ ఉంచబడవà±. మీరౠడౌనà±â€Œà°²à±‹à°¡à± చేసే à°à°µà±ˆà°¨à°¾ ఫైలà±à°¸à± లేదా మీరౠసృషà±à°Ÿà°¿à°‚చే à°à°µà±ˆà°¨à°¾ à°¬à±à°•à±â€Œà°®à°¾à°°à±à°•à±â€Œà°²à± అలాగే ఉంచబడతాయి.</translation>
<translation id="3169472444629675720">à°•à°¨à±à°—ొనà±</translation>
<translation id="3174168572213147020">దీవి</translation>
<translation id="3176929007561373547">à°ªà±à°°à°¾à°•à±à°¸à±€ సరà±à°µà°°à± పని చేసà±à°¤à±à°¨à±à°¨à°Ÿà±à°²à± నిరà±à°§à°¾à°°à°¿à°‚à°šà±à°•à±‹à°µà°¡à°¾à°¨à°¿à°•à°¿ మీ à°ªà±à°°à°¾à°•à±à°¸à±€ సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°¨à± తనిఖీ చేయండి లేదా
@@ -585,7 +600,7 @@
<translation id="3194737229810486521"><ph name="URL" /> శాశà±à°µà°¤à°‚à°—à°¾ డేటానౠమీ పరికరంలో నిలà±à°µ చేయాలనà±à°•à±à°‚టోంది</translation>
<translation id="3195213714973468956"><ph name="SERVER_NAME" />లో <ph name="PRINTER_NAME" /></translation>
<translation id="3202497928925179914"><ph name="MANAGE_SYNC_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹ మీరౠఠసమాచారానà±à°¨à°¿ సింకౠచేయాలనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à±‹ మేనేజౠచేయడానికి 'Tab'నౠనొకà±à°•à°¿, ఆపై 'Enter'నౠనొకà±à°•à°‚à°¡à°¿</translation>
-<translation id="320323717674993345">చెలà±à°²à°¿à°‚à°ªà±à°¨à± à°°à°¦à±à°¦à± చేయండి</translation>
+<translation id="320323717674993345">పేమెంటà±â€Œà°¨à± à°°à°¦à±à°¦à± చేయండి</translation>
<translation id="3207960819495026254">à°¬à±à°•à±â€Œà°®à°¾à°°à±à°•à± చేయబడింది</translation>
<translation id="3209034400446768650">పేజీ, నగదà±à°¨à± ఛారà±à°œà± చేయవచà±à°šà±</translation>
<translation id="3212581601480735796"><ph name="HOSTNAME" />లోని మీ కారà±à°¯à°•à°²à°¾à°ªà°‚ పరà±à°¯à°µà±‡à°•à±à°·à°¿à°‚చబడà±à°¤à±‹à°‚ది</translation>
@@ -599,10 +614,12 @@
<translation id="3229041911291329567">మీ పరికరం, à°¬à±à°°à±Œà°œà°°à±â€Œà°² వెరà±à°·à°¨à± సమాచారం</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> కారà±à°¡à± CVCని నమోదౠచేయండి</translation>
<translation id="3234666976984236645">à°ˆ సైటà±â€Œà°²à±‹ à°Žà°ªà±à°ªà±à°¡à±‚ à°®à±à°–à±à°¯à°®à±ˆà°¨ కంటెంటà±â€Œà°¨à± à°—à±à°°à±à°¤à°¿à°‚à°šà±</translation>
+<translation id="3249845759089040423">సొగసైనది</translation>
<translation id="3252266817569339921">à°«à±à°°à±†à°‚à°šà±</translation>
<translation id="3266793032086590337">విలà±à°µ (వైరà±à°§à±à°¯à°‚)</translation>
<translation id="3268451620468152448">ఓపెనౠటాబà±â€Œà°²à±</translation>
<translation id="3270847123878663523">&amp;మళà±à°²à±€ à°•à±à°°à°®à°‚ చేయడానà±à°¨à°¿ à°°à°¦à±à°¦à± చేయి</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> దీనికి కనెకà±à°Ÿà± చేయాలనà±à°•à±à°‚టోంది</translation>
<translation id="3274521967729236597">పా-కాయà±</translation>
<translation id="3282085321714087552">సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à± లేదా పాలసీల వంటి కొంత సమాచారానà±à°¨à°¿ మీ సంసà±à°¥ <ph name="ENROLLMENT_DOMAIN" />, దిగà±à°µà±à°¨ పేరà±à°•à±Šà°¨à±à°¨ వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°²à°•à± పంపింది.</translation>
<translation id="3282497668470633863">కారà±à°¡à±â€Œà°²à±‹ పేరà±à°¨à°¿ జోడించండి</translation>
@@ -655,10 +672,11 @@
<translation id="3428151540071562330">DnsOverHttpsTemplates సరà±à°µà°°à± టెంపà±à°²à±‡à°Ÿà±â€Œ URIలౠచెలà±à°²à°µà±, ఉపయోగించబడవà±.</translation>
<translation id="3431636764301398940">à°ˆ కారà±à°¡à±â€Œà°¨à± à°ˆ పరికరానికి సేవౠచేయి</translation>
<translation id="3432601291244612633">పేజీని మూసివేయండి</translation>
+<translation id="3435738964857648380">à°­à°¦à±à°°à°¤</translation>
<translation id="3435896845095436175">à°ªà±à°°à°¾à°°à°‚à°­à°¿à°‚à°šà°‚à°¡à°¿</translation>
<translation id="3438829137925142401">మీ Google ఖాతాలో సేవౠచేయబడిన పాసà±â€Œà°µà°°à±à°¡à±â€Œâ€Œà°²à°¨à± ఉపయోగించండి</translation>
<translation id="3443726618221119081">à°œà±à°°à±à°°à±‹-à°•à±-కాయà±</translation>
-<translation id="3447661539832366887">à°ˆ పరికర యజమాని డైనోసారౠగేమà±â€Œà°¨à± ఆఫౠచేసారà±.</translation>
+<translation id="3447661539832366887">à°ˆ పరికర యజమాని డైనోసారౠగేమà±â€Œà°¨à± ఆఫౠచేశారà±.</translation>
<translation id="3447884698081792621">సరà±à°Ÿà°¿à°«à°¿à°•à±‡à°Ÿà±â€Œà°¨à± చూపౠ(<ph name="ISSUER" /> à°¦à±à°µà°¾à°°à°¾ జారీ చేయబడింది)</translation>
<translation id="3452404311384756672">విరామానà±à°¨à°¿ పొందండి:</translation>
<translation id="3453962258458347894">à°ªà±à°¨à°ƒà°ªà±à°°à°¯à°¤à±à°¨à°¾à°² సంఖà±à°¯</translation>
@@ -697,7 +715,10 @@
<translation id="3584299510153766161">దిగà±à°µ భాగంలో రెండౠరంధà±à°°à°¾à°²à±</translation>
<translation id="3586931643579894722">వివరాలనౠదాచిపెటà±à°Ÿà±</translation>
<translation id="3587738293690942763">మధà±à°¯à°²à±‹</translation>
+<translation id="3590643883886679995">మీరౠఅజà±à°žà°¾à°¤ మోడౠనà±à°‚à°¡à°¿ నిషà±à°•à±à°°à°®à°¿à°‚à°šà°¿à°¨ తరà±à°µà°¾à°¤ సైనà±-ఇనౠడేటా à°ˆ పరికరంలో à°¸à±à°Ÿà±‹à°°à± చేయబడà±à°¤à±à°‚ది.</translation>
+<translation id="359126217934908072">నెల/సంవతà±à°¸à°°à°‚:</translation>
<translation id="3592413004129370115">ఇటాలియనౠ(à°Žà°¨à±à°µà°²à°ªà±)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{మీరౠఠసమయంలో అయినా మీ à°—à±à°°à±‚à°ªà±â€Œà°¨à± రీసెటౠచేయవచà±à°šà±. కొతà±à°¤ à°—à±à°°à±‚à°ªà±â€Œà°•à± చేరడానికి à°’à°• రోజౠవరకౠపడà±à°¤à±à°‚ది.}=1{మీరౠఠసమయంలో అయినా మీ à°—à±à°°à±‚à°ªà±â€Œà°¨à± రీసెటౠచేయవచà±à°šà±. కొతà±à°¤ à°—à±à°°à±‚à°ªà±â€Œà°•à± చేరడానికి à°’à°• రోజౠవరకౠపడà±à°¤à±à°‚ది.}other{మీరౠఠసమయంలో అయినా మీ à°—à±à°°à±‚à°ªà±â€Œà°¨à± రీసెటౠచేయవచà±à°šà±. కొతà±à°¤ à°—à±à°°à±‚à°ªà±â€Œà°•à± చేరడానికి {NUM_DAYS} రోజà±à°²à± పడà±à°¤à±à°‚ది.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">మీ నిరà±à°µà°¾à°¹à°•à±à°¡à± యాపà±â€Œà°¨à± à°¬à±à°²à°¾à°•à± చేశారà±</translation>
<translation id="3608932978122581043">ఫీడౠఓరియంటేషనà±</translation>
@@ -706,13 +727,13 @@
<translation id="3615877443314183785">చెలà±à°²à±à°¬à°¾à°Ÿà± à°…à°¯à±à°¯à±‡ à°—à°¡à±à°µà± à°®à±à°—ింపౠతేదీని నమోదౠచేయండి</translation>
<translation id="36224234498066874">à°¬à±à°°à±Œà°œà°¿à°‚గౠడేటానౠకà±à°²à°¿à°¯à°°à± చేయి...</translation>
<translation id="362276910939193118">పూరà±à°¤à°¿ à°šà°°à°¿à°¤à±à°°à°¨à± చూపించà±</translation>
-<translation id="3625635938337243871">మీరౠఅజà±à°žà°¾à°¤ మోడౠనà±à°‚à°¡à°¿ నిషà±à°•à±à°°à°®à°¿à°‚à°šà°¿à°¨ తరà±à°µà°¾à°¤ సైనà±-ఇనౠడేటా à°ˆ పరికరంలో à°¸à±à°Ÿà±‹à°°à± చేయబడà±à°¤à±à°‚ది.</translation>
<translation id="3630155396527302611">ఇపà±à°ªà°Ÿà°¿à°•à±‡ ఇది నెటà±â€Œà°µà°°à±à°•à±â€Œà°¨à± యాకà±à°¸à±†à°¸à± చేయడానికి à°…à°¨à±à°®à°¤à°¿à°‚చబడిన à°ªà±à°°à±‹à°—à±à°°à°¾à°®à± లాగా జాబితా చేయబడి ఉంటే,
దీనà±à°¨à°¿ జాబితా à°¨à±à°‚à°¡à°¿ తీసివేసి, ఆపై మళà±à°²à±€ జోడించి à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚à°šà°‚à°¡à°¿.</translation>
<translation id="3630699740441428070">à°ˆ పరికరానికి సంబంధించిన à°…à°¡à±à°®à°¿à°¨à°¿à°¸à±à°Ÿà±à°°à±‡à°Ÿâ€Œà°°à±â€Œà°²à± మీ నెటà±â€Œà°µà°°à±à°•à± కనెకà±à°·à°¨à±â€Œà°¨à± కానà±à°«à°¿à°—రౠచేశారà±, ఇది మీరౠసందరà±à°¶à°¿à°‚చే వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°²à°¤à±‹ సహా మీ నెటà±â€Œà°µà°°à±à°•à± à°Ÿà±à°°à°¾à°«à°¿à°•à±â€Œà°¨à± చూడటానికి వారిని à°…à°¨à±à°®à°¤à°¿à°‚చవచà±à°šà±.</translation>
<translation id="3631244953324577188">బయోమెటà±à°°à°¿à°•à±à°¸à±</translation>
<translation id="3633738897356909127">'Chromeనౠఅపà±â€Œà°¡à±‡à°Ÿà± చేయి' బటనà±, మీ Chrome సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°² à°¨à±à°‚à°¡à°¿ Chromeనౠఅపà±â€Œà°¡à±‡à°Ÿà± చేయడానికి 'Enter'నౠనొకà±à°•à°‚à°¡à°¿</translation>
<translation id="3634530185120165534">à°Ÿà±à°°à±‡ 5</translation>
+<translation id="3637662659967048211">Google ఖాతాకౠసేవౠచేయండి</translation>
<translation id="3640766068866876100">సూచిక-4x6-Ext</translation>
<translation id="3642638418806704195">యాపà±:</translation>
<translation id="3650584904733503804">à°ªà±à°°à°¾à°®à°¾à°£à±€à°•à°°à°£ విజయవంతం అయింది</translation>
@@ -753,6 +774,7 @@
<translation id="3781428340399460090">à°®à±à°¦à±à°°à± à°—à±à°²à°¾à°¬à°¿ à°°à°‚à°—à±</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">à°¬à±à°²à±‚టూతౠపరికరాలà±</translation>
+<translation id="3787675388804467730">వరà±à°šà±à°µà°²à± కారà±à°¡à± నంబరà±</translation>
<translation id="3787705759683870569">à°—à°¡à±à°µà± à°®à±à°—ింపౠ<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">పరిమాణం 16</translation>
<translation id="3789841737615482174">ఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేయి</translation>
@@ -766,12 +788,13 @@
<translation id="382518646247711829">మీరౠపà±à°°à°¾à°•à±à°¸à±€ సరà±à°µà°°à±â€Œà°¨à± ఉపయోగిసà±à°¤à±‡...</translation>
<translation id="3827112369919217609">à°…à°¬à±à°¸à°²à±à°¯à±‚à°Ÿà±</translation>
<translation id="3828924085048779000">ఖాళీ రహసà±à°¯ పదబంధం à°…à°¨à±à°®à°¤à°¿à°‚చబడదà±.</translation>
-<translation id="3831915413245941253"><ph name="ENROLLMENT_DOMAIN" /> అదనపౠఫంకà±à°·à°¨à±â€Œà°² కోసం à°Žà°•à±à°¸à±â€Œà°Ÿà±†à°¨à±à°·à°¨à±â€Œà°²à°¨à± ఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేసారà±. మీ డేటాలో కొంత భాగానికి à°Žà°•à±à°¸à±â€Œà°Ÿà±†à°¨à±à°·à°¨à±â€Œà°²à± యాకà±à°¸à±†à°¸à± కలిగి ఉంటాయి.</translation>
+<translation id="3831915413245941253"><ph name="ENROLLMENT_DOMAIN" /> అదనపౠఫంకà±à°·à°¨à±â€Œà°² కోసం à°Žà°•à±à°¸à±â€Œà°Ÿà±†à°¨à±à°·à°¨à±â€Œà°²à°¨à± ఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేశారà±. మీ డేటాలో కొంత భాగానికి à°Žà°•à±à°¸à±â€Œà°Ÿà±†à°¨à±à°·à°¨à±â€Œà°²à± యాకà±à°¸à±†à°¸à± కలిగి ఉంటాయి.</translation>
<translation id="3832522519263485449">ఎడమవైపౠఅనేక à°°à°‚à°§à±à°°à°¾à°²à±</translation>
<translation id="3835233591525155343">మీ పరికర వినియోగం</translation>
<translation id="3841184659773414994">ఫైలౠహà±à°¯à°¾à°‚à°¡à±à°²à°°à±â€Œà°²à±</translation>
<translation id="385051799172605136">వెనà±à°•à°•à±</translation>
<translation id="3858027520442213535">తేదీని, సమయానà±à°¨à°¿ à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేయి</translation>
+<translation id="3881478300875776315">కొనà±à°¨à°¿ వరà±à°¸à°²à°¨à± మాతà±à°°à°®à±‡ చూపించà±</translation>
<translation id="3884278016824448484">వైరà±à°§à±à°¯à°®à±ˆà°¨ పరికరం à°à°¡à±†à°‚టిఫైయరà±</translation>
<translation id="3885155851504623709">పారిషà±</translation>
<translation id="388632593194507180">పరà±à°¯à°µà±‡à°•à±à°·à°£ à°—à±à°°à±à°¤à°¿à°‚చబడింది</translation>
@@ -797,6 +820,7 @@
<translation id="397105322502079400">గణిసà±à°¤à±‹à°‚ది...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> à°¬à±à°²à°¾à°•à± చేయబడింది</translation>
<translation id="3973357910713125165">Chrome à°­à°¦à±à°°à°¤à°¾ తనిఖీ రనౠచేసే బటనà±, Chrome సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹ à°­à°¦à±à°°à°¤à°¾ తనిఖీని రనౠచేయడానికి 'Enter'నౠనొకà±à°•à°‚à°¡à°¿</translation>
+<translation id="3986705137476756801">à°ªà±à°°à°¸à±à°¤à±à°¤à°¾à°¨à°¿à°•à°¿ లైవౠకà±à°¯à°¾à°ªà±à°·à°¨à±â€Œà°¨à± ఆఫౠచేయి</translation>
<translation id="3987405730340719549">à°ˆ సైటౠనకిలీ లేదా మోసపూరితమైనది కావచà±à°šà°¨à°¿ Chrome à°—à±à°°à±à°¤à°¿à°‚చింది.
ఇది పొరపాటà±à°—à°¾ చూపించబడింది అని మీరౠఅనà±à°•à±à°‚టే, దయచేసి https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals లింకà±â€Œà°¨à± సందరà±à°¶à°¿à°‚à°šà°‚à°¡à°¿.</translation>
@@ -822,7 +846,7 @@
<translation id="4098354747657067197">à°®à±à°‚à°¦à±à°¨à±à°¨ సైటౠమోసపూరితమైనది</translation>
<translation id="4101413244023615925">టెకà±à°¸à±à°Ÿà±, à°—à±à°°à°¾à°«à°¿à°•à±à°¸à±</translation>
<translation id="4103249731201008433">పరికరం à°•à±à°°à°® సంఖà±à°¯ చెలà±à°²à°¦à±</translation>
-<translation id="4110652170750985508">మీ చెలà±à°²à°¿à°‚à°ªà±à°¨à± à°°à°¿à°µà±à°¯à±‚ చేయండి</translation>
+<translation id="4110652170750985508">మీ పేమెంటà±â€Œà°¨à± à°°à°¿à°µà±à°¯à±‚ చేయండి</translation>
<translation id="4112140312785995938">వెనà±à°•à°•à± జరà±à°ªà±</translation>
<translation id="4116663294526079822">à°ˆ సైటà±â€Œà°²à±‹ à°Žà°²à±à°²à°ªà±à°ªà±à°¡à±‚ à°…à°¨à±à°®à°¤à°¿à°‚à°šà±</translation>
<translation id="4116701314593212016">JIS B7</translation>
@@ -893,13 +917,14 @@
<translation id="4275830172053184480">మీ పరికరానà±à°¨à°¿ à°ªà±à°¨à°ƒà°ªà±à°°à°¾à°°à°‚à°­à°¿à°‚à°šà°‚à°¡à°¿</translation>
<translation id="4277028893293644418">పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± రీసెటౠచేయి</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{à°ˆ కారà±à°¡à± మీ Google ఖాతాలో సేవౠచేయబడింది}other{à°ˆ కారà±à°¡à±â€Œà°²à± మీ Google ఖాతాలో సేవౠచేయబడà±à°¡à°¾à°¯à°¿}}</translation>
+<translation id="4287885627794386150">à°Ÿà±à°°à°¯à°²à±â€Œà°•à± à°…à°°à±à°¹à°¤ పొందారà±, కానీ యాకà±à°Ÿà°¿à°µà±â€Œà°²à±‹ లేదà±</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> పేజీ కోసం థంబà±â€Œà°¨à±†à°¯à°¿à°²à±</translation>
<translation id="42981349822642051">విసà±à°¤à°°à°¿à°‚à°šà±</translation>
<translation id="4300675098767811073">à°•à±à°¡à°¿à°µà±ˆà°ªà± అనేక à°°à°‚à°§à±à°°à°¾à°²à±</translation>
<translation id="4302514097724775343">ఆడటానికి డైనోసారà±â€Œà°¨à± à°Ÿà±à°¯à°¾à°ªà± చేయండి</translation>
<translation id="4302965934281694568">Chou3 (à°Žà°¨à±à°µà°²à°ªà±)</translation>
<translation id="4305666528087210886">మీ ఫైలà±â€Œà°¨à± యాకà±à°¸à±†à°¸à± చేయడం సాధà±à°¯à°ªà°¡à°²à±‡à°¦à±</translation>
-<translation id="4305817255990598646">à°¸à±à°µà°¿à°šà±</translation>
+<translation id="4306529830550717874">à°…à°¡à±à°°à°¸à±â€Œà°¨à± సేవౠచేయాలా?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">à°¬à±à°²à°¾à°•à± చేయి (డిఫాలà±à°Ÿà±)</translation>
<translation id="4314815835985389558">సింకà±â€Œà°¨à± నిరà±à°µà°¹à°¿à°‚à°šà°‚à°¡à°¿</translation>
@@ -915,7 +940,7 @@
<translation id="4346197816712207223">ఆమోదించే à°•à±à°°à±†à°¡à°¿à°Ÿà± కారà±à°¡à±â€Œà°²à±</translation>
<translation id="4346833872170306413">Roc-16K</translation>
<translation id="4349531505348777662">మీరౠమోసపూరితమైన సైటà±â€Œà°²à±‹ మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఎంటరౠచేశారà±. మీరౠఈ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఉపయోగించిన<ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, ఇతర సైటà±â€Œà°²à°•à± ఇపà±à°ªà±à°¡à±‡ వెళà±à°²à°¿, మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± మారà±à°šà°¾à°²à±à°¸à°¿à°‚దిగా Chrome సిఫారà±à°¸à± చేసà±à°¤à±‹à°‚ది.</translation>
-<translation id="4356973930735388585">à°ˆ సైటà±â€Œà°²à±‹à°¨à°¿ దాడి చేసేవారౠమీ సమాచారానà±à°¨à°¿ (ఉదాహరణకà±, ఫోటోలà±, పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à±, సందేశాలౠమరియౠకà±à°°à±†à°¡à°¿à°Ÿà± కారà±à°¡à±â€Œà°²à±) దొంగిలించడం కోసం లేదా తొలగించడం కోసం మీ à°•à°‚à°ªà±à°¯à±‚à°Ÿà°°à±â€Œà°²à±‹ à°ªà±à°°à°®à°¾à°¦à°•à°°à°®à±ˆà°¨ à°ªà±à°°à±‹à°—à±à°°à°¾à°®à±â€Œà°²à°¨à± ఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేయడానికి à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚చవచà±à°šà±.</translation>
+<translation id="4356973930735388585">à°ˆ సైటà±â€Œà°²à±‹à°¨à°¿ దాడి చేసేవారౠమీ సమాచారానà±à°¨à°¿ (ఉదాహరణకà±, ఫోటోలà±, పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à±, మెసేజà±â€Œà°²à± మరియౠకà±à°°à±†à°¡à°¿à°Ÿà± కారà±à°¡à±â€Œà°²à±) దొంగిలించడం కోసం లేదా తొలగించడం కోసం మీ à°•à°‚à°ªà±à°¯à±‚à°Ÿà°°à±â€Œà°²à±‹ à°ªà±à°°à°®à°¾à°¦à°•à°°à°®à±ˆà°¨ à°ªà±à°°à±‹à°—à±à°°à°¾à°®à±â€Œà°²à°¨à± ఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేయడానికి à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚చవచà±à°šà±.</translation>
<translation id="4358059973562876591">DnsOverHttpsMode విధానానికి సంబంధించి à°à°°à±à°ªà°¡à°¿à°¨ à°Žà°°à±à°°à°°à± కారణంగా మీరౠపేరà±à°•à±Šà°¨à±à°¨ టెంపà±à°²à±‡à°Ÿà±â€Œà°²à°¨à± వరà±à°¤à°¿à°‚పజేయడం వీలౠకాకపోవచà±à°šà±.</translation>
<translation id="4358461427845829800">చెలà±à°²à°¿à°‚పౠపదà±à°§à°¤à±à°²à°¨à± నిరà±à°µà°¹à°¿à°‚à°šà°‚à°¡à°¿...</translation>
<translation id="4359160567981085931">మీరౠమోసపూరితమైన సైటà±â€Œà°²à±‹ మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఎంటరౠచేశారà±. Chrome సహాయపడగలదà±. మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œâ€Œà°¨à± మారà±à°šà°¿, మీ ఖాతా à°ªà±à°°à°®à°¾à°¦à°‚లో ఉండవచà±à°šà°¨à°¿ Googleకౠతెలియజేయడానికి, 'ఖాతానౠసంరకà±à°·à°¿à°‚à°šà±'నౠకà±à°²à°¿à°•à± చేయండి.</translation>
@@ -923,9 +948,10 @@
<translation id="437058704415269440">ఖాతా à°¬à±à°¯à°¾à°²à±†à°¨à±à°¸à±</translation>
<translation id="4372516964750095882">à°«à±à°¯à°¾à°¨à±â€Œà°«à±‹à°²à±à°¡à±-Us</translation>
<translation id="4372948949327679948">ఆశిసà±à°¤à±à°¨à±à°¨ <ph name="VALUE_TYPE" /> విలà±à°µ.</translation>
-<translation id="4377125064752653719"><ph name="DOMAIN" />నౠచేరà±à°•à±‹à°µà°¡à°¾à°¨à°¿à°•à°¿ మీరౠపà±à°°à°¯à°¤à±à°¨à°¿à°‚చారà±, కానీ సరà±à°µà°°à± అందించిన à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°¾à°¨à±à°¨à°¿ దానà±à°¨à°¿ జారీ చేసినవారౠరదà±à°¦à± చేసారà±. సరà±à°µà°°à± అందించిన à°­à°¦à±à°°à°¤ ఆధారాలౠఖచà±à°šà°¿à°¤à°‚à°—à°¾ విశà±à°µà°¸à°¿à°‚చబడలేదని దీని à°…à°°à±à°¥à°‚. మీరౠదాడి చేసే వారితో à°•à°®à±à°¯à±‚నికేటౠచేసà±à°¤à±‚ ఉండవచà±à°šà±.</translation>
+<translation id="4377125064752653719"><ph name="DOMAIN" />నౠచేరà±à°•à±‹à°µà°¡à°¾à°¨à°¿à°•à°¿ మీరౠపà±à°°à°¯à°¤à±à°¨à°¿à°‚చారà±, కానీ సరà±à°µà°°à± అందించిన à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°¾à°¨à±à°¨à°¿ దానà±à°¨à°¿ జారీ చేసినవారౠరదà±à°¦à± చేశారà±. సరà±à°µà°°à± అందించిన à°­à°¦à±à°°à°¤ ఆధారాలౠఖచà±à°šà°¿à°¤à°‚à°—à°¾ విశà±à°µà°¸à°¿à°‚చబడలేదని దీని à°…à°°à±à°¥à°‚. మీరౠదాడి చేసే వారితో à°•à°®à±à°¯à±‚నికేటౠచేసà±à°¤à±‚ ఉండవచà±à°šà±.</translation>
<translation id="4378154925671717803">ఫోనà±</translation>
<translation id="4390472908992056574">à°¬à±à°°à°¿à°®à±</translation>
+<translation id="4406883609789734330">లైవౠకà±à°¯à°¾à°ªà±à°·à°¨à±</translation>
<translation id="4406896451731180161">శోధన ఫలితాలà±</translation>
<translation id="4408413947728134509">à°•à±à°•à±à°•à±€à°²à± <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">మీరౠమోసపూరితమైన సైటà±â€Œà°²à±‹ మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఎంటరౠచేశారà±. మీరౠఈ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఉపయోగించిన<ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> మరియౠఇతర సైటà±â€Œà°²à°•à± ఇపà±à°ªà±à°¡à±‡ వెళà±à°²à°¿, మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± మారà±à°šà°¾à°²à±à°¸à°¿à°‚దిగా Chrome సిఫారà±à°¸à± చేసà±à°¤à±‹à°‚ది.</translation>
@@ -938,7 +964,6 @@
<translation id="4435702339979719576">పోసà±à°Ÿà±â€Œà°•à°¾à°°à±à°¡à±)</translation>
<translation id="443673843213245140">à°ªà±à°°à°¾à°•à±à°¸à±€à°¨à°¿ ఉపయోగించడం ఆపివేయబడింది కానీ à°¸à±à°ªà°·à±à°Ÿà°®à±ˆà°¨ à°ªà±à°°à°¾à°•à±à°¸à±€ కానà±à°«à°¿à°—రేషనౠపేరà±à°•à±Šà°¨à°¬à°¡à°¿à°‚ది.</translation>
<translation id="4464826014807964867">మీ సంసà±à°¥à°•à± సంబంధించిన సమాచారం ఉనà±à°¨ వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°²à±</translation>
-<translation id="4466881336512663640">ఫారమà±â€Œà°²à±‹ చేసిన మారà±à°ªà±à°²à°¨à± కోలà±à°ªà±‹à°¤à°¾à°°à±. మీరౠఖచà±à°šà°¿à°¤à°‚à°—à°¾ కొనసాగాలనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à°¾?</translation>
<translation id="4476953670630786061">à°ˆ ఫారమౠసà±à°°à°•à±à°·à°¿à°¤à°®à±ˆà°¨à°¦à°¿ కాదà±. ఆటోఫిలౠఆఫౠచేయబడింది.</translation>
<translation id="4477350412780666475">తరà±à°µà°¾à°¤à°¿ à°Ÿà±à°°à°¾à°•à±</translation>
<translation id="4482953324121162758">à°ˆ సైటౠఅనà±à°µà°¦à°¿à°‚చబడదà±.</translation>
@@ -972,6 +997,7 @@
<translation id="4594403342090139922">&amp;తొలగించడానà±à°¨à°¿ à°°à°¦à±à°¦à± చేయి</translation>
<translation id="4597348597567598915">పరిమాణం 8</translation>
<translation id="4600854749408232102">C6/C5 (à°Žà°¨à±à°µà°²à°ªà±)</translation>
+<translation id="4606870351894164739">à°ªà±à°°à°­à°¾à°µà°µà°‚తమైనది</translation>
<translation id="4628948037717959914">ఫోటో</translation>
<translation id="4631649115723685955">à°•à±à°¯à°¾à°·à±â€Œà°¬à±à°¯à°¾à°•à± లింకౠచేయబడింది</translation>
<translation id="4636930964841734540">సమాచారం</translation>
@@ -991,6 +1017,7 @@
<translation id="4691835149146451662">ఆరà±à°•à°¿à°Ÿà±†à°•à±à°šà°°à±-A (à°Žà°¨à±à°µà°²à°ªà±)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">పకà±à°•à°¨</translation>
+<translation id="4702656508969495934">లైవౠకà±à°¯à°¾à°ªà±à°·à°¨à± కనిపిసà±à°¤à±‹à°‚ది, ఫోకసౠచేయడానికి విండో మారà±à°ªà°¿à°¡à°¿à°¨à°¿ ఉపయోగించండి</translation>
<translation id="4708268264240856090">మీ కనెకà±à°·à°¨à±â€Œà°•à± అంతరాయం à°à°°à±à°ªà°¡à°¿à°‚ది</translation>
<translation id="4712404868219726379">Windows Hell</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows నెటà±â€Œà°µà°°à±à°•à± సమసà±à°¯ విశà±à°²à±‡à°·à°£à°²à°¨à± అమలౠచేయడం<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> శోధన సూచన</translation>
<translation id="4742407542027196863">పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à°¨à± నిరà±à°µà°¹à°¿à°‚à°šà±â€¦</translation>
<translation id="4744603770635761495">అమలౠచేయగల పాథà±â€Œ</translation>
+<translation id="4749011317274908093">మీరౠఅజà±à°žà°¾à°¤ మోడà±â€Œà°²à±‹à°•à°¿ వెళà±à°²à°¾à°°à±</translation>
<translation id="4750917950439032686">మీ సమాచారానà±à°¨à°¿ (ఉదాహరణకà±, పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à± లేదా à°•à±à°°à±†à°¡à°¿à°Ÿà± కారà±à°¡à± నంబరà±â€Œà°²à±) à°ˆ సైటà±â€Œà°•à± పంపినపà±à°ªà±à°¡à± అది à°ªà±à°°à±ˆà°µà±‡à°Ÿà±â€Œà°—à°¾ ఉంచబడà±à°¤à±à°‚ది.</translation>
<translation id="4756388243121344051">&amp;à°šà°°à°¿à°¤à±à°°</translation>
<translation id="4758311279753947758">సంపà±à°°à°¦à°¿à°‚పౠసమాచారానà±à°¨à°¿ జోడించà±</translation>
@@ -1033,6 +1061,8 @@
<translation id="4813512666221746211">నెటà±â€Œà°µà°°à±à°•à± à°Žà°°à±à°°à°°à±</translation>
<translation id="4816492930507672669">పేజీకి తగినటà±à°²à± అమరà±à°šà±</translation>
<translation id="4819347708020428563">అదనపౠగమనికలనౠఆటోమేటికౠవీకà±à°·à°£à°²à±‹ ఎడిటౠచేయాలనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à°¾?</translation>
+<translation id="4825507807291741242">శకà±à°¤à°¿à°µà°‚తమైనది</translation>
+<translation id="4838327282952368871">à°¸à±à°µà°ªà±à°¨à°‚ లాంటిది</translation>
<translation id="484462545196658690">ఆటో</translation>
<translation id="4850886885716139402">వీకà±à°·à°£</translation>
<translation id="485316830061041779">జరà±à°®à°¨à±</translation>
@@ -1099,7 +1129,7 @@
<translation id="507130231501693183">మెయిలà±â€Œà°¬à°¾à°•à±à°¸à± 4</translation>
<translation id="5087286274860437796">à°ªà±à°°à°¸à±à°¤à±à°¤à°‚ సరà±à°µà°°à± à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ చెలà±à°²à°¦à±.</translation>
<translation id="5087580092889165836">కారà±à°¡à±â€Œà°¨à± జోడించà±</translation>
-<translation id="5088142053160410913">ఆపరేటరà±â€Œà°•à± సందేశం పంపà±</translation>
+<translation id="5088142053160410913">ఆపరేటరà±â€Œà°•à± మెసేజà±â€Œ పంపà±</translation>
<translation id="5089810972385038852">రాషà±à°Ÿà±à°°à°‚</translation>
<translation id="5093232627742069661">Z-ఫోలà±à°¡à±</translation>
<translation id="5094747076828555589">à°ˆ సరà±à°µà°°à± <ph name="DOMAIN" /> అని నిరూపించà±à°•à±‹à°²à±‡à°•à°ªà±‹à°¯à°¿à°‚ది; దీని à°­à°¦à±à°°à°¤à°¾ à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°¾à°¨à±à°¨à°¿ Chromium విశà±à°µà°¸à°¿à°‚చలేదà±. ఇది తపà±à°ªà±à°—à°¾ కానà±à°«à°¿à°—రౠచేయడం వలన లేదా దాడిచేసే à°µà±à°¯à°•à±à°¤à°¿ మీ కనెకà±à°·à°¨à±â€Œà°•à± అంతరాయం కలిగించడం వలన జరిగి ఉండవచà±à°šà±.</translation>
@@ -1165,10 +1195,11 @@
<translation id="5306593769196050043">రెండౠషీటà±â€Œà°²à±‚</translation>
<translation id="5307166000025436103">సరే</translation>
<translation id="5308380583665731573">కనెకà±à°Ÿà± చేయండి</translation>
-<translation id="5308689395849655368">à°•à±à°°à°¾à°·à± నివేదిక నిలిపివేయ‌బడింది.</translation>
+<translation id="5308689395849655368">à°•à±à°°à°¾à°·à± రిపోరà±à°Ÿà±â€Œ నిలిపివేయ‌బడింది.</translation>
<translation id="5314967030527622926">à°¬à±à°•à±â€Œà°²à±†à°Ÿà± తయారీ దారà±</translation>
<translation id="5316812925700871227">అపసవà±à°¯ దిశలో తిపà±à°ªà±</translation>
<translation id="5317780077021120954">సేవౠచేయి</translation>
+<translation id="5321288445143113935">à°—à°°à°¿à°·à±à° à±€à°•à°°à°¿à°‚చబడింది</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" />లో <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">సంపà±à°°à°¦à°¿à°‚పౠసమాచారానà±à°¨à°¿ à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿</translation>
<translation id="5327248766486351172">పేరà±</translation>
@@ -1176,11 +1207,13 @@
<translation id="5332219387342487447">à°·à°¿à°ªà±à°ªà°¿à°‚గౠపదà±à°§à°¤à°¿</translation>
<translation id="5333022057423422993">డేటా ఉలà±à°²à°‚ఘనలో మీరౠఇపà±à°ªà±à°¡à±‡ ఉపయోగించిన పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± Chrome à°•à°¨à±à°—ొనింది. మీ ఖాతాలనౠసà±à°°à°•à±à°·à°¿à°‚చడానికి, మీ సేవౠచేయబడిన పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à°¨à± చెకౠచేయమని మేమౠసిఫారà±à°¸à± చేసà±à°¤à±à°¨à±à°¨à°¾à°®à±.</translation>
<translation id="5334013548165032829">వివరణాతà±à°®à°• సిసà±à°Ÿà°®à± లాగà±â€Œà°²à±</translation>
+<translation id="5334145288572353250">à°…à°¡à±à°°à°¸à±â€Œà°¨à± సేవౠచేయాలా?</translation>
<translation id="5340250774223869109">యాపౠబà±à°²à°¾à°•à± చేయబడింది</translation>
<translation id="534295439873310000">NFC పరికరాలà±</translation>
<translation id="5344579389779391559">à°ˆ పేజీ మీకౠడబà±à°¬à± ఛారà±à°œà±€ చేయడానికి à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚చవచà±à°šà±</translation>
<translation id="5355557959165512791"><ph name="SITE" /> యొకà±à°• à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ à°°à°¦à±à°¦à± చేయబడినందà±à°¨ మీరౠపà±à°°à°¸à±à°¤à±à°¤à°‚ దీనà±à°¨à°¿ సందరà±à°¶à°¿à°‚చలేరà±. నెటà±â€Œà°µà°°à±à°•à± లోపాలౠమరియౠదాడà±à°²à± సాధారణంగా తాతà±à°•à°¾à°²à°¿à°•à°®à±‡, à°•à°¨à±à°• à°ˆ పేజీ తరà±à°µà°¾à°¤ పని చేయవచà±à°šà±.</translation>
<translation id="536296301121032821">విధాన సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°¨à± నిలà±à°µ చేయడంలో విఫలమైంది</translation>
+<translation id="5363309033720083897">మీ à°…à°¡à±à°®à°¿à°¨à°¿à°¸à±à°Ÿà±à°°à±‡à°Ÿà°°à± à°…à°¨à±à°®à°¤à°¿à°‚à°šà°¿à°¨ సీరియలౠపోరà±à°Ÿà±</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="5386426401304769735">à°ˆ సైటౠసరà±à°Ÿà°¿à°«à°¿à°•à±†à°Ÿà± గొలà±à°¸à±à°²à±‹ SHA-1 ఉపయోగించి సంతకం చేసిన సరà±à°Ÿà°¿à°«à°¿à°•à±†à°Ÿà± ఉంది.</translation>
@@ -1189,6 +1222,7 @@
<translation id="5398772614898833570">à°ªà±à°°à°•à°Ÿà°¨à°²à± à°¬à±à°²à°¾à°•à± చేయబడà±à°¡à°¾à°¯à°¿</translation>
<translation id="5400836586163650660">బూడిద à°°à°‚à°—à±</translation>
<translation id="540969355065856584">à°ˆ సరà±à°µà°°à± <ph name="DOMAIN" /> అని నిరూపించà±à°•à±‹à°²à±‡à°•à°ªà±‹à°¯à°¿à°‚ది; దీని à°­à°¦à±à°°à°¤à°¾ à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ à°ªà±à°°à°¸à±à°¤à±à°¤à°‚ చెలà±à°²à°¦à±. ఇది తపà±à°ªà±à°—à°¾ కానà±à°«à°¿à°—రౠచేయడం వలన లేదా దాడి చేసే à°µà±à°¯à°•à±à°¤à°¿ మీ కనెకà±à°·à°¨à±â€Œà°•à± అంతరాయం కలిగించడం వలన జరిగి ఉండవచà±à°šà±.</translation>
+<translation id="541143247543991491">à°•à±à°²à±Œà°¡à± (సిసà±à°Ÿà°®à± అంతటా)</translation>
<translation id="541416427766103491">à°¸à±à°Ÿà°¾à°•à°°à± 4</translation>
<translation id="5421136146218899937">à°¬à±à°°à±Œà°œà°¿à°‚గౠడేటానౠకà±à°²à°¿à°¯à°°à± చేయి...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> మీకౠనోటిఫికేషనà±â€Œà°²à°¨à± పంపాలనà±à°•à±à°‚టోంది</translation>
@@ -1202,6 +1236,7 @@
<translation id="5455374756549232013">చెలà±à°²à°¨à°¿ విధాన సమయమà±à°¦à±à°°</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" />}other{<ph name="CONTACT_PREVIEW" /> మరియౠమరో <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" />}}</translation>
+<translation id="5463625433003343978">పరికరాలనౠకనà±à°—ొంటోంది...</translation>
<translation id="5469868506864199649">ఇటాలియనà±</translation>
<translation id="5470861586879999274">&amp;సవరించడానà±à°¨à°¿ à°ªà±à°¨à°°à°¾à°µà±ƒà°¤à°‚ చేయి</translation>
<translation id="5478437291406423475">B6/C4 (à°Žà°¨à±à°µà°²à°ªà±)</translation>
@@ -1251,15 +1286,14 @@
<translation id="5624120631404540903">పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à°¨à± నిరà±à°µà°¹à°¿à°‚à°šà°‚à°¡à°¿</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="5644090287519800334">1 వైపౠపà±à°°à°¿à°‚à°Ÿà±â€Œà°²à±‹ à°šà°¿à°¤à±à°°à°¾à°¨à±à°¨à°¿ X à°…à°•à±à°·à°‚లో జరపà±</translation>
<translation id="5645854190134202180">రెండవ à°·à°¿à°«à±à°Ÿà±</translation>
<translation id="5654927323611874862">à°…à°ªà±â€Œà°²à±‹à°¡à± చేసిన à°•à±à°°à°¾à°·à± రిపోరà±à°Ÿà± ID:</translation>
<translation id="5659593005791499971">ఇమెయిలà±</translation>
<translation id="5663614846592581799">9x11 (à°Žà°¨à±à°µà°²à°ªà±)</translation>
-<translation id="5663955426505430495">à°ˆ పరికరం నిరà±à°µà°¾à°¹à°•à±à°¡à± అదనపౠఫంకà±à°·à°¨à±â€Œà°² కోసం à°Žà°•à±à°¸à±â€Œà°Ÿà±†à°¨à±à°·à°¨à±â€Œà°²à°¨à± ఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేసారà±. మీ డేటాలో కొంత భాగానికి à°Žà°•à±à°¸à±â€Œà°Ÿà±†à°¨à±à°·à°¨à±â€Œà°²à± యాకà±à°¸à±†à°¸à± కలిగి ఉంటాయి.</translation>
+<translation id="5663955426505430495">à°ˆ పరికరం నిరà±à°µà°¾à°¹à°•à±à°¡à± అదనపౠఫంకà±à°·à°¨à±â€Œà°² కోసం à°Žà°•à±à°¸à±â€Œà°Ÿà±†à°¨à±à°·à°¨à±â€Œà°²à°¨à± ఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేశారà±. మీ డేటాలో కొంత భాగానికి à°Žà°•à±à°¸à±â€Œà°Ÿà±†à°¨à±à°·à°¨à±â€Œà°²à± యాకà±à°¸à±†à°¸à± కలిగి ఉంటాయి.</translation>
<translation id="5675650730144413517">à°ˆ పేజీ పని చేయడం లేదà±</translation>
<translation id="568292603005599551">à°šà°¿à°¤à±à°°à°‚ యొకà±à°• X కోఆరà±à°¡à°¿à°¨à±‡à°Ÿà±</translation>
<translation id="5684874026226664614">à°…à°¯à±à°¯à±‹. à°ˆ పేజీని à°…à°¨à±à°µà°¦à°¿à°‚à°šà°¡à°‚ సాధà±à°¯à°ªà°¡à°²à±‡à°¦à±.</translation>
@@ -1290,12 +1324,12 @@
<translation id="5785756445106461925">అలాగే, à°ˆ పేజీలో à°¸à±à°°à°•à±à°·à°¿à°¤à°‚ కాని ఇతర వనరà±à°²à± ఉనà±à°¨à°¾à°¯à°¿. à°ˆ వనరà±à°²à°¨à± బదిలీ చేసà±à°¤à±à°¨à±à°¨à°ªà±à°ªà±à°¡à± ఇతరà±à°²à± చూడగలరౠమరియౠదాడికి పాలà±à°ªà°¡à±‡à°µà°¾à°°à± పేజీ రూపానà±à°¨à°¿ మారà±à°šà±‡à°²à°¾ వీటిని సవరించగలరà±.</translation>
<translation id="5786044859038896871">మీరౠమీ కారà±à°¡à± సమాచారం పూరించాలనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à°¾?</translation>
<translation id="578633867165174378">డేటా ఉలà±à°²à°‚ఘనలో మీరౠఇపà±à°ªà±à°¡à±‡ ఉపయోగించిన పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± Chrome à°•à°¨à±à°—ొనింది. ఇపà±à°ªà±à°¡à±‡ à°ˆ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± మారà±à°šà°®à°¨à°¿ మేమౠసిఫారà±à°¸à± చేసà±à°¤à±à°¨à±à°¨à°¾à°®à±.</translation>
-<translation id="5798290721819630480">మారà±à°ªà±à°²à°¨à± విసà±à°®à°°à°¿à°‚చాలా?</translation>
<translation id="5803412860119678065">మీరౠమీ <ph name="CARD_DETAIL" /> కారà±à°¡à± సమాచారం పూరించాలనà±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à°¾?</translation>
<translation id="5804241973901381774">à°…à°¨à±à°®à°¤à±à°²à±</translation>
<translation id="5804427196348435412">NFC పరికరాలనౠఉపయోగించండి</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" />à°•à± à°—à°² మీ కనెకà±à°·à°¨à± వాడà±à°•à°²à±‹ లేని సైఫరౠసూటౠఉపయోగించి à°Žà°¨à±â€Œà°•à±à°°à°¿à°ªà±à°Ÿà± చేయ‌బ‌డింది.</translation>
<translation id="5813119285467412249">&amp;జోడించడానà±à°¨à°¿ à°ªà±à°¨à°°à°¾à°µà±ƒà°¤à°‚ చేయి</translation>
+<translation id="5817918615728894473">జత చేయి</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{మీరౠచెలà±à°²à°¿à°‚చినపà±à°ªà±à°¡à± à°ˆ కారà±à°¡à± ఛారà±à°œà°¿ చేయబడà±à°¤à±à°‚ది, కానీ దాని అసలైన నంబరౠఈ సైటà±â€Œà°¤à±‹ షేరౠచేయబడదà±. అదనపౠభదà±à°°à°¤ కోసం, తాతà±à°•à°¾à°²à°¿à°• CVC జెనరేటౠచేయబడà±à°¤à±à°‚ది.}other{మీరౠచెలà±à°²à°¿à°‚చినపà±à°ªà±à°¡à± మీరౠఎంచà±à°•à±à°¨à±à°¨ కారà±à°¡à± ఛారà±à°œà°¿ చేయబడà±à°¤à±à°‚ది, కానీ దాని అసలైన నంబరౠఈ సైటà±â€Œà°¤à±‹ షేరౠచేయబడదà±. అదనపౠభదà±à°°à°¤ కోసం, తాతà±à°•à°¾à°²à°¿à°• CVC జెనరేటౠచేయబడà±à°¤à±à°‚ది.}}</translation>
<translation id="5826507051599432481">సాధారణ పేరౠ(CN)</translation>
<translation id="5838278095973806738">మీరౠఈ సైటà±â€Œà°²à±‹ ఎలాంటి గోపà±à°¯à°®à±ˆà°¨ సమాచారానà±à°¨à°¿ నమోదౠచేయకూడదౠ(ఉదాహరణకà±, పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à± లేదా à°•à±à°°à±†à°¡à°¿à°Ÿà± కారà±à°¡à±â€Œà°²à±), దాడికి పాలà±à°ªà°¡à±‡à°µà°¾à°°à± à°† సమాచారం దొంగిలించే అవకాశం ఉంటà±à°‚ది.</translation>
@@ -1303,6 +1337,7 @@
<translation id="5855253129151731373">à°ˆ సైటౠయొకà±à°• హోసà±à°Ÿà± పేరౠ<ph name="LOOKALIKE_DOMAIN" /> లాగా ఉంది. దాడి చేసే వారà±, కొనà±à°¨à°¿à°¸à°¾à°°à±à°²à± డొమైనౠపేరà±à°¨à± à°¸à±à°µà°²à±à°ªà°‚à°—à°¾, à°…à°‚à°¤ తేలికగా పసిగటà±à°Ÿà°²à±‡à°¨à°¿ విధంగా మారà±à°šà°¿ నకిలీ సైటà±â€Œà°²à°¨à± రూపొందిసà±à°¤à°¾à°°à±.
ఇది పొరపాటà±à°—à°¾ చూపించబడింది అని మీరౠఅనà±à°•à±à°‚టే, దయచేసి https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals లింకà±â€Œà°¨à± సందరà±à°¶à°¿à°‚à°šà°‚à°¡à°¿.</translation>
+<translation id="5860033963881614850">ఆఫౠఅయà±à°¯à°¿à°‚ది</translation>
<translation id="5862579898803147654">à°¸à±à°Ÿà°¾à°•à°°à± 8</translation>
<translation id="5863847714970149516">మీరౠచూడబోతà±à°¨à±à°¨ పేజీ మీకౠడబà±à°¬à± ఛారà±à°œà± చేయడానికి à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚చవచà±à°šà±</translation>
<translation id="5866257070973731571">ఫోనౠనంబరà±â€Œà°¨à± జోడించండి</translation>
@@ -1319,6 +1354,7 @@
<translation id="5913377024445952699">à°¸à±à°•à±à°°à±€à°¨à±â€Œà°¨à± à°•à±à°¯à°¾à°ªà±à°šà°°à± చేయడం పాజౠచేయబడింది</translation>
<translation id="59174027418879706">à°ªà±à°°à°¾à°°à°‚భించబడింది</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 వినియోగంలో ఉంది}other{# వినియోగంలో ఉనà±à°¨à°¾à°¯à°¿}}</translation>
<translation id="5921185718311485855">ఆనౠచేయబడà±à°¡à°¾à°¯à°¿</translation>
<translation id="5921639886840618607">Google ఖాతాకౠకారà±à°¡à±â€Œà°¨à± సేవౠచేయాలా?</translation>
<translation id="5922853866070715753">దాదాపౠపూరà±à°¤à°¯à°¿à°‚ది</translation>
@@ -1327,7 +1363,7 @@
<translation id="5946937721014915347"><ph name="SITE_NAME" /> తెరవబడà±à°¤à±‹à°‚ది…</translation>
<translation id="5951495562196540101">వినియోగదారౠఖాతాతో నమోదౠచేయడం సాధà±à°¯à°ªà°¡à°¦à± (à°ªà±à°¯à°¾à°•à±‡à°œà±à°¡à± లైసెనà±à°¸à± à°…à°‚à°¦à±à°¬à°¾à°Ÿà±à°²à±‹ ఉంది).</translation>
<translation id="5963413905009737549">విభాగం</translation>
-<translation id="5967592137238574583">సంపà±à°°à°¦à°¿à°‚పౠసమాచారానà±à°¨à°¿ సవరించండి</translation>
+<translation id="5967592137238574583">సంపà±à°°à°¦à°¿à°‚పౠసమాచారానà±à°¨à°¿ ఎడిటౠచేయండి</translation>
<translation id="5967867314010545767">à°šà°°à°¿à°¤à±à°° à°¨à±à°‚à°¡à°¿ తీసివేయి</translation>
<translation id="5968793460449681917">à°ªà±à°°à°¤à°¿ సందరà±à°¶à°¨à°²à±‹</translation>
<translation id="5975083100439434680">దూరంగా జూమౠచేయి</translation>
@@ -1338,6 +1374,7 @@
<translation id="5989320800837274978">à°¸à±à°¥à°¿à°° à°ªà±à°°à°¾à°•à±à°¸à±€ సరà±à°µà°°à±â€Œà°²à± లేదా à°’à°• .pac à°¸à±à°•à±à°°à°¿à°ªà±à°Ÿà± URL పేరà±à°•à±Šà°¨à°¬à°¡à°²à±‡à°¦à±.</translation>
<translation id="5992691462791905444">ఇంజినీరింగౠ'Z' ఫోలà±à°¡à±</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' అనే దానికి <ph name="RESULT_COUNT" /> ఫలితాలౠలభించాయి</translation>
+<translation id="6006484371116297560">à°•à±à°²à°¾à°¸à°¿à°•à±</translation>
<translation id="6008122969617370890">N-à°¨à±à°‚à°¡à°¿-1 వరకౠఉనà±à°¨ à°•à±à°°à°®à°‚</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à°¨à± తనిఖీ చేయండి</translation>
@@ -1359,6 +1396,7 @@
<translation id="6045164183059402045">ఇంపోజిషనౠటెంపà±à°²à±‡à°Ÿà±</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="6049004884579590341">పూరà±à°¤à°¿ à°¸à±à°•à±à°°à±€à°¨à± à°¨à±à°‚à°¡à°¿ నిషà±à°•à±à°°à°®à°¿à°‚చడానికి |<ph name="ACCELERATOR" />|ని నొకà±à°•à°¿, పటà±à°Ÿà±à°•à±‹à°‚à°¡à°¿</translation>
<translation id="6049488691372270142">పేజీ డెలివరీ</translation>
<translation id="6051221802930200923">స‌రà±à°Ÿà°¿à°«à°¿à°•à±†à°Ÿà±â€Œà°¨à± పినౠచేసే పదà±à°§à°¤à°¿à°¨à°¿ వెబà±â€Œà°¸à±ˆà°Ÿà± ఉపయోగిసà±à°¤à±à°‚ది. à°•à°¨à±à°• మీరౠపà±à°°à°¸à±à°¤à±à°¤à°¾à°¨à°¿à°•à°¿ <ph name="SITE" />‌నౠసందరà±à°¶à°¿à°‚చలేరà±. నెటà±â€Œà°µà°°à±à°•à± à°Žà°°à±à°°â€Œà°°à±â€Œà°²à± మరియౠదాడà±à°²à± సాధారణంగా తాతà±à°•à°¾à°²à°¿à°•à°®à±‡, à°•à°¨à±à°• à°ˆ పేజీ తరà±à°µà°¾à°¤ పని చేయవచà±à°šà±.</translation>
<translation id="6051898664905071243">పేజీల సంఖà±à°¯:</translation>
@@ -1367,7 +1405,7 @@
<translation id="6059925163896151826">USB పరికరాలà±</translation>
<translation id="6060009363608157444">చెలà±à°²à°¨à°¿ DnsOverHttps మోడà±.</translation>
<translation id="6064217302520318294">à°¸à±à°•à±à°°à±€à°¨à± లాకà±</translation>
-<translation id="6080696365213338172">మీరౠనిరà±à°µà°¾à°¹à°•à±à°¨à°¿ à°¦à±à°µà°¾à°°à°¾ అందించబడిన à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°¾à°¨à±à°¨à°¿ ఉపయోగించి కంటెంటà±â€Œà°¨à± యాకà±à°¸à±†à°¸à± చేసారà±. మీరౠ<ph name="DOMAIN" />కౠఅందించే డేటాకౠమీ నిరà±à°µà°¾à°¹à°•à±à°¨à°¿ à°¦à±à°µà°¾à°°à°¾ అంతరాయం à°à°°à±à°ªà°¡à°µà°šà±à°šà±.</translation>
+<translation id="6080696365213338172">మీరౠనిరà±à°µà°¾à°¹à°•à±à°¨à°¿ à°¦à±à°µà°¾à°°à°¾ అందించబడిన à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°¾à°¨à±à°¨à°¿ ఉపయోగించి కంటెంటà±â€Œà°¨à± యాకà±à°¸à±†à°¸à± చేశారà±. మీరౠ<ph name="DOMAIN" />కౠఅందించే డేటాకౠమీ నిరà±à°µà°¾à°¹à°•à±à°¨à°¿ à°¦à±à°µà°¾à°°à°¾ అంతరాయం à°à°°à±à°ªà°¡à°µà°šà±à°šà±.</translation>
<translation id="6094273045989040137">అదనపౠగమనికనౠజోడించండి</translation>
<translation id="6104072995492677441">JIS B6</translation>
<translation id="6106989379647458772"><ph name="PAGE" />లోని వెబà±â€Œà°ªà±‡à°œà±€ తాతà±à°•à°¾à°²à°¿à°•à°‚à°—à°¾ నిలిపివేయబడి ఉండవచà±à°šà± లేదా ఇది శాశà±à°µà°¤à°‚à°—à°¾ కొతà±à°¤ వెబౠచిరà±à°¨à°¾à°®à°¾à°•à± తరలించబడి ఉండవచà±à°šà±.</translation>
@@ -1375,6 +1413,7 @@
<translation id="610911394827799129">మీ Google ఖాతా <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />లో ఇతర రూపాలà±à°²à±‹ ఉనà±à°¨ à°¬à±à°°à±Œà°œà°¿à°‚à°—à± à°šà°°à°¿à°¤à±à°°à°¨à± కలిగి ఉండవచà±à°šà±</translation>
<translation id="6116338172782435947">à°•à±à°²à°¿à°ªà±â€Œà°¬à±‹à°°à±à°¡à±â€Œà°•à± కాపీ చేసిన వచనం మరియౠచితà±à°°à°¾à°²à°¨à± చూడండి</translation>
<translation id="6120179357481664955">మీ UPI ID à°—à±à°°à±à°¤à±à°‚దా?</translation>
+<translation id="6123290840358279103">వరà±à°šà±à°µà°²à± కారà±à°¡à±â€Œà°¨à± చూడండి</translation>
<translation id="6124432979022149706">Chrome Enterprise కనెకà±à°Ÿà°°à±â€Œà°²à±</translation>
<translation id="6146055958333702838">à°à°µà±ˆà°¨à°¾ కేబà±à°²à±â€Œà°²à°¨à± తనిఖీ చేయండి మరియౠమీరౠఉపయోగించే à°à°µà±ˆà°¨à°¾ రూటరà±â€Œà°²à±, మోడెమà±â€Œà°²à±
లేదా ఇతర నెటà±â€Œà°µà°°à±à°•à± పరికరాలనౠరీబూటౠచేయండి.</translation>
@@ -1411,6 +1450,7 @@
<translation id="6289939620939689042">పేజీ à°°à°‚à°—à±</translation>
<translation id="6290238015253830360">మీకౠసూచించిన కథనాలౠఇకà±à°•à°¡ కనిపిసà±à°¤à°¾à°¯à°¿</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chromeలో Google అసిసà±à°Ÿà±†à°‚టౠఆపివేయబడà±à°¤à±‹à°‚ది</translation>
<translation id="6305205051461490394"><ph name="URL" />ని చేరà±à°•à±‹à°²à±‡à°•à°ªà±‹à°¯à°¾à°®à±.</translation>
<translation id="6312113039770857350">వెబà±â€Œà°ªà±‡à°œà±€ à°…à°‚à°¦à±à°¬à°¾à°Ÿà±à°²à±‹ లేదà±</translation>
@@ -1436,6 +1476,7 @@
<translation id="6390200185239044127">'Z' ఆకారంలో సగం ఫోలà±à°¡à±</translation>
<translation id="6390662030813198813">ఇంజనీరింగà±-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> à°¨à±à°‚à°¡à°¿ à°ˆ లొకేషనà±â€Œà°²à±‹ పేసà±à°Ÿà± చేయడం à°…à°¡à±à°®à°¿à°¨à°¿à°¸à±à°Ÿà±à°°à±‡à°Ÿà°°à± పాలసీ à°¦à±à°µà°¾à°°à°¾ à°¬à±à°²à°¾à°•à± చేయబడింది</translation>
+<translation id="6398765197997659313">పూరà±à°¤à°¿ à°¸à±à°•à±à°°à±€à°¨à± à°¨à±à°‚à°¡à°¿ నిషà±à°•à±à°°à°®à°¿à°‚à°šà±</translation>
<translation id="6401136357288658127">à°ˆ విధానం విసà±à°®à°°à°¿à°‚చబడింది. దానికి బదà±à°²à±à°—à°¾, మీరౠ<ph name="NEW_POLICY" /> విధానానà±à°¨à°¿ ఉపయోగించాలి.</translation>
<translation id="6404511346730675251">à°¬à±à°•à±â€Œà°®à°¾à°°à±à°•à±â€Œà°¨à± సవరించà±</translation>
<translation id="6406765186087300643">C0 (à°Žà°¨à±à°µà°²à°ªà±)</translation>
@@ -1446,9 +1487,8 @@
<translation id="6425092077175753609">విశిషà±à°Ÿà°‚</translation>
<translation id="6427730057873428458">గేటౠఫోలà±à°¡à±</translation>
<translation id="6428450836711225518">మీ ఫోనౠనంబరà±â€Œà°¨à± ధృవీకరించండి</translation>
-<translation id="6433490469411711332">సంపà±à°°à°¦à°¿à°‚పౠసమాచారానà±à°¨à°¿ సవరించండి</translation>
+<translation id="6433490469411711332">సంపà±à°°à°¦à°¿à°‚పౠసమాచారానà±à°¨à°¿ ఎడిటౠచేయండి</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> కనెకà±à°Ÿà± కావడానికి నిరాకరించింది.</translation>
-<translation id="6434309073475700221">తొలగించà±</translation>
<translation id="6440503408713884761">విసà±à°®à°°à°¿à°‚చబడింది</translation>
<translation id="6443406338865242315">à° à°Žà°•à±à°¸à±â€Œà°Ÿà±†à°¨à±à°·à°¨à±â€Œà°²à± మరియౠపà±à°²à°—à°¿à°¨à±â€Œà°²à°¨à± మీరౠఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేశారà±</translation>
<translation id="6446163441502663861">Kahu (à°Žà°¨à±à°µà°²à°ªà±)</translation>
@@ -1491,7 +1531,8 @@
<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="6630043285902923878">USB పరికరాలనౠకనà±à°—ొంటోంది...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">à°•à±à°²à°¿à°¯à°°à± చేయి</translation>
<translation id="6645291930348198241">à°•à±à°•à±à°•à±€à°²à°¨à±, సైటౠడేటానౠయాకà±à°¸à±†à°¸à± చేయాలనà±à°•à±à°‚టోంది.</translation>
@@ -1506,6 +1547,7 @@
<translation id="6671697161687535275">Chromium à°¨à±à°‚à°¡à°¿ ఫారమౠసూచననౠతీసివేయాలా?</translation>
<translation id="6685834062052613830">సైనౠఅవà±à°Ÿà± చేసి, సెటపà±â€Œà°¨à± పూరà±à°¤à°¿ చేయండి</translation>
<translation id="6687335167692595844">à°…à°­à±à°¯à°°à±à°¥à°¿à°‚చబడిన ఫాంటౠపరిమాణం</translation>
+<translation id="6688743156324860098">à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేయి…</translation>
<translation id="6689249931105087298">సంబంధిత à°¬à±à°²à°¾à°•à± పాయింటౠకంపà±à°°à±†à°·à°¨à±</translation>
<translation id="6689271823431384964">మీరౠసైనౠఇనౠచేసి ఉనà±à°¨à°‚à°¦à±à°¨, మీ కారà±à°¡à±â€Œà°²à°¨à± మీ Google ఖాతాలో సేవౠచేసà±à°•à±‹à°—à°² అవకాశానà±à°¨à°¿ Chrome మీకౠఅందిసà±à°¤à±‹à°‚ది. మీరౠసెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹ à°ˆ à°ªà±à°°à°µà°°à±à°¤à°¨à°¨à± మారà±à°šà°µà°šà±à°šà±. కారà±à°¡à±à°¦à°¾à°°à±à°¡à°¿ పేరౠమీ ఖాతా à°¨à±à°‚à°¡à°¿ అందించబడింది.</translation>
<translation id="6698381487523150993">సృషà±à°Ÿà°¿à°‚చబడింది:</translation>
@@ -1521,6 +1563,7 @@
<translation id="6744009308914054259">కనెకà±à°·à°¨à± కోసం వేచి ఉనà±à°¨à°ªà±à°ªà±à°¡à±, మీరౠఆఫà±â€Œà°²à±ˆà°¨à± కథనాలనౠచదవడానికి డౌనà±â€Œà°²à±‹à°¡à±â€Œà°²à°¨à± సందరà±à°¶à°¿à°‚చవచà±à°šà±.</translation>
<translation id="6753269504797312559">విధానం విలà±à°µ</translation>
<translation id="6757797048963528358">మీ పరికరం నిదà±à°°à°¾à°µà°¸à±à°¥à°•à± వెళà±à°²à°¿à°‚ది.</translation>
+<translation id="6767985426384634228">à°…à°¡à±à°°à°¸à±â€Œà°¨à± à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేయాలా?</translation>
<translation id="6768213884286397650">హగకి (పోసà±à°Ÿà±â€Œà°•à°¾à°°à±à°¡à±)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">నీలి ఊదా à°°à°‚à°—à±</translation>
@@ -1543,6 +1586,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">మరింత తేలికగా చదవడానికి వీలà±à°—à°¾ Chrome à°ˆ పేజీని à°¸à±à°²à°­à°¤à°°à°‚ చేసింది. à°¸à±à°°à°•à±à°·à°¿à°¤à°‚ కాని కనెకà±à°·à°¨à± à°¦à±à°µà°¾à°°à°¾ Chrome అసలౠపేజీని తిరిగి పొందింది.</translation>
<translation id="6891596781022320156">విధాన à°¸à±à°¥à°¾à°¯à°¿à°•à°¿ మదà±à°¦à°¤à± లేదà±.</translation>
+<translation id="6895143722905299846">వరà±à°šà±à°µà°²à± నంబరà±:</translation>
<translation id="6895330447102777224">మీ కారà±à°¡à± నిరà±à°§à°¾à°°à°¿à°‚చబడింది</translation>
<translation id="6897140037006041989">వినియోగదారౠపà±à°°à°¤à°¿à°¨à°¿à°§à°¿</translation>
<translation id="6898699227549475383">సంసà±à°¥ (O)</translation>
@@ -1551,7 +1595,7 @@
<translation id="691325982945105493">Google డాకౠబటనà±â€Œà°¨à± à°•à±à°°à°¿à°¯à±‡à°Ÿà± చేయండి, కొతà±à°¤ Google డాకà±â€Œà°¨à± à°¤à±à°µà°°à°—à°¾ à°•à±à°°à°¿à°¯à±‡à°Ÿà± చేయడానికి Enterనౠనొకà±à°•à°‚à°¡à°¿</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>
+<translation id="6944692733090228304"><ph name="BEGIN_BOLD" /><ph name="ORG_NAME" /><ph name="END_BOLD" /> నిరà±à°µà°¹à°¿à°‚చని à°’à°• సైటà±â€Œà°²à±‹ మీరౠమీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à°¿ నమోదౠచేశారà±. మీ ఖాతాని à°°à°•à±à°·à°¿à°‚à°šà°¡à°‚ కోసం, మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à°¿ ఇతర యాపà±â€Œà°²à± మరియౠసైటà±â€Œà°²à°²à±‹ తిరిగి ఉపయోగించవదà±à°¦à±.</translation>
<translation id="6945221475159498467">à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿</translation>
<translation id="6948051842255602737">గేమౠపూరà±à°¤à°¯à°¿à°‚ది, మీ à°¸à±à°•à±‹à°°à± <ph name="SCORE" />.</translation>
<translation id="6948701128805548767">పికపౠపదà±à°§à°¤à±à°²à± మరియౠఅవసరాలనౠచూడాలంటే, à°šà°¿à°°à±à°¨à°¾à°®à°¾à°¨à°¿ à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿</translation>
@@ -1578,10 +1622,10 @@
<translation id="7004583254764674281">కారà±à°¡à±â€Œà°²à°¨à± వేగంగా నిరà±à°§à°¾à°°à°¿à°‚చడానికి Windows Helloనౠఉపయోగించండి</translation>
<translation id="7006930604109697472">à°à°¦à±‡à°®à±ˆà°¨à°¾ పంపà±</translation>
<translation id="7012363358306927923">చైనా యూనియనౠపే</translation>
-<translation id="7012404007611495949">సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°² పరిమాణం మారà±à°šà±</translation>
<translation id="7014741021609395734">జూమౠసà±à°¥à°¾à°¯à°¿</translation>
<translation id="7016992613359344582">à°ˆ ఛారà±à°œà±â€Œà°²à± ఒకే సారి చెలà±à°²à°¿à°‚చేవి లేదా à°ªà±à°¨à°°à°¾à°µà±ƒà°¤à°‚à°—à°¾ చెలà±à°²à°¿à°‚చాలà±à°¸à°¿à°¨à°µà°¿ కావచà±à°šà± మరియౠసà±à°ªà°·à±à°Ÿà°‚à°—à°¾ పేరà±à°•à±Šà°¨à°¬à°¡à°•à°ªà±‹à°µà°šà±à°šà±.</translation>
<translation id="7029809446516969842">పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à±</translation>
+<translation id="7030436163253143341">సరà±à°Ÿà°¿à°«à°¿à°•à±†à°Ÿà± చెలà±à°²à°¦à±</translation>
<translation id="7031646650991750659">à° Google Play యాపà±â€Œà°²à± మీరౠఇనà±â€Œà°¸à±à°Ÿà°¾à°²à± చేశారà±</translation>
<translation id="7050187094878475250">మీరౠ<ph name="DOMAIN" />నౠచేరà±à°•à±‹à°µà°¡à°¾à°¨à°¿à°•à°¿ à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚చారà±, కానీ సరà±à°µà°°à± అందించిన à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ విశà±à°µà°¸à°¿à°‚చలేనంత à°Žà°•à±à°•à±à°µ చెలà±à°²à±à°¬à°¾à°Ÿà± à°µà±à°¯à°µà°§à°¿à°¨à°¿ కలిగి ఉంది.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{à°ªà±à°°à°¸à±à°¤à±à°¤à°‚ à°ˆ కారà±à°¡à±â€Œà°¨à°¿ సేవౠచేయలేరà±}other{à°ªà±à°°à°¸à±à°¤à±à°¤à°‚ à°ˆ కారà±à°¡à±â€Œà°²à°¨à°¿ సేవౠచేయలేరà±}}</translation>
@@ -1651,12 +1695,14 @@
<translation id="7300012071106347854">నలà±à°² కావిరాయి నీలం</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">అధికం</translation>
+<translation id="7305756307268530424">నెమà±à°®à°¦à°¿à°—à°¾ à°ªà±à°°à°¾à°°à°‚à°­à°¿à°‚à°šà°‚à°¡à°¿</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">కనెకà±à°·à°¨à± సహాయం</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" విభాగానà±à°¨à°¿ దాచà±</translation>
<translation id="733354035281974745">పరికర à°¸à±à°¥à°¾à°¨à°¿à°• ఖాతా à°­à°°à±à°¤à±€</translation>
<translation id="7333654844024768166">మీరౠమోసపూరితమైన సైటà±â€Œà°²à±‹ మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఎంటరౠచేశారà±. మీరౠఈ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఉపయోగించిన <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ఇతర సైటà±â€Œà°²à°•à± ఇపà±à°ªà±à°¡à±‡ వెళà±à°²à°¿, దానà±à°¨à°¿ మారà±à°šà°¾à°²à±à°¸à°¿à°‚దిగా Chromium సిఫారà±à°¸à± చేసà±à°¤à±‹à°‚ది.</translation>
<translation id="7334320624316649418">&amp;మళà±à°²à±€ à°•à±à°°à°®à°‚ చేయడానà±à°¨à°¿ à°ªà±à°¨à°°à°¾à°µà±ƒà°¤à°‚ చేయి</translation>
+<translation id="7337248890521463931">మరినà±à°¨à°¿ వరà±à°¸à°²à°¨à± చూపించà±</translation>
<translation id="7337706099755338005">మీ à°ªà±à°²à°¾à°Ÿà±â€Œà°«à°¾à°°à°®à±â€Œà°²à±‹ à°…à°‚à°¦à±à°¬à°¾à°Ÿà±à°²à±‹ లేదà±.</translation>
<translation id="733923710415886693">సరà±à°µà°°à± à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°¾à°¨à±à°¨à°¿ à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ పారదరà±à°¶à°•à°¤ à°¦à±à°µà°¾à°°à°¾ బహిరంగపరచలేదà±.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1664,6 +1710,7 @@
<translation id="7349430561505560861">A4-అదనం</translation>
<translation id="7353601530677266744">ఆదేశ పంకà±à°¤à°¿</translation>
<translation id="7359588939039777303">à°ªà±à°°à°•à°Ÿà°¨à°²à± à°¬à±à°²à°¾à°•à± చేయబడà±à°¡à°¾à°¯à°¿.</translation>
+<translation id="7363096869660964304">అయితే, మీరౠకనిపించకà±à°‚à°¡à°¾ ఉండరà±. à°…à°œà±à°žà°¾à°¤à°‚లోకి వెళà±à°²à°¡à°‚ వలన మీ à°¬à±à°°à±Œà°œà°¿à°‚గౠమీ ఉపాధి సంసà±à°¥à°•à±, మీ ఇంటరà±à°¨à±†à°Ÿà± సరà±à°µà±€à°¸à± à°ªà±à°°à±Šà°µà±ˆà°¡à°°à±â€Œà°•à± లేదా మీరౠసందరà±à°¶à°¿à°‚చే వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°²à°•à± కనిపించకà±à°‚à°¡à°¾ దాచబడదà±.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹ à°…à°¡à±à°°à°¸à±â€Œà°²à°¨à± జోడించడానికి, మేనేజౠచేయడానికి 'Tab'నౠనొకà±à°•à°¿, ఆపై 'Enter'నౠనొకà±à°•à°‚à°¡à°¿</translation>
<translation id="7365849542400970216">మీ పరికరానà±à°¨à°¿ ఎలా ఉపయోగించాలో తెలà±à°¸à±à°•à±‹à°µà°¾à°²à°¨à±à°•à±à°‚à°Ÿà±à°¨à±à°¨à°¾à°°à°¾?</translation>
<translation id="7372973238305370288">శోధన ఫలితం</translation>
@@ -1674,14 +1721,16 @@
<translation id="7378594059915113390">మీడియా నియంతà±à°°à°£à°²à±</translation>
<translation id="7378627244592794276">వదà±à°¦à±</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">వరà±à°¤à°¿à°‚à°šà°¦à±</translation>
<translation id="7390545607259442187">కారà±à°¡à±â€Œà°¨à°¿ నిరà±à°§à°¾à°°à°¿à°‚à°šà°‚à°¡à°¿</translation>
+<translation id="7392089738299859607">à°…à°¡à±à°°à°¸à±â€Œà°¨à± à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేయండి</translation>
<translation id="7399802613464275309">à°­à°¦à±à°°à°¤à°¾ చెకà±-à°…à°ªà±</translation>
<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;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;నౠకà±à°²à°¿à°•à± చేసి, ఆపై &lt;strong&gt;"à°¸à±à°¥à°¾à°¨à°¿à°• సేవ‌లౠచూడండి"&lt;/strong&gt; కోసం వెతికి, దానిని à°Žà°‚à°šà±à°•à±‹à°‚à°¡à°¿
&lt;li&gt;&lt;strong&gt;VisualDiscovery&lt;/strong&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;లో, &lt;strong&gt;ఆపివేయి&lt;/strong&gt;ని à°•à±à°²à°¿à°•à± చేయండి
@@ -1689,6 +1738,7 @@
&lt;li&gt;మీ à°•à°‚à°ªà±à°¯à±‚à°Ÿà°°à± à°¨à±à°‚à°¡à°¿ శాశà±à°µà°¤à°‚à°—à°¾ సాఫà±à°Ÿà±â€Œà°µà±‡à°°à±â€Œà°¨à± ఎలా తొలగించాలో తెలà±à°¸à±à°•à±‹à°µà°¡à°¾à°¨à°¿à°•à°¿ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome సహాయ కేందà±à°°à°‚&lt;/a&gt;నౠసందరà±à°¶à°¿à°‚à°šà°‚à°¡à°¿
&lt;/ol&gt;</translation>
<translation id="741007362987735528">వెడలà±à°ªà±ˆà°¨-ఫారà±à°®à°¾à°Ÿà±</translation>
+<translation id="7410471291937727359">అందమైనది</translation>
<translation id="7416351320495623771">పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à°¨à± నిరà±à°µà°¹à°¿à°‚చండి…</translation>
<translation id="7419106976560586862">à°ªà±à°°à±Šà°«à±ˆà°²à± మారà±à°—à°‚</translation>
<translation id="7437289804838430631">సంపà±à°°à°¦à°¿à°‚పౠసమాచారానà±à°¨à°¿ జోడించà±</translation>
@@ -1704,7 +1754,7 @@
<translation id="7481312909269577407">ఫారà±à°µà°°à±à°¡à±</translation>
<translation id="7485870689360869515">డేటా à°•à°¨à±à°—ొనబడలేదà±.</translation>
<translation id="7495528107193238112">à°ˆ కంటెంటౠబà±à°²à°¾à°•à± అయింది. à°ˆ సమసà±à°¯ పరిషà±à°•à°¾à°°à°‚ కోసం సైటౠఓనరà±â€Œà°¨à± సంపà±à°°à°¦à°¿à°‚à°šà°‚à°¡à°¿.</translation>
-<translation id="7498234416455752244">సవరణనౠకొనసాగించà±</translation>
+<translation id="7498193950643227031">పరిమాణం మారà±à°šà°¬à°¡à°¿à°¨à°Ÿà±à°²à°¯à°¿à°¤à±‡, అది à°…à°¨à±à°•à±‹à°¨à°¿à°µà°¿à°§à°‚à°—à°¾ à°ªà±à°°à°µà°°à±à°¤à°¿à°‚చవచà±à°šà±. <ph name="SETTINGS" />లో మీరౠఇపà±à°ªà±à°¡à± యాపà±â€Œà°² పరిమాణం మారà±à°šà±‡ సామరà±à°¥à±à°¯à°¾à°¨à±à°¨à°¿ పరిమితి చేయవచà±à°šà±.</translation>
<translation id="7503664977220660814">మీరౠమోసపూరితమైన సైటà±â€Œà°²à±‹ మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఎంటరౠచేశారà±. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, ఇతర సైటà±â€Œà°²à°²à±‹ à°ªà±à°°à°¸à±à°¤à±à°¤à°‚ మీరౠఎకà±à°•à°¡à±ˆà°¤à±‡ à°ˆ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఉపయోగిసà±à°¤à°¾à°°à±‹, à°…à°•à±à°•à°¡ మీ సేవౠచేసిన పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à°¨à± తనిఖీ చేసà±à°•à±‹à°®à°¨à°¿ Chromium సిఫారà±à°¸à± చేసà±à°¤à±‹à°‚ది.</translation>
<translation id="7508255263130623398">అందించబడిన విధాన పరికర id ఖాళీగా ఉంది లేదా à°ªà±à°°à°¸à±à°¤à±à°¤ పరికర idà°•à°¿ సరిపోలలేదà±</translation>
<translation id="7508870219247277067">వెనà±à°¨à°ªà°‚డౠఆకà±à°ªà°šà±à°š</translation>
@@ -1724,6 +1774,7 @@
<translation id="7548892272833184391">కనెకà±à°·à°¨à± à°Žà°°à±à°°à°°à±â€Œà°²à°¨à± పరిషà±à°•à°°à°¿à°‚à°šà°‚à°¡à°¿</translation>
<translation id="7549584377607005141">à°ˆ వెబà±â€Œà°ªà±‡à°œà±€ సరిగà±à°—à°¾ à°ªà±à°°à°¦à°°à±à°¶à°¿à°‚చబడటానికి మీరౠమà±à°¨à±à°ªà± నమోదౠచేసిన డేటా అవసరం. మీరౠఈ డేటానౠమళà±à°²à±€ పంపవచà±à°šà±. కానీ అలా చేయడం వ‌లà±à°²â€Œ à°ˆ పేజీ à°®à±à°¨à±à°ªà± à°ªà±à°°à°¦à°°à±à°¶à°¿à°‚à°šà°¿à°¨ à°à°¦à±ˆà°¨à°¾ à°šà°°à±à°¯ à°ªà±à°¨à°°à°¾à°µà±ƒà°¤à°‚ కావచà±à°šà±.</translation>
<translation id="7550637293666041147">మీ పరికరం వినియోగదారౠపేరౠమరియౠChrome వినియోగదారౠపేరà±</translation>
+<translation id="755279583747225797">à°Ÿà±à°°à°¯à°²à± యాకà±à°Ÿà°¿à°µà±â€Œà°—à°¾ ఉంది</translation>
<translation id="7552846755917812628">à°•à±à°°à°¿à°‚ది à°šà°¿à°Ÿà±à°•à°¾à°²à°¨à± à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚à°šà°‚à°¡à°¿:</translation>
<translation id="7554475479213504905">à°à°¦à±‡à°®à±ˆà°¨à°¾ రీలోడౠచేసి, చూపà±</translation>
<translation id="7554791636758816595">కొతà±à°¤ à°Ÿà±à°¯à°¾à°¬à±</translation>
@@ -1732,7 +1783,7 @@
<translation id="7569952961197462199">Chrome à°¨à±à°‚à°¡à°¿ à°•à±à°°à±†à°¡à°¿à°Ÿà± కారà±à°¡à±â€Œà°¨à± తీసివేయాలా?</translation>
<translation id="7569983096843329377">నలà±à°ªà±</translation>
<translation id="7575207903026901870">సూచన బటనà±â€Œà°¨à± తీసివేసి, à°ˆ సూచననౠతీసివేయడానికి ఎంటరౠనొకà±à°•à°‚à°¡à°¿</translation>
-<translation id="7578104083680115302">మీరౠGoogleతో సేవౠచేసిన కారà±à°¡à±â€Œà°²à°¨à± ఉపయోగించి పరికరాలà±à°²à±‹à°¨à°¿ సైటà±â€Œà°²à± మరియౠఅనà±à°µà°°à±à°¤à°¨à°¾à°²à±à°²à±‹ శీఘà±à°°à°‚à°—à°¾ చెలà±à°²à°¿à°‚à°šà°‚à°¡à°¿.</translation>
+<translation id="7578104083680115302">మీరౠGoogleతో సేవౠచేసిన కారà±à°¡à±â€Œà°²à°¨à± ఉపయోగించి పరికరాలà±à°²à±‹à°¨à°¿ సైటà±â€Œà°²à± మరియౠఅనà±à°µà°°à±à°¤à°¨à°¾à°²à±à°²à±‹ శీఘà±à°°à°‚à°—à°¾ పేమెంటౠచేయండి.</translation>
<translation id="7581199239021537589">2à°µ వైపౠపà±à°°à°¿à°‚à°Ÿà±â€Œà°²à±‹ à°šà°¿à°¤à±à°°à°¾à°¨à±à°¨à°¿ Y à°…à°•à±à°·à°‚లో జరపà±</translation>
<translation id="7591636454931265313"><ph name="TOP_LEVEL_URL" />లోని à°•à±à°•à±à°•à±€à°²à°¨à±, సైటౠడేటానౠవినియోగించడానికి <ph name="EMBEDDED_URL" /> à°…à°¨à±à°®à°¤à°¿ à°…à°¡à±à°—à±à°¤à±‹à°‚ది</translation>
<translation id="7592362899630581445">సరà±à°µà°°à± యొకà±à°• à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ పేరౠపరిమితà±à°²à°¨à± ఉలà±à°²à°‚ఘిసà±à°¤à±‹à°‚ది.</translation>
@@ -1742,17 +1793,16 @@
<translation id="7610193165460212391">విలà±à°µ <ph name="VALUE" /> పరిధి వెలà±à°ªà°² ఉంది.</translation>
<translation id="7613889955535752492">à°—à°¡à±à°µà± à°®à±à°—à°¿à°‚à°ªà±: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹ మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à°¨à± చూసి, మేనేజౠచేయడానికి 'Tab'నౠనొకà±à°•à°¿, ఆపై 'Enter'నౠనొకà±à°•à°‚à°¡à°¿</translation>
-<translation id="7615602087246926389">మీకౠఇపà±à°ªà°Ÿà°¿à°•à±‡ మీ Google ఖాతా పాసà±â€Œà°µà°°à±à°¡à± యొకà±à°• మరొక వెరà±à°·â€Œà°¨à±â€Œà°¨à± ఉపయోగించి à°Žà°¨à±â€Œà°•à±à°°à°¿à°ªà±à°Ÿà± అయిన డేటా ఉంది. దయచేసి దానà±à°¨à°¿ దిగà±à°µ నమోదౠచేయండి.</translation>
<translation id="7616645509853975347">మీ à°…à°¡à±à°®à°¿à°¨à°¿à°¸à±à°Ÿà±à°°à±‡à°Ÿà°°à±, మీ à°¬à±à°°à±Œà°œà°°à±â€Œà°²à±‹ Chrome Enterprise కనెకà±à°Ÿà°°à±â€Œà°²à°¨à± ఆనౠచేశారà±. à°ˆ కనెకà±à°Ÿà°°à±â€Œà°²à°•à± మీ డేటాలో కొంత డేటాకౠయాకà±à°¸à±†à°¸à± ఉంది.</translation>
<translation id="7619838219691048931">చివరి షీటà±</translation>
<translation id="762844065391966283">ఒకసారికి ఒకటి</translation>
-<translation id="7633909222644580952">పనితీరౠడేటా, à°•à±à°°à°¾à°·à± నివేదికలà±</translation>
+<translation id="7633909222644580952">పనితీరౠడేటా, à°•à±à°°à°¾à°·à± రిపోరà±à°Ÿà±â€Œà°²à±</translation>
<translation id="7637571805876720304">Chromium à°¨à±à°‚à°¡à°¿ à°•à±à°°à±†à°¡à°¿à°Ÿà± కారà±à°¡à±â€Œà°¨à± తీసివేయాలా?</translation>
<translation id="7637586430889951925">{COUNT,plural, =0{à°à°µà±€ లేవà±}=1{మీ ఖాతాలో 1 పాసà±â€Œà°µà°°à±à°¡à±â€Œ (<ph name="DOMAIN_LIST" /> కోసం)}other{మీ ఖాతాలో # పాసà±â€Œà°µà°°à±à°¡à±â€Œâ€Œà°²à± (<ph name="DOMAIN_LIST" /> కోసం)}}</translation>
<translation id="7638605456503525968">సీరియలౠపోరà±à°Ÿà±â€Œà°²à±</translation>
<translation id="7639968568612851608">à°®à±à°¦à±à°°à± బూడిద à°°à°‚à°—à±</translation>
-<translation id="7647206758853451655">à°ªà±à°°à°¿à°‚టౠనాణà±à°¯à°¤</translation>
-<translation id="7648992873808071793">à°ˆ పరికరంలో ఫైలà±â€Œà°²à°¨à± నిలà±à°µ చేయాలనà±à°•à±à°‚టోంది</translation>
+<translation id="7647206758853451655">à°ªà±à°°à°¿à°‚à°Ÿà± à°•à±à°µà°¾à°²à°¿à°Ÿà±€</translation>
+<translation id="7648992873808071793">à°ˆ పరికరంలో ఫైళà±à°²à°¨à± నిలà±à°µ చేయాలనà±à°•à±à°‚టోంది</translation>
<translation id="7653957176542370971">చెలà±à°²à°¿à°‚పౠహà±à°¯à°¾à°‚à°¡à±à°²à°°à± షీటౠమూసివేయబడింది</translation>
<translation id="7654909834015434372">మీరౠఅదనపౠగమనికలనౠఎడిటౠచేసినపà±à°ªà±à°¡à±, à°ˆ డాకà±à°¯à±à°®à±†à°‚à°Ÿà±, దాని ఒరిజినలౠరొటేషనà±â€Œà°•à± తిరిగి వసà±à°¤à±à°‚ది</translation>
<translation id="765676359832457558">à°…à°§à±à°¨à°¾à°¤à°¨ సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°¨à± దాచà±...</translation>
@@ -1777,7 +1827,7 @@
<translation id="7716147886133743102">మీ నిరà±à°µà°¾à°¹à°•à±à°² à°¦à±à°µà°¾à°°à°¾ à°¬à±à°²à°¾à°•à± చేయబడింది</translation>
<translation id="7716375162095500223">ఇంకా à°…à°ªà±â€Œà°²à±‹à°¡à± చేయలేదౠలేదా విసà±à°®à°°à°¿à°‚చబడింది</translation>
<translation id="7716424297397655342">కాషౠనà±à°‚à°¡à°¿ à°ˆ సైటà±â€Œà°¨à± లోడౠచేయలేకపోయామà±</translation>
-<translation id="7723047071702270851">కారà±à°¡à±â€Œà°¨à± సవరించండి</translation>
+<translation id="7723047071702270851">కారà±à°¡à±â€Œà°¨à± ఎడిటౠచేయండి</translation>
<translation id="773466115871691567"><ph name="SOURCE_LANGUAGE" />లో ఉనà±à°¨ పేజీలనౠఎలà±à°²à°ªà±à°ªà±à°¡à±‚ à°…à°¨à±à°µà°¦à°¿à°‚à°šà±</translation>
<translation id="7740996059027112821">à°ªà±à°°à°¾à°®à°¾à°£à°¿à°•à°‚</translation>
<translation id="774634243536837715">హానికరమైన కంటెంటౠబà±à°²à°¾à°•à± చేయబడింది.</translation>
@@ -1807,13 +1857,12 @@
<translation id="782886543891417279">మీరౠఉపయోగిసà±à°¤à±à°¨à±à°¨ Wi-Fi (<ph name="WIFI_NAME" />)కౠమీరౠదాని లాగినౠపేజీని సందరà±à°¶à°¿à°‚à°šà°¡à°‚ అవసరం.</translation>
<translation id="7836231406687464395">Postfix (à°Žà°¨à±à°µà°²à°ªà±)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{à°à°¦à±€ వదà±à°¦à±}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">ఫైలౠరకం à°…à°¨à±à°¬à°‚ధాలతో ఉనà±à°¨ ఫైలà±â€Œà°²à°¨à± తెరవడం.</translation>
<translation id="7862185352068345852">సైటౠనà±à°‚à°¡à°¿ నిషà±à°•à±à°°à°®à°¿à°‚చాలా?</translation>
<translation id="7865448901209910068">ఉతà±à°¤à°® వేగం</translation>
<translation id="7874263914261512992">మీరౠమోసపూరితమైన సైటà±â€Œà°²à±‹ మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఎంటరౠచేశారà±. <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, ఇతర సైటà±â€Œà°²à°²à±‹ à°ªà±à°°à°¸à±à°¤à±à°¤à°‚ మీరౠఎకà±à°•à°¡à±ˆà°¤à±‡ à°ˆ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°¨à± ఉపయోగిసà±à°¤à°¾à°°à±‹, à°…à°•à±à°•à°¡ మీ సేవౠచేసిన పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à°¨à± తనిఖీ చేసà±à°•à±‹à°®à°¨à°¿ Chrome సిఫారà±à°¸à± చేసà±à°¤à±‹à°‚ది.</translation>
<translation id="7878562273885520351">మీ పాసà±â€Œà°µà°°à±à°¡à± ఎవరికైనా తెలిసిపోయి ఉండవచà±à°šà±</translation>
+<translation id="7880146494886811634">à°…à°¡à±à°°à°¸à±â€Œà°¨à± సేవౠచేయండి</translation>
<translation id="7882421473871500483">గోధà±à°® à°°à°‚à°—à±</translation>
<translation id="7887683347370398519">మీ CVCని తనిఖీ చేసి, మళà±à°²à±€ à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚à°šà°‚à°¡à°¿</translation>
<translation id="7887885240995164102">à°šà°¿à°¤à±à°°à°‚లో à°šà°¿à°¤à±à°°à°‚ మోడà±â€Œà°²à±‹à°•à°¿ à°ªà±à°°à°µà±‡à°¶à°¿à°¸à±à°¤à±à°‚ది</translation>
@@ -1821,6 +1870,7 @@
<translation id="7894280532028510793">à°¸à±à°ªà±†à°²à±à°²à°¿à°‚గౠసరైనది అయితే, <ph name="BEGIN_LINK" />నెటà±â€Œà°µà°°à±à°•à± సమసà±à°¯ విశà±à°²à±‡à°·à°£à°²à°¨à± రనౠచేయడానికి à°Ÿà±à°°à±ˆ చేయండి<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (à°Žà°¨à±à°µà°²à°ªà±)</translation>
<translation id="7931318309563332511">తెలియదà±</translation>
+<translation id="793209273132572360">à°…à°¡à±à°°à°¸à±â€Œà°¨à± à°…à°ªà±â€Œà°¡à±‡à°Ÿà± చేయాలా?</translation>
<translation id="7932579305932748336">కోటà±</translation>
<translation id="79338296614623784">చెలà±à°²à±à°¬à°¾à°Ÿà± à°…à°¯à±à°¯à±‡ ఫోనౠనంబరà±â€Œà°¨à± నమోదౠచేయండి</translation>
<translation id="7934052535022478634">చెలà±à°²à°¿à°‚పౠపూరà±à°¤à°¯à°¿à°‚ది</translation>
@@ -1891,6 +1941,7 @@
<translation id="8175796834047840627">మీరౠసైనౠఇనౠచేశారౠకనà±à°• మీ కారà±à°¡à±â€Œà°²à°¨à± మీ Google ఖాతాలో సేవౠచేసà±à°•à±à°¨à±‡ à°šà°•à±à°•à°¨à°¿ అవకాశానà±à°¨à°¿ Chrome మీకౠఅందిసà±à°¤à±‹à°‚ది. అలాగే మీరౠఈ à°šà°°à±à°¯à°¨à± సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹à°•à°¿ వెళà±à°²à°¿ మారà±à°šà±à°•à±‹à°µà°šà±à°šà±.</translation>
<translation id="8176440868214972690">సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à± లేదా పాలసీల వంటి కొంత సమాచారానà±à°¨à°¿, దిగà±à°µà±à°¨ పేరà±à°•à±Šà°¨à±à°¨ వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°²à°•à± à°ˆ పరికరపౠఅడà±à°®à°¿à°¨à°¿à°¸à±à°Ÿà±à°°à±‡à°Ÿà°°à± పంపారà±.</translation>
<translation id="8184538546369750125">సారà±à°µà°œà°¨à±€à°¨ డిఫాలà±à°Ÿà±â€Œà°¨à± ఉపయోగించౠ(à°…à°¨à±à°®à°¤à°¿à°‚à°šà±)</translation>
+<translation id="8193086767630290324">గోపà±à°¯à°®à±ˆà°¨à°µà°¿à°—à°¾ à°«à±à°²à°¾à°—ౠచేయబడిన డేటాతో à°šà°°à±à°¯à°²à± తీసà±à°•à±‹à°¬à°¡à±à°¡à°¾à°¯à°¿</translation>
<translation id="8194797478851900357">&amp;తరలించడానà±à°¨à°¿ à°°à°¦à±à°¦à± చేయి</translation>
<translation id="8201077131113104583">ID "<ph name="EXTENSION_ID" />" ఉనà±à°¨ à°Žà°•à±à°¸à±â€Œà°Ÿà±†à°¨à±à°·â€Œà°¨à±â€Œ కోసం à°…à°ªà±â€Œà°¡à±‡à°Ÿà±â€Œ URL చెలà±à°²à°¦à±.</translation>
<translation id="8202097416529803614">ఆరà±à°¡à°°à± సారాంశం</translation>
@@ -1913,6 +1964,7 @@
<translation id="8249296373107784235">à°°à°¦à±à°¦à±à°šà±‡à°¯à°¿</translation>
<translation id="8249320324621329438">చివరగా పొందబడినవి:</translation>
<translation id="8253091569723639551">బిలà±à°²à°¿à°‚à°—à± à°šà°¿à°°à±à°¨à°¾à°®à°¾ ఆవశà±à°¯à°•à°‚</translation>
+<translation id="8257387598443225809">ఈ యాపౠమొబైలౠకోసం రూపొందించబడింది</translation>
<translation id="825929999321470778">సేవౠచేసిన à°…à°¨à±à°¨à°¿ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à°¨à± చూపండి</translation>
<translation id="8261506727792406068">తొలగించà±</translation>
<translation id="8262952874573525464">దిగà±à°µ భాగంలో à°•à±à°Ÿà±à°Ÿà°¿à°¨ à°…à°‚à°šà±à°²à±</translation>
@@ -2003,7 +2055,7 @@
<ph name="END_LIST" /></translation>
<translation id="8574899947864779331">కారà±à°¡à±â€Œà°²à°¨à± వేగంగా నిరà±à°§à°¾à°°à°¿à°‚చడానికి Touch IDని ఉపయోగించండి</translation>
<translation id="858637041960032120">ఫోనౠనం. జోడిం.</translation>
-<translation id="8589998999637048520">ఉతà±à°¤à°® నాణà±à°¯à°¤</translation>
+<translation id="8589998999637048520">ఉతà±à°¤à°® à°•à±à°µà°¾à°²à°¿à°Ÿà±€</translation>
<translation id="8600271352425265729">à°ˆ à°’à°•à±à°•à°¸à°¾à°°à°¿ మాతà±à°°à°®à±‡</translation>
<translation id="860043288473659153">కారà±à°¡à±à°¦à°¾à°°à±à°¨à°¿ పేరà±</translation>
<translation id="8606726445206553943">మీ MIDI పరికరాలనౠఉపయోగించాలనà±à°•à±à°‚టోంది</translation>
@@ -2036,7 +2088,6 @@
<translation id="8719528812645237045">à°Žà°—à±à°µ భాగంలో అనేక à°°à°‚à°§à±à°°à°¾à°²à±</translation>
<translation id="8725066075913043281">మళà±à°³à±€ à°ªà±à°°à°¯à°¤à±à°¨à°¿à°‚à°šà°‚à°¡à°¿</translation>
<translation id="8726549941689275341">పేజీ సైజà±:</translation>
-<translation id="8728672262656704056">మీరౠఇపà±à°ªà±à°¡à± à°…à°œà±à°žà°¾à°¤ మోడà±â€Œà°²à±‹ ఉనà±à°¨à°¾à°°à±</translation>
<translation id="8730621377337864115">పూరà±à°¤à°¯à°¿à°‚ది</translation>
<translation id="8731544501227493793">'పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à± మేనేజౠచేయి' బటనà±, Chrome సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹ మీ పాసà±â€Œà°µà°°à±à°¡à±â€Œà°²à± చూసి, మేనేజౠచేయడానికి 'Enter' నొకà±à°•à°‚à°¡à°¿</translation>
<translation id="8734529307927223492"><ph name="MANAGER" />, మీ <ph name="DEVICE_TYPE" />నౠమేనేజౠచేసà±à°¤à±‹à°‚ది</translation>
@@ -2095,7 +2146,7 @@
<translation id="8968766641738584599">కారà±à°¡à±â€Œà°¨à°¿ సేవౠచేయండి</translation>
<translation id="8971063699422889582">సరà±à°µà°°à± à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ à°—à°¡à±à°µà± à°®à±à°—ిసింది.</translation>
<translation id="8975012916872825179">ఫోనౠనంబరà±â€Œà°²à±, ఇమెయిలౠచిరà±à°¨à°¾à°®à°¾à°²à± మరియౠబటà±à°µà°¾à°¡à°¾ à°šà°¿à°°à±à°¨à°¾à°®à°¾à°²à± లాంటి సమాచారం ఉంటà±à°‚ది</translation>
-<translation id="8975263830901772334">మీరౠమà±à°¦à±à°°à°¿à°‚చే ఫైలà±â€Œà°² పేరà±à°²à±</translation>
+<translation id="8975263830901772334">మీరౠమà±à°¦à±à°°à°¿à°‚చే ఫైళà±à°² పేరà±à°²à±</translation>
<translation id="8978053250194585037">Google à°¸à±à°°à°•à±à°·à°¿à°¤ à°¬à±à°°à±Œà°œà°¿à°‚గౠఇటీవల <ph name="SITE" />లో <ph name="BEGIN_LINK" />à°«à°¿à°·à°¿à°‚à°—à±â€Œà°¨à°¿ à°—à±à°°à±à°¤à°¿à°‚చింది<ph name="END_LINK" />. ఫిషింగౠసైటà±â€Œà°²à± వేరే వెబà±â€Œà°¸à±ˆà°Ÿà±â€Œà°² వలె à°ªà±à°°à°µà°°à±à°¤à°¿à°‚à°šà°¡à°‚ à°¦à±à°µà°¾à°°à°¾ మిమà±à°®à°²à±à°¨à°¿ మాయ చేయవచà±à°šà±.</translation>
<translation id="8983003182662520383">Google Payని ఉపయోగిసà±à°¤à±à°¨à±à°¨ చెలà±à°²à°¿à°‚పౠపదà±à°§à°¤à±à°²à± మరియౠచిరà±à°¨à°¾à°®à°¾à°²à±</translation>
<translation id="8987927404178983737">నెల</translation>
@@ -2113,6 +2164,7 @@
<translation id="9020542370529661692">à°ˆ పేజీ <ph name="TARGET_LANGUAGE" />à°•à°¿ à°…à°¨à±à°µà°¦à°¿à°‚చబడింది</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(చెలà±à°²à°¦à±)</translation>
+<translation id="9030265603405983977">మోనోకà±à°°à±‹à°®à±</translation>
<translation id="9035022520814077154">à°­à°¦à±à°°à°¤à°¾ à°Žà°°à±à°°à°°à±</translation>
<translation id="9038649477754266430">పేజీలనౠమరింత à°¤à±à°µà°°à°—à°¾ లోడౠచేయడానికి సూచన సేవనౠఉపయోగించండి</translation>
<translation id="9039213469156557790">అలాగే, à°ˆ పేజీలో à°¸à±à°°à°•à±à°·à°¿à°¤à°‚ కాని ఇతర వనరà±à°²à± ఉనà±à°¨à°¾à°¯à°¿. à°ˆ వనరà±à°²à°¨à± బదిలీ చేసà±à°¤à±à°¨à±à°¨à°ªà±à°ªà±à°¡à± ఇతరà±à°²à± చూడగలరౠమరియౠదాడికి పాలà±à°ªà°¡à±‡à°µà°¾à°°à± పేజీ à°ªà±à°°à°µà°°à±à°¤à°¨à°¨à± మారà±à°šà±‡à°²à°¾ వీటిని సవరించగలరà±.</translation>
@@ -2136,6 +2188,7 @@
<translation id="91108059142052966">గోపà±à°¯à°®à±ˆà°¨ కంటెంటౠకనిపించినపà±à°ªà±à°¡à± <ph name="APPLICATION_TITLE" />తో à°¸à±à°•à±à°°à±€à°¨à± షేరౠచేయడానà±à°¨à°¿ à°…à°¡à±à°®à°¿à°¨à°¿à°¸à±à°Ÿà±à°°à±‡à°Ÿà°°à± పాలసీ డిజేబà±à°²à± చేసà±à°¤à±à°‚ది</translation>
<translation id="9114524666733003316">కారà±à°¡à±â€Œ నిరà±à°§à°¾à°°à°¿à°‚చబడà±à°¤à±‹à°‚ది...</translation>
<translation id="9114581008513152754">à°ˆ à°¬à±à°°à±Œà°œà°°à± à°’à°• కంపెనీ లేదా ఇతర సంసà±à°¥ à°¦à±à°µà°¾à°°à°¾ మేనేజౠచేయబడదà±. à°ˆ పరికరంలోని యాకà±à°Ÿà°¿à°µà°¿à°Ÿà±€à°¨à°¿ Chrome వెలà±à°ªà°² మేనేజౠచేసà±à°¤à±à°‚డవచà±à°šà±. <ph name="BEGIN_LINK" />మరింత తెలà±à°¸à±à°•à±‹à°‚à°¡à°¿<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">తాజా</translation>
<translation id="9119042192571987207">à°…à°ªà±â€Œà°²à±‹à°¡à± చేయబడింది</translation>
<translation id="9128016270925453879">పాలసీలౠలోడౠచేయబడà±à°¡à°¾à°¯à°¿</translation>
<translation id="9128870381267983090">నెటà±â€Œà°µà°°à±à°•à±â€Œà°•à°¿ కనెకà±à°Ÿà± చేయి</translation>
@@ -2154,6 +2207,7 @@
<translation id="9170848237812810038">&amp;à°…à°¨à±à°¡à±</translation>
<translation id="9171296965991013597">యాపౠనà±à°‚à°¡à°¿ నిషà±à°•à±à°°à°®à°¿à°‚చాలా?</translation>
<translation id="9173282814238175921">à°’à°• డాకà±à°¯à±à°®à±†à°‚à°Ÿà±/కొతà±à°¤ షీటà±</translation>
+<translation id="9173995187295789444">à°¬à±à°²à±‚టూతౠపరికరాల కోసం à°¸à±à°•à°¾à°¨à± చేసà±à°¤à±‹à°‚ది...</translation>
<translation id="917450738466192189">సరà±à°µà°°à± యొకà±à°• à°ªà±à°°à°®à°¾à°£à°ªà°¤à±à°°à°‚ చెలà±à°²à±à°¬à°¾à°Ÿà± కాదà±.</translation>
<translation id="9174917557437862841">à°Ÿà±à°¯à°¾à°¬à± à°¸à±à°µà°¿à°šà± బటనà±, à°ˆ à°Ÿà±à°¯à°¾à°¬à±â€Œà°•à°¿ మారడానికి à°Žà°‚à°Ÿà°°à±â€Œà°¨à°¿ నొకà±à°•à°‚à°¡à°¿</translation>
<translation id="9179703756951298733">Chrome సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°²à±‹ మీ పేమెంటà±â€Œà°²à°¨à±, à°•à±à°°à±†à°¡à°¿à°Ÿà± కారà±à°¡à± సమాచారానà±à°¨à°¿ మేనేజౠచేయండి</translation>
diff --git a/chromium/components/strings/components_strings_th.xtb b/chromium/components/strings/components_strings_th.xtb
index 7321fe2e3c6..2d32a7ed033 100644
--- a/chromium/components/strings/components_strings_th.xtb
+++ b/chromium/components/strings/components_strings_th.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">หาà¸à¹€à¸¥à¸·à¸­à¸ Chrome จะจัดเà¸à¹‡à¸šà¸ªà¸³à¹€à¸™à¸²à¸‚องบัตรบนอุปà¸à¸£à¸“์นี้เพื่อà¸à¸²à¸£à¸à¸£à¸­à¸à¸‚้อมูลà¹à¸šà¸šà¸Ÿà¸­à¸£à¹Œà¸¡à¸­à¸¢à¹ˆà¸²à¸‡à¸£à¸§à¸”เร็ว</translation>
<translation id="1110994991967754504">เลือà¸à¸ªà¸´à¸—ธิ์สำหรับ<ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;เลิà¸à¸—ำà¸à¸²à¸£à¸ˆà¸±à¸”ลำดับใหม่</translation>
+<translation id="1123753900084781868">ใช้คำบรรยายสดไม่ได้ในขณะนี้</translation>
<translation id="1125573121925420732">คุณอาจเห็นคำเตือนอยู่บ่อยๆ ระหว่างที่เว็บไซต์อัปเดตความปลอดภัย เราจะปรับปรุงเร็วๆ นี้</translation>
<translation id="112840717907525620">à¹à¸„ชนโยบายใช้ได้</translation>
<translation id="1130564665089811311">ปุ่มà¹à¸›à¸¥à¸«à¸™à¹‰à¸²à¹€à¸§à¹‡à¸š à¸à¸” Enter เพื่อà¹à¸›à¸¥à¸«à¸™à¹‰à¸²à¸™à¸µà¹‰à¸”้วย Google à¹à¸›à¸¥à¸ à¸²à¸©à¸²</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">ชื่ออุปà¸à¸£à¸“์ของคุณ</translation>
<translation id="124116460088058876">ภาษาเพิ่มเติม</translation>
<translation id="1243027604378859286">ผู้เขียน:</translation>
+<translation id="1246424317317450637">ตัวหนา</translation>
<translation id="1250759482327835220">เพื่อความรวดเร็วในà¸à¸²à¸£à¸Šà¸³à¸£à¸°à¹€à¸‡à¸´à¸™à¸„รั้งถัดไป โปรดบันทึà¸à¸šà¸±à¸•à¸£ ชื่อ à¹à¸¥à¸°à¸—ี่อยู่สำหรับà¸à¸²à¸£à¹€à¸£à¸µà¸¢à¸à¹€à¸à¹‡à¸šà¹€à¸‡à¸´à¸™à¹„ว้ในบัà¸à¸Šà¸µ Google</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" /> <ph name="TYPE_2" /> (ซิงค์à¹à¸¥à¹‰à¸§)</translation>
<translation id="1256368399071562588">&lt;p&gt;หาà¸à¸„ุณพยายามเข้าชมเว็บไซต์ à¹à¸•à¹ˆà¹€à¸§à¹‡à¸šà¹„ซต์ไม่เปิดขึ้นมา ให้ลองà¹à¸à¹‰à¸‚้อผิดพลาดด้วยขั้นตอนà¸à¸²à¸£à¹à¸à¹‰à¸›à¸±à¸à¸«à¸²à¸•à¹ˆà¸­à¹„ปนี้&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">เปลี่ยนรหัสผ่าน</translation>
<translation id="1484290072879560759">เลือà¸à¸—ี่อยู่สำหรับจัดส่ง</translation>
<translation id="1492194039220927094">à¸à¸²à¸£à¸žà¸¸à¸Šà¸™à¹‚ยบาย:</translation>
+<translation id="1495677929897281669">à¸à¸¥à¸±à¸šà¹„ปที่à¹à¸—็บ</translation>
<translation id="1501859676467574491">à¹à¸ªà¸”งบัตรจาà¸à¸šà¸±à¸à¸Šà¸µ Google ของคุณ</translation>
<translation id="1507202001669085618">&lt;p&gt;คุณจะเห็นข้อผิดพลาดนี้ หาà¸à¹ƒà¸Šà¹‰à¸žà¸­à¸£à¹Œà¸—ัล Wi-Fi ที่คุณต้องลงชื่อเข้าใช้à¸à¹ˆà¸­à¸™à¸ˆà¸¶à¸‡à¸ˆà¸°à¸ªà¸²à¸¡à¸²à¸£à¸–ออนไลน์ได้&lt;/p&gt;
&lt;p&gt;ในà¸à¸²à¸£à¹à¸à¹‰à¹„ขข้อผิดพลาด ให้คลิà¸&lt;strong&gt;เชื่อมต่อ&lt;/strong&gt;บนหน้าเว็บที่คุณพยายามจะเปิด&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">หน้านี้บอà¸à¸§à¹ˆà¸²</translation>
<translation id="153384715582417236">เสร็จเรียบร้อย</translation>
<translation id="1536390784834419204">à¹à¸›à¸¥à¸«à¸™à¹‰à¸²à¹€à¸§à¹‡à¸š</translation>
+<translation id="1539840569003678498">ส่งรายงานà¹à¸¥à¹‰à¸§:</translation>
<translation id="154408704832528245">เลือà¸à¸—ี่อยู่สำหรับนำส่งสินค้า</translation>
<translation id="1549470594296187301">ต้องเปิดใช้ JavaScript เพื่อใช้ฟีเจอร์นี้</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">ด้านขอบสั้นà¸à¹ˆà¸­à¸™</translation>
<translation id="168693727862418163">ตรวจสอบค่านโยบายนี้à¸à¸±à¸šà¸ªà¸„ีมาไม่ได้ ระบบจะเพิà¸à¹€à¸‰à¸¢à¸•à¹ˆà¸­à¸„่านี้</translation>
<translation id="168841957122794586">ใบรับรองของเซิร์ฟเวอร์มีคีย์à¸à¸²à¸£à¹€à¸‚้ารหัสที่ไม่รัดà¸à¸¸à¸¡</translation>
+<translation id="1696290444144917273">ดูรายละเอียดบัตรเสมือน</translation>
<translation id="1697532407822776718">คุณพร้อมà¹à¸¥à¹‰à¸§!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{เซิร์ฟเวอร์นี้พิสูจน์ไม่ได้ว่าเป็น <ph name="DOMAIN" /> เพราะใบรับรองความปลอดภัยควรจะเริ่มใช้งานได้ตั้งà¹à¸•à¹ˆà¸§à¸±à¸™à¸žà¸£à¸¸à¹ˆà¸‡à¸™à¸µà¹‰ โดยอาจเà¸à¸´à¸”จาà¸à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าผิดหรือผู้บุà¸à¸£à¸¸à¸à¸—ี่ขัดขวางà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸‚องคุณ}other{เซิร์ฟเวอร์นี้พิสูจน์ไม่ได้ว่าเป็น <ph name="DOMAIN" /> เพราะใบรับรองความปลอดภัยควรจะเริ่มใช้งานได้ในอีภ# วันข้างหน้า โดยอาจเà¸à¸´à¸”จาà¸à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าผิดหรือผู้บุà¸à¸£à¸¸à¸à¸—ี่ขัดขวางà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸‚องคุณ}}</translation>
<translation id="1710259589646384581">ระบบปà¸à¸´à¸šà¸±à¸•à¸´à¸à¸²à¸£</translation>
+<translation id="1711234383449478798">ละเว้นเนื่องจาภ<ph name="POLICY_NAME" /> ไม่ได้ตั้งค่าเป็น "<ph name="VALUE" />"</translation>
<translation id="1712552549805331520"><ph name="URL" /> ต้องà¸à¸²à¸£à¸ˆà¸±à¸”เà¸à¹‡à¸šà¸‚้อมูลถาวรในเครื่องคอมพิวเตอร์ของคุณ</translation>
<translation id="1713628304598226412">ถาด 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">à¸à¸¥à¹ˆà¸­à¸‡à¸ˆà¸”หมาย 3</translation>
<translation id="1718029547804390981">เอà¸à¸ªà¸²à¸£à¸¡à¸µà¸‚นาดใหà¸à¹ˆà¹€à¸à¸´à¸™à¸à¸§à¹ˆà¸²à¸ˆà¸°à¹ƒà¸ªà¹ˆà¸«à¸¡à¸²à¸¢à¹€à¸«à¸•à¸¸à¹„ด้</translation>
<translation id="1721424275792716183">* ช่องที่ต้องà¸à¸£à¸­à¸</translation>
+<translation id="1727613060316725209">ใบรับรองถูà¸à¸•à¹‰à¸­à¸‡</translation>
<translation id="1727741090716970331">เพิ่มหมายเลขบัตรที่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
<translation id="1728677426644403582">คุณà¸à¸³à¸¥à¸±à¸‡à¸”ูซอร์สโค้ดของหน้าเว็บ</translation>
<translation id="173080396488393970">ไม่รองรับบัตรประเภทนี้</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />ลองเรียà¸à¹ƒà¸Šà¹‰à¸à¸²à¸£à¸§à¸´à¸™à¸´à¸ˆà¸‰à¸±à¸¢à¹€à¸„รือข่ายของ Windows<ph name="END_LINK" /></translation>
<translation id="1772163372082567643">เซิร์ฟเวอร์ที่คุณà¸à¸³à¸¥à¸±à¸‡à¸ˆà¸°à¹€à¸‚้าถึง <ph name="ORIGIN" /> ได้ตั้งค่าส่วนหัวที่à¸à¸³à¸«à¸™à¸”ให้บังคับใช้นโยบายดั้งเดิมà¸à¸±à¸šà¸„ำขอทั้งหมดที่ส่งถึงเซิร์ฟเวอร์ à¹à¸•à¹ˆà¸ªà¹ˆà¸§à¸™à¸«à¸±à¸§à¸”ังà¸à¸¥à¹ˆà¸²à¸§à¸¡à¸µà¸£à¸¹à¸›à¹à¸šà¸šà¸—ี่ไม่ถูà¸à¸•à¹‰à¸­à¸‡ ซึ่งทำให้เบราว์เซอร์ดำเนินà¸à¸²à¸£à¸•à¸²à¸¡à¸„ำขอของคุณสำหรับ <ph name="SITE" /> ไม่ได้ ผู้ให้บริà¸à¸²à¸£à¹€à¸§à¹‡à¸šà¹„ซต์อาจใช้นโยบายดั้งเดิมในà¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าความปลอดภัยà¹à¸¥à¸°à¸žà¸£à¹‡à¸­à¸žà¹€à¸žà¸­à¸£à¹Œà¸•à¸µà¹‰à¸­à¸·à¹ˆà¸™à¹† ของเว็บไซต์</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">โปรดอัปเดตข้อความรหัสผ่านที่ซิงค์ของคุณ</translation>
<translation id="1787142507584202372">à¹à¸—็บที่คุณเปิดไว้จะปราà¸à¸à¸—ี่นี่</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" /> มีà¸à¸²à¸£à¸—ำงานหลายอย่างที่ทำได้ à¸à¸” Tab เพื่อวนดูà¸à¸²à¸£à¸—ำงานดังà¸à¸¥à¹ˆà¸²à¸§</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">โฆษณา</translation>
<translation id="1919367280705858090">ขอความช่วยเหลือเà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸šà¸‚้อความà¹à¸ªà¸”งข้อผิดพลาดที่เจาะจง</translation>
<translation id="192020519938775529">{COUNT,plural, =0{ไม่มี}=1{เว็บไซต์ 1 à¹à¸«à¹ˆà¸‡}other{เว็บไซต์ # à¹à¸«à¹ˆà¸‡}}</translation>
+<translation id="1924727005275031552">ใหม่</translation>
<translation id="1945968466830820669">คุณอาจเข้าถึงบัà¸à¸Šà¸µà¸‚ององค์à¸à¸£à¹„ม่ได้หรือถูà¸à¹‚จรà¸à¸£à¸£à¸¡à¸‚้อมูลประจำตัว Chromium ขอà¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™à¸•à¸­à¸™à¸™à¸µà¹‰à¹€à¸¥à¸¢</translation>
<translation id="1947454675006758438">เย็บด้วยลวดเย็บà¸à¸£à¸°à¸”าษด้านขวาบน</translation>
<translation id="1958218078413065209">คะà¹à¸™à¸™à¸ªà¸¹à¸‡à¸ªà¸¸à¸”ของคุณคือ <ph name="SCORE" /></translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">ถาด 7</translation>
<translation id="204357726431741734">ลงชื่อเข้าใช้เพื่อใช้รหัสผ่านที่บันทึà¸à¹„ว้ในบัà¸à¸Šà¸µ Google</translation>
<translation id="2053111141626950936">ระบบจะไม่à¹à¸›à¸¥à¸«à¸™à¹‰à¸²à¹€à¸§à¹‡à¸šà¸ à¸²à¸©à¸²<ph name="LANGUAGE" /></translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{เมื่อเปิดà¸à¸²à¸£à¸„วบคุมนี้ไว้à¹à¸¥à¸°à¸ªà¸–านะเป็น "ใช้งานอยู่" Chrome จะระบุว่าà¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸à¸²à¸£à¸—่องเว็บล่าสุดของคุณคล้ายà¸à¸±à¸šà¸à¸¥à¸¸à¹ˆà¸¡à¸„นจำนวนมาà¸à¸«à¸£à¸·à¸­ "à¸à¸¥à¸¸à¹ˆà¸¡à¸›à¸£à¸°à¸Šà¸²à¸à¸£à¸•à¸²à¸¡à¸£à¸¸à¹ˆà¸™" à¸à¸¥à¸¸à¹ˆà¸¡à¹ƒà¸”มาà¸à¸—ี่สุด ผู้ลงโฆษณาจะเลือà¸à¹‚ฆษณาสำหรับà¸à¸¥à¸¸à¹ˆà¸¡à¸”ังà¸à¸¥à¹ˆà¸²à¸§à¹„ด้ à¹à¸¥à¸°à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸à¸²à¸£à¸—่องเว็บจะเà¸à¹‡à¸šà¹„ว้เป็นส่วนตัวในอุปà¸à¸£à¸“์ของคุณ à¸à¸¥à¸¸à¹ˆà¸¡à¸ˆà¸°à¸­à¸±à¸›à¹€à¸”ตทุà¸à¸§à¸±à¸™}=1{เมื่อเปิดà¸à¸²à¸£à¸„วบคุมนี้ไว้à¹à¸¥à¸°à¸ªà¸–านะเป็น "ใช้งานอยู่" Chrome จะระบุว่าà¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸à¸²à¸£à¸—่องเว็บล่าสุดของคุณคล้ายà¸à¸±à¸šà¸à¸¥à¸¸à¹ˆà¸¡à¸„นจำนวนมาà¸à¸«à¸£à¸·à¸­ "à¸à¸¥à¸¸à¹ˆà¸¡à¸›à¸£à¸°à¸Šà¸²à¸à¸£à¸•à¸²à¸¡à¸£à¸¸à¹ˆà¸™" à¸à¸¥à¸¸à¹ˆà¸¡à¹ƒà¸”มาà¸à¸—ี่สุด ผู้ลงโฆษณาจะเลือà¸à¹‚ฆษณาสำหรับà¸à¸¥à¸¸à¹ˆà¸¡à¸”ังà¸à¸¥à¹ˆà¸²à¸§à¹„ด้ à¹à¸¥à¸°à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸à¸²à¸£à¸—่องเว็บจะเà¸à¹‡à¸šà¹„ว้เป็นส่วนตัวในอุปà¸à¸£à¸“์ของคุณ à¸à¸¥à¸¸à¹ˆà¸¡à¸ˆà¸°à¸­à¸±à¸›à¹€à¸”ตทุà¸à¸§à¸±à¸™}other{เมื่อเปิดà¸à¸²à¸£à¸„วบคุมนี้ไว้à¹à¸¥à¸°à¸ªà¸–านะเป็น "ใช้งานอยู่" Chrome จะระบุว่าà¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸à¸²à¸£à¸—่องเว็บล่าสุดของคุณคล้ายà¸à¸±à¸šà¸à¸¥à¸¸à¹ˆà¸¡à¸„นจำนวนมาà¸à¸«à¸£à¸·à¸­ "à¸à¸¥à¸¸à¹ˆà¸¡à¸›à¸£à¸°à¸Šà¸²à¸à¸£à¸•à¸²à¸¡à¸£à¸¸à¹ˆà¸™" à¸à¸¥à¸¸à¹ˆà¸¡à¹ƒà¸”มาà¸à¸—ี่สุด ผู้ลงโฆษณาจะเลือà¸à¹‚ฆษณาสำหรับà¸à¸¥à¸¸à¹ˆà¸¡à¸”ังà¸à¸¥à¹ˆà¸²à¸§à¹„ด้ à¹à¸¥à¸°à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸à¸²à¸£à¸—่องเว็บจะเà¸à¹‡à¸šà¹„ว้เป็นส่วนตัวในอุปà¸à¸£à¸“์ของคุณ à¸à¸¥à¸¸à¹ˆà¸¡à¸ˆà¸°à¸­à¸±à¸›à¹€à¸”ตทุภ{NUM_DAYS} วัน}}</translation>
<translation id="2053553514270667976">รหัสไปรษณีย์</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 คำà¹à¸™à¸°à¸™à¸³}other{# คำà¹à¸™à¸°à¸™à¸³}}</translation>
<translation id="2071692954027939183">à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•à¸·à¸­à¸™à¸–ูà¸à¸šà¸¥à¹‡à¸­à¸à¹‚ดยอัตโนมัติเนื่องจาà¸à¸„ุณมัà¸à¹„ม่อนุà¸à¸²à¸•à¹ƒà¸«à¹‰à¹à¸ªà¸”ง</translation>
<translation id="2079545284768500474">เลิà¸à¸—ำ</translation>
<translation id="20817612488360358">มีà¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ให้ใช้à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าพร็อà¸à¸‹à¸µà¸£à¸°à¸šà¸š à¹à¸•à¹ˆà¸à¹‡à¸¡à¸µà¸à¸²à¸£à¸£à¸°à¸šà¸¸à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าพร็อà¸à¸‹à¸µà¸­à¸¢à¹ˆà¸²à¸‡à¸Šà¸±à¸”เจนไว้ด้วยเช่นà¸à¸±à¸™</translation>
<translation id="2082238445998314030">ผลลัพธ์ <ph name="RESULT_NUMBER" /> จาภ<ph name="TOTAL_RESULTS" /> รายà¸à¸²à¸£</translation>
+<translation id="2085876078937250610">บันทึà¸â€¦</translation>
<translation id="2088086323192747268">ปุ่มจัดà¸à¸²à¸£à¸à¸²à¸£à¸‹à¸´à¸‡à¸„์ à¸à¸” Enter เพื่อจัดà¸à¸²à¸£à¸‚้อมูลที่คุณซิงค์ในà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Chrome</translation>
<translation id="2091887806945687916">เสียง</translation>
<translation id="2094505752054353250">โดเมนไม่ตรง</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> ต้องใช้ชื่อผู้ใช้à¹à¸¥à¸°à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" /> หมดอายุ <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">ผู้ดูà¹à¸¥à¸£à¸°à¸šà¸šà¹€à¸›à¹‡à¸™à¸œà¸¹à¹‰à¸„วบคุมà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ต้องà¸à¸²à¸£à¸ˆà¸±à¸šà¸„ู่</translation>
<translation id="2344028582131185878">à¸à¸²à¸£à¸”าวน์โหลดโดยอัตโนมัติ</translation>
<translation id="2346319942568447007">รูปภาพที่คุณคัดลอà¸</translation>
<translation id="2354001756790975382">บุ๊à¸à¸¡à¸²à¸£à¹Œà¸à¸­à¸·à¹ˆà¸™à¹†</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">ผู้โจมตีอาจเห็นรูปภาพที่คุณà¸à¸³à¸¥à¸±à¸‡à¸”ูอยู่บนเว็บไซต์นี้à¹à¸¥à¸°à¸«à¸¥à¸­à¸à¸¥à¸§à¸‡à¸„ุณโดยà¸à¸²à¸£à¹à¸à¹‰à¹„ขรูปภาพ</translation>
<translation id="2356070529366658676">ถาม</translation>
<translation id="2357481397660644965">อุปà¸à¸£à¸“์ของคุณจัดà¸à¸²à¸£à¹‚ดย <ph name="DEVICE_MANAGER" /> à¹à¸¥à¸°à¸šà¸±à¸à¸Šà¸µà¸‚องคุณจัดà¸à¸²à¸£à¹‚ดย <ph name="ACCOUNT_MANAGER" /></translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ในเวลาไม่ถึง 1 วัน}=1{ใน 1 วัน}other{ใน {NUM_DAYS} วัน}}</translation>
<translation id="2359629602545592467">หลายรายà¸à¸²à¸£</translation>
<translation id="2359808026110333948">ต่อไป</translation>
+<translation id="2359961752320758691">ใช้หมายเลขบัตรเสมือนของคุณà¹à¸¥à¹‰à¸§</translation>
<translation id="2367567093518048410">ระดับ</translation>
<translation id="2372464001869762664">เมื่อยืนยันà¹à¸¥à¹‰à¸§ ระบบจะà¹à¸Šà¸£à¹Œà¸£à¸²à¸¢à¸¥à¸°à¹€à¸­à¸µà¸¢à¸”ของบัตรจาà¸à¸šà¸±à¸à¸Šà¸µ Google à¸à¸±à¸šà¹€à¸§à¹‡à¸šà¹„ซต์นี้ ดู CVC ได้ในรายละเอียดของบัà¸à¸Šà¸µ Plex</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">วิธีà¸à¸²à¸£à¸ˆà¸±à¸”ส่งสินค้านี้ไม่พร้อมให้บริà¸à¸²à¸£ โปรดลองใช้วิธีà¸à¸²à¸£à¸­à¸·à¹ˆà¸™</translation>
<translation id="2396249848217231973">&amp;เลิà¸à¸—ำà¸à¸²à¸£à¸™à¸³à¸­à¸­à¸</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">เà¸à¹ˆà¸²</translation>
<translation id="2413528052993050574">เซิร์ฟเวอร์นี้ไม่สามารถพิสูจน์ได้ว่าเป็น <ph name="DOMAIN" /> เพราะอาจมีà¸à¸²à¸£à¹€à¸žà¸´à¸à¸–อนใบรับรองความปลอดภัย โดยอาจเà¸à¸´à¸”จาà¸à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าผิดหรือผู้บุà¸à¸£à¸¸à¸à¸—ี่ขัดขวางà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸‚องคุณ</translation>
<translation id="2414886740292270097">มืด</translation>
<translation id="2438874542388153331">เจาะรูด้านขวา 4 รู</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">เย็บด้วยลวดเย็บà¸à¸£à¸°à¸”าษด้านขวาล่าง</translation>
<translation id="2523886232349826891">บันทึà¸à¹„ว้เฉพาะในอุปà¸à¸£à¸“์นี้</translation>
<translation id="2524461107774643265">เพิ่มข้อมูลอื่นๆ</translation>
-<translation id="2526590354069164005">เดสà¸à¹Œà¸—็อป</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{à¹à¸¥à¸°à¸­à¸µà¸ 1 โดเมน}other{à¹à¸¥à¸°à¸­à¸µà¸ # โดเมน}}</translation>
<translation id="2536110899380797252">เพิ่มที่อยู่</translation>
<translation id="2539524384386349900">ตรวจหา</translation>
+<translation id="2541219929084442027">หน้าที่คุณดูในà¹à¸—็บที่ไม่ระบุตัวตนจะไม่เà¸à¹‡à¸šà¸­à¸¢à¸¹à¹ˆà¹ƒà¸™à¸›à¸£à¸°à¸§à¸±à¸•à¸´à¸à¸²à¸£à¹€à¸‚้าชมของเบราว์เซอร์ à¸à¸²à¸£à¸ˆà¸±à¸”เà¸à¹‡à¸šà¸„ุà¸à¸à¸µà¹‰ หรือประวัติà¸à¸²à¸£à¸„้นหาหลังจาà¸à¸—ี่คุณปิดà¹à¸—็บที่ไม่ระบุตัวตนทั้งหมด à¹à¸•à¹ˆà¸ˆà¸°à¸¡à¸µà¸à¸²à¸£à¹€à¸à¹‡à¸šà¹„ฟล์ที่คุณดาวน์โหลดหรือบุ๊à¸à¸¡à¸²à¸£à¹Œà¸à¸—ี่คุณสร้างขึ้น</translation>
<translation id="2544644783021658368">เอà¸à¸ªà¸²à¸£à¹€à¸”ียว</translation>
<translation id="254947805923345898">ค่านโยบายไม่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> ส่งà¸à¸²à¸£à¸•à¸­à¸šà¸à¸¥à¸±à¸šà¸—ี่ไม่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240"><ph name="BEGIN_ENHANCED_PROTECTION_LINK" />เปิดà¸à¸²à¸£à¸›à¸à¸›à¹‰à¸­à¸‡à¸—ี่ปรับปรุงà¹à¸¥à¹‰à¸§<ph name="END_ENHANCED_PROTECTION_LINK" />เพื่อให้ Chrome รัà¸à¸©à¸²à¸„วามปลอดภัยในระดับสูงสุด</translation>
<translation id="2634124572758952069">ไม่พบที่อยู่ IP ของเซิร์ฟเวอร์ <ph name="HOST_NAME" /></translation>
<translation id="2639739919103226564">สถานะ:</translation>
+<translation id="264810637653812429">ไม่พบอุปà¸à¸£à¸“์ที่เข้าà¸à¸±à¸™à¹„ด้</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" /> à¸à¸” Tab ตามด้วย Enter เพื่อล้างประวัติà¸à¸²à¸£à¸—่องเว็บ คุà¸à¸à¸µà¹‰ à¹à¸„ช à¹à¸¥à¸°à¸­à¸·à¹ˆà¸™à¹† ในà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Chrome</translation>
<translation id="2650446666397867134">à¸à¸²à¸£à¹€à¸‚้าถึงไฟล์ถูà¸à¸›à¸à¸´à¹€à¸ªà¸˜</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">เปิดใหม่</translation>
<translation id="2803306138276472711">เมื่อเร็วๆ นี้ Google Safe Browsing <ph name="BEGIN_LINK" />ตรวจพบมัลà¹à¸§à¸£à¹Œ<ph name="END_LINK" />ใน <ph name="SITE" /> เว็บไซต์ที่โดยปà¸à¸•à¸´à¸ˆà¸°à¸›à¸¥à¸­à¸”ภัยบางครั้งอาจติดมัลà¹à¸§à¸£à¹Œ</translation>
<translation id="2807052079800581569">ตำà¹à¸«à¸™à¹ˆà¸‡à¸£à¸¹à¸›à¸ à¸²à¸žà¸•à¸²à¸¡à¹à¸à¸™ Y</translation>
+<translation id="2820957248982571256">à¸à¸³à¸¥à¸±à¸‡à¸ªà¹à¸à¸™...</translation>
<translation id="2824775600643448204">ที่อยู่à¹à¸¥à¸°à¹à¸–บค้นหา</translation>
<translation id="2826760142808435982">à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸–ูà¸à¹€à¸‚้ารหัสà¹à¸¥à¸°à¸£à¸±à¸šà¸£à¸­à¸‡à¸„วามถูà¸à¸•à¹‰à¸­à¸‡à¹‚ดยใช้ <ph name="CIPHER" /> à¹à¸¥à¸°à¹ƒà¸Šà¹‰ <ph name="KX" /> เป็นà¸à¸¥à¹„à¸à¸à¸²à¸£à¹à¸¥à¸à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸„ีย์</translation>
<translation id="2835170189407361413">ล้างฟอร์ม</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">Invite (ซองจดหมาย)</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="2859806420264540918">เว็บไซต์นี้à¹à¸ªà¸”งโฆษณาที่à¹à¸—รà¸à¸«à¸£à¸·à¸­à¸—ำให้เข้าใจผิด</translation>
+<translation id="287596039013813457">เป็นà¸à¸±à¸™à¹€à¸­à¸‡</translation>
+<translation id="2876489322757410363">à¸à¸³à¸¥à¸±à¸‡à¸­à¸­à¸à¸ˆà¸²à¸à¹‚หมดไม่ระบุตัวตนเพื่อชำระเงินผ่านà¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันภายนอภต้องà¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸•à¹ˆà¸­à¹„หม</translation>
<translation id="2878197950673342043">พับà¹à¸šà¸šà¹‚ปสเตอร์</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ตำà¹à¸«à¸™à¹ˆà¸‡à¸«à¸™à¹‰à¸²à¸•à¹ˆà¸²à¸‡</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">C9 (ซองจดหมาย)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" /> à¸à¸” Tab ตามด้วย Enter เพื่อเรียà¸à¹ƒà¸Šà¹‰à¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¸„วามปลอดภัยในà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Chrome</translation>
<translation id="3061707000357573562">à¹à¸žà¸•à¸Šà¹Œà¸šà¸£à¸´à¸à¸²à¸£</translation>
-<translation id="3064966200440839136">ออà¸à¸ˆà¸²à¸à¹‚หมดไม่ระบุตัวตนเพื่อชำระเงินผ่านà¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันภายนอภดำเนินà¸à¸²à¸£à¸•à¹ˆà¸­à¹„หม</translation>
<translation id="306573536155379004">เà¸à¸¡à¹€à¸£à¸´à¹ˆà¸¡à¹à¸¥à¹‰à¸§</translation>
<translation id="3080254622891793721">à¸à¸£à¸²à¸Ÿà¸´à¸</translation>
<translation id="3086579638707268289">มีà¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸—ี่คุณทำบนเว็บ</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">บัà¸à¸Šà¸µà¸‚องคุณจัดà¸à¸²à¸£à¹‚ดย <ph name="MANAGER" /></translation>
<translation id="3157931365184549694">คืนค่า</translation>
<translation id="3162559335345991374">Wi-Fi ที่คุณใช้อาจต้องà¸à¸²à¸£à¹ƒà¸«à¹‰à¸„ุณไปที่หน้าà¸à¸²à¸£à¹€à¸‚้าสู่ระบบ</translation>
-<translation id="3167968892399408617">หน้าที่คุณดูในà¹à¸—็บไม่ระบุตัวตนจะไม่เà¸à¹‡à¸šà¸­à¸¢à¸¹à¹ˆà¹ƒà¸™à¸›à¸£à¸°à¸§à¸±à¸•à¸´à¸à¸²à¸£à¹€à¸‚้าชมของเบราว์เซอร์ à¸à¸²à¸£à¸ˆà¸±à¸”เà¸à¹‡à¸šà¸„ุà¸à¸à¸µà¹‰ หรือประวัติà¸à¸²à¸£à¸„้นหาหลังจาà¸à¸—ี่คุณปิดà¹à¸—็บไม่ระบุตัวตนทั้งหมด à¹à¸•à¹ˆà¸ˆà¸°à¸¡à¸µà¸à¸²à¸£à¹€à¸à¹‡à¸šà¹„ฟล์ที่คุณดาวน์โหลดหรือบุ๊à¸à¸¡à¸²à¸£à¹Œà¸à¸—ี่คุณสร้างขึ้น</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">เà¸à¸²à¸°</translation>
<translation id="3176929007561373547">ตรวจสอบà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าพร็อà¸à¸‹à¸µà¸«à¸£à¸·à¸­à¸•à¸´à¸”ต่อผู้ดูà¹à¸¥à¸£à¸°à¸šà¸šà¹€à¸„รือข่ายของคุณเพื่อ
@@ -593,10 +608,12 @@
<translation id="3229041911291329567">ข้อมูลเวอร์ชันเà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸šà¸­à¸¸à¸›à¸à¸£à¸“์à¹à¸¥à¸°à¹€à¸šà¸£à¸²à¸§à¹Œà¹€à¸‹à¸­à¸£à¹Œ</translation>
<translation id="323107829343500871">ป้อน CVC สำหรับ <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">ตรวจหาเนื้อหาที่สำคัà¸à¸šà¸™à¹„ซต์นี้เสมอ</translation>
+<translation id="3249845759089040423">ดึงดูด</translation>
<translation id="3252266817569339921">à¸à¸£à¸±à¹ˆà¸‡à¹€à¸¨à¸ª</translation>
<translation id="3266793032086590337">ค่า (มีความขัดà¹à¸¢à¹‰à¸‡)</translation>
<translation id="3268451620468152448">à¹à¸—็บที่เปิดอยู่</translation>
<translation id="3270847123878663523">&amp;เลิà¸à¸—ำà¸à¸²à¸£à¸ˆà¸±à¸”ลำดับใหม่</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> ต้องà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">องค์à¸à¸£à¸‚องคุณ <ph name="ENROLLMENT_DOMAIN" /> ได้ส่งข้อมูลบางอย่าง เช่น à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าหรือนโยบายไปยังเว็บไซต์ต่อไปนี้</translation>
<translation id="3282497668470633863">เพิ่มชื่อบนบัตร</translation>
@@ -649,6 +666,7 @@
<translation id="3428151540071562330">URI ของเซิร์ฟเวอร์เทมเพลต DnsOverHttpsTemplates อย่างน้อย 1 รายà¸à¸²à¸£à¹„ม่ถูà¸à¸•à¹‰à¸­à¸‡à¹à¸¥à¸°à¸ˆà¸°à¹„ม่มีà¸à¸²à¸£à¸™à¸³à¹„ปใช้</translation>
<translation id="3431636764301398940">บันทึà¸à¸šà¸±à¸•à¸£à¸™à¸µà¹‰à¸¥à¸‡à¹ƒà¸™à¸­à¸¸à¸›à¸à¸£à¸“์นี้</translation>
<translation id="3432601291244612633">ปิดหน้า</translation>
+<translation id="3435738964857648380">ความปลอดภัย</translation>
<translation id="3435896845095436175">เปิดà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™</translation>
<translation id="3438829137925142401">ใช้รหัสผ่านที่บันทึà¸à¹„ว้ในบัà¸à¸Šà¸µ Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -690,7 +708,10 @@
<translation id="3584299510153766161">เจาะรูด้านล่าง 2 รู</translation>
<translation id="3586931643579894722">ซ่อนรายละเอียด</translation>
<translation id="3587738293690942763">ตรงà¸à¸¥à¸²à¸‡</translation>
+<translation id="3590643883886679995">ข้อมูลà¸à¸²à¸£à¸¥à¸‡à¸Šà¸·à¹ˆà¸­à¹€à¸‚้าใช้จะจัดเà¸à¹‡à¸šà¸­à¸¢à¸¹à¹ˆà¹ƒà¸™à¸­à¸¸à¸›à¸à¸£à¸“์นี้หลังจาà¸à¸­à¸­à¸à¸ˆà¸²à¸à¹‚หมดไม่ระบุตัวตน</translation>
+<translation id="359126217934908072">เดือน/ปี:</translation>
<translation id="3592413004129370115">Italian (ซองจดหมาย)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{คุณรีเซ็ตà¸à¸¥à¸¸à¹ˆà¸¡à¹„ด้ทุà¸à¹€à¸¡à¸·à¹ˆà¸­ à¸à¸²à¸£à¹€à¸‚้าร่วมà¸à¸¥à¸¸à¹ˆà¸¡à¹ƒà¸«à¸¡à¹ˆà¸ˆà¸°à¹ƒà¸Šà¹‰à¹€à¸§à¸¥à¸²à¸›à¸£à¸°à¸¡à¸²à¸“ 1 วัน}=1{คุณรีเซ็ตà¸à¸¥à¸¸à¹ˆà¸¡à¹„ด้ทุà¸à¹€à¸¡à¸·à¹ˆà¸­ à¸à¸²à¸£à¹€à¸‚้าร่วมà¸à¸¥à¸¸à¹ˆà¸¡à¹ƒà¸«à¸¡à¹ˆà¸ˆà¸°à¹ƒà¸Šà¹‰à¹€à¸§à¸¥à¸²à¸›à¸£à¸°à¸¡à¸²à¸“ 1 วัน}other{คุณรีเซ็ตà¸à¸¥à¸¸à¹ˆà¸¡à¹„ด้ทุà¸à¹€à¸¡à¸·à¹ˆà¸­ à¸à¸²à¸£à¹€à¸‚้าร่วมà¸à¸¥à¸¸à¹ˆà¸¡à¹ƒà¸«à¸¡à¹ˆà¸ˆà¸°à¹ƒà¸Šà¹‰à¹€à¸§à¸¥à¸²à¸›à¸£à¸°à¸¡à¸²à¸“ {NUM_DAYS} วัน}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">ผู้ดูà¹à¸¥à¸£à¸°à¸šà¸šà¸šà¸¥à¹‡à¸­à¸à¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันไว้</translation>
<translation id="3608932978122581043">ฟีดà¸à¸£à¸°à¸”าษตามà¹à¸™à¸§</translation>
@@ -699,13 +720,13 @@
<translation id="3615877443314183785">ป้อนวันที่หมดอายุที่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
<translation id="36224234498066874">ล้างข้อมูลà¸à¸²à¸£à¸—่องเว็บ</translation>
<translation id="362276910939193118">à¹à¸ªà¸”งประวัติà¸à¸²à¸£à¹€à¸‚้าชมทั้งหมด</translation>
-<translation id="3625635938337243871">ข้อมูลà¸à¸²à¸£à¸¥à¸‡à¸Šà¸·à¹ˆà¸­à¹€à¸‚้าใช้จะจัดเà¸à¹‡à¸šà¸­à¸¢à¸¹à¹ˆà¹ƒà¸™à¸­à¸¸à¸›à¸à¸£à¸“์นี้หลังจาà¸à¸­à¸­à¸à¸ˆà¸²à¸à¹‚หมดไม่ระบุตัวตน</translation>
<translation id="3630155396527302611">หาà¸à¹‚ปรà¹à¸à¸£à¸¡à¸­à¸¢à¸¹à¹ˆà¹ƒà¸™à¸£à¸²à¸¢à¸à¸²à¸£à¸—ี่ได้รับอนุà¸à¸²à¸•à¹ƒà¸«à¹‰à¹€à¸‚้าถึงเครือข่ายอยู่à¹à¸¥à¹‰à¸§
ลองนำโปรà¹à¸à¸£à¸¡à¸­à¸­à¸à¸ˆà¸²à¸à¸£à¸²à¸¢à¸à¸²à¸£à¹à¸¥à¸°à¹€à¸žà¸´à¹ˆà¸¡à¸à¸¥à¸±à¸šà¹€à¸‚้าไปใหม่</translation>
<translation id="3630699740441428070">ผู้ดูà¹à¸¥à¸£à¸°à¸šà¸šà¸‚องอุปà¸à¸£à¸“์นี้ได้à¸à¸³à¸«à¸™à¸”ค่าà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¹€à¸„รือข่ายของคุณ ซึ่งอาจทำให้เห็นà¸à¸²à¸£à¸ˆà¸£à¸²à¸ˆà¸£à¸‚องข้อมูลในเครือข่าย รวมถึงเว็บไซต์ที่คุณเข้าชม</translation>
<translation id="3631244953324577188">ข้อมูลไบโอเมตริà¸</translation>
<translation id="3633738897356909127">ปุ่มอัปเดต Chrome à¸à¸” Enter เพื่ออัปเดต Chrome จาà¸à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Chrome</translation>
<translation id="3634530185120165534">ถาด 5</translation>
+<translation id="3637662659967048211">บันทึà¸à¸¥à¸‡à¹ƒà¸™à¸šà¸±à¸à¸Šà¸µ Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">à¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชัน:</translation>
<translation id="3650584904733503804">à¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¸ªà¸³à¹€à¸£à¹‡à¸ˆ</translation>
@@ -746,6 +767,7 @@
<translation id="3781428340399460090">ชมพูเจิดจ้า</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">อุปà¸à¸£à¸“์บลูทูธ</translation>
+<translation id="3787675388804467730">หมายเลขบัตรเสมือน</translation>
<translation id="3787705759683870569">หมดอายุ <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">ขนาด 16</translation>
<translation id="3789841737615482174">ติดตั้ง</translation>
@@ -765,6 +787,7 @@
<translation id="3841184659773414994">เครื่องจัดà¸à¸²à¸£à¹„ฟล์</translation>
<translation id="385051799172605136">à¸à¸¥à¸±à¸š</translation>
<translation id="3858027520442213535">อัปเดตวันที่à¹à¸¥à¸°à¹€à¸§à¸¥à¸²</translation>
+<translation id="3881478300875776315">à¹à¸ªà¸”งบรรทัดน้อยลง</translation>
<translation id="3884278016824448484">ตัวชี้อุปà¸à¸£à¸“์ขัดà¹à¸¢à¹‰à¸‡à¸à¸±à¸™</translation>
<translation id="3885155851504623709">Parish</translation>
<translation id="388632593194507180">ตรวจพบà¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸š</translation>
@@ -790,6 +813,7 @@
<translation id="397105322502079400">à¸à¸³à¸¥à¸±à¸‡à¸„ำนวณ...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> ถูà¸à¸šà¸¥à¹‡à¸­à¸</translation>
<translation id="3973357910713125165">ปุ่ม "เรียà¸à¹ƒà¸Šà¹‰à¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¸„วามปลอดภัยของ Chrome" à¸à¸” Enter เพื่อเรียà¸à¹ƒà¸Šà¹‰à¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¸„วามปลอดภัยในà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Chrome</translation>
+<translation id="3986705137476756801">ปิดคำบรรยายสดไปà¸à¹ˆà¸­à¸™</translation>
<translation id="3987405730340719549">Chrome ระบุว่าเว็บไซต์นี้อาจเป็นเว็บไซต์ปลอมหรือฉ้อโà¸à¸‡
หาà¸à¸„ุณเชื่อว่าคำเตือนนี้เป็นข้อผิดพลาด โปรดไปที่ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals</translation>
@@ -811,7 +835,7 @@
<translation id="4082393374666368382">à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า - à¸à¸²à¸£à¸ˆà¸±à¸”à¸à¸²à¸£</translation>
<translation id="4084120443451129199">โหมดà¸à¸²à¸£à¸„้นหา à¸à¸” Enter เพื่อค้นหา <ph name="KEYWORD_SUFFIX" /></translation>
<translation id="4088981014127559358">เปลี่ยนตำà¹à¸«à¸™à¹ˆà¸‡à¸£à¸¹à¸›à¸ à¸²à¸žà¸”้าน 1 ตามà¹à¸à¸™ Y</translation>
-<translation id="4098354747657067197">เว็บไซต์ข้างหน้ามีà¸à¸²à¸£à¸«à¸¥à¸­à¸à¸¥à¸§à¸‡</translation>
+<translation id="4098354747657067197">เว็บไซต์ที่à¸à¸³à¸¥à¸±à¸‡à¸ˆà¸°à¹€à¸‚้าชมไม่ปลอดภัย</translation>
<translation id="4101413244023615925">ข้อความà¹à¸¥à¸°à¸à¸£à¸²à¸Ÿà¸´à¸</translation>
<translation id="4103249731201008433">หมายเลขซีเรียลของอุปà¸à¸£à¸“์ไม่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
<translation id="4110652170750985508">ตรวจสอบà¸à¸²à¸£à¸Šà¸³à¸£à¸°à¹€à¸‡à¸´à¸™</translation>
@@ -881,13 +905,14 @@
<translation id="4275830172053184480">รีสตาร์ทอุปà¸à¸£à¸“์ของคุณ</translation>
<translation id="4277028893293644418">รีเซ็ตรหัสผ่าน</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{บันทึà¸à¸šà¸±à¸•à¸£à¸™à¸µà¹‰à¸¥à¸‡à¹ƒà¸™à¸šà¸±à¸à¸Šà¸µ Google ของคุณà¹à¸¥à¹‰à¸§}other{บันทึà¸à¸šà¸±à¸•à¸£à¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¸¥à¸‡à¹ƒà¸™à¸šà¸±à¸à¸Šà¸µ Google ของคุณà¹à¸¥à¹‰à¸§}}</translation>
+<translation id="4287885627794386150">มีสิทธิ์สำหรับà¸à¸²à¸£à¸—ดลองใช้ à¹à¸•à¹ˆà¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¹„ม่ได้</translation>
<translation id="4297502707443874121">ภาพขนาดย่อของหน้า <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">ขยาย</translation>
<translation id="4300675098767811073">เจาะรูด้านขวาหลายรู</translation>
<translation id="4302514097724775343">à¹à¸•à¸°à¹„ดโนเสาร์เพื่อเล่น</translation>
<translation id="4302965934281694568">Chou3 (ซองจดหมาย)</translation>
<translation id="4305666528087210886">เข้าถึงไฟล์ไม่ได้</translation>
-<translation id="4305817255990598646">สลับ</translation>
+<translation id="4306529830550717874">บันทึà¸à¸—ี่อยู่ไหม</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">บล็อภ(ค่าเริ่มต้น)</translation>
<translation id="4314815835985389558">จัดà¸à¸²à¸£à¸à¸²à¸£à¸‹à¸´à¸‡à¸„์</translation>
@@ -914,6 +939,7 @@
<translation id="4377125064752653719">คุณพยายามเข้าถึง <ph name="DOMAIN" /> à¹à¸•à¹ˆà¹ƒà¸šà¸£à¸±à¸šà¸£à¸­à¸‡à¸—ี่เซิร์ฟเวอร์à¹à¸ˆà¹‰à¸‡à¸¡à¸²à¸–ูà¸à¹€à¸žà¸´à¸à¸–อนโดยผู้ออà¸à¹ƒà¸šà¸£à¸±à¸šà¸£à¸­à¸‡ ซึ่งหมายความว่าข้อมูลรับรองด้านความปลอดภัยที่เซิร์ฟเวอร์à¹à¸ˆà¹‰à¸‡à¸¡à¸²à¸™à¸±à¹‰à¸™à¹„ม่สามารถเชื่อถือได้ คุณอาจà¸à¸³à¸¥à¸±à¸‡à¸•à¸´à¸”ต่อà¸à¸±à¸šà¸„นที่คิดจะโจมตีคุณ</translation>
<translation id="4378154925671717803">โทรศัพท์</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">คำบรรยายสด</translation>
<translation id="4406896451731180161">ผลà¸à¸²à¸£à¸„้นหา</translation>
<translation id="4408413947728134509">คุà¸à¸à¸µà¹‰ <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">คุณเพิ่งใส่รหัสผ่านในเว็บไซต์ที่มีà¸à¸²à¸£à¸«à¸¥à¸­à¸à¸¥à¸§à¸‡ Chrome ขอà¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¹„ปที่ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> à¹à¸¥à¸°à¹€à¸§à¹‡à¸šà¹„ซต์อื่นๆ ที่คุณใช้รหัสผ่านนี้ à¹à¸¥à¸°à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™à¸—ันที</translation>
@@ -926,7 +952,6 @@
<translation id="4435702339979719576">โปสà¸à¸²à¸£à¹Œà¸”)</translation>
<translation id="443673843213245140">à¸à¸²à¸£à¹ƒà¸Šà¹‰à¸žà¸£à¹‡à¸­à¸à¸‹à¸µà¸–ูà¸à¸›à¸´à¸”ใช้งาน à¹à¸•à¹ˆà¸¡à¸µà¸à¸²à¸£à¸£à¸°à¸šà¸¸à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าพร็อà¸à¸‹à¸µà¸­à¸¢à¹ˆà¸²à¸‡à¸Šà¸±à¸”เจน</translation>
<translation id="4464826014807964867">เว็บไซต์ที่มีข้อมูลจาà¸à¸­à¸‡à¸„์à¸à¸£à¸‚องคุณ</translation>
-<translation id="4466881336512663640">à¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹à¸›à¸¥à¸‡à¹ƒà¸™à¸Ÿà¸­à¸£à¹Œà¸¡à¸ˆà¸°à¸«à¸²à¸¢à¹„ป คุณà¹à¸™à¹ˆà¹ƒà¸ˆà¹„หมว่าต้องà¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸•à¹ˆà¸­</translation>
<translation id="4476953670630786061">ฟอร์มนี้ไม่ปลอดภัย ปิดà¸à¸²à¸£à¸›à¹‰à¸­à¸™à¸‚้อความอัตโนมัติà¹à¸¥à¹‰à¸§</translation>
<translation id="4477350412780666475">à¹à¸—ร็à¸à¸–ัดไป</translation>
<translation id="4482953324121162758">ระบบจะไม่à¹à¸›à¸¥à¹€à¸§à¹‡à¸šà¹„ซต์นี้</translation>
@@ -960,6 +985,7 @@
<translation id="4594403342090139922">&amp;เลิà¸à¸—ำà¸à¸²à¸£à¸™à¸³à¸­à¸­à¸</translation>
<translation id="4597348597567598915">ขนาด 8</translation>
<translation id="4600854749408232102">C6/C5 (ซองจดหมาย)</translation>
+<translation id="4606870351894164739">มีประสิทธิภาพ</translation>
<translation id="4628948037717959914">รูปภาพ</translation>
<translation id="4631649115723685955">บริà¸à¸²à¸£à¸„ืนเงินที่ลิงà¸à¹Œà¸­à¸¢à¸¹à¹ˆ</translation>
<translation id="4636930964841734540">ข้อมูล</translation>
@@ -979,6 +1005,7 @@
<translation id="4691835149146451662">Architecture-A (ซองจดหมาย)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">ด้านข้าง</translation>
+<translation id="4702656508969495934">มองเห็นคำบรรยายสดอยู่ ใช้ปุ่มสลับหน้าต่างเพื่อโฟà¸à¸±à¸ª</translation>
<translation id="4708268264240856090">à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸‚องคุณขัดข้อง</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />เรียà¸à¹ƒà¸Šà¹‰à¸à¸²à¸£à¸§à¸´à¸™à¸´à¸ˆà¸‰à¸±à¸¢à¹€à¸„รือข่ายของ Windows<ph name="END_LINK" /></translation>
@@ -992,6 +1019,7 @@
<translation id="4738601419177586157">à¸à¸²à¸£à¹à¸™à¸°à¸™à¸³à¸à¸²à¸£à¸„้นหา <ph name="TEXT" /></translation>
<translation id="4742407542027196863">จัดà¸à¸²à¸£à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™â€¦</translation>
<translation id="4744603770635761495">เส้นทางปà¸à¸´à¸šà¸±à¸•à¸´à¸à¸²à¸£</translation>
+<translation id="4749011317274908093">คุณเข้าสู่โหมดไม่ระบุตัวตนà¹à¸¥à¹‰à¸§</translation>
<translation id="4750917950439032686">ข้อมูลของคุณ (ตัวอย่างเช่น รหัสผ่านหรือหมายเลขบัตรเครดิต) จะเป็นส่วนตัวเมื่อส่งมายังเว็บไซต์นี้</translation>
<translation id="4756388243121344051">&amp;ประวัติà¸à¸²à¸£à¹€à¸‚้าชม</translation>
<translation id="4758311279753947758">เพิ่มข้อมูลติดต่อ</translation>
@@ -1021,6 +1049,8 @@
<translation id="4813512666221746211">ข้อผิดพลาดของเครือข่าย</translation>
<translation id="4816492930507672669">พอดีà¸à¸±à¸šà¸«à¸™à¹‰à¸²</translation>
<translation id="4819347708020428563">à¹à¸à¹‰à¹„ขคำอธิบายประà¸à¸­à¸šà¹ƒà¸™à¸¡à¸¸à¸¡à¸¡à¸­à¸‡à¹€à¸£à¸´à¹ˆà¸¡à¸•à¹‰à¸™à¹ƒà¸Šà¹ˆà¹„หม</translation>
+<translation id="4825507807291741242">ทรงพลัง</translation>
+<translation id="4838327282952368871">ชวนà¸à¸±à¸™</translation>
<translation id="484462545196658690">อัตโนมัติ</translation>
<translation id="4850886885716139402">มุมมอง</translation>
<translation id="485316830061041779">เยอรมัน</translation>
@@ -1151,12 +1181,13 @@
<translation id="5299298092464848405">ข้อผิดพลาดในà¸à¸²à¸£à¹à¸¢à¸à¸§à¸´à¹€à¸„ราะห์นโยบาย</translation>
<translation id="5300589172476337783">à¹à¸ªà¸”ง</translation>
<translation id="5306593769196050043">ทั้ง 2 à¹à¸œà¹ˆà¸™à¸‡à¸²à¸™</translation>
-<translation id="5307166000025436103">ตà¸à¸¥à¸‡</translation>
+<translation id="5307166000025436103">ปà¸à¸•à¸´</translation>
<translation id="5308380583665731573">เชื่อมต่อ</translation>
<translation id="5308689395849655368">à¸à¸²à¸£à¸£à¸²à¸¢à¸‡à¸²à¸™à¸‚้อขัดข้องถูà¸à¸›à¸´à¸”ใช้งาน</translation>
<translation id="5314967030527622926">เครื่องทำจุลสาร</translation>
<translation id="5316812925700871227">หมุนทวนเข็มนาฬิà¸à¸²</translation>
<translation id="5317780077021120954">บันทึà¸</translation>
+<translation id="5321288445143113935">ขยาย</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" /> <ph name="MATCH_POSITION" /> จาภ<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">เลือà¸à¸‚้อมูลติดต่อ</translation>
<translation id="5327248766486351172">ชื่อ</translation>
@@ -1164,11 +1195,13 @@
<translation id="5332219387342487447">วิธีà¸à¸²à¸£à¸ˆà¸±à¸”ส่ง</translation>
<translation id="5333022057423422993">Chrome พบว่ารหัสผ่านที่คุณเพิ่งใช้รั่วไหลในà¸à¸²à¸£à¸¥à¸°à¹€à¸¡à¸´à¸”ข้อมูลครั้งหนึ่ง เราขอà¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™à¸—ี่บันทึà¸à¹„ว้เพื่อรัà¸à¸©à¸²à¸„วามปลอดภัยของบัà¸à¸Šà¸µ</translation>
<translation id="5334013548165032829">บันทึà¸à¸‚องระบบโดยละเอียด</translation>
+<translation id="5334145288572353250">บันทึà¸à¸—ี่อยู่ไหม</translation>
<translation id="5340250774223869109">à¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันถูà¸à¸šà¸¥à¹‡à¸­à¸</translation>
<translation id="534295439873310000">อุปà¸à¸£à¸“์ NFC</translation>
<translation id="5344579389779391559">อาจมีà¸à¸²à¸£à¸žà¸¢à¸²à¸¢à¸²à¸¡à¹€à¸£à¸µà¸¢à¸à¹€à¸à¹‡à¸šà¹€à¸‡à¸´à¸™à¸ˆà¸²à¸à¸„ุณในหน้านี้</translation>
<translation id="5355557959165512791">คุณไม่สามารถไปที่ <ph name="SITE" /> ได้ในขณะนี้เนื่องจาà¸à¹ƒà¸šà¸£à¸±à¸šà¸£à¸­à¸‡à¸–ูà¸à¹€à¸žà¸´à¸à¸–อนà¹à¸¥à¹‰à¸§ โดยปà¸à¸•à¸´à¸‚้อผิดพลาดของเครือข่ายà¹à¸¥à¸°à¸à¸²à¸£à¹‚จมตีจะเà¸à¸´à¸”ขึ้นเพียงชั่วคราว หน้านี้จึงอาจจะใช้งานได้ในภายหลัง</translation>
<translation id="536296301121032821">ไม่สามารถจัดเà¸à¹‡à¸šà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่านโยบาย</translation>
+<translation id="5363309033720083897">พอร์ตอนุà¸à¸£à¸¡à¸™à¸µà¹‰à¹„ด้รับอนุà¸à¸²à¸•à¸ˆà¸²à¸à¸œà¸¹à¹‰à¸”ูà¹à¸¥à¸£à¸°à¸šà¸š</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="5386426401304769735">à¸à¸¥à¸¸à¹ˆà¸¡à¹ƒà¸šà¸£à¸±à¸šà¸£à¸­à¸‡à¸ªà¸³à¸«à¸£à¸±à¸šà¹€à¸§à¹‡à¸šà¹„ซต์นี้มีใบรับรองที่ลงนามโดยใช้ SHA-1</translation>
@@ -1177,6 +1210,7 @@
<translation id="5398772614898833570">บล็อà¸à¹‚ฆษณา</translation>
<translation id="5400836586163650660">สีเทา</translation>
<translation id="540969355065856584">เซิร์ฟเวอร์นี้ไม่สามารถพิสูจน์ได้ว่าเป็น <ph name="DOMAIN" /> เนื่องจาà¸à¹ƒà¸šà¸£à¸±à¸šà¸£à¸­à¸‡à¸„วามปลอดภัยไม่สามารถใช้ได้ในขณะนี้ ซึ่งอาจเป็นเพราะà¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าที่ไม่ถูà¸à¸•à¹‰à¸­à¸‡à¸«à¸£à¸·à¸­à¸¡à¸µà¸œà¸¹à¹‰à¹‚จมตีที่ขัดขวางà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸‚องคุณ</translation>
+<translation id="541143247543991491">ระบบคลาวด์ (ทั้งระบบ)</translation>
<translation id="541416427766103491">สà¹à¸•à¹‡à¸à¹€à¸à¸­à¸£à¹Œ 4</translation>
<translation id="5421136146218899937">ล้างข้อมูลà¸à¸²à¸£à¸—่องเว็บ...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> ต้องà¸à¸²à¸£à¸ªà¹ˆà¸‡à¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•à¸·à¸­à¸™à¹ƒà¸«à¹‰à¸„ุณ</translation>
@@ -1190,6 +1224,7 @@
<translation id="5455374756549232013">เวลาบันทึà¸à¸‚องนโยบายไม่เหมาะสม</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" /> รายà¸à¸²à¸£}other{<ph name="CONTACT_PREVIEW" /> à¹à¸¥à¸°à¸­à¸µà¸ <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> รายà¸à¸²à¸£}}</translation>
+<translation id="5463625433003343978">à¸à¸³à¸¥à¸±à¸‡à¸„้นหาอุปà¸à¸£à¸“์...</translation>
<translation id="5469868506864199649">อิตาลี</translation>
<translation id="5470861586879999274">&amp;ทำซ้ำà¸à¸²à¸£à¹à¸à¹‰à¹„ข</translation>
<translation id="5478437291406423475">B6/C4 (ซองจดหมาย)</translation>
@@ -1239,7 +1274,6 @@
<translation id="5624120631404540903">จัดà¸à¸²à¸£à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™</translation>
<translation id="5629630648637658800">ไม่สามารถโหลดà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่านโยบาย</translation>
<translation id="5631439013527180824">โทเค็นà¸à¸²à¸£à¸ˆà¸±à¸”à¸à¸²à¸£à¸­à¸¸à¸›à¸à¸£à¸“์ไม่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
-<translation id="5632627355679805402">ข้อมูลของคุณเข้ารหัสลับไว้ด้วย<ph name="BEGIN_LINK" />รหัสผ่าน Google<ph name="END_LINK" /> เมื่อ <ph name="TIME" /> ป้อนรหัสผ่านเพื่อเริ่มซิงค์</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="5644090287519800334">เปลี่ยนตำà¹à¸«à¸™à¹ˆà¸‡à¸£à¸¹à¸›à¸ à¸²à¸žà¸”้าน 1 ตามà¹à¸à¸™ X</translation>
@@ -1278,12 +1312,12 @@
<translation id="5785756445106461925">นอà¸à¸ˆà¸²à¸à¸™à¸µà¹‰ หน้านี้ประà¸à¸­à¸šà¸”้วยทรัพยาà¸à¸£à¸­à¸·à¹ˆà¸™à¹† ซึ่งไม่ปลอดภัย ผู้อื่นสามารถดูทรัพยาà¸à¸£à¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¸‚ณะถ่ายโอน à¹à¸¥à¸°à¸œà¸¹à¹‰à¸šà¸¸à¸à¸£à¸¸à¸à¸ªà¸²à¸¡à¸²à¸£à¸–à¹à¸à¹‰à¹„ขเพื่อเปลี่ยนรูปลัà¸à¸©à¸“์ของหน้าได้</translation>
<translation id="5786044859038896871">คุณต้องà¸à¸²à¸£à¸à¸£à¸­à¸à¸‚้อมูลบัตรไหม</translation>
<translation id="578633867165174378">Chrome พบว่ารหัสผ่านที่คุณเพิ่งใช้รั่วไหลในà¸à¸²à¸£à¸¥à¸°à¹€à¸¡à¸´à¸”ข้อมูลครั้งหนึ่ง เราขอà¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™à¸™à¸µà¹‰à¸—ันที</translation>
-<translation id="5798290721819630480">ทิ้งà¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹à¸›à¸¥à¸‡à¹„หม</translation>
<translation id="5803412860119678065">คุณต้องà¸à¸²à¸£à¸à¸£à¸­à¸à¸‚้อมูล <ph name="CARD_DETAIL" /> ไหม</translation>
<translation id="5804241973901381774">à¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•</translation>
<translation id="5804427196348435412">ใช้อุปà¸à¸£à¸“์ NFC</translation>
<translation id="5810442152076338065">มีà¸à¸²à¸£à¹€à¸‚้ารหัสà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸‚องคุณà¸à¸±à¸š <ph name="DOMAIN" /> ด้วยชุดà¸à¸²à¸£à¹€à¸‚้ารหัสที่ล้าสมัยà¹à¸¥à¹‰à¸§</translation>
<translation id="5813119285467412249">&amp;ทำซ้ำà¸à¸²à¸£à¹€à¸žà¸´à¹ˆà¸¡</translation>
+<translation id="5817918615728894473">จับคู่</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{ระบบจะเรียà¸à¹€à¸à¹‡à¸šà¹€à¸‡à¸´à¸™à¸ˆà¸²à¸à¸šà¸±à¸•à¸£à¸™à¸µà¹‰à¹€à¸¡à¸·à¹ˆà¸­à¸„ุณชำระเงิน à¹à¸•à¹ˆà¸ˆà¸°à¹„ม่à¹à¸Šà¸£à¹Œà¸«à¸¡à¸²à¸¢à¹€à¸¥à¸‚บัตรจริงà¸à¸±à¸šà¹€à¸§à¹‡à¸šà¹„ซต์นี้ เพื่อความปลอดภัยมาà¸à¸‚ึ้น ระบบจะสร้างรหัส CVC ชั่วคราวขึ้นมา}other{ระบบจะเรียà¸à¹€à¸à¹‡à¸šà¹€à¸‡à¸´à¸™à¸ˆà¸²à¸à¸šà¸±à¸•à¸£à¸—ี่เลือà¸à¹€à¸¡à¸·à¹ˆà¸­à¸„ุณชำระเงิน à¹à¸•à¹ˆà¸ˆà¸°à¹„ม่à¹à¸Šà¸£à¹Œà¸«à¸¡à¸²à¸¢à¹€à¸¥à¸‚บัตรจริงà¸à¸±à¸šà¹€à¸§à¹‡à¸šà¹„ซต์นี้ เพื่อความปลอดภัยมาà¸à¸‚ึ้น ระบบจะสร้างรหัส CVC ชั่วคราวขึ้นมา}}</translation>
<translation id="5826507051599432481">ชื่อทั่วไป (CN)</translation>
<translation id="5838278095973806738">คุณไม่ควรป้อนข้อมูลที่ละเอียดอ่อนบนเว็บไซต์นี้ (ตัวอย่างเช่น รหัสผ่านหรือบัตรเครดิต) เนื่องจาà¸à¸œà¸¹à¹‰à¹‚จมตีอาจขโมยข้อมูลดังà¸à¸¥à¹ˆà¸²à¸§à¹„ปได้</translation>
@@ -1291,6 +1325,7 @@
<translation id="5855253129151731373">ชื่อโฮสต์ของเว็บไซต์นี้ดูคล้ายà¸à¸±à¸š <ph name="LOOKALIKE_DOMAIN" /> บางครั้งผู้โจมตีจะเลียนà¹à¸šà¸šà¹€à¸§à¹‡à¸šà¹„ซต์ต่างๆ โดยทำà¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹à¸›à¸¥à¸‡à¹€à¸¥à¹‡à¸à¹† น้อยๆ ที่สังเà¸à¸•à¹€à¸«à¹‡à¸™à¹„ด้ยาà¸à¸à¸±à¸šà¸Šà¸·à¹ˆà¸­à¹‚ดเมน
หาà¸à¸„ุณเชื่อว่าคำเตือนนี้เป็นข้อผิดพลาด โปรดไปที่ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals</translation>
+<translation id="5860033963881614850">ปิด</translation>
<translation id="5862579898803147654">สà¹à¸•à¹‡à¸à¹€à¸à¸­à¸£à¹Œ 8</translation>
<translation id="5863847714970149516">ระบบอาจพยายามเรียà¸à¹€à¸à¹‡à¸šà¹€à¸‡à¸´à¸™à¸ˆà¸²à¸à¸„ุณในหน้าถัดไป</translation>
<translation id="5866257070973731571">เพิ่มหมายเลขโทรศัพท์</translation>
@@ -1307,6 +1342,7 @@
<translation id="5913377024445952699">à¸à¸²à¸£à¸ˆà¸±à¸šà¸ à¸²à¸žà¸«à¸™à¹‰à¸²à¸ˆà¸­à¸«à¸¢à¸¸à¸”อยู่ชั่วคราว</translation>
<translation id="59174027418879706">เปิดใช้งาน</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{ใช้งานอยู่ 1 รายà¸à¸²à¸£}other{ใช้งานอยู่ # รายà¸à¸²à¸£}}</translation>
<translation id="5921185718311485855">เปิด</translation>
<translation id="5921639886840618607">บันทึà¸à¸šà¸±à¸•à¸£à¸¥à¸‡à¹ƒà¸™à¸šà¸±à¸à¸Šà¸µ Google ไหม</translation>
<translation id="5922853866070715753">เà¸à¸·à¸­à¸šà¹€à¸ªà¸£à¹‡à¸ˆà¹à¸¥à¹‰à¸§</translation>
@@ -1326,6 +1362,7 @@
<translation id="5989320800837274978">ไม่มีà¸à¸²à¸£à¸£à¸°à¸šà¸¸à¸—ั้งพร็อà¸à¸‹à¸µà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸­à¸£à¹Œà¹à¸šà¸šà¸„งที่หรือ URL สคริปต์ .pac</translation>
<translation id="5992691462791905444">พับทบà¹à¸šà¸š Engineering รูปตัว Z</translation>
<translation id="6000758707621254961">มีผลà¸à¸²à¸£à¸„้นหา "<ph name="SEARCH_TEXT" />" <ph name="RESULT_COUNT" /> รายà¸à¸²à¸£</translation>
+<translation id="6006484371116297560">คลาสสิà¸</translation>
<translation id="6008122969617370890">ลำดับ N ถึง 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">ตรวจสอบรหัสผ่านของคุณ</translation>
@@ -1347,6 +1384,7 @@
<translation id="6045164183059402045">เทมเพลตà¸à¸²à¸£à¸ˆà¸±à¸”เรียงหน้าà¸à¹ˆà¸­à¸™à¸žà¸´à¸¡à¸žà¹Œ</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="6049004884579590341">à¸à¸” |<ph name="ACCELERATOR" />| ค้างไว้เพื่อออà¸à¸ˆà¸²à¸à¹‚หมดเต็มหน้าจอ</translation>
<translation id="6049488691372270142">หน้าที่à¹à¸ªà¸”ง</translation>
<translation id="6051221802930200923">คุณไม่สามารถไปที่ <ph name="SITE" /> ได้ในขณะนี้เนื่องจาà¸à¹€à¸§à¹‡à¸šà¹„ซต์ใช้à¸à¸²à¸£à¸•à¸£à¸¶à¸‡à¹ƒà¸šà¸£à¸±à¸šà¸£à¸­à¸‡ โดยปà¸à¸•à¸´à¸‚้อผิดพลาดของเครือข่ายà¹à¸¥à¸°à¸à¸²à¸£à¹‚จมตีจะเà¸à¸´à¸”ขึ้นเพียงชั่วคราว หน้านี้จึงอาจใช้งานได้ในภายหลัง</translation>
<translation id="6051898664905071243">จำนวนหน้า:</translation>
@@ -1363,6 +1401,7 @@
<translation id="610911394827799129">บัà¸à¸Šà¸µ Google อาจมีประวัติà¸à¸²à¸£à¸—่องเว็บรูปà¹à¸šà¸šà¸­à¸·à¹ˆà¸™à¹† ที่ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">ดูข้อความà¹à¸¥à¸°à¸£à¸¹à¸›à¸ à¸²à¸žà¸—ี่คัดลอà¸à¹„ปที่คลิปบอร์ด</translation>
<translation id="6120179357481664955">จำรหัส UPI ไหม</translation>
+<translation id="6123290840358279103">ดูบัตรเสมือน</translation>
<translation id="6124432979022149706">เครื่องมือเชื่อมต่อ Chrome Enterprise</translation>
<translation id="6146055958333702838">ตรวจสายเคเบิลà¹à¸¥à¸°à¸£à¸µà¸šà¸¹à¸•à¹€à¸£à¸²à¹€à¸•à¸­à¸£à¹Œ โมเด็ม หรืออุปà¸à¸£à¸“์เครือข่ายอื่น
ที่คุณอาจใช้งานอยู่</translation>
@@ -1399,6 +1438,7 @@
<translation id="6289939620939689042">สีของหน้าเว็บ</translation>
<translation id="6290238015253830360">บทความที่à¹à¸™à¸°à¸™à¸³à¸ˆà¸°à¸›à¸£à¸²à¸à¸à¸—ี่นี่</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Google Assistant ใน Chrome หยุดทำงาน</translation>
<translation id="6305205051461490394">ไม่สามารถเข้าถึง <ph name="URL" /></translation>
<translation id="6312113039770857350">หน้าเว็บไม่พร้อมใช้งาน</translation>
@@ -1424,6 +1464,7 @@
<translation id="6390200185239044127">พับครึ่งà¹à¸šà¸šà¸•à¸±à¸§ Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">นโยบายของผู้ดูà¹à¸¥à¸£à¸°à¸šà¸šà¸šà¸¥à¹‡à¸­à¸à¸à¸²à¸£à¸§à¸²à¸‡à¸ˆà¸²à¸ <ph name="ORIGIN_NAME" /> ลงในตำà¹à¸«à¸™à¹ˆà¸‡à¸™à¸µà¹‰à¹„ว้</translation>
+<translation id="6398765197997659313">ออà¸à¸ˆà¸²à¸à¸à¸²à¸£à¹à¸ªà¸”งà¹à¸šà¸šà¹€à¸•à¹‡à¸¡à¸«à¸™à¹‰à¸²à¸ˆà¸­</translation>
<translation id="6401136357288658127">นโยบายนี้เลิà¸à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¹„ปà¹à¸¥à¹‰à¸§ คุณควรใช้นโยบาย <ph name="NEW_POLICY" /> à¹à¸—น</translation>
<translation id="6404511346730675251">à¹à¸à¹‰à¹„ขบุ๊à¸à¸¡à¸²à¸£à¹Œà¸</translation>
<translation id="6406765186087300643">C0 (ซองจดหมาย)</translation>
@@ -1436,7 +1477,6 @@
<translation id="6428450836711225518">ยืนยันเบอร์โทรศัพท์</translation>
<translation id="6433490469411711332">à¹à¸à¹‰à¹„ขข้อมูลติดต่อ</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> ปà¸à¸´à¹€à¸ªà¸˜à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­</translation>
-<translation id="6434309073475700221">ทิ้ง</translation>
<translation id="6440503408713884761">ละเว้น</translation>
<translation id="6443406338865242315">ส่วนขยายà¹à¸¥à¸°à¸›à¸¥à¸±à¹Šà¸à¸­à¸´à¸™à¸—ี่คุณติดตั้ง</translation>
<translation id="6446163441502663861">Kahu (ซองจดหมาย)</translation>
@@ -1479,6 +1519,7 @@
<translation id="6624427990725312378">ข้อมูลติดต่อ</translation>
<translation id="6626291197371920147">เพิ่มหมายเลขบัตรที่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> ค้นหา</translation>
+<translation id="6630043285902923878">à¸à¸³à¸¥à¸±à¸‡à¸„้นหาอุปà¸à¸£à¸“์ USB...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ล้าง</translation>
@@ -1494,6 +1535,7 @@
<translation id="6671697161687535275">ต้องà¸à¸²à¸£à¸™à¸³à¸„ำà¹à¸™à¸°à¸™à¸³à¸ªà¸³à¸«à¸£à¸±à¸šà¹à¸šà¸šà¸Ÿà¸­à¸£à¹Œà¸¡à¸­à¸­à¸à¸ˆà¸²à¸ Chromium ใช่ไหม</translation>
<translation id="6685834062052613830">ออà¸à¸ˆà¸²à¸à¸£à¸°à¸šà¸šà¹à¸¥à¸°à¸•à¸±à¹‰à¸‡à¸„่าให้เสร็จสมบูรณ์</translation>
<translation id="6687335167692595844">ขอขนาดà¹à¸šà¸šà¸­à¸±à¸à¸©à¸£à¹à¸¥à¹‰à¸§</translation>
+<translation id="6688743156324860098">อัปเดต…</translation>
<translation id="6689249931105087298">สัมพัทธ์à¸à¸±à¸šà¸à¸²à¸£à¸šà¸µà¸šà¸ˆà¸¸à¸”สีดำ</translation>
<translation id="6689271823431384964">Chrome เสนอที่จะบันทึà¸à¸šà¸±à¸•à¸£à¸¥à¸‡à¹ƒà¸™à¸šà¸±à¸à¸Šà¸µ Google ของคุณเพราะคุณลงชื่อเข้าใช้อยู่ คุณปรับเปลี่ยนลัà¸à¸©à¸“ะà¸à¸²à¸£à¸—ำงานนี้ได้ในà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า ชื่อผู้ถือบัตรมาจาà¸à¸šà¸±à¸à¸Šà¸µà¸‚องคุณ</translation>
<translation id="6698381487523150993">สร้าง:</translation>
@@ -1509,6 +1551,7 @@
<translation id="6744009308914054259">ระหว่างที่รอà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­ คุณไปที่หน้า "ดาวน์โหลด" เพื่ออ่านบทความออฟไลน์ได้</translation>
<translation id="6753269504797312559">ค่านโยบาย</translation>
<translation id="6757797048963528358">อุปà¸à¸£à¸“์ของคุณเข้าสู่โหมดสลีปà¹à¸¥à¹‰à¸§</translation>
+<translation id="6767985426384634228">อัปเดตที่อยู่ไหม</translation>
<translation id="6768213884286397650">Hagaki (โปสà¸à¸²à¸£à¹Œà¸”)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">ม่วงอมน้ำเงิน</translation>
@@ -1531,6 +1574,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome ทำให้หน้านี้อ่านง่ายขึ้น Chrome ดึงข้อมูลหน้าต้นฉบับผ่านà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­à¸—ี่ไม่ปลอดภัย</translation>
<translation id="6891596781022320156">ระดับนโยบายไม่ได้รับà¸à¸²à¸£à¸ªà¸™à¸±à¸šà¸ªà¸™à¸¸à¸™</translation>
+<translation id="6895143722905299846">หมายเลขเสมือน:</translation>
<translation id="6895330447102777224">บัตรของคุณได้รับà¸à¸²à¸£à¸¢à¸·à¸™à¸¢à¸±à¸™à¹à¸¥à¹‰à¸§</translation>
<translation id="6897140037006041989">User agent</translation>
<translation id="6898699227549475383">องค์à¸à¸£ (O)</translation>
@@ -1566,10 +1610,10 @@
<translation id="7004583254764674281">ใช้ Windows Hello เพื่อยืนยันบัตรได้เร็วขึ้น</translation>
<translation id="7006930604109697472">ส่งเลย</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าà¸à¸²à¸£à¸›à¸£à¸±à¸šà¸‚นาด</translation>
<translation id="7014741021609395734">ระดับà¸à¸²à¸£à¸‹à¸¹à¸¡</translation>
<translation id="7016992613359344582">à¸à¸²à¸£à¹€à¸£à¸µà¸¢à¸à¹€à¸à¹‡à¸šà¹€à¸‡à¸´à¸™à¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¸­à¸²à¸ˆà¹€à¸à¸´à¸”ขึ้นครั้งเดียวหรือเป็นเà¸à¸´à¸”ขึ้นซ้ำๆ à¹à¸¥à¸°à¸­à¸²à¸ˆà¹„ม่à¹à¸ªà¸”งอย่างชัดà¹à¸ˆà¹‰à¸‡</translation>
<translation id="7029809446516969842">รหัสผ่าน</translation>
+<translation id="7030436163253143341">ใบรับรองไม่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
<translation id="7031646650991750659">à¹à¸­à¸›à¸ˆà¸²à¸ Google Play ที่คุณติดตั้ง</translation>
<translation id="7050187094878475250">คุณพยายามเข้าถึง <ph name="DOMAIN" /> à¹à¸•à¹ˆà¹€à¸‹à¸´à¸£à¹Œà¸Ÿà¹€à¸§à¸­à¸£à¹Œà¹„ด้à¹à¸ªà¸”งใบรับรองที่มีระยะเวลาที่สามารถใช้ได้นานเà¸à¸´à¸™à¸à¸§à¹ˆà¸²à¸—ี่จะเชื่อถือได้</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{บันทึà¸à¸šà¸±à¸•à¸£à¸™à¸µà¹‰à¹„ม่ได้ในตอนนี้}other{บันทึà¸à¸šà¸±à¸•à¸£à¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¹„ม่ได้ในตอนนี้}}</translation>
@@ -1639,12 +1683,14 @@
<translation id="7300012071106347854">น้ำเงินเข้ม</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">สูง</translation>
+<translation id="7305756307268530424">เริ่มโดยให้ช้าลง</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">ความช่วยเหลือเà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸šà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­</translation>
<translation id="7323804146520582233">ซ่อนส่วน "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">ลบล้างบัà¸à¸Šà¸µà¸ à¸²à¸¢à¹ƒà¸™à¸­à¸¸à¸›à¸à¸£à¸“์</translation>
<translation id="7333654844024768166">คุณเพิ่งใส่รหัสผ่านในเว็บไซต์ที่มีà¸à¸²à¸£à¸«à¸¥à¸­à¸à¸¥à¸§à¸‡ Chromium ขอà¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¹„ปที่ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> à¹à¸¥à¸°à¹€à¸§à¹‡à¸šà¹„ซต์อื่นๆ ที่คุณใช้รหัสผ่านนี้ à¹à¸¥à¸°à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™à¸—ันที</translation>
<translation id="7334320624316649418">&amp;ทำซ้ำà¸à¸²à¸£à¸ˆà¸±à¸”ลำดับใหม่</translation>
+<translation id="7337248890521463931">à¹à¸ªà¸”งบรรทัดเพิ่มเติม</translation>
<translation id="7337706099755338005">ยังไม่พร้อมให้ใช้งานในà¹à¸žà¸¥à¸•à¸Ÿà¸­à¸£à¹Œà¸¡à¸‚องคุณ</translation>
<translation id="733923710415886693">ไม่มีà¸à¸²à¸£à¹€à¸›à¸´à¸”เผยใบรับรองของเซิร์ฟเวอร์ผ่านความโปร่งใสของใบรับรอง</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1652,6 +1698,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">บรรทัดคำสั่ง </translation>
<translation id="7359588939039777303">บล็อà¸à¹‚ฆษณา</translation>
+<translation id="7363096869660964304">อย่างไรà¸à¹‡à¸•à¸²à¸¡ คนอื่นจะยังมองเห็นคุณ à¸à¸²à¸£à¹€à¸‚้าสู่โหมดไม่ระบุตัวตนไม่ได้เป็นà¸à¸²à¸£à¸‹à¹ˆà¸­à¸™à¸à¸²à¸£à¸—่องเว็บจาà¸à¸™à¸²à¸¢à¸ˆà¹‰à¸²à¸‡à¸‚องคุณ ผู้ให้บริà¸à¸²à¸£à¸­à¸´à¸™à¹€à¸—อร์เน็ต หรือเว็บไซต์ที่คุณเข้าชม</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" /> à¸à¸” Tab ตามด้วย Enter เพื่อเพิ่มà¹à¸¥à¸°à¸ˆà¸±à¸”à¸à¸²à¸£à¸—ี่อยู่ในà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Chrome</translation>
<translation id="7365849542400970216">หาà¸à¸•à¹‰à¸­à¸‡à¸à¸²à¸£à¸—ราบเà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸šà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¸­à¸¸à¸›à¸à¸£à¸“์</translation>
<translation id="7372973238305370288">ผลà¸à¸²à¸£à¸„้นหา</translation>
@@ -1662,7 +1709,9 @@
<translation id="7378594059915113390">à¸à¸²à¸£à¸„วบคุมสื่อ</translation>
<translation id="7378627244592794276">ไม่</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ไม่เà¸à¸µà¹ˆà¸¢à¸§à¸‚้อง</translation>
<translation id="7390545607259442187">ยืนยันบัตร</translation>
+<translation id="7392089738299859607">อัปเดตที่อยู่</translation>
<translation id="7399802613464275309">à¸à¸²à¸£à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¸„วามปลอดภัย</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> ของคุณมีà¸à¸²à¸£à¸ˆà¸±à¸”à¸à¸²à¸£</translation>
@@ -1677,6 +1726,7 @@
&lt;li&gt;ไปที่&lt;a href="https://support.google.com/chrome/answer/6098869"&gt;ศูนย์ช่วยเหลือของ Chrome&lt;/a&gt; เพื่อดูวิธีนำซอฟต์à¹à¸§à¸£à¹Œà¸”ังà¸à¸¥à¹ˆà¸²à¸§à¸­à¸­à¸à¸ˆà¸²à¸à¸„อมพิวเตอร์อย่างถาวร
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">น่ารัà¸</translation>
<translation id="7416351320495623771">จัดà¸à¸²à¸£à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™â€¦</translation>
<translation id="7419106976560586862">เส้นทางโปรไฟล์</translation>
<translation id="7437289804838430631">เพิ่มข้อมูลติดต่อ</translation>
@@ -1692,7 +1742,7 @@
<translation id="7481312909269577407">ส่งต่อ</translation>
<translation id="7485870689360869515">ไม่พบข้อมูล</translation>
<translation id="7495528107193238112">เนื้อหานี้ถูà¸à¸šà¸¥à¹‡à¸­à¸ โปรดติดต่อเจ้าของเว็บไซต์เพื่อให้à¹à¸à¹‰à¸›à¸±à¸à¸«à¸²</translation>
-<translation id="7498234416455752244">à¹à¸à¹‰à¹„ขต่อ</translation>
+<translation id="7498193950643227031">à¹à¸­à¸›à¸­à¸²à¸ˆà¸—ำงานผิดปà¸à¸•à¸´à¸«à¸²à¸à¸¡à¸µà¸à¸²à¸£à¸›à¸£à¸±à¸šà¸‚นาด คุณจำà¸à¸±à¸”ความสามารถในà¸à¸²à¸£à¸›à¸£à¸±à¸šà¸‚นาดà¹à¸­à¸›à¹„ด้ใน <ph name="SETTINGS" /></translation>
<translation id="7503664977220660814">คุณเพิ่งใส่รหัสผ่านในเว็บไซต์ที่มีà¸à¸²à¸£à¸«à¸¥à¸­à¸à¸¥à¸§à¸‡ Chromium ขอà¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™à¸—ี่บันทึà¸à¹„ว้สำหรับ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> à¹à¸¥à¸°à¹€à¸§à¹‡à¸šà¹„ซต์อื่นๆ ที่คุณใช้รหัสผ่านนี้ทันที</translation>
<translation id="7508255263130623398">รหัสอุปà¸à¸£à¸“์นโยบายที่ส่งà¸à¸¥à¸±à¸šà¸§à¹ˆà¸²à¸‡à¹€à¸›à¸¥à¹ˆà¸²à¸«à¸£à¸·à¸­à¹„ม่ตรงà¸à¸±à¸šà¸£à¸«à¸±à¸ªà¸­à¸¸à¸›à¸à¸£à¸“์ปัจจุบัน</translation>
<translation id="7508870219247277067">เขียวอะโวคาโด</translation>
@@ -1712,6 +1762,7 @@
<translation id="7548892272833184391">à¹à¸à¹‰à¹„ขข้อผิดพลาดในà¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•à¹ˆà¸­</translation>
<translation id="7549584377607005141">หน้าเว็บนี้ต้องใช้ข้อมูลที่คุณป้อนà¸à¹ˆà¸­à¸™à¸«à¸™à¹‰à¸²à¸™à¸µà¹‰à¹€à¸žà¸·à¹ˆà¸­à¹ƒà¸«à¹‰à¹à¸ªà¸”งได้อย่างถูà¸à¸•à¹‰à¸­à¸‡ คุณสามารถส่งข้อมูลนี้ได้อีà¸à¸„รั้ง à¹à¸•à¹ˆà¸à¸²à¸£à¸—ำเช่นนั้นจะเป็นà¸à¸²à¸£à¸—ำสิ่งที่หน้าเว็บนี้เคยดำเนินà¸à¸²à¸£à¸‹à¹‰à¸³à¸­à¸µà¸à¸„รั้ง</translation>
<translation id="7550637293666041147">ชื่อผู้ใช้ของคุณในอุปà¸à¸£à¸“์à¹à¸¥à¸°à¹ƒà¸™ Chrome</translation>
+<translation id="755279583747225797">สามารถใช้à¸à¸²à¸£à¸—ดลองใช้ได้</translation>
<translation id="7552846755917812628">ลองทำตามเคล็ดลับต่อไปนี้:</translation>
<translation id="7554475479213504905">โหลดซ้ำà¹à¸¥à¸°à¹à¸ªà¸”งเนื้อหา</translation>
<translation id="7554791636758816595">à¹à¸—็บใหม่</translation>
@@ -1730,7 +1781,6 @@
<translation id="7610193165460212391">ค่าอยู่นอà¸à¸Šà¹ˆà¸§à¸‡ <ph name="VALUE" /></translation>
<translation id="7613889955535752492">หมดอายุ: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" /> à¸à¸” Tab ตามด้วย Enter เพื่อดูà¹à¸¥à¸°à¸ˆà¸±à¸”à¸à¸²à¸£à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™à¹ƒà¸™à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Chrome</translation>
-<translation id="7615602087246926389">คุณมีข้อมูลที่ถูà¸à¹€à¸‚้ารหัสโดยใช้รหัสผ่านบัà¸à¸Šà¸µ Google รูปà¹à¸šà¸šà¸­à¸·à¹ˆà¸™à¸­à¸¢à¸¹à¹ˆà¹à¸¥à¹‰à¸§ โปรดป้อนรหัสผ่านด้านล่าง</translation>
<translation id="7616645509853975347">ผู้ดูà¹à¸¥à¸£à¸°à¸šà¸šà¹„ด้เปิดใช้เครื่องมือเชื่อมต่อ Chrome Enterprise ในเบราว์เซอร์ เครื่องมือเชื่อมต่อเหล่านี้เข้าถึงข้อมูลบางอย่างของคุณได้</translation>
<translation id="7619838219691048931">à¹à¸œà¹ˆà¸™à¸‡à¸²à¸™à¸ªà¸¸à¸”ท้าย</translation>
<translation id="762844065391966283">ทีละรายà¸à¸²à¸£</translation>
@@ -1795,13 +1845,12 @@
<translation id="782886543891417279">Wi-Fi ที่คุณใช้ (<ph name="WIFI_NAME" />) อาจต้องà¸à¸²à¸£à¹ƒà¸«à¹‰à¸„ุณไปที่หน้าà¸à¸²à¸£à¹€à¸‚้าสู่ระบบ</translation>
<translation id="7836231406687464395">Postfix (ซองจดหมาย)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ไม่มี}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">เปิดไฟล์โดยใช้à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¹‚ยงประเภทไฟล์</translation>
<translation id="7862185352068345852">ออà¸à¸ˆà¸²à¸à¹€à¸§à¹‡à¸šà¹„ซต์ไหม</translation>
<translation id="7865448901209910068">เร็วที่สุด</translation>
<translation id="7874263914261512992">คุณเพิ่งใส่รหัสผ่านในเว็บไซต์ที่มีà¸à¸²à¸£à¸«à¸¥à¸­à¸à¸¥à¸§à¸‡ Chrome ขอà¹à¸™à¸°à¸™à¸³à¹ƒà¸«à¹‰à¸•à¸£à¸§à¸ˆà¸ªà¸­à¸šà¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™à¸—ี่บันทึà¸à¹„ว้สำหรับ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> à¹à¸¥à¸°à¹€à¸§à¹‡à¸šà¹„ซต์อื่นๆ ที่คุณใช้รหัสผ่านนี้ทันที</translation>
<translation id="7878562273885520351">รหัสผ่านของคุณอาจถูà¸à¸‚โมยได้</translation>
+<translation id="7880146494886811634">บันทึà¸à¸—ี่อยู่</translation>
<translation id="7882421473871500483">น้ำตาล</translation>
<translation id="7887683347370398519">ตรวจสอบ CVC à¹à¸¥à¸°à¸¥à¸­à¸‡à¸­à¸µà¸à¸„รั้ง</translation>
<translation id="7887885240995164102">เข้าสู่à¸à¸²à¸£à¹à¸ªà¸”งภาพซ้อนภาพ</translation>
@@ -1809,6 +1858,7 @@
<translation id="7894280532028510793">หาà¸à¸à¸²à¸£à¸ªà¸°à¸à¸”ถูà¸à¸•à¹‰à¸­à¸‡ ให้<ph name="BEGIN_LINK" />ลองเรียà¸à¹ƒà¸Šà¹‰à¸à¸²à¸£à¸§à¸´à¸™à¸´à¸ˆà¸‰à¸±à¸¢à¹€à¸„รือข่าย<ph name="END_LINK" /></translation>
<translation id="7904208859782148177">C3 (ซองจดหมาย)</translation>
<translation id="7931318309563332511">ไม่รู้จัà¸</translation>
+<translation id="793209273132572360">อัปเดตที่อยู่ไหม</translation>
<translation id="7932579305932748336">เคลือบ</translation>
<translation id="79338296614623784">ป้อนหมายเลขโทรศัพท์ที่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
<translation id="7934052535022478634">à¸à¸²à¸£à¸Šà¸³à¸£à¸°à¹€à¸‡à¸´à¸™à¹€à¸ªà¸£à¹‡à¸ˆà¸ªà¸¡à¸šà¸¹à¸£à¸“์</translation>
@@ -1879,6 +1929,7 @@
<translation id="8175796834047840627">Chrome เสนอที่จะบันทึà¸à¸šà¸±à¸•à¸£à¸¥à¸‡à¹ƒà¸™à¸šà¸±à¸à¸Šà¸µ Google ของคุณเพราะคุณลงชื่อเข้าใช้อยู่ คุณปรับเปลี่ยนลัà¸à¸©à¸“ะà¸à¸²à¸£à¸—ำงานนี้ได้ในà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า</translation>
<translation id="8176440868214972690">ผู้ดูà¹à¸¥à¸£à¸°à¸šà¸šà¸‚องอุปà¸à¸£à¸“์นี้ได้ส่งข้อมูลบางอย่าง เช่น à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่าหรือนโยบายไปยังเว็บไซต์ต่อไปนี้</translation>
<translation id="8184538546369750125">ใช้ค่าเริ่มต้นสาà¸à¸¥ (อนุà¸à¸²à¸•)</translation>
+<translation id="8193086767630290324">à¸à¸²à¸£à¸”ำเนินà¸à¸²à¸£à¸à¸±à¸šà¸‚้อมูลที่à¹à¸ˆà¹‰à¸‡à¸§à¹ˆà¸²à¹€à¸›à¹‡à¸™à¸„วามลับ</translation>
<translation id="8194797478851900357">&amp;เลิà¸à¸—ำà¸à¸²à¸£à¸¢à¹‰à¸²à¸¢</translation>
<translation id="8201077131113104583">à¸à¸²à¸£à¸­à¸±à¸›à¹€à¸”ต URL ไม่ถูà¸à¸•à¹‰à¸­à¸‡à¸ªà¸³à¸«à¸£à¸±à¸šà¸ªà¹ˆà¸§à¸™à¸‚ยายรหัส "<ph name="EXTENSION_ID" />"</translation>
<translation id="8202097416529803614">ข้อมูลสรุปคำสั่งซื้อ</translation>
@@ -1901,6 +1952,7 @@
<translation id="8249296373107784235">ล้มเลิà¸</translation>
<translation id="8249320324621329438">เรียà¸à¸”ูครั้งสุดท้ายเมื่อ:</translation>
<translation id="8253091569723639551">ต้องใส่ที่อยู่สำหรับà¸à¸²à¸£à¹€à¸£à¸µà¸¢à¸à¹€à¸à¹‡à¸šà¹€à¸‡à¸´à¸™</translation>
+<translation id="8257387598443225809">à¹à¸­à¸›à¸™à¸µà¹‰à¸­à¸­à¸à¹à¸šà¸šà¸¡à¸²à¸ªà¸³à¸«à¸£à¸±à¸šà¸­à¸¸à¸›à¸à¸£à¸“์เคลื่อนที่</translation>
<translation id="825929999321470778">à¹à¸ªà¸”งรหัสผ่านที่บันทึà¸à¹„ว้ทั้งหมด</translation>
<translation id="8261506727792406068">ลบ</translation>
<translation id="8262952874573525464">เย็บขอบด้านล่าง</translation>
@@ -2025,7 +2077,6 @@
<translation id="8719528812645237045">เจาะรูด้านบนหลายรู</translation>
<translation id="8725066075913043281">ลองอีà¸à¸„รั้ง</translation>
<translation id="8726549941689275341">ขนาดหน้า:</translation>
-<translation id="8728672262656704056">คุณได้เข้าสู่โหมดไม่ระบุตัวตนà¹à¸¥à¹‰à¸§</translation>
<translation id="8730621377337864115">เสร็จสิ้น</translation>
<translation id="8731544501227493793">จัดà¸à¸²à¸£à¸›à¸¸à¹ˆà¸¡à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™ à¸à¸” Enter เพื่อดูà¹à¸¥à¸°à¸ˆà¸±à¸”à¸à¸²à¸£à¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™à¹ƒà¸™à¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Chrome</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> ของคุณจัดà¸à¸²à¸£à¹‚ดย <ph name="MANAGER" /></translation>
@@ -2102,6 +2153,7 @@
<translation id="9020542370529661692">หน้านี้ได้รับà¸à¸²à¸£à¹à¸›à¸¥à¹€à¸›à¹‡à¸™ <ph name="TARGET_LANGUAGE" /> à¹à¸¥à¹‰à¸§</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ไม่ถูà¸à¸•à¹‰à¸­à¸‡)</translation>
+<translation id="9030265603405983977">โมโนโครม</translation>
<translation id="9035022520814077154">ข้อผิดพลาดของà¸à¸²à¸£à¸£à¸±à¸à¸©à¸²à¸„วามปลอดภัย</translation>
<translation id="9038649477754266430">ใช้บริà¸à¸²à¸£à¸à¸²à¸£à¸„าดคะเนเพื่อโหลดหน้าได้เร็วขึ้น</translation>
<translation id="9039213469156557790">นอà¸à¸ˆà¸²à¸à¸™à¸µà¹‰ หน้านี้ประà¸à¸­à¸šà¸”้วยทรัพยาà¸à¸£à¸­à¸·à¹ˆà¸™à¹† ซึ่งไม่ปลอดภัย ผู้อื่นสามารถดูทรัพยาà¸à¸£à¹€à¸«à¸¥à¹ˆà¸²à¸™à¸µà¹‰à¸‚ณะถ่ายโอน à¹à¸¥à¸°à¸œà¸¹à¹‰à¸šà¸¸à¸à¸£à¸¸à¸à¸ªà¸²à¸¡à¸²à¸£à¸–à¹à¸à¹‰à¹„ขเพื่อเปลี่ยนà¸à¸²à¸£à¸—ำงานของหน้าได้</translation>
@@ -2125,6 +2177,7 @@
<translation id="91108059142052966">นโยบายของผู้ดูà¹à¸¥à¸£à¸°à¸šà¸šà¸›à¸´à¸”ใช้à¸à¸²à¸£à¹à¸Šà¸£à¹Œà¸«à¸™à¹‰à¸²à¸ˆà¸­à¸à¸±à¸š <ph name="APPLICATION_TITLE" /> เมื่อมีเนื้อหาลับà¹à¸ªà¸”งอยู่</translation>
<translation id="9114524666733003316">à¸à¸³à¸¥à¸±à¸‡à¸¢à¸·à¸™à¸¢à¸±à¸™à¸šà¸±à¸•à¸£â€¦</translation>
<translation id="9114581008513152754">เบราว์เซอร์นี้ไม่ได้จัดà¸à¸²à¸£à¹‚ดยบริษัทหรือองค์à¸à¸£à¸­à¸·à¹ˆà¸™à¹† à¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¹ƒà¸™à¸­à¸¸à¸›à¸à¸£à¸“์นี้อาจมีà¸à¸²à¸£à¸ˆà¸±à¸”à¸à¸²à¸£à¸ à¸²à¸¢à¸™à¸­à¸ Chrome <ph name="BEGIN_LINK" />ดูข้อมูลเพิ่มเติม<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">สดชื่น</translation>
<translation id="9119042192571987207">อัปโหลดà¹à¸¥à¹‰à¸§</translation>
<translation id="9128016270925453879">โหลดนโยบายà¹à¸¥à¹‰à¸§</translation>
<translation id="9128870381267983090">เชื่อมต่อà¸à¸±à¸šà¹€à¸„รือข่าย</translation>
@@ -2143,6 +2196,7 @@
<translation id="9170848237812810038">เ&amp;ลิà¸à¸—ำ</translation>
<translation id="9171296965991013597">ออà¸à¸ˆà¸²à¸à¹à¸­à¸›à¹„หม</translation>
<translation id="9173282814238175921">เอà¸à¸ªà¸²à¸£à¹€à¸”ียว/à¹à¸œà¹ˆà¸™à¸‡à¸²à¸™à¹ƒà¸«à¸¡à¹ˆ</translation>
+<translation id="9173995187295789444">à¸à¸³à¸¥à¸±à¸‡à¸ªà¹à¸à¸™à¸«à¸²à¸­à¸¸à¸›à¸à¸£à¸“์บลูทูธ...</translation>
<translation id="917450738466192189">ใบรับรองของเซิร์ฟเวอร์ไม่ถูà¸à¸•à¹‰à¸­à¸‡</translation>
<translation id="9174917557437862841">ปุ่มเปลี่ยนà¹à¸—็บ โปรดà¸à¸” Enter เพื่อเปลี่ยนไปยังà¹à¸—็บนี้</translation>
<translation id="9179703756951298733">จัดà¸à¸²à¸£à¸à¸²à¸£à¸Šà¸³à¸£à¸°à¹€à¸‡à¸´à¸™à¹à¸¥à¸°à¸‚้อมูลบัตรเครดิตในà¸à¸²à¸£à¸•à¸±à¹‰à¸‡à¸„่า Chrome</translation>
diff --git a/chromium/components/strings/components_strings_tr.xtb b/chromium/components/strings/components_strings_tr.xtb
index d0f7ceadb36..93b82ae5daa 100644
--- a/chromium/components/strings/components_strings_tr.xtb
+++ b/chromium/components/strings/components_strings_tr.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">İşaretlenirse Chrome, formları daha hızlı doldurma amacıyla kartınızın bir kopyasını bu cihazda depolar.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> için izin seçin</translation>
<translation id="1113869188872983271">Sıralama değişikliğini &amp;geri al</translation>
+<translation id="1123753900084781868">Canlı Altyazı şu anda kullanılamıyor</translation>
<translation id="1125573121925420732">Web siteleri güvenliklerini güncellerken uyarılar yaygın olarak görülebilir. Yakında bu işlev iyileştirilecektir.</translation>
<translation id="112840717907525620">Politika önbelleği uygun</translation>
<translation id="1130564665089811311">Sayfayı çevir düğmesi, bu sayfayı Google Çeviri'yle çevirmek için Enter'a basın</translation>
@@ -74,6 +75,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="1240347957665416060">Cihazınızın adı</translation>
<translation id="124116460088058876">DiÄŸer diller</translation>
<translation id="1243027604378859286">Yazar:</translation>
+<translation id="1246424317317450637">Kalın</translation>
<translation id="1250759482327835220">Bir dahaki sefere daha hızlı ödeme yapmak için kartınızı ve fatura adresinizi Google Hesabınıza kaydedin.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (senkronize edildi)</translation>
<translation id="1256368399071562588">&lt;p&gt;Bir web sitesini ziyaret etmeye çalıştığınızda site açılmıyorsa sorunu düzeltmek için ilk olarak aşağıdaki sorun giderme adımlarını deneyin:&lt;/p&gt;
@@ -156,6 +158,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="1476595624592550506">Åžifrenizi deÄŸiÅŸtirin</translation>
<translation id="1484290072879560759">Gönderim Adresi Seç</translation>
<translation id="1492194039220927094">Politikalar aktarılabilir:</translation>
+<translation id="1495677929897281669">Sekmeye dön</translation>
<translation id="1501859676467574491">Google Hesabımdaki kartları göster</translation>
<translation id="1507202001669085618">&lt;p&gt;İnternete girmek için oturum açmanızı gerektiren bir kablosuz portal kullanıyorsanız bu hatayı görürsünüz.&lt;/p&gt;
&lt;p&gt;Hatayı gidermek için, açmaya çalıştığınız sayfada &lt;strong&gt;Bağlan&lt;/strong&gt;'ı tıklayın.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="1532118530259321453">Bu sayfanın mesajı</translation>
<translation id="153384715582417236">Åžimdilik hepsi bu</translation>
<translation id="1536390784834419204">Sayfayı çevir</translation>
+<translation id="1539840569003678498">Rapor gönderildi:</translation>
<translation id="154408704832528245">Teslimat Adresi Seç</translation>
<translation id="1549470594296187301">Bu özelliğin kullanılabilmesi için JavaScript etkinleştirilmelidir.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="1682696192498422849">Önce kısa kenar</translation>
<translation id="168693727862418163">Bu politika değeri, şemasına göre doğrulanamadı, yok sayılacak.</translation>
<translation id="168841957122794586">Sunucu sertifikasında zayıf bir şifreleme anahtarı var.</translation>
+<translation id="1696290444144917273">Sanal kart ayrıntılarını görüntüle</translation>
<translation id="1697532407822776718">Artık hazırsınız!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Bu sunucu, <ph name="DOMAIN" /> olduğunu kanıtlayamadı. Güvenlik sertifikasının alınma tarihinin yarın olduğu iddia ediliyor. Bu durum, bir yanlış yapılandırmadan veya bağlantınıza müdahale eden bir saldırgandan kaynaklanıyor olabilir.}other{Bu sunucu, <ph name="DOMAIN" /> olduğunu kanıtlayamadı. Güvenlik sertifikasının alınma tarihinin # gün sonra olduğu iddia ediliyor. Bu durum, bir yanlış yapılandırmadan veya bağlantınıza müdahale eden bir saldırgandan kaynaklanıyor olabilir.}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" />, <ph name="VALUE" /> olarak ayarlanmadığından yok sayıldı.</translation>
<translation id="1712552549805331520"><ph name="URL" />, verileri yerel bilgisayarınızda kalıcı olarak saklamak istiyor</translation>
<translation id="1713628304598226412">Tepsi 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Posta kutusu 3</translation>
<translation id="1718029547804390981">Doküman, ek açıklama ilave edilemeyecek kadar büyük</translation>
<translation id="1721424275792716183">* Zorunlu alan</translation>
+<translation id="1727613060316725209">Sertifika geçerli</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>
<translation id="173080396488393970">Bu kart türü desteklenmiyor</translation>
@@ -243,7 +250,6 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="1772163372082567643">Ziyaret etmek üzere olduğunuz sunucu (<ph name="ORIGIN" />) kendisine gelen tüm isteklere bir kaynak politikası uygulanmasını gerektiren bir üst bilgi ayarladı. Ancak üst bilgi yanlış biçimlendirildiği için tarayıcı, <ph name="SITE" /> sitesiyle ilgili isteğinizi yerine getiremiyor. Kaynak politikaları
site operatörleri tarafından sitenin güvenliğini ve diğer mülklerini yapılandırmak için kullanılabilir.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Lütfen senkronizasyon parolanızı güncelleyin.</translation>
<translation id="1787142507584202372">Açık sekmeleriniz burada görünür</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, birden fazla işlem mevcut, işlemler arasında geçiş yapmak için Sekme'ye basın</translation>
@@ -276,6 +282,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="1919345977826869612">Reklamlar</translation>
<translation id="1919367280705858090">Belirli bir hata mesajıyla ilgili yardım alma</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Yok}=1{1 site}other{# site}}</translation>
+<translation id="1924727005275031552">Yeni</translation>
<translation id="1945968466830820669">Kuruluşunuzun hesabına erişimi kaybedebilir veya kimlik hırsızlığına maruz kalabilirsiniz. Chromium, şifrenizi hemen değiştirmenizi önerir.</translation>
<translation id="1947454675006758438">Sağ üstte tel zımba</translation>
<translation id="1958218078413065209">Aldığınız en yüksek puan <ph name="SCORE" />.</translation>
@@ -298,12 +305,14 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="2042213636306070719">Tepsi 7</translation>
<translation id="204357726431741734">Google Hesabınızda kayıtlı şifreleri kullanmak için oturum açın</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> dilindeki sayfalar çevrilmeyecek.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Bu denetim açık ve durum etkin olduğunda Chrome, son tarama etkinliklerinizin en çok benzediği geniş kullanıcı grubu veya "kohort"u belirler. Reklamverenler grup için reklam seçebilirler ve tarama etkinliğiniz cihazınızda gizli tutulur. Grubunuz her gün güncellenir.}=1{Bu denetim açık ve durum etkin olduğunda Chrome, son tarama etkinliklerinizin en çok benzediği geniş kullanıcı grubu veya "kohort"u belirler. Reklamverenler grup için reklam seçebilirler ve tarama etkinliğiniz cihazınızda gizli tutulur. Grubunuz her gün güncellenir.}other{Bu denetim açık ve durum etkin olduğunda Chrome, son tarama etkinliklerinizin en çok benzediği geniş kullanıcı grubu veya "kohort"u belirler. Reklamverenler grup için reklam seçebilirler ve tarama etkinliğiniz cihazınızda gizli tutulur. Grubunuz {NUM_DAYS} günde bir güncellenir.}}</translation>
<translation id="2053553514270667976">Posta kodu</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 öneri}other{# öneri}}</translation>
<translation id="2071692954027939183">Genelde izin vermediğiniz için bildirimler otomatik olarak engellendi</translation>
<translation id="2079545284768500474">Geri al</translation>
<translation id="20817612488360358">Sistem proxy ayarları kullanılmak üzere ayarlandı, ancak açık bir proxy yapılandırması da belirtildi.</translation>
<translation id="2082238445998314030"><ph name="TOTAL_RESULTS" /> sonuçtan <ph name="RESULT_NUMBER" /> numaralı sonuç</translation>
+<translation id="2085876078937250610">Kaydet…</translation>
<translation id="2088086323192747268">Senkronizasyonu yönet düğmesi, Chrome ayarlarında hangi bilgileri senkronize ettiğinizi yönetmek için Enter'a basın</translation>
<translation id="2091887806945687916">Ses</translation>
<translation id="2094505752054353250">Alan adı uyuşmazlığı</translation>
@@ -376,6 +385,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="2317259163369394535"><ph name="DOMAIN" /> için kullanıcı adı ve şifre gerekiyor.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" /> için kullanım süresi sonu: <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Ayar yöneticinizin kontrolü altındadır</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> eÅŸlenmek istiyor</translation>
<translation id="2344028582131185878">Otomatik Ä°ndirmeler</translation>
<translation id="2346319942568447007">Kopyalanan resim</translation>
<translation id="2354001756790975382">DiÄŸer yer iÅŸaretleri</translation>
@@ -383,8 +393,10 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="2355395290879513365">Saldırganlar bu sitede baktığınız resimleri görebilir ve bu resimler üzerinde değişiklik yaparak sizi kandırabilirler.</translation>
<translation id="2356070529366658676">Sor</translation>
<translation id="2357481397660644965">Cihazınız <ph name="DEVICE_MANAGER" /> tarafından, hesabınız ise <ph name="ACCOUNT_MANAGER" /> tarafından yönetiliyor.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Bir günden kısa bir süre içinde}=1{Bir gün içinde}other{{NUM_DAYS} gün içinde}}</translation>
<translation id="2359629602545592467">Birden fazla</translation>
<translation id="2359808026110333948">Devam et</translation>
+<translation id="2359961752320758691">Sanal kart numaranız uygulandı.</translation>
<translation id="2367567093518048410">Düzey</translation>
<translation id="2372464001869762664">Onayladığınızda Google Hesabınızdaki kart bilgileriniz bu siteyle paylaşılır. Plex Hesabı bilgilerinizde CVC numaranızı bulun.</translation>
<translation id="2380886658946992094">Hukuk</translation>
@@ -395,6 +407,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="239429038616798445">Bu gönderim yöntemi kullanılamıyor. Farklı bir yöntem deneyin.</translation>
<translation id="2396249848217231973">Silmeyi &amp;geri al</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Eski</translation>
<translation id="2413528052993050574">Bu sunucu <ph name="DOMAIN" /> olduğunu kanıtlayamadı. Güvenlik sertifikası iptal edilmiş olabilir. Bu durum, bir yanlış yapılandırmadan veya bağlantıya müdahale eden bir saldırgandan kaynaklanıyor olabilir.</translation>
<translation id="2414886740292270097">Koyu</translation>
<translation id="2438874542388153331">Sağda dörtlü delik</translation>
@@ -422,10 +435,10 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="2521385132275182522">Sağ altta tel zımba</translation>
<translation id="2523886232349826891">Yalnızca bu cihazda kaydedildi</translation>
<translation id="2524461107774643265">Daha Fazla Bilgi Ekleyin</translation>
-<translation id="2526590354069164005">Masaüstü</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{ve 1 tane daha}other{ve # tane daha}}</translation>
<translation id="2536110899380797252">Adres Ekle</translation>
<translation id="2539524384386349900">Algıla</translation>
+<translation id="2541219929084442027">Gizli sekmelerde görüntülediğiniz sayfalar, açık olan tüm gizli sekmeler kapatıldıktan sonra tarayıcınızın geçmişinden, çerez deposundan veya arama geçmişinden silinecektir. İndirdiğiniz dosyalar veya oluşturduğunuz yer işaretleri kalacaktır.</translation>
<translation id="2544644783021658368">Tek doküman</translation>
<translation id="254947805923345898">Politika değeri geçerli değil.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> geçersiz bir yanıt gönderdi.</translation>
@@ -445,6 +458,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="2629325967560697240">Chrome’un sağladığı en yüksek güvenlik düzeyinden faydalanmak için <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />gelişmiş korumayı açın<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> ana makinesinin sunucu IP adresi bulunamadı.</translation>
<translation id="2639739919103226564">Durum:</translation>
+<translation id="264810637653812429">Uyumlu cihaz bulunamadı.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ayarlarında tarama geçmişinizi, çerezleri, önbelleği ve diğer öğeleri Temizlemek için Sekme'ye, sonra Enter'a basın</translation>
<translation id="2650446666397867134">Dosyaya eriÅŸim reddedildi</translation>
@@ -489,6 +503,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<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="2807052079800581569">Resim Y konumu</translation>
+<translation id="2820957248982571256">Taranıyor...</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>
@@ -496,6 +511,8 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="2850739647070081192">Invite (Zarf)</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="2859806420264540918">Bu site, araya giren veya yanıltıcı reklamlar gösteriyor.</translation>
+<translation id="287596039013813457">Dost Canlısı</translation>
+<translation id="2876489322757410363">Harici bir uygulama üzerinden ödeme gerçekleştirmek için Gizli moddan çıkılıyor. Devam etmek istiyor musunuz?</translation>
<translation id="2878197950673342043">Poster katlama</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Pencere yerleÅŸimi</translation>
@@ -545,7 +562,6 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="3060227939791841287">C9 (Zarf)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ayarlarında Güvenlik Kontrolü yürütmek için Sekme'ye, sonra Enter'a basın</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>
<translation id="306573536155379004">Oyun başladı.</translation>
<translation id="3080254622891793721">Grafik</translation>
<translation id="3086579638707268289">Web'de etkinliÄŸiniz izleniyor</translation>
@@ -568,7 +584,6 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="315504272643575312">Hesabınız <ph name="MANAGER" /> tarafından yönetiliyor.</translation>
<translation id="3157931365184549694">Geri yükle</translation>
<translation id="3162559335345991374">Kullandığınız Kablosuz ağ, giriş sayfasını ziyaret etmenizi gerektiriyor olabilir.</translation>
-<translation id="3167968892399408617">Gizli sekmelerde görüntülediğiniz sayfalar, açık olan tüm gizli sekmeler kapatıldıktan sonra tarayıcınızın geçmişinden, çerez deposundan veya arama geçmişinden silinecektir. İndirdiğiniz dosyalar veya oluşturduğunuz yer işaretleri kalacaktır.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Ada</translation>
<translation id="3176929007561373547">Proxy sunucunun çalışıyor olduğundan emin olmak için
@@ -594,10 +609,12 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<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="3249845759089040423">Modern</translation>
<translation id="3252266817569339921">Fransızca</translation>
<translation id="3266793032086590337">Değer (çakışma)</translation>
<translation id="3268451620468152448">Açık Sekmeler</translation>
<translation id="3270847123878663523">Sıralama Değişikliğini &amp;Geri Al</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> baÄŸlanmak istiyor</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Kuruluşunuz (<ph name="ENROLLMENT_DOMAIN" />), aşağıdaki web sitelerine ayarlar ve politikalar gibi bazı bilgiler gönderdi.</translation>
<translation id="3282497668470633863">Kart üzerindeki ismi ekle</translation>
@@ -650,6 +667,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="3428151540071562330">DnsOverHttpsTemplates sunucu şablonu URI'larından biri veya daha fazlası geçersiz olduğundan kullanılmayacak.</translation>
<translation id="3431636764301398940">Bu kartı bu cihaza kaydet</translation>
<translation id="3432601291244612633">Sayfayı kapat</translation>
+<translation id="3435738964857648380">Güvenlik</translation>
<translation id="3435896845095436175">EtkinleÅŸtir</translation>
<translation id="3438829137925142401">Google Hesabınızdaki kayıtlı şifreleri kullanın</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -692,7 +710,10 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="3584299510153766161">Altta ikili delik</translation>
<translation id="3586931643579894722">Ayrıntıları gizle</translation>
<translation id="3587738293690942763">Orta</translation>
+<translation id="3590643883886679995">Gizli moddan çıktıktan sonra oturum açma verileriniz bu cihazda saklanır.</translation>
+<translation id="359126217934908072">Ay/Yıl:</translation>
<translation id="3592413004129370115">Italian (Zarf)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Grubunuzu istediğiniz zaman sıfırlayabilirsiniz. Yeni bir gruba katılmak yaklaşık bir gün sürer.}=1{Grubunuzu istediğiniz zaman sıfırlayabilirsiniz. Yeni bir gruba katılmak yaklaşık bir gün sürer.}other{Grubunuzu istediğiniz zaman sıfırlayabilirsiniz. Yeni bir gruba katılmak yaklaşık {NUM_DAYS} gün sürer.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Uygulama, yöneticiniz tarafından engellendi</translation>
<translation id="3608932978122581043">Besleme yönü</translation>
@@ -701,13 +722,13 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="3615877443314183785">Geçerli bir son kullanma tarihi girin</translation>
<translation id="36224234498066874">Tarama Verilerini Temizle...</translation>
<translation id="362276910939193118">Tam Geçmişi Göster</translation>
-<translation id="3625635938337243871">Gizli moddan çıktıktan sonra oturum açma verileri bu cihazda saklanır.</translation>
<translation id="3630155396527302611">AÄŸa eriÅŸmesine izin verilmiÅŸ bir program olarak zaten listeleniyorsa,
listeden kaldırıp tekrar eklemeyi deneyin.</translation>
<translation id="3630699740441428070">Bu cihazın yöneticileri ağ bağlantınızı yapılandırdı. Bu sayede, ziyaret ettiğiniz web siteleri de dahil olmak üzere ağ trafiğinizi görebilirler.</translation>
<translation id="3631244953324577188">Biyometri</translation>
<translation id="3633738897356909127">Chrome'u güncelle düğmesi, Chrome ayarlarınızdan Chrome'u güncellemek için Enter'a basın</translation>
<translation id="3634530185120165534">Tepsi 5</translation>
+<translation id="3637662659967048211">Google Hesabı'na kaydedin</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Uygulama:</translation>
<translation id="3650584904733503804">Doğrulama başarılı</translation>
@@ -748,6 +769,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="3781428340399460090">Canlı Pembe</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth cihazlar</translation>
+<translation id="3787675388804467730">Sanal kart numarası</translation>
<translation id="3787705759683870569">Son kullanma tarihi: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Boyut 16</translation>
<translation id="3789841737615482174">Yükle</translation>
@@ -767,6 +789,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="3841184659773414994">Dosya Ä°ÅŸleyiciler</translation>
<translation id="385051799172605136">Geri</translation>
<translation id="3858027520442213535">Tarih ve saati güncelle</translation>
+<translation id="3881478300875776315">Daha az satır göster</translation>
<translation id="3884278016824448484">Çakışan cihaz tanımlayıcısı</translation>
<translation id="3885155851504623709">Ä°l</translation>
<translation id="388632593194507180">Ä°zleme Tespit Edildi</translation>
@@ -792,6 +815,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="397105322502079400">Hesaplanııyor...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> engellendi</translation>
<translation id="3973357910713125165">Chrome Güvenlik Kontrolü yürüt düğmesi, Chrome ayarlarında Güvenlik Kontrolü yürütmek için Enter'a basın</translation>
+<translation id="3986705137476756801">Canlı Altyazı'yı şimdilik kapat</translation>
<translation id="3987405730340719549">Chrome, bu sitenin taklit veya sahte olduÄŸunu belirledi.
Bu mesajın yanlışlıkla gösterildiğini düşünüyorsanız lütfen https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals adresini ziyaret edin.</translation>
@@ -884,13 +908,14 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="4275830172053184480">Cihazınızı yeniden başlatın</translation>
<translation id="4277028893293644418">Şifreyi sıfırla</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="4287885627794386150">Deneme için uygun ancak etkin değil</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" />. sayfanın küçük resmi</translation>
<translation id="42981349822642051">GeniÅŸlet</translation>
<translation id="4300675098767811073">Sağda çoklu delik</translation>
<translation id="4302514097724775343">Oynamak için dinozora dokunun</translation>
<translation id="4302965934281694568">Chou3 (Zarf)</translation>
<translation id="4305666528087210886">Dosyanıza erişilemedi</translation>
-<translation id="4305817255990598646">Anahtar</translation>
+<translation id="4306529830550717874">Adres kaydedilsin mi?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Engelle (varsayılan)</translation>
<translation id="4314815835985389558">Senkronizasyonu yönetin</translation>
@@ -917,6 +942,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="4377125064752653719"><ph name="DOMAIN" /> adresine ulaşmayı denediniz, ancak sunucunun sağladığı sertifika, sertifikayı veren tarafından iptal edildi. Bu, sunucunun sağladığı güvenlik kimlik bilgilerine kesinlikle güvenilmemesi gerektiği anlamına gelir. Bir saldırganla irtibat kuruyor olabilirsiniz.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Brim</translation>
+<translation id="4406883609789734330">Canlı Altyazı</translation>
<translation id="4406896451731180161">arama sonuçları</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> çerez</translation>
<translation id="4414290883293381923">Az önce şifrenizi yanıltıcı bir sitede girdiniz. Chrome, bu şifreyi kullandığınız <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ve diğer sitelere giderek şifrenizi hemen değiştirmenizi öneriyor.</translation>
@@ -929,7 +955,6 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<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="4464826014807964867">Kuruluşunuzun gönderdiği bilgilerin olduğu web siteleri</translation>
-<translation id="4466881336512663640">Formda yaptığınız değişiklikler kaybolacak. Devam etmek istediğinizden emin misiniz?</translation>
<translation id="4476953670630786061">Bu form güvenli değil. Otomatik doldurma kapatıldı.</translation>
<translation id="4477350412780666475">Sonraki Parça</translation>
<translation id="4482953324121162758">Bu site çevrilmeyecek.</translation>
@@ -963,6 +988,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="4594403342090139922">Silmeyi &amp;Geri Al</translation>
<translation id="4597348597567598915">Boyut 8</translation>
<translation id="4600854749408232102">C6/C5 (Zarf)</translation>
+<translation id="4606870351894164739">Etkili</translation>
<translation id="4628948037717959914">FotoÄŸraf</translation>
<translation id="4631649115723685955">Nakit para üstü bağlantısı oluşturuldu</translation>
<translation id="4636930964841734540">Bilgi</translation>
@@ -982,6 +1008,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="4691835149146451662">Architecture-A (Zarf)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Taraf</translation>
+<translation id="4702656508969495934">Canlı Altyazı görünüyor, odaklamak için pencere değiştiriciyi kullanın</translation>
<translation id="4708268264240856090">Bağlantınız kesildi</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows Ağ Teşhislerini Çalıştırma<ph name="END_LINK" /></translation>
@@ -995,6 +1022,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="4738601419177586157"><ph name="TEXT" /> arama önerisi</translation>
<translation id="4742407542027196863">Şifreleri yönet…</translation>
<translation id="4744603770635761495">Çalıştırılabilir Yol</translation>
+<translation id="4749011317274908093">Gizli sekme açtınız</translation>
<translation id="4750917950439032686">Bilgileriniz (örneğin şifreler veya kredi kartı numaraları), bu siteye gönderilirken gizli olur.</translation>
<translation id="4756388243121344051">&amp;Geçmiş</translation>
<translation id="4758311279753947758">Ä°letiÅŸim bilgilerinizi ekleyin</translation>
@@ -1024,6 +1052,8 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="4813512666221746211">Ağ hatası</translation>
<translation id="4816492930507672669">Sayfaya sığdır</translation>
<translation id="4819347708020428563">Ek açıklamalar varsayılan görünümde düzenlensin mi?</translation>
+<translation id="4825507807291741242">Güçlü</translation>
+<translation id="4838327282952368871">Hayalperest</translation>
<translation id="484462545196658690">Auto</translation>
<translation id="4850886885716139402">Görüntüle</translation>
<translation id="485316830061041779">Almanca</translation>
@@ -1160,6 +1190,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="5314967030527622926">Kitapçık yapıcı</translation>
<translation id="5316812925700871227">Saat yönünün tersine döndür</translation>
<translation id="5317780077021120954">Kaydet</translation>
+<translation id="5321288445143113935">Tam ekran</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="NUM_MATCHES" /> eşleşme arasında <ph name="MATCH_POSITION" />. sırada</translation>
<translation id="5324080437450482387">İletişim Bilgisi Seç</translation>
<translation id="5327248766486351172">Ad</translation>
@@ -1167,11 +1198,13 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="5332219387342487447">Gönderim Yöntemi</translation>
<translation id="5333022057423422993">Chrome, az önce kullandığınız şifrenin bir veri ihlali sonucunda açığa çıktığını belirledi. Hesaplarınızın güvenliğini sağlamak için kayıtlı şifrelerinizi kontrol etmenizi öneririz.</translation>
<translation id="5334013548165032829">Ayrıntılı sistem günlükleri</translation>
+<translation id="5334145288572353250">Adres Kaydedilsin mi?</translation>
<translation id="5340250774223869109">Uygulama engellendi</translation>
<translation id="534295439873310000">NFC cihazları</translation>
<translation id="5344579389779391559">Bu sayfa sizden para almaya çalışabilir</translation>
<translation id="5355557959165512791">Sertifikası iptal edildiği için <ph name="SITE" /> sitesini şu anda ziyaret edemezsiniz. Ağ hataları ve saldırılar genellikle geçici olduğundan, bu sayfa muhtemelen daha sonra çalışacaktır.</translation>
<translation id="536296301121032821">Politika ayarları saklanamadı</translation>
+<translation id="5363309033720083897">Yöneticiniz tarafından izin verilen seri bağlantı noktası</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="5386426401304769735">Bu sitenin sertifika zinciri, SHA-1 kullanılarak imzalanmış bir sertifika içeriyor.</translation>
@@ -1180,6 +1213,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="5398772614898833570">Reklamlar engellendi</translation>
<translation id="5400836586163650660">Gri</translation>
<translation id="540969355065856584">Bu sunucu <ph name="DOMAIN" /> olduğunu kanıtlayamadı. Güvenlik sertifikası şu anda geçerli değil. Bu durum, bir yanlış yapılandırmadan veya bağlantıya müdahale eden bir saldırgandan kaynaklanıyor olabilir.</translation>
+<translation id="541143247543991491">Bulut (sistem genelinde)</translation>
<translation id="541416427766103491">Yığınlayıcı 4</translation>
<translation id="5421136146218899937">Tarama verilerini temizle...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> size bildirim göndermek istiyor</translation>
@@ -1193,6 +1227,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="5455374756549232013">Politika zaman damgası yanlış</translation>
<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="5463625433003343978">Cihazlar bulunuyor...</translation>
<translation id="5469868506864199649">Ä°talyanca</translation>
<translation id="5470861586879999274">Düzenlemeyi &amp;yeniden yap</translation>
<translation id="5478437291406423475">B6/C4 (Zarf)</translation>
@@ -1242,7 +1277,6 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="5624120631404540903">Şifreleri yönet</translation>
<translation id="5629630648637658800">Politika ayarları yüklenemedi</translation>
<translation id="5631439013527180824">Geçersiz cihaz yönetimi jetonu</translation>
-<translation id="5632627355679805402"><ph name="TIME" /> itibarıyla verileriniz <ph name="BEGIN_LINK" />Google şifrenizle<ph name="END_LINK" /> şifrelendi. Senkronizasyonu başlatmak için şifreyi girin.</translation>
<translation id="5633066919399395251">Şu anda <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> sitesindeki saldırganlar, bilgilerinizi (örneğin, fotoğraflar, şifreler, mesajlar ve kredi kartları) çalabilecek veya silebilecek tehlikeli programları bilgisayarınıza yüklemeye çalışabilir. <ph name="BEGIN_LEARN_MORE_LINK" />Daha fazla bilgi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Yanıltıcı içerik engellendi.</translation>
<translation id="5644090287519800334">Taraf 1 resim X kayması</translation>
@@ -1281,12 +1315,12 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="5785756445106461925">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 görünüşünü değiştirmek üzere kullanılabilir.</translation>
<translation id="5786044859038896871">Kart bilgilerinizin doldurulmasını istiyor musunuz?</translation>
<translation id="578633867165174378">Chrome, az önce kullandığınız şifrenin bir veri ihlali sonucunda açığa çıktığını belirledi. Bu şifreyi hemen değiştirmenizi öneriyoruz.</translation>
-<translation id="5798290721819630480">DeÄŸiÅŸiklikler silinsin mi?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" /> kartınıza ait bilgilerin doldurulmasını istiyor musunuz?</translation>
<translation id="5804241973901381774">Ä°zinler</translation>
<translation id="5804427196348435412">NFC cihazlarını kullanma</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> ile olan bağlantınız eski bir şifre seti kullanılarak şifrelendi.</translation>
<translation id="5813119285467412249">Eklemeyi &amp;Yeniden Yap</translation>
+<translation id="5817918615728894473">EÅŸle</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Ödeme yaptığınızda ücret bu karttan alınır ancak kartın gerçek numarası bu site ile paylaşılmaz. Ek güvenlik için geçici bir CVC oluşturulur.}other{Ödeme yaptığınızda ücret, seçtiğiniz karttan alınır ancak kartın gerçek numarası bu site ile paylaşılmaz. Ek güvenlik için geçici bir CVC oluşturulur.}}</translation>
<translation id="5826507051599432481">Genel Ad (CN)</translation>
<translation id="5838278095973806738">Bu sitede hiçbir hassas bilginizi (örneğin şifrelerinizi veya kredi kartı bilgilerinizi) girmemelisiniz. Aksi takdirde bu bilgiler saldırganlar tarafından çalınabilir.</translation>
@@ -1294,6 +1328,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="5855253129151731373">Bu sitenin ana makine adı <ph name="LOOKALIKE_DOMAIN" /> sitesinin adına benziyor. Saldırganlar bazen alan adında görülmesi zor ufak değişiklikler yaparak siteleri taklit ederler.
Bu mesajın yanlışlıkla gösterildiğini düşünüyorsanız lütfen https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals adresini ziyaret edin.</translation>
+<translation id="5860033963881614850">Kapalı</translation>
<translation id="5862579898803147654">Yığınlayıcı 8</translation>
<translation id="5863847714970149516">Gireceğiniz sayfa sizden para almaya çalışabilir</translation>
<translation id="5866257070973731571">Telefon Numarası Ekleyin</translation>
@@ -1310,6 +1345,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="5913377024445952699">Ekran görüntüsü alma duraklatıldı</translation>
<translation id="59174027418879706">Etkin</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 çerez kullanımda}other{# çerez kullanımda}}</translation>
<translation id="5921185718311485855">Açık</translation>
<translation id="5921639886840618607">Kart Google Hesabı'na kaydedilsin mi?</translation>
<translation id="5922853866070715753">Tamamlanmak üzere</translation>
@@ -1329,6 +1365,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="5989320800837274978">Sabit proxy sunucular veya bir .pac komut dosyası URL'si belirtilmedi.</translation>
<translation id="5992691462791905444">Yarım Z katlama</translation>
<translation id="6000758707621254961">"<ph name="SEARCH_TEXT" />" için bulunan <ph name="RESULT_COUNT" /> sonuç gösteriliyor</translation>
+<translation id="6006484371116297560">Klasik</translation>
<translation id="6008122969617370890">N'den 1'e sıralı</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Åžifrelerinizi kontrol edin</translation>
@@ -1350,6 +1387,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="6045164183059402045">Tanzim ÅŸablonu</translation>
<translation id="6047233362582046994">Güvenliğinize ilişkin riskleri anladıysanız zararlı programlar kaldırılmadan önce <ph name="BEGIN_LINK" />bu siteyi ziyaret edebilirsiniz<ph name="END_LINK" />.</translation>
<translation id="6047927260846328439">Bu içerik sizi kandırarak yazılım yüklemenizi veya kişisel bilgilerinizi ifşa etmenizi sağlamaya çalışabilir. <ph name="BEGIN_LINK" />Yine de göster<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Tam ekrandan çıkmak için |<ph name="ACCELERATOR" />| tuşunu basılı tutun</translation>
<translation id="6049488691372270142">Sayfa teslimi</translation>
<translation id="6051221802930200923"><ph name="SITE" /> sitesi sertifika sabitleme yöntemi kullandığından siteyi şu anda ziyaret edemezsiniz. Ağ hataları ve saldırılar genellikle geçici olduğundan bu sayfa muhtemelen daha sonra çalışacaktır.</translation>
<translation id="6051898664905071243">Sayfa sayısı:</translation>
@@ -1366,6 +1404,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<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>
<translation id="6116338172782435947">Panoya kopyalanan metin ve resimleri görme</translation>
<translation id="6120179357481664955">UPI ID'nizi hatırlıyor musunuz?</translation>
+<translation id="6123290840358279103">Sanal kartı görüntüle</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Kabloları kontrol edin ve kullandığınız yönlendiricileri, modemleri
veya diğer ağ cihazlarını yeniden başlatın.</translation>
@@ -1402,6 +1441,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="6289939620939689042">Sayfa Rengi</translation>
<translation id="6290238015253830360">Önerilen makaleler burada görünür</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome'da Google Asistan durduruluyor</translation>
<translation id="6305205051461490394"><ph name="URL" /> adresine ulaşılamıyor.</translation>
<translation id="6312113039770857350">Web sayfası mevcut değil</translation>
@@ -1427,6 +1467,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="6390200185239044127">Yarım Z katlama</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> sitesinden bu konuma yapıştırma işlevi, yönetici politikası tarafından engellendi</translation>
+<translation id="6398765197997659313">Tam ekrandan çık</translation>
<translation id="6401136357288658127">Bu politika kullanımdan kaldırılmıştır. Onun yerine <ph name="NEW_POLICY" /> politikasını kullanmalısınız.</translation>
<translation id="6404511346730675251">Yer işaretini düzenle</translation>
<translation id="6406765186087300643">C0 (Zarf)</translation>
@@ -1439,7 +1480,6 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="6428450836711225518">Telefon numaranızı doğrulayın</translation>
<translation id="6433490469411711332">İletişim bilgilerini düzenle</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> bağlanmayı reddetti.</translation>
-<translation id="6434309073475700221">Kapat</translation>
<translation id="6440503408713884761">Yoksayıldı</translation>
<translation id="6443406338865242315">Hangi uzantıları ve eklentileri yüklediğiniz</translation>
<translation id="6446163441502663861">Kahu (Zarf)</translation>
@@ -1482,6 +1522,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="6624427990725312378">Ä°letiÅŸim Bilgileri</translation>
<translation id="6626291197371920147">Geçerli kart numarası ekle</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Arama</translation>
+<translation id="6630043285902923878">USB cihazlar bulunuyor...</translation>
<translation id="6630809736994426279">Şu anda <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> sitesindeki saldırganlar bilgilerinizi (örneğin, fotoğraflar, şifreler, mesajlar ve kredi kartları) çalabilecek veya silebilecek tehlikeli programları Mac'inize yüklemeye çalışabilir. <ph name="BEGIN_LEARN_MORE_LINK" />Daha fazla bilgi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Temizle</translation>
@@ -1497,6 +1538,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<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="6687335167692595844">Yazı tipi boyutu istendi</translation>
+<translation id="6688743156324860098">Güncelle…</translation>
<translation id="6689249931105087298">Siyah nokta sıkıştırma ile göreli</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="6698381487523150993">OluÅŸturma tarihi:</translation>
@@ -1512,6 +1554,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="6744009308914054259">Bağlantı kurulmasını beklerken çevrimdışı makaleleri okumak için İndirilenler bölümünü ziyaret edebilirsiniz.</translation>
<translation id="6753269504797312559">Politika deÄŸeri</translation>
<translation id="6757797048963528358">Cihazınız uyku moduna geçti.</translation>
+<translation id="6767985426384634228">Adres Güncellensin mi?</translation>
<translation id="6768213884286397650">Hagaki (Kartpostal)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Mor</translation>
@@ -1534,6 +1577,7 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome, okumayı kolaylaştırmak için bu sayfayı basitleştirdi. Chrome, orijinal sayfayı güvenli olmayan bir bağlantı üzerinden aldı.</translation>
<translation id="6891596781022320156">Politika düzeyi desteklenmiyor.</translation>
+<translation id="6895143722905299846">Sanal numara:</translation>
<translation id="6895330447102777224">Kartınız onaylandı</translation>
<translation id="6897140037006041989">Kullanıcı Aracısı</translation>
<translation id="6898699227549475383">KuruluÅŸ (O)</translation>
@@ -1569,10 +1613,10 @@ Aksi halde bu işlem gizlilik ayarlarınız tarafından engellenecek. Buna izin
<translation id="7004583254764674281">Kartları daha hızlı onaylamak için Windows Hello'yu kullanın</translation>
<translation id="7006930604109697472">Yine de gönder</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Yeniden Boyutlandırma Ayarları</translation>
<translation id="7014741021609395734">Yakınlaştırma düzeyi</translation>
<translation id="7016992613359344582">Bu ödemeler bir defalık alınabileceği gibi yinelenen ödemeler de olabilir ve bu durum açıkça belli olmayabilir.</translation>
<translation id="7029809446516969842">Åžifreler</translation>
+<translation id="7030436163253143341">Sertifika geçerli değil</translation>
<translation id="7031646650991750659">Hangi Google Play uygulamalarını yüklediğiniz</translation>
<translation id="7050187094878475250"><ph name="DOMAIN" /> alan adına erişmeyi denediniz, ancak sunucu, geçerlilik dönemi güvenilir olmayacak kadar uzun olan bir sertifika sundu.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Bu kart ÅŸu anda kaydedilemiyor}other{Bu kartlar ÅŸu anda kaydedilemiyor}}</translation>
@@ -1642,12 +1686,14 @@ Ek ayrıntılar:
<translation id="7300012071106347854">Çini Mavisi</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Ä°nce</translation>
+<translation id="7305756307268530424">Daha yavaÅŸ baÅŸlat</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Bağlantı Yardımı</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" bölümünü gizle</translation>
<translation id="733354035281974745">Cihaz yerel hesabını geçersiz kıl</translation>
<translation id="7333654844024768166">Az önce şifrenizi yanıltıcı bir sitede girdiniz. Chromium, <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> ve bu şifreyi kullandığınız diğer sitelere giderek şifrenizi hemen değiştirmenizi öneriyor.</translation>
<translation id="7334320624316649418">Sıralama değişikliğini &amp;yeniden yap</translation>
+<translation id="7337248890521463931">Daha fazla satır göster</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>
@@ -1655,6 +1701,7 @@ Ek ayrıntılar:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Komut Satırı</translation>
<translation id="7359588939039777303">Reklamlar engellendi.</translation>
+<translation id="7363096869660964304">Ancak görünmez olmazsınız. Gizli moda geçmek göz atma etkinliğinizi işvereninizden, İnternet servis sağlayıcınızdan veya ziyaret ettiğiniz web sitelerinden gizlemez.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ayarlarında adres ekleyip yönetmek için Sekme'ye, ardından Enter'a basın</translation>
<translation id="7365849542400970216">Cihaz kullanımınız bilinsin mi?</translation>
<translation id="7372973238305370288">arama sonucu</translation>
@@ -1665,7 +1712,9 @@ Ek ayrıntılar:
<translation id="7378594059915113390">Medya Denetimleri</translation>
<translation id="7378627244592794276">Hayır</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Geçerli değil</translation>
<translation id="7390545607259442187">Kartı Onayla</translation>
+<translation id="7392089738299859607">Adresi Güncelle</translation>
<translation id="7399802613464275309">Güvenlik Kontrolü</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> adlı cihazınız yönetilmektedir</translation>
@@ -1680,6 +1729,7 @@ Ek ayrıntılar:
&lt;li&gt;Yazılımı bilgisayarınızdan kalıcı olarak nasıl kaldıracağınızı öğrenmek için &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome yardım merkezini&lt;/a&gt; ziyaret edin
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">HoÅŸ</translation>
<translation id="7416351320495623771">Şifreleri Yönet…</translation>
<translation id="7419106976560586862">Profil Yolu</translation>
<translation id="7437289804838430631">Ä°letiÅŸim Bilgisi Ekle</translation>
@@ -1695,7 +1745,7 @@ Ek ayrıntılar:
<translation id="7481312909269577407">Ä°leri</translation>
<translation id="7485870689360869515">Hiçbir veri bulunamadı.</translation>
<translation id="7495528107193238112">Bu içerik engellenmiştir. Sorunu gidermek için site sahibiyle iletişime geçin.</translation>
-<translation id="7498234416455752244">Düzenlemeye devam et</translation>
+<translation id="7498193950643227031">Yeniden boyutlandırılırsa beklenmeyen şekilde davranabilir. Artık uygulamaları yeniden boyutlandırma özelliğini <ph name="SETTINGS" /> bölümünde sınırlandırabilirsiniz.</translation>
<translation id="7503664977220660814">Az önce şifrenizi yanıltıcı bir sitede girdiniz. Chromium, <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ve bu şifreyi kullandığınız diğer sitelerdeki kayıtlı şifrelerinizi hemen kontrol etmenizi öneriyor.</translation>
<translation id="7508255263130623398">Döndürülen politika cihaz kimliği boş veya mevcut cihaz kimliğiyle eşleşmiyor</translation>
<translation id="7508870219247277067">Avokado YeÅŸili</translation>
@@ -1715,6 +1765,7 @@ Ek ayrıntılar:
<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="755279583747225797">Deneme etkin</translation>
<translation id="7552846755917812628">Aşağıdaki ipuçlarını deneyin:</translation>
<translation id="7554475479213504905">Yine de yeniden yükle ve göster</translation>
<translation id="7554791636758816595">Yeni Sekme</translation>
@@ -1733,7 +1784,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome ayarlarında şifrelerinizi görüntüleyip yönetmek için Sekme'ye, sonra Enter'a basın</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="7616645509853975347">Yöneticiniz, tarayıcınızda Chrome Enterprise Connectors özelliğini etkinleştirdi. Bu bağlayıcıların verilerinizin bir kısmına erişimi vardır.</translation>
<translation id="7619838219691048931">Son sayfa</translation>
<translation id="762844065391966283">Birer birer</translation>
@@ -1798,13 +1848,12 @@ Ek ayrıntılar:
<translation id="782886543891417279">Kullandığınız kablosuz bağlantı ağı (<ph name="WIFI_NAME" />) giriş sayfasını ziyaret etmenizi gerektiriyor olabilir.</translation>
<translation id="7836231406687464395">Postfix (Zarf)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Yok}=1{1 uygulama (<ph name="EXAMPLE_APP_1" />)}=2{2 uygulama (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# uygulama (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Ancak görünmez olmazsınız. Gizli moda geçmek göz atma etkinliğinizi işvereninizden, İnternet servis sağlayıcınızdan veya ziyaret ettiğiniz web sitelerinden gizlemez.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Dosyaları, dosya türü ilişkilendirmeleriyle aç.</translation>
<translation id="7862185352068345852">Siteden çıkılsın mı?</translation>
<translation id="7865448901209910068">En iyi hız</translation>
<translation id="7874263914261512992">Az önce şifrenizi yanıltıcı bir sitede girdiniz. Chrome, <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> ve bu şifreyi kullandığınız diğer sitelerdeki kayıtlı şifrelerinizi hemen kontrol etmenizi öneriyor.</translation>
<translation id="7878562273885520351">Şifrenizin güvenliği ihlal edilmiş olabilir</translation>
+<translation id="7880146494886811634">Adresi Kaydet</translation>
<translation id="7882421473871500483">Kahverengi</translation>
<translation id="7887683347370398519">CVC'nizi kontrol edin ve tekrar deneyin</translation>
<translation id="7887885240995164102">Pencere içinde pencere moduna gir</translation>
@@ -1812,6 +1861,7 @@ Ek ayrıntılar:
<translation id="7894280532028510793">Yazım doğruysa <ph name="BEGIN_LINK" />Ağ Teşhisi'ni çalıştırmayı deneyin<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Zarf)</translation>
<translation id="7931318309563332511">Bilinmiyor</translation>
+<translation id="793209273132572360">Adres güncellensin mi?</translation>
<translation id="7932579305932748336">Kaplama</translation>
<translation id="79338296614623784">Geçerli bir telefon numarası girin</translation>
<translation id="7934052535022478634">Ödeme tamamlandı</translation>
@@ -1882,6 +1932,7 @@ Ek ayrıntılar:
<translation id="8175796834047840627">Chrome, oturumunuz açık olduğu için kartlarınızı Google Hesabınıza kaydetmeyi öneriyor. Bu davranışı ayarlardan değiştirebilirsiniz.</translation>
<translation id="8176440868214972690">Bu cihazın yöneticisi, aşağıdaki web sitelerine ayarlar ve politikalar gibi bazı bilgiler gönderdi.</translation>
<translation id="8184538546369750125">Genel varsayılanı kullan (İzin ver)</translation>
+<translation id="8193086767630290324">Gizli olarak işaretlenmiş verilerle yapılan işlemler</translation>
<translation id="8194797478851900357">Taşımayı &amp;Geri Al</translation>
<translation id="8201077131113104583">"<ph name="EXTENSION_ID" />" kodlu uzantı için geçersiz güncelleme URL'si.</translation>
<translation id="8202097416529803614">Sipariş özeti</translation>
@@ -1904,6 +1955,7 @@ Ek ayrıntılar:
<translation id="8249296373107784235">Ä°ptal Et</translation>
<translation id="8249320324621329438">Son getirilen:</translation>
<translation id="8253091569723639551">Fatura adresi gerekli</translation>
+<translation id="8257387598443225809">Bu uygulama mobil cihazlar için tasarlanmıştır</translation>
<translation id="825929999321470778">Tüm Kayıtlı Şifreleri Göster</translation>
<translation id="8261506727792406068">Sil</translation>
<translation id="8262952874573525464">Altta kenar dikiÅŸi</translation>
@@ -2028,7 +2080,6 @@ Ek ayrıntılar:
<translation id="8719528812645237045">Üstte çoklu delik</translation>
<translation id="8725066075913043281">Yeniden dene</translation>
<translation id="8726549941689275341">Sayfa boyutu:</translation>
-<translation id="8728672262656704056">Gizli moda geçtiniz</translation>
<translation id="8730621377337864115">Bitti</translation>
<translation id="8731544501227493793">Şifreleri yönet düğmesi, Chrome ayarlarında şifrelerinizi görüp yönetmek için Enter'a basın</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> cihazınız <ph name="MANAGER" /> tarafından yönetiliyor</translation>
@@ -2105,6 +2156,7 @@ Ek ayrıntılar:
<translation id="9020542370529661692">Bu sayfa <ph name="TARGET_LANGUAGE" /> diline çevrildi</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Geçersiz)</translation>
+<translation id="9030265603405983977">Tek renk</translation>
<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>
@@ -2128,6 +2180,7 @@ Ek ayrıntılar:
<translation id="91108059142052966">Yönetici politikası, gizli içerik görünür haldeyken <ph name="APPLICATION_TITLE" /> ile ekran paylaşımını devre dışı bırakır</translation>
<translation id="9114524666733003316">Kart onaylanıyor...</translation>
<translation id="9114581008513152754">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="9117930699067497412">Taze</translation>
<translation id="9119042192571987207">Yüklendi</translation>
<translation id="9128016270925453879">Politikalar yüklendi</translation>
<translation id="9128870381267983090">AÄŸa baÄŸlan</translation>
@@ -2146,6 +2199,7 @@ Ek ayrıntılar:
<translation id="9170848237812810038">&amp;Geri al</translation>
<translation id="9171296965991013597">Uygulamadan çıkılsın mı?</translation>
<translation id="9173282814238175921">Tek doküman/Yeni sayfa</translation>
+<translation id="9173995187295789444">Bluetooth cihazları taranıyor...</translation>
<translation id="917450738466192189">Sunucunun sertifikası geçersiz.</translation>
<translation id="9174917557437862841">Sekme değiştirme düğmesi, bu sekmeye geçmek için Enter tuşuna basın</translation>
<translation id="9179703756951298733">Chrome ayarlarından ödemelerinizi ve kredi kartı bilgilerini yönetin</translation>
diff --git a/chromium/components/strings/components_strings_uk.xtb b/chromium/components/strings/components_strings_uk.xtb
index 649c79963ef..257463e0c45 100644
--- a/chromium/components/strings/components_strings_uk.xtb
+++ b/chromium/components/strings/components_strings_uk.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Якщо вибрати цю опцію, Chrome зберігатиме копію даних вашої картки на цьому приÑтрої Ð´Ð»Ñ ÑˆÐ²Ð¸Ð´ÑˆÐ¾Ð³Ð¾ Ð·Ð°Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€Ð¼.</translation>
<translation id="1110994991967754504">Виберіть тип Ð´Ð»Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»Ñƒ "<ph name="PERMISSION_NAME" />"</translation>
<translation id="1113869188872983271">&amp;Відмінити перевпорÑдкуваннÑ</translation>
+<translation id="1123753900084781868">Живі Ñубтитри зараз недоÑтупні</translation>
<translation id="1125573121925420732">Можуть з’ÑвлÑтиÑÑ Ð·Ð°ÑÑ‚ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑиÑтеми безпеки Ñайтів. Цю проблему буде незабаром виправлено.</translation>
<translation id="112840717907525620">Кеш-пам’ÑÑ‚ÑŒ правила не пошкоджено</translation>
<translation id="1130564665089811311">Кнопка "ПереклаÑти Ñторінку"; натиÑніть Enter, що переклаÑти цю Ñторінку в Google Перекладачі</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">Ðазва приÑтрою</translation>
<translation id="124116460088058876">Інші мови</translation>
<translation id="1243027604378859286">Ðвтор:</translation>
+<translation id="1246424317317450637">Жирний</translation>
<translation id="1250759482327835220">Щоб наÑтупного разу платити швидше, збережіть дані картки, Ñ–Ð¼â€™Ñ Ñ‚Ð° платіжну адреÑу в обліковому запиÑÑ– Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (Ñинхронізовано)</translation>
<translation id="1256368399071562588">&lt;p&gt;Якщо веб-Ñайт не відкриваєтьÑÑ:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">Змініть пароль</translation>
<translation id="1484290072879560759">Вибрати адреÑу доÑтавки</translation>
<translation id="1492194039220927094">Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ правила:</translation>
+<translation id="1495677929897281669">Ðазад на вкладку</translation>
<translation id="1501859676467574491">Показує картки з облікового запиÑу Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ помилку з’ÑвлÑєтьÑÑ, Ñкщо ви кориÑтуєтеÑÑ Ð¿Ð¾Ñ€Ñ‚Ð°Ð»Ð¾Ð¼ Wi-Fi, на Ñкий потрібно ввійти, перш ніж підключитиÑÑ Ð´Ð¾ мережі.&lt;/p&gt;
&lt;p&gt;Щоб виправити цю помилку, натиÑніть &lt;strong&gt;ПідключитиÑÑ&lt;/strong&gt; на Ñторінці, Ñку ви намагаєтеÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð· цієї Ñторінки</translation>
<translation id="153384715582417236">Більше нічого немає</translation>
<translation id="1536390784834419204">ПереклаÑти Ñторінку</translation>
+<translation id="1539840569003678498">Звіт надіÑлано:</translation>
<translation id="154408704832528245">Вибрати адреÑу доÑтавки</translation>
<translation id="1549470594296187301">Щоб кориÑтуватиÑÑ Ñ†Ñ–Ñ”ÑŽ функцією, потрібно ввімкнути JavaScript.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">Спочатку по ширині</translation>
<translation id="168693727862418163">Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€Ð¸Ñ‚Ð¸ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ правила в Ñхемі, тому воно ігноруватиметьÑÑ.</translation>
<translation id="168841957122794586">Сертифікат Ñервера міÑтить Ñлабкий криптографічний ключ.</translation>
+<translation id="1696290444144917273">ПереглÑнути дані віртуальної картки</translation>
<translation id="1697532407822776718">Готово!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Ðе вдалоÑÑ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¸Ñ‚Ð¸, що це Ñервер <ph name="DOMAIN" />. Його Ñертифікат безпеки почне діÑти завтра. Можливо, Ñервер налаштовано неправильно або хтоÑÑŒ намагаєтьÑÑ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð¿Ð¸Ñ‚Ð¸ ваші дані.}one{Ðе вдалоÑÑ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¸Ñ‚Ð¸, що це Ñервер <ph name="DOMAIN" />. Його Ñертифікат безпеки почне діÑти через # день. Можливо, Ñервер налаштовано неправильно або хтоÑÑŒ намагаєтьÑÑ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð¿Ð¸Ñ‚Ð¸ ваші дані.}few{Ðе вдалоÑÑ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¸Ñ‚Ð¸, що це Ñервер <ph name="DOMAIN" />. Його Ñертифікат безпеки почне діÑти через # дні. Можливо, Ñервер налаштовано неправильно або хтоÑÑŒ намагаєтьÑÑ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð¿Ð¸Ñ‚Ð¸ ваші дані.}many{Ðе вдалоÑÑ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¸Ñ‚Ð¸, що це Ñервер <ph name="DOMAIN" />. Його Ñертифікат безпеки почне діÑти через # днів. Можливо, Ñервер налаштовано неправильно або хтоÑÑŒ намагаєтьÑÑ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð¿Ð¸Ñ‚Ð¸ ваші дані.}other{Ðе вдалоÑÑ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¸Ñ‚Ð¸, що це Ñервер <ph name="DOMAIN" />. Його Ñертифікат безпеки почне діÑти через # днÑ. Можливо, Ñервер налаштовано неправильно або хтоÑÑŒ намагаєтьÑÑ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð¿Ð¸Ñ‚Ð¸ ваші дані.}}</translation>
<translation id="1710259589646384581">ОС</translation>
+<translation id="1711234383449478798">Проігноровано, оÑкільки Ð´Ð»Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð° <ph name="POLICY_NAME" /> не вибрано Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ <ph name="VALUE" />.</translation>
<translation id="1712552549805331520">Сайт <ph name="URL" /> хоче поÑтійно зберігати дані на вашому локальному комп’ютері</translation>
<translation id="1713628304598226412">Лоток 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Поштова Ñкринька 3</translation>
<translation id="1718029547804390981">Документ завеликий Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð¼Ñ–Ñ‚Ð¾Ðº</translation>
<translation id="1721424275792716183">* Обов’Ñзкове поле</translation>
+<translation id="1727613060316725209">Сертифікат дійÑний</translation>
<translation id="1727741090716970331">Додайте дійÑний номер картки</translation>
<translation id="1728677426644403582">Ви переглÑдаєте джерело веб-Ñторінки</translation>
<translation id="173080396488393970">Цей тип картки не підтримуєтьÑÑ</translation>
@@ -246,7 +253,6 @@
ваш запит Ð´Ð»Ñ Ñайту <ph name="SITE" />. Оператори можуть викориÑтовувати
правило джерела, щоб налаштувати захиÑÑ‚ та інші реÑурÑи Ñайту.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Оновіть парольну фразу Ð´Ð»Ñ Ñинхронізації.</translation>
<translation id="1787142507584202372">Тут відображатимутьÑÑ Ð²Ð°ÑˆÑ– відкриті вкладки</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />; доÑтупно кілька дій, натиÑкайте Tab, щоб переходити між ними</translation>
@@ -279,6 +285,7 @@
<translation id="1919345977826869612">ОголошеннÑ</translation>
<translation id="1919367280705858090">Як виправити конкретну помилку</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Ðемає}=1{1 Ñайт}one{# Ñайт}few{# Ñайти}many{# Ñайтів}other{# Ñайту}}</translation>
+<translation id="1924727005275031552">Ðові дані</translation>
<translation id="1945968466830820669">Ви можете втратити доÑтуп до облікового запиÑу організації, або хтоÑÑŒ може викраÑти вашу оÑобиÑту інформацію. Chromium радить змінити пароль.</translation>
<translation id="1947454675006758438">Скріпити вгорі праворуч</translation>
<translation id="1958218078413065209">Ваш найкращий результат – <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@
<translation id="2042213636306070719">Лоток 7</translation>
<translation id="204357726431741734">Увійдіть, щоб кориÑтуватиÑÑ Ð¿Ð°Ñ€Ð¾Ð»Ñми, збереженими в обліковому запиÑÑ– Google</translation>
<translation id="2053111141626950936">Сторінки цією мовою (<ph name="LANGUAGE" />) не перекладатимутьÑÑ.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Коли цей елемент ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾ й активовано, Chrome аналізує ваші нещодавні дії у веб-переглÑдачі та визначає, до Ñкої великої групи чи "когорти" людей Ð²Ð°Ñ Ð²Ñ–Ð´Ð½ÐµÑти. Рекламодавці можуть вибирати Ð¾Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи. Ваші дії у веб-переглÑдачі конфіденційно зберігаютьÑÑ Ð½Ð° приÑтрої. Ваша група оновлюєтьÑÑ Ñ‰Ð¾Ð´Ð½Ñ.}=1{Коли цей елемент ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾ й активовано, Chrome аналізує ваші нещодавні дії у веб-переглÑдачі та визначає, до Ñкої великої групи чи "когорти" людей Ð²Ð°Ñ Ð²Ñ–Ð´Ð½ÐµÑти. Рекламодавці можуть вибирати Ð¾Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи. Ваші дії у веб-переглÑдачі конфіденційно зберігаютьÑÑ Ð½Ð° приÑтрої. Ваша група оновлюєтьÑÑ Ñ‰Ð¾Ð´Ð½Ñ.}one{Коли цей елемент ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾ й активовано, Chrome аналізує ваші нещодавні дії у веб-переглÑдачі та визначає, до Ñкої великої групи чи "когорти" людей Ð²Ð°Ñ Ð²Ñ–Ð´Ð½ÐµÑти. Рекламодавці можуть вибирати Ð¾Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи. Ваші дії у веб-переглÑдачі конфіденційно зберігаютьÑÑ Ð½Ð° приÑтрої. Ваша група оновлюєтьÑÑ ÐºÐ¾Ð¶ÐµÐ½ {NUM_DAYS} день.}few{Коли цей елемент ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾ й активовано, Chrome аналізує ваші нещодавні дії у веб-переглÑдачі та визначає, до Ñкої великої групи чи "когорти" людей Ð²Ð°Ñ Ð²Ñ–Ð´Ð½ÐµÑти. Рекламодавці можуть вибирати Ð¾Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи. Ваші дії у веб-переглÑдачі конфіденційно зберігаютьÑÑ Ð½Ð° приÑтрої. Ваша група оновлюєтьÑÑ ÐºÐ¾Ð¶Ð½Ñ– {NUM_DAYS} дні.}many{Коли цей елемент ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾ й активовано, Chrome аналізує ваші нещодавні дії у веб-переглÑдачі та визначає, до Ñкої великої групи чи "когорти" людей Ð²Ð°Ñ Ð²Ñ–Ð´Ð½ÐµÑти. Рекламодавці можуть вибирати Ð¾Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи. Ваші дії у веб-переглÑдачі конфіденційно зберігаютьÑÑ Ð½Ð° приÑтрої. Ваша група оновлюєтьÑÑ ÐºÐ¾Ð¶Ð½Ñ– {NUM_DAYS} днів.}other{Коли цей елемент ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾ й активовано, Chrome аналізує ваші нещодавні дії у веб-переглÑдачі та визначає, до Ñкої великої групи чи "когорти" людей Ð²Ð°Ñ Ð²Ñ–Ð´Ð½ÐµÑти. Рекламодавці можуть вибирати Ð¾Ð³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— групи. Ваші дії у веб-переглÑдачі конфіденційно зберігаютьÑÑ Ð½Ð° приÑтрої. Ваша група оновлюєтьÑÑ ÐºÐ¾Ð¶Ð½Ñ– {NUM_DAYS} днÑ.}}</translation>
<translation id="2053553514270667976">Поштовий індекÑ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 пропозиціÑ}one{# пропозиціÑ}few{# пропозиції}many{# пропозицій}other{# пропозиції}}</translation>
<translation id="2071692954027939183">Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾ заблоковано, оÑкільки ви зазвичай не дозволÑєте Ñ—Ñ…</translation>
<translation id="2079545284768500474">Відмінити</translation>
<translation id="20817612488360358">СиÑтемні параметри прокÑÑ–-Ñервера налаштовано Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑтаннÑ, але чітко вказано Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ÐºÑÑ–-Ñервера.</translation>
<translation id="2082238445998314030">Результат <ph name="RESULT_NUMBER" /> з <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Зберегти…</translation>
<translation id="2088086323192747268">Кнопка "Керувати Ñинхронізацією"; натиÑніть Enter, щоб вибрати в налаштуваннÑÑ… Chrome, Ñку інформацію Ñинхронізувати</translation>
<translation id="2091887806945687916">Сигнал</translation>
<translation id="2094505752054353250">ÐевідповідніÑÑ‚ÑŒ домену</translation>
@@ -379,6 +388,7 @@
<translation id="2317259163369394535">Ð”Ð»Ñ Ñайту <ph name="DOMAIN" /> потрібно ввеÑти Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та пароль.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, діє до <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">ÐалаштуваннÑм керує ваш адмініÑтратор</translation>
+<translation id="2340263603246777781">Сайт <ph name="ORIGIN" /> хоче підключитиÑÑ Ð´Ð¾ приÑтрою</translation>
<translation id="2344028582131185878">Ðвтоматичні завантаженнÑ</translation>
<translation id="2346319942568447007">Скопійоване зображеннÑ</translation>
<translation id="2354001756790975382">Інші закладки</translation>
@@ -386,8 +396,10 @@
<translation id="2355395290879513365">ЗловмиÑники можуть бачити зображеннÑ, Ñкі ви переглÑдаєте на цьому Ñайті, Ñ– змінювати Ñ—Ñ… із метою ошукати ваÑ.</translation>
<translation id="2356070529366658676">Запитати</translation>
<translation id="2357481397660644965">Вашим приÑтроєм керує <ph name="DEVICE_MANAGER" />, а обліковим запиÑом – <ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Менше ніж через день}=1{Через день}one{Через {NUM_DAYS} день}few{Через {NUM_DAYS} дні}many{Через {NUM_DAYS} днів}other{Через {NUM_DAYS} днÑ}}</translation>
<translation id="2359629602545592467">Декілька</translation>
<translation id="2359808026110333948">Продовжити</translation>
+<translation id="2359961752320758691">ЗаÑтоÑовуєтьÑÑ Ð½Ð¾Ð¼ÐµÑ€ віртуальної картки.</translation>
<translation id="2367567093518048410">Рівень</translation>
<translation id="2372464001869762664">Щойно ви підтвердите дані картки з облікового запиÑу Google, цей Ñайт отримає доÑтуп до них. Знайдіть код CVC в даних про обліковий Ð·Ð°Ð¿Ð¸Ñ Plex.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@
<translation id="239429038616798445">Цей ÑпоÑіб Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð½ÐµÐ´Ð¾Ñтупний. Виберіть інший ÑпоÑіб.</translation>
<translation id="2396249848217231973">&amp;Відмінити видаленнÑ</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Старі дані</translation>
<translation id="2413528052993050574">Цей Ñервер не зміг довеÑти, що він – домен <ph name="DOMAIN" />. Можливо, його Ñертифікат безпеки відкликано. Імовірні причини: неправильна ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð°Ð±Ð¾ хтоÑÑŒ намагаєтьÑÑ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð¿Ð¸Ñ‚Ð¸ ваше з’єднаннÑ.</translation>
<translation id="2414886740292270097">Темна</translation>
<translation id="2438874542388153331">Пробити чотири отвори праворуч</translation>
@@ -425,10 +438,10 @@
<translation id="2521385132275182522">Скріпити внизу праворуч</translation>
<translation id="2523886232349826891">Збережено лише на цьому приÑтрої</translation>
<translation id="2524461107774643265">Додайте більше інформації</translation>
-<translation id="2526590354069164005">Google Desktop</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{і ще 1}one{і ще #}few{і ще #}many{і ще #}other{і ще #}}</translation>
<translation id="2536110899380797252">Додати адреÑу</translation>
<translation id="2539524384386349900">Визначити</translation>
+<translation id="2541219929084442027">Сторінки, Ñкі ви переглÑдали в анонімному режимі, не реєÑтруютьÑÑ Ð² Ñ–Ñторії веб-переглÑдача чи пошуку та не залишають файлів cookie. Коли ви закриваєте вÑÑ– анонімні вкладки, зберігаютьÑÑ Ð»Ð¸ÑˆÐµ завантажені файли й Ñтворені закладки.</translation>
<translation id="2544644783021658368">Один документ</translation>
<translation id="254947805923345898">ÐедійÑне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð°.</translation>
<translation id="255002559098805027">ХоÑÑ‚ <ph name="HOST_NAME" /> надіÑлав недійÑну відповідь.</translation>
@@ -448,6 +461,7 @@
<translation id="2629325967560697240">Щоб веб-переглÑдач Chrome був макÑимально безпечним, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />увімкніть покращений захиÑÑ‚<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">IP-адреÑу Ñервера <ph name="HOST_NAME" /> не знайдено.</translation>
<translation id="2639739919103226564">СтатуÑ:</translation>
+<translation id="264810637653812429">СуміÑних приÑтроїв не знайдено.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />; натиÑніть Tab, а потім – Enter, щоб очиÑтити Ñ–Ñторію веб-переглÑду, файли cookie, кеш та інше в налаштуваннÑÑ… Chrome</translation>
<translation id="2650446666397867134">У доÑтупі до файлу відмовлено</translation>
@@ -492,6 +506,7 @@
<translation id="2799223571221894425">ПерезапуÑтити</translation>
<translation id="2803306138276472711">Ð¤ÑƒÐ½ÐºÑ†Ñ–Ñ Ð±ÐµÐ·Ð¿ÐµÑ‡Ð½Ð¾Ð³Ð¾ переглÑду від Google нещодавно <ph name="BEGIN_LINK" />виÑвила зловмиÑне програмне забезпеченнÑ<ph name="END_LINK" /> на Ñайті <ph name="SITE" />. Іноді зловмиÑне програмне Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ Ð·Ð°Ñ€Ð°Ð¶Ð°Ñ” зазвичай безпечні веб-Ñайти.</translation>
<translation id="2807052079800581569">Вертикальне Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ</translation>
+<translation id="2820957248982571256">СкануваннÑ…</translation>
<translation id="2824775600643448204">ÐдреÑний Ñ– пошуковий Ñ€Ñдок</translation>
<translation id="2826760142808435982">Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð·Ð°ÑˆÐ¸Ñ„Ñ€Ð¾Ð²Ð°Ð½Ð¾ й автентифіковано з викориÑтаннÑм шифру <ph name="CIPHER" /> Ñ– викориÑтовує механізм обміну ключами <ph name="KX" />.</translation>
<translation id="2835170189407361413">ОчиÑтити форму</translation>
@@ -499,6 +514,8 @@
<translation id="2850739647070081192">Invite (конверт)</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="2859806420264540918">Цей Ñайт показує нав’Ñзливі чи оманливі оголошеннÑ.</translation>
+<translation id="287596039013813457">ПриÑзний</translation>
+<translation id="2876489322757410363">Щоб оплатити в зовнішньому додатку, ви вийдете з режиму анонімного переглÑду. Продовжити?</translation>
<translation id="2878197950673342043">Зігнути за типом плаката</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ñ–ÐºÐ¾Ð½</translation>
@@ -548,7 +565,6 @@
<translation id="3060227939791841287">C9 (конверт)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, натиÑніть Tab, а тоді Enter, щоб виконати перевірку безпеки в налаштуваннÑÑ… Chrome</translation>
<translation id="3061707000357573562">Служба виправлень</translation>
-<translation id="3064966200440839136">Щоб оплатити в зовнішньому додатку, ви вийдете з режиму анонімного переглÑду. Продовжити?</translation>
<translation id="306573536155379004">Гра почалаÑÑ.</translation>
<translation id="3080254622891793721">ЗображеннÑ</translation>
<translation id="3086579638707268289">Ваші дії в Інтернеті відÑтежуютьÑÑ</translation>
@@ -571,7 +587,6 @@
<translation id="315504272643575312">Вашим обліковим запиÑом керує <ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Відновити</translation>
<translation id="3162559335345991374">Можливо, щоб під’єднатиÑÑ Ð´Ð¾ цієї мережі Wi-Fi, потрібно відвідати Ñ—Ñ— Ñторінку входу.</translation>
-<translation id="3167968892399408617">Сторінки, Ñкі ви переглÑдаєте на анонімних вкладках, не реєÑтруютьÑÑ Ð² Ñ–Ñторії веб-переглÑдача чи Ñ–Ñторії пошуку та не залишають файлів cookie, коли ви закриваєте вÑÑ– анонімні вкладки. УÑÑ– завантажені файли чи Ñтворені закладки зберігаютьÑÑ.</translation>
<translation id="3169472444629675720">Рекомендації</translation>
<translation id="3174168572213147020">ОÑтрів</translation>
<translation id="3176929007561373547">Перевірте Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñвого прокÑÑ–-Ñервера чи звернітьÑÑ Ð´Ð¾ адмініÑтратора мережі,
@@ -597,10 +612,12 @@
<translation id="3229041911291329567">Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ верÑÑ–Ñ— приÑтрою та веб-переглÑдача</translation>
<translation id="323107829343500871">ВвеÑти код CVC картки <ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Завжди виÑвлÑти важливий вміÑÑ‚ на цьому Ñайті</translation>
+<translation id="3249845759089040423">Чудовий</translation>
<translation id="3252266817569339921">Французька</translation>
<translation id="3266793032086590337">Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ (конфліктне)</translation>
<translation id="3268451620468152448">Відкриті вкладки</translation>
<translation id="3270847123878663523">&amp;Відмінити перевпорÑдкуваннÑ</translation>
+<translation id="3271648667212143903">Сайт <ph name="ORIGIN" /> хоче підключитиÑÑ</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Ваша Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ (<ph name="ENROLLMENT_DOMAIN" />) надіÑлала вказаним веб-Ñайтам деÑку інформацію, таку Ñк Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¹ правила.</translation>
<translation id="3282497668470633863">Додати Ñ–Ð¼â€™Ñ Ð½Ð° кредитній картці</translation>
@@ -653,6 +670,7 @@
<translation id="3428151540071562330">Щонайменше один ідентифікатор URI шаблону Ñервера DnsOverHttpsTemplates недійÑний Ñ– не викориÑтовуватиметьÑÑ.</translation>
<translation id="3431636764301398940">Зберегти цю картку на приÑтрої</translation>
<translation id="3432601291244612633">Закрити Ñторінку</translation>
+<translation id="3435738964857648380">Безпека</translation>
<translation id="3435896845095436175">Увімкнути</translation>
<translation id="3438829137925142401">ВикориÑтовувати паролі, збережені в обліковому запиÑÑ– Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -695,7 +713,10 @@
<translation id="3584299510153766161">Пробити два отвори внизу</translation>
<translation id="3586931643579894722">Сховати докладні дані</translation>
<translation id="3587738293690942763">Середній</translation>
+<translation id="3590643883886679995">Коли ви вимкнете режим анонімного переглÑду, дані Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ зберігатимутьÑÑ Ð½Ð° цьому приÑтрої.</translation>
+<translation id="359126217934908072">МіÑÑць/рік:</translation>
<translation id="3592413004129370115">Italian (конверт)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Ви можете будь-коли Ñкинути цю групу. Перехід у нову групу займає приблизно один день.}=1{Ви можете будь-коли Ñкинути цю групу. Перехід у нову групу займає приблизно один день.}one{Ви можете будь-коли Ñкинути цю групу. Перехід у нову групу займає {NUM_DAYS} день.}few{Ви можете будь-коли Ñкинути цю групу. Перехід у нову групу займає {NUM_DAYS} дні.}many{Ви можете будь-коли Ñкинути цю групу. Перехід у нову групу займає {NUM_DAYS} днів.}other{Ви можете будь-коли Ñкинути цю групу. Перехід у нову групу займає {NUM_DAYS} днÑ.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Додаток заблоковано адмініÑтратором</translation>
<translation id="3608932978122581043">ÐžÑ€Ñ–Ñ”Ð½Ñ‚Ð°Ñ†Ñ–Ñ Ñтрічки</translation>
@@ -703,14 +724,14 @@
<translation id="361438452008624280">Пункт ÑпиÑку <ph name="LANGUAGE_ID" />: мова невідома або не підтримуєтьÑÑ.</translation>
<translation id="3615877443314183785">Введіть дійÑний термін дії</translation>
<translation id="36224234498066874">ОчиÑтити Ñ–Ñторію…</translation>
-<translation id="362276910939193118">Показати повну Ñ–Ñторію</translation>
-<translation id="3625635938337243871">Дані Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ зберігатимутьÑÑ Ð½Ð° цьому приÑтрої піÑÐ»Ñ Ð²Ð¸Ñ…Ð¾Ð´Ñƒ з режиму анонімного переглÑду.</translation>
+<translation id="362276910939193118">Показати вÑÑŽ Ñ–Ñторію</translation>
<translation id="3630155396527302611">Якщо цій програмі вже надано доÑтуп до мережі, Ñпробуйте
вилучити Ñ—Ñ— зі ÑпиÑку та додати знову.</translation>
<translation id="3630699740441428070">ÐдмініÑтратори цього приÑтрою, Ñкі налаштували з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· мережею, імовірно, можуть переглÑдати ваш мережевий трафік (зокрема веб-Ñайти, Ñкі ви відвідуєте).</translation>
<translation id="3631244953324577188">БіометріÑ</translation>
<translation id="3633738897356909127">Кнопка "Оновити Chrome"; натиÑніть Enter, щоб оновити веб-переглÑдач Chrome у його налаштуваннÑÑ…</translation>
<translation id="3634530185120165534">Лоток 5</translation>
+<translation id="3637662659967048211">Зберегти в обліковий Ð·Ð°Ð¿Ð¸Ñ Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Додаток:</translation>
<translation id="3650584904733503804">Перевірку закінчено</translation>
@@ -751,6 +772,7 @@
<translation id="3781428340399460090">ЯÑкраво-рожевий</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">ПриÑтрої Bluetooth</translation>
+<translation id="3787675388804467730">Ðомер віртуальної картки</translation>
<translation id="3787705759683870569">Діє до <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Розмір 16</translation>
<translation id="3789841737615482174">УÑтановити</translation>
@@ -770,6 +792,7 @@
<translation id="3841184659773414994">Обробники файлів</translation>
<translation id="385051799172605136">Ðазад</translation>
<translation id="3858027520442213535">Оновити дату й чаÑ</translation>
+<translation id="3881478300875776315">Показати менше Ñ€Ñдків</translation>
<translation id="3884278016824448484">Конфліктуючий ідентифікатор приÑтрою</translation>
<translation id="3885155851504623709">Цивільний округ</translation>
<translation id="388632593194507180">ВиÑвлено відÑтеженнÑ</translation>
@@ -795,6 +818,7 @@
<translation id="397105322502079400">ОбчиÑленнÑ...</translation>
<translation id="3973234410852337861">ХоÑÑ‚ <ph name="HOST_NAME" /> заблокований</translation>
<translation id="3973357910713125165">Кнопка "Виконати перевірку безпеки Chrome", натиÑніть Enter, щоб виконати перевірку безпеки в налаштуваннÑÑ… Chrome</translation>
+<translation id="3986705137476756801">Ðаразі вимкнути живі Ñубтитри</translation>
<translation id="3987405730340719549">Веб-переглÑдач Chrome визначив, що цей Ñайт може бути підробленим або шахрайÑьким.
Якщо ви вважаєте, що ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°, перейдіть на Ñторінку https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -891,13 +915,14 @@
<translation id="4275830172053184480">ПерезапуÑÑ‚Ñ–Ñ‚ÑŒ приÑтрій</translation>
<translation id="4277028893293644418">Скинути пароль</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Цю картку збережено у вашому обліковому запиÑÑ– Google}one{Ці картки збережено у вашому обліковому запиÑÑ– Google}few{Ці картки збережено у вашому обліковому запиÑÑ– Google}many{Ці картки збережено у вашому обліковому запиÑÑ– Google}other{Ці картки збережено у вашому обліковому запиÑÑ– Google}}</translation>
+<translation id="4287885627794386150">ДоÑтупно в пробній верÑÑ–Ñ—, але не активовано</translation>
<translation id="4297502707443874121">ЕÑкіз Ð´Ð»Ñ Ñторінки <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Розгорнути</translation>
<translation id="4300675098767811073">Пробити кілька отворів праворуч</translation>
<translation id="4302514097724775343">Щоб почати гру, торкнітьÑÑ Ð´Ð¸Ð½Ð¾Ð·Ð°Ð²Ñ€Ð°</translation>
<translation id="4302965934281694568">Chou3 (конверт)</translation>
<translation id="4305666528087210886">Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ доÑтуп до файлу</translation>
-<translation id="4305817255990598646">Перейти</translation>
+<translation id="4306529830550717874">Зберегти адреÑу?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Блокувати (за умовчаннÑм)</translation>
<translation id="4314815835985389558">ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñинхронізацією</translation>
@@ -924,6 +949,7 @@
<translation id="4377125064752653719">Ви пробували зв’ÑзатиÑÑ Ð· доменом <ph name="DOMAIN" />, проте Ñервер надав Ñертифікат, відкликаний його видавцем. Це означає, що не варто довірÑти обліковим даним ÑиÑтеми захиÑту, наданим Ñервером. Можливо, ви обмінюєтеÑÑ Ð´Ð°Ð½Ð¸Ð¼Ð¸ зі зловмиÑником.</translation>
<translation id="4378154925671717803">Телефон</translation>
<translation id="4390472908992056574">До полів</translation>
+<translation id="4406883609789734330">Живі Ñубтитри</translation>
<translation id="4406896451731180161">результати пошуку</translation>
<translation id="4408413947728134509">Файли cookie: <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Щойно ви ввели пароль на оманливому Ñайті. Chrome радить негайно перейти на <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> та інші Ñайти, де викориÑтовуєтьÑÑ Ñ†ÐµÐ¹ пароль, Ñ– змінити його.</translation>
@@ -936,7 +962,6 @@
<translation id="4435702339979719576">ЛиÑтівка)</translation>
<translation id="443673843213245140">ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ÐºÑÑ–-Ñервера вимкнено, але чітко вказано Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ÐºÑÑ–-Ñервера.</translation>
<translation id="4464826014807964867">Веб-Ñайти, Ñкі отримали інформацію від вашої організації</translation>
-<translation id="4466881336512663640">Зміни форми не буде збережено. Продовжити?</translation>
<translation id="4476953670630786061">Ð¦Ñ Ñ„Ð¾Ñ€Ð¼Ð° незахищена. ÐÐ²Ñ‚Ð¾Ð·Ð°Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾.</translation>
<translation id="4477350412780666475">ÐаÑтупна композиціÑ</translation>
<translation id="4482953324121162758">Цей Ñайт не перекладатиметьÑÑ.</translation>
@@ -970,6 +995,7 @@
<translation id="4594403342090139922">&amp;Відмінити видаленнÑ</translation>
<translation id="4597348597567598915">Розмір 8</translation>
<translation id="4600854749408232102">C6/C5 (конверт)</translation>
+<translation id="4606870351894164739">Вражаючий</translation>
<translation id="4628948037717959914">ФотографіÑ</translation>
<translation id="4631649115723685955">З кешбеком</translation>
<translation id="4636930964841734540">ІнформаціÑ</translation>
@@ -989,6 +1015,7 @@
<translation id="4691835149146451662">Architecture-A (конверт)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Сторона</translation>
+<translation id="4702656508969495934">ВідображаютьÑÑ Ð¶Ð¸Ð²Ñ– Ñубтитри. Щоб ÑфокуÑуватиÑÑ Ð½Ð° них, ÑкориÑтайтеÑÑ Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ñ‡ÐµÐ¼ вікон.</translation>
<translation id="4708268264240856090">Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ñ–Ñ€Ð²Ð°Ð½Ð¾</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />провеÑти діагноÑтику мережі Windows<ph name="END_LINK" /></translation>
@@ -1002,6 +1029,7 @@
<translation id="4738601419177586157">ÐŸÑ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ за запитом "<ph name="TEXT" />"</translation>
<translation id="4742407542027196863">Керувати паролÑми…</translation>
<translation id="4744603770635761495">Виконуваний шлÑÑ…</translation>
+<translation id="4749011317274908093">Ви перейшли в анонімний режим</translation>
<translation id="4750917950439032686">Ваша Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ (Ñк-от паролі та номери кредитних карток) залишаєтьÑÑ ÐºÐ¾Ð½Ñ„Ñ–Ð´ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ÑŽ, коли надÑилаєтьÑÑ Ð½Ð° цей Ñайт.</translation>
<translation id="4756388243121344051">&amp;ІÑторіÑ</translation>
<translation id="4758311279753947758">Додати контактну інформацію</translation>
@@ -1031,6 +1059,8 @@
<translation id="4813512666221746211">Помилка мережі</translation>
<translation id="4816492930507672669">За розміром Ñторінки</translation>
<translation id="4819347708020428563">Редагувати примітки в режимі переглÑду за умовчаннÑм?</translation>
+<translation id="4825507807291741242">Потужний</translation>
+<translation id="4838327282952368871">Мрійливий</translation>
<translation id="484462545196658690">Ðвтоматично</translation>
<translation id="4850886885716139402">ПереглÑд</translation>
<translation id="485316830061041779">Ðімецька</translation>
@@ -1124,7 +1154,7 @@
<translation id="5164798890604758545">Введено текÑÑ‚</translation>
<translation id="516920405563544094">Введіть код CVC картки <ph name="CREDIT_CARD" />. Щойно ви підтвердите дані картки в обліковому запиÑÑ– Google, цей Ñайт отримає доÑтуп до них.</translation>
<translation id="5169827969064885044">Ви можете втратити доÑтуп до облікового запиÑу організації, або хтоÑÑŒ може викраÑти вашу оÑобиÑту інформацію. Chrome радить змінити пароль.</translation>
-<translation id="5171045022955879922">Знайдіть або введіть URL-адреÑу</translation>
+<translation id="5171045022955879922">Введіть запит або URL-адреÑу</translation>
<translation id="5171689220826475070">Fanfold-European</translation>
<translation id="5172758083709347301">Комп’ютер</translation>
<translation id="5179510805599951267">Це не <ph name="ORIGINAL_LANGUAGE" />? Повідомте про помилку</translation>
@@ -1167,18 +1197,21 @@
<translation id="5314967030527622926">Виробник буклетів</translation>
<translation id="5316812925700871227">Обернути проти годинникової Ñтрілки</translation>
<translation id="5317780077021120954">Зберегти</translation>
+<translation id="5321288445143113935">Розгорнуто</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> з <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Вибрати контактну інформацію</translation>
-<translation id="5327248766486351172">Ðазва</translation>
+<translation id="5327248766486351172">Ім’Ñ</translation>
<translation id="5329858041417644019">Веб-переглÑдачем не керує адмініÑтратор</translation>
<translation id="5332219387342487447">СпоÑіб доÑтавки</translation>
<translation id="5333022057423422993">Веб-переглÑдач Chrome виÑвив, що введений пароль розкрито через Ð¿Ð¾Ñ€ÑƒÑˆÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ даних. Щоб захиÑтити Ñвої облікові запиÑи, радимо перевірити надійніÑÑ‚ÑŒ збережених паролів.</translation>
<translation id="5334013548165032829">Докладні журнали ÑиÑтеми</translation>
+<translation id="5334145288572353250">Зберегти адреÑу?</translation>
<translation id="5340250774223869109">Додаток заблоковано</translation>
<translation id="534295439873310000">ПриÑтрої NFC</translation>
<translation id="5344579389779391559">Ð¦Ñ Ñторінка може Ñпробувати ÑÑ‚Ñгнути плату</translation>
<translation id="5355557959165512791">Зараз не можна перейти на Ñторінку <ph name="SITE" />, оÑкільки цей Ñертифікат відкликано. Помилки мережі й атаки зазвичай тимчаÑові, тому Ñ†Ñ Ñторінка, Ñкоріш за вÑе, запрацює пізніше.</translation>
<translation id="536296301121032821">Помилка Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½ÑŒ правила</translation>
+<translation id="5363309033720083897">ÐдмініÑтратор дозволив цей поÑлідовний порт</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="5386426401304769735">Ланцюжок Ñертифіката цього Ñайту міÑтить Ñертифікат, підпиÑаний за допомогою SHA-1.</translation>
@@ -1187,6 +1220,7 @@
<translation id="5398772614898833570">ÐžÐ³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð¾</translation>
<translation id="5400836586163650660">Сірий</translation>
<translation id="540969355065856584">Серверу не вдалоÑÑ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¸Ñ‚Ð¸, що це <ph name="DOMAIN" />. Його Ñертифікат безпеки зараз недійÑний. Можливі причини: неправильна ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð°Ð±Ð¾ хтоÑÑŒ перехопив ваше з’єднаннÑ.</translation>
+<translation id="541143247543991491">Хмара (на рівні ÑиÑтеми)</translation>
<translation id="541416427766103491">Ðакопичувач 4</translation>
<translation id="5421136146218899937">ОчиÑтити Ñ–Ñторію…</translation>
<translation id="5426179911063097041">Сайт <ph name="SITE" /> хоче надÑилати вам ÑповіщеннÑ</translation>
@@ -1200,6 +1234,7 @@
<translation id="5455374756549232013">ÐедійÑна мітка чаÑу правила</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" />}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="5463625433003343978">Пошук приÑтроїв…</translation>
<translation id="5469868506864199649">ІталійÑька</translation>
<translation id="5470861586879999274">&amp;Повторити редагуваннÑ</translation>
<translation id="5478437291406423475">B6/C4 (конверт)</translation>
@@ -1249,7 +1284,6 @@
<translation id="5624120631404540903">Керувати паролÑми</translation>
<translation id="5629630648637658800">Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½ÑŒ правила</translation>
<translation id="5631439013527180824">ÐедійÑний маркер ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ñтрою</translation>
-<translation id="5632627355679805402">Дані зашифровано <ph name="BEGIN_LINK" />паролем Google<ph name="END_LINK" /> від <ph name="TIME" />. Введіть пароль, щоб почати Ñинхронізацію.</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="5644090287519800334">Горизонтальний зÑув Ñторони 1 зображеннÑ</translation>
@@ -1288,12 +1322,12 @@
<translation id="5785756445106461925">Окрім цього, Ñторінка міÑтить незахищені реÑурÑи. Інші оÑоби можуть переглÑдати Ñ—Ñ… під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ…, а зловмиÑники можуть змінювати виглÑд Ñторінки.</translation>
<translation id="5786044859038896871">ВвеÑти дані кредитної картки?</translation>
<translation id="578633867165174378">Веб-переглÑдач Chrome виÑвив, що введений пароль розкрито через Ð¿Ð¾Ñ€ÑƒÑˆÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ даних. Радимо негайно змінити його.</translation>
-<translation id="5798290721819630480">Відхилити зміни?</translation>
<translation id="5803412860119678065">ВвеÑти дані кредитної картки <ph name="CARD_DETAIL" />?</translation>
<translation id="5804241973901381774">Дозволи</translation>
<translation id="5804427196348435412">ВикориÑтовувати приÑтрої NFC</translation>
<translation id="5810442152076338065">Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· доменом <ph name="DOMAIN" /> шифруєтьÑÑ Ð·Ð° допомогою заÑтарілого набору шифрів.</translation>
<translation id="5813119285467412249">&amp;Повторити додаваннÑ</translation>
+<translation id="5817918615728894473">Підключити</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Кошти ÑÑ‚ÑгуватимутьÑÑ Ð· цієї картки під Ñ‡Ð°Ñ Ð¾Ð¿Ð»Ð°Ñ‚Ð¸, але Ñ—Ñ— Ñправжній номер не повідомлÑтиметьÑÑ Ñайту. Ð—Ð°Ð´Ð»Ñ Ð¿Ñ–Ð´Ð²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ буде згенеровано тимчаÑовий код CVC.}one{Кошти ÑÑ‚ÑгуватимутьÑÑ Ð· вибраної картки під Ñ‡Ð°Ñ Ð¾Ð¿Ð»Ð°Ñ‚Ð¸, але Ñ—Ñ— Ñправжній номер не повідомлÑтиметьÑÑ Ñайту. Ð—Ð°Ð´Ð»Ñ Ð¿Ñ–Ð´Ð²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ буде згенеровано тимчаÑовий код CVC.}few{Кошти ÑÑ‚ÑгуватимутьÑÑ Ð· вибраної картки під Ñ‡Ð°Ñ Ð¾Ð¿Ð»Ð°Ñ‚Ð¸, але Ñ—Ñ— Ñправжній номер не повідомлÑтиметьÑÑ Ñайту. Ð—Ð°Ð´Ð»Ñ Ð¿Ñ–Ð´Ð²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ буде згенеровано тимчаÑовий код CVC.}many{Кошти ÑÑ‚ÑгуватимутьÑÑ Ð· вибраної картки під Ñ‡Ð°Ñ Ð¾Ð¿Ð»Ð°Ñ‚Ð¸, але Ñ—Ñ— Ñправжній номер не повідомлÑтиметьÑÑ Ñайту. Ð—Ð°Ð´Ð»Ñ Ð¿Ñ–Ð´Ð²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ буде згенеровано тимчаÑовий код CVC.}other{Кошти ÑÑ‚ÑгуватимутьÑÑ Ð· вибраної картки під Ñ‡Ð°Ñ Ð¾Ð¿Ð»Ð°Ñ‚Ð¸, але Ñ—Ñ— Ñправжній номер не повідомлÑтиметьÑÑ Ñайту. Ð—Ð°Ð´Ð»Ñ Ð¿Ñ–Ð´Ð²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ буде згенеровано тимчаÑовий код CVC.}}</translation>
<translation id="5826507051599432481">Загальне ім'Ñ (CN)</translation>
<translation id="5838278095973806738">Ðе вводьте конфіденційну інформацію на цьому Ñайті (Ñк-от паролі й дані кредитних карток). ЗловмиÑники можуть викраÑти Ñ—Ñ—.</translation>
@@ -1301,6 +1335,7 @@
<translation id="5855253129151731373">Ім'Ñ Ñ…Ð¾Ñту цього Ñайту Ñхоже на ім'Ñ Ñ…Ð¾Ñту Ñайту <ph name="LOOKALIKE_DOMAIN" />. Іноді зловмиÑники імітують Ñайти, вноÑÑчи незначні, майже непомітні зміни в доменне ім'Ñ.
Якщо ви вважаєте, що ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°, перейдіть на Ñторінку https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Вимк.</translation>
<translation id="5862579898803147654">Ðакопичувач 8</translation>
<translation id="5863847714970149516">ÐаÑтупна Ñторінка може Ñпробувати ÑÑ‚Ñгнути плату</translation>
<translation id="5866257070973731571">Додайте номер телефону</translation>
@@ -1317,6 +1352,7 @@
<translation id="5913377024445952699">Зйомку екрана призупинено</translation>
<translation id="59174027418879706">Увімкнено</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{ВикориÑтовуєтьÑÑ 1 файл}one{ВикориÑтовуєтьÑÑ # файл}few{ВикориÑтовуютьÑÑ # файли}many{ВикориÑтовуютьÑÑ # файлів}other{ВикориÑтовуютьÑÑ # файлу}}</translation>
<translation id="5921185718311485855">Увімкнено</translation>
<translation id="5921639886840618607">Зберегти картку в обліковому запиÑÑ– Google?</translation>
<translation id="5922853866070715753">Майже готово</translation>
@@ -1336,6 +1372,7 @@
<translation id="5989320800837274978">Ðе вказано ні фікÑованих прокÑÑ–-Ñерверів, ні URL-Ð°Ð´Ñ€ÐµÑ Ñценарію .pac.</translation>
<translation id="5992691462791905444">Зігнути гармошкою</translation>
<translation id="6000758707621254961">Результатів Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ "<ph name="SEARCH_TEXT" />": <ph name="RESULT_COUNT" /></translation>
+<translation id="6006484371116297560">КлаÑична</translation>
<translation id="6008122969617370890">ПорÑдок від N до 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Перевірте Ñвої паролі</translation>
@@ -1357,6 +1394,7 @@
<translation id="6045164183059402045">Шаблон накладеннÑ</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="6049004884579590341">Щоб вийти з повноекранного режиму, утримуйте клавішу |<ph name="ACCELERATOR" />|,</translation>
<translation id="6049488691372270142">Подача Ñторінки</translation>
<translation id="6051221802930200923">Зараз не можна перейти на Ñторінку <ph name="SITE" />, оÑкільки цей веб-Ñайт викориÑтовує Ð·Ð°ÐºÑ€Ñ–Ð¿Ð»ÐµÐ½Ð½Ñ Ñертифікатів. Помилки мережі й атаки зазвичай тимчаÑові, тому Ñ†Ñ Ñторінка, Ñкоріш за вÑе, запрацює пізніше.</translation>
<translation id="6051898664905071243">КількіÑÑ‚ÑŒ Ñторінок:</translation>
@@ -1373,6 +1411,7 @@
<translation id="610911394827799129">ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð²ÐµÐ±-переглÑду може також зберігатиÑÑ Ñƒ вашому обліковому запиÑÑ– Google на Ñторінці <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /></translation>
<translation id="6116338172782435947">ПереглÑдати текÑти й Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð² буфері обміну</translation>
<translation id="6120179357481664955">Запам'Ñтати ідентифікатор UPI?</translation>
+<translation id="6123290840358279103">ПереглÑнути віртуальну картку</translation>
<translation id="6124432979022149706">Конектори Chrome Enterprise</translation>
<translation id="6146055958333702838">Перевірте вÑÑ– кабелі та перезавантажте вÑÑ– маршрутизатори, модеми чи інші мережеві
приÑтрої, Ñкі ви викориÑтовуєте.</translation>
@@ -1409,6 +1448,7 @@
<translation id="6289939620939689042">Колір Ñторінки</translation>
<translation id="6290238015253830360">Тут відображатимутьÑÑ Ñ€ÐµÐºÐ¾Ð¼ÐµÐ½Ð´Ð¾Ð²Ð°Ð½Ñ– Ñтатті</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">ÐŸÑ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ Google ÐÑиÑтента в Chrome</translation>
<translation id="6305205051461490394">Сторінка <ph name="URL" /> недоÑтупна.</translation>
<translation id="6312113039770857350">Веб-Ñторінка недоÑтупна</translation>
@@ -1434,6 +1474,7 @@
<translation id="6390200185239044127">Зігнути гармошкою поÑередині</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">ÐдмініÑтратор заблокував можливіÑÑ‚ÑŒ вÑтавлÑти Ñюди контент зі Ñторінки <ph name="ORIGIN_NAME" /></translation>
+<translation id="6398765197997659313">Вийти з повноекранного режиму</translation>
<translation id="6401136357288658127">Це правило не підтримуєтьÑÑ. ÐатоміÑÑ‚ÑŒ потрібно заÑтоÑувати правило <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Редагувати закладку</translation>
<translation id="6406765186087300643">C0 (конверт)</translation>
@@ -1446,7 +1487,6 @@
<translation id="6428450836711225518">Підтвердьте номер телефону</translation>
<translation id="6433490469411711332">Змінити контактні дані</translation>
<translation id="6433595998831338502">ХоÑÑ‚ <ph name="HOST_NAME" /> відхилив запит на з’єднаннÑ.</translation>
-<translation id="6434309073475700221">Відхилити</translation>
<translation id="6440503408713884761">ІгноруєтьÑÑ</translation>
<translation id="6443406338865242315">вÑтановлені Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° плагіни;</translation>
<translation id="6446163441502663861">Kahu (конверт)</translation>
@@ -1484,11 +1524,12 @@
<translation id="6596325263575161958">Параметри шифруваннÑ</translation>
<translation id="6604181099783169992">Датчики руху чи Ñвітла</translation>
<translation id="6609880536175561541">Prc7 (конверт)</translation>
-<translation id="6612358246767739896">Захищений вміÑÑ‚</translation>
+<translation id="6612358246767739896">Захищений контент</translation>
<translation id="6615297766614333076">Ðакопичувач 2</translation>
<translation id="6624427990725312378">Контактна інформаціÑ</translation>
<translation id="6626291197371920147">Додати дійÑний номер картки</translation>
<translation id="6628463337424475685">Пошук <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Пошук приÑтроїв USB…</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">ОчиÑтити</translation>
@@ -1504,6 +1545,7 @@
<translation id="6671697161687535275">Видалити пропозицію Ð°Ð²Ñ‚Ð¾Ð·Ð°Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€Ð¼ із Chromium?</translation>
<translation id="6685834062052613830">Вийдіть з облікового запиÑу та завершіть процедуру налаштуваннÑ</translation>
<translation id="6687335167692595844">Запит на розмір шрифту</translation>
+<translation id="6688743156324860098">Оновити…</translation>
<translation id="6689249931105087298">ВідноÑно ÑтиÑÐ½ÐµÐ½Ð½Ñ Ñ‡Ð¾Ñ€Ð½Ð¾Ñ— точки</translation>
<translation id="6689271823431384964">Chrome пропонує вам зберегти картки в обліковому запиÑÑ– Google, оÑкільки ви ввійшли в нього. Це можна змінити в налаштуваннÑÑ…. Ім'Ñ Ð²Ð»Ð°Ñника картки взÑто з вашого облікового запиÑу.</translation>
<translation id="6698381487523150993">Створено:</translation>
@@ -1519,6 +1561,7 @@
<translation id="6744009308914054259">Очікуючи на з’єднаннÑ, можете перейти в папку "ЗавантаженнÑ" й переглÑнути Ñтатті, доÑтупні в режимі офлайн.</translation>
<translation id="6753269504797312559">Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð°</translation>
<translation id="6757797048963528358">Ваш приÑтрій перейшов у режим Ñну.</translation>
+<translation id="6767985426384634228">Оновити адреÑу?</translation>
<translation id="6768213884286397650">Hagaki (лиÑтівка)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Фіолетовий</translation>
@@ -1541,6 +1584,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Веб-переглÑдач Chrome зробив цю Ñторінку проÑтішою Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ. Оригінальна Ñторінка була завантажена через незахищене з'єднаннÑ.</translation>
<translation id="6891596781022320156">Правило не підтримуєтьÑÑ.</translation>
+<translation id="6895143722905299846">Ðомер картки:</translation>
<translation id="6895330447102777224">Дані картки підтверджено</translation>
<translation id="6897140037006041989">Ðгент кориÑтувача</translation>
<translation id="6898699227549475383">ÐžÑ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ (О)</translation>
@@ -1576,10 +1620,10 @@
<translation id="7004583254764674281">ВикориÑтовувати Windows Hello, щоб швидше підтверджувати картки</translation>
<translation id="7006930604109697472">УÑе одно надіÑлати</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð¼Ñ–Ð½Ð¸ розміру</translation>
<translation id="7014741021609395734">Рівень маÑштабуваннÑ</translation>
<translation id="7016992613359344582">Такі ÑÑ‚ÑÐ³Ð½ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶ÑƒÑ‚ÑŒ бути одноразовими чи регулÑрними й неочевидними.</translation>
<translation id="7029809446516969842">Паролі</translation>
+<translation id="7030436163253143341">Сертифікат недійÑний</translation>
<translation id="7031646650991750659">вÑтановлені додатки Google Play.</translation>
<translation id="7050187094878475250">Ви намагалиÑÑ Ð·Ð²â€™ÑзатиÑÑ Ð· доменом <ph name="DOMAIN" />, але Ñервер надав Ñертифікат із задовгим терміном дії.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Зараз не вдаєтьÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ цю картку}one{Зараз не вдаєтьÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ ці картки}few{Зараз не вдаєтьÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ ці картки}many{Зараз не вдаєтьÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ ці картки}other{Зараз не вдаєтьÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ ці картки}}</translation>
@@ -1649,12 +1693,14 @@
<translation id="7300012071106347854">Кобальтовий</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">ВиÑокий</translation>
+<translation id="7305756307268530424">Сповільнити</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Довідка щодо з’єднаннÑ</translation>
<translation id="7323804146520582233">Сховати розділ "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Заміна локального облікового запиÑу на приÑтрої</translation>
<translation id="7333654844024768166">Щойно ви ввели пароль на оманливому Ñайті. Chromium радить негайно перейти на <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> та інші Ñайти, де викориÑтовуєтьÑÑ Ñ†ÐµÐ¹ пароль, Ñ– змінити його.</translation>
<translation id="7334320624316649418">&amp;Повторити перевпорÑдкуваннÑ</translation>
+<translation id="7337248890521463931">Показати більше Ñ€Ñдків</translation>
<translation id="7337706099755338005">ÐедоÑтупний на вашій платформі.</translation>
<translation id="733923710415886693">Сертифікат Ñервера не надав інформацію про перевірку.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1662,6 +1708,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Командний Ñ€Ñдок</translation>
<translation id="7359588939039777303">ÐžÐ³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð¾.</translation>
+<translation id="7363096869660964304">Ðавіть в анонімному режимі ваш роботодавець, поÑтачальник поÑлуг Інтернету чи веб-Ñайти, Ñкі ви відвідуєте, можуть бачити, що ви переглÑдаєте.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />; натиÑніть Tab, а потім – Enter, щоб додати адреÑи й керувати ними в налаштуваннÑÑ… Chrome</translation>
<translation id="7365849542400970216">Інформувати про активний Ñтан приÑтрою?</translation>
<translation id="7372973238305370288">результат пошуку</translation>
@@ -1672,7 +1719,9 @@
<translation id="7378594059915113390">Елементи ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼ÐµÐ´Ñ–Ð°</translation>
<translation id="7378627244592794276">ÐÑ–</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Ðе заÑтоÑовуєтьÑÑ</translation>
<translation id="7390545607259442187">Підтвердити дані картки</translation>
+<translation id="7392089738299859607">Оновіть адреÑу</translation>
<translation id="7399802613464275309">Перевірка безпеки</translation>
<translation id="7400418766976504921">URL-адреÑа</translation>
<translation id="7403591733719184120">ПриÑтроєм <ph name="DEVICE_NAME" /> керує адмініÑтратор</translation>
@@ -1687,6 +1736,7 @@
&lt;li&gt;Відвідайте &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Довідковий центр Chrome&lt;/a&gt;, щоб дізнатиÑÑ, Ñк повніÑÑ‚ÑŽ видалити програмне Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ Ð· комп’ютера
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Широкий формат</translation>
+<translation id="7410471291937727359">Милий</translation>
<translation id="7416351320495623771">Керувати паролÑми…</translation>
<translation id="7419106976560586862">ШлÑÑ… до профілю</translation>
<translation id="7437289804838430631">Додати контактну інформацію</translation>
@@ -1702,7 +1752,7 @@
<translation id="7481312909269577407">ПереÑлати</translation>
<translation id="7485870689360869515">Даних не знайдено.</translation>
<translation id="7495528107193238112">ÐŸÑ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð¾. Щоб вирішити проблему, зв'ÑжітьÑÑ Ð· влаÑником Ñайту.</translation>
-<translation id="7498234416455752244">Продовжити редагуваннÑ</translation>
+<translation id="7498193950643227031">ПіÑÐ»Ñ Ð·Ð¼Ñ–Ð½Ð¸ розмірів робота додатка може бути непередбачуваною. Тепер можна обмежувати можливіÑÑ‚ÑŒ змінювати розміри додатків, відкривши <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Щойно ви ввели пароль на оманливому Ñайті. Chromium радить перевірити збережені паролі Ð´Ð»Ñ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> та інших Ñайтів, де викориÑтовуєтьÑÑ Ñ†ÐµÐ¹ пароль.</translation>
<translation id="7508255263130623398">Отриманий ідентифікатор правил приÑтрою порожній або не збігаєтьÑÑ Ð· поточним ідентифікатором приÑтрою</translation>
<translation id="7508870219247277067">Світло-зелений</translation>
@@ -1722,6 +1772,7 @@
<translation id="7548892272833184391">Як виправити помилки з’єднаннÑ</translation>
<translation id="7549584377607005141">Ð”Ð»Ñ Ð½Ð°Ð»ÐµÐ¶Ð½Ð¾Ð³Ð¾ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ†Ñ–Ð¹ веб-Ñторінці потрібні введені вами раніше дані. Можна ще раз надіÑлати дані, однак зробивши це, ви повторите вÑÑ– дії, Ñкі Ñ†Ñ Ñторінка виконувала раніше.</translation>
<translation id="7550637293666041147">Імена кориÑтувачів Ð´Ð»Ñ Ð¿Ñ€Ð¸Ñтрою та Chrome</translation>
+<translation id="755279583747225797">Пробна верÑÑ–Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð°</translation>
<translation id="7552846755917812628">Виконайте вказівки нижче.</translation>
<translation id="7554475479213504905">Оновити й уÑе одно показати</translation>
<translation id="7554791636758816595">Ðова вкладка</translation>
@@ -1740,7 +1791,6 @@
<translation id="7610193165460212391">Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° межами діапазону <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Діє до: <ph name="EXPIRATION_MONTH" />.<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />; натиÑніть Tab, а потім – Enter, щоб переглÑнути паролі й керувати ними в налаштуваннÑÑ… Chrome</translation>
-<translation id="7615602087246926389">Ви вже зашифрували дані, викориÑтовуючи іншу верÑÑ–ÑŽ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу Google. Введіть його нижче.</translation>
<translation id="7616645509853975347">Ваш адмініÑтратор увімкнув Chrome Enterprise Connectors у веб-переглÑдачі. Ці конектори мають доÑтуп до деÑких ваших даних.</translation>
<translation id="7619838219691048931">ОÑтанній аркуш</translation>
<translation id="762844065391966283">По одному</translation>
@@ -1805,13 +1855,12 @@
<translation id="782886543891417279">Можливо, щоб під’єднатиÑÑ Ð´Ð¾ цієї мережі Wi-Fi (<ph name="WIFI_NAME" />), потрібно відвідати Ñ—Ñ— Ñторінку входу.</translation>
<translation id="7836231406687464395">Postfix (конверт)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Ðемає}=1{1 додаток (<ph name="EXAMPLE_APP_1" />)}=2{2 додатки (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# додаток (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}few{# додатки (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}many{# додатків (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}other{# додатка (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" /> <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Ðавіть у режимі анонімного переглÑду ваш роботодавець, поÑтачальник поÑлуг Інтернету чи веб-Ñайти, Ñкі ви відвідуєте, можуть бачити, що ви переглÑдаєте.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" />: <ph name="FORMATTED_TOTAL_AMOUNT" /> <ph name="CURRENCY_CODE" /></translation>
-<translation id="7858035578849836010">Відкривати файли за допомогою зв'ÑÐ·ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð¸Ð¿Ñ–Ð² файлів.</translation>
<translation id="7862185352068345852">Залишити Ñайт?</translation>
<translation id="7865448901209910068">Оптимальна швидкіÑÑ‚ÑŒ</translation>
<translation id="7874263914261512992">Щойно ви ввели пароль на оманливому Ñайті. Chrome радить перевірити збережені паролі Ð´Ð»Ñ <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> та інших Ñайтів, де викориÑтовуєтьÑÑ Ñ†ÐµÐ¹ пароль.</translation>
<translation id="7878562273885520351">Ваш пароль можуть зламати</translation>
+<translation id="7880146494886811634">Збережіть адреÑу</translation>
<translation id="7882421473871500483">Коричневий</translation>
<translation id="7887683347370398519">Перевірте код CVC й повторіть Ñпробу</translation>
<translation id="7887885240995164102">Увімкнути режим "Картинка в картинці"</translation>
@@ -1819,6 +1868,7 @@
<translation id="7894280532028510793">Якщо помилок немає, <ph name="BEGIN_LINK" />проведіть діагноÑтику мережі<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (конверт)</translation>
<translation id="7931318309563332511">невідомо</translation>
+<translation id="793209273132572360">Оновити адреÑу?</translation>
<translation id="7932579305932748336">Вкрити обкладинкою</translation>
<translation id="79338296614623784">Введіть дійÑний номер телефону</translation>
<translation id="7934052535022478634">Платіж виконано</translation>
@@ -1889,6 +1939,7 @@
<translation id="8175796834047840627">Chrome пропонує вам зберегти картки в обліковому запиÑÑ– Google, оÑкільки ви ввійшли в нього. Це можна змінити в налаштуваннÑÑ….</translation>
<translation id="8176440868214972690">ÐдмініÑтратор приÑтрою надіÑлав указаним веб-Ñайтам деÑку інформацію, таку Ñк Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¹ правила.</translation>
<translation id="8184538546369750125">ВикориÑтовувати глобальне Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° умовчаннÑм (ДозволÑти)</translation>
+<translation id="8193086767630290324">Дії з конфіденційними даними</translation>
<translation id="8194797478851900357">&amp;Відмінити переміщеннÑ</translation>
<translation id="8201077131113104583">ÐедійÑна URL-адреÑа Ð´Ð»Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð· ідентифікатором "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">ПідÑумок замовленнÑ</translation>
@@ -1911,6 +1962,7 @@
<translation id="8249296373107784235">СкаÑувати</translation>
<translation id="8249320324621329438">ВоÑтаннє отримано:</translation>
<translation id="8253091569723639551">Потрібно вказати платіжну адреÑу</translation>
+<translation id="8257387598443225809">Цей додаток Ñтворено Ð´Ð»Ñ Ð¼Ð¾Ð±Ñ–Ð»ÑŒÐ½Ð¸Ñ… приÑтроїв</translation>
<translation id="825929999321470778">Показати вÑÑ– збережені паролі</translation>
<translation id="8261506727792406068">Видалити</translation>
<translation id="8262952874573525464">Зшити вздовж нижнього краю</translation>
@@ -2035,7 +2087,6 @@
<translation id="8719528812645237045">Пробити кілька отворів угорі</translation>
<translation id="8725066075913043281">Повторити Ñпробу</translation>
<translation id="8726549941689275341">Розмір Ñторінки:</translation>
-<translation id="8728672262656704056">Ви перейшли в режим анонімного переглÑду</translation>
<translation id="8730621377337864115">Готово</translation>
<translation id="8731544501227493793">Кнопка "Керувати паролÑми"; натиÑніть Enter, щоб переглÑнути паролі й керувати ними в налаштуваннÑÑ… Chrome</translation>
<translation id="8734529307927223492">Вашим приÑтроєм <ph name="DEVICE_TYPE" /> керує <ph name="MANAGER" /></translation>
@@ -2112,6 +2163,7 @@
<translation id="9020542370529661692">Цю Ñторінку перекладено такою мовою: <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(ÐедійÑний)</translation>
+<translation id="9030265603405983977">Монохромний</translation>
<translation id="9035022520814077154">Помилка ÑиÑтеми безпеки</translation>
<translation id="9038649477754266430">КориÑтуйтеÑÑ Ñлужбою передбаченнÑ, щоб Ñторінки завантажувалиÑÑ ÑˆÐ²Ð¸Ð´ÑˆÐµ</translation>
<translation id="9039213469156557790">Окрім цього, Ñторінка міÑтить незахищені реÑурÑи. Інші оÑоби можуть переглÑдати Ñ—Ñ… під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ´Ð°Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ…, а зловмиÑники можуть змінювати роботу Ñторінки.</translation>
@@ -2135,6 +2187,7 @@
<translation id="91108059142052966">ÐдмініÑтратор заборонив показувати екран за допомогою додатка <ph name="APPLICATION_TITLE" />, коли видно конфіденційний контент</translation>
<translation id="9114524666733003316">ПідтверджуютьÑÑ Ð´Ð°Ð½Ñ– картки…</translation>
<translation id="9114581008513152754">Цим веб-переглÑдачем не керує адмініÑтратор компанії чи іншої організації. ДіÑми на цьому приÑтрої можна керувати за межами Chrome. <ph name="BEGIN_LINK" />Докладніше<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Свіжий</translation>
<translation id="9119042192571987207">Завантажено</translation>
<translation id="9128016270925453879">Правила завантажено</translation>
<translation id="9128870381267983090">З'єднатиÑÑ Ð· мережею</translation>
@@ -2153,6 +2206,7 @@
<translation id="9170848237812810038">&amp;СкаÑувати</translation>
<translation id="9171296965991013597">Закрити додаток?</translation>
<translation id="9173282814238175921">Один документ/новий аркуш</translation>
+<translation id="9173995187295789444">Пошук приÑтроїв Bluetooth…</translation>
<translation id="917450738466192189">Сертифікат Ñервера недійÑний.</translation>
<translation id="9174917557437862841">Кнопка Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð²ÐºÐ»Ð°Ð´ÐºÐ¸: натиÑніть Enter, щоб перейти на цю вкладку</translation>
<translation id="9179703756951298733">Керувати платежами й даними кредитних карток у налаштуваннÑÑ… Chrome</translation>
diff --git a/chromium/components/strings/components_strings_ur.xtb b/chromium/components/strings/components_strings_ur.xtb
index acec7c3e58d..30eee9200a6 100644
--- a/chromium/components/strings/components_strings_ur.xtb
+++ b/chromium/components/strings/components_strings_ur.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">â€Ù†Ø´Ø§Ù† زد کیے جانے پر، Ø²ÛŒØ§Ø¯Û ØªÛŒØ²ÛŒ سے Ùارم بھرنے کیلئے Chrome آپ Ú©Û’ کارڈ Ú©ÛŒ ایک کاپی اس Ø¢Ù„Û Ù¾Ø± اسٹور کرے گا۔</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> کے لیے اجازت منتخب کریں</translation>
<translation id="1113869188872983271">Ø¯ÙˆØ¨Ø§Ø±Û ØªØ±ØªÛŒØ¨ &amp;کالعدم کریں</translation>
+<translation id="1123753900084781868">لائیو کیپشن ابھی دستیاب Ù†Ûیں ÛÛ’</translation>
<translation id="1125573121925420732">ویب سائٹس Ú©ÛŒ جانب سے اپنی سیکیورٹی Ú©Ùˆ اپ ڈیٹ کرنے Ú©Û’ دوران انتباÛات عام ÛÙˆ سکتی Ûیں۔ اسے جلد ÛÛŒ بÛتر ÛÙˆ جانا چاÛئے۔</translation>
<translation id="112840717907525620">پالیسی کیش ٹھیک ÛÛ’</translation>
<translation id="1130564665089811311">â€'صÙØ­Û’ کا ØªØ±Ø¬Ù…Û Ú©Ø±ÛŒÚº' بٹن، Google ترجمے سے اس صÙØ­Û’ کا ØªØ±Ø¬Ù…Û Ú©Ø±Ù†Û’ Ú©Û’ لیے اینٹر دبائیں</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">آپ کے آلے کا نام</translation>
<translation id="124116460088058876">مزید زبانیں</translation>
<translation id="1243027604378859286">مصنÙ:</translation>
+<translation id="1246424317317450637">بولڈ</translation>
<translation id="1250759482327835220">â€Ø§Ú¯Ù„ÛŒ بار Ø²ÛŒØ§Ø¯Û ØªÛŒØ²ÛŒ سے ادائیگی کرنے کیلئے، اپنے کارڈ، نام اور بلنگ Ù¾ØªÛ Ú©Ùˆ اپنے Google اکاؤنٹ میں محÙوظ کریں۔</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />ØŒ <ph name="TYPE_2" /> (مطابقت پذیر کردÛ)</translation>
<translation id="1256368399071562588">â€&lt;p&gt;اگر آپ کوئی ویب سائٹ Ù…Ù„Ø§Ø­Ø¸Û Ú©Ø±Ù†Û’ Ú©ÛŒ کوشش کرتے Ûیں اور ÙˆÛ Ù†Ûیں کھلتی ÛÛ’ØŒ تو Ù¾ÛÙ„Û’ ٹربل شوٹنگ Ú©Û’ ان مراحل Ú©ÛŒ مدد سے خرابی Ú©Ùˆ ٹھیک کرنے Ú©ÛŒ کوشش کریں:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">اپنا پاس ورڈ تبدیل کریں</translation>
<translation id="1484290072879560759">ترسیل کا Ù¾ØªÛ Ù…Ù†ØªØ®Ø¨ کریں</translation>
<translation id="1492194039220927094">پالیسیوں Ú©Ùˆ Ù¾ÙØ´ کرنا:</translation>
+<translation id="1495677929897281669">ٹیب پر واپس جائیں</translation>
<translation id="1501859676467574491">â€Ø§Ù¾Ù†Û’ Google اکاؤنٹ سے کارڈز دکھائیں</translation>
<translation id="1507202001669085618">â€&lt;p&gt;اگر آپ کسی ایسے Wi-Fi پورٹل کا استعمال کر رÛÛ’ Ûیں، جس میں آپ Ú©Ùˆ آن لائن جانے سے Ù¾ÛÙ„Û’ سائن ان کرنا پڑتا ÛÛ’ØŒ تو آپ Ú©Ùˆ ÛŒÛ Ø®Ø±Ø§Ø¨ÛŒ دکھائی دے گی۔&lt;/p&gt;
&lt;p&gt;خرابی ٹھیک کرنے کیلئے، اس صÙØ­Û’ پر &lt;strong&gt;منسلک کریں&lt;/strong&gt; پر Ú©Ù„Ú© کریں جسے آپ کھولنے Ú©ÛŒ کوشش کر رÛÛ’ Ûیں۔&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">اس صÙØ­Û’ Ú©Û’ مطابق</translation>
<translation id="153384715582417236">ابھی کیلئے بس اتنا ÛÛŒ</translation>
<translation id="1536390784834419204">صÙØ­Û Ú©Ø§ ØªØ±Ø¬Ù…Û Ú©Ø±ÛŒÚº</translation>
+<translation id="1539840569003678498">رپورٹ بھیج دی گئی:</translation>
<translation id="154408704832528245">ڈیلیوری کا Ù¾ØªÛ Ù…Ù†ØªØ®Ø¨ کریں</translation>
<translation id="1549470594296187301">â€Ø§Ø³ خصوصیت کا استعمال کرنے کیلئے JavaScript کا Ùعال Ûونا لازمی ÛÛ’Û”</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -214,16 +218,19 @@
<translation id="1682696192498422849">چھوٹا Ú©Ù†Ø§Ø±Û Ù¾ÛÙ„Û’</translation>
<translation id="168693727862418163">اس پالیسی Ú©ÛŒ قدر اس Ú©Û’ سکیما Ú©Ùˆ توثیق کرنے میں ناکام ÛÙˆ گئی اور اسے نظر انداز کر دیا جائے گا۔</translation>
<translation id="168841957122794586">سرور سرٹیÙکیٹ میں ایک ÛÙتے Ú©ÛŒ کرپٹوگراÙÚ© کلید شامل ÛÛ’Û”</translation>
+<translation id="1696290444144917273">ورچوئل کارڈ Ú©ÛŒ تÙصیلات دیکھیں</translation>
<translation id="1697532407822776718">آپ بالکل ٹھیک Ûیں!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{ÛŒÛ Ø³Ø±ÙˆØ± ثابت Ù†Ûیں کر سکا Ú©Û ÛŒÛ <ph name="DOMAIN" /> ÛÛ’Ø› اس Ú©Û’ سیکیورٹی سرٹیÙکیٹ Ú©ÛŒ میعاد Ù…Ù…Ú©Ù†Û Ø·ÙˆØ± پر Ú©Ù„ سے ÛÛ’Û” ÛŒÛ ØºÙ„Ø· Ú©Ù†Ùیگریشن یا آپ Ú©Û’ کنکشن Ú©Ùˆ قطع کرنے والے کسی Ø­Ù…Ù„Û Ø¢ÙˆØ± Ú©ÛŒ ÙˆØ¬Û Ø³Û’ ÛÙˆ سکتا ÛÛ’Û”}other{ÛŒÛ Ø³Ø±ÙˆØ± ثابت Ù†Ûیں کر سکا Ú©Û ÛŒÛ <ph name="DOMAIN" /> ÛÛ’Ø› اس Ú©Û’ سیکیورٹی سرٹیÙکیٹ Ú©ÛŒ میعاد Ù…Ù…Ú©Ù†Û Ø·ÙˆØ± پر مستقبل میں # دن بعد سے ÛÛ’Û” ÛŒÛ ØºÙ„Ø· Ú©Ù†Ùیگریشن یا آپ Ú©Û’ کنکشن Ú©Ùˆ قطع کرنے والے کسی Ø­Ù…Ù„Û Ø¢ÙˆØ± Ú©ÛŒ ÙˆØ¬Û Ø³Û’ ÛÙˆ سکتا ÛÛ’Û”}}</translation>
<translation id="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">نظر انداز کیا گیا Ú©ÛŒÙˆÙ†Ú©Û <ph name="POLICY_NAME" /> <ph name="VALUE" /> پر سیٹ Ù†Ûیں ÛÛ’Û”</translation>
<translation id="1712552549805331520"><ph name="URL" /> آپ Ú©Û’ مقامی کمپیوٹر پر مستقل طور پر ڈیٹا اسٹور کرنا چاÛتا ÛÛ’</translation>
<translation id="1713628304598226412">ٹرے 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">میل باکس 3</translation>
<translation id="1718029547804390981">دستاویز اتنی بڑی ÛÛ’ Ú©Û Ø§Ø³ Ú©ÛŒ تشریح Ù†Ûیں Ú©ÛŒ جا سکتی</translation>
<translation id="1721424275792716183">* Ùیلڈ لازمی ÛÛ’</translation>
+<translation id="1727613060316725209">سرٹیÙیکیٹ درست ÛÛ’</translation>
<translation id="1727741090716970331">درست کارڈ نمبر شامل کریں</translation>
<translation id="1728677426644403582">آپ ویب صÙØ­Û Ú©Ø§ ماخذ دیکھ رÛÛ’ Ûیں</translation>
<translation id="173080396488393970">اس قسم کا کارڈ تعاون یاÙØªÛ Ù†Ûیں ÛÛ’</translation>
@@ -247,7 +254,6 @@
آپ Ú©ÛŒ درخواست Ú©Ùˆ پورا کرنے سے روکتا ÛÛ’Û” کسی سائٹ Ú©ÛŒ خاطر سیکیورٹی اور دیگر پراپرٹیز Ú©Ùˆ ترتیب دینے Ú©Û’ لیے
سائٹ آپریٹرز Ú©Û’ ذریعے ماخذ پالیسیوں کا استعمال کیا جا سکتا ÛÛ’Û”</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Ø¨Ø±Ø§Û Ú©Ø±Ù… اپنا مطابقت پذیری پاس Ùریز اپ ڈیٹ کریں۔</translation>
<translation id="1787142507584202372">آپ Ú©Û’ Ú©Ú¾Ù„Û’ ٹیبز ÛŒÛاں ظاÛر Ûوتے Ûیں</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742">â€<ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ متعدد کارروائیاں دستیاب Ûیں، Ûر ایک پر جانے کیلئے Tab دبائیں</translation>
@@ -280,6 +286,7 @@
<translation id="1919345977826869612">اشتÛارات</translation>
<translation id="1919367280705858090">خرابی کے کسی مخصوص پیغام کے بارے میں مدد حاصل کریں</translation>
<translation id="192020519938775529">{COUNT,plural, =0{کوئی سائٹ Ù†Ûیں}=1{1 سائٹ}other{# سائٹس}}</translation>
+<translation id="1924727005275031552">نئی</translation>
<translation id="1945968466830820669">â€Ø¢Ù¾ اپنی تنظیم Ú©Û’ اکاؤنٹ تک رسائی سے محروم ÛÙˆ سکتے Ûیں یا شناخت Ú©ÛŒ چوری ÛÙˆ سکتی ÛÛ’Û” Chromium آپ Ú©Ùˆ ابھی اپنا پاس ورڈ تبدیل کرنے Ú©ÛŒ تجویز کرتا ÛÛ’Û”</translation>
<translation id="1947454675006758438">اوپر دائیں طر٠سٹیپل</translation>
<translation id="1958218078413065209">آپ کا اعلی ترین اسکور <ph name="SCORE" /> ÛÛ’Û”</translation>
@@ -302,12 +309,14 @@
<translation id="2042213636306070719">ٹرے 7</translation>
<translation id="204357726431741734">â€Ø§Ù¾Ù†Û’ Google اکاؤنٹ میں محÙوظ Ú©Ø±Ø¯Û Ù¾Ø§Ø³ ورڈز کا استعمال کرنے Ú©Û’ لئے سائن ان کریں</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> Ú©Û’ صÙحات کا ØªØ±Ø¬Ù…Û Ù†Ûیں کیا جائے گا۔</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{â€Ø§Ø³ کنٹرول Ú©Û’ آن Ûونے اور اسٹیٹس Ú©Û’ Ùعال Ûونے پر، Chrome اس بات کا تعین کرتا ÛÛ’ Ú©Û Ù„ÙˆÚ¯ÙˆÚº Ú©Û’ کون سے بڑے گروپ یا "مشترک خصوصیات Ú©Û’ حامل لوگوں Ú©Û’ گروپ" سے آپ Ú©ÛŒ Ø­Ø§Ù„ÛŒÛ Ø¨Ø±Ø§Ø¤Ø²Ù†Ú¯ Ú©ÛŒ سرگرمی سب سے Ø²ÛŒØ§Ø¯Û Ù…Ù„ØªÛŒ جلتی ÛÛ’Û” مشتÛرین گروپ Ú©Û’ لیے اشتÛارات کا انتخاب کر سکتے Ûیں اور آپ Ú©ÛŒ براؤزنگ Ú©ÛŒ سرگرمی Ú©Ùˆ آپ Ú©Û’ آلے پر نجی رکھا جاتا ÛÛ’Û” آپ کا گروپ Ûر روز اپ ڈیٹ کیا جاتا ÛÛ’Û”}=1{â€Ø§Ø³ کنٹرول Ú©Û’ آن Ûونے اور اسٹیٹس Ú©Û’ Ùعال Ûونے پر، Chrome اس بات کا تعین کرتا ÛÛ’ Ú©Û Ù„ÙˆÚ¯ÙˆÚº Ú©Û’ کون سے بڑے گروپ یا "مشترک خصوصیات Ú©Û’ حامل لوگوں Ú©Û’ گروپ" سے آپ Ú©ÛŒ Ø­Ø§Ù„ÛŒÛ Ø¨Ø±Ø§Ø¤Ø²Ù†Ú¯ Ú©ÛŒ سرگرمی سب سے Ø²ÛŒØ§Ø¯Û Ù…Ù„ØªÛŒ جلتی ÛÛ’Û” مشتÛرین گروپ Ú©Û’ لیے اشتÛارات کا انتخاب کر سکتے Ûیں اور آپ Ú©ÛŒ براؤزنگ Ú©ÛŒ سرگرمی Ú©Ùˆ آپ Ú©Û’ آلے پر نجی رکھا جاتا ÛÛ’Û” آپ کا گروپ Ûر روز اپ ڈیٹ کیا جاتا ÛÛ’Û”}other{â€Ø§Ø³ کنٹرول Ú©Û’ آن Ûونے اور اسٹیٹس Ú©Û’ Ùعال Ûونے پر، Chrome اس بات کا تعین کرتا ÛÛ’ Ú©Û Ù„ÙˆÚ¯ÙˆÚº Ú©Û’ کون سے بڑے گروپ یا "مشترک خصوصیات Ú©Û’ حامل لوگوں Ú©Û’ گروپ" سے آپ Ú©ÛŒ Ø­Ø§Ù„ÛŒÛ Ø¨Ø±Ø§Ø¤Ø²Ù†Ú¯ Ú©ÛŒ سرگرمی سب سے Ø²ÛŒØ§Ø¯Û Ù…Ù„ØªÛŒ جلتی ÛÛ’Û” مشتÛرین گروپ Ú©Û’ لیے اشتÛارات کا انتخاب کر سکتے Ûیں اور آپ Ú©ÛŒ براؤزنگ Ú©ÛŒ سرگرمی Ú©Ùˆ آپ Ú©Û’ آلے پر نجی رکھا جاتا ÛÛ’Û” آپ کا گروپ Ûر {NUM_DAYS} دن میں اپ ڈیٹ کیا جاتا ÛÛ’Û”}}</translation>
<translation id="2053553514270667976">زپ کوڈ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 تجویز}other{# تجاویز}}</translation>
<translation id="2071692954027939183">اطلاعات Ú©Ùˆ خودکار طور پر مسدود کر دیا گیا Ú©ÛŒÙˆÙ†Ú©Û Ø¢Ù¾ عموماً انÛیں اجازت Ù†Ûیں دیتے Ûیں</translation>
<translation id="2079545284768500474">کالعدم کریں</translation>
<translation id="20817612488360358">سسٹم پراکسی Ú©ÛŒ ترتیبات استعمال کیے جانے کیلئے سیٹ Ûیں لیکن ایک واضح پراکسی Ú©Ù†Ùیگریشن بھی متعین Ú©ÛŒ گئی ÛÛ’Û”</translation>
<translation id="2082238445998314030">Ù†ØªÛŒØ¬Û <ph name="RESULT_NUMBER" /> از <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">محÙوظ کریں…</translation>
<translation id="2088086323192747268">â€Ù…طابقت پذیری Ú©Û’ بٹن کا نظم کریں، آپ Chrome ترتیبات میں Ú©Ù† معلومات Ú©Ùˆ مطابقت پذیر بناتے Ûیں ان کا نظم کرنے Ú©Û’ لئے اینٹر دبائیں</translation>
<translation id="2091887806945687916">آواز</translation>
<translation id="2094505752054353250">ڈومین کی عدم مماثلت</translation>
@@ -380,6 +389,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> Ú©Ùˆ ایک صار٠نام اور پاس ورڈ درکار ÛÛ’Û”</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" /> Ú©ÛŒ میعاد <ph name="EXPIRATION_DATE_ABBR" /> Ú©Ùˆ ختم ÛÙˆ جائے Ú¯ÛŒ</translation>
<translation id="2337852623177822836">ترتیب آپ Ú©Û’ منتظم Ú©ÛŒ جانب سے کنٹرول Ú©ÛŒ جاتی ÛÛ’</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> جوڑا بنانا چاÛتی ÛÛ’</translation>
<translation id="2344028582131185878">â€Ø®ÙˆØ¯ کار ڈا‎ؤن لوڈز</translation>
<translation id="2346319942568447007">آپ Ú©ÛŒ کاپی Ú©Ø±Ø¯Û ØªØµÙˆÛŒØ±</translation>
<translation id="2354001756790975382">دیگر بÙÚ© مارکس</translation>
@@ -387,8 +397,10 @@
<translation id="2355395290879513365">Ø­Ù…Ù„Û Ø¢ÙˆØ± ان تصاویر Ú©Ùˆ دیکھ سکتے Ûیں جنÛیں آپ اس سائٹ پر دیکھ رÛÛ’ Ûیں اور ان میں ترمیم کر Ú©Û’ آپ Ú©Ùˆ Ø¯Ú¾ÙˆÚ©Û Ø¯Û’ سکتے Ûیں۔</translation>
<translation id="2356070529366658676">پوچھیں</translation>
<translation id="2357481397660644965">آپ کا Ø¢Ù„Û <ph name="DEVICE_MANAGER" /> Ú©Û’ زیر انتظام ÛÛ’ اور آپ کا اکاؤنٹ <ph name="ACCOUNT_MANAGER" /> Ú©Û’ زیر انتظام ÛÛ’Û”</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ایک دن سے کم وقت میں}=1{ایک دن میں}other{{NUM_DAYS} دنوں میں}}</translation>
<translation id="2359629602545592467">متعدد</translation>
<translation id="2359808026110333948">جاری رکھیں</translation>
+<translation id="2359961752320758691">آپ کا ورچوئل کارڈ نمبر لاگو ÛÛ’Û”</translation>
<translation id="2367567093518048410">سطح</translation>
<translation id="2372464001869762664">â€Ø¢Ù¾ Ú©Û’ توثیق کرنے Ú©Û’ بعد آپ Ú©Û’ Google اکاؤنٹ سے کارڈ Ú©ÛŒ تÙصیلات کا اشتراک اس سائٹ Ú©Û’ ساتھ کر دیا جائے گا۔ اپنے Plex اکاؤنٹ Ú©ÛŒ تÙصیلات میں CVC تلاش کریں۔</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -399,6 +411,7 @@
<translation id="239429038616798445">ترسیل کا ÛŒÛ Ø·Ø±ÛŒÙ‚Û Ø¯Ø³ØªÛŒØ§Ø¨ Ù†Ûیں ÛÛ’Û” کوئی دوسرا Ø·Ø±ÛŒÙ‚Û Ø¢Ø²Ù…Ø§Ø¦ÛŒÚºÛ”</translation>
<translation id="2396249848217231973">Ø­Ø°Ù Ú©Ø±Ø¯Û Ú©Ùˆ &amp;کالعدم کریں</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">پرانا</translation>
<translation id="2413528052993050574">ÛŒÛ Ø³Ø±ÙˆØ± ÛŒÛ Ø«Ø§Ø¨Øª Ù†Ûیں کر سکا Ú©Û ÛŒÛ <ph name="DOMAIN" /> ÛÛ’Ø› ممکن ÛÛ’ Ú©Û Ø§Ø³ کا سیکیورٹی سرٹیÙکیٹ کالعدم قرار دے دیا گیا ÛÙˆÛ” ÛŒÛ ØºÙ„Ø· Ú©Ù†Ùیگریشن یا آپ Ú©Û’ کنکشن Ú©Ùˆ قطع کرنے والے کسی Ø­Ù…Ù„Û Ø¢ÙˆØ± Ú©ÛŒ ÙˆØ¬Û Ø³Û’ ÛÙˆ سکتا ÛÛ’Û”</translation>
<translation id="2414886740292270097">Ú¯Ûری</translation>
<translation id="2438874542388153331">دائیں طر٠مستطیل سوراخ</translation>
@@ -426,10 +439,10 @@
<translation id="2521385132275182522">نیچے بائیں طر٠سٹیپل</translation>
<translation id="2523886232349826891">صر٠اس Ø¢Ù„Û Ù¾Ø± محÙوظ ÛÛ’</translation>
<translation id="2524461107774643265">مزید معلومات شامل کریں</translation>
-<translation id="2526590354069164005">ڈیسک ٹاپ</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{اور 1 مزید}other{اور # مزید}}</translation>
<translation id="2536110899380797252">Ù¾ØªÛ Ø´Ø§Ù…Ù„ کریں</translation>
<translation id="2539524384386349900">پتا لگائیں</translation>
+<translation id="2541219929084442027">صÙحات جنÛیں آپ پوشیدگی ٹیبز میں دیکھتے Ûیں ÙˆÛ Ø¢Ù¾ Ú©Û’ براؤزر Ú©ÛŒ سرگزشت، Ú©ÙˆÚ©ÛŒ اسٹور یا تلاش Ú©ÛŒ سرگزشت میں آپ Ú©ÛŒ جانب سے آپ Ú©Û’ سبھی پوشیدگی ٹیبز بند کر دیے جانے Ú©Û’ بعد موجود Ù†Ûیں رÛیں Ú¯Û’Û” کوئی Ùائل جو آپ ڈاؤن لوڈ کرتے Ûیں یا بÙÚ© مارکس جو آپ بناتے Ûیں ÙˆÛ Ø¨Ø§Ù‚ÛŒ رÛیں Ú¯Û’Û”</translation>
<translation id="2544644783021658368">واحد دستاویز</translation>
<translation id="254947805923345898">پالیسی Ú©ÛŒ قدر درست Ù†Ûیں ÛÛ’Û”</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> نے ایک غلط جواب بھیجا۔</translation>
@@ -449,6 +462,7 @@
<translation id="2629325967560697240">â€Chrome Ú©ÛŒ اعلی ترین سیکیورٹی حاصل کرنے Ú©Û’ لیے <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />بÛتر Ú©Ø±Ø¯Û Ø­Ùاظت Ú©Ùˆ آن کریں<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">â€<ph name="HOST_NAME" /> Ú©Û’ سرور کا IP Ù¾ØªÛ Ù†Ûیں مل سکا۔</translation>
<translation id="2639739919103226564">صورتحال:</translation>
+<translation id="264810637653812429">کوئی مطابقت پذیر Ø¢Ù„Û Ù†Ûیں ملا۔</translation>
<translation id="2649204054376361687"><ph name="CITY" />، <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861">â€<ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ Chrome ترتیبات میں اپنے براؤزنگ Ú©ÛŒ سرگزشت، کوکیز، کیش اور بÛت Ú©Ú†Ú¾ Ú©Ùˆ صا٠کرنے Ú©Û’ لیے ٹیب، پھر اینٹر دبائیں</translation>
<translation id="2650446666397867134">Ùائل تک رسائی مسترد کر دی گئی</translation>
@@ -496,6 +510,7 @@
<translation id="2799223571221894425">Ø¯ÙˆØ¨Ø§Ø±Û Ø´Ø±ÙˆØ¹ کریں</translation>
<translation id="2803306138276472711">â€Google سی٠براؤزنگ Ú©Ùˆ حال ÛÛŒ میں <ph name="SITE" /> پر <ph name="BEGIN_LINK" />میلویئر کا Ù¾ØªÛ Ú†Ù„Ø§<ph name="END_LINK" />Û” جو ویب سائٹس عام طور پر محÙوظ Ûوتی Ûیں ÙˆÛ Ú©Ø¨Ú¾ÛŒ کبھی میلویئر سے متاثر ÛÙˆ جاتی Ûیں۔</translation>
<translation id="2807052079800581569">â€ØªØµÙˆÛŒØ± Ú©ÛŒ Y پوزیشن</translation>
+<translation id="2820957248982571256">اسکین ÛÙˆ رÛا Ûے…</translation>
<translation id="2824775600643448204">Ù¾ØªÛ Ø§ÙˆØ± تلاش بار</translation>
<translation id="2826760142808435982">کنکشن Ú©Ùˆ <ph name="CIPHER" /> کا استعمال کر Ú©Û’ مرموز کیا گیا ÛÛ’ اور اس Ú©ÛŒ توثیق Ú©ÛŒ گئی ÛÛ’ اور ÛŒÛ Ú©Ù„ÛŒØ¯ Ú©Û’ ØªØ¨Ø§Ø¯Ù„Û Ú©Û’ Ø·Ø±ÛŒÙ‚Û Ú©Ø§Ø± Ú©Û’ بطور <ph name="KX" /> کا استعمال کرتا ÛÛ’Û”</translation>
<translation id="2835170189407361413">Ùارم صا٠کریں</translation>
@@ -503,6 +518,8 @@
<translation id="2850739647070081192">Invite ‎(Envelope‎)‎</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="2859806420264540918">ÛŒÛ Ø³Ø§Ø¦Ù¹ دخل انداز یا Ú¯Ù…Ø±Ø§Û Ú©Ù† اشتÛارات دکھاتی ÛÛ’Û”</translation>
+<translation id="287596039013813457">دوستانÛ</translation>
+<translation id="2876489322757410363">کسی خارجی ایپلیکیشن Ú©Û’ ذریعے ادائیگی کرنے Ú©Û’ لیے پوشیدگی وضع Ú©Ùˆ Ú†Ú¾ÙˆÚ‘ رÛÛ’ Ûیں۔ جاری رکھیں؟</translation>
<translation id="2878197950673342043">پوسٹر جیسے Ùولڈ</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">ونڈو کا مقام</translation>
@@ -552,7 +569,6 @@
<translation id="3060227939791841287">C9 ‎(Envelope‎)‎</translation>
<translation id="3060557858482803256">â€<ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ Chrome Ú©ÛŒ ترتیبات میں موجود سیÙÙ¹ÛŒ چیک چلانے Ú©Û’ لئے ٹیب پھر اینٹر دبائیں</translation>
<translation id="3061707000357573562">پیچ سروس</translation>
-<translation id="3064966200440839136">کسی خارجی ایپلیکیشن Ú©Û’ ذریعے ادائیگی کرنے کیلئے پوشیدگی وضع Ú©Ùˆ Ú†Ú¾ÙˆÚ‘ رÛÛ’ Ûیں۔ جاری رکھیں؟</translation>
<translation id="306573536155379004">گیم شروع ÛÙˆ گئی۔</translation>
<translation id="3080254622891793721">گراÙÚ©</translation>
<translation id="3086579638707268289">ویب پر Ú©ÛŒ جانے والی آپ Ú©ÛŒ سرگرمی Ú©Ùˆ مانیٹر کیا جا رÛا ÛÛ’</translation>
@@ -575,7 +591,6 @@
<translation id="315504272643575312">آپ کا اکاؤنٹ <ph name="MANAGER" /> Ú©Û’ زیر انتظام ÛÛ’Û”</translation>
<translation id="3157931365184549694">بحال کریں</translation>
<translation id="3162559335345991374">â€Ø¢Ù¾ جو Wi-Fi استعمال کر رÛÛ’ Ûیں ÙˆÛ Ø¢Ù¾ سے اپنا لاگ ان صÙØ­Û Ù…Ù„Ø§Ø­Ø¸Û Ú©Ø±Ù†Û’ کا ØªÙ‚Ø§Ø¶Û Ú©Ø± سکتا ÛÛ’Û”</translation>
-<translation id="3167968892399408617">جو صÙحات آپ پوشیدگی ٹیبز میں دیکھتے Ûیں ÙˆÛ Ø¢Ù¾ Ú©ÛŒ جانب سے آپ Ú©Û’ سبھی پوشیدگی ٹیبز بند کر دیے جانے Ú©Û’ بعد آپ Ú©Û’ براؤزر Ú©ÛŒ سرگزشت، Ú©ÙˆÚ©ÛŒ اسٹور یا تلاش Ú©ÛŒ سرگزشت میں موجود Ù†Ûیں رÛیں Ú¯Û’Û” آپ جو کوئی Ùائلیں ڈاؤن لوڈ کرتے یا بÙÚ© مارکس بناتے Ûیں ÙˆÛ Ø¨Ø§Ù‚ÛŒ رÛیں Ú¯Û’Û”</translation>
<translation id="3169472444629675720">دریاÙت کریں</translation>
<translation id="3174168572213147020">جزیرÛ</translation>
<translation id="3176929007561373547">اپنی پراکسی کی ترتیبات چیک کریں یا اپنے
@@ -602,10 +617,12 @@
<translation id="3229041911291329567">آپ کے آلے اور براؤزر کے بارے میں ورژن کی معلومات</translation>
<translation id="323107829343500871">â€<ph name="CREDIT_CARD" /> کا CVC درج کریں</translation>
<translation id="3234666976984236645">اس سائٹ پر اÛÙ… مواد کا ÛÙ…ÛŒØ´Û Ù¾ØªØ§ لگائیں</translation>
+<translation id="3249845759089040423">دلکش</translation>
<translation id="3252266817569339921">Ùرانسيسی</translation>
<translation id="3266793032086590337">قدر (متضاد)</translation>
<translation id="3268451620468152448">کھلے ٹیبز</translation>
<translation id="3270847123878663523">Ø¯ÙˆØ¨Ø§Ø±Û ØªØ±ØªÛŒØ¨ &amp;کالعدم کریں</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> منسلک Ûونا چاÛتی ÛÛ’</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">آپ Ú©ÛŒ تنظیم، <ph name="ENROLLMENT_DOMAIN" />ØŒ Ù†Û’ Ú©Ú†Ú¾ معلومات، جیسے ترتیبات یا پالیسیاں درج ذیل ویب سائٹس پر بھیجی Ûیں۔</translation>
<translation id="3282497668470633863">کارڈ پر نام شامل کریں</translation>
@@ -658,6 +675,7 @@
<translation id="3428151540071562330">â€Ø§ÛŒÚ© یا ایک سے Ø²ÛŒØ§Ø¯Û DnsOverHttpsTemplates سرور تمثیل URIs غلط Ûیں اور استعمال Ù†Ûیں کیے جائیں Ú¯Û’Û”</translation>
<translation id="3431636764301398940">اس کارڈ Ú©Ùˆ اس Ø¢Ù„Û Ù…ÛŒÚº محÙوظ کریں</translation>
<translation id="3432601291244612633">صÙØ­Û Ø¨Ù†Ø¯ کریں</translation>
+<translation id="3435738964857648380">سیکیورٹی</translation>
<translation id="3435896845095436175">Ùعال کریں</translation>
<translation id="3438829137925142401">â€Ø§Ù¾Ù†Û’ Google اکاؤنٹ میں محÙوظ Ú©Ø±Ø¯Û Ù¾Ø§Ø³ ورڈ کا استعمال کریں</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -700,7 +718,10 @@
<translation id="3584299510153766161">نیچے دÙÛرا سوراخ</translation>
<translation id="3586931643579894722">تÙصیلات چھپائیں</translation>
<translation id="3587738293690942763">وسطی</translation>
+<translation id="3590643883886679995">آپ Ú©Û’ پوشیدگی وضع سے باÛر نکلنے Ú©Û’ بعد، سائن ان ڈیٹا اس آلے پر اسٹور کیا جائے گا۔</translation>
+<translation id="359126217934908072">ماÛ/سال:</translation>
<translation id="3592413004129370115">Italian ‎(Envelope‎)‎</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{آپ کسی بھی وقت اپنے گروپ Ú©Ùˆ ری سیٹ کر سکتے Ûیں۔ ایک نئے گروپ میں شامل Ûونے Ú©Û’ لیے ایک دن لگتا ÛÛ’Û”}=1{آپ کسی بھی وقت اپنے گروپ Ú©Ùˆ ری سیٹ کر سکتے Ûیں۔ ایک نئے گروپ میں شامل Ûونے Ú©Û’ لیے ایک دن لگتا ÛÛ’Û”}other{آپ کسی بھی وقت اپنے گروپ Ú©Ùˆ ری سیٹ کر سکتے Ûیں۔ ایک نئے گروپ میں شامل Ûونے Ú©Û’ لیے {NUM_DAYS} دن لگتے Ûیں۔}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />، <ph name="DOMAIN" />، <ph name="TIME" /></translation>
<translation id="3603507503523709">ایپلیکیشن کو آپ کے منتظم کے ذریعے مسدود کیا گیا</translation>
<translation id="3608932978122581043">سمت بندی Ùیڈ کریں</translation>
@@ -709,13 +730,13 @@
<translation id="3615877443314183785">ایک درست تاریخ اختتام درج کریں</translation>
<translation id="36224234498066874">براؤزنگ ڈیٹا صا٠کریں…</translation>
<translation id="362276910939193118">پوری سرگزشت دکھائیں</translation>
-<translation id="3625635938337243871">آپ Ú©Û’ پوشیدگی وضع سے باÛر نکلنے Ú©Û’ بعد، سائن ان ڈیٹا اس آلے پر اسٹور کیا جائے گا۔</translation>
<translation id="3630155396527302611">اگر ÛŒÛ Ù¾ÛÙ„Û’ سے ÛÛŒ نیٹ ورک تک رسائی کیلئے اجازت یاÙØªÛ Ù¾Ø±ÙˆÚ¯Ø±Ø§Ù… Ú©Û’ بطور مندرج
ÛÛ’ تو اسے ÙÛرست سے Ûٹانے اور Ø¯ÙˆØ¨Ø§Ø±Û Ø´Ø§Ù…Ù„ کرنے Ú©ÛŒ کوشش کریں۔</translation>
<translation id="3630699740441428070">اس Ø¢Ù„Û Ú©Û’ منتظمین Ù†Û’ آپ Ú©Û’ نیٹ ورک کنکشن Ú©Ùˆ ترتیب دیا ÛÛ’ØŒ جس Ú©ÛŒ مدد سے ÙˆÛ Ø¢Ù¾ Ú©ÛŒ Ù…Ù„Ø§Ø­Ø¸Û Ú©Ø±Ø¯Û ÙˆÛŒØ¨ سائٹس سمیت آپ Ú©ÛŒ نیٹ ورک ٹریÙÚ© دیکھ سکتے Ûیں۔</translation>
<translation id="3631244953324577188">بایو میٹرکس</translation>
<translation id="3633738897356909127">â€Chrome اپ ڈیٹ کریں بٹن، اپنی Chrome Ú©ÛŒ ترتیبات سے Chrome اپ ڈیٹ کرنے Ú©Û’ لیے اینٹر دبائیں</translation>
<translation id="3634530185120165534">ٹرے 5</translation>
+<translation id="3637662659967048211">â€Google اکاؤنٹ میں محÙوظ کریں</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">ایپلیکیشن:</translation>
<translation id="3650584904733503804">توثیق کامیاب رÛÛŒ</translation>
@@ -756,6 +777,7 @@
<translation id="3781428340399460090">Ú¯Ûرا گلابی</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">بلوٹوتھ آلات</translation>
+<translation id="3787675388804467730">ورچوئل کارڈ نمبر</translation>
<translation id="3787705759683870569"><ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /> Ú©Ùˆ میعاد ختم ÛÙˆ رÛÛŒ ÛÛ’</translation>
<translation id="3789155188480882154">سائز 16</translation>
<translation id="3789841737615482174">انسٹال کریں</translation>
@@ -775,6 +797,7 @@
<translation id="3841184659773414994">Ùائل Ûینڈلرز</translation>
<translation id="385051799172605136">پیچھے</translation>
<translation id="3858027520442213535">تاریخ اور وقت اپ ڈیٹ کریں</translation>
+<translation id="3881478300875776315">قدرے کم لائنز دکھائیں</translation>
<translation id="3884278016824448484">متنازع Ø¢Ù„Û Ø´Ù†Ø§Ø®Øª کنندÛ</translation>
<translation id="3885155851504623709">پیرش</translation>
<translation id="388632593194507180">مانیٹر کرنے کا Ù¾ØªÛ Ú†Ù„Ø§</translation>
@@ -800,6 +823,7 @@
<translation id="397105322502079400">حساب لگایا جا رÛا Ûے…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> مسدود ÛÛ’</translation>
<translation id="3973357910713125165">â€Chrome کا سیÙÙ¹ÛŒ چیک بٹن چلائیں، Chrome Ú©ÛŒ ترتیبات میں موجود سیÙÙ¹ÛŒ چیک چلانے Ú©Û’ لئے اینٹر دبائیں</translation>
+<translation id="3986705137476756801">ابھی کیلئے لائیو کیپشن آ٠کریں</translation>
<translation id="3987405730340719549">â€Chrome اس نتیجے پر Ù¾Ûنچا ÛÛ’ Ú©Û ÛŒÛ Ø³Ø§Ø¦Ù¹ جعلی یا Ù¾Ùر Ùریب ÛÙˆ سکتی ÛÛ’Û”
اگر آپ Ú©Ùˆ لگتا ÛÛ’ Ú©Û ÛŒÛ ØºÙ„Ø·ÛŒ سے دکھایا جا رÛا ÛÛ’ تو https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals Ù…Ù„Ø§Ø­Ø¸Û Ú©Ø±ÛŒÚºÛ”</translation>
@@ -896,13 +920,14 @@
<translation id="4275830172053184480">اپنا Ø¢Ù„Û Ø¯ÙˆØ¨Ø§Ø±Û Ø´Ø±ÙˆØ¹ کریں</translation>
<translation id="4277028893293644418">پاس ورڈ ری سیٹ کریں</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{â€Ø§Ø³ کارڈ Ú©Ùˆ آپ Ú©Û’ Google اکاؤنٹ میں محÙوظ کر دیا گیا ÛÛ’}other{â€Ø§Ù† کارڈز Ú©Ùˆ آپ Ú©Û’ Google اکاؤنٹ میں محÙوظ کر دیا گیا ÛÛ’}}</translation>
+<translation id="4287885627794386150">ٹرائل کا اÛÙ„ ÛÛ’ لیکن Ùعال Ù†Ûیں ÛÛ’</translation>
<translation id="4297502707443874121"><ph name="THUMBNAIL_PAGE" /> صÙØ­Û Ú©Ø§ تھمب نیل</translation>
<translation id="42981349822642051">پھیلائیں</translation>
<translation id="4300675098767811073">دائیں طر٠متعدد سوراخ</translation>
<translation id="4302514097724775343">کھیلنے کے لیے ڈائنوسار گیم کھیلنے پر تھپتھپائیں</translation>
<translation id="4302965934281694568">Chou3 ‎(Envelope‎)‎</translation>
<translation id="4305666528087210886">آپ Ú©ÛŒ Ùائل تک رسائی Ù†Ûیں ÛÙˆ سکی</translation>
-<translation id="4305817255990598646">سوئچ کریں</translation>
+<translation id="4306529830550717874">Ù¾ØªÛ Ù…Ø­Ùوظ کریں؟</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">مسدود کریں (ÚˆÛŒÙالٹ)</translation>
<translation id="4314815835985389558">مطابقت پذیری کا نظم کريں</translation>
@@ -929,6 +954,7 @@
<translation id="4377125064752653719">آپ Ù†Û’ <ph name="DOMAIN" /> تک رسائی Ú©ÛŒ کوشش کی، لیکن سرور Ú©Û’ ذریعے پیش Ú©Ø±Ø¯Û Ø³Ø±Ù¹ÛŒÙیکیٹ Ú©Ùˆ اس Ú©Û’ جاری Ú©Ù†Ù†Ø¯Û Ù†Û’ منسوخ کر دیا ÛÛ’Û” اس کا مطلب ÛÛ’ Ú©Û Ø³Ø±ÙˆØ± Ú©Û’ ذریعے پیش Ú©Ø±Ø¯Û Ø³ÛŒÚ©ÛŒÙˆØ±Ù¹ÛŒ اسنادات پر مطلق طور پر Ø¨Ú¾Ø±ÙˆØ³Û Ù†Ûیں کیا جانا چاÛیے۔ ممکن ÛÛ’ Ú©Û Ø¢Ù¾ Ú©ÛŒ مواصلت ایک Ø­Ù…Ù„Û Ø¢ÙˆØ± Ú©Û’ ساتھ ÛÙˆ رÛÛŒ ÛÙˆÛ”</translation>
<translation id="4378154925671717803">Ùون</translation>
<translation id="4390472908992056574">کنارÛ</translation>
+<translation id="4406883609789734330">لائیو کیپشن</translation>
<translation id="4406896451731180161">تلاش کے نتائج</translation>
<translation id="4408413947728134509">کوکیز <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">â€Ø¢Ù¾ Ù†Û’ ابھی ایک Ù¾ÙرÙریب سائٹ پر اپنا پاس ورڈ درج کیا ÛÛ’Û” Chrome آپ Ú©Ùˆ <ph name="WEBSITE_1" />ØŒ <ph name="WEBSITE_2" />ØŒ<ph name="WEBSITE_3" /> اور دیگر ایسی سائٹس پر جانے اور ابھی اپنا پاس ورڈ بدلنے Ú©ÛŒ تجویز کرتا ÛÛ’ جÛاں آپ اس پاس ورڈ Ú©Ùˆ استعمال کرتے Ûیں۔</translation>
@@ -941,7 +967,6 @@
<translation id="4435702339979719576">Postcard)‎</translation>
<translation id="443673843213245140">پراکسی کا استعمال غیر Ùعال کر دیا گیا ÛÛ’ لیکن ایک واضح پراکسی Ú©Ù†Ùیگریشن متعین Ú©ÛŒ گئی ÛÛ’Û”</translation>
<translation id="4464826014807964867">آپ کی تنظیم کے ذریعے دی گئی معلومات والی ویب سائٹس</translation>
-<translation id="4466881336512663640">Ùارم میں Ú©ÛŒ گئی تبدیلیاں ضائع ÛÙˆ جائیں گی۔ کیا آپ واقعی جاری رکھنا چاÛتے Ûیں؟</translation>
<translation id="4476953670630786061">ÛŒÛ Ùارم محÙوظ Ù†Ûیں ÛÛ’Û” آٹو ÙÙ„ Ú©Ùˆ آ٠کر دیا گیا ÛÛ’Û”</translation>
<translation id="4477350412780666475">اگلا ٹریک</translation>
<translation id="4482953324121162758">اس سائٹ کا ØªØ±Ø¬Ù…Û Ù†Ûیں کیا جائے گا۔</translation>
@@ -975,6 +1000,7 @@
<translation id="4594403342090139922">حذ٠کو کالعدم کریں</translation>
<translation id="4597348597567598915">سائز 8</translation>
<translation id="4600854749408232102">C6/C5 ‎(Envelope‎)‎</translation>
+<translation id="4606870351894164739">متاثر کن</translation>
<translation id="4628948037717959914">تصویر</translation>
<translation id="4631649115723685955">کیش بیک لنک Ú©Ø±Ø¯Û ÛÛ’</translation>
<translation id="4636930964841734540">معلومات</translation>
@@ -994,6 +1020,7 @@
<translation id="4691835149146451662">Architecture-A ‎(Envelope‎)‎</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">سائیڈ</translation>
+<translation id="4702656508969495934">لائیو کیپشن دکھائی دے رÛا ÛÛ’ØŒ Ùوکس کرنے کیلئے ونڈو سوئچر استعمال کریں</translation>
<translation id="4708268264240856090">آپ Ú©Û’ کنکشن میں مداخلت Ûوگئی</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131">â€<ph name="BEGIN_LINK" />Windows نیٹ ورک Ú©ÛŒ تشخیصات چلانے Ú©ÛŒ<ph name="END_LINK" /></translation>
@@ -1007,6 +1034,7 @@
<translation id="4738601419177586157"><ph name="TEXT" /> تلاش کی تجویز</translation>
<translation id="4742407542027196863">پاس ورڈز کا نظم کریں…</translation>
<translation id="4744603770635761495">قابل کارروائی پاتھ</translation>
+<translation id="4749011317274908093">آپ پوشیدگی وضع میں Ú†Ù„Û’ گئے Ûیں</translation>
<translation id="4750917950439032686">جب آپ Ú©ÛŒ معلومات (مثلاً، پاس ورڈز یا کریڈٹ کارڈ نمبرز) اس سائٹ پر بھیجی جاتی ÛÛ’ تو اس وقت ÙˆÛ Ù†Ø¬ÛŒ Ûوتی ÛÛ’Û”</translation>
<translation id="4756388243121344051">&amp;سرگزشت</translation>
<translation id="4758311279753947758">رابطے کی معلومات شامل کریں</translation>
@@ -1036,6 +1064,8 @@
<translation id="4813512666221746211">نیٹ ورک کی خرابی</translation>
<translation id="4816492930507672669">صÙØ­Û Ù…ÛŒÚº ÙÙ¹ کریں</translation>
<translation id="4819347708020428563">ÚˆÛŒÙالٹ منظر میں تشریحات میں ترمیم کریں؟</translation>
+<translation id="4825507807291741242">طاقتور</translation>
+<translation id="4838327282952368871">خیالی</translation>
<translation id="484462545196658690">خودکار</translation>
<translation id="4850886885716139402">دیکھیں</translation>
<translation id="485316830061041779">جرمن</translation>
@@ -1172,6 +1202,7 @@
<translation id="5314967030527622926">Ú©ØªØ§Ø¨Ú†Û Ø¨Ù†Ø§Ù†Û’ والا</translation>
<translation id="5316812925700871227">گھڑی کی مخال٠سمت میں گھمائیں</translation>
<translation id="5317780077021120954">محÙوظ کریں</translation>
+<translation id="5321288445143113935">بڑا کر دیا گیا</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />، <ph name="MATCH_POSITION" /> از <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">رابطے کی معلومات منتخب کریں</translation>
<translation id="5327248766486351172">نام</translation>
@@ -1179,11 +1210,13 @@
<translation id="5332219387342487447">ترسیل کا طریقÛ</translation>
<translation id="5333022057423422993">â€Chrome Ú©Ùˆ ÙˆÛ Ù¾Ø§Ø³ ورڈ مل گیا جو آپ Ù†Û’ ابھی ڈیٹا Ú©ÛŒ خلا٠ورزی میں استعمال کیا ÛÛ’Û” اپنے اکاؤنٹس Ú©Ùˆ محÙوظ کرنے Ú©Û’ لیے ÛÙ… آپ Ú©Û’ محÙوظ Ú©Ø±Ø¯Û Ù¾Ø§Ø³ ورڈز Ú©Ùˆ چیک کرنے Ú©ÛŒ تجویز کرتے Ûیں۔</translation>
<translation id="5334013548165032829">Ù…Ùصل سسٹم لاگز</translation>
+<translation id="5334145288572353250">Ù¾ØªÛ Ù…Ø­Ùوظ کریں؟</translation>
<translation id="5340250774223869109">ایپلیکیشن مسدود ÛÛ’</translation>
<translation id="534295439873310000">â€NFC آلات</translation>
<translation id="5344579389779391559">ÛŒÛ ØµÙØ­Û Ø¢Ù¾ سے رقم چارج کرنے Ú©ÛŒ کوشش کر سکتا ÛÛ’</translation>
<translation id="5355557959165512791">آپ ابھی <ph name="SITE" /> Ù…Ù„Ø§Ø­Ø¸Û Ù†Ûیں کر سکتے Ú©ÛŒÙˆÙ†Ú©Û Ø§Ø³ Ú©Û’ سرٹیÙکیٹ Ú©Ùˆ کالعدم قرار دے دیا گیا ÛÛ’Û” نیٹ ورک Ú©ÛŒ خرابیاں اور حملے عام طور پر عارضی Ûوتے Ûیں، Ù„Ûذا ÛŒÛ ØµÙØ­Û Ø´Ø§ÛŒØ¯ بعد میں کام کرے گا۔</translation>
<translation id="536296301121032821">پالیسی کی ترتیبات کو اسٹور کرنے میں ناکام</translation>
+<translation id="5363309033720083897">آپ Ú©Û’ منتظم Ú©ÛŒ جانب سے اجازت یاÙØªÛ Ø³ÛŒØ±ÛŒÙ„ پورٹ</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="5386426401304769735">â€Ø§Ø³ سائٹ کیلئے سرٹیÙکیٹ چین میں SHA-1 کا استعمال کر Ú©Û’ دستخط Ú©Ø±Ø¯Û Ø³Ø±Ù¹ÛŒÙکیٹ شامل ÛÛ’Û”</translation>
@@ -1192,6 +1225,7 @@
<translation id="5398772614898833570">اشتÛارات مسدود Ûیں</translation>
<translation id="5400836586163650660">خاکستری</translation>
<translation id="540969355065856584">ÛŒÛ Ø³Ø±ÙˆØ± ÛŒÛ Ø«Ø§Ø¨Øª Ù†Ûیں کر سکا Ú©Û ÛŒÛ <ph name="DOMAIN" /> ÛÛ’Ø› اس کا سیکیورٹی سرٹیÙکیٹ اس وقت درست Ù†Ûیں ÛÛ’Û” ÛŒÛ ØºÙ„Ø· Ú©Ù†Ùیگریشن یا آپ Ú©Û’ کنکشن میں مانع بن رÛÛ’ کسی Ø­Ù…Ù„Û Ø¢ÙˆØ± Ú©ÛŒ ÙˆØ¬Û Ø³Û’ ÛÙˆ سکتا ÛÛ’Û”</translation>
+<translation id="541143247543991491">کلاؤڈ (سسٹم وار)</translation>
<translation id="541416427766103491">اسٹیکر 4</translation>
<translation id="5421136146218899937">براؤزنگ ڈیٹا صا٠کریں…</translation>
<translation id="5426179911063097041"><ph name="SITE" /> آپ Ú©Ùˆ اطلاعات بھیجنا چاÛتی ÛÛ’</translation>
@@ -1205,6 +1239,7 @@
<translation id="5455374756549232013">غلط پالیسی ٹائم اسٹامپ</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" /> مزید}other{<ph name="CONTACT_PREVIEW" /> اور <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> مزید}}</translation>
+<translation id="5463625433003343978">آلات تلاش کئے جا رÛÛ’ Ûیں...</translation>
<translation id="5469868506864199649">اطالوی</translation>
<translation id="5470861586879999274">ترمییم &amp;Ø¯ÙˆØ¨Ø§Ø±Û Ú©Ø±ÛŒÚº</translation>
<translation id="5478437291406423475">B6/C4 ‎(Envelope‎)‎</translation>
@@ -1254,7 +1289,6 @@
<translation id="5624120631404540903">پاس ورڈز کا نظم کریں</translation>
<translation id="5629630648637658800">پالیسی Ú©ÛŒ ترتیبات لوڈ Ûونے میں ناکام</translation>
<translation id="5631439013527180824">آلے کے مینیجمنٹ کا غلط ٹوکن</translation>
-<translation id="5632627355679805402">â€Ø¢Ù¾ Ú©Û’ ڈیٹا Ú©Ùˆ آپ Ú©Û’ <ph name="BEGIN_LINK" />Google پاس ورڈ<ph name="END_LINK" /> Ú©Û’ ساتھ <ph name="TIME" /> تک مرموز کر دیا گیا۔ مطابقت پذیری شروع کرنے کیلئے اسے درج کریں۔</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="5644090287519800334">â€Ø³Ø§Ø¦ÛŒÚˆ 1 تصویر X Ø´ÙÙ¹</translation>
@@ -1293,12 +1327,12 @@
<translation id="5785756445106461925">اس Ú©Û’ علاوÛØŒ اس صÙØ­Û Ù…ÛŒÚº دیگر ایسے وسائل شامل Ûیں جو محÙوظ Ù†Ûیں Ûیں۔ ان وسائل Ú©Ùˆ ٹرانزٹ Ú©Û’ دوران دیگر لوگ دیکھ سکتے Ûیں اور صÙØ­Û Ú©ÛŒ Ûیئت تبدیل کرنے کیلئے Ø­Ù…Ù„Û Ø¢ÙˆØ± اس میں ترمیم کر سکتے Ûیں۔</translation>
<translation id="5786044859038896871">کیا آپ اپنے کارڈ Ú©ÛŒ معلومات Ù¾Ùر کرنا چاÛتے Ûیں؟</translation>
<translation id="578633867165174378">â€Chrome Ú©Ùˆ ÙˆÛ Ù¾Ø§Ø³ ورڈ مل گیا جو آپ Ù†Û’ ابھی ڈیٹا Ú©ÛŒ خلا٠ورزی میں استعمال کیا ÛÛ’Û” ÛÙ… اس پاس ورڈ Ú©Ùˆ ابھی تبدیل کرنے Ú©ÛŒ تجویز کرتے Ûیں۔</translation>
-<translation id="5798290721819630480">تبدیلیاں مسترد کریں؟</translation>
<translation id="5803412860119678065">کیا آپ اپنے <ph name="CARD_DETAIL" /> Ú©Ùˆ Ù¾Ùر کرنا چاÛتے Ûیں؟</translation>
<translation id="5804241973901381774">اجازتیں</translation>
<translation id="5804427196348435412">â€NFC آلات استعمال کریں</translation>
<translation id="5810442152076338065">ایک ÙØ±Ø³ÙˆØ¯Û Ø³Ø§Ø¦Ùر سوئٹ کا استعمال کر Ú©Û’ <ph name="DOMAIN" /> کا آپ کا کنکشن مرموز کیا گیا ÛÛ’Û”</translation>
<translation id="5813119285467412249">&amp;Ø¯ÙˆØ¨Ø§Ø±Û Ø´Ø§Ù…Ù„ کریں</translation>
+<translation id="5817918615728894473">جوڑا بنائيں</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{â€Ø§Ø¯Ø§Ø¦ÛŒÚ¯ÛŒ کرتے وقت اس کارڈ Ú©Ùˆ چارج کیا جائے گا، تاÛÙ… اس Ú©Û’ اصل نمبر کا اشتراک اس سائٹ Ú©Û’ ساتھ Ù†Ûیں کیا جائے گا۔ اضاÙÛŒ سیکیورٹی Ú©Û’ لیے ایک عارضی CVC تخلیق Ú©ÛŒ جائے گی۔}other{â€Ø§Ø¯Ø§Ø¦ÛŒÚ¯ÛŒ کرتے وقت آپ Ú©Û’ منتخب Ú©Ø±Ø¯Û Ú©Ø§Ø±Úˆ Ú©Ùˆ چارج کیا جائے گا، تاÛÙ… اس Ú©Û’ اصل نمبر کا اشتراک اس سائٹ Ú©Û’ ساتھ Ù†Ûیں کیا جائے گا۔ اضاÙÛŒ سیکیورٹی Ú©Û’ لیے ایک عارضی CVC تخلیق Ú©ÛŒ جائے گی۔}}</translation>
<translation id="5826507051599432481">â€Ø¹Ø§Ù… نام (CN)</translation>
<translation id="5838278095973806738">اس سائٹ پر آپ Ú©Ùˆ کوئی حساس معلومات (مثلاً، پاس ورڈز یا کریڈٹ کارڈز) درج Ù†Ûیں کرنا چاÛیے، Ú©ÛŒÙˆÚºÚ©Û Ø§Ø³Û’ Ø­Ù…Ù„Û Ø¢ÙˆØ± چوری کر سکتے Ûیں۔</translation>
@@ -1306,6 +1340,7 @@
<translation id="5855253129151731373">â€Ø§Ø³ سائٹ Ú©Û’ میزبان کا نام <ph name="LOOKALIKE_DOMAIN" /> سے مماثل لگتا ÛÛ’Û” بعض اوقات Ø­Ù…Ù„Û Ø¢ÙˆØ± ڈومین Ú©Û’ نام میں چھوٹی، مشکل سے نظر آنے والی تبدیلیاں کر Ú©Û’ سائٹس Ú©ÛŒ نقل کرتے Ûیں۔
اگر آپ Ú©Ùˆ لگتا ÛÛ’ Ú©Û ÛŒÛ ØºÙ„Ø·ÛŒ سے دکھایا جا رÛا ÛÛ’ تو https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals Ù…Ù„Ø§Ø­Ø¸Û Ú©Ø±ÛŒÚºÛ”</translation>
+<translation id="5860033963881614850">Ø¢Ù</translation>
<translation id="5862579898803147654">اسٹیکر 8</translation>
<translation id="5863847714970149516">Ø¢Ú¯Û’ کا صÙØ­Û Ø¢Ù¾ سے رقم چارج کرنے Ú©ÛŒ کوشش کر سکتا ÛÛ’</translation>
<translation id="5866257070973731571">Ùون نمبر شامل کریں</translation>
@@ -1322,6 +1357,7 @@
<translation id="5913377024445952699">اسکرین کیپچر روک دیا گیا</translation>
<translation id="59174027418879706">Ùعال</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 زیر استعمال ÛÛ’}other{# زیر استعمال Ûیں}}</translation>
<translation id="5921185718311485855">آن</translation>
<translation id="5921639886840618607">â€Ú©Ø§Ø±Úˆ Ú©Ùˆ Google اکاؤنٹ میں محÙوظ کریں؟</translation>
<translation id="5922853866070715753">تقریباً مکمل ÛÙˆ گیا</translation>
@@ -1341,6 +1377,7 @@
<translation id="5989320800837274978">â€Ù†Û تو Ùکس Ú©Ø±Ø¯Û Ù¾Ø±Ø§Ú©Ø³ÛŒ سرورز Ù†Û ÛÛŒ ‎.pac اسکرپٹ URL کا تعین کیا گیا ÛÛ’Û”</translation>
<translation id="5992691462791905444">â€Ø§Ù†Ø¬ÛŒÙ†ÛŒØ¦Ø±Ù†Ú¯ Z-Ùولڈ</translation>
<translation id="6000758707621254961">'<ph name="SEARCH_TEXT" />' کے <ph name="RESULT_COUNT" /> نتائج</translation>
+<translation id="6006484371116297560">کلاسک</translation>
<translation id="6008122969617370890">â€N سے 1 ترتیب</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">اپنے پاس ورڈز چیک کریں</translation>
@@ -1362,6 +1399,7 @@
<translation id="6045164183059402045">Ù†Ùاذ Ú©ÛŒ تمثیل</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="6049004884579590341">پوری اسکرین سے باÛر نکلنے Ú©Û’ لیے |<ph name="ACCELERATOR" />| Ú©Ùˆ دبائے رکھیں</translation>
<translation id="6049488691372270142">صÙØ­Û Ú©ÛŒ ڈیلیوری</translation>
<translation id="6051221802930200923">آپ ابھی <ph name="SITE" /> Ù…Ù„Ø§Ø­Ø¸Û Ù†Ûیں کر سکتے Ûیں Ú©ÛŒÙˆÙ†Ú©Û ÙˆÛŒØ¨ سائٹ سرٹیÙکیٹ پننگ کا استعمال کرتی ÛÛ’Û” نیٹ ورک Ú©ÛŒ خرابیاں اور حملے عام طور پر عارضی Ûوتے Ûیں، Ù„Ûذا ÛŒÛ ØµÙØ­Û Ø´Ø§ÛŒØ¯ بعد میں کام کرے گا۔</translation>
<translation id="6051898664905071243">صÙØ­Û’ Ú©ÛŒ تعداد:</translation>
@@ -1378,6 +1416,7 @@
<translation id="610911394827799129">â€Ù…Ù…Ú©Ù† ÛÛ’ Ú©Û â€Ž<ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />‎ پر آپ Ú©Û’ Google اکاؤنٹ میں براؤزنگ Ú©ÛŒ سرگزشت Ú©ÛŒ دیگر شکلیں موجود ÛÙˆÚº</translation>
<translation id="6116338172782435947">کلپ بورڈ میں کاپی کیے گئے متن اور تصاویر دیکھیں</translation>
<translation id="6120179357481664955">â€Ø¢Ù¾ Ú©ÛŒ UPI ID یاد رکھیں؟</translation>
+<translation id="6123290840358279103">ورچوئل کارڈ دیکھیں</translation>
<translation id="6124432979022149706">â€Chrome Enterprise کنیکٹرز</translation>
<translation id="6146055958333702838">کوئی بھی کیبلز چیک کریں اور کوئی بھی
روٹرز، موڈمز
@@ -1415,6 +1454,7 @@
<translation id="6289939620939689042">صÙØ­Û’ کا رنگ</translation>
<translation id="6290238015253830360">آپ Ú©Û’ تجویز Ú©Ø±Ø¯Û Ù…Ø¶Ø§Ù…ÛŒÙ† ÛŒÛاں ظاÛر Ûوتے Ûیں</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">â€Chrome میں Google اسسٹنٹ موقو٠کی جا ر ÛÛŒ ÛÛ’</translation>
<translation id="6305205051461490394"><ph name="URL" /> ناقابل رسائی ÛÛ’Û”</translation>
<translation id="6312113039770857350">ویب صÙØ­Û Ø¯Ø³ØªÛŒØ§Ø¨ Ù†Ûیں ÛÛ’</translation>
@@ -1440,6 +1480,7 @@
<translation id="6390200185239044127">â€Ù†ØµÙ Z-Ùولڈ</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">منتظم Ú©ÛŒ پالیسی Ú©Û’ ذریعے <ph name="ORIGIN_NAME" /> سے اس مقام پر پیسٹ کرنا مسدود کر دیا گیا ÛÛ’</translation>
+<translation id="6398765197997659313">پوری سکرین سے خارج ÛÙˆÚº</translation>
<translation id="6401136357288658127">ÛŒÛ Ù¾Ø§Ù„ÛŒØ³ÛŒ ÙØ±Ø³ÙˆØ¯Û ÛÛ’Û” اس Ú©ÛŒ بجائے، آپ Ú©Ùˆ <ph name="NEW_POLICY" /> پالیسی کا استعمال کرنا چاÛیے۔</translation>
<translation id="6404511346730675251">بک مارک میں ترمیم کریں</translation>
<translation id="6406765186087300643">C0 ‎(Envelope‎)‎</translation>
@@ -1452,7 +1493,6 @@
<translation id="6428450836711225518">اپنے Ùون نمبر Ú©ÛŒ توثیق کریں</translation>
<translation id="6433490469411711332">Ø±Ø§Ø¨Ø·Û Ú©ÛŒ معلومات میں ترمیم کریں</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> Ù†Û’ منسلک Ûونے سے منع کر دیا۔</translation>
-<translation id="6434309073475700221">مسترد کریں</translation>
<translation id="6440503408713884761">نظر انداز کردÛ</translation>
<translation id="6443406338865242315">آپ Ù†Û’ Ú©Ù† ایکسٹینشنز اور پلگ انز Ú©Ùˆ انسٹال کیا ÛÛ’</translation>
<translation id="6446163441502663861">Kahu ‎(Envelope‎)‎</translation>
@@ -1495,6 +1535,7 @@
<translation id="6624427990725312378">رابطے کی معلومات</translation>
<translation id="6626291197371920147">درست کارڈ نمبر شامل کریں</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> تلاش</translation>
+<translation id="6630043285902923878">â€USB آلات تلاش کئے جا رÛÛ’ Ûیں...</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">صا٠کریں</translation>
@@ -1510,6 +1551,7 @@
<translation id="6671697161687535275">â€Chromium سے Ùارم Ú©ÛŒ تجویز Ûٹائیں؟</translation>
<translation id="6685834062052613830">سائن آؤٹ کریں اور سیٹ اپ مکمل کریں</translation>
<translation id="6687335167692595844">Ùونٹ سائز Ú©ÛŒ درخواست Ú©ÛŒ گئی</translation>
+<translation id="6688743156324860098">اپ ڈیٹ کریں…</translation>
<translation id="6689249931105087298">Ø³ÛŒØ§Û Ù¾ÙˆØ§Ø¦Ù†Ù¹ کمپریشن Ú©Û’ ساتھ متعلقÛ</translation>
<translation id="6689271823431384964">â€Ø¢Ù¾ Ú©Û’ سائن ان Ûونے Ú©ÛŒ ÙˆØ¬Û Ø³Û’ Chrome آپ Ú©Û’ کارڈز Ú©Ùˆ آپ Ú©Û’ Google اکاؤنٹ میں محÙوظ کرنے Ú©ÛŒ پیشکش کر رÛا ÛÛ’Û” آپ اس برتاؤ Ú©Ùˆ ترتیبات میں تبدیل کر سکتے Ûیں۔ کارڈ Ûولڈر Ú©Û’ نام کا تعلق آپ Ú©Û’ اکاؤنٹ سے ÛÛ’Û”</translation>
<translation id="6698381487523150993">بنا دی گئی:</translation>
@@ -1525,6 +1567,7 @@
<translation id="6744009308914054259">کنکشن کا انتظار کرنے Ú©Û’ دوران، آ٠لائن مضامین Ù¾Ú‘Ú¾Ù†Û’ Ú©Û’ لیے آپ ڈاؤن لوڈز Ù…Ù„Ø§Ø­Ø¸Û Ú©Ø± سکتے Ûیں۔</translation>
<translation id="6753269504797312559">پالیسی کی قدر</translation>
<translation id="6757797048963528358">آپ کا Ø¢Ù„Û Ø³ÛŒÙ„Ù¾ وضع میں چلا گیا۔</translation>
+<translation id="6767985426384634228">Ù¾ØªÛ Ø§Ù¾ ڈیٹ کریں؟</translation>
<translation id="6768213884286397650">Hagaki ‎(Postcard)‎</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">وائلیٹ</translation>
@@ -1547,6 +1590,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">â€Ù¾Ú‘Ú¾Ù†Û’ Ú©Ùˆ Ø²ÛŒØ§Ø¯Û Ø¢Ø³Ø§Ù† بنانے Ú©Û’ ليے Chrome Ù†Û’ اس صÙØ­Û’ Ú©Ùˆ آسان بنایا۔ Chrome Ù†Û’ غیر محÙوظ کنکشن پر اصل صÙØ­Û Ú©Ùˆ بازیاب کیا۔</translation>
<translation id="6891596781022320156">پالیسی Ú©ÛŒ سطح تعاون یاÙØªÛ Ù†Ûیں ÛÛ’Û”</translation>
+<translation id="6895143722905299846">ورچوئل نمبر:</translation>
<translation id="6895330447102777224">آپ Ú©Û’ کارڈ Ú©ÛŒ توثیق ÛÙˆ گئی ÛÛ’</translation>
<translation id="6897140037006041989">صار٠کا ایجنٹ</translation>
<translation id="6898699227549475383">â€ØªÙ†Ø¸ÛŒÙ… (O)</translation>
@@ -1582,10 +1626,10 @@
<translation id="7004583254764674281">â€ØªÛŒØ²ÛŒ سے کاڈرز Ú©ÛŒ تصدیق کرنے کیلئے Windows Hello کا استعمال کریں</translation>
<translation id="7006930604109697472">بÛر صورت بھیجیں</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">ترتیبات کا سائز تبدیل کریں</translation>
<translation id="7014741021609395734">زوم کی سطح</translation>
<translation id="7016992613359344582">ÛŒÛ Ú†Ø§Ø±Ø¬Ø² ایک بار یا بار بار عائد Ûوسکتے Ûیں اور ÛÙˆ سکتا ÛÛ’ Ú©Û ÙˆØ§Ø¶Ø­ Ù†Û ÛÙˆÚºÛ”</translation>
<translation id="7029809446516969842">پاس ورڈز</translation>
+<translation id="7030436163253143341">سرٹیÙیکیٹ درست Ù†Ûیں ÛÛ’</translation>
<translation id="7031646650991750659">â€Ø¢Ù¾ Ù†Û’ Ú©Ù† Google Play ایپس Ú©Ùˆ انسٹال کیا ÛÛ’</translation>
<translation id="7050187094878475250">آپ Ù†Û’ <ph name="DOMAIN" /> تک Ù¾ÛÙ†Ú†Ù†Û’ Ú©ÛŒ کوشش کی، لیکن سرور Ù†Û’ ایک سرٹیÙکیٹ پیش کیا جس Ú©Û’ جواز کا Ø¹Ø±ØµÛ Ø§ØªÙ†Ø§ طویل ÛÛ’ Ú©Û Ø§Ø³ پر Ø¨Ú¾Ø±ÙˆØ³Û Ù†Ûیں کیا جا سکتا۔</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{اس کارڈ Ú©Ùˆ ابھی محÙوظ Ù†Ûیں کیا جا سکتا}other{ان کارڈز Ú©Ùˆ ابھی محÙوظ Ù†Ûیں کیا جا سکتا}}</translation>
@@ -1655,12 +1699,14 @@
<translation id="7300012071106347854">کوبالٹ نیلا</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">زیادÛ</translation>
+<translation id="7305756307268530424">آÛØ³ØªÛ Ø´Ø±ÙˆØ¹ کریں</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">کنکشن سے متعلق مدد</translation>
<translation id="7323804146520582233">"<ph name="SECTION" />" سیکشن چھپائیں</translation>
<translation id="733354035281974745">Ø¢Ù„Û Ú©Û’ مقامی اکاؤنٹ کا اوور رائیڈ</translation>
<translation id="7333654844024768166">â€Ø¢Ù¾ Ù†Û’ ابھی ایک Ù¾ÙرÙریب سائٹ پر اپنا پاس ورڈ درج کیا ÛÛ’Û” Chromium آپ Ú©Ùˆ <ph name="WEBSITE_1" />ØŒ <ph name="WEBSITE_2" />ØŒ<ph name="WEBSITE_3" /> اور دیگر ایسی سائٹس پر جانے اور ابھی اپنا پاس ورڈ بدلنے Ú©ÛŒ تجویز کرتا ÛÛ’ جÛاں آپ اس پاس ورڈ Ú©Ùˆ استعمال کرتے Ûیں۔</translation>
<translation id="7334320624316649418">Ø¯ÙˆØ¨Ø§Ø±Û ØªØ±ØªÛŒØ¨ Ú©Ùˆ &amp;واپس لائیں</translation>
+<translation id="7337248890521463931">مزید لائنز دکھائیں</translation>
<translation id="7337706099755338005">آپ Ú©Û’ پلیٹ Ùارم پر دستیاب Ù†Ûیں ÛÛ’Û”</translation>
<translation id="733923710415886693">سرٹیÙیکیٹ Ú©ÛŒ Ø´ÙاÙیت Ú©Û’ ذریعے سرور Ú©Û’ سرٹیÙیکیٹ کا انکشا٠نÛیں کیا گیا۔</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1668,6 +1714,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">کمانڈ لائن</translation>
<translation id="7359588939039777303">اشتÛارات مسدود Ûیں۔</translation>
+<translation id="7363096869660964304">تاÛÙ…ØŒ آپ غیر مرئی Ù†Ûیں Ûیں۔ پوشیدگی اختیار کرنا آپ Ú©Û’ آجر، آپ Ú©Û’ انٹرنیٹ سروس ÙراÛÙ… Ú©Ù†Ù†Ø¯Û ÛŒØ§ آپ جو ویب سائٹس Ù…Ù„Ø§Ø­Ø¸Û Ú©Ø±ØªÛ’ Ûیں ان سے آپ Ú©ÛŒ براؤزنگ Ú©Ùˆ Ù†Ûیں چھپاتا ÛÛ’Û”</translation>
<translation id="7365596969960773405">â€<ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ Chrome Ú©ÛŒ ترتیبات میں پتوں Ú©Ùˆ شامل کرنے اور ان کا نظم کرنے Ú©Û’ لیے ٹیب پھر اینٹر دبائیں</translation>
<translation id="7365849542400970216">اپنے آلے کا استعمال جانتے Ûیں؟</translation>
<translation id="7372973238305370288">تلاش کا نتیجÛ</translation>
@@ -1678,7 +1725,9 @@
<translation id="7378594059915113390">میڈیا کنٹرولز</translation>
<translation id="7378627244592794276">Ù†Ûیں</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ناقابل اطلاق</translation>
<translation id="7390545607259442187">کارڈ کی توثیق کریں</translation>
+<translation id="7392089738299859607">Ù¾ØªÛ Ø§Ù¾ ڈیٹ کریں</translation>
<translation id="7399802613464275309">سیÙÙ¹ÛŒ چیک</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120">آپ کا <ph name="DEVICE_NAME" /> زیر انتظام ÛÛ’</translation>
@@ -1693,6 +1742,7 @@
&lt;li&gt;مستقل طور پر اپنے کمپیوٹر سے ساÙÙ¹ ویئر Ûٹانے کا Ø·Ø±ÛŒÙ‚Û Ø¬Ø§Ù†Ù†Û’ کیلئے، &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome کا مرکز امداد&lt;/a&gt; Ù…Ù„Ø§Ø­Ø¸Û Ú©Ø±ÛŒÚº
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">لولی</translation>
<translation id="7416351320495623771">پاس ورڈز کا نظم کریں…</translation>
<translation id="7419106976560586862">پروÙائل پاتھ</translation>
<translation id="7437289804838430631">رابطے کی معلومات شامل کریں</translation>
@@ -1708,7 +1758,7 @@
<translation id="7481312909269577407">Ùارورڈ کریں</translation>
<translation id="7485870689360869515">کوئی ڈیٹا Ù†Ûیں ملا۔</translation>
<translation id="7495528107193238112">ÛŒÛ Ù…ÙˆØ§Ø¯ مسدود ÛÛ’Û” مسئلے Ú©Ùˆ حل کرنے Ú©Û’ لیے سائٹ Ú©Û’ مالک سے Ø±Ø§Ø¨Ø·Û Ú©Ø±ÛŒÚºÛ”</translation>
-<translation id="7498234416455752244">ترمیم جاری رکھیں</translation>
+<translation id="7498193950643227031">سائز تبدیل Ûونے پر ممکن ÛÛ’ Ú©Û ÛŒÛ ØºÛŒØ± متوقع طور پر برتاؤ کرے۔ اب آپ <ph name="SETTINGS" /> میں ایپس کا سائز تبدیل کرنے Ú©ÛŒ اÛلیت Ú©Ùˆ محدود کر سکتے Ûیں۔</translation>
<translation id="7503664977220660814">â€Ø¢Ù¾ Ù†Û’ ابھی ایک Ù¾ÙرÙریب سائٹ پر اپنا پاس ورڈ درج کیا ÛÛ’Û” Chromium <ph name="WEBSITE_1" />ØŒ <ph name="WEBSITE_2" /> اور دیگر ایسی سائٹس Ú©Û’ لیے اپنے محÙوظ Ú©Ø±Ø¯Û Ù¾Ø§Ø³ ورڈز Ú©Ùˆ ابھی چیک کرنے Ú©ÛŒ تجویز کرتا ÛÛ’ جÛاں آپ اس پاس ورڈ کا استعمال کرتے Ûیں۔</translation>
<translation id="7508255263130623398">â€ÙˆØ§Ù¾Ø³ Ú©Ø±Ø¯Û Ù¾Ø§Ù„ÛŒØ³ÛŒ Ø¢Ù„Û id خالی ÛÛ’ یا Ù…ÙˆØ¬ÙˆØ¯Û Ø¢Ù„Û id سے مماثل Ù†Ûیں ÛÛ’</translation>
<translation id="7508870219247277067">مَگَر ناشپاتی سبز</translation>
@@ -1728,6 +1778,7 @@
<translation id="7548892272833184391">کنکشن کی خرابیاں ٹھیک کریں</translation>
<translation id="7549584377607005141">ٹھیک سے ڈسپلے کیے جانے کیلئے ÛŒÛ ÙˆÛŒØ¨ صÙØ­Û Ø¢Ù¾ Ú©ÛŒ جانب سے Ù¾ÛÙ„Û’ داخل Ú©Ø±Ø¯Û ÚˆÛŒÙ¹Ø§ کا ØªÙ‚Ø§Ø¶Û Ú©Ø±ØªØ§ ÛÛ’Û” آپ اس ڈیٹا Ú©Ùˆ Ø¯ÙˆØ¨Ø§Ø±Û Ø¨Ú¾ÛŒØ¬ سکتے Ûیں لیکن ایسا کرنے سے آپ کسی ایسی کارروائی Ú©Ùˆ دوÛرائیں Ú¯Û’ جسے اس صÙØ­Û Ù†Û’ Ù¾ÛÙ„Û’ انجام دیا ÛÛ’Û”</translation>
<translation id="7550637293666041147">â€Ø¢Ù¾ Ú©Û’ آلے کا صار٠نام اور Chrome کا صار٠نام</translation>
+<translation id="755279583747225797">ٹرائل Ùعال ÛÛ’</translation>
<translation id="7552846755917812628">درج ذیل تجاویز کی کوشش کریں:</translation>
<translation id="7554475479213504905">Ø¯ÙˆØ¨Ø§Ø±Û Ù„ÙˆÚˆ کریں اور بÛرصورت دکھائیں</translation>
<translation id="7554791636758816595">نیا ٹیب</translation>
@@ -1746,7 +1797,6 @@
<translation id="7610193165460212391">قدر رینج سے باÛر Ú©ÛŒ ÛÛ’ <ph name="VALUE" />Û”</translation>
<translation id="7613889955535752492">â€Ø§Ø®ØªØªØ§Ù…ÛŒ تاریخ: ‎<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" />‎</translation>
<translation id="7614494068621678628">â€<ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />ØŒ Chrome Ú©ÛŒ ترتیبات میں اپنے پاس ورڈز کا نظم کرنے اور انÛیں دیکھنے Ú©Û’ لیے ٹیب، پھر اینٹر دبائیں</translation>
-<translation id="7615602087246926389">â€Ø¢Ù¾ Ú©Û’ پاس Ù¾ÛÙ„Û’ ÛÛŒ ایسا ڈیٹا ÛÛ’ جسے آپ Ú©Û’ Google اکاؤنٹ Ú©Û’ پاس ورڈ کا مختل٠ورژن استعمال کر Ú©Û’ مرموز کر دیا گیا ÛÛ’Û” Ø¨Ø±Ø§Û Ú©Ø±Ù… اسے ذیل میں داخل کریں۔</translation>
<translation id="7616645509853975347">â€Ø¢Ù¾ Ú©Û’ منتظم Ù†Û’ آپ Ú©Û’ براؤزر میں Chrome انٹرپرائز کنیکٹرز آن کر دیے Ûیں۔ ان کنیکٹرز Ú©Ùˆ آپ Ú©Û’ Ú©Ú†Ú¾ ڈیٹا تک رسائی حاصل ÛÛ’Û”</translation>
<translation id="7619838219691048931">آخری شیٹ</translation>
<translation id="762844065391966283">ایک وقت میں ایک</translation>
@@ -1811,13 +1861,12 @@
<translation id="782886543891417279">â€Ø¢Ù¾ جو Wi-Fi استعمال کر رÛÛ’ Ûیں <ph name="WIFI_NAME" /> ÙˆÛ Ø¢Ù¾ سے اپنا لاگ ان صÙØ­Û Ù…Ù„Ø§Ø­Ø¸Û Ú©Ø±Ù†Û’ کا ØªÙ‚Ø§Ø¶Û Ú©Ø± سکتا ÛÛ’Û”</translation>
<translation id="7836231406687464395">Postfix ‎(Envelope‎)‎</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{کوئی Ù†Ûیں}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Ùائل ٹائپ ایسوسی ایشنز Ú©Û’ ساتھ Ùائلز کھولیں۔</translation>
<translation id="7862185352068345852">سائٹ چھوڑیں؟</translation>
<translation id="7865448901209910068">Ø¹Ù…Ø¯Û Ø±Ùتار</translation>
<translation id="7874263914261512992">â€Ø¢Ù¾ Ù†Û’ ابھی ایک Ù¾ÙرÙریب سائٹ پر اپنا پاس ورڈ درج کیا ÛÛ’Û” Chrome <ph name="WEBSITE_1" />ØŒ <ph name="WEBSITE_2" /> اور دیگر ایسی سائٹس Ú©Û’ لیے اپنے محÙوظ Ú©Ø±Ø¯Û Ù¾Ø§Ø³ ورڈز Ú©Ùˆ ابھی چیک کرنے Ú©ÛŒ تجویز کرتا ÛÛ’ جÛاں آپ اس پاس ورڈ کا استعمال کرتے Ûیں۔</translation>
<translation id="7878562273885520351">لگتا ÛÛ’ کسی Ù†Û’ آپ Ú©Û’ پاس ورڈ Ú©Û’ ساتھ چھیڑ چھاڑ Ú©ÛŒ ÛÛ’</translation>
+<translation id="7880146494886811634">Ù¾ØªÛ Ù…Ø­Ùوظ کریں</translation>
<translation id="7882421473871500483">بھورا</translation>
<translation id="7887683347370398519">â€Ø§Ù¾Ù†Ø§ CVC چیک کریں اور Ø¯ÙˆØ¨Ø§Ø±Û Ú©ÙˆØ´Ø´ کریں</translation>
<translation id="7887885240995164102">'تصویر میں تصویر' میں داخل ÛÙˆÚº</translation>
@@ -1825,6 +1874,7 @@
<translation id="7894280532028510793">اگر Ûجے درست Ûیں تو <ph name="BEGIN_LINK" />نیٹ ورک Ú©ÛŒ تشخیصات چلانے Ú©ÛŒ کوشش کریں<ph name="END_LINK" />Û”</translation>
<translation id="7904208859782148177">C3 ‎(Envelope‎)‎</translation>
<translation id="7931318309563332511">نامعلوم</translation>
+<translation id="793209273132572360">Ù¾ØªÛ Ø§Ù¾ ڈیٹ کریں؟</translation>
<translation id="7932579305932748336">کوٹ</translation>
<translation id="79338296614623784">ایک درست Ùون نمبر درج کریں</translation>
<translation id="7934052535022478634">ادائیگی مکمل Ûوگئی</translation>
@@ -1895,6 +1945,7 @@
<translation id="8175796834047840627">â€Ø¢Ù¾ Ú©Û’ سائن ان Ûونے Ú©ÛŒ ÙˆØ¬Û Ø³Û’ Chrome آپ Ú©Û’ کارڈز Ú©Ùˆ آپ Ú©Û’ Google اکاؤنٹ میں محÙوظ کرنے Ú©ÛŒ پیشکش کر رÛا ÛÛ’Û” آپ اس برتاؤ Ú©Ùˆ ترتیبات میں تبدیل کر سکتے Ûیں۔</translation>
<translation id="8176440868214972690">اس Ø¢Ù„Û Ú©Û’ منتظم Ù†Û’ Ú©Ú†Ú¾ معلومات جیسے ترتیبات یا پالیسیاں درج ذیل ویب سائٹ پر بھیجی Ûیں۔</translation>
<translation id="8184538546369750125">عالمی ÚˆÛŒÙالٹ استعمال کریں (اجازت دیں)</translation>
+<translation id="8193086767630290324">Ø±Ø§Ø²Ø¯Ø§Ø±Ø§Ù†Û Ú©Û’ بطور پرچم لگائے گئے ڈیٹا Ú©Û’ متعلق Ú©ÛŒ گئی کاروائیاں</translation>
<translation id="8194797478851900357">منتقلی کو &amp;کالعدم کریں</translation>
<translation id="8201077131113104583">â€â€ŽID "<ph name="EXTENSION_ID" />"‎ Ú©Û’ ساتھ ایکسٹینشن کیلئے غلط اپ ڈیٹ URLÛ”</translation>
<translation id="8202097416529803614">آرڈر کا خلاصÛ</translation>
@@ -1917,6 +1968,7 @@
<translation id="8249296373107784235">منسوخ کریں</translation>
<translation id="8249320324621329438">آخری بازیابی:</translation>
<translation id="8253091569723639551">بلنگ Ù¾ØªÛ Ø¯Ø±Ú©Ø§Ø± ÛÛ’</translation>
+<translation id="8257387598443225809">ÛŒÛ Ø§ÛŒÙ¾ موبائل Ú©Û’ لیے بنائی گئی ÛÛ’</translation>
<translation id="825929999321470778">سبھی 'محÙوظ پاسورڈز' دکھائيں</translation>
<translation id="8261506727792406068">حذ٠کریں</translation>
<translation id="8262952874573525464">نیچے کنارے کی سلائی</translation>
@@ -2040,7 +2092,6 @@
<translation id="8719528812645237045">اوپر متعدد سوراخ</translation>
<translation id="8725066075913043281">Ø¯ÙˆØ¨Ø§Ø±Û Ú©ÙˆØ´Ø´ کریں</translation>
<translation id="8726549941689275341">صÙØ­Û’ کا سائز:</translation>
-<translation id="8728672262656704056">آپ پرائیویٹ براؤزنگ کر رÛÛ’ Ûیں</translation>
<translation id="8730621377337864115">Ûوگیا</translation>
<translation id="8731544501227493793">â€'پاس ورڈز کا نظم کریں' بٹن، Chrome Ú©ÛŒ ترتیبات میں اپنے پاس ورڈز کا نظم کرنے اور انÛیں دیکھنے Ú©Û’ لیے اینٹر دبائیں</translation>
<translation id="8734529307927223492">آپ کا <ph name="DEVICE_TYPE" /> <ph name="MANAGER" /> Ú©Û’ زیر انتظام ÛÛ’</translation>
@@ -2117,6 +2168,7 @@
<translation id="9020542370529661692">اس صÙØ­Û Ú©Ø§ <ph name="TARGET_LANGUAGE" /> میں ØªØ±Ø¬Ù…Û Ú©Ø± دیا گیا ÛÛ’</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(غلط)</translation>
+<translation id="9030265603405983977">مونوکروم</translation>
<translation id="9035022520814077154">سیکیورٹی کی خرابی</translation>
<translation id="9038649477754266430">صÙحات Ú©Ùˆ مزید تیزی سے لوڈ کرنے کیلئے پیشین گوئی سروس کا استعمال کریں</translation>
<translation id="9039213469156557790">اس Ú©Û’ علاوÛØŒ اس صÙØ­Û Ù…ÛŒÚº دیگر ایسے وسائل شامل Ûیں جو محÙوظ Ù†Ûیں Ûیں۔ ان وسائل Ú©Ùˆ ٹرانزٹ Ú©Û’ دوران دیگر لوگ دیکھ سکتے Ûیں اور صÙØ­Û Ú©Ø§ برتاؤ تبدیل کرنے کیلئے Ø­Ù…Ù„Û Ø¢ÙˆØ± اس میں ترمیم کر سکتے Ûیں۔</translation>
@@ -2141,6 +2193,7 @@
<translation id="91108059142052966">Ø±Ø§Ø²Ø¯Ø§Ø±Ø§Ù†Û Ù…ÙˆØ§Ø¯ Ú©Û’ مرئی Ûونے پر منتظم Ú©ÛŒ پالیسی <ph name="APPLICATION_TITLE" /> Ú©Û’ ساتھ اسکرین Ú©Û’ اشتراک Ú©Ùˆ غیر Ùعال کرتی ÛÛ’</translation>
<translation id="9114524666733003316">کارڈ Ú©ÛŒ توثیق Ú©ÛŒ جا رÛÛŒ Ûے…</translation>
<translation id="9114581008513152754">â€ÛŒÛ براؤزر کسی کمپنی یا دوسری تنظیم Ú©Û’ زیر انتظام Ù†Ûیں ÛÛ’Û” اس آلے پر Ûونے والی سرگرمی کا Chrome سے باÛر نظم کیا جا سکتا ÛÛ’Û” <ph name="BEGIN_LINK" />مزید جانیں<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">تازه</translation>
<translation id="9119042192571987207">اپ لوڈ ÛÙˆ گیا</translation>
<translation id="9128016270925453879">پالیسیاں لوڈ ÛÙˆ گئی Ûیں</translation>
<translation id="9128870381267983090">نیٹ ورک سے منسلک ÛÙˆÚº</translation>
@@ -2159,6 +2212,7 @@
<translation id="9170848237812810038">&amp;کالعدم کریں</translation>
<translation id="9171296965991013597">ایپ بند کریں؟</translation>
<translation id="9173282814238175921">واحد دستاویز/نئی شیٹ</translation>
+<translation id="9173995187295789444">بلوٹوتھ آلات کیلئے اسکین کیا جا رÛا ÛÛ’...</translation>
<translation id="917450738466192189">سرور کا سرٹیÙکیٹ غلط ÛÛ’Û”</translation>
<translation id="9174917557437862841">â€Ù¹ÛŒØ¨ پر سوئچ کرنے کا بٹن، اس ٹیب پر سوئچ کرنے Ú©Û’ لیے Enter دبائیں</translation>
<translation id="9179703756951298733">â€Chrome ترتیبات میں اپنی ادائیگیوں اور کریڈٹ کارڈ Ú©ÛŒ معلومات کا نظم کریں</translation>
diff --git a/chromium/components/strings/components_strings_uz.xtb b/chromium/components/strings/components_strings_uz.xtb
index 795b8e92abb..6ad6b180425 100644
--- a/chromium/components/strings/components_strings_uz.xtb
+++ b/chromium/components/strings/components_strings_uz.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Chrome shakllarni tezroq to‘ldirish uchun karta ma’lumotlarini ushbu qurilmaga saqlaydi.</translation>
<translation id="1110994991967754504"><ph name="PERMISSION_NAME" /> ruxsatini tanlang</translation>
<translation id="1113869188872983271">&amp;Qayta tartiblashni qaytarish</translation>
+<translation id="1123753900084781868">Jonli izoh hozirda mavjud emas</translation>
<translation id="1125573121925420732">Saytlar xavfsizlik sozlamalarini yangilayotganda ogohlantirishlar umumiy bo‘lishi mumkin. Bu tezda yashilanadi.</translation>
<translation id="112840717907525620">Siyosat keshida xatoliklar yo‘q</translation>
<translation id="1130564665089811311">“Sahifani tarjima qilish†tugmasi, bu sahifani Google Tarjimon orqali tarjima qilish uchun Enter tugmasini bosing</translation>
@@ -74,6 +75,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="1240347957665416060">Qurilma nomi</translation>
<translation id="124116460088058876">Boshqa tillar</translation>
<translation id="1243027604378859286">Muallif:</translation>
+<translation id="1246424317317450637">Qalin</translation>
<translation id="1250759482327835220">Keyingi safar tezroq to‘lash uchun kartangizni Google hisobingizga saqlang.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (sinxronlandi)</translation>
<translation id="1256368399071562588">&lt;p&gt;Sayt ochilmasa, quyidagi usullar orqali muammoni hal qilishga urining:&lt;/p&gt;
@@ -156,6 +158,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="1476595624592550506">Parolingizni almashtiring</translation>
<translation id="1484290072879560759">Yetkazib berish manzilini tanlang</translation>
<translation id="1492194039220927094">Push-xabar orqali yuboriladigan siyosatlar:</translation>
+<translation id="1495677929897281669">Varaqqa qaytish</translation>
<translation id="1501859676467574491">Google hisobingizdagi kartalarni ochish</translation>
<translation id="1507202001669085618">&lt;p&gt;Wi-Fi portaldan foydalanayotganingizda onlayn bo‘lishingiz uchun sizdan kirishni so‘raganda shunday xatolik ko‘rsatiladi.&lt;/p&gt;
&lt;p&gt;Muammoni hal qilish uchun ochilishi kerak bo‘lgan sahifadagi &lt;strong&gt;Ulanish&lt;/strong&gt; tugmasini bosing.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="1532118530259321453">Amalni tasdiqlang</translation>
<translation id="153384715582417236">Hozircha hammasi shu</translation>
<translation id="1536390784834419204">Sahifani tarjima qilish</translation>
+<translation id="1539840569003678498">Hisobot yuborildi:</translation>
<translation id="154408704832528245">Yetkazib berish manzilini tanlang</translation>
<translation id="1549470594296187301">Bu xususiyatdan foydalanish uchun JavaScript yoqilgan bo‘lishi lozim.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -212,16 +216,19 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="1682696192498422849">Avval eniga</translation>
<translation id="168693727862418163">Bu parametr oʻz andozasiga mos tushmagani uchun inkor etiladi.</translation>
<translation id="168841957122794586">Server sertifikati ishonchsiz kriptografik kalitga ega.</translation>
+<translation id="1696290444144917273">Virtual karta tafsilotlarini ochish</translation>
<translation id="1697532407822776718">Tayyor!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{Server bu domenni <ph name="DOMAIN" /> ekanligini tasdiqlay olmaydi. Uning xavfsizlik sertifikati ertadan boshlab shubhali hisoblanadi. Balki, server noto‘g‘ri sozlangan yoki kimdir ma’lumotlaringizni o‘g‘irlashga urinayotgan bo‘lishi mumkin.}other{Server bu domenni <ph name="DOMAIN" /> ekanligini tasdiqlay olmaydi. Uning xavfsizlik sertifikati # kundan keyin kuchga kiradi. Balki, server noto‘g‘ri sozlangan yoki kimdir ma’lumotlaringizni o‘g‘irlashga urinayotgan bo‘lishi mumkin.}}</translation>
<translation id="1710259589646384581">OT</translation>
+<translation id="1711234383449478798"><ph name="POLICY_NAME" /> siyosatida <ph name="VALUE" /> qiymati sozlanmagani uchun inkor etildi.</translation>
<translation id="1712552549805331520"><ph name="URL" /> sayti ma’lumotlarni kompyuteringizda doimiy saqlashga ruxsat so‘ramoqda</translation>
<translation id="1713628304598226412">Tarnov 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Pochta qutisi 3</translation>
<translation id="1718029547804390981">Hujjat juda kattaligi uchun izohlanmaydi</translation>
<translation id="1721424275792716183">* Bu maydoncha kiritilishi shart</translation>
+<translation id="1727613060316725209">Sertifikat yaroqli</translation>
<translation id="1727741090716970331">Karta raqamini xatosiz kiriting</translation>
<translation id="1728677426644403582">Siz veb-sahifa kodini ko‘rmoqdasiz.</translation>
<translation id="173080396488393970">Bunday karta hozirda ishlamaydi</translation>
@@ -245,7 +252,6 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
bajara olmaydi. Manba siyosatlari sayt operatorlari
tomonidan xavfsizlik kabi sayt parametrlarini sozlashda ishlatiladi.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Iltimos, sinxronlash uchun kodli iborani yangilang.</translation>
<translation id="1787142507584202372">Ochiq varaqlar shu yerda ko‘rsatiladi</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, bir nechta amal mavjud, ularga oʻtish uchun Tab tugmasini bosing</translation>
@@ -278,6 +284,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="1919345977826869612">Reklamalar</translation>
<translation id="1919367280705858090">Maxsus turdagi xato xabarlari asosida yordam olish</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Yo‘q}=1{1 ta sayt}other{# ta sayt}}</translation>
+<translation id="1924727005275031552">Yangi</translation>
<translation id="1945968466830820669">Tashkilot hisobingiz xavf ostida va o‘g‘irlanishi mumkin. Chromium parolingizni hoziroq o‘zgartirishni tavsiya etadi.</translation>
<translation id="1947454675006758438">Yuqori oʻngdan steplerlash</translation>
<translation id="1958218078413065209">Eng yuqori ballingiz: <ph name="SCORE" />.</translation>
@@ -300,12 +307,14 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="2042213636306070719">Tarnov 7</translation>
<translation id="204357726431741734">Google hisobingizda saqlangan parollardan foydalanish uchun hisobingizga kiring</translation>
<translation id="2053111141626950936"><ph name="LANGUAGE" /> tilidagi sahifalar tarjima qilinmaydi</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Bu boshqaruv elementi yoniq va faol boʻlsa, Chrome brauzerdagi oxirgi harakatlaringizga eng mos katta yoki “kogort†guruh odamlarni aniqlaydi. Reklama beruvchilar eʼlonlari uchun guruh tanlaganda qurilmadagi harakatlaringiz maxfiyligi saqlanib qoladi. Guruhingiz har kuni yangilanib turadi.}=1{Bu boshqaruv elementi yoniq va faol boʻlsa, Chrome brauzerdagi oxirgi harakatlaringizga eng mos katta yoki “kogort†guruh odamlarni aniqlaydi. Reklama beruvchilar eʼlonlari uchun guruh tanlaganda qurilmadagi harakatlaringiz maxfiyligi saqlanib qoladi. Guruhingiz har kuni yangilanib turadi.}other{Bu boshqaruv elementi yoniq va faol boʻlsa, Chrome brauzerdagi oxirgi harakatlaringizga eng mos katta yoki “kogort†guruh odamlarni aniqlaydi. Reklama beruvchilar eʼlonlari uchun guruh tanlaganda qurilmadagi harakatlaringiz maxfiyligi saqlanib qoladi. Guruhingiz har {NUM_DAYS} kunda yangilanib turadi.}}</translation>
<translation id="2053553514270667976">Pochta indeksi</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 ta tavsiya}other{# ta tavsiya}}</translation>
<translation id="2071692954027939183">Odatda ruxsat bermasligingiz uchun bildirishnomalar avtomatik bloklanadi</translation>
<translation id="2079545284768500474">Bekor qilish</translation>
<translation id="20817612488360358">Tizim proksi-server sozlamalari yoniq, lekin uning sozlamalari aniq belgilangan.</translation>
<translation id="2082238445998314030">Natija: <ph name="RESULT_NUMBER" /> / <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Saqlash…</translation>
<translation id="2088086323192747268">Sinxronizatsiyani boshqarish tugmasi, Chrome sozlamalari orqali sinxronlanadigan maʼlumotlarni boshqarish uchun Enter tugmasini bosing</translation>
<translation id="2091887806945687916">Tovush</translation>
<translation id="2094505752054353250">Domen noto‘g‘ri kiritildi</translation>
@@ -378,6 +387,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="2317259163369394535"><ph name="DOMAIN" /> domeniga kirish uchun login va parolni kiritish zarur.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, muddati: <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Sozlamani administrator boshqaradi</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> qurilmangizga ulanmoqchi</translation>
<translation id="2344028582131185878">Avtomatik yuklanishlar</translation>
<translation id="2346319942568447007">Nusxalangan rasm</translation>
<translation id="2354001756790975382">Boshqa xatcho‘plar</translation>
@@ -385,8 +395,10 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="2355395290879513365">Firibgarlar bu saytda siz ochgan rasmlarni ko‘rishi va bu rasmlarni qalbakilashtirib, o‘zgartirishi mumkin.</translation>
<translation id="2356070529366658676">So‘ralsin</translation>
<translation id="2357481397660644965">Qurilma <ph name="DEVICE_MANAGER" /> domenida va hisobingiz <ph name="ACCOUNT_MANAGER" /> tomonidan boshqariladi.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Bir kun ichida}=1{Bir kundan keyin}other{{NUM_DAYS} kundan keyin}}</translation>
<translation id="2359629602545592467">Bir nechta</translation>
<translation id="2359808026110333948">Davom etish</translation>
+<translation id="2359961752320758691">Virtual kartangiz raqamlari kiritildi.</translation>
<translation id="2367567093518048410">Daraja</translation>
<translation id="2372464001869762664">Tasdiqlasangiz, Google hisobingizdagi bank karta maʼlumotlari bu saytda saqlanib qoladi. Plex hisobingizdagi karta CVC kodini toping.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -397,6 +409,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="239429038616798445">Bu yetkazib berish usuli hozirda ishlamaydi. Boshqa usulni tanlang.</translation>
<translation id="2396249848217231973">&amp;O‘chirishni bekor qilish</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">Eski</translation>
<translation id="2413528052993050574">Bu <ph name="DOMAIN" /> serveri ekanligi tasdiqlanmadi. Uning havfsizlik sertifikati eskirgan. Server sozlamalari noto‘g‘ri moslangan yoki kimdir sizning shaxsiy ma’lumotlaringizni o‘g‘irlashga harakat qilmoqda.</translation>
<translation id="2414886740292270097">Qorong‘i</translation>
<translation id="2438874542388153331">Oʻngdan 4 ta teshik ochish</translation>
@@ -424,10 +437,10 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="2521385132275182522">Quyi oʻngdan steplerlash</translation>
<translation id="2523886232349826891">Faqat shu qurilmada saqlanadi</translation>
<translation id="2524461107774643265">Qo‘shimcha axborot qo‘shish</translation>
-<translation id="2526590354069164005">Ish soli</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{va yana 1 ta}other{va yana # ta}}</translation>
<translation id="2536110899380797252">Manzil kiritish</translation>
<translation id="2539524384386349900">Aniqlansin</translation>
+<translation id="2541219929084442027">Inkognito rejimida ochilgan sahifalar brauzer yoki qidiruv tarixida saqlanmaydi. Barcha inkognito sahifalari yopilganda qurilmangizda cookie fayllar kabi izlar qolmaydi. Yuklab olingan fayllar va bukmarklaringiz saqlanib qoladi.</translation>
<translation id="2544644783021658368">Bitta hujjat</translation>
<translation id="254947805923345898">Parametr qiymati yaroqsiz.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> yaroqsiz javob qaytardi.</translation>
@@ -447,6 +460,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="2629325967560697240">Chrome brauzerining yuqori darajadagi xavfsizligidan foydalanish uchun <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />kengaytirilgan himoyani yoqing<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069"><ph name="HOST_NAME" /> serverining IP manzili topilmadi.</translation>
<translation id="2639739919103226564">Holat:</translation>
+<translation id="264810637653812429">Mos qurilmalar topilmadi.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome sozlamalari orqali brauzer tarixi, cookie fayllari, kesh va boshqa maʼlumotlarni tozalash uchun Enter tugmasini bosing</translation>
<translation id="2650446666397867134">Faylga kirish taqiqlandi</translation>
@@ -493,6 +507,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="2799223571221894425">Qaytadan ishga tushirish</translation>
<translation id="2803306138276472711">Google saytlar xavfsizligini tekshirish tizimi yaqinda <ph name="SITE" /> saytida <ph name="BEGIN_LINK" />zararli dasturlarni<ph name="END_LINK" /> topdi. Ehtiyot bo‘ling, ba’zida himoyalangan saytlardan ham zararli dasturlar tarqatilishi mumkin.</translation>
<translation id="2807052079800581569">Tasvirning Y oʻqidagi joylashuvi</translation>
+<translation id="2820957248982571256">Tekshirilmoqda...</translation>
<translation id="2824775600643448204">Manzil va qidiruv paneli</translation>
<translation id="2826760142808435982">Aloqa shifrlangan va <ph name="CIPHER" /> yordamida tekshirilgan. Kalitlar almashinuvi mexanizmi sifatida <ph name="KX" /> qo‘llanilmoqda.</translation>
<translation id="2835170189407361413">Tozalash</translation>
@@ -500,6 +515,8 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="2850739647070081192">Invite (Envelope)</translation>
<translation id="2856444702002559011">Firibgarlar <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> saytidan ma’lumotlaringizni (parol, xabar va kredit karta ma’lumotlari kabilarni) o‘g‘irlashga urinayotgan bo‘lishi mumkin. <ph name="BEGIN_LEARN_MORE_LINK" />Batafsil<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Bu saytda yoqimsiz yoki befoyda reklamalar chiqadi.</translation>
+<translation id="287596039013813457">Doʻstona</translation>
+<translation id="2876489322757410363">Tashqi ilova orqali toʻlash uchun inkognito rejimidan chiqib ketasiz. Davom etasizmi?</translation>
<translation id="2878197950673342043">Poster shaklida taxlash</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Oynani joylashtirish</translation>
@@ -549,7 +566,6 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome sozlamalari orqali Xavfsizlik tekshiruvini bajarish uchun avval Tab, keyin Enter tugmalarini bosing</translation>
<translation id="3061707000357573562">Xizmatni tuzatish</translation>
-<translation id="3064966200440839136">Tashqi ilova orqali to‘lash uchun inkognito rejimidan chiqib ketasiz. Davom ettirilsinmi?</translation>
<translation id="306573536155379004">Oʻyin boshlandi.</translation>
<translation id="3080254622891793721">Tasvirlar</translation>
<translation id="3086579638707268289">Internetdagi faoliyatingiz kuzatuv ostida</translation>
@@ -572,7 +588,6 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="315504272643575312">Hisobingiz <ph name="MANAGER" /> domenida boshqariladi.</translation>
<translation id="3157931365184549694">Qayta tiklash</translation>
<translation id="3162559335345991374">Siz ulangan Wi-Fi tarmog‘i tizimga kirishingizni talab qilishi mumkin.</translation>
-<translation id="3167968892399408617">Inkognito rejimida ochilgan sahifalar brauzer yoki qidiruv tarixida saqlanmaydi. Barcha inkognito sahifalari yopilganda qurilmangizda cookie-fayllar kabi izlar qolmaydi. Siz ko‘chirib olgan fayllar va qo‘shilgan xatcho‘plar saqlanib qoladi.</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">Orol</translation>
<translation id="3176929007561373547">Proksi sozlamalarini tekshiring yoki administratordan kerakli parametrlarni so‘rang. Aks holda:
@@ -596,10 +611,12 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="3229041911291329567">Qurilma va brauzer versiyalari axboroti</translation>
<translation id="323107829343500871"><ph name="CREDIT_CARD" /> kartasining CVC kodini kiriting</translation>
<translation id="3234666976984236645">Bu saytda har doim muhim kontent aniqlansin</translation>
+<translation id="3249845759089040423">Jozibali</translation>
<translation id="3252266817569339921">Fransuzcha</translation>
<translation id="3266793032086590337">Qiymat (ziddiyatli)</translation>
<translation id="3268451620468152448">Ochiq ichki oynalar</translation>
<translation id="3270847123878663523">&amp;Qayta tartiblashni bekor qilish</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> qurilmangizga ulanmoqchi</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552"><ph name="ENROLLMENT_DOMAIN" /> tashkilotingiz quyidagi saytlarga sozlamalar va qoidalar kabi ayrim axborotlarni yubordi.</translation>
<translation id="3282497668470633863">Karta egasining ismini kiriting</translation>
@@ -652,6 +669,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="3428151540071562330">Bir yoki bir nechta DnsOverHttpsTemplates server andozasi URI manzillari yaroqsiz va ishlatilmaydi.</translation>
<translation id="3431636764301398940">Kartani bu qurilmaga saqlash</translation>
<translation id="3432601291244612633">Sahifani yopish</translation>
+<translation id="3435738964857648380">Xavfsizlik</translation>
<translation id="3435896845095436175">Yoqish</translation>
<translation id="3438829137925142401">Google hisobingizda saqlangan parollarni ishlatish</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -693,7 +711,10 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="3584299510153766161">Quyidan ikkita teshik ochish</translation>
<translation id="3586931643579894722">Tafsilotlarni yopish</translation>
<translation id="3587738293690942763">Oʻrtacha</translation>
+<translation id="3590643883886679995">Inkognito rejimini tark etganingizdan keyin kirish maʼlumotlari shu qurilmada saqlanadi.</translation>
+<translation id="359126217934908072">Oy/Yil:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Guruh sozlamalarini istalgan vaqtda tiklash mumkin. Yangi guruhga qoʻshilish bir kun vaqt oladi.}=1{Guruh sozlamalarini istalgan vaqtda tiklash mumkin. Yangi guruhga qoʻshilish bir kun vaqt oladi.}other{Guruh sozlamalarini istalgan vaqtda tiklash mumkin. Yangi guruhga qoʻshilish {NUM_DAYS} kun vaqt oladi.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Ilova administrator tomonidan bloklangan</translation>
<translation id="3608932978122581043">Holatini belgilash</translation>
@@ -702,12 +723,12 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="3615877443314183785">Amal qilish muddatini xatosiz kiriting</translation>
<translation id="36224234498066874">Brauzer tarixini tozalash...</translation>
<translation id="362276910939193118">To‘liq tarixni ko‘rsatish</translation>
-<translation id="3625635938337243871">Inkognito rejimini tark etganingizdan keyin kirish maʼlumotlari shu qurilmada saqlanadi.</translation>
<translation id="3630155396527302611">Agar bu dasturga avvaldan tarmoqqa ulanish uchun ruxsat berilgan bo‘lsa, undan ruxsatni olib tashlab, keyin qaytadan ruxsat bering.</translation>
<translation id="3630699740441428070">Qurilmadagi tarmoq administratorlar tomonidan sozlangan va ular tarmoqdagi trafik, siz ochadigan saytlarni kuzatishi mumkin.</translation>
<translation id="3631244953324577188">Biometrik tizimlar</translation>
<translation id="3633738897356909127">Chromeni yangilash tugmasi, Chrome sozlamalari orqali Chromeni yangilash uchun Enter tugmasini bosing</translation>
<translation id="3634530185120165534">Tarnov 5</translation>
+<translation id="3637662659967048211">Google hisobiga saqlash</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Ilova:</translation>
<translation id="3650584904733503804">Tekshiruv muvaffaqiyatli bajarildi</translation>
@@ -748,6 +769,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="3781428340399460090">Och pushti</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Bluetooth qurilmalar</translation>
+<translation id="3787675388804467730">Virtual karta raqami</translation>
<translation id="3787705759683870569">Amal qilish muddati: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Hajmi: 16</translation>
<translation id="3789841737615482174">O‘rnatish</translation>
@@ -767,6 +789,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="3841184659773414994">Faylga ishlov berish vositalari</translation>
<translation id="385051799172605136">Orqaga</translation>
<translation id="3858027520442213535">Sana va vaqtni yangilash</translation>
+<translation id="3881478300875776315">Kamroq qatorlarni koʻrsatish</translation>
<translation id="3884278016824448484">Ziddiyatli qurilma identifikatori</translation>
<translation id="3885155851504623709">Okrug</translation>
<translation id="388632593194507180">Kuzatuv aniqlandi</translation>
@@ -792,6 +815,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="397105322502079400">Hisoblanmoqda...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> saytiga kirish taqiqlangan</translation>
<translation id="3973357910713125165">Chrome sozlamalari orqali Xavfsizlik tekshiruvini bajarish uchun Enter tugmasini bosing</translation>
+<translation id="3986705137476756801">Jonli izohni hozircha faolsizlantirish</translation>
<translation id="3987405730340719549">Chrome bu saytni soxta yoki firibgarlarniki deb hisoblaydi.
Bu ogohlantirish xato chiqqan boʻlsa, https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals sahifasini oching.</translation>
@@ -888,13 +912,14 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="4275830172053184480">Qurilmangizni qayta yuklang</translation>
<translation id="4277028893293644418">Parolni o‘zgartirish</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Bu karta Google hisobingizga saqlandi}other{Bu kartalar Google hisobingizga saqlandi}}</translation>
+<translation id="4287885627794386150">Sinov funksiyasi bor, lekin faol emas</translation>
<translation id="4297502707443874121">Sahifa eskizi: <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Kengaytirish</translation>
<translation id="4300675098767811073">Oʻngdan bir necha teshik ochish</translation>
<translation id="4302514097724775343">Boshlash uchun dinozavrni bosing</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Fayldan foydalanishga ruxsat berilmadi</translation>
-<translation id="4305817255990598646">Almashtirish</translation>
+<translation id="4306529830550717874">Manzil saqlansinmi?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Bloklansin (standart parametr)</translation>
<translation id="4314815835985389558">Sinxronizatsiyani boshqarish</translation>
@@ -921,6 +946,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="4377125064752653719">Siz <ph name="DOMAIN" /> saytiga o‘tmoqchi bo‘ldingiz, lekin server taqdim qilgan sertifikat noshiri tomonidan bekor qilingan. Bu server bergan havfsizlik hisob ma’lumotlari ishonchsizligini bildiradi. Siz firibgarlar saytiga kirgan bo‘lishingiz mumkin.</translation>
<translation id="4378154925671717803">Telefon</translation>
<translation id="4390472908992056574">Maydonchalar</translation>
+<translation id="4406883609789734330">Jonli izoh</translation>
<translation id="4406896451731180161">qidiruv natijalari</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> cookie fayllari</translation>
<translation id="4414290883293381923">Hozirgina shubhali saytda parol kiritdingiz. Chrome hoziroq <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> va boshqa saytlardagi shu parolingizni yangilashni tavsiya qiladi.</translation>
@@ -933,7 +959,6 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">Proksi-server o‘chiq, lekin uning sozlamalari aniq belgilangan.</translation>
<translation id="4464826014807964867">Tashkilotingiz axborot yuborgan saytlar</translation>
-<translation id="4466881336512663640">Toʻldirilgan shakl tozalanadi. Davom ettirilsinmi?</translation>
<translation id="4476953670630786061">Bu shakl xavfsiz emas. Avtomatik kiritish faolsizlantirildi.</translation>
<translation id="4477350412780666475">Keyingi trek</translation>
<translation id="4482953324121162758">Bu sayt tarjima qilinmaydi</translation>
@@ -967,6 +992,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="4594403342090139922">&amp;O‘chirishni bekor qilish</translation>
<translation id="4597348597567598915">Hajmi: 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Taʼsirli</translation>
<translation id="4628948037717959914">Rasm</translation>
<translation id="4631649115723685955">Keshbek ulandi</translation>
<translation id="4636930964841734540">Ma’lumot</translation>
@@ -986,6 +1012,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Tomoni</translation>
+<translation id="4702656508969495934">Jonli izoh yoniq, fokuslash uchun oynani almashtiring</translation>
<translation id="4708268264240856090">Aloqa uzilib qoldi</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Windows tarmoq diagnostikasini ishga tushiring<ph name="END_LINK" /></translation>
@@ -999,6 +1026,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="4738601419177586157"><ph name="TEXT" /> qidiruv taklifi</translation>
<translation id="4742407542027196863">Parollarni boshqarish…</translation>
<translation id="4744603770635761495">Ishga tushirish havolasi</translation>
+<translation id="4749011317274908093">Siz inkognito rejimidasiz</translation>
<translation id="4750917950439032686">Bu saytga shaxsiy ma’lumotlaringiz (parollar yoki bank kartalar kabi) xavfsiz uzatiladi.</translation>
<translation id="4756388243121344051">&amp;Tarix</translation>
<translation id="4758311279753947758">Aloqa ma’lumotini qo‘shish</translation>
@@ -1028,6 +1056,8 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="4813512666221746211">Tarmoq xatoligi</translation>
<translation id="4816492930507672669">Sahifa hajmiga moslash</translation>
<translation id="4819347708020428563">Izohlar standart shaklda tahrirlansinmi?</translation>
+<translation id="4825507807291741242">Qudratli</translation>
+<translation id="4838327282952368871">Xayolparast</translation>
<translation id="484462545196658690">Avto</translation>
<translation id="4850886885716139402">Ko‘rish</translation>
<translation id="485316830061041779">Nemis</translation>
@@ -1164,6 +1194,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="5314967030527622926">Buklet yasash vositasi</translation>
<translation id="5316812925700871227">Soat miliga teskari yo‘nalishda burish</translation>
<translation id="5317780077021120954">Saqlash</translation>
+<translation id="5321288445143113935">Kattalashtirilgan</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" />/<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Aloqa axborotini tanlang</translation>
<translation id="5327248766486351172">Nomi</translation>
@@ -1171,11 +1202,13 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="5332219387342487447">Yetkazib berish usuli</translation>
<translation id="5333022057423422993">Chrome hozirgina oshkor qilingan parol ishlatganini aniqladi. Hisoblaringiz himoyasi uchun saqlangan parollaringizni tekshiring.</translation>
<translation id="5334013548165032829">Batafsil tizim jurnali qaydlari</translation>
+<translation id="5334145288572353250">Manzil saqlansinmi?</translation>
<translation id="5340250774223869109">Ilova bloklandi</translation>
<translation id="534295439873310000">NFC qurilmalar</translation>
<translation id="5344579389779391559">Bu sahifa sizdan pul talab qilishi mumkin</translation>
<translation id="5355557959165512791"><ph name="SITE" /> sayti ochilmadi, bu sayt bekor qilingan sertifikatdan foydalanayotgan bo‘lishi mumkin. Bunday xatolik tarmoq xatoligi va saytga hujumlar bo‘layotganda yuz beradi, lekin keyinroq sayt ishlab ketishi mumkin.</translation>
<translation id="536296301121032821">Tartib-qoida parametrlarini saqlab bo‘lmadi</translation>
+<translation id="5363309033720083897">Seriyali port administrator tomonidan ruxsat etilgan</translation>
<translation id="5371425731340848620">Kartani yangilash</translation>
<translation id="5377026284221673050">“Soatingiz orqada†yoki “Soatingiz oldinda†yoki “&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;â€</translation>
<translation id="5386426401304769735">Bu veb-saytning sertifikatlari zanjiridagi sertifikat SHA-1 algoritmi asosida yozilgan.</translation>
@@ -1184,6 +1217,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="5398772614898833570">Reklamalar bloklandi</translation>
<translation id="5400836586163650660">Kulrang</translation>
<translation id="540969355065856584">Bu <ph name="DOMAIN" /> serveri ekanligini tasdiqlab bo‘lmadi. Uning sertifikati ayni paytda yaroqsiz bo‘lishi mumkin. Balki, server noto‘g‘ri sozlangan yoki kimdir ma’lumotlaringizni o‘g‘rilashga urinayotgan bo‘lishi mumkin.</translation>
+<translation id="541143247543991491">Bulut (umumtizimli)</translation>
<translation id="541416427766103491">Taxlovchi 4</translation>
<translation id="5421136146218899937">Brauzer tarixini tozalash...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> sayti bildirishnoma yuborishga ruxsat so‘ramoqda.</translation>
@@ -1197,6 +1231,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="5455374756549232013">Siyosat vaqti belgisi buzilgan</translation>
<translation id="5457113250005438886">Yaroqsiz</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> va yana <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ta}other{<ph name="CONTACT_PREVIEW" /> va yana <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ta}}</translation>
+<translation id="5463625433003343978">Qurilmalar qidirilmoqda...</translation>
<translation id="5469868506864199649">Italyan</translation>
<translation id="5470861586879999274">O‘zgarishlarni &amp;qaytarish</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1246,7 +1281,6 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="5624120631404540903">Sozlash</translation>
<translation id="5629630648637658800">Siyosat sozlamalarini qo‘llab bo‘lmadi</translation>
<translation id="5631439013527180824">Qurilma tokeni yaroqsiz</translation>
-<translation id="5632627355679805402">Maʼlumotlaringiz <ph name="TIME" /> sanasida <ph name="BEGIN_LINK" />Google hisobingiz paroli<ph name="END_LINK" /> bilan shifrlangan. Sinxronizatsiyani boshlash uchun oʻsha parolingizni kiriting.</translation>
<translation id="5633066919399395251">Firibgarlar ma’lumotlaringizni (rasm, parol, xabar va kredit karta ma’lumotlari kabilarni) o‘g‘irlash yoki o‘chirish maqsadida <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> sayti orqali kompyuteringizga zararli dasturlarni o‘rnatishi mumkin. <ph name="BEGIN_LEARN_MORE_LINK" />Batafsil<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Soxta kontent bloklandi.</translation>
<translation id="5644090287519800334">Tasvirning old tomondagi X oʻqidagi siljish</translation>
@@ -1285,12 +1319,12 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="5785756445106461925">Bundan tashqari, ushbu sahifada xavfli kontent ham aniqlandi. Ma’lumotlarni uzatishda uchinchi tomon resurslarni ko‘rishi mumkin. Yovuz niyatli odamlar esa sahifaga kirishi va uning ko‘rinishini o‘zgartirishi mumkin.</translation>
<translation id="5786044859038896871">Bank karta ma’lumotlari to‘ldirilsinmi?</translation>
<translation id="578633867165174378">Chrome hozirgina oshkor qilingan parol ishlatganini aniqladi. Parolingizni hoziroq yangilashni tavsiya qilamiz.</translation>
-<translation id="5798290721819630480">Oʻzgarishlar bekor qilinsinmi?</translation>
<translation id="5803412860119678065"><ph name="CARD_DETAIL" /> kartangiz ma’lumotlari to‘ldirilsinmi?</translation>
<translation id="5804241973901381774">Ruxsatlar</translation>
<translation id="5804427196348435412">NFC qurilmalarni ishlatish</translation>
<translation id="5810442152076338065"><ph name="DOMAIN" /> domeniga ulanish eski shifrlar to‘plami bilan shifrlangan.</translation>
<translation id="5813119285467412249">&amp;Qo‘shish amaliga qaytish</translation>
+<translation id="5817918615728894473">Ulanish</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Toʻlov vaqtida bu kartadan haq olinadi, lekin uning haqiqiy raqamlari bu saytga ulashilmaydi. Qoʻshimcha himoya maqsadida vaqtinchalik CVC kod yaratiladi.}other{Toʻlov vaqtida tanlangan kartadan haq olinadi, lekin uning haqiqiy raqamlari bu saytga ulashilmaydi. Qoʻshimcha himoya maqsadida vaqtinchalik CVC kod yaratiladi.}}</translation>
<translation id="5826507051599432481">Umumiy Ism (CN)</translation>
<translation id="5838278095973806738">Bu saytda muhim ma’lumotlaringizni (parollar va bank kartalar kabi) kiritmasligingiz kerak, chunki firibgarlar tomonidan o‘g‘irlanishi mumkin.</translation>
@@ -1298,6 +1332,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="5855253129151731373">Sayt nomi mana bunga oʻxshash ekan: <ph name="LOOKALIKE_DOMAIN" />. Odatda shubhali kimsalar domen nomida kichik oʻzgarishlar kiritib, saytlarga soxta nusxalar yasaydi.
Bu ogohlantirish xato chiqqan boʻlsa, https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals sahifasini oching.</translation>
+<translation id="5860033963881614850">O‘chiq</translation>
<translation id="5862579898803147654">Taxlovchi 8</translation>
<translation id="5863847714970149516">Bu sahifa sizdan pul talab qilishi mumkin</translation>
<translation id="5866257070973731571">Telefon raqamini qo‘shing</translation>
@@ -1314,6 +1349,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="5913377024445952699">Ekranni tasvirga olish pauza qilindi</translation>
<translation id="59174027418879706">Yoqilgan</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 ta cookie-fayl}other{ # ta cookie-fayl}}</translation>
<translation id="5921185718311485855">Yoniq</translation>
<translation id="5921639886840618607">Ushbu karta Google hisobingizda saqlansinmi?</translation>
<translation id="5922853866070715753">Deyarli tayyor</translation>
@@ -1333,6 +1369,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="5989320800837274978">Sozlangan proksi serverlar ham, PAC-skriptlar URL manzillari ham ko‘rsatilmagan.</translation>
<translation id="5992691462791905444">Engineering-Z shaklida taxlash</translation>
<translation id="6000758707621254961">“<ph name="SEARCH_TEXT" />†uchun <ph name="RESULT_COUNT" /> ta natija</translation>
+<translation id="6006484371116297560">Klassik</translation>
<translation id="6008122969617370890">N dan 1 gacha tartibda</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Parollarni tekshiring</translation>
@@ -1354,6 +1391,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="6045164183059402045">Boshlangʻich chiziqlar andozasi</translation>
<translation id="6047233362582046994">Xavfli bo‘lsa ham, zararli ilovalar hali olib tashlanmagan bo‘lsa ham bu saytni ochishni xohlasangiz, <ph name="BEGIN_LINK" />bu yerga bosing<ph name="END_LINK" />.</translation>
<translation id="6047927260846328439">Bu kontent zararli dastur o‘rnatishga yoki shaxsiy ma’lumotlaringizni o‘g‘irlashga urinishi mumkin. <ph name="BEGIN_LINK" />Baribir ko‘rsatilsin<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">To‘liq ekran rejimidan chiqish uchun |<ph name="ACCELERATOR" />| tugmasini bosib turing</translation>
<translation id="6049488691372270142">Sahifa yetkazib berilishi</translation>
<translation id="6051221802930200923"><ph name="SITE" /> sayti ochilmadi, bu sayt taqilgan sertifikatdan foydalanayotgan bo‘lishi mumkin. Bunday xatolik tarmoq xatoligi va saytga hujumlar bo‘layotganda yuz beradi, lekin keyinroq sayt ishlab ketishi mumkin.</translation>
<translation id="6051898664905071243">Sahifalar soni:</translation>
@@ -1370,6 +1408,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="610911394827799129">Google hisobingiz orqali bajargan internetdagi faoliyatingizni <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> orqali ko‘rishingiz mumkin.</translation>
<translation id="6116338172782435947">Klipbordga nusxalangan matn va rasmlarni ko‘rish</translation>
<translation id="6120179357481664955">UPI identifikatori eslab qolinsinmi?</translation>
+<translation id="6123290840358279103">Virtual kartani ochish</translation>
<translation id="6124432979022149706">Chrome korporativ konnektorlari</translation>
<translation id="6146055958333702838">Kabel ulanishlarini tekshiring, router, modem yoki boshqa tarmoq qurilmalarini o‘chirib yoqing.</translation>
<translation id="614940544461990577">Quyidagilarni bajaring:</translation>
@@ -1405,6 +1444,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="6289939620939689042">Sahifa rangi</translation>
<translation id="6290238015253830360">Tavsiya etiladigan maqolalar shu yerda chiqadi</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC kod:</translation>
<translation id="6302269476990306341">Chrome ichidagi Google Assistent toʻxtatilmoqda</translation>
<translation id="6305205051461490394"><ph name="URL" /> bilan aloqa o‘rnatib bo‘lmadi.</translation>
<translation id="6312113039770857350">Veb-sahifa mavjud emas</translation>
@@ -1430,6 +1470,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="6390200185239044127">Z-simon yarim taxlash</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117"><ph name="ORIGIN_NAME" /> saytidan bu manzilga joylashni administrator taqiqlagan</translation>
+<translation id="6398765197997659313">To‘liq ekran rejimidan chiqish</translation>
<translation id="6401136357288658127">Bu parametr eskirgan. Oʻrniga <ph name="NEW_POLICY" /> parametridan foydalaning.</translation>
<translation id="6404511346730675251">Xatcho‘pni tahrirlash</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1442,7 +1483,6 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="6428450836711225518">Telefon raqamingizni tasdiqlang</translation>
<translation id="6433490469411711332">Aloqa ma’lumotini tahrirlash</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> serveri ulanish so‘rovini rad etdi.</translation>
-<translation id="6434309073475700221">Bekor qilish</translation>
<translation id="6440503408713884761">Rad etilgan</translation>
<translation id="6443406338865242315">Oʻrnatilgan kengaytma va plaginlar</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1485,6 +1525,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="6624427990725312378">Aloqa ma’lumoti</translation>
<translation id="6626291197371920147">Karta raqamini xatosiz kiriting</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> qidiruvi</translation>
+<translation id="6630043285902923878">USB qurilmalar qidirilmoqda...</translation>
<translation id="6630809736994426279">Firibgarlar <ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> sayti orqali Mac kompyuteringizga shaxsiy ma’lumotlarni (masalan, rasmlar, parollar, xabarlar va kredit karta ma’lumotlari) o‘g‘irlash yoki o‘chirish maqsadida zararli ilovalarni o‘rnatishi mumkin. <ph name="BEGIN_LEARN_MORE_LINK" />Batafsil<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Tozalash</translation>
@@ -1500,6 +1541,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="6671697161687535275">Bu taklif Chromium’dan o‘chirib tashlansinmi?</translation>
<translation id="6685834062052613830">Hisobdan chiqing va sozlash jarayonini nihoyasiga yetkazing</translation>
<translation id="6687335167692595844">Shrift oʻlchami talab qilindi</translation>
+<translation id="6688743156324860098">Yangilash…</translation>
<translation id="6689249931105087298">Qora nuqta tejalishiga aloqador</translation>
<translation id="6689271823431384964">Hisobingizga kirganingiz uchun Chrome kartalarni Google hisobingizga saqlashni taklif qilmoqda. Buni sozlamalar orqali oʻzgartirish mumkin. Karta egasining ismi hisobingizdan olinadi.</translation>
<translation id="6698381487523150993">Yaratilgan sanasi:</translation>
@@ -1515,6 +1557,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="6744009308914054259">Aloqa o‘rnatilguncha Yuklanmalar jildini ochib oflayn maqolalar o‘qishingiz mumkin.</translation>
<translation id="6753269504797312559">Siyosatdagi qiymat</translation>
<translation id="6757797048963528358">Qurilma uyqu rejimiga o‘tib qoldi.</translation>
+<translation id="6767985426384634228">Manzil yangilansinmi?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Siyohrang</translation>
@@ -1537,6 +1580,7 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Mutolaani osonlashtirish uchun bu sahifa Chrome tomonidan soddalashtirildi. Chrome asl sahifani xavfli ulanish orqali yuklab oldi.</translation>
<translation id="6891596781022320156">Qoida qiymati qo‘llab-quvvatlanmaydi.</translation>
+<translation id="6895143722905299846">Virtual raqam:</translation>
<translation id="6895330447102777224">Kartangiz tasdiqlandi</translation>
<translation id="6897140037006041989">User Agent</translation>
<translation id="6898699227549475383">Tashkilot (O)</translation>
@@ -1572,10 +1616,10 @@ Aks holda bu maxfiylik sozlamalaringiz tomonidan bloklanadi. Bunda siz ochgan sa
<translation id="7004583254764674281">Kartalarni tezroq tasdiqlash uchun Windows Hello ishlating</translation>
<translation id="7006930604109697472">Baribir yuborilsin</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Hajmni oʻzgartirish sozlamalari</translation>
<translation id="7014741021609395734">Masshtab</translation>
<translation id="7016992613359344582">To‘lov bir martalik, qayta bo‘lishi yoki umuman bo‘lmasligi ham mumkin.</translation>
<translation id="7029809446516969842">Parollar</translation>
+<translation id="7030436163253143341">Sertifikat yaroqsiz</translation>
<translation id="7031646650991750659">Google Play Marketdan oʻrnatilgan ilovalar</translation>
<translation id="7050187094878475250">Siz <ph name="DOMAIN" /> domenini ochmoqchi bo‘ldingiz, lekin server taqdim qilgan sertifikat juda uzoq ishonchsiz muddatga ega.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Bu karta saqlanmadi}other{Bu kartalar saqlanmadi}}</translation>
@@ -1645,12 +1689,14 @@ Batafsil axborot:
<translation id="7300012071106347854">Koʻk kobalt</translation>
<translation id="7302712225291570345">“<ph name="TEXT" />â€</translation>
<translation id="7304030187361489308">Baland</translation>
+<translation id="7305756307268530424">Sekinroq ishga tushirish</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Internetga ulanish yuzasidan yordam</translation>
<translation id="7323804146520582233">“<ph name="SECTION" />†bandini yopish</translation>
<translation id="733354035281974745">Qurilmadagi mahalliy hisob qayta tayinlanishi</translation>
<translation id="7333654844024768166">Hozirgina shubhali saytda parol kiritdingiz. Chromium hoziroq <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> va boshqa saytlardagi shu parolingizni yangilashni tavsiya qiladi.</translation>
<translation id="7334320624316649418">&amp;Qayta tartiblashni qayta bajarish</translation>
+<translation id="7337248890521463931">Koʻproq qatorlarni koʻrsatish</translation>
<translation id="7337706099755338005">Sizdagi tizimda ishlamaydi.</translation>
<translation id="733923710415886693">Sertifikatning ishonchlilik belgilari haqidagi ma’lumot server tomonidan taqdim etilmadi.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1658,6 +1704,7 @@ Batafsil axborot:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Buyruqlar qatori</translation>
<translation id="7359588939039777303">Reklamalar bloklandi.</translation>
+<translation id="7363096869660964304">Inkognito oynasidagi bajargan ishlaringiz va tashrif buyurgan saytlaringiz tizim administratori va internet-provayderingizga ko‘rinadi.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome sozlamalari orqali manzillarni kiritish va boshqarish uchun avval Tab, keyin Enter tugmasini bosing</translation>
<translation id="7365849542400970216">Qurilmadan foydalanish haqidagi axborot berilsinmi?</translation>
<translation id="7372973238305370288">qidiruv natijasi</translation>
@@ -1668,7 +1715,9 @@ Batafsil axborot:
<translation id="7378594059915113390">Media boshqaruv elementlari</translation>
<translation id="7378627244592794276">Yo‘q</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Tegishli emas</translation>
<translation id="7390545607259442187">Kartani tasdiqlash</translation>
+<translation id="7392089738299859607">Manzilni yangilash</translation>
<translation id="7399802613464275309">Xavfsizlik tekshiruvi</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> qurilmangiz nazorat ostida</translation>
@@ -1683,6 +1732,7 @@ Batafsil axborot:
&lt;li&gt;Dasturni butunlay kompyuterdan olib tashlash haqida ma’lumot olish uchun &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome yordam markaziga&lt;/a&gt; tashrif buyuring.
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Sevimli</translation>
<translation id="7416351320495623771">Parollarni boshqarish…</translation>
<translation id="7419106976560586862">Profil saqlanadigan jild</translation>
<translation id="7437289804838430631">Aloqa ma’lumotini qo‘shish</translation>
@@ -1698,7 +1748,7 @@ Batafsil axborot:
<translation id="7481312909269577407">Oldinga</translation>
<translation id="7485870689360869515">Ma‘lumotlar topilmadi.</translation>
<translation id="7495528107193238112">Bu kontent bloklandi. Muammoni yechish uchun sayt egasiga murojaat qiling.</translation>
-<translation id="7498234416455752244">Tahrirlashda davom etish</translation>
+<translation id="7498193950643227031">Oʻlchami oʻzgartirilsa, ishlashida xato yuz berishi mumkin. <ph name="SETTINGS" /> orqali ilovalar hajmi oʻzgartirilishini cheklash mumkin.</translation>
<translation id="7503664977220660814">Hozirgina shubhali saytda parol kiritdingiz. Chromium hoziroq <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> va boshqa saytlardagi shu parolingizni tekshirishni tavsiya qiladi.</translation>
<translation id="7508255263130623398">Qurilmaning qaytarilgan identifikatori bo‘sh yoki joriy qurilma identifikatoriga mos kelmaydi</translation>
<translation id="7508870219247277067">Yashil avokado</translation>
@@ -1718,6 +1768,7 @@ Batafsil axborot:
<translation id="7548892272833184391">Ulanish xatoliklarini hal qilish</translation>
<translation id="7549584377607005141">Veb-sahifaning to‘g‘ri ko‘rsatilishi uchun avval kiritilgan ma’lumotlar kerak bo‘ladi. Ularni qayta jo‘natish mumkin, lekin bu holatda sahifada bajarilgan barcha amallarni qaytadan bajarish kerak bo‘ladi.</translation>
<translation id="7550637293666041147">Qurilmangiz va Chrome foydalanuvchilari nomi</translation>
+<translation id="755279583747225797">Funksiyaning sinov davri faol</translation>
<translation id="7552846755917812628">Quyidagi amallarni bajarib ko‘ring:</translation>
<translation id="7554475479213504905">Yangilash va baribir ochish</translation>
<translation id="7554791636758816595">Yangi varaq</translation>
@@ -1736,7 +1787,6 @@ Batafsil axborot:
<translation id="7610193165460212391">Diapazondan tashqaridagi qiymat: <ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Muddati: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, Chrome sozlamalari orqali parollaringizni boshqarish uchun avval Tab, keyin esa Enter tugmasini bosing</translation>
-<translation id="7615602087246926389">Sizda allaqachon boshqa Google hisobi paroli orqali shifrlangan ma’lumotlar mavjud. O‘sha parolni quyida kiriting.</translation>
<translation id="7616645509853975347">Brauzeringizda administrator tomonidan Chrome korporativ konnektorlari yoqilgan. Bu konnektorlar ayrim axborotlaringizdan foydalana oladi.</translation>
<translation id="7619838219691048931">Oxirgi varaq</translation>
<translation id="762844065391966283">Bir obyektdan</translation>
@@ -1801,13 +1851,12 @@ Batafsil axborot:
<translation id="782886543891417279">Siz ulangan Wi-Fi (<ph name="WIFI_NAME" />) tarmog‘i hisob sahifasida tizimga kirishingizni talab qilishi mumkin.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Hech qanday}=1{1 ta ilova (<ph name="EXAMPLE_APP_1" />)}=2{2 ta ilova (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# ta ilova (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Inkognito oynasidagi bajargan ishlaringiz va tashrif buyurgan saytlaringiz tizim administratori va internet-provayderingizga ko‘rinadi.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Shu turdagi fayllarni ochish.</translation>
<translation id="7862185352068345852">Sayt tark etilsinmi?</translation>
<translation id="7865448901209910068">Eng tez</translation>
<translation id="7874263914261512992">Hozirgina shubhali saytda parol kiritdingiz. Chrome hoziroq <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> va boshqa saytlardagi shu parolingizni tekshirishni tavsiya qiladi.</translation>
<translation id="7878562273885520351">Parolingiz o‘g‘irlangan bo‘lishi mumkin</translation>
+<translation id="7880146494886811634">Manzilni saqlash</translation>
<translation id="7882421473871500483">Jigarrang</translation>
<translation id="7887683347370398519">CVC-kodni tekshiring va qayta urinib ko‘ring.</translation>
<translation id="7887885240995164102">Tasvir ustida tasvir rejimiga kirish</translation>
@@ -1815,6 +1864,7 @@ Batafsil axborot:
<translation id="7894280532028510793">Xatosiz kiritilgan boʻlsa, <ph name="BEGIN_LINK" />Tarmoq diagnostikasini<ph name="END_LINK" /> ishga tushiring.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Noma’lum</translation>
+<translation id="793209273132572360">Manzil yangilansinmi?</translation>
<translation id="7932579305932748336">Muqovalash</translation>
<translation id="79338296614623784">Telefon raqamini xatosiz kiriting</translation>
<translation id="7934052535022478634">Toʻlov bajarildi</translation>
@@ -1885,6 +1935,7 @@ Batafsil axborot:
<translation id="8175796834047840627">Hisobingizga kirganingiz uchun Chrome kartalarni Google hisobingizga saqlashni taklif qilmoqda. Buni sozlamalar orqali oʻzgartirish mumkin.</translation>
<translation id="8176440868214972690">Bu qurilma administratori quyidagi saytlarga sozlamalar va qoidalar kabi ayrim axborotlarni yubordi.</translation>
<translation id="8184538546369750125">Global parametrdan foydalanish (ruxsat berish)</translation>
+<translation id="8193086767630290324">Maʼlumotlar bilan bajariladigan amallar maxfiy hisoblanadi</translation>
<translation id="8194797478851900357">&amp;Ko‘chirib o‘tkazishni bekor qilish</translation>
<translation id="8201077131113104583">“<ph name="EXTENSION_ID" />†identifikatoriga ega kengaytmani yangilash uchun yaroqsiz URL kiritildi</translation>
<translation id="8202097416529803614">Buyurtma ma’lumotlari</translation>
@@ -1907,6 +1958,7 @@ Batafsil axborot:
<translation id="8249296373107784235">Bekor qilish</translation>
<translation id="8249320324621329438">Oxirgi yuklanish vaqti:</translation>
<translation id="8253091569723639551">To‘lov manzilini kiriting</translation>
+<translation id="8257387598443225809">Bu ilova mobil qurilmalar uchun ishlab chiqilgan</translation>
<translation id="825929999321470778">Saqlangan barcha parollar ko‘rsatilsin</translation>
<translation id="8261506727792406068">O‘chirish</translation>
<translation id="8262952874573525464">Quyi chekkasini tikish</translation>
@@ -2030,7 +2082,6 @@ Batafsil axborot:
<translation id="8719528812645237045">Yuqoridan bir nechta teshik ochish</translation>
<translation id="8725066075913043281">Qayta urinib ko‘ring</translation>
<translation id="8726549941689275341">Sahifa hajmi:</translation>
-<translation id="8728672262656704056">Siz inkognito rejimiga o‘tdingiz</translation>
<translation id="8730621377337864115">Tayyor</translation>
<translation id="8731544501227493793">Parollarni boshqarish tugmasi, Chrome sozlamalari orqali parollarni koʻrish va boshqarish uchun Enter tugmasini bosing</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> qurilmangiz <ph name="MANAGER" /> domenida boshqariladi</translation>
@@ -2107,6 +2158,7 @@ Batafsil axborot:
<translation id="9020542370529661692">Bu sahifa <ph name="TARGET_LANGUAGE" /> tiliga o‘girildi.</translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(yaroqsiz)</translation>
+<translation id="9030265603405983977">Monoxrom</translation>
<translation id="9035022520814077154">Xavfsizlik xatosi</translation>
<translation id="9038649477754266430">Sahifalar tezroq yuklanishi uchun oldindan yuklash xizmatidan foydalaning</translation>
<translation id="9039213469156557790">Bundan tashqari, ushbu sahifada xavfli kontent ham aniqlandi. Ma’lumotlarni uzatishda uchinchi tomon resurslarni ko‘rishi mumkin. Yovuz niyatli odamlar esa sahifaga kirishi va uning xatti-harakatini o‘zgartirishi mumkin.</translation>
@@ -2130,6 +2182,7 @@ Batafsil axborot:
<translation id="91108059142052966">Maxfiy axborotlar koʻrinib turganda administrator ekran namoyishini <ph name="APPLICATION_TITLE" /> uchun taqiqlagan</translation>
<translation id="9114524666733003316">Karta tasdiqlanmoqda...</translation>
<translation id="9114581008513152754">Bu brauzer kompaniya yoki tashkilot boshqaruvida emas. Bu qurilmadagi amallar Chromedan tashqarida boshqarilishi mumkin. <ph name="BEGIN_LINK" />Batafsil<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Yangi</translation>
<translation id="9119042192571987207">Yuklangan</translation>
<translation id="9128016270925453879">Qoidalar yuklandi</translation>
<translation id="9128870381267983090">Tarmoqqa ulanish</translation>
@@ -2148,6 +2201,7 @@ Batafsil axborot:
<translation id="9170848237812810038">&amp;Bekor qilish</translation>
<translation id="9171296965991013597">Ilovadan chiqilsinmi?</translation>
<translation id="9173282814238175921">Bitta hujjat/Yangi varaq</translation>
+<translation id="9173995187295789444">Bluetooth qurilmalar qidirilmoqda...</translation>
<translation id="917450738466192189">Server sertifikati yaroqsiz.</translation>
<translation id="9174917557437862841">Varaqlar orasida almashtirish tugmasi, shu varaqqa almashish uchun Enter tugmasini bosing</translation>
<translation id="9179703756951298733">Toʻlov va kredit karta axborotini Chrome sozlamalari orqali boshqarish</translation>
diff --git a/chromium/components/strings/components_strings_vi.xtb b/chromium/components/strings/components_strings_vi.xtb
index ebb2ef75833..0ee206e50e4 100644
--- a/chromium/components/strings/components_strings_vi.xtb
+++ b/chromium/components/strings/components_strings_vi.xtb
@@ -39,6 +39,7 @@
<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>
<translation id="1110994991967754504">Chá»n quyá»n cho <ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Hoàn tác sắp xếp lại</translation>
+<translation id="1123753900084781868">Tính năng Phụ đỠtrực tiếp hiện không hoạt động</translation>
<translation id="1125573121925420732">Cảnh báo hiển thị khi trang web cập nhật bảo mật là Ä‘iá»u bình thÆ°á»ng. Việc này sẽ sá»›m được cải tiến.</translation>
<translation id="112840717907525620">Bộ nhớ đệm chính sách OK</translation>
<translation id="1130564665089811311">Nút Dịch trang, nhấn phím Enter để dịch trang này bằng Google Dịch</translation>
@@ -74,6 +75,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="1240347957665416060">Tên thiết bị của bạn</translation>
<translation id="124116460088058876">Ngôn ngữ khác</translation>
<translation id="1243027604378859286">Tác giả:</translation>
+<translation id="1246424317317450637">In đậm</translation>
<translation id="1250759482327835220">Äể thanh toán nhanh hÆ¡n vào lần tá»›i, hãy lÆ°u địa chỉ thanh toán, tên và thẻ vào Tài khoản Google của bạn.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (được đồng bộ hóa)</translation>
<translation id="1256368399071562588">&lt;p&gt;Nếu bạn cố truy cập vào một trang web nhưng vẫn không mở được, trước tiên, hãy tìm cách khắc phục lỗi này bằng các bước khắc phục sự cố dưới đây:&lt;/p&gt;
@@ -156,6 +158,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="1476595624592550506">Thay đổi mật khẩu của bạn</translation>
<translation id="1484290072879560759">Chá»n địa chỉ giao hàng</translation>
<translation id="1492194039220927094">Gửi thông báo đẩy khi có chính sách:</translation>
+<translation id="1495677929897281669">Quay lại thẻ</translation>
<translation id="1501859676467574491">Hiển thị các thẻ trong Tài khoản Google của bạn</translation>
<translation id="1507202001669085618">&lt;p&gt;Bạn sẽ gặp lỗi này nếu đang sử dụng cổng Wi-Fi yêu cầu bạn đăng nhập để có thể vào mạng.&lt;/p&gt;
&lt;p&gt;Äể khắc phục lá»—i này, hãy nhấp vào &lt;strong&gt;Kết nối&lt;/strong&gt; trên trang mà bạn Ä‘ang cố mở.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="1532118530259321453">Trang này cho biết</translation>
<translation id="153384715582417236">Hiện chưa có nội dung</translation>
<translation id="1536390784834419204">Dịch trang</translation>
+<translation id="1539840569003678498">Thá»i gian gá»­i báo cáo:</translation>
<translation id="154408704832528245">Chá»n địa chỉ giao hàng</translation>
<translation id="1549470594296187301">Bạn phải bật JavaScript để sử dụng tính năng này.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="1682696192498422849">Cạnh ngắn trước</translation>
<translation id="168693727862418163">Giá trị chính sách này không xác thực được dựa vào giản đồ và sẽ bị bỠqua.</translation>
<translation id="168841957122794586">Chứng chỉ máy chủ chứa khóa mật mã yếu.</translation>
+<translation id="1696290444144917273">Xem thông tin chi tiết vỠthẻ ảo</translation>
<translation id="1697532407822776718">Bạn đã hoàn tất!</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{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 Ä‘á» từ ngày mai. Ä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.}other{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 Ä‘á» # ngày trong tÆ°Æ¡ng lai. Ä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="1710259589646384581">OS</translation>
+<translation id="1711234383449478798">Äã bá» qua do bạn không đặt <ph name="POLICY_NAME" /> thành <ph name="VALUE" />.</translation>
<translation id="1712552549805331520"><ph name="URL" /> muốn lưu trữ vĩnh viễn dữ liệu trên máy tính cục bộ của bạn</translation>
<translation id="1713628304598226412">Khay 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Há»™p thÆ° 3</translation>
<translation id="1718029547804390981">Tài liệu quá lớn nên không thể chú thích được</translation>
<translation id="1721424275792716183">TrÆ°á»ng * là bắt buá»™c</translation>
+<translation id="1727613060316725209">Chứng chỉ hợp lệ</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>
<translation id="173080396488393970">Loại thẻ này không được hỗ trợ</translation>
@@ -246,7 +253,6 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
yêu cầu của bạn là truy cập vào <ph name="SITE" />. Nhà Ä‘iá»u hành trang web có thể
dựa vào chính sách nguồn gốc để định cấu hình bảo mật và các thuộc tính khác cho trang web.</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">Vui lòng cập nhật cụm mật khẩu đồng bộ hóa của bạn.</translation>
<translation id="1787142507584202372">Thẻ đang mở của bạn xuất hiện ở đây</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, có nhiá»u thao tác, nhấn phím Tab để chuyển giữa các thao tác đó</translation>
@@ -279,6 +285,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<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>
<translation id="192020519938775529">{COUNT,plural, =0{Không có}=1{1 trang web}other{# trang web}}</translation>
+<translation id="1924727005275031552">Má»›i</translation>
<translation id="1945968466830820669">Bạn có thể mất quyá»n truy cập vào tài khoản của tổ chức mình hoặc bị đánh cắp danh tính. Chromium khuyên bạn nên thay đổi mật khẩu ngay bây giá».</translation>
<translation id="1947454675006758438">Dập ghim trên cùng bên phải</translation>
<translation id="1958218078413065209">Äiểm cao nhất của bạn là <ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="2042213636306070719">Khay 7</translation>
<translation id="204357726431741734">Äăng nhập để sá»­ dụng mật khẩu đã lÆ°u trong Tài khoản Google của bạn</translation>
<translation id="2053111141626950936">Các trang viết bằng <ph name="LANGUAGE" /> sẽ không được dịch.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Khi chế Ä‘á»™ Ä‘iá»u khiển này bật và trạng thái là Ä‘ang hoạt Ä‘á»™ng, Chrome sẽ xác định xem hoạt Ä‘á»™ng duyệt web gần đây của bạn giống vá»›i nhóm đông ngÆ°á»i hoặc "nhóm thuần tập" nào nhất. Các nhà quảng cáo có thể chá»n quảng cáo cho nhóm này và hoạt Ä‘á»™ng duyệt web sẽ được lÆ°u giữ riêng tÆ° trên thiết bị của bạn. Nhóm của bạn được cập nhật hằng ngày.}=1{Khi chế Ä‘á»™ Ä‘iá»u khiển này bật và trạng thái là Ä‘ang hoạt Ä‘á»™ng, Chrome sẽ xác định xem hoạt Ä‘á»™ng duyệt web gần đây của bạn giống vá»›i nhóm đông ngÆ°á»i hoặc "nhóm thuần tập" nào nhất. Các nhà quảng cáo có thể chá»n quảng cáo cho nhóm này và hoạt Ä‘á»™ng duyệt web sẽ được lÆ°u giữ riêng tÆ° trên thiết bị của bạn. Nhóm của bạn được cập nhật hằng ngày.}other{Khi chế Ä‘á»™ Ä‘iá»u khiển này bật và trạng thái là Ä‘ang hoạt Ä‘á»™ng, Chrome sẽ xác định xem hoạt Ä‘á»™ng duyệt web gần đây của bạn giống vá»›i nhóm đông ngÆ°á»i hoặc "nhóm thuần tập" nào nhất. Các nhà quảng cáo có thể chá»n quảng cáo cho nhóm này và hoạt Ä‘á»™ng duyệt web sẽ được lÆ°u giữ riêng tÆ° trên thiết bị của bạn. Nhóm của bạn được cập nhật {NUM_DAYS} ngày má»™t lần.}}</translation>
<translation id="2053553514270667976">Mã zip</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 đỠxuất}other{# đỠxuất}}</translation>
<translation id="2071692954027939183">Các thông báo tá»± Ä‘á»™ng bị chặn do bạn thÆ°á»ng xuyên không cho phép các thông báo đó</translation>
<translation id="2079545284768500474">Hoàn tác</translation>
<translation id="20817612488360358">Cài đặt proxy hệ thống được đặt để sử dụng nhưng cấu hình proxy rõ ràng cũng được chỉ định.</translation>
<translation id="2082238445998314030">Kết quả <ph name="RESULT_NUMBER" /> trong tổng số <ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Lưu…</translation>
<translation id="2088086323192747268">Nút Quản lý dữ liệu đồng bộ hóa, hãy nhấn Enter để quản lý loại thông tin bạn đồng bộ hóa trong phần Cài đặt của Chrome</translation>
<translation id="2091887806945687916">Âm thanh</translation>
<translation id="2094505752054353250">Miá»n không khá»›p</translation>
@@ -379,6 +388,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="2317259163369394535"><ph name="DOMAIN" /> yêu cầu tên ngÆ°á»i dùng và mật khẩu.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, hết hạn vào <ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Cài đặt do quản trị viên kiểm soát</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> muốn ghép nối</translation>
<translation id="2344028582131185878">Tải xuống tự động</translation>
<translation id="2346319942568447007">Hình ảnh bạn đã sao chép</translation>
<translation id="2354001756790975382">Dấu trang khác</translation>
@@ -386,8 +396,10 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="2355395290879513365">Kẻ tấn công có thể thấy những hình ảnh mà bạn đang xem trên trang web này và lừa bạn bằng cách sửa đổi những hình ảnh đó.</translation>
<translation id="2356070529366658676">Yêu cầu</translation>
<translation id="2357481397660644965">Thiết bị của bạn do <ph name="DEVICE_MANAGER" /> quản lý, còn tài khoản của bạn do <ph name="ACCOUNT_MANAGER" /> quản lý.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Chưa đến 1 ngày}=1{Sau 1 ngày nữa}other{Sau {NUM_DAYS} ngày nữa}}</translation>
<translation id="2359629602545592467">Nhiá»u</translation>
<translation id="2359808026110333948">Tiếp tục</translation>
+<translation id="2359961752320758691">Äã áp dụng số thẻ ảo của bạn.</translation>
<translation id="2367567093518048410">Mức độ</translation>
<translation id="2372464001869762664">Sau khi bạn xác nhận, thông tin thẻ trong Tài khoản Google của bạn sẽ được chia sẻ với trang web này. Hãy tìm CVC (Mã xác minh thẻ) trong phần thông tin chi tiết vỠTài khoản Plex của bạn.</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -398,6 +410,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="239429038616798445">Phương thức giao hàng này không có sẵn. Hãy thử một phương thức khác.</translation>
<translation id="2396249848217231973">&amp;Hoàn tác xóa</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">CÅ©</translation>
<translation id="2413528052993050574">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ó thể đã bị thu hồ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>
<translation id="2414886740292270097">Tối</translation>
<translation id="2438874542388153331">Äục 4 lá»— bên phải</translation>
@@ -425,10 +438,10 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="2521385132275182522">Dập ghim dưới cùng bên phải</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>
-<translation id="2526590354069164005">Màn hình ná»n</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{và 1 miá»n khác}other{và # miá»n khác}}</translation>
<translation id="2536110899380797252">Thêm địa chỉ</translation>
<translation id="2539524384386349900">Phát hiện</translation>
+<translation id="2541219929084442027">Những trang mà bạn xem trong các thẻ Ẩn danh sẽ không bị lÆ°u lại trong nhật ký của trình duyệt, kho cookie hoặc nhật ký tìm kiếm sau khi bạn đóng tất cả các thẻ Ẩn danh. Má»i tệp bạn tải xuống hoặc dấu trang mà bạn tạo sẽ được giữ nguyên.</translation>
<translation id="2544644783021658368">Một tài liệu</translation>
<translation id="254947805923345898">Giá trị của chính sách là không hợp lệ.</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> đã gửi phản hồi không hợp lệ.</translation>
@@ -448,6 +461,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="2629325967560697240">Äể tận dụng mức bảo mật cao nhất của Chrome, hãy <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />bật chế Ä‘á»™ bảo vệ tăng cÆ°á»ng<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Không thể tìm thấy địa chỉ IP của máy chủ <ph name="HOST_NAME" />.</translation>
<translation id="2639739919103226564">Trạng thái:</translation>
+<translation id="264810637653812429">Không tìm thấy thiết bị tương thích nào.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, nhấn phím Tab rồi nhấn Enter để Xóa lịch sá»­ duyệt web, cookie, bá»™ nhá»› đệm và nhiá»u ná»™i dung khác trong phần cài đặt của Chrome</translation>
<translation id="2650446666397867134">Truy cập vào tệp bị từ chối</translation>
@@ -494,6 +508,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<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="2807052079800581569">Vị trí Y của hình ảnh</translation>
+<translation id="2820957248982571256">Äang quét...</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>
@@ -501,6 +516,8 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="2850739647070081192">Invite (Phong bì)</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="2859806420264540918">Trang web này hiển thị quảng cáo xâm nhập hoặc quảng cáo gây hiểu nhầm.</translation>
+<translation id="287596039013813457">Thân thiện</translation>
+<translation id="2876489322757410363">Äang thoát khá»i chế Ä‘á»™ Ẩn danh để thanh toán qua má»™t ứng dụng bên ngoài. Bạn muốn tiếp tục?</translation>
<translation id="2878197950673342043">Gấp kiểu áp phích</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Vị trí cửa sổ</translation>
@@ -550,7 +567,6 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="3060227939791841287">C9 (Phong bì)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, nhấn phím Tab rồi nhấn Enter để chạy quy trình Kiểm tra an toàn trong phần cài đặt của Chrome</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>
<translation id="306573536155379004">Äã bắt đầu trò chÆ¡i.</translation>
<translation id="3080254622891793721">Äồ há»a</translation>
<translation id="3086579638707268289">Hoạt động của bạn trên web đang bị giám sát</translation>
@@ -573,7 +589,6 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="315504272643575312">Tài khoản của bạn do <ph name="MANAGER" /> quản lý.</translation>
<translation id="3157931365184549694">Khôi phục</translation>
<translation id="3162559335345991374">Wi-Fi 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="3167968892399408617">Các trang bạn xem trong thẻ ẩn danh sẽ không bị lÆ°u lại trong lịch sá»­ của trình duyệt, kho cookie hoặc lịch sá»­ tìm kiếm sau khi bạn đóng tất cả các thẻ ẩn danh của mình. Má»i tệp bạn tải xuống hoặc dấu trang mà bạn tạo sẽ được giữ nguyên.</translation>
<translation id="3169472444629675720">Khám phá</translation>
<translation id="3174168572213147020">Äảo</translation>
<translation id="3176929007561373547">Kiểm tra cài đặt proxy của bạn hoặc liên hệ với quản trị viên mạng để
@@ -599,10 +614,12 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<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="3249845759089040423">Sành điệu</translation>
<translation id="3252266817569339921">Tiếng Pháp</translation>
<translation id="3266793032086590337">Giá trị (xung đột)</translation>
<translation id="3268451620468152448">Thẻ đang mở</translation>
<translation id="3270847123878663523">&amp;Hoàn tác sắp xếp lại</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> muốn kết nối</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Tổ chức <ph name="ENROLLMENT_DOMAIN" /> của bạn đã gửi một số thông tin (chẳng hạn như chế độ cài đặt hoặc chính sách) đến các trang web sau đây.</translation>
<translation id="3282497668470633863">Thêm tên trên thẻ</translation>
@@ -655,6 +672,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="3428151540071562330">Má»™t hoặc nhiá»u URI mẫu máy chủ DnsOverHttpsTemplates là không hợp lệ và sẽ không được dùng.</translation>
<translation id="3431636764301398940">Lưu thẻ này vào thiết bị này</translation>
<translation id="3432601291244612633">Äóng trang</translation>
+<translation id="3435738964857648380">Bảo mật</translation>
<translation id="3435896845095436175">Bật</translation>
<translation id="3438829137925142401">Dùng mật khẩu đã lưu trong Tài khoản Google của bạn</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -697,7 +715,10 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="3584299510153766161">Äục 2 lá»— dÆ°á»›i cùng</translation>
<translation id="3586931643579894722">Ẩn chi tiết</translation>
<translation id="3587738293690942763">Ở giữa</translation>
+<translation id="3590643883886679995">Dữ liệu đăng nhập sẽ được lÆ°u trữ trên thiết bị này sau khi bạn thoát khá»i chế Ä‘á»™ Ẩn danh.</translation>
+<translation id="359126217934908072">Tháng/Năm:</translation>
<translation id="3592413004129370115">Italian (Phong bì)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Bạn có thể đặt lại nhóm của mình bất cứ lúc nào. Bạn sẽ mất khoảng 1 ngày để tham gia một nhóm mới.}=1{Bạn có thể đặt lại nhóm của mình bất cứ lúc nào. Bạn sẽ mất khoảng 1 ngày để tham gia một nhóm mới.}other{Bạn có thể đặt lại nhóm của mình bất cứ lúc nào. Bạn sẽ mất {NUM_DAYS} ngày để tham gia một nhóm mới.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Quản trị viên đã chặn ứng dụng</translation>
<translation id="3608932978122581043">Hướng nạp giấy</translation>
@@ -706,13 +727,13 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="3615877443314183785">Nhập ngày hết hạn hợp lệ</translation>
<translation id="36224234498066874">Xóa DL duyệt web</translation>
<translation id="362276910939193118">Hiển thị Toàn bộ Lịch sử</translation>
-<translation id="3625635938337243871">Dữ liệu đăng nhập sẽ được lÆ°u trữ trên thiết bị này sau khi bạn thoát khá»i chế Ä‘á»™ ẩn danh.</translation>
<translation id="3630155396527302611">Nếu chương trình đã được liệt kê là chương trình được phép truy cập mạng, hãy thử
xóa chÆ°Æ¡ng trình này khá»i danh sách rồi thêm lại.</translation>
<translation id="3630699740441428070">Các quản trị viên của thiết bị này đã định cấu hình Ä‘Æ°á»ng kết nối mạng của bạn, nhỠđó há» có thể xem lÆ°u lượng truy cập mạng của bạn, kể cả những trang web mà bạn truy cập.</translation>
<translation id="3631244953324577188">Sinh trắc há»c</translation>
<translation id="3633738897356909127">Nút Cập nhật Chrome, nhấn phím Enter để cập nhật Chrome trong phần cài đặt của Chrome</translation>
<translation id="3634530185120165534">Khay 5</translation>
+<translation id="3637662659967048211">Lưu vào Tài khoản Google</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">Ứng dụng:</translation>
<translation id="3650584904733503804">Xác thực thành công</translation>
@@ -753,6 +774,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="3781428340399460090">Hồng đậm</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">Thiết bị Bluetooth</translation>
+<translation id="3787675388804467730">Số thẻ ảo</translation>
<translation id="3787705759683870569">Ngày hết hạn <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Kích thước 16</translation>
<translation id="3789841737615482174">Cài đặt</translation>
@@ -772,6 +794,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="3841184659773414994">Trình xử lý tệp</translation>
<translation id="385051799172605136">Quay lại</translation>
<translation id="3858027520442213535">Cập nhật ngày và giá»</translation>
+<translation id="3881478300875776315">Ẩn bớt dòng</translation>
<translation id="3884278016824448484">Số nhận dạng thiết bị xung đột</translation>
<translation id="3885155851504623709">Giáo xứ</translation>
<translation id="388632593194507180">Hoạt động giám sát đã phát hiện</translation>
@@ -797,6 +820,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="397105322502079400">Äang tính...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> bị chặn</translation>
<translation id="3973357910713125165">Nút Chạy quy trình Kiểm tra an toàn trên Chrome, nhấn Enter để chạy quy trình Kiểm tra an toàn trong phần cài đặt của Chrome</translation>
+<translation id="3986705137476756801">Tắt tính năng Phụ đỠtrực tiếp lúc này</translation>
<translation id="3987405730340719549">Chrome đã xác định được rằng đây có thể là trang web giả mạo hoặc lừa đảo.
Nếu bạn cho rằng thông báo này hiển thị do lỗi, vui lòng truy cập vào https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -893,13 +917,14 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="4275830172053184480">Khởi động lại thiết bị của bạn</translation>
<translation id="4277028893293644418">Äặt lại mật khẩu</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="4287885627794386150">Äủ Ä‘iá»u kiện dùng thá»­ nhÆ°ng chÆ°a hoạt Ä‘á»™ng</translation>
<translation id="4297502707443874121">Hình thu nhỠcủa trang <ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Mở rộng</translation>
<translation id="4300675098767811073">Äục nhiá»u lá»— bên phải</translation>
<translation id="4302514097724775343">Nhấn vào hình khủng long để chơi</translation>
<translation id="4302965934281694568">Chou3 (Phong bì)</translation>
<translation id="4305666528087210886">Không thể truy cập vào tệp của bạn</translation>
-<translation id="4305817255990598646">Chuyển</translation>
+<translation id="4306529830550717874">Lưu địa chỉ?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Chặn (mặc định)</translation>
<translation id="4314815835985389558">Quản lý dữ liệu đồng bộ hóa</translation>
@@ -926,6 +951,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="4377125064752653719">Bạn đã cố truy cập vào <ph name="DOMAIN" /> nhÆ°ng chứng chỉ mà máy chủ xuất trình đã bị nhà phát hành thu hồi. Äiá»u này có nghÄ©a là giấy ủy nhiệm bảo mật mà máy chủ xuất trình hoàn toàn không đáng tin cậy. Bạn có thể Ä‘ang giao tiếp vá»›i kẻ tấn công.</translation>
<translation id="4378154925671717803">Äiện thoaÌ£i</translation>
<translation id="4390472908992056574">Vành</translation>
+<translation id="4406883609789734330">Phụ đỠtrực tiếp</translation>
<translation id="4406896451731180161">kết quả tìm kiếm</translation>
<translation id="4408413947728134509">Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Bạn vừa nhập mật khẩu vào má»™t trang web lừa đảo. Chrome khuyên bạn nên truy cập vào <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> và các trang web khác mà bạn dùng mật khẩu này rồi đổi mật khẩu ngay bây giá».</translation>
@@ -938,7 +964,6 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<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="4464826014807964867">Các trang web có thông tin của tổ chức bạn</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="4476953670630786061">Biểu mẫu này không an toàn. Do đó, tính năng tá»± Ä‘á»™ng Ä‘iá»n đã bị tắt.</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>
@@ -972,6 +997,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<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="4606870351894164739">Ấn tượng</translation>
<translation id="4628948037717959914">Ảnh</translation>
<translation id="4631649115723685955">Äã liên kết Æ°u đãi hoàn tiá»n</translation>
<translation id="4636930964841734540">Thông tin</translation>
@@ -991,6 +1017,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="4691835149146451662">Architecture-A (Phong bì)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Mặt bên</translation>
+<translation id="4702656508969495934">Phụ đỠtrực tiếp đang hiển thị, hãy dùng trình chuyển đổi cửa sổ để đặt tiêu điểm</translation>
<translation id="4708268264240856090">Kết nối của bạn bị gián đoạn</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Chạy Chẩn đoán mạng của Windows<ph name="END_LINK" /></translation>
@@ -1004,6 +1031,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="4738601419177586157">Äá» xuất tìm kiếm <ph name="TEXT" /></translation>
<translation id="4742407542027196863">Quản lý mật khẩu…</translation>
<translation id="4744603770635761495">ÄÆ°á»ng dẫn thá»±c thi</translation>
+<translation id="4749011317274908093">Bạn đã chuyển sang chế độ Ẩn danh</translation>
<translation id="4750917950439032686">Thông tin của bạn (ví dụ: mật khẩu hoặc số thẻ tín dụng) sẽ được bảo mật khi được gửi tới trang web này.</translation>
<translation id="4756388243121344051">&amp;Lịch sử</translation>
<translation id="4758311279753947758">Thêm thông tin liên hệ</translation>
@@ -1033,6 +1061,8 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="4813512666221746211">Lỗi mạng</translation>
<translation id="4816492930507672669">Vừa với trang</translation>
<translation id="4819347708020428563">Chỉnh sửa chú thích ở chế độ xem mặc định?</translation>
+<translation id="4825507807291741242">Mạnh mẽ</translation>
+<translation id="4838327282952368871">MÆ¡ má»™ng</translation>
<translation id="484462545196658690">Tá»± Ä‘á»™ng</translation>
<translation id="4850886885716139402">Xem</translation>
<translation id="485316830061041779">Tiếng Äức</translation>
@@ -1169,6 +1199,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="5314967030527622926">Máy tạo cuốn sách nhá»</translation>
<translation id="5316812925700871227">Xoay ngược chiá»u kim đồng hồ</translation>
<translation id="5317780077021120954">LÆ°u</translation>
+<translation id="5321288445143113935">Phóng to</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> / <ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Chá»n thông tin liên hệ</translation>
<translation id="5327248766486351172">Tên</translation>
@@ -1176,11 +1207,13 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="5332219387342487447">Phương thức giao hàng</translation>
<translation id="5333022057423422993">Chrome phát hiện thấy mật khẩu bạn vừa sá»­ dụng bị lá»™ trong má»™t sá»± cố rò rỉ dữ liệu. Äể bảo mật tài khoản, bạn nên kiểm tra các mật khẩu mình đã lÆ°u.</translation>
<translation id="5334013548165032829">Nhật ký hệ thống chi tiết</translation>
+<translation id="5334145288572353250">Lưu địa chỉ?</translation>
<translation id="5340250774223869109">Äã chặn ứng dụng</translation>
<translation id="534295439873310000">Thiết bị dùng công nghệ NFC</translation>
<translation id="5344579389779391559">Trang này có thể tìm cách tính phí bạn</translation>
<translation id="5355557959165512791">Bạn không thể truy cập vào <ph name="SITE" /> ngay bây giá» vì chứng chỉ của trang này đã bị thu hồi. 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="536296301121032821">Không thể lưu trữ cài đặt chính sách</translation>
+<translation id="5363309033720083897">Cổng nối tiếp được quản trị viên của bạn cho phép</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="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>
@@ -1189,6 +1222,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="5398772614898833570">Äã chặn quảng cáo</translation>
<translation id="5400836586163650660">Màu xám</translation>
<translation id="540969355065856584">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 không hợp lệ tại thá»i Ä‘iểm này. Ä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>
+<translation id="541143247543991491">Äám mây (trên toàn hệ thống)</translation>
<translation id="541416427766103491">Khay xếp chồng 4</translation>
<translation id="5421136146218899937">Xóa dữ liệu duyệt web...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> muốn gửi thông báo cho bạn</translation>
@@ -1202,6 +1236,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="5455374756549232013">Dấu thá»i gian chính sách không hợp lệ</translation>
<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="5463625433003343978">Äang tìm thiết bị...</translation>
<translation id="5469868506864199649">Tiếng Ã</translation>
<translation id="5470861586879999274">&amp;Làm lại chỉnh sửa</translation>
<translation id="5478437291406423475">B6/C4 (Phong bì)</translation>
@@ -1251,7 +1286,6 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="5624120631404540903">Quản lý mật khẩu</translation>
<translation id="5629630648637658800">Không thể tải cài đặt chính sách</translation>
<translation id="5631439013527180824">Mã thông báo quản lý thiết bị không hợp lệ</translation>
-<translation id="5632627355679805402">Dữ liệu của bạn đã được mã hóa bằng <ph name="BEGIN_LINK" />mật khẩu Google<ph name="END_LINK" /> kể từ <ph name="TIME" />. Hãy nhập mật khẩu đó để bắt đầu đồng bộ hóa.</translation>
<translation id="5633066919399395251">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ố gắng cài đặt các chương trình nguy hiểm vào máy tính của bạn. Các chương trình này sẽ đánh cắp hoặc xóa thông tin của bạn (ví dụ: ảnh, mật khẩu, thư và 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="563324245173044180">Äã chặn ná»™i dung lừa đảo.</translation>
<translation id="5644090287519800334">Trục X của hình ảnh mặt 1</translation>
@@ -1290,12 +1324,12 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="5785756445106461925">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 giao diện của trang.</translation>
<translation id="5786044859038896871">Bạn có muốn Ä‘iá»n thông tin thẻ của mình không?</translation>
<translation id="578633867165174378">Chrome phát hiện thấy mật khẩu bạn vừa sử dụng bị lộ trong một sự cố rò rỉ dữ liệu. Bạn nên đổi mật khẩu này ngay.</translation>
-<translation id="5798290721819630480">Hủy thay đổi?</translation>
<translation id="5803412860119678065">Bạn có muốn Ä‘iá»n <ph name="CARD_DETAIL" /> của mình không?</translation>
<translation id="5804241973901381774">Quyá»n</translation>
<translation id="5804427196348435412">Sử dụng các thiết bị dùng công nghệ NFC</translation>
<translation id="5810442152076338065">Kết nối của bạn tá»›i <ph name="DOMAIN" /> được mã hóa bằng bá»™ số 0 đã lá»—i thá»i.</translation>
<translation id="5813119285467412249">&amp;Làm lại thêm</translation>
+<translation id="5817918615728894473">Ghép nối</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Thẻ này sẽ bị trừ tiá»n khi bạn thanh toán, nhÆ°ng số thẻ thật sẽ không được chia sẻ vá»›i trang web này. Äể tăng cÆ°á»ng tính bảo mật, hệ thống sẽ tạo má»™t Mã xác minh thẻ (CVC) tạm thá»i.}other{Thẻ bạn chá»n sẽ bị trừ tiá»n khi bạn thanh toán, nhÆ°ng số thẻ thật sẽ không được chia sẻ vá»›i trang web này. Äể tăng cÆ°á»ng tính bảo mật, hệ thống sẽ tạo má»™t Mã xác minh thẻ (CVC) tạm thá»i.}}</translation>
<translation id="5826507051599432481">Tên Phổ biến (CN)</translation>
<translation id="5838278095973806738">Bạn không nên nhập bất kỳ thông tin nhạy cảm nào trên trang web này (ví dụ: mật khẩu hoặc thẻ tín dụng), vì những kẻ tấn công có thể đánh cắp thông tin đó.</translation>
@@ -1303,6 +1337,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="5855253129151731373">Tên máy chủ của trang web này giống vá»›i miá»n <ph name="LOOKALIKE_DOMAIN" />. 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Ỡđối vá»›i tên miá»n mà bạn khó phát hiện ra.
Nếu bạn cho rằng thông báo này hiển thị do lỗi, vui lòng truy cập vào https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Tắt</translation>
<translation id="5862579898803147654">Khay xếp chồng 8</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>
@@ -1319,6 +1354,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="5913377024445952699">Tính năng chụp ảnh màn hình bị tạm dừng</translation>
<translation id="59174027418879706">Äược kích hoạt</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{Äang sá»­ dụng 1 cookie}other{Äang sá»­ dụng # cookie}}</translation>
<translation id="5921185718311485855">Äang bật</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>
@@ -1338,6 +1374,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="5989320800837274978">Cả máy chủ proxy cố định và URL tập lệnh .pac Ä‘á»u chÆ°a được chỉ định.</translation>
<translation id="5992691462791905444">Gấp kiểu chữ Z kỹ thuật</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> kết quả cho '<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">Cổ điển</translation>
<translation id="6008122969617370890">Thứ tự từ N đến 1</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">Kiểm tra mật khẩu của bạn</translation>
@@ -1359,6 +1396,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="6045164183059402045">Mẫu áp dụng</translation>
<translation id="6047233362582046994">Nếu bạn hiểu các rủi ro vỠbảo mật, bạn có thể <ph name="BEGIN_LINK" />truy cập trang này<ph name="END_LINK" /> trước khi các ứng dụng có hại bị xóa.</translation>
<translation id="6047927260846328439">Ná»™i dung này có thể tìm cách đánh lừa bạn cài đặt phần má»m hoặc tiết lá»™ thông tin cá nhân. <ph name="BEGIN_LINK" />Vẫn hiển thị<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Hãy nhấn và giữ |<ph name="ACCELERATOR" />| để thoát khá»i toàn màn hình</translation>
<translation id="6049488691372270142">Phân phối trang</translation>
<translation id="6051221802930200923">Bạn không thể truy cập vào <ph name="SITE" /> ngay bây giá» do trang web sá»­ dụng tính năng ghim chứng chỉ. 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="6051898664905071243">Số lượng trang:</translation>
@@ -1375,6 +1413,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<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>
<translation id="6116338172782435947">Xem văn bản và hình ảnh đã sao chép sang bảng nhớ tạm</translation>
<translation id="6120179357481664955">Ghi nhớ mã nhận dạng sản phẩm duy nhất (UPI) của bạn?</translation>
+<translation id="6123290840358279103">Xem thẻ ảo</translation>
<translation id="6124432979022149706">Trình kết nối của Chrome Enterprise</translation>
<translation id="6146055958333702838">Kiểm tra má»i dây cáp rồi khởi Ä‘á»™ng lại bá»™ định tuyến, modem hoặc các thiết bị
mạng khác mà bạn có thể đang sử dụng.</translation>
@@ -1411,6 +1450,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="6289939620939689042">Màu trang</translation>
<translation id="6290238015253830360">Bài viết đỠxuất cho bạn sẽ xuất hiện ở đây</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Trợ lý Google trong Chrome đang dừng</translation>
<translation id="6305205051461490394">Không thể truy cập <ph name="URL" />.</translation>
<translation id="6312113039770857350">Trang web hiện không khả dụng</translation>
@@ -1436,6 +1476,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="6390200185239044127">Gấp đôi kiểu chữ Z</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Chính sách của quản trị viên đã chặn thao tác dán từ <ph name="ORIGIN_NAME" /> vào trị trí này</translation>
+<translation id="6398765197997659313">Thoát khá»i chế Ä‘á»™ toàn màn hình</translation>
<translation id="6401136357288658127">Chính sách này không còn dùng nữa. Thay vào đó, bạn nên sử dụng chính sách <ph name="NEW_POLICY" />.</translation>
<translation id="6404511346730675251">Chỉnh sửa dấu trang</translation>
<translation id="6406765186087300643">C0 (Phong bì)</translation>
@@ -1448,7 +1489,6 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="6428450836711225518">Xác minh số điện thoại của bạn</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="6440503408713884761">Bị bỠqua</translation>
<translation id="6443406338865242315">Các tiện ích và plugin bạn đã cài đặt</translation>
<translation id="6446163441502663861">Kahu (Phong bì)</translation>
@@ -1491,6 +1531,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="6624427990725312378">Thông tin liên hệ</translation>
<translation id="6626291197371920147">Thêm số thẻ hợp lệ</translation>
<translation id="6628463337424475685">Tìm kiếm trên <ph name="ENGINE" /></translation>
+<translation id="6630043285902923878">Äang tìm thiết bị USB...</translation>
<translation id="6630809736994426279">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ố gắng cài đặt các chương trình nguy hiểm vào máy Mac của bạn. Các chương trình này sẽ đánh cắp hoặc xóa thông tin của bạn (ví dụ: ảnh, mật khẩu, thư và 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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">Xóa</translation>
@@ -1506,6 +1547,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<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="6687335167692595844">Kích thước phông chữ đã yêu cầu</translation>
+<translation id="6688743156324860098">Cập nhật…</translation>
<translation id="6689249931105087298">Tương đối có nén điểm đen</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="6698381487523150993">Tạo:</translation>
@@ -1521,6 +1563,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<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="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="6767985426384634228">Cập nhật địa chỉ?</translation>
<translation id="6768213884286397650">Hagaki (Bưu thiếp)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">Tím vi-ô-lét</translation>
@@ -1543,6 +1586,7 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome Ä‘Æ¡n giản hóa trang này để bạn dá»… Ä‘á»c hÆ¡n. Chrome đã truy xuất trang gốc qua má»™t Ä‘Æ°á»ng kết nối không an toàn.</translation>
<translation id="6891596781022320156">CâÌp chiÌnh saÌch không Ä‘Æ°Æ¡Ì£c hỗ trÆ¡Ì£.</translation>
+<translation id="6895143722905299846">Số thẻ ảo:</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="6898699227549475383">Tổ chức (O)</translation>
@@ -1578,10 +1622,10 @@ Nếu bạn từ chối, chế Ä‘á»™ cài đặt quyá»n riêng tÆ° của bạn
<translation id="7004583254764674281">Dùng Windows Hello để xác nhận các thẻ nhanh hơn</translation>
<translation id="7006930604109697472">Vẫn gửi</translation>
<translation id="7012363358306927923">China UnionPay</translation>
-<translation id="7012404007611495949">Cài đặt đổi kích thước</translation>
<translation id="7014741021609395734">Mức thu phóng</translation>
<translation id="7016992613359344582">Các khoản phí này có thể là khoản thu một lần hoặc định kỳ và có thể không rõ ràng.</translation>
<translation id="7029809446516969842">Mật khẩu</translation>
+<translation id="7030436163253143341">Chứng chỉ không hợp lệ</translation>
<translation id="7031646650991750659">Những ứng dụng bạn đã cài đặt bằng Google Play</translation>
<translation id="7050187094878475250">Bạn đã cố gắng truy cập <ph name="DOMAIN" /> nhÆ°ng máy chủ đã hiển thị chứng chỉ có thá»i gian hiệu lá»±c quá dài để có thể tin cậy.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Không thể lÆ°u thẻ này ngay bây giá»}other{Không thể lÆ°u các thẻ này ngay bây giá»}}</translation>
@@ -1651,12 +1695,14 @@ Thông tin chi tiết bổ sung:
<translation id="7300012071106347854">Xanh thẩm</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Cao</translation>
+<translation id="7305756307268530424">Bắt đầu tốc độ chậm hơn</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Trợ giúp kết nối</translation>
<translation id="7323804146520582233">Ẩn phần "<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Ghi đè tài khoản trên thiết bị</translation>
<translation id="7333654844024768166">Bạn vừa nhập mật khẩu vào má»™t trang web lừa đảo. Chromium khuyên bạn nên truy cập vào <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" /> và các trang web khác mà bạn dùng mật khẩu này rồi đổi mật khẩu ngay bây giá».</translation>
<translation id="7334320624316649418">&amp;Làm lại sắp xếp lại</translation>
+<translation id="7337248890521463931">Hiện thêm dòng</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>
@@ -1664,6 +1710,7 @@ Thông tin chi tiết bổ sung:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Dòng Lệnh</translation>
<translation id="7359588939039777303">Äã chặn quảng cáo.</translation>
+<translation id="7363096869660964304">Tuy nhiên, thông tin của bạn vẫn hiển thị. Việc chuyển sang chế Ä‘á»™ Ẩn danh sẽ không ẩn hoạt Ä‘á»™ng duyệt web của bạn khá»i công ty, nhà cung cấp dịch vụ Internet hoặc các trang web mà bạn truy cập.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, hãy nhấn Tab rồi nhấn Enter để thêm và quản lý các địa chỉ trong phần Cài đặt của Chrome</translation>
<translation id="7365849542400970216">Biết hoạt động dùng thiết bị của bạn?</translation>
<translation id="7372973238305370288">kết quả tìm kiếm</translation>
@@ -1674,7 +1721,9 @@ Thông tin chi tiết bổ sung:
<translation id="7378594059915113390">Các chức năng Ä‘iá»u khiển ná»™i dung Ä‘a phÆ°Æ¡ng tiện</translation>
<translation id="7378627244592794276">Không</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Không áp dụng</translation>
<translation id="7390545607259442187">Xác nhận thẻ</translation>
+<translation id="7392089738299859607">Cập nhật địa chỉ</translation>
<translation id="7399802613464275309">Kiểm tra an toàn</translation>
<translation id="7400418766976504921">URL</translation>
<translation id="7403591733719184120"><ph name="DEVICE_NAME" /> của bạn được quản lý</translation>
@@ -1689,6 +1738,7 @@ Thông tin chi tiết bổ sung:
&lt;li&gt;Truy cập vào &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Trung tâm trợ giúp Chrome&lt;/a&gt; để tìm hiểu cách xóa vÄ©nh viá»…n phần má»m này khá»i máy tính của bạn
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">Äáng yêu</translation>
<translation id="7416351320495623771">Quản lý mật khẩu…</translation>
<translation id="7419106976560586862">ÄÆ°á»ng dẫn cấu hình</translation>
<translation id="7437289804838430631">Thêm thông tin liên hệ</translation>
@@ -1704,7 +1754,7 @@ Thông tin chi tiết bổ sung:
<translation id="7481312909269577407">Chuyển tiếp</translation>
<translation id="7485870689360869515">Không tìm thấy dữ liệu.</translation>
<translation id="7495528107193238112">Nội dung này bị chặn. Hãy liên hệ với chủ sở hữu trang web để khắc phục sự cố.</translation>
-<translation id="7498234416455752244">Tiếp tục chỉnh sửa</translation>
+<translation id="7498193950643227031">Ứng dụng có thể không hoạt động như mong đợi khi bị đổi kích thước. GiỠđây, bạn có thể hạn chế khả năng đổi kích thước các ứng dụng trong phần <ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Bạn vừa nhập mật khẩu vào một trang web lừa đảo. Chromium khuyên bạn nên kiểm tra ngay những mật khẩu bạn đã lưu cho <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> và các trang web khác mà bạn sử dụng mật khẩu này.</translation>
<translation id="7508255263130623398">ID thiết bị thuộc chính sách trả lại trống hoặc không khớp với ID của thiết bị hiện tại</translation>
<translation id="7508870219247277067">Xanh quả bơ</translation>
@@ -1724,6 +1774,7 @@ Thông tin chi tiết bổ sung:
<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="755279583747225797">Chế độ dùng thử đang hoạt động</translation>
<translation id="7552846755917812628">Thử các mẹo sau:</translation>
<translation id="7554475479213504905">Tải lại và vẫn hiển thị</translation>
<translation id="7554791636758816595">Thẻ mới</translation>
@@ -1742,7 +1793,6 @@ 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="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, nhấn phím Tab rồi nhấn Enter để xem và quản lý các mật khẩu của bạn trong phần cài đặt của Chrome</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="7616645509853975347">Quản trị viên đã bật Chrome Enterprise Connectors trên trình duyệt bạn dùng. Các trình kết nối này có quyá»n truy cập vào má»™t số dữ liệu của bạn.</translation>
<translation id="7619838219691048931">TỠcuối</translation>
<translation id="762844065391966283">Từng đối tượng</translation>
@@ -1807,13 +1857,12 @@ Thông tin chi tiết bổ sung:
<translation id="782886543891417279">Wi-Fi mà bạn đang sử dụng (<ph name="WIFI_NAME" />) có thể yêu cầu bạn phải truy cập trang đăng nhập của mạng đó.</translation>
<translation id="7836231406687464395">Postfix (Phong bì)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Không có}=1{1 ứng dụng (<ph name="EXAMPLE_APP_1" />)}=2{2 ứng dụng (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}other{# ứng dụng (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Tuy nhiên, bạn không ẩn. Việc chuyển sang chế độ ẩn danh sẽ không ẩn thao tác duyệt của bạn với chủ lao động, nhà cung cấp dịch vụ internet hoặc các trang web bạn truy cập.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Mở tệp bằng trình xử lý loại tệp liên kết.</translation>
<translation id="7862185352068345852">Rá»i khá»i trang web?</translation>
<translation id="7865448901209910068">Tốc độ tốt nhất</translation>
<translation id="7874263914261512992">Bạn vừa nhập mật khẩu vào một trang web lừa đảo. Chrome khuyên bạn nên kiểm tra ngay những mật khẩu bạn đã lưu cho <ph name="WEBSITE_1" />, <ph name="WEBSITE_2" /> và các trang web khác mà bạn sử dụng mật khẩu này.</translation>
<translation id="7878562273885520351">Mật khẩu của bạn có thể bị xâm phạm</translation>
+<translation id="7880146494886811634">Lưu địa chỉ</translation>
<translation id="7882421473871500483">Nâu</translation>
<translation id="7887683347370398519">Kiểm tra CVC của bạn và thử lại</translation>
<translation id="7887885240995164102">Vào chế độ hình trong hình</translation>
@@ -1821,6 +1870,7 @@ Thông tin chi tiết bổ sung:
<translation id="7894280532028510793">Nếu đúng chính tả, hãy <ph name="BEGIN_LINK" />thử chạy Chẩn đoán mạng<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Phong bì)</translation>
<translation id="7931318309563332511">Không xác định</translation>
+<translation id="793209273132572360">Cập nhật địa chỉ?</translation>
<translation id="7932579305932748336">Phủ</translation>
<translation id="79338296614623784">Nhập số điện thoại hợp lệ</translation>
<translation id="7934052535022478634">Thanh toán hoàn tất</translation>
@@ -1891,6 +1941,7 @@ Thông tin chi tiết bổ sung:
<translation id="8175796834047840627">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 hành động này trong phần cài đặt.</translation>
<translation id="8176440868214972690">Quản trị viên của thiết bị này đã gửi một số thông tin (chẳng hạn như chế độ cài đặt hoặc chính sách) đến các trang web sau đây.</translation>
<translation id="8184538546369750125">Sử dụng giá trị mặc định chung (Cho phép)</translation>
+<translation id="8193086767630290324">Các thao tác đã thực hiện có dữ liệu được gắn cỠlà bảo mật</translation>
<translation id="8194797478851900357">&amp;Hoàn tác di chuyển</translation>
<translation id="8201077131113104583">URL cập nhật không hợp lệ cho tiện ích có ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Tóm tắt đơn đặt hàng</translation>
@@ -1913,6 +1964,7 @@ Thông tin chi tiết bổ sung:
<translation id="8249296373107784235">Hủy bá»</translation>
<translation id="8249320324621329438">Tìm nạp lần cuối:</translation>
<translation id="8253091569723639551">Yêu cầu địa chỉ thanh toán</translation>
+<translation id="8257387598443225809">Ứng dụng này được thiết kế cho thiết bị di động</translation>
<translation id="825929999321470778">Hiển thị tất cả các mật khẩu đã lưu</translation>
<translation id="8261506727792406068">Xóa</translation>
<translation id="8262952874573525464">May viá»n ở dÆ°á»›i cùng</translation>
@@ -2037,7 +2089,6 @@ Thông tin chi tiết bổ sung:
<translation id="8719528812645237045">Äục nhiá»u lá»— trên cùng</translation>
<translation id="8725066075913043281">Thử lại</translation>
<translation id="8726549941689275341">Kích thước trang:</translation>
-<translation id="8728672262656704056">Bạn đã chuyển sang chế độ ẩn danh</translation>
<translation id="8730621377337864115">Xong</translation>
<translation id="8731544501227493793">Nút Quản lý mật khẩu, nhấn phím Enter để xem và quản lý các mật khẩu của bạn trong phần cài đặt của Chrome</translation>
<translation id="8734529307927223492"><ph name="DEVICE_TYPE" /> của bạn do <ph name="MANAGER" /> quản lý</translation>
@@ -2114,6 +2165,7 @@ Thông tin chi tiết bổ sung:
<translation id="9020542370529661692">Trang này đã được dịch sang <ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Không hợp lệ)</translation>
+<translation id="9030265603405983977">ÄÆ¡n sắc</translation>
<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>
@@ -2137,6 +2189,7 @@ Thông tin chi tiết bổ sung:
<translation id="91108059142052966">Tính năng chia sẻ màn hình với <ph name="APPLICATION_TITLE" /> khi hiển thị nội dung bí mật bị vô hiệu hóa theo chính sách của quản trị viên</translation>
<translation id="9114524666733003316">Äang xác nhận thẻ...</translation>
<translation id="9114581008513152754">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="9117930699067497412">TÆ°Æ¡i má»›i</translation>
<translation id="9119042192571987207">Äã tải lên</translation>
<translation id="9128016270925453879">Äã tải chính sách</translation>
<translation id="9128870381267983090">Kết nối đến mạng</translation>
@@ -2155,6 +2208,7 @@ Thông tin chi tiết bổ sung:
<translation id="9170848237812810038">H&amp;oàn tác</translation>
<translation id="9171296965991013597">Thoát khá»i ứng dụng?</translation>
<translation id="9173282814238175921">Một tài liệu/TỠmới</translation>
+<translation id="9173995187295789444">Äang quét tìm thiết bị Bluetooth...</translation>
<translation id="917450738466192189">Chứng chỉ của máy chủ không hợp lệ.</translation>
<translation id="9174917557437862841">Nút chuyển đổi thẻ, nhấn phím Enter để chuyển sang thẻ này</translation>
<translation id="9179703756951298733">Quản lý thông tin thanh toán và thẻ tín dụng của bạn trong phần cài đặt của Chrome</translation>
diff --git a/chromium/components/strings/components_strings_zh-CN.xtb b/chromium/components/strings/components_strings_zh-CN.xtb
index a066aa64d9c..31a4c579787 100644
--- a/chromium/components/strings/components_strings_zh-CN.xtb
+++ b/chromium/components/strings/components_strings_zh-CN.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">选中åŽï¼ŒChrome 会将您的信用å¡å‰¯æœ¬å­˜å‚¨åœ¨æ­¤è®¾å¤‡ä¸Šï¼Œä»¥åŠ å¿«è¡¨å•å¡«å†™é€Ÿåº¦ã€‚</translation>
<translation id="1110994991967754504">选择对<ph name="PERMISSION_NAME" />çš„æƒé™</translation>
<translation id="1113869188872983271">撤消顺åºè°ƒæ•´(&amp;U)</translation>
+<translation id="1123753900084781868">暂时无法使用实时字幕功能</translation>
<translation id="1125573121925420732">网站在更新其安全设置期间å¯èƒ½ä¼šç»å¸¸æ˜¾ç¤ºè­¦å‘Šã€‚此问题应该很快就会得到改进。</translation>
<translation id="112840717907525620">策略缓存良好</translation>
<translation id="1130564665089811311">“翻译网页â€æŒ‰é’®ï¼ŒæŒ‰ Enter é”®å³å¯ä½¿ç”¨â€œGoogle 翻译â€æœåŠ¡æ¥ç¿»è¯‘此页é¢</translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">您的设备å称</translation>
<translation id="124116460088058876">更多语言</translation>
<translation id="1243027604378859286">作者:</translation>
+<translation id="1246424317317450637">粗体</translation>
<translation id="1250759482327835220">若想在下次购物时更快æ·åœ°ä»˜æ¬¾ï¼Œè¯·å°†æ‚¨çš„付款å¡ä¿¡æ¯ã€å§“åå’Œå¸å•é‚®å¯„地å€ä¿å­˜åˆ°æ‚¨çš„ Google å¸å·å下。</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />ã€<ph name="TYPE_2" />(已åŒæ­¥ï¼‰</translation>
<translation id="1256368399071562588">&lt;p&gt;如果您å°è¯•è®¿é—®æŸä¸ªç½‘站,但无法打开它,å¯ä»¥æŒ‰ç…§ä»¥ä¸‹é—®é¢˜æŽ’查步骤æ“作,å°è¯•è§£å†³é—®é¢˜ï¼š&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">更改您的密ç </translation>
<translation id="1484290072879560759">选择é€è´§åœ°å€</translation>
<translation id="1492194039220927094">政策推é€ï¼š</translation>
+<translation id="1495677929897281669">返回到标签页</translation>
<translation id="1501859676467574491">显示您的 Google å¸å·ä¸­ä¿å­˜çš„支付å¡</translation>
<translation id="1507202001669085618">&lt;p&gt;如果您使用的 Wi-Fi 门户网站必须登录æ‰èƒ½è¿žæŽ¥ç½‘络,您就会看到这æ¡é”™è¯¯æ¶ˆæ¯ã€‚&lt;/p&gt;
&lt;p&gt;è¦ä¿®æ­£è¯¥é”™è¯¯ï¼Œè¯·åœ¨æ‚¨å°è¯•æ‰“开的网页上点击&lt;strong&gt;连接&lt;/strong&gt;。&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">此网页显示</translation>
<translation id="153384715582417236">暂无新内容</translation>
<translation id="1536390784834419204">翻译网页</translation>
+<translation id="1539840569003678498">报告å‘é€æ—¶é—´ï¼š</translation>
<translation id="154408704832528245">选择速递地å€</translation>
<translation id="1549470594296187301">å¿…é¡»å¯ç”¨ JavaScript æ‰èƒ½ä½¿ç”¨æ­¤åŠŸèƒ½ã€‚</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">短边先入</translation>
<translation id="168693727862418163">此政策值未能根æ®å…¶æž¶æž„进行验è¯ï¼Œå› æ­¤ä¼šè¢«å¿½ç•¥ã€‚</translation>
<translation id="168841957122794586">æœåŠ¡å™¨è¯ä¹¦åŒ…å«å¼±åŠ å¯†å¯†é’¥ã€‚</translation>
+<translation id="1696290444144917273">查看虚拟å¡è¯¦ç»†ä¿¡æ¯</translation>
<translation id="1697532407822776718">æžå®šäº†ï¼</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{æ­¤æœåŠ¡å™¨æ— æ³•è¯æ˜Žå®ƒæ˜¯ <ph name="DOMAIN" />;其安全è¯ä¹¦æ˜Žå¤©æ‰ä¼šç”Ÿæ•ˆã€‚出现此问题的原因å¯èƒ½æ˜¯é…置有误,或有攻击者拦截了您的连接。}other{æ­¤æœåŠ¡å™¨æ— æ³•è¯æ˜Žå®ƒæ˜¯ <ph name="DOMAIN" />;其安全è¯ä¹¦ # 天åŽæ‰ä¼šç”Ÿæ•ˆã€‚出现此问题的原因å¯èƒ½æ˜¯é…置有误,或有攻击者拦截了您的连接。}}</translation>
<translation id="1710259589646384581">æ“作系统</translation>
+<translation id="1711234383449478798">被忽略了,因为 <ph name="POLICY_NAME" /> 未设为 <ph name="VALUE" />。</translation>
<translation id="1712552549805331520"><ph name="URL" /> 想在您的本地计算机上永久存储数æ®</translation>
<translation id="1713628304598226412">纸匣 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">ä¿¡ç®± 3</translation>
<translation id="1718029547804390981">无法为该文档添加注释,因为它太大</translation>
<translation id="1721424275792716183">标有“*â€çš„字段å‡æ˜¯å¿…填字段</translation>
+<translation id="1727613060316725209">è¯ä¹¦æœ‰æ•ˆ</translation>
<translation id="1727741090716970331">添加有效å¡å·</translation>
<translation id="1728677426644403582">您正在查看网页的æºä»£ç </translation>
<translation id="173080396488393970">此信用å¡ç±»åž‹ä¸å—支æŒ</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />å°è¯•è¿è¡Œ Windows 网络诊断<ph name="END_LINK" />。</translation>
<translation id="1772163372082567643">您è¦è®¿é—®çš„æœåŠ¡å™¨ <ph name="ORIGIN" /> 已设定标头,其中è¦æ±‚收到的所有请求都应用一项æ¥æºæ”¿ç­–。但该标头的格å¼ä¸æ­£ç¡®ï¼Œå¯¼è‡´æµè§ˆå™¨æ— æ³•å®žçŽ°æ‚¨å¯¹ <ph name="SITE" /> 的访问请求。网站è¿è¥å•†å¯ä»¥ä½¿ç”¨æ¥æºæ”¿ç­–为网站é…置安全属性åŠå…¶ä»–属性。</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">请更新您的åŒæ­¥å¯†ç ã€‚</translation>
<translation id="1787142507584202372">您打开的标签页会显示在此处</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />,å¯æ‰§è¡Œå¤šç§æ“作,按 Tab é”®å¯å¾ªçŽ¯æµè§ˆè¿™äº›æ“作</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">广告</translation>
<translation id="1919367280705858090">了解如何解决特定错误消æ¯æŒ‡å‡ºçš„错误</translation>
<translation id="192020519938775529">{COUNT,plural, =0{无}=1{1 个网站}other{# 个网站}}</translation>
+<translation id="1924727005275031552">æ–°</translation>
<translation id="1945968466830820669">您å¯èƒ½ä¼šæ— æ³•å†è®¿é—®æ‰€å±žç»„织的å¸å·ï¼Œæˆ–被他人盗用身份信æ¯ã€‚Chromium 建议您立å³æ›´æ”¹å¯†ç ã€‚</translation>
<translation id="1947454675006758438">钉装(å³ä¸Šè§’)</translation>
<translation id="1958218078413065209">您的最高得分是 <ph name="SCORE" />。</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">纸匣 7</translation>
<translation id="204357726431741734">登录åŽå³å¯ä½¿ç”¨æ‚¨ Google å¸å·ä¸­ä¿å­˜çš„密ç </translation>
<translation id="2053111141626950936">系统ä¸ä¼šç¿»è¯‘<ph name="LANGUAGE" />网页。</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{如果此控件已开å¯ä¸”处于有效状æ€ï¼ŒChrome 会确定您近期的æµè§ˆæ´»åŠ¨ä¸Žå“ªä¸ªå¤§åž‹ç”¨æˆ·ç¾¤ç»„或“åŒç±»ç¾¤ç»„â€æœ€æŽ¥è¿‘。广告主å¯ä¸ºç¾¤ç»„选择广告,您的æµè§ˆæ´»åŠ¨è®°å½•ä¼šç§å¯†åœ°ä¿ç•™åœ¨æ‚¨çš„设备上。系统会按æ¯å¤© 1 次的频率更新您所属的群组。}=1{如果此控件已开å¯ä¸”处于有效状æ€ï¼ŒChrome 会确定您近期的æµè§ˆæ´»åŠ¨ä¸Žå“ªä¸ªå¤§åž‹ç”¨æˆ·ç¾¤ç»„或“åŒç±»ç¾¤ç»„â€æœ€æŽ¥è¿‘。广告主å¯ä¸ºç¾¤ç»„选择广告,您的æµè§ˆæ´»åŠ¨è®°å½•ä¼šç§å¯†åœ°ä¿ç•™åœ¨æ‚¨çš„设备上。系统会按æ¯å¤© 1 次的频率更新您所属的群组。}other{如果此控件已开å¯ä¸”处于有效状æ€ï¼ŒChrome 会确定您近期的æµè§ˆæ´»åŠ¨ä¸Žå“ªä¸ªå¤§åž‹ç”¨æˆ·ç¾¤ç»„或“åŒç±»ç¾¤ç»„â€æœ€æŽ¥è¿‘。广告主å¯ä¸ºç¾¤ç»„选择广告,您的æµè§ˆæ´»åŠ¨è®°å½•ä¼šç§å¯†åœ°ä¿ç•™åœ¨æ‚¨çš„è®¾å¤‡ä¸Šã€‚ç³»ç»Ÿä¼šæŒ‰æ¯ {NUM_DAYS} 天 1 次的频率更新您所属的群组。}}</translation>
<translation id="2053553514270667976">邮编</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 æ¡å»ºè®®}other{# æ¡å»ºè®®}}</translation>
<translation id="2071692954027939183">由于您通常ä¸å…许显示通知,系统已自动å±è”½é€šçŸ¥</translation>
<translation id="2079545284768500474">撤消</translation>
<translation id="20817612488360358">已设置为使用系统代ç†è®¾ç½®ï¼Œä½†åŒæ—¶æŒ‡å®šäº†ä¸€ä¸ªæ˜Žç¡®çš„代ç†é…置。</translation>
<translation id="2082238445998314030">第 <ph name="RESULT_NUMBER" /> æ¡ç»“果,共 <ph name="TOTAL_RESULTS" /> æ¡</translation>
+<translation id="2085876078937250610">ä¿å­˜â€¦</translation>
<translation id="2088086323192747268">“管ç†åŒæ­¥æ•°æ®â€æŒ‰é’®ï¼ŒæŒ‰ Enter é”®å³å¯åœ¨ Chrome 设置中管ç†æ‚¨è¦åŒæ­¥çš„ä¿¡æ¯</translation>
<translation id="2091887806945687916">声音</translation>
<translation id="2094505752054353250">网域ä¸åŒ¹é…</translation>
@@ -313,7 +322,7 @@
<translation id="2102495993840063010">Android 应用</translation>
<translation id="2107021941795971877">打å°æ–¹é¢çš„支æŒ</translation>
<translation id="2108755909498034140">é‡æ–°å¯åŠ¨è®¡ç®—机</translation>
-<translation id="2111166930115883695">按空格键å³å¯æ’­æ”¾</translation>
+<translation id="2111166930115883695">按空格键å³å¯å¼€å§‹æ¸¸æˆ</translation>
<translation id="2111256659903765347">Super-A</translation>
<translation id="2113977810652731515">信用å¡</translation>
<translation id="2114841414352855701">由于已被 <ph name="POLICY_NAME" /> 替æ¢ï¼Œè¯¥æ”¿ç­–已忽略。</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> è¦æ±‚æ供用户å和密ç ã€‚</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />,到期时间:<ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">设置由管ç†å‘˜æŽ§åˆ¶</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> 希望与以下所选设备é…对:</translation>
<translation id="2344028582131185878">自动下载</translation>
<translation id="2346319942568447007">您å¤åˆ¶çš„图片</translation>
<translation id="2354001756790975382">其他书签</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">攻击者å¯èƒ½èƒ½å¤Ÿçœ‹åˆ°æ‚¨æ­£åœ¨æ­¤ç½‘站上æµè§ˆçš„图片,并通过编辑这些图片让您å—骗。</translation>
<translation id="2356070529366658676">询问</translation>
<translation id="2357481397660644965">您的设备由 <ph name="DEVICE_MANAGER" /> 管ç†ï¼Œæ‚¨çš„å¸å·ç”± <ph name="ACCOUNT_MANAGER" /> 管ç†ã€‚</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ä¸åˆ° 1 天åŽ}=1{1 天åŽ}other{{NUM_DAYS} 天åŽ}}</translation>
<translation id="2359629602545592467">多ç§è´§å¸</translation>
<translation id="2359808026110333948">继续</translation>
+<translation id="2359961752320758691">已应用您的虚拟å¡å·ã€‚</translation>
<translation id="2367567093518048410">级别</translation>
<translation id="2372464001869762664">待您确认åŽï¼Œç³»ç»Ÿä¾¿ä¼šå°†æ‚¨ Google å¸å·ä¸­çš„信用å¡è¯¦ç»†ä¿¡æ¯å…±äº«ç»™è¯¥ç½‘站。您å¯åœ¨ Plex å¸å·è¯¦æƒ…中找到银行å¡éªŒè¯ç  (CVC)。</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">该é€è´§æ–¹å¼ä¸å¯ç”¨ã€‚请å¦é€‰ä¸€ç§æ–¹å¼ã€‚</translation>
<translation id="2396249848217231973">撤消删除(&amp;U)</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">æ—§</translation>
<translation id="2413528052993050574">æ­¤æœåŠ¡å™¨æ— æ³•è¯æ˜Žå®ƒæ˜¯<ph name="DOMAIN" />;其安全è¯ä¹¦å¯èƒ½å·²è¢«æ’¤æ¶ˆã€‚出现此问题的原因å¯èƒ½æ˜¯é…置有误或您的连接被拦截了。</translation>
<translation id="2414886740292270097">深色调</translation>
<translation id="2438874542388153331">四孔(å³ä¾§ï¼‰</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">钉装(å³ä¸‹è§’)</translation>
<translation id="2523886232349826891">仅会ä¿å­˜åœ¨æ­¤è®¾å¤‡ä¸Š</translation>
<translation id="2524461107774643265">添加更多信æ¯</translation>
-<translation id="2526590354069164005">æ¡Œé¢</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{以åŠå¦å¤– 1 个网域}other{以åŠå¦å¤– # 个网域}}</translation>
<translation id="2536110899380797252">添加地å€</translation>
<translation id="2539524384386349900">检测</translation>
+<translation id="2541219929084442027">在您关闭所有无痕å¼æ ‡ç­¾é¡µåŽï¼Œæ‚¨åœ¨è¿™äº›æ ‡ç­¾é¡µä¸­æµè§ˆçš„网页ä¸ä¼šåœ¨æµè§ˆå™¨åŽ†å²è®°å½•ã€Cookie 存储区或æœç´¢è®°å½•ä¸­ç•™ä¸‹ä»»ä½•ç—•è¿¹ã€‚ä¸è¿‡ï¼Œæ‚¨ä¸‹è½½çš„所有文件或创建的书签å‡ä¼šä¿ç•™ä¸‹æ¥ã€‚</translation>
<translation id="2544644783021658368">å•ä¸€æ–‡æ¡£</translation>
<translation id="254947805923345898">政策值无效。</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> å‘é€çš„å“应无效。</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">如果您想获得 Chrome 最高级别的安全ä¿æŠ¤ï¼Œè¯·<ph name="BEGIN_ENHANCED_PROTECTION_LINK" />å¼€å¯å¢žå¼ºåž‹ä¿æŠ¤<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">找ä¸åˆ° <ph name="HOST_NAME" /> çš„æœåŠ¡å™¨ IP 地å€ã€‚</translation>
<translation id="2639739919103226564">状æ€ï¼š</translation>
+<translation id="264810637653812429">找ä¸åˆ°ä»»ä½•å…¼å®¹è®¾å¤‡ã€‚</translation>
<translation id="2649204054376361687"><ph name="COUNTRY" /><ph name="CITY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />,ä¾æ¬¡æŒ‰ Tab 键和 Enter é”®å³å¯åœ¨ Chrome 设置中清除您的æµè§ˆè®°å½•ã€Cookieã€ç¼“å­˜åŠå…¶ä»–æ•°æ®</translation>
<translation id="2650446666397867134">访问文件é­æ‹’</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">é‡æ–°å¯åŠ¨</translation>
<translation id="2803306138276472711">Google安全æµè§ˆåŠŸèƒ½æœ€è¿‘在<ph name="SITE" />上<ph name="BEGIN_LINK" />检测到了æ¶æ„软件<ph name="END_LINK" />。平常éžå¸¸å®‰å…¨çš„网站有时也会感染æ¶æ„软件。</translation>
<translation id="2807052079800581569">图片 Y è½´ä½ç½®</translation>
+<translation id="2820957248982571256">正在扫æ…</translation>
<translation id="2824775600643448204">地å€å’Œæœç´¢æ </translation>
<translation id="2826760142808435982">该连接使用 <ph name="CIPHER" /> 进行加密和身份验è¯ï¼Œå¹¶ä½¿ç”¨ <ph name="KX" /> 作为密钥交æ¢æœºåˆ¶ã€‚</translation>
<translation id="2835170189407361413">清除表å•</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">Invite (Envelope)</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="2859806420264540918">此网站展示过侵扰性或误导性广告。</translation>
+<translation id="287596039013813457">å‹å¥½</translation>
+<translation id="2876489322757410363">å°†è¦é€€å‡ºæ— ç—•æ¨¡å¼ï¼Œä»¥ä¾¿é€šè¿‡å¤–部应用付款。是å¦ç»§ç»­ï¼Ÿ</translation>
<translation id="2878197950673342043">海报折</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">窗å£æ”¾ç½®</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />,ä¾æ¬¡æŒ‰ Tab 键和 Enter é”®å³å¯ä»Ž Chrome 设置中è¿è¡Œå®‰å…¨æ£€æŸ¥</translation>
<translation id="3061707000357573562">修补æœåŠ¡</translation>
-<translation id="3064966200440839136">å°†è¦é€€å‡ºéšèº«æ¨¡å¼ï¼Œä»¥ä¾¿é€šè¿‡å¤–部应用付款。是å¦ç»§ç»­ï¼Ÿ</translation>
<translation id="306573536155379004">游æˆå·²å¼€å§‹ã€‚</translation>
<translation id="3080254622891793721">图形</translation>
<translation id="3086579638707268289">您在网络上的活动正被监控</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">您的å¸å·ç”± <ph name="MANAGER" /> 管ç†ã€‚</translation>
<translation id="3157931365184549694">æ¢å¤</translation>
<translation id="3162559335345991374">您è¦ä½¿ç”¨çš„ Wi-Fi 网络å¯èƒ½éœ€è¦æ‚¨è®¿é—®å…¶ç™»å½•é¡µé¢ã€‚</translation>
-<translation id="3167968892399408617">在您关闭所有无痕模å¼æ ‡ç­¾é¡µåŽï¼Œæ‚¨åœ¨è¿™äº›æ ‡ç­¾é¡µä¸­æŸ¥çœ‹çš„网页ä¸ä¼šåœ¨æµè§ˆå™¨åŽ†å²è®°å½•ã€Cookie 存储区或æœç´¢è®°å½•ä¸­ç•™ä¸‹ä»»ä½•ç—•è¿¹ã€‚ä¸è¿‡ï¼Œæ‚¨ä¸‹è½½çš„所有文件或创建的书签å‡ä¼šä¿ç•™ä¸‹æ¥ã€‚</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">å²›</translation>
<translation id="3176929007561373547">请检查您的代ç†æœåŠ¡å™¨è®¾ç½®æˆ–与网络管ç†å‘˜è”系,以确ä¿ä»£ç†æœåŠ¡å™¨æ­£å¸¸è¿è¡Œã€‚如果您认为自己ä¸éœ€è¦ä½¿ç”¨ä»£ç†æœåŠ¡å™¨ï¼Œè¯·æ‰§è¡Œä»¥ä¸‹æ“作:
@@ -591,10 +606,12 @@
<translation id="3229041911291329567">与您的设备和æµè§ˆå™¨ç›¸å…³çš„版本信æ¯</translation>
<translation id="323107829343500871">输入“<ph name="CREDIT_CARD" />â€çš„银行å¡éªŒè¯ç  (CVC)</translation>
<translation id="3234666976984236645">始终检测此网站上的é‡è¦å†…容</translation>
+<translation id="3249845759089040423">时髦</translation>
<translation id="3252266817569339921">法语</translation>
<translation id="3266793032086590337">值(冲çªï¼‰</translation>
<translation id="3268451620468152448">打开的标签页</translation>
<translation id="3270847123878663523">撤消顺åºè°ƒæ•´(&amp;U)</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> 希望连接到以下所选设备:</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">贵组织 <ph name="ENROLLMENT_DOMAIN" /> 已将æŸäº›ä¿¡æ¯ï¼ˆä¾‹å¦‚设置或政策)å‘é€ç»™ä¸‹åˆ—网站。</translation>
<translation id="3282497668470633863">添加æŒå¡äººå§“å</translation>
@@ -647,6 +664,7 @@
<translation id="3428151540071562330">一个或多个 DnsOverHttpsTemplates æœåŠ¡å™¨æ¨¡æ¿ URI 无效,因此ä¸ä¼šè¢«ä½¿ç”¨ã€‚</translation>
<translation id="3431636764301398940">将此å¡çš„ä¿¡æ¯ä¿å­˜åˆ°è¯¥è®¾å¤‡</translation>
<translation id="3432601291244612633">关闭页é¢</translation>
+<translation id="3435738964857648380">安全</translation>
<translation id="3435896845095436175">å¯ç”¨</translation>
<translation id="3438829137925142401">使用您 Google å¸å·ä¸­ä¿å­˜çš„密ç </translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -688,7 +706,10 @@
<translation id="3584299510153766161">åŒå­”(底部)</translation>
<translation id="3586931643579894722">éšè—详细信æ¯</translation>
<translation id="3587738293690942763">中间</translation>
+<translation id="3590643883886679995">当您退出无痕模å¼åŽï¼Œç™»å½•æ•°æ®ä¼šå­˜å‚¨åœ¨æ­¤è®¾å¤‡ä¸­ã€‚</translation>
+<translation id="359126217934908072">月/年:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{您å¯ä»¥éšæ—¶é‡ç½®è‡ªå·±æ‰€å±žçš„ç¾¤ç»„ã€‚å¤§çº¦éœ€è¦ 1 天的时间æ‰èƒ½åŠ å…¥æ–°ç¾¤ç»„。}=1{您å¯ä»¥éšæ—¶é‡ç½®è‡ªå·±æ‰€å±žçš„ç¾¤ç»„ã€‚å¤§çº¦éœ€è¦ 1 天的时间æ‰èƒ½åŠ å…¥æ–°ç¾¤ç»„。}other{您å¯ä»¥éšæ—¶é‡ç½®è‡ªå·±æ‰€å±žçš„ç¾¤ç»„ã€‚å¤§çº¦éœ€è¦ {NUM_DAYS} 天的时间æ‰èƒ½åŠ å…¥æ–°ç¾¤ç»„。}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />,<ph name="DOMAIN" />,<ph name="TIME" /></translation>
<translation id="3603507503523709">已被您的管ç†å‘˜ç¦ç”¨çš„应用</translation>
<translation id="3608932978122581043">é€çº¸æ–¹å‘</translation>
@@ -697,12 +718,12 @@
<translation id="3615877443314183785">请输入有效的失效日期</translation>
<translation id="36224234498066874">清除æµè§ˆæ•°æ®...</translation>
<translation id="362276910939193118">显示全部历å²è®°å½•</translation>
-<translation id="3625635938337243871">当您退出无痕模å¼åŽï¼Œç™»å½•æ•°æ®ä¼šå­˜å‚¨åœ¨æ­¤è®¾å¤‡ä¸­ã€‚</translation>
<translation id="3630155396527302611">如果它已在å¯è®¿é—®ç½‘络的程åºåˆ—表中,请å°è¯•å°†å®ƒä»Žè¯¥åˆ—表中移除,然åŽé‡æ–°æ·»åŠ åˆ°å…¶ä¸­ã€‚</translation>
<translation id="3630699740441428070">此设备的管ç†å‘˜å·²ç»é…置了您的网络连接,这项连接å¯èƒ½ä¼šå…许他们查看您的网络æµé‡ï¼ˆåŒ…括您访问的网站)。</translation>
<translation id="3631244953324577188">生物识别</translation>
<translation id="3633738897356909127">“更新 Chromeâ€æŒ‰é’®ï¼ŒæŒ‰ Enter é”®å³å¯å‰å¾€ Chrome 设置以更新 Chrome</translation>
<translation id="3634530185120165534">纸匣 5</translation>
+<translation id="3637662659967048211">ä¿å­˜åˆ° Google å¸å·</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">应用:</translation>
<translation id="3650584904733503804">验è¯æˆåŠŸ</translation>
@@ -743,6 +764,7 @@
<translation id="3781428340399460090">艳粉色</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">è“牙设备</translation>
+<translation id="3787675388804467730">虚拟å¡å·</translation>
<translation id="3787705759683870569">失效日期:<ph name="EXPIRATION_YEAR" /> 年 <ph name="EXPIRATION_MONTH" /> 月</translation>
<translation id="3789155188480882154">大å°ï¼š16</translation>
<translation id="3789841737615482174">安装</translation>
@@ -762,6 +784,7 @@
<translation id="3841184659773414994">文件处ç†ç¨‹åº</translation>
<translation id="385051799172605136">返回</translation>
<translation id="3858027520442213535">更新日期和时间</translation>
+<translation id="3881478300875776315">éšè—部分行</translation>
<translation id="3884278016824448484">设备标识符存在冲çª</translation>
<translation id="3885155851504623709">教区</translation>
<translation id="388632593194507180">检测到正被监控</translation>
@@ -787,6 +810,7 @@
<translation id="397105322502079400">正在计算...</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> 已被å±è”½</translation>
<translation id="3973357910713125165">“è¿è¡Œ Chrome 安全检查â€æŒ‰é’®ï¼ŒæŒ‰ Enter é”®å³å¯ä»Ž Chrome 设置中è¿è¡Œå®‰å…¨æ£€æŸ¥</translation>
+<translation id="3986705137476756801">暂时关闭“实时字幕â€åŠŸèƒ½</translation>
<translation id="3987405730340719549">Chrome 已确定此网站å¯èƒ½æ˜¯è™šå‡ç½‘站或欺诈性网站。
如果您认为系统ä¸è¯¥å‘您显示这æ¡æ示,请访问 https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals。</translation>
@@ -878,13 +902,14 @@
<translation id="4275830172053184480">é‡å¯æ‚¨çš„设备</translation>
<translation id="4277028893293644418">é‡ç½®å¯†ç </translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{这张å¡å·²ä¿å­˜åˆ°æ‚¨çš„ Google å¸å·ä¸­}other{这些å¡å·²ä¿å­˜åˆ°æ‚¨çš„ Google å¸å·ä¸­}}</translation>
+<translation id="4287885627794386150">符åˆè¯•ç”¨æ¡ä»¶ä½†å¤„于无效状æ€</translation>
<translation id="4297502707443874121">第 <ph name="THUMBNAIL_PAGE" /> 页的缩略图</translation>
<translation id="42981349822642051">展开</translation>
<translation id="4300675098767811073">多孔(å³ä¾§ï¼‰</translation>
<translation id="4302514097724775343">点按æ龙图标å³å¯å¼€å§‹çŽ©è¿™æ¬¾æ¸¸æˆ</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">无法访问您的文件</translation>
-<translation id="4305817255990598646">切æ¢</translation>
+<translation id="4306529830550717874">ä¿å­˜åœ°å€ï¼Ÿ</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">å±è”½ï¼ˆé»˜è®¤ï¼‰</translation>
<translation id="4314815835985389558">管ç†åŒæ­¥æ•°æ®</translation>
@@ -911,6 +936,7 @@
<translation id="4377125064752653719">您å°è¯•è®¿é—®çš„是 <ph name="DOMAIN" />,但æœåŠ¡å™¨å‡ºç¤ºçš„è¯ä¹¦å·²è¢«å…¶é¢å‘者åŠé”€ã€‚这表明ç»å¯¹ä¸åº”该信任此æœåŠ¡å™¨å‡ºç¤ºçš„安全凭æ®ã€‚您å¯èƒ½æ­£åœ¨ä¸Žæ”»å‡»è€…进行通信。</translation>
<translation id="4378154925671717803">电è¯æœº</translation>
<translation id="4390472908992056574">帽æªå¼</translation>
+<translation id="4406883609789734330">实时字幕</translation>
<translation id="4406896451731180161">æœç´¢ç»“æžœ</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" />Cookie</translation>
<translation id="4414290883293381923">您刚刚在一个诈骗网站中输入了密ç ã€‚Chrome 建议您立å³å‰å¾€ <ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" />ã€<ph name="WEBSITE_3" /> 以åŠä½¿ç”¨æ­¤å¯†ç çš„其他网站更改密ç ã€‚</translation>
@@ -923,7 +949,6 @@
<translation id="4435702339979719576">Postcard)</translation>
<translation id="443673843213245140">å·²åœç”¨ä»£ç†ï¼Œä½†æ˜¯æŒ‡å®šäº†æ˜Žç¡®çš„代ç†é…置。</translation>
<translation id="4464826014807964867">包å«æ¥è‡ªè´µç»„织的信æ¯çš„网站</translation>
-<translation id="4466881336512663640">对表å•æ‰€åšçš„更改将会丢失。确定è¦ç»§ç»­å—?</translation>
<translation id="4476953670630786061">此表å•ä¸å®‰å…¨ã€‚因此,系统已关闭自动填充功能。</translation>
<translation id="4477350412780666475">下一曲</translation>
<translation id="4482953324121162758">系统ä¸ä¼šç¿»è¯‘此网站。</translation>
@@ -941,7 +966,7 @@
<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>
<translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> 毫米(<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">详细信æ¯</translation>
+<translation id="4522570452068850558">详情</translation>
<translation id="4524138615196389145">从现在开始,您åªéœ€ä½¿ç”¨ WebAuthn 便能更快速地确认银行å¡</translation>
<translation id="4524805452350978254">管ç†å¡ç‰‡</translation>
<translation id="4542971377163063093">纸匣 6</translation>
@@ -957,6 +982,7 @@
<translation id="4594403342090139922">撤消删除(&amp;U)</translation>
<translation id="4597348597567598915">大å°ï¼š8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">富有影å“力</translation>
<translation id="4628948037717959914">照片</translation>
<translation id="4631649115723685955">已关è”返现</translation>
<translation id="4636930964841734540">ä¿¡æ¯</translation>
@@ -976,6 +1002,7 @@
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /><ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">侧边</translation>
+<translation id="4702656508969495934">能看到“实时字幕â€æ°”泡了,使用窗å£åˆ‡æ¢å™¨å¯åˆ‡æ¢ç„¦ç‚¹</translation>
<translation id="4708268264240856090">您的连接已中断</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />è¿è¡Œ Windows 网络诊断<ph name="END_LINK" /></translation>
@@ -989,6 +1016,7 @@
<translation id="4738601419177586157"><ph name="TEXT" />æœç´¢å»ºè®®</translation>
<translation id="4742407542027196863">管ç†å¯†ç â€¦</translation>
<translation id="4744603770635761495">å¯æ‰§è¡Œæ–‡ä»¶è·¯å¾„</translation>
+<translation id="4749011317274908093">您已进入无痕模å¼</translation>
<translation id="4750917950439032686">您å‘é€ç»™è¿™ä¸ªç½‘站的信æ¯ï¼ˆä¾‹å¦‚密ç æˆ–信用å¡å·ï¼‰ä¸ä¼šå¤–泄。</translation>
<translation id="4756388243121344051">历å²è®°å½•(&amp;H)</translation>
<translation id="4758311279753947758">添加è”系信æ¯</translation>
@@ -1018,6 +1046,8 @@
<translation id="4813512666221746211">网络错误</translation>
<translation id="4816492930507672669">适åˆé¡µé¢å¤§å°</translation>
<translation id="4819347708020428563">在默认视图中修改注释?</translation>
+<translation id="4825507807291741242">强大</translation>
+<translation id="4838327282952368871">梦幻</translation>
<translation id="484462545196658690">自动</translation>
<translation id="4850886885716139402">视图</translation>
<translation id="485316830061041779">德语</translation>
@@ -1154,6 +1184,7 @@
<translation id="5314967030527622926">手册制作工具</translation>
<translation id="5316812925700871227">逆时针旋转</translation>
<translation id="5317780077021120954">ä¿å­˜</translation>
+<translation id="5321288445143113935">最大化</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />,第 <ph name="MATCH_POSITION" /> 个(共 <ph name="NUM_MATCHES" /> 个)</translation>
<translation id="5324080437450482387">选择è”系信æ¯</translation>
<translation id="5327248766486351172">å称</translation>
@@ -1161,11 +1192,13 @@
<translation id="5332219387342487447">é€è´§æ–¹å¼</translation>
<translation id="5333022057423422993">Chrome å‘现您刚æ‰ä½¿ç”¨çš„密ç å·²é­é‡æ•°æ®æ³„露。为确ä¿æ‚¨çš„å¸å·å®‰å…¨ï¼Œå»ºè®®æ‚¨æ£€æŸ¥æ‚¨ä¿å­˜çš„密ç ã€‚</translation>
<translation id="5334013548165032829">详细的系统日志</translation>
+<translation id="5334145288572353250">ä¿å­˜åœ°å€ï¼Ÿ</translation>
<translation id="5340250774223869109">此应用已被ç¦ç”¨</translation>
<translation id="534295439873310000">NFC 设备</translation>
<translation id="5344579389779391559">此页é¢å¯èƒ½ä¼šå‘您收å–费用</translation>
<translation id="5355557959165512791">您目å‰æ— æ³•è®¿é—® <ph name="SITE" />,因为此è¯ä¹¦å·²è¢«æ’¤æ¶ˆã€‚网络错误和攻击行为通常是暂时的,因此,此网页ç¨åŽå¯èƒ½ä¼šæ¢å¤æ­£å¸¸ã€‚</translation>
<translation id="536296301121032821">无法存储策略设置</translation>
+<translation id="5363309033720083897">您的管ç†å‘˜å…许使用的串行端å£</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="5386426401304769735">此网站的è¯ä¹¦é“¾åŒ…å«ä½¿ç”¨ SHA-1 签署的è¯ä¹¦ã€‚</translation>
@@ -1174,6 +1207,7 @@
<translation id="5398772614898833570">广告已被拦截</translation>
<translation id="5400836586163650660">ç°è‰²</translation>
<translation id="540969355065856584">æ­¤æœåŠ¡å™¨æ— æ³•è¯æ˜Žå®ƒæ˜¯ <ph name="DOMAIN" />;其安全è¯ä¹¦ç›®å‰æ— æ•ˆã€‚出现此问题的原因å¯èƒ½æ˜¯é…置有误或您的连接被拦截了。</translation>
+<translation id="541143247543991491">云端(系统级)</translation>
<translation id="541416427766103491">å †å å‡ºçº¸å™¨ 4</translation>
<translation id="5421136146218899937">清除æµè§ˆæ•°æ®...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> 想å‘您å‘é€é€šçŸ¥</translation>
@@ -1187,6 +1221,7 @@
<translation id="5455374756549232013">策略时间戳无效</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" /> åè”系人}other{<ph name="CONTACT_PREVIEW" />以åŠå¦å¤– <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> åè”系人}}</translation>
+<translation id="5463625433003343978">正在查找设备…</translation>
<translation id="5469868506864199649">æ„大利语</translation>
<translation id="5470861586879999274">æ¢å¤ä¿®æ”¹(&amp;R)</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1236,7 +1271,6 @@
<translation id="5624120631404540903">管ç†å¯†ç </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="563324245173044180">欺骗性内容已被拦截。</translation>
<translation id="5644090287519800334">侧边 1,图片沿 X è½´ä½ç§»</translation>
@@ -1275,12 +1309,12 @@
<translation id="5785756445106461925">而且,此页中包å«å…¶ä»–ä¸å®‰å…¨çš„资æºã€‚他人能在这些资æºä¼ è¾“过程中进行查看,攻击者也å¯ä»¥ä¿®æ”¹è¿™äº›èµ„æºï¼Œä»Žè€Œæ”¹å˜æ­¤é¡µçš„外观。</translation>
<translation id="5786044859038896871">è¦å¡«å……您的信用å¡ä¿¡æ¯å—?</translation>
<translation id="578633867165174378">Chrome å‘现您刚æ‰ä½¿ç”¨çš„密ç å·²é­é‡æ•°æ®æ³„露。建议您立å³æ›´æ”¹æ­¤å¯†ç ã€‚</translation>
-<translation id="5798290721819630480">èˆå¼ƒæ›´æ”¹ï¼Ÿ</translation>
<translation id="5803412860119678065">è¦å¡«å……您的“<ph name="CARD_DETAIL" />â€å—?</translation>
<translation id="5804241973901381774">æƒé™</translation>
<translation id="5804427196348435412">使用 NFC 设备</translation>
<translation id="5810442152076338065">您与 <ph name="DOMAIN" /> 之间的连接采用过时的加密套件进行了加密。</translation>
<translation id="5813119285467412249">æ¢å¤æ·»åŠ (&amp;R)</translation>
+<translation id="5817918615728894473">é…对</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{当您付款时,系统会从这张å¡ä¸­æ‰£æ¬¾ï¼Œä½†ä¸ä¼šå°†å…¶çœŸå®žå¡å·åˆ†äº«ç»™æ­¤ç½‘站。为进一步增强安全ä¿éšœï¼Œç³»ç»Ÿä¼šç”Ÿæˆä¸€ä¸ªä¸´æ—¶çš„银行å¡éªŒè¯ç  (CVC)。}other{当您付款时,系统会从您所选的å¡ä¸­æ‰£æ¬¾ï¼Œä½†ä¸ä¼šå°†å…¶çœŸå®žå¡å·åˆ†äº«ç»™æ­¤ç½‘站。为进一步增强安全ä¿éšœï¼Œç³»ç»Ÿä¼šç”Ÿæˆä¸€ä¸ªä¸´æ—¶çš„银行å¡éªŒè¯ç  (CVC)。}}</translation>
<translation id="5826507051599432481">公用å (CN)</translation>
<translation id="5838278095973806738">请勿在此网站上输入任何æ•æ„Ÿä¿¡æ¯ï¼ˆä¾‹å¦‚密ç æˆ–信用å¡ä¿¡æ¯ï¼‰ï¼Œå› ä¸ºæ”»å‡»è€…å¯èƒ½ä¼šç›—å–这些信æ¯ã€‚</translation>
@@ -1288,6 +1322,7 @@
<translation id="5855253129151731373">此网站的主机å看起æ¥å’Œ <ph name="LOOKALIKE_DOMAIN" /> 很相似。攻击者有时会对域ååšäº›ä»¤äººéš¾ä»¥å‘现的细微更改æ¥ä»¿å†’网站。
如果您认为系统ä¸è¯¥å‘您显示这æ¡æ示,请访问 https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals。</translation>
+<translation id="5860033963881614850">关闭</translation>
<translation id="5862579898803147654">å †å å‡ºçº¸å™¨ 8</translation>
<translation id="5863847714970149516">å³å°†è¿›å…¥çš„页é¢å¯èƒ½ä¼šå‘您收å–费用</translation>
<translation id="5866257070973731571">添加电è¯å·ç </translation>
@@ -1304,6 +1339,7 @@
<translation id="5913377024445952699">å±å¹•æˆªå–功能已暂åœ</translation>
<translation id="59174027418879706">å·²å¯ç”¨</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{正在使用 1 个}other{正在使用 # 个}}</translation>
<translation id="5921185718311485855">已开å¯</translation>
<translation id="5921639886840618607">将银行å¡ä¿¡æ¯ä¿å­˜åˆ° Google å¸å·ä¸­ï¼Ÿ</translation>
<translation id="5922853866070715753">å³å°†å®Œæˆ</translation>
@@ -1323,6 +1359,7 @@
<translation id="5989320800837274978">固定代ç†æœåŠ¡å™¨å’Œ .pac 脚本网å€å‡æœªæŒ‡å®šã€‚</translation>
<translation id="5992691462791905444">工程 Z 型折</translation>
<translation id="6000758707621254961"><ph name="RESULT_COUNT" /> 个与“<ph name="SEARCH_TEXT" />â€ç›¸ç¬¦çš„æœç´¢ç»“æžœ</translation>
+<translation id="6006484371116297560">ç»å…¸</translation>
<translation id="6008122969617370890">从 N 到 1 的顺åº</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">检查您的密ç </translation>
@@ -1344,6 +1381,7 @@
<translation id="6045164183059402045">拼版模æ¿</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="6049004884579590341">æŒ‰ä½ |<ph name="ACCELERATOR" />| å³å¯é€€å‡ºå…¨å±æ¨¡å¼</translation>
<translation id="6049488691372270142">页é¢ä¼ é€</translation>
<translation id="6051221802930200923">您目å‰æ— æ³•è®¿é—® <ph name="SITE" />,因为此网站使用了è¯ä¹¦é”定。网络错误和攻击通常是暂时的,因此,此网页ç¨åŽå¯èƒ½ä¼šæ¢å¤æ­£å¸¸ã€‚</translation>
<translation id="6051898664905071243">页数:</translation>
@@ -1360,6 +1398,7 @@
<translation id="610911394827799129">您的 Google å¸å·åœ¨ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> 上å¯èƒ½æœ‰å…¶ä»–å½¢å¼çš„æµè§ˆè®°å½•</translation>
<translation id="6116338172782435947">查看å¤åˆ¶åˆ°å‰ªè´´æ¿çš„文字和图片</translation>
<translation id="6120179357481664955">è¦è®°ä½æ‚¨çš„ UPI ID å—?</translation>
+<translation id="6123290840358279103">查看虚拟å¡</translation>
<translation id="6124432979022149706">Chrome ä¼ä¸šç‰ˆè¿žæŽ¥å™¨</translation>
<translation id="6146055958333702838">请检查所有网线是å¦éƒ½å·²è¿žå¥½ï¼Œç„¶åŽé‡æ–°å¯åŠ¨æ‚¨å¯èƒ½æ­£åœ¨ä½¿ç”¨çš„任何路由器ã€è°ƒåˆ¶è§£è°ƒå™¨æˆ–其他网络设备。</translation>
<translation id="614940544461990577">请试试以下办法:</translation>
@@ -1395,6 +1434,7 @@
<translation id="6289939620939689042">页é¢é¢œè‰²</translation>
<translation id="6290238015253830360">为您推è的文章会显示在此处</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">Chrome 中的 Google 助ç†å³å°†åœæ­¢å·¥ä½œ</translation>
<translation id="6305205051461490394">无法访问 <ph name="URL" />。</translation>
<translation id="6312113039770857350">网页无法打开</translation>
@@ -1420,6 +1460,7 @@
<translation id="6390200185239044127">Z 型对折</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">管ç†å‘˜æ”¿ç­–ç¦æ­¢å°† <ph name="ORIGIN_NAME" /> 上的内容粘贴到此处</translation>
+<translation id="6398765197997659313">退出全å±æ¨¡å¼</translation>
<translation id="6401136357288658127">此政策已被弃用。您应改用 <ph name="NEW_POLICY" /> 政策。</translation>
<translation id="6404511346730675251">修改书签</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1432,7 +1473,6 @@
<translation id="6428450836711225518">验è¯æ‚¨çš„手机å·ç </translation>
<translation id="6433490469411711332">修改è”系信æ¯</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> æ‹’ç»äº†æˆ‘们的连接请求。</translation>
-<translation id="6434309073475700221">èˆå¼ƒ</translation>
<translation id="6440503408713884761">已忽略</translation>
<translation id="6443406338865242315">您已安装的扩展程åºå’Œæ’件</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1475,6 +1515,7 @@
<translation id="6624427990725312378">è”系信æ¯</translation>
<translation id="6626291197371920147">添加有效的å¡å·</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> æœç´¢</translation>
+<translation id="6630043285902923878">正在查找 USB 设备…</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">清除</translation>
@@ -1490,6 +1531,7 @@
<translation id="6671697161687535275">è¦ä»Ž Chromium 中移除表å•å¡«å†™å»ºè®®å—?</translation>
<translation id="6685834062052613830">请退出并完æˆè®¾ç½®</translation>
<translation id="6687335167692595844">请求的字å·</translation>
+<translation id="6688743156324860098">更新…</translation>
<translation id="6689249931105087298">相对(使用黑点压缩)</translation>
<translation id="6689271823431384964">Chrome 正在询问是å¦è¦å°†å¡ä¿å­˜åˆ°æ‚¨çš„ Google å¸å·ä¸­ï¼Œå› ä¸ºæ‚¨å·²ç™»å½•ã€‚您å¯åœ¨â€œè®¾ç½®â€ä¸­æ›´æ”¹æ­¤è¡Œä¸ºã€‚æŒå¡äººå§“åæ¥è‡ªæ‚¨çš„å¸å·ã€‚</translation>
<translation id="6698381487523150993">创建时间:</translation>
@@ -1505,6 +1547,7 @@
<translation id="6744009308914054259">在等待连接时,您å¯ä»¥å‰å¾€â€œä¸‹è½½å†…容â€é¡µé¢é˜…读离线文章。</translation>
<translation id="6753269504797312559">政策值</translation>
<translation id="6757797048963528358">您的设备已进入休眠模å¼ã€‚</translation>
+<translation id="6767985426384634228">更新地å€ï¼Ÿ</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">紫罗兰色</translation>
@@ -1527,6 +1570,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome 已简化该页é¢ï¼Œè®©å†…容更易于阅读,并且通过ä¸å®‰å…¨çš„连接检索到了原始网页。</translation>
<translation id="6891596781022320156">政策级别ä¸å—支æŒã€‚</translation>
+<translation id="6895143722905299846">虚拟å¡å·ï¼š</translation>
<translation id="6895330447102777224">已确认您的信用å¡</translation>
<translation id="6897140037006041989">用户代ç†</translation>
<translation id="6898699227549475383">组织 (O)</translation>
@@ -1562,10 +1606,10 @@
<translation id="7004583254764674281">使用 Windows Hello 更快地确认银行å¡</translation>
<translation id="7006930604109697472">ä»ç„¶å‘é€</translation>
<translation id="7012363358306927923">中国银è”</translation>
-<translation id="7012404007611495949">与调整大å°æœ‰å…³çš„设置</translation>
<translation id="7014741021609395734">缩放级别</translation>
<translation id="7016992613359344582">这些费用å¯èƒ½åªæ”¶å–一次,也å¯èƒ½ä¼šå‘¨æœŸæ€§æ”¶å–,而且å¯èƒ½ä¸æ˜“察觉。</translation>
<translation id="7029809446516969842">密ç </translation>
+<translation id="7030436163253143341">è¯ä¹¦æ— æ•ˆ</translation>
<translation id="7031646650991750659">您已安装的 Google Play 应用</translation>
<translation id="7050187094878475250">您å°è¯•è®¿é—® <ph name="DOMAIN" />,但æœåŠ¡å™¨æ供的è¯ä¹¦ä¸å¯ä¿¡ï¼ˆæœ‰æ•ˆæœŸè¿‡é•¿ï¼‰ã€‚</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{此刻无法ä¿å­˜è¿™å¼ å¡}other{此刻无法ä¿å­˜è¿™äº›å¡}}</translation>
@@ -1635,12 +1679,14 @@
<translation id="7300012071106347854">é’´è“色</translation>
<translation id="7302712225291570345">“<ph name="TEXT" />â€</translation>
<translation id="7304030187361489308">高</translation>
+<translation id="7305756307268530424">å¯ç”¨æ…¢é€Ÿæ¨¡å¼</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">与连接相关的帮助</translation>
<translation id="7323804146520582233">éšè—“<ph name="SECTION" />â€éƒ¨åˆ†</translation>
<translation id="733354035281974745">设备本地å¸å·æ›¿æ¢</translation>
<translation id="7333654844024768166">您刚刚在一个诈骗网站中输入了密ç ã€‚Chromium 建议您立å³å‰å¾€ <ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" />ã€<ph name="WEBSITE_3" /> 以åŠä½¿ç”¨æ­¤å¯†ç çš„其他网站更改密ç ã€‚</translation>
<translation id="7334320624316649418">æ¢å¤é¡ºåºè°ƒæ•´(&amp;R)</translation>
+<translation id="7337248890521463931">显示更多行</translation>
<translation id="7337706099755338005">在您的平å°ä¸Šä¸å¯ç”¨ã€‚</translation>
<translation id="733923710415886693">该æœåŠ¡å™¨çš„è¯ä¹¦æœªé€šè¿‡è¯ä¹¦é€æ˜Žåº¦æ”¿ç­–进行披露。</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1648,6 +1694,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">命令行</translation>
<translation id="7359588939039777303">广告已被拦截。</translation>
+<translation id="7363096869660964304">但是,这并ä¸æ„味ç€æ‚¨èƒ½å®Œå…¨éšèº«ã€‚å³ä½¿æ‚¨è¿›å…¥æ— ç—•æ¨¡å¼ï¼Œæ‚¨çš„雇主ã€äº’è”网æœåŠ¡æ供商和您访问的网站ä»ç„¶èƒ½çœ‹åˆ°æ‚¨çš„æµè§ˆæ´»åŠ¨ã€‚</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />,ä¾æ¬¡æŒ‰ Tab 键和 Enter é”®å³å¯åœ¨ Chrome 设置中添加和管ç†åœ°å€</translation>
<translation id="7365849542400970216">å…许网站了解您的设备使用情况?</translation>
<translation id="7372973238305370288">æœç´¢ç»“æžœ</translation>
@@ -1658,7 +1705,9 @@
<translation id="7378594059915113390">媒体控件</translation>
<translation id="7378627244592794276">å¦</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ä¸é€‚用</translation>
<translation id="7390545607259442187">确认信用å¡</translation>
+<translation id="7392089738299859607">更新地å€</translation>
<translation id="7399802613464275309">安全检查</translation>
<translation id="7400418766976504921">网å€</translation>
<translation id="7403591733719184120">您的 <ph name="DEVICE_NAME" /> å—管ç†</translation>
@@ -1673,6 +1722,7 @@
&lt;li&gt;访问 &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome 帮助中心&lt;/a&gt;,了解如何从您的计算机中永久移除该软件
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">å¯çˆ±</translation>
<translation id="7416351320495623771">管ç†å¯†ç â€¦</translation>
<translation id="7419106976560586862">个人资料路径</translation>
<translation id="7437289804838430631">添加è”系信æ¯</translation>
@@ -1688,7 +1738,7 @@
<translation id="7481312909269577407">å‰è¿›</translation>
<translation id="7485870689360869515">找ä¸åˆ°æ•°æ®ã€‚</translation>
<translation id="7495528107193238112">该内容被å±è”½äº†ã€‚请è”系网站所有者以解决此问题。</translation>
-<translation id="7498234416455752244">继续修改</translation>
+<translation id="7498193950643227031">如果调整大å°ï¼Œåº”用å¯èƒ½ä¼šå‡ºçŽ°æ„外行为。现在,您å¯ä»Žâ€œ<ph name="SETTINGS" />â€ä¸­é™åˆ¶è°ƒæ•´åº”用大å°çš„功能。</translation>
<translation id="7503664977220660814">您刚刚在一个诈骗网站中输入了密ç ã€‚Chromium 建议您立å³å‰å¾€ <ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" /> 以åŠä½¿ç”¨æ­¤å¯†ç çš„其他网站检查您ä¿å­˜çš„密ç ã€‚</translation>
<translation id="7508255263130623398">返回的政策设备 ID 为空,或与当å‰çš„设备 ID ä¸ä¸€è‡´</translation>
<translation id="7508870219247277067">黄绿色</translation>
@@ -1708,6 +1758,7 @@
<translation id="7548892272833184391">修正网络连接错误</translation>
<translation id="7549584377607005141">此网页需è¦ä½¿ç”¨æ‚¨ä¹‹å‰è¾“入的数æ®æ‰èƒ½æ­£å¸¸æ˜¾ç¤ºã€‚您å¯ä»¥é‡æ–°å‘é€è¿™äº›æ•°æ®ï¼Œä¸è¿‡ï¼Œè¿™ä¹ˆåšä¼šé‡å¤æ‰§è¡Œæ­¤ç½‘页之å‰æ‰§è¡Œè¿‡çš„所有æ“作。</translation>
<translation id="7550637293666041147">您的设备用户åå’Œ Chrome 用户å</translation>
+<translation id="755279583747225797">试用版功能处于有效状æ€</translation>
<translation id="7552846755917812628">请å°è¯•æŒ‰ä»¥ä¸‹æ示æ“作:</translation>
<translation id="7554475479213504905">ä»ç„¶é‡æ–°åŠ è½½å¹¶æ˜¾ç¤º</translation>
<translation id="7554791636758816595">新标签页</translation>
@@ -1726,7 +1777,6 @@
<translation id="7610193165460212391">值超出了范围 (<ph name="VALUE" />)。</translation>
<translation id="7613889955535752492">过期时间:<ph name="EXPIRATION_YEAR" /> 年 <ph name="EXPIRATION_MONTH" /> 月</translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />,ä¾æ¬¡æŒ‰ Tab 键和 Enter é”®å³å¯åœ¨ Chrome 设置中查看和管ç†æ‚¨çš„密ç </translation>
-<translation id="7615602087246926389">您已ç»ä½¿ç”¨ä¸åŒç‰ˆæœ¬çš„ Google å¸å·å¯†ç åŠ å¯†äº†æ•°æ®ã€‚请在下方输入。</translation>
<translation id="7616645509853975347">您的管ç†å‘˜å·²åœ¨æ‚¨çš„æµè§ˆå™¨ä¸­å¯ç”¨äº† Chrome ä¼ä¸šç‰ˆæŽ¥å£ã€‚这些接å£å¯ä»¥è®¿é—®æ‚¨çš„部分数æ®ã€‚</translation>
<translation id="7619838219691048931">结尾工作表</translation>
<translation id="762844065391966283">一次一个</translation>
@@ -1791,13 +1841,12 @@
<translation id="782886543891417279">您è¦ä½¿ç”¨çš„ Wi-Fi 网络(<ph name="WIFI_NAME" />)å¯èƒ½éœ€è¦æ‚¨è®¿é—®å…¶ç™»å½•é¡µé¢ã€‚</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{æ— }=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">使用文件类型关è”项打开文件。</translation>
<translation id="7862185352068345852">离开此网站?</translation>
<translation id="7865448901209910068">最快的速度</translation>
<translation id="7874263914261512992">您刚刚在一个诈骗网站中输入了密ç ã€‚Chrome 建议您立å³å‰å¾€ <ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" /> 以åŠä½¿ç”¨æ­¤å¯†ç çš„其他网站检查您ä¿å­˜çš„密ç ã€‚</translation>
<translation id="7878562273885520351">您的密ç å¯èƒ½ä¼šè¢«ç›—用</translation>
+<translation id="7880146494886811634">ä¿å­˜åœ°å€</translation>
<translation id="7882421473871500483">棕色</translation>
<translation id="7887683347370398519">请检查您的银行å¡éªŒè¯ç  (CVC),然åŽé‡è¯•</translation>
<translation id="7887885240995164102">进入“画中画â€æ¨¡å¼</translation>
@@ -1805,6 +1854,7 @@
<translation id="7894280532028510793">如果拼写无误,请<ph name="BEGIN_LINK" />å°è¯•è¿è¡Œç½‘络诊断<ph name="END_LINK" />。</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">未知</translation>
+<translation id="793209273132572360">更新地å€ï¼Ÿ</translation>
<translation id="7932579305932748336">涂层</translation>
<translation id="79338296614623784">请输入有效的电è¯å·ç </translation>
<translation id="7934052535022478634">付款已完æˆ</translation>
@@ -1875,6 +1925,7 @@
<translation id="8175796834047840627">Chrome 会主动询问是å¦è¦å°†æ‚¨çš„å¡ä¿å­˜åˆ°æ‚¨çš„ Google å¸å·ä¸­ï¼Œå› ä¸ºæ‚¨å·²ç™»å½•ã€‚您å¯åœ¨â€œè®¾ç½®â€ä¸­æ›´æ”¹æ­¤è¡Œä¸ºã€‚</translation>
<translation id="8176440868214972690">此设备的管ç†å‘˜å·²å°†æŸäº›ä¿¡æ¯ï¼ˆä¾‹å¦‚设置或政策)å‘é€ç»™ä¸‹åˆ—网站。</translation>
<translation id="8184538546369750125">使用全局默认设置(å…许)</translation>
+<translation id="8193086767630290324">使用标记为机密的数æ®æ‰§è¡Œçš„æ“作</translation>
<translation id="8194797478851900357">撤消移动(&amp;U)</translation>
<translation id="8201077131113104583">ID 为“<ph name="EXTENSION_ID" />â€çš„扩展程åºçš„更新网å€æ— æ•ˆã€‚</translation>
<translation id="8202097416529803614">订å•æ‘˜è¦</translation>
@@ -1897,6 +1948,7 @@
<translation id="8249296373107784235">å–消</translation>
<translation id="8249320324621329438">最åŽä¸€æ¬¡æŠ“å–时间:</translation>
<translation id="8253091569723639551">è´¦å•é‚®å¯„地å€æ˜¯å¿…填项</translation>
+<translation id="8257387598443225809">此应用是专为移动设备设计的</translation>
<translation id="825929999321470778">显示所有已ä¿å­˜çš„密ç </translation>
<translation id="8261506727792406068">删除</translation>
<translation id="8262952874573525464">边缘装订(底部)</translation>
@@ -2021,7 +2073,6 @@
<translation id="8719528812645237045">多孔(顶部)</translation>
<translation id="8725066075913043281">é‡è¯•</translation>
<translation id="8726549941689275341">页é¢å°ºå¯¸ï¼š</translation>
-<translation id="8728672262656704056">您已进入无痕模å¼</translation>
<translation id="8730621377337864115">完æˆ</translation>
<translation id="8731544501227493793">“管ç†å¯†ç â€æŒ‰é’®ï¼ŒæŒ‰ Enter é”®å³å¯åœ¨ Chrome 设置中查看和管ç†æ‚¨çš„密ç </translation>
<translation id="8734529307927223492">您的 <ph name="DEVICE_TYPE" /> ç”± <ph name="MANAGER" /> 管ç†</translation>
@@ -2098,6 +2149,7 @@
<translation id="9020542370529661692">已将此网页内容翻译æˆ<ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(无效)</translation>
+<translation id="9030265603405983977">å•è‰²</translation>
<translation id="9035022520814077154">安全错误</translation>
<translation id="9038649477754266430">使用è”想查询æœåŠ¡æ›´å¿«é€Ÿåœ°åŠ è½½ç½‘页</translation>
<translation id="9039213469156557790">而且,此页中包å«å…¶ä»–ä¸å®‰å…¨çš„资æºã€‚他人能在这些资æºä¼ è¾“过程中进行查看,而攻击者å¯ä»¥ä¿®æ”¹è¿™äº›èµ„æºï¼Œä»Žè€Œæ”¹å˜æ­¤é¡µçš„行为。</translation>
@@ -2121,6 +2173,7 @@
<translation id="91108059142052966">管ç†å‘˜æ”¿ç­–ç¦æ­¢åœ¨å±å¹•æ˜¾ç¤ºæœºå¯†å†…容时与<ph name="APPLICATION_TITLE" />共享å±å¹•</translation>
<translation id="9114524666733003316">正在确认信用å¡â€¦</translation>
<translation id="9114581008513152754">æ­¤æµè§ˆå™¨å¹¶æœªç”±æŸä¸ªå…¬å¸æˆ–其他组织管ç†ã€‚此设备上的活动å¯èƒ½åœ¨æŽ¥å— Chrome 外部的管ç†ã€‚<ph name="BEGIN_LINK" />了解详情<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">清新</translation>
<translation id="9119042192571987207">已上传</translation>
<translation id="9128016270925453879">政策已加载完毕</translation>
<translation id="9128870381267983090">连接到网络</translation>
@@ -2139,6 +2192,7 @@
<translation id="9170848237812810038">撤消(&amp;U)</translation>
<translation id="9171296965991013597">è¦é€€å‡ºåº”用å—?</translation>
<translation id="9173282814238175921">å•ä¸€æ–‡æ¡£/新工作表</translation>
+<translation id="9173995187295789444">正在扫æè“牙设备…</translation>
<translation id="917450738466192189">æœåŠ¡å™¨è¯ä¹¦æ— æ•ˆã€‚</translation>
<translation id="9174917557437862841">标签页切æ¢æŒ‰é’®ï¼ŒæŒ‰ Enter é”®å¯åˆ‡æ¢åˆ°æ­¤æ ‡ç­¾é¡µ</translation>
<translation id="9179703756951298733">请在 Chrome 设置中管ç†æ‚¨çš„付款和信用å¡ä¿¡æ¯</translation>
diff --git a/chromium/components/strings/components_strings_zh-HK.xtb b/chromium/components/strings/components_strings_zh-HK.xtb
index 3ade09b6e07..6ac6882e9ae 100644
--- a/chromium/components/strings/components_strings_zh-HK.xtb
+++ b/chromium/components/strings/components_strings_zh-HK.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">勾é¸å¾Œï¼ŒChrome 會在此è£ç½®ä¸Šå„²å­˜å¡ç‰‡å‰¯æœ¬ï¼Œè®“您填寫表格更快速。</translation>
<translation id="1110994991967754504">é¸æ“‡å°<ph name="PERMISSION_NAME" />的權é™</translation>
<translation id="1113869188872983271">復原é‡æ–°æŽ’åº(&amp;U)</translation>
+<translation id="1123753900084781868">ç›®å‰ç„¡æ³•ä½¿ç”¨å³æ™‚字幕</translation>
<translation id="1125573121925420732">在網站進行安全性更新時,å¯èƒ½æœƒç¶“常看到警告。我們會盡快改善此å•é¡Œã€‚</translation>
<translation id="112840717907525620">政策快å–正確</translation>
<translation id="1130564665089811311">翻譯網é æŒ‰éˆ•ï¼Œã©’一下 Enter éµå°±å¯ä»¥é€éŽ Google 翻譯翻譯呢個網é </translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">您的è£ç½®å稱</translation>
<translation id="124116460088058876">更多語言</translation>
<translation id="1243027604378859286">作者:</translation>
+<translation id="1246424317317450637">ç²—é«”</translation>
<translation id="1250759482327835220">åªè¦å°‡æ‚¨çš„付款å¡ã€å§“å和帳單地å€å„²å­˜è‡³æ‚¨çš„ Google 帳戶,下次å³å¯æ›´å¿«å®Œæˆä»˜æ¬¾ç¨‹åºã€‚</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />ã€<ph name="TYPE_2" /> (å·²åŒæ­¥)</translation>
<translation id="1256368399071562588">&lt;p&gt;如果您無法順利開啟網站,請先執行以下解決疑難步驟來修正錯誤:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">變更您的密碼</translation>
<translation id="1484290072879560759">é¸æ“‡ä»˜é‹åœ°å€</translation>
<translation id="1492194039220927094">政策推é€ï¼š</translation>
+<translation id="1495677929897281669">返回分é </translation>
<translation id="1501859676467574491">顯示您 Google 帳戶中的付款å¡</translation>
<translation id="1507202001669085618">&lt;p&gt;如果您正在使用的 Wi-Fi å…¥å£ç¶²ç«™éœ€è¦ç™»å…¥æ‰èƒ½é€£ç·šè‡³ç¶²çµ¡ï¼Œä¾¿æœƒçœ‹åˆ°æ­¤éŒ¯èª¤è¨Šæ¯ã€‚&lt;/p&gt;
&lt;p&gt;如è¦ä¿®æ­£éŒ¯èª¤ï¼Œè«‹åœ¨å˜—試開啟的網é ä¸ŠæŒ‰ä¸€ä¸‹ [連線]&lt;strong&gt;&lt;/strong&gt;。&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">此網é é¡¯ç¤ºï¼š</translation>
<translation id="153384715582417236">暫時沒有其他項目</translation>
<translation id="1536390784834419204">翻譯網é </translation>
+<translation id="1539840569003678498">報告傳é€æ™‚間:</translation>
<translation id="154408704832528245">é¸æ“‡é€Ÿéžåœ°å€</translation>
<translation id="1549470594296187301">必須啟用 JavaScript æ‰èƒ½ä½¿ç”¨æ­¤åŠŸèƒ½ã€‚</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">先從短邊開始</translation>
<translation id="168693727862418163">此政策的值無法通éŽå…¶ç¶±è¦ (schema) 的驗證,因此會被忽略。</translation>
<translation id="168841957122794586">伺æœå™¨æ†‘è­‰å«æœ‰é˜²è­·åŠ›è–„弱的加密編譯金鑰。</translation>
+<translation id="1696290444144917273">查看虛擬付款å¡è³‡æ–™</translation>
<translation id="1697532407822776718">大功告æˆï¼</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{伺æœå™¨ç„¡æ³•è­‰æ˜Žå±¬æ–¼ <ph name="DOMAIN" /> 網域;其安全性憑證é æœŸæ–¼æ˜Žå¤©ç”Ÿæ•ˆã€‚這å¯èƒ½æ˜¯ç”±æ–¼è¨­å®šéŒ¯èª¤ï¼Œæˆ–有攻擊者攔截您的連線。}other{伺æœå™¨ç„¡æ³•è­‰æ˜Žå±¬æ–¼ <ph name="DOMAIN" /> 網域;其安全性憑證é æœŸæ–¼ # 天後生效。這å¯èƒ½æ˜¯ç”±æ–¼è¨­å®šéŒ¯èª¤ï¼Œæˆ–有攻擊者攔截您的連線。}}</translation>
<translation id="1710259589646384581">作業系統</translation>
+<translation id="1711234383449478798">由於「<ph name="POLICY_NAME" />ã€æœªè¨­å®šç‚ºã€Œ<ph name="VALUE" />ã€ï¼Œå› æ­¤è¢«å¿½ç•¥ã€‚</translation>
<translation id="1712552549805331520"><ph name="URL" /> è¦æ±‚在您的本機電腦上永久儲存數據</translation>
<translation id="1713628304598226412">紙匣 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">出紙槽 3</translation>
<translation id="1718029547804390981">文件éŽå¤§ï¼Œç„¡æ³•åŠ å…¥è¨»é‡‹</translation>
<translation id="1721424275792716183">* 為必填欄ä½</translation>
+<translation id="1727613060316725209">憑證有效</translation>
<translation id="1727741090716970331">新增有效的信用å¡è™Ÿç¢¼</translation>
<translation id="1728677426644403582">您正在查看網é çš„原始碼</translation>
<translation id="173080396488393970">ä¸æ”¯æ´æ­¤ä¿¡ç”¨å¡é¡žåž‹</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />嘗試執行 Windows 網絡診斷<ph name="END_LINK" />。</translation>
<translation id="1772163372082567643">您的目標伺æœå™¨ã€Œ<ph name="ORIGIN" />ã€å·²è¨­å®šæ¨™é¡Œè¦æ±‚為收到的所有è¦æ±‚套用來æºæ”¿ç­–。ä¸éŽï¼Œç”±æ–¼è©²æ¨™é¡Œæ ¼å¼éŒ¯èª¤ï¼Œå› æ­¤ç€è¦½å™¨ç„¡æ³•å®Œæˆæ‚¨å‘ <ph name="SITE" /> æ出的è¦æ±‚。網站網絡供應商å¯ä½¿ç”¨ä¾†æºæ”¿ç­–設定網站的安全性åŠå…¶ä»–屬性。</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">請更新您的åŒæ­¥è¤‡é›œå¯†ç¢¼ã€‚</translation>
<translation id="1787142507584202372">您最近開啟的分é æœƒåœ¨é€™è£¡é¡¯ç¤º</translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />,å¯ä»¥é€²è¡Œå¹¾ç¨®å‹•ä½œï¼Œã©’ Tab éµå°±å¯ä»¥è·Ÿæ¬¡åºè½‰æ›å””åŒå˜…動作</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">廣告</translation>
<translation id="1919367280705858090">瞭解如何修正特定錯誤訊æ¯æŒ‡å‡ºçš„錯誤</translation>
<translation id="192020519938775529">{COUNT,plural, =0{無}=1{1 個網站}other{# 個網站}}</translation>
+<translation id="1924727005275031552">新地å€</translation>
<translation id="1945968466830820669">您有å¯èƒ½æœƒå¤±åŽ»æ©Ÿæ§‹å¸³æˆ¶å­˜å–權,或會é­èº«ä»½ç›œç”¨ã€‚Chromium 建議您立å³è®Šæ›´å¯†ç¢¼ã€‚</translation>
<translation id="1947454675006758438">é‡˜è£ (å³ä¸Šæ–¹)</translation>
<translation id="1958218078413065209">你嘅最高得分係 <ph name="SCORE" />。</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">紙匣 7</translation>
<translation id="204357726431741734">登入å³å¯ä½¿ç”¨å„²å­˜åœ¨ Google 帳戶中的密碼</translation>
<translation id="2053111141626950936">系統將ä¸æœƒç¿»è­¯<ph name="LANGUAGE" />網é ã€‚</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{如果此功能已啟用且處於有效狀態,Chrome 就會判斷您最近的ç€è¦½æ´»å‹•èˆ‡å“ªå€‹å¤§åž‹ä½¿ç”¨è€…群組 (åˆç¨±ã€Œçµ„別ã€) 最為相似。廣告客戶å¯ä»¥é¸æ“‡è¦å‘該群組顯示的廣告,而您的ç€è¦½æ´»å‹•æœƒä¿ç•™åœ¨è£ç½®ä¸Šï¼Œçµ•ä¸æœƒå¤–洩。系統會æ¯æ—¥æ›´æ–°æ‚¨æ‰€å±¬çš„群組。}=1{如果此功能已啟用且處於有效狀態,Chrome 就會判斷您最近的ç€è¦½æ´»å‹•èˆ‡å“ªå€‹å¤§åž‹ä½¿ç”¨è€…群組 (åˆç¨±ã€Œçµ„別ã€) 最為相似。廣告客戶å¯ä»¥é¸æ“‡è¦å‘該群組顯示的廣告,而您的ç€è¦½æ´»å‹•æœƒä¿ç•™åœ¨è£ç½®ä¸Šï¼Œçµ•ä¸æœƒå¤–洩。系統會æ¯æ—¥æ›´æ–°æ‚¨æ‰€å±¬çš„群組。}other{如果此功能已啟用且處於有效狀態,Chrome 就會判斷您最近的ç€è¦½æ´»å‹•èˆ‡å“ªå€‹å¤§åž‹ä½¿ç”¨è€…群組 (åˆç¨±ã€Œçµ„別ã€) 最為相似。廣告客戶å¯ä»¥é¸æ“‡è¦å‘該群組顯示的廣告,而您的ç€è¦½æ´»å‹•æœƒä¿ç•™åœ¨è£ç½®ä¸Šï¼Œçµ•ä¸æœƒå¤–洩。系統會æ¯éš” {NUM_DAYS} 日更新您所屬的群組。}}</translation>
<translation id="2053553514270667976">郵éžå€è™Ÿ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 個建議}other{# 個建議}}</translation>
<translation id="2071692954027939183">由於您通常ä¸å…許通知,因此系統已自動å°éŽ–通知</translation>
<translation id="2079545284768500474">復原</translation>
<translation id="20817612488360358">雖然系統 Proxy 設定已設為使用,ä¸éŽä¹ŸæŒ‡å®šäº†æ˜Žç¢ºçš„ Proxy 設定。</translation>
<translation id="2082238445998314030">第 <ph name="RESULT_NUMBER" /> é …çµæžœ (å…± <ph name="TOTAL_RESULTS" /> é …)</translation>
+<translation id="2085876078937250610">儲存…</translation>
<translation id="2088086323192747268">管ç†åŒæ­¥åŠŸèƒ½æŒ‰éˆ•ï¼Œã©’一下 Enter éµå°±å¯ä»¥å–º Chrome 設定度管ç†åŒæ­¥è³‡æ–™</translation>
<translation id="2091887806945687916">音效</translation>
<translation id="2094505752054353250">網域ä¸ç¬¦</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> è¦æ±‚æ供使用者å稱和密碼。</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />,到期日:<ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">由管ç†å“¡æŽ§åˆ¶çš„設定</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> è¦æ±‚與下列è—牙è£ç½®é…å°</translation>
<translation id="2344028582131185878">自動下載</translation>
<translation id="2346319942568447007">您複製的圖片</translation>
<translation id="2354001756790975382">其他書籤</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">攻擊者å¯èƒ½å¯ä»¥çœ‹åˆ°æ‚¨æ­£åœ¨æ­¤ç¶²ç«™ä¸Šçœ‹åˆ°çš„圖片,然後é€éŽä¿®æ”¹åœ–片來欺騙您。</translation>
<translation id="2356070529366658676">è©¢å•</translation>
<translation id="2357481397660644965">您的è£ç½®ç”± <ph name="DEVICE_MANAGER" /> 管ç†ï¼Œè€Œæ‚¨çš„帳戶由 <ph name="ACCOUNT_MANAGER" /> 管ç†ã€‚</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{少於 1 天內}=1{1 天後}other{{NUM_DAYS} 天後}}</translation>
<translation id="2359629602545592467">多種貨幣</translation>
<translation id="2359808026110333948">繼續</translation>
+<translation id="2359961752320758691">已套用虛擬å¡è™Ÿã€‚</translation>
<translation id="2367567093518048410">級別</translation>
<translation id="2372464001869762664">確èªå¾Œï¼Œæ‚¨çš„ Google 帳戶會與此網站共用信用å¡è³‡æ–™ã€‚如è¦æŸ¥è©¢ CVC,請ç€è¦½ Plex 帳戶詳情。</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">ä¸æ”¯æ´æ­¤é‹é€æ–¹å¼ï¼Œè«‹é¸æ“‡å…¶ä»–æ–¹å¼ã€‚</translation>
<translation id="2396249848217231973">復原刪除(&amp;U)</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">舊地å€</translation>
<translation id="2413528052993050574">伺æœå™¨ç„¡æ³•è­‰æ˜Žå…¶å±¬æ–¼ <ph name="DOMAIN" /> 網域;其安全性憑證已被撤銷。這å¯èƒ½æ˜¯å› ç‚ºè¨­å®šéŒ¯èª¤ï¼Œæˆ–有攻擊者攔截您的連線。</translation>
<translation id="2414886740292270097">ç°æš—</translation>
<translation id="2438874542388153331">四孔 (å³å´)</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">é‡˜è£ (å³ä¸‹æ–¹)</translation>
<translation id="2523886232349826891">åªæœƒå„²å­˜è‡³æ­¤è£ç½®</translation>
<translation id="2524461107774643265">新增更多資料</translation>
-<translation id="2526590354069164005">æ¡Œé¢é›»è…¦</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{å’Œå¦å¤– 1 個網域}other{å’Œå¦å¤– # 個網域}}</translation>
<translation id="2536110899380797252">新增地å€</translation>
<translation id="2539524384386349900">åµæ¸¬</translation>
+<translation id="2541219929084442027">當您關閉所有無痕å¼åˆ†é å¾Œï¼Œæ‚¨åœ¨å…¶ä¸­ç€è¦½çš„網é éƒ½ä¸æœƒä¿ç•™åœ¨ç€è¦½å™¨è¨˜éŒ„ã€Cookie 儲存庫或æœå°‹è¨˜éŒ„中。ä¸éŽï¼Œæ‚¨ä¸‹è¼‰çš„檔案或建立的書籤將會全部ä¿ç•™ã€‚</translation>
<translation id="2544644783021658368">單一文件</translation>
<translation id="254947805923345898">政策值無效。</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> 傳é€çš„回應無效。</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">如è¦ç²å¾— Chrome 最高程度的安全防護,請<ph name="BEGIN_ENHANCED_PROTECTION_LINK" />啟用強化ä¿è­·åŠŸèƒ½<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">找ä¸åˆ° <ph name="HOST_NAME" /> 的伺æœå™¨ IP ä½å€ã€‚</translation>
<translation id="2639739919103226564">狀態:</translation>
+<translation id="264810637653812429">找ä¸åˆ°ä»»ä½•å…¼å®¹çš„è£ç½®ã€‚</translation>
<translation id="2649204054376361687"><ph name="COUNTRY" />,<ph name="CITY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />,㩒一下 Tab éµï¼Œç„¶å¾Œã©’一下 Enter éµå°±å¯ä»¥å–º Chrome 設定度清除ç€è¦½è¨˜éŒ„ã€Cookieã€å¿«å–åŒæ›´å¤šè³‡æ–™</translation>
<translation id="2650446666397867134">å­˜å–檔案被拒</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">é‡æ–°å•Ÿå‹•</translation>
<translation id="2803306138276472711">Google 安全ç€è¦½åŠŸèƒ½æœ€è¿‘在 <ph name="SITE" /> 上<ph name="BEGIN_LINK" />åµæ¸¬åˆ°æƒ¡æ„軟件<ph name="END_LINK" />。å³ä½¿æ˜¯å¹³å¸¸å¯ä»¥å®‰å…¨ä½¿ç”¨çš„網站,有時也會被惡æ„軟件感染。</translation>
<translation id="2807052079800581569">圖片 Y ä½ç½®</translation>
+<translation id="2820957248982571256">正在掃瞄…</translation>
<translation id="2824775600643448204">網å€èˆ‡æœå°‹åˆ—</translation>
<translation id="2826760142808435982">連線採用 <ph name="CIPHER" /> 加密,並設有 <ph name="KX" /> 金鑰交æ›æ©Ÿåˆ¶ã€‚</translation>
<translation id="2835170189407361413">清除表格</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">Invite (ä¿¡å°)</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="2859806420264540918">此網站顯示滋擾性或誤導廣告。</translation>
+<translation id="287596039013813457">å‹å–„</translation>
+<translation id="2876489322757410363">å³å°‡é€€å‡ºç„¡ç—•æ¨¡å¼ï¼Œæ”¹ç”¨å¤–部應用程å¼ä»˜æ¬¾ã€‚è¦ç¹¼çºŒå—Žï¼Ÿ</translation>
<translation id="2878197950673342043">å字摺</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">放置視窗</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">C9 (ä¿¡å°)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />,㩒一下 Tab éµï¼Œç„¶å¾Œã©’一下 Enter éµå°±å¯ä»¥å–º Chrome 設定度執行安全檢查</translation>
<translation id="3061707000357573562">修補æœå‹™</translation>
-<translation id="3064966200440839136">å³å°‡é€€å‡ºç„¡ç—•æ¨¡å¼ï¼Œæ”¹ç”¨å¤–部應用程å¼ä»˜æ¬¾ï¼Œè¦ç¹¼çºŒå—Žï¼Ÿ</translation>
<translation id="306573536155379004">å•Ÿå‹•å’—éŠæˆ²ã€‚</translation>
<translation id="3080254622891793721">圖片</translation>
<translation id="3086579638707268289">您的網絡活動正å—監控</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">您的帳戶由 <ph name="MANAGER" /> 管ç†ã€‚</translation>
<translation id="3157931365184549694">還原</translation>
<translation id="3162559335345991374">ç›®å‰ä½¿ç”¨çš„ Wi-Fi å¯èƒ½è¦æ±‚您å‰å¾€å…¶ç™»å…¥é é¢ã€‚</translation>
-<translation id="3167968892399408617">當您關閉所有無痕模å¼åˆ†é å¾Œï¼Œæ‚¨åœ¨å…¶ä¸­ç€è¦½çš„網é éƒ½ä¸æœƒä¿ç•™åœ¨ç€è¦½å™¨è¨˜éŒ„ã€Cookie 儲存庫或æœå°‹è¨˜éŒ„中。ä¸éŽï¼Œæ‚¨ä¸‹è¼‰çš„檔案或建立的書籤將會全部ä¿ç•™ã€‚</translation>
<translation id="3169472444629675720">探索</translation>
<translation id="3174168572213147020">島嶼</translation>
<translation id="3176929007561373547">檢查您的 Proxy 設定,或與網絡管ç†å“¡è¯çµ¡ï¼Œä»¥
@@ -593,10 +608,12 @@
<translation id="3229041911291329567">è£ç½®å’Œç€è¦½å™¨çš„版本資料</translation>
<translation id="323107829343500871">請輸入 <ph name="CREDIT_CARD" /> 的信用å¡é©—證碼 (CVC)</translation>
<translation id="3234666976984236645">一律在這個網站上åµæ¸¬é‡è¦å…§å®¹</translation>
+<translation id="3249845759089040423">åž‹æ ¼</translation>
<translation id="3252266817569339921">法文</translation>
<translation id="3266793032086590337">值 (è¡çª)</translation>
<translation id="3268451620468152448">開啟的分é </translation>
<translation id="3270847123878663523">復原é‡æ–°æŽ’åº(&amp;U)</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> è¦æ±‚連接至</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">機構 (<ph name="ENROLLMENT_DOMAIN" />) 已將一些資訊 (例如設定或政策) 傳é€åˆ°ä»¥ä¸‹ç¶²ç«™ã€‚</translation>
<translation id="3282497668470633863">新增æŒå¡äººå§“å</translation>
@@ -649,6 +666,7 @@
<translation id="3428151540071562330">一或多個 DnsOverHttpsTemplates 伺æœå™¨ç¯„本 URI 無效,因此系統ä¸æœƒæŽ¡ç”¨é€™äº›ä¼ºæœå™¨ç¯„本 URI。</translation>
<translation id="3431636764301398940">將這張信用å¡å„²å­˜è‡³æ­¤è£ç½®</translation>
<translation id="3432601291244612633">關閉é é¢</translation>
+<translation id="3435738964857648380">安全性</translation>
<translation id="3435896845095436175">啟用</translation>
<translation id="3438829137925142401">使用儲存在 Google 帳戶中的密碼</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -690,7 +708,10 @@
<translation id="3584299510153766161">雙孔 (底部)</translation>
<translation id="3586931643579894722">éš±è—詳情</translation>
<translation id="3587738293690942763">中間</translation>
+<translation id="3590643883886679995">離開無痕模å¼å¾Œï¼Œç™»å…¥è³‡æ–™æœƒå„²å­˜åœ¨æ­¤è£ç½®ä¸­ã€‚</translation>
+<translation id="359126217934908072">月/年:</translation>
<translation id="3592413004129370115">Italian (ä¿¡å°)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{您å¯éš¨æ™‚é‡è¨­ç¾¤çµ„。加入新群組約需時 1 天。}=1{您å¯éš¨æ™‚é‡è¨­ç¾¤çµ„。加入新群組約需時 1 天。}other{您å¯éš¨æ™‚é‡è¨­ç¾¤çµ„。加入新群組約需時 {NUM_DAYS} 天。}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />,<ph name="DOMAIN" />,<ph name="TIME" /></translation>
<translation id="3603507503523709">您的管ç†å“¡å·²å°éŽ–應用程å¼</translation>
<translation id="3608932978122581043">é€ç´™æ–¹å‘</translation>
@@ -699,13 +720,13 @@
<translation id="3615877443314183785">請輸入有效的到期日</translation>
<translation id="36224234498066874">清除ç€è¦½è³‡æ–™â€¦</translation>
<translation id="362276910939193118">顯示完整記錄</translation>
-<translation id="3625635938337243871">離開無痕模å¼å¾Œï¼Œç™»å…¥è³‡æ–™æœƒå„²å­˜åœ¨æ­¤è£ç½®ä¸­ã€‚</translation>
<translation id="3630155396527302611">如果程å¼å·²åˆ—在å…許存å–網絡的清單中,建議您
從清單中移除該程å¼ï¼Œç„¶å¾Œé‡æ–°åŠ å…¥ã€‚</translation>
<translation id="3630699740441428070">æ­¤è£ç½®çš„管ç†å“¡å·²è¨­å®šæ‚¨çš„網絡連線,此設定å¯å…許管ç†å“¡æŸ¥çœ‹æ‚¨çš„網絡æµé‡ï¼ŒåŒ…括您ç€è¦½çš„網站。</translation>
<translation id="3631244953324577188">生物識別</translation>
<translation id="3633738897356909127">æ›´æ–° Chrome 按鈕,㩒一下 Enter éµå°±å¯ä»¥é€éŽ Chrome 設定更新 Chrome</translation>
<translation id="3634530185120165534">紙匣 5</translation>
+<translation id="3637662659967048211">儲存至 Google 帳戶</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">應用程å¼ï¼š</translation>
<translation id="3650584904733503804">é©—è­‰æˆåŠŸ</translation>
@@ -746,6 +767,7 @@
<translation id="3781428340399460090">豔粉紅色</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">è—牙è£ç½®</translation>
+<translation id="3787675388804467730">虛擬å¡è™Ÿ</translation>
<translation id="3787705759683870569">到期日:<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">粗幼:16</translation>
<translation id="3789841737615482174">安è£</translation>
@@ -765,6 +787,7 @@
<translation id="3841184659773414994">檔案處ç†å¸¸å¼</translation>
<translation id="385051799172605136">返回</translation>
<translation id="3858027520442213535">更新日期和時間</translation>
+<translation id="3881478300875776315">顯示較少行</translation>
<translation id="3884278016824448484">è£ç½®è­˜åˆ¥ç¢¼ç™¼ç”Ÿè¡çª</translation>
<translation id="3885155851504623709">管轄å€</translation>
<translation id="388632593194507180">åµæ¸¬åˆ°ç›£æŽ§</translation>
@@ -790,6 +813,7 @@
<translation id="397105322502079400">計算中…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> å·²é­å°éŽ–</translation>
<translation id="3973357910713125165">執行 Chrome 安全檢查按鈕,㩒一下 Enter éµå°±å¯ä»¥å–º Chrome 設定度執行安全檢查</translation>
+<translation id="3986705137476756801">暫時關閉å³æ™‚字幕</translation>
<translation id="3987405730340719549">Chrome 判斷這å¯èƒ½æ˜¯å½é€ æˆ–è©é¨™ç¶²ç«™ã€‚
如果您èªç‚ºç³»çµ±ä¸æ‡‰é¡¯ç¤ºæ­¤è¨Šæ¯ï¼Œè«‹å‰å¾€ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals。</translation>
@@ -881,13 +905,14 @@
<translation id="4275830172053184480">é‡æ–°å•Ÿå‹•è£ç½®</translation>
<translation id="4277028893293644418">é‡è¨­å¯†ç¢¼</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{æ­¤å¡å·²å„²å­˜è‡³æ‚¨çš„ Google 帳戶}other{這些å¡å·²å„²å­˜è‡³æ‚¨çš„ Google 帳戶}}</translation>
+<translation id="4287885627794386150">符åˆé©ç”¨æ¢ä»¶ä½†å°šæœªå•Ÿç”¨</translation>
<translation id="4297502707443874121">第 <ph name="THUMBNAIL_PAGE" /> é å˜…縮圖</translation>
<translation id="42981349822642051">展開</translation>
<translation id="4300675098767811073">多孔 (å³å´)</translation>
<translation id="4302514097724775343">輕按æé¾å³å¯é–‹å§‹éŠæˆ²</translation>
<translation id="4302965934281694568">Chou3 (ä¿¡å°)</translation>
<translation id="4305666528087210886">無法存å–您的檔案</translation>
-<translation id="4305817255990598646">切æ›</translation>
+<translation id="4306529830550717874">è¦å„²å­˜åœ°å€å—Žï¼Ÿ</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">å°éŽ– (é è¨­)</translation>
<translation id="4314815835985389558">管ç†åŒæ­¥è³‡æ–™</translation>
@@ -914,6 +939,7 @@
<translation id="4377125064752653719">您嘗試å‰å¾€ <ph name="DOMAIN" />,但是發行者已撤銷伺æœå™¨æ供的憑證。在這種情æ³ä¸‹ï¼Œè«‹å‹¿ä¿¡ä»»ä¼ºæœå™¨æ供的安全性憑證,因為您å¯èƒ½é€£æŽ¥è‡³æ”»æ“Šè€…。</translation>
<translation id="4378154925671717803">電話號碼</translation>
<translation id="4390472908992056574">åœé‚Š</translation>
+<translation id="4406883609789734330">å³æ™‚字幕</translation>
<translation id="4406896451731180161">æœå°‹çµæžœ</translation>
<translation id="4408413947728134509">Cookie <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">您剛æ‰åœ¨æ¬ºè©ç¶²ç«™ä¸Šè¼¸å…¥äº†å¯†ç¢¼ã€‚Chrome 建議å‰å¾€ <ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" />ã€<ph name="WEBSITE_3" /> 以åŠå…¶ä»–您使用此密碼的網站,並立å³è®Šæ›´å¯†ç¢¼ã€‚</translation>
@@ -926,7 +952,6 @@
<translation id="4435702339979719576">明信片</translation>
<translation id="443673843213245140">雖然已åœç”¨ Proxy,ä¸éŽå·²æ˜Žç¢ºæŒ‡å®šäº† Proxy 設定。</translation>
<translation id="4464826014807964867">有來自您機構資料的網站</translation>
-<translation id="4466881336512663640">您å°è¡¨å–®æ‰€ä½œçš„變更將會éºå¤±ã€‚您確定è¦ç¹¼çºŒå—Žï¼Ÿ</translation>
<translation id="4476953670630786061">此表格ä¸å®‰å…¨ï¼Œè‡ªå‹•å¡«å…¥åŠŸèƒ½å·²é—œé–‰ã€‚</translation>
<translation id="4477350412780666475">下一首曲目</translation>
<translation id="4482953324121162758">系統ä¸æœƒç¿»è­¯æ­¤ç¶²ç«™ã€‚</translation>
@@ -960,6 +985,7 @@
<translation id="4594403342090139922">復原刪除(&amp;U)</translation>
<translation id="4597348597567598915">粗幼:8</translation>
<translation id="4600854749408232102">C6/C5 (ä¿¡å°)</translation>
+<translation id="4606870351894164739">具影響力</translation>
<translation id="4628948037717959914">相片</translation>
<translation id="4631649115723685955">已連çµç¾é‡‘回贈</translation>
<translation id="4636930964841734540">資訊</translation>
@@ -979,6 +1005,7 @@
<translation id="4691835149146451662">Architecture-A (ä¿¡å°)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">å´é‚Š</translation>
+<translation id="4702656508969495934">顯示咗å³æ™‚字幕,用視窗切æ›é¸é …將焦點移去å³æ™‚字幕</translation>
<translation id="4708268264240856090">您的連線已中斷</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />執行 Windows 網絡診斷<ph name="END_LINK" /></translation>
@@ -992,6 +1019,7 @@
<translation id="4738601419177586157">「<ph name="TEXT" />ã€æœå°‹å»ºè­°</translation>
<translation id="4742407542027196863">管ç†å¯†ç¢¼â€¦</translation>
<translation id="4744603770635761495">å¯åŸ·è¡Œæª”的路徑</translation>
+<translation id="4749011317274908093">您已啟用無痕模å¼</translation>
<translation id="4750917950439032686">傳é€è³‡æ–™è‡³æ­¤ç¶²ç«™æ™‚ (例如密碼或信用å¡è™Ÿç¢¼),您的資料將會ä¿å¯†ã€‚</translation>
<translation id="4756388243121344051">記錄(&amp;H)</translation>
<translation id="4758311279753947758">新增è¯çµ¡äººè³‡è¨Š</translation>
@@ -1021,6 +1049,8 @@
<translation id="4813512666221746211">網絡錯誤</translation>
<translation id="4816492930507672669">ä¾é é¢å¤§å°èª¿æ•´</translation>
<translation id="4819347708020428563">è¦åœ¨é è¨­æª¢è¦–模å¼ä¸­ç·¨è¼¯è¨»è§£å—Žï¼Ÿ</translation>
+<translation id="4825507807291741242">強大</translation>
+<translation id="4838327282952368871">夢幻</translation>
<translation id="484462545196658690">自動</translation>
<translation id="4850886885716139402">檢視</translation>
<translation id="485316830061041779">å¾·æ–‡</translation>
@@ -1157,6 +1187,7 @@
<translation id="5314967030527622926">手冊製作工具</translation>
<translation id="5316812925700871227">逆時é‡æ–¹å‘旋轉</translation>
<translation id="5317780077021120954">儲存</translation>
+<translation id="5321288445143113935">最大化</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />,<ph name="NUM_MATCHES" /> 個入é¢å˜…第 <ph name="MATCH_POSITION" /> 個</translation>
<translation id="5324080437450482387">é¸æ“‡è¯çµ¡äººè³‡æ–™</translation>
<translation id="5327248766486351172">å稱</translation>
@@ -1164,11 +1195,13 @@
<translation id="5332219387342487447">é‹é€æ–¹å¼</translation>
<translation id="5333022057423422993">Chrome 發ç¾æ‚¨å‰›æ‰ä½¿ç”¨çš„密碼因資料外洩而被洩露。如è¦ç¢ºä¿å¸³æˆ¶å®‰å…¨ï¼Œå»ºè­°æ‚¨æª¢æŸ¥å·²å„²å­˜çš„密碼。</translation>
<translation id="5334013548165032829">詳細系統記錄</translation>
+<translation id="5334145288572353250">è¦å„²å­˜åœ°å€å—Žï¼Ÿ</translation>
<translation id="5340250774223869109">å·²å°éŽ–應用程å¼</translation>
<translation id="534295439873310000">NFC è£ç½®</translation>
<translation id="5344579389779391559">此網é å¯èƒ½æœƒå‘您收å–費用</translation>
<translation id="5355557959165512791">您目å‰ç„¡æ³•ç€è¦½ <ph name="SITE" />,因為此網站的憑證已被撤銷。網絡錯誤和攻擊行為通常是暫時性å•é¡Œï¼Œæ‰€ä»¥æ­¤ç¶²é å¯èƒ½ç¨å¾Œå°±èƒ½æ­£å¸¸ä½¿ç”¨ã€‚</translation>
<translation id="536296301121032821">無法儲存政策設定</translation>
+<translation id="5363309033720083897">管ç†å“¡å…許的åºåˆ—連接埠</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="5386426401304769735">此網站的憑證éˆå…§åŒ…å«ä½¿ç”¨ SHA-1 簽署的憑證。</translation>
@@ -1177,6 +1210,7 @@
<translation id="5398772614898833570">å·²å°éŽ–廣告</translation>
<translation id="5400836586163650660">ç°è‰²</translation>
<translation id="540969355065856584">伺æœå™¨ç„¡æ³•è­‰æ˜Žå…¶å±¬æ–¼ <ph name="DOMAIN" /> 網域;其安全性憑證目å‰ç„¡æ•ˆã€‚這å¯èƒ½æ˜¯å› ç‚ºè¨­å®šéŒ¯èª¤ï¼Œæˆ–有攻擊者攔截您的連線。</translation>
+<translation id="541143247543991491">雲端 (整個系統)</translation>
<translation id="541416427766103491">堆疊器 4</translation>
<translation id="5421136146218899937">清除ç€è¦½æ•¸æ“šâ€¦</translation>
<translation id="5426179911063097041"><ph name="SITE" /> è¦æ±‚傳é€é€šçŸ¥çµ¦æ‚¨</translation>
@@ -1190,6 +1224,7 @@
<translation id="5455374756549232013">政策時間戳記有誤</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" /> é …è¯çµ¡è³‡æ–™}other{「<ph name="CONTACT_PREVIEW" />ã€å’Œå¦å¤– <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> é …è¯çµ¡è³‡æ–™}}</translation>
+<translation id="5463625433003343978">正在尋找è£ç½®â€¦</translation>
<translation id="5469868506864199649">æ„大利文</translation>
<translation id="5470861586879999274">é‡åšç·¨è¼¯(&amp;R)</translation>
<translation id="5478437291406423475">B6/C4 (ä¿¡å°)</translation>
@@ -1239,7 +1274,6 @@
<translation id="5624120631404540903">管ç†å¯†ç¢¼</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="563324245173044180">å·²å°éŽ–欺è©å…§å®¹ã€‚</translation>
<translation id="5644090287519800334">å´é‚Š 1 圖片 X 軸移動</translation>
@@ -1278,12 +1312,12 @@
<translation id="5785756445106461925">而且,這個網é å«æœ‰å…¶ä»–ä¸å®‰å…¨çš„資æºã€‚其他人å¯èƒ½æœƒåœ¨è³‡æºå‚³è¼¸æœŸé–“檢視這些資æºï¼Œæ”»æ“Šè€…也å¯èƒ½æœƒä¿®æ”¹é€™äº›è³‡æºï¼Œç¹¼è€Œè®Šæ›´ç¶²é å¤–觀。</translation>
<translation id="5786044859038896871">è¦å¡«å¯«æ‚¨çš„信用å¡è³‡æ–™å—Žï¼Ÿ</translation>
<translation id="578633867165174378">Chrome 發ç¾æ‚¨å‰›æ‰ä½¿ç”¨çš„密碼因資料外洩而被洩露。建議您立å³è®Šæ›´å¯†ç¢¼ã€‚</translation>
-<translation id="5798290721819630480">è¦æ¨æ£„變更嗎?</translation>
<translation id="5803412860119678065">è¦å¡«å¯« <ph name="CARD_DETAIL" /> 的資料嗎?</translation>
<translation id="5804241973901381774">權é™</translation>
<translation id="5804427196348435412">使用 NFC è£ç½®</translation>
<translation id="5810442152076338065">您與 <ph name="DOMAIN" /> 之間的連線é€éŽéŽæ™‚的加密套件加密處ç†ã€‚</translation>
<translation id="5813119285467412249">é‡åšæ–°å¢ž(&amp;R)</translation>
+<translation id="5817918615728894473">é…å°</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{付帳時,系統會從此付款å¡æ‰£æ¬¾ï¼Œä½†å…¶è™Ÿç¢¼ä¸¦ä¸æœƒèˆ‡æ­¤ç¶²ç«™åˆ†äº«ã€‚為æ高安全性,系統會產生一組臨時 CVC。}other{付帳時,系統會從所é¸çš„付款å¡æ‰£æ¬¾ï¼Œä½†å…¶è™Ÿç¢¼ä¸¦ä¸æœƒèˆ‡æ­¤ç¶²ç«™åˆ†äº«ã€‚為æ高安全性,系統會產生一組臨時 CVC。}}</translation>
<translation id="5826507051599432481">真實姓å (CN)</translation>
<translation id="5838278095973806738">您ä¸æ‡‰åœ¨æ­¤ç¶²ç«™ä¸Šè¼¸å…¥ä»»ä½•æ•æ„Ÿè³‡æ–™ (例如密碼或信用å¡è³‡æ–™),因為攻擊者å¯èƒ½æœƒç«Šå–這些資料。</translation>
@@ -1291,6 +1325,7 @@
<translation id="5855253129151731373">此網站的主機å稱與 <ph name="LOOKALIKE_DOMAIN" /> 相似。攻擊者有時會在網域å稱中加入難以辨識的細微變更來仿冒網站。
如果您èªç‚ºç³»çµ±ä¸æ‡‰é¡¯ç¤ºæ­¤è¨Šæ¯ï¼Œè«‹å‰å¾€ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals。</translation>
+<translation id="5860033963881614850">關閉</translation>
<translation id="5862579898803147654">堆疊器 8</translation>
<translation id="5863847714970149516">接下來的é é¢å¯èƒ½æœƒå‘您收å–費用</translation>
<translation id="5866257070973731571">新增電話號碼</translation>
@@ -1307,6 +1342,7 @@
<translation id="5913377024445952699">已暫åœæ“·å–螢幕畫é¢</translation>
<translation id="59174027418879706">已啟用</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{正在使用 1 個 cookie}other{正在使用 # 個 cookie}}</translation>
<translation id="5921185718311485855">é–‹å•Ÿ</translation>
<translation id="5921639886840618607">è¦å°‡ä»˜æ¬¾å¡å„²å­˜è‡³ Google 帳戶嗎?</translation>
<translation id="5922853866070715753">快將完æˆ</translation>
@@ -1326,6 +1362,7 @@
<translation id="5989320800837274978">沒有指定固定的 Proxy 伺æœå™¨å’Œ .pac 指令碼網å€ã€‚</translation>
<translation id="5992691462791905444">大å°é¢¨ç´æ‘º</translation>
<translation id="6000758707621254961">有 <ph name="RESULT_COUNT" /> 個åŒã€Œ<ph name="SEARCH_TEXT" />ã€ç›¸é—œå˜…æœå°‹çµæžœ</translation>
+<translation id="6006484371116297560">經典主題</translation>
<translation id="6008122969617370890">N 至 1 çš„é †åº</translation>
<translation id="6008256403891681546">JCB å¡</translation>
<translation id="6014801569448771146">請檢查您的密碼</translation>
@@ -1347,6 +1384,7 @@
<translation id="6045164183059402045">拼版範本</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="6049004884579590341">æŒ‰ä½ |<ph name="ACCELERATOR" />| å³å¯é€€å‡ºå…¨èž¢å¹•æ¨¡å¼</translation>
<translation id="6049488691372270142">é é¢å‚³é€</translation>
<translation id="6051221802930200923">您目å‰ç„¡æ³•ç€è¦½ <ph name="SITE" />,因為此網站使用憑證固定功能。網絡錯誤和攻擊行為通常是暫時性å•é¡Œï¼Œæ‰€ä»¥æ­¤ç¶²é å¯èƒ½ç¨å¾Œå°±èƒ½æ­£å¸¸ä½¿ç”¨ã€‚</translation>
<translation id="6051898664905071243">é æ•¸ï¼š</translation>
@@ -1363,6 +1401,7 @@
<translation id="610911394827799129">您的 Google 帳戶在 <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> 上å¯èƒ½æœ‰å…¶ä»–å½¢å¼çš„ç€è¦½è¨˜éŒ„</translation>
<translation id="6116338172782435947">查看複製到剪貼簿的文字和圖片</translation>
<translation id="6120179357481664955">è¦è¨˜ä½æ‚¨çš„ UPI ID 嗎?</translation>
+<translation id="6123290840358279103">查看虛擬å¡</translation>
<translation id="6124432979022149706">Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">檢查連接線,或é‡æ–°å•Ÿå‹•è·¯ç”±å™¨ã€æ•¸æ“šæ©Ÿæˆ–其他使用中的
網絡è£ç½®ã€‚</translation>
@@ -1399,6 +1438,7 @@
<translation id="6289939620939689042">é é¢é¡è‰²</translation>
<translation id="6290238015253830360">為您推薦的文章會在這裡顯示</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">正在åœæ­¢ Chrome 的「Google 助ç†ã€</translation>
<translation id="6305205051461490394">ç„¡æ³•å­˜å– <ph name="URL" />。</translation>
<translation id="6312113039770857350">網é ç„¡æ³•ä½¿ç”¨</translation>
@@ -1424,6 +1464,7 @@
<translation id="6390200185239044127">風ç´æ‘ºå°æ‘º</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">管ç†å“¡æ”¿ç­–å·²ç¦æ­¢å°‡å…§å®¹ç”± <ph name="ORIGIN_NAME" /> 貼到此ä½ç½®</translation>
+<translation id="6398765197997659313">退出全螢幕模å¼</translation>
<translation id="6401136357288658127">此政策已被淘汰,請改用 <ph name="NEW_POLICY" /> 政策。</translation>
<translation id="6404511346730675251">編輯書籤</translation>
<translation id="6406765186087300643">C0 (ä¿¡å°)</translation>
@@ -1436,7 +1477,6 @@
<translation id="6428450836711225518">請驗證您的電話號碼</translation>
<translation id="6433490469411711332">編輯è¯çµ¡äººè³‡æ–™</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> 已拒絕連線。</translation>
-<translation id="6434309073475700221">æ¨æ£„</translation>
<translation id="6440503408713884761">已略éŽ</translation>
<translation id="6443406338865242315">您已安è£çš„擴充程å¼å’Œå¤–掛程å¼</translation>
<translation id="6446163441502663861">Kahu (ä¿¡å°)</translation>
@@ -1479,6 +1519,7 @@
<translation id="6624427990725312378">è¯çµ¡äººè³‡æ–™</translation>
<translation id="6626291197371920147">新增有效的信用å¡è™Ÿç¢¼</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> æœå°‹</translation>
+<translation id="6630043285902923878">正在尋找 USB è£ç½®â€¦</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">清除</translation>
@@ -1494,6 +1535,7 @@
<translation id="6671697161687535275">è¦å¾ž Chromium 移除表格建議嗎?</translation>
<translation id="6685834062052613830">請登出並完æˆè¨­å®šç¨‹åº</translation>
<translation id="6687335167692595844">è¦æ±‚的字型大å°</translation>
+<translation id="6688743156324860098">更新…</translation>
<translation id="6689249931105087298">與黑點壓縮相å°</translation>
<translation id="6689271823431384964">由於您已登入,因此 Chrome æ議將您的付款å¡å„²å­˜è‡³ Google 帳戶。您å¯åœ¨è¨­å®šä¸­è®Šæ›´æ­¤è¡Œç‚ºã€‚æŒå¡äººå§“å來自您的帳戶。</translation>
<translation id="6698381487523150993">已建立:</translation>
@@ -1509,6 +1551,7 @@
<translation id="6744009308914054259">等待連線時,您å¯ä»¥å‰å¾€ã€Œä¸‹è¼‰ã€é–±è®€é›¢ç·šæ–‡ç« ã€‚</translation>
<translation id="6753269504797312559">政策值</translation>
<translation id="6757797048963528358">您的è£ç½®å·²é€²å…¥ä¼‘眠狀態。</translation>
+<translation id="6767985426384634228">è¦æ›´æ–°åœ°å€å—Žï¼Ÿ</translation>
<translation id="6768213884286397650">Hagaki (明信片)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">紫羅蘭色</translation>
@@ -1531,6 +1574,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome 已簡化此é é¢ï¼Œæ–¹ä¾¿æ‚¨é–±è®€ã€‚Chrome å·²é€éŽä¸å®‰å…¨é€£ç·šæ“·å–原始網é ã€‚</translation>
<translation id="6891596781022320156">系統ä¸æ”¯æ´é€™é …政策的層級。</translation>
+<translation id="6895143722905299846">虛擬å¡è™Ÿï¼š</translation>
<translation id="6895330447102777224">您的信用å¡å·²å®Œæˆé©—è­‰</translation>
<translation id="6897140037006041989">使用者代ç†ç¨‹å¼</translation>
<translation id="6898699227549475383">機構 (O)</translation>
@@ -1566,10 +1610,10 @@
<translation id="7004583254764674281">使用 Windows Hello å¯åŠ å¿«ç¢ºèªä»˜æ¬¾å¡</translation>
<translation id="7006930604109697472">ä»è¦å‚³é€</translation>
<translation id="7012363358306927923">中國銀è¯</translation>
-<translation id="7012404007611495949">調整大å°åŠŸèƒ½è¨­å®š</translation>
<translation id="7014741021609395734">縮放比例</translation>
<translation id="7016992613359344582">這些費用å¯èƒ½æ˜¯ä¸€æ¬¡æ€§æˆ–會é‡è¤‡æ”¶å–,而收費時亦å¯èƒ½é›£ä»¥å¯Ÿè¦ºã€‚</translation>
<translation id="7029809446516969842">密碼</translation>
+<translation id="7030436163253143341">憑證無效</translation>
<translation id="7031646650991750659">您已安è£çš„ Google Play 應用程å¼</translation>
<translation id="7050187094878475250">您曾嘗試å‰å¾€ <ph name="DOMAIN" />,但其伺æœå™¨æ†‘證有效期éŽé•·ï¼Œä¸¦ä¸å€¼å¾—信任。</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ç›®å‰ç„¡æ³•å„²å­˜æ­¤å¡}other{ç›®å‰ç„¡æ³•å„²å­˜é€™äº›å¡}}</translation>
@@ -1639,12 +1683,14 @@
<translation id="7300012071106347854">鈷è—色</translation>
<translation id="7302712225291570345">「<ph name="TEXT" />ã€</translation>
<translation id="7304030187361489308">高</translation>
+<translation id="7305756307268530424">啟用慢速模å¼</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">連線說明</translation>
<translation id="7323804146520582233">éš±è—「<ph name="SECTION" />ã€éƒ¨åˆ†</translation>
<translation id="733354035281974745">è£ç½®æœ¬æ©Ÿå¸³æˆ¶è¦†å¯«</translation>
<translation id="7333654844024768166">您剛æ‰åœ¨æ¬ºè©ç¶²ç«™ä¸Šè¼¸å…¥äº†å¯†ç¢¼ã€‚Chromium 建議å‰å¾€ <ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" />ã€<ph name="WEBSITE_3" /> 以åŠå…¶ä»–您使用此密碼的網站,並立å³è®Šæ›´å¯†ç¢¼ã€‚</translation>
<translation id="7334320624316649418">é‡åšé‡æ–°æŽ’åº(&amp;R)</translation>
+<translation id="7337248890521463931">顯示更多行</translation>
<translation id="7337706099755338005">無法在您的平å°ä¸Šä½¿ç”¨ã€‚</translation>
<translation id="733923710415886693">伺æœå™¨æ†‘證並未é€éŽæ†‘è­‰é€æ˜Žåº¦æ”¿ç­–披露。</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1652,6 +1698,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">命令列</translation>
<translation id="7359588939039777303">å·²å°éŽ–廣告。</translation>
+<translation id="7363096869660964304">然而,您並éžè™•æ–¼éš±è—狀態。使用無痕模å¼æ™‚,您的僱主ã€äº’è¯ç¶²æœå‹™ä¾›æ‡‰å•†æˆ–您所ç€è¦½çš„網站ä»ç„¶å¯ä»¥è¿½è¹¤æ‚¨çš„ç€è¦½è¡Œç‚ºã€‚</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />,㩒一下 Tab éµï¼Œç„¶å¾Œã©’一下 Enter éµå°±å¯ä»¥å–º Chrome 設定度新增åŒç®¡ç†åœ°å€</translation>
<translation id="7365849542400970216">知é“您的è£ç½®ä½¿ç”¨ç‹€æ…‹å—Žï¼Ÿ</translation>
<translation id="7372973238305370288">æœå°‹çµæžœ</translation>
@@ -1662,7 +1709,9 @@
<translation id="7378594059915113390">媒體控制項</translation>
<translation id="7378627244592794276">ä¸éœ€è¦</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ä¸é©ç”¨</translation>
<translation id="7390545607259442187">驗證信用å¡</translation>
+<translation id="7392089738299859607">更新地å€</translation>
<translation id="7399802613464275309">安全檢查</translation>
<translation id="7400418766976504921">網å€</translation>
<translation id="7403591733719184120">您的 <ph name="DEVICE_NAME" /> å·²å—管ç†</translation>
@@ -1677,6 +1726,7 @@
&lt;li&gt;å‰å¾€ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome 說明中心&lt;/a&gt;,瞭解如何從您的電腦中永久移除有關軟件
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">å¯æ„›</translation>
<translation id="7416351320495623771">管ç†å¯†ç¢¼â€¦</translation>
<translation id="7419106976560586862">設定檔路徑</translation>
<translation id="7437289804838430631">新增è¯çµ¡äººè³‡æ–™</translation>
@@ -1692,7 +1742,7 @@
<translation id="7481312909269577407">å‘å‰</translation>
<translation id="7485870689360869515">找ä¸åˆ°ä»»ä½•æ•¸æ“šã€‚</translation>
<translation id="7495528107193238112">此內容已被å°éŽ–。如è¦ä¿®æ­£å•é¡Œï¼Œè«‹è¯çµ¡ç¶²ç«™æ“有者。</translation>
-<translation id="7498234416455752244">繼續編輯</translation>
+<translation id="7498193950643227031">調整大å°å¯èƒ½å°Žè‡´æ‡‰ç”¨ç¨‹å¼ç„¡æ³•æ­£å¸¸é‹ä½œã€‚您ç¾åœ¨å¯ä»¥åœ¨ã€Œ<ph name="SETTINGS" />ã€ä¸­é™åˆ¶èª¿æ•´æ‡‰ç”¨ç¨‹å¼å¤§å°çš„功能。</translation>
<translation id="7503664977220660814">您剛æ‰åœ¨æ¬ºè©ç¶²ç«™ä¸Šè¼¸å…¥äº†å¯†ç¢¼ã€‚Chromium 建議您立å³æª¢æŸ¥å·²å„²å­˜åœ¨ <ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" /> 以åŠå…¶ä»–您使用此密碼的網站。</translation>
<translation id="7508255263130623398">傳回的政策è£ç½®è­˜åˆ¥ç¢¼ç‚ºç©ºç™½æˆ–與目å‰è£ç½®è­˜åˆ¥ç¢¼ä¸ç¬¦</translation>
<translation id="7508870219247277067">牛油果色</translation>
@@ -1712,6 +1762,7 @@
<translation id="7548892272833184391">修正連線錯誤</translation>
<translation id="7549584377607005141">這個網é éœ€è¦ä½¿ç”¨æ‚¨å…ˆå‰è¼¸å…¥çš„數據æ‰èƒ½æ­£ç¢ºé¡¯ç¤ºã€‚您å¯ä»¥é‡æ–°å‚³é€é€™äº›æ•¸æ“šï¼Œä½†é€™æ¨£åšæœƒé‡è¤‡é€™å€‹ç¶²é å…ˆå‰å·²åŸ·è¡Œçš„動作。</translation>
<translation id="7550637293666041147">您的è£ç½®ä½¿ç”¨è€…å稱和 Chrome 使用者å稱</translation>
+<translation id="755279583747225797">試用功能已啟用</translation>
<translation id="7552846755917812628">請嘗試按照以下æ示æ“作:</translation>
<translation id="7554475479213504905">ä»è¦é‡æ–°è¼‰å…¥åŠé¡¯ç¤ºå…§å®¹</translation>
<translation id="7554791636758816595">新分é </translation>
@@ -1730,7 +1781,6 @@
<translation id="7610193165460212391">值超出 <ph name="VALUE" /> 的範åœã€‚</translation>
<translation id="7613889955535752492">到期日:<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />,㩒一下 Tab éµï¼Œç„¶å¾Œã©’一下 Enter éµå°±å¯ä»¥å–º Chrome 設定度ç‡åŒç®¡ç†å¯†ç¢¼</translation>
-<translation id="7615602087246926389">您已經使用其他版本的「Google 帳戶ã€å¯†ç¢¼å°æ•¸æ“šé€²è¡ŒåŠ å¯†ï¼Œè«‹åœ¨ä¸‹æ–¹è¼¸å…¥å¯†ç¢¼ã€‚</translation>
<translation id="7616645509853975347">管ç†å“¡å·²åœ¨æ‚¨çš„ç€è¦½å™¨ä¸Šå•Ÿç”¨ Chrome Enterprise Connectors。這些連接器å¯å­˜å–您的部分資料。</translation>
<translation id="7619838219691048931">çµæŸå·¥ä½œè¡¨</translation>
<translation id="762844065391966283">一次一個物件</translation>
@@ -1795,13 +1845,12 @@
<translation id="782886543891417279">ç›®å‰ä½¿ç”¨çš„ Wi-Fi (<ph name="WIFI_NAME" />) å¯èƒ½è¦æ±‚您å‰å¾€å…¶ç™»å…¥é é¢ã€‚</translation>
<translation id="7836231406687464395">Postfix (ä¿¡å°)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ç„¡}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">é–‹å•Ÿé—œè¯é¡žåž‹çš„檔案。</translation>
<translation id="7862185352068345852">è¦é›¢é–‹ç¶²ç«™å—Žï¼Ÿ</translation>
<translation id="7865448901209910068">最佳速度</translation>
<translation id="7874263914261512992">您剛æ‰åœ¨æ¬ºè©ç¶²ç«™ä¸Šè¼¸å…¥äº†å¯†ç¢¼ã€‚Chrome 建議您立å³æª¢æŸ¥å·²å„²å­˜åœ¨ <ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" /> 以åŠå…¶ä»–您使用此密碼的網站。</translation>
<translation id="7878562273885520351">您的密碼å¯èƒ½æœƒè¢«ç›œç”¨</translation>
+<translation id="7880146494886811634">儲存地å€</translation>
<translation id="7882421473871500483">啡色</translation>
<translation id="7887683347370398519">請檢查您的 CVC,然後å†è©¦ä¸€æ¬¡</translation>
<translation id="7887885240995164102">進入畫中畫</translation>
@@ -1809,6 +1858,7 @@
<translation id="7894280532028510793">如果拼字正確,<ph name="BEGIN_LINK" />請嘗試執行網絡診斷<ph name="END_LINK" />。</translation>
<translation id="7904208859782148177">C3 (ä¿¡å°)</translation>
<translation id="7931318309563332511">ä¸æ˜Ž</translation>
+<translation id="793209273132572360">è¦æ›´æ–°åœ°å€å—Žï¼Ÿ</translation>
<translation id="7932579305932748336">塗布</translation>
<translation id="79338296614623784">請輸入有效的電話號碼</translation>
<translation id="7934052535022478634">付款完æˆ</translation>
@@ -1879,6 +1929,7 @@
<translation id="8175796834047840627">由於您已登入,因此 Chrome æ議將您的付款å¡å„²å­˜è‡³ Google 帳戶。您å¯ä»¥åœ¨è¨­å®šä¸­è®Šæ›´æ­¤è¡Œç‚ºã€‚</translation>
<translation id="8176440868214972690">æ­¤è£ç½®çš„管ç†å“¡å·²å°‡ä¸€äº›è³‡è¨Š (例如設定或政策) 傳é€åˆ°ä»¥ä¸‹ç¶²ç«™ã€‚</translation>
<translation id="8184538546369750125">使用全域é è¨­å€¼ (å…許)</translation>
+<translation id="8193086767630290324">在標示為機密的資料所採å–的行動</translation>
<translation id="8194797478851900357">復原移動(&amp;U)</translation>
<translation id="8201077131113104583">無效的擴充功能 (ID:<ph name="EXTENSION_ID" />) 更新網å€ã€‚</translation>
<translation id="8202097416529803614">訂單摘è¦</translation>
@@ -1901,6 +1952,7 @@
<translation id="8249296373107784235">å–消</translation>
<translation id="8249320324621329438">上次擷å–時間:</translation>
<translation id="8253091569723639551">å¿…é ˆæ供帳單地å€</translation>
+<translation id="8257387598443225809">此應用程å¼å°ˆç‚ºæµå‹•è£ç½®è€Œè¨­</translation>
<translation id="825929999321470778">顯示所有已儲存的密碼</translation>
<translation id="8261506727792406068">刪除</translation>
<translation id="8262952874573525464">é‚Šç·£è£è¨‚ (底部)</translation>
@@ -1967,7 +2019,7 @@
<translation id="8490137692873530638">堆疊器 10</translation>
<translation id="8498891568109133222"><ph name="HOST_NAME" /> 的回應時間éŽé•·ã€‚</translation>
<translation id="8503559462189395349">Chrome 密碼</translation>
-<translation id="8503813439785031346">使用者å稱</translation>
+<translation id="8503813439785031346">用戶å稱</translation>
<translation id="8507227106804027148">指令列</translation>
<translation id="8508648098325802031">æœå°‹åœ–示</translation>
<translation id="8511402995811232419">ç®¡ç† Cookie</translation>
@@ -2024,7 +2076,6 @@
<translation id="8719528812645237045">多孔 (頂端)</translation>
<translation id="8725066075913043281">å†è©¦ä¸€æ¬¡</translation>
<translation id="8726549941689275341">é é¢å¤§å°ï¼š</translation>
-<translation id="8728672262656704056">您已進入無痕模å¼</translation>
<translation id="8730621377337864115">完æˆ</translation>
<translation id="8731544501227493793">管ç†å¯†ç¢¼æŒ‰éˆ•ï¼Œã©’一下 Enter éµå°±å¯ä»¥å–º Chrome 設定度ç‡åŒç®¡ç†å¯†ç¢¼</translation>
<translation id="8734529307927223492">您的 <ph name="DEVICE_TYPE" /> ç”± <ph name="MANAGER" /> 管ç†</translation>
@@ -2101,6 +2152,7 @@
<translation id="9020542370529661692">這個網é å…§å®¹å·²ç¿»è­¯æˆ<ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(無效)</translation>
+<translation id="9030265603405983977">單色</translation>
<translation id="9035022520814077154">安全錯誤</translation>
<translation id="9038649477754266430">使用æœå°‹é æ¸¬æœå‹™ï¼ŒåŠ å¿«ç¶²é è¼‰å…¥é€Ÿåº¦</translation>
<translation id="9039213469156557790">而且,這個網é å«æœ‰å…¶ä»–ä¸å®‰å…¨çš„資æºã€‚其他人å¯èƒ½æœƒåœ¨è³‡æºå‚³è¼¸æœŸé–“檢視這些資æºï¼Œæ”»æ“Šè€…也å¯èƒ½æœƒä¿®æ”¹é€™äº›è³‡æºï¼Œç¹¼è€Œè®Šæ›´ç¶²é è¡Œç‚ºã€‚</translation>
@@ -2124,6 +2176,7 @@
<translation id="91108059142052966">當畫é¢ä¸Šå‡ºç¾æ©Ÿå¯†å…§å®¹ï¼Œç®¡ç†å“¡æ”¿ç­–就會åœç”¨èˆ‡ã€Œ<ph name="APPLICATION_TITLE" />ã€åˆ†äº«èž¢å¹•ç•«é¢çš„功能</translation>
<translation id="9114524666733003316">正在驗證信用å¡â€¦</translation>
<translation id="9114581008513152754">æ­¤ç€è¦½å™¨æœªå—任何公å¸æˆ–其他機構管ç†ã€‚æ­¤è£ç½®ä¸Šçš„活動å¯é€éŽ Chrome 以外的æœå‹™ç®¡ç†ã€‚<ph name="BEGIN_LINK" />瞭解詳情<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">æ–°é®®</translation>
<translation id="9119042192571987207">已上載</translation>
<translation id="9128016270925453879">載入咗政策</translation>
<translation id="9128870381267983090">連線至網路</translation>
@@ -2142,6 +2195,7 @@
<translation id="9170848237812810038">復原(&amp;U)</translation>
<translation id="9171296965991013597">è¦é€€å‡ºæ‡‰ç”¨ç¨‹å¼å—Žï¼Ÿ</translation>
<translation id="9173282814238175921">單一文件/新工作表</translation>
+<translation id="9173995187295789444">正在掃瞄è—牙è£ç½®â€¦</translation>
<translation id="917450738466192189">伺æœå™¨æ†‘證無效。</translation>
<translation id="9174917557437862841">分é åˆ‡æ›æŒ‰éˆ•ï¼Œã©’一下 Enter éµå°±å¯ä»¥è½‰åŽ»å‘¢å€‹åˆ†é </translation>
<translation id="9179703756951298733">在 Chrome 設定中管ç†ä»˜æ¬¾å’Œä¿¡ç”¨å¡è³‡æ–™</translation>
diff --git a/chromium/components/strings/components_strings_zh-TW.xtb b/chromium/components/strings/components_strings_zh-TW.xtb
index eef9eb4b71c..2cba1e9e1dd 100644
--- a/chromium/components/strings/components_strings_zh-TW.xtb
+++ b/chromium/components/strings/components_strings_zh-TW.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">勾é¸å¾Œï¼ŒChrome 會在這個è£ç½®ä¸Šå„²å­˜æ‚¨çš„信用å¡è¤‡æœ¬ï¼Œä»¥ä¾¿æ›´å¿«å¡«å¯«è³‡è¨Šã€‚</translation>
<translation id="1110994991967754504">é¸å–<ph name="PERMISSION_NAME" />權é™è¨­å®š</translation>
<translation id="1113869188872983271">復原é‡æ–°æŽ’åº(&amp;U)</translation>
+<translation id="1123753900084781868">ç›®å‰ç„¡æ³•ä½¿ç”¨å³æ™‚字幕功能</translation>
<translation id="1125573121925420732">網站更新安全性設定期間,å¯èƒ½æœƒç¶“常顯示警告。這項行為將於近期內改善。</translation>
<translation id="112840717907525620">政策快å–正確</translation>
<translation id="1130564665089811311">「翻譯網é ã€æŒ‰éˆ•ï¼ŒæŒ‰ä¸‹ Enter éµå³å¯ä½¿ç”¨ Google 翻譯來翻譯這個網é </translation>
@@ -74,6 +75,7 @@
<translation id="1240347957665416060">ä½ çš„è£ç½®å稱</translation>
<translation id="124116460088058876">更多語言</translation>
<translation id="1243027604378859286">作者:</translation>
+<translation id="1246424317317450637">ç²—é«”</translation>
<translation id="1250759482327835220">åªè¦å°‡ä½ çš„å¡ç‰‡è³‡è¨Šã€å§“å與帳單地å€å„²å­˜åˆ°ä½ çš„ Google 帳戶中,下次å³å¯æ›´å¿«å®Œæˆä»˜æ¬¾ç¨‹åºã€‚</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />ã€<ph name="TYPE_2" /> (å·²åŒæ­¥)</translation>
<translation id="1256368399071562588">&lt;p&gt;如果您無法順利開啟網站,請先嘗試按照以下疑難排解步驟修正相關錯誤:&lt;/p&gt;
@@ -156,6 +158,7 @@
<translation id="1476595624592550506">變更你的密碼</translation>
<translation id="1484290072879560759">é¸æ“‡é‹é€åœ°å€</translation>
<translation id="1492194039220927094">政策通知推é€ï¼š</translation>
+<translation id="1495677929897281669">返回分é </translation>
<translation id="1501859676467574491">顯示你 Google 帳戶中的å¡ç‰‡</translation>
<translation id="1507202001669085618">&lt;p&gt;如果您使用的 Wi-Fi å…¥å£ç¶²ç«™å¿…須先登入æ‰èƒ½é€£ä¸Šç¶²è·¯ï¼Œç³»çµ±å°±æœƒé¡¯ç¤ºé€™å‰‡éŒ¯èª¤è¨Šæ¯ã€‚&lt;/p&gt;
&lt;p&gt;如è¦ä¿®æ­£é€™å€‹éŒ¯èª¤ï¼Œè«‹åœ¨æ‚¨è¦å˜—試開啟的網é ä¸ŠæŒ‰ä¸€ä¸‹ [連線]&lt;strong&gt;&lt;/strong&gt;。&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@
<translation id="1532118530259321453">這個網é é¡¯ç¤º</translation>
<translation id="153384715582417236">暫無內容</translation>
<translation id="1536390784834419204">翻譯網é </translation>
+<translation id="1539840569003678498">回報時間:</translation>
<translation id="154408704832528245">é¸æ“‡å¿«éžåœ°å€</translation>
<translation id="1549470594296187301">您必須啟用 JavaScript æ‰èƒ½ä½¿ç”¨é€™é …功能。</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@
<translation id="1682696192498422849">先從短邊開始</translation>
<translation id="168693727862418163">這項政策的值未通éŽå…¶çµæ§‹å®šç¾©çš„驗證,因此會é­åˆ°å¿½ç•¥ã€‚</translation>
<translation id="168841957122794586">伺æœå™¨æ†‘è­‰å«æœ‰é˜²è­·åŠ›è–„弱的加密編譯金鑰。</translation>
+<translation id="1696290444144917273">查看虛擬å¡ç‰‡è³‡æ–™</translation>
<translation id="1697532407822776718">大功告æˆï¼</translation>
<translation id="1703835215927279855">Letter</translation>
<translation id="1706954506755087368">{1,plural, =1{這個伺æœå™¨ç„¡æ³•è­‰æ˜Žæ‰€åœ¨ç¶²åŸŸæ˜¯ <ph name="DOMAIN" />;伺æœå™¨çš„安全性憑證é å®šæ˜Žå¤©æ‰ç”Ÿæ•ˆã€‚這å¯èƒ½æ˜¯å› ç‚ºè¨­å®šéŒ¯èª¤ï¼Œæˆ–是有攻擊者攔截您的連線。}other{這個伺æœå™¨ç„¡æ³•è­‰æ˜Žæ‰€åœ¨ç¶²åŸŸæ˜¯ <ph name="DOMAIN" />;伺æœå™¨çš„安全性憑證é å®š # 天後æ‰ç”Ÿæ•ˆã€‚這å¯èƒ½æ˜¯å› ç‚ºè¨­å®šéŒ¯èª¤ï¼Œæˆ–是有攻擊者攔截您的連線。}}</translation>
<translation id="1710259589646384581">作業系統</translation>
+<translation id="1711234383449478798">由於 <ph name="POLICY_NAME" /> 未設為 <ph name="VALUE" />,因此é­åˆ°å¿½ç•¥ã€‚</translation>
<translation id="1712552549805331520"><ph name="URL" /> è¦æ±‚在你的本機電腦上永久儲存資料</translation>
<translation id="1713628304598226412">紙匣 2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">出紙槽 3</translation>
<translation id="1718029547804390981">文件éŽå¤§ï¼Œç„¡æ³•åŠ è¨»</translation>
<translation id="1721424275792716183">* 這是必填欄ä½</translation>
+<translation id="1727613060316725209">憑證有效</translation>
<translation id="1727741090716970331">新增有效的信用å¡è™Ÿç¢¼</translation>
<translation id="1728677426644403582">ç›®å‰é¡¯ç¤ºçš„是網é åŽŸå§‹ç¢¼</translation>
<translation id="173080396488393970">ä¸æ”¯æ´é€™ç¨®ä¿¡ç”¨å¡é¡žåž‹</translation>
@@ -242,7 +249,6 @@
<translation id="1768211456781949159"><ph name="BEGIN_LINK" />嘗試執行 Windows 網路診斷<ph name="END_LINK" />。</translation>
<translation id="1772163372082567643">ä½ è¦å­˜å–的伺æœå™¨ã€Œ<ph name="ORIGIN" />ã€å·²è¨­å®šæ¨™é ­ï¼ŒæŒ‡å®šæ‰€æœ‰æ”¶åˆ°çš„è¦æ±‚都必須套用來æºæ”¿ç­–。但該標頭格å¼éŒ¯èª¤ï¼Œå› æ­¤ç€è¦½å™¨ç„¡æ³•å®Œæˆä½ å‘「<ph name="SITE" />ã€æ出的è¦æ±‚。網站業者å¯ä½¿ç”¨ä¾†æºæ”¿ç­–設定網站的安全性和其他屬性。</translation>
<translation id="1778646502362731194">JIS B0</translation>
-<translation id="1783075131180517613">è«‹æ›´æ–°ä½ çš„åŒæ­¥é€šé—œå¯†èªžã€‚</translation>
<translation id="1787142507584202372">這裡會顯示你最近開啟的分é </translation>
<translation id="1791429645902722292">Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />,å¯åŸ·è¡Œå¤šå€‹å‹•ä½œï¼ŒæŒ‰ä¸‹ Tab éµå³å¯åˆ‡æ›ä¸åŒçš„動作</translation>
@@ -275,6 +281,7 @@
<translation id="1919345977826869612">廣告</translation>
<translation id="1919367280705858090">瞭解如何修正特定錯誤訊æ¯æŒ‡å‡ºçš„錯誤</translation>
<translation id="192020519938775529">{COUNT,plural, =0{無}=1{1 個網站}other{# 個網站}}</translation>
+<translation id="1924727005275031552">新地å€</translation>
<translation id="1945968466830820669">ä½ å¯èƒ½æœƒå¤±åŽ»è²´æ©Ÿæ§‹å¸³æˆ¶çš„å­˜å–權,或身分é­åˆ°å†’用。Chromium 建議你立å³è®Šæ›´å¯†ç¢¼ã€‚</translation>
<translation id="1947454675006758438">é‡˜è£ (å³ä¸Šæ–¹)</translation>
<translation id="1958218078413065209">最高得分為 <ph name="SCORE" />。</translation>
@@ -297,12 +304,14 @@
<translation id="2042213636306070719">紙匣 7</translation>
<translation id="204357726431741734">登入以使用儲存在 Google 帳戶中的密碼</translation>
<translation id="2053111141626950936">系統ä¸æœƒç¿»è­¯<ph name="LANGUAGE" />網é ã€‚</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{如果這項功能已啟用且處於有效狀態,Chrome 就能判斷你近期的ç€è¦½æ´»å‹•èˆ‡å“ªå€‹å¤§åž‹ä½¿ç”¨è€…群組 (或稱「åŒé¡žç¾¤çµ„ã€) 最為相近。廣告客戶å¯ä»¥é¸æ“‡è¦å‘該群組顯示的廣告,而你的ç€è¦½è¨˜éŒ„會ä¿ç•™åœ¨è£ç½®ä¸Šï¼Œåƒ…供本人存å–。你所在的群組會æ¯å¤©æ›´æ–°ã€‚}=1{如果這項功能已啟用且處於有效狀態,Chrome 就能判斷你近期的ç€è¦½æ´»å‹•èˆ‡å“ªå€‹å¤§åž‹ä½¿ç”¨è€…群組 (或稱「åŒé¡žç¾¤çµ„ã€) 最為相近。廣告客戶å¯ä»¥é¸æ“‡è¦å‘該群組顯示的廣告,而你的ç€è¦½è¨˜éŒ„會ä¿ç•™åœ¨è£ç½®ä¸Šï¼Œåƒ…供本人存å–。你所在的群組會æ¯å¤©æ›´æ–°ã€‚}other{如果這項功能已啟用且處於有效狀態,Chrome 就能判斷你近期的ç€è¦½æ´»å‹•èˆ‡å“ªå€‹å¤§åž‹ä½¿ç”¨è€…群組 (或稱「åŒé¡žç¾¤çµ„ã€) 最為相近。廣告客戶å¯ä»¥é¸æ“‡è¦å‘該群組顯示的廣告,而你的ç€è¦½è¨˜éŒ„會ä¿ç•™åœ¨è£ç½®ä¸Šï¼Œåƒ…供本人存å–。你所在的群組會æ¯éš” {NUM_DAYS} 天更新。}}</translation>
<translation id="2053553514270667976">郵éžå€è™Ÿ</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 個建議項目}other{# 個建議項目}}</translation>
<translation id="2071692954027939183">系統已按照你的習慣自動å°éŽ–通知</translation>
<translation id="2079545284768500474">復原</translation>
<translation id="20817612488360358">雖然系統 Proxy 設定已設為使用,ä¸éŽä¹ŸæŒ‡å®šäº†æ˜Žç¢º Proxy 設定。</translation>
<translation id="2082238445998314030">第 <ph name="RESULT_NUMBER" /> 個çµæžœï¼Œå…± <ph name="TOTAL_RESULTS" /> 個</translation>
+<translation id="2085876078937250610">儲存…</translation>
<translation id="2088086323192747268">「管ç†åŒæ­¥åŠŸèƒ½ã€æŒ‰éˆ•ï¼›æŒ‰ä¸‹ Enter éµå³å¯åœ¨ Chrome 設定中管ç†è¦åŒæ­¥è™•ç†å“ªäº›è³‡è¨Š</translation>
<translation id="2091887806945687916">音訊</translation>
<translation id="2094505752054353250">網域ä¸ç¬¦</translation>
@@ -375,6 +384,7 @@
<translation id="2317259163369394535"><ph name="DOMAIN" /> è¦æ±‚æ供使用者å稱和密碼。</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />,到期日:<ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">管ç†å“¡æ‰€æŽ§åˆ¶çš„設定</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> è¦æ±‚é…å°</translation>
<translation id="2344028582131185878">自動下載</translation>
<translation id="2346319942568447007">你複製的圖片</translation>
<translation id="2354001756790975382">其他書籤</translation>
@@ -382,8 +392,10 @@
<translation id="2355395290879513365">攻擊者å¯èƒ½æœƒçœ‹åˆ°ä½ æ­£åœ¨é€™å€‹ç¶²ç«™ä¸Šç€è¦½çš„圖片,並以修改圖片內容的方å¼è®“ä½ å—騙。</translation>
<translation id="2356070529366658676">è©¢å•</translation>
<translation id="2357481397660644965">ä½ çš„è£ç½®æ˜¯ç”± <ph name="DEVICE_MANAGER" /> 管ç†ï¼Œå¸³æˆ¶æ˜¯ç”± <ph name="ACCOUNT_MANAGER" /> 管ç†ã€‚</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{ä¸åˆ° 1 天後}=1{1 天後}other{{NUM_DAYS} 天後}}</translation>
<translation id="2359629602545592467">多種</translation>
<translation id="2359808026110333948">繼續</translation>
+<translation id="2359961752320758691">已套用虛擬å¡è™Ÿã€‚</translation>
<translation id="2367567093518048410">等級</translation>
<translation id="2372464001869762664">確èªå¾Œï¼Œé€™å€‹ç¶²ç«™å°±æœƒå–得你在 Google 帳戶中的å¡ç‰‡è³‡æ–™ã€‚如è¦æŸ¥è©¢ä¿¡ç”¨å¡é©—證碼,請ç€è¦½ Plex 帳戶詳細資料。</translation>
<translation id="2380886658946992094">Legal</translation>
@@ -394,6 +406,7 @@
<translation id="239429038616798445">ä¸æ”¯æ´æ‰€é¸çš„é‹é€æ–¹å¼ï¼Œè«‹æ”¹é¸å…¶ä»–æ–¹å¼ã€‚</translation>
<translation id="2396249848217231973">復原刪除(&amp;U)</translation>
<translation id="2410754574180102685">Government-Legal</translation>
+<translation id="2413155254802890957">舊地å€</translation>
<translation id="2413528052993050574">伺æœå™¨ç„¡æ³•è­‰æ˜Žå…¶å±¬æ–¼ <ph name="DOMAIN" /> 網域;其安全性憑證已é­æ’¤éŠ·ã€‚這å¯èƒ½æ˜¯å› ç‚ºè¨­å®šéŒ¯èª¤ï¼Œæˆ–有攻擊者攔截你的連線所致。</translation>
<translation id="2414886740292270097">深色</translation>
<translation id="2438874542388153331">四孔 (å³å´)</translation>
@@ -421,10 +434,10 @@
<translation id="2521385132275182522">é‡˜è£ (å³ä¸‹æ–¹)</translation>
<translation id="2523886232349826891">僅儲存在這部è£ç½®</translation>
<translation id="2524461107774643265">新增詳細資訊</translation>
-<translation id="2526590354069164005">æ¡Œé¢</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{å’Œå¦å¤– 1 個網域}other{å’Œå¦å¤– # 個網域}}</translation>
<translation id="2536110899380797252">新增地å€</translation>
<translation id="2539524384386349900">åµæ¸¬</translation>
+<translation id="2541219929084442027">關閉所有無痕分é å¾Œï¼Œä½ åœ¨å…¶ä¸­ç€è¦½çš„網é éƒ½ä¸æœƒä¿ç•™åœ¨ç€è¦½å™¨è¨˜éŒ„ã€Cookie 儲存庫或æœå°‹è¨˜éŒ„中。ä¸éŽï¼Œä½ ä¸‹è¼‰çš„檔案或建立的書籤全部都會ä¿ç•™ä¸‹ä¾†ã€‚</translation>
<translation id="2544644783021658368">單一文件</translation>
<translation id="254947805923345898">政策的值無效。</translation>
<translation id="255002559098805027"><ph name="HOST_NAME" /> 傳é€çš„回應無效。</translation>
@@ -444,6 +457,7 @@
<translation id="2629325967560697240">è¦ç²å¾— Chrome 最高等級的安全防護,請<ph name="BEGIN_ENHANCED_PROTECTION_LINK" />啟用強化防護功能<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">找ä¸åˆ° <ph name="HOST_NAME" /> 的伺æœå™¨ IP ä½å€ã€‚</translation>
<translation id="2639739919103226564">狀態:</translation>
+<translation id="264810637653812429">找ä¸åˆ°ç›¸å®¹çš„è£ç½®ã€‚</translation>
<translation id="2649204054376361687"><ph name="COUNTRY" />,<ph name="CITY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />,按下 Tab éµå†æŒ‰ä¸‹ Enter éµå³å¯åœ¨ Chrome 設定中清除你的ç€è¦½è¨˜éŒ„ã€Cookieã€å¿«å–和其他資料</translation>
<translation id="2650446666397867134">å­˜å–檔案é­æ‹’</translation>
@@ -488,6 +502,7 @@
<translation id="2799223571221894425">é‡æ–°å•Ÿå‹•</translation>
<translation id="2803306138276472711">Google 安全ç€è¦½åŠŸèƒ½æœ€è¿‘在 <ph name="SITE" /> 上<ph name="BEGIN_LINK" />åµæ¸¬åˆ°æƒ¡æ„軟體<ph name="END_LINK" />。å³ä½¿æ˜¯å¹³å¸¸å¯ä»¥å®‰å…¨ä½¿ç”¨çš„網站,有時也會é­åˆ°æƒ¡æ„軟體感染。</translation>
<translation id="2807052079800581569">圖片 Y ä½ç½®</translation>
+<translation id="2820957248982571256">掃æ中...</translation>
<translation id="2824775600643448204">網å€èˆ‡æœå°‹åˆ—</translation>
<translation id="2826760142808435982">連線採用 <ph name="CIPHER" /> 加密,並設有 <ph name="KX" /> 金鑰交æ›æ©Ÿåˆ¶ã€‚</translation>
<translation id="2835170189407361413">清除表單</translation>
@@ -495,6 +510,8 @@
<translation id="2850739647070081192">Invite (ä¿¡å°)</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="2859806420264540918">這個網站會顯示干擾性或誤導性的廣告。</translation>
+<translation id="287596039013813457">å‹å–„</translation>
+<translation id="2876489322757410363">å³å°‡é€€å‡ºç„¡ç—•æ¨¡å¼ï¼Œæ”¹ç‚ºä½¿ç”¨å¤–部應用程å¼ä»˜æ¬¾ï¼Œè¦ç¹¼çºŒå—Žï¼Ÿ</translation>
<translation id="2878197950673342043">å字摺</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">放置視窗</translation>
@@ -544,7 +561,6 @@
<translation id="3060227939791841287">C9 (ä¿¡å°)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />,ä¾åºæŒ‰ä¸‹ Tab éµå’Œ Enter éµå³å¯åœ¨ Chrome 設定中執行安全檢查</translation>
<translation id="3061707000357573562">修補æœå‹™</translation>
-<translation id="3064966200440839136">å³å°‡é›¢é–‹ç„¡ç—•æ¨¡å¼ï¼Œæ”¹ç‚ºä½¿ç”¨å¤–部應用程å¼ä»˜æ¬¾ï¼Œè¦ç¹¼çºŒå—Žï¼Ÿ</translation>
<translation id="306573536155379004">已啟動éŠæˆ²ã€‚</translation>
<translation id="3080254622891793721">圖片</translation>
<translation id="3086579638707268289">你的網路活動正é­åˆ°ç›£æŽ§</translation>
@@ -567,7 +583,6 @@
<translation id="315504272643575312">你的帳戶是由 <ph name="MANAGER" /> 管ç†ã€‚</translation>
<translation id="3157931365184549694">還原</translation>
<translation id="3162559335345991374">ç›®å‰ä½¿ç”¨çš„ Wi-Fi 網路å¯èƒ½æœƒè¦æ±‚您造訪登入網é ã€‚</translation>
-<translation id="3167968892399408617">當您關閉所有無痕å¼åˆ†é å¾Œï¼Œæ‚¨åœ¨å…¶ä¸­ç€è¦½çš„網é éƒ½ä¸æœƒä¿ç•™åœ¨ç€è¦½å™¨è¨˜éŒ„ã€Cookie 儲存庫或æœå°‹è¨˜éŒ„中。ä¸éŽï¼Œæ‚¨ä¸‹è¼‰çš„檔案或建立的書籤全部都會ä¿ç•™ä¸‹ä¾†ã€‚</translation>
<translation id="3169472444629675720">Discover</translation>
<translation id="3174168572213147020">島</translation>
<translation id="3176929007561373547">檢查您的 Proxy 設定,或是與您的網路管ç†å“¡è¯çµ¡
@@ -593,10 +608,12 @@
<translation id="3229041911291329567">è£ç½®å’Œç€è¦½å™¨çš„版本資訊</translation>
<translation id="323107829343500871">輸入 <ph name="CREDIT_CARD" /> 的信用å¡é©—證碼</translation>
<translation id="3234666976984236645">一律åµæ¸¬é€™å€‹ç¶²ç«™çš„é‡è¦å…§å®¹</translation>
+<translation id="3249845759089040423">時髦</translation>
<translation id="3252266817569339921">法文</translation>
<translation id="3266793032086590337">值 (è¡çª)</translation>
<translation id="3268451620468152448">開啟的分é </translation>
<translation id="3270847123878663523">復原é‡æ–°æŽ’åº(&amp;U)</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> è¦æ±‚連線</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">貴機構 (<ph name="ENROLLMENT_DOMAIN" />) 已將一些資訊 (例如設定或政策) 傳é€åˆ°ä¸‹åˆ—網站。</translation>
<translation id="3282497668470633863">新增æŒå¡äººå§“å</translation>
@@ -649,6 +666,7 @@
<translation id="3428151540071562330">一或多個 DnsOverHttpsTemplates 伺æœå™¨ç¯„本 URI 無效,因此系統ä¸æœƒæŽ¡ç”¨é€™äº›ä¼ºæœå™¨ç¯„本 URI。</translation>
<translation id="3431636764301398940">將這張信用å¡å„²å­˜åˆ°é€™å€‹è£ç½®</translation>
<translation id="3432601291244612633">關閉é é¢</translation>
+<translation id="3435738964857648380">安全性</translation>
<translation id="3435896845095436175">啟用</translation>
<translation id="3438829137925142401">使用儲存在 Google 帳戶中的密碼</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -691,7 +709,10 @@
<translation id="3584299510153766161">雙孔 (底部)</translation>
<translation id="3586931643579894722">éš±è—詳細資訊</translation>
<translation id="3587738293690942763">中間</translation>
+<translation id="3590643883886679995">系統會在無痕模å¼çµæŸå¾Œå°‡ç™»å…¥è³‡æ–™å„²å­˜åœ¨é€™éƒ¨è£ç½®ä¸Šã€‚</translation>
+<translation id="359126217934908072">月/年:</translation>
<translation id="3592413004129370115">Italian (ä¿¡å°)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{你隨時å¯ä»¥é‡è¨­ç¾¤çµ„ã€‚å¤§ç´„éœ€è¦ 1 天æ‰èƒ½åŠ å…¥æ–°ç¾¤çµ„。}=1{你隨時å¯ä»¥é‡è¨­ç¾¤çµ„ã€‚å¤§ç´„éœ€è¦ 1 天æ‰èƒ½åŠ å…¥æ–°ç¾¤çµ„。}other{你隨時å¯ä»¥é‡è¨­ç¾¤çµ„ã€‚éœ€è¦ {NUM_DAYS} 天æ‰èƒ½åŠ å…¥æ–°ç¾¤çµ„。}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />,<ph name="DOMAIN" />,<ph name="TIME" /></translation>
<translation id="3603507503523709">å·²é­ç³»çµ±ç®¡ç†å“¡å°éŽ–的應用程å¼</translation>
<translation id="3608932978122581043">é€ç´™æ–¹å‘</translation>
@@ -700,13 +721,13 @@
<translation id="3615877443314183785">請輸入有效的到期日</translation>
<translation id="36224234498066874">清除ç€è¦½è³‡æ–™...</translation>
<translation id="362276910939193118">顯示完整記錄</translation>
-<translation id="3625635938337243871">系統會在無痕模å¼çµæŸå¾Œå°‡ç™»å…¥è³‡æ–™å„²å­˜åœ¨é€™éƒ¨è£ç½®ä¸Šã€‚</translation>
<translation id="3630155396527302611">如果程å¼å·²åˆ—在å…許存å–網路的清單中,建議您
從清單中將其移除,然後å†é‡æ–°åŠ å…¥ã€‚</translation>
<translation id="3630699740441428070">這部è£ç½®çš„系統管ç†å“¡å·²è¨­å®šä½ çš„網路連線,這項設定å¯èƒ½æœƒè®“系統管ç†å“¡å¯ä»¥æŸ¥çœ‹ä½ çš„網路æµé‡ (包括你所造訪的網站)。</translation>
<translation id="3631244953324577188">生物特徵辨識</translation>
<translation id="3633738897356909127">「更新 Chromeã€æŒ‰éˆ•ï¼ŒæŒ‰ä¸‹ Enter éµå³å¯é€éŽ Chrome 設定來更新 Chrome</translation>
<translation id="3634530185120165534">紙匣 5</translation>
+<translation id="3637662659967048211">儲存至 Google 帳戶</translation>
<translation id="3640766068866876100">Index-4x6-Ext</translation>
<translation id="3642638418806704195">應用程å¼ï¼š</translation>
<translation id="3650584904733503804">é©—è­‰æˆåŠŸ</translation>
@@ -747,6 +768,7 @@
<translation id="3781428340399460090">亮粉色</translation>
<translation id="3783418713923659662">Mastercard</translation>
<translation id="3784372983762739446">è—牙è£ç½®</translation>
+<translation id="3787675388804467730">虛擬å¡è™Ÿ</translation>
<translation id="3787705759683870569">到期日:<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">粗細:16</translation>
<translation id="3789841737615482174">安è£</translation>
@@ -766,6 +788,7 @@
<translation id="3841184659773414994">檔案處ç†å¸¸å¼</translation>
<translation id="385051799172605136">返回</translation>
<translation id="3858027520442213535">更新日期和時間</translation>
+<translation id="3881478300875776315">顯示較少行</translation>
<translation id="3884278016824448484">è£ç½® ID 發生è¡çª</translation>
<translation id="3885155851504623709">æ•™å€</translation>
<translation id="388632593194507180">åµæ¸¬åˆ°ä½ æ­£é­åˆ°ç›£æŽ§</translation>
@@ -791,6 +814,7 @@
<translation id="397105322502079400">計算中…</translation>
<translation id="3973234410852337861"><ph name="HOST_NAME" /> é­åˆ°å°éŽ–</translation>
<translation id="3973357910713125165">Chrome 安全檢查的執行按鈕,按下 Enter éµå³å¯åœ¨ Chrome 設定中執行安全檢查</translation>
+<translation id="3986705137476756801">暫時關閉å³æ™‚字幕</translation>
<translation id="3987405730340719549">Chrome 判斷這å¯èƒ½æ˜¯å½é€ ç¶²ç«™æˆ–è©é¨™ç¶²ç«™ã€‚
如果你èªç‚ºç³»çµ±ä¸æ‡‰é¡¯ç¤ºé€™å‰‡è¨Šæ¯ï¼Œè«‹å‰å¾€ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals。</translation>
@@ -882,13 +906,14 @@
<translation id="4275830172053184480">é‡æ–°å•Ÿå‹•è£ç½®</translation>
<translation id="4277028893293644418">é‡è¨­å¯†ç¢¼</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{這張å¡ç‰‡å·²å„²å­˜åˆ°ä½ çš„ Google 帳戶}other{這些å¡ç‰‡å·²å„²å­˜åˆ°ä½ çš„ Google 帳戶}}</translation>
+<translation id="4287885627794386150">符åˆé©ç”¨æ¢ä»¶ä½†å°šæœªå•Ÿç”¨</translation>
<translation id="4297502707443874121">第 <ph name="THUMBNAIL_PAGE" /> é çš„縮圖</translation>
<translation id="42981349822642051">展開</translation>
<translation id="4300675098767811073">多孔 (å³å´)</translation>
<translation id="4302514097724775343">輕觸æé¾å³å¯é–‹å§‹éŠæˆ²</translation>
<translation id="4302965934281694568">Chou3 (ä¿¡å°)</translation>
<translation id="4305666528087210886">無法存å–你的檔案</translation>
-<translation id="4305817255990598646">切æ›</translation>
+<translation id="4306529830550717874">è¦å„²å­˜åœ°å€å—Žï¼Ÿ</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">å°éŽ– (é è¨­)</translation>
<translation id="4314815835985389558">管ç†åŒæ­¥åŠŸèƒ½è³‡æ–™</translation>
@@ -915,6 +940,7 @@
<translation id="4377125064752653719">你嘗試å‰å¾€ <ph name="DOMAIN" />,但是發行者已撤銷伺æœå™¨æ供的憑證。在這種情æ³ä¸‹ï¼Œè«‹å‹¿ä¿¡ä»»ä¼ºæœå™¨æ供的安全性憑證,因為你的連線å°è±¡å¯èƒ½æ˜¯æ”»æ“Šè€…的電腦。</translation>
<translation id="4378154925671717803">電話</translation>
<translation id="4390472908992056574">邊裙</translation>
+<translation id="4406883609789734330">å³æ™‚字幕</translation>
<translation id="4406896451731180161">æœå°‹çµæžœ</translation>
<translation id="4408413947728134509"><ph name="NUM_COOKIES" /> 個 Cookie</translation>
<translation id="4414290883293381923">你剛æ‰åœ¨è©é¨™ç¶²ç«™ä¸Šè¼¸å…¥äº†å¯†ç¢¼ã€‚Chrome 建議你立å³å‰å¾€ <ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" />ã€<ph name="WEBSITE_3" />,以åŠä¹Ÿä½¿ç”¨é€™å€‹å¯†ç¢¼çš„其他網站變更密碼。</translation>
@@ -927,7 +953,6 @@
<translation id="4435702339979719576">明信片)</translation>
<translation id="443673843213245140">雖然已åœç”¨ Proxy,ä¸éŽå·²æŒ‡å®šæ˜Žç¢º Proxy 設定。</translation>
<translation id="4464826014807964867">有貴機構資訊的網站</translation>
-<translation id="4466881336512663640">ä½ å°è¡¨å–®æ‰€åšè®Šæ›´å°‡æœƒéºå¤±ã€‚確定è¦ç¹¼çºŒå—Žï¼Ÿ</translation>
<translation id="4476953670630786061">這個表單ä¸å®‰å…¨ï¼Œå› æ­¤ç³»çµ±å·²åœç”¨è‡ªå‹•å¡«å…¥åŠŸèƒ½ã€‚</translation>
<translation id="4477350412780666475">下一首曲目</translation>
<translation id="4482953324121162758">系統ä¸æœƒç¿»è­¯é€™å€‹ç¶²ç«™ã€‚</translation>
@@ -945,7 +970,7 @@
<translation id="4515275063822566619">信用å¡å’Œåœ°å€è³‡è¨Šçš†ä¾†è‡ª Chrome 和你的 Google 帳戶 (<ph name="ACCOUNT_EMAIL" />)。你å¯ä»¥åœ¨<ph name="BEGIN_LINK" />設定<ph name="END_LINK" />é é¢ç®¡ç†é€™äº›è³‡è¨Šã€‚</translation>
<translation id="4517607026994743406">Comm-10 (ä¿¡å°)</translation>
<translation id="4521157617044179198"><ph name="WIDTH" /> × <ph name="HEIGHT" /> å…¬é‡ (<ph name="ORIENTATION" />)</translation>
-<translation id="4522570452068850558">詳細資訊</translation>
+<translation id="4522570452068850558">詳細資料</translation>
<translation id="4524138615196389145">ç¾åœ¨å°±é–‹å§‹ä½¿ç”¨ WebAuthn,加快å¡ç‰‡é©—證速度</translation>
<translation id="4524805452350978254">管ç†å¡ç‰‡</translation>
<translation id="4542971377163063093">紙匣 6</translation>
@@ -961,6 +986,7 @@
<translation id="4594403342090139922">復原刪除(&amp;U)</translation>
<translation id="4597348597567598915">粗細:8</translation>
<translation id="4600854749408232102">C6/C5 (ä¿¡å°)</translation>
+<translation id="4606870351894164739">深具影響力</translation>
<translation id="4628948037717959914">相片</translation>
<translation id="4631649115723685955">已連çµç¾é‡‘回饋</translation>
<translation id="4636930964841734540">資訊</translation>
@@ -980,6 +1006,7 @@
<translation id="4691835149146451662">Architecture-A (ä¿¡å°)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">å´é‚Š</translation>
+<translation id="4702656508969495934">已顯示å³æ™‚字幕,使用視窗切æ›é¸é …將焦點移至å³æ™‚字幕</translation>
<translation id="4708268264240856090">您的連線已中斷</translation>
<translation id="4712404868219726379">Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />執行 Windows 網路診斷<ph name="END_LINK" /></translation>
@@ -993,6 +1020,7 @@
<translation id="4738601419177586157">「<ph name="TEXT" />ã€æœå°‹å»ºè­°</translation>
<translation id="4742407542027196863">管ç†å¯†ç¢¼â€¦</translation>
<translation id="4744603770635761495">å¯åŸ·è¡Œæª”的路徑</translation>
+<translation id="4749011317274908093">你已進入無痕模å¼</translation>
<translation id="4750917950439032686">你傳é€çµ¦é€™å€‹ç¶²ç«™çš„資訊 (例如密碼或信用å¡è™Ÿç¢¼) ä¸æœƒå¤–洩。</translation>
<translation id="4756388243121344051">記錄(&amp;H)</translation>
<translation id="4758311279753947758">新增è¯çµ¡è³‡è¨Š</translation>
@@ -1022,6 +1050,8 @@
<translation id="4813512666221746211">網路錯誤</translation>
<translation id="4816492930507672669">ä¾é é¢å¤§å°è‡ªå‹•èª¿æ•´</translation>
<translation id="4819347708020428563">è¦åœ¨é è¨­æª¢è¦–中編輯註解嗎?</translation>
+<translation id="4825507807291741242">強大</translation>
+<translation id="4838327282952368871">夢幻</translation>
<translation id="484462545196658690">自動</translation>
<translation id="4850886885716139402">檢視</translation>
<translation id="485316830061041779">å¾·æ–‡</translation>
@@ -1158,6 +1188,7 @@
<translation id="5314967030527622926">手冊製作工具</translation>
<translation id="5316812925700871227">逆時é‡æ—‹è½‰</translation>
<translation id="5317780077021120954">儲存</translation>
+<translation id="5321288445143113935">最大化</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />,<ph name="NUM_MATCHES" /> 之 <ph name="MATCH_POSITION" /></translation>
<translation id="5324080437450482387">é¸æ“‡è¯çµ¡è³‡è¨Š</translation>
<translation id="5327248766486351172">å稱</translation>
@@ -1165,11 +1196,13 @@
<translation id="5332219387342487447">é‹é€æ–¹å¼</translation>
<translation id="5333022057423422993">Chrome 發ç¾ä½ å‰›æ‰ä½¿ç”¨çš„密碼因為資料侵害事件而é­åˆ°å¤–洩。如è¦ç¢ºä¿å¸³æˆ¶å®‰å…¨ï¼Œå»ºè­°ä½ æª¢æŸ¥å·²å„²å­˜çš„密碼。</translation>
<translation id="5334013548165032829">詳細系統記錄</translation>
+<translation id="5334145288572353250">è¦å„²å­˜åœ°å€å—Žï¼Ÿ</translation>
<translation id="5340250774223869109">應用程å¼å·²é­å°éŽ–</translation>
<translation id="534295439873310000">NFC è£ç½®</translation>
<translation id="5344579389779391559">進入接下來的é é¢å¾Œï¼Œç³»çµ±å¯èƒ½æœƒå‘您收費</translation>
<translation id="5355557959165512791">ç›®å‰ç„¡æ³•é€ è¨ª <ph name="SITE" />,因為這個網站的憑證已é­æ’¤éŠ·ã€‚網路錯誤和攻擊行為通常是暫時性的,因此這個網é å¯èƒ½ç¨å¾Œå°±æœƒæ¢å¾©æ­£å¸¸ç‹€æ…‹ã€‚</translation>
<translation id="536296301121032821">無法儲存政策設定</translation>
+<translation id="5363309033720083897">管ç†å“¡å…許使用的åºåˆ—埠</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="5386426401304769735">這個網站的憑證éˆçµåŒ…å«ä½¿ç”¨ SHA-1 進行簽署的憑證。</translation>
@@ -1178,6 +1211,7 @@
<translation id="5398772614898833570">å·²å°éŽ–廣告</translation>
<translation id="5400836586163650660">ç°</translation>
<translation id="540969355065856584">這個伺æœå™¨ç„¡æ³•è­‰æ˜Žæ‰€å±¬ç¶²åŸŸç‚º <ph name="DOMAIN" />;其安全性憑證目å‰ç„¡æ•ˆã€‚這å¯èƒ½æ˜¯å› ç‚ºè¨­å®šéŒ¯èª¤ï¼Œæˆ–是有攻擊者攔截您的連線所致。</translation>
+<translation id="541143247543991491">雲端 (整個系統)</translation>
<translation id="541416427766103491">堆疊出紙器 4</translation>
<translation id="5421136146218899937">清除ç€è¦½è³‡æ–™...</translation>
<translation id="5426179911063097041"><ph name="SITE" /> è¦æ±‚傳é€é€šçŸ¥çµ¦ä½ </translation>
@@ -1191,6 +1225,7 @@
<translation id="5455374756549232013">政策時間戳記有誤</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" /> é …è¯çµ¡è³‡è¨Š}other{「<ph name="CONTACT_PREVIEW" />ã€å’Œå¦å¤– <ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> é …è¯çµ¡è³‡è¨Š}}</translation>
+<translation id="5463625433003343978">正在尋找è£ç½®â€¦</translation>
<translation id="5469868506864199649">義大利文</translation>
<translation id="5470861586879999274">é‡åšç·¨è¼¯(&amp;R)</translation>
<translation id="5478437291406423475">B6/C4 (ä¿¡å°)</translation>
@@ -1240,7 +1275,6 @@
<translation id="5624120631404540903">管ç†å¯†ç¢¼</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="563324245173044180">å·²å°éŽ–欺騙性內容。</translation>
<translation id="5644090287519800334">å´é‚Š 1 圖片 X 批次</translation>
@@ -1279,12 +1313,12 @@
<translation id="5785756445106461925">此外,這個網é å«æœ‰å…¶ä»–ä¸å®‰å…¨çš„資æºã€‚其他人å¯èƒ½æœƒåœ¨è³‡æºå‚³è¼¸æœŸé–“檢視這些資æºï¼Œæ”»æ“Šè€…也å¯èƒ½æœƒä¿®æ”¹é€™äº›è³‡æºï¼Œé€²è€Œè®Šæ›´ç¶²é å¤–觀。</translation>
<translation id="5786044859038896871">è¦å¡«å…¥ä½ çš„信用å¡è³‡è¨Šå—Žï¼Ÿ</translation>
<translation id="578633867165174378">Chrome 發ç¾ä½ å‰›æ‰ä½¿ç”¨çš„密碼因為資料侵害事件而é­åˆ°å¤–洩。建議你立å³è®Šæ›´å¯†ç¢¼ã€‚</translation>
-<translation id="5798290721819630480">è¦æ¨æ£„變更嗎?</translation>
<translation id="5803412860119678065">è¦å¡«å…¥ä½ çš„ <ph name="CARD_DETAIL" /> 資訊嗎?</translation>
<translation id="5804241973901381774">權é™</translation>
<translation id="5804427196348435412">使用 NFC è£ç½®</translation>
<translation id="5810442152076338065">您的 <ph name="DOMAIN" /> 連線使用éŽèˆŠçš„加密套件進行加密。</translation>
<translation id="5813119285467412249">é‡åšæ–°å¢ž(&amp;R)</translation>
+<translation id="5817918615728894473">é…å°</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{當你付款時,系統會從這張å¡ç‰‡æ‰£æ¬¾ã€‚別擔心,我們ä¸æœƒå°‡å¡ç‰‡çš„實際å¡è™Ÿæ供給這個網站。為了加強安全性,系統會產生暫時性的信用å¡é©—證碼。}other{當你付款時,系統會從這張å¡ç‰‡æ‰£æ¬¾ã€‚別擔心,我們ä¸æœƒå°‡å¡ç‰‡çš„實際å¡è™Ÿæ供給這個網站。為了加強安全性,系統會產生暫時性的信用å¡é©—證碼。}}</translation>
<translation id="5826507051599432481">一般å稱 (CN)</translation>
<translation id="5838278095973806738">請勿在這個網站上輸入任何機密資訊 (例如密碼或信用å¡è™Ÿç¢¼),以å…é­åˆ°æ”»æ“Šè€…ç«Šå–。</translation>
@@ -1292,6 +1326,7 @@
<translation id="5855253129151731373">這個網站的主機å稱與 <ph name="LOOKALIKE_DOMAIN" /> 相似。攻擊者有時會在網域å稱中加入ä¸æ˜“察覺的細微變更來仿冒網站。
如果你èªç‚ºç³»çµ±ä¸æ‡‰é¡¯ç¤ºé€™å‰‡è¨Šæ¯ï¼Œè«‹å‰å¾€ https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals。</translation>
+<translation id="5860033963881614850">關閉</translation>
<translation id="5862579898803147654">堆疊出紙器 8</translation>
<translation id="5863847714970149516">ä½ è¦ç€è¦½çš„網é å¯èƒ½æœƒå‘你收å–費用</translation>
<translation id="5866257070973731571">新增電話號碼</translation>
@@ -1308,6 +1343,7 @@
<translation id="5913377024445952699">已暫åœæ“·å–螢幕畫é¢</translation>
<translation id="59174027418879706">已啟用</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{ç›®å‰ä½¿ç”¨ 1 個 Cookie}other{ç›®å‰ä½¿ç”¨ # 個 Cookie}}</translation>
<translation id="5921185718311485855">é–‹å•Ÿ</translation>
<translation id="5921639886840618607">è¦å°‡é€™å¼µå¡ç‰‡å„²å­˜åˆ° Google 帳戶嗎?</translation>
<translation id="5922853866070715753">å³å°‡å®Œæˆ</translation>
@@ -1327,6 +1363,7 @@
<translation id="5989320800837274978">沒有指定固定的 Proxy 伺æœå™¨å’Œ .pac 指令碼網å€ã€‚</translation>
<translation id="5992691462791905444">大å°å½ˆç°§æ‘º</translation>
<translation id="6000758707621254961">有 <ph name="RESULT_COUNT" /> 個與「<ph name="SEARCH_TEXT" />ã€ç›¸ç¬¦çš„æœå°‹çµæžœ</translation>
+<translation id="6006484371116297560">傳統版</translation>
<translation id="6008122969617370890">N 到 1 çš„é †åº</translation>
<translation id="6008256403891681546">JCB</translation>
<translation id="6014801569448771146">請檢查你的密碼</translation>
@@ -1348,6 +1385,7 @@
<translation id="6045164183059402045">拼版範本</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="6049004884579590341">æŒ‰ä½ |<ph name="ACCELERATOR" />| å³å¯çµæŸå…¨èž¢å¹•æ¨¡å¼</translation>
<translation id="6049488691372270142">é é¢å‚³é€</translation>
<translation id="6051221802930200923">ç›®å‰ç„¡æ³•é€ è¨ª <ph name="SITE" />,因為這個網站使用憑證鎖定功能。網路錯誤和攻擊行為通常是暫時性的,因此這個網é å¯èƒ½ç¨å¾Œå°±æœƒæ¢å¾©æ­£å¸¸ç‹€æ…‹ã€‚</translation>
<translation id="6051898664905071243">é æ•¸ï¼š</translation>
@@ -1364,6 +1402,7 @@
<translation id="610911394827799129">ä½ çš„ Google 帳戶ä»å¯èƒ½ä¿ç•™äº†å…¶ä»–é¡žåž‹çš„ç€è¦½è¨˜éŒ„ (å¯å‰å¾€ <ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" /> 查詢)。</translation>
<translation id="6116338172782435947">讀å–已複製到剪貼簿的文字和圖片</translation>
<translation id="6120179357481664955">還記得你的 UPI ID 嗎?</translation>
+<translation id="6123290840358279103">查看虛擬å¡ç‰‡</translation>
<translation id="6124432979022149706">Chrome Enterprise 連接器</translation>
<translation id="6146055958333702838">檢查您的網路線是å¦ç©©å›ºé€£æŽ¥ã€‚é‡æ–°å•Ÿå‹•æ‚¨å¯èƒ½æ­£åœ¨ä½¿ç”¨çš„任何路由器ã€
數據機或其他網路è£ç½®ã€‚</translation>
@@ -1400,6 +1439,7 @@
<translation id="6289939620939689042">é é¢é¡è‰²</translation>
<translation id="6290238015253830360">這裡會顯示推薦給你的文章</translation>
<translation id="6293309776179964942">JIS B5</translation>
+<translation id="6295618774959045776">CVC:</translation>
<translation id="6302269476990306341">正在åœæ­¢ Chrome 版 Google 助ç†</translation>
<translation id="6305205051461490394">無法連上 <ph name="URL" />。</translation>
<translation id="6312113039770857350">網é ç„¡æ³•ä½¿ç”¨</translation>
@@ -1425,6 +1465,7 @@
<translation id="6390200185239044127">å°æŠ˜å¾Œçš„彈簧二摺</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">系統管ç†å“¡æ”¿ç­–ç¦æ­¢å°‡ <ph name="ORIGIN_NAME" /> 的內容貼到這個ä½ç½®</translation>
+<translation id="6398765197997659313">退出全螢幕模å¼</translation>
<translation id="6401136357288658127">這項政策目å‰å·²æ·˜æ±°ï¼Œè«‹æ”¹ç”¨ <ph name="NEW_POLICY" /> 政策。</translation>
<translation id="6404511346730675251">編輯書籤</translation>
<translation id="6406765186087300643">C0 (ä¿¡å°)</translation>
@@ -1437,7 +1478,6 @@
<translation id="6428450836711225518">驗證你的電話號碼</translation>
<translation id="6433490469411711332">編輯è¯çµ¡è³‡è¨Š</translation>
<translation id="6433595998831338502"><ph name="HOST_NAME" /> 拒絕連線。</translation>
-<translation id="6434309073475700221">æ¨æ£„</translation>
<translation id="6440503408713884761">已忽略</translation>
<translation id="6443406338865242315">你安è£çš„擴充功能和外掛程å¼</translation>
<translation id="6446163441502663861">Kahu (ä¿¡å°)</translation>
@@ -1480,6 +1520,7 @@
<translation id="6624427990725312378">è¯çµ¡è³‡è¨Š</translation>
<translation id="6626291197371920147">新增有效的信用å¡è™Ÿç¢¼</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> æœå°‹</translation>
+<translation id="6630043285902923878">正在尋找 USB è£ç½®â€¦</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="663260587451432563">JIS B4</translation>
<translation id="6643016212128521049">清除</translation>
@@ -1495,6 +1536,7 @@
<translation id="6671697161687535275">è¦å¾ž Chromium 中移除表單填寫建議嗎?</translation>
<translation id="6685834062052613830">請登出並完æˆè¨­å®šç¨‹åº</translation>
<translation id="6687335167692595844">è¦æ±‚的字型大å°</translation>
+<translation id="6688743156324860098">更新…</translation>
<translation id="6689249931105087298">與黑點壓縮相å°</translation>
<translation id="6689271823431384964">你已登入帳戶,因此 Chrome è©¢å•ä½ æ˜¯å¦è¦å°‡å¡ç‰‡å„²å­˜è‡³ Google 帳戶。你å¯ä»¥åœ¨è¨­å®šä¸­è®Šæ›´é€™é …行為。æŒå¡äººå§“å來自你的帳戶。</translation>
<translation id="6698381487523150993">建立於:</translation>
@@ -1510,6 +1552,7 @@
<translation id="6744009308914054259">等待連線的åŒæ™‚,你å¯ä»¥å‰å¾€ã€Œä¸‹è¼‰ã€é é¢é–±è®€é›¢ç·šæ–‡ç« ã€‚</translation>
<translation id="6753269504797312559">政策值</translation>
<translation id="6757797048963528358">您的è£ç½®å·²é€²å…¥ç¡çœ æ¨¡å¼ã€‚</translation>
+<translation id="6767985426384634228">è¦æ›´æ–°åœ°å€å—Žï¼Ÿ</translation>
<translation id="6768213884286397650">Hagaki (明信片)</translation>
<translation id="6775759552199460396">JIS B2</translation>
<translation id="67862343314499040">紫羅蘭色</translation>
@@ -1532,6 +1575,7 @@
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">Chrome 已簡化這個é é¢ï¼Œè®“內容更易於閱讀。Chrome é€éŽä¸å®‰å…¨çš„連線擷å–原始é é¢ã€‚</translation>
<translation id="6891596781022320156">系統ä¸æ”¯æ´é€™é …政策的層級。</translation>
+<translation id="6895143722905299846">虛擬å¡è™Ÿï¼š</translation>
<translation id="6895330447102777224">您的信用å¡å·²é€šéŽé©—è­‰</translation>
<translation id="6897140037006041989">使用者代ç†ç¨‹å¼</translation>
<translation id="6898699227549475383">組織 (O)</translation>
@@ -1567,10 +1611,10 @@
<translation id="7004583254764674281">使用 Windows Hello 加快å¡ç‰‡é©—證速度</translation>
<translation id="7006930604109697472">ä»è¦å‚³é€</translation>
<translation id="7012363358306927923">中國銀è¯</translation>
-<translation id="7012404007611495949">調整設定大å°</translation>
<translation id="7014741021609395734">縮放比例</translation>
<translation id="7016992613359344582">這些費用å¯èƒ½åªæ”¶å–一次,也å¯èƒ½å±¬æ–¼é€±æœŸæ€§è²»ç”¨ï¼Œè€Œä¸”ä½ ä¸ä¸€å®šæœƒæ³¨æ„到自己需è¦ä»˜è²»ã€‚</translation>
<translation id="7029809446516969842">密碼</translation>
+<translation id="7030436163253143341">憑證無效</translation>
<translation id="7031646650991750659">你安è£çš„ Google Play 應用程å¼</translation>
<translation id="7050187094878475250">您嘗試連線至 <ph name="DOMAIN" />,但伺æœå™¨æ供的憑證有效期é™å¤ªé•·ï¼Œå› æ­¤é›£ä»¥ä¿¡ä»»ã€‚</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{ç›®å‰ç„¡æ³•å„²å­˜é€™å¼µå¡ç‰‡}other{ç›®å‰ç„¡æ³•å„²å­˜é€™äº›å¡ç‰‡}}</translation>
@@ -1640,12 +1684,14 @@
<translation id="7300012071106347854">鈷è—色</translation>
<translation id="7302712225291570345">「<ph name="TEXT" />ã€</translation>
<translation id="7304030187361489308">高</translation>
+<translation id="7305756307268530424">啟用慢速模å¼</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">連線說明</translation>
<translation id="7323804146520582233">éš±è—「<ph name="SECTION" />ã€éƒ¨åˆ†</translation>
<translation id="733354035281974745">è£ç½®æœ¬æ©Ÿå¸³æˆ¶è¦†å¯«</translation>
<translation id="7333654844024768166">你剛æ‰åœ¨è©é¨™ç¶²ç«™ä¸Šè¼¸å…¥äº†å¯†ç¢¼ã€‚Chromium 建議你立å³å‰å¾€ <ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" />ã€<ph name="WEBSITE_3" />,以åŠä¹Ÿä½¿ç”¨é€™å€‹å¯†ç¢¼çš„其他網站變更密碼。</translation>
<translation id="7334320624316649418">é‡åšé‡æ–°æŽ’åº(&amp;R)</translation>
+<translation id="7337248890521463931">顯示更多行</translation>
<translation id="7337706099755338005">ä½ çš„å¹³å°ç„¡æ³•ä½¿ç”¨å¯¦é©—性功能。</translation>
<translation id="733923710415886693">伺æœå™¨æ†‘證未ä¾æ†‘è­‰é€æ˜ŽåŒ–政策公開。</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1653,6 +1699,7 @@
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">命令列</translation>
<translation id="7359588939039777303">å·²å°éŽ–廣告。</translation>
+<translation id="7363096869660964304">ä¸éŽï¼Œé€™ä¸¦ä¸ä»£è¡¨ä½ çš„ç€è¦½è¨˜éŒ„會完全ä¸ç•™ç—•è·¡ã€‚你使用無痕模å¼æ™‚,你的雇主ã€ç¶²éš›ç¶²è·¯æœå‹™ä¾›æ‡‰å•†å’Œä½ æ‰€é€ è¨ªçš„網站ä»ç„¶å¯ä»¥è¿½è¹¤ä½ çš„ç€è¦½è¨˜éŒ„。</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />;按下 Tab éµå†æŒ‰ä¸‹ Enter éµå³å¯åœ¨ Chrome 設定中新增åŠç®¡ç†åœ°å€</translation>
<translation id="7365849542400970216">知é“ä½ çš„è£ç½®ä½¿ç”¨ç‹€æ…‹å—Žï¼Ÿ</translation>
<translation id="7372973238305370288">æœå°‹çµæžœ</translation>
@@ -1663,7 +1710,9 @@
<translation id="7378594059915113390">媒體控制項</translation>
<translation id="7378627244592794276">ä¸éœ€è¦</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">ä¸é©ç”¨</translation>
<translation id="7390545607259442187">驗證信用å¡</translation>
+<translation id="7392089738299859607">更新地å€</translation>
<translation id="7399802613464275309">安全檢查</translation>
<translation id="7400418766976504921">網å€</translation>
<translation id="7403591733719184120">ä½ çš„ <ph name="DEVICE_NAME" /> å—到管ç†</translation>
@@ -1678,6 +1727,7 @@
&lt;li&gt;å‰å¾€ &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Chrome 說明中心&lt;/a&gt;瞭解如何將該軟體從電腦上永久移除
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Wide-Format</translation>
+<translation id="7410471291937727359">å¯æ„›</translation>
<translation id="7416351320495623771">管ç†å¯†ç¢¼â€¦</translation>
<translation id="7419106976560586862">設定檔路徑</translation>
<translation id="7437289804838430631">新增è¯çµ¡è³‡è¨Š</translation>
@@ -1693,7 +1743,7 @@
<translation id="7481312909269577407">å¾€å‰</translation>
<translation id="7485870689360869515">找ä¸åˆ°ä»»ä½•è³‡æ–™ã€‚</translation>
<translation id="7495528107193238112">這項內容已é­åˆ°å°éŽ–,請è¯çµ¡ç¶²ç«™æ“有者以修正å•é¡Œã€‚</translation>
-<translation id="7498234416455752244">繼續編輯</translation>
+<translation id="7498193950643227031">調整大å°å¯èƒ½å°Žè‡´æ‡‰ç”¨ç¨‹å¼ç„¡æ³•æ­£å¸¸é‹ä½œã€‚ä½ å¯ä»¥åœ¨<ph name="SETTINGS" />中é‡å°èª¿æ•´æ‡‰ç”¨ç¨‹å¼å¤§å°çš„功能設é™ã€‚</translation>
<translation id="7503664977220660814">你剛æ‰åœ¨è©é¨™ç¶²ç«™ä¸Šè¼¸å…¥äº†å¯†ç¢¼ã€‚Chromium 建議你立å³æª¢æŸ¥ç‚ºä»¥ä¸‹ç¶²ç«™å„²å­˜çš„密碼:<ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" />,以åŠä½¿ç”¨é€™çµ„密碼的其他網站。</translation>
<translation id="7508255263130623398">傳回的政策è£ç½® ID 沒有任何內容,或是與目å‰çš„è£ç½® ID ä¸ç¬¦</translation>
<translation id="7508870219247277067">酪梨綠</translation>
@@ -1713,6 +1763,7 @@
<translation id="7548892272833184391">修正連線錯誤</translation>
<translation id="7549584377607005141">這個網é éœ€è¦ä½¿ç”¨ä½ å…ˆå‰è¼¸å…¥çš„資料æ‰èƒ½æ­£ç¢ºé¡¯ç¤ºã€‚ä½ å¯ä»¥é‡æ–°å‚³é€é€™äº›è³‡æ–™ï¼Œä¸éŽé€™éº¼åšæœƒé‡è¤‡åŸ·è¡Œé€™å€‹ç¶²é å…ˆå‰åŸ·è¡ŒéŽçš„任何動作。</translation>
<translation id="7550637293666041147">ä½ çš„è£ç½®ä½¿ç”¨è€…å稱和 Chrome 使用者å稱</translation>
+<translation id="755279583747225797">試用功能已啟用</translation>
<translation id="7552846755917812628">嘗試按照下列æ示æ“作:</translation>
<translation id="7554475479213504905">ä»è¦é‡æ–°è¼‰å…¥åŠé¡¯ç¤ºå…§å®¹</translation>
<translation id="7554791636758816595">新分é </translation>
@@ -1731,7 +1782,6 @@
<translation id="7610193165460212391">值超出 <ph name="VALUE" /> 的範åœã€‚</translation>
<translation id="7613889955535752492">有效期é™ï¼š<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />,按下 Tab éµå†æŒ‰ä¸‹ Enter éµå³å¯åœ¨ Chrome 設定中查看和管ç†å¯†ç¢¼</translation>
-<translation id="7615602087246926389">你已經使用其他版本的「Google 帳戶ã€å¯†ç¢¼å°è³‡æ–™é€²è¡ŒåŠ å¯†ï¼Œè«‹åœ¨ä¸‹æ–¹è¼¸å…¥å¯†ç¢¼ã€‚</translation>
<translation id="7616645509853975347">系統管ç†å“¡å·²ç‚ºä½ çš„ç€è¦½å™¨å•Ÿç”¨ Chrome Enterprise 連接器。這些連接器å¯ä»¥å­˜å–你的部分資料。</translation>
<translation id="7619838219691048931">çµæŸå·¥ä½œè¡¨</translation>
<translation id="762844065391966283">一次一個物件</translation>
@@ -1796,13 +1846,12 @@
<translation id="782886543891417279">ç›®å‰ä½¿ç”¨çš„ Wi-Fi 網路 (<ph name="WIFI_NAME" />) å¯èƒ½æœƒè¦æ±‚您造訪登入網é ã€‚</translation>
<translation id="7836231406687464395">Postfix (ä¿¡å°)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{ç„¡}=1{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="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">é–‹å•Ÿé—œè¯é¡žåž‹çš„檔案。</translation>
<translation id="7862185352068345852">è¦é›¢é–‹ç¶²ç«™å—Žï¼Ÿ</translation>
<translation id="7865448901209910068">最佳速度</translation>
<translation id="7874263914261512992">你剛æ‰åœ¨è©é¨™ç¶²ç«™ä¸Šè¼¸å…¥äº†å¯†ç¢¼ã€‚Chrome 建議你立å³æª¢æŸ¥ç‚ºä»¥ä¸‹ç¶²ç«™å„²å­˜çš„密碼:<ph name="WEBSITE_1" />ã€<ph name="WEBSITE_2" />,以åŠä½¿ç”¨é€™çµ„密碼的其他網站。</translation>
<translation id="7878562273885520351">你的密碼å¯èƒ½å·²ç¶“外洩</translation>
+<translation id="7880146494886811634">儲存地å€</translation>
<translation id="7882421473871500483">棕色</translation>
<translation id="7887683347370398519">請檢查您的信用å¡é©—證碼,然後å†è©¦ä¸€æ¬¡</translation>
<translation id="7887885240995164102">進入å­æ¯ç•«é¢</translation>
@@ -1810,6 +1859,7 @@
<translation id="7894280532028510793">如果拼字正確,<ph name="BEGIN_LINK" />請嘗試執行網路診斷<ph name="END_LINK" />。</translation>
<translation id="7904208859782148177">C3 (ä¿¡å°)</translation>
<translation id="7931318309563332511">ä¸æ˜Ž</translation>
+<translation id="793209273132572360">è¦æ›´æ–°åœ°å€å—Žï¼Ÿ</translation>
<translation id="7932579305932748336">塗布</translation>
<translation id="79338296614623784">請輸入有效的電話號碼</translation>
<translation id="7934052535022478634">付款完æˆ</translation>
@@ -1880,6 +1930,7 @@
<translation id="8175796834047840627">你已登入帳戶,因此 Chrome è©¢å•ä½ æ˜¯å¦è¦å°‡å¡ç‰‡å„²å­˜è‡³ä½ çš„ Google 帳戶。你å¯ä»¥åœ¨è¨­å®šä¸­è®Šæ›´é€™é …行為。</translation>
<translation id="8176440868214972690">這部è£ç½®çš„管ç†å“¡å·²å°‡ä¸€äº›è³‡è¨Š (例如設定或政策) 傳é€åˆ°ä¸‹åˆ—網站。</translation>
<translation id="8184538546369750125">使用全域é è¨­å€¼ (å…許)</translation>
+<translation id="8193086767630290324">é‡å°æ¨™è¨˜ç‚ºæ©Ÿå¯†çš„資料所採å–的行動</translation>
<translation id="8194797478851900357">復原移動(&amp;U)</translation>
<translation id="8201077131113104583">擴充功能 (ID:「<ph name="EXTENSION_ID" />ã€) 的更新網å€ç„¡æ•ˆã€‚</translation>
<translation id="8202097416529803614">訂單摘è¦</translation>
@@ -1902,6 +1953,7 @@
<translation id="8249296373107784235">å–消</translation>
<translation id="8249320324621329438">上次擷å–時間:</translation>
<translation id="8253091569723639551">è«‹æ供帳單地å€</translation>
+<translation id="8257387598443225809">這是專為行動è£ç½®è¨­è¨ˆçš„應用程å¼</translation>
<translation id="825929999321470778">顯示所有已儲存的密碼</translation>
<translation id="8261506727792406068">刪除</translation>
<translation id="8262952874573525464">é‚Šç·£è£è¨‚ (底部)</translation>
@@ -2025,7 +2077,6 @@
<translation id="8719528812645237045">多孔 (頂端)</translation>
<translation id="8725066075913043281">å†è©¦ä¸€æ¬¡</translation>
<translation id="8726549941689275341">é é¢å¤§å°ï¼š</translation>
-<translation id="8728672262656704056">你已進入無痕模å¼</translation>
<translation id="8730621377337864115">完æˆ</translation>
<translation id="8731544501227493793">「管ç†å¯†ç¢¼ã€æŒ‰éˆ•ï¼ŒæŒ‰ä¸‹ Enter éµå³å¯åœ¨ Chrome 設定中查看和管ç†å¯†ç¢¼</translation>
<translation id="8734529307927223492">ä½ çš„ <ph name="DEVICE_TYPE" /> 是由 <ph name="MANAGER" /> 管ç†</translation>
@@ -2102,6 +2153,7 @@
<translation id="9020542370529661692">此網é å…§å®¹å·²ç¿»è­¯æˆ<ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(無效)</translation>
+<translation id="9030265603405983977">單色</translation>
<translation id="9035022520814077154">安全性錯誤</translation>
<translation id="9038649477754266430">使用é æ¸¬æŸ¥è©¢å­—串æœå‹™ï¼Œè®“系統更快載入網é </translation>
<translation id="9039213469156557790">此外,這個網é å«æœ‰å…¶ä»–ä¸å®‰å…¨çš„資æºã€‚其他人å¯èƒ½æœƒåœ¨è³‡æºå‚³è¼¸æœŸé–“檢視這些資æºï¼Œæ”»æ“Šè€…也å¯èƒ½æœƒä¿®æ”¹é€™äº›è³‡æºï¼Œé€²è€Œè®Šæ›´ç¶²é è¡Œç‚ºã€‚</translation>
@@ -2125,6 +2177,7 @@
<translation id="91108059142052966">當畫é¢ä¸Šå‡ºç¾æ©Ÿå¯†å…§å®¹ï¼Œç³»çµ±ç®¡ç†å“¡æ”¿ç­–就會åœç”¨èˆ‡ã€Œ<ph name="APPLICATION_TITLE" />ã€åˆ†äº«èž¢å¹•ç•«é¢çš„功能</translation>
<translation id="9114524666733003316">正在驗證信用å¡...</translation>
<translation id="9114581008513152754">這個ç€è¦½å™¨æœªå—到任何公å¸æˆ–其他機構管ç†ã€‚這部è£ç½®ä¸Šçš„活動å¯é€éŽ Chrome 以外的æœå‹™ç®¡ç†ã€‚<ph name="BEGIN_LINK" />瞭解詳情<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">æ–°é®®</translation>
<translation id="9119042192571987207">已上傳</translation>
<translation id="9128016270925453879">已載入政策</translation>
<translation id="9128870381267983090">連線至網路</translation>
@@ -2143,6 +2196,7 @@
<translation id="9170848237812810038">å–消(&amp;U)</translation>
<translation id="9171296965991013597">è¦é›¢é–‹æ‡‰ç”¨ç¨‹å¼å—Žï¼Ÿ</translation>
<translation id="9173282814238175921">單一文件/新工作表</translation>
+<translation id="9173995187295789444">正在掃æè—牙è£ç½®â€¦</translation>
<translation id="917450738466192189">伺æœå™¨æ†‘證無效。</translation>
<translation id="9174917557437862841">分é åˆ‡æ›æŒ‰éˆ•ï¼ŒæŒ‰ä¸‹ Enter éµå³å¯åˆ‡æ›åˆ°é€™å€‹åˆ†é </translation>
<translation id="9179703756951298733">在 Chrome 設定中管ç†ä»˜æ¬¾å’Œä¿¡ç”¨å¡è³‡è¨Š</translation>
diff --git a/chromium/components/strings/components_strings_zu.xtb b/chromium/components/strings/components_strings_zu.xtb
index 3c12c04f449..2638a76be09 100644
--- a/chromium/components/strings/components_strings_zu.xtb
+++ b/chromium/components/strings/components_strings_zu.xtb
@@ -39,6 +39,7 @@
<translation id="1107591249535594099">Uma ihloliwe, i-Chrome izogcina ikhophi yekhadi lakho kule divayisi ukuze kugcwaliswe ifomu ngokushesha.</translation>
<translation id="1110994991967754504">Khetha imvume ye-<ph name="PERMISSION_NAME" /></translation>
<translation id="1113869188872983271">&amp;Hlehlisa ukuhlela kabusha</translation>
+<translation id="1123753900084781868">Okushuthwe Bukhoma akutholakali njengamanje</translation>
<translation id="1125573121925420732">Izexwayiso kumele zifane ngenkathi amawebhusayithi abuyekeza ukuvikelwa kwawo. Lokhu kumele kuthuthuke maduze.</translation>
<translation id="112840717907525620">Inqolobale yenqubomgomo ILUNGILE</translation>
<translation id="1130564665089811311">Inkinobho yokuhumusha ikhasi, cindezela u-Enter ukuze uhumushe leli khasi nge-Google Translate</translation>
@@ -74,6 +75,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="1240347957665416060">Igama ledivayisi yakho</translation>
<translation id="124116460088058876">Izilimi eziningi</translation>
<translation id="1243027604378859286">Umbhali:</translation>
+<translation id="1246424317317450637">Okugqamile</translation>
<translation id="1250759482327835220">Ukuze ukhokhe ngokushesha ngokuzayo, londoloza ikhadi lakho, igama, nekheli lokukhokha ku-akhawunti yakho ye-Google.</translation>
<translation id="1253921432148366685"><ph name="TYPE_1" />, <ph name="TYPE_2" /> (kuvumelanisiwe)</translation>
<translation id="1256368399071562588">&lt;p&gt;Uma uzama ukuvakashela iwebhusayithi futhi ingavuli, qala ngokuzama ukulungisa iphutha ngalezi zinyathelo zokuxazulula inkinga:&lt;/p&gt;
@@ -156,6 +158,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="1476595624592550506">Shintsha iphasiwedi yakho</translation>
<translation id="1484290072879560759">Khetha ikheli lokuthumela</translation>
<translation id="1492194039220927094">Ukuphusha izinqubomgomo:</translation>
+<translation id="1495677929897281669">Emuva kuthebhu</translation>
<translation id="1501859676467574491">Bonisa amakhadi kusuka ku-akhawunti yakho ye-Google</translation>
<translation id="1507202001669085618">&lt;p&gt;Uzobona leli phutha uma uzama ukusebenzisa iphothali ye-Wi-Fi lapho kufanele ungene khona ngemvume ngaphambi okuthi ufike ku-inthanethi.&lt;/p&gt;
&lt;p&gt;Ukuze ulungise iphutha, chofoza okuthi &lt;strong&gt;Xhuma&lt;/strong&gt; ekhasini ozama ukulivula.&lt;/p&gt;</translation>
@@ -171,6 +174,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="1532118530259321453">Leli khasi lithi</translation>
<translation id="153384715582417236">Yikho konke lokho okwamanje</translation>
<translation id="1536390784834419204">Humusha ikhasi</translation>
+<translation id="1539840569003678498">Umbiko uthunyelwe:</translation>
<translation id="154408704832528245">Khetha ikheli lokulethwa</translation>
<translation id="1549470594296187301">I-JavaScript kumele inikwe amandla ukuze isebenzise lesi sici.</translation>
<translation id="155039086686388498">Engineering-D</translation>
@@ -213,16 +217,19 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="1682696192498422849">Umkhawulo omfushane kuqala</translation>
<translation id="168693727862418163">Ukubaluleka kwale nqubomgomo kuhlulekile ukuqinisekisa ngokumelene ne-schema sayo futhi ngeke inakwe.</translation>
<translation id="168841957122794586">Isitifiketi seseva siqukethe ukhiye we-cryptographic obuthaka.</translation>
+<translation id="1696290444144917273">Buka imininingwane yekhadi elibonakalayo</translation>
<translation id="1697532407822776718">Senisethiwe nonke!</translation>
<translation id="1703835215927279855">Incwadi</translation>
<translation id="1706954506755087368">{1,plural, =1{Le seva ayikwazanga ukufakazela ukuthi iyi-<ph name="DOMAIN" />; isitifiketi sayo sokuvikela singahle sivele kusukela kusasa. Lokhu kungabangelwa ukungalungisi kahle noma umhlaseli ohlangabeza ukuxhumeka kwakho.}one{Le seva ayikwazanga ukufakazela ukuthi iyi-<ph name="DOMAIN" />; isitifiketi sayo sokuvikela singahle sivele kusuka ezinsukwini ezingu-# ngokuzayo. Lokhu kungabangelwa ukungalungisi kahle noma umhlaseli ohlangabeza ukuxhumeka kwakho.}other{Le seva ayikwazanga ukufakazela ukuthi iyi-<ph name="DOMAIN" />; isitifiketi sayo sokuvikela singahle sivele kusuka ezinsukwini ezingu-# ngokuzayo. Lokhu kungabangelwa ukungalungisi kahle noma umhlaseli ohlangabeza ukuxhumeka kwakho.}}</translation>
<translation id="1710259589646384581">I-OS</translation>
+<translation id="1711234383449478798">Kuzitshiwe ngoba i-<ph name="POLICY_NAME" /> ayisethwanga ku-<ph name="VALUE" />.</translation>
<translation id="1712552549805331520">I-<ph name="URL" /> ifuna ukugcina unaphakade idatha kukhompuyutha yakho yasendaweni</translation>
<translation id="1713628304598226412">Ithileyi elingu-2</translation>
<translation id="1715874602234207">F</translation>
<translation id="1717494416764505390">Ibhokisi lemeyili elingu-3</translation>
<translation id="1718029547804390981">Idokhumenti likhulu kakhulu ukuthi lingachasiswa</translation>
<translation id="1721424275792716183">* Inkambu iyadingeka</translation>
+<translation id="1727613060316725209">Isitifiketi asivumelekile</translation>
<translation id="1727741090716970331">Engeza inombolo yekhadi evumelekile</translation>
<translation id="1728677426644403582">Ubuka umthombo wekhasi lewebhu</translation>
<translation id="173080396488393970">Lolu hlobo lwekhadi alusekelwe</translation>
@@ -246,7 +253,6 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
isicelo sakho se-<ph name="SITE" />. Izinqubomgomo zoqobo zingasetshenziswa
abasebenzisi besayithi ukulungisa ukuphepha nezinye izinto zesayithi.</translation>
<translation id="1778646502362731194">I-JIS B0</translation>
-<translation id="1783075131180517613">Sicela ubuyekeze umushwana wakho wokungena wokuvumelanisa.</translation>
<translation id="1787142507584202372">Amathebhu akho avulekile abonakala lapha</translation>
<translation id="1791429645902722292">I-Google Smart Lock</translation>
<translation id="1798447301915465742"><ph name="MULTIPLE_ACTIONS_FOCUSED_FRIENDLY_MATCH_TEXT" />, izenzo eziningi ziyatholakala, cindezela Ithebhu ukuzibona</translation>
@@ -279,6 +285,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="1919345977826869612">Izikhangiso</translation>
<translation id="1919367280705858090">Thola usizo ngomlayezo wephutha othize</translation>
<translation id="192020519938775529">{COUNT,plural, =0{Lutho}=1{1 isayithi}one{# amasayithi}other{# amasayithi}}</translation>
+<translation id="1924727005275031552">Kusha</translation>
<translation id="1945968466830820669">Ungalahlekelwa ukufinyelela ku-akhawunti yenhlangano yakho noma uzwe ukuntshontshwa kobunikazi. I-Chromium iphakamisa ukushintsha iphasiwedi yakho manje.</translation>
<translation id="1947454675006758438">Ukunamathisela phezulu kwesokudla</translation>
<translation id="1958218078413065209">Umphumela wakho ophambili ungu-<ph name="SCORE" />.</translation>
@@ -301,12 +308,14 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="2042213636306070719">Ithileyi elingu-7</translation>
<translation id="204357726431741734">Ngena ngemvume ukuze usebenzise amaphasiwedi alondolozwe ku-akhawunti yakho ye-Google</translation>
<translation id="2053111141626950936">Amakhasi angesi-<ph name="LANGUAGE" /> ngeke aze ahunyushwe.</translation>
+<translation id="2053373601901562871">{NUM_DAYS,plural, =0{Uma lokhu kulawula kuvuliwe futhi nesimo sisebenza, i-Chrome inquma ukuthi yiliphi iqembu elikhulu labantu, noma "iqoqo," umsebenzi wakho wokuphequlula wakamuva ofana kakhulu nalo. Abakhangisi bangakhetha izikhangiso zeqembu futhi umsebenzi wakho wokuphequlula ugcinwa uyimfihlo kudivayisi yakho. Iqembu lakho libuyekezwa nsuku zonke.}=1{Uma lokhu kulawula kuvuliwe futhi nesimo sisebenza, i-Chrome inquma ukuthi yiliphi iqembu elikhulu labantu, noma "iqoqo," umsebenzi wakho wokuphequlula wakamuva ofana kakhulu nalo. Abakhangisi bangakhetha izikhangiso zeqembu futhi umsebenzi wakho wokuphequlula ugcinwa uyimfihlo kudivayisi yakho. Iqembu lakho libuyekezwa nsuku zonke.}one{Uma lokhu kulawula kuvuliwe futhi nesimo sisebenza, i-Chrome inquma ukuthi yiliphi iqembu elikhulu labantu, noma "iqoqo," umsebenzi wakho wokuphequlula wakamuva ofana kakhulu nalo. Abakhangisi bangakhetha izikhangiso zeqembu futhi umsebenzi wakho wokuphequlula ugcinwa uyimfihlo kudivayisi yakho. Iqembu lakho libuyekezwa njalo ezinsukwini ezingu-{NUM_DAYS}.}other{Uma lokhu kulawula kuvuliwe futhi nesimo sisebenza, i-Chrome inquma ukuthi yiliphi iqembu elikhulu labantu, noma "iqoqo," umsebenzi wakho wokuphequlula wakamuva ofana kakhulu nalo. Abakhangisi bangakhetha izikhangiso zeqembu futhi umsebenzi wakho wokuphequlula ugcinwa uyimfihlo kudivayisi yakho. Iqembu lakho libuyekezwa njalo ezinsukwini ezingu-{NUM_DAYS}.}}</translation>
<translation id="2053553514270667976">Ikhodi ye-Zip</translation>
<translation id="2064691555167957331">{COUNT,plural, =1{1 isiphakamiso}one{# iziphakamiso}other{# iziphakamiso}}</translation>
<translation id="2071692954027939183">Izaziso zivinjelwe ngokuzenzakalela ngoba ngokuvamile awuzivumeli</translation>
<translation id="2079545284768500474">Hlehlisa</translation>
<translation id="20817612488360358">Izilungiselelo zesistimu yommeleli zisethelwe ukusetshenziswa kodwa ukulungiselelwa kommeleli okubekelwe obala kuphinde kucaciswe.</translation>
<translation id="2082238445998314030">Umphumela ongu-<ph name="RESULT_NUMBER" /> wokungu-<ph name="TOTAL_RESULTS" /></translation>
+<translation id="2085876078937250610">Londoloza…</translation>
<translation id="2088086323192747268">Inkinobho yokuphatha ukuvumelanisa, cindezela u-Enter ukuphatha ukuthi yiluphi ulwazi oluvumelanisa kumasethingi we-Chrome</translation>
<translation id="2091887806945687916">Umsindo</translation>
<translation id="2094505752054353250">Ukungafani kwesizinda</translation>
@@ -379,6 +388,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="2317259163369394535"><ph name="DOMAIN" /> idinga igama lomsebenzisi nephasiwedi.</translation>
<translation id="2330137317877982892"><ph name="CREDIT_CARD" />, iphelelwa isikhathi ngomhla ka-<ph name="EXPIRATION_DATE_ABBR" /></translation>
<translation id="2337852623177822836">Isethingi lilawulwa umlawuli wakho</translation>
+<translation id="2340263603246777781"><ph name="ORIGIN" /> ufuna ukubhangqa</translation>
<translation id="2344028582131185878">Ukulandwa okuzenzakalela</translation>
<translation id="2346319942568447007">Isithombe osikopishile</translation>
<translation id="2354001756790975382">Amanye amawebhusayithi</translation>
@@ -386,8 +396,10 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="2355395290879513365">Abahlaseli kungenzeka bakwazi ukubona izithombe ozibonayo kuleli sayithi baphinde bakukhohlise ngokuzilungisa.</translation>
<translation id="2356070529366658676">Buza</translation>
<translation id="2357481397660644965">Idivayisi yakho iphethwe yi-<ph name="DEVICE_MANAGER" /> futhi i-akhawunti yakho iphethwe yi-<ph name="ACCOUNT_MANAGER" />.</translation>
+<translation id="2359347814217202136">{NUM_DAYS,plural, =0{Ngaphansi kosuku}=1{Ngosuku}one{Ezinsukwini ezingu-{NUM_DAYS}}other{Ezinsukwini ezingu-{NUM_DAYS}}}</translation>
<translation id="2359629602545592467">Okuningi</translation>
<translation id="2359808026110333948">Qhubeka</translation>
+<translation id="2359961752320758691">Kusetshenziswa inombolo yakho yekhadi ebonakalayo.</translation>
<translation id="2367567093518048410">Ileveli</translation>
<translation id="2372464001869762664">Ngemuva kokuqinisekisa, imininingwane yekhadi lakho izokwabiwa naleli sayithi. Thola i-CVC kwimininingwane yakho ye-akhawunti ye-Alex.</translation>
<translation id="2380886658946992094">Ezomthetho</translation>
@@ -398,6 +410,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="239429038616798445">Le ndlela yokuthumela ayitholakali. Zama indlela ehlukile.</translation>
<translation id="2396249848217231973">&amp;Hlehlisa ukususa</translation>
<translation id="2410754574180102685">Kukahulumeni-Ezomthetho</translation>
+<translation id="2413155254802890957">Okudala</translation>
<translation id="2413528052993050574">Le seva ayikwazanga ukukhombisa ukuthi iyi-<ph name="DOMAIN" />; isitifiketi sayo sokuvikeleka kungenzeka sibuyisiwe. Lokhu kungahle kubangelwe ukulungisa okungalungile noma umhlaseli uzama ukufinyelela uxhumo lwakho.</translation>
<translation id="2414886740292270097">Mnyama</translation>
<translation id="2438874542388153331">Ukushaya kane kwesokudla</translation>
@@ -425,10 +438,10 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="2521385132275182522">Namathisela phansi kwesokudla</translation>
<translation id="2523886232349826891">Kulondolozwe kule divayisi kuphela</translation>
<translation id="2524461107774643265">Engeza ulwazi olungeziwe</translation>
-<translation id="2526590354069164005">Ideskithophu</translation>
<translation id="2535659140340599600">{COUNT,plural, =1{nokungu-1 ngaphezulu}one{nokungu-# ngaphezulu}other{nokungu-# ngaphezulu}}</translation>
<translation id="2536110899380797252">Engeza ikheli</translation>
<translation id="2539524384386349900">Thola</translation>
+<translation id="2541219929084442027">Amakhasi owabukayo kumathebhu we-incognito ngeke ahlale akhona kumlando wesiphequluli sakho, amakhukhi, noma umlando wokubuka ngemuva kokuthi uvale wonke amathebhu we-incognito. Noma yimaphi amafayela owadawunilodayo noma amabhukhimakhi owadalayo kuzogcinwa.</translation>
<translation id="2544644783021658368">Idokhumenti eyodwa</translation>
<translation id="254947805923345898">Inani lenqubomgomo alivumelekile.</translation>
<translation id="255002559098805027">I-<ph name="HOST_NAME" /> ithumele impendulo engavumelekile.</translation>
@@ -448,6 +461,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="2629325967560697240">Ukuze uthole ileveli yokuphepha ephakeme kakhulu ye-Chrome, <ph name="BEGIN_ENHANCED_PROTECTION_LINK" />vula ukuvikela okuthuthukisiwe<ph name="END_ENHANCED_PROTECTION_LINK" /></translation>
<translation id="2634124572758952069">Ikheli lasesizindeni se-inthanethi le-<ph name="HOST_NAME" /> alikwazanga ukutholwa.</translation>
<translation id="2639739919103226564">Isimo:</translation>
+<translation id="264810637653812429">Awekho amadivayisi asebenzisanayo atholakele.</translation>
<translation id="2649204054376361687"><ph name="CITY" />, <ph name="COUNTRY" /></translation>
<translation id="2649259151839507861"><ph name="CLEAR_BROWSING_DATA_FOCUSED_FRIENDLY_MATCH_TEXT" />, cindezela u-Tab bese u-Enter ukuze Usule umlando wakho wokuphequlula, amakhukhi, inqolobane, kanye nokuningi kumasethingi e-Chrome</translation>
<translation id="2650446666397867134">Ukufinyelela kufayela kuye kwanqatshelwa</translation>
@@ -494,6 +508,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="2799223571221894425">Qalisa kabusha</translation>
<translation id="2803306138276472711">Kamuva nje Ukuphequlula Okuphephile kwe-Google <ph name="BEGIN_LINK" />kuthole i-malware<ph name="END_LINK" /> ku-<ph name="SITE" />. Ngokujwayelekile amawebhusayithi aphephile ngezinye izikhathi afakwa i-malware.</translation>
<translation id="2807052079800581569">Indawo yesithombe engu-Y</translation>
+<translation id="2820957248982571256">Iyaskena...</translation>
<translation id="2824775600643448204">Ikheli nebha yosesho</translation>
<translation id="2826760142808435982">Ukuxhumeka kubetheliwe kwaphinde kwaqinisekiswa kusetshenziswa i-<ph name="CIPHER" /> futhi kusebenzisa i-<ph name="KX" /> njengendlela yokushintshanisa ukhiye.</translation>
<translation id="2835170189407361413">Sula ifomu</translation>
@@ -501,6 +516,8 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="2850739647070081192">Mema (Envelope)</translation>
<translation id="2856444702002559011">Abahlaseli bangazama ukutshontsha ulwazi lwakho kusuka ku-<ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> (isibonelo, amaphasiwedi, imilayezo, noma amakhadi esikweletu). <ph name="BEGIN_LEARN_MORE_LINK" />Funda kabanzi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="2859806420264540918">Leli sayithi libonisa izikhangiso ezingathandeki noma ezidukisayo.</translation>
+<translation id="287596039013813457">Ubungani</translation>
+<translation id="2876489322757410363">Ushiya imodi ye-incognito ukuze ukhokhe nge-app yangaphandle. Qhubeka?</translation>
<translation id="2878197950673342043">Ukugoqa iphosta</translation>
<translation id="2878424575911748999">A1</translation>
<translation id="2880660355386638022">Ukubekwa kwewindi</translation>
@@ -550,7 +567,6 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="3060227939791841287">C9 (Envelope)</translation>
<translation id="3060557858482803256"><ph name="RUN_CHROME_SAFETY_CHECK_FOCUSED_FRIENDLY_MATCH_TEXT" />, cindezela Ithebhu bese u-Enter ukuqalisa Ukuhlola ukuphepha kumasethingi we-Chrome</translation>
<translation id="3061707000357573562">Isevisi yepeshi</translation>
-<translation id="3064966200440839136">Ushiya imodi ye-incognito ukuze udlale ngohlelo lokusebenza lwangaphandle. Qhubeka?</translation>
<translation id="306573536155379004">Igeyimu iqalile.</translation>
<translation id="3080254622891793721">Umfanekiso</translation>
<translation id="3086579638707268289">Umsebenzi wakho kuwebhu uyangamelwa</translation>
@@ -573,7 +589,6 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="315504272643575312">I-akhawunti yakho iphethwe i-<ph name="MANAGER" />.</translation>
<translation id="3157931365184549694">Buyisela</translation>
<translation id="3162559335345991374">I-Wi-Fi oyisebenzisayo ingadinga ukuthi uvakashele ikhasi layo lokungena ngemvume.</translation>
-<translation id="3167968892399408617">Amakhasi owabukayo kumathebhu we-incognito ngeke ahlale akhona kumlando wesiphequluli sakho, amakhukhi, noma umlando wokubuka ngemuva uvale wonke amathebhu we-incognito. Noma yimaphi amafayela owalandayo noma amabhukhimakhi owadalayo azogcinwa.</translation>
<translation id="3169472444629675720">Zitholele</translation>
<translation id="3174168572213147020">Isiqhingi</translation>
<translation id="3176929007561373547">Hlola izilungiselelo zakho zommeleli noma uxhumane nomlawuli wakho wenethiwekhi ukuze uqiniseke ukuthi iseva elibamba iyasebenza. Uma ungakholwa ukuthi kumele usebenzise iseva elibamba:
@@ -597,10 +612,12 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="3229041911291329567">Ulwazi lwenguqulo olumayelana nedivayisi yakho nesiphequluli</translation>
<translation id="323107829343500871">Faka i-CVC ye-<ph name="CREDIT_CARD" /></translation>
<translation id="3234666976984236645">Njalo thola okuqukethwe okubalulekile kuleli sayithi</translation>
+<translation id="3249845759089040423">I-Groovy</translation>
<translation id="3252266817569339921">Isi-French</translation>
<translation id="3266793032086590337">Inani (liyaphambana)</translation>
<translation id="3268451620468152448">Vula amathebhu</translation>
<translation id="3270847123878663523">&amp;Hlehlisa ukuhlela kabusha</translation>
+<translation id="3271648667212143903"><ph name="ORIGIN" /> ufuna ukuxhuma</translation>
<translation id="3274521967729236597">Pa-Kai</translation>
<translation id="3282085321714087552">Inhlangano yakho, i-<ph name="ENROLLMENT_DOMAIN" />, ithumele ulwazi kumawebhusayithi alandelayo, njengamasethingi noma izinqumbomgomo.</translation>
<translation id="3282497668470633863">Engeza igama kukhadi</translation>
@@ -653,6 +670,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="3428151540071562330">Eyodwa noma ngaphezulu yama-URL wethempulethi leseva le-DnsOverHttpsTemplates alivumelekile futhi ngeke lisetshenziswe.</translation>
<translation id="3431636764301398940">Londoloza leli khadi kule divayisi</translation>
<translation id="3432601291244612633">Vala ikhasi</translation>
+<translation id="3435738964857648380">Ukuvikela</translation>
<translation id="3435896845095436175">Nika amandla</translation>
<translation id="3438829137925142401">Sebenzisa amaphasiwedi alondolozwe ku-Akhawunti yakho ye-Google</translation>
<translation id="3443726618221119081">Juuro-Ku-Kai</translation>
@@ -695,7 +713,10 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="3584299510153766161">Ukushaya kabili phansi</translation>
<translation id="3586931643579894722">Fihla imininingwana</translation>
<translation id="3587738293690942763">Okumaphakathi</translation>
+<translation id="3590643883886679995">Idatha yokungena ngemvume izolondolozwa kule divayisi ngemuva kokuphuma kumodi ye-Incognito.</translation>
+<translation id="359126217934908072">Inyanga/Unyaka:</translation>
<translation id="3592413004129370115">Italian (Envelope)</translation>
+<translation id="3595699422137460894">{NUM_DAYS,plural, =0{Ungasetha kabusha iqembu lakho nganoma yisiphi isikhathi. Kuthatha cishe usuku ukujoyina iqembu elisha.}=1{Ungasetha kabusha iqembu lakho nganoma yisiphi isikhathi. Kuthatha cishe usuku ukujoyina iqembu elisha.}one{Ungasetha kabusha iqembu lakho nganoma yisiphi isikhathi. Kuthatha izinsuku ezingu-{NUM_DAYS} ukujoyina iqembu elisha.}other{Ungasetha kabusha iqembu lakho nganoma yisiphi isikhathi. Kuthatha izinsuku ezingu-{NUM_DAYS} ukujoyina iqembu elisha.}}</translation>
<translation id="3600246354004376029"><ph name="TITLE" />, <ph name="DOMAIN" />, <ph name="TIME" /></translation>
<translation id="3603507503523709">Uhlelo lokusebenza luvinjwe ngumlawuli wakho</translation>
<translation id="3608932978122581043">Umumo wokuphakelayo</translation>
@@ -704,12 +725,12 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="3615877443314183785">Faka idethi evumelekile yokuphelelwa isikhathi</translation>
<translation id="36224234498066874">Sula idatha yokuphequlula...</translation>
<translation id="362276910939193118">Bonisa umlando ogcwele</translation>
-<translation id="3625635938337243871">Idatha yokungena ngemvume izolondolozwa kule divayisi ngemuva kokuphuma kumodi ye-incognito.</translation>
<translation id="3630155396527302611">Uma seluvele lifakwe kuhlu njengohlelo oluvunyelwe ukuze lufinyelele kunethiwekhi, zama ukulisusa kusukela kuhlu uphinde ulingeze futhi.</translation>
<translation id="3630699740441428070">Abalawuli bale divayisi balungiselele uxhumo lenethiwekhi yakho, olungabavumela ukuba babone ithrafikhi yenethiwekhi yakho, kuhlanganise nokuthi yimaphi amawebhusayithi owavakashelayo.</translation>
<translation id="3631244953324577188">I-biometrics</translation>
<translation id="3633738897356909127">Inkinoho yokubuyekekeza ye-Chrome, cindezela u-Enter ukuze ubuyekeze i-Chrome kusuka kumasethingi akho e-Chrome</translation>
<translation id="3634530185120165534">Ithileyi elingu-5</translation>
+<translation id="3637662659967048211">Londoloza ku-akhawunti ye-Google</translation>
<translation id="3640766068866876100">I-Index-4x6-Ext</translation>
<translation id="3642638418806704195">Uhlelo lokusebenza:</translation>
<translation id="3650584904733503804">Ukuqinisekiswa kuphumelele</translation>
@@ -750,6 +771,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="3781428340399460090">Okuphinki kakhulu</translation>
<translation id="3783418713923659662">I-Mastercard</translation>
<translation id="3784372983762739446">Amadivaysi e-Bluetooth</translation>
+<translation id="3787675388804467730">Inombolo yekhadi ebonakalayo</translation>
<translation id="3787705759683870569">Iphelelwa isikhathi ngomhla ka-<ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="3789155188480882154">Usayizi 16</translation>
<translation id="3789841737615482174">Faka</translation>
@@ -769,6 +791,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="3841184659773414994">Izibambi Zefayela</translation>
<translation id="385051799172605136">Emuva</translation>
<translation id="3858027520442213535">Buyekeza idethi nesikhathi</translation>
+<translation id="3881478300875776315">Bonisa imigqa embalwa</translation>
<translation id="3884278016824448484">Isikhombi sedivayisi esishayisanayo</translation>
<translation id="3885155851504623709">I-Parish</translation>
<translation id="388632593194507180">Ukwengamela kutholiwe</translation>
@@ -794,6 +817,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="397105322502079400">Iyabala...</translation>
<translation id="3973234410852337861">I-<ph name="HOST_NAME" /> ivinjiwe</translation>
<translation id="3973357910713125165">Qalisa inkinobho Yokuhlola ukuphepha ye-Chrome, cindezela u-Enter ukuqalisa Ukuhlola kokuphepha kumasethingi we-Chrome</translation>
+<translation id="3986705137476756801">Vala Okushuthwe Bukhoma okwamanje</translation>
<translation id="3987405730340719549">I-Chrome inqume ukuthi leli sayithi lingaba ukukhwabanisa noma libe umgunyathi.
Uma ukholwa ukuthi lokhu kuboniswa ngephutha sicela uvakashele ku-https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
@@ -890,13 +914,14 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="4275830172053184480">Qalisa kabusha idivayisi yakho</translation>
<translation id="4277028893293644418">Setha kabusha iphasiwedi</translation>
<translation id="428639260510061158">{NUM_CARDS,plural, =1{Leli khadi lilondolozwe ku-akhawunti yakho ye-Google}one{Lawa makhadi alondolozwe ku-akhawunti yakho ye-Google}other{Lawa makhadi alondolozwe ku-akhawunti yakho ye-Google}}</translation>
+<translation id="4287885627794386150">Kufanelwe ukuzanywa kodwa akusebenzi</translation>
<translation id="4297502707443874121">Isithonjana sekhasi le-<ph name="THUMBNAIL_PAGE" /></translation>
<translation id="42981349822642051">Nweba</translation>
<translation id="4300675098767811073">Ukushaya okuningi kwesokudla</translation>
<translation id="4302514097724775343">Thepha i-dino ukuze udlale</translation>
<translation id="4302965934281694568">Chou3 (Envelope)</translation>
<translation id="4305666528087210886">Ifayela lakho alikwazanga ukufinyelelwa</translation>
-<translation id="4305817255990598646">Shintsha</translation>
+<translation id="4306529830550717874">Londoloza ikheli?</translation>
<translation id="4312613361423056926">B2</translation>
<translation id="4312866146174492540">Vimba (ngokuzenzakalela)</translation>
<translation id="4314815835985389558">Phatha ukuvumelanisa</translation>
@@ -923,6 +948,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="4377125064752653719">Uzame ukufinyelela ku-<ph name="DOMAIN" />, kodwa isitifiketi esiphrezentwe yiseva sihoxisiwe ngokukhishwa kwaso. Lokhu kusho ukuthi izifakazelo zokuvikela eziphrezentwe yiseva akumele zithenjwe sanhlobo. Kungenzeka ukuthi uxhumana nesihlaseli.</translation>
<translation id="4378154925671717803">Ifoni</translation>
<translation id="4390472908992056574">Umphetho</translation>
+<translation id="4406883609789734330">Okushuthwe Bukhoma</translation>
<translation id="4406896451731180161">imiphumela yokusesha</translation>
<translation id="4408413947728134509">Amakhukhi <ph name="NUM_COOKIES" /></translation>
<translation id="4414290883293381923">Usanda kufaka iphasiwedi yakho kusayithi elikhohlisayo. I-Chrome incoma ukuya ku-<ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />, namanye amasayithi lapho usebenzisa khona le phasiwedi nokuyishintsha manje.</translation>
@@ -935,7 +961,6 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="4435702339979719576">Ikhadi lokuposa)</translation>
<translation id="443673843213245140">Ukusetshenziswa ummeleli kukhitshaziwe kodwa ukulungiselelwa okubekelwe obala kommeleli kucacisiwe.</translation>
<translation id="4464826014807964867">Amawebhusayithi anolwazi oluvela enhlanganweni yakho</translation>
-<translation id="4466881336512663640">Izinguquko zefomu zizolahleka. Ingabe uqinisekile ukuthi ufuna ukuqhubeka?</translation>
<translation id="4476953670630786061">Leli fomu alivikelekile. Ukugcwalisa okuzenzakalelayo kuvaliwe.</translation>
<translation id="4477350412780666475">Ithrekhi elandelayo</translation>
<translation id="4482953324121162758">Leli sayithi ngeke lihunyushwe.</translation>
@@ -969,6 +994,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="4594403342090139922">&amp;Hlehlisa ukususa</translation>
<translation id="4597348597567598915">Usayizi 8</translation>
<translation id="4600854749408232102">C6/C5 (Envelope)</translation>
+<translation id="4606870351894164739">Kunomthelela</translation>
<translation id="4628948037717959914">Isithombe</translation>
<translation id="4631649115723685955">Imbuyiselo ixhunyanisiwe</translation>
<translation id="4636930964841734540">Ulwazi</translation>
@@ -988,6 +1014,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="4691835149146451662">Architecture-A (Envelope)</translation>
<translation id="4701488924964507374"><ph name="SENTENCE1" /> <ph name="SENTENCE2" /></translation>
<translation id="4702504834785592287">Uhlangothi</translation>
+<translation id="4702656508969495934">Okushuthwe Bukhoma kuyabonakala, sebenzisa isishintshi sewindi ukugxilisa</translation>
<translation id="4708268264240856090">Ukuxhumeka kwakho kuye kwaphazanyiswa</translation>
<translation id="4712404868219726379">I-Windows Hello</translation>
<translation id="4722547256916164131"><ph name="BEGIN_LINK" />Iqalisa ukuxilongwa kwenethiwekhi ye-Windows<ph name="END_LINK" /></translation>
@@ -1001,6 +1028,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="4738601419177586157"><ph name="TEXT" /> sesha isiphakamiso</translation>
<translation id="4742407542027196863">Phatha amaphasiwedi...</translation>
<translation id="4744603770635761495">Indlela esebenzisekayo</translation>
+<translation id="4749011317274908093">Usuye ku-incognito</translation>
<translation id="4750917950439032686">Ulwazi lakho (isibonelo, amaphasiwedi noma izinombolo zekhadi lesikweletu) luyimfihlo uma luthunyelwa kuleli sayithi.</translation>
<translation id="4756388243121344051">Umlando</translation>
<translation id="4758311279753947758">Engeza imininingwane yokuxhumana</translation>
@@ -1030,6 +1058,8 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="4813512666221746211">Iphutha lenethiwekhi</translation>
<translation id="4816492930507672669">Linganisa kukhasi</translation>
<translation id="4819347708020428563">Hlela izichasiselo kukubuka kokuzenzakalelayo?</translation>
+<translation id="4825507807291741242">Kunamandla</translation>
+<translation id="4838327282952368871">I-Dreamy</translation>
<translation id="484462545196658690">Okuzenzakalelayo</translation>
<translation id="4850886885716139402">Buka</translation>
<translation id="485316830061041779">Isi-German</translation>
@@ -1166,6 +1196,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="5314967030527622926">Umaka wencwajana</translation>
<translation id="5316812925700871227">Zungezisa ngokuphambana newashi</translation>
<translation id="5317780077021120954">Londoloza</translation>
+<translation id="5321288445143113935">Kukhulisiwe</translation>
<translation id="5323105697514565458"><ph name="FRIENDLY_MATCH_TEXT" />, <ph name="MATCH_POSITION" /> kokungu-<ph name="NUM_MATCHES" /></translation>
<translation id="5324080437450482387">Khetha ulwazi lokuxhumana</translation>
<translation id="5327248766486351172">Igama</translation>
@@ -1173,11 +1204,13 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="5332219387342487447">Indlela yokuhambisa</translation>
<translation id="5333022057423422993">I-Chrome ithole iphasiwedi osanda kuyisebenzisa ekwephuleni idatha. Ukuze uvikele ama-akhawunti akho, sincoma ukuthi uhlole amaphasiwedi akho alondoloziwe.</translation>
<translation id="5334013548165032829">Amalogi anemininingwane yesistimu</translation>
+<translation id="5334145288572353250">Londoloza Ikheli?</translation>
<translation id="5340250774223869109">Uhlelo lokusebenza luvinjiwe</translation>
<translation id="534295439873310000">Amadivayisi e-NFC</translation>
<translation id="5344579389779391559">Leli khasi lingazama ukukukhokhisa imali</translation>
<translation id="5355557959165512791">Awukwazi ukuvakashela i-<ph name="SITE" /> okwamanje ngoba isitifiketi sayo sibuyisiwe. Amaphutha enethiwekhi nokuhlasela kuvameukuba okwesikhashana, ngakho-ke leli khasi lizosebenza kamuva.</translation>
<translation id="536296301121032821">Yehlulekile ukugcina izilungiselelo zenqubomgomo</translation>
+<translation id="5363309033720083897">Imbobo ye-serial ivunyelwe ngumlawuli wakho</translation>
<translation id="5371425731340848620">Buyekeza ikhadi</translation>
<translation id="5377026284221673050">"Iwashi lakho lisemuva" noma "Iwashi lakho liphambili" noma "&lt;span class="error-code"&gt;NET::ERR_CERT_DATE_INVALID&lt;/span&gt;"</translation>
<translation id="5386426401304769735">Iketanga lesitifiketi laleli sayithi liqukethe isitifiketi esisayinwe kusetshenziswa i-SHA-1.</translation>
@@ -1186,6 +1219,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="5398772614898833570">Izikhangiso zivinjewe</translation>
<translation id="5400836586163650660">Okumpunga</translation>
<translation id="540969355065856584">Le seva ayikwazanga ukubonisa ukuthi iyi-<ph name="DOMAIN" />; isitifiketi sayo sokuphepha asivumelekile ngalesi sikhathi. Lokhu kungabangelwa ukungalungiseki kahle noma umhlaseli uhlasela uxhumo lakho.</translation>
+<translation id="541143247543991491">I-Cloud (isistimu ebanzi)</translation>
<translation id="541416427766103491">Isitaki esingu-4</translation>
<translation id="5421136146218899937">Sula idatha yokudlulisa amehlo...</translation>
<translation id="5426179911063097041">I-<ph name="SITE" /> ifuna ukukuthumelela izaziso</translation>
@@ -1199,6 +1233,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="5455374756549232013">Isitembu sesikhathi senqubomgomo embi</translation>
<translation id="5457113250005438886">Ayivumelekile</translation>
<translation id="5458150163479425638">{CONTACT,plural, =0{<ph name="CONTACT_PREVIEW" />}=1{<ph name="CONTACT_PREVIEW" /> nongu-<ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ngaphezulu}one{<ph name="CONTACT_PREVIEW" /> nongu-<ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ngaphezulu}other{<ph name="CONTACT_PREVIEW" /> nongu-<ph name="NUMBER_OF_ADDITIONAL_CONTACTS" /> ngaphezulu}}</translation>
+<translation id="5463625433003343978">Ithola amadivayisi...</translation>
<translation id="5469868506864199649">Isi-Italian</translation>
<translation id="5470861586879999274">&amp;Yenza futhi ukuhlela</translation>
<translation id="5478437291406423475">B6/C4 (Envelope)</translation>
@@ -1248,7 +1283,6 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="5624120631404540903">Phatha amaphasiwedi</translation>
<translation id="5629630648637658800">Yehlulekile ukulayisha izilungiselelo zenqubomgomo</translation>
<translation id="5631439013527180824">Ithokheni yokuphatha idivayisi engavumelekile</translation>
-<translation id="5632627355679805402">Idatha yakho ibethelwe <ph name="BEGIN_LINK" />ngephasiwedi yakho ye-Google<ph name="END_LINK" /> kusuka ngo-<ph name="TIME" />. Ifake ukuze uqale ukuvumelanisa.</translation>
<translation id="5633066919399395251">Abahlaseli okwamanje ku-<ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> bangazama ukufaka izinhlelo eziyingozi kukhompyutha yakho ezitshontsha noma ezisula ulwazi lwakho (isibonelo, izithombe, amaphasiwedi, imilayezo, namakhadi esikweletu). <ph name="BEGIN_LEARN_MORE_LINK" />Funda kabanzi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="563324245173044180">Okuqukethwe okulahlekisayo kuvinjelwe.</translation>
<translation id="5644090287519800334">I-Side 1 image X shift</translation>
@@ -1287,12 +1321,12 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="5785756445106461925">Ngokuqhubekayo, leli khasi lifaka ezinye izisetshenziswa ezingavikelekile. Lezi zisetshenziswa zingabukwa ngabanye ngenkathi ikwezokuthutha, futhi zingalungiswa yisihlaseli ukuze kuguqulwe ukubukeka kwekhasi.</translation>
<translation id="5786044859038896871">Ingabe ufuna ukugcwalisa ulwazi lwekhadi lakho?</translation>
<translation id="578633867165174378">I-Chrome ithole iphasiwedi osanda kuyisebenzisa ekwephuleni idatha. Sincoma ukuba ushintshe le phasiwedi manje.</translation>
-<translation id="5798290721819630480">Lahla izinguquko?</translation>
<translation id="5803412860119678065">Ingabe ufuna ukugcwalisa i-<ph name="CARD_DETAIL" /> yakho?</translation>
<translation id="5804241973901381774">Izimvume</translation>
<translation id="5804427196348435412">Sebenzisa amadivayisi e-NFC</translation>
<translation id="5810442152076338065">Ukuxhumeka kwakho ku-<ph name="DOMAIN" /> kubethelwe kusetshenziswa i-obsolete cipher suite.</translation>
<translation id="5813119285467412249">&amp;Yenza futhi ukungeza</translation>
+<translation id="5817918615728894473">Banqa</translation>
<translation id="5824687817967109979">{NUM_CARDS,plural, =1{Leli khadi lizokhokhiswa uma ukhokha, kodwa inombolo yalo yangempela ngeke yabiwe naleli sayithi. Ngokuphepha okungeziwe, i-CVC yesikhashana izokwenziwa.}one{Ikhadi olikhethayo lizokhokhiswa uma ukhokha, kodwa inombolo yalo yangempela ngeke yabiwe naleli sayithi. Ngokuphepha okungeziwe, i-CVC yesikhashana izokwenziwa.}other{Ikhadi olikhethayo lizokhokhiswa uma ukhokha, kodwa inombolo yalo yangempela ngeke yabiwe naleli sayithi. Ngokuphepha okungeziwe, i-CVC yesikhashana izokwenziwa.}}</translation>
<translation id="5826507051599432481">Igama eljwayelekile (CN)</translation>
<translation id="5838278095973806738">Akumele ufake noma iluphi ulwazi olubucayi kuleli sayithi (isibonelo, amaphasiwedi noma amakhadi esikweletu), ngoba lungantshontshwa abahlaseli.</translation>
@@ -1300,6 +1334,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="5855253129151731373">Igama lomethuleli laleli sayithi libonakala lifana ne-<ph name="LOOKALIKE_DOMAIN" />. Abahlaseli kwesinye isikhathi balingisa amasayithi ngokwenza ushintsho oluncane, oluboneka kanzima kugama lesizinda.
Uma ukholwa ukuthi lokhu kuboniswa ngephutha sicela uvakashele ku-https://bugs.chromium.org/p/chromium/issues/entry?template=Safety+Tips+Appeals.</translation>
+<translation id="5860033963881614850">Valiwe</translation>
<translation id="5862579898803147654">Isitaki esingu-8</translation>
<translation id="5863847714970149516">Ikhasi eliphambili lingazama ukushintsha imali yakho</translation>
<translation id="5866257070973731571">Engeza inombolo yefoni</translation>
@@ -1316,6 +1351,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="5913377024445952699">Ukuthatha isikrini kuphunyuziwe</translation>
<translation id="59174027418879706">Kunikwe amandla</translation>
<translation id="5919090499915321845">B10</translation>
+<translation id="5920262536204764679">{NUM_COOKIES,plural, =1{1 esebenzayo}one{# esebenzayo}other{# esebenzayo}}</translation>
<translation id="5921185718311485855">Vuliwe</translation>
<translation id="5921639886840618607">Londoloza ikhadi ku-akhawunti ye-Google?</translation>
<translation id="5922853866070715753">Usuzoqeda</translation>
@@ -1335,6 +1371,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="5989320800837274978">Akuwona amaseva alibamba agxilile noma i-URL yesikripthi se-.pac acacisiwe.</translation>
<translation id="5992691462791905444">I-Engineering Z-fold</translation>
<translation id="6000758707621254961">imiphumela engu-<ph name="RESULT_COUNT" /> ye-'<ph name="SEARCH_TEXT" />'</translation>
+<translation id="6006484371116297560">Okwakudala</translation>
<translation id="6008122969617370890">N-ukuya ku-oda elingu-1</translation>
<translation id="6008256403891681546">I-JCB</translation>
<translation id="6014801569448771146">Hlola amaphasiwedi akho</translation>
@@ -1356,6 +1393,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="6045164183059402045">Isifanekiso sokuqondisa</translation>
<translation id="6047233362582046994">Uma uqonda ubungozi ekuphepheni kwakho, unghle <ph name="BEGIN_LINK" />uvakashele leli sayithi<ph name="END_LINK" /> ngaphambi kokuthi izinhlelo zokusebenza eziyingozi zisuswe.</translation>
<translation id="6047927260846328439">Lokhu okuqukethwe kungazama ukukukhohlisa ukuthi ufake amasofthiwe noma ekuvezeni ulwazi lomuntu siqu. <ph name="BEGIN_LINK" />Bonisa noma kunjalo<ph name="END_LINK" /></translation>
+<translation id="6049004884579590341">Cindezela uphinde ubambe okuthi |<ph name="ACCELERATOR" />| ukuze uphume kusikrini esigcwele</translation>
<translation id="6049488691372270142">Ukulethwa kwekhasi</translation>
<translation id="6051221802930200923">Awukwazi ukuvakashela i-<ph name="SITE" /> okwamanje ngoba iwebhusayithi isebenzisa ukuphina kwesitifiketi. Amaphutha wenethiwekhi nokuhlaselwa kuvamise ukuba ngokwesikhashana, ngakho-ke leli khasi lizosebenza ngemuva kwesikhathi..</translation>
<translation id="6051898664905071243">Ukubalwa kwekhasi:</translation>
@@ -1372,6 +1410,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="610911394827799129">I-akhawunti yakho ye-Google ingaba namanye amafomu omlando wokuphequlula ku-<ph name="BEGIN_LINK" />myactivity.google.com<ph name="END_LINK" />.</translation>
<translation id="6116338172782435947">Bona umbhalo nezithombe ezikopishelwe kubhodi lokunamathisela</translation>
<translation id="6120179357481664955">Khumbula i-UPI ID yakho?</translation>
+<translation id="6123290840358279103">Buka ikhadi elibonakalayo</translation>
<translation id="6124432979022149706">I-Chrome Enterprise Connectors</translation>
<translation id="6146055958333702838">Hlola noma yiziphi izintambo uphinde uqalise kabusha kunoma yimiphi imizila, amamodemu, noma amanye amadivayisi
wenethiwekhi okungahle ukuthi uyawasebenzisa.</translation>
@@ -1408,6 +1447,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="6289939620939689042">Umbala Wekhasi</translation>
<translation id="6290238015253830360">Ama-athikili akho aphakanyisiwe avela lapha</translation>
<translation id="6293309776179964942">I-JIS B5</translation>
+<translation id="6295618774959045776">I-CVC:</translation>
<translation id="6302269476990306341">Umsizi we-Google ku-Chrome uyama</translation>
<translation id="6305205051461490394">I-<ph name="URL" /> ayifinyeleleki.</translation>
<translation id="6312113039770857350">Ikhasi lwebhu alitholakali</translation>
@@ -1433,6 +1473,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="6390200185239044127">Z-fold uhafu</translation>
<translation id="6390662030813198813">Engineering-E</translation>
<translation id="6393956493820063117">Ukunamathisela kusuka ku-<ph name="ORIGIN_NAME" /> kuya kule ndawo kuvinjelwe inqubomgomo yomlawuli</translation>
+<translation id="6398765197997659313">Phuma kusikrini esigcwele</translation>
<translation id="6401136357288658127">Le nqubomgomo ihoxisiwe. Kuzomele usebenzise inqubomgomo ye-<ph name="NEW_POLICY" /> kunalokho.</translation>
<translation id="6404511346730675251">Hlela ibhukhimakhi</translation>
<translation id="6406765186087300643">C0 (Envelope)</translation>
@@ -1445,7 +1486,6 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="6428450836711225518">Iqinisekisa inombolo yakho yefoni</translation>
<translation id="6433490469411711332">Hlela ulwazi loxhumana naye</translation>
<translation id="6433595998831338502">I-<ph name="HOST_NAME" /> inqabe ukuxhumeka.</translation>
-<translation id="6434309073475700221">Lahla</translation>
<translation id="6440503408713884761">Izitshiwe</translation>
<translation id="6443406338865242315">Iziphi izandiso nama-plugins owafakile</translation>
<translation id="6446163441502663861">Kahu (Envelope)</translation>
@@ -1488,6 +1528,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="6624427990725312378">Ulwazi Lokuthintana</translation>
<translation id="6626291197371920147">Engeza inombolo yekhadi evumelekile</translation>
<translation id="6628463337424475685"><ph name="ENGINE" /> Usesho</translation>
+<translation id="6630043285902923878">Ithola wonke amadivayisi we-USB...</translation>
<translation id="6630809736994426279">Abahlaseli okwamanje ku-<ph name="BEGIN_BOLD" /><ph name="SITE" /><ph name="END_BOLD" /> bangazama ukufaka izinhlelo eziyingozi ku-Mac yakho ezitshontsha noma zisule ulwazi lwakho (isibonelo, izithombe, amaphasiwedi, imilayezo, namakhadi esikweletu). <ph name="BEGIN_LEARN_MORE_LINK" />Funda kabanzi<ph name="END_LEARN_MORE_LINK" /></translation>
<translation id="663260587451432563">I-JIS B4</translation>
<translation id="6643016212128521049">Sula</translation>
@@ -1503,6 +1544,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="6671697161687535275">Susa ukuphakanyiswa kwefomu kusukela ku-Chromium?</translation>
<translation id="6685834062052613830">Phuma ngemvume bese uqedele ukusetha</translation>
<translation id="6687335167692595844">Usayizi wefonti eceliwe</translation>
+<translation id="6688743156324860098">Buyekeza…</translation>
<translation id="6689249931105087298">Kuhlobene nephoyinti elimnyama lokucindezela</translation>
<translation id="6689271823431384964">I-Chrome inikeza ngokulondoloza amakhadi akho ku-akhawunti yakho ye-Google ngoba ungene ngemvume. Ungashintsha le mpatho kuzilungiselelo. Igama lomnikazi wekhadi livela ku-akhawunti yakho.</translation>
<translation id="6698381487523150993">Idalwe:</translation>
@@ -1518,6 +1560,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="6744009308914054259">Ngenkathi ulindele ukuxhumeka, ungavakashela kokulandiwe ukuze ufunde ama-athikili angaxhunyiwe kwi-inthanethi.</translation>
<translation id="6753269504797312559">Inani lenqubomgomo</translation>
<translation id="6757797048963528358">Idivayisi yakho iye yalala.</translation>
+<translation id="6767985426384634228">Buyekeza Ikheli?</translation>
<translation id="6768213884286397650">Hagaki (Postcard)</translation>
<translation id="6775759552199460396">I-JIS B2</translation>
<translation id="67862343314499040">Okuvayolethi</translation>
@@ -1540,6 +1583,7 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="6886577214605505410"><ph name="LOCATION_TITLE" /> <ph name="SHORT_URL" /></translation>
<translation id="6888584790432772780">I-Chrome yenze leli khasi laba lula okwenza kube lula ukufunda. I-Chrome ibuyise ikhasi langempela ngaphezulu kokuxhumeka okungaphephile.</translation>
<translation id="6891596781022320156">Izinga lenqubomgomo alisekelwa.</translation>
+<translation id="6895143722905299846">Inombolo ebonakalayo:</translation>
<translation id="6895330447102777224">Ikhadi lakho liqinisekisiwe</translation>
<translation id="6897140037006041989">Umenzeli womsebenzisi</translation>
<translation id="6898699227549475383">Inhlangano (O)</translation>
@@ -1575,10 +1619,10 @@ Lokhu uma kungenjalo kuzovinjelwa izilungiselelo zakho zobumfihlo. Lokhu kuzovum
<translation id="7004583254764674281">Sebenzisa i-Windows Hello ukuqinisekisa amakhadi ngokushesha</translation>
<translation id="7006930604109697472">Thumela noma kunjalo</translation>
<translation id="7012363358306927923">I-China UnionPay</translation>
-<translation id="7012404007611495949">Yenza usayizi omusha Amasethingi</translation>
<translation id="7014741021609395734">Ileveli yokusondeza</translation>
<translation id="7016992613359344582">Lawo mashaji angahle abe isikhathi esisodwa noma avele kaningi futhi kungenzeka angacaci.</translation>
<translation id="7029809446516969842">Amaphasiwedi</translation>
+<translation id="7030436163253143341">Isitifiketi asivumelekile</translation>
<translation id="7031646650991750659">Iziphi izinhlelo zokusebenza ze-Google Play ozifakile</translation>
<translation id="7050187094878475250">Uzame ukufinyelela ku-<ph name="DOMAIN" />, kodwa iseva iphrezente isitifiketi lapho isikhathi sayo sokuba semthethweni siside kakhulu ukuthi singathembeka.</translation>
<translation id="705310974202322020">{NUM_CARDS,plural, =1{Leli khadi alikwazi ukulondolozwa khona manje}one{Lawa makhadi awakwazi ukulondolozwa khona manje}other{Lawa makhadi awakwazi ukulondolozwa khona manje}}</translation>
@@ -1648,12 +1692,14 @@ Imininingwane engeziwe:
<translation id="7300012071106347854">I-Cobalt Blue</translation>
<translation id="7302712225291570345">"<ph name="TEXT" />"</translation>
<translation id="7304030187361489308">Okuphezulu</translation>
+<translation id="7305756307268530424">Qala kabuthaka</translation>
<translation id="7319430975418800333">A3</translation>
<translation id="7320336641823683070">Usizo lokuxhumana</translation>
<translation id="7323804146520582233">Fihla isigaba se-"<ph name="SECTION" />"</translation>
<translation id="733354035281974745">Ukukhishwa kwe-akhawunti kwedivayisi yasendaweni</translation>
<translation id="7333654844024768166">Usanda kufaka iphasiwedi yakho kusayithi elikhohlisayo. I-Chromium incoma ukuya ku-<ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, <ph name="WEBSITE_3" />, namanye amasayithi lapho usebenzisa khona le phasiwedi nokuyishintsha manje.</translation>
<translation id="7334320624316649418">&amp;Yenza futhi ukuhlela kabusha</translation>
+<translation id="7337248890521463931">Bonisa imigqa eminingi</translation>
<translation id="7337706099755338005">Akutholakali kungxenyekazi yakho.</translation>
<translation id="733923710415886693">Isitifiketi seseva asizange sidalulwe ngokubonisa ngale kwesitifiketi.</translation>
<translation id="734600844861828519">11x15</translation>
@@ -1661,6 +1707,7 @@ Imininingwane engeziwe:
<translation id="7349430561505560861">A4-Extra</translation>
<translation id="7353601530677266744">Umugqa womyalo</translation>
<translation id="7359588939039777303">Izikhangiso zivinjewe.</translation>
+<translation id="7363096869660964304">Kodwa, akusho ukuthi awubonakali. Ukuya ku-incognito akufihli ukuphequlula kwakho kusukela kumqashi wakho, umhlinzeki wesevisi yakho ye-inthanethi, noma amawebhusayithi owavakashelayo.</translation>
<translation id="7365596969960773405"><ph name="MANAGE_ADDRESSES_FOCUSED_FRIENDLY_MATCH_TEXT" />, cindezela u-Tab bese u-Enter ukwengeza nokuphatha amakheli kumasethingi we-Chrome</translation>
<translation id="7365849542400970216">Uyawazi umsebenzi wedivayisi yakho?</translation>
<translation id="7372973238305370288">umphumela wosesho</translation>
@@ -1671,7 +1718,9 @@ Imininingwane engeziwe:
<translation id="7378594059915113390">Izilawuli zemidiya</translation>
<translation id="7378627244592794276">Cha</translation>
<translation id="7378810950367401542">/</translation>
+<translation id="7386364858855961704">Akusebenzi</translation>
<translation id="7390545607259442187">Qinisekisa ikhadi</translation>
+<translation id="7392089738299859607">Buyekeza Ikheli</translation>
<translation id="7399802613464275309">Ukuhlola kokuphepha</translation>
<translation id="7400418766976504921">I-URL</translation>
<translation id="7403591733719184120">I-<ph name="DEVICE_NAME" /> yakho iphethwe</translation>
@@ -1686,6 +1735,7 @@ Imininingwane engeziwe:
&lt;li&gt;Vakashela &lt;a href="https://support.google.com/chrome/answer/6098869"&gt;Isikhungo sosizo se-Chrome&lt;/a&gt; ukuze ufunde ukuthi uyisusa kanjani isofthwe kusuka kukhompyutha yakho
&lt;/ol&gt;</translation>
<translation id="741007362987735528">Ifomethi ebanzi</translation>
+<translation id="7410471291937727359">I-Lovely</translation>
<translation id="7416351320495623771">Phatha amaphasiwedi...</translation>
<translation id="7419106976560586862">Indlela yephrofayela</translation>
<translation id="7437289804838430631">Engeza ulwazi loxhumana naye</translation>
@@ -1701,7 +1751,7 @@ Imininingwane engeziwe:
<translation id="7481312909269577407">Dlulisela</translation>
<translation id="7485870689360869515">Ayikho idatha etholiwe.</translation>
<translation id="7495528107193238112">Lokhu okuqukethwe kuvinjelwe. Xhumana nomnikazi wesayithi ukulungisa inkinga.</translation>
-<translation id="7498234416455752244">Qhubeka nokuhlela</translation>
+<translation id="7498193950643227031">Kungaziphatha ngokungalindelekile uma kushintshwa usayizi. Manje usungakhawulela amandla okwenza usayizi wama-app ku-<ph name="SETTINGS" />.</translation>
<translation id="7503664977220660814">Usanda kufaka iphasiwedi yakho kusayithi elikhohlisayo. I-Chromium incoma ukuhlola amaphasiwedi akho alondoloziwe we-<ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, namanye amasayithi lapho usebenzisa khona le phasiwedi manje.</translation>
<translation id="7508255263130623398">Inqubogomo yokubuyisa idivayisi ayinalutho noma ayifani ne-id yedivayisi yamanje</translation>
<translation id="7508870219247277067">I-Avocado Green</translation>
@@ -1721,6 +1771,7 @@ Imininingwane engeziwe:
<translation id="7548892272833184391">Lungisa amaphutha okuxhumana</translation>
<translation id="7549584377607005141">Leli khasi lewebhu lidinga idatha oyifake ngaphambili ukuze liboniswe ngokufanelekile. Ungaphinda uthumele le datha, ngokwenza kanjalo uzophinda noma yisiphi isenzo leli khasi elisenze ngokwedlule.</translation>
<translation id="7550637293666041147">Igama lomsebenzisi ledivayisi yakho negama lomsebenzisi le-Chrome</translation>
+<translation id="755279583747225797">Ukuzama kuyasebenza</translation>
<translation id="7552846755917812628">Zama amathiphu alandelayo:</translation>
<translation id="7554475479213504905">Layisha kabusha uphinde ubonise noma kunjalo</translation>
<translation id="7554791636758816595">Ithebhu entsha</translation>
@@ -1739,7 +1790,6 @@ Imininingwane engeziwe:
<translation id="7610193165460212391">Inani lingaphandle kwebanga elingu-<ph name="VALUE" />.</translation>
<translation id="7613889955535752492">Iphelelwa isikhathi: <ph name="EXPIRATION_MONTH" />/<ph name="EXPIRATION_YEAR" /></translation>
<translation id="7614494068621678628"><ph name="MANAGE_PASSWORDS_FOCUSED_FRIENDLY_MATCH_TEXT" />, cindezela u-Tab bese u-Enter ukuze ubuke futhi uphathe amaphasiwedi akho kumasethingi e-Chrome</translation>
-<translation id="7615602087246926389">Usuvele unedatha ebetheliwe esebenzisa inguqulo ehlukile yephasiwedi yakho ye-Akhawunti ye-Google. Sicela uyifake ngezansi.</translation>
<translation id="7616645509853975347">Umlawuli wakho uvule i-Chrome Enterprise Connectors kusiphequluli sakho. Lezi zixhumi zikwazi ukufinyelela kwenye idatha yakho.</translation>
<translation id="7619838219691048931">Ishidi lokuphela</translation>
<translation id="762844065391966283">Okukodwa ngesikhathi</translation>
@@ -1804,13 +1854,12 @@ Imininingwane engeziwe:
<translation id="782886543891417279">I-Wi-Fi oyisebenzisayo (<ph name="WIFI_NAME" />) ingadinga ukuthi uvakashele ikhasi layo lokungena ngemvume.</translation>
<translation id="7836231406687464395">Postfix (Envelope)</translation>
<translation id="7844689747373518809">{COUNT,plural, =0{Lutho}=1{1 uhlelo lokusebenza (<ph name="EXAMPLE_APP_1" />)}=2{2 izinhlelo zokusebenza (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />)}one{# izinhlelo zokusebenza (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}other{# izinhlelo zokusebenza (<ph name="EXAMPLE_APP_1" />, <ph name="EXAMPLE_APP_2" />, <ph name="AND_MORE" />)}}</translation>
-<translation id="785549533363645510">Kodwa, akusho ukuthi awubonakali. Ukuya ku-incognito akufihli ukuphequlula kwakho kusukela kumqashi wakho, umhlinzeki wesevisi yakho ye-inthanethi, noma amawebhusayithi owavakashelayo.</translation>
<translation id="7855695075675558090"><ph name="TOTAL_LABEL" /> <ph name="CURRENCY_CODE" /> <ph name="FORMATTED_TOTAL_AMOUNT" /></translation>
-<translation id="7858035578849836010">Vula amafayela ngezinhlobo zezinhlangano zefayela.</translation>
<translation id="7862185352068345852">Shiya isayithi?</translation>
<translation id="7865448901209910068">Isivinini esihamba phambili</translation>
<translation id="7874263914261512992">Usanda kufaka iphasiwedi yakho kusayithi elikhohlisayo. I-Chrome incoma ukuhlola amaphasiwedi akho alondoloziwe we-<ph name="WEBSITE_1" />, <ph name="WEBSITE_2" />, namanye amasayithi lapho usebenzisa khona le phasiwedi manje.</translation>
<translation id="7878562273885520351">Iphasiwedi yakho ingafakwa engozini</translation>
+<translation id="7880146494886811634">Londoloza Ikheli</translation>
<translation id="7882421473871500483">Mpofu</translation>
<translation id="7887683347370398519">Hlola i-CVC yakho uphinde uzame futhi</translation>
<translation id="7887885240995164102">Faka isithombe-esithombeni</translation>
@@ -1818,6 +1867,7 @@ Imininingwane engeziwe:
<translation id="7894280532028510793">Uma isipelingi singalungile, <ph name="BEGIN_LINK" />zama ukuqalisa Ukuxilongwa Kwenethiwekhi<ph name="END_LINK" />.</translation>
<translation id="7904208859782148177">C3 (Envelope)</translation>
<translation id="7931318309563332511">Akwaziwa</translation>
+<translation id="793209273132572360">Buyekeza ikheli?</translation>
<translation id="7932579305932748336">Ibhantshi</translation>
<translation id="79338296614623784">Faka inombolo yefoni evumelekile</translation>
<translation id="7934052535022478634">Inkokhelo iqediwe</translation>
@@ -1888,6 +1938,7 @@ Imininingwane engeziwe:
<translation id="8175796834047840627">I-Chrome inikezela ngokulondoloza amakhadi akho ku-akhawunti yakho ye-Google ngoba ungene ngemvume. Ungashintsha lokhu kuziphatha kuzilungiselelo.</translation>
<translation id="8176440868214972690">Umlawuli wale divayisi uthumele ulwazi kumawebhusayithi alandelayo, njengamasethingi noma izinqumbomgomo.</translation>
<translation id="8184538546369750125">Sebenzisa komhlaba okuzenzakalelayo (Vumela)</translation>
+<translation id="8193086767630290324">Izenzo ezithathwe ngedatha zimakwe njengeziyimfihlo</translation>
<translation id="8194797478851900357">&amp;Hlehlisa ukuhambisa</translation>
<translation id="8201077131113104583">I-URL yesibuyekezo esingavumelekile esine-ID "<ph name="EXTENSION_ID" />".</translation>
<translation id="8202097416529803614">Isifinyezo se-oda</translation>
@@ -1910,6 +1961,7 @@ Imininingwane engeziwe:
<translation id="8249296373107784235">Khansela</translation>
<translation id="8249320324621329438">Igcine ukulandwa:</translation>
<translation id="8253091569723639551">Kudingeka ikheli lokukhokha</translation>
+<translation id="8257387598443225809">Le app idizayinelwe iselula</translation>
<translation id="825929999321470778">Bonisa onke amaphasiwedi alondoloziwe</translation>
<translation id="8261506727792406068">Susa</translation>
<translation id="8262952874573525464">Ukuthunga uphetho phansi</translation>
@@ -2033,7 +2085,6 @@ Imininingwane engeziwe:
<translation id="8719528812645237045">Ukushaya okuningi phezulu</translation>
<translation id="8725066075913043281">Zama futhi</translation>
<translation id="8726549941689275341">Usayizi wekhasi:</translation>
-<translation id="8728672262656704056">Usuye ku-incognito</translation>
<translation id="8730621377337864115">Kwenziwe</translation>
<translation id="8731544501227493793">Inkinobho yokuphatha amaphasiwedi, cindezela u-Enter ukuze ubuke futhi uphathe amaphasiwedi akho kumasethingi e-Chrome</translation>
<translation id="8734529307927223492">I-<ph name="DEVICE_TYPE" /> yakho iphethwe ngu-<ph name="MANAGER" /></translation>
@@ -2110,6 +2161,7 @@ Imininingwane engeziwe:
<translation id="9020542370529661692">Leli khasi lihunyushelwe ku-<ph name="TARGET_LANGUAGE" /></translation>
<translation id="9020742383383852663">A8</translation>
<translation id="9025348182339809926">(Ayivumelekile)</translation>
+<translation id="9030265603405983977">I-Monochrome</translation>
<translation id="9035022520814077154">Iphutha lokuvikeleka</translation>
<translation id="9038649477754266430">Sebenzisa isevisi yokuqagela ukulayisha amakhasi ngokushesha</translation>
<translation id="9039213469156557790">Ngokuqhubekayo, leli khasi lifaka ezinye izisetshenziswa ezingavikelekile. Lezi zisetshenziswa zingabukwa ngabanye ngenkathi ikwezokuthutha, futhi zingalungiswa yisihlaseli ukuze kuguqulwe ukuziphatha kwekhasi.</translation>
@@ -2133,6 +2185,7 @@ Imininingwane engeziwe:
<translation id="91108059142052966">Inqubomgomo yomlawuli ikhubaza ukwabelana ngesikrini ne-<ph name="APPLICATION_TITLE" /> lapho okuqukethwe okuyimfihlo kubonakala</translation>
<translation id="9114524666733003316">Iqinisekisa ikhadi...</translation>
<translation id="9114581008513152754">Lesi siphequluli asiphethwe inkampani noma enye inhlangano. Umsebenzi kule divayisi ungaphathwa ngaphandle kwe-Chrome. <ph name="BEGIN_LINK" />Funda kabanzi<ph name="END_LINK" /></translation>
+<translation id="9117930699067497412">Okusha</translation>
<translation id="9119042192571987207">Kulayishiwe</translation>
<translation id="9128016270925453879">Izinqubomgomo zilayishiwe</translation>
<translation id="9128870381267983090">Xhuma kunethiwekhi</translation>
@@ -2151,6 +2204,7 @@ Imininingwane engeziwe:
<translation id="9170848237812810038">&amp;Hlehlisa</translation>
<translation id="9171296965991013597">Shiya uhlelo lokusebenza?</translation>
<translation id="9173282814238175921">Idokhumenti elilodwa/Ishidi elisha</translation>
+<translation id="9173995187295789444">Iskena amadivayisi e-Bluetooth...</translation>
<translation id="917450738466192189">Isitifiketi seseva asivumelekile.</translation>
<translation id="9174917557437862841">Inkinobho yokushintsha ithebhu, cindezela ku-Enter ukuze ushintshele kule thebhu</translation>
<translation id="9179703756951298733">Phatha izinkokhelo zakho nolwazi lwekhadi lesikweletu kumasethingi we-Chrome</translation>
diff --git a/chromium/components/subresource_filter/android/BUILD.gn b/chromium/components/subresource_filter/android/BUILD.gn
index 9b8a1265014..1bf595d6837 100644
--- a/chromium/components/subresource_filter/android/BUILD.gn
+++ b/chromium/components/subresource_filter/android/BUILD.gn
@@ -30,25 +30,11 @@ android_library("java") {
}
source_set("android") {
- sources = [
- "ads_blocked_infobar.cc",
- "ads_blocked_infobar.h",
- "ads_blocked_infobar_delegate.cc",
- "ads_blocked_infobar_delegate.h",
- "subresource_filter_feature_list.cc",
- ]
+ sources = [ "subresource_filter_feature_list.cc" ]
deps = [
":subresource_filter_jni_headers",
"//base",
- "//components/infobars/android",
- "//components/infobars/content",
- "//components/infobars/core",
- "//components/resources:android_resources",
- "//components/strings:components_strings_grit",
- "//components/subresource_filter/content/browser",
"//components/subresource_filter/core/browser",
- "//content/public/browser",
- "//ui/base",
]
}
diff --git a/chromium/components/subresource_filter/android/DEPS b/chromium/components/subresource_filter/android/DEPS
deleted file mode 100644
index ff048235361..00000000000
--- a/chromium/components/subresource_filter/android/DEPS
+++ /dev/null
@@ -1,9 +0,0 @@
-include_rules = [
- "+components/infobars",
- "+components/resources",
- "+components/strings",
- "+components/subresource_filter/content/browser",
- "+content/public/browser",
- "+ui/android/java",
- "+ui/base/l10n",
-]
diff --git a/chromium/components/subresource_filter/android/subresource_filter_feature_list.cc b/chromium/components/subresource_filter/android/subresource_filter_feature_list.cc
index e9ecae9395b..320eb7f90cb 100644
--- a/chromium/components/subresource_filter/android/subresource_filter_feature_list.cc
+++ b/chromium/components/subresource_filter/android/subresource_filter_feature_list.cc
@@ -4,7 +4,7 @@
#include "base/android/jni_string.h"
#include "base/feature_list.h"
-#include "base/stl_util.h"
+#include "base/notreached.h"
#include "components/subresource_filter/android/subresource_filter_jni_headers/SubresourceFilterFeatureList_jni.h"
#include "components/subresource_filter/core/browser/subresource_filter_features.h"
@@ -18,15 +18,15 @@ namespace {
// Array of features exposed through the Java ContentFeatureList API. Entries in
// this array may either refer to features defined in the header of this file or
// in other locations in the code base (e.g. content_features.h).
-const base::Feature* kFeaturesExposedToJava[] = {
+const base::Feature* const kFeaturesExposedToJava[] = {
&kSafeBrowsingSubresourceFilter,
};
// TODO(crbug.com/1060097): Removethis once a generalized FeatureList exists.
const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
- for (size_t i = 0; i < base::size(kFeaturesExposedToJava); ++i) {
- if (kFeaturesExposedToJava[i]->name == feature_name)
- return kFeaturesExposedToJava[i];
+ for (const base::Feature* feature : kFeaturesExposedToJava) {
+ if (feature->name == feature_name)
+ return feature;
}
NOTREACHED() << "Queried feature not found in SubresourceFilterFeatureList: "
<< feature_name;
diff --git a/chromium/components/subresource_filter/content/browser/BUILD.gn b/chromium/components/subresource_filter/content/browser/BUILD.gn
index 22b2b036ae6..5a3f31eaac3 100644
--- a/chromium/components/subresource_filter/content/browser/BUILD.gn
+++ b/chromium/components/subresource_filter/content/browser/BUILD.gn
@@ -31,7 +31,6 @@ static_library("browser") {
"ruleset_version.h",
"subframe_navigation_filtering_throttle.cc",
"subframe_navigation_filtering_throttle.h",
- "subresource_filter_client.h",
"subresource_filter_content_settings_manager.cc",
"subresource_filter_content_settings_manager.h",
"subresource_filter_observer.h",
@@ -75,6 +74,22 @@ static_library("browser") {
"//third_party/flatbuffers:flatbuffers",
"//ui/base",
]
+ if (is_android) {
+ sources += [
+ "ads_blocked_infobar.cc",
+ "ads_blocked_infobar.h",
+ "ads_blocked_infobar_delegate.cc",
+ "ads_blocked_infobar_delegate.h",
+ ]
+ deps += [
+ "//components/infobars/android",
+ "//components/infobars/content",
+ "//components/infobars/core",
+ "//components/resources:android_resources",
+ "//components/strings:components_strings_grit",
+ "//components/subresource_filter/android:subresource_filter_jni_headers",
+ ]
+ }
}
static_library("test_support") {
@@ -94,8 +109,8 @@ static_library("test_support") {
"subresource_filter_test_harness.h",
"test_ruleset_publisher.cc",
"test_ruleset_publisher.h",
- "test_subresource_filter_client.cc",
- "test_subresource_filter_client.h",
+ "throttle_manager_test_support.cc",
+ "throttle_manager_test_support.h",
]
deps = [
":browser",
@@ -103,6 +118,8 @@ static_library("test_support") {
"//components/content_settings/browser",
"//components/content_settings/browser:test_support",
"//components/content_settings/core/browser",
+ "//components/infobars/content",
+ "//components/infobars/core",
"//components/prefs:test_support",
"//components/safe_browsing/core/db:database_manager",
"//components/subresource_filter/content/common",
@@ -147,8 +164,11 @@ source_set("unit_tests") {
":browser",
":test_support",
"//base/test:test_support",
+ "//components/content_settings/browser",
"//components/content_settings/core/browser",
"//components/content_settings/core/common",
+ "//components/infobars/content",
+ "//components/infobars/core",
"//components/prefs:test_support",
"//components/safe_browsing/core/db:database_manager",
"//components/safe_browsing/core/db:util",
diff --git a/chromium/components/subresource_filter/content/browser/DEPS b/chromium/components/subresource_filter/content/browser/DEPS
index ba59e48d0b3..4d8c8a634cd 100644
--- a/chromium/components/subresource_filter/content/browser/DEPS
+++ b/chromium/components/subresource_filter/content/browser/DEPS
@@ -2,6 +2,9 @@ include_rules = [
"+components/content_settings/browser",
"+components/content_settings/core/browser",
"+components/content_settings/core/common",
+ "+components/infobars",
+ "+components/resources",
+ "+components/strings",
"+components/keyed_service/core",
"+components/safe_browsing/core/db",
"+components/sync_preferences",
diff --git a/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc b/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
index 07c3c5f9553..4301246c668 100644
--- a/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
+++ b/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.cc
@@ -22,7 +22,7 @@ ActivationStateComputingNavigationThrottle::CreateForMainFrame(
content::NavigationHandle* navigation_handle) {
DCHECK(navigation_handle->IsInMainFrame());
return base::WrapUnique(new ActivationStateComputingNavigationThrottle(
- navigation_handle, base::Optional<mojom::ActivationState>(), nullptr));
+ navigation_handle, absl::optional<mojom::ActivationState>(), nullptr));
}
// static
@@ -42,7 +42,7 @@ ActivationStateComputingNavigationThrottle::CreateForSubframe(
ActivationStateComputingNavigationThrottle::
ActivationStateComputingNavigationThrottle(
content::NavigationHandle* navigation_handle,
- const base::Optional<mojom::ActivationState> parent_activation_state,
+ const absl::optional<mojom::ActivationState> parent_activation_state,
VerifiedRuleset::Handle* ruleset_handle)
: content::NavigationThrottle(navigation_handle),
parent_activation_state_(parent_activation_state),
diff --git a/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h b/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h
index 9474b0534c5..bde2e535d03 100644
--- a/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h
+++ b/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_FRAME_ACTIVATION_NAVIGATION_THROTTLE_H_
-#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_FRAME_ACTIVATION_NAVIGATION_THROTTLE_H_
+#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ACTIVATION_STATE_COMPUTING_NAVIGATION_THROTTLE_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ACTIVATION_STATE_COMPUTING_NAVIGATION_THROTTLE_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/subresource_filter/content/browser/verified_ruleset_dealer.h"
#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h"
#include "content/public/browser/navigation_throttle.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace subresource_filter {
@@ -97,11 +97,11 @@ class ActivationStateComputingNavigationThrottle
ActivationStateComputingNavigationThrottle(
content::NavigationHandle* navigation_handle,
- const base::Optional<mojom::ActivationState> parent_activation_state,
+ const absl::optional<mojom::ActivationState> parent_activation_state,
VerifiedRuleset::Handle* ruleset_handle);
// Optional to allow for DCHECKing.
- base::Optional<mojom::ActivationState> parent_activation_state_;
+ absl::optional<mojom::ActivationState> parent_activation_state_;
std::unique_ptr<AsyncDocumentSubresourceFilter> async_filter_;
@@ -126,4 +126,4 @@ class ActivationStateComputingNavigationThrottle
} // namespace subresource_filter
-#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_FRAME_ACTIVATION_NAVIGATION_THROTTLE_H_
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ACTIVATION_STATE_COMPUTING_NAVIGATION_THROTTLE_H_
diff --git a/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc b/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
index 5e1d7df0d40..ccc0d7e30ae 100644
--- a/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
+++ b/chromium/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
@@ -12,7 +12,6 @@
#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/test/metrics/histogram_tester.h"
@@ -30,6 +29,7 @@
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace subresource_filter {
@@ -238,8 +238,8 @@ class ActivationStateComputingNavigationThrottleTest
// Owned by the current navigation.
ActivationStateComputingNavigationThrottle* test_throttle_;
- base::Optional<mojom::ActivationState> last_activation_state_;
- base::Optional<mojom::ActivationState> parent_activation_state_;
+ absl::optional<mojom::ActivationState> last_activation_state_;
+ absl::optional<mojom::ActivationState> parent_activation_state_;
// Needed for potential cross process navigations which swap hosts.
content::RenderFrameHost* last_committed_frame_host_ = nullptr;
diff --git a/chromium/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.cc b/chromium/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.cc
index e7347aadde3..0821750ff90 100644
--- a/chromium/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.cc
+++ b/chromium/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.cc
@@ -74,7 +74,7 @@ void ExpectFrameAdEvidence(
auto* throttle_manager =
ContentSubresourceFilterThrottleManager::FromWebContents(
content::WebContents::FromRenderFrameHost(frame_host));
- base::Optional<blink::FrameAdEvidence> ad_evidence =
+ absl::optional<blink::FrameAdEvidence> ad_evidence =
throttle_manager->GetAdEvidenceForFrame(frame_host);
ASSERT_TRUE(ad_evidence.has_value());
EXPECT_TRUE(ad_evidence->is_complete());
diff --git a/chromium/components/subresource_filter/android/ads_blocked_infobar.cc b/chromium/components/subresource_filter/content/browser/ads_blocked_infobar.cc
index 925fcb2f55b..062b351a128 100644
--- a/chromium/components/subresource_filter/android/ads_blocked_infobar.cc
+++ b/chromium/components/subresource_filter/content/browser/ads_blocked_infobar.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/subresource_filter/android/ads_blocked_infobar.h"
+#include "components/subresource_filter/content/browser/ads_blocked_infobar.h"
#include <utility>
diff --git a/chromium/components/subresource_filter/android/ads_blocked_infobar.h b/chromium/components/subresource_filter/content/browser/ads_blocked_infobar.h
index ad7f9c42db7..0d46b4fc7e0 100644
--- a/chromium/components/subresource_filter/android/ads_blocked_infobar.h
+++ b/chromium/components/subresource_filter/content/browser/ads_blocked_infobar.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_SUBRESOURCE_FILTER_ANDROID_ADS_BLOCKED_INFOBAR_H_
-#define COMPONENTS_SUBRESOURCE_FILTER_ANDROID_ADS_BLOCKED_INFOBAR_H_
+#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ADS_BLOCKED_INFOBAR_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ADS_BLOCKED_INFOBAR_H_
#include "base/macros.h"
#include "components/infobars/android/confirm_infobar.h"
-#include "components/subresource_filter/android/ads_blocked_infobar_delegate.h"
+#include "components/subresource_filter/content/browser/ads_blocked_infobar_delegate.h"
namespace subresource_filter {
@@ -28,4 +28,4 @@ class AdsBlockedInfoBar : public infobars::ConfirmInfoBar {
} // namespace subresource_filter
-#endif // COMPONENTS_SUBRESOURCE_FILTER_ANDROID_ADS_BLOCKED_INFOBAR_H_
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ADS_BLOCKED_INFOBAR_H_
diff --git a/chromium/components/subresource_filter/android/ads_blocked_infobar_delegate.cc b/chromium/components/subresource_filter/content/browser/ads_blocked_infobar_delegate.cc
index 36193f0a6cc..c56c7ee2223 100644
--- a/chromium/components/subresource_filter/android/ads_blocked_infobar_delegate.cc
+++ b/chromium/components/subresource_filter/content/browser/ads_blocked_infobar_delegate.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/subresource_filter/android/ads_blocked_infobar_delegate.h"
+#include "components/subresource_filter/content/browser/ads_blocked_infobar_delegate.h"
#include <memory>
@@ -12,7 +12,7 @@
#include "components/infobars/core/infobar.h"
#include "components/resources/android/theme_resources.h"
#include "components/strings/grit/components_strings.h"
-#include "components/subresource_filter/android/ads_blocked_infobar.h"
+#include "components/subresource_filter/content/browser/ads_blocked_infobar.h"
#include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h"
#include "components/subresource_filter/core/browser/subresource_filter_constants.h"
#include "content/public/browser/web_contents.h"
diff --git a/chromium/components/subresource_filter/android/ads_blocked_infobar_delegate.h b/chromium/components/subresource_filter/content/browser/ads_blocked_infobar_delegate.h
index 430aa9af529..894012e6b38 100644
--- a/chromium/components/subresource_filter/android/ads_blocked_infobar_delegate.h
+++ b/chromium/components/subresource_filter/content/browser/ads_blocked_infobar_delegate.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_SUBRESOURCE_FILTER_ANDROID_ADS_BLOCKED_INFOBAR_DELEGATE_H_
-#define COMPONENTS_SUBRESOURCE_FILTER_ANDROID_ADS_BLOCKED_INFOBAR_DELEGATE_H_
+#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ADS_BLOCKED_INFOBAR_DELEGATE_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ADS_BLOCKED_INFOBAR_DELEGATE_H_
#include "base/macros.h"
#include "components/infobars/android/infobar_android.h"
@@ -53,4 +53,4 @@ class AdsBlockedInfobarDelegate : public ConfirmInfoBarDelegate {
} // namespace subresource_filter
-#endif // COMPONENTS_SUBRESOURCE_FILTER_ANDROID_ADS_BLOCKED_INFOBAR_DELEGATE_H_
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ADS_BLOCKED_INFOBAR_DELEGATE_H_
diff --git a/chromium/components/subresource_filter/content/browser/ads_intervention_manager.cc b/chromium/components/subresource_filter/content/browser/ads_intervention_manager.cc
index e7fdffb9f6a..1a91d8f94e5 100644
--- a/chromium/components/subresource_filter/content/browser/ads_intervention_manager.cc
+++ b/chromium/components/subresource_filter/content/browser/ads_intervention_manager.cc
@@ -83,7 +83,7 @@ void AdsInterventionManager::TriggerAdsInterventionForUrlOnSubsequentLoads(
ads_violation);
}
-base::Optional<AdsInterventionManager::LastAdsIntervention>
+absl::optional<AdsInterventionManager::LastAdsIntervention>
AdsInterventionManager::GetLastAdsIntervention(const GURL& url) const {
int ads_violation;
double last_violation_time;
@@ -100,7 +100,7 @@ AdsInterventionManager::GetLastAdsIntervention(const GURL& url) const {
{diff, static_cast<mojom::AdsViolation>(ads_violation)});
}
- return base::nullopt;
+ return absl::nullopt;
}
bool AdsInterventionManager::ShouldActivate(
@@ -109,7 +109,7 @@ bool AdsInterventionManager::ShouldActivate(
// TODO(https://crbug.com/1136987): Add new ads intervention
// manager function to return struct with all ads intervention
// metadata to reduce metadata accesses.
- base::Optional<AdsInterventionManager::LastAdsIntervention>
+ absl::optional<AdsInterventionManager::LastAdsIntervention>
last_intervention = GetLastAdsIntervention(url);
// Only activate the subresource filter if we are intervening on
diff --git a/chromium/components/subresource_filter/content/browser/ads_intervention_manager.h b/chromium/components/subresource_filter/content/browser/ads_intervention_manager.h
index 0561bfb52dd..3c666f3d22e 100644
--- a/chromium/components/subresource_filter/content/browser/ads_intervention_manager.h
+++ b/chromium/components/subresource_filter/content/browser/ads_intervention_manager.h
@@ -5,11 +5,9 @@
#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ADS_INTERVENTION_MANAGER_H_
#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ADS_INTERVENTION_MANAGER_H_
-#include <memory>
-
-#include "base/optional.h"
#include "components/subresource_filter/content/browser/subresource_filter_content_settings_manager.h"
#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -86,10 +84,10 @@ class AdsInterventionManager {
mojom::AdsViolation ads_violation);
// Returns the last active ads intervention written to metadata,
- // otherwise base::nullopt is returned. When retrieving ads interventions
+ // otherwise absl::nullopt is returned. When retrieving ads interventions
// for a navigation, should_record_metrics should be true to record
// per-navigation ads intervention metrics.
- base::Optional<LastAdsIntervention> GetLastAdsIntervention(
+ absl::optional<LastAdsIntervention> GetLastAdsIntervention(
const GURL& url) const;
// Returns whether the subresource filter should activate for
diff --git a/chromium/components/subresource_filter/content/browser/ads_intervention_manager_unittest.cc b/chromium/components/subresource_filter/content/browser/ads_intervention_manager_unittest.cc
index 17ffa249939..b161333005c 100644
--- a/chromium/components/subresource_filter/content/browser/ads_intervention_manager_unittest.cc
+++ b/chromium/components/subresource_filter/content/browser/ads_intervention_manager_unittest.cc
@@ -71,7 +71,7 @@ TEST_F(AdsInterventionManagerTest,
NoIntervention_NoActiveInterventionReturned) {
GURL url("https://example.test/");
- base::Optional<AdsInterventionManager::LastAdsIntervention> ads_intervention =
+ absl::optional<AdsInterventionManager::LastAdsIntervention> ads_intervention =
ads_intervention_manager_->GetLastAdsIntervention(url);
EXPECT_FALSE(ads_intervention.has_value());
}
@@ -83,7 +83,7 @@ TEST_F(AdsInterventionManagerTest, SingleIntervention_TimeSinceMatchesClock) {
url, mojom::AdsViolation::kMobileAdDensityByHeightAbove30);
test_clock()->Advance(base::TimeDelta::FromHours(1));
- base::Optional<AdsInterventionManager::LastAdsIntervention> ads_intervention =
+ absl::optional<AdsInterventionManager::LastAdsIntervention> ads_intervention =
ads_intervention_manager_->GetLastAdsIntervention(url);
EXPECT_TRUE(ads_intervention.has_value());
EXPECT_EQ(ads_intervention->ads_violation,
diff --git a/chromium/components/subresource_filter/content/browser/async_document_subresource_filter.h b/chromium/components/subresource_filter/content/browser/async_document_subresource_filter.h
index 7580945ef38..defd32c03f1 100644
--- a/chromium/components/subresource_filter/content/browser/async_document_subresource_filter.h
+++ b/chromium/components/subresource_filter/content/browser/async_document_subresource_filter.h
@@ -6,18 +6,17 @@
#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ASYNC_DOCUMENT_SUBRESOURCE_FILTER_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "components/subresource_filter/content/browser/verified_ruleset_dealer.h"
#include "components/subresource_filter/core/common/document_subresource_filter.h"
#include "components/subresource_filter/core/common/load_policy.h"
#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -185,7 +184,7 @@ class AsyncDocumentSubresourceFilter {
std::unique_ptr<Core, base::OnTaskRunnerDeleter> core_;
base::OnceClosure first_disallowed_load_callback_;
- base::Optional<mojom::ActivationState> activation_state_;
+ absl::optional<mojom::ActivationState> activation_state_;
base::SequenceChecker sequence_checker_;
@@ -228,7 +227,7 @@ class AsyncDocumentSubresourceFilter::Core {
const url::Origin& document_origin,
VerifiedRuleset* verified_ruleset);
- base::Optional<DocumentSubresourceFilter> filter_;
+ absl::optional<DocumentSubresourceFilter> filter_;
base::SequenceChecker sequence_checker_;
DISALLOW_COPY_AND_ASSIGN(Core);
diff --git a/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc b/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
index 3f56725466b..6f921b776a7 100644
--- a/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
+++ b/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
@@ -19,7 +19,6 @@
#include "components/subresource_filter/content/browser/async_document_subresource_filter.h"
#include "components/subresource_filter/content/browser/page_load_statistics.h"
#include "components/subresource_filter/content/browser/profile_interaction_manager.h"
-#include "components/subresource_filter/content/browser/subresource_filter_client.h"
#include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h"
#include "components/subresource_filter/content/mojom/subresource_filter_agent.mojom.h"
#include "components/subresource_filter/core/browser/subresource_filter_constants.h"
@@ -35,6 +34,7 @@
#include "content/public/common/url_utils.h"
#include "net/base/net_errors.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
namespace subresource_filter {
@@ -89,8 +89,8 @@ const char ContentSubresourceFilterThrottleManager::
// static
void ContentSubresourceFilterThrottleManager::CreateForWebContents(
content::WebContents* web_contents,
- std::unique_ptr<SubresourceFilterClient> client,
SubresourceFilterProfileContext* profile_context,
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager,
VerifiedRulesetDealer::Handle* dealer_handle) {
if (!base::FeatureList::IsEnabled(kSafeBrowsingSubresourceFilter))
return;
@@ -101,7 +101,7 @@ void ContentSubresourceFilterThrottleManager::CreateForWebContents(
web_contents->SetUserData(
kContentSubresourceFilterThrottleManagerWebContentsUserDataKey,
std::make_unique<ContentSubresourceFilterThrottleManager>(
- std::move(client), profile_context, dealer_handle, web_contents));
+ profile_context, database_manager, dealer_handle, web_contents));
}
// static
@@ -115,14 +115,15 @@ ContentSubresourceFilterThrottleManager::FromWebContents(
ContentSubresourceFilterThrottleManager::
ContentSubresourceFilterThrottleManager(
- std::unique_ptr<SubresourceFilterClient> client,
SubresourceFilterProfileContext* profile_context,
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
+ database_manager,
VerifiedRulesetDealer::Handle* dealer_handle,
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
receiver_(web_contents, this),
dealer_handle_(dealer_handle),
- client_(std::move(client)),
+ database_manager_(std::move(database_manager)),
profile_interaction_manager_(
std::make_unique<subresource_filter::ProfileInteractionManager>(
web_contents,
@@ -164,61 +165,66 @@ void ContentSubresourceFilterThrottleManager::ReadyToCommitNavigation(
content::RenderFrameHost* frame_host =
navigation_handle->GetRenderFrameHost();
+ absl::optional<blink::FrameAdEvidence> ad_evidence_for_navigation;
+
// Update the ad status of a frame given the new navigation. This may tag or
// untag a frame as an ad.
if (!navigation_handle->IsInMainFrame()) {
blink::FrameAdEvidence& ad_evidence = EnsureFrameAdEvidence(frame_host);
+ DCHECK_EQ(ad_evidence.parent_is_ad(),
+ base::Contains(ad_frames_,
+ frame_host->GetParent()->GetFrameTreeNodeId()));
ad_evidence.set_is_complete();
+ ad_evidence_for_navigation = ad_evidence;
SetIsAdSubframe(frame_host, ad_evidence.IndicatesAdSubframe());
}
+ mojom::ActivationState activation_state =
+ ActivationStateForNextCommittedLoad(navigation_handle);
+
+ TRACE_EVENT2(
+ TRACE_DISABLED_BY_DEFAULT("loading"),
+ "ContentSubresourceFilterThrottleManager::ReadyToCommitNavigation",
+ "activation_state", static_cast<int>(activation_state.activation_level),
+ "render_frame_host", navigation_handle->GetRenderFrameHost());
+
+ mojo::AssociatedRemote<mojom::SubresourceFilterAgent> agent;
+ frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&agent);
+
+ // We send `ad_evidence_for_navigation` even if the frame is not tagged as an
+ // ad. This ensures the renderer's copy is up-to-date, including propagating
+ // it on cross-process navigations.
+ agent->ActivateForNextCommittedLoad(activation_state.Clone(),
+ ad_evidence_for_navigation);
+}
+
+mojom::ActivationState
+ContentSubresourceFilterThrottleManager::ActivationStateForNextCommittedLoad(
+ content::NavigationHandle* navigation_handle) {
if (navigation_handle->GetNetErrorCode() != net::OK)
- return;
+ return mojom::ActivationState();
auto it =
ongoing_activation_throttles_.find(navigation_handle->GetNavigationId());
if (it == ongoing_activation_throttles_.end())
- return;
+ return mojom::ActivationState();
// Main frame throttles with disabled page-level activation will not have
// associated filters.
ActivationStateComputingNavigationThrottle* throttle = it->second;
AsyncDocumentSubresourceFilter* filter = throttle->filter();
if (!filter)
- return;
+ return mojom::ActivationState();
// A filter with DISABLED activation indicates a corrupted ruleset.
- mojom::ActivationLevel level = filter->activation_state().activation_level;
- if (level == mojom::ActivationLevel::kDisabled)
- return;
-
- TRACE_EVENT2(
- TRACE_DISABLED_BY_DEFAULT("loading"),
- "ContentSubresourceFilterThrottleManager::ReadyToCommitNavigation",
- "activation_state", static_cast<int>(level), "render_frame_host",
- frame_host);
-
- throttle->WillSendActivationToRenderer();
-
- bool is_ad_subframe =
- base::Contains(ad_frames_, navigation_handle->GetFrameTreeNodeId());
- DCHECK(!is_ad_subframe || !navigation_handle->IsInMainFrame());
-
- bool parent_is_ad =
- frame_host->GetParent() &&
- base::Contains(ad_frames_, frame_host->GetParent()->GetFrameTreeNodeId());
-
- blink::mojom::AdFrameType ad_frame_type = blink::mojom::AdFrameType::kNonAd;
- if (is_ad_subframe) {
- ad_frame_type = parent_is_ad ? blink::mojom::AdFrameType::kChildAd
- : blink::mojom::AdFrameType::kRootAd;
+ if (filter->activation_state().activation_level ==
+ mojom::ActivationLevel::kDisabled) {
+ return mojom::ActivationState();
}
- mojo::AssociatedRemote<mojom::SubresourceFilterAgent> agent;
- frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&agent);
- agent->ActivateForNextCommittedLoad(filter->activation_state().Clone(),
- ad_frame_type);
+ throttle->WillSendActivationToRenderer();
+ return filter->activation_state();
}
void ContentSubresourceFilterThrottleManager::DidFinishNavigation(
@@ -323,7 +329,7 @@ ContentSubresourceFilterThrottleManager::FilterForFinishedNavigation(
DCHECK(frame_host);
std::unique_ptr<AsyncDocumentSubresourceFilter> filter;
- base::Optional<mojom::ActivationState> activation_to_inherit;
+ absl::optional<mojom::ActivationState> activation_to_inherit;
did_inherit_opener_activation = false;
if (navigation_handle->HasCommitted() && throttle) {
@@ -472,13 +478,11 @@ void ContentSubresourceFilterThrottleManager::MaybeAppendNavigationThrottles(
DCHECK(!navigation_handle->IsSameDocument());
DCHECK(!ShouldInheritActivation(navigation_handle->GetURL()));
- if (navigation_handle->IsInMainFrame() &&
- client_->GetSafeBrowsingDatabaseManager()) {
+ if (navigation_handle->IsInMainFrame() && database_manager_) {
throttles->push_back(
std::make_unique<SubresourceFilterSafeBrowsingActivationThrottle>(
navigation_handle, profile_interaction_manager_.get(),
- content::GetIOThreadTaskRunner({}),
- client_->GetSafeBrowsingDatabaseManager()));
+ content::GetIOThreadTaskRunner({}), database_manager_));
}
if (!dealer_handle_)
@@ -504,14 +508,14 @@ bool ContentSubresourceFilterThrottleManager::IsFrameTaggedAsAd(
base::Contains(ad_frames_, frame_host->GetFrameTreeNodeId());
}
-base::Optional<LoadPolicy>
+absl::optional<LoadPolicy>
ContentSubresourceFilterThrottleManager::LoadPolicyForLastCommittedNavigation(
content::RenderFrameHost* frame_host) const {
if (!frame_host)
- return base::nullopt;
+ return absl::nullopt;
auto it = navigation_load_policies_.find(frame_host->GetFrameTreeNodeId());
if (it == navigation_load_policies_.end())
- return base::nullopt;
+ return absl::nullopt;
return it->second;
}
@@ -582,12 +586,12 @@ ContentSubresourceFilterThrottleManager::GetParentFrameFilter(
return GetFrameFilter(parent);
}
-const base::Optional<subresource_filter::mojom::ActivationState>
+const absl::optional<subresource_filter::mojom::ActivationState>
ContentSubresourceFilterThrottleManager::GetFrameActivationState(
content::RenderFrameHost* frame_host) {
if (AsyncDocumentSubresourceFilter* filter = GetFrameFilter(frame_host))
return filter->activation_state();
- return base::nullopt;
+ return absl::nullopt;
}
AsyncDocumentSubresourceFilter*
@@ -616,7 +620,7 @@ void ContentSubresourceFilterThrottleManager::MaybeShowNotification() {
return;
}
- profile_interaction_manager_->MaybeShowNotification(client_.get());
+ profile_interaction_manager_->MaybeShowNotification();
current_committed_load_has_notified_disallowed_load_ = true;
}
@@ -705,13 +709,13 @@ void ContentSubresourceFilterThrottleManager::SetIsAdSubframeForTesting(
}
}
-base::Optional<blink::FrameAdEvidence>
+absl::optional<blink::FrameAdEvidence>
ContentSubresourceFilterThrottleManager::GetAdEvidenceForFrame(
content::RenderFrameHost* render_frame_host) {
auto tracked_ad_evidence_it =
tracked_ad_evidence_.find(render_frame_host->GetFrameTreeNodeId());
if (tracked_ad_evidence_it == tracked_ad_evidence_.end())
- return base::nullopt;
+ return absl::nullopt;
return tracked_ad_evidence_it->second;
}
diff --git a/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h b/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
index ae4f41ad80f..af0819d781a 100644
--- a/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
+++ b/chromium/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
@@ -12,10 +12,10 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "base/stl_util.h"
#include "base/supports_user_data.h"
+#include "components/safe_browsing/core/db/database_manager.h"
#include "components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h"
@@ -25,6 +25,7 @@
#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_receiver_set.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/frame/frame_ad_evidence.h"
namespace content {
@@ -40,7 +41,6 @@ class ActivationStateComputingNavigationThrottle;
class PageLoadStatistics;
class ProfileInteractionManager;
class SubresourceFilterProfileContext;
-class SubresourceFilterClient;
// This enum backs a histogram. Make sure new elements are only added to the
// end. Keep histograms.xml up to date with any changes.
@@ -76,10 +76,7 @@ enum class SubresourceFilterAction {
// RenderFrameHosts, along with their associated DocumentSubresourceFilters.
//
// The class is designed to be attached to a WebContents instance by an embedder
-// via CreateForWebContents(), with the embedder passing a
-// SubresourceFilterClient instance customized for that embedder. The client
-// will be notified of the first disallowed subresource load for a top level
-// navgation, and has veto power for frame activation.
+// via CreateForWebContents().
class ContentSubresourceFilterThrottleManager
: public base::SupportsUserData::Data,
public content::WebContentsObserver,
@@ -95,16 +92,18 @@ class ContentSubresourceFilterThrottleManager
// not enabled.
static void CreateForWebContents(
content::WebContents* web_contents,
- std::unique_ptr<SubresourceFilterClient> client,
SubresourceFilterProfileContext* profile_context,
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
+ database_manager,
VerifiedRulesetDealer::Handle* dealer_handle);
static ContentSubresourceFilterThrottleManager* FromWebContents(
content::WebContents* web_contents);
ContentSubresourceFilterThrottleManager(
- std::unique_ptr<SubresourceFilterClient> client,
SubresourceFilterProfileContext* profile_context,
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
+ database_manager,
VerifiedRulesetDealer::Handle* dealer_handle,
content::WebContents* web_contents);
~ContentSubresourceFilterThrottleManager() override;
@@ -124,8 +123,6 @@ class ContentSubresourceFilterThrottleManager
PageLoadStatistics* page_load_statistics() const { return statistics_.get(); }
- SubresourceFilterClient* client() { return client_.get(); }
-
VerifiedRuleset::Handle* ruleset_handle_for_testing() {
return ruleset_handle_.get();
}
@@ -138,10 +135,10 @@ class ContentSubresourceFilterThrottleManager
// the last navigation was not evaluated by the subresource filter in
// |frame_host|. Load policy is determined by presence of the navigation url
// in the filter list.
- base::Optional<LoadPolicy> LoadPolicyForLastCommittedNavigation(
+ absl::optional<LoadPolicy> LoadPolicyForLastCommittedNavigation(
content::RenderFrameHost* frame_host) const;
- // Notifies the client that the user has requested a reload of a page with
+ // Called when the user has requested a reload of a page with
// blocked ads (e.g., via an infobar).
void OnReloadRequested();
@@ -154,11 +151,18 @@ class ContentSubresourceFilterThrottleManager
void SetIsAdSubframeForTesting(content::RenderFrameHost* render_frame_host,
bool is_ad_subframe);
+ // Sets the SafeBrowsingDatabaseManager instance used to |database_manager|.
+ void set_database_manager_for_testing(
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
+ database_manager) {
+ database_manager_ = std::move(database_manager);
+ }
+
// Returns the matching FrameAdEvidence for the frame indicated by
- // `render_frame_host` or `base::nullopt` if there is none (i.e. the frame is
+ // `render_frame_host` or `absl::nullopt` if there is none (i.e. the frame is
// a main frame, or no navigation or commit has yet occurred and no evidence
// has been reported by the renderer).
- base::Optional<blink::FrameAdEvidence> GetAdEvidenceForFrame(
+ absl::optional<blink::FrameAdEvidence> GetAdEvidenceForFrame(
content::RenderFrameHost* render_frame_host);
protected:
@@ -208,12 +212,12 @@ class ContentSubresourceFilterThrottleManager
content::RenderFrameHost* frame_host);
// Returns the activation state of the frame's filter. If the frame is not
- // activated (and therefore has no subresource filter), returns base::nullopt.
- const base::Optional<subresource_filter::mojom::ActivationState>
+ // activated (and therefore has no subresource filter), returns absl::nullopt.
+ const absl::optional<subresource_filter::mojom::ActivationState>
GetFrameActivationState(content::RenderFrameHost* frame_host);
- // Calls ShowNotification on |client_| at most once per committed,
- // non-same-page navigation in the main frame.
+ // Calls MaybeShowNotification on |profile_interaction_manager_| at most once
+ // per committed, non-same-page navigation in the main frame.
void MaybeShowNotification();
VerifiedRuleset::Handle* EnsureRulesetHandle();
@@ -222,6 +226,9 @@ class ContentSubresourceFilterThrottleManager
blink::FrameAdEvidence& EnsureFrameAdEvidence(
content::RenderFrameHost* render_frame_host);
+ mojom::ActivationState ActivationStateForNextCommittedLoad(
+ content::NavigationHandle* navigation_handle);
+
// Registers `render_frame_host` as an ad frame. If the frame later moves to
// a new process its RenderHost will be told that it's an ad.
void OnFrameIsAdSubframe(content::RenderFrameHost* render_frame_host);
@@ -316,7 +323,7 @@ class ContentSubresourceFilterThrottleManager
// This member outlives this class.
VerifiedRulesetDealer::Handle* dealer_handle_;
- std::unique_ptr<SubresourceFilterClient> client_;
+ scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager_;
std::unique_ptr<ProfileInteractionManager> profile_interaction_manager_;
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 9cdd0ad304d..39137fe9b27 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,10 +21,16 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "components/content_settings/browser/page_specific_content_settings.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/infobars/content/content_infobar_manager.h"
+#include "components/infobars/core/confirm_infobar_delegate.h"
+#include "components/infobars/core/infobar.h"
#include "components/subresource_filter/content/browser/async_document_subresource_filter.h"
+#include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h"
#include "components/subresource_filter/content/browser/subframe_navigation_test_utils.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h"
-#include "components/subresource_filter/content/browser/test_subresource_filter_client.h"
+#include "components/subresource_filter/content/browser/throttle_manager_test_support.h"
#include "components/subresource_filter/content/mojom/subresource_filter_agent.mojom.h"
#include "components/subresource_filter/core/browser/subresource_filter_features.h"
#include "components/subresource_filter/core/common/common_features.h"
@@ -80,10 +86,10 @@ class FakeSubresourceFilterAgent : public mojom::SubresourceFilterAgent {
// mojom::SubresourceFilterAgent:
void ActivateForNextCommittedLoad(
mojom::ActivationStatePtr activation_state,
- blink::mojom::AdFrameType ad_frame_type =
- blink::mojom::AdFrameType::kNonAd) override {
+ const absl::optional<blink::FrameAdEvidence>& ad_evidence) override {
last_activation_ = std::move(activation_state);
- is_ad_subframe_ = ad_frame_type != blink::mojom::AdFrameType::kNonAd;
+ is_ad_subframe_ =
+ ad_evidence.has_value() && ad_evidence->IndicatesAdSubframe();
}
// These methods reset state back to default when they are called.
@@ -92,9 +98,11 @@ class FakeSubresourceFilterAgent : public mojom::SubresourceFilterAgent {
is_ad_subframe_ = false;
return is_ad_subframe;
}
- bool LastActivated() {
- bool activated = last_activation_ && last_activation_->activation_level !=
- mojom::ActivationLevel::kDisabled;
+ absl::optional<bool> LastActivated() {
+ if (!last_activation_)
+ return absl::nullopt;
+ bool activated =
+ last_activation_->activation_level != mojom::ActivationLevel::kDisabled;
last_activation_.reset();
return activated;
}
@@ -198,39 +206,43 @@ class ContentSubresourceFilterThrottleManagerTest
/*expected_checksum=*/0,
base::DoNothing());
- auto subresource_filter_client =
- std::make_unique<TestSubresourceFilterClient>(web_contents);
- client_ = subresource_filter_client.get();
+ throttle_manager_test_support_ =
+ std::make_unique<ThrottleManagerTestSupport>(web_contents);
// Turn off smart UI to make it easier to reason about expectations on
// ShowNotification() being invoked.
- client_->SetShouldUseSmartUI(false);
+ throttle_manager_test_support_->SetShouldUseSmartUI(false);
+
throttle_manager_ =
std::make_unique<ContentSubresourceFilterThrottleManager>(
- std::move(subresource_filter_client), client_->profile_context(),
- dealer_handle_.get(), web_contents);
+ throttle_manager_test_support_->profile_context(),
+ /*database_manager=*/nullptr, dealer_handle_.get(), web_contents);
Observe(web_contents);
}
void TearDown() override {
- client_ = nullptr;
throttle_manager_.reset();
+ throttle_manager_test_support_.reset();
dealer_handle_.reset();
base::RunLoop().RunUntilIdle();
content::RenderViewHostTestHarness::TearDown();
}
- void ExpectActivationSignalForFrame(content::RenderFrameHost* rfh,
- bool expect_activation,
- bool expect_is_ad_subframe = false) {
+ void ExpectActivationSignalForFrame(
+ content::RenderFrameHost* rfh,
+ bool expect_activation,
+ bool expect_is_ad_subframe = false,
+ bool expect_activation_sent_to_agent = true) {
// In some cases we need to verify that messages were _not_ sent, in which
// case using a Wait() idiom would cause hangs. RunUntilIdle instead to
// ensure mojo calls make it to the fake agent.
base::RunLoop().RunUntilIdle();
FakeSubresourceFilterAgent* agent = agent_map_[rfh].get();
- EXPECT_EQ(expect_activation, agent->LastActivated());
+ absl::optional<bool> last_activated = agent->LastActivated();
+ EXPECT_EQ(expect_activation, last_activated && *last_activated);
EXPECT_EQ(expect_is_ad_subframe, agent->LastAdSubframe());
+ EXPECT_EQ(expect_activation_sent_to_agent, last_activated.has_value());
}
// Helper methods:
@@ -269,8 +281,28 @@ class ContentSubresourceFilterThrottleManagerTest
return throttle_manager_->ruleset_handle_for_testing();
}
- int disallowed_notification_count() const {
- return client_->disallowed_notification_count();
+ bool ads_blocked_in_content_settings() {
+ auto* content_settings =
+ content_settings::PageSpecificContentSettings::GetForFrame(
+ content::RenderViewHostTestHarness::web_contents()->GetMainFrame());
+
+ return content_settings->IsContentBlocked(ContentSettingsType::ADS);
+ }
+
+ bool presenting_ads_blocked_infobar() {
+ auto* infobar_manager = infobars::ContentInfoBarManager::FromWebContents(
+ content::RenderViewHostTestHarness::web_contents());
+ if (infobar_manager->infobar_count() == 0)
+ return false;
+
+ // No infobars other than the ads blocked infobar should be displayed in the
+ // context of these tests.
+ EXPECT_EQ(infobar_manager->infobar_count(), 1u);
+ auto* infobar = infobar_manager->infobar_at(0);
+ EXPECT_EQ(infobar->delegate()->GetIdentifier(),
+ infobars::InfoBarDelegate::ADS_BLOCKED_INFOBAR_DELEGATE_ANDROID);
+
+ return true;
}
protected:
@@ -329,7 +361,11 @@ class ContentSubresourceFilterThrottleManagerTest
}
void CreateSafeBrowsingDatabaseManager() {
- client_->CreateSafeBrowsingDatabaseManager();
+ scoped_refptr<FakeSafeBrowsingDatabaseManager> database_manager =
+ base::MakeRefCounted<FakeSafeBrowsingDatabaseManager>();
+
+ throttle_manager_->set_database_manager_for_testing(
+ std::move(database_manager));
}
VerifiedRulesetDealer::Handle* dealer_handle() {
@@ -339,7 +375,7 @@ class ContentSubresourceFilterThrottleManagerTest
private:
testing::TestRulesetCreator test_ruleset_creator_;
testing::TestRulesetPair test_ruleset_pair_;
- TestSubresourceFilterClient* client_;
+ std::unique_ptr<ThrottleManagerTestSupport> throttle_manager_test_support_;
std::unique_ptr<VerifiedRulesetDealer::Handle> dealer_handle_;
@@ -373,8 +409,32 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
+}
+
+#if defined(OS_ANDROID)
+TEST_P(ContentSubresourceFilterThrottleManagerTest,
+ NoCrashWhenInfoBarManagerIsNotPresent) {
+ auto* web_contents = RenderViewHostTestHarness::web_contents();
+ web_contents->RemoveUserData(infobars::ContentInfoBarManager::UserDataKey());
+
+ // Commit a navigation that triggers page level activation.
+ NavigateAndCommitMainFrame(GURL(kTestURLWithActivation));
+ ExpectActivationSignalForFrame(main_rfh(), true /* expect_activation */);
+
+ // A disallowed subframe navigation should be successfully filtered, and the
+ // lack of infobar manager should not cause a crash.
+ CreateSubframeWithTestNavigation(
+ GURL("https://www.example.com/disallowed.html"), main_rfh());
+ EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
+ SimulateStartAndGetResult(navigation_simulator()));
+
+ EXPECT_TRUE(ads_blocked_in_content_settings());
}
+#endif
TEST_P(ContentSubresourceFilterThrottleManagerTest, NoPageActivation) {
// This test assumes that we're not in DryRun mode.
@@ -391,7 +451,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, NoPageActivation) {
GURL("https://www.example.com/disallowed.html"), main_rfh());
EXPECT_EQ(content::NavigationThrottle::PROCEED,
SimulateCommitAndGetResult(navigation_simulator()));
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
@@ -413,7 +476,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
ExpectActivationSignalForFrame(child, true /* expect_activation */,
true /* is_ad_subframe */);
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
@@ -432,7 +498,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
SimulateRedirectAndGetResult(
navigation_simulator(),
GURL("https://www.example.com/disallowed.html")));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
@@ -456,7 +525,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(child, true /* expect_activation */);
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
}
// This should fail if the throttle manager notifies the delegate twice of a
@@ -473,14 +545,20 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/2/disallowed.html"), main_rfh());
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
@@ -495,24 +573,35 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
// Commit another navigation that triggers page level activation.
NavigateAndCommitMainFrame(GURL(kTestURLWithActivation2));
ExpectActivationSignalForFrame(main_rfh(), true /* expect_activation */);
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
+
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/2/disallowed.html"), main_rfh());
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(2, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
-// Test that the disallow load notification will not be repeated for the first
-// disallowed load that follows a same-document navigation.
+// Test that once presented, the ads blocked infobar will remain present after a
+// same-document navigation.
TEST_P(ContentSubresourceFilterThrottleManagerTest,
- ActivateMainFrameDoNotNotifyAfterSameDocumentNav) {
+ InfoBarStaysPresentAfterSameDocumentNav) {
// Commit a navigation that triggers page level activation.
NavigateAndCommitMainFrame(GURL(kTestURLWithActivation));
ExpectActivationSignalForFrame(main_rfh(), true /* expect_activation */);
@@ -523,20 +612,36 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
// Commit another navigation that triggers page level activation.
GURL url2 = GURL(base::StringPrintf("%s#ref", kTestURLWithActivation));
CreateTestNavigation(url2, main_rfh());
navigation_simulator()->CommitSameDocument();
- ExpectActivationSignalForFrame(main_rfh(), false /* expect_activation */);
+
+ // Same-document navigations do not pass through ReadyToCommitNavigation so no
+ // ActivateForNextCommittedLoad mojo call is expected.
+ ExpectActivationSignalForFrame(main_rfh(), false /* expect_activation */,
+ false /* expect_is_ad_subframe */,
+ false /* expect_activation_sent_to_agent */);
+
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/2/disallowed.html"), main_rfh());
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
@@ -559,7 +664,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(child, false /* expect_activation */);
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
}
// Once there are no activated frames, the manager drops its ruleset handle. If
@@ -573,7 +681,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, RulesetHandleRegeneration) {
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
// Simulate a renderer crash which should delete the frame.
EXPECT_TRUE(ManagerHasRulesetHandle());
@@ -584,12 +695,20 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, RulesetHandleRegeneration) {
NavigateAndCommitMainFrame(GURL(kTestURLWithActivation));
ExpectActivationSignalForFrame(main_rfh(), true /* expect_activation */);
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
+
CreateSubframeWithTestNavigation(
GURL("https://www.example.com/disallowed.html"), main_rfh());
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(2, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
@@ -620,7 +739,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(child, false /* expect_activation */);
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
@@ -635,7 +757,12 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
CreateTestNavigation(same_site_inactive_url, main_rfh());
SimulateFailedNavigation(navigation_simulator(), net::ERR_ABORTED);
EXPECT_TRUE(ManagerHasRulesetHandle());
- ExpectActivationSignalForFrame(main_rfh(), false /* expect_activation */);
+
+ // The aborted navigation does not pass through ReadyToCommitNavigation so no
+ // ActivateForNextCommittedLoad mojo call is expected.
+ ExpectActivationSignalForFrame(main_rfh(), false /* expect_activation */,
+ false /* expect_is_ad_subframe */,
+ false /* expect_activation_sent_to_agent */);
// A subframe navigation fail.
CreateSubframeWithTestNavigation(
@@ -643,7 +770,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
@@ -670,7 +800,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(child, false /* expect_activation */);
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
}
// Ensure activation propagates into great-grandchild frames, including cross
@@ -709,7 +842,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest, ActivationPropagation) {
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
// Ensure activation propagates through allowlisted documents.
@@ -745,7 +881,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(subframe2, true /* expect_activation */);
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
// An identical series of events that don't match allowlist rules cause
// filtering.
@@ -764,7 +903,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
// Same-site navigations within a single RFH do not persist activation.
@@ -793,7 +935,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
navigation_simulator()->GetFinalRenderFrameHost();
ExpectActivationSignalForFrame(child, false /* expect_activation */);
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
}
TEST_F(ContentSubresourceFilterThrottleManagerTest, CreateForWebContents) {
@@ -803,9 +948,9 @@ TEST_F(ContentSubresourceFilterThrottleManagerTest, CreateForWebContents) {
web_contents.get()),
nullptr);
- auto client =
- std::make_unique<TestSubresourceFilterClient>(web_contents.get());
- SubresourceFilterProfileContext* profile_context = client->profile_context();
+ ThrottleManagerTestSupport throttle_manager_test_support(web_contents.get());
+ SubresourceFilterProfileContext* profile_context =
+ throttle_manager_test_support.profile_context();
{
base::test::ScopedFeatureList scoped_feature;
@@ -814,7 +959,7 @@ TEST_F(ContentSubresourceFilterThrottleManagerTest, CreateForWebContents) {
// CreateForWebContents() should not do anything if the subresource filter
// feature is not enabled.
ContentSubresourceFilterThrottleManager::CreateForWebContents(
- web_contents.get(), std::move(client), profile_context,
+ web_contents.get(), profile_context, /*database_manager=*/nullptr,
dealer_handle());
EXPECT_EQ(ContentSubresourceFilterThrottleManager::FromWebContents(
web_contents.get()),
@@ -823,20 +968,18 @@ TEST_F(ContentSubresourceFilterThrottleManagerTest, CreateForWebContents) {
// If the subresource filter feature is enabled (as it is by default),
// CreateForWebContents() should create and attach an instance.
- client = std::make_unique<TestSubresourceFilterClient>(web_contents.get());
- profile_context = client->profile_context();
ContentSubresourceFilterThrottleManager::CreateForWebContents(
- web_contents.get(), std::move(client), profile_context, dealer_handle());
+ web_contents.get(), profile_context,
+ /*database_manager=*/nullptr, dealer_handle());
auto* throttle_manager =
ContentSubresourceFilterThrottleManager::FromWebContents(
web_contents.get());
EXPECT_NE(throttle_manager, nullptr);
// A second call should not attach a different instance.
- client = std::make_unique<TestSubresourceFilterClient>(web_contents.get());
- profile_context = client->profile_context();
ContentSubresourceFilterThrottleManager::CreateForWebContents(
- web_contents.get(), std::move(client), profile_context, dealer_handle());
+ web_contents.get(), profile_context,
+ /*database_manager=*/nullptr, dealer_handle());
EXPECT_EQ(ContentSubresourceFilterThrottleManager::FromWebContents(
web_contents.get()),
throttle_manager);
@@ -916,7 +1059,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
SimulateStartAndGetResult(navigation_simulator()));
- EXPECT_EQ(1, disallowed_notification_count());
+ EXPECT_TRUE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
// If the RenderFrame determines that the frame is an ad due to creation by ad
@@ -1085,7 +1231,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
true /* is_ad_subframe */);
EXPECT_TRUE(throttle_manager()->IsFrameTaggedAsAd(greatGrandchild));
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
@@ -1121,7 +1270,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
false /* is_ad_subframe */);
EXPECT_FALSE(throttle_manager()->IsFrameTaggedAsAd(grandchild));
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(ContentSubresourceFilterThrottleManagerTest,
@@ -1133,7 +1285,10 @@ TEST_P(ContentSubresourceFilterThrottleManagerTest,
// This could happen e.g. for cross-process navigations, which have no
// ordering guarantees.
throttle_manager()->DidDisallowFirstSubresource();
- EXPECT_EQ(0, disallowed_notification_count());
+ EXPECT_FALSE(ads_blocked_in_content_settings());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
}
// TODO(csharrison): Make sure the following conditions are exercised in tests:
diff --git a/chromium/components/subresource_filter/content/browser/profile_interaction_manager.cc b/chromium/components/subresource_filter/content/browser/profile_interaction_manager.cc
index b9c8e16c9bb..f7369ec0936 100644
--- a/chromium/components/subresource_filter/content/browser/profile_interaction_manager.cc
+++ b/chromium/components/subresource_filter/content/browser/profile_interaction_manager.cc
@@ -9,7 +9,6 @@
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/subresource_filter/content/browser/ads_intervention_manager.h"
#include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h"
-#include "components/subresource_filter/content/browser/subresource_filter_client.h"
#include "components/subresource_filter/content/browser/subresource_filter_content_settings_manager.h"
#include "components/subresource_filter/content/browser/subresource_filter_profile_context.h"
#include "content/public/browser/navigation_controller.h"
@@ -17,6 +16,11 @@
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#if defined(OS_ANDROID)
+#include "components/infobars/content/content_infobar_manager.h" // nogncheck
+#include "components/subresource_filter/content/browser/ads_blocked_infobar_delegate.h"
+#endif
+
namespace subresource_filter {
ProfileInteractionManager::ProfileInteractionManager(
@@ -66,7 +70,7 @@ void ProfileInteractionManager::OnAdsViolationTriggered(
// TODO(https://crbug.com/1131971): Add support for enabling ads interventions
// separately for different ads violations.
const GURL& url = rfh->GetLastCommittedURL();
- base::Optional<AdsInterventionManager::LastAdsIntervention>
+ absl::optional<AdsInterventionManager::LastAdsIntervention>
last_intervention =
profile_context_->ads_intervention_manager()->GetLastAdsIntervention(
url);
@@ -119,12 +123,18 @@ mojom::ActivationLevel ProfileInteractionManager::OnPageActivationComputed(
return effective_activation_level;
}
-void ProfileInteractionManager::MaybeShowNotification(
- SubresourceFilterClient* client) {
+void ProfileInteractionManager::MaybeShowNotification() {
const GURL& top_level_url = web_contents()->GetLastCommittedURL();
if (profile_context_->settings_manager()->ShouldShowUIForSite(
top_level_url)) {
- client->ShowNotification();
+#if defined(OS_ANDROID)
+ // NOTE: It is acceptable for the embedder to not have installed an infobar
+ // manager.
+ if (auto* infobar_manager =
+ infobars::ContentInfoBarManager::FromWebContents(web_contents())) {
+ subresource_filter::AdsBlockedInfobarDelegate::Create(infobar_manager);
+ }
+#endif
// TODO(https://crbug.com/1103176): Plumb the actual frame reference here
// (it comes from
diff --git a/chromium/components/subresource_filter/content/browser/profile_interaction_manager.h b/chromium/components/subresource_filter/content/browser/profile_interaction_manager.h
index 21d15076370..c976b122942 100644
--- a/chromium/components/subresource_filter/content/browser/profile_interaction_manager.h
+++ b/chromium/components/subresource_filter/content/browser/profile_interaction_manager.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_PROFILE_INTERACTION_MANAGER_H_
#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_PROFILE_INTERACTION_MANAGER_H_
+#include "build/build_config.h"
#include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h"
#include "components/subresource_filter/core/common/activation_decision.h"
#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h"
@@ -17,7 +18,6 @@ class WebContents;
namespace subresource_filter {
-class SubresourceFilterClient;
class SubresourceFilterProfileContext;
// Class that manages interaction between interaction between the
@@ -49,9 +49,10 @@ class ProfileInteractionManager
// Invoked when a notification should potentially be shown to the user that
// ads are being blocked on this page. Will make the final determination as to
- // whether the notification should be shown and call out to |client| to show
- // the notification if so.
- void MaybeShowNotification(SubresourceFilterClient* client);
+ // whether the notification should be shown. On Android this will show an
+ // infobar if appropriate and if an infobar::ContentInfoBarManager instance
+ // has been installed in web_contents() by the embedder.
+ void MaybeShowNotification();
// SubresourceFilterSafeBrowsingActivationThrottle::Delegate:
mojom::ActivationLevel OnPageActivationComputed(
diff --git a/chromium/components/subresource_filter/content/browser/ruleset_publisher.h b/chromium/components/subresource_filter/content/browser/ruleset_publisher.h
index 725f6df0dc1..24a68e01e48 100644
--- a/chromium/components/subresource_filter/content/browser/ruleset_publisher.h
+++ b/chromium/components/subresource_filter/content/browser/ruleset_publisher.h
@@ -50,4 +50,4 @@ class RulesetPublisher {
} // namespace subresource_filter
-#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_RULESET_SERVICE_H_
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_RULESET_PUBLISHER_H_
diff --git a/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl.h b/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl.h
index ba1d2c0cba1..211aca03c07 100644
--- a/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl.h
+++ b/chromium/components/subresource_filter/content/browser/ruleset_publisher_impl.h
@@ -76,4 +76,4 @@ class RulesetPublisherImpl : public RulesetPublisher,
} // namespace subresource_filter
-#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_RULESET_SERVICE_H_
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_RULESET_PUBLISHER_IMPL_H_
diff --git a/chromium/components/subresource_filter/content/browser/ruleset_service.h b/chromium/components/subresource_filter/content/browser/ruleset_service.h
index 33a3176e018..c2bb66feab4 100644
--- a/chromium/components/subresource_filter/content/browser/ruleset_service.h
+++ b/chromium/components/subresource_filter/content/browser/ruleset_service.h
@@ -33,7 +33,6 @@
#include <stdint.h>
#include <memory>
-#include <string>
#include <vector>
#include "base/callback.h"
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 c9e73d4cfd6..156bd93f3e2 100644
--- a/chromium/components/subresource_filter/content/browser/ruleset_service_unittest.cc
+++ b/chromium/components/subresource_filter/content/browser/ruleset_service_unittest.cc
@@ -876,9 +876,7 @@ TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_ParseFailure) {
mock_publisher()->RunBestEffortUntilIdle();
const std::string kGarbage(10000, '\xff');
- ASSERT_TRUE(base::AppendToFile(test_ruleset_1().unindexed.path,
- kGarbage.data(),
- static_cast<int>(kGarbage.size())));
+ ASSERT_TRUE(base::AppendToFile(test_ruleset_1().unindexed.path, kGarbage));
WaitForIndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
kTestContentVersion1);
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 6064ad100e7..8f5a9b405b6 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
@@ -278,7 +278,7 @@ TEST_F(SubframeNavigationFilteringThrottleTest, DelayMetrics) {
InitializeDocumentSubresourceFilter(GURL("https://example.test"));
CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
main_rfh());
- navigation_simulator()->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
+ navigation_simulator()->SetTransition(ui::PAGE_TRANSITION_AUTO_SUBFRAME);
EXPECT_EQ(content::NavigationThrottle::PROCEED,
SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE,
@@ -316,7 +316,7 @@ TEST_F(SubframeNavigationFilteringThrottleTest, DelayMetricsDryRun) {
mojom::ActivationLevel::kDryRun);
CreateTestSubframeAndInitNavigation(GURL("https://example.test/allowed.html"),
main_rfh());
- navigation_simulator()->SetTransition(ui::PAGE_TRANSITION_MANUAL_SUBFRAME);
+ navigation_simulator()->SetTransition(ui::PAGE_TRANSITION_AUTO_SUBFRAME);
EXPECT_EQ(content::NavigationThrottle::PROCEED,
SimulateStartAndGetResult(navigation_simulator()));
EXPECT_EQ(content::NavigationThrottle::PROCEED,
diff --git a/chromium/components/subresource_filter/content/browser/subresource_filter_client.h b/chromium/components/subresource_filter/content/browser/subresource_filter_client.h
deleted file mode 100644
index fafc62eb8bb..00000000000
--- a/chromium/components/subresource_filter/content/browser/subresource_filter_client.h
+++ /dev/null
@@ -1,32 +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_SUBRESOURCE_FILTER_CONTENT_BROWSER_SUBRESOURCE_FILTER_CLIENT_H_
-#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_SUBRESOURCE_FILTER_CLIENT_H_
-
-#include "base/memory/scoped_refptr.h"
-
-namespace safe_browsing {
-class SafeBrowsingDatabaseManager;
-}
-
-namespace subresource_filter {
-
-class SubresourceFilterClient {
- public:
- virtual ~SubresourceFilterClient() = default;
-
- // Informs the embedder to show some UI indicating that resources are being
- // blocked. This method will be called at most once per main-frame navigation.
- virtual void ShowNotification() = 0;
-
- // Returns the SafeBrowsingDatabaseManager instance associated with this
- // client, or null if there is no such instance.
- virtual const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
- GetSafeBrowsingDatabaseManager() = 0;
-};
-
-} // namespace subresource_filter
-
-#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_SUBRESOURCE_FILTER_CLIENT_H_
diff --git a/chromium/components/subresource_filter/content/browser/subresource_filter_content_settings_manager.cc b/chromium/components/subresource_filter/content/browser/subresource_filter_content_settings_manager.cc
index 2ed324f0835..c9818050159 100644
--- a/chromium/components/subresource_filter/content/browser/subresource_filter_content_settings_manager.cc
+++ b/chromium/components/subresource_filter/content/browser/subresource_filter_content_settings_manager.cc
@@ -161,7 +161,7 @@ void SubresourceFilterContentSettingsManager::SetSiteMetadata(
// was previously set.
base::Time expiry_time = base::Time::Now() + kMaxPersistMetadataDuration;
if (dict && dict->HasKey(kNonRenewingExpiryTime)) {
- base::Optional<double> metadata_expiry_time =
+ absl::optional<double> metadata_expiry_time =
dict->FindDoubleKey(kNonRenewingExpiryTime);
DCHECK(metadata_expiry_time);
expiry_time = base::Time::FromDoubleT(*metadata_expiry_time);
@@ -194,7 +194,7 @@ bool SubresourceFilterContentSettingsManager::ShouldDeleteDataWithNoActivation(
if (!dict)
return true;
- base::Optional<double> metadata_expiry_time =
+ absl::optional<double> metadata_expiry_time =
dict->FindDoubleKey(kNonRenewingExpiryTime);
if (!metadata_expiry_time)
@@ -213,7 +213,7 @@ bool SubresourceFilterContentSettingsManager::GetSiteActivationFromMetadata(
if (!dict)
return false;
- base::Optional<bool> site_activation_status =
+ absl::optional<bool> site_activation_status =
dict->FindBoolKey(kActivatedKey);
// If there is no explicit site activation status, it is metadata V1:
diff --git a/chromium/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.cc b/chromium/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.cc
index c6f9d9afb3b..1b8f08499a6 100644
--- a/chromium/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.cc
+++ b/chromium/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.cc
@@ -71,12 +71,12 @@ void TestSubresourceFilterObserver::DidFinishNavigation(
}
}
-base::Optional<mojom::ActivationLevel>
+absl::optional<mojom::ActivationLevel>
TestSubresourceFilterObserver::GetPageActivation(const GURL& url) const {
auto it = page_activations_.find(url);
if (it != page_activations_.end())
return it->second;
- return base::nullopt;
+ return absl::nullopt;
}
bool TestSubresourceFilterObserver::GetIsAdSubframe(
@@ -84,25 +84,25 @@ bool TestSubresourceFilterObserver::GetIsAdSubframe(
return base::Contains(ad_frames_, frame_tree_node_id);
}
-base::Optional<LoadPolicy> TestSubresourceFilterObserver::GetSubframeLoadPolicy(
+absl::optional<LoadPolicy> TestSubresourceFilterObserver::GetSubframeLoadPolicy(
const GURL& url) const {
auto it = subframe_load_evaluations_.find(url);
if (it != subframe_load_evaluations_.end())
return it->second;
- return base::Optional<LoadPolicy>();
+ return absl::optional<LoadPolicy>();
}
-base::Optional<mojom::ActivationLevel>
+absl::optional<mojom::ActivationLevel>
TestSubresourceFilterObserver::GetPageActivationForLastCommittedLoad() const {
return last_committed_activation_;
}
-base::Optional<TestSubresourceFilterObserver::SafeBrowsingCheck>
+absl::optional<TestSubresourceFilterObserver::SafeBrowsingCheck>
TestSubresourceFilterObserver::GetSafeBrowsingResult(const GURL& url) const {
auto it = safe_browsing_checks_.find(url);
if (it != safe_browsing_checks_.end())
return it->second;
- return base::Optional<SafeBrowsingCheck>();
+ return absl::optional<SafeBrowsingCheck>();
}
} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h b/chromium/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h
index 40fed6e66db..c29dc3f3120 100644
--- a/chromium/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h
+++ b/chromium/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h
@@ -10,7 +10,6 @@
#include <utility>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "components/safe_browsing/core/db/util.h"
#include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
@@ -19,6 +18,7 @@
#include "components/subresource_filter/core/common/load_policy.h"
#include "components/subresource_filter/core/mojom/subresource_filter.mojom.h"
#include "content/public/browser/web_contents_observer.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace content {
@@ -52,18 +52,18 @@ class TestSubresourceFilterObserver : public SubresourceFilterObserver,
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
- base::Optional<mojom::ActivationLevel> GetPageActivation(
+ absl::optional<mojom::ActivationLevel> GetPageActivation(
const GURL& url) const;
- base::Optional<LoadPolicy> GetSubframeLoadPolicy(const GURL& url) const;
+ absl::optional<LoadPolicy> GetSubframeLoadPolicy(const GURL& url) const;
bool GetIsAdSubframe(int frame_tree_node_id) const;
- base::Optional<mojom::ActivationLevel> GetPageActivationForLastCommittedLoad()
+ absl::optional<mojom::ActivationLevel> GetPageActivationForLastCommittedLoad()
const;
using SafeBrowsingCheck =
std::pair<safe_browsing::SBThreatType, safe_browsing::ThreatMetadata>;
- base::Optional<SafeBrowsingCheck> GetSafeBrowsingResult(
+ absl::optional<SafeBrowsingCheck> GetSafeBrowsingResult(
const GURL& url) const;
private:
@@ -76,7 +76,7 @@ class TestSubresourceFilterObserver : public SubresourceFilterObserver,
std::map<GURL, SafeBrowsingCheck> safe_browsing_checks_;
std::map<content::NavigationHandle*, mojom::ActivationLevel>
pending_activations_;
- base::Optional<mojom::ActivationLevel> last_committed_activation_;
+ absl::optional<mojom::ActivationLevel> last_committed_activation_;
base::ScopedObservation<SubresourceFilterObserverManager,
SubresourceFilterObserver>
diff --git a/chromium/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc b/chromium/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
index 6a6d09bdcac..de31a2a9d72 100644
--- a/chromium/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
+++ b/chromium/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/timer/timer.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
@@ -26,6 +25,7 @@
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
@@ -37,7 +37,7 @@ namespace {
using CheckResults =
std::vector<SubresourceFilterSafeBrowsingClient::CheckResult>;
-base::Optional<RedirectPosition> GetEnforcementRedirectPosition(
+absl::optional<RedirectPosition> GetEnforcementRedirectPosition(
const CheckResults& results) {
// Safe cast since we have strict limits on HTTP redirects.
int num_results = static_cast<int>(results.size());
@@ -55,7 +55,7 @@ base::Optional<RedirectPosition> GetEnforcementRedirectPosition(
return RedirectPosition::kMiddle;
}
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace
diff --git a/chromium/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/chromium/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
index 0c4c96d1a60..5f21178267c 100644
--- a/chromium/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
+++ b/chromium/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -19,13 +19,16 @@
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
+#include "components/infobars/content/content_infobar_manager.h"
+#include "components/infobars/core/confirm_infobar_delegate.h"
+#include "components/infobars/core/infobar.h"
#include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h"
#include "components/subresource_filter/content/browser/devtools_interaction_tracker.h"
#include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h"
#include "components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h"
#include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.h"
#include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.h"
-#include "components/subresource_filter/content/browser/test_subresource_filter_client.h"
+#include "components/subresource_filter/content/browser/throttle_manager_test_support.h"
#include "components/subresource_filter/content/browser/verified_ruleset_dealer.h"
#include "components/subresource_filter/core/browser/subresource_filter_features.h"
#include "components/subresource_filter/core/browser/subresource_filter_features_test_support.h"
@@ -161,13 +164,12 @@ class SubresourceFilterSafeBrowsingActivationThrottleTest
base::DoNothing());
auto* contents = RenderViewHostTestHarness::web_contents();
- auto subresource_filter_client =
- std::make_unique<TestSubresourceFilterClient>(contents);
- client_ = subresource_filter_client.get();
+ throttle_manager_test_support_ =
+ std::make_unique<ThrottleManagerTestSupport>(contents);
throttle_manager_ =
std::make_unique<ContentSubresourceFilterThrottleManager>(
- std::move(subresource_filter_client), client_->profile_context(),
- ruleset_dealer_.get(), contents);
+ throttle_manager_test_support_->profile_context(),
+ /*database_manager=*/nullptr, ruleset_dealer_.get(), contents);
fake_safe_browsing_database_ = new FakeSafeBrowsingDatabaseManager();
NavigateAndCommit(GURL("https://test.com"));
Observe(contents);
@@ -327,8 +329,6 @@ class SubresourceFilterSafeBrowsingActivationThrottleTest
const base::HistogramTester& tester() const { return tester_; }
- TestSubresourceFilterClient* client() { return client_; }
-
TestSafeBrowsingActivationThrottleDelegate* delegate() { return &delegate_; }
base::TestMockTimeTaskRunner* test_io_task_runner() const {
return test_io_task_runner_.get();
@@ -338,6 +338,22 @@ class SubresourceFilterSafeBrowsingActivationThrottleTest
return &scoped_configuration_;
}
+ bool presenting_ads_blocked_infobar() {
+ auto* infobar_manager = infobars::ContentInfoBarManager::FromWebContents(
+ content::RenderViewHostTestHarness::web_contents());
+ if (infobar_manager->infobar_count() == 0)
+ return false;
+
+ // No infobars other than the ads blocked infobar should be displayed in the
+ // context of these tests.
+ EXPECT_EQ(infobar_manager->infobar_count(), 1u);
+ auto* infobar = infobar_manager->infobar_at(0);
+ EXPECT_EQ(infobar->delegate()->GetIdentifier(),
+ infobars::InfoBarDelegate::ADS_BLOCKED_INFOBAR_DELEGATE_ANDROID);
+
+ return true;
+ }
+
private:
testing::ScopedSubresourceFilterConfigurator scoped_configuration_;
scoped_refptr<base::TestMockTimeTaskRunner> test_io_task_runner_;
@@ -351,7 +367,7 @@ class SubresourceFilterSafeBrowsingActivationThrottleTest
std::unique_ptr<ContentSubresourceFilterThrottleManager> throttle_manager_;
std::unique_ptr<content::NavigationSimulator> navigation_simulator_;
- TestSubresourceFilterClient* client_;
+ std::unique_ptr<ThrottleManagerTestSupport> throttle_manager_test_support_;
std::unique_ptr<TestSubresourceFilterObserver> observer_;
scoped_refptr<FakeSafeBrowsingDatabaseManager> fake_safe_browsing_database_;
base::HistogramTester tester_;
@@ -545,11 +561,11 @@ TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest,
TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest,
NavigationFails_NoActivation) {
- EXPECT_EQ(base::Optional<mojom::ActivationLevel>(),
+ EXPECT_EQ(absl::optional<mojom::ActivationLevel>(),
observer()->GetPageActivationForLastCommittedLoad());
content::NavigationSimulator::NavigateAndFailFromDocument(
GURL(kURL), net::ERR_TIMED_OUT, main_rfh());
- EXPECT_EQ(base::Optional<mojom::ActivationLevel>(),
+ EXPECT_EQ(absl::optional<mojom::ActivationLevel>(),
observer()->GetPageActivationForLastCommittedLoad());
}
@@ -560,7 +576,9 @@ TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest,
content::RenderFrameHost* rfh = SimulateNavigateAndCommit({url}, main_rfh());
EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(rfh));
- EXPECT_EQ(1, client()->disallowed_notification_count());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest, ActivationList) {
@@ -728,7 +746,9 @@ TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest,
// Navigate initially, should be no activation.
SimulateNavigateAndCommit({url}, main_rfh());
EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh()));
- EXPECT_EQ(0, client()->disallowed_notification_count());
+#if defined(OS_ANDROID)
+ EXPECT_FALSE(presenting_ads_blocked_infobar());
+#endif
// Simulate opening devtools and forcing activation.
devtools_interaction_tracker->ToggleForceActivation(true);
@@ -738,7 +758,9 @@ TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest,
SimulateNavigateAndCommit({url}, main_rfh());
EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh()));
- EXPECT_EQ(1, client()->disallowed_notification_count());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
histogram_tester.ExpectBucketCount(
"SubresourceFilter.PageLoad.ActivationDecision",
@@ -769,7 +791,9 @@ TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest,
// Resource should be disallowed, since navigation commit had activation.
EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh()));
- EXPECT_EQ(1, client()->disallowed_notification_count());
+#if defined(OS_ANDROID)
+ EXPECT_TRUE(presenting_ads_blocked_infobar());
+#endif
}
TEST_P(SubresourceFilterSafeBrowsingActivationThrottleScopeTest,
@@ -956,7 +980,7 @@ TEST_P(SubresourceFilterSafeBrowsingActivationThrottleParamTest,
struct RedirectSamplesAndResults {
std::vector<GURL> urls;
bool expected_activation;
- base::Optional<RedirectPosition> last_enforcement_position;
+ absl::optional<RedirectPosition> last_enforcement_position;
};
TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest,
@@ -988,7 +1012,7 @@ TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest,
{{bad_url, normal_url, worse_url}, true, RedirectPosition::kLast},
{{worse_url, normal_url, bad_url}, true, RedirectPosition::kLast},
{{normal_url, worse_url, bad_url}, true, RedirectPosition::kLast},
- {{normal_url, normal_url}, false, base::nullopt},
+ {{normal_url, normal_url}, false, absl::nullopt},
{{normal_url, bad_url, normal_url}, false, RedirectPosition::kMiddle},
{{worse_url}, true, RedirectPosition::kOnly},
};
diff --git a/chromium/components/subresource_filter/content/browser/subresource_filter_test_harness.cc b/chromium/components/subresource_filter/content/browser/subresource_filter_test_harness.cc
index abe697b585f..8a73fed7a7e 100644
--- a/chromium/components/subresource_filter/content/browser/subresource_filter_test_harness.cc
+++ b/chromium/components/subresource_filter/content/browser/subresource_filter_test_harness.cc
@@ -10,6 +10,9 @@
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/content_settings/browser/page_specific_content_settings.h"
+#include "components/infobars/content/content_infobar_manager.h"
+#include "components/infobars/core/confirm_infobar_delegate.h"
+#include "components/infobars/core/infobar.h"
#include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
#include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h"
#include "components/subresource_filter/content/browser/ruleset_service.h"
@@ -86,11 +89,13 @@ void SubresourceFilterTestHarness::SetUp() {
VerifiedRulesetDealer::Handle* dealer =
ruleset_service_.get()->GetRulesetDealer();
- auto client = std::make_unique<TestSubresourceFilterClient>(web_contents());
- client_ = client.get();
- client_->CreateSafeBrowsingDatabaseManager();
+ throttle_manager_test_support_ =
+ std::make_unique<ThrottleManagerTestSupport>(web_contents());
+ database_manager_ = base::MakeRefCounted<FakeSafeBrowsingDatabaseManager>();
+ infobars::ContentInfoBarManager::CreateForWebContents(web_contents());
ContentSubresourceFilterThrottleManager::CreateForWebContents(
- web_contents(), std::move(client), client_->profile_context(), dealer);
+ web_contents(), throttle_manager_test_support_->profile_context(),
+ database_manager_, dealer);
// Observe web_contents() to add subresource filter navigation throttles at
// the start of navigations.
@@ -158,7 +163,7 @@ void SubresourceFilterTestHarness::RemoveURLFromBlocklist(const GURL& url) {
SubresourceFilterContentSettingsManager*
SubresourceFilterTestHarness::GetSettingsManager() {
- return client_->profile_context()->settings_manager();
+ return throttle_manager_test_support_->profile_context()->settings_manager();
}
void SubresourceFilterTestHarness::SetIsAdSubframe(
diff --git a/chromium/components/subresource_filter/content/browser/subresource_filter_test_harness.h b/chromium/components/subresource_filter/content/browser/subresource_filter_test_harness.h
index 21986bc7a2e..6cb77f7feaa 100644
--- a/chromium/components/subresource_filter/content/browser/subresource_filter_test_harness.h
+++ b/chromium/components/subresource_filter/content/browser/subresource_filter_test_harness.h
@@ -9,7 +9,7 @@
#include "base/files/scoped_temp_dir.h"
#include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h"
-#include "components/subresource_filter/content/browser/test_subresource_filter_client.h"
+#include "components/subresource_filter/content/browser/throttle_manager_test_support.h"
#include "components/subresource_filter/core/browser/subresource_filter_features.h"
#include "components/subresource_filter/core/browser/subresource_filter_features_test_support.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
@@ -23,6 +23,10 @@ class NavigationThrottle;
class RenderFrameHost;
} // namespace content
+namespace infobars {
+class ContentInfoBarManager;
+}
+
namespace subresource_filter {
class RulesetService;
@@ -72,7 +76,7 @@ class SubresourceFilterTestHarness : public content::RenderViewHostTestHarness,
}
FakeSafeBrowsingDatabaseManager* fake_safe_browsing_database() {
- return client_->fake_safe_browsing_database_manager();
+ return database_manager_.get();
}
void SetIsAdSubframe(content::RenderFrameHost* render_frame_host,
@@ -100,7 +104,9 @@ class SubresourceFilterTestHarness : public content::RenderViewHostTestHarness,
base::ScopedTempDir ruleset_service_dir_;
sync_preferences::TestingPrefServiceSyncable pref_service_;
testing::ScopedSubresourceFilterConfigurator scoped_configuration_;
- TestSubresourceFilterClient* client_;
+ scoped_refptr<FakeSafeBrowsingDatabaseManager> database_manager_;
+ std::unique_ptr<ThrottleManagerTestSupport> throttle_manager_test_support_;
+ std::unique_ptr<infobars::ContentInfoBarManager> infobar_manager_;
std::unique_ptr<RulesetService> ruleset_service_;
};
diff --git a/chromium/components/subresource_filter/content/browser/test_subresource_filter_client.h b/chromium/components/subresource_filter/content/browser/test_subresource_filter_client.h
deleted file mode 100644
index 5e367cc83c3..00000000000
--- a/chromium/components/subresource_filter/content/browser/test_subresource_filter_client.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_TEST_SUBRESOURCE_FILTER_CLIENT_H_
-#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_TEST_SUBRESOURCE_FILTER_CLIENT_H_
-
-#include <memory>
-
-#include "base/memory/scoped_refptr.h"
-#include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h"
-#include "components/subresource_filter/content/browser/subresource_filter_client.h"
-#include "components/sync_preferences/testing_pref_service_syncable.h"
-
-class HostContentSettingsMap;
-
-namespace content {
-class WebContents;
-}
-
-namespace subresource_filter {
-
-class SubresourceFilterProfileContext;
-
-// An implementation of SubresourceFilterClient suitable for use in unittests.
-class TestSubresourceFilterClient : public SubresourceFilterClient {
- public:
- explicit TestSubresourceFilterClient(content::WebContents* web_contents);
- ~TestSubresourceFilterClient() override;
-
- // SubresourceFilterClient:
- void ShowNotification() override;
- const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
- GetSafeBrowsingDatabaseManager() override;
-
- // GetSafeBrowsingDatabaseManager() returns null by default. Invoke this
- // method to change that behavior.
- void CreateSafeBrowsingDatabaseManager();
-
- SubresourceFilterProfileContext* profile_context() {
- return profile_context_.get();
- }
-
- FakeSafeBrowsingDatabaseManager* fake_safe_browsing_database_manager() {
- return database_manager_.get();
- }
-
- // Turns on/off the smart UI feature (currently enabled in production on
- // some platforms only).
- void SetShouldUseSmartUI(bool enabled);
-
- // Returns the number of times that ShowNotification() was invoked.
- int disallowed_notification_count() const {
- return disallowed_notification_count_;
- }
-
- private:
- scoped_refptr<FakeSafeBrowsingDatabaseManager> database_manager_;
- sync_preferences::TestingPrefServiceSyncable prefs_;
- scoped_refptr<HostContentSettingsMap> settings_map_;
- std::unique_ptr<SubresourceFilterProfileContext> profile_context_;
-
- int disallowed_notification_count_ = 0;
-};
-
-} // namespace subresource_filter
-
-#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_TEST_SUBRESOURCE_FILTER_CLIENT_H_
diff --git a/chromium/components/subresource_filter/content/browser/test_subresource_filter_client.cc b/chromium/components/subresource_filter/content/browser/throttle_manager_test_support.cc
index 3c7e6169900..ed5402c8b81 100644
--- a/chromium/components/subresource_filter/content/browser/test_subresource_filter_client.cc
+++ b/chromium/components/subresource_filter/content/browser/throttle_manager_test_support.cc
@@ -2,18 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "components/subresource_filter/content/browser/test_subresource_filter_client.h"
+#include "components/subresource_filter/content/browser/throttle_manager_test_support.h"
#include "components/content_settings/browser/page_specific_content_settings.h"
#include "components/content_settings/browser/test_page_specific_content_settings_delegate.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/infobars/content/content_infobar_manager.h"
#include "components/safe_browsing/core/db/database_manager.h"
#include "components/subresource_filter/content/browser/subresource_filter_content_settings_manager.h"
#include "components/subresource_filter/content/browser/subresource_filter_profile_context.h"
namespace subresource_filter {
-TestSubresourceFilterClient::TestSubresourceFilterClient(
+ThrottleManagerTestSupport::ThrottleManagerTestSupport(
content::WebContents* web_contents) {
// Set up the state that's required by ProfileInteractionManager.
HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
@@ -30,26 +31,14 @@ TestSubresourceFilterClient::TestSubresourceFilterClient(
std::make_unique<
content_settings::TestPageSpecificContentSettingsDelegate>(
/*prefs=*/nullptr, settings_map_.get()));
+ infobars::ContentInfoBarManager::CreateForWebContents(web_contents);
}
-TestSubresourceFilterClient::~TestSubresourceFilterClient() {
+ThrottleManagerTestSupport::~ThrottleManagerTestSupport() {
settings_map_->ShutdownOnUIThread();
}
-void TestSubresourceFilterClient::ShowNotification() {
- ++disallowed_notification_count_;
-}
-
-const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
-TestSubresourceFilterClient::GetSafeBrowsingDatabaseManager() {
- return database_manager_;
-}
-
-void TestSubresourceFilterClient::CreateSafeBrowsingDatabaseManager() {
- database_manager_ = base::MakeRefCounted<FakeSafeBrowsingDatabaseManager>();
-}
-
-void TestSubresourceFilterClient::SetShouldUseSmartUI(bool enabled) {
+void ThrottleManagerTestSupport::SetShouldUseSmartUI(bool enabled) {
profile_context_->settings_manager()->set_should_use_smart_ui_for_testing(
enabled);
}
diff --git a/chromium/components/subresource_filter/content/browser/throttle_manager_test_support.h b/chromium/components/subresource_filter/content/browser/throttle_manager_test_support.h
new file mode 100644
index 00000000000..4ee4fd5898a
--- /dev/null
+++ b/chromium/components/subresource_filter/content/browser/throttle_manager_test_support.h
@@ -0,0 +1,50 @@
+// Copyright 2021 The Chromium Authors. 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_THROTTLE_MANAGER_TEST_SUPPORT_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_THROTTLE_MANAGER_TEST_SUPPORT_H_
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+
+class HostContentSettingsMap;
+
+namespace content {
+class WebContents;
+}
+
+namespace subresource_filter {
+
+class SubresourceFilterProfileContext;
+
+// Sets up necessary dependencies of ContentSubresourceFilterThrottleManager for
+// convenience in unittests.
+class ThrottleManagerTestSupport {
+ public:
+ explicit ThrottleManagerTestSupport(content::WebContents* web_contents);
+ ~ThrottleManagerTestSupport();
+
+ ThrottleManagerTestSupport(const ThrottleManagerTestSupport&) = delete;
+ ThrottleManagerTestSupport& operator=(const ThrottleManagerTestSupport&) =
+ delete;
+
+ SubresourceFilterProfileContext* profile_context() {
+ return profile_context_.get();
+ }
+
+ // Turns on/off the smart UI feature (currently enabled in production on
+ // some platforms only).
+ void SetShouldUseSmartUI(bool enabled);
+
+ private:
+ sync_preferences::TestingPrefServiceSyncable prefs_;
+ scoped_refptr<HostContentSettingsMap> settings_map_;
+ std::unique_ptr<SubresourceFilterProfileContext> profile_context_;
+};
+
+} // namespace subresource_filter
+
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_THROTTLE_MANAGER_TEST_SUPPORT_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 dcd838dafbb..f820459704f 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
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/files/file.h"
+#include "base/hash/hash.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/test_simple_task_runner.h"
#include "components/subresource_filter/core/common/memory_mapped_ruleset.h"
diff --git a/chromium/components/subresource_filter/content/common/ruleset_dealer.h b/chromium/components/subresource_filter/content/common/ruleset_dealer.h
index fe5db99ff9f..a92df2803ce 100644
--- a/chromium/components/subresource_filter/content/common/ruleset_dealer.h
+++ b/chromium/components/subresource_filter/content/common/ruleset_dealer.h
@@ -72,4 +72,4 @@ class RulesetDealer {
} // namespace subresource_filter
-#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_RENDERER_RULESET_DEALER_H_
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_COMMON_RULESET_DEALER_H_
diff --git a/chromium/components/subresource_filter/content/common/subresource_filter_utils.cc b/chromium/components/subresource_filter/content/common/subresource_filter_utils.cc
index 3fdb0f83be4..3dcff1589e1 100644
--- a/chromium/components/subresource_filter/content/common/subresource_filter_utils.cc
+++ b/chromium/components/subresource_filter/content/common/subresource_filter_utils.cc
@@ -13,7 +13,7 @@ bool ShouldInheritActivation(const GURL& url) {
}
blink::mojom::FilterListResult InterpretLoadPolicyAsEvidence(
- const base::Optional<LoadPolicy>& load_policy) {
+ const absl::optional<LoadPolicy>& load_policy) {
if (!load_policy.has_value()) {
return blink::mojom::FilterListResult::kNotChecked;
}
diff --git a/chromium/components/subresource_filter/content/common/subresource_filter_utils.h b/chromium/components/subresource_filter/content/common/subresource_filter_utils.h
index 1f5f3b1d5b8..8c887025ba5 100644
--- a/chromium/components/subresource_filter/content/common/subresource_filter_utils.h
+++ b/chromium/components/subresource_filter/content/common/subresource_filter_utils.h
@@ -5,8 +5,8 @@
#ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_COMMON_SUBRESOURCE_FILTER_UTILS_H_
#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_COMMON_SUBRESOURCE_FILTER_UTILS_H_
-#include "base/optional.h"
#include "components/subresource_filter/core/common/load_policy.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/ad_tagging/ad_evidence.mojom-shared.h"
class GURL;
@@ -25,10 +25,10 @@ bool ShouldInheritActivation(const GURL& url);
// Returns the appropriate FilterListResult, given the result of the most recent
// filter list check. If no LoadPolicy has been computed, i.e. no URL has been
// checked against the filter list for this frame, `load_policy` should be
-// `base::nullopt`. Otherwise, `load_policy.value()` should be the result of the
+// `absl::nullopt`. Otherwise, `load_policy.value()` should be the result of the
// latest check.
blink::mojom::FilterListResult InterpretLoadPolicyAsEvidence(
- const base::Optional<LoadPolicy>& load_policy);
+ const absl::optional<LoadPolicy>& load_policy);
} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/content/mojom/subresource_filter_agent.mojom b/chromium/components/subresource_filter/content/mojom/subresource_filter_agent.mojom
index 7a1b2f83329..bdb2dcbada9 100644
--- a/chromium/components/subresource_filter/content/mojom/subresource_filter_agent.mojom
+++ b/chromium/components/subresource_filter/content/mojom/subresource_filter_agent.mojom
@@ -5,15 +5,17 @@
module subresource_filter.mojom;
import "components/subresource_filter/core/mojom/subresource_filter.mojom";
-import "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom";
+import "third_party/blink/public/mojom/ad_tagging/ad_evidence.mojom";
interface SubresourceFilterAgent {
// Instructs the renderer to activate subresource filtering at the specified
- // |activation_state| for the document load committed next in a frame.
+ // |activation_state| for the document load committed next in a frame. Also
+ // informs the renderer of the frame's ad evidence. If the frame is a main
+ // frame, `ad_evidence` should be null as only subframes can be tagged.
//
- // Most be called just before mojom::FrameNavigationControl::CommitNavigation,
+ // Must be called just before mojom::FrameNavigationControl::CommitNavigation,
// at ReadyToCommitNavigation time. If not called, the default behavior is
- // mojom::ActivationLevel::kDisabled.
+ // mojom::ActivationLevel::kDisabled and unchanged ad evidence.
ActivateForNextCommittedLoad(ActivationState activation_state,
- blink.mojom.AdFrameType ad_type);
-}; \ No newline at end of file
+ blink.mojom.FrameAdEvidence? ad_evidence);
+};
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 6c2b23a59a1..a110fe15c2a 100644
--- a/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc
+++ b/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.cc
@@ -67,8 +67,8 @@ void SubresourceFilterAgent::Initialize() {
SendSubframeWasCreatedByAdScript();
// As this is the initial empty document, we won't have received any message
- // from the browser and so we must calculate the ad status here.
- SetIsAdSubframeIfNecessary();
+ // from the browser and so we must populate the ad evidence here.
+ SetAdEvidenceForInitialEmptySubframe();
}
// `render_frame()` can be null in unit tests.
@@ -127,10 +127,6 @@ bool SubresourceFilterAgent::IsSubframeCreatedByAdScript() {
return render_frame()->GetWebFrame()->IsSubframeCreatedByAdScript();
}
-bool SubresourceFilterAgent::HasDocumentLoader() {
- return render_frame()->GetWebFrame()->GetDocumentLoader();
-}
-
void SubresourceFilterAgent::SetSubresourceFilterForCurrentDocument(
std::unique_ptr<blink::WebDocumentSubresourceFilter> filter) {
blink::WebLocalFrame* web_frame = render_frame()->GetWebFrame();
@@ -160,9 +156,14 @@ bool SubresourceFilterAgent::IsAdSubframe() {
return render_frame()->GetWebFrame()->IsAdSubframe();
}
-void SubresourceFilterAgent::SetIsAdSubframe(
- blink::mojom::AdFrameType ad_frame_type) {
- render_frame()->GetWebFrame()->SetIsAdSubframe(ad_frame_type);
+void SubresourceFilterAgent::SetAdEvidence(
+ const blink::FrameAdEvidence& ad_evidence) {
+ render_frame()->GetWebFrame()->SetAdEvidence(ad_evidence);
+}
+
+const absl::optional<blink::FrameAdEvidence>&
+SubresourceFilterAgent::AdEvidence() {
+ return render_frame()->GetWebFrame()->AdEvidence();
}
// static
@@ -235,12 +236,13 @@ void SubresourceFilterAgent::OnSubresourceFilterAgentRequest(
void SubresourceFilterAgent::ActivateForNextCommittedLoad(
mojom::ActivationStatePtr activation_state,
- blink::mojom::AdFrameType ad_frame_type) {
+ const absl::optional<blink::FrameAdEvidence>& ad_evidence) {
activation_state_for_next_document_ = *activation_state;
if (!IsMainFrame()) {
- SetIsAdSubframe(ad_frame_type);
+ DCHECK(ad_evidence.has_value());
+ SetAdEvidence(ad_evidence.value());
} else {
- DCHECK_EQ(ad_frame_type, blink::mojom::AdFrameType::kNonAd);
+ DCHECK(!ad_evidence.has_value());
}
}
@@ -248,24 +250,19 @@ void SubresourceFilterAgent::OnDestruct() {
delete this;
}
-void SubresourceFilterAgent::SetIsAdSubframeIfNecessary() {
+void SubresourceFilterAgent::SetAdEvidenceForInitialEmptySubframe() {
DCHECK(!IsAdSubframe());
+ DCHECK(!AdEvidence().has_value());
- // TODO(alexmt): Store FrameAdEvidence on each frame, typically updated by the
- // browser but also populated here when the browser has not informed the
- // renderer.
blink::FrameAdEvidence ad_evidence(IsParentAdSubframe());
ad_evidence.set_created_by_ad_script(
IsSubframeCreatedByAdScript()
? blink::mojom::FrameCreationStackEvidence::kCreatedByAdScript
: blink::mojom::FrameCreationStackEvidence::kNotCreatedByAdScript);
ad_evidence.set_is_complete();
+ SetAdEvidence(ad_evidence);
if (ad_evidence.IndicatesAdSubframe()) {
- blink::mojom::AdFrameType ad_frame_type =
- ad_evidence.parent_is_ad() ? blink::mojom::AdFrameType::kChildAd
- : blink::mojom::AdFrameType::kRootAd;
- SetIsAdSubframe(ad_frame_type);
SendFrameIsAdSubframe();
}
}
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 fd658a6390a..0703ad07fbb 100644
--- a/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h
+++ b/chromium/components/subresource_filter/content/renderer/subresource_filter_agent.h
@@ -63,8 +63,6 @@ class SubresourceFilterAgent
virtual bool IsProvisional();
virtual bool IsSubframeCreatedByAdScript();
- virtual bool HasDocumentLoader();
-
// Injects the provided subresource |filter| into the DocumentLoader
// orchestrating the most recently created document.
virtual void SetSubresourceFilterForCurrentDocument(
@@ -89,18 +87,19 @@ class SubresourceFilterAgent
// True if the frame has been heuristically determined to be an ad subframe.
virtual bool IsAdSubframe();
- virtual void SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type);
- // If the browser has not yet informed the renderer of the frame's ad status
- // (i.e. due to an initial synchronous commit to about:blank), calculates
- // whether the frame should be an ad by populating a temporary FrameAdEvidence
- // object.
- void SetIsAdSubframeIfNecessary();
+ virtual const absl::optional<blink::FrameAdEvidence>& AdEvidence();
+ virtual void SetAdEvidence(const blink::FrameAdEvidence& ad_evidence);
+
+ // The browser will not inform the renderer of the (sub)frame's ad status and
+ // evidence in the case of an initial synchronous commit to about:blank. We
+ // thus fill in the frame's ad evidence and, if necessary, tag it as an ad.
+ void SetAdEvidenceForInitialEmptySubframe();
// mojom::SubresourceFilterAgent:
void ActivateForNextCommittedLoad(
mojom::ActivationStatePtr activation_state,
- blink::mojom::AdFrameType ad_frame_type) override;
+ const absl::optional<blink::FrameAdEvidence>& ad_evidence) override;
private:
// Returns the activation state for the `render_frame` to inherit. Main frames
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 e149f333711..7840a8152b6 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
@@ -72,17 +72,22 @@ class SubresourceFilterAgentUnderTest : public SubresourceFilterAgent {
return is_subframe_created_by_ad_script_;
}
- bool HasDocumentLoader() override { return true; }
-
void SetSubresourceFilterForCurrentDocument(
std::unique_ptr<blink::WebDocumentSubresourceFilter> filter) override {
last_injected_filter_ = std::move(filter);
OnSetSubresourceFilterForCurrentDocumentCalled();
}
- bool IsAdSubframe() override { return is_ad_subframe_; }
- void SetIsAdSubframe(AdFrameType ad_frame_type) override {
- is_ad_subframe_ = ad_frame_type != blink::mojom::AdFrameType::kNonAd;
+ bool IsAdSubframe() override {
+ return ad_evidence_ && ad_evidence_->is_complete() &&
+ ad_evidence_->IndicatesAdSubframe();
+ }
+
+ const absl::optional<blink::FrameAdEvidence>& AdEvidence() override {
+ return ad_evidence_;
+ }
+ void SetAdEvidence(const blink::FrameAdEvidence& ad_evidence) override {
+ ad_evidence_ = ad_evidence;
}
blink::WebDocumentSubresourceFilter* filter() {
@@ -114,7 +119,7 @@ class SubresourceFilterAgentUnderTest : public SubresourceFilterAgent {
// Production can set this on the RenderFrame, which we intercept and store
// here.
- bool is_ad_subframe_ = false;
+ absl::optional<blink::FrameAdEvidence> ad_evidence_;
std::unique_ptr<blink::WebDocumentSubresourceFilter> last_injected_filter_;
mojom::ActivationState inherited_activation_state_for_new_document_;
@@ -198,13 +203,13 @@ class SubresourceFilterAgentTest : public ::testing::Test {
}
void StartLoadWithoutSettingActivationState() {
- agent_as_rfo()->DidStartNavigation(GURL(), base::nullopt);
+ agent_as_rfo()->DidStartNavigation(GURL(), absl::nullopt);
agent_as_rfo()->ReadyToCommitNavigation(nullptr);
agent_as_rfo()->DidCreateNewDocument();
}
void PerformSameDocumentNavigationWithoutSettingActivationLevel() {
- agent_as_rfo()->DidStartNavigation(GURL(), base::nullopt);
+ agent_as_rfo()->DidStartNavigation(GURL(), absl::nullopt);
agent_as_rfo()->ReadyToCommitNavigation(nullptr);
// No DidCreateNewDocument, since same document navigations by definition
// don't create a new document.
@@ -222,9 +227,23 @@ class SubresourceFilterAgentTest : public ::testing::Test {
void StartLoadAndSetActivationState(
mojom::ActivationState state,
AdFrameType ad_type = AdFrameType::kNonAd) {
- agent_as_rfo()->DidStartNavigation(GURL(), base::nullopt);
+ agent_as_rfo()->DidStartNavigation(GURL(), absl::nullopt);
agent_as_rfo()->ReadyToCommitNavigation(nullptr);
- agent()->ActivateForNextCommittedLoad(state.Clone(), ad_type);
+
+ absl::optional<blink::FrameAdEvidence> ad_evidence;
+ if (!agent()->IsMainFrame()) {
+ // Generate an evidence object matching the `ad_type`.
+ ad_evidence = blink::FrameAdEvidence(ad_type == AdFrameType::kChildAd);
+ if (ad_type == AdFrameType::kRootAd) {
+ ad_evidence->set_created_by_ad_script(
+ blink::mojom::FrameCreationStackEvidence::kCreatedByAdScript);
+ }
+ ad_evidence->set_is_complete();
+ } else {
+ ASSERT_EQ(ad_type, AdFrameType::kNonAd);
+ }
+
+ agent()->ActivateForNextCommittedLoad(state.Clone(), ad_evidence);
agent_as_rfo()->DidCreateNewDocument();
}
@@ -508,15 +527,14 @@ TEST_F(SubresourceFilterAgentTest,
ASSERT_NO_FATAL_FAILURE(
SetTestRulesetToDisallowURLsWithPathSuffix(kTestBothURLsPathSuffix));
ExpectNoSubresourceFilterGetsInjected();
- agent_as_rfo()->DidStartNavigation(GURL(), base::nullopt);
+ agent_as_rfo()->DidStartNavigation(GURL(), absl::nullopt);
agent_as_rfo()->ReadyToCommitNavigation(nullptr);
mojom::ActivationStatePtr state = mojom::ActivationState::New();
state->activation_level = mojom::ActivationLevel::kEnabled;
state->measure_performance = true;
- agent()->ActivateForNextCommittedLoad(std::move(state),
- AdFrameType::kNonAd /* ad_type */);
+ agent()->ActivateForNextCommittedLoad(std::move(state), absl::nullopt);
agent_as_rfo()->DidFailProvisionalLoad();
- agent_as_rfo()->DidStartNavigation(GURL(), base::nullopt);
+ agent_as_rfo()->DidStartNavigation(GURL(), absl::nullopt);
agent_as_rfo()->ReadyToCommitNavigation(nullptr);
agent_as_rfo()->DidCommitProvisionalLoad(ui::PAGE_TRANSITION_LINK);
FinishLoad();
@@ -838,22 +856,4 @@ TEST_F(
agent_as_rfo()->DidCreateNewDocument();
}
-TEST_F(SubresourceFilterAgentTest,
- DryRun_SendSubframeWasCreatedByAdScriptNotSentFromMainFrame) {
- ResetAgentWithoutInitialize(/*is_main_frame=*/true, /*is_provisional=*/false,
- /*is_parent_ad_subframe=*/false,
- /*is_subframe_created_by_ad_script=*/true);
- ExpectSendSubframeWasCreatedByAdScript(0);
- agent()->Initialize();
- // SendSubframeWasCreatedByAdScript() is not sent from Initialize() since the
- // frame is the main frame, even though it's created by ad script.
- ::testing::Mock::VerifyAndClearExpectations(agent());
-
- // Call DidCreateNewDocument and verify that SendSubframeWasCreatedByAdScript
- // is not called from there either.
- EXPECT_CALL(*agent(), GetDocumentURL())
- .WillOnce(::testing::Return(GURL("about:blank")));
- agent_as_rfo()->DidCreateNewDocument();
-}
-
} // namespace subresource_filter
diff --git a/chromium/components/subresource_filter/content/renderer/unverified_ruleset_dealer.h b/chromium/components/subresource_filter/content/renderer/unverified_ruleset_dealer.h
index 7e9516e8e94..dc5821696e6 100644
--- a/chromium/components/subresource_filter/content/renderer/unverified_ruleset_dealer.h
+++ b/chromium/components/subresource_filter/content/renderer/unverified_ruleset_dealer.h
@@ -51,4 +51,4 @@ class UnverifiedRulesetDealer : public RulesetDealer,
} // namespace subresource_filter
-#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_RENDERER_RULESET_DEALER_H_
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_RENDERER_UNVERIFIED_RULESET_DEALER_H_
diff --git a/chromium/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc b/chromium/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc
index fe986905e05..24934f50df7 100644
--- a/chromium/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc
+++ b/chromium/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc
@@ -71,7 +71,6 @@ proto::ElementType ToElementType(
case blink::mojom::RequestContextType::CSP_REPORT:
case blink::mojom::RequestContextType::DOWNLOAD:
- case blink::mojom::RequestContextType::IMPORT:
case blink::mojom::RequestContextType::MANIFEST:
case blink::mojom::RequestContextType::UNSPECIFIED:
default:
diff --git a/chromium/components/subresource_filter/core/browser/subresource_filter_features.h b/chromium/components/subresource_filter/core/browser/subresource_filter_features.h
index 9cb949a2001..1a796b54d64 100644
--- a/chromium/components/subresource_filter/core/browser/subresource_filter_features.h
+++ b/chromium/components/subresource_filter/core/browser/subresource_filter_features.h
@@ -12,6 +12,7 @@
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/metrics/field_trial_params.h"
#include "base/strings/string_piece.h"
#include "components/subresource_filter/core/common/activation_list.h"
#include "components/subresource_filter/core/common/activation_scope.h"
diff --git a/chromium/components/subresource_filter/core/common/indexed_ruleset.cc b/chromium/components/subresource_filter/core/common/indexed_ruleset.cc
index 971d91ea588..503f2305c21 100644
--- a/chromium/components/subresource_filter/core/common/indexed_ruleset.cc
+++ b/chromium/components/subresource_filter/core/common/indexed_ruleset.cc
@@ -17,6 +17,8 @@ namespace {
namespace proto = url_pattern_index::proto;
using FindRuleStrategy =
url_pattern_index::UrlPatternIndexMatcher::FindRuleStrategy;
+using EmbedderConditionsMatcher =
+ url_pattern_index::UrlPatternIndexMatcher::EmbedderConditionsMatcher;
// A helper function to get the checksum on a data buffer.
int LocalGetChecksum(const uint8_t* data, size_t size) {
@@ -52,12 +54,12 @@ VerifyStatus GetVerifyStatus(const uint8_t* buffer,
// RulesetIndexer --------------------------------------------------------------
-const int RulesetIndexer::kIndexedFormatVersion = 29;
+const int RulesetIndexer::kIndexedFormatVersion = 30;
// This static assert is meant to catch cases where
// url_pattern_index::kUrlPatternIndexFormatVersion is incremented without
// updating RulesetIndexer::kIndexedFormatVersion.
-static_assert(url_pattern_index::kUrlPatternIndexFormatVersion == 8,
+static_assert(url_pattern_index::kUrlPatternIndexFormatVersion == 9,
"kUrlPatternIndexFormatVersion has changed, make sure you've "
"also updated RulesetIndexer::kIndexedFormatVersion above.");
@@ -136,7 +138,7 @@ bool IndexedRulesetMatcher::ShouldDisableFilteringForDocument(
document_url, parent_document_origin, proto::ELEMENT_TYPE_UNSPECIFIED,
activation_type,
FirstPartyOrigin::IsThirdParty(document_url, parent_document_origin),
- false, FindRuleStrategy::kAny);
+ false, EmbedderConditionsMatcher(), FindRuleStrategy::kAny);
}
LoadPolicy IndexedRulesetMatcher::GetLoadPolicyForResourceLoad(
@@ -161,17 +163,19 @@ const url_pattern_index::flat::UrlRule* IndexedRulesetMatcher::MatchedUrlRule(
url_pattern_index::proto::ElementType element_type,
bool disable_generic_rules) const {
const bool is_third_party = first_party.IsThirdParty(url);
+ const EmbedderConditionsMatcher embedder_conditions_matcher;
- const url_pattern_index::flat::UrlRule* blocklist_rule =
- blocklist_.FindMatch(url, first_party.origin(), element_type,
- proto::ACTIVATION_TYPE_UNSPECIFIED, is_third_party,
- disable_generic_rules, FindRuleStrategy::kAny);
+ const url_pattern_index::flat::UrlRule* blocklist_rule = blocklist_.FindMatch(
+ url, first_party.origin(), element_type,
+ proto::ACTIVATION_TYPE_UNSPECIFIED, is_third_party, disable_generic_rules,
+ embedder_conditions_matcher, FindRuleStrategy::kAny);
const url_pattern_index::flat::UrlRule* allowlist_rule = nullptr;
if (blocklist_rule) {
allowlist_rule =
allowlist_.FindMatch(url, first_party.origin(), element_type,
proto::ACTIVATION_TYPE_UNSPECIFIED, is_third_party,
- disable_generic_rules, FindRuleStrategy::kAny);
+ disable_generic_rules, embedder_conditions_matcher,
+ FindRuleStrategy::kAny);
return allowlist_rule ? allowlist_rule : blocklist_rule;
}
return nullptr;
diff --git a/chromium/components/subresource_filter/core/common/scoped_timers.h b/chromium/components/subresource_filter/core/common/scoped_timers.h
index 6eb617b195f..b370a55a034 100644
--- a/chromium/components/subresource_filter/core/common/scoped_timers.h
+++ b/chromium/components/subresource_filter/core/common/scoped_timers.h
@@ -13,8 +13,8 @@
//
// TODO(pkalinnikov): Consider moving this file to "base/metrics/".
-#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_
-#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_
+#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_H_
#include <type_traits>
#include <utility>
@@ -153,4 +153,4 @@ using ScopedThreadTimers =
} // namespace subresource_filter
-#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_SCOPED_TIMERS_H_
diff --git a/chromium/components/subresource_filter/core/common/test_ruleset_creator.cc b/chromium/components/subresource_filter/core/common/test_ruleset_creator.cc
index 1fef23f4a64..92fde645ead 100644
--- a/chromium/components/subresource_filter/core/common/test_ruleset_creator.cc
+++ b/chromium/components/subresource_filter/core/common/test_ruleset_creator.cc
@@ -10,6 +10,7 @@
#include "base/check.h"
#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/threading/thread_restrictions.h"
#include "components/subresource_filter/core/common/indexed_ruleset.h"
#include "components/subresource_filter/core/common/test_ruleset_utils.h"
@@ -155,7 +156,7 @@ void TestRulesetCreator::CreateRulesetToDisallowURLsWithManySuffixes(
std::vector<proto::UrlRule> rules;
for (int i = 0; i < num_of_suffixes; ++i) {
std::string current_suffix =
- suffix.as_string() + '_' + base::NumberToString(i);
+ std::string(suffix) + '_' + base::NumberToString(i);
rules.push_back(CreateSuffixRule(current_suffix));
}
CreateRulesetWithRules(rules, test_ruleset_pair);
diff --git a/chromium/components/subresource_filter/core/common/test_ruleset_utils.cc b/chromium/components/subresource_filter/core/common/test_ruleset_utils.cc
index 2e13d786fb1..4771f494d26 100644
--- a/chromium/components/subresource_filter/core/common/test_ruleset_utils.cc
+++ b/chromium/components/subresource_filter/core/common/test_ruleset_utils.cc
@@ -6,6 +6,8 @@
#include <utility>
+#include "base/strings/string_piece.h"
+
namespace subresource_filter {
namespace testing {
@@ -20,7 +22,7 @@ proto::UrlRule CreateSubstringRule(base::StringPiece substring) {
rule.set_url_pattern_type(proto::URL_PATTERN_TYPE_SUBSTRING);
rule.set_anchor_left(proto::ANCHOR_TYPE_NONE);
rule.set_anchor_right(proto::ANCHOR_TYPE_NONE);
- rule.set_url_pattern(substring.as_string());
+ rule.set_url_pattern(std::string(substring));
return rule;
}
@@ -33,7 +35,7 @@ proto::UrlRule CreateSuffixRule(base::StringPiece suffix) {
rule.set_url_pattern_type(proto::URL_PATTERN_TYPE_SUBSTRING);
rule.set_anchor_left(proto::ANCHOR_TYPE_NONE);
rule.set_anchor_right(proto::ANCHOR_TYPE_BOUNDARY);
- rule.set_url_pattern(suffix.as_string());
+ rule.set_url_pattern(std::string(suffix));
return rule;
}
@@ -45,7 +47,7 @@ proto::UrlRule CreateAllowlistSuffixRule(base::StringPiece suffix) {
rule.set_url_pattern_type(proto::URL_PATTERN_TYPE_SUBSTRING);
rule.set_anchor_left(proto::ANCHOR_TYPE_NONE);
rule.set_anchor_right(proto::ANCHOR_TYPE_BOUNDARY);
- rule.set_url_pattern(suffix.as_string());
+ rule.set_url_pattern(std::string(suffix));
return rule;
}
@@ -65,7 +67,7 @@ proto::UrlRule CreateAllowlistRuleForDocument(
rule.set_url_pattern_type(proto::URL_PATTERN_TYPE_SUBSTRING);
rule.set_anchor_left(proto::ANCHOR_TYPE_NONE);
rule.set_anchor_right(proto::ANCHOR_TYPE_NONE);
- rule.set_url_pattern(pattern.as_string());
+ rule.set_url_pattern(std::string(pattern));
return rule;
}
diff --git a/chromium/components/subresource_filter/core/common/time_measurements.h b/chromium/components/subresource_filter/core/common/time_measurements.h
index e682ffce237..e9c6973a9e3 100644
--- a/chromium/components/subresource_filter/core/common/time_measurements.h
+++ b/chromium/components/subresource_filter/core/common/time_measurements.h
@@ -11,8 +11,8 @@
// after some refactoring. Note that most of the code generated by the macros
// below is not thread-safe.
-#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TIME_MEASUREMENTS_
-#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TIME_MEASUREMENTS_
+#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TIME_MEASUREMENTS_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TIME_MEASUREMENTS_H_
#include "base/metrics/histogram.h"
#include "base/time/time.h"
@@ -147,4 +147,4 @@ using ExportMicrosecondsToHistogram = ExportTimeDeltaToHistogram<true>;
} // namespace subresource_filter
-#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TIME_MEASUREMENTS_
+#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_TIME_MEASUREMENTS_H_
diff --git a/chromium/components/subresource_filter/tools/filter_tool_main.cc b/chromium/components/subresource_filter/tools/filter_tool_main.cc
index b31c2a86980..7829a3d6947 100644
--- a/chromium/components/subresource_filter/tools/filter_tool_main.cc
+++ b/chromium/components/subresource_filter/tools/filter_tool_main.cc
@@ -99,8 +99,8 @@ int main(int argc, char* argv[]) {
base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!rules_file.IsValid()) {
- std::cerr << "Could not open file: "
- << command_line.GetSwitchValueASCII(kSwitchRuleset) << std::endl;
+ LOG(ERROR) << "Could not open file: "
+ << command_line.GetSwitchValueASCII(kSwitchRuleset);
PrintHelp();
return 1;
}
@@ -122,7 +122,7 @@ int main(int argc, char* argv[]) {
if (cmd != kMatchCommand && cmd != kMatchRulesCommand &&
cmd != kMatchBatchCommand) {
- std::cerr << "Not a recognized command " << cmd << std::endl;
+ LOG(ERROR) << "Not a recognized command " << cmd;
PrintHelp();
return 1;
}
@@ -136,8 +136,8 @@ int main(int argc, char* argv[]) {
if (!command_line.HasSwitch(arg))
missing_args.push_back(arg);
}
- std::cerr << "Missing arguments for match command: "
- << base::JoinString(missing_args, ",") << std::endl;
+ LOG(ERROR) << "Missing arguments for match command: "
+ << base::JoinString(missing_args, ",");
PrintHelp();
return 1;
}
@@ -156,9 +156,8 @@ int main(int argc, char* argv[]) {
if (command_line.HasSwitch(kSwitchMinMatches) &&
!base::StringToInt(command_line.GetSwitchValueASCII(kSwitchMinMatches),
&min_match_count)) {
- std::cerr << "Could not convert min matches to integer: "
- << command_line.GetSwitchValueASCII(kSwitchMinMatches)
- << std::endl;
+ LOG(ERROR) << "Could not convert min matches to integer: "
+ << command_line.GetSwitchValueASCII(kSwitchMinMatches);
PrintHelp();
return 1;
}
diff --git a/chromium/components/subresource_filter/tools/ruleset_converter/rule_stream.cc b/chromium/components/subresource_filter/tools/ruleset_converter/rule_stream.cc
index e64570328e8..9d3690ee1bf 100644
--- a/chromium/components/subresource_filter/tools/ruleset_converter/rule_stream.cc
+++ b/chromium/components/subresource_filter/tools/ruleset_converter/rule_stream.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/check_op.h"
+#include "base/logging.h"
#include "components/subresource_filter/core/common/unindexed_ruleset.h"
#include "components/subresource_filter/tools/rule_parser/rule.h"
#include "components/subresource_filter/tools/rule_parser/rule_parser.h"
@@ -84,7 +85,7 @@ class FilterListRuleInputStream : public RuleInputStream {
if (rule_type != url_pattern_index::proto::RULE_TYPE_UNSPECIFIED)
return rule_type;
if (!IsTrivialParseError(parser_.parse_error())) {
- std::cerr << parser_.parse_error() << std::endl;
+ LOG(ERROR) << parser_.parse_error();
}
// TODO(pkalinnikov): Export the number of processed/skipped rules.
}
diff --git a/chromium/components/subresource_filter/tools/ruleset_converter/rule_stream.h b/chromium/components/subresource_filter/tools/ruleset_converter/rule_stream.h
index bab58711e02..e24fdb09dd0 100644
--- a/chromium/components/subresource_filter/tools/ruleset_converter/rule_stream.h
+++ b/chromium/components/subresource_filter/tools/ruleset_converter/rule_stream.h
@@ -8,7 +8,6 @@
#include <istream>
#include <memory>
#include <ostream>
-#include <string>
#include "components/subresource_filter/tools/ruleset_converter/ruleset_format.h"
#include "components/url_pattern_index/proto/rules.pb.h"
diff --git a/chromium/components/subresource_redirect/common/subresource_redirect_result.h b/chromium/components/subresource_redirect/common/subresource_redirect_result.h
index fedde2638de..dae817b683b 100644
--- a/chromium/components/subresource_redirect/common/subresource_redirect_result.h
+++ b/chromium/components/subresource_redirect/common/subresource_redirect_result.h
@@ -15,53 +15,61 @@ enum class SubresourceRedirectResult {
// The image was determined as public and is eligible to be redirected
// to a compressed version.
- kRedirectable,
+ kRedirectable = 1,
// Possible reasons for ineligibility:
// Because of reasons Blink could disallow compression such as non <img>
// element, CSP/CORS security restrictions, javascript initiated image, etc.
- kIneligibleBlinkDisallowed,
+ kIneligibleBlinkDisallowed = 2,
// Because the resource is fetched for a subframe.
- kIneligibleSubframeResource,
+ kIneligibleSubframeResource = 3,
// Because the compressed subresource fetch failed, and then the original
// subresource was loaded.
- kIneligibleRedirectFailed,
+ kIneligibleRedirectFailed = 4,
// Possible reasons for ineligibility due to public image hints approach:
// Because the image hint list was not retrieved within certain time limit
// of navigation start,
- kIneligibleImageHintsUnavailable,
+ kIneligibleImageHintsUnavailable = 5,
// Because the image hint list was not retrieved at the time of image fetch,
// but the image URL was found in the hint list, which finished fetching
// later.
- kIneligibleImageHintsUnavailableButRedirectable,
+ kIneligibleImageHintsUnavailableButRedirectable = 6,
// Because the image hint list was not retrieved at the time of image fetch,
// and the image URL was not in the hint list as well, which finished
// fetching later.
- kIneligibleImageHintsUnavailableAndMissingInHints,
+ kIneligibleImageHintsUnavailableAndMissingInHints = 7,
// Because the image URL was not found in the image hints.
- kIneligibleMissingInImageHints,
+ kIneligibleMissingInImageHints = 8,
// Possible reasons for ineligibility due to login and robots rules
// based approach:
// Because the image was disallowed by robots rules of the image origin.
- kIneligibleRobotsDisallowed,
+ kIneligibleRobotsDisallowed = 9,
// Because the robots rules fetch timedout.
- kIneligibleRobotsTimeout,
+ kIneligibleRobotsTimeout = 10,
// Because the page was detected to be logged-in.
- kIneligibleLoginDetected,
+ kIneligibleLoginDetected = 11,
- kMaxValue = SubresourceRedirectResult::kIneligibleLoginDetected
+ // Because the subresource was within the first k subresources on the page and
+ // got disabled.
+ kIneligibleFirstKDisableSubresourceRedirect = 12,
+
+ // Because the subresource redirection was disabled, where only metrics are
+ // recorded and the actual subresource redirection does not happen.
+ kIneligibleCompressionDisabled = 13,
+
+ kMaxValue = SubresourceRedirectResult::kIneligibleCompressionDisabled
};
} // namespace subresource_redirect
diff --git a/chromium/components/subresource_redirect/subresource_redirect_browser_test_util.cc b/chromium/components/subresource_redirect/subresource_redirect_browser_test_util.cc
index e55b3ad97af..6f093889720 100644
--- a/chromium/components/subresource_redirect/subresource_redirect_browser_test_util.cc
+++ b/chromium/components/subresource_redirect/subresource_redirect_browser_test_util.cc
@@ -85,7 +85,7 @@ RobotsRulesTestServer::OnServerRequest(
return response;
case FailureMode::kTimeout:
response = std::make_unique<net::test_server::DelayedHttpResponse>(
- base::TimeDelta::FromSeconds(3));
+ base::TimeDelta::FromSeconds(4));
break;
case FailureMode::kNone:
break;
diff --git a/chromium/components/suggestions/suggestions_service.h b/chromium/components/suggestions/suggestions_service.h
index 3226b303541..43daf37b429 100644
--- a/chromium/components/suggestions/suggestions_service.h
+++ b/chromium/components/suggestions/suggestions_service.h
@@ -5,14 +5,12 @@
#ifndef COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_
#define COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_
-#include <memory>
-
#include "base/callback.h"
#include "base/callback_list.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/suggestions/proto/suggestions.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace suggestions {
@@ -32,7 +30,7 @@ class SuggestionsService : public KeyedService {
virtual bool FetchSuggestionsData() = 0;
// Returns the current set of suggestions from the cache.
- virtual base::Optional<SuggestionsProfile> GetSuggestionsDataFromCache()
+ virtual absl::optional<SuggestionsProfile> GetSuggestionsDataFromCache()
const = 0;
// Adds a callback that is called when the suggestions are updated.
diff --git a/chromium/components/suggestions/suggestions_service_impl.cc b/chromium/components/suggestions/suggestions_service_impl.cc
index e141fc13e98..7dd92fe69cb 100644
--- a/chromium/components/suggestions/suggestions_service_impl.cc
+++ b/chromium/components/suggestions/suggestions_service_impl.cc
@@ -140,12 +140,12 @@ bool SuggestionsServiceImpl::FetchSuggestionsData() {
return true;
}
-base::Optional<SuggestionsProfile>
+absl::optional<SuggestionsProfile>
SuggestionsServiceImpl::GetSuggestionsDataFromCache() const {
SuggestionsProfile suggestions;
// In case of empty cache or error, return empty.
if (!suggestions_store_->LoadSuggestions(&suggestions))
- return base::nullopt;
+ return absl::nullopt;
blocklist_store_->FilterSuggestions(&suggestions);
return suggestions;
}
diff --git a/chromium/components/suggestions/suggestions_service_impl.h b/chromium/components/suggestions/suggestions_service_impl.h
index 43e70953de1..eaa210d22e1 100644
--- a/chromium/components/suggestions/suggestions_service_impl.h
+++ b/chromium/components/suggestions/suggestions_service_impl.h
@@ -15,7 +15,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/scoped_observation.h"
#include "base/threading/thread_checker.h"
#include "base/time/tick_clock.h"
@@ -30,6 +29,7 @@
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/base/backoff_entry.h"
#include "net/url_request/url_fetcher_delegate.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace signin {
@@ -66,7 +66,7 @@ class SuggestionsServiceImpl : public SuggestionsService,
// SuggestionsService implementation.
bool FetchSuggestionsData() override;
- base::Optional<SuggestionsProfile> GetSuggestionsDataFromCache()
+ absl::optional<SuggestionsProfile> GetSuggestionsDataFromCache()
const override;
base::CallbackListSubscription AddCallback(
const ResponseCallback& callback) override WARN_UNUSED_RESULT;
diff --git a/chromium/components/suggestions/suggestions_store.h b/chromium/components/suggestions/suggestions_store.h
index 35f1095cf0f..eb25c574942 100644
--- a/chromium/components/suggestions/suggestions_store.h
+++ b/chromium/components/suggestions/suggestions_store.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SUGGESTIONS_SUGGESTIONS_STORE_H_
#define COMPONENTS_SUGGESTIONS_SUGGESTIONS_STORE_H_
-#include <memory>
-
#include "base/macros.h"
#include "base/time/clock.h"
#include "components/suggestions/proto/suggestions.pb.h"
diff --git a/chromium/components/sync/BUILD.gn b/chromium/components/sync/BUILD.gn
index acbdcc79f18..8207fd988c4 100644
--- a/chromium/components/sync/BUILD.gn
+++ b/chromium/components/sync/BUILD.gn
@@ -150,7 +150,7 @@ source_set("unit_tests") {
"driver/sync_service_utils_unittest.cc",
"driver/sync_session_durations_metrics_recorder_unittest.cc",
"driver/sync_stopped_reporter_unittest.cc",
- "driver/sync_user_settings_unittest.cc",
+ "driver/sync_user_settings_impl_unittest.cc",
"engine/backoff_delay_provider_unittest.cc",
"engine/bookmark_update_preprocessing_unittest.cc",
"engine/cancelation_signal_unittest.cc",
diff --git a/chromium/components/sync/base/BUILD.gn b/chromium/components/sync/base/BUILD.gn
index 7f8be1a315b..5877f47853b 100644
--- a/chromium/components/sync/base/BUILD.gn
+++ b/chromium/components/sync/base/BUILD.gn
@@ -104,7 +104,6 @@ static_library("base") {
static_library("test_support") {
testonly = true
sources = [
- "../test/callback_counter.h",
"../test/mock_invalidation.cc",
"../test/mock_invalidation.h",
"../test/mock_invalidation_tracker.cc",
diff --git a/chromium/components/sync/base/ordinal.h b/chromium/components/sync/base/ordinal.h
index 5deba3940b7..c73b07cdf04 100644
--- a/chromium/components/sync/base/ordinal.h
+++ b/chromium/components/sync/base/ordinal.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <algorithm>
-#include <cstddef>
#include <string>
#include "base/check_op.h"
diff --git a/chromium/components/sync/driver/BUILD.gn b/chromium/components/sync/driver/BUILD.gn
index 2d0822486c2..80ab10a408c 100644
--- a/chromium/components/sync/driver/BUILD.gn
+++ b/chromium/components/sync/driver/BUILD.gn
@@ -47,6 +47,8 @@ static_library("driver") {
"sync_driver_switches.h",
"sync_internals_util.cc",
"sync_internals_util.h",
+ "sync_policy_handler.cc",
+ "sync_policy_handler.h",
"sync_service.cc",
"sync_service.h",
"sync_service_crypto.cc",
@@ -101,13 +103,6 @@ static_library("driver") {
"//services/network/public/cpp",
]
- if (!is_ios) {
- sources += [
- "sync_policy_handler.cc",
- "sync_policy_handler.h",
- ]
- }
-
if (is_chromeos_ash) {
deps += [ "//ash/constants" ]
}
diff --git a/chromium/components/sync/engine/BUILD.gn b/chromium/components/sync/engine/BUILD.gn
index ee0ea0e1927..8788ee3b89c 100644
--- a/chromium/components/sync/engine/BUILD.gn
+++ b/chromium/components/sync/engine/BUILD.gn
@@ -121,11 +121,10 @@ static_library("engine") {
"net/url_translator.h",
"nigori/cryptographer.cc",
"nigori/cryptographer.h",
+ "nigori/key_derivation_params.cc",
+ "nigori/key_derivation_params.h",
"nigori/keystore_keys_handler.h",
- "nigori/nigori.cc",
- "nigori/nigori.h",
"nudge_handler.h",
- "polling_constants.cc",
"polling_constants.h",
"shutdown_reason.cc",
"shutdown_reason.h",
diff --git a/chromium/components/sync/nigori/BUILD.gn b/chromium/components/sync/nigori/BUILD.gn
index 4bc70c729d7..2ff2dead5fc 100644
--- a/chromium/components/sync/nigori/BUILD.gn
+++ b/chromium/components/sync/nigori/BUILD.gn
@@ -8,6 +8,8 @@ static_library("nigori") {
"cryptographer_impl.h",
"keystore_keys_cryptographer.cc",
"keystore_keys_cryptographer.h",
+ "nigori.cc",
+ "nigori.h",
"nigori_key_bag.cc",
"nigori_key_bag.h",
"nigori_local_change_processor.cc",
diff --git a/chromium/components/sync/protocol/protocol_sources.gni b/chromium/components/sync/protocol/protocol_sources.gni
index 39de476ba9d..2c1534b8d7e 100644
--- a/chromium/components/sync/protocol/protocol_sources.gni
+++ b/chromium/components/sync/protocol/protocol_sources.gni
@@ -32,7 +32,6 @@ sync_protocol_bases = [
"managed_user_setting_specifics",
"managed_user_shared_setting_specifics",
"managed_user_specifics",
- "managed_user_whitelist_specifics",
"model_type_state",
"model_type_store_schema_descriptor",
"nigori_local_data",
@@ -65,6 +64,7 @@ sync_protocol_bases = [
"vault",
"web_app_specifics",
"wifi_configuration_specifics",
+ "workspace_desk_specifics",
]
sync_protocol_sources = []
diff --git a/chromium/components/sync/trusted_vault/BUILD.gn b/chromium/components/sync/trusted_vault/BUILD.gn
index 854dbfa2a80..d2914d7ecc6 100644
--- a/chromium/components/sync/trusted_vault/BUILD.gn
+++ b/chromium/components/sync/trusted_vault/BUILD.gn
@@ -29,6 +29,8 @@ static_library("trusted_vault") {
"trusted_vault_request.h",
"trusted_vault_server_constants.cc",
"trusted_vault_server_constants.h",
+ "trusted_vault_switches.cc",
+ "trusted_vault_switches.h",
]
public_deps = [
"//base",
diff --git a/chromium/components/sync_bookmarks/bookmark_local_changes_builder.cc b/chromium/components/sync_bookmarks/bookmark_local_changes_builder.cc
index 1f85aa70c9f..a0eb5a2e172 100644
--- a/chromium/components/sync_bookmarks/bookmark_local_changes_builder.cc
+++ b/chromium/components/sync_bookmarks/bookmark_local_changes_builder.cc
@@ -4,9 +4,11 @@
#include "components/sync_bookmarks/bookmark_local_changes_builder.h"
+#include <limits>
#include <memory>
#include <string>
#include <utility>
+#include <vector>
#include "base/strings/utf_string_conversions.h"
#include "components/bookmarks/browser/bookmark_model.h"
@@ -30,14 +32,22 @@ BookmarkLocalChangesBuilder::BookmarkLocalChangesBuilder(
syncer::CommitRequestDataList BookmarkLocalChangesBuilder::BuildCommitRequests(
size_t max_entries) const {
DCHECK(bookmark_tracker_);
+
const std::vector<const SyncedBookmarkTracker::Entity*>
entities_with_local_changes =
- bookmark_tracker_->GetEntitiesWithLocalChanges(max_entries);
- DCHECK_LE(entities_with_local_changes.size(), max_entries);
+ bookmark_tracker_->GetEntitiesWithLocalChanges(
+ base::FeatureList::IsEnabled(
+ switches::kSyncBookmarksEnforceLateMaxEntriesToCommit)
+ ? std::numeric_limits<int>::max()
+ : max_entries);
syncer::CommitRequestDataList commit_requests;
for (const SyncedBookmarkTracker::Entity* entity :
entities_with_local_changes) {
+ if (commit_requests.size() >= max_entries) {
+ break;
+ }
+
DCHECK(entity);
DCHECK(entity->IsUnsynced());
const sync_pb::EntityMetadata* metadata = entity->metadata();
@@ -90,7 +100,8 @@ syncer::CommitRequestDataList BookmarkLocalChangesBuilder::BuildCommitRequests(
// 2. Bookmarks (maybe ancient legacy bookmarks only?) use/used |name| to
// encode the title.
data->is_folder = node->is_folder();
- data->unique_position = metadata->unique_position();
+ data->unique_position =
+ syncer::UniquePosition::FromProto(metadata->unique_position());
// Assign specifics only for the non-deletion case. In case of deletion,
// EntityData should contain empty specifics to indicate deletion.
data->specifics = CreateSpecificsFromBookmarkNode(
diff --git a/chromium/components/sync_bookmarks/bookmark_local_changes_builder.h b/chromium/components/sync_bookmarks/bookmark_local_changes_builder.h
index 93802053939..8da0609e8f4 100644
--- a/chromium/components/sync_bookmarks/bookmark_local_changes_builder.h
+++ b/chromium/components/sync_bookmarks/bookmark_local_changes_builder.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_LOCAL_CHANGES_BUILDER_H_
#define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_LOCAL_CHANGES_BUILDER_H_
-#include <vector>
-
#include "components/sync/engine/commit_and_get_updates_types.h"
namespace bookmarks {
diff --git a/chromium/components/sync_bookmarks/bookmark_model_merger.cc b/chromium/components/sync_bookmarks/bookmark_model_merger.cc
index e6f6fe4077d..1bacc4490be 100644
--- a/chromium/components/sync_bookmarks/bookmark_model_merger.cc
+++ b/chromium/components/sync_bookmarks/bookmark_model_merger.cc
@@ -10,9 +10,11 @@
#include "base/containers/contains.h"
#include "base/guid.h"
+#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/trace_event.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node.h"
#include "components/sync/base/hash_util.h"
@@ -82,7 +84,10 @@ enum class BookmarksGUIDDuplicates {
// Used in metrics: "Sync.ProblematicServerSideBookmarksDuringMerge". These
// values are persisted to logs. Entries should not be renumbered and numeric
-// values should never be reused.
+// values should never be reused. Note the existence of gaps because the
+// metric enum is reused for another UMA metric,
+// Sync.ProblematicServerSideBookmarks, which logs the analogous error cases
+// for non-initial updates.
enum class RemoteBookmarkUpdateError {
// Invalid specifics.
kInvalidSpecifics = 1,
@@ -94,8 +99,13 @@ enum class RemoteBookmarkUpdateError {
kUnexpectedGuid = 9,
// Parent is not a folder.
kParentNotFolder = 10,
+ // Unknown/unsupported permanent folder.
+ kUnsupportedPermanentFolder = 13,
+ // A bookmark that is not contained in any permanent folder and is instead
+ // hanging (directly or indirectly) from the root node.
+ kDescendantOfRootNodeWithoutPermanentFolder = 14,
- kMaxValue = kParentNotFolder,
+ kMaxValue = kDescendantOfRootNodeWithoutPermanentFolder,
};
void LogProblematicBookmark(RemoteBookmarkUpdateError problem) {
@@ -315,8 +325,7 @@ bool IsValidUpdate(const UpdateResponseData& update) {
DCHECK(!update_entity.is_deleted());
DCHECK(update_entity.server_defined_unique_tag.empty());
- if (!syncer::UniquePosition::FromProto(update_entity.unique_position)
- .IsValid()) {
+ if (!update_entity.unique_position.IsValid()) {
// Ignore updates with invalid positions.
DLOG(ERROR)
<< "Remote update with invalid position: "
@@ -355,25 +364,44 @@ struct GroupedUpdates {
// are grouped in a dedicated |permanent_node_updates| list in a returned value.
GroupedUpdates GroupValidUpdates(UpdateResponseDataList updates) {
GroupedUpdates grouped_updates;
+ int num_valid_updates = 0;
for (UpdateResponseData& update : updates) {
const EntityData& update_entity = update.entity;
if (update_entity.is_deleted()) {
continue;
}
if (!update_entity.server_defined_unique_tag.empty()) {
+ ++num_valid_updates;
grouped_updates.permanent_node_updates.push_back(std::move(update));
continue;
}
if (!IsValidUpdate(update)) {
continue;
}
+ ++num_valid_updates;
grouped_updates.updates_per_parent_id[update_entity.parent_id].push_back(
std::move(update));
}
+ base::UmaHistogramCounts100000("Sync.BookmarkModelMerger.ValidInputUpdates",
+ num_valid_updates);
+
return grouped_updates;
}
+int GetNumUnsyncedEntities(const SyncedBookmarkTracker* tracker) {
+ DCHECK(tracker);
+
+ int num_unsynced_entities = 0;
+ for (const SyncedBookmarkTracker::Entity* entity :
+ tracker->GetAllEntities()) {
+ if (entity->IsUnsynced()) {
+ ++num_unsynced_entities;
+ }
+ }
+ return num_unsynced_entities;
+}
+
} // namespace
BookmarkModelMerger::RemoteTreeNode::RemoteTreeNode() = default;
@@ -409,11 +437,7 @@ void BookmarkModelMerger::RemoteTreeNode::EmplaceSelfAndDescendantsByGUID(
bool BookmarkModelMerger::RemoteTreeNode::UniquePositionLessThan(
const RemoteTreeNode& lhs,
const RemoteTreeNode& rhs) {
- const syncer::UniquePosition a_pos =
- syncer::UniquePosition::FromProto(lhs.entity().unique_position);
- const syncer::UniquePosition b_pos =
- syncer::UniquePosition::FromProto(rhs.entity().unique_position);
- return a_pos.LessThan(b_pos);
+ return lhs.entity().unique_position.LessThan(rhs.entity().unique_position);
}
// static
@@ -479,11 +503,21 @@ BookmarkModelMerger::BookmarkModelMerger(
FindGuidMatchesOrReassignLocal(remote_forest_, bookmark_model_)) {
DCHECK(bookmark_tracker_->IsEmpty());
DCHECK(favicon_service);
+
+ int num_updates_in_forest = 0;
+ for (const auto& tree_tag_and_root : remote_forest_) {
+ num_updates_in_forest +=
+ 1 + CountRemoteTreeNodeDescendantsForUma(tree_tag_and_root.second);
+ }
+ base::UmaHistogramCounts100000(
+ "Sync.BookmarkModelMerger.ReachableInputUpdates", num_updates_in_forest);
}
BookmarkModelMerger::~BookmarkModelMerger() {}
void BookmarkModelMerger::Merge() {
+ TRACE_EVENT0("sync", "BookmarkModelMerger::Merge");
+
// Algorithm description:
// Match up the roots and recursively do the following:
// * For each remote node for the current remote (sync) parent node, either
@@ -504,9 +538,27 @@ void BookmarkModelMerger::Merge() {
// selects the first one.
// Associate permanent folders.
for (const auto& tree_tag_and_root : remote_forest_) {
+ // Special-case the root folder to avoid recording
+ // |RemoteBookmarkUpdateError::kUnsupportedPermanentFolder|.
+ if (tree_tag_and_root.first ==
+ syncer::ModelTypeToRootTag(syncer::BOOKMARKS)) {
+ // The root folder is not expected to have children, because all children
+ // should themselves be permanent folders too and hence directly populate
+ // |tree_tag_and_root| without nesting.
+ const int num_unexpected_descendants_of_root_folder =
+ CountRemoteTreeNodeDescendantsForUma(tree_tag_and_root.second);
+ for (int i = 0; i < num_unexpected_descendants_of_root_folder; ++i) {
+ LogProblematicBookmark(RemoteBookmarkUpdateError::
+ kDescendantOfRootNodeWithoutPermanentFolder);
+ }
+ continue;
+ }
+
const bookmarks::BookmarkNode* permanent_folder =
GetPermanentFolder(bookmark_model_, tree_tag_and_root.first);
if (!permanent_folder) {
+ LogProblematicBookmark(
+ RemoteBookmarkUpdateError::kUnsupportedPermanentFolder);
continue;
}
MergeSubtree(/*local_subtree_root=*/permanent_folder,
@@ -519,11 +571,17 @@ void BookmarkModelMerger::Merge() {
// is used to disable reupload after initial merge.
bookmark_tracker_->SetBookmarksFullTitleReuploaded();
}
+
+ base::UmaHistogramCounts100000(
+ "Sync.BookmarkModelMerger.UnsyncedEntitiesUponCompletion",
+ GetNumUnsyncedEntities(bookmark_tracker_));
}
// static
BookmarkModelMerger::RemoteForest BookmarkModelMerger::BuildRemoteForest(
syncer::UpdateResponseDataList updates) {
+ TRACE_EVENT0("sync", "BookmarkModelMerger::BuildRemoteForest");
+
// Filter out invalid remote updates and group the valid ones by the server ID
// of their parent.
GroupedUpdates grouped_updates = GroupValidUpdates(std::move(updates));
@@ -551,8 +609,7 @@ BookmarkModelMerger::RemoteForest BookmarkModelMerger::BuildRemoteForest(
for (const auto& parent_id_and_updates :
grouped_updates.updates_per_parent_id) {
for (const UpdateResponseData& update : parent_id_and_updates.second) {
- if (!update.entity.is_deleted() &&
- update.entity.specifics.has_bookmark()) {
+ if (update.entity.specifics.has_bookmark()) {
LogProblematicBookmark(RemoteBookmarkUpdateError::kMissingParentEntity);
}
}
@@ -562,12 +619,24 @@ BookmarkModelMerger::RemoteForest BookmarkModelMerger::BuildRemoteForest(
}
// static
+int BookmarkModelMerger::CountRemoteTreeNodeDescendantsForUma(
+ const RemoteTreeNode& node) {
+ int descendants = 0;
+ for (const RemoteTreeNode& child : node.children()) {
+ descendants += 1 + CountRemoteTreeNodeDescendantsForUma(child);
+ }
+ return descendants;
+}
+
+// static
std::unordered_map<base::GUID, BookmarkModelMerger::GuidMatch, base::GUIDHash>
BookmarkModelMerger::FindGuidMatchesOrReassignLocal(
const RemoteForest& remote_forest,
bookmarks::BookmarkModel* bookmark_model) {
DCHECK(bookmark_model);
+ TRACE_EVENT0("sync", "BookmarkModelMerger::FindGuidMatchesOrReassignLocal");
+
// Build a temporary lookup table for remote GUIDs.
std::unordered_map<base::GUID, const RemoteTreeNode*, base::GUIDHash>
guid_to_remote_node_map;
@@ -858,7 +927,7 @@ void BookmarkModelMerger::ProcessLocalCreation(
const sync_pb::EntitySpecifics specifics = CreateSpecificsFromBookmarkNode(
node, bookmark_model_, /*force_favicon_load=*/true);
const SyncedBookmarkTracker::Entity* entity = bookmark_tracker_->Add(
- node, sync_id, server_version, creation_time, pos.ToProto(), specifics);
+ node, sync_id, server_version, creation_time, pos, specifics);
// Mark the entity that it needs to be committed.
bookmark_tracker_->IncrementSequenceNumber(entity);
for (size_t i = 0; i < node->children().size(); ++i) {
diff --git a/chromium/components/sync_bookmarks/bookmark_model_merger.h b/chromium/components/sync_bookmarks/bookmark_model_merger.h
index 61d6bdb3080..08e5b2f608f 100644
--- a/chromium/components/sync_bookmarks/bookmark_model_merger.h
+++ b/chromium/components/sync_bookmarks/bookmark_model_merger.h
@@ -119,6 +119,11 @@ class BookmarkModelMerger {
// sends tombstones as part of the initial download.
static RemoteForest BuildRemoteForest(syncer::UpdateResponseDataList updates);
+ // Recursively counts and returns the number of descendants for |node|,
+ // excluding |node| itself.
+ static int CountRemoteTreeNodeDescendantsForUma(
+ const BookmarkModelMerger::RemoteTreeNode& node);
+
// Computes bookmark pairs that should be matched by GUID. Local bookmark
// GUIDs may be regenerated for the case where they collide with a remote GUID
// that is not compatible (e.g. folder vs non-folder).
diff --git a/chromium/components/sync_bookmarks/bookmark_model_merger_unittest.cc b/chromium/components/sync_bookmarks/bookmark_model_merger_unittest.cc
index a798934d77d..d083b7c2001 100644
--- a/chromium/components/sync_bookmarks/bookmark_model_merger_unittest.cc
+++ b/chromium/components/sync_bookmarks/bookmark_model_merger_unittest.cc
@@ -35,6 +35,10 @@ namespace sync_bookmarks {
namespace {
+MATCHER_P(HasTitle, title, "") {
+ return arg->GetTitle() == title;
+}
+
// Copy of BookmarksGUIDDuplicates.
enum class ExpectedBookmarksGUIDDuplicates {
kMatchingUrls = 0,
@@ -54,7 +58,9 @@ enum class ExpectedRemoteBookmarkUpdateError {
kMissingParentEntity = 4,
kUnexpectedGuid = 9,
kParentNotFolder = 10,
- kMaxValue = kParentNotFolder,
+ kUnsupportedPermanentFolder = 13,
+ kDescendantOfRootNodeWithoutPermanentFolder = 14,
+ kMaxValue = kDescendantOfRootNodeWithoutPermanentFolder,
};
// |*arg| must be of type std::vector<std::unique_ptr<bookmarks::BookmarkNode>>.
@@ -81,7 +87,7 @@ class UpdateResponseDataBuilder {
const syncer::UniquePosition& unique_position) {
data_.id = server_id;
data_.parent_id = parent_id;
- data_.unique_position = unique_position.ToProto();
+ data_.unique_position = unique_position;
data_.is_folder = true;
sync_pb::BookmarkSpecifics* bookmark_specifics =
@@ -136,7 +142,7 @@ syncer::UpdateResponseData CreateUpdateResponseData(
const std::string& url,
bool is_folder,
const syncer::UniquePosition& unique_position,
- base::Optional<base::GUID> guid = base::nullopt,
+ absl::optional<base::GUID> guid = absl::nullopt,
const std::string& icon_url = std::string(),
const std::string& icon_data = std::string()) {
UpdateResponseDataBuilder builder(server_id, parent_id, title,
@@ -338,6 +344,8 @@ TEST(BookmarkModelMergerTest, ShouldMergeLocalAndRemoteModels) {
// |- url3(http://www.url3.com)
// |- url4(http://www.url4.com)
+ base::HistogramTester histogram_tester;
+
std::unique_ptr<SyncedBookmarkTracker> tracker =
Merge(std::move(updates), bookmark_model.get());
ASSERT_THAT(bookmark_bar_node->children().size(), Eq(3u));
@@ -390,6 +398,10 @@ TEST(BookmarkModelMergerTest, ShouldMergeLocalAndRemoteModels) {
EXPECT_THAT(bookmark_bar_node->children()[2]->children()[1]->url(),
Eq(GURL(kUrl4)));
+ EXPECT_THAT(histogram_tester.GetTotalSum(
+ "Sync.BookmarkModelMerger.UnsyncedEntitiesUponCompletion"),
+ Eq(4));
+
// Verify the tracker contents.
EXPECT_THAT(tracker->TrackedEntitiesCountForTest(), Eq(11U));
std::vector<const SyncedBookmarkTracker::Entity*> local_changes =
@@ -1757,15 +1769,76 @@ TEST(BookmarkModelMergerTest, ShouldLogMetricsForChildrenOfOrphanUpdates) {
base::HistogramTester histogram_tester;
Merge(std::move(updates), bookmark_model.get());
+ EXPECT_THAT(histogram_tester.GetTotalSum(
+ "Sync.BookmarkModelMerger.ValidInputUpdates"),
+ Eq(2));
histogram_tester.ExpectUniqueSample(
"Sync.ProblematicServerSideBookmarksDuringMerge",
/*sample=*/ExpectedRemoteBookmarkUpdateError::kMissingParentEntity,
/*count=*/1);
+ EXPECT_THAT(histogram_tester.GetTotalSum(
+ "Sync.BookmarkModelMerger.ReachableInputUpdates"),
+ Eq(1));
+}
+
+TEST(BookmarkModelMergerTest, ShouldLogMetricsForUnsupportedServerTag) {
+ std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
+ bookmarks::TestBookmarkClient::CreateModel();
+
+ syncer::UpdateResponseDataList updates;
+ updates.push_back(CreateBookmarkBarNodeUpdateData());
+ updates.back().entity.server_defined_unique_tag = "someunknowntag";
+
+ base::HistogramTester histogram_tester;
+ Merge(std::move(updates), bookmark_model.get());
+ histogram_tester.ExpectUniqueSample(
+ "Sync.ProblematicServerSideBookmarksDuringMerge",
+ /*sample=*/ExpectedRemoteBookmarkUpdateError::kUnsupportedPermanentFolder,
+ /*count=*/1);
+}
+
+TEST(BookmarkModelMergerTest, ShouldLogMetricsForkDescendantOfRootNode) {
+ const std::string kRootNodeId = "test_root_node_id";
+ std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
+ bookmarks::TestBookmarkClient::CreateModel();
+
+ // -------- The remote model --------
+ // root node
+ // | - bookmark (url1/Title1)
+ // | - bookmark (url2/Title2)
+ syncer::UpdateResponseDataList updates;
+ updates.push_back(CreateBookmarkBarNodeUpdateData());
+ updates.back().entity.id = kRootNodeId;
+ updates.back().entity.server_defined_unique_tag =
+ syncer::ModelTypeToRootTag(syncer::BOOKMARKS);
+
+ updates.push_back(CreateUpdateResponseData(
+ /*server_id=*/"Id1", /*parent_id=*/kRootNodeId, "Title1",
+ /*url=*/"http://url1",
+ /*is_folder=*/false,
+ /*unique_position=*/MakeRandomPosition(),
+ /*guid=*/base::GUID::GenerateRandomV4()));
+ updates.push_back(CreateUpdateResponseData(
+ /*server_id=*/"Id2", /*parent_id=*/kRootNodeId, "Title2",
+ /*url=*/"http://url2",
+ /*is_folder=*/false,
+ /*unique_position=*/MakeRandomPosition(),
+ /*guid=*/base::GUID::GenerateRandomV4()));
+
+ base::HistogramTester histogram_tester;
+ Merge(std::move(updates), bookmark_model.get());
+ histogram_tester.ExpectUniqueSample(
+ "Sync.ProblematicServerSideBookmarksDuringMerge",
+ /*sample=*/
+ ExpectedRemoteBookmarkUpdateError::
+ kDescendantOfRootNodeWithoutPermanentFolder,
+ /*count=*/2);
}
TEST(BookmarkModelMergerTest, ShouldRemoveMatchingDuplicatesByGUID) {
const std::string kTitle1 = "Title 1";
const std::string kTitle2 = "Title 2";
+ const std::string kTitle3 = "Title 3";
const std::string kUrl = "http://www.url.com/";
const base::GUID kUrlGUID = base::GUID::GenerateRandomV4();
@@ -1777,6 +1850,7 @@ TEST(BookmarkModelMergerTest, ShouldRemoveMatchingDuplicatesByGUID) {
// bookmark_bar
// |- url1(http://www.url.com, UrlGUID)
// |- url2(http://www.url.com, UrlGUID)
+ // |- url3(http://www.url.com, <other-guid>)
std::unique_ptr<bookmarks::BookmarkModel> bookmark_model =
bookmarks::TestBookmarkClient::CreateModel();
@@ -1794,18 +1868,31 @@ TEST(BookmarkModelMergerTest, ShouldRemoveMatchingDuplicatesByGUID) {
/*url=*/kUrl,
/*is_folder=*/false, /*unique_position=*/MakeRandomPosition(), kUrlGUID));
updates.back().entity.creation_time = base::Time::Now();
+ updates.push_back(CreateUpdateResponseData(
+ /*server_id=*/"Id3", /*parent_id=*/kBookmarkBarId, kTitle3,
+ /*url=*/kUrl,
+ /*is_folder=*/false, /*unique_position=*/MakeRandomPosition(),
+ base::GUID::GenerateRandomV4()));
+ updates.back().entity.creation_time = base::Time::Now();
base::HistogramTester histogram_tester;
std::unique_ptr<SyncedBookmarkTracker> tracker =
Merge(std::move(updates), bookmark_model.get());
const bookmarks::BookmarkNode* bookmark_bar_node =
bookmark_model->bookmark_bar_node();
- ASSERT_THAT(bookmark_bar_node->children().size(), Eq(1u));
+ EXPECT_THAT(bookmark_bar_node->children(),
+ UnorderedElementsAre(HasTitle(base::UTF8ToUTF16(kTitle2)),
+ HasTitle(base::UTF8ToUTF16(kTitle3))));
+
+ EXPECT_THAT(histogram_tester.GetTotalSum(
+ "Sync.BookmarkModelMerger.ValidInputUpdates"),
+ Eq(4));
histogram_tester.ExpectBucketCount(
"Sync.BookmarksGUIDDuplicates",
/*sample=*/ExpectedBookmarksGUIDDuplicates::kMatchingUrls, /*count=*/1);
- EXPECT_EQ(bookmark_bar_node->children().front()->GetTitle(),
- base::UTF8ToUTF16(kTitle2));
+ EXPECT_THAT(histogram_tester.GetTotalSum(
+ "Sync.BookmarkModelMerger.ReachableInputUpdates"),
+ Eq(3));
}
TEST(BookmarkModelMergerTest, ShouldRemoveDifferentDuplicatesByGUID) {
@@ -1846,12 +1933,11 @@ TEST(BookmarkModelMergerTest, ShouldRemoveDifferentDuplicatesByGUID) {
Merge(std::move(updates), bookmark_model.get());
const bookmarks::BookmarkNode* bookmark_bar_node =
bookmark_model->bookmark_bar_node();
- ASSERT_THAT(bookmark_bar_node->children().size(), Eq(1u));
+ EXPECT_THAT(bookmark_bar_node->children(),
+ UnorderedElementsAre(HasTitle(base::UTF8ToUTF16(kTitle1))));
histogram_tester.ExpectBucketCount(
"Sync.BookmarksGUIDDuplicates",
/*sample=*/ExpectedBookmarksGUIDDuplicates::kDifferentUrls, /*count=*/1);
- EXPECT_EQ(bookmark_bar_node->children().front()->GetTitle(),
- base::UTF8ToUTF16(kTitle1));
}
TEST(BookmarkModelMergerTest, ShouldRemoveMatchingFolderDuplicatesByGUID) {
@@ -2046,6 +2132,7 @@ TEST(BookmarkModelMergerTest, ShouldReuploadBookmarkOnEmptyGuid) {
/*is_folder=*/true, /*unique_position=*/posFolder2,
base::GUID::GenerateRandomV4()));
+ base::HistogramTester histogram_tester;
std::unique_ptr<SyncedBookmarkTracker> tracker =
Merge(std::move(updates), bookmark_model.get());
@@ -2054,6 +2141,10 @@ TEST(BookmarkModelMergerTest, ShouldReuploadBookmarkOnEmptyGuid) {
EXPECT_TRUE(tracker->GetEntityForSyncId(kFolder1Id)->IsUnsynced());
EXPECT_FALSE(tracker->GetEntityForSyncId(kFolder2Id)->IsUnsynced());
+
+ EXPECT_THAT(histogram_tester.GetTotalSum(
+ "Sync.BookmarkModelMerger.UnsyncedEntitiesUponCompletion"),
+ Eq(1));
}
TEST(BookmarkModelMergerTest, ShouldRemoveDifferentTypeDuplicatesByGUID) {
diff --git a/chromium/components/sync_bookmarks/bookmark_model_observer_impl.cc b/chromium/components/sync_bookmarks/bookmark_model_observer_impl.cc
index 01edbbf9f1a..aacbed17169 100644
--- a/chromium/components/sync_bookmarks/bookmark_model_observer_impl.cc
+++ b/chromium/components/sync_bookmarks/bookmark_model_observer_impl.cc
@@ -60,8 +60,8 @@ void BookmarkModelObserverImpl::BookmarkNodeMoved(
const std::string& sync_id = entity->metadata()->server_id();
const base::Time modification_time = base::Time::Now();
- const sync_pb::UniquePosition unique_position =
- ComputePosition(*new_parent, new_index, sync_id).ToProto();
+ const syncer::UniquePosition unique_position =
+ ComputePosition(*new_parent, new_index, sync_id);
sync_pb::EntitySpecifics specifics =
CreateSpecificsFromBookmarkNode(node, model, /*force_favicon_load=*/true);
@@ -88,13 +88,8 @@ void BookmarkModelObserverImpl::BookmarkNodeAdded(
// Should be removed after figuring out the reason for the crash.
CHECK(parent_entity);
- // Assign a temp server id for the entity. Will be overriden by the actual
- // server id upon receiving commit response.
- // Local bookmark creations should have used a random GUID so it's safe to
- // use it as originator client item ID, without the risk for collision.
- const sync_pb::UniquePosition unique_position =
- ComputePosition(*parent, index, node->guid().AsLowercaseString())
- .ToProto();
+ const syncer::UniquePosition unique_position =
+ ComputePosition(*parent, index, node->guid().AsLowercaseString());
sync_pb::EntitySpecifics specifics =
CreateSpecificsFromBookmarkNode(node, model, /*force_favicon_load=*/true);
@@ -294,7 +289,7 @@ void BookmarkModelObserverImpl::BookmarkNodeChildrenReordered(
child.get(), model, /*force_favicon_load=*/true);
bookmark_tracker_->Update(entity, entity->metadata()->server_version(),
- modification_time, position.ToProto(), specifics);
+ modification_time, position, specifics);
// Mark the entity that it needs to be committed.
bookmark_tracker_->IncrementSequenceNumber(entity);
}
@@ -383,9 +378,11 @@ void BookmarkModelObserverImpl::ProcessUpdate(
return;
}
- bookmark_tracker_->Update(entity, entity->metadata()->server_version(),
- /*modification_time=*/base::Time::Now(),
- entity->metadata()->unique_position(), specifics);
+ bookmark_tracker_->Update(
+ entity, entity->metadata()->server_version(),
+ /*modification_time=*/base::Time::Now(),
+ syncer::UniquePosition::FromProto(entity->metadata()->unique_position()),
+ specifics);
// Mark the entity that it needs to be committed.
bookmark_tracker_->IncrementSequenceNumber(entity);
nudge_for_commit_closure_.Run();
diff --git a/chromium/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc b/chromium/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc
index 7e22d12a118..7c0e78d379f 100644
--- a/chromium/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc
+++ b/chromium/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc
@@ -138,8 +138,7 @@ class BookmarkModelObserverImplTest : public testing::Test {
/*sync_id=*/kBookmarkBarId,
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
specifics);
specifics.mutable_bookmark()->set_legacy_canonicalized_title(
kOtherBookmarksTag);
@@ -148,8 +147,7 @@ class BookmarkModelObserverImplTest : public testing::Test {
/*sync_id=*/kOtherBookmarksId,
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
specifics);
specifics.mutable_bookmark()->set_legacy_canonicalized_title(
kMobileBookmarksTag);
@@ -158,8 +156,7 @@ class BookmarkModelObserverImplTest : public testing::Test {
/*sync_id=*/kMobileBookmarksId,
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
specifics);
}
@@ -574,8 +571,7 @@ TEST_F(BookmarkModelObserverImplTest, ShouldNotSyncUnsyncableBookmarks) {
/*sync_id=*/kBookmarkBarId,
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
specifics);
specifics.mutable_bookmark()->set_legacy_canonicalized_title(
kOtherBookmarksTag);
@@ -584,8 +580,7 @@ TEST_F(BookmarkModelObserverImplTest, ShouldNotSyncUnsyncableBookmarks) {
/*sync_id=*/kOtherBookmarksId,
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
specifics);
specifics.mutable_bookmark()->set_legacy_canonicalized_title(
kMobileBookmarksTag);
@@ -594,8 +589,7 @@ TEST_F(BookmarkModelObserverImplTest, ShouldNotSyncUnsyncableBookmarks) {
/*sync_id=*/kMobileBookmarksId,
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
specifics);
BookmarkModelObserverImpl observer(
nudge_for_commit_closure()->Get(),
@@ -647,8 +641,7 @@ TEST_F(BookmarkModelObserverImplTest, ShouldAddChildrenInArbitraryOrder) {
/*sync_id=*/kBookmarkBarId,
/*server_version=*/0, /*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
specifics);
// Build this structure:
@@ -817,8 +810,7 @@ TEST_F(BookmarkModelObserverImplTest,
const SyncedBookmarkTracker::Entity* entity = bookmark_tracker()->Add(
bookmark_node, "id", /*server_version=*/1, base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
specifics);
bookmark_tracker()->IncrementSequenceNumber(entity);
diff --git a/chromium/components/sync_bookmarks/bookmark_model_type_processor.cc b/chromium/components/sync_bookmarks/bookmark_model_type_processor.cc
index ef233866964..ef7e44d1cb3 100644
--- a/chromium/components/sync_bookmarks/bookmark_model_type_processor.cc
+++ b/chromium/components/sync_bookmarks/bookmark_model_type_processor.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/feature_list.h"
+#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/memory_usage_estimator.h"
@@ -516,7 +517,8 @@ void BookmarkModelTypeProcessor::AppendNodeAndChildrenForDebugging(
syncer::ProtoTimeToTime(metadata->modification_time());
data.name = base::UTF16ToUTF8(node->GetTitle());
data.is_folder = node->is_folder();
- data.unique_position = metadata->unique_position();
+ data.unique_position =
+ syncer::UniquePosition::FromProto(metadata->unique_position());
data.specifics =
CreateSpecificsFromBookmarkNode(node, bookmark_model_,
/*force_favicon_load=*/false);
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 c9812717675..5f8ca39e05d 100644
--- a/chromium/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
+++ b/chromium/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -12,6 +12,7 @@
#include "base/guid.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
+#include "base/test/gmock_move_support.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
@@ -29,16 +30,19 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace sync_bookmarks {
+
+namespace {
+
using base::ASCIIToUTF16;
using testing::_;
+using testing::ElementsAre;
using testing::Eq;
+using testing::IsEmpty;
using testing::IsNull;
using testing::NiceMock;
using testing::NotNull;
-
-namespace sync_bookmarks {
-
-namespace {
+using testing::UnorderedElementsAre;
const char kBookmarkBarTag[] = "bookmark_bar";
const char kOtherBookmarksTag[] = "other_bookmarks";
@@ -57,6 +61,17 @@ struct BookmarkInfo {
std::string server_tag;
};
+MATCHER_P(CommitRequestDataMatchesGuid, guid, "") {
+ const syncer::CommitRequestData* data = arg.get();
+ return data != nullptr && data->entity != nullptr &&
+ data->entity->specifics.bookmark().guid() == guid.AsLowercaseString();
+}
+
+MATCHER_P(TrackedEntityCorrespondsToBookmarkNode, bookmark_node, "") {
+ const SyncedBookmarkTracker::Entity* entity = arg;
+ return entity->bookmark_node() == bookmark_node;
+}
+
syncer::UpdateResponseData CreateUpdateResponseData(
const BookmarkInfo& bookmark_info,
const syncer::UniquePosition& unique_position,
@@ -66,7 +81,7 @@ syncer::UpdateResponseData CreateUpdateResponseData(
data.id = bookmark_info.server_id;
data.parent_id = bookmark_info.parent_id;
data.server_defined_unique_tag = bookmark_info.server_tag;
- data.unique_position = unique_position.ToProto();
+ data.unique_position = unique_position;
data.originator_client_item_id = guid.AsLowercaseString();
sync_pb::BookmarkSpecifics* bookmark_specifics =
@@ -116,6 +131,37 @@ sync_pb::BookmarkMetadata CreateNodeMetadata(
return bookmark_metadata;
}
+// Same as above but marks the node as unsynced (pending commit). |node| must
+// not be nullptr.
+sync_pb::BookmarkMetadata CreateUnsyncedNodeMetadata(
+ const bookmarks::BookmarkNode* node,
+ const std::string& server_id) {
+ sync_pb::BookmarkMetadata bookmark_metadata =
+ CreateNodeMetadata(node, server_id);
+ // Mark the entity as unsynced.
+ bookmark_metadata.mutable_metadata()->set_sequence_number(2);
+ bookmark_metadata.mutable_metadata()->set_acked_sequence_number(1);
+ return bookmark_metadata;
+}
+
+sync_pb::BookmarkModelMetadata CreateMetadataForPermanentNodes(
+ const bookmarks::BookmarkModel* bookmark_model) {
+ sync_pb::BookmarkModelMetadata model_metadata;
+ *model_metadata.mutable_model_type_state() = CreateDummyModelTypeState();
+
+ *model_metadata.add_bookmarks_metadata() =
+ CreateNodeMetadata(bookmark_model->bookmark_bar_node(),
+ /*server_id=*/kBookmarkBarId);
+ *model_metadata.add_bookmarks_metadata() =
+ CreateNodeMetadata(bookmark_model->mobile_node(),
+ /*server_id=*/kMobileBookmarksId);
+ *model_metadata.add_bookmarks_metadata() =
+ CreateNodeMetadata(bookmark_model->other_node(),
+ /*server_id=*/kOtherBookmarksId);
+
+ return model_metadata;
+}
+
void AssertState(const BookmarkModelTypeProcessor* processor,
const std::vector<BookmarkInfo>& bookmarks) {
const SyncedBookmarkTracker* tracker = processor->GetTrackerForTest();
@@ -203,7 +249,10 @@ class TestBookmarkClientWithFavicon : public bookmarks::TestBookmarkClient {
favicon_base::FaviconImageResult result;
result.image = std::move(image);
result.icon_url = std::move(icon_url);
- std::move(favicon_image_callbacks_[task_id]).Run(result);
+ favicon_base::FaviconImageCallback cb =
+ std::move(favicon_image_callbacks_[task_id]);
+ favicon_image_callbacks_.erase(task_id);
+ std::move(cb).Run(result);
}
size_t GetTasksCount() const { return favicon_image_callbacks_.size(); }
@@ -288,6 +337,17 @@ class BookmarkModelTypeProcessorTest : public testing::Test {
return model_metadata;
}
+ syncer::CommitRequestDataList GetLocalChangesFromProcessor(
+ size_t max_entries) {
+ base::MockOnceCallback<void(syncer::CommitRequestDataList &&)> callback;
+ syncer::CommitRequestDataList local_changes;
+ // Destruction of the mock upon return will verify that Run() was indeed
+ // invoked.
+ EXPECT_CALL(callback, Run).WillOnce(MoveArg(&local_changes));
+ processor_->GetLocalChanges(max_entries, callback.Get());
+ return local_changes;
+ }
+
private:
base::test::TaskEnvironment task_environment_;
NiceMock<base::MockCallback<base::RepeatingClosure>> schedule_save_closure_;
@@ -467,34 +527,9 @@ TEST_F(BookmarkModelTypeProcessorTest, ShouldDecodeSyncMetadata) {
SimulateModelReadyToSync();
SimulateOnSyncStarting();
- // TODO(crbug.com/516866): Remove this after initial sync done is properly set
- // within the processor.
- sync_pb::BookmarkModelMetadata model_metadata;
- model_metadata.mutable_model_type_state()->set_initial_sync_done(true);
- // Add entries for the permanent nodes. TestBookmarkClient adds all of them.
- sync_pb::BookmarkMetadata* bookmark_metadata =
- model_metadata.add_bookmarks_metadata();
- bookmark_metadata->set_id(bookmark_bar_node->id());
- bookmark_metadata->mutable_metadata()->set_server_id(kBookmarkBarId);
- bookmark_metadata->mutable_metadata()->set_client_tag_hash(
- SyncedBookmarkTracker::GetClientTagHashFromGUID(bookmark_bar_node->guid())
- .value());
-
- bookmark_metadata = model_metadata.add_bookmarks_metadata();
- bookmark_metadata->set_id(bookmark_model()->other_node()->id());
- bookmark_metadata->mutable_metadata()->set_server_id(kOtherBookmarksId);
- bookmark_metadata->mutable_metadata()->set_client_tag_hash(
- SyncedBookmarkTracker::GetClientTagHashFromGUID(
- bookmark_model()->other_node()->guid())
- .value());
- bookmark_metadata = model_metadata.add_bookmarks_metadata();
- bookmark_metadata->set_id(bookmark_model()->mobile_node()->id());
- bookmark_metadata->mutable_metadata()->set_server_id(kMobileBookmarksId);
- bookmark_metadata->mutable_metadata()->set_client_tag_hash(
- SyncedBookmarkTracker::GetClientTagHashFromGUID(
- bookmark_model()->mobile_node()->guid())
- .value());
+ sync_pb::BookmarkModelMetadata model_metadata =
+ CreateMetadataForPermanentNodes(bookmark_model());
// Add an entry for the bookmark node.
*model_metadata.add_bookmarks_metadata() =
@@ -590,10 +625,9 @@ TEST_F(BookmarkModelTypeProcessorTest,
model_metadata.mutable_model_type_state()->set_initial_sync_done(true);
// Add entries for only the bookmark bar. However, the TestBookmarkClient will
// create all the 3 permanent nodes.
- sync_pb::BookmarkMetadata* bookmark_metadata =
- model_metadata.add_bookmarks_metadata();
- bookmark_metadata->set_id(bookmark_model()->bookmark_bar_node()->id());
- bookmark_metadata->mutable_metadata()->set_server_id(kBookmarkBarId);
+ *model_metadata.add_bookmarks_metadata() =
+ CreateNodeMetadata(bookmark_model()->bookmark_bar_node(),
+ /*server_id=*/kBookmarkBarId);
// Create a new processor and init it with the metadata str.
BookmarkModelTypeProcessor new_processor(bookmark_undo_service());
@@ -729,68 +763,95 @@ TEST_F(BookmarkModelTypeProcessorTest,
/*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16(kTitle),
GURL(kUrl));
- sync_pb::BookmarkModelMetadata model_metadata;
- *model_metadata.mutable_model_type_state() = CreateDummyModelTypeState();
-
- // Add entries for the permanent nodes. TestBookmarkClient adds all of them.
- sync_pb::BookmarkMetadata* bookmark_metadata =
- model_metadata.add_bookmarks_metadata();
- bookmark_metadata->set_id(bookmark_bar_node->id());
- bookmark_metadata->mutable_metadata()->set_server_id(kBookmarkBarId);
- bookmark_metadata->mutable_metadata()->set_client_tag_hash(
- SyncedBookmarkTracker::GetClientTagHashFromGUID(bookmark_bar_node->guid())
- .value());
-
- bookmark_metadata = model_metadata.add_bookmarks_metadata();
- bookmark_metadata->set_id(bookmark_model()->other_node()->id());
- bookmark_metadata->mutable_metadata()->set_server_id(kOtherBookmarksId);
- bookmark_metadata->mutable_metadata()->set_client_tag_hash(
- SyncedBookmarkTracker::GetClientTagHashFromGUID(
- bookmark_model()->other_node()->guid())
- .value());
-
- bookmark_metadata = model_metadata.add_bookmarks_metadata();
- bookmark_metadata->set_id(bookmark_model()->mobile_node()->id());
- bookmark_metadata->mutable_metadata()->set_server_id(kMobileBookmarksId);
- bookmark_metadata->mutable_metadata()->set_client_tag_hash(
- SyncedBookmarkTracker::GetClientTagHashFromGUID(
- bookmark_model()->mobile_node()->guid())
- .value());
-
- // Add an entry for the bookmark node.
- bookmark_metadata = model_metadata.add_bookmarks_metadata();
- *bookmark_metadata = CreateNodeMetadata(node, kNodeId);
- // Mark the entity as unsynced.
- bookmark_metadata->mutable_metadata()->set_sequence_number(2);
- bookmark_metadata->mutable_metadata()->set_acked_sequence_number(1);
+ // Add an entry for the bookmark node that is unsynced.
+ sync_pb::BookmarkModelMetadata model_metadata =
+ CreateMetadataForPermanentNodes(bookmark_model());
+ *model_metadata.add_bookmarks_metadata() =
+ CreateUnsyncedNodeMetadata(node, kNodeId);
SimulateOnSyncStarting();
processor()->ModelReadyToSync(model_metadata.SerializeAsString(),
schedule_save_closure()->Get(),
bookmark_model());
- base::MockOnceCallback<void(
- std::vector<std::unique_ptr<syncer::CommitRequestData>> &&)>
- callback;
- std::vector<std::unique_ptr<syncer::CommitRequestData>> callback_result;
- ON_CALL(callback, Run)
- .WillByDefault(
- [&callback_result](
- std::vector<std::unique_ptr<syncer::CommitRequestData>>&&
- commit_data) { callback_result = std::move(commit_data); });
-
ASSERT_EQ(0u, bookmark_client()->GetTasksCount());
- EXPECT_CALL(callback, Run);
- processor()->GetLocalChanges(/*max_entries=*/10, callback.Get());
- EXPECT_TRUE(callback_result.empty());
+ EXPECT_THAT(GetLocalChangesFromProcessor(/*max_entries=*/10), IsEmpty());
EXPECT_TRUE(node->is_favicon_loading());
bookmark_client()->SimulateFaviconLoaded(GURL(kUrl), gfx::Image(),
GURL(kIconUrl));
ASSERT_TRUE(node->is_favicon_loaded());
- EXPECT_CALL(callback, Run);
- processor()->GetLocalChanges(/*max_entries=*/10, callback.Get());
- EXPECT_FALSE(callback_result.empty());
+ EXPECT_THAT(GetLocalChangesFromProcessor(/*max_entries=*/10),
+ ElementsAre(CommitRequestDataMatchesGuid(node->guid())));
+}
+
+TEST_F(BookmarkModelTypeProcessorTest,
+ ShouldCommitEntitiesWhileOtherFaviconsLoading) {
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeature(
+ switches::kSyncBookmarksEnforceLateMaxEntriesToCommit);
+
+ const std::string kNodeId1 = "node_id1";
+ const std::string kNodeId2 = "node_id2";
+ const std::string kTitle = "title";
+ const std::string kUrl1 = "http://www.url1.com";
+ const std::string kUrl2 = "http://www.url2.com";
+ const std::string kIconUrl = "http://www.url.com/favicon";
+
+ const bookmarks::BookmarkNode* bookmark_bar_node =
+ bookmark_model()->bookmark_bar_node();
+ const bookmarks::BookmarkNode* node1 = bookmark_model()->AddURL(
+ /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16(kTitle),
+ GURL(kUrl1));
+ const bookmarks::BookmarkNode* node2 = bookmark_model()->AddURL(
+ /*parent=*/bookmark_bar_node, /*index=*/1, base::UTF8ToUTF16(kTitle),
+ GURL(kUrl2));
+
+ // Add entries for the two bookmark nodes and mark them as unsynced.
+ sync_pb::BookmarkModelMetadata model_metadata =
+ CreateMetadataForPermanentNodes(bookmark_model());
+ *model_metadata.add_bookmarks_metadata() =
+ CreateUnsyncedNodeMetadata(node1, kNodeId1);
+ *model_metadata.add_bookmarks_metadata() =
+ CreateUnsyncedNodeMetadata(node2, kNodeId2);
+
+ SimulateOnSyncStarting();
+ processor()->ModelReadyToSync(model_metadata.SerializeAsString(),
+ schedule_save_closure()->Get(),
+ bookmark_model());
+
+ // The goal of this test is to mimic the case where one bookmark (the first
+ // one listed by SyncedBookmarkTracker::GetEntitiesWithLocalChanges()) has no
+ // loaded favicon, while the second one does. The precise order is not known
+ // in advance (in the current implementation, it depends on the iteration
+ // order for raw pointers in an unordered_set) which means the test needs to
+ // pass for both cases.
+ const std::vector<const SyncedBookmarkTracker::Entity*> unsynced_entities =
+ processor()->GetTrackerForTest()->GetEntitiesWithLocalChanges(
+ /*max_entries=*/1000);
+ ASSERT_THAT(
+ unsynced_entities,
+ UnorderedElementsAre(TrackedEntityCorrespondsToBookmarkNode(node1),
+ TrackedEntityCorrespondsToBookmarkNode(node2)));
+
+ // Force a favicon load for the second listed entity, but leave the first
+ // without loaded favicon.
+ bookmark_model()->GetFavicon(unsynced_entities[1]->bookmark_node());
+ bookmark_client()->SimulateFaviconLoaded(
+ unsynced_entities[1]->bookmark_node()->url(), gfx::Image(),
+ GURL(kIconUrl));
+ ASSERT_TRUE(unsynced_entities[1]->bookmark_node()->is_favicon_loaded());
+ ASSERT_FALSE(unsynced_entities[0]->bookmark_node()->is_favicon_loaded());
+ ASSERT_FALSE(unsynced_entities[0]->bookmark_node()->is_favicon_loading());
+
+ EXPECT_THAT(GetLocalChangesFromProcessor(/*max_entries=*/1),
+ ElementsAre(CommitRequestDataMatchesGuid(
+ unsynced_entities[1]->bookmark_node()->guid())));
+
+ // |unsynced_entities[0]| has been excluded from the result above because the
+ // favicon isn't loaded, but the loading process should have started now (see
+ // BookmarkLocalChangesBuilder::BuildCommitRequests()).
+ EXPECT_TRUE(unsynced_entities[0]->bookmark_node()->is_favicon_loading());
}
TEST_F(BookmarkModelTypeProcessorTest, ShouldReuploadLegacyBookmarksOnStart) {
diff --git a/chromium/components/sync_bookmarks/bookmark_remote_updates_handler.cc b/chromium/components/sync_bookmarks/bookmark_remote_updates_handler.cc
index 8d25d4d9e39..46d147de2a4 100644
--- a/chromium/components/sync_bookmarks/bookmark_remote_updates_handler.cc
+++ b/chromium/components/sync_bookmarks/bookmark_remote_updates_handler.cc
@@ -13,6 +13,7 @@
#include <utility>
#include "base/guid.h"
+#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_piece.h"
@@ -57,8 +58,10 @@ enum class RemoteBookmarkUpdateError {
kParentNotFolder = 10,
// The GUID changed for an already-tracked server ID.
kGuidChangedForTrackedServerId = 11,
+ // An update to a permanent node received without a server-defined unique tag.
+ kTrackedServerIdWithoutServerTagMatchesPermanentNode = 12,
- kMaxValue = kGuidChangedForTrackedServerId,
+ kMaxValue = kTrackedServerIdWithoutServerTagMatchesPermanentNode,
};
void LogProblematicBookmark(RemoteBookmarkUpdateError problem) {
@@ -105,14 +108,11 @@ syncer::UniquePosition ComputeUniquePositionForTrackedBookmarkNode(
}
size_t ComputeChildNodeIndex(const bookmarks::BookmarkNode* parent,
- const sync_pb::UniquePosition& unique_position,
+ const syncer::UniquePosition& position,
const SyncedBookmarkTracker* bookmark_tracker) {
DCHECK(parent);
DCHECK(bookmark_tracker);
- const syncer::UniquePosition position =
- syncer::UniquePosition::FromProto(unique_position);
-
auto iter = std::partition_point(
parent->children().begin(), parent->children().end(),
[bookmark_tracker,
@@ -207,10 +207,21 @@ void BookmarkRemoteUpdatesHandler::Process(
for (const syncer::UpdateResponseData* update : ReorderUpdates(&updates)) {
const syncer::EntityData& update_entity = update->entity;
- // Only non deletions and non premanent node should have valid specifics and
- // unique positions.
- if (!update_entity.is_deleted() &&
- update_entity.server_defined_unique_tag.empty()) {
+
+ // Ignore changes to the permanent nodes (e.g. bookmarks bar). We only
+ // care about their children.
+ if (!update_entity.server_defined_unique_tag.empty()) {
+ if (bookmark_tracker_->GetEntityForSyncId(update_entity.id) == nullptr) {
+ DLOG(ERROR)
+ << "Permanent nodes should have been merged during intial sync.";
+ LogProblematicBookmark(
+ RemoteBookmarkUpdateError::kPermanentNodeCreationAfterMerge);
+ }
+ continue;
+ }
+
+ // Only non-deletions should have valid specifics and unique positions.
+ if (!update_entity.is_deleted()) {
if (!IsValidBookmarkSpecifics(update_entity.specifics.bookmark(),
update_entity.is_folder)) {
// Ignore updates with invalid specifics.
@@ -219,8 +230,7 @@ void BookmarkRemoteUpdatesHandler::Process(
LogProblematicBookmark(RemoteBookmarkUpdateError::kInvalidSpecifics);
continue;
}
- if (!syncer::UniquePosition::FromProto(update_entity.unique_position)
- .IsValid()) {
+ if (!update_entity.unique_position.IsValid()) {
// Ignore updates with invalid unique position.
DLOG(ERROR) << "Couldn't process an update bookmark with an invalid "
"unique position.";
@@ -249,6 +259,20 @@ void BookmarkRemoteUpdatesHandler::Process(
continue;
}
+ // Filter out permanent nodes once again (in case the server tag wasn't
+ // populated and yet the entity ID points to a permanent node). This case
+ // shoudn't be possible with a well-behaving server.
+ if (tracked_entity && tracked_entity->bookmark_node() &&
+ tracked_entity->bookmark_node()->is_permanent_node()) {
+ DLOG(ERROR) << "Ignoring update to permanent node without server defined "
+ "unique tag for ID "
+ << update_entity.id;
+ LogProblematicBookmark(
+ RemoteBookmarkUpdateError::
+ kTrackedServerIdWithoutServerTagMatchesPermanentNode);
+ continue;
+ }
+
// Ignore updates that have already been seen according to the version.
if (tracked_entity && tracked_entity->metadata()->server_version() >=
update->response_version) {
@@ -288,11 +312,6 @@ void BookmarkRemoteUpdatesHandler::Process(
CHECK_EQ(tracked_entity,
bookmark_tracker_->GetEntityForSyncId(update_entity.id));
} else {
- // Ignore changes to the permanent nodes (e.g. bookmarks bar). We only
- // care about their children.
- if (bookmark_model_->is_permanent_node(tracked_entity->bookmark_node())) {
- continue;
- }
ProcessUpdate(*update, tracked_entity);
// TODO(crbug.com/516866): The below CHECK is added to debug some crashes.
// Should be removed after figuring out the reason for the crash.
@@ -348,7 +367,7 @@ BookmarkRemoteUpdatesHandler::ReorderUpdatesForTest(
// static
size_t BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
const bookmarks::BookmarkNode* parent,
- const sync_pb::UniquePosition& unique_position,
+ const syncer::UniquePosition& unique_position,
const SyncedBookmarkTracker* bookmark_tracker) {
return ComputeChildNodeIndex(parent, unique_position, bookmark_tracker);
}
@@ -508,14 +527,7 @@ BookmarkRemoteUpdatesHandler::ProcessCreate(
const syncer::UpdateResponseData& update) {
const syncer::EntityData& update_entity = update.entity;
DCHECK(!update_entity.is_deleted());
- if (!update_entity.server_defined_unique_tag.empty()) {
- DLOG(ERROR)
- << "Permanent nodes should have been merged during intial sync.";
- LogProblematicBookmark(
- RemoteBookmarkUpdateError::kPermanentNodeCreationAfterMerge);
- return nullptr;
- }
-
+ DCHECK(update_entity.server_defined_unique_tag.empty());
DCHECK(IsValidBookmarkSpecifics(update_entity.specifics.bookmark(),
update_entity.is_folder));
@@ -565,7 +577,7 @@ void BookmarkRemoteUpdatesHandler::ProcessUpdate(
bookmark_tracker_->GetEntityForSyncId(update_entity.id));
// Must not be a deletion.
DCHECK(!update_entity.is_deleted());
-
+ DCHECK(update_entity.server_defined_unique_tag.empty());
DCHECK(IsValidBookmarkSpecifics(update_entity.specifics.bookmark(),
update_entity.is_folder));
DCHECK(!tracked_entity->IsUnsynced());
@@ -633,11 +645,9 @@ void BookmarkRemoteUpdatesHandler::ProcessDelete(
}
const bookmarks::BookmarkNode* node = tracked_entity->bookmark_node();
- // Ignore changes to the permanent top-level nodes. We only care about
- // their children.
- if (bookmark_model_->is_permanent_node(node)) {
- return;
- }
+ DCHECK(node);
+ // Changes to permanent nodes have been filtered out earlier.
+ DCHECK(!node->is_permanent_node());
// Remove the entities of |node| and its children.
RemoveEntityAndChildrenFromTracker(node);
// Remove the node and its children from the model.
@@ -655,6 +665,9 @@ void BookmarkRemoteUpdatesHandler::ProcessConflict(
DCHECK(tracked_entity);
DCHECK_EQ(tracked_entity,
bookmark_tracker_->GetEntityForSyncId(update_entity.id));
+ DCHECK(!tracked_entity->bookmark_node() ||
+ !tracked_entity->bookmark_node()->is_permanent_node());
+ DCHECK(update_entity.server_defined_unique_tag.empty());
if (tracked_entity->metadata()->is_deleted() && update_entity.is_deleted()) {
// Both have been deleted, delete the corresponding entity from the tracker.
@@ -741,6 +754,9 @@ void BookmarkRemoteUpdatesHandler::ProcessConflict(
void BookmarkRemoteUpdatesHandler::RemoveEntityAndChildrenFromTracker(
const bookmarks::BookmarkNode* node) {
+ DCHECK(node);
+ DCHECK(!node->is_permanent_node());
+
const SyncedBookmarkTracker::Entity* entity =
bookmark_tracker_->GetEntityForBookmarkNode(node);
DCHECK(entity);
@@ -765,11 +781,12 @@ void BookmarkRemoteUpdatesHandler::ReuploadEntityIfNeeded(
const SyncedBookmarkTracker::Entity* tracked_entity) {
DCHECK(tracked_entity);
DCHECK_EQ(tracked_entity->metadata()->server_id(), entity_data.id);
- // Do not initiate reupload if the local entity is a tombstone or a permanent
- // node.
+ DCHECK(!tracked_entity->bookmark_node() ||
+ !tracked_entity->bookmark_node()->is_permanent_node());
+
+ // Do not initiate reupload if the local entity is a tombstone.
const bool is_reupload_needed =
tracked_entity->bookmark_node() &&
- !tracked_entity->bookmark_node()->is_permanent_node() &&
IsBookmarkEntityReuploadNeeded(entity_data);
base::UmaHistogramBoolean(
"Sync.BookmarkEntityReuploadNeeded.OnIncrementalUpdate",
diff --git a/chromium/components/sync_bookmarks/bookmark_remote_updates_handler.h b/chromium/components/sync_bookmarks/bookmark_remote_updates_handler.h
index c050df66a28..dcf8f8997d4 100644
--- a/chromium/components/sync_bookmarks/bookmark_remote_updates_handler.h
+++ b/chromium/components/sync_bookmarks/bookmark_remote_updates_handler.h
@@ -6,9 +6,9 @@
#define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_REMOTE_UPDATES_HANDLER_H_
#include <map>
-#include <string>
#include <vector>
+#include "components/sync/base/unique_position.h"
#include "components/sync/engine/commit_and_get_updates_types.h"
#include "components/sync_bookmarks/synced_bookmark_tracker.h"
@@ -46,7 +46,7 @@ class BookmarkRemoteUpdatesHandler {
static size_t ComputeChildNodeIndexForTest(
const bookmarks::BookmarkNode* parent,
- const sync_pb::UniquePosition& unique_position,
+ const syncer::UniquePosition& unique_position,
const SyncedBookmarkTracker* bookmark_tracker);
private:
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 11b01681202..5f016d4e7c5 100644
--- a/chromium/components/sync_bookmarks/bookmark_remote_updates_handler_unittest.cc
+++ b/chromium/components/sync_bookmarks/bookmark_remote_updates_handler_unittest.cc
@@ -65,7 +65,8 @@ enum class ExpectedRemoteBookmarkUpdateError {
kUnexpectedGuid = 9,
kParentNotFolder = 10,
kGuidChangedForTrackedServerId = 11,
- kMaxValue = kGuidChangedForTrackedServerId,
+ kTrackedServerIdWithoutServerTagMatchesPermanentNode = 12,
+ kMaxValue = kTrackedServerIdWithoutServerTagMatchesPermanentNode,
};
// |node| must not be nullptr.
@@ -123,7 +124,7 @@ syncer::UpdateResponseData CreateUpdateResponseData(
syncer::EntityData data;
data.id = server_id;
data.parent_id = parent_id;
- data.unique_position = unique_position.ToProto();
+ data.unique_position = unique_position;
data.originator_client_item_id = guid.AsLowercaseString();
// EntityData would be considered a deletion if its specifics hasn't been set.
@@ -579,6 +580,35 @@ TEST_F(BookmarkRemoteUpdatesHandlerWithInitialMergeTest,
}
TEST_F(BookmarkRemoteUpdatesHandlerWithInitialMergeTest,
+ ShouldIgnoreMisbehavingServerWithPermanentNodeUpdateWithoutServerTag) {
+ ASSERT_THAT(tracker()->GetEntityForSyncId(kBookmarkBarId), NotNull());
+
+ // Push an update for a permanent entity, but without a unique server tag.
+ syncer::UpdateResponseDataList updates;
+ updates.push_back(CreateUpdateResponseData(
+ /*server_id=*/kBookmarkBarId,
+ /*parent_id=*/"root_id",
+ /*guid=*/bookmark_model()->bookmark_bar_node()->guid(),
+ /*title=*/"title",
+ /*is_deletion=*/false,
+ /*version=*/1,
+ /*unique_position=*/
+ syncer::UniquePosition::InitialPosition(
+ syncer::UniquePosition::RandomSuffix())));
+
+ base::HistogramTester histogram_tester;
+ updates_handler()->Process(updates,
+ /*got_new_encryption_requirements=*/false);
+
+ histogram_tester.ExpectBucketCount(
+ "Sync.ProblematicServerSideBookmarks",
+ /*sample=*/
+ ExpectedRemoteBookmarkUpdateError::
+ kTrackedServerIdWithoutServerTagMatchesPermanentNode,
+ /*expected_count=*/1);
+}
+
+TEST_F(BookmarkRemoteUpdatesHandlerWithInitialMergeTest,
ShouldKeepOldGUIDUponRemoteUpdateWithoutGUID) {
const std::string kId = "id";
const std::string kTitle = "title";
@@ -889,8 +919,7 @@ TEST_F(BookmarkRemoteUpdatesHandlerWithInitialMergeTest,
data.id = kParentId;
data.parent_id = kBookmarkBarId;
data.unique_position = syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto();
+ syncer::UniquePosition::RandomSuffix());
sync_pb::BookmarkSpecifics* bookmark_specifics =
data.specifics.mutable_bookmark();
bookmark_specifics->set_guid(
@@ -942,8 +971,7 @@ TEST_F(BookmarkRemoteUpdatesHandlerWithInitialMergeTest,
data.id = "server_id";
data.parent_id = kBookmarkBarId;
data.unique_position = syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto();
+ syncer::UniquePosition::RandomSuffix());
sync_pb::BookmarkSpecifics* bookmark_specifics =
data.specifics.mutable_bookmark();
bookmark_specifics->set_guid(
@@ -984,8 +1012,7 @@ TEST_F(BookmarkRemoteUpdatesHandlerWithInitialMergeTest,
data.id = "server_id";
data.parent_id = kBookmarkBarId;
data.unique_position = syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto();
+ syncer::UniquePosition::RandomSuffix());
sync_pb::BookmarkSpecifics* bookmark_specifics =
data.specifics.mutable_bookmark();
bookmark_specifics->set_guid(
@@ -1026,7 +1053,7 @@ TEST_F(BookmarkRemoteUpdatesHandlerWithInitialMergeTest,
sync_pb::ModelTypeState model_type_state;
model_type_state.set_initial_sync_done(true);
- const sync_pb::UniquePosition unique_position;
+ const syncer::UniquePosition unique_position;
sync_pb::EntitySpecifics specifics;
sync_pb::BookmarkSpecifics* bookmark_specifics = specifics.mutable_bookmark();
bookmark_specifics->set_guid(
@@ -1051,8 +1078,7 @@ TEST_F(BookmarkRemoteUpdatesHandlerWithInitialMergeTest,
data.originator_client_item_id = kOriginatorClientItemId;
// Set the other required fields.
data.unique_position = syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto();
+ syncer::UniquePosition::RandomSuffix());
data.specifics = specifics;
data.specifics.mutable_bookmark()->set_guid(kOriginatorClientItemId);
data.is_folder = true;
@@ -1091,7 +1117,7 @@ TEST_F(
sync_pb::ModelTypeState model_type_state;
model_type_state.set_initial_sync_done(true);
- const sync_pb::UniquePosition unique_position;
+ const syncer::UniquePosition unique_position;
sync_pb::EntitySpecifics specifics;
sync_pb::BookmarkSpecifics* bookmark_specifics = specifics.mutable_bookmark();
bookmark_specifics->set_guid(kBookmarkGuid);
@@ -1116,8 +1142,7 @@ TEST_F(
syncer::ClientTagHash::FromUnhashed(syncer::BOOKMARKS, kBookmarkGuid);
// Set the other required fields.
data.unique_position = syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto();
+ syncer::UniquePosition::RandomSuffix());
data.specifics = specifics;
data.specifics.mutable_bookmark()->set_guid(kBookmarkGuid);
data.is_folder = true;
@@ -1925,7 +1950,7 @@ TEST(BookmarkRemoteUpdatesHandlerTest,
// Should always return 0 for any UniquePosition in the initial state.
EXPECT_EQ(0u, BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
- bookmark_bar_node, pos1.ToProto(), tracker.get()));
+ bookmark_bar_node, pos1, tracker.get()));
}
TEST(BookmarkRemoteUpdatesHandlerTest, ShouldComputeRightChildNodeIndex) {
@@ -1967,32 +1992,30 @@ TEST(BookmarkRemoteUpdatesHandlerTest, ShouldComputeRightChildNodeIndex) {
// Check for the same position as existing bookmarks have. In practice this
// shouldn't happen.
EXPECT_EQ(1u, BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
- bookmark_bar_node, pos1.ToProto(), tracker.get()));
+ bookmark_bar_node, pos1, tracker.get()));
EXPECT_EQ(2u, BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
- bookmark_bar_node, pos2.ToProto(), tracker.get()));
+ bookmark_bar_node, pos2, tracker.get()));
EXPECT_EQ(3u, BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
- bookmark_bar_node, pos3.ToProto(), tracker.get()));
+ bookmark_bar_node, pos3, tracker.get()));
- EXPECT_EQ(0u, BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
- bookmark_bar_node,
- syncer::UniquePosition::Before(pos1, suffix).ToProto(),
- tracker.get()));
+ EXPECT_EQ(0u,
+ BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
+ bookmark_bar_node, syncer::UniquePosition::Before(pos1, suffix),
+ tracker.get()));
EXPECT_EQ(1u, BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
bookmark_bar_node,
syncer::UniquePosition::Between(/*before=*/pos1,
- /*after=*/pos2, suffix)
- .ToProto(),
+ /*after=*/pos2, suffix),
tracker.get()));
EXPECT_EQ(2u, BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
bookmark_bar_node,
syncer::UniquePosition::Between(/*before=*/pos2,
- /*after=*/pos3, suffix)
- .ToProto(),
- tracker.get()));
- EXPECT_EQ(3u, BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
- bookmark_bar_node,
- syncer::UniquePosition::After(pos3, suffix).ToProto(),
+ /*after=*/pos3, suffix),
tracker.get()));
+ EXPECT_EQ(3u,
+ BookmarkRemoteUpdatesHandler::ComputeChildNodeIndexForTest(
+ bookmark_bar_node, syncer::UniquePosition::After(pos3, suffix),
+ tracker.get()));
}
} // namespace
diff --git a/chromium/components/sync_bookmarks/bookmark_specifics_conversions.cc b/chromium/components/sync_bookmarks/bookmark_specifics_conversions.cc
index 55351adf8ae..4d5642a333f 100644
--- a/chromium/components/sync_bookmarks/bookmark_specifics_conversions.cc
+++ b/chromium/components/sync_bookmarks/bookmark_specifics_conversions.cc
@@ -56,6 +56,10 @@ void LogInvalidSpecifics(InvalidBookmarkSpecificsError error) {
base::UmaHistogramEnumeration("Sync.InvalidBookmarkSpecifics", error);
}
+void LogFaviconContainedInSpecifics(bool contains_favicon) {
+ base::UmaHistogramBoolean(
+ "Sync.BookmarkSpecificsExcludingFoldersContainFavicon", contains_favicon);
+}
void UpdateBookmarkSpecificsMetaInfo(
const bookmarks::BookmarkNode::MetaInfoMap* metainfo_map,
sync_pb::BookmarkSpecifics* bm_specifics) {
@@ -86,6 +90,9 @@ void SetBookmarkFaviconFromSpecifics(
DCHECK(bookmark_node);
DCHECK(favicon_service);
+ // TODO(crbug.com/1214843): Avoid invoking this function for folders, although
+ // it's harmless in practice due to later filtering via
+ // HistoryClient::CanAddURL().
favicon_service->AddPageNoVisitForBookmark(bookmark_node->url(),
bookmark_node->GetTitle());
@@ -97,12 +104,19 @@ void SetBookmarkFaviconFromSpecifics(
GURL icon_url(specifics.icon_url());
if (icon_bytes->size() == 0 && icon_url.is_empty()) {
+ if (!bookmark_node->is_folder()) {
+ LogFaviconContainedInSpecifics(false);
+ }
// Empty icon URL and no bitmap data means no icon mapping.
favicon_service->DeleteFaviconMappings({bookmark_node->url()},
favicon_base::IconType::kFavicon);
return;
}
+ if (!bookmark_node->is_folder()) {
+ LogFaviconContainedInSpecifics(true);
+ }
+
if (icon_url.is_empty()) {
// WebUI pages such as "chrome://bookmarks/" are missing a favicon URL but
// they have a favicon. In addition, ancient clients (prior to M25) may not
@@ -286,6 +300,8 @@ const bookmarks::BookmarkNode* CreateBookmarkNodeFromSpecifics(
GetBookmarkMetaInfo(specifics);
const bookmarks::BookmarkNode* node;
if (is_folder) {
+ // TODO(crbug.com/1214840): Folders should propagate the creation time into
+ // BookmarkModel, just like non-folders.
node = model->AddFolder(parent, index, NodeTitleFromSpecifics(specifics),
&metainfo, guid);
} else {
@@ -324,8 +340,6 @@ void UpdateBookmarkNodeFromSpecifics(
SetBookmarkFaviconFromSpecifics(specifics, node, favicon_service);
}
-// TODO(crbug.com/1005219): Replace this function to move children between
-// parent nodes more efficiently.
const bookmarks::BookmarkNode* ReplaceBookmarkNodeGUID(
const bookmarks::BookmarkNode* node,
const base::GUID& guid,
diff --git a/chromium/components/sync_bookmarks/bookmark_specifics_conversions_unittest.cc b/chromium/components/sync_bookmarks/bookmark_specifics_conversions_unittest.cc
index 311e227061e..497edfd26e4 100644
--- a/chromium/components/sync_bookmarks/bookmark_specifics_conversions_unittest.cc
+++ b/chromium/components/sync_bookmarks/bookmark_specifics_conversions_unittest.cc
@@ -12,6 +12,7 @@
#include "base/guid.h"
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node.h"
@@ -25,6 +26,7 @@
using testing::_;
using testing::Eq;
+using testing::Ge;
using testing::NotNull;
namespace sync_bookmarks {
@@ -169,7 +171,8 @@ TEST(BookmarkSpecificsConversionsTest,
EXPECT_THAT(client_ptr->GetLoadFaviconRequestsForTest(), Eq(0));
}
-TEST(BookmarkSpecificsConversionsTest, ShouldCreateBookmarkNodeFromSpecifics) {
+TEST(BookmarkSpecificsConversionsTest,
+ ShouldCreateNonFolderBookmarkNodeFromSpecifics) {
const GURL kUrl("http://www.url.com");
const base::GUID kGuid = base::GUID::GenerateRandomV4();
const std::string kTitle = "Title";
@@ -203,6 +206,7 @@ TEST(BookmarkSpecificsConversionsTest, ShouldCreateBookmarkNodeFromSpecifics) {
EXPECT_CALL(favicon_service,
AddPageNoVisitForBookmark(kUrl, base::UTF8ToUTF16(kTitle)));
EXPECT_CALL(favicon_service, MergeFavicon(kUrl, kIconUrl, _, _, _));
+ base::HistogramTester histogram_tester;
const bookmarks::BookmarkNode* node = CreateBookmarkNodeFromSpecifics(
*bm_specifics,
/*parent=*/model->bookmark_bar_node(), /*index=*/0,
@@ -210,6 +214,7 @@ TEST(BookmarkSpecificsConversionsTest, ShouldCreateBookmarkNodeFromSpecifics) {
ASSERT_THAT(node, NotNull());
EXPECT_THAT(node->guid(), Eq(kGuid));
EXPECT_THAT(node->GetTitle(), Eq(base::UTF8ToUTF16(kTitle)));
+ EXPECT_FALSE(node->is_folder());
EXPECT_THAT(node->url(), Eq(kUrl));
EXPECT_THAT(node->date_added(), Eq(kTime));
std::string value1;
@@ -218,6 +223,66 @@ TEST(BookmarkSpecificsConversionsTest, ShouldCreateBookmarkNodeFromSpecifics) {
std::string value2;
node->GetMetaInfo(kKey2, &value2);
EXPECT_THAT(value2, Eq(kValue2));
+
+ histogram_tester.ExpectUniqueSample(
+ "Sync.BookmarkSpecificsExcludingFoldersContainFavicon",
+ /*sample=*/true,
+ /*expected_bucket_count=*/1);
+}
+
+TEST(BookmarkSpecificsConversionsTest, ShouldCreateFolderFromSpecifics) {
+ const base::GUID kGuid = base::GUID::GenerateRandomV4();
+ const std::string kTitle = "Title";
+ const base::Time kTime = base::Time::Now();
+ const std::string kKey1 = "key1";
+ const std::string kValue1 = "value1";
+ const std::string kKey2 = "key2";
+ const std::string kValue2 = "value2";
+
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::BookmarkSpecifics* bm_specifics = specifics.mutable_bookmark();
+ bm_specifics->set_guid(kGuid.AsLowercaseString());
+ bm_specifics->set_legacy_canonicalized_title(kTitle);
+ bm_specifics->set_creation_time_us(
+ kTime.ToDeltaSinceWindowsEpoch().InMicroseconds());
+ sync_pb::MetaInfo* meta_info1 = bm_specifics->add_meta_info();
+ meta_info1->set_key(kKey1);
+ meta_info1->set_value(kValue1);
+
+ sync_pb::MetaInfo* meta_info2 = bm_specifics->add_meta_info();
+ meta_info2->set_key(kKey2);
+ meta_info2->set_value(kValue2);
+
+ std::unique_ptr<bookmarks::BookmarkModel> model =
+ bookmarks::TestBookmarkClient::CreateModel();
+ testing::NiceMock<favicon::MockFaviconService> favicon_service;
+ // AddPageNoVisitForBookmark() is redundant and later filtered out by
+ // HistoryService, via HistoryClient::CanAddURL().
+ // TODO(crbug.com/1214843): Avoid this call for folders.
+ EXPECT_CALL(favicon_service, AddPageNoVisitForBookmark(_, _));
+ EXPECT_CALL(favicon_service, MergeFavicon(_, _, _, _, _)).Times(0);
+ base::HistogramTester histogram_tester;
+ const bookmarks::BookmarkNode* node = CreateBookmarkNodeFromSpecifics(
+ *bm_specifics,
+ /*parent=*/model->bookmark_bar_node(), /*index=*/0,
+ /*is_folder=*/true, model.get(), &favicon_service);
+ ASSERT_THAT(node, NotNull());
+ EXPECT_THAT(node->guid(), Eq(kGuid));
+ EXPECT_THAT(node->GetTitle(), Eq(base::UTF8ToUTF16(kTitle)));
+ EXPECT_TRUE(node->is_folder());
+ // TODO(crbug.com/1214840): Folders should propagate the creation time into
+ // BookmarkModel, just like non-folders.
+ EXPECT_THAT(node->date_added(), Ge(kTime));
+ std::string value1;
+ node->GetMetaInfo(kKey1, &value1);
+ EXPECT_THAT(value1, Eq(kValue1));
+ std::string value2;
+ node->GetMetaInfo(kKey2, &value2);
+ EXPECT_THAT(value2, Eq(kValue2));
+
+ // The histogram should not be recorded for folders.
+ histogram_tester.ExpectTotalCount(
+ "Sync.BookmarkSpecificsExcludingFoldersContainFavicon", 0);
}
TEST(BookmarkSpecificsConversionsTest,
diff --git a/chromium/components/sync_bookmarks/switches.cc b/chromium/components/sync_bookmarks/switches.cc
index 98281c8b208..0fc9d150240 100644
--- a/chromium/components/sync_bookmarks/switches.cc
+++ b/chromium/components/sync_bookmarks/switches.cc
@@ -11,9 +11,13 @@ const base::Feature kSyncReuploadBookmarkFullTitles{
"SyncReuploadBookmarkFullTitles", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kSyncUseClientTagForBookmarkCommits{
- "SyncUseClientTagForBookmarkCommits", base::FEATURE_DISABLED_BY_DEFAULT};
+ "SyncUseClientTagForBookmarkCommits", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kSyncReuploadBookmarksUponMatchingData{
"SyncReuploadBookmarksUponMatchingData", base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kSyncBookmarksEnforceLateMaxEntriesToCommit{
+ "SyncBookmarksEnforceLateMaxEntriesToCommit",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
} // namespace switches
diff --git a/chromium/components/sync_bookmarks/switches.h b/chromium/components/sync_bookmarks/switches.h
index c0e3009ae99..4bd996387ef 100644
--- a/chromium/components/sync_bookmarks/switches.h
+++ b/chromium/components/sync_bookmarks/switches.h
@@ -19,6 +19,10 @@ extern const base::Feature kSyncUseClientTagForBookmarkCommits;
// SyncReuploadBookmarkFullTitles is enabled.
extern const base::Feature kSyncReuploadBookmarksUponMatchingData;
+// TODO(crbug.com/1177798): remove this code after a quick verification that it
+// doesn't cause issues.
+extern const base::Feature kSyncBookmarksEnforceLateMaxEntriesToCommit;
+
} // namespace switches
#endif // COMPONENTS_SYNC_BOOKMARKS_SWITCHES_H_
diff --git a/chromium/components/sync_bookmarks/synced_bookmark_tracker.cc b/chromium/components/sync_bookmarks/synced_bookmark_tracker.cc
index 172ac957ec0..9f6f053d0f7 100644
--- a/chromium/components/sync_bookmarks/synced_bookmark_tracker.cc
+++ b/chromium/components/sync_bookmarks/synced_bookmark_tracker.cc
@@ -12,6 +12,7 @@
#include "base/guid.h"
#include "base/hash/hash.h"
#include "base/hash/sha1.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
@@ -83,7 +84,7 @@ bool SyncedBookmarkTracker::Entity::MatchesDataIgnoringParent(
return metadata_->is_deleted() == data.is_deleted();
}
if (!syncer::UniquePosition::FromProto(metadata_->unique_position())
- .Equals(syncer::UniquePosition::FromProto(data.unique_position))) {
+ .Equals(data.unique_position)) {
return false;
}
return MatchesSpecificsHash(data.specifics);
@@ -255,7 +256,7 @@ const SyncedBookmarkTracker::Entity* SyncedBookmarkTracker::Add(
const std::string& sync_id,
int64_t server_version,
base::Time creation_time,
- const sync_pb::UniquePosition& unique_position,
+ const syncer::UniquePosition& unique_position,
const sync_pb::EntitySpecifics& specifics) {
DCHECK_GT(specifics.ByteSize(), 0);
DCHECK(bookmark_node);
@@ -272,7 +273,7 @@ const SyncedBookmarkTracker::Entity* SyncedBookmarkTracker::Add(
metadata->set_modification_time(syncer::TimeToProtoTime(creation_time));
metadata->set_sequence_number(0);
metadata->set_acked_sequence_number(0);
- metadata->mutable_unique_position()->CopyFrom(unique_position);
+ *metadata->mutable_unique_position() = unique_position.ToProto();
metadata->set_client_tag_hash(client_tag_hash.value());
HashSpecifics(specifics, metadata->mutable_specifics_hash());
metadata->set_bookmark_favicon_hash(
@@ -297,7 +298,7 @@ void SyncedBookmarkTracker::Update(
const Entity* entity,
int64_t server_version,
base::Time modification_time,
- const sync_pb::UniquePosition& unique_position,
+ const syncer::UniquePosition& unique_position,
const sync_pb::EntitySpecifics& specifics) {
DCHECK_GT(specifics.ByteSize(), 0);
DCHECK(entity);
@@ -306,7 +307,8 @@ void SyncedBookmarkTracker::Update(
mutable_entity->metadata()->set_server_version(server_version);
mutable_entity->metadata()->set_modification_time(
syncer::TimeToProtoTime(modification_time));
- *mutable_entity->metadata()->mutable_unique_position() = unique_position;
+ *mutable_entity->metadata()->mutable_unique_position() =
+ unique_position.ToProto();
HashSpecifics(specifics,
mutable_entity->metadata()->mutable_specifics_hash());
mutable_entity->metadata()->set_bookmark_favicon_hash(
diff --git a/chromium/components/sync_bookmarks/synced_bookmark_tracker.h b/chromium/components/sync_bookmarks/synced_bookmark_tracker.h
index 486f4169f56..9fed53246d2 100644
--- a/chromium/components/sync_bookmarks/synced_bookmark_tracker.h
+++ b/chromium/components/sync_bookmarks/synced_bookmark_tracker.h
@@ -16,7 +16,6 @@
#include "components/sync/base/client_tag_hash.h"
#include "components/sync/protocol/bookmark_model_metadata.pb.h"
#include "components/sync/protocol/entity_metadata.pb.h"
-#include "components/sync/protocol/unique_position.pb.h"
namespace base {
class GUID;
@@ -30,6 +29,7 @@ class BookmarkNode;
namespace syncer {
class ClientTagHash;
struct EntityData;
+class UniquePosition;
} // namespace syncer
namespace sync_bookmarks {
@@ -154,7 +154,7 @@ class SyncedBookmarkTracker {
const std::string& sync_id,
int64_t server_version,
base::Time creation_time,
- const sync_pb::UniquePosition& unique_position,
+ const syncer::UniquePosition& unique_position,
const sync_pb::EntitySpecifics& specifics);
// Updates the sync metadata for a tracked entity. |entity| must be owned by
@@ -162,7 +162,7 @@ class SyncedBookmarkTracker {
void Update(const Entity* entity,
int64_t server_version,
base::Time modification_time,
- const sync_pb::UniquePosition& unique_position,
+ const syncer::UniquePosition& unique_position,
const sync_pb::EntitySpecifics& specifics);
// Updates the server version of an existing entity. |entity| must be owned by
diff --git a/chromium/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc b/chromium/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
index ae1d2098fba..68cac7a814d 100644
--- a/chromium/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
+++ b/chromium/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
@@ -129,7 +129,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldAddEntity) {
bookmarks::BookmarkNode node(kId, kGuid, kUrl);
const SyncedBookmarkTracker::Entity* entity =
tracker->Add(&node, kSyncId, kServerVersion, kCreationTime,
- unique_position.ToProto(), specifics);
+ unique_position, specifics);
ASSERT_THAT(entity, NotNull());
EXPECT_THAT(entity->bookmark_node(), Eq(&node));
EXPECT_THAT(entity->GetClientTagHash(),
@@ -151,7 +151,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldAddEntity) {
syncer::EntityData data;
*data.specifics.mutable_bookmark() = specifics.bookmark();
- data.unique_position = unique_position.ToProto();
+ data.unique_position = unique_position;
EXPECT_TRUE(entity->MatchesDataIgnoringParent(data));
EXPECT_THAT(tracker->GetEntityForSyncId("unknown id"), IsNull());
@@ -167,7 +167,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldRemoveEntity) {
const int64_t kServerVersion = 1000;
const base::Time kModificationTime(base::Time::Now() -
base::TimeDelta::FromSeconds(1));
- const sync_pb::UniquePosition unique_position;
+ const syncer::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
bookmarks::BookmarkNode node(kId, kGuid, GURL());
@@ -210,8 +210,8 @@ TEST(SyncedBookmarkTrackerTest, ShouldBuildBookmarkModelMetadata) {
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
bookmarks::BookmarkNode node(kId, base::GUID::GenerateRandomV4(), kUrl);
- tracker->Add(&node, kSyncId, kServerVersion, kCreationTime,
- unique_position.ToProto(), specifics);
+ tracker->Add(&node, kSyncId, kServerVersion, kCreationTime, unique_position,
+ specifics);
sync_pb::BookmarkModelMetadata bookmark_model_metadata =
tracker->BuildBookmarkModelMetadata();
@@ -233,7 +233,7 @@ TEST(SyncedBookmarkTrackerTest,
const int64_t kServerVersion = 1000;
const base::Time kModificationTime(base::Time::Now() -
base::TimeDelta::FromSeconds(1));
- const sync_pb::UniquePosition unique_position;
+ const syncer::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
bookmarks::BookmarkNode node(kId, base::GUID::GenerateRandomV4(), GURL());
@@ -257,7 +257,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldAckSequenceNumber) {
const int64_t kServerVersion = 1000;
const base::Time kModificationTime(base::Time::Now() -
base::TimeDelta::FromSeconds(1));
- const sync_pb::UniquePosition unique_position;
+ const syncer::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
bookmarks::BookmarkNode node(kId, base::GUID::GenerateRandomV4(), GURL());
@@ -293,7 +293,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldUpdateUponCommitResponseWithNewId) {
const int64_t kNewServerVersion = 1001;
const base::Time kModificationTime(base::Time::Now() -
base::TimeDelta::FromSeconds(1));
- const sync_pb::UniquePosition unique_position;
+ const syncer::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
bookmarks::BookmarkNode node(kId, base::GUID::GenerateRandomV4(), GURL());
@@ -328,7 +328,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldUpdateId) {
const int64_t kServerVersion = 1000;
const base::Time kModificationTime(base::Time::Now() -
base::TimeDelta::FromSeconds(1));
- const sync_pb::UniquePosition unique_position;
+ const syncer::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
bookmarks::BookmarkNode node(/*id=*/1, base::GUID::GenerateRandomV4(),
@@ -491,7 +491,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldMarkDeleted) {
const int64_t kServerVersion = 1000;
const base::Time kModificationTime(base::Time::Now() -
base::TimeDelta::FromSeconds(1));
- const sync_pb::UniquePosition unique_position;
+ const syncer::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
bookmarks::BookmarkNode node(kId, kGuid, GURL());
@@ -533,7 +533,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldUndeleteTombstone) {
const int64_t kServerVersion = 1000;
const base::Time kModificationTime(base::Time::Now() -
base::TimeDelta::FromSeconds(1));
- const sync_pb::UniquePosition unique_position;
+ const syncer::UniquePosition unique_position;
const sync_pb::EntitySpecifics specifics =
GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
bookmarks::BookmarkNode node(kId, kGuid, GURL());
@@ -1029,7 +1029,7 @@ TEST(SyncedBookmarkTrackerTest,
bookmarks::BookmarkNode node(kId, base::GUID::GenerateRandomV4(), kUrl);
const SyncedBookmarkTracker::Entity* entity =
tracker->Add(&node, kSyncId, kServerVersion, kCreationTime,
- kUniquePosition.ToProto(), specifics);
+ kUniquePosition, specifics);
EXPECT_TRUE(entity->metadata()->has_bookmark_favicon_hash());
EXPECT_TRUE(entity->MatchesFaviconHash(kFaviconPngBytes));
@@ -1075,8 +1075,8 @@ TEST(SyncedBookmarkTrackerTest, ShouldPopulateFaviconHashUponUpdate) {
sync_pb::EntitySpecifics specifics = GenerateSpecifics(kTitle, kUrl.spec());
specifics.mutable_bookmark()->set_favicon(kFaviconPngBytes);
- tracker->Update(entity, kServerVersion, kModificationTime,
- kUniquePosition.ToProto(), specifics);
+ tracker->Update(entity, kServerVersion, kModificationTime, kUniquePosition,
+ specifics);
EXPECT_TRUE(entity->metadata()->has_bookmark_favicon_hash());
EXPECT_TRUE(entity->MatchesFaviconHash(kFaviconPngBytes));
@@ -1147,8 +1147,7 @@ TEST(SyncedBookmarkTrackerTest, ShouldNotReuploadEntitiesAfterMergeAndRestart) {
tracker->Add(node, /*sync_id=*/"id", /*server_version=*/0,
/*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
specifics);
sync_pb::EntitySpecifics permanent_specifics;
@@ -1158,20 +1157,17 @@ TEST(SyncedBookmarkTrackerTest, ShouldNotReuploadEntitiesAfterMergeAndRestart) {
tracker->Add(model->bookmark_bar_node(), kBookmarkBarId, /*server_version=*/0,
/*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
permanent_specifics);
tracker->Add(model->other_node(), kOtherBookmarksId, /*server_version=*/0,
/*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
permanent_specifics);
tracker->Add(model->mobile_node(), kMobileBookmarksId, /*server_version=*/0,
/*creation_time=*/base::Time::Now(),
syncer::UniquePosition::InitialPosition(
- syncer::UniquePosition::RandomSuffix())
- .ToProto(),
+ syncer::UniquePosition::RandomSuffix()),
permanent_specifics);
ASSERT_FALSE(tracker->HasLocalChanges());
diff --git a/chromium/components/sync_device_info/device_info.cc b/chromium/components/sync_device_info/device_info.cc
index 8e69e4f8169..7f333351051 100644
--- a/chromium/components/sync_device_info/device_info.cc
+++ b/chromium/components/sync_device_info/device_info.cc
@@ -4,9 +4,15 @@
#include "components/sync_device_info/device_info.h"
+// device_info.h's size can impact build time. Try not to raise this limit
+// unless absolutely necessary. See
+// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/wmax_tokens.md
+#pragma clang max_tokens_here 505000
+
#include <utility>
#include "base/values.h"
+#include "components/sync/protocol/sync.pb.h"
namespace syncer {
@@ -70,8 +76,8 @@ DeviceInfo::DeviceInfo(
base::Time last_updated_timestamp,
base::TimeDelta pulse_interval,
bool send_tab_to_self_receiving_enabled,
- const base::Optional<SharingInfo>& sharing_info,
- const base::Optional<PhoneAsASecurityKeyInfo>& paask_info,
+ const absl::optional<SharingInfo>& sharing_info,
+ const absl::optional<PhoneAsASecurityKeyInfo>& paask_info,
const std::string& fcm_registration_token,
const ModelTypeSet& interested_data_types)
: guid_(guid),
@@ -145,12 +151,12 @@ bool DeviceInfo::send_tab_to_self_receiving_enabled() const {
return send_tab_to_self_receiving_enabled_;
}
-const base::Optional<DeviceInfo::SharingInfo>& DeviceInfo::sharing_info()
+const absl::optional<DeviceInfo::SharingInfo>& DeviceInfo::sharing_info()
const {
return sharing_info_;
}
-const base::Optional<DeviceInfo::PhoneAsASecurityKeyInfo>&
+const absl::optional<DeviceInfo::PhoneAsASecurityKeyInfo>&
DeviceInfo::paask_info() const {
return paask_info_;
}
@@ -247,7 +253,7 @@ void DeviceInfo::set_send_tab_to_self_receiving_enabled(bool new_value) {
}
void DeviceInfo::set_sharing_info(
- const base::Optional<SharingInfo>& sharing_info) {
+ const absl::optional<SharingInfo>& sharing_info) {
sharing_info_ = sharing_info;
}
diff --git a/chromium/components/sync_device_info/device_info.h b/chromium/components/sync_device_info/device_info.h
index c16d57e97fb..832bc5eb8f6 100644
--- a/chromium/components/sync_device_info/device_info.h
+++ b/chromium/components/sync_device_info/device_info.h
@@ -12,15 +12,19 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/sync/base/model_type.h"
-#include "components/sync/protocol/sync.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class DictionaryValue;
}
+namespace sync_pb {
+enum SharingSpecificFields_EnabledFeatures : int;
+enum SyncEnums_DeviceType : int;
+} // namespace sync_pb
+
namespace syncer {
// A class that holds information regarding the properties of a device.
@@ -44,7 +48,7 @@ class DeviceInfo {
struct SharingInfo {
SharingInfo(SharingTargetInfo vapid_target_info,
SharingTargetInfo sharing_target_info,
- std::set<sync_pb::SharingSpecificFields::EnabledFeatures>
+ std::set<sync_pb::SharingSpecificFields_EnabledFeatures>
enabled_features);
SharingInfo(const SharingInfo& other);
SharingInfo(SharingInfo&& other);
@@ -59,7 +63,7 @@ class DeviceInfo {
SharingTargetInfo sender_id_target_info;
// Set of Sharing features enabled on the device.
- std::set<sync_pb::SharingSpecificFields::EnabledFeatures> enabled_features;
+ std::set<sync_pb::SharingSpecificFields_EnabledFeatures> enabled_features;
bool operator==(const SharingInfo& other) const;
};
@@ -93,7 +97,7 @@ class DeviceInfo {
const std::string& client_name,
const std::string& chrome_version,
const std::string& sync_user_agent,
- const sync_pb::SyncEnums::DeviceType device_type,
+ const sync_pb::SyncEnums_DeviceType device_type,
const std::string& signin_scoped_device_id,
const std::string& manufacturer_name,
const std::string& model_name,
@@ -101,8 +105,8 @@ class DeviceInfo {
base::Time last_updated_timestamp,
base::TimeDelta pulse_interval,
bool send_tab_to_self_receiving_enabled,
- const base::Optional<SharingInfo>& sharing_info,
- const base::Optional<PhoneAsASecurityKeyInfo>& paask_info,
+ const absl::optional<SharingInfo>& sharing_info,
+ const absl::optional<PhoneAsASecurityKeyInfo>& paask_info,
const std::string& fcm_registration_token,
const ModelTypeSet& interested_data_types);
~DeviceInfo();
@@ -128,7 +132,7 @@ class DeviceInfo {
const std::string& public_id() const;
// Device Type.
- sync_pb::SyncEnums::DeviceType device_type() const;
+ sync_pb::SyncEnums_DeviceType device_type() const;
// Device_id that is stable until user signs out. This device_id is used for
// annotating login scoped refresh token.
@@ -157,9 +161,9 @@ class DeviceInfo {
bool send_tab_to_self_receiving_enabled() const;
// Returns Sharing related info of the device.
- const base::Optional<SharingInfo>& sharing_info() const;
+ const absl::optional<SharingInfo>& sharing_info() const;
- const base::Optional<PhoneAsASecurityKeyInfo>& paask_info() const;
+ const absl::optional<PhoneAsASecurityKeyInfo>& paask_info() const;
// Returns the FCM registration token for sync invalidations.
const std::string& fcm_registration_token() const;
@@ -186,7 +190,7 @@ class DeviceInfo {
void set_send_tab_to_self_receiving_enabled(bool new_value);
- void set_sharing_info(const base::Optional<SharingInfo>& sharing_info);
+ void set_sharing_info(const absl::optional<SharingInfo>& sharing_info);
void set_paask_info(PhoneAsASecurityKeyInfo&& paask_info);
@@ -209,7 +213,7 @@ class DeviceInfo {
const std::string sync_user_agent_;
- const sync_pb::SyncEnums::DeviceType device_type_;
+ const sync_pb::SyncEnums_DeviceType device_type_;
const std::string signin_scoped_device_id_;
@@ -231,9 +235,9 @@ class DeviceInfo {
bool send_tab_to_self_receiving_enabled_;
- base::Optional<SharingInfo> sharing_info_;
+ absl::optional<SharingInfo> sharing_info_;
- base::Optional<PhoneAsASecurityKeyInfo> paask_info_;
+ absl::optional<PhoneAsASecurityKeyInfo> paask_info_;
// An FCM registration token obtained by sync invalidations service.
std::string fcm_registration_token_;
diff --git a/chromium/components/sync_device_info/device_info_prefs.cc b/chromium/components/sync_device_info/device_info_prefs.cc
index d3a47f1e94d..5816536961f 100644
--- a/chromium/components/sync_device_info/device_info_prefs.cc
+++ b/chromium/components/sync_device_info/device_info_prefs.cc
@@ -113,7 +113,7 @@ void DeviceInfoPrefs::GarbageCollectExpiredCacheGuids() {
return true;
}
- base::Optional<int> days_since_epoch = dict.FindIntKey(kTimestampKey);
+ absl::optional<int> days_since_epoch = dict.FindIntKey(kTimestampKey);
// Avoid crashes if the dictionary contains no timestamp and meanwhile clean
// up these corrupt entries.
diff --git a/chromium/components/sync_device_info/device_info_sync_bridge.cc b/chromium/components/sync_device_info/device_info_sync_bridge.cc
index 8216d6e1161..5d56e530777 100644
--- a/chromium/components/sync_device_info/device_info_sync_bridge.cc
+++ b/chromium/components/sync_device_info/device_info_sync_bridge.cc
@@ -66,10 +66,10 @@ TimeDelta GetPulseIntervalFromSpecifics(const DeviceInfoSpecifics& specifics) {
return TimeDelta::FromDays(1);
}
-base::Optional<DeviceInfo::SharingInfo> SpecificsToSharingInfo(
+absl::optional<DeviceInfo::SharingInfo> SpecificsToSharingInfo(
const DeviceInfoSpecifics& specifics) {
if (!specifics.has_sharing_fields()) {
- return base::nullopt;
+ return absl::nullopt;
}
std::set<SharingSpecificFields::EnabledFeatures> enabled_features;
@@ -91,10 +91,10 @@ std::vector<uint8_t> VectorFromString(const std::string& s) {
return std::vector<uint8_t>(ptr, ptr + s.size());
}
-base::Optional<DeviceInfo::PhoneAsASecurityKeyInfo>
+absl::optional<DeviceInfo::PhoneAsASecurityKeyInfo>
SpecificsToPhoneAsASecurityKeyInfo(const DeviceInfoSpecifics& specifics) {
if (!specifics.has_paask_fields()) {
- return base::nullopt;
+ return absl::nullopt;
}
DeviceInfo::PhoneAsASecurityKeyInfo to;
@@ -103,19 +103,19 @@ SpecificsToPhoneAsASecurityKeyInfo(const DeviceInfoSpecifics& specifics) {
!from.has_contact_id() || !from.has_secret() ||
!from.has_peer_public_key_x962() ||
from.tunnel_server_domain() >= 0x10000) {
- return base::nullopt;
+ return absl::nullopt;
}
to.tunnel_server_domain = from.tunnel_server_domain();
to.id = from.id();
to.contact_id = VectorFromString(from.contact_id());
if (from.secret().size() != to.secret.size()) {
- return base::nullopt;
+ return absl::nullopt;
}
memcpy(to.secret.data(), from.secret().data(), to.secret.size());
if (from.peer_public_key_x962().size() != to.peer_public_key_x962.size()) {
- return base::nullopt;
+ return absl::nullopt;
}
memcpy(to.peer_public_key_x962.data(), from.peer_public_key_x962().data(),
to.peer_public_key_x962.size());
@@ -123,6 +123,23 @@ SpecificsToPhoneAsASecurityKeyInfo(const DeviceInfoSpecifics& specifics) {
return to;
}
+std::string GetVersionNumberFromSpecifics(
+ const DeviceInfoSpecifics& specifics) {
+ // The new field takes precedence, if populated.
+ if (specifics.has_chrome_version_info()) {
+ return specifics.chrome_version_info().version_number();
+ }
+
+ // Fall back to the legacy proto field.
+ return specifics.chrome_version();
+}
+
+// Returns true if |speifics| represents a client that is
+// chromium-based and hence exposed in DeviceInfoTracker.
+bool IsChromeClient(const DeviceInfoSpecifics& specifics) {
+ return specifics.has_chrome_version_info() || specifics.has_chrome_version();
+}
+
// Converts DeviceInfoSpecifics into a freshly allocated DeviceInfo.
std::unique_ptr<DeviceInfo> SpecificsToModel(
const DeviceInfoSpecifics& specifics) {
@@ -139,7 +156,7 @@ std::unique_ptr<DeviceInfo> SpecificsToModel(
return std::make_unique<DeviceInfo>(
specifics.cache_guid(), specifics.client_name(),
- specifics.chrome_version(), specifics.sync_user_agent(),
+ GetVersionNumberFromSpecifics(specifics), specifics.sync_user_agent(),
specifics.device_type(), specifics.signin_scoped_device_id(),
specifics.manufacturer(), specifics.model(),
specifics.full_hardware_class(),
@@ -180,6 +197,8 @@ std::unique_ptr<DeviceInfoSpecifics> MakeLocalDeviceSpecifics(
specifics->set_cache_guid(info.guid());
specifics->set_client_name(info.client_name());
specifics->set_chrome_version(info.chrome_version());
+ specifics->mutable_chrome_version_info()->set_version_number(
+ info.chrome_version());
specifics->set_sync_user_agent(info.sync_user_agent());
specifics->set_device_type(info.device_type());
specifics->set_signin_scoped_device_id(info.signin_scoped_device_id());
@@ -201,7 +220,7 @@ std::unique_ptr<DeviceInfoSpecifics> MakeLocalDeviceSpecifics(
feature_fields->set_send_tab_to_self_receiving_enabled(
info.send_tab_to_self_receiving_enabled());
- const base::Optional<DeviceInfo::SharingInfo>& sharing_info =
+ const absl::optional<DeviceInfo::SharingInfo>& sharing_info =
info.sharing_info();
if (sharing_info) {
SharingSpecificFields* sharing_fields = specifics->mutable_sharing_fields();
@@ -222,7 +241,7 @@ std::unique_ptr<DeviceInfoSpecifics> MakeLocalDeviceSpecifics(
}
}
- const base::Optional<DeviceInfo::PhoneAsASecurityKeyInfo>& paask_info =
+ const absl::optional<DeviceInfo::PhoneAsASecurityKeyInfo>& paask_info =
info.paask_info();
if (paask_info) {
*specifics->mutable_paask_fields() =
@@ -244,7 +263,7 @@ std::unique_ptr<DeviceInfoSpecifics> MakeLocalDeviceSpecifics(
// Parses the content of |record_list| into |*all_data|. The output
// parameter is first for binding purposes.
-base::Optional<ModelError> ParseSpecificsOnBackendSequence(
+absl::optional<ModelError> ParseSpecificsOnBackendSequence(
ClientIdToSpecifics* all_data,
std::unique_ptr<ModelTypeStore::RecordList> record_list) {
DCHECK(all_data);
@@ -261,7 +280,7 @@ base::Optional<ModelError> ParseSpecificsOnBackendSequence(
all_data->emplace(specifics->cache_guid(), std::move(specifics));
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace
@@ -337,7 +356,7 @@ DeviceInfoSyncBridge::CreateMetadataChangeList() {
return WriteBatch::CreateMetadataChangeList();
}
-base::Optional<ModelError> DeviceInfoSyncBridge::MergeSyncData(
+absl::optional<ModelError> DeviceInfoSyncBridge::MergeSyncData(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_data) {
DCHECK(change_processor()->IsTrackingMetadata());
@@ -370,10 +389,10 @@ base::Optional<ModelError> DeviceInfoSyncBridge::MergeSyncData(
batch->TakeMetadataChangesFrom(std::move(metadata_change_list));
// Complete batch with local data and commit.
SendLocalDataWithBatch(std::move(batch));
- return base::nullopt;
+ return absl::nullopt;
}
-base::Optional<ModelError> DeviceInfoSyncBridge::ApplySyncChanges(
+absl::optional<ModelError> DeviceInfoSyncBridge::ApplySyncChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_changes) {
std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
@@ -410,7 +429,7 @@ base::Optional<ModelError> DeviceInfoSyncBridge::ApplySyncChanges(
device_info_synced_callback_list_.clear();
}
- return base::nullopt;
+ return absl::nullopt;
}
void DeviceInfoSyncBridge::GetData(StorageKeyList storage_keys,
@@ -482,6 +501,9 @@ std::unique_ptr<DeviceInfo> DeviceInfoSyncBridge::GetDeviceInfo(
if (iter == all_data_.end()) {
return nullptr;
}
+ if (!IsChromeClient(*iter->second)) {
+ return nullptr;
+ }
return SpecificsToModel(*iter->second);
}
@@ -489,7 +511,9 @@ std::vector<std::unique_ptr<DeviceInfo>>
DeviceInfoSyncBridge::GetAllDeviceInfo() const {
std::vector<std::unique_ptr<DeviceInfo>> list;
for (auto iter = all_data_.begin(); iter != all_data_.end(); ++iter) {
- list.push_back(SpecificsToModel(*iter->second));
+ if (IsChromeClient(*iter->second)) {
+ list.push_back(SpecificsToModel(*iter->second));
+ }
}
return list;
}
@@ -558,7 +582,7 @@ std::string DeviceInfoSyncBridge::GetLocalClientName() const {
}
void DeviceInfoSyncBridge::OnStoreCreated(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<ModelTypeStore> store) {
if (error) {
change_processor()->ReportError(*error);
@@ -588,7 +612,7 @@ void DeviceInfoSyncBridge::OnLocalDeviceNameInfoRetrieved(
void DeviceInfoSyncBridge::OnReadAllData(
std::unique_ptr<ClientIdToSpecifics> all_data,
- const base::Optional<syncer::ModelError>& error) {
+ const absl::optional<syncer::ModelError>& error) {
DCHECK(all_data);
if (error) {
@@ -604,7 +628,7 @@ void DeviceInfoSyncBridge::OnReadAllData(
}
void DeviceInfoSyncBridge::OnReadAllMetadata(
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<MetadataBatch> metadata_batch) {
if (error) {
change_processor()->ReportError(*error);
@@ -680,7 +704,7 @@ void DeviceInfoSyncBridge::OnReadAllMetadata(
}
void DeviceInfoSyncBridge::OnCommit(
- const base::Optional<syncer::ModelError>& error) {
+ const absl::optional<syncer::ModelError>& error) {
if (error) {
change_processor()->ReportError(*error);
}
@@ -765,6 +789,10 @@ int DeviceInfoSyncBridge::CountActiveDevices(const Time now) const {
relevant_events;
for (const auto& pair : all_data_) {
+ if (!IsChromeClient(*pair.second)) {
+ continue;
+ }
+
if (DeviceInfoUtil::IsActive(GetLastUpdateTime(*pair.second), now)) {
base::Time begin = change_processor()->GetEntityCreationTime(pair.first);
base::Time end =
diff --git a/chromium/components/sync_device_info/device_info_sync_bridge.h b/chromium/components/sync_device_info/device_info_sync_bridge.h
index 1211d68291c..d0e954d1b06 100644
--- a/chromium/components/sync_device_info/device_info_sync_bridge.h
+++ b/chromium/components/sync_device_info/device_info_sync_bridge.h
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/sync/base/sync_mode.h"
@@ -23,6 +22,7 @@
#include "components/sync_device_info/device_info_tracker.h"
#include "components/sync_device_info/local_device_info_provider.h"
#include "components/sync_device_info/local_device_info_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sync_pb {
class DeviceInfoSpecifics;
@@ -60,10 +60,10 @@ class DeviceInfoSyncBridge : public ModelTypeSyncBridge,
// ModelTypeSyncBridge implementation.
void OnSyncStarting(const DataTypeActivationRequest& request) override;
std::unique_ptr<MetadataChangeList> CreateMetadataChangeList() override;
- base::Optional<ModelError> MergeSyncData(
+ absl::optional<ModelError> MergeSyncData(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_data) override;
- base::Optional<ModelError> ApplySyncChanges(
+ absl::optional<ModelError> ApplySyncChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
@@ -109,16 +109,16 @@ class DeviceInfoSyncBridge : public ModelTypeSyncBridge,
void NotifyObservers();
// Methods used as callbacks given to DataTypeStore.
- void OnStoreCreated(const base::Optional<syncer::ModelError>& error,
+ void OnStoreCreated(const absl::optional<syncer::ModelError>& error,
std::unique_ptr<ModelTypeStore> store);
void OnLocalDeviceNameInfoRetrieved(
LocalDeviceNameInfo local_device_name_info);
void OnReadAllData(std::unique_ptr<ClientIdToSpecifics> all_data,
- const base::Optional<syncer::ModelError>& error);
+ const absl::optional<syncer::ModelError>& error);
void OnSyncInvalidationsInitialized();
- void OnReadAllMetadata(const base::Optional<syncer::ModelError>& error,
+ void OnReadAllMetadata(const absl::optional<syncer::ModelError>& error,
std::unique_ptr<MetadataBatch> metadata_batch);
- void OnCommit(const base::Optional<syncer::ModelError>& error);
+ void OnCommit(const absl::optional<syncer::ModelError>& error);
// Performs reconciliation between the locally provided device info and the
// stored device info data. If the sets of data differ, then we consider this
@@ -157,7 +157,7 @@ class DeviceInfoSyncBridge : public ModelTypeSyncBridge,
LocalDeviceNameInfo local_device_name_info_;
- base::Optional<SyncMode> sync_mode_;
+ absl::optional<SyncMode> sync_mode_;
// Registered observers, not owned.
base::ObserverList<Observer, true>::Unchecked observers_;
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 f2c086c04e7..b57bb2b6fa4 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
@@ -30,6 +30,7 @@
#include "components/sync_device_info/device_info_prefs.h"
#include "components/sync_device_info/device_info_util.h"
#include "components/sync_device_info/local_device_info_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -375,7 +376,7 @@ class TestLocalDeviceInfoProvider : public MutableLocalDeviceInfoProvider {
SharingSenderIdP256dhForSuffix(kLocalSuffix),
SharingSenderIdAuthSecretForSuffix(kLocalSuffix)},
sharing_enabled_features),
- /*paask_info=*/base::nullopt, last_fcm_registration_token,
+ /*paask_info=*/absl::nullopt, last_fcm_registration_token,
last_interested_data_types);
}
@@ -421,8 +422,8 @@ class TestLocalDeviceInfoProvider : public MutableLocalDeviceInfoProvider {
private:
std::unique_ptr<DeviceInfo> local_device_info_;
- base::Optional<std::string> fcm_registration_token_;
- base::Optional<ModelTypeSet> interested_data_types_;
+ absl::optional<std::string> fcm_registration_token_;
+ absl::optional<ModelTypeSet> interested_data_types_;
DISALLOW_COPY_AND_ASSIGN(TestLocalDeviceInfoProvider);
}; // namespace
@@ -564,7 +565,7 @@ class DeviceInfoSyncBridgeTest : public testing::Test,
store()->CommitWriteBatch(
std::move(batch),
base::BindOnce(
- [](base::RunLoop* loop, const base::Optional<ModelError>& result) {
+ [](base::RunLoop* loop, const absl::optional<ModelError>& result) {
EXPECT_FALSE(result.has_value()) << result->ToString();
loop->Quit();
},
@@ -597,7 +598,7 @@ class DeviceInfoSyncBridgeTest : public testing::Test,
base::RunLoop loop;
store()->ReadAllData(base::BindOnce(
[](std::unique_ptr<ModelTypeStore::RecordList>* output_records,
- base::RunLoop* loop, const base::Optional<syncer::ModelError>& error,
+ base::RunLoop* loop, const absl::optional<syncer::ModelError>& error,
std::unique_ptr<ModelTypeStore::RecordList> input_records) {
EXPECT_FALSE(error) << error->ToString();
EXPECT_THAT(input_records, NotNull());
@@ -1150,6 +1151,48 @@ TEST_F(DeviceInfoSyncBridgeTest, CountActiveDevicesWithMalformedTimestamps) {
EXPECT_EQ(1, bridge()->CountActiveDevices());
}
+TEST_F(DeviceInfoSyncBridgeTest,
+ ShouldFilterOutNonChromeClientsFromDeviceTracker) {
+ InitializeAndMergeInitialData(SyncMode::kFull);
+ // Local device.
+ EXPECT_EQ(1, bridge()->CountActiveDevices());
+
+ ON_CALL(*processor(), GetEntityCreationTime)
+ .WillByDefault(Return(base::Time::Now()));
+ ON_CALL(*processor(), GetEntityModificationTime)
+ .WillByDefault(Return(base::Time::Now()));
+
+ // A different guid will contribute to the count.
+ bridge()->ApplySyncChanges(bridge()->CreateMetadataChangeList(),
+ EntityAddList({CreateSpecifics(1)}));
+ ASSERT_THAT(GetAllData(), SizeIs(2));
+ ASSERT_THAT(bridge()->GetAllDeviceInfo(), SizeIs(2));
+ ASSERT_EQ(2, bridge()->CountActiveDevices());
+ ASSERT_THAT(bridge()->GetDeviceInfo(CacheGuidForSuffix(1)), NotNull());
+
+ // If the Chrome version is not present, it should not be exposed as device.
+ sync_pb::DeviceInfoSpecifics specifics2 = CreateSpecifics(2);
+ specifics2.clear_chrome_version();
+ bridge()->ApplySyncChanges(bridge()->CreateMetadataChangeList(),
+ EntityAddList({specifics2}));
+ ASSERT_THAT(GetAllData(), SizeIs(3));
+ EXPECT_THAT(bridge()->GetAllDeviceInfo(), SizeIs(2));
+ EXPECT_EQ(2, bridge()->CountActiveDevices());
+ EXPECT_THAT(bridge()->GetDeviceInfo(CacheGuidForSuffix(2)), IsNull());
+
+ // If only the non-legacy field is present, the device should still be exposed
+ // in DeviceInfoTracker.
+ sync_pb::DeviceInfoSpecifics specifics3 = CreateSpecifics(3);
+ specifics3.clear_chrome_version();
+ specifics3.mutable_chrome_version_info()->set_version_number("someversion");
+ bridge()->ApplySyncChanges(bridge()->CreateMetadataChangeList(),
+ EntityAddList({specifics3}));
+ ASSERT_THAT(GetAllData(), SizeIs(4));
+ EXPECT_THAT(bridge()->GetAllDeviceInfo(), SizeIs(3));
+ EXPECT_EQ(3, bridge()->CountActiveDevices());
+ EXPECT_THAT(bridge()->GetDeviceInfo(CacheGuidForSuffix(3)), NotNull());
+}
+
TEST_F(DeviceInfoSyncBridgeTest, SendLocalData) {
// Ensure |last_updated| is about now, plus or minus a little bit.
EXPECT_CALL(*processor(), Put(_, HasSpecifics(HasLastUpdatedAboutNow()), _));
diff --git a/chromium/components/sync_device_info/device_info_sync_client.h b/chromium/components/sync_device_info/device_info_sync_client.h
index 459a1ed5d10..51f25b43e0a 100644
--- a/chromium/components/sync_device_info/device_info_sync_client.h
+++ b/chromium/components/sync_device_info/device_info_sync_client.h
@@ -7,9 +7,9 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/sync/base/model_type.h"
#include "components/sync_device_info/device_info.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace syncer {
@@ -21,20 +21,20 @@ class DeviceInfoSyncClient {
virtual std::string GetSigninScopedDeviceId() const = 0;
virtual bool GetSendTabToSelfReceivingEnabled() const = 0;
- virtual base::Optional<DeviceInfo::SharingInfo> GetLocalSharingInfo()
+ virtual absl::optional<DeviceInfo::SharingInfo> GetLocalSharingInfo()
const = 0;
// Returns current FCM registration token if known, empty if the invalidation
- // service is not enabled. base::nullopt will be returned if the token has
+ // service is not enabled. absl::nullopt will be returned if the token has
// been requested but hasn't been retrieved yet.
- virtual base::Optional<std::string> GetFCMRegistrationToken() const = 0;
+ virtual absl::optional<std::string> GetFCMRegistrationToken() const = 0;
- // A list of enabled data types, base::nullopt if the invalidation service is
+ // A list of enabled data types, absl::nullopt if the invalidation service is
// not initialized yet.
- virtual base::Optional<ModelTypeSet> GetInterestedDataTypes() const = 0;
+ virtual absl::optional<ModelTypeSet> GetInterestedDataTypes() const = 0;
// Returns registration information for using a phone-as-a-security-key.
- virtual base::Optional<DeviceInfo::PhoneAsASecurityKeyInfo>
+ virtual absl::optional<DeviceInfo::PhoneAsASecurityKeyInfo>
GetPhoneAsASecurityKeyInfo() const = 0;
// Returns whether a CrOS device has User Metric Analysis (UMA) enabled.
diff --git a/chromium/components/sync_device_info/device_info_sync_service.h b/chromium/components/sync_device_info/device_info_sync_service.h
index 6ca64fc8fa2..f77a3baac5c 100644
--- a/chromium/components/sync_device_info/device_info_sync_service.h
+++ b/chromium/components/sync_device_info/device_info_sync_service.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_SYNC_DEVICE_INFO_DEVICE_INFO_SYNC_SERVICE_H_
#define COMPONENTS_SYNC_DEVICE_INFO_DEVICE_INFO_SYNC_SERVICE_H_
-#include <memory>
-#include <string>
-
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/sync_device_info/device_info_sync_service_impl.h b/chromium/components/sync_device_info/device_info_sync_service_impl.h
index b2209dabac1..7be70a9c1d9 100644
--- a/chromium/components/sync_device_info/device_info_sync_service_impl.h
+++ b/chromium/components/sync_device_info/device_info_sync_service_impl.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SYNC_DEVICE_INFO_DEVICE_INFO_SYNC_SERVICE_IMPL_H_
#include <memory>
-#include <string>
#include "base/callback_helpers.h"
#include "components/sync/invalidations/fcm_registration_token_observer.h"
diff --git a/chromium/components/sync_device_info/device_info_tracker.h b/chromium/components/sync_device_info/device_info_tracker.h
index 36657799e5b..0b88ee513e8 100644
--- a/chromium/components/sync_device_info/device_info_tracker.h
+++ b/chromium/components/sync_device_info/device_info_tracker.h
@@ -13,7 +13,8 @@
namespace syncer {
-// Interface for tracking synced DeviceInfo.
+// Interface for tracking synced DeviceInfo. This excludes sync-ing clients that
+// are not chromium-based.
class DeviceInfoTracker {
public:
virtual ~DeviceInfoTracker() {}
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 15a8789635e..9e491b822eb 100644
--- a/chromium/components/sync_device_info/fake_device_info_tracker.h
+++ b/chromium/components/sync_device_info/fake_device_info_tracker.h
@@ -11,8 +11,8 @@
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "components/sync_device_info/device_info_tracker.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace syncer {
@@ -49,7 +49,7 @@ class FakeDeviceInfoTracker : public DeviceInfoTracker {
// DeviceInfo stored here are not owned.
std::vector<const DeviceInfo*> devices_;
std::string local_device_cache_guid_;
- base::Optional<int> active_device_count_;
+ absl::optional<int> active_device_count_;
// Registered observers, not owned.
base::ObserverList<Observer, true>::Unchecked observers_;
diff --git a/chromium/components/sync_device_info/fake_local_device_info_provider.cc b/chromium/components/sync_device_info/fake_local_device_info_provider.cc
index 1a169a0e8dc..a017140a1d4 100644
--- a/chromium/components/sync_device_info/fake_local_device_info_provider.cc
+++ b/chromium/components/sync_device_info/fake_local_device_info_provider.cc
@@ -6,6 +6,7 @@
#include "base/time/time.h"
#include "components/sync/base/model_type.h"
+#include "components/sync/protocol/sync_enums.pb.h"
#include "components/sync_device_info/device_info_util.h"
namespace syncer {
@@ -23,8 +24,8 @@ FakeLocalDeviceInfoProvider::FakeLocalDeviceInfoProvider()
/*last_updated_timestamp=*/base::Time::Now(),
DeviceInfoUtil::GetPulseInterval(),
/*send_tab_to_self_receiving_enabled=*/false,
- /*sharing_info=*/base::nullopt,
- /*paask_info=*/base::nullopt,
+ /*sharing_info=*/absl::nullopt,
+ /*paask_info=*/absl::nullopt,
/*fcm_registration_token=*/std::string(),
/*interested_data_types=*/ModelTypeSet()) {}
diff --git a/chromium/components/sync_device_info/fake_local_device_info_provider.h b/chromium/components/sync_device_info/fake_local_device_info_provider.h
index 6275eff3741..8bc8cafdb97 100644
--- a/chromium/components/sync_device_info/fake_local_device_info_provider.h
+++ b/chromium/components/sync_device_info/fake_local_device_info_provider.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SYNC_DEVICE_INFO_FAKE_LOCAL_DEVICE_INFO_PROVIDER_H_
#define COMPONENTS_SYNC_DEVICE_INFO_FAKE_LOCAL_DEVICE_INFO_PROVIDER_H_
-#include <memory>
-
#include "base/macros.h"
#include "components/sync_device_info/device_info.h"
#include "components/sync_device_info/local_device_info_provider.h"
diff --git a/chromium/components/sync_device_info/local_device_info_provider_impl.cc b/chromium/components/sync_device_info/local_device_info_provider_impl.cc
index eb6705eb5e9..8ee6712d2bc 100644
--- a/chromium/components/sync_device_info/local_device_info_provider_impl.cc
+++ b/chromium/components/sync_device_info/local_device_info_provider_impl.cc
@@ -43,21 +43,21 @@ const DeviceInfo* LocalDeviceInfoProviderImpl::GetLocalDeviceInfo() const {
local_device_info_->set_sharing_info(sync_client_->GetLocalSharingInfo());
// Do not update previous values if the service is not fully initialized.
- // base::nullopt means that the value is unknown yet and the previous value
+ // absl::nullopt means that the value is unknown yet and the previous value
// should be kept.
- const base::Optional<std::string> fcm_token =
+ const absl::optional<std::string> fcm_token =
sync_client_->GetFCMRegistrationToken();
if (fcm_token) {
local_device_info_->set_fcm_registration_token(*fcm_token);
}
- const base::Optional<ModelTypeSet> interested_data_types =
+ const absl::optional<ModelTypeSet> interested_data_types =
sync_client_->GetInterestedDataTypes();
if (interested_data_types) {
local_device_info_->set_interested_data_types(*interested_data_types);
}
- base::Optional<DeviceInfo::PhoneAsASecurityKeyInfo> paask_info =
+ absl::optional<DeviceInfo::PhoneAsASecurityKeyInfo> paask_info =
sync_client_->GetPhoneAsASecurityKeyInfo();
if (paask_info) {
local_device_info_->set_paask_info(std::move(*paask_info));
@@ -105,7 +105,7 @@ void LocalDeviceInfoProviderImpl::Initialize(
// become ready by then.
std::string last_fcm_registration_token;
ModelTypeSet last_interested_data_types;
- base::Optional<DeviceInfo::PhoneAsASecurityKeyInfo> paask_info;
+ absl::optional<DeviceInfo::PhoneAsASecurityKeyInfo> paask_info;
if (device_info_restored_from_store) {
last_fcm_registration_token =
device_info_restored_from_store->fcm_registration_token();
diff --git a/chromium/components/sync_device_info/local_device_info_provider_impl_unittest.cc b/chromium/components/sync_device_info/local_device_info_provider_impl_unittest.cc
index 85d5c60bd0c..d7a81cbe140 100644
--- a/chromium/components/sync_device_info/local_device_info_provider_impl_unittest.cc
+++ b/chromium/components/sync_device_info/local_device_info_provider_impl_unittest.cc
@@ -7,6 +7,7 @@
#include "base/memory/ptr_util.h"
#include "components/sync/base/model_type.h"
#include "components/sync/base/sync_util.h"
+#include "components/sync/protocol/sync.pb.h"
#include "components/sync_device_info/device_info_sync_client.h"
#include "components/version_info/version_string.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -44,19 +45,19 @@ class MockDeviceInfoSyncClient : public DeviceInfoSyncClient {
MOCK_METHOD(std::string, GetSigninScopedDeviceId, (), (const override));
MOCK_METHOD(bool, GetSendTabToSelfReceivingEnabled, (), (const override));
- MOCK_METHOD(base::Optional<DeviceInfo::SharingInfo>,
+ MOCK_METHOD(absl::optional<DeviceInfo::SharingInfo>,
GetLocalSharingInfo,
(),
(const override));
- MOCK_METHOD(base::Optional<DeviceInfo::PhoneAsASecurityKeyInfo>,
+ MOCK_METHOD(absl::optional<DeviceInfo::PhoneAsASecurityKeyInfo>,
GetPhoneAsASecurityKeyInfo,
(),
(const override));
- MOCK_METHOD(base::Optional<std::string>,
+ MOCK_METHOD(absl::optional<std::string>,
GetFCMRegistrationToken,
(),
(const override));
- MOCK_METHOD(base::Optional<ModelTypeSet>,
+ MOCK_METHOD(absl::optional<ModelTypeSet>,
GetInterestedDataTypes,
(),
(const override));
@@ -194,7 +195,7 @@ TEST_F(LocalDeviceInfoProviderImplTest, SendTabToSelfReceivingEnabled) {
TEST_F(LocalDeviceInfoProviderImplTest, SharingInfo) {
ON_CALL(device_info_sync_client_, GetLocalSharingInfo())
- .WillByDefault(Return(base::nullopt));
+ .WillByDefault(Return(absl::nullopt));
InitializeProvider();
@@ -203,8 +204,8 @@ TEST_F(LocalDeviceInfoProviderImplTest, SharingInfo) {
std::set<sync_pb::SharingSpecificFields::EnabledFeatures> enabled_features(
std::begin(kSharingEnabledFeatures), std::end(kSharingEnabledFeatures));
- base::Optional<DeviceInfo::SharingInfo> sharing_info =
- base::make_optional<DeviceInfo::SharingInfo>(
+ absl::optional<DeviceInfo::SharingInfo> sharing_info =
+ absl::make_optional<DeviceInfo::SharingInfo>(
DeviceInfo::SharingTargetInfo{kSharingVapidFCMRegistrationToken,
kSharingVapidP256dh,
kSharingVapidAuthSecret},
@@ -216,7 +217,7 @@ TEST_F(LocalDeviceInfoProviderImplTest, SharingInfo) {
.WillByDefault(Return(sharing_info));
ASSERT_THAT(provider_->GetLocalDeviceInfo(), NotNull());
- const base::Optional<DeviceInfo::SharingInfo>& local_sharing_info =
+ const absl::optional<DeviceInfo::SharingInfo>& local_sharing_info =
provider_->GetLocalDeviceInfo()->sharing_info();
ASSERT_TRUE(local_sharing_info);
EXPECT_EQ(kSharingVapidFCMRegistrationToken,
@@ -271,7 +272,7 @@ TEST_F(LocalDeviceInfoProviderImplTest, ShouldKeepStoredInvalidationFields) {
"model", "full_hardware_class", base::Time(),
base::TimeDelta::FromDays(1),
/*send_tab_to_self_receiving_enabled=*/true,
- /*sharing_info=*/base::nullopt, paask_info, kFCMRegistrationToken,
+ /*sharing_info=*/absl::nullopt, paask_info, kFCMRegistrationToken,
kInterestedDataTypes);
// |kFCMRegistrationToken|, |kInterestedDataTypes|,
@@ -283,11 +284,11 @@ TEST_F(LocalDeviceInfoProviderImplTest, ShouldKeepStoredInvalidationFields) {
std::move(device_info_restored_from_store));
EXPECT_CALL(device_info_sync_client_, GetFCMRegistrationToken())
- .WillOnce(Return(base::nullopt));
+ .WillOnce(Return(absl::nullopt));
EXPECT_CALL(device_info_sync_client_, GetInterestedDataTypes())
- .WillOnce(Return(base::nullopt));
+ .WillOnce(Return(absl::nullopt));
EXPECT_CALL(device_info_sync_client_, GetPhoneAsASecurityKeyInfo())
- .WillOnce(Return(base::nullopt));
+ .WillOnce(Return(absl::nullopt));
const DeviceInfo* local_device_info = provider_->GetLocalDeviceInfo();
EXPECT_EQ(local_device_info->interested_data_types(), kInterestedDataTypes);
@@ -297,7 +298,7 @@ TEST_F(LocalDeviceInfoProviderImplTest, ShouldKeepStoredInvalidationFields) {
TEST_F(LocalDeviceInfoProviderImplTest, PhoneAsASecurityKeyInfo) {
ON_CALL(device_info_sync_client_, GetPhoneAsASecurityKeyInfo())
- .WillByDefault(Return(base::nullopt));
+ .WillByDefault(Return(absl::nullopt));
InitializeProvider();
@@ -310,7 +311,7 @@ TEST_F(LocalDeviceInfoProviderImplTest, PhoneAsASecurityKeyInfo) {
.WillByDefault(Return(paask_info));
ASSERT_THAT(provider_->GetLocalDeviceInfo(), NotNull());
- const base::Optional<DeviceInfo::PhoneAsASecurityKeyInfo>& result_paask_info =
+ const absl::optional<DeviceInfo::PhoneAsASecurityKeyInfo>& result_paask_info =
provider_->GetLocalDeviceInfo()->paask_info();
ASSERT_TRUE(result_paask_info);
EXPECT_EQ(paask_info.tunnel_server_domain,
diff --git a/chromium/components/sync_device_info/local_device_info_util.cc b/chromium/components/sync_device_info/local_device_info_util.cc
index 1f89260ea42..90fa4a5716b 100644
--- a/chromium/components/sync_device_info/local_device_info_util.cc
+++ b/chromium/components/sync_device_info/local_device_info_util.cc
@@ -81,7 +81,7 @@ sync_pb::SyncEnums::DeviceType GetLocalDeviceType() {
return ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET
? sync_pb::SyncEnums_DeviceType_TYPE_TABLET
: sync_pb::SyncEnums_DeviceType_TYPE_PHONE;
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
return sync_pb::SyncEnums_DeviceType_TYPE_MAC;
#elif defined(OS_WIN)
return sync_pb::SyncEnums_DeviceType_TYPE_WIN;
diff --git a/chromium/components/sync_preferences/DIR_METADATA b/chromium/components/sync_preferences/DIR_METADATA
index 8c96537a680..ce059d2af1c 100644
--- a/chromium/components/sync_preferences/DIR_METADATA
+++ b/chromium/components/sync_preferences/DIR_METADATA
@@ -1,5 +1,5 @@
monorail {
- component: "UI>Browser>Preferences"
+ component: "Internals>Preferences"
}
team_email: "chromium-reviews@chromium.org"
diff --git a/chromium/components/sync_preferences/pref_model_associator.cc b/chromium/components/sync_preferences/pref_model_associator.cc
index e22e3202f66..207d534402e 100644
--- a/chromium/components/sync_preferences/pref_model_associator.cc
+++ b/chromium/components/sync_preferences/pref_model_associator.cc
@@ -136,12 +136,12 @@ void PrefModelAssociator::InitPrefAndAssociate(
if (new_value->is_none()) {
LOG(WARNING) << "Sync has null value for pref " << pref_name.c_str();
pref_service_->ClearPref(pref_name);
- } else if (!user_pref_value->Equals(new_value.get())) {
+ } else if (*user_pref_value != *new_value) {
SetPrefWithTypeCheck(pref_name, *new_value);
}
// If the merge resulted in an updated value, inform the syncer.
- if (!sync_value->Equals(new_value.get())) {
+ if (*sync_value != *new_value) {
syncer::SyncData sync_data;
if (!CreatePrefSyncData(pref_name, *new_value, &sync_data)) {
LOG(ERROR) << "Failed to update preference.";
@@ -184,7 +184,7 @@ void PrefModelAssociator::WaitUntilReadyToSync(base::OnceClosure done) {
std::move(done).Run();
}
-base::Optional<syncer::ModelError>
+absl::optional<syncer::ModelError>
PrefModelAssociator::MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
@@ -242,7 +242,7 @@ PrefModelAssociator::MergeDataAndStartSyncing(
}
// Push updates to sync.
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
if (!error.has_value()) {
models_associated_ = true;
@@ -280,7 +280,7 @@ std::unique_ptr<base::Value> PrefModelAssociator::MergePreference(
}
// If this is not a specially handled preference, server wins.
- return base::WrapUnique(server_value.DeepCopy());
+ return base::Value::ToUniquePtrValue(server_value.Clone());
}
bool PrefModelAssociator::CreatePrefSyncData(
@@ -383,7 +383,7 @@ syncer::SyncDataList PrefModelAssociator::GetAllSyncDataForTesting(
return current_data;
}
-base::Optional<syncer::ModelError> PrefModelAssociator::ProcessSyncChanges(
+absl::optional<syncer::ModelError> PrefModelAssociator::ProcessSyncChanges(
const base::Location& from_here,
const syncer::SyncChangeList& change_list) {
if (!models_associated_) {
@@ -410,7 +410,7 @@ base::Optional<syncer::ModelError> PrefModelAssociator::ProcessSyncChanges(
continue;
}
- base::Optional<base::Value> new_value(
+ absl::optional<base::Value> new_value(
ReadPreferenceSpecifics(pref_specifics));
if (!new_value) {
// Skip values we can't deserialize.
@@ -438,11 +438,11 @@ base::Optional<syncer::ModelError> PrefModelAssociator::ProcessSyncChanges(
synced_preferences_.insert(pref_specifics.name());
}
}
- return base::nullopt;
+ return absl::nullopt;
}
// static
-base::Optional<base::Value> PrefModelAssociator::ReadPreferenceSpecifics(
+absl::optional<base::Value> PrefModelAssociator::ReadPreferenceSpecifics(
const sync_pb::PreferenceSpecifics& preference) {
base::JSONReader::ValueWithError parsed_json =
base::JSONReader::ReadAndReturnValueWithError(preference.value());
@@ -450,7 +450,7 @@ base::Optional<base::Value> PrefModelAssociator::ReadPreferenceSpecifics(
std::string err =
"Failed to deserialize preference value: " + parsed_json.error_message;
LOG(ERROR) << err;
- return base::nullopt;
+ return absl::nullopt;
}
return std::move(parsed_json.value);
}
diff --git a/chromium/components/sync_preferences/pref_model_associator.h b/chromium/components/sync_preferences/pref_model_associator.h
index 15b39ec3fef..965c441c095 100644
--- a/chromium/components/sync_preferences/pref_model_associator.h
+++ b/chromium/components/sync_preferences/pref_model_associator.h
@@ -59,13 +59,13 @@ class PrefModelAssociator : public syncer::SyncableService {
// syncer::SyncableService implementation.
void WaitUntilReadyToSync(base::OnceClosure done) override;
- base::Optional<syncer::ModelError> MergeDataAndStartSyncing(
+ absl::optional<syncer::ModelError> 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;
- base::Optional<syncer::ModelError> ProcessSyncChanges(
+ absl::optional<syncer::ModelError> ProcessSyncChanges(
const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
// Note for GetAllSyncDataForTesting: This will build a model of all
@@ -148,7 +148,7 @@ class PrefModelAssociator : public syncer::SyncableService {
const base::Value& to_value);
// Extract preference value from sync specifics.
- static base::Optional<base::Value> ReadPreferenceSpecifics(
+ static absl::optional<base::Value> ReadPreferenceSpecifics(
const sync_pb::PreferenceSpecifics& specifics);
void NotifySyncedPrefObservers(const std::string& path, bool from_sync) const;
diff --git a/chromium/components/sync_preferences/pref_service_syncable_unittest.cc b/chromium/components/sync_preferences/pref_service_syncable_unittest.cc
index b584d346920..21f517cbd86 100644
--- a/chromium/components/sync_preferences/pref_service_syncable_unittest.cc
+++ b/chromium/components/sync_preferences/pref_service_syncable_unittest.cc
@@ -21,6 +21,7 @@
#include "components/prefs/pref_notifier_impl.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/prefs/testing_pref_store.h"
+#include "components/sync/base/client_tag_hash.h"
#include "components/sync/base/model_type.h"
#include "components/sync/model/sync_change.h"
#include "components/sync/model/sync_change_processor.h"
@@ -89,7 +90,7 @@ class TestSyncProcessorStub : public syncer::SyncChangeProcessor {
explicit TestSyncProcessorStub(syncer::SyncChangeList* output)
: output_(output), fail_next_(false) {}
- base::Optional<syncer::ModelError> ProcessSyncChanges(
+ absl::optional<syncer::ModelError> ProcessSyncChanges(
const base::Location& from_here,
const syncer::SyncChangeList& change_list) override {
if (output_)
@@ -98,7 +99,7 @@ class TestSyncProcessorStub : public syncer::SyncChangeProcessor {
fail_next_ = false;
return syncer::ModelError(FROM_HERE, "Error");
}
- return base::nullopt;
+ return absl::nullopt;
}
void FailNextProcessSyncChanges() { fail_next_ = true; }
@@ -168,8 +169,10 @@ syncer::SyncChange MakeRemoteChange(const std::string& name,
PrefModelAssociator::GetMutableSpecifics(model_type, &entity);
pref->set_name(name);
pref->set_value(serialized);
- return syncer::SyncChange(FROM_HERE, change_type,
- syncer::SyncData::CreateRemoteData(entity));
+ return syncer::SyncChange(
+ FROM_HERE, change_type,
+ syncer::SyncData::CreateRemoteData(
+ entity, syncer::ClientTagHash::FromUnhashed(model_type, name)));
}
// Creates a SyncChange for model type |PREFERENCES|.
@@ -189,7 +192,9 @@ SyncData CreateRemoteSyncData(const std::string& name,
sync_pb::PreferenceSpecifics* pref_one = one.mutable_preference();
pref_one->set_name(name);
pref_one->set_value(serialized);
- return SyncData::CreateRemoteData(one);
+ return SyncData::CreateRemoteData(
+ one, syncer::ClientTagHash::FromUnhashed(syncer::ModelType::PREFERENCES,
+ name));
}
class PrefServiceSyncableTest : public testing::Test {
@@ -221,7 +226,7 @@ class PrefServiceSyncableTest : public testing::Test {
void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data,
syncer::SyncChangeList* output) {
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
pref_sync_service_->MergeDataAndStartSyncing(
syncer::PREFERENCES, initial_data,
std::make_unique<TestSyncProcessorStub>(output),
@@ -445,7 +450,9 @@ class PrefServiceSyncableMergeTest : public testing::Test {
pref_one->set_name(name);
pref_one->set_value(serialized);
return syncer::SyncChange(FROM_HERE, type,
- syncer::SyncData::CreateRemoteData(entity));
+ syncer::SyncData::CreateRemoteData(
+ entity, syncer::ClientTagHash::FromUnhashed(
+ syncer::PREFERENCES, name)));
}
void AddToRemoteDataList(const std::string& name,
@@ -458,12 +465,13 @@ class PrefServiceSyncableMergeTest : public testing::Test {
sync_pb::PreferenceSpecifics* pref_one = one.mutable_preference();
pref_one->set_name(name);
pref_one->set_value(serialized);
- out->push_back(SyncData::CreateRemoteData(one));
+ out->push_back(SyncData::CreateRemoteData(
+ one, syncer::ClientTagHash::FromUnhashed(syncer::PREFERENCES, name)));
}
void InitWithSyncDataTakeOutput(const syncer::SyncDataList& initial_data,
syncer::SyncChangeList* output) {
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
pref_sync_service_->MergeDataAndStartSyncing(
syncer::PREFERENCES, initial_data,
std::make_unique<TestSyncProcessorStub>(output),
@@ -533,10 +541,11 @@ TEST_F(PrefServiceSyncableMergeTest, ShouldMergeSelectedListValues) {
// managed preferences.
TEST_F(PrefServiceSyncableMergeTest, ManagedListPreferences) {
// Make the list of urls to restore on startup managed.
- base::ListValue managed_value;
- managed_value.AppendString(kExampleUrl0);
- managed_value.AppendString(kExampleUrl1);
- managed_prefs_->SetValue(kListPrefName, managed_value.CreateDeepCopy(),
+ base::Value managed_value(base::Value::Type::LIST);
+ managed_value.Append(kExampleUrl0);
+ managed_value.Append(kExampleUrl1);
+ managed_prefs_->SetValue(kListPrefName,
+ base::Value::ToUniquePtrValue(managed_value.Clone()),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
// Set a cloud version.
@@ -678,7 +687,7 @@ TEST_F(PrefServiceSyncableTest, FailModelAssociation) {
syncer::SyncChangeList output;
TestSyncProcessorStub* stub = new TestSyncProcessorStub(&output);
stub->FailNextProcessSyncChanges();
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
pref_sync_service_->MergeDataAndStartSyncing(
syncer::PREFERENCES, syncer::SyncDataList(), base::WrapUnique(stub),
std::make_unique<syncer::SyncErrorFactoryMock>());
@@ -938,7 +947,7 @@ class PrefServiceSyncableChromeOsTest : public testing::Test {
void InitSyncForType(ModelType type,
syncer::SyncChangeList* output = nullptr) {
syncer::SyncDataList empty_data;
- base::Optional<syncer::ModelError> error =
+ absl::optional<syncer::ModelError> error =
prefs_->GetSyncableService(type)->MergeDataAndStartSyncing(
type, empty_data, std::make_unique<TestSyncProcessorStub>(output),
std::make_unique<syncer::SyncErrorFactoryMock>());
@@ -973,7 +982,8 @@ class PrefServiceSyncableChromeOsTest : public testing::Test {
PrefModelAssociator::GetMutableSpecifics(model_type, &entity);
pref->set_name(name);
pref->set_value(serialized);
- return SyncData::CreateRemoteData(entity);
+ return SyncData::CreateRemoteData(
+ entity, syncer::ClientTagHash::FromUnhashed(model_type, name));
}
protected:
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 6a5348420b8..d42cdb7698b 100644
--- a/chromium/components/sync_sessions/local_session_event_handler_impl.cc
+++ b/chromium/components/sync_sessions/local_session_event_handler_impl.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/logging.h"
#include "components/sync/model/sync_change.h"
#include "components/sync/protocol/sync.pb.h"
#include "components/sync_sessions/switches.h"
diff --git a/chromium/components/sync_sessions/local_session_event_router.h b/chromium/components/sync_sessions/local_session_event_router.h
index 46ef7fbf019..248f7dccac0 100644
--- a/chromium/components/sync_sessions/local_session_event_router.h
+++ b/chromium/components/sync_sessions/local_session_event_router.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SYNC_SESSIONS_LOCAL_SESSION_EVENT_ROUTER_H_
#define COMPONENTS_SYNC_SESSIONS_LOCAL_SESSION_EVENT_ROUTER_H_
-#include <set>
-
#include "base/macros.h"
#include "url/gurl.h"
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 f44e9ebcf83..5af823f1775 100644
--- a/chromium/components/sync_sessions/proxy_tabs_data_type_controller.h
+++ b/chromium/components/sync_sessions/proxy_tabs_data_type_controller.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_SYNC_SESSIONS_PROXY_TABS_DATA_TYPE_CONTROLLER_H_
#define COMPONENTS_SYNC_SESSIONS_PROXY_TABS_DATA_TYPE_CONTROLLER_H_
-#include <memory>
-#include <string>
-
#include "base/callback_forward.h"
#include "base/macros.h"
#include "components/sync/driver/data_type_controller.h"
diff --git a/chromium/components/sync_sessions/session_store.cc b/chromium/components/sync_sessions/session_store.cc
index 14eb57e668f..ffd3f623fe8 100644
--- a/chromium/components/sync_sessions/session_store.cc
+++ b/chromium/components/sync_sessions/session_store.cc
@@ -13,6 +13,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/pickle.h"
@@ -93,7 +94,7 @@ std::string GetSessionTagWithPrefs(const std::string& cache_guid,
}
void ForwardError(syncer::OnceModelErrorHandler error_handler,
- const base::Optional<syncer::ModelError>& error) {
+ const absl::optional<syncer::ModelError>& error) {
if (error) {
std::move(error_handler).Run(*error);
}
@@ -101,7 +102,7 @@ void ForwardError(syncer::OnceModelErrorHandler error_handler,
// Parses the content of |record_list| into |*initial_data|. The output
// parameters are first for binding purposes.
-base::Optional<syncer::ModelError> ParseInitialDataOnBackendSequence(
+absl::optional<syncer::ModelError> ParseInitialDataOnBackendSequence(
std::map<std::string, sync_pb::SessionSpecifics>* initial_data,
std::string* session_name,
std::unique_ptr<ModelTypeStore::RecordList> record_list) {
@@ -122,7 +123,7 @@ base::Optional<syncer::ModelError> ParseInitialDataOnBackendSequence(
*session_name = syncer::GetPersonalizableDeviceNameBlocking();
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace
@@ -322,7 +323,7 @@ std::string SessionStore::GetTabClientTagForTest(const std::string& session_tag,
// static
void SessionStore::OnStoreCreated(
std::unique_ptr<Builder> builder,
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<ModelTypeStore> underlying_store) {
DCHECK(builder);
@@ -344,7 +345,7 @@ void SessionStore::OnStoreCreated(
// static
void SessionStore::OnReadAllMetadata(
std::unique_ptr<Builder> builder,
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
DCHECK(builder);
@@ -370,7 +371,7 @@ void SessionStore::OnReadAllMetadata(
// static
void SessionStore::OnReadAllData(
std::unique_ptr<Builder> builder,
- const base::Optional<syncer::ModelError>& error) {
+ const absl::optional<syncer::ModelError>& error) {
DCHECK(builder);
if (error) {
@@ -394,7 +395,7 @@ void SessionStore::OnReadAllData(
builder->metadata_batch->GetAllMetadata(), builder->sessions_client));
std::move(builder->callback)
- .Run(/*error=*/base::nullopt, std::move(session_store),
+ .Run(/*error=*/absl::nullopt, std::move(session_store),
std::move(builder->metadata_batch));
}
diff --git a/chromium/components/sync_sessions/session_store.h b/chromium/components/sync_sessions/session_store.h
index b209305a819..dfec7695d4a 100644
--- a/chromium/components/sync_sessions/session_store.h
+++ b/chromium/components/sync_sessions/session_store.h
@@ -35,7 +35,7 @@ class SessionStore {
};
using OpenCallback = base::OnceCallback<void(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<SessionStore> store,
std::unique_ptr<syncer::MetadataBatch> metadata_batch)>;
@@ -141,14 +141,14 @@ class SessionStore {
static void OnStoreCreated(
std::unique_ptr<Builder> builder,
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore> underlying_store);
static void OnReadAllMetadata(
std::unique_ptr<Builder> builder,
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch);
static void OnReadAllData(std::unique_ptr<Builder> builder,
- const base::Optional<syncer::ModelError>& error);
+ const absl::optional<syncer::ModelError>& error);
// |sessions_client| must not be null and must outlive this object.
SessionStore(const SessionInfo& local_session_info,
diff --git a/chromium/components/sync_sessions/session_store_unittest.cc b/chromium/components/sync_sessions/session_store_unittest.cc
index cbf1f502c10..d3695cab54f 100644
--- a/chromium/components/sync_sessions/session_store_unittest.cc
+++ b/chromium/components/sync_sessions/session_store_unittest.cc
@@ -59,7 +59,7 @@ class MockOpenCallback {
public:
MOCK_METHOD(void,
Run,
- (const base::Optional<syncer::ModelError>& error,
+ (const absl::optional<syncer::ModelError>& error,
SessionStore* store,
MetadataBatch* metadata_batch),
());
@@ -67,7 +67,7 @@ class MockOpenCallback {
SessionStore::OpenCallback Get() {
return base::BindOnce(
[](MockOpenCallback* callback,
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<SessionStore> store,
std::unique_ptr<MetadataBatch> metadata_batch) {
// Store a copy of the pointer for GetResult().
@@ -117,7 +117,7 @@ std::unique_ptr<MetadataBatch> ReadAllPersistedMetadataFrom(
base::RunLoop loop;
store->ReadAllMetadata(base::BindOnce(
[](std::unique_ptr<MetadataBatch>* output_batch, base::RunLoop* loop,
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<MetadataBatch> input_batch) {
EXPECT_FALSE(error) << error->ToString();
EXPECT_THAT(input_batch, NotNull());
@@ -135,7 +135,7 @@ std::map<std::string, SessionSpecifics> ReadAllPersistedDataFrom(
base::RunLoop loop;
store->ReadAllData(base::BindOnce(
[](std::unique_ptr<ModelTypeStore::RecordList>* output_records,
- base::RunLoop* loop, const base::Optional<syncer::ModelError>& error,
+ base::RunLoop* loop, const absl::optional<syncer::ModelError>& error,
std::unique_ptr<ModelTypeStore::RecordList> input_records) {
EXPECT_FALSE(error) << error->ToString();
EXPECT_THAT(input_records, NotNull());
@@ -228,7 +228,7 @@ TEST_F(SessionStoreOpenTest, ShouldNotUseClientIfCancelled) {
}
private:
- void Completed(const base::Optional<syncer::ModelError>& error,
+ void Completed(const absl::optional<syncer::ModelError>& error,
std::unique_ptr<SessionStore> store,
std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
std::move(cb_).Run(error, std::move(store), std::move(metadata_batch));
diff --git a/chromium/components/sync_sessions/session_sync_bridge.cc b/chromium/components/sync_sessions/session_sync_bridge.cc
index 5dced7e8869..c7f19a4b563 100644
--- a/chromium/components/sync_sessions/session_sync_bridge.cc
+++ b/chromium/components/sync_sessions/session_sync_bridge.cc
@@ -13,6 +13,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
@@ -131,7 +132,7 @@ SessionSyncBridge::CreateMetadataChangeList() {
return std::make_unique<syncer::InMemoryMetadataChangeList>();
}
-base::Optional<syncer::ModelError> SessionSyncBridge::MergeSyncData(
+absl::optional<syncer::ModelError> SessionSyncBridge::MergeSyncData(
std::unique_ptr<MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) {
DCHECK(!syncing_);
@@ -168,7 +169,7 @@ void SessionSyncBridge::StartLocalSessionEventHandler() {
syncing_->local_session_event_handler.get());
}
-base::Optional<syncer::ModelError> SessionSyncBridge::ApplySyncChanges(
+absl::optional<syncer::ModelError> SessionSyncBridge::ApplySyncChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) {
DCHECK(change_processor()->IsTrackingMetadata());
@@ -244,7 +245,7 @@ base::Optional<syncer::ModelError> SessionSyncBridge::ApplySyncChanges(
notify_foreign_session_updated_cb_.Run();
}
- return base::nullopt;
+ return absl::nullopt;
}
void SessionSyncBridge::GetData(StorageKeyList storage_keys,
@@ -346,7 +347,7 @@ void SessionSyncBridge::OnSyncStarting(
}
void SessionSyncBridge::OnStoreInitialized(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<SessionStore> store,
std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
DCHECK(!syncing_);
diff --git a/chromium/components/sync_sessions/session_sync_bridge.h b/chromium/components/sync_sessions/session_sync_bridge.h
index bf51b6bb689..e2246c334ed 100644
--- a/chromium/components/sync_sessions/session_sync_bridge.h
+++ b/chromium/components/sync_sessions/session_sync_bridge.h
@@ -52,10 +52,10 @@ class SessionSyncBridge : public syncer::ModelTypeSyncBridge,
const syncer::DataTypeActivationRequest& request) override;
std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
override;
- base::Optional<syncer::ModelError> MergeSyncData(
+ absl::optional<syncer::ModelError> MergeSyncData(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_data) override;
- base::Optional<syncer::ModelError> ApplySyncChanges(
+ absl::optional<syncer::ModelError> ApplySyncChanges(
std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
syncer::EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
@@ -73,7 +73,7 @@ class SessionSyncBridge : public syncer::ModelTypeSyncBridge,
private:
void OnStoreInitialized(
- const base::Optional<syncer::ModelError>& error,
+ const absl::optional<syncer::ModelError>& error,
std::unique_ptr<SessionStore> store,
std::unique_ptr<syncer::MetadataBatch> metadata_batch);
void StartLocalSessionEventHandler();
@@ -111,7 +111,7 @@ class SessionSyncBridge : public syncer::ModelTypeSyncBridge,
};
// TODO(mastiz): We should rather rename this to |syncing_state_|.
- base::Optional<SyncingState> syncing_;
+ absl::optional<SyncingState> syncing_;
base::WeakPtrFactory<SessionSyncBridge> weak_ptr_factory_{this};
diff --git a/chromium/components/sync_sessions/session_sync_bridge_unittest.cc b/chromium/components/sync_sessions/session_sync_bridge_unittest.cc
index 02de8607754..9b18a95e0a1 100644
--- a/chromium/components/sync_sessions/session_sync_bridge_unittest.cc
+++ b/chromium/components/sync_sessions/session_sync_bridge_unittest.cc
@@ -12,7 +12,6 @@
#include "base/json/json_writer.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
@@ -188,8 +187,7 @@ class SessionSyncBridgeTest : public ::testing::Test {
void InitializeBridge() {
real_processor_ =
std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
- syncer::SESSIONS, /*dump_stack=*/base::DoNothing(),
- /*commit_only=*/false);
+ syncer::SESSIONS, /*dump_stack=*/base::DoNothing());
mock_processor_.DelegateCallsByDefaultTo(real_processor_.get());
// Instantiate the bridge.
bridge_ = std::make_unique<SessionSyncBridge>(
@@ -1290,7 +1288,7 @@ TEST_F(SessionSyncBridgeTest, ShouldHandleRemoteDeletion) {
underlying_store()->ReadData(
{header_storage_key, tab_storage_key},
base::BindLambdaForTesting(
- [&](const base::Optional<syncer::ModelError>& error,
+ [&](const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::ModelTypeStore::RecordList>
data_records,
std::unique_ptr<syncer::ModelTypeStore::IdList>
@@ -1308,7 +1306,7 @@ TEST_F(SessionSyncBridgeTest, ShouldHandleRemoteDeletion) {
{
base::RunLoop loop;
underlying_store()->ReadAllMetadata(base::BindLambdaForTesting(
- [&](const base::Optional<syncer::ModelError>& error,
+ [&](const absl::optional<syncer::ModelError>& error,
std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
syncer::EntityMetadataMap entity_metadata_map =
metadata_batch->TakeAllMetadata();
diff --git a/chromium/components/sync_sessions/session_sync_service.h b/chromium/components/sync_sessions/session_sync_service.h
index 65d2b62c8b3..3d1fce52df6 100644
--- a/chromium/components/sync_sessions/session_sync_service.h
+++ b/chromium/components/sync_sessions/session_sync_service.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_SYNC_SESSIONS_SESSION_SYNC_SERVICE_H_
#define COMPONENTS_SYNC_SESSIONS_SESSION_SYNC_SERVICE_H_
-#include <memory>
-#include <string>
-
#include "base/callback_list.h"
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/sync_sessions/session_sync_service_impl.h b/chromium/components/sync_sessions/session_sync_service_impl.h
index 234abb8a415..08e46e641f9 100644
--- a/chromium/components/sync_sessions/session_sync_service_impl.h
+++ b/chromium/components/sync_sessions/session_sync_service_impl.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SYNC_SESSIONS_SESSION_SYNC_SERVICE_IMPL_H_
#include <memory>
-#include <string>
#include "base/callback_list.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/sync_sessions/synced_session.cc b/chromium/components/sync_sessions/synced_session.cc
index 9fc5beadd6b..3879bd657ed 100644
--- a/chromium/components/sync_sessions/synced_session.cc
+++ b/chromium/components/sync_sessions/synced_session.cc
@@ -270,7 +270,7 @@ sync_pb::TabNavigation SessionNavigationToSyncData(
}
}
- const base::Optional<SerializedNavigationEntry::ReplacedNavigationEntryData>&
+ const absl::optional<SerializedNavigationEntry::ReplacedNavigationEntryData>&
replaced_entry_data = navigation.replaced_entry_data();
if (replaced_entry_data.has_value()) {
sync_pb::ReplacedNavigation* replaced_navigation =
@@ -310,7 +310,7 @@ void SetSessionTabFromSyncData(const sync_pb::SessionTab& sync_data,
sync_pb::SessionTab SessionTabToSyncData(
const sessions::SessionTab& tab,
- base::Optional<sync_pb::SessionWindow::BrowserType> browser_type) {
+ absl::optional<sync_pb::SessionWindow::BrowserType> browser_type) {
sync_pb::SessionTab sync_data;
sync_data.set_tab_id(tab.tab_id.id());
sync_data.set_window_id(tab.window_id.id());
diff --git a/chromium/components/sync_sessions/synced_session.h b/chromium/components/sync_sessions/synced_session.h
index 06b39fdc358..4f80e47878e 100644
--- a/chromium/components/sync_sessions/synced_session.h
+++ b/chromium/components/sync_sessions/synced_session.h
@@ -11,13 +11,13 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/sessions/core/serialized_navigation_entry.h"
#include "components/sessions/core/session_id.h"
#include "components/sessions/core/session_types.h"
#include "components/sync/protocol/session_specifics.pb.h"
#include "components/sync/protocol/sync_enums.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sync_sessions {
@@ -51,7 +51,7 @@ void SetSessionTabFromSyncData(const sync_pb::SessionTab& sync_data,
// property of the window.
sync_pb::SessionTab SessionTabToSyncData(
const sessions::SessionTab& tab,
- base::Optional<sync_pb::SessionWindow::BrowserType> browser_type);
+ absl::optional<sync_pb::SessionWindow::BrowserType> browser_type);
// A Sync wrapper for a SessionWindow.
struct SyncedSessionWindow {
diff --git a/chromium/components/sync_sessions/synced_session_tracker.cc b/chromium/components/sync_sessions/synced_session_tracker.cc
index 1aaf36f99c0..89ab934bb79 100644
--- a/chromium/components/sync_sessions/synced_session_tracker.cc
+++ b/chromium/components/sync_sessions/synced_session_tracker.cc
@@ -225,19 +225,19 @@ const sessions::SessionTab* SyncedSessionTracker::LookupSessionTab(
return tab_iter->second;
}
-base::Optional<sync_pb::SessionWindow::BrowserType>
+absl::optional<sync_pb::SessionWindow::BrowserType>
SyncedSessionTracker::LookupWindowType(const std::string& session_tag,
SessionID window_id) const {
if (!base::FeatureList::IsEnabled(kSyncPopulateTabBrowserTypeInGetData))
- return base::nullopt;
+ return absl::nullopt;
const TrackedSession* session = LookupTrackedSession(session_tag);
if (!session)
- return base::nullopt;
+ return absl::nullopt;
auto window_iter = session->synced_window_map.find(window_id);
if (window_iter == session->synced_window_map.end())
- return base::nullopt; // We have no record of this window.
+ return absl::nullopt; // We have no record of this window.
return window_iter->second->window_type;
}
diff --git a/chromium/components/sync_sessions/synced_session_tracker.h b/chromium/components/sync_sessions/synced_session_tracker.h
index 3ec7aef7887..4afb32f922e 100644
--- a/chromium/components/sync_sessions/synced_session_tracker.h
+++ b/chromium/components/sync_sessions/synced_session_tracker.h
@@ -15,12 +15,12 @@
#include "base/feature_list.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/sessions/core/session_id.h"
#include "components/sessions/core/session_types.h"
#include "components/sync/protocol/session_specifics.pb.h"
#include "components/sync_sessions/synced_session.h"
#include "components/sync_sessions/tab_node_pool.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sync_sessions {
@@ -84,7 +84,7 @@ class SyncedSessionTracker {
const sessions::SessionTab* LookupSessionTab(const std::string& session_tag,
SessionID tab_id) const;
- base::Optional<sync_pb::SessionWindow::BrowserType> LookupWindowType(
+ absl::optional<sync_pb::SessionWindow::BrowserType> LookupWindowType(
const std::string& session_tag,
SessionID window_id) const;
diff --git a/chromium/components/sync_sessions/synced_session_unittest.cc b/chromium/components/sync_sessions/synced_session_unittest.cc
index f5ffc8710a7..98e6b1890c5 100644
--- a/chromium/components/sync_sessions/synced_session_unittest.cc
+++ b/chromium/components/sync_sessions/synced_session_unittest.cc
@@ -262,7 +262,7 @@ TEST(SyncedSessionTest, SessionTabToSyncData) {
tab.session_storage_persistent_id = "fake";
const sync_pb::SessionTab sync_data =
- SessionTabToSyncData(tab, /*browser_type=*/base::nullopt);
+ SessionTabToSyncData(tab, /*browser_type=*/absl::nullopt);
EXPECT_EQ(5, sync_data.tab_id());
EXPECT_EQ(10, sync_data.window_id());
EXPECT_EQ(13, sync_data.tab_visual_index());
diff --git a/chromium/components/sync_sessions/synced_window_delegate.h b/chromium/components/sync_sessions/synced_window_delegate.h
index 1a78be80825..01f9622bf2f 100644
--- a/chromium/components/sync_sessions/synced_window_delegate.h
+++ b/chromium/components/sync_sessions/synced_window_delegate.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_SYNC_SESSIONS_SYNCED_WINDOW_DELEGATE_H_
#define COMPONENTS_SYNC_SESSIONS_SYNCED_WINDOW_DELEGATE_H_
-#include <set>
-
#include "components/sessions/core/session_id.h"
namespace sync_sessions {
diff --git a/chromium/components/sync_sessions/tab_node_pool.cc b/chromium/components/sync_sessions/tab_node_pool.cc
index 0eb692e9603..6e180a0c3e5 100644
--- a/chromium/components/sync_sessions/tab_node_pool.cc
+++ b/chromium/components/sync_sessions/tab_node_pool.cc
@@ -11,7 +11,6 @@
#include "base/logging.h"
#include "components/sync/base/model_type.h"
#include "components/sync/protocol/session_specifics.pb.h"
-#include "components/sync/protocol/sync.pb.h"
#include "components/sync_sessions/synced_tab_delegate.h"
namespace sync_sessions {
diff --git a/chromium/components/sync_sessions/tab_node_pool.h b/chromium/components/sync_sessions/tab_node_pool.h
index 01f68749536..39f1c5bde83 100644
--- a/chromium/components/sync_sessions/tab_node_pool.h
+++ b/chromium/components/sync_sessions/tab_node_pool.h
@@ -9,7 +9,6 @@
#include <map>
#include <set>
-#include <string>
#include "base/feature_list.h"
#include "base/macros.h"
diff --git a/chromium/components/sync_ui_strings.grdp b/chromium/components/sync_ui_strings.grdp
index d8a948cf7e9..dc917fa3753 100644
--- a/chromium/components/sync_ui_strings.grdp
+++ b/chromium/components/sync_ui_strings.grdp
@@ -4,9 +4,6 @@
<message name="IDS_SYNC_BASIC_ENCRYPTION_DATA" desc="Text of the radio that when selected enables basic encryption.">
Encrypt synced passwords with your Google Account
</message>
- <message name="IDS_SYNC_CONFIGURE_ENCRYPTION" desc="Link to configure sync encryption for passwords">
- Please update your sync passphrase.
- </message>
<message name="IDS_SYNC_DATATYPE_AUTOFILL" desc="Form Autofill items, one of the data types that we allow syncing.">
Addresses and More
</message>
@@ -34,9 +31,6 @@
<message name="IDS_SYNC_ENCRYPTION_SECTION_TITLE" desc="Title of the section containing sync encryption preferences.">
Encryption options
</message>
- <message name="IDS_SYNC_ENTER_GOOGLE_PASSPHRASE_BODY" desc="Instructions for the dialog where the user needs to enter their previous google passphrase.">
- You already have data that is encrypted using a different version of your Google Account password. Please enter it below.
- </message>
<message name="IDS_SYNC_FULL_ENCRYPTION_DATA" desc="Text of the radio that when selected enables full encryption.">
Encrypt synced data with your own sync passphrase
</message>
@@ -55,22 +49,9 @@
<message name="IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE" desc="Instructions for the dialog where the user enters their Sync passphrase.">
Your data was encrypted with your <ph name="BEGIN_LINK">&lt;a target="_blank" href="$1"&gt;</ph>sync passphrase<ph name="END_LINK">&lt;/a&gt;</ph> on <ph name="TIME">$2<ex>Sept 1, 2012</ex></ph>. Enter it to start sync.
</message>
- <message name="IDS_SYNC_ENTER_GOOGLE_PASSPHRASE_BODY_WITH_DATE" desc="Instructions for the dialog where the user needs to enter their previous google passphrase.">
- Your data was encrypted with your <ph name="BEGIN_LINK">&lt;a target="_blank" href="$1"&gt;</ph>Google password<ph name="END_LINK">&lt;/a&gt;</ph> as of <ph name="TIME">$2<ex>Sept 1, 2012</ex></ph>. Enter it to start sync.
- </message>
- </if>
-
- <if expr="is_android">
- <message name="IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE_ANDROID" desc="Instructions for the dialog where the user enters their Sync passphrase.">
- Your data was encrypted with your <ph name="BEGIN_LINK">&lt;learnmore&gt;</ph>sync passphrase<ph name="END_LINK">&lt;/learnmore&gt;</ph> on <ph name="TIME">$1<ex>Sept 1, 2012</ex></ph>. Enter it to start sync.
- </message>
- <message name="IDS_SYNC_ENTER_GOOGLE_PASSPHRASE_BODY_WITH_DATE_ANDROID" desc="Instructions for the dialog where the user needs to enter their previous google passphrase.">
- Your data was encrypted with your <ph name="BEGIN_LINK">&lt;learnmore&gt;</ph>Google password<ph name="END_LINK">&lt;/learnmore&gt;</ph> as of <ph name="TIME">$1<ex>Sept 1, 2012</ex></ph>. Enter it to start sync.
- </message>
-
</if>
- <message name="IDS_SYNC_ENTER_PASSPHRASE_BODY" desc="Instructions for the dialog where the user enters the passphrase.">
+ <message name="IDS_SYNC_ENTER_PASSPHRASE_BODY" formatter_data="android_java" desc="Instructions for the dialog where the user enters the passphrase.">
Your data is encrypted with your sync passphrase. Enter it to start sync.
</message>
</grit-part>
diff --git a/chromium/components/sync_ui_strings_grdp/IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE_ANDROID.png.sha1 b/chromium/components/sync_ui_strings_grdp/IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE_ANDROID.png.sha1
deleted file mode 100644
index 085de34624f..00000000000
--- a/chromium/components/sync_ui_strings_grdp/IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE_ANDROID.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-874727fdb430be8fa0f9565dcaa63bbbc6c796f6 \ No newline at end of file
diff --git a/chromium/components/sync_user_events/fake_user_event_service.h b/chromium/components/sync_user_events/fake_user_event_service.h
index 7b3bee37497..64ea7c18c87 100644
--- a/chromium/components/sync_user_events/fake_user_event_service.h
+++ b/chromium/components/sync_user_events/fake_user_event_service.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SYNC_USER_EVENTS_FAKE_USER_EVENT_SERVICE_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/macros.h"
diff --git a/chromium/components/sync_user_events/no_op_user_event_service.h b/chromium/components/sync_user_events/no_op_user_event_service.h
index fd69d6fd1f4..1f385af5a17 100644
--- a/chromium/components/sync_user_events/no_op_user_event_service.h
+++ b/chromium/components/sync_user_events/no_op_user_event_service.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SYNC_USER_EVENTS_NO_OP_USER_EVENT_SERVICE_H_
#include <memory>
-#include <string>
#include "base/macros.h"
#include "components/sync_user_events/user_event_service.h"
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 05b64abb16e..fbbd83e04be 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
@@ -44,7 +44,7 @@ void UserEventModelTypeController::Stop(syncer::ShutdownReason shutdown_reason,
DataTypeController::PreconditionState
UserEventModelTypeController::GetPreconditionState() const {
- return sync_service_->GetUserSettings()->IsUsingSecondaryPassphrase()
+ return sync_service_->GetUserSettings()->IsUsingExplicitPassphrase()
? PreconditionState::kMustStopAndClearData
: PreconditionState::kPreconditionsMet;
}
diff --git a/chromium/components/sync_user_events/user_event_service.h b/chromium/components/sync_user_events/user_event_service.h
index 75d6ea43c73..c8d5b93c8c7 100644
--- a/chromium/components/sync_user_events/user_event_service.h
+++ b/chromium/components/sync_user_events/user_event_service.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SYNC_USER_EVENTS_USER_EVENT_SERVICE_H_
#include <memory>
-#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/sync_user_events/user_event_service_impl.h b/chromium/components/sync_user_events/user_event_service_impl.h
index 70ea7636607..968252ea28b 100644
--- a/chromium/components/sync_user_events/user_event_service_impl.h
+++ b/chromium/components/sync_user_events/user_event_service_impl.h
@@ -6,7 +6,6 @@
#define COMPONENTS_SYNC_USER_EVENTS_USER_EVENT_SERVICE_IMPL_H_
#include <memory>
-#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/sync_user_events/user_event_sync_bridge.cc b/chromium/components/sync_user_events/user_event_sync_bridge.cc
index ffb5bec05d4..ce99fb99d1a 100644
--- a/chromium/components/sync_user_events/user_event_sync_bridge.cc
+++ b/chromium/components/sync_user_events/user_event_sync_bridge.cc
@@ -82,7 +82,7 @@ UserEventSyncBridge::CreateMetadataChangeList() {
return WriteBatch::CreateMetadataChangeList();
}
-base::Optional<ModelError> UserEventSyncBridge::MergeSyncData(
+absl::optional<ModelError> UserEventSyncBridge::MergeSyncData(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_data) {
DCHECK(entity_data.empty());
@@ -92,7 +92,7 @@ base::Optional<ModelError> UserEventSyncBridge::MergeSyncData(
std::move(entity_data));
}
-base::Optional<ModelError> UserEventSyncBridge::ApplySyncChanges(
+absl::optional<ModelError> UserEventSyncBridge::ApplySyncChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_changes) {
std::unique_ptr<WriteBatch> batch = store_->CreateWriteBatch();
@@ -209,7 +209,7 @@ void UserEventSyncBridge::RecordUserEventImpl(
}
void UserEventSyncBridge::OnStoreCreated(
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<ModelTypeStore> store) {
if (error) {
change_processor()->ReportError(*error);
@@ -222,7 +222,7 @@ void UserEventSyncBridge::OnStoreCreated(
}
void UserEventSyncBridge::OnReadAllMetadata(
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<MetadataBatch> metadata_batch) {
if (error) {
change_processor()->ReportError(*error);
@@ -231,14 +231,14 @@ void UserEventSyncBridge::OnReadAllMetadata(
}
}
-void UserEventSyncBridge::OnCommit(const base::Optional<ModelError>& error) {
+void UserEventSyncBridge::OnCommit(const absl::optional<ModelError>& error) {
if (error) {
change_processor()->ReportError(*error);
}
}
void UserEventSyncBridge::OnReadData(DataCallback callback,
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<RecordList> data_records,
std::unique_ptr<IdList> missing_id_list) {
OnReadAllData(std::move(callback), error, std::move(data_records));
@@ -246,7 +246,7 @@ void UserEventSyncBridge::OnReadData(DataCallback callback,
void UserEventSyncBridge::OnReadAllData(
DataCallback callback,
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<RecordList> data_records) {
if (error) {
change_processor()->ReportError(*error);
diff --git a/chromium/components/sync_user_events/user_event_sync_bridge.h b/chromium/components/sync_user_events/user_event_sync_bridge.h
index b278912a3e5..97a6485b81b 100644
--- a/chromium/components/sync_user_events/user_event_sync_bridge.h
+++ b/chromium/components/sync_user_events/user_event_sync_bridge.h
@@ -14,11 +14,11 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "components/sync/model/model_type_change_processor.h"
#include "components/sync/model/model_type_store.h"
#include "components/sync/model/model_type_sync_bridge.h"
#include "components/sync_user_events/global_id_mapper.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace syncer {
@@ -32,10 +32,10 @@ class UserEventSyncBridge : public ModelTypeSyncBridge {
// ModelTypeSyncBridge implementation.
std::unique_ptr<MetadataChangeList> CreateMetadataChangeList() override;
- base::Optional<ModelError> MergeSyncData(
+ absl::optional<ModelError> MergeSyncData(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_data) override;
- base::Optional<ModelError> ApplySyncChanges(
+ absl::optional<ModelError> ApplySyncChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_changes) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
@@ -55,17 +55,17 @@ class UserEventSyncBridge : public ModelTypeSyncBridge {
void RecordUserEventImpl(
std::unique_ptr<sync_pb::UserEventSpecifics> specifics);
- void OnStoreCreated(const base::Optional<ModelError>& error,
+ void OnStoreCreated(const absl::optional<ModelError>& error,
std::unique_ptr<ModelTypeStore> store);
- void OnReadAllMetadata(const base::Optional<ModelError>& error,
+ void OnReadAllMetadata(const absl::optional<ModelError>& error,
std::unique_ptr<MetadataBatch> metadata_batch);
- void OnCommit(const base::Optional<ModelError>& error);
+ void OnCommit(const absl::optional<ModelError>& error);
void OnReadData(DataCallback callback,
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<ModelTypeStore::RecordList> data_records,
std::unique_ptr<ModelTypeStore::IdList> missing_id_list);
void OnReadAllData(DataCallback callback,
- const base::Optional<ModelError>& error,
+ const absl::optional<ModelError>& error,
std::unique_ptr<ModelTypeStore::RecordList> data_records);
void HandleGlobalIdChange(int64_t old_global_id, int64_t new_global_id);
diff --git a/chromium/components/system_media_controls/mac/now_playing_info_center_delegate.h b/chromium/components/system_media_controls/mac/now_playing_info_center_delegate.h
index 71e27766803..bb0dfbe844e 100644
--- a/chromium/components/system_media_controls/mac/now_playing_info_center_delegate.h
+++ b/chromium/components/system_media_controls/mac/now_playing_info_center_delegate.h
@@ -8,6 +8,7 @@
#include "base/mac/scoped_nsobject.h"
#include "base/timer/timer.h"
#include "components/system_media_controls/system_media_controls.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
@class NowPlayingInfoCenterDelegateCocoa;
@@ -43,10 +44,10 @@ class API_AVAILABLE(macos(10.13.1)) NowPlayingInfoCenterDelegate {
void UpdatePlaybackStatusAndPosition();
// Stores the most recently received playback status.
- base::Optional<SystemMediaControls::PlaybackStatus> playback_status_;
+ absl::optional<SystemMediaControls::PlaybackStatus> playback_status_;
// Stores the most recently received position.
- base::Optional<media_session::MediaPosition> position_;
+ absl::optional<media_session::MediaPosition> position_;
// Calls UpdatePlaybackStatusAndPosition() when the timer expires.
std::unique_ptr<base::OneShotTimer> timer_ =
diff --git a/chromium/components/thin_webview/internal/compositor_view_impl.cc b/chromium/components/thin_webview/internal/compositor_view_impl.cc
index 7b812292f32..71b35de4b39 100644
--- a/chromium/components/thin_webview/internal/compositor_view_impl.cc
+++ b/chromium/components/thin_webview/internal/compositor_view_impl.cc
@@ -56,7 +56,7 @@ CompositorViewImpl::CompositorViewImpl(JNIEnv* env,
current_surface_format_(kPixelFormatUnknown) {
compositor_.reset(content::Compositor::Create(this, window_android));
root_layer_->SetIsDrawable(true);
- base::Optional<SkColor> background_color =
+ absl::optional<SkColor> background_color =
ui::JavaColorToOptionalSkColor(java_background_color);
root_layer_->SetBackgroundColor(background_color.value());
}
diff --git a/chromium/components/thin_webview/internal/java/src/org/chromium/components/thinwebview/internal/ThinWebViewImpl.java b/chromium/components/thin_webview/internal/java/src/org/chromium/components/thinwebview/internal/ThinWebViewImpl.java
index 26beb1bfbed..32f053ff9ba 100644
--- a/chromium/components/thin_webview/internal/java/src/org/chromium/components/thinwebview/internal/ThinWebViewImpl.java
+++ b/chromium/components/thin_webview/internal/java/src/org/chromium/components/thinwebview/internal/ThinWebViewImpl.java
@@ -12,6 +12,7 @@ import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import org.chromium.base.ContextUtils;
+import org.chromium.base.annotations.DoNotInline;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.components.embedder_support.delegate.WebContentsDelegateAndroid;
@@ -31,8 +32,11 @@ public class ThinWebViewImpl extends FrameLayout implements ThinWebView {
private WindowAndroid mWindowAndroid;
private long mNativeThinWebViewImpl;
private WebContents mWebContents;
- private WebContentsDelegateAndroid mWebContentsDelegate;
private View mContentView;
+ // Passed to native and stored as a weak reference, so ensure this strong
+ // reference is not optimized away by R8.
+ @DoNotInline
+ private WebContentsDelegateAndroid mWebContentsDelegate;
/**
* Creates a {@link ThinWebViewImpl} backed by a {@link Surface}.
@@ -72,8 +76,8 @@ public class ThinWebViewImpl extends FrameLayout implements ThinWebView {
mWebContentsDelegate = delegate;
setContentView(contentView);
ThinWebViewImplJni.get().setWebContents(
- mNativeThinWebViewImpl, ThinWebViewImpl.this, mWebContents, mWebContentsDelegate);
- mWebContents.onShow();
+ mNativeThinWebViewImpl, ThinWebViewImpl.this, webContents, delegate);
+ webContents.onShow();
}
@Override
diff --git a/chromium/components/timers/BUILD.gn b/chromium/components/timers/BUILD.gn
deleted file mode 100644
index 6d6495188ed..00000000000
--- a/chromium/components/timers/BUILD.gn
+++ /dev/null
@@ -1,25 +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("timers") {
- sources = [
- "alarm_timer_chromeos.cc",
- "alarm_timer_chromeos.h",
- ]
-
- deps = [ "//base" ]
-}
-
-source_set("unit_tests") {
- testonly = true
-
- sources = [ "alarm_timer_unittest.cc" ]
-
- deps = [
- ":timers",
- "//base",
- "//base/test:test_support",
- "//testing/gtest",
- ]
-}
diff --git a/chromium/components/timers/DEPS b/chromium/components/timers/DEPS
deleted file mode 100644
index 413f57b96ca..00000000000
--- a/chromium/components/timers/DEPS
+++ /dev/null
@@ -1,10 +0,0 @@
-include_rules = [
- # This directory is shared with Chrome OS, which only links against
- # base/. We don't want any other dependencies to creep in.
- "-build",
- "-content",
- "-library_loaders",
- "-net",
- "-third_party",
- "-url",
-] \ No newline at end of file
diff --git a/chromium/components/timers/DIR_METADATA b/chromium/components/timers/DIR_METADATA
deleted file mode 100644
index 9640755ce1e..00000000000
--- a/chromium/components/timers/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "Internals>TaskScheduler"
-}
diff --git a/chromium/components/timers/OWNERS b/chromium/components/timers/OWNERS
deleted file mode 100644
index 8a3310217a3..00000000000
--- a/chromium/components/timers/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-chirantan@chromium.org
diff --git a/chromium/components/timers/README b/chromium/components/timers/README
deleted file mode 100644
index 0b2b4e37f82..00000000000
--- a/chromium/components/timers/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory hosts a timer class that is shared with Chrome OS. Code that
-lives in this directory is not allowed to depend on anything other than base/
-because Chrome OS only pulls in and depends on base/ as a library.
diff --git a/chromium/components/timers/alarm_timer_chromeos.cc b/chromium/components/timers/alarm_timer_chromeos.cc
deleted file mode 100644
index bd3947cd168..00000000000
--- a/chromium/components/timers/alarm_timer_chromeos.cc
+++ /dev/null
@@ -1,157 +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/timers/alarm_timer_chromeos.h"
-
-#include <stdint.h>
-#include <sys/timerfd.h>
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/pending_task.h"
-#include "base/task/common/task_annotator.h"
-#include "base/trace_event/task_execution_macros.h"
-#include "base/trace_event/trace_event.h"
-
-namespace timers {
-
-// static
-std::unique_ptr<SimpleAlarmTimer> SimpleAlarmTimer::Create() {
- return CreateInternal(CLOCK_REALTIME_ALARM);
-}
-
-// static
-std::unique_ptr<SimpleAlarmTimer> SimpleAlarmTimer::CreateForTesting() {
- // For unittest, use CLOCK_REALTIME in order to run the tests without
- // CAP_WAKE_ALARM.
- return CreateInternal(CLOCK_REALTIME);
-}
-
-// static
-std::unique_ptr<SimpleAlarmTimer> SimpleAlarmTimer::CreateInternal(
- int clockid) {
- base::ScopedFD alarm_fd(timerfd_create(clockid, TFD_CLOEXEC));
- if (!alarm_fd.is_valid()) {
- PLOG(ERROR) << "Failed to create timer fd";
- return nullptr;
- }
-
- // Note: std::make_unique<> cannot be used because the constructor is
- // private.
- return base::WrapUnique(new SimpleAlarmTimer(std::move(alarm_fd)));
-}
-
-SimpleAlarmTimer::SimpleAlarmTimer(base::ScopedFD alarm_fd)
- : alarm_fd_(std::move(alarm_fd)) {}
-
-SimpleAlarmTimer::~SimpleAlarmTimer() {
- DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
- Stop();
-}
-
-void SimpleAlarmTimer::Stop() {
- DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
-
- if (!IsRunning())
- return;
-
- // Cancel any previous callbacks.
- weak_factory_.InvalidateWeakPtrs();
-
- base::RetainingOneShotTimer::set_is_running(false);
- alarm_fd_watcher_.reset();
- pending_task_.reset();
-}
-
-void SimpleAlarmTimer::Reset() {
- DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(!base::RetainingOneShotTimer::user_task().is_null());
-
- // Cancel any previous callbacks and stop watching |alarm_fd_|.
- weak_factory_.InvalidateWeakPtrs();
- alarm_fd_watcher_.reset();
-
- // Ensure that the delay is not negative.
- const base::TimeDelta delay = std::max(
- base::TimeDelta(), base::RetainingOneShotTimer::GetCurrentDelay());
-
- // Set up the pending task.
- base::RetainingOneShotTimer::set_desired_run_time(
- delay.is_zero() ? base::TimeTicks() : base::TimeTicks::Now() + delay);
- pending_task_ = std::make_unique<base::PendingTask>(
- base::RetainingOneShotTimer::posted_from(),
- base::RetainingOneShotTimer::user_task(),
- base::RetainingOneShotTimer::desired_run_time());
-
- // Set |alarm_fd_| to be signaled when the delay expires. If the delay is
- // zero, |alarm_fd_| will never be signaled. This overrides the previous
- // delay, if any.
- itimerspec alarm_time = {};
- alarm_time.it_value.tv_sec = delay.InSeconds();
- alarm_time.it_value.tv_nsec =
- (delay.InMicroseconds() % base::Time::kMicrosecondsPerSecond) *
- base::Time::kNanosecondsPerMicrosecond;
- if (timerfd_settime(alarm_fd_.get(), 0, &alarm_time, NULL) < 0)
- PLOG(ERROR) << "Error while setting alarm time. Timer will not fire";
-
- // The timer is running.
- base::RetainingOneShotTimer::set_is_running(true);
-
- // If the delay is zero, post the task now.
- if (delay.is_zero()) {
- origin_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&SimpleAlarmTimer::OnTimerFired,
- weak_factory_.GetWeakPtr()));
- } else {
- // Otherwise, if the delay is not zero, generate a tracing event to indicate
- // that the task was posted and watch |alarm_fd_|.
- base::TaskAnnotator().WillQueueTask("SimpleAlarmTimer::Reset",
- pending_task_.get(), "");
- alarm_fd_watcher_ = base::FileDescriptorWatcher::WatchReadable(
- alarm_fd_.get(),
- base::BindRepeating(&SimpleAlarmTimer::OnAlarmFdReadableWithoutBlocking,
- weak_factory_.GetWeakPtr()));
- }
-}
-
-void SimpleAlarmTimer::OnAlarmFdReadableWithoutBlocking() {
- DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(base::RetainingOneShotTimer::IsRunning());
-
- // Read from |alarm_fd_| to ack the event.
- char val[sizeof(uint64_t)];
- if (!base::ReadFromFD(alarm_fd_.get(), val, sizeof(uint64_t)))
- PLOG(DFATAL) << "Unable to read from timer file descriptor.";
-
- OnTimerFired();
-}
-
-void SimpleAlarmTimer::OnTimerFired() {
- DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
- DCHECK(base::RetainingOneShotTimer::IsRunning());
- DCHECK(pending_task_.get());
-
- // Take ownership of the PendingTask to prevent it from being deleted if the
- // SimpleAlarmTimer is deleted.
- const auto pending_user_task = std::move(pending_task_);
-
- base::WeakPtr<SimpleAlarmTimer> weak_ptr = weak_factory_.GetWeakPtr();
-
- // Run the task.
- TRACE_TASK_EXECUTION("SimpleAlarmTimer::OnTimerFired", *pending_user_task);
- base::TaskAnnotator().RunTask("SimpleAlarmTimer::Reset",
- pending_user_task.get());
-
- // If the timer wasn't deleted, stopped or reset by the callback, stop it.
- if (weak_ptr)
- Stop();
-}
-
-} // namespace timers
diff --git a/chromium/components/timers/alarm_timer_chromeos.h b/chromium/components/timers/alarm_timer_chromeos.h
deleted file mode 100644
index c1e00122a2f..00000000000
--- a/chromium/components/timers/alarm_timer_chromeos.h
+++ /dev/null
@@ -1,89 +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_TIMERS_ALARM_TIMER_CHROMEOS_H_
-#define COMPONENTS_TIMERS_ALARM_TIMER_CHROMEOS_H_
-
-#include <memory>
-
-#include "base/files/file_descriptor_watcher_posix.h"
-#include "base/files/scoped_file.h"
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-
-namespace base {
-struct PendingTask;
-}
-
-namespace timers {
-// The class implements a timer that is capable of waking the system up from a
-// suspended state. For example, this is useful for running tasks that are
-// needed for maintaining network connectivity, like sending heartbeat messages.
-// Currently, this feature is only available on Chrome OS systems running linux
-// version 3.11 or higher.
-//
-// A SimpleAlarmTimer instance can only be used from the sequence on which it
-// was instantiated. Start() and Stop() must be called from a thread that
-// supports FileDescriptorWatcher.
-//
-// A SimpleAlarmTimer only fires once but remembers the task that it was given
-// even after it has fired. Useful if you want to run the same task multiple
-// times but not at a regular interval.
-class SimpleAlarmTimer : public base::RetainingOneShotTimer {
- public:
- // Creates the SimpleAlarmTimer instance, or returns null on failure, e.g.,
- // on a platform without timerfd_* system calls support, or missing
- // capability (CAP_WAKE_ALARM).
- static std::unique_ptr<SimpleAlarmTimer> Create();
-
- // Similar to Create(), but for unittests without capability.
- // Specifically, uses CLOCK_REALTIME instead of CLOCK_REALTIME_ALARM.
- static std::unique_ptr<SimpleAlarmTimer> CreateForTesting();
-
- ~SimpleAlarmTimer() override;
-
- // Timer overrides.
- void Stop() override;
- void Reset() override;
-
- private:
- // Shared implementation of Create and CreateForTesting.
- static std::unique_ptr<SimpleAlarmTimer> CreateInternal(int clockid);
-
- explicit SimpleAlarmTimer(base::ScopedFD alarm_fd);
-
- // Called when |alarm_fd_| is readable without blocking. Reads data from
- // |alarm_fd_| and calls OnTimerFired().
- void OnAlarmFdReadableWithoutBlocking();
-
- // Called when the timer fires. Runs the callback.
- void OnTimerFired();
-
- // Timer file descriptor.
- const base::ScopedFD alarm_fd_;
-
- // Watches |alarm_fd_|.
- std::unique_ptr<base::FileDescriptorWatcher::Controller> alarm_fd_watcher_;
-
- // Posts tasks to the sequence on which this AlarmTimer was instantiated.
- const scoped_refptr<base::SequencedTaskRunner> origin_task_runner_ =
- base::SequencedTaskRunnerHandle::Get();
-
- // Keeps track of the user task we want to run. A new one is constructed every
- // time Reset() is called.
- std::unique_ptr<base::PendingTask> pending_task_;
-
- // Used to invalidate pending callbacks.
- base::WeakPtrFactory<SimpleAlarmTimer> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(SimpleAlarmTimer);
-};
-
-} // namespace timers
-
-#endif // COMPONENTS_TIMERS_ALARM_TIMER_CHROMEOS_H_
diff --git a/chromium/components/timers/alarm_timer_unittest.cc b/chromium/components/timers/alarm_timer_unittest.cc
deleted file mode 100644
index c8b5224ed42..00000000000
--- a/chromium/components/timers/alarm_timer_unittest.cc
+++ /dev/null
@@ -1,366 +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 <sys/timerfd.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.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"
-#include "components/timers/alarm_timer_chromeos.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// Most of these tests have been lifted right out of timer_unittest.cc with only
-// cosmetic changes. We want the AlarmTimer to be a drop-in replacement for the
-// regular Timer so it should pass the same tests as the Timer class.
-namespace timers {
-namespace {
-
-constexpr base::TimeDelta kTenMilliseconds =
- base::TimeDelta::FromMilliseconds(10);
-
-class AlarmTimerTester {
- public:
- AlarmTimerTester(bool* did_run,
- base::TimeDelta delay,
- base::OnceClosure quit_closure)
- : did_run_(did_run),
- quit_closure_(std::move(quit_closure)),
- delay_(delay),
- timer_(SimpleAlarmTimer::CreateForTesting()) {}
- void Start() {
- timer_->Start(
- FROM_HERE, delay_,
- base::BindRepeating(&AlarmTimerTester::Run, base::Unretained(this)));
- }
-
- private:
- void Run() {
- *did_run_ = true;
- if (quit_closure_)
- std::move(quit_closure_).Run();
- }
-
- bool* did_run_;
- base::OnceClosure quit_closure_;
- const base::TimeDelta delay_;
- std::unique_ptr<SimpleAlarmTimer> timer_;
-
- DISALLOW_COPY_AND_ASSIGN(AlarmTimerTester);
-};
-
-class SelfDeletingAlarmTimerTester {
- public:
- SelfDeletingAlarmTimerTester(bool* did_run,
- base::TimeDelta delay,
- base::OnceClosure quit_closure)
- : did_run_(did_run),
- quit_closure_(std::move(quit_closure)),
- delay_(delay),
- timer_(SimpleAlarmTimer::CreateForTesting()) {}
- void Start() {
- timer_->Start(FROM_HERE, delay_,
- base::BindRepeating(&SelfDeletingAlarmTimerTester::Run,
- base::Unretained(this)));
- }
-
- private:
- void Run() {
- *did_run_ = true;
- timer_.reset();
-
- if (quit_closure_)
- std::move(quit_closure_).Run();
- }
-
- bool* did_run_;
- base::OnceClosure quit_closure_;
- const base::TimeDelta delay_;
- std::unique_ptr<SimpleAlarmTimer> timer_;
-
- DISALLOW_COPY_AND_ASSIGN(SelfDeletingAlarmTimerTester);
-};
-
-} // namespace
-
-//-----------------------------------------------------------------------------
-// Each test is run against each type of MessageLoop. That way we are sure
-// that timers work properly in all configurations.
-
-TEST(AlarmTimerTest, SimpleAlarmTimer) {
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- base::RunLoop run_loop;
- bool did_run = false;
- AlarmTimerTester f(&did_run, kTenMilliseconds,
- run_loop.QuitWhenIdleClosure());
- f.Start();
-
- run_loop.Run();
-
- EXPECT_TRUE(did_run);
-}
-
-TEST(AlarmTimerTest, SimpleAlarmTimer_Cancel) {
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- bool did_run_a = false;
- AlarmTimerTester* a =
- new AlarmTimerTester(&did_run_a, kTenMilliseconds, base::OnceClosure());
-
- // This should run before the timer expires.
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
-
- // Now start the timer.
- a->Start();
-
- base::RunLoop run_loop;
- bool did_run_b = false;
- AlarmTimerTester b(&did_run_b, kTenMilliseconds,
- run_loop.QuitWhenIdleClosure());
- b.Start();
-
- run_loop.Run();
-
- EXPECT_FALSE(did_run_a);
- EXPECT_TRUE(did_run_b);
-}
-
-// If underlying timer does not handle this properly, we will crash or fail
-// in full page heap environment.
-TEST(AlarmTimerTest, SelfDeletingAlarmTimer) {
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- base::RunLoop run_loop;
- bool did_run = false;
- SelfDeletingAlarmTimerTester f(&did_run, kTenMilliseconds,
- run_loop.QuitWhenIdleClosure());
- f.Start();
-
- run_loop.Run();
-
- EXPECT_TRUE(did_run);
-}
-
-TEST(AlarmTimerTest, AlarmTimerZeroDelay) {
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- base::RunLoop run_loop;
- bool did_run = false;
- AlarmTimerTester f(&did_run, base::TimeDelta(),
- run_loop.QuitWhenIdleClosure());
- f.Start();
-
- run_loop.Run();
-
- EXPECT_TRUE(did_run);
-}
-
-TEST(AlarmTimerTest, AlarmTimerZeroDelay_Cancel) {
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- bool did_run_a = false;
- AlarmTimerTester* a =
- new AlarmTimerTester(&did_run_a, base::TimeDelta(), base::OnceClosure());
-
- // This should run before the timer expires.
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
-
- // Now start the timer.
- a->Start();
-
- base::RunLoop run_loop;
- bool did_run_b = false;
- AlarmTimerTester b(&did_run_b, base::TimeDelta(),
- run_loop.QuitWhenIdleClosure());
- b.Start();
-
- run_loop.Run();
-
- EXPECT_FALSE(did_run_a);
- EXPECT_TRUE(did_run_b);
-}
-
-TEST(AlarmTimerTest, MessageLoopShutdown) {
- // This test is designed to verify that shutdown of the
- // message loop does not cause crashes if there were pending
- // timers not yet fired. It may only trigger exceptions
- // if debug heap checking is enabled.
- bool did_run = false;
- {
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- AlarmTimerTester a(&did_run, kTenMilliseconds, base::OnceClosure());
- AlarmTimerTester b(&did_run, kTenMilliseconds, base::OnceClosure());
- AlarmTimerTester c(&did_run, kTenMilliseconds, base::OnceClosure());
- AlarmTimerTester d(&did_run, kTenMilliseconds, base::OnceClosure());
-
- a.Start();
- b.Start();
-
- // Allow FileDescriptorWatcher to start watching the timers. Without this,
- // tasks posted by FileDescriptorWatcher::WatchReadable() are leaked.
- base::RunLoop().RunUntilIdle();
-
- } // SimpleAlarmTimers destruct. SHOULD NOT CRASH, of course.
-
- EXPECT_FALSE(did_run);
-}
-
-TEST(AlarmTimerTest, NonRepeatIsRunning) {
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- auto timer = SimpleAlarmTimer::CreateForTesting();
- EXPECT_FALSE(timer->IsRunning());
- timer->Start(FROM_HERE, base::TimeDelta::FromDays(1), base::DoNothing());
-
- // Allow FileDescriptorWatcher to start watching the timer. Without this, a
- // task posted by FileDescriptorWatcher::WatchReadable() is leaked.
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(timer->IsRunning());
- timer->Stop();
- EXPECT_FALSE(timer->IsRunning());
- ASSERT_FALSE(timer->user_task().is_null());
- timer->Reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(timer->IsRunning());
-}
-
-TEST(AlarmTimerTest, RetainNonRepeatIsRunning) {
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- auto timer = SimpleAlarmTimer::CreateForTesting();
- EXPECT_FALSE(timer->IsRunning());
- timer->Start(FROM_HERE, base::TimeDelta::FromDays(1), base::DoNothing());
-
- // Allow FileDescriptorWatcher to start watching the timer. Without this, a
- // task posted by FileDescriptorWatcher::WatchReadable() is leaked.
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(timer->IsRunning());
- timer->Reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(timer->IsRunning());
- timer->Stop();
- EXPECT_FALSE(timer->IsRunning());
- timer->Reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(timer->IsRunning());
-}
-
-namespace {
-
-bool g_callback_happened1 = false;
-bool g_callback_happened2 = false;
-
-void ClearAllCallbackHappened() {
- g_callback_happened1 = false;
- g_callback_happened2 = false;
-}
-
-void SetCallbackHappened1(base::OnceClosure quit_closure) {
- g_callback_happened1 = true;
- if (quit_closure)
- std::move(quit_closure).Run();
-}
-
-void SetCallbackHappened2(base::OnceClosure quit_closure) {
- g_callback_happened2 = true;
- if (quit_closure)
- std::move(quit_closure).Run();
-}
-
-TEST(AlarmTimerTest, ContinuationStopStart) {
- ClearAllCallbackHappened();
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- auto timer = SimpleAlarmTimer::CreateForTesting();
- timer->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
- base::BindRepeating(&SetCallbackHappened1,
- base::DoNothing().Repeatedly()));
- timer->Stop();
-
- base::RunLoop run_loop;
- timer->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(40),
- base::BindRepeating(&SetCallbackHappened2,
- run_loop.QuitWhenIdleClosure()));
- run_loop.Run();
-
- EXPECT_FALSE(g_callback_happened1);
- EXPECT_TRUE(g_callback_happened2);
-}
-
-TEST(AlarmTimerTest, ContinuationReset) {
- ClearAllCallbackHappened();
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- base::RunLoop run_loop;
- auto timer = SimpleAlarmTimer::CreateForTesting();
- timer->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
- base::BindRepeating(&SetCallbackHappened1,
- run_loop.QuitWhenIdleClosure()));
- timer->Reset();
- ASSERT_FALSE(timer->user_task().is_null());
- run_loop.Run();
- EXPECT_TRUE(g_callback_happened1);
-}
-
-// Verify that no crash occurs if a timer is deleted while its callback is
-// running.
-TEST(AlarmTimerTest, DeleteTimerWhileCallbackIsRunning) {
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
-
- base::RunLoop run_loop;
-
- // Will be deleted by the callback.
- auto timer = SimpleAlarmTimer::CreateForTesting();
- auto* timer_ptr = timer.get();
- timer_ptr->Start(
- FROM_HERE, base::TimeDelta::FromMilliseconds(10),
- base::BindRepeating([](std::unique_ptr<SimpleAlarmTimer> timer,
- base::RunLoop* run_loop) { run_loop->Quit(); },
- base::Passed(std::move(timer)), &run_loop));
- run_loop.Run();
-}
-
-// Verify that no crash occurs if a zero-delay timer is deleted while its
-// callback is running.
-TEST(AlarmTimerTest, DeleteTimerWhileCallbackIsRunningZeroDelay) {
- base::test::TaskEnvironment task_environment(
- base::test::TaskEnvironment::MainThreadType::IO);
- base::RunLoop run_loop;
-
- // Will be deleted by the callback.
- auto timer = SimpleAlarmTimer::CreateForTesting();
- auto* timer_ptr = timer.get();
- timer_ptr->Start(
- FROM_HERE, base::TimeDelta(),
- base::BindRepeating([](std::unique_ptr<SimpleAlarmTimer> timer,
- base::RunLoop* run_loop) { run_loop->Quit(); },
- base::Passed(std::move(timer)), &run_loop));
- run_loop.Run();
-}
-
-} // namespace
-} // namespace timers
diff --git a/chromium/components/translate_strings.grdp b/chromium/components/translate_strings.grdp
index 962e32282a1..238ff6f56c1 100644
--- a/chromium/components/translate_strings.grdp
+++ b/chromium/components/translate_strings.grdp
@@ -57,10 +57,10 @@
<message name="IDS_TRANSLATE_INFOBAR_ERROR" formatter_data="android_java">
Oops. This page could not be translated.
</message>
- <message name="IDS_TRANSLATE_BUTTON" desc="Possible texts to display on the translate infobar buttons. [CHAR-LIMIT=24]" formatter_data="android_java">
+ <message name="IDS_TRANSLATE_BUTTON" desc="Possible texts to display on the translate infobar buttons. [CHAR_LIMIT=24]" formatter_data="android_java">
Translate
</message>
- <message name="IDS_TRANSLATE_NEVER_TRANSLATE_SITE" desc="Text to display on the never translate site (like www.google.com) button. [CHAR-LIMIT=64]" formatter_data="android_java">
+ <message name="IDS_TRANSLATE_NEVER_TRANSLATE_SITE" desc="Text to display on the never translate site (like www.google.com) button. [CHAR_LIMIT=64]" formatter_data="android_java">
Never translate this site
</message>
<message name="IDS_TRANSLATE_DONT_OFFER_SITE" desc="Text to display on overflow option stopping Chrome from offering translate for a site. (like www.google.com)" formatter_data="android_java">
@@ -76,22 +76,22 @@
<message name="IDS_TRANSLATE_DONT_OFFER_LANG" desc="Option in the overflow menu. User can click the 'Don't offer Translate' option to indicate that they don't want the app to offer translations for pages in this language. The variable SOURCE_LANGUAGE could be any of 50+ languages supported by Google Translate, like French, Spanish, German, Italian, Japanese, Korean, etc. Imperative." formatter_data="android_java">
Don‘t offer to translate pages in <ph name="SOURCE_LANGUAGE">%1$s<ex>French</ex></ph>
</message>
- <message name="IDS_TRANSLATE_OPTION_MORE_LANGUAGE" desc="Option in the overflow menu. Lets the user open a dialog to choose other target languages for translation, from a list of available languages. [CHAR-LIMIT=64]" formatter_data="android_java">
+ <message name="IDS_TRANSLATE_OPTION_MORE_LANGUAGE" desc="Option in the overflow menu. Lets the user open a dialog to choose other target languages for translation, from a list of available languages. [CHAR_LIMIT=64]" formatter_data="android_java">
More languages
</message>
- <message name="IDS_TRANSLATE_OPTION_NOT_SOURCE_LANGUAGE" desc="Option in the overflow menu. Sometimes a web page's source language is not correctly identified by Google Translate, and this menu option lets the user open a submenu to select another language as the source language to translate. Phrased as a question as if to query the user, 'Is this page not in [source language identified]? If so, click here.' [CHAR-LIMIT=64]" formatter_data="android_java">
+ <message name="IDS_TRANSLATE_OPTION_NOT_SOURCE_LANGUAGE" desc="Option in the overflow menu. Sometimes a web page's source language is not correctly identified by Google Translate, and this menu option lets the user open a submenu to select another language as the source language to translate. Phrased as a question as if to query the user, 'Is this page not in [source language identified]? If so, click here.' [CHAR_LIMIT=64]" formatter_data="android_java">
Page is not in <ph name="LANGUAGE">%1$s<ex>French</ex></ph>?
</message>
- <message name="IDS_TRANSLATE_SNACKBAR_ALWAYS_TRANSLATE" desc="After the user selects 'Always translate pages in [LANGUAGE]', this text confirms the user's choice and lets them know that pages in [LANGUAGE] will be translated to their chosen target language automatically. Imperative. [CHAR-LIMIT=64]" formatter_data="android_java">
+ <message name="IDS_TRANSLATE_SNACKBAR_ALWAYS_TRANSLATE" desc="After the user selects 'Always translate pages in [LANGUAGE]', this text confirms the user's choice and lets them know that pages in [LANGUAGE] will be translated to their chosen target language automatically. Imperative. [CHAR_LIMIT=64]" formatter_data="android_java">
Pages in <ph name="SOURCE_LANGUAGE">%1$s<ex>French</ex></ph> will be translated to <ph name="TARGET_LANGUAGE">%2$s<ex>English</ex></ph> from now on
</message>
- <message name="IDS_TRANSLATE_SNACKBAR_LANGUAGE_NEVER" desc="After the user selects 'Never translate pages in [LANGUAGE]', this text confirms the user's choice and lets them know that pages in [LANGUAGE] will not be translated to their chosen target language automatically. Imperative[CHAR-LIMIT=64]" formatter_data="android_java">
+ <message name="IDS_TRANSLATE_SNACKBAR_LANGUAGE_NEVER" desc="After the user selects 'Never translate pages in [LANGUAGE]', this text confirms the user's choice and lets them know that pages in [LANGUAGE] will not be translated to their chosen target language automatically. Imperative[CHAR_LIMIT=64]" formatter_data="android_java">
Pages in <ph name="LANGUAGE">%1$s<ex>French</ex></ph> will not be translated
</message>
- <message name="IDS_TRANSLATE_SNACKBAR_SITE_NEVER" desc="Text to be displayed in translate snackbar that lets the user know this site will not be translated. [CHAR-LIMIT=64]" formatter_data="android_java">
+ <message name="IDS_TRANSLATE_SNACKBAR_SITE_NEVER" desc="Text to be displayed in translate snackbar that lets the user know this site will not be translated. [CHAR_LIMIT=64]" formatter_data="android_java">
This site will not be translated
</message>
- <message name="IDS_TRANSLATE_SNACKBAR_CANCEL" desc="A text label on the translate snackbar widget to cancel this selection. [CHAR-LIMIT=16]" formatter_data="android_java">
+ <message name="IDS_TRANSLATE_SNACKBAR_CANCEL" desc="A text label on the translate snackbar widget to cancel this selection. [CHAR_LIMIT=16]" formatter_data="android_java">
Cancel
</message>
</if>
diff --git a/chromium/components/ui_devtools/agent_util.h b/chromium/components/ui_devtools/agent_util.h
index caaf2bdb173..22744b9bfba 100644
--- a/chromium/components/ui_devtools/agent_util.h
+++ b/chromium/components/ui_devtools/agent_util.h
@@ -5,7 +5,8 @@
#ifndef COMPONENTS_UI_DEVTOOLS_AGENT_UTIL_H_
#define COMPONENTS_UI_DEVTOOLS_AGENT_UTIL_H_
-#include "base/files/file_path.h"
+#include <string>
+
#include "components/ui_devtools/devtools_export.h"
namespace ui_devtools {
diff --git a/chromium/components/ui_devtools/css_agent.cc b/chromium/components/ui_devtools/css_agent.cc
index a4048bb7b7d..ef070878171 100644
--- a/chromium/components/ui_devtools/css_agent.cc
+++ b/chromium/components/ui_devtools/css_agent.cc
@@ -271,9 +271,8 @@ Response CSSAgent::setStyleTexts(
if (!ui_element)
return Response::ServerError("Node id not found");
- // Handle setting properties from metadata for View.
- if (ui_element->type() != VIEW ||
- !ui_element->SetPropertiesFromString(edit->getText())) {
+ // Handle setting properties from metadata for elements which use metadata.
+ if (!ui_element->SetPropertiesFromString(edit->getText())) {
gfx::Rect updated_bounds;
bool visible = false;
if (!GetPropertiesForUIElement(ui_element, &updated_bounds, &visible))
diff --git a/chromium/components/ui_devtools/css_agent_unittest.cc b/chromium/components/ui_devtools/css_agent_unittest.cc
index 3e1e64b0922..6ee5961cceb 100644
--- a/chromium/components/ui_devtools/css_agent_unittest.cc
+++ b/chromium/components/ui_devtools/css_agent_unittest.cc
@@ -6,7 +6,6 @@
#include "base/strings/string_number_conversions.h"
#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"
diff --git a/chromium/components/ui_devtools/devtools_export.h b/chromium/components/ui_devtools/devtools_export.h
index 1a94a2c50e8..02aa32f30db 100644
--- a/chromium/components/ui_devtools/devtools_export.h
+++ b/chromium/components/ui_devtools/devtools_export.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_UI_DEVTOOLS_EXPORT_H_
-#define COMPONENTS_UI_DEVTOOLS_EXPORT_H_
+#ifndef COMPONENTS_UI_DEVTOOLS_DEVTOOLS_EXPORT_H_
+#define COMPONENTS_UI_DEVTOOLS_DEVTOOLS_EXPORT_H_
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
@@ -26,4 +26,4 @@
#define UI_DEVTOOLS_EXPORT
#endif
-#endif // COMPONENTS_UI_DEVTOOLS_EXPORT_H_
+#endif // COMPONENTS_UI_DEVTOOLS_DEVTOOLS_EXPORT_H_
diff --git a/chromium/components/ui_devtools/devtools_server.cc b/chromium/components/ui_devtools/devtools_server.cc
index ea25b6112e5..4675946dad2 100644
--- a/chromium/components/ui_devtools/devtools_server.cc
+++ b/chromium/components/ui_devtools/devtools_server.cc
@@ -107,7 +107,7 @@ std::unique_ptr<UiDevToolsServer> UiDevToolsServer::CreateForViz(
int port) {
auto server =
base::WrapUnique(new UiDevToolsServer(port, kVizDevtoolsServerTag));
- server->MakeServer(std::move(server_socket), net::OK, base::nullopt);
+ server->MakeServer(std::move(server_socket), net::OK, absl::nullopt);
return server;
}
@@ -185,7 +185,7 @@ void UiDevToolsServer::SetOnSessionEnded(base::OnceClosure callback) const {
void UiDevToolsServer::MakeServer(
mojo::PendingRemote<network::mojom::TCPServerSocket> server_socket,
int result,
- const base::Optional<net::IPEndPoint>& local_addr) {
+ const absl::optional<net::IPEndPoint>& local_addr) {
DCHECK_CALLED_ON_VALID_SEQUENCE(devtools_server_sequence_);
if (result == net::OK) {
server_ = std::make_unique<network::server::HttpServer>(
diff --git a/chromium/components/ui_devtools/devtools_server.h b/chromium/components/ui_devtools/devtools_server.h
index 4bfb4559574..7a8b1ffd7ae 100644
--- a/chromium/components/ui_devtools/devtools_server.h
+++ b/chromium/components/ui_devtools/devtools_server.h
@@ -87,7 +87,7 @@ class UI_DEVTOOLS_EXPORT UiDevToolsServer
void MakeServer(
mojo::PendingRemote<network::mojom::TCPServerSocket> server_socket,
int result,
- const base::Optional<net::IPEndPoint>& local_addr);
+ const absl::optional<net::IPEndPoint>& local_addr);
// HttpServer::Delegate
void OnConnect(int connection_id) override;
diff --git a/chromium/components/ui_devtools/dom_agent.cc b/chromium/components/ui_devtools/dom_agent.cc
index c1ae1d3237b..a30eddf6c61 100644
--- a/chromium/components/ui_devtools/dom_agent.cc
+++ b/chromium/components/ui_devtools/dom_agent.cc
@@ -403,4 +403,14 @@ protocol::Response DOMAgent::dispatchMouseEvent(
return Response::Success();
}
+protocol::Response DOMAgent::dispatchKeyEvent(
+ int node_id,
+ std::unique_ptr<protocol::DOM::KeyEvent> event) {
+ if (node_id_to_ui_element_.count(node_id) == 0)
+ return Response::ServerError("Element not found on node id");
+ if (!node_id_to_ui_element_[node_id]->DispatchKeyEvent(event.get()))
+ return Response::ServerError("Failed to dispatch key event for node id");
+ return Response::Success();
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/dom_agent.h b/chromium/components/ui_devtools/dom_agent.h
index 759074847ad..ecf91c414d2 100644
--- a/chromium/components/ui_devtools/dom_agent.h
+++ b/chromium/components/ui_devtools/dom_agent.h
@@ -55,6 +55,9 @@ class UI_DEVTOOLS_EXPORT DOMAgent
protocol::Response dispatchMouseEvent(
int node_id,
std::unique_ptr<protocol::DOM::MouseEvent> event) override;
+ protocol::Response dispatchKeyEvent(
+ int node_id,
+ std::unique_ptr<protocol::DOM::KeyEvent> event) override;
// UIElementDelegate:
void OnUIElementAdded(UIElement* parent, UIElement* child) override;
diff --git a/chromium/components/ui_devtools/protocol.json b/chromium/components/ui_devtools/protocol.json
index 7d1d7cf282e..db029e3ab0f 100644
--- a/chromium/components/ui_devtools/protocol.json
+++ b/chromium/components/ui_devtools/protocol.json
@@ -105,6 +105,22 @@
}
],
"description": "Dispatch a mouse event for a given node. Only used for UI Devtools."
+ },
+ {
+ "name": "dispatchKeyEvent",
+ "parameters": [
+ {
+ "name": "nodeId",
+ "$ref": "NodeId",
+ "description": "Id of the node."
+ },
+ {
+ "name": "event",
+ "$ref": "KeyEvent",
+ "description": "Keyboard event to dispatch."
+ }
+ ],
+ "description": "Dispatch a keyboard event for a given node. Only used for UI Devtools."
}
],
"description": "This domain exposes DOM read/write operations. Each DOM Node is represented with its mirror object\nthat has an `id`. This `id` can be used to get additional information on the Node, resolve it into\nthe JavaScript object wrapper, etc. It is important that client receives DOM events only for the\nnodes that are known to the client. Backend keeps track of the nodes that were sent to the client\nand never sends the same node twice. It is client's responsibility to collect information about\nthe nodes that were sent to the client.<p>Note that `iframe` owner elements will return\ncorresponding document elements as their child nodes.</p>",
@@ -308,7 +324,48 @@
"description": "Only used for mouseWheel event."
}
]
- }
+ },
+ {
+ "id": "KeyEvent",
+ "description": "Used by dispatchKeyEvent. Only used for UI DevTools. Mirroring the KeyEvent class from ui/events/event.h",
+ "type": "object",
+ "properties" : [
+ {
+ "name": "type",
+ "type": "string",
+ "enum": [
+ "keyPressed",
+ "keyReleased"
+ ],
+ "description": "Key event type."
+ },
+ {
+ "name": "keyCode",
+ "type": "integer",
+ "description": "Virtual key code. Definition: ui/events/keycodes/keyboard_codes_posix.h"
+ },
+ {
+ "name": "code",
+ "type": "integer",
+ "description": "Dom code. Definition: ui/events/keycodes/dom/dom_code_data.inc"
+ },
+ {
+ "name": "flags",
+ "type": "integer",
+ "description": "Event flags for keyboard modifiers. Definition: ui/events/event_constants.h"
+ },
+ {
+ "name": "key",
+ "type": "integer",
+ "description": "Provide meaning of a key. It's either a dom key value for a key stroke event or an unicode character for a character event."
+ },
+ {
+ "name": "isChar",
+ "type": "boolean",
+ "description": "Whether it's a character event or a key stroke event."
+ }
+ ]
+ }
]
},
{
diff --git a/chromium/components/ui_devtools/ui_element.cc b/chromium/components/ui_devtools/ui_element.cc
index abe06fc3156..794d2ae124d 100644
--- a/chromium/components/ui_devtools/ui_element.cc
+++ b/chromium/components/ui_devtools/ui_element.cc
@@ -135,7 +135,6 @@ UIElement::UIElement(const UIElementType type,
}
bool UIElement::SetPropertiesFromString(const std::string& text) {
- NOTREACHED();
return false;
}
@@ -154,4 +153,8 @@ bool UIElement::DispatchMouseEvent(protocol::DOM::MouseEvent* event) {
return false;
}
+bool UIElement::DispatchKeyEvent(protocol::DOM::KeyEvent* event) {
+ return false;
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/ui_element.h b/chromium/components/ui_devtools/ui_element.h
index c95a8b072e2..9a081f7648c 100644
--- a/chromium/components/ui_devtools/ui_element.h
+++ b/chromium/components/ui_devtools/ui_element.h
@@ -50,10 +50,13 @@ class UI_DEVTOOLS_EXPORT UIElement {
using UIElements = std::vector<UIElement*>;
+ UIElement(const UIElement&) = delete;
+ UIElement& operator=(const UIElement&) = delete;
+ virtual ~UIElement();
+
// resets node ids to 0 so that they are reusable
static void ResetNodeId();
- virtual ~UIElement();
int node_id() const { return node_id_; }
std::string GetTypeName() const;
UIElement* parent() const { return parent_; }
@@ -139,6 +142,8 @@ class UI_DEVTOOLS_EXPORT UIElement {
virtual bool DispatchMouseEvent(protocol::DOM::MouseEvent* event);
+ virtual bool DispatchKeyEvent(protocol::DOM::KeyEvent* event);
+
protected:
UIElement(const UIElementType type,
UIElementDelegate* delegate,
@@ -156,8 +161,6 @@ class UI_DEVTOOLS_EXPORT UIElement {
int base_stylesheet_id_;
bool header_sent_ = false;
std::vector<Source> sources_;
-
- DISALLOW_COPY_AND_ASSIGN(UIElement);
};
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/ui_element_delegate.h b/chromium/components/ui_devtools/ui_element_delegate.h
index 7b3205b73fe..af2656e277d 100644
--- a/chromium/components/ui_devtools/ui_element_delegate.h
+++ b/chromium/components/ui_devtools/ui_element_delegate.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_UI_DEVTOOLS_UI_ELEMENT_DELEGATE_H_
#define COMPONENTS_UI_DEVTOOLS_UI_ELEMENT_DELEGATE_H_
-#include <vector>
-
#include "base/macros.h"
namespace ui_devtools {
diff --git a/chromium/components/ui_devtools/views/BUILD.gn b/chromium/components/ui_devtools/views/BUILD.gn
index e9fb3b23196..422fa006f5e 100644
--- a/chromium/components/ui_devtools/views/BUILD.gn
+++ b/chromium/components/ui_devtools/views/BUILD.gn
@@ -11,6 +11,8 @@ source_set("views") {
}
sources = [
+ "devtools_event_util.cc",
+ "devtools_event_util.h",
"devtools_server_util.cc",
"devtools_server_util.h",
"dom_agent_views.cc",
@@ -21,6 +23,8 @@ source_set("views") {
"overlay_agent_views.h",
"page_agent_views.cc",
"page_agent_views.h",
+ "ui_element_with_metadata.cc",
+ "ui_element_with_metadata.h",
"view_element.cc",
"view_element.h",
"widget_element.cc",
diff --git a/chromium/components/ui_devtools/views/DEPS b/chromium/components/ui_devtools/views/DEPS
index 7484cad79df..b9bcc8fe7a8 100644
--- a/chromium/components/ui_devtools/views/DEPS
+++ b/chromium/components/ui_devtools/views/DEPS
@@ -1,5 +1,6 @@
include_rules = [
+ "+components/viz/common/surfaces",
"+extensions/common/image_util.h",
"+third_party/skia/include",
- "+ui"
+ "+ui",
]
diff --git a/chromium/components/ui_devtools/views/devtools_event_util.cc b/chromium/components/ui_devtools/views/devtools_event_util.cc
new file mode 100644
index 00000000000..779bbd4f6c9
--- /dev/null
+++ b/chromium/components/ui_devtools/views/devtools_event_util.cc
@@ -0,0 +1,23 @@
+// Copyright 2021 The Chromium Authors. 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/devtools_event_util.h"
+#include "ui/events/types/event_type.h"
+
+namespace ui_devtools {
+
+ui::KeyEvent ConvertToUIKeyEvent(protocol::DOM::KeyEvent* event) {
+ ui::EventType event_type =
+ event->getType() == protocol::DOM::KeyEvent::TypeEnum::KeyPressed
+ ? ui::ET_KEY_PRESSED
+ : ui::ET_KEY_RELEASED;
+ return ui::KeyEvent(
+ event_type, static_cast<ui::KeyboardCode>(event->getKeyCode()),
+ static_cast<ui::DomCode>(event->getCode()), event->getFlags(),
+ event->getIsChar() ? ui::DomKey::FromCharacter(event->getKey())
+ : ui::DomKey(event->getKey()),
+ ui::EventTimeForNow(), event->getIsChar());
+}
+
+} // namespace ui_devtools \ No newline at end of file
diff --git a/chromium/components/ui_devtools/views/devtools_event_util.h b/chromium/components/ui_devtools/views/devtools_event_util.h
new file mode 100644
index 00000000000..88ab6f89ba1
--- /dev/null
+++ b/chromium/components/ui_devtools/views/devtools_event_util.h
@@ -0,0 +1,17 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_DEVTOOLS_EVENT_UTIL_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_DEVTOOLS_EVENT_UTIL_H_
+
+#include "components/ui_devtools/DOM.h"
+#include "ui/events/event_utils.h"
+
+namespace ui_devtools {
+
+ui::KeyEvent ConvertToUIKeyEvent(protocol::DOM::KeyEvent* event);
+
+} // namespace ui_devtools
+
+#endif // COMPONENTS_UI_DEVTOOLS_VIEWS_DEVTOOLS_EVENT_UTIL_H_
diff --git a/chromium/components/ui_devtools/views/dom_agent_mac.mm b/chromium/components/ui_devtools/views/dom_agent_mac.mm
index 59fc8fdac3a..e9aa5a39301 100644
--- a/chromium/components/ui_devtools/views/dom_agent_mac.mm
+++ b/chromium/components/ui_devtools/views/dom_agent_mac.mm
@@ -45,6 +45,7 @@ std::vector<UIElement*> DOMAgentMac::CreateChildrenForRoot() {
}
void DOMAgentMac::OnWidgetDestroying(views::Widget* widget) {
+ widget->RemoveObserver(this);
roots_.erase(std::find(roots_.begin(), roots_.end(), widget), roots_.end());
}
@@ -54,6 +55,7 @@ void DOMAgentMac::OnNativeWidgetAdded(views::NativeWidgetMac* native_widget) {
roots_.push_back(widget);
UIElement* widget_element = new WidgetElement(widget, this, element_root());
element_root()->AddChild(widget_element);
+ widget->AddObserver(this);
}
std::unique_ptr<protocol::DOM::Node> DOMAgentMac::BuildTreeForWindow(
diff --git a/chromium/components/ui_devtools/views/dom_agent_unittest.cc b/chromium/components/ui_devtools/views/dom_agent_unittest.cc
index ba7517438a0..d7ad99918e2 100644
--- a/chromium/components/ui_devtools/views/dom_agent_unittest.cc
+++ b/chromium/components/ui_devtools/views/dom_agent_unittest.cc
@@ -614,7 +614,7 @@ TEST_F(DOMAgentTest, SimpleDomSearch) {
std::string search_id;
int result_count = 0;
- std::unique_ptr<protocol::Array<int>> node_ids = nullptr;
+ std::unique_ptr<protocol::Array<int>> node_ids;
// 1 match
dom_agent()->performSearch("child_a1", false, &search_id, &result_count);
@@ -640,7 +640,7 @@ TEST_F(DOMAgentTest, ExactDomSearch) {
dom_agent()->getDocument(&root);
std::string search_id;
int result_count = 0;
- std::unique_ptr<protocol::Array<int>> node_ids = nullptr;
+ std::unique_ptr<protocol::Array<int>> node_ids;
// substring matches
dom_agent()->performSearch("child_a", false, &search_id, &result_count);
@@ -675,7 +675,7 @@ TEST_F(DOMAgentTest, TagDomSearch) {
dom_agent()->getDocument(&root);
std::string search_id;
int result_count = 0;
- std::unique_ptr<protocol::Array<int>> node_ids = nullptr;
+ std::unique_ptr<protocol::Array<int>> node_ids;
// normal search looks for any "widget" substrings
dom_agent()->performSearch("widget", false, &search_id, &result_count);
@@ -701,7 +701,7 @@ TEST_F(DOMAgentTest, DomSearchForStylesPanel) {
std::string search_id;
int result_count = 0;
- std::unique_ptr<protocol::Array<int>> node_ids = nullptr;
+ std::unique_ptr<protocol::Array<int>> node_ids;
// Search for something that is in style properties but not in dom name or
// attributes.
diff --git a/chromium/components/ui_devtools/views/element_utility.cc b/chromium/components/ui_devtools/views/element_utility.cc
index 67813479e02..6f721e969b5 100644
--- a/chromium/components/ui_devtools/views/element_utility.cc
+++ b/chromium/components/ui_devtools/views/element_utility.cc
@@ -7,6 +7,7 @@
#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.h"
#include "ui/compositor/layer_owner.h"
namespace ui_devtools {
diff --git a/chromium/components/ui_devtools/views/overlay_agent_unittest.cc b/chromium/components/ui_devtools/views/overlay_agent_unittest.cc
index 00c8f366198..dbefbdb6456 100644
--- a/chromium/components/ui_devtools/views/overlay_agent_unittest.cc
+++ b/chromium/components/ui_devtools/views/overlay_agent_unittest.cc
@@ -4,6 +4,7 @@
#include "components/ui_devtools/views/overlay_agent_views.h"
+#include "base/strings/stringprintf.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"
@@ -114,12 +115,14 @@ class OverlayAgentTest : public views::ViewsTestBase {
}
#endif
- void CreateWidget(const gfx::Rect& bounds) {
+ void CreateWidget(const gfx::Rect& bounds,
+ views::Widget::InitParams::Type type) {
widget_ = std::make_unique<views::Widget>();
views::Widget::InitParams params;
params.delegate = nullptr;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.bounds = bounds;
+ params.type = type;
#if defined(USE_AURA)
params.parent = GetContext();
#endif
@@ -129,7 +132,8 @@ class OverlayAgentTest : public views::ViewsTestBase {
void CreateWidget() {
// Create a widget with default bounds.
- return CreateWidget(gfx::Rect(0, 0, 400, 400));
+ return CreateWidget(gfx::Rect(0, 0, 400, 400),
+ views::Widget::InitParams::Type::TYPE_WINDOW);
}
views::Widget* widget() { return widget_.get(); }
@@ -176,13 +180,14 @@ TEST_F(OverlayAgentTest, FindElementIdTargetedByPointWindow) {
#endif
TEST_F(OverlayAgentTest, FindElementIdTargetedByPointViews) {
- CreateWidget();
+ // Use a frameless window instead of deleting all children of |contents_view|
+ CreateWidget(gfx::Rect(0, 0, 400, 400),
+ views::Widget::InitParams::Type::TYPE_WINDOW_FRAMELESS);
std::unique_ptr<protocol::DOM::Node> root;
dom_agent()->getDocument(&root);
- views::View* contents_view = widget()->GetContentsView();
- contents_view->RemoveAllChildViews(true);
+ views::View* contents_view = widget()->GetRootView();
views::View* child_1 = new views::View;
views::View* child_2 = new views::View;
@@ -203,7 +208,7 @@ TEST_F(OverlayAgentTest, FindElementIdTargetedByPointViews) {
child_1->SetBounds(20, 20, 100, 100);
child_2->SetBounds(90, 50, 100, 100);
- EXPECT_EQ(GetViewAtPoint(1, 1), widget()->GetContentsView());
+ EXPECT_EQ(GetViewAtPoint(1, 1), widget()->GetRootView());
EXPECT_EQ(GetViewAtPoint(21, 21), child_1);
EXPECT_EQ(GetViewAtPoint(170, 130), child_2);
// At the overlap.
@@ -237,7 +242,7 @@ TEST_F(OverlayAgentTest, HighlightRects) {
for (const auto& test_case : kTestCases) {
SCOPED_TRACE(testing::Message() << "Case: " << test_case.name);
- CreateWidget(kWidgetBounds);
+ CreateWidget(kWidgetBounds, views::Widget::InitParams::Type::TYPE_WINDOW);
// Can't just use kWidgetBounds because of Mac's menu bar.
gfx::Vector2d widget_screen_offset =
widget()->GetClientAreaBoundsInScreen().OffsetFromOrigin();
@@ -265,7 +270,6 @@ TEST_F(OverlayAgentTest, HighlightRects) {
overlay_agent()->setInspectMode(
"searchForNode", protocol::Maybe<protocol::Overlay::HighlightConfig>());
ui::test::EventGenerator generator(GetRootWindow(widget()));
- generator.set_assume_window_at_origin(false);
// Highlight child 1.
generator.MoveMouseTo(GetOriginInScreen(child_1));
@@ -314,7 +318,7 @@ TEST_F(OverlayAgentTest, MouseEventsGenerateFEEventsInInspectMode) {
// Moving the mouse cursor over the widget bounds should request a node
// highlight.
ui::test::EventGenerator generator(GetRootWindow(widget()));
- generator.MoveMouseBy(p.x(), p.y());
+ generator.MoveMouseTo(widget()->GetClientAreaBoundsInScreen().origin());
// Aura platforms generate both ET_MOUSE_ENTERED and ET_MOUSE_MOVED for
// this but Mac just generates ET_MOUSE_ENTERED, so just ensure we sent
diff --git a/chromium/components/ui_devtools/views/ui_element_with_metadata.cc b/chromium/components/ui_devtools/views/ui_element_with_metadata.cc
new file mode 100644
index 00000000000..e391c2b2eab
--- /dev/null
+++ b/chromium/components/ui_devtools/views/ui_element_with_metadata.cc
@@ -0,0 +1,145 @@
+// Copyright 2021 The Chromium Authors. 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/ui_element_with_metadata.h"
+
+#include "base/notreached.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/ui_devtools/views/element_utility.h"
+#include "ui/base/metadata/metadata_types.h"
+
+namespace ui_devtools {
+
+namespace {
+
+// Remove any custom editor "prefixes" from the property name. The prefixes must
+// not be valid identifier characters.
+void StripPrefix(std::string& property_name) {
+ auto cur = property_name.cbegin();
+ for (; cur < property_name.cend(); ++cur) {
+ if ((*cur >= 'A' && *cur <= 'Z') || (*cur >= 'a' && *cur <= 'z') ||
+ *cur == '_') {
+ break;
+ }
+ }
+ property_name.erase(property_name.cbegin(), cur);
+}
+
+} // namespace
+
+UIElementWithMetaData::UIElementWithMetaData(const UIElementType type,
+ UIElementDelegate* delegate,
+ UIElement* parent)
+ : UIElement(type, delegate, parent) {}
+
+UIElementWithMetaData::~UIElementWithMetaData() = default;
+
+std::vector<UIElement::ClassProperties>
+UIElementWithMetaData::GetCustomPropertiesForMatchedStyle() const {
+ std::vector<UIElement::ClassProperties> ret;
+ std::vector<UIElement::UIProperty> class_properties;
+
+ ui::Layer* layer = GetLayer();
+ if (layer) {
+ AppendLayerPropertiesMatchedStyle(layer, &class_properties);
+ ret.emplace_back("Layer", class_properties);
+ class_properties.clear();
+ }
+
+ ui::metadata::ClassMetaData* metadata = GetClassMetaData();
+ void* instance = GetClassInstance();
+ for (auto member = metadata->begin(); member != metadata->end(); member++) {
+ auto flags = (*member)->GetPropertyFlags();
+ if (!!(flags & ui::metadata::PropertyFlags::kSerializable) ||
+ !!(flags & ui::metadata::PropertyFlags::kReadOnly)) {
+ class_properties.emplace_back(
+ (*member)->GetMemberNamePrefix() + (*member)->member_name(),
+ base::UTF16ToUTF8((*member)->GetValueAsString(instance)));
+ }
+
+ if (member.IsLastMember()) {
+ ret.emplace_back(member.GetCurrentCollectionName(), class_properties);
+ class_properties.clear();
+ }
+ }
+ return ret;
+}
+
+void UIElementWithMetaData::GetVisible(bool* visible) const {
+ // Visibility information should be directly retrieved from element's
+ // metadata, no need for this function any more.
+ NOTREACHED();
+}
+
+void UIElementWithMetaData::SetVisible(bool visible) {
+ // Intentional No-op.
+}
+
+bool UIElementWithMetaData::SetPropertiesFromString(const std::string& text) {
+ bool property_set = false;
+ std::vector<std::string> tokens = base::SplitString(
+ text, ":;", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ if (tokens.size() == 0UL)
+ return false;
+
+ ui::metadata::ClassMetaData* metadata = GetClassMetaData();
+ void* instance = GetClassInstance();
+
+ for (size_t i = 0; i < tokens.size() - 1; i += 2) {
+ std::string property_name = tokens.at(i);
+ std::string property_value = base::ToLowerASCII(tokens.at(i + 1));
+
+ // Remove any type editor "prefixes" from the property name.
+ StripPrefix(property_name);
+
+ ui::metadata::MemberMetaDataBase* member =
+ metadata->FindMemberData(property_name);
+ if (!member) {
+ DLOG(ERROR) << "UI DevTools: Can not find property " << property_name
+ << " in MetaData.";
+ continue;
+ }
+
+ // Since DevTools frontend doesn't check the value, we do a sanity check
+ // based on the allowed values specified in the metadata.
+ auto valid_values = member->GetValidValues();
+ if (!valid_values.empty() &&
+ std::find(valid_values.begin(), valid_values.end(),
+ base::UTF8ToUTF16(property_value)) == valid_values.end()) {
+ // Ignore the value.
+ continue;
+ }
+
+ auto property_flags = member->GetPropertyFlags();
+ if (!!(property_flags & ui::metadata::PropertyFlags::kReadOnly))
+ continue;
+ DCHECK(!!(property_flags & ui::metadata::PropertyFlags::kSerializable));
+ member->SetValueAsString(instance, base::UTF8ToUTF16(property_value));
+ property_set = true;
+ }
+
+ return property_set;
+}
+
+void UIElementWithMetaData::InitSources() {
+ if (GetLayer())
+ AddSource("ui/compositor/layer.h", 0);
+
+ for (ui::metadata::ClassMetaData* metadata = 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());
+ }
+ }
+}
+
+ui::Layer* UIElementWithMetaData::GetLayer() const {
+ return nullptr;
+}
+
+} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/ui_element_with_metadata.h b/chromium/components/ui_devtools/views/ui_element_with_metadata.h
new file mode 100644
index 00000000000..d0d43b30d37
--- /dev/null
+++ b/chromium/components/ui_devtools/views/ui_element_with_metadata.h
@@ -0,0 +1,51 @@
+// Copyright 2021 The Chromium Authors. 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_VIEWS_UI_ELEMENT_WITH_METADATA_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_UI_ELEMENT_WITH_METADATA_H_
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "components/ui_devtools/ui_element.h"
+#include "ui/base/metadata/metadata_types.h"
+#include "ui/compositor/layer.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ui_devtools {
+
+class UIElementWithMetaData : public UIElement {
+ public:
+ UIElementWithMetaData(const UIElementWithMetaData&) = delete;
+ UIElementWithMetaData& operator=(const UIElementWithMetaData&) = delete;
+ ~UIElementWithMetaData() override;
+
+ // UIElement:
+ std::vector<UIElement::ClassProperties> GetCustomPropertiesForMatchedStyle()
+ const override;
+ void GetVisible(bool* visible) const override;
+ void SetVisible(bool visible) override;
+ bool SetPropertiesFromString(const std::string& text) override;
+ void InitSources() override;
+
+ protected:
+ UIElementWithMetaData(const UIElementType type,
+ UIElementDelegate* delegate,
+ UIElement* parent);
+
+ // Returns the metadata for the class instance type for this specific element.
+ virtual ui::metadata::ClassMetaData* GetClassMetaData() const = 0;
+ // Returns an opaque pointer for the actual instance which this element
+ // represents.
+ virtual void* GetClassInstance() const = 0;
+ // Returns the layer for the given element if one exists. Returns null if no
+ // layer is currently available.
+ virtual ui::Layer* GetLayer() const;
+};
+
+} // namespace ui_devtools
+
+#endif // COMPONENTS_UI_DEVTOOLS_VIEWS_UI_ELEMENT_WITH_METADATA_H_
diff --git a/chromium/components/ui_devtools/views/view_element.cc b/chromium/components/ui_devtools/views/view_element.cc
index 50dc58d4c91..274d3a8375b 100644
--- a/chromium/components/ui_devtools/views/view_element.cc
+++ b/chromium/components/ui_devtools/views/view_element.cc
@@ -11,29 +11,18 @@
#include "base/strings/utf_string_conversions.h"
#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/ui_element_delegate.h"
+#include "components/ui_devtools/views/devtools_event_util.h"
#include "components/ui_devtools/views/element_utility.h"
-#include "ui/events/event_utils.h"
+#include "ui/base/metadata/metadata_types.h"
#include "ui/gfx/color_utils.h"
-#include "ui/views/metadata/metadata_types.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/view_utils.h"
#include "ui/views/widget/widget.h"
namespace ui_devtools {
namespace {
-// Remove any custom editor "prefixes" from the property name. The prefixes must
-// not be valid identifier characters.
-void StripPrefix(std::string& property_name) {
- auto cur = property_name.cbegin();
- for (; cur < property_name.cend(); ++cur) {
- if ((*cur >= 'A' && *cur <= 'Z') || (*cur >= 'a' && *cur <= 'z') ||
- *cur == '_') {
- break;
- }
- }
- property_name.erase(property_name.cbegin(), cur);
-}
-
ui::EventType GetMouseEventType(const std::string& type) {
if (type == protocol::DOM::MouseEvent::TypeEnum::MousePressed)
return ui::ET_MOUSE_PRESSED;
@@ -91,13 +80,12 @@ int GetMouseWheelYOffset(const std::string& mouse_wheel_direction) {
ViewElement::ViewElement(views::View* view,
UIElementDelegate* ui_element_delegate,
UIElement* parent)
- : UIElement(UIElementType::VIEW, ui_element_delegate, parent), view_(view) {
- view_->AddObserver(this);
+ : UIElementWithMetaData(UIElementType::VIEW, ui_element_delegate, parent),
+ view_(view) {
+ observer_.Observe(view_);
}
-ViewElement::~ViewElement() {
- view_->RemoveObserver(this);
-}
+ViewElement::~ViewElement() = default;
void ViewElement::OnChildViewRemoved(views::View* parent, views::View* view) {
DCHECK_EQ(parent, view_);
@@ -134,36 +122,6 @@ void ViewElement::OnViewBoundsChanged(views::View* view) {
delegate()->OnUIElementBoundsChanged(this);
}
-std::vector<UIElement::ClassProperties>
-ViewElement::GetCustomPropertiesForMatchedStyle() const {
- std::vector<UIElement::ClassProperties> ret;
-
- ui::Layer* layer = view_->layer();
- if (layer) {
- std::vector<UIElement::UIProperty> layer_properties;
- AppendLayerPropertiesMatchedStyle(layer, &layer_properties);
- ret.emplace_back("Layer", layer_properties);
- }
-
- std::vector<UIElement::UIProperty> class_properties;
- views::metadata::ClassMetaData* metadata = view_->GetClassMetaData();
- for (auto member = metadata->begin(); member != metadata->end(); member++) {
- auto flags = (*member)->GetPropertyFlags();
- if (!!(flags & views::metadata::PropertyFlags::kSerializable) ||
- !!(flags & views::metadata::PropertyFlags::kReadOnly)) {
- class_properties.emplace_back(
- (*member)->GetMemberNamePrefix() + (*member)->member_name(),
- base::UTF16ToUTF8((*member)->GetValueAsString(view_)));
- }
-
- if (member.IsLastMember()) {
- ret.emplace_back(member.GetCurrentCollectionName(), class_properties);
- class_properties.clear();
- }
- }
- return ret;
-}
-
void ViewElement::GetBounds(gfx::Rect* bounds) const {
*bounds = view_->bounds();
}
@@ -172,61 +130,6 @@ void ViewElement::SetBounds(const gfx::Rect& bounds) {
view_->SetBoundsRect(bounds);
}
-void ViewElement::GetVisible(bool* visible) const {
- // Visibility information should be directly retrieved from View's metadata,
- // no need for this function any more.
- NOTREACHED();
-}
-
-void ViewElement::SetVisible(bool visible) {
- // Intentional No-op.
-}
-
-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);
-
- if (tokens.size() == 0UL)
- return false;
-
- for (size_t i = 0; i < tokens.size() - 1; i += 2) {
- std::string property_name = tokens.at(i);
- std::string property_value = base::ToLowerASCII(tokens.at(i + 1));
-
- // Remove any type editor "prefixes" from the property name.
- StripPrefix(property_name);
-
- views::metadata::ClassMetaData* metadata = view_->GetClassMetaData();
- views::metadata::MemberMetaDataBase* member =
- metadata->FindMemberData(property_name);
- if (!member) {
- DLOG(ERROR) << "UI DevTools: Can not find property " << property_name
- << " in MetaData.";
- continue;
- }
-
- // Since DevTools frontend doesn't check the value, we do a sanity check
- // based on the allowed values specified in the metadata.
- auto valid_values = member->GetValidValues();
- if (!valid_values.empty() &&
- std::find(valid_values.begin(), valid_values.end(),
- base::UTF8ToUTF16(property_value)) == valid_values.end()) {
- // Ignore the value.
- continue;
- }
-
- auto property_flags = member->GetPropertyFlags();
- if (!!(property_flags & views::metadata::PropertyFlags::kReadOnly))
- continue;
- DCHECK(!!(property_flags & views::metadata::PropertyFlags::kSerializable));
- member->SetValueAsString(view_, base::UTF8ToUTF16(property_value));
- property_set = true;
- }
-
- return property_set;
-}
-
std::vector<std::string> ViewElement::GetAttributes() const {
// TODO(lgrey): Change name to class after updating tests.
return {"name", view_->GetClassName()};
@@ -263,20 +166,6 @@ 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());
- }
- }
-}
-
bool ViewElement::DispatchMouseEvent(protocol::DOM::MouseEvent* event) {
ui::EventType event_type = GetMouseEventType(event->getType());
int button_flags = GetButtonFlags(event->getButton());
@@ -299,4 +188,35 @@ bool ViewElement::DispatchMouseEvent(protocol::DOM::MouseEvent* event) {
return true;
}
+bool ViewElement::DispatchKeyEvent(protocol::DOM::KeyEvent* event) {
+ ui::KeyEvent key_event = ConvertToUIKeyEvent(event);
+ // Key events are processed differently based on classes. Character events are
+ // routed to the text input client while key stroke events are propragated
+ // through the normal event flow. The IME flow is bypassed.
+ if (key_event.is_char()) {
+ // Since the IME flow is bypassed, we need to manually add ui components
+ // we want to receive character events here.
+ if (views::IsViewClass<views::Textfield>(view_)) {
+ static_cast<views::Textfield*>(view_)->InsertChar(key_event);
+ } else {
+ return false;
+ }
+ } else {
+ view_->OnKeyEvent(&key_event);
+ }
+ return true;
+}
+
+ui::metadata::ClassMetaData* ViewElement::GetClassMetaData() const {
+ return view_->GetClassMetaData();
+}
+
+void* ViewElement::GetClassInstance() const {
+ return view_;
+}
+
+ui::Layer* ViewElement::GetLayer() const {
+ return view_->layer();
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/view_element.h b/chromium/components/ui_devtools/views/view_element.h
index 034ae0c105d..b6a769bf817 100644
--- a/chromium/components/ui_devtools/views/view_element.h
+++ b/chromium/components/ui_devtools/views/view_element.h
@@ -6,7 +6,9 @@
#define COMPONENTS_UI_DEVTOOLS_VIEWS_VIEW_ELEMENT_H_
#include "base/macros.h"
+#include "base/scoped_observation.h"
#include "components/ui_devtools/ui_element.h"
+#include "components/ui_devtools/views/ui_element_with_metadata.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/view.h"
@@ -16,11 +18,13 @@ namespace ui_devtools {
class UIElementDelegate;
-class ViewElement : public views::ViewObserver, public UIElement {
+class ViewElement : public views::ViewObserver, public UIElementWithMetaData {
public:
ViewElement(views::View* view,
UIElementDelegate* ui_element_delegate,
UIElement* parent);
+ ViewElement(const ViewElement&) = delete;
+ ViewElement& operator=(const ViewElement&) = delete;
~ViewElement() override;
views::View* view() const { return view_; }
@@ -31,25 +35,24 @@ class ViewElement : public views::ViewObserver, public UIElement {
void OnViewBoundsChanged(views::View* view) override;
// UIElement:
- std::vector<UIElement::ClassProperties> GetCustomPropertiesForMatchedStyle()
- const override;
void GetBounds(gfx::Rect* bounds) const override;
void SetBounds(const gfx::Rect& bounds) override;
- void GetVisible(bool* visible) const override;
- void SetVisible(bool visible) override;
- bool SetPropertiesFromString(const std::string& text) override;
std::vector<std::string> GetAttributes() const override;
std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndScreenBounds()
const override;
static views::View* From(const UIElement* element);
void PaintRect() const override;
- void InitSources() override;
bool DispatchMouseEvent(protocol::DOM::MouseEvent* event) override;
+ bool DispatchKeyEvent(protocol::DOM::KeyEvent* event) override;
+
+ protected:
+ ui::metadata::ClassMetaData* GetClassMetaData() const override;
+ void* GetClassInstance() const override;
+ ui::Layer* GetLayer() const override;
private:
views::View* view_;
-
- DISALLOW_COPY_AND_ASSIGN(ViewElement);
+ base::ScopedObservation<views::View, views::ViewObserver> observer_{this};
};
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/view_element_unittest.cc b/chromium/components/ui_devtools/views/view_element_unittest.cc
index 92b614ed636..1fe39ea83c7 100644
--- a/chromium/components/ui_devtools/views/view_element_unittest.cc
+++ b/chromium/components/ui_devtools/views/view_element_unittest.cc
@@ -9,7 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/ui_devtools_unittest_utils.h"
-#include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/test/views_test_base.h"
namespace ui_devtools {
@@ -94,7 +94,7 @@ class MockNamedTestView : public views::View {
BEGIN_METADATA(MockNamedTestView, views::View)
ADD_PROPERTY_METADATA(bool, BoolProperty)
-ADD_PROPERTY_METADATA(SkColor, ColorProperty, views::metadata::SkColorConverter)
+ADD_PROPERTY_METADATA(SkColor, ColorProperty, ui::metadata::SkColorConverter)
END_METADATA
class ViewElementTest : public views::ViewsTestBase {
diff --git a/chromium/components/ui_devtools/views/widget_element.cc b/chromium/components/ui_devtools/views/widget_element.cc
index ccd786d0b63..7586ffb6dc2 100644
--- a/chromium/components/ui_devtools/views/widget_element.cc
+++ b/chromium/components/ui_devtools/views/widget_element.cc
@@ -6,13 +6,14 @@
#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/ui_element_delegate.h"
+#include "components/ui_devtools/views/devtools_event_util.h"
namespace ui_devtools {
WidgetElement::WidgetElement(views::Widget* widget,
UIElementDelegate* ui_element_delegate,
UIElement* parent)
- : UIElement(UIElementType::WIDGET, ui_element_delegate, parent),
+ : UIElementWithMetaData(UIElementType::WIDGET, ui_element_delegate, parent),
widget_(widget) {
widget_->AddRemovalsObserver(this);
widget_->AddObserver(this);
@@ -43,7 +44,10 @@ void WidgetElement::OnWidgetBoundsChanged(views::Widget* widget,
void WidgetElement::OnWidgetDestroyed(views::Widget* widget) {
DCHECK_EQ(widget, widget_);
- delegate()->OnUIElementRemoved(this);
+ if (parent())
+ parent()->RemoveChild(this);
+ else
+ delegate()->OnUIElementRemoved(this);
widget_ = nullptr;
}
@@ -85,10 +89,6 @@ 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 {
@@ -105,4 +105,22 @@ int UIElement::FindUIElementIdForBackendElement<views::Widget>(
return 0;
}
+bool WidgetElement::DispatchKeyEvent(protocol::DOM::KeyEvent* event) {
+ ui::KeyEvent key_event = ConvertToUIKeyEvent(event);
+ widget_->OnKeyEvent(&key_event);
+ return true;
+}
+
+ui::metadata::ClassMetaData* WidgetElement::GetClassMetaData() const {
+ return widget_->GetClassMetaData();
+}
+
+void* WidgetElement::GetClassInstance() const {
+ return widget_;
+}
+
+ui::Layer* WidgetElement::GetLayer() const {
+ return widget_->GetLayer();
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/widget_element.h b/chromium/components/ui_devtools/views/widget_element.h
index dc43b46d4b5..38c75ac846f 100644
--- a/chromium/components/ui_devtools/views/widget_element.h
+++ b/chromium/components/ui_devtools/views/widget_element.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "components/ui_devtools/ui_element.h"
+#include "components/ui_devtools/views/ui_element_with_metadata.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/widget/widget.h"
@@ -19,11 +20,13 @@ class UIElementDelegate;
class WidgetElement : public views::WidgetRemovalsObserver,
public views::WidgetObserver,
- public UIElement {
+ public UIElementWithMetaData {
public:
WidgetElement(views::Widget* widget,
UIElementDelegate* ui_element_delegate,
UIElement* parent);
+ WidgetElement(const WidgetElement&) = delete;
+ WidgetElement& operator=(const WidgetElement&) = delete;
~WidgetElement() override;
views::Widget* widget() const { return widget_; }
@@ -43,14 +46,17 @@ class WidgetElement : public views::WidgetRemovalsObserver,
std::vector<std::string> GetAttributes() const override;
std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndScreenBounds()
const override;
+ bool DispatchKeyEvent(protocol::DOM::KeyEvent* event) override;
static views::Widget* From(const UIElement* element);
- void InitSources() override;
+
+ protected:
+ ui::Layer* GetLayer() const override;
+ ui::metadata::ClassMetaData* GetClassMetaData() const override;
+ void* GetClassInstance() const override;
private:
views::Widget* widget_;
-
- DISALLOW_COPY_AND_ASSIGN(WidgetElement);
};
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/widget_element_unittest.cc b/chromium/components/ui_devtools/views/widget_element_unittest.cc
index 49bd355ac0d..71c2c4ee00c 100644
--- a/chromium/components/ui_devtools/views/widget_element_unittest.cc
+++ b/chromium/components/ui_devtools/views/widget_element_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "components/ui_devtools/Protocol.h"
+#include "components/ui_devtools/root_element.h"
#include "components/ui_devtools/ui_devtools_unittest_utils.h"
#include "components/ui_devtools/views/view_element.h"
#include "ui/views/test/views_test_base.h"
@@ -19,10 +20,26 @@ namespace {
const std::string kWidgetName = "A test widget";
}
+class MockWidgetElementDelegate : public MockUIElementDelegate {
+ public:
+ MockWidgetElementDelegate() = default;
+ MockWidgetElementDelegate(const MockWidgetElementDelegate&) = delete;
+ MockWidgetElementDelegate& operator=(const MockWidgetElementDelegate&) =
+ delete;
+ ~MockWidgetElementDelegate() override = default;
+
+ UIElement* root_element() { return &root_element_; }
+
+ private:
+ RootElement root_element_{this};
+};
+
class WidgetElementTest : public views::ViewsTestBase {
public:
- WidgetElementTest() {}
- ~WidgetElementTest() override {}
+ WidgetElementTest() = default;
+ WidgetElementTest(const WidgetElementTest&) = delete;
+ WidgetElementTest& operator=(const WidgetElementTest&) = delete;
+ ~WidgetElementTest() override = default;
void SetUp() override {
views::ViewsTestBase::SetUp();
@@ -33,7 +50,8 @@ class WidgetElementTest : public views::ViewsTestBase {
params.name = kWidgetName;
widget_->Init(std::move(params));
- delegate_ = std::make_unique<testing::NiceMock<MockUIElementDelegate>>();
+ delegate_ =
+ std::make_unique<testing::NiceMock<MockWidgetElementDelegate>>();
element_ =
std::make_unique<WidgetElement>(widget_, delegate_.get(), nullptr);
// The widget element will delete the ViewElement in |OnWillRemoveView|
@@ -44,22 +62,30 @@ class WidgetElementTest : public views::ViewsTestBase {
}
void TearDown() override {
- widget_->CloseNow();
+ if (widget())
+ CloseWidget();
views::ViewsTestBase::TearDown();
}
protected:
views::Widget* widget() { return widget_; }
+ void CloseWidget() {
+ widget_->CloseNow();
+ widget_ = nullptr;
+ }
WidgetElement* element() { return element_.get(); }
- MockUIElementDelegate* delegate() { return delegate_.get(); }
+ MockWidgetElementDelegate* delegate() { return delegate_.get(); }
+ void AddWidgetElementToTree() {
+ element_->set_parent(delegate_->root_element());
+ delegate_->root_element()->AddChild(element_.get());
+ }
private:
views::Widget* widget_ = nullptr;
std::unique_ptr<WidgetElement> element_;
- std::unique_ptr<MockUIElementDelegate> delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(WidgetElementTest);
+ std::unique_ptr<MockWidgetElementDelegate> delegate_;
};
+
TEST_F(WidgetElementTest, SettingsBoundsOnWidgetCallsDelegate) {
// Once for the root view, and once for the widget.
EXPECT_CALL(*delegate(), OnUIElementBoundsChanged(_))
@@ -133,4 +159,32 @@ TEST_F(WidgetElementTest, GetNodeWindowAndScreenBounds) {
EXPECT_EQ(widget()->GetWindowBoundsInScreen(), window_and_bounds.second);
}
+TEST_F(WidgetElementTest, TrackNonParentedElementLifetime) {
+ ASSERT_TRUE(widget());
+ EXPECT_FALSE(element()->parent());
+ // While closing the widget, the widget element and its children should be
+ // removed as well.
+ // Remove the root view element.
+ EXPECT_CALL(*delegate(), OnUIElementRemoved(_));
+ // Remove the widget element.
+ EXPECT_CALL(*delegate(), OnUIElementRemoved(element()));
+ CloseWidget();
+}
+
+TEST_F(WidgetElementTest, TrackParentedElementLifetime) {
+ ASSERT_TRUE(widget());
+ AddWidgetElementToTree();
+ UIElement* root = delegate()->root_element();
+ EXPECT_EQ(root, element()->parent());
+ EXPECT_EQ(1u, root->children().size());
+
+ // Remove the root view element.
+ EXPECT_CALL(*delegate(), OnUIElementRemoved(_));
+ // Remove the widget element.
+ EXPECT_CALL(*delegate(), OnUIElementRemoved(element()));
+ CloseWidget();
+ // After closing the widget, the element tree should only has the root.
+ EXPECT_EQ(0u, root->children().size());
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/window_element.cc b/chromium/components/ui_devtools/views/window_element.cc
index aacb1a3e8a7..feb07e97019 100644
--- a/chromium/components/ui_devtools/views/window_element.cc
+++ b/chromium/components/ui_devtools/views/window_element.cc
@@ -7,8 +7,14 @@
#include "base/strings/string_number_conversions.h"
#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/ui_element_delegate.h"
+#include "components/ui_devtools/views/devtools_event_util.h"
#include "components/ui_devtools/views/element_utility.h"
+#include "components/viz/common/surfaces/surface_id.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/aura/window_tree_host_platform.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/ime/text_input_client.h"
#include "ui/wm/core/window_util.h"
namespace ui_devtools {
@@ -26,7 +32,7 @@ int GetIndexOfChildInParent(aura::Window* window) {
WindowElement::WindowElement(aura::Window* window,
UIElementDelegate* ui_element_delegate,
UIElement* parent)
- : UIElement(UIElementType::WINDOW, ui_element_delegate, parent),
+ : UIElementWithMetaData(UIElementType::WINDOW, ui_element_delegate, parent),
window_(window) {
if (window)
window_->AddObserver(this);
@@ -67,44 +73,10 @@ void WindowElement::OnWindowBoundsChanged(aura::Window* window,
delegate()->OnUIElementBoundsChanged(this);
}
-std::vector<UIElement::ClassProperties>
-WindowElement::GetCustomPropertiesForMatchedStyle() const {
- std::vector<UIElement::ClassProperties> ret;
- std::vector<UIElement::UIProperty> cur_properties;
-
- ui::Layer* layer = window_->layer();
- if (layer) {
- AppendLayerPropertiesMatchedStyle(layer, &cur_properties);
- ret.emplace_back("Layer", cur_properties);
- cur_properties.clear();
- }
-
- gfx::Rect bounds;
- GetBounds(&bounds);
- cur_properties.emplace_back("x", base::NumberToString(bounds.x()));
- cur_properties.emplace_back("y", base::NumberToString(bounds.y()));
- cur_properties.emplace_back("width", base::NumberToString(bounds.width()));
- cur_properties.emplace_back("height", base::NumberToString(bounds.height()));
-
- std::string state_str =
- aura::Window::OcclusionStateToString(window_->occlusion_state());
- // change OcclusionState::UNKNOWN to UNKNOWN
- state_str = state_str.substr(state_str.find("::") + 2);
- cur_properties.emplace_back("occlusion-state", state_str);
- cur_properties.emplace_back("is-visible",
- window_->IsVisible() ? "true" : "false");
- cur_properties.emplace_back("surface",
- window_->GetSurfaceId().is_valid()
- ? window_->GetSurfaceId().ToString()
- : "none");
- cur_properties.emplace_back("capture",
- window_->HasCapture() ? "true" : "false");
- cur_properties.emplace_back(
- "is-activatable", wm::CanActivateWindow(window_) ? "true" : "false");
-
- ret.emplace_back("Window", cur_properties);
- return ret;
-}
+// TODO (kylixrd@): Still need to add support for the following property.
+//
+// cur_properties.emplace_back(
+// "is-activatable", wm::CanActivateWindow(window_) ? "true" : "false");
void WindowElement::GetBounds(gfx::Rect* bounds) const {
*bounds = window_->bounds();
@@ -165,4 +137,35 @@ void WindowElement::InitSources() {
AddSource("ui/aura/window.h", 0);
}
+bool WindowElement::DispatchKeyEvent(protocol::DOM::KeyEvent* event) {
+ ui::KeyEvent key_event = ConvertToUIKeyEvent(event);
+ // Key events are processed differently based on classes. Character events are
+ // routed to the text input client while key stroke events are propragated
+ // through the normal event flow. The IME flow is bypassed.
+ if (key_event.is_char()) {
+ ui::InputMethod* input_method = window_->GetHost()->GetInputMethod();
+ DCHECK(input_method);
+ if (input_method->GetTextInputClient()) {
+ input_method->GetTextInputClient()->InsertChar(key_event);
+ } else {
+ return false;
+ }
+ } else {
+ window_->GetHost()->DispatchKeyEventPostIME(&key_event);
+ }
+ return true;
+}
+
+ui::metadata::ClassMetaData* WindowElement::GetClassMetaData() const {
+ return window_->GetClassMetaData();
+}
+
+void* WindowElement::GetClassInstance() const {
+ return window_;
+}
+
+ui::Layer* WindowElement::GetLayer() const {
+ return window_->layer();
+}
+
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/window_element.h b/chromium/components/ui_devtools/views/window_element.h
index 40ed6c5773f..9a5674e3369 100644
--- a/chromium/components/ui_devtools/views/window_element.h
+++ b/chromium/components/ui_devtools/views/window_element.h
@@ -6,7 +6,7 @@
#define COMPONENTS_UI_DEVTOOLS_VIEWS_WINDOW_ELEMENT_H_
#include "base/macros.h"
-#include "components/ui_devtools/ui_element.h"
+#include "components/ui_devtools/views/ui_element_with_metadata.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/gfx/geometry/rect.h"
@@ -14,11 +14,14 @@
namespace ui_devtools {
-class WindowElement : public aura::WindowObserver, public UIElement {
+class WindowElement : public aura::WindowObserver,
+ public UIElementWithMetaData {
public:
WindowElement(aura::Window* window,
UIElementDelegate* ui_element_delegate,
UIElement* parent);
+ WindowElement(const WindowElement&) = delete;
+ WindowElement& operator=(const WindowElement&) = delete;
~WindowElement() override;
aura::Window* window() const { return window_; }
@@ -34,8 +37,6 @@ class WindowElement : public aura::WindowObserver, public UIElement {
ui::PropertyChangeReason reason) override;
// UIElement:
- std::vector<UIElement::ClassProperties> GetCustomPropertiesForMatchedStyle()
- const override;
void GetBounds(gfx::Rect* bounds) const override;
void SetBounds(const gfx::Rect& bounds) override;
void GetVisible(bool* visible) const override;
@@ -43,14 +44,18 @@ class WindowElement : public aura::WindowObserver, public UIElement {
std::vector<std::string> GetAttributes() const override;
std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndScreenBounds()
const override;
+ bool DispatchKeyEvent(protocol::DOM::KeyEvent* event) override;
static aura::Window* From(const UIElement* element);
void InitSources() override;
+ protected:
+ ui::metadata::ClassMetaData* GetClassMetaData() const override;
+ void* GetClassInstance() const override;
+ ui::Layer* GetLayer() const override;
+
private:
aura::Window* window_;
-
- DISALLOW_COPY_AND_ASSIGN(WindowElement);
};
} // namespace ui_devtools
diff --git a/chromium/components/ui_devtools/views/window_element_unittest.cc b/chromium/components/ui_devtools/views/window_element_unittest.cc
index 8dc11c3fd32..7dfe973322a 100644
--- a/chromium/components/ui_devtools/views/window_element_unittest.cc
+++ b/chromium/components/ui_devtools/views/window_element_unittest.cc
@@ -4,6 +4,8 @@
#include "components/ui_devtools/views/window_element.h"
+#include <memory>
+
#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/ui_devtools_unittest_utils.h"
#include "ui/aura/window.h"
@@ -21,15 +23,17 @@ class WindowElementTest : public views::ViewsTestBase {
void SetUp() override {
views::ViewsTestBase::SetUp();
- window_.reset(new aura::Window(nullptr, aura::client::WINDOW_TYPE_NORMAL));
+ window_ = std::make_unique<aura::Window>(nullptr,
+ aura::client::WINDOW_TYPE_NORMAL);
window_->Init(ui::LAYER_NOT_DRAWN);
aura::Window* root_window = GetContext();
DCHECK(root_window);
root_window->AddChild(window_.get());
- delegate_.reset(new testing::NiceMock<MockUIElementDelegate>);
+ delegate_ = std::make_unique<testing::NiceMock<MockUIElementDelegate>>();
// |OnUIElementAdded| is called on element creation.
EXPECT_CALL(*delegate_, OnUIElementAdded(_, _)).Times(1);
- element_.reset(new WindowElement(window_.get(), delegate_.get(), nullptr));
+ element_ = std::make_unique<WindowElement>(window_.get(), delegate_.get(),
+ nullptr);
}
void TearDown() override {
diff --git a/chromium/components/ui_devtools/viz/OWNERS b/chromium/components/ui_devtools/viz/OWNERS
index b0bbdaf9558..1921986a38b 100644
--- a/chromium/components/ui_devtools/viz/OWNERS
+++ b/chromium/components/ui_devtools/viz/OWNERS
@@ -1,2 +1,2 @@
kylechar@chromium.org
-sgilhuly@chromium.org
+rivr@chromium.org
diff --git a/chromium/components/ui_devtools/viz/dom_agent_viz.cc b/chromium/components/ui_devtools/viz/dom_agent_viz.cc
index 543b9ceebb3..35631be8d90 100644
--- a/chromium/components/ui_devtools/viz/dom_agent_viz.cc
+++ b/chromium/components/ui_devtools/viz/dom_agent_viz.cc
@@ -107,7 +107,7 @@ void DOMAgentViz::OnSurfaceDestroyed(const viz::SurfaceId& surface_id) {
DestroyElementAndRemoveSubtree(it->second.get());
}
-// TODO(sgilhuly): Add support for elements to have multiple parents. Currently,
+// TODO(rivr): Add support for elements to have multiple parents. Currently,
// when a reference is added to a surface, the SurfaceElement is moved to be a
// child of only its most recent referrer. When a reference is removed from a
// surface, this is ignored unless the reference is to the SurfaceElement's
@@ -151,7 +151,7 @@ void DOMAgentViz::OnRemovedSurfaceReference(const viz::SurfaceId& parent_id,
// happen when we have Surface A referencing Surface B, then we create
// Surface C and ask it to reference Surface B. When A asks to remove
// the reference to B, do nothing because B is already referenced by C.
- // TODO(sgilhuly): Add support for elements to have multiple parents so this
+ // TODO(rivr): Add support for elements to have multiple parents so this
// case can be correctly handled.
UIElement* old_parent = child->parent();
if (SurfaceElement::From(old_parent) != parent_id)
diff --git a/chromium/components/ui_devtools/viz/surface_element.cc b/chromium/components/ui_devtools/viz/surface_element.cc
index e3740494f38..c2cad3822ed 100644
--- a/chromium/components/ui_devtools/viz/surface_element.cc
+++ b/chromium/components/ui_devtools/viz/surface_element.cc
@@ -4,6 +4,7 @@
#include "components/ui_devtools/viz/surface_element.h"
+#include "base/strings/string_piece.h"
#include "components/ui_devtools/Protocol.h"
#include "components/ui_devtools/ui_element_delegate.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
@@ -53,10 +54,9 @@ void SurfaceElement::GetVisible(bool* visible) const {
void SurfaceElement::SetVisible(bool visible) {}
std::vector<std::string> SurfaceElement::GetAttributes() const {
- return {
- "SurfaceId", surface_id_.ToString(), "FrameSink Debug Label",
- frame_sink_manager_->GetFrameSinkDebugLabel(surface_id_.frame_sink_id())
- .as_string()};
+ return {"SurfaceId", surface_id_.ToString(), "FrameSink Debug Label",
+ std::string(frame_sink_manager_->GetFrameSinkDebugLabel(
+ surface_id_.frame_sink_id()))};
}
std::pair<gfx::NativeWindow, gfx::Rect>
diff --git a/chromium/components/ui_devtools/viz/viz_devtools_unittest.cc b/chromium/components/ui_devtools/viz/viz_devtools_unittest.cc
index ce8472c6414..69d07917270 100644
--- a/chromium/components/ui_devtools/viz/viz_devtools_unittest.cc
+++ b/chromium/components/ui_devtools/viz/viz_devtools_unittest.cc
@@ -417,7 +417,7 @@ TEST_F(VizDevToolsTest, SurfaceHierarchyCleanup) {
// Verify that a surface with multiple references is only a child of its most
// recent referrer.
-// TODO(sgilhuly): This test follows the current behaviour of surfaces with
+// TODO(rivr): This test follows the current behaviour of surfaces with
// multiple references, and should be changed if support for nodes to have
// multiple parents is added.
TEST_F(VizDevToolsTest, MultipleSurfaceReferences) {
diff --git a/chromium/components/ui_devtools/viz/viz_element.h b/chromium/components/ui_devtools/viz/viz_element.h
index 19e228f188a..abe4382293d 100644
--- a/chromium/components/ui_devtools/viz/viz_element.h
+++ b/chromium/components/ui_devtools/viz/viz_element.h
@@ -36,4 +36,4 @@ class VizElement : public UIElement {
} // namespace ui_devtools
-#endif // COMPONENTS_UI_DEVTOOLS_VIZ_FRAME_SINK_ELEMENT_H_
+#endif // COMPONENTS_UI_DEVTOOLS_VIZ_VIZ_ELEMENT_H_
diff --git a/chromium/components/ukm/content/source_url_recorder.cc b/chromium/components/ukm/content/source_url_recorder.cc
index 92720e93c92..a6de4e2e83c 100644
--- a/chromium/components/ukm/content/source_url_recorder.cc
+++ b/chromium/components/ukm/content/source_url_recorder.cc
@@ -316,6 +316,22 @@ void SourceUrlRecorderWebContentsObserver::MaybeRecordUrl(
navigation_data.is_same_document_navigation =
navigation_handle->IsSameDocument();
+
+ navigation_data.same_origin_status =
+ UkmSource::NavigationData::SameOriginStatus::UNSET;
+ // Only set the same origin flag for committed non-error,
+ // non-same-document navigations.
+ if (navigation_handle->HasCommitted() && !navigation_handle->IsErrorPage() &&
+ !navigation_handle->IsSameDocument()) {
+ navigation_data.same_origin_status =
+ navigation_handle->IsSameOrigin()
+ ? UkmSource::NavigationData::SameOriginStatus::SAME_ORIGIN
+ : UkmSource::NavigationData::SameOriginStatus::CROSS_ORIGIN;
+ }
+ navigation_data.is_renderer_initiated =
+ navigation_handle->IsRendererInitiated();
+ navigation_data.is_error_page = navigation_handle->IsErrorPage();
+
navigation_data.previous_source_id =
last_committed_full_navigation_source_id_;
diff --git a/chromium/components/ukm/content/source_url_recorder_browsertest.cc b/chromium/components/ukm/content/source_url_recorder_browsertest.cc
index b62e4b15769..003cd30de6c 100644
--- a/chromium/components/ukm/content/source_url_recorder_browsertest.cc
+++ b/chromium/components/ukm/content/source_url_recorder_browsertest.cc
@@ -5,6 +5,7 @@
#include <memory>
#include "base/files/scoped_temp_dir.h"
+#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
#include "components/ukm/content/source_url_recorder.h"
#include "components/ukm/test_ukm_recorder.h"
@@ -242,10 +243,8 @@ IN_PROC_BROWSER_TEST_F(SourceUrlRecorderWebContentsObserverBrowserTest,
window.domAutomationController.send(true);
}, 10);
)";
- // EvalJsWithManualReply returns an EvalJsResult, whose docs say to use
- // EXPECT_EQ(true, ...) rather than EXPECT_TRUE(), as the latter does not
- // compile.
- EXPECT_EQ(true, EvalJsWithManualReply(portal_contents, activated_poll));
+ EXPECT_EQ(true, EvalJs(portal_contents, activated_poll,
+ content::EXECUTE_SCRIPT_USE_MANUAL_REPLY));
// The activated portal contents should be the currently active contents.
EXPECT_EQ(portal_contents, shell()->web_contents());
diff --git a/chromium/components/ukm/content/source_url_recorder_test.cc b/chromium/components/ukm/content/source_url_recorder_test.cc
index 04f1a50c73f..213069fe5a5 100644
--- a/chromium/components/ukm/content/source_url_recorder_test.cc
+++ b/chromium/components/ukm/content/source_url_recorder_test.cc
@@ -96,7 +96,7 @@ TEST_F(SourceUrlRecorderWebContentsObserverTest, IgnoreUrlInSubframe) {
const auto& sources = test_ukm_recorder_.GetSources();
// Expect two sources created, one for navigation and one for document, both
- // should have the URL of the main frame .
+ // should have the URL of the main frame.
EXPECT_EQ(2ul, sources.size());
for (const auto& kv : sources) {
EXPECT_EQ(main_frame_url, kv.second->url());
@@ -223,3 +223,93 @@ TEST_F(SourceUrlRecorderWebContentsObserverTest,
EXPECT_EQ(url, GetAssociatedURLForWebContentsDocument());
}
+
+TEST_F(SourceUrlRecorderWebContentsObserverTest, NavigationMetadata) {
+ GURL url1("https://www.example.com/1");
+ GURL same_origin_url1("https://www.example.com/same_origin");
+ GURL url2("https://test.example.com/2");
+ GURL cross_origin_url2("https://test1.example.com/cross_origin");
+ GURL error_url("chrome://error");
+ NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(), url1);
+ NavigationSimulator::CreateRendererInitiated(same_origin_url1, main_rfh())
+ ->Commit();
+ NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(), url2);
+ NavigationSimulator::CreateRendererInitiated(cross_origin_url2, main_rfh())
+ ->Commit();
+ NavigationSimulator::NavigateAndFailFromBrowser(web_contents(), error_url,
+ net::ERR_FAILED);
+
+ EXPECT_EQ(error_url, web_contents()->GetLastCommittedURL());
+
+ // Serialize each source so we can verify expectations below.
+ ukm::Source full_nav_source1;
+ ukm::Source full_nav_source2;
+ ukm::Source same_origin_source1;
+ ukm::Source cross_origin_source2;
+ ukm::Source error_page_source;
+
+ for (auto& kv : test_ukm_recorder_.GetSources()) {
+ // Populate protos from the navigation sources.
+ if (ukm::GetSourceIdType(kv.first) != ukm::SourceIdObj::Type::NAVIGATION_ID)
+ continue;
+
+ if (kv.second->url() == url1) {
+ kv.second->PopulateProto(&full_nav_source1);
+ } else if (kv.second->url() == url2) {
+ kv.second->PopulateProto(&full_nav_source2);
+ } else if (kv.second->url() == same_origin_url1) {
+ kv.second->PopulateProto(&same_origin_source1);
+ } else if (kv.second->url() == cross_origin_url2) {
+ kv.second->PopulateProto(&cross_origin_source2);
+ } else if (kv.second->url() == error_url) {
+ kv.second->PopulateProto(&error_page_source);
+ } else {
+ FAIL() << "Encountered unexpected source.";
+ }
+ }
+
+ // The first navigation was a browser initiated navigation to url1.
+ EXPECT_EQ(url1, full_nav_source1.urls(0).url());
+ EXPECT_TRUE(full_nav_source1.has_id());
+ EXPECT_FALSE(full_nav_source1.navigation_metadata().is_renderer_initiated());
+ EXPECT_EQ(full_nav_source1.navigation_metadata().same_origin_status(),
+ ukm::Source::CROSS_ORIGIN);
+ EXPECT_FALSE(full_nav_source1.navigation_metadata().is_error_page());
+
+ // The second navigation was a same-origin renderer-initiated navigation to
+ // same_origin_url1.
+ EXPECT_EQ(same_origin_url1, same_origin_source1.urls(0).url());
+ EXPECT_TRUE(same_origin_source1.has_id());
+ EXPECT_TRUE(
+ same_origin_source1.navigation_metadata().is_renderer_initiated());
+ EXPECT_EQ(same_origin_source1.navigation_metadata().same_origin_status(),
+ ukm::Source::SAME_ORIGIN);
+ EXPECT_FALSE(same_origin_source1.navigation_metadata().is_error_page());
+
+ // The third navigation was a browser initiated navigation to url2.
+ EXPECT_EQ(url2, full_nav_source2.urls(0).url());
+ EXPECT_TRUE(full_nav_source2.has_id());
+ EXPECT_FALSE(full_nav_source2.navigation_metadata().is_renderer_initiated());
+ EXPECT_EQ(full_nav_source2.navigation_metadata().same_origin_status(),
+ ukm::Source::CROSS_ORIGIN);
+ EXPECT_FALSE(full_nav_source2.navigation_metadata().is_error_page());
+
+ // The fourth navigation was a cross-origin renderer-initiated navigation to
+ // url2.
+ EXPECT_EQ(cross_origin_url2, cross_origin_source2.urls(0).url());
+ EXPECT_TRUE(cross_origin_source2.has_id());
+ EXPECT_TRUE(
+ cross_origin_source2.navigation_metadata().is_renderer_initiated());
+ EXPECT_EQ(cross_origin_source2.navigation_metadata().same_origin_status(),
+ ukm::Source::CROSS_ORIGIN);
+ EXPECT_FALSE(cross_origin_source2.navigation_metadata().is_error_page());
+
+ // The fifth navigation was an error page. Make sure it's is_error_page flag
+ // is set.
+ EXPECT_EQ(error_url, error_page_source.urls(0).url());
+ EXPECT_TRUE(error_page_source.has_id());
+ EXPECT_FALSE(error_page_source.navigation_metadata().is_renderer_initiated());
+ EXPECT_EQ(error_page_source.navigation_metadata().same_origin_status(),
+ ukm::Source::UNSET);
+ EXPECT_TRUE(error_page_source.navigation_metadata().is_error_page());
+}
diff --git a/chromium/components/ukm/debug/ukm_debug_data_extractor.h b/chromium/components/ukm/debug/ukm_debug_data_extractor.h
index 9d06209e34e..b94218a3c30 100644
--- a/chromium/components/ukm/debug/ukm_debug_data_extractor.h
+++ b/chromium/components/ukm/debug/ukm_debug_data_extractor.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_UKM_DEBUG_UKM_DEBUG_DATA_EXTRACTOR_H_
#define COMPONENTS_UKM_DEBUG_UKM_DEBUG_DATA_EXTRACTOR_H_
-#include <string>
-
#include "base/macros.h"
#include "base/values.h"
#include "components/ukm/ukm_service.h"
diff --git a/chromium/components/ukm/debug/ukm_internals.html b/chromium/components/ukm/debug/ukm_internals.html
index a4c5aab3e95..9b202d707db 100644
--- a/chromium/components/ukm/debug/ukm_internals.html
+++ b/chromium/components/ukm/debug/ukm_internals.html
@@ -12,6 +12,7 @@
<div> Session: <span id="sessionid"/></div>
<div> Client_id: <span id="clientid"/></div>
<div> Event Sampling Enabled: <span id="is_sampling_enabled"/></div>
+ <div> NOTE FOR MOBILE: This only shows events since the most recent foregrounding.</div>
</div>
</div>
<div>
diff --git a/chromium/components/ukm/ios/ukm_url_recorder_unittest.mm b/chromium/components/ukm/ios/ukm_url_recorder_unittest.mm
index 2d0d434f03c..58d1039b83d 100644
--- a/chromium/components/ukm/ios/ukm_url_recorder_unittest.mm
+++ b/chromium/components/ukm/ios/ukm_url_recorder_unittest.mm
@@ -5,7 +5,6 @@
#include "components/ukm/ios/ukm_url_recorder.h"
#include "base/bind.h"
-#include "base/optional.h"
#import "base/test/ios/wait_util.h"
#include "components/ukm/test_ukm_recorder.h"
#import "ios/web/public/navigation/navigation_manager.h"
@@ -15,6 +14,7 @@
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "services/metrics/public/cpp/ukm_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -79,14 +79,14 @@ class UkmUrlRecorderTest : public web::WebTestWithWebState {
testing::AssertionResult RecordedUrl(
ukm::SourceId source_id,
GURL expected_url,
- base::Optional<GURL> expected_initial_url) {
+ absl::optional<GURL> expected_initial_url) {
auto* source = test_ukm_recorder_.GetSourceForSourceId(source_id);
if (!source)
return testing::AssertionFailure() << "No URL recorded";
if (source->url() != expected_url)
return testing::AssertionFailure()
<< "Url was " << source->url() << ", expected: " << expected_url;
- base::Optional<GURL> initial_url;
+ absl::optional<GURL> initial_url;
if (source->urls().size() > 1u)
initial_url = source->urls().front();
if (expected_initial_url != initial_url) {
@@ -121,7 +121,7 @@ TEST_F(UkmUrlRecorderTest, Basic) {
GURL url = server_.GetURL("/title1.html");
EXPECT_TRUE(LoadUrlAndWait(url));
ukm::SourceId source_id = ukm::GetSourceIdForWebStateDocument(web_state());
- EXPECT_TRUE(RecordedUrl(source_id, url, base::nullopt));
+ EXPECT_TRUE(RecordedUrl(source_id, url, absl::nullopt));
}
// Tests that subframe URLs do not get recorded.
@@ -130,7 +130,7 @@ TEST_F(UkmUrlRecorderTest, IgnoreUrlInSubframe) {
GURL subframe_url = server_.GetURL("/title1.html");
EXPECT_TRUE(LoadUrlAndWait(main_url));
ukm::SourceId source_id = ukm::GetSourceIdForWebStateDocument(web_state());
- EXPECT_TRUE(RecordedUrl(source_id, main_url, base::nullopt));
+ EXPECT_TRUE(RecordedUrl(source_id, main_url, absl::nullopt));
EXPECT_TRUE(DidNotRecordUrl(subframe_url));
}
diff --git a/chromium/components/ukm/observers/history_delete_observer.h b/chromium/components/ukm/observers/history_delete_observer.h
index 7a96bc380db..894b7276610 100644
--- a/chromium/components/ukm/observers/history_delete_observer.h
+++ b/chromium/components/ukm/observers/history_delete_observer.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_UKM_OBSERVERS_HISTORY_DELETE_OBSERVER_H_
#define COMPONENTS_UKM_OBSERVERS_HISTORY_DELETE_OBSERVER_H_
-#include <set>
-
#include "base/scoped_multi_source_observation.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/history_service_observer.h"
diff --git a/chromium/components/ukm/observers/ukm_consent_state_observer_unittest.cc b/chromium/components/ukm/observers/ukm_consent_state_observer_unittest.cc
index 9f7ee2a8632..4ba2ece8b85 100644
--- a/chromium/components/ukm/observers/ukm_consent_state_observer_unittest.cc
+++ b/chromium/components/ukm/observers/ukm_consent_state_observer_unittest.cc
@@ -28,7 +28,7 @@ class MockSyncService : public syncer::TestSyncService {
void SetStatus(bool has_passphrase, bool history_enabled, bool active) {
SetTransportState(active ? TransportState::ACTIVE
: TransportState::INITIALIZING);
- SetIsUsingSecondaryPassphrase(has_passphrase);
+ SetIsUsingExplicitPassphrase(has_passphrase);
SetPreferredDataTypes(
history_enabled
? syncer::ModelTypeSet(syncer::HISTORY_DELETE_DIRECTIVES)
diff --git a/chromium/components/ukm/ukm_rotation_scheduler.h b/chromium/components/ukm/ukm_rotation_scheduler.h
index 2e0f99e23af..d0482651d3a 100644
--- a/chromium/components/ukm/ukm_rotation_scheduler.h
+++ b/chromium/components/ukm/ukm_rotation_scheduler.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_UKM_METRICS_REPORTING_SCHEDULER_H_
-#define COMPONENTS_UKM_METRICS_REPORTING_SCHEDULER_H_
+#ifndef COMPONENTS_UKM_UKM_ROTATION_SCHEDULER_H_
+#define COMPONENTS_UKM_UKM_ROTATION_SCHEDULER_H_
#include "base/time/time.h"
#include "components/metrics/metrics_rotation_scheduler.h"
@@ -31,4 +31,4 @@ class UkmRotationScheduler : public metrics::MetricsRotationScheduler {
} // namespace ukm
-#endif // COMPONENTS_UKM_METRICS_REPORTING_SCHEDULER_H_
+#endif // COMPONENTS_UKM_UKM_ROTATION_SCHEDULER_H_
diff --git a/chromium/components/ukm/ukm_service.cc b/chromium/components/ukm/ukm_service.cc
index 0bd80a9fbf5..515d0db9d51 100644
--- a/chromium/components/ukm/ukm_service.cc
+++ b/chromium/components/ukm/ukm_service.cc
@@ -160,7 +160,7 @@ void PurgeExtensionDataFromUnsentLogStore(
// Replace the compressed log in the store by its filtered version.
const std::string old_compressed_log_data =
ukm_log_store->ReplaceLogAtIndex(index, reserialized_log_data,
- base::nullopt);
+ absl::nullopt);
// Reached here only if extensions were found in the log, so data should now
// be different after filtering.
@@ -430,7 +430,7 @@ void UkmService::BuildAndStoreLog() {
std::string serialized_log =
UkmService::SerializeReportProtoToString(&report);
- reporting_service_.ukm_log_store()->StoreLog(serialized_log, base::nullopt);
+ reporting_service_.ukm_log_store()->StoreLog(serialized_log, absl::nullopt);
}
bool UkmService::ShouldRestrictToWhitelistedEntries() const {
diff --git a/chromium/components/ukm/ukm_service_unittest.cc b/chromium/components/ukm/ukm_service_unittest.cc
index 0e3feedb655..d60e2bc762e 100644
--- a/chromium/components/ukm/ukm_service_unittest.cc
+++ b/chromium/components/ukm/ukm_service_unittest.cc
@@ -306,7 +306,7 @@ TEST_F(UkmServiceTest, PurgeExtensionDataFromUnsentLogStore) {
report.SerializeToString(&serialized_log);
// Makes sure that the serialized ukm report can be parsed.
ASSERT_TRUE(UkmService::LogCanBeParsed(serialized_log));
- unsent_log_store->StoreLog(serialized_log, base::nullopt);
+ unsent_log_store->StoreLog(serialized_log, absl::nullopt);
// Do extension purging.
service.PurgeExtensions();
diff --git a/chromium/components/unified_consent/unified_consent_service.cc b/chromium/components/unified_consent/unified_consent_service.cc
index 1d54d113904..5251ac16d5e 100644
--- a/chromium/components/unified_consent/unified_consent_service.cc
+++ b/chromium/components/unified_consent/unified_consent_service.cc
@@ -175,7 +175,7 @@ void UnifiedConsentService::UpdateSettingsForMigration() {
sync_service_->IsSyncFeatureEnabled() &&
sync_service_->GetUserSettings()->GetSelectedTypes().Has(
syncer::UserSelectableType::kHistory) &&
- !sync_service_->GetUserSettings()->IsUsingSecondaryPassphrase();
+ !sync_service_->GetUserSettings()->IsUsingExplicitPassphrase();
SetUrlKeyedAnonymizedDataCollectionEnabled(url_keyed_metrics_enabled);
}
diff --git a/chromium/components/update_client/background_downloader_win.h b/chromium/components/update_client/background_downloader_win.h
index db3aa3e9d99..1abccbf1705 100644
--- a/chromium/components/update_client/background_downloader_win.h
+++ b/chromium/components/update_client/background_downloader_win.h
@@ -10,7 +10,6 @@
#include <wrl/client.h>
#include <memory>
-#include <string>
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
diff --git a/chromium/components/update_client/component.cc b/chromium/components/update_client/component.cc
index 5973357da2a..4d7f92ef8d5 100644
--- a/chromium/components/update_client/component.cc
+++ b/chromium/components/update_client/component.cc
@@ -341,7 +341,7 @@ void Component::SetParseResult(const ProtocolParser::Result& result) {
hashdiff_sha256_ = package.hashdiff_sha256;
if (!result.manifest.run.empty()) {
- install_params_ = base::make_optional(CrxInstaller::InstallParams(
+ install_params_ = absl::make_optional(CrxInstaller::InstallParams(
result.manifest.run, result.manifest.arguments));
}
}
@@ -375,7 +375,7 @@ void Component::Registration(const base::Version& version) {
}
void Component::SetUpdateCheckResult(
- const base::Optional<ProtocolParser::Result>& result,
+ const absl::optional<ProtocolParser::Result>& result,
ErrorCategory error_category,
int error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chromium/components/update_client/component.h b/chromium/components/update_client/component.h
index 46b38607d87..20dce03867d 100644
--- a/chromium/components/update_client/component.h
+++ b/chromium/components/update_client/component.h
@@ -15,13 +15,13 @@
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/version.h"
#include "components/update_client/crx_downloader.h"
#include "components/update_client/protocol_parser.h"
#include "components/update_client/update_client.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace base {
@@ -62,7 +62,7 @@ class Component {
// Called by the UpdateEngine when an update check for this component is done.
void SetUpdateCheckResult(
- const base::Optional<ProtocolParser::Result>& result,
+ const absl::optional<ProtocolParser::Result>& result,
ErrorCategory error_category,
int error);
@@ -84,7 +84,7 @@ class Component {
std::string id() const { return id_; }
- const base::Optional<CrxComponent>& crx_component() const {
+ const absl::optional<CrxComponent>& crx_component() const {
return crx_component_;
}
void set_crx_component(const CrxComponent& crx_component) {
@@ -411,7 +411,7 @@ class Component {
SEQUENCE_CHECKER(sequence_checker_);
const std::string id_;
- base::Optional<CrxComponent> crx_component_;
+ absl::optional<CrxComponent> crx_component_;
// The status of the updatecheck response.
std::string status_;
@@ -478,7 +478,7 @@ class Component {
// Contains the optional |run| and |arguments| values in the update response
// manifest. This data is provided as an argument to the |Install| call.
- base::Optional<CrxInstaller::InstallParams> install_params_;
+ absl::optional<CrxInstaller::InstallParams> install_params_;
// Contains the events which are therefore serialized in the requests.
std::vector<base::Value> events_;
diff --git a/chromium/components/update_client/component_patcher.cc b/chromium/components/update_client/component_patcher.cc
index 8e55a56e1c8..e0dfc94eda1 100644
--- a/chromium/components/update_client/component_patcher.cc
+++ b/chromium/components/update_client/component_patcher.cc
@@ -67,13 +67,13 @@ void ComponentPatcher::StartPatching() {
if (!commands_) {
DonePatching(UnpackerError::kDeltaBadCommands, 0);
} else {
- next_command_ = commands_->begin();
+ next_command_ = commands_->GetList().begin();
PatchNextFile();
}
}
void ComponentPatcher::PatchNextFile() {
- if (next_command_ == commands_->end()) {
+ if (next_command_ == commands_->GetList().end()) {
DonePatching(UnpackerError::kNone, 0);
return;
}
diff --git a/chromium/components/update_client/component_patcher_unittest.h b/chromium/components/update_client/component_patcher_unittest.h
index cb50e87d80d..119efbae622 100644
--- a/chromium/components/update_client/component_patcher_unittest.h
+++ b/chromium/components/update_client/component_patcher_unittest.h
@@ -5,9 +5,6 @@
#ifndef COMPONENTS_UPDATE_CLIENT_COMPONENT_PATCHER_UNITTEST_H_
#define COMPONENTS_UPDATE_CLIENT_COMPONENT_PATCHER_UNITTEST_H_
-#include <memory>
-
-#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
diff --git a/chromium/components/update_client/component_unpacker.cc b/chromium/components/update_client/component_unpacker.cc
index 62c28f143f4..d0119ea37fc 100644
--- a/chromium/components/update_client/component_unpacker.cc
+++ b/chromium/components/update_client/component_unpacker.cc
@@ -18,7 +18,6 @@
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/crx_file/crx_verifier.h"
#include "components/update_client/component_patcher.h"
diff --git a/chromium/components/update_client/crx_update_item.h b/chromium/components/update_client/crx_update_item.h
index 80b2b2fe520..8662275b16b 100644
--- a/chromium/components/update_client/crx_update_item.h
+++ b/chromium/components/update_client/crx_update_item.h
@@ -11,12 +11,12 @@
#include <vector>
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/version.h"
#include "components/update_client/crx_downloader.h"
#include "components/update_client/update_client.h"
#include "components/update_client/update_client_errors.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace update_client {
@@ -33,7 +33,7 @@ struct CrxUpdateItem {
// caller by responding to the |CrxDataCallback|. If the caller can't
// provide this value, for instance, in cases where the CRX was uninstalled,
// then the |component| member will not be present.
- base::Optional<CrxComponent> component;
+ absl::optional<CrxComponent> component;
// Time when an update check for this CRX has happened.
base::TimeTicks last_check;
diff --git a/chromium/components/update_client/patch/patch_impl.h b/chromium/components/update_client/patch/patch_impl.h
index e76666d4917..b539b82ecdf 100644
--- a/chromium/components/update_client/patch/patch_impl.h
+++ b/chromium/components/update_client/patch/patch_impl.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_UPDATE_CLIENT_PATCH_PATCH_IMPL_H_
#define COMPONENTS_UPDATE_CLIENT_PATCH_PATCH_IMPL_H_
-#include <memory>
-
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/components/update_client/protocol_definition.h b/chromium/components/update_client/protocol_definition.h
index f82015d8479..d913bf17b4f 100644
--- a/chromium/components/update_client/protocol_definition.h
+++ b/chromium/components/update_client/protocol_definition.h
@@ -12,9 +12,9 @@
#include "base/containers/flat_map.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace update_client {
@@ -56,8 +56,8 @@ struct Updater {
std::string version;
bool is_machine = false;
bool autoupdate_check_enabled = false;
- base::Optional<int> last_started;
- base::Optional<int> last_checked;
+ absl::optional<int> last_started;
+ absl::optional<int> last_checked;
int update_policy = 0;
};
@@ -75,11 +75,11 @@ struct Ping {
~Ping();
// Preferred user count metrics ("ad" and "rd").
- base::Optional<int> date_last_active;
- base::Optional<int> date_last_roll_call;
+ absl::optional<int> date_last_active;
+ absl::optional<int> date_last_roll_call;
// Legacy user count metrics ("a" and "r").
- base::Optional<int> days_since_last_active_ping;
+ absl::optional<int> days_since_last_active_ping;
int days_since_last_roll_call = 0;
std::string ping_freshness;
@@ -105,17 +105,17 @@ struct App {
std::string release_channel;
- base::Optional<bool> enabled;
- base::Optional<std::vector<int>> disabled_reasons;
+ absl::optional<bool> enabled;
+ absl::optional<std::vector<int>> disabled_reasons;
// Optional update check.
- base::Optional<UpdateCheck> update_check;
+ absl::optional<UpdateCheck> update_check;
// Optional 'did run' ping.
- base::Optional<Ping> ping;
+ absl::optional<Ping> ping;
// Progress/result pings.
- base::Optional<std::vector<base::Value>> events;
+ absl::optional<std::vector<base::Value>> events;
private:
DISALLOW_COPY_AND_ASSIGN(App);
@@ -156,7 +156,7 @@ struct Request {
std::string dlpref;
// True if this machine is part of a managed enterprise domain.
- base::Optional<bool> domain_joined;
+ absl::optional<bool> domain_joined;
base::flat_map<std::string, std::string> additional_attributes;
@@ -164,7 +164,7 @@ struct Request {
OS os;
- base::Optional<Updater> updater;
+ absl::optional<Updater> updater;
std::vector<App> apps;
diff --git a/chromium/components/update_client/protocol_serializer.cc b/chromium/components/update_client/protocol_serializer.cc
index f88de4edf4c..d649a1484ee 100644
--- a/chromium/components/update_client/protocol_serializer.cc
+++ b/chromium/components/update_client/protocol_serializer.cc
@@ -130,7 +130,7 @@ protocol_request::Request MakeProtocolRequest(
request.os.arch = base::SysInfo().OperatingSystemArchitecture();
if (updater_state_attributes) {
- request.updater = base::make_optional<protocol_request::Updater>();
+ request.updater = absl::make_optional<protocol_request::Updater>();
auto it = updater_state_attributes->find("name");
if (it != updater_state_attributes->end())
request.updater->name = it->second;
@@ -174,7 +174,7 @@ protocol_request::Request MakeProtocolRequest(
protocol_request::App MakeProtocolApp(
const std::string& app_id,
const base::Version& version,
- base::Optional<std::vector<base::Value>> events) {
+ absl::optional<std::vector<base::Value>> events) {
protocol_request::App app;
app.app_id = app_id;
app.version = version.GetString();
@@ -195,9 +195,9 @@ protocol_request::App MakeProtocolApp(
const std::string& cohort_name,
const std::string& release_channel,
const std::vector<int>& disabled_reasons,
- base::Optional<protocol_request::UpdateCheck> update_check,
- base::Optional<protocol_request::Ping> ping) {
- auto app = MakeProtocolApp(app_id, version, base::nullopt);
+ absl::optional<protocol_request::UpdateCheck> update_check,
+ absl::optional<protocol_request::Ping> ping) {
+ auto app = MakeProtocolApp(app_id, version, absl::nullopt);
app.brand_code = brand_code;
app.install_source = install_source;
app.install_location = install_location;
diff --git a/chromium/components/update_client/protocol_serializer.h b/chromium/components/update_client/protocol_serializer.h
index 00fcc944cae..5c495638acb 100644
--- a/chromium/components/update_client/protocol_serializer.h
+++ b/chromium/components/update_client/protocol_serializer.h
@@ -47,7 +47,7 @@ protocol_request::Request MakeProtocolRequest(
protocol_request::App MakeProtocolApp(
const std::string& app_id,
const base::Version& version,
- base::Optional<std::vector<base::Value>> events);
+ absl::optional<std::vector<base::Value>> events);
protocol_request::App MakeProtocolApp(
const std::string& app_id,
@@ -62,8 +62,8 @@ protocol_request::App MakeProtocolApp(
const std::string& cohort_name,
const std::string& release_channel,
const std::vector<int>& disabled_reasons,
- base::Optional<protocol_request::UpdateCheck> update_check,
- base::Optional<protocol_request::Ping> ping);
+ absl::optional<protocol_request::UpdateCheck> update_check,
+ absl::optional<protocol_request::Ping> ping);
protocol_request::UpdateCheck MakeProtocolUpdateCheck(bool is_update_disabled);
diff --git a/chromium/components/update_client/protocol_serializer_json_unittest.cc b/chromium/components/update_client/protocol_serializer_json_unittest.cc
index fa8dab41e57..9d446700f1b 100644
--- a/chromium/components/update_client/protocol_serializer_json_unittest.cc
+++ b/chromium/components/update_client/protocol_serializer_json_unittest.cc
@@ -9,7 +9,6 @@
#include <utility>
#include <vector>
-#include "base/optional.h"
#include "base/test/task_environment.h"
#include "base/values.h"
#include "base/version.h"
@@ -21,6 +20,7 @@
#include "components/update_client/test_activity_data_service.h"
#include "components/update_client/updater_state.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/re2/src/re2/re2.h"
using base::Value;
diff --git a/chromium/components/update_client/request_sender.cc b/chromium/components/update_client/request_sender.cc
index 3fc7cf7aea2..8a23e72f621 100644
--- a/chromium/components/update_client/request_sender.cc
+++ b/chromium/components/update_client/request_sender.cc
@@ -25,10 +25,10 @@ namespace update_client {
namespace {
// This is an ECDSA prime256v1 named-curve key.
-constexpr int kKeyVersion = 10;
+constexpr int kKeyVersion = 11;
constexpr char kKeyPubBytesBase64[] =
- "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzOqC8cKNUYIi0UkNu0smZKDW8w5/"
- "0EmEw1KQ6Aj/5JWBMdUVm13EIVwFwPlkO/U6vXa+iu4wyUB89GFaldJ7Bg==";
+ "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgH30WRJf4g6I2C1FKsBQF3qHANLw"
+ "thwYsNt2PWTDQBS0ufSRE83piOPoJQcePzTkMfbghjnZerDjLJhBsDkfFg==";
// The content type for all protocol requests.
constexpr char kContentType[] = "application/json";
diff --git a/chromium/components/update_client/test_installer.cc b/chromium/components/update_client/test_installer.cc
index 0ea3a62a202..4a2db7bccb7 100644
--- a/chromium/components/update_client/test_installer.cc
+++ b/chromium/components/update_client/test_installer.cc
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
+#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
@@ -96,11 +97,12 @@ void VersionedTestInstaller::Install(
std::unique_ptr<InstallParams> /*install_params*/,
ProgressCallback progress_callback,
Callback callback) {
- const auto manifest = update_client::ReadManifest(unpack_path);
- std::string version_string;
- manifest->GetStringASCII("version", &version_string);
- const base::Version version(version_string);
+ const base::Value manifest = update_client::ReadManifest(unpack_path);
+ const std::string* version_string = manifest.FindStringKey("version");
+ if (!version_string || !base::IsStringASCII(*version_string))
+ return;
+ const base::Version version(*version_string);
const base::FilePath path =
install_directory_.AppendASCII(version.GetString());
base::CreateDirectory(path.DirName());
diff --git a/chromium/components/update_client/update_checker.cc b/chromium/components/update_client/update_checker.cc
index 177793bebb3..ae5fa562689 100644
--- a/chromium/components/update_client/update_checker.cc
+++ b/chromium/components/update_client/update_checker.cc
@@ -18,7 +18,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_checker.h"
@@ -283,7 +282,7 @@ void UpdateCheckerImpl::UpdateCheckSucceeded(
base::OnceClosure reply =
base::BindOnce(std::move(update_check_callback_),
- base::make_optional<ProtocolParser::Results>(results),
+ absl::make_optional<ProtocolParser::Results>(results),
ErrorCategory::kNone, 0, retry_after_sec);
if (daynum != ProtocolParser::kNoDaystart) {
@@ -302,7 +301,7 @@ void UpdateCheckerImpl::UpdateCheckFailed(ErrorCategory error_category,
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(std::move(update_check_callback_), base::nullopt,
+ base::BindOnce(std::move(update_check_callback_), absl::nullopt,
error_category, error, retry_after_sec));
}
diff --git a/chromium/components/update_client/update_checker.h b/chromium/components/update_client/update_checker.h
index d5126e193d5..fe0151310c2 100644
--- a/chromium/components/update_client/update_checker.h
+++ b/chromium/components/update_client/update_checker.h
@@ -13,9 +13,9 @@
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "components/update_client/component.h"
#include "components/update_client/protocol_parser.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace update_client {
@@ -26,7 +26,7 @@ class PersistedData;
class UpdateChecker {
public:
using UpdateCheckCallback = base::OnceCallback<void(
- const base::Optional<ProtocolParser::Results>& results,
+ const absl::optional<ProtocolParser::Results>& results,
ErrorCategory error_category,
int error,
int retry_after_sec)>;
diff --git a/chromium/components/update_client/update_checker_unittest.cc b/chromium/components/update_client/update_checker_unittest.cc
index 91a78b1d129..515257465ec 100644
--- a/chromium/components/update_client/update_checker_unittest.cc
+++ b/chromium/components/update_client/update_checker_unittest.cc
@@ -15,11 +15,9 @@
#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
@@ -37,6 +35,7 @@
#include "components/update_client/update_engine.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
using std::string;
@@ -69,7 +68,7 @@ class UpdateCheckerTest : public testing::TestWithParam<bool> {
void TearDown() override;
void UpdateCheckComplete(
- const base::Optional<ProtocolParser::Results>& results,
+ const absl::optional<ProtocolParser::Results>& results,
ErrorCategory error_category,
int error,
int retry_after_sec);
@@ -89,7 +88,7 @@ class UpdateCheckerTest : public testing::TestWithParam<bool> {
std::unique_ptr<URLLoaderPostInterceptor> post_interceptor_;
- base::Optional<ProtocolParser::Results> results_;
+ absl::optional<ProtocolParser::Results> results_;
ErrorCategory error_category_ = ErrorCategory::kNone;
int error_ = 0;
int retry_after_sec_ = 0;
@@ -162,7 +161,7 @@ void UpdateCheckerTest::Quit() {
}
void UpdateCheckerTest::UpdateCheckComplete(
- const base::Optional<ProtocolParser::Results>& results,
+ const absl::optional<ProtocolParser::Results>& results,
ErrorCategory error_category,
int error,
int retry_after_sec) {
diff --git a/chromium/components/update_client/update_client.h b/chromium/components/update_client/update_client.h
index 89868629d12..4085b34f81b 100644
--- a/chromium/components/update_client/update_client.h
+++ b/chromium/components/update_client/update_client.h
@@ -14,9 +14,9 @@
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/version.h"
#include "components/update_client/update_client_errors.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
// The UpdateClient class is a facade with a simple interface. The interface
// exposes a few APIs to install a CRX or update a group of CRXs.
@@ -346,7 +346,7 @@ class UpdateClient : public base::RefCountedThreadSafe<UpdateClient> {
// skip the component, and instead, they must insert a `nullopt` value in
// the output vector.
using CrxDataCallback =
- base::OnceCallback<std::vector<base::Optional<CrxComponent>>(
+ base::OnceCallback<std::vector<absl::optional<CrxComponent>>(
const std::vector<std::string>& ids)>;
// Called when state changes occur during an Install or Update call.
diff --git a/chromium/components/update_client/update_client_unittest.cc b/chromium/components/update_client/update_client_unittest.cc
index 5907ba967e8..7a4cc1621fc 100644
--- a/chromium/components/update_client/update_client_unittest.cc
+++ b/chromium/components/update_client/update_client_unittest.cc
@@ -12,7 +12,6 @@
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
@@ -43,6 +42,7 @@
#include "components/update_client/update_client_internal.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace update_client {
@@ -270,7 +270,7 @@ base::FilePath UpdateClientTest::TestFilePath(const char* file) {
TEST_F(UpdateClientTest, OneCrxNoUpdate) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx;
crx.name = "test_jebg";
@@ -278,7 +278,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdate) {
crx.version = base::Version("0.9");
crx.installer = base::MakeRefCounted<TestInstaller>();
crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
- std::vector<base::Optional<CrxComponent>> component = {crx};
+ std::vector<absl::optional<CrxComponent>> component = {crx};
return component;
}
};
@@ -394,7 +394,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdate) {
TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx1;
crx1.name = "test_jebg";
@@ -650,7 +650,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) {
TEST_F(UpdateClientTest, TwoCrxUpdateFirstServerIgnoresSecond) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx1;
crx1.name = "test_jebg";
@@ -888,7 +888,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateFirstServerIgnoresSecond) {
TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentData) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx;
crx.name = "test_jebg";
@@ -896,7 +896,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentData) {
crx.version = base::Version("0.9");
crx.installer = base::MakeRefCounted<TestInstaller>();
crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
- return {crx, base::nullopt};
+ return {crx, absl::nullopt};
}
};
@@ -1103,9 +1103,9 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentData) {
TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentDataAtAll) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
- return {base::nullopt, base::nullopt};
+ return {absl::nullopt, absl::nullopt};
}
};
@@ -1204,7 +1204,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateNoCrxComponentDataAtAll) {
TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx1;
crx1.name = "test_jebg";
@@ -1500,7 +1500,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateDownloadTimeout) {
TEST_F(UpdateClientTest, OneCrxDiffUpdate) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
static int num_calls = 0;
@@ -1915,7 +1915,7 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
scoped_refptr<MockInstaller> installer =
base::MakeRefCounted<MockInstaller>();
@@ -2119,7 +2119,7 @@ TEST_F(UpdateClientTest, OneCrxInstallError) {
TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
static int num_calls = 0;
@@ -2475,7 +2475,7 @@ TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) {
TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx;
crx.name = "test_jebg";
@@ -2625,7 +2625,7 @@ TEST_F(UpdateClientTest, OneCrxNoUpdateQueuedCall) {
TEST_F(UpdateClientTest, OneCrxInstall) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx;
crx.name = "test_jebg";
@@ -2864,9 +2864,9 @@ TEST_F(UpdateClientTest, OneCrxInstall) {
TEST_F(UpdateClientTest, OneCrxInstallNoCrxComponentData) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
- return {base::nullopt};
+ return {absl::nullopt};
}
};
@@ -2970,7 +2970,7 @@ TEST_F(UpdateClientTest, OneCrxInstallNoCrxComponentData) {
TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx;
crx.name = "test_jebg";
@@ -3113,7 +3113,7 @@ TEST_F(UpdateClientTest, ConcurrentInstallSameCRX) {
TEST_F(UpdateClientTest, EmptyIdList) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
return {};
}
@@ -3316,7 +3316,7 @@ TEST_F(UpdateClientTest, SendRegistrationPing) {
TEST_F(UpdateClientTest, RetryAfter) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx;
crx.name = "test_jebg";
@@ -3507,7 +3507,7 @@ TEST_F(UpdateClientTest, RetryAfter) {
TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx1;
crx1.name = "test_jebg";
@@ -3787,7 +3787,7 @@ TEST_F(UpdateClientTest, TwoCrxUpdateOneUpdateDisabled) {
TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx;
crx.name = "test_jebg";
@@ -3830,7 +3830,7 @@ TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
EXPECT_EQ(1u, components.count(id));
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(std::move(update_check_callback), base::nullopt,
+ base::BindOnce(std::move(update_check_callback), absl::nullopt,
ErrorCategory::kUpdateCheck, -1, 0));
}
};
@@ -3907,9 +3907,9 @@ TEST_F(UpdateClientTest, OneCrxUpdateCheckFails) {
TEST_F(UpdateClientTest, OneCrxErrorUnknownApp) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
- std::vector<base::Optional<CrxComponent>> component;
+ std::vector<absl::optional<CrxComponent>> component;
{
CrxComponent crx;
crx.name = "test_jebg";
@@ -4288,7 +4288,7 @@ TEST_F(UpdateClientTest, ActionRun_Install) {
crx.installer = base::MakeRefCounted<VersionedTestInstaller>();
crx.action_handler = action_handler;
crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
- return std::vector<base::Optional<CrxComponent>>{crx};
+ return std::vector<absl::optional<CrxComponent>>{crx};
}),
{},
base::BindOnce(
@@ -4448,7 +4448,7 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
base::MakeRefCounted<ReadOnlyTestInstaller>(unpack_path);
crx.action_handler = action_handler;
crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
- return std::vector<base::Optional<CrxComponent>>{crx};
+ return std::vector<absl::optional<CrxComponent>>{crx};
},
unpack_path),
{}, false,
@@ -4466,7 +4466,7 @@ TEST_F(UpdateClientTest, ActionRun_NoUpdate) {
TEST_F(UpdateClientTest, CustomAttributeNoUpdate) {
class DataCallbackMock {
public:
- static std::vector<base::Optional<CrxComponent>> Callback(
+ static std::vector<absl::optional<CrxComponent>> Callback(
const std::vector<std::string>& ids) {
CrxComponent crx;
crx.name = "test_jebg";
@@ -4474,7 +4474,7 @@ TEST_F(UpdateClientTest, CustomAttributeNoUpdate) {
crx.version = base::Version("0.9");
crx.installer = base::MakeRefCounted<TestInstaller>();
crx.crx_format_requirement = crx_file::VerifierFormat::CRX3;
- std::vector<base::Optional<CrxComponent>> component = {crx};
+ std::vector<absl::optional<CrxComponent>> component = {crx};
return component;
}
};
@@ -4633,7 +4633,7 @@ TEST_F(UpdateClientTest, BadCrxDataCallback) {
update_client->Update(
ids, base::BindOnce([](const std::vector<std::string>& ids) {
EXPECT_EQ(ids.size(), size_t{2});
- return std::vector<base::Optional<CrxComponent>>{base::nullopt};
+ return std::vector<absl::optional<CrxComponent>>{absl::nullopt};
}),
base::BindRepeating(&MockCrxStateChangeReceiver::Receive, receiver), true,
base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
diff --git a/chromium/components/update_client/update_engine.cc b/chromium/components/update_client/update_engine.cc
index 0a4c2d615ea..b0a84caee41 100644
--- a/chromium/components/update_client/update_engine.cc
+++ b/chromium/components/update_client/update_engine.cc
@@ -13,7 +13,6 @@
#include "base/check_op.h"
#include "base/guid.h"
#include "base/location.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -26,6 +25,7 @@
#include "components/update_client/update_checker.h"
#include "components/update_client/update_client_errors.h"
#include "components/update_client/utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace update_client {
@@ -93,7 +93,7 @@ void UpdateEngine::Update(
}
// Calls out to get the corresponding CrxComponent data for the components.
- const std::vector<base::Optional<CrxComponent>> crx_components =
+ const std::vector<absl::optional<CrxComponent>> crx_components =
std::move(crx_data_callback).Run(ids);
if (crx_components.size() < ids.size()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -168,7 +168,7 @@ void UpdateEngine::DoUpdateCheck(scoped_refptr<UpdateContext> update_context) {
void UpdateEngine::UpdateCheckResultsAvailable(
scoped_refptr<UpdateContext> update_context,
- const base::Optional<ProtocolParser::Results>& results,
+ const absl::optional<ProtocolParser::Results>& results,
ErrorCategory error_category,
int error,
int retry_after_sec) {
@@ -197,7 +197,7 @@ void UpdateEngine::UpdateCheckResultsAvailable(
for (const auto& id : update_context->components_to_check_for_updates) {
DCHECK_EQ(1u, update_context->components.count(id));
auto& component = update_context->components.at(id);
- component->SetUpdateCheckResult(base::nullopt,
+ component->SetUpdateCheckResult(absl::nullopt,
ErrorCategory::kUpdateCheck, error);
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -239,7 +239,7 @@ void UpdateEngine::UpdateCheckResultsAvailable(
static_cast<int>(error.second));
} else {
component->SetUpdateCheckResult(
- base::nullopt, ErrorCategory::kUpdateCheck,
+ absl::nullopt, ErrorCategory::kUpdateCheck,
static_cast<int>(ProtocolError::UPDATE_RESPONSE_NOT_FOUND));
}
}
diff --git a/chromium/components/update_client/update_engine.h b/chromium/components/update_client/update_engine.h
index a6f291cf5f0..ff8dbb087f6 100644
--- a/chromium/components/update_client/update_engine.h
+++ b/chromium/components/update_client/update_engine.h
@@ -14,7 +14,6 @@
#include "base/callback.h"
#include "base/containers/queue.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "components/update_client/component.h"
@@ -23,6 +22,7 @@
#include "components/update_client/ping_manager.h"
#include "components/update_client/update_checker.h"
#include "components/update_client/update_client.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class TimeTicks;
@@ -83,7 +83,7 @@ class UpdateEngine : public base::RefCountedThreadSafe<UpdateEngine> {
void DoUpdateCheck(scoped_refptr<UpdateContext> update_context);
void UpdateCheckResultsAvailable(
scoped_refptr<UpdateContext> update_context,
- const base::Optional<ProtocolParser::Results>& results,
+ const absl::optional<ProtocolParser::Results>& results,
ErrorCategory error_category,
int error,
int retry_after_sec);
diff --git a/chromium/components/update_client/utils.cc b/chromium/components/update_client/utils.cc
index 6a82327fcc0..af519eb6e21 100644
--- a/chromium/components/update_client/utils.cc
+++ b/chromium/components/update_client/utils.cc
@@ -9,6 +9,8 @@
#include <algorithm>
#include <cmath>
#include <cstring>
+#include <memory>
+#include <utility>
#include "base/callback.h"
#include "base/files/file_path.h"
@@ -154,21 +156,17 @@ CrxInstaller::Result InstallFunctionWrapper(
// TODO(cpu): add a specific attribute check to a component json that the
// extension unpacker will reject, so that a component cannot be installed
// as an extension.
-std::unique_ptr<base::DictionaryValue> ReadManifest(
- const base::FilePath& unpack_path) {
+base::Value ReadManifest(const base::FilePath& unpack_path) {
base::FilePath manifest =
unpack_path.Append(FILE_PATH_LITERAL("manifest.json"));
if (!base::PathExists(manifest))
- return std::unique_ptr<base::DictionaryValue>();
+ return base::Value();
JSONFileValueDeserializer deserializer(manifest);
std::string error;
std::unique_ptr<base::Value> root = deserializer.Deserialize(nullptr, &error);
if (!root)
- return std::unique_ptr<base::DictionaryValue>();
- if (!root->is_dict())
- return std::unique_ptr<base::DictionaryValue>();
- return std::unique_ptr<base::DictionaryValue>(
- static_cast<base::DictionaryValue*>(root.release()));
+ return base::Value();
+ return base::Value::FromUniquePtrValue(std::move(root));
}
} // namespace update_client
diff --git a/chromium/components/update_client/utils.h b/chromium/components/update_client/utils.h
index 9423392b3ef..4dee34d187d 100644
--- a/chromium/components/update_client/utils.h
+++ b/chromium/components/update_client/utils.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_UPDATE_CLIENT_UTILS_H_
#define COMPONENTS_UPDATE_CLIENT_UTILS_H_
-#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -17,8 +16,8 @@
class GURL;
namespace base {
-class DictionaryValue;
class FilePath;
+class Value;
}
namespace update_client {
@@ -72,8 +71,9 @@ CrxInstaller::Result InstallFunctionWrapper(
base::OnceCallback<bool()> callback);
// Deserializes the CRX manifest. The top level must be a dictionary.
-std::unique_ptr<base::DictionaryValue> ReadManifest(
- const base::FilePath& unpack_path);
+// Returns a base::Value object of type dictionary on success, or another type
+// on failure.
+base::Value ReadManifest(const base::FilePath& unpack_path);
// Converts a custom, specific installer error (and optionally extended error)
// to an installer result.
diff --git a/chromium/components/upload_list/combining_upload_list.cc b/chromium/components/upload_list/combining_upload_list.cc
index d6139e8b9ec..cf5cf6bf6f8 100644
--- a/chromium/components/upload_list/combining_upload_list.cc
+++ b/chromium/components/upload_list/combining_upload_list.cc
@@ -47,3 +47,9 @@ void CombiningUploadList::ClearUploadList(const base::Time& begin,
sublist->ClearUploadList(begin, end);
}
}
+
+void CombiningUploadList::RequestSingleUpload(const std::string& local_id) {
+ for (const scoped_refptr<UploadList>& sublist : sublists_) {
+ sublist->RequestSingleUpload(local_id);
+ }
+}
diff --git a/chromium/components/upload_list/combining_upload_list.h b/chromium/components/upload_list/combining_upload_list.h
index bba6207e3c4..05502235c7a 100644
--- a/chromium/components/upload_list/combining_upload_list.h
+++ b/chromium/components/upload_list/combining_upload_list.h
@@ -22,6 +22,7 @@ class CombiningUploadList : public UploadList {
~CombiningUploadList() override;
std::vector<UploadInfo> LoadUploadList() override;
void ClearUploadList(const base::Time& begin, const base::Time& end) override;
+ void RequestSingleUpload(const std::string& local_id) override;
private:
const std::vector<scoped_refptr<UploadList>> sublists_;
diff --git a/chromium/components/upload_list/combining_upload_list_unittest.cc b/chromium/components/upload_list/combining_upload_list_unittest.cc
index e88d0119254..8351fe320cb 100644
--- a/chromium/components/upload_list/combining_upload_list_unittest.cc
+++ b/chromium/components/upload_list/combining_upload_list_unittest.cc
@@ -12,6 +12,7 @@
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/upload_list/text_log_upload_list.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
@@ -276,4 +277,26 @@ TEST_F(CombiningUploadListTest, Clear) {
)");
}
+class MockUploadList : public UploadList {
+ public:
+ MOCK_METHOD0(LoadUploadList, std::vector<UploadInfo>());
+ MOCK_METHOD2(ClearUploadList, void(const base::Time&, const base::Time&));
+ MOCK_METHOD1(RequestSingleUpload, void(const std::string&));
+
+ protected:
+ ~MockUploadList() final = default;
+};
+
+TEST_F(CombiningUploadListTest, RequestSingleUpload) {
+ auto mock_list1 = base::MakeRefCounted<MockUploadList>();
+ auto mock_list2 = base::MakeRefCounted<MockUploadList>();
+ auto combined_lists = base::MakeRefCounted<CombiningUploadList>(
+ std::vector<scoped_refptr<UploadList>>({mock_list1, mock_list2}));
+
+ constexpr char kLocalId[] = "12345";
+ EXPECT_CALL(*mock_list1, RequestSingleUpload(kLocalId));
+ EXPECT_CALL(*mock_list2, RequestSingleUpload(kLocalId));
+ combined_lists->RequestSingleUploadAsync(kLocalId);
+}
+
} // namespace
diff --git a/chromium/components/upload_list/text_log_upload_list.cc b/chromium/components/upload_list/text_log_upload_list.cc
index 776229b5459..189d49b40a8 100644
--- a/chromium/components/upload_list/text_log_upload_list.cc
+++ b/chromium/components/upload_list/text_log_upload_list.cc
@@ -9,10 +9,10 @@
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace {
@@ -167,7 +167,7 @@ std::unique_ptr<TextLogUploadList::UploadInfo> TryParseJsonLogEntry(
info->capture_time = base::Time::FromDoubleT(capture_time_double);
// Parse state.
- base::Optional<int> state = dict.FindIntKey(kJsonLogKeyState);
+ absl::optional<int> state = dict.FindIntKey(kJsonLogKeyState);
if (state.has_value())
info->state =
static_cast<TextLogUploadList::UploadInfo::State>(state.value());
@@ -210,7 +210,7 @@ void TextLogUploadList::ClearUploadList(const base::Time& begin,
std::ostringstream new_contents_stream;
for (const std::string& line : log_entries) {
- base::Optional<base::Value> json = base::JSONReader::Read(line);
+ absl::optional<base::Value> json = base::JSONReader::Read(line);
bool should_copy = false;
if (json.has_value())
@@ -237,8 +237,8 @@ void TextLogUploadList::ParseLogEntries(
std::vector<std::string>::const_reverse_iterator i;
for (i = log_entries.rbegin(); i != log_entries.rend(); ++i) {
const std::string& line = *i;
- std::unique_ptr<UploadInfo> info = nullptr;
- base::Optional<base::Value> json = base::JSONReader::Read(line);
+ std::unique_ptr<UploadInfo> info;
+ absl::optional<base::Value> json = base::JSONReader::Read(line);
if (json.has_value() && json->is_dict())
info = TryParseJsonLogEntry(json.value());
diff --git a/chromium/components/url_formatter/OWNERS b/chromium/components/url_formatter/OWNERS
index 013962e225e..8ad18268102 100644
--- a/chromium/components/url_formatter/OWNERS
+++ b/chromium/components/url_formatter/OWNERS
@@ -1,6 +1,9 @@
pkasting@chromium.org
tommycli@chromium.org
meacer@chromium.org
+cthomp@chromium.org
+estark@chromium.org
+felt@chromium.org
# Changes to FormatUrlForSecurityDisplay and FormatOriginForSecurityDisplay
# require a security review to avoid introducing security bugs.
diff --git a/chromium/components/url_formatter/android/javatests/src/org/chromium/components/url_formatter/UrlFormatterUnitTest.java b/chromium/components/url_formatter/android/javatests/src/org/chromium/components/url_formatter/UrlFormatterUnitTest.java
index 3040b32668d..02a0ef8bbcb 100644
--- a/chromium/components/url_formatter/android/javatests/src/org/chromium/components/url_formatter/UrlFormatterUnitTest.java
+++ b/chromium/components/url_formatter/android/javatests/src/org/chromium/components/url_formatter/UrlFormatterUnitTest.java
@@ -59,6 +59,20 @@ public class UrlFormatterUnitTest {
@Test
@SmallTest
+ public void testFormatUrlForDisplayOmitSchemeOmitTrivialSubdomains() {
+ Function<String, String> f =
+ UrlFormatter::formatUrlForDisplayOmitSchemeOmitTrivialSubdomains;
+
+ assertEquals("google.com/path", f.apply("http://user:pass@google.com/path"));
+ assertEquals("chrome://version", f.apply("chrome://version"));
+ assertEquals("äää.de", f.apply("https://äää.de"));
+ assertEquals("xn--4caaa.com", f.apply("https://äää.com"));
+ assertEquals("مثال.إختبار", f.apply("https://xn--mgbh0fb.xn--kgbechtv/"));
+ assertEquals("example.com/ test", f.apply("http://user:password@example.com/%20test"));
+ }
+
+ @Test
+ @SmallTest
public void testFormatUrlForDisplayOmitSchemePathAndTrivialSubdomains() {
Function<GURL, String> f =
UrlFormatter::formatUrlForDisplayOmitSchemePathAndTrivialSubdomains;
diff --git a/chromium/components/url_formatter/elide_url.cc b/chromium/components/url_formatter/elide_url.cc
index 86cde24d9d9..d195f8c1df3 100644
--- a/chromium/components/url_formatter/elide_url.cc
+++ b/chromium/components/url_formatter/elide_url.cc
@@ -430,4 +430,15 @@ std::u16string FormatOriginForSecurityDisplay(
return result;
}
+std::u16string FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
+ const GURL& url) {
+ return url_formatter::FormatUrl(
+ url,
+ url_formatter::kFormatUrlOmitDefaults |
+ url_formatter::kFormatUrlTrimAfterHost |
+ url_formatter::kFormatUrlOmitHTTPS |
+ url_formatter::kFormatUrlOmitTrivialSubdomains,
+ net::UnescapeRule::SPACES, nullptr, nullptr, nullptr);
+}
+
} // namespace url_formatter
diff --git a/chromium/components/url_formatter/elide_url.h b/chromium/components/url_formatter/elide_url.h
index 75543567ad5..ba326a60e36 100644
--- a/chromium/components/url_formatter/elide_url.h
+++ b/chromium/components/url_formatter/elide_url.h
@@ -98,6 +98,21 @@ std::u16string FormatOriginForSecurityDisplay(
const url::Origin& origin,
const SchemeDisplay scheme_display = SchemeDisplay::SHOW);
+// This is a convenience function for formatting a URL in a concise and
+// human-friendly way, omitting the HTTP/HTTPS scheme, the username and
+// password, the path and removing trivial subdomains.
+
+// The IDN hostname is turned to Unicode if the Unicode representation is deemed
+// safe, including RTL characters (as opposed to
+// `url_formatter::FormatUrlForSecurityDisplay()`).
+
+// Example:
+// - "http://user:password@example.com/%20test" -> "example.com"
+// - "http://user:password@example.com/" -> "example.com"
+// - "http://www.xn--frgbolaget-q5a.se" -> "färgbolaget.se"
+std::u16string FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
+ const GURL& url);
+
} // namespace url_formatter
#endif // COMPONENTS_URL_FORMATTER_ELIDE_URL_H_
diff --git a/chromium/components/url_formatter/elide_url_unittest.cc b/chromium/components/url_formatter/elide_url_unittest.cc
index 340321725a8..784ddc0044f 100644
--- a/chromium/components/url_formatter/elide_url_unittest.cc
+++ b/chromium/components/url_formatter/elide_url_unittest.cc
@@ -684,4 +684,27 @@ TEST(TextEliderTest, FormatOriginForSecurityDisplay) {
<< "Explicitly test the url::Origin which takes an empty, invalid URL";
}
+TEST(TextEliderTest, FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains) {
+ EXPECT_EQ(
+ u"google.com",
+ url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
+ GURL("http://user:pass@google.com/path")));
+ EXPECT_EQ(
+ u"chrome://version",
+ url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
+ GURL("chrome://version")));
+ EXPECT_EQ(
+ u"äää.de",
+ url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
+ GURL("https://äää.de")));
+ EXPECT_EQ(
+ u"xn--4caaa.com",
+ url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
+ GURL("https://äää.com")));
+ EXPECT_EQ(
+ u"مثال.إختبار",
+ url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
+ GURL("https://xn--mgbh0fb.xn--kgbechtv/")));
+}
+
} // namespace
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 23bd3e81873..3909d486869 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
@@ -9,7 +9,6 @@
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/url_formatter/spoof_checks/idn_spoof_checker.h"
diff --git a/chromium/components/url_formatter/tools/DIR_METADATA b/chromium/components/url_formatter/tools/DIR_METADATA
deleted file mode 100644
index f5b2b442c26..00000000000
--- a/chromium/components/url_formatter/tools/DIR_METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-monorail {
- component: "UI>Security>UrlFormatting"
-}
diff --git a/chromium/components/url_formatter/url_formatter.cc b/chromium/components/url_formatter/url_formatter.cc
index 29d59e0a225..f8f57f2d85e 100644
--- a/chromium/components/url_formatter/url_formatter.cc
+++ b/chromium/components/url_formatter/url_formatter.cc
@@ -11,6 +11,7 @@
#include "base/lazy_instance.h"
#include "base/numerics/safe_conversions.h"
#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_offset_string_conversions.h"
@@ -191,8 +192,7 @@ std::u16string FormatViewSourceUrl(
size_t* prefix_end,
base::OffsetAdjuster::Adjustments* adjustments) {
DCHECK(new_parsed);
- const char kViewSource[] = "view-source:";
- const size_t kViewSourceLength = base::size(kViewSource) - 1;
+ static constexpr base::StringPiece16 kViewSource = u"view-source:";
// The URL embedded within view-source should never have destructive elisions
// applied to it. Users of view-source likely want to see the full URL.
@@ -204,28 +204,27 @@ std::u16string FormatViewSourceUrl(
// Format the underlying URL and record adjustments.
const std::string& url_str(url.possibly_invalid_spec());
adjustments->clear();
- std::u16string result(
- base::ASCIIToUTF16(kViewSource) +
- FormatUrlWithAdjustments(GURL(url_str.substr(kViewSourceLength)),
- format_types, unescape_rules, new_parsed,
- prefix_end, adjustments));
+ std::u16string result = base::StrCat(
+ {kViewSource, FormatUrlWithAdjustments(
+ GURL(url_str.substr(kViewSource.size())), format_types,
+ unescape_rules, new_parsed, prefix_end, adjustments)});
// Revise |adjustments| by shifting to the offsets to prefix that the above
// call to FormatUrl didn't get to see.
- for (auto it = adjustments->begin(); it != adjustments->end(); ++it)
- it->original_offset += kViewSourceLength;
+ for (auto& adjustment : *adjustments)
+ adjustment.original_offset += kViewSource.size();
// Adjust positions of the parsed components.
if (new_parsed->scheme.is_nonempty()) {
// Assume "view-source:real-scheme" as a scheme.
- new_parsed->scheme.len += kViewSourceLength;
+ new_parsed->scheme.len += kViewSource.size();
} else {
new_parsed->scheme.begin = 0;
- new_parsed->scheme.len = kViewSourceLength - 1;
+ new_parsed->scheme.len = kViewSource.size() - 1;
}
- AdjustAllComponentsButScheme(kViewSourceLength, new_parsed);
+ AdjustAllComponentsButScheme(kViewSource.size(), new_parsed);
if (prefix_end)
- *prefix_end += kViewSourceLength;
+ *prefix_end += kViewSource.size();
return result;
}
diff --git a/chromium/components/url_formatter/url_formatter_android.cc b/chromium/components/url_formatter/url_formatter_android.cc
index 9a93a0245df..1376a177d77 100644
--- a/chromium/components/url_formatter/url_formatter_android.cc
+++ b/chromium/components/url_formatter/url_formatter_android.cc
@@ -125,13 +125,8 @@ JNI_UrlFormatter_FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
DCHECK(j_gurl);
std::unique_ptr<GURL> gurl = url::GURLAndroid::ToNativeGURL(env, j_gurl);
return base::android::ConvertUTF16ToJavaString(
- env, url_formatter::FormatUrl(
- *gurl,
- url_formatter::kFormatUrlOmitDefaults |
- url_formatter::kFormatUrlTrimAfterHost |
- url_formatter::kFormatUrlOmitHTTPS |
- url_formatter::kFormatUrlOmitTrivialSubdomains,
- net::UnescapeRule::SPACES, nullptr, nullptr, nullptr));
+ env, url_formatter::FormatUrlForDisplayOmitSchemePathAndTrivialSubdomains(
+ *gurl));
}
} // namespace android
diff --git a/chromium/components/url_formatter/url_formatter_unittest.cc b/chromium/components/url_formatter/url_formatter_unittest.cc
index 7212afb46d5..d286cbb5258 100644
--- a/chromium/components/url_formatter/url_formatter_unittest.cc
+++ b/chromium/components/url_formatter/url_formatter_unittest.cc
@@ -13,7 +13,6 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
diff --git a/chromium/components/url_matcher/substring_set_matcher.h b/chromium/components/url_matcher/substring_set_matcher.h
index f941d17cb7c..c247d499fa2 100644
--- a/chromium/components/url_matcher/substring_set_matcher.h
+++ b/chromium/components/url_matcher/substring_set_matcher.h
@@ -14,9 +14,9 @@
#include "base/containers/flat_map.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/url_matcher/string_pattern.h"
#include "components/url_matcher/url_matcher_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace url_matcher {
diff --git a/chromium/components/url_matcher/url_matcher_factory.cc b/chromium/components/url_matcher/url_matcher_factory.cc
index af99a765631..ae18f6d97a9 100644
--- a/chromium/components/url_matcher/url_matcher_factory.cc
+++ b/chromium/components/url_matcher/url_matcher_factory.cc
@@ -248,11 +248,10 @@ std::unique_ptr<URLMatcherPortFilter> URLMatcherFactory::CreateURLMatcherPorts(
return nullptr;
}
- for (const auto& entry : *value_list) {
- int port = 0;
+ for (const auto& entry : value_list->GetList()) {
const base::ListValue* range = nullptr;
- if (entry.GetAsInteger(&port)) {
- ranges.push_back(URLMatcherPortFilter::CreateRange(port));
+ if (entry.is_int()) {
+ ranges.push_back(URLMatcherPortFilter::CreateRange(entry.GetInt()));
} else if (entry.GetAsList(&range)) {
int from = 0, to = 0;
if (range->GetSize() != 2u ||
diff --git a/chromium/components/url_matcher/url_matcher_factory_unittest.cc b/chromium/components/url_matcher/url_matcher_factory_unittest.cc
index df62aff75fd..31301e20e9d 100644
--- a/chromium/components/url_matcher/url_matcher_factory_unittest.cc
+++ b/chromium/components/url_matcher/url_matcher_factory_unittest.cc
@@ -237,7 +237,8 @@ void UrlConditionCaseTest::CheckCondition(
if (use_list_of_strings_) {
auto list = std::make_unique<base::ListValue>();
list->AppendString(value);
- condition.SetWithoutPathExpansion(condition_key_, std::move(list));
+ condition.SetKey(condition_key_,
+ base::Value::FromUniquePtrValue(std::move(list)));
} else {
condition.SetKey(condition_key_, base::Value(value));
}
diff --git a/chromium/components/url_pattern_index/flat/url_pattern_index.fbs b/chromium/components/url_pattern_index/flat/url_pattern_index.fbs
index b7005163df0..a8ed7d00a12 100644
--- a/chromium/components/url_pattern_index/flat/url_pattern_index.fbs
+++ b/chromium/components/url_pattern_index/flat/url_pattern_index.fbs
@@ -121,6 +121,10 @@ table UrlRule {
// Priority of the rule. Larger the value, greater the priority.
priority : uint64;
+
+ // Binary blob for any embedder specific rule conditions. When specified,
+ // these should be interpreted by the url_pattern_index embedder.
+ embedder_conditions : [ubyte];
}
// Contains an N-gram (acting as a key in a hash table) and a list of URL rules
diff --git a/chromium/components/url_pattern_index/uint64_hasher.h b/chromium/components/url_pattern_index/uint64_hasher.h
index aa6bab2e2e0..7e4ba3c6785 100644
--- a/chromium/components/url_pattern_index/uint64_hasher.h
+++ b/chromium/components/url_pattern_index/uint64_hasher.h
@@ -7,8 +7,8 @@
// https://gist.github.com/badboy/6267743
// TODO(pkalinnikov): Consider moving the implementation into base/.
-#ifndef COMPONENTS_URL_PATTERN_INDEX_HASH_H_
-#define COMPONENTS_URL_PATTERN_INDEX_HASH_H_
+#ifndef COMPONENTS_URL_PATTERN_INDEX_UINT64_HASHER_H_
+#define COMPONENTS_URL_PATTERN_INDEX_UINT64_HASHER_H_
#include <stddef.h>
#include <stdint.h>
@@ -55,4 +55,4 @@ class Uint64ToUint32Hasher {
} // namespace url_pattern_index
-#endif // COMPONENTS_URL_PATTERN_INDEX_HASH_H_
+#endif // COMPONENTS_URL_PATTERN_INDEX_UINT64_HASHER_H_
diff --git a/chromium/components/url_pattern_index/url_pattern.h b/chromium/components/url_pattern_index/url_pattern.h
index c36209bc97a..cf0d86ae22d 100644
--- a/chromium/components/url_pattern_index/url_pattern.h
+++ b/chromium/components/url_pattern_index/url_pattern.h
@@ -8,9 +8,9 @@
#include <iosfwd>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "components/url_pattern_index/proto/rules.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/third_party/mozilla/url_parse.h"
class GURL;
@@ -47,7 +47,7 @@ class UrlPattern {
// String to hold the lazily computed lower cased spec.
mutable std::string lower_case_spec_owner_;
// Reference to the lower case spec. Computed lazily.
- mutable base::Optional<base::StringPiece> lower_case_spec_cached_;
+ mutable absl::optional<base::StringPiece> lower_case_spec_cached_;
// The url host component.
const url::Component host_;
diff --git a/chromium/components/url_pattern_index/url_pattern_index.cc b/chromium/components/url_pattern_index/url_pattern_index.cc
index c8c240d8950..96695fcb6a4 100644
--- a/chromium/components/url_pattern_index/url_pattern_index.cc
+++ b/chromium/components/url_pattern_index/url_pattern_index.cc
@@ -9,19 +9,20 @@
#include <string>
#include <utility>
+#include "base/callback.h"
#include "base/check_op.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
-#include "base/optional.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/trace_event/trace_event.h"
#include "components/url_pattern_index/ngram_extractor.h"
#include "components/url_pattern_index/url_pattern.h"
#include "components/url_pattern_index/url_rule_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
#include "url/url_constants.h"
@@ -590,6 +591,8 @@ const flat::UrlRule* FindMatchAmongCandidates(
flat::RequestMethod request_method,
bool is_third_party,
bool disable_generic_rules,
+ const UrlPatternIndexMatcher::EmbedderConditionsMatcher&
+ embedder_conditions_matcher,
std::vector<const flat::UrlRule*>* matched_rules) {
if (!sorted_candidates)
return nullptr;
@@ -601,9 +604,11 @@ const flat::UrlRule* FindMatchAmongCandidates(
DCHECK_NE(rule, nullptr);
DCHECK_NE(rule->url_pattern_type(), flat::UrlPatternType_REGEXP);
if (!DoesRuleFlagsMatch(*rule, element_type, activation_type,
- request_method, is_third_party)) {
+ request_method, is_third_party,
+ embedder_conditions_matcher)) {
continue;
}
+
if (!UrlPattern(*rule).MatchesUrl(url))
continue;
@@ -633,6 +638,8 @@ const flat::UrlRule* FindMatchInFlatUrlPatternIndex(
flat::RequestMethod request_method,
bool is_third_party,
bool disable_generic_rules,
+ const UrlPatternIndexMatcher::EmbedderConditionsMatcher&
+ embedder_conditions_matcher,
UrlPatternIndexMatcher::FindRuleStrategy strategy,
std::vector<const flat::UrlRule*>* matched_rules) {
using FindRuleStrategy = UrlPatternIndexMatcher::FindRuleStrategy;
@@ -678,7 +685,8 @@ const flat::UrlRule* FindMatchInFlatUrlPatternIndex(
continue;
const flat::UrlRule* rule = FindMatchAmongCandidates(
entry->rule_list(), url, document_origin, element_type, activation_type,
- request_method, is_third_party, disable_generic_rules, matched_rules);
+ request_method, is_third_party, disable_generic_rules,
+ embedder_conditions_matcher, matched_rules);
if (!rule)
continue;
@@ -698,7 +706,7 @@ const flat::UrlRule* FindMatchInFlatUrlPatternIndex(
const flat::UrlRule* rule = FindMatchAmongCandidates(
index.fallback_rules(), url, document_origin, element_type,
activation_type, request_method, is_third_party, disable_generic_rules,
- matched_rules);
+ embedder_conditions_matcher, matched_rules);
switch (strategy) {
case FindRuleStrategy::kAny:
@@ -743,7 +751,9 @@ bool DoesRuleFlagsMatch(const flat::UrlRule& rule,
flat::ElementType element_type,
flat::ActivationType activation_type,
flat::RequestMethod request_method,
- bool is_third_party) {
+ bool is_third_party,
+ const UrlPatternIndexMatcher::EmbedderConditionsMatcher&
+ embedder_conditions_matcher) {
DCHECK((element_type == flat::ElementType_NONE) !=
(activation_type == flat::ActivationType_NONE));
@@ -769,6 +779,11 @@ bool DoesRuleFlagsMatch(const flat::UrlRule& rule,
return false;
}
+ if (rule.embedder_conditions() && !embedder_conditions_matcher.is_null() &&
+ !embedder_conditions_matcher.Run(*rule.embedder_conditions())) {
+ return false;
+ }
+
return true;
}
@@ -813,11 +828,13 @@ const flat::UrlRule* UrlPatternIndexMatcher::FindMatch(
proto::ActivationType activation_type,
bool is_third_party,
bool disable_generic_rules,
+ const EmbedderConditionsMatcher& embedder_conditions_matcher,
FindRuleStrategy strategy) const {
return FindMatch(
url, first_party_origin, ProtoToFlatElementType(element_type),
ProtoToFlatActivationType(activation_type), flat::RequestMethod_NONE,
- is_third_party, disable_generic_rules, strategy);
+ is_third_party, disable_generic_rules, embedder_conditions_matcher,
+ strategy);
}
const flat::UrlRule* UrlPatternIndexMatcher::FindMatch(
@@ -828,6 +845,7 @@ const flat::UrlRule* UrlPatternIndexMatcher::FindMatch(
flat::RequestMethod request_method,
bool is_third_party,
bool disable_generic_rules,
+ const EmbedderConditionsMatcher& embedder_conditions_matcher,
FindRuleStrategy strategy) const {
// Ignore URLs that are greater than the max URL length. Since those will be
// disallowed elsewhere in the loading stack, we can save compute time by
@@ -847,7 +865,7 @@ const flat::UrlRule* UrlPatternIndexMatcher::FindMatch(
auto* rule = FindMatchInFlatUrlPatternIndex(
*flat_index_, UrlPattern::UrlInfo(url), first_party_origin, element_type,
activation_type, request_method, is_third_party, disable_generic_rules,
- strategy, nullptr /* matched_rules */);
+ embedder_conditions_matcher, strategy, nullptr /* matched_rules */);
if (rule) {
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("loading"),
"UrlPatternIndexMatcher::FindMatch", "pattern",
@@ -862,11 +880,12 @@ std::vector<const flat::UrlRule*> UrlPatternIndexMatcher::FindAllMatches(
proto::ElementType element_type,
proto::ActivationType activation_type,
bool is_third_party,
- bool disable_generic_rules) const {
+ bool disable_generic_rules,
+ const EmbedderConditionsMatcher& embedder_conditions_matcher) const {
return FindAllMatches(
url, first_party_origin, ProtoToFlatElementType(element_type),
ProtoToFlatActivationType(activation_type), flat::RequestMethod_NONE,
- is_third_party, disable_generic_rules);
+ is_third_party, disable_generic_rules, embedder_conditions_matcher);
}
std::vector<const flat::UrlRule*> UrlPatternIndexMatcher::FindAllMatches(
@@ -876,7 +895,8 @@ std::vector<const flat::UrlRule*> UrlPatternIndexMatcher::FindAllMatches(
flat::ActivationType activation_type,
flat::RequestMethod request_method,
bool is_third_party,
- bool disable_generic_rules) const {
+ bool disable_generic_rules,
+ const EmbedderConditionsMatcher& embedder_conditions_matcher) const {
// Ignore URLs that are greater than the max URL length. Since those will be
// disallowed elsewhere in the loading stack, we can save compute time by
// avoiding matching here.
@@ -893,7 +913,7 @@ std::vector<const flat::UrlRule*> UrlPatternIndexMatcher::FindAllMatches(
FindMatchInFlatUrlPatternIndex(
*flat_index_, UrlPattern::UrlInfo(url), first_party_origin, element_type,
activation_type, request_method, is_third_party, disable_generic_rules,
- FindRuleStrategy::kAll, &rules);
+ embedder_conditions_matcher, FindRuleStrategy::kAll, &rules);
return rules;
}
diff --git a/chromium/components/url_pattern_index/url_pattern_index.h b/chromium/components/url_pattern_index/url_pattern_index.h
index 8543d0f9d30..7d47a1820cf 100644
--- a/chromium/components/url_pattern_index/url_pattern_index.h
+++ b/chromium/components/url_pattern_index/url_pattern_index.h
@@ -11,13 +11,14 @@
#include <map>
#include <vector>
+#include "base/callback_forward.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/strings/string_piece_forward.h"
#include "components/url_pattern_index/closed_hash_map.h"
#include "components/url_pattern_index/flat/url_pattern_index_generated.h"
#include "components/url_pattern_index/proto/rules.pb.h"
#include "components/url_pattern_index/uint64_hasher.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/flatbuffers/src/include/flatbuffers/flatbuffers.h"
class GURL;
@@ -84,7 +85,7 @@ int CompareDomains(base::StringPiece lhs_domain, base::StringPiece rhs_domain);
// Increase this value when introducing an incompatible change to the
// UrlPatternIndex schema (flat/url_pattern_index.fbs). url_pattern_index
// clients can use this as a signal to rebuild rulesets.
-constexpr int kUrlPatternIndexFormatVersion = 8;
+constexpr int kUrlPatternIndexFormatVersion = 9;
// The class used to construct an index over the URL patterns of a set of URL
// rules. The rules themselves need to be converted to FlatBuffers format by the
@@ -129,32 +130,6 @@ class UrlPatternIndexBuilder {
DISALLOW_COPY_AND_ASSIGN(UrlPatternIndexBuilder);
};
-// Returns whether the |origin| matches the domain list of the |rule|. A match
-// means that the longest domain in |domains| that |origin| is a sub-domain of
-// is not an exception OR all the |domains| are exceptions and neither matches
-// the |origin|. Thus, domain filters with more domain components trump filters
-// with fewer domain components, i.e. the more specific a filter is, the higher
-// the priority.
-//
-// A rule whose domain list is empty or contains only negative domains is still
-// considered a "generic" rule. Therefore, if |disable_generic_rules| is set,
-// this function will always return false for such rules.
-bool DoesOriginMatchDomainList(const url::Origin& origin,
- const flat::UrlRule& rule,
- bool disable_generic_rules);
-
-// Returns whether the request matches flags of the specified `rule`. Takes into
-// account:
-// - `element_type` of the requested resource, if not *_NONE.
-// - `activation_type` for a subdocument request, if not *_NONE.
-// - `request_method` of the request, if not *_NONE.
-// - Whether the resource `is_third_party` w.r.t. its embedding document.
-bool DoesRuleFlagsMatch(const flat::UrlRule& rule,
- flat::ElementType element_type,
- flat::ActivationType activation_type,
- flat::RequestMethod request_method,
- bool is_third_party);
-
// Encapsulates a read-only index built over the URL patterns of a set of URL
// rules, and provides fast matching of network requests against these rules.
class UrlPatternIndexMatcher {
@@ -171,6 +146,11 @@ class UrlPatternIndexMatcher {
kAll,
};
+ // Matches the request against `embedder_conditions` and returns true if the
+ // request matched.
+ using EmbedderConditionsMatcher = base::RepeatingCallback<bool(
+ const flatbuffers::Vector<uint8_t>& embedder_conditions)>;
+
// Creates an instance to access the given |flat_index|. If |flat_index| is
// nullptr, then all requests return no match.
explicit UrlPatternIndexMatcher(const flat::UrlPatternIndex* flat_index);
@@ -206,25 +186,29 @@ class UrlPatternIndexMatcher {
// - The `is_third_party` bit matches the rule's requirement on the requested
// `url` being first-/third-party w.r.t. its `first_party_origin`.
// - The rule is not generic if `disable_generic_rules` is true.
- const flat::UrlRule* FindMatch(const GURL& url,
- const url::Origin& first_party_origin,
- proto::ElementType element_type,
- proto::ActivationType activation_type,
- bool is_third_party,
- bool disable_generic_rules,
- FindRuleStrategy strategy) const;
+ const flat::UrlRule* FindMatch(
+ const GURL& url,
+ const url::Origin& first_party_origin,
+ proto::ElementType element_type,
+ proto::ActivationType activation_type,
+ bool is_third_party,
+ bool disable_generic_rules,
+ const EmbedderConditionsMatcher& embedder_conditions_matcher,
+ FindRuleStrategy strategy) const;
// Helper function to work with flat::*Type(s). If the index contains one or
// more UrlRules that match the request, returns one of them depending on
// |strategy|. Otherwise, returns nullptr.
- const flat::UrlRule* FindMatch(const GURL& url,
- const url::Origin& first_party_origin,
- flat::ElementType element_type,
- flat::ActivationType activation_type,
- flat::RequestMethod request_method,
- bool is_third_party,
- bool disable_generic_rules,
- FindRuleStrategy strategy) const;
+ const flat::UrlRule* FindMatch(
+ const GURL& url,
+ const url::Origin& first_party_origin,
+ flat::ElementType element_type,
+ flat::ActivationType activation_type,
+ flat::RequestMethod request_method,
+ bool is_third_party,
+ bool disable_generic_rules,
+ const EmbedderConditionsMatcher& embedder_conditions_matcher,
+ FindRuleStrategy strategy) const;
// Same as FindMatch, except this function returns all UrlRules that match the
// request for the index. If no UrlRules match, returns an empty vector.
@@ -234,7 +218,8 @@ class UrlPatternIndexMatcher {
proto::ElementType element_type,
proto::ActivationType activation_type,
bool is_third_party,
- bool disable_generic_rules) const;
+ bool disable_generic_rules,
+ const EmbedderConditionsMatcher& embedder_conditions_matcher) const;
// Helper function to work with flat::*Type(s). Returns all UrlRules that
// match the request for the index. If no UrlRules match, returns an empty
@@ -246,18 +231,48 @@ class UrlPatternIndexMatcher {
flat::ActivationType activation_type,
flat::RequestMethod request_method,
bool is_third_party,
- bool disable_generic_rules) const;
+ bool disable_generic_rules,
+ const EmbedderConditionsMatcher& embedder_conditions_matcher) const;
private:
// Must outlive this instance.
const flat::UrlPatternIndex* flat_index_;
// The number of rules in this index. Mutable since this is lazily computed.
- mutable base::Optional<size_t> rules_count_;
+ mutable absl::optional<size_t> rules_count_;
DISALLOW_COPY_AND_ASSIGN(UrlPatternIndexMatcher);
};
+// Returns whether the |origin| matches the domain list of the |rule|. A match
+// means that the longest domain in |domains| that |origin| is a sub-domain of
+// is not an exception OR all the |domains| are exceptions and neither matches
+// the |origin|. Thus, domain filters with more domain components trump filters
+// with fewer domain components, i.e. the more specific a filter is, the higher
+// the priority.
+//
+// A rule whose domain list is empty or contains only negative domains is still
+// considered a "generic" rule. Therefore, if |disable_generic_rules| is set,
+// this function will always return false for such rules.
+bool DoesOriginMatchDomainList(const url::Origin& origin,
+ const flat::UrlRule& rule,
+ bool disable_generic_rules);
+
+// Returns whether the request matches flags of the specified `rule`. Takes into
+// account:
+// - `element_type` of the requested resource, if not *_NONE.
+// - `activation_type` for a subdocument request, if not *_NONE.
+// - `request_method` of the request, if not *_NONE.
+// - Whether the resource `is_third_party` w.r.t. its embedding document.
+// - Options specified by the embedder via `embedder_conditions_matcher`.
+bool DoesRuleFlagsMatch(const flat::UrlRule& rule,
+ flat::ElementType element_type,
+ flat::ActivationType activation_type,
+ flat::RequestMethod request_method,
+ bool is_third_party,
+ const UrlPatternIndexMatcher::EmbedderConditionsMatcher&
+ embedder_conditions_matcher);
+
} // namespace url_pattern_index
#endif // COMPONENTS_URL_PATTERN_INDEX_URL_PATTERN_INDEX_H_
diff --git a/chromium/components/url_pattern_index/url_pattern_index_unittest.cc b/chromium/components/url_pattern_index/url_pattern_index_unittest.cc
index 20b8440f03f..2b47981a67d 100644
--- a/chromium/components/url_pattern_index/url_pattern_index_unittest.cc
+++ b/chromium/components/url_pattern_index/url_pattern_index_unittest.cc
@@ -11,6 +11,8 @@
#include <string>
#include <vector>
+#include "base/bind.h"
+#include "base/callback.h"
#include "base/macros.h"
#include "base/rand_util.h"
#include "base/strings/string_piece.h"
@@ -35,6 +37,8 @@ using testing::kSubdomain;
using testing::kSubstring;
using testing::kThirdParty;
using testing::MakeUrlRule;
+using EmbedderConditionsMatcher =
+ UrlPatternIndexMatcher::EmbedderConditionsMatcher;
class UrlPatternIndexTest : public ::testing::Test {
public:
@@ -50,13 +54,16 @@ class UrlPatternIndexTest : public ::testing::Test {
return !!offset.o;
}
- void AddSimpleUrlRule(std::string pattern,
+ void AddSimpleUrlRule(const std::string& pattern,
uint32_t id,
uint32_t priority,
uint8_t options,
uint16_t element_types,
- uint16_t request_methods_mask) {
+ uint16_t request_methods_mask,
+ const std::vector<uint8_t>& embedder_conditions = {}) {
auto pattern_offset = flat_builder_->CreateString(pattern);
+ auto embedder_conditions_offset =
+ flat_builder_->CreateVector(embedder_conditions);
flat::UrlRuleBuilder rule_builder(*flat_builder_);
rule_builder.add_options(options);
@@ -65,6 +72,8 @@ class UrlPatternIndexTest : public ::testing::Test {
rule_builder.add_priority(priority);
rule_builder.add_element_types(element_types);
rule_builder.add_request_methods(request_methods_mask);
+ rule_builder.add_embedder_conditions(embedder_conditions_offset);
+
auto rule_offset = rule_builder.Finish();
index_builder_->IndexUrlRule(rule_offset);
@@ -95,21 +104,26 @@ class UrlPatternIndexTest : public ::testing::Test {
return index_matcher_->FindMatch(
url, document_origin, element_type, activation_type,
testing::IsThirdParty(url, document_origin), disable_generic_rules,
+ UrlPatternIndexMatcher::EmbedderConditionsMatcher(),
UrlPatternIndexMatcher::FindRuleStrategy::kAny);
}
- const flat::UrlRule* FindMatch(base::StringPiece url_string,
- base::StringPiece document_origin_string,
- flat::ElementType element_type,
- flat::ActivationType activation_type,
- flat::RequestMethod request_method,
- bool disable_generic_rules) const {
+ const flat::UrlRule* FindMatch(
+ base::StringPiece url_string,
+ base::StringPiece document_origin_string,
+ flat::ElementType element_type,
+ flat::ActivationType activation_type,
+ flat::RequestMethod request_method,
+ bool disable_generic_rules,
+ const EmbedderConditionsMatcher& embedder_conditions_matcher =
+ EmbedderConditionsMatcher()) const {
const GURL url(url_string);
const url::Origin document_origin =
testing::GetOrigin(document_origin_string);
return index_matcher_->FindMatch(
url, document_origin, element_type, activation_type, request_method,
testing::IsThirdParty(url, document_origin), disable_generic_rules,
+ embedder_conditions_matcher,
UrlPatternIndexMatcher::FindRuleStrategy::kAny);
}
@@ -124,7 +138,8 @@ class UrlPatternIndexTest : public ::testing::Test {
testing::GetOrigin(document_origin_string);
return index_matcher_->FindAllMatches(
url, document_origin, element_type, activation_type,
- testing::IsThirdParty(url, document_origin), disable_generic_rules);
+ testing::IsThirdParty(url, document_origin), disable_generic_rules,
+ UrlPatternIndexMatcher::EmbedderConditionsMatcher());
}
const flat::UrlRule* FindHighestPriorityMatch(
@@ -133,6 +148,7 @@ class UrlPatternIndexTest : public ::testing::Test {
GURL(url_string), url::Origin(), testing::kOther /*element_type*/,
kNoActivation /*activation_type*/, true /*is_third_party*/,
false /*disable_generic_rules*/,
+ UrlPatternIndexMatcher::EmbedderConditionsMatcher(),
UrlPatternIndexMatcher::FindRuleStrategy::
kHighestPriority /*strategy*/);
}
@@ -985,4 +1001,62 @@ TEST_F(UrlPatternIndexTest, RequestMethod) {
}
}
+TEST_F(UrlPatternIndexTest, EmbedderConditions) {
+ const std::vector<uint8_t> embedder_data_1 = {1, 2, 3};
+ const std::string url_1 = "http://foo.com";
+ AddSimpleUrlRule("foo", 1 /* id */, 0 /* priority */, flat::OptionFlag_ANY,
+ flat::ElementType_ANY, flat::RequestMethod_ANY,
+ embedder_data_1);
+ const std::vector<uint8_t> embedder_data_2 = {4, 5};
+ const std::string url_2 = "http://bar.com";
+ AddSimpleUrlRule("bar", 2 /* id */, 0 /* priority */, flat::OptionFlag_ANY,
+ flat::ElementType_ANY, flat::RequestMethod_ANY,
+ embedder_data_2);
+ Finish();
+
+ EmbedderConditionsMatcher match_first_element_one =
+ base::BindRepeating([](const flatbuffers::Vector<uint8_t>& conditions) {
+ return conditions.size() >= 1 && conditions[0] == 1;
+ });
+ EmbedderConditionsMatcher match_first_element_three =
+ base::BindRepeating([](const flatbuffers::Vector<uint8_t>& conditions) {
+ return conditions.size() >= 1 && conditions[0] == 3;
+ });
+ EmbedderConditionsMatcher match_has_evens =
+ base::BindRepeating([](const flatbuffers::Vector<uint8_t>& conditions) {
+ return base::ranges::any_of(conditions,
+ [](int i) { return i % 2 == 0; });
+ });
+
+ struct {
+ const std::string url;
+ const EmbedderConditionsMatcher matcher;
+ const bool expect_match;
+ // Fields below are valid iff `expect_match` is true.
+ const uint32_t expected_id = 0;
+ const absl::optional<std::vector<uint8_t>> expected_embedder_data;
+ } cases[] = {{url_1, match_first_element_one, true, 1, embedder_data_1},
+ {url_1, match_has_evens, true, 1, embedder_data_1},
+ {url_1, match_first_element_three, false},
+ {url_2, match_first_element_one, false},
+ {url_2, match_has_evens, true, 2, embedder_data_2},
+ {url_2, match_first_element_three, false},
+ {"http://abc.com", match_first_element_one, false}};
+
+ for (size_t i = 0; i < base::size(cases); ++i) {
+ SCOPED_TRACE(::testing::Message() << "Testing case " << i);
+ bool disable_generic_rules = false;
+ const flat::UrlRule* rule = FindMatch(
+ cases[i].url, "", flat::ElementType_OTHER, flat::ActivationType_NONE,
+ flat::RequestMethod_GET, disable_generic_rules, cases[i].matcher);
+ EXPECT_EQ(cases[i].expect_match, !!rule);
+ if (cases[i].expect_match) {
+ EXPECT_EQ(cases[i].expected_id, rule->id());
+ EXPECT_EQ(cases[i].expected_embedder_data,
+ std::vector<uint8_t>(rule->embedder_conditions()->begin(),
+ rule->embedder_conditions()->end()));
+ }
+ }
+}
+
} // namespace url_pattern_index
diff --git a/chromium/components/url_pattern_index/url_rule_test_support.cc b/chromium/components/url_pattern_index/url_rule_test_support.cc
index 5654e15b6e8..ada11a7dbdb 100644
--- a/chromium/components/url_pattern_index/url_rule_test_support.cc
+++ b/chromium/components/url_pattern_index/url_rule_test_support.cc
@@ -5,6 +5,7 @@
#include "components/url_pattern_index/url_rule_test_support.h"
#include "base/check.h"
+#include "base/strings/string_piece.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -23,7 +24,7 @@ proto::UrlRule MakeUrlRule(const UrlPattern& url_pattern) {
rule.set_anchor_left(url_pattern.anchor_left());
rule.set_anchor_right(url_pattern.anchor_right());
rule.set_match_case(url_pattern.match_case());
- rule.set_url_pattern(url_pattern.url_pattern().as_string());
+ rule.set_url_pattern(std::string(url_pattern.url_pattern()));
return rule;
}
diff --git a/chromium/components/url_pattern_index/url_rule_util_unittest.cc b/chromium/components/url_pattern_index/url_rule_util_unittest.cc
index 69337da207f..3e41c2bedc9 100644
--- a/chromium/components/url_pattern_index/url_rule_util_unittest.cc
+++ b/chromium/components/url_pattern_index/url_rule_util_unittest.cc
@@ -10,6 +10,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/strings/string_piece.h"
#include "components/url_pattern_index/flat/url_pattern_index_generated.h"
#include "components/url_pattern_index/url_pattern.h"
#include "components/url_pattern_index/url_pattern_index.h"
@@ -37,7 +38,7 @@ proto::UrlRule MakeProtoRule(proto::RuleSemantics semantics,
rule.set_anchor_left(url_pattern.anchor_left());
rule.set_anchor_right(url_pattern.anchor_right());
rule.set_match_case(url_pattern.match_case());
- rule.set_url_pattern(url_pattern.url_pattern().as_string());
+ rule.set_url_pattern(std::string(url_pattern.url_pattern()));
testing::AddDomains(domains, &rule);
diff --git a/chromium/components/user_manager/BUILD.gn b/chromium/components/user_manager/BUILD.gn
index cb3bd2acedd..3aae83e1f36 100644
--- a/chromium/components/user_manager/BUILD.gn
+++ b/chromium/components/user_manager/BUILD.gn
@@ -71,10 +71,17 @@ if (is_chromeos_ash) {
source_set("unit_tests") {
testonly = true
- sources = [ "user_unittest.cc" ]
+ sources = [
+ "known_user_unittest.cc",
+ "user_unittest.cc",
+ ]
deps = [
+ ":test_support",
":user_manager",
+ "//base/test:test_support",
"//components/account_id",
+ "//components/prefs:test_support",
+ "//testing/gmock",
"//testing/gtest",
]
}
diff --git a/chromium/components/user_manager/fake_user_manager.cc b/chromium/components/user_manager/fake_user_manager.cc
index a28dd1bcdcc..0ba57ff3125 100644
--- a/chromium/components/user_manager/fake_user_manager.cc
+++ b/chromium/components/user_manager/fake_user_manager.cc
@@ -10,6 +10,7 @@
#include "ash/constants/ash_switches.h"
#include "base/callback.h"
#include "base/command_line.h"
+#include "base/containers/contains.h"
#include "base/single_thread_task_runner.h"
#include "base/system/sys_info.h"
#include "components/user_manager/user_names.h"
@@ -125,6 +126,16 @@ void FakeUserManager::LogoutAllUsers() {
active_user_ = nullptr;
}
+void FakeUserManager::SetUserNonCryptohomeDataEphemeral(
+ const AccountId& account_id,
+ bool is_ephemeral) {
+ if (is_ephemeral) {
+ accounts_with_ephemeral_non_cryptohome_data_.insert(account_id);
+ } else {
+ accounts_with_ephemeral_non_cryptohome_data_.erase(account_id);
+ }
+}
+
void FakeUserManager::UserLoggedIn(const AccountId& account_id,
const std::string& username_hash,
bool browser_restart,
@@ -295,7 +306,8 @@ bool FakeUserManager::IsLoggedInAsStub() const {
bool FakeUserManager::IsUserNonCryptohomeDataEphemeral(
const AccountId& account_id) const {
- return false;
+ return base::Contains(accounts_with_ephemeral_non_cryptohome_data_,
+ account_id);
}
bool FakeUserManager::IsGuestSessionAllowed() const {
diff --git a/chromium/components/user_manager/fake_user_manager.h b/chromium/components/user_manager/fake_user_manager.h
index 66ce963af4b..99edb9348c0 100644
--- a/chromium/components/user_manager/fake_user_manager.h
+++ b/chromium/components/user_manager/fake_user_manager.h
@@ -41,6 +41,11 @@ class USER_MANAGER_EXPORT FakeUserManager : public UserManagerBase {
void LogoutAllUsers();
+ // Subsequent calls to IsCurrentUserNonCryptohomeDataEphemeral for
+ // |account_id| will return |is_ephemeral|.
+ void SetUserNonCryptohomeDataEphemeral(const AccountId& account_id,
+ bool is_ephemeral);
+
void set_local_state(PrefService* local_state) { local_state_ = local_state; }
void set_is_current_user_new(bool is_current_user_new) {
is_current_user_new_ = is_current_user_new;
@@ -171,6 +176,10 @@ class USER_MANAGER_EXPORT FakeUserManager : public UserManagerBase {
bool is_current_user_owner_ = false;
bool is_current_user_new_ = false;
+ // Contains AccountIds for which IsCurrentUserNonCryptohomeDataEphemeral will
+ // return true.
+ std::set<AccountId> accounts_with_ephemeral_non_cryptohome_data_;
+
DISALLOW_COPY_AND_ASSIGN(FakeUserManager);
};
diff --git a/chromium/components/user_manager/known_user.cc b/chromium/components/user_manager/known_user.cc
index e34ed8cf075..783d96a5b2c 100644
--- a/chromium/components/user_manager/known_user.cc
+++ b/chromium/components/user_manager/known_user.cc
@@ -21,7 +21,6 @@
#include "google_apis/gaia/gaia_auth_util.h"
namespace user_manager {
-namespace known_user {
namespace {
// A vector pref of preferences of known users. All new preferences should be
@@ -29,7 +28,7 @@ namespace {
const char kKnownUsers[] = "KnownUsers";
// Known user preferences keys (stored in Local State). All keys should be
-// listed in kReservedKeys below.
+// listed in kReservedKeys or kObsoleteKeys below.
// Key of canonical e-mail value.
const char kCanonicalEmail[] = "email";
@@ -62,8 +61,9 @@ const char kReauthReasonKey[] = "reauth_reason";
const char kGaiaIdMigration[] = "gaia_id_migration";
// Key of the boolean flag telling if a minimal user home migration has been
-// attempted.
-const char kMinimalMigrationAttempted[] = "minimal_migration_attempted";
+// attempted. This flag is not used since M88 and is only kept here to be able
+// to remove it from existing entries.
+const char kMinimalMigrationAttemptedObsolete[] = "minimal_migration_attempted";
// Key of the boolean flag telling if user session requires policy.
const char kProfileRequiresPolicy[] = "profile_requires_policy";
@@ -109,7 +109,6 @@ const char* kReservedKeys[] = {kCanonicalEmail,
kGAPSCookie,
kReauthReasonKey,
kGaiaIdMigration,
- kMinimalMigrationAttempted,
kProfileRequiresPolicy,
kIsEphemeral,
kChallengeResponseKeys,
@@ -122,7 +121,13 @@ const char* kReservedKeys[] = {kCanonicalEmail,
kPinAutosubmitBackfillNeeded,
kPasswordSyncToken};
-PrefService* GetLocalState() {
+// List containing all known user preference keys that used to be reserved and
+// are now obsolete.
+const char* kObsoleteKeys[] = {
+ kMinimalMigrationAttemptedObsolete,
+};
+
+PrefService* GetLocalStateLegacy() {
if (!UserManager::IsInitialized())
return nullptr;
@@ -140,6 +145,8 @@ bool UserMatches(const AccountId& account_id,
}
// TODO(alemate): update code once user id is really a struct.
+ // TODO(https://crbug.com/1190902): If the gaia id or GUID doesn't match,
+ // this function should likely be returning false even if the e-mail matches.
switch (account_id.GetAccountType()) {
case AccountType::GOOGLE: {
bool has_gaia_id = dict.GetString(kGAIAIdKey, &value);
@@ -185,29 +192,16 @@ void UpdateIdentity(const AccountId& account_id, base::DictionaryValue& dict) {
AccountId::AccountTypeToString(account_id.GetAccountType()));
}
-void ClearPref(const AccountId& account_id, const std::string& path) {
- const base::DictionaryValue* user_pref_dict = nullptr;
- if (!FindPrefs(account_id, &user_pref_dict))
- return;
-
- base::Value updated_user_pref = user_pref_dict->Clone();
- base::DictionaryValue* updated_user_pref_dict;
- updated_user_pref.GetAsDictionary(&updated_user_pref_dict);
-
- updated_user_pref_dict->RemovePath(path);
- UpdatePrefs(account_id, *updated_user_pref_dict, true);
-}
-
} // namespace
-bool FindPrefs(const AccountId& account_id,
- const base::DictionaryValue** out_value) {
- PrefService* local_state = GetLocalState();
+KnownUser::KnownUser(PrefService* local_state) : local_state_(local_state) {
+ DCHECK(local_state);
+}
- // Local State may not be initialized in tests.
- if (!local_state)
- return false;
+KnownUser::~KnownUser() = default;
+bool KnownUser::FindPrefs(const AccountId& account_id,
+ const base::DictionaryValue** out_value) {
// UserManager is usually NULL in unit tests.
if (account_id.GetAccountType() != AccountType::ACTIVE_DIRECTORY &&
UserManager::IsInitialized() &&
@@ -218,7 +212,7 @@ bool FindPrefs(const AccountId& account_id,
if (!account_id.is_valid())
return false;
- const base::ListValue* known_users = local_state->GetList(kKnownUsers);
+ const base::ListValue* known_users = local_state_->GetList(kKnownUsers);
for (size_t i = 0; i < known_users->GetSize(); ++i) {
const base::DictionaryValue* element = nullptr;
if (known_users->GetDictionary(i, &element)) {
@@ -231,15 +225,9 @@ bool FindPrefs(const AccountId& account_id,
return false;
}
-void UpdatePrefs(const AccountId& account_id,
- const base::DictionaryValue& values,
- bool clear) {
- PrefService* local_state = GetLocalState();
-
- // Local State may not be initialized in tests.
- if (!local_state)
- return;
-
+void KnownUser::UpdatePrefs(const AccountId& account_id,
+ const base::DictionaryValue& values,
+ bool clear) {
// UserManager is usually NULL in unit tests.
if (account_id.GetAccountType() != AccountType::ACTIVE_DIRECTORY &&
UserManager::IsInitialized() &&
@@ -250,7 +238,7 @@ void UpdatePrefs(const AccountId& account_id,
if (!account_id.is_valid())
return;
- ListPrefUpdate update(local_state, kKnownUsers);
+ ListPrefUpdate update(local_state_, kKnownUsers);
for (size_t i = 0; i < update->GetSize(); ++i) {
base::DictionaryValue* element = nullptr;
if (update->GetDictionary(i, &element)) {
@@ -269,9 +257,9 @@ void UpdatePrefs(const AccountId& account_id,
update->Append(std::move(new_value));
}
-bool GetStringPref(const AccountId& account_id,
- const std::string& path,
- std::string* out_value) {
+bool KnownUser::GetStringPref(const AccountId& account_id,
+ const std::string& path,
+ std::string* out_value) {
const base::DictionaryValue* user_pref_dict = nullptr;
if (!FindPrefs(account_id, &user_pref_dict))
return false;
@@ -279,17 +267,17 @@ bool GetStringPref(const AccountId& account_id,
return user_pref_dict->GetString(path, out_value);
}
-void SetStringPref(const AccountId& account_id,
- const std::string& path,
- const std::string& in_value) {
+void KnownUser::SetStringPref(const AccountId& account_id,
+ const std::string& path,
+ const std::string& in_value) {
base::DictionaryValue dict;
dict.SetString(path, in_value);
UpdatePrefs(account_id, dict, false);
}
-bool GetBooleanPref(const AccountId& account_id,
- const std::string& path,
- bool* out_value) {
+bool KnownUser::GetBooleanPref(const AccountId& account_id,
+ const std::string& path,
+ bool* out_value) {
const base::DictionaryValue* user_pref_dict = nullptr;
if (!FindPrefs(account_id, &user_pref_dict))
return false;
@@ -297,34 +285,34 @@ bool GetBooleanPref(const AccountId& account_id,
return user_pref_dict->GetBoolean(path, out_value);
}
-void SetBooleanPref(const AccountId& account_id,
- const std::string& path,
- const bool in_value) {
+void KnownUser::SetBooleanPref(const AccountId& account_id,
+ const std::string& path,
+ const bool in_value) {
base::DictionaryValue dict;
dict.SetBoolean(path, in_value);
UpdatePrefs(account_id, dict, false);
}
-bool GetIntegerPref(const AccountId& account_id,
- const std::string& path,
- int* out_value) {
+bool KnownUser::GetIntegerPref(const AccountId& account_id,
+ const std::string& path,
+ int* out_value) {
const base::DictionaryValue* user_pref_dict = nullptr;
if (!FindPrefs(account_id, &user_pref_dict))
return false;
return user_pref_dict->GetInteger(path, out_value);
}
-void SetIntegerPref(const AccountId& account_id,
- const std::string& path,
- const int in_value) {
+void KnownUser::SetIntegerPref(const AccountId& account_id,
+ const std::string& path,
+ const int in_value) {
base::DictionaryValue dict;
dict.SetInteger(path, in_value);
UpdatePrefs(account_id, dict, false);
}
-bool GetPref(const AccountId& account_id,
- const std::string& path,
- const base::Value** out_value) {
+bool KnownUser::GetPref(const AccountId& account_id,
+ const std::string& path,
+ const base::Value** out_value) {
const base::DictionaryValue* user_pref_dict = nullptr;
if (!FindPrefs(account_id, &user_pref_dict))
return false;
@@ -333,15 +321,16 @@ bool GetPref(const AccountId& account_id,
return *out_value != nullptr;
}
-void SetPref(const AccountId& account_id,
- const std::string& path,
- base::Value in_value) {
+void KnownUser::SetPref(const AccountId& account_id,
+ const std::string& path,
+ base::Value in_value) {
base::DictionaryValue dict;
dict.SetPath(path, std::move(in_value));
UpdatePrefs(account_id, dict, false);
}
-void RemovePref(const AccountId& account_id, const std::string& path) {
+void KnownUser::RemovePref(const AccountId& account_id,
+ const std::string& path) {
// Prevent removing keys that are used internally.
for (const std::string& key : kReservedKeys)
CHECK_NE(path, key);
@@ -349,9 +338,9 @@ void RemovePref(const AccountId& account_id, const std::string& path) {
ClearPref(account_id, path);
}
-AccountId GetAccountId(const std::string& user_email,
- const std::string& id,
- const AccountType& account_type) {
+AccountId KnownUser::GetAccountId(const std::string& user_email,
+ const std::string& id,
+ const AccountType& account_type) {
DCHECK((id.empty() && account_type == AccountType::UNKNOWN) ||
(!id.empty() && account_type != AccountType::UNKNOWN));
// In tests empty accounts are possible.
@@ -422,15 +411,10 @@ AccountId GetAccountId(const std::string& user_email,
return EmptyAccountId();
}
-std::vector<AccountId> GetKnownAccountIds() {
+std::vector<AccountId> KnownUser::GetKnownAccountIds() {
std::vector<AccountId> result;
- PrefService* local_state = GetLocalState();
- // Local State may not be initialized in tests.
- if (!local_state)
- return result;
-
- const base::ListValue* known_users = local_state->GetList(kKnownUsers);
+ const base::ListValue* known_users = local_state_->GetList(kKnownUsers);
for (size_t i = 0; i < known_users->GetSize(); ++i) {
const base::DictionaryValue* element = nullptr;
if (known_users->GetDictionary(i, &element)) {
@@ -465,8 +449,8 @@ std::vector<AccountId> GetKnownAccountIds() {
return result;
}
-bool GetGaiaIdMigrationStatus(const AccountId& account_id,
- const std::string& subsystem) {
+bool KnownUser::GetGaiaIdMigrationStatus(const AccountId& account_id,
+ const std::string& subsystem) {
bool migrated = false;
if (GetBooleanPref(account_id,
@@ -478,13 +462,13 @@ bool GetGaiaIdMigrationStatus(const AccountId& account_id,
return false;
}
-void SetGaiaIdMigrationStatusDone(const AccountId& account_id,
- const std::string& subsystem) {
+void KnownUser::SetGaiaIdMigrationStatusDone(const AccountId& account_id,
+ const std::string& subsystem) {
SetBooleanPref(account_id, std::string(kGaiaIdMigration) + "." + subsystem,
true);
}
-void SaveKnownUser(const AccountId& account_id) {
+void KnownUser::SaveKnownUser(const AccountId& account_id) {
const bool is_ephemeral =
UserManager::IsInitialized() &&
UserManager::Get()->IsUserNonCryptohomeDataEphemeral(account_id);
@@ -493,22 +477,24 @@ void SaveKnownUser(const AccountId& account_id) {
return;
}
UpdateId(account_id);
- GetLocalState()->CommitPendingWrite();
+ local_state_->CommitPendingWrite();
}
-void SetIsEphemeralUser(const AccountId& account_id, bool is_ephemeral) {
+void KnownUser::SetIsEphemeralUser(const AccountId& account_id,
+ bool is_ephemeral) {
if (account_id.GetAccountType() != AccountType::ACTIVE_DIRECTORY)
return;
SetBooleanPref(account_id, kIsEphemeral, is_ephemeral);
}
-void UpdateGaiaID(const AccountId& account_id, const std::string& gaia_id) {
+void KnownUser::UpdateGaiaID(const AccountId& account_id,
+ const std::string& gaia_id) {
SetStringPref(account_id, kGAIAIdKey, gaia_id);
SetStringPref(account_id, kAccountTypeKey,
AccountId::AccountTypeToString(AccountType::GOOGLE));
}
-void UpdateId(const AccountId& account_id) {
+void KnownUser::UpdateId(const AccountId& account_id) {
switch (account_id.GetAccountType()) {
case AccountType::GOOGLE:
SetStringPref(account_id, kGAIAIdKey, account_id.GetGaiaId());
@@ -523,11 +509,13 @@ void UpdateId(const AccountId& account_id) {
AccountId::AccountTypeToString(account_id.GetAccountType()));
}
-bool FindGaiaID(const AccountId& account_id, std::string* out_value) {
+bool KnownUser::FindGaiaID(const AccountId& account_id,
+ std::string* out_value) {
return GetStringPref(account_id, kGAIAIdKey, out_value);
}
-void SetDeviceId(const AccountId& account_id, const std::string& device_id) {
+void KnownUser::SetDeviceId(const AccountId& account_id,
+ const std::string& device_id) {
const std::string known_device_id = GetDeviceId(account_id);
if (!known_device_id.empty() && device_id != known_device_id) {
NOTREACHED() << "Trying to change device ID for known user.";
@@ -535,7 +523,7 @@ void SetDeviceId(const AccountId& account_id, const std::string& device_id) {
SetStringPref(account_id, kDeviceId, device_id);
}
-std::string GetDeviceId(const AccountId& account_id) {
+std::string KnownUser::GetDeviceId(const AccountId& account_id) {
std::string device_id;
if (GetStringPref(account_id, kDeviceId, &device_id)) {
return device_id;
@@ -543,12 +531,12 @@ std::string GetDeviceId(const AccountId& account_id) {
return std::string();
}
-void SetGAPSCookie(const AccountId& account_id,
- const std::string& gaps_cookie) {
+void KnownUser::SetGAPSCookie(const AccountId& account_id,
+ const std::string& gaps_cookie) {
SetStringPref(account_id, kGAPSCookie, gaps_cookie);
}
-std::string GetGAPSCookie(const AccountId& account_id) {
+std::string KnownUser::GetGAPSCookie(const AccountId& account_id) {
std::string gaps_cookie;
if (GetStringPref(account_id, kGAPSCookie, &gaps_cookie)) {
return gaps_cookie;
@@ -556,26 +544,26 @@ std::string GetGAPSCookie(const AccountId& account_id) {
return std::string();
}
-void UpdateUsingSAML(const AccountId& account_id, const bool using_saml) {
+void KnownUser::UpdateUsingSAML(const AccountId& account_id,
+ const bool using_saml) {
SetBooleanPref(account_id, kUsingSAMLKey, using_saml);
}
-bool IsUsingSAML(const AccountId& account_id) {
+bool KnownUser::IsUsingSAML(const AccountId& account_id) {
bool using_saml;
if (GetBooleanPref(account_id, kUsingSAMLKey, &using_saml))
return using_saml;
return false;
}
-void USER_MANAGER_EXPORT
-UpdateIsUsingSAMLPrincipalsAPI(const AccountId& account_id,
- bool is_using_saml_principals_api) {
+void KnownUser::UpdateIsUsingSAMLPrincipalsAPI(
+ const AccountId& account_id,
+ bool is_using_saml_principals_api) {
SetBooleanPref(account_id, kIsUsingSAMLPrincipalsAPI,
is_using_saml_principals_api);
}
-bool USER_MANAGER_EXPORT
-GetIsUsingSAMLPrincipalsAPI(const AccountId& account_id) {
+bool KnownUser::GetIsUsingSAMLPrincipalsAPI(const AccountId& account_id) {
bool is_using_saml_principals_api;
if (GetBooleanPref(account_id, kIsUsingSAMLPrincipalsAPI,
&is_using_saml_principals_api)) {
@@ -584,14 +572,15 @@ GetIsUsingSAMLPrincipalsAPI(const AccountId& account_id) {
return false;
}
-void SetProfileRequiresPolicy(const AccountId& account_id,
- ProfileRequiresPolicy required) {
+void KnownUser::SetProfileRequiresPolicy(const AccountId& account_id,
+ ProfileRequiresPolicy required) {
DCHECK_NE(required, ProfileRequiresPolicy::kUnknown);
SetBooleanPref(account_id, kProfileRequiresPolicy,
required == ProfileRequiresPolicy::kPolicyRequired);
}
-ProfileRequiresPolicy GetProfileRequiresPolicy(const AccountId& account_id) {
+ProfileRequiresPolicy KnownUser::GetProfileRequiresPolicy(
+ const AccountId& account_id) {
bool requires_policy;
if (GetBooleanPref(account_id, kProfileRequiresPolicy, &requires_policy)) {
return requires_policy ? ProfileRequiresPolicy::kPolicyRequired
@@ -600,64 +589,50 @@ ProfileRequiresPolicy GetProfileRequiresPolicy(const AccountId& account_id) {
return ProfileRequiresPolicy::kUnknown;
}
-void ClearProfileRequiresPolicy(const AccountId& account_id) {
+void KnownUser::ClearProfileRequiresPolicy(const AccountId& account_id) {
ClearPref(account_id, kProfileRequiresPolicy);
}
-void UpdateReauthReason(const AccountId& account_id, const int reauth_reason) {
+void KnownUser::UpdateReauthReason(const AccountId& account_id,
+ const int reauth_reason) {
SetIntegerPref(account_id, kReauthReasonKey, reauth_reason);
}
-bool FindReauthReason(const AccountId& account_id, int* out_value) {
+bool KnownUser::FindReauthReason(const AccountId& account_id, int* out_value) {
return GetIntegerPref(account_id, kReauthReasonKey, out_value);
}
-bool WasUserHomeMinimalMigrationAttempted(const AccountId& account_id) {
- bool minimal_migration_attempted;
- const bool pref_set = GetBooleanPref(account_id, kMinimalMigrationAttempted,
- &minimal_migration_attempted);
- if (pref_set)
- return minimal_migration_attempted;
-
- // If we haven't recorded that a minimal migration has been attempted, assume
- // no.
- return false;
-}
-
-void SetUserHomeMinimalMigrationAttempted(const AccountId& account_id,
- bool minimal_migration_attempted) {
- SetBooleanPref(account_id, kMinimalMigrationAttempted,
- minimal_migration_attempted);
-}
-
-void SetChallengeResponseKeys(const AccountId& account_id, base::Value value) {
+void KnownUser::SetChallengeResponseKeys(const AccountId& account_id,
+ base::Value value) {
DCHECK(value.is_list());
SetPref(account_id, kChallengeResponseKeys, std::move(value));
}
-base::Value GetChallengeResponseKeys(const AccountId& account_id) {
+base::Value KnownUser::GetChallengeResponseKeys(const AccountId& account_id) {
const base::Value* value = nullptr;
if (!GetPref(account_id, kChallengeResponseKeys, &value) || !value->is_list())
return base::Value();
return value->Clone();
}
-void SetLastOnlineSignin(const AccountId& account_id, base::Time time) {
+void KnownUser::SetLastOnlineSignin(const AccountId& account_id,
+ base::Time time) {
SetPref(account_id, kLastOnlineSignin, util::TimeToValue(time));
}
-base::Time GetLastOnlineSignin(const AccountId& account_id) {
+base::Time KnownUser::GetLastOnlineSignin(const AccountId& account_id) {
const base::Value* value = nullptr;
if (!GetPref(account_id, kLastOnlineSignin, &value))
return base::Time();
- base::Optional<base::Time> time = util::ValueToTime(value);
+ absl::optional<base::Time> time = util::ValueToTime(value);
if (!time)
return base::Time();
return *time;
}
-void SetOfflineSigninLimit(const AccountId& account_id,
- base::Optional<base::TimeDelta> time_delta) {
+void KnownUser::SetOfflineSigninLimit(
+ const AccountId& account_id,
+ absl::optional<base::TimeDelta> time_delta) {
if (!time_delta) {
ClearPref(account_id, kOfflineSigninLimit);
} else {
@@ -666,58 +641,59 @@ void SetOfflineSigninLimit(const AccountId& account_id,
}
}
-base::Optional<base::TimeDelta> GetOfflineSigninLimit(
+absl::optional<base::TimeDelta> KnownUser::GetOfflineSigninLimit(
const AccountId& account_id) {
const base::Value* value = nullptr;
if (!GetPref(account_id, kOfflineSigninLimit, &value))
- return base::nullopt;
- base::Optional<base::TimeDelta> time_delta = util::ValueToTimeDelta(value);
+ return absl::nullopt;
+ absl::optional<base::TimeDelta> time_delta = util::ValueToTimeDelta(value);
return time_delta;
}
-void SetIsEnterpriseManaged(const AccountId& account_id,
- bool is_enterprise_managed) {
+void KnownUser::SetIsEnterpriseManaged(const AccountId& account_id,
+ bool is_enterprise_managed) {
SetBooleanPref(account_id, kIsEnterpriseManaged, is_enterprise_managed);
}
-bool GetIsEnterpriseManaged(const AccountId& account_id) {
+bool KnownUser::GetIsEnterpriseManaged(const AccountId& account_id) {
bool is_enterprise_managed;
if (GetBooleanPref(account_id, kIsEnterpriseManaged, &is_enterprise_managed))
return is_enterprise_managed;
return false;
}
-void SetAccountManager(const AccountId& account_id,
- const std::string& manager) {
+void KnownUser::SetAccountManager(const AccountId& account_id,
+ const std::string& manager) {
SetStringPref(account_id, kAccountManager, manager);
}
-bool GetAccountManager(const AccountId& account_id, std::string* manager) {
+bool KnownUser::GetAccountManager(const AccountId& account_id,
+ std::string* manager) {
return GetStringPref(account_id, kAccountManager, manager);
}
-void SetUserLastLoginInputMethod(const AccountId& account_id,
- const std::string& input_method) {
+void KnownUser::SetUserLastLoginInputMethod(const AccountId& account_id,
+ const std::string& input_method) {
SetStringPref(account_id, kLastInputMethod, input_method);
}
-bool GetUserLastInputMethod(const AccountId& account_id,
- std::string* input_method) {
+bool KnownUser::GetUserLastInputMethod(const AccountId& account_id,
+ std::string* input_method) {
return GetStringPref(account_id, kLastInputMethod, input_method);
}
-void SetUserPinLength(const AccountId& account_id, int pin_length) {
+void KnownUser::SetUserPinLength(const AccountId& account_id, int pin_length) {
SetIntegerPref(account_id, kPinAutosubmitLength, pin_length);
}
-int GetUserPinLength(const AccountId& account_id) {
+int KnownUser::GetUserPinLength(const AccountId& account_id) {
int pin_length = 0;
if (GetIntegerPref(account_id, kPinAutosubmitLength, &pin_length))
return pin_length;
return 0;
}
-bool PinAutosubmitIsBackfillNeeded(const AccountId& account_id) {
+bool KnownUser::PinAutosubmitIsBackfillNeeded(const AccountId& account_id) {
bool backfill_needed;
if (GetBooleanPref(account_id, kPinAutosubmitBackfillNeeded,
&backfill_needed))
@@ -726,20 +702,21 @@ bool PinAutosubmitIsBackfillNeeded(const AccountId& account_id) {
return true;
}
-void PinAutosubmitSetBackfillNotNeeded(const AccountId& account_id) {
+void KnownUser::PinAutosubmitSetBackfillNotNeeded(const AccountId& account_id) {
SetBooleanPref(account_id, kPinAutosubmitBackfillNeeded, false);
}
-void PinAutosubmitSetBackfillNeededForTests(const AccountId& account_id) {
+void KnownUser::PinAutosubmitSetBackfillNeededForTests(
+ const AccountId& account_id) {
SetBooleanPref(account_id, kPinAutosubmitBackfillNeeded, true);
}
-void SetPasswordSyncToken(const AccountId& account_id,
- const std::string& token) {
+void KnownUser::SetPasswordSyncToken(const AccountId& account_id,
+ const std::string& token) {
SetStringPref(account_id, kPasswordSyncToken, token);
}
-std::string GetPasswordSyncToken(const AccountId& account_id) {
+std::string KnownUser::GetPasswordSyncToken(const AccountId& account_id) {
std::string token;
if (GetStringPref(account_id, kPasswordSyncToken, &token))
return token;
@@ -747,17 +724,25 @@ std::string GetPasswordSyncToken(const AccountId& account_id) {
return std::string();
}
-void RemovePrefs(const AccountId& account_id) {
- PrefService* local_state = GetLocalState();
-
- // Local State may not be initialized in tests.
- if (!local_state)
+void KnownUser::ClearPref(const AccountId& account_id,
+ const std::string& path) {
+ const base::DictionaryValue* user_pref_dict = nullptr;
+ if (!FindPrefs(account_id, &user_pref_dict))
return;
+ base::Value updated_user_pref = user_pref_dict->Clone();
+ base::DictionaryValue* updated_user_pref_dict;
+ updated_user_pref.GetAsDictionary(&updated_user_pref_dict);
+
+ updated_user_pref_dict->RemovePath(path);
+ UpdatePrefs(account_id, *updated_user_pref_dict, true);
+}
+
+void KnownUser::RemovePrefs(const AccountId& account_id) {
if (!account_id.is_valid())
return;
- ListPrefUpdate update(local_state, kKnownUsers);
+ ListPrefUpdate update(local_state_, kKnownUsers);
for (size_t i = 0; i < update->GetSize(); ++i) {
base::DictionaryValue* element = nullptr;
if (update->GetDictionary(i, &element)) {
@@ -769,26 +754,520 @@ void RemovePrefs(const AccountId& account_id) {
}
}
-void CleanEphemeralUsers() {
- PrefService* local_state = GetLocalState();
-
- // Local State may not be initialized in tests.
- if (!local_state)
- return;
-
- ListPrefUpdate update(local_state, kKnownUsers);
+void KnownUser::CleanEphemeralUsers() {
+ ListPrefUpdate update(local_state_, kKnownUsers);
update->EraseListValueIf([](const auto& value) {
if (!value.is_dict())
return false;
- base::Optional<bool> is_ephemeral = value.FindBoolKey(kIsEphemeral);
+ absl::optional<bool> is_ephemeral = value.FindBoolKey(kIsEphemeral);
return is_ephemeral && *is_ephemeral;
});
}
-void RegisterPrefs(PrefRegistrySimple* registry) {
+void KnownUser::CleanObsoletePrefs() {
+ ListPrefUpdate update(local_state_, kKnownUsers);
+ for (base::Value& user_entry : update.Get()->GetList()) {
+ if (!user_entry.is_dict())
+ continue;
+ for (const std::string& key : kObsoleteKeys)
+ user_entry.RemoveKey(key);
+ }
+}
+
+// static
+void KnownUser::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterListPref(kKnownUsers);
}
+// --- Legacy interface ---
+namespace known_user {
+
+bool FindPrefs(const AccountId& account_id,
+ const base::DictionaryValue** out_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).FindPrefs(account_id, out_value);
+}
+
+void UpdatePrefs(const AccountId& account_id,
+ const base::DictionaryValue& values,
+ bool clear) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).UpdatePrefs(account_id, values, clear);
+}
+
+bool GetStringPref(const AccountId& account_id,
+ const std::string& path,
+ std::string* out_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).GetStringPref(account_id, path, out_value);
+}
+
+void SetStringPref(const AccountId& account_id,
+ const std::string& path,
+ const std::string& in_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetStringPref(account_id, path, in_value);
+}
+
+bool GetBooleanPref(const AccountId& account_id,
+ const std::string& path,
+ bool* out_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).GetBooleanPref(account_id, path, out_value);
+}
+
+void SetBooleanPref(const AccountId& account_id,
+ const std::string& path,
+ const bool in_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetBooleanPref(account_id, path, in_value);
+}
+
+bool GetIntegerPref(const AccountId& account_id,
+ const std::string& path,
+ int* out_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).GetIntegerPref(account_id, path, out_value);
+}
+
+void SetIntegerPref(const AccountId& account_id,
+ const std::string& path,
+ const int in_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetIntegerPref(account_id, path, in_value);
+}
+
+bool GetPref(const AccountId& account_id,
+ const std::string& path,
+ const base::Value** out_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).GetPref(account_id, path, out_value);
+}
+
+void SetPref(const AccountId& account_id,
+ const std::string& path,
+ base::Value in_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetPref(account_id, path, std::move(in_value));
+}
+
+void RemovePref(const AccountId& account_id, const std::string& path) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).RemovePref(account_id, path);
+}
+
+AccountId GetAccountId(const std::string& user_email,
+ const std::string& id,
+ const AccountType& account_type) {
+ DCHECK((id.empty() && account_type == AccountType::UNKNOWN) ||
+ (!id.empty() && account_type != AccountType::UNKNOWN));
+ PrefService* local_state = GetLocalStateLegacy();
+ if (local_state) {
+ return KnownUser(local_state).GetAccountId(user_email, id, account_type);
+ }
+
+ // The handling of the local-state-not-initialized case is pretty complex - it
+ // is KnownUser::GetAccountId with all queries assuming to return false.
+ // This should be come unnecessary when all callers are migrated to the
+ // KnownUser class interface (https://crbug.com/1150434) and thus responsible
+ // to pass a valid |local_state| pointer.
+
+ // In tests empty accounts are possible.
+ if (user_email.empty() && id.empty() &&
+ account_type == AccountType::UNKNOWN) {
+ return EmptyAccountId();
+ }
+ AccountId result(EmptyAccountId());
+ // UserManager is usually NULL in unit tests.
+ if (account_type == AccountType::UNKNOWN && UserManager::IsInitialized() &&
+ UserManager::Get()->GetPlatformKnownUserId(user_email, id, &result)) {
+ return result;
+ }
+ const std::string sanitized_email =
+ user_email.empty()
+ ? std::string()
+ : gaia::CanonicalizeEmail(gaia::SanitizeEmail(user_email));
+ std::string stored_email;
+ switch (account_type) {
+ case AccountType::GOOGLE:
+ return AccountId::FromUserEmailGaiaId(sanitized_email, id);
+ case AccountType::ACTIVE_DIRECTORY:
+ return AccountId::AdFromUserEmailObjGuid(sanitized_email, id);
+ case AccountType::UNKNOWN:
+ return AccountId::FromUserEmail(sanitized_email);
+ }
+ NOTREACHED();
+ return EmptyAccountId();
+}
+
+std::vector<AccountId> GetKnownAccountIds() {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return {};
+ return KnownUser(local_state).GetKnownAccountIds();
+}
+
+bool GetGaiaIdMigrationStatus(const AccountId& account_id,
+ const std::string& subsystem) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).GetGaiaIdMigrationStatus(account_id, subsystem);
+}
+
+void SetGaiaIdMigrationStatusDone(const AccountId& account_id,
+ const std::string& subsystem) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state)
+ .SetGaiaIdMigrationStatusDone(account_id, subsystem);
+}
+
+void SaveKnownUser(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SaveKnownUser(account_id);
+}
+
+void UpdateGaiaID(const AccountId& account_id, const std::string& gaia_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).UpdateGaiaID(account_id, gaia_id);
+}
+
+void UpdateId(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).UpdateId(account_id);
+}
+
+bool FindGaiaID(const AccountId& account_id, std::string* out_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).FindGaiaID(account_id, out_value);
+}
+
+void SetDeviceId(const AccountId& account_id, const std::string& device_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetDeviceId(account_id, device_id);
+}
+
+std::string GetDeviceId(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return std::string();
+ return KnownUser(local_state).GetDeviceId(account_id);
+}
+
+void SetGAPSCookie(const AccountId& account_id,
+ const std::string& gaps_cookie) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetGAPSCookie(account_id, gaps_cookie);
+}
+
+std::string GetGAPSCookie(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return std::string();
+ return KnownUser(local_state).GetGAPSCookie(account_id);
+}
+
+void UpdateUsingSAML(const AccountId& account_id, const bool using_saml) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).UpdateUsingSAML(account_id, using_saml);
+}
+
+bool IsUsingSAML(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).IsUsingSAML(account_id);
+}
+
+void USER_MANAGER_EXPORT
+UpdateIsUsingSAMLPrincipalsAPI(const AccountId& account_id,
+ bool is_using_saml_principals_api) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state)
+ .UpdateIsUsingSAMLPrincipalsAPI(account_id, is_using_saml_principals_api);
+}
+
+bool USER_MANAGER_EXPORT
+GetIsUsingSAMLPrincipalsAPI(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).GetIsUsingSAMLPrincipalsAPI(account_id);
+}
+
+void SetProfileRequiresPolicy(const AccountId& account_id,
+ ProfileRequiresPolicy required) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetProfileRequiresPolicy(account_id, required);
+}
+
+ProfileRequiresPolicy GetProfileRequiresPolicy(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return ProfileRequiresPolicy::kUnknown;
+ return KnownUser(local_state).GetProfileRequiresPolicy(account_id);
+}
+
+void ClearProfileRequiresPolicy(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).ClearProfileRequiresPolicy(account_id);
+}
+
+void UpdateReauthReason(const AccountId& account_id, const int reauth_reason) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).UpdateReauthReason(account_id, reauth_reason);
+}
+
+bool FindReauthReason(const AccountId& account_id, int* out_value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).FindReauthReason(account_id, out_value);
+}
+
+void SetChallengeResponseKeys(const AccountId& account_id, base::Value value) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state)
+ .SetChallengeResponseKeys(account_id, std::move(value));
+}
+
+base::Value GetChallengeResponseKeys(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return base::Value();
+ return KnownUser(local_state).GetChallengeResponseKeys(account_id);
+}
+
+void SetLastOnlineSignin(const AccountId& account_id, base::Time time) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetLastOnlineSignin(account_id, time);
+}
+
+base::Time GetLastOnlineSignin(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return base::Time();
+ return KnownUser(local_state).GetLastOnlineSignin(account_id);
+}
+
+void SetOfflineSigninLimit(const AccountId& account_id,
+ absl::optional<base::TimeDelta> time_delta) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetOfflineSigninLimit(account_id, time_delta);
+}
+
+absl::optional<base::TimeDelta> GetOfflineSigninLimit(
+ const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return absl::nullopt;
+ return KnownUser(local_state).GetOfflineSigninLimit(account_id);
+}
+
+void SetIsEnterpriseManaged(const AccountId& account_id,
+ bool is_enterprise_managed) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state)
+ .SetIsEnterpriseManaged(account_id, is_enterprise_managed);
+}
+
+bool GetIsEnterpriseManaged(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).GetIsEnterpriseManaged(account_id);
+}
+
+void SetAccountManager(const AccountId& account_id,
+ const std::string& manager) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetAccountManager(account_id, manager);
+}
+
+bool GetAccountManager(const AccountId& account_id, std::string* manager) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state).GetAccountManager(account_id, manager);
+}
+
+void SetUserLastLoginInputMethod(const AccountId& account_id,
+ const std::string& input_method) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state)
+ .SetUserLastLoginInputMethod(account_id, input_method);
+}
+
+bool GetUserLastInputMethod(const AccountId& account_id,
+ std::string* input_method) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return false;
+ return KnownUser(local_state)
+ .GetUserLastInputMethod(account_id, input_method);
+}
+
+void SetUserPinLength(const AccountId& account_id, int pin_length) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetUserPinLength(account_id, pin_length);
+}
+
+int GetUserPinLength(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return 0;
+ return KnownUser(local_state).GetUserPinLength(account_id);
+}
+
+bool PinAutosubmitIsBackfillNeeded(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state) {
+ // If the pref is not set, the pref needs to be backfilled.
+ return true;
+ }
+ return KnownUser(local_state).PinAutosubmitIsBackfillNeeded(account_id);
+}
+
+void PinAutosubmitSetBackfillNotNeeded(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).PinAutosubmitSetBackfillNotNeeded(account_id);
+}
+
+void PinAutosubmitSetBackfillNeededForTests(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state)
+ .PinAutosubmitSetBackfillNeededForTests(account_id);
+}
+
+void SetPasswordSyncToken(const AccountId& account_id,
+ const std::string& token) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return;
+ return KnownUser(local_state).SetPasswordSyncToken(account_id, token);
+}
+
+std::string GetPasswordSyncToken(const AccountId& account_id) {
+ PrefService* local_state = GetLocalStateLegacy();
+ // Local State may not be initialized in tests.
+ if (!local_state)
+ return std::string();
+ return KnownUser(local_state).GetPasswordSyncToken(account_id);
+}
+
} // namespace known_user
} // namespace user_manager
diff --git a/chromium/components/user_manager/known_user.h b/chromium/components/user_manager/known_user.h
index ab6b09e1239..22394e38e3d 100644
--- a/chromium/components/user_manager/known_user.h
+++ b/chromium/components/user_manager/known_user.h
@@ -8,12 +8,15 @@
#include <string>
#include <vector>
+#include "base/gtest_prod_util.h"
#include "base/time/time.h"
#include "components/user_manager/user_manager_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class AccountId;
enum class AccountType;
class PrefRegistrySimple;
+class PrefService;
namespace base {
class DictionaryValue;
@@ -21,106 +24,392 @@ class Value;
}
namespace user_manager {
+
+class UserManagerBase;
+
+// Enum describing whether a user's profile requires policy. If kPolicyRequired,
+// the profile initialization code will ensure that valid policy is loaded
+// before session initialization completes.
+enum class ProfileRequiresPolicy {
+ kUnknown,
+ kPolicyRequired,
+ kNoPolicyRequired
+};
+
+// Accessor for attributes of per-user properties stored in local_state.
+class USER_MANAGER_EXPORT KnownUser final {
+ public:
+ // Constructing KnownUser is cheap.
+ // |local_state| may not be nullptr. This is different from the legacy
+ // accessors (user_manager::known_user::) which will return a default value if
+ // local_state is not available.
+ KnownUser(PrefService* local_state);
+ ~KnownUser();
+
+ KnownUser(const KnownUser& other) = delete;
+ KnownUser& operator=(const KnownUser& other) = delete;
+
+ // Performs a lookup of properties associated with |account_id|. If found,
+ // returns |true| and fills |out_value|. |out_value| can be NULL, if
+ // only existence check is required.
+ bool FindPrefs(const AccountId& account_id,
+ const base::DictionaryValue** out_value);
+
+ // Updates (or creates) properties associated with |account_id| based
+ // on |values|. |clear| defines if existing properties are cleared (|true|)
+ // or if it is just a incremental update (|false|).
+ void UpdatePrefs(const AccountId& account_id,
+ const base::DictionaryValue& values,
+ bool clear);
+
+ // Returns true if |account_id| preference by |path| does exist,
+ // fills in |out_value|. Otherwise returns false.
+ bool GetStringPref(const AccountId& account_id,
+ const std::string& path,
+ std::string* out_value);
+
+ // Updates user's identified by |account_id| string preference |path|.
+ void SetStringPref(const AccountId& account_id,
+ const std::string& path,
+ const std::string& in_value);
+
+ // Returns true if |account_id| preference by |path| does exist,
+ // fills in |out_value|. Otherwise returns false.
+ bool GetBooleanPref(const AccountId& account_id,
+ const std::string& path,
+ bool* out_value);
+
+ // Updates user's identified by |account_id| boolean preference |path|.
+ void SetBooleanPref(const AccountId& account_id,
+ const std::string& path,
+ const bool in_value);
+
+ // Returns true if |account_id| preference by |path| does exist,
+ // fills in |out_value|. Otherwise returns false.
+ bool GetIntegerPref(const AccountId& account_id,
+ const std::string& path,
+ int* out_value);
+
+ // Updates user's identified by |account_id| integer preference |path|.
+ void SetIntegerPref(const AccountId& account_id,
+ const std::string& path,
+ const int in_value);
+
+ // Returns true if |account_id| preference by |path| does exist,
+ // fills in |out_value|. Otherwise returns false.
+ bool GetPref(const AccountId& account_id,
+ const std::string& path,
+ const base::Value** out_value);
+
+ // Updates user's identified by |account_id| value preference |path|.
+ void SetPref(const AccountId& account_id,
+ const std::string& path,
+ base::Value in_value);
+
+ // Removes user's identified by |account_id| preference |path|.
+ void RemovePref(const AccountId& account_id, const std::string& path);
+
+ // Returns the list of known AccountIds.
+ std::vector<AccountId> GetKnownAccountIds();
+
+ // This call forms full account id of a known user by email and (optionally)
+ // gaia_id.
+ // This is a temporary call while migrating to AccountId.
+ AccountId GetAccountId(const std::string& user_email,
+ const std::string& id,
+ const AccountType& account_type);
+
+ // Returns true if |subsystem| data was migrated to GaiaId for the
+ // |account_id|.
+ bool GetGaiaIdMigrationStatus(const AccountId& account_id,
+ const std::string& subsystem);
+
+ // Marks |subsystem| migrated to GaiaId for the |account_id|.
+ void SetGaiaIdMigrationStatusDone(const AccountId& account_id,
+ const std::string& subsystem);
+
+ // Saves |account_id| into known users. Tries to commit the change on disk.
+ // Use only if account_id is not yet in the known user list. Important if
+ // Chrome crashes shortly after starting a session. Cryptohome should be able
+ // to find known account_id on Chrome restart.
+ void SaveKnownUser(const AccountId& account_id);
+
+ // Updates |gaia_id| for user with |account_id|.
+ // TODO(alemate): Update this once AccountId contains GAIA ID
+ // (crbug.com/548926).
+ void UpdateGaiaID(const AccountId& account_id, const std::string& gaia_id);
+
+ // Updates |account_id.account_type_| and |account_id.GetGaiaId()| or
+ // |account_id.GetObjGuid()| for user with |account_id|.
+ void UpdateId(const AccountId& account_id);
+
+ // Find GAIA ID for user with |account_id|, fill in |out_value| and return
+ // true
+ // if GAIA ID was found or false otherwise.
+ // TODO(antrim): Update this once AccountId contains GAIA ID
+ // (crbug.com/548926).
+ bool FindGaiaID(const AccountId& account_id, std::string* out_value);
+
+ // Setter and getter for DeviceId known user string preference.
+ void SetDeviceId(const AccountId& account_id, const std::string& device_id);
+
+ std::string GetDeviceId(const AccountId& account_id);
+
+ // Setter and getter for GAPSCookie known user string preference.
+ void SetGAPSCookie(const AccountId& account_id,
+ const std::string& gaps_cookie);
+
+ std::string GetGAPSCookie(const AccountId& account_id);
+
+ // Saves whether the user authenticates using SAML.
+ void UpdateUsingSAML(const AccountId& account_id, const bool using_saml);
+
+ // Returns if SAML needs to be used for authentication of the user with
+ // |account_id|, if it is known (was set by a |UpdateUsingSaml| call).
+ // Otherwise
+ // returns false.
+ bool IsUsingSAML(const AccountId& account_id);
+
+ // Setter and getter for the known user preference that stores whether the
+ // user authenticated via SAML using the principals API.
+ void UpdateIsUsingSAMLPrincipalsAPI(const AccountId& account_id,
+ bool is_using_saml_principals_api);
+
+ bool GetIsUsingSAMLPrincipalsAPI(const AccountId& account_id);
+
+ // Returns whether the current profile requires policy or not (returns UNKNOWN
+ // if the profile has never been initialized and so the policy status is
+ // not yet known).
+ ProfileRequiresPolicy GetProfileRequiresPolicy(const AccountId& account_id);
+
+ // Sets whether the profile requires policy or not.
+ void SetProfileRequiresPolicy(const AccountId& account_id,
+ ProfileRequiresPolicy policy_required);
+
+ // Clears information whether profile requires policy.
+ void ClearProfileRequiresPolicy(const AccountId& account_id);
+
+ // Saves why the user has to go through re-auth flow.
+ void UpdateReauthReason(const AccountId& account_id, const int reauth_reason);
+
+ // Returns the reason why the user with |account_id| has to go through the
+ // re-auth flow. Returns true if such a reason was recorded or false
+ // otherwise.
+ bool FindReauthReason(const AccountId& account_id, int* out_value);
+
+ // Setter and getter for the information about challenge-response keys that
+ // can be used by this user to authenticate. The getter returns a null value
+ // when the property isn't present. For the format of the value, refer to
+ // chromeos/login/auth/challenge_response/known_user_pref_utils.h.
+ void SetChallengeResponseKeys(const AccountId& account_id, base::Value value);
+
+ base::Value GetChallengeResponseKeys(const AccountId& account_id);
+
+ void SetLastOnlineSignin(const AccountId& account_id, base::Time time);
+
+ base::Time GetLastOnlineSignin(const AccountId& account_id);
+
+ void SetOfflineSigninLimit(const AccountId& account_id,
+ absl::optional<base::TimeDelta> time_limit);
+
+ absl::optional<base::TimeDelta> GetOfflineSigninLimit(
+ const AccountId& account_id);
+
+ void SetIsEnterpriseManaged(const AccountId& account_id,
+ bool is_enterprise_managed);
+
+ bool GetIsEnterpriseManaged(const AccountId& account_id);
+
+ void SetAccountManager(const AccountId& account_id,
+ const std::string& manager);
+ bool GetAccountManager(const AccountId& account_id, std::string* manager);
+ void SetUserLastLoginInputMethod(const AccountId& account_id,
+ const std::string& input_method);
+
+ bool GetUserLastInputMethod(const AccountId& account_id,
+ std::string* input_method);
+
+ // Exposes the user's PIN length in local state for PIN auto submit.
+ void SetUserPinLength(const AccountId& account_id, int pin_length);
+
+ // Returns the user's PIN length if available, otherwise 0.
+ int GetUserPinLength(const AccountId& account_id);
+
+ // Whether the user needs to have their pin auto submit preferences
+ // backfilled.
+ // TODO(crbug.com/1104164) - Remove this once most users have their
+ // preferences backfilled.
+ bool PinAutosubmitIsBackfillNeeded(const AccountId& account_id);
+ void PinAutosubmitSetBackfillNotNeeded(const AccountId& account_id);
+ void PinAutosubmitSetBackfillNeededForTests(const AccountId& account_id);
+
+ // Setter and getter for password sync token used for syncing SAML passwords
+ // across multiple user devices.
+ void SetPasswordSyncToken(const AccountId& account_id,
+ const std::string& token);
+
+ std::string GetPasswordSyncToken(const AccountId& account_id);
+
+ // Register known user prefs.
+ static void RegisterPrefs(PrefRegistrySimple* registry);
+
+ private:
+ friend class UserManagerBase;
+
+ FRIEND_TEST_ALL_PREFIXES(KnownUserTest,
+ CleanEphemeralUsersRemovesEphemeralAdOnly);
+ FRIEND_TEST_ALL_PREFIXES(KnownUserTest, CleanObsoletePrefs);
+
+ // Removes |path| from account_id's known user dictionary.
+ void ClearPref(const AccountId& account_id, const std::string& path);
+
+ // Removes all user preferences associated with |account_id|.
+ // Not exported as code should not be calling this outside this component
+ void RemovePrefs(const AccountId& account_id);
+
+ // Removes all ephemeral users.
+ void CleanEphemeralUsers();
+
+ // Marks if user is ephemeral and should be removed on log out.
+ void SetIsEphemeralUser(const AccountId& account_id, bool is_ephemeral);
+
+ // Removes all obsolete prefs from all users.
+ void CleanObsoletePrefs();
+
+ PrefService* const local_state_;
+};
+
+// Legacy interface of KnownUsersDatabase.
+// TODO(https://crbug.com/1150434): Migrate callers and remove this.
namespace known_user {
// Methods for storage/retrieval of per-user properties in Local State.
// Performs a lookup of properties associated with |account_id|. If found,
// returns |true| and fills |out_value|. |out_value| can be NULL, if
// only existence check is required.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::FindPrefs
+// instead.
bool USER_MANAGER_EXPORT FindPrefs(const AccountId& account_id,
const base::DictionaryValue** out_value);
// Updates (or creates) properties associated with |account_id| based
// on |values|. |clear| defines if existing properties are cleared (|true|)
// or if it is just a incremental update (|false|).
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser:: instead.
void USER_MANAGER_EXPORT UpdatePrefs(const AccountId& account_id,
const base::DictionaryValue& values,
bool clear);
// Returns true if |account_id| preference by |path| does exist,
// fills in |out_value|. Otherwise returns false.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetStringPref
+// instead.
bool USER_MANAGER_EXPORT GetStringPref(const AccountId& account_id,
const std::string& path,
std::string* out_value);
// Updates user's identified by |account_id| string preference |path|.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::SetStringPref
+// instead.
void USER_MANAGER_EXPORT SetStringPref(const AccountId& account_id,
const std::string& path,
const std::string& in_value);
// Returns true if |account_id| preference by |path| does exist,
// fills in |out_value|. Otherwise returns false.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetBooleanPref
+// instead.
bool USER_MANAGER_EXPORT GetBooleanPref(const AccountId& account_id,
const std::string& path,
bool* out_value);
// Updates user's identified by |account_id| boolean preference |path|.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::SetBooleanPref
+// instead.
void USER_MANAGER_EXPORT SetBooleanPref(const AccountId& account_id,
const std::string& path,
const bool in_value);
// Returns true if |account_id| preference by |path| does exist,
// fills in |out_value|. Otherwise returns false.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetIntegerPref
+// instead.
bool USER_MANAGER_EXPORT GetIntegerPref(const AccountId& account_id,
const std::string& path,
int* out_value);
// Updates user's identified by |account_id| integer preference |path|.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::SetIntegerPref
+// instead.
void USER_MANAGER_EXPORT SetIntegerPref(const AccountId& account_id,
const std::string& path,
const int in_value);
// Returns true if |account_id| preference by |path| does exist,
// fills in |out_value|. Otherwise returns false.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetPref instead.
bool USER_MANAGER_EXPORT GetPref(const AccountId& account_id,
const std::string& path,
const base::Value** out_value);
// Updates user's identified by |account_id| value preference |path|.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::SetPref instead.
void USER_MANAGER_EXPORT SetPref(const AccountId& account_id,
const std::string& path,
base::Value in_value);
// Removes user's identified by |account_id| preference |path|.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::RemovePref
+// instead.
void USER_MANAGER_EXPORT RemovePref(const AccountId& account_id,
const std::string& path);
// Returns the list of known AccountIds.
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::GetKnownAccountIds instead.
std::vector<AccountId> USER_MANAGER_EXPORT GetKnownAccountIds();
// This call forms full account id of a known user by email and (optionally)
// gaia_id.
// This is a temporary call while migrating to AccountId.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetAccountId
+// instead.
AccountId USER_MANAGER_EXPORT GetAccountId(const std::string& user_email,
const std::string& id,
const AccountType& account_type);
// Returns true if |subsystem| data was migrated to GaiaId for the |account_id|.
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::GetGaiaIdMigrationStatus instead.
bool USER_MANAGER_EXPORT GetGaiaIdMigrationStatus(const AccountId& account_id,
const std::string& subsystem);
// Marks |subsystem| migrated to GaiaId for the |account_id|.
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::SetGaiaIdMigrationStatusDone instead.
void USER_MANAGER_EXPORT
SetGaiaIdMigrationStatusDone(const AccountId& account_id,
const std::string& subsystem);
-// Marks if user is ephemeral and should be removed on log out.
-void SetIsEphemeralUser(const AccountId& account_id, bool is_ephemeral);
-
// Saves |account_id| into known users. Tries to commit the change on disk. Use
// only if account_id is not yet in the known user list. Important if Chrome
// crashes shortly after starting a session. Cryptohome should be able to find
// known account_id on Chrome restart.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::SaveKnownUser
+// instead.
void USER_MANAGER_EXPORT SaveKnownUser(const AccountId& account_id);
// Updates |gaia_id| for user with |account_id|.
// TODO(alemate): Update this once AccountId contains GAIA ID
// (crbug.com/548926).
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::UpdateGaiaID
+// instead.
void USER_MANAGER_EXPORT UpdateGaiaID(const AccountId& account_id,
const std::string& gaia_id);
// Updates |account_id.account_type_| and |account_id.GetGaiaId()| or
// |account_id.GetObjGuid()| for user with |account_id|.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::UpdateId instead.
void USER_MANAGER_EXPORT UpdateId(const AccountId& account_id);
// Find GAIA ID for user with |account_id|, fill in |out_value| and return
@@ -128,22 +417,34 @@ void USER_MANAGER_EXPORT UpdateId(const AccountId& account_id);
// if GAIA ID was found or false otherwise.
// TODO(antrim): Update this once AccountId contains GAIA ID
// (crbug.com/548926).
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::FindGaiaID
+// instead.
bool USER_MANAGER_EXPORT FindGaiaID(const AccountId& account_id,
std::string* out_value);
// Setter and getter for DeviceId known user string preference.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::SetDeviceId
+// instead.
void USER_MANAGER_EXPORT SetDeviceId(const AccountId& account_id,
const std::string& device_id);
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetDeviceId
+// instead.
std::string USER_MANAGER_EXPORT GetDeviceId(const AccountId& account_id);
// Setter and getter for GAPSCookie known user string preference.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::SetGAPSCookie
+// instead.
void USER_MANAGER_EXPORT SetGAPSCookie(const AccountId& account_id,
const std::string& gaps_cookie);
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetGAPSCookie
+// instead.
std::string USER_MANAGER_EXPORT GetGAPSCookie(const AccountId& account_id);
// Saves whether the user authenticates using SAML.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::UpdateUsingSAML
+// instead.
void USER_MANAGER_EXPORT UpdateUsingSAML(const AccountId& account_id,
const bool using_saml);
@@ -151,109 +452,137 @@ void USER_MANAGER_EXPORT UpdateUsingSAML(const AccountId& account_id,
// |account_id|, if it is known (was set by a |UpdateUsingSaml| call).
// Otherwise
// returns false.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::IsUsingSAML
+// instead.
bool USER_MANAGER_EXPORT IsUsingSAML(const AccountId& account_id);
// Setter and getter for the known user preference that stores whether the user
// authenticated via SAML using the principals API.
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::UpdateIsUsingSAMLPrincipalsAPI instead.
void USER_MANAGER_EXPORT
UpdateIsUsingSAMLPrincipalsAPI(const AccountId& account_id,
bool is_using_saml_principals_api);
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::GetIsUsingSAMLPrincipalsAPI instead.
bool USER_MANAGER_EXPORT
GetIsUsingSAMLPrincipalsAPI(const AccountId& account_id);
-// Enum describing whether a user's profile requires policy. If kPolicyRequired,
-// the profile initialization code will ensure that valid policy is loaded
-// before session initialization completes.
-enum class ProfileRequiresPolicy {
- kUnknown,
- kPolicyRequired,
- kNoPolicyRequired
-};
-
// Returns whether the current profile requires policy or not (returns UNKNOWN
// if the profile has never been initialized and so the policy status is
// not yet known).
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::GetProfileRequiresPolicy instead.
ProfileRequiresPolicy USER_MANAGER_EXPORT
GetProfileRequiresPolicy(const AccountId& account_id);
// Sets whether the profile requires policy or not.
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::SetProfileRequiresPolicy instead.
void USER_MANAGER_EXPORT
SetProfileRequiresPolicy(const AccountId& account_id,
ProfileRequiresPolicy policy_required);
// Clears information whether profile requires policy.
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::ClearProfileRequiresPolicy instead.
void USER_MANAGER_EXPORT
ClearProfileRequiresPolicy(const AccountId& account_id);
// Saves why the user has to go through re-auth flow.
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::UpdateReauthReason instead.
void USER_MANAGER_EXPORT UpdateReauthReason(const AccountId& account_id,
const int reauth_reason);
// Returns the reason why the user with |account_id| has to go through the
// re-auth flow. Returns true if such a reason was recorded or false
// otherwise.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::FindReauthReason
+// instead.
bool USER_MANAGER_EXPORT FindReauthReason(const AccountId& account_id,
int* out_value);
-// Saves that a minimal migration was attempted for this user's cryptohome.
-void USER_MANAGER_EXPORT
-SetUserHomeMinimalMigrationAttempted(const AccountId& account_id,
- bool minimal_migration_attempted);
-
-// Returns true if minimal migration was attempted for this user's cryptohome.
-bool USER_MANAGER_EXPORT
-WasUserHomeMinimalMigrationAttempted(const AccountId& account_id);
-
// Setter and getter for the information about challenge-response keys that can
// be used by this user to authenticate.
// The getter returns a null value when the property isn't present.
// For the format of the value, refer to
// chromeos/login/auth/challenge_response/known_user_pref_utils.h.
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::SetChallengeResponseKeys instead.
void USER_MANAGER_EXPORT SetChallengeResponseKeys(const AccountId& account_id,
base::Value value);
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::GetChallengeResponseKeys instead.
base::Value USER_MANAGER_EXPORT
GetChallengeResponseKeys(const AccountId& account_id);
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::SetLastOnlineSignin instead.
void USER_MANAGER_EXPORT SetLastOnlineSignin(const AccountId& account_id,
base::Time time);
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::GetLastOnlineSignin instead.
base::Time USER_MANAGER_EXPORT GetLastOnlineSignin(const AccountId& account_id);
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::SetOfflineSigninLimit instead.
void USER_MANAGER_EXPORT
SetOfflineSigninLimit(const AccountId& account_id,
- base::Optional<base::TimeDelta> time_limit);
+ absl::optional<base::TimeDelta> time_limit);
-base::Optional<base::TimeDelta> USER_MANAGER_EXPORT
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::GetOfflineSigninLimit instead.
+absl::optional<base::TimeDelta> USER_MANAGER_EXPORT
GetOfflineSigninLimit(const AccountId& account_id);
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::SetIsEnterpriseManaged instead.
void USER_MANAGER_EXPORT SetIsEnterpriseManaged(const AccountId& account_id,
bool is_enterprise_managed);
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::GetIsEnterpriseManaged instead.
bool USER_MANAGER_EXPORT GetIsEnterpriseManaged(const AccountId& account_id);
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::SetAccountManager
+// instead.
void USER_MANAGER_EXPORT SetAccountManager(const AccountId& account_id,
const std::string& manager);
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetAccountManager
+// instead.
bool USER_MANAGER_EXPORT GetAccountManager(const AccountId& account_id,
std::string* manager);
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::SetUserLastLoginInputMethod instead.
void USER_MANAGER_EXPORT
SetUserLastLoginInputMethod(const AccountId& account_id,
const std::string& input_method);
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::GetUserLastInputMethod instead.
bool USER_MANAGER_EXPORT GetUserLastInputMethod(const AccountId& account_id,
std::string* input_method);
// Exposes the user's PIN length in local state for PIN auto submit.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::SetUserPinLength
+// instead.
void USER_MANAGER_EXPORT SetUserPinLength(const AccountId& account_id,
int pin_length);
// Returns the user's PIN length if available, otherwise 0.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser::GetUserPinLength
+// instead.
int USER_MANAGER_EXPORT GetUserPinLength(const AccountId& account_id);
// Whether the user needs to have their pin auto submit preferences backfilled.
// TODO(crbug.com/1104164) - Remove this once most users have their
// preferences backfilled.
+// TODO(https://crbug.com/1150434): Deprecated, use KnownUser:: equivalents
+// instead.
bool USER_MANAGER_EXPORT
PinAutosubmitIsBackfillNeeded(const AccountId& account_id);
void USER_MANAGER_EXPORT
@@ -263,22 +592,17 @@ PinAutosubmitSetBackfillNeededForTests(const AccountId& account_id);
// Setter and getter for password sync token used for syncing SAML passwords
// across multiple user devices.
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::SetPasswordSyncToken instead.
void USER_MANAGER_EXPORT SetPasswordSyncToken(const AccountId& account_id,
const std::string& token);
+// TODO(https://crbug.com/1150434): Deprecated, use
+// KnownUser::GetPasswordSyncToken instead.
std::string USER_MANAGER_EXPORT
GetPasswordSyncToken(const AccountId& account_id);
-// Removes all user preferences associated with |account_id|.
-// Not exported as code should not be calling this outside this component
-void RemovePrefs(const AccountId& account_id);
-
-// Removes all ephemeral users.
-void CleanEphemeralUsers();
-
-// Register known user prefs.
-void USER_MANAGER_EXPORT RegisterPrefs(PrefRegistrySimple* registry);
-}
+} // namespace known_user
} // namespace user_manager
#endif // COMPONENTS_USER_MANAGER_KNOWN_USER_H_
diff --git a/chromium/components/user_manager/known_user_unittest.cc b/chromium/components/user_manager/known_user_unittest.cc
new file mode 100644
index 00000000000..910171faeb9
--- /dev/null
+++ b/chromium/components/user_manager/known_user_unittest.cc
@@ -0,0 +1,854 @@
+// Copyright 2021 The Chromium Authors. 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/user_manager/known_user.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/test/task_environment.h"
+#include "components/account_id/account_id.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/user_manager/fake_user_manager.h"
+#include "components/user_manager/scoped_user_manager.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+
+namespace user_manager {
+namespace {
+absl::optional<std::string> GetStringPrefValue(KnownUser* known_user,
+ const AccountId& account_id,
+ const char* pref_name) {
+ std::string value;
+ if (!known_user->GetStringPref(account_id, pref_name, &value)) {
+ return {};
+ }
+ return value;
+}
+} // namespace
+
+// Base class for tests of known_user.
+// Sets up global objects necessary for known_user to be able to access
+// local_state.
+class KnownUserTest : public testing::Test {
+ public:
+ KnownUserTest() {
+ auto fake_user_manager = std::make_unique<FakeUserManager>();
+ fake_user_manager_ = fake_user_manager.get();
+ scoped_user_manager_ =
+ std::make_unique<ScopedUserManager>(std::move(fake_user_manager));
+
+ KnownUser::RegisterPrefs(local_state_.registry());
+ }
+ ~KnownUserTest() override = default;
+
+ KnownUserTest(const KnownUserTest& other) = delete;
+ KnownUserTest& operator=(const KnownUserTest& other) = delete;
+
+ protected:
+ const AccountId kDefaultAccountId =
+ AccountId::FromUserEmailGaiaId("default_account@gmail.com",
+ "fake-gaia-id");
+
+ FakeUserManager* fake_user_manager() { return fake_user_manager_; }
+
+ PrefService* local_state() { return &local_state_; }
+
+ private:
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::UI};
+
+ // Owned by |scoped_user_manager_|.
+ FakeUserManager* fake_user_manager_ = nullptr;
+ std::unique_ptr<ScopedUserManager> scoped_user_manager_;
+ TestingPrefServiceSimple local_state_;
+};
+
+TEST_F(KnownUserTest, FindPrefsNonExisting) {
+ KnownUser known_user(local_state());
+ const base::DictionaryValue* value = nullptr;
+ bool read_success = known_user.FindPrefs(kDefaultAccountId, &value);
+ EXPECT_FALSE(read_success);
+ EXPECT_FALSE(value);
+}
+
+TEST_F(KnownUserTest, FindPrefsExisting) {
+ KnownUser known_user(local_state());
+ const std::string kCustomPrefName = "custom_pref";
+ known_user.SetStringPref(kDefaultAccountId, kCustomPrefName, "value");
+
+ const base::DictionaryValue* value = nullptr;
+ bool read_success = known_user.FindPrefs(kDefaultAccountId, &value);
+ EXPECT_TRUE(read_success);
+ ASSERT_TRUE(value);
+
+ const std::string* pref_value = value->FindStringKey(kCustomPrefName);
+ ASSERT_TRUE(pref_value);
+ EXPECT_EQ(*pref_value, "value");
+}
+
+TEST_F(KnownUserTest, FindPrefsIgnoresEphemeralGaiaUsers) {
+ KnownUser known_user(local_state());
+ const AccountId kAccountIdEphemeralGaia =
+ AccountId::FromUserEmailGaiaId("account2@gmail.com", "gaia_id_2");
+ const AccountId kAccountIdEphemeralAd =
+ AccountId::AdFromUserEmailObjGuid("account4@gmail.com", "guid_4");
+ fake_user_manager()->SetUserNonCryptohomeDataEphemeral(
+ kAccountIdEphemeralGaia,
+ /*is_ephemeral=*/true);
+ fake_user_manager()->SetUserNonCryptohomeDataEphemeral(kAccountIdEphemeralAd,
+ /*is_ephemeral=*/true);
+ const std::string kCustomPrefName = "custom_pref";
+ known_user.SetStringPref(kAccountIdEphemeralGaia, kCustomPrefName, "value");
+ known_user.SetStringPref(kAccountIdEphemeralAd, kCustomPrefName, "value");
+
+ {
+ const base::DictionaryValue* value = nullptr;
+ bool read_success = known_user.FindPrefs(kAccountIdEphemeralGaia, &value);
+ EXPECT_FALSE(read_success);
+ EXPECT_FALSE(value);
+ }
+
+ {
+ const base::DictionaryValue* value = nullptr;
+ bool read_success = known_user.FindPrefs(kAccountIdEphemeralAd, &value);
+ EXPECT_TRUE(read_success);
+ EXPECT_TRUE(value);
+ }
+}
+
+TEST_F(KnownUserTest, FindPrefsMatchForUnknownAccountType) {
+ KnownUser known_user(local_state());
+ // All account ids have the same e-mail
+ const AccountId kAccountIdUnknown =
+ AccountId::FromUserEmail("account1@gmail.com");
+ const AccountId kAccountIdGaia =
+ AccountId::FromUserEmailGaiaId("account1@gmail.com", "gaia_id_2");
+ const AccountId kAccountIdAd =
+ AccountId::AdFromUserEmailObjGuid("account1@gmail.com", "guid");
+
+ known_user.SetStringPref(kAccountIdUnknown, "some_pref", "some_value");
+
+ // Looking it up by AccountId always succeeds, no matter which AccountType is
+ // used for the lookup.
+ const base::DictionaryValue* value = nullptr;
+ EXPECT_TRUE(known_user.FindPrefs(kAccountIdUnknown, &value));
+ EXPECT_TRUE(known_user.FindPrefs(kAccountIdGaia, &value));
+ EXPECT_TRUE(known_user.FindPrefs(kAccountIdAd, &value));
+}
+
+TEST_F(KnownUserTest, FindPrefsMatchForGaiaAccountWithEmail) {
+ KnownUser known_user(local_state());
+ const char* kEmailA = "a@gmail.com";
+ const char* kEmailB = "b@gmail.com";
+ const char* kGaiaIdA = "a";
+ const char* kGaiaIdB = "b";
+
+ known_user.SaveKnownUser(AccountId::FromUserEmailGaiaId(kEmailA, kGaiaIdA));
+
+ const base::DictionaryValue* value = nullptr;
+
+ // Finding by itself should work
+ EXPECT_TRUE(known_user.FindPrefs(
+ AccountId::FromUserEmailGaiaId(kEmailA, kGaiaIdA), &value));
+ // Finding by gaia id should also work even if the e-mail doesn't match.
+ EXPECT_TRUE(known_user.FindPrefs(
+ AccountId::FromUserEmailGaiaId(kEmailB, kGaiaIdA), &value));
+ // Finding by e-mail should also work even if the gaia id doesn't match.
+ // TODO(https://crbug.com/1190902): This should likely be EXPECT_FALSE going
+ // forward.
+ EXPECT_TRUE(known_user.FindPrefs(
+ AccountId::FromUserEmailGaiaId(kEmailA, kGaiaIdB), &value));
+ // Finding by just gaia id without any e-mail doesn't work (because the
+ // resulting AccountId is not considered valid).
+ EXPECT_FALSE(known_user.FindPrefs(AccountId::FromGaiaId(kGaiaIdA), &value));
+
+ // An unrelated gaia AccountId with the same Account Type doesn't find
+ // anything.
+ EXPECT_FALSE(known_user.FindPrefs(
+ AccountId::FromUserEmailGaiaId(kEmailB, kGaiaIdB), &value));
+
+ // Looking up an AccountId stored as gaia by an unknown-type AccountId with
+ // the same e-mail address succeeds.
+ EXPECT_TRUE(known_user.FindPrefs(AccountId::FromUserEmail(kEmailA), &value));
+
+ // Looking up an AccountId stored as gaia by an AccountId with type Ad fails.
+ EXPECT_FALSE(known_user.FindPrefs(
+ AccountId::AdFromUserEmailObjGuid(kEmailA, "guid"), &value));
+}
+
+TEST_F(KnownUserTest, FindPrefsMatchForAdAccountWithEmail) {
+ KnownUser known_user(local_state());
+ const std::string kEmailA = "a@gmail.com";
+ const std::string kEmailB = "b@gmail.com";
+
+ known_user.SaveKnownUser(AccountId::AdFromUserEmailObjGuid(kEmailA, "a"));
+
+ const base::DictionaryValue* value = nullptr;
+
+ // Finding by itself should work
+ EXPECT_TRUE(known_user.FindPrefs(
+ AccountId::AdFromUserEmailObjGuid(kEmailA, "a"), &value));
+ // Finding by guid should also work even if the e-mail doesn't match.
+ EXPECT_TRUE(known_user.FindPrefs(
+ AccountId::AdFromUserEmailObjGuid(kEmailB, "a"), &value));
+ // Finding by e-mail should also work even if the guid doesn't match.
+ EXPECT_TRUE(known_user.FindPrefs(
+ AccountId::AdFromUserEmailObjGuid(kEmailA, "b"), &value));
+ // Finding by just AD guid without any e-mail doesn't work (because the
+ // resulting AccountId is not considered valid).
+ EXPECT_FALSE(known_user.FindPrefs(AccountId::AdFromObjGuid("a"), &value));
+
+ // An unrelated AD AccountId with the same Account Type doesn't find
+ // anything.
+ EXPECT_FALSE(known_user.FindPrefs(
+ AccountId::AdFromUserEmailObjGuid(kEmailB, "b"), &value));
+
+ // Looking up an AccountId stored as AD by an unknown-type AccountId with
+ // the same e-mail address succeeds.
+ EXPECT_TRUE(known_user.FindPrefs(AccountId::FromUserEmail(kEmailA), &value));
+
+ // Looking up an AccountId stored as AD by an AccountId with type gaia fails.
+ EXPECT_FALSE(known_user.FindPrefs(
+ AccountId::FromUserEmailGaiaId(kEmailA, "gaia_id"), &value));
+}
+
+TEST_F(KnownUserTest, UpdatePrefsWithoutClear) {
+ KnownUser known_user(local_state());
+ constexpr char kPrefName1[] = "pref1";
+ constexpr char kPrefName2[] = "pref2";
+
+ {
+ base::DictionaryValue update;
+ update.SetKey(kPrefName1, base::Value("pref1_value1"));
+ known_user.UpdatePrefs(kDefaultAccountId, update, /*clear=*/false);
+ }
+
+ {
+ base::DictionaryValue update;
+ update.SetKey(kPrefName1, base::Value("pref1_value2"));
+ known_user.UpdatePrefs(kDefaultAccountId, update, /*clear=*/false);
+ }
+
+ {
+ base::DictionaryValue update;
+ update.SetKey(kPrefName2, base::Value("pref2_value1"));
+ known_user.UpdatePrefs(kDefaultAccountId, update, /*clear=*/false);
+ }
+
+ EXPECT_EQ(absl::make_optional(std::string("pref1_value2")),
+ GetStringPrefValue(&known_user, kDefaultAccountId, kPrefName1));
+ EXPECT_EQ(absl::make_optional(std::string("pref2_value1")),
+ GetStringPrefValue(&known_user, kDefaultAccountId, kPrefName2));
+}
+
+TEST_F(KnownUserTest, UpdatePrefsWithClear) {
+ KnownUser known_user(local_state());
+ constexpr char kPrefName1[] = "pref1";
+ constexpr char kPrefName2[] = "pref2";
+
+ {
+ base::DictionaryValue update;
+ update.SetKey(kPrefName1, base::Value("pref1_value1"));
+ known_user.UpdatePrefs(kDefaultAccountId, update, /*clear=*/false);
+ }
+
+ {
+ base::DictionaryValue update;
+ update.SetKey(kPrefName2, base::Value("pref2_value1"));
+ known_user.UpdatePrefs(kDefaultAccountId, update, /*clear=*/true);
+ }
+
+ EXPECT_EQ(absl::nullopt,
+ GetStringPrefValue(&known_user, kDefaultAccountId, kPrefName1));
+ EXPECT_EQ(absl::make_optional(std::string("pref2_value1")),
+ GetStringPrefValue(&known_user, kDefaultAccountId, kPrefName2));
+}
+
+TEST_F(KnownUserTest, GetKnownAccountIdsNoAccounts) {
+ KnownUser known_user(local_state());
+ EXPECT_THAT(known_user.GetKnownAccountIds(), testing::IsEmpty());
+}
+
+TEST_F(KnownUserTest, GetKnownAccountIdsWithAccounts) {
+ KnownUser known_user(local_state());
+ const AccountId kAccountIdGaia =
+ AccountId::FromUserEmailGaiaId("account2@gmail.com", "gaia_id");
+ const AccountId kAccountIdAd =
+ AccountId::AdFromUserEmailObjGuid("account3@gmail.com", "obj_guid");
+
+ known_user.SaveKnownUser(kAccountIdGaia);
+ known_user.SaveKnownUser(kAccountIdAd);
+
+ EXPECT_THAT(known_user.GetKnownAccountIds(),
+ testing::UnorderedElementsAre(kAccountIdGaia, kAccountIdAd));
+}
+
+TEST_F(KnownUserTest, SaveKnownUserIgnoresUnknownType) {
+ KnownUser known_user(local_state());
+ const AccountId kAccountIdUnknown =
+ AccountId::FromUserEmail("account2@gmail.com");
+
+ known_user.SaveKnownUser(kAccountIdUnknown);
+
+ EXPECT_THAT(known_user.GetKnownAccountIds(), testing::IsEmpty());
+}
+
+TEST_F(KnownUserTest, SaveKnownUserIgnoresEphemeralGaiaUsers) {
+ KnownUser known_user(local_state());
+ const AccountId kAccountIdNonEphemeralGaia =
+ AccountId::FromUserEmailGaiaId("account1@gmail.com", "gaia_id_1");
+ const AccountId kAccountIdEphemeralGaia =
+ AccountId::FromUserEmailGaiaId("account2@gmail.com", "gaia_id_2");
+ const AccountId kAccountIdNonEphemeralAd =
+ AccountId::AdFromUserEmailObjGuid("account3@gmail.com", "guid_3");
+ const AccountId kAccountIdEphemeralAd =
+ AccountId::AdFromUserEmailObjGuid("account4@gmail.com", "guid_4");
+
+ fake_user_manager()->SetUserNonCryptohomeDataEphemeral(
+ kAccountIdEphemeralGaia,
+ /*is_ephemeral=*/true);
+ fake_user_manager()->SetUserNonCryptohomeDataEphemeral(kAccountIdEphemeralAd,
+ /*is_ephemeral=*/true);
+
+ known_user.SaveKnownUser(kAccountIdNonEphemeralGaia);
+ known_user.SaveKnownUser(kAccountIdEphemeralGaia);
+ known_user.SaveKnownUser(kAccountIdNonEphemeralAd);
+ known_user.SaveKnownUser(kAccountIdEphemeralAd);
+
+ EXPECT_THAT(known_user.GetKnownAccountIds(),
+ testing::UnorderedElementsAre(kAccountIdNonEphemeralGaia,
+ kAccountIdNonEphemeralAd,
+ kAccountIdEphemeralAd));
+}
+
+TEST_F(KnownUserTest, UpdateGaiaID) {
+ KnownUser known_user(local_state());
+ const AccountId kAccountIdUnknown =
+ AccountId::FromUserEmail("account1@gmail.com");
+ known_user.SetStringPref(kAccountIdUnknown, "some_pref", "some_value");
+
+ {
+ std::string gaia_id;
+ EXPECT_FALSE(known_user.FindGaiaID(kAccountIdUnknown, &gaia_id));
+ }
+
+ known_user.UpdateGaiaID(kAccountIdUnknown, "gaia_id");
+
+ {
+ std::string gaia_id;
+ EXPECT_TRUE(known_user.FindGaiaID(kAccountIdUnknown, &gaia_id));
+ EXPECT_EQ(gaia_id, "gaia_id");
+ }
+
+ // UpdateGaiaID also sets account type to gaia account.
+ const AccountId kAccountIdGaia =
+ AccountId::FromUserEmailGaiaId("account1@gmail.com", "gaia_id");
+ EXPECT_THAT(known_user.GetKnownAccountIds(),
+ testing::UnorderedElementsAre(kAccountIdGaia));
+}
+
+TEST_F(KnownUserTest, UpdateIdForGaiaAccount) {
+ KnownUser known_user(local_state());
+ const AccountId kAccountIdUnknown =
+ AccountId::FromUserEmail("account1@gmail.com");
+ known_user.SetStringPref(kAccountIdUnknown, "some_pref", "some_value");
+ EXPECT_THAT(known_user.GetKnownAccountIds(),
+ testing::UnorderedElementsAre(kAccountIdUnknown));
+
+ const AccountId kAccountIdGaia =
+ AccountId::FromUserEmailGaiaId("account1@gmail.com", "gaia_id");
+ known_user.UpdateId(kAccountIdGaia);
+ EXPECT_THAT(known_user.GetKnownAccountIds(),
+ testing::UnorderedElementsAre(kAccountIdGaia));
+}
+
+TEST_F(KnownUserTest, UpdateIdForAdAccount) {
+ KnownUser known_user(local_state());
+ const AccountId kAccountIdUnknown =
+ AccountId::FromUserEmail("account1@gmail.com");
+ known_user.SetStringPref(kAccountIdUnknown, "some_pref", "some_value");
+ EXPECT_THAT(known_user.GetKnownAccountIds(),
+ testing::UnorderedElementsAre(kAccountIdUnknown));
+
+ const AccountId kAccountIdAd =
+ AccountId::AdFromUserEmailObjGuid("account1@gmail.com", "guid");
+ known_user.UpdateId(kAccountIdAd);
+ EXPECT_THAT(known_user.GetKnownAccountIds(),
+ testing::UnorderedElementsAre(kAccountIdAd));
+}
+
+TEST_F(KnownUserTest, FindGaiaIdForGaiaAccount) {
+ KnownUser known_user(local_state());
+ const AccountId kAccountIdGaia =
+ AccountId::FromUserEmailGaiaId("account1@gmail.com", "gaia_id");
+ known_user.SaveKnownUser(kAccountIdGaia);
+
+ std::string gaia_id;
+ EXPECT_TRUE(known_user.FindGaiaID(kAccountIdGaia, &gaia_id));
+ EXPECT_EQ(gaia_id, "gaia_id");
+}
+
+TEST_F(KnownUserTest, FindGaiaIdForAdAccount) {
+ KnownUser known_user(local_state());
+ const AccountId kAccountIdAd =
+ AccountId::AdFromUserEmailObjGuid("account1@gmail.com", "guid");
+ known_user.SaveKnownUser(kAccountIdAd);
+
+ std::string gaia_id;
+ EXPECT_FALSE(known_user.FindGaiaID(kAccountIdAd, &gaia_id));
+}
+
+// TODO(https://crbug.com/1148457): Add tests for GetAccountId.
+
+TEST_F(KnownUserTest, RemovePrefOnCustomPref) {
+ KnownUser known_user(local_state());
+ const std::string kCustomPrefName = "custom_pref";
+
+ known_user.SetStringPref(kDefaultAccountId, kCustomPrefName, "value");
+ {
+ std::string read_value;
+ EXPECT_TRUE(known_user.GetStringPref(kDefaultAccountId, kCustomPrefName,
+ &read_value));
+ }
+
+ known_user.RemovePref(kDefaultAccountId, kCustomPrefName);
+ {
+ std::string read_value;
+ EXPECT_FALSE(known_user.GetStringPref(kDefaultAccountId, kCustomPrefName,
+ &read_value));
+ }
+}
+
+// Test failing on linux-chromeos-chrome (crbug.com/1198519)
+TEST_F(KnownUserTest, DISABLED_RemovePrefOnReservedPref) {
+ KnownUser known_user(local_state());
+ const std::string kReservedPrefName = "device_id";
+
+ known_user.SetStringPref(kDefaultAccountId, kReservedPrefName, "value");
+ ASSERT_DEATH(known_user.RemovePref(kDefaultAccountId, kReservedPrefName),
+ ".*Check failed.*");
+}
+
+TEST_F(KnownUserTest, GaiaIdMigrationStatus) {
+ KnownUser known_user(local_state());
+ const std::string kSubsystem1 = "subsystem1";
+ const std::string kSubsystem2 = "subsystem2";
+
+ EXPECT_FALSE(
+ known_user.GetGaiaIdMigrationStatus(kDefaultAccountId, kSubsystem1));
+ EXPECT_FALSE(
+ known_user.GetGaiaIdMigrationStatus(kDefaultAccountId, kSubsystem2));
+
+ known_user.SetGaiaIdMigrationStatusDone(kDefaultAccountId, kSubsystem1);
+
+ EXPECT_TRUE(
+ known_user.GetGaiaIdMigrationStatus(kDefaultAccountId, kSubsystem1));
+ EXPECT_FALSE(
+ known_user.GetGaiaIdMigrationStatus(kDefaultAccountId, kSubsystem2));
+}
+
+TEST_F(KnownUserTest, DeviceId) {
+ KnownUser known_user(local_state());
+ EXPECT_EQ(known_user.GetDeviceId(kDefaultAccountId), std::string());
+
+ known_user.SetDeviceId(kDefaultAccountId, "test");
+
+ EXPECT_EQ(known_user.GetDeviceId(kDefaultAccountId), "test");
+}
+
+TEST_F(KnownUserTest, GAPSCookie) {
+ KnownUser known_user(local_state());
+ EXPECT_EQ(known_user.GetGAPSCookie(kDefaultAccountId), std::string());
+
+ known_user.SetGAPSCookie(kDefaultAccountId, "test");
+
+ EXPECT_EQ(known_user.GetGAPSCookie(kDefaultAccountId), "test");
+}
+
+TEST_F(KnownUserTest, UsingSAML) {
+ KnownUser known_user(local_state());
+ EXPECT_FALSE(known_user.IsUsingSAML(kDefaultAccountId));
+
+ known_user.UpdateUsingSAML(kDefaultAccountId, /*using_saml=*/true);
+ EXPECT_TRUE(known_user.IsUsingSAML(kDefaultAccountId));
+}
+
+TEST_F(KnownUserTest, UsingSAMLPrincipalsAPI) {
+ KnownUser known_user(local_state());
+ EXPECT_FALSE(known_user.GetIsUsingSAMLPrincipalsAPI(kDefaultAccountId));
+
+ known_user.UpdateIsUsingSAMLPrincipalsAPI(kDefaultAccountId,
+ /*using_saml=*/true);
+ EXPECT_TRUE(known_user.GetIsUsingSAMLPrincipalsAPI(kDefaultAccountId));
+}
+
+TEST_F(KnownUserTest, ProfileRequiresPolicy) {
+ KnownUser known_user(local_state());
+ EXPECT_EQ(known_user.GetProfileRequiresPolicy(kDefaultAccountId),
+ ProfileRequiresPolicy::kUnknown);
+
+ known_user.SetProfileRequiresPolicy(kDefaultAccountId,
+ ProfileRequiresPolicy::kPolicyRequired);
+ EXPECT_EQ(known_user.GetProfileRequiresPolicy(kDefaultAccountId),
+ ProfileRequiresPolicy::kPolicyRequired);
+
+ known_user.SetProfileRequiresPolicy(kDefaultAccountId,
+ ProfileRequiresPolicy::kNoPolicyRequired);
+ EXPECT_EQ(known_user.GetProfileRequiresPolicy(kDefaultAccountId),
+ ProfileRequiresPolicy::kNoPolicyRequired);
+
+ known_user.ClearProfileRequiresPolicy(kDefaultAccountId);
+ EXPECT_EQ(known_user.GetProfileRequiresPolicy(kDefaultAccountId),
+ ProfileRequiresPolicy::kUnknown);
+}
+
+TEST_F(KnownUserTest, ReauthReason) {
+ KnownUser known_user(local_state());
+ {
+ int auth_reason;
+ EXPECT_FALSE(known_user.FindReauthReason(kDefaultAccountId, &auth_reason));
+ }
+
+ known_user.UpdateReauthReason(kDefaultAccountId, 3);
+ {
+ int auth_reason;
+ EXPECT_TRUE(known_user.FindReauthReason(kDefaultAccountId, &auth_reason));
+ EXPECT_EQ(auth_reason, 3);
+ }
+}
+
+TEST_F(KnownUserTest, ChallengeResponseKeys) {
+ KnownUser known_user(local_state());
+ EXPECT_TRUE(known_user.GetChallengeResponseKeys(kDefaultAccountId).is_none());
+
+ base::Value challenge_response_keys(base::Value::Type::LIST);
+ challenge_response_keys.Append(base::Value("key1"));
+ known_user.SetChallengeResponseKeys(kDefaultAccountId,
+ challenge_response_keys.Clone());
+
+ EXPECT_EQ(known_user.GetChallengeResponseKeys(kDefaultAccountId),
+ challenge_response_keys);
+}
+
+TEST_F(KnownUserTest, LastOnlineSignin) {
+ KnownUser known_user(local_state());
+ EXPECT_TRUE(known_user.GetLastOnlineSignin(kDefaultAccountId).is_null());
+
+ base::Time last_online_signin = base::Time::Now();
+ known_user.SetLastOnlineSignin(kDefaultAccountId, last_online_signin);
+
+ EXPECT_EQ(known_user.GetLastOnlineSignin(kDefaultAccountId),
+ last_online_signin);
+}
+
+TEST_F(KnownUserTest, OfflineSigninLimit) {
+ KnownUser known_user(local_state());
+ EXPECT_FALSE(known_user.GetOfflineSigninLimit(kDefaultAccountId).has_value());
+
+ base::TimeDelta offline_signin_limit = base::TimeDelta::FromMinutes(80);
+ known_user.SetOfflineSigninLimit(kDefaultAccountId, offline_signin_limit);
+
+ EXPECT_EQ(known_user.GetOfflineSigninLimit(kDefaultAccountId).value(),
+ offline_signin_limit);
+}
+
+TEST_F(KnownUserTest, IsEnterpriseManaged) {
+ KnownUser known_user(local_state());
+ EXPECT_FALSE(known_user.GetIsEnterpriseManaged(kDefaultAccountId));
+
+ known_user.SetIsEnterpriseManaged(kDefaultAccountId, true);
+
+ EXPECT_TRUE(known_user.GetIsEnterpriseManaged(kDefaultAccountId));
+}
+
+TEST_F(KnownUserTest, AccountManager) {
+ KnownUser known_user(local_state());
+ {
+ std::string account_manager;
+ EXPECT_FALSE(
+ known_user.GetAccountManager(kDefaultAccountId, &account_manager));
+ }
+
+ known_user.SetAccountManager(kDefaultAccountId, "test");
+
+ {
+ std::string account_manager;
+ EXPECT_TRUE(
+ known_user.GetAccountManager(kDefaultAccountId, &account_manager));
+ }
+}
+
+TEST_F(KnownUserTest, UserLastLoginInputMethod) {
+ KnownUser known_user(local_state());
+ {
+ std::string user_last_input_method;
+ EXPECT_FALSE(known_user.GetUserLastInputMethod(kDefaultAccountId,
+ &user_last_input_method));
+ }
+
+ known_user.SetUserLastLoginInputMethod(kDefaultAccountId, "test");
+
+ {
+ std::string user_last_input_method;
+ EXPECT_TRUE(known_user.GetUserLastInputMethod(kDefaultAccountId,
+ &user_last_input_method));
+ }
+}
+
+TEST_F(KnownUserTest, UserPinLength) {
+ KnownUser known_user(local_state());
+ EXPECT_EQ(known_user.GetUserPinLength(kDefaultAccountId), 0);
+
+ known_user.SetUserPinLength(kDefaultAccountId, 8);
+
+ EXPECT_EQ(known_user.GetUserPinLength(kDefaultAccountId), 8);
+}
+
+TEST_F(KnownUserTest, PinAutosubmitBackfillNeeded) {
+ KnownUser known_user(local_state());
+ // If the pref is not set, returns true.
+ EXPECT_TRUE(known_user.PinAutosubmitIsBackfillNeeded(kDefaultAccountId));
+
+ known_user.PinAutosubmitSetBackfillNotNeeded(kDefaultAccountId);
+
+ EXPECT_FALSE(known_user.PinAutosubmitIsBackfillNeeded(kDefaultAccountId));
+
+ known_user.PinAutosubmitSetBackfillNeededForTests(kDefaultAccountId);
+
+ EXPECT_TRUE(known_user.PinAutosubmitIsBackfillNeeded(kDefaultAccountId));
+}
+
+TEST_F(KnownUserTest, PasswordSyncToken) {
+ KnownUser known_user(local_state());
+ EXPECT_EQ(known_user.GetPasswordSyncToken(kDefaultAccountId), std::string());
+
+ known_user.SetPasswordSyncToken(kDefaultAccountId, "test");
+
+ EXPECT_EQ(known_user.GetPasswordSyncToken(kDefaultAccountId), "test");
+}
+
+TEST_F(KnownUserTest, CleanEphemeralUsersRemovesEphemeralAdOnly) {
+ KnownUser known_user(local_state());
+ const AccountId kAccountIdNonEphemeralGaia =
+ AccountId::FromUserEmailGaiaId("account1@gmail.com", "gaia_id_1");
+ const AccountId kAccountIdEphemeralGaia =
+ AccountId::FromUserEmailGaiaId("account2@gmail.com", "gaia_id_2");
+ const AccountId kAccountIdNonEphemeralAd =
+ AccountId::AdFromUserEmailObjGuid("account3@gmail.com", "guid_3");
+ const AccountId kAccountIdEphemeralAd =
+ AccountId::AdFromUserEmailObjGuid("account4@gmail.com", "guid_4");
+
+ known_user.SaveKnownUser(kAccountIdNonEphemeralGaia);
+ known_user.SaveKnownUser(kAccountIdEphemeralGaia);
+ known_user.SaveKnownUser(kAccountIdNonEphemeralAd);
+ known_user.SaveKnownUser(kAccountIdEphemeralAd);
+ known_user.SetIsEphemeralUser(kAccountIdEphemeralGaia,
+ /*is_ephemeral=*/true);
+ known_user.SetIsEphemeralUser(kAccountIdEphemeralAd, /*is_ephemeral=*/true);
+
+ EXPECT_THAT(known_user.GetKnownAccountIds(),
+ testing::UnorderedElementsAre(
+ kAccountIdNonEphemeralGaia, kAccountIdEphemeralGaia,
+ kAccountIdNonEphemeralAd, kAccountIdEphemeralAd));
+
+ known_user.CleanEphemeralUsers();
+
+ EXPECT_THAT(known_user.GetKnownAccountIds(),
+ testing::UnorderedElementsAre(kAccountIdNonEphemeralGaia,
+ kAccountIdEphemeralGaia,
+ kAccountIdNonEphemeralAd));
+}
+
+TEST_F(KnownUserTest, CleanObsoletePrefs) {
+ KnownUser known_user(local_state());
+ const std::string kObsoletePrefName = "minimal_migration_attempted";
+ const std::string kCustomPrefName = "custom_pref";
+
+ // Set an obsolete pref.
+ known_user.SetBooleanPref(kDefaultAccountId, kObsoletePrefName, true);
+ // Set a custom pref.
+ known_user.SetBooleanPref(kDefaultAccountId, kCustomPrefName, true);
+ // Set a reserved, non-obsolete pref.
+ known_user.SetIsEnterpriseManaged(kDefaultAccountId, true);
+
+ known_user.CleanObsoletePrefs();
+
+ // Verify that only the obsolete pref has been removed.
+ EXPECT_FALSE(known_user.GetBooleanPref(kDefaultAccountId, kObsoletePrefName,
+ /*out_value=*/nullptr));
+
+ bool custom_pref_value = false;
+ EXPECT_TRUE(known_user.GetBooleanPref(kDefaultAccountId, kCustomPrefName,
+ &custom_pref_value));
+ EXPECT_TRUE(custom_pref_value);
+
+ EXPECT_TRUE(known_user.GetIsEnterpriseManaged(kDefaultAccountId));
+}
+
+//
+// =============================================================================
+// Type-parametrized unittests for Set{String,Boolean,Integer,}Pref and
+// Get{String,Boolean,Integer,}Pref.
+// For every type (string, boolean, integer, raw base::Value) a PrefTypeInfo
+// struct is declared which is then referenced in the generic test code.
+
+// Test type holder for known_user string prefs.
+struct PrefTypeInfoString {
+ using PrefType = std::string;
+ using PrefTypeForReading = std::string;
+
+ static constexpr auto SetFunc = &KnownUser::SetStringPref;
+ static constexpr auto GetFunc = &KnownUser::GetStringPref;
+
+ static PrefType CreatePrefValue() { return std::string("test"); }
+ static bool CheckPrefValue(PrefTypeForReading read_value) {
+ return read_value == "test";
+ }
+ static bool CheckPrefValueAsBaseValue(const base::Value& read_value) {
+ return read_value.is_string() && read_value.GetString() == "test";
+ }
+};
+
+// Test type holder for known_user integer prefs.
+struct PrefTypeInfoInteger {
+ using PrefType = int;
+ using PrefTypeForReading = int;
+
+ static constexpr auto SetFunc = &KnownUser::SetIntegerPref;
+ static constexpr auto GetFunc = &KnownUser::GetIntegerPref;
+
+ static PrefType CreatePrefValue() { return 7; }
+ static bool CheckPrefValue(PrefTypeForReading read_value) {
+ return read_value == 7;
+ }
+ static bool CheckPrefValueAsBaseValue(const base::Value& read_value) {
+ return read_value.is_int() && read_value.GetInt() == 7;
+ }
+};
+
+// Test type holder for known_user boolean prefs.
+struct PrefTypeInfoBoolean {
+ using PrefType = bool;
+ using PrefTypeForReading = bool;
+
+ static constexpr auto SetFunc = &KnownUser::SetBooleanPref;
+ static constexpr auto GetFunc = &KnownUser::GetBooleanPref;
+
+ static PrefType CreatePrefValue() { return true; }
+ static bool CheckPrefValue(PrefTypeForReading read_value) {
+ return read_value == true;
+ }
+ static bool CheckPrefValueAsBaseValue(const base::Value& read_value) {
+ return read_value.is_bool() && read_value.GetBool() == true;
+ }
+};
+
+// Test type holder for known_user base::Value prefs.
+struct PrefTypeInfoValue {
+ using PrefType = base::Value;
+ using PrefTypeForReading = const base::Value*;
+
+ static constexpr auto SetFunc = &KnownUser::SetPref;
+ static constexpr auto GetFunc = &KnownUser::GetPref;
+
+ static PrefType CreatePrefValue() { return base::Value("test"); }
+ static bool CheckPrefValue(PrefTypeForReading read_value) {
+ return *read_value == CreatePrefValue();
+ }
+ static bool CheckPrefValueAsBaseValue(const base::Value& read_value) {
+ return read_value == CreatePrefValue();
+ }
+};
+
+template <typename PrefTypeInfo>
+class KnownUserWithPrefTypeTest : public KnownUserTest {
+ public:
+ KnownUserWithPrefTypeTest() = default;
+ ~KnownUserWithPrefTypeTest() = default;
+};
+
+TYPED_TEST_SUITE_P(KnownUserWithPrefTypeTest);
+
+TYPED_TEST_P(KnownUserWithPrefTypeTest, ReadOnNonExistingUser) {
+ KnownUser known_user(KnownUserTest::local_state());
+
+ constexpr char kPrefName[] = "some_pref";
+ const AccountId kNonExistingUser =
+ AccountId::FromUserEmail("account1@gmail.com");
+
+ typename TypeParam::PrefTypeForReading read_result;
+ bool read_success = (known_user.*TypeParam::GetFunc)(kNonExistingUser,
+ kPrefName, &read_result);
+ EXPECT_FALSE(read_success);
+}
+
+TYPED_TEST_P(KnownUserWithPrefTypeTest, ReadMissingPrefOnExistingUser) {
+ KnownUser known_user(KnownUserTest::local_state());
+
+ constexpr char kPrefName[] = "some_pref";
+ const AccountId kUser = AccountId::FromUserEmail("account1@gmail.com");
+ known_user.SaveKnownUser(kUser);
+
+ typename TypeParam::PrefTypeForReading read_result;
+ bool read_success =
+ (known_user.*TypeParam::GetFunc)(kUser, kPrefName, &read_result);
+ EXPECT_FALSE(read_success);
+}
+
+TYPED_TEST_P(KnownUserWithPrefTypeTest, ReadExistingPref) {
+ KnownUser known_user(KnownUserTest::local_state());
+
+ constexpr char kPrefName[] = "some_pref";
+ const AccountId kUser = AccountId::FromUserEmail("account1@gmail.com");
+
+ // Set* implicitly creates the known_user user entry.
+ (known_user.*TypeParam::SetFunc)(kUser, kPrefName,
+ TypeParam::CreatePrefValue());
+
+ typename TypeParam::PrefTypeForReading read_result;
+ bool read_success =
+ (known_user.*TypeParam::GetFunc)(kUser, kPrefName, &read_result);
+ EXPECT_TRUE(read_success);
+ TypeParam::CheckPrefValue(read_result);
+}
+
+TYPED_TEST_P(KnownUserWithPrefTypeTest, ReadExistingPrefAsValue) {
+ KnownUser known_user(KnownUserTest::local_state());
+
+ constexpr char kPrefName[] = "some_pref";
+ const AccountId kUser = AccountId::FromUserEmail("account1@gmail.com");
+
+ // Set* implicitly creates the known_user user entry.
+ (known_user.*TypeParam::SetFunc)(kUser, kPrefName,
+ TypeParam::CreatePrefValue());
+
+ const base::Value* read_result;
+ bool read_success = known_user.GetPref(kUser, kPrefName, &read_result);
+ EXPECT_TRUE(read_success);
+ ASSERT_TRUE(read_result);
+ TypeParam::CheckPrefValueAsBaseValue(*read_result);
+}
+
+REGISTER_TYPED_TEST_SUITE_P(KnownUserWithPrefTypeTest,
+ // All test functions must be listed:
+ ReadOnNonExistingUser,
+ ReadMissingPrefOnExistingUser,
+ ReadExistingPref,
+ ReadExistingPrefAsValue);
+
+// This must be an alias because the preprocessor does not understand <> so if
+// it was directly embedded in the INSTANTIATE_TYPED_TEST_SUITE_P macro the
+// prepocessor would be confused on the comma.
+using AllTypeInfos = testing::Types<PrefTypeInfoString,
+ PrefTypeInfoInteger,
+ PrefTypeInfoBoolean,
+ PrefTypeInfoValue>;
+
+INSTANTIATE_TYPED_TEST_SUITE_P(AllTypes,
+ KnownUserWithPrefTypeTest,
+ AllTypeInfos);
+
+} // namespace user_manager
diff --git a/chromium/components/user_manager/user.cc b/chromium/components/user_manager/user.cc
index 3bdefd4f520..1766663565d 100644
--- a/chromium/components/user_manager/user.cc
+++ b/chromium/components/user_manager/user.cc
@@ -6,11 +6,12 @@
#include <stddef.h>
+#include <memory>
+
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "components/account_id/account_id.h"
@@ -335,7 +336,7 @@ User* User::CreatePublicAccountUser(const AccountId& account_id,
}
void User::SetAccountLocale(const std::string& resolved_account_locale) {
- account_locale_.reset(new std::string(resolved_account_locale));
+ account_locale_ = std::make_unique<std::string>(resolved_account_locale);
}
void User::SetImage(std::unique_ptr<UserImage> user_image, int image_index) {
diff --git a/chromium/components/user_manager/user.h b/chromium/components/user_manager/user.h
index 0891b46077d..75263bf811b 100644
--- a/chromium/components/user_manager/user.h
+++ b/chromium/components/user_manager/user.h
@@ -22,13 +22,13 @@ namespace ash {
class ChromeUserManagerImpl;
class FakeChromeUserManager;
class MockUserManager;
+class UserSessionManager;
class UserImageManagerImpl;
} // namespace ash
namespace chromeos {
class SupervisedUserManagerImpl;
class UserAddingScreenTest;
-class UserSessionManager;
} // namespace chromeos
namespace gfx {
@@ -216,7 +216,7 @@ class USER_MANAGER_EXPORT User : public UserInfo {
friend class ash::ChromeUserManagerImpl;
friend class chromeos::SupervisedUserManagerImpl;
friend class ash::UserImageManagerImpl;
- friend class chromeos::UserSessionManager;
+ friend class ash::UserSessionManager;
// For testing:
friend class FakeUserManager;
@@ -337,7 +337,7 @@ class USER_MANAGER_EXPORT User : public UserInfo {
bool profile_is_created_ = false;
// True if the user is affiliated to the device.
- base::Optional<bool> is_affiliated_;
+ absl::optional<bool> is_affiliated_;
std::vector<base::OnceClosure> on_profile_created_observers_;
std::vector<base::OnceCallback<void(bool is_affiliated)>>
diff --git a/chromium/components/user_manager/user_image/user_image.h b/chromium/components/user_manager/user_image/user_image.h
index 55e4978d143..7b8da5954ff 100644
--- a/chromium/components/user_manager/user_image/user_image.h
+++ b/chromium/components/user_manager/user_image/user_image.h
@@ -6,7 +6,6 @@
#define COMPONENTS_USER_MANAGER_USER_IMAGE_USER_IMAGE_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/files/file_path.h"
diff --git a/chromium/components/user_manager/user_manager_base.cc b/chromium/components/user_manager/user_manager_base.cc
index b674741c659..098523d2d62 100644
--- a/chromium/components/user_manager/user_manager_base.cc
+++ b/chromium/components/user_manager/user_manager_base.cc
@@ -21,7 +21,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "components/prefs/pref_registry_simple.h"
@@ -64,11 +63,6 @@ const char kLastLoggedInGaiaUser[] = "LastLoggedInRegularUser";
// session restore.
const char kLastActiveUser[] = "LastActiveUser";
-// Histogram for tracking the number of deprecated legacy supervised user
-// cryptohomes remaining in the wild.
-const char kHideLegacySupervisedUserHistogramName[] =
- "ChromeOS.LegacySupervisedUsers.HiddenFromLoginScreen";
-
// Upper bound for a histogram metric reporting the amount of time between
// one regular user logging out and a different regular user logging in.
const int kLogoutToLoginDelayMaxSec = 1800;
@@ -95,6 +89,13 @@ UserType GetStoredUserType(const base::DictionaryValue* prefs_user_types,
} // namespace
// static
+const char UserManagerBase::kLegacySupervisedUsersHistogramName[] =
+ "ChromeOS.LegacySupervisedUsers.HiddenFromLoginScreen";
+// static
+const base::Feature UserManagerBase::kRemoveLegacySupervisedUsersOnStartup{
+ "RemoveLegacySupervisedUsersOnStartup", base::FEATURE_ENABLED_BY_DEFAULT};
+
+// static
void UserManagerBase::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterListPref(kRegularUsersPref);
registry->RegisterStringPref(kLastLoggedInGaiaUser, std::string());
@@ -106,7 +107,7 @@ void UserManagerBase::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(kUserType);
registry->RegisterStringPref(kLastActiveUser, std::string());
- known_user::RegisterPrefs(registry);
+ KnownUser::RegisterPrefs(registry);
}
UserManagerBase::UserManagerBase(
@@ -329,7 +330,7 @@ void UserManagerBase::RemoveNonOwnerUserInternal(const AccountId& account_id,
void UserManagerBase::RemoveUserFromList(const AccountId& account_id) {
DCHECK(!task_runner_ || task_runner_->RunsTasksInCurrentSequence());
RemoveNonCryptohomeData(account_id);
- known_user::RemovePrefs(account_id);
+ KnownUser(GetLocalState()).RemovePrefs(account_id);
if (user_loading_stage_ == STAGE_LOADED) {
// After the User object is deleted from memory in DeleteUser() here,
// the account_id reference will be invalid if the reference points
@@ -805,10 +806,13 @@ void UserManagerBase::EnsureUsersLoaded() {
for (std::vector<AccountId>::const_iterator it = regular_users.begin();
it != regular_users.end(); ++it) {
if (IsDeprecatedSupervisedAccountId(*it)) {
- base::UmaHistogramBoolean(kHideLegacySupervisedUserHistogramName, true);
+ RemoveLegacySupervisedUser(*it);
+ // Hide legacy supervised users from the login screen if not removed.
continue;
}
- base::UmaHistogramBoolean(kHideLegacySupervisedUserHistogramName, false);
+ base::UmaHistogramEnumeration(
+ kLegacySupervisedUsersHistogramName,
+ LegacySupervisedUserStatus::kGaiaUserDisplayed);
User* user =
User::CreateRegularUser(*it, GetStoredUserType(prefs_user_types, *it));
user->set_oauth_token_status(LoadUserOAuthStatus(*it));
@@ -912,7 +916,8 @@ void UserManagerBase::RegularUserLoggedIn(const AccountId& account_id,
}
AddUserRecord(active_user_);
- known_user::SetIsEphemeralUser(active_user_->GetAccountId(), false);
+ KnownUser(GetLocalState())
+ .SetIsEphemeralUser(active_user_->GetAccountId(), false);
// Make sure that new data is persisted to Local State.
GetLocalState()->CommitPendingWrite();
@@ -925,7 +930,8 @@ void UserManagerBase::RegularUserLoggedInAsEphemeral(
SetIsCurrentUserNew(true);
is_current_user_ephemeral_regular_user_ = true;
active_user_ = User::CreateRegularUser(account_id, user_type);
- known_user::SetIsEphemeralUser(active_user_->GetAccountId(), true);
+ KnownUser(GetLocalState())
+ .SetIsEphemeralUser(active_user_->GetAccountId(), true);
}
void UserManagerBase::NotifyActiveUserChanged(User* active_user) {
@@ -989,7 +995,7 @@ void UserManagerBase::RemoveNonCryptohomeData(const AccountId& account_id) {
DictionaryPrefUpdate prefs_force_online_update(prefs, kUserForceOnlineSignin);
prefs_force_online_update->RemoveKey(account_id.GetUserEmail());
- known_user::RemovePrefs(account_id);
+ KnownUser(prefs).RemovePrefs(account_id);
const AccountId last_active_user =
AccountId::FromUserEmail(GetLocalState()->GetString(kLastActiveUser));
@@ -1037,8 +1043,15 @@ void UserManagerBase::NotifyActiveUserHashChanged(const std::string& hash) {
void UserManagerBase::Initialize() {
UserManager::Initialize();
- if (!HasBrowserRestarted())
- known_user::CleanEphemeralUsers();
+ if (!HasBrowserRestarted()) {
+ PrefService* local_state = GetLocalState();
+ // local_state may be null in unit tests.
+ if (local_state) {
+ KnownUser known_user(local_state);
+ known_user.CleanEphemeralUsers();
+ known_user.CleanObsoletePrefs();
+ }
+ }
CallUpdateLoginState();
}
@@ -1091,7 +1104,7 @@ void UserManagerBase::UpdateUserAccountLocale(const AccountId& account_id,
std::move(resolved_locale)),
raw_resolved_locale);
} else {
- resolved_locale.reset(new std::string(locale));
+ resolved_locale = std::make_unique<std::string>(locale);
DoUpdateAccountLocale(account_id, std::move(resolved_locale));
}
}
@@ -1111,4 +1124,23 @@ void UserManagerBase::DeleteUser(User* user) {
active_user_ = nullptr;
}
+// TODO(crbug/1189715): Remove dormant legacy supervised user cryptohomes. After
+// we have enough confidence that there are no more supervised users on devices
+// in the wild, remove this.
+void UserManagerBase::RemoveLegacySupervisedUser(const AccountId& account_id) {
+ DCHECK(IsDeprecatedSupervisedAccountId(account_id));
+ if (base::FeatureList::IsEnabled(kRemoveLegacySupervisedUsersOnStartup)) {
+ // Since we skip adding legacy supervised users to the users list,
+ // FindUser(account_id) returns nullptr and CanUserBeRemoved() returns
+ // false. This is why we call RemoveUserInternal() directly instead of
+ // RemoveUser().
+ RemoveUserInternal(account_id, /*delegate=*/nullptr);
+ base::UmaHistogramEnumeration(kLegacySupervisedUsersHistogramName,
+ LegacySupervisedUserStatus::kLSUDeleted);
+ } else {
+ base::UmaHistogramEnumeration(kLegacySupervisedUsersHistogramName,
+ LegacySupervisedUserStatus::kLSUHidden);
+ }
+}
+
} // namespace user_manager
diff --git a/chromium/components/user_manager/user_manager_base.h b/chromium/components/user_manager/user_manager_base.h
index 8305a8bff8a..c3c9183550b 100644
--- a/chromium/components/user_manager/user_manager_base.h
+++ b/chromium/components/user_manager/user_manager_base.h
@@ -38,11 +38,40 @@ class RemoveUserDelegate;
// Base implementation of the UserManager interface.
class USER_MANAGER_EXPORT UserManagerBase : public UserManager {
public:
+ // These enum values represent a legacy supervised user's (LSU) status on the
+ // sign in screen.
+ // TODO(crbug/1155729): Remove once all LSUs deleted in the wild. LSUs were
+ // first hidden on the login screen in M74. Assuming a five year AUE, we
+ // should stop supporting devices with LSUs by 2024.
+ // These values are logged to UMA. Entries should not be renumbered and
+ // numeric values should never be reused. Please keep in sync with
+ // "LegacySupervisedUserStatus" in src/tools/metrics/histograms/enums.xml.
+ enum class LegacySupervisedUserStatus {
+ // Non-LSU Gaia user displayed on login screen.
+ kGaiaUserDisplayed = 0,
+ // LSU hidden on login screen. Expect this count to decline to zero over
+ // time as we delete LSUs.
+ kLSUHidden = 1,
+ // LSU attempted to delete cryptohome. Expect this count to decline to zero
+ // over time as we delete LSUs.
+ kLSUDeleted = 2,
+ // Add future entires above this comment, in sync with
+ // "LegacySupervisedUserStatus" in src/tools/metrics/histograms/enums.xml.
+ // Update kMaxValue to the last value.
+ kMaxValue = kLSUDeleted
+ };
+
// Creates UserManagerBase with |task_runner| for UI thread.
explicit UserManagerBase(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~UserManagerBase() override;
+ // Histogram for tracking the number of deprecated legacy supervised user
+ // cryptohomes remaining in the wild.
+ static const char kLegacySupervisedUsersHistogramName[];
+ // Feature that removes legacy supervised users.
+ static const base::Feature kRemoveLegacySupervisedUsersOnStartup;
+
// Registers UserManagerBase preferences.
static void RegisterPrefs(PrefRegistrySimple* registry);
@@ -322,6 +351,8 @@ class USER_MANAGER_EXPORT UserManagerBase : public UserManager {
void DoUpdateAccountLocale(const AccountId& account_id,
std::unique_ptr<std::string> resolved_locale);
+ void RemoveLegacySupervisedUser(const AccountId& account_id);
+
// Indicates stage of loading user from prefs.
UserLoadStage user_loading_stage_ = STAGE_NOT_LOADED;
diff --git a/chromium/components/user_manager/user_manager_export.h b/chromium/components/user_manager/user_manager_export.h
index 3bd54572ff3..9f6877ff7b5 100644
--- a/chromium/components/user_manager/user_manager_export.h
+++ b/chromium/components/user_manager/user_manager_export.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_USER_MANAGER_USERS_EXPORT_H_
-#define COMPONENTS_USER_MANAGER_USERS_EXPORT_H_
+#ifndef COMPONENTS_USER_MANAGER_USER_MANAGER_EXPORT_H_
+#define COMPONENTS_USER_MANAGER_USER_MANAGER_EXPORT_H_
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
@@ -26,4 +26,4 @@
#define USER_MANAGER_EXPORT
#endif
-#endif // COMPONENTS_USER_MANAGER_USERS_EXPORT_H_
+#endif // COMPONENTS_USER_MANAGER_USER_MANAGER_EXPORT_H_
diff --git a/chromium/components/user_prefs/DIR_METADATA b/chromium/components/user_prefs/DIR_METADATA
index 1b859d641e2..e9153b069b8 100644
--- a/chromium/components/user_prefs/DIR_METADATA
+++ b/chromium/components/user_prefs/DIR_METADATA
@@ -1,5 +1,5 @@
monorail {
- component: "UI>Browser>Preferences"
+ component: "Internals>Preferences"
}
team_email: "chromium-dev@chromium.org"
diff --git a/chromium/components/variations/BUILD.gn b/chromium/components/variations/BUILD.gn
index e13a93b088a..23163a2ecb1 100644
--- a/chromium/components/variations/BUILD.gn
+++ b/chromium/components/variations/BUILD.gn
@@ -104,16 +104,23 @@ static_library("variations") {
]
}
+ if (is_chromeos_ash) {
+ sources += [
+ "variations_crash_keys_chromeos.cc",
+ "variations_crash_keys_chromeos.h",
+ ]
+ }
+
public_deps = [
":variations_features",
"proto",
+ "//base",
]
deps = [
":buildflags",
":variations_mojom",
"proto",
- "//base",
"//build:chromeos_buildflags",
"//components/crash/core/common:crash_key",
"//components/prefs",
@@ -196,6 +203,10 @@ source_set("unit_tests") {
sources += [ "variations_request_scheduler_mobile_unittest.cc" ]
}
+ if (is_chromeos_ash) {
+ sources += [ "variations_crash_keys_chromeos_unittest.cc" ]
+ }
+
deps = [
":test_support",
":variations",
diff --git a/chromium/components/variations/active_field_trials.cc b/chromium/components/variations/active_field_trials.cc
index ae0fb9fd3bb..7edcfabc6f9 100644
--- a/chromium/components/variations/active_field_trials.cc
+++ b/chromium/components/variations/active_field_trials.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/lazy_instance.h"
+#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "components/variations/hashing.h"
@@ -29,8 +30,8 @@ void GetFieldTrialActiveGroupIdsForActiveGroups(
DCHECK(name_group_ids->empty());
for (auto it = active_groups.begin(); it != active_groups.end(); ++it) {
name_group_ids->push_back(
- MakeActiveGroupId(it->trial_name + suffix.as_string(),
- it->group_name + suffix.as_string()));
+ MakeActiveGroupId(it->trial_name + std::string(suffix),
+ it->group_name + std::string(suffix)));
}
}
diff --git a/chromium/components/variations/android/variations_seed_bridge.h b/chromium/components/variations/android/variations_seed_bridge.h
index 652623b9d6d..e4ac1854774 100644
--- a/chromium/components/variations/android/variations_seed_bridge.h
+++ b/chromium/components/variations/android/variations_seed_bridge.h
@@ -38,4 +38,4 @@ bool HasMarkedPrefsForTesting();
} // namespace android
} // namespace variations
-#endif // COMPONENTS_VARIATIONS_ANDROID_FIRSTRUN_VARIATIONS_SEED_BRIDGE_H_
+#endif // COMPONENTS_VARIATIONS_ANDROID_VARIATIONS_SEED_BRIDGE_H_
diff --git a/chromium/components/variations/child_process_field_trial_syncer.cc b/chromium/components/variations/child_process_field_trial_syncer.cc
index 6825bdd2d14..eac367958f0 100644
--- a/chromium/components/variations/child_process_field_trial_syncer.cc
+++ b/chromium/components/variations/child_process_field_trial_syncer.cc
@@ -13,26 +13,49 @@
namespace variations {
+namespace {
+
+ChildProcessFieldTrialSyncer* g_instance = nullptr;
+
+} // namespace
+
+// static
+ChildProcessFieldTrialSyncer* ChildProcessFieldTrialSyncer::CreateInstance(
+ FieldTrialActivatedCallback activated_callback) {
+ DCHECK(!g_instance);
+ g_instance = new ChildProcessFieldTrialSyncer(std::move(activated_callback));
+ g_instance->Init();
+ return g_instance;
+}
+
+// static
+void ChildProcessFieldTrialSyncer::DeleteInstanceForTesting() {
+ DCHECK(g_instance);
+ delete g_instance;
+ g_instance = nullptr;
+ // Revert the effect of calling variations::InitCrashKeys() in Init().
+ ClearCrashKeysInstanceForTesting(); // IN-TEST
+}
+
ChildProcessFieldTrialSyncer::ChildProcessFieldTrialSyncer(
- base::FieldTrialList::Observer* observer)
- : observer_(observer) {}
+ FieldTrialActivatedCallback activated_callback)
+ : activated_callback_(std::move(activated_callback)) {}
-ChildProcessFieldTrialSyncer::~ChildProcessFieldTrialSyncer() {}
+ChildProcessFieldTrialSyncer::~ChildProcessFieldTrialSyncer() = default;
-void ChildProcessFieldTrialSyncer::InitFieldTrialObserving(
- const base::CommandLine& command_line) {
+void ChildProcessFieldTrialSyncer::Init() {
// Set up initial set of crash dump data for field trials in this process.
variations::InitCrashKeys();
// Listen for field trial activations to report them to the browser.
- base::FieldTrialList::AddObserver(observer_);
+ base::FieldTrialList::AddObserver(this);
// Some field trials may have been activated before this point. Notify the
// browser of these activations now. To detect these, take the set difference
// of currently active trials with the initially active trials.
base::FieldTrial::ActiveGroups initially_active_trials;
- base::FieldTrialList::GetInitiallyActiveFieldTrials(command_line,
- &initially_active_trials);
+ base::FieldTrialList::GetInitiallyActiveFieldTrials(
+ *base::CommandLine::ForCurrentProcess(), &initially_active_trials);
std::set<std::string> initially_active_trials_set;
for (const auto& entry : initially_active_trials) {
initially_active_trials_set.insert(std::move(entry.trial_name));
@@ -42,18 +65,34 @@ void ChildProcessFieldTrialSyncer::InitFieldTrialObserving(
base::FieldTrialList::GetActiveFieldTrialGroups(&current_active_trials);
for (const auto& trial : current_active_trials) {
if (!base::Contains(initially_active_trials_set, trial.trial_name))
- observer_->OnFieldTrialGroupFinalized(trial.trial_name, trial.group_name);
+ activated_callback_.Run(trial.trial_name);
}
}
-void ChildProcessFieldTrialSyncer::OnSetFieldTrialGroup(
+void ChildProcessFieldTrialSyncer::SetFieldTrialGroupFromBrowser(
const std::string& trial_name,
const std::string& group_name) {
+ DCHECK(!in_set_field_trial_group_from_browser_.Get());
+ in_set_field_trial_group_from_browser_.Set(true);
+
base::FieldTrial* trial =
base::FieldTrialList::CreateFieldTrial(trial_name, group_name);
// Ensure the trial is marked as "used" by calling group() on it if it is
// marked as activated.
trial->group();
+
+ in_set_field_trial_group_from_browser_.Set(false);
+}
+
+void ChildProcessFieldTrialSyncer::OnFieldTrialGroupFinalized(
+ const std::string& trial_name,
+ const std::string& group_name) {
+ // It is not necessary to notify the browser if this is invoked from
+ // SetFieldTrialGroupFromBrowser().
+ if (in_set_field_trial_group_from_browser_.Get())
+ return;
+
+ activated_callback_.Run(trial_name);
}
} // namespace variations
diff --git a/chromium/components/variations/child_process_field_trial_syncer.h b/chromium/components/variations/child_process_field_trial_syncer.h
index 22f946513ae..ed6b5708738 100644
--- a/chromium/components/variations/child_process_field_trial_syncer.h
+++ b/chromium/components/variations/child_process_field_trial_syncer.h
@@ -1,50 +1,72 @@
+
// 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_VARIATIONS_FIELD_TRIAL_SYNCER_H_
-#define COMPONENTS_VARIATIONS_FIELD_TRIAL_SYNCER_H_
+#ifndef COMPONENTS_VARIATIONS_CHILD_PROCESS_FIELD_TRIAL_SYNCER_H_
+#define COMPONENTS_VARIATIONS_CHILD_PROCESS_FIELD_TRIAL_SYNCER_H_
#include <string>
+#include "base/callback.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
-
-namespace base {
-class CommandLine;
-}
+#include "base/threading/thread_local.h"
namespace variations {
-// ChildProcessFieldTrialSyncer is a utility class that's responsible for
-// syncing the "activated" state of field trials between browser and child
+// Syncs the "activated" state of field trials between browser and child
// processes. Specifically, when a field trial is activated in the browser, it
-// also activates it in the child process and when a field trial is activated
-// in the child process, it notifies the browser process to activate it.
-class ChildProcessFieldTrialSyncer {
+// also activates it in the child process and when a field trial is activated in
+// the child process, it notifies the browser process to activate it.
+class ChildProcessFieldTrialSyncer : public base::FieldTrialList::Observer {
public:
- // ChildProcessFieldTrialSyncer constructor taking an externally owned
- // |observer| param that's responsible for sending IPCs to the browser process
- // when a trial is activated. The |observer| must outlive this object.
- explicit ChildProcessFieldTrialSyncer(
- base::FieldTrialList::Observer* observer);
- ~ChildProcessFieldTrialSyncer();
+ using FieldTrialActivatedCallback =
+ base::RepeatingCallback<void(const std::string& trial_name)>;
- // Initializes field trial state change observation and notifies the browser
- // of any field trials that might have already been activated.
- void InitFieldTrialObserving(const base::CommandLine& command_line);
+ // Creates and returns the global ChildProcessFieldTrialSyncer instance for
+ // this process. Immediately invokes |activated_callback| for each currently
+ // active field trial. Then, |activated_callback| is invoked as field trial
+ // are activated. |activated_callback| may be invoked from any sequence and
+ // must therefore be thread-safe. CreateInstance() must not be called
+ // concurrently with activating a field trial. The created instance is never
+ // destroyed because it would be difficult to ensure that no field trial is
+ // activated concurrently with unregistering it as an observer of
+ // FieldTrialList (see FieldTrialList::RemoveObserver).
+ static ChildProcessFieldTrialSyncer* CreateInstance(
+ FieldTrialActivatedCallback activated_callback);
- // Handler for messages from the browser process notifying the child process
- // that a field trial was activated.
- void OnSetFieldTrialGroup(const std::string& trial_name,
- const std::string& group_name);
+ // Deletes the global ChildProcessFieldTrialSyncer instance.
+ static void DeleteInstanceForTesting();
+
+ // Must be invoked when the browser process notifies this child process that a
+ // field trial was activated.
+ void SetFieldTrialGroupFromBrowser(const std::string& trial_name,
+ const std::string& group_name);
private:
- base::FieldTrialList::Observer* const observer_;
+ explicit ChildProcessFieldTrialSyncer(
+ FieldTrialActivatedCallback activated_callback);
+ ~ChildProcessFieldTrialSyncer() override;
+
+ // Initializes field trial state change observation and invokes |callback_|
+ // for any field trials that might have already been activated.
+ void Init();
+
+ // base::FieldTrialList::Observer:
+ void OnFieldTrialGroupFinalized(const std::string& trial_name,
+ const std::string& group_name) override;
+
+ // Whether SetFieldTrialGroupFromBrowser() is being called on the current
+ // thread.
+ base::ThreadLocalBoolean in_set_field_trial_group_from_browser_;
+
+ // Callback to invoke when a field trial is activated.
+ const FieldTrialActivatedCallback activated_callback_;
DISALLOW_COPY_AND_ASSIGN(ChildProcessFieldTrialSyncer);
};
} // namespace variations
-#endif // COMPONENTS_VARIATIONS_FIELD_TRIAL_SYNCER_H_
+#endif // COMPONENTS_VARIATIONS_CHILD_PROCESS_FIELD_TRIAL_SYNCER_H_
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 4493e7abbcd..bab525295c6 100644
--- a/chromium/components/variations/child_process_field_trial_syncer_unittest.cc
+++ b/chromium/components/variations/child_process_field_trial_syncer_unittest.cc
@@ -5,55 +5,20 @@
#include "components/variations/child_process_field_trial_syncer.h"
#include <string>
-#include <utility>
#include <vector>
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/metrics/field_trial.h"
-#include "base/run_loop.h"
+#include "base/test/bind.h"
#include "base/test/task_environment.h"
-#include "components/variations/variations_crash_keys.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace variations {
-namespace {
-
-// TestFieldTrialObserver to listen to be notified by the child process syncer.
-class TestFieldTrialObserver : public base::FieldTrialList::Observer {
- public:
- TestFieldTrialObserver() {}
- ~TestFieldTrialObserver() override { ClearCrashKeysInstanceForTesting(); }
-
- // base::FieldTrialList::Observer:
- void OnFieldTrialGroupFinalized(const std::string& trial_name,
- const std::string& group_name) override {
- observed_entries_.push_back(std::make_pair(trial_name, group_name));
- }
-
- size_t observed_entries_count() const { return observed_entries_.size(); }
-
- std::pair<std::string, std::string> get_observed_entry(int i) const {
- return observed_entries_[i];
- }
-
- private:
- std::vector<std::pair<std::string, std::string>> observed_entries_;
-
- DISALLOW_COPY_AND_ASSIGN(TestFieldTrialObserver);
-};
-
-// Needed because make_pair("a", "b") doesn't convert to std::string pair.
-std::pair<std::string, std::string> MakeStringPair(const std::string& a,
- const std::string& b) {
- return std::make_pair(a, b);
-}
-
-} // namespace
-
TEST(ChildProcessFieldTrialSyncerTest, FieldTrialState) {
- base::test::SingleThreadTaskEnvironment task_environment;
+ base::test::TaskEnvironment task_environment;
// We don't use the descriptor here anyways so it's ok to pass -1.
base::FieldTrialList::CreateTrialsFromCommandLine(
@@ -75,24 +40,24 @@ TEST(ChildProcessFieldTrialSyncerTest, FieldTrialState) {
// Active trial 2 before creating the syncer.
trial2->group();
- TestFieldTrialObserver observer;
- ChildProcessFieldTrialSyncer syncer(&observer);
- syncer.InitFieldTrialObserving(*base::CommandLine::ForCurrentProcess());
+ std::vector<std::string> observed_trial_names;
+ auto callback =
+ base::BindLambdaForTesting([&](const std::string& trial_name) {
+ observed_trial_names.push_back(trial_name);
+ });
+
+ ChildProcessFieldTrialSyncer::CreateInstance(callback);
- // The observer should be notified of activated entries that were not activate
+ // The callback should be invoked for activated trials that were not specified
// on the command line. In this case, trial 2. (Trial 1 was already active via
// command line and so its state shouldn't be notified.)
- ASSERT_EQ(1U, observer.observed_entries_count());
- EXPECT_EQ(MakeStringPair("B", "G2"), observer.get_observed_entry(0));
+ EXPECT_THAT(observed_trial_names, testing::ElementsAre("B"));
// Now, activate trial 3, which should also get reflected.
trial3->group();
- // Notifications from field trial activation actually happen via posted tasks,
- // so invoke the run loop.
- base::RunLoop().RunUntilIdle();
+ EXPECT_THAT(observed_trial_names, testing::ElementsAre("B", "C"));
- ASSERT_EQ(2U, observer.observed_entries_count());
- EXPECT_EQ(MakeStringPair("C", "G3"), observer.get_observed_entry(1));
+ ChildProcessFieldTrialSyncer::DeleteInstanceForTesting();
}
} // namespace variations
diff --git a/chromium/components/variations/client_filterable_state.cc b/chromium/components/variations/client_filterable_state.cc
index 35883cd5b1e..e51e7cd1c40 100644
--- a/chromium/components/variations/client_filterable_state.cc
+++ b/chromium/components/variations/client_filterable_state.cc
@@ -18,7 +18,7 @@ Study::Platform ClientFilterableState::GetCurrentPlatform() {
return Study::PLATFORM_WINDOWS;
#elif defined(OS_IOS)
return Study::PLATFORM_IOS;
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
return Study::PLATFORM_MAC;
#elif BUILDFLAG(IS_CHROMEOS_ASH)
return Study::PLATFORM_CHROMEOS;
diff --git a/chromium/components/variations/client_filterable_state.h b/chromium/components/variations/client_filterable_state.h
index 7480d3a8eaa..06c3c406359 100644
--- a/chromium/components/variations/client_filterable_state.h
+++ b/chromium/components/variations/client_filterable_state.h
@@ -9,10 +9,10 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "base/version.h"
#include "components/variations/proto/study.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace variations {
@@ -92,7 +92,7 @@ struct ClientFilterableState {
// evaluate it if needed (i.e. if a study is filtering by enterprise) and at
// most once.
mutable IsEnterpriseFunction is_enterprise_function_;
- mutable base::Optional<bool> is_enterprise_;
+ mutable absl::optional<bool> is_enterprise_;
DISALLOW_COPY_AND_ASSIGN(ClientFilterableState);
};
diff --git a/chromium/components/variations/field_trial_config/field_trial_testing_config_schema.json b/chromium/components/variations/field_trial_config/field_trial_testing_config_schema.json
index 68499c29c4d..710f8af3533 100644
--- a/chromium/components/variations/field_trial_config/field_trial_testing_config_schema.json
+++ b/chromium/components/variations/field_trial_config/field_trial_testing_config_schema.json
@@ -4,7 +4,7 @@
{
"type_name": "FieldTrialTestingConfig",
- "headers": ["base/optional.h", "components/variations/proto/study.pb.h"],
+ "headers": ["third_party/abseil-cpp/absl/types/optional.h", "components/variations/proto/study.pb.h"],
"schema": [{
"field": "studies",
"type": "array",
@@ -34,8 +34,8 @@
{
"field": "is_low_end_device",
"type": "class",
- "ctype": "base::Optional<bool>",
- "default": "base::nullopt",
+ "ctype": "absl::optional<bool>",
+ "default": "absl::nullopt",
"optional": "True"
},
{
diff --git a/chromium/components/variations/field_trial_config/field_trial_util.cc b/chromium/components/variations/field_trial_config/field_trial_util.cc
index 74c72ecb662..4d7f8396cd0 100644
--- a/chromium/components/variations/field_trial_config/field_trial_util.cc
+++ b/chromium/components/variations/field_trial_config/field_trial_util.cc
@@ -16,13 +16,13 @@
#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "components/variations/client_filterable_state.h"
#include "components/variations/field_trial_config/fieldtrial_testing_config.h"
#include "components/variations/variations_seed_processor.h"
#include "net/base/escape.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/device_form_factor.h"
namespace variations {
diff --git a/chromium/components/variations/field_trial_config/field_trial_util_unittest.cc b/chromium/components/variations/field_trial_config/field_trial_util_unittest.cc
index 0449e7d38d8..34344103695 100644
--- a/chromium/components/variations/field_trial_config/field_trial_util_unittest.cc
+++ b/chromium/components/variations/field_trial_config/field_trial_util_unittest.cc
@@ -12,7 +12,6 @@
#include "base/macros.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
@@ -24,6 +23,7 @@
#include "components/variations/variations_seed_processor.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/device_form_factor.h"
namespace variations {
@@ -142,7 +142,7 @@ TEST_F(FieldTrialUtilTest, AssociateParamsFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
array_kFieldTrialConfig_params_0,
2,
@@ -162,7 +162,7 @@ TEST_F(FieldTrialUtilTest, AssociateParamsFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
array_kFieldTrialConfig_params_0,
2,
@@ -178,7 +178,7 @@ TEST_F(FieldTrialUtilTest, AssociateParamsFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
array_kFieldTrialConfig_params_1,
2,
@@ -246,7 +246,7 @@ TEST_F(FieldTrialUtilTest,
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
array_kFieldTrialConfig_params,
2,
@@ -294,7 +294,7 @@ TEST_F(FieldTrialUtilTest,
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
array_kFieldTrialConfig_params,
2,
@@ -338,7 +338,7 @@ TEST_F(FieldTrialUtilTest,
2,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
array_kFieldTrialConfig_params,
2,
@@ -385,7 +385,7 @@ TEST_F(FieldTrialUtilTest,
const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] =
{{"x", "1"}, {"y", "2"}};
const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = {
- {"TestGroup", &platform, 1, form_factors, 4, base::nullopt, nullptr,
+ {"TestGroup", &platform, 1, form_factors, 4, absl::nullopt, nullptr,
array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr,
nullptr, 0},
};
@@ -420,7 +420,7 @@ TEST_F(FieldTrialUtilTest,
const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] =
{{"x", "1"}, {"y", "2"}};
const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = {
- {"TestGroup", &platform, 1, &form_factor, 1, base::nullopt, nullptr,
+ {"TestGroup", &platform, 1, &form_factor, 1, absl::nullopt, nullptr,
array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr,
nullptr, 0},
};
@@ -466,7 +466,7 @@ TEST_F(FieldTrialUtilTest,
const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] =
{{"x", "1"}, {"y", "2"}};
const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = {
- {"TestGroup", &platform, 1, &form_factor, 1, base::nullopt, nullptr,
+ {"TestGroup", &platform, 1, &form_factor, 1, absl::nullopt, nullptr,
array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr,
nullptr, 0},
};
@@ -507,7 +507,7 @@ TEST_F(FieldTrialUtilTest, AssociateFeaturesFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
nullptr,
0,
@@ -525,7 +525,7 @@ TEST_F(FieldTrialUtilTest, AssociateFeaturesFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
nullptr,
0,
@@ -541,7 +541,7 @@ TEST_F(FieldTrialUtilTest, AssociateFeaturesFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
nullptr,
0,
@@ -591,7 +591,7 @@ TEST_F(FieldTrialUtilTest, AssociateForcingFlagsFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
nullptr,
0,
@@ -608,7 +608,7 @@ TEST_F(FieldTrialUtilTest, AssociateForcingFlagsFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
nullptr,
0,
@@ -624,7 +624,7 @@ TEST_F(FieldTrialUtilTest, AssociateForcingFlagsFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
nullptr,
0,
@@ -642,7 +642,7 @@ TEST_F(FieldTrialUtilTest, AssociateForcingFlagsFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
nullptr,
0,
@@ -658,7 +658,7 @@ TEST_F(FieldTrialUtilTest, AssociateForcingFlagsFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
nullptr,
0,
@@ -674,7 +674,7 @@ TEST_F(FieldTrialUtilTest, AssociateForcingFlagsFromFieldTrialConfig) {
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
nullptr,
nullptr,
0,
@@ -716,7 +716,7 @@ TEST_F(FieldTrialUtilTest,
const OverrideUIString array_kFieldTrialConfig_override_ui_string[] =
{{1234, "test1"}, {5678, "test2"}};
const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = {
- {"TestGroup", &platform, 1, nullptr, 0, base::nullopt, nullptr,
+ {"TestGroup", &platform, 1, nullptr, 0, absl::nullopt, nullptr,
array_kFieldTrialConfig_params, 2, nullptr, 0, nullptr, 0, nullptr,
array_kFieldTrialConfig_override_ui_string, 2},
};
@@ -848,7 +848,7 @@ TEST_F(FieldTrialUtilTest,
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
min_os_version.c_str(),
array_kFieldTrialConfig_params,
2,
@@ -895,7 +895,7 @@ TEST_F(FieldTrialUtilTest,
1,
{},
0,
- base::nullopt,
+ absl::nullopt,
min_os_version.c_str(),
array_kFieldTrialConfig_params,
2,
diff --git a/chromium/components/variations/pref_names.cc b/chromium/components/variations/pref_names.cc
index 42022dfeca7..03783fa316b 100644
--- a/chromium/components/variations/pref_names.cc
+++ b/chromium/components/variations/pref_names.cc
@@ -7,6 +7,13 @@
namespace variations {
namespace prefs {
+// Reflects the state of the "DeviceChromeVariations" policy. The policy
+// determines if and which variations should be enabled for the client on
+// ChromeOS. The possible values are defined in the
+// variations::RestrictionPolicy enum.
+const char kDeviceVariationsRestrictionsByPolicy[] =
+ "device_variations_restrictions_by_policy";
+
// base64-encoded compressed serialized form of the variations seed protobuf.
const char kVariationsCompressedSeed[] = "variations_compressed_seed";
@@ -34,12 +41,18 @@ const char kVariationsPermanentConsistencyCountry[] =
"variations_permanent_consistency_country";
// A country code string representing the country used for filtering permanent
-// consistency studies and will not be updated on Chrome updated. It can be
-// changed via chrome://translate-internals and is intended for
-// testing / developer use.
+// consistency studies. This is not updated when Chrome is updated, but it can
+// be changed via chrome://translate-internals and is intended for testing and
+// developer use.
const char kVariationsPermanentOverriddenCountry[] =
"variations_permanent_overridden_country";
+// Reflects the state of the "ChromeVariations" policy. The policy determines if
+// and which variations should be enabled for the client. The possible values
+// are defined in the variations::RestrictionPolicy enum.
+const char kVariationsRestrictionsByPolicy[] =
+ "variations_restrictions_by_policy";
+
// String for the restrict parameter to be appended to the variations URL.
const char kVariationsRestrictParameter[] = "variations_restrict_parameter";
@@ -52,18 +65,18 @@ const char kVariationsRestrictParameter[] = "variations_restrict_parameter";
const char kVariationsSafeCompressedSeed[] = "variations_safe_compressed_seed";
// The serialized base::Time used for safe seed expiry checks. This is usually
-// the time at which the last known "safe" seed was received, though it could
-// potentially be a build timestamp instead, if the received date is unknown. An
-// empty (default-constructed) base::Time if there is no known "safe" seed. This
-// is a server-provided timestamp.
+// the time at which the last known "safe" seed was received; however, it could
+// be a build timestamp if the received date is unknown. An empty
+// (default-constructed) base::Time if there is no known "safe" seed. This is a
+// server-provided timestamp.
const char kVariationsSafeSeedDate[] = "variations_safe_seed_date";
// The serialized base::Time from the fetch corresponding to the safe seed, i.e.
-// a copy of the last value stored to the |kVariationsLastFetchTime| pref that
+// a copy of the last value stored in the |kVariationsLastFetchTime| pref that
// corresponded to the same seed contents as the safe seed. This is a client
// timestamp.
// Note: This pref was added about a milestone after most of the other safe seed
-// prefs, and so might be missing for some clients that otherwise have safe seed
+// prefs, so it might be missing for some clients that otherwise have safe seed
// data.
const char kVariationsSafeSeedFetchTime[] = "variations_safe_seed_fetch_time";
@@ -71,15 +84,15 @@ const char kVariationsSafeSeedFetchTime[] = "variations_safe_seed_fetch_time";
// last known "safe" seed.
const char kVariationsSafeSeedLocale[] = "variations_safe_seed_locale";
-// The country code used by the VariationsService for evaluating permanent
-// consistency studies, that was successfully used in association with the last
-// known "safe" seed.
+// A saved copy of |kVariationsPermanentConsistencyCountry|. The saved value is
+// the most recent value that was successfully used by the VariationsService for
+// evaluating permanent consistency studies.
const char kVariationsSafeSeedPermanentConsistencyCountry[] =
"variations_safe_seed_permanent_consistency_country";
-// The country code received by the VariationsService for evaluating studies,
-// that was successfully used in association with the last known "safe" seed.
-// This is the country code used for session consistency studies.
+// A saved copy of |kVariationsCountry|. The saved value is the most recent
+// value that was successfully used by the VariationsService for evaluating
+// session consistency studies.
const char kVariationsSafeSeedSessionConsistencyCountry[] =
"variations_safe_seed_session_consistency_country";
@@ -94,18 +107,5 @@ const char kVariationsSeedDate[] = "variations_seed_date";
// Digital signature of the binary variations seed data, base64-encoded.
const char kVariationsSeedSignature[] = "variations_seed_signature";
-// Reflects the state of the "ChromeVariations" policy which determines
-// if and which variations should be enabled for the client. The possible
-// values are defined in the VariationsService::RestrictionPolicyValues enum.
-const char kVariationsRestrictionsByPolicy[] =
- "variations_restrictions_by_policy";
-
-// Reflects the state of the "DeviceChromeVariations" policy which determines
-// if and which variations should be enabled for the client on ChromeOS. The
-// possible values are defined in the
-// VariationsService::RestrictionPolicyValues enum.
-const char kDeviceVariationsRestrictionsByPolicy[] =
- "device_variations_restrictions_by_policy";
-
} // namespace prefs
} // namespace variations
diff --git a/chromium/components/variations/pref_names.h b/chromium/components/variations/pref_names.h
index 3f7c49de596..ca7e4e78f4e 100644
--- a/chromium/components/variations/pref_names.h
+++ b/chromium/components/variations/pref_names.h
@@ -9,8 +9,9 @@ namespace variations {
namespace prefs {
// Alphabetical list of preference names specific to the variations component.
-// Keep alphabetized, and document each in the .cc file.
+// Keep alphabetized and document each in the .cc file.
+extern const char kDeviceVariationsRestrictionsByPolicy[];
extern const char kVariationsCompressedSeed[];
extern const char kVariationsCountry[];
extern const char kVariationsCrashStreak[];
@@ -18,6 +19,7 @@ extern const char kVariationsFailedToFetchSeedStreak[];
extern const char kVariationsLastFetchTime[];
extern const char kVariationsPermanentConsistencyCountry[];
extern const char kVariationsPermanentOverriddenCountry[];
+extern const char kVariationsRestrictionsByPolicy[];
extern const char kVariationsRestrictParameter[];
extern const char kVariationsSafeCompressedSeed[];
extern const char kVariationsSafeSeedDate[];
@@ -28,8 +30,6 @@ extern const char kVariationsSafeSeedSessionConsistencyCountry[];
extern const char kVariationsSafeSeedSignature[];
extern const char kVariationsSeedDate[];
extern const char kVariationsSeedSignature[];
-extern const char kVariationsRestrictionsByPolicy[];
-extern const char kDeviceVariationsRestrictionsByPolicy[];
} // namespace prefs
} // namespace variations
diff --git a/chromium/components/variations/service/generate_ui_string_overrider.gni b/chromium/components/variations/service/generate_ui_string_overrider.gni
index a8ed3f368fb..14497f9ae44 100644
--- a/chromium/components/variations/service/generate_ui_string_overrider.gni
+++ b/chromium/components/variations/service/generate_ui_string_overrider.gni
@@ -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("//build/config/python.gni")
-
# Runs the resources map generation script other the given header files to
# produce an output file and a source_set to build it.
#
@@ -32,8 +30,7 @@ template("generate_ui_string_overrider") {
source_set_target_name = target_name
gen_action_target_name = target_name + "_gen_sources"
- # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
- python2_action(gen_action_target_name) {
+ action(gen_action_target_name) {
header_filename = "$target_gen_dir/" + invoker.header_filename
source_filename = "$target_gen_dir/" + invoker.source_filename
diff --git a/chromium/components/variations/service/generate_ui_string_overrider.py b/chromium/components/variations/service/generate_ui_string_overrider.py
index 33f71eb1348..bcf33dca075 100755
--- a/chromium/components/variations/service/generate_ui_string_overrider.py
+++ b/chromium/components/variations/service/generate_ui_string_overrider.py
@@ -43,7 +43,7 @@ def HashName(name):
An int that is at most 32 bits.
"""
md5hash = hashlib.md5()
- md5hash.update(name)
+ md5hash.update(name.encode('utf-8'))
return int(md5hash.hexdigest()[:8], 16)
@@ -101,7 +101,7 @@ def _CheckForHashCollisions(sorted_resource_list):
A set of all |Resource| objects with collisions.
"""
collisions = set()
- for i in xrange(len(sorted_resource_list) - 1):
+ for i in range(len(sorted_resource_list) - 1):
resource = sorted_resource_list[i]
next_resource = sorted_resource_list[i+1]
if resource.hash == next_resource.hash:
diff --git a/chromium/components/variations/service/safe_seed_manager.cc b/chromium/components/variations/service/safe_seed_manager.cc
index e82dd986713..b44a0d5c722 100644
--- a/chromium/components/variations/service/safe_seed_manager.cc
+++ b/chromium/components/variations/service/safe_seed_manager.cc
@@ -9,6 +9,7 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/ranges.h"
+#include "components/prefs/pref_registry.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/variations/client_filterable_state.h"
@@ -64,24 +65,10 @@ constexpr int kCrashStreakThreshold = 3;
// to find a better balance here.
constexpr int kFetchFailureStreakThreshold = 25;
-SafeSeedManager::SafeSeedManager(bool did_previous_session_exit_cleanly,
- PrefService* local_state)
+SafeSeedManager::SafeSeedManager(PrefService* local_state)
: local_state_(local_state) {
- // Increment the crash streak if the previous session crashed.
- // Note that the streak is not cleared if the previous run didn’t crash.
- // Instead, it’s incremented on each crash until Chrome is able to
- // successfully fetch a new seed. This way, a seed update that mostly
- // destabilizes Chrome will still result in a fallback to safe mode.
- int num_crashes = local_state->GetInteger(prefs::kVariationsCrashStreak);
- if (!did_previous_session_exit_cleanly) {
- ++num_crashes;
- local_state->SetInteger(prefs::kVariationsCrashStreak, num_crashes);
- }
-
int num_failed_fetches =
- local_state->GetInteger(prefs::kVariationsFailedToFetchSeedStreak);
- base::UmaHistogramSparse("Variations.SafeMode.Streak.Crashes",
- base::ClampToRange(num_crashes, 0, 100));
+ local_state_->GetInteger(prefs::kVariationsFailedToFetchSeedStreak);
base::UmaHistogramSparse("Variations.SafeMode.Streak.FetchFailures",
base::ClampToRange(num_failed_fetches, 0, 100));
}
@@ -90,8 +77,14 @@ SafeSeedManager::~SafeSeedManager() = default;
// static
void SafeSeedManager::RegisterPrefs(PrefRegistrySimple* registry) {
- // Prefs tracking failures along the way to fetching a seed.
- registry->RegisterIntegerPref(prefs::kVariationsCrashStreak, 0);
+ // Verify that the crash streak pref has already been registered.
+ DCHECK(
+ registry->defaults()->GetValue(prefs::kVariationsCrashStreak, nullptr));
+
+ // Registers one of two prefs used for tracking variations-seed-related
+ // failures. The other pref, kVariationsCrashStreak, is registered in
+ // CleanExitBeacon::RegisterPrefs(). See components/metrics/
+ // clean_exit_beacon.cc for more details.
registry->RegisterIntegerPref(prefs::kVariationsFailedToFetchSeedStreak, 0);
}
diff --git a/chromium/components/variations/service/safe_seed_manager.h b/chromium/components/variations/service/safe_seed_manager.h
index 5855f7a07f2..610e4033d6b 100644
--- a/chromium/components/variations/service/safe_seed_manager.h
+++ b/chromium/components/variations/service/safe_seed_manager.h
@@ -22,13 +22,12 @@ class VariationsSeedStore;
// The primary class that encapsulates state for managing the safe seed.
class SafeSeedManager {
public:
- // Creates a SafeSeedManager instance, and updates safe mode prefs for
- // bookkeeping.
- SafeSeedManager(bool did_previous_session_exit_cleanly,
- PrefService* local_state);
+ // Creates a SafeSeedManager instance and updates a safe mode pref,
+ // kVariationsFailedToFetchSeedStreak, for bookkeeping.
+ explicit SafeSeedManager(PrefService* local_state);
virtual ~SafeSeedManager();
- // Register safe mode prefs in Local State.
+ // Registers safe mode prefs in Local State.
static void RegisterPrefs(PrefRegistrySimple* registry);
// Returns true iff the client should use the safe seed for variations state.
@@ -83,8 +82,8 @@ class SafeSeedManager {
// The active seed state must never be set more than once.
bool has_set_active_seed_state_ = false;
- // The pref service used to store persist the variations seed. Weak reference;
- // must outlive |this| instance.
+ // The pref service used to persist the variations seed. Weak reference; must
+ // outlive |this| instance.
PrefService* local_state_;
DISALLOW_COPY_AND_ASSIGN(SafeSeedManager);
diff --git a/chromium/components/variations/service/safe_seed_manager_unittest.cc b/chromium/components/variations/service/safe_seed_manager_unittest.cc
index 40d3b117261..31abfaab792 100644
--- a/chromium/components/variations/service/safe_seed_manager_unittest.cc
+++ b/chromium/components/variations/service/safe_seed_manager_unittest.cc
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
+#include "components/metrics/clean_exit_beacon.h"
#include "components/prefs/testing_pref_service.h"
#include "components/variations/client_filterable_state.h"
#include "components/variations/pref_names.h"
@@ -109,7 +110,10 @@ void ExpectDefaultActiveState(const FakeSeedStore& seed_store) {
class SafeSeedManagerTest : public testing::Test {
public:
- SafeSeedManagerTest() { SafeSeedManager::RegisterPrefs(prefs_.registry()); }
+ SafeSeedManagerTest() {
+ metrics::CleanExitBeacon::RegisterPrefs(prefs_.registry());
+ SafeSeedManager::RegisterPrefs(prefs_.registry());
+ }
~SafeSeedManagerTest() override = default;
protected:
@@ -117,7 +121,7 @@ class SafeSeedManagerTest : public testing::Test {
};
TEST_F(SafeSeedManagerTest, RecordSuccessfulFetch_FirstCallSavesSafeSeed) {
- SafeSeedManager safe_seed_manager(true, &prefs_);
+ SafeSeedManager safe_seed_manager(&prefs_);
SetDefaultActiveState(&safe_seed_manager);
FakeSeedStore seed_store(&prefs_);
@@ -127,7 +131,7 @@ TEST_F(SafeSeedManagerTest, RecordSuccessfulFetch_FirstCallSavesSafeSeed) {
}
TEST_F(SafeSeedManagerTest, RecordSuccessfulFetch_RepeatedCallsRetainSafeSeed) {
- SafeSeedManager safe_seed_manager(true, &prefs_);
+ SafeSeedManager safe_seed_manager(&prefs_);
SetDefaultActiveState(&safe_seed_manager);
FakeSeedStore seed_store(&prefs_);
@@ -140,7 +144,7 @@ TEST_F(SafeSeedManagerTest, RecordSuccessfulFetch_RepeatedCallsRetainSafeSeed) {
TEST_F(SafeSeedManagerTest,
RecordSuccessfulFetch_NoActiveState_DoesntSaveSafeSeed) {
- SafeSeedManager safe_seed_manager(true, &prefs_);
+ SafeSeedManager safe_seed_manager(&prefs_);
// Omit setting any active state.
FakeSeedStore seed_store(&prefs_);
@@ -155,59 +159,31 @@ TEST_F(SafeSeedManagerTest,
EXPECT_EQ(base::Time(), seed_store.fetch_time());
}
-TEST_F(SafeSeedManagerTest, StreakMetrics_NoPrefs) {
+TEST_F(SafeSeedManagerTest, FetchFailureMetrics_DefaultPrefs) {
base::HistogramTester histogram_tester;
- SafeSeedManager safe_seed_manager(true, &prefs_);
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 0,
- 1);
+ SafeSeedManager safe_seed_manager(&prefs_);
histogram_tester.ExpectUniqueSample(
"Variations.SafeMode.Streak.FetchFailures", 0, 1);
}
-TEST_F(SafeSeedManagerTest, StreakMetrics_NoCrashes_NoFetchFailures) {
- prefs_.SetInteger(prefs::kVariationsCrashStreak, 0);
+TEST_F(SafeSeedManagerTest, FetchFailureMetrics_NoFailures) {
prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 0);
base::HistogramTester histogram_tester;
- SafeSeedManager safe_seed_manager(true, &prefs_);
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 0,
- 1);
+ SafeSeedManager safe_seed_manager(&prefs_);
histogram_tester.ExpectUniqueSample(
"Variations.SafeMode.Streak.FetchFailures", 0, 1);
}
-TEST_F(SafeSeedManagerTest, StreakMetrics_SomeCrashes_SomeFetchFailures) {
- prefs_.SetInteger(prefs::kVariationsCrashStreak, 1);
+TEST_F(SafeSeedManagerTest, FetchFailureMetrics_SomeFailures) {
prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 2);
base::HistogramTester histogram_tester;
- SafeSeedManager safe_seed_manager(true, &prefs_);
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 1,
- 1);
+ SafeSeedManager safe_seed_manager(&prefs_);
histogram_tester.ExpectUniqueSample(
"Variations.SafeMode.Streak.FetchFailures", 2, 1);
}
-TEST_F(SafeSeedManagerTest, StreakMetrics_CrashIncrementsCrashStreak) {
- prefs_.SetInteger(prefs::kVariationsCrashStreak, 1);
-
- base::HistogramTester histogram_tester;
- SafeSeedManager safe_seed_manager(false, &prefs_);
-
- EXPECT_EQ(2, prefs_.GetInteger(prefs::kVariationsCrashStreak));
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 2,
- 1);
-}
-
-TEST_F(SafeSeedManagerTest, StreakMetrics_CrashIncrementsCrashStreak_NoPrefs) {
- base::HistogramTester histogram_tester;
- SafeSeedManager safe_seed_manager(false, &prefs_);
-
- EXPECT_EQ(1, prefs_.GetInteger(prefs::kVariationsCrashStreak));
- histogram_tester.ExpectUniqueSample("Variations.SafeMode.Streak.Crashes", 1,
- 1);
-}
-
TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_OverriddenByCommandlineFlag) {
// So many failures.
prefs_.SetInteger(prefs::kVariationsCrashStreak, 100);
@@ -215,7 +191,7 @@ TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_OverriddenByCommandlineFlag) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
::switches::kForceFieldTrials, "SomeFieldTrial");
- SafeSeedManager safe_seed_manager(true, &prefs_);
+ SafeSeedManager safe_seed_manager(&prefs_);
EXPECT_FALSE(safe_seed_manager.ShouldRunInSafeMode());
}
@@ -223,14 +199,14 @@ TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_NoCrashes_NoFetchFailures) {
prefs_.SetInteger(prefs::kVariationsCrashStreak, 0);
prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 0);
- SafeSeedManager safe_seed_manager(true, &prefs_);
+ SafeSeedManager safe_seed_manager(&prefs_);
EXPECT_FALSE(safe_seed_manager.ShouldRunInSafeMode());
}
TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_NoPrefs) {
// Don't explicitly set either of the prefs. The implicit/default values
// should be zero.
- SafeSeedManager safe_seed_manager(true, &prefs_);
+ SafeSeedManager safe_seed_manager(&prefs_);
EXPECT_FALSE(safe_seed_manager.ShouldRunInSafeMode());
}
@@ -238,7 +214,7 @@ TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_FewCrashes_FewFetchFailures) {
prefs_.SetInteger(prefs::kVariationsCrashStreak, 2);
prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 2);
- SafeSeedManager safe_seed_manager(true, &prefs_);
+ SafeSeedManager safe_seed_manager(&prefs_);
EXPECT_FALSE(safe_seed_manager.ShouldRunInSafeMode());
}
@@ -246,7 +222,7 @@ TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_ManyCrashes_NoFetchFailures) {
prefs_.SetInteger(prefs::kVariationsCrashStreak, 3);
prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 0);
- SafeSeedManager safe_seed_manager(true, &prefs_);
+ SafeSeedManager safe_seed_manager(&prefs_);
EXPECT_TRUE(safe_seed_manager.ShouldRunInSafeMode());
}
@@ -254,7 +230,7 @@ TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_NoCrashes_ManyFetchFailures) {
prefs_.SetInteger(prefs::kVariationsCrashStreak, 0);
prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 50);
- SafeSeedManager safe_seed_manager(true, &prefs_);
+ SafeSeedManager safe_seed_manager(&prefs_);
EXPECT_TRUE(safe_seed_manager.ShouldRunInSafeMode());
}
@@ -262,7 +238,7 @@ TEST_F(SafeSeedManagerTest, ShouldRunInSafeMode_ManyCrashes_ManyFetchFailures) {
prefs_.SetInteger(prefs::kVariationsCrashStreak, 3);
prefs_.SetInteger(prefs::kVariationsFailedToFetchSeedStreak, 50);
- SafeSeedManager safe_seed_manager(true, &prefs_);
+ SafeSeedManager safe_seed_manager(&prefs_);
EXPECT_TRUE(safe_seed_manager.ShouldRunInSafeMode());
}
diff --git a/chromium/components/variations/service/ui_string_overrider.h b/chromium/components/variations/service/ui_string_overrider.h
index 45a4ad1cd6c..02383f1ce99 100644
--- a/chromium/components/variations/service/ui_string_overrider.h
+++ b/chromium/components/variations/service/ui_string_overrider.h
@@ -8,8 +8,6 @@
#include <stddef.h>
#include <stdint.h>
-#include <string>
-
#include "base/macros.h"
namespace variations {
diff --git a/chromium/components/variations/service/variations_field_trial_creator.cc b/chromium/components/variations/service/variations_field_trial_creator.cc
index 7d93ed956f6..30611ab65dd 100644
--- a/chromium/components/variations/service/variations_field_trial_creator.cc
+++ b/chromium/components/variations/service/variations_field_trial_creator.cc
@@ -28,6 +28,7 @@
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/language/core/browser/locale_util.h"
+#include "components/metrics/metrics_state_manager.h"
#include "components/prefs/pref_service.h"
#include "components/variations/field_trial_config/field_trial_util.h"
#include "components/variations/platform_field_trials.h"
@@ -40,6 +41,7 @@
#include "components/variations/variations_ids_provider.h"
#include "components/variations/variations_seed_processor.h"
#include "components/variations/variations_switches.h"
+#include "components/version_info/channel.h"
#include "ui/base/device_form_factor.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
@@ -171,64 +173,122 @@ std::string VariationsFieldTrialCreator::GetLatestCountry() const {
: local_state()->GetString(prefs::kVariationsCountry);
}
-bool VariationsFieldTrialCreator::CreateTrialsFromSeed(
- const base::FieldTrial::EntropyProvider* low_entropy_provider,
- base::FeatureList* feature_list,
- SafeSeedManager* safe_seed_manager) {
- TRACE_EVENT0("startup", "VariationsFieldTrialCreator::CreateTrialsFromSeed");
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- CHECK(!create_trials_from_seed_called_);
- create_trials_from_seed_called_ = true;
+bool VariationsFieldTrialCreator::SetupFieldTrials(
+ const char* kEnableGpuBenchmarking,
+ const char* kEnableFeatures,
+ const char* kDisableFeatures,
+ 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,
+ metrics::MetricsStateManager* metrics_state_manager,
+ PlatformFieldTrials* platform_field_trials,
+ SafeSeedManager* safe_seed_manager,
+ absl::optional<int> low_entropy_source_value) {
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kEnableBenchmarking) ||
+ command_line->HasSwitch(kEnableGpuBenchmarking)) {
+ base::FieldTrial::EnableBenchmarking();
+ }
- base::TimeTicks start_time = base::TimeTicks::Now();
+ if (command_line->HasSwitch(switches::kForceFieldTrialParams)) {
+ bool result = AssociateParamsFromString(
+ command_line->GetSwitchValueASCII(switches::kForceFieldTrialParams));
+ if (!result) {
+ // Some field trial params implement things like csv or json with a
+ // particular param. If some control characters are not %-encoded, it can
+ // lead to confusing error messages, so add a hint here.
+ ExitWithMessage(base::StringPrintf(
+ "Invalid --%s list specified. Make sure you %%-"
+ "encode the following characters in param values: %%:/.,",
+ switches::kForceFieldTrialParams));
+ }
+ }
- const base::Version& current_version = version_info::GetVersion();
- if (!current_version.IsValid())
- return false;
+ // Ensure any field trials specified on the command line are initialized.
+ if (command_line->HasSwitch(::switches::kForceFieldTrials)) {
+ // Create field trials without activating them, so that this behaves in a
+ // consistent manner with field trials created from the server.
+ bool result = base::FieldTrialList::CreateTrialsFromString(
+ command_line->GetSwitchValueASCII(::switches::kForceFieldTrials));
+ if (!result) {
+ ExitWithMessage(base::StringPrintf("Invalid --%s list specified.",
+ ::switches::kForceFieldTrials));
+ }
+ }
- std::unique_ptr<ClientFilterableState> client_filterable_state =
- GetClientFilterableStateForVersion(current_version);
- base::UmaHistogramSparse("Variations.UserChannel",
- client_filterable_state->channel);
- base::UmaHistogramEnumeration("Variations.PolicyRestriction",
- client_filterable_state->policy_restriction);
+ VariationsIdsProvider* http_header_provider =
+ VariationsIdsProvider::GetInstance();
+ http_header_provider->SetLowEntropySourceValue(low_entropy_source_value);
+ // Force the variation ids selected in chrome://flags and/or specified using
+ // the command-line flag.
+ auto result = http_header_provider->ForceVariationIds(
+ variation_ids,
+ command_line->GetSwitchValueASCII(switches::kForceVariationIds));
- VariationsSeed seed;
- bool run_in_safe_mode = safe_seed_manager->ShouldRunInSafeMode() &&
- LoadSafeSeed(&seed, client_filterable_state.get());
+ switch (result) {
+ case VariationsIdsProvider::ForceIdsResult::INVALID_SWITCH_ENTRY:
+ ExitWithMessage(base::StringPrintf("Invalid --%s list specified.",
+ switches::kForceVariationIds));
+ break;
+ case VariationsIdsProvider::ForceIdsResult::INVALID_VECTOR_ENTRY:
+ // It should not be possible to have invalid variation ids from the
+ // vector param (which corresponds to chrome://flags).
+ NOTREACHED();
+ break;
+ case VariationsIdsProvider::ForceIdsResult::SUCCESS:
+ break;
+ }
- std::string seed_data;
- std::string base64_seed_signature;
- if (!run_in_safe_mode && !LoadSeed(&seed, &seed_data, &base64_seed_signature))
- return false;
+ bool success = http_header_provider->ForceDisableVariationIds(
+ command_line->GetSwitchValueASCII(switches::kForceDisableVariationIds));
+ if (!success) {
+ ExitWithMessage(base::StringPrintf("Invalid --%s list specified.",
+ switches::kForceDisableVariationIds));
+ }
- UMA_HISTOGRAM_BOOLEAN("Variations.SafeMode.FellBackToSafeMode2",
- run_in_safe_mode);
+ feature_list->InitializeFromCommandLine(
+ command_line->GetSwitchValueASCII(kEnableFeatures),
+ command_line->GetSwitchValueASCII(kDisableFeatures));
- // Note that passing base::Unretained(this) below is safe because the callback
- // is executed synchronously. It is not possible to pass UIStringOverrider
- // directly to VariationsSeedProcessor (which is in components/variations and
- // not components/variations/service) as the variations component should not
- // depend on //ui/base.
- VariationsSeedProcessor().CreateTrialsFromSeed(
- seed, *client_filterable_state,
- base::BindRepeating(&VariationsFieldTrialCreator::OverrideUIString,
- base::Unretained(this)),
- low_entropy_provider, feature_list);
+ // 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);
- // Store into the |safe_seed_manager| the combined server and client data used
- // to create the field trials. But, as an optimization, skip this step when
- // running in safe mode – once running in safe mode, there can never be a need
- // to save the active state to the safe seed prefs.
- if (!run_in_safe_mode) {
- safe_seed_manager->SetActiveSeedState(seed_data, base64_seed_signature,
- std::move(client_filterable_state),
- seed_store_->GetLastFetchTime());
+ bool used_testing_config = false;
+#if BUILDFLAG(FIELDTRIAL_TESTING_ENABLED)
+ if (!command_line->HasSwitch(switches::kDisableFieldTrialTestingConfig) &&
+ !command_line->HasSwitch(::switches::kForceFieldTrials) &&
+ !command_line->HasSwitch(switches::kVariationsServerURL)) {
+ // Note that passing base::Unretained(this) below is safe because the
+ // callback is executed synchronously.
+ AssociateDefaultFieldTrialConfig(
+ base::BindRepeating(&VariationsFieldTrialCreator::OverrideUIString,
+ base::Unretained(this)),
+ GetPlatform(), client_->GetCurrentFormFactor(), feature_list.get());
+ used_testing_config = true;
+ }
+#endif // BUILDFLAG(FIELDTRIAL_TESTING_ENABLED)
+ bool used_seed = false;
+ if (!used_testing_config) {
+ used_seed = CreateTrialsFromSeed(low_entropy_provider.get(),
+ feature_list.get(), safe_seed_manager);
}
- UMA_HISTOGRAM_TIMES("Variations.SeedProcessingTime",
- base::TimeTicks::Now() - start_time);
- return true;
+ platform_field_trials->SetupFeatureControllingFieldTrials(
+ used_seed, low_entropy_provider.get(), feature_list.get());
+
+ base::FeatureList::SetInstance(std::move(feature_list));
+
+ // This must be called after |local_state_| is initialized.
+ platform_field_trials->SetupFieldTrials();
+
+ return used_seed;
}
std::unique_ptr<ClientFilterableState>
@@ -386,6 +446,10 @@ void VariationsFieldTrialCreator::OverrideCachedUIStrings() {
overridden_strings_map_.clear();
}
+bool VariationsFieldTrialCreator::IsOverrideResourceMapEmpty() {
+ return overridden_strings_map_.empty();
+}
+
bool VariationsFieldTrialCreator::LoadSeed(VariationsSeed* seed,
std::string* seed_data,
std::string* base64_signature) {
@@ -431,121 +495,64 @@ bool VariationsFieldTrialCreator::LoadSafeSeed(
return true;
}
-bool VariationsFieldTrialCreator::SetupFieldTrials(
- const char* kEnableGpuBenchmarking,
- const char* kEnableFeatures,
- const char* kDisableFeatures,
- 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,
- base::Optional<int> low_entropy_source_value) {
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kEnableBenchmarking) ||
- command_line->HasSwitch(kEnableGpuBenchmarking)) {
- base::FieldTrial::EnableBenchmarking();
- }
+bool VariationsFieldTrialCreator::CreateTrialsFromSeed(
+ const base::FieldTrial::EntropyProvider* low_entropy_provider,
+ base::FeatureList* feature_list,
+ SafeSeedManager* safe_seed_manager) {
+ TRACE_EVENT0("startup", "VariationsFieldTrialCreator::CreateTrialsFromSeed");
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ CHECK(!create_trials_from_seed_called_);
+ create_trials_from_seed_called_ = true;
- if (command_line->HasSwitch(switches::kForceFieldTrialParams)) {
- bool result = AssociateParamsFromString(
- command_line->GetSwitchValueASCII(switches::kForceFieldTrialParams));
- if (!result) {
- // Some field trial params implement things like csv or json with a
- // particular param. If some control characters are not %-encoded, it can
- // lead to confusing error messages, so add a hint here.
- ExitWithMessage(base::StringPrintf(
- "Invalid --%s list specified. Make sure you %%-"
- "encode the following characters in param values: %%:/.,",
- switches::kForceFieldTrialParams));
- }
- }
+ base::TimeTicks start_time = base::TimeTicks::Now();
- // Ensure any field trials specified on the command line are initialized.
- if (command_line->HasSwitch(::switches::kForceFieldTrials)) {
- // Create field trials without activating them, so that this behaves in a
- // consistent manner with field trials created from the server.
- bool result = base::FieldTrialList::CreateTrialsFromString(
- command_line->GetSwitchValueASCII(::switches::kForceFieldTrials));
- if (!result) {
- ExitWithMessage(base::StringPrintf("Invalid --%s list specified.",
- ::switches::kForceFieldTrials));
- }
- }
+ const base::Version& current_version = version_info::GetVersion();
+ if (!current_version.IsValid())
+ return false;
- VariationsIdsProvider* http_header_provider =
- VariationsIdsProvider::GetInstance();
- http_header_provider->SetLowEntropySourceValue(low_entropy_source_value);
- // Force the variation ids selected in chrome://flags and/or specified using
- // the command-line flag.
- auto result = http_header_provider->ForceVariationIds(
- variation_ids,
- command_line->GetSwitchValueASCII(switches::kForceVariationIds));
+ std::unique_ptr<ClientFilterableState> client_filterable_state =
+ GetClientFilterableStateForVersion(current_version);
+ base::UmaHistogramSparse("Variations.UserChannel",
+ client_filterable_state->channel);
+ base::UmaHistogramEnumeration("Variations.PolicyRestriction",
+ client_filterable_state->policy_restriction);
- switch (result) {
- case VariationsIdsProvider::ForceIdsResult::INVALID_SWITCH_ENTRY:
- ExitWithMessage(base::StringPrintf("Invalid --%s list specified.",
- switches::kForceVariationIds));
- break;
- case VariationsIdsProvider::ForceIdsResult::INVALID_VECTOR_ENTRY:
- // It should not be possible to have invalid variation ids from the
- // vector param (which corresponds to chrome://flags).
- NOTREACHED();
- break;
- case VariationsIdsProvider::ForceIdsResult::SUCCESS:
- break;
- }
+ VariationsSeed seed;
+ bool run_in_safe_mode = safe_seed_manager->ShouldRunInSafeMode() &&
+ LoadSafeSeed(&seed, client_filterable_state.get());
- bool success = http_header_provider->ForceDisableVariationIds(
- command_line->GetSwitchValueASCII(switches::kForceDisableVariationIds));
- if (!success) {
- ExitWithMessage(base::StringPrintf("Invalid --%s list specified.",
- switches::kForceDisableVariationIds));
- }
+ std::string seed_data;
+ std::string base64_seed_signature;
+ if (!run_in_safe_mode && !LoadSeed(&seed, &seed_data, &base64_seed_signature))
+ return false;
- feature_list->InitializeFromCommandLine(
- command_line->GetSwitchValueASCII(kEnableFeatures),
- command_line->GetSwitchValueASCII(kDisableFeatures));
+ UMA_HISTOGRAM_BOOLEAN("Variations.SafeMode.FellBackToSafeMode2",
+ run_in_safe_mode);
- // 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);
+ // Note that passing base::Unretained(this) below is safe because the callback
+ // is executed synchronously. It is not possible to pass UIStringOverrider
+ // directly to VariationsSeedProcessor (which is in components/variations and
+ // not components/variations/service) as the variations component should not
+ // depend on //ui/base.
+ VariationsSeedProcessor().CreateTrialsFromSeed(
+ seed, *client_filterable_state,
+ base::BindRepeating(&VariationsFieldTrialCreator::OverrideUIString,
+ base::Unretained(this)),
+ low_entropy_provider, feature_list);
- bool used_testing_config = false;
-#if BUILDFLAG(FIELDTRIAL_TESTING_ENABLED)
- if (!command_line->HasSwitch(switches::kDisableFieldTrialTestingConfig) &&
- !command_line->HasSwitch(::switches::kForceFieldTrials) &&
- !command_line->HasSwitch(switches::kVariationsServerURL)) {
- // Note that passing base::Unretained(this) below is safe because the
- // callback is executed synchronously.
- AssociateDefaultFieldTrialConfig(
- base::BindRepeating(&VariationsFieldTrialCreator::OverrideUIString,
- base::Unretained(this)),
- GetPlatform(), client_->GetCurrentFormFactor(), feature_list.get());
- used_testing_config = true;
- }
-#endif // BUILDFLAG(FIELDTRIAL_TESTING_ENABLED)
- bool used_seed = false;
- if (!used_testing_config) {
- used_seed = CreateTrialsFromSeed(low_entropy_provider.get(),
- feature_list.get(), safe_seed_manager);
+ // Store into the |safe_seed_manager| the combined server and client data used
+ // to create the field trials. But, as an optimization, skip this step when
+ // running in safe mode – once running in safe mode, there can never be a need
+ // to save the active state to the safe seed prefs.
+ if (!run_in_safe_mode) {
+ safe_seed_manager->SetActiveSeedState(seed_data, base64_seed_signature,
+ std::move(client_filterable_state),
+ seed_store_->GetLastFetchTime());
}
- platform_field_trials->SetupFeatureControllingFieldTrials(
- used_seed, low_entropy_provider.get(), feature_list.get());
-
- base::FeatureList::SetInstance(std::move(feature_list));
-
- // This must be called after |local_state_| is initialized.
- platform_field_trials->SetupFieldTrials();
-
- return used_seed;
+ UMA_HISTOGRAM_TIMES("Variations.SeedProcessingTime",
+ base::TimeTicks::Now() - start_time);
+ return true;
}
void VariationsFieldTrialCreator::OverrideUIString(uint32_t resource_hash,
@@ -565,10 +572,6 @@ void VariationsFieldTrialCreator::OverrideUIString(uint32_t resource_hash,
resource_id, str);
}
-bool VariationsFieldTrialCreator::IsOverrideResourceMapEmpty() {
- return overridden_strings_map_.empty();
-}
-
VariationsSeedStore* VariationsFieldTrialCreator::GetSeedStore() {
return seed_store_.get();
}
diff --git a/chromium/components/variations/service/variations_field_trial_creator.h b/chromium/components/variations/service/variations_field_trial_creator.h
index 21b528b1dcf..093a5d09dd0 100644
--- a/chromium/components/variations/service/variations_field_trial_creator.h
+++ b/chromium/components/variations/service/variations_field_trial_creator.h
@@ -19,6 +19,10 @@
#include "components/variations/service/ui_string_overrider.h"
#include "components/variations/variations_seed_store.h"
+namespace metrics {
+class MetricsStateManager;
+}
+
namespace variations {
enum LoadPermanentConsistencyCountryResult {
@@ -59,25 +63,29 @@ class VariationsFieldTrialCreator {
// Sets up field trials based on stored variations seed data. Returns whether
// setup completed successfully.
+ //
// |kEnableGpuBenchmarking|, |kEnableFeatures|, |kDisableFeatures| are
- // feature controlling flags not directly accesible from variations.
+ // feature-controlling flags not directly accessible from variations.
// |variation_ids| allows for forcing ids selected in chrome://flags and/or
// specified using the command-line flag.
+ // |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.
// |low_entropy_provider| allows for field trial randomization.
// |feature_list| contains the list of all active features for this client.
- // |platform_field_trials| provides the platform specific field trial set up
+ // |metrics_state_manager| facilitates signaling that Chrome has not yet
+ // exited cleanly.
+ // |platform_field_trials| provides the platform-specific field trial set up
// for Chrome.
// |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).
// |low_entropy_source_value| contains the low entropy source value that was
// used for client-side randomization of variations.
- // |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
+ //
+ // 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
+ // take precedence over |extra_overrides|, which takes precedence over the
// field trials.
bool SetupFieldTrials(
const char* kEnableGpuBenchmarking,
@@ -89,9 +97,10 @@ class VariationsFieldTrialCreator {
std::unique_ptr<const base::FieldTrial::EntropyProvider>
low_entropy_provider,
std::unique_ptr<base::FeatureList> feature_list,
+ metrics::MetricsStateManager* metrics_state_manager,
PlatformFieldTrials* platform_field_trials,
SafeSeedManager* safe_seed_manager,
- base::Optional<int> low_entropy_source_value);
+ absl::optional<int> low_entropy_source_value);
// Returns all of the client state used for filtering studies.
// As a side-effect, may update the stored permanent consistency country.
@@ -115,9 +124,6 @@ class VariationsFieldTrialCreator {
// client.
void StoreVariationsOverriddenCountry(const std::string& country);
- // Records the time of the most recent successful fetch.
- void RecordLastFetchTime();
-
// Allow the platform that is used to filter the set of active trials to be
// overridden.
void OverrideVariationsPlatform(Study::Platform platform_override);
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 8f2b829b343..86c6d0cd96b 100644
--- a/chromium/components/variations/service/variations_field_trial_creator_unittest.cc
+++ b/chromium/components/variations/service/variations_field_trial_creator_unittest.cc
@@ -12,10 +12,13 @@
#include "base/callback_helpers.h"
#include "base/feature_list.h"
#include "base/macros.h"
-#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/version.h"
#include "build/build_config.h"
+#include "components/metrics/clean_exit_beacon.h"
+#include "components/metrics/client_info.h"
+#include "components/metrics/metrics_state_manager.h"
+#include "components/metrics/test/test_enabled_state_provider.h"
#include "components/prefs/testing_pref_service.h"
#include "components/variations/platform_field_trials.h"
#include "components/variations/pref_names.h"
@@ -51,6 +54,12 @@ const char kTestSeedSerialNumber[] = "123";
const char kTestSeedData[] = "a serialized seed, 100% realistic";
const char kTestSeedSignature[] = "a totally valid signature, I swear!";
+// No-op functions used to create a MetricsStateManager.
+void NoOpStoreClientInfoBackup(const metrics::ClientInfo&) {}
+std::unique_ptr<metrics::ClientInfo> NoOpLoadClientInfoBackup() {
+ return nullptr;
+}
+
// Populates |seed| with simple test data. The resulting seed will contain one
// study called "test", which contains one experiment called "abc" with
// probability weight 100.
@@ -129,7 +138,7 @@ class TestPlatformFieldTrials : public PlatformFieldTrials {
class MockSafeSeedManager : public SafeSeedManager {
public:
explicit MockSafeSeedManager(PrefService* local_state)
- : SafeSeedManager(true, local_state) {}
+ : SafeSeedManager(local_state) {}
~MockSafeSeedManager() override = default;
MOCK_CONST_METHOD0(ShouldRunInSafeMode, bool());
@@ -238,8 +247,14 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
client,
std::make_unique<VariationsSeedStore>(local_state),
UIStringOverrider()),
+ enabled_state_provider_(/*consent=*/true, /*enabled=*/true),
seed_store_(local_state),
- safe_seed_manager_(safe_seed_manager) {}
+ safe_seed_manager_(safe_seed_manager) {
+ metrics_state_manager_ = metrics::MetricsStateManager::Create(
+ local_state, &enabled_state_provider_, std::wstring(),
+ base::BindRepeating(&NoOpStoreClientInfoBackup),
+ base::BindRepeating(&NoOpLoadClientInfoBackup));
+ }
~TestVariationsFieldTrialCreator() override = default;
@@ -250,8 +265,8 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
return VariationsFieldTrialCreator::SetupFieldTrials(
"", "", "", std::vector<std::string>(),
std::vector<base::FeatureList::FeatureOverrideInfo>(), nullptr,
- std::make_unique<base::FeatureList>(), &platform_field_trials,
- safe_seed_manager_, base::nullopt);
+ std::make_unique<base::FeatureList>(), metrics_state_manager_.get(),
+ &platform_field_trials, safe_seed_manager_, absl::nullopt);
}
TestVariationsSeedStore* seed_store() { return &seed_store_; }
@@ -259,8 +274,10 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
private:
VariationsSeedStore* GetSeedStore() override { return &seed_store_; }
+ metrics::TestEnabledStateProvider enabled_state_provider_;
TestVariationsSeedStore seed_store_;
SafeSeedManager* const safe_seed_manager_;
+ std::unique_ptr<metrics::MetricsStateManager> metrics_state_manager_;
DISALLOW_COPY_AND_ASSIGN(TestVariationsFieldTrialCreator);
};
@@ -270,6 +287,8 @@ class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator {
class FieldTrialCreatorTest : public ::testing::Test {
protected:
FieldTrialCreatorTest() {
+ metrics::CleanExitBeacon::RegisterPrefs(prefs_.registry());
+ metrics::MetricsStateManager::RegisterPrefs(prefs_.registry());
VariationsService::RegisterPrefs(prefs_.registry());
global_feature_list_ = base::FeatureList::ClearInstanceForTesting();
}
@@ -494,6 +513,13 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_LoadsCountryOnFirstRun) {
&prefs_, &variations_service_client, std::move(seed_store),
UIStringOverrider());
+ metrics::TestEnabledStateProvider enabled_state_provider(/*consent=*/true,
+ /*enabled=*/true);
+ auto metrics_state_manager = metrics::MetricsStateManager::Create(
+ &prefs_, &enabled_state_provider, std::wstring(),
+ base::BindRepeating(&NoOpStoreClientInfoBackup),
+ base::BindRepeating(&NoOpLoadClientInfoBackup));
+
// Check that field trials are created from the seed. The test seed contains a
// single study with an experiment targeting 100% of users in India. Since
// |initial_seed| included the country code for India, this study should be
@@ -501,8 +527,8 @@ TEST_F(FieldTrialCreatorTest, SetupFieldTrials_LoadsCountryOnFirstRun) {
EXPECT_TRUE(field_trial_creator.SetupFieldTrials(
"", "", "", std::vector<std::string>(),
std::vector<base::FeatureList::FeatureOverrideInfo>(), nullptr,
- std::make_unique<base::FeatureList>(), &platform_field_trials,
- &safe_seed_manager, base::nullopt));
+ std::make_unique<base::FeatureList>(), metrics_state_manager.get(),
+ &platform_field_trials, &safe_seed_manager, absl::nullopt));
EXPECT_EQ(kTestSeedExperimentName,
base::FieldTrialList::FindFullName(kTestSeedStudyName));
diff --git a/chromium/components/variations/service/variations_service.cc b/chromium/components/variations/service/variations_service.cc
index d4611738efd..e7bf9b17b8e 100644
--- a/chromium/components/variations/service/variations_service.cc
+++ b/chromium/components/variations/service/variations_service.cc
@@ -104,7 +104,7 @@ std::string GetPlatformString() {
return "win";
#elif defined(OS_IOS)
return "ios";
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
return "mac";
#elif BUILDFLAG(IS_CHROMEOS_ASH)
return "chromeos";
@@ -359,8 +359,7 @@ VariationsService::VariationsService(
disable_deltas_for_next_request_(false),
resource_request_allowed_notifier_(std::move(notifier)),
request_count_(0),
- safe_seed_manager_(state_manager->clean_exit_beacon()->exited_cleanly(),
- local_state),
+ safe_seed_manager_(local_state),
field_trial_creator_(local_state,
client_.get(),
std::make_unique<VariationsSeedStore>(
@@ -1006,7 +1005,7 @@ bool VariationsService::SetupFieldTrials(
return field_trial_creator_.SetupFieldTrials(
kEnableGpuBenchmarking, kEnableFeatures, kDisableFeatures, variation_ids,
extra_overrides, CreateLowEntropyProvider(), std::move(feature_list),
- platform_field_trials, &safe_seed_manager_,
+ state_manager_, platform_field_trials, &safe_seed_manager_,
state_manager_->GetLowEntropySource());
}
diff --git a/chromium/components/variations/service/variations_service_unittest.cc b/chromium/components/variations/service/variations_service_unittest.cc
index e37b2485be6..8c73177af49 100644
--- a/chromium/components/variations/service/variations_service_unittest.cc
+++ b/chromium/components/variations/service/variations_service_unittest.cc
@@ -67,7 +67,7 @@ void StubStoreClientInfo(const metrics::ClientInfo& /* client_info */) {}
// A stub for the metrics state manager.
std::unique_ptr<metrics::ClientInfo> StubLoadClientInfo() {
- return std::unique_ptr<metrics::ClientInfo>();
+ return nullptr;
}
// TODO(crbug.com/1167566): Remove when fake VariationsServiceClient created.
@@ -306,8 +306,8 @@ class VariationsServiceTest : public ::testing::Test {
: network_tracker_(network::TestNetworkConnectionTracker::GetInstance()),
enabled_state_provider_(
new metrics::TestEnabledStateProvider(false, false)) {
- VariationsService::RegisterPrefs(prefs_.registry());
metrics::CleanExitBeacon::RegisterPrefs(prefs_.registry());
+ VariationsService::RegisterPrefs(prefs_.registry());
metrics::MetricsStateManager::RegisterPrefs(prefs_.registry());
}
diff --git a/chromium/components/variations/synthetic_trial_registry.h b/chromium/components/variations/synthetic_trial_registry.h
index a549721f365..3cfe4decbd3 100644
--- a/chromium/components/variations/synthetic_trial_registry.h
+++ b/chromium/components/variations/synthetic_trial_registry.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
#include "base/observer_list.h"
#include "components/variations/synthetic_trials.h"
diff --git a/chromium/components/variations/synthetic_trial_registry_unittest.cc b/chromium/components/variations/synthetic_trial_registry_unittest.cc
index 7bb77445781..d2d59a7eca7 100644
--- a/chromium/components/variations/synthetic_trial_registry_unittest.cc
+++ b/chromium/components/variations/synthetic_trial_registry_unittest.cc
@@ -55,7 +55,7 @@ class SyntheticTrialRegistryTest : public ::testing::Test {
}
private:
- base::test::SingleThreadTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(SyntheticTrialRegistryTest);
};
diff --git a/chromium/components/variations/variations_crash_keys.cc b/chromium/components/variations/variations_crash_keys.cc
index 95aa6445eb8..37946499b8b 100644
--- a/chromium/components/variations/variations_crash_keys.cc
+++ b/chromium/components/variations/variations_crash_keys.cc
@@ -11,11 +11,17 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
+#include "build/buildflag.h"
#include "components/crash/core/common/crash_key.h"
#include "components/variations/active_field_trials.h"
#include "components/variations/buildflags.h"
#include "components/variations/synthetic_trials.h"
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "base/task/thread_pool.h"
+#include "components/variations/variations_crash_keys_chromeos.h"
+#endif
+
namespace variations {
namespace {
@@ -31,11 +37,12 @@ constexpr size_t kVariationsKeySize = 4096;
// Crash key reporting the number of experiments. 8 is the size of the crash key
// in bytes, which is used to hold an int as a string.
-crash_reporter::CrashKeyString<8> g_num_variations_crash_key("num-experiments");
+crash_reporter::CrashKeyString<8> g_num_variations_crash_key(
+ kNumExperimentsKey);
// Crash key reporting the variations state.
crash_reporter::CrashKeyString<kVariationsKeySize> g_variations_crash_key(
- "variations");
+ kExperimentListKey);
std::string ActiveGroupToString(const ActiveGroupId& active_group) {
return base::StringPrintf("%x-%x,", active_group.name, active_group.group);
@@ -55,6 +62,10 @@ class VariationsCrashKeys final : public base::FieldTrialList::Observer {
// object isn't a direct observer, so doesn't implement it.
void OnSyntheticTrialsChanged(const std::vector<SyntheticTrialGroup>& groups);
+ // Gets the list of experiments and number of experiments in the format we
+ // want to place it in the crash keys.
+ ExperimentListInfo GetExperimentListInfo();
+
private:
// Adds an entry for the specified field trial to internal state, without
// updating crash keys.
@@ -68,6 +79,12 @@ class VariationsCrashKeys final : public base::FieldTrialList::Observer {
// observer calls that happen on a different thread.
scoped_refptr<base::SequencedTaskRunner> ui_thread_task_runner_;
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ // Task runner corresponding to a background thread, used for tasks that may
+ // block.
+ scoped_refptr<base::SequencedTaskRunner> background_thread_task_runner_;
+#endif // IS_CHROMEOS_ASH
+
// A serialized string containing the variations state.
std::string variations_string_;
@@ -91,14 +108,19 @@ VariationsCrashKeys::VariationsCrashKeys() {
for (const auto& entry : active_groups) {
AppendFieldTrial(entry.trial_name, entry.group_name);
}
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ background_thread_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
+ {base::TaskPriority::BEST_EFFORT, base::MayBlock()});
+#endif // IS_CHROMEOS_ASH
+
UpdateCrashKeys();
ui_thread_task_runner_ = base::SequencedTaskRunnerHandle::Get();
- base::FieldTrialList::SetSynchronousObserver(this);
+ base::FieldTrialList::AddObserver(this);
}
VariationsCrashKeys::~VariationsCrashKeys() {
- base::FieldTrialList::RemoveSynchronousObserver(this);
+ base::FieldTrialList::RemoveObserver(this);
g_num_variations_crash_key.Clear();
g_variations_crash_key.Clear();
}
@@ -137,27 +159,37 @@ void VariationsCrashKeys::AppendFieldTrial(const std::string& trial_name,
++num_variations_;
}
-void VariationsCrashKeys::UpdateCrashKeys() {
+ExperimentListInfo VariationsCrashKeys::GetExperimentListInfo() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ ExperimentListInfo result;
+ result.num_experiments = num_variations_ + num_synthetic_trials_;
+ result.experiment_list.reserve(variations_string_.size() +
+ synthetic_trials_string_.size());
+ result.experiment_list.append(variations_string_);
+ result.experiment_list.append(synthetic_trials_string_);
+ return result;
+}
- g_num_variations_crash_key.Set(
- base::NumberToString(num_variations_ + num_synthetic_trials_));
+void VariationsCrashKeys::UpdateCrashKeys() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::string combined_string;
- combined_string.reserve(variations_string_.size() +
- synthetic_trials_string_.size());
- combined_string.append(variations_string_);
- combined_string.append(synthetic_trials_string_);
+ ExperimentListInfo info = GetExperimentListInfo();
+ g_num_variations_crash_key.Set(base::NumberToString(info.num_experiments));
- if (combined_string.size() > kVariationsKeySize) {
+ if (info.experiment_list.size() > kVariationsKeySize) {
// If size exceeded, truncate to the last full entry.
- int comma_index = combined_string.substr(0, kVariationsKeySize).rfind(',');
- combined_string.resize(comma_index + 1);
+ int comma_index =
+ info.experiment_list.substr(0, kVariationsKeySize).rfind(',');
+ info.experiment_list.resize(comma_index + 1);
// NOTREACHED() will let us know of the problem and adjust the limit.
NOTREACHED();
}
- g_variations_crash_key.Set(combined_string);
+ g_variations_crash_key.Set(info.experiment_list);
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+ ReportVariationsToChromeOs(background_thread_task_runner_, info);
+#endif // IS_CHROMEOS_ASH
}
void VariationsCrashKeys::OnSyntheticTrialsChanged(
@@ -183,6 +215,9 @@ VariationsCrashKeys* g_variations_crash_keys = nullptr;
} // namespace
+const char kNumExperimentsKey[] = "num-experiments";
+const char kExperimentListKey[] = "variations";
+
void InitCrashKeys() {
DCHECK(!g_variations_crash_keys);
g_variations_crash_keys = new VariationsCrashKeys();
@@ -201,4 +236,9 @@ void ClearCrashKeysInstanceForTesting() {
g_variations_crash_keys = nullptr;
}
+ExperimentListInfo GetExperimentListInfo() {
+ DCHECK(g_variations_crash_keys);
+ return g_variations_crash_keys->GetExperimentListInfo();
+}
+
} // namespace variations
diff --git a/chromium/components/variations/variations_crash_keys.h b/chromium/components/variations/variations_crash_keys.h
index 499acd82723..2bee11c6a3c 100644
--- a/chromium/components/variations/variations_crash_keys.h
+++ b/chromium/components/variations/variations_crash_keys.h
@@ -5,12 +5,22 @@
#ifndef COMPONENTS_VARIATIONS_VARIATIONS_CRASH_KEYS_H_
#define COMPONENTS_VARIATIONS_VARIATIONS_CRASH_KEYS_H_
+#include <string>
#include <vector>
namespace variations {
struct SyntheticTrialGroup;
+// The key used in crash reports to indicate the number of active experiments.
+// Should match the number of entries in kExperimentListKey.
+extern const char kNumExperimentsKey[];
+
+// The key used in crash reports to list all the active experiments. Each
+// experiment is listed as two hex numbers: trial ID and group ID, separated by
+// a dash. The experiments are separated by a comma.
+extern const char kExperimentListKey[];
+
// Initializes crash keys that report the current set of active FieldTrial
// groups (aka variations) for crash reports. After initialization, an observer
// will be registered on FieldTrialList that will keep the crash keys up-to-date
@@ -26,6 +36,20 @@ void UpdateCrashKeysWithSyntheticTrials(
// Clears the internal instance, for testing.
void ClearCrashKeysInstanceForTesting();
+// The list of experiments, in the format needed by the crash keys. The
+// |num_experiments| goes into the |kNumExperimentsKey| crash key, and the
+// |experiment_list| goes into the |kExperimentListKey| crash key.
+struct ExperimentListInfo {
+ int num_experiments = 0;
+ std::string experiment_list;
+};
+
+// Gets the variation information that we encode in the crash keys.
+// Specifically, returns the string used for representing the active experiment
+// groups + the synthetic trials in |experiment_list| and the number of elements
+// in that list in |num_experiments|. Must be called on the UI thread.
+ExperimentListInfo GetExperimentListInfo();
+
} // namespace variations
#endif // COMPONENTS_VARIATIONS_VARIATIONS_CRASH_KEYS_H_
diff --git a/chromium/components/variations/variations_crash_keys_chromeos.cc b/chromium/components/variations/variations_crash_keys_chromeos.cc
new file mode 100644
index 00000000000..d1633e61f86
--- /dev/null
+++ b/chromium/components/variations/variations_crash_keys_chromeos.cc
@@ -0,0 +1,49 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/variations/variations_crash_keys_chromeos.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/task/thread_pool.h"
+
+namespace variations {
+
+namespace {
+
+// Path where we put variations in cryptohome.
+constexpr char kCrashVariationsFileName[] = ".variations-list.txt";
+
+void WriteVariationsToFile(ExperimentListInfo info) {
+ std::string combined_string = base::StrCat(
+ {kNumExperimentsKey, "=", base::NumberToString(info.num_experiments),
+ "\n", kExperimentListKey, "=", info.experiment_list, "\n"});
+
+ base::FilePath path = base::PathService::CheckedGet(base::DIR_HOME);
+ if (path == base::FilePath("/")) {
+ // Fallback to /home/chronos if DIR_HOME is not overridden and
+ // no user has signed in.
+ path = base::FilePath("/home/chronos");
+ }
+
+ path = path.Append(kCrashVariationsFileName);
+
+ if (!base::WriteFile(path, combined_string)) {
+ VLOG(1) << "Failed to write " << path.value();
+ }
+}
+
+} // namespace
+
+void ReportVariationsToChromeOs(scoped_refptr<base::SequencedTaskRunner> runner,
+ ExperimentListInfo info) {
+ // On a thread in the background, write variants to a file.
+ runner->PostTask(FROM_HERE, base::BindOnce(&WriteVariationsToFile, info));
+}
+
+} // namespace variations
diff --git a/chromium/components/variations/variations_crash_keys_chromeos.h b/chromium/components/variations/variations_crash_keys_chromeos.h
new file mode 100644
index 00000000000..34537762eeb
--- /dev/null
+++ b/chromium/components/variations/variations_crash_keys_chromeos.h
@@ -0,0 +1,21 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VARIATIONS_VARIATIONS_CRASH_KEYS_CHROMEOS_H_
+#define COMPONENTS_VARIATIONS_VARIATIONS_CRASH_KEYS_CHROMEOS_H_
+
+#include "base/sequenced_task_runner.h"
+#include "components/variations/variations_crash_keys.h"
+
+namespace variations {
+
+// On a separate thread, report the provided crash keys to Chrome OS using a
+// .variant-list.txt in the user's home directory, or /home/chronos if no user
+// is logged in.
+void ReportVariationsToChromeOs(scoped_refptr<base::SequencedTaskRunner> runner,
+ ExperimentListInfo info);
+
+} // namespace variations
+
+#endif // COMPONENTS_VARIATIONS_VARIATIONS_CRASH_KEYS_CHROMEOS_H_
diff --git a/chromium/components/variations/variations_crash_keys_chromeos_unittest.cc b/chromium/components/variations/variations_crash_keys_chromeos_unittest.cc
new file mode 100644
index 00000000000..66eb0e16711
--- /dev/null
+++ b/chromium/components/variations/variations_crash_keys_chromeos_unittest.cc
@@ -0,0 +1,87 @@
+// Copyright 2021 The Chromium Authors. 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/variations/variations_crash_keys_chromeos.h"
+
+#include "base/base_paths.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/metrics/field_trial.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_path_override.h"
+#include "base/test/task_environment.h"
+#include "components/crash/core/common/crash_key.h"
+#include "components/variations/synthetic_trials_active_group_id_provider.h"
+#include "components/variations/variations_crash_keys.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace variations {
+namespace {
+
+class VariationsCrashKeysChromeOsTest : public ::testing::Test {
+ public:
+ VariationsCrashKeysChromeOsTest() {
+ crash_reporter::ResetCrashKeysForTesting();
+ crash_reporter::InitializeCrashKeysForTesting();
+ }
+
+ ~VariationsCrashKeysChromeOsTest() override {
+ SyntheticTrialsActiveGroupIdProvider::GetInstance()->ResetForTesting();
+ ClearCrashKeysInstanceForTesting();
+ crash_reporter::ResetCrashKeysForTesting();
+ }
+
+ protected:
+ base::test::TaskEnvironment task_environment_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VariationsCrashKeysChromeOsTest);
+};
+
+TEST_F(VariationsCrashKeysChromeOsTest, WritesVariationsList) {
+ // Override the homedir so that the class writes to a known location we can
+ // check.
+ base::ScopedTempDir dir;
+ ASSERT_TRUE(dir.CreateUniqueTempDir());
+ const base::FilePath& home_path = dir.GetPath();
+ base::ScopedPathOverride home_override(base::DIR_HOME, home_path);
+ base::FilePath variations_list_path =
+ home_path.Append(".variations-list.txt");
+
+ // Start with 2 trials, one active and one not
+ base::FieldTrialList::CreateFieldTrial("Trial1", "Group1")->group();
+ base::FieldTrialList::CreateFieldTrial("Trial2", "Group2");
+
+ InitCrashKeys();
+
+ base::RunLoop().RunUntilIdle();
+ task_environment_.RunUntilIdle();
+
+ ExperimentListInfo info = GetExperimentListInfo();
+ EXPECT_EQ(1, info.num_experiments);
+ EXPECT_EQ("8e7abfb0-c16397b7,", info.experiment_list);
+
+ std::string contents;
+ ASSERT_TRUE(base::ReadFileToString(variations_list_path, &contents));
+ EXPECT_EQ(contents,
+ "num-experiments=1\n"
+ "variations=8e7abfb0-c16397b7,\n");
+
+ // Now, activate Trial2.
+ EXPECT_EQ("Group2", base::FieldTrialList::FindFullName("Trial2"));
+ base::RunLoop().RunUntilIdle();
+ task_environment_.RunUntilIdle();
+
+ info = GetExperimentListInfo();
+ EXPECT_EQ(2, info.num_experiments);
+ EXPECT_EQ("8e7abfb0-c16397b7,277f2a3d-d77354d0,", info.experiment_list);
+
+ ASSERT_TRUE(base::ReadFileToString(variations_list_path, &contents));
+ EXPECT_EQ(contents,
+ "num-experiments=2\n"
+ "variations=8e7abfb0-c16397b7,277f2a3d-d77354d0,\n");
+}
+
+} // namespace
+} // namespace variations
diff --git a/chromium/components/variations/variations_crash_keys_unittest.cc b/chromium/components/variations/variations_crash_keys_unittest.cc
index 11c71c9c829..259aaf6d2a2 100644
--- a/chromium/components/variations/variations_crash_keys_unittest.cc
+++ b/chromium/components/variations/variations_crash_keys_unittest.cc
@@ -42,7 +42,7 @@ class VariationsCrashKeysTest : public ::testing::Test {
}
private:
- base::test::SingleThreadTaskEnvironment task_environment_;
+ base::test::TaskEnvironment task_environment_;
DISALLOW_COPY_AND_ASSIGN(VariationsCrashKeysTest);
};
@@ -63,12 +63,19 @@ TEST_F(VariationsCrashKeysTest, BasicFunctionality) {
EXPECT_EQ("1", GetNumExperimentsCrashKey());
EXPECT_EQ("8e7abfb0-c16397b7,", GetVariationsCrashKey());
+ ExperimentListInfo info = GetExperimentListInfo();
+ EXPECT_EQ(1, info.num_experiments);
+ EXPECT_EQ("8e7abfb0-c16397b7,", info.experiment_list);
+
// Now, active Trial2.
EXPECT_EQ("Group2", base::FieldTrialList::FindFullName("Trial2"));
base::RunLoop().RunUntilIdle();
EXPECT_EQ("2", GetNumExperimentsCrashKey());
EXPECT_EQ("8e7abfb0-c16397b7,277f2a3d-d77354d0,", GetVariationsCrashKey());
+ info = GetExperimentListInfo();
+ EXPECT_EQ(2, info.num_experiments);
+ EXPECT_EQ("8e7abfb0-c16397b7,277f2a3d-d77354d0,", info.experiment_list);
// Add two synthetic trials and confirm that they show up in the list.
SyntheticTrialGroup synth_trial(HashName("Trial3"), HashName("Group3"));
@@ -77,6 +84,10 @@ TEST_F(VariationsCrashKeysTest, BasicFunctionality) {
EXPECT_EQ("3", GetNumExperimentsCrashKey());
EXPECT_EQ("8e7abfb0-c16397b7,277f2a3d-d77354d0,9f339c9d-746c2ad4,",
GetVariationsCrashKey());
+ info = GetExperimentListInfo();
+ EXPECT_EQ(3, info.num_experiments);
+ EXPECT_EQ("8e7abfb0-c16397b7,277f2a3d-d77354d0,9f339c9d-746c2ad4,",
+ info.experiment_list);
// Add another regular trial.
base::FieldTrialList::CreateFieldTrial("Trial4", "Group4")->group();
@@ -86,6 +97,12 @@ TEST_F(VariationsCrashKeysTest, BasicFunctionality) {
"8e7abfb0-c16397b7,277f2a3d-d77354d0,21710f4c-99b90b01,"
"9f339c9d-746c2ad4,",
GetVariationsCrashKey());
+ info = GetExperimentListInfo();
+ EXPECT_EQ(4, info.num_experiments);
+ EXPECT_EQ(
+ "8e7abfb0-c16397b7,277f2a3d-d77354d0,21710f4c-99b90b01,"
+ "9f339c9d-746c2ad4,",
+ info.experiment_list);
// Replace synthetic trial group and add one more.
SyntheticTrialGroup synth_trial2(HashName("Trial3"), HashName("Group3_A"));
@@ -98,6 +115,12 @@ TEST_F(VariationsCrashKeysTest, BasicFunctionality) {
"8e7abfb0-c16397b7,277f2a3d-d77354d0,21710f4c-99b90b01,"
"9f339c9d-3250dddc,21710f4c-99b90b01,",
GetVariationsCrashKey());
+ info = GetExperimentListInfo();
+ EXPECT_EQ(5, info.num_experiments);
+ EXPECT_EQ(
+ "8e7abfb0-c16397b7,277f2a3d-d77354d0,21710f4c-99b90b01,"
+ "9f339c9d-3250dddc,21710f4c-99b90b01,",
+ info.experiment_list);
}
} // namespace variations
diff --git a/chromium/components/variations/variations_features.h b/chromium/components/variations/variations_features.h
index 8d15b831f78..51de6df6b86 100644
--- a/chromium/components/variations/variations_features.h
+++ b/chromium/components/variations/variations_features.h
@@ -21,4 +21,4 @@ extern const base::Feature kRestrictGoogleWebVisibility;
} // namespace internal
} // namespace variations
-#endif // COMPONENTS_VARIATIONS_VARIATIONS_ASSOCIATED_DATA_H_ \ No newline at end of file
+#endif // COMPONENTS_VARIATIONS_VARIATIONS_FEATURES_H_
diff --git a/chromium/components/variations/variations_ids_provider.cc b/chromium/components/variations/variations_ids_provider.cc
index 7237221105b..2b64ee3cf5d 100644
--- a/chromium/components/variations/variations_ids_provider.cc
+++ b/chromium/components/variations/variations_ids_provider.cc
@@ -7,7 +7,6 @@
#include <algorithm>
#include "base/base64.h"
-#include "base/memory/singleton.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -44,7 +43,8 @@ bool VariationsHeaderKey::operator<(const VariationsHeaderKey& other) const {
// static
VariationsIdsProvider* VariationsIdsProvider::GetInstance() {
- return base::Singleton<VariationsIdsProvider>::get();
+ static base::NoDestructor<VariationsIdsProvider> instance;
+ return instance.get();
}
variations::mojom::VariationsHeadersPtr
@@ -116,7 +116,7 @@ VariationsIdsProvider::GetVariationsVectorForWebPropertiesKeys() {
}
void VariationsIdsProvider::SetLowEntropySourceValue(
- base::Optional<int> low_entropy_source_value) {
+ absl::optional<int> low_entropy_source_value) {
// The low entropy source value is an integer that is between 0 and 7999,
// inclusive. See components/metrics/metrics_state_manager.cc for the logic to
// generate it.
@@ -359,10 +359,10 @@ std::string VariationsIdsProvider::GenerateBase64EncodedProto(
// This is the bottleneck for the creation of the header, so validate the size
// here. Force a hard maximum on the ID count in case the Variations server
// returns too many IDs and DOSs receiving servers with large requests.
- DCHECK_LE(total_id_count, 35U);
+ DCHECK_LE(total_id_count, 50U);
UMA_HISTOGRAM_COUNTS_100("Variations.Headers.ExperimentCount",
total_id_count);
- if (total_id_count > 50)
+ if (total_id_count > 75)
return std::string();
std::string serialized;
diff --git a/chromium/components/variations/variations_ids_provider.h b/chromium/components/variations/variations_ids_provider.h
index 2c63f04a937..00ed5987dc4 100644
--- a/chromium/components/variations/variations_ids_provider.h
+++ b/chromium/components/variations/variations_ids_provider.h
@@ -14,6 +14,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
+#include "base/no_destructor.h"
#include "base/observer_list.h"
#include "base/synchronization/lock.h"
#include "components/variations/proto/study.pb.h"
@@ -21,11 +22,6 @@
#include "components/variations/variations.mojom.h"
#include "components/variations/variations_associated_data.h"
-namespace base {
-template <typename T>
-struct DefaultSingletonTraits;
-}
-
namespace variations {
class VariationsClient;
@@ -98,7 +94,7 @@ class VariationsIdsProvider : public base::FieldTrialList::Observer,
// Sets low entropy source value that was used for client-side randomization
// of variations.
- void SetLowEntropySourceValue(base::Optional<int> low_entropy_source_value);
+ void SetLowEntropySourceValue(absl::optional<int> low_entropy_source_value);
// Result of ForceVariationIds() call.
enum class ForceIdsResult {
@@ -131,7 +127,7 @@ class VariationsIdsProvider : public base::FieldTrialList::Observer,
void ResetForTesting();
private:
- friend struct base::DefaultSingletonTraits<VariationsIdsProvider>;
+ friend class base::NoDestructor<VariationsIdsProvider>;
typedef std::pair<VariationID, IDCollectionKey> VariationIDEntry;
@@ -228,7 +224,7 @@ class VariationsIdsProvider : public base::FieldTrialList::Observer,
// Low entropy source value from client that was used for client-side
// randomization of variations.
- base::Optional<int> low_entropy_source_value_;
+ absl::optional<int> low_entropy_source_value_;
// Whether or not we've initialized the caches.
bool variation_ids_cache_initialized_;
diff --git a/chromium/components/variations/variations_ids_provider_unittest.cc b/chromium/components/variations/variations_ids_provider_unittest.cc
index 49db65d29a2..9da42b1a464 100644
--- a/chromium/components/variations/variations_ids_provider_unittest.cc
+++ b/chromium/components/variations/variations_ids_provider_unittest.cc
@@ -163,7 +163,7 @@ TEST_P(VariationsIdsProviderTestWithRestrictedVisibility,
LowEntropySourceValue_Valid) {
VariationsIdsProvider provider;
- base::Optional<int> valid_low_entropy_source_value = 5;
+ absl::optional<int> valid_low_entropy_source_value = 5;
provider.SetLowEntropySourceValue(valid_low_entropy_source_value);
provider.InitVariationIDsCacheIfNeeded();
variations::mojom::VariationsHeadersPtr headers =
@@ -200,7 +200,7 @@ TEST_P(VariationsIdsProviderTestWithRestrictedVisibility,
LowEntropySourceValue_Null) {
VariationsIdsProvider provider;
- base::Optional<int> null_low_entropy_source_value = base::nullopt;
+ absl::optional<int> null_low_entropy_source_value = absl::nullopt;
provider.SetLowEntropySourceValue(null_low_entropy_source_value);
// Valid experiment ids.
diff --git a/chromium/components/variations/variations_layers.cc b/chromium/components/variations/variations_layers.cc
index aa45b748692..b4f07e13700 100644
--- a/chromium/components/variations/variations_layers.cc
+++ b/chromium/components/variations/variations_layers.cc
@@ -23,7 +23,7 @@ double GetEntropyForLayer(
// Iterates through the members of the given layer proto definition, and
// returns the ID of the member which contains that slot (if any).
-base::Optional<uint32_t> FindActiveMemberBySlot(uint32_t chosen_slot,
+absl::optional<uint32_t> FindActiveMemberBySlot(uint32_t chosen_slot,
const Layer& layer_proto) {
for (const Layer::LayerMember& member : layer_proto.members()) {
if (!member.id())
@@ -35,13 +35,13 @@ base::Optional<uint32_t> FindActiveMemberBySlot(uint32_t chosen_slot,
}
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace
VariationsLayers::LayerInfo::LayerInfo(
- base::Optional<uint32_t> active_member_id,
+ absl::optional<uint32_t> active_member_id,
Layer::EntropyMode entropy_mode)
: active_member_id(active_member_id), entropy_mode(entropy_mode) {}
diff --git a/chromium/components/variations/variations_layers.h b/chromium/components/variations/variations_layers.h
index 9dde18c03bf..d24484fd1ea 100644
--- a/chromium/components/variations/variations_layers.h
+++ b/chromium/components/variations/variations_layers.h
@@ -8,8 +8,8 @@
#include <map>
#include "base/metrics/field_trial.h"
-#include "base/optional.h"
#include "components/variations/proto/variations_seed.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace variations {
@@ -40,13 +40,13 @@ class VariationsLayers {
const Layer& layer_proto);
struct LayerInfo {
- LayerInfo(base::Optional<uint32_t> active_member_id,
+ LayerInfo(absl::optional<uint32_t> active_member_id,
Layer::EntropyMode entropy_mode);
~LayerInfo();
LayerInfo(const LayerInfo& other); // = delete;
LayerInfo& operator=(const LayerInfo&) = delete;
- base::Optional<uint32_t> active_member_id;
+ absl::optional<uint32_t> active_member_id;
Layer::EntropyMode entropy_mode;
};
std::map<uint32_t, LayerInfo> active_member_for_layer_;
diff --git a/chromium/components/variations/variations_murmur_hash.h b/chromium/components/variations/variations_murmur_hash.h
index a1e28ee342f..d4a02918792 100644
--- a/chromium/components/variations/variations_murmur_hash.h
+++ b/chromium/components/variations/variations_murmur_hash.h
@@ -6,7 +6,6 @@
#define COMPONENTS_VARIATIONS_VARIATIONS_MURMUR_HASH_H_
#include <cstdint>
-#include <string>
#include <vector>
#include "base/compiler_specific.h"
diff --git a/chromium/components/variations/variations_seed_processor.cc b/chromium/components/variations/variations_seed_processor.cc
index d0120106e57..2ee99c1600e 100644
--- a/chromium/components/variations/variations_seed_processor.cc
+++ b/chromium/components/variations/variations_seed_processor.cc
@@ -13,13 +13,13 @@
#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "components/variations/client_filterable_state.h"
#include "components/variations/processed_study.h"
#include "components/variations/study_filtering.h"
#include "components/variations/variations_associated_data.h"
#include "components/variations/variations_layers.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace variations {
@@ -40,14 +40,14 @@ void RegisterExperimentParams(const Study& study,
// Returns the IDCollectionKey with which |experiment| should be associated.
// Returns nullopt when |experiment| doesn't have a Google web or Google web
// trigger experiment ID.
-base::Optional<IDCollectionKey> GetKeyForWebExperiment(
+absl::optional<IDCollectionKey> GetKeyForWebExperiment(
const Study_Experiment& experiment) {
bool has_web_experiment_id = experiment.has_google_web_experiment_id();
bool has_web_trigger_experiment_id =
experiment.has_google_web_trigger_experiment_id();
if (!has_web_experiment_id && !has_web_trigger_experiment_id)
- return base::nullopt;
+ return absl::nullopt;
// An experiment cannot have both |google_web_experiment_id| and
// |google_trigger_web_experiment_id|. This is enforced by the variations
@@ -76,7 +76,7 @@ void RegisterVariationIds(const Study_Experiment& experiment,
variation_id);
}
- base::Optional<IDCollectionKey> key = GetKeyForWebExperiment(experiment);
+ absl::optional<IDCollectionKey> key = GetKeyForWebExperiment(experiment);
if (!key.has_value())
return;
diff --git a/chromium/components/variations/variations_seed_processor.h b/chromium/components/variations/variations_seed_processor.h
index 75c0ba8d37a..553556b0012 100644
--- a/chromium/components/variations/variations_seed_processor.h
+++ b/chromium/components/variations/variations_seed_processor.h
@@ -15,7 +15,6 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
-#include "base/time/time.h"
#include "base/version.h"
#include "components/variations/proto/study.pb.h"
#include "components/variations/proto/variations_seed.pb.h"
diff --git a/chromium/components/vector_icons/BUILD.gn b/chromium/components/vector_icons/BUILD.gn
index b407f2d64d8..2cafc73063d 100644
--- a/chromium/components/vector_icons/BUILD.gn
+++ b/chromium/components/vector_icons/BUILD.gn
@@ -8,7 +8,6 @@ aggregate_vector_icons("components_vector_icons") {
icon_directory = "."
sources = [
- "add_cellular_network.icon",
"ads.icon",
"back_arrow.icon",
"blocked_badge.icon",
@@ -18,6 +17,8 @@ aggregate_vector_icons("components_vector_icons") {
"business.icon",
"call.icon",
"call_end.icon",
+ "caret_down.icon",
+ "caret_up.icon",
"certificate.icon",
"check_circle.icon",
"close.icon",
@@ -29,6 +30,7 @@ aggregate_vector_icons("components_vector_icons") {
"description.icon",
"devices.icon",
"edit.icon",
+ "email.icon",
"error.icon",
"error_outline.icon",
"ethernet.icon",
@@ -45,6 +47,8 @@ aggregate_vector_icons("components_vector_icons") {
"headset.icon",
"help.icon",
"help_outline.icon",
+ "https_valid.icon",
+ "https_valid_arrow.icon",
"info_outline.icon",
"insert_drive_file_outline.icon",
"launch.icon",
@@ -64,6 +68,7 @@ aggregate_vector_icons("components_vector_icons") {
"mic.icon",
"mic_off.icon",
"midi.icon",
+ "not_secure_warning.icon",
"notification_explore.icon",
"notifications.icon",
"notifications_off.icon",
@@ -83,6 +88,7 @@ aggregate_vector_icons("components_vector_icons") {
"sensors.icon",
"serial_port.icon",
"settings.icon",
+ "submenu_arrow.icon",
"sync.icon",
"usb.icon",
"videocam.icon",
diff --git a/chromium/components/vector_icons/add_cellular_network.icon b/chromium/components/vector_icons/add_cellular_network.icon
deleted file mode 100644
index 3cd14272a09..00000000000
--- a/chromium/components/vector_icons/add_cellular_network.icon
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 20,
-MOVE_TO, 16, 8,
-CUBIC_TO, 16.34f, 8, 16.68f, 8.03f, 17, 8.08f,
-V_LINE_TO, 5,
-CUBIC_TO, 17, 4.11f, 15.92f, 3.66f, 15.29f, 4.29f,
-LINE_TO, 4.29f, 15.29f,
-CUBIC_TO, 3.66f, 15.92f, 4.11f, 17, 5, 17,
-H_LINE_TO, 10.8f,
-CUBIC_TO, 10.29f, 16.12f, 10, 15.09f, 10, 14,
-CUBIC_TO, 10, 10.69f, 12.69f, 8, 16, 8,
-CLOSE,
-MOVE_TO, 19, 13,
-H_LINE_TO, 17,
-V_LINE_TO, 11,
-H_LINE_TO, 15,
-V_LINE_TO, 13,
-H_LINE_TO, 13,
-V_LINE_TO, 15,
-H_LINE_TO, 15,
-V_LINE_TO, 17,
-H_LINE_TO, 17,
-V_LINE_TO, 15,
-H_LINE_TO, 19,
-V_LINE_TO, 13,
-CLOSE \ No newline at end of file
diff --git a/chromium/components/vector_icons/caret_down.icon b/chromium/components/vector_icons/caret_down.icon
new file mode 100644
index 00000000000..e281716f9c9
--- /dev/null
+++ b/chromium/components/vector_icons/caret_down.icon
@@ -0,0 +1,20 @@
+// 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.
+
+// A variant of ic_expand_more with rounded corners.
+CANVAS_DIMENSIONS, 32,
+STROKE, 3,
+MOVE_TO, 8.5f, 12.5f,
+R_LINE_TO, 7.5f, 8,
+R_LINE_TO, 7.5f, -8,
+// Hard clip at path points +- half the stroke.
+CLIP, 7, 11, 18, 11,
+
+// A variant of ic_expand_more with rounded corners and optimized for 1x
+// scale factor devices.
+CANVAS_DIMENSIONS, 16,
+STROKE, 1.765f,
+MOVE_TO, 4, 6,
+R_LINE_TO, 4, 4,
+R_LINE_TO, 4, -4,
diff --git a/chromium/components/vector_icons/caret_up.icon b/chromium/components/vector_icons/caret_up.icon
new file mode 100644
index 00000000000..91082812fc0
--- /dev/null
+++ b/chromium/components/vector_icons/caret_up.icon
@@ -0,0 +1,20 @@
+// 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.
+
+// A variant of ic_expand_less with rounded corners.
+CANVAS_DIMENSIONS, 32,
+// Hard clip at path points +- half the stroke.
+CLIP, 7, 10, 18, 11,
+STROKE, 3,
+MOVE_TO, 8.5f, 19.5f,
+R_LINE_TO, 7.5f, -8,
+R_LINE_TO, 7.5f, 8,
+
+// A variant of ic_expand_less with rounded corners and optimized for 1x
+// scale factor devices.
+CANVAS_DIMENSIONS, 16,
+STROKE, 1.765f,
+MOVE_TO, 4, 10,
+R_LINE_TO, 4, -4,
+R_LINE_TO, 4, 4,
diff --git a/chromium/components/vector_icons/email.icon b/chromium/components/vector_icons/email.icon
new file mode 100644
index 00000000000..5e2190dadea
--- /dev/null
+++ b/chromium/components/vector_icons/email.icon
@@ -0,0 +1,23 @@
+// Copyright 2021 The Chromium 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, 20, 4,
+H_LINE_TO, 4,
+R_CUBIC_TO, -1.1f, 0, -1.99f, 0.9f, -1.99f, 2,
+LINE_TO, 2, 18,
+R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
+R_H_LINE_TO, 16,
+R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
+V_LINE_TO, 6,
+R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
+CLOSE,
+R_MOVE_TO, 0, 4,
+R_LINE_TO, -8, 5,
+R_LINE_TO, -8, -5,
+V_LINE_TO, 6,
+R_LINE_TO, 8, 5,
+R_LINE_TO, 8, -5,
+R_V_LINE_TO, 2,
+CLOSE
diff --git a/chromium/components/vector_icons/https_valid.icon b/chromium/components/vector_icons/https_valid.icon
new file mode 100644
index 00000000000..ae3a54b46f5
--- /dev/null
+++ b/chromium/components/vector_icons/https_valid.icon
@@ -0,0 +1,49 @@
+// 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.
+
+CANVAS_DIMENSIONS, 32,
+MOVE_TO, 21, 13,
+R_V_LINE_TO, -2,
+R_CUBIC_TO, 0, -2.76f, -2.24f, -5, -5, -5,
+R_CUBIC_TO, -2.76f, 0.02f, -5, 2.24f, -5, 5,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, -1,
+R_CUBIC_TO, -1.1f, 0, -2, 0.9f, -2, 1.99f,
+V_LINE_TO, 25,
+R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
+R_H_LINE_TO, 12,
+R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
+V_LINE_TO, 15,
+R_CUBIC_TO, 0, -1.05f, -0.9f, -2, -2, -2,
+R_H_LINE_TO, -1,
+CLOSE,
+R_MOVE_TO, -8, 0.02f,
+V_LINE_TO, 11,
+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, 2.02f,
+R_H_LINE_TO, -6,
+CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 11, 5,
+R_CUBIC_TO, 0, -1.67f, -1.34f, -3, -3, -2.99f,
+R_CUBIC_TO, -1.67f, 0, -3, 1.32f, -3, 2.99f,
+R_V_LINE_TO, 1,
+R_CUBIC_TO, -0.55f, 0, -1, 0.45f, -1, 1,
+V_LINE_TO, 12,
+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, 7,
+R_CUBIC_TO, 0, -0.53f, -0.48f, -0.97f, -1, -1,
+R_CUBIC_TO, -0.02f, 0, 0, -1, 0, -1,
+CLOSE,
+MOVE_TO, 6, 6.01f,
+V_LINE_TO, 5.01f,
+R_CUBIC_TO, 0, -1.1f, 0.9f, -1.99f, 2, -1.99f,
+R_CUBIC_TO, 1.1f, 0, 2, 0.89f, 2, 2,
+V_LINE_TO, 6.01f,
+H_LINE_TO, 6,
+CLOSE
diff --git a/chromium/components/vector_icons/https_valid_arrow.icon b/chromium/components/vector_icons/https_valid_arrow.icon
new file mode 100644
index 00000000000..9548363fbe9
--- /dev/null
+++ b/chromium/components/vector_icons/https_valid_arrow.icon
@@ -0,0 +1,20 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 16,
+NEW_PATH,
+MOVE_TO, 8.59f, 10.75f,
+CUBIC_TO, 8.44f, 10.9f, 8.23f, 11, 8, 11,
+CUBIC_TO, 7.77f, 11, 7.56f, 10.9f, 7.41f, 10.75f,
+LINE_TO, 3.24f, 6.46f,
+CUBIC_TO, 3.09f, 6.31f, 3, 6.09f, 3, 5.86f,
+CUBIC_TO, 3, 5.38f, 3.37f, 5, 3.83f, 5,
+CUBIC_TO, 4.06f, 5, 4.27f, 5.1f, 4.42f, 5.25f,
+LINE_TO, 8, 8.93f,
+LINE_TO, 11.58f, 5.25f,
+CUBIC_TO, 11.73f, 5.1f, 11.94f, 5, 12.17f, 5,
+CUBIC_TO, 12.63f, 5, 13, 5.38f, 13, 5.86f,
+CUBIC_TO, 13, 6.09f, 12.91f, 6.31f, 12.76f, 6.46f,
+LINE_TO, 8.59f, 10.75f,
+CLOSE \ No newline at end of file
diff --git a/chromium/components/vector_icons/not_secure_warning.icon b/chromium/components/vector_icons/not_secure_warning.icon
new file mode 100644
index 00000000000..87478cc5562
--- /dev/null
+++ b/chromium/components/vector_icons/not_secure_warning.icon
@@ -0,0 +1,41 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 32,
+MOVE_TO, 4, 27,
+R_H_LINE_TO, 25,
+LINE_TO, 16.5f, 5,
+LINE_TO, 4, 27,
+CLOSE,
+R_MOVE_TO, 14, -3,
+R_H_LINE_TO, -3,
+R_V_LINE_TO, -3,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, 3,
+CLOSE,
+R_MOVE_TO, 0, -5,
+R_H_LINE_TO, -3,
+R_V_LINE_TO, -6,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, 6,
+CLOSE
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 0.5f, 14,
+R_H_LINE_TO, 15,
+LINE_TO, 8, 1,
+LINE_TO, 0.5f, 14,
+CLOSE,
+MOVE_TO, 9, 12,
+H_LINE_TO, 7,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 2,
+CLOSE,
+R_MOVE_TO, 0, -3,
+H_LINE_TO, 7,
+V_LINE_TO, 6,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 3,
+CLOSE
diff --git a/chromium/components/vector_icons/submenu_arrow.icon b/chromium/components/vector_icons/submenu_arrow.icon
new file mode 100644
index 00000000000..9d633095483
--- /dev/null
+++ b/chromium/components/vector_icons/submenu_arrow.icon
@@ -0,0 +1,19 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 16,
+FLIPS_IN_RTL,
+MOVE_TO, 3, 16,
+R_LINE_TO, 11, -8,
+LINE_TO, 3, 0,
+R_V_LINE_TO, 16,
+CLOSE
+
+CANVAS_DIMENSIONS, 8,
+FLIPS_IN_RTL,
+MOVE_TO, 2, 8,
+R_LINE_TO, 5, -4,
+R_LINE_TO, -5, -4,
+R_V_LINE_TO, 8,
+CLOSE
diff --git a/chromium/components/vector_icons/vector_icons.gni b/chromium/components/vector_icons/vector_icons.gni
index ec13569abe4..a0641b285bb 100644
--- a/chromium/components/vector_icons/vector_icons.gni
+++ b/chromium/components/vector_icons/vector_icons.gni
@@ -28,6 +28,8 @@ template("aggregate_vector_icons") {
defined(invoker.icon_directory),
"Need icon_directory in $target_name where the icons and templates live.")
+ public_deps = [ "//base" ]
+
action(target_name) {
visibility = [ ":*" ]
diff --git a/chromium/components/version_info/version_info.cc b/chromium/components/version_info/version_info.cc
index f608d5e23f5..32e6081a0f4 100644
--- a/chromium/components/version_info/version_info.cc
+++ b/chromium/components/version_info/version_info.cc
@@ -52,7 +52,7 @@ std::string GetOSType() {
return "Windows";
#elif defined(OS_IOS)
return "iOS";
-#elif defined(OS_APPLE)
+#elif defined(OS_MAC)
return "Mac OS X";
#elif BUILDFLAG(IS_CHROMEOS_ASH)
# if BUILDFLAG(GOOGLE_CHROME_BRANDING)
diff --git a/chromium/components/viz/BUILD.gn b/chromium/components/viz/BUILD.gn
index 90239672e57..71a7ee40546 100644
--- a/chromium/components/viz/BUILD.gn
+++ b/chromium/components/viz/BUILD.gn
@@ -59,6 +59,8 @@ viz_test("viz_perftests") {
"//skia",
]
+ data = [ "test/data/" ]
+
# This target should not require the Chrome executable to run.
assert_no_deps = [ "//chrome" ]
diff --git a/chromium/components/viz/DEPS b/chromium/components/viz/DEPS
index fc9c58a7cf5..4f0645c83c6 100644
--- a/chromium/components/viz/DEPS
+++ b/chromium/components/viz/DEPS
@@ -8,7 +8,7 @@ include_rules = [
]
specific_include_rules = {
- ".*_(unittest|perftest|fuzzer)\.cc": [
+ ".*_(unittest|perftest|perf_test|fuzzer)\.cc": [
"+components/viz",
],
diff --git a/chromium/components/viz/OWNERS b/chromium/components/viz/OWNERS
index 7815abbb2b4..db011f87e38 100644
--- a/chromium/components/viz/OWNERS
+++ b/chromium/components/viz/OWNERS
@@ -49,6 +49,10 @@ vasilyt@chromium.org
magchen@chromium.org
petermcneeley@chromium.org
+# viz debugger
+petermcneeley@chromium.org
+sadrul@chromium.org
+
# scheduling / begin frames
sunnyps@chromium.org
diff --git a/chromium/components/viz/client/client_resource_provider.cc b/chromium/components/viz/client/client_resource_provider.cc
index a36b4322389..758a1313baf 100644
--- a/chromium/components/viz/client/client_resource_provider.cc
+++ b/chromium/components/viz/client/client_resource_provider.cc
@@ -29,7 +29,7 @@ namespace viz {
struct ClientResourceProvider::ImportedResource {
TransferableResource resource;
- std::unique_ptr<SingleReleaseCallback> release_callback;
+ ReleaseCallback release_callback;
int exported_count = 0;
bool marked_for_deletion = false;
@@ -42,7 +42,7 @@ struct ClientResourceProvider::ImportedResource {
ImportedResource(ResourceId id,
const TransferableResource& resource,
- std::unique_ptr<SingleReleaseCallback> release_callback)
+ ReleaseCallback release_callback)
: resource(resource),
release_callback(std::move(release_callback)),
// If the resource is immediately deleted, it returns the same SyncToken
@@ -260,15 +260,8 @@ void ClientResourceProvider::ReceiveReturnsFromParent(
continue;
}
- // Save the ReleaseCallback to run after iterating through internal data
- // structures, in case it calls back into this class.
- auto run_callback = [](std::unique_ptr<SingleReleaseCallback> cb,
- const gpu::SyncToken& sync_token, bool lost) {
- cb->Run(sync_token, lost);
- // |cb| is destroyed when leaving scope.
- };
release_callbacks.push_back(
- base::BindOnce(run_callback, std::move(imported.release_callback),
+ base::BindOnce(std::move(imported.release_callback),
imported.returned_sync_token, imported.returned_lost));
// We don't want to keep this resource, so we leave |imported_keep_end_it|
// pointing to it (since it points past the end of what we're keeping). We
@@ -291,7 +284,7 @@ void ClientResourceProvider::ReceiveReturnsFromParent(
ResourceId ClientResourceProvider::ImportResource(
const TransferableResource& resource,
- std::unique_ptr<SingleReleaseCallback> release_callback) {
+ ReleaseCallback release_callback) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
ResourceId id = id_generator_.GenerateNextId();
auto result = imported_resources_.emplace(
@@ -307,8 +300,8 @@ void ClientResourceProvider::RemoveImportedResource(ResourceId id) {
ImportedResource& imported = it->second;
imported.marked_for_deletion = true;
if (imported.exported_count == 0) {
- imported.release_callback->Run(imported.returned_sync_token,
- imported.returned_lost);
+ std::move(imported.release_callback)
+ .Run(imported.returned_sync_token, imported.returned_lost);
imported_resources_.erase(it);
}
}
@@ -329,8 +322,8 @@ void ClientResourceProvider::ReleaseAllExportedResources(bool lose) {
return false;
}
- imported.release_callback->Run(imported.returned_sync_token,
- imported.returned_lost);
+ std::move(imported.release_callback)
+ .Run(imported.returned_sync_token, imported.returned_lost);
// Was exported and removed by the client, so return it now.
return true;
};
@@ -355,8 +348,9 @@ void ClientResourceProvider::ShutdownAndReleaseAllResources() {
<< imported.stack_trace.ToString() << "===";
#endif
- imported.release_callback->Run(imported.returned_sync_token,
- /*is_lost=*/true);
+ std::move(imported.release_callback)
+ .Run(imported.returned_sync_token,
+ /*is_lost=*/true);
}
imported_resources_.clear();
}
diff --git a/chromium/components/viz/client/client_resource_provider.h b/chromium/components/viz/client/client_resource_provider.h
index ad2206924f5..dd14785110f 100644
--- a/chromium/components/viz/client/client_resource_provider.h
+++ b/chromium/components/viz/client/client_resource_provider.h
@@ -8,6 +8,7 @@
#include <memory>
#include <vector>
+#include "base/containers/flat_map.h"
#include "base/threading/thread_checker.h"
#include "components/viz/client/viz_client_export.h"
#include "components/viz/common/display/renderer_settings.h"
@@ -15,7 +16,6 @@
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/resource_settings.h"
#include "components/viz/common/resources/returned_resource.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/skia/include/core/SkSurface.h"
@@ -37,9 +37,8 @@ class RasterContextProvider;
// This class is used to give an integer name (ResourceId) to a gpu or software
// resource (shipped as a TransferableResource), in order to use that name in
// DrawQuads and give the resource to the viz display compositor. When the
-// resource is removed from the ClientResourceProvider, the
-// SingleReleaseCallback will be called once the resource is no longer in use by
-// the display compositor.
+// resource is removed from the ClientResourceProvider, the ReleaseCallback will
+// be called once the resource is no longer in use by the display compositor.
//
// This class is not thread-safe and can only be called from the thread it was
// created on (in practice, the impl thread).
@@ -77,11 +76,11 @@ class VIZ_CLIENT_EXPORT ClientResourceProvider {
// Receives a resource from an external client that can be used in compositor
// frames, via the returned ResourceId.
- ResourceId ImportResource(const TransferableResource&,
- std::unique_ptr<SingleReleaseCallback>);
+ ResourceId ImportResource(const TransferableResource& resource,
+ ReleaseCallback release_callback);
// Removes an imported resource, which will call the ReleaseCallback given
// originally, once the resource is no longer in use by any compositor frame.
- void RemoveImportedResource(ResourceId);
+ void RemoveImportedResource(ResourceId resource_id);
// Call this to indicate that the connection to the parent is lost and
// resources previously exported will not be able to be returned. If |lose| is
@@ -95,7 +94,7 @@ class VIZ_CLIENT_EXPORT ClientResourceProvider {
// RemoveImportedResource().
void ReleaseAllExportedResources(bool lose);
- // Immediately runs the SingleReleaseCallback for all resources that have been
+ // Immediately runs the ReleaseCallback for all resources that have been
// previously imported and removed, but not released yet. There should not be
// any imported resources yet when this is called, as they can be removed
// first via RemoveImportedResource(), and potentially avoid being lost.
diff --git a/chromium/components/viz/client/client_resource_provider_unittest.cc b/chromium/components/viz/client/client_resource_provider_unittest.cc
index 98cfd43cf62..0d7f2fa3643 100644
--- a/chromium/components/viz/client/client_resource_provider_unittest.cc
+++ b/chromium/components/viz/client/client_resource_provider_unittest.cc
@@ -10,8 +10,8 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/test/gtest_util.h"
+#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/resources/returned_resource.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/test/test_context_provider.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -96,8 +96,8 @@ TEST_P(ClientResourceProviderTest, TransferableResourceReleased) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId id = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// The local id is different.
EXPECT_NE(id, tran.id);
@@ -112,8 +112,8 @@ TEST_P(ClientResourceProviderTest, TransferableResourceSendToParent) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId id = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Export the resource.
std::vector<ResourceId> to_send = {id};
@@ -142,7 +142,7 @@ TEST_P(ClientResourceProviderTest, TransferableResourceSendToParent) {
// Return the resource, with a sync token if using gpu.
std::vector<ReturnedResource> returned;
- returned.push_back({});
+ returned.emplace_back();
returned.back().id = exported[0].id;
if (use_gpu())
returned.back().sync_token = SyncTokenFromUInt(31);
@@ -151,16 +151,14 @@ TEST_P(ClientResourceProviderTest, TransferableResourceSendToParent) {
// The sync token is given to the ReleaseCallback.
EXPECT_CALL(release, Released(returned[0].sync_token, false));
- provider().ReceiveReturnsFromParent(returned);
+ provider().ReceiveReturnsFromParent(std::move(returned));
}
TEST_P(ClientResourceProviderTest, TransferableResourceSendTwoToParent) {
TransferableResource tran[] = {MakeTransferableResource(use_gpu(), 'a', 15),
MakeTransferableResource(use_gpu(), 'b', 16)};
- ResourceId id1 = provider().ImportResource(
- tran[0], SingleReleaseCallback::Create(base::DoNothing()));
- ResourceId id2 = provider().ImportResource(
- tran[1], SingleReleaseCallback::Create(base::DoNothing()));
+ ResourceId id1 = provider().ImportResource(tran[0], base::DoNothing());
+ ResourceId id2 = provider().ImportResource(tran[1], base::DoNothing());
// Export the resource.
std::vector<ResourceId> to_send = {id1, id2};
@@ -193,8 +191,7 @@ TEST_P(ClientResourceProviderTest, TransferableResourceSendTwoToParent) {
TEST_P(ClientResourceProviderTest, TransferableResourceSendToParentTwoTimes) {
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
- ResourceId id = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::DoNothing()));
+ ResourceId id = provider().ImportResource(tran, base::DoNothing());
// Export the resource.
std::vector<ResourceId> to_send = {id};
@@ -205,13 +202,13 @@ TEST_P(ClientResourceProviderTest, TransferableResourceSendToParentTwoTimes) {
// Return the resource, with a sync token if using gpu.
std::vector<ReturnedResource> returned;
- returned.push_back({});
+ returned.emplace_back();
returned.back().id = exported[0].id;
if (use_gpu())
returned.back().sync_token = SyncTokenFromUInt(31);
returned.back().count = 1;
returned.back().lost = false;
- provider().ReceiveReturnsFromParent(returned);
+ provider().ReceiveReturnsFromParent(std::move(returned));
// Then export again, it still sends.
exported.clear();
@@ -228,8 +225,8 @@ TEST_P(ClientResourceProviderTest,
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId id = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Export the resource.
std::vector<ResourceId> to_send = {id};
@@ -257,9 +254,8 @@ TEST_P(ClientResourceProviderTest, TransferableResourceSendToParentManyUnsent) {
for (int i = 0; i < 5; ++i) {
data[i].tran = MakeTransferableResource(use_gpu(), 'a', 15);
data[i].id = provider().ImportResource(
- data[i].tran,
- SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ data[i].tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
}
std::sort(std::begin(data), std::end(data),
[](const Data& a, const Data& b) { return a.id < b.id; });
@@ -283,7 +279,7 @@ TEST_P(ClientResourceProviderTest, TransferableResourceSendToParentManyUnsent) {
// Return the resource, with a sync token if using gpu.
std::vector<ReturnedResource> returned;
- returned.push_back({});
+ returned.emplace_back();
returned.back().id = exported[0].id;
if (use_gpu())
returned.back().sync_token = SyncTokenFromUInt(31);
@@ -292,7 +288,7 @@ TEST_P(ClientResourceProviderTest, TransferableResourceSendToParentManyUnsent) {
// The sync token is given to the ReleaseCallback.
EXPECT_CALL(release, Released(returned[0].sync_token, false));
- provider().ReceiveReturnsFromParent(returned);
+ provider().ReceiveReturnsFromParent(std::move(returned));
EXPECT_CALL(release, Released(_, false)).Times(4);
provider().RemoveImportedResource(data[0].id);
@@ -305,8 +301,8 @@ TEST_P(ClientResourceProviderTest, TransferableResourceRemovedAfterReturn) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId id = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Export the resource.
std::vector<ResourceId> to_send = {id};
@@ -316,7 +312,7 @@ TEST_P(ClientResourceProviderTest, TransferableResourceRemovedAfterReturn) {
// Return the resource. This does not release the resource back to
// the client.
std::vector<ReturnedResource> returned;
- returned.push_back({});
+ returned.emplace_back();
returned.back().id = exported[0].id;
if (use_gpu())
returned.back().sync_token = SyncTokenFromUInt(31);
@@ -324,10 +320,12 @@ TEST_P(ClientResourceProviderTest, TransferableResourceRemovedAfterReturn) {
returned.back().lost = false;
EXPECT_CALL(release, Released(_, _)).Times(0);
- provider().ReceiveReturnsFromParent(returned);
+ auto sync_token = returned.back().sync_token;
+ provider().ReceiveReturnsFromParent(std::move(returned));
+ testing::Mock::VerifyAndClearExpectations(&release);
// Once removed, the resource is released.
- EXPECT_CALL(release, Released(returned[0].sync_token, false));
+ EXPECT_CALL(release, Released(sync_token, false));
provider().RemoveImportedResource(id);
}
@@ -335,8 +333,8 @@ TEST_P(ClientResourceProviderTest, TransferableResourceExportedTwice) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId id = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Export the resource once.
std::vector<ResourceId> to_send = {id};
@@ -352,30 +350,39 @@ TEST_P(ClientResourceProviderTest, TransferableResourceExportedTwice) {
exported = {};
provider().PrepareSendToParent(to_send, &exported, context_provider());
- // Return the resource the first time.
- std::vector<ReturnedResource> returned;
- returned.push_back({});
- returned.back().id = exported[0].id;
- if (use_gpu())
- returned.back().sync_token = SyncTokenFromUInt(31);
- returned.back().count = 1;
- returned.back().lost = false;
- provider().ReceiveReturnsFromParent(returned);
+ {
+ // Return the resource the first time.
+ std::vector<ReturnedResource> returned;
+ returned.emplace_back();
+ returned.back().id = exported[0].id;
+ if (use_gpu())
+ returned.back().sync_token = SyncTokenFromUInt(31);
+ returned.back().count = 1;
+ returned.back().lost = false;
+ provider().ReceiveReturnsFromParent(std::move(returned));
+ }
- // And a second time, with a different sync token. Now the ReleaseCallback can
- // happen, using the latest sync token.
- if (use_gpu())
- returned.back().sync_token = SyncTokenFromUInt(47);
- EXPECT_CALL(release, Released(returned[0].sync_token, false));
- provider().ReceiveReturnsFromParent(returned);
+ {
+ // And a second time, with a different sync token. Now the ReleaseCallback
+ // can happen, using the latest sync token.
+ std::vector<ReturnedResource> returned;
+ returned.emplace_back();
+ returned.back().id = exported[0].id;
+ if (use_gpu())
+ returned.back().sync_token = SyncTokenFromUInt(47);
+ returned.back().count = 1;
+ returned.back().lost = false;
+ EXPECT_CALL(release, Released(returned[0].sync_token, false));
+ provider().ReceiveReturnsFromParent(std::move(returned));
+ }
}
TEST_P(ClientResourceProviderTest, TransferableResourceReturnedTwiceAtOnce) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId id = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Export the resource once.
std::vector<ResourceId> to_send = {id};
@@ -393,7 +400,7 @@ TEST_P(ClientResourceProviderTest, TransferableResourceReturnedTwiceAtOnce) {
// Return both exports at once.
std::vector<ReturnedResource> returned;
- returned.push_back({});
+ returned.emplace_back();
returned.back().id = exported[0].id;
if (use_gpu())
returned.back().sync_token = SyncTokenFromUInt(31);
@@ -402,15 +409,15 @@ TEST_P(ClientResourceProviderTest, TransferableResourceReturnedTwiceAtOnce) {
// When returned, the ReleaseCallback can happen, using the latest sync token.
EXPECT_CALL(release, Released(returned[0].sync_token, false));
- provider().ReceiveReturnsFromParent(returned);
+ provider().ReceiveReturnsFromParent(std::move(returned));
}
TEST_P(ClientResourceProviderTest, TransferableResourceLostOnReturn) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId id = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Export the resource once.
std::vector<ResourceId> to_send = {id};
@@ -426,27 +433,35 @@ TEST_P(ClientResourceProviderTest, TransferableResourceLostOnReturn) {
exported = {};
provider().PrepareSendToParent(to_send, &exported, context_provider());
- // Return the resource the first time, not lost.
- std::vector<ReturnedResource> returned;
- returned.push_back({});
- returned.back().id = exported[0].id;
- returned.back().count = 1;
- returned.back().lost = false;
- provider().ReceiveReturnsFromParent(returned);
+ {
+ // Return the resource the first time, not lost.
+ std::vector<ReturnedResource> returned;
+ returned.emplace_back();
+ returned.back().id = exported[0].id;
+ returned.back().count = 1;
+ returned.back().lost = false;
+ provider().ReceiveReturnsFromParent(std::move(returned));
+ }
- // Return a second time, as lost. The ReturnCallback should report it
- // lost.
- returned.back().lost = true;
- EXPECT_CALL(release, Released(_, true));
- provider().ReceiveReturnsFromParent(returned);
+ {
+ // Return a second time, as lost. The ReturnCallback should report it
+ // lost.
+ std::vector<ReturnedResource> returned;
+ returned.emplace_back();
+ returned.back().id = exported[0].id;
+ returned.back().count = 1;
+ returned.back().lost = true;
+ EXPECT_CALL(release, Released(_, true));
+ provider().ReceiveReturnsFromParent(std::move(returned));
+ }
}
TEST_P(ClientResourceProviderTest, TransferableResourceLostOnFirstReturn) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId id = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Export the resource once.
std::vector<ResourceId> to_send = {id};
@@ -462,18 +477,26 @@ TEST_P(ClientResourceProviderTest, TransferableResourceLostOnFirstReturn) {
exported = {};
provider().PrepareSendToParent(to_send, &exported, context_provider());
- // Return the resource the first time, marked as lost.
- std::vector<ReturnedResource> returned;
- returned.push_back({});
- returned.back().id = exported[0].id;
- returned.back().count = 1;
- returned.back().lost = true;
- provider().ReceiveReturnsFromParent(returned);
+ {
+ // Return the resource the first time, marked as lost.
+ std::vector<ReturnedResource> returned;
+ returned.emplace_back();
+ returned.back().id = exported[0].id;
+ returned.back().count = 1;
+ returned.back().lost = true;
+ provider().ReceiveReturnsFromParent(std::move(returned));
+ }
- // Return a second time, not lost. The first lost signal should not be lost.
- returned.back().lost = false;
- EXPECT_CALL(release, Released(_, true));
- provider().ReceiveReturnsFromParent(returned);
+ {
+ // Return a second time, not lost. The first lost signal should not be lost.
+ std::vector<ReturnedResource> returned;
+ returned.emplace_back();
+ returned.back().id = exported[0].id;
+ returned.back().count = 1;
+ returned.back().lost = false;
+ EXPECT_CALL(release, Released(_, true));
+ provider().ReceiveReturnsFromParent(std::move(returned));
+ }
}
TEST_P(ClientResourceProviderTest, ReturnedSyncTokensArePassedToClient) {
@@ -496,8 +519,8 @@ TEST_P(ClientResourceProviderTest, ReturnedSyncTokensArePassedToClient) {
sync_token, size,
false /* is_overlay_candidate */);
ResourceId resource = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
EXPECT_TRUE(tran.mailbox_holder.sync_token.HasData());
// All the logic below assumes that the sync token releases are all positive.
@@ -541,8 +564,8 @@ TEST_P(ClientResourceProviderTest, LostResourcesAreReturnedLost) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId resource = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Transfer the resource to the parent.
std::vector<TransferableResource> list;
@@ -553,7 +576,7 @@ TEST_P(ClientResourceProviderTest, LostResourcesAreReturnedLost) {
std::vector<ReturnedResource> returned_to_child;
returned_to_child.push_back(list[0].ToReturnedResource());
returned_to_child.back().lost = true;
- provider().ReceiveReturnsFromParent(returned_to_child);
+ provider().ReceiveReturnsFromParent(std::move(returned_to_child));
// Delete the resource in the child. Expect the resource to be lost.
EXPECT_CALL(release, Released(_, true));
@@ -564,8 +587,8 @@ TEST_P(ClientResourceProviderTest, ShutdownLosesExportedResources) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId resource = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Transfer the resource to the parent.
std::vector<TransferableResource> list;
@@ -585,8 +608,8 @@ TEST_P(ClientResourceProviderTest, ReleaseExportedResources) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId resource = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Transfer the resource to the parent.
std::vector<TransferableResource> list;
@@ -610,8 +633,8 @@ TEST_P(ClientResourceProviderTest, ReleaseExportedResourcesThenRemove) {
MockReleaseCallback release;
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 15);
ResourceId resource = provider().ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
// Transfer the resource to the parent.
std::vector<TransferableResource> list;
@@ -639,9 +662,8 @@ TEST_P(ClientResourceProviderTest, ReleaseMultipleResources) {
for (int i = 0; i < 5; ++i) {
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 1 + i);
resources[i] = provider().ImportResource(
- tran, SingleReleaseCallback::Create(
- base::BindOnce(&MockReleaseCallback::ReleasedWithId,
- base::Unretained(&release), ResourceId(i))));
+ tran, base::BindOnce(&MockReleaseCallback::ReleasedWithId,
+ base::Unretained(&release), ResourceId(i)));
}
// Transfer some resources to the parent, but not in the sorted order.
@@ -658,7 +680,7 @@ TEST_P(ClientResourceProviderTest, ReleaseMultipleResources) {
returned_to_child.push_back(list[0].ToReturnedResource());
returned_to_child.push_back(list[1].ToReturnedResource());
returned_to_child.push_back(list[2].ToReturnedResource());
- provider().ReceiveReturnsFromParent(returned_to_child);
+ provider().ReceiveReturnsFromParent(std::move(returned_to_child));
// Remove them from the ClientResourceProvider, they should be returned as
// they're no longer exported.
@@ -686,9 +708,8 @@ TEST_P(ClientResourceProviderTest, ReleaseMultipleResourcesBeforeReturn) {
for (int i = 0; i < 5; ++i) {
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 1 + i);
resources[i] = provider().ImportResource(
- tran, SingleReleaseCallback::Create(
- base::BindOnce(&MockReleaseCallback::ReleasedWithId,
- base::Unretained(&release), ResourceId(i))));
+ tran, base::BindOnce(&MockReleaseCallback::ReleasedWithId,
+ base::Unretained(&release), ResourceId(i)));
}
// Transfer some resources to the parent, but not in the sorted order.
@@ -715,7 +736,7 @@ TEST_P(ClientResourceProviderTest, ReleaseMultipleResourcesBeforeReturn) {
EXPECT_CALL(release, ReleasedWithId(kInvalidResourceId, _, false));
EXPECT_CALL(release, ReleasedWithId(ResourceId(2), _, false));
EXPECT_CALL(release, ReleasedWithId(ResourceId(4), _, false));
- provider().ReceiveReturnsFromParent(returned_to_child);
+ provider().ReceiveReturnsFromParent(std::move(returned_to_child));
// These were never exported.
EXPECT_CALL(release, ReleasedWithId(ResourceId(1), _, false));
@@ -734,9 +755,8 @@ TEST_P(ClientResourceProviderTest, ReturnDuplicateResourceBeforeRemove) {
for (int i = 0; i < 5; ++i) {
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 1 + i);
resources[i] = provider().ImportResource(
- tran, SingleReleaseCallback::Create(
- base::BindOnce(&MockReleaseCallback::ReleasedWithId,
- base::Unretained(&release), ResourceId(i))));
+ tran, base::BindOnce(&MockReleaseCallback::ReleasedWithId,
+ base::Unretained(&release), ResourceId(i)));
}
// Transfer a resource to the parent, do it twice.
@@ -751,7 +771,7 @@ TEST_P(ClientResourceProviderTest, ReturnDuplicateResourceBeforeRemove) {
std::vector<ReturnedResource> returned_to_child;
returned_to_child.push_back(list[0].ToReturnedResource());
returned_to_child.push_back(list[0].ToReturnedResource());
- provider().ReceiveReturnsFromParent(returned_to_child);
+ provider().ReceiveReturnsFromParent(std::move(returned_to_child));
// Remove it from the ClientResourceProvider, it should be returned as
// it's no longer exported.
@@ -779,9 +799,8 @@ TEST_P(ClientResourceProviderTest, ReturnDuplicateResourceAfterRemove) {
for (int i = 0; i < 5; ++i) {
TransferableResource tran = MakeTransferableResource(use_gpu(), 'a', 1 + i);
resources[i] = provider().ImportResource(
- tran, SingleReleaseCallback::Create(
- base::BindOnce(&MockReleaseCallback::ReleasedWithId,
- base::Unretained(&release), ResourceId(i))));
+ tran, base::BindOnce(&MockReleaseCallback::ReleasedWithId,
+ base::Unretained(&release), ResourceId(i)));
}
// Transfer a resource to the parent, do it twice.
@@ -803,7 +822,7 @@ TEST_P(ClientResourceProviderTest, ReturnDuplicateResourceAfterRemove) {
// Once no longer exported, since it was removed earlier, it will be returned
// immediately.
EXPECT_CALL(release, ReleasedWithId(ResourceId(2), _, false));
- provider().ReceiveReturnsFromParent(returned_to_child);
+ provider().ReceiveReturnsFromParent(std::move(returned_to_child));
// These were never exported.
EXPECT_CALL(release, ReleasedWithId(kInvalidResourceId, _, false));
diff --git a/chromium/components/viz/client/frame_eviction_manager.h b/chromium/components/viz/client/frame_eviction_manager.h
index 6b745230ff5..2d0b8e03b27 100644
--- a/chromium/components/viz/client/frame_eviction_manager.h
+++ b/chromium/components/viz/client/frame_eviction_manager.h
@@ -13,8 +13,8 @@
#include "base/macros.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/singleton.h"
-#include "base/optional.h"
#include "components/viz/client/viz_client_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace viz {
@@ -90,7 +90,7 @@ class VIZ_CLIENT_EXPORT FrameEvictionManager {
int pause_count_ = 0;
// Argument of the last CullUnlockedFrames call while paused.
- base::Optional<size_t> pending_unlocked_frame_limit_;
+ absl::optional<size_t> pending_unlocked_frame_limit_;
DISALLOW_COPY_AND_ASSIGN(FrameEvictionManager);
};
diff --git a/chromium/components/viz/common/BUILD.gn b/chromium/components/viz/common/BUILD.gn
index ae09dd6919a..6869f9dedb6 100644
--- a/chromium/components/viz/common/BUILD.gn
+++ b/chromium/components/viz/common/BUILD.gn
@@ -2,15 +2,24 @@
# 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/viz/common/debugger/viz_debugger.gni")
import("//components/viz/viz.gni")
import("//gpu/vulkan/features.gni")
import("//skia/features.gni")
import("//testing/test.gni")
+import("//third_party/inspector_protocol/inspector_protocol.gni")
+
source_set("resource_format") {
sources = [ "resources/resource_format.h" ]
}
+buildflag_header("buildflags") {
+ header = "buildflags.h"
+ flags = [ "USE_VIZ_DEBUGGER=$use_viz_debugger" ]
+}
+
viz_component("resource_format_utils") {
output_name = "viz_resource_format_utils"
@@ -44,7 +53,7 @@ viz_component("resource_format_utils") {
}
}
-# TODO(sgilhuly): To reduce link times, merge these context provider components
+# TODO(rivr): To reduce link times, merge these context provider components
# into a single gr_context_provider component.
if (is_mac) {
viz_component("metal_context_provider") {
@@ -248,8 +257,6 @@ viz_component("common") {
"resources/returned_resource.h",
"resources/shared_bitmap.cc",
"resources/shared_bitmap.h",
- "resources/single_release_callback.cc",
- "resources/single_release_callback.h",
"resources/transferable_resource.cc",
"resources/transferable_resource.h",
"skia_helper.cc",
@@ -279,6 +286,8 @@ viz_component("common") {
"switches.h",
"traced_value.cc",
"traced_value.h",
+ "transition_utils.cc",
+ "transition_utils.h",
"vertical_scroll_direction.h",
"viz_common_export.h",
"viz_utils.cc",
@@ -330,12 +339,14 @@ viz_component("common") {
}
public_deps = [
+ ":buildflags",
":resource_format_utils",
"//gpu/command_buffer/client",
"//gpu/command_buffer/common",
"//mojo/public/cpp/bindings",
"//skia",
]
+
if (enable_vulkan) {
public_deps += [ ":vulkan_context_provider" ]
}
diff --git a/chromium/components/viz/common/debugger/viz_debugger.gni b/chromium/components/viz/common/debugger/viz_debugger.gni
new file mode 100644
index 00000000000..2c9354ca08a
--- /dev/null
+++ b/chromium/components/viz/common/debugger/viz_debugger.gni
@@ -0,0 +1,10 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import("//components/ui_devtools/devtools.gni")
+
+declare_args() {
+ # Indicates if the Viz Debugger is enabled. This is disabled by default on
+ # official builds due to security and performance reasons.
+ use_viz_debugger = use_viz_devtools && !is_official_build
+}
diff --git a/chromium/components/viz/common/debugger/viz_debugger.pdl b/chromium/components/viz/common/debugger/viz_debugger.pdl
new file mode 100644
index 00000000000..b762f5d41f3
--- /dev/null
+++ b/chromium/components/viz/common/debugger/viz_debugger.pdl
@@ -0,0 +1,32 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+version
+ major 1
+ minor 0
+
+
+# The VisualDebugger domain defines methods and events for the Visual Debugger.
+domain VisualDebugger
+ # Sends filtering information to the visual debugging instance.
+ command filterStream
+ parameters
+ # This string contains filtering information for the debugging stream.
+ # See: //components/viz/service/debugger/README.md
+ object filter
+
+ # Starts communication stream for visual debugger.
+ command startStream
+ # Simply informs the visual debugger that debugging session has ended.
+ command stopStream
+
+ # Frame data is sent from the debugging instance with this event.
+ # This event will be emitted every render frame.
+ event frameResponse
+ parameters
+ # This Json dictionary object contains one full frame
+ # of visual debug submissions.
+ # See: //components/viz/service/debugger/README.md
+ object frameData
+
diff --git a/chromium/components/viz/common/display/renderer_settings.h b/chromium/components/viz/common/display/renderer_settings.h
index 2e32385af86..b7c9b29c088 100644
--- a/chromium/components/viz/common/display/renderer_settings.h
+++ b/chromium/components/viz/common/display/renderer_settings.h
@@ -23,6 +23,7 @@ class VIZ_COMMON_EXPORT RendererSettings {
RendererSettings(const RendererSettings& other);
~RendererSettings();
+ bool apply_simple_frame_rate_throttling = false;
bool allow_antialiasing = true;
bool force_antialiasing = false;
bool force_blending_with_shaders = false;
@@ -71,6 +72,7 @@ class VIZ_COMMON_EXPORT RendererSettings {
// HostFrameSinkManager.
struct VIZ_COMMON_EXPORT DebugRendererSettings {
bool tint_composited_content = false;
+ bool tint_composited_content_modulate = false;
bool show_overdraw_feedback = false;
bool show_dc_layer_debug_borders = false;
bool show_aggregated_damage = false;
diff --git a/chromium/components/viz/common/features.cc b/chromium/components/viz/common/features.cc
index 8e88ef0480b..9deaa7899cb 100644
--- a/chromium/components/viz/common/features.cc
+++ b/chromium/components/viz/common/features.cc
@@ -7,6 +7,7 @@
#include <string>
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/system/sys_info.h"
#include "build/chromeos_buildflags.h"
#include "components/viz/common/delegated_ink_prediction_configuration.h"
@@ -34,12 +35,17 @@ const base::Feature kEnableOverlayPrioritization {
#endif
};
+const base::Feature kSimpleFrameRateThrottling{
+ "SimpleFrameRateThrottling", base::FEATURE_DISABLED_BY_DEFAULT};
+
// Use the SkiaRenderer.
const base::Feature kUseSkiaRenderer {
"UseSkiaRenderer",
#if defined(OS_WIN) || defined(OS_ANDROID) || BUILDFLAG(IS_CHROMEOS_LACROS) || \
defined(OS_LINUX)
base::FEATURE_ENABLED_BY_DEFAULT
+#elif defined(OS_MAC)
+ base::FEATURE_ENABLED_BY_DEFAULT
#else
base::FEATURE_DISABLED_BY_DEFAULT
#endif
@@ -61,16 +67,6 @@ const base::Feature kDynamicColorGamut{"DynamicColorGamut",
const base::Feature kFastSolidColorDraw{"FastSolidColorDraw",
base::FEATURE_DISABLED_BY_DEFAULT};
-// Viz for WebView architecture.
-const base::Feature kVizForWebView{"VizForWebView",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-// We use this feature for default value, because enabled VizForWebView forces
-// skia renderer on and we want to have different feature state between webview
-// and chrome. This one is set by webview, while the above can be set via finch.
-const base::Feature kVizForWebViewDefault{"VizForWebViewDefault",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
// Submit CompositorFrame from SynchronousLayerTreeFrameSink directly to viz in
// WebView.
const base::Feature kVizFrameSubmissionForWebView{
@@ -99,7 +95,7 @@ const base::Feature kUseRealBuffersForPageFlipTest{
#if defined(OS_FUCHSIA)
// Enables SkiaOutputDeviceBufferQueue instead of Vulkan swapchain on Fuchsia.
const base::Feature kUseSkiaOutputDeviceBufferQueue{
- "UseSkiaOutputDeviceBufferQueue", base::FEATURE_DISABLED_BY_DEFAULT};
+ "UseSkiaOutputDeviceBufferQueue", base::FEATURE_ENABLED_BY_DEFAULT};
#endif
// Whether we should log extra debug information to webrtc native log.
@@ -122,7 +118,7 @@ const base::Feature kUseX11Present{"UseX11Present",
// Enables platform supported delegated ink trails instead of Skia backed
// delegated ink trails.
const base::Feature kUsePlatformDelegatedInk{"UsePlatformDelegatedInk",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Used to debug Android WebView Vulkan composite. Composite to an intermediate
// buffer and draw the intermediate buffer to the secondary command buffer.
@@ -154,6 +150,10 @@ bool IsSyncWindowDestructionEnabled() {
return base::FeatureList::IsEnabled(kSyncWindowDestruction);
}
+bool IsSimpleFrameRateThrottlingEnabled() {
+ return base::FeatureList::IsEnabled(kSimpleFrameRateThrottling);
+}
+
bool IsUsingSkiaRenderer() {
#if defined(OS_ANDROID)
// We don't support KitKat. Check for it before looking at the feature flag
@@ -163,10 +163,6 @@ bool IsUsingSkiaRenderer() {
return false;
#endif
- // Viz for webview requires SkiaRenderer.
- if (IsUsingVizForWebView())
- return true;
-
#if BUILDFLAG(IS_CHROMEOS_ASH)
// TODO(https://crbug.com/1145180): SkiaRenderer isn't supported on Chrome
// OS boards that still use the legacy video decoder.
@@ -195,28 +191,8 @@ bool IsUsingFastPathForSolidColorQuad() {
return base::FeatureList::IsEnabled(kFastSolidColorDraw);
}
-bool IsUsingVizForWebView() {
- // Vulkan on WebView requires viz.
- if (features::IsUsingVulkan())
- return true;
-
- // If the feature is overridden from command line or finch we will use this
- // value. If not we check for different state that is altered in
- // aw_main_delegate.cc.
- base::FeatureList* feature_list = base::FeatureList::GetInstance();
- if (feature_list && feature_list->IsFeatureOverridden(kVizForWebView.name))
- return base::FeatureList::IsEnabled(kVizForWebView);
-
- return base::FeatureList::IsEnabled(kVizForWebViewDefault);
-}
-
bool IsUsingVizFrameSubmissionForWebView() {
- if (base::FeatureList::IsEnabled(kVizFrameSubmissionForWebView)) {
- DCHECK(IsUsingVizForWebView())
- << "kVizFrameSubmissionForWebView requires kVizForWebView";
- return true;
- }
- return false;
+ return base::FeatureList::IsEnabled(kVizFrameSubmissionForWebView);
}
bool IsUsingPreferredIntervalForVideo() {
@@ -242,10 +218,10 @@ bool ShouldUseSetPresentDuration() {
}
#endif // OS_WIN
-base::Optional<int> ShouldDrawPredictedInkPoints() {
+absl::optional<int> ShouldDrawPredictedInkPoints() {
auto* command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(switches::kDrawPredictedInkPoint))
- return base::nullopt;
+ return absl::nullopt;
std::string predicted_points =
command_line->GetSwitchValueASCII(switches::kDrawPredictedInkPoint);
@@ -259,7 +235,7 @@ base::Optional<int> ShouldDrawPredictedInkPoints() {
return viz::PredictionConfig::k2Points3Ms;
NOTREACHED();
- return base::nullopt;
+ return absl::nullopt;
}
bool ShouldUsePlatformDelegatedInk() {
diff --git a/chromium/components/viz/common/features.h b/chromium/components/viz/common/features.h
index ca49cfd7f67..75adc3f42a0 100644
--- a/chromium/components/viz/common/features.h
+++ b/chromium/components/viz/common/features.h
@@ -7,10 +7,9 @@
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/viz/common/viz_common_export.h"
-
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace features {
@@ -23,7 +22,6 @@ VIZ_COMMON_EXPORT extern const base::Feature kDisableDeJelly;
VIZ_COMMON_EXPORT extern const base::Feature kDynamicColorGamut;
#endif
VIZ_COMMON_EXPORT extern const base::Feature kFastSolidColorDraw;
-VIZ_COMMON_EXPORT extern const base::Feature kVizForWebViewDefault;
VIZ_COMMON_EXPORT extern const base::Feature kVizFrameSubmissionForWebView;
VIZ_COMMON_EXPORT extern const base::Feature kUsePreferredIntervalForVideo;
VIZ_COMMON_EXPORT extern const base::Feature kUseRealBuffersForPageFlipTest;
@@ -44,6 +42,7 @@ VIZ_COMMON_EXPORT extern const base::Feature kUseSurfaceLayerForVideoDefault;
#endif
VIZ_COMMON_EXPORT bool IsAdpfEnabled();
+VIZ_COMMON_EXPORT bool IsSimpleFrameRateThrottlingEnabled();
#if defined(OS_ANDROID)
VIZ_COMMON_EXPORT bool IsDynamicColorGamutEnabled();
#endif
@@ -51,7 +50,6 @@ VIZ_COMMON_EXPORT bool IsOverlayPrioritizationEnabled();
VIZ_COMMON_EXPORT bool IsSyncWindowDestructionEnabled();
VIZ_COMMON_EXPORT bool IsUsingFastPathForSolidColorQuad();
VIZ_COMMON_EXPORT bool IsUsingSkiaRenderer();
-VIZ_COMMON_EXPORT bool IsUsingVizForWebView();
VIZ_COMMON_EXPORT bool IsUsingVizFrameSubmissionForWebView();
VIZ_COMMON_EXPORT bool IsUsingPreferredIntervalForVideo();
VIZ_COMMON_EXPORT bool IsVizHitTestingDebugEnabled();
@@ -60,7 +58,7 @@ VIZ_COMMON_EXPORT bool ShouldWebRtcLogCapturePipeline();
#if defined(OS_WIN)
VIZ_COMMON_EXPORT bool ShouldUseSetPresentDuration();
#endif // OS_WIN
-VIZ_COMMON_EXPORT base::Optional<int> ShouldDrawPredictedInkPoints();
+VIZ_COMMON_EXPORT absl::optional<int> ShouldDrawPredictedInkPoints();
VIZ_COMMON_EXPORT bool ShouldUsePlatformDelegatedInk();
#if defined(OS_ANDROID)
VIZ_COMMON_EXPORT bool UseSurfaceLayerForVideo();
diff --git a/chromium/components/viz/common/frame_sinks/begin_frame_args.h b/chromium/components/viz/common/frame_sinks/begin_frame_args.h
index 31252663fab..61481ff6e80 100644
--- a/chromium/components/viz/common/frame_sinks/begin_frame_args.h
+++ b/chromium/components/viz/common/frame_sinks/begin_frame_args.h
@@ -13,7 +13,6 @@
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
-#include "base/values.h"
#include "components/viz/common/viz_common_export.h"
namespace perfetto {
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 9c57f339779..76615163014 100644
--- a/chromium/components/viz/common/frame_sinks/begin_frame_source.cc
+++ b/chromium/components/viz/common/frame_sinks/begin_frame_source.cc
@@ -17,7 +17,6 @@
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#include "components/viz/common/frame_sinks/delay_based_time_source.h"
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 d420a12ec41..c05efdb42d1 100644
--- a/chromium/components/viz/common/frame_sinks/begin_frame_source.h
+++ b/chromium/components/viz/common/frame_sinks/begin_frame_source.h
@@ -9,12 +9,10 @@
#include <stdint.h>
#include <memory>
-#include <string>
#include "base/check.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
-#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/frame_sinks/delay_based_time_source.h"
diff --git a/chromium/components/viz/common/frame_sinks/copy_output_request.h b/chromium/components/viz/common/frame_sinks/copy_output_request.h
index a62fca68fd4..22d6576a9bd 100644
--- a/chromium/components/viz/common/frame_sinks/copy_output_request.h
+++ b/chromium/components/viz/common/frame_sinks/copy_output_request.h
@@ -8,15 +8,14 @@
#include <memory>
#include "base/callback.h"
-#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/unguessable_token.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/common/viz_common_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
@@ -131,9 +130,9 @@ class VIZ_COMMON_EXPORT CopyOutputRequest {
scoped_refptr<base::SequencedTaskRunner> result_task_runner_;
gfx::Vector2d scale_from_;
gfx::Vector2d scale_to_;
- base::Optional<base::UnguessableToken> source_;
- base::Optional<gfx::Rect> area_;
- base::Optional<gfx::Rect> result_selection_;
+ absl::optional<base::UnguessableToken> source_;
+ absl::optional<gfx::Rect> area_;
+ absl::optional<gfx::Rect> result_selection_;
DISALLOW_COPY_AND_ASSIGN(CopyOutputRequest);
};
diff --git a/chromium/components/viz/common/frame_sinks/copy_output_result.cc b/chromium/components/viz/common/frame_sinks/copy_output_result.cc
index 93149fc0217..2910ed82564 100644
--- a/chromium/components/viz/common/frame_sinks/copy_output_result.cc
+++ b/chromium/components/viz/common/frame_sinks/copy_output_result.cc
@@ -64,9 +64,8 @@ const CopyOutputResult::TextureResult* CopyOutputResult::GetTextureResult()
return nullptr;
}
-std::unique_ptr<SingleReleaseCallback>
-CopyOutputResult::TakeTextureOwnership() {
- return nullptr;
+ReleaseCallback CopyOutputResult::TakeTextureOwnership() {
+ return ReleaseCallback();
}
bool CopyOutputResult::ReadI420Planes(uint8_t* y_out,
@@ -177,7 +176,7 @@ CopyOutputTextureResult::CopyOutputTextureResult(
const gpu::Mailbox& mailbox,
const gpu::SyncToken& sync_token,
const gfx::ColorSpace& color_space,
- std::unique_ptr<SingleReleaseCallback> release_callback)
+ ReleaseCallback release_callback)
: CopyOutputResult(Format::RGBA_TEXTURE, rect, false),
texture_result_(mailbox, sync_token, color_space),
release_callback_(std::move(release_callback)) {
@@ -189,7 +188,7 @@ CopyOutputTextureResult::CopyOutputTextureResult(
CopyOutputTextureResult::~CopyOutputTextureResult() {
if (release_callback_)
- release_callback_->Run(gpu::SyncToken(), false);
+ std::move(release_callback_).Run(gpu::SyncToken(), false);
}
const CopyOutputResult::TextureResult*
@@ -197,8 +196,7 @@ CopyOutputTextureResult::GetTextureResult() const {
return &texture_result_;
}
-std::unique_ptr<SingleReleaseCallback>
-CopyOutputTextureResult::TakeTextureOwnership() {
+ReleaseCallback CopyOutputTextureResult::TakeTextureOwnership() {
texture_result_.mailbox = gpu::Mailbox();
texture_result_.sync_token = gpu::SyncToken();
texture_result_.color_space = gfx::ColorSpace();
diff --git a/chromium/components/viz/common/frame_sinks/copy_output_result.h b/chromium/components/viz/common/frame_sinks/copy_output_result.h
index 38c77b433a2..f21f3ebbdeb 100644
--- a/chromium/components/viz/common/frame_sinks/copy_output_result.h
+++ b/chromium/components/viz/common/frame_sinks/copy_output_result.h
@@ -5,11 +5,8 @@
#ifndef COMPONENTS_VIZ_COMMON_FRAME_SINKS_COPY_OUTPUT_RESULT_H_
#define COMPONENTS_VIZ_COMMON_FRAME_SINKS_COPY_OUTPUT_RESULT_H_
-#include <memory>
-#include <utility>
-
#include "base/threading/thread_checker.h"
-#include "components/viz/common/resources/single_release_callback.h"
+#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/viz_common_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
@@ -91,7 +88,7 @@ class VIZ_COMMON_EXPORT CopyOutputResult {
: mailbox(mailbox), sync_token(sync_token), color_space(color_space) {}
};
virtual const TextureResult* GetTextureResult() const;
- virtual std::unique_ptr<SingleReleaseCallback> TakeTextureOwnership();
+ virtual ReleaseCallback TakeTextureOwnership();
// Copies the image planes of an I420_PLANES result to the caller-provided
// memory. Returns true if successful, or false if: 1) this result is empty,
@@ -169,28 +166,27 @@ class VIZ_COMMON_EXPORT CopyOutputSkBitmapResult : public CopyOutputResult {
DISALLOW_COPY_AND_ASSIGN(CopyOutputSkBitmapResult);
};
-// Subclass of CopyOutputResult that holds a reference to a texture (via
-// a mailbox). The owner of the result must take ownership of the texture
-// if it wants to use it by calling TakeTextureOwnership(), and then call the
-// SingleReleaseCallback when the texture will no longer be used to release
-// ownership and allow the texture to be reused or destroyed. If ownership is
-// not claimed, it will be released when this class is destroyed.
+// Subclass of CopyOutputResult that holds a reference to a texture (via a
+// mailbox). The owner of the result must take ownership of the texture if it
+// wants to use it by calling TakeTextureOwnership(), and then call the
+// ReleaseCallback when the texture will no longer be used to release ownership
+// and allow the texture to be reused or destroyed. If ownership is not claimed,
+// it will be released when this class is destroyed.
class VIZ_COMMON_EXPORT CopyOutputTextureResult : public CopyOutputResult {
public:
- CopyOutputTextureResult(
- const gfx::Rect& rect,
- const gpu::Mailbox& mailbox,
- const gpu::SyncToken& sync_token,
- const gfx::ColorSpace& color_space,
- std::unique_ptr<SingleReleaseCallback> release_callback);
+ CopyOutputTextureResult(const gfx::Rect& rect,
+ const gpu::Mailbox& mailbox,
+ const gpu::SyncToken& sync_token,
+ const gfx::ColorSpace& color_space,
+ ReleaseCallback release_callback);
~CopyOutputTextureResult() override;
const TextureResult* GetTextureResult() const override;
- std::unique_ptr<SingleReleaseCallback> TakeTextureOwnership() override;
+ ReleaseCallback TakeTextureOwnership() override;
private:
TextureResult texture_result_;
- std::unique_ptr<SingleReleaseCallback> release_callback_;
+ ReleaseCallback release_callback_;
DISALLOW_COPY_AND_ASSIGN(CopyOutputTextureResult);
};
diff --git a/chromium/components/viz/common/frame_sinks/delay_based_time_source.cc b/chromium/components/viz/common/frame_sinks/delay_based_time_source.cc
index 8d9fd556842..891a3c912d1 100644
--- a/chromium/components/viz/common/frame_sinks/delay_based_time_source.cc
+++ b/chromium/components/viz/common/frame_sinks/delay_based_time_source.cc
@@ -27,8 +27,11 @@ DelayBasedTimeSource::DelayBasedTimeSource(
timebase_(base::TimeTicks()),
interval_(BeginFrameArgs::DefaultInterval()),
last_tick_time_(base::TimeTicks() - interval_),
- next_tick_time_(base::TimeTicks()),
- task_runner_(task_runner) {}
+ task_runner_(task_runner),
+ tick_closure_(base::BindRepeating(&DelayBasedTimeSource::OnTimerTick,
+ base::Unretained(this))) {
+ timer_.SetTaskRunner(task_runner_);
+}
DelayBasedTimeSource::~DelayBasedTimeSource() = default;
@@ -43,9 +46,9 @@ void DelayBasedTimeSource::SetActive(bool active) {
if (active_) {
PostNextTickTask(Now());
} else {
+ timer_.AbandonAndStop();
last_tick_time_ = base::TimeTicks();
next_tick_time_ = base::TimeTicks();
- tick_closure_.Cancel();
}
}
@@ -154,10 +157,7 @@ void DelayBasedTimeSource::PostNextTickTask(base::TimeTicks now) {
next_tick_time_ += interval_;
DCHECK_GT(next_tick_time_, now);
}
- tick_closure_.Reset(base::BindOnce(&DelayBasedTimeSource::OnTimerTick,
- weak_factory_.GetWeakPtr()));
- task_runner_->PostDelayedTask(FROM_HERE, tick_closure_.callback(),
- next_tick_time_ - now);
+ timer_.Start(FROM_HERE, next_tick_time_ - now, tick_closure_);
}
std::string DelayBasedTimeSource::TypeString() const {
diff --git a/chromium/components/viz/common/frame_sinks/delay_based_time_source.h b/chromium/components/viz/common/frame_sinks/delay_based_time_source.h
index f387bea5761..ba46acd59f8 100644
--- a/chromium/components/viz/common/frame_sinks/delay_based_time_source.h
+++ b/chromium/components/viz/common/frame_sinks/delay_based_time_source.h
@@ -10,8 +10,7 @@
#include "base/cancelable_callback.h"
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/values.h"
+#include "base/timer/timer.h"
#include "components/viz/common/viz_common_export.h"
namespace base {
@@ -76,11 +75,10 @@ class VIZ_COMMON_EXPORT DelayBasedTimeSource {
base::TimeTicks last_tick_time_;
base::TimeTicks next_tick_time_;
- base::CancelableOnceClosure tick_closure_;
-
base::SingleThreadTaskRunner* task_runner_;
- base::WeakPtrFactory<DelayBasedTimeSource> weak_factory_{this};
+ base::RepeatingClosure tick_closure_;
+ base::OneShotTimer timer_;
DISALLOW_COPY_AND_ASSIGN(DelayBasedTimeSource);
};
diff --git a/chromium/components/viz/common/gl_scaler.h b/chromium/components/viz/common/gl_scaler.h
index 7b7b3199163..8daab47a3bc 100644
--- a/chromium/components/viz/common/gl_scaler.h
+++ b/chromium/components/viz/common/gl_scaler.h
@@ -18,10 +18,10 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "components/viz/common/gpu/context_lost_observer.h"
#include "components/viz/common/viz_common_export.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -481,7 +481,7 @@ class VIZ_COMMON_EXPORT GLScaler final : public ContextLostObserver {
// If set to true, half-float textures are supported. This is lazy-initialized
// by SupportsPreciseColorManagement().
- mutable base::Optional<bool> supports_half_floats_;
+ mutable absl::optional<bool> supports_half_floats_;
// The maximum number of simultaneous draw buffers, lazy-initialized by
// GetMaxDrawBuffersSupported(). -1 means "not yet known."
diff --git a/chromium/components/viz/common/gpu/dawn_context_provider.cc b/chromium/components/viz/common/gpu/dawn_context_provider.cc
index 2e54f916585..d4004c125e9 100644
--- a/chromium/components/viz/common/gpu/dawn_context_provider.cc
+++ b/chromium/components/viz/common/gpu/dawn_context_provider.cc
@@ -38,7 +38,7 @@ std::unique_ptr<DawnContextProvider> DawnContextProvider::Create() {
}
DawnContextProvider::DawnContextProvider() {
- // TODO(sgilhuly): This may return a GPU that is not the active one. Currently
+ // TODO(rivr): This may return a GPU that is not the active one. Currently
// the only known way to avoid this is platform-specific; e.g. on Mac, create
// a Dawn device, get the actual Metal device from it, and compare against
// MTLCreateSystemDefaultDevice().
diff --git a/chromium/components/viz/common/gpu/vulkan_context_provider.h b/chromium/components/viz/common/gpu/vulkan_context_provider.h
index fcf86efb16d..dfe85d6206d 100644
--- a/chromium/components/viz/common/gpu/vulkan_context_provider.h
+++ b/chromium/components/viz/common/gpu/vulkan_context_provider.h
@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h"
#include "components/viz/common/viz_vulkan_context_provider_export.h"
#include "gpu/vulkan/buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if BUILDFLAG(ENABLE_VULKAN)
#include <vulkan/vulkan.h>
@@ -53,7 +54,7 @@ class VIZ_VULKAN_CONTEXT_PROVIDER_EXPORT VulkanContextProvider
// memory immediately. In other words, the CPU will wait for GPU work to
// complete before proceeding when the current amount of allocated memory
// exceeds this limit.
- virtual base::Optional<uint32_t> GetSyncCpuMemoryLimit() const = 0;
+ virtual absl::optional<uint32_t> GetSyncCpuMemoryLimit() const = 0;
protected:
friend class base::RefCountedThreadSafe<VulkanContextProvider>;
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 70b96882a3c..62927dd2124 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
@@ -134,9 +134,7 @@ bool VulkanInProcessContextProvider::InitializeGrContext(
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;
+ backend_context.fProtectedContext = GrProtected::kNo;
gr_context_ = GrDirectContext::MakeVulkan(backend_context, context_options);
@@ -192,15 +190,15 @@ void VulkanInProcessContextProvider::EnqueueSecondaryCBPostSubmitTask(
NOTREACHED();
}
-base::Optional<uint32_t> VulkanInProcessContextProvider::GetSyncCpuMemoryLimit()
+absl::optional<uint32_t> VulkanInProcessContextProvider::GetSyncCpuMemoryLimit()
const {
// Return false to indicate that there's no limit.
if (!sync_cpu_memory_limit_)
- return base::Optional<uint32_t>();
+ return absl::optional<uint32_t>();
return base::TimeTicks::Now() < critical_memory_pressure_expiration_time_
- ? base::Optional<uint32_t>(
+ ? absl::optional<uint32_t>(
kSyncCpuMemoryLimitAtMemoryPressureCritical)
- : base::Optional<uint32_t>(sync_cpu_memory_limit_);
+ : absl::optional<uint32_t>(sync_cpu_memory_limit_);
}
void VulkanInProcessContextProvider::OnMemoryPressure(
diff --git a/chromium/components/viz/common/gpu/vulkan_in_process_context_provider.h b/chromium/components/viz/common/gpu/vulkan_in_process_context_provider.h
index 971b25823cc..d1d13fdaef5 100644
--- a/chromium/components/viz/common/gpu/vulkan_in_process_context_provider.h
+++ b/chromium/components/viz/common/gpu/vulkan_in_process_context_provider.h
@@ -53,7 +53,7 @@ class VIZ_VULKAN_CONTEXT_PROVIDER_EXPORT VulkanInProcessContextProvider
void EnqueueSecondaryCBSemaphores(
std::vector<VkSemaphore> semaphores) override;
void EnqueueSecondaryCBPostSubmitTask(base::OnceClosure closure) override;
- base::Optional<uint32_t> GetSyncCpuMemoryLimit() const override;
+ absl::optional<uint32_t> GetSyncCpuMemoryLimit() const override;
private:
friend class VulkanInProcessContextProviderTest;
diff --git a/chromium/components/viz/common/quads/aggregated_render_pass.cc b/chromium/components/viz/common/quads/aggregated_render_pass.cc
index 7a05d537e33..2a78bfbe3b4 100644
--- a/chromium/components/viz/common/quads/aggregated_render_pass.cc
+++ b/chromium/components/viz/common/quads/aggregated_render_pass.cc
@@ -58,7 +58,7 @@ void AggregatedRenderPass::SetAll(
const gfx::Transform& transform_to_root_target,
const cc::FilterOperations& filters,
const cc::FilterOperations& backdrop_filters,
- const base::Optional<gfx::RRectF>& backdrop_filter_bounds,
+ const absl::optional<gfx::RRectF>& backdrop_filter_bounds,
gfx::ContentColorUsage content_color_usage,
bool has_transparent_background,
bool cache_render_pass,
diff --git a/chromium/components/viz/common/quads/aggregated_render_pass.h b/chromium/components/viz/common/quads/aggregated_render_pass.h
index a2b0cd51c8e..b93f63bf118 100644
--- a/chromium/components/viz/common/quads/aggregated_render_pass.h
+++ b/chromium/components/viz/common/quads/aggregated_render_pass.h
@@ -56,7 +56,7 @@ class VIZ_COMMON_EXPORT AggregatedRenderPass : public RenderPassInternal {
const gfx::Transform& transform_to_root_target,
const cc::FilterOperations& filters,
const cc::FilterOperations& backdrop_filters,
- const base::Optional<gfx::RRectF>& backdrop_filter_bounds,
+ const absl::optional<gfx::RRectF>& backdrop_filter_bounds,
gfx::ContentColorUsage content_color_usage,
bool has_transparent_background,
bool cache_render_pass,
diff --git a/chromium/components/viz/common/quads/aggregated_render_pass_draw_quad.h b/chromium/components/viz/common/quads/aggregated_render_pass_draw_quad.h
index 0bb190108da..04f2ecb2cb1 100644
--- a/chromium/components/viz/common/quads/aggregated_render_pass_draw_quad.h
+++ b/chromium/components/viz/common/quads/aggregated_render_pass_draw_quad.h
@@ -7,8 +7,6 @@
#include <stddef.h>
-#include <memory>
-
#include "cc/paint/filter_operations.h"
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/common/quads/draw_quad.h"
diff --git a/chromium/components/viz/common/quads/compositor_frame_metadata.h b/chromium/components/viz/common/quads/compositor_frame_metadata.h
index cf503f40e2d..823c6c35614 100644
--- a/chromium/components/viz/common/quads/compositor_frame_metadata.h
+++ b/chromium/components/viz/common/quads/compositor_frame_metadata.h
@@ -10,7 +10,6 @@
#include <memory>
#include <vector>
-#include "base/optional.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
@@ -19,6 +18,7 @@
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/common/surfaces/surface_range.h"
#include "components/viz/common/viz_common_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/delegated_ink_metadata.h"
#include "ui/gfx/display_color_spaces.h"
@@ -144,9 +144,9 @@ class VIZ_COMMON_EXPORT CompositorFrameMetadata {
// The visible height of the top-controls. If the value is not set, then the
// visible height should be the same as in the latest submitted frame with a
// value set.
- base::Optional<float> top_controls_visible_height;
+ absl::optional<float> top_controls_visible_height;
- base::Optional<base::TimeDelta> preferred_frame_interval;
+ absl::optional<base::TimeDelta> preferred_frame_interval;
// Display transform hint when the frame is generated. Note this is only
// applicable to frames of the root surface.
diff --git a/chromium/components/viz/common/quads/compositor_frame_metadata_unittest.cc b/chromium/components/viz/common/quads/compositor_frame_metadata_unittest.cc
index 54be1074f39..2ae5adf3729 100644
--- a/chromium/components/viz/common/quads/compositor_frame_metadata_unittest.cc
+++ b/chromium/components/viz/common/quads/compositor_frame_metadata_unittest.cc
@@ -4,7 +4,6 @@
#include "components/viz/common/quads/compositor_frame_metadata.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
@@ -14,6 +13,7 @@
#include "components/viz/common/surfaces/surface_range.h"
#include "components/viz/common/viz_common_export.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/delegated_ink_metadata.h"
#include "ui/gfx/display_color_spaces.h"
diff --git a/chromium/components/viz/common/quads/compositor_frame_transition_directive.h b/chromium/components/viz/common/quads/compositor_frame_transition_directive.h
index 89973893418..0bc722586b4 100644
--- a/chromium/components/viz/common/quads/compositor_frame_transition_directive.h
+++ b/chromium/components/viz/common/quads/compositor_frame_transition_directive.h
@@ -72,7 +72,7 @@ class VIZ_COMMON_EXPORT CompositorFrameTransitionDirective {
Effect effect() const { return effect_; }
// Shared element render passes.
- const std::vector<CompositorRenderPassId> shared_render_pass_ids() const {
+ const std::vector<CompositorRenderPassId>& shared_render_pass_ids() const {
return shared_render_pass_ids_;
}
diff --git a/chromium/components/viz/common/quads/compositor_render_pass.cc b/chromium/components/viz/common/quads/compositor_render_pass.cc
index 96c65f30afa..62760054b32 100644
--- a/chromium/components/viz/common/quads/compositor_render_pass.cc
+++ b/chromium/components/viz/common/quads/compositor_render_pass.cc
@@ -87,7 +87,7 @@ void CompositorRenderPass::SetAll(
const gfx::Transform& transform_to_root_target,
const cc::FilterOperations& filters,
const cc::FilterOperations& backdrop_filters,
- const base::Optional<gfx::RRectF>& backdrop_filter_bounds,
+ const absl::optional<gfx::RRectF>& backdrop_filter_bounds,
SubtreeCaptureId subtree_capture_id,
bool has_transparent_background,
bool cache_render_pass,
diff --git a/chromium/components/viz/common/quads/compositor_render_pass.h b/chromium/components/viz/common/quads/compositor_render_pass.h
index ca96b4c8145..2bef30328f0 100644
--- a/chromium/components/viz/common/quads/compositor_render_pass.h
+++ b/chromium/components/viz/common/quads/compositor_render_pass.h
@@ -67,7 +67,7 @@ class VIZ_COMMON_EXPORT CompositorRenderPass : public RenderPassInternal {
const gfx::Transform& transform_to_root_target,
const cc::FilterOperations& filters,
const cc::FilterOperations& backdrop_filters,
- const base::Optional<gfx::RRectF>& backdrop_filter_bounds,
+ const absl::optional<gfx::RRectF>& backdrop_filter_bounds,
SubtreeCaptureId subtree_capture_id,
bool has_transparent_background,
bool cache_render_pass,
diff --git a/chromium/components/viz/common/quads/compositor_render_pass_draw_quad.h b/chromium/components/viz/common/quads/compositor_render_pass_draw_quad.h
index cd0684704ad..7d58672d8c9 100644
--- a/chromium/components/viz/common/quads/compositor_render_pass_draw_quad.h
+++ b/chromium/components/viz/common/quads/compositor_render_pass_draw_quad.h
@@ -7,8 +7,6 @@
#include <stddef.h>
-#include <memory>
-
#include "cc/paint/filter_operations.h"
#include "components/viz/common/quads/compositor_render_pass.h"
#include "components/viz/common/quads/draw_quad.h"
diff --git a/chromium/components/viz/common/quads/compositor_render_pass_unittest.cc b/chromium/components/viz/common/quads/compositor_render_pass_unittest.cc
index 0b83d642547..917c2e5d2c1 100644
--- a/chromium/components/viz/common/quads/compositor_render_pass_unittest.cc
+++ b/chromium/components/viz/common/quads/compositor_render_pass_unittest.cc
@@ -67,7 +67,7 @@ TEST(CompositorRenderPassTest,
filters.Append(cc::FilterOperation::CreateOpacityFilter(0.5));
cc::FilterOperations backdrop_filters;
backdrop_filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
- base::Optional<gfx::RRectF> backdrop_filter_bounds(
+ absl::optional<gfx::RRectF> backdrop_filter_bounds(
{10, 20, 130, 140, 1, 2, 3, 4, 5, 6, 7, 8});
gfx::ContentColorUsage content_color_usage = gfx::ContentColorUsage::kHDR;
bool has_transparent_background = true;
@@ -86,7 +86,7 @@ TEST(CompositorRenderPassTest,
// Stick a quad in the pass, this should not get copied.
SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(), gfx::Rect(), gfx::Rect(),
- gfx::MaskFilterInfo(), gfx::Rect(), false, false, 1,
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1,
SkBlendMode::kSrcOver, 0);
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -129,7 +129,7 @@ TEST(CompositorRenderPassTest, CopyAllShouldBeIdentical) {
filters.Append(cc::FilterOperation::CreateOpacityFilter(0.5));
cc::FilterOperations backdrop_filters;
backdrop_filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
- base::Optional<gfx::RRectF> backdrop_filter_bounds(
+ absl::optional<gfx::RRectF> backdrop_filter_bounds(
{10, 20, 130, 140, 1, 2, 3, 4, 5, 6, 7, 8});
bool has_transparent_background = true;
bool cache_render_pass = false;
@@ -145,7 +145,7 @@ TEST(CompositorRenderPassTest, CopyAllShouldBeIdentical) {
// Two quads using one shared state.
SharedQuadState* shared_state1 = pass->CreateAndAppendSharedQuadState();
shared_state1->SetAll(gfx::Transform(), gfx::Rect(0, 0, 1, 1), gfx::Rect(),
- gfx::MaskFilterInfo(), gfx::Rect(), false, false, 1,
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1,
SkBlendMode::kSrcOver, 0);
auto* color_quad1 = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -161,7 +161,7 @@ TEST(CompositorRenderPassTest, CopyAllShouldBeIdentical) {
// And two quads using another shared state.
SharedQuadState* shared_state2 = pass->CreateAndAppendSharedQuadState();
shared_state2->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
- gfx::MaskFilterInfo(), gfx::Rect(), false, false, 1,
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1,
SkBlendMode::kSrcOver, 0);
auto* color_quad3 = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -184,7 +184,7 @@ TEST(CompositorRenderPassTest, CopyAllShouldBeIdentical) {
contrib_filters.Append(cc::FilterOperation::CreateSepiaFilter(0.5));
cc::FilterOperations contrib_backdrop_filters;
contrib_backdrop_filters.Append(cc::FilterOperation::CreateSaturateFilter(1));
- base::Optional<gfx::RRectF> contrib_backdrop_filter_bounds(
+ absl::optional<gfx::RRectF> contrib_backdrop_filter_bounds(
{20, 30, 140, 150, 1, 2, 3, 4, 5, 6, 7, 8});
bool contrib_has_transparent_background = true;
bool contrib_cache_render_pass = false;
@@ -201,9 +201,9 @@ TEST(CompositorRenderPassTest, CopyAllShouldBeIdentical) {
SharedQuadState* contrib_shared_state =
contrib->CreateAndAppendSharedQuadState();
- contrib_shared_state->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2),
- gfx::Rect(), gfx::MaskFilterInfo(), gfx::Rect(),
- false, false, 1, SkBlendMode::kSrcOver, 0);
+ contrib_shared_state->SetAll(
+ gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1, SkBlendMode::kSrcOver, 0);
auto* contrib_quad = contrib->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
contrib_quad->SetNew(contrib->shared_quad_state_list.back(),
@@ -239,7 +239,7 @@ TEST(CompositorRenderPassTest, CopyAllWithCulledQuads) {
filters.Append(cc::FilterOperation::CreateOpacityFilter(0.5));
cc::FilterOperations backdrop_filters;
backdrop_filters.Append(cc::FilterOperation::CreateInvertFilter(1.0));
- base::Optional<gfx::RRectF> backdrop_filter_bounds(
+ absl::optional<gfx::RRectF> backdrop_filter_bounds(
{10, 20, 130, 140, 1, 2, 3, 4, 5, 6, 7, 8});
bool has_transparent_background = true;
bool cache_render_pass = false;
@@ -255,7 +255,7 @@ TEST(CompositorRenderPassTest, CopyAllWithCulledQuads) {
// A shared state with a quad.
SharedQuadState* shared_state1 = pass->CreateAndAppendSharedQuadState();
shared_state1->SetAll(gfx::Transform(), gfx::Rect(0, 0, 1, 1), gfx::Rect(),
- gfx::MaskFilterInfo(), gfx::Rect(), false, false, 1,
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1,
SkBlendMode::kSrcOver, 0);
auto* color_quad1 = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -266,19 +266,19 @@ TEST(CompositorRenderPassTest, CopyAllWithCulledQuads) {
// A shared state with no quads, they were culled.
SharedQuadState* shared_state2 = pass->CreateAndAppendSharedQuadState();
shared_state2->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
- gfx::MaskFilterInfo(), gfx::Rect(), false, false, 1,
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1,
SkBlendMode::kSrcOver, 0);
// A second shared state with no quads.
SharedQuadState* shared_state3 = pass->CreateAndAppendSharedQuadState();
shared_state3->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
- gfx::MaskFilterInfo(), gfx::Rect(), false, false, 1,
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1,
SkBlendMode::kSrcOver, 0);
// A last shared state with a quad again.
SharedQuadState* shared_state4 = pass->CreateAndAppendSharedQuadState();
shared_state4->SetAll(gfx::Transform(), gfx::Rect(0, 0, 2, 2), gfx::Rect(),
- gfx::MaskFilterInfo(), gfx::Rect(), false, false, 1,
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1,
SkBlendMode::kSrcOver, 0);
auto* color_quad2 = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
diff --git a/chromium/components/viz/common/quads/content_draw_quad_base.h b/chromium/components/viz/common/quads/content_draw_quad_base.h
index a1066f1ea97..00bdee4d74b 100644
--- a/chromium/components/viz/common/quads/content_draw_quad_base.h
+++ b/chromium/components/viz/common/quads/content_draw_quad_base.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_VIZ_COMMON_QUADS_CONTENT_DRAW_QUAD_BASE_H_
#define COMPONENTS_VIZ_COMMON_QUADS_CONTENT_DRAW_QUAD_BASE_H_
-#include <memory>
-
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/viz_common_export.h"
#include "ui/gfx/geometry/rect_f.h"
diff --git a/chromium/components/viz/common/quads/debug_border_draw_quad.h b/chromium/components/viz/common/quads/debug_border_draw_quad.h
index e01b87fc2c1..5444863cbf4 100644
--- a/chromium/components/viz/common/quads/debug_border_draw_quad.h
+++ b/chromium/components/viz/common/quads/debug_border_draw_quad.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_VIZ_COMMON_QUADS_DEBUG_BORDER_DRAW_QUAD_H_
#define COMPONENTS_VIZ_COMMON_QUADS_DEBUG_BORDER_DRAW_QUAD_H_
-#include <memory>
-
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/viz_common_export.h"
#include "third_party/skia/include/core/SkColor.h"
diff --git a/chromium/components/viz/common/quads/draw_quad_perftest.cc b/chromium/components/viz/common/quads/draw_quad_perftest.cc
index 6b178ea3d38..d64d2d1c3c2 100644
--- a/chromium/components/viz/common/quads/draw_quad_perftest.cc
+++ b/chromium/components/viz/common/quads/draw_quad_perftest.cc
@@ -38,8 +38,6 @@ SharedQuadState* CreateSharedQuadState(CompositorRenderPass* render_pass) {
gfx::Transform quad_transform = gfx::Transform(1.0, 0.0, 0.5, 1.0, 0.5, 0.0);
gfx::Rect content_rect(26, 28);
gfx::Rect visible_layer_rect(10, 12, 14, 16);
- gfx::Rect clip_rect(19, 21, 23, 25);
- bool is_clipped = false;
bool are_contents_opaque = false;
float opacity = 1.f;
int sorting_context_id = 65536;
@@ -47,7 +45,7 @@ SharedQuadState* CreateSharedQuadState(CompositorRenderPass* render_pass) {
SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState();
state->SetAll(quad_transform, content_rect, visible_layer_rect,
- gfx::MaskFilterInfo(), clip_rect, is_clipped,
+ gfx::MaskFilterInfo(), /*clip_rect=*/absl::nullopt,
are_contents_opaque, opacity, blend_mode, sorting_context_id);
return state;
}
diff --git a/chromium/components/viz/common/quads/draw_quad_unittest.cc b/chromium/components/viz/common/quads/draw_quad_unittest.cc
index f32b57e94e1..e3d9d86df9c 100644
--- a/chromium/components/viz/common/quads/draw_quad_unittest.cc
+++ b/chromium/components/viz/common/quads/draw_quad_unittest.cc
@@ -49,7 +49,6 @@ TEST(DrawQuadTest, CopySharedQuadState) {
gfx::Rect layer_rect(26, 28);
gfx::Rect visible_layer_rect(10, 12, 14, 16);
gfx::Rect clip_rect(19, 21, 23, 25);
- bool is_clipped = true;
bool are_contents_opaque = true;
float opacity = 0.25f;
SkBlendMode blend_mode = SkBlendMode::kMultiply;
@@ -57,15 +56,14 @@ TEST(DrawQuadTest, CopySharedQuadState) {
auto state = std::make_unique<SharedQuadState>();
state->SetAll(quad_transform, layer_rect, visible_layer_rect,
- gfx::MaskFilterInfo(), clip_rect, is_clipped,
- are_contents_opaque, opacity, blend_mode, sorting_context_id);
+ gfx::MaskFilterInfo(), clip_rect, are_contents_opaque, opacity,
+ blend_mode, sorting_context_id);
auto copy = std::make_unique<SharedQuadState>(*state);
EXPECT_EQ(quad_transform, copy->quad_to_target_transform);
EXPECT_EQ(visible_layer_rect, copy->visible_quad_layer_rect);
EXPECT_EQ(opacity, copy->opacity);
EXPECT_EQ(clip_rect, copy->clip_rect);
- EXPECT_EQ(is_clipped, copy->is_clipped);
EXPECT_EQ(are_contents_opaque, copy->are_contents_opaque);
EXPECT_EQ(blend_mode, copy->blend_mode);
}
@@ -74,8 +72,6 @@ SharedQuadState* CreateSharedQuadState(CompositorRenderPass* render_pass) {
gfx::Transform quad_transform = gfx::Transform(1.0, 0.0, 0.5, 1.0, 0.5, 0.0);
gfx::Rect layer_rect(26, 28);
gfx::Rect visible_layer_rect(10, 12, 14, 16);
- gfx::Rect clip_rect(19, 21, 23, 25);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
int sorting_context_id = 65536;
@@ -83,8 +79,8 @@ SharedQuadState* CreateSharedQuadState(CompositorRenderPass* render_pass) {
SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState();
state->SetAll(quad_transform, layer_rect, visible_layer_rect,
- gfx::MaskFilterInfo(), clip_rect, is_clipped,
- are_contents_opaque, opacity, blend_mode, sorting_context_id);
+ gfx::MaskFilterInfo(), absl::nullopt, are_contents_opaque,
+ opacity, blend_mode, sorting_context_id);
return state;
}
@@ -96,7 +92,6 @@ void CompareSharedQuadState(const SharedQuadState* source_sqs,
EXPECT_EQ(source_sqs->visible_quad_layer_rect,
copy_sqs->visible_quad_layer_rect);
EXPECT_EQ(source_sqs->clip_rect, copy_sqs->clip_rect);
- EXPECT_EQ(source_sqs->is_clipped, copy_sqs->is_clipped);
EXPECT_EQ(source_sqs->opacity, copy_sqs->opacity);
EXPECT_EQ(source_sqs->blend_mode, copy_sqs->blend_mode);
EXPECT_EQ(source_sqs->sorting_context_id, copy_sqs->sorting_context_id);
@@ -606,7 +601,7 @@ TEST_F(DrawQuadIteratorTest, SurfaceDrawQuad) {
CREATE_SHARED_STATE();
CREATE_QUAD_NEW(SurfaceDrawQuad, visible_rect,
- SurfaceRange(base::nullopt, surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, surface_id), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
EXPECT_EQ(0, IterateAndCount(quad_new));
}
diff --git a/chromium/components/viz/common/quads/frame_deadline.cc b/chromium/components/viz/common/quads/frame_deadline.cc
index 4af2eb08a9e..b12f53b12df 100644
--- a/chromium/components/viz/common/quads/frame_deadline.cc
+++ b/chromium/components/viz/common/quads/frame_deadline.cc
@@ -17,7 +17,7 @@ FrameDeadline FrameDeadline::MakeZero() {
}
base::TimeTicks FrameDeadline::ToWallTime(
- base::Optional<uint32_t> default_deadline_in_frames) const {
+ absl::optional<uint32_t> default_deadline_in_frames) const {
uint32_t deadline_in_frames = deadline_in_frames_;
if (use_default_lower_bound_deadline_) {
deadline_in_frames =
diff --git a/chromium/components/viz/common/quads/frame_deadline.h b/chromium/components/viz/common/quads/frame_deadline.h
index e980980dcc5..b32aa0c7ef1 100644
--- a/chromium/components/viz/common/quads/frame_deadline.h
+++ b/chromium/components/viz/common/quads/frame_deadline.h
@@ -5,10 +5,12 @@
#ifndef COMPONENTS_VIZ_COMMON_QUADS_FRAME_DEADLINE_H_
#define COMPONENTS_VIZ_COMMON_QUADS_FRAME_DEADLINE_H_
-#include "components/viz/common/viz_common_export.h"
+#include <string>
#include "base/time/time.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/viz_common_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace viz {
@@ -43,8 +45,8 @@ class VIZ_COMMON_EXPORT FrameDeadline {
// Converts this FrameDeadline object into a wall time given a system default
// deadline in frames.
base::TimeTicks ToWallTime(
- base::Optional<uint32_t> default_deadline_in_frames =
- base::nullopt) const;
+ absl::optional<uint32_t> default_deadline_in_frames =
+ absl::nullopt) const;
bool operator==(const FrameDeadline& other) const {
return other.frame_start_time_ == frame_start_time_ &&
diff --git a/chromium/components/viz/common/quads/picture_draw_quad.h b/chromium/components/viz/common/quads/picture_draw_quad.h
index 0341d72a9e5..58f716a9b16 100644
--- a/chromium/components/viz/common/quads/picture_draw_quad.h
+++ b/chromium/components/viz/common/quads/picture_draw_quad.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_VIZ_COMMON_QUADS_PICTURE_DRAW_QUAD_H_
#define COMPONENTS_VIZ_COMMON_QUADS_PICTURE_DRAW_QUAD_H_
-#include <memory>
-
#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "cc/paint/display_item_list.h"
diff --git a/chromium/components/viz/common/quads/render_pass_draw_quad_internal.h b/chromium/components/viz/common/quads/render_pass_draw_quad_internal.h
index 5e86ae48340..020f9fe7226 100644
--- a/chromium/components/viz/common/quads/render_pass_draw_quad_internal.h
+++ b/chromium/components/viz/common/quads/render_pass_draw_quad_internal.h
@@ -7,8 +7,6 @@
#include <stddef.h>
-#include <memory>
-
#include "cc/paint/filter_operations.h"
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/viz_common_export.h"
diff --git a/chromium/components/viz/common/quads/render_pass_internal.h b/chromium/components/viz/common/quads/render_pass_internal.h
index 9165c5c483e..c6d059629ba 100644
--- a/chromium/components/viz/common/quads/render_pass_internal.h
+++ b/chromium/components/viz/common/quads/render_pass_internal.h
@@ -10,10 +10,10 @@
#include <memory>
#include <vector>
-#include "base/optional.h"
#include "cc/paint/filter_operations.h"
#include "components/viz/common/quads/quad_list.h"
#include "components/viz/common/viz_common_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/display_color_spaces.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/rrect_f.h"
@@ -52,7 +52,7 @@ class VIZ_COMMON_EXPORT RenderPassInternal {
cc::FilterOperations backdrop_filters;
// Clipping bounds for backdrop filter.
- base::Optional<gfx::RRectF> backdrop_filter_bounds;
+ absl::optional<gfx::RRectF> backdrop_filter_bounds;
// If false, the pixels in the render pass' texture are all opaque.
bool has_transparent_background = true;
diff --git a/chromium/components/viz/common/quads/render_pass_io.cc b/chromium/components/viz/common/quads/render_pass_io.cc
index 33b7519d715..80ab3245b23 100644
--- a/chromium/components/viz/common/quads/render_pass_io.cc
+++ b/chromium/components/viz/common/quads/render_pass_io.cc
@@ -76,10 +76,10 @@ bool RectFromDict(const base::Value& dict, gfx::Rect* rect) {
DCHECK(rect);
if (!dict.is_dict())
return false;
- base::Optional<int> x = dict.FindIntKey("x");
- base::Optional<int> y = dict.FindIntKey("y");
- base::Optional<int> width = dict.FindIntKey("width");
- base::Optional<int> height = dict.FindIntKey("height");
+ absl::optional<int> x = dict.FindIntKey("x");
+ absl::optional<int> y = dict.FindIntKey("y");
+ absl::optional<int> width = dict.FindIntKey("width");
+ absl::optional<int> height = dict.FindIntKey("height");
if (!x || !y || !width || !height) {
return false;
}
@@ -100,10 +100,10 @@ bool RectFFromDict(const base::Value& dict, gfx::RectF* rect) {
DCHECK(rect);
if (!dict.is_dict())
return false;
- base::Optional<double> x = dict.FindDoubleKey("x");
- base::Optional<double> y = dict.FindDoubleKey("y");
- base::Optional<double> width = dict.FindDoubleKey("width");
- base::Optional<double> height = dict.FindDoubleKey("height");
+ absl::optional<double> x = dict.FindDoubleKey("x");
+ absl::optional<double> y = dict.FindDoubleKey("y");
+ absl::optional<double> width = dict.FindDoubleKey("width");
+ absl::optional<double> height = dict.FindDoubleKey("height");
if (!x || !y || !width || !height) {
return false;
}
@@ -124,8 +124,8 @@ bool SizeFromDict(const base::Value& dict, gfx::Size* size) {
DCHECK(size);
if (!dict.is_dict())
return false;
- base::Optional<int> width = dict.FindIntKey("width");
- base::Optional<int> height = dict.FindIntKey("height");
+ absl::optional<int> width = dict.FindIntKey("width");
+ absl::optional<int> height = dict.FindIntKey("height");
if (!width || !height) {
return false;
}
@@ -145,8 +145,8 @@ bool PointFromDict(const base::Value& dict, gfx::Point* point) {
DCHECK(point);
if (!dict.is_dict())
return false;
- base::Optional<int> x = dict.FindIntKey("x");
- base::Optional<int> y = dict.FindIntKey("y");
+ absl::optional<int> x = dict.FindIntKey("x");
+ absl::optional<int> y = dict.FindIntKey("y");
if (!x || !y) {
return false;
}
@@ -166,8 +166,8 @@ bool PointFFromDict(const base::Value& dict, gfx::PointF* point) {
DCHECK(point);
if (!dict.is_dict())
return false;
- base::Optional<double> x = dict.FindDoubleKey("x");
- base::Optional<double> y = dict.FindDoubleKey("y");
+ absl::optional<double> x = dict.FindDoubleKey("x");
+ absl::optional<double> y = dict.FindDoubleKey("y");
if (!x || !y) {
return false;
}
@@ -296,14 +296,14 @@ bool RRectFFromDict(const base::Value& dict, gfx::RRectF* out) {
return true;
}
const base::Value* rect = dict.FindDictKey("rect");
- base::Optional<double> upper_left_x = dict.FindDoubleKey("upper_left.x");
- base::Optional<double> upper_left_y = dict.FindDoubleKey("upper_left.y");
- base::Optional<double> upper_right_x = dict.FindDoubleKey("upper_right.x");
- base::Optional<double> upper_right_y = dict.FindDoubleKey("upper_right.y");
- base::Optional<double> lower_right_x = dict.FindDoubleKey("lower_right.x");
- base::Optional<double> lower_right_y = dict.FindDoubleKey("lower_right.y");
- base::Optional<double> lower_left_x = dict.FindDoubleKey("lower_left.x");
- base::Optional<double> lower_left_y = dict.FindDoubleKey("lower_left.y");
+ absl::optional<double> upper_left_x = dict.FindDoubleKey("upper_left.x");
+ absl::optional<double> upper_left_y = dict.FindDoubleKey("upper_left.y");
+ absl::optional<double> upper_right_x = dict.FindDoubleKey("upper_right.x");
+ absl::optional<double> upper_right_y = dict.FindDoubleKey("upper_right.y");
+ absl::optional<double> lower_right_x = dict.FindDoubleKey("lower_right.x");
+ absl::optional<double> lower_right_y = dict.FindDoubleKey("lower_right.y");
+ absl::optional<double> lower_left_x = dict.FindDoubleKey("lower_left.x");
+ absl::optional<double> lower_left_y = dict.FindDoubleKey("lower_left.y");
if (!rect || !upper_left_x || !upper_left_y || !upper_right_x ||
!upper_right_y || !lower_right_x || !lower_right_y || !lower_left_x ||
!lower_left_y) {
@@ -383,12 +383,10 @@ std::string PaintFilterToString(const sk_sp<cc::PaintFilter>& filter) {
// No need to populate the SerializeOptions here since the security
// constraints explicitly disable serializing images using the transfer cache
// and serialization of PaintRecords.
- cc::PaintOp::SerializeOptions options(nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, false, false, 0,
- SkM44());
+ cc::PaintOp::SerializeOptions options;
cc::PaintOpWriter writer(buffer.data(), buffer.size(), options,
true /* enable_security_constraints */);
- writer.Write(filter.get());
+ writer.Write(filter.get(), SkM44());
if (writer.size() == 0)
return "";
buffer.resize(writer.size());
@@ -471,18 +469,18 @@ bool FilterOperationFromDict(const base::Value& dict,
return false;
}
- base::Optional<int> type = dict.FindIntKey("type");
- base::Optional<double> amount = dict.FindDoubleKey("amount");
- base::Optional<double> outer_threshold =
+ absl::optional<int> type = dict.FindIntKey("type");
+ absl::optional<double> amount = dict.FindDoubleKey("amount");
+ absl::optional<double> outer_threshold =
dict.FindDoubleKey("outer_threshold");
const base::Value* drop_shadow_offset =
dict.FindDictKey("drop_shadow_offset");
- base::Optional<int> drop_shadow_color = dict.FindIntKey("drop_shadow_color");
+ absl::optional<int> drop_shadow_color = dict.FindIntKey("drop_shadow_color");
const std::string* image_filter = dict.FindStringKey("image_filter");
const base::Value* matrix = dict.FindListKey("matrix");
- base::Optional<int> zoom_inset = dict.FindIntKey("zoom_inset");
+ absl::optional<int> zoom_inset = dict.FindIntKey("zoom_inset");
const base::Value* shape = dict.FindListKey("shape");
- base::Optional<int> blur_tile_mode = dict.FindIntKey("blur_tile_mode");
+ absl::optional<int> blur_tile_mode = dict.FindIntKey("blur_tile_mode");
cc::FilterOperation filter;
@@ -879,6 +877,53 @@ bool DrawQuadResourcesFromList(const base::Value& list,
return true;
}
+base::Value SurfaceIdToDict(const SurfaceId& id) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetIntKey("client_id", id.frame_sink_id().client_id());
+ dict.SetIntKey("sink_id", id.frame_sink_id().sink_id());
+ dict.SetIntKey("parent_seq", id.local_surface_id().parent_sequence_number());
+ dict.SetIntKey("child_seq", id.local_surface_id().child_sequence_number());
+
+ // |embed_token_| doesn't need to be saved as long as a consistent token is
+ // used when deserializing.
+ return dict;
+}
+
+absl::optional<SurfaceId> SurfaceIdFromDict(const base::Value& dict) {
+ absl::optional<int> client_id = dict.FindIntKey("client_id");
+ absl::optional<int> sink_id = dict.FindIntKey("sink_id");
+ absl::optional<int> parent_seq = dict.FindIntKey("parent_seq");
+ absl::optional<int> child_seq = dict.FindIntKey("child_seq");
+ if (!client_id || !sink_id || !parent_seq || !child_seq)
+ return absl::nullopt;
+
+ base::UnguessableToken token = base::UnguessableToken::Deserialize(1, 1);
+ return SurfaceId(FrameSinkId(*client_id, *sink_id),
+ LocalSurfaceId(*parent_seq, *child_seq, token));
+}
+
+base::Value SurfaceRangeToDict(const SurfaceRange& range) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ if (range.start().has_value())
+ dict.SetKey("start", SurfaceIdToDict(*(range.start())));
+ dict.SetKey("end", SurfaceIdToDict(range.end()));
+ return dict;
+}
+
+absl::optional<SurfaceRange> SurfaceRangeFromDict(const base::Value& dict) {
+ const base::Value* start_dict = dict.FindDictKey("start");
+ const base::Value* end_dict = dict.FindDictKey("end");
+ if (!end_dict)
+ return absl::nullopt;
+ absl::optional<SurfaceId> start =
+ start_dict ? SurfaceIdFromDict(*start_dict) : absl::nullopt;
+ absl::optional<SurfaceId> end = SurfaceIdFromDict(*end_dict);
+ if (!end || (start_dict && !start))
+ return absl::nullopt;
+
+ return SurfaceRange(start, *end);
+}
+
int GetSharedQuadStateIndex(const SharedQuadStateList& shared_quad_state_list,
const SharedQuadState* shared_quad_state) {
for (auto iter = shared_quad_state_list.begin();
@@ -968,38 +1013,38 @@ struct DrawQuadCommon {
DrawQuad::Resources resources;
};
-base::Optional<DrawQuadCommon> GetDrawQuadCommonFromDict(
+absl::optional<DrawQuadCommon> GetDrawQuadCommonFromDict(
const base::Value& dict,
const SharedQuadStateList& shared_quad_state_list) {
if (!dict.is_dict())
- return base::nullopt;
+ return absl::nullopt;
const std::string* material = dict.FindStringKey("material");
const base::Value* rect = dict.FindDictKey("rect");
const base::Value* visible_rect = dict.FindDictKey("visible_rect");
- base::Optional<bool> needs_blending = dict.FindBoolKey("needs_blending");
- base::Optional<int> shared_quad_state_index =
+ absl::optional<bool> needs_blending = dict.FindBoolKey("needs_blending");
+ absl::optional<int> shared_quad_state_index =
dict.FindIntKey("shared_quad_state_index");
const base::Value* resources = dict.FindListKey("resources");
if (!material || !rect || !visible_rect || !needs_blending ||
!shared_quad_state_index || !resources) {
- return base::nullopt;
+ return absl::nullopt;
}
int material_index = StringToDrawQuadMaterial(*material);
if (material_index < 0)
- return base::nullopt;
+ return absl::nullopt;
int sqs_index = shared_quad_state_index.value();
if (sqs_index < 0 ||
static_cast<size_t>(sqs_index) >= shared_quad_state_list.size()) {
- return base::nullopt;
+ return absl::nullopt;
}
gfx::Rect t_rect, t_visible_rect;
if (!RectFromDict(*rect, &t_rect) ||
!RectFromDict(*visible_rect, &t_visible_rect)) {
- return base::nullopt;
+ return absl::nullopt;
}
DrawQuad::Resources t_resources;
if (!DrawQuadResourcesFromList(*resources, &t_resources))
- return base::nullopt;
+ return absl::nullopt;
return DrawQuadCommon{static_cast<DrawQuad::Material>(material_index),
t_rect,
@@ -1017,26 +1062,26 @@ struct ContentDrawQuadCommon {
bool force_anti_aliasing_off;
};
-base::Optional<ContentDrawQuadCommon> GetContentDrawQuadCommonFromDict(
+absl::optional<ContentDrawQuadCommon> GetContentDrawQuadCommonFromDict(
const base::Value& dict) {
if (!dict.is_dict())
- return base::nullopt;
+ return absl::nullopt;
const base::Value* tex_coord_rect = dict.FindDictKey("tex_coord_rect");
const base::Value* texture_size = dict.FindDictKey("texture_size");
- base::Optional<bool> is_premultiplied = dict.FindBoolKey("is_premultiplied");
- base::Optional<bool> nearest_neighbor = dict.FindBoolKey("nearest_neighbor");
- base::Optional<bool> force_anti_aliasing_off =
+ absl::optional<bool> is_premultiplied = dict.FindBoolKey("is_premultiplied");
+ absl::optional<bool> nearest_neighbor = dict.FindBoolKey("nearest_neighbor");
+ absl::optional<bool> force_anti_aliasing_off =
dict.FindBoolKey("force_anti_aliasing_off");
if (!tex_coord_rect || !texture_size || !is_premultiplied ||
!nearest_neighbor || !force_anti_aliasing_off) {
- return base::nullopt;
+ return absl::nullopt;
}
gfx::RectF t_tex_coord_rect;
gfx::Size t_texture_size;
if (!RectFFromDict(*tex_coord_rect, &t_tex_coord_rect) ||
!SizeFromDict(*texture_size, &t_texture_size)) {
- return base::nullopt;
+ return absl::nullopt;
}
return ContentDrawQuadCommon{
@@ -1112,6 +1157,19 @@ int StringToProtectedVideoType(const std::string& str) {
}
#undef MAP_STRING_TO_VIDEO_TYPE
+void SurfaceDrawQuadToDict(const SurfaceDrawQuad* draw_quad,
+ base::Value* dict) {
+ DCHECK(draw_quad);
+ DCHECK(dict);
+ dict->SetKey("surface_range", SurfaceRangeToDict(draw_quad->surface_range));
+ dict->SetIntKey("default_background_color",
+ bit_cast<int>(draw_quad->default_background_color));
+ dict->SetBoolKey("stretch_content",
+ draw_quad->stretch_content_to_fill_bounds);
+ dict->SetBoolKey("is_reflection", draw_quad->is_reflection);
+ dict->SetBoolKey("allow_merge", draw_quad->allow_merge);
+}
+
void TextureDrawQuadToDict(const TextureDrawQuad* draw_quad,
base::Value* dict) {
DCHECK(draw_quad);
@@ -1191,12 +1249,12 @@ base::Value DrawQuadToDict(const DrawQuad* draw_quad,
CompositorRenderPassDrawQuad)
WRITE_DRAW_QUAD_TYPE_FIELDS(kSolidColor, SolidColorDrawQuad)
WRITE_DRAW_QUAD_TYPE_FIELDS(kStreamVideoContent, StreamVideoDrawQuad)
+ WRITE_DRAW_QUAD_TYPE_FIELDS(kSurfaceContent, SurfaceDrawQuad)
WRITE_DRAW_QUAD_TYPE_FIELDS(kTextureContent, TextureDrawQuad)
WRITE_DRAW_QUAD_TYPE_FIELDS(kTiledContent, TileDrawQuad)
WRITE_DRAW_QUAD_TYPE_FIELDS(kYuvVideoContent, YUVVideoDrawQuad)
WRITE_DRAW_QUAD_TYPE_FIELDS(kVideoHole, VideoHoleDrawQuad)
UNEXPECTED_DRAW_QUAD_TYPE(kPictureContent)
- UNEXPECTED_DRAW_QUAD_TYPE(kSurfaceContent)
default:
break;
}
@@ -1230,11 +1288,11 @@ bool CompositorRenderPassDrawQuadFromDict(
const base::Value* filters_scale = dict.FindDictKey("filters_scale");
const base::Value* filters_origin = dict.FindDictKey("filters_origin");
const base::Value* tex_coord_rect = dict.FindDictKey("tex_coord_rect");
- base::Optional<double> backdrop_filter_quality =
+ absl::optional<double> backdrop_filter_quality =
dict.FindDoubleKey("backdrop_filter_quality");
- base::Optional<bool> force_anti_aliasing_off =
+ absl::optional<bool> force_anti_aliasing_off =
dict.FindBoolKey("force_anti_aliasing_off");
- base::Optional<bool> intersects_damage_under =
+ absl::optional<bool> intersects_damage_under =
dict.FindBoolKey("intersects_damage_under");
if (!render_pass_id || !mask_uv_rect || !mask_texture_size ||
@@ -1277,8 +1335,8 @@ bool SolidColorDrawQuadFromDict(const base::Value& dict,
DCHECK(draw_quad);
if (!dict.is_dict())
return false;
- base::Optional<int> color = dict.FindIntKey("color");
- base::Optional<bool> force_anti_aliasing_off =
+ absl::optional<int> color = dict.FindIntKey("color");
+ absl::optional<bool> force_anti_aliasing_off =
dict.FindBoolKey("force_anti_aliasing_off");
if (!color || !force_anti_aliasing_off)
return false;
@@ -1323,6 +1381,34 @@ bool StreamVideoDrawQuadFromDict(const base::Value& dict,
return true;
}
+bool SurfaceDrawQuadFromDict(const base::Value& dict,
+ const DrawQuadCommon& common,
+ SurfaceDrawQuad* draw_quad) {
+ DCHECK(draw_quad);
+ if (!dict.is_dict())
+ return false;
+
+ const base::Value* surface_range_dict = dict.FindDictKey("surface_range");
+ if (!surface_range_dict)
+ return false;
+ absl::optional<SurfaceRange> surface_range =
+ SurfaceRangeFromDict(*surface_range_dict);
+ absl::optional<int> default_background_color =
+ dict.FindIntKey("default_background_color");
+ absl::optional<bool> stretch_content = dict.FindBoolKey("stretch_content");
+ absl::optional<bool> is_reflection = dict.FindBoolKey("is_reflection");
+ absl::optional<bool> allow_merge = dict.FindBoolKey("allow_merge");
+ if (!surface_range || !default_background_color || !stretch_content ||
+ !is_reflection || !allow_merge)
+ return false;
+
+ draw_quad->SetAll(common.shared_quad_state, common.rect, common.visible_rect,
+ common.needs_blending, *surface_range,
+ bit_cast<SkColor>(*default_background_color),
+ *stretch_content, *is_reflection, *allow_merge);
+ return true;
+}
+
bool TextureDrawQuadFromDict(const base::Value& dict,
const DrawQuadCommon& common,
TextureDrawQuad* draw_quad) {
@@ -1332,15 +1418,15 @@ bool TextureDrawQuadFromDict(const base::Value& dict,
if (common.resources.count != 1u)
return false;
- base::Optional<bool> premultiplied_alpha =
+ absl::optional<bool> premultiplied_alpha =
dict.FindBoolKey("premultiplied_alpha");
const base::Value* uv_top_left = dict.FindDictKey("uv_top_left");
const base::Value* uv_bottom_right = dict.FindDictKey("uv_bottom_right");
- base::Optional<int> background_color = dict.FindIntKey("background_color");
+ absl::optional<int> background_color = dict.FindIntKey("background_color");
const base::Value* vertex_opacity = dict.FindListKey("vertex_opacity");
- base::Optional<bool> y_flipped = dict.FindBoolKey("y_flipped");
- base::Optional<bool> nearest_neighbor = dict.FindBoolKey("nearest_neighbor");
- base::Optional<bool> secure_output_only =
+ absl::optional<bool> y_flipped = dict.FindBoolKey("y_flipped");
+ absl::optional<bool> nearest_neighbor = dict.FindBoolKey("nearest_neighbor");
+ absl::optional<bool> secure_output_only =
dict.FindBoolKey("secure_output_only");
const std::string* protected_video_type =
dict.FindStringKey("protected_video_type");
@@ -1388,7 +1474,7 @@ bool TileDrawQuadFromDict(const base::Value& dict,
if (common.resources.count != 1u)
return false;
- base::Optional<ContentDrawQuadCommon> content_common =
+ absl::optional<ContentDrawQuadCommon> content_common =
GetContentDrawQuadCommonFromDict(dict);
if (!content_common)
return false;
@@ -1417,11 +1503,11 @@ bool YUVVideoDrawQuadFromDict(const base::Value& dict,
const base::Value* uv_tex_coord_rect = dict.FindDictKey("uv_tex_coord_rect");
const base::Value* ya_tex_size = dict.FindDictKey("ya_tex_size");
const base::Value* uv_tex_size = dict.FindDictKey("uv_tex_size");
- base::Optional<double> resource_offset =
+ absl::optional<double> resource_offset =
dict.FindDoubleKey("resource_offset");
- base::Optional<double> resource_multiplier =
+ absl::optional<double> resource_multiplier =
dict.FindDoubleKey("resource_multiplier");
- base::Optional<int> bits_per_channel = dict.FindIntKey("bits_per_channel");
+ absl::optional<int> bits_per_channel = dict.FindIntKey("bits_per_channel");
const base::Value* video_color_space = dict.FindDictKey("video_color_space");
const std::string* protected_video_type =
dict.FindStringKey("protected_video_type");
@@ -1479,7 +1565,7 @@ bool VideoHoleDrawQuadFromDict(const base::Value& dict,
if (!dict.is_dict())
return false;
- base::Optional<bool> overlay_plane_id_empty =
+ absl::optional<bool> overlay_plane_id_empty =
dict.FindBoolKey("overlay_plane_id.empty");
if (!overlay_plane_id_empty)
return false;
@@ -1530,7 +1616,7 @@ bool QuadListFromList(const base::Value& list,
for (size_t ii = 0; ii < size; ++ii) {
if (!list.GetList()[ii].is_dict())
return false;
- base::Optional<DrawQuadCommon> common =
+ absl::optional<DrawQuadCommon> common =
GetDrawQuadCommonFromDict(list.GetList()[ii], shared_quad_state_list);
if (!common)
return false;
@@ -1538,12 +1624,12 @@ bool QuadListFromList(const base::Value& list,
GET_QUAD_FROM_DICT(kCompositorRenderPass, CompositorRenderPassDrawQuad)
GET_QUAD_FROM_DICT(kSolidColor, SolidColorDrawQuad)
GET_QUAD_FROM_DICT(kStreamVideoContent, StreamVideoDrawQuad)
+ GET_QUAD_FROM_DICT(kSurfaceContent, SurfaceDrawQuad)
GET_QUAD_FROM_DICT(kTextureContent, TextureDrawQuad)
GET_QUAD_FROM_DICT(kTiledContent, TileDrawQuad)
GET_QUAD_FROM_DICT(kYuvVideoContent, YUVVideoDrawQuad)
GET_QUAD_FROM_DICT(kVideoHole, VideoHoleDrawQuad)
UNEXPECTED_DRAW_QUAD_TYPE(kPictureContent)
- UNEXPECTED_DRAW_QUAD_TYPE(kSurfaceContent)
default:
break;
}
@@ -1604,8 +1690,9 @@ base::Value SharedQuadStateToDict(const SharedQuadState& sqs) {
RectToDict(sqs.visible_quad_layer_rect));
dict.SetKey("rounded_corner_bounds",
RRectFToDict(sqs.mask_filter_info.rounded_corner_bounds()));
- dict.SetKey("clip_rect", RectToDict(sqs.clip_rect));
- dict.SetBoolKey("is_clipped", sqs.is_clipped);
+ if (sqs.clip_rect) {
+ dict.SetKey("clip_rect", RectToDict(*sqs.clip_rect));
+ }
dict.SetBoolKey("are_contents_opaque", sqs.are_contents_opaque);
dict.SetDoubleKey("opacity", sqs.opacity);
dict.SetStringKey("blend_mode", BlendModeToString(sqs.blend_mode));
@@ -1664,22 +1751,22 @@ bool SharedQuadStateFromDict(const base::Value& dict, SharedQuadState* sqs) {
const base::Value* rounded_corner_bounds =
dict.FindDictKey("rounded_corner_bounds");
const base::Value* clip_rect = dict.FindDictKey("clip_rect");
- base::Optional<bool> is_clipped = dict.FindBoolKey("is_clipped");
- base::Optional<bool> are_contents_opaque =
+ absl::optional<bool> is_clipped = dict.FindBoolKey("is_clipped");
+ absl::optional<bool> are_contents_opaque =
dict.FindBoolKey("are_contents_opaque");
- base::Optional<double> opacity = dict.FindDoubleKey("opacity");
+ absl::optional<double> opacity = dict.FindDoubleKey("opacity");
const std::string* blend_mode = dict.FindStringKey("blend_mode");
- base::Optional<int> sorting_context_id =
+ absl::optional<int> sorting_context_id =
dict.FindIntKey("sorting_context_id");
- base::Optional<bool> is_fast_rounded_corner =
+ absl::optional<bool> is_fast_rounded_corner =
dict.FindBoolKey("is_fast_rounded_corner");
- base::Optional<double> de_jelly_delta_y =
+ absl::optional<double> de_jelly_delta_y =
dict.FindDoubleKey("de_jelly_delta_y");
if (!quad_to_target_transform || !quad_layer_rect ||
- !visible_quad_layer_rect || !rounded_corner_bounds || !clip_rect ||
- !is_clipped || !are_contents_opaque || !opacity || !blend_mode ||
- !sorting_context_id || !is_fast_rounded_corner || !de_jelly_delta_y) {
+ !visible_quad_layer_rect || !rounded_corner_bounds ||
+ !are_contents_opaque || !opacity || !blend_mode || !sorting_context_id ||
+ !is_fast_rounded_corner || !de_jelly_delta_y) {
return false;
}
gfx::Transform t_quad_to_target_transform;
@@ -1690,9 +1777,20 @@ bool SharedQuadStateFromDict(const base::Value& dict, SharedQuadState* sqs) {
!RectFromDict(*quad_layer_rect, &t_quad_layer_rect) ||
!RectFromDict(*visible_quad_layer_rect, &t_visible_quad_layer_rect) ||
!RRectFFromDict(*rounded_corner_bounds, &t_rounded_corner_bounds) ||
- !RectFromDict(*clip_rect, &t_clip_rect)) {
+ (clip_rect && !RectFromDict(*clip_rect, &t_clip_rect))) {
return false;
}
+ absl::optional<gfx::Rect> clip_rect_opt;
+ // Some older files still use the is_clipped field. If it's present, we'll
+ // respect it, and ignore clip_rect if it's false.
+ if (is_clipped.has_value()) {
+ if (is_clipped.value()) {
+ clip_rect_opt = t_clip_rect;
+ }
+ } else if (clip_rect) {
+ clip_rect_opt = t_clip_rect;
+ }
+
int blend_mode_index = StringToBlendMode(*blend_mode);
DCHECK_GE(static_cast<int>(SkBlendMode::kLastMode), blend_mode_index);
if (blend_mode_index < 0)
@@ -1700,10 +1798,9 @@ bool SharedQuadStateFromDict(const base::Value& dict, SharedQuadState* sqs) {
SkBlendMode t_blend_mode = static_cast<SkBlendMode>(blend_mode_index);
gfx::MaskFilterInfo mask_filter_info(t_rounded_corner_bounds);
sqs->SetAll(t_quad_to_target_transform, t_quad_layer_rect,
- t_visible_quad_layer_rect, mask_filter_info, t_clip_rect,
- is_clipped.value(), are_contents_opaque.value(),
- static_cast<float>(opacity.value()), t_blend_mode,
- sorting_context_id.value());
+ t_visible_quad_layer_rect, mask_filter_info, clip_rect_opt,
+ are_contents_opaque.value(), static_cast<float>(opacity.value()),
+ t_blend_mode, sorting_context_id.value());
sqs->is_fast_rounded_corner = is_fast_rounded_corner.value();
sqs->de_jelly_delta_y = static_cast<float>(de_jelly_delta_y.value());
return true;
@@ -1900,7 +1997,7 @@ std::unique_ptr<CompositorRenderPass> CompositorRenderPassFromDict(
}
if (ProcessRenderPassField(kRenderPassHasTransparentBackground)) {
- const base::Optional<bool> has_transparent_background =
+ const absl::optional<bool> has_transparent_background =
dict.FindBoolKey("has_transparent_background");
if (!has_transparent_background)
return nullptr;
@@ -1908,7 +2005,7 @@ std::unique_ptr<CompositorRenderPass> CompositorRenderPassFromDict(
}
if (ProcessRenderPassField(kRenderPassCacheRenderPass)) {
- const base::Optional<bool> cache_render_pass =
+ const absl::optional<bool> cache_render_pass =
dict.FindBoolKey("cache_render_pass");
if (!cache_render_pass)
return nullptr;
@@ -1916,7 +2013,7 @@ std::unique_ptr<CompositorRenderPass> CompositorRenderPassFromDict(
}
if (ProcessRenderPassField(kRenderPassHasDamageFromContributingContent)) {
- const base::Optional<bool> has_damage_from_contributing_content =
+ const absl::optional<bool> has_damage_from_contributing_content =
dict.FindBoolKey("has_damage_from_contributing_content");
if (!has_damage_from_contributing_content)
return nullptr;
@@ -1925,7 +2022,7 @@ std::unique_ptr<CompositorRenderPass> CompositorRenderPassFromDict(
}
if (ProcessRenderPassField(kRenderPassGenerateMipmap)) {
- const base::Optional<bool> generate_mipmap =
+ const absl::optional<bool> generate_mipmap =
dict.FindBoolKey("generate_mipmap");
if (!generate_mipmap)
return nullptr;
diff --git a/chromium/components/viz/common/quads/render_pass_io_unittest.cc b/chromium/components/viz/common/quads/render_pass_io_unittest.cc
index 567d1a4cd85..1c819ea537c 100644
--- a/chromium/components/viz/common/quads/render_pass_io_unittest.cc
+++ b/chromium/components/viz/common/quads/render_pass_io_unittest.cc
@@ -14,6 +14,7 @@
#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/stream_video_draw_quad.h"
+#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/quads/tile_draw_quad.h"
#include "components/viz/common/quads/video_hole_draw_quad.h"
#include "components/viz/common/quads/yuv_video_draw_quad.h"
@@ -27,6 +28,11 @@ struct HDRMetadata;
namespace viz {
namespace {
+constexpr SurfaceId kSurfaceId1(FrameSinkId(1, 1),
+ LocalSurfaceId(1, 1, base::UnguessableToken()));
+constexpr SurfaceId kSurfaceId2(FrameSinkId(2, 2),
+ LocalSurfaceId(2, 2, base::UnguessableToken()));
+
TEST(RenderPassIOTest, Default) {
auto render_pass0 = CompositorRenderPass::Create();
base::Value dict0 = CompositorRenderPassToDict(*render_pass0);
@@ -124,8 +130,7 @@ TEST(RenderPassIOTest, SharedQuadStateList) {
sqs1->SetAll(
transform, gfx::Rect(0, 0, 640, 480), gfx::Rect(10, 10, 600, 400),
gfx::MaskFilterInfo(gfx::RRectF(gfx::RectF(2.f, 3.f, 4.f, 5.f), 1.5f)),
- gfx::Rect(5, 20, 1000, 200), true, false, 0.5f, SkBlendMode::kDstOver,
- 101);
+ gfx::Rect(5, 20, 1000, 200), false, 0.5f, SkBlendMode::kDstOver, 101);
sqs1->is_fast_rounded_corner = true;
sqs1->de_jelly_delta_y = 0.7f;
}
@@ -142,8 +147,7 @@ TEST(RenderPassIOTest, SharedQuadStateList) {
EXPECT_EQ(gfx::Rect(), sqs0->quad_layer_rect);
EXPECT_EQ(gfx::Rect(), sqs0->visible_quad_layer_rect);
EXPECT_FALSE(sqs0->mask_filter_info.HasRoundedCorners());
- EXPECT_EQ(gfx::Rect(), sqs0->clip_rect);
- EXPECT_FALSE(sqs0->is_clipped);
+ EXPECT_EQ(absl::nullopt, sqs0->clip_rect);
EXPECT_TRUE(sqs0->are_contents_opaque);
EXPECT_EQ(1.0f, sqs0->opacity);
EXPECT_EQ(SkBlendMode::kSrcOver, sqs0->blend_mode);
@@ -163,7 +167,6 @@ TEST(RenderPassIOTest, SharedQuadStateList) {
sqs1->mask_filter_info.rounded_corner_bounds().GetSimpleRadius());
EXPECT_EQ(gfx::RectF(2.f, 3.f, 4.f, 5.f), sqs1->mask_filter_info.bounds());
EXPECT_EQ(gfx::Rect(5, 20, 1000, 200), sqs1->clip_rect);
- EXPECT_TRUE(sqs1->is_clipped);
EXPECT_FALSE(sqs1->are_contents_opaque);
EXPECT_EQ(0.5f, sqs1->opacity);
EXPECT_EQ(SkBlendMode::kDstOver, sqs1->blend_mode);
@@ -186,6 +189,8 @@ TEST(RenderPassIOTest, QuadList) {
DrawQuad::Material::kTextureContent,
DrawQuad::Material::kCompositorRenderPass,
DrawQuad::Material::kTiledContent,
+ DrawQuad::Material::kSurfaceContent,
+ DrawQuad::Material::kSurfaceContent,
};
auto render_pass0 = CompositorRenderPass::Create();
{
@@ -284,6 +289,26 @@ TEST(RenderPassIOTest, QuadList) {
gfx::Size(256, 512), true, true, true);
++quad_count;
}
+ {
+ // 8. SurfaceDrawQuad
+ SurfaceDrawQuad* quad =
+ render_pass0->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ quad->SetAll(render_pass0->shared_quad_state_list.ElementAt(sqs_index),
+ gfx::Rect(0, 0, 512, 256), gfx::Rect(2, 2, 500, 250), true,
+ SurfaceRange(kSurfaceId1, kSurfaceId2), SK_ColorWHITE, false,
+ false, true);
+ ++quad_count;
+ }
+ {
+ // 9. SurfaceDrawQuad with no starting SurfaceId
+ SurfaceDrawQuad* quad =
+ render_pass0->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
+ quad->SetAll(render_pass0->shared_quad_state_list.ElementAt(sqs_index),
+ gfx::Rect(10, 10, 512, 256), gfx::Rect(12, 12, 500, 250),
+ true, SurfaceRange(absl::nullopt, kSurfaceId1),
+ SK_ColorBLACK, true, true, false);
+ ++quad_count;
+ }
DCHECK_EQ(kSharedQuadStateCount, sqs_index + 1);
}
base::Value dict0 = CompositorRenderPassToDict(*render_pass0);
@@ -312,7 +337,7 @@ TEST(RenderPassIOTest, CompositorRenderPassList) {
std::string json_text;
ASSERT_TRUE(base::ReadFileToString(json_path, &json_text));
- base::Optional<base::Value> dict0 = base::JSONReader::Read(json_text);
+ absl::optional<base::Value> dict0 = base::JSONReader::Read(json_text);
EXPECT_TRUE(dict0.has_value());
CompositorRenderPassList render_pass_list;
EXPECT_TRUE(
diff --git a/chromium/components/viz/common/quads/shared_quad_state.cc b/chromium/components/viz/common/quads/shared_quad_state.cc
index 5d7d3b32292..e7a003dd021 100644
--- a/chromium/components/viz/common/quads/shared_quad_state.cc
+++ b/chromium/components/viz/common/quads/shared_quad_state.cc
@@ -9,6 +9,7 @@
#include "base/values.h"
#include "cc/base/math_util.h"
#include "components/viz/common/traced_value.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBlendMode.h"
namespace viz {
@@ -24,8 +25,7 @@ void SharedQuadState::SetAll(const gfx::Transform& quad_to_target_transform,
const gfx::Rect& quad_layer_rect,
const gfx::Rect& visible_quad_layer_rect,
const gfx::MaskFilterInfo& mask_filter_info,
- const gfx::Rect& clip_rect,
- bool is_clipped,
+ const absl::optional<gfx::Rect>& clip_rect,
bool are_contents_opaque,
float opacity,
SkBlendMode blend_mode,
@@ -35,7 +35,6 @@ void SharedQuadState::SetAll(const gfx::Transform& quad_to_target_transform,
this->visible_quad_layer_rect = visible_quad_layer_rect;
this->mask_filter_info = mask_filter_info;
this->clip_rect = clip_rect;
- this->is_clipped = is_clipped;
this->are_contents_opaque = are_contents_opaque;
this->opacity = opacity;
this->blend_mode = blend_mode;
@@ -53,8 +52,9 @@ void SharedQuadState::AsValueInto(base::trace_event::TracedValue* value) const {
"mask_filter_rounded_corners_radii",
mask_filter_info.rounded_corner_bounds(), value);
- value->SetBoolean("is_clipped", is_clipped);
- cc::MathUtil::AddToTracedValue("clip_rect", clip_rect, value);
+ if (clip_rect) {
+ cc::MathUtil::AddToTracedValue("clip_rect", *clip_rect, value);
+ }
value->SetBoolean("are_contents_opaque", are_contents_opaque);
value->SetDouble("opacity", opacity);
diff --git a/chromium/components/viz/common/quads/shared_quad_state.h b/chromium/components/viz/common/quads/shared_quad_state.h
index a1694be0054..c16c0a2248d 100644
--- a/chromium/components/viz/common/quads/shared_quad_state.h
+++ b/chromium/components/viz/common/quads/shared_quad_state.h
@@ -5,10 +5,8 @@
#ifndef COMPONENTS_VIZ_COMMON_QUADS_SHARED_QUAD_STATE_H_
#define COMPONENTS_VIZ_COMMON_QUADS_SHARED_QUAD_STATE_H_
-#include <memory>
-
-#include "base/optional.h"
#include "components/viz/common/viz_common_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBlendMode.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/mask_filter_info.h"
@@ -38,8 +36,7 @@ class VIZ_COMMON_EXPORT SharedQuadState {
const gfx::Rect& quad_layer_rect,
const gfx::Rect& visible_layer_rect,
const gfx::MaskFilterInfo& mask_filter_info,
- const gfx::Rect& clip_rect,
- bool is_clipped,
+ const absl::optional<gfx::Rect>& clip_rect,
bool are_contents_opaque,
float opacity,
SkBlendMode blend_mode,
@@ -60,8 +57,7 @@ class VIZ_COMMON_EXPORT SharedQuadState {
// the corner radius to clip the quads with.
gfx::MaskFilterInfo mask_filter_info;
// This rect lives in the target content space.
- gfx::Rect clip_rect;
- bool is_clipped = false;
+ absl::optional<gfx::Rect> clip_rect;
// Indicates whether the content in |quad_layer_rect| are fully opaque.
bool are_contents_opaque = true;
float opacity = 1.f;
@@ -75,7 +71,7 @@ class VIZ_COMMON_EXPORT SharedQuadState {
// and the OverlayProcessor. Do not set the value in CompositorRenderPass.
// This index points to the damage rect in the surface damage rect list where
// the overlay quad belongs to. SetAll() doesn't update this data.
- base::Optional<size_t> overlay_damage_index;
+ absl::optional<size_t> overlay_damage_index;
// The amount to skew quads in this layer. For experimental de-jelly effect.
float de_jelly_delta_y = 0.0f;
diff --git a/chromium/components/viz/common/quads/solid_color_draw_quad.h b/chromium/components/viz/common/quads/solid_color_draw_quad.h
index ab831fac410..b653fb15a20 100644
--- a/chromium/components/viz/common/quads/solid_color_draw_quad.h
+++ b/chromium/components/viz/common/quads/solid_color_draw_quad.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_VIZ_COMMON_QUADS_SOLID_COLOR_DRAW_QUAD_H_
#define COMPONENTS_VIZ_COMMON_QUADS_SOLID_COLOR_DRAW_QUAD_H_
-#include <memory>
-
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/viz_common_export.h"
#include "third_party/skia/include/core/SkColor.h"
diff --git a/chromium/components/viz/common/quads/stream_video_draw_quad.h b/chromium/components/viz/common/quads/stream_video_draw_quad.h
index a07a5ffebae..5b575f5d9ad 100644
--- a/chromium/components/viz/common/quads/stream_video_draw_quad.h
+++ b/chromium/components/viz/common/quads/stream_video_draw_quad.h
@@ -7,8 +7,6 @@
#include <stddef.h>
-#include <memory>
-
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/viz_common_export.h"
diff --git a/chromium/components/viz/common/quads/surface_draw_quad.cc b/chromium/components/viz/common/quads/surface_draw_quad.cc
index 833c1dc059a..12f75ac8dab 100644
--- a/chromium/components/viz/common/quads/surface_draw_quad.cc
+++ b/chromium/components/viz/common/quads/surface_draw_quad.cc
@@ -5,9 +5,9 @@
#include "components/viz/common/quads/surface_draw_quad.h"
#include "base/check_op.h"
-#include "base/optional.h"
#include "base/trace_event/traced_value.h"
#include "base/values.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace viz {
diff --git a/chromium/components/viz/common/quads/surface_draw_quad.h b/chromium/components/viz/common/quads/surface_draw_quad.h
index 52f06060dc4..cfa6a8d78bc 100644
--- a/chromium/components/viz/common/quads/surface_draw_quad.h
+++ b/chromium/components/viz/common/quads/surface_draw_quad.h
@@ -5,12 +5,10 @@
#ifndef COMPONENTS_VIZ_COMMON_QUADS_SURFACE_DRAW_QUAD_H_
#define COMPONENTS_VIZ_COMMON_QUADS_SURFACE_DRAW_QUAD_H_
-#include <memory>
-
-#include "base/optional.h"
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/surfaces/surface_range.h"
#include "components/viz/common/viz_common_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
namespace viz {
diff --git a/chromium/components/viz/common/quads/texture_draw_quad.h b/chromium/components/viz/common/quads/texture_draw_quad.h
index a2d0fdaaaa7..3426ca94d3c 100644
--- a/chromium/components/viz/common/quads/texture_draw_quad.h
+++ b/chromium/components/viz/common/quads/texture_draw_quad.h
@@ -7,8 +7,6 @@
#include <stddef.h>
-#include <memory>
-
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/viz_common_export.h"
diff --git a/chromium/components/viz/common/quads/video_hole_draw_quad.h b/chromium/components/viz/common/quads/video_hole_draw_quad.h
index 7b48a8bf779..f0a1954332e 100644
--- a/chromium/components/viz/common/quads/video_hole_draw_quad.h
+++ b/chromium/components/viz/common/quads/video_hole_draw_quad.h
@@ -7,8 +7,6 @@
#include <stddef.h>
-#include <memory>
-
#include "base/unguessable_token.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/viz_common_export.h"
diff --git a/chromium/components/viz/common/quads/yuv_video_draw_quad.h b/chromium/components/viz/common/quads/yuv_video_draw_quad.h
index a712274476c..e0528601ca1 100644
--- a/chromium/components/viz/common/quads/yuv_video_draw_quad.h
+++ b/chromium/components/viz/common/quads/yuv_video_draw_quad.h
@@ -7,8 +7,6 @@
#include <stddef.h>
-#include <memory>
-
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/viz_common_export.h"
diff --git a/chromium/components/viz/common/resources/bitmap_allocation.h b/chromium/components/viz/common/resources/bitmap_allocation.h
index 8068a19310d..d2da4eadc6b 100644
--- a/chromium/components/viz/common/resources/bitmap_allocation.h
+++ b/chromium/components/viz/common/resources/bitmap_allocation.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_VIZ_COMMON_RESOURCES_BITMAP_ALLOCATION_H_
#define COMPONENTS_VIZ_COMMON_RESOURCES_BITMAP_ALLOCATION_H_
-#include <memory>
-
#include "base/memory/read_only_shared_memory_region.h"
#include "components/viz/common/resources/resource_format.h"
#include "components/viz/common/viz_common_export.h"
diff --git a/chromium/components/viz/common/resources/resource_format_utils.cc b/chromium/components/viz/common/resources/resource_format_utils.cc
index 3a8d31e0ef5..0abe8d20a35 100644
--- a/chromium/components/viz/common/resources/resource_format_utils.cc
+++ b/chromium/components/viz/common/resources/resource_format_utils.cc
@@ -72,6 +72,47 @@ SkColorType ResourceFormatToClosestSkColorType(bool gpu_compositing,
return kN32_SkColorType;
}
+ResourceFormat SkColorTypeToResourceFormat(SkColorType color_type) {
+ switch (color_type) {
+ case kARGB_4444_SkColorType:
+ return RGBA_4444;
+ case kBGRA_8888_SkColorType:
+ return BGRA_8888;
+ case kRGBA_8888_SkColorType:
+ return RGBA_8888;
+ case kRGBA_F16_SkColorType:
+ return RGBA_F16;
+ case kAlpha_8_SkColorType:
+ return ALPHA_8;
+ case kRGB_565_SkColorType:
+ return RGB_565;
+ case kGray_8_SkColorType:
+ return LUMINANCE_8;
+ case kRGB_888x_SkColorType:
+ return RGBX_8888;
+ case kRGBA_1010102_SkColorType:
+ return RGBA_1010102;
+ case kBGRA_1010102_SkColorType:
+ return BGRA_1010102;
+ // These colortypes are just for reading from - not to render to
+ case kR8G8_unorm_SkColorType:
+ case kA16_float_SkColorType:
+ case kR16G16_float_SkColorType:
+ case kA16_unorm_SkColorType:
+ case kR16G16_unorm_SkColorType:
+ case kR16G16B16A16_unorm_SkColorType:
+ case kUnknown_SkColorType:
+ // These colortypes are don't have an equivalent in ResourceFormat
+ case kRGB_101010x_SkColorType:
+ case kBGR_101010x_SkColorType:
+ case kRGBA_F16Norm_SkColorType:
+ case kRGBA_F32_SkColorType:
+ break;
+ }
+ NOTREACHED();
+ return RGBA_8888;
+}
+
int BitsPerPixel(ResourceFormat format) {
switch (format) {
case RGBA_F16:
@@ -463,34 +504,8 @@ bool GLSupportsFormat(ResourceFormat format) {
}
#if BUILDFLAG(ENABLE_VULKAN)
-bool HasVkFormat(ResourceFormat format) {
- switch (format) {
- case RGBA_8888:
- case RGBA_4444:
- case BGRA_8888:
- case RED_8:
- case RGB_565:
- case BGR_565:
- case RG_88:
- case RGBA_F16:
- case R16_EXT:
- case RG16_EXT:
- case RGBX_8888:
- case BGRX_8888:
- case RGBA_1010102:
- case BGRA_1010102:
- case ALPHA_8:
- case LUMINANCE_8:
- case YVU_420:
- case YUV_420_BIPLANAR:
- case ETC1:
- return true;
- default:
- return false;
- }
-}
-
-VkFormat ToVkFormat(ResourceFormat format) {
+namespace {
+VkFormat ToVkFormatInternal(ResourceFormat format) {
switch (format) {
case RGBA_8888:
return VK_FORMAT_R8G8B8A8_UNORM; // or VK_FORMAT_R8G8B8A8_SRGB
@@ -531,12 +546,23 @@ VkFormat ToVkFormat(ResourceFormat format) {
case ETC1:
return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
case LUMINANCE_F16:
+ return VK_FORMAT_R16_SFLOAT;
case P010:
break;
}
- NOTREACHED() << "Unsupported format " << format;
return VK_FORMAT_UNDEFINED;
}
+} // namespace
+
+bool HasVkFormat(ResourceFormat format) {
+ return ToVkFormatInternal(format) != VK_FORMAT_UNDEFINED;
+}
+
+VkFormat ToVkFormat(ResourceFormat format) {
+ auto result = ToVkFormatInternal(format);
+ DCHECK_NE(result, VK_FORMAT_UNDEFINED) << "Unsupported format " << format;
+ return result;
+}
#endif
wgpu::TextureFormat ToDawnFormat(ResourceFormat format) {
diff --git a/chromium/components/viz/common/resources/resource_format_utils.h b/chromium/components/viz/common/resources/resource_format_utils.h
index 05861bdc329..77b5c55d254 100644
--- a/chromium/components/viz/common/resources/resource_format_utils.h
+++ b/chromium/components/viz/common/resources/resource_format_utils.h
@@ -26,6 +26,8 @@ VIZ_RESOURCE_FORMAT_EXPORT SkColorType
ResourceFormatToClosestSkColorType(bool gpu_compositing, ResourceFormat format);
VIZ_RESOURCE_FORMAT_EXPORT int BitsPerPixel(ResourceFormat format);
VIZ_RESOURCE_FORMAT_EXPORT bool HasAlpha(ResourceFormat format);
+VIZ_RESOURCE_FORMAT_EXPORT ResourceFormat
+SkColorTypeToResourceFormat(SkColorType color_type);
// The following functions use unsigned int instead of GLenum, since including
// third_party/khronos/GLES2/gl2.h causes redefinition errors as
diff --git a/chromium/components/viz/common/resources/return_callback.h b/chromium/components/viz/common/resources/return_callback.h
index c0ae0a1235d..8e5f3538dbe 100644
--- a/chromium/components/viz/common/resources/return_callback.h
+++ b/chromium/components/viz/common/resources/return_callback.h
@@ -11,7 +11,7 @@
namespace viz {
using ReturnCallback =
- base::RepeatingCallback<void(const std::vector<ReturnedResource>&)>;
+ base::RepeatingCallback<void(std::vector<ReturnedResource>)>;
} // namespace viz
diff --git a/chromium/components/viz/common/resources/returned_resource.cc b/chromium/components/viz/common/resources/returned_resource.cc
index 3d29e3bc2d6..10f1a7cef66 100644
--- a/chromium/components/viz/common/resources/returned_resource.cc
+++ b/chromium/components/viz/common/resources/returned_resource.cc
@@ -3,19 +3,28 @@
// found in the LICENSE file.
#include "components/viz/common/resources/returned_resource.h"
+#include "ui/gfx/gpu_fence_handle.h"
namespace viz {
ReturnedResource::ReturnedResource(ResourceId id,
gpu::SyncToken sync_token,
+ gfx::GpuFenceHandle release_fence,
int count,
bool lost)
- : id(id), sync_token(sync_token), count(count), lost(lost) {}
+ : id(id),
+ sync_token(sync_token),
+ release_fence(std::move(release_fence)),
+ count(count),
+ lost(lost) {}
ReturnedResource::ReturnedResource() = default;
-ReturnedResource::ReturnedResource(const ReturnedResource& other) = default;
-ReturnedResource& ReturnedResource::operator=(const ReturnedResource& other) =
+ReturnedResource::~ReturnedResource() = default;
+
+ReturnedResource::ReturnedResource(ReturnedResource&& other) = default;
+
+ReturnedResource& ReturnedResource::operator=(ReturnedResource&& other) =
default;
} // namespace viz
diff --git a/chromium/components/viz/common/resources/returned_resource.h b/chromium/components/viz/common/resources/returned_resource.h
index 688157c0949..459e9d9a100 100644
--- a/chromium/components/viz/common/resources/returned_resource.h
+++ b/chromium/components/viz/common/resources/returned_resource.h
@@ -5,11 +5,10 @@
#ifndef COMPONENTS_VIZ_COMMON_RESOURCES_RETURNED_RESOURCE_H_
#define COMPONENTS_VIZ_COMMON_RESOURCES_RETURNED_RESOURCE_H_
-#include <vector>
-
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/viz_common_export.h"
#include "gpu/command_buffer/common/sync_token.h"
+#include "ui/gfx/gpu_fence_handle.h"
namespace viz {
@@ -19,22 +18,17 @@ namespace viz {
struct VIZ_COMMON_EXPORT ReturnedResource {
ReturnedResource(ResourceId id,
gpu::SyncToken sync_token,
+ gfx::GpuFenceHandle release_fence,
int count,
bool lost);
ReturnedResource();
- ReturnedResource(const ReturnedResource& other);
-
- ReturnedResource& operator=(const ReturnedResource& other);
+ ~ReturnedResource();
+ ReturnedResource(ReturnedResource&& other);
+ ReturnedResource& operator=(ReturnedResource&& other);
- bool operator==(const ReturnedResource& other) const {
- return id == other.id && sync_token == other.sync_token &&
- count == other.count && lost == other.lost;
- }
-
- bool operator!=(const ReturnedResource& other) const {
- return !(*this == other);
- }
+ ReturnedResource(const ReturnedResource& other) = delete;
+ ReturnedResource& operator=(const ReturnedResource& other) = delete;
// |id| is an identifier generated by the child compositor that uniquely
// identifies a resource. This is the same ID space as TransferableResource.
@@ -47,6 +41,11 @@ struct VIZ_COMMON_EXPORT ReturnedResource {
// are executed before commands submitted by the child.
gpu::SyncToken sync_token;
+ // Release fence for this resource. If this is a valid fence then the client
+ // may use it to wait if they need to perform external operations
+ // (e.g. CPU operations) on this resource.
+ gfx::GpuFenceHandle release_fence;
+
// |count| is a reference count for this resource. A resource may be used
// by mulitple compositor frames submitted to the parent compositor. |count|
// is the number of references being returned back to the child compositor.
diff --git a/chromium/components/viz/common/resources/shared_bitmap.cc b/chromium/components/viz/common/resources/shared_bitmap.cc
index c5f3955bc5e..3c9cffb1fd6 100644
--- a/chromium/components/viz/common/resources/shared_bitmap.cc
+++ b/chromium/components/viz/common/resources/shared_bitmap.cc
@@ -10,7 +10,6 @@
#include "base/numerics/safe_math.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "components/viz/common/resources/resource_format_utils.h"
namespace viz {
diff --git a/chromium/components/viz/common/resources/single_release_callback.cc b/chromium/components/viz/common/resources/single_release_callback.cc
deleted file mode 100644
index acea5762079..00000000000
--- a/chromium/components/viz/common/resources/single_release_callback.cc
+++ /dev/null
@@ -1,27 +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/viz/common/resources/single_release_callback.h"
-
-#include "base/callback_helpers.h"
-#include "base/check.h"
-
-namespace viz {
-
-SingleReleaseCallback::SingleReleaseCallback(ReleaseCallback callback)
- : callback_(std::move(callback)) {
- DCHECK(!callback_.is_null())
- << "Use a NULL SingleReleaseCallback for an empty callback.";
-}
-
-SingleReleaseCallback::~SingleReleaseCallback() = default;
-
-void SingleReleaseCallback::Run(const gpu::SyncToken& sync_token,
- bool is_lost) {
- DCHECK(!callback_.is_null())
- << "SingleReleaseCallback was run more than once.";
- std::move(callback_).Run(sync_token, is_lost);
-}
-
-} // namespace viz
diff --git a/chromium/components/viz/common/resources/single_release_callback.h b/chromium/components/viz/common/resources/single_release_callback.h
deleted file mode 100644
index fe28abb6703..00000000000
--- a/chromium/components/viz/common/resources/single_release_callback.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_COMMON_RESOURCES_SINGLE_RELEASE_CALLBACK_H_
-#define COMPONENTS_VIZ_COMMON_RESOURCES_SINGLE_RELEASE_CALLBACK_H_
-
-#include <memory>
-
-#include "base/memory/ptr_util.h"
-#include "components/viz/common/resources/release_callback.h"
-#include "components/viz/common/viz_common_export.h"
-
-namespace viz {
-
-class VIZ_COMMON_EXPORT SingleReleaseCallback {
- public:
- static std::unique_ptr<SingleReleaseCallback> Create(ReleaseCallback cb) {
- return base::WrapUnique(new SingleReleaseCallback(std::move(cb)));
- }
-
- ~SingleReleaseCallback();
-
- void Run(const gpu::SyncToken& sync_token, bool is_lost);
-
- private:
- explicit SingleReleaseCallback(ReleaseCallback callback);
-
- ReleaseCallback callback_;
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_COMMON_RESOURCES_SINGLE_RELEASE_CALLBACK_H_
diff --git a/chromium/components/viz/common/resources/transferable_resource.h b/chromium/components/viz/common/resources/transferable_resource.h
index 73f1eba844b..8713ea10218 100644
--- a/chromium/components/viz/common/resources/transferable_resource.h
+++ b/chromium/components/viz/common/resources/transferable_resource.h
@@ -19,6 +19,7 @@
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/hdr_metadata.h"
namespace viz {
@@ -91,8 +92,9 @@ struct VIZ_COMMON_EXPORT TransferableResource {
// resources.
gpu::MailboxHolder mailbox_holder;
- // The color space of the pixels in the resource.
+ // The color space and associated mastering of the pixels in the resource.
gfx::ColorSpace color_space;
+ absl::optional<gfx::HDRMetadata> hdr_metadata;
// A gpu resource may be possible to use directly in an overlay if this is
// true.
@@ -107,7 +109,7 @@ struct VIZ_COMMON_EXPORT TransferableResource {
bool read_lock_fences_enabled = false;
// YCbCr info for resources backed by YCbCr Vulkan images.
- base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info;
+ absl::optional<gpu::VulkanYCbCrInfo> ycbcr_info;
#if defined(OS_ANDROID)
// Indicates whether this resource may not be overlayed on Android, since
@@ -130,7 +132,7 @@ struct VIZ_COMMON_EXPORT TransferableResource {
mailbox_holder.mailbox == o.mailbox_holder.mailbox &&
mailbox_holder.sync_token == o.mailbox_holder.sync_token &&
mailbox_holder.texture_target == o.mailbox_holder.texture_target &&
- color_space == o.color_space &&
+ color_space == o.color_space && hdr_metadata == o.hdr_metadata &&
is_overlay_candidate == o.is_overlay_candidate &&
filter == o.filter &&
#if defined(OS_ANDROID)
diff --git a/chromium/components/viz/common/surfaces/frame_sink_id.cc b/chromium/components/viz/common/surfaces/frame_sink_id.cc
index 1cc2a104d14..553d3e68e60 100644
--- a/chromium/components/viz/common/surfaces/frame_sink_id.cc
+++ b/chromium/components/viz/common/surfaces/frame_sink_id.cc
@@ -4,6 +4,7 @@
#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
namespace viz {
@@ -14,7 +15,7 @@ std::string FrameSinkId::ToString() const {
std::string FrameSinkId::ToString(base::StringPiece debug_label) const {
return base::StringPrintf("FrameSinkId[%s](%u, %u)",
- debug_label.as_string().c_str(), client_id_,
+ std::string(debug_label).c_str(), client_id_,
sink_id_);
}
diff --git a/chromium/components/viz/common/surfaces/surface_range.cc b/chromium/components/viz/common/surfaces/surface_range.cc
index 339b36ebe69..e8bdf9a5540 100644
--- a/chromium/components/viz/common/surfaces/surface_range.cc
+++ b/chromium/components/viz/common/surfaces/surface_range.cc
@@ -10,7 +10,7 @@ namespace viz {
SurfaceRange::SurfaceRange() = default;
-SurfaceRange::SurfaceRange(const base::Optional<SurfaceId>& start,
+SurfaceRange::SurfaceRange(const absl::optional<SurfaceId>& start,
const SurfaceId& end)
: start_(start), end_(end) {}
diff --git a/chromium/components/viz/common/surfaces/surface_range.h b/chromium/components/viz/common/surfaces/surface_range.h
index 814849656e0..83aa8984ff5 100644
--- a/chromium/components/viz/common/surfaces/surface_range.h
+++ b/chromium/components/viz/common/surfaces/surface_range.h
@@ -5,10 +5,10 @@
#ifndef COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_RANGE_H_
#define COMPONENTS_VIZ_COMMON_SURFACES_SURFACE_RANGE_H_
-#include "base/optional.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/common/viz_common_export.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace viz {
@@ -23,7 +23,7 @@ class VIZ_COMMON_EXPORT SurfaceRange {
public:
SurfaceRange();
- SurfaceRange(const base::Optional<SurfaceId>& start, const SurfaceId& end);
+ SurfaceRange(const absl::optional<SurfaceId>& start, const SurfaceId& end);
explicit SurfaceRange(const SurfaceId& surface_id);
@@ -53,7 +53,7 @@ class VIZ_COMMON_EXPORT SurfaceRange {
bool IsValid() const;
- const base::Optional<SurfaceId>& start() const { return start_; }
+ const absl::optional<SurfaceId>& start() const { return start_; }
const SurfaceId& end() const { return end_; }
@@ -62,7 +62,7 @@ class VIZ_COMMON_EXPORT SurfaceRange {
private:
friend struct mojo::StructTraits<mojom::SurfaceRangeDataView, SurfaceRange>;
- base::Optional<SurfaceId> start_;
+ absl::optional<SurfaceId> start_;
SurfaceId end_;
};
diff --git a/chromium/components/viz/common/surfaces/surface_range_unittest.cc b/chromium/components/viz/common/surfaces/surface_range_unittest.cc
index 0183644c616..6157f45ec88 100644
--- a/chromium/components/viz/common/surfaces/surface_range_unittest.cc
+++ b/chromium/components/viz/common/surfaces/surface_range_unittest.cc
@@ -21,7 +21,7 @@ TEST(SurfaceRangeTest, InRangeTest) {
viz::LocalSurfaceId(2, 2, token2));
const viz::SurfaceRange surface_range1(start, end);
- const viz::SurfaceRange surface_range2(base::nullopt, end);
+ const viz::SurfaceRange surface_range2(absl::nullopt, end);
const viz::SurfaceRange surface_range1_token2(start, end_token2);
const viz::SurfaceId surface_id1(FrameSink1,
@@ -38,7 +38,7 @@ TEST(SurfaceRangeTest, InRangeTest) {
EXPECT_TRUE(surface_range1.IsInRangeExclusive(surface_id1));
// |surface_id1| has the right embed token and inside the range
- // (base::nullopt,end).
+ // (absl::nullopt,end).
EXPECT_TRUE(surface_range2.IsInRangeExclusive(surface_id1));
// |surface_id2| has an unmatching token.
diff --git a/chromium/components/viz/common/switches.cc b/chromium/components/viz/common/switches.cc
index e5bc2b79e1b..ef1aecec89f 100644
--- a/chromium/components/viz/common/switches.cc
+++ b/chromium/components/viz/common/switches.cc
@@ -68,15 +68,22 @@ const char kRunAllCompositorStagesBeforeDraw[] =
// real damage rect, which could hide damage rect problems.
const char kShowAggregatedDamage[] = "show-aggregated-damage";
+// Modulates the debug compositor tint color so that damage and page flip
+// updates are made clearly visible. This feature was useful in determining the
+// root cause of https://b.corp.google.com/issues/183260320 . The tinting flag
+// "tint-composited-content" must also be enabled for this flag to used.
+const char kTintCompositedContentModulate[] =
+ "tint-composited-content-modulate";
+
// 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";
-base::Optional<uint32_t> GetDeadlineToSynchronizeSurfaces() {
+absl::optional<uint32_t> GetDeadlineToSynchronizeSurfaces() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kRunAllCompositorStagesBeforeDraw)) {
// In full-pipeline mode, surface deadlines should always be unlimited.
- return base::nullopt;
+ return absl::nullopt;
}
std::string deadline_to_synchronize_surfaces_string =
command_line->GetSwitchValueASCII(
@@ -87,7 +94,7 @@ base::Optional<uint32_t> GetDeadlineToSynchronizeSurfaces() {
uint32_t activation_deadline_in_frames;
if (!base::StringToUint(deadline_to_synchronize_surfaces_string,
&activation_deadline_in_frames)) {
- return base::nullopt;
+ return absl::nullopt;
}
return activation_deadline_in_frames;
}
diff --git a/chromium/components/viz/common/switches.h b/chromium/components/viz/common/switches.h
index 3c878a43a0b..cc8c571b9a6 100644
--- a/chromium/components/viz/common/switches.h
+++ b/chromium/components/viz/common/switches.h
@@ -6,11 +6,10 @@
#define COMPONENTS_VIZ_COMMON_SWITCHES_H_
#include <stdint.h>
-#include <string>
-#include "base/optional.h"
#include "build/chromeos_buildflags.h"
#include "components/viz/common/viz_common_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace switches {
@@ -36,6 +35,8 @@ VIZ_COMMON_EXPORT extern const char
VIZ_COMMON_EXPORT extern const char kRunAllCompositorStagesBeforeDraw[];
VIZ_COMMON_EXPORT extern const char kShowAggregatedDamage[];
+VIZ_COMMON_EXPORT extern const char kTintCompositedContentModulate[];
+
// kShowDCLayerDebugBorders shows the debug borders of the overlays and the
// damage rect after using overlays on Windows. Do not use
// kShowDCLayerDebugBorders and kShowAggregatedDamage together because
@@ -43,7 +44,7 @@ VIZ_COMMON_EXPORT extern const char kShowAggregatedDamage[];
// incorrect damage rect borders after using overlays.
VIZ_COMMON_EXPORT extern const char kShowDCLayerDebugBorders[];
-VIZ_COMMON_EXPORT base::Optional<uint32_t> GetDeadlineToSynchronizeSurfaces();
+VIZ_COMMON_EXPORT absl::optional<uint32_t> GetDeadlineToSynchronizeSurfaces();
} // namespace switches
diff --git a/chromium/components/viz/common/transition_utils.cc b/chromium/components/viz/common/transition_utils.cc
new file mode 100644
index 00000000000..f4192743cea
--- /dev/null
+++ b/chromium/components/viz/common/transition_utils.cc
@@ -0,0 +1,99 @@
+// Copyright 2021 The Chromium Authors. 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/transition_utils.h"
+
+#include <vector>
+
+#include "components/viz/common/quads/compositor_render_pass.h"
+#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
+
+namespace viz {
+
+// static
+float TransitionUtils::ComputeAccumulatedOpacity(
+ const CompositorRenderPassList& render_passes,
+ CompositorRenderPassId target_id) {
+ float opacity = 1.f;
+ bool found_render_pass = false;
+ for (auto& render_pass : render_passes) {
+ // If we haven't even reached the needed render pass, then we don't need to
+ // iterate the quads. Note that we also don't iterate the quads of the
+ // target render pass itself, since it can't draw itself.
+ if (!found_render_pass) {
+ found_render_pass = render_pass->id == target_id;
+ continue;
+ }
+
+ for (auto* quad : render_pass->quad_list) {
+ if (quad->material != DrawQuad::Material::kCompositorRenderPass)
+ continue;
+
+ const auto* pass_quad = CompositorRenderPassDrawQuad::MaterialCast(quad);
+ if (pass_quad->render_pass_id != target_id)
+ continue;
+
+ // TODO(vmpstr): We need to consider different blend modes as well,
+ // although it's difficult in general. For the simple case of common
+ // SrcOver blend modes however, we can just multiply the opacity.
+ opacity *= pass_quad->shared_quad_state->opacity;
+ target_id = render_pass->id;
+ break;
+ }
+ }
+ return opacity;
+}
+
+// static
+std::unique_ptr<CompositorRenderPass>
+TransitionUtils::CopyPassWithRenderPassFiltering(
+ const CompositorRenderPass& source_pass,
+ FilterCallback filter_callback) {
+ // This code is similar to CompositorRenderPass::DeepCopy, but does special
+ // logic when copying compositor render pass draw quads.
+ auto copy_pass = CompositorRenderPass::Create(
+ source_pass.shared_quad_state_list.size(), source_pass.quad_list.size());
+
+ copy_pass->SetAll(
+ source_pass.id, source_pass.output_rect, source_pass.damage_rect,
+ source_pass.transform_to_root_target, source_pass.filters,
+ source_pass.backdrop_filters, source_pass.backdrop_filter_bounds,
+ source_pass.subtree_capture_id, source_pass.has_transparent_background,
+ source_pass.cache_render_pass,
+ source_pass.has_damage_from_contributing_content,
+ source_pass.generate_mipmap);
+
+ if (source_pass.shared_quad_state_list.empty())
+ return copy_pass;
+
+ SharedQuadStateList::ConstIterator sqs_iter =
+ source_pass.shared_quad_state_list.begin();
+ SharedQuadState* copy_shared_quad_state =
+ copy_pass->CreateAndAppendSharedQuadState();
+ *copy_shared_quad_state = **sqs_iter;
+
+ for (auto* quad : source_pass.quad_list) {
+ while (quad->shared_quad_state != *sqs_iter) {
+ ++sqs_iter;
+ DCHECK(sqs_iter != source_pass.shared_quad_state_list.end());
+ copy_shared_quad_state = copy_pass->CreateAndAppendSharedQuadState();
+ *copy_shared_quad_state = **sqs_iter;
+ }
+ DCHECK(quad->shared_quad_state == *sqs_iter);
+
+ if (quad->material == DrawQuad::Material::kCompositorRenderPass) {
+ const auto* pass_quad = CompositorRenderPassDrawQuad::MaterialCast(quad);
+ if (!filter_callback.Run(*pass_quad, *copy_pass.get())) {
+ copy_pass->CopyFromAndAppendRenderPassDrawQuad(
+ pass_quad, pass_quad->render_pass_id);
+ }
+ } else {
+ copy_pass->CopyFromAndAppendDrawQuad(quad);
+ }
+ }
+
+ return copy_pass;
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/common/transition_utils.h b/chromium/components/viz/common/transition_utils.h
new file mode 100644
index 00000000000..94e349b2be6
--- /dev/null
+++ b/chromium/components/viz/common/transition_utils.h
@@ -0,0 +1,45 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_COMMON_TRANSITION_UTILS_H_
+#define COMPONENTS_VIZ_COMMON_TRANSITION_UTILS_H_
+
+#include "base/callback_forward.h"
+#include "components/viz/common/quads/compositor_render_pass.h"
+#include "components/viz/common/viz_common_export.h"
+
+namespace viz {
+
+// This class is a collection of utils used by document transition API.
+class VIZ_COMMON_EXPORT TransitionUtils {
+ public:
+ // Computes the opacity value of the given target_id as drawn in the root
+ // render pass. It looks through the chain of CompositorRenderPassDrawQuads to
+ // accumulate this value. Note that it is assumed, and not checked, that the
+ // render pass draw quads use "regular" opacity accumulation (i.e. kSrcOver
+ // blend mode).
+ static float ComputeAccumulatedOpacity(
+ const CompositorRenderPassList& render_passes,
+ CompositorRenderPassId target_id);
+
+ // Creates a deep copy of |source_pass| retaining all state except copy
+ // requests. |filter_callback| is invoked for each render pass draw quad to
+ // let the caller modify the copy of these quads. If the callback returns true
+ // the quad is skipped otherwise it is copied as-is.
+ using FilterCallback =
+ base::RepeatingCallback<bool(const CompositorRenderPassDrawQuad&,
+ CompositorRenderPass&)>;
+ static std::unique_ptr<CompositorRenderPass> CopyPassWithRenderPassFiltering(
+ const CompositorRenderPass& source_pass,
+ FilterCallback filter_callback);
+
+ static CompositorRenderPassId NextRenderPassId(
+ const CompositorRenderPassId& id) {
+ return CompositorRenderPassId(id.GetUnsafeValue() + 1);
+ }
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_COMMON_TRANSITION_UTILS_H_
diff --git a/chromium/components/viz/demo/client/demo_client.cc b/chromium/components/viz/demo/client/demo_client.cc
index 6f255f94524..d47f91f863d 100644
--- a/chromium/components/viz/demo/client/demo_client.cc
+++ b/chromium/components/viz/demo/client/demo_client.cc
@@ -98,14 +98,14 @@ viz::CompositorFrame DemoClient::CreateFrame(const viz::BeginFrameArgs& args) {
viz::SharedQuadState* quad_state =
render_pass->CreateAndAppendSharedQuadState();
- quad_state->SetAll(
- transform,
- /*quad_layer_rect=*/child_bounds,
- /*visible_quad_layer_rect=*/child_bounds,
- /*mask_filter_info=*/gfx::MaskFilterInfo(),
- /*clip_rect=*/gfx::Rect(),
- /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/1.f,
- /*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
+ quad_state->SetAll(transform,
+ /*quad_layer_rect=*/child_bounds,
+ /*visible_layer_rect=*/child_bounds,
+ /*mask_filter_info=*/gfx::MaskFilterInfo(),
+ /*clip_rect=*/absl::nullopt,
+ /*are_contents_opaque=*/false, /*opacity=*/1.f,
+ /*blend_mode=*/SkBlendMode::kSrcOver,
+ /*sorting_context_id=*/0);
viz::SurfaceDrawQuad* embed =
render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
@@ -123,14 +123,14 @@ viz::CompositorFrame DemoClient::CreateFrame(const viz::BeginFrameArgs& args) {
// content-area of the client.
viz::SharedQuadState* quad_state =
render_pass->CreateAndAppendSharedQuadState();
- quad_state->SetAll(
- gfx::Transform(),
- /*quad_layer_rect=*/output_rect,
- /*visible_quad_layer_rect=*/output_rect,
- /*mask_filter_info=*/gfx::MaskFilterInfo(),
- /*clip_rect=*/gfx::Rect(),
- /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/1.f,
- /*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
+ quad_state->SetAll(gfx::Transform(),
+ /*quad_layer_rect=*/output_rect,
+ /*visible_layer_rect=*/output_rect,
+ /*mask_filter_info=*/gfx::MaskFilterInfo(),
+ /*clip_rect=*/absl::nullopt, /*are_contents_opaque=*/false,
+ /*opacity=*/1.f,
+ /*blend_mode=*/SkBlendMode::kSrcOver,
+ /*sorting_context_id=*/0);
viz::SolidColorDrawQuad* color_quad =
render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
@@ -163,7 +163,7 @@ void DemoClient::InitializeOnThread(
}
void DemoClient::DidReceiveCompositorFrameAck(
- const std::vector<viz::ReturnedResource>& resources) {
+ std::vector<viz::ReturnedResource> resources) {
// See documentation in mojom for how this can be used.
}
@@ -176,11 +176,11 @@ void DemoClient::OnBeginFrame(
// deadline for the client before it needs to submit the compositor-frame.
base::AutoLock lock(lock_);
GetPtr()->SubmitCompositorFrame(local_surface_id_, CreateFrame(args),
- base::Optional<viz::HitTestRegionList>(),
+ absl::optional<viz::HitTestRegionList>(),
/*trace_time=*/0);
}
void DemoClient::OnBeginFramePausedChanged(bool paused) {}
void DemoClient::ReclaimResources(
- const std::vector<viz::ReturnedResource>& resources) {}
+ std::vector<viz::ReturnedResource> resources) {}
} // namespace demo
diff --git a/chromium/components/viz/demo/client/demo_client.h b/chromium/components/viz/demo/client/demo_client.h
index 330ea1a7dc9..8e2af0b713e 100644
--- a/chromium/components/viz/demo/client/demo_client.h
+++ b/chromium/components/viz/demo/client/demo_client.h
@@ -96,12 +96,11 @@ class DemoClient : public viz::mojom::CompositorFrameSinkClient {
// viz::mojom::CompositorFrameSinkClient:
void DidReceiveCompositorFrameAck(
- const std::vector<viz::ReturnedResource>& resources) override;
+ std::vector<viz::ReturnedResource> resources) override;
void OnBeginFrame(const viz::BeginFrameArgs& args,
const viz::FrameTimingDetailsMap& timing_details) override;
void OnBeginFramePausedChanged(bool paused) override;
- void ReclaimResources(
- const std::vector<viz::ReturnedResource>& resources) override;
+ void ReclaimResources(std::vector<viz::ReturnedResource> resources) override;
void OnCompositorFrameTransitionDirectiveProcessed(
uint32_t sequence_id) override {}
diff --git a/chromium/components/viz/host/client_frame_sink_video_capturer.cc b/chromium/components/viz/host/client_frame_sink_video_capturer.cc
index 405ec19e02c..8ffb71ad80c 100644
--- a/chromium/components/viz/host/client_frame_sink_video_capturer.cc
+++ b/chromium/components/viz/host/client_frame_sink_video_capturer.cc
@@ -72,7 +72,7 @@ void ClientFrameSinkVideoCapturer::SetAutoThrottlingEnabled(bool enabled) {
}
void ClientFrameSinkVideoCapturer::ChangeTarget(
- const base::Optional<FrameSinkId>& frame_sink_id,
+ const absl::optional<FrameSinkId>& frame_sink_id,
SubtreeCaptureId subtree_capture_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
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 019a5ea02ed..0b5cc507242 100644
--- a/chromium/components/viz/host/client_frame_sink_video_capturer.h
+++ b/chromium/components/viz/host/client_frame_sink_video_capturer.h
@@ -84,7 +84,7 @@ class VIZ_HOST_EXPORT ClientFrameSinkVideoCapturer
const gfx::Size& max_size,
bool use_fixed_aspect_ratio);
void SetAutoThrottlingEnabled(bool enabled);
- void ChangeTarget(const base::Optional<FrameSinkId>& frame_sink_id,
+ void ChangeTarget(const absl::optional<FrameSinkId>& frame_sink_id,
SubtreeCaptureId subtree_capture_id);
void Stop();
void RequestRefreshFrame();
@@ -147,12 +147,12 @@ class VIZ_HOST_EXPORT ClientFrameSinkVideoCapturer
// corresponding method in mojom::FrameSinkVideoCapturer. The arguments are
// saved so we can resend them if viz crashes and a new FrameSinkVideoCapturer
// has to be created.
- base::Optional<Format> format_;
- base::Optional<base::TimeDelta> min_capture_period_;
- base::Optional<base::TimeDelta> min_size_change_period_;
- base::Optional<ResolutionConstraints> resolution_constraints_;
- base::Optional<bool> auto_throttling_enabled_;
- base::Optional<FrameSinkId> target_;
+ absl::optional<Format> format_;
+ absl::optional<base::TimeDelta> min_capture_period_;
+ absl::optional<base::TimeDelta> min_size_change_period_;
+ absl::optional<ResolutionConstraints> resolution_constraints_;
+ absl::optional<bool> auto_throttling_enabled_;
+ absl::optional<FrameSinkId> target_;
SubtreeCaptureId subtree_capture_id_;
// Overlays are owned by the callers of CreateOverlay().
std::vector<Overlay*> overlays_;
diff --git a/chromium/components/viz/host/gpu_client.cc b/chromium/components/viz/host/gpu_client.cc
index 03419bcac1b..8104da3802b 100644
--- a/chromium/components/viz/host/gpu_client.cc
+++ b/chromium/components/viz/host/gpu_client.cc
@@ -24,6 +24,7 @@ bool IsSizeValid(const gfx::Size& size) {
bytes *= size.height();
return bytes.IsValid();
}
+
} // namespace
GpuClient::GpuClient(std::unique_ptr<GpuClientDelegate> delegate,
@@ -93,7 +94,6 @@ void GpuClient::OnEstablishGpuChannel(
status == GpuHostImpl::EstablishChannelStatus::kSuccess);
gpu_channel_requested_ = false;
EstablishGpuChannelCallback callback = std::move(callback_);
- DCHECK(!callback_);
if (status == GpuHostImpl::EstablishChannelStatus::kGpuHostInvalid) {
// GPU process may have crashed or been killed. Try again.
@@ -126,7 +126,6 @@ void GpuClient::ClearCallback() {
EstablishGpuChannelCallback callback = std::move(callback_);
std::move(callback).Run(client_id_, mojo::ScopedMessagePipeHandle(),
gpu::GPUInfo(), gpu::GpuFeatureInfo());
- DCHECK(!callback_);
}
void GpuClient::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
@@ -162,7 +161,7 @@ void GpuClient::EstablishGpuChannel(EstablishGpuChannelCallback callback) {
gpu_channel_requested_ = true;
const bool is_gpu_host = false;
gpu_host->EstablishGpuChannel(
- client_id_, client_tracing_id_, is_gpu_host,
+ client_id_, client_tracing_id_, is_gpu_host, false,
base::BindOnce(&GpuClient::OnEstablishGpuChannel,
weak_factory_.GetWeakPtr()));
}
diff --git a/chromium/components/viz/host/gpu_client.h b/chromium/components/viz/host/gpu_client.h
index 6571632f9d2..108b13f8340 100644
--- a/chromium/components/viz/host/gpu_client.h
+++ b/chromium/components/viz/host/gpu_client.h
@@ -98,9 +98,9 @@ class VIZ_HOST_EXPORT GpuClient : public mojom::GpuMemoryBufferFactory,
gpu::GPUInfo gpu_info_;
gpu::GpuFeatureInfo gpu_feature_info_;
ConnectionErrorHandlerClosure connection_error_handler_;
- // |task_runner_| is associated with the thread |gpu_bindings_| is bound on.
- // GpuClient instance is bound to this thread, and must be destroyed on this
- // thread.
+ // |task_runner_| is associated with the thread |gpu_bindings_| is bound
+ // on. GpuClient instance is bound to this thread, and must be destroyed on
+ // this thread.
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::WeakPtrFactory<GpuClient> weak_factory_{this};
diff --git a/chromium/components/viz/host/gpu_client_delegate.h b/chromium/components/viz/host/gpu_client_delegate.h
index 19f08b2a1e1..c12d4ef5210 100644
--- a/chromium/components/viz/host/gpu_client_delegate.h
+++ b/chromium/components/viz/host/gpu_client_delegate.h
@@ -5,7 +5,6 @@
#ifndef COMPONENTS_VIZ_HOST_GPU_CLIENT_DELEGATE_H_
#define COMPONENTS_VIZ_HOST_GPU_CLIENT_DELEGATE_H_
-#include "base/callback_forward.h"
#include "mojo/public/cpp/system/message_pipe.h"
namespace viz {
diff --git a/chromium/components/viz/host/gpu_host_impl.cc b/chromium/components/viz/host/gpu_host_impl.cc
index 22e1a08be64..0bcd6213c6e 100644
--- a/chromium/components/viz/host/gpu_host_impl.cc
+++ b/chromium/components/viz/host/gpu_host_impl.cc
@@ -14,6 +14,7 @@
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "components/viz/common/features.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
@@ -22,6 +23,7 @@
#include "gpu/config/gpu_info.h"
#include "gpu/ipc/common/gpu_client_ids.h"
#include "gpu/ipc/host/shader_disk_cache.h"
+#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/font_render_params.h"
@@ -31,6 +33,8 @@
#if defined(OS_WIN)
#include "ui/gfx/win/rendering_window_manager.h"
+#elif defined(OS_MAC)
+#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#endif
#if defined(USE_OZONE)
@@ -47,7 +51,7 @@ class FontRenderParams {
public:
void Set(const gfx::FontRenderParams& params);
void Reset();
- const base::Optional<gfx::FontRenderParams>& Get();
+ const absl::optional<gfx::FontRenderParams>& Get();
private:
friend class base::NoDestructor<FontRenderParams>;
@@ -56,7 +60,7 @@ class FontRenderParams {
~FontRenderParams();
THREAD_CHECKER(thread_checker_);
- base::Optional<gfx::FontRenderParams> params_;
+ absl::optional<gfx::FontRenderParams> params_;
DISALLOW_COPY_AND_ASSIGN(FontRenderParams);
};
@@ -68,10 +72,10 @@ void FontRenderParams::Set(const gfx::FontRenderParams& params) {
void FontRenderParams::Reset() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- params_ = base::nullopt;
+ params_ = absl::nullopt;
}
-const base::Optional<gfx::FontRenderParams>& FontRenderParams::Get() {
+const absl::optional<gfx::FontRenderParams>& FontRenderParams::Get() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
return params_;
}
@@ -120,11 +124,17 @@ GpuHostImpl::GpuHostImpl(Delegate* delegate,
discardable_manager_remote.InitWithNewPipeAndPassReceiver());
DCHECK(GetFontRenderParams().Get());
- viz_main_->CreateGpuService(gpu_service_remote_.BindNewPipeAndPassReceiver(),
- gpu_host_receiver_.BindNewPipeAndPassRemote(),
- std::move(discardable_manager_remote),
- activity_flags_.CloneHandle(),
- GetFontRenderParams().Get()->subpixel_rendering);
+ scoped_refptr<base::SequencedTaskRunner> task_runner = nullptr;
+#if defined(OS_MAC)
+ if (params_.main_thread_task_runner->BelongsToCurrentThread())
+ task_runner = ui::WindowResizeHelperMac::Get()->task_runner();
+#endif
+
+ viz_main_->CreateGpuService(
+ gpu_service_remote_.BindNewPipeAndPassReceiver(task_runner),
+ gpu_host_receiver_.BindNewPipeAndPassRemote(task_runner),
+ std::move(discardable_manager_remote), activity_flags_.CloneHandle(),
+ GetFontRenderParams().Get()->subpixel_rendering);
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform())
@@ -217,6 +227,7 @@ void GpuHostImpl::ConnectVizDevTools(mojom::VizDevToolsParamsPtr params) {
void GpuHostImpl::EstablishGpuChannel(int client_id,
uint64_t client_tracing_id,
bool is_gpu_host,
+ bool sync,
EstablishChannelCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_EVENT0("gpu", "GpuHostImpl::EstablishGpuChannel");
@@ -244,16 +255,52 @@ void GpuHostImpl::EstablishGpuChannel(int client_id,
bool cache_shaders_on_disk =
delegate_->GetShaderCacheFactory()->Get(client_id) != nullptr;
- channel_requests_.push(std::move(callback));
- gpu_service_remote_->EstablishGpuChannel(
- client_id, client_tracing_id, is_gpu_host, cache_shaders_on_disk,
- base::BindOnce(&GpuHostImpl::OnChannelEstablished,
- weak_ptr_factory_.GetWeakPtr(), client_id));
+ channel_requests_[client_id] = std::move(callback);
+ if (sync) {
+ mojo::ScopedMessagePipeHandle channel_handle;
+ gpu::GPUInfo gpu_info;
+ gpu::GpuFeatureInfo gpu_feature_info;
+ {
+ mojo::SyncCallRestrictions::ScopedAllowSyncCall scoped_allow;
+ gpu_service_remote_->EstablishGpuChannel(
+ client_id, client_tracing_id, is_gpu_host, cache_shaders_on_disk,
+ &channel_handle, &gpu_info, &gpu_feature_info);
+ }
+ OnChannelEstablished(client_id, true, std::move(channel_handle), gpu_info,
+ gpu_feature_info);
+ } else {
+ gpu_service_remote_->EstablishGpuChannel(
+ client_id, client_tracing_id, is_gpu_host, cache_shaders_on_disk,
+ base::BindOnce(&GpuHostImpl::OnChannelEstablished,
+ weak_ptr_factory_.GetWeakPtr(), client_id, false));
+ }
if (!params_.disable_gpu_shader_disk_cache)
CreateChannelCache(client_id);
}
+void GpuHostImpl::CloseChannel(int client_id) {
+ gpu_service_remote_->CloseChannel(client_id);
+
+ channel_requests_.erase(client_id);
+}
+#if BUILDFLAG(USE_VIZ_DEBUGGER)
+void GpuHostImpl::FilterVisualDebugStream(base::Value json) {
+ viz_main_->FilterDebugStream(std::move(json));
+}
+
+void GpuHostImpl::StartVisualDebugStream(
+ base::RepeatingCallback<void(base::Value)> callback) {
+ viz_debug_output_callback_ = std::move(callback);
+ viz_main_->StartDebugStream(viz_debug_output_.BindNewPipeAndPassRemote());
+}
+
+void GpuHostImpl::StopVisualDebugStream() {
+ viz_main_->StopDebugStream();
+ viz_debug_output_.reset();
+}
+#endif
+
void GpuHostImpl::SendOutstandingReplies() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -262,13 +309,12 @@ void GpuHostImpl::SendOutstandingReplies() {
connection_error_handlers_.clear();
// Send empty channel handles for all EstablishChannel requests.
- while (!channel_requests_.empty()) {
- auto callback = std::move(channel_requests_.front());
- channel_requests_.pop();
- std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
- gpu::GpuFeatureInfo(),
- EstablishChannelStatus::kGpuHostInvalid);
+ for (auto& entry : channel_requests_) {
+ std::move(entry.second)
+ .Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
+ gpu::GpuFeatureInfo(), EstablishChannelStatus::kGpuHostInvalid);
}
+ channel_requests_.clear();
}
void GpuHostImpl::BindInterface(const std::string& interface_name,
@@ -371,13 +417,19 @@ void GpuHostImpl::CreateChannelCache(int32_t client_id) {
void GpuHostImpl::OnChannelEstablished(
int client_id,
- mojo::ScopedMessagePipeHandle channel_handle) {
+ bool sync,
+ mojo::ScopedMessagePipeHandle channel_handle,
+ const gpu::GPUInfo& gpu_info,
+ const gpu::GpuFeatureInfo& gpu_feature_info) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
TRACE_EVENT0("gpu", "GpuHostImpl::OnChannelEstablished");
- DCHECK(!channel_requests_.empty());
- auto callback = std::move(channel_requests_.front());
- channel_requests_.pop();
+ auto it = channel_requests_.find(client_id);
+ if (it == channel_requests_.end())
+ return;
+
+ auto callback = std::move(it->second);
+ channel_requests_.erase(it);
// Currently if any of the GPU features are blocklisted, we don't establish a
// GPU channel.
@@ -391,16 +443,26 @@ void GpuHostImpl::OnChannelEstablished(
return;
}
- std::move(callback).Run(std::move(channel_handle), delegate_->GetGPUInfo(),
- delegate_->GetGpuFeatureInfo(),
- EstablishChannelStatus::kSuccess);
+ // TODO(jam): always use GPUInfo & GpuFeatureInfo from the service once we
+ // know there's no issue with the ProcessHostOnUI which is the only mode
+ // that currently uses it. This is because in that mode the sync mojo call
+ // in the caller means we won't get the async DidInitialize() call before
+ // this point, so the delegate_ methods won't have the GPU info structs yet.
+ if (sync) {
+ std::move(callback).Run(std::move(channel_handle), gpu_info,
+ gpu_feature_info, EstablishChannelStatus::kSuccess);
+ } else {
+ std::move(callback).Run(std::move(channel_handle), delegate_->GetGPUInfo(),
+ delegate_->GetGpuFeatureInfo(),
+ EstablishChannelStatus::kSuccess);
+ }
}
void GpuHostImpl::DidInitialize(
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
- const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
- const base::Optional<gpu::GpuFeatureInfo>&
+ const absl::optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
+ const absl::optional<gpu::GpuFeatureInfo>&
gpu_feature_info_for_hardware_gpu,
const gfx::GpuExtraInfo& gpu_extra_info) {
UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", true);
@@ -408,9 +470,6 @@ void GpuHostImpl::DidInitialize(
// Set GPU driver bug workaround flags that are checked on the browser side.
wake_up_gpu_before_drawing_ =
gpu_feature_info.IsWorkaroundEnabled(gpu::WAKE_UP_GPU_BEFORE_DRAWING);
- dont_disable_webgl_when_compositor_context_lost_ =
- gpu_feature_info.IsWorkaroundEnabled(
- gpu::DONT_DISABLE_WEBGL_WHEN_COMPOSITOR_CONTEXT_LOST);
delegate_->DidInitialize(gpu_info, gpu_feature_info,
gpu_info_for_hardware_gpu,
@@ -547,4 +606,11 @@ void GpuHostImpl::RecordLogMessage(int32_t severity,
delegate_->RecordLogMessage(severity, header, message);
}
+#if BUILDFLAG(USE_VIZ_DEBUGGER)
+void GpuHostImpl::LogFrame(base::Value frame_data) {
+ if (!viz_debug_output_callback_.is_null())
+ viz_debug_output_callback_.Run(std::move(frame_data));
+}
+#endif
+
} // namespace viz
diff --git a/chromium/components/viz/host/gpu_host_impl.h b/chromium/components/viz/host/gpu_host_impl.h
index 2406f890431..ab02526fdec 100644
--- a/chromium/components/viz/host/gpu_host_impl.h
+++ b/chromium/components/viz/host/gpu_host_impl.h
@@ -12,16 +12,18 @@
#include <vector>
#include "base/callback.h"
+#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/process/process_handle.h"
#include "base/sequence_checker.h"
#include "base/timer/timer.h"
+#include "base/values.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/common/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"
@@ -35,6 +37,7 @@
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/gpu_extra_info.h"
#include "url/gurl.h"
@@ -53,7 +56,12 @@ class ShaderDiskCache;
namespace viz {
-class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
+class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost
+#if BUILDFLAG(USE_VIZ_DEBUGGER)
+ ,
+ public mojom::VizDebugOutput
+#endif
+{
public:
class VIZ_HOST_EXPORT Delegate {
public:
@@ -62,8 +70,8 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
virtual void DidInitialize(
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
- const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
- const base::Optional<gpu::GpuFeatureInfo>&
+ const absl::optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
+ const absl::optional<gpu::GpuFeatureInfo>&
gpu_feature_info_for_hardware_gpu,
const gfx::GpuExtraInfo& gpu_extra_info) = 0;
virtual void DidFailInitialize() = 0;
@@ -113,7 +121,7 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
std::string product;
// Number of frames to CompositorFrame activation deadline.
- base::Optional<uint32_t> deadline_to_synchronize_surfaces;
+ absl::optional<uint32_t> deadline_to_synchronize_surfaces;
// Task runner corresponding to the main thread.
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner;
@@ -165,11 +173,28 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
// Tells the GPU service to create a new channel for communication with a
// client. Once the GPU service responds asynchronously with the channel
- // handle and GPUInfo, we call the callback.
+ // handle and GPUInfo, we call the callback. If |sync| is true then the
+ // callback will be run before this method returns, and note that the
+ // browser GPU info data might not be initialized as well.
void EstablishGpuChannel(int client_id,
uint64_t client_tracing_id,
bool is_gpu_host,
+ bool sync,
EstablishChannelCallback callback);
+ void CloseChannel(int client_id);
+
+#if BUILDFLAG(USE_VIZ_DEBUGGER)
+ // Command as a Json string that the visual debugging instance interprets as
+ // stream filtering.
+ void FilterVisualDebugStream(base::Value filter_data);
+
+ // Establishes the connection between the visual debugging instance and the
+ // output stream.
+ void StartVisualDebugStream(
+ base::RepeatingCallback<void(base::Value)> callback);
+
+ void StopVisualDebugStream();
+#endif
void SendOutstandingReplies();
@@ -203,15 +228,18 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
void CreateChannelCache(int32_t client_id);
void OnChannelEstablished(int client_id,
- mojo::ScopedMessagePipeHandle channel_handle);
+ bool sync,
+ mojo::ScopedMessagePipeHandle channel_handle,
+ const gpu::GPUInfo& gpu_info,
+ const gpu::GpuFeatureInfo& gpu_feature_info);
void MaybeShutdownGpuProcess();
// mojom::GpuHost:
void DidInitialize(
const gpu::GPUInfo& gpu_info,
const gpu::GpuFeatureInfo& gpu_feature_info,
- const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
- const base::Optional<gpu::GpuFeatureInfo>&
+ const absl::optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
+ const absl::optional<gpu::GpuFeatureInfo>&
gpu_feature_info_for_hardware_gpu,
const gfx::GpuExtraInfo& gpu_extra_info) override;
void DidFailInitialize() override;
@@ -238,6 +266,11 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
const std::string& header,
const std::string& message) override;
+ // Implements mojom::VizDebugOutput and is called by VizDebugger.
+#if BUILDFLAG(USE_VIZ_DEBUGGER)
+ void LogFrame(base::Value frame_data) override;
+#endif
+
Delegate* const delegate_;
mojo::Remote<mojom::VizMain> viz_main_;
const InitParams params_;
@@ -253,6 +286,11 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
mojo::Receiver<mojom::GpuHost> gpu_host_receiver_{this};
gpu::GpuProcessHostActivityFlags activity_flags_;
+#if BUILDFLAG(USE_VIZ_DEBUGGER)
+ mojo::Receiver<mojom::VizDebugOutput> viz_debug_output_{this};
+ base::RepeatingCallback<void(base::Value)> viz_debug_output_callback_;
+#endif
+
base::ProcessId pid_ = base::kNullProcessId;
// List of connection error handlers for the GpuService.
@@ -262,7 +300,6 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
// set to true in DidInitialize(), where GPU service has started and GPU
// driver bug workarounds have been computed and sent back.
bool wake_up_gpu_before_drawing_ = false;
- bool dont_disable_webgl_when_compositor_context_lost_ = false;
// Track the URLs of the pages which have live offscreen contexts, assumed to
// be associated with untrusted content such as WebGL. For best robustness,
@@ -276,7 +313,7 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
// These are the channel requests that we have already sent to the GPU
// service, but haven't heard back about yet.
- base::queue<EstablishChannelCallback> channel_requests_;
+ base::flat_map<int, EstablishChannelCallback> channel_requests_;
base::OneShotTimer shutdown_timeout_;
diff --git a/chromium/components/viz/host/host_frame_sink_manager.h b/chromium/components/viz/host/host_frame_sink_manager.h
index 0d6f45921f1..e58ad927268 100644
--- a/chromium/components/viz/host/host_frame_sink_manager.h
+++ b/chromium/components/viz/host/host_frame_sink_manager.h
@@ -16,7 +16,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/host/client_frame_sink_video_capturer.h"
@@ -29,6 +28,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class SingleThreadTaskRunner;
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 26f2c3259c8..f9cad838901 100644
--- a/chromium/components/viz/host/host_frame_sink_manager_unittest.cc
+++ b/chromium/components/viz/host/host_frame_sink_manager_unittest.cc
@@ -42,6 +42,7 @@ struct RootCompositorFrameSinkData {
mojom::RootCompositorFrameSinkParamsPtr BuildParams(
const FrameSinkId& frame_sink_id) {
auto params = mojom::RootCompositorFrameSinkParams::New();
+ params->gpu_compositing = false;
params->frame_sink_id = frame_sink_id;
params->widget = gpu::kNullSurfaceHandle;
params->compositor_frame_sink =
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 ee69ec8e6f3..b73fecf2dd3 100644
--- a/chromium/components/viz/host/host_gpu_memory_buffer_manager.cc
+++ b/chromium/components/viz/host/host_gpu_memory_buffer_manager.cc
@@ -14,6 +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 "mojo/public/cpp/bindings/sync_call_restrictions.h"
#include "services/viz/privileged/mojom/gl/gpu_service.mojom.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/buffer_format_util.h"
@@ -72,11 +73,12 @@ HostGpuMemoryBufferManager::HostGpuMemoryBufferManager(
client_id_(client_id),
gpu_memory_buffer_support_(std::move(gpu_memory_buffer_support)),
pool_(base::MakeRefCounted<base::UnsafeSharedMemoryPool>()),
+ runs_on_ui_thread_(task_runner->BelongsToCurrentThread()),
task_runner_(std::move(task_runner)) {
if (!WillGetGmbConfigFromGpu()) {
native_configurations_ = gpu::GetNativeGpuMemoryBufferConfigurations(
gpu_memory_buffer_support_.get());
- native_configurations_initialized_.Signal();
+ native_configurations_initialized_.Set();
}
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
this, "HostGpuMemoryBufferManager", task_runner_);
@@ -142,13 +144,12 @@ void HostGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
gfx::BufferFormat format,
gfx::BufferUsage usage,
gpu::SurfaceHandle surface_handle,
- base::OnceCallback<void(gfx::GpuMemoryBufferHandle)> callback) {
+ base::OnceCallback<void(gfx::GpuMemoryBufferHandle)> callback,
+ bool call_sync) {
DCHECK(task_runner_->BelongsToCurrentThread());
if (!weak_ptr_)
weak_ptr_ = weak_factory_.GetWeakPtr();
- if (gpu_memory_buffer_support_->GetNativeGpuMemoryBufferType() !=
- gfx::EMPTY_BUFFER &&
- IsNativeGpuMemoryBufferConfiguration(format, usage)) {
+ if (CreateBufferUsesGpuService(format, usage)) {
if (auto* gpu_service = GetGpuService()) {
PendingBufferInfo buffer_info;
buffer_info.size = size;
@@ -158,11 +159,23 @@ void HostGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
buffer_info.callback = std::move(callback);
pending_buffers_[client_id].insert(
std::make_pair(id, std::move(buffer_info)));
- gpu_service->CreateGpuMemoryBuffer(
- id, size, format, usage, client_id, surface_handle,
- base::BindOnce(
- &HostGpuMemoryBufferManager::OnGpuMemoryBufferAllocated,
- weak_ptr_, gpu_service_version_, client_id, id));
+ if (call_sync) {
+ DCHECK(runs_on_ui_thread_);
+ gfx::GpuMemoryBufferHandle handle;
+ {
+ mojo::SyncCallRestrictions::ScopedAllowSyncCall scoped_allow;
+ gpu_service->CreateGpuMemoryBuffer(id, size, format, usage, client_id,
+ surface_handle, &handle);
+ }
+ OnGpuMemoryBufferAllocated(gpu_service_version_, client_id, id,
+ std::move(handle));
+ } else {
+ gpu_service->CreateGpuMemoryBuffer(
+ id, size, format, usage, client_id, surface_handle,
+ base::BindOnce(
+ &HostGpuMemoryBufferManager::OnGpuMemoryBufferAllocated,
+ weak_ptr_, gpu_service_version_, client_id, id));
+ }
} else {
// GPU service failed to start. Run the callback with null handle.
std::move(callback).Run(gfx::GpuMemoryBufferHandle());
@@ -184,17 +197,21 @@ void HostGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
std::make_pair(buffer_handle.id, buffer_info));
}
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), std::move(buffer_handle)));
+ if (call_sync) {
+ std::move(callback).Run(std::move(buffer_handle));
+ } else {
+ task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback),
+ std::move(buffer_handle)));
+ }
}
bool HostGpuMemoryBufferManager::IsNativeGpuMemoryBufferConfiguration(
gfx::BufferFormat format,
gfx::BufferUsage usage) const {
- DCHECK(task_runner_->BelongsToCurrentThread());
- {
- base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
- native_configurations_initialized_.Wait();
+ if (WillGetGmbConfigFromGpu()) {
+ DCHECK(native_configurations_initialized_.IsSet())
+ << "On X11 this must have waited for GPU initialization to complete "
+ << "before knowing that GpuMemoryBuffers can be used.";
}
return native_configurations_.find(gfx::BufferUsageAndFormat(
usage, format)) != native_configurations_.end();
@@ -205,30 +222,62 @@ HostGpuMemoryBufferManager::CreateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle) {
+ gpu::SurfaceHandle surface_handle,
+ base::WaitableEvent* shutdown_event) {
gfx::GpuMemoryBufferId id(next_gpu_memory_id_++);
gfx::GpuMemoryBufferHandle handle;
base::WaitableEvent wait_event(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
- DCHECK(!task_runner_->BelongsToCurrentThread());
+ DCHECK(runs_on_ui_thread_ || !task_runner_->BelongsToCurrentThread());
+ bool call_sync = runs_on_ui_thread_ && task_runner_->BelongsToCurrentThread();
+
+ // A refcounted wrapper around a bool so that if the thread waiting on a
+ // PostTask to the main thread is quit due to shutdown and the task runs
+ // later on the message loop, it can detect this and not use the
+ // now deleted |handle| and |wait_event|. A boolean is fine since if it
+ // is set on the worker thread that means the main thread is blocked, and
+ // would only run once the worker thread set the boolean.
+ auto cancelled = base::MakeRefCounted<base::RefCountedData<bool>>(false);
+
auto reply_callback = base::BindOnce(
- [](gfx::GpuMemoryBufferHandle* handle, base::WaitableEvent* wait_event,
+ [](scoped_refptr<base::RefCountedData<bool>> cancelled,
+ gfx::GpuMemoryBufferHandle* handle, base::WaitableEvent* wait_event,
gfx::GpuMemoryBufferHandle allocated_buffer_handle) {
+ if (cancelled->data)
+ return;
*handle = std::move(allocated_buffer_handle);
wait_event->Signal();
},
- &handle, &wait_event);
+ cancelled, &handle, &wait_event);
// We block with a WaitableEvent until the callback is run. So using
// base::Unretained() is safe here.
- auto allocate_callback =
- base::BindOnce(&HostGpuMemoryBufferManager::AllocateGpuMemoryBuffer,
- base::Unretained(this), id, client_id_, size, format,
- usage, surface_handle, std::move(reply_callback));
- task_runner_->PostTask(FROM_HERE, std::move(allocate_callback));
- base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
- allow_base_sync_primitives;
- wait_event.Wait();
+ auto allocate_callback = base::BindOnce(
+ &HostGpuMemoryBufferManager::AllocateGpuMemoryBuffer,
+ base::Unretained(this), id, client_id_, size, format, usage,
+ surface_handle, std::move(reply_callback), call_sync);
+ if (call_sync) {
+ std::move(allocate_callback).Run();
+ } else {
+ task_runner_->PostTask(FROM_HERE, std::move(allocate_callback));
+ base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
+ allow_base_sync_primitives;
+ if (runs_on_ui_thread_ && shutdown_event) {
+ // If this class is running on the UI thread then
+ // TileManager::FinishTasksAndCleanUp could block on the worker thread
+ // where this task is running. That could in turn block on a task posted
+ // to the UI thread. We avoid this deadlock by having an event that
+ // TileManager can set to cancel this wait.
+ base::WaitableEvent* waitables[] = {&wait_event, shutdown_event};
+ size_t index =
+ base::WaitableEvent::WaitMany(waitables, base::size(waitables));
+ if (index == 1)
+ cancelled->data = true;
+ } else {
+ wait_event.Wait();
+ }
+ }
+
if (handle.is_null())
return nullptr;
// The destruction callback can be called on any thread. So use an
@@ -289,14 +338,12 @@ bool HostGpuMemoryBufferManager::OnMemoryDump(
void HostGpuMemoryBufferManager::SetNativeConfigurations(
gpu::GpuMemoryBufferConfigurationSet native_configurations) {
- // Must not be done on the task runner thread to avoid deadlock.
- DCHECK(!task_runner_->BelongsToCurrentThread());
- if (native_configurations_initialized_.IsSignaled()) {
+ if (native_configurations_initialized_.IsSet()) {
// The configurations are set on GPU initialization and should not change.
DCHECK(native_configurations_ == native_configurations);
} else {
native_configurations_ = native_configurations;
- native_configurations_initialized_.Signal();
+ native_configurations_initialized_.Set();
}
}
@@ -374,7 +421,6 @@ void HostGpuMemoryBufferManager::OnGpuMemoryBufferAllocated(
// callback is already called with null handle.
if (!handle.is_null()) {
auto* gpu_service = GetGpuService();
- DCHECK(gpu_service);
gpu_service->DestroyGpuMemoryBuffer(handle.id, client_id,
gpu::SyncToken());
}
@@ -382,7 +428,17 @@ void HostGpuMemoryBufferManager::OnGpuMemoryBufferAllocated(
}
auto buffer_iter = client_iter->second.find(id);
- DCHECK(buffer_iter != client_iter->second.end());
+ if (buffer_iter == client_iter->second.end()) {
+ if (!handle.is_null()) {
+ // DestroyGpuMemoryBuffer for client_id was called followed by an
+ // AllocateGpuMemoryBuffer for a new id.
+ auto* gpu_service = GetGpuService();
+ gpu_service->DestroyGpuMemoryBuffer(handle.id, client_id,
+ gpu::SyncToken());
+ }
+ return;
+ }
+
PendingBufferInfo pending_buffer = std::move(buffer_iter->second);
client_iter->second.erase(buffer_iter);
@@ -396,4 +452,12 @@ void HostGpuMemoryBufferManager::OnGpuMemoryBufferAllocated(
std::move(pending_buffer.callback).Run(std::move(handle));
}
+bool HostGpuMemoryBufferManager::CreateBufferUsesGpuService(
+ gfx::BufferFormat format,
+ gfx::BufferUsage usage) {
+ return gpu_memory_buffer_support_->GetNativeGpuMemoryBufferType() !=
+ gfx::EMPTY_BUFFER &&
+ IsNativeGpuMemoryBufferConfiguration(format, usage);
+}
+
} // namespace viz
diff --git a/chromium/components/viz/host/host_gpu_memory_buffer_manager.h b/chromium/components/viz/host/host_gpu_memory_buffer_manager.h
index ff251eb8953..9de38d4979f 100644
--- a/chromium/components/viz/host/host_gpu_memory_buffer_manager.h
+++ b/chromium/components/viz/host/host_gpu_memory_buffer_manager.h
@@ -14,6 +14,7 @@
#include "base/memory/unsafe_shared_memory_pool.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "base/synchronization/atomic_flag.h"
#include "base/synchronization/waitable_event.h"
#include "base/trace_event/memory_dump_provider.h"
#include "components/viz/host/viz_host_export.h"
@@ -68,9 +69,9 @@ class VIZ_HOST_EXPORT HostGpuMemoryBufferManager
gfx::BufferFormat format,
gfx::BufferUsage usage,
gpu::SurfaceHandle surface_handle,
- base::OnceCallback<void(gfx::GpuMemoryBufferHandle)> callback);
+ base::OnceCallback<void(gfx::GpuMemoryBufferHandle)> callback,
+ bool call_sync = false);
- // This method will block until the initial GPUInfo is received.
bool IsNativeGpuMemoryBufferConfiguration(gfx::BufferFormat format,
gfx::BufferUsage usage) const;
@@ -79,7 +80,8 @@ class VIZ_HOST_EXPORT HostGpuMemoryBufferManager
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle) override;
+ gpu::SurfaceHandle surface_handle,
+ base::WaitableEvent* shutdown_event) override;
void SetDestructionSyncToken(gfx::GpuMemoryBuffer* buffer,
const gpu::SyncToken& sync_token) override;
void CopyGpuMemoryBufferAsync(
@@ -95,7 +97,6 @@ class VIZ_HOST_EXPORT HostGpuMemoryBufferManager
base::trace_event::ProcessMemoryDump* pmd) override;
protected:
- // Must be called from a thread other than |task_runner_|'s thread.
void SetNativeConfigurations(
gpu::GpuMemoryBufferConfigurationSet native_configurations);
@@ -135,6 +136,9 @@ class VIZ_HOST_EXPORT HostGpuMemoryBufferManager
gfx::GpuMemoryBufferId id,
gfx::GpuMemoryBufferHandle handle);
+ bool CreateBufferUsesGpuService(gfx::BufferFormat format,
+ gfx::BufferUsage usage);
+
GpuServiceProvider gpu_service_provider_;
mojom::GpuService* gpu_service_ = nullptr;
@@ -153,7 +157,9 @@ class VIZ_HOST_EXPORT HostGpuMemoryBufferManager
scoped_refptr<base::UnsafeSharedMemoryPool> pool_;
gpu::GpuMemoryBufferConfigurationSet native_configurations_;
- mutable base::WaitableEvent native_configurations_initialized_;
+ base::AtomicFlag native_configurations_initialized_;
+
+ const bool runs_on_ui_thread_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::WeakPtr<HostGpuMemoryBufferManager> weak_ptr_;
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 127bf0a34a0..996fd0e76a7 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
@@ -222,8 +222,6 @@ class TestGpuService : public mojom::GpuService {
void ThrowJavaException() override {}
- void Stop(StopCallback callback) override {}
-
private:
base::OnceClosure connection_error_handler_;
@@ -261,7 +259,7 @@ class HostGpuMemoryBufferManagerTest : public ::testing::Test {
std::move(gpu_memory_buffer_support),
base::ThreadTaskRunnerHandle::Get());
if (MustSignalGmbConfigReadyForTest())
- gpu_memory_buffer_manager_->native_configurations_initialized_.Signal();
+ gpu_memory_buffer_manager_->native_configurations_initialized_.Set();
}
// Not all platforms support native configurations (currently only Windows,
@@ -295,18 +293,17 @@ class HostGpuMemoryBufferManagerTest : public ::testing::Test {
std::unique_ptr<gfx::GpuMemoryBuffer> buffer;
base::RunLoop run_loop;
diff_thread.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(
- [](HostGpuMemoryBufferManager* manager,
- std::unique_ptr<gfx::GpuMemoryBuffer>* out_buffer,
- base::OnceClosure callback) {
- *out_buffer = manager->CreateGpuMemoryBuffer(
- gfx::Size(64, 64), gfx::BufferFormat::YVU_420,
- gfx::BufferUsage::GPU_READ,
- gpu::kNullSurfaceHandle);
- std::move(callback).Run();
- },
- gpu_memory_buffer_manager_.get(), &buffer,
- run_loop.QuitClosure()));
+ FROM_HERE,
+ base::BindOnce(
+ [](HostGpuMemoryBufferManager* manager,
+ std::unique_ptr<gfx::GpuMemoryBuffer>* out_buffer,
+ base::OnceClosure callback) {
+ *out_buffer = manager->CreateGpuMemoryBuffer(
+ gfx::Size(64, 64), gfx::BufferFormat::YVU_420,
+ gfx::BufferUsage::GPU_READ, gpu::kNullSurfaceHandle, nullptr);
+ std::move(callback).Run();
+ },
+ gpu_memory_buffer_manager_.get(), &buffer, run_loop.QuitClosure()));
run_loop.Run();
return buffer;
}
diff --git a/chromium/components/viz/host/renderer_settings_creation.cc b/chromium/components/viz/host/renderer_settings_creation.cc
index 4dbfd138a46..f919df4d79a 100644
--- a/chromium/components/viz/host/renderer_settings_creation.cc
+++ b/chromium/components/viz/host/renderer_settings_creation.cc
@@ -56,6 +56,13 @@ RendererSettings CreateRendererSettings() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
renderer_settings.partial_swap_enabled =
!command_line->HasSwitch(switches::kUIDisablePartialSwap);
+
+#if defined(OS_APPLE) || defined(OS_LINUX)
+ // Simple frame rate throttling only works on macOS and Linux
+ renderer_settings.apply_simple_frame_rate_throttling =
+ features::IsSimpleFrameRateThrottlingEnabled();
+#endif
+
#if defined(OS_APPLE)
renderer_settings.release_overlay_resources_after_gpu_query = true;
renderer_settings.auto_resize_output_surface = false;
@@ -105,6 +112,8 @@ DebugRendererSettings CreateDefaultDebugRendererSettings() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
result.tint_composited_content =
command_line->HasSwitch(switches::kTintCompositedContent);
+ result.tint_composited_content_modulate =
+ command_line->HasSwitch(switches::kTintCompositedContentModulate);
result.show_overdraw_feedback =
command_line->HasSwitch(switches::kShowOverdrawFeedback);
result.show_dc_layer_debug_borders =
diff --git a/chromium/components/viz/service/BUILD.gn b/chromium/components/viz/service/BUILD.gn
index 159fa9efa79..838a44f26f0 100644
--- a/chromium/components/viz/service/BUILD.gn
+++ b/chromium/components/viz/service/BUILD.gn
@@ -16,6 +16,8 @@ config("viz_service_implementation") {
viz_component("service") {
sources = [
+ "debugger/viz_debugger.cc",
+ "debugger/viz_debugger.h",
"display/aggregated_frame.cc",
"display/aggregated_frame.h",
"display/bsp_tree.cc",
@@ -522,6 +524,7 @@ viz_source_set("gpu_service_dependencies") {
viz_source_set("unit_tests") {
testonly = true
sources = [
+ "debugger/viz_debugger_unittest.cc",
"display/bsp_tree_unittest.cc",
"display/copy_output_scaling_pixeltest.cc",
"display/delegated_ink_point_pixel_test_helper.cc",
@@ -564,6 +567,7 @@ viz_source_set("unit_tests") {
"hit_test/hit_test_aggregator_unittest.cc",
"main/viz_main_impl_unittest.cc",
"surfaces/referenced_surface_tracker_unittest.cc",
+ "surfaces/surface_saved_frame_unittest.cc",
"surfaces/surface_unittest.cc",
"transitions/surface_animation_manager_unittest.cc",
"transitions/transferable_resource_tracker_unittest.cc",
diff --git a/chromium/components/viz/service/DEPS b/chromium/components/viz/service/DEPS
index 00c1c1cad39..e7f63ed4104 100644
--- a/chromium/components/viz/service/DEPS
+++ b/chromium/components/viz/service/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"-components/viz/common/features.h",
"-components/viz/common/switches.h",
"-components/viz/service",
+ "+components/viz/service/debugger/viz_debugger.h",
"+components/viz/service/gl/gpu_service_impl.h",
"+components/viz/service/viz_service_export.h",
"+gpu/config/gpu_feature_info.h",
diff --git a/chromium/components/viz/service/compositor_frame_fuzzer/BUILD.gn b/chromium/components/viz/service/compositor_frame_fuzzer/BUILD.gn
index 5aa76fa6a43..175cc8f52be 100644
--- a/chromium/components/viz/service/compositor_frame_fuzzer/BUILD.gn
+++ b/chromium/components/viz/service/compositor_frame_fuzzer/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("//build/config/python.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/protobuf/proto_library.gni")
@@ -20,8 +19,7 @@ proto_library("compositor_frame_fuzzer_proto") {
# The messages must be of type RenderPass, as defined in the proto2 file
# compositor_frame_fuzzer.proto (these assumptions are all hardcoded into
# generate_renderpass_binary.py)
-# TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
-python2_action_foreach("generate_seed_corpus") {
+action_foreach("generate_seed_corpus") {
script = "generate_renderpass_binary.py"
pyproto_path = "$root_out_dir/pyproto"
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 dbfbda249ac..3dc44605e2c 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
@@ -27,9 +27,9 @@ struct Env {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
auto png_dir_path =
command_line->HasSwitch("dump-to-png")
- ? base::Optional<base::FilePath>(
+ ? absl::optional<base::FilePath>(
command_line->GetSwitchValuePath("dump-to-png"))
- : base::nullopt;
+ : absl::nullopt;
// Re-initialize logging in order to pick up any command-line parameters
// (such as --v=1 to enable verbose logging).
diff --git a/chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc b/chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
index 226e84a8923..dbdc8f58d5b 100644
--- a/chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
+++ b/chromium/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
@@ -341,12 +341,15 @@ void FuzzedCompositorFrameBuilder::ConfigureSharedQuadState(
SharedQuadState* shared_quad_state,
const proto::DrawQuad& quad_spec) {
if (quad_spec.has_sqs()) {
+ absl::optional<gfx::Rect> clip_rect;
+ if (quad_spec.sqs().is_clipped()) {
+ clip_rect = GetRectFromProtobuf(quad_spec.sqs().clip_rect());
+ }
shared_quad_state->SetAll(
GetTransformFromProtobuf(quad_spec.sqs().transform()),
GetRectFromProtobuf(quad_spec.sqs().layer_rect()),
GetRectFromProtobuf(quad_spec.sqs().visible_rect()),
- gfx::MaskFilterInfo(), GetRectFromProtobuf(quad_spec.sqs().clip_rect()),
- quad_spec.sqs().is_clipped(), quad_spec.sqs().are_contents_opaque(),
+ gfx::MaskFilterInfo(), clip_rect, quad_spec.sqs().are_contents_opaque(),
Normalize(quad_spec.sqs().opacity()), SkBlendMode::kSrcOver,
quad_spec.sqs().sorting_context_id());
} else {
@@ -364,9 +367,8 @@ void FuzzedCompositorFrameBuilder::ConfigureSharedQuadState(
shared_quad_state->SetAll(
transform, GetRectFromProtobuf(quad_spec.rect()),
GetRectFromProtobuf(quad_spec.visible_rect()), gfx::MaskFilterInfo(),
- gfx::Rect(), /*is_clipped=*/false,
- /*are_contents_opaque=*/true, /*opacity=*/1.0, SkBlendMode::kSrcOver,
- /*sorting_context_id=*/0);
+ /*clip_rect=*/absl::nullopt, /*are_contents_opaque=*/true,
+ /*opacity=*/1.0, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
}
}
diff --git a/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc b/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
index de70a88d98e..a3d75bd386c 100644
--- a/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
+++ b/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
@@ -31,7 +31,7 @@ constexpr FrameSinkId kRootFrameSinkId(1, 1);
} // namespace
FuzzerBrowserProcess::FuzzerBrowserProcess(
- base::Optional<base::FilePath> png_dir_path)
+ absl::optional<base::FilePath> png_dir_path)
: root_local_surface_id_(1, 1, base::UnguessableToken::Create()),
output_surface_provider_(std::move(png_dir_path)),
frame_sink_manager_(&shared_bitmap_manager_, &output_surface_provider_) {
@@ -68,12 +68,12 @@ void FuzzerBrowserProcess::EmbedFuzzedCompositorFrame(
SurfaceId embedded_surface_id(kEmbeddedFrameSinkId,
lsi_allocator_.GetCurrentLocalSurfaceId());
sink_remote->SubmitCompositorFrame(embedded_surface_id.local_surface_id(),
- std::move(fuzzed_frame), base::nullopt, 0);
+ std::move(fuzzed_frame), absl::nullopt, 0);
CompositorFrame browser_frame =
BuildBrowserUICompositorFrame(embedded_surface_id);
root_compositor_frame_sink_remote_->SubmitCompositorFrame(
- root_local_surface_id_, std::move(browser_frame), base::nullopt, 0);
+ root_local_surface_id_, std::move(browser_frame), absl::nullopt, 0);
// run queued messages (memory allocation and frame submission)
base::RunLoop().RunUntilIdle();
@@ -120,7 +120,7 @@ CompositorFrame FuzzerBrowserProcess::BuildBrowserUICompositorFrame(
BeginFrameArgs::kManualSourceId, BeginFrameArgs::kStartingFrameNumber);
frame.metadata.device_scale_factor = 1;
frame.metadata.referenced_surfaces.push_back(
- SurfaceRange(base::nullopt, renderer_surface_id));
+ SurfaceRange(absl::nullopt, renderer_surface_id));
auto pass = CompositorRenderPass::Create();
pass->SetNew(CompositorRenderPassId{1}, gfx::Rect(kBrowserSize),
@@ -131,22 +131,21 @@ CompositorFrame FuzzerBrowserProcess::BuildBrowserUICompositorFrame(
gfx::Rect(kRendererFrameSize),
gfx::Rect(kRendererFrameSize),
/*mask_filter_info=*/gfx::MaskFilterInfo(),
- gfx::Rect(kRendererFrameSize), /*is_clipped=*/false,
+ /*clip_rect=*/absl::nullopt,
/*are_contents_opaque=*/false, /*opacity=*/1,
SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetNew(renderer_sqs, gfx::Rect(kRendererFrameSize),
gfx::Rect(kRendererFrameSize),
- SurfaceRange(base::nullopt, renderer_surface_id),
+ SurfaceRange(absl::nullopt, renderer_surface_id),
SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
auto* toolbar_sqs = pass->CreateAndAppendSharedQuadState();
toolbar_sqs->SetAll(
gfx::Transform(), gfx::Rect(kTopBarSize), gfx::Rect(kTopBarSize),
- /*mask_filter_info=*/gfx::MaskFilterInfo(), gfx::Rect(kTopBarSize),
- /*is_clipped=*/false, /*are_contents_opaque=*/false,
- /*opacity=*/1, SkBlendMode::kSrcOver,
+ /*mask_filter_info=*/gfx::MaskFilterInfo(), /*clip_rect=*/absl::nullopt,
+ /*are_contents_opaque=*/false, /*opacity=*/1, SkBlendMode::kSrcOver,
/*sorting_context_id=*/0);
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
color_quad->SetNew(toolbar_sqs, gfx::Rect(kTopBarSize),
diff --git a/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h b/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h
index 1eae9f7f19f..ba69e7a1b13 100644
--- a/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h
+++ b/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h
@@ -16,13 +16,14 @@
#include "components/viz/test/fake_compositor_frame_sink_client.h"
#include "components/viz/test/fake_display_client.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "services/viz/privileged/mojom/compositing/external_begin_frame_controller.mojom.h"
namespace viz {
// A fake browser process to use as a fuzzer target. Uses software compositing.
class FuzzerBrowserProcess {
public:
- explicit FuzzerBrowserProcess(base::Optional<base::FilePath> png_dir_path);
+ explicit FuzzerBrowserProcess(absl::optional<base::FilePath> png_dir_path);
~FuzzerBrowserProcess();
// Fuzz target mimicking the process of submitting a rendered CompositorFrame
diff --git a/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_software_output_surface_provider.cc b/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_software_output_surface_provider.cc
index 34014e91bd1..9b0b639fdae 100644
--- a/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_software_output_surface_provider.cc
+++ b/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_software_output_surface_provider.cc
@@ -9,11 +9,11 @@
#include <vector>
#include "base/files/file_util.h"
-#include "base/optional.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/service/display/software_output_device.h"
#include "components/viz/service/display_embedder/software_output_surface.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/encode/SkPngEncoder.h"
#include "ui/gfx/codec/png_codec.h"
@@ -80,7 +80,7 @@ class PNGSoftwareOutputDevice : public SoftwareOutputDevice {
} // namespace
FuzzerSoftwareOutputSurfaceProvider::FuzzerSoftwareOutputSurfaceProvider(
- base::Optional<base::FilePath> png_dir_path)
+ absl::optional<base::FilePath> png_dir_path)
: png_dir_path_(png_dir_path) {}
FuzzerSoftwareOutputSurfaceProvider::~FuzzerSoftwareOutputSurfaceProvider() =
diff --git a/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_software_output_surface_provider.h b/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_software_output_surface_provider.h
index 83014ffa9e2..c4c73310967 100644
--- a/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_software_output_surface_provider.h
+++ b/chromium/components/viz/service/compositor_frame_fuzzer/fuzzer_software_output_surface_provider.h
@@ -8,8 +8,8 @@
#include <memory>
#include "base/files/file_path.h"
-#include "base/optional.h"
#include "components/viz/service/display_embedder/output_surface_provider.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace viz {
@@ -18,7 +18,7 @@ namespace viz {
class FuzzerSoftwareOutputSurfaceProvider : public OutputSurfaceProvider {
public:
explicit FuzzerSoftwareOutputSurfaceProvider(
- base::Optional<base::FilePath> png_dir_path);
+ absl::optional<base::FilePath> png_dir_path);
~FuzzerSoftwareOutputSurfaceProvider() override;
// OutputSurfaceProvider implementation.
@@ -35,7 +35,7 @@ class FuzzerSoftwareOutputSurfaceProvider : public OutputSurfaceProvider {
const DebugRendererSettings* debug_settings) override;
private:
- base::Optional<base::FilePath> png_dir_path_;
+ absl::optional<base::FilePath> png_dir_path_;
DISALLOW_COPY_AND_ASSIGN(FuzzerSoftwareOutputSurfaceProvider);
};
diff --git a/chromium/components/viz/service/compositor_frame_fuzzer/generate_renderpass_binary.py b/chromium/components/viz/service/compositor_frame_fuzzer/generate_renderpass_binary.py
index 30ff934e880..d1190b8e4b9 100755
--- a/chromium/components/viz/service/compositor_frame_fuzzer/generate_renderpass_binary.py
+++ b/chromium/components/viz/service/compositor_frame_fuzzer/generate_renderpass_binary.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
diff --git a/chromium/components/viz/service/debugger/DEPS b/chromium/components/viz/service/debugger/DEPS
new file mode 100644
index 00000000000..9263a086f6d
--- /dev/null
+++ b/chromium/components/viz/service/debugger/DEPS
@@ -0,0 +1,9 @@
+# Please consult components/viz/README.md about allowable dependencies.
+
+include_rules = [
+ "+components/viz",
+ "+ui/base",
+ "+ui/gfx",
+ "+mojo/public",
+]
+
diff --git a/chromium/components/viz/service/debugger/README.md b/chromium/components/viz/service/debugger/README.md
new file mode 100644
index 00000000000..01d4385f761
--- /dev/null
+++ b/chromium/components/viz/service/debugger/README.md
@@ -0,0 +1,62 @@
+# //components/viz/service/debugger
+
+## Viz Remote Visual Debugger
+
+The Viz Remote Debugger is a debug only connection that allows an active chromium instance to send graphical and text debug information to a remote client for display.
+
+### Motivation
+[Visual Debugger one-pager](https://docs.google.com/document/d/1s2OLZcUrUxXRxOD8nR4giNRnCQZcdtXBp4DUI_Fb2GU/edit?usp=sharing).
+
+
+### Usage
+Macros constitute the full Viz Debugger logging API (as far as a nominal chromium developer is concerned).
+
+These macros tend to take the basic form below:
+
+DBG_DRAW_RECT(anno, rect);
+
+This macro will log a rect to the viz debugger for this frame.
+anno - short for Annotation. This must be a string literal. The remote can filter on anno (as well as file and function).
+rect - a (gfx::) rect. Expected dimensions is in pixels.
+
+Unlike a debugging session printfs these logging macros can be remain the chromium source. This allows developers to use these debug logs in future sessions and other share them with other developers.
+
+
+The full list of these macros can be found in VizDebugger.h
+At present, Visual debugging is currently limited to the VizCompositor thread.
+
+
+### Operation
+The debugging macros feed information into the VizDebugger static instance. At the end of each frame this cached information is fed upstream and eventually reaches the remote client.
+
+[Viz Debugger Communication](https://docs.google.com/drawings/d/11zqorcaRuyGx7W2AdL-7hSQJG0wknm0-RDkZSyobmy4/edit?usp=sharing)
+
+
+### Performance
+The logging performance of this system has several variants depending on the configuration.
+
+* Disabled at Compile time
+
+ Zero overhead with the exception of mutable side effects in the creation of input variables.
+
+* Disabled at Runtime
+
+ Every log call must check the debugging instance. This case has been optimized to be one memory read instruction followed by one predictable branch.
+
+* Disabled by Source Filter
+
+ Must read the local static data to determine if this specific logging is enabled. This is on the order of tens of instructions.
+
+* Enabled
+
+ Submits data into VizDebugger buffers. On the order of 100 instructions with the exception of when these buffers need to expand.
+
+
+Additional performance overhead of this system comes from when the collected data is serialized and sent upstream. Unlike the logging submission overhead, this overhead is very easy to track and currently is not consider to be a concern.
+
+
+### Security
+
+For official builds all visual debug macros are compiled out and the VizDebugger is reduced to a selective few method stubs. This means there are no security concerns for this system with exception of mutable side effects in the creation of input variables to the logging macros. These concerns for mutable side effects already exist for any other code; so no special attention is warranted for these macros.
+
+For non-official (debug) builds the dev-tools remote debugging port command line argument must be provided for the viz debugger to collect and stream data. Thus the security of this new system is identical to that of the remote dev tools for the case of debugging builds.
diff --git a/chromium/components/viz/service/debugger/viz_debugger.cc b/chromium/components/viz/service/debugger/viz_debugger.cc
new file mode 100644
index 00000000000..601a0cbdfb5
--- /dev/null
+++ b/chromium/components/viz/service/debugger/viz_debugger.cc
@@ -0,0 +1,339 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include <algorithm>
+#include <atomic>
+#include <string>
+#include <utility>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/values.h"
+#include "components/viz/service/debugger/viz_debugger.h"
+
+#if VIZ_DEBUGGER_IS_ON()
+
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+
+namespace viz {
+
+std::atomic<bool> VizDebugger::enabled_;
+
+VizDebugger* VizDebugger::GetInstance() {
+ static VizDebugger g_debugger;
+ return &g_debugger;
+}
+
+VizDebugger::FilterBlock::FilterBlock(const std::string file_str,
+ const std::string func_str,
+ const std::string anno_str,
+ bool is_active)
+ : file(std::move(file_str)),
+ func(std::move(func_str)),
+ anno(std::move(anno_str)),
+ active(is_active) {}
+
+VizDebugger::FilterBlock::~FilterBlock() = default;
+
+VizDebugger::FilterBlock::FilterBlock(const FilterBlock& other) = default;
+
+base::DictionaryValue VizDebugger::CallSubmitCommon::GetDictionaryValue()
+ const {
+ base::DictionaryValue option_dict;
+ option_dict.SetString("color",
+ base::StringPrintf("#%02x%02x%02x", option.color_r,
+ option.color_g, option.color_b));
+ option_dict.SetInteger("alpha", option.color_a);
+
+ base::DictionaryValue dict;
+ dict.SetInteger("drawindex", draw_index);
+ dict.SetInteger("source_index", source_index);
+ dict.SetKey("option", std::move(option_dict));
+ return dict;
+}
+
+VizDebugger::StaticSource::StaticSource(const char* anno_name,
+ const char* file_name,
+ int file_line,
+ const char* func_name)
+ : anno(anno_name), file(file_name), func(func_name), line(file_line) {
+ VizDebugger::GetInstance()->RegisterSource(this);
+}
+
+VizDebugger::VizDebugger()
+ : gpu_thread_task_runner_(base::SequencedTaskRunnerHandle::Get()) {
+ DETACH_FROM_THREAD(viz_compositor_thread_checker_);
+ enabled_.store(false);
+}
+
+VizDebugger::~VizDebugger() = default;
+
+base::Value VizDebugger::FrameAsJson(const uint64_t counter,
+ const gfx::Size& window_pix,
+ base::TimeTicks time_ticks) {
+ // TODO(petermcneeley): When we move to multithread we need to do something
+ // like an atomic swap here. Currently all multithreading concerns are handled
+ // by having a lock around the |json_frame_output_| object.
+ common_lock_.AssertAcquired();
+ submission_count_ = 0;
+
+ base::DictionaryValue global_dict;
+ global_dict.SetString("frame", base::NumberToString(counter));
+ global_dict.SetInteger("windowx", window_pix.width());
+ global_dict.SetInteger("windowy", window_pix.height());
+ global_dict.SetString(
+ "time", base::NumberToString(time_ticks.since_origin().InMicroseconds()));
+
+ base::ListValue new_sources;
+ for (size_t i = last_sent_source_count_; i < sources_.size(); i++) {
+ const StaticSource* each = sources_[i];
+ base::DictionaryValue dict;
+ dict.SetString("file", each->file);
+ dict.SetInteger("line", each->line);
+ dict.SetString("func", each->func);
+ dict.SetString("anno", each->anno);
+ dict.SetInteger("index", each->reg_index);
+ new_sources.Append(std::move(dict));
+ }
+
+ // Remote connection will now have acknowledged all the new sources.
+ last_sent_source_count_ = sources_.size();
+ global_dict.SetKey("new_sources", std::move(new_sources));
+
+ base::ListValue draw_calls;
+ for (auto&& each : draw_rect_calls_) {
+ base::DictionaryValue dict = each.GetDictionaryValue();
+ {
+ base::ListValue list_xy;
+ list_xy.AppendInteger(each.obj_size.width());
+ list_xy.AppendInteger(each.obj_size.height());
+ dict.SetKey("size", std::move(list_xy));
+ }
+ {
+ base::ListValue list_xy;
+ list_xy.Append(static_cast<double>(each.pos.x()));
+ list_xy.Append(static_cast<double>(each.pos.y()));
+ dict.SetKey("pos", std::move(list_xy));
+ }
+
+ draw_calls.Append(std::move(dict));
+ }
+ global_dict.SetKey("drawcalls", std::move(draw_calls));
+
+ base::ListValue logs;
+ for (auto&& log : logs_) {
+ base::DictionaryValue dict = log.GetDictionaryValue();
+ dict.SetString("value", std::move(log.value));
+ logs.Append(std::move(dict));
+ }
+ global_dict.SetKey("logs", std::move(logs));
+
+ base::ListValue texts;
+ for (auto&& text : draw_text_calls_) {
+ base::DictionaryValue dict = text.GetDictionaryValue();
+ {
+ base::ListValue list_xy;
+ list_xy.Append(static_cast<double>(text.pos.x()));
+ list_xy.Append(static_cast<double>(text.pos.y()));
+ dict.SetKey("pos", std::move(list_xy));
+ }
+ dict.SetString("text", text.text);
+ texts.Append(std::move(dict));
+ }
+ global_dict.SetKey("text", std::move(texts));
+
+ logs_.clear();
+ draw_rect_calls_.clear();
+ draw_text_calls_.clear();
+ return std::move(global_dict);
+}
+
+void VizDebugger::UpdateFilters() {
+ common_lock_.AssertAcquired();
+ if (apply_new_filters_next_frame_) {
+ cached_filters_ = new_filters_;
+ for (auto&& source : sources_) {
+ ApplyFilters(source);
+ }
+ new_filters_.clear();
+ apply_new_filters_next_frame_ = false;
+ }
+}
+
+void VizDebugger::CompleteFrame(uint64_t counter,
+ const gfx::Size& window_pix,
+ base::TimeTicks time_ticks) {
+ DCHECK_CALLED_ON_VALID_THREAD(viz_compositor_thread_checker_);
+ base::AutoLock scoped_lock(common_lock_);
+ UpdateFilters();
+ json_frame_output_ = FrameAsJson(counter, window_pix, time_ticks);
+ gpu_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&VizDebugger::AddFrame, base::Unretained(this)));
+}
+
+void VizDebugger::ApplyFilters(VizDebugger::StaticSource* src) {
+ // In the case of no filters we disable this source.
+ src->active = false;
+
+ // TODO(petermcneeley): We should probably make this string filtering more
+ // optimal. However, for the most part it the cost is only paid on the
+ // application of new filters.
+ auto simple_match = [](const char* source_str,
+ const std::string& filter_match) {
+ if (filter_match.empty() || source_str == nullptr) {
+ return true;
+ }
+ return std::strstr(source_str, filter_match.c_str()) != nullptr;
+ };
+
+ for (const auto& filter_block : cached_filters_) {
+ if (simple_match(src->file, filter_block.file) &&
+ simple_match(src->func, filter_block.func) &&
+ simple_match(src->anno, filter_block.anno)) {
+ src->active = filter_block.active;
+ }
+ }
+}
+
+void VizDebugger::RegisterSource(StaticSource* src) {
+ DCHECK_CALLED_ON_VALID_THREAD(viz_compositor_thread_checker_);
+ int index = sources_.size();
+ src->reg_index = index;
+ ApplyFilters(src);
+ sources_.push_back(src);
+}
+
+void VizDebugger::Draw(const gfx::SizeF& obj_size,
+ const gfx::Vector2dF& pos,
+ const VizDebugger::StaticSource* dcs,
+ VizDebugger::DrawOption option) {
+ DCHECK_CALLED_ON_VALID_THREAD(viz_compositor_thread_checker_);
+ Draw(gfx::Size(obj_size.width(), obj_size.height()), pos, dcs, option);
+}
+
+void VizDebugger::Draw(const gfx::Size& obj_size,
+ const gfx::Vector2dF& pos,
+ const VizDebugger::StaticSource* dcs,
+ VizDebugger::DrawOption option) {
+ DCHECK_CALLED_ON_VALID_THREAD(viz_compositor_thread_checker_);
+ DrawInternal(obj_size, pos, dcs, option);
+}
+
+void VizDebugger::DrawInternal(const gfx::Size& obj_size,
+ const gfx::Vector2dF& pos,
+ const VizDebugger::StaticSource* dcs,
+ VizDebugger::DrawOption option) {
+ DCHECK_CALLED_ON_VALID_THREAD(viz_compositor_thread_checker_);
+ draw_rect_calls_.emplace_back(submission_count_++, dcs->reg_index, option,
+ obj_size, pos);
+}
+
+void VizDebugger::DrawText(const gfx::Point& pos,
+ const std::string& text,
+ const VizDebugger::StaticSource* dcs,
+ VizDebugger::DrawOption option) {
+ DCHECK_CALLED_ON_VALID_THREAD(viz_compositor_thread_checker_);
+ DrawText(gfx::Vector2dF(pos.x(), pos.y()), text, dcs, option);
+}
+
+void VizDebugger::DrawText(const gfx::Vector2dF& pos,
+ const std::string& text,
+ const VizDebugger::StaticSource* dcs,
+ VizDebugger::DrawOption option) {
+ DCHECK_CALLED_ON_VALID_THREAD(viz_compositor_thread_checker_);
+ draw_text_calls_.emplace_back(submission_count_++, dcs->reg_index, option,
+ pos, text);
+}
+
+void VizDebugger::AddFrame() {
+ // TODO(petermcneeley): This code has duel thread entry. One to launch the
+ // task and one for the task to run. We should improve on this design in the
+ // future and have a better multithreaded frame data aggregation system.
+ base::AutoLock scoped_lock(common_lock_);
+ DCHECK(gpu_thread_task_runner_->RunsTasksInCurrentSequence());
+ if (debug_output_.is_bound()) {
+ debug_output_->LogFrame(std::move(json_frame_output_));
+ }
+}
+
+void VizDebugger::FilterDebugStream(base::Value json) {
+ base::AutoLock scoped_lock(common_lock_);
+ DCHECK(gpu_thread_task_runner_->RunsTasksInCurrentSequence());
+ const base::Value* value = &(json);
+ const base::Value* filterlist = value->FindPath("filters");
+
+ if (!filterlist || !filterlist->is_list()) {
+ LOG(ERROR) << "Missing filter list in json: " << json;
+ return;
+ }
+
+ new_filters_.clear();
+
+ for (const auto& filter : filterlist->GetList()) {
+ const base::Value* file = filter.FindPath("selector.file");
+ const base::Value* func = filter.FindPath("selector.func");
+ const base::Value* anno = filter.FindPath("selector.anno");
+ const base::Value* active = filter.FindPath("active");
+
+ if (!active) {
+ LOG(ERROR) << "Missing filter props in json: " << json;
+ return;
+ }
+
+ if ((file && !file->is_string()) || (func && !func->is_string()) ||
+ (anno && !anno->is_string()) || !active->is_bool()) {
+ LOG(ERROR) << "Filter props wrong type in json: " << json;
+ continue;
+ }
+
+ auto check_str = [](const base::Value* filter_str) {
+ return (filter_str ? filter_str->GetString() : std::string());
+ };
+
+ new_filters_.emplace_back(check_str(file), check_str(func), check_str(anno),
+ active->GetBool());
+ }
+
+ apply_new_filters_next_frame_ = true;
+}
+
+void VizDebugger::StartDebugStream(
+ mojo::PendingRemote<mojom::VizDebugOutput> pending_debug_output) {
+ base::AutoLock scoped_lock(common_lock_);
+ DCHECK(gpu_thread_task_runner_->RunsTasksInCurrentSequence());
+ debug_output_.Bind(std::move(pending_debug_output));
+ debug_output_.reset_on_disconnect();
+ last_sent_source_count_ = 0;
+
+ // Reset our filters for our new connection. By default the client will send
+ // along the new filters after establishing the connection.
+ new_filters_.clear();
+ apply_new_filters_next_frame_ = true;
+
+ base::DictionaryValue dict;
+ dict.SetString("connection", "ok");
+ debug_output_->LogFrame(std::move(dict));
+
+ enabled_.store(true);
+}
+
+void VizDebugger::StopDebugStream() {
+ base::AutoLock scoped_lock(common_lock_);
+ DCHECK(gpu_thread_task_runner_->RunsTasksInCurrentSequence());
+ debug_output_.reset();
+ enabled_.store(false);
+}
+
+void VizDebugger::AddLogMessage(std::string log,
+ const VizDebugger::StaticSource* dcs,
+ DrawOption option) {
+ DCHECK_CALLED_ON_VALID_THREAD(viz_compositor_thread_checker_);
+ logs_.emplace_back(submission_count_++, dcs->reg_index, option,
+ std::move(log));
+}
+
+} // namespace viz
+
+#endif // VIZ_DEBUGGER_IS_ON()
diff --git a/chromium/components/viz/service/debugger/viz_debugger.h b/chromium/components/viz/service/debugger/viz_debugger.h
new file mode 100644
index 00000000000..b5fb9929136
--- /dev/null
+++ b/chromium/components/viz/service/debugger/viz_debugger.h
@@ -0,0 +1,328 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DEBUGGER_VIZ_DEBUGGER_H_
+#define COMPONENTS_VIZ_SERVICE_DEBUGGER_VIZ_DEBUGGER_H_
+
+#include <atomic>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/debug/debugging_buildflags.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/stringprintf.h"
+#include "base/synchronization/lock.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "components/viz/common/buildflags.h"
+#include "components/viz/service/viz_service_export.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/viz/privileged/mojom/viz_main.mojom.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+// The visual debugger can be completely disabled/enabled at compile time via
+// the |USE_VIZ_DEBUGGER| build flag which corresponds to boolean gn arg
+// 'use_viz_debugger'. Consult README.md for more information.
+
+#if BUILDFLAG(USE_VIZ_DEBUGGER)
+
+#define VIZ_DEBUGGER_IS_ON() true
+
+namespace viz {
+
+class VIZ_SERVICE_EXPORT VizDebugger {
+ public:
+ // These functions are called on a gpu thread that is not the
+ // 'VizCompositorThread' and therefore have mulithreaded considerations.
+ void FilterDebugStream(base::Value json);
+ void StartDebugStream(
+ mojo::PendingRemote<mojom::VizDebugOutput> pending_debug_output);
+ void StopDebugStream();
+
+ struct VIZ_SERVICE_EXPORT StaticSource {
+ StaticSource(const char* anno_name,
+ const char* file_name,
+ int file_line,
+ const char* func_name);
+ inline bool IsActive() const { return active; }
+ const char* anno;
+ const char* file;
+ const char* func;
+ const int line;
+
+ int reg_index;
+ bool active;
+ };
+
+ struct DrawOption {
+ // TODO(petermcneeley): Consider moving this custom rgba color data over to
+ // |SkColor| representation.
+ uint8_t color_r;
+ uint8_t color_g;
+ uint8_t color_b;
+ // Alpha is applied to rect fill only.
+ uint8_t color_a;
+ };
+
+ static ALWAYS_INLINE bool IsEnabled() {
+ return enabled_.load(std::memory_order_acquire);
+ }
+
+ static VizDebugger* GetInstance();
+
+ ~VizDebugger();
+
+ void CompleteFrame(const uint64_t counter,
+ const gfx::Size& window_pix,
+ base::TimeTicks time_ticks);
+ void DrawText(const gfx::Point& pos,
+ const std::string& text,
+ const StaticSource* dcs,
+ DrawOption option);
+ void DrawText(const gfx::Vector2dF& pos,
+ const std::string& text,
+ const StaticSource* dcs,
+ DrawOption option);
+ void Draw(const gfx::Size& obj_size,
+ const gfx::Vector2dF& pos,
+ const StaticSource* dcs,
+ DrawOption option);
+ void Draw(const gfx::SizeF& obj_size,
+ const gfx::Vector2dF& pos,
+ const StaticSource* dcs,
+ DrawOption option);
+
+ void AddLogMessage(std::string log,
+ const StaticSource* dcs,
+ DrawOption option);
+
+ VizDebugger(const VizDebugger&) = delete;
+ VizDebugger& operator=(const VizDebugger&) = delete;
+
+ private:
+ friend class VizDebuggerInternal;
+ static std::atomic<bool> enabled_;
+ VizDebugger();
+ base::Value FrameAsJson(const uint64_t counter,
+ const gfx::Size& window_pix,
+ base::TimeTicks time_ticks);
+
+ void AddFrame();
+ void UpdateFilters();
+ void RegisterSource(StaticSource* source);
+ void DrawInternal(const gfx::Size& obj_size,
+ const gfx::Vector2dF& pos,
+ const StaticSource* dcs,
+ DrawOption option);
+ void ApplyFilters(VizDebugger::StaticSource* source);
+ mojo::Remote<mojom::VizDebugOutput> debug_output_;
+
+ // This |task_runner_| is required to send json through mojo.
+ scoped_refptr<base::SequencedTaskRunner> gpu_thread_task_runner_;
+
+ struct CallSubmitCommon {
+ CallSubmitCommon(int index, int source, DrawOption draw_option)
+ : draw_index(index), source_index(source), option(draw_option) {}
+ base::DictionaryValue GetDictionaryValue() const;
+ int draw_index;
+ int source_index;
+ VizDebugger::DrawOption option;
+ };
+
+ struct DrawCall : public CallSubmitCommon {
+ DrawCall(int index,
+ int source,
+ DrawOption draw_option,
+ gfx::Size size,
+ gfx::Vector2dF position)
+ : CallSubmitCommon(index, source, draw_option),
+ obj_size(size),
+ pos(position) {}
+ gfx::Size obj_size;
+ gfx::Vector2dF pos;
+ };
+
+ struct DrawTextCall : public CallSubmitCommon {
+ DrawTextCall(int index,
+ int source,
+ DrawOption draw_option,
+ gfx::Vector2dF position,
+ std::string str)
+ : CallSubmitCommon(index, source, draw_option),
+ pos(position),
+ text(str) {}
+ gfx::Vector2dF pos;
+ std::string text;
+ };
+
+ struct LogCall : public CallSubmitCommon {
+ LogCall(int index, int source, DrawOption draw_option, std::string str)
+ : CallSubmitCommon(index, source, draw_option), value(std::move(str)) {}
+ std::string value;
+ };
+
+ struct FilterBlock {
+ FilterBlock(const std::string file_str,
+ const std::string func_str,
+ const std::string anno_str,
+ bool is_active);
+ ~FilterBlock();
+ FilterBlock(const FilterBlock& other);
+ std::string file;
+ std::string func;
+ std::string anno;
+ bool active;
+ };
+
+ // Synchronize access to the variables in the block below as it is mutated by
+ // multiple threads.
+ base::Lock common_lock_;
+ // New filters to promoted to cached filters on next frame.
+ std::vector<FilterBlock> new_filters_;
+ bool apply_new_filters_next_frame_ = false;
+ // Json is saved out every frame on the call to 'CompleteFrame' but may not be
+ // uploaded immediately due to task runner sequencing.
+ base::Value json_frame_output_;
+ size_t last_sent_source_count_ = 0;
+
+ // Cached filters to apply filtering to new sources not just on filter update.
+ std::vector<FilterBlock> cached_filters_;
+ // Common counter for all submissions.
+ int submission_count_ = 0;
+ std::vector<DrawCall> draw_rect_calls_;
+ std::vector<DrawTextCall> draw_text_calls_;
+ std::vector<LogCall> logs_;
+ std::vector<StaticSource*> sources_;
+
+ THREAD_CHECKER(viz_compositor_thread_checker_);
+};
+
+} // namespace viz
+
+#define DBG_OPT_RED \
+ (viz::VizDebugger::DrawOption) { 255, 0, 0, 0 }
+#define DBG_OPT_GREEN \
+ (viz::VizDebugger::DrawOption) { 0, 255, 0, 0 }
+#define DBG_OPT_BLUE \
+ (viz::VizDebugger::DrawOption) { 0, 0, 255, 0 }
+#define DBG_OPT_BLACK \
+ (viz::VizDebugger::DrawOption) { 0, 0, 0, 0 }
+
+#define DBG_DRAW_RECTANGLE_OPT(anno, option, pos, size) \
+ do { \
+ if (viz::VizDebugger::IsEnabled()) { \
+ static VizDebugger::StaticSource dcs(anno, __FILE__, __LINE__, \
+ __func__); \
+ if (dcs.IsActive()) { \
+ viz::VizDebugger::GetInstance()->Draw(size, pos, &dcs, option); \
+ } \
+ } \
+ } while (0)
+
+#define DBG_DRAW_RECTANGLE(anno, pos, size) \
+ DBG_DRAW_RECTANGLE_OPT(anno, DBG_OPT_BLACK, pos, size)
+
+#define DBG_DRAW_TEXT_OPT(anno, option, pos, text) \
+ do { \
+ if (viz::VizDebugger::IsEnabled()) { \
+ static VizDebugger::StaticSource dcs(anno, __FILE__, __LINE__, \
+ __func__); \
+ if (dcs.IsActive()) { \
+ viz::VizDebugger::GetInstance()->DrawText(pos, text, &dcs, option); \
+ } \
+ } \
+ } while (0)
+
+#define DBG_DRAW_TEXT(anno, pos, text) \
+ DBG_DRAW_TEXT_OPT(anno, DBG_OPT_BLACK, pos, text)
+
+#define DBG_LOG_OPT(anno, option, format, ...) \
+ do { \
+ if (VizDebugger::IsEnabled()) { \
+ static VizDebugger::StaticSource dcs(anno, __FILE__, __LINE__, \
+ __func__); \
+ if (dcs.IsActive()) { \
+ VizDebugger::GetInstance()->AddLogMessage( \
+ base::StringPrintf(format, __VA_ARGS__), &dcs, option); \
+ } \
+ } \
+ } while (0)
+
+#define DBG_LOG(anno, format, ...) \
+ DBG_LOG_OPT(anno, DBG_OPT_BLACK, format, __VA_ARGS__)
+
+#define DBG_DRAW_RECT_OPT(anno, option, rect) \
+ DBG_DRAW_RECTANGLE( \
+ anno, gfx::Vector2dF(rect.origin().x(), rect.origin().y()), rect.size())
+
+#define DBG_DRAW_RECT(anno, rect) DBG_DRAW_RECT_OPT(anno, DBG_OPT_BLACK, rect)
+
+#else // !BUILDFLAG(USE_VIZ_DEBUGGER)
+
+#define VIZ_DEBUGGER_IS_ON() false
+
+// Viz Debugger is not enabled. The |VizDebugger| class is minimally defined to
+// reduce the need for if/def checks in external code. All debugging macros
+// compiled to empty statements but do eat some parameters to prevent used
+// variable warnings.
+
+namespace viz {
+class VIZ_SERVICE_EXPORT VizDebugger {
+ public:
+ VizDebugger() = default;
+ static inline VizDebugger* GetInstance() {
+ static VizDebugger g_debugger;
+ return &g_debugger;
+ }
+ inline void CompleteFrame(uint64_t counter,
+ const gfx::Size& window_pix,
+ base::TimeTicks time_ticks) {}
+
+ static inline bool IsEnabled() { return false; }
+ VizDebugger(const VizDebugger&) = delete;
+ VizDebugger& operator=(const VizDebugger&) = delete;
+};
+} // namespace viz
+
+#define DBG_OPT_RED 0
+
+#define DBG_OPT_GREEN 0
+
+#define DBG_OPT_BLUE 0
+
+#define DBG_OPT_BLACK 0
+
+#define DBG_DRAW_RECTANGLE_OPT(anno, option, pos, size) \
+ ANALYZER_ALLOW_UNUSED(anno) \
+ ANALYZER_ALLOW_UNUSED(option) \
+ ANALYZER_ALLOW_UNUSED(pos) ANALYZER_ALLOW_UNUSED(size)
+
+#define DBG_DRAW_RECTANGLE(anno, pos, size) \
+ DBG_DRAW_RECTANGLE_OPT(anno, DBG_OPT_BLACK, pos, size)
+
+#define DBG_DRAW_TEXT_OPT(anno, option, pos, text) \
+ ANALYZER_ALLOW_UNUSED(anno) \
+ ANALYZER_ALLOW_UNUSED(option) \
+ ANALYZER_ALLOW_UNUSED(pos) ANALYZER_ALLOW_UNUSED(text)
+
+#define DBG_DRAW_TEXT(anno, pos, text) \
+ DBG_DRAW_TEXT_OPT(anno, DBG_OPT_BLACK, pos, text)
+
+#define DBG_LOG_OPT(anno, option, format, ...) \
+ ANALYZER_ALLOW_UNUSED(anno) \
+ ANALYZER_ALLOW_UNUSED(option) ANALYZER_ALLOW_UNUSED(format)
+
+#define DBG_LOG(anno, format, ...) DBG_LOG_OPT(anno, DBG_OPT_BLACK, format, ...)
+
+#define DBG_DRAW_RECT_OPT(anno, option, rect) \
+ ANALYZER_ALLOW_UNUSED(anno) \
+ ANALYZER_ALLOW_UNUSED(option) ANALYZER_ALLOW_UNUSED(rect)
+
+#define DBG_DRAW_RECT(anno, rect) DBG_DRAW_RECT_OPT(anno, DBG_OPT_BLACK, rect)
+
+#endif // BUILDFLAG(USE_VIZ_DEBUGGER)
+
+#endif // COMPONENTS_VIZ_SERVICE_DEBUGGER_VIZ_DEBUGGER_H_
diff --git a/chromium/components/viz/service/debugger/viz_debugger_unittest.cc b/chromium/components/viz/service/debugger/viz_debugger_unittest.cc
new file mode 100644
index 00000000000..d7c2eb56459
--- /dev/null
+++ b/chromium/components/viz/service/debugger/viz_debugger_unittest.cc
@@ -0,0 +1,387 @@
+// 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 <stddef.h>
+
+#include <cstdio>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/json/json_reader.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "components/viz/service/debugger/viz_debugger.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+#if VIZ_DEBUGGER_IS_ON()
+using testing::_;
+using testing::Mock;
+
+namespace viz {
+
+class VizDebuggerInternal : public VizDebugger {
+ public:
+ void ForceEnabled() { enabled_ = true; }
+ bool Reset();
+
+ int GetSourceCount() { return static_cast<int>(sources_.size()); }
+
+ using VizDebugger::CallSubmitCommon;
+ using VizDebugger::common_lock_;
+ using VizDebugger::DrawCall;
+ using VizDebugger::DrawTextCall;
+ using VizDebugger::FrameAsJson;
+ using VizDebugger::LogCall;
+ using VizDebugger::UpdateFilters;
+};
+
+bool VizDebuggerInternal::Reset() {
+ submission_count_ = 0;
+ draw_rect_calls_.clear();
+ draw_text_calls_.clear();
+ logs_.clear();
+ last_sent_source_count_ = 0;
+ sources_.clear();
+ return true;
+}
+
+namespace {
+
+struct TestFilter {
+ std::string anno;
+ std::string func;
+ std::string file;
+ bool active = true;
+};
+
+static_assert(sizeof(VizDebuggerInternal) == sizeof(VizDebugger),
+ "This test code exposes the internals of |VizDebugger| via an "
+ "upcast; thus they must be the same size.");
+
+class VisualDebuggerTest : public testing::Test {
+ protected:
+ VizDebuggerInternal* GetInternal() {
+ return static_cast<VizDebuggerInternal*>(VizDebugger::GetInstance());
+ }
+
+ void SetUp() override { GetInternal()->Reset(); }
+ void TearDown() override { GetInternal()->Reset(); }
+
+ void SetFilter(std::vector<TestFilter> filters) {
+ base::DictionaryValue filters_json;
+ base::ListValue filters_list;
+ for (auto&& each : filters) {
+ base::DictionaryValue full_filter;
+ base::DictionaryValue selector;
+ if (!each.file.empty())
+ selector.SetString("file", each.file);
+
+ if (!each.func.empty())
+ selector.SetString("func", each.func);
+
+ selector.SetString("anno", each.anno);
+
+ full_filter.SetKey("selector", std::move(selector));
+ full_filter.SetBoolean("active", each.active);
+ filters_list.Append(std::move(full_filter));
+ }
+ filters_json.SetKey("filters", std::move(filters_list));
+ GetInternal()->FilterDebugStream(std::move(filters_json));
+ GetInternal()->common_lock_.Acquire();
+ GetInternal()->UpdateFilters();
+ GetInternal()->common_lock_.Release();
+ }
+
+ public:
+ struct StaticSource {
+ std::string file;
+ std::string func;
+ std::string anno;
+ int line;
+ int index;
+ };
+
+ void GetFrameData() {
+ sources_.clear();
+ draw_calls_.clear();
+ log_calls_.clear();
+ draw_text_calls_.clear();
+ GetInternal()->common_lock_.Acquire();
+ absl::optional<base::Value> global_dict = GetInternal()->FrameAsJson(
+ frame_counter_, gfx::Size(window_x_, window_y_), base::TimeTicks());
+ GetInternal()->common_lock_.Release();
+ frame_counter_++;
+
+ EXPECT_TRUE(global_dict->is_dict());
+
+ std::string str;
+ global_dict->FindKey("frame")->GetAsString(&str);
+ base::StringToUint64(str.c_str(), &counter_);
+ static const int kNoVal = -1;
+
+ window_x_ = global_dict->FindKey("windowx")->GetIfInt().value_or(kNoVal);
+ window_y_ = global_dict->FindKey("windowy")->GetIfInt().value_or(kNoVal);
+
+ base::Value* list_source = global_dict->FindListKey("new_sources");
+ EXPECT_TRUE(list_source->is_list());
+
+ for (size_t i = 0; i < list_source->GetList().size(); i++) {
+ auto&& local_dict = list_source->GetList()[i];
+ StaticSource ss;
+ local_dict.FindKey("file")->GetAsString(&str);
+ ss.file = str;
+
+ local_dict.FindKey("func")->GetAsString(&str);
+ ss.func = str;
+
+ local_dict.FindKey("anno")->GetAsString(&str);
+ ss.anno = str;
+
+ ss.line = local_dict.FindKey("line")->GetIfInt().value_or(kNoVal);
+ ss.index = local_dict.FindKey("index")->GetIfInt().value_or(kNoVal);
+ sources_.push_back(ss);
+ }
+
+ base::Value* draw_call_list = global_dict->FindListKey("drawcalls");
+ EXPECT_TRUE(draw_call_list->is_list());
+
+ auto func_common_call = [](const base::Value& dict, int* draw_index,
+ int* source_index,
+ VizDebugger::DrawOption* option) {
+ *draw_index = dict.FindKey("drawindex")->GetIfInt().value_or(kNoVal);
+ *source_index = dict.FindKey("source_index")->GetIfInt().value_or(kNoVal);
+
+ std::string str;
+ const base::Value* option_dict = dict.FindDictKey("option");
+ option_dict->FindKey("color")->GetAsString(&str);
+
+ uint32_t red;
+ uint32_t green;
+ uint32_t blue;
+ std::sscanf(str.c_str(), "#%x%x%x", &red, &green, &blue);
+
+ option->color_r = red;
+ option->color_g = green;
+ option->color_b = blue;
+ option->color_a = static_cast<uint8_t>(
+ option_dict->FindKey("alpha")->GetIfInt().value_or(kNoVal));
+ };
+
+ for (size_t i = 0; i < draw_call_list->GetList().size(); i++) {
+ const base::Value& local_dict = draw_call_list->GetList()[i];
+ int draw_index;
+ int source_index;
+ VizDebugger::DrawOption option;
+ func_common_call(local_dict, &draw_index, &source_index, &option);
+
+ const base::Value* list_size = local_dict.FindListKey("size");
+ EXPECT_TRUE(list_size->is_list());
+ int size_x = list_size->GetList()[0].GetIfInt().value_or(kNoVal);
+ int size_y = list_size->GetList()[1].GetIfInt().value_or(kNoVal);
+
+ const base::Value* list_pos = local_dict.FindListKey("pos");
+ EXPECT_TRUE(list_pos->is_list());
+ float pos_x = list_pos->GetList()[0].GetIfDouble().value_or(kNoVal);
+ float pos_y = list_pos->GetList()[1].GetIfDouble().value_or(kNoVal);
+
+ VizDebuggerInternal::DrawCall draw_call(draw_index, source_index, option,
+ gfx::Size(size_x, size_y),
+ gfx::Vector2dF(pos_x, pos_y));
+
+ draw_calls_.push_back(draw_call);
+ }
+
+ base::Value* text_call_list = global_dict->FindListKey("text");
+ EXPECT_TRUE(text_call_list->is_list());
+
+ for (size_t i = 0; i < text_call_list->GetList().size(); i++) {
+ const base::Value& local_dict = text_call_list->GetList()[i];
+ int draw_index;
+ int source_index;
+ VizDebugger::DrawOption option;
+
+ func_common_call(local_dict, &draw_index, &source_index, &option);
+
+ local_dict.FindKey("text")->GetAsString(&str);
+ std::string text_str = str;
+
+ const base::Value* list_pos = local_dict.FindListKey("pos");
+ EXPECT_TRUE(list_pos->is_list());
+ float pos_x = list_pos->GetList()[0].GetIfDouble().value_or(kNoVal);
+ float pos_y = list_pos->GetList()[1].GetIfDouble().value_or(kNoVal);
+
+ VizDebuggerInternal::DrawTextCall text_call(
+ draw_index, source_index, option, gfx::Vector2dF(pos_x, pos_y),
+ text_str);
+
+ draw_text_calls_.push_back(text_call);
+ }
+
+ base::Value* log_call_list = global_dict->FindListKey("logs");
+ EXPECT_TRUE(log_call_list->is_list());
+
+ for (size_t i = 0; i < log_call_list->GetList().size(); i++) {
+ const base::Value& local_dict = log_call_list->GetList()[i];
+ int draw_index;
+ int source_index;
+ VizDebugger::DrawOption option;
+ func_common_call(local_dict, &draw_index, &source_index, &option);
+
+ local_dict.FindKey("value")->GetAsString(&str);
+ std::string log_str = str;
+
+ VizDebuggerInternal::LogCall log_call(draw_index, source_index, option,
+ log_str);
+
+ log_calls_.push_back(log_call);
+ }
+ }
+
+ uint64_t frame_counter_ = 0;
+
+ // Cached result of call to 'GetFrameData' to simplify code.
+ uint64_t counter_;
+ int window_x_ = 256;
+ int window_y_ = 256;
+ std::vector<StaticSource> sources_;
+ std::vector<VizDebuggerInternal::DrawCall> draw_calls_;
+ std::vector<VizDebuggerInternal::LogCall> log_calls_;
+ std::vector<VizDebuggerInternal::DrawTextCall> draw_text_calls_;
+};
+
+TEST_F(VisualDebuggerTest, GeneralDrawSubmission) {
+ const char kAnnoRect[] = "annorect";
+ const char kAnnoText[] = "annotext";
+ const char kAnnoLog[] = "annolog";
+ const gfx::Rect kTestRect = gfx::Rect(12, 34, 56, 78);
+ static const int kNumFrames = 4;
+ GetInternal()->ForceEnabled();
+ for (uint64_t frame_idx = 0; frame_idx < kNumFrames; frame_idx++) {
+ SetFilter({TestFilter({""})});
+
+ static const int kNumSubmission = 8;
+ for (int i = 0; i < kNumSubmission; i++) {
+ DBG_DRAW_RECT(kAnnoRect, kTestRect);
+ DBG_DRAW_TEXT(kAnnoText, kTestRect.origin(),
+ base::StringPrintf("Text %d", i));
+ DBG_LOG(kAnnoLog, "%d", i);
+ }
+
+ GetFrameData();
+
+ EXPECT_EQ(counter_, frame_idx);
+ EXPECT_EQ(window_x_, 256);
+ EXPECT_EQ(window_x_, 256);
+ EXPECT_EQ(draw_calls_.size(), static_cast<size_t>(kNumSubmission));
+ EXPECT_EQ(log_calls_.size(), static_cast<size_t>(kNumSubmission));
+ EXPECT_EQ(draw_text_calls_.size(), static_cast<size_t>(kNumSubmission));
+
+ if (frame_idx == 0) {
+ EXPECT_EQ(sources_.size(), 3u);
+ EXPECT_EQ(sources_[0].func, "TestBody");
+ EXPECT_EQ(sources_[0].file, __FILE__);
+ EXPECT_EQ(sources_[0].anno, kAnnoRect);
+ EXPECT_EQ(sources_[1].func, "TestBody");
+ EXPECT_EQ(sources_[1].file, __FILE__);
+ EXPECT_EQ(sources_[1].anno, kAnnoText);
+ EXPECT_EQ(sources_[2].func, "TestBody");
+ EXPECT_EQ(sources_[2].file, __FILE__);
+ EXPECT_EQ(sources_[2].anno, kAnnoLog);
+ } else {
+ // After the first frame there are no new sources in the loop.
+ EXPECT_EQ(sources_.size(), 0u);
+ }
+
+ for (int i = 0; i < kNumSubmission; i++) {
+ EXPECT_EQ(draw_calls_[i].pos,
+ gfx::Vector2dF(kTestRect.origin().x(), kTestRect.origin().y()));
+ EXPECT_EQ(draw_calls_[i].obj_size, kTestRect.size());
+ EXPECT_EQ(draw_calls_[i].source_index, 0);
+ EXPECT_EQ(draw_calls_[i].draw_index, i * 3);
+
+ EXPECT_EQ(draw_text_calls_[i].pos,
+ gfx::Vector2dF(kTestRect.origin().x(), kTestRect.origin().y()));
+ EXPECT_EQ(draw_text_calls_[i].source_index, 1);
+ EXPECT_EQ(draw_text_calls_[i].draw_index, i * 3 + 1);
+ EXPECT_EQ(draw_text_calls_[i].text, base::StringPrintf("Text %d", i));
+
+ EXPECT_EQ(log_calls_[i].value, base::StringPrintf("%d", i));
+ EXPECT_EQ(log_calls_[i].source_index, 2);
+ EXPECT_EQ(log_calls_[i].draw_index, i * 3 + 2);
+ }
+ }
+}
+
+static void FunctionNameTest(const char* anno_rect, gfx::Rect rect) {
+ DBG_DRAW_RECT(anno_rect, rect);
+}
+
+TEST_F(VisualDebuggerTest, FilterDrawSubmission) {
+ const char kAnnoRect[] = "annorect";
+ const char kAnnoMissing[] = "testmissing";
+ const char kAnnoMatch[] = "before_annorect_after";
+
+ GetInternal()->ForceEnabled();
+ const gfx::Rect kTestRect = gfx::Rect(10, 30, 50, 70);
+ const gfx::Rect kMissingRect = gfx::Rect(11, 33, 55, 77);
+ std::vector<int> valid_indices;
+ SetFilter({TestFilter({"annorect"})});
+ valid_indices.push_back(GetInternal()->GetSourceCount());
+ FunctionNameTest(kAnnoRect, kTestRect);
+ valid_indices.push_back(GetInternal()->GetSourceCount());
+ DBG_DRAW_RECT(kAnnoRect, kTestRect);
+ DBG_DRAW_RECT(kAnnoMissing, kMissingRect);
+ valid_indices.push_back(GetInternal()->GetSourceCount());
+ DBG_DRAW_RECT(kAnnoMatch, kTestRect);
+
+ SetFilter({TestFilter({"", "FunctionNameTest"})});
+ DBG_DRAW_RECT(kAnnoRect, kMissingRect);
+ valid_indices.push_back(0);
+ FunctionNameTest(kAnnoRect, kTestRect);
+
+ SetFilter({TestFilter({"", "TestBody"})});
+ FunctionNameTest(kAnnoRect, kMissingRect);
+ valid_indices.push_back(GetInternal()->GetSourceCount());
+ DBG_DRAW_RECT(kAnnoRect, kTestRect);
+
+ SetFilter({TestFilter({"", "", "no_file"})});
+ DBG_DRAW_RECT(kAnnoRect, kMissingRect);
+
+ SetFilter({TestFilter({"", "", __FILE__})});
+ valid_indices.push_back(GetInternal()->GetSourceCount());
+ DBG_DRAW_RECT(kAnnoRect, kTestRect);
+
+ GetFrameData();
+ EXPECT_EQ(sources_[0].func, "FunctionNameTest");
+ EXPECT_EQ(sources_[0].file, __FILE__);
+ EXPECT_EQ(sources_[0].anno, kAnnoRect);
+ EXPECT_EQ(sources_[1].func, "TestBody");
+ EXPECT_EQ(sources_[1].file, __FILE__);
+ EXPECT_EQ(sources_[1].anno, kAnnoRect);
+ EXPECT_EQ(sources_[2].anno, kAnnoMissing);
+ EXPECT_EQ(sources_[3].anno, kAnnoMatch);
+
+ auto check_draw = [](const VizDebuggerInternal::DrawCall& draw_call,
+ const gfx::Rect& rect, int src_idx, int draw_idx) {
+ EXPECT_EQ(draw_call.pos,
+ gfx::Vector2dF(rect.origin().x(), rect.origin().y()));
+ EXPECT_EQ(draw_call.obj_size, rect.size());
+ EXPECT_EQ(draw_call.source_index, src_idx);
+ EXPECT_EQ(draw_call.draw_index, draw_idx);
+ };
+
+ // Makes sure all valid indices are here and have the correct rect.
+ for (size_t i = 0; i < draw_calls_.size(); i++) {
+ check_draw(draw_calls_[i], kTestRect, valid_indices[i], i);
+ }
+}
+
+} // namespace
+} // namespace viz
+#endif // VIZ_DEBUGGER_IS_ON()
diff --git a/chromium/components/viz/service/display/DEPS b/chromium/components/viz/service/display/DEPS
index c9c7950c33b..ee10217b447 100644
--- a/chromium/components/viz/service/display/DEPS
+++ b/chromium/components/viz/service/display/DEPS
@@ -78,5 +78,8 @@ specific_include_rules = {
"overlay_processor_using_strategy\.(cc|h)": [
"+media/gpu/buildflags.h",
"+media/gpu/vaapi/vaapi_wrapper.h",
+ ],
+ "output_surface\.h": [
+ "+mojo/public/cpp/bindings/pending_receiver.h",
]
}
diff --git a/chromium/components/viz/service/display/aggregated_frame.h b/chromium/components/viz/service/display/aggregated_frame.h
index a1a1aa284a8..eabef95c83f 100644
--- a/chromium/components/viz/service/display/aggregated_frame.h
+++ b/chromium/components/viz/service/display/aggregated_frame.h
@@ -8,9 +8,9 @@
#include <memory>
#include <vector>
-#include "base/optional.h"
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/service/viz_service_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/delegated_ink_metadata.h"
#include "ui/gfx/display_color_spaces.h"
#include "ui/latency/latency_info.h"
@@ -30,7 +30,7 @@ class VIZ_SERVICE_EXPORT AggregatedFrame {
// The visible height of the top-controls. If the value is not set, then the
// visible height should be the same as in the latest submitted frame with a
// value set.
- base::Optional<float> top_controls_visible_height;
+ absl::optional<float> top_controls_visible_height;
// A list of latency info used for this frame.
std::vector<ui::LatencyInfo> latency_info;
diff --git a/chromium/components/viz/service/display/ca_layer_overlay.cc b/chromium/components/viz/service/display/ca_layer_overlay.cc
index c4cb61d4584..060525de1cf 100644
--- a/chromium/components/viz/service/display/ca_layer_overlay.cc
+++ b/chromium/components/viz/service/display/ca_layer_overlay.cc
@@ -46,17 +46,17 @@ enum CALayerResult {
CA_LAYER_FAILED_TILE_NOT_CANDIDATE = 7,
CA_LAYER_FAILED_QUAD_BLEND_MODE = 8,
// CA_LAYER_FAILED_QUAD_TRANSFORM = 9,
- // CA_LAYER_FAILED_QUAD_CLIPPING = 10,
+ CA_LAYER_FAILED_QUAD_CLIPPING = 10,
CA_LAYER_FAILED_DEBUG_BORDER = 11,
CA_LAYER_FAILED_PICTURE_CONTENT = 12,
// CA_LAYER_FAILED_RENDER_PASS = 13,
CA_LAYER_FAILED_SURFACE_CONTENT = 14,
- CA_LAYER_FAILED_YUV_VIDEO_CONTENT = 15,
+ // CA_LAYER_FAILED_YUV_VIDEO_CONTENT = 15,
CA_LAYER_FAILED_DIFFERENT_CLIP_SETTINGS = 16,
CA_LAYER_FAILED_DIFFERENT_VERTEX_OPACITIES = 17,
// CA_LAYER_FAILED_RENDER_PASS_FILTER_SCALE = 18,
CA_LAYER_FAILED_RENDER_PASS_BACKDROP_FILTERS = 19,
- // CA_LAYER_FAILED_RENDER_PASS_MASK = 20,
+ CA_LAYER_FAILED_RENDER_PASS_MASK = 20,
CA_LAYER_FAILED_RENDER_PASS_FILTER_OPERATION = 21,
CA_LAYER_FAILED_RENDER_PASS_SORTING_CONTEXT_ID = 22,
CA_LAYER_FAILED_TOO_MANY_RENDER_PASS_DRAW_QUADS = 23,
@@ -64,6 +64,9 @@ enum CALayerResult {
CA_LAYER_FAILED_QUAD_ROUNDED_CORNER_CLIP_MISMATCH = 25,
CA_LAYER_FAILED_QUAD_ROUNDED_CORNER_NOT_UNIFORM = 26,
CA_LAYER_FAILED_TOO_MANY_QUADS = 27,
+ CA_LAYER_FAILED_YUV_NOT_CANDIDATE = 28,
+ CA_LAYER_FAILED_Y_UV_TEXCOORD_MISMATCH = 29,
+ CA_LAYER_FAILED_YUV_INVALID_PLANES = 30,
CA_LAYER_FAILED_COUNT,
};
@@ -97,7 +100,8 @@ CALayerResult FromRenderPassQuad(
return CA_LAYER_FAILED_RENDER_PASS_BACKDROP_FILTERS;
}
- if (quad->shared_quad_state->sorting_context_id != 0)
+ auto* shared_quad_state = quad->shared_quad_state;
+ if (shared_quad_state->sorting_context_id != 0)
return CA_LAYER_FAILED_RENDER_PASS_SORTING_CONTEXT_ID;
auto it = render_pass_filters.find(quad->render_pass_id);
@@ -109,6 +113,18 @@ CALayerResult FromRenderPassQuad(
}
}
+ // TODO(crbug.com/1215491): support not 2d axis aligned clipping.
+ if (shared_quad_state->clip_rect &&
+ !shared_quad_state->quad_to_target_transform.Preserves2dAxisAlignment()) {
+ return CA_LAYER_FAILED_QUAD_CLIPPING;
+ }
+
+ // TODO(crbug.com/1215491): support not 2d axis aligned mask.
+ if (!shared_quad_state->mask_filter_info.IsEmpty() &&
+ !shared_quad_state->quad_to_target_transform.Preserves2dAxisAlignment()) {
+ return CA_LAYER_FAILED_RENDER_PASS_MASK;
+ }
+
ca_layer_overlay->rpdq = quad;
ca_layer_overlay->contents_rect = gfx::RectF(0, 0, 1, 1);
@@ -167,6 +183,37 @@ CALayerResult FromTextureQuad(DisplayResourceProvider* resource_provider,
return CA_LAYER_SUCCESS;
}
+CALayerResult FromYUVVideoQuad(DisplayResourceProvider* resource_provider,
+ const YUVVideoDrawQuad* quad,
+ CALayerOverlay* ca_layer_overlay) {
+ // For YUVVideoDrawQuads, the Y and UV planes alias the same underlying
+ // IOSurface. Ensure all planes are overlays and have the same contents
+ // rect. Then use the Y plane as the resource for the overlay.
+ ResourceId y_resource_id = quad->y_plane_resource_id();
+ if (!resource_provider->IsOverlayCandidate(y_resource_id) ||
+ !resource_provider->IsOverlayCandidate(quad->u_plane_resource_id()) ||
+ !resource_provider->IsOverlayCandidate(quad->v_plane_resource_id())) {
+ return CA_LAYER_FAILED_YUV_NOT_CANDIDATE;
+ }
+ if (quad->y_plane_resource_id() == quad->u_plane_resource_id() ||
+ quad->y_plane_resource_id() == quad->v_plane_resource_id() ||
+ quad->u_plane_resource_id() != quad->v_plane_resource_id()) {
+ return CA_LAYER_FAILED_YUV_INVALID_PLANES;
+ }
+
+ gfx::RectF ya_contents_rect =
+ gfx::ScaleRect(quad->ya_tex_coord_rect, 1.f / quad->ya_tex_size.width(),
+ 1.f / quad->ya_tex_size.height());
+ gfx::RectF uv_contents_rect =
+ gfx::ScaleRect(quad->uv_tex_coord_rect, 1.f / quad->uv_tex_size.width(),
+ 1.f / quad->uv_tex_size.height());
+ if (ya_contents_rect != uv_contents_rect)
+ return CA_LAYER_FAILED_Y_UV_TEXCOORD_MISMATCH;
+ ca_layer_overlay->contents_resource_id = y_resource_id;
+ ca_layer_overlay->contents_rect = ya_contents_rect;
+ return CA_LAYER_SUCCESS;
+}
+
CALayerResult FromTileQuad(DisplayResourceProvider* resource_provider,
const TileDrawQuad* quad,
CALayerOverlay* ca_layer_overlay) {
@@ -210,7 +257,7 @@ class CALayerOverlayProcessorInternal {
// another CALayer to the tree). Handling non-single border radii is also,
// but requires APIs not supported on all macOS versions.
if (quad->shared_quad_state->mask_filter_info.HasRoundedCorners()) {
- DCHECK(quad->shared_quad_state->is_clipped);
+ DCHECK(quad->shared_quad_state->clip_rect);
if (quad->shared_quad_state->mask_filter_info.rounded_corner_bounds()
.GetType() > gfx::RRectF::Type::kSingle) {
return CA_LAYER_FAILED_QUAD_ROUNDED_CORNER_NOT_UNIFORM;
@@ -235,9 +282,9 @@ class CALayerOverlayProcessorInternal {
most_recent_overlay_shared_state_->sorting_context_id =
quad->shared_quad_state->sorting_context_id;
most_recent_overlay_shared_state_->is_clipped =
- quad->shared_quad_state->is_clipped;
+ quad->shared_quad_state->clip_rect.has_value();
most_recent_overlay_shared_state_->clip_rect =
- gfx::RectF(quad->shared_quad_state->clip_rect);
+ gfx::RectF(quad->shared_quad_state->clip_rect.value_or(gfx::Rect()));
most_recent_overlay_shared_state_->rounded_corner_bounds =
quad->shared_quad_state->mask_filter_info.rounded_corner_bounds();
@@ -279,7 +326,9 @@ class CALayerOverlayProcessorInternal {
case DrawQuad::Material::kSurfaceContent:
return CA_LAYER_FAILED_SURFACE_CONTENT;
case DrawQuad::Material::kYuvVideoContent:
- return CA_LAYER_FAILED_YUV_VIDEO_CONTENT;
+ return FromYUVVideoQuad(resource_provider,
+ YUVVideoDrawQuad::MaterialCast(quad),
+ ca_layer_overlay);
default:
break;
}
@@ -341,13 +390,17 @@ void CALayerOverlayProcessor::PutForcedOverlayContentIntoOverlays(
for (auto it = quad_list->begin(); it != quad_list->end(); ++it) {
const DrawQuad* quad = *it;
bool force_quad_to_overlay = false;
+ gfx::ProtectedVideoType protected_video_type =
+ gfx::ProtectedVideoType::kClear;
// Put hardware protected video into an overlay
if (quad->material == ContentDrawQuadBase::Material::kYuvVideoContent) {
const YUVVideoDrawQuad* video_quad = YUVVideoDrawQuad::MaterialCast(quad);
if (video_quad->protected_video_type ==
- gfx::ProtectedVideoType::kHardwareProtected)
+ gfx::ProtectedVideoType::kHardwareProtected) {
force_quad_to_overlay = true;
+ protected_video_type = gfx::ProtectedVideoType::kHardwareProtected;
+ }
}
if (quad->material == ContentDrawQuadBase::Material::kTextureContent) {
@@ -368,7 +421,7 @@ void CALayerOverlayProcessor::PutForcedOverlayContentIntoOverlays(
if (!PutQuadInSeparateOverlay(it, resource_provider, render_pass,
display_rect, quad, render_pass_filters,
render_pass_backdrop_filters,
- ca_layer_overlays)) {
+ protected_video_type, ca_layer_overlays)) {
failed = true;
break;
}
@@ -454,6 +507,7 @@ bool CALayerOverlayProcessor::PutQuadInSeparateOverlay(
render_pass_filters,
const base::flat_map<AggregatedRenderPassId, cc::FilterOperations*>&
render_pass_backdrop_filters,
+ gfx::ProtectedVideoType protected_video_type,
CALayerOverlayList* ca_layer_overlays) const {
CALayerOverlayProcessorInternal processor;
CALayerOverlay ca_layer;
@@ -471,6 +525,7 @@ bool CALayerOverlayProcessor::PutQuadInSeparateOverlay(
if (!AreClipSettingsValid(ca_layer, ca_layer_overlays))
return true;
+ ca_layer.protected_video_type = protected_video_type;
render_pass->ReplaceExistingQuadWithSolidColor(at, SK_ColorTRANSPARENT,
SkBlendMode::kSrcOver);
ca_layer_overlays->push_back(ca_layer);
diff --git a/chromium/components/viz/service/display/ca_layer_overlay.h b/chromium/components/viz/service/display/ca_layer_overlay.h
index 4be2ad18b76..b3a3180a6f8 100644
--- a/chromium/components/viz/service/display/ca_layer_overlay.h
+++ b/chromium/components/viz/service/display/ca_layer_overlay.h
@@ -9,16 +9,17 @@
#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/common/quads/compositor_render_pass.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/mailbox.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkMatrix44.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/rrect_f.h"
+#include "ui/gfx/video_types.h"
#include "ui/gl/ca_renderer_layer_params.h"
class SkDeferredDisplayList;
@@ -78,6 +79,9 @@ class VIZ_SERVICE_EXPORT CALayerOverlay {
unsigned edge_aa_mask = 0;
// The minification and magnification filters for the CALayer.
unsigned filter = 0;
+ // The protected video status of the AVSampleBufferDisplayLayer.
+ gfx::ProtectedVideoType protected_video_type =
+ gfx::ProtectedVideoType::kClear;
// If |rpdq| is present, then the renderer must draw the filter effects and
// copy the result into an IOSurface.
const AggregatedRenderPassDrawQuad* rpdq = nullptr;
@@ -131,6 +135,7 @@ class VIZ_SERVICE_EXPORT CALayerOverlayProcessor {
render_pass_filters,
const base::flat_map<AggregatedRenderPassId, cc::FilterOperations*>&
render_pass_backdrop_filters,
+ gfx::ProtectedVideoType protected_video_type,
CALayerOverlayList* ca_layer_overlays) const;
DISALLOW_COPY_AND_ASSIGN(CALayerOverlayProcessor);
diff --git a/chromium/components/viz/service/display/copy_output_scaling_pixeltest.cc b/chromium/components/viz/service/display/copy_output_scaling_pixeltest.cc
index b53fe44a771..89b4251d5b4 100644
--- a/chromium/components/viz/service/display/copy_output_scaling_pixeltest.cc
+++ b/chromium/components/viz/service/display/copy_output_scaling_pixeltest.cc
@@ -191,7 +191,7 @@ class CopyOutputScalingPixelTest
copy_output::ComputeResultRect(copy_rect, scale_from_, scale_to_);
EXPECT_EQ(expected_result_rect, result->rect());
EXPECT_EQ(result_format_, result->format());
- base::Optional<CopyOutputResult::ScopedSkBitmap> scoped_bitmap;
+ absl::optional<CopyOutputResult::ScopedSkBitmap> scoped_bitmap;
SkBitmap result_bitmap;
if (result_format_ == CopyOutputResult::Format::I420_PLANES) {
result_bitmap = ReadI420ResultToSkBitmap(*result);
diff --git a/chromium/components/viz/service/display/damage_frame_annotator.cc b/chromium/components/viz/service/display/damage_frame_annotator.cc
index 38d85d4e2ac..288bdb9fc75 100644
--- a/chromium/components/viz/service/display/damage_frame_annotator.cc
+++ b/chromium/components/viz/service/display/damage_frame_annotator.cc
@@ -53,7 +53,7 @@ void DamageFrameAnnotator::AnnotateRootRenderPass(
SharedQuadState* new_sqs = render_pass->shared_quad_state_list
.AllocateAndConstruct<SharedQuadState>();
new_sqs->SetAll(annotation.transform, output_rect, output_rect,
- gfx::MaskFilterInfo(), output_rect, true, false, 1.f,
+ gfx::MaskFilterInfo(), output_rect, false, 1.f,
SkBlendMode::kSrcOver, 0);
DebugBorderDrawQuad* new_quad =
diff --git a/chromium/components/viz/service/display/dc_layer_overlay.cc b/chromium/components/viz/service/display/dc_layer_overlay.cc
index 0db3f2431e7..4be7ffb0517 100644
--- a/chromium/components/viz/service/display/dc_layer_overlay.cc
+++ b/chromium/components/viz/service/display/dc_layer_overlay.cc
@@ -65,8 +65,8 @@ 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));
+ if (quad->shared_quad_state->clip_rect)
+ quad_rect.Intersect(gfx::RectF(*quad->shared_quad_state->clip_rect));
return quad_rect;
}
@@ -152,11 +152,10 @@ void FromYUVQuad(const YUVVideoDrawQuad* quad,
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) {
+ if (quad->shared_quad_state->clip_rect) {
// 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);
+ 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);
}
@@ -219,11 +218,10 @@ void FromTextureQuad(const TextureDrawQuad* quad,
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) {
+ if (quad->shared_quad_state->clip_rect) {
// 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);
+ 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);
}
@@ -542,8 +540,8 @@ void DCLayerOverlayProcessor::InsertDebugBorderDrawQuad(
for (const auto& dc_layer : *dc_layer_overlays) {
gfx::RectF overlay_rect(dc_layer.quad_rect);
dc_layer.transform.TransformRect(&overlay_rect);
- if (dc_layer.is_clipped)
- overlay_rect.Intersect(gfx::RectF(dc_layer.clip_rect));
+ if (dc_layer.clip_rect)
+ overlay_rect.Intersect(gfx::RectF(*dc_layer.clip_rect));
// Overlay:red, Underlay:blue.
SkColor border_color = dc_layer.z_order > 0 ? SK_ColorRED : SK_ColorBLUE;
diff --git a/chromium/components/viz/service/display/dc_layer_overlay.h b/chromium/components/viz/service/display/dc_layer_overlay.h
index 76cf3357573..142d3702b5a 100644
--- a/chromium/components/viz/service/display/dc_layer_overlay.h
+++ b/chromium/components/viz/service/display/dc_layer_overlay.h
@@ -58,9 +58,8 @@ class VIZ_SERVICE_EXPORT DCLayerOverlay {
// after applying the |quad_rect.origin()| as an offset.
gfx::Transform transform;
- // If |is_clipped| is true, then clip to |clip_rect| in root target space.
- bool is_clipped = false;
- gfx::Rect clip_rect;
+ // If |clip_rect| is present, then clip to it in root target space.
+ absl::optional<gfx::Rect> clip_rect;
// This is the color-space the texture should be displayed as. If invalid,
// then the default for the texture should be used. For YUV textures, that's
diff --git a/chromium/components/viz/service/display/delegated_ink_point_renderer_base.cc b/chromium/components/viz/service/display/delegated_ink_point_renderer_base.cc
index 16a282cd8a4..b0493314725 100644
--- a/chromium/components/viz/service/display/delegated_ink_point_renderer_base.cc
+++ b/chromium/components/viz/service/display/delegated_ink_point_renderer_base.cc
@@ -14,7 +14,7 @@ DelegatedInkPointRendererBase::DelegatedInkPointRendererBase() = default;
DelegatedInkPointRendererBase::~DelegatedInkPointRendererBase() = default;
void DelegatedInkPointRendererBase::InitMessagePipeline(
- mojo::PendingReceiver<mojom::DelegatedInkPointRenderer> receiver) {
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer> receiver) {
// The remote end of this pipeline exists on a per-tab basis, so if tab A
// is using the feature and then tab B starts trying to use it, a new
// PendingReceiver will arrive here while |receiver_| is still bound to the
@@ -53,7 +53,7 @@ void DelegatedInkPointRendererBase::SetDelegatedInkMetadata(
// If we aren't able to find any matching point, set the pointer ID to null
// so that FilterPoints and PredictPoints can early out.
- pointer_id_ = base::nullopt;
+ pointer_id_ = absl::nullopt;
}
std::vector<gfx::DelegatedInkPoint>
diff --git a/chromium/components/viz/service/display/delegated_ink_point_renderer_base.h b/chromium/components/viz/service/display/delegated_ink_point_renderer_base.h
index 00334339da9..69206455ec6 100644
--- a/chromium/components/viz/service/display/delegated_ink_point_renderer_base.h
+++ b/chromium/components/viz/service/display/delegated_ink_point_renderer_base.h
@@ -10,11 +10,11 @@
#include <utility>
#include <vector>
-#include "base/optional.h"
#include "components/viz/service/display/delegated_ink_trail_data.h"
#include "components/viz/service/viz_service_export.h"
#include "mojo/public/cpp/bindings/receiver.h"
-#include "services/viz/public/mojom/compositing/delegated_ink_point_renderer.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "ui/gfx/mojom/delegated_ink_point_renderer.mojom.h"
namespace gfx {
class DelegatedInkMetadata;
@@ -31,7 +31,7 @@ namespace viz {
// For more information on the feature, please see the explainer:
// https://github.com/WICG/ink-enhancement/blob/master/README.md
class VIZ_SERVICE_EXPORT DelegatedInkPointRendererBase
- : public mojom::DelegatedInkPointRenderer {
+ : public gfx::mojom::DelegatedInkPointRenderer {
public:
DelegatedInkPointRendererBase();
~DelegatedInkPointRendererBase() override;
@@ -40,7 +40,7 @@ class VIZ_SERVICE_EXPORT DelegatedInkPointRendererBase
const DelegatedInkPointRendererBase&) = delete;
void InitMessagePipeline(
- mojo::PendingReceiver<mojom::DelegatedInkPointRenderer> receiver);
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer> receiver);
void StoreDelegatedInkPoint(const gfx::DelegatedInkPoint& point) override;
virtual void SetDelegatedInkMetadata(
@@ -80,7 +80,7 @@ class VIZ_SERVICE_EXPORT DelegatedInkPointRendererBase
// Cached pointer id that matches the most recent metadata. This is set when
// a metadata arrives, and if no stored DelegatedInkPoints match the metadata,
// then it is null.
- base::Optional<int32_t> pointer_id_;
+ absl::optional<int32_t> pointer_id_;
// The points that arrived from the browser process and may be drawn as part
// of the ink trail are stored according to their pointer ids so that if
@@ -88,7 +88,7 @@ class VIZ_SERVICE_EXPORT DelegatedInkPointRendererBase
// of points to use when drawing the delegated ink trail.
std::unordered_map<int32_t, DelegatedInkTrailData> pointer_ids_;
- mojo::Receiver<mojom::DelegatedInkPointRenderer> receiver_{this};
+ mojo::Receiver<gfx::mojom::DelegatedInkPointRenderer> receiver_{this};
};
} // namespace viz
diff --git a/chromium/components/viz/service/display/delegated_ink_trail_data.cc b/chromium/components/viz/service/display/delegated_ink_trail_data.cc
index 51ecdff1cdd..5b521e7607b 100644
--- a/chromium/components/viz/service/display/delegated_ink_trail_data.cc
+++ b/chromium/components/viz/service/display/delegated_ink_trail_data.cc
@@ -7,11 +7,11 @@
#include <string>
#include "base/metrics/histogram_functions.h"
-#include "base/optional.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/trace_event/trace_event.h"
#include "components/viz/common/features.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/base/prediction/kalman_predictor.h"
#include "ui/gfx/delegated_ink_metadata.h"
#include "ui/gfx/delegated_ink_point.h"
@@ -26,7 +26,7 @@ DelegatedInkTrailData::DelegatedInkTrailData() {
for (int i = 0; i < kNumberOfPredictionConfigs; ++i) {
prediction_handlers_[i].metrics_handler =
std::make_unique<ui::PredictionMetricsHandler>(
- (full_name + base::NumberToString(i)).c_str());
+ base::StrCat({full_name, base::NumberToString(i)}));
prediction_handlers_[i].predictor =
std::make_unique<ui::KalmanPredictor>(predictor_options);
}
@@ -66,7 +66,7 @@ void DelegatedInkTrailData::PredictPoints(
// Used to know if the user enabled prediction, and if so, which prediction
// config they opted into.
- base::Optional<int> should_draw_predicted_ink_points =
+ absl::optional<int> should_draw_predicted_ink_points =
features::ShouldDrawPredictedInkPoints();
for (int experiment = 0; experiment < kNumberOfPredictionConfigs;
@@ -106,12 +106,7 @@ void DelegatedInkTrailData::PredictPoints(
// produce a prediction if the predicted point would go in to the
// opposite direction of most recently stored points. If this happens,
// don't continue trying to generate more predicted points.
- handler.metrics_handler->EvaluatePrediction();
- base::UmaHistogramTimes(
- base::StrCat(
- {histogram_base_name, base::NumberToString(experiment)}),
- latency_improvement_with_prediction);
- continue;
+ break;
}
}
}
diff --git a/chromium/components/viz/service/display/direct_renderer.cc b/chromium/components/viz/service/display/direct_renderer.cc
index 0e310698ff7..71261f1d210 100644
--- a/chromium/components/viz/service/display/direct_renderer.cc
+++ b/chromium/components/viz/service/display/direct_renderer.cc
@@ -476,8 +476,8 @@ bool DirectRenderer::ShouldSkipQuad(const DrawQuad& quad,
gfx::Rect target_rect = cc::MathUtil::MapEnclosingClippedRect(
quad.shared_quad_state->quad_to_target_transform, quad.visible_rect);
- if (quad.shared_quad_state->is_clipped)
- target_rect.Intersect(quad.shared_quad_state->clip_rect);
+ if (quad.shared_quad_state->clip_rect)
+ target_rect.Intersect(*quad.shared_quad_state->clip_rect);
target_rect.Intersect(render_pass_scissor);
return target_rect.IsEmpty();
@@ -489,12 +489,12 @@ void DirectRenderer::SetScissorStateForQuad(
bool use_render_pass_scissor) {
if (use_render_pass_scissor) {
gfx::Rect quad_scissor_rect = render_pass_scissor;
- if (quad.shared_quad_state->is_clipped)
- quad_scissor_rect.Intersect(quad.shared_quad_state->clip_rect);
+ if (quad.shared_quad_state->clip_rect)
+ quad_scissor_rect.Intersect(*quad.shared_quad_state->clip_rect);
SetScissorTestRectInDrawSpace(quad_scissor_rect);
return;
- } else if (quad.shared_quad_state->is_clipped) {
- SetScissorTestRectInDrawSpace(quad.shared_quad_state->clip_rect);
+ } else if (quad.shared_quad_state->clip_rect) {
+ SetScissorTestRectInDrawSpace(*quad.shared_quad_state->clip_rect);
return;
}
@@ -539,11 +539,11 @@ const cc::FilterOperations* DirectRenderer::BackdropFiltersForPass(
return it == render_pass_backdrop_filters_.end() ? nullptr : it->second;
}
-const base::Optional<gfx::RRectF> DirectRenderer::BackdropFilterBoundsForPass(
+const absl::optional<gfx::RRectF> DirectRenderer::BackdropFilterBoundsForPass(
AggregatedRenderPassId render_pass_id) const {
auto it = render_pass_backdrop_filter_bounds_.find(render_pass_id);
return it == render_pass_backdrop_filter_bounds_.end()
- ? base::Optional<gfx::RRectF>()
+ ? absl::optional<gfx::RRectF>()
: it->second;
}
@@ -802,12 +802,15 @@ gfx::Rect DirectRenderer::ComputeScissorRectForRenderPass(
const AggregatedRenderPass* root_render_pass =
current_frame()->root_render_pass;
gfx::Rect root_damage_rect = current_frame()->root_damage_rect;
+ // If |frame_buffer_damage|, which is carried over from the previous frame
+ // when we want to preserve buffer content, is not empty, we should add it
+ // to both root and non-root render passes.
+ gfx::Rect frame_buffer_damage =
+ output_surface_->GetCurrentFramebufferDamage();
if (render_pass == root_render_pass) {
base::CheckedNumeric<int64_t> display_area =
current_frame()->device_viewport_size.GetCheckedArea();
- gfx::Rect frame_buffer_damage =
- output_surface_->GetCurrentFramebufferDamage();
base::CheckedNumeric<int64_t> root_damage_area =
root_damage_rect.size().GetCheckedArea();
if (display_area.IsValid() && root_damage_area.IsValid()) {
@@ -880,7 +883,22 @@ gfx::Rect DirectRenderer::ComputeScissorRectForRenderPass(
DCHECK(render_pass->copy_requests.empty() ||
(render_pass->damage_rect == render_pass->output_rect));
- return render_pass->damage_rect;
+
+ // For the non-root render pass.
+ gfx::Rect damage_rect = render_pass->damage_rect;
+ if (!frame_buffer_damage.IsEmpty()) {
+ gfx::Transform inverse_transform(gfx::Transform::kSkipInitialization);
+ if (render_pass->transform_to_root_target.GetInverse(&inverse_transform)) {
+ // |frame_buffer_damage| is in the root target space. Transform the damage
+ // from the root to the non-root space before it's added.
+ gfx::Rect frame_buffer_damage_in_render_pass_space =
+ cc::MathUtil::MapEnclosingClippedRect(inverse_transform,
+ frame_buffer_damage);
+ damage_rect.Union(frame_buffer_damage_in_render_pass_space);
+ }
+ }
+
+ return damage_rect;
}
gfx::Size DirectRenderer::CalculateTextureSizeForRenderPass(
diff --git a/chromium/components/viz/service/display/direct_renderer.h b/chromium/components/viz/service/display/direct_renderer.h
index 9268fcaa462..22a9122f444 100644
--- a/chromium/components/viz/service/display/direct_renderer.h
+++ b/chromium/components/viz/service/display/direct_renderer.h
@@ -13,7 +13,6 @@
#include "base/containers/circular_deque.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/common/quads/tile_draw_quad.h"
@@ -24,10 +23,12 @@
#include "components/viz/service/display/overlay_processor_interface.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/texture_in_use_response.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/delegated_ink_metadata.h"
#include "ui/gfx/display_color_spaces.h"
#include "ui/gfx/geometry/quad_f.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/latency/latency_info.h"
namespace cc {
@@ -97,7 +98,8 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
};
virtual void SwapBuffers(SwapFrameData swap_frame_data) = 0;
virtual void SwapBuffersSkipped() {}
- virtual void SwapBuffersComplete() {}
+ virtual void SwapBuffersComplete(gfx::GpuFenceHandle release_fence) {}
+ virtual void BuffersPresented() {}
virtual void DidReceiveTextureInUseResponses(
const gpu::TextureInUseResponses& responses) {}
virtual void DidReceiveReleasedOverlays(
@@ -124,7 +126,7 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
// 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<OverlayProcessorInterface::OutputSurfaceOverlayPlane>
+ absl::optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>
output_surface_plane;
};
@@ -221,7 +223,7 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
AggregatedRenderPassId render_pass_id) const;
const cc::FilterOperations* BackdropFiltersForPass(
AggregatedRenderPassId render_pass_id) const;
- const base::Optional<gfx::RRectF> BackdropFilterBoundsForPass(
+ const absl::optional<gfx::RRectF> BackdropFilterBoundsForPass(
AggregatedRenderPassId render_pass_id) const;
// Private interface implemented by subclasses for use by DirectRenderer.
@@ -306,7 +308,7 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
render_pass_filters_;
base::flat_map<AggregatedRenderPassId, cc::FilterOperations*>
render_pass_backdrop_filters_;
- base::flat_map<AggregatedRenderPassId, base::Optional<gfx::RRectF>>
+ base::flat_map<AggregatedRenderPassId, absl::optional<gfx::RRectF>>
render_pass_backdrop_filter_bounds_;
base::flat_map<AggregatedRenderPassId, gfx::Rect>
backdrop_filter_output_rects_;
@@ -372,7 +374,7 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
gfx::Size device_viewport_size_;
float reshape_device_scale_factor_ = 0.f;
gfx::ColorSpace reshape_color_space_;
- base::Optional<gfx::BufferFormat> reshape_buffer_format_;
+ absl::optional<gfx::BufferFormat> reshape_buffer_format_;
bool reshape_use_stencil_ = false;
DISALLOW_COPY_AND_ASSIGN(DirectRenderer);
diff --git a/chromium/components/viz/service/display/display.cc b/chromium/components/viz/service/display/display.cc
index 67efacb47bc..f371b4fb836 100644
--- a/chromium/components/viz/service/display/display.cc
+++ b/chromium/components/viz/service/display/display.cc
@@ -9,10 +9,9 @@
#include <limits>
#include <utility>
+#include "base/containers/contains.h"
#include "base/debug/dump_without_crashing.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
-#include "base/stl_util.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -26,6 +25,7 @@
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/quads/shared_quad_state.h"
#include "components/viz/common/viz_utils.h"
+#include "components/viz/service/debugger/viz_debugger.h"
#include "components/viz/service/display/aggregated_frame.h"
#include "components/viz/service/display/damage_frame_annotator.h"
#include "components/viz/service/display/direct_renderer.h"
@@ -49,9 +49,12 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/ipc/scheduler_sequence.h"
#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_latency_info.pbzero.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/overlay_transform_utils.h"
#include "ui/gfx/presentation_feedback.h"
#include "ui/gfx/swap_result.h"
@@ -599,6 +602,40 @@ void Display::OnContextLost() {
client_->DisplayOutputSurfaceLost();
}
+namespace {
+void DebugDrawFrame(const AggregatedFrame& frame) {
+ if (!VizDebugger::GetInstance()->IsEnabled())
+ return;
+
+ auto& root_render_pass = *frame.render_pass_list.back();
+ for (auto* quad : root_render_pass.quad_list) {
+ auto& transform = quad->shared_quad_state->quad_to_target_transform;
+ auto display_rect = gfx::RectF(quad->rect);
+ transform.TransformRect(&display_rect);
+
+ DBG_DRAW_RECT("frame.root.quad", display_rect);
+ }
+}
+
+void VisualDebuggerSync(gfx::OverlayTransform current_display_transform,
+ gfx::Size current_surface_size,
+ int64_t last_presented_trace_id) {
+ if (!VizDebugger::GetInstance()->IsEnabled())
+ return;
+
+ const gfx::Transform display_transform = gfx::OverlayTransformToTransform(
+ current_display_transform, gfx::SizeF(current_surface_size));
+ current_surface_size =
+ cc::MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
+ display_transform, gfx::Rect(current_surface_size))
+ .size();
+
+ VizDebugger::GetInstance()->CompleteFrame(
+ last_presented_trace_id, current_surface_size, base::TimeTicks::Now());
+}
+
+} // namespace
+
bool Display::DrawAndSwap(base::TimeTicks expected_display_time) {
TRACE_EVENT0("viz", "Display::DrawAndSwap");
if (debug_settings_->show_aggregated_damage !=
@@ -635,6 +672,10 @@ bool Display::DrawAndSwap(base::TimeTicks expected_display_time) {
}
}
+ base::ScopedClosureRunner visual_debugger_sync_scoped_exit(
+ base::BindOnce(&VisualDebuggerSync, current_display_transform,
+ current_surface_size_, last_presented_trace_id_));
+
// During aggregation, SurfaceAggregator marks all resources used for a draw
// in the resource provider. This has the side effect of deleting unused
// resources and their textures, generating sync tokens, and returning the
@@ -667,6 +708,7 @@ bool Display::DrawAndSwap(base::TimeTicks expected_display_time) {
current_surface_id_, expected_display_time, current_display_transform,
target_damage_bounding_rect, ++swapped_trace_id_);
}
+ DebugDrawFrame(frame);
// Records whether the aggregated frame contains video or not.
// TODO(vikassoni) : Extend this capability to record whether a video frame is
@@ -759,7 +801,7 @@ bool Display::DrawAndSwap(base::TimeTicks expected_display_time) {
bool should_draw = have_copy_requests || (have_damage && size_matches);
client_->DisplayWillDrawAndSwap(should_draw, &frame.render_pass_list);
- base::Optional<base::ElapsedTimer> draw_timer;
+ absl::optional<base::ElapsedTimer> draw_timer;
if (should_draw) {
TRACE_EVENT_ASYNC_STEP_INTO0("viz,benchmark",
"Graphics.Pipeline.DrawAndSwap",
@@ -899,7 +941,9 @@ bool Display::DrawAndSwap(base::TimeTicks expected_display_time) {
return true;
}
-void Display::DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings) {
+void Display::DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings,
+ gfx::GpuFenceHandle release_fence) {
+ DCHECK(release_fence.is_null());
// Adding to |pending_presentation_group_timings_| must
// have been done in DrawAndSwap(), and should not be popped until
// DidReceiveSwapBuffersAck.
@@ -925,7 +969,7 @@ void Display::DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings) {
if (overlay_processor_)
overlay_processor_->OverlayPresentationComplete();
if (renderer_)
- renderer_->SwapBuffersComplete();
+ renderer_->SwapBuffersComplete(std::move(release_fence));
// It's possible to receive multiple calls to DidReceiveSwapBuffersAck()
// before DidReceivePresentationFeedback(). Ensure that we're not setting
@@ -1000,6 +1044,9 @@ void Display::DidSwapWithSize(const gfx::Size& pixel_size) {
void Display::DidReceivePresentationFeedback(
const gfx::PresentationFeedback& feedback) {
+ if (renderer_)
+ renderer_->BuffersPresented();
+
if (pending_presentation_group_timings_.empty()) {
DLOG(ERROR) << "Received unexpected PresentationFeedback";
return;
@@ -1164,8 +1211,8 @@ void Display::RemoveOverdrawQuads(AggregatedFrame* frame) {
last_sqs->mask_filter_info.rounded_corner_bounds())));
}
- if (last_sqs->is_clipped)
- sqs_rect_in_target.Intersect(last_sqs->clip_rect);
+ if (last_sqs->clip_rect)
+ sqs_rect_in_target.Intersect(*last_sqs->clip_rect);
// If region complexity is above our threshold, remove the smallest
// rects from occlusion region.
@@ -1337,9 +1384,17 @@ void Display::PreserveChildSurfaceControls() {
}
}
-DelegatedInkPointRendererBase* Display::GetDelegatedInkPointRenderer(
- bool create_if_necessary) {
- return renderer_->GetDelegatedInkPointRenderer(create_if_necessary);
+void Display::InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) {
+ if (DoesPlatformSupportDelegatedInk() &&
+ features::ShouldUsePlatformDelegatedInk()) {
+ output_surface_->InitDelegatedInkPointRendererReceiver(
+ std::move(pending_receiver));
+ } else {
+ renderer_->GetDelegatedInkPointRenderer(/*create_if_necessary=*/true)
+ ->InitMessagePipeline(std::move(pending_receiver));
+ }
}
} // namespace viz
diff --git a/chromium/components/viz/service/display/display.h b/chromium/components/viz/service/display/display.h
index 09d46308dee..ab5074109db 100644
--- a/chromium/components/viz/service/display/display.h
+++ b/chromium/components/viz/service/display/display.h
@@ -49,7 +49,6 @@ class ScopedAllowScheduleGpuTask;
namespace viz {
class AggregatedFrame;
-class DelegatedInkPointRendererBase;
class DirectRenderer;
class DisplayClient;
class DisplayResourceProvider;
@@ -151,7 +150,8 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
// OutputSurfaceClient implementation.
void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override;
- void DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings) override;
+ void DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings,
+ gfx::GpuFenceHandle release_fence) override;
void DidReceiveTextureInUseResponses(
const gpu::TextureInUseResponses& responses) override;
void DidReceiveCALayerParams(
@@ -195,11 +195,16 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
bool IsRootFrameMissing() const;
bool HasPendingSurfaces(const BeginFrameArgs& args) const;
- // Return the delegated ink point renderer from |renderer_|, creating it if
- // one doesn't exist. Should only be used when the delegated ink trails web
- // API has been used.
- DelegatedInkPointRendererBase* GetDelegatedInkPointRenderer(
- bool create_if_necessary);
+ bool DoesPlatformSupportDelegatedInk() const {
+ return output_surface_->capabilities().supports_delegated_ink;
+ }
+
+ // If the platform supports delegated ink trails, then forward the pending
+ // receiver to the gpu main thread where it will be bound so that points can
+ // be sent directly there from the browser process and bypass viz.
+ void InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver);
private:
friend class DisplayTest;
diff --git a/chromium/components/viz/service/display/display_perftest.cc b/chromium/components/viz/service/display/display_perftest.cc
index 22f2bf904f5..1d9ce188bd2 100644
--- a/chromium/components/viz/service/display/display_perftest.cc
+++ b/chromium/components/viz/service/display/display_perftest.cc
@@ -90,7 +90,6 @@ class RemoveOverdrawQuadPerfTest : public testing::Test {
SharedQuadState* CreateSharedQuadState(AggregatedRenderPass* render_pass,
gfx::Rect rect) {
gfx::Transform quad_transform = gfx::Transform();
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
int sorting_context_id = 65536;
@@ -98,8 +97,9 @@ class RemoveOverdrawQuadPerfTest : public testing::Test {
SharedQuadState* state = render_pass->CreateAndAppendSharedQuadState();
state->SetAll(quad_transform, rect, rect,
- /*mask_filter_info=*/gfx::MaskFilterInfo(), rect, is_clipped,
- are_contents_opaque, opacity, blend_mode, sorting_context_id);
+ /*mask_filter_info=*/gfx::MaskFilterInfo(),
+ /*clip_rect=*/absl::nullopt, are_contents_opaque, opacity,
+ blend_mode, sorting_context_id);
return state;
}
diff --git a/chromium/components/viz/service/display/display_resource_provider.cc b/chromium/components/viz/service/display/display_resource_provider.cc
index 0cb87dae120..d0738b30a4f 100644
--- a/chromium/components/viz/service/display/display_resource_provider.cc
+++ b/chromium/components/viz/service/display/display_resource_provider.cc
@@ -120,42 +120,15 @@ bool DisplayResourceProvider::IsBackedBySurfaceTexture(ResourceId id) {
return resource->transferable.is_backed_by_surface_texture;
}
-size_t DisplayResourceProvider::CountPromotionHintRequestsForTesting() {
- return wants_promotion_hints_set_.size();
-}
-
-void DisplayResourceProvider::InitializePromotionHintRequest(ResourceId id) {
+bool DisplayResourceProvider::DoesResourceWantPromotionHint(ResourceId id) {
ChildResource* resource = TryGetResource(id);
// TODO(ericrk): We should never fail TryGetResource, but we appear to
// be doing so on Android in rare cases. Handle this gracefully until a
// better solution can be found. https://crbug.com/811858
- if (!resource)
- return;
-
- // We could sync all |wants_promotion_hint| resources elsewhere, and send 'no'
- // to all resources that weren't used. However, there's no real advantage.
- if (resource->transferable.wants_promotion_hint)
- wants_promotion_hints_set_.insert(id);
+ return resource && resource->transferable.wants_promotion_hint;
}
#endif
-bool DisplayResourceProvider::DoesResourceWantPromotionHint(
- ResourceId id) const {
-#if defined(OS_ANDROID)
- return wants_promotion_hints_set_.count(id) > 0;
-#else
- return false;
-#endif
-}
-
-bool DisplayResourceProvider::DoAnyResourcesWantPromotionHints() const {
-#if defined(OS_ANDROID)
- return wants_promotion_hints_set_.size() > 0;
-#else
- return false;
-#endif
-}
-
bool DisplayResourceProvider::IsOverlayCandidate(ResourceId id) {
ChildResource* resource = TryGetResource(id);
// TODO(ericrk): We should never fail TryGetResource, but we appear to
@@ -164,6 +137,16 @@ bool DisplayResourceProvider::IsOverlayCandidate(ResourceId id) {
return resource && resource->transferable.is_overlay_candidate;
}
+SurfaceId DisplayResourceProvider::GetSurfaceId(ResourceId id) {
+ ChildResource* resource = GetResource(id);
+ return children_[resource->child_id].surface_id;
+}
+
+int DisplayResourceProvider::GetChildId(ResourceId id) {
+ ChildResource* resource = GetResource(id);
+ return resource->child_id;
+}
+
bool DisplayResourceProvider::IsResourceSoftwareBacked(ResourceId id) {
return GetResource(id)->transferable.is_software;
}
@@ -182,12 +165,15 @@ const gfx::ColorSpace& DisplayResourceProvider::GetColorSpace(ResourceId id) {
return resource->transferable.color_space;
}
-int DisplayResourceProvider::CreateChild(ReturnCallback return_callback) {
+int DisplayResourceProvider::CreateChild(ReturnCallback return_callback,
+ const SurfaceId& surface_id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
int child_id = next_child_++;
Child& child = children_[child_id];
+ child.id = child_id;
child.return_callback = std::move(return_callback);
+ child.surface_id = surface_id;
return child_id;
}
@@ -225,7 +211,9 @@ void DisplayResourceProvider::ReceiveFromChild(
resource.mailbox_holder.mailbox.IsZero()) {
TRACE_EVENT0(
"viz", "DisplayResourceProvider::ReceiveFromChild dropping invalid");
- child_info.return_callback.Run({resource.ToReturnedResource()});
+ std::vector<ReturnedResource> returned;
+ returned.push_back(resource.ToReturnedResource());
+ child_info.return_callback.Run(std::move(returned));
continue;
}
@@ -315,16 +303,6 @@ bool DisplayResourceProvider::ReadLockFenceHasPassed(
return !resource->read_lock_fence || resource->read_lock_fence->HasPassed();
}
-#if defined(OS_ANDROID)
-void DisplayResourceProvider::DeletePromotionHint(ResourceMap::iterator it) {
- ChildResource* resource = &it->second;
- // If this resource was interested in promotion hints, then remove it from
- // the set of resources that we'll notify.
- if (resource->transferable.wants_promotion_hint)
- wants_promotion_hints_set_.erase(it->first);
-}
-#endif
-
DisplayResourceProvider::CanDeleteNowResult
DisplayResourceProvider::CanDeleteNow(const Child& child_info,
const ChildResource& resource,
@@ -361,11 +339,8 @@ void DisplayResourceProvider::DeleteAndReturnUnusedResourcesToChild(
if (unused.empty() && !child_info.marked_for_deletion)
return;
- // Store unused resources while batching is enabled or we can't access gpu
- // thread right now.
- // TODO(vasilyt): Technically we need to delay only resources with
- // |image_context|.
- if (batch_return_resources_lock_count_ > 0 || !can_access_gpu_thread_) {
+ // Store unused resources while batching is enabled.
+ if (batch_return_resources_lock_count_ > 0) {
int child_id = child_it->first;
auto& child_resources = batched_returning_resources_[child_id];
child_resources.reserve(child_resources.size() + unused.size());
@@ -377,7 +352,7 @@ void DisplayResourceProvider::DeleteAndReturnUnusedResourcesToChild(
DeleteAndReturnUnusedResourcesToChildImpl(child_info, style, unused);
if (!to_return.empty())
- child_info.return_callback.Run(to_return);
+ child_info.return_callback.Run(std::move(to_return));
if (child_info.marked_for_deletion &&
child_info.child_to_parent_map.empty()) {
@@ -481,6 +456,18 @@ DisplayResourceProvider::ScopedReadLockSharedImage::operator=(
return *this;
}
+void DisplayResourceProvider::ScopedReadLockSharedImage::SetReleaseFence(
+ gfx::GpuFenceHandle release_fence) {
+ DCHECK(resource_);
+ resource_->release_fence = std::move(release_fence);
+}
+
+bool DisplayResourceProvider::ScopedReadLockSharedImage::HasReadLockFence()
+ const {
+ DCHECK(resource_);
+ return resource_->transferable.read_lock_fences_enabled;
+}
+
void DisplayResourceProvider::ScopedReadLockSharedImage::Reset() {
if (!resource_provider_)
return;
diff --git a/chromium/components/viz/service/display/display_resource_provider.h b/chromium/components/viz/service/display/display_resource_provider.h
index 5534e2426cc..c9cea0ded48 100644
--- a/chromium/components/viz/service/display/display_resource_provider.h
+++ b/chromium/components/viz/service/display/display_resource_provider.h
@@ -22,6 +22,7 @@
#include "components/viz/common/resources/return_callback.h"
#include "components/viz/common/resources/shared_bitmap.h"
#include "components/viz/common/resources/transferable_resource.h"
+#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/service/display/external_use_client.h"
#include "components/viz/service/display/resource_fence.h"
#include "components/viz/service/viz_service_export.h"
@@ -74,18 +75,9 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
// can't really be promoted to an overlay.
bool IsBackedBySurfaceTexture(ResourceId id);
- // Return the number of resources that request promotion hints.
- size_t CountPromotionHintRequestsForTesting();
-
- // This should be called after WaitSyncToken in GLRenderer.
- void InitializePromotionHintRequest(ResourceId id);
-#endif
-
// Indicates if this resource wants to receive promotion hints.
- bool DoesResourceWantPromotionHint(ResourceId id) const;
-
- // Return true if and only if any resource wants a promotion hint.
- bool DoAnyResourcesWantPromotionHints() const;
+ bool DoesResourceWantPromotionHint(ResourceId id);
+#endif
bool IsResourceSoftwareBacked(ResourceId id);
// Return the format of the underlying buffer that can be used for scanout.
@@ -94,6 +86,8 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
const gfx::ColorSpace& GetColorSpace(ResourceId id);
// Indicates if this resource may be used for a hardware overlay plane.
bool IsOverlayCandidate(ResourceId id);
+ SurfaceId GetSurfaceId(ResourceId id);
+ int GetChildId(ResourceId id);
// Checks whether a resource is in use.
bool InUse(ResourceId id);
@@ -127,6 +121,16 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
return resource_->sync_token();
}
+ // Sets the given |release_fence| onto this resource.
+ // This is propagated to ReturnedResource when the resource is freed.
+ void SetReleaseFence(gfx::GpuFenceHandle release_fence);
+
+ // Returns true iff this resource has a read lock fence set.
+ bool HasReadLockFence() const;
+
+ protected:
+ ChildResource* resource() { return resource_; }
+
private:
void Reset();
@@ -156,8 +160,11 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
current_read_lock_fence_ = fence;
}
- // Creates accounting for a child. Returns a child ID.
- int CreateChild(ReturnCallback return_callback);
+ // Creates accounting for a child. Returns a child ID. surface_id is used to
+ // associate resources to the surface they belong to. This is used for
+ // overlays on webview where overlays are updated outside of normal draw (i.e
+ // DrawAndSwap isn't called).
+ int CreateChild(ReturnCallback return_callback, const SurfaceId& surface_id);
// Destroys accounting for the child, deleting all accounted resources.
void DestroyChild(int child);
@@ -237,9 +244,11 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
Child& operator=(Child&& other);
~Child();
+ int id;
std::unordered_map<ResourceId, ResourceId, ResourceIdHasher>
child_to_parent_map;
ReturnCallback return_callback;
+ SurfaceId surface_id;
bool marked_for_deletion = false;
};
@@ -328,6 +337,10 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
// to avoid map lookups further down the pipeline.
std::unique_ptr<ExternalUseClient::ImageContext> image_context;
+ // A release fence to propagate to ReturnedResource so clients may
+ // use it.
+ gfx::GpuFenceHandle release_fence;
+
private:
// Tracks if a sync token needs to be waited on before using the resource.
SynchronizationState synchronization_state_;
@@ -355,9 +368,6 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
// specified filter for both minification and magnification. Returns the
// texture target used. The resource must be locked for reading.
bool ReadLockFenceHasPassed(const ChildResource* resource);
-#if defined(OS_ANDROID)
- void DeletePromotionHint(ResourceMap::iterator it);
-#endif
void DeleteAndReturnUnusedResourcesToChild(
ChildMap::iterator child_it,
@@ -400,11 +410,6 @@ class VIZ_SERVICE_EXPORT DisplayResourceProvider
// resource providers.
int tracing_id_;
-#if defined(OS_ANDROID)
- // Set of ResourceIds that would like to be notified about promotion hints.
- ResourceIdSet wants_promotion_hints_set_;
-#endif
-
// Indicates that gpu thread is available and calls like
// ReleaseImageContexts() are expected to finish in finite time. It's always
// true for Chrome, but on WebView we need to have access to RenderThread.
diff --git a/chromium/components/viz/service/display/display_resource_provider_gl.cc b/chromium/components/viz/service/display/display_resource_provider_gl.cc
index 1a3fa91b13c..0deaa090ef7 100644
--- a/chromium/components/viz/service/display/display_resource_provider_gl.cc
+++ b/chromium/components/viz/service/display/display_resource_provider_gl.cc
@@ -191,6 +191,7 @@ DisplayResourceProviderGL::DeleteAndReturnUnusedResourcesToChildImpl(
GLES2Interface* gl = ContextGL();
DCHECK(gl);
+ DCHECK(can_access_gpu_thread_);
for (ResourceId local_id : unused) {
auto it = resources_.find(local_id);
CHECK(it != resources_.end());
@@ -222,6 +223,7 @@ DisplayResourceProviderGL::DeleteAndReturnUnusedResourcesToChildImpl(
}
to_return.emplace_back(child_id, resource.sync_token(),
+ std::move(resource.release_fence),
resource.imported_count, is_lost);
auto& returned = to_return.back();
@@ -234,9 +236,6 @@ DisplayResourceProviderGL::DeleteAndReturnUnusedResourcesToChildImpl(
child_info.child_to_parent_map.erase(child_id);
resource.imported_count = 0;
-#if defined(OS_ANDROID)
- DeletePromotionHint(it);
-#endif
DeleteResourceInternal(it);
}
@@ -270,11 +269,6 @@ void DisplayResourceProviderGL::WaitSyncToken(ResourceId id) {
if (!resource)
return;
WaitSyncTokenInternal(resource);
-
-#if defined(OS_ANDROID)
- // Now that the resource is synced, we may send it a promotion hint.
- InitializePromotionHintRequest(id);
-#endif
}
GLenum DisplayResourceProviderGL::BindForSampling(ResourceId resource_id,
@@ -335,6 +329,7 @@ DisplayResourceProviderGL::ScopedReadLockGL::ScopedReadLockGL(
target_ = resource->transferable.mailbox_holder.texture_target;
size_ = resource->transferable.size;
color_space_ = resource->transferable.color_space;
+ hdr_metadata_ = resource->transferable.hdr_metadata;
}
DisplayResourceProviderGL::ScopedReadLockGL::~ScopedReadLockGL() {
diff --git a/chromium/components/viz/service/display/display_resource_provider_gl.h b/chromium/components/viz/service/display/display_resource_provider_gl.h
index c4665882aec..f249233af8e 100644
--- a/chromium/components/viz/service/display/display_resource_provider_gl.h
+++ b/chromium/components/viz/service/display/display_resource_provider_gl.h
@@ -49,6 +49,9 @@ class VIZ_SERVICE_EXPORT DisplayResourceProviderGL
GLenum target() const { return target_; }
const gfx::Size& size() const { return size_; }
const gfx::ColorSpace& color_space() const { return color_space_; }
+ const absl::optional<gfx::HDRMetadata>& hdr_metadata() const {
+ return hdr_metadata_;
+ }
private:
DisplayResourceProviderGL* const resource_provider_;
@@ -58,6 +61,7 @@ class VIZ_SERVICE_EXPORT DisplayResourceProviderGL
GLenum target_ = GL_TEXTURE_2D;
gfx::Size size_;
gfx::ColorSpace color_space_;
+ absl::optional<gfx::HDRMetadata> hdr_metadata_;
};
class VIZ_SERVICE_EXPORT ScopedSamplerGL {
@@ -79,6 +83,9 @@ class VIZ_SERVICE_EXPORT DisplayResourceProviderGL
const gfx::ColorSpace& color_space() const {
return resource_lock_.color_space();
}
+ const absl::optional<gfx::HDRMetadata>& hdr_metadata() const {
+ return resource_lock_.hdr_metadata();
+ }
private:
const ScopedReadLockGL resource_lock_;
diff --git a/chromium/components/viz/service/display/display_resource_provider_gl_unittest.cc b/chromium/components/viz/service/display/display_resource_provider_gl_unittest.cc
index 0976f4e81df..c2694679a48 100644
--- a/chromium/components/viz/service/display/display_resource_provider_gl_unittest.cc
+++ b/chromium/components/viz/service/display/display_resource_provider_gl_unittest.cc
@@ -19,9 +19,9 @@
#include "base/memory/ref_counted.h"
#include "build/build_config.h"
#include "components/viz/client/client_resource_provider.h"
+#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/resources/returned_resource.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/test/test_context_provider.h"
#include "components/viz/test/test_gles2_interface.h"
#include "gpu/GLES2/gl2extchromium.h"
@@ -52,8 +52,9 @@ MATCHER_P(MatchesSyncToken, sync_token, "") {
}
static void CollectResources(std::vector<ReturnedResource>* array,
- const std::vector<ReturnedResource>& returned) {
- array->insert(array->end(), returned.begin(), returned.end());
+ std::vector<ReturnedResource> returned) {
+ array->insert(array->end(), std::make_move_iterator(returned.begin()),
+ std::make_move_iterator(returned.end()));
}
class ResourceProviderGLES2Interface : public TestGLES2Interface {
@@ -136,7 +137,7 @@ class DisplayResourceProviderGLTest : public testing::Test {
DisplayResourceProvider* resource_provider) {
ReturnCallback return_callback = base::DoNothing();
- int child = resource_provider->CreateChild(return_callback);
+ int child = resource_provider->CreateChild(return_callback, SurfaceId());
gpu::Mailbox gpu_mailbox = gpu::Mailbox::Generate();
constexpr gfx::Size size(64, 64);
@@ -170,12 +171,12 @@ TEST_F(DisplayResourceProviderGLTest, ReadLockCountStopsReturnToChildOrDelete) {
MockReleaseCallback release;
TransferableResource tran = CreateResource(RGBA_8888);
ResourceId id1 = child_resource_provider_->ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ int child_id = resource_provider_->CreateChild(
+ GetReturnCallback(&returned_to_child), SurfaceId());
{
// Transfer some resources to the parent.
std::vector<TransferableResource> list;
@@ -201,7 +202,8 @@ TEST_F(DisplayResourceProviderGLTest, ReadLockCountStopsReturnToChildOrDelete) {
}
EXPECT_EQ(1u, returned_to_child.size());
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
// No need to wait for the sync token here -- it will be returned to the
// client on delete.
@@ -232,12 +234,12 @@ TEST_F(DisplayResourceProviderGLTest, ReadLockFenceStopsReturnToChildOrDelete) {
TransferableResource tran1 = CreateResource(RGBA_8888);
tran1.read_lock_fences_enabled = true;
ResourceId id1 = child_resource_provider_->ImportResource(
- tran1, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran1, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ int child_id = resource_provider_->CreateChild(
+ GetReturnCallback(&returned_to_child), SurfaceId());
// Transfer some resources to the parent.
std::vector<TransferableResource> list;
@@ -272,7 +274,8 @@ TEST_F(DisplayResourceProviderGLTest, ReadLockFenceStopsReturnToChildOrDelete) {
resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
EXPECT_EQ(1u, returned_to_child.size());
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
EXPECT_CALL(release, Released(_, _));
child_resource_provider_->RemoveImportedResource(id1);
}
@@ -283,18 +286,18 @@ TEST_F(DisplayResourceProviderGLTest, ReadLockFenceDestroyChild) {
TransferableResource tran1 = CreateResource(RGBA_8888);
tran1.read_lock_fences_enabled = true;
ResourceId id1 = child_resource_provider_->ImportResource(
- tran1, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran1, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
TransferableResource tran2 = CreateResource(RGBA_8888);
tran2.read_lock_fences_enabled = false;
ResourceId id2 = child_resource_provider_->ImportResource(
- tran2, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran2, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ int child_id = resource_provider_->CreateChild(
+ GetReturnCallback(&returned_to_child), SurfaceId());
// Transfer resources to the parent.
std::vector<TransferableResource> list;
@@ -334,7 +337,8 @@ TEST_F(DisplayResourceProviderGLTest, ReadLockFenceDestroyChild) {
EXPECT_EQ(returned_to_child[0].lost, returned_to_child[0].id == id1);
EXPECT_EQ(returned_to_child[1].lost, returned_to_child[1].id == id1);
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
EXPECT_CALL(release, Released(_, _)).Times(2);
child_resource_provider_->RemoveImportedResource(id1);
child_resource_provider_->RemoveImportedResource(id2);
@@ -346,8 +350,8 @@ TEST_F(DisplayResourceProviderGLTest,
MockReleaseCallback release;
std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ int child_id = resource_provider_->CreateChild(
+ GetReturnCallback(&returned_to_child), SurfaceId());
// Transfer some resources to the parent.
constexpr size_t kTotalResources = 5;
@@ -357,8 +361,8 @@ TEST_F(DisplayResourceProviderGLTest,
for (auto& id : ids) {
TransferableResource tran = CreateResource(RGBA_8888);
id = child_resource_provider_->ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
}
std::vector<ResourceId> resource_ids_to_transfer(ids, ids + kTotalResources);
@@ -395,7 +399,8 @@ TEST_F(DisplayResourceProviderGLTest,
EXPECT_EQ(0u, returned_to_child.size());
}
EXPECT_EQ(1u, returned_to_child.size());
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
returned_to_child.clear();
// Return all locked resources.
@@ -417,7 +422,8 @@ TEST_F(DisplayResourceProviderGLTest,
for (const auto& resource : returned_to_child)
EXPECT_EQ(resource.sync_token, returned_to_child[0].sync_token);
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
returned_to_child.clear();
// Returns from destroying the child is also batched.
@@ -428,7 +434,8 @@ TEST_F(DisplayResourceProviderGLTest,
EXPECT_EQ(0u, returned_to_child.size());
}
EXPECT_EQ(1u, returned_to_child.size());
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
returned_to_child.clear();
EXPECT_CALL(release, Released(_, _)).Times(kTotalResources);
@@ -489,9 +496,8 @@ class ResourceProviderTestImportedResourceGLFilters {
MockReleaseCallback release;
ResourceId resource_id = child_resource_provider->ImportResource(
- resource,
- SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ resource, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
EXPECT_NE(kInvalidResourceId, resource_id);
testing::Mock::VerifyAndClearExpectations(child_gl);
@@ -500,7 +506,8 @@ class ResourceProviderTestImportedResourceGLFilters {
std::vector<TransferableResource> send_to_parent;
std::vector<ReturnedResource> returned_to_child;
int child_id = resource_provider->CreateChild(
- base::BindRepeating(&CollectResources, &returned_to_child));
+ base::BindRepeating(&CollectResources, &returned_to_child),
+ SurfaceId());
child_resource_provider->PrepareSendToParent(
{resource_id}, &send_to_parent,
static_cast<RasterContextProvider*>(child_context_provider.get()));
@@ -549,7 +556,8 @@ class ResourceProviderTestImportedResourceGLFilters {
// being in use.
resource_provider->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
EXPECT_EQ(1u, returned_to_child.size());
- child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
gpu::SyncToken released_sync_token;
{
@@ -602,8 +610,7 @@ TEST_F(DisplayResourceProviderGLTest, ReceiveGLTextureExternalOES) {
EXPECT_CALL(*child_gl, CreateAndConsumeTextureCHROMIUM(_)).Times(0);
gpu::Mailbox gpu_mailbox = gpu::Mailbox::Generate();
- std::unique_ptr<SingleReleaseCallback> callback =
- SingleReleaseCallback::Create(base::DoNothing());
+ ReleaseCallback callback = base::DoNothing();
constexpr gfx::Size size(64, 64);
auto resource = TransferableResource::MakeGL(
@@ -620,7 +627,7 @@ TEST_F(DisplayResourceProviderGLTest, ReceiveGLTextureExternalOES) {
std::vector<TransferableResource> send_to_parent;
std::vector<ReturnedResource> returned_to_child;
int child_id = resource_provider->CreateChild(
- base::BindRepeating(&CollectResources, &returned_to_child));
+ base::BindRepeating(&CollectResources, &returned_to_child), SurfaceId());
child_resource_provider->PrepareSendToParent(
{resource_id}, &send_to_parent,
static_cast<RasterContextProvider*>(child_context_provider_.get()));
@@ -662,7 +669,8 @@ TEST_F(DisplayResourceProviderGLTest, ReceiveGLTextureExternalOES) {
// being in use.
resource_provider->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
EXPECT_EQ(1u, returned_to_child.size());
- child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
child_resource_provider->RemoveImportedResource(resource_id);
}
@@ -705,95 +713,5 @@ TEST_F(DisplayResourceProviderGLTest, WaitSyncTokenIfNeeded) {
}
}
-#if defined(OS_ANDROID)
-TEST_F(DisplayResourceProviderGLTest, OverlayPromotionHint) {
- gpu::Mailbox external_mailbox = gpu::Mailbox::Generate();
- gpu::SyncToken external_sync_token = GenSyncToken();
- EXPECT_TRUE(external_sync_token.HasData());
-
- TransferableResource id1_transfer = TransferableResource::MakeGL(
- external_mailbox, GL_LINEAR, GL_TEXTURE_EXTERNAL_OES, external_sync_token,
- gfx::Size(1, 1), true);
- id1_transfer.wants_promotion_hint = true;
- id1_transfer.is_backed_by_surface_texture = true;
- ResourceId id1 = child_resource_provider_->ImportResource(
- id1_transfer, SingleReleaseCallback::Create(base::DoNothing()));
-
- TransferableResource id2_transfer = TransferableResource::MakeGL(
- external_mailbox, GL_LINEAR, GL_TEXTURE_EXTERNAL_OES, external_sync_token,
- gfx::Size(1, 1), true);
- id2_transfer.wants_promotion_hint = false;
- id2_transfer.is_backed_by_surface_texture = false;
- ResourceId id2 = child_resource_provider_->ImportResource(
- id2_transfer, SingleReleaseCallback::Create(base::DoNothing()));
-
- std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
-
- // Transfer some resources to the parent.
- std::vector<TransferableResource> list;
- child_resource_provider_->PrepareSendToParent(
- {id1, id2}, &list,
- static_cast<RasterContextProvider*>(child_context_provider_.get()));
- ASSERT_EQ(2u, list.size());
- resource_provider_->ReceiveFromChild(child_id, list);
- std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map =
- resource_provider_->GetChildToParentMap(child_id);
- ResourceId mapped_id1 = resource_map[list[0].id];
- ResourceId mapped_id2 = resource_map[list[1].id];
-
- // The promotion hints should not be recorded until after we wait. This is
- // because we can't notify them until they're synchronized, and we choose to
- // ignore unwaited resources rather than send them a "no" hint. If they end
- // up in the request set before we wait, then the attempt to notify them wil;
- // DCHECK when we try to lock them for reading in SendPromotionHints.
- EXPECT_EQ(0u, resource_provider_->CountPromotionHintRequestsForTesting());
- EXPECT_FALSE(resource_provider_->DoAnyResourcesWantPromotionHints());
- {
- resource_provider_->WaitSyncToken(mapped_id1);
- DisplayResourceProviderGL::ScopedReadLockGL lock(resource_provider_.get(),
- mapped_id1);
- }
- EXPECT_EQ(1u, resource_provider_->CountPromotionHintRequestsForTesting());
- EXPECT_TRUE(resource_provider_->DoAnyResourcesWantPromotionHints());
-
- EXPECT_EQ(list[0].mailbox_holder.sync_token, gl_->last_waited_sync_token());
- ResourceIdSet resource_ids_to_receive;
- resource_ids_to_receive.insert(id1);
- resource_ids_to_receive.insert(id2);
- resource_provider_->DeclareUsedResourcesFromChild(child_id,
- resource_ids_to_receive);
-
- EXPECT_EQ(2u, resource_provider_->num_resources());
-
- EXPECT_NE(kInvalidResourceId, mapped_id1);
- EXPECT_NE(kInvalidResourceId, mapped_id2);
-
- // Make sure that the request for a promotion hint was noticed.
- EXPECT_TRUE(resource_provider_->IsOverlayCandidate(mapped_id1));
- EXPECT_TRUE(resource_provider_->IsBackedBySurfaceTexture(mapped_id1));
- EXPECT_TRUE(resource_provider_->DoesResourceWantPromotionHint(mapped_id1));
-
- EXPECT_TRUE(resource_provider_->IsOverlayCandidate(mapped_id2));
- EXPECT_FALSE(resource_provider_->IsBackedBySurfaceTexture(mapped_id2));
- EXPECT_FALSE(resource_provider_->DoesResourceWantPromotionHint(mapped_id2));
-
- // ResourceProvider maintains a set of promotion hint requests that should be
- // cleared when resources are deleted.
- resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
- EXPECT_EQ(2u, returned_to_child.size());
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
-
- EXPECT_EQ(0u, resource_provider_->CountPromotionHintRequestsForTesting());
- EXPECT_FALSE(resource_provider_->DoAnyResourcesWantPromotionHints());
-
- resource_provider_->DestroyChild(child_id);
-
- child_resource_provider_->RemoveImportedResource(id2);
- child_resource_provider_->RemoveImportedResource(id1);
-}
-#endif
-
} // namespace
} // namespace viz
diff --git a/chromium/components/viz/service/display/display_resource_provider_null.cc b/chromium/components/viz/service/display/display_resource_provider_null.cc
index 733970f40d8..559bf318ce9 100644
--- a/chromium/components/viz/service/display/display_resource_provider_null.cc
+++ b/chromium/components/viz/service/display/display_resource_provider_null.cc
@@ -35,6 +35,7 @@ DisplayResourceProviderNull::DeleteAndReturnUnusedResourcesToChildImpl(
DCHECK_EQ(can_delete, CanDeleteNowResult::kYes);
to_return.emplace_back(child_id, resource.sync_token(),
+ std::move(resource.release_fence),
resource.imported_count, /*is_lost=*/false);
child_info.child_to_parent_map.erase(child_id);
diff --git a/chromium/components/viz/service/display/display_resource_provider_skia.cc b/chromium/components/viz/service/display/display_resource_provider_skia.cc
index a34aa05dba8..fb0e5910f1c 100644
--- a/chromium/components/viz/service/display/display_resource_provider_skia.cc
+++ b/chromium/components/viz/service/display/display_resource_provider_skia.cc
@@ -50,12 +50,27 @@ DisplayResourceProviderSkia::DeleteAndReturnUnusedResourcesToChildImpl(
external_used_resources.reserve(unused.size());
DCHECK(external_use_client_);
+ std::vector<ResourceId>* batch_return = nullptr;
for (ResourceId local_id : unused) {
auto it = resources_.find(local_id);
CHECK(it != resources_.end());
ChildResource& resource = it->second;
+ if (!can_access_gpu_thread_) {
+ // We should always has access to gpu thread during shutdown.
+ DCHECK(style != DeleteStyle::FOR_SHUTDOWN);
+
+ // If we don't have access to gpu thread, we can't free it right now.
+ if (resource.image_context) {
+ if (!batch_return) {
+ batch_return = &batched_returning_resources_[child_info.id];
+ }
+ batch_return->push_back(local_id);
+ continue;
+ }
+ }
+
ResourceId child_id = resource.transferable.id;
DCHECK(child_info.child_to_parent_map.count(child_id));
DCHECK(resource.is_gpu_resource_type());
@@ -70,6 +85,7 @@ DisplayResourceProviderSkia::DeleteAndReturnUnusedResourcesToChildImpl(
const bool is_lost = can_delete == CanDeleteNowResult::kYesButLoseResource;
to_return.emplace_back(child_id, resource.sync_token(),
+ std::move(resource.release_fence),
resource.imported_count, is_lost);
auto& returned = to_return.back();
@@ -80,9 +96,6 @@ DisplayResourceProviderSkia::DeleteAndReturnUnusedResourcesToChildImpl(
child_info.child_to_parent_map.erase(child_id);
resource.imported_count = 0;
-#if defined(OS_ANDROID)
- DeletePromotionHint(it);
-#endif
resources_.erase(it);
}
@@ -181,4 +194,33 @@ void DisplayResourceProviderSkia::LockSetForExternalUse::UnlockResources(
resources_.clear();
}
+DisplayResourceProviderSkia::ScopedExclusiveReadLockSharedImage::
+ ScopedExclusiveReadLockSharedImage(
+ DisplayResourceProviderSkia* resource_provider,
+ ResourceId resource_id)
+ : ScopedReadLockSharedImage(resource_provider, resource_id) {
+ ChildResource& resource = *this->resource();
+ if (resource.image_context) {
+ DCHECK(!resource.locked_for_external_use)
+ << "Resource already locked, can't get exclusive lock!";
+ DCHECK(resource_provider->can_access_gpu_thread_)
+ << "Can't release |image_context| without access to gpu thread";
+
+ std::vector<std::unique_ptr<ExternalUseClient::ImageContext>>
+ image_contexts;
+ image_contexts.push_back(std::move(resource.image_context));
+
+ gpu::SyncToken sync_token =
+ resource_provider->external_use_client_->ReleaseImageContexts(
+ std::move(image_contexts));
+ resource.UpdateSyncToken(sync_token);
+ }
+}
+DisplayResourceProviderSkia::ScopedExclusiveReadLockSharedImage::
+ ~ScopedExclusiveReadLockSharedImage() = default;
+
+DisplayResourceProviderSkia::ScopedExclusiveReadLockSharedImage::
+ ScopedExclusiveReadLockSharedImage(
+ ScopedExclusiveReadLockSharedImage&& other) = default;
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/display_resource_provider_skia.h b/chromium/components/viz/service/display/display_resource_provider_skia.h
index 6a8dc88eee1..c586f66c2d4 100644
--- a/chromium/components/viz/service/display/display_resource_provider_skia.h
+++ b/chromium/components/viz/service/display/display_resource_provider_skia.h
@@ -21,6 +21,19 @@ class VIZ_SERVICE_EXPORT DisplayResourceProviderSkia
DisplayResourceProviderSkia();
~DisplayResourceProviderSkia() override;
+ // Same as ScopedReadLockSharedImage, but will release |image_context| if
+ // already was created, making sure resource isn't locked by compositor.
+ class VIZ_SERVICE_EXPORT ScopedExclusiveReadLockSharedImage
+ : public ScopedReadLockSharedImage {
+ public:
+ ScopedExclusiveReadLockSharedImage(
+ DisplayResourceProviderSkia* resource_provider,
+ ResourceId resource_id);
+ ~ScopedExclusiveReadLockSharedImage();
+ ScopedExclusiveReadLockSharedImage(
+ ScopedExclusiveReadLockSharedImage&& other);
+ };
+
// Maintains set of resources locked for external use by SkiaRenderer.
class VIZ_SERVICE_EXPORT LockSetForExternalUse {
public:
diff --git a/chromium/components/viz/service/display/display_resource_provider_skia_unittest.cc b/chromium/components/viz/service/display/display_resource_provider_skia_unittest.cc
index ee689d65d09..e516a371c99 100644
--- a/chromium/components/viz/service/display/display_resource_provider_skia_unittest.cc
+++ b/chromium/components/viz/service/display/display_resource_provider_skia_unittest.cc
@@ -17,14 +17,14 @@
#include "base/callback_helpers.h"
#include "base/check.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/viz/client/client_resource_provider.h"
+#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/resources/returned_resource.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/test/test_context_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "ui/gfx/geometry/rect.h"
@@ -48,8 +48,9 @@ MATCHER_P(SamePtr, ptr_to_expected, "") {
}
static void CollectResources(std::vector<ReturnedResource>* array,
- const std::vector<ReturnedResource>& returned) {
- array->insert(array->end(), returned.begin(), returned.end());
+ std::vector<ReturnedResource> returned) {
+ array->insert(array->end(), std::make_move_iterator(returned.begin()),
+ std::make_move_iterator(returned.end()));
}
class MockExternalUseClient : public ExternalUseClient {
@@ -64,7 +65,7 @@ class MockExternalUseClient : public ExternalUseClient {
const gfx::Size&,
ResourceFormat,
bool,
- const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
+ const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
sk_sp<SkColorSpace>));
};
@@ -117,7 +118,7 @@ class DisplayResourceProviderSkiaTest : public testing::Test {
std::unique_ptr<DisplayResourceProviderSkia> resource_provider_;
std::unique_ptr<ClientResourceProvider> child_resource_provider_;
testing::NiceMock<MockExternalUseClient> client_;
- base::Optional<DisplayResourceProviderSkia::LockSetForExternalUse> lock_set_;
+ absl::optional<DisplayResourceProviderSkia::LockSetForExternalUse> lock_set_;
};
TEST_F(DisplayResourceProviderSkiaTest, LockForExternalUse) {
@@ -129,11 +130,11 @@ TEST_F(DisplayResourceProviderSkiaTest, LockForExternalUse) {
TransferableResource gl_resource = TransferableResource::MakeGL(
mailbox, GL_LINEAR, GL_TEXTURE_2D, sync_token1, size,
false /* is_overlay_candidate */);
- ResourceId id1 = child_resource_provider_->ImportResource(
- gl_resource, SingleReleaseCallback::Create(base::DoNothing()));
+ ResourceId id1 =
+ child_resource_provider_->ImportResource(gl_resource, base::DoNothing());
std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ int child_id = resource_provider_->CreateChild(
+ GetReturnCallback(&returned_to_child), SurfaceId());
// Transfer some resources to the parent.
std::vector<TransferableResource> list;
@@ -153,7 +154,7 @@ TEST_F(DisplayResourceProviderSkiaTest, LockForExternalUse) {
auto owned_image_context = std::make_unique<ExternalUseClient::ImageContext>(
gpu::MailboxHolder(mailbox, sync_token1, GL_TEXTURE_2D), size, RGBA_8888,
- /*ycbcr_info=*/base::nullopt, /*color_space=*/nullptr);
+ /*ycbcr_info=*/absl::nullopt, /*color_space=*/nullptr);
auto* image_context = owned_image_context.get();
gpu::MailboxHolder holder;
@@ -195,7 +196,8 @@ TEST_F(DisplayResourceProviderSkiaTest, LockForExternalUse) {
// The resource should be returned after the lock is released.
EXPECT_EQ(1u, returned_to_child.size());
EXPECT_EQ(sync_token3, returned_to_child[0].sync_token);
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
child_resource_provider_->RemoveImportedResource(id1);
}
@@ -208,11 +210,11 @@ TEST_F(DisplayResourceProviderSkiaTest, LockForExternalUseWebView) {
TransferableResource gl_resource = TransferableResource::MakeGL(
mailbox, GL_LINEAR, GL_TEXTURE_2D, sync_token1, size,
false /* is_overlay_candidate */);
- ResourceId id1 = child_resource_provider_->ImportResource(
- gl_resource, SingleReleaseCallback::Create(base::DoNothing()));
+ ResourceId id1 =
+ child_resource_provider_->ImportResource(gl_resource, base::DoNothing());
std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ int child_id = resource_provider_->CreateChild(
+ GetReturnCallback(&returned_to_child), SurfaceId());
// Transfer some resources to the parent.
std::vector<TransferableResource> list;
@@ -232,7 +234,7 @@ TEST_F(DisplayResourceProviderSkiaTest, LockForExternalUseWebView) {
auto owned_image_context = std::make_unique<ExternalUseClient::ImageContext>(
gpu::MailboxHolder(mailbox, sync_token1, GL_TEXTURE_2D), size, RGBA_8888,
- /*ycbcr_info=*/base::nullopt, /*color_space=*/nullptr);
+ /*ycbcr_info=*/absl::nullopt, /*color_space=*/nullptr);
auto* image_context = owned_image_context.get();
gpu::MailboxHolder holder;
@@ -287,7 +289,8 @@ TEST_F(DisplayResourceProviderSkiaTest, LockForExternalUseWebView) {
// The resource should be returned after the lock is released.
EXPECT_EQ(1u, returned_to_child.size());
EXPECT_EQ(sync_token3, returned_to_child[0].sync_token);
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
child_resource_provider_->RemoveImportedResource(id1);
}
@@ -311,12 +314,12 @@ TEST_F(DisplayResourceProviderSkiaTest,
TransferableResource tran1 = CreateResource(RGBA_8888);
tran1.read_lock_fences_enabled = true;
ResourceId id1 = child_resource_provider_->ImportResource(
- tran1, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran1, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ int child_id = resource_provider_->CreateChild(
+ GetReturnCallback(&returned_to_child), SurfaceId());
// Transfer some resources to the parent.
std::vector<TransferableResource> list;
@@ -351,7 +354,8 @@ TEST_F(DisplayResourceProviderSkiaTest,
resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
EXPECT_EQ(1u, returned_to_child.size());
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
EXPECT_CALL(release, Released(_, _));
child_resource_provider_->RemoveImportedResource(id1);
}
@@ -362,18 +366,18 @@ TEST_F(DisplayResourceProviderSkiaTest, ReadLockFenceDestroyChild) {
TransferableResource tran1 = CreateResource(RGBA_8888);
tran1.read_lock_fences_enabled = true;
ResourceId id1 = child_resource_provider_->ImportResource(
- tran1, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran1, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
TransferableResource tran2 = CreateResource(RGBA_8888);
tran2.read_lock_fences_enabled = false;
ResourceId id2 = child_resource_provider_->ImportResource(
- tran2, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran2, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ int child_id = resource_provider_->CreateChild(
+ GetReturnCallback(&returned_to_child), SurfaceId());
// Transfer resources to the parent.
std::vector<TransferableResource> list;
@@ -413,7 +417,8 @@ TEST_F(DisplayResourceProviderSkiaTest, ReadLockFenceDestroyChild) {
EXPECT_EQ(returned_to_child[0].lost, returned_to_child[0].id == id1);
EXPECT_EQ(returned_to_child[1].lost, returned_to_child[1].id == id1);
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
EXPECT_CALL(release, Released(_, _)).Times(2);
child_resource_provider_->RemoveImportedResource(id1);
child_resource_provider_->RemoveImportedResource(id2);
@@ -425,8 +430,8 @@ TEST_F(DisplayResourceProviderSkiaTest,
MockReleaseCallback release;
std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ int child_id = resource_provider_->CreateChild(
+ GetReturnCallback(&returned_to_child), SurfaceId());
// Transfer some resources to the parent.
constexpr size_t kTotalResources = 5;
@@ -436,8 +441,8 @@ TEST_F(DisplayResourceProviderSkiaTest,
for (auto& id : ids) {
TransferableResource tran = CreateResource(RGBA_8888);
id = child_resource_provider_->ImportResource(
- tran, SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ tran, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
}
std::vector<ResourceId> resource_ids_to_transfer(ids, ids + kTotalResources);
@@ -473,7 +478,8 @@ TEST_F(DisplayResourceProviderSkiaTest,
EXPECT_EQ(0u, returned_to_child.size());
}
EXPECT_EQ(1u, returned_to_child.size());
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
returned_to_child.clear();
// Return all locked resources.
@@ -495,7 +501,8 @@ TEST_F(DisplayResourceProviderSkiaTest,
for (const auto& resource : returned_to_child)
EXPECT_EQ(resource.sync_token, returned_to_child[0].sync_token);
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
returned_to_child.clear();
// Returns from destroying the child is also batched.
@@ -506,102 +513,14 @@ TEST_F(DisplayResourceProviderSkiaTest,
EXPECT_EQ(0u, returned_to_child.size());
}
EXPECT_EQ(1u, returned_to_child.size());
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
returned_to_child.clear();
EXPECT_CALL(release, Released(_, _)).Times(kTotalResources);
for (const auto& id : ids)
child_resource_provider_->RemoveImportedResource(id);
-} // namespace
-
-#if defined(OS_ANDROID)
-TEST_F(DisplayResourceProviderSkiaTest, OverlayPromotionHint) {
- gpu::Mailbox external_mailbox = gpu::Mailbox::GenerateForSharedImage();
- gpu::SyncToken external_sync_token = GenSyncToken();
- EXPECT_TRUE(external_sync_token.HasData());
-
- TransferableResource id1_transfer = TransferableResource::MakeGL(
- external_mailbox, GL_LINEAR, GL_TEXTURE_EXTERNAL_OES, external_sync_token,
- gfx::Size(1, 1), true);
- id1_transfer.wants_promotion_hint = true;
- id1_transfer.is_backed_by_surface_texture = true;
- ResourceId id1 = child_resource_provider_->ImportResource(
- id1_transfer, SingleReleaseCallback::Create(base::DoNothing()));
-
- TransferableResource id2_transfer = TransferableResource::MakeGL(
- external_mailbox, GL_LINEAR, GL_TEXTURE_EXTERNAL_OES, external_sync_token,
- gfx::Size(1, 1), true);
- id2_transfer.wants_promotion_hint = false;
- id2_transfer.is_backed_by_surface_texture = false;
- ResourceId id2 = child_resource_provider_->ImportResource(
- id2_transfer, SingleReleaseCallback::Create(base::DoNothing()));
-
- std::vector<ReturnedResource> returned_to_child;
- int child_id =
- resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
-
- // Transfer some resources to the parent.
- std::vector<TransferableResource> list;
- child_resource_provider_->PrepareSendToParent(
- {id1, id2}, &list,
- static_cast<RasterContextProvider*>(child_context_provider_.get()));
- ASSERT_EQ(2u, list.size());
- resource_provider_->ReceiveFromChild(child_id, list);
- std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map =
- resource_provider_->GetChildToParentMap(child_id);
- ResourceId mapped_id1 = resource_map[list[0].id];
- ResourceId mapped_id2 = resource_map[list[1].id];
-
- // The promotion hints should not be recorded until after we wait. This is
- // because we can't notify them until they're synchronized, and we choose to
- // ignore unwaited resources rather than send them a "no" hint. If they end
- // up in the request set before we wait, then the attempt to notify them wil;
- // DCHECK when we try to lock them for reading in SendPromotionHints.
- EXPECT_EQ(0u, resource_provider_->CountPromotionHintRequestsForTesting());
- EXPECT_FALSE(resource_provider_->DoAnyResourcesWantPromotionHints());
- {
- resource_provider_->InitializePromotionHintRequest(mapped_id1);
- DisplayResourceProvider::ScopedReadLockSharedImage lock(
- resource_provider_.get(), mapped_id1);
- }
- EXPECT_EQ(1u, resource_provider_->CountPromotionHintRequestsForTesting());
- EXPECT_TRUE(resource_provider_->DoAnyResourcesWantPromotionHints());
-
- ResourceIdSet resource_ids_to_receive;
- resource_ids_to_receive.insert(id1);
- resource_ids_to_receive.insert(id2);
- resource_provider_->DeclareUsedResourcesFromChild(child_id,
- resource_ids_to_receive);
-
- EXPECT_EQ(2u, resource_provider_->num_resources());
-
- EXPECT_NE(kInvalidResourceId, mapped_id1);
- EXPECT_NE(kInvalidResourceId, mapped_id2);
-
- // Make sure that the request for a promotion hint was noticed.
- EXPECT_TRUE(resource_provider_->IsOverlayCandidate(mapped_id1));
- EXPECT_TRUE(resource_provider_->IsBackedBySurfaceTexture(mapped_id1));
- EXPECT_TRUE(resource_provider_->DoesResourceWantPromotionHint(mapped_id1));
-
- EXPECT_TRUE(resource_provider_->IsOverlayCandidate(mapped_id2));
- EXPECT_FALSE(resource_provider_->IsBackedBySurfaceTexture(mapped_id2));
- EXPECT_FALSE(resource_provider_->DoesResourceWantPromotionHint(mapped_id2));
-
- // ResourceProvider maintains a set of promotion hint requests that should be
- // cleared when resources are deleted.
- resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
- EXPECT_EQ(2u, returned_to_child.size());
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
-
- EXPECT_EQ(0u, resource_provider_->CountPromotionHintRequestsForTesting());
- EXPECT_FALSE(resource_provider_->DoAnyResourcesWantPromotionHints());
-
- resource_provider_->DestroyChild(child_id);
-
- child_resource_provider_->RemoveImportedResource(id2);
- child_resource_provider_->RemoveImportedResource(id1);
}
-#endif
} // namespace
} // namespace viz
diff --git a/chromium/components/viz/service/display/display_resource_provider_software.cc b/chromium/components/viz/service/display/display_resource_provider_software.cc
index 31a6200844c..78fda8a7c95 100644
--- a/chromium/components/viz/service/display/display_resource_provider_software.cc
+++ b/chromium/components/viz/service/display/display_resource_provider_software.cc
@@ -92,6 +92,7 @@ DisplayResourceProviderSoftware::DeleteAndReturnUnusedResourcesToChildImpl(
const bool is_lost = can_delete == CanDeleteNowResult::kYesButLoseResource;
to_return.emplace_back(child_id, resource.sync_token(),
+ std::move(resource.release_fence),
resource.imported_count, is_lost);
child_info.child_to_parent_map.erase(child_id);
diff --git a/chromium/components/viz/service/display/display_resource_provider_software_unittest.cc b/chromium/components/viz/service/display/display_resource_provider_software_unittest.cc
index d3b74dc0722..f8472c01ab8 100644
--- a/chromium/components/viz/service/display/display_resource_provider_software_unittest.cc
+++ b/chromium/components/viz/service/display/display_resource_provider_software_unittest.cc
@@ -22,10 +22,10 @@
#include "build/build_config.h"
#include "components/viz/client/client_resource_provider.h"
#include "components/viz/common/resources/bitmap_allocation.h"
+#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/resources/shared_bitmap.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/service/display/shared_bitmap_manager.h"
#include "components/viz/test/test_shared_bitmap_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -47,8 +47,9 @@ class MockReleaseCallback {
};
static void CollectResources(std::vector<ReturnedResource>* array,
- const std::vector<ReturnedResource>& returned) {
- array->insert(array->end(), returned.begin(), returned.end());
+ std::vector<ReturnedResource> returned) {
+ array->insert(array->end(), std::make_move_iterator(returned.begin()),
+ std::make_move_iterator(returned.end()));
}
static SharedBitmapId CreateAndFillSharedBitmap(SharedBitmapManager* manager,
@@ -107,16 +108,15 @@ TEST_F(DisplayResourceProviderSoftwareTest, ReadSoftwareResources) {
MockReleaseCallback release;
ResourceId resource_id = child_resource_provider_->ImportResource(
- resource,
- SingleReleaseCallback::Create(base::BindOnce(
- &MockReleaseCallback::Released, base::Unretained(&release))));
+ resource, base::BindOnce(&MockReleaseCallback::Released,
+ base::Unretained(&release)));
EXPECT_NE(kInvalidResourceId, resource_id);
// Transfer resources to the parent.
std::vector<TransferableResource> send_to_parent;
std::vector<ReturnedResource> returned_to_child;
int child_id = resource_provider_->CreateChild(
- base::BindRepeating(&CollectResources, &returned_to_child));
+ base::BindRepeating(&CollectResources, &returned_to_child), SurfaceId());
child_resource_provider_->PrepareSendToParent(
{resource_id}, &send_to_parent,
static_cast<RasterContextProvider*>(nullptr));
@@ -143,7 +143,8 @@ TEST_F(DisplayResourceProviderSoftwareTest, ReadSoftwareResources) {
// being in use.
resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
EXPECT_EQ(1u, returned_to_child.size());
- child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->ReceiveReturnsFromParent(
+ std::move(returned_to_child));
EXPECT_CALL(release, Released(_, false));
child_resource_provider_->RemoveImportedResource(resource_id);
diff --git a/chromium/components/viz/service/display/display_scheduler.cc b/chromium/components/viz/service/display/display_scheduler.cc
index 9fc4a5ba4ed..59d1cc1fc9e 100644
--- a/chromium/components/viz/service/display/display_scheduler.cc
+++ b/chromium/components/viz/service/display/display_scheduler.cc
@@ -8,6 +8,8 @@
#include "base/auto_reset.h"
#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
+#include "gpu/config/gpu_finch_features.h"
namespace viz {
@@ -162,7 +164,7 @@ bool DisplayScheduler::OnBeginFrame(const BeginFrameArgs& args) {
DCHECK(missed_begin_frame_task_.IsCancelled());
missed_begin_frame_task_.Reset(
base::BindOnce(base::IgnoreResult(&DisplayScheduler::OnBeginFrame),
- // The CancelableCallback will not run after it is
+ // The CancelableOnceCallback will not run after it is
// destroyed, which happens when |this| is destroyed.
base::Unretained(this), args));
task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback());
@@ -197,6 +199,21 @@ bool DisplayScheduler::OnBeginFrame(const BeginFrameArgs& args) {
return true;
}
+int DisplayScheduler::MaxPendingSwaps() const {
+#if defined(OS_ANDROID)
+ if (::features::IncreaseBufferCountForHighFrameRate() &&
+ max_pending_swaps_ == 4) {
+ // Interval for 120hz with some delta for margin of error.
+ constexpr base::TimeDelta k120HzInterval =
+ base::TimeDelta::FromMicroseconds(8500);
+ if (current_begin_frame_args_.interval > k120HzInterval) {
+ return 2;
+ }
+ }
+#endif
+ return max_pending_swaps_;
+}
+
void DisplayScheduler::SetNeedsOneBeginFrame(bool needs_draw) {
// If we are not currently observing BeginFrames because needs_draw_ is false,
// we will stop observing again after one BeginFrame in AttemptDrawAndSwap().
@@ -278,7 +295,7 @@ DisplayScheduler::DesiredBeginFrameDeadlineMode() const {
return BeginFrameDeadlineMode::kImmediate;
}
- if (pending_swaps_ >= max_pending_swaps_) {
+ if (pending_swaps_ >= MaxPendingSwaps()) {
TRACE_EVENT_INSTANT0("viz", "Swap throttled", TRACE_EVENT_SCOPE_THREAD);
return BeginFrameDeadlineMode::kLate;
}
@@ -369,7 +386,7 @@ bool DisplayScheduler::AttemptDrawAndSwap() {
begin_frame_deadline_task_time_ = base::TimeTicks();
if (ShouldDraw()) {
- if (pending_swaps_ < max_pending_swaps_)
+ if (pending_swaps_ < MaxPendingSwaps())
return DrawAndSwap();
} else {
// We are going idle, so reset expectations.
@@ -402,7 +419,7 @@ void DisplayScheduler::DidFinishFrame(bool did_draw) {
void DisplayScheduler::DidSwapBuffers() {
pending_swaps_++;
- if (pending_swaps_ == max_pending_swaps_)
+ if (pending_swaps_ >= MaxPendingSwaps())
begin_frame_source_->SetIsGpuBusy(true);
uint32_t swap_id = next_swap_id_++;
diff --git a/chromium/components/viz/service/display/display_scheduler.h b/chromium/components/viz/service/display/display_scheduler.h
index 9e0b32fe210..fb80bdbdbe5 100644
--- a/chromium/components/viz/service/display/display_scheduler.h
+++ b/chromium/components/viz/service/display/display_scheduler.h
@@ -50,6 +50,7 @@ class VIZ_SERVICE_EXPORT DisplayScheduler : public DisplaySchedulerBase {
class BeginFrameObserver;
bool OnBeginFrame(const BeginFrameArgs& args);
+ int MaxPendingSwaps() const;
base::TimeTicks current_frame_display_time() const {
return current_begin_frame_args_.frame_time +
@@ -99,7 +100,7 @@ class VIZ_SERVICE_EXPORT DisplayScheduler : public DisplaySchedulerBase {
BeginFrameSource* begin_frame_source_;
base::SingleThreadTaskRunner* task_runner_;
gfx::RenderingPipeline* gpu_pipeline_;
- base::Optional<gfx::RenderingPipeline::ScopedPipelineActive>
+ absl::optional<gfx::RenderingPipeline::ScopedPipelineActive>
gpu_pipeline_active_;
BeginFrameArgs current_begin_frame_args_;
diff --git a/chromium/components/viz/service/display/display_scheduler_unittest.cc b/chromium/components/viz/service/display/display_scheduler_unittest.cc
index 1d18f5a5556..60ccdd70326 100644
--- a/chromium/components/viz/service/display/display_scheduler_unittest.cc
+++ b/chromium/components/viz/service/display/display_scheduler_unittest.cc
@@ -9,7 +9,7 @@
#include <vector>
#include "base/check.h"
-#include "base/stl_util.h"
+#include "base/containers/contains.h"
#include "base/test/null_task_runner.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/components/viz/service/display/display_unittest.cc b/chromium/components/viz/service/display/display_unittest.cc
index 6031011b76c..7a72e37b099 100644
--- a/chromium/components/viz/service/display/display_unittest.cc
+++ b/chromium/components/viz/service/display/display_unittest.cc
@@ -657,7 +657,8 @@ TEST_F(DisplayTest, DisableSwapUntilResize) {
[&swap_callback_run]() { swap_callback_run = true; }));
EXPECT_TRUE(scheduler_->swapped());
- display_->DidReceiveSwapBuffersAck(GetTestSwapTimings());
+ display_->DidReceiveSwapBuffersAck(GetTestSwapTimings(),
+ /*release_fence=*/gfx::GpuFenceHandle());
EXPECT_TRUE(swap_callback_run);
display_->Resize(gfx::Size(150, 150));
@@ -786,13 +787,12 @@ TEST_F(DisplayTest, BackdropFilterTest) {
gfx::Transform(), /*quad_layer_rect=*/sub_surface_rect,
/*visible_quad_layer_rect=*/sub_surface_rect,
/*mask_filter_info=*/gfx::MaskFilterInfo(),
- /*clip_rect=*/sub_surface_rect, /*is_clipped=*/false,
- /*are_contents_opaque=*/true, /*opacity=*/1.0f, SkBlendMode::kSrcOver,
- /*sorting_context_id=*/0);
+ /*clip_rect=*/absl::nullopt, /*are_contents_opaque=*/true,
+ /*opacity=*/1.0f, SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
auto* quad1 = pass->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
quad1->SetNew(shared_quad_state1, /*rect=*/sub_surface_rect,
/*visible_rect=*/sub_surface_rect,
- SurfaceRange(base::nullopt, sub_surface_id1), SK_ColorBLACK,
+ SurfaceRange(absl::nullopt, sub_surface_id1), SK_ColorBLACK,
/*stretch_content_to_fill_bounds=*/false);
quad1->allow_merge = false;
@@ -802,14 +802,14 @@ TEST_F(DisplayTest, BackdropFilterTest) {
shared_quad_state2->SetAll(gfx::Transform(), /*quad_layer_rect=*/rect1,
/*visible_quad_layer_rect=*/rect1,
/*mask_filter_info=*/gfx::MaskFilterInfo(),
- /*clip_rect=*/rect1, /*is_clipped=*/false,
+ /*clip_rect=*/absl::nullopt,
/*are_contents_opaque=*/true, /*opacity=*/1.0f,
SkBlendMode::kSrcOver,
/*sorting_context_id=*/0);
auto* quad2 = pass->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
quad2->SetNew(shared_quad_state2, /*rect=*/rect1,
/*visible_rect=*/rect1,
- SurfaceRange(base::nullopt, sub_surface_id2), SK_ColorBLACK,
+ SurfaceRange(absl::nullopt, sub_surface_id2), SK_ColorBLACK,
/*stretch_content_to_fill_bounds=*/false);
quad2->allow_merge = false;
@@ -929,7 +929,6 @@ TEST_F(DisplayTest, DrawOcclusionWithBlending) {
display_->Initialize(&client, manager_.surface_manager());
AggregatedFrame frame = MakeDefaultAggregatedFrame(/*num_render_passes=*/2);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
@@ -941,13 +940,13 @@ TEST_F(DisplayTest, DrawOcclusionWithBlending) {
auto* src_sqs = render_pass->CreateAndAppendSharedQuadState();
src_sqs->SetAll(
- gfx::Transform(), src_rect, src_rect, gfx::MaskFilterInfo(), src_rect,
- is_clipped, are_contents_opaque, opacity,
+ gfx::Transform(), src_rect, src_rect, gfx::MaskFilterInfo(),
+ absl::nullopt, are_contents_opaque, opacity,
is_root_render_pass ? SkBlendMode::kSrcOver : SkBlendMode::kSrcIn, 0);
auto* dest_sqs = render_pass->CreateAndAppendSharedQuadState();
dest_sqs->SetAll(
gfx::Transform(), dest_rect, dest_rect, gfx::MaskFilterInfo(),
- dest_rect, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
is_root_render_pass ? SkBlendMode::kSrcOver : SkBlendMode::kDstIn, 0);
auto* src_quad =
render_pass->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
@@ -977,7 +976,6 @@ TEST_F(DisplayTest, DrawOcclusionWithIntersectingBackdropFilter) {
display_->Initialize(&client, manager_.surface_manager());
AggregatedFrame frame = MakeDefaultAggregatedFrame(/*num_render_passes=*/2);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
@@ -1007,8 +1005,8 @@ TEST_F(DisplayTest, DrawOcclusionWithIntersectingBackdropFilter) {
for (int i = 0; i < 3; i++) {
shared_quad_states[i] = root_render_pass->CreateAndAppendSharedQuadState();
shared_quad_states[i]->SetAll(
- gfx::Transform(), rects[i], rects[i], gfx::MaskFilterInfo(), rects[i],
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rects[i], rects[i], gfx::MaskFilterInfo(),
+ absl::nullopt, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
if (i == 0) { // Backdrop filter quad
auto* new_quad =
@@ -1060,7 +1058,6 @@ TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
gfx::Rect rect6(25, 0, 50, 160);
gfx::Rect rect7(0, 20, 100, 100);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -1073,8 +1070,8 @@ TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
// +----+
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
EXPECT_EQ(1u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -1098,12 +1095,12 @@ TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
// +----+
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -1133,12 +1130,12 @@ TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
// +--+ +--+
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect3, rect3, SK_ColorBLACK, false);
@@ -1167,12 +1164,12 @@ TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
// +--+ +--+
{
shared_quad_state->SetAll(
- gfx::Transform(), rect7, rect7, gfx::MaskFilterInfo(), rect7,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect7, rect7, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect6, rect6, gfx::MaskFilterInfo(), rect6,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect6, rect6, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect7, rect7, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect6, rect6, SK_ColorBLACK, false);
@@ -1200,12 +1197,12 @@ TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
// +----+
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect4, rect4, gfx::MaskFilterInfo(), rect4,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect4, rect4, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect4, rect4, SK_ColorBLACK, false);
@@ -1225,19 +1222,18 @@ TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
->quad_list.ElementAt(1)
->visible_rect.ToString());
}
-
// +-----++
// | ||
// +-----+|
// +------+
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect5, rect5, gfx::MaskFilterInfo(), rect5,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect5, rect5, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect5, rect5, SK_ColorBLACK, false);
@@ -1280,7 +1276,6 @@ TEST_F(DisplayTest, DrawOcclusionWithSingleOverlapBehindDisjointedDrawQuads) {
rects.emplace_back(150, 0, 150, 150);
rects.emplace_back(25, 25, 50, 50);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
@@ -1290,7 +1285,7 @@ TEST_F(DisplayTest, DrawOcclusionWithSingleOverlapBehindDisjointedDrawQuads) {
auto* quad = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(
- gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
}
@@ -1336,7 +1331,6 @@ TEST_F(DisplayTest, DrawOcclusionWithMultipleOverlapBehindDisjointedDrawQuads) {
rects.emplace_back(25, 25, 50, 50);
rects.emplace_back(150, 0, 100, 100);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
@@ -1346,7 +1340,7 @@ TEST_F(DisplayTest, DrawOcclusionWithMultipleOverlapBehindDisjointedDrawQuads) {
auto* quad = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(
- gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
}
@@ -1388,7 +1382,6 @@ TEST_F(DisplayTest, CompositorFrameWithOverlapDrawQuad) {
gfx::Rect rect3(50, 50, 50, 25);
gfx::Rect rect4(0, 0, 50, 50);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -1405,11 +1398,11 @@ TEST_F(DisplayTest, CompositorFrameWithOverlapDrawQuad) {
// +-----+
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect1, rect1, SK_ColorBLACK, false);
@@ -1421,7 +1414,6 @@ TEST_F(DisplayTest, CompositorFrameWithOverlapDrawQuad) {
->quad_list.ElementAt(0)
->visible_rect.ToString());
}
-
// +-----+
// | +-+ |
// | +-+ |
@@ -1430,11 +1422,11 @@ TEST_F(DisplayTest, CompositorFrameWithOverlapDrawQuad) {
quad2 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -1456,11 +1448,11 @@ TEST_F(DisplayTest, CompositorFrameWithOverlapDrawQuad) {
quad2 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect3, rect3, SK_ColorBLACK, false);
@@ -1482,12 +1474,12 @@ TEST_F(DisplayTest, CompositorFrameWithOverlapDrawQuad) {
quad2 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect4, rect4, gfx::MaskFilterInfo(), rect4,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect4, rect4, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect4, rect4, SK_ColorBLACK, false);
@@ -1533,7 +1525,6 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
half_scale.Scale3d(0.5, 0.5, 0.5);
gfx::Transform double_scale;
double_scale.Scale(2, 2);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -1547,10 +1538,10 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(half_scale, rect2, rect2, gfx::MaskFilterInfo(),
- rect2, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1570,10 +1561,10 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
quad2 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(half_scale, rect3, rect3, gfx::MaskFilterInfo(),
- rect3, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1593,11 +1584,11 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
quad2 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(half_scale, rect4, rect4, gfx::MaskFilterInfo(),
- rect4, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1616,7 +1607,7 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
{
shared_quad_state->SetAll(double_scale, rect1, rect1, gfx::MaskFilterInfo(),
- rect1, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1634,11 +1625,11 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
quad2 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- double_scale, rect5, rect5, gfx::MaskFilterInfo(), rect5, is_clipped,
+ double_scale, rect5, rect5, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1662,11 +1653,11 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- double_scale, rect6, rect6, gfx::MaskFilterInfo(), rect6, is_clipped,
+ double_scale, rect6, rect6, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1691,11 +1682,11 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- double_scale, rect7, rect7, gfx::MaskFilterInfo(), rect7, is_clipped,
+ double_scale, rect7, rect7, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1719,11 +1710,11 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- double_scale, rect8, rect8, gfx::MaskFilterInfo(), rect8, is_clipped,
+ double_scale, rect8, rect8, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
@@ -1747,11 +1738,11 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
{
shared_quad_state->SetAll(
- double_scale, rect10, rect10, gfx::MaskFilterInfo(), rect10, is_clipped,
+ double_scale, rect10, rect10, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- double_scale, rect9, rect9, gfx::MaskFilterInfo(), rect9, is_clipped,
+ double_scale, rect9, rect9, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect10, rect10, SK_ColorBLACK, false);
@@ -1792,7 +1783,6 @@ TEST_F(DisplayTest, CompositorFrameWithEpsilonScaleTransform) {
epsilon_scale.Scale(epsilon, epsilon);
gfx::Transform larger_epsilon_scale;
larger_epsilon_scale.Scale(larger_than_epsilon, larger_than_epsilon);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -1807,10 +1797,10 @@ TEST_F(DisplayTest, CompositorFrameWithEpsilonScaleTransform) {
{
shared_quad_state->SetAll(
- gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(zero_scale, rect, rect, gfx::MaskFilterInfo(),
- rect, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1831,10 +1821,10 @@ TEST_F(DisplayTest, CompositorFrameWithEpsilonScaleTransform) {
{
shared_quad_state->SetAll(
- gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(epsilon_scale, rect, rect, gfx::MaskFilterInfo(),
- rect, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 1);
quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1861,11 +1851,11 @@ TEST_F(DisplayTest, CompositorFrameWithEpsilonScaleTransform) {
{
shared_quad_state->SetAll(
- gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- larger_epsilon_scale, rect, rect, gfx::MaskFilterInfo(), rect,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ larger_epsilon_scale, rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect, rect, SK_ColorBLACK, false);
@@ -1895,7 +1885,6 @@ TEST_F(DisplayTest, CompositorFrameWithNegativeScaleTransform) {
gfx::Rect rect(0, 0, 100, 100);
gfx::Transform negative_scale;
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -1910,10 +1899,10 @@ TEST_F(DisplayTest, CompositorFrameWithNegativeScaleTransform) {
{
negative_scale.Scale3d(-1, 1, 1);
shared_quad_state->SetAll(
- gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- negative_scale, rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ negative_scale, rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1942,10 +1931,10 @@ TEST_F(DisplayTest, CompositorFrameWithNegativeScaleTransform) {
negative_scale.MakeIdentity();
negative_scale.Scale3d(1, -1, 1);
shared_quad_state->SetAll(
- gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- negative_scale, rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ negative_scale, rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -1974,10 +1963,10 @@ TEST_F(DisplayTest, CompositorFrameWithNegativeScaleTransform) {
negative_scale.MakeIdentity();
negative_scale.Scale3d(1, 1, -1);
shared_quad_state->SetAll(
- gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ gfx::Transform(), rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- negative_scale, rect, rect, gfx::MaskFilterInfo(), rect, is_clipped,
+ negative_scale, rect, rect, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
@@ -2022,7 +2011,6 @@ TEST_F(DisplayTest, CompositorFrameWithRotation) {
gfx::Transform rotate;
rotate.RotateAboutYAxis(45);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -2036,11 +2024,11 @@ TEST_F(DisplayTest, CompositorFrameWithRotation) {
{
// Apply rotation transform on |rect1| only.
shared_quad_state->SetAll(rotate, rect1, rect1, gfx::MaskFilterInfo(),
- rect1, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2060,10 +2048,10 @@ TEST_F(DisplayTest, CompositorFrameWithRotation) {
{
// Apply rotation transform on |rect1| and |rect2|.
shared_quad_state->SetAll(rotate, rect1, rect1, gfx::MaskFilterInfo(),
- rect1, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(rotate, rect2, rect2, gfx::MaskFilterInfo(),
- rect2, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2082,11 +2070,11 @@ TEST_F(DisplayTest, CompositorFrameWithRotation) {
quad2 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(rotate, rect1, rect1, gfx::MaskFilterInfo(),
- rect1, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect3, rect3, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2108,10 +2096,10 @@ TEST_F(DisplayTest, CompositorFrameWithRotation) {
// or translation transform and rotation transform applies to quads,
// |visible_rect| of |quad2| should not be changed.
shared_quad_state->SetAll(rotate, rect1, rect1, gfx::MaskFilterInfo(),
- rect1, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(rotate, rect3, rect3, gfx::MaskFilterInfo(),
- rect3, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect3, rect3, SK_ColorBLACK, false);
@@ -2148,7 +2136,6 @@ TEST_F(DisplayTest, CompositorFrameWithPerspective) {
perspective.ApplyPerspectiveDepth(100);
perspective.RotateAboutYAxis(45);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -2161,11 +2148,11 @@ TEST_F(DisplayTest, CompositorFrameWithPerspective) {
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
{
shared_quad_state->SetAll(perspective, rect1, rect1, gfx::MaskFilterInfo(),
- rect1, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect1, rect1, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2185,10 +2172,10 @@ TEST_F(DisplayTest, CompositorFrameWithPerspective) {
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(perspective, rect2, rect2, gfx::MaskFilterInfo(),
- rect2, is_clipped, are_contents_opaque, opacity,
+ absl::nullopt, are_contents_opaque, opacity,
SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -2217,7 +2204,6 @@ TEST_F(DisplayTest, CompositorFrameWithOpacityChange) {
gfx::Rect rect1(0, 0, 100, 100);
gfx::Rect rect2(25, 25, 10, 10);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity1 = 1.f;
float opacityLess1 = 0.5f;
@@ -2230,13 +2216,12 @@ TEST_F(DisplayTest, CompositorFrameWithOpacityChange) {
auto* quad2 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
{
- shared_quad_state->SetAll(gfx::Transform(), rect1, rect1,
- gfx::MaskFilterInfo(), rect1, is_clipped,
- are_contents_opaque, opacityLess1,
- SkBlendMode::kSrcOver, 0);
+ shared_quad_state->SetAll(
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacityLess1, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, are_contents_opaque, opacity1, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity1, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2254,11 +2239,11 @@ TEST_F(DisplayTest, CompositorFrameWithOpacityChange) {
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity1, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity1, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, are_contents_opaque, opacity1, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity1, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2282,7 +2267,6 @@ TEST_F(DisplayTest, CompositorFrameWithOpaquenessChange) {
gfx::Rect rect1(0, 0, 100, 100);
gfx::Rect rect2(25, 25, 10, 10);
- bool is_clipped = false;
bool opaque_content = true;
bool transparent_content = false;
float opacity = 1.f;
@@ -2296,11 +2280,11 @@ TEST_F(DisplayTest, CompositorFrameWithOpaquenessChange) {
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, transparent_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ transparent_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2318,11 +2302,11 @@ TEST_F(DisplayTest, CompositorFrameWithOpaquenessChange) {
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2349,7 +2333,6 @@ TEST_F(DisplayTest, CompositorFrameZTranslate) {
gfx::Transform translate_back;
translate_back.Translate3d(0, 0, 100);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -2367,11 +2350,11 @@ TEST_F(DisplayTest, CompositorFrameZTranslate) {
// +-----+
{
shared_quad_state->SetAll(
- translate_back, rect1, rect1, gfx::MaskFilterInfo(), rect1, is_clipped,
+ translate_back, rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 1);
shared_quad_state2->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 1);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 1);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect1, SK_ColorBLACK, false);
@@ -2402,7 +2385,6 @@ TEST_F(DisplayTest, CompositorFrameWithTranslateTransformer) {
gfx::Rect rect2(120, 120, 10, 10);
gfx::Rect rect3(100, 100, 100, 20);
- bool is_clipped = false;
bool opaque_content = true;
bool transparent_content = false;
float opacity = 1.f;
@@ -2425,11 +2407,11 @@ TEST_F(DisplayTest, CompositorFrameWithTranslateTransformer) {
// +-+
// +-+
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, transparent_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ transparent_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2454,11 +2436,11 @@ TEST_F(DisplayTest, CompositorFrameWithTranslateTransformer) {
// +-+ | +-+ |
// +-+ +-----+
shared_quad_state->SetAll(translate_up, rect1, rect1, gfx::MaskFilterInfo(),
- rect1, is_clipped, opaque_content, opacity,
+ absl::nullopt, opaque_content, opacity,
SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2484,11 +2466,11 @@ TEST_F(DisplayTest, CompositorFrameWithTranslateTransformer) {
quad2 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(translate_up, rect1, rect1, gfx::MaskFilterInfo(),
- rect1, is_clipped, opaque_content, opacity,
+ absl::nullopt, opaque_content, opacity,
SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect3, rect3, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2525,7 +2507,6 @@ TEST_F(DisplayTest, CompositorFrameWithCombinedSharedQuadState) {
gfx::Rect rect4(10, 10, 180, 30);
gfx::Rect rect5(10, 10, 120, 100);
- bool is_clipped = false;
bool opaque_content = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -2548,14 +2529,14 @@ TEST_F(DisplayTest, CompositorFrameWithCombinedSharedQuadState) {
// +----+ +----+
//
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state3->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
quad3->SetNew(shared_quad_state3, rect3, rect3, SK_ColorBLACK, false);
@@ -2583,8 +2564,8 @@ TEST_F(DisplayTest, CompositorFrameWithCombinedSharedQuadState) {
quad3 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state3->SetAll(
- gfx::Transform(), rect4, rect4, gfx::MaskFilterInfo(), rect4,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect4, rect4, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad3->SetNew(shared_quad_state3, rect4, rect4, SK_ColorBLACK, false);
EXPECT_EQ(3u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
display_->RemoveOverdrawQuads(&frame);
@@ -2612,8 +2593,8 @@ TEST_F(DisplayTest, CompositorFrameWithCombinedSharedQuadState) {
// +----+ +-|--+ |
// +-----+
shared_quad_state3->SetAll(
- gfx::Transform(), rect5, rect5, gfx::MaskFilterInfo(), rect5,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect5, rect5, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad3->SetNew(shared_quad_state3, rect5, rect5, SK_ColorBLACK, false);
EXPECT_EQ(3u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
display_->RemoveOverdrawQuads(&frame);
@@ -2661,9 +2642,9 @@ TEST_F(DisplayTest, DrawOcclusionWithMultipleRenderPass) {
quads[i] =
render_pass->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_states[i]->SetAll(
- gfx::Transform(), rects[i], rects[i], gfx::MaskFilterInfo(), rects[i],
- false /*is_clipped*/, true /*are_contents_opaque*/, 1.f /*opacity*/,
- SkBlendMode::kSrcOver, 0 /*sorting_context_id*/);
+ gfx::Transform(), rects[i], rects[i], gfx::MaskFilterInfo(),
+ /*clip_rect=*/absl::nullopt, true /*are_contents_opaque*/,
+ 1.f /*opacity*/, SkBlendMode::kSrcOver, 0 /*sorting_context_id*/);
quads[i]->SetNew(shared_quad_states[i], rects[i], rects[i], SK_ColorBLACK,
false /*force_anti_aliasing_off*/);
}
@@ -2699,7 +2680,6 @@ TEST_F(DisplayTest, CompositorFrameWithMultipleRenderPass) {
frame.render_pass_list.push_back(std::move(render_pass2));
gfx::Rect rect3(10, 10, 120, 30);
- bool is_clipped = false;
bool opaque_content = true;
float opacity = 1.f;
@@ -2725,14 +2705,14 @@ TEST_F(DisplayTest, CompositorFrameWithMultipleRenderPass) {
// +----+ +----+
//
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state3->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
quad3->SetNew(shared_quad_state3, rect3, rect3, SK_ColorBLACK, false);
@@ -2771,7 +2751,6 @@ TEST_F(DisplayTest, CompositorFrameWithCoveredRenderPass) {
gfx::Transform());
frame.render_pass_list.push_back(std::move(render_pass2));
- bool is_clipped = false;
bool opaque_content = true;
float opacity = 1.f;
AggregatedRenderPassId render_pass_id{1};
@@ -2798,11 +2777,11 @@ TEST_F(DisplayTest, CompositorFrameWithCoveredRenderPass) {
//
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad1->SetNew(shared_quad_state2, rect1, rect1, render_pass_id,
mask_resource_id, gfx::RectF(), gfx::Size(),
@@ -2838,8 +2817,6 @@ TEST_F(DisplayTest, CompositorFrameWithClip) {
gfx::Rect clip_rect(0, 0, 60, 60);
gfx::Rect rect3(50, 50, 20, 10);
- bool clipped = true;
- bool non_clipped = false;
bool opaque_content = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -2859,11 +2836,11 @@ TEST_F(DisplayTest, CompositorFrameWithClip) {
// +------+
//
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- non_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- non_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2885,12 +2862,12 @@ TEST_F(DisplayTest, CompositorFrameWithClip) {
//
quad2 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
- shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), clip_rect,
- clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ shared_quad_state->SetAll(gfx::Transform(), rect1, rect1,
+ gfx::MaskFilterInfo(), clip_rect, opaque_content,
+ opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- non_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2914,12 +2891,12 @@ TEST_F(DisplayTest, CompositorFrameWithClip) {
// | +-+| => +--+++
// +------+
//
- shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), clip_rect,
- clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ shared_quad_state->SetAll(gfx::Transform(), rect1, rect1,
+ gfx::MaskFilterInfo(), clip_rect, opaque_content,
+ opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- non_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect3, rect3, SK_ColorBLACK, false);
EXPECT_EQ(2u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -2951,7 +2928,6 @@ TEST_F(DisplayTest, CompositorFrameWithCopyRequest) {
gfx::Rect rect1(0, 0, 100, 100);
gfx::Rect rect2(50, 50, 25, 25);
- bool is_clipped = false;
bool opaque_content = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -2964,11 +2940,11 @@ TEST_F(DisplayTest, CompositorFrameWithCopyRequest) {
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
frame.render_pass_list.front()->copy_requests.push_back(
@@ -3002,7 +2978,6 @@ TEST_F(DisplayTest, CompositorFrameWithRenderPass) {
gfx::Rect rect6(0, 75, 25, 25);
gfx::Rect rect7(0, 0, 10, 10);
- bool is_clipped = false;
bool opaque_content = true;
AggregatedRenderPassId render_pass_id{1};
ResourceId mask_resource_id(2);
@@ -3034,17 +3009,17 @@ TEST_F(DisplayTest, CompositorFrameWithRenderPass) {
// | R1 | | R2 |
// +-------+---+--------+
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state3->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state4->SetAll(
- gfx::Transform(), rect4, rect4, gfx::MaskFilterInfo(), rect4,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect4, rect4, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
R1->SetNew(shared_quad_state, rect1, rect1, render_pass_id,
mask_resource_id, gfx::RectF(), gfx::Size(),
gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
@@ -3082,17 +3057,17 @@ TEST_F(DisplayTest, CompositorFrameWithRenderPass) {
// | R2 | R1 |
// +-------+-----------+
shared_quad_state->SetAll(
- gfx::Transform(), rect5, rect5, gfx::MaskFilterInfo(), rect5,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect5, rect5, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state3->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state4->SetAll(
- gfx::Transform(), rect6, rect6, gfx::MaskFilterInfo(), rect6,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect6, rect6, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
R1->SetNew(shared_quad_state, rect5, rect5, render_pass_id,
mask_resource_id, gfx::RectF(), gfx::Size(),
gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
@@ -3129,17 +3104,17 @@ TEST_F(DisplayTest, CompositorFrameWithRenderPass) {
// | R2 | R1 |
// +-----------+-------+
shared_quad_state->SetAll(
- gfx::Transform(), rect5, rect5, gfx::MaskFilterInfo(), rect5,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect5, rect5, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state3->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state4->SetAll(
- gfx::Transform(), rect7, rect7, gfx::MaskFilterInfo(), rect7,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect7, rect7, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
R1->SetNew(shared_quad_state, rect5, rect5, render_pass_id,
mask_resource_id, gfx::RectF(), gfx::Size(),
gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f);
@@ -3191,7 +3166,6 @@ TEST_F(DisplayTest, CompositorFrameWithMultipleDrawQuadInSharedQuadState) {
gfx::Rect rect3_1(0, 0, 70, 30);
gfx::Rect rect3_2(70, 0, 70, 30);
- bool is_clipped = false;
bool opaque_content = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -3218,12 +3192,11 @@ TEST_F(DisplayTest, CompositorFrameWithMultipleDrawQuadInSharedQuadState) {
// | | |
// +--+--+
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
- shared_quad_state2->SetAll(gfx::Transform(), rect_in_rect1, rect_in_rect1,
- gfx::MaskFilterInfo(), rect_in_rect1, is_clipped,
- opaque_content, opacity, SkBlendMode::kSrcOver,
- 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ shared_quad_state2->SetAll(
+ gfx::Transform(), rect_in_rect1, rect_in_rect1, gfx::MaskFilterInfo(),
+ absl::nullopt, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad1->SetNew(shared_quad_state, rect1_1, rect1_1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state, rect1_2, rect1_2, SK_ColorBLACK, false);
quad3->SetNew(shared_quad_state, rect1_3, rect1_3, SK_ColorBLACK, false);
@@ -3259,10 +3232,10 @@ TEST_F(DisplayTest, CompositorFrameWithMultipleDrawQuadInSharedQuadState) {
// +--+--+
quad5 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
- shared_quad_state2->SetAll(
- gfx::Transform(), rect_intersects_rect1, rect_intersects_rect1,
- gfx::MaskFilterInfo(), rect_intersects_rect1, is_clipped,
- opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ shared_quad_state2->SetAll(gfx::Transform(), rect_intersects_rect1,
+ rect_intersects_rect1, gfx::MaskFilterInfo(),
+ absl::nullopt, opaque_content, opacity,
+ SkBlendMode::kSrcOver, 0);
quad5->SetNew(shared_quad_state2, rect_intersects_rect1,
rect_intersects_rect1, SK_ColorBLACK, false);
EXPECT_EQ(5u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -3301,11 +3274,11 @@ TEST_F(DisplayTest, CompositorFrameWithMultipleDrawQuadInSharedQuadState) {
auto* quad6 = frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state->SetAll(
- gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), rect2,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect2, rect2, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(
- gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
+ opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad1->SetNew(shared_quad_state, rect2_1, rect2_1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state, rect2_2, rect2_2, SK_ColorBLACK, false);
quad3->SetNew(shared_quad_state, rect2_3, rect2_3, SK_ColorBLACK, false);
@@ -3360,7 +3333,6 @@ TEST_F(DisplayTest, CompositorFrameWithNonInvertibleTransform) {
0, 0, 0, 1); // row 4
gfx::Transform non_invertible_miss_z;
non_invertible_miss_z.Scale3d(1, 1, 0);
- bool is_clipped = false;
bool opaque_content = true;
float opacity = 1.f;
auto* quad1 = frame.render_pass_list.front()
@@ -3391,13 +3363,13 @@ TEST_F(DisplayTest, CompositorFrameWithNonInvertibleTransform) {
// and is hiding behind quad1; |quad3| follows a non-invertible transform
// and it is not covered by the occlusion rect.
shared_quad_state1->SetAll(invertible, rect1, rect1, gfx::MaskFilterInfo(),
- rect1, is_clipped, opaque_content, opacity,
+ absl::nullopt, opaque_content, opacity,
SkBlendMode::kSrcOver, 0);
shared_quad_state2->SetAll(invertible, rect2, rect2, gfx::MaskFilterInfo(),
- rect2, is_clipped, opaque_content, opacity,
+ absl::nullopt, opaque_content, opacity,
SkBlendMode::kSrcOver, 0);
shared_quad_state3->SetAll(
- non_invertible, rect3, rect3, gfx::MaskFilterInfo(), rect3, is_clipped,
+ non_invertible, rect3, rect3, gfx::MaskFilterInfo(), absl::nullopt,
opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad1->SetNew(shared_quad_state1, rect1, rect1, SK_ColorBLACK, false);
quad2->SetNew(shared_quad_state2, rect2, rect2, SK_ColorBLACK, false);
@@ -3425,11 +3397,11 @@ TEST_F(DisplayTest, CompositorFrameWithNonInvertibleTransform) {
// Verify if draw occlusion can occlude quad with non-invertible
// transform.
shared_quad_state1->SetAll(invertible, rect1, rect1, gfx::MaskFilterInfo(),
- rect1, is_clipped, opaque_content, opacity,
+ absl::nullopt, opaque_content, opacity,
SkBlendMode::kSrcOver, 0);
shared_quad_state3->SetAll(
- non_invertible_miss_z, rect3, rect3, gfx::MaskFilterInfo(), rect3,
- is_clipped, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
+ non_invertible_miss_z, rect3, rect3, gfx::MaskFilterInfo(),
+ absl::nullopt, opaque_content, opacity, SkBlendMode::kSrcOver, 0);
quad1->SetNew(shared_quad_state1, rect1, rect1, SK_ColorBLACK, false);
quad3->SetNew(shared_quad_state3, rect3, rect3, SK_ColorBLACK, false);
@@ -3456,7 +3428,6 @@ TEST_F(DisplayTest, DrawOcclusionWithLargeDrawQuad) {
// which caused the integer overflow in the bug.
gfx::Rect rect1(237790, 237790);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state =
@@ -3469,8 +3440,8 @@ TEST_F(DisplayTest, DrawOcclusionWithLargeDrawQuad) {
// +----+
{
shared_quad_state->SetAll(
- gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), rect1,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), rect1, rect1, gfx::MaskFilterInfo(), absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quad->SetNew(shared_quad_state, rect1, rect1, SK_ColorBLACK, false);
EXPECT_EQ(1u, NumVisibleRects(frame.render_pass_list.front()->quad_list));
@@ -3535,8 +3506,8 @@ TEST_F(DisplayTest, CompositorFrameWithPresentationToken) {
shared_quad_state1->SetAll(
gfx::Transform(), rect1 /* quad_layer_rect */,
rect1 /* visible_quad_layer_rect */,
- gfx::MaskFilterInfo() /* mask_filter_info */, rect1 /*clip_rect */,
- false /* is_clipped */, false /* are_contents_opaque */,
+ gfx::MaskFilterInfo() /* mask_filter_info */,
+ absl::nullopt /*clip_rect */, false /* are_contents_opaque */,
0.5f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
auto* quad1 = pass->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
quad1->SetNew(shared_quad_state1, rect1 /* rect */,
@@ -3548,13 +3519,13 @@ TEST_F(DisplayTest, CompositorFrameWithPresentationToken) {
shared_quad_state2->SetAll(
gfx::Transform(), rect2 /* quad_layer_rect */,
rect2 /* visible_quad_layer_rect */,
- gfx::MaskFilterInfo() /* mask_filter_info */, rect2 /*clip_rect */,
- false /* is_clipped */, true /* are_contents_opaque */,
+ gfx::MaskFilterInfo() /* mask_filter_info */,
+ absl::nullopt /*clip_rect */, true /* are_contents_opaque */,
1.0f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
auto* quad2 = pass->quad_list.AllocateAndConstruct<SurfaceDrawQuad>();
quad2->SetNew(shared_quad_state2, rect2 /* rect */,
rect2 /* visible_rect */,
- SurfaceRange(base::nullopt, sub_surface_id), SK_ColorBLACK,
+ SurfaceRange(absl::nullopt, sub_surface_id), SK_ColorBLACK,
false /* stretch_content_to_fill_bounds */);
pass_list.push_back(std::move(pass));
@@ -3838,7 +3809,8 @@ TEST_F(DisplayTest, InvalidPresentationTimestamps) {
.Build();
support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
display_->DrawAndSwap(base::TimeTicks::Now());
- display_->DidReceiveSwapBuffersAck(GetTestSwapTimings());
+ display_->DidReceiveSwapBuffersAck(GetTestSwapTimings(),
+ /*release_fence=*/gfx::GpuFenceHandle());
display_->DidReceivePresentationFeedback({base::TimeTicks::Now(), {}, 0});
EXPECT_THAT(histograms.GetAllSamples(
"Graphics.PresentationTimestamp.InvalidBeforeSwap"),
@@ -3857,7 +3829,8 @@ TEST_F(DisplayTest, InvalidPresentationTimestamps) {
.Build();
support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
display_->DrawAndSwap(base::TimeTicks::Now());
- display_->DidReceiveSwapBuffersAck(GetTestSwapTimings());
+ display_->DidReceiveSwapBuffersAck(GetTestSwapTimings(),
+ /*release_fence=*/gfx::GpuFenceHandle());
display_->DidReceivePresentationFeedback(
{base::TimeTicks::Now() - base::TimeDelta::FromSeconds(1), {}, 0});
EXPECT_THAT(histograms.GetAllSamples(
@@ -3881,7 +3854,8 @@ TEST_F(DisplayTest, InvalidPresentationTimestamps) {
.Build();
support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
display_->DrawAndSwap(base::TimeTicks::Now());
- display_->DidReceiveSwapBuffersAck(GetTestSwapTimings());
+ display_->DidReceiveSwapBuffersAck(GetTestSwapTimings(),
+ /*release_fence=*/gfx::GpuFenceHandle());
display_->DidReceivePresentationFeedback(
{base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(1),
{},
@@ -3903,7 +3877,8 @@ TEST_F(DisplayTest, InvalidPresentationTimestamps) {
.Build();
support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
display_->DrawAndSwap(base::TimeTicks::Now());
- display_->DidReceiveSwapBuffersAck(GetTestSwapTimings());
+ display_->DidReceiveSwapBuffersAck(GetTestSwapTimings(),
+ /*release_fence=*/gfx::GpuFenceHandle());
display_->DidReceivePresentationFeedback(
{base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(1), {}, 0});
EXPECT_THAT(histograms.GetAllSamples(
@@ -3926,7 +3901,8 @@ TEST_F(DisplayTest, InvalidPresentationTimestamps) {
.Build();
support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
display_->DrawAndSwap(base::TimeTicks::Now());
- display_->DidReceiveSwapBuffersAck(GetTestSwapTimings());
+ display_->DidReceiveSwapBuffersAck(GetTestSwapTimings(),
+ /*release_fence=*/gfx::GpuFenceHandle());
display_->DidReceivePresentationFeedback(
{base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1), {}, 0});
EXPECT_THAT(histograms.GetAllSamples(
@@ -3956,7 +3932,6 @@ TEST_F(DisplayTest, DrawOcclusionWithRoundedCornerDoesNotOcclude) {
gfx::MaskFilterInfo mask_filter_info(
gfx::RRectF(gfx::RectF(quad_rect), 10.f));
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state_with_rrect =
@@ -3972,16 +3947,15 @@ TEST_F(DisplayTest, DrawOcclusionWithRoundedCornerDoesNotOcclude) {
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
{
- shared_quad_state_occluded->SetAll(gfx::Transform(), quad_rect, quad_rect,
- gfx::MaskFilterInfo(), quad_rect,
- is_clipped, are_contents_opaque, opacity,
- SkBlendMode::kSrcOver, 0);
+ shared_quad_state_occluded->SetAll(
+ gfx::Transform(), quad_rect, quad_rect, gfx::MaskFilterInfo(),
+ absl::nullopt, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
occluded_quad->SetNew(shared_quad_state_occluded, quad_rect, quad_rect,
SK_ColorRED, false);
shared_quad_state_with_rrect->SetAll(
- gfx::Transform(), quad_rect, quad_rect, mask_filter_info, quad_rect,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), quad_rect, quad_rect, mask_filter_info, absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
rounded_corner_quad->SetNew(shared_quad_state_with_rrect, quad_rect,
quad_rect, SK_ColorBLUE, false);
@@ -4012,7 +3986,6 @@ TEST_F(DisplayTest, DrawOcclusionWithRoundedCornerDoesOcclude) {
gfx::MaskFilterInfo mask_filter_info(
gfx::RRectF(gfx::RectF(quad_rect), 10.f));
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state_with_rrect =
@@ -4030,14 +4003,14 @@ TEST_F(DisplayTest, DrawOcclusionWithRoundedCornerDoesOcclude) {
{
shared_quad_state_occluded->SetAll(
gfx::Transform(), occluded_quad_rect, occluded_quad_rect,
- gfx::MaskFilterInfo(), occluded_quad_rect, is_clipped,
- are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::MaskFilterInfo(), absl::nullopt, are_contents_opaque, opacity,
+ SkBlendMode::kSrcOver, 0);
occluded_quad->SetNew(shared_quad_state_occluded, occluded_quad_rect,
occluded_quad_rect, SK_ColorRED, false);
shared_quad_state_with_rrect->SetAll(
- gfx::Transform(), quad_rect, quad_rect, mask_filter_info, quad_rect,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), quad_rect, quad_rect, mask_filter_info, absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
rounded_corner_quad->SetNew(shared_quad_state_with_rrect, quad_rect,
quad_rect, SK_ColorBLUE, false);
@@ -4081,7 +4054,6 @@ TEST_F(DisplayTest, DrawOcclusionSplit) {
};
gfx::Rect occluded_sqs_rect(0, 0, 1200, 510);
- const bool is_clipped = false;
const bool are_contents_opaque = true;
const float opacity = 1.f;
SharedQuadState* shared_quad_state_occluder =
@@ -4098,15 +4070,14 @@ TEST_F(DisplayTest, DrawOcclusionSplit) {
{
shared_quad_state_occluder->SetAll(
gfx::Transform(), occluding_rect, occluding_rect, gfx::MaskFilterInfo(),
- occluding_rect, is_clipped, are_contents_opaque, opacity,
- SkBlendMode::kSrcOver, 0);
+ absl::nullopt, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
quads[0]->SetNew(shared_quad_state_occluder, occluding_rect, occluding_rect,
SK_ColorRED, false);
- shared_quad_state_occluded->SetAll(
- gfx::Transform(), occluded_sqs_rect, occluded_sqs_rect,
- gfx::MaskFilterInfo(), occluded_sqs_rect, is_clipped,
- are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ shared_quad_state_occluded->SetAll(gfx::Transform(), occluded_sqs_rect,
+ occluded_sqs_rect, gfx::MaskFilterInfo(),
+ absl::nullopt, are_contents_opaque,
+ opacity, SkBlendMode::kSrcOver, 0);
for (int i = 1; i < 4; i++) {
quads[i]->SetNew(shared_quad_state_occluded, quad_rects[i - 1],
quad_rects[i - 1], SK_ColorRED, false);
@@ -4156,7 +4127,6 @@ TEST_F(DisplayTest, FirstPassVisibleComplexityReduction) {
AggregatedFrame frame = MakeDefaultAggregatedFrame();
- const bool is_clipped = false;
const bool are_contents_opaque = true;
const float opacity = 1.f;
@@ -4201,7 +4171,7 @@ TEST_F(DisplayTest, FirstPassVisibleComplexityReduction) {
SharedQuadState* shared_quad_state_occluder =
frame.render_pass_list.front()->CreateAndAppendSharedQuadState();
shared_quad_state_occluder->SetAll(
- gfx::Transform(), r, r, gfx::MaskFilterInfo(), r, is_clipped,
+ gfx::Transform(), r, r, gfx::MaskFilterInfo(), absl::nullopt,
are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
SolidColorDrawQuad* quad =
frame.render_pass_list.front()
@@ -4215,8 +4185,7 @@ TEST_F(DisplayTest, FirstPassVisibleComplexityReduction) {
frame.render_pass_list.front()->CreateAndAppendSharedQuadState();
shared_quad_state_occluded->SetAll(
gfx::Transform(), occluded_rect, occluded_rect, gfx::MaskFilterInfo(),
- occluded_rect, is_clipped, are_contents_opaque, opacity,
- SkBlendMode::kSrcOver, 0);
+ absl::nullopt, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
SolidColorDrawQuad* occluded_quad =
frame.render_pass_list.front()
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
@@ -4270,7 +4239,6 @@ TEST_F(DisplayTest, DrawOcclusionSplitDeviceScaleFactorFractional) {
AggregatedFrame frame = MakeDefaultAggregatedFrame();
- const bool is_clipped = false;
const bool are_contents_opaque = true;
const float opacity = 1.f;
@@ -4283,8 +4251,7 @@ TEST_F(DisplayTest, DrawOcclusionSplitDeviceScaleFactorFractional) {
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state_occluding->SetAll(
gfx::Transform(), occluding_rect, occluding_rect, gfx::MaskFilterInfo(),
- occluding_rect, is_clipped, are_contents_opaque, opacity,
- SkBlendMode::kSrcOver, 0);
+ absl::nullopt, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
occluding_quad->SetNew(shared_quad_state_occluding, occluding_rect,
occluding_rect, SK_ColorRED, false);
// Occluded quad.
@@ -4296,8 +4263,7 @@ TEST_F(DisplayTest, DrawOcclusionSplitDeviceScaleFactorFractional) {
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
shared_quad_state_occluded->SetAll(
gfx::Transform(), occluded_rect, occluded_rect, gfx::MaskFilterInfo(),
- occluded_rect, is_clipped, are_contents_opaque, opacity,
- SkBlendMode::kSrcOver, 0);
+ absl::nullopt, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
occluded_quad->SetNew(shared_quad_state_occluded, occluded_rect,
occluded_rect, SK_ColorRED, false);
@@ -4343,7 +4309,6 @@ TEST_F(DisplayTest, DrawOcclusionWithRoundedCornerPartialOcclude) {
occluded_sqs_rect.Union(occluded_quad_rect_3);
occluded_sqs_rect.Union(occluded_quad_rect_4);
- bool is_clipped = false;
bool are_contents_opaque = true;
float opacity = 1.f;
SharedQuadState* shared_quad_state_with_rrect =
@@ -4368,10 +4333,10 @@ TEST_F(DisplayTest, DrawOcclusionWithRoundedCornerPartialOcclude) {
->quad_list.AllocateAndConstruct<SolidColorDrawQuad>();
{
- shared_quad_state_occluded->SetAll(
- gfx::Transform(), occluded_sqs_rect, occluded_sqs_rect,
- gfx::MaskFilterInfo(), occluded_sqs_rect, is_clipped,
- are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ shared_quad_state_occluded->SetAll(gfx::Transform(), occluded_sqs_rect,
+ occluded_sqs_rect, gfx::MaskFilterInfo(),
+ absl::nullopt, are_contents_opaque,
+ opacity, SkBlendMode::kSrcOver, 0);
occluded_quad_1->SetNew(shared_quad_state_occluded, occluded_quad_rect_1,
occluded_quad_rect_1, SK_ColorRED, false);
occluded_quad_2->SetNew(shared_quad_state_occluded, occluded_quad_rect_2,
@@ -4382,8 +4347,8 @@ TEST_F(DisplayTest, DrawOcclusionWithRoundedCornerPartialOcclude) {
occluded_quad_rect_4, SK_ColorRED, false);
shared_quad_state_with_rrect->SetAll(
- gfx::Transform(), quad_rect, quad_rect, mask_filter_info, quad_rect,
- is_clipped, are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
+ gfx::Transform(), quad_rect, quad_rect, mask_filter_info, absl::nullopt,
+ are_contents_opaque, opacity, SkBlendMode::kSrcOver, 0);
rounded_corner_quad->SetNew(shared_quad_state_with_rrect, quad_rect,
quad_rect, SK_ColorBLUE, false);
@@ -5108,4 +5073,27 @@ TEST_P(DelegatedInkDisplayTest, MetadataOnlySentToSkiaRendererOrOutputSurface) {
EXPECT_FALSE(skia_output_surface_->last_delegated_ink_metadata());
}
+// Check that a pending delegated ink point renderer sent to the display
+// correctly goes to either the renderer or the output surface depending on if
+// the platform supports delegated ink and the feature flag is enabled or not.
+TEST_P(DelegatedInkDisplayTest,
+ InkRendererRemoteGoesToSkiaRendererOrOutputSurface) {
+ SetUpGpuDisplay();
+
+ mojo::Remote<gfx::mojom::DelegatedInkPointRenderer> ink_renderer_remote;
+ display_->InitDelegatedInkPointRendererReceiver(
+ ink_renderer_remote.BindNewPipeAndPassReceiver());
+
+ if (GetParam() == DelegatedInkType::kPlatformInk) {
+ EXPECT_TRUE(skia_output_surface_
+ ->ContainsDelegatedInkPointRendererReceiverForTesting());
+ EXPECT_FALSE(ink_renderer());
+ } else {
+ EXPECT_FALSE(skia_output_surface_
+ ->ContainsDelegatedInkPointRendererReceiverForTesting());
+ EXPECT_TRUE(ink_renderer());
+ EXPECT_TRUE(ink_renderer_remote.is_bound());
+ }
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/draw_polygon.h b/chromium/components/viz/service/display/draw_polygon.h
index 9bafa163f2f..410279ae420 100644
--- a/chromium/components/viz/service/display/draw_polygon.h
+++ b/chromium/components/viz/service/display/draw_polygon.h
@@ -32,13 +32,6 @@ class VIZ_SERVICE_EXPORT DrawPolygon {
const gfx::Transform& transform,
int draw_order_index = 0);
- // Split takes this DrawPolygon and splits it into two pieces that are on
- // either side of |splitter|. Any edges of this polygon that cross the plane
- // of |splitter| will have an intersection point that is shared by both
- // polygons on either side.
- // Split will only return true if it determines that we got back 2
- // intersection points. Only when it returns true will front and back both be
- // valid new polygons that are on opposite sides of the splitting plane.
void SplitPolygon(std::unique_ptr<DrawPolygon> polygon,
std::unique_ptr<DrawPolygon>* front,
std::unique_ptr<DrawPolygon>* back,
diff --git a/chromium/components/viz/service/display/draw_polygon_unittest.cc b/chromium/components/viz/service/display/draw_polygon_unittest.cc
index c44b6239bb5..598e61ab47d 100644
--- a/chromium/components/viz/service/display/draw_polygon_unittest.cc
+++ b/chromium/components/viz/service/display/draw_polygon_unittest.cc
@@ -9,9 +9,9 @@
#include <utility>
#include <vector>
+#include "base/containers/contains.h"
#include "base/logging.h"
#include "base/numerics/math_constants.h"
-#include "base/stl_util.h"
#include "build/build_config.h"
#include "components/viz/service/display/bsp_compare_result.h"
#include "components/viz/service/display/draw_polygon.h"
diff --git a/chromium/components/viz/service/display/external_use_client.cc b/chromium/components/viz/service/display/external_use_client.cc
index 31d4e592a45..c940fd25614 100644
--- a/chromium/components/viz/service/display/external_use_client.cc
+++ b/chromium/components/viz/service/display/external_use_client.cc
@@ -12,7 +12,7 @@ ExternalUseClient::ImageContext::ImageContext(
const gpu::MailboxHolder& mailbox_holder,
const gfx::Size& size,
ResourceFormat resource_format,
- const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
+ const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
sk_sp<SkColorSpace> color_space)
: mailbox_holder_(mailbox_holder),
size_(size),
diff --git a/chromium/components/viz/service/display/external_use_client.h b/chromium/components/viz/service/display/external_use_client.h
index dced00dbfcb..88ca217256f 100644
--- a/chromium/components/viz/service/display/external_use_client.h
+++ b/chromium/components/viz/service/display/external_use_client.h
@@ -9,12 +9,13 @@
#include <utility>
#include <vector>
+#include "base/check.h"
#include "base/macros.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/abseil-cpp/absl/types/optional.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"
@@ -36,7 +37,7 @@ class VIZ_SERVICE_EXPORT ExternalUseClient {
ImageContext(const gpu::MailboxHolder& mailbox_holder,
const gfx::Size& size,
ResourceFormat resource_format,
- const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
+ const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
sk_sp<SkColorSpace> color_space);
virtual ~ImageContext();
virtual void OnContextLost();
@@ -65,7 +66,7 @@ class VIZ_SERVICE_EXPORT ExternalUseClient {
origin_ = origin;
}
- base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info() { return ycbcr_info_; }
+ absl::optional<gpu::VulkanYCbCrInfo> ycbcr_info() { return ycbcr_info_; }
bool has_image() { return !!image_; }
sk_sp<SkImage> image() { return image_; }
@@ -85,7 +86,7 @@ class VIZ_SERVICE_EXPORT ExternalUseClient {
// Sampler conversion information which is used in vulkan context for
// android video.
- base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info_;
+ absl::optional<gpu::VulkanYCbCrInfo> ycbcr_info_;
// The promise image which is used on display thread.
sk_sp<SkImage> image_;
@@ -101,7 +102,7 @@ class VIZ_SERVICE_EXPORT ExternalUseClient {
const gfx::Size& size,
ResourceFormat format,
bool maybe_concurrent_reads,
- const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
+ const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
sk_sp<SkColorSpace> color_space) = 0;
virtual gpu::SyncToken ReleaseImageContexts(
diff --git a/chromium/components/viz/service/display/frame_rate_decider.cc b/chromium/components/viz/service/display/frame_rate_decider.cc
index 64aa8063b79..ee93f14320e 100644
--- a/chromium/components/viz/service/display/frame_rate_decider.cc
+++ b/chromium/components/viz/service/display/frame_rate_decider.cc
@@ -170,7 +170,7 @@ void FrameRateDecider::UpdatePreferredFrameIntervalIfNeeded() {
// animating. This ensures that, for instance, if we're currently displaying
// a video while the rest of the page is static, we choose the frame interval
// optimal for the video.
- base::Optional<base::TimeDelta> min_frame_sink_interval;
+ absl::optional<base::TimeDelta> min_frame_sink_interval;
bool all_frame_sinks_have_same_interval = true;
for (const auto& frame_sink_id : frame_sinks_updated_in_previous_frame_) {
auto interval =
diff --git a/chromium/components/viz/service/display/frame_rate_decider_unittest.cc b/chromium/components/viz/service/display/frame_rate_decider_unittest.cc
index e4d902accf3..bd9f210709a 100644
--- a/chromium/components/viz/service/display/frame_rate_decider_unittest.cc
+++ b/chromium/components/viz/service/display/frame_rate_decider_unittest.cc
@@ -26,7 +26,7 @@ class FrameRateDeciderTest : public testing::Test,
~FrameRateDeciderTest() override = default;
void SetUp() override {
- surface_manager_ = std::make_unique<SurfaceManager>(this, base::nullopt);
+ surface_manager_ = std::make_unique<SurfaceManager>(this, absl::nullopt);
bool hw_support_for_multiple_refresh_rates = true;
frame_rate_decider_ = std::make_unique<FrameRateDecider>(
surface_manager_.get(), this, hw_support_for_multiple_refresh_rates,
diff --git a/chromium/components/viz/service/display/gl_renderer.cc b/chromium/components/viz/service/display/gl_renderer.cc
index de998b97d01..1def2c5e8b8 100644
--- a/chromium/components/viz/service/display/gl_renderer.cc
+++ b/chromium/components/viz/service/display/gl_renderer.cc
@@ -23,7 +23,6 @@
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -61,6 +60,7 @@
#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 "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkColorFilter.h"
@@ -79,6 +79,7 @@
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/vector2d.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/rrect_f.h"
#include "ui/gfx/skia_util.h"
@@ -303,7 +304,7 @@ struct GLRenderer::DrawRenderPassDrawQuadParams {
gfx::Transform quad_to_target_transform;
const cc::FilterOperations* filters = nullptr;
const cc::FilterOperations* backdrop_filters = nullptr;
- base::Optional<gfx::RRectF> backdrop_filter_bounds;
+ absl::optional<gfx::RRectF> backdrop_filter_bounds;
// Whether the texture to be sampled from needs to be flipped.
bool source_needs_flip = false;
@@ -867,7 +868,7 @@ bool GLRenderer::ShouldApplyBackdropFilters(
gfx::Rect GLRenderer::GetBackdropBoundingBoxForRenderPassQuad(
DrawRenderPassDrawQuadParams* params,
gfx::Transform* backdrop_filter_bounds_transform,
- base::Optional<gfx::RRectF>* backdrop_filter_bounds,
+ absl::optional<gfx::RRectF>* backdrop_filter_bounds,
gfx::Rect* unclipped_rect) const {
DCHECK(backdrop_filter_bounds_transform);
DCHECK(backdrop_filter_bounds);
@@ -1053,7 +1054,7 @@ static sk_sp<SkImage> FinalizeImage(sk_sp<SkSurface> surface) {
sk_sp<SkImage> GLRenderer::ApplyBackdropFilters(
DrawRenderPassDrawQuadParams* params,
const gfx::Rect& unclipped_rect,
- const base::Optional<gfx::RRectF>& backdrop_filter_bounds,
+ const absl::optional<gfx::RRectF>& backdrop_filter_bounds,
const gfx::Transform& backdrop_filter_bounds_transform) {
DCHECK(ShouldApplyBackdropFilters(params));
DCHECK(params->backdrop_filter_quality > 0.0f &&
@@ -1421,7 +1422,7 @@ void GLRenderer::UpdateRPDQShadersForBlending(
if (params->use_shaders_for_blending) {
// Compute a bounding box around the pixels that will be visible through
// the quad.
- base::Optional<gfx::RRectF> backdrop_filter_bounds;
+ absl::optional<gfx::RRectF> backdrop_filter_bounds;
gfx::Transform backdrop_filter_bounds_transform;
gfx::Rect unclipped_rect;
params->background_rect = GetBackdropBoundingBoxForRenderPassQuad(
@@ -1519,10 +1520,8 @@ bool GLRenderer::UpdateRPDQWithSkiaFilters(
filter = sk_ref_sp(filter->getInput(0));
}
if (filter) {
- gfx::Rect clip_rect = quad->shared_quad_state->clip_rect;
- if (clip_rect.IsEmpty()) {
- clip_rect = current_draw_rect_;
- }
+ gfx::Rect clip_rect =
+ quad->shared_quad_state->clip_rect.value_or(current_draw_rect_);
gfx::Transform transform = params->quad_to_target_transform;
transform.FlattenTo2d();
if (!transform.IsInvertible()) {
@@ -2603,7 +2602,7 @@ void GLRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad,
}
#endif
- // TODO(jbauman): Use base::Optional when available.
+ // TODO(jbauman): Use absl::optional when available.
std::unique_ptr<DisplayResourceProviderGL::ScopedSamplerGL> v_plane_lock;
if (uv_texture_mode == UV_TEXTURE_MODE_U_V) {
v_plane_lock = std::make_unique<DisplayResourceProviderGL::ScopedSamplerGL>(
@@ -2837,7 +2836,8 @@ void GLRenderer::FlushTextureQuadCache(BoundGeometry flush_binding) {
// Bind the program to the GL state.
SetUseProgram(draw_cache_.program_key, locked_quad.color_space(),
CurrentRenderPassColorSpace(),
- /*adjust_src_white_level=*/draw_cache_.is_video_frame);
+ /*adjust_src_white_level=*/draw_cache_.is_video_frame,
+ locked_quad.hdr_metadata());
if (current_program_->rounded_corner_rect_location() != -1) {
SetShaderRoundedCorner(
@@ -3458,7 +3458,8 @@ void GLRenderer::SwapBuffersSkipped() {
}
}
-void GLRenderer::SwapBuffersComplete() {
+void GLRenderer::SwapBuffersComplete(gfx::GpuFenceHandle release_fence) {
+ DCHECK(release_fence.is_null());
if (settings_->release_overlay_resources_after_gpu_query) {
// Once a resource has been swap-ACKed, send a query to the GPU process to
// ask if the resource is no longer being consumed by the system compositor.
@@ -3663,12 +3664,16 @@ void GLRenderer::PrepareGeometry(BoundGeometry binding) {
void GLRenderer::SetUseProgram(const ProgramKey& program_key_no_color,
const gfx::ColorSpace& src_color_space,
const gfx::ColorSpace& dst_color_space,
- bool adjust_src_white_level) {
+ bool adjust_src_white_level,
+ absl::optional<gfx::HDRMetadata> hdr_metadata) {
DCHECK(dst_color_space.IsValid());
gfx::ColorSpace adjusted_src_color_space = src_color_space;
- if (adjust_src_white_level) {
- // If the input color space is HDR, and it did not specify a white level,
- // override it with the frame's white level.
+ if (adjust_src_white_level && src_color_space.IsHDR()) {
+ // TODO(b/183236148): consider using the destination's HDR static metadata
+ // in current_frame()->display_color_spaces.hdr_static_metadata() and the
+ // mastering metadata in |src_hdr_metadata| for the tone mapping; e.g. the
+ // content might be mastered in 0-1000 nits but the display only be able to
+ // represent 0 to 500.
adjusted_src_color_space = src_color_space.GetWithSDRWhiteLevel(
current_frame()->display_color_spaces.GetSDRWhiteLevel());
}
@@ -3914,8 +3919,9 @@ void GLRenderer::ScheduleDCLayers() {
const gfx::Rect& quad_rect = dc_layer_overlay.quad_rect;
DCHECK(dc_layer_overlay.transform.IsFlat());
const SkMatrix44& transform = dc_layer_overlay.transform.matrix();
- bool is_clipped = dc_layer_overlay.is_clipped;
- const gfx::Rect& clip_rect = dc_layer_overlay.clip_rect;
+ bool is_clipped = dc_layer_overlay.clip_rect.has_value();
+ const gfx::Rect& clip_rect =
+ dc_layer_overlay.clip_rect.value_or(gfx::Rect());
unsigned protected_video_type =
static_cast<unsigned>(dc_layer_overlay.protected_video_type);
diff --git a/chromium/components/viz/service/display/gl_renderer.h b/chromium/components/viz/service/display/gl_renderer.h
index 60eb61f791e..2570a53afbb 100644
--- a/chromium/components/viz/service/display/gl_renderer.h
+++ b/chromium/components/viz/service/display/gl_renderer.h
@@ -34,6 +34,7 @@
#include "components/viz/service/display/texture_deleter.h"
#include "components/viz/service/viz_service_export.h"
#include "ui/gfx/geometry/quad_f.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/latency/latency_info.h"
#if defined(OS_APPLE)
@@ -85,7 +86,7 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
void SwapBuffers(SwapFrameData swap_frame_data) override;
void SwapBuffersSkipped() override;
- void SwapBuffersComplete() override;
+ void SwapBuffersComplete(gfx::GpuFenceHandle release_fence) override;
void DidReceiveTextureInUseResponses(
const gpu::TextureInUseResponses& responses) override;
@@ -224,7 +225,7 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
gfx::Rect GetBackdropBoundingBoxForRenderPassQuad(
DrawRenderPassDrawQuadParams* params,
gfx::Transform* backdrop_filter_bounds_transform,
- base::Optional<gfx::RRectF>* backdrop_filter_bounds,
+ absl::optional<gfx::RRectF>* backdrop_filter_bounds,
gfx::Rect* unclipped_rect) const;
// Allocates and returns a texture id that contains a copy of the contents
@@ -247,7 +248,7 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
sk_sp<SkImage> ApplyBackdropFilters(
DrawRenderPassDrawQuadParams* params,
const gfx::Rect& unclipped_rect,
- const base::Optional<gfx::RRectF>& backdrop_filter_bounds,
+ const absl::optional<gfx::RRectF>& backdrop_filter_bounds,
const gfx::Transform& backdrop_filter_bounds_transform);
// gl_renderer can bypass TileDrawQuads that fill the RenderPass
@@ -306,11 +307,14 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
// that video color conversion can be enabled separately from general color
// conversion. If |adjust_src_white_level| is true, then the |src_color_space|
// white levels are adjusted to the display SDR white level so that no white
- // level scaling happens.
- void SetUseProgram(const ProgramKey& program_key,
- const gfx::ColorSpace& src_color_space,
- const gfx::ColorSpace& dst_color_space,
- bool adjust_src_white_level = false);
+ // level scaling happens. |src_hdr_metadata|, if available, is the mastering
+ // metadata associated to the source quad.
+ void SetUseProgram(
+ const ProgramKey& program_key,
+ const gfx::ColorSpace& src_color_space,
+ const gfx::ColorSpace& dst_color_space,
+ bool adjust_src_white_level = false,
+ absl::optional<gfx::HDRMetadata> src_hdr_metadata = absl::nullopt);
bool MakeContextCurrent();
diff --git a/chromium/components/viz/service/display/gl_renderer_copier_pixeltest.cc b/chromium/components/viz/service/display/gl_renderer_copier_pixeltest.cc
index 79ae1af745d..1f090f446ed 100644
--- a/chromium/components/viz/service/display/gl_renderer_copier_pixeltest.cc
+++ b/chromium/components/viz/service/display/gl_renderer_copier_pixeltest.cc
@@ -291,7 +291,7 @@ TEST_P(GLRendererCopierPixelTest, ExecutesCopyRequest) {
ASSERT_EQ(kRequestArea, result->rect());
// Examine the image in the |result|, and compare it to the baseline PNG file.
- base::Optional<CopyOutputResult::ScopedSkBitmap> scoped_bitmap;
+ absl::optional<CopyOutputResult::ScopedSkBitmap> scoped_bitmap;
SkBitmap actual;
if (result_format_ == CopyOutputResult::Format::RGBA_BITMAP) {
scoped_bitmap = result->ScopedAccessSkBitmap();
diff --git a/chromium/components/viz/service/display/gl_renderer_unittest.cc b/chromium/components/viz/service/display/gl_renderer_unittest.cc
index c2923e22204..60c460a2e1b 100644
--- a/chromium/components/viz/service/display/gl_renderer_unittest.cc
+++ b/chromium/components/viz/service/display/gl_renderer_unittest.cc
@@ -16,6 +16,7 @@
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -852,7 +853,7 @@ TEST_F(GLRendererWithDefaultHarnessTest, TextureDrawQuadShaderPrecisionHigh) {
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
gfx::Size(1025, 1025), true);
ResourceId client_resource_id = child_resource_provider->ImportResource(
- transfer_resource, SingleReleaseCallback::Create(base::DoNothing()));
+ transfer_resource, base::DoNothing());
std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map =
cc::SendResourceAndGetChildToParentMap(
@@ -867,8 +868,7 @@ TEST_F(GLRendererWithDefaultHarnessTest, TextureDrawQuadShaderPrecisionHigh) {
SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
gfx::Rect(1023, 1023), gfx::MaskFilterInfo(),
- gfx::Rect(1023, 1023), false, false, 1,
- SkBlendMode::kSrcOver, 0);
+ absl::nullopt, false, 1, SkBlendMode::kSrcOver, 0);
overlay_quad->SetNew(shared_state, gfx::Rect(1023, 1023),
gfx::Rect(1023, 1023), needs_blending, resource_id,
premultiplied_alpha, uv_top_left, uv_bottom_right,
@@ -915,7 +915,7 @@ TEST_F(GLRendererWithDefaultHarnessTest, TextureDrawQuadShaderPrecisionMedium) {
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
gfx::Size(1023, 1023), true);
ResourceId client_resource_id = child_resource_provider->ImportResource(
- transfer_resource, SingleReleaseCallback::Create(base::DoNothing()));
+ transfer_resource, base::DoNothing());
std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map =
cc::SendResourceAndGetChildToParentMap(
@@ -930,8 +930,7 @@ TEST_F(GLRendererWithDefaultHarnessTest, TextureDrawQuadShaderPrecisionMedium) {
SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
gfx::Rect(1025, 1025), gfx::MaskFilterInfo(),
- gfx::Rect(1025, 1025), false, false, 1,
- SkBlendMode::kSrcOver, 0);
+ absl::nullopt, false, 1, SkBlendMode::kSrcOver, 0);
overlay_quad->SetNew(shared_state, gfx::Rect(1025, 1025),
gfx::Rect(1025, 1025), needs_blending, resource_id,
premultiplied_alpha, uv_top_left, uv_bottom_right,
@@ -975,7 +974,7 @@ class GLRendererTextureDrawQuadHDRTest
kTextureSize, true);
transfer_resource.color_space = gfx::ColorSpace::CreateSCRGBLinear();
ResourceId client_resource_id = child_resource_provider->ImportResource(
- transfer_resource, SingleReleaseCallback::Create(base::DoNothing()));
+ transfer_resource, base::DoNothing());
std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map =
cc::SendResourceAndGetChildToParentMap(
@@ -988,8 +987,7 @@ class GLRendererTextureDrawQuadHDRTest
SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
gfx::Rect(kTextureSize), gfx::MaskFilterInfo(),
- gfx::Rect(kTextureSize), false, false, 1,
- SkBlendMode::kSrcOver, 0);
+ absl::nullopt, false, 1, SkBlendMode::kSrcOver, 0);
overlay_quad->SetNew(shared_state, gfx::Rect(kTextureSize),
gfx::Rect(kTextureSize), needs_blending, resource_id,
premultiplied_alpha, uv_top_left, uv_bottom_right,
@@ -1497,7 +1495,7 @@ TEST_F(GLRendererTest, DrawYUVVideoDrawQuadWithVisibleRect) {
SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(), gfx::Rect(), rect,
- gfx::MaskFilterInfo(), rect, false, false, 1,
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1,
SkBlendMode::kSrcOver, 0);
YUVVideoDrawQuad* quad =
@@ -2053,7 +2051,6 @@ TEST_F(GLRendererSkipTest, SkipVisibleRect) {
gfx::Transform(), cc::FilterOperations());
root_pass->damage_rect = gfx::Rect(0, 0, 10, 10);
cc::AddQuad(root_pass, quad_rect, SK_ColorGREEN);
- root_pass->shared_quad_state_list.front()->is_clipped = true;
root_pass->shared_quad_state_list.front()->clip_rect =
gfx::Rect(0, 0, 40, 40);
root_pass->quad_list.front()->visible_rect = gfx::Rect(20, 20, 20, 20);
@@ -2149,8 +2146,8 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
auto transfer_resource = TransferableResource::MakeGL(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
child_rect.size(), false /* is_overlay_candidate */);
- ResourceId mask = child_resource_provider_->ImportResource(
- transfer_resource, SingleReleaseCallback::Create(base::DoNothing()));
+ ResourceId mask = child_resource_provider_->ImportResource(transfer_resource,
+ base::DoNothing());
// Return the mapped resource id.
std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map =
@@ -2690,8 +2687,9 @@ class TestOverlayProcessor : public OverlayProcessorStub {
void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource) {}
static void CollectResources(std::vector<ReturnedResource>* array,
- const std::vector<ReturnedResource>& returned) {
- array->insert(array->end(), returned.begin(), returned.end());
+ std::vector<ReturnedResource> returned) {
+ array->insert(array->end(), std::make_move_iterator(returned.begin()),
+ std::make_move_iterator(returned.end()));
}
TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
@@ -2713,14 +2711,13 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
auto transfer_resource = TransferableResource::MakeGL(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
gfx::Size(256, 256), true);
- auto release_callback =
- SingleReleaseCallback::Create(base::BindOnce(&MailboxReleased));
+ auto release_callback = base::BindOnce(&MailboxReleased);
ResourceId resource_id = child_resource_provider->ImportResource(
transfer_resource, std::move(release_callback));
std::vector<ReturnedResource> returned_to_child;
int child_id = parent_resource_provider->CreateChild(
- base::BindRepeating(&CollectResources, &returned_to_child));
+ base::BindRepeating(&CollectResources, &returned_to_child), SurfaceId());
// Transfer resource to the parent.
std::vector<ResourceId> resource_ids_to_transfer;
@@ -2922,14 +2919,13 @@ TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
auto transfer_resource = TransferableResource::MakeGL(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, sync_token,
gfx::Size(256, 256), true);
- auto release_callback =
- SingleReleaseCallback::Create(base::BindOnce(&MailboxReleased));
+ auto release_callback = base::BindOnce(&MailboxReleased);
ResourceId resource_id = child_resource_provider->ImportResource(
transfer_resource, std::move(release_callback));
std::vector<ReturnedResource> returned_to_child;
int child_id = parent_resource_provider->CreateChild(
- base::BindRepeating(&CollectResources, &returned_to_child));
+ base::BindRepeating(&CollectResources, &returned_to_child), SurfaceId());
// Transfer resource to the parent.
std::vector<ResourceId> resource_ids_to_transfer;
@@ -2972,8 +2968,7 @@ TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
gfx::Rect(viewport_size), gfx::MaskFilterInfo(),
- gfx::Rect(viewport_size), false, false, 1,
- SkBlendMode::kSrcOver, 0);
+ absl::nullopt, false, 1, SkBlendMode::kSrcOver, 0);
overlay_quad->SetNew(shared_state, gfx::Rect(viewport_size),
gfx::Rect(viewport_size), needs_blending,
parent_resource_id, premultiplied_alpha, uv_top_left,
@@ -3701,14 +3696,13 @@ TEST_F(GLRendererTest, DCLayerOverlaySwitch) {
auto transfer_resource = TransferableResource::MakeGL(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
gfx::Size(256, 256), true);
- auto release_callback =
- SingleReleaseCallback::Create(base::BindOnce(&MailboxReleased));
+ auto release_callback = base::BindOnce(&MailboxReleased);
ResourceId resource_id = child_resource_provider->ImportResource(
transfer_resource, std::move(release_callback));
std::vector<ReturnedResource> returned_to_child;
int child_id = parent_resource_provider->CreateChild(
- base::BindRepeating(&CollectResources, &returned_to_child));
+ base::BindRepeating(&CollectResources, &returned_to_child), SurfaceId());
// Transfer resource to the parent.
std::vector<ResourceId> resource_ids_to_transfer;
@@ -3749,7 +3743,7 @@ TEST_F(GLRendererTest, DCLayerOverlaySwitch) {
SharedQuadState* shared_state =
root_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(), rect, rect, gfx::MaskFilterInfo(),
- rect, false, false, 1, SkBlendMode::kSrcOver, 0);
+ absl::nullopt, false, 1, SkBlendMode::kSrcOver, 0);
YUVVideoDrawQuad* quad =
root_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
quad->SetNew(shared_state, rect, rect, needs_blending, tex_coord_rect,
@@ -4071,7 +4065,7 @@ class CALayerGLRendererTest : public GLRendererTest {
DrawFrame(&renderer(), viewport_size);
renderer().SwapBuffers(DirectRenderer::SwapFrameData());
- renderer().SwapBuffersComplete();
+ renderer().SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
Mock::VerifyAndClearExpectations(&gl());
}
@@ -4190,11 +4184,10 @@ TEST_F(CALayerGLRendererTest, CALayerRoundRects) {
SharedQuadState* sqs =
const_cast<SharedQuadState*>(quad->shared_quad_state);
- sqs->is_clipped = true;
sqs->clip_rect = gfx::Rect(2, 2, 6, 6);
const float radius = 2;
sqs->mask_filter_info =
- gfx::MaskFilterInfo(gfx::RRectF(gfx::RectF(sqs->clip_rect), radius));
+ gfx::MaskFilterInfo(gfx::RRectF(gfx::RectF(*sqs->clip_rect), radius));
switch (subtest) {
case 0:
@@ -4294,7 +4287,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReusesTextureWithDifferentSizes) {
// The texture will be checked to verify if it is free yet.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(1, _));
- renderer().SwapBuffersComplete();
+ renderer().SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
Mock::VerifyAndClearExpectations(&gl());
// Frame number 2. We change the size of the child RenderPass to be smaller
@@ -4340,7 +4333,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReusesTextureWithDifferentSizes) {
// There are now 2 textures to check if they are free.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(2, _));
- renderer().SwapBuffersComplete();
+ renderer().SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
Mock::VerifyAndClearExpectations(&gl());
// The first (256x256) texture is returned to the GLRenderer.
@@ -4449,7 +4442,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysDontReuseTooBigTexture) {
// The texture will be checked to verify if it is free yet.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(1, _));
- renderer().SwapBuffersComplete();
+ renderer().SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
Mock::VerifyAndClearExpectations(&gl());
// Frame number 2. We change the size of the child RenderPass to be much
@@ -4493,7 +4486,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysDontReuseTooBigTexture) {
// There are now 2 textures to check if they are free.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(2, _));
- renderer().SwapBuffersComplete();
+ renderer().SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
Mock::VerifyAndClearExpectations(&gl());
// The first (256x256) texture is returned to the GLRenderer.
@@ -4627,7 +4620,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseAfterNoSwapBuffers) {
// There are 2 textures to check if they are free.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(2, _));
- renderer().SwapBuffersComplete();
+ renderer().SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
Mock::VerifyAndClearExpectations(&gl());
// Both textures get returned and the 2nd one can be reused.
@@ -4727,7 +4720,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseManyIfReturnedSlowly) {
// All sent textures will be checked to verify if they are free yet.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(i + 1, _));
- renderer().SwapBuffersComplete();
+ renderer().SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
Mock::VerifyAndClearExpectations(&gl());
}
@@ -4796,7 +4789,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseManyIfReturnedSlowly) {
// also 1 outstanding texture to check for that wasn't returned yet from the
// above loop.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(i + 2, _));
- renderer().SwapBuffersComplete();
+ renderer().SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
Mock::VerifyAndClearExpectations(&gl());
}
}
@@ -4856,7 +4849,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysCachedTexturesAreFreed) {
// All sent textures will be checked to verify if they are free yet.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(i + 1, _));
- renderer().SwapBuffersComplete();
+ renderer().SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
Mock::VerifyAndClearExpectations(&gl());
}
@@ -4889,7 +4882,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysCachedTexturesAreFreed) {
// There's just 1 outstanding RenderPass texture to query for.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(1, _));
- renderer().SwapBuffersComplete();
+ renderer().SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
Mock::VerifyAndClearExpectations(&gl());
}
@@ -5112,7 +5105,7 @@ class GLRendererWithGpuFenceTest : public GLRendererTest {
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
gfx::Size(256, 256), true);
ResourceId client_resource_id = child_resource_provider_->ImportResource(
- transfer_resource, SingleReleaseCallback::Create(base::DoNothing()));
+ transfer_resource, base::DoNothing());
std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map =
cc::SendResourceAndGetChildToParentMap(
@@ -5177,9 +5170,8 @@ TEST_F(GLRendererWithGpuFenceTest,
root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
SharedQuadState* shared_state = root_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(), gfx::Rect(viewport_size),
- gfx::Rect(50, 50), gfx::MaskFilterInfo(),
- gfx::Rect(viewport_size), false, false, 1,
- SkBlendMode::kSrcOver, 0);
+ gfx::Rect(50, 50), gfx::MaskFilterInfo(), absl::nullopt,
+ false, 1, SkBlendMode::kSrcOver, 0);
overlay_quad->SetNew(
shared_state, gfx::Rect(viewport_size), gfx::Rect(viewport_size),
needs_blending, create_overlay_resource(), premultiplied_alpha,
diff --git a/chromium/components/viz/service/display/output_surface.cc b/chromium/components/viz/service/display/output_surface.cc
index cba4925311d..df3d9eab1a3 100644
--- a/chromium/components/viz/service/display/output_surface.cc
+++ b/chromium/components/viz/service/display/output_surface.cc
@@ -95,4 +95,10 @@ gpu::Mailbox OutputSurface::GetOverlayMailbox() const {
return gpu::Mailbox();
}
+void OutputSurface::InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) {
+ NOTREACHED();
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/output_surface.h b/chromium/components/viz/service/display/output_surface.h
index 5fdee5686e5..b36ceaa21d0 100644
--- a/chromium/components/viz/service/display/output_surface.h
+++ b/chromium/components/viz/service/display/output_surface.h
@@ -23,6 +23,8 @@
#include "gpu/command_buffer/common/texture_in_use_response.h"
#include "gpu/ipc/common/surface_handle.h"
#include "gpu/ipc/gpu_task_scheduler_helper.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "third_party/skia/include/core/SkMatrix44.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/overlay_transform.h"
@@ -30,6 +32,9 @@
#include "ui/latency/latency_info.h"
namespace gfx {
+namespace mojom {
+class DelegatedInkPointRenderer;
+} // namespace mojom
class ColorSpace;
class Rect;
class Size;
@@ -277,6 +282,12 @@ class VIZ_SERVICE_EXPORT OutputSurface {
// Notifies the OutputSurface of rate of content updates in frames per second.
virtual void SetFrameRate(float frame_rate) {}
+ // Sends the pending delegated ink renderer receiver to GPU Main to allow the
+ // browser process to send points directly there.
+ virtual void InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver);
+
protected:
struct OutputSurface::Capabilities capabilities_;
scoped_refptr<ContextProvider> context_provider_;
diff --git a/chromium/components/viz/service/display/output_surface_client.h b/chromium/components/viz/service/display/output_surface_client.h
index 2e6107a7aaa..3aa54a8e1d1 100644
--- a/chromium/components/viz/service/display/output_surface_client.h
+++ b/chromium/components/viz/service/display/output_surface_client.h
@@ -9,13 +9,13 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/texture_in_use_response.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/latency/latency_info.h"
namespace gfx {
@@ -31,7 +31,8 @@ class VIZ_SERVICE_EXPORT OutputSurfaceClient {
// A notification that the swap of the backbuffer to the hardware is complete
// and is now visible to the user, along with timing information on when the
// swapping of the backbuffer started and completed.
- virtual void DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings) = 0;
+ virtual void DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings,
+ gfx::GpuFenceHandle release_fence) = 0;
// For surfaceless/ozone implementations to create damage for the next frame.
virtual void SetNeedsRedrawRect(const gfx::Rect& damage_rect) = 0;
diff --git a/chromium/components/viz/service/display/output_surface_frame.h b/chromium/components/viz/service/display/output_surface_frame.h
index ae73f037e6f..3c6bc2f22fa 100644
--- a/chromium/components/viz/service/display/output_surface_frame.h
+++ b/chromium/components/viz/service/display/output_surface_frame.h
@@ -9,8 +9,8 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/viz/service/viz_service_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/delegated_ink_metadata.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -32,7 +32,7 @@ class VIZ_SERVICE_EXPORT OutputSurfaceFrame {
// Providing both |sub_buffer_rect| and |content_bounds| is not supported;
// if neither is present, regular swap is used.
// Optional rect for partial or empty swap.
- base::Optional<gfx::Rect> sub_buffer_rect;
+ absl::optional<gfx::Rect> sub_buffer_rect;
// Optional content area for SwapWithBounds. Rectangles may overlap.
std::vector<gfx::Rect> content_bounds;
std::vector<ui::LatencyInfo> latency_info;
diff --git a/chromium/components/viz/service/display/overlay_ca_unittest.cc b/chromium/components/viz/service/display/overlay_ca_unittest.cc
index e5219451972..000715f3476 100644
--- a/chromium/components/viz/service/display/overlay_ca_unittest.cc
+++ b/chromium/components/viz/service/display/overlay_ca_unittest.cc
@@ -115,11 +115,9 @@ static ResourceId CreateResourceInLayerTree(
auto resource = TransferableResource::MakeGL(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
size, is_overlay_candidate);
- auto release_callback = SingleReleaseCallback::Create(
- base::BindRepeating([](const gpu::SyncToken&, bool) {}));
- ResourceId resource_id = child_resource_provider->ImportResource(
- resource, std::move(release_callback));
+ ResourceId resource_id =
+ child_resource_provider->ImportResource(resource, base::DoNothing());
return resource_id;
}
@@ -132,7 +130,8 @@ ResourceId CreateResource(DisplayResourceProvider* parent_resource_provider,
ResourceId resource_id = CreateResourceInLayerTree(
child_resource_provider, size, is_overlay_candidate);
- int child_id = parent_resource_provider->CreateChild(base::DoNothing());
+ int child_id =
+ parent_resource_provider->CreateChild(base::DoNothing(), SurfaceId());
// Transfer resource to the parent.
std::vector<ResourceId> resource_ids_to_transfer;
@@ -311,7 +310,6 @@ TEST_F(CALayerOverlayTest, AllowContainingClip) {
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
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::Rect damage_rect;
@@ -337,7 +335,6 @@ TEST_F(CALayerOverlayTest, NontrivialClip) {
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
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::Rect damage_rect;
@@ -355,7 +352,6 @@ TEST_F(CALayerOverlayTest, NontrivialClip) {
&damage_rect_, &content_bounds_);
EXPECT_EQ(gfx::Rect(), damage_rect);
EXPECT_EQ(1U, ca_layer_list.size());
- EXPECT_TRUE(ca_layer_list.back().shared_state->is_clipped);
EXPECT_EQ(gfx::RectF(64, 64, 128, 128),
ca_layer_list.back().shared_state->clip_rect);
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
@@ -411,6 +407,94 @@ TEST_F(CALayerOverlayTest, SkipNonVisible) {
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
}
+TEST_F(CALayerOverlayTest, YUVDrawQuadOverlay) {
+ const gfx::Size y_size(640, 480);
+ const gfx::Size uv_size(320, 240);
+ bool is_overlay_candidate = true;
+ ResourceId y_resource_id =
+ CreateResource(resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), y_size, is_overlay_candidate);
+
+ ResourceId u_resource_id =
+ CreateResource(resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), uv_size, is_overlay_candidate);
+
+ ResourceId v_resource_id =
+ CreateResource(resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), uv_size, is_overlay_candidate);
+
+ ResourceId uv_resource_id =
+ CreateResource(resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), uv_size, is_overlay_candidate);
+
+ // NV12 frames should be promoted to overlays.
+ {
+ auto pass = CreateRenderPass();
+ auto* yuv_quad = pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
+ yuv_quad->SetNew(pass->shared_quad_state_list.back(), gfx::Rect(y_size),
+ gfx::Rect(y_size),
+ /*needs_blending=*/false,
+ /*ya_texcoord_rect=*/gfx::RectF(0, 0, 640, 480),
+ /*uv_texcoord_rect=*/gfx::RectF(0, 0, 320, 240), y_size,
+ uv_size, y_resource_id, uv_resource_id, uv_resource_id,
+ kInvalidResourceId, gfx::ColorSpace::CreateREC709(),
+ /*offset=*/0.0f,
+ /*multiplier=*/1.0f,
+ /*bits_per_channel=*/8);
+
+ gfx::Rect damage_rect;
+ CALayerOverlayList ca_layer_list;
+ OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
+ OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
+ AggregatedRenderPassList pass_list;
+ pass_list.push_back(std::move(pass));
+ SurfaceDamageRectList surface_damage_rect_list;
+
+ overlay_processor_->ProcessForOverlays(
+ resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+ render_pass_filters, render_pass_backdrop_filters,
+ std::move(surface_damage_rect_list), nullptr, &ca_layer_list,
+ &damage_rect_, &content_bounds_);
+ EXPECT_EQ(gfx::Rect(), damage_rect);
+ EXPECT_EQ(1U, ca_layer_list.size());
+ }
+
+ // If seprate Y, U, and V resources are specified, then we cannot represent
+ // them as overlays. Only Y and U==V resources are supported.
+ // https://crbug.com/1216345
+ {
+ auto pass = CreateRenderPass();
+ auto* yuv_quad = pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
+ yuv_quad->SetNew(pass->shared_quad_state_list.back(), gfx::Rect(y_size),
+ gfx::Rect(y_size),
+ /*needs_blending=*/false,
+ /*ya_texcoord_rect=*/gfx::RectF(0, 0, 640, 480),
+ /*uv_texcoord_rect=*/gfx::RectF(0, 0, 320, 240), y_size,
+ uv_size, y_resource_id, u_resource_id, v_resource_id,
+ kInvalidResourceId, gfx::ColorSpace::CreateREC709(),
+ /*offset=*/0.0f,
+ /*multiplier=*/1.0f,
+ /*bits_per_channel=*/8);
+
+ gfx::Rect damage_rect;
+ CALayerOverlayList ca_layer_list;
+ OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
+ OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
+ AggregatedRenderPassList pass_list;
+ pass_list.push_back(std::move(pass));
+ SurfaceDamageRectList surface_damage_rect_list;
+
+ overlay_processor_->ProcessForOverlays(
+ resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+ render_pass_filters, render_pass_backdrop_filters,
+ std::move(surface_damage_rect_list), nullptr, &ca_layer_list,
+ &damage_rect_, &content_bounds_);
+ EXPECT_EQ(gfx::Rect(), damage_rect);
+ EXPECT_EQ(0U, ca_layer_list.size());
+ EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
+ }
+}
+
class CALayerOverlayRPDQTest : public CALayerOverlayTest {
protected:
void SetUp() override {
diff --git a/chromium/components/viz/service/display/overlay_candidate.cc b/chromium/components/viz/service/display/overlay_candidate.cc
index 49d138812fc..0f0d179e559 100644
--- a/chromium/components/viz/service/display/overlay_candidate.cc
+++ b/chromium/components/viz/service/display/overlay_candidate.cc
@@ -311,7 +311,6 @@ bool OverlayCandidate::FromDrawQuadResource(
transform.TransformRect(&candidate->display_rect);
candidate->clip_rect = sqs->clip_rect;
- candidate->is_clipped = sqs->is_clipped;
candidate->is_opaque =
!quad->ShouldDrawWithBlendingForReasonOtherThanMaskFilter();
candidate->has_mask_filter = !sqs->mask_filter_info.IsEmpty();
@@ -415,7 +414,7 @@ void OverlayCandidate::HandleClipAndSubsampling(
// the Intel DRM driver. This should not be used in cases where the surface
// will not always be promoted to an overlay as it will lead to shifting of
// the content when it switches between composition and overlay.
- if (!candidate->is_clipped)
+ if (!candidate->clip_rect)
return;
// Make sure it's in a format we can deal with, we only support YUV and P010.
@@ -427,20 +426,20 @@ void OverlayCandidate::HandleClipAndSubsampling(
// a single display, so we want to perform our calculations within the bounds
// of that display.
if (!primary_rect.IsEmpty())
- candidate->clip_rect.Intersect(gfx::ToNearestRect(primary_rect));
+ candidate->clip_rect->Intersect(gfx::ToNearestRect(primary_rect));
// Calculate |uv_rect| of |clip_rect| in |display_rect|
gfx::RectF uv_rect = cc::MathUtil::ScaleRectProportional(
candidate->uv_rect, candidate->display_rect,
- gfx::RectF(candidate->clip_rect));
+ gfx::RectF(*candidate->clip_rect));
// In case that |uv_rect| of candidate is not (0, 0, 1, 1)
candidate->uv_rect.Intersect(uv_rect);
// Update |display_rect| to avoid unexpected scaling and the candidate should
// not be regarded as clippped after this.
- candidate->display_rect.Intersect(gfx::RectF(candidate->clip_rect));
- candidate->is_clipped = false;
+ candidate->display_rect.Intersect(gfx::RectF(*candidate->clip_rect));
+ candidate->clip_rect.reset();
// Now correct |uv_rect| if required so that the source rect aligns on a pixel
// boundary that is a multiple of the chroma subsampling.
diff --git a/chromium/components/viz/service/display/overlay_candidate.h b/chromium/components/viz/service/display/overlay_candidate.h
index c04e71bd91d..25381ffceb7 100644
--- a/chromium/components/viz/service/display/overlay_candidate.h
+++ b/chromium/components/viz/service/display/overlay_candidate.h
@@ -95,10 +95,9 @@ class VIZ_SERVICE_EXPORT OverlayCandidate {
gfx::RectF display_rect;
// Crop within the buffer to be placed inside |display_rect|.
gfx::RectF uv_rect = gfx::RectF(0.f, 0.f, 1.f, 1.f);
- // Clip rect in the target content space after composition.
- gfx::Rect clip_rect;
- // If the quad is clipped after composition.
- bool is_clipped = false;
+ // Clip rect in the target content space after composition, or empty if the
+ // quad is not clipped.
+ absl::optional<gfx::Rect> clip_rect;
// If the quad doesn't require blending.
bool is_opaque = false;
// If the quad has a mask filter.
diff --git a/chromium/components/viz/service/display/overlay_candidate_temporal_tracker.h b/chromium/components/viz/service/display/overlay_candidate_temporal_tracker.h
index 7848d3a0e46..27d6abb57df 100644
--- a/chromium/components/viz/service/display/overlay_candidate_temporal_tracker.h
+++ b/chromium/components/viz/service/display/overlay_candidate_temporal_tracker.h
@@ -5,10 +5,7 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_CANDIDATE_TEMPORAL_TRACKER_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_CANDIDATE_TEMPORAL_TRACKER_H_
-#include <vector>
-
#include "base/macros.h"
-#include "base/time/time.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/service/viz_service_export.h"
diff --git a/chromium/components/viz/service/display/overlay_dc_unittest.cc b/chromium/components/viz/service/display/overlay_dc_unittest.cc
index 3b9ec474741..45ffe97e5a7 100644
--- a/chromium/components/viz/service/display/overlay_dc_unittest.cc
+++ b/chromium/components/viz/service/display/overlay_dc_unittest.cc
@@ -122,11 +122,9 @@ static ResourceId CreateResourceInLayerTree(
auto resource = TransferableResource::MakeGL(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
size, is_overlay_candidate);
- auto release_callback = SingleReleaseCallback::Create(
- base::BindRepeating([](const gpu::SyncToken&, bool) {}));
- ResourceId resource_id = child_resource_provider->ImportResource(
- resource, std::move(release_callback));
+ ResourceId resource_id =
+ child_resource_provider->ImportResource(resource, base::DoNothing());
return resource_id;
}
@@ -139,7 +137,8 @@ ResourceId CreateResource(DisplayResourceProvider* parent_resource_provider,
ResourceId resource_id = CreateResourceInLayerTree(
child_resource_provider, size, is_overlay_candidate);
- int child_id = parent_resource_provider->CreateChild(base::DoNothing());
+ int child_id =
+ parent_resource_provider->CreateChild(base::DoNothing(), SurfaceId());
// Transfer resource to the parent.
std::vector<ResourceId> resource_ids_to_transfer;
@@ -510,7 +509,6 @@ TEST_F(DCLayerOverlayTest, ClipRect) {
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
gfx::Rect(0, 2, 100, 100), SK_ColorWHITE);
- pass->shared_quad_state_list.back()->is_clipped = true;
pass->shared_quad_state_list.back()->clip_rect = gfx::Rect(0, 3, 100, 100);
SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
@@ -519,7 +517,6 @@ TEST_F(DCLayerOverlayTest, ClipRect) {
CreateFullscreenCandidateYUVVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
child_provider_.get(), shared_state, pass.get());
- shared_state->is_clipped = true;
// Clipped rect shouldn't be overlapped by clipped opaque quad rect.
shared_state->clip_rect = gfx::Rect(0, 0, 100, 3);
@@ -541,7 +538,6 @@ TEST_F(DCLayerOverlayTest, ClipRect) {
// Because of clip rects the overlay isn't occluded and shouldn't be an
// underlay.
EXPECT_EQ(1, dc_layer_list.back().z_order);
- EXPECT_TRUE(dc_layer_list.back().is_clipped);
EXPECT_EQ(gfx::Rect(0, 0, 100, 3), dc_layer_list.back().clip_rect);
if (i == 1) {
// The damage rect should only contain contents that aren't in the
diff --git a/chromium/components/viz/service/display/overlay_processor_android.cc b/chromium/components/viz/service/display/overlay_processor_android.cc
index cdf4ebc8315..af88d1d9d72 100644
--- a/chromium/components/viz/service/display/overlay_processor_android.cc
+++ b/chromium/components/viz/service/display/overlay_processor_android.cc
@@ -187,11 +187,6 @@ void OverlayProcessorAndroid::NotifyOverlayPromotion(
DisplayResourceProvider* resource_provider,
const CandidateList& candidates,
const QuadList& quad_list) {
- // No need to notify overlay promotion if not any resource wants promotion
- // hints.
- if (!resource_provider->DoAnyResourcesWantPromotionHints())
- return;
-
// If we don't have a processor_on_gpu_, there is nothing to send the overlay
// promotions to.
if (!processor_on_gpu_) {
@@ -212,6 +207,11 @@ void OverlayProcessorAndroid::NotifyOverlayPromotion(
promotion_hint_requestor_set.insert(id);
}
+ if (promotion_hint_requestor_set.empty()) {
+ promotion_hint_info_map_.clear();
+ return;
+ }
+
base::flat_set<gpu::Mailbox> promotion_denied;
base::flat_map<gpu::Mailbox, gfx::Rect> possible_promotions;
diff --git a/chromium/components/viz/service/display/overlay_processor_interface.h b/chromium/components/viz/service/display/overlay_processor_interface.h
index 782b3392a2a..6562476a4d8 100644
--- a/chromium/components/viz/service/display/overlay_processor_interface.h
+++ b/chromium/components/viz/service/display/overlay_processor_interface.h
@@ -140,11 +140,11 @@ class VIZ_SERVICE_EXPORT OverlayProcessorInterface {
// 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.
+ // to the absl::optional instance so the instance can be reset.
// TODO(weiliangc): Internalize the |output_surface_plane| inside the overlay
// processor.
virtual void AdjustOutputSurfaceOverlay(
- base::Optional<OutputSurfaceOverlayPlane>* output_surface_plane) = 0;
+ absl::optional<OutputSurfaceOverlayPlane>* output_surface_plane) = 0;
// Before the overlay refactor to use OverlayProcessorOnGpu, overlay
// candidates are stored inside DirectRenderer. Those overlay candidates are
diff --git a/chromium/components/viz/service/display/overlay_processor_mac.cc b/chromium/components/viz/service/display/overlay_processor_mac.cc
index 777b93cd72b..5bdbb3e2001 100644
--- a/chromium/components/viz/service/display/overlay_processor_mac.cc
+++ b/chromium/components/viz/service/display/overlay_processor_mac.cc
@@ -108,7 +108,7 @@ void OverlayProcessorMac::ProcessForOverlays(
}
void OverlayProcessorMac::AdjustOutputSurfaceOverlay(
- base::Optional<OutputSurfaceOverlayPlane>* output_surface_plane) {
+ absl::optional<OutputSurfaceOverlayPlane>* output_surface_plane) {
if (!output_surface_plane->has_value())
return;
diff --git a/chromium/components/viz/service/display/overlay_processor_mac.h b/chromium/components/viz/service/display/overlay_processor_mac.h
index d7e422852b5..35a5eec0e1e 100644
--- a/chromium/components/viz/service/display/overlay_processor_mac.h
+++ b/chromium/components/viz/service/display/overlay_processor_mac.h
@@ -60,11 +60,11 @@ class VIZ_SERVICE_EXPORT OverlayProcessorMac
// 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.
+ // to the absl::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) override;
+ absl::optional<OutputSurfaceOverlayPlane>* output_surface_plane) override;
private:
const bool enable_ca_overlay_;
diff --git a/chromium/components/viz/service/display/overlay_processor_ozone.cc b/chromium/components/viz/service/display/overlay_processor_ozone.cc
index 296a44d4702..1e7ef466c8d 100644
--- a/chromium/components/viz/service/display/overlay_processor_ozone.cc
+++ b/chromium/components/viz/service/display/overlay_processor_ozone.cc
@@ -33,8 +33,7 @@ void ConvertToOzoneOverlaySurface(
ozone_candidate->format = primary_plane.format;
ozone_candidate->display_rect = primary_plane.display_rect;
ozone_candidate->crop_rect = primary_plane.uv_rect;
- ozone_candidate->clip_rect = gfx::ToEnclosingRect(primary_plane.display_rect);
- ozone_candidate->is_clipped = false;
+ ozone_candidate->clip_rect.reset();
ozone_candidate->is_opaque = !primary_plane.enable_blending;
ozone_candidate->plane_z_order = 0;
ozone_candidate->buffer_size = primary_plane.resource_size;
@@ -48,7 +47,6 @@ void ConvertToOzoneOverlaySurface(
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->is_opaque = overlay_candidate.is_opaque;
ozone_candidate->plane_z_order = overlay_candidate.plane_z_order;
ozone_candidate->buffer_size = overlay_candidate.resource_size_in_pixels;
diff --git a/chromium/components/viz/service/display/overlay_processor_stub.h b/chromium/components/viz/service/display/overlay_processor_stub.h
index d90c9968bf2..41517974954 100644
--- a/chromium/components/viz/service/display/overlay_processor_stub.h
+++ b/chromium/components/viz/service/display/overlay_processor_stub.h
@@ -35,7 +35,7 @@ class VIZ_SERVICE_EXPORT OverlayProcessorStub
gfx::Rect* damage_rect,
std::vector<gfx::Rect>* content_bounds) final {}
void AdjustOutputSurfaceOverlay(
- base::Optional<OutputSurfaceOverlayPlane>* output_surface_plane) final {}
+ absl::optional<OutputSurfaceOverlayPlane>* output_surface_plane) final {}
void SetDisplayTransformHint(gfx::OverlayTransform transform) final {}
void SetViewportSize(const gfx::Size& size) final {}
diff --git a/chromium/components/viz/service/display/overlay_processor_surface_control.cc b/chromium/components/viz/service/display/overlay_processor_surface_control.cc
index b285cd8df4e..35d4b81ba67 100644
--- a/chromium/components/viz/service/display/overlay_processor_surface_control.cc
+++ b/chromium/components/viz/service/display/overlay_processor_surface_control.cc
@@ -66,8 +66,8 @@ void OverlayProcessorSurfaceControl::CheckOverlaySupport(
gfx::RectF orig_display_rect = candidate.display_rect;
gfx::RectF display_rect = orig_display_rect;
- if (candidate.is_clipped)
- display_rect.Intersect(gfx::RectF(candidate.clip_rect));
+ if (candidate.clip_rect)
+ display_rect.Intersect(gfx::RectF(*candidate.clip_rect));
// The framework doesn't support display rects positioned at a negative
// offset.
display_rect = ClipFromOrigin(display_rect);
@@ -92,7 +92,7 @@ void OverlayProcessorSurfaceControl::CheckOverlaySupport(
}
void OverlayProcessorSurfaceControl::AdjustOutputSurfaceOverlay(
- base::Optional<OutputSurfaceOverlayPlane>* output_surface_plane) {
+ absl::optional<OutputSurfaceOverlayPlane>* output_surface_plane) {
// For surface control, we should always have a valid |output_surface_plane|
// here.
DCHECK(output_surface_plane && output_surface_plane->has_value());
diff --git a/chromium/components/viz/service/display/overlay_processor_surface_control.h b/chromium/components/viz/service/display/overlay_processor_surface_control.h
index a265576c5cd..314bc6a3d00 100644
--- a/chromium/components/viz/service/display/overlay_processor_surface_control.h
+++ b/chromium/components/viz/service/display/overlay_processor_surface_control.h
@@ -24,7 +24,7 @@ class VIZ_SERVICE_EXPORT OverlayProcessorSurfaceControl
void SetDisplayTransformHint(gfx::OverlayTransform transform) override;
void SetViewportSize(const gfx::Size& size) override;
void AdjustOutputSurfaceOverlay(
- base::Optional<OutputSurfaceOverlayPlane>* output_surface_plane) override;
+ absl::optional<OutputSurfaceOverlayPlane>* output_surface_plane) override;
void CheckOverlaySupport(
const OverlayProcessorInterface::OutputSurfaceOverlayPlane* primary_plane,
OverlayCandidateList* candidates) override;
diff --git a/chromium/components/viz/service/display/overlay_processor_surface_control_unittest.cc b/chromium/components/viz/service/display/overlay_processor_surface_control_unittest.cc
index 9f1b80fadca..90a5c601fdb 100644
--- a/chromium/components/viz/service/display/overlay_processor_surface_control_unittest.cc
+++ b/chromium/components/viz/service/display/overlay_processor_surface_control_unittest.cc
@@ -13,8 +13,6 @@ TEST(OverlayCandidateValidatorSurfaceControlTest, NoClipOrNegativeOffset) {
OverlayCandidate candidate;
candidate.display_rect = gfx::RectF(10.f, 10.f);
candidate.uv_rect = gfx::RectF(1.f, 1.f);
- candidate.is_clipped = false;
- candidate.clip_rect = gfx::Rect(5, 5);
candidate.overlay_handled = false;
OverlayCandidateList candidates;
@@ -30,7 +28,6 @@ TEST(OverlayProcessorSurfaceControlTest, Clipped) {
OverlayCandidate candidate;
candidate.display_rect = gfx::RectF(10.f, 10.f);
candidate.uv_rect = gfx::RectF(1.f, 1.f);
- candidate.is_clipped = true;
candidate.clip_rect = gfx::Rect(2, 2, 5, 5);
candidate.overlay_handled = false;
@@ -49,8 +46,6 @@ TEST(OverlayProcessorSurfaceControlTest, NegativeOffset) {
OverlayCandidate candidate;
candidate.display_rect = gfx::RectF(-2.f, -4.f, 10.f, 10.f);
candidate.uv_rect = gfx::RectF(0.5f, 0.5f);
- candidate.is_clipped = false;
- candidate.clip_rect = gfx::Rect(5, 5);
candidate.overlay_handled = false;
OverlayCandidateList candidates;
@@ -68,7 +63,6 @@ TEST(OverlayProcessorSurfaceControlTest, ClipAndNegativeOffset) {
OverlayCandidate candidate;
candidate.display_rect = gfx::RectF(-5.0f, -5.0f, 10.0f, 10.0f);
candidate.uv_rect = gfx::RectF(0.5f, 0.5f, 0.5f, 0.5f);
- candidate.is_clipped = true;
candidate.clip_rect = gfx::Rect(5, 5);
candidate.overlay_handled = false;
@@ -113,7 +107,7 @@ TEST(OverlayProcessorSurfaceControlTest, DisplayTransformOutputSurfaceOverlay) {
OverlayProcessorInterface::OutputSurfaceOverlayPlane candidate;
candidate.display_rect = gfx::RectF(100, 200);
candidate.transform = gfx::OVERLAY_TRANSFORM_NONE;
- base::Optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>
+ absl::optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>
overlay_plane = candidate;
OverlayProcessorSurfaceControl processor;
diff --git a/chromium/components/viz/service/display/overlay_processor_using_strategy.cc b/chromium/components/viz/service/display/overlay_processor_using_strategy.cc
index a6488c695f6..d29e9f6c275 100644
--- a/chromium/components/viz/service/display/overlay_processor_using_strategy.cc
+++ b/chromium/components/viz/service/display/overlay_processor_using_strategy.cc
@@ -16,6 +16,7 @@
#include "build/chromeos_buildflags.h"
#include "components/viz/common/features.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
+#include "components/viz/service/debugger/viz_debugger.h"
#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/overlay_candidate.h"
@@ -151,6 +152,11 @@ void OverlayProcessorUsingStrategy::ProcessForOverlays(
auto* render_pass = render_passes->back().get();
bool success = false;
+ DBG_DRAW_RECT("overlay.incoming.damage", (*damage_rect));
+ for (auto&& each : surface_damage_rect_list) {
+ DBG_DRAW_RECT("overlay.surface.damage", each);
+ }
+
// 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.
@@ -176,6 +182,11 @@ void OverlayProcessorUsingStrategy::ProcessForOverlays(
NotifyOverlayPromotion(resource_provider, *candidates,
render_pass->quad_list);
+ if (!candidates->empty()) {
+ DBG_DRAW_RECT("overlay.selected.rect", (*candidates)[0].display_rect);
+ }
+ DBG_DRAW_RECT("overlay.outgoing.dmage", (*damage_rect));
+
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("viz.debug.overlay_planes"),
"Scheduled overlay planes", candidates->size());
}
@@ -191,14 +202,15 @@ gfx::Rect ComputeDamageExcludingIndex(
SurfaceDamageRectList* surface_damage_rect_list,
const gfx::Rect& existing_damage,
const gfx::Rect& display_rect,
- bool is_opaque_pure_overlay) {
+ bool is_opaque,
+ bool is_underlay) {
gfx::Rect root_damage_rect;
if (overlay_damage_index == OverlayCandidate::kInvalidDamageIndex) {
// An opaque overlay that is on top will hide any damage underneath.
// TODO(petermcneeley): This is a special case optimization which could be
// removed if we had more reliable damage.
- if (is_opaque_pure_overlay) {
+ if (is_opaque && !is_underlay) {
return gfx::SubtractRects(existing_damage, display_rect);
}
return existing_damage;
@@ -207,15 +219,26 @@ gfx::Rect ComputeDamageExcludingIndex(
gfx::Rect occluding_rect;
for (size_t i = 0; i < surface_damage_rect_list->size(); i++) {
if (overlay_damage_index != i) {
+ gfx::Rect curr_surface_damage = (*surface_damage_rect_list)[i];
+
+ // The |surface_damage_rect_list| can include damage rects coming from
+ // outside and partially outside the original |existing_damage| area. This
+ // is due to the conditional inclusion of these damage rects based on
+ // target damage in surface aggregator. So by restricting this damage to
+ // the |existing_damage| we avoid unnecessary final damage output.
+ // https://crbug.com/1197609
+ curr_surface_damage.Intersect(existing_damage);
// Only add damage back in if it is not occluded by the overlay.
- if (!occluding_rect.Contains((*surface_damage_rect_list)[i])) {
- root_damage_rect.Union((*surface_damage_rect_list)[i]);
+ if (!occluding_rect.Contains(curr_surface_damage)) {
+ root_damage_rect.Union(curr_surface_damage);
}
} else {
// |surface_damage_rect_list| is ordered such that from here on the
// |display_rect| for the overlay will act as an occluder for damage
// after.
- occluding_rect = display_rect;
+ if (is_opaque) {
+ occluding_rect = display_rect;
+ }
}
}
return root_damage_rect;
@@ -252,12 +275,11 @@ void OverlayProcessorUsingStrategy::UpdateDamageRect(
// If an overlay candidate comes from output surface, its z-order should
// be 0.
overlay_damage_rect_.Union(this_frame_overlay_rect);
- if (overlay.is_opaque) {
- is_opaque_overlay = true;
- exclude_overlay_index = overlay.overlay_damage_index;
- }
+ is_opaque_overlay = overlay.is_opaque;
+ exclude_overlay_index = overlay.overlay_damage_index;
} else {
// Underlay candidate is assumed to be opaque.
+ is_opaque_overlay = true;
is_underlay = true;
exclude_overlay_index = overlay.overlay_damage_index;
}
@@ -272,7 +294,7 @@ void OverlayProcessorUsingStrategy::UpdateDamageRect(
// Removes all damage from this overlay and occluded surface damages.
*damage_rect = ComputeDamageExcludingIndex(
exclude_overlay_index, surface_damage_rect_list, *damage_rect,
- this_frame_overlay_rect, is_opaque_overlay && !is_underlay);
+ this_frame_overlay_rect, is_opaque_overlay, is_underlay);
// Drawing on the overlay_rect usually occurs on a different plane, but we
// still need to damage the overlay_rect when certain changes occur from one
@@ -287,7 +309,7 @@ void OverlayProcessorUsingStrategy::UpdateDamageRect(
// black transparent hole is made for the underlay to show through
// but its possible that the damage for this quad is less than the
// complete size of the underlay. https://crbug.com/1130733
- if (!is_opaque_overlay) {
+ if (is_underlay) {
damage_rect->Union(this_frame_overlay_rect);
}
}
@@ -298,7 +320,7 @@ void OverlayProcessorUsingStrategy::UpdateDamageRect(
}
void OverlayProcessorUsingStrategy::AdjustOutputSurfaceOverlay(
- base::Optional<OutputSurfaceOverlayPlane>* output_surface_plane) {
+ absl::optional<OutputSurfaceOverlayPlane>* output_surface_plane) {
if (!output_surface_plane || !output_surface_plane->has_value())
return;
diff --git a/chromium/components/viz/service/display/overlay_processor_using_strategy.h b/chromium/components/viz/service/display/overlay_processor_using_strategy.h
index 9ed5151ceb1..42fd0b4cde2 100644
--- a/chromium/components/viz/service/display/overlay_processor_using_strategy.h
+++ b/chromium/components/viz/service/display/overlay_processor_using_strategy.h
@@ -145,14 +145,14 @@ class VIZ_SERVICE_EXPORT OverlayProcessorUsingStrategy
gfx::Rect* damage_rect,
std::vector<gfx::Rect>* content_bounds) final;
- // This function takes a pointer to the base::Optional instance so the
+ // This function takes a pointer to the absl::optional instance so the
// instance can be reset. When overlay strategy covers the entire output
// surface, we no longer need the output surface as a separate overlay. This
// is also used by SurfaceControl to adjust rotation.
// TODO(weiliangc): Internalize the |output_surface_plane| inside the overlay
// processor.
void AdjustOutputSurfaceOverlay(
- base::Optional<OutputSurfaceOverlayPlane>* output_surface_plane) override;
+ absl::optional<OutputSurfaceOverlayPlane>* output_surface_plane) override;
OverlayProcessorUsingStrategy();
diff --git a/chromium/components/viz/service/display/overlay_processor_win.h b/chromium/components/viz/service/display/overlay_processor_win.h
index b23e9f1c97e..67d0dcaf062 100644
--- a/chromium/components/viz/service/display/overlay_processor_win.h
+++ b/chromium/components/viz/service/display/overlay_processor_win.h
@@ -46,7 +46,7 @@ class VIZ_SERVICE_EXPORT OverlayProcessorWin
// Set |is_video_capture_enabled_|.
void SetIsVideoCaptureEnabled(bool enabled) override;
- void AdjustOutputSurfaceOverlay(base::Optional<OutputSurfaceOverlayPlane>*
+ void AdjustOutputSurfaceOverlay(absl::optional<OutputSurfaceOverlayPlane>*
output_surface_plane) override {}
// Attempt to replace quads from the specified root render pass with overlays
diff --git a/chromium/components/viz/service/display/overlay_unittest.cc b/chromium/components/viz/service/display/overlay_unittest.cc
index 1f7b4e35efb..fff88532832 100644
--- a/chromium/components/viz/service/display/overlay_unittest.cc
+++ b/chromium/components/viz/service/display/overlay_unittest.cc
@@ -45,6 +45,7 @@
#include "gpu/config/gpu_finch_features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size.h"
#include "ui/latency/latency_info.h"
@@ -167,8 +168,7 @@ class DefaultOverlayProcessor : public TestOverlayProcessor {
kAbsoluteError) {
EXPECT_FLOAT_RECT_EQ(BoundingRect(kUVTopLeft, kUVBottomRight),
candidate.uv_rect);
- if (!candidate.clip_rect.IsEmpty()) {
- EXPECT_EQ(true, candidate.is_clipped);
+ if (candidate.clip_rect) {
EXPECT_EQ(kOverlayClipRect, candidate.clip_rect);
}
candidate.overlay_handled = true;
@@ -361,11 +361,9 @@ static ResourceId CreateResourceInLayerTree(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
size, is_overlay_candidate);
resource.format = resource_format;
- auto release_callback = SingleReleaseCallback::Create(
- base::BindRepeating([](const gpu::SyncToken&, bool) {}));
- ResourceId resource_id = child_resource_provider->ImportResource(
- resource, std::move(release_callback));
+ ResourceId resource_id =
+ child_resource_provider->ImportResource(resource, base::DoNothing());
return resource_id;
}
@@ -387,7 +385,8 @@ ResourceId CreateResource(DisplayResourceProvider* parent_resource_provider,
ResourceId resource_id = CreateResourceInLayerTree(
child_resource_provider, size, is_overlay_candidate, resource_format);
- int child_id = parent_resource_provider->CreateChild(base::DoNothing());
+ int child_id =
+ parent_resource_provider->CreateChild(base::DoNothing(), SurfaceId());
// Transfer resource to the parent.
std::vector<ResourceId> resource_ids_to_transfer;
@@ -1053,6 +1052,69 @@ TEST_F(SingleOverlayOnTopTest, OpaqueOverlayDamageSubtract) {
}
}
+TEST_F(SingleOverlayOnTopTest, NonOpaquePureOverlayNonOccludingDamage) {
+ // This tests a specific damage optimization where a pure overlay (aka not an
+ // underlay) which is non opaque removes the damage associated with the
+ // overlay quad but occludes no other surface damage. This is in contrast to
+ // opaque overlays which can occlude damage beneath them.
+ constexpr int kCandidateSmall = 64;
+ const gfx::Rect kOverlayDisplayRect = {10, 10, kCandidateSmall,
+ kCandidateSmall};
+ const gfx::Rect kInFrontDamage = {0, 0, 16, 16};
+ const gfx::Rect kBehindOverlayDamage = {10, 10, 32, 32};
+
+ const gfx::Rect kExpectedDamage[] = {
+ kInFrontDamage, kInFrontDamage,
+ gfx::UnionRects(kInFrontDamage, kBehindOverlayDamage)};
+
+ AddExpectedRectToOverlayProcessor(gfx::RectF(kOverlayDisplayRect));
+ for (size_t i = 0; i < base::size(kExpectedDamage); ++i) {
+ SCOPED_TRACE(i);
+
+ auto pass = CreateRenderPass();
+ SharedQuadState* damaged_shared_quad_state =
+ pass->shared_quad_state_list.AllocateAndCopyFrom(
+ pass->shared_quad_state_list.back());
+ damaged_shared_quad_state->no_damage = false;
+
+ // Create surface damages corresponding to the in front damage, the overlay
+ // damage, and finally the behind overlay damage.
+ SurfaceDamageRectList surface_damage_rect_list;
+ surface_damage_rect_list.push_back(kInFrontDamage);
+ surface_damage_rect_list.push_back(kOverlayDisplayRect);
+ damaged_shared_quad_state->overlay_damage_index = 1;
+ surface_damage_rect_list.push_back(kBehindOverlayDamage);
+
+ auto* quad = CreateCandidateQuadAt(
+ resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), damaged_shared_quad_state, pass.get(),
+ kOverlayDisplayRect);
+
+ // On the last iteration we test non opaque overlays.
+ quad->needs_blending = i == 2;
+
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get());
+
+ // Check for potential candidates.
+ OverlayCandidateList candidate_list;
+ OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
+ OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
+ AggregatedRenderPassList pass_list;
+
+ pass_list.push_back(std::move(pass));
+ damage_rect_ = kOverlayRect;
+
+ overlay_processor_->ProcessForOverlays(
+ resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+ render_pass_filters, render_pass_backdrop_filters,
+ std::move(surface_damage_rect_list), nullptr, &candidate_list,
+ &damage_rect_, &content_bounds_);
+ LOG(ERROR) << "iter=" << i << " damage =" << damage_rect_.ToString();
+ EXPECT_RECT_EQ(damage_rect_, kExpectedDamage[i]);
+ }
+}
+
TEST_F(SingleOverlayOnTopTest, DamageRect) {
auto pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
@@ -1092,6 +1154,49 @@ TEST_F(SingleOverlayOnTopTest, DamageRect) {
EXPECT_TRUE(damage_rect_.IsEmpty());
}
+TEST_F(SingleOverlayOnTopTest, DamageWithMutipleSurfaceDamage) {
+ // This test makes sure that damage is not unnecessarily expanded when there
+ // is |SurfaceDamageRectList| that is outside the original damage bounds. See
+ // https://crbug.com/1197609 for context.
+ auto pass = CreateRenderPass();
+ damage_rect_ = kOverlayTopLeftRect;
+ AddExpectedRectToOverlayProcessor(gfx::RectF(kOverlayTopLeftRect));
+ SurfaceDamageRectList surface_damage_rect_list;
+
+ SharedQuadState* default_damaged_shared_quad_state =
+ pass->shared_quad_state_list.AllocateAndCopyFrom(
+ pass->shared_quad_state_list.back());
+
+ auto* sqs = pass->shared_quad_state_list.front();
+ surface_damage_rect_list.emplace_back(damage_rect_);
+ // This line adds the unnecessarily damage.
+ surface_damage_rect_list.emplace_back(kOverlayRect);
+ sqs->overlay_damage_index = 0;
+
+ auto* quad = CreateCandidateQuadAt(
+ resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), sqs, pass.get(), kOverlayTopLeftRect);
+ quad->needs_blending = false;
+ // Add something behind it.
+ CreateFullscreenOpaqueQuad(resource_provider_.get(),
+ default_damaged_shared_quad_state, pass.get());
+
+ // Check for potential candidates.
+ OverlayCandidateList candidate_list;
+
+ OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
+ OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
+ AggregatedRenderPassList 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,
+ std::move(surface_damage_rect_list), nullptr, &candidate_list,
+ &damage_rect_, &content_bounds_);
+ EXPECT_TRUE(damage_rect_.IsEmpty());
+}
+
TEST_F(SingleOverlayOnTopTest, NoCandidates) {
auto pass = CreateRenderPass();
CreateFullscreenOpaqueQuad(resource_provider_.get(),
@@ -1370,7 +1475,6 @@ TEST_F(SingleOverlayOnTopTest, AllowClipped) {
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
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 = kOverlayClipRect;
OverlayCandidateList candidate_list;
@@ -3410,10 +3514,12 @@ class GLRendererWithOverlaysTest : public testing::Test {
}
void SwapBuffers() {
renderer_->SwapBuffers({});
- renderer_->SwapBuffersComplete();
+ renderer_->SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
}
void SwapBuffersWithoutComplete() { renderer_->SwapBuffers({}); }
- void SwapBuffersComplete() { renderer_->SwapBuffersComplete(); }
+ void SwapBuffersComplete() {
+ renderer_->SwapBuffersComplete(/*release_fence=*/gfx::GpuFenceHandle());
+ }
void ReturnResourceInUseQuery(ResourceId id) {
DisplayResourceProviderGL::ScopedReadLockGL lock(resource_provider_.get(),
id);
@@ -4229,10 +4335,10 @@ void AddQuad(gfx::Rect quad_rect,
SharedQuadState* quad_state = render_pass->CreateAndAppendSharedQuadState();
quad_state->SetAll(
- /*quad_layer_rect=*/quad_to_target_transform, quad_rect,
- /*visible_quad_layer_rect=*/quad_rect,
- /*mask_filter_info=*/gfx::MaskFilterInfo(), /*clip_rect=*/gfx::Rect(),
- /*is_clipped=*/false,
+ /*quad_to_target_transform=*/quad_to_target_transform, quad_rect,
+ /*visible_layer_rect=*/quad_rect,
+ /*mask_filter_info=*/gfx::MaskFilterInfo(),
+ /*clip_rect=*/absl::nullopt,
/*are contents opaque=*/true,
/*opacity=*/1.f,
/*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
@@ -4367,7 +4473,6 @@ TEST_F(SingleOverlayOnTopTest, RequiredOverlayClippingAndSubsampling) {
child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
kVideoCandidateRect, gfx::ProtectedVideoType::kHardwareProtected,
YUV_420_BIPLANAR);
- pass->shared_quad_state_list.back()->is_clipped = true;
pass->shared_quad_state_list.back()->clip_rect = kOverlayClipRect;
SurfaceDamageRectList surface_damage_rect_list;
SkMatrix44 default_color = GetIdentityColorMatrix();
@@ -4387,7 +4492,7 @@ TEST_F(SingleOverlayOnTopTest, RequiredOverlayClippingAndSubsampling) {
candidate.uv_rect, candidate.resource_size_in_pixels.width(),
candidate.resource_size_in_pixels.height())));
EXPECT_TRUE(candidate.requires_overlay);
- EXPECT_FALSE(candidate.is_clipped);
+ EXPECT_FALSE(candidate.clip_rect);
EXPECT_EQ(gfx::ToRoundedRect(candidate.display_rect), kOverlayClipRect);
}
@@ -4401,7 +4506,6 @@ TEST_F(SingleOverlayOnTopTest,
child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
kVideoCandidateRect, gfx::ProtectedVideoType::kHardwareProtected,
YUV_420_BIPLANAR);
- pass->shared_quad_state_list.back()->is_clipped = true;
pass->shared_quad_state_list.back()->clip_rect = kOverlayClipRect;
SurfaceDamageRectList surface_damage_rect_list;
SkMatrix44 default_color = GetIdentityColorMatrix();
@@ -4423,7 +4527,7 @@ TEST_F(SingleOverlayOnTopTest,
candidate.uv_rect, candidate.resource_size_in_pixels.width(),
candidate.resource_size_in_pixels.height())));
EXPECT_TRUE(candidate.requires_overlay);
- EXPECT_FALSE(candidate.is_clipped);
+ EXPECT_FALSE(candidate.clip_rect);
EXPECT_EQ(candidate.display_rect, primary_rect);
}
diff --git a/chromium/components/viz/service/display/renderer_perftest.cc b/chromium/components/viz/service/display/renderer_perftest.cc
index e497ac061b1..74d698899e0 100644
--- a/chromium/components/viz/service/display/renderer_perftest.cc
+++ b/chromium/components/viz/service/display/renderer_perftest.cc
@@ -15,21 +15,16 @@
// --use_virtualized_gl_contexts=1
#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/json/json_reader.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/path_service.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 "build/build_config.h"
#include "components/viz/client/client_resource_provider.h"
#include "components/viz/common/display/renderer_settings.h"
-#include "components/viz/common/quads/render_pass_io.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/display/display.h"
@@ -48,7 +43,6 @@
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/gl/gpu_service_impl.h"
#include "components/viz/test/compositor_frame_helpers.h"
-#include "components/viz/test/paths.h"
#include "components/viz/test/test_gpu_service_holder.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
@@ -131,15 +125,13 @@ SharedQuadState* CreateTestSharedQuadState(
const gfx::MaskFilterInfo& mask_filter_info) {
const gfx::Rect layer_rect = rect;
const gfx::Rect visible_layer_rect = rect;
- const gfx::Rect clip_rect = rect;
- const bool is_clipped = false;
const bool are_contents_opaque = false;
const float opacity = 1.0f;
const SkBlendMode blend_mode = SkBlendMode::kSrcOver;
const int sorting_context_id = 0;
SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
- mask_filter_info, clip_rect, is_clipped,
+ mask_filter_info, /*clip_rect=*/absl::nullopt,
are_contents_opaque, opacity, blend_mode,
sorting_context_id);
return shared_state;
@@ -190,8 +182,8 @@ TransferableResource CreateTestTexture(
false /* is_overlay_candidate */);
gl_resource.format = RGBA_8888;
gl_resource.color_space = gfx::ColorSpace();
- auto release_callback = SingleReleaseCallback::Create(base::BindOnce(
- &DeleteSharedImage, std::move(child_context_provider), mailbox));
+ auto release_callback = base::BindOnce(
+ &DeleteSharedImage, std::move(child_context_provider), mailbox);
gl_resource.id = child_resource_provider->ImportResource(
gl_resource, std::move(release_callback));
return gl_resource;
@@ -234,35 +226,6 @@ void CreateTestTileDrawQuad(ResourceId resource_id,
nearest_neighbor, force_anti_aliasing_off);
}
-bool CompositorRenderPassListFromJSON(
- const std::string& tag,
- const std::string& site,
- uint32_t year,
- size_t frame_index,
- CompositorRenderPassList* render_pass_list) {
- base::FilePath json_path;
- if (!base::PathService::Get(Paths::DIR_TEST_DATA, &json_path))
- return false;
- std::string site_year = site + "_" + base::NumberToString(year);
- std::string filename = base::NumberToString(frame_index);
- while (filename.length() < 4)
- filename = "0" + filename;
- filename += ".json";
- json_path = json_path.Append(FILE_PATH_LITERAL("render_pass_data"))
- .AppendASCII(tag)
- .AppendASCII(site_year)
- .AppendASCII(filename);
- if (!base::PathExists(json_path))
- return false;
- std::string json_text;
- if (!base::ReadFileToString(json_path, &json_text))
- return false;
- base::Optional<base::Value> dict = base::JSONReader::Read(json_text);
- if (!dict.has_value())
- return false;
- return CompositorRenderPassListFromDict(dict.value(), render_pass_list);
-}
-
} // namespace
template <typename RendererType>
@@ -296,6 +259,7 @@ class RendererPerfTest : public VizPerfTest {
#endif
auto* gpu_service = TestGpuServiceHolder::GetInstance()->gpu_service();
+ auto* task_executor = TestGpuServiceHolder::GetInstance()->task_executor();
gpu_memory_buffer_manager_ =
std::make_unique<InProcessGpuMemoryBufferManager>(
@@ -322,7 +286,7 @@ class RendererPerfTest : public VizPerfTest {
display_controller;
if (renderer_settings_.use_skia_renderer) {
auto skia_deps = std::make_unique<SkiaOutputSurfaceDependencyImpl>(
- gpu_service, gpu::kNullSurfaceHandle);
+ gpu_service, task_executor, gpu::kNullSurfaceHandle);
display_controller =
std::make_unique<DisplayCompositorMemoryAndTaskController>(
std::move(skia_deps));
diff --git a/chromium/components/viz/service/display/renderer_pixeltest.cc b/chromium/components/viz/service/display/renderer_pixeltest.cc
index c96dd0dd9fa..d0834667b5b 100644
--- a/chromium/components/viz/service/display/renderer_pixeltest.cc
+++ b/chromium/components/viz/service/display/renderer_pixeltest.cc
@@ -114,8 +114,8 @@ ResourceId CreateGpuResource(scoped_refptr<ContextProvider> context_provider,
false /* is_overlay_candidate */);
gl_resource.format = format;
gl_resource.color_space = std::move(color_space);
- auto release_callback = SingleReleaseCallback::Create(
- base::BindOnce(&DeleteSharedImage, std::move(context_provider), mailbox));
+ auto release_callback =
+ base::BindOnce(&DeleteSharedImage, std::move(context_provider), mailbox);
return resource_provider->ImportResource(gl_resource,
std::move(release_callback));
}
@@ -149,8 +149,6 @@ SharedQuadState* CreateTestSharedQuadState(
const gfx::RRectF& rrect) {
const gfx::Rect layer_rect = rect;
const gfx::Rect visible_layer_rect = rect;
- const gfx::Rect clip_rect = rect;
- const bool is_clipped = false;
const bool are_contents_opaque = false;
const float opacity = 1.0f;
const gfx::MaskFilterInfo mask_filter_info(rrect);
@@ -158,7 +156,7 @@ SharedQuadState* CreateTestSharedQuadState(
int sorting_context_id = 0;
SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
- mask_filter_info, clip_rect, is_clipped,
+ mask_filter_info, /**clip_rect=*/absl::nullopt,
are_contents_opaque, opacity, blend_mode,
sorting_context_id);
return shared_state;
@@ -171,7 +169,6 @@ SharedQuadState* CreateTestSharedQuadStateClipped(
AggregatedRenderPass* render_pass) {
const gfx::Rect layer_rect = rect;
const gfx::Rect visible_layer_rect = clip_rect;
- const bool is_clipped = true;
const bool are_contents_opaque = false;
const float opacity = 1.0f;
const SkBlendMode blend_mode = SkBlendMode::kSrcOver;
@@ -179,8 +176,9 @@ SharedQuadState* CreateTestSharedQuadStateClipped(
SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(quad_to_target_transform, layer_rect, visible_layer_rect,
/*mask_filter_info=*/gfx::MaskFilterInfo(), clip_rect,
- is_clipped, are_contents_opaque, opacity, blend_mode,
+ are_contents_opaque, opacity, blend_mode,
sorting_context_id);
+
return shared_state;
}
@@ -266,7 +264,7 @@ void CreateTestTwoColoredTextureDrawQuad(
resource = child_resource_provider->ImportResource(
TransferableResource::MakeSoftware(shared_bitmap_id, rect.size(),
RGBA_8888),
- SingleReleaseCallback::Create(base::DoNothing()));
+ base::DoNothing());
auto span = mapping.GetMemoryAsSpan<uint32_t>(pixels.size());
std::copy(pixels.begin(), pixels.end(), span.begin());
@@ -327,7 +325,7 @@ void CreateTestTextureDrawQuad(
resource = child_resource_provider->ImportResource(
TransferableResource::MakeSoftware(shared_bitmap_id, rect.size(),
RGBA_8888),
- SingleReleaseCallback::Create(base::DoNothing()));
+ base::DoNothing());
auto span = mapping.GetMemoryAsSpan<uint32_t>(pixels.size());
std::copy(pixels.begin(), pixels.end(), span.begin());
@@ -409,22 +407,18 @@ void CreateTestYUVVideoDrawQuad_FromVideoFrame(
ResourceId resource_y = child_resource_provider->ImportResource(
resources.resources[media::VideoFrame::kYPlane],
- SingleReleaseCallback::Create(
- std::move(resources.release_callbacks[media::VideoFrame::kYPlane])));
+ std::move(resources.release_callbacks[media::VideoFrame::kYPlane]));
ResourceId resource_u = child_resource_provider->ImportResource(
resources.resources[media::VideoFrame::kUPlane],
- SingleReleaseCallback::Create(
- std::move(resources.release_callbacks[media::VideoFrame::kUPlane])));
+ std::move(resources.release_callbacks[media::VideoFrame::kUPlane]));
ResourceId resource_v = child_resource_provider->ImportResource(
resources.resources[media::VideoFrame::kVPlane],
- SingleReleaseCallback::Create(
- std::move(resources.release_callbacks[media::VideoFrame::kVPlane])));
+ std::move(resources.release_callbacks[media::VideoFrame::kVPlane]));
ResourceId resource_a = kInvalidResourceId;
if (with_alpha) {
resource_a = child_resource_provider->ImportResource(
resources.resources[media::VideoFrame::kAPlane],
- SingleReleaseCallback::Create(std::move(
- resources.release_callbacks[media::VideoFrame::kAPlane])));
+ std::move(resources.release_callbacks[media::VideoFrame::kAPlane]));
}
std::vector<ResourceId> resource_ids_to_transfer;
@@ -519,8 +513,7 @@ void CreateTestY16TextureDrawQuad_FromVideoFrame(
EXPECT_EQ(1u, resources.release_callbacks.size());
ResourceId resource_y = child_resource_provider->ImportResource(
- resources.resources[0],
- SingleReleaseCallback::Create(std::move(resources.release_callbacks[0])));
+ resources.resources[0], std::move(resources.release_callbacks[0]));
// Transfer resources to the parent, and get the resource map.
std::unordered_map<ResourceId, ResourceId, ResourceIdHasher> resource_map =
@@ -1316,7 +1309,6 @@ class IntersectingQuadPixelTest : public VizPixelTestWithParam {
trans.RotateAboutYAxis(45.0);
front_quad_state_ = CreateTestSharedQuadState(
trans, viewport_rect_, render_pass_.get(), gfx::RRectF());
- front_quad_state_->clip_rect = quad_rect_;
// Make sure they end up in a 3d sorting context.
front_quad_state_->sorting_context_id = 1;
@@ -1328,7 +1320,6 @@ class IntersectingQuadPixelTest : public VizPixelTestWithParam {
back_quad_state_ = CreateTestSharedQuadState(
trans, viewport_rect_, render_pass_.get(), gfx::RRectF());
back_quad_state_->sorting_context_id = 1;
- back_quad_state_->clip_rect = quad_rect_;
}
void AppendBackgroundAndRunTest(const cc::PixelComparator& comparator,
const base::FilePath::CharType* ref_file) {
@@ -3016,7 +3007,7 @@ class RendererPixelTestWithBackdropFilter : public VizPixelTestWithParam {
AggregatedRenderPassList pass_list_;
cc::FilterOperations backdrop_filters_;
- base::Optional<gfx::RRectF> backdrop_filter_bounds_;
+ absl::optional<gfx::RRectF> backdrop_filter_bounds_;
bool include_backdrop_mask_ = false;
gfx::Transform filter_pass_to_target_transform_;
gfx::Rect filter_pass_layer_rect_;
@@ -3144,7 +3135,7 @@ class GLRendererPixelTestWithBackdropFilter : public VizPixelTest {
AggregatedRenderPassList pass_list_;
cc::FilterOperations backdrop_filters_;
- base::Optional<gfx::RRectF> backdrop_filter_bounds_;
+ absl::optional<gfx::RRectF> backdrop_filter_bounds_;
float backdrop_filter_quality_ = 1.0f;
bool intersects_damage_under_ = true;
gfx::Transform filter_pass_to_target_transform_;
diff --git a/chromium/components/viz/service/display/shared_bitmap_manager.h b/chromium/components/viz/service/display/shared_bitmap_manager.h
index 62375e0cfd1..5fa0da1a7d5 100644
--- a/chromium/components/viz/service/display/shared_bitmap_manager.h
+++ b/chromium/components/viz/service/display/shared_bitmap_manager.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/shared_memory_mapping.h"
#include "components/viz/common/resources/shared_bitmap.h"
+#include "third_party/skia/include/core/SkBitmap.h"
namespace gfx {
class Size;
@@ -19,8 +20,8 @@ namespace viz {
class SharedBitmapManager {
public:
- SharedBitmapManager() {}
- virtual ~SharedBitmapManager() {}
+ SharedBitmapManager() = default;
+ virtual ~SharedBitmapManager() = default;
// Used in the display compositor to find the bitmap associated with an id.
virtual std::unique_ptr<SharedBitmap> GetSharedBitmapFromId(
@@ -29,6 +30,9 @@ class SharedBitmapManager {
const SharedBitmapId& id) = 0;
virtual base::UnguessableToken GetSharedBitmapTracingGUIDFromId(
const SharedBitmapId& id) = 0;
+ // Used for locally allocated bitmaps that are not in shared memory.
+ virtual bool LocalAllocatedSharedBitmap(SkBitmap bitmap,
+ const SharedBitmapId& id) = 0;
// Used in the display compositor to associate an id to a shm mapping.
virtual bool ChildAllocatedSharedBitmap(
base::ReadOnlySharedMemoryMapping mapping,
diff --git a/chromium/components/viz/service/display/skia_readback_pixeltest.cc b/chromium/components/viz/service/display/skia_readback_pixeltest.cc
index ec7eba6f2f6..0ab88ecb955 100644
--- a/chromium/components/viz/service/display/skia_readback_pixeltest.cc
+++ b/chromium/components/viz/service/display/skia_readback_pixeltest.cc
@@ -46,10 +46,9 @@ SharedQuadState* CreateSharedQuadState(AggregatedRenderPass* render_pass,
const gfx::Rect& rect) {
const gfx::Rect layer_rect = rect;
const gfx::Rect visible_layer_rect = rect;
- const gfx::Rect clip_rect = rect;
SharedQuadState* shared_state = render_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(), layer_rect, visible_layer_rect,
- gfx::MaskFilterInfo(), clip_rect, /*is_clipped=*/false,
+ gfx::MaskFilterInfo(), /*clip_rect=*/absl::nullopt,
/*are_contents_opaque=*/false, /*opacity=*/1.0f,
SkBlendMode::kSrcOver,
/*sorting_context_id=*/0);
@@ -115,8 +114,8 @@ class SkiaReadbackPixelTest : public cc::PixelTest,
mailbox, GL_LINEAR, GL_TEXTURE_2D, sync_token, size,
/*is_overlay_candidate=*/false);
gl_resource.format = format;
- auto release_callback = SingleReleaseCallback::Create(
- base::BindOnce(&DeleteSharedImage, child_context_provider_, mailbox));
+ auto release_callback =
+ base::BindOnce(&DeleteSharedImage, child_context_provider_, mailbox);
return child_resource_provider_->ImportResource(
gl_resource, std::move(release_callback));
}
diff --git a/chromium/components/viz/service/display/skia_renderer.cc b/chromium/components/viz/service/display/skia_renderer.cc
index 75a2af2c485..56b89942819 100644
--- a/chromium/components/viz/service/display/skia_renderer.cc
+++ b/chromium/components/viz/service/display/skia_renderer.cc
@@ -12,7 +12,6 @@
#include "base/bits.h"
#include "base/command_line.h"
#include "base/logging.h"
-#include "base/optional.h"
#include "base/synchronization/waitable_event.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -46,6 +45,7 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "skia/ext/opacity_filter_canvas.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkColorFilter.h"
@@ -68,6 +68,7 @@
#include "ui/gfx/geometry/axis_transform2d.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"
#include "ui/gfx/transform_util.h"
@@ -428,7 +429,7 @@ SkYUVAInfo::Subsampling SubsamplingFromTextureSizes(gfx::Size ya_size,
} // namespace
// chrome style prevents this from going in skia_renderer.h, but since it
-// uses base::Optional, the style also requires it to have a declared ctor
+// uses absl::optional, the style also requires it to have a declared ctor
SkiaRenderer::BatchedQuadState::BatchedQuadState() = default;
// Parameters needed to draw a CompositorRenderPassDrawQuad.
@@ -460,13 +461,13 @@ struct SkiaRenderer::DrawRPDQParams {
// which will be applied using SkCanvas::clipShader in RPDQ's coord space.
sk_sp<SkShader> mask_shader = nullptr;
// Backdrop border box for the render pass, to clip backdrop-filtered content
- base::Optional<gfx::RRectF> backdrop_filter_bounds;
+ absl::optional<gfx::RRectF> backdrop_filter_bounds;
// The content space bounds that includes any filtered extents. If empty,
// the draw can be skipped.
gfx::Rect filter_bounds;
// Geometry from the bypassed RenderPassDrawQuad.
- base::Optional<BypassGeometry> bypass_geometry;
+ absl::optional<BypassGeometry> bypass_geometry;
// True when there is an |image_filter| and it's not equivalent to
// |color_filter|.
@@ -525,13 +526,13 @@ struct SkiaRenderer::DrawQuadParams {
SkSamplingOptions sampling;
// Optional restricted draw geometry, will point to a length 4 SkPoint array
// with its points in CW order matching Skia's vertex/edge expectations.
- base::Optional<SkDrawRegion> draw_region;
+ absl::optional<SkDrawRegion> draw_region;
// Optional rounded corner clip to apply. If present, it will have been
// transformed to device space and ShouldApplyRoundedCorner returns true.
- base::Optional<gfx::RRectF> rounded_corner_bounds;
+ absl::optional<gfx::RRectF> rounded_corner_bounds;
// Optional device space clip to apply. If present, it is equal to the current
// |scissor_rect_| of the renderer.
- base::Optional<gfx::Rect> scissor_rect;
+ absl::optional<gfx::Rect> scissor_rect;
SkPaint paint(sk_sp<SkColorFilter> color_filter) const {
SkPaint p;
@@ -748,22 +749,13 @@ SkiaRenderer::SkiaRenderer(const RendererSettings* settings,
SkiaRenderer::~SkiaRenderer() = default;
bool SkiaRenderer::CanPartialSwap() {
- return output_surface_->capabilities().supports_post_sub_buffer;
+ return output_surface_->capabilities().supports_post_sub_buffer;
}
void SkiaRenderer::BeginDrawingFrame() {
TRACE_EVENT0("viz", "SkiaRenderer::BeginDrawingFrame");
DCHECK(!current_frame_resource_fence_->WasSet());
-
-#if defined(OS_ANDROID)
- for (const auto& pass : *current_frame()->render_passes_in_draw_order) {
- for (auto* quad : pass->quad_list) {
- for (ResourceId resource_id : quad->resources)
- resource_provider()->InitializePromotionHintRequest(resource_id);
- }
- }
-#endif
}
void SkiaRenderer::FinishDrawingFrame() {
@@ -779,6 +771,7 @@ void SkiaRenderer::FinishDrawingFrame() {
current_frame()->output_surface_plane.value());
}
ScheduleOverlays();
+ debug_tint_modulate_count_++;
}
void SkiaRenderer::SwapBuffers(SwapFrameData swap_frame_data) {
@@ -817,7 +810,14 @@ void SkiaRenderer::SwapBuffersSkipped() {
FlushOutputSurface();
}
-void SkiaRenderer::SwapBuffersComplete() {
+void SkiaRenderer::SwapBuffersComplete(gfx::GpuFenceHandle release_fence) {
+ if (!release_fence.is_null()) {
+ // Set release fences for returning for last frame overlay resources.
+ for (auto& lock : committed_overlay_locks_) {
+ lock.SetReleaseFence(release_fence.Clone());
+ }
+ }
+
// Right now, only macOS needs to return mailboxes of released overlays, so
// we should not release |committed_overlay_locks_| here. The resources in it
// will be released by DidReceiveReleasedOverlays() later.
@@ -827,11 +827,31 @@ void SkiaRenderer::SwapBuffersComplete() {
}
#endif // defined(OS_APPLE)
+ // Find all locks that have a read-lock fence associated with them.
+ // If we have a release fence, it's not safe to release them here.
+ // Release them later in BuffersPresented.
+ auto& read_lock_release_fence_overlay_locks =
+ read_lock_release_fence_overlay_locks_.emplace_back();
+ if (!release_fence.is_null()) {
+ auto read_lock_iter = std::partition(
+ committed_overlay_locks_.begin(), committed_overlay_locks_.end(),
+ [](auto& lock) { return !lock.HasReadLockFence(); });
+ read_lock_release_fence_overlay_locks.insert(
+ read_lock_release_fence_overlay_locks.end(),
+ std::make_move_iterator(read_lock_iter),
+ std::make_move_iterator(committed_overlay_locks_.end()));
+ }
+
committed_overlay_locks_.clear();
std::swap(committed_overlay_locks_, pending_overlay_locks_.front());
pending_overlay_locks_.pop_front();
}
+void SkiaRenderer::BuffersPresented() {
+ DCHECK(!read_lock_release_fence_overlay_locks_.empty());
+ read_lock_release_fence_overlay_locks_.pop_front();
+}
+
void SkiaRenderer::DidReceiveReleasedOverlays(
const std::vector<gpu::Mailbox>& released_overlays) {
// This method is only called on macOS right now.
@@ -1021,8 +1041,8 @@ void SkiaRenderer::DrawQuadInternal(const DrawQuad* quad,
}
void SkiaRenderer::PrepareCanvas(
- const base::Optional<gfx::Rect>& scissor_rect,
- const base::Optional<gfx::RRectF>& rounded_corner_bounds,
+ const absl::optional<gfx::Rect>& scissor_rect,
+ const absl::optional<gfx::RRectF>& rounded_corner_bounds,
const gfx::Transform* cdt) {
// Scissor is applied in the device space (CTM == I) and since no changes
// to the canvas persist, CTM should already be the identity
@@ -1831,7 +1851,7 @@ void SkiaRenderer::DrawPictureQuad(const PictureDrawQuad* quad,
}
SkCanvas* raster_canvas = current_canvas_;
- base::Optional<skia::OpacityFilterCanvas> opacity_canvas;
+ absl::optional<skia::OpacityFilterCanvas> opacity_canvas;
if (disable_image_filtering) {
// TODO(vmpstr): Fold this canvas into playback and have raster source
// accept a set of settings on playback that will determine which canvas to
@@ -2164,7 +2184,6 @@ void SkiaRenderer::ScheduleOverlays() {
if (current_frame()->overlay_list.empty())
return;
- auto& locks = pending_overlay_locks_.back();
std::vector<gpu::SyncToken> sync_tokens;
#if !defined(OS_WIN)
@@ -2176,6 +2195,7 @@ void SkiaRenderer::ScheduleOverlays() {
// switched over to OverlayProcessor.
// TODO(weiliangc): Remove this when CrOS and Android SurfaceControl switch
// to OverlayProcessor as well.
+ auto& locks = pending_overlay_locks_.back();
for (auto& overlay : current_frame()->overlay_list) {
// Resources will be unlocked after the next SwapBuffers() is completed.
locks.emplace_back(resource_provider(), overlay.resource_id);
@@ -2190,6 +2210,7 @@ void SkiaRenderer::ScheduleOverlays() {
DCHECK(!overlay.mailbox.IsZero());
}
#elif defined(OS_WIN)
+ auto& locks = pending_overlay_locks_.back();
for (auto& dc_layer_overlay : current_frame()->overlay_list) {
for (size_t i = 0; i < DCLayerOverlay::kNumResources; ++i) {
ResourceId resource_id = dc_layer_overlay.resources[i];
@@ -2210,6 +2231,7 @@ void SkiaRenderer::ScheduleOverlays() {
DCHECK(!dc_layer_overlay.mailbox[0].IsZero());
}
#elif defined(OS_APPLE)
+ auto& locks = pending_overlay_locks_.back();
for (CALayerOverlay& ca_layer_overlay : current_frame()->overlay_list) {
if (ca_layer_overlay.rpdq) {
PrepareRenderPassOverlay(&ca_layer_overlay);
@@ -2244,6 +2266,7 @@ void SkiaRenderer::ScheduleOverlays() {
return;
}
// Only Wayland uses this code path.
+ auto& locks = pending_overlay_locks_.back();
for (auto& overlay : current_frame()->overlay_list) {
// Resources will be unlocked after the next SwapBuffers() is completed.
locks.emplace_back(resource_provider(), overlay.resource_id);
@@ -2296,10 +2319,8 @@ sk_sp<SkColorFilter> SkiaRenderer::GetColorSpaceConversionFilter(
const char* hdr = R"(
uniform half offset;
uniform half multiplier;
-uniform shader child;
-half4 main() {
- half4 color = sample(child);
+half4 main(half4 color) {
// un-premultiply alpha
if (color.a > 0)
color.rgb /= color.a;
@@ -2316,8 +2337,9 @@ half4 main() {
std::string shader = hdr + transform->GetSkShaderSource() + ftr;
- effect = SkRuntimeEffect::Make(SkString(shader.c_str(), shader.size()),
- /*options=*/{})
+ effect = SkRuntimeEffect::MakeForColorFilter(
+ SkString(shader.c_str(), shader.size()),
+ /*options=*/{})
.effect;
DCHECK(effect);
}
@@ -2327,36 +2349,51 @@ half4 main() {
input.multiplier = resource_multiplier;
sk_sp<SkData> data = SkData::MakeWithCopy(&input, sizeof(input));
- sk_sp<SkColorFilter> child = nullptr; // = default input color
- return effect->makeColorFilter(std::move(data), &child, 1);
+ return effect->makeColorFilter(std::move(data));
}
+namespace {
+SkColorMatrix ToColorMatrix(const SkMatrix44& mat) {
+ std::array<float, 20> values;
+ values.fill(0.0f);
+ for (uint32_t r = 0; r < 4; r++) {
+ for (uint32_t c = 0; c < 4; c++) {
+ values[r * 5 + c] = mat.getFloat(r, c);
+ }
+ }
+ SkColorMatrix mat_out;
+ mat_out.setRowMajor(values.data());
+ return mat_out;
+}
+} // namespace
+
sk_sp<SkColorFilter> SkiaRenderer::GetContentColorFilter() {
sk_sp<SkColorFilter> color_transform = nullptr;
if (current_canvas_ == root_canvas_ &&
!output_surface_->color_matrix().isIdentity()) {
- std::array<float, 20> values;
- values.fill(0.0f);
- for (uint32_t r = 0; r < 4; r++) {
- for (uint32_t c = 0; c < 4; c++) {
- values[r * 5 + c] = output_surface_->color_matrix().getFloat(r, c);
- }
- }
- color_transform = SkColorFilters::Matrix(values.data());
+ color_transform =
+ SkColorFilters::Matrix(ToColorMatrix(output_surface_->color_matrix()));
}
sk_sp<SkColorFilter> tint_transform = nullptr;
if (current_canvas_ == root_canvas_ &&
debug_settings_->tint_composited_content) {
- std::array<float, 20> values;
- values.fill(0.0f);
- auto tint = cc::DebugColors::TintCompositedContentColorTransformMatrix();
- for (int r = 0; r < 4; r++) {
- for (int c = 0; c < 4; c++) {
- values[r * 5 + c] = tint[c * 4 + r];
+ if (debug_settings_->tint_composited_content_modulate) {
+ // Integer counter causes modulation through rgb dimming variations.
+ std::array<float, 3> rgb;
+ uint32_t ci = debug_tint_modulate_count_ % 7u;
+ for (int rc = 0; rc < 3; rc++) {
+ rgb[rc] = (ci & (1u << rc)) ? 0.7f : 1.0f;
}
+ SkColorMatrix color_mat;
+ color_mat.setScale(rgb[0], rgb[1], rgb[2]);
+ tint_transform = SkColorFilters::Matrix(color_mat);
+ } else {
+ SkMatrix44 mat44;
+ mat44.setColMajorf(
+ cc::DebugColors::TintCompositedContentColorTransformMatrix().data());
+ tint_transform = SkColorFilters::Matrix(ToColorMatrix(mat44));
}
- tint_transform = SkColorFilters::Matrix(values.data());
}
if (color_transform) {
@@ -2422,10 +2459,8 @@ SkiaRenderer::DrawRPDQParams SkiaRenderer::CalculateRPDQParams(
filters->MapRect(rpdq_params.filter_bounds, local_matrix);
// If after applying the filter we would be clipped out, skip the draw.
- gfx::Rect clip_rect = quad->shared_quad_state->clip_rect;
- if (clip_rect.IsEmpty()) {
- clip_rect = current_draw_rect_;
- }
+ gfx::Rect clip_rect =
+ quad->shared_quad_state->clip_rect.value_or(current_draw_rect_);
gfx::Transform transform =
quad->shared_quad_state->quad_to_target_transform;
transform.FlattenTo2d();
@@ -2495,7 +2530,7 @@ SkiaRenderer::DrawRPDQParams SkiaRenderer::CalculateRPDQParams(
// Determine if the backdrop filter has its own clip (which only needs to be
// checked when we have a backdrop filter to apply)
if (rpdq_params.backdrop_filter) {
- const base::Optional<gfx::RRectF> backdrop_filter_bounds =
+ const absl::optional<gfx::RRectF> backdrop_filter_bounds =
BackdropFilterBoundsForPass(quad->render_pass_id);
if (backdrop_filter_bounds) {
// The backdrop filters effect will be cropped by these bounds. If the
@@ -2745,22 +2780,34 @@ void SkiaRenderer::PrepareRenderPassOverlay(CALayerOverlay* overlay) {
auto* shared_quad_state =
const_cast<SharedQuadState*>(quad->shared_quad_state);
- gfx::Transform quad_to_target_transform_inverse(
- gfx::Transform::kSkipInitialization);
- if (shared_quad_state->is_clipped ||
+ absl::optional<gfx::Transform> quad_to_target_transform_inverse;
+ if (shared_quad_state->clip_rect ||
!shared_quad_state->mask_filter_info.IsEmpty()) {
- bool result = shared_quad_state->quad_to_target_transform.GetInverse(
- &quad_to_target_transform_inverse);
- DCHECK(result) << "quad_to_target_transform.GetInverse() failed";
+ // We cannot handle rotation with clip rect or mask filter.
+ DCHECK(
+ shared_quad_state->quad_to_target_transform.Preserves2dAxisAlignment());
+ quad_to_target_transform_inverse.emplace(
+ gfx::Transform::kSkipInitialization);
+ // Flatten before inverting, since we're interested in how points
+ // with z=0 in local space map to the clip rect, not in how the clip
+ // rect at z=0 in device space maps to some other z in local space.
+ gfx::Transform flat_quad_to_target_transform(
+ shared_quad_state->quad_to_target_transform);
+ flat_quad_to_target_transform.FlattenTo2d();
+ bool result = flat_quad_to_target_transform.GetInverse(
+ &*quad_to_target_transform_inverse);
+ DCHECK(result) << "flat_quad_to_target_transform.GetInverse() failed";
}
// The |clip_rect| is in the device coordinate and with all transforms
// (translation, scaling, rotation, etc), so remove them.
- base::Optional<base::AutoReset<gfx::Rect>> auto_reset_clip_rect;
- if (shared_quad_state->is_clipped) {
- gfx::RectF clip_rect(shared_quad_state->clip_rect);
- quad_to_target_transform_inverse.TransformRect(&clip_rect);
- auto_reset_clip_rect.emplace(&shared_quad_state->clip_rect,
+ absl::optional<base::AutoReset<gfx::Rect>> auto_reset_clip_rect;
+ if (shared_quad_state->clip_rect) {
+ // TODO(dbaron): This operation is likely not to be valid if
+ // quad_to_target_transform_inverse.HasPerspective().
+ gfx::RectF clip_rect(*shared_quad_state->clip_rect);
+ quad_to_target_transform_inverse->TransformRect(&clip_rect);
+ auto_reset_clip_rect.emplace(&shared_quad_state->clip_rect.value(),
gfx::ToEnclosedRect(clip_rect));
}
@@ -2768,7 +2815,7 @@ void SkiaRenderer::PrepareRenderPassOverlay(CALayerOverlay* overlay) {
// (translation, scaling, rotation, etc), so remove them.
if (!shared_quad_state->mask_filter_info.IsEmpty()) {
auto result = shared_quad_state->mask_filter_info.Transform(
- quad_to_target_transform_inverse);
+ *quad_to_target_transform_inverse);
DCHECK(result) << "shared_quad_state->mask_filter_info.Transform() failed.";
}
diff --git a/chromium/components/viz/service/display/skia_renderer.h b/chromium/components/viz/service/display/skia_renderer.h
index 3f0875291b3..acb51b7efec 100644
--- a/chromium/components/viz/service/display/skia_renderer.h
+++ b/chromium/components/viz/service/display/skia_renderer.h
@@ -51,7 +51,8 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
void SwapBuffers(SwapFrameData swap_frame_data) override;
void SwapBuffersSkipped() override;
- void SwapBuffersComplete() override;
+ void SwapBuffersComplete(gfx::GpuFenceHandle release_fence) override;
+ void BuffersPresented() override;
void DidReceiveReleasedOverlays(
const std::vector<gpu::Mailbox>& released_overlays) override;
@@ -112,8 +113,8 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
// Callers should init an SkAutoCanvasRestore before calling this function.
// |scissor_rect| and |rounded_corner_bounds| should be in device space,
// i.e. same space that |cdt| will transform subsequent draws into.
- void PrepareCanvas(const base::Optional<gfx::Rect>& scissor_rect,
- const base::Optional<gfx::RRectF>& rounded_corner_bounds,
+ void PrepareCanvas(const absl::optional<gfx::Rect>& scissor_rect,
+ const absl::optional<gfx::RRectF>& rounded_corner_bounds,
const gfx::Transform* cdt);
// Further modify the canvas as needed to apply the effects represented by
// |rpdq_params|. Call Prepare[Paint|Color]OrCanvasForRPDQ when possible,
@@ -286,8 +287,8 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
// State common to all quads in a batch. Draws that require an SkPaint not
// captured by this state cannot be batched.
struct BatchedQuadState {
- base::Optional<gfx::Rect> scissor_rect;
- base::Optional<gfx::RRectF> rounded_corner_bounds;
+ absl::optional<gfx::Rect> scissor_rect;
+ absl::optional<gfx::RRectF> rounded_corner_bounds;
SkBlendMode blend_mode;
SkSamplingOptions sampling;
SkCanvas::SrcRectConstraint constraint;
@@ -311,7 +312,7 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
// the compositor thread. And the sync token will be released when the DDL
// for the current frame is replayed on the GPU thread.
// It is only used with DDL.
- base::Optional<DisplayResourceProviderSkia::LockSetForExternalUse>
+ absl::optional<DisplayResourceProviderSkia::LockSetForExternalUse>
lock_set_for_external_use_;
// Locks for overlays are pending for swapbuffers.
@@ -324,6 +325,11 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
std::vector<DisplayResourceProviderSkia::ScopedReadLockSharedImage>
committed_overlay_locks_;
+ // Locks for overlays that have release fences and read lock fences.
+ base::circular_deque<
+ std::vector<DisplayResourceProviderSkia::ScopedReadLockSharedImage>>
+ read_lock_release_fence_overlay_locks_;
+
#if defined(OS_APPLE)
class ScopedReadLockComparator {
public:
@@ -352,6 +358,7 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
color_filter_cache_;
bool UsingSkiaForDelegatedInk() const;
+ uint32_t debug_tint_modulate_count_ = 0;
DISALLOW_COPY_AND_ASSIGN(SkiaRenderer);
};
diff --git a/chromium/components/viz/service/display/software_renderer.cc b/chromium/components/viz/service/display/software_renderer.cc
index cda71d845d7..ac91841d5f4 100644
--- a/chromium/components/viz/service/display/software_renderer.cc
+++ b/chromium/components/viz/service/display/software_renderer.cc
@@ -395,7 +395,7 @@ void SoftwareRenderer::DrawPictureQuad(const PictureDrawQuad* quad) {
SkCanvas* raster_canvas = current_canvas_;
- base::Optional<skia::OpacityFilterCanvas> opacity_canvas;
+ absl::optional<skia::OpacityFilterCanvas> opacity_canvas;
if (needs_transparency || disable_image_filtering) {
// TODO(aelias): This isn't correct in all cases. We should detect these
// cases and fall back to a persistent bitmap backing
@@ -549,7 +549,8 @@ void SoftwareRenderer::DrawRenderPassQuad(
SkMatrix content_mat = SkMatrix::RectToRect(content_rect, dest_rect);
sk_sp<SkShader> shader;
- SkSamplingOptions sampling(current_paint_.getFilterQuality());
+ SkSamplingOptions sampling(cc::PaintFlags::FilterQualityToSkSamplingOptions(
+ current_paint_.getFilterQuality()));
if (!filter_image) {
shader = source_bitmap.makeShader(sampling, content_mat);
} else {
@@ -751,10 +752,10 @@ SkBitmap SoftwareRenderer::GetBackdropBitmap(
gfx::Rect SoftwareRenderer::GetBackdropBoundingBoxForRenderPassQuad(
const AggregatedRenderPassDrawQuad* quad,
const cc::FilterOperations* backdrop_filters,
- base::Optional<gfx::RRectF> backdrop_filter_bounds_input,
+ absl::optional<gfx::RRectF> backdrop_filter_bounds_input,
gfx::Transform contents_device_transform,
gfx::Transform* backdrop_filter_bounds_transform,
- base::Optional<gfx::RRectF>* backdrop_filter_bounds,
+ absl::optional<gfx::RRectF>* backdrop_filter_bounds,
gfx::Rect* unclipped_rect) const {
DCHECK(backdrop_filter_bounds_transform);
DCHECK(backdrop_filter_bounds);
@@ -794,7 +795,7 @@ sk_sp<SkShader> SoftwareRenderer::GetBackdropFilterShader(
BackdropFiltersForPass(quad->render_pass_id);
if (!ShouldApplyBackdropFilters(backdrop_filters, quad))
return nullptr;
- base::Optional<gfx::RRectF> backdrop_filter_bounds_input =
+ absl::optional<gfx::RRectF> backdrop_filter_bounds_input =
BackdropFilterBoundsForPass(quad->render_pass_id);
DCHECK(!FiltersForPass(quad->render_pass_id))
<< "Filters should always be in a separate Effect node";
@@ -812,7 +813,7 @@ sk_sp<SkShader> SoftwareRenderer::GetBackdropFilterShader(
quad_rect_matrix;
contents_device_transform.FlattenTo2d();
- base::Optional<gfx::RRectF> backdrop_filter_bounds;
+ absl::optional<gfx::RRectF> backdrop_filter_bounds;
gfx::Transform backdrop_filter_bounds_transform;
gfx::Rect unclipped_rect;
gfx::Rect backdrop_rect = GetBackdropBoundingBoxForRenderPassQuad(
diff --git a/chromium/components/viz/service/display/software_renderer.h b/chromium/components/viz/service/display/software_renderer.h
index d879a3b32e8..17779847fde 100644
--- a/chromium/components/viz/service/display/software_renderer.h
+++ b/chromium/components/viz/service/display/software_renderer.h
@@ -97,10 +97,10 @@ class VIZ_SERVICE_EXPORT SoftwareRenderer : public DirectRenderer {
gfx::Rect GetBackdropBoundingBoxForRenderPassQuad(
const AggregatedRenderPassDrawQuad* quad,
const cc::FilterOperations* backdrop_filters,
- base::Optional<gfx::RRectF> backdrop_filter_bounds_input,
+ absl::optional<gfx::RRectF> backdrop_filter_bounds_input,
gfx::Transform contents_device_transform,
gfx::Transform* backdrop_filter_bounds_transform,
- base::Optional<gfx::RRectF>* backdrop_filter_bounds,
+ absl::optional<gfx::RRectF>* backdrop_filter_bounds,
gfx::Rect* unclipped_rect) const;
SkBitmap GetBackdropBitmap(const gfx::Rect& bounding_rect) const;
diff --git a/chromium/components/viz/service/display/software_renderer_unittest.cc b/chromium/components/viz/service/display/software_renderer_unittest.cc
index 3b1737919df..fd23f9f3292 100644
--- a/chromium/components/viz/service/display/software_renderer_unittest.cc
+++ b/chromium/components/viz/service/display/software_renderer_unittest.cc
@@ -94,7 +94,7 @@ class SoftwareRendererTest : public testing::Test {
// Makes a resource id that refers to the registered SharedBitmapId.
return child_resource_provider_->ImportResource(
TransferableResource::MakeSoftware(shared_bitmap_id, size, RGBA_8888),
- SingleReleaseCallback::Create(base::DoNothing()));
+ base::DoNothing());
}
std::unique_ptr<SkBitmap> DrawAndCopyOutput(AggregatedRenderPassList* list,
@@ -155,7 +155,7 @@ TEST_F(SoftwareRendererTest, SolidColorQuad) {
SharedQuadState* shared_quad_state =
root_render_pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(gfx::Transform(), outer_rect, outer_rect,
- gfx::MaskFilterInfo(), outer_rect, false, true, 1.0,
+ gfx::MaskFilterInfo(), absl::nullopt, true, 1.0,
SkBlendMode::kSrcOver, 0);
auto* inner_quad =
root_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -223,7 +223,7 @@ TEST_F(SoftwareRendererTest, TileQuad) {
SharedQuadState* shared_quad_state =
root_render_pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(gfx::Transform(), outer_rect, outer_rect,
- gfx::MaskFilterInfo(), outer_rect, false, true, 1.0,
+ gfx::MaskFilterInfo(), absl::nullopt, true, 1.0,
SkBlendMode::kSrcOver, 0);
auto* inner_quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
inner_quad->SetNew(shared_quad_state, inner_rect, inner_rect, needs_blending,
@@ -285,7 +285,7 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
SharedQuadState* shared_quad_state =
root_render_pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(gfx::Transform(), tile_rect, tile_rect,
- gfx::MaskFilterInfo(), tile_rect, false, true, 1.0,
+ gfx::MaskFilterInfo(), absl::nullopt, true, 1.0,
SkBlendMode::kSrcOver, 0);
auto* quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
quad->SetNew(shared_quad_state, tile_rect, tile_rect, needs_blending,
@@ -447,7 +447,7 @@ TEST_F(SoftwareRendererTest, ClipRoundRect) {
root_pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(gfx::Transform(), outer_rect, outer_rect,
gfx::MaskFilterInfo(), gfx::Rect(1, 1, 30, 30),
- true, true, 1.0, SkBlendMode::kSrcOver, 0);
+ true, 1.0, SkBlendMode::kSrcOver, 0);
auto* outer_quad = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
outer_quad->SetNew(shared_quad_state, outer_rect, outer_rect, SK_ColorGREEN,
false);
@@ -463,7 +463,7 @@ TEST_F(SoftwareRendererTest, ClipRoundRect) {
shared_quad_state->SetAll(
gfx::Transform(), inner_rect, inner_rect,
gfx::MaskFilterInfo(gfx::RRectF(gfx::RectF(5, 5, 10, 10), 2)),
- inner_rect, false, true, 1.0, SkBlendMode::kSrcOver, 0);
+ absl::nullopt, true, 1.0, SkBlendMode::kSrcOver, 0);
auto* inner_quad = root_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
inner_quad->SetNew(shared_quad_state, inner_rect, inner_rect, SK_ColorRED,
false);
diff --git a/chromium/components/viz/service/display/surface_aggregator.cc b/chromium/components/viz/service/display/surface_aggregator.cc
index a6b6b8b136f..bf18b592cac 100644
--- a/chromium/components/viz/service/display/surface_aggregator.cc
+++ b/chromium/components/viz/service/display/surface_aggregator.cc
@@ -184,11 +184,11 @@ SurfaceAggregator::GenerateRenderPassMap(
// Create a clip rect for an aggregated quad from the original clip rect and
// the clip rect from the surface it's on.
-base::Optional<gfx::Rect> SurfaceAggregator::CalculateClipRect(
- const base::Optional<gfx::Rect>& surface_clip,
- const base::Optional<gfx::Rect>& quad_clip,
+absl::optional<gfx::Rect> SurfaceAggregator::CalculateClipRect(
+ const absl::optional<gfx::Rect>& surface_clip,
+ const absl::optional<gfx::Rect>& quad_clip,
const gfx::Transform& target_transform) {
- base::Optional<gfx::Rect> out_clip;
+ absl::optional<gfx::Rect> out_clip;
if (surface_clip)
out_clip = surface_clip;
@@ -209,8 +209,10 @@ base::Optional<gfx::Rect> SurfaceAggregator::CalculateClipRect(
int SurfaceAggregator::ChildIdForSurface(Surface* surface) {
auto it = surface_id_to_resource_child_id_.find(surface->surface_id());
if (it == surface_id_to_resource_child_id_.end()) {
- int child_id = provider_->CreateChild(base::BindRepeating(
- &SurfaceAggregator::UnrefResources, surface->client()));
+ int child_id = provider_->CreateChild(
+ base::BindRepeating(&SurfaceAggregator::UnrefResources,
+ surface->client()),
+ surface->surface_id());
surface_id_to_resource_child_id_[surface->surface_id()] = child_id;
return child_id;
} else {
@@ -304,7 +306,7 @@ void SurfaceAggregator::AddRenderPassFilterDamageToDamageList(
void SurfaceAggregator::AddSurfaceDamageToDamageList(
const gfx::Rect& default_damage_rect,
const gfx::Transform& parent_target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
const CompositorRenderPass* source_pass,
AggregatedRenderPass* dest_pass,
Surface* surface) {
@@ -354,7 +356,7 @@ const DrawQuad* SurfaceAggregator::FindQuadWithOverlayDamage(
AggregatedRenderPass* dest_pass,
const gfx::Transform& parent_target_transform,
const Surface* surface,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
size_t* overlay_damage_index) {
// If we have damage from a surface animation, then we shouldn't have an
// overlay candidate from the root render pass, since that's an interpolated
@@ -424,9 +426,9 @@ bool SurfaceAggregator::RenderPassNeedsFullDamage(
// static
void SurfaceAggregator::UnrefResources(
base::WeakPtr<SurfaceClient> surface_client,
- const std::vector<ReturnedResource>& resources) {
+ std::vector<ReturnedResource> resources) {
if (surface_client)
- surface_client->UnrefResources(resources);
+ surface_client->UnrefResources(std::move(resources));
}
bool SurfaceAggregator::CanPotentiallyMergePass(
@@ -441,7 +443,7 @@ void SurfaceAggregator::HandleSurfaceQuad(
const SurfaceDrawQuad* surface_quad,
float parent_device_scale_factor,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
AggregatedRenderPass* dest_pass,
bool ignore_undamaged,
gfx::Rect* damage_rect_in_quad_space,
@@ -507,7 +509,7 @@ void SurfaceAggregator::EmitSurfaceContent(
float parent_device_scale_factor,
const SurfaceDrawQuad* surface_quad,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
AggregatedRenderPass* dest_pass,
bool ignore_undamaged,
gfx::Rect* damage_rect_in_quad_space,
@@ -603,14 +605,14 @@ void SurfaceAggregator::EmitSurfaceContent(
copy_requests.empty() && combined_transform.Preserves2dAxisAlignment() &&
CanMergeMaskFilterInfo(mask_filter_info, *render_pass_list.back());
- base::Optional<gfx::Rect> quads_clip;
+ absl::optional<gfx::Rect> quads_clip;
if (merge_pass) {
// Intersect the transformed visible rect and the clip rect to create a
// smaller cliprect for the quad.
gfx::Rect surface_quad_clip_rect = cc::MathUtil::MapEnclosingClippedRect(
source_sqs->quad_to_target_transform, source_visible_rect);
- if (source_sqs->is_clipped) {
- surface_quad_clip_rect.Intersect(source_sqs->clip_rect);
+ if (source_sqs->clip_rect) {
+ surface_quad_clip_rect.Intersect(*source_sqs->clip_rect);
}
quads_clip =
@@ -777,12 +779,14 @@ void SurfaceAggregator::EmitSurfaceContent(
void SurfaceAggregator::EmitDefaultBackgroundColorQuad(
const SurfaceDrawQuad* surface_quad,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
AggregatedRenderPass* dest_pass,
const MaskFilterInfoExt& mask_filter_info) {
- // The primary surface is unavailable and there is no fallback
- // surface specified so create a SolidColorDrawQuad with the default
- // background color.
+ TRACE_EVENT1("viz", "SurfaceAggregator::EmitDefaultBackgroundColorQuad",
+ "surface_range", surface_quad->surface_range.ToString());
+
+ // No matching surface was found so create a SolidColorDrawQuad with the
+ // SurfaceDrawQuad default background color.
SkColor background_color = surface_quad->default_background_color;
auto* shared_quad_state =
CopySharedQuadState(surface_quad->shared_quad_state, target_transform,
@@ -799,7 +803,7 @@ void SurfaceAggregator::EmitGutterQuadsIfNecessary(
const gfx::Rect& fallback_rect,
const SharedQuadState* primary_shared_quad_state,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
SkColor background_color,
AggregatedRenderPass* dest_pass,
const MaskFilterInfoExt& mask_filter_info) {
@@ -888,10 +892,10 @@ void SurfaceAggregator::AddColorConversionPass() {
shared_quad_state->SetAll(
/*quad_to_target_transform=*/gfx::Transform(),
/*quad_layer_rect=*/output_rect,
- /*visible_quad_layer_rect=*/output_rect,
+ /*visible_layer_rect=*/output_rect,
/*mask_filter_info=*/gfx::MaskFilterInfo(),
- /*clip_rect=*/gfx::Rect(),
- /*is_clipped=*/false, /*are_contents_opaque=*/false, /*opacity=*/1.f,
+ /*clip_rect=*/absl::nullopt, /*are_contents_opaque=*/false,
+ /*opacity=*/1.f,
/*blend_mode=*/SkBlendMode::kSrc, /*sorting_context_id=*/0);
auto* quad = color_conversion_pass
@@ -946,10 +950,9 @@ void SurfaceAggregator::AddDisplayTransformPass() {
shared_quad_state->SetAll(
/*quad_to_target_transform=*/root_surface_transform_,
/*quad_layer_rect=*/output_rect,
- /*visible_quad_layer_rect=*/output_rect,
+ /*visible_layer_rect=*/output_rect,
/*mask_filter_info=*/gfx::MaskFilterInfo(),
- /*clip_rect=*/gfx::Rect(),
- /*is_clipped=*/false, are_contents_opaque, /*opacity=*/1.f,
+ /*clip_rect=*/absl::nullopt, are_contents_opaque, /*opacity=*/1.f,
/*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
auto* quad = display_transform_pass
@@ -966,7 +969,7 @@ void SurfaceAggregator::AddDisplayTransformPass() {
SharedQuadState* SurfaceAggregator::CopySharedQuadState(
const SharedQuadState* source_sqs,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
AggregatedRenderPass* dest_render_pass,
const MaskFilterInfoExt& mask_filter_info) {
return CopyAndScaleSharedQuadState(
@@ -981,16 +984,12 @@ SharedQuadState* SurfaceAggregator::CopyAndScaleSharedQuadState(
const gfx::Transform& target_transform,
const gfx::Rect& quad_layer_rect,
const gfx::Rect& visible_quad_layer_rect,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
AggregatedRenderPass* dest_render_pass,
const MaskFilterInfoExt& mask_filter_info_ext) {
auto* shared_quad_state = dest_render_pass->CreateAndAppendSharedQuadState();
- base::Optional<gfx::Rect> quad_clip;
- if (source_sqs->is_clipped) {
- quad_clip = source_sqs->clip_rect;
- }
auto new_clip_rect =
- CalculateClipRect(clip_rect, quad_clip, target_transform);
+ CalculateClipRect(clip_rect, source_sqs->clip_rect, target_transform);
// target_transform contains any transformation that may exist
// between the context that these quads are being copied from (i.e. the
@@ -1003,8 +1002,7 @@ SharedQuadState* SurfaceAggregator::CopyAndScaleSharedQuadState(
shared_quad_state->SetAll(
new_transform, quad_layer_rect, visible_quad_layer_rect,
- mask_filter_info_ext.mask_filter_info,
- new_clip_rect.value_or(gfx::Rect()), new_clip_rect.has_value(),
+ mask_filter_info_ext.mask_filter_info, new_clip_rect,
source_sqs->are_contents_opaque, source_sqs->opacity,
source_sqs->blend_mode, source_sqs->sorting_context_id);
shared_quad_state->is_fast_rounded_corner =
@@ -1021,7 +1019,7 @@ void SurfaceAggregator::CopyQuadsToPass(
const std::unordered_map<ResourceId, ResourceId, ResourceIdHasher>&
child_to_parent_map,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
const Surface* surface,
const MaskFilterInfoExt& parent_mask_filter_info_ext) {
const QuadList& source_quad_list = source_pass.quad_list;
@@ -1526,8 +1524,8 @@ gfx::Rect SurfaceAggregator::PrewalkRenderPass(
cc::MathUtil::MapEnclosingClippedRectIgnoringError(
quad->shared_quad_state->quad_to_target_transform,
quad_damage_rect, kEpsilon);
- if (quad->shared_quad_state->is_clipped) {
- rect_in_target_space.Intersect(quad->shared_quad_state->clip_rect);
+ if (quad->shared_quad_state->clip_rect) {
+ rect_in_target_space.Intersect(*quad->shared_quad_state->clip_rect);
}
damage_rect.Union(rect_in_target_space);
}
@@ -1556,6 +1554,8 @@ bool SurfaceAggregator::DeclareResourcesToProvider(
surface->client()->RefResources(resource_list);
provider_->ReceiveFromChild(child_id, resource_list);
+ stats_->declare_resources_count += resource_list.size();
+
// Figure out which resources are actually used in the render pass.
// Note that we first gather them in a vector, since ResourceIdSet (which we
// actually need) is a flat_set, which means bulk insertion we do at the end
@@ -1619,8 +1619,11 @@ gfx::Rect SurfaceAggregator::PrewalkSurface(
base::flat_map<CompositorRenderPassId, RenderPassMapEntry> render_pass_map =
GenerateRenderPassMap(frame.render_pass_list, IsRootSurface(surface));
+ base::ElapsedTimer timer;
bool valid_frame = DeclareResourcesToProvider(surface, frame.resource_list,
frame.render_pass_list);
+ stats_->declare_resources_time += timer.Elapsed();
+
if (!valid_frame)
return gfx::Rect();
valid_surfaces_.insert(surface->surface_id());
@@ -1951,6 +1954,9 @@ void SurfaceAggregator::RecordStatHistograms() {
stats_->prewalked_surface_count);
UMA_HISTOGRAM_COUNTS_100("Compositing.SurfaceAggregator.CopiedSurfaceCount",
stats_->copied_surface_count);
+ UMA_HISTOGRAM_COUNTS_1000(
+ "Compositing.SurfaceAggregator.DeclareResourcesCount",
+ stats_->declare_resources_count);
constexpr auto kMinTime = base::TimeDelta::FromMicroseconds(5);
constexpr auto kMaxTime = base::TimeDelta::FromMilliseconds(10);
@@ -1961,6 +1967,9 @@ void SurfaceAggregator::RecordStatHistograms() {
UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
"Compositing.SurfaceAggregator.CopyUs", stats_->copy_time, kMinTime,
kMaxTime, kTimeBuckets);
+ UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+ "Compositing.SurfaceAggregator.DeclareResourcesUs",
+ stats_->declare_resources_time, kMinTime, kMaxTime, kTimeBuckets);
stats_.reset();
}
@@ -2122,7 +2131,9 @@ void SurfaceAggregator::HandleDeJelly(Surface* surface) {
continue;
// We are going to de-jelly this SharedQuadState. Expand the max clip.
- jelly_clip.Union(state->clip_rect);
+ if (state->clip_rect) {
+ 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));
@@ -2177,7 +2188,7 @@ void SurfaceAggregator::HandleDeJelly(Surface* surface) {
// 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;
+ has_skew && state->clip_rect && state->clip_rect != jelly_clip;
if (!sub_render_pass && create_render_pass) {
sub_render_pass = std::make_unique<AggregatedRenderPass>(1, 1);
gfx::Transform skew_transform;
@@ -2228,10 +2239,11 @@ void SurfaceAggregator::CreateDeJellyRenderPassQuads(
// MaxDeJellyHeight().
int un_clip_top = 0;
int un_clip_bottom = 0;
- if (state->clip_rect.y() <= jelly_clip.y()) {
+ DCHECK(state->clip_rect);
+ if (state->clip_rect->y() <= jelly_clip.y()) {
un_clip_top = MaxDeJellyHeight();
}
- if (state->clip_rect.bottom() >= jelly_clip.bottom()) {
+ if (state->clip_rect->bottom() >= jelly_clip.bottom()) {
un_clip_bottom = MaxDeJellyHeight();
}
@@ -2274,7 +2286,7 @@ void SurfaceAggregator::CreateDeJellyRenderPassQuads(
}
// Expand our clip by un clip amounts.
- new_state->clip_rect.Inset(0, -un_clip_top, 0, -un_clip_bottom);
+ new_state->clip_rect->Inset(0, -un_clip_top, 0, -un_clip_bottom);
}
// Append all quads sharing |new_state|.
@@ -2315,7 +2327,7 @@ void SurfaceAggregator::AppendDeJellyRenderPass(
gfx::Transform transform;
new_state->SetAll(transform, render_pass->output_rect,
render_pass->output_rect, gfx::MaskFilterInfo(), jelly_clip,
- true, false, opacity, blend_mode, 0);
+ false, opacity, blend_mode, 0);
auto* quad =
root_pass->CreateAndAppendDrawQuad<AggregatedRenderPassDrawQuad>();
quad->SetNew(new_state, render_pass->output_rect, render_pass->output_rect,
diff --git a/chromium/components/viz/service/display/surface_aggregator.h b/chromium/components/viz/service/display/surface_aggregator.h
index 092e7417232..988868e0427 100644
--- a/chromium/components/viz/service/display/surface_aggregator.h
+++ b/chromium/components/viz/service/display/surface_aggregator.h
@@ -6,7 +6,6 @@
#define COMPONENTS_VIZ_SERVICE_DISPLAY_SURFACE_AGGREGATOR_H_
#include <memory>
-#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
@@ -99,9 +98,11 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
struct AggregateStatistics {
int prewalked_surface_count = 0;
int copied_surface_count = 0;
+ int declare_resources_count = 0;
base::TimeDelta prewalk_time;
base::TimeDelta copy_time;
+ base::TimeDelta declare_resources_time;
};
// Helper function that gets a list of render passes and returns a map from
@@ -110,15 +111,15 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
GenerateRenderPassMap(const CompositorRenderPassList& render_pass_list,
bool is_root_surface);
- base::Optional<gfx::Rect> CalculateClipRect(
- const base::Optional<gfx::Rect>& surface_clip,
- const base::Optional<gfx::Rect>& quad_clip,
+ absl::optional<gfx::Rect> CalculateClipRect(
+ const absl::optional<gfx::Rect>& surface_clip,
+ const absl::optional<gfx::Rect>& quad_clip,
const gfx::Transform& target_transform);
void HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad,
float parent_device_scale_factor,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
AggregatedRenderPass* dest_pass,
bool ignore_undamaged,
gfx::Rect* damage_rect_in_quad_space,
@@ -129,7 +130,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
float parent_device_scale_factor,
const SurfaceDrawQuad* surface_quad,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
AggregatedRenderPass* dest_pass,
bool ignore_undamaged,
gfx::Rect* damage_rect_in_quad_space,
@@ -139,7 +140,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
void EmitDefaultBackgroundColorQuad(
const SurfaceDrawQuad* surface_quad,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
AggregatedRenderPass* dest_pass,
const MaskFilterInfoExt& mask_filter_info_pair);
@@ -148,7 +149,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
const gfx::Rect& fallback_rect,
const SharedQuadState* primary_shared_quad_state,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
SkColor background_color,
AggregatedRenderPass* dest_pass,
const MaskFilterInfoExt& mask_filter_info_pair);
@@ -156,7 +157,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
SharedQuadState* CopySharedQuadState(
const SharedQuadState* source_sqs,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
AggregatedRenderPass* dest_render_pass,
const MaskFilterInfoExt& mask_filter_info_pair);
@@ -166,7 +167,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
const gfx::Transform& target_transform,
const gfx::Rect& quad_layer_rect,
const gfx::Rect& visible_quad_layer_rect,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
AggregatedRenderPass* dest_render_pass,
const MaskFilterInfoExt& mask_filter_info_pair);
@@ -177,7 +178,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
const std::unordered_map<ResourceId, ResourceId, ResourceIdHasher>&
resource_to_child_map,
const gfx::Transform& target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
const Surface* surface,
const MaskFilterInfoExt& mask_filter_info_pair);
@@ -273,7 +274,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
void AddSurfaceDamageToDamageList(
const gfx::Rect& damage_rect,
const gfx::Transform& parent_target_transform,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
const CompositorRenderPass* source_pass,
AggregatedRenderPass* dest_pass,
Surface* surface);
@@ -289,7 +290,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
AggregatedRenderPass* dest_pass,
const gfx::Transform& parent_target_transform,
const Surface* surface,
- const base::Optional<gfx::Rect>& clip_rect,
+ const absl::optional<gfx::Rect>& clip_rect,
size_t* overlay_damage_index);
// Returns true if the render pass with the given id and cache_render_pass
@@ -300,7 +301,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
bool IsRootSurface(const Surface* surface) const;
static void UnrefResources(base::WeakPtr<SurfaceClient> surface_client,
- const std::vector<ReturnedResource>& resources);
+ std::vector<ReturnedResource> resources);
// This method transforms the delegated ink metadata to be in the root target
// space, so that it can eventually be drawn onto the back buffer in the
@@ -396,7 +397,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
SurfaceId root_surface_id_;
gfx::Transform root_surface_transform_;
- base::Optional<AggregateStatistics> stats_;
+ absl::optional<AggregateStatistics> stats_;
// For each Surface used in the last aggregation, gives the frame_index at
// that time.
diff --git a/chromium/components/viz/service/display/surface_aggregator_perftest.cc b/chromium/components/viz/service/display/surface_aggregator_perftest.cc
index 4e8dc5518c0..5322d27c2ab 100644
--- a/chromium/components/viz/service/display/surface_aggregator_perftest.cc
+++ b/chromium/components/viz/service/display/surface_aggregator_perftest.cc
@@ -7,6 +7,7 @@
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/service/display/aggregated_frame.h"
#include "components/viz/service/display/display_resource_provider_software.h"
#include "components/viz/service/display/surface_aggregator.h"
@@ -16,6 +17,7 @@
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "components/viz/test/compositor_frame_helpers.h"
+#include "components/viz/test/test_surface_id_allocator.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_result_reporter.h"
@@ -119,7 +121,7 @@ class SurfaceAggregatorPerfTest : public VizPerfTest {
surface_quad->SetNew(
sqs, gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1),
// Surface at index i embeds surface at index i - 1.
- SurfaceRange(base::nullopt,
+ SurfaceRange(absl::nullopt,
SurfaceId(FrameSinkId(1, i),
LocalSurfaceId(i, child_tokens[i - 1]))),
SK_ColorWHITE, /*stretch_content_to_fill_bounds=*/false);
@@ -146,7 +148,7 @@ class SurfaceAggregatorPerfTest : public VizPerfTest {
surface_quad->SetNew(
sqs, gfx::Rect(0, 0, 100, 100), gfx::Rect(0, 0, 100, 100),
SurfaceRange(
- base::nullopt,
+ absl::nullopt,
// Root surface embeds surface at index num_surfaces - 1.
SurfaceId(FrameSinkId(1, num_surfaces),
LocalSurfaceId(num_surfaces,
@@ -190,11 +192,78 @@ class SurfaceAggregatorPerfTest : public VizPerfTest {
reporter.AddResult(kMetricSpeedRunsPerS, timer_.LapsPerSecond());
}
+ void SetUpRenderPassListResources(
+ CompositorRenderPassList* render_pass_list) {
+ std::set<ResourceId> created_resources;
+ for (auto& render_pass : *render_pass_list) {
+ for (auto* quad : render_pass->quad_list) {
+ for (ResourceId resource_id : quad->resources) {
+ // Don't create multiple resources for the same ResourceId.
+ if (created_resources.find(resource_id) != created_resources.end()) {
+ continue;
+ }
+ resource_list_.push_back(TransferableResource::MakeSoftware(
+ SharedBitmap::GenerateId(), quad->rect.size(), RGBA_8888));
+ resource_list_.back().id = resource_id;
+ created_resources.insert(resource_id);
+ }
+ }
+ }
+ }
+
+ void RunSingleSurfaceRenderPassListFromJson(const std::string& tag,
+ const std::string& site,
+ uint32_t year,
+ size_t index) {
+ CompositorRenderPassList render_pass_list;
+ ASSERT_TRUE(CompositorRenderPassListFromJSON(tag, site, year, index,
+ &render_pass_list));
+ ASSERT_FALSE(render_pass_list.empty());
+ this->SetUpRenderPassListResources(&render_pass_list);
+
+ aggregator_ = std::make_unique<SurfaceAggregator>(
+ manager_.surface_manager(), resource_provider_.get(), true, true);
+
+ constexpr FrameSinkId root_frame_sink_id(1, 1);
+ TestSurfaceIdAllocator root_surface_id(root_frame_sink_id);
+ auto root_support = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, &manager_, root_frame_sink_id, /*is_root=*/true);
+
+ base::TimeTicks next_fake_display_time =
+ base::TimeTicks() + base::TimeDelta::FromSeconds(1);
+
+ timer_.Reset();
+ do {
+ CompositorRenderPassList local_list;
+ CompositorRenderPass::CopyAllForTest(render_pass_list, &local_list);
+ // Ensure damage encompasses the entire output_rect so everything is
+ // aggregated.
+ auto& last_render_pass = *local_list.back();
+ last_render_pass.damage_rect = last_render_pass.output_rect;
+
+ CompositorFrame frame = CompositorFrameBuilder()
+ .SetRenderPassList(std::move(local_list))
+ .SetTransferableResources(resource_list_)
+ .Build();
+ root_support->SubmitCompositorFrame(root_surface_id.local_surface_id(),
+ std::move(frame));
+ auto aggregated = aggregator_->Aggregate(
+ root_surface_id, next_fake_display_time, gfx::OVERLAY_TRANSFORM_NONE);
+
+ next_fake_display_time += BeginFrameArgs::DefaultInterval();
+ timer_.NextLap();
+ } while (!timer_.HasTimeLimitExpired());
+
+ auto reporter = SetUpSurfaceAggregatorReporter(site + "_json");
+ reporter.AddResult(kMetricSpeedRunsPerS, timer_.LapsPerSecond());
+ }
+
protected:
ServerSharedBitmapManager shared_bitmap_manager_;
FrameSinkManagerImpl manager_;
std::unique_ptr<DisplayResourceProvider> resource_provider_;
std::unique_ptr<SurfaceAggregator> aggregator_;
+ std::vector<TransferableResource> resource_list_;
};
TEST_F(SurfaceAggregatorPerfTest, ManySurfacesOpaque) {
@@ -251,5 +320,35 @@ TEST_F(SurfaceAggregatorPerfTest, FewSurfacesAggregateDamaged) {
ExpectedOutput(1, 1500));
}
+#define TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(SITE, FRAME) \
+ TEST_F(SurfaceAggregatorPerfTest, SITE##_JsonTest) { \
+ this->RunSingleSurfaceRenderPassListFromJson( \
+ /*tag=*/"top_real_world_desktop", /*site=*/#SITE, /*year=*/2018, \
+ /*frame_index=*/FRAME); \
+ }
+
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(accu_weather, 298)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(amazon, 30)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(blogspot, 56)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(ebay, 44)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(espn, 463)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(facebook, 327)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(gmail, 66)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(google_calendar, 53)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(google_docs, 369)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(google_image_search, 44)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(google_plus, 45)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(google_web_search, 89)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(linkedin, 284)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(pinterest, 120)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(techcrunch, 190)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(twitch, 396)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(wikipedia, 48)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(wordpress, 75)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(yahoo_answers, 74)
+TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST(yahoo_sports, 269)
+
+#undef TOP_REAL_WORLD_DESKTOP_RENDERER_PERF_TEST
+
} // namespace
} // namespace viz
diff --git a/chromium/components/viz/service/display/surface_aggregator_pixeltest.cc b/chromium/components/viz/service/display/surface_aggregator_pixeltest.cc
index a5823e2e87f..ae4b37f7c82 100644
--- a/chromium/components/viz/service/display/surface_aggregator_pixeltest.cc
+++ b/chromium/components/viz/service/display/surface_aggregator_pixeltest.cc
@@ -76,15 +76,13 @@ SharedQuadState* CreateAndAppendTestSharedQuadState(
const gfx::Rect layer_rect = gfx::Rect(size);
const gfx::Rect visible_layer_rect = gfx::Rect(size);
const gfx::MaskFilterInfo mask_filter_info;
- const gfx::Rect clip_rect = gfx::Rect(size);
- bool is_clipped = false;
bool are_contents_opaque = false;
float opacity = 1.f;
const SkBlendMode blend_mode = SkBlendMode::kSrcOver;
auto* shared_state = render_pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(transform, layer_rect, visible_layer_rect,
- mask_filter_info, clip_rect, is_clipped,
- are_contents_opaque, opacity, blend_mode, 0);
+ mask_filter_info, absl::nullopt, are_contents_opaque,
+ opacity, blend_mode, 0);
return shared_state;
}
@@ -155,7 +153,7 @@ TEST_P(SurfaceAggregatorPixelTest, DrawSimpleAggregatedFrame) {
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetNew(
pass->shared_quad_state_list.back(), gfx::Rect(child_size),
- gfx::Rect(child_size), SurfaceRange(base::nullopt, child_surface_id),
+ gfx::Rect(child_size), SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, /*stretch_content_to_fill_bounds=*/false);
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
@@ -249,7 +247,7 @@ TEST_P(SurfaceAggregatorPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
auto* left_surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
left_surface_quad->SetNew(
pass->shared_quad_state_list.back(), gfx::Rect(child_size),
- gfx::Rect(child_size), SurfaceRange(base::nullopt, left_child_id),
+ gfx::Rect(child_size), SurfaceRange(absl::nullopt, left_child_id),
SK_ColorWHITE, /*stretch_content_to_fill_bounds=*/false);
surface_transform.Translate(100, 0);
@@ -259,7 +257,7 @@ TEST_P(SurfaceAggregatorPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
auto* right_surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
right_surface_quad->SetNew(
pass->shared_quad_state_list.back(), gfx::Rect(child_size),
- gfx::Rect(child_size), SurfaceRange(base::nullopt, right_child_id),
+ gfx::Rect(child_size), SurfaceRange(absl::nullopt, right_child_id),
SK_ColorWHITE, /*stretch_content_to_fill_bounds=*/false);
auto root_frame =
diff --git a/chromium/components/viz/service/display/surface_aggregator_unittest.cc b/chromium/components/viz/service/display/surface_aggregator_unittest.cc
index a91ea2916d2..3b158670238 100644
--- a/chromium/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/chromium/components/viz/service/display/surface_aggregator_unittest.cc
@@ -14,6 +14,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/format_macros.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/stl_util.h"
@@ -383,15 +384,13 @@ class SurfaceAggregatorTest : public testing::Test, public DisplayTimeSource {
gfx::Transform layer_to_target_transform = transform;
gfx::Rect layer_bounds(primary_surface_rect);
gfx::Rect visible_layer_rect(primary_surface_rect);
- gfx::Rect clip_rect(primary_surface_rect);
- bool is_clipped = false;
bool are_contents_opaque = false;
SkBlendMode blend_mode = SkBlendMode::kSrcOver;
auto* shared_quad_state = pass->CreateAndAppendSharedQuadState();
shared_quad_state->SetAll(layer_to_target_transform, layer_bounds,
- visible_layer_rect, mask_filter_info, clip_rect,
- is_clipped, are_contents_opaque, opacity,
+ visible_layer_rect, mask_filter_info,
+ absl::nullopt, are_contents_opaque, opacity,
blend_mode, 0);
shared_quad_state->is_fast_rounded_corner = is_fast_rounded_corner;
@@ -411,7 +410,7 @@ class SurfaceAggregatorTest : public testing::Test, public DisplayTimeSource {
gfx::Rect output_rect = gfx::Rect(0, 0, 5, 5);
auto* shared_state = pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(transform, output_rect, output_rect,
- gfx::MaskFilterInfo(), output_rect, false, false, 1,
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1,
SkBlendMode::kSrcOver, 0);
auto* quad = pass->CreateAndAppendDrawQuad<CompositorRenderPassDrawQuad>();
quad->SetAll(shared_state, output_rect, output_rect,
@@ -426,7 +425,7 @@ class SurfaceAggregatorTest : public testing::Test, public DisplayTimeSource {
const gfx::Rect& output_rect) {
auto* shared_state = pass->CreateAndAppendSharedQuadState();
shared_state->SetAll(gfx::Transform(), output_rect, output_rect,
- gfx::MaskFilterInfo(), output_rect, false, false, 1,
+ gfx::MaskFilterInfo(), absl::nullopt, false, 1,
SkBlendMode::kSrcOver, 0);
auto* quad = pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
quad->SetNew(shared_state, output_rect, output_rect, false,
@@ -453,7 +452,8 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
nullptr,
&manager_,
kArbitraryReservedFrameSinkId,
- kChildIsRoot)) {
+ kChildIsRoot)),
+ root_surface_id_(kArbitraryRootFrameSinkId) {
child_sink_->set_allow_copy_output_requests_for_testing();
}
@@ -462,10 +462,8 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
void SetUp() override {
SurfaceAggregatorTest::SetUp();
- root_allocator_.GenerateId();
- root_local_surface_id_ = root_allocator_.GetCurrentLocalSurfaceId();
- root_surface_ = manager_.surface_manager()->GetSurfaceForId(
- SurfaceId(root_sink_->frame_sink_id(), root_local_surface_id_));
+ root_surface_ =
+ manager_.surface_manager()->GetSurfaceForId(root_surface_id_);
}
void TearDown() override { SurfaceAggregatorTest::TearDown(); }
@@ -494,9 +492,7 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
void AggregateAndVerify(const std::vector<Pass>& expected_passes,
const std::vector<SurfaceId>& expected_surface_ids) {
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
TestPassesMatchExpectations(expected_passes,
&aggregated_frame.render_pass_list);
@@ -596,10 +592,9 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
}
protected:
- LocalSurfaceId root_local_surface_id_;
Surface* root_surface_;
- ParentLocalSurfaceIdAllocator root_allocator_;
std::unique_ptr<CompositorFrameSinkSupport> child_sink_;
+ TestSurfaceIdAllocator root_surface_id_;
};
// This test is parameterized on a boolean value to allow the
@@ -626,19 +621,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {
aggregated_damage_callback.GetCallback());
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
// Check that the AggregatedDamageCallback is called with the right arguments.
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
- AggregateAndVerify(passes, {root_surface_id});
+ AggregateAndVerify(passes, {root_surface_id_});
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
}
@@ -648,12 +641,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {
TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
auto embedded_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kRootIsRoot);
- ParentLocalSurfaceIdAllocator embedded_allocator;
- embedded_allocator.GenerateId();
- LocalSurfaceId embedded_local_surface_id =
- embedded_allocator.GetCurrentLocalSurfaceId();
- SurfaceId embedded_surface_id(embedded_support->frame_sink_id(),
- embedded_local_surface_id);
+ TestSurfaceIdAllocator embedded_surface_id(embedded_support->frame_sink_id());
std::vector<Quad> embedded_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5)),
@@ -662,21 +650,22 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
constexpr float device_scale_factor = 1.0f;
SubmitCompositorFrame(embedded_support.get(), embedded_passes,
- embedded_local_surface_id, device_scale_factor);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
+ embedded_surface_id.local_surface_id(),
+ device_scale_factor);
+
{
std::vector<Quad> quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, embedded_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, embedded_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), .5f, gfx::Transform(),
/*stretch_content_to_fill_bounds=*/false, gfx::MaskFilterInfo(),
/*is_fast_rounded_corner=*/false)};
std::vector<Pass> passes = {Pass(quads, SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto& render_pass_list = aggregated_frame.render_pass_list;
EXPECT_EQ(2u, render_pass_list.size());
@@ -690,16 +679,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
// use a render surface.
{
std::vector<Quad> quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, embedded_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, embedded_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), .9999f, gfx::Transform(),
/*stretch_content_to_fill_bounds=*/false, gfx::MaskFilterInfo(),
/*is_fast_rounded_corner=*/false)};
std::vector<Pass> passes = {Pass(quads, SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto& render_pass_list = aggregated_frame.render_pass_list;
EXPECT_EQ(1u, render_pass_list.size());
@@ -711,12 +701,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
TEST_F(SurfaceAggregatorValidSurfaceTest, RotatedClip) {
auto embedded_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kRootIsRoot);
- ParentLocalSurfaceIdAllocator embedded_allocator;
- embedded_allocator.GenerateId();
- LocalSurfaceId embedded_local_surface_id =
- embedded_allocator.GetCurrentLocalSurfaceId();
- SurfaceId embedded_surface_id(embedded_support->frame_sink_id(),
- embedded_local_surface_id);
+ TestSurfaceIdAllocator embedded_surface_id(embedded_support->frame_sink_id());
std::vector<Quad> embedded_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5)),
@@ -724,23 +709,24 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RotatedClip) {
std::vector<Pass> embedded_passes = {Pass(embedded_quads, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
+
SubmitCompositorFrame(embedded_support.get(), embedded_passes,
- embedded_local_surface_id, device_scale_factor);
+ embedded_surface_id.local_surface_id(),
+ device_scale_factor);
gfx::Transform rotate;
rotate.Rotate(30);
std::vector<Quad> quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, embedded_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, embedded_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), 1.f, rotate,
/*stretch_content_to_fill_bounds=*/false, gfx::MaskFilterInfo(),
/*is_fast_rounded_corner=*/false)};
std::vector<Pass> passes = {Pass(quads, SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto& render_pass_list = aggregated_frame.render_pass_list;
EXPECT_EQ(2u, render_pass_list.size());
@@ -762,13 +748,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
- AggregateAndVerify(passes, {root_surface_id});
+ AggregateAndVerify(passes, {root_surface_id_});
}
// Ensure that the render pass ID map properly keeps and deletes entries.
@@ -783,10 +767,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassDeallocation) {
Pass(quads[1], CompositorRenderPassId{1}, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId surface_id(root_sink_->frame_sink_id(), root_local_surface_id_);
+ SurfaceId surface_id(root_sink_->frame_sink_id(),
+ root_surface_id_.local_surface_id());
auto aggregated_frame = AggregateFrame(surface_id);
auto id0 = aggregated_frame.render_pass_list[0]->id;
@@ -802,7 +788,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassDeallocation) {
Pass(quads[0], CompositorRenderPassId{3}, SurfaceSize()),
Pass(quads[1], CompositorRenderPassId{1}, SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), passes2, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes2,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
// The RenderPass that still exists should keep the same ID.
@@ -812,7 +799,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassDeallocation) {
EXPECT_NE(id2, id0);
EXPECT_EQ(id1, aggregated_frame.render_pass_list[1]->id);
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
// |id1| didn't exist in the previous frame, so it should be
@@ -832,30 +820,28 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassDeallocation) {
TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
auto embedded_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kRootIsRoot);
- ParentLocalSurfaceIdAllocator embedded_allocator;
- embedded_allocator.GenerateId();
- LocalSurfaceId embedded_local_surface_id =
- embedded_allocator.GetCurrentLocalSurfaceId();
- SurfaceId embedded_surface_id(embedded_support->frame_sink_id(),
- embedded_local_surface_id);
+ TestSurfaceIdAllocator embedded_surface_id(embedded_support->frame_sink_id());
std::vector<Quad> embedded_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> embedded_passes = {Pass(embedded_quads, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
+
SubmitCompositorFrame(embedded_support.get(), embedded_passes,
- embedded_local_surface_id, device_scale_factor);
+ embedded_surface_id.local_surface_id(),
+ device_scale_factor);
std::vector<Quad> root_quads = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, embedded_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, embedded_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
std::vector<Quad> expected_quads = {
@@ -863,9 +849,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5)),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
std::vector<Pass> expected_passes = {Pass(expected_quads, SurfaceSize())};
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- AggregateAndVerify(expected_passes, {root_surface_id, embedded_surface_id});
+ AggregateAndVerify(expected_passes, {root_surface_id_, embedded_surface_id});
}
class TestVizClient {
@@ -900,12 +884,12 @@ class TestVizClient {
for (const auto& embed : embedded_clients_) {
if (embed.second) {
embedded_quads.push_back(Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, embed.first->surface_id()),
+ SurfaceRange(absl::nullopt, embed.first->surface_id()),
SK_ColorWHITE, embed.first->bounds(),
/*stretch_content_to_fill_bounds=*/false));
} else {
referenced_surfaces.emplace_back(
- SurfaceRange(base::nullopt, embed.first->surface_id()));
+ SurfaceRange(absl::nullopt, embed.first->surface_id()));
}
}
std::vector<Pass> embedded_passes = {Pass(embedded_quads, bounds_.size())};
@@ -963,14 +947,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UndrawnSurfaces) {
std::vector<Quad> root_quads = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, parent.surface_id()),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, parent.surface_id()),
SK_ColorWHITE, parent.bounds(),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
std::vector<Quad> expected_quads = {
@@ -978,9 +963,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UndrawnSurfaces) {
Quad::SolidColorQuad(SK_ColorGREEN, parent.bounds()),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
std::vector<Pass> expected_passes = {Pass(expected_quads, SurfaceSize())};
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- AggregateAndVerify(expected_passes, {root_surface_id, parent.surface_id(),
+ AggregateAndVerify(expected_passes, {root_surface_id_, parent.surface_id(),
child.surface_id()});
// |child| should not be drawn.
EXPECT_TRUE(child.GetSurface()->HasUndrawnActiveFrame());
@@ -997,7 +980,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UndrawnSurfaces) {
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
AggregateAndVerify(
{Pass(expected_quads, SurfaceSize())},
- {root_surface_id, parent.surface_id(), child.surface_id()});
+ {root_surface_id_, parent.surface_id(), child.surface_id()});
EXPECT_FALSE(child.GetSurface()->HasUndrawnActiveFrame());
}
@@ -1016,14 +999,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UndrawnSurfacesWithCopyRequests) {
std::vector<Quad> root_quads = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, parent.surface_id()),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, parent.surface_id()),
SK_ColorWHITE, parent.bounds(),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
std::vector<Quad> expected_quads = {
@@ -1034,9 +1018,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UndrawnSurfacesWithCopyRequests) {
Quad::SolidColorQuad(SK_ColorBLUE, child.bounds())};
std::vector<Pass> expected_passes = {Pass(expected_copy_quads, SurfaceSize()),
Pass(expected_quads, SurfaceSize())};
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- AggregateAndVerify(expected_passes, {root_surface_id, parent.surface_id(),
+ AggregateAndVerify(expected_passes, {root_surface_id_, parent.surface_id(),
child.surface_id()});
EXPECT_FALSE(child.GetSurface()->HasUndrawnActiveFrame());
EXPECT_FALSE(parent.GetSurface()->HasUndrawnActiveFrame());
@@ -1065,17 +1047,18 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
// Submit a root CompositorFrame that embeds both parents.
std::vector<Quad> root_quads = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, first_parent.surface_id()),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, first_parent.surface_id()),
SK_ColorCYAN, first_parent.bounds(),
/*stretch_content_to_fill_bounds=*/false),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, second_parent.surface_id()),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, second_parent.surface_id()),
SK_ColorMAGENTA, second_parent.bounds(),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
EXPECT_TRUE(child.GetSurface()->HasUndrawnActiveFrame());
@@ -1090,10 +1073,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
std::vector<Quad> expected_copy_quads = {};
std::vector<Pass> expected_passes = {Pass(expected_quads, SurfaceSize())};
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
AggregateAndVerify(expected_passes,
- {root_surface_id, first_parent.surface_id(),
+ {root_surface_id_, first_parent.surface_id(),
second_parent.surface_id(), child.surface_id()});
EXPECT_FALSE(child.GetSurface()->HasUndrawnActiveFrame());
EXPECT_FALSE(first_parent.GetSurface()->HasUndrawnActiveFrame());
@@ -1103,15 +1084,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
// This test verifies that the appropriate transform will be applied to a
// surface embedded by a parent SurfaceDrawQuad marked as
// stretch_content_to_fill_bounds.
+
TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillBounds) {
auto primary_child_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId primary_child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId primary_child_surface_id(primary_child_support->frame_sink_id(),
- primary_child_local_surface_id);
+ TestSurfaceIdAllocator primary_child_surface_id(
+ primary_child_support->frame_sink_id());
{
auto pass = CompositorRenderPass::Create();
@@ -1123,12 +1101,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillBounds) {
solid_color_quad->SetNew(sqs, gfx::Rect(0, 0, 20, 20),
gfx::Rect(0, 0, 20, 20), SK_ColorRED, false);
-
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
- primary_child_support->SubmitCompositorFrame(primary_child_local_surface_id,
- std::move(frame));
+ primary_child_support->SubmitCompositorFrame(
+ primary_child_surface_id.local_surface_id(), std::move(frame));
}
constexpr gfx::Rect surface_quad_rect(10, 5);
@@ -1141,16 +1118,14 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillBounds) {
root_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
- 1.0f);
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(), 1.0f);
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
- auto frame = AggregateFrame(root_surface_id);
+ auto frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
EXPECT_EQ(1u, frame.render_pass_list.size());
@@ -1177,12 +1152,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillBounds) {
TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillStretchedBounds) {
auto primary_child_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId primary_child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId primary_child_surface_id(primary_child_support->frame_sink_id(),
- primary_child_local_surface_id);
+ TestSurfaceIdAllocator primary_child_surface_id(
+ primary_child_support->frame_sink_id());
{
auto pass = CompositorRenderPass::Create();
@@ -1198,8 +1169,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillStretchedBounds) {
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
- primary_child_support->SubmitCompositorFrame(primary_child_local_surface_id,
- std::move(frame));
+ primary_child_support->SubmitCompositorFrame(
+ primary_child_surface_id.local_surface_id(), std::move(frame));
}
constexpr gfx::Rect surface_quad_rect(10, 5);
@@ -1212,16 +1183,14 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillStretchedBounds) {
root_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
- 2.0f);
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(), 2.0f);
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
- auto frame = AggregateFrame(root_surface_id);
+ auto frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
@@ -1249,12 +1218,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillStretchedBounds) {
TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillSquashedBounds) {
auto primary_child_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId primary_child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId primary_child_surface_id(primary_child_support->frame_sink_id(),
- primary_child_local_surface_id);
+ TestSurfaceIdAllocator primary_child_surface_id(
+ primary_child_support->frame_sink_id());
{
auto pass = CompositorRenderPass::Create();
@@ -1270,8 +1235,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillSquashedBounds) {
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
- primary_child_support->SubmitCompositorFrame(primary_child_local_surface_id,
- std::move(frame));
+ primary_child_support->SubmitCompositorFrame(
+ primary_child_surface_id.local_surface_id(), std::move(frame));
}
constexpr gfx::Rect surface_quad_rect(10, 5);
@@ -1284,16 +1249,14 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillSquashedBounds) {
root_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
- 0.5f);
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(), 0.5f);
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
- auto frame = AggregateFrame(root_surface_id);
+ auto frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
EXPECT_EQ(1u, frame.render_pass_list.size());
@@ -1317,9 +1280,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillSquashedBounds) {
// root RenderPass merged with the RenderPass that embeds it. This ensures the
// reflected pixels can be scaled with AA enabled.
TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadScaled) {
- const SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
// Submit a CompositorFrame for the primary display. This will get mirrored
// by the second display through surface embedding.
const gfx::Rect display_rect(0, 0, 100, 100);
@@ -1337,17 +1297,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadScaled) {
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
- root_sink_->SubmitCompositorFrame(root_surface_id.local_surface_id(),
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(frame));
}
auto mirror_display_sink = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, true);
- ParentLocalSurfaceIdAllocator lsi_allocator;
- lsi_allocator.GenerateId();
- LocalSurfaceId mirror_display_local_surface_id =
- lsi_allocator.GetCurrentLocalSurfaceId();
+ TestSurfaceIdAllocator mirror_display_surface_id(
+ mirror_display_sink->frame_sink_id());
// The mirroring display size is smaller than the primary display. The
// mirrored content would be scaled to fit.
@@ -1366,7 +1324,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadScaled) {
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetAll(sqs, display_rect, display_rect,
/*needs_blending=*/false,
- SurfaceRange(base::nullopt, root_surface_id),
+ SurfaceRange(absl::nullopt, root_surface_id_),
SK_ColorBLACK,
/*stretch_content_to_fill_bounds=*/true,
/*is_reflection=*/true,
@@ -1374,12 +1332,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadScaled) {
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
- mirror_display_sink->SubmitCompositorFrame(mirror_display_local_surface_id,
- std::move(frame));
+ mirror_display_sink->SubmitCompositorFrame(
+ mirror_display_surface_id.local_surface_id(), std::move(frame));
}
- const SurfaceId mirror_display_surface_id(
- mirror_display_sink->frame_sink_id(), mirror_display_local_surface_id);
auto frame = AggregateFrame(mirror_display_surface_id);
// The reflected surface should be a separate RenderPass as it's scaled. The
@@ -1401,9 +1357,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadScaled) {
// Verify that a reflected SurfaceDrawQuad with no scaling has the surfaces root
// RenderPass merged with the RenderPass that embeds it.
TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadNotScaled) {
- const SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
// Submit a CompositorFrame for the primary display. This will get mirrored
// by the second display through surface embedding.
const gfx::Rect display_rect(0, 0, 100, 100);
@@ -1421,17 +1374,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadNotScaled) {
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
- root_sink_->SubmitCompositorFrame(root_surface_id.local_surface_id(),
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(frame));
}
auto mirror_display_sink = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, true);
- ParentLocalSurfaceIdAllocator lsi_allocator;
- lsi_allocator.GenerateId();
- LocalSurfaceId mirror_display_local_surface_id =
- lsi_allocator.GetCurrentLocalSurfaceId();
+ TestSurfaceIdAllocator mirror_display_surface_id(
+ mirror_display_sink->frame_sink_id());
// The mirroring display is the same width but different height. The mirrored
// content would be letterboxed by translating it.
@@ -1450,7 +1401,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadNotScaled) {
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetAll(sqs, display_rect, display_rect,
/*needs_blending=*/false,
- SurfaceRange(base::nullopt, root_surface_id),
+ SurfaceRange(absl::nullopt, root_surface_id_),
SK_ColorBLACK,
/*stretch_content_to_fill_bounds=*/true,
/*is_reflection=*/true,
@@ -1458,12 +1409,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadNotScaled) {
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
- mirror_display_sink->SubmitCompositorFrame(mirror_display_local_surface_id,
- std::move(frame));
+ mirror_display_sink->SubmitCompositorFrame(
+ mirror_display_surface_id.local_surface_id(), std::move(frame));
}
- const SurfaceId mirror_display_surface_id(
- mirror_display_sink->frame_sink_id(), mirror_display_local_surface_id);
auto frame = AggregateFrame(mirror_display_surface_id);
// The reflected surfaces RenderPass should be merged into the root RenderPass
@@ -1487,12 +1436,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadNotScaled) {
TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) {
auto primary_child_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot);
- ParentLocalSurfaceIdAllocator primary_allocator;
- primary_allocator.GenerateId();
- LocalSurfaceId primary_child_local_surface_id =
- primary_allocator.GetCurrentLocalSurfaceId();
- SurfaceId primary_child_surface_id(primary_child_support->frame_sink_id(),
- primary_child_local_surface_id);
+ TestSurfaceIdAllocator primary_child_surface_id(
+ primary_child_support->frame_sink_id());
std::vector<Quad> primary_child_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
constexpr gfx::Size primary_size(50, 50);
@@ -1503,17 +1448,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) {
// SolidColorDrawQuad.
constexpr float device_scale_factor = 1.0f;
SubmitCompositorFrame(primary_child_support.get(), primary_child_passes,
-
- primary_child_local_surface_id, device_scale_factor);
+ primary_child_surface_id.local_surface_id(),
+ device_scale_factor);
auto fallback_child_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId2, kChildIsRoot);
- ParentLocalSurfaceIdAllocator fallback_allocator;
- fallback_allocator.GenerateId();
- LocalSurfaceId fallback_child_local_surface_id =
- fallback_allocator.GetCurrentLocalSurfaceId();
- SurfaceId fallback_child_surface_id(fallback_child_support->frame_sink_id(),
- fallback_child_local_surface_id);
+ TestSurfaceIdAllocator fallback_child_surface_id(
+ fallback_child_support->frame_sink_id());
std::vector<Quad> fallback_child_quads = {
Quad::SolidColorQuad(SK_ColorRED, gfx::Rect(5, 5))};
@@ -1524,7 +1465,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) {
// SolidColorDrawQuad.
SubmitCompositorFrame(fallback_child_support.get(), fallback_child_passes,
- fallback_child_local_surface_id, device_scale_factor);
+ fallback_child_surface_id.local_surface_id(),
+ device_scale_factor);
// Try to embed |primary_child_surface_id| and if unavailabe, embed
// |fallback_child_surface_id|.
@@ -1539,7 +1481,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) {
root_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
// The CompositorFrame is submitted to |primary_child_surface_id|, so
@@ -1549,32 +1492,30 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> expected_passes1 = {Pass(expected_quads1, SurfaceSize())};
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, root_size,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), root_size,
gfx::Rect(root_size), next_display_time()));
// The fallback will not be contained within the aggregated frame.
AggregateAndVerify(expected_passes1,
- {root_surface_id, primary_child_surface_id});
+ {root_surface_id_, primary_child_surface_id});
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
// Submit a new frame to the primary surface to cause some damage.
SubmitCompositorFrame(primary_child_support.get(), primary_child_passes,
- primary_child_local_surface_id, device_scale_factor);
+ primary_child_surface_id.local_surface_id(),
+ device_scale_factor);
// The size of the damage should be equal to the size of the primary surface.
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, root_size,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), root_size,
gfx::Rect(primary_size), next_display_time()));
// Generate a new aggregated frame.
AggregateAndVerify(expected_passes1,
- {root_surface_id, primary_child_surface_id});
+ {root_surface_id_, primary_child_surface_id});
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
}
@@ -1582,12 +1523,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) {
TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
auto embedded_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot);
- ParentLocalSurfaceIdAllocator embedded_allocator;
- embedded_allocator.GenerateId();
- LocalSurfaceId embedded_local_surface_id =
- embedded_allocator.GetCurrentLocalSurfaceId();
- SurfaceId embedded_surface_id(embedded_support->frame_sink_id(),
- embedded_local_surface_id);
+ TestSurfaceIdAllocator embedded_surface_id(embedded_support->frame_sink_id());
std::vector<Quad> embedded_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
@@ -1595,26 +1531,27 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
constexpr float device_scale_factor = 1.0f;
SubmitCompositorFrame(embedded_support.get(), embedded_passes,
- embedded_local_surface_id, device_scale_factor);
+ embedded_surface_id.local_surface_id(),
+ device_scale_factor);
auto copy_request = CopyOutputRequest::CreateStubForTesting();
auto* copy_request_ptr = copy_request.get();
- embedded_support->RequestCopyOfOutput(
- {embedded_local_surface_id, SubtreeCaptureId(), std::move(copy_request)});
+ embedded_support->RequestCopyOfOutput({embedded_surface_id.local_surface_id(),
+ SubtreeCaptureId(),
+ std::move(copy_request)});
std::vector<Quad> root_quads = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, embedded_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, embedded_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
std::vector<Quad> expected_quads = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
@@ -1632,7 +1569,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
DCHECK_EQ(copy_request_ptr,
aggregated_frame.render_pass_list[0]->copy_requests[0].get());
- SurfaceId surface_ids[] = {root_surface_id, embedded_surface_id};
+ SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id};
EXPECT_EQ(base::size(surface_ids),
aggregator_.previous_contained_surfaces().size());
for (size_t i = 0; i < base::size(surface_ids); i++) {
@@ -1646,12 +1583,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {
TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
auto embedded_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId2, kChildIsRoot);
- ParentLocalSurfaceIdAllocator embedded_allocator;
- embedded_allocator.GenerateId();
- LocalSurfaceId embedded_local_surface_id =
- embedded_allocator.GetCurrentLocalSurfaceId();
- SurfaceId embedded_surface_id(embedded_support->frame_sink_id(),
- embedded_local_surface_id);
+ TestSurfaceIdAllocator embedded_surface_id(embedded_support->frame_sink_id());
std::vector<Quad> embedded_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
@@ -1659,7 +1591,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
constexpr float device_scale_factor = 1.0f;
SubmitCompositorFrame(embedded_support.get(), embedded_passes,
- embedded_local_surface_id, device_scale_factor);
+ embedded_surface_id.local_surface_id(),
+ device_scale_factor);
auto copy_request(CopyOutputRequest::CreateStubForTesting());
auto* copy_request_ptr = copy_request.get();
auto copy_request2(CopyOutputRequest::CreateStubForTesting());
@@ -1667,7 +1600,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
std::vector<Quad> root_quads = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, embedded_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, embedded_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorBLACK, gfx::Rect(5, 5))};
@@ -1684,12 +1617,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
frame.render_pass_list[1]->copy_requests.push_back(
std::move(copy_request2));
- root_sink_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame));
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
+ std::move(frame));
}
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
std::vector<Quad> expected_quads = {
Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)),
@@ -1708,7 +1640,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
DCHECK_EQ(copy_request2_ptr,
aggregated_frame.render_pass_list[1]->copy_requests[0].get());
- SurfaceId surface_ids[] = {root_surface_id, embedded_surface_id};
+ SurfaceId surface_ids[] = {root_surface_id_, embedded_surface_id};
EXPECT_EQ(base::size(surface_ids),
aggregator_.previous_contained_surfaces().size());
for (size_t i = 0; i < base::size(surface_ids); i++) {
@@ -1718,9 +1650,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {
}
// Ensure copy requests have been removed from root surface.
- const CompositorFrame& original_frame = manager_.surface_manager()
- ->GetSurfaceForId(root_surface_id)
- ->GetActiveFrame();
+ const CompositorFrame& original_frame =
+ manager_.surface_manager()
+ ->GetSurfaceForId(root_surface_id_)
+ ->GetActiveFrame();
const auto& original_pass_list = original_frame.render_pass_list;
ASSERT_EQ(2u, original_pass_list.size());
DCHECK(original_pass_list[0]->copy_requests.empty());
@@ -1733,9 +1666,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) {
auto parent_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId2, kRootIsRoot);
TestSurfaceIdAllocator embedded_surface_id(embedded_support->frame_sink_id());
- root_allocator_.GenerateId();
- SurfaceId nonexistent_surface_id(root_sink_->frame_sink_id(),
- root_allocator_.GetCurrentLocalSurfaceId());
+ TestSurfaceIdAllocator nonexistent_surface_id(root_sink_->frame_sink_id());
std::vector<Quad> embedded_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
@@ -1751,16 +1682,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) {
SubtreeCaptureId(),
std::move(copy_request)});
- ParentLocalSurfaceIdAllocator parent_allocator;
- parent_allocator.GenerateId();
- LocalSurfaceId parent_local_surface_id =
- parent_allocator.GetCurrentLocalSurfaceId();
- SurfaceId parent_surface_id(parent_support->frame_sink_id(),
- parent_local_surface_id);
+ TestSurfaceIdAllocator parent_surface_id(parent_support->frame_sink_id());
std::vector<Quad> parent_quads = {
Quad::SolidColorQuad(SK_ColorGRAY, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, embedded_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, embedded_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorLTGRAY, gfx::Rect(5, 5))};
@@ -1774,7 +1700,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) {
frame.metadata.referenced_surfaces.emplace_back(embedded_surface_id);
- parent_support->SubmitCompositorFrame(parent_local_surface_id,
+ parent_support->SubmitCompositorFrame(parent_surface_id.local_surface_id(),
std::move(frame));
}
@@ -1793,12 +1719,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) {
// included in previous_contained_surfaces, but otherwise ignored.
frame.metadata.referenced_surfaces.emplace_back(nonexistent_surface_id);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame));
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
+ std::move(frame));
}
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// First pass should come from surface that had a copy request but was not
// referenced directly. The second pass comes from the root surface.
@@ -1814,9 +1739,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) {
DCHECK_EQ(copy_request_ptr,
aggregated_frame.render_pass_list[0]->copy_requests[0].get());
- SurfaceId surface_ids[] = {
- SurfaceId(root_sink_->frame_sink_id(), root_local_surface_id_),
- parent_surface_id, embedded_surface_id};
+ SurfaceId surface_ids[] = {root_surface_id_, parent_surface_id,
+ embedded_surface_id};
EXPECT_EQ(base::size(surface_ids),
aggregator_.previous_contained_surfaces().size());
for (size_t i = 0; i < base::size(surface_ids); i++) {
@@ -1854,7 +1778,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
std::vector<Quad> root_quads[3] = {
{Quad::SolidColorQuad(5, gfx::Rect(5, 5)),
Quad::SolidColorQuad(6, gfx::Rect(5, 5))},
- {Quad::SurfaceQuad(SurfaceRange(base::nullopt, embedded_surface_id),
+ {Quad::SurfaceQuad(SurfaceRange(absl::nullopt, embedded_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
Quad::RenderPassQuad(pass_ids[0], gfx::Transform(), true)},
@@ -1865,12 +1789,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
Pass(root_quads[1], pass_ids[1], SurfaceSize()),
Pass(root_quads[2], pass_ids[2], SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -1990,38 +1913,33 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
std::vector<Pass> passes = {Pass(quads, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
std::vector<Quad> expected_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5)),
Quad::SolidColorQuad(SK_ColorBLUE, gfx::Rect(5, 5))};
std::vector<Pass> expected_passes = {Pass(expected_quads, SurfaceSize())};
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- AggregateAndVerify(expected_passes, {root_surface_id});
+ AggregateAndVerify(expected_passes, {root_surface_id_});
}
// Tests a reference to a valid surface with no submitted frame. A
// SolidColorDrawQuad should be placed in lieu of a frame.
TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId empty_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId surface_with_no_frame_id(kArbitraryFrameSinkId1,
- empty_local_surface_id);
+ TestSurfaceIdAllocator surface_with_no_frame_id(kArbitraryFrameSinkId1);
std::vector<Quad> quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, surface_with_no_frame_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, surface_with_no_frame_id),
SK_ColorYELLOW, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorBLUE, gfx::Rect(5, 5))};
std::vector<Pass> passes = {Pass(quads, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
std::vector<Quad> expected_quads = {
@@ -2029,20 +1947,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {
Quad::SolidColorQuad(SK_ColorYELLOW, gfx::Rect(5, 5)),
Quad::SolidColorQuad(SK_ColorBLUE, gfx::Rect(5, 5))};
std::vector<Pass> expected_passes = {Pass(expected_quads, SurfaceSize())};
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- AggregateAndVerify(expected_passes, {root_surface_id});
+ AggregateAndVerify(expected_passes, {root_surface_id_});
}
// Tests a reference to a valid primary surface and a fallback surface
// with no submitted frame. A SolidColorDrawQuad should be placed in lieu of a
// frame.
TEST_F(SurfaceAggregatorValidSurfaceTest, ValidFallbackWithNoFrame) {
- root_allocator_.GenerateId();
- const LocalSurfaceId empty_local_surface_id =
- root_allocator_.GetCurrentLocalSurfaceId();
- const SurfaceId surface_with_no_frame_id(root_sink_->frame_sink_id(),
- empty_local_surface_id);
+ const TestSurfaceIdAllocator surface_with_no_frame_id(
+ root_sink_->frame_sink_id());
std::vector<Quad> quads = {Quad::SurfaceQuad(
SurfaceRange(surface_with_no_frame_id), SK_ColorYELLOW, gfx::Rect(5, 5),
@@ -2050,72 +1963,65 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ValidFallbackWithNoFrame) {
std::vector<Pass> passes = {Pass(quads, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
std::vector<Quad> expected_quads = {
Quad::SolidColorQuad(SK_ColorYELLOW, gfx::Rect(5, 5)),
};
std::vector<Pass> expected_passes = {Pass(expected_quads, SurfaceSize())};
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- AggregateAndVerify(expected_passes, {root_surface_id});
+ AggregateAndVerify(expected_passes, {root_surface_id_});
}
// Tests a surface quad referencing itself, generating a trivial cycle.
// The quad creating the cycle should be dropped from the final frame.
TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
std::vector<Quad> quads = {
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, root_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, root_surface_id_),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorYELLOW, gfx::Rect(5, 5))};
std::vector<Pass> passes = {Pass(quads, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
std::vector<Quad> expected_quads = {
Quad::SolidColorQuad(SK_ColorYELLOW, gfx::Rect(5, 5))};
std::vector<Pass> expected_passes = {Pass(expected_quads, SurfaceSize())};
- AggregateAndVerify(expected_passes, {root_surface_id});
+ AggregateAndVerify(expected_passes, {root_surface_id_});
}
// Tests a more complex cycle with one intermediate surface.
TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
std::vector<Quad> parent_quads = {
Quad::SolidColorQuad(SK_ColorBLUE, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorCYAN, gfx::Rect(5, 5))};
std::vector<Pass> parent_passes = {Pass(parent_quads, SurfaceSize())};
constexpr float device_scale_factor = 1.0f;
- SubmitCompositorFrame(root_sink_.get(), parent_passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), parent_passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
std::vector<Quad> child_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, root_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, root_surface_id_),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
Quad::SolidColorQuad(SK_ColorMAGENTA, gfx::Rect(5, 5))};
std::vector<Pass> child_passes = {Pass(child_quads, SurfaceSize())};
- SubmitCompositorFrame(child_sink_.get(), child_passes, child_local_surface_id,
+ SubmitCompositorFrame(child_sink_.get(), child_passes,
+ child_surface_id.local_surface_id(),
device_scale_factor);
// The child surface's reference to the root_surface_ will be dropped, so
@@ -2130,18 +2036,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
Quad::SolidColorQuad(SK_ColorMAGENTA, gfx::Rect(5, 5)),
Quad::SolidColorQuad(SK_ColorCYAN, gfx::Rect(5, 5))};
std::vector<Pass> expected_passes = {Pass(expected_quads, SurfaceSize())};
- AggregateAndVerify(expected_passes, {root_surface_id, child_surface_id});
+ AggregateAndVerify(expected_passes, {root_surface_id_, child_surface_id});
}
// Tests that we map render pass IDs from different surfaces into a unified
// namespace and update CompositorRenderPassDrawQuad's id references to match.
TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
CompositorRenderPassId child_pass_id[] = {CompositorRenderPassId{1u},
CompositorRenderPassId{2u}};
@@ -2154,13 +2055,14 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
constexpr float device_scale_factor = 1.0f;
SubmitCompositorFrame(child_sink_.get(), surface_passes,
- child_local_surface_id, device_scale_factor);
+ child_surface_id.local_surface_id(),
+ device_scale_factor);
// Pass IDs from the parent surface may collide with ones from the child.
CompositorRenderPassId parent_pass_id[] = {CompositorRenderPassId{3u},
CompositorRenderPassId{2u}};
std::vector<Quad> parent_quad[2] = {
- {Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ {Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false)},
{Quad::RenderPassQuad(parent_pass_id[0], gfx::Transform(), true)}};
@@ -2168,12 +2070,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
Pass(parent_quad[0], parent_pass_id[0], SurfaceSize()),
Pass(parent_quad[1], parent_pass_id[1], SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), parent_passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), parent_passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -2213,9 +2114,7 @@ void AddSolidColorQuadWithBlendMode(
const gfx::Transform layer_to_target_transform;
const gfx::Rect layer_rect(size);
const gfx::Rect visible_layer_rect(size);
- const gfx::Rect clip_rect(size);
- bool is_clipped = false;
SkColor color = SK_ColorGREEN;
bool are_contents_opaque = SkColorGetA(color) == 0xFF;
float opacity = 1.f;
@@ -2223,8 +2122,8 @@ void AddSolidColorQuadWithBlendMode(
bool force_anti_aliasing_off = false;
auto* sqs = pass->CreateAndAppendSharedQuadState();
sqs->SetAll(layer_to_target_transform, layer_rect, visible_layer_rect,
- mask_filter_info, clip_rect, is_clipped, are_contents_opaque,
- opacity, blend_mode, 0);
+ mask_filter_info, absl::nullopt, are_contents_opaque, opacity,
+ blend_mode, 0);
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
color_quad->SetNew(pass->shared_quad_state_list.back(), visible_layer_rect,
@@ -2268,9 +2167,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
SkBlendMode::kSrcIn, // 5
SkBlendMode::kDstIn, // 6
};
- ParentLocalSurfaceIdAllocator grandchild_allocator;
- ParentLocalSurfaceIdAllocator child_one_allocator;
- ParentLocalSurfaceIdAllocator child_two_allocator;
auto grandchild_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot);
auto child_one_support = std::make_unique<CompositorFrameSinkSupport>(
@@ -2278,11 +2174,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
auto child_two_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId3, kChildIsRoot);
CompositorRenderPassId pass_id{1};
- grandchild_allocator.GenerateId();
- LocalSurfaceId grandchild_local_surface_id =
- grandchild_allocator.GetCurrentLocalSurfaceId();
- SurfaceId grandchild_surface_id(grandchild_support->frame_sink_id(),
- grandchild_local_surface_id);
+ TestSurfaceIdAllocator grandchild_surface_id(
+ grandchild_support->frame_sink_id());
auto grandchild_pass = CompositorRenderPass::Create();
constexpr float device_scale_factor = 1.0f;
@@ -2293,14 +2186,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
transform_to_root_target);
AddSolidColorQuadWithBlendMode(SurfaceSize(), grandchild_pass.get(),
blend_modes[2], gfx::MaskFilterInfo());
- QueuePassAsFrame(std::move(grandchild_pass), grandchild_local_surface_id,
+ QueuePassAsFrame(std::move(grandchild_pass),
+ grandchild_surface_id.local_surface_id(),
device_scale_factor, grandchild_support.get());
- child_one_allocator.GenerateId();
- LocalSurfaceId child_one_local_surface_id =
- child_one_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_one_surface_id(child_one_support->frame_sink_id(),
- child_one_local_surface_id);
+ TestSurfaceIdAllocator child_one_surface_id(
+ child_one_support->frame_sink_id());
auto child_one_pass = CompositorRenderPass::Create();
child_one_pass->SetNew(pass_id, output_rect, damage_rect,
@@ -2312,26 +2203,25 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
grandchild_surface_quad->SetNew(
child_one_pass->shared_quad_state_list.back(), gfx::Rect(SurfaceSize()),
gfx::Rect(SurfaceSize()),
- SurfaceRange(base::nullopt, grandchild_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, grandchild_surface_id), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
AddSolidColorQuadWithBlendMode(SurfaceSize(), child_one_pass.get(),
blend_modes[3], gfx::MaskFilterInfo());
- QueuePassAsFrame(std::move(child_one_pass), child_one_local_surface_id,
- device_scale_factor, child_one_support.get());
+ QueuePassAsFrame(std::move(child_one_pass),
+ child_one_surface_id.local_surface_id(), device_scale_factor,
+ child_one_support.get());
- child_two_allocator.GenerateId();
- LocalSurfaceId child_two_local_surface_id =
- child_two_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_two_surface_id(child_two_support->frame_sink_id(),
- child_two_local_surface_id);
+ TestSurfaceIdAllocator child_two_surface_id(
+ child_two_support->frame_sink_id());
auto child_two_pass = CompositorRenderPass::Create();
child_two_pass->SetNew(pass_id, output_rect, damage_rect,
transform_to_root_target);
AddSolidColorQuadWithBlendMode(SurfaceSize(), child_two_pass.get(),
blend_modes[5], gfx::MaskFilterInfo());
- QueuePassAsFrame(std::move(child_two_pass), child_two_local_surface_id,
- device_scale_factor, child_two_support.get());
+ QueuePassAsFrame(std::move(child_two_pass),
+ child_two_surface_id.local_surface_id(), device_scale_factor,
+ child_two_support.get());
auto root_pass = CompositorRenderPass::Create();
root_pass->SetNew(pass_id, output_rect, damage_rect,
@@ -2344,7 +2234,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
child_one_surface_quad->SetNew(
root_pass->shared_quad_state_list.back(), gfx::Rect(SurfaceSize()),
gfx::Rect(SurfaceSize()),
- SurfaceRange(base::nullopt, child_one_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_one_surface_id), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
AddSolidColorQuadWithBlendMode(SurfaceSize(), root_pass.get(), blend_modes[4],
gfx::MaskFilterInfo());
@@ -2353,17 +2243,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
child_two_surface_quad->SetNew(
root_pass->shared_quad_state_list.back(), gfx::Rect(SurfaceSize()),
gfx::Rect(SurfaceSize()),
- SurfaceRange(base::nullopt, child_two_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_two_surface_id), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
AddSolidColorQuadWithBlendMode(SurfaceSize(), root_pass.get(), blend_modes[6],
gfx::MaskFilterInfo());
- QueuePassAsFrame(std::move(root_pass), root_local_surface_id_,
+ QueuePassAsFrame(std::move(root_pass), root_surface_id_.local_surface_id(),
device_scale_factor, root_sink_.get());
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -2412,10 +2300,6 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
const gfx::MaskFilterInfo kMaskFilterInfoWithRoundedCorners(
gfx::RRectF(0, 0, 100, 100, 2));
- ParentLocalSurfaceIdAllocator child_root_allocator;
- ParentLocalSurfaceIdAllocator child_one_allocator;
- ParentLocalSurfaceIdAllocator child_two_allocator;
- ParentLocalSurfaceIdAllocator child_three_allocator;
auto child_root_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot);
auto child_one_support = std::make_unique<CompositorFrameSinkSupport>(
@@ -2432,26 +2316,21 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
gfx::Transform transform_to_root_target;
// Setup childe three surface.
- child_three_allocator.GenerateId();
- LocalSurfaceId child_three_local_surface_id =
- child_three_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_three_surface_id(child_three_support->frame_sink_id(),
- child_three_local_surface_id);
+ TestSurfaceIdAllocator child_three_surface_id(
+ child_three_support->frame_sink_id());
auto child_three_pass = CompositorRenderPass::Create();
child_three_pass->SetNew(pass_id, output_rect, damage_rect,
transform_to_root_target);
AddSolidColorQuadWithBlendMode(SurfaceSize(), child_three_pass.get(),
SkBlendMode::kSrcOver, gfx::MaskFilterInfo());
- QueuePassAsFrame(std::move(child_three_pass), child_three_local_surface_id,
+ QueuePassAsFrame(std::move(child_three_pass),
+ child_three_surface_id.local_surface_id(),
device_scale_factor, child_three_support.get());
// Setup Child one surface
- child_one_allocator.GenerateId();
- LocalSurfaceId child_one_local_surface_id =
- child_one_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_one_surface_id(child_one_support->frame_sink_id(),
- child_one_local_surface_id);
+ TestSurfaceIdAllocator child_one_surface_id(
+ child_one_support->frame_sink_id());
auto child_one_pass = CompositorRenderPass::Create();
child_one_pass->SetNew(pass_id, output_rect, damage_rect,
@@ -2468,18 +2347,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
child_three_surface_quad->SetNew(
child_three_surface_sqs, gfx::Rect(SurfaceSize()),
gfx::Rect(SurfaceSize()),
- SurfaceRange(base::nullopt, child_three_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_three_surface_id), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
- QueuePassAsFrame(std::move(child_one_pass), child_one_local_surface_id,
- device_scale_factor, child_one_support.get());
+ QueuePassAsFrame(std::move(child_one_pass),
+ child_one_surface_id.local_surface_id(), device_scale_factor,
+ child_one_support.get());
// Setup child two surface
- child_two_allocator.GenerateId();
- LocalSurfaceId child_two_local_surface_id =
- child_two_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_two_surface_id(child_two_support->frame_sink_id(),
- child_two_local_surface_id);
+ TestSurfaceIdAllocator child_two_surface_id(
+ child_two_support->frame_sink_id());
auto child_two_pass = CompositorRenderPass::Create();
child_two_pass->SetNew(pass_id, output_rect, damage_rect,
@@ -2489,15 +2366,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddSolidColorQuadWithBlendMode(SurfaceSize(), child_two_pass.get(),
SkBlendMode::kSrcOver,
kMaskFilterInfoWithRoundedCorners);
- QueuePassAsFrame(std::move(child_two_pass), child_two_local_surface_id,
- device_scale_factor, child_two_support.get());
+ QueuePassAsFrame(std::move(child_two_pass),
+ child_two_surface_id.local_surface_id(), device_scale_factor,
+ child_two_support.get());
// Setup child root surface
- child_root_allocator.GenerateId();
- LocalSurfaceId child_root_local_surface_id =
- child_root_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_root_surface_id(child_root_support->frame_sink_id(),
- child_root_local_surface_id);
+ TestSurfaceIdAllocator child_root_surface_id(
+ child_root_support->frame_sink_id());
auto child_root_pass = CompositorRenderPass::Create();
child_root_pass->SetNew(pass_id, output_rect, damage_rect,
@@ -2511,7 +2386,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
child_root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
child_one_surface_quad->SetNew(
child_one_surface_sqs, gfx::Rect(SurfaceSize()), gfx::Rect(SurfaceSize()),
- SurfaceRange(base::nullopt, child_one_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_one_surface_id), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
// Add child two surface quad
@@ -2522,13 +2397,14 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
child_root_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
child_two_surface_quad->SetNew(
child_two_surface_sqs, gfx::Rect(SurfaceSize()), gfx::Rect(SurfaceSize()),
- SurfaceRange(base::nullopt, child_two_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_two_surface_id), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
// Add solid color quad
AddSolidColorQuadWithBlendMode(SurfaceSize(), child_root_pass.get(),
SkBlendMode::kSrcOver, gfx::MaskFilterInfo());
- QueuePassAsFrame(std::move(child_root_pass), child_root_local_surface_id,
+ QueuePassAsFrame(std::move(child_root_pass),
+ child_root_surface_id.local_surface_id(),
device_scale_factor, child_root_support.get());
auto root_pass = CompositorRenderPass::Create();
@@ -2545,15 +2421,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
child_root_surface_quad->SetNew(
child_root_surface_sqs, gfx::Rect(SurfaceSize()),
gfx::Rect(SurfaceSize()),
- SurfaceRange(base::nullopt, child_root_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_root_surface_id), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
- QueuePassAsFrame(std::move(root_pass), root_local_surface_id_,
+ QueuePassAsFrame(std::move(root_pass), root_surface_id_.local_surface_id(),
device_scale_factor, root_sink_.get());
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -2602,12 +2476,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
auto middle_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot);
// Innermost child surface.
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
{
CompositorRenderPassId child_pass_id[] = {CompositorRenderPassId{1},
CompositorRenderPassId{2}};
@@ -2632,23 +2501,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
auto* child_root_pass = child_frame.render_pass_list[1].get();
auto* child_root_pass_sqs = child_root_pass->shared_quad_state_list.front();
child_root_pass_sqs->quad_to_target_transform.Translate(8, 0);
- child_root_pass_sqs->is_clipped = true;
child_root_pass_sqs->clip_rect = gfx::Rect(0, 0, 5, 5);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
}
// Middle child surface.
- ParentLocalSurfaceIdAllocator middle_allocator;
- middle_allocator.GenerateId();
- LocalSurfaceId middle_local_surface_id =
- middle_allocator.GetCurrentLocalSurfaceId();
- SurfaceId middle_surface_id(middle_support->frame_sink_id(),
- middle_local_surface_id);
+ TestSurfaceIdAllocator middle_surface_id(middle_support->frame_sink_id());
{
std::vector<Quad> middle_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> middle_passes = {
Pass(middle_quads, SurfaceSize()),
@@ -2666,14 +2529,14 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
middle_root_pass->shared_quad_state_list.front();
middle_root_pass_sqs->quad_to_target_transform.Scale(2, 3);
- middle_support->SubmitCompositorFrame(middle_local_surface_id,
+ middle_support->SubmitCompositorFrame(middle_surface_id.local_surface_id(),
std::move(middle_frame));
}
// Root surface.
std::vector<Quad> secondary_quads = {
Quad::SolidColorQuad(1, gfx::Rect(5, 5)),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, middle_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, middle_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false)};
std::vector<Quad> root_quads = {Quad::SolidColorQuad(1, gfx::Rect(5, 5))};
@@ -2696,12 +2559,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
root_frame_quad->visible_rect = gfx::Rect(8, 100);
root_frame.render_pass_list[0]->transform_to_root_target.Translate(10, 5);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -2760,16 +2621,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
<< iter.index();
}
- EXPECT_TRUE(
- aggregated_pass_list[1]->shared_quad_state_list.ElementAt(1)->is_clipped);
+ EXPECT_TRUE(aggregated_pass_list[1]
+ ->shared_quad_state_list.ElementAt(1)
+ ->clip_rect.has_value());
// The second quad in the root pass is aggregated from the child, so its
// clip rect must be transformed by the child's translation/scale and
// clipped be the visible_rects for both children.
- EXPECT_EQ(gfx::Rect(0, 13, 8, 12).ToString(),
- aggregated_pass_list[1]
- ->shared_quad_state_list.ElementAt(1)
- ->clip_rect.ToString());
+ EXPECT_EQ(
+ gfx::Rect(0, 13, 8, 12),
+ aggregated_pass_list[1]->shared_quad_state_list.ElementAt(1)->clip_rect);
}
// This test verifies that in the absence of a primary Surface,
@@ -2783,19 +2644,11 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
auto fallback_child_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId2, kChildIsRoot);
- ParentLocalSurfaceIdAllocator fallback_allocator;
- fallback_allocator.GenerateId();
- LocalSurfaceId fallback_child_local_surface_id =
- fallback_allocator.GetCurrentLocalSurfaceId();
- SurfaceId fallback_child_surface_id(fallback_child_support->frame_sink_id(),
- fallback_child_local_surface_id);
+ TestSurfaceIdAllocator fallback_child_surface_id(
+ fallback_child_support->frame_sink_id());
- ParentLocalSurfaceIdAllocator primary_allocator;
- primary_allocator.GenerateId();
- LocalSurfaceId primary_child_local_surface_id =
- primary_allocator.GetCurrentLocalSurfaceId();
- SurfaceId primary_child_surface_id(primary_child_support->frame_sink_id(),
- primary_child_local_surface_id);
+ TestSurfaceIdAllocator primary_child_surface_id(
+ primary_child_support->frame_sink_id());
constexpr gfx::Size fallback_size(10, 10);
std::vector<Quad> fallback_child_quads = {
@@ -2808,7 +2661,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
constexpr float device_scale_factor_1 = 1.0f;
constexpr float device_scale_factor_2 = 2.0f;
SubmitCompositorFrame(fallback_child_support.get(), fallback_child_passes,
- fallback_child_local_surface_id, device_scale_factor_2);
+ fallback_child_surface_id.local_surface_id(),
+ device_scale_factor_2);
// Try to embed |primary_child_surface_id| and if unavailable, embed
// |fallback_child_surface_id|. The |allow_merge| flag would be set to
@@ -2829,7 +2683,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
fallback_child_support->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor_1);
// There is no CompositorFrame submitted to |primary_child_surface_id|
@@ -2858,48 +2713,49 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
}
expected_passes1.emplace_back(expected_quads1, SurfaceSize());
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(fallback_child_local_surface_id, fallback_size,
- gfx::Rect(fallback_size), next_display_time()))
+ OnAggregatedDamage(fallback_child_surface_id.local_surface_id(),
+ fallback_size, gfx::Rect(fallback_size),
+ next_display_time()))
.Times(1);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(primary_child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(primary_child_surface_id.local_surface_id(), _, _, _))
.Times(0);
// The whole root surface should be damaged because this is the first
// aggregation.
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- gfx::Rect(SurfaceSize()), next_display_time()))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ gfx::Rect(SurfaceSize()), next_display_time()))
.Times(1);
// The primary_surface will not be listed in previously contained surfaces.
AggregateAndVerify(expected_passes1,
- {root_surface_id, fallback_child_surface_id});
+ {root_surface_id_, fallback_child_surface_id});
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
// Submit the fallback again to create some damage then aggregate again.
- fallback_allocator.GenerateId();
- fallback_child_local_surface_id =
- fallback_allocator.GetCurrentLocalSurfaceId();
+ fallback_child_surface_id.Increment();
SubmitCompositorFrame(fallback_child_support.get(), fallback_child_passes,
- fallback_child_local_surface_id, device_scale_factor_2);
+ fallback_child_surface_id.local_surface_id(),
+ device_scale_factor_2);
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(fallback_child_local_surface_id, fallback_size,
- gfx::Rect(fallback_size), next_display_time()))
+ OnAggregatedDamage(fallback_child_surface_id.local_surface_id(),
+ fallback_size, gfx::Rect(fallback_size),
+ next_display_time()))
.Times(1);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(primary_child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(primary_child_surface_id.local_surface_id(), _, _, _))
.Times(0);
// The damage should be equal to whole size of the primary SurfaceDrawQuad.
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
surface_quad_rect, testing::A<base::TimeTicks>()))
.Times(1);
@@ -2911,10 +2767,10 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
if (!AllowMerge())
expected_passes2.emplace_back(fallback_child_quads, fallback_size);
expected_passes2.emplace_back(expected_quads2, SurfaceSize());
- AggregateAndVerify(
- expected_passes2,
- {root_surface_id, SurfaceId(fallback_child_support->frame_sink_id(),
- fallback_child_local_surface_id)});
+ AggregateAndVerify(expected_passes2,
+ {root_surface_id_,
+ SurfaceId(fallback_child_support->frame_sink_id(),
+ fallback_child_surface_id.local_surface_id())});
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
@@ -2927,7 +2783,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// Submit a CompositorFrame to the primary Surface containing a green
// SolidColorDrawQuad.
SubmitCompositorFrame(primary_child_support.get(), primary_child_passes,
- primary_child_local_surface_id, device_scale_factor_2);
+ primary_child_surface_id.local_surface_id(),
+ device_scale_factor_2);
// Now that the primary Surface has a CompositorFrame, we expect
// SurfaceAggregator to embed the primary Surface, and drop the fallback
@@ -2943,22 +2800,24 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(primary_child_local_surface_id, primary_surface_size,
- gfx::Rect(primary_surface_size), next_display_time()))
+ OnAggregatedDamage(primary_child_surface_id.local_surface_id(),
+ primary_surface_size, gfx::Rect(primary_surface_size),
+ next_display_time()))
.Times(1);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(fallback_child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(fallback_child_surface_id.local_surface_id(), _, _, _))
.Times(0);
// The damage of the root should be equal to the damage of the primary
// surface.
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(primary_surface_size), next_display_time()))
.Times(1);
AggregateAndVerify(expected_passes3,
- {root_surface_id, primary_child_surface_id});
+ {root_surface_id_, primary_child_surface_id});
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
}
@@ -2986,17 +2845,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
auto* child_root_pass_sqs = child_root_pass->shared_quad_state_list.front();
child_root_pass_sqs->quad_to_target_transform.Translate(8, 0);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
std::vector<Quad> parent_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false, AllowMerge())};
std::vector<Pass> parent_surface_passes = {
Pass(parent_surface_quads, CompositorRenderPassId{1}, SurfaceSize())};
@@ -3007,17 +2861,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&parent_surface_frame.render_pass_list, parent_surface_passes,
&parent_surface_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator parent_allocator;
- parent_allocator.GenerateId();
- LocalSurfaceId parent_local_surface_id =
- parent_allocator.GetCurrentLocalSurfaceId();
- SurfaceId parent_surface_id(parent_support->frame_sink_id(),
- parent_local_surface_id);
- parent_support->SubmitCompositorFrame(parent_local_surface_id,
+ TestSurfaceIdAllocator parent_surface_id(parent_support->frame_sink_id());
+ parent_support->SubmitCompositorFrame(parent_surface_id.local_surface_id(),
std::move(parent_surface_frame));
std::vector<Quad> root_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, parent_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, parent_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false, AllowMerge())};
std::vector<Quad> root_render_pass_quads = {
Quad::RenderPassQuad(CompositorRenderPassId{1}, gfx::Transform(), true)};
@@ -3036,21 +2885,19 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
root_frame.render_pass_list[0]->damage_rect = gfx::Rect(5, 5, 10, 10);
root_frame.render_pass_list[1]->damage_rect = gfx::Rect(5, 5, 100, 100);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
// Damage rect for first aggregation should contain entire root surface. The
// damage rect reported to the callback is actually 10 pixels taller because
// of the 10-pixel vertical translation of the first RenderPass.
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
size_t expected_num_passes_after_aggregation = AllowMerge() ? 2u : 4u;
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(0, 0, 100, 110), next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation, aggregated_pass_list.size());
@@ -3066,18 +2913,17 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
child_root_pass_sqs->quad_to_target_transform.Translate(8, 0);
child_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// Outer surface didn't change, so a transformed inner damage rect is
// expected.
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
const gfx::Rect expected_damage_rect(10, 20, 10, 10);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- expected_damage_rect, next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -3095,7 +2941,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
->quad_to_target_transform.Translate(0, 10);
root_frame.render_pass_list[0]->damage_rect = gfx::Rect(0, 0, 1, 1);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
}
@@ -3109,18 +2955,16 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
->quad_to_target_transform.Translate(0, 10);
root_frame.render_pass_list[0]->damage_rect = gfx::Rect(1, 1, 1, 1);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
// The root surface was enqueued without being aggregated once, so it should
// be treated as completely damaged.
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -3130,11 +2974,9 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// No Surface changed, so no damage should be given.
{
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
EXPECT_CALL(aggregated_damage_callback, OnAggregatedDamage(_, _, _, _))
.Times(0);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -3144,12 +2986,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// SetFullDamageRectForSurface should cause the entire output to be
// marked as damaged.
{
- aggregator_.SetFullDamageForSurface(root_surface_id);
+ aggregator_.SetFullDamageForSurface(root_surface_id_);
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -3182,17 +3024,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
auto* child_root_pass_sqs = child_root_pass->shared_quad_state_list.front();
child_root_pass_sqs->quad_to_target_transform.Translate(8, 0);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
std::vector<Quad> parent_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false, AllowMerge())};
std::vector<Pass> parent_surface_passes = {
Pass(parent_surface_quads, CompositorRenderPassId{1}, SurfaceSize())};
@@ -3203,17 +3040,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&parent_surface_frame.render_pass_list, parent_surface_passes,
&parent_surface_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator parent_allocator;
- parent_allocator.GenerateId();
- LocalSurfaceId parent_local_surface_id =
- parent_allocator.GetCurrentLocalSurfaceId();
- SurfaceId parent_surface_id(parent_support->frame_sink_id(),
- parent_local_surface_id);
- parent_support->SubmitCompositorFrame(parent_local_surface_id,
+ TestSurfaceIdAllocator parent_surface_id(parent_support->frame_sink_id());
+ parent_support->SubmitCompositorFrame(parent_surface_id.local_surface_id(),
std::move(parent_surface_frame));
std::vector<Quad> root_surface_quads = {
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, parent_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, parent_surface_id),
SK_ColorWHITE, gfx::Rect(50, 50),
/*stretch_content_to_fill_bounds=*/true, AllowMerge())};
std::vector<Quad> root_render_pass_quads = {
@@ -3223,20 +3055,18 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
Pass(root_surface_quads, CompositorRenderPassId{1}, SurfaceSize()),
Pass(root_render_pass_quads, CompositorRenderPassId{2}, SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
- 1.0f);
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(), 1.0f);
// Damage rect for first aggregation should be exactly the entire root
// surface.
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
size_t expected_num_passes_after_aggregation = AllowMerge() ? 2u : 4u;
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation, aggregated_pass_list.size());
@@ -3250,20 +3080,19 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
auto* child_root_pass = child_frame.render_pass_list[0].get();
child_root_pass->damage_rect = gfx::Rect(10, 20, 20, 30);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// Outer surface didn't change, so transformed inner damage rect should be
// used. Since the child surface is stretching to fit the outer surface
// which is half the size, we end up with a damage rect that is half the
// size of the child surface.
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
const gfx::Rect expected_damage_rect(5, 10, 10, 15);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- expected_damage_rect, next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -3295,17 +3124,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
auto* child_root_pass_sqs = child_root_pass->shared_quad_state_list.front();
child_root_pass_sqs->quad_to_target_transform.Translate(8, 0);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
std::vector<Quad> parent_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false, AllowMerge())};
std::vector<Pass> parent_surface_passes = {
Pass(parent_surface_quads, CompositorRenderPassId{1}, SurfaceSize())};
@@ -3316,17 +3140,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&parent_surface_frame.render_pass_list, parent_surface_passes,
&parent_surface_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator parent_allocator;
- parent_allocator.GenerateId();
- LocalSurfaceId parent_local_surface_id =
- parent_allocator.GetCurrentLocalSurfaceId();
- SurfaceId parent_surface_id(parent_support->frame_sink_id(),
- parent_local_surface_id);
- parent_support->SubmitCompositorFrame(parent_local_surface_id,
+ TestSurfaceIdAllocator parent_surface_id(parent_support->frame_sink_id());
+ parent_support->SubmitCompositorFrame(parent_surface_id.local_surface_id(),
std::move(parent_surface_frame));
std::vector<Quad> root_surface_quads = {
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, parent_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, parent_surface_id),
SK_ColorWHITE, gfx::Rect(200, 200),
/*stretch_content_to_fill_bounds=*/true, AllowMerge())};
std::vector<Quad> root_render_pass_quads = {
@@ -3336,20 +3155,18 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
Pass(root_surface_quads, CompositorRenderPassId{1}, SurfaceSize()),
Pass(root_render_pass_quads, CompositorRenderPassId{2}, SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
- 1.0f);
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(), 1.0f);
// Damage rect for first aggregation should contain entire root surface. The
// damage rect reported to the callback is actually 200x200, larger than the
// root surface size, because the root's Quad is 200x200.
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
size_t expected_num_passes_after_aggregation = AllowMerge() ? 2u : 4u;
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(0, 0, 200, 200), next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation, aggregated_pass_list.size());
@@ -3363,20 +3180,19 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
auto* child_root_pass = child_frame.render_pass_list[0].get();
child_root_pass->damage_rect = gfx::Rect(10, 15, 20, 30);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// Outer surface didn't change, so transformed inner damage rect should be
// used. Since the child surface is stretching to fit the outer surface
// which is twice the size, we end up with a damage rect that is double the
// size of the child surface.
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
const gfx::Rect expected_damage_rect(20, 30, 40, 60);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- expected_damage_rect, next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -3398,13 +3214,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SwitchSurfaceDamage) {
root_frame.render_pass_list[0]->damage_rect = gfx::Rect(5, 5, 100, 100);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
{
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -3415,10 +3229,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SwitchSurfaceDamage) {
gfx::Rect(SurfaceSize())));
}
- LocalSurfaceId second_root_local_surface_id =
- root_allocator_.GetCurrentLocalSurfaceId();
- SurfaceId second_root_surface_id(root_sink_->frame_sink_id(),
- second_root_local_surface_id);
+ TestSurfaceIdAllocator second_root_surface_id(root_sink_->frame_sink_id());
{
std::vector<Quad> root_render_pass_quads = {
Quad::SolidColorQuad(1, gfx::Rect(5, 5))};
@@ -3432,7 +3243,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SwitchSurfaceDamage) {
root_frame.render_pass_list[0]->damage_rect = gfx::Rect(1, 2, 3, 4);
- root_sink_->SubmitCompositorFrame(second_root_local_surface_id,
+ root_sink_->SubmitCompositorFrame(second_root_surface_id.local_surface_id(),
std::move(root_frame));
}
{
@@ -3485,11 +3296,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SurfaceDamageSameFrameSinkId) {
CompositorFrame frame = MakeCompositorFrameFromSurfaceRanges(
{SurfaceRange(fallback_surface_id, primary_surface_id)});
- root_sink_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame));
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
+ std::move(frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// |id1| is before the fallback id so it shouldn't damage the display.
EXPECT_FALSE(aggregator_.NotifySurfaceDamageAndCheckForDisplayDamage(
@@ -3546,11 +3356,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SurfaceDamageDifferentFrameSinkId) {
CompositorFrame frame = MakeCompositorFrameFromSurfaceRanges(
{SurfaceRange(fallback_surface_id, primary_surface_id)});
- root_sink_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame));
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
+ std::move(frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// |id1| is before the fallback id so it shouldn't damage the display.
EXPECT_FALSE(aggregator_.NotifySurfaceDamageAndCheckForDisplayDamage(
@@ -3591,12 +3400,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SurfaceDamagePrimarySurfaceOnly) {
LocalSurfaceId id4 = allocator2.GetCurrentLocalSurfaceId();
CompositorFrame frame = MakeCompositorFrameFromSurfaceRanges(
- {SurfaceRange(base::nullopt, primary_surface_id)});
- root_sink_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame));
+ {SurfaceRange(absl::nullopt, primary_surface_id)});
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
+ std::move(frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// |id1| is inside the range so it should damage the display.
EXPECT_TRUE(aggregator_.NotifySurfaceDamageAndCheckForDisplayDamage(
@@ -3644,11 +3452,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
CompositorFrame frame =
MakeCompositorFrameFromSurfaceRanges({SurfaceRange(surface_id)});
- root_sink_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame));
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
+ std::move(frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// |id1| is before the fallback id so it shouldn't damage the display.
EXPECT_FALSE(aggregator_.NotifySurfaceDamageAndCheckForDisplayDamage(
@@ -3693,13 +3500,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
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.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// The frame of the root surface has two render passes.
@@ -3714,7 +3516,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// on this quad.
Quad::RenderPassQuad(CompositorRenderPassId{1}, gfx::Transform(),
/*intersects_damage_under=*/false),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(90, 90),
/*stretch_content_to_fill_bounds=*/false,
AllowMerge())};
@@ -3730,23 +3532,21 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(20, 30);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
size_t expected_num_passes_after_aggregation = AllowMerge() ? 2u : 3u;
// First aggregation.
{
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
- EXPECT_CALL(
- aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- gfx::Rect(child_surface_size), next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(
+ child_surface_id.local_surface_id(), child_surface_size,
+ gfx::Rect(child_surface_size), next_display_time()));
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
@@ -3776,18 +3576,20 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
->quad_to_target_transform.Translate(20, 30);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), _, _, _))
.Times(0);
// No damage is expected from the child surface.
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(child_surface_id.local_surface_id(), _, _, _))
.Times(0);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -3810,20 +3612,22 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
auto* child_root_pass = child_frame.render_pass_list[0].get();
child_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// Both the root and child surface should expect the damage from the child
// surface (10,10 10x10)
const gfx::Rect expected_damage_rect(10, 10, 10, 10);
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- expected_damage_rect, next_display_time()));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- expected_damage_rect, next_display_time()));
+ OnAggregatedDamage(child_surface_id.local_surface_id(),
+ child_surface_size, expected_damage_rect,
+ next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -3845,20 +3649,22 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
auto* child_root_pass = child_frame.render_pass_list[0].get();
child_root_pass->damage_rect = gfx::Rect(60, 60, 10, 10);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// Both the root and child surface should expect the damage from the child
// surface (60,60 10x10)
const gfx::Rect expected_damage_rect(60, 60, 10, 10);
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- expected_damage_rect, next_display_time()));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- expected_damage_rect, next_display_time()));
+ OnAggregatedDamage(child_surface_id.local_surface_id(),
+ child_surface_size, expected_damage_rect,
+ next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -3913,13 +3719,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
&child_frame.metadata.referenced_surfaces);
child_frame.render_pass_list.back()->damage_rect = gfx::Rect();
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// The second surface will be embedded into a surface quad on the root pass of
@@ -3936,13 +3737,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&second_surface_frame.render_pass_list, second_surface_passes,
&second_surface_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator second_allocator;
- second_allocator.GenerateId();
- LocalSurfaceId second_local_surface_id =
- second_allocator.GetCurrentLocalSurfaceId();
- SurfaceId second_surface_id(second_support->frame_sink_id(),
- second_local_surface_id);
- second_support->SubmitCompositorFrame(second_local_surface_id,
+ TestSurfaceIdAllocator second_surface_id(second_support->frame_sink_id());
+ second_support->SubmitCompositorFrame(second_surface_id.local_surface_id(),
std::move(second_surface_frame));
// The frame of the root surface has one single render pass with a surface
@@ -3951,10 +3747,10 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
std::vector<Quad> render_pass_quads = {
// The |allow_merge| flag of the surface quad would be set to true/false
// according to the parameter of the test.
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(90, 90),
/*stretch_content_to_fill_bounds=*/false, AllowMerge()),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, second_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, second_surface_id),
SK_ColorWHITE, gfx::Rect(second_surface_size),
/*stretch_content_to_fill_bounds=*/false,
/*allow_merge=*/false)};
@@ -3968,31 +3764,29 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
root_frame.render_pass_list.back()
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(20, 30);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
size_t expected_num_passes_after_aggregation = AllowMerge() ? 3u : 4u;
// First aggregation.
{
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
// The damage for the first aggregation should contain
// the entire child surface (0,0 60x60).
gfx::Rect expected_child_damage_rect = gfx::Rect(child_surface_size);
- EXPECT_CALL(
- aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- expected_child_damage_rect, next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(second_local_surface_id, second_surface_size,
- gfx::Rect(second_surface_size),
- next_display_time()));
+ OnAggregatedDamage(
+ child_surface_id.local_surface_id(), child_surface_size,
+ expected_child_damage_rect, next_display_time()));
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(
+ second_surface_id.local_surface_id(), second_surface_size,
+ gfx::Rect(second_surface_size), next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
@@ -4027,22 +3821,25 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
child_frame.render_pass_list.back()->damage_rect = gfx::Rect();
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), _, _, _))
.Times(0);
// There should be no damage on any surface.
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(child_surface_id.local_surface_id(), _, _, _))
.Times(0);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(second_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(second_surface_id.local_surface_id(), _, _, _))
.Times(0);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -4067,22 +3864,25 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
second_surface_frame.render_pass_list[0].get();
second_surface_root_pass->damage_rect = gfx::Rect(10, 10, 10, 10);
- second_support->SubmitCompositorFrame(second_local_surface_id,
+ second_support->SubmitCompositorFrame(second_surface_id.local_surface_id(),
std::move(second_surface_frame));
const 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()));
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
// There is no damage on the child surface.
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(child_surface_id.local_surface_id(), _, _, _))
.Times(0);
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(second_local_surface_id, second_surface_size,
- expected_damage_rect, next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ OnAggregatedDamage(second_surface_id.local_surface_id(),
+ second_surface_size, expected_damage_rect,
+ next_display_time()));
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -4111,22 +3911,25 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
second_surface_frame.render_pass_list[0].get();
second_surface_root_pass->damage_rect = gfx::Rect(60, 60, 10, 10);
- second_support->SubmitCompositorFrame(second_local_surface_id,
+ second_support->SubmitCompositorFrame(second_surface_id.local_surface_id(),
std::move(second_surface_frame));
const gfx::Rect expected_damage_rect(60, 60, 10, 10);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- expected_damage_rect, next_display_time()));
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
// There is no damage on the child surface.
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(child_surface_id.local_surface_id(), _, _, _))
.Times(0);
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(second_local_surface_id, second_surface_size,
- expected_damage_rect, next_display_time()));
+ OnAggregatedDamage(second_surface_id.local_surface_id(),
+ second_surface_size, expected_damage_rect,
+ next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -4176,18 +3979,13 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
auto* child_root_pass_sqs = child_root_pass->shared_quad_state_list.front();
child_root_pass_sqs->quad_to_target_transform.Translate(8, 0);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
constexpr gfx::Size parent_surface_size(90, 90);
std::vector<Quad> parent_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false, AllowMerge())};
std::vector<Pass> parent_surface_passes = {Pass(
parent_surface_quads, CompositorRenderPassId{1}, parent_surface_size)};
@@ -4198,13 +3996,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&parent_surface_frame.render_pass_list, parent_surface_passes,
&parent_surface_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator parent_allocator;
- parent_allocator.GenerateId();
- LocalSurfaceId parent_local_surface_id =
- parent_allocator.GetCurrentLocalSurfaceId();
- SurfaceId parent_surface_id(parent_support->frame_sink_id(),
- parent_local_surface_id);
- parent_support->SubmitCompositorFrame(parent_local_surface_id,
+ TestSurfaceIdAllocator parent_surface_id(parent_support->frame_sink_id());
+ parent_support->SubmitCompositorFrame(parent_surface_id.local_surface_id(),
std::move(parent_surface_frame));
std::vector<Quad> render_pass_1_quads = {
@@ -4217,7 +4010,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// damage of the SurfaceDrawQuad under it.
Quad::RenderPassQuad(CompositorRenderPassId{1}, gfx::Transform(),
/*intersects_damage_under=*/false),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, parent_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, parent_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false,
AllowMerge())};
@@ -4236,27 +4029,25 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
root_frame.render_pass_list[0]->damage_rect = gfx::Rect(5, 5, 10, 10);
root_frame.render_pass_list[1]->damage_rect = gfx::Rect(5, 5, 100, 100);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
size_t expected_num_passes_after_aggregation = AllowMerge() ? 2u : 4u;
{
// First aggregation.
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
- EXPECT_CALL(
- aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- gfx::Rect(child_surface_size), next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(parent_local_surface_id, parent_surface_size,
- gfx::Rect(parent_surface_size),
- next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ OnAggregatedDamage(
+ child_surface_id.local_surface_id(), child_surface_size,
+ gfx::Rect(child_surface_size), next_display_time()));
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(
+ parent_surface_id.local_surface_id(), parent_surface_size,
+ gfx::Rect(parent_surface_size), next_display_time()));
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
// After aggregation, there should be two render passes with merging
@@ -4281,18 +4072,21 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), _, _, _))
.Times(0);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(child_surface_id.local_surface_id(), _, _, _))
.Times(0);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(parent_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(parent_surface_id.local_surface_id(), _, _, _))
.Times(0);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -4317,23 +4111,26 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
child_root_pass_sqs->quad_to_target_transform.Translate(8, 0);
child_root_pass->damage_rect = gfx::Rect(1, 1, 10, 10);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// Outer surface didn't change, so a transformed inner damage rect is
// expected.
const gfx::Rect expected_damage_rect(1, 1, 10, 10);
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- expected_damage_rect, next_display_time()));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- expected_damage_rect, next_display_time()));
+ OnAggregatedDamage(child_surface_id.local_surface_id(),
+ child_surface_size, expected_damage_rect,
+ next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(parent_local_surface_id, parent_surface_size,
- expected_damage_rect, next_display_time()));
+ OnAggregatedDamage(parent_surface_id.local_surface_id(),
+ parent_surface_size, expected_damage_rect,
+ next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -4355,19 +4152,22 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), _, _, _))
.Times(0);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(child_surface_id.local_surface_id(), _, _, _))
.Times(0);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(parent_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(parent_surface_id.local_surface_id(), _, _, _))
.Times(0);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -4404,13 +4204,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
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.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// The root surface consists of four render passes. In top-down order, they
@@ -4433,7 +4228,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
gfx::Transform translation2;
translation2.Translate(2.f, 2.f);
std::vector<Quad> root_quads[] = {
- {Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ {Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false,
AllowMerge())},
@@ -4448,8 +4243,6 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
Pass(root_quads[1], CompositorRenderPassId{2}, SurfaceSize()),
Pass(root_quads[2], CompositorRenderPassId{3}, SurfaceSize())};
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
size_t expected_num_passes_after_aggregation = AllowMerge() ? 4u : 5u;
{
// First aggregation.
@@ -4457,7 +4250,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
// Damage rect for the first aggregation would contain entire root surface
@@ -4465,16 +4258,16 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// (0,0 230x250) from RP3, a total of (0,0 230x250).
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(0, 0, 230, 250), next_display_time()));
// The child surface is embedded twice so the callback is called twice.
- EXPECT_CALL(
- aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- gfx::Rect(child_surface_size), next_display_time()))
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(
+ child_surface_id.local_surface_id(), child_surface_size,
+ gfx::Rect(child_surface_size), next_display_time()))
.Times(2);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_frame.render_pass_list.size());
@@ -4495,16 +4288,18 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), _, _, _))
.Times(0);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(child_surface_id.local_surface_id(), _, _, _))
.Times(0);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -4527,7 +4322,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
child_frame_2.render_pass_list.back()->damage_rect =
gfx::Rect(10, 10, 10, 10);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame_2));
// The child surface is embedded twice in the root surface, so its damage
@@ -4546,15 +4341,16 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// which is (10,10 60x80).
constexpr gfx::Rect expected_damage_rect(10, 10, 60, 80);
constexpr gfx::Rect expected_child_damage_rect(10, 10, 10, 10);
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- expected_damage_rect, next_display_time()));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- gfx::Rect(expected_child_damage_rect),
- next_display_time()))
+ OnAggregatedDamage(
+ child_surface_id.local_surface_id(), child_surface_size,
+ gfx::Rect(expected_child_damage_rect), next_display_time()))
.Times(2);
- auto aggregated_frame_2 = AggregateFrame(root_surface_id);
+ auto aggregated_frame_2 = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto* quad_to_test =
@@ -4574,7 +4370,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
child_frame_2.render_pass_list.back()->damage_rect =
gfx::Rect(10, 10, 10, 10);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame_2));
// The total translation of the quad with |intersects_damage_under| to be
@@ -4587,20 +4383,21 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
&root_frame.metadata.referenced_surfaces);
root_frame.render_pass_list.back()->damage_rect = gfx::Rect();
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
constexpr gfx::Rect expected_damage_rect(10, 10, 60, 80);
constexpr gfx::Rect expected_child_damage_rect(10, 10, 10, 10);
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- expected_damage_rect, next_display_time()));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- gfx::Rect(expected_child_damage_rect),
- next_display_time()))
+ OnAggregatedDamage(
+ child_surface_id.local_surface_id(), child_surface_size,
+ gfx::Rect(expected_child_damage_rect), next_display_time()))
.Times(2);
- auto aggregated_frame_2 = AggregateFrame(root_surface_id);
+ auto aggregated_frame_2 = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
// The unioned damage rect from under |quad_to_test| (10,10 60x80)
@@ -4656,13 +4453,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
child_frame.render_pass_list[1]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// The frame of the root surface has one single render pass with a surface
@@ -4670,7 +4462,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
std::vector<Quad> render_pass_quads = {
// The |allow_merge| flag of the surface quad would be set to true/false
// according to the parameter of the test.
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(90, 90),
/*stretch_content_to_fill_bounds=*/false,
AllowMerge())};
@@ -4685,17 +4477,15 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
root_frame.render_pass_list.back()
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(5, 5);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
size_t expected_num_passes_after_aggregation = AllowMerge() ? 3u : 4u;
// First aggregation.
{
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(SurfaceSize()), next_display_time()));
// In the local space of the root pass of the child frame, the second render
// pass (20,30 60x60) has a blur backdrop filter. It expands the damage from
@@ -4707,12 +4497,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// 100x100), so the child surface has a damage rect of (-5,-5 100x100).
gfx::Rect expected_child_damage_rect =
AllowMerge() ? gfx::Rect(-5, -5, 100, 100) : gfx::Rect(0, 0, 80, 90);
- EXPECT_CALL(
- aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- expected_child_damage_rect, next_display_time()));
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(
+ child_surface_id.local_surface_id(), child_surface_size,
+ expected_child_damage_rect, next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
@@ -4729,11 +4519,11 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(0, 0, 10, 20), next_display_time()));
// 1) Without merging, there is no damage on the child surface.
// 2) With merging, in the local space of the root pass of the child frame,
@@ -4741,11 +4531,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// However, the damage passed from parent surface and transformed into the
// same local space is (-5,-5 10x20), so this damage is not expanded. The
// child surface doesn't have any damage.
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(child_surface_id.local_surface_id(), _, _, _))
.Times(0);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -4796,13 +4587,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
child_frame.render_pass_list[1]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// The frame of the root surface has one single render pass with a surface
@@ -4810,7 +4596,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
std::vector<Quad> render_pass_quads = {
// The |allow_merge| flag of the surface quad would be set to true/false
// according to the parameter of the test.
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(90, 90),
/*stretch_content_to_fill_bounds=*/true, AllowMerge())};
@@ -4824,11 +4610,9 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
root_frame.render_pass_list.back()
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(5, 5);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
size_t expected_num_passes_after_aggregation = AllowMerge() ? 3u : 4u;
// First aggregation.
{
@@ -4842,10 +4626,10 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// 68x68). The backdrop filter expands this damage to (-4,-4, 84x94).
gfx::Rect expected_child_damage_rect =
AllowMerge() ? gfx::Rect(-4, -4, 84, 94) : gfx::Rect(0, 0, 80, 90);
- EXPECT_CALL(
- aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- expected_child_damage_rect, next_display_time()));
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(
+ child_surface_id.local_surface_id(), child_surface_size,
+ expected_child_damage_rect, next_display_time()));
// 1) Without merging, child surface damage (0,0 80x90) stretches to (0,0
// 120x135), and transformed to root surface as (5,5 120x135), unions root
@@ -4856,10 +4640,10 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AllowMerge() ? gfx::Rect(-1, -1, 126, 141) : gfx::Rect(0, 0, 125, 140);
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
expected_root_damage_rect, next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
@@ -4877,11 +4661,11 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
root_frame.render_pass_list.back()
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(5, 5);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(0, 0, 10, 20), next_display_time()));
// 1) Without merging, there is no damage on the child surface.
// 2) With merging, in the local space of the root pass of the child frame,
@@ -4889,11 +4673,12 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// However, the damage passed from parent surface and transformed into the
// same local space is (-4,-4 8x14), so this damage is not expanded. The
// child surface doesn't have any damage.
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, _, _, _))
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(child_surface_id.local_surface_id(), _, _, _))
.Times(0);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(expected_num_passes_after_aggregation,
aggregated_pass_list.size());
@@ -4911,11 +4696,7 @@ class SurfaceAggregatorPartialSwapTest
// Tests that quads outside the damage rect are ignored.
TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
- ParentLocalSurfaceIdAllocator allocator;
- allocator.GenerateId();
- LocalSurfaceId child_local_surface_id = allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
constexpr float device_scale_factor = 1.0f;
// The child surface has three quads, one with a visible rect of 13,13 4x4 and
@@ -4958,14 +4739,14 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
child_pass_list[2]->quad_list.ElementAt(0)->visible_rect =
gfx::Rect(0, 0, 2, 2);
- SubmitPassListAsFrame(child_sink_.get(), child_local_surface_id,
- &child_pass_list, std::move(referenced_surfaces),
- device_scale_factor);
+ SubmitPassListAsFrame(child_sink_.get(),
+ child_surface_id.local_surface_id(), &child_pass_list,
+ std::move(referenced_surfaces), device_scale_factor);
}
{
std::vector<Quad> root_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
@@ -4979,14 +4760,12 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
->quad_to_target_transform.Translate(10, 10);
root_pass->damage_rect = gfx::Rect(0, 0, 1, 1);
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
}
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -5001,7 +4780,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
// Create a root surface with a smaller damage rect.
{
std::vector<Quad> root_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
@@ -5014,13 +4793,13 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
root_pass->shared_quad_state_list.front()
->quad_to_target_transform.Translate(10, 10);
root_pass->damage_rect = gfx::Rect(10, 10, 2, 2);
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
}
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -5066,13 +4845,13 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
child_root_pass->copy_requests.push_back(
CopyOutputRequest::CreateStubForTesting());
child_root_pass->damage_rect = gfx::Rect();
- SubmitPassListAsFrame(child_sink_.get(), child_local_surface_id,
- &child_pass_list, std::move(referenced_surfaces),
- device_scale_factor);
+ SubmitPassListAsFrame(child_sink_.get(),
+ child_surface_id.local_surface_id(), &child_pass_list,
+ std::move(referenced_surfaces), device_scale_factor);
}
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -5092,7 +4871,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
}
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
// There were no changes since last aggregation, so output should be empty
@@ -5111,7 +4890,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
CompositorRenderPassId{2},
CompositorRenderPassId{3}};
std::vector<Quad> root_quads1 = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Quad> root_quads2 = {
Quad::RenderPassQuad(root_pass_ids[0], gfx::Transform(), true)};
@@ -5141,11 +4920,11 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
// from the filter_pass and the first render pass draw quad will not be
// drawn.
root_pass->damage_rect = gfx::Rect(20, 20, 2, 2);
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -5174,7 +4953,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
CompositorRenderPassId{2},
CompositorRenderPassId{3}};
std::vector<Quad> root_quads1 = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Quad> root_quads2 = {
Quad::RenderPassQuad(root_pass_ids[0], gfx::Transform(), true)};
@@ -5203,11 +4982,11 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
// -30, 65, 65)), but not with filter_pass quad itself (0, 0, 5, 5). The
// first render pass will be drawn.
root_pass->damage_rect = gfx::Rect(20, 20, 2, 2);
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -5239,7 +5018,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
};
std::vector<Quad> root_quads2 = {
Quad::RenderPassQuad(root_pass_ids[0], gfx::Transform(), true),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
@@ -5257,13 +5036,13 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
pass->backdrop_filters.Append(
cc::FilterOperation::CreateOpacityFilter(0.5f));
root_pass->damage_rect = gfx::Rect(10, 10, 2, 2);
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
}
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(3u, aggregated_pass_list.size());
@@ -5309,9 +5088,10 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
gfx::Rect(0, 0, 2, 2);
child_pass_list[1]->damage_rect = gfx::Rect(-2, -2, 3, 3);
- SubmitPassListAsFrame(
- child_sink_.get(), child_local_surface_id, &child_pass_list,
- std::move(child_referenced_surfaces), device_scale_factor);
+ SubmitPassListAsFrame(child_sink_.get(),
+ child_surface_id.local_surface_id(), &child_pass_list,
+ std::move(child_referenced_surfaces),
+ device_scale_factor);
CompositorRenderPassId root_pass_ids[] = {CompositorRenderPassId{1},
CompositorRenderPassId{2}};
@@ -5321,7 +5101,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
};
std::vector<Quad> root_quads2 = {
Quad::RenderPassQuad(root_pass_ids[0], gfx::Transform(), true),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
@@ -5339,13 +5119,13 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
pass_with_filter->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(2));
root_pass->damage_rect = gfx::Rect();
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
}
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -5393,9 +5173,10 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
gfx::Rect(0, 0, 2, 2);
child_pass_list[1]->damage_rect = gfx::Rect(1, 1, 3, 3);
- SubmitPassListAsFrame(
- child_sink_.get(), child_local_surface_id, &child_pass_list,
- std::move(child_referenced_surfaces), device_scale_factor);
+ SubmitPassListAsFrame(child_sink_.get(),
+ child_surface_id.local_surface_id(), &child_pass_list,
+ std::move(child_referenced_surfaces),
+ device_scale_factor);
CompositorRenderPassId root_pass_ids[] = {CompositorRenderPassId{1},
CompositorRenderPassId{2}};
@@ -5405,7 +5186,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
};
std::vector<Quad> root_quads2 = {
Quad::RenderPassQuad(root_pass_ids[0], gfx::Transform(), true),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
@@ -5423,13 +5204,13 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
pass_with_filter->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(2));
root_pass->damage_rect = gfx::Rect();
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
}
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -5451,11 +5232,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, IgnoreOutside) {
}
TEST_F(SurfaceAggregatorPartialSwapTest, ExpandByTargetDamage) {
- ParentLocalSurfaceIdAllocator allocator;
- allocator.GenerateId();
- LocalSurfaceId child_local_surface_id = allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
constexpr float device_scale_factor = 1.0f;
// The child surface has one quad.
@@ -5470,14 +5247,14 @@ TEST_F(SurfaceAggregatorPartialSwapTest, ExpandByTargetDamage) {
std::vector<SurfaceRange> referenced_surfaces;
AddPasses(&child_pass_list, child_passes, &referenced_surfaces);
- SubmitPassListAsFrame(child_sink_.get(), child_local_surface_id,
- &child_pass_list, std::move(referenced_surfaces),
- device_scale_factor);
+ SubmitPassListAsFrame(child_sink_.get(),
+ child_surface_id.local_surface_id(), &child_pass_list,
+ std::move(referenced_surfaces), device_scale_factor);
}
{
std::vector<Quad> root_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(SurfaceSize()), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
@@ -5487,14 +5264,12 @@ TEST_F(SurfaceAggregatorPartialSwapTest, ExpandByTargetDamage) {
AddPasses(&root_pass_list, root_passes, &referenced_surfaces);
// No damage, this is the first frame submitted, so all quads should be
// produced.
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
}
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -5508,7 +5283,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, ExpandByTargetDamage) {
// This time the damage should be smaller.
{
std::vector<Quad> root_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(SurfaceSize()), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
@@ -5519,13 +5294,13 @@ TEST_F(SurfaceAggregatorPartialSwapTest, ExpandByTargetDamage) {
auto* root_pass = root_pass_list[0].get();
root_pass->damage_rect = gfx::Rect(10, 10, 2, 2);
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
}
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -5541,7 +5316,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, ExpandByTargetDamage) {
// surface.
{
std::vector<Quad> root_quads = {
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(SurfaceSize()), false)};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
@@ -5552,7 +5327,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, ExpandByTargetDamage) {
auto* root_pass = root_pass_list[0].get();
root_pass->damage_rect = gfx::Rect(10, 10, 2, 2);
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
}
@@ -5562,7 +5337,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, ExpandByTargetDamage) {
// root render pass damage.
{
gfx::Rect target_damage(0, 0, 1, 1);
- auto aggregated_frame = AggregateFrame(root_surface_id, target_damage);
+ auto aggregated_frame = AggregateFrame(root_surface_id_, target_damage);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(1u, aggregated_pass_list.size());
@@ -5600,10 +5375,6 @@ class SurfaceAggregatorWithResourcesTest : public testing::Test,
support->OnBeginFrame(args);
}
- void EnableDocumentTransitions(CompositorFrameSinkSupport* support) {
- support->document_transitions_enabled_ = true;
- }
-
protected:
ServerSharedBitmapManager shared_bitmap_manager_;
FrameSinkManagerImpl manager_;
@@ -5624,7 +5395,7 @@ CompositorFrame BuildCompositorFrameWithResources(
if (child_id.is_valid()) {
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetNew(sqs, gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1),
- SurfaceRange(base::nullopt, child_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_id), SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
}
@@ -5823,15 +5594,9 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) {
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot);
auto child_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot);
- LocalSurfaceId root_local_surface_id(7u, kArbitraryToken);
- SurfaceId root_surface_id(root_support->frame_sink_id(),
- root_local_surface_id);
- LocalSurfaceId middle_local_surface_id(8u, kArbitraryToken2);
- SurfaceId middle_surface_id(middle_support->frame_sink_id(),
- middle_local_surface_id);
- LocalSurfaceId child_local_surface_id(9u, kArbitraryToken3);
- SurfaceId child_surface_id(child_support->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator root_surface_id(root_support->frame_sink_id());
+ TestSurfaceIdAllocator middle_surface_id(middle_support->frame_sink_id());
+ TestSurfaceIdAllocator child_surface_id(child_support->frame_sink_id());
std::vector<ResourceId> ids = {ResourceId(14), ResourceId(15),
ResourceId(16)};
@@ -5898,7 +5663,7 @@ TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) {
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetNew(sqs, gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1),
- SurfaceRange(base::nullopt, surface1_id),
+ SurfaceRange(absl::nullopt, surface1_id),
SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false);
pass->copy_requests.push_back(CopyOutputRequest::CreateStubForTesting());
@@ -5976,9 +5741,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ColorSpaceTestWin) {
// converting to SCRGB-linear.
aggregator_.SetDisplayColorSpaces(display_color_spaces);
{
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId surface_id(root_sink_->frame_sink_id(), root_local_surface_id_);
+ SurfaceId surface_id(root_sink_->frame_sink_id(),
+ root_surface_id_.local_surface_id());
auto aggregated_frame = AggregateFrame(surface_id);
@@ -6003,9 +5770,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ColorSpaceTestWin) {
// converting to HDR10.
passes[1].has_transparent_background = false;
{
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId surface_id(root_sink_->frame_sink_id(), root_local_surface_id_);
+ SurfaceId surface_id(root_sink_->frame_sink_id(),
+ root_surface_id_.local_surface_id());
auto aggregated_frame = AggregateFrame(surface_id);
@@ -6044,9 +5813,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ColorSpaceTestWin) {
passes[1].has_transparent_background = false;
aggregator_.SetDisplayColorSpaces(display_color_spaces);
{
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId surface_id(root_sink_->frame_sink_id(), root_local_surface_id_);
+ SurfaceId surface_id(root_sink_->frame_sink_id(),
+ root_surface_id_.local_surface_id());
auto aggregated_frame = AggregateFrame(surface_id);
@@ -6065,9 +5836,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ColorSpaceTestWin) {
// color conversion pass.
passes[1].has_transparent_background = true;
{
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId surface_id(root_sink_->frame_sink_id(), root_local_surface_id_);
+ SurfaceId surface_id(root_sink_->frame_sink_id(),
+ root_surface_id_.local_surface_id());
auto aggregated_frame = AggregateFrame(surface_id);
@@ -6103,17 +5876,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MetadataContentColorUsageTest) {
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.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
std::vector<Quad> root_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
@@ -6122,12 +5890,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MetadataContentColorUsageTest) {
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
// Make sure the root render pass has a color space that matches
@@ -6154,16 +5920,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageByChangingChildSurface) {
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator allocator;
- allocator.GenerateId();
- LocalSurfaceId child_local_surface_id = allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
std::vector<Quad> root_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
Pass(root_surface_quads, CompositorRenderPassId{1}, SurfaceSize())};
@@ -6172,18 +5934,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageByChangingChildSurface) {
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
// On first frame there is no existing cache texture to worry about re-using,
// so we don't worry what this bool is set to.
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// No Surface changed, so no damage should be given.
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_FALSE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
}
@@ -6193,10 +5953,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageByChangingChildSurface) {
CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// True for new child_frame with damage.
EXPECT_TRUE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
@@ -6208,10 +5968,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageByChangingChildSurface) {
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
child_surface_frame.render_pass_list[0]->damage_rect = gfx::Rect();
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// False for new child_frame without damage.
EXPECT_FALSE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
@@ -6234,17 +5994,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
std::vector<Quad> root_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
Pass(root_surface_quads, CompositorRenderPassId{1}, SurfaceSize())};
@@ -6253,18 +6008,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
// On first frame there is no existing cache texture to worry about re-using,
// so we don't worry what this bool is set to.
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// No Surface changed, so no damage should be given.
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_FALSE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
}
@@ -6274,23 +6027,20 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))};
std::vector<Pass> grand_child_passes = {
Pass(grand_child_quads, CompositorRenderPassId{1}, SurfaceSize())};
- ParentLocalSurfaceIdAllocator grandchild_allocator;
- grandchild_allocator.GenerateId();
- LocalSurfaceId grand_child_local_surface_id =
- grandchild_allocator.GetCurrentLocalSurfaceId();
- SurfaceId grand_child_surface_id(grand_child_support->frame_sink_id(),
- grand_child_local_surface_id);
+ TestSurfaceIdAllocator grand_child_surface_id(
+ grand_child_support->frame_sink_id());
{
CompositorFrame grand_child_frame = MakeEmptyCompositorFrame();
AddPasses(&grand_child_frame.render_pass_list, grand_child_passes,
&grand_child_frame.metadata.referenced_surfaces);
- grand_child_support->SubmitCompositorFrame(grand_child_local_surface_id,
- std::move(grand_child_frame));
+ grand_child_support->SubmitCompositorFrame(
+ grand_child_surface_id.local_surface_id(),
+ std::move(grand_child_frame));
std::vector<Quad> new_child_surface_quads = {
child_surface_quads[0],
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, grand_child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, grand_child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> new_child_surface_passes = {Pass(
@@ -6298,10 +6048,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, new_child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// True for new grand_child_frame.
EXPECT_TRUE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
@@ -6309,7 +6059,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
// No Surface changed, so no damage should be given.
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_FALSE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
}
@@ -6319,10 +6069,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
CompositorFrame grand_child_frame = MakeEmptyCompositorFrame();
AddPasses(&grand_child_frame.render_pass_list, grand_child_passes,
&grand_child_frame.metadata.referenced_surfaces);
- grand_child_support->SubmitCompositorFrame(grand_child_local_surface_id,
- std::move(grand_child_frame));
+ grand_child_support->SubmitCompositorFrame(
+ grand_child_surface_id.local_surface_id(),
+ std::move(grand_child_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// True for new grand_child_frame with damage.
EXPECT_TRUE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
@@ -6334,10 +6085,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&grand_child_frame.render_pass_list, grand_child_passes,
&grand_child_frame.metadata.referenced_surfaces);
grand_child_frame.render_pass_list[0]->damage_rect = gfx::Rect();
- grand_child_support->SubmitCompositorFrame(grand_child_local_surface_id,
- std::move(grand_child_frame));
+ grand_child_support->SubmitCompositorFrame(
+ grand_child_surface_id.local_surface_id(),
+ std::move(grand_child_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// False for new grand_child_frame without damage.
EXPECT_FALSE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
@@ -6356,16 +6108,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageFromRenderPassQuads) {
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator allocator;
- allocator.GenerateId();
- LocalSurfaceId child_local_surface_id = allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
std::vector<Quad> root_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Quad> root_render_pass_quads = {
Quad::RenderPassQuad(CompositorRenderPassId{1}, gfx::Transform(), true)};
@@ -6378,12 +6126,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageFromRenderPassQuads) {
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// On first frame there is no existing cache texture to worry about re-using,
// so we don't worry what this bool is set to.
@@ -6393,7 +6139,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageFromRenderPassQuads) {
// No Surface changed, so no damage should be given.
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_FALSE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
EXPECT_FALSE(aggregated_frame.render_pass_list[1]
@@ -6405,10 +6151,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageFromRenderPassQuads) {
CompositorFrame child_frame = MakeEmptyCompositorFrame();
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// True for new child_frame.
EXPECT_TRUE(aggregated_frame.render_pass_list[0]
->has_damage_from_contributing_content);
@@ -6434,12 +6180,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectOfCachedRenderPass) {
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -6467,10 +6211,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectOfCachedRenderPass) {
auto* root_pass_sqs = root_pass->shared_quad_state_list.front();
root_pass_sqs->quad_to_target_transform.Translate(8, 0);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
// Only the visible area is damaged.
@@ -6494,10 +6238,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectOfCachedRenderPass) {
auto* root_pass_sqs = root_pass->shared_quad_state_list.front();
root_pass_sqs->quad_to_target_transform.Translate(8, 0);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
// Should have full damage.
@@ -6524,16 +6268,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator allocator;
- allocator.GenerateId();
- LocalSurfaceId child_local_surface_id = allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
std::vector<Quad> root_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
@@ -6543,12 +6283,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -6576,10 +6314,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
auto* child_root_pass_sqs = child_root_pass->shared_quad_state_list.front();
child_root_pass_sqs->quad_to_target_transform.Translate(8, 0);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
// Only the visible area is damaged.
@@ -6603,10 +6341,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
auto* child_root_pass_sqs = child_root_pass->shared_quad_state_list.front();
child_root_pass_sqs->quad_to_target_transform.Translate(8, 0);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
// Should have full damage.
@@ -6627,17 +6365,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithClippedChildSurface) {
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator allocator;
- allocator.GenerateId();
- LocalSurfaceId child_local_surface_id = allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
// root surface quads
std::vector<Quad> root_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(SurfaceSize()), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
Pass(root_surface_quads, CompositorRenderPassId{1}, SurfaceSize())};
@@ -6646,12 +6380,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithClippedChildSurface) {
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
// The damage rect of the very first frame is always the full rect
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// Parameters used for damage rect testing
gfx::Transform transform(0.5, 0, 0, 0.5, 20, 0);
@@ -6662,7 +6394,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithClippedChildSurface) {
CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
CompositorFrame root_frame = MakeEmptyCompositorFrame();
@@ -6671,13 +6403,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithClippedChildSurface) {
auto* root_render_pass = root_frame.render_pass_list[0].get();
auto* surface_quad_sqs = root_render_pass->shared_quad_state_list.front();
surface_quad_sqs->quad_to_target_transform = transform;
- surface_quad_sqs->is_clipped = false;
+ surface_quad_sqs->clip_rect.reset();
// Set the root damage rect to empty. Only the child surface will be tested.
root_render_pass->damage_rect = gfx::Rect();
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// The root damage rect should be the size of the child surface damage rect
gfx::Rect expected_damage_rect(20, 0, 50, 50);
@@ -6689,7 +6421,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithClippedChildSurface) {
CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
CompositorFrame root_frame = MakeEmptyCompositorFrame();
@@ -6698,13 +6430,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithClippedChildSurface) {
auto* root_render_pass = root_frame.render_pass_list[0].get();
auto* surface_quad_sqs = root_render_pass->shared_quad_state_list.front();
surface_quad_sqs->quad_to_target_transform = transform;
- surface_quad_sqs->is_clipped = true;
surface_quad_sqs->clip_rect = clip_rect;
root_render_pass->damage_rect = gfx::Rect();
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// The root damage rect should be the size of the clipped child surface
// damage rect
@@ -6716,14 +6447,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithClippedChildSurface) {
// Tests the damage rect with a invalid child frame
TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithInvalidChildFrame) {
- ParentLocalSurfaceIdAllocator allocator;
- allocator.GenerateId();
- LocalSurfaceId child_local_surface_id = allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
std::vector<Quad> root_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(0, 0, 100, 100), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
Pass(root_surface_quads,
@@ -6734,15 +6461,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithInvalidChildFrame) {
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
// Frame # 0 - The primary surface of the child frame is not available.
// The child frame is not submitted.
// The damage rect of the very first frame is always the full rect.
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
EXPECT_EQ(gfx::Rect(gfx::Rect(0, 0, 100, 100)),
output_root_pass->damage_rect);
@@ -6754,10 +6479,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithInvalidChildFrame) {
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
// The damage rect is the full display rect when the child surface is not
// available.
@@ -6780,16 +6505,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithInvalidChildFrame) {
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
// The damage rect is the union of root surface damage (10, 10, 20, 20) and
// child surface (20, 20, 50, 50).
@@ -6800,13 +6525,9 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithInvalidChildFrame) {
}
// Frame # 3 - The primary surface is not available, with a different id.
{
- allocator.GenerateId();
- LocalSurfaceId child_local_surface_id2 =
- allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id2(child_sink_->frame_sink_id(),
- child_local_surface_id2);
+ TestSurfaceIdAllocator child_surface_id2(child_sink_->frame_sink_id());
std::vector<Quad> root_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id2), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id2), SK_ColorWHITE,
gfx::Rect(0, 0, 100, 100), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
Pass(root_surface_quads,
@@ -6816,10 +6537,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithInvalidChildFrame) {
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
// The damage rect is the full display rect when the primary child surface
// is not available.
@@ -6844,12 +6565,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator allocator;
- allocator.GenerateId();
- LocalSurfaceId child_local_surface_id = allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
// Original video quad (0, 0, 100, 100) x this video_transform matrix ==
@@ -6860,7 +6577,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
std::vector<Quad> root_surface_quads = {
Quad::SolidColorQuad(SK_ColorRED, gfx::Rect(60, 0, 40, 40)),
Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
/*primary_surface_rect*/ gfx::Rect(0, 0, 100, 100),
/*opacity*/ 1.f, video_transform,
/*stretch_content_to_fill_bounds=*/false, gfx::MaskFilterInfo(),
@@ -6875,12 +6592,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// Frame # 0 - Full occluding damage rect
// The damage rect of the very first frame is always the full rect.
@@ -6909,17 +6624,17 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
// The video quad (10, 0, 80, 80) unions the solid quad on top (60, 0, 40,
@@ -6946,11 +6661,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
// No change in root frame.
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
// Only the video quad (10, 0, 80, 80) is damaged.
@@ -6976,12 +6691,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
// root surface quads, the solid quad (60, 0, 40, 40) is removed.
std::vector<Quad> root_surface_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
/*primary_surface_rect*/ gfx::Rect(0, 0, 100, 100),
/*opacity*/ 1.f, video_transform,
/*stretch_content_to_fill_bounds=*/false, gfx::MaskFilterInfo(),
@@ -6996,10 +6711,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
// The video quad (10, 0, 80, 80) unions the expose damage from removing
@@ -7030,20 +6745,19 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
auto* render_pass = child_surface_frame.render_pass_list[0].get();
auto* surface_quad_sqs = render_pass->shared_quad_state_list.front();
- surface_quad_sqs->is_clipped = true;
surface_quad_sqs->clip_rect = gfx::Rect(20, 0, 60, 80);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
CompositorFrame root_frame = MakeEmptyCompositorFrame();
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
// The video quad (10, 0, 80, 80) unions the solid quad on top (60, 0, 40,
@@ -7072,14 +6786,14 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
// root surface quads
std::vector<Quad> root_surface_quads = {
Quad::SolidColorQuad(SK_ColorRED, gfx::Rect(60, 0, 100, 100)),
Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
/*primary_surface_rect*/ gfx::Rect(0, 0, 100, 100),
/*opacity*/ 1.f, video_transform,
/*stretch_content_to_fill_bounds=*/false, gfx::MaskFilterInfo(),
@@ -7096,13 +6810,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
auto* last_pass = root_frame.render_pass_list.back().get();
auto* solid_quad_sqs = last_pass->shared_quad_state_list.front();
- solid_quad_sqs->is_clipped = true;
solid_quad_sqs->clip_rect = gfx::Rect(80, 0, 40, 30);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
// The video quad (10, 0, 80, 80) unions the clipped damage rect of the
@@ -7136,11 +6849,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
CompositorFrame child_surface_frame = MakeEmptyCompositorFrame();
AddPasses(&child_surface_frame.render_pass_list, child_surface_passes,
&child_surface_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
// No change in root frame.
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
// Only the video quad (10, 0, 80, 80) is damaged.
@@ -7163,11 +6876,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
auto* surface_quad_sqs = render_pass->shared_quad_state_list.front();
surface_quad_sqs->no_damage = true;
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_surface_frame));
// No change in root frame.
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* output_root_pass = aggregated_frame.render_pass_list.back().get();
// Only the video quad (10, 0, 80, 80) is damaged.
@@ -7191,11 +6904,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {
// Tests that quads outside the damage rect are not ignored for cached render
// pass.
TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
- ParentLocalSurfaceIdAllocator allocator;
- allocator.GenerateId();
- LocalSurfaceId child_local_surface_id = allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
// The child surface has two quads, one with a visible rect of 15,15 6x6 and
// the other other with a visible rect of 10,10 2x2 (relative to root target
// space).
@@ -7226,16 +6935,16 @@ TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
child_pass_list[1]->quad_list.ElementAt(0)->visible_rect =
gfx::Rect(0, 0, 2, 2);
- SubmitPassListAsFrame(child_sink_.get(), child_local_surface_id,
- &child_pass_list, std::move(referenced_surfaces),
- device_scale_factor);
+ SubmitPassListAsFrame(child_sink_.get(),
+ child_surface_id.local_surface_id(), &child_pass_list,
+ std::move(referenced_surfaces), device_scale_factor);
}
{
CompositorRenderPassId pass_id[] = {CompositorRenderPassId{1},
CompositorRenderPassId{2}};
std::vector<Quad> root_quads[2] = {
- {Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ {Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false)},
{Quad::RenderPassQuad(pass_id[0], gfx::Transform(), true)},
@@ -7253,14 +6962,12 @@ TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
->quad_to_target_transform.Translate(10, 10);
root_pass->damage_rect = gfx::Rect(0, 0, 1, 1);
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
}
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
@@ -7278,7 +6985,7 @@ TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
CompositorRenderPassId pass_id[] = {CompositorRenderPassId{1},
CompositorRenderPassId{2}};
std::vector<Quad> root_quads[2] = {
- {Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ {Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false)},
{Quad::RenderPassQuad(pass_id[0], gfx::Transform(), true)},
@@ -7295,13 +7002,13 @@ TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
root_pass->shared_quad_state_list.front()
->quad_to_target_transform.Translate(10, 10);
root_pass->damage_rect = gfx::Rect(10, 10, 2, 2);
- SubmitPassListAsFrame(root_sink_.get(), root_local_surface_id_,
+ SubmitPassListAsFrame(root_sink_.get(), root_surface_id_.local_surface_id(),
&root_pass_list, std::move(referenced_surfaces),
device_scale_factor);
}
{
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
ASSERT_EQ(3u, aggregated_pass_list.size());
@@ -7326,12 +7033,8 @@ TEST_F(SurfaceAggregatorPartialSwapTest, NotIgnoreOutsideForCachedRenderPass) {
TEST_F(SurfaceAggregatorValidSurfaceTest, DisplayTransformDamageCallback) {
auto primary_child_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kChildIsRoot);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId primary_child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId primary_child_surface_id(primary_child_support->frame_sink_id(),
- primary_child_local_surface_id);
+ TestSurfaceIdAllocator primary_child_surface_id(
+ primary_child_support->frame_sink_id());
{
auto pass = CompositorRenderPass::Create();
@@ -7347,8 +7050,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DisplayTransformDamageCallback) {
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
- primary_child_support->SubmitCompositorFrame(primary_child_local_surface_id,
- std::move(frame));
+ primary_child_support->SubmitCompositorFrame(
+ primary_child_surface_id.local_surface_id(), std::move(frame));
}
constexpr gfx::Rect surface_quad_rect(10, 5);
@@ -7363,17 +7066,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DisplayTransformDamageCallback) {
root_sink_->SetAggregatedDamageCallbackForTesting(
aggregated_damage_callback.GetCallback());
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
- 0.5f);
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(), 0.5f);
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, surface_size,
- gfx::Rect(surface_size), next_display_time()));
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), surface_size,
+ gfx::Rect(surface_size), next_display_time()));
auto frame =
- aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement(),
+ aggregator_.Aggregate(root_surface_id_, GetNextDisplayTimeAndIncrement(),
gfx::OVERLAY_TRANSFORM_ROTATE_90);
gfx::Rect transformed_rect(surface_size.height(), surface_size.width());
EXPECT_EQ(frame.render_pass_list.back()->output_rect, transformed_rect);
@@ -7388,12 +7090,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RoundedCornerTransformChange) {
auto middle_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot);
// Child surface.
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
{
std::vector<Quad> child_quads[1] = {
{Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))},
@@ -7409,13 +7106,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RoundedCornerTransformChange) {
->shared_quad_state_list.front()
->mask_filter_info = gfx::MaskFilterInfo(gfx::RRectF(0, 0, 100, 10, 5));
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
}
// Root surface.
std::vector<Quad> surface_quads = {
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5), false)};
std::vector<Pass> root_passes = {Pass(surface_quads, SurfaceSize())};
@@ -7426,13 +7123,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RoundedCornerTransformChange) {
root_frame.render_pass_list[0]
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(0, 7);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* aggregated_first_pass_sqs =
aggregated_frame.render_pass_list[0]->shared_quad_state_list.front();
@@ -7450,13 +7144,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RoundedCornerTransformedSurfaceQuad) {
auto middle_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot);
// Grandchild surface.
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
-
- LocalSurfaceId grandchild_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId grandchild_surface_id(child_sink_->frame_sink_id(),
- grandchild_local_surface_id);
+ TestSurfaceIdAllocator grandchild_surface_id(child_sink_->frame_sink_id());
{
std::vector<Quad> child_quads[1] = {
{Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))},
@@ -7468,20 +7156,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RoundedCornerTransformedSurfaceQuad) {
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(grandchild_local_surface_id,
+ child_sink_->SubmitCompositorFrame(grandchild_surface_id.local_surface_id(),
std::move(child_frame));
}
// Child surface.
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
{
// Set an opacity in order to prevent merging into the root render pass.
std::vector<Quad> child_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, grandchild_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, grandchild_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), 0.5f, gfx::Transform(), false,
gfx::MaskFilterInfo(gfx::RRectF(0, 0, 96, 10, 5)),
/*is_fast_rounded_corner=*/false)};
@@ -7493,7 +7177,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RoundedCornerTransformedSurfaceQuad) {
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
}
@@ -7501,7 +7185,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RoundedCornerTransformedSurfaceQuad) {
gfx::Transform surface_transform;
surface_transform.Translate(3, 4);
std::vector<Quad> secondary_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), 1.f, surface_transform, false, gfx::MaskFilterInfo(),
/*is_fast_rounded_corner=*/false)};
@@ -7515,13 +7199,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RoundedCornerTransformedSurfaceQuad) {
root_frame.render_pass_list[0]
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(0, 7);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* aggregated_first_pass_sqs =
aggregated_frame.render_pass_list[1]->shared_quad_state_list.front();
@@ -7540,13 +7221,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
auto middle_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot);
// Grandchild surface.
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
-
- LocalSurfaceId grandchild_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId grandchild_surface_id(child_sink_->frame_sink_id(),
- grandchild_local_surface_id);
+ TestSurfaceIdAllocator grandchild_surface_id(child_sink_->frame_sink_id());
{
std::vector<Quad> child_quads[1] = {
{Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))},
@@ -7558,19 +7233,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(grandchild_local_surface_id,
+ child_sink_->SubmitCompositorFrame(grandchild_surface_id.local_surface_id(),
std::move(child_frame));
}
// Child surface.
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
{
std::vector<Quad> child_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, grandchild_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, grandchild_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), 1.f, gfx::Transform(), false,
gfx::MaskFilterInfo(gfx::RRectF(0, 0, 96, 10, 5)),
/*is_fast_rounded_corner=*/false)};
@@ -7582,7 +7253,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
}
@@ -7590,7 +7261,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
gfx::Transform surface_transform;
surface_transform.Translate(3, 4);
std::vector<Quad> secondary_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), 1.f, surface_transform, false, gfx::MaskFilterInfo(),
/*is_fast_rounded_corner=*/false)};
@@ -7604,13 +7275,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
root_frame.render_pass_list[0]
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(0, 7);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
auto* aggregated_first_pass_sqs =
aggregated_frame.render_pass_list[1]->shared_quad_state_list.front();
@@ -7630,11 +7298,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TransformedRoundedSurfaceQuad) {
child_allocator.GenerateId();
// Child surface.
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
{
std::vector<Quad> child_quads[1] = {
{Quad::SolidColorQuad(SK_ColorGREEN, gfx::Rect(5, 5))},
@@ -7646,7 +7310,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TransformedRoundedSurfaceQuad) {
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
}
@@ -7654,7 +7318,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TransformedRoundedSurfaceQuad) {
gfx::Transform surface_transform;
surface_transform.Translate(3, 4);
std::vector<Quad> secondary_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), 1.f, surface_transform, false,
gfx::MaskFilterInfo(gfx::RRectF(0, 0, 96, 10, 5)),
/*is_fast_rounded_corner=*/true)};
@@ -7669,13 +7333,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TransformedRoundedSurfaceQuad) {
root_frame.render_pass_list[0]
->shared_quad_state_list.front()
->quad_to_target_transform.Translate(0, 7);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// Only one aggregated quad will result, because the use of
// is_fast_border_radius will result in the child surface being merged
// into the parent.
@@ -7708,13 +7369,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
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.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// The root surface consists of three render passes:
@@ -7730,7 +7386,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
gfx::Transform translation;
translation.Translate(30.f, 50.f);
std::vector<Quad> root_quads[] = {
- {Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ {Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false,
AllowMerge())},
@@ -7747,19 +7403,16 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.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 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(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(0, 0, 230, 250), next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
// For the second aggregation we only damage the child surface at
@@ -7771,7 +7424,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
child_frame_2.render_pass_list.back()->damage_rect =
gfx::Rect(10, 10, 10, 10);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame_2));
// The child surface is embedded twice in the root surface, so its damage rect
@@ -7784,10 +7437,11 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// 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()));
- auto aggregated_frame_2 = AggregateFrame(root_surface_id);
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
+ auto aggregated_frame_2 = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
}
@@ -7811,13 +7465,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
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.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// The root surface consists of two render passes:
@@ -7830,7 +7479,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
CompositorRenderPassId root_pass_ids[] = {CompositorRenderPassId{1},
CompositorRenderPassId{2}};
std::vector<Quad> root_quads_1 = {
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
Quad::RenderPassQuad(root_pass_ids[1], gfx::Transform(), true)};
@@ -7850,21 +7499,18 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
rpdq_2_transform.Translate(30.f, 50.f);
rpdq_2_transform.Scale(2.f, 2.f);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.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(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(0, 0, 100, 100), next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
// For the second aggregation we only damage the child surface at
@@ -7877,14 +7523,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
child_frame_2.render_pass_list.back()->damage_rect =
gfx::Rect(10, 10, 10, 10);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.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()));
- auto aggregated_frame_2 = AggregateFrame(root_surface_id);
+ EXPECT_CALL(
+ aggregated_damage_callback,
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
+ auto aggregated_frame_2 = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
}
@@ -7893,13 +7540,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
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.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
{
std::vector<Quad> child_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, child_rect)};
@@ -7910,7 +7551,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AllowMerge) {
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
}
@@ -7927,7 +7568,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AllowMerge) {
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetAll(sqs, child_rect, child_rect,
/*needs_blending=*/false,
- SurfaceRange(base::nullopt, child_surface_id),
+ SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false,
/*is_reflection=*/false,
@@ -7935,12 +7576,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AllowMerge) {
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_);
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
+ std::move(frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// Merging allowed, so 1 pass should be present.
EXPECT_EQ(1u, aggregated_frame.render_pass_list.size());
}
@@ -7956,7 +7595,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AllowMerge) {
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetAll(sqs, child_rect, child_rect,
/*needs_blending=*/false,
- SurfaceRange(base::nullopt, child_surface_id),
+ SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false,
/*is_reflection=*/false,
@@ -7964,12 +7603,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AllowMerge) {
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_);
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
+ std::move(frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// Merging not allowed, so 2 passes should be present.
EXPECT_EQ(2u, aggregated_frame.render_pass_list.size());
}
@@ -7980,13 +7617,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AllowMerge) {
TEST_F(SurfaceAggregatorValidSurfaceTest, SkipInvisibleSurface) {
// Child surface.
gfx::Rect child_rect(5, 5);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
-
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
{
std::vector<Quad> child_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, child_rect)};
@@ -8000,7 +7631,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SkipInvisibleSurface) {
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
}
@@ -8016,7 +7647,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SkipInvisibleSurface) {
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetAll(sqs, child_rect, child_rect,
/*needs_blending=*/false,
- SurfaceRange(base::nullopt, child_surface_id),
+ SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false,
/*is_reflection=*/false,
@@ -8024,12 +7655,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SkipInvisibleSurface) {
CompositorFrame frame =
CompositorFrameBuilder().AddRenderPass(std::move(pass)).Build();
- root_sink_->SubmitCompositorFrame(root_local_surface_id_, std::move(frame));
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
+ std::move(frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
-
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// Merging not allowed, but child rect should be dropped.
EXPECT_EQ(1u, aggregated_frame.render_pass_list.size());
}
@@ -8039,13 +7668,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SkipInvisibleSurface) {
TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassDoesNotFillSurface) {
// Child surface.
gfx::Rect child_rect(5, 4, 5, 5);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
-
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
{
std::vector<Quad> child_quads = {
Quad::SolidColorQuad(SK_ColorGREEN, child_rect)};
@@ -8056,7 +7679,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassDoesNotFillSurface) {
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
}
@@ -8074,7 +7697,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassDoesNotFillSurface) {
auto* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_quad->SetAll(sqs, surface_size, surface_size,
/*needs_blending=*/false,
- SurfaceRange(base::nullopt, child_surface_id),
+ SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE,
/*stretch_content_to_fill_bounds=*/false,
/*is_reflection=*/false,
@@ -8082,12 +7705,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassDoesNotFillSurface) {
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_);
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
+ std::move(frame));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
// Merging not allowed, so 2 passes should be present.
ASSERT_EQ(2u, aggregated_frame.render_pass_list.size());
@@ -8127,13 +7748,8 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
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.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
std::vector<Quad> solid_color_quad = {
@@ -8144,7 +7760,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
Quad::RenderPassQuad(CompositorRenderPassId{2}, gfx::Transform(), true),
Quad::RenderPassQuad(CompositorRenderPassId{3}, gfx::Transform(), true),
Quad::RenderPassQuad(CompositorRenderPassId{4}, gfx::Transform(), true),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_surface_id),
SK_ColorWHITE, gfx::Rect(child_surface_size),
/*stretch_content_to_fill_bounds=*/false,
AllowMerge())};
@@ -8187,22 +7803,20 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
root_frame.render_pass_list[3]->backdrop_filters.Append(
cc::FilterOperation::CreateBlurFilter(5));
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
// Damage rect for first aggregation should contain entire root surface.
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
size_t expected_num_passes_after_aggregation = AllowMerge() ? 5u : 6u;
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(
+ child_surface_id.local_surface_id(), child_surface_size,
+ gfx::Rect(child_surface_size), next_display_time()));
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- gfx::Rect(child_surface_size), next_display_time()));
- EXPECT_CALL(
- aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
gfx::Rect(0, 0, 100, 100), next_display_time()));
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list = aggregated_frame.render_pass_list;
EXPECT_EQ(expected_num_passes_after_aggregation, aggregated_pass_list.size());
@@ -8225,7 +7839,7 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
AddPasses(&child_frame.render_pass_list, child_passes,
&child_frame.metadata.referenced_surfaces);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// The damage from the surface quad (0,85 100x15) is below all the four quads
@@ -8235,14 +7849,15 @@ TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
// be the bottom 3 render pass from the image.
const gfx::Rect expected_damage_rect(0, 30, 100, 70);
+ EXPECT_CALL(aggregated_damage_callback,
+ OnAggregatedDamage(
+ child_surface_id.local_surface_id(), child_surface_size,
+ gfx::Rect(child_surface_size), next_display_time()));
EXPECT_CALL(
aggregated_damage_callback,
- OnAggregatedDamage(child_local_surface_id, child_surface_size,
- gfx::Rect(child_surface_size), next_display_time()));
- EXPECT_CALL(aggregated_damage_callback,
- OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
- expected_damage_rect, next_display_time()));
- aggregated_frame = AggregateFrame(root_surface_id);
+ OnAggregatedDamage(root_surface_id_.local_surface_id(), SurfaceSize(),
+ expected_damage_rect, next_display_time()));
+ aggregated_frame = AggregateFrame(root_surface_id_);
testing::Mock::VerifyAndClearExpectations(&aggregated_damage_callback);
const auto& aggregated_pass_list2 = aggregated_frame.render_pass_list;
@@ -8255,14 +7870,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
ContainedFrameSinkChangeInvalidatesHitTestData) {
auto embedded_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryFrameSinkId1, kRootIsRoot);
- ParentLocalSurfaceIdAllocator embedded_allocator;
- embedded_allocator.GenerateId();
- LocalSurfaceId embedded_local_surface_id =
- embedded_allocator.GetCurrentLocalSurfaceId();
- SurfaceId embedded_surface_id(embedded_support->frame_sink_id(),
- embedded_local_surface_id);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
+ TestSurfaceIdAllocator embedded_surface_id(embedded_support->frame_sink_id());
// First submit a root frame which doesn't reference the embedded frame
// and aggregate.
@@ -8272,15 +7880,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
Quad::SolidColorQuad(SK_ColorGRAY, gfx::Rect(5, 5))};
std::vector<Pass> embedded_passes = {Pass(embedded_quads, SurfaceSize())};
SubmitCompositorFrame(embedded_support.get(), embedded_passes,
- embedded_local_surface_id, 1.0f);
+ embedded_surface_id.local_surface_id(), 1.0f);
std::vector<Quad> root_quads = {
Quad::SolidColorQuad(SK_ColorRED, gfx::Rect(5, 5)),
Quad::SolidColorQuad(SK_ColorBLUE, gfx::Rect(5, 5))};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
- 1.0f);
- AggregateFrame(root_surface_id);
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(), 1.0f);
+ AggregateFrame(root_surface_id_);
}
const HitTestManager* hit_test_manager = manager_.hit_test_manager();
@@ -8291,15 +7899,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
// aggregate.
{
std::vector<Quad> root_quads = {
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, embedded_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, embedded_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5), false),
Quad::SolidColorQuad(SK_ColorRED, gfx::Rect(5, 5)),
Quad::SolidColorQuad(SK_ColorBLUE, gfx::Rect(5, 5))};
std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
- SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
- 1.0);
- AggregateFrame(root_surface_id);
+ SubmitCompositorFrame(root_sink_.get(), root_passes,
+ root_surface_id_.local_surface_id(), 1.0);
+ AggregateFrame(root_surface_id_);
}
// Check that the HitTestManager was marked as needing to re-aggregate hit
@@ -8342,17 +7950,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DelegatedInkMetadataTest) {
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.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
std::vector<Quad> root_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
@@ -8383,12 +7986,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DelegatedInkMetadataTest) {
pt, metadata.diameter(), metadata.color(), metadata.timestamp(), area,
metadata.frame_time(), metadata.is_hovering());
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
std::unique_ptr<gfx::DelegatedInkMetadata> actual_metadata =
std::move(aggregated_frame.delegated_ink_metadata);
@@ -8397,7 +7998,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, DelegatedInkMetadataTest) {
// Then confirm that the |delegated_ink_metadata| was reset and a new
// aggregated frame does not contain any delegated ink metadata.
- auto new_aggregated_frame = AggregateFrame(root_surface_id);
+ auto new_aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_FALSE(new_aggregated_frame.delegated_ink_metadata);
}
@@ -8421,20 +8022,16 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&greatgrandchild_frame.render_pass_list, greatgrandchild_passes,
&greatgrandchild_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator greatgrandchild_allocator;
- greatgrandchild_allocator.GenerateId();
- LocalSurfaceId greatgrandchild_local_surface_id =
- greatgrandchild_allocator.GetCurrentLocalSurfaceId();
- SurfaceId great_grandchild_surface_id(
- greatgrand_child_support->frame_sink_id(),
- greatgrandchild_local_surface_id);
+ TestSurfaceIdAllocator great_grandchild_surface_id(
+ greatgrand_child_support->frame_sink_id());
greatgrand_child_support->SubmitCompositorFrame(
- greatgrandchild_local_surface_id, std::move(greatgrandchild_frame));
+ great_grandchild_surface_id.local_surface_id(),
+ std::move(greatgrandchild_frame));
auto grand_child_support = std::make_unique<CompositorFrameSinkSupport>(
nullptr, &manager_, kArbitraryMiddleFrameSinkId, kChildIsRoot);
std::vector<Quad> grandchild_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, great_grandchild_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, great_grandchild_surface_id), SK_ColorWHITE,
gfx::Rect(7, 7), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> grandchild_passes = {
Pass(grandchild_quads, CompositorRenderPassId{1}, gfx::Size(100, 100))};
@@ -8462,17 +8059,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
->shared_quad_state_list.ElementAt(0)
->quad_to_target_transform.TransformRect(&area);
- ParentLocalSurfaceIdAllocator grandchild_allocator;
- grandchild_allocator.GenerateId();
- LocalSurfaceId grandchild_local_surface_id =
- grandchild_allocator.GetCurrentLocalSurfaceId();
- SurfaceId grandchild_surface_id(grand_child_support->frame_sink_id(),
- grandchild_local_surface_id);
- grand_child_support->SubmitCompositorFrame(grandchild_local_surface_id,
- std::move(grandchild_frame));
+ TestSurfaceIdAllocator grandchild_surface_id(
+ grand_child_support->frame_sink_id());
+ grand_child_support->SubmitCompositorFrame(
+ grandchild_surface_id.local_surface_id(), std::move(grandchild_frame));
std::vector<Quad> child_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, grandchild_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, grandchild_surface_id), SK_ColorWHITE,
gfx::Rect(7, 7), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> child_passes = {
Pass(child_quads, CompositorRenderPassId{1}, gfx::Size(30, 30))};
@@ -8492,17 +8085,12 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
->shared_quad_state_list.ElementAt(0)
->quad_to_target_transform.TransformRect(&area);
- ParentLocalSurfaceIdAllocator child_allocator;
- child_allocator.GenerateId();
- LocalSurfaceId child_local_surface_id =
- child_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
std::vector<Quad> root_quads = {Quad::SurfaceQuad(
- SurfaceRange(base::nullopt, child_surface_id), SK_ColorWHITE,
+ SurfaceRange(absl::nullopt, child_surface_id), SK_ColorWHITE,
gfx::Rect(5, 5), /*stretch_content_to_fill_bounds=*/false)};
std::vector<Pass> root_passes = {
@@ -8526,12 +8114,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
->shared_quad_state_list.ElementAt(0)
->quad_to_target_transform.TransformRect(&area);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
metadata = gfx::DelegatedInkMetadata(
pt, metadata.diameter(), metadata.color(), metadata.timestamp(), area,
@@ -8544,7 +8130,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
// Then confirm that the |delegated_ink_metadata| was reset and a new
// aggregated frame does not contain any delegated ink metadata.
- auto new_aggregated_frame = AggregateFrame(root_surface_id);
+ auto new_aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_FALSE(new_aggregated_frame.delegated_ink_metadata);
}
@@ -8566,13 +8152,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&child_1_frame.render_pass_list, child_1_passes,
&child_1_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator child_1_allocator;
- child_1_allocator.GenerateId();
- LocalSurfaceId child_1_local_surface_id =
- child_1_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_1_surface_id(child_sink_->frame_sink_id(),
- child_1_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_1_local_surface_id,
+ TestSurfaceIdAllocator child_1_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_1_surface_id.local_surface_id(),
std::move(child_1_frame));
std::vector<Quad> child_2_quads = {
@@ -8589,13 +8170,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&child_2_frame.render_pass_list, child_2_passes,
&child_2_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator child_2_allocator;
- child_2_allocator.GenerateId();
- LocalSurfaceId child_2_local_surface_id =
- child_2_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_2_surface_id(child_2_support->frame_sink_id(),
- child_2_local_surface_id);
- child_2_support->SubmitCompositorFrame(child_2_local_surface_id,
+ TestSurfaceIdAllocator child_2_surface_id(child_2_support->frame_sink_id());
+ child_2_support->SubmitCompositorFrame(child_2_surface_id.local_surface_id(),
std::move(child_2_frame));
std::vector<Quad> child_3_quads = {
@@ -8607,23 +8183,18 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&child_3_frame.render_pass_list, child_3_passes,
&child_3_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator child_3_allocator;
- child_3_allocator.GenerateId();
- LocalSurfaceId child_3_local_surface_id =
- child_3_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_3_surface_id(child_3_support->frame_sink_id(),
- child_3_local_surface_id);
- child_3_support->SubmitCompositorFrame(child_3_local_surface_id,
+ TestSurfaceIdAllocator child_3_surface_id(child_3_support->frame_sink_id());
+ child_3_support->SubmitCompositorFrame(child_3_surface_id.local_surface_id(),
std::move(child_3_frame));
std::vector<Quad> root_quads = {
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_1_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_1_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_2_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_2_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_3_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_3_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false)};
@@ -8658,12 +8229,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
->shared_quad_state_list.ElementAt(1)
->quad_to_target_transform.TransformRect(&area);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
metadata = gfx::DelegatedInkMetadata(
pt, metadata.diameter(), metadata.color(), metadata.timestamp(), area,
@@ -8676,7 +8245,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
// Then confirm that the |delegated_ink_metadata| was reset and a new
// aggregated frame does not contain any delegated ink metadata.
- auto new_aggregated_frame = AggregateFrame(root_surface_id);
+ auto new_aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_FALSE(new_aggregated_frame.delegated_ink_metadata);
}
@@ -8698,13 +8267,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&child_1_frame.render_pass_list, child_1_passes,
&child_1_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator child_1_allocator;
- child_1_allocator.GenerateId();
- LocalSurfaceId child_1_local_surface_id =
- child_1_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_1_surface_id(child_sink_->frame_sink_id(),
- child_1_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_1_local_surface_id,
+ TestSurfaceIdAllocator child_1_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_1_surface_id.local_surface_id(),
std::move(child_1_frame));
std::vector<Quad> child_2_quads = {
@@ -8733,13 +8297,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&child_2_frame.render_pass_list, child_2_passes,
&child_2_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator child_2_allocator;
- child_2_allocator.GenerateId();
- LocalSurfaceId child_2_local_surface_id =
- child_2_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_2_surface_id(child_2_support->frame_sink_id(),
- child_2_local_surface_id);
- child_2_support->SubmitCompositorFrame(child_2_local_surface_id,
+ TestSurfaceIdAllocator child_2_surface_id(child_2_support->frame_sink_id());
+ child_2_support->SubmitCompositorFrame(child_2_surface_id.local_surface_id(),
std::move(child_2_frame));
std::vector<Quad> child_3_quads = {
@@ -8753,23 +8312,18 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
AddPasses(&child_3_frame.render_pass_list, child_3_passes,
&child_3_frame.metadata.referenced_surfaces);
- ParentLocalSurfaceIdAllocator child_3_allocator;
- child_3_allocator.GenerateId();
- LocalSurfaceId child_3_local_surface_id =
- child_3_allocator.GetCurrentLocalSurfaceId();
- SurfaceId child_3_surface_id(child_3_support->frame_sink_id(),
- child_3_local_surface_id);
- child_3_support->SubmitCompositorFrame(child_3_local_surface_id,
+ TestSurfaceIdAllocator child_3_surface_id(child_3_support->frame_sink_id());
+ child_3_support->SubmitCompositorFrame(child_3_surface_id.local_surface_id(),
std::move(child_3_frame));
std::vector<Quad> root_quads = {
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_1_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_1_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_2_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_2_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false),
- Quad::SurfaceQuad(SurfaceRange(base::nullopt, child_3_surface_id),
+ Quad::SurfaceQuad(SurfaceRange(absl::nullopt, child_3_surface_id),
SK_ColorWHITE, gfx::Rect(5, 5),
/*stretch_content_to_fill_bounds=*/false)};
@@ -8805,12 +8359,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
->shared_quad_state_list.ElementAt(1)
->quad_to_target_transform.TransformRect(&area);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
gfx::DelegatedInkMetadata expected_metadata(
pt, later_metadata.diameter(), later_metadata.color(),
@@ -8824,7 +8376,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
// Then confirm that the |delegated_ink_metadata| was reset and a new
// aggregated frame does not contain any delegated ink metadata.
- auto new_aggregated_frame = AggregateFrame(root_surface_id);
+ auto new_aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_FALSE(new_aggregated_frame.delegated_ink_metadata);
}
@@ -8847,13 +8399,8 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
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.GetCurrentLocalSurfaceId();
- SurfaceId child_surface_id(child_sink_->frame_sink_id(),
- child_local_surface_id);
- child_sink_->SubmitCompositorFrame(child_local_surface_id,
+ TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
+ child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
std::move(child_frame));
// Do not put the child surface in a SurfaceDrawQuad so that it remains
@@ -8866,7 +8413,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
CompositorFrame root_frame = MakeEmptyCompositorFrame();
root_frame.metadata.referenced_surfaces.emplace_back(
- SurfaceRange(base::nullopt, child_surface_id));
+ SurfaceRange(absl::nullopt, child_surface_id));
AddPasses(&root_frame.render_pass_list, root_passes,
&root_frame.metadata.referenced_surfaces);
@@ -8877,22 +8424,21 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
->shared_quad_state_list.ElementAt(0)
->quad_to_target_transform.Translate(70, 240);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(root_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_FALSE(aggregated_frame.delegated_ink_metadata);
// Now add a CopyOutputRequest on the child surface, so that the delegated
// ink metadata does get populated on the aggregated frame.
auto copy_request = CopyOutputRequest::CreateStubForTesting();
- child_sink_->RequestCopyOfOutput(
- {child_local_surface_id, SubtreeCaptureId(), std::move(copy_request)});
+ child_sink_->RequestCopyOfOutput({child_surface_id.local_surface_id(),
+ SubtreeCaptureId(),
+ std::move(copy_request)});
- aggregated_frame = AggregateFrame(root_surface_id);
+ aggregated_frame = AggregateFrame(root_surface_id_);
std::unique_ptr<gfx::DelegatedInkMetadata> actual_metadata =
std::move(aggregated_frame.delegated_ink_metadata);
@@ -8901,7 +8447,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest,
// Then confirm that the |delegated_ink_metadata| was reset and a new
// aggregated frame does not contain any delegated ink metadata.
- auto new_aggregated_frame = AggregateFrame(root_surface_id);
+ auto new_aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_FALSE(new_aggregated_frame.delegated_ink_metadata);
}
@@ -8917,11 +8463,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ColorUsageChangeFullFrameDamage) {
// First frame has full damage.
{
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_EQ(gfx::ContentColorUsage::kHDR,
aggregated_frame.render_pass_list[0]->content_color_usage);
@@ -8930,11 +8475,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ColorUsageChangeFullFrameDamage) {
}
// Second frame has partial damage.
{
- SubmitCompositorFrame(root_sink_.get(), passes, root_local_surface_id_,
+ SubmitCompositorFrame(root_sink_.get(), passes,
+ root_surface_id_.local_surface_id(),
device_scale_factor);
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_EQ(gfx::ContentColorUsage::kHDR,
aggregated_frame.render_pass_list[0]->content_color_usage);
@@ -8949,11 +8493,9 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, ColorUsageChangeFullFrameDamage) {
gfx::ContentColorUsage::kSRGB;
AddPasses(&compositor_frame.render_pass_list, passes,
&compositor_frame.metadata.referenced_surfaces);
- root_sink_->SubmitCompositorFrame(root_local_surface_id_,
+ root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
std::move(compositor_frame));
- SurfaceId root_surface_id(root_sink_->frame_sink_id(),
- root_local_surface_id_);
- auto aggregated_frame = AggregateFrame(root_surface_id);
+ auto aggregated_frame = AggregateFrame(root_surface_id_);
EXPECT_EQ(gfx::ContentColorUsage::kSRGB,
aggregated_frame.render_pass_list[0]->content_color_usage);
@@ -8966,7 +8508,6 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TransitionDirectiveFrameBehind) {
FakeCompositorFrameSinkClient client;
auto support = std::make_unique<CompositorFrameSinkSupport>(
&client, &manager_, kArbitraryRootFrameSinkId, kRootIsRoot);
- EnableDocumentTransitions(support.get());
LocalSurfaceId local_surface_id(7u, base::UnguessableToken::Create());
SurfaceId surface_id(support->frame_sink_id(), local_surface_id);
diff --git a/chromium/components/viz/service/display/texture_deleter.cc b/chromium/components/viz/service/display/texture_deleter.cc
index 5a5dead9323..a0c58b35316 100644
--- a/chromium/components/viz/service/display/texture_deleter.cc
+++ b/chromium/components/viz/service/display/texture_deleter.cc
@@ -8,11 +8,11 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_post_task.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "components/viz/common/gpu/context_provider.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
@@ -28,35 +28,23 @@ static void DeleteTextureOnImplThread(
mailbox);
}
-static void PostTaskFromMainToImplThread(
- scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner,
- ReleaseCallback run_impl_callback,
- const gpu::SyncToken& sync_token,
- bool is_lost) {
- // This posts the task to RunDeleteTextureOnImplThread().
- impl_task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(run_impl_callback), sync_token, is_lost));
-}
-
TextureDeleter::TextureDeleter(
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: impl_task_runner_(std::move(task_runner)) {}
TextureDeleter::~TextureDeleter() {
- for (size_t i = 0; i < impl_callbacks_.size(); ++i)
- impl_callbacks_.at(i)->Run(gpu::SyncToken(), true);
+ for (auto& callback : impl_callbacks_)
+ std::move(*callback).Run(gpu::SyncToken(), /*is_lost=*/true);
}
-std::unique_ptr<SingleReleaseCallback> TextureDeleter::GetReleaseCallback(
+ReleaseCallback TextureDeleter::GetReleaseCallback(
scoped_refptr<ContextProvider> context_provider,
const gpu::Mailbox& mailbox) {
// This callback owns the |context_provider|. It must be destroyed on the impl
// thread. Upon destruction of this class, the callback must immediately be
// destroyed.
- std::unique_ptr<SingleReleaseCallback> impl_callback =
- SingleReleaseCallback::Create(base::BindOnce(
- &DeleteTextureOnImplThread, std::move(context_provider), mailbox));
+ auto impl_callback = std::make_unique<ReleaseCallback>(base::BindOnce(
+ &DeleteTextureOnImplThread, std::move(context_provider), mailbox));
impl_callbacks_.push_back(std::move(impl_callback));
@@ -68,26 +56,25 @@ std::unique_ptr<SingleReleaseCallback> TextureDeleter::GetReleaseCallback(
// Provide a callback for the main thread that posts back to the impl
// thread.
- std::unique_ptr<SingleReleaseCallback> main_callback;
+ ReleaseCallback main_callback;
if (impl_task_runner_) {
- main_callback = SingleReleaseCallback::Create(
- base::BindOnce(&PostTaskFromMainToImplThread, impl_task_runner_,
- std::move(run_impl_callback)));
+ main_callback =
+ base::BindPostTask(impl_task_runner_, std::move(run_impl_callback));
} else {
- main_callback = SingleReleaseCallback::Create(std::move(run_impl_callback));
+ main_callback = std::move(run_impl_callback);
}
return main_callback;
}
void TextureDeleter::RunDeleteTextureOnImplThread(
- SingleReleaseCallback* impl_callback,
+ ReleaseCallback* impl_callback,
const gpu::SyncToken& sync_token,
bool is_lost) {
for (size_t i = 0; i < impl_callbacks_.size(); ++i) {
if (impl_callbacks_[i].get() == impl_callback) {
// Run the callback, then destroy it here on the impl thread.
- impl_callbacks_[i]->Run(sync_token, is_lost);
+ std::move(*impl_callbacks_[i]).Run(sync_token, is_lost);
impl_callbacks_.erase(impl_callbacks_.begin() + i);
return;
}
diff --git a/chromium/components/viz/service/display/texture_deleter.h b/chromium/components/viz/service/display/texture_deleter.h
index da6c0d31148..dfec16bd9ce 100644
--- a/chromium/components/viz/service/display/texture_deleter.h
+++ b/chromium/components/viz/service/display/texture_deleter.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/memory/weak_ptr.h"
+#include "components/viz/common/resources/release_callback.h"
#include "components/viz/service/viz_service_export.h"
namespace base {
@@ -22,7 +23,6 @@ struct SyncToken;
namespace viz {
class ContextProvider;
-class SingleReleaseCallback;
class VIZ_SERVICE_EXPORT TextureDeleter {
public:
@@ -39,19 +39,19 @@ class VIZ_SERVICE_EXPORT TextureDeleter {
// ReleaseCallback will become a no-op and the texture will be deleted
// immediately on the impl thread, along with dropping the reference to the
// ContextProvider.
- std::unique_ptr<SingleReleaseCallback> GetReleaseCallback(
+ ReleaseCallback GetReleaseCallback(
scoped_refptr<ContextProvider> context_provider,
const gpu::Mailbox& mailbox);
private:
// Runs the |impl_callback| to delete the texture and removes the callback
// from the |impl_callbacks_| list.
- void RunDeleteTextureOnImplThread(SingleReleaseCallback* impl_callback,
+ void RunDeleteTextureOnImplThread(ReleaseCallback* impl_callback,
const gpu::SyncToken& sync_token,
bool is_lost);
scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner_;
- std::vector<std::unique_ptr<SingleReleaseCallback>> impl_callbacks_;
+ std::vector<std::unique_ptr<ReleaseCallback>> impl_callbacks_;
base::WeakPtrFactory<TextureDeleter> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(TextureDeleter);
diff --git a/chromium/components/viz/service/display/texture_deleter_unittest.cc b/chromium/components/viz/service/display/texture_deleter_unittest.cc
index 01b62e27b07..9d6e03ca49d 100644
--- a/chromium/components/viz/service/display/texture_deleter_unittest.cc
+++ b/chromium/components/viz/service/display/texture_deleter_unittest.cc
@@ -6,7 +6,7 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "components/viz/common/resources/single_release_callback.h"
+#include "components/viz/common/resources/release_callback.h"
#include "components/viz/test/test_context_provider.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
@@ -34,8 +34,7 @@ TEST(TextureDeleterTest, Destroy) {
EXPECT_TRUE(context_provider->HasOneRef());
EXPECT_EQ(1u, sii->shared_image_count());
- std::unique_ptr<SingleReleaseCallback> cb =
- deleter->GetReleaseCallback(context_provider, mailbox);
+ ReleaseCallback cb = deleter->GetReleaseCallback(context_provider, mailbox);
EXPECT_FALSE(context_provider->HasOneRef());
EXPECT_EQ(1u, sii->shared_image_count());
@@ -47,7 +46,7 @@ TEST(TextureDeleterTest, Destroy) {
// Run the scoped release callback before destroying it, but it won't do
// anything.
- cb->Run(gpu::SyncToken(), false);
+ std::move(cb).Run(gpu::SyncToken(), false);
}
TEST(TextureDeleterTest, NullTaskRunner) {
@@ -67,12 +66,11 @@ TEST(TextureDeleterTest, NullTaskRunner) {
EXPECT_TRUE(context_provider->HasOneRef());
EXPECT_EQ(1u, sii->shared_image_count());
- std::unique_ptr<SingleReleaseCallback> cb =
- deleter->GetReleaseCallback(context_provider, mailbox);
+ ReleaseCallback cb = deleter->GetReleaseCallback(context_provider, mailbox);
EXPECT_FALSE(context_provider->HasOneRef());
EXPECT_EQ(1u, sii->shared_image_count());
- cb->Run(gpu::SyncToken(), false);
+ std::move(cb).Run(gpu::SyncToken(), false);
// With no task runner the callback will immediately drops its ref on the
// ContextProvider and delete the shared image.
diff --git a/chromium/components/viz/service/display/viz_perf_test.cc b/chromium/components/viz/service/display/viz_perf_test.cc
index 27c137dc2d2..0b863b5c470 100644
--- a/chromium/components/viz/service/display/viz_perf_test.cc
+++ b/chromium/components/viz/service/display/viz_perf_test.cc
@@ -5,9 +5,44 @@
#include "components/viz/service/display/viz_perf_test.h"
#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
+#include "components/viz/common/quads/render_pass_io.h"
+#include "components/viz/test/paths.h"
namespace viz {
+
+bool CompositorRenderPassListFromJSON(
+ const std::string& tag,
+ const std::string& site,
+ uint32_t year,
+ size_t frame_index,
+ CompositorRenderPassList* render_pass_list) {
+ base::FilePath json_path;
+ if (!base::PathService::Get(Paths::DIR_TEST_DATA, &json_path))
+ return false;
+ std::string site_year = site + "_" + base::NumberToString(year);
+ std::string filename = base::NumberToString(frame_index);
+ while (filename.length() < 4)
+ filename = "0" + filename;
+ filename += ".json";
+ json_path = json_path.Append(FILE_PATH_LITERAL("render_pass_data"))
+ .AppendASCII(tag)
+ .AppendASCII(site_year)
+ .AppendASCII(filename);
+ if (!base::PathExists(json_path))
+ return false;
+ std::string json_text;
+ if (!base::ReadFileToString(json_path, &json_text))
+ return false;
+ absl::optional<base::Value> dict = base::JSONReader::Read(json_text);
+ if (!dict.has_value())
+ return false;
+ return CompositorRenderPassListFromDict(dict.value(), render_pass_list);
+}
+
namespace {
constexpr char kPerfTestTimeMillis[] = "perf-test-time-ms";
diff --git a/chromium/components/viz/service/display/viz_perf_test.h b/chromium/components/viz/service/display/viz_perf_test.h
index 5e42536fc3d..8ef6093e622 100644
--- a/chromium/components/viz/service/display/viz_perf_test.h
+++ b/chromium/components/viz/service/display/viz_perf_test.h
@@ -5,11 +5,23 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_VIZ_PERF_TEST_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_VIZ_PERF_TEST_H_
+#include <string>
+
#include "base/timer/lap_timer.h"
+#include "components/viz/common/quads/compositor_render_pass.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace viz {
+// Reads the specified JSON file and parses a CompositorRenderPassList from it,
+// storing the result in |render_pass_list|.
+bool CompositorRenderPassListFromJSON(
+ const std::string& tag,
+ const std::string& site,
+ uint32_t year,
+ size_t frame_index,
+ CompositorRenderPassList* render_pass_list);
+
// Viz perf test base class that sets up a lap timer with a specified duration.
class VizPerfTest : public testing::Test {
public:
diff --git a/chromium/components/viz/service/display/viz_pixel_test.h b/chromium/components/viz/service/display/viz_pixel_test.h
index 978bb5dda09..ee041e7fe54 100644
--- a/chromium/components/viz/service/display/viz_pixel_test.h
+++ b/chromium/components/viz/service/display/viz_pixel_test.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_VIZ_PIXEL_TEST_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_VIZ_PIXEL_TEST_H_
-#include <vector>
-
#include "cc/test/pixel_test.h"
#include "components/viz/test/test_types.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/components/viz/service/display_embedder/buffer_queue.h b/chromium/components/viz/service/display_embedder/buffer_queue.h
index c0519ba75a2..eaa491fd917 100644
--- a/chromium/components/viz/service/display_embedder/buffer_queue.h
+++ b/chromium/components/viz/service/display_embedder/buffer_queue.h
@@ -14,10 +14,10 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/ipc/common/surface_handle.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
@@ -153,7 +153,7 @@ class VIZ_SERVICE_EXPORT BufferQueue {
size_t max_buffers_ = 3U;
size_t allocated_count_;
// The |format_| is optional to prevent use of uninitialized values.
- base::Optional<gfx::BufferFormat> format_;
+ absl::optional<gfx::BufferFormat> format_;
// This surface is currently bound. This may be nullptr if no surface has
// been bound, or if allocation failed at bind.
std::unique_ptr<AllocatedSurface> current_surface_;
diff --git a/chromium/components/viz/service/display_embedder/buffer_queue_unittest.cc b/chromium/components/viz/service/display_embedder/buffer_queue_unittest.cc
index 223324c039d..0284c6802cd 100644
--- a/chromium/components/viz/service/display_embedder/buffer_queue_unittest.cc
+++ b/chromium/components/viz/service/display_embedder/buffer_queue_unittest.cc
@@ -92,10 +92,11 @@ class StubGpuMemoryBufferManager : public TestGpuMemoryBufferManager {
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle) override {
+ gpu::SurfaceHandle surface_handle,
+ base::WaitableEvent* shutdown_event) override {
if (surface_handle == gpu::kNullSurfaceHandle) {
return TestGpuMemoryBufferManager::CreateGpuMemoryBuffer(
- size, format, usage, surface_handle);
+ size, format, usage, surface_handle, shutdown_event);
}
if (allocate_succeeds_)
return base::WrapUnique<gfx::GpuMemoryBuffer>(
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface.cc b/chromium/components/viz/service/display_embedder/gl_output_surface.cc
index 4bed8df8711..f116099944a 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface.cc
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface.cc
@@ -163,7 +163,8 @@ void GLOutputSurface::ApplyExternalStencil() {}
void GLOutputSurface::DidReceiveSwapBuffersAck(
const gfx::SwapResponse& response) {
- client_->DidReceiveSwapBuffersAck(response.timings);
+ client_->DidReceiveSwapBuffersAck(response.timings,
+ /*release_fence=*/gfx::GpuFenceHandle());
}
void GLOutputSurface::HandlePartialSwap(
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_android.h b/chromium/components/viz/service/display_embedder/gl_output_surface_android.h
index ca6482961ac..6ccf9ec52ba 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_android.h
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_android.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_GL_OUTPUT_SURFACE_ANDROID_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_GL_OUTPUT_SURFACE_ANDROID_H_
-#include <memory>
-
#include "components/viz/service/display_embedder/gl_output_surface.h"
namespace viz {
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc b/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
index c25c095f8ec..75af07697cf 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
@@ -265,7 +265,8 @@ void GLOutputSurfaceBufferQueue::DidReceiveSwapBuffersAck(
}
buffer_queue_->PageFlipComplete();
- client()->DidReceiveSwapBuffersAck(response.timings);
+ client()->DidReceiveSwapBuffersAck(response.timings,
+ /*release_fence=*/gfx::GpuFenceHandle());
if (force_swap)
client()->SetNeedsRedrawRect(gfx::Rect(swap_size_));
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue_unittest.cc b/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue_unittest.cc
index 1c0b0245b47..e4354daf2cb 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue_unittest.cc
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue_unittest.cc
@@ -99,7 +99,8 @@ class GLOutputSurfaceBufferQueueTest : public ::testing::Test,
}
// OutputSurfaceClient implementation.
- void DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings) override {}
+ void DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings,
+ gfx::GpuFenceHandle release_fence) override {}
void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override {}
void DidReceiveTextureInUseResponses(
const gpu::TextureInUseResponses& responses) override {}
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_offscreen.cc b/chromium/components/viz/service/display_embedder/gl_output_surface_offscreen.cc
index dcb815eda89..7e61d17d3fe 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_offscreen.cc
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_offscreen.cc
@@ -127,7 +127,8 @@ void GLOutputSurfaceOffscreen::OnSwapBuffersComplete(
// Swap timings are not available since for offscreen there is no Swap, just a
// SignalSyncToken. We use base::TimeTicks::Now() as an overestimate.
auto now = base::TimeTicks::Now();
- client()->DidReceiveSwapBuffersAck({.swap_start = now});
+ client()->DidReceiveSwapBuffersAck({.swap_start = now},
+ /*release_fence=*/gfx::GpuFenceHandle());
client()->DidReceivePresentationFeedback(gfx::PresentationFeedback(
now, base::TimeDelta::FromMilliseconds(16), /*flags=*/0));
diff --git a/chromium/components/viz/service/display_embedder/image_context_impl.cc b/chromium/components/viz/service/display_embedder/image_context_impl.cc
index 5002a214f36..cf445e14014 100644
--- a/chromium/components/viz/service/display_embedder/image_context_impl.cc
+++ b/chromium/components/viz/service/display_embedder/image_context_impl.cc
@@ -23,7 +23,7 @@ ImageContextImpl::ImageContextImpl(
const gfx::Size& size,
ResourceFormat resource_format,
bool maybe_concurrent_reads,
- const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
+ const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
sk_sp<SkColorSpace> color_space)
: ImageContext(mailbox_holder,
size,
@@ -40,7 +40,7 @@ ImageContextImpl::ImageContextImpl(AggregatedRenderPassId render_pass_id,
: ImageContext(gpu::MailboxHolder(),
size,
resource_format,
- /*ycbcr_info=*/base::nullopt,
+ /*ycbcr_info=*/absl::nullopt,
std::move(color_space)),
render_pass_id_(render_pass_id),
mipmap_(mipmap ? GrMipMapped::kYes : GrMipMapped::kNo) {}
@@ -139,7 +139,8 @@ void ImageContextImpl::BeginAccessIfNecessary(
if (BindOrCopyTextureIfNecessary(texture_base, &texture_size) &&
texture_size != size()) {
DLOG(ERROR) << "Failed to fulfill the promise texture - texture "
- "size does not match TransferableResource size.";
+ "size does not match TransferableResource size: "
+ << texture_size.ToString() << " vs " << size().ToString();
CreateFallbackImage(context_state);
return;
}
@@ -202,7 +203,9 @@ bool ImageContextImpl::BeginAccessIfNecessaryForSharedImage(
if (representation->size() != size()) {
DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage "
- "size does not match TransferableResource size.";
+ "size does not match TransferableResource size: "
+ << representation->size().ToString() << " vs "
+ << size().ToString();
return false;
}
diff --git a/chromium/components/viz/service/display_embedder/image_context_impl.h b/chromium/components/viz/service/display_embedder/image_context_impl.h
index 422f456fdfd..83c5dd6f8a1 100644
--- a/chromium/components/viz/service/display_embedder/image_context_impl.h
+++ b/chromium/components/viz/service/display_embedder/image_context_impl.h
@@ -11,13 +11,13 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "components/viz/common/quads/aggregated_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/abseil-cpp/absl/types/optional.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"
@@ -50,7 +50,7 @@ class ImageContextImpl final : public ExternalUseClient::ImageContext {
const gfx::Size& size,
ResourceFormat resource_format,
bool maybe_concurrent_reads,
- const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
+ const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
sk_sp<SkColorSpace> color_space);
// TODO(https://crbug.com/991659): The use of ImageContext for
diff --git a/chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.cc b/chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.cc
index 2e347529284..44a4c4f4a7e 100644
--- a/chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.cc
+++ b/chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.cc
@@ -57,7 +57,8 @@ InProcessGpuMemoryBufferManager::CreateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle) {
+ gpu::SurfaceHandle surface_handle,
+ base::WaitableEvent* shutdown_event) {
gfx::GpuMemoryBufferId id(next_gpu_memory_id_++);
gfx::GpuMemoryBufferHandle buffer_handle =
gpu_memory_buffer_factory_->CreateGpuMemoryBuffer(
diff --git a/chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h b/chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h
index ec0a55eb7ac..516c0a22d0d 100644
--- a/chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h
+++ b/chromium/components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h
@@ -16,6 +16,10 @@
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace gpu {
class GpuMemoryBufferFactory;
class SyncPointManager;
@@ -42,7 +46,8 @@ class VIZ_SERVICE_EXPORT InProcessGpuMemoryBufferManager
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
- gpu::SurfaceHandle surface_handle) override;
+ gpu::SurfaceHandle surface_handle,
+ base::WaitableEvent* shutdown_event) override;
void SetDestructionSyncToken(gfx::GpuMemoryBuffer* buffer,
const gpu::SyncToken& sync_token) override;
void CopyGpuMemoryBufferAsync(
diff --git a/chromium/components/viz/service/display_embedder/output_presenter.h b/chromium/components/viz/service/display_embedder/output_presenter.h
index dc8f493d16b..9358d35046b 100644
--- a/chromium/components/viz/service/display_embedder/output_presenter.h
+++ b/chromium/components/viz/service/display_embedder/output_presenter.h
@@ -14,6 +14,7 @@
#include "components/viz/service/display/skia_output_surface.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/service/shared_image_representation.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gfx/presentation_feedback.h"
#include "ui/gfx/swap_result.h"
@@ -53,7 +54,7 @@ class VIZ_SERVICE_EXPORT OutputPresenter {
void PreGrContextSubmit();
virtual void BeginPresent() = 0;
- virtual void EndPresent() = 0;
+ virtual void EndPresent(gfx::GpuFenceHandle release_fence) = 0;
virtual int GetPresentCount() const = 0;
virtual void OnContextLost() = 0;
diff --git a/chromium/components/viz/service/display_embedder/output_presenter_fuchsia.cc b/chromium/components/viz/service/display_embedder/output_presenter_fuchsia.cc
index 8840fd0eeac..4bf6200d9eb 100644
--- a/chromium/components/viz/service/display_embedder/output_presenter_fuchsia.cc
+++ b/chromium/components/viz/service/display_embedder/output_presenter_fuchsia.cc
@@ -6,7 +6,6 @@
#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>
-#include <lib/sys/inspect/cpp/component.h>
#include <algorithm>
#include <memory>
@@ -47,15 +46,20 @@ void GrSemaphoresToZxEvents(gpu::VulkanImplementation* vulkan_implementation,
}
}
+zx::event DuplicateZxEvent(const zx::event& event) {
+ zx::event result;
+ zx_status_t status = event.duplicate(ZX_RIGHT_SAME_RIGHTS, &result);
+ ZX_DCHECK(status == ZX_OK, status);
+ return result;
+}
+
// Duplicates the given zx::events and stores in gfx::GpuFences.
std::vector<gfx::GpuFence> ZxEventsToGpuFences(
const std::vector<zx::event>& events) {
std::vector<gfx::GpuFence> fences;
for (const auto& event : events) {
gfx::GpuFenceHandle handle;
- zx_status_t status =
- event.duplicate(ZX_RIGHT_SAME_RIGHTS, &handle.owned_event);
- ZX_DCHECK(status == ZX_OK, status);
+ handle.owned_event = DuplicateZxEvent(event);
fences.emplace_back(std::move(handle));
}
return fences;
@@ -67,7 +71,7 @@ class PresenterImageFuchsia : public OutputPresenter::Image {
~PresenterImageFuchsia() override;
void BeginPresent() final;
- void EndPresent() final;
+ void EndPresent(gfx::GpuFenceHandle release_fence) final;
int GetPresentCount() const final;
void OnContextLost() final;
@@ -108,8 +112,9 @@ void PresenterImageFuchsia::BeginPresent() {
}
}
-void PresenterImageFuchsia::EndPresent() {
+void PresenterImageFuchsia::EndPresent(gfx::GpuFenceHandle release_fence) {
DCHECK(present_count_);
+ DCHECK(release_fence.is_null());
--present_count_;
if (!present_count_)
read_access_.reset();
@@ -135,18 +140,6 @@ void PresenterImageFuchsia::TakeSemaphores(
} // namespace
-OutputPresenterFuchsia::PendingOverlay::PendingOverlay(
- OverlayCandidate candidate,
- std::vector<gfx::GpuFence> release_fences)
- : candidate(std::move(candidate)),
- release_fences(std::move(release_fences)) {}
-OutputPresenterFuchsia::PendingOverlay::~PendingOverlay() = default;
-
-OutputPresenterFuchsia::PendingOverlay::PendingOverlay(PendingOverlay&&) =
- default;
-OutputPresenterFuchsia::PendingOverlay&
-OutputPresenterFuchsia::PendingOverlay::operator=(PendingOverlay&&) = default;
-
OutputPresenterFuchsia::PendingFrame::PendingFrame(uint32_t ordinal)
: ordinal(ordinal) {}
OutputPresenterFuchsia::PendingFrame::~PendingFrame() = default;
@@ -161,17 +154,11 @@ std::unique_ptr<OutputPresenterFuchsia> OutputPresenterFuchsia::Create(
SkiaOutputSurfaceDependency* deps,
gpu::SharedImageFactory* shared_image_factory,
gpu::SharedImageRepresentationFactory* representation_factory) {
- auto* inspector = base::ComponentInspectorForProcess();
-
if (!base::FeatureList::IsEnabled(
features::kUseSkiaOutputDeviceBufferQueue)) {
- inspector->root().CreateString("output_presenter", "swapchain", inspector);
return {};
}
- inspector->root().CreateString("output_presenter",
- "SkiaOutputDeviceBufferQueue", inspector);
-
// SetTextureToNewImagePipe() will call ScenicSession::Present() to send
// CreateImagePipe2Cmd creation command, but it will be processed only after
// vsync, which will delay buffer allocation of buffers in AllocateImages(),
@@ -212,7 +199,16 @@ OutputPresenterFuchsia::OutputPresenterFuchsia(
});
}
-OutputPresenterFuchsia::~OutputPresenterFuchsia() {}
+OutputPresenterFuchsia::~OutputPresenterFuchsia() {
+ // Signal release fences that were submitted in the last PresentImage(). This
+ // is necessary because ExternalVkImageBacking destructor will wait for the
+ // corresponding semaphores, while they may not be signaled by the ImagePipe.
+ for (auto& fence : release_fences_from_last_present_) {
+ auto status =
+ fence.signal(/*clear_mask=*/0, /*set_maks=*/ZX_EVENT_SIGNALED);
+ ZX_DCHECK(status == ZX_OK, status);
+ }
+}
void OutputPresenterFuchsia::InitializeCapabilities(
OutputSurface::Capabilities* capabilities) {
@@ -308,10 +304,9 @@ OutputPresenterFuchsia::AllocateImages(gfx::ColorSpace color_space,
}
// Create PresenterImageFuchsia for each buffer in the collection.
- uint32_t image_usage =
- gpu::SHARED_IMAGE_USAGE_RASTER | gpu::SHARED_IMAGE_USAGE_SCANOUT;
- if (vulkan->enforce_protected_memory())
- image_usage |= gpu::SHARED_IMAGE_USAGE_PROTECTED;
+ uint32_t image_usage = gpu::SHARED_IMAGE_USAGE_DISPLAY |
+ gpu::SHARED_IMAGE_USAGE_RASTER |
+ gpu::SHARED_IMAGE_USAGE_SCANOUT;
std::vector<std::unique_ptr<OutputPresenter::Image>> images;
images.reserve(num_images);
@@ -334,8 +329,9 @@ OutputPresenterFuchsia::AllocateImages(gfx::ColorSpace color_space,
auto mailbox = gpu::Mailbox::GenerateForSharedImage();
if (!shared_image_factory_->CreateSharedImage(
mailbox, gpu::kDisplayCompositorClientId, std::move(gmb_handle),
- buffer_format_, gpu::kNullSurfaceHandle, frame_size_, color_space,
- kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, image_usage)) {
+ buffer_format_, gfx::BufferPlane::DEFAULT, gpu::kNullSurfaceHandle,
+ frame_size_, color_space, kTopLeft_GrSurfaceOrigin,
+ kPremul_SkAlphaType, image_usage)) {
return {};
}
@@ -426,25 +422,8 @@ void OutputPresenterFuchsia::ScheduleOverlays(
if (!next_frame_)
next_frame_ = PendingFrame(next_frame_ordinal_++);
- for (size_t i = 0; i < overlays.size(); ++i) {
- auto semaphore = dependency_->GetSharedContextState()
- ->external_semaphore_pool()
- ->GetOrCreateSemaphore();
- gfx::GpuFenceHandle fence_handle;
- fence_handle.owned_event = semaphore.handle().TakeHandle();
-
- accesses[i]->SetReleaseFence(fence_handle.Clone());
- std::vector<gfx::GpuFence> release_fences;
- release_fences.emplace_back(std::move(fence_handle));
- next_frame_->overlays.emplace_back(std::move(overlays[i]),
- std::move(release_fences));
- // TODO(crbug.com/1144890): Enqueue overlay plane's acquire fences
- // after |supports_commit_overlay_planes| is supported. Overlay plane might
- // display the same Image more than once, which can create a fence
- // dependency that can be broken by a later Image. However, primary plane
- // implementation allows only one present at a time. In this scenario,
- // merging fences might cause hangs, see crbug.com/1151042.
- }
+ DCHECK(next_frame_->overlays.empty());
+ next_frame_->overlays = std::move(overlays);
}
void OutputPresenterFuchsia::PresentNextFrame() {
@@ -462,7 +441,7 @@ void OutputPresenterFuchsia::PresentNextFrame() {
"image_id", frame.image_id);
for (size_t i = 0; i < frame.overlays.size(); ++i) {
- auto& overlay = frame.overlays[i].candidate;
+ auto& overlay = frame.overlays[i];
DCHECK(overlay.mailbox.IsSharedImage());
auto pixmap =
dependency_->GetSharedImageManager()->GetNativePixmap(overlay.mailbox);
@@ -475,7 +454,7 @@ void OutputPresenterFuchsia::PresentNextFrame() {
gfx::ToRoundedRect(overlay.display_rect),
overlay.uv_rect, !overlay.is_opaque,
ZxEventsToGpuFences(frame.acquire_fences),
- std::move(frame.overlays[i].release_fences));
+ /*release_fences=*/{});
}
auto now = base::TimeTicks::Now();
@@ -498,6 +477,11 @@ void OutputPresenterFuchsia::PresentNextFrame() {
present_time = std::max(present_time, last_frame_present_time_);
last_frame_present_time_ = present_time;
+ release_fences_from_last_present_.clear();
+ for (auto& fence : frame.release_fences) {
+ release_fences_from_last_present_.push_back(DuplicateZxEvent(fence));
+ }
+
image_pipe_->PresentImage(
frame.image_id, present_time.ToZxTime(), std::move(frame.acquire_fences),
std::move(frame.release_fences),
diff --git a/chromium/components/viz/service/display_embedder/output_presenter_fuchsia.h b/chromium/components/viz/service/display_embedder/output_presenter_fuchsia.h
index a7465920a6e..8255b6e15e3 100644
--- a/chromium/components/viz/service/display_embedder/output_presenter_fuchsia.h
+++ b/chromium/components/viz/service/display_embedder/output_presenter_fuchsia.h
@@ -63,18 +63,6 @@ class VIZ_SERVICE_EXPORT OutputPresenterFuchsia : public OutputPresenter {
std::vector<ScopedOverlayAccess*> accesses) final;
private:
- struct PendingOverlay {
- PendingOverlay(OverlayCandidate candidate,
- std::vector<gfx::GpuFence> release_fences);
- ~PendingOverlay();
-
- PendingOverlay(PendingOverlay&&);
- PendingOverlay& operator=(PendingOverlay&&);
-
- OverlayCandidate candidate;
- std::vector<gfx::GpuFence> release_fences;
- };
-
struct PendingFrame {
explicit PendingFrame(uint32_t ordinal);
~PendingFrame();
@@ -98,7 +86,7 @@ class VIZ_SERVICE_EXPORT OutputPresenterFuchsia : public OutputPresenter {
bool remove_buffer_collection = false;
// Vector of overlays that are associated with this frame.
- std::vector<PendingOverlay> overlays;
+ std::vector<OverlayCandidate> overlays;
};
struct PresentationState {
@@ -130,10 +118,12 @@ class VIZ_SERVICE_EXPORT OutputPresenterFuchsia : public OutputPresenter {
std::unique_ptr<gpu::SysmemBufferCollection> buffer_collection_;
// The next frame to be submitted by SwapBuffers().
- base::Optional<PendingFrame> next_frame_;
+ absl::optional<PendingFrame> next_frame_;
base::circular_deque<PendingFrame> pending_frames_;
+ std::vector<zx::event> release_fences_from_last_present_;
+
// Ordinal that will be assigned to the next frame. Ordinals are used to
// calculate frame position relative to the current frame stored in
// |presentation_state_|. They will wrap around when reaching 2^32, but the
@@ -143,7 +133,7 @@ class VIZ_SERVICE_EXPORT OutputPresenterFuchsia : public OutputPresenter {
// Presentation information received from ImagePipe after rendering a frame.
// Used to calculate target presentation time for the frames presented in the
// future.
- base::Optional<PresentationState> presentation_state_;
+ absl::optional<PresentationState> presentation_state_;
// Target presentation time of tha last frame sent to ImagePipe. Stored here
// to ensure ImagePipe.Present() is not called with decreasing timestamps.
diff --git a/chromium/components/viz/service/display_embedder/output_presenter_gl.cc b/chromium/components/viz/service/display_embedder/output_presenter_gl.cc
index 936113a6621..926cd38b1ca 100644
--- a/chromium/components/viz/service/display_embedder/output_presenter_gl.cc
+++ b/chromium/components/viz/service/display_embedder/output_presenter_gl.cc
@@ -54,7 +54,7 @@ class PresenterImageGL : public OutputPresenter::Image {
uint32_t shared_image_usage);
void BeginPresent() final;
- void EndPresent() final;
+ void EndPresent(gfx::GpuFenceHandle release_fence) final;
int GetPresentCount() const final;
void OnContextLost() final;
@@ -131,10 +131,16 @@ void PresenterImageGL::BeginPresent() {
DCHECK(scoped_gl_read_access_);
}
-void PresenterImageGL::EndPresent() {
+void PresenterImageGL::EndPresent(gfx::GpuFenceHandle release_fence) {
DCHECK(present_count_);
if (--present_count_)
return;
+
+ // Check there is no release fence if we have a non-overlay read access.
+ DCHECK(!scoped_gl_read_access_ || release_fence.is_null());
+ if (scoped_overlay_read_access_)
+ scoped_overlay_read_access_->SetReleaseFence(std::move(release_fence));
+
scoped_overlay_read_access_.reset();
scoped_gl_read_access_.reset();
}
@@ -192,6 +198,12 @@ std::unique_ptr<OutputPresenterGL> OutputPresenterGL::Create(
ANativeWindow* window =
gpu::GpuSurfaceLookup::GetInstance()->AcquireNativeWidget(
deps->GetSurfaceHandle(), &can_be_used_with_surface_control);
+ base::ScopedClosureRunner release_runner(base::BindOnce(
+ [](gfx::AcceleratedWidget widget) {
+ if (widget)
+ ANativeWindow_release(widget);
+ },
+ window));
if (!window || !can_be_used_with_surface_control)
return nullptr;
// TODO(https://crbug.com/1012401): don't depend on GL.
@@ -425,8 +437,8 @@ void OutputPresenterGL::ScheduleOverlays(
overlay.shared_state->sorting_context_id,
gfx::Transform(overlay.shared_state->transform), gl_image,
overlay.contents_rect, gfx::ToEnclosingRect(overlay.bounds_rect),
- overlay.background_color, overlay.edge_aa_mask, opacity,
- overlay.filter));
+ overlay.background_color, overlay.edge_aa_mask, opacity, overlay.filter,
+ overlay.protected_video_type));
#endif
}
#endif // defined(OS_ANDROID) || defined(OS_APPLE) || defined(USE_OZONE)
diff --git a/chromium/components/viz/service/display_embedder/output_presenter_x11.cc b/chromium/components/viz/service/display_embedder/output_presenter_x11.cc
index 246a7ff5d2f..288e642606e 100644
--- a/chromium/components/viz/service/display_embedder/output_presenter_x11.cc
+++ b/chromium/components/viz/service/display_embedder/output_presenter_x11.cc
@@ -111,7 +111,7 @@ class PresenterImageX11 : public OutputPresenter::Image {
scoped_refptr<base::SingleThreadTaskRunner> x11_task_runner);
// OutputPresenterX11::Image:
void BeginPresent() final;
- void EndPresent() final;
+ void EndPresent(gfx::GpuFenceHandle release_fence) final;
int GetPresentCount() const final;
void OnContextLost() final;
@@ -272,8 +272,9 @@ bool PresenterImageX11::Initialize(
auto mailbox = gpu::Mailbox::GenerateForSharedImage();
if (!factory->CreateSharedImage(
mailbox, 0, std::move(gmb_handle), BufferFormat(format),
- deps->GetSurfaceHandle(), size, color_space, kTopLeft_GrSurfaceOrigin,
- kPremul_SkAlphaType, shared_image_usage)) {
+ gfx::BufferPlane::DEFAULT, deps->GetSurfaceHandle(), size,
+ color_space, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType,
+ shared_image_usage)) {
DLOG(ERROR) << "CreateSharedImage failed.";
return false;
}
@@ -348,8 +349,9 @@ void PresenterImageX11::BeginPresent() {
}
}
-void PresenterImageX11::EndPresent() {
+void PresenterImageX11::EndPresent(gfx::GpuFenceHandle release_fence) {
DCHECK(present_count_);
+ DCHECK(release_fence.is_null());
if (--present_count_)
return;
auto vk_semaphores = ToVkSemaphores(end_read_semaphores_);
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 79c800e77a1..bd64ee19f71 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
@@ -111,9 +111,10 @@ OutputSurfaceProviderImpl::CreateGpuDependency(
return nullptr;
if (renderer_settings.use_skia_renderer) {
+ DCHECK(task_executor_);
gpu::ScopedAllowScheduleGpuTask allow_schedule_gpu_task;
auto skia_deps = std::make_unique<SkiaOutputSurfaceDependencyImpl>(
- gpu_service_impl_, surface_handle);
+ gpu_service_impl_, task_executor_, surface_handle);
return std::make_unique<DisplayCompositorMemoryAndTaskController>(
std::move(skia_deps));
} else {
@@ -150,6 +151,16 @@ std::unique_ptr<OutputSurface> OutputSurfaceProviderImpl::CreateOutputSurface(
output_surface = SkiaOutputSurfaceImpl::Create(
gpu_dependency, renderer_settings, debug_settings);
}
+
+#if defined(OS_ANDROID)
+ // As with non-skia-renderer case, communicate the creation result to
+ // CompositorImplAndroid so that it can attempt to recreate the surface on
+ // failure.
+ display_client->OnContextCreationResult(
+ output_surface ? gpu::ContextResult::kSuccess
+ : gpu::ContextResult::kSurfaceFailure);
+#endif // defined(OS_ANDROID)
+
if (!output_surface) {
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMECAST)
// GPU compositing is expected to always work on Chrome OS so we should
diff --git a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc
index 9a8fabbe0d2..c2a177e6832 100644
--- a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc
+++ b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc
@@ -6,14 +6,15 @@
#include <stdint.h>
+#include <string>
#include <utility>
+#include "base/containers/contains.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory_mapping.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/process_memory_dump.h"
@@ -26,19 +27,53 @@ namespace viz {
class BitmapData : public base::RefCounted<BitmapData> {
public:
- explicit BitmapData(base::ReadOnlySharedMemoryMapping mapping)
+ BitmapData() = default;
+ BitmapData(const BitmapData& other) = delete;
+ BitmapData& operator=(const BitmapData& other) = delete;
+
+ virtual const void* GetMemory() const = 0;
+ virtual size_t GetSize() const = 0;
+ virtual const base::UnguessableToken& GetGUID() const = 0;
+
+ protected:
+ friend class base::RefCounted<BitmapData>;
+ virtual ~BitmapData() = default;
+};
+
+// Holds a bitmap stored in local memory.
+class LocalBitmapData : public BitmapData {
+ public:
+ explicit LocalBitmapData(SkBitmap bitmap)
+ : bitmap_(std::move(bitmap)), guid_(base::UnguessableToken::Create()) {}
+
+ const void* GetMemory() const override { return bitmap_.getPixels(); }
+ size_t GetSize() const override { return bitmap_.computeByteSize(); }
+ const base::UnguessableToken& GetGUID() const override { return guid_; }
+
+ private:
+ ~LocalBitmapData() override = default;
+
+ SkBitmap bitmap_;
+ // GUID to identify this bitmap in memory dumps.
+ base::UnguessableToken guid_;
+};
+
+// Holds a bitmap stored in shared memory.
+class SharedMemoryBitmapData : public BitmapData {
+ public:
+ explicit SharedMemoryBitmapData(base::ReadOnlySharedMemoryMapping mapping)
: mapping_(std::move(mapping)) {}
- const void* memory() const { return mapping_.memory(); }
- size_t size() const { return mapping_.size(); }
- const base::UnguessableToken& mapped_id() const { return mapping_.guid(); }
+ const void* GetMemory() const override { return mapping_.memory(); }
+ size_t GetSize() const override { return mapping_.size(); }
+ const base::UnguessableToken& GetGUID() const override {
+ return mapping_.guid();
+ }
private:
- friend class base::RefCounted<BitmapData>;
- ~BitmapData() {}
+ ~SharedMemoryBitmapData() override = default;
base::ReadOnlySharedMemoryMapping mapping_;
- DISALLOW_COPY_AND_ASSIGN(BitmapData);
};
namespace {
@@ -48,16 +83,15 @@ namespace {
// object is held alive.
class ServerSharedBitmap : public SharedBitmap {
public:
- // NOTE: bitmap_data->memory() is read-only but SharedBitmap expects a
+ // NOTE: bitmap_data->GetMemory() is read-only but SharedBitmap expects a
// uint8_t* pointer, even though all instances returned by a
// SharedBitmapManager will be used read-only.
explicit ServerSharedBitmap(scoped_refptr<BitmapData> bitmap_data)
: SharedBitmap(
- static_cast<uint8_t*>(const_cast<void*>(bitmap_data->memory()))),
+ static_cast<uint8_t*>(const_cast<void*>(bitmap_data->GetMemory()))),
bitmap_data_(std::move(bitmap_data)) {}
- ~ServerSharedBitmap() override {
- }
+ ~ServerSharedBitmap() override = default;
private:
scoped_refptr<BitmapData> bitmap_data_;
@@ -77,7 +111,6 @@ std::unique_ptr<SharedBitmap> ServerSharedBitmapManager::GetSharedBitmapFromId(
ResourceFormat format,
const SharedBitmapId& id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
auto it = handle_map_.find(id);
if (it == handle_map_.end()) {
return nullptr;
@@ -87,11 +120,11 @@ std::unique_ptr<SharedBitmap> ServerSharedBitmapManager::GetSharedBitmapFromId(
size_t bitmap_size;
if (!ResourceSizes::MaybeSizeInBytes(size, format, &bitmap_size) ||
- bitmap_size > data->size()) {
+ bitmap_size > data->GetSize()) {
return nullptr;
}
- if (!data->memory()) {
+ if (!data->GetMemory()) {
return nullptr;
}
@@ -105,7 +138,22 @@ ServerSharedBitmapManager::GetSharedBitmapTracingGUIDFromId(
if (it == handle_map_.end())
return {};
BitmapData* data = it->second.get();
- return data->mapped_id();
+ return data->GetGUID();
+}
+
+bool ServerSharedBitmapManager::LocalAllocatedSharedBitmap(
+ SkBitmap bitmap,
+ const SharedBitmapId& id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!bitmap.drawsNothing());
+
+ // Duplicate ids are not allowed.
+ if (base::Contains(handle_map_, id))
+ return false;
+
+ handle_map_[id] = base::MakeRefCounted<LocalBitmapData>(std::move(bitmap));
+
+ return true;
}
bool ServerSharedBitmapManager::ChildAllocatedSharedBitmap(
@@ -122,7 +170,8 @@ bool ServerSharedBitmapManager::ChildAllocatedSharedBitmap(
if (!mapping.IsValid())
return false;
- handle_map_[id] = base::MakeRefCounted<BitmapData>(std::move(mapping));
+ handle_map_[id] =
+ base::MakeRefCounted<SharedMemoryBitmapData>(std::move(mapping));
// Note: |region| will be destroyed at scope exit, releasing the fd.
return true;
@@ -152,14 +201,14 @@ bool ServerSharedBitmapManager::OnMemoryDump(
dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
- data->size());
+ data->GetSize());
// This GUID is the same returned by GetSharedBitmapTracingGUIDFromId() so
// other components use a consistent GUID for a given SharedBitmapId.
- base::UnguessableToken shared_memory_guid = data->mapped_id();
- DCHECK(!shared_memory_guid.is_empty());
- pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid,
- 0 /* importance*/);
+ base::UnguessableToken bitmap_guid = data->GetGUID();
+ DCHECK(!bitmap_guid.is_empty());
+ pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), bitmap_guid,
+ /*importance=*/0);
}
return true;
diff --git a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h
index b71bd4a4a38..50bb6f97d09 100644
--- a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h
+++ b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h
@@ -38,6 +38,8 @@ class VIZ_SERVICE_EXPORT ServerSharedBitmapManager
const SharedBitmapId& id) override;
base::UnguessableToken GetSharedBitmapTracingGUIDFromId(
const SharedBitmapId& id) override;
+ bool LocalAllocatedSharedBitmap(SkBitmap bitmap,
+ const SharedBitmapId& id) override;
bool ChildAllocatedSharedBitmap(base::ReadOnlySharedMemoryMapping mapping,
const SharedBitmapId& id) override;
void ChildDeletedSharedBitmap(const SharedBitmapId& id) override;
diff --git a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc
index bbe9e8982f6..973604fb967 100644
--- a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc
+++ b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc
@@ -4,11 +4,16 @@
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
+#include <utility>
+
#include "base/containers/span.h"
#include "components/viz/common/resources/bitmap_allocation.h"
#include "components/viz/common/resources/resource_sizes.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
namespace viz {
namespace {
@@ -84,6 +89,35 @@ TEST_F(ServerSharedBitmapManagerTest, TestCreate) {
shared_bitmap.reset();
}
+TEST_F(ServerSharedBitmapManagerTest, TestLocalCreate) {
+ constexpr gfx::Size bitmap_size(100, 100);
+ SharedBitmapId id = SharedBitmap::GenerateId();
+ void* pixels = nullptr;
+
+ {
+ // Allocate a local bitmap and fill it with red.
+ SkImageInfo info =
+ SkImageInfo::MakeN32Premul(bitmap_size.width(), bitmap_size.height());
+ SkBitmap bitmap;
+ bitmap.allocPixels(info);
+ bitmap.eraseColor(SK_ColorRED);
+
+ pixels = bitmap.getPixels();
+ EXPECT_TRUE(pixels);
+
+ manager()->LocalAllocatedSharedBitmap(std::move(bitmap), id);
+ }
+
+ std::unique_ptr<SharedBitmap> returned_bitmap =
+ manager()->GetSharedBitmapFromId(bitmap_size, RGBA_8888, id);
+
+ // Check the shared bitmap returns the address of pixmap allocated earlier.
+ ASSERT_TRUE(returned_bitmap);
+ EXPECT_EQ(pixels, returned_bitmap->pixels());
+
+ manager()->ChildDeletedSharedBitmap(id);
+}
+
TEST_F(ServerSharedBitmapManagerTest, AddDuplicate) {
gfx::Size bitmap_size(1, 1);
base::MappedReadOnlyRegion shm =
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 c3e281b9472..17f9bedfaf8 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_device.cc
@@ -155,7 +155,7 @@ bool SkiaOutputDevice::IsPrimaryPlaneOverlay() const {
}
void SkiaOutputDevice::SchedulePrimaryPlane(
- const base::Optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>&
+ const absl::optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>&
plane) {
if (plane)
NOTIMPLEMENTED();
@@ -194,17 +194,19 @@ void SkiaOutputDevice::FinishSwapBuffers(
gfx::SwapCompletionResult result,
const gfx::Size& size,
OutputSurfaceFrame frame,
- const base::Optional<gfx::Rect>& damage_area,
+ const absl::optional<gfx::Rect>& damage_area,
std::vector<gpu::Mailbox> released_overlays,
const gpu::Mailbox& primary_plane_mailbox) {
DCHECK(!pending_swaps_.empty());
+ auto release_fence = std::move(result.release_fence);
const gpu::SwapBuffersCompleteParams& params =
pending_swaps_.front().Complete(std::move(result), damage_area,
std::move(released_overlays),
primary_plane_mailbox);
- did_swap_buffer_complete_callback_.Run(params, size);
+ did_swap_buffer_complete_callback_.Run(params, size,
+ std::move(release_fence));
pending_swaps_.front().CallFeedback();
@@ -247,7 +249,7 @@ SkiaOutputDevice::SwapInfo::~SwapInfo() = default;
const gpu::SwapBuffersCompleteParams& SkiaOutputDevice::SwapInfo::Complete(
gfx::SwapCompletionResult result,
- const base::Optional<gfx::Rect>& damage_rect,
+ const absl::optional<gfx::Rect>& damage_rect,
std::vector<gpu::Mailbox> released_overlays,
const gpu::Mailbox& primary_plane_mailbox) {
params_.swap_response.result = result.swap_result;
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 63fc06bb1fb..e51844f9f65 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_device.h
@@ -12,13 +12,13 @@
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/overlay_processor_interface.h"
#include "components/viz/service/display/skia_output_surface.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/src/gpu/GrSemaphore.h"
#include "ui/gfx/swap_result.h"
@@ -90,7 +90,8 @@ class SkiaOutputDevice {
base::OnceCallback<void(const gfx::PresentationFeedback& feedback)>;
using DidSwapBufferCompleteCallback =
base::RepeatingCallback<void(gpu::SwapBuffersCompleteParams,
- const gfx::Size& pixel_size)>;
+ const gfx::Size& pixel_size,
+ gfx::GpuFenceHandle release_fence)>;
SkiaOutputDevice(
GrDirectContext* gr_context,
gpu::MemoryTracker* memory_tracker,
@@ -141,7 +142,7 @@ class SkiaOutputDevice {
// primary plane will be on screen when SwapBuffers() or PostSubBuffer() is
// called.
virtual void SchedulePrimaryPlane(
- const base::Optional<
+ const absl::optional<
OverlayProcessorInterface::OutputSurfaceOverlayPlane>& plane);
// Schedule overlays which will be on screen when SwapBuffers() or
@@ -177,7 +178,7 @@ class SkiaOutputDevice {
~SwapInfo();
const gpu::SwapBuffersCompleteParams& Complete(
gfx::SwapCompletionResult result,
- const base::Optional<gfx::Rect>& damage_area,
+ const absl::optional<gfx::Rect>& damage_area,
std::vector<gpu::Mailbox> released_overlays,
const gpu::Mailbox& primary_plane_mailbox);
void CallFeedback();
@@ -218,7 +219,7 @@ class SkiaOutputDevice {
gfx::SwapCompletionResult result,
const gfx::Size& size,
OutputSurfaceFrame frame,
- const base::Optional<gfx::Rect>& damage_area = base::nullopt,
+ const absl::optional<gfx::Rect>& damage_area = absl::nullopt,
std::vector<gpu::Mailbox> released_overlays = {},
const gpu::Mailbox& primary_plane_mailbox = gpu::Mailbox());
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 5294625e18f..341378c0d79 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
@@ -134,6 +134,11 @@ SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue(
capabilities_.preserve_buffer_content = true;
capabilities_.only_invalidates_damage_rect = false;
capabilities_.number_of_buffers = 3;
+#if defined(OS_ANDROID)
+ if (::features::IncreaseBufferCountForHighFrameRate()) {
+ capabilities_.number_of_buffers = 5;
+ }
+#endif
capabilities_.orientation_mode = OutputSurface::OrientationMode::kHardware;
// Force the number of max pending frames to one when the switch
@@ -178,18 +183,21 @@ OutputPresenter::Image* SkiaOutputDeviceBufferQueue::GetNextImage() {
}
void SkiaOutputDeviceBufferQueue::PageFlipComplete(
- OutputPresenter::Image* image) {
+ OutputPresenter::Image* image,
+ gfx::GpuFenceHandle release_fence) {
if (displayed_image_) {
DCHECK_EQ(displayed_image_->skia_representation()->size(), image_size_);
DCHECK_EQ(displayed_image_->GetPresentCount() > 1,
displayed_image_ == image);
- displayed_image_->EndPresent();
+ // MakeCurrent is necessary for inserting release fences and for
+ // BeginWriteSkia below.
+ context_state_->MakeCurrent(/*surface=*/nullptr);
+ displayed_image_->EndPresent(std::move(release_fence));
if (!displayed_image_->GetPresentCount()) {
available_images_.push_back(displayed_image_);
// Call BeginWriteSkia() for the next frame here to avoid some expensive
// operations on the critical code path.
- if (!available_images_.front()->sk_surface() &&
- context_state_->MakeCurrent(nullptr)) {
+ if (!available_images_.front()->sk_surface()) {
// BeginWriteSkia() may alter GL's state.
context_state_->set_need_context_state_reset(true);
available_images_.front()->BeginWriteSkia();
@@ -214,7 +222,7 @@ bool SkiaOutputDeviceBufferQueue::IsPrimaryPlaneOverlay() const {
}
void SkiaOutputDeviceBufferQueue::SchedulePrimaryPlane(
- const base::Optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>&
+ const absl::optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>&
plane) {
if (background_image_ && !background_image_is_scheduled_) {
background_image_->BeginPresent();
@@ -443,6 +451,9 @@ void SkiaOutputDeviceBufferQueue::DoFinishSwapBuffers(
for (const auto& mailbox : overlay_mailboxes) {
auto it = overlays_.find(mailbox);
DCHECK(it != overlays_.end());
+ if (!result.release_fence.is_null())
+ it->scoped_read_access()->SetReleaseFence(result.release_fence.Clone());
+
it->Unref();
}
@@ -480,13 +491,13 @@ void SkiaOutputDeviceBufferQueue::DoFinishSwapBuffers(
bool should_reallocate =
result.swap_result == gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS;
- DCHECK(!result.gpu_fence);
const auto& mailbox =
image ? image->skia_representation()->mailbox() : gpu::Mailbox();
+ auto release_fence = result.release_fence.Clone();
FinishSwapBuffers(std::move(result), size, std::move(frame),
- /*damage_area=*/base::nullopt, std::move(released_overlays),
+ /*damage_area=*/absl::nullopt, std::move(released_overlays),
mailbox);
- PageFlipComplete(image.get());
+ PageFlipComplete(image.get(), std::move(release_fence));
if (should_reallocate)
RecreateImages();
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 ed3a8660638..b2ffd63b44b 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
@@ -59,7 +59,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue : public SkiaOutputDevice {
bool IsPrimaryPlaneOverlay() const override;
void SchedulePrimaryPlane(
- const base::Optional<
+ const absl::optional<
OverlayProcessorInterface::OutputSurfaceOverlayPlane>& plane)
override;
void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays) override;
@@ -71,7 +71,8 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue : public SkiaOutputDevice {
base::CancelableOnceCallback<void(gfx::SwapCompletionResult)>;
OutputPresenter::Image* GetNextImage();
- void PageFlipComplete(OutputPresenter::Image* image);
+ void PageFlipComplete(OutputPresenter::Image* image,
+ gfx::GpuFenceHandle release_fence);
void FreeAllSurfaces();
// Used as callback for SwapBuffersAsync and PostSubBufferAsync to finish
// operation
@@ -132,7 +133,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue : public SkiaOutputDevice {
// for opaque accelerated widgets and event wiring.
bool needs_background_image_ = false;
// A 4x4 small image that will be scaled to cover an opaque region.
- std::unique_ptr<OutputPresenter::Image> background_image_ = nullptr;
+ std::unique_ptr<OutputPresenter::Image> background_image_;
// Set to true if background has been scheduled in a frame.
bool background_image_is_scheduled_ = false;
// Whether |SchedulePrimaryPlane| needs to wait for a paint before scheduling
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc b/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
index fd26bec76a0..dfd94943b85 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
@@ -169,6 +169,7 @@ class TestSharedImageBackingFactory : public gpu::SharedImageBackingFactory {
int client_id,
gfx::GpuMemoryBufferHandle handle,
gfx::BufferFormat format,
+ gfx::BufferPlane plane,
gpu::SurfaceHandle surface_handle,
const gfx::Size& size,
const gfx::ColorSpace& color_space,
@@ -262,7 +263,8 @@ class SkiaOutputDeviceBufferQueueTest : public TestOnGpu {
void SetUpOnMain() override {
gpu::SurfaceHandle surface_handle_ = gpu::kNullSurfaceHandle;
dependency_ = std::make_unique<SkiaOutputSurfaceDependencyImpl>(
- gpu_service_holder_->gpu_service(), surface_handle_);
+ gpu_service_holder_->gpu_service(),
+ gpu_service_holder_->task_executor(), surface_handle_);
}
void SetUpOnGpu() override {
@@ -283,7 +285,7 @@ class SkiaOutputDeviceBufferQueueTest : public TestOnGpu {
auto present_callback =
base::DoNothing::Repeatedly<gpu::SwapBuffersCompleteParams,
- const gfx::Size&>();
+ const gfx::Size&, gfx::GpuFenceHandle>();
output_device_ = std::make_unique<SkiaOutputDeviceBufferQueue>(
std::make_unique<OutputPresenterGL>(
@@ -369,7 +371,7 @@ class SkiaOutputDeviceBufferQueueTest : public TestOnGpu {
}
void ScheduleNoPrimaryPlane() {
- base::Optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>
+ absl::optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>
no_plane;
output_device_->SchedulePrimaryPlane(no_plane);
}
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_dawn.cc b/chromium/components/viz/service/display_embedder/skia_output_device_dawn.cc
index 0b258857b89..4f542231790 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_dawn.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_dawn.cc
@@ -26,7 +26,7 @@ constexpr wgpu::TextureFormat kSwapChainFormat =
wgpu::TextureFormat::RGBA8Unorm;
constexpr wgpu::TextureUsage kUsage =
- wgpu::TextureUsage::OutputAttachment | wgpu::TextureUsage::CopySrc;
+ wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
} // namespace
@@ -77,7 +77,7 @@ bool SkiaOutputDeviceDawn::Reshape(const gfx::Size& size,
CreateSwapChainImplementation();
wgpu::SwapChainDescriptor desc;
desc.implementation = reinterpret_cast<int64_t>(&swap_chain_implementation_);
- // TODO(sgilhuly): Use a wgpu::Surface in this call once the Surface-based
+ // TODO(rivr): Use a wgpu::Surface in this call once the Surface-based
// SwapChain API is ready.
swap_chain_ = context_provider_->GetDevice().CreateSwapChain(nullptr, &desc);
if (!swap_chain_)
@@ -98,7 +98,7 @@ void SkiaOutputDeviceDawn::SwapBuffers(BufferPresentedCallback feedback,
base::TimeTicks vsync_timebase;
base::TimeDelta vsync_interval;
uint32_t flags = 0;
- // TODO(sgilhuly): Add an async path for getting vsync parameters. The sync
+ // TODO(rivr): Add an async path for getting vsync parameters. The sync
// path is sufficient for VSyncProviderWin.
if (vsync_provider_ && vsync_provider_->GetVSyncParametersIfAvailable(
&vsync_timebase, &vsync_interval)) {
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 2a96a361c91..e3f83e219ac 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
@@ -354,14 +354,14 @@ void SkiaOutputDeviceGL::DoFinishSwapBuffersAsync(
const gfx::Size& size,
OutputSurfaceFrame frame,
gfx::SwapCompletionResult result) {
- DCHECK(!result.gpu_fence);
+ DCHECK(result.release_fence.is_null());
FinishSwapBuffers(std::move(result), size, std::move(frame));
}
void SkiaOutputDeviceGL::DoFinishSwapBuffers(const gfx::Size& size,
OutputSurfaceFrame frame,
gfx::SwapCompletionResult result) {
- DCHECK(!result.gpu_fence);
+ DCHECK(result.release_fence.is_null());
// Remove entries from |overlays_| for textures that weren't scheduled as an
// overlay this frame.
@@ -422,7 +422,6 @@ void SkiaOutputDeviceGL::ScheduleOverlays(
params.quad_rect = dc_layer.quad_rect;
DCHECK(dc_layer.transform.IsFlat());
params.transform = dc_layer.transform;
- params.is_clipped = dc_layer.is_clipped;
params.clip_rect = dc_layer.clip_rect;
params.protected_video_type = dc_layer.protected_video_type;
params.hdr_metadata = dc_layer.hdr_metadata;
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 65f2c530aae..6e1bcf10af9 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
@@ -25,6 +25,10 @@
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/vk/GrVkTypes.h"
+#if defined(OS_ANDROID)
+#include <android/native_window_jni.h>
+#endif
+
namespace viz {
// static
@@ -190,10 +194,7 @@ SkSurface* SkiaOutputDeviceVulkan::BeginPaint(
vk_image_info.fSampleCount = 1;
vk_image_info.fLevelCount = 1;
vk_image_info.fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED;
- vk_image_info.fProtected =
- vulkan_surface_->swap_chain()->use_protected_memory()
- ? GrProtected::kYes
- : GrProtected::kNo;
+ vk_image_info.fProtected = GrProtected::kNo;
const auto& vk_image_size = vulkan_surface_->image_size();
GrBackendRenderTarget render_target(vk_image_size.width(),
vk_image_size.height(),
@@ -261,6 +262,12 @@ bool SkiaOutputDeviceVulkan::Initialize() {
accelerated_widget =
gpu::GpuSurfaceLookup::GetInstance()->AcquireNativeWidget(
surface_handle_, &can_be_used_with_surface_control);
+ base::ScopedClosureRunner release_runner(base::BindOnce(
+ [](gfx::AcceleratedWidget widget) {
+ if (widget)
+ ANativeWindow_release(widget);
+ },
+ accelerated_widget));
#else
accelerated_widget = surface_handle_;
#endif
diff --git a/chromium/components/viz/service/display_embedder/skia_output_device_vulkan.h b/chromium/components/viz/service/display_embedder/skia_output_device_vulkan.h
index 1b17fc3bb98..316863da08f 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_device_vulkan.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_device_vulkan.h
@@ -10,12 +10,12 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
#include "gpu/ipc/common/surface_handle.h"
#include "gpu/vulkan/vulkan_swap_chain.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace gpu {
class VulkanSurface;
@@ -82,7 +82,7 @@ class SkiaOutputDeviceVulkan final : public SkiaOutputDevice {
const gpu::SurfaceHandle surface_handle_;
std::unique_ptr<gpu::VulkanSurface> vulkan_surface_;
- base::Optional<gpu::VulkanSwapChain::ScopedWrite> scoped_write_;
+ absl::optional<gpu::VulkanSwapChain::ScopedWrite> scoped_write_;
#if DCHECK_IS_ON()
bool image_modified_ = false;
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_dependency.h b/chromium/components/viz/service/display_embedder/skia_output_surface_dependency.h
index 86be475a729..348dd0ef7a5 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_surface_dependency.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_dependency.h
@@ -12,7 +12,6 @@
#include "base/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "build/build_config.h"
#include "components/viz/service/display/display_compositor_memory_and_task_controller.h"
#include "components/viz/service/viz_service_export.h"
@@ -20,6 +19,7 @@
#include "gpu/command_buffer/service/sequence_id.h"
#include "gpu/config/gpu_preferences.h"
#include "gpu/ipc/common/surface_handle.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkSurfaceCharacterization.h"
#include "ui/gl/gl_surface_format.h"
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_dependency_impl.cc b/chromium/components/viz/service/display_embedder/skia_output_surface_dependency_impl.cc
index accf893f211..42c2fc4d8e4 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_surface_dependency_impl.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_dependency_impl.cc
@@ -12,6 +12,7 @@
#include "build/build_config.h"
#include "components/viz/service/gl/gpu_service_impl.h"
#include "gpu/command_buffer/service/scheduler.h"
+#include "gpu/ipc/command_buffer_task_executor.h"
#include "gpu/ipc/gpu_task_scheduler_helper.h"
#include "gpu/ipc/scheduler_sequence.h"
#include "gpu/ipc/service/image_transport_surface.h"
@@ -21,8 +22,10 @@ namespace viz {
SkiaOutputSurfaceDependencyImpl::SkiaOutputSurfaceDependencyImpl(
GpuServiceImpl* gpu_service_impl,
+ gpu::CommandBufferTaskExecutor* gpu_task_executor,
gpu::SurfaceHandle surface_handle)
: gpu_service_impl_(gpu_service_impl),
+ gpu_task_executor_(gpu_task_executor),
surface_handle_(surface_handle),
client_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
@@ -30,8 +33,8 @@ SkiaOutputSurfaceDependencyImpl::~SkiaOutputSurfaceDependencyImpl() = default;
std::unique_ptr<gpu::SingleTaskSequence>
SkiaOutputSurfaceDependencyImpl::CreateSequence() {
- return std::make_unique<gpu::SchedulerSequence>(
- gpu_service_impl_->GetGpuScheduler());
+ // Using the |gpu_task_executor_| to create sequence on the gpu main thread.
+ return gpu_task_executor_->CreateSequence();
}
gpu::SharedImageManager*
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_dependency_impl.h b/chromium/components/viz/service/display_embedder/skia_output_surface_dependency_impl.h
index c793118243c..9ca43a646c7 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_surface_dependency_impl.h
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_dependency_impl.h
@@ -16,6 +16,10 @@ namespace base {
class SingleThreadTaskRunner;
}
+namespace gpu {
+class CommandBufferTaskExecutor;
+}
+
namespace viz {
class GpuServiceImpl;
@@ -23,8 +27,10 @@ class GpuServiceImpl;
class VIZ_SERVICE_EXPORT SkiaOutputSurfaceDependencyImpl
: public SkiaOutputSurfaceDependency {
public:
- SkiaOutputSurfaceDependencyImpl(GpuServiceImpl* gpu_service_impl,
- gpu::SurfaceHandle surface_handle);
+ SkiaOutputSurfaceDependencyImpl(
+ GpuServiceImpl* gpu_service_impl,
+ gpu::CommandBufferTaskExecutor* gpu_task_executor,
+ gpu::SurfaceHandle surface_handle);
~SkiaOutputSurfaceDependencyImpl() override;
std::unique_ptr<gpu::SingleTaskSequence> CreateSequence() override;
@@ -65,6 +71,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceDependencyImpl
private:
GpuServiceImpl* const gpu_service_impl_;
+ gpu::CommandBufferTaskExecutor* const gpu_task_executor_;
const gpu::SurfaceHandle surface_handle_;
scoped_refptr<base::SingleThreadTaskRunner> client_thread_task_runner_;
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 0cd9767cb92..4579f810e19 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
@@ -365,7 +365,7 @@ sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromYUV(
DCHECK(context->origin() == kTopLeft_GrSurfaceOrigin);
formats[i] = GetGrBackendFormatForTexture(
context->resource_format(), context->mailbox_holder().texture_target,
- /*ycbcr_info=*/base::nullopt);
+ /*ycbcr_info=*/absl::nullopt);
// NOTE: We don't have promises for individual planes, but still need format
// for fallback
@@ -409,7 +409,7 @@ SkiaOutputSurfaceImpl::CreateImageContext(
const gfx::Size& size,
ResourceFormat format,
bool maybe_concurrent_reads,
- const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
+ const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
sk_sp<SkColorSpace> color_space) {
return std::make_unique<ImageContextImpl>(holder, size, format,
maybe_concurrent_reads, ycbcr_info,
@@ -444,18 +444,11 @@ void SkiaOutputSurfaceImpl::SwapBuffers(OutputSurfaceFrame frame) {
}
current_buffer_modified_ = false;
- base::TimeTicks post_task_timestamp;
- if (should_measure_next_post_task_) {
- should_measure_next_post_task_ = false;
- post_task_timestamp = base::TimeTicks::Now();
- has_enqueued_measured_post_task_ = true;
- }
-
// 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::SwapBuffers,
- base::Unretained(impl_on_gpu_.get()),
- post_task_timestamp, std::move(frame));
+ auto callback =
+ base::BindOnce(&SkiaOutputSurfaceImplOnGpu::SwapBuffers,
+ base::Unretained(impl_on_gpu_.get()), std::move(frame));
EnqueueGpuTask(std::move(callback), std::move(resource_sync_tokens_),
/*make_current=*/true,
/*need_framebuffer=*/!dependency_->IsOffscreen());
@@ -577,18 +570,11 @@ void SkiaOutputSurfaceImpl::EndPaint(base::OnceClosure on_finished) {
it->second->clear_image();
}
- base::TimeTicks post_task_timestamp;
- if (should_measure_next_post_task_) {
- should_measure_next_post_task_ = false;
- post_task_timestamp = base::TimeTicks::Now();
- }
-
- auto task =
- base::BindOnce(&SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass,
- base::Unretained(impl_on_gpu_.get()),
- post_task_timestamp, current_paint_->render_pass_id(),
- std::move(ddl), std::move(images_in_current_paint_),
- resource_sync_tokens_, std::move(on_finished));
+ auto task = base::BindOnce(
+ &SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass,
+ base::Unretained(impl_on_gpu_.get()), current_paint_->render_pass_id(),
+ std::move(ddl), std::move(images_in_current_paint_),
+ resource_sync_tokens_, std::move(on_finished));
EnqueueGpuTask(std::move(task), std::move(resource_sync_tokens_),
/*make_current=*/true, /*need_framebuffer=*/false);
} else {
@@ -634,7 +620,7 @@ sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromRenderPass(
SkColorType color_type =
ResourceFormatToClosestSkColorType(true /* gpu_compositing */, format);
GrBackendFormat backend_format = GetGrBackendFormatForTexture(
- format, GL_TEXTURE_2D, /*ycbcr_info=*/base::nullopt);
+ format, GL_TEXTURE_2D, /*ycbcr_info=*/absl::nullopt);
image_context->SetImage(
current_paint_->recorder()->makePromiseTexture(
backend_format, image_context->size().width(),
@@ -754,16 +740,15 @@ bool SkiaOutputSurfaceImpl::Initialize() {
// calling it bypasses SkiaOutputSurfaceDependency.
GpuVSyncCallback vsync_callback_runner = base::DoNothing();
#else
- GpuVSyncCallback vsync_callback_runner =
- base::BindRepeating(
- [](scoped_refptr<base::SingleThreadTaskRunner> runner,
- base::WeakPtr<SkiaOutputSurfaceImpl> weak_ptr,
- base::TimeTicks timebase, base::TimeDelta interval) {
- runner->PostTask(FROM_HERE,
- base::BindOnce(&SkiaOutputSurfaceImpl::OnGpuVSync,
- weak_ptr, timebase, interval));
- },
- base::ThreadTaskRunnerHandle::Get(), weak_ptr_);
+ GpuVSyncCallback vsync_callback_runner = base::BindRepeating(
+ [](scoped_refptr<base::SingleThreadTaskRunner> runner,
+ base::WeakPtr<SkiaOutputSurfaceImpl> weak_ptr,
+ base::TimeTicks timebase, base::TimeDelta interval) {
+ runner->PostTask(FROM_HERE,
+ base::BindOnce(&SkiaOutputSurfaceImpl::OnGpuVSync,
+ weak_ptr, timebase, interval));
+ },
+ base::ThreadTaskRunnerHandle::Get(), weak_ptr_);
#endif
bool result = false;
@@ -858,10 +843,7 @@ SkiaOutputSurfaceImpl::CreateSkSurfaceCharacterization(
cache_max_resource_bytes, image_info, backend_format,
0 /* sampleCount */, surface_origin, surface_props, mipmap,
capabilities_.uses_default_gl_framebuffer, false /* isTextureable */,
- impl_on_gpu_->GetGpuPreferences().enforce_vulkan_protected_memory
- ? GrProtected::kYes
- : GrProtected::kNo,
- false /* vkRTSupportsInputAttachment */,
+ GrProtected::kNo, false /* vkRTSupportsInputAttachment */,
capabilities_.root_is_vulkan_secondary_command_buffer);
VkFormat vk_format = VK_FORMAT_UNDEFINED;
LOG_IF(DFATAL, !characterization.isValid())
@@ -878,9 +860,7 @@ SkiaOutputSurfaceImpl::CreateSkSurfaceCharacterization(
<< "\n backend_format.asVkFormat() vk_format="
<< static_cast<int>(vk_format)
<< "\n surface_origin=" << static_cast<int>(surface_origin)
- << "\n willGlFBO0=" << capabilities_.uses_default_gl_framebuffer
- << "\n isProtected="
- << impl_on_gpu_->GetGpuPreferences().enforce_vulkan_protected_memory;
+ << "\n willGlFBO0=" << capabilities_.uses_default_gl_framebuffer;
return characterization;
}
@@ -897,17 +877,15 @@ SkiaOutputSurfaceImpl::CreateSkSurfaceCharacterization(
auto characterization = gr_context_thread_safe_->createCharacterization(
cache_max_resource_bytes, image_info, backend_format, 0 /* sampleCount */,
kTopLeft_GrSurfaceOrigin, surface_props, mipmap,
- false /* willUseGLFBO0 */, true /* isTextureable */,
- impl_on_gpu_->GetGpuPreferences().enforce_vulkan_protected_memory
- ? GrProtected::kYes
- : GrProtected::kNo);
+ false /* willUseGLFBO0 */, true /* isTextureable */, GrProtected::kNo);
DCHECK(characterization.isValid());
return characterization;
}
void SkiaOutputSurfaceImpl::DidSwapBuffersComplete(
gpu::SwapBuffersCompleteParams params,
- const gfx::Size& pixel_size) {
+ const gfx::Size& pixel_size,
+ gfx::GpuFenceHandle release_fence) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(client_);
last_swapped_mailbox_ = params.primary_plane_mailbox;
@@ -930,7 +908,8 @@ void SkiaOutputSurfaceImpl::DidSwapBuffersComplete(
if (!params.ca_layer_params.is_empty)
client_->DidReceiveCALayerParams(params.ca_layer_params);
- client_->DidReceiveSwapBuffersAck(params.swap_response.timings);
+ client_->DidReceiveSwapBuffersAck(params.swap_response.timings,
+ std::move(release_fence));
if (!params.released_overlays.empty())
client_->DidReceiveReleasedOverlays(params.released_overlays);
if (needs_swap_size_notifications_)
@@ -991,14 +970,25 @@ void SkiaOutputSurfaceImpl::FlushGpuTasks(bool wait_for_finish) {
auto event =
wait_for_finish ? std::make_unique<base::WaitableEvent>() : nullptr;
+ base::TimeTicks post_task_timestamp;
+ if (should_measure_next_post_task_) {
+ post_task_timestamp = base::TimeTicks::Now();
+ }
+
auto callback = base::BindOnce(
[](std::vector<GpuTask> tasks, base::WaitableEvent* event,
- SkiaOutputSurfaceImplOnGpu* impl_on_gpu, bool need_framebuffer) {
+ SkiaOutputSurfaceImplOnGpu* impl_on_gpu, bool make_current,
+ bool need_framebuffer, base::TimeTicks post_task_timestamp) {
gpu::ContextUrl::SetActiveUrl(GetActiveUrl());
- // MakeCurrent() will mark context lost in SkiaOutputSurfaceImplOnGpu,
- // if it fails.
- if (impl_on_gpu)
- impl_on_gpu->MakeCurrent(need_framebuffer);
+ // impl_on_gpu can be null during destruction.
+ if (impl_on_gpu) {
+ if (!post_task_timestamp.is_null())
+ impl_on_gpu->SetDrawTimings(post_task_timestamp);
+ // MakeCurrent() will mark context lost in SkiaOutputSurfaceImplOnGpu,
+ // if it fails.
+ if (make_current)
+ impl_on_gpu->MakeCurrent(need_framebuffer);
+ }
// Each task can check SkiaOutputSurfaceImplOnGpu::contest_is_lost_
// to detect errors.
for (auto& task : tasks) {
@@ -1007,17 +997,17 @@ void SkiaOutputSurfaceImpl::FlushGpuTasks(bool wait_for_finish) {
if (event)
event->Signal();
},
- std::move(gpu_tasks_), event.get(),
- make_current_ ? impl_on_gpu_.get() : nullptr, need_framebuffer_);
+ std::move(gpu_tasks_), event.get(), impl_on_gpu_.get(), make_current_,
+ need_framebuffer_, post_task_timestamp);
gpu::GpuTaskSchedulerHelper::ReportingCallback reporting_callback;
- if (has_enqueued_measured_post_task_) {
+ if (should_measure_next_post_task_) {
// Note that the usage of base::Unretained() with the impl_on_gpu_ is
// considered safe as it is also owned by |callback| and share the same
// lifetime.
- reporting_callback =
- base::Bind(&SkiaOutputSurfaceImplOnGpu::SetDependenciesResolvedTimings,
- base::Unretained(impl_on_gpu_.get()));
+ reporting_callback = base::BindOnce(
+ &SkiaOutputSurfaceImplOnGpu::SetDependenciesResolvedTimings,
+ base::Unretained(impl_on_gpu_.get()));
}
gpu_task_scheduler_->ScheduleGpuTask(std::move(callback),
@@ -1026,7 +1016,7 @@ void SkiaOutputSurfaceImpl::FlushGpuTasks(bool wait_for_finish) {
make_current_ = false;
need_framebuffer_ = false;
- has_enqueued_measured_post_task_ = false;
+ should_measure_next_post_task_ = false;
gpu_task_sync_tokens_.clear();
gpu_tasks_.clear();
@@ -1037,7 +1027,7 @@ void SkiaOutputSurfaceImpl::FlushGpuTasks(bool wait_for_finish) {
GrBackendFormat SkiaOutputSurfaceImpl::GetGrBackendFormatForTexture(
ResourceFormat resource_format,
uint32_t gl_texture_target,
- const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info) {
+ const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info) {
if (dependency_->IsUsingVulkan()) {
#if BUILDFLAG(ENABLE_VULKAN)
if (!ycbcr_info) {
@@ -1181,4 +1171,14 @@ void SkiaOutputSurfaceImpl::PreserveChildSurfaceControls() {
/*need_framebuffer=*/false);
}
+void SkiaOutputSurfaceImpl::InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) {
+ auto task = base::BindOnce(
+ &SkiaOutputSurfaceImplOnGpu::InitDelegatedInkPointRendererReceiver,
+ base::Unretained(impl_on_gpu_.get()), std::move(pending_receiver));
+ EnqueueGpuTask(std::move(task), {}, /*make_current=*/false,
+ /*need_framebuffer=*/false);
+}
+
} // namespace viz
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 05b368ccfea..dea6f74111e 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
@@ -11,7 +11,6 @@
#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"
@@ -23,10 +22,18 @@
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/ipc/common/vulkan_ycbcr_info.h"
#include "gpu/ipc/in_process_command_buffer.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkDeferredDisplayListRecorder.h"
#include "third_party/skia/include/core/SkOverdrawCanvas.h"
#include "third_party/skia/include/core/SkSurfaceCharacterization.h"
+namespace gfx {
+namespace mojom {
+class DelegatedInkPointRenderer;
+} // namespace mojom
+} // namespace gfx
+
namespace viz {
class ImageContextImpl;
@@ -149,9 +156,13 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
const gfx::Size& size,
ResourceFormat format,
bool maybe_concurrent_reads,
- const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
+ const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info,
sk_sp<SkColorSpace> color_space) override;
+ void InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) override;
+
// Set the fields of |capabilities_| and propagates to |impl_on_gpu_|. Should
// be called after BindToClient().
void SetCapabilitiesForTesting(gfx::SurfaceOrigin output_surface_origin);
@@ -172,7 +183,8 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
sk_sp<SkColorSpace> color_space,
bool is_root_render_pass);
void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params,
- const gfx::Size& pixel_size);
+ const gfx::Size& pixel_size,
+ gfx::GpuFenceHandle release_fence);
void BufferPresented(const gfx::PresentationFeedback& feedback);
// Provided as a callback for the GPU thread.
@@ -188,7 +200,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
GrBackendFormat GetGrBackendFormatForTexture(
ResourceFormat resource_format,
uint32_t gl_texture_target,
- const base::Optional<gpu::VulkanYCbCrInfo>& ycbcr_info);
+ const absl::optional<gpu::VulkanYCbCrInfo>& ycbcr_info);
void ContextLost();
void RecreateRootRecorder();
@@ -216,7 +228,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
gfx::BufferFormat format_;
bool is_hdr_ = false;
SkSurfaceCharacterization characterization_;
- base::Optional<SkDeferredDisplayListRecorder> root_recorder_;
+ absl::optional<SkDeferredDisplayListRecorder> root_recorder_;
class ScopedPaint {
public:
@@ -234,23 +246,23 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
SkDeferredDisplayListRecorder* recorder_;
// If we need new recorder for this Paint (i.e it's not root render pass),
// it's stored here
- base::Optional<SkDeferredDisplayListRecorder> recorder_storage_;
+ absl::optional<SkDeferredDisplayListRecorder> recorder_storage_;
const AggregatedRenderPassId render_pass_id_;
};
// This holds current paint info
- base::Optional<ScopedPaint> current_paint_;
+ absl::optional<ScopedPaint> current_paint_;
// The SkDDL recorder is used for overdraw feedback. It is created by
// BeginPaintOverdraw, and FinishPaintCurrentFrame will turn it into a SkDDL
// and play the SkDDL back on the GPU thread.
- base::Optional<SkDeferredDisplayListRecorder> overdraw_surface_recorder_;
+ absl::optional<SkDeferredDisplayListRecorder> overdraw_surface_recorder_;
// |overdraw_canvas_| is used to record draw counts.
- base::Optional<SkOverdrawCanvas> overdraw_canvas_;
+ absl::optional<SkOverdrawCanvas> overdraw_canvas_;
// |nway_canvas_| contains |overdraw_canvas_| and root canvas.
- base::Optional<SkNWayCanvas> nway_canvas_;
+ absl::optional<SkNWayCanvas> nway_canvas_;
// The cache for promise image created from render passes.
base::flat_map<AggregatedRenderPassId, std::unique_ptr<ImageContextImpl>>
@@ -293,13 +305,10 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
sk_sp<GrContextThreadSafeProxy> gr_context_thread_safe_;
bool has_set_draw_rectangle_for_frame_ = false;
- base::Optional<gfx::Rect> draw_rectangle_;
+ absl::optional<gfx::Rect> draw_rectangle_;
bool should_measure_next_post_task_ = false;
- // whether thee is a measured post task enqueued.
- bool has_enqueued_measured_post_task_ = false;
-
// GPU tasks pending for flush.
std::vector<GpuTask> gpu_tasks_;
// GPU sync tokens which are depended by |gpu_tasks_|.
@@ -311,7 +320,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
bool use_damage_area_from_skia_output_device_ = false;
// Damage area of the current buffer. Differ to the last submit buffer.
- base::Optional<gfx::Rect> damage_of_current_buffer_;
+ absl::optional<gfx::Rect> damage_of_current_buffer_;
// Current buffer index.
size_t current_buffer_ = 0;
// Accumulates framebuffer damage since last drawing to a particular buffer.
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 c9a1e808962..0eb1e4fd852 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
@@ -7,7 +7,6 @@
#include "base/atomic_sequence_num.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/optional.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
@@ -41,11 +40,13 @@
#include "gpu/ipc/common/gpu_surface_lookup.h"
#include "gpu/vulkan/buildflags.h"
#include "skia/buildflags.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/libyuv/include/libyuv/planar_functions.h"
#include "third_party/skia/include/core/SkDeferredDisplayList.h"
#include "third_party/skia/include/core/SkPixelRef.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/gpu_fence_handle.h"
#include "ui/gl/gl_surface.h"
#if BUILDFLAG(ENABLE_VULKAN)
@@ -659,7 +660,7 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame(
std::vector<ImageContextImpl*> image_contexts,
std::vector<gpu::SyncToken> sync_tokens,
base::OnceClosure on_finished,
- base::Optional<gfx::Rect> draw_rectangle) {
+ absl::optional<gfx::Rect> draw_rectangle) {
TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!scoped_output_device_paint_);
@@ -692,7 +693,7 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame(
dependency_->ScheduleGrContextCleanup();
{
- base::Optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
+ absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
if (dependency_->GetGrShaderCache()) {
cache_use.emplace(dependency_->GetGrShaderCache(),
gpu::kDisplayCompositorClientId);
@@ -758,15 +759,10 @@ void SkiaOutputSurfaceImplOnGpu::ScheduleOutputSurfaceAsOverlay(
}
void SkiaOutputSurfaceImplOnGpu::SwapBuffers(
- base::TimeTicks post_task_timestamp,
OutputSurfaceFrame frame) {
TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::SwapBuffers");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (!post_task_timestamp.is_null()) {
- output_device_->SetDrawTimings(post_task_timestamp, base::TimeTicks::Now());
- }
-
SwapBuffersInternal(std::move(frame));
}
@@ -776,13 +772,17 @@ void SkiaOutputSurfaceImplOnGpu::SetDependenciesResolvedTimings(
output_device_->SetDependencyTimings(task_ready);
}
+void SkiaOutputSurfaceImplOnGpu::SetDrawTimings(base::TimeTicks task_posted) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ output_device_->SetDrawTimings(task_posted, base::TimeTicks::Now());
+}
+
void SkiaOutputSurfaceImplOnGpu::SwapBuffersSkipped() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- SwapBuffersInternal(base::nullopt);
+ SwapBuffersInternal(absl::nullopt);
}
void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass(
- base::TimeTicks post_task_timestamp,
AggregatedRenderPassId id,
sk_sp<SkDeferredDisplayList> ddl,
std::vector<ImageContextImpl*> image_contexts,
@@ -792,10 +792,6 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass(
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(ddl);
- if (!post_task_timestamp.is_null()) {
- output_device_->SetDrawTimings(post_task_timestamp, base::TimeTicks::Now());
- }
-
if (context_is_lost_)
return;
@@ -812,7 +808,7 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass(
}
{
- base::Optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
+ absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
if (dependency_->GetGrShaderCache()) {
cache_use.emplace(dependency_->GetGrShaderCache(),
gpu::kDisplayCompositorClientId);
@@ -912,7 +908,7 @@ void SkiaOutputSurfaceImplOnGpu::CopyOutput(
bool need_discard_alpha =
from_framebuffer && (output_device_->is_emulated_rgbx());
if (need_discard_alpha) {
- base::Optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
+ absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
if (dependency_->GetGrShaderCache()) {
cache_use.emplace(dependency_->GetGrShaderCache(),
gpu::kDisplayCompositorClientId);
@@ -924,7 +920,7 @@ void SkiaOutputSurfaceImplOnGpu::CopyOutput(
surface->flush();
}
- base::Optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
+ absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
if (dependency_->GetGrShaderCache()) {
cache_use.emplace(dependency_->GetGrShaderCache(),
gpu::kDisplayCompositorClientId);
@@ -1069,9 +1065,9 @@ void SkiaOutputSurfaceImplOnGpu::CopyOutput(
&SkiaOutputSurfaceImplOnGpu::DestroySharedImageOnImplThread,
weak_ptr_factory_.GetWeakPtr(), std::move(representation),
context_state_);
- auto main_callback = SingleReleaseCallback::Create(base::BindOnce(
- &PostTaskFromMainToImplThread, base::ThreadTaskRunnerHandle::Get(),
- std::move(release_callback)));
+ auto main_callback = base::BindOnce(&PostTaskFromMainToImplThread,
+ base::ThreadTaskRunnerHandle::Get(),
+ std::move(release_callback));
request->SendResult(std::make_unique<CopyOutputTextureResult>(
geometry.result_bounds, mailbox, gpu::SyncToken(), color_space,
std::move(main_callback)));
@@ -1209,7 +1205,7 @@ void SkiaOutputSurfaceImplOnGpu::ScheduleOverlays(
}
if (!scoped_write_accesses.empty()) {
- base::Optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
+ absl::optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
if (dependency_->GetGrShaderCache()) {
cache_use.emplace(dependency_->GetGrShaderCache(),
gpu::kDisplayCompositorClientId);
@@ -1488,7 +1484,7 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForDawn() {
GetDidSwapBuffersCompleteCallback());
} else {
#if defined(USE_X11) || defined(USE_OZONE_PLATFORM_X11)
- // TODO(sgilhuly): Set up a Vulkan swapchain so that Linux can also use
+ // TODO(rivr): Set up a Vulkan swapchain so that Linux can also use
// SkiaOutputDeviceDawn.
if (MayFallBackToSkiaOutputDeviceX11()) {
output_device_ = SkiaOutputDeviceX11::Create(
@@ -1553,7 +1549,7 @@ void SkiaOutputSurfaceImplOnGpu::ReleaseFenceSync(uint64_t sync_fence_release) {
}
void SkiaOutputSurfaceImplOnGpu::SwapBuffersInternal(
- base::Optional<OutputSurfaceFrame> frame) {
+ absl::optional<OutputSurfaceFrame> frame) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(output_device_);
@@ -1586,7 +1582,7 @@ void SkiaOutputSurfaceImplOnGpu::SwapBuffersInternal(
}
void SkiaOutputSurfaceImplOnGpu::PostSubmit(
- base::Optional<OutputSurfaceFrame> frame) {
+ absl::optional<OutputSurfaceFrame> frame) {
promise_image_access_helper_.EndAccess();
scoped_output_device_paint_.reset();
@@ -1687,7 +1683,8 @@ void SkiaOutputSurfaceImplOnGpu::BufferPresented(
void SkiaOutputSurfaceImplOnGpu::DidSwapBuffersCompleteInternal(
gpu::SwapBuffersCompleteParams params,
- const gfx::Size& pixel_size) {
+ const gfx::Size& pixel_size,
+ gfx::GpuFenceHandle release_fence) {
if (params.swap_response.result == gfx::SwapResult::SWAP_FAILED) {
DLOG(ERROR) << "Context lost on SWAP_FAILED";
if (!context_state_->IsCurrent(nullptr) ||
@@ -1727,8 +1724,9 @@ void SkiaOutputSurfaceImplOnGpu::DidSwapBuffersCompleteInternal(
#endif
- PostTaskToClientThread(
- base::BindOnce(did_swap_buffer_complete_callback_, params, pixel_size));
+ PostTaskToClientThread(base::BindOnce(did_swap_buffer_complete_callback_,
+ params, pixel_size,
+ std::move(release_fence)));
}
SkiaOutputSurfaceImplOnGpu::DidSwapBufferCompleteCallback
@@ -1854,4 +1852,13 @@ SkiaOutputSurfaceImplOnGpu::GetOrCreateRenderPassOverlayBacking(
}
#endif
+void SkiaOutputSurfaceImplOnGpu::InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver) {
+ if (gl_surface_) {
+ gl_surface_->InitDelegatedInkPointRendererReceiver(
+ std::move(pending_receiver));
+ }
+}
+
} // namespace viz
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 8cf630fd941..885aa1f9479 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
@@ -10,7 +10,6 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"
@@ -31,12 +30,17 @@
#include "gpu/ipc/service/context_url.h"
#include "gpu/ipc/service/display_context.h"
#include "gpu/ipc/service/image_transport_surface_delegate.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkDeferredDisplayList.h"
#include "third_party/skia/include/core/SkPromiseImageTexture.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrBackendSemaphore.h"
namespace gfx {
+namespace mojom {
+class DelegatedInkPointRenderer;
+} // namespace mojom
class ColorSpace;
}
@@ -48,7 +52,7 @@ namespace gpu {
class SharedImageRepresentationFactory;
class SharedImageFactory;
class SyncPointClientState;
-}
+} // namespace gpu
namespace ui {
#if defined(USE_OZONE)
@@ -74,7 +78,8 @@ class SkiaOutputSurfaceImplOnGpu
public:
using DidSwapBufferCompleteCallback =
base::RepeatingCallback<void(gpu::SwapBuffersCompleteParams,
- const gfx::Size& pixel_size)>;
+ const gfx::Size& pixel_size,
+ gfx::GpuFenceHandle release_fence)>;
using BufferPresentedCallback =
base::RepeatingCallback<void(const gfx::PresentationFeedback& feedback)>;
using ContextLostCallback = base::OnceClosure;
@@ -108,7 +113,7 @@ class SkiaOutputSurfaceImplOnGpu
return shared_gpu_deps_->command_buffer_id();
}
- const OutputSurface::Capabilities capabilities() const {
+ const OutputSurface::Capabilities& capabilities() const {
return output_device_->capabilities();
}
const base::WeakPtr<SkiaOutputSurfaceImplOnGpu>& weak_ptr() const {
@@ -127,22 +132,21 @@ class SkiaOutputSurfaceImplOnGpu
std::vector<ImageContextImpl*> image_contexts,
std::vector<gpu::SyncToken> sync_tokens,
base::OnceClosure on_finished,
- base::Optional<gfx::Rect> draw_rectangle);
+ absl::optional<gfx::Rect> draw_rectangle);
void ScheduleOutputSurfaceAsOverlay(
const OverlayProcessorInterface::OutputSurfaceOverlayPlane&
output_surface_plane);
- void SwapBuffers(base::TimeTicks post_task_timestamp,
- OutputSurfaceFrame frame);
+ void SwapBuffers(OutputSurfaceFrame frame);
void SetDependenciesResolvedTimings(base::TimeTicks task_ready);
+ void SetDrawTimings(base::TimeTicks task_ready);
// Runs |deferred_framebuffer_draw_closure| when SwapBuffers() or CopyOutput()
// will not.
void SwapBuffersSkipped();
void EnsureBackbuffer() { output_device_->EnsureBackbuffer(); }
void DiscardBackbuffer() { output_device_->DiscardBackbuffer(); }
- void FinishPaintRenderPass(base::TimeTicks post_task_timestamp,
- AggregatedRenderPassId id,
+ void FinishPaintRenderPass(AggregatedRenderPassId id,
sk_sp<SkDeferredDisplayList> ddl,
std::vector<ImageContextImpl*> image_contexts,
std::vector<gpu::SyncToken> sync_tokens,
@@ -217,6 +221,10 @@ class SkiaOutputSurfaceImplOnGpu
void PreserveChildSurfaceControls();
+ void InitDelegatedInkPointRendererReceiver(
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer>
+ pending_receiver);
+
private:
class OffscreenSurface;
class DisplayContext;
@@ -228,7 +236,8 @@ class SkiaOutputSurfaceImplOnGpu
// Provided as a callback to |device_|.
void DidSwapBuffersCompleteInternal(gpu::SwapBuffersCompleteParams params,
- const gfx::Size& pixel_size);
+ const gfx::Size& pixel_size,
+ gfx::GpuFenceHandle release_fence);
DidSwapBufferCompleteCallback GetDidSwapBuffersCompleteCallback();
@@ -240,8 +249,8 @@ class SkiaOutputSurfaceImplOnGpu
const gpu::SyncToken& sync_token,
bool is_lost);
- void SwapBuffersInternal(base::Optional<OutputSurfaceFrame> frame);
- void PostSubmit(base::Optional<OutputSurfaceFrame> frame);
+ void SwapBuffersInternal(absl::optional<OutputSurfaceFrame> frame);
+ void PostSubmit(absl::optional<OutputSurfaceFrame> frame);
GrDirectContext* gr_context() { return context_state_->gr_context(); }
@@ -285,7 +294,7 @@ class SkiaOutputSurfaceImplOnGpu
// This must remain the first member variable to ensure that other member
// dtors are called first.
- base::Optional<ReleaseCurrent> release_current_last_;
+ absl::optional<ReleaseCurrent> release_current_last_;
SkiaOutputSurfaceDependency* const dependency_;
gpu::DisplayCompositorMemoryAndTaskControllerOnGpu* shared_gpu_deps_;
@@ -341,7 +350,7 @@ class SkiaOutputSurfaceImplOnGpu
std::unique_ptr<SkiaOutputDevice> output_device_;
std::unique_ptr<SkiaOutputDevice::ScopedPaint> scoped_output_device_paint_;
- base::Optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>
+ absl::optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>
output_surface_plane_;
base::flat_map<AggregatedRenderPassId, OffscreenSurface> offscreen_surfaces_;
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc b/chromium/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
index 1801a6dadd7..70fd910865c 100644
--- a/chromium/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
@@ -79,7 +79,8 @@ void SkiaOutputSurfaceImplTest::SetUpSkiaOutputSurfaceImpl() {
RendererSettings settings;
settings.use_skia_renderer = true;
auto skia_deps = std::make_unique<SkiaOutputSurfaceDependencyImpl>(
- GetGpuService(), gpu::kNullSurfaceHandle);
+ GetGpuService(), TestGpuServiceHolder::GetInstance()->task_executor(),
+ gpu::kNullSurfaceHandle);
display_controller_ =
std::make_unique<DisplayCompositorMemoryAndTaskController>(
std::move(skia_deps));
diff --git a/chromium/components/viz/service/display_embedder/software_output_surface.cc b/chromium/components/viz/service/display_embedder/software_output_surface.cc
index 88885b46b0e..a909718f5f1 100644
--- a/chromium/components/viz/service/display_embedder/software_output_surface.cc
+++ b/chromium/components/viz/service/display_embedder/software_output_surface.cc
@@ -107,7 +107,8 @@ void SoftwareOutputSurface::SwapBuffersCallback(base::TimeTicks swap_time,
latency_tracker_.OnGpuSwapBuffersCompleted(
std::move(stored_latency_info_.front()));
stored_latency_info_.pop();
- client_->DidReceiveSwapBuffersAck({swap_time, swap_time});
+ client_->DidReceiveSwapBuffersAck({swap_time, swap_time},
+ /*release_fence=*/gfx::GpuFenceHandle());
base::TimeTicks now = base::TimeTicks::Now();
base::TimeDelta interval_to_next_refresh =
diff --git a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc
index 39b59f406e5..3fc9538e727 100644
--- a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc
+++ b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc
@@ -43,7 +43,7 @@ void CompositorFrameSinkImpl::SetWantsAnimateOnlyBeginFrames() {
void CompositorFrameSinkImpl::SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time) {
// Non-root surface frames should not have display transform hint.
DCHECK_EQ(gfx::OVERLAY_TRANSFORM_NONE, frame.metadata.display_transform_hint);
@@ -55,7 +55,7 @@ void CompositorFrameSinkImpl::SubmitCompositorFrame(
void CompositorFrameSinkImpl::SubmitCompositorFrameSync(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time,
SubmitCompositorFrameSyncCallback callback) {
SubmitCompositorFrameInternal(local_surface_id, std::move(frame),
@@ -66,7 +66,7 @@ void CompositorFrameSinkImpl::SubmitCompositorFrameSync(
void CompositorFrameSinkImpl::SubmitCompositorFrameInternal(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback callback) {
const auto result = support_->MaybeSubmitCompositorFrame(
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 6c17d8c5031..37c72b4ceb0 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
@@ -38,12 +38,12 @@ class CompositorFrameSinkImpl : public mojom::CompositorFrameSink {
void SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time) override;
void SubmitCompositorFrameSync(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time,
SubmitCompositorFrameSyncCallback callback) override;
void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override;
@@ -57,7 +57,7 @@ class CompositorFrameSinkImpl : public mojom::CompositorFrameSink {
void SubmitCompositorFrameInternal(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback);
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 8ebb46dbd0b..90ef058b804 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
@@ -10,8 +10,8 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/containers/contains.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "cc/base/features.h"
@@ -65,10 +65,14 @@ CompositorFrameSinkSupport::CompositorFrameSinkSupport(
surface_resource_holder_(this),
is_root_(is_root),
allow_copy_output_requests_(is_root),
- animation_power_mode_voter_(
- power_scheduler::PowerModeArbiter::GetInstance()->NewVoter(
- "PowerModeVoter.Animation")),
- document_transitions_enabled_(features::IsDocumentTransitionEnabled()) {
+ surface_animation_manager_(frame_sink_manager_->shared_bitmap_manager()),
+ // Don't track the root surface for PowerMode voting. All child surfaces
+ // are tracked individually instead, and tracking the root surface could
+ // override votes from the children.
+ power_mode_voter_(
+ is_root ? nullptr
+ : power_scheduler::PowerModeArbiter::GetInstance()->NewVoter(
+ "PowerModeVoter.Animation")) {
surface_animation_manager_.SetDirectiveFinishedCallback(
base::BindRepeating(&CompositorFrameSinkSupport::
OnCompositorFrameTransitionDirectiveProcessed,
@@ -158,7 +162,7 @@ void CompositorFrameSinkSupport::OnSurfaceActivated(Surface* surface) {
// Let the animation manager process any new directives on the surface.
const auto& transition_directives =
surface->GetActiveFrameMetadata().transition_directives;
- if (document_transitions_enabled_ && !transition_directives.empty()) {
+ if (!transition_directives.empty()) {
bool started_animation =
surface_animation_manager_.ProcessTransitionDirectives(
transition_directives, surface->GetSurfaceSavedFrameStorage());
@@ -255,11 +259,7 @@ void CompositorFrameSinkSupport::OnSurfaceAggregatedDamage(
}
bool CompositorFrameSinkSupport::IsVideoCaptureStarted() {
- for (auto* client : capture_clients_) {
- if (client->IsVideoCaptureStarted())
- return true;
- }
- return false;
+ return number_clients_capturing_ > 0;
}
void CompositorFrameSinkSupport::OnSurfaceDestroyed(Surface* surface) {
@@ -288,21 +288,24 @@ void CompositorFrameSinkSupport::RefResources(
}
void CompositorFrameSinkSupport::UnrefResources(
- const std::vector<ReturnedResource>& resources) {
+ std::vector<ReturnedResource> resources) {
+ // |surface_animation_manager_| allocates ResourceIds in a different range
+ // than the client so it can process returned resources before
+ // |surface_resource_holder_|.
surface_animation_manager_.UnrefResources(resources);
- surface_resource_holder_.UnrefResources(resources);
+ surface_resource_holder_.UnrefResources(std::move(resources));
}
void CompositorFrameSinkSupport::ReturnResources(
- const std::vector<ReturnedResource>& resources) {
+ std::vector<ReturnedResource> resources) {
if (resources.empty())
return;
if (!ack_pending_count_ && client_) {
- client_->ReclaimResources(resources);
+ client_->ReclaimResources(std::move(resources));
return;
}
- std::copy(resources.begin(), resources.end(),
+ std::move(resources.begin(), resources.end(),
std::back_inserter(surface_returned_resources_));
}
@@ -423,7 +426,7 @@ void CompositorFrameSinkSupport::DidNotProduceFrame(const BeginFrameAck& ack) {
void CompositorFrameSinkSupport::SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time) {
const auto result = MaybeSubmitCompositorFrame(
local_surface_id, std::move(frame), std::move(hit_test_region_list),
@@ -453,7 +456,7 @@ void CompositorFrameSinkSupport::DidDeleteSharedBitmap(
SubmitResult CompositorFrameSinkSupport::MaybeSubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback callback) {
TRACE_EVENT_WITH_FLOW2(
@@ -658,7 +661,7 @@ void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck() {
return;
}
- client_->DidReceiveCompositorFrameAck(surface_returned_resources_);
+ client_->DidReceiveCompositorFrameAck(std::move(surface_returned_resources_));
surface_returned_resources_.clear();
}
@@ -707,7 +710,7 @@ void CompositorFrameSinkSupport::DidRejectCompositorFrame(
std::vector<ReturnedResource> resources =
TransferableResource::ReturnResources(frame_resource_list);
- ReturnResources(resources);
+ ReturnResources(std::move(resources));
DidReceiveCompositorFrameAck();
DidPresentCompositorFrame(frame_token, base::TimeTicks(), gfx::SwapTimings(),
gfx::PresentationFeedback::Failure());
@@ -765,9 +768,11 @@ void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) {
UpdateNeedsBeginFramesInternal();
}
- // Notify surface animation manager if it needs a begin frame.
+ // Notify surface animation manager of the latest time and advance a frame if
+ // it needs a begin frame.
+ surface_animation_manager_.UpdateFrameTime(args.frame_time);
if (surface_animation_manager_.NeedsBeginFrame()) {
- surface_animation_manager_.NotifyFrameAdvanced(args.frame_time);
+ surface_animation_manager_.NotifyFrameAdvanced();
// Interpolate the frame here, since it is a reliable spot during the
// animation.
@@ -839,12 +844,22 @@ void CompositorFrameSinkSupport::UpdateNeedsBeginFramesInternal() {
added_frame_observer_ = needs_begin_frame;
if (needs_begin_frame) {
begin_frame_source_->AddObserver(this);
- animation_power_mode_voter_->VoteFor(
- power_scheduler::PowerMode::kAnimation);
+ if (power_mode_voter_) {
+ power_mode_voter_->VoteFor(
+ frame_sink_type_ == mojom::CompositorFrameSinkType::kMediaStream ||
+ frame_sink_type_ == mojom::CompositorFrameSinkType::kVideo
+ ? power_scheduler::PowerMode::kVideoPlayback
+ : power_scheduler::PowerMode::kAnimation);
+ }
} else {
begin_frame_source_->RemoveObserver(this);
- animation_power_mode_voter_->ResetVoteAfterTimeout(
- power_scheduler::PowerModeVoter::kAnimationTimeout);
+ if (power_mode_voter_) {
+ power_mode_voter_->ResetVoteAfterTimeout(
+ frame_sink_type_ == mojom::CompositorFrameSinkType::kMediaStream ||
+ frame_sink_type_ == mojom::CompositorFrameSinkType::kVideo
+ ? power_scheduler::PowerModeVoter::kVideoTimeout
+ : power_scheduler::PowerModeVoter::kAnimationTimeout);
+ }
}
}
@@ -852,6 +867,8 @@ void CompositorFrameSinkSupport::AttachCaptureClient(
CapturableFrameSink::Client* client) {
DCHECK(!base::Contains(capture_clients_, client));
capture_clients_.push_back(client);
+ if (client->IsVideoCaptureStarted())
+ OnClientCaptureStarted();
}
void CompositorFrameSinkSupport::DetachCaptureClient(
@@ -860,6 +877,23 @@ void CompositorFrameSinkSupport::DetachCaptureClient(
std::find(capture_clients_.begin(), capture_clients_.end(), client);
if (it != capture_clients_.end())
capture_clients_.erase(it);
+ if (client->IsVideoCaptureStarted())
+ OnClientCaptureStopped();
+}
+
+void CompositorFrameSinkSupport::OnClientCaptureStarted() {
+ if (number_clients_capturing_++ == 0) {
+ // First client started capturing.
+ frame_sink_manager_->OnCaptureStarted(frame_sink_id_);
+ }
+}
+
+void CompositorFrameSinkSupport::OnClientCaptureStopped() {
+ DCHECK_GT(number_clients_capturing_, 0u);
+ if (--number_clients_capturing_ == 0) {
+ // The last client has stopped capturing.
+ frame_sink_manager_->OnCaptureStopped(frame_sink_id_);
+ }
}
gfx::Size CompositorFrameSinkSupport::GetActiveFrameSize() {
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 31afa1613ce..1f163e40d3c 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
@@ -13,7 +13,6 @@
#include "base/compiler_specific.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/power_scheduler/power_mode_voter.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
@@ -31,6 +30,7 @@
#include "components/viz/service/viz_service_export.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"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace viz {
@@ -124,8 +124,8 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
void OnSurfaceWillDraw(Surface* surface) override;
void RefResources(
const std::vector<TransferableResource>& resources) override;
- void UnrefResources(const std::vector<ReturnedResource>& resources) override;
- void ReturnResources(const std::vector<ReturnedResource>& resources) override;
+ void UnrefResources(std::vector<ReturnedResource> resources) override;
+ void ReturnResources(std::vector<ReturnedResource> resources) override;
void ReceiveFromChild(
const std::vector<TransferableResource>& resources) override;
// Takes the CopyOutputRequests that were requested for a surface with at
@@ -153,7 +153,7 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
void SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list = base::nullopt,
+ absl::optional<HitTestRegionList> hit_test_region_list = absl::nullopt,
uint64_t submit_time = 0);
// Returns false if the notification was not valid (a duplicate).
bool DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region,
@@ -175,13 +175,15 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
SubmitResult MaybeSubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback callback);
// CapturableFrameSink implementation.
void AttachCaptureClient(CapturableFrameSink::Client* client) override;
void DetachCaptureClient(CapturableFrameSink::Client* client) override;
+ void OnClientCaptureStarted() override;
+ void OnClientCaptureStopped() override;
gfx::Size GetActiveFrameSize() override;
void RequestCopyOfOutput(
PendingCopyOutputRequest pending_copy_output_request) override;
@@ -273,7 +275,7 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
// If this contains a value then a surface reference from the top-level root
// to SurfaceId(frame_sink_id_, referenced_local_surface_id_.value()) was
// added. This will not contain a value if |is_root_| is false.
- base::Optional<LocalSurfaceId> referenced_local_surface_id_;
+ absl::optional<LocalSurfaceId> referenced_local_surface_id_;
SurfaceResourceHolder surface_resource_holder_;
@@ -373,14 +375,14 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
// single-page-app transitions.
SurfaceAnimationManager surface_animation_manager_;
- std::unique_ptr<power_scheduler::PowerModeVoter> animation_power_mode_voter_;
-
- // Represents whether the DocumentTransition feature is enabled.
- bool document_transitions_enabled_;
+ std::unique_ptr<power_scheduler::PowerModeVoter> power_mode_voter_;
// Number of frames skipped during throttling since last BeginFrame sent.
uint64_t frames_throttled_since_last_ = 0;
+ // Number of clients that have started video capturing.
+ uint32_t number_clients_capturing_ = 0;
+
base::WeakPtrFactory<CompositorFrameSinkSupport> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CompositorFrameSinkSupport);
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 bc0c4be8559..8df78696711 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
@@ -145,7 +145,7 @@ class CompositorFrameSinkSupportTest : public testing::Test {
std::unique_ptr<CopyOutputRequest> request) {
frame.render_pass_list.back()->copy_requests.push_back(std::move(request));
const auto result = support_->MaybeSubmitCompositorFrame(
- local_surface_id_, std::move(frame), base::nullopt, 0,
+ local_surface_id_, std::move(frame), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
switch (result) {
case SubmitResult::ACCEPTED:
@@ -170,9 +170,9 @@ class CompositorFrameSinkSupportTest : public testing::Test {
resource.sync_token = consumer_sync_token_;
resource.id = ids_to_unref[i];
resource.count = counts_to_unref[i];
- unref_array.push_back(resource);
+ unref_array.push_back(std::move(resource));
}
- support_->UnrefResources(unref_array);
+ support_->UnrefResources(std::move(unref_array));
}
void CheckReturnedResourcesMatchExpected(ResourceId* expected_returned_ids,
@@ -181,8 +181,7 @@ class CompositorFrameSinkSupportTest : public testing::Test {
fake_support_client_.returned_resources();
ASSERT_EQ(expected_resources, actual_resources.size());
for (size_t i = 0; i < expected_resources; ++i) {
- ReturnedResource resource = actual_resources[i];
- EXPECT_EQ(expected_returned_ids[i], resource.id);
+ EXPECT_EQ(expected_returned_ids[i], actual_resources[i].id);
}
fake_support_client_.clear_returned_resources();
}
@@ -195,7 +194,7 @@ class CompositorFrameSinkSupportTest : public testing::Test {
fake_support_client_.returned_resources();
ASSERT_EQ(expected_resources, actual_resources.size());
for (size_t i = 0; i < expected_resources; ++i) {
- ReturnedResource resource = actual_resources[i];
+ const auto& resource = actual_resources[i];
EXPECT_EQ(expected_sync_token, resource.sync_token);
EXPECT_EQ(expected_returned_ids[i], resource.id);
EXPECT_EQ(expected_returned_counts[i], resource.count);
@@ -611,37 +610,37 @@ TEST_F(CompositorFrameSinkSupportTest, MonotonicallyIncreasingLocalSurfaceIds) {
// LocalSurfaceId1(6, 1)
auto result = support->MaybeSubmitCompositorFrame(
- local_surface_id1, MakeDefaultCompositorFrame(), base::nullopt, 0,
+ local_surface_id1, MakeDefaultCompositorFrame(), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::ACCEPTED, result);
// LocalSurfaceId(6, 2): Child-initiated synchronization.
result = support->MaybeSubmitCompositorFrame(
- local_surface_id2, MakeDefaultCompositorFrame(), base::nullopt, 0,
+ local_surface_id2, MakeDefaultCompositorFrame(), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::ACCEPTED, result);
// LocalSurfaceId(7, 2): Parent-initiated synchronization.
result = support->MaybeSubmitCompositorFrame(
- local_surface_id3, MakeDefaultCompositorFrame(), base::nullopt, 0,
+ local_surface_id3, MakeDefaultCompositorFrame(), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::ACCEPTED, result);
// LocalSurfaceId(5, 3): Submit rejected because not monotonically increasing.
result = support->MaybeSubmitCompositorFrame(
- local_surface_id4, MakeDefaultCompositorFrame(), base::nullopt, 0,
+ local_surface_id4, MakeDefaultCompositorFrame(), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::SURFACE_ID_DECREASED, result);
// LocalSurfaceId(8, 1): Submit rejected because not monotonically increasing.
result = support->MaybeSubmitCompositorFrame(
- local_surface_id5, MakeDefaultCompositorFrame(), base::nullopt, 0,
+ local_surface_id5, MakeDefaultCompositorFrame(), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::SURFACE_ID_DECREASED, result);
// LocalSurfaceId(9, 3): Parent AND child-initiated synchronization.
result = support->MaybeSubmitCompositorFrame(
- local_surface_id6, MakeDefaultCompositorFrame(), base::nullopt, 0,
+ local_surface_id6, MakeDefaultCompositorFrame(), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::ACCEPTED, result);
@@ -711,11 +710,13 @@ TEST_F(CompositorFrameSinkSupportTest, EvictLastActivatedSurface) {
local_surface_id);
local_surface_id_ = LocalSurfaceId();
- std::vector<ReturnedResource> returned_resources = {
- resource.ToReturnedResource()};
+ ResourceId returned_id = resource.ToReturnedResource().id;
EXPECT_TRUE(GetSurfaceForId(id));
- EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(returned_resources))
- .Times(1);
+ EXPECT_CALL(mock_client, DidReceiveCompositorFrameAck(_))
+ .WillOnce([=](std::vector<ReturnedResource> got) {
+ EXPECT_EQ(1u, got.size());
+ EXPECT_EQ(returned_id, got[0].id);
+ });
support->EvictSurface(local_surface_id);
ExpireAllTemporaryReferences();
manager_.surface_manager()->GarbageCollectSurfaces();
@@ -954,7 +955,7 @@ TEST_F(CompositorFrameSinkSupportTest, FrameSizeMismatch) {
.AddRenderPass(gfx::Rect(5, 5), gfx::Rect())
.Build();
auto result = support_->MaybeSubmitCompositorFrame(
- local_surface_id_, std::move(frame), base::nullopt, 0,
+ local_surface_id_, std::move(frame), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::ACCEPTED, result);
EXPECT_TRUE(GetSurfaceForId(id));
@@ -970,7 +971,7 @@ TEST_F(CompositorFrameSinkSupportTest, FrameSizeMismatch) {
base::size(frame_resource_ids));
result = support_->MaybeSubmitCompositorFrame(
- local_surface_id_, std::move(frame), base::nullopt, 0,
+ local_surface_id_, std::move(frame), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::SIZE_MISMATCH, result);
@@ -992,7 +993,7 @@ TEST_F(CompositorFrameSinkSupportTest, DeviceScaleFactorMismatch) {
.SetDeviceScaleFactor(0.5f)
.Build();
auto result = support_->MaybeSubmitCompositorFrame(
- local_surface_id_, std::move(frame), base::nullopt, 0,
+ local_surface_id_, std::move(frame), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::ACCEPTED, result);
EXPECT_TRUE(GetSurfaceForId(id));
@@ -1004,7 +1005,7 @@ TEST_F(CompositorFrameSinkSupportTest, DeviceScaleFactorMismatch) {
.SetDeviceScaleFactor(0.4f)
.Build();
result = support_->MaybeSubmitCompositorFrame(
- local_surface_id_, std::move(frame), base::nullopt, 0,
+ local_surface_id_, std::move(frame), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::SIZE_MISMATCH, result);
}
@@ -1303,7 +1304,7 @@ TEST_F(CompositorFrameSinkSupportTest, OnFrameTokenUpdate) {
TEST_F(CompositorFrameSinkSupportTest,
DisallowEmbedTokenReuseAcrossFrameSinks) {
auto result = support_->MaybeSubmitCompositorFrame(
- local_surface_id_, MakeDefaultCompositorFrame(), base::nullopt, 0,
+ local_surface_id_, MakeDefaultCompositorFrame(), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::ACCEPTED, result);
@@ -1315,7 +1316,7 @@ TEST_F(CompositorFrameSinkSupportTest,
false /* not root frame sink */);
LocalSurfaceId local_surface_id(31232, local_surface_id_.embed_token());
result = support->MaybeSubmitCompositorFrame(
- local_surface_id, MakeDefaultCompositorFrame(), base::nullopt, 0,
+ local_surface_id, MakeDefaultCompositorFrame(), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::SURFACE_OWNED_BY_ANOTHER_CLIENT, result);
}
@@ -1331,13 +1332,13 @@ TEST_F(CompositorFrameSinkSupportTest, SubmitAfterReparenting) {
CompositorFrame frame =
CompositorFrameBuilder().AddDefaultRenderPass().Build();
SubmitResult result = support_->MaybeSubmitCompositorFrame(
- local_surface_id1, std::move(frame), base::nullopt, 0,
+ local_surface_id1, std::move(frame), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(SubmitResult::ACCEPTED, result);
frame = CompositorFrameBuilder().AddDefaultRenderPass().Build();
result = support_->MaybeSubmitCompositorFrame(
- local_surface_id2, std::move(frame), base::nullopt, 0,
+ local_surface_id2, std::move(frame), absl::nullopt, 0,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
// Even though |local_surface_id2| has a smaller parent sequence number than
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 e1affe8994d..92d4a3d3d9a 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
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_VIZ_SERVICE_FRAME_SINKS_EXTERNAL_BEGIN_FRAME_SOURCE_MOJO_H_
#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_EXTERNAL_BEGIN_FRAME_SOURCE_MOJO_H_
-#include <memory>
-
#include "base/containers/flat_set.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
diff --git a/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
index fa087e0586c..81a910698db 100644
--- a/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
+++ b/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/check_op.h"
+#include "base/containers/queue.h"
#include "base/metrics/histogram_functions.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
@@ -113,18 +114,6 @@ void FrameSinkManagerImpl::SetLocalClient(
ui_task_runner_ = ui_task_runner;
}
-void FrameSinkManagerImpl::ForceShutdown() {
- if (receiver_.is_bound())
- receiver_.reset();
-
- for (auto& it : cached_back_buffers_)
- it.second.RunAndReset();
- cached_back_buffers_.clear();
-
- sink_map_.clear();
- root_sink_map_.clear();
-}
-
void FrameSinkManagerImpl::RegisterFrameSinkId(const FrameSinkId& frame_sink_id,
bool report_activation) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -213,6 +202,9 @@ void FrameSinkManagerImpl::RegisterFrameSinkHierarchy(
DCHECK(!base::Contains(children, child_frame_sink_id));
children.insert(child_frame_sink_id);
+ // Now the hierarchy has been updated, update throttling.
+ UpdateThrottling();
+
for (auto& observer : observer_list_) {
observer.OnRegisteredFrameSinkHierarchy(parent_frame_sink_id,
child_frame_sink_id);
@@ -251,6 +243,9 @@ void FrameSinkManagerImpl::UnregisterFrameSinkHierarchy(
DCHECK(base::Contains(mapping.children, child_frame_sink_id));
mapping.children.erase(child_frame_sink_id);
+ // Now the hierarchy has been updated, update throttling.
+ UpdateThrottling();
+
// Delete the FrameSinkSourceMapping for |parent_frame_sink_id| if empty.
if (mapping.children.empty() && !mapping.source) {
frame_sink_source_map_.erase(iter);
@@ -499,7 +494,7 @@ bool FrameSinkManagerImpl::ChildContains(
void FrameSinkManagerImpl::SubmitHitTestRegionList(
const SurfaceId& surface_id,
uint64_t frame_index,
- base::Optional<HitTestRegionList> hit_test_region_list) {
+ absl::optional<HitTestRegionList> hit_test_region_list) {
hit_test_manager_.SubmitHitTestRegionList(surface_id, frame_index,
std::move(hit_test_region_list));
}
@@ -610,6 +605,17 @@ void FrameSinkManagerImpl::DiscardPendingCopyOfOutputRequests(
}
}
+void FrameSinkManagerImpl::OnCaptureStarted(const FrameSinkId& id) {
+ if (captured_frame_sink_ids_.insert(id).second) {
+ ClearThrottling(id);
+ }
+}
+
+void FrameSinkManagerImpl::OnCaptureStopped(const FrameSinkId& id) {
+ captured_frame_sink_ids_.erase(id);
+ UpdateThrottling();
+}
+
void FrameSinkManagerImpl::CacheBackBuffer(
uint32_t cache_id,
const FrameSinkId& root_frame_sink_id) {
@@ -649,14 +655,30 @@ void FrameSinkManagerImpl::UpdateThrottlingRecursively(
void FrameSinkManagerImpl::Throttle(const std::vector<FrameSinkId>& ids,
base::TimeDelta interval) {
+ frame_sink_ids_to_throttle_ = ids;
+ throttle_interval_ = interval;
+ UpdateThrottling();
+}
+
+void FrameSinkManagerImpl::UpdateThrottling() {
+ // Clear previous throttling effect on all frame sinks.
for (auto& support_map_item : support_map_) {
support_map_item.second->ThrottleBeginFrame(base::TimeDelta());
}
+ if (throttle_interval_.is_zero())
+ return;
- // Set the |interval| for frame sinks whose ids are listed in |ids|.
- for (const auto& id : ids) {
- UpdateThrottlingRecursively(id, interval);
+ for (const auto& id : frame_sink_ids_to_throttle_) {
+ UpdateThrottlingRecursively(id, throttle_interval_);
+ }
+ // Clear throttling on frame sinks currently being captured.
+ for (const auto& id : captured_frame_sink_ids_) {
+ UpdateThrottlingRecursively(id, base::TimeDelta());
}
}
+void FrameSinkManagerImpl::ClearThrottling(const FrameSinkId& id) {
+ UpdateThrottlingRecursively(id, base::TimeDelta());
+}
+
} // 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 efa5073ec0b..65f4d19f3e4 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
@@ -17,7 +17,6 @@
#include "base/containers/flat_set.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_checker.h"
@@ -43,6 +42,7 @@
#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"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace viz {
@@ -69,7 +69,7 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
InitParams& operator=(InitParams&& other);
SharedBitmapManager* shared_bitmap_manager = nullptr;
- base::Optional<uint32_t> activation_deadline_in_frames =
+ absl::optional<uint32_t> activation_deadline_in_frames =
kDefaultActivationDeadlineInFrames;
OutputSurfaceProvider* output_surface_provider = nullptr;
uint32_t restart_id = BeginFrameSource::kNotRestartableId;
@@ -85,10 +85,6 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
OutputSurfaceProvider* output_surface_provider = nullptr);
~FrameSinkManagerImpl() override;
- // Performs cleanup needed to force shutdown from the GPU process. Stops all
- // incoming IPCs and destroys all [Root]CompositorFrameSinkImpls.
- void ForceShutdown();
-
// Binds |this| as a FrameSinkManagerImpl for |receiver| on |task_runner|. On
// Mac |task_runner| will be the resize helper task runner. May only be called
// once.
@@ -186,7 +182,7 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
void SubmitHitTestRegionList(
const SurfaceId& surface_id,
uint64_t frame_index,
- base::Optional<HitTestRegionList> hit_test_region_list);
+ absl::optional<HitTestRegionList> hit_test_region_list);
// Instantiates |video_detector_| for tests where we simulate the passage of
// time.
@@ -231,6 +227,11 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
// so there's no point for caller to wait for the copy of output.
void DiscardPendingCopyOfOutputRequests(const BeginFrameSource* source);
+ // Called when video capture starts on the target frame sink with |id|.
+ void OnCaptureStarted(const FrameSinkId& id);
+ // Called when video capture stops on the target frame sink with |id|.
+ void OnCaptureStopped(const FrameSinkId& id);
+
private:
friend class FrameSinkManagerTest;
@@ -288,6 +289,16 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
void UpdateThrottlingRecursively(const FrameSinkId& id,
base::TimeDelta interval);
+ // Called when throttling needs to be updated. Some examples can trigger such
+ // an update include: starting of video capturing requires throttling on the
+ // frame sink being captured to be stopped; a frame sink hierarchical change
+ // requires throttling on affected frame sinks to be started or stopped.
+ void UpdateThrottling();
+
+ // Clears throttling operation on the frame sink with |id| and all its
+ // descendants.
+ void ClearThrottling(const FrameSinkId& id);
+
// SharedBitmapManager for the viz display service for receiving software
// resources in CompositorFrameSinks.
SharedBitmapManager* const shared_bitmap_manager_;
@@ -340,6 +351,16 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
base::UniquePtrComparator>
video_capturers_;
+ // The ids of the frame sinks that are currently being captured.
+ // These frame sinks should not be throttled.
+ base::flat_set<FrameSinkId> captured_frame_sink_ids_;
+
+ // Ids of the frame sinks that have been requested to throttle.
+ std::vector<FrameSinkId> frame_sink_ids_to_throttle_;
+
+ // The throttling interval which defines how often BeginFrames are sent.
+ base::TimeDelta throttle_interval_ = BeginFrameArgs::DefaultInterval();
+
base::flat_map<uint32_t, base::ScopedClosureRunner> cached_back_buffers_;
THREAD_CHECKER(thread_checker_);
@@ -362,7 +383,7 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
// OnFrameTokenChanged() will be directly called (without PostTask) on
// |client_|. Used for some unit tests.
mojom::FrameSinkManagerClient* client_ = nullptr;
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_ = nullptr;
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
mojo::Remote<mojom::FrameSinkManagerClient> client_remote_;
mojo::Receiver<mojom::FrameSinkManager> receiver_{this};
diff --git a/chromium/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc b/chromium/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc
index 23631ef420d..597d85e727f 100644
--- a/chromium/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/frame_sink_manager_unittest.cc
@@ -86,9 +86,17 @@ class FrameSinkManagerTest : public testing::Test {
base::Contains(manager_.root_sink_map_, frame_sink_id);
}
- const base::TimeDelta GetCompositorFrameSinkSupportBeginFrameInterval(
- const FrameSinkId& id) {
- return manager_.support_map_[id]->begin_frame_interval_;
+ CapturableFrameSink* FindCapturableFrameSink(const FrameSinkId& id) {
+ return manager_.FindCapturableFrameSink(id);
+ }
+
+ // Verifies the frame sinks with provided id in |ids| are throttled at
+ // |interval|.
+ void VerifyThrottling(base::TimeDelta interval,
+ const std::vector<FrameSinkId>& ids) {
+ for (auto& id : ids) {
+ EXPECT_EQ(interval, manager_.support_map_[id]->begin_frame_interval_);
+ }
}
// testing::Test implementation.
@@ -430,36 +438,20 @@ TEST_F(FrameSinkManagerTest, Throttle) {
// By default, a CompositorFrameSinkSupport shouldn't have its
// |begin_frame_interval| set.
- for (auto& id : ids) {
- EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id),
- base::TimeDelta());
- }
+ VerifyThrottling(base::TimeDelta(), ids);
manager_.Throttle({kFrameSinkIdRoot}, interval);
- for (auto& id : ids) {
- EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id), interval);
- }
+ VerifyThrottling(interval, ids);
manager_.Throttle({}, base::TimeDelta());
- for (auto& id : ids) {
- EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id),
- base::TimeDelta());
- }
+ VerifyThrottling(base::TimeDelta(), ids);
manager_.Throttle({kFrameSinkIdB, kFrameSinkIdC}, interval);
- for (auto& id : {kFrameSinkIdB, kFrameSinkIdC, kFrameSinkIdD}) {
- EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id), interval);
- }
- for (auto& id : {kFrameSinkIdA, kFrameSinkIdRoot}) {
- EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id),
- base::TimeDelta());
- }
+ VerifyThrottling(interval, {kFrameSinkIdB, kFrameSinkIdC, kFrameSinkIdD});
+ VerifyThrottling(base::TimeDelta(), {kFrameSinkIdA, kFrameSinkIdRoot});
manager_.Throttle({}, base::TimeDelta());
- for (auto& id : ids) {
- EXPECT_EQ(GetCompositorFrameSinkSupportBeginFrameInterval(id),
- base::TimeDelta());
- }
+ VerifyThrottling(base::TimeDelta(), ids);
manager_.UnregisterFrameSinkHierarchy(root->frame_sink_id(),
client_a->frame_sink_id());
@@ -471,6 +463,113 @@ TEST_F(FrameSinkManagerTest, Throttle) {
client_d->frame_sink_id());
}
+// Verifies if a frame sink is being captured, it should not be throttled.
+TEST_F(FrameSinkManagerTest, NoThrottleOnFrameSinksBeingCaptured) {
+ // root -> A -> B -> C
+ auto root = CreateCompositorFrameSinkSupport(kFrameSinkIdRoot);
+ auto client_a = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+ auto client_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+ auto client_c = CreateCompositorFrameSinkSupport(kFrameSinkIdC);
+
+ // Set up the hierarchy.
+ manager_.RegisterFrameSinkHierarchy(root->frame_sink_id(),
+ client_a->frame_sink_id());
+ manager_.RegisterFrameSinkHierarchy(client_a->frame_sink_id(),
+ client_b->frame_sink_id());
+ manager_.RegisterFrameSinkHierarchy(client_b->frame_sink_id(),
+ client_c->frame_sink_id());
+
+ constexpr base::TimeDelta interval = base::TimeDelta::FromHz(20);
+
+ std::vector<FrameSinkId> ids{kFrameSinkIdRoot, kFrameSinkIdA, kFrameSinkIdB,
+ kFrameSinkIdC};
+
+ // By default, a CompositorFrameSinkSupport shouldn't have its
+ // |begin_frame_interval| set.
+ VerifyThrottling(base::TimeDelta(), ids);
+
+ // Throttle all frame sinks.
+ manager_.Throttle({kFrameSinkIdRoot}, interval);
+ VerifyThrottling(interval, ids);
+
+ // Start capturing frame sink B.
+ CapturableFrameSink* capturable_frame_sink =
+ FindCapturableFrameSink(kFrameSinkIdB);
+ capturable_frame_sink->OnClientCaptureStarted();
+
+ // Throttling should be stopped on frame sink B and its child C, but not
+ // affected on root frame sink and frame sink A.
+ VerifyThrottling(interval, {kFrameSinkIdRoot, kFrameSinkIdA});
+ VerifyThrottling(base::TimeDelta(), {kFrameSinkIdB, kFrameSinkIdC});
+
+ // Explicitly request to throttle all frame sinks. This would not affect B or
+ // C while B is still being captured.
+ manager_.Throttle(ids, interval);
+ VerifyThrottling(interval, {kFrameSinkIdRoot, kFrameSinkIdA});
+ VerifyThrottling(base::TimeDelta(), {kFrameSinkIdB, kFrameSinkIdC});
+
+ // Stop capturing.
+ capturable_frame_sink->OnClientCaptureStopped();
+ // Now the throttling state should be the same as before capturing started,
+ // i.e. all frame sinks will now be throttled.
+ VerifyThrottling(interval, ids);
+
+ manager_.Throttle({}, base::TimeDelta());
+ VerifyThrottling(base::TimeDelta(), ids);
+
+ manager_.UnregisterFrameSinkHierarchy(root->frame_sink_id(),
+ client_a->frame_sink_id());
+ manager_.UnregisterFrameSinkHierarchy(client_a->frame_sink_id(),
+ client_b->frame_sink_id());
+ manager_.UnregisterFrameSinkHierarchy(client_b->frame_sink_id(),
+ client_c->frame_sink_id());
+}
+
+// Verifies if throttling on frame sinks is updated properly when hierarchy
+// changes.
+TEST_F(FrameSinkManagerTest, ThrottleUponHierarchyChange) {
+ // root -> A -> B
+ auto root = CreateCompositorFrameSinkSupport(kFrameSinkIdRoot);
+ auto client_a = CreateCompositorFrameSinkSupport(kFrameSinkIdA);
+ auto client_b = CreateCompositorFrameSinkSupport(kFrameSinkIdB);
+
+ // Set up the hierarchy.
+ manager_.RegisterFrameSinkHierarchy(root->frame_sink_id(),
+ client_a->frame_sink_id());
+ manager_.RegisterFrameSinkHierarchy(client_a->frame_sink_id(),
+ client_b->frame_sink_id());
+
+ constexpr base::TimeDelta interval = base::TimeDelta::FromHz(20);
+
+ std::vector<FrameSinkId> ids{kFrameSinkIdRoot, kFrameSinkIdA, kFrameSinkIdB};
+
+ // Throttle the root frame sink.
+ manager_.Throttle({kFrameSinkIdRoot}, interval);
+ // All frame sinks should now be throttled.
+ VerifyThrottling(interval, ids);
+
+ // Unparent A from root. Root should remain throttled while A and B should be
+ // unthrottled.
+ manager_.UnregisterFrameSinkHierarchy(root->frame_sink_id(),
+ client_a->frame_sink_id());
+ VerifyThrottling(interval, {kFrameSinkIdRoot});
+ VerifyThrottling(base::TimeDelta(), {kFrameSinkIdA, kFrameSinkIdB});
+
+ // Reparent A to root. Both A and B should now be throttled along with root.
+ manager_.RegisterFrameSinkHierarchy(root->frame_sink_id(),
+ client_a->frame_sink_id());
+ VerifyThrottling(interval, ids);
+
+ // Unthrottle all frame sinks.
+ manager_.Throttle({}, base::TimeDelta());
+ VerifyThrottling(base::TimeDelta(), ids);
+
+ manager_.UnregisterFrameSinkHierarchy(root->frame_sink_id(),
+ client_a->frame_sink_id());
+ manager_.UnregisterFrameSinkHierarchy(client_a->frame_sink_id(),
+ client_b->frame_sink_id());
+}
+
namespace {
enum RegisterOrder { REGISTER_HIERARCHY_FIRST, REGISTER_CLIENTS_FIRST };
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 7d804bdc816..6ea2c624e1e 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
@@ -11,10 +11,10 @@
#include "base/compiler_specific.h"
#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
-#include "components/viz/service/display/delegated_ink_point_renderer_base.h"
#include "components/viz/service/display/display.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display_embedder/output_surface_provider.h"
@@ -162,7 +162,8 @@ RootCompositorFrameSinkImpl::Create(
std::move(synthetic_begin_frame_source),
std::move(external_begin_frame_source), std::move(display),
params->use_preferred_interval_for_video,
- hw_support_for_multiple_refresh_rates));
+ hw_support_for_multiple_refresh_rates,
+ params->renderer_settings.apply_simple_frame_rate_throttling));
#if !defined(OS_APPLE)
// On Mac vsync parameter updates come from the browser process. We don't need
@@ -264,6 +265,7 @@ void RootCompositorFrameSinkImpl::SetDisplayVSyncParameters(
void RootCompositorFrameSinkImpl::UpdateVSyncParameters() {
base::TimeTicks timebase = display_frame_timebase_;
+
// Overwrite the interval with a meaningful one here if
// |use_preferred_interval_|
base::TimeDelta interval =
@@ -272,6 +274,19 @@ void RootCompositorFrameSinkImpl::UpdateVSyncParameters() {
FrameRateDecider::UnspecifiedFrameInterval()
? preferred_frame_interval_
: display_frame_interval_;
+
+ // Throttle rendering to 30hz.
+ constexpr base::TimeDelta kThrottledInterval = base::TimeDelta::FromHz(30);
+
+ // Only throttle if the frame interval is smaller than |kThrottledInterval|
+ // meaning the refresh rate is higher than the target of 30hz.
+ if (apply_simple_frame_rate_throttling_ &&
+ display_frame_interval_ <= kThrottledInterval) {
+ interval = kThrottledInterval;
+ // timebase remains constant while throttling.
+ timebase = base::TimeTicks();
+ }
+
if (synthetic_begin_frame_source_) {
synthetic_begin_frame_source_->OnUpdateVSyncParameters(timebase, interval);
if (vsync_listener_)
@@ -321,11 +336,8 @@ void RootCompositorFrameSinkImpl::AddVSyncParameterObserver(
}
void RootCompositorFrameSinkImpl::SetDelegatedInkPointRenderer(
- mojo::PendingReceiver<mojom::DelegatedInkPointRenderer> receiver) {
- if (auto* ink_renderer = display_->GetDelegatedInkPointRenderer(
- /*create_if_necessary=*/true)) {
- ink_renderer->InitMessagePipeline(std::move(receiver));
- }
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer> receiver) {
+ display_->InitDelegatedInkPointRendererReceiver(std::move(receiver));
}
void RootCompositorFrameSinkImpl::SetNeedsBeginFrame(bool needs_begin_frame) {
@@ -339,7 +351,7 @@ void RootCompositorFrameSinkImpl::SetWantsAnimateOnlyBeginFrames() {
void RootCompositorFrameSinkImpl::SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time) {
if (support_->last_activated_local_surface_id() != local_surface_id) {
display_->SetLocalSurfaceId(local_surface_id, frame.device_scale_factor());
@@ -366,7 +378,7 @@ void RootCompositorFrameSinkImpl::SubmitCompositorFrame(
void RootCompositorFrameSinkImpl::SubmitCompositorFrameSync(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time,
SubmitCompositorFrameSyncCallback callback) {
NOTIMPLEMENTED();
@@ -409,7 +421,8 @@ RootCompositorFrameSinkImpl::RootCompositorFrameSinkImpl(
std::unique_ptr<ExternalBeginFrameSource> external_begin_frame_source,
std::unique_ptr<Display> display,
bool use_preferred_interval_for_video,
- bool hw_support_for_multiple_refresh_rates)
+ bool hw_support_for_multiple_refresh_rates,
+ bool apply_simple_frame_rate_throttling)
: compositor_frame_sink_client_(std::move(frame_sink_client)),
compositor_frame_sink_receiver_(this, std::move(frame_sink_receiver)),
display_client_(std::move(display_client)),
@@ -421,7 +434,8 @@ RootCompositorFrameSinkImpl::RootCompositorFrameSinkImpl(
/*is_root=*/true)),
synthetic_begin_frame_source_(std::move(synthetic_begin_frame_source)),
external_begin_frame_source_(std::move(external_begin_frame_source)),
- display_(std::move(display)) {
+ display_(std::move(display)),
+ apply_simple_frame_rate_throttling_(apply_simple_frame_rate_throttling) {
DCHECK(display_);
DCHECK(begin_frame_source());
frame_sink_manager->RegisterBeginFrameSource(begin_frame_source(),
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 76262430c84..b0707817767 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
@@ -81,7 +81,7 @@ class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
mojo::PendingRemote<mojom::VSyncParameterObserver> observer) override;
void SetDelegatedInkPointRenderer(
- mojo::PendingReceiver<mojom::DelegatedInkPointRenderer> receiver)
+ mojo::PendingReceiver<gfx::mojom::DelegatedInkPointRenderer> receiver)
override;
// mojom::CompositorFrameSink:
@@ -90,7 +90,7 @@ class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
void SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time) override;
void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override;
void DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region,
@@ -99,7 +99,7 @@ class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
void SubmitCompositorFrameSync(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- base::Optional<HitTestRegionList> hit_test_region_list,
+ absl::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time,
SubmitCompositorFrameSyncCallback callback) override;
void InitializeCompositorFrameSinkType(
@@ -120,7 +120,8 @@ class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
std::unique_ptr<ExternalBeginFrameSource> external_begin_frame_source,
std::unique_ptr<Display> display,
bool use_preferred_interval_for_video,
- bool hw_support_for_multiple_refresh_rates);
+ bool hw_support_for_multiple_refresh_rates,
+ bool apply_simple_frame_rate_throttling);
// DisplayClient:
void DisplayOutputSurfaceLost() override;
@@ -170,6 +171,10 @@ class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
base::TimeDelta preferred_frame_interval_ =
FrameRateDecider::UnspecifiedFrameInterval();
+ // Determines whether to throttle frame rate by half.
+ // TODO(http://crbug.com/1153404): Remove this field when experiment is over.
+ bool apply_simple_frame_rate_throttling_ = false;
+
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chromium/components/viz/service/frame_sinks/surface_resource_holder.cc b/chromium/components/viz/service/frame_sinks/surface_resource_holder.cc
index e167b37a615..1955d1c3669 100644
--- a/chromium/components/viz/service/frame_sinks/surface_resource_holder.cc
+++ b/chromium/components/viz/service/frame_sinks/surface_resource_holder.cc
@@ -43,10 +43,10 @@ void SurfaceResourceHolder::RefResources(
}
void SurfaceResourceHolder::UnrefResources(
- const std::vector<ReturnedResource>& resources) {
+ std::vector<ReturnedResource> resources) {
std::vector<ReturnedResource> resources_available_to_return;
- for (const auto& resource : resources) {
+ for (auto& resource : resources) {
// We don't handle reserved resources here.
if (resource.id >= kVizReservedRangeStartId)
continue;
@@ -61,15 +61,14 @@ void SurfaceResourceHolder::UnrefResources(
if (resource.sync_token.HasData())
ref.sync_token = resource.sync_token;
if (ref.refs_holding_resource_alive == 0) {
- ReturnedResource returned = resource;
- returned.sync_token = ref.sync_token;
- returned.count = ref.refs_received_from_child;
- resources_available_to_return.push_back(returned);
+ resource.sync_token = ref.sync_token;
+ resource.count = ref.refs_received_from_child;
+ resources_available_to_return.push_back(std::move(resource));
resource_id_info_map_.erase(count_it);
}
}
- client_->ReturnResources(resources_available_to_return);
+ client_->ReturnResources(std::move(resources_available_to_return));
}
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/surface_resource_holder.h b/chromium/components/viz/service/frame_sinks/surface_resource_holder.h
index 22cf5779587..9c9af03fab1 100644
--- a/chromium/components/viz/service/frame_sinks/surface_resource_holder.h
+++ b/chromium/components/viz/service/frame_sinks/surface_resource_holder.h
@@ -29,7 +29,7 @@ class VIZ_SERVICE_EXPORT SurfaceResourceHolder {
void Reset();
void ReceiveFromChild(const std::vector<TransferableResource>& resources);
void RefResources(const std::vector<TransferableResource>& resources);
- void UnrefResources(const std::vector<ReturnedResource>& resources);
+ void UnrefResources(std::vector<ReturnedResource> resources);
private:
SurfaceResourceHolderClient* client_;
diff --git a/chromium/components/viz/service/frame_sinks/surface_resource_holder_client.h b/chromium/components/viz/service/frame_sinks/surface_resource_holder_client.h
index 9f97baedaba..fff270e096b 100644
--- a/chromium/components/viz/service/frame_sinks/surface_resource_holder_client.h
+++ b/chromium/components/viz/service/frame_sinks/surface_resource_holder_client.h
@@ -16,8 +16,7 @@ class VIZ_SERVICE_EXPORT SurfaceResourceHolderClient {
// ReturnResources gets called when the display compositor is done using the
// resources so that the client can use them.
- virtual void ReturnResources(
- const std::vector<ReturnedResource>& resources) = 0;
+ virtual void ReturnResources(std::vector<ReturnedResource> resources) = 0;
};
} // 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 2bdc20a2a99..8e2d4ed2fd6 100644
--- a/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -16,6 +16,7 @@
#include "components/viz/test/fake_surface_observer.h"
#include "components/viz/test/mock_compositor_frame_sink_client.h"
#include "components/viz/test/surface_id_allocator_set.h"
+#include "components/viz/test/test_surface_id_allocator.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -413,7 +414,7 @@ TEST_F(SurfaceSynchronizationTest, TwoBlockedOnOne) {
parent_support().SubmitCompositorFrame(
parent_id.local_surface_id(),
- MakeCompositorFrame({child_id2}, {SurfaceRange(base::nullopt, child_id2)},
+ MakeCompositorFrame({child_id2}, {SurfaceRange(absl::nullopt, child_id2)},
std::vector<TransferableResource>()));
// parent_support is blocked on |child_id2|.
@@ -426,7 +427,7 @@ TEST_F(SurfaceSynchronizationTest, TwoBlockedOnOne) {
// child_support1 should now be blocked on |child_id2|.
child_support1().SubmitCompositorFrame(
child_id1.local_surface_id(),
- MakeCompositorFrame({child_id2}, {SurfaceRange(base::nullopt, child_id2)},
+ MakeCompositorFrame({child_id2}, {SurfaceRange(absl::nullopt, child_id2)},
std::vector<TransferableResource>()));
EXPECT_TRUE(child_surface1()->has_deadline());
@@ -534,7 +535,7 @@ TEST_F(SurfaceSynchronizationTest, UnlimitedDeadline) {
// Turn on unlimited deadline mode.
frame_sink_manager()
.surface_manager()
- ->SetActivationDeadlineInFramesForTesting(base::nullopt);
+ ->SetActivationDeadlineInFramesForTesting(absl::nullopt);
const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1);
const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1);
@@ -741,10 +742,13 @@ TEST_F(SurfaceSynchronizationTest, ResourcesOnlyReturnedOnce) {
EXPECT_FALSE(parent_surface()->HasPendingFrame());
EXPECT_THAT(parent_surface()->activation_dependencies(), IsEmpty());
- std::vector<ReturnedResource> returned_resources = {
- resource.ToReturnedResource()};
- EXPECT_CALL(support_client_,
- DidReceiveCompositorFrameAck(returned_resources));
+ std::vector<ReturnedResource> returned_resources;
+ ResourceId id = resource.ToReturnedResource().id;
+ EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_))
+ .WillOnce([=](std::vector<ReturnedResource> got) {
+ EXPECT_EQ(1u, got.size());
+ EXPECT_EQ(id, got[0].id);
+ });
// The parent submits a CompositorFrame without any dependencies. That
// frame should activate immediately, replacing the earlier frame. The
@@ -1280,11 +1284,13 @@ TEST_F(SurfaceSynchronizationTest, ReturnResourcesWithAck) {
parent_id.local_surface_id(),
MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(),
{resource}));
- std::vector<ReturnedResource> returned_resources =
- TransferableResource::ReturnResources({resource});
+ ResourceId id = resource.ToReturnedResource().id;
EXPECT_CALL(support_client_, ReclaimResources(_)).Times(0);
- EXPECT_CALL(support_client_,
- DidReceiveCompositorFrameAck(Eq(returned_resources)));
+ EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_))
+ .WillOnce([=](std::vector<ReturnedResource> got) {
+ EXPECT_EQ(1u, got.size());
+ EXPECT_EQ(id, got[0].id);
+ });
parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
MakeDefaultCompositorFrame());
}
@@ -1337,9 +1343,12 @@ TEST_F(SurfaceSynchronizationTest, SubmitToDestroyedSurface) {
MakeDefaultCompositorFrame());
{
- std::vector<ReturnedResource> returned_resources =
- TransferableResource::ReturnResources({resource});
- EXPECT_CALL(support_client_, ReclaimResources(Eq(returned_resources)));
+ ResourceId id = resource.ToReturnedResource().id;
+ EXPECT_CALL(support_client_, ReclaimResources(_))
+ .WillOnce([=](std::vector<ReturnedResource> got) {
+ EXPECT_EQ(1u, got.size());
+ EXPECT_EQ(id, got[0].id);
+ });
frame_sink_manager().surface_manager()->GarbageCollectSurfaces();
testing::Mock::VerifyAndClearExpectations(&support_client_);
}
@@ -1572,7 +1581,7 @@ TEST_F(SurfaceSynchronizationTest, LateArrivingDependency) {
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
MakeCompositorFrame(
- {parent_id1}, {SurfaceRange(base::nullopt, parent_id1)},
+ {parent_id1}, {SurfaceRange(absl::nullopt, parent_id1)},
std::vector<TransferableResource>(), MakeDefaultDeadline()));
EXPECT_TRUE(display_surface()->HasPendingFrame());
@@ -1594,7 +1603,7 @@ TEST_F(SurfaceSynchronizationTest, LateArrivingDependency) {
// scheduling a deadline and without waiting for dependencies to resolve.
parent_support().SubmitCompositorFrame(
parent_id1.local_surface_id(),
- MakeCompositorFrame({child_id1}, {SurfaceRange(base::nullopt, child_id1)},
+ MakeCompositorFrame({child_id1}, {SurfaceRange(absl::nullopt, child_id1)},
std::vector<TransferableResource>(),
MakeDefaultDeadline()));
EXPECT_FALSE(parent_surface()->has_deadline());
@@ -1612,7 +1621,7 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelLateArrivingDependency) {
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
- MakeCompositorFrame({parent_id}, {SurfaceRange(base::nullopt, parent_id)},
+ MakeCompositorFrame({parent_id}, {SurfaceRange(absl::nullopt, parent_id)},
std::vector<TransferableResource>(),
MakeDefaultDeadline()));
EXPECT_TRUE(display_surface()->HasPendingFrame());
@@ -1635,7 +1644,7 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelLateArrivingDependency) {
child_support1().SubmitCompositorFrame(
child_id.local_surface_id(),
MakeCompositorFrame(
- {arbitrary_id}, {SurfaceRange(base::nullopt, arbitrary_id)},
+ {arbitrary_id}, {SurfaceRange(absl::nullopt, arbitrary_id)},
std::vector<TransferableResource>(), MakeDefaultDeadline()));
EXPECT_TRUE(child_surface1()->HasPendingFrame());
EXPECT_FALSE(child_surface1()->HasActiveFrame());
@@ -1647,7 +1656,7 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelLateArrivingDependency) {
// be late and activate immediately.
parent_support().SubmitCompositorFrame(
parent_id.local_surface_id(),
- MakeCompositorFrame({child_id}, {SurfaceRange(base::nullopt, child_id)},
+ MakeCompositorFrame({child_id}, {SurfaceRange(absl::nullopt, child_id)},
std::vector<TransferableResource>(),
MakeDefaultDeadline()));
EXPECT_FALSE(parent_surface()->HasPendingFrame());
@@ -1678,7 +1687,7 @@ TEST_F(SurfaceSynchronizationTest, FallbackSurfacesClosed) {
child_support1().SubmitCompositorFrame(
child_id1.local_surface_id(),
MakeCompositorFrame({arbitrary_id},
- {SurfaceRange(base::nullopt, arbitrary_id)}, {},
+ {SurfaceRange(absl::nullopt, arbitrary_id)}, {},
MakeDefaultDeadline()));
EXPECT_TRUE(child_surface1()->has_deadline());
EXPECT_TRUE(child_surface1()->HasPendingFrame());
@@ -1708,7 +1717,7 @@ TEST_F(SurfaceSynchronizationTest, FallbackSurfacesClosed) {
child_support1().SubmitCompositorFrame(
child_id1.local_surface_id(),
MakeCompositorFrame({arbitrary_id},
- {SurfaceRange(base::nullopt, arbitrary_id)}, {},
+ {SurfaceRange(absl::nullopt, arbitrary_id)}, {},
MakeDefaultDeadline()));
EXPECT_FALSE(child_surface1()->HasPendingFrame());
EXPECT_TRUE(child_surface1()->HasActiveFrame());
@@ -1811,7 +1820,7 @@ TEST_F(SurfaceSynchronizationTest, InheritShorterDeadline) {
parent_support().SubmitCompositorFrame(
parent_id1.local_surface_id(),
MakeCompositorFrame(
- {child_id1}, {SurfaceRange(base::nullopt, child_id1)},
+ {child_id1}, {SurfaceRange(absl::nullopt, child_id1)},
std::vector<TransferableResource>(),
FrameDeadline(Now(), 2, BeginFrameArgs::DefaultInterval(), true)));
@@ -1868,7 +1877,7 @@ TEST_F(SurfaceSynchronizationTest, ChildDeadlineNotExtendedByInheritance) {
// Child1 blocks on Child2 with a deadline of 2.
child_support1().SubmitCompositorFrame(
child_id1.local_surface_id(),
- MakeCompositorFrame({child_id2}, {SurfaceRange(base::nullopt, child_id2)},
+ MakeCompositorFrame({child_id2}, {SurfaceRange(absl::nullopt, child_id2)},
std::vector<TransferableResource>(),
MakeDeadline(2)));
@@ -1907,7 +1916,7 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelDeadlineInheritance) {
display_support().SubmitCompositorFrame(
display_id.local_surface_id(),
- MakeCompositorFrame({parent_id}, {SurfaceRange(base::nullopt, parent_id)},
+ MakeCompositorFrame({parent_id}, {SurfaceRange(absl::nullopt, parent_id)},
std::vector<TransferableResource>(),
MakeDefaultDeadline()));
EXPECT_TRUE(display_surface()->HasPendingFrame());
@@ -1922,7 +1931,7 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelDeadlineInheritance) {
child_support1().SubmitCompositorFrame(
child_id.local_surface_id(),
MakeCompositorFrame(
- {arbitrary_id}, {SurfaceRange(base::nullopt, arbitrary_id)},
+ {arbitrary_id}, {SurfaceRange(absl::nullopt, arbitrary_id)},
std::vector<TransferableResource>(), MakeDefaultDeadline()));
EXPECT_TRUE(child_surface1()->HasPendingFrame());
EXPECT_FALSE(child_surface1()->HasActiveFrame());
@@ -1933,7 +1942,7 @@ TEST_F(SurfaceSynchronizationTest, MultiLevelDeadlineInheritance) {
// assume the same deadline.
parent_support().SubmitCompositorFrame(
parent_id.local_surface_id(),
- MakeCompositorFrame({child_id}, {SurfaceRange(base::nullopt, child_id)},
+ MakeCompositorFrame({child_id}, {SurfaceRange(absl::nullopt, child_id)},
std::vector<TransferableResource>(),
MakeDefaultDeadline()));
EXPECT_TRUE(parent_surface()->HasPendingFrame());
@@ -2206,7 +2215,7 @@ TEST_F(SurfaceSynchronizationTest, LatestInFlightSurface) {
parent_support().SubmitCompositorFrame(
parent_id.local_surface_id(),
- MakeCompositorFrame({child_id3}, {SurfaceRange(base::nullopt, child_id3)},
+ MakeCompositorFrame({child_id3}, {SurfaceRange(absl::nullopt, child_id3)},
std::vector<TransferableResource>()));
EXPECT_THAT(GetChildReferences(parent_id), UnorderedElementsAre(child_id3));
@@ -2285,7 +2294,7 @@ TEST_F(SurfaceSynchronizationTest, LatestInFlightSurfaceWithoutFallback) {
// Fallback is not specified and |child_id1| is the latest.
EXPECT_EQ(GetSurfaceForId(child_id1),
- GetLatestInFlightSurface(SurfaceRange(base::nullopt, child_id2)));
+ GetLatestInFlightSurface(SurfaceRange(absl::nullopt, child_id2)));
// Activate |child_id2|
child_support1().SubmitCompositorFrame(child_id2.local_surface_id(),
@@ -2301,7 +2310,7 @@ TEST_F(SurfaceSynchronizationTest, LatestInFlightSurfaceWithoutFallback) {
// Fallback is not specified but primary exists so we return it.
EXPECT_EQ(GetSurfaceForId(child_id2),
- GetLatestInFlightSurface(SurfaceRange(base::nullopt, child_id2)));
+ GetLatestInFlightSurface(SurfaceRange(absl::nullopt, child_id2)));
}
// This test verifies that GetLatestInFlightSurface will not return null if the
@@ -3021,7 +3030,7 @@ TEST_F(SurfaceSynchronizationTest, AllocationGroupCreationInitiatedByEmbedder) {
// Now submit a CompositorFrame that references |child_id|. An allocation
// group will be created for it.
CompositorFrame frame =
- MakeCompositorFrame({}, {SurfaceRange(base::nullopt, child_id)}, {});
+ MakeCompositorFrame({}, {SurfaceRange(absl::nullopt, child_id)}, {});
parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
std::move(frame));
EXPECT_TRUE(surface_manager()->GetAllocationGroupForSurfaceId(child_id));
@@ -3160,7 +3169,7 @@ TEST_F(SurfaceSynchronizationTest, LatestInFlightSurfaceConflict) {
parent_support().SubmitCompositorFrame(id2.local_surface_id(),
MakeDefaultCompositorFrame());
EXPECT_EQ(GetSurfaceForId(id1),
- GetLatestInFlightSurface(SurfaceRange(base::nullopt, id3)));
+ GetLatestInFlightSurface(SurfaceRange(absl::nullopt, id3)));
}
// Check that if two different SurfaceIds with the same embed token are
@@ -3177,7 +3186,7 @@ TEST_F(SurfaceSynchronizationTest,
CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetActivationDependencies({child2_id1})
- .SetReferencedSurfaces({SurfaceRange(base::nullopt, child2_id1)})
+ .SetReferencedSurfaces({SurfaceRange(absl::nullopt, child2_id1)})
.Build();
child_support1().SubmitCompositorFrame(child1_id1.local_surface_id(),
std::move(child1_frame));
@@ -3188,8 +3197,8 @@ TEST_F(SurfaceSynchronizationTest,
CompositorFrameBuilder()
.AddDefaultRenderPass()
.SetActivationDependencies({child1_id1, child1_id2})
- .SetReferencedSurfaces({SurfaceRange(base::nullopt, child1_id1),
- SurfaceRange(base::nullopt, child1_id2)})
+ .SetReferencedSurfaces({SurfaceRange(absl::nullopt, child1_id1),
+ SurfaceRange(absl::nullopt, child1_id2)})
.Build();
// This shouldn't crash.
parent_support().SubmitCompositorFrame(parent_id.local_surface_id(),
@@ -3201,4 +3210,166 @@ TEST_F(SurfaceSynchronizationTest,
EXPECT_EQ(child1_id1, *parent_surface()->activation_dependencies().begin());
}
+// Tests that when a new CompositorFrame for an Embedded Surface arrives, and is
+// not immediately ACKed, that when a CompositorFrame from its Embedder arrives
+// with new ActivationDependencies, that the UnACKed frame receives and ACK so
+// that that client can begin frame production to satistfy the new dependencies.
+// (https://crbug.com/1203804)
+TEST_F(SurfaceSynchronizationTest,
+ UnAckedSurfaceArrivesBeforeNewActivationDependencies) {
+ TestSurfaceIdAllocator parent_id(kParentFrameSink);
+ TestSurfaceIdAllocator child_id(kChildFrameSink1);
+
+ parent_support().SubmitCompositorFrame(
+ parent_id.local_surface_id(),
+ MakeCompositorFrame({child_id}, {SurfaceRange(absl::nullopt, child_id)},
+ std::vector<TransferableResource>()));
+ // |parent_support| is blocked on |child_id|.
+ EXPECT_TRUE(parent_surface()->has_deadline());
+ EXPECT_FALSE(parent_surface()->HasActiveFrame());
+ EXPECT_TRUE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(),
+ UnorderedElementsAre(child_id));
+
+ child_support1().SubmitCompositorFrame(
+ child_id.local_surface_id(),
+ MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(),
+ std::vector<TransferableResource>()));
+ // |child_surface| should now be active.
+ EXPECT_TRUE(child_surface1()->HasActiveFrame());
+ EXPECT_FALSE(child_surface1()->HasPendingFrame());
+ EXPECT_THAT(child_surface1()->activation_dependencies(), IsEmpty());
+ EXPECT_FALSE(child_surface1()->HasUnackedActiveFrame());
+
+ // |parent_surface| should now be active.
+ EXPECT_TRUE(parent_surface()->HasActiveFrame());
+ EXPECT_FALSE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(), IsEmpty());
+
+ // We start tracking that surfaces will damage the display. This will lead to
+ // frames not being immediately ACKed.
+ surface_observer().set_damage_display(true);
+ // Submit second frame at the same LocalSurfaceId.
+ EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0);
+ child_support1().SubmitCompositorFrame(
+ child_id.local_surface_id(),
+ MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(),
+ std::vector<TransferableResource>()));
+ testing::Mock::VerifyAndClearExpectations(&support_client_);
+ // |child_surface| should still have an active frame, which will be the newly
+ // submitted frame.
+ EXPECT_TRUE(child_surface1()->HasActiveFrame());
+ EXPECT_FALSE(child_surface1()->HasPendingFrame());
+ EXPECT_THAT(child_surface1()->activation_dependencies(), IsEmpty());
+ // There should also be an un-acked frame, which was just submitted.
+ EXPECT_TRUE(child_surface1()->HasUnackedActiveFrame());
+
+ // Submit new |parent_surface|, with ActivationDependencies that are newer
+ // than the currently unACKed |child_surface|.
+ parent_id.Increment();
+ child_id.Increment();
+
+ parent_support().SubmitCompositorFrame(
+ parent_id.local_surface_id(),
+ MakeCompositorFrame({child_id}, {SurfaceRange(absl::nullopt, child_id)},
+ std::vector<TransferableResource>()));
+ // |parent_support| is blocked on |child_id2| the previous parent_surface
+ // should still be active.
+ EXPECT_TRUE(parent_surface()->has_deadline());
+ EXPECT_FALSE(parent_surface()->HasActiveFrame());
+ EXPECT_TRUE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(),
+ UnorderedElementsAre(child_id));
+ EXPECT_FALSE(child_surface1()->HasUnackedActiveFrame());
+
+ // Submitting a new child frame for the newer dependencies should activate the
+ // parent frame.
+ child_support1().SubmitCompositorFrame(
+ child_id.local_surface_id(),
+ MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(),
+ std::vector<TransferableResource>()));
+ EXPECT_TRUE(child_surface1()->HasActiveFrame());
+ EXPECT_FALSE(child_surface1()->HasPendingFrame());
+ EXPECT_THAT(child_surface1()->activation_dependencies(), IsEmpty());
+ EXPECT_TRUE(parent_surface()->HasActiveFrame());
+ EXPECT_FALSE(parent_surface()->HasPendingFrame());
+}
+
+// Tests that when a CompositorFrame for an Embedded Surface arrives after its
+// Embedder has submitted new ActivationDependencies, that it is immediately
+// ACKed, even if normally it would not be due to damage. This way we don't have
+// an Embedder blocked on an unACKed frame. (https://crbug.com/1203804)
+TEST_F(SurfaceSynchronizationTest,
+ UnAckedOldActivationDependencyArrivesAfterNewDependencies) {
+ TestSurfaceIdAllocator parent_id(kParentFrameSink);
+ TestSurfaceIdAllocator child_id(kChildFrameSink1);
+
+ parent_support().SubmitCompositorFrame(
+ parent_id.local_surface_id(),
+ MakeCompositorFrame({child_id}, {SurfaceRange(absl::nullopt, child_id)},
+ std::vector<TransferableResource>()));
+ // |parent_support| is blocked on |child_id|.
+ EXPECT_TRUE(parent_surface()->has_deadline());
+ EXPECT_FALSE(parent_surface()->HasActiveFrame());
+ EXPECT_TRUE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(),
+ UnorderedElementsAre(child_id));
+
+ child_support1().SubmitCompositorFrame(
+ child_id.local_surface_id(),
+ MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(),
+ std::vector<TransferableResource>()));
+ // |child_surface| should now be active.
+ EXPECT_TRUE(child_surface1()->HasActiveFrame());
+ EXPECT_FALSE(child_surface1()->HasPendingFrame());
+ EXPECT_THAT(child_surface1()->activation_dependencies(), IsEmpty());
+ EXPECT_FALSE(child_surface1()->HasUnackedActiveFrame());
+
+ // |parent_surface| should now be active.
+ EXPECT_TRUE(parent_surface()->HasActiveFrame());
+ EXPECT_FALSE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(), IsEmpty());
+
+ // Submit new |parent_surface|, with ActivationDependencies that are newer
+ // than the currently |child_surface|.
+ parent_id.Increment();
+ LocalSurfaceId old_child_id = child_id.local_surface_id();
+ child_id.Increment();
+
+ EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(0);
+ parent_support().SubmitCompositorFrame(
+ parent_id.local_surface_id(),
+ MakeCompositorFrame({child_id}, {SurfaceRange(absl::nullopt, child_id)},
+ std::vector<TransferableResource>()));
+ testing::Mock::VerifyAndClearExpectations(&support_client_);
+ // |parent_support| is blocked on |child_id2| the previous |parent_surface|
+ // should still be active.
+ EXPECT_TRUE(parent_surface()->has_deadline());
+ EXPECT_FALSE(parent_surface()->HasActiveFrame());
+ EXPECT_TRUE(parent_surface()->HasPendingFrame());
+ EXPECT_THAT(parent_surface()->activation_dependencies(),
+ UnorderedElementsAre(child_id));
+ // There should not be an unACKed |child_surface|.
+ EXPECT_FALSE(child_surface1()->HasUnackedActiveFrame());
+
+ // We start tracking that surfaces will damage the display. This will lead to
+ // frames not being immediately ACKed.
+ surface_observer().set_damage_display(true);
+ // Submitting a CompositorFrame to the old SurfaceId, which is no longer the
+ // dependency, should lead to an immediate ACK.
+ EXPECT_CALL(support_client_, DidReceiveCompositorFrameAck(_)).Times(1);
+ child_support1().SubmitCompositorFrame(
+ old_child_id,
+ MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(),
+ std::vector<TransferableResource>()));
+ testing::Mock::VerifyAndClearExpectations(&support_client_);
+ // |child_surface| should still have an active frame.
+ EXPECT_TRUE(child_surface1()->HasActiveFrame());
+ EXPECT_FALSE(child_surface1()->HasPendingFrame());
+ EXPECT_THAT(child_surface1()->activation_dependencies(), IsEmpty());
+ // Since we are blocking our embedder, we should have been ACKed to allow for
+ // frame production to begin on the new dependency.
+ EXPECT_FALSE(child_surface1()->HasUnackedActiveFrame());
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h b/chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
index 1944ca0172a..38c26e5f74c 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
+++ b/chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_VIZ_SERVICE_FRAME_SINKS_VIDEO_CAPTURE_CAPTURABLE_FRAME_SINK_H_
#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_VIDEO_CAPTURE_CAPTURABLE_FRAME_SINK_H_
-#include <memory>
-
#include "base/time/time.h"
#include "components/viz/service/surfaces/pending_copy_output_request.h"
#include "ui/gfx/geometry/size.h"
@@ -55,6 +53,10 @@ class CapturableFrameSink {
virtual void AttachCaptureClient(Client* client) = 0;
virtual void DetachCaptureClient(Client* client) = 0;
+ // Called when a video capture client starts or stops capturing.
+ virtual void OnClientCaptureStarted() = 0;
+ virtual void OnClientCaptureStopped() = 0;
+
// Returns the currently-active frame size, or an empty size if there is no
// active frame.
virtual gfx::Size GetActiveFrameSize() = 0;
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 290a27e66e5..45bcf714f9a 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
@@ -226,7 +226,7 @@ void FrameSinkVideoCapturerImpl::SetAutoThrottlingEnabled(bool enabled) {
}
void FrameSinkVideoCapturerImpl::ChangeTarget(
- const base::Optional<FrameSinkId>& frame_sink_id,
+ const absl::optional<FrameSinkId>& frame_sink_id,
const SubtreeCaptureId& subtree_capture_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -247,9 +247,14 @@ void FrameSinkVideoCapturerImpl::Start(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(consumer);
- Stop();
+ if (video_capture_started_)
+ Stop();
+
video_capture_started_ = true;
+ if (resolved_target_)
+ resolved_target_->OnClientCaptureStarted();
+
consumer_.Bind(std::move(consumer));
// In the future, if the connection to the consumer is lost before a call to
// Stop(), make that call on its behalf.
@@ -259,6 +264,9 @@ void FrameSinkVideoCapturerImpl::Start(
}
void FrameSinkVideoCapturerImpl::Stop() {
+ if (!video_capture_started_)
+ return;
+
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
refresh_frame_retry_timer_->Stop();
@@ -276,6 +284,9 @@ void FrameSinkVideoCapturerImpl::Stop() {
consumer_.reset();
}
+ if (resolved_target_)
+ resolved_target_->OnClientCaptureStopped();
+
video_capture_started_ = false;
}
@@ -563,9 +574,14 @@ void FrameSinkVideoCapturerImpl::MaybeCaptureFrame(
DCHECK_EQ(media::PIXEL_FORMAT_ARGB, pixel_format_);
content_rect =
media::ComputeLetterboxRegion(frame->visible_rect(), source_size);
+ // The media letterboxing computation explicitly allows for off-by-one
+ // errors due to computation, so we address those here.
+ if (content_rect.ApproximatelyEqual(frame->visible_rect(), 1)) {
+ content_rect = frame->visible_rect();
+ }
}
- // Determine what rectangluar region has changed since the last captured
+ // Determine what rectangular region has changed since the last captured
// frame.
gfx::Rect update_rect;
if (dirty_rect_ == kMaxRect ||
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 4d7183c83ce..e061df5e776 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
@@ -12,11 +12,9 @@
#include <string>
#include <vector>
-#include "base/callback_forward.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
@@ -37,6 +35,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -113,7 +112,7 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
const gfx::Size& max_size,
bool use_fixed_aspect_ratio) final;
void SetAutoThrottlingEnabled(bool enabled) final;
- void ChangeTarget(const base::Optional<FrameSinkId>& frame_sink_id,
+ void ChangeTarget(const absl::optional<FrameSinkId>& frame_sink_id,
const SubtreeCaptureId& subtree_capture_id) final;
void Start(mojo::PendingRemote<mojom::FrameSinkVideoConsumer> consumer) final;
void Stop() final;
@@ -300,7 +299,7 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
// frame, when RequestRefreshFrame() has been called.
//
// Note: This is always set, but the instance is overridden for unit testing.
- base::Optional<base::OneShotTimer> refresh_frame_retry_timer_;
+ absl::optional<base::OneShotTimer> refresh_frame_retry_timer_;
// Provides a pool of VideoFrames that can be efficiently delivered across
// processes. The size of this pool is used to limit the maximum number of
@@ -334,7 +333,7 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
// The Oracle-provided media timestamp of the first frame. This is used to
// compute the relative media stream timestamps for each successive frame.
- base::Optional<base::TimeTicks> first_frame_media_ticks_;
+ absl::optional<base::TimeTicks> first_frame_media_ticks_;
// Zero or more overlays to be rendered over each captured video frame. The
// order of the entries in this map determines the order in which each overlay
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 d177f00bc3d..ba6e7fff18a 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
@@ -11,7 +11,6 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/shared_memory_mapping.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/time.h"
@@ -30,6 +29,7 @@
#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/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/point.h"
@@ -249,6 +249,10 @@ class FakeCapturableFrameSink : public CapturableFrameSink {
client_ = nullptr;
}
+ void OnClientCaptureStarted() override { ++number_clients_capturing_; }
+
+ void OnClientCaptureStopped() override { --number_clients_capturing_; }
+
gfx::Size GetActiveFrameSize() override { return source_size(); }
void RequestCopyOfOutput(
@@ -296,7 +300,11 @@ class FakeCapturableFrameSink : public CapturableFrameSink {
task_runner_ = std::move(runner);
}
+ int number_clients_capturing() const { return number_clients_capturing_; }
+
private:
+ // Number of clients that have started capturing.
+ int number_clients_capturing_ = 0;
CapturableFrameSink::Client* client_ = nullptr;
YUVColor color_ = {0xde, 0xad, 0xbf};
SizeSet size_set_;
@@ -330,13 +338,13 @@ class InstrumentedVideoCaptureOracle : public media::VideoCaptureOracle {
return media::VideoCaptureOracle::capture_size();
}
- void set_forced_capture_size(base::Optional<gfx::Size> size) {
+ void set_forced_capture_size(absl::optional<gfx::Size> size) {
forced_capture_size_ = size;
}
private:
bool return_false_on_complete_capture_;
- base::Optional<gfx::Size> forced_capture_size_;
+ absl::optional<gfx::Size> forced_capture_size_;
};
// Matcher that returns true if the content region of a letterboxed VideoFrame
@@ -1297,4 +1305,21 @@ TEST_F(FrameSinkVideoCapturerTest, CaptureCounterSkipsWhenFramesAreDropped) {
StopCapture();
}
+TEST_F(FrameSinkVideoCapturerTest, ClientCaptureStartsAndStops) {
+ EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
+ .WillRepeatedly(Return(&frame_sink_));
+
+ capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId());
+ EXPECT_EQ(frame_sink_.number_clients_capturing(), 0);
+
+ // Start capturing. frame_sink_ should now have one client capturing.
+ NiceMock<MockConsumer> consumer;
+ StartCapture(&consumer);
+ EXPECT_EQ(frame_sink_.number_clients_capturing(), 1);
+
+ // Stop capturing. frame_sink_ should now have no client capturing.
+ StopCapture();
+ EXPECT_EQ(frame_sink_.number_clients_capturing(), 0);
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/video_capture_overlay_unittest.cc b/chromium/components/viz/service/frame_sinks/video_capture/video_capture_overlay_unittest.cc
index 33a1f3fb10a..c0d82348636 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/video_capture_overlay_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/video_capture/video_capture_overlay_unittest.cc
@@ -13,7 +13,6 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/numerics/safe_conversions.h"
-#include "base/optional.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
@@ -27,6 +26,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
diff --git a/chromium/components/viz/service/frame_sinks/video_detector.h b/chromium/components/viz/service/frame_sinks/video_detector.h
index 1bab06eb0d5..f13540576ed 100644
--- a/chromium/components/viz/service/frame_sinks/video_detector.h
+++ b/chromium/components/viz/service/frame_sinks/video_detector.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_VIZ_SERVICE_FRAME_SINKS_VIDEO_DETECTOR_H_
#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_VIDEO_DETECTOR_H_
-#include <unordered_map>
-
#include "base/sequenced_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "base/timer/timer.h"
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 c0236494caf..cd475dd139a 100644
--- a/chromium/components/viz/service/frame_sinks/video_detector_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/video_detector_unittest.cc
@@ -142,7 +142,7 @@ class VideoDetectorTest : public testing::Test {
render_pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
quad->SetNew(
shared_quad_state, gfx::Rect(0, 0, 10, 10), gfx::Rect(0, 0, 5, 5),
- SurfaceRange(base::nullopt, frame_sink->last_activated_surface_id()),
+ SurfaceRange(absl::nullopt, frame_sink->last_activated_surface_id()),
SK_ColorMAGENTA, /*stretch_content_to_fill_bounds=*/false);
}
root_frame_sink_->SubmitCompositorFrame(
diff --git a/chromium/components/viz/service/gl/gpu_service_impl.cc b/chromium/components/viz/service/gl/gpu_service_impl.cc
index 2285b0bb682..47a9fbe8c70 100644
--- a/chromium/components/viz/service/gl/gpu_service_impl.cc
+++ b/chromium/components/viz/service/gl/gpu_service_impl.cc
@@ -326,12 +326,12 @@ GpuServiceImpl::GpuServiceImpl(
scoped_refptr<base::SingleThreadTaskRunner> io_runner,
const gpu::GpuFeatureInfo& gpu_feature_info,
const gpu::GpuPreferences& gpu_preferences,
- const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
- const base::Optional<gpu::GpuFeatureInfo>&
+ const absl::optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
+ const absl::optional<gpu::GpuFeatureInfo>&
gpu_feature_info_for_hardware_gpu,
const gfx::GpuExtraInfo& gpu_extra_info,
gpu::VulkanImplementation* vulkan_implementation,
- base::OnceCallback<void(base::Optional<ExitCode>)> exit_callback)
+ base::OnceCallback<void(ExitCode)> exit_callback)
: main_runner_(base::ThreadTaskRunnerHandle::Get()),
io_runner_(std::move(io_runner)),
watchdog_thread_(std::move(watchdog_thread)),
@@ -431,7 +431,9 @@ GpuServiceImpl::~GpuServiceImpl() {
is_exiting_.Set();
bind_task_tracker_.TryCancelAll();
- GetLogMessageManager()->ShutdownLogging();
+
+ if (!in_host_process())
+ GetLogMessageManager()->ShutdownLogging();
// Destroy the receiver on the IO thread.
{
@@ -567,8 +569,8 @@ void GpuServiceImpl::InitializeWithHost(
shutdown_event_ = owned_shutdown_event_.get();
}
- scheduler_ = std::make_unique<gpu::Scheduler>(
- main_runner_, sync_point_manager, gpu_preferences_);
+ scheduler_ =
+ std::make_unique<gpu::Scheduler>(sync_point_manager, gpu_preferences_);
// Defer creation of the render thread. This is to prevent it from handling
// IPC messages before the sandbox has been enabled and all other necessary
@@ -910,7 +912,19 @@ void GpuServiceImpl::StoreShaderToDisk(int client_id,
}
void GpuServiceImpl::MaybeExitOnContextLost() {
- MaybeExit(true);
+ DCHECK(main_runner_->BelongsToCurrentThread());
+
+ // We can't restart the GPU process when running in the host process.
+ if (in_host_process())
+ return;
+
+ if (IsExiting() || !exit_callback_)
+ return;
+
+ LOG(ERROR) << "Exiting GPU process because some drivers can't recover "
+ "from errors. GPU process will restart shortly.";
+ is_exiting_.Set();
+ std::move(exit_callback_).Run(ExitCode::RESULT_CODE_GPU_EXIT_ON_CONTEXT_LOST);
}
bool GpuServiceImpl::IsExiting() const {
@@ -942,16 +956,19 @@ void GpuServiceImpl::EstablishGpuChannel(int32_t client_id,
if (gpu::IsReservedClientId(client_id)) {
// This returns a null handle, which is treated by the client as a failure
// case.
- std::move(callback).Run(mojo::ScopedMessagePipeHandle());
+ std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
+ gpu::GpuFeatureInfo());
return;
}
EstablishGpuChannelCallback wrap_callback = base::BindOnce(
[](scoped_refptr<base::SingleThreadTaskRunner> runner,
- EstablishGpuChannelCallback cb,
- mojo::ScopedMessagePipeHandle handle) {
+ EstablishGpuChannelCallback cb, mojo::ScopedMessagePipeHandle handle,
+ const gpu::GPUInfo& gpu_info,
+ const gpu::GpuFeatureInfo& gpu_feature_info) {
runner->PostTask(FROM_HERE,
- base::BindOnce(std::move(cb), std::move(handle)));
+ base::BindOnce(std::move(cb), std::move(handle),
+ gpu_info, gpu_feature_info));
},
io_runner_, std::move(callback));
main_runner_->PostTask(
@@ -968,7 +985,8 @@ void GpuServiceImpl::EstablishGpuChannel(int32_t client_id,
if (!gpu_channel) {
// This returns a null handle, which is treated by the client as a failure
// case.
- std::move(callback).Run(mojo::ScopedMessagePipeHandle());
+ std::move(callback).Run(mojo::ScopedMessagePipeHandle(), gpu::GPUInfo(),
+ gpu::GpuFeatureInfo());
return;
}
mojo::MessagePipe pipe;
@@ -976,7 +994,8 @@ void GpuServiceImpl::EstablishGpuChannel(int32_t client_id,
media_gpu_channel_manager_->AddChannel(client_id);
- std::move(callback).Run(std::move(pipe.handle1));
+ std::move(callback).Run(std::move(pipe.handle1), gpu_info_,
+ gpu_feature_info_);
}
void GpuServiceImpl::CloseChannel(int32_t client_id) {
@@ -1173,13 +1192,6 @@ void GpuServiceImpl::ThrowJavaException() {
#endif
}
-void GpuServiceImpl::Stop(StopCallback callback) {
- DCHECK(io_runner_->BelongsToCurrentThread());
- main_runner_->PostTaskAndReply(
- FROM_HERE, base::BindOnce(&GpuServiceImpl::MaybeExit, weak_ptr_, false),
- std::move(callback));
-}
-
void GpuServiceImpl::StartPeakMemoryMonitorOnMainThread(uint32_t sequence_num) {
gpu_channel_manager_->StartPeakMemoryMonitor(sequence_num);
}
@@ -1195,31 +1207,6 @@ void GpuServiceImpl::GetPeakMemoryUsageOnMainThread(
std::move(allocation_per_source)));
}
-void GpuServiceImpl::MaybeExit(bool for_context_loss) {
- DCHECK(main_runner_->BelongsToCurrentThread());
-
- // We can't restart the GPU process when running in the host process.
- if (in_host_process())
- return;
-
- if (IsExiting() || !exit_callback_)
- return;
-
- if (for_context_loss) {
- LOG(ERROR) << "Exiting GPU process because some drivers can't recover "
- "from errors. GPU process will restart shortly.";
- }
- is_exiting_.Set();
- // For the unsandboxed GPU info collection process used for info collection,
- // if we exit immediately, then the reply message could be lost. That's why
- // the |exit_callback_| takes the boolean argument.
- if (for_context_loss)
- std::move(exit_callback_)
- .Run(ExitCode::RESULT_CODE_GPU_EXIT_ON_CONTEXT_LOST);
- else
- std::move(exit_callback_).Run(base::nullopt);
-}
-
gpu::Scheduler* GpuServiceImpl::GetGpuScheduler() {
return scheduler_.get();
}
diff --git a/chromium/components/viz/service/gl/gpu_service_impl.h b/chromium/components/viz/service/gl/gpu_service_impl.h
index 9306892ace8..f1a06ff7944 100644
--- a/chromium/components/viz/service/gl/gpu_service_impl.h
+++ b/chromium/components/viz/service/gl/gpu_service_impl.h
@@ -87,18 +87,17 @@ enum class ExitCode {
class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
public mojom::GpuService {
public:
- GpuServiceImpl(
- const gpu::GPUInfo& gpu_info,
- std::unique_ptr<gpu::GpuWatchdogThread> watchdog,
- scoped_refptr<base::SingleThreadTaskRunner> io_runner,
- const gpu::GpuFeatureInfo& gpu_feature_info,
- const gpu::GpuPreferences& gpu_preferences,
- const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
- const base::Optional<gpu::GpuFeatureInfo>&
- gpu_feature_info_for_hardware_gpu,
- const gfx::GpuExtraInfo& gpu_extra_info,
- gpu::VulkanImplementation* vulkan_implementation,
- base::OnceCallback<void(base::Optional<ExitCode>)> exit_callback);
+ GpuServiceImpl(const gpu::GPUInfo& gpu_info,
+ std::unique_ptr<gpu::GpuWatchdogThread> watchdog,
+ scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ const gpu::GpuPreferences& gpu_preferences,
+ const absl::optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
+ const absl::optional<gpu::GpuFeatureInfo>&
+ gpu_feature_info_for_hardware_gpu,
+ const gfx::GpuExtraInfo& gpu_extra_info,
+ gpu::VulkanImplementation* vulkan_implementation,
+ base::OnceCallback<void(ExitCode)> exit_callback);
~GpuServiceImpl() override;
@@ -200,7 +199,6 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
void Crash() override;
void Hang() override;
void ThrowJavaException() override;
- void Stop(StopCallback callback) override;
// gpu::GpuChannelManagerDelegate:
void RegisterDisplayContext(gpu::DisplayContext* display_context) override;
@@ -221,6 +219,8 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
void StoreShaderToDisk(int client_id,
const std::string& key,
const std::string& shader) override;
+ // Attempts to atomically shut down the process but only if not running in
+ // host process. An error message will be logged.
void MaybeExitOnContextLost() override;
bool IsExiting() const override;
gpu::Scheduler* GetGpuScheduler() override;
@@ -350,10 +350,6 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
void GetPeakMemoryUsageOnMainThread(uint32_t sequence_num,
GetPeakMemoryUsageCallback callback);
- // Attempts to cleanly exit the process but only if not running in host
- // process. If |for_context_loss| is true an error message will be logged.
- void MaybeExit(bool for_context_loss);
-
// Update overlay info and HDR status on the GPU process and send the updated
// info back to the browser process if there is a change.
#if defined(OS_WIN)
@@ -379,8 +375,8 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
// What we would have gotten if we haven't fallen back to SwiftShader or
// pure software (in the viz case).
- base::Optional<gpu::GPUInfo> gpu_info_for_hardware_gpu_;
- base::Optional<gpu::GpuFeatureInfo> gpu_feature_info_for_hardware_gpu_;
+ absl::optional<gpu::GPUInfo> gpu_info_for_hardware_gpu_;
+ absl::optional<gpu::GpuFeatureInfo> gpu_feature_info_for_hardware_gpu_;
// Information about the GPU process populated on creation.
gfx::GpuExtraInfo gpu_extra_info_;
@@ -414,7 +410,7 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
base::WaitableEvent* shutdown_event_ = nullptr;
// Callback that safely exits GPU process.
- base::OnceCallback<void(base::Optional<ExitCode>)> exit_callback_;
+ base::OnceCallback<void(ExitCode)> exit_callback_;
base::AtomicFlag is_exiting_;
// Used for performing hardware decode acceleration of images. This is shared
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 ccc1f7a927f..dc472a9f5d0 100644
--- a/chromium/components/viz/service/gl/gpu_service_impl_unittest.cc
+++ b/chromium/components/viz/service/gl/gpu_service_impl_unittest.cc
@@ -85,7 +85,7 @@ class GpuServiceTest : public testing::Test {
io_thread_.Stop();
}
- base::Optional<bool> visible_;
+ absl::optional<bool> visible_;
private:
base::Thread io_thread_;
diff --git a/chromium/components/viz/service/hit_test/hit_test_aggregator.cc b/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
index 0a42bc10c6a..099ee78c6ea 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
@@ -138,18 +138,18 @@ void HitTestAggregator::SendHitTestData() {
hit_test_data_);
}
-base::Optional<int64_t> HitTestAggregator::GetTraceIdIfUpdated(
+absl::optional<int64_t> HitTestAggregator::GetTraceIdIfUpdated(
const SurfaceId& surface_id,
uint64_t active_frame_index) {
bool enabled;
TRACE_EVENT_CATEGORY_GROUP_ENABLED(
TRACE_DISABLED_BY_DEFAULT("viz.hit_testing_flow"), &enabled);
if (!enabled)
- return base::nullopt;
+ return absl::nullopt;
uint64_t& frame_index = last_active_frame_index_[surface_id.frame_sink_id()];
if (frame_index == active_frame_index)
- return base::nullopt;
+ return absl::nullopt;
frame_index = active_frame_index;
return ~hit_test_manager_->GetTraceId(surface_id);
}
@@ -164,7 +164,7 @@ void HitTestAggregator::AppendRoot(const SurfaceId& surface_id) {
if (!hit_test_region_list)
return;
- base::Optional<int64_t> trace_id =
+ absl::optional<int64_t> trace_id =
GetTraceIdIfUpdated(surface_id, active_frame_index);
TRACE_EVENT_WITH_FLOW1(
TRACE_DISABLED_BY_DEFAULT("viz.hit_testing_flow"), "Event.Pipeline",
@@ -248,7 +248,7 @@ size_t HitTestAggregator::AppendRegion(size_t region_index,
region.frame_sink_id);
SurfaceId surface_id(region.frame_sink_id, local_surface_id);
- base::Optional<int64_t> trace_id =
+ absl::optional<int64_t> trace_id =
GetTraceIdIfUpdated(surface_id, active_frame_index);
TRACE_EVENT_WITH_FLOW1(
TRACE_DISABLED_BY_DEFAULT("viz.hit_testing_flow"), "Event.Pipeline",
diff --git a/chromium/components/viz/service/hit_test/hit_test_aggregator.h b/chromium/components/viz/service/hit_test/hit_test_aggregator.h
index 2c760c20103..6867558b6ba 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator.h
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator.h
@@ -69,7 +69,7 @@ class VIZ_SERVICE_EXPORT HitTestAggregator {
// the given |surface_id| if it is different than when it was last queried.
// This is used in order to ensure that the flow between receiving hit-test
// data and aggregating is included only once per submission.
- base::Optional<int64_t> GetTraceIdIfUpdated(const SurfaceId& surface_id,
+ absl::optional<int64_t> GetTraceIdIfUpdated(const SurfaceId& surface_id,
uint64_t active_frame_index);
// Inserts debug quads based on hit-test data.
diff --git a/chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc b/chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
index 927dbe4f21a..47a5b5016f6 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
@@ -1158,7 +1158,7 @@ TEST_F(HitTestAggregatorTest, HitTestDataNotUpdated) {
// We did not update the hit-test data. Expect the index from Aggregator /
// Manager to remain unchanged.
support()->SubmitCompositorFrame(surface_id.local_surface_id(),
- MakeDefaultCompositorFrame(), base::nullopt);
+ MakeDefaultCompositorFrame(), absl::nullopt);
aggregator->Aggregate(surface_id);
EXPECT_EQ(last_index, aggregator->GetLastSubmitHitTestRegionListIndex());
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 e424d0cbb73..9381b42e6e4 100644
--- a/chromium/components/viz/service/hit_test/hit_test_manager.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_manager.cc
@@ -81,7 +81,7 @@ void HitTestManager::OnSurfaceActivated(const SurfaceId& surface_id) {
void HitTestManager::SubmitHitTestRegionList(
const SurfaceId& surface_id,
const uint64_t frame_index,
- base::Optional<HitTestRegionList> hit_test_region_list) {
+ absl::optional<HitTestRegionList> hit_test_region_list) {
if (!hit_test_region_list) {
auto& frame_index_map = hit_test_region_lists_[surface_id];
if (!frame_index_map.empty()) {
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 f4840b46b54..c056341a067 100644
--- a/chromium/components/viz/service/hit_test/hit_test_manager.h
+++ b/chromium/components/viz/service/hit_test/hit_test_manager.h
@@ -5,14 +5,16 @@
#ifndef COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_MANAGER_H_
#define COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_MANAGER_H_
-#include "base/optional.h"
+#include <map>
+#include <vector>
+
#include "base/timer/elapsed_timer.h"
#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
#include "components/viz/common/surfaces/surface_id.h"
#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/mojom/hit_test/hit_test_region_list.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace viz {
@@ -41,7 +43,7 @@ class VIZ_SERVICE_EXPORT HitTestManager : public SurfaceObserver {
void SubmitHitTestRegionList(
const SurfaceId& surface_id,
const uint64_t frame_index,
- base::Optional<HitTestRegionList> hit_test_region_list);
+ absl::optional<HitTestRegionList> hit_test_region_list);
// Returns the HitTestRegionList corresponding to the given
// |frame_sink_id| and the active CompositorFrame matched by frame_index.
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 47d9ecc4f83..93387ceae25 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
@@ -109,7 +109,7 @@ void SubmitHitTestRegionList(
return;
}
- base::Optional<viz::HitTestRegionList> hit_test_region_list;
+ absl::optional<viz::HitTestRegionList> hit_test_region_list;
if (fuzz->ConsumeBool()) {
hit_test_region_list.emplace();
hit_test_region_list->flags = fuzz->ConsumeIntegral<uint32_t>();
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 98446a2d3c8..0a9c5ff28e0 100644
--- a/chromium/components/viz/service/main/viz_compositor_thread_runner.h
+++ b/chromium/components/viz/service/main/viz_compositor_thread_runner.h
@@ -52,18 +52,6 @@ class VizCompositorThreadRunner {
#if BUILDFLAG(USE_VIZ_DEVTOOLS)
virtual void CreateVizDevTools(mojom::VizDevToolsParamsPtr params) = 0;
#endif
-
- // Performs cleanup on VizCompositorThread needed before forcing thread to
- // shut down. Ensures VizCompositorThread teardown during the destructor
- // doesn't block on PostTasks back to the GPU thread. After cleanup has
- // finished |cleanup_finished_callback| will be run. Should be called from the
- // thread that owns |this|.
- //
- // 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.
- virtual void CleanupForShutdown(
- base::OnceClosure cleanup_finished_callback) = 0;
};
} // namespace viz
diff --git a/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.cc b/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.cc
index dfe9db2a98a..6ee5fa96f61 100644
--- a/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.cc
+++ b/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.cc
@@ -170,16 +170,6 @@ void VizCompositorThreadRunnerImpl::CreateVizDevTools(
}
#endif
-void VizCompositorThreadRunnerImpl::CleanupForShutdown(
- base::OnceClosure cleanup_finished_callback) {
- task_runner_->PostTaskAndReply(
- FROM_HERE,
- base::BindOnce(
- &VizCompositorThreadRunnerImpl::CleanupForShutdownOnCompositorThread,
- base::Unretained(this)),
- std::move(cleanup_finished_callback));
-}
-
void VizCompositorThreadRunnerImpl::CreateFrameSinkManagerOnCompositorThread(
mojom::FrameSinkManagerParamsPtr params,
gpu::CommandBufferTaskExecutor* task_executor,
@@ -221,7 +211,7 @@ void VizCompositorThreadRunnerImpl::CreateFrameSinkManagerOnCompositorThread(
FrameSinkManagerImpl::InitParams init_params;
init_params.shared_bitmap_manager = server_shared_bitmap_manager_.get();
// Set default activation deadline to infinite if client doesn't provide one.
- init_params.activation_deadline_in_frames = base::nullopt;
+ init_params.activation_deadline_in_frames = absl::nullopt;
if (params->use_activation_deadline) {
init_params.activation_deadline_in_frames =
params->activation_deadline_in_frames;
@@ -276,13 +266,6 @@ void VizCompositorThreadRunnerImpl::InitVizDevToolsOnCompositorThread(
}
#endif
-void VizCompositorThreadRunnerImpl::CleanupForShutdownOnCompositorThread() {
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- if (frame_sink_manager_)
- frame_sink_manager_->ForceShutdown();
-}
-
void VizCompositorThreadRunnerImpl::TearDownOnCompositorThread() {
DCHECK(task_runner_->BelongsToCurrentThread());
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
index 9e4b20d62d3..6ed5be83ee0 100644
--- a/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.h
+++ b/chromium/components/viz/service/main/viz_compositor_thread_runner_impl.h
@@ -54,7 +54,6 @@ class VizCompositorThreadRunnerImpl : public VizCompositorThreadRunner {
#if BUILDFLAG(USE_VIZ_DEVTOOLS)
void CreateVizDevTools(mojom::VizDevToolsParamsPtr params) override;
#endif
- void CleanupForShutdown(base::OnceClosure cleanup_finished_callback) override;
private:
void CreateFrameSinkManagerOnCompositorThread(
@@ -66,7 +65,6 @@ class VizCompositorThreadRunnerImpl : public VizCompositorThreadRunner {
void CreateVizDevToolsOnCompositorThread(mojom::VizDevToolsParamsPtr params);
void InitVizDevToolsOnCompositorThread(mojom::VizDevToolsParamsPtr params);
#endif
- void CleanupForShutdownOnCompositorThread();
void TearDownOnCompositorThread();
// Start variables to be accessed only on |task_runner_|.
diff --git a/chromium/components/viz/service/main/viz_main_impl.cc b/chromium/components/viz/service/main/viz_main_impl.cc
index bb73fb251a6..55a292a0c77 100644
--- a/chromium/components/viz/service/main/viz_main_impl.cc
+++ b/chromium/components/viz/service/main/viz_main_impl.cc
@@ -17,6 +17,7 @@
#include "build/build_config.h"
#include "components/ui_devtools/buildflags.h"
#include "components/viz/common/features.h"
+#include "components/viz/service/debugger/viz_debugger.h"
#include "gpu/command_buffer/common/activity_flags.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/ipc/service/gpu_init.h"
@@ -111,6 +112,7 @@ VizMainImpl::VizMainImpl(Delegate* delegate,
gpu_init_->gpu_feature_info_for_hardware_gpu(),
gpu_init_->gpu_extra_info(), gpu_init_->vulkan_implementation(),
base::BindOnce(&VizMainImpl::ExitProcess, base::Unretained(this)));
+ VizDebugger::GetInstance();
}
VizMainImpl::~VizMainImpl() {
@@ -266,6 +268,21 @@ void VizMainImpl::CreateVizDevTools(mojom::VizDevToolsParamsPtr params) {
#endif
}
+#if BUILDFLAG(USE_VIZ_DEBUGGER)
+void VizMainImpl::FilterDebugStream(base::Value filter_data) {
+ VizDebugger::GetInstance()->FilterDebugStream(std::move(filter_data));
+}
+
+void VizMainImpl::StartDebugStream(
+ mojo::PendingRemote<mojom::VizDebugOutput> pending_debug_output) {
+ VizDebugger::GetInstance()->StartDebugStream(std::move(pending_debug_output));
+}
+
+void VizMainImpl::StopDebugStream() {
+ VizDebugger::GetInstance()->StopDebugStream();
+}
+#endif
+
scoped_refptr<gpu::SharedContextState> VizMainImpl::GetSharedContextState() {
return gpu_service_->GetContextState();
}
@@ -274,28 +291,21 @@ scoped_refptr<gl::GLShareGroup> VizMainImpl::GetShareGroup() {
return gpu_service_->share_group();
}
-void VizMainImpl::ExitProcess(base::Optional<ExitCode> immediate_exit_code) {
+void VizMainImpl::ExitProcess(ExitCode immediate_exit_code) {
DCHECK(gpu_thread_task_runner_->BelongsToCurrentThread());
- if (!gpu_init_->gpu_info().in_process_gpu && immediate_exit_code) {
+ if (!gpu_init_->gpu_info().in_process_gpu) {
// Atomically shut down GPU process to make it faster and simpler.
base::Process::TerminateCurrentProcessImmediately(
- static_cast<int>(immediate_exit_code.value()));
+ static_cast<int>(immediate_exit_code));
return;
}
// Close mojom::VizMain bindings first so the browser can't try to reconnect.
receiver_.reset();
- if (viz_compositor_thread_runner_) {
- // Destroy RootCompositorFrameSinkImpls on the compositor while the GPU
- // thread is still running to avoid deadlock. Quit GPU thread TaskRunner
- // after cleanup on compositor thread is finished.
- viz_compositor_thread_runner_->CleanupForShutdown(base::BindOnce(
- &Delegate::QuitMainMessageLoop, base::Unretained(delegate_)));
- } else {
- delegate_->QuitMainMessageLoop();
- }
+ DCHECK(!viz_compositor_thread_runner_);
+ delegate_->QuitMainMessageLoop();
}
} // namespace viz
diff --git a/chromium/components/viz/service/main/viz_main_impl.h b/chromium/components/viz/service/main/viz_main_impl.h
index 4b82e5a2226..27e0c52cf9b 100644
--- a/chromium/components/viz/service/main/viz_main_impl.h
+++ b/chromium/components/viz/service/main/viz_main_impl.h
@@ -6,13 +6,13 @@
#define COMPONENTS_VIZ_SERVICE_MAIN_VIZ_MAIN_IMPL_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "components/discardable_memory/client/client_discardable_shared_memory_manager.h"
+#include "components/viz/common/buildflags.h"
#include "components/viz/service/gl/gpu_service_impl.h"
#include "components/viz/service/main/viz_compositor_thread_runner_impl.h"
#include "gpu/ipc/gpu_in_process_thread_service.h"
@@ -126,6 +126,12 @@ class VizMainImpl : public mojom::VizMain,
#endif
void CreateFrameSinkManager(mojom::FrameSinkManagerParamsPtr params) override;
void CreateVizDevTools(mojom::VizDevToolsParamsPtr params) override;
+#if BUILDFLAG(USE_VIZ_DEBUGGER)
+ void FilterDebugStream(base::Value filter_data) override;
+ void StartDebugStream(
+ mojo::PendingRemote<mojom::VizDebugOutput> debug_output) override;
+ void StopDebugStream() override;
+#endif
// gpu::GpuInProcessThreadServiceDelegate implementation:
scoped_refptr<gpu::SharedContextState> GetSharedContextState() override;
@@ -141,10 +147,9 @@ class VizMainImpl : public mojom::VizMain,
return discardable_shared_memory_manager_.get();
}
- // Cleanly exits the process. If |immediate_exit_code| is base::nullopt, the
- // process exits by shutting down the GPU main thread. Otherwise, the process
- // is terminated immediately with the specified exit code.
- void ExitProcess(base::Optional<ExitCode> immediate_exit_code);
+ // If it's in browser process, shut down the GPU main thread. Otherwise, the
+ // GPU process is terminated immediately with the specified exit code.
+ void ExitProcess(ExitCode immediate_exit_code);
private:
void CreateFrameSinkManagerInternal(mojom::FrameSinkManagerParamsPtr params);
diff --git a/chromium/components/viz/service/main/viz_main_impl_unittest.cc b/chromium/components/viz/service/main/viz_main_impl_unittest.cc
index 8a60ed0e8b0..dff6d7a16ca 100644
--- a/chromium/components/viz/service/main/viz_main_impl_unittest.cc
+++ b/chromium/components/viz/service/main/viz_main_impl_unittest.cc
@@ -62,7 +62,6 @@ class MockVizCompositorThreadRunner : public VizCompositorThreadRunner {
#if BUILDFLAG(USE_VIZ_DEVTOOLS)
MOCK_METHOD1(CreateVizDevTools, void(mojom::VizDevToolsParamsPtr));
#endif
- MOCK_METHOD1(CleanupForShutdown, void(base::OnceClosure));
private:
base::SingleThreadTaskRunner* const task_runner_;
diff --git a/chromium/components/viz/service/surfaces/surface.cc b/chromium/components/viz/service/surfaces/surface.cc
index baee433fc73..9e808d5da97 100644
--- a/chromium/components/viz/service/surfaces/surface.cc
+++ b/chromium/components/viz/service/surfaces/surface.cc
@@ -238,7 +238,7 @@ Surface::QueueFrameResult Surface::QueueFrame(
TakePendingLatencyInfo(&frame.metadata.latency_info);
- base::Optional<FrameData> previous_pending_frame_data =
+ absl::optional<FrameData> previous_pending_frame_data =
std::move(pending_frame_data_);
pending_frame_data_.reset();
@@ -258,6 +258,11 @@ Surface::QueueFrameResult Surface::QueueFrame(
if (deadline_->HasDeadlinePassed()) {
ActivatePendingFrameForDeadline();
} else {
+ // If we are blocked on another Surface, and its latest frame is unacked,
+ // we send the Ack now. This will allow frame production to continue for
+ // that client, leading to the group being unblocked.
+ for (auto* it : blocking_allocation_groups_)
+ it->AckLastestActiveUnAckedFrame();
auto traced_value = std::make_unique<base::trace_event::TracedValue>();
traced_value->BeginArray("Pending");
for (auto& it : activation_dependencies_)
@@ -295,7 +300,7 @@ void Surface::RequestCopyOfOutput(
if (!active_frame_data_)
return;
- for (auto& render_pass : active_frame_data_->frame.render_pass_list) {
+ for (auto& render_pass : GetActiveOrInterpolatedFrame().render_pass_list) {
if (render_pass->subtree_capture_id ==
pending_copy_output_request.subtree_capture_id) {
RequestCopyOfOutputOnRenderPass(
@@ -315,7 +320,7 @@ void Surface::RequestCopyOfOutputOnRootRenderPass(
RequestCopyOfOutputOnRenderPass(
std::move(copy_request),
- *active_frame_data_->frame.render_pass_list.back());
+ *GetActiveOrInterpolatedFrame().render_pass_list.back());
}
bool Surface::RequestCopyOfOutputOnActiveFrameRenderPassId(
@@ -328,7 +333,7 @@ bool Surface::RequestCopyOfOutputOnActiveFrameRenderPassId(
// Find a render pass with a given id, and attach the copy output request on
// it.
- for (auto& render_pass : active_frame_data_->frame.render_pass_list) {
+ for (auto& render_pass : GetActiveOrInterpolatedFrame().render_pass_list) {
if (render_pass->id == render_pass_id) {
RequestCopyOfOutputOnRenderPass(std::move(copy_request), *render_pass);
return true;
@@ -379,7 +384,7 @@ void Surface::ActivatePendingFrame() {
FrameData frame_data = std::move(*pending_frame_data_);
pending_frame_data_.reset();
- base::Optional<base::TimeDelta> duration = deadline_->Cancel();
+ absl::optional<base::TimeDelta> duration = deadline_->Cancel();
if (duration.has_value()) {
TRACE_EVENT_INSTANT2("viz", "SurfaceSynchronizationEvent",
TRACE_EVENT_SCOPE_THREAD, "surface_id",
@@ -460,6 +465,10 @@ void Surface::ActivateFrame(FrameData frame_data) {
TRACE_EVENT1("viz", "Surface::ActivateFrame", "SurfaceId",
surface_id().ToString());
+ // The interpolated frame is based off of the active frame. If we're
+ // activating a new frame we need to do interpolation again (if needed).
+ interpolated_frame_.reset();
+
// Save root pass copy requests.
std::vector<std::unique_ptr<CopyOutputRequest>> old_copy_requests;
if (active_frame_data_) {
@@ -471,7 +480,7 @@ void Surface::ActivateFrame(FrameData frame_data) {
TakeActiveLatencyInfo(&frame_data.frame.metadata.latency_info);
- base::Optional<FrameData> previous_frame_data = std::move(active_frame_data_);
+ absl::optional<FrameData> previous_frame_data = std::move(active_frame_data_);
active_frame_data_ = std::move(frame_data);
@@ -534,7 +543,7 @@ FrameDeadline Surface::ResolveFrameDeadline(
return FrameDeadline::MakeZero();
}
- const base::Optional<uint32_t>& default_deadline =
+ const absl::optional<uint32_t>& default_deadline =
surface_manager_->activation_deadline_in_frames();
const FrameDeadline& deadline = current_frame.metadata.deadline;
uint32_t deadline_in_frames = deadline.deadline_in_frames();
@@ -603,7 +612,8 @@ void Surface::TakeCopyOutputRequests(Surface::CopyRequestsMap* copy_requests) {
if (!active_frame_data_)
return;
- for (const auto& render_pass : active_frame_data_->frame.render_pass_list) {
+ for (const auto& render_pass :
+ GetActiveOrInterpolatedFrame().render_pass_list) {
for (auto& request : render_pass->copy_requests) {
copy_requests->insert(
std::make_pair(render_pass->id, std::move(request)));
@@ -625,7 +635,7 @@ void Surface::TakeCopyOutputRequestsFromClient() {
bool Surface::HasCopyOutputRequests() const {
return active_frame_data_ &&
- active_frame_data_->frame.HasCopyOutputRequests();
+ GetActiveOrInterpolatedFrame().HasCopyOutputRequests();
}
const CompositorFrame& Surface::GetActiveFrame() const {
@@ -640,6 +650,10 @@ const CompositorFrame& Surface::GetActiveOrInterpolatedFrame() const {
return active_frame_data_->frame;
}
+bool Surface::HasInterpolatedFrame() const {
+ return interpolated_frame_.has_value();
+}
+
const CompositorFrameMetadata& Surface::GetActiveFrameMetadata() const {
DCHECK(active_frame_data_);
return active_frame_data_->frame.metadata;
@@ -725,7 +739,7 @@ bool Surface::IsVideoCaptureOnFromClient() {
}
void Surface::UnrefFrameResourcesAndRunCallbacks(
- base::Optional<FrameData> frame_data) {
+ absl::optional<FrameData> frame_data) {
if (!frame_data || !surface_client_)
return;
@@ -734,7 +748,7 @@ void Surface::UnrefFrameResourcesAndRunCallbacks(
// No point in returning same sync token to sender.
for (auto& resource : resources)
resource.sync_token.Clear();
- surface_client_->UnrefResources(resources);
+ surface_client_->UnrefResources(std::move(resources));
if (!frame_data->frame_acked)
surface_client_->OnSurfaceProcessed(this);
@@ -755,7 +769,8 @@ void Surface::UnrefFrameResourcesAndRunCallbacks(
void Surface::ClearCopyRequests() {
if (active_frame_data_) {
- for (const auto& render_pass : active_frame_data_->frame.render_pass_list) {
+ for (const auto& render_pass :
+ GetActiveOrInterpolatedFrame().render_pass_list) {
// When the container is cleared, all copy requests within it will
// auto-send an empty result as they are being destroyed.
render_pass->copy_requests.clear();
diff --git a/chromium/components/viz/service/surfaces/surface.h b/chromium/components/viz/service/surfaces/surface.h
index 8484c8d1f9b..c5875566994 100644
--- a/chromium/components/viz/service/surfaces/surface.h
+++ b/chromium/components/viz/service/surfaces/surface.h
@@ -19,7 +19,6 @@
#include "base/callback_helpers.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/quads/compositor_frame.h"
@@ -30,6 +29,7 @@
#include "components/viz/service/surfaces/surface_dependency_deadline.h"
#include "components/viz/service/surfaces/surface_saved_frame_storage.h"
#include "components/viz/service/viz_service_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/size.h"
namespace cc {
@@ -122,7 +122,7 @@ class VIZ_SERVICE_EXPORT Surface final {
bool has_deadline() const { return deadline_ && deadline_->has_deadline(); }
- base::Optional<base::TimeTicks> deadline_for_testing() const {
+ absl::optional<base::TimeTicks> deadline_for_testing() const {
return deadline_->deadline_for_testing();
}
@@ -170,6 +170,7 @@ class VIZ_SERVICE_EXPORT Surface final {
void ResetInterpolatedFrame();
void SetInterpolatedFrame(CompositorFrame frame);
const CompositorFrame& GetActiveOrInterpolatedFrame() const;
+ bool HasInterpolatedFrame() const;
// Returns true if the active or interpolated frame has damage due to a
// surface animation. This means that the damage should be respected even if
// the active frame index has not changed.
@@ -337,7 +338,7 @@ class VIZ_SERVICE_EXPORT Surface final {
// dependencies will be added even if they're not yet available.
void UpdateActivationDependencies(const CompositorFrame& current_frame);
- void UnrefFrameResourcesAndRunCallbacks(base::Optional<FrameData> frame_data);
+ void UnrefFrameResourcesAndRunCallbacks(absl::optional<FrameData> frame_data);
void ClearCopyRequests();
void TakePendingLatencyInfo(std::vector<ui::LatencyInfo>* latency_info);
@@ -351,9 +352,9 @@ class VIZ_SERVICE_EXPORT Surface final {
base::WeakPtr<SurfaceClient> surface_client_;
std::unique_ptr<SurfaceDependencyDeadline> deadline_;
- base::Optional<FrameData> pending_frame_data_;
- base::Optional<FrameData> active_frame_data_;
- base::Optional<CompositorFrame> interpolated_frame_;
+ absl::optional<FrameData> pending_frame_data_;
+ absl::optional<FrameData> active_frame_data_;
+ absl::optional<CompositorFrame> interpolated_frame_;
bool seen_first_frame_activation_ = false;
bool seen_first_surface_embedding_ = false;
diff --git a/chromium/components/viz/service/surfaces/surface_allocation_group.cc b/chromium/components/viz/service/surfaces/surface_allocation_group.cc
index 048e2e93358..355e29a6672 100644
--- a/chromium/components/viz/service/surfaces/surface_allocation_group.cc
+++ b/chromium/components/viz/service/surfaces/surface_allocation_group.cc
@@ -4,6 +4,8 @@
#include "components/viz/service/surfaces/surface_allocation_group.h"
+#include <utility>
+
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_manager.h"
@@ -176,6 +178,18 @@ void SurfaceAllocationGroup::WillNotRegisterNewSurfaces() {
}
}
+void SurfaceAllocationGroup::AckLastestActiveUnAckedFrame() {
+ if (!last_active_reference_.is_valid())
+ return;
+ SurfaceRange range(last_active_reference_);
+ auto* lastest_active = FindLatestActiveSurfaceInRange(range);
+ // If this group is blocking another Surface, and our latest frame is unacked,
+ // we send the Ack now. This will allow frame production to continue for our
+ // client, leading to this group unblocking the other.
+ if (lastest_active && lastest_active->HasUnackedActiveFrame())
+ lastest_active->SendAckToClient();
+}
+
std::vector<Surface*>::const_iterator
SurfaceAllocationGroup::FindLatestSurfaceUpTo(
const SurfaceId& surface_id) const {
diff --git a/chromium/components/viz/service/surfaces/surface_allocation_group.h b/chromium/components/viz/service/surfaces/surface_allocation_group.h
index f88acdfb8d5..bd69a4ff337 100644
--- a/chromium/components/viz/service/surfaces/surface_allocation_group.h
+++ b/chromium/components/viz/service/surfaces/surface_allocation_group.h
@@ -113,6 +113,10 @@ class VIZ_SERVICE_EXPORT SurfaceAllocationGroup {
// will have their dependency resolved.
void WillNotRegisterNewSurfaces();
+ // Called by surfaces which are blocked by this allocation group. This will
+ // send an Ack to the latest active surface, if it has an un-Acked frame.
+ void AckLastestActiveUnAckedFrame();
+
// Returns the last surface created in this allocation group.
Surface* last_created_surface() const {
return surfaces_.empty() ? nullptr : surfaces_.back();
diff --git a/chromium/components/viz/service/surfaces/surface_client.h b/chromium/components/viz/service/surfaces/surface_client.h
index 44b43bc1edc..a3305ac2b41 100644
--- a/chromium/components/viz/service/surfaces/surface_client.h
+++ b/chromium/components/viz/service/surfaces/surface_client.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/macros.h"
+#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/service/surfaces/pending_copy_output_request.h"
#include "components/viz/service/viz_service_export.h"
@@ -49,13 +50,11 @@ class VIZ_SERVICE_EXPORT SurfaceClient {
const std::vector<TransferableResource>& resources) = 0;
// Decrements the reference count on resources specified by |resources|.
- virtual void UnrefResources(
- const std::vector<ReturnedResource>& resources) = 0;
+ virtual void UnrefResources(std::vector<ReturnedResource> resources) = 0;
// ReturnResources gets called when the display compositor is done using the
// resources so that the client can use them.
- virtual void ReturnResources(
- const std::vector<ReturnedResource>& resources) = 0;
+ virtual void ReturnResources(std::vector<ReturnedResource> resources) = 0;
// Increments the reference count of resources received from a child
// compositor.
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc b/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc
index e193c56283c..c07469a94de 100644
--- a/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc
+++ b/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc
@@ -31,9 +31,9 @@ bool SurfaceDependencyDeadline::HasDeadlinePassed() const {
return tick_clock_->NowTicks() >= deadline_;
}
-base::Optional<base::TimeDelta> SurfaceDependencyDeadline::Cancel() {
+absl::optional<base::TimeDelta> SurfaceDependencyDeadline::Cancel() {
if (!deadline_)
- return base::nullopt;
+ return absl::nullopt;
deadline_.reset();
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_deadline.h b/chromium/components/viz/service/surfaces/surface_dependency_deadline.h
index 6a7747dfaa8..b3291296569 100644
--- a/chromium/components/viz/service/surfaces/surface_dependency_deadline.h
+++ b/chromium/components/viz/service/surfaces/surface_dependency_deadline.h
@@ -5,8 +5,8 @@
#ifndef COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_DEPENDENCY_DEADLINE_H_
#define COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_DEPENDENCY_DEADLINE_H_
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "base/macros.h"
#include "components/viz/service/viz_service_export.h"
@@ -33,12 +33,12 @@ class VIZ_SERVICE_EXPORT SurfaceDependencyDeadline {
// If a deadline had been set, then cancel the deadline and return the
// the duration of the event tracked by this object. If there was no
- // deadline set, then return base::nullopt.
- base::Optional<base::TimeDelta> Cancel();
+ // deadline set, then return absl::nullopt.
+ absl::optional<base::TimeDelta> Cancel();
bool has_deadline() const { return deadline_.has_value(); }
- base::Optional<base::TimeTicks> deadline_for_testing() const {
+ absl::optional<base::TimeTicks> deadline_for_testing() const {
return deadline_;
}
@@ -50,7 +50,7 @@ class VIZ_SERVICE_EXPORT SurfaceDependencyDeadline {
private:
const base::TickClock* tick_clock_;
base::TimeTicks start_time_;
- base::Optional<base::TimeTicks> deadline_;
+ absl::optional<base::TimeTicks> deadline_;
DISALLOW_COPY_AND_ASSIGN(SurfaceDependencyDeadline);
};
diff --git a/chromium/components/viz/service/surfaces/surface_manager.cc b/chromium/components/viz/service/surfaces/surface_manager.cc
index 4c811beaa35..79d635a9cad 100644
--- a/chromium/components/viz/service/surfaces/surface_manager.cc
+++ b/chromium/components/viz/service/surfaces/surface_manager.cc
@@ -15,6 +15,7 @@
#include "base/logging.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
+#include "base/trace_event/trace_event.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/service/surfaces/surface.h"
@@ -35,7 +36,7 @@ constexpr base::TimeDelta kExpireInterval = base::TimeDelta::FromSeconds(10);
SurfaceManager::SurfaceManager(
SurfaceManagerDelegate* delegate,
- base::Optional<uint32_t> activation_deadline_in_frames)
+ absl::optional<uint32_t> activation_deadline_in_frames)
: delegate_(delegate),
activation_deadline_in_frames_(activation_deadline_in_frames),
root_surface_id_(FrameSinkId(0u, 0u),
@@ -83,7 +84,7 @@ std::string SurfaceManager::SurfaceReferencesToString() {
#endif
void SurfaceManager::SetActivationDeadlineInFramesForTesting(
- base::Optional<uint32_t> activation_deadline_in_frames) {
+ absl::optional<uint32_t> activation_deadline_in_frames) {
activation_deadline_in_frames_ = activation_deadline_in_frames;
}
@@ -454,6 +455,11 @@ void SurfaceManager::SurfaceActivated(Surface* surface) {
TRACE_EVENT_INSTANT0("viz", "Damage not visible.",
TRACE_EVENT_SCOPE_THREAD);
surface->SendAckToClient();
+ } else if (HasBlockedEmbedder(surface->surface_id().frame_sink_id())) {
+ // If the Surface is a part of a blocked embedding group, Ack even if it is
+ // modified. This will allow frame production to continue for this client
+ // leading to the group being unblocked.
+ surface->SendAckToClient();
}
for (auto& observer : observer_list_)
diff --git a/chromium/components/viz/service/surfaces/surface_manager.h b/chromium/components/viz/service/surfaces/surface_manager.h
index a2a774769f7..fb99d740f00 100644
--- a/chromium/components/viz/service/surfaces/surface_manager.h
+++ b/chromium/components/viz/service/surfaces/surface_manager.h
@@ -18,14 +18,13 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
-#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "base/timer/timer.h"
-#include "base/trace_event/trace_event.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/service/surfaces/surface_observer.h"
#include "components/viz/service/surfaces/surface_reference.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#if DCHECK_IS_ON()
#include <iosfwd>
@@ -49,7 +48,7 @@ struct BeginFrameArgs;
class VIZ_SERVICE_EXPORT SurfaceManager {
public:
SurfaceManager(SurfaceManagerDelegate* delegate,
- base::Optional<uint32_t> activation_deadline_in_frames);
+ absl::optional<uint32_t> activation_deadline_in_frames);
~SurfaceManager();
#if DCHECK_IS_ON()
@@ -58,12 +57,12 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
#endif
// Sets an alternative system default frame activation deadline for unit
- // tests. base::nullopt indicates no deadline (in other words, an unlimited
+ // tests. absl::nullopt indicates no deadline (in other words, an unlimited
// deadline).
void SetActivationDeadlineInFramesForTesting(
- base::Optional<uint32_t> deadline);
+ absl::optional<uint32_t> deadline);
- base::Optional<uint32_t> activation_deadline_in_frames() const {
+ absl::optional<uint32_t> activation_deadline_in_frames() const {
return activation_deadline_in_frames_;
}
@@ -270,7 +269,7 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
// Can be nullptr.
SurfaceManagerDelegate* const delegate_;
- base::Optional<uint32_t> activation_deadline_in_frames_;
+ absl::optional<uint32_t> activation_deadline_in_frames_;
base::flat_map<base::UnguessableToken,
std::unique_ptr<SurfaceAllocationGroup>>
@@ -319,7 +318,7 @@ class VIZ_SERVICE_EXPORT SurfaceManager {
// Timer to remove old temporary references that aren't removed after an
// interval of time. The timer will started/stopped so it only runs if there
// are temporary references. Also the timer isn't used with Android WebView.
- base::Optional<base::RepeatingTimer> expire_timer_;
+ absl::optional<base::RepeatingTimer> expire_timer_;
bool allocation_groups_need_garbage_collection_ = false;
diff --git a/chromium/components/viz/service/surfaces/surface_observer.h b/chromium/components/viz/service/surfaces/surface_observer.h
index e88d661b7bc..314f8ae26bd 100644
--- a/chromium/components/viz/service/surfaces/surface_observer.h
+++ b/chromium/components/viz/service/surfaces/surface_observer.h
@@ -5,9 +5,8 @@
#ifndef COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_OBSERVER_H_
#define COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_OBSERVER_H_
-#include "base/optional.h"
-#include "base/time/time.h"
#include "components/viz/service/viz_service_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace viz {
diff --git a/chromium/components/viz/service/surfaces/surface_saved_frame.cc b/chromium/components/viz/service/surfaces/surface_saved_frame.cc
index 8c310c2a2cc..4b3ed5596ff 100644
--- a/chromium/components/viz/service/surfaces/surface_saved_frame.cc
+++ b/chromium/components/viz/service/surfaces/surface_saved_frame.cc
@@ -4,42 +4,33 @@
#include "components/viz/service/surfaces/surface_saved_frame.h"
+#include <iterator>
#include <utility>
+#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/quads/compositor_frame_transition_directive.h"
+#include "components/viz/common/quads/compositor_render_pass.h"
+#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
+#include "components/viz/common/quads/draw_quad.h"
+#include "components/viz/common/transition_utils.h"
#include "components/viz/service/surfaces/surface.h"
+#include "services/viz/public/mojom/compositing/compositor_render_pass_id.mojom.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/geometry/point.h"
namespace viz {
namespace {
constexpr gfx::Size kDefaultTextureSizeForTesting = gfx::Size(20, 20);
-struct RenderPassGeometry {
- gfx::Rect rect;
- gfx::Transform target_transform;
-};
-
-RenderPassGeometry GetRootRenderPassGeometry(Surface* surface) {
+SurfaceSavedFrame::RenderPassDrawData GetRootRenderPassDrawData(
+ Surface* surface) {
const auto& frame = surface->GetActiveFrame();
DCHECK(!frame.render_pass_list.empty());
const auto& root_render_pass = frame.render_pass_list.back();
- return {root_render_pass->output_rect,
- root_render_pass->transform_to_root_target};
-}
-
-RenderPassGeometry GetRenderPassGeometryInRootSpace(
- Surface* surface,
- const CompositorRenderPassId& render_pass_id) {
- const auto& frame = surface->GetActiveFrame();
- for (const auto& render_pass : frame.render_pass_list) {
- if (render_pass_id != render_pass->id)
- continue;
- return {render_pass->output_rect, render_pass->transform_to_root_target};
- }
- NOTREACHED();
- return {gfx::Rect(), gfx::Transform()};
+ return {*root_render_pass, 1.f};
}
} // namespace
@@ -67,42 +58,179 @@ bool SurfaceSavedFrame::IsValid() const {
void SurfaceSavedFrame::RequestCopyOfOutput(Surface* surface) {
DCHECK(surface->HasActiveFrame());
- const auto& root_geometry = GetRootRenderPassGeometry(surface);
+
+ // RGBA_TEXTURE will become RGBA_BITMAP with SoftwareCompositing path.
+ // TODO(kylechar): Add RGBA_NATIVE that returns either RGBA_TEXTURE or
+ // RGBA_BITMAP depending on what is native.
+ constexpr auto result_format = CopyOutputRequest::ResultFormat::RGBA_TEXTURE;
+
+ const auto& root_draw_data = GetRootRenderPassDrawData(surface);
// Bind kRoot and root geometry information to the callback.
- auto request = std::make_unique<CopyOutputRequest>(
- CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
+ auto root_request = std::make_unique<CopyOutputRequest>(
+ result_format,
base::BindOnce(&SurfaceSavedFrame::NotifyCopyOfOutputComplete,
weak_factory_.GetWeakPtr(), ResultType::kRoot, 0,
- root_geometry.rect, root_geometry.target_transform));
- request->set_result_task_runner(base::ThreadTaskRunnerHandle::Get());
- surface->RequestCopyOfOutputOnRootRenderPass(std::move(request));
- copy_request_count_ = 1;
+ root_draw_data));
+ root_request->set_result_task_runner(base::ThreadTaskRunnerHandle::Get());
+ copy_request_count_ = 0;
- const auto& shared_pass_ids = directive_.shared_render_pass_ids();
- for (size_t i = 0; i < shared_pass_ids.size(); ++i) {
- if (shared_pass_ids[i].is_null())
- continue;
-
- const auto& geometry =
- GetRenderPassGeometryInRootSpace(surface, shared_pass_ids[i]);
- // Shared callbacks bind kShared with an index, and geometry information on
- // the callbacks.
- auto request = std::make_unique<CopyOutputRequest>(
- CopyOutputRequest::ResultFormat::RGBA_TEXTURE,
- base::BindOnce(&SurfaceSavedFrame::NotifyCopyOfOutputComplete,
- weak_factory_.GetWeakPtr(), ResultType::kShared, i,
- geometry.rect, geometry.target_transform));
- request->set_result_task_runner(base::ThreadTaskRunnerHandle::Get());
- bool success = surface->RequestCopyOfOutputOnActiveFrameRenderPassId(
- std::move(request), shared_pass_ids[i]);
- DCHECK(success) << "PassId: " << shared_pass_ids[i];
-
- ++copy_request_count_;
+ // Only one copy request implies only the root element needs to be copied so
+ // the frame must not have any shared element render passes.
+ if (ExpectedResultCount() == 1) {
+ surface->RequestCopyOfOutputOnRootRenderPass(std::move(root_request));
+ copy_request_count_++;
+ return;
+ }
+
+ // If the directive includes shared elements then we need to create a new
+ // CompositorFrame with render passes that remove these elements. The strategy
+ // is as follows :
+ //
+ // 1) For each render pass create a deep copy with identical content that will
+ // draw (directly or indirectly) to the onscreen buffer.
+ //
+ // 2) If a render pass is a shared element or is "tainted" (includes content
+ // from a shared element), create a new "clean" render pass with the
+ // following modifications :
+ //
+ // - RenderPassDrawQuads which are 1:1 with a shared element are removed.
+ //
+ // - RenderPassDrawQuads which are tainted are replaced with the equivalent
+ // clean render pass.
+ //
+ // The new clean render passes are only used to issue copy requests and
+ // never drawn to the onscreen buffer.
+ const auto& active_frame = surface->GetActiveFrame();
+ CompositorRenderPassId max_id = CompositorRenderPassId(0);
+ base::flat_map<CompositorRenderPassId, CompositorRenderPassId>
+ tainted_to_clean_pass_ids;
+ PrepareForCopy(active_frame.render_pass_list, max_id,
+ tainted_to_clean_pass_ids);
+
+ DCHECK(tainted_to_clean_pass_ids.contains(
+ (active_frame.render_pass_list.back()->id)))
+ << "The root pass must be tainted";
+
+ TransitionUtils::FilterCallback filter_callback = base::BindRepeating(
+ &SurfaceSavedFrame::FilterSharedElementAndTaintedQuads,
+ base::Unretained(this), base::Unretained(&tainted_to_clean_pass_ids));
+
+ CompositorFrame interpolated_frame;
+ interpolated_frame.metadata = active_frame.metadata.Clone();
+ interpolated_frame.resource_list = active_frame.resource_list;
+
+ for (auto& render_pass : active_frame.render_pass_list) {
+ const auto original_render_pass_id = render_pass->id;
+ CompositorRenderPass* pass_for_clean_copy = nullptr;
+
+ auto it = tainted_to_clean_pass_ids.find(original_render_pass_id);
+ if (it != tainted_to_clean_pass_ids.end()) {
+ auto clean_pass = TransitionUtils::CopyPassWithRenderPassFiltering(
+ *render_pass, filter_callback);
+ it->second = max_id = clean_pass->id =
+ TransitionUtils::NextRenderPassId(max_id);
+ pass_for_clean_copy = clean_pass.get();
+ interpolated_frame.render_pass_list.push_back(std::move(clean_pass));
+ }
+
+ // Deep copy of the original pass propagating copy requests.
+ auto copy_requests = std::move(render_pass->copy_requests);
+ auto duplicate_pass = render_pass->DeepCopy();
+ duplicate_pass->copy_requests = std::move(copy_requests);
+ if (!pass_for_clean_copy)
+ pass_for_clean_copy = duplicate_pass.get();
+ interpolated_frame.render_pass_list.push_back(std::move(duplicate_pass));
+
+ const auto& shared_pass_ids = directive_.shared_render_pass_ids();
+ auto shared_pass_it =
+ std::find(shared_pass_ids.begin(), shared_pass_ids.end(),
+ original_render_pass_id);
+ if (shared_pass_it != shared_pass_ids.end()) {
+ RenderPassDrawData draw_data(
+ *render_pass,
+ TransitionUtils::ComputeAccumulatedOpacity(
+ active_frame.render_pass_list, original_render_pass_id));
+ int index = std::distance(shared_pass_ids.begin(), shared_pass_it);
+ auto request = std::make_unique<CopyOutputRequest>(
+ result_format,
+ base::BindOnce(&SurfaceSavedFrame::NotifyCopyOfOutputComplete,
+ weak_factory_.GetWeakPtr(), ResultType::kShared, index,
+ draw_data));
+ request->set_result_task_runner(base::ThreadTaskRunnerHandle::Get());
+ pass_for_clean_copy->copy_requests.push_back(std::move(request));
+ copy_request_count_++;
+ }
+
+ bool is_root_pass =
+ original_render_pass_id == active_frame.render_pass_list.back()->id;
+ if (is_root_pass) {
+ DCHECK(root_request);
+ pass_for_clean_copy->copy_requests.push_back(std::move(root_request));
+ copy_request_count_++;
+ }
}
+ surface_.emplace(surface, std::move(interpolated_frame));
+
DCHECK_EQ(copy_request_count_, ExpectedResultCount());
}
+void SurfaceSavedFrame::ReleaseSurface() {
+ surface_.reset();
+}
+
+void SurfaceSavedFrame::PrepareForCopy(
+ const CompositorRenderPassList& render_passes,
+ CompositorRenderPassId& max_id,
+ base::flat_map<CompositorRenderPassId, CompositorRenderPassId>&
+ tainted_to_clean_pass_ids) const {
+ for (const auto& pass : render_passes) {
+ max_id = std::max(max_id, pass->id);
+
+ for (auto it = pass->quad_list.BackToFrontBegin();
+ it != pass->quad_list.BackToFrontEnd(); ++it) {
+ const DrawQuad* quad = *it;
+ if (quad->material != DrawQuad::Material::kCompositorRenderPass)
+ continue;
+
+ auto quad_pass_id =
+ CompositorRenderPassDrawQuad::MaterialCast(quad)->render_pass_id;
+ if (IsSharedElementRenderPass(quad_pass_id) ||
+ tainted_to_clean_pass_ids.contains(quad_pass_id)) {
+ tainted_to_clean_pass_ids[pass->id] = CompositorRenderPassId(0);
+ break;
+ }
+ }
+ }
+}
+
+bool SurfaceSavedFrame::FilterSharedElementAndTaintedQuads(
+ const base::flat_map<CompositorRenderPassId, CompositorRenderPassId>*
+ tainted_to_clean_pass_ids,
+ const CompositorRenderPassDrawQuad& pass_quad,
+ CompositorRenderPass& copy_pass) const {
+ // Skip drawing shared elements embedded inside render passes.
+ if (IsSharedElementRenderPass(pass_quad.render_pass_id))
+ return true;
+
+ // Replace tainted quads with equivalent clean render passes.
+ auto it = tainted_to_clean_pass_ids->find(pass_quad.render_pass_id);
+ if (it != tainted_to_clean_pass_ids->end()) {
+ DCHECK_NE(it->second, CompositorRenderPassId(0));
+ copy_pass.CopyFromAndAppendRenderPassDrawQuad(&pass_quad, it->second);
+ return true;
+ }
+
+ return false;
+}
+
+bool SurfaceSavedFrame::IsSharedElementRenderPass(
+ CompositorRenderPassId pass_id) const {
+ const auto& shared_pass_ids = directive_.shared_render_pass_ids();
+ return std::find(shared_pass_ids.begin(), shared_pass_ids.end(), pass_id) !=
+ shared_pass_ids.end();
+}
+
size_t SurfaceSavedFrame::ExpectedResultCount() const {
// Start with 1 for the root render pass.
size_t count = 1;
@@ -114,25 +242,21 @@ size_t SurfaceSavedFrame::ExpectedResultCount() const {
void SurfaceSavedFrame::NotifyCopyOfOutputComplete(
ResultType type,
size_t shared_index,
- const gfx::Rect& rect,
- const gfx::Transform& target_transform,
+ const RenderPassDrawData& data,
std::unique_ptr<CopyOutputResult> output_copy) {
DCHECK_GT(copy_request_count_, 0u);
// Even if we early out, we update the count since we are no longer waiting
// for this result.
- if (--copy_request_count_ == 0)
+ if (--copy_request_count_ == 0) {
std::move(directive_finished_callback_).Run(directive_.sequence_id());
+ surface_.reset();
+ }
// Return if the result is empty.
// TODO(vmpstr): We should log / trace this.
if (output_copy->IsEmpty())
return;
- // TODO(crbug.com/1174129): We need to support SoftwareRenderer, which would
- // return a bitmap result here.
- if (!output_copy->GetTextureResult())
- return;
-
++valid_result_count_;
if (!frame_result_) {
frame_result_.emplace();
@@ -141,7 +265,6 @@ void SurfaceSavedFrame::NotifyCopyOfOutputComplete(
directive_.shared_render_pass_ids().size());
}
- auto output_copy_texture = *output_copy->GetTextureResult();
OutputCopyResult* slot = nullptr;
if (type == ResultType::kRoot) {
slot = &frame_result_->root_result;
@@ -153,27 +276,35 @@ void SurfaceSavedFrame::NotifyCopyOfOutputComplete(
}
DCHECK(slot);
- DCHECK_EQ(output_copy->size(), rect.size());
- slot->mailbox = output_copy_texture.mailbox;
- slot->sync_token = output_copy_texture.sync_token;
- slot->release_callback = output_copy->TakeTextureOwnership();
- slot->rect = rect;
- slot->target_transform = target_transform;
- slot->is_software = false;
+ DCHECK_EQ(output_copy->size(), data.size);
+ if (output_copy->format() == CopyOutputResult::Format::RGBA_BITMAP) {
+ slot->bitmap = output_copy->ScopedAccessSkBitmap().GetOutScopedBitmap();
+ slot->is_software = true;
+ } else {
+ auto output_copy_texture = *output_copy->GetTextureResult();
+ slot->mailbox = output_copy_texture.mailbox;
+ slot->sync_token = output_copy_texture.sync_token;
+ slot->release_callback = output_copy->TakeTextureOwnership();
+ slot->is_software = false;
+ }
+ slot->draw_data = data;
}
-base::Optional<SurfaceSavedFrame::FrameResult> SurfaceSavedFrame::TakeResult() {
- return std::exchange(frame_result_, base::nullopt);
+absl::optional<SurfaceSavedFrame::FrameResult> SurfaceSavedFrame::TakeResult() {
+ return std::exchange(frame_result_, absl::nullopt);
}
-void SurfaceSavedFrame::CompleteSavedFrameForTesting(
- base::OnceCallback<void(const gpu::SyncToken&, bool)> release_callback) {
+void SurfaceSavedFrame::CompleteSavedFrameForTesting() {
+ SkBitmap bitmap;
+ bitmap.allocPixels(
+ SkImageInfo::MakeN32Premul(kDefaultTextureSizeForTesting.width(),
+ kDefaultTextureSizeForTesting.height()));
+
frame_result_.emplace();
- frame_result_->root_result.mailbox = gpu::Mailbox::GenerateForSharedImage();
- frame_result_->root_result.release_callback =
- SingleReleaseCallback::Create(std::move(release_callback));
- frame_result_->root_result.rect = gfx::Rect(kDefaultTextureSizeForTesting);
- frame_result_->root_result.target_transform.MakeIdentity();
+ frame_result_->root_result.bitmap = std::move(bitmap);
+ frame_result_->root_result.draw_data.size = kDefaultTextureSizeForTesting;
+ frame_result_->root_result.draw_data.target_transform.MakeIdentity();
+ frame_result_->root_result.draw_data.opacity = 1.f;
frame_result_->root_result.is_software = true;
frame_result_->shared_results.resize(
@@ -184,6 +315,20 @@ void SurfaceSavedFrame::CompleteSavedFrameForTesting(
DCHECK(IsValid());
}
+SurfaceSavedFrame::RenderPassDrawData::RenderPassDrawData() = default;
+SurfaceSavedFrame::RenderPassDrawData::RenderPassDrawData(
+ const CompositorRenderPass& render_pass,
+ float opacity)
+ : opacity(opacity) {
+ // During copy request, the origin for |render_pass|'s output_rect is mapped
+ // to the origin of the texture in the result. We account for that here.
+ size = render_pass.output_rect.size();
+
+ target_transform = render_pass.transform_to_root_target;
+ target_transform.Translate(render_pass.output_rect.x(),
+ render_pass.output_rect.y());
+}
+
SurfaceSavedFrame::OutputCopyResult::OutputCopyResult() = default;
SurfaceSavedFrame::OutputCopyResult::OutputCopyResult(
OutputCopyResult&& other) {
@@ -192,7 +337,7 @@ SurfaceSavedFrame::OutputCopyResult::OutputCopyResult(
SurfaceSavedFrame::OutputCopyResult::~OutputCopyResult() {
if (release_callback)
- release_callback->Run(sync_token, /*is_lost=*/false);
+ std::move(release_callback).Run(sync_token, /*is_lost=*/false);
}
SurfaceSavedFrame::OutputCopyResult&
@@ -203,8 +348,10 @@ SurfaceSavedFrame::OutputCopyResult::operator=(OutputCopyResult&& other) {
sync_token = std::move(other.sync_token);
other.sync_token = gpu::SyncToken();
- rect = std::move(other.rect);
- target_transform = std::move(other.target_transform);
+ bitmap = std::move(other.bitmap);
+ other.bitmap = SkBitmap();
+
+ draw_data = std::move(other.draw_data);
release_callback = std::move(other.release_callback);
@@ -223,4 +370,15 @@ SurfaceSavedFrame::FrameResult::~FrameResult() = default;
SurfaceSavedFrame::FrameResult& SurfaceSavedFrame::FrameResult::operator=(
FrameResult&& other) = default;
+SurfaceSavedFrame::ScopedInterpolatedSurface::ScopedInterpolatedSurface(
+ Surface* surface,
+ CompositorFrame frame)
+ : surface_(surface) {
+ surface_->SetInterpolatedFrame(std::move(frame));
+}
+
+SurfaceSavedFrame::ScopedInterpolatedSurface::~ScopedInterpolatedSurface() {
+ surface_->ResetInterpolatedFrame();
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/surfaces/surface_saved_frame.h b/chromium/components/viz/service/surfaces/surface_saved_frame.h
index 8c6b06da4eb..c82728236d0 100644
--- a/chromium/components/viz/service/surfaces/surface_saved_frame.h
+++ b/chromium/components/viz/service/surfaces/surface_saved_frame.h
@@ -9,13 +9,15 @@
#include <vector>
#include "base/compiler_specific.h"
+#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
-#include "base/time/time.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
+#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/compositor_frame_transition_directive.h"
-#include "components/viz/common/resources/single_release_callback.h"
+#include "components/viz/common/quads/compositor_render_pass.h"
+#include "components/viz/common/resources/release_callback.h"
#include "components/viz/service/viz_service_export.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace viz {
@@ -26,6 +28,20 @@ class VIZ_SERVICE_EXPORT SurfaceSavedFrame {
using TransitionDirectiveCompleteCallback =
base::OnceCallback<void(uint32_t)>;
+ struct RenderPassDrawData {
+ RenderPassDrawData();
+ RenderPassDrawData(const CompositorRenderPass& render_pass, float opacity);
+
+ // This represents the size of the copied texture.
+ gfx::Size size;
+ // This is a transform that takes `rect` into a root render pass space. Note
+ // that this makes this result dependent on the structure of the compositor
+ // frame render pass list used to request the copy output.
+ gfx::Transform target_transform;
+ // Opacity accumulated from the original frame.
+ float opacity = 1.f;
+ };
+
struct OutputCopyResult {
OutputCopyResult();
OutputCopyResult(OutputCopyResult&& other);
@@ -37,18 +53,18 @@ class VIZ_SERVICE_EXPORT SurfaceSavedFrame {
gpu::Mailbox mailbox;
gpu::SyncToken sync_token;
- // This represents the region for the pixel output.
- gfx::Rect rect;
- // This is a transform that takes `rect` into a root render pass space. Note
- // that this makes this result dependent on the structure of the compositor
- // frame render pass list used to request the copy output.
- gfx::Transform target_transform;
+ // Software bitmap representation.
+ SkBitmap bitmap;
+
+ // This is information needed to draw the texture as if it was a part of the
+ // original frame.
+ RenderPassDrawData draw_data;
// Is this a software or a GPU copy result?
bool is_software = false;
// Release callback used to return a GPU texture.
- std::unique_ptr<SingleReleaseCallback> release_callback;
+ ReleaseCallback release_callback;
};
struct FrameResult {
@@ -59,7 +75,7 @@ class VIZ_SERVICE_EXPORT SurfaceSavedFrame {
FrameResult& operator=(FrameResult&& other);
OutputCopyResult root_result;
- std::vector<base::Optional<OutputCopyResult>> shared_results;
+ std::vector<absl::optional<OutputCopyResult>> shared_results;
};
SurfaceSavedFrame(CompositorFrameTransitionDirective directive,
@@ -74,28 +90,63 @@ class VIZ_SERVICE_EXPORT SurfaceSavedFrame {
// Appends copy output requests to the needed render passes in the active
// frame.
void RequestCopyOfOutput(Surface* surface);
+ void ReleaseSurface();
- base::Optional<FrameResult> TakeResult() WARN_UNUSED_RESULT;
+ absl::optional<FrameResult> TakeResult() WARN_UNUSED_RESULT;
// For testing functionality that ensures that we have a valid frame.
- void CompleteSavedFrameForTesting(
- base::OnceCallback<void(const gpu::SyncToken&, bool)> release_callback);
+ void CompleteSavedFrameForTesting();
private:
enum class ResultType { kRoot, kShared };
+ class ScopedInterpolatedSurface {
+ public:
+ ScopedInterpolatedSurface(Surface* surface, CompositorFrame frame);
+ ~ScopedInterpolatedSurface();
+
+ private:
+ Surface* surface_;
+ };
+
void NotifyCopyOfOutputComplete(ResultType type,
size_t shared_index,
- const gfx::Rect& rect,
- const gfx::Transform& target_transform,
+ const RenderPassDrawData& info,
std::unique_ptr<CopyOutputResult> result);
size_t ExpectedResultCount() const;
+ // Collects metadata to create a copy of the source CompositorFrame for shared
+ // element snapshots.
+ // |render_passes| is the render pass list from the source frame.
+ // |max_id| returns the maximum render pass id in the list above.
+ // |tainted_to_clean_pass_ids| populates the set of render passes which
+ // include shared elements and need clean render passes for snapshots.
+ void PrepareForCopy(
+ const CompositorRenderPassList& render_passes,
+ CompositorRenderPassId& max_id,
+ base::flat_map<CompositorRenderPassId, CompositorRenderPassId>&
+ tainted_to_clean_pass_ids) const;
+
+ // Used to filter render pass draw quads when copying render passes for shared
+ // element snapshots.
+ // |tained_to_clean_pass_ids| is used to replace tainted quads with the
+ // equivalent clean render passes.
+ // |pass_quad| is the quad from the source pass being copied.
+ // |copy_pass| is the new clean pass being created.
+ bool FilterSharedElementAndTaintedQuads(
+ const base::flat_map<CompositorRenderPassId, CompositorRenderPassId>*
+ tainted_to_clean_pass_ids,
+ const CompositorRenderPassDrawQuad& pass_quad,
+ CompositorRenderPass& copy_pass) const;
+
+ // Returns true if |pass_id|'s content is 1:1 with a shared element.
+ bool IsSharedElementRenderPass(CompositorRenderPassId pass_id) const;
+
CompositorFrameTransitionDirective directive_;
TransitionDirectiveCompleteCallback directive_finished_callback_;
- base::Optional<FrameResult> frame_result_;
+ absl::optional<FrameResult> frame_result_;
// This is the number of copy requests we requested. We decrement this value
// anytime we get a result back. When it reaches 0, we notify that this frame
@@ -108,6 +159,8 @@ class VIZ_SERVICE_EXPORT SurfaceSavedFrame {
// whether the SurfaceSavedFrame is "valid".
size_t valid_result_count_ = 0;
+ absl::optional<ScopedInterpolatedSurface> surface_;
+
base::WeakPtrFactory<SurfaceSavedFrame> weak_factory_{this};
};
diff --git a/chromium/components/viz/service/surfaces/surface_saved_frame_storage.cc b/chromium/components/viz/service/surfaces/surface_saved_frame_storage.cc
index 2a534b6ded6..498e0a9a8cc 100644
--- a/chromium/components/viz/service/surfaces/surface_saved_frame_storage.cc
+++ b/chromium/components/viz/service/surfaces/surface_saved_frame_storage.cc
@@ -54,6 +54,10 @@ void SurfaceSavedFrameStorage::ProcessSaveDirective(
std::unique_ptr<SurfaceSavedFrame> SurfaceSavedFrameStorage::TakeSavedFrame() {
expiry_closure_.Cancel();
+
+ // We might not have a saved frame here if it expired.
+ if (saved_frame_)
+ saved_frame_->ReleaseSurface();
return std::move(saved_frame_);
}
@@ -69,8 +73,7 @@ void SurfaceSavedFrameStorage::ExpireForTesting() {
void SurfaceSavedFrameStorage::CompleteForTesting() {
if (saved_frame_) {
- saved_frame_->CompleteSavedFrameForTesting( // IN-TEST
- base::BindOnce([](const gpu::SyncToken&, bool) {}));
+ saved_frame_->CompleteSavedFrameForTesting(); // IN-TEST
}
}
diff --git a/chromium/components/viz/service/surfaces/surface_saved_frame_unittest.cc b/chromium/components/viz/service/surfaces/surface_saved_frame_unittest.cc
new file mode 100644
index 00000000000..d9f251af82c
--- /dev/null
+++ b/chromium/components/viz/service/surfaces/surface_saved_frame_unittest.cc
@@ -0,0 +1,387 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstdint>
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "components/viz/common/quads/compositor_frame_transition_directive.h"
+#include "components/viz/common/quads/compositor_render_pass.h"
+#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
+#include "components/viz/common/quads/shared_quad_state.h"
+#include "components/viz/common/quads/solid_color_draw_quad.h"
+#include "components/viz/common/resources/resource_id.h"
+#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
+#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
+#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/surfaces/surface.h"
+#include "components/viz/service/surfaces/surface_saved_frame.h"
+#include "components/viz/test/compositor_frame_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBlendMode.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/rrect_f.h"
+#include "ui/gfx/transform.h"
+
+namespace viz {
+namespace {
+
+constexpr gfx::Rect kQuadLayerRect{0, 0, 20, 20};
+constexpr gfx::Rect kVisibleLayerRect{5, 5, 10, 10};
+
+class SurfaceSavedFrameTest : public testing::Test {
+ public:
+ void SetUp() override {
+ constexpr FrameSinkId kArbitraryFrameSinkId(1, 1);
+ support_ = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, &frame_sink_manager_, kArbitraryFrameSinkId, /*is_root=*/true);
+ LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create());
+ surface_id_ = SurfaceId(kArbitraryFrameSinkId, local_surface_id);
+ }
+
+ void DirectiveComplete(uint32_t sequence_id) {
+ last_complete_id_ = sequence_id;
+ run_loop_.Quit();
+ }
+
+ std::unique_ptr<SurfaceSavedFrame> CreateSavedFrame(
+ CompositorFrameTransitionDirective directive) {
+ return std::make_unique<SurfaceSavedFrame>(
+ directive,
+ base::BindRepeating(&SurfaceSavedFrameTest::DirectiveComplete,
+ base::Unretained(this)));
+ }
+
+ Surface* GetSurface() {
+ return frame_sink_manager_.surface_manager()->GetSurfaceForId(surface_id_);
+ }
+
+ void CancelAllCopyRequests() {
+ for (auto& pass :
+ GetSurface()->GetActiveOrInterpolatedFrame().render_pass_list) {
+ pass->copy_requests.clear();
+ }
+ run_loop_.Run();
+ }
+
+ SharedQuadState* AddSharedQuadState(CompositorRenderPass& render_pass) {
+ auto* sqs = render_pass.CreateAndAppendSharedQuadState();
+ gfx::Transform quad_to_target_transform;
+ sqs->SetAll(quad_to_target_transform, kQuadLayerRect, kVisibleLayerRect,
+ gfx::MaskFilterInfo(), kQuadLayerRect, true, 0.9f,
+ SkBlendMode::kClear, 2);
+ return sqs;
+ }
+
+ CompositorRenderPassDrawQuad* AddRenderPassDrawQuad(
+ CompositorRenderPass& render_pass) {
+ auto* pass_quad =
+ render_pass.CreateAndAppendDrawQuad<CompositorRenderPassDrawQuad>();
+ pass_quad->SetAll(render_pass.shared_quad_state_list.front(),
+ kQuadLayerRect, kVisibleLayerRect, true,
+ CompositorRenderPassId(1), ResourceId(4),
+ gfx::RectF(0, 0, 0.4f, 0.4f), gfx::Size(20, 20),
+ gfx::Vector2dF(0.4f, 0.4f), gfx::PointF(0.2f, 0.2f),
+ gfx::RectF(0, 0, 0.4f, 0.4f), true, 0.5f, true);
+ return pass_quad;
+ }
+
+ SolidColorDrawQuad* AddSolidColorDrawQuad(CompositorRenderPass& render_pass) {
+ auto* solid_color_quad =
+ render_pass.CreateAndAppendDrawQuad<SolidColorDrawQuad>();
+ solid_color_quad->SetAll(render_pass.shared_quad_state_list.front(),
+ kQuadLayerRect, kVisibleLayerRect, true,
+ SK_ColorBLACK, true);
+ return solid_color_quad;
+ }
+
+ protected:
+ ServerSharedBitmapManager shared_bitmap_manager_;
+ FrameSinkManagerImpl frame_sink_manager_{&shared_bitmap_manager_};
+ std::unique_ptr<CompositorFrameSinkSupport> support_;
+ SurfaceId surface_id_;
+
+ uint32_t last_complete_id_ = 0u;
+ base::RunLoop run_loop_;
+};
+
+// No interpolated frame if there are no shared elements.
+TEST_F(SurfaceSavedFrameTest, OnlyRootSnapshotNoSharedPass) {
+ auto frame = CompositorFrameBuilder()
+ .AddDefaultRenderPass()
+ .AddDefaultRenderPass()
+ .Build();
+ support_->SubmitCompositorFrame(surface_id_.local_surface_id(),
+ std::move(frame));
+
+ const uint32_t sequence_id = 2u;
+ CompositorFrameTransitionDirective directive(
+ sequence_id, CompositorFrameTransitionDirective::Type::kSave,
+ CompositorFrameTransitionDirective::Effect::kCoverDown,
+ /*shared_render_pass_ids=*/{});
+ auto saved_frame = CreateSavedFrame(directive);
+ saved_frame->RequestCopyOfOutput(GetSurface());
+ EXPECT_FALSE(GetSurface()->HasInterpolatedFrame());
+
+ CancelAllCopyRequests();
+ EXPECT_EQ(last_complete_id_, sequence_id);
+ EXPECT_FALSE(GetSurface()->HasInterpolatedFrame());
+}
+
+// No interpolated frame if there are no shared elements with valid render pass.
+TEST_F(SurfaceSavedFrameTest, OnlyRootSnapshotNullSharedPass) {
+ auto frame = CompositorFrameBuilder()
+ .AddDefaultRenderPass()
+ .AddDefaultRenderPass()
+ .Build();
+ support_->SubmitCompositorFrame(surface_id_.local_surface_id(),
+ std::move(frame));
+
+ const uint32_t sequence_id = 2u;
+ CompositorFrameTransitionDirective directive(
+ sequence_id, CompositorFrameTransitionDirective::Type::kSave,
+ CompositorFrameTransitionDirective::Effect::kCoverDown,
+ /*shared_render_pass_ids=*/{CompositorRenderPassId(0u)});
+ auto saved_frame = CreateSavedFrame(directive);
+ saved_frame->RequestCopyOfOutput(GetSurface());
+ EXPECT_FALSE(GetSurface()->HasInterpolatedFrame());
+
+ CancelAllCopyRequests();
+ EXPECT_EQ(last_complete_id_, sequence_id);
+ EXPECT_FALSE(GetSurface()->HasInterpolatedFrame());
+}
+
+// Remove only shared element quads from the root pass and add a copy pass.
+// RP0 [] -> RP1[SolidColor, RP0]
+// Shared elements : [RP0]
+TEST_F(SurfaceSavedFrameTest, RemoveSharedElementQuadOnly) {
+ auto frame = CompositorFrameBuilder()
+ .AddDefaultRenderPass()
+ .AddDefaultRenderPass()
+ .AddDefaultRenderPass()
+ .Build();
+ auto* original_root_pass = frame.render_pass_list.back().get();
+ const auto shared_pass_id = frame.render_pass_list.at(0)->id;
+ const auto non_shared_pass_id = frame.render_pass_list.at(1)->id;
+ AddSharedQuadState(*original_root_pass);
+
+ auto* shared_pass_quad = AddRenderPassDrawQuad(*original_root_pass);
+ shared_pass_quad->render_pass_id = shared_pass_id;
+
+ AddSolidColorDrawQuad(*original_root_pass);
+
+ auto* non_shared_pass_quad = AddRenderPassDrawQuad(*original_root_pass);
+ non_shared_pass_quad->render_pass_id = non_shared_pass_id;
+
+ support_->SubmitCompositorFrame(surface_id_.local_surface_id(),
+ std::move(frame));
+
+ const uint32_t sequence_id = 2u;
+ CompositorFrameTransitionDirective directive(
+ sequence_id, CompositorFrameTransitionDirective::Type::kSave,
+ CompositorFrameTransitionDirective::Effect::kCoverDown,
+ /*shared_render_pass_ids=*/{shared_pass_id});
+ auto saved_frame = CreateSavedFrame(directive);
+ saved_frame->RequestCopyOfOutput(GetSurface());
+ EXPECT_TRUE(GetSurface()->HasInterpolatedFrame());
+
+ const auto& interpolated_frame = GetSurface()->GetActiveOrInterpolatedFrame();
+ const auto& render_passes = interpolated_frame.render_pass_list;
+
+ // 3 passes from the original frame and another pass to copy the root render
+ // pass.
+ ASSERT_EQ(render_passes.size(), 4u);
+
+ // The first pass is the original shared element.
+ EXPECT_EQ(render_passes[0]->id, shared_pass_id);
+ EXPECT_EQ(render_passes[0]->copy_requests.size(), 1u);
+ EXPECT_EQ(render_passes[0]->quad_list.size(), 0u);
+
+ // The second pass is the non-shared element pass.
+ EXPECT_EQ(render_passes[1]->id, non_shared_pass_id);
+ EXPECT_EQ(render_passes[1]->copy_requests.size(), 0u);
+ EXPECT_EQ(render_passes[1]->quad_list.size(), 0u);
+
+ // The third pass is the clean root pass for copy.
+ EXPECT_NE(render_passes[2]->id, original_root_pass->id);
+ EXPECT_NE(render_passes[2]->id, shared_pass_id);
+ EXPECT_EQ(render_passes[2]->quad_list.size(), 2u);
+ EXPECT_EQ(render_passes[2]->quad_list.ElementAt(0)->material,
+ DrawQuad::Material::kSolidColor);
+ const auto* copied_non_shared_quad =
+ CompositorRenderPassDrawQuad::MaterialCast(
+ render_passes[2]->quad_list.ElementAt(1));
+ EXPECT_EQ(copied_non_shared_quad->render_pass_id, non_shared_pass_id);
+ EXPECT_EQ(render_passes[2]->copy_requests.size(), 1u);
+
+ // The last pass is the original root pass.
+ EXPECT_EQ(render_passes[3]->id, original_root_pass->id);
+ EXPECT_EQ(render_passes[3]->quad_list.size(), 3u);
+ EXPECT_EQ(render_passes[3]->copy_requests.size(), 0u);
+
+ CancelAllCopyRequests();
+ EXPECT_EQ(last_complete_id_, sequence_id);
+ EXPECT_FALSE(GetSurface()->HasInterpolatedFrame());
+}
+
+// Removed shared element and tainted quads.
+// RP0 [] -> RP1 [RP0] -> RP2 [RP1]
+// Shared elements : [RP0]
+TEST_F(SurfaceSavedFrameTest, SharedElementNestedInNonSharedElementPass) {
+ auto frame = CompositorFrameBuilder()
+ .AddDefaultRenderPass()
+ .AddDefaultRenderPass()
+ .AddDefaultRenderPass()
+ .Build();
+
+ const auto shared_pass_id = frame.render_pass_list.at(0)->id;
+ auto* parent_pass = frame.render_pass_list.at(1).get();
+ AddSharedQuadState(*parent_pass);
+ auto* parent_pass_quad = AddRenderPassDrawQuad(*parent_pass);
+ parent_pass_quad->render_pass_id = shared_pass_id;
+
+ auto* original_root_pass = frame.render_pass_list.back().get();
+ AddSharedQuadState(*original_root_pass);
+ auto* root_shared_pass_quad = AddRenderPassDrawQuad(*original_root_pass);
+ root_shared_pass_quad->render_pass_id = parent_pass->id;
+
+ support_->SubmitCompositorFrame(surface_id_.local_surface_id(),
+ std::move(frame));
+
+ const uint32_t sequence_id = 2u;
+ CompositorFrameTransitionDirective directive(
+ sequence_id, CompositorFrameTransitionDirective::Type::kSave,
+ CompositorFrameTransitionDirective::Effect::kCoverDown,
+ /*shared_render_pass_ids=*/
+ {shared_pass_id});
+ auto saved_frame = CreateSavedFrame(directive);
+ saved_frame->RequestCopyOfOutput(GetSurface());
+ EXPECT_TRUE(GetSurface()->HasInterpolatedFrame());
+
+ const auto& interpolated_frame = GetSurface()->GetActiveOrInterpolatedFrame();
+ const auto& render_passes = interpolated_frame.render_pass_list;
+
+ // 3 passes from the original frame and 2 clean passes, one for the render
+ // pass embedding the shared element and 1 additional pass for the root.
+ ASSERT_EQ(render_passes.size(), 5u);
+
+ // The first pass is the shared element.
+ EXPECT_EQ(render_passes[0]->id, shared_pass_id);
+ EXPECT_EQ(render_passes[0]->quad_list.size(), 0u);
+ EXPECT_EQ(render_passes[0]->copy_requests.size(), 1u);
+
+ // The second pass is the clean pass for render pass including shared element.
+ EXPECT_NE(render_passes[1]->id, original_root_pass->id);
+ EXPECT_NE(render_passes[1]->id, parent_pass->id);
+ EXPECT_NE(render_passes[1]->id, shared_pass_id);
+ EXPECT_EQ(render_passes[1]->quad_list.size(), 0u);
+ EXPECT_EQ(render_passes[1]->copy_requests.size(), 0u);
+
+ // The third pass is the original pass for render pass including shared
+ // element.
+ EXPECT_EQ(render_passes[2]->id, parent_pass->id);
+ EXPECT_EQ(render_passes[2]->quad_list.size(), 1u);
+ EXPECT_EQ(render_passes[2]->copy_requests.size(), 0u);
+
+ // The fourth pass is the clean root pass for copy.
+ EXPECT_NE(render_passes[3]->id, original_root_pass->id);
+ EXPECT_NE(render_passes[3]->id, parent_pass->id);
+ EXPECT_NE(render_passes[3]->id, shared_pass_id);
+ EXPECT_EQ(render_passes[3]->quad_list.size(), 1u);
+ EXPECT_EQ(CompositorRenderPassDrawQuad::MaterialCast(
+ render_passes[3]->quad_list.front())
+ ->render_pass_id,
+ render_passes[1]->id);
+ EXPECT_EQ(render_passes[3]->copy_requests.size(), 1u);
+
+ // The last pass is the original root pass.
+ EXPECT_EQ(render_passes[4]->id, original_root_pass->id);
+ EXPECT_EQ(render_passes[4]->quad_list.size(), 1u);
+ EXPECT_EQ(render_passes[4]->copy_requests.size(), 0u);
+
+ CancelAllCopyRequests();
+ EXPECT_EQ(last_complete_id_, sequence_id);
+ EXPECT_FALSE(GetSurface()->HasInterpolatedFrame());
+}
+
+// Add multiple render passes for shared elements nested inside each other.
+// RP0 [] -> RP1 [RP0] -> RP2 [RP1]
+// Shared elements : [RP0, RP1]
+TEST_F(SurfaceSavedFrameTest, SharedElementNestedInSharedElementPass) {
+ auto frame = CompositorFrameBuilder()
+ .AddDefaultRenderPass()
+ .AddDefaultRenderPass()
+ .AddDefaultRenderPass()
+ .Build();
+
+ const auto child_shared_pass_id = frame.render_pass_list.at(0)->id;
+ auto* parent_shared_pass = frame.render_pass_list.at(1).get();
+ AddSharedQuadState(*parent_shared_pass);
+ auto* parent_shared_pass_quad = AddRenderPassDrawQuad(*parent_shared_pass);
+ parent_shared_pass_quad->render_pass_id = child_shared_pass_id;
+
+ auto* original_root_pass = frame.render_pass_list.back().get();
+ AddSharedQuadState(*original_root_pass);
+ auto* root_shared_pass_quad = AddRenderPassDrawQuad(*original_root_pass);
+ root_shared_pass_quad->render_pass_id = parent_shared_pass->id;
+
+ support_->SubmitCompositorFrame(surface_id_.local_surface_id(),
+ std::move(frame));
+
+ const uint32_t sequence_id = 2u;
+ CompositorFrameTransitionDirective directive(
+ sequence_id, CompositorFrameTransitionDirective::Type::kSave,
+ CompositorFrameTransitionDirective::Effect::kCoverDown,
+ /*shared_render_pass_ids=*/
+ {child_shared_pass_id, parent_shared_pass->id});
+ auto saved_frame = CreateSavedFrame(directive);
+ saved_frame->RequestCopyOfOutput(GetSurface());
+ EXPECT_TRUE(GetSurface()->HasInterpolatedFrame());
+
+ const auto& interpolated_frame = GetSurface()->GetActiveOrInterpolatedFrame();
+ const auto& render_passes = interpolated_frame.render_pass_list;
+
+ // 3 passes from the original frame and 2 additional passes to copy the parent
+ // shared element and root pass.
+ ASSERT_EQ(render_passes.size(), 5u);
+
+ // The first pass is the child shared element.
+ EXPECT_EQ(render_passes[0]->id, child_shared_pass_id);
+ EXPECT_EQ(render_passes[0]->quad_list.size(), 0u);
+ EXPECT_EQ(render_passes[0]->copy_requests.size(), 1u);
+
+ // The second pass is the clean pass for parent shared element.
+ EXPECT_NE(render_passes[1]->id, original_root_pass->id);
+ EXPECT_NE(render_passes[1]->id, parent_shared_pass->id);
+ EXPECT_NE(render_passes[1]->id, child_shared_pass_id);
+ EXPECT_EQ(render_passes[1]->quad_list.size(), 0u);
+ EXPECT_EQ(render_passes[1]->copy_requests.size(), 1u);
+
+ // The third pass is the original pass for parent shared element.
+ EXPECT_EQ(render_passes[2]->id, parent_shared_pass->id);
+ EXPECT_EQ(render_passes[2]->quad_list.size(), 1u);
+ EXPECT_EQ(render_passes[2]->copy_requests.size(), 0u);
+
+ // The fourth pass is the clean root pass for copy.
+ EXPECT_NE(render_passes[3]->id, original_root_pass->id);
+ EXPECT_NE(render_passes[3]->id, parent_shared_pass->id);
+ EXPECT_NE(render_passes[3]->id, child_shared_pass_id);
+ EXPECT_EQ(render_passes[3]->quad_list.size(), 0u);
+ EXPECT_EQ(render_passes[3]->copy_requests.size(), 1u);
+
+ // The last pass is the original root pass.
+ EXPECT_EQ(render_passes[4]->id, original_root_pass->id);
+ EXPECT_EQ(render_passes[4]->quad_list.size(), 1u);
+ EXPECT_EQ(render_passes[4]->copy_requests.size(), 0u);
+
+ CancelAllCopyRequests();
+ EXPECT_EQ(last_complete_id_, sequence_id);
+ EXPECT_FALSE(GetSurface()->HasInterpolatedFrame());
+}
+
+} // namespace
+} // namespace viz
diff --git a/chromium/components/viz/service/transitions/DEPS b/chromium/components/viz/service/transitions/DEPS
index dab1d85af51..50093217afa 100644
--- a/chromium/components/viz/service/transitions/DEPS
+++ b/chromium/components/viz/service/transitions/DEPS
@@ -1,6 +1,13 @@
# Please consult components/viz/README.md about allowable dependencies.
include_rules = [
+ "+components/viz/service/display/shared_bitmap_manager.h",
"+components/viz/service/surfaces",
"+gpu/command_buffer/common",
]
+
+specific_include_rules = {
+ ".*_unittest\.cc": [
+ "+components/viz/service/display_embedder",
+ ],
+}
diff --git a/chromium/components/viz/service/transitions/surface_animation_manager.cc b/chromium/components/viz/service/transitions/surface_animation_manager.cc
index e0298c7a015..40cec5659f4 100644
--- a/chromium/components/viz/service/transitions/surface_animation_manager.cc
+++ b/chromium/components/viz/service/transitions/surface_animation_manager.cc
@@ -5,29 +5,50 @@
#include "components/viz/service/transitions/surface_animation_manager.h"
#include <algorithm>
+#include <memory>
#include <utility>
#include <vector>
+#include "base/bind.h"
+#include "base/check_op.h"
+#include "base/containers/flat_map.h"
#include "base/time/time.h"
+#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/compositor_render_pass.h"
#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/resources/transferable_resource.h"
+#include "components/viz/common/transition_utils.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_saved_frame_storage.h"
+#include "third_party/skia/include/core/SkBlendMode.h"
+#include "ui/gfx/animation/keyframe/animation_curve.h"
#include "ui/gfx/animation/keyframe/keyframed_animation_curve.h"
#include "ui/gfx/animation/keyframe/timing_function.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/gfx/transform.h"
+#include "ui/gfx/transform_operations.h"
namespace viz {
namespace {
-CompositorRenderPassId NextRenderPassId(const CompositorRenderPassId& id) {
- return CompositorRenderPassId(id.GetUnsafeValue() + 1);
-}
+constexpr int kAnimationSlowDownFactor = 1;
constexpr base::TimeDelta kDefaultAnimationDuration =
- base::TimeDelta::FromMilliseconds(300);
+ base::TimeDelta::FromMilliseconds(250) * kAnimationSlowDownFactor;
+
+constexpr base::TimeDelta kSharedOpacityAnimationDuration =
+ base::TimeDelta::FromMilliseconds(60) * kAnimationSlowDownFactor;
+
+constexpr base::TimeDelta kSharedOpacityAnimationDelay =
+ base::TimeDelta::FromMilliseconds(60) * kAnimationSlowDownFactor;
// Scale the overall duration to produce the opacity duration. Opacity
// transitions which reveal an element (i.e., transition opacity from 0 -> 1)
@@ -49,7 +70,9 @@ constexpr float kScaleProportion = 1.1f;
void CreateAndAppendSrcTextureQuad(CompositorRenderPass* render_pass,
const gfx::Rect& output_rect,
const gfx::Transform& src_transform,
+ SkBlendMode blend_mode,
float src_opacity,
+ bool y_flipped,
ResourceId id) {
auto* src_quad_state = render_pass->CreateAndAppendSharedQuadState();
src_quad_state->SetAll(
@@ -57,10 +80,9 @@ void CreateAndAppendSrcTextureQuad(CompositorRenderPass* render_pass,
/*quad_layer_rect=*/output_rect,
/*visible_layer_rect=*/output_rect,
/*mask_filter_info=*/gfx::MaskFilterInfo(),
- /*clip_rect=*/gfx::Rect(),
- /*is_clipped=*/false, /*are_contents_opaque=*/false,
+ /*clip_rect=*/absl::nullopt, /*are_contents_opaque=*/false,
/*opacity=*/src_opacity,
- /*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
+ /*blend_mode=*/blend_mode, /*sorting_context_id=*/0);
auto* src_quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
float vertex_opacity[] = {1.f, 1.f, 1.f, 1.f};
@@ -73,17 +95,111 @@ void CreateAndAppendSrcTextureQuad(CompositorRenderPass* render_pass,
/*premultiplied_alpha=*/true,
/*uv_top_left=*/gfx::PointF(0, 0),
/*uv_bottom_right=*/gfx::PointF(1, 1),
- /*background_color=*/SK_ColorWHITE,
- /*vertex_opacity=*/vertex_opacity,
- /*y_flipped=*/true,
+ /*background_color=*/SK_ColorTRANSPARENT,
+ /*vertex_opacity=*/vertex_opacity, y_flipped,
/*nearest_neighbor=*/true,
/*secure_output_only=*/false,
/*protected_video_type=*/gfx::ProtectedVideoType::kClear);
}
+void CreateAndAppendSharedRenderPassDrawQuad(
+ CompositorRenderPass* render_pass,
+ const gfx::Rect& rect,
+ gfx::Transform transform,
+ float opacity,
+ CompositorRenderPassId render_pass_id,
+ SkBlendMode blend_mode,
+ const CompositorRenderPassDrawQuad& sample_quad) {
+ auto* quad_state = render_pass->CreateAndAppendSharedQuadState();
+ quad_state->SetAll(
+ /*quad_to_target_transform=*/transform,
+ /*quad_layer_rect=*/rect,
+ /*visible_layer_rect=*/rect,
+ /*mask_filter_info=*/gfx::MaskFilterInfo(),
+ /*clip_rect=*/absl::nullopt,
+ /*are_contents_opaque=*/false,
+ /*opacity=*/opacity,
+ /*blend_mode=*/blend_mode, /*sorting_context_id=*/0);
+
+ auto* quad =
+ render_pass->CreateAndAppendDrawQuad<CompositorRenderPassDrawQuad>();
+ quad->SetNew(
+ /*shared_quad_state=*/quad_state,
+ /*rect=*/rect,
+ /*visible_rect=*/rect,
+ /*render_pass_id=*/render_pass_id,
+ /*mask_resource_id=*/sample_quad.mask_resource_id(),
+ /*mask_uv_rect=*/sample_quad.mask_uv_rect,
+ /*mask_texture_size=*/sample_quad.mask_texture_size,
+ /*filters_scale=*/sample_quad.filters_scale,
+ /*filters_origin=*/sample_quad.filters_origin,
+ /*tex_coord_rect=*/sample_quad.tex_coord_rect,
+ /*force_anti_aliasing_off=*/sample_quad.force_anti_aliasing_off,
+ /*backdrop_filter_quality*/ sample_quad.backdrop_filter_quality);
+}
+
+std::unique_ptr<gfx::AnimationCurve> CreateOpacityCurve(
+ float start_opacity,
+ float end_opacity,
+ gfx::FloatAnimationCurve::Target* target) {
+ auto float_curve = gfx::KeyframedFloatAnimationCurve::Create();
+
+ // The curve starts at opacity delay and runs for opacity animation, so it
+ // potentially has 4 points:
+ // time 0 == start opacity
+ // time 'delay' == start opacity
+ // time 'delay' + 'duration' == end opacity
+ // time end of animation == end opacity
+ float_curve->AddKeyframe(
+ gfx::FloatKeyframe::Create(base::TimeDelta(), start_opacity, nullptr));
+ if (!kSharedOpacityAnimationDelay.is_zero()) {
+ float_curve->AddKeyframe(gfx::FloatKeyframe::Create(
+ kSharedOpacityAnimationDelay, start_opacity, nullptr));
+ }
+ float_curve->AddKeyframe(gfx::FloatKeyframe::Create(
+ kSharedOpacityAnimationDuration + kSharedOpacityAnimationDelay,
+ end_opacity, nullptr));
+ float_curve->AddKeyframe(gfx::FloatKeyframe::Create(kDefaultAnimationDuration,
+ end_opacity, nullptr));
+ float_curve->set_target(target);
+ return float_curve;
+}
+
+std::unique_ptr<gfx::AnimationCurve> CreateSizeCurve(
+ const gfx::SizeF& start_size,
+ std::unique_ptr<gfx::TimingFunction> timing_function,
+ gfx::SizeAnimationCurve::Target* target) {
+ auto size_curve = gfx::KeyframedSizeAnimationCurve::Create();
+ size_curve->AddKeyframe(gfx::SizeKeyframe::Create(
+ base::TimeDelta(), start_size, timing_function->Clone()));
+ size_curve->AddKeyframe(gfx::SizeKeyframe::Create(
+ kDefaultAnimationDuration, start_size, std::move(timing_function)));
+ size_curve->set_target(target);
+ return size_curve;
+}
+
+std::unique_ptr<gfx::AnimationCurve> CreateTransformCurve(
+ const gfx::Transform& transform,
+ std::unique_ptr<gfx::TimingFunction> timing_function,
+ gfx::TransformAnimationCurve::Target* target) {
+ gfx::TransformOperations transform_ops;
+ transform_ops.AppendMatrix(transform);
+
+ auto transform_curve = gfx::KeyframedTransformAnimationCurve::Create();
+ transform_curve->AddKeyframe(gfx::TransformKeyframe::Create(
+ base::TimeDelta(), transform_ops, timing_function->Clone()));
+ transform_curve->AddKeyframe(gfx::TransformKeyframe::Create(
+ kDefaultAnimationDuration, transform_ops, std::move(timing_function)));
+ transform_curve->set_target(target);
+ return transform_curve;
+}
+
} // namespace
-SurfaceAnimationManager::SurfaceAnimationManager() = default;
+SurfaceAnimationManager::SurfaceAnimationManager(
+ SharedBitmapManager* shared_bitmap_manager)
+ : transferable_resource_tracker_(shared_bitmap_manager) {}
+
SurfaceAnimationManager::~SurfaceAnimationManager() = default;
void SurfaceAnimationManager::SetDirectiveFinishedCallback(
@@ -159,7 +275,9 @@ bool SurfaceAnimationManager::ProcessAnimateDirective(
saved_textures_.emplace(
transferable_resource_tracker_.ImportResources(std::move(saved_frame)));
- UpdateAnimationCurves(saved_textures_->root.rect.size());
+ CreateRootAnimationCurves(saved_textures_->root.draw_data.size);
+ CreateSharedElementCurves();
+ TickAnimations(latest_time_);
state_ = State::kAnimating;
return true;
}
@@ -167,11 +285,17 @@ bool SurfaceAnimationManager::ProcessAnimateDirective(
bool SurfaceAnimationManager::NeedsBeginFrame() const {
// If we're animating we need to keep pumping frames to advance the animation.
// If we're done, we require one more frame to switch back to idle state.
- return animator_.IsAnimating() || state_ == State::kLastFrame;
+ return root_animation_.driver().IsAnimating() || state_ == State::kLastFrame;
+}
+
+void SurfaceAnimationManager::TickAnimations(base::TimeTicks new_time) {
+ root_animation_.driver().Tick(new_time);
+ for (auto& shared : shared_animations_)
+ shared.driver().Tick(new_time);
}
-void SurfaceAnimationManager::NotifyFrameAdvanced(base::TimeTicks new_time) {
- animator_.Tick(new_time);
+void SurfaceAnimationManager::NotifyFrameAdvanced() {
+ TickAnimations(latest_time_);
switch (state_) {
case State::kIdle:
@@ -191,7 +315,7 @@ void SurfaceAnimationManager::FinishAnimationIfNeeded() {
DCHECK(saved_textures_.has_value());
DCHECK(save_directive_.has_value());
DCHECK(animate_directive_.has_value());
- if (!animator_.IsAnimating()) {
+ if (!root_animation_.driver().IsAnimating()) {
state_ = State::kLastFrame;
sequence_id_finished_callback_.Run(animate_directive_->sequence_id());
}
@@ -224,25 +348,12 @@ void SurfaceAnimationManager::InterpolateFrame(Surface* surface) {
interpolated_frame.metadata = active_frame.metadata.Clone();
interpolated_frame.resource_list = active_frame.resource_list;
interpolated_frame.resource_list.push_back(saved_textures_->root.resource);
- CompositorRenderPassId max_id = CompositorRenderPassId(0);
- for (auto& render_pass : active_frame.render_pass_list) {
- if (render_pass->id > max_id)
- max_id = render_pass->id;
- // TODO(vmpstr): If we are doing an interpolation, we fail requested copy
- // requests, since we can't copy them into an interpolated frame below. The
- // todo is to change DeepCopy into a function that copies everything and
- // moves copy output requests, since we can satisfy the requests on the
- // interpolated frame.
- render_pass->copy_requests.clear();
- interpolated_frame.render_pass_list.emplace_back(render_pass->DeepCopy());
- }
- gfx::Rect output_rect =
- interpolated_frame.render_pass_list.back()->output_rect;
+ gfx::Rect output_rect = active_frame.render_pass_list.back()->output_rect;
+ auto animation_pass = CreateAnimationCompositorRenderPass(output_rect);
- auto animation_pass = CompositorRenderPass::Create(2, 2);
- animation_pass->SetNew(NextRenderPassId(max_id), output_rect, output_rect,
- gfx::Transform());
+ CopyAndInterpolateSharedElements(active_frame.render_pass_list,
+ animation_pass.get(), &interpolated_frame);
bool src_on_top = false;
switch (save_directive_->effect()) {
@@ -258,12 +369,16 @@ void SurfaceAnimationManager::InterpolateFrame(Surface* surface) {
break;
}
- gfx::Transform src_transform = src_transform_.Apply();
- gfx::Transform dst_transform = dst_transform_.Apply();
+ gfx::Transform src_transform = root_animation_.src_transform().Apply();
+ gfx::Transform dst_transform = root_animation_.dst_transform().Apply();
+
+ // GPU textures are flipped but software bitmaps are not.
+ bool y_flipped = !saved_textures_->root.resource.is_software;
if (src_on_top) {
CreateAndAppendSrcTextureQuad(animation_pass.get(), output_rect,
- src_transform, src_opacity_,
+ src_transform, SkBlendMode::kSrcOver,
+ root_animation_.src_opacity(), y_flipped,
saved_textures_->root.resource.id);
}
@@ -273,10 +388,9 @@ void SurfaceAnimationManager::InterpolateFrame(Surface* surface) {
/*quad_layer_rect=*/output_rect,
/*visible_layer_rect=*/output_rect,
/*mask_filter_info=*/gfx::MaskFilterInfo(),
- /*clip_rect=*/gfx::Rect(),
- /*is_clipped=*/false,
+ /*clip_rect=*/absl::nullopt,
/*are_contents_opaque=*/false,
- /*opacity=*/dst_opacity_,
+ /*opacity=*/root_animation_.dst_opacity(),
/*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
auto* dst_quad =
@@ -285,7 +399,7 @@ void SurfaceAnimationManager::InterpolateFrame(Surface* surface) {
/*shared_quad_state=*/dst_quad_state,
/*rect=*/output_rect,
/*visible_rect=*/output_rect,
- /*render_pass_id=*/interpolated_frame.render_pass_list.back()->id,
+ /*render_pass_id=*/active_frame.render_pass_list.back()->id,
/*mask_resource_id=*/kInvalidResourceId,
/*mask_uv_rect=*/gfx::RectF(),
/*mask_texture_size=*/gfx::Size(),
@@ -297,7 +411,8 @@ void SurfaceAnimationManager::InterpolateFrame(Surface* surface) {
if (!src_on_top) {
CreateAndAppendSrcTextureQuad(animation_pass.get(), output_rect,
- src_transform, src_opacity_,
+ src_transform, SkBlendMode::kSrcOver,
+ root_animation_.src_opacity(), y_flipped,
saved_textures_->root.resource.id);
}
@@ -305,6 +420,293 @@ void SurfaceAnimationManager::InterpolateFrame(Surface* surface) {
surface->SetInterpolatedFrame(std::move(interpolated_frame));
}
+std::unique_ptr<CompositorRenderPass>
+SurfaceAnimationManager::CreateAnimationCompositorRenderPass(
+ const gfx::Rect& output_rect) const {
+ // One quad for the root render pass, and expect that each shared texture is
+ // non-nullopt. Then we double it: 1 for the source frame, one for the
+ // destination frame.
+ size_t quad_size_limit = 2 * (1 + saved_textures_->shared.size());
+ // Reserve the same number of shared quad states as there are quads, since we
+ // expect each quad to have a separate shared quad state.
+ auto animation_pass =
+ CompositorRenderPass::Create(quad_size_limit, quad_size_limit);
+
+ // We create an animation pass before copying the existing frame, since we'll
+ // do a smart copy -- interpolating shared elements as we encounter them
+ // during the copy. As a result, we use id 1 here, since we don't know what is
+ // the maximum id yet, we'll update it after we do the copy.
+ animation_pass->SetNew(CompositorRenderPassId(1), output_rect, output_rect,
+ gfx::Transform());
+ return animation_pass;
+}
+
+void SurfaceAnimationManager::CopyAndInterpolateSharedElements(
+ const std::vector<std::unique_ptr<CompositorRenderPass>>& source_passes,
+ CompositorRenderPass* animation_pass,
+ CompositorFrame* interpolated_frame) {
+ // First create a placeholder for the shared render passes. We need this to
+ // quickly check whether a compositor render pass is shared (i.e. do we need
+ // to do something special for this).
+ base::flat_map<CompositorRenderPassId, RenderPassDrawData> shared_draw_data;
+ for (const CompositorRenderPassId& shared_render_pass_id :
+ animate_directive_->shared_render_pass_ids()) {
+ shared_draw_data.emplace(shared_render_pass_id, RenderPassDrawData());
+ }
+
+ // Now run through all the source passes, making a 'smart' copy and filtering
+ // based on whether the pass is a shared element or not. After this loop, we
+ // should have populated `shared_render_passes` with the shared passes, and
+ // `animation_draw_quads` with draw quads for those render passes. All other
+ // passes would have been copied and added into the interpolated frame.
+ CompositorRenderPassId max_id = CompositorRenderPassId(0);
+ TransitionUtils::FilterCallback filter_callback = base::BindRepeating(
+ &FilterSharedElementQuads, base::Unretained(&shared_draw_data));
+ for (auto& render_pass : source_passes) {
+ // First, clear the copy requests.
+ // TODO(vmpstr): Can we preserve these in some situations?
+ render_pass->copy_requests.clear();
+
+ // Get the max_id for any render pass, since we'll need to create new passes
+ // with ids that don't conflict with existing passes.
+ if (render_pass->id > max_id)
+ max_id = render_pass->id;
+
+ // Now do the pass copy, filtering shared element quads into
+ // `shared_draw_data` instead of the render pass.
+ auto pass_copy = TransitionUtils::CopyPassWithRenderPassFiltering(
+ *render_pass, filter_callback);
+
+ // If this is a shared pass, store it in `shared_draw_data`. Otherwise,
+ // put it directly into the interpolated frame since we don't need to do
+ // anything special with it.
+ auto shared_it = shared_draw_data.find(pass_copy->id);
+ if (shared_it != shared_draw_data.end()) {
+ RenderPassDrawData& data = shared_it->second;
+ data.render_pass = std::move(pass_copy);
+ data.opacity = TransitionUtils::ComputeAccumulatedOpacity(
+ source_passes, data.render_pass->id);
+ } else {
+ interpolated_frame->render_pass_list.emplace_back(std::move(pass_copy));
+ }
+ }
+
+ // Update the animation pass id to avoid conflicts.
+ max_id = animation_pass->id = TransitionUtils::NextRenderPassId(max_id);
+
+ const std::vector<CompositorRenderPassId>& shared_render_pass_ids =
+ animate_directive_->shared_render_pass_ids();
+ for (size_t i = 0; i < shared_render_pass_ids.size(); ++i) {
+ const CompositorRenderPassId& shared_pass_id = shared_render_pass_ids[i];
+ SharedAnimationState& animation = shared_animations_[i];
+ auto& draw_data = shared_draw_data[shared_pass_id];
+ const absl::optional<TransferableResourceTracker::PositionedResource>&
+ src_texture = saved_textures_->shared[i];
+
+ const bool has_destination_pass =
+ draw_data.render_pass && draw_data.draw_quad;
+ const bool should_have_destination_pass = !shared_pass_id.is_null();
+ DCHECK(!has_destination_pass || should_have_destination_pass);
+
+ // We have to retarget the animations, whether or not we have a destination
+ // pass. Ideally we should only need an opacity curve (to fade out the src
+ // element) if the dest element is missing but we try to handle the dest
+ // element getting added or removed during the transition gracefully by
+ // pausing the animation to it's current state.
+ auto* opacity_model = animation.driver().GetKeyframeModel(
+ SharedAnimationState::kCombinedOpacity);
+ float target_opacity = 0.f;
+ if (has_destination_pass)
+ target_opacity = draw_data.opacity;
+ else if (should_have_destination_pass)
+ target_opacity = animation.combined_opacity();
+ opacity_model->Retarget(
+ latest_time_, SharedAnimationState::kCombinedOpacity, target_opacity);
+
+ auto* size_model =
+ animation.driver().GetKeyframeModel(SharedAnimationState::kContentSize);
+ gfx::SizeF target_size =
+ has_destination_pass
+ ? gfx::SizeF(draw_data.render_pass->output_rect.size())
+ : animation.content_size();
+ if (size_model) {
+ size_model->Retarget(latest_time_, SharedAnimationState::kContentSize,
+ target_size);
+ } else {
+ animation.OnSizeAnimated(target_size, SharedAnimationState::kContentSize,
+ nullptr);
+ }
+
+ auto* transform_model = animation.driver().GetKeyframeModel(
+ SharedAnimationState::kCombinedTransform);
+ gfx::TransformOperations target_transform_ops;
+ gfx::Transform end_transform(gfx::Transform::kSkipInitialization);
+ if (has_destination_pass) {
+ end_transform = draw_data.render_pass->transform_to_root_target;
+ // The mapping from dest pass origin to target buffer is done when drawing
+ // the dest pass to the intermediate transition pass (if used). So we
+ // exclude this translation from the transform here and add it when
+ // drawing the dest pass.
+ auto origin = draw_data.render_pass->output_rect.origin();
+ end_transform.Translate(origin.x(), origin.y());
+ } else {
+ end_transform = animation.combined_transform().Apply();
+ }
+ target_transform_ops.AppendMatrix(end_transform);
+
+ if (transform_model) {
+ transform_model->Retarget(latest_time_,
+ SharedAnimationState::kCombinedTransform,
+ target_transform_ops);
+ } else {
+ animation.OnTransformAnimated(target_transform_ops,
+ SharedAnimationState::kCombinedTransform,
+ nullptr);
+ }
+
+ // Now that we have updated the animations, we can append the interpolations
+ // to the animation pass.
+ const float content_opacity = animation.content_opacity();
+ const gfx::Size content_size = gfx::ToFlooredSize(animation.content_size());
+ const float combined_opacity = animation.combined_opacity();
+ const gfx::Transform combined_transform =
+ animation.combined_transform().Apply();
+
+ std::unique_ptr<CompositorRenderPass> transition_pass;
+ if (src_texture.has_value() && has_destination_pass) {
+ size_t num_of_quads = 2;
+ transition_pass =
+ CompositorRenderPass::Create(num_of_quads, num_of_quads);
+ gfx::Rect output_rect(content_size);
+ max_id = TransitionUtils::NextRenderPassId(max_id);
+ transition_pass->SetNew(max_id, output_rect, output_rect,
+ combined_transform);
+ }
+
+ // The quad list is in front to back order. So adding the src texture first
+ // makes it so it draws on top of the dest texture.
+ if (src_texture.has_value()) {
+ bool y_flipped = !src_texture->resource.is_software;
+ gfx::Transform src_transform;
+ src_transform.Scale(static_cast<float>(content_size.width()) /
+ src_texture->draw_data.size.width(),
+ static_cast<float>(content_size.height()) /
+ src_texture->draw_data.size.height());
+ float src_opacity = 1.f - content_opacity;
+
+ // Use kPlus mode to add the pixel values from src and destination
+ // textures. This ensures the blending pass is a no-op if the 2 have the
+ // same content.
+ SkBlendMode blend_mode = SkBlendMode::kPlus;
+
+ auto* pass_for_draw = transition_pass.get();
+ if (!pass_for_draw) {
+ pass_for_draw = animation_pass;
+ src_transform.ConcatTransform(combined_transform);
+ src_opacity *= combined_opacity;
+ blend_mode = SkBlendMode::kSrcOver;
+ }
+
+ CreateAndAppendSrcTextureQuad(
+ pass_for_draw, gfx::Rect(src_texture->draw_data.size), src_transform,
+ blend_mode, src_opacity, y_flipped, src_texture->resource.id);
+ interpolated_frame->resource_list.push_back(src_texture->resource);
+ }
+
+ if (!has_destination_pass)
+ continue;
+
+ // Now that we know we have a render pass destination, create a copy of the
+ // shared render pass, and update it with all the right values.
+ auto pass_copy = draw_data.render_pass->DeepCopy();
+ max_id = pass_copy->id = TransitionUtils::NextRenderPassId(max_id);
+ gfx::Vector2dF dest_scale(static_cast<float>(content_size.width()) /
+ pass_copy->output_rect.width(),
+ static_cast<float>(content_size.height()) /
+ pass_copy->output_rect.height());
+ gfx::Point dest_origin = pass_copy->output_rect.origin();
+ pass_copy->transform_to_root_target = combined_transform;
+ pass_copy->transform_to_root_target.Scale(dest_scale.x(), dest_scale.y());
+ pass_copy->transform_to_root_target.Translate(-dest_origin.x(),
+ -dest_origin.y());
+
+ auto* pass_for_draw = transition_pass.get();
+ gfx::Transform dest_transform;
+ dest_transform.Scale(dest_scale.x(), dest_scale.y());
+ dest_transform.Translate(-dest_origin.x(), -dest_origin.y());
+ float dest_opacity = content_opacity;
+
+ // Use kSrc mode to clear the intermediate texture used for blending with
+ // dest content.
+ SkBlendMode blend_mode = SkBlendMode::kSrc;
+ if (!pass_for_draw) {
+ pass_for_draw = animation_pass;
+ dest_transform.ConcatTransform(combined_transform);
+ dest_opacity *= combined_opacity;
+ blend_mode = SkBlendMode::kSrcOver;
+ }
+
+ CreateAndAppendSharedRenderPassDrawQuad(
+ pass_for_draw, draw_data.render_pass->output_rect, dest_transform,
+ dest_opacity, pass_copy->id, blend_mode, *draw_data.draw_quad);
+
+ // Finally, add the pass into the interpolated frame. Make sure this comes
+ // after CreateAndAppend* call, because we use a pass id, so we need to
+ // access the pass before moving it here.
+ interpolated_frame->render_pass_list.emplace_back(std::move(pass_copy));
+
+ if (transition_pass) {
+ auto* quad_state = animation_pass->CreateAndAppendSharedQuadState();
+ gfx::Rect rect(content_size);
+ quad_state->SetAll(
+ /*quad_to_target_transform=*/combined_transform,
+ /*quad_layer_rect=*/rect,
+ /*visible_layer_rect=*/rect,
+ /*mask_filter_info=*/gfx::MaskFilterInfo(),
+ /*clip_rect=*/absl::nullopt,
+ /*are_contents_opaque=*/false,
+ /*opacity=*/combined_opacity,
+ /*blend_mode=*/SkBlendMode::kSrcOver, /*sorting_context_id=*/0);
+
+ auto* quad =
+ animation_pass
+ ->CreateAndAppendDrawQuad<CompositorRenderPassDrawQuad>();
+ quad->SetNew(
+ /*shared_quad_state=*/quad_state,
+ /*rect=*/rect,
+ /*visible_rect=*/rect,
+ /*render_pass_id=*/transition_pass->id,
+ /*mask_resource_id=*/kInvalidResourceId,
+ /*mask_uv_rect=*/gfx::RectF(),
+ /*mask_texture_size=*/gfx::Size(),
+ /*filters_scale=*/gfx::Vector2dF(),
+ /*filters_origin=*/gfx::PointF(),
+ /*tex_coord_rect=*/gfx::RectF(rect),
+ /*force_anti_aliasing_off=*/
+ draw_data.draw_quad->force_anti_aliasing_off,
+ /*backdrop_filter_quality=*/0.f);
+
+ interpolated_frame->render_pass_list.emplace_back(
+ std::move(transition_pass));
+ }
+ }
+}
+// static
+bool SurfaceAnimationManager::FilterSharedElementQuads(
+ base::flat_map<CompositorRenderPassId, RenderPassDrawData>*
+ shared_draw_data,
+ const CompositorRenderPassDrawQuad& pass_quad,
+ CompositorRenderPass& copy_pass) {
+ auto shared_it = shared_draw_data->find(pass_quad.render_pass_id);
+ // If the quad is shared, then add it to the `shared_draw_data`.
+ // Otherwise, it will be added to the copy pass directly.
+ if (shared_it != shared_draw_data->end()) {
+ shared_it->second.draw_quad = pass_quad;
+ return true;
+ }
+ return false;
+}
+
void SurfaceAnimationManager::RefResources(
const std::vector<TransferableResource>& resources) {
if (transferable_resource_tracker_.is_empty())
@@ -321,32 +723,15 @@ void SurfaceAnimationManager::UnrefResources(
return;
for (const auto& resource : resources) {
if (resource.id >= kVizReservedRangeStartId)
- transferable_resource_tracker_.UnrefResource(resource.id);
- }
-}
-void SurfaceAnimationManager::OnFloatAnimated(
- const float& value,
- int target_property_id,
- gfx::KeyframeModel* keyframe_model) {
- if (target_property_id == kDstOpacity) {
- dst_opacity_ = value;
- } else {
- src_opacity_ = value;
+ transferable_resource_tracker_.UnrefResource(resource.id, resource.count);
}
}
-void SurfaceAnimationManager::OnTransformAnimated(
- const gfx::TransformOperations& operations,
- int target_property_id,
- gfx::KeyframeModel* keyframe_model) {
- if (target_property_id == kDstTransform) {
- dst_transform_ = operations;
- } else {
- src_transform_ = operations;
- }
+void SurfaceAnimationManager::UpdateFrameTime(base::TimeTicks now) {
+ latest_time_ = now;
}
-void SurfaceAnimationManager::UpdateAnimationCurves(
+void SurfaceAnimationManager::CreateRootAnimationCurves(
const gfx::Size& output_size) {
// A small translation. We want to roughly scale this with screen size, but
// we choose the minimum screen dimension to keep horizontal and vertical
@@ -356,11 +741,11 @@ void SurfaceAnimationManager::UpdateAnimationCurves(
gfx::TransformOperations start_transform;
gfx::TransformOperations end_transform;
- int transform_property_id = kDstTransform;
+ int transform_property_id = RootAnimationState::kDstTransform;
float start_opacity = 0.0f;
float end_opacity = 1.0f;
- int opacity_property_id = kDstOpacity;
+ int opacity_property_id = RootAnimationState::kDstOpacity;
DCHECK(save_directive_.has_value());
@@ -383,30 +768,30 @@ void SurfaceAnimationManager::UpdateAnimationCurves(
}
case CompositorFrameTransitionDirective::Effect::kRevealLeft: {
end_transform.AppendTranslate(-delta, 0.0f, 0.0f);
- transform_property_id = kSrcTransform;
+ transform_property_id = RootAnimationState::kSrcTransform;
std::swap(start_opacity, end_opacity);
- opacity_property_id = kSrcOpacity;
+ opacity_property_id = RootAnimationState::kSrcOpacity;
break;
}
case CompositorFrameTransitionDirective::Effect::kRevealRight: {
end_transform.AppendTranslate(delta, 0.0f, 0.0f);
- transform_property_id = kSrcTransform;
+ transform_property_id = RootAnimationState::kSrcTransform;
std::swap(start_opacity, end_opacity);
- opacity_property_id = kSrcOpacity;
+ opacity_property_id = RootAnimationState::kSrcOpacity;
break;
}
case CompositorFrameTransitionDirective::Effect::kRevealUp: {
end_transform.AppendTranslate(0.0f, -delta, 0.0f);
- transform_property_id = kSrcTransform;
+ transform_property_id = RootAnimationState::kSrcTransform;
std::swap(start_opacity, end_opacity);
- opacity_property_id = kSrcOpacity;
+ opacity_property_id = RootAnimationState::kSrcOpacity;
break;
}
case CompositorFrameTransitionDirective::Effect::kRevealDown: {
end_transform.AppendTranslate(0.0f, delta, 0.0f);
- transform_property_id = kSrcTransform;
+ transform_property_id = RootAnimationState::kSrcTransform;
std::swap(start_opacity, end_opacity);
- opacity_property_id = kSrcOpacity;
+ opacity_property_id = RootAnimationState::kSrcOpacity;
break;
}
case CompositorFrameTransitionDirective::Effect::kExplode: {
@@ -421,22 +806,22 @@ void SurfaceAnimationManager::UpdateAnimationCurves(
end_transform.AppendScale(kScaleProportion, kScaleProportion, 1.0f);
end_transform.AppendTranslate(-output_size.width() * 0.5f,
-output_size.height() * 0.5f, 0.0f);
- transform_property_id = kSrcTransform;
+ transform_property_id = RootAnimationState::kSrcTransform;
std::swap(start_opacity, end_opacity);
- opacity_property_id = kSrcOpacity;
+ opacity_property_id = RootAnimationState::kSrcOpacity;
break;
}
case CompositorFrameTransitionDirective::Effect::kFade: {
// Fade is effectively an explode with no scaling.
- transform_property_id = kSrcTransform;
+ transform_property_id = RootAnimationState::kSrcTransform;
std::swap(start_opacity, end_opacity);
- opacity_property_id = kSrcOpacity;
+ opacity_property_id = RootAnimationState::kSrcOpacity;
break;
}
case CompositorFrameTransitionDirective::Effect::kNone: {
- transform_property_id = kSrcTransform;
+ transform_property_id = RootAnimationState::kSrcTransform;
start_opacity = end_opacity = 0.0f;
- opacity_property_id = kSrcOpacity;
+ opacity_property_id = RootAnimationState::kSrcOpacity;
break;
}
case CompositorFrameTransitionDirective::Effect::kImplode: {
@@ -456,7 +841,7 @@ void SurfaceAnimationManager::UpdateAnimationCurves(
}
// Ensure we have no conflicting animation.
- animator_.RemoveAllKeyframeModels();
+ root_animation_.driver().RemoveAllKeyframeModels();
// We will use the ease in or ease out timing function (used by CSS
// transitions) depending on whether the the new content is being covered or
@@ -464,7 +849,7 @@ void SurfaceAnimationManager::UpdateAnimationCurves(
// but ease into position, eg.
std::unique_ptr<gfx::CubicBezierTimingFunction> timing_function =
gfx::CubicBezierTimingFunction::CreatePreset(
- opacity_property_id == kSrcOpacity
+ opacity_property_id == RootAnimationState::kSrcOpacity
? gfx::CubicBezierTimingFunction::EaseType::EASE_IN
: gfx::CubicBezierTimingFunction::EaseType::EASE_OUT);
@@ -477,8 +862,8 @@ void SurfaceAnimationManager::UpdateAnimationCurves(
base::TimeDelta(), start_transform, timing_function->Clone()));
transform_curve->AddKeyframe(gfx::TransformKeyframe::Create(
transform_duration, end_transform, timing_function->Clone()));
- transform_curve->set_target(this);
- animator_.AddKeyframeModel(gfx::KeyframeModel::Create(
+ transform_curve->set_target(&root_animation_);
+ root_animation_.driver().AddKeyframeModel(gfx::KeyframeModel::Create(
std::move(transform_curve), gfx::KeyframeEffect::GetNextKeyframeModelId(),
transform_property_id));
@@ -503,22 +888,164 @@ void SurfaceAnimationManager::UpdateAnimationCurves(
gfx::FloatKeyframe::Create(opacity_delay, start_opacity, nullptr));
float_curve->AddKeyframe(
gfx::FloatKeyframe::Create(opacity_duration, end_opacity, nullptr));
- float_curve->set_target(this);
- animator_.AddKeyframeModel(gfx::KeyframeModel::Create(
+ float_curve->set_target(&root_animation_);
+ root_animation_.driver().AddKeyframeModel(gfx::KeyframeModel::Create(
std::move(float_curve), gfx::KeyframeEffect::GetNextKeyframeModelId(),
opacity_property_id));
// We should now have animations queued up.
- DCHECK(animator_.IsAnimating());
+ DCHECK(root_animation_.driver().IsAnimating());
// To ensure we don't flicker at the beginning of the animation, ensure that
// our initial state is correct before we start ticking.
+ root_animation_.Reset();
+ root_animation_.OnTransformAnimated(start_transform, transform_property_id,
+ nullptr);
+ root_animation_.OnFloatAnimated(start_opacity, opacity_property_id, nullptr);
+}
+
+void SurfaceAnimationManager::CreateSharedElementCurves() {
+ DCHECK(animate_directive_.has_value());
+ // Clear and resize, to reset the shared animations state if any.
+ shared_animations_.clear();
+ shared_animations_.resize(
+ animate_directive_->shared_render_pass_ids().size());
+
+ // Since we don't have a target state yet, create animations as if all of the
+ // shared elements are targeted to stay in place with opacity going to 0.
+ for (size_t i = 0; i < saved_textures_->shared.size(); ++i) {
+ auto& shared = saved_textures_->shared[i];
+ auto& state = shared_animations_[i];
+ const bool has_src_element = shared.has_value();
+
+ // The kSrcOpacity curve animates the screen space opacity applied to the
+ // blended content from src and dest elements. The value goes from the
+ // src element's opacity value to dest element's opacity value.
+ // - If the src element is missing, the start opacity is 0 to allow the dest
+ // element to gradually fade in.
+ // - If the dest element is missing, the end opacity is 0 to allow the src
+ // element to gradually fade out.
+ // The animation is re-targeted once the dest element values are known.
+ float start_opacity = has_src_element ? shared->draw_data.opacity : 0.f;
+ auto opacity_curve = CreateOpacityCurve(start_opacity, 1.f, &state);
+ state.driver().AddKeyframeModel(gfx::KeyframeModel::Create(
+ std::move(opacity_curve), gfx::KeyframeEffect::GetNextKeyframeModelId(),
+ SharedAnimationState::kCombinedOpacity));
+
+ if (!has_src_element)
+ continue;
+
+ // The specific timing function is fine tuned for these effects.
+ auto ease_timing =
+ gfx::CubicBezierTimingFunction::Create(0.4, 0.0, 0.2, 1.0);
+
+ // Interpolation between the 2 textures involves an opacity animation (to
+ // cross-fade the content) and a scale animation to transition the content
+ // size.
+ auto content_size_curve = CreateSizeCurve(
+ gfx::SizeF(shared->draw_data.size), ease_timing->Clone(), &state);
+ state.driver().AddKeyframeModel(gfx::KeyframeModel::Create(
+ std::move(content_size_curve),
+ gfx::KeyframeEffect::GetNextKeyframeModelId(),
+ SharedAnimationState::kContentSize));
+ auto content_opacity_curve =
+ CreateOpacityCurve(/*start_opacity=*/0.f, /*end_opacity=*/1.f, &state);
+ state.driver().AddKeyframeModel(gfx::KeyframeModel::Create(
+ std::move(content_opacity_curve),
+ gfx::KeyframeEffect::GetNextKeyframeModelId(),
+ SharedAnimationState::kContentOpacity));
+
+ // The screen space transform for the interpolated texture is animated from
+ // src element to dest element value. The animation is re-targeted once the
+ // dest element values are known.
+ auto transform_curve = CreateTransformCurve(
+ shared->draw_data.target_transform, ease_timing->Clone(), &state);
+ state.driver().AddKeyframeModel(gfx::KeyframeModel::Create(
+ std::move(transform_curve),
+ gfx::KeyframeEffect::GetNextKeyframeModelId(),
+ SharedAnimationState::kCombinedTransform));
+ }
+}
+
+// RootAnimationState
+SurfaceAnimationManager::RootAnimationState::RootAnimationState() = default;
+SurfaceAnimationManager::RootAnimationState::RootAnimationState(
+ RootAnimationState&&) = default;
+SurfaceAnimationManager::RootAnimationState::~RootAnimationState() = default;
+
+void SurfaceAnimationManager::RootAnimationState::OnFloatAnimated(
+ const float& value,
+ int target_property_id,
+ gfx::KeyframeModel* keyframe_model) {
+ if (target_property_id == kDstOpacity) {
+ dst_opacity_ = value;
+ } else {
+ src_opacity_ = value;
+ }
+}
+
+void SurfaceAnimationManager::RootAnimationState::OnTransformAnimated(
+ const gfx::TransformOperations& operations,
+ int target_property_id,
+ gfx::KeyframeModel* keyframe_model) {
+ if (target_property_id == kDstTransform) {
+ dst_transform_ = operations;
+ } else {
+ src_transform_ = operations;
+ }
+}
+
+void SurfaceAnimationManager::RootAnimationState::Reset() {
src_opacity_ = 1.0f;
dst_opacity_ = 1.0f;
src_transform_ = gfx::TransformOperations();
dst_transform_ = gfx::TransformOperations();
- OnTransformAnimated(start_transform, transform_property_id, nullptr);
- OnFloatAnimated(start_opacity, opacity_property_id, nullptr);
}
+SurfaceAnimationManager::SharedAnimationState::SharedAnimationState() = default;
+SurfaceAnimationManager::SharedAnimationState::SharedAnimationState(
+ SharedAnimationState&&) = default;
+SurfaceAnimationManager::SharedAnimationState::~SharedAnimationState() =
+ default;
+
+void SurfaceAnimationManager::SharedAnimationState::OnFloatAnimated(
+ const float& value,
+ int target_property_id,
+ gfx::KeyframeModel* keyframe_model) {
+ if (target_property_id == kContentOpacity) {
+ content_opacity_ = value;
+ } else {
+ DCHECK_EQ(target_property_id, kCombinedOpacity);
+ combined_opacity_ = value;
+ }
+}
+
+void SurfaceAnimationManager::SharedAnimationState::OnTransformAnimated(
+ const gfx::TransformOperations& operations,
+ int target_property_id,
+ gfx::KeyframeModel* keyframe_model) {
+ DCHECK_EQ(target_property_id, kCombinedTransform);
+ combined_transform_ = operations;
+}
+
+void SurfaceAnimationManager::SharedAnimationState::OnSizeAnimated(
+ const gfx::SizeF& value,
+ int target_property_id,
+ gfx::KeyframeModel* keyframe_model) {
+ DCHECK_EQ(target_property_id, kContentSize);
+ content_size_ = value;
+}
+
+void SurfaceAnimationManager::SharedAnimationState::Reset() {
+ content_opacity_ = 1.0f;
+ content_size_ = gfx::SizeF();
+ combined_opacity_ = 1.0f;
+ combined_transform_ = gfx::TransformOperations();
+}
+
+SurfaceAnimationManager::RenderPassDrawData::RenderPassDrawData() = default;
+SurfaceAnimationManager::RenderPassDrawData::RenderPassDrawData(
+ RenderPassDrawData&&) = default;
+SurfaceAnimationManager::RenderPassDrawData::~RenderPassDrawData() = default;
+
} // namespace viz
diff --git a/chromium/components/viz/service/transitions/surface_animation_manager.h b/chromium/components/viz/service/transitions/surface_animation_manager.h
index 39f125fe443..f5230aeb447 100644
--- a/chromium/components/viz/service/transitions/surface_animation_manager.h
+++ b/chromium/components/viz/service/transitions/surface_animation_manager.h
@@ -9,18 +9,24 @@
#include <memory>
#include <vector>
+#include "base/containers/flat_map.h"
#include "base/time/time.h"
#include "components/viz/common/quads/compositor_frame_transition_directive.h"
+#include "components/viz/common/quads/compositor_render_pass.h"
+#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
#include "components/viz/common/resources/resource_id.h"
+#include "components/viz/service/display/shared_bitmap_manager.h"
#include "components/viz/service/surfaces/surface_saved_frame.h"
#include "components/viz/service/transitions/transferable_resource_tracker.h"
#include "components/viz/service/viz_service_export.h"
#include "ui/gfx/animation/keyframe/animation_curve.h"
#include "ui/gfx/animation/keyframe/keyframe_effect.h"
+#include "ui/gfx/animation/keyframe/keyframe_model.h"
namespace viz {
class Surface;
+class CompositorFrame;
class SurfaceSavedFrameStorage;
struct ReturnedResource;
struct TransferableResource;
@@ -30,15 +36,13 @@ struct TransferableResource;
// TODO(vmpstr): This class should also be responsible for interpolating frames
// and providing the result back to the surface, but that is currently not
// implemented.
-class VIZ_SERVICE_EXPORT SurfaceAnimationManager
- : public gfx::FloatAnimationCurve::Target,
- public gfx::TransformAnimationCurve::Target {
+class VIZ_SERVICE_EXPORT SurfaceAnimationManager {
public:
using TransitionDirectiveCompleteCallback =
base::RepeatingCallback<void(uint32_t)>;
- SurfaceAnimationManager();
- ~SurfaceAnimationManager() override;
+ explicit SurfaceAnimationManager(SharedBitmapManager* shared_bitmap_manager);
+ ~SurfaceAnimationManager();
void SetDirectiveFinishedCallback(
TransitionDirectiveCompleteCallback sequence_id_finished_callback);
@@ -60,7 +64,7 @@ class VIZ_SERVICE_EXPORT SurfaceAnimationManager
bool NeedsBeginFrame() const;
// Notify when a begin frame happens and a frame is advanced.
- void NotifyFrameAdvanced(base::TimeTicks new_time);
+ void NotifyFrameAdvanced();
// Interpolates from the saved frame to the current active frame on the
// surface, storing the result back on the surface.
@@ -70,29 +74,26 @@ class VIZ_SERVICE_EXPORT SurfaceAnimationManager
void RefResources(const std::vector<TransferableResource>& resources);
void UnrefResources(const std::vector<ReturnedResource>& resources);
- void OnFloatAnimated(const float& value,
- int target_property_id,
- gfx::KeyframeModel* keyframe_model) override;
+ // Updates the current frame time, without doing anything else.
+ void UpdateFrameTime(base::TimeTicks now);
- void OnTransformAnimated(const gfx::TransformOperations& operations,
- int target_property_id,
- gfx::KeyframeModel* keyframe_model) override;
+ private:
+ friend class SurfaceAnimationManagerTest;
- protected:
- float src_opacity() const { return src_opacity_; }
- float dst_opacity() const { return dst_opacity_; }
- gfx::TransformOperations src_transform() const { return src_transform_; }
- gfx::TransformOperations dst_transform() const { return dst_transform_; }
+ struct RenderPassDrawData {
+ RenderPassDrawData();
+ RenderPassDrawData(RenderPassDrawData&&);
+ ~RenderPassDrawData();
- private:
- enum TargetProperty : int {
- kSrcOpacity = 1,
- kDstOpacity,
- kSrcTransform,
- kDstTransform,
+ RenderPassDrawData& operator=(RenderPassDrawData&&) = default;
+
+ std::unique_ptr<CompositorRenderPass> render_pass;
+ absl::optional<CompositorRenderPassDrawQuad> draw_quad;
+ float opacity = 1.f;
};
- void UpdateAnimationCurves(const gfx::Size& output_size);
+ void CreateRootAnimationCurves(const gfx::Size& output_size);
+ void CreateSharedElementCurves();
// Helpers to process specific directives.
bool ProcessSaveDirective(const CompositorFrameTransitionDirective& directive,
@@ -110,6 +111,29 @@ class VIZ_SERVICE_EXPORT SurfaceAnimationManager
// valid if state is kLastFrame.
void FinalizeAndDisposeOfState();
+ // A helper function to copy render passes, while interpolating shared
+ // elements.
+ void CopyAndInterpolateSharedElements(
+ const std::vector<std::unique_ptr<CompositorRenderPass>>& source_passes,
+ CompositorRenderPass* animation_pass,
+ CompositorFrame* interpolated_frame);
+
+ // Helper function to create an animation pass which interpolates needed
+ // components.
+ std::unique_ptr<CompositorRenderPass> CreateAnimationCompositorRenderPass(
+ const gfx::Rect& output_rect) const;
+
+ // Given a render pass, this makes a copy of it while filtering animated
+ // render pass draw quads.
+ static bool FilterSharedElementQuads(
+ base::flat_map<CompositorRenderPassId, RenderPassDrawData>*
+ shared_draw_data,
+ const CompositorRenderPassDrawQuad& pass_quad,
+ CompositorRenderPass& copy_pass);
+
+ // Tick both the root and shared animations.
+ void TickAnimations(base::TimeTicks new_time);
+
enum class State { kIdle, kAnimating, kLastFrame };
TransitionDirectiveCompleteCallback sequence_id_finished_callback_;
@@ -118,19 +142,126 @@ class VIZ_SERVICE_EXPORT SurfaceAnimationManager
TransferableResourceTracker transferable_resource_tracker_;
- base::Optional<TransferableResourceTracker::ResourceFrame> saved_textures_;
- base::Optional<CompositorFrameTransitionDirective> save_directive_;
- base::Optional<CompositorFrameTransitionDirective> animate_directive_;
+ absl::optional<TransferableResourceTracker::ResourceFrame> saved_textures_;
+ absl::optional<CompositorFrameTransitionDirective> save_directive_;
+ absl::optional<CompositorFrameTransitionDirective> animate_directive_;
- // TODO(vmpstr): if SurfaceAnimationManager ultimately manages multiple
- // animations, then the following should be encapsulated in a per-animation
- // class.
+ // State represents the total state of the animation for this manager. It is
+ // adjusted in step with the root animation. In other words, if the root
+ // animation ends then the total animation is considered (almost) ended as
+ // well. We keep track of a separate state, since we need to produce a
+ // kLastFrame value after the root animation ends which is responsible for
+ // produce a clean active frame without any interpolations.
State state_ = State::kIdle;
- gfx::KeyframeEffect animator_;
- float src_opacity_ = 1.0f;
- float dst_opacity_ = 1.0f;
- gfx::TransformOperations src_transform_;
- gfx::TransformOperations dst_transform_;
+
+ // This is the animation state for the root elements.
+ class RootAnimationState : public gfx::FloatAnimationCurve::Target,
+ public gfx::TransformAnimationCurve::Target {
+ public:
+ RootAnimationState();
+ RootAnimationState(RootAnimationState&&);
+ ~RootAnimationState() override;
+
+ enum TargetProperty : int {
+ kSrcOpacity = 1,
+ kDstOpacity,
+ kSrcTransform,
+ kDstTransform,
+ };
+
+ void OnFloatAnimated(const float& value,
+ int target_property_id,
+ gfx::KeyframeModel* keyframe_model) override;
+
+ void OnTransformAnimated(const gfx::TransformOperations& operations,
+ int target_property_id,
+ gfx::KeyframeModel* keyframe_model) override;
+
+ void Reset();
+
+ gfx::KeyframeEffect& driver() { return driver_; }
+ const gfx::KeyframeEffect& driver() const { return driver_; }
+
+ float src_opacity() const { return src_opacity_; }
+ float dst_opacity() const { return dst_opacity_; }
+ const gfx::TransformOperations& src_transform() const {
+ return src_transform_;
+ }
+ const gfx::TransformOperations& dst_transform() const {
+ return dst_transform_;
+ }
+
+ private:
+ gfx::KeyframeEffect driver_;
+ float src_opacity_ = 1.0f;
+ float dst_opacity_ = 1.0f;
+ gfx::TransformOperations src_transform_;
+ gfx::TransformOperations dst_transform_;
+ };
+
+ // This is the animation state for a pair of shared elements.
+ class SharedAnimationState : public gfx::FloatAnimationCurve::Target,
+ public gfx::TransformAnimationCurve::Target,
+ public gfx::SizeAnimationCurve::Target {
+ public:
+ SharedAnimationState();
+ SharedAnimationState(SharedAnimationState&&);
+ ~SharedAnimationState() override;
+
+ enum TargetProperty : int {
+ // The following properties are used to blend the content of src and dest
+ // textues to produce a combined image.
+ kContentOpacity = 1,
+ kContentSize,
+
+ // The following properties are used when drawing the combined image to
+ // the target buffer.
+ kCombinedOpacity,
+ kCombinedTransform,
+ };
+
+ void OnFloatAnimated(const float& value,
+ int target_property_id,
+ gfx::KeyframeModel* keyframe_model) override;
+
+ void OnTransformAnimated(const gfx::TransformOperations& operations,
+ int target_property_id,
+ gfx::KeyframeModel* keyframe_model) override;
+
+ void OnSizeAnimated(const gfx::SizeF& value,
+ int target_property_id,
+ gfx::KeyframeModel* keyframe_model) override;
+
+ void Reset();
+
+ gfx::KeyframeEffect& driver() { return driver_; }
+ const gfx::KeyframeEffect& driver() const { return driver_; }
+
+ float content_opacity() const { return content_opacity_; }
+ const gfx::SizeF& content_size() const { return content_size_; }
+ float combined_opacity() const { return combined_opacity_; }
+ const gfx::TransformOperations& combined_transform() const {
+ return combined_transform_;
+ }
+
+ private:
+ gfx::KeyframeEffect driver_;
+ float content_opacity_ = 1.0f;
+ gfx::SizeF content_size_;
+ float combined_opacity_ = 1.0f;
+ gfx::TransformOperations combined_transform_;
+ };
+
+ // This is the root animation state.
+ RootAnimationState root_animation_;
+
+ // This is a vector of animation states for each of the shared elements. Note
+ // that the position in the vector matches both the position of the shared
+ // texture in the saved_textures_->shared vector and the corresponding
+ // position in the animate_directive->shared_render_pass_ids() vector.
+ std::vector<SharedAnimationState> shared_animations_;
+
+ base::TimeTicks latest_time_;
};
} // namespace viz
diff --git a/chromium/components/viz/service/transitions/surface_animation_manager_unittest.cc b/chromium/components/viz/service/transitions/surface_animation_manager_unittest.cc
index 16496c31a74..745c92c544a 100644
--- a/chromium/components/viz/service/transitions/surface_animation_manager_unittest.cc
+++ b/chromium/components/viz/service/transitions/surface_animation_manager_unittest.cc
@@ -42,10 +42,45 @@ std::vector<CompositorFrameTransitionDirective> CreateAnimateDirectiveAsVector(
} // namespace
-class TestSurfaceAnimationManager : public SurfaceAnimationManager {
+class SurfaceAnimationManagerTest : public testing::Test {
public:
- TestSurfaceAnimationManager() = default;
- ~TestSurfaceAnimationManager() override = default;
+ void SetUp() override {
+ current_time_ = base::TimeTicks() + base::TimeDelta::FromDays(1);
+ surface_manager_ = frame_sink_manager_.surface_manager();
+ support_ = std::make_unique<CompositorFrameSinkSupport>(
+ nullptr, &frame_sink_manager_, kArbitraryFrameSinkId, /*is_root=*/true);
+
+ LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create());
+ surface_id_ = SurfaceId(kArbitraryFrameSinkId, local_surface_id);
+ CompositorFrame frame = MakeDefaultCompositorFrame();
+ support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
+
+ manager_.emplace(&shared_bitmap_manager_);
+ manager_->SetDirectiveFinishedCallback(base::DoNothing());
+ manager_->UpdateFrameTime(current_time_);
+ }
+
+ void TearDown() override {
+ if (storage())
+ storage()->ExpireForTesting();
+ manager_.reset();
+ }
+
+ base::TimeTicks AdvanceTime(base::TimeDelta delta) {
+ current_time_ += delta;
+ return current_time_;
+ }
+
+ Surface* surface() const {
+ Surface* surface = surface_manager_->GetSurfaceForId(surface_id_);
+ // Can't ASSERT in a non-void function, so just CHECK instead.
+ CHECK(surface);
+ return surface;
+ }
+
+ SurfaceSavedFrameStorage* storage() const {
+ return surface()->GetSurfaceSavedFrameStorage();
+ }
void ValidateStartState(CompositorFrameTransitionDirective::Effect effect) {
switch (effect) {
@@ -55,13 +90,16 @@ class TestSurfaceAnimationManager : public SurfaceAnimationManager {
case CompositorFrameTransitionDirective::Effect::kRevealDown:
case CompositorFrameTransitionDirective::Effect::kExplode:
case CompositorFrameTransitionDirective::Effect::kFade:
- EXPECT_EQ(src_opacity(), 1.0f) << static_cast<int>(effect);
+ EXPECT_EQ(manager().root_animation_.src_opacity(), 1.0f)
+ << static_cast<int>(effect);
break;
case CompositorFrameTransitionDirective::Effect::kNone:
- EXPECT_EQ(src_opacity(), 0.0f) << static_cast<int>(effect);
+ EXPECT_EQ(manager().root_animation_.src_opacity(), 0.0f)
+ << static_cast<int>(effect);
break;
default:
- EXPECT_EQ(dst_opacity(), 0.0f) << static_cast<int>(effect);
+ EXPECT_EQ(manager().root_animation_.dst_opacity(), 0.0f)
+ << static_cast<int>(effect);
break;
}
@@ -73,36 +111,49 @@ class TestSurfaceAnimationManager : public SurfaceAnimationManager {
case CompositorFrameTransitionDirective::Effect::kRevealLeft:
case CompositorFrameTransitionDirective::Effect::kRevealRight:
case CompositorFrameTransitionDirective::Effect::kRevealUp:
- EXPECT_TRUE(src_transform().Apply().IsIdentity())
+ EXPECT_TRUE(
+ manager().root_animation_.src_transform().Apply().IsIdentity())
<< static_cast<int>(effect);
- EXPECT_TRUE(dst_transform().Apply().IsIdentity())
+ EXPECT_TRUE(
+ manager().root_animation_.dst_transform().Apply().IsIdentity())
<< static_cast<int>(effect);
break;
case CompositorFrameTransitionDirective::Effect::kCoverDown:
case CompositorFrameTransitionDirective::Effect::kCoverLeft:
case CompositorFrameTransitionDirective::Effect::kCoverRight:
case CompositorFrameTransitionDirective::Effect::kCoverUp:
- EXPECT_TRUE(src_transform().Apply().IsIdentity())
+ EXPECT_TRUE(
+ manager().root_animation_.src_transform().Apply().IsIdentity())
<< static_cast<int>(effect);
- EXPECT_FALSE(dst_transform().Apply().IsIdentity())
+ EXPECT_FALSE(
+ manager().root_animation_.dst_transform().Apply().IsIdentity())
<< static_cast<int>(effect);
- EXPECT_TRUE(dst_transform().Apply().IsIdentityOr2DTranslation());
+ EXPECT_TRUE(manager()
+ .root_animation_.dst_transform()
+ .Apply()
+ .IsIdentityOr2DTranslation());
break;
case CompositorFrameTransitionDirective::Effect::kImplode:
- EXPECT_TRUE(src_transform().Apply().IsIdentity())
+ EXPECT_TRUE(
+ manager().root_animation_.src_transform().Apply().IsIdentity())
<< static_cast<int>(effect);
- EXPECT_FALSE(dst_transform().Apply().IsIdentity())
+ EXPECT_FALSE(
+ manager().root_animation_.dst_transform().Apply().IsIdentity())
<< static_cast<int>(effect);
- EXPECT_TRUE(dst_transform().Apply().IsScaleOrTranslation())
+ EXPECT_TRUE(manager()
+ .root_animation_.dst_transform()
+ .Apply()
+ .IsScaleOrTranslation())
<< static_cast<int>(effect);
break;
default:
break;
}
}
+
void ValidateEndState(CompositorFrameTransitionDirective::Effect effect) {
- EXPECT_EQ(dst_opacity(), 1.0f);
- EXPECT_TRUE(dst_transform().Apply().IsIdentity());
+ EXPECT_EQ(manager().root_animation_.dst_opacity(), 1.0f);
+ EXPECT_TRUE(manager().root_animation_.dst_transform().Apply().IsIdentity());
switch (effect) {
case CompositorFrameTransitionDirective::Effect::kRevealRight:
@@ -111,7 +162,8 @@ class TestSurfaceAnimationManager : public SurfaceAnimationManager {
case CompositorFrameTransitionDirective::Effect::kRevealDown:
case CompositorFrameTransitionDirective::Effect::kExplode:
case CompositorFrameTransitionDirective::Effect::kFade:
- EXPECT_EQ(src_opacity(), 0.0f) << static_cast<int>(effect);
+ EXPECT_EQ(manager().root_animation_.src_opacity(), 0.0f)
+ << static_cast<int>(effect);
break;
default:
break;
@@ -122,61 +174,33 @@ class TestSurfaceAnimationManager : public SurfaceAnimationManager {
case CompositorFrameTransitionDirective::Effect::kRevealLeft:
case CompositorFrameTransitionDirective::Effect::kRevealRight:
case CompositorFrameTransitionDirective::Effect::kRevealUp:
- EXPECT_FALSE(src_transform().Apply().IsIdentity())
+ EXPECT_FALSE(
+ manager().root_animation_.src_transform().Apply().IsIdentity())
<< static_cast<int>(effect);
- EXPECT_TRUE(src_transform().Apply().IsIdentityOr2DTranslation())
+ EXPECT_TRUE(manager()
+ .root_animation_.src_transform()
+ .Apply()
+ .IsIdentityOr2DTranslation())
<< static_cast<int>(effect);
break;
case CompositorFrameTransitionDirective::Effect::kExplode:
- EXPECT_FALSE(src_transform().Apply().IsIdentity())
+ EXPECT_FALSE(
+ manager().root_animation_.src_transform().Apply().IsIdentity())
<< static_cast<int>(effect);
- EXPECT_TRUE(src_transform().Apply().IsScaleOrTranslation())
+ EXPECT_TRUE(manager()
+ .root_animation_.src_transform()
+ .Apply()
+ .IsScaleOrTranslation())
<< static_cast<int>(effect);
break;
default:
break;
}
}
-};
-
-class SurfaceAnimationManagerTest : public testing::Test {
- public:
- void SetUp() override {
- current_time_ = base::TimeTicks() + base::TimeDelta::FromDays(1);
- surface_manager_ = frame_sink_manager_.surface_manager();
- support_ = std::make_unique<CompositorFrameSinkSupport>(
- nullptr, &frame_sink_manager_, kArbitraryFrameSinkId, /*is_root=*/true);
-
- LocalSurfaceId local_surface_id(6, base::UnguessableToken::Create());
- surface_id_ = SurfaceId(kArbitraryFrameSinkId, local_surface_id);
- CompositorFrame frame = MakeDefaultCompositorFrame();
- support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
- }
-
- void TearDown() override {
- if (storage())
- storage()->ExpireForTesting();
- }
-
- base::TimeTicks AdvanceTime(base::TimeDelta delta) {
- current_time_ += delta;
- return current_time_;
- }
- base::TimeTicks current_time() const { return current_time_; }
+ SurfaceAnimationManager& manager() { return *manager_; }
- Surface* surface() const {
- Surface* surface = surface_manager_->GetSurfaceForId(surface_id_);
- // Can't ASSERT in a non-void function, so just CHECK instead.
- CHECK(surface);
- return surface;
- }
-
- SurfaceSavedFrameStorage* storage() const {
- return surface()->GetSurfaceSavedFrameStorage();
- }
-
- private:
+ protected:
base::TimeTicks current_time_;
ServerSharedBitmapManager shared_bitmap_manager_;
@@ -184,118 +208,113 @@ class SurfaceAnimationManagerTest : public testing::Test {
SurfaceManager* surface_manager_;
std::unique_ptr<CompositorFrameSinkSupport> support_;
SurfaceId surface_id_;
+
+ absl::optional<SurfaceAnimationManager> manager_;
};
TEST_F(SurfaceAnimationManagerTest, DefaultState) {
- TestSurfaceAnimationManager manager;
- manager.SetDirectiveFinishedCallback(base::DoNothing());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
- manager.ProcessTransitionDirectives({}, storage());
+ manager().ProcessTransitionDirectives({}, storage());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
}
TEST_F(SurfaceAnimationManagerTest, SaveAnimateNeedsBeginFrame) {
- TestSurfaceAnimationManager manager;
- manager.SetDirectiveFinishedCallback(base::DoNothing());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
- manager.ProcessTransitionDirectives(CreateSaveDirectiveAsVector(1),
- storage());
+ manager().ProcessTransitionDirectives(CreateSaveDirectiveAsVector(1),
+ storage());
storage()->CompleteForTesting();
- manager.ProcessTransitionDirectives(CreateAnimateDirectiveAsVector(2),
- storage());
+ manager().ProcessTransitionDirectives(CreateAnimateDirectiveAsVector(2),
+ storage());
// Tick curves to set start time.
- manager.NotifyFrameAdvanced(AdvanceTime(base::TimeDelta()));
+ manager().UpdateFrameTime(AdvanceTime(base::TimeDelta()));
+ manager().NotifyFrameAdvanced();
- EXPECT_TRUE(manager.NeedsBeginFrame());
+ EXPECT_TRUE(manager().NeedsBeginFrame());
- manager.NotifyFrameAdvanced(
- AdvanceTime(base::TimeDelta::FromMilliseconds(50)));
- EXPECT_TRUE(manager.NeedsBeginFrame());
+ manager().UpdateFrameTime(AdvanceTime(base::TimeDelta::FromMilliseconds(50)));
+ manager().NotifyFrameAdvanced();
+ EXPECT_TRUE(manager().NeedsBeginFrame());
- manager.NotifyFrameAdvanced(
+ manager().UpdateFrameTime(
AdvanceTime(base::TimeDelta::FromMilliseconds(500)));
+ manager().NotifyFrameAdvanced();
// We should be at the done state, but still need a frame.
- EXPECT_TRUE(manager.NeedsBeginFrame());
+ EXPECT_TRUE(manager().NeedsBeginFrame());
- manager.NotifyFrameAdvanced(
- AdvanceTime(base::TimeDelta::FromMilliseconds(1)));
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ manager().UpdateFrameTime(AdvanceTime(base::TimeDelta::FromMilliseconds(1)));
+ manager().NotifyFrameAdvanced();
+ EXPECT_FALSE(manager().NeedsBeginFrame());
}
TEST_F(SurfaceAnimationManagerTest, AnimateWithoutSaveIsNoop) {
- TestSurfaceAnimationManager manager;
- manager.SetDirectiveFinishedCallback(base::DoNothing());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
- manager.ProcessTransitionDirectives(CreateAnimateDirectiveAsVector(1),
- storage());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ manager().ProcessTransitionDirectives(CreateAnimateDirectiveAsVector(1),
+ storage());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
}
TEST_F(SurfaceAnimationManagerTest, SaveTimesOut) {
- TestSurfaceAnimationManager manager;
- manager.SetDirectiveFinishedCallback(base::DoNothing());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
- manager.ProcessTransitionDirectives(CreateSaveDirectiveAsVector(1),
- storage());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ manager().ProcessTransitionDirectives(CreateSaveDirectiveAsVector(1),
+ storage());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
storage()->ExpireForTesting();
AdvanceTime(base::TimeDelta::FromSeconds(6));
- manager.ProcessTransitionDirectives(CreateAnimateDirectiveAsVector(2),
- storage());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ manager().ProcessTransitionDirectives(CreateAnimateDirectiveAsVector(2),
+ storage());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
}
TEST_F(SurfaceAnimationManagerTest, RepeatedSavesAreOk) {
- TestSurfaceAnimationManager manager;
- manager.SetDirectiveFinishedCallback(base::DoNothing());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
uint32_t sequence_id = 1;
for (int i = 0; i < 200; ++i) {
- manager.ProcessTransitionDirectives(
+ manager().ProcessTransitionDirectives(
CreateSaveDirectiveAsVector(sequence_id), storage());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
++sequence_id;
- AdvanceTime(base::TimeDelta::FromMilliseconds(50));
+ manager().UpdateFrameTime(
+ AdvanceTime(base::TimeDelta::FromMilliseconds(50)));
}
storage()->CompleteForTesting();
- manager.ProcessTransitionDirectives(
+ manager().ProcessTransitionDirectives(
CreateAnimateDirectiveAsVector(sequence_id), storage());
// Tick curves to set start time.
- manager.NotifyFrameAdvanced(AdvanceTime(base::TimeDelta()));
+ manager().UpdateFrameTime(AdvanceTime(base::TimeDelta()));
+ manager().NotifyFrameAdvanced();
- EXPECT_TRUE(manager.NeedsBeginFrame());
+ EXPECT_TRUE(manager().NeedsBeginFrame());
- manager.NotifyFrameAdvanced(
+ manager().UpdateFrameTime(
AdvanceTime(base::TimeDelta::FromMilliseconds(500)));
+ manager().NotifyFrameAdvanced();
// We're at the done state now.
- EXPECT_TRUE(manager.NeedsBeginFrame());
+ EXPECT_TRUE(manager().NeedsBeginFrame());
- manager.NotifyFrameAdvanced(
- AdvanceTime(base::TimeDelta::FromMilliseconds(1)));
+ manager().UpdateFrameTime(AdvanceTime(base::TimeDelta::FromMilliseconds(1)));
+ manager().NotifyFrameAdvanced();
// Now we're idle.
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
}
TEST_F(SurfaceAnimationManagerTest, CheckStartEndStates) {
- TestSurfaceAnimationManager manager;
- manager.SetDirectiveFinishedCallback(base::DoNothing());
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ EXPECT_FALSE(manager().NeedsBeginFrame());
CompositorFrameTransitionDirective::Effect effects[] = {
CompositorFrameTransitionDirective::Effect::kNone,
@@ -313,35 +332,39 @@ TEST_F(SurfaceAnimationManagerTest, CheckStartEndStates) {
uint32_t sequence_id = 1;
for (auto effect : effects) {
- manager.ProcessTransitionDirectives(
+ manager().ProcessTransitionDirectives(
CreateSaveDirectiveAsVector(sequence_id++, effect), storage());
storage()->CompleteForTesting();
- manager.ProcessTransitionDirectives(
+ manager().ProcessTransitionDirectives(
CreateAnimateDirectiveAsVector(sequence_id++), storage());
// Tick curves to set start time.
- manager.NotifyFrameAdvanced(AdvanceTime(base::TimeDelta()));
+ manager().UpdateFrameTime(AdvanceTime(base::TimeDelta()));
+ manager().NotifyFrameAdvanced();
- manager.ValidateStartState(effect);
+ ValidateStartState(effect);
- EXPECT_TRUE(manager.NeedsBeginFrame());
+ EXPECT_TRUE(manager().NeedsBeginFrame());
- manager.NotifyFrameAdvanced(
- AdvanceTime(base::TimeDelta::FromMilliseconds(250)));
- EXPECT_TRUE(manager.NeedsBeginFrame());
+ manager().UpdateFrameTime(
+ AdvanceTime(base::TimeDelta::FromMilliseconds(200)));
+ manager().NotifyFrameAdvanced();
+ EXPECT_TRUE(manager().NeedsBeginFrame());
- manager.NotifyFrameAdvanced(
- AdvanceTime(base::TimeDelta::FromMilliseconds(250)));
+ manager().UpdateFrameTime(
+ AdvanceTime(base::TimeDelta::FromMilliseconds(200)));
+ manager().NotifyFrameAdvanced();
// We should be at the done state, but still need a frame.
- EXPECT_TRUE(manager.NeedsBeginFrame());
+ EXPECT_TRUE(manager().NeedsBeginFrame());
- manager.NotifyFrameAdvanced(
+ manager().UpdateFrameTime(
AdvanceTime(base::TimeDelta::FromMilliseconds(1)));
- EXPECT_FALSE(manager.NeedsBeginFrame());
+ manager().NotifyFrameAdvanced();
+ EXPECT_FALSE(manager().NeedsBeginFrame());
- manager.ValidateEndState(effect);
+ ValidateEndState(effect);
}
}
diff --git a/chromium/components/viz/service/transitions/transferable_resource_tracker.cc b/chromium/components/viz/service/transitions/transferable_resource_tracker.cc
index 7cbb87c36d8..6e6a5b9109a 100644
--- a/chromium/components/viz/service/transitions/transferable_resource_tracker.cc
+++ b/chromium/components/viz/service/transitions/transferable_resource_tracker.cc
@@ -11,8 +11,9 @@
#include <utility>
#include "base/containers/contains.h"
+#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/resources/resource_id.h"
-#include "components/viz/common/resources/single_release_callback.h"
+#include "components/viz/common/resources/shared_bitmap.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
@@ -20,9 +21,11 @@
namespace viz {
-TransferableResourceTracker::TransferableResourceTracker()
+TransferableResourceTracker::TransferableResourceTracker(
+ SharedBitmapManager* shared_bitmap_manager)
: starting_id_(kVizReservedRangeStartId.GetUnsafeValue()),
- next_id_(kVizReservedRangeStartId.GetUnsafeValue()) {}
+ next_id_(kVizReservedRangeStartId.GetUnsafeValue()),
+ shared_bitmap_manager_(shared_bitmap_manager) {}
TransferableResourceTracker::~TransferableResourceTracker() = default;
@@ -34,7 +37,7 @@ TransferableResourceTracker::ImportResources(
// valid.
CHECK(saved_frame->IsValid());
- base::Optional<SurfaceSavedFrame::FrameResult> frame_copy =
+ absl::optional<SurfaceSavedFrame::FrameResult> frame_copy =
saved_frame->TakeResult();
ResourceFrame resource_frame;
@@ -55,37 +58,61 @@ TransferableResourceTracker::PositionedResource
TransferableResourceTracker::ImportResource(
SurfaceSavedFrame::OutputCopyResult output_copy) {
TransferableResource resource;
+
+ TransferableResourceHolder::ResourceReleaseCallback release_callback;
if (output_copy.is_software) {
- // TODO(vmpstr): This needs to be updated and tested in software. For
- // example, we don't currently have a release callback in software, although
- // tests do set one up.
+ DCHECK(output_copy.mailbox.IsZero());
+ DCHECK(!output_copy.release_callback);
+
+ SharedBitmapId id = SharedBitmap::GenerateId();
+ shared_bitmap_manager_->LocalAllocatedSharedBitmap(
+ std::move(output_copy.bitmap), id);
resource = TransferableResource::MakeSoftware(
- output_copy.mailbox, output_copy.rect.size(), RGBA_8888);
+ id, output_copy.draw_data.size, RGBA_8888);
+
+ // Remove the bitmap from shared bitmap manager when no longer in use.
+ release_callback = base::BindOnce(
+ [](SharedBitmapManager* manager, const TransferableResource& resource) {
+ const SharedBitmapId& id = resource.mailbox_holder.mailbox;
+ manager->ChildDeletedSharedBitmap(id);
+ },
+ shared_bitmap_manager_);
} else {
+ DCHECK(output_copy.bitmap.drawsNothing());
+
resource = TransferableResource::MakeGL(
output_copy.mailbox, GL_LINEAR, GL_TEXTURE_2D, output_copy.sync_token,
- output_copy.rect.size(),
+ output_copy.draw_data.size,
/*is_overlay_candidate=*/false);
+
+ // Run the SingleReleaseCallback when no longer in use.
+ if (output_copy.release_callback) {
+ release_callback = base::BindOnce(
+ [](ReleaseCallback callback, const TransferableResource& resource) {
+ std::move(callback).Run(resource.mailbox_holder.sync_token,
+ /*is_lost=*/false);
+ },
+ std::move(output_copy.release_callback));
+ }
}
resource.id = GetNextAvailableResourceId();
DCHECK(!base::Contains(managed_resources_, resource.id));
managed_resources_.emplace(
- resource.id, TransferableResourceHolder(
- resource, std::move(output_copy.release_callback)));
+ resource.id,
+ TransferableResourceHolder(resource, std::move(release_callback)));
PositionedResource result;
result.resource = resource;
- result.rect = output_copy.rect;
- result.target_transform = output_copy.target_transform;
+ result.draw_data = output_copy.draw_data;
return result;
}
void TransferableResourceTracker::ReturnFrame(const ResourceFrame& frame) {
- UnrefResource(frame.root.resource.id);
+ UnrefResource(frame.root.resource.id, /*count=*/1);
for (const auto& shared : frame.shared) {
if (shared.has_value())
- UnrefResource(shared->resource.id);
+ UnrefResource(shared->resource.id, /*count=*/1);
}
}
@@ -94,9 +121,11 @@ void TransferableResourceTracker::RefResource(ResourceId id) {
++managed_resources_[id].ref_count;
}
-void TransferableResourceTracker::UnrefResource(ResourceId id) {
+void TransferableResourceTracker::UnrefResource(ResourceId id, int count) {
DCHECK(base::Contains(managed_resources_, id));
- if (--managed_resources_[id].ref_count == 0)
+ DCHECK_LE(count, managed_resources_[id].ref_count);
+ managed_resources_[id].ref_count -= count;
+ if (managed_resources_[id].ref_count == 0)
managed_resources_.erase(id);
}
@@ -129,9 +158,8 @@ TransferableResourceTracker::TransferableResourceHolder::
TransferableResourceTracker::TransferableResourceHolder::
TransferableResourceHolder(TransferableResourceHolder&& other) = default;
TransferableResourceTracker::TransferableResourceHolder::
- TransferableResourceHolder(
- const TransferableResource& resource,
- std::unique_ptr<SingleReleaseCallback> release_callback)
+ TransferableResourceHolder(const TransferableResource& resource,
+ ResourceReleaseCallback release_callback)
: resource(resource),
release_callback(std::move(release_callback)),
ref_count(1u) {}
@@ -139,8 +167,7 @@ TransferableResourceTracker::TransferableResourceHolder::
TransferableResourceTracker::TransferableResourceHolder::
~TransferableResourceHolder() {
if (release_callback)
- release_callback->Run(resource.mailbox_holder.sync_token,
- /*is_lost=*/false);
+ std::move(release_callback).Run(resource);
}
TransferableResourceTracker::TransferableResourceHolder&
diff --git a/chromium/components/viz/service/transitions/transferable_resource_tracker.h b/chromium/components/viz/service/transitions/transferable_resource_tracker.h
index 151b5bce750..5edd08ef507 100644
--- a/chromium/components/viz/service/transitions/transferable_resource_tracker.h
+++ b/chromium/components/viz/service/transitions/transferable_resource_tracker.h
@@ -9,9 +9,10 @@
#include <memory>
#include <vector>
+#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/resources/resource_id.h"
-#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/common/resources/transferable_resource.h"
+#include "components/viz/service/display/shared_bitmap_manager.h"
#include "components/viz/service/surfaces/surface_saved_frame.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/mailbox.h"
@@ -27,10 +28,7 @@ class VIZ_SERVICE_EXPORT TransferableResourceTracker {
// This represents a resource that is positioned somewhere on screen.
struct VIZ_SERVICE_EXPORT PositionedResource {
TransferableResource resource;
- // This is the resource's initial rect.
- gfx::Rect rect;
- // This is the transform that takes `rect` into root render pass space.
- gfx::Transform target_transform;
+ SurfaceSavedFrame::RenderPassDrawData draw_data;
};
// A resource frame consists of a root PositionedResource and a set of
@@ -44,10 +42,11 @@ class VIZ_SERVICE_EXPORT TransferableResourceTracker {
ResourceFrame& operator=(ResourceFrame&& other);
PositionedResource root;
- std::vector<base::Optional<PositionedResource>> shared;
+ std::vector<absl::optional<PositionedResource>> shared;
};
- TransferableResourceTracker();
+ explicit TransferableResourceTracker(
+ SharedBitmapManager* shared_bitmap_manager);
TransferableResourceTracker(const TransferableResourceTracker&) = delete;
~TransferableResourceTracker();
@@ -73,7 +72,7 @@ class VIZ_SERVICE_EXPORT TransferableResourceTracker {
// Ref count management for the resources returned by `ImportResources`.
void RefResource(ResourceId id);
- void UnrefResource(ResourceId id);
+ void UnrefResource(ResourceId id, int count);
bool is_empty() const { return managed_resources_.empty(); }
@@ -92,18 +91,21 @@ class VIZ_SERVICE_EXPORT TransferableResourceTracker {
const uint32_t starting_id_;
uint32_t next_id_;
+ SharedBitmapManager* const shared_bitmap_manager_;
+
struct TransferableResourceHolder {
+ using ResourceReleaseCallback =
+ base::OnceCallback<void(const TransferableResource&)>;
+
TransferableResourceHolder();
+ TransferableResourceHolder(const TransferableResource& resource,
+ ResourceReleaseCallback release_callback);
TransferableResourceHolder(TransferableResourceHolder&& other);
- TransferableResourceHolder(
- const TransferableResource& resource,
- std::unique_ptr<SingleReleaseCallback> release_callback);
- ~TransferableResourceHolder();
-
TransferableResourceHolder& operator=(TransferableResourceHolder&& other);
+ ~TransferableResourceHolder();
TransferableResource resource;
- std::unique_ptr<SingleReleaseCallback> release_callback;
+ ResourceReleaseCallback release_callback;
uint8_t ref_count = 0u;
};
diff --git a/chromium/components/viz/service/transitions/transferable_resource_tracker_unittest.cc b/chromium/components/viz/service/transitions/transferable_resource_tracker_unittest.cc
index 8a5a33d98d2..30127ed03b2 100644
--- a/chromium/components/viz/service/transitions/transferable_resource_tracker_unittest.cc
+++ b/chromium/components/viz/service/transitions/transferable_resource_tracker_unittest.cc
@@ -6,8 +6,9 @@
#include <memory>
#include <utility>
-#include "base/test/bind.h"
+#include "base/bind.h"
#include "components/viz/common/quads/compositor_frame_transition_directive.h"
+#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/surfaces/surface_saved_frame.h"
#include "components/viz/service/transitions/transferable_resource_tracker.h"
#include "gpu/command_buffer/common/mailbox.h"
@@ -17,13 +18,12 @@
namespace viz {
namespace {
-std::unique_ptr<SurfaceSavedFrame> CreateFrameWithResult(
- base::OnceCallback<void(const gpu::SyncToken&, bool)> callback) {
+std::unique_ptr<SurfaceSavedFrame> CreateFrameWithResult() {
CompositorFrameTransitionDirective directive(
1, CompositorFrameTransitionDirective::Type::kSave);
auto frame = std::make_unique<SurfaceSavedFrame>(
std::move(directive), base::BindRepeating([](uint32_t sequence_id) {}));
- frame->CompleteSavedFrameForTesting(std::move(callback));
+ frame->CompleteSavedFrameForTesting();
return frame;
}
@@ -34,39 +34,40 @@ class TransferableResourceTrackerTest : public testing::Test {
void SetNextId(TransferableResourceTracker* tracker, uint32_t id) {
tracker->next_id_ = id;
}
+
+ // Returns if there is a SharedBitmap in SharedBitmapManager for |resource|.
+ bool HasBitmapResource(const TransferableResource& resource) {
+ DCHECK(resource.is_software);
+ SharedBitmapId id = resource.mailbox_holder.mailbox;
+ return !!shared_bitmap_manager_.GetSharedBitmapFromId(gfx::Size(1, 1),
+ RGBA_8888, id);
+ }
+
+ protected:
+ ServerSharedBitmapManager shared_bitmap_manager_;
};
TEST_F(TransferableResourceTrackerTest, IdInRange) {
- TransferableResourceTracker tracker;
+ TransferableResourceTracker tracker(&shared_bitmap_manager_);
- bool resource1_released = false;
- auto frame1 =
- tracker.ImportResources(CreateFrameWithResult(base::BindLambdaForTesting(
- [&resource1_released](const gpu::SyncToken&, bool) {
- ASSERT_FALSE(resource1_released);
- resource1_released = true;
- })));
+ auto frame1 = tracker.ImportResources(CreateFrameWithResult());
+ EXPECT_TRUE(HasBitmapResource(frame1.root.resource));
EXPECT_GE(frame1.root.resource.id, kVizReservedRangeStartId);
- bool resource2_released = false;
- auto frame2 =
- tracker.ImportResources(CreateFrameWithResult(base::BindLambdaForTesting(
- [&resource2_released](const gpu::SyncToken&, bool) {
- ASSERT_FALSE(resource2_released);
- resource2_released = true;
- })));
+ auto frame2 = tracker.ImportResources(CreateFrameWithResult());
+ EXPECT_TRUE(HasBitmapResource(frame2.root.resource));
EXPECT_GE(frame2.root.resource.id, frame1.root.resource.id);
tracker.ReturnFrame(frame1);
- EXPECT_TRUE(resource1_released);
+ EXPECT_FALSE(HasBitmapResource(frame1.root.resource));
tracker.RefResource(frame2.root.resource.id);
tracker.ReturnFrame(frame2);
- EXPECT_FALSE(resource2_released);
- tracker.UnrefResource(frame2.root.resource.id);
- EXPECT_TRUE(resource2_released);
+ EXPECT_TRUE(HasBitmapResource(frame2.root.resource));
+ tracker.UnrefResource(frame2.root.resource.id, 1);
+ EXPECT_FALSE(HasBitmapResource(frame2.root.resource));
}
TEST_F(TransferableResourceTrackerTest, ExhaustedIdLoops) {
@@ -74,36 +75,44 @@ TEST_F(TransferableResourceTrackerTest, ExhaustedIdLoops) {
uint32_t>::value,
"The test only makes sense if ResourceId is uint32_t");
uint32_t next_id = std::numeric_limits<uint32_t>::max() - 3u;
- TransferableResourceTracker tracker;
+ TransferableResourceTracker tracker(&shared_bitmap_manager_);
SetNextId(&tracker, next_id);
ResourceId last_id = kInvalidResourceId;
for (int i = 0; i < 10; ++i) {
- bool resource_released = false;
- auto frame = tracker.ImportResources(
- CreateFrameWithResult(base::BindLambdaForTesting(
- [&resource_released](const gpu::SyncToken&, bool) {
- ASSERT_FALSE(resource_released);
- resource_released = true;
- })));
+ auto frame = tracker.ImportResources(CreateFrameWithResult());
+ EXPECT_TRUE(HasBitmapResource(frame.root.resource));
EXPECT_GE(frame.root.resource.id, kVizReservedRangeStartId);
EXPECT_NE(frame.root.resource.id, last_id);
last_id = frame.root.resource.id;
tracker.ReturnFrame(frame);
- EXPECT_TRUE(resource_released);
+ EXPECT_FALSE(HasBitmapResource(frame.root.resource));
}
}
+TEST_F(TransferableResourceTrackerTest, UnrefWithCount) {
+ TransferableResourceTracker tracker(&shared_bitmap_manager_);
+ auto frame = tracker.ImportResources(CreateFrameWithResult());
+ for (int i = 0; i < 100; ++i)
+ tracker.RefResource(frame.root.resource.id);
+ ASSERT_FALSE(tracker.is_empty());
+ tracker.UnrefResource(frame.root.resource.id, 1);
+ EXPECT_FALSE(tracker.is_empty());
+ tracker.UnrefResource(frame.root.resource.id, 1);
+ EXPECT_FALSE(tracker.is_empty());
+ tracker.UnrefResource(frame.root.resource.id, 99);
+ EXPECT_TRUE(tracker.is_empty());
+}
+
TEST_F(TransferableResourceTrackerTest,
ExhaustedIdLoopsButSkipsUnavailableIds) {
static_assert(std::is_same<decltype(kInvalidResourceId.GetUnsafeValue()),
uint32_t>::value,
"The test only makes sense if ResourceId is uint32_t");
- TransferableResourceTracker tracker;
+ TransferableResourceTracker tracker(&shared_bitmap_manager_);
- auto reserved = tracker.ImportResources(CreateFrameWithResult(
- base::BindOnce([](const gpu::SyncToken&, bool) {})));
+ auto reserved = tracker.ImportResources(CreateFrameWithResult());
EXPECT_GE(reserved.root.resource.id, kVizReservedRangeStartId);
uint32_t next_id = std::numeric_limits<uint32_t>::max() - 3u;
@@ -111,20 +120,15 @@ TEST_F(TransferableResourceTrackerTest,
ResourceId last_id = kInvalidResourceId;
for (int i = 0; i < 10; ++i) {
- bool resource_released = false;
- auto frame = tracker.ImportResources(
- CreateFrameWithResult(base::BindLambdaForTesting(
- [&resource_released](const gpu::SyncToken&, bool) {
- ASSERT_FALSE(resource_released);
- resource_released = true;
- })));
+ auto frame = tracker.ImportResources(CreateFrameWithResult());
+ EXPECT_TRUE(HasBitmapResource(frame.root.resource));
EXPECT_GE(frame.root.resource.id, kVizReservedRangeStartId);
EXPECT_NE(frame.root.resource.id, last_id);
EXPECT_NE(frame.root.resource.id, reserved.root.resource.id);
last_id = frame.root.resource.id;
tracker.ReturnFrame(frame);
- EXPECT_TRUE(resource_released);
+ EXPECT_FALSE(HasBitmapResource(frame.root.resource));
}
}
diff --git a/chromium/components/web_cache/browser/BUILD.gn b/chromium/components/web_cache/browser/BUILD.gn
index 17468f850fc..5a2969497b6 100644
--- a/chromium/components/web_cache/browser/BUILD.gn
+++ b/chromium/components/web_cache/browser/BUILD.gn
@@ -13,6 +13,7 @@ static_library("browser") {
deps = [
"//base",
"//components/prefs",
+ "//components/web_cache/public:features",
"//components/web_cache/public/mojom",
"//content/public/browser",
"//content/public/common",
diff --git a/chromium/components/web_cache/browser/web_cache_manager.cc b/chromium/components/web_cache/browser/web_cache_manager.cc
index 59e92cb41e5..593ef17152d 100644
--- a/chromium/components/web_cache/browser/web_cache_manager.cc
+++ b/chromium/components/web_cache/browser/web_cache_manager.cc
@@ -18,6 +18,7 @@
#include "base/time/time.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
+#include "components/web_cache/public/features.h"
using base::Time;
using base::TimeDelta;
@@ -326,6 +327,8 @@ void WebCacheManager::ClearRendererCache(
}
void WebCacheManager::ReviseAllocationStrategy() {
+ DCHECK(!base::FeatureList::IsEnabled(kTrimWebCacheOnMemoryPressureOnly));
+
DCHECK(stats_.size() <=
active_renderers_.size() + inactive_renderers_.size());
@@ -377,6 +380,9 @@ void WebCacheManager::ReviseAllocationStrategy() {
}
void WebCacheManager::ReviseAllocationStrategyLater() {
+ if (base::FeatureList::IsEnabled(kTrimWebCacheOnMemoryPressureOnly))
+ return;
+
// Ask to be called back in a few milliseconds to actually recompute our
// allocation.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
diff --git a/chromium/components/web_cache/public/BUILD.gn b/chromium/components/web_cache/public/BUILD.gn
new file mode 100644
index 00000000000..1ea1c0a807d
--- /dev/null
+++ b/chromium/components/web_cache/public/BUILD.gn
@@ -0,0 +1,12 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("features") {
+ sources = [
+ "features.cc",
+ "features.h",
+ ]
+
+ deps = [ "//base" ]
+}
diff --git a/chromium/components/web_cache/public/features.cc b/chromium/components/web_cache/public/features.cc
new file mode 100644
index 00000000000..3b66dc96c63
--- /dev/null
+++ b/chromium/components/web_cache/public/features.cc
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/web_cache/public/features.h"
+
+namespace web_cache {
+
+const base::Feature kTrimWebCacheOnMemoryPressureOnly{
+ "TrimWebCacheOnMemoryPressureOnly", base::FEATURE_DISABLED_BY_DEFAULT};
+
+} // namespace web_cache
diff --git a/chromium/components/web_cache/public/features.h b/chromium/components/web_cache/public/features.h
new file mode 100644
index 00000000000..93dad44d0ef
--- /dev/null
+++ b/chromium/components/web_cache/public/features.h
@@ -0,0 +1,19 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_WEB_CACHE_PUBLIC_FEATURES_H_
+#define COMPONENTS_WEB_CACHE_PUBLIC_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace web_cache {
+
+// Disable the logic that try to coordinate the in-memory cache resource usage
+// of all renderers and simply trim the caches on memory pressure. Renderers
+// get a memory pressure signal a few minutes after they've been backgrounded.
+extern const base::Feature kTrimWebCacheOnMemoryPressureOnly;
+
+} // namespace web_cache
+
+#endif // COMPONENTS_WEB_CACHE_PUBLIC_FEATURES_H_
diff --git a/chromium/components/web_cache/renderer/BUILD.gn b/chromium/components/web_cache/renderer/BUILD.gn
index 66d3194ea05..8fe881db3d6 100644
--- a/chromium/components/web_cache/renderer/BUILD.gn
+++ b/chromium/components/web_cache/renderer/BUILD.gn
@@ -10,6 +10,7 @@ static_library("renderer") {
deps = [
"//base",
+ "//components/web_cache/public:features",
"//components/web_cache/public/mojom",
"//content/public/child",
"//content/public/common",
diff --git a/chromium/components/web_cache/renderer/web_cache_impl.cc b/chromium/components/web_cache/renderer/web_cache_impl.cc
index c96ce1e21ee..520c3a54240 100644
--- a/chromium/components/web_cache/renderer/web_cache_impl.cc
+++ b/chromium/components/web_cache/renderer/web_cache_impl.cc
@@ -8,13 +8,40 @@
#include <memory>
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/numerics/safe_conversions.h"
+#include "components/web_cache/public/features.h"
#include "content/public/renderer/render_thread.h"
#include "third_party/blink/public/platform/web_cache.h"
namespace web_cache {
-WebCacheImpl::WebCacheImpl() = default;
+WebCacheImpl::WebCacheImpl() {
+ // The cache implementation is a blink::MemoryCache, which already owns a
+ // memory pressure listener. This listener is only enabled for low end devices
+ // (with 512MB or less of RAM), so for this type of device this memory
+ // pressure listener is redundant as we'll clear the cache twice. Preventing
+ // this would require exposing the |kTrimWebCacheOnMemoryPressureOnly| as a
+ // blink feature and this adds too much overhead for the sake of this
+ // experiment. If this feature gets enabled by default this should be
+ // optimized (the low end device check should be removed from
+ // blink::MemoryCache and this listener should be removed).
+ if (base::FeatureList::IsEnabled(kTrimWebCacheOnMemoryPressureOnly)) {
+ memory_pressure_listener_.emplace(
+ FROM_HERE,
+ base::BindRepeating(
+ [](WebCacheImpl* cache_impl,
+ base::MemoryPressureListener::MemoryPressureLevel level) {
+ if (level == base::MemoryPressureListener::MemoryPressureLevel::
+ MEMORY_PRESSURE_LEVEL_CRITICAL) {
+ cache_impl->ClearCache(false);
+ }
+ },
+ // Using unretained is safe because the memory pressure listener is
+ // owned by this object and so this can't cause an use-after-free.
+ base::Unretained(this)));
+ }
+}
WebCacheImpl::~WebCacheImpl() = default;
diff --git a/chromium/components/web_cache/renderer/web_cache_impl.h b/chromium/components/web_cache/renderer/web_cache_impl.h
index 198fb35320a..b8d544565c3 100644
--- a/chromium/components/web_cache/renderer/web_cache_impl.h
+++ b/chromium/components/web_cache/renderer/web_cache_impl.h
@@ -10,9 +10,11 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/memory_pressure_listener.h"
#include "components/web_cache/public/mojom/web_cache.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace web_cache {
@@ -48,6 +50,8 @@ class WebCacheImpl : public mojom::WebCache {
mojo::ReceiverSet<mojom::WebCache> receivers_;
+ absl::optional<base::MemoryPressureListener> memory_pressure_listener_;
+
DISALLOW_COPY_AND_ASSIGN(WebCacheImpl);
};
diff --git a/chromium/components/web_modal/BUILD.gn b/chromium/components/web_modal/BUILD.gn
index 2b71f8979fd..9cdf39faec5 100644
--- a/chromium/components/web_modal/BUILD.gn
+++ b/chromium/components/web_modal/BUILD.gn
@@ -27,6 +27,7 @@ component("web_modal") {
]
deps = [
+ "//components/back_forward_cache",
"//net",
"//skia",
"//ui/gfx/geometry",
diff --git a/chromium/components/web_modal/DEPS b/chromium/components/web_modal/DEPS
index 3539cc43913..acf2ee5acb4 100644
--- a/chromium/components/web_modal/DEPS
+++ b/chromium/components/web_modal/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/back_forward_cache",
"+content/public/browser",
"+content/public/test",
"+net/base",
diff --git a/chromium/components/web_modal/web_contents_modal_dialog_manager.cc b/chromium/components/web_modal/web_contents_modal_dialog_manager.cc
index 04fffc4b131..25bcae2ee61 100644
--- a/chromium/components/web_modal/web_contents_modal_dialog_manager.cc
+++ b/chromium/components/web_modal/web_contents_modal_dialog_manager.cc
@@ -8,7 +8,9 @@
#include <utility>
#include "base/check.h"
+#include "components/back_forward_cache/back_forward_cache_disable.h"
#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
+#include "content/public/browser/back_forward_cache.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
@@ -129,9 +131,22 @@ void WebContentsModalDialogManager::CloseAllDialogs() {
void WebContentsModalDialogManager::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
- if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted())
+ if (!navigation_handle->IsInPrimaryMainFrame() ||
+ !navigation_handle->HasCommitted())
return;
+ if (!child_dialogs_.empty()) {
+ // Disable BFCache for the page which had any modal dialog open.
+ // This prevents the page which has print, confirm form resubmission, http
+ // password dialogs, etc. to go in to BFCache. We can't simply dismiss the
+ // dialogs in the case, since they are requesting meaningful input from the
+ // user that affects the loading or display of the content.
+ content::BackForwardCache::DisableForRenderFrameHost(
+ navigation_handle->GetPreviousRenderFrameHostId(),
+ back_forward_cache::DisabledReason(
+ back_forward_cache::DisabledReasonId::kModalDialog));
+ }
+
// Close constrained windows if necessary.
if (!net::registry_controlled_domains::SameDomainOrHost(
navigation_handle->GetPreviousMainFrameURL(),
diff --git a/chromium/components/web_package/web_bundle_parser.cc b/chromium/components/web_package/web_bundle_parser.cc
index 9d3a4f5eccf..085e41f618f 100644
--- a/chromium/components/web_package/web_bundle_parser.cc
+++ b/chromium/components/web_package/web_bundle_parser.cc
@@ -13,6 +13,7 @@
#include "base/memory/weak_ptr.h"
#include "base/numerics/checked_math.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "components/cbor/reader.h"
#include "components/web_package/web_bundle_utils.h"
@@ -80,21 +81,21 @@ bool IsMetadataSection(const std::string& name) {
// Parses a `section-lengths` CBOR item.
// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
-base::Optional<SectionLengths> ParseSectionLengths(
+absl::optional<SectionLengths> ParseSectionLengths(
base::span<const uint8_t> data) {
cbor::Reader::DecoderError error;
- base::Optional<cbor::Value> value = cbor::Reader::Read(data, &error);
+ absl::optional<cbor::Value> value = cbor::Reader::Read(data, &error);
if (!value.has_value() || !value->is_array())
- return base::nullopt;
+ return absl::nullopt;
const cbor::Value::ArrayValue& array = value->GetArray();
if (array.size() % 2 != 0)
- return base::nullopt;
+ return absl::nullopt;
SectionLengths result;
for (size_t i = 0; i < array.size(); i += 2) {
if (!array[i].is_string() || !array[i + 1].is_unsigned())
- return base::nullopt;
+ return absl::nullopt;
result.emplace_back(array[i].GetString(), array[i + 1].GetUnsigned());
}
return result;
@@ -106,12 +107,12 @@ struct ParsedHeaders {
};
// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#cbor-headers
-base::Optional<ParsedHeaders> ConvertCBORValueToHeaders(
+absl::optional<ParsedHeaders> ConvertCBORValueToHeaders(
const cbor::Value& headers_value) {
// Step 1. If item doesn’t match the headers rule in the above CDDL, return
// an error.
if (!headers_value.is_map())
- return base::nullopt;
+ return absl::nullopt;
// Step 2. Let headers be a new header list ([FETCH]).
// Step 3. Let pseudos be an empty map ([INFRA]).
@@ -120,7 +121,7 @@ base::Optional<ParsedHeaders> ConvertCBORValueToHeaders(
// Step 4. For each pair (name, value) in item:
for (const auto& item : headers_value.GetMap()) {
if (!item.first.is_bytestring() || !item.second.is_bytestring())
- return base::nullopt;
+ return absl::nullopt;
base::StringPiece name = item.first.GetBytestringAsString();
base::StringPiece value = item.second.GetBytestringAsString();
@@ -128,7 +129,7 @@ base::Optional<ParsedHeaders> ConvertCBORValueToHeaders(
// an error. This matches the requirement in Section 8.1.2 of [RFC7540].
if (!base::IsStringASCII(name) ||
std::any_of(name.begin(), name.end(), base::IsAsciiUpper<char>))
- return base::nullopt;
+ return absl::nullopt;
// Step 4.2. If name starts with a ‘:’:
if (!name.empty() && name[0] == ':') {
@@ -138,7 +139,7 @@ base::Optional<ParsedHeaders> ConvertCBORValueToHeaders(
DCHECK(!result.pseudos.contains(name));
// Step 4.2.2. Set pseudos[name] to value.
result.pseudos.insert(
- std::make_pair(name.as_string(), value.as_string()));
+ std::make_pair(std::string(name), std::string(value)));
// Step 4.3.3. Continue.
continue;
}
@@ -147,7 +148,7 @@ base::Optional<ParsedHeaders> ConvertCBORValueToHeaders(
// in [FETCH], return an error.
if (!net::HttpUtil::IsValidHeaderName(name) ||
!net::HttpUtil::IsValidHeaderValue(value))
- return base::nullopt;
+ return absl::nullopt;
// Step 4.4. Assert: headers does not contain ([FETCH]) name, because CBOR
// maps cannot contain duplicate keys and an earlier step rejected
@@ -156,7 +157,8 @@ base::Optional<ParsedHeaders> ConvertCBORValueToHeaders(
DCHECK(!result.headers.contains(name));
// Step 4.5. Append (name, value) to headers.
- result.headers.insert(std::make_pair(name.as_string(), value.as_string()));
+ result.headers.insert(
+ std::make_pair(std::string(name), std::string(value)));
}
// Step 5. Return (headers, pseudos).
@@ -171,9 +173,9 @@ class InputReader {
uint64_t CurrentOffset() const { return current_offset_; }
size_t Size() const { return buf_.size(); }
- base::Optional<uint8_t> ReadByte() {
+ absl::optional<uint8_t> ReadByte() {
if (buf_.empty())
- return base::nullopt;
+ return absl::nullopt;
uint8_t byte = buf_[0];
Advance(1);
return byte;
@@ -188,41 +190,41 @@ class InputReader {
return true;
}
- base::Optional<base::span<const uint8_t>> ReadBytes(size_t n) {
+ absl::optional<base::span<const uint8_t>> ReadBytes(size_t n) {
if (buf_.size() < n)
- return base::nullopt;
+ return absl::nullopt;
auto result = buf_.subspan(0, n);
Advance(n);
return result;
}
- base::Optional<base::StringPiece> ReadString(size_t n) {
+ absl::optional<base::StringPiece> ReadString(size_t n) {
auto bytes = ReadBytes(n);
if (!bytes)
- return base::nullopt;
+ return absl::nullopt;
base::StringPiece str(reinterpret_cast<const char*>(bytes->data()),
bytes->size());
if (!base::IsStringUTF8(str))
- return base::nullopt;
+ return absl::nullopt;
return str;
}
// Parses the type and argument of a CBOR item from the input head. If parsed
// successfully and the type matches |expected_type|, returns the argument.
// Otherwise returns nullopt.
- base::Optional<uint64_t> ReadCBORHeader(CBORType expected_type) {
+ absl::optional<uint64_t> ReadCBORHeader(CBORType expected_type) {
auto pair = ReadTypeAndArgument();
if (!pair || pair->first != expected_type)
- return base::nullopt;
+ return absl::nullopt;
return pair->second;
}
private:
// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#parse-type-argument
- base::Optional<std::pair<CBORType, uint64_t>> ReadTypeAndArgument() {
- base::Optional<uint8_t> first_byte = ReadByte();
+ absl::optional<std::pair<CBORType, uint64_t>> ReadTypeAndArgument() {
+ absl::optional<uint8_t> first_byte = ReadByte();
if (!first_byte)
- return base::nullopt;
+ return absl::nullopt;
CBORType type = static_cast<CBORType>((*first_byte & 0xE0) / 0x20);
uint8_t b = *first_byte & 0x1F;
@@ -232,28 +234,28 @@ class InputReader {
if (b == 24) {
auto content = ReadByte();
if (!content || *content < 24)
- return base::nullopt;
+ return absl::nullopt;
return std::make_pair(type, *content);
}
if (b == 25) {
uint16_t content;
if (!ReadBigEndian(&content) || content >> 8 == 0)
- return base::nullopt;
+ return absl::nullopt;
return std::make_pair(type, content);
}
if (b == 26) {
uint32_t content;
if (!ReadBigEndian(&content) || content >> 16 == 0)
- return base::nullopt;
+ return absl::nullopt;
return std::make_pair(type, content);
}
if (b == 27) {
uint64_t content;
if (!ReadBigEndian(&content) || content >> 32 == 0)
- return base::nullopt;
+ return absl::nullopt;
return std::make_pair(type, content);
}
- return base::nullopt;
+ return absl::nullopt;
}
void Advance(size_t n) {
@@ -327,7 +329,7 @@ class WebBundleParser::MetadataParser
private:
// Step 1-4 of
// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
- void ParseMagicBytes(const base::Optional<std::vector<uint8_t>>& data) {
+ void ParseMagicBytes(const absl::optional<std::vector<uint8_t>>& data) {
if (!data) {
RunErrorCallbackAndDestroy("Error reading bundle magic bytes.");
return;
@@ -387,7 +389,7 @@ class WebBundleParser::MetadataParser
// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
void ParseBundleHeader(uint64_t url_length,
uint64_t offset_in_stream,
- const base::Optional<std::vector<uint8_t>>& data) {
+ const absl::optional<std::vector<uint8_t>>& data) {
if (!data) {
RunErrorCallbackAndDestroy("Error reading bundle header.");
return;
@@ -601,7 +603,7 @@ class WebBundleParser::MetadataParser
void ParseMetadataSection(SectionOffsets::const_iterator section_iter,
uint64_t expected_data_length,
- const base::Optional<std::vector<uint8_t>>& data) {
+ const absl::optional<std::vector<uint8_t>>& data) {
if (!data || data->size() != expected_data_length) {
RunErrorCallbackAndDestroy("Error reading section content.");
return;
@@ -609,7 +611,7 @@ class WebBundleParser::MetadataParser
// Parse the section contents as a CBOR item.
cbor::Reader::DecoderError error;
- base::Optional<cbor::Value> section_value =
+ absl::optional<cbor::Value> section_value =
cbor::Reader::Read(*data, &error);
if (!section_value) {
RunErrorCallbackAndDestroy(
@@ -758,7 +760,7 @@ class WebBundleParser::MetadataParser
}
requests.insert(std::make_pair(
parsed_url,
- mojom::BundleIndexValue::New(variants_value.as_string(),
+ mojom::BundleIndexValue::New(std::string(variants_value),
std::move(response_locations))));
}
@@ -944,7 +946,7 @@ class WebBundleParser::MetadataParser
const cbor::Value::BinaryValue& signed_bytes) {
// Parse |signed_bytes| as a CBOR item.
cbor::Reader::DecoderError error;
- base::Optional<cbor::Value> value =
+ absl::optional<cbor::Value> value =
cbor::Reader::Read(signed_bytes, &error);
if (!value) {
RunErrorCallbackAndDestroy(
@@ -1051,7 +1053,7 @@ class WebBundleParser::MetadataParser
}
subset_hashes.insert(std::make_pair(
parsed_url,
- mojom::SubsetHashesValue::New(variants_value.as_string(),
+ mojom::SubsetHashesValue::New(std::string(variants_value),
std::move(resource_integrities))));
}
@@ -1127,7 +1129,7 @@ class WebBundleParser::ResponseParser
private:
// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-response
void ParseResponseHeader(uint64_t expected_data_length,
- const base::Optional<std::vector<uint8_t>>& data) {
+ const absl::optional<std::vector<uint8_t>>& data) {
// Step 1. "Seek to offset requestMetadata.offset in stream. If this fails,
// return an error."
if (!data || data->size() != expected_data_length) {
@@ -1181,7 +1183,7 @@ class WebBundleParser::ResponseParser
return;
}
cbor::Reader::DecoderError error;
- base::Optional<cbor::Value> headers_value =
+ absl::optional<cbor::Value> headers_value =
cbor::Reader::Read(*headers_bytes, &error);
if (!headers_value) {
RunErrorCallbackAndDestroy("Cannot parse response headers.");
diff --git a/chromium/components/web_package/web_bundle_parser.h b/chromium/components/web_package/web_bundle_parser.h
index a1a3b1b7e18..26927d8abd0 100644
--- a/chromium/components/web_package/web_bundle_parser.h
+++ b/chromium/components/web_package/web_bundle_parser.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_WEB_PACKAGE_WEB_BUNDLE_PARSER_H_
#define COMPONENTS_WEB_PACKAGE_WEB_BUNDLE_PARSER_H_
-#include <memory>
-
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/components/web_package/web_bundle_parser_factory.cc b/chromium/components/web_package/web_bundle_parser_factory.cc
index 1a1a276e27d..8079508f6b8 100644
--- a/chromium/components/web_package/web_bundle_parser_factory.cc
+++ b/chromium/components/web_package/web_bundle_parser_factory.cc
@@ -31,7 +31,7 @@ class FileDataSource final : public mojom::BundleDataSource {
buf.resize(bytes);
std::move(callback).Run(std::move(buf));
} else {
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
}
}
diff --git a/chromium/components/web_package/web_bundle_parser_factory_unittest.cc b/chromium/components/web_package/web_bundle_parser_factory_unittest.cc
index 9a0d3fd507f..1b3d4f71a78 100644
--- a/chromium/components/web_package/web_bundle_parser_factory_unittest.cc
+++ b/chromium/components/web_package/web_bundle_parser_factory_unittest.cc
@@ -6,7 +6,6 @@
#include "base/files/file.h"
#include "base/files/file_path.h"
-#include "base/optional.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
@@ -15,6 +14,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace web_package {
@@ -74,14 +74,14 @@ TEST_F(WebBundleParserFactoryTest, FileDataSource) {
auto data_source = CreateFileDataSource(
remote.InitWithNewPipeAndPassReceiver(), std::move(file));
- base::Optional<std::vector<uint8_t>> result_data;
+ absl::optional<std::vector<uint8_t>> result_data;
{
base::RunLoop run_loop;
data_source->Read(
/*offset=*/0, test_length,
base::BindLambdaForTesting(
[&result_data,
- &run_loop](const base::Optional<std::vector<uint8_t>>& data) {
+ &run_loop](const absl::optional<std::vector<uint8_t>>& data) {
result_data = data;
run_loop.QuitClosure().Run();
}));
@@ -96,7 +96,7 @@ TEST_F(WebBundleParserFactoryTest, FileDataSource) {
file_length - test_length, test_length,
base::BindLambdaForTesting(
[&result_data,
- &run_loop](const base::Optional<std::vector<uint8_t>>& data) {
+ &run_loop](const absl::optional<std::vector<uint8_t>>& data) {
result_data = data;
run_loop.QuitClosure().Run();
}));
@@ -111,7 +111,7 @@ TEST_F(WebBundleParserFactoryTest, FileDataSource) {
file_length - test_length, test_length + 1,
base::BindLambdaForTesting(
[&result_data,
- &run_loop](const base::Optional<std::vector<uint8_t>>& data) {
+ &run_loop](const absl::optional<std::vector<uint8_t>>& data) {
result_data = data;
run_loop.QuitClosure().Run();
}));
@@ -126,7 +126,7 @@ TEST_F(WebBundleParserFactoryTest, FileDataSource) {
file_length + 1, test_length,
base::BindLambdaForTesting(
[&result_data,
- &run_loop](const base::Optional<std::vector<uint8_t>>& data) {
+ &run_loop](const absl::optional<std::vector<uint8_t>>& data) {
result_data = data;
run_loop.QuitClosure().Run();
}));
diff --git a/chromium/components/web_package/web_bundle_parser_fuzzer.cc b/chromium/components/web_package/web_bundle_parser_fuzzer.cc
index 116ecc669ce..8d25b61f5b3 100644
--- a/chromium/components/web_package/web_bundle_parser_fuzzer.cc
+++ b/chromium/components/web_package/web_bundle_parser_fuzzer.cc
@@ -25,7 +25,7 @@ class DataSource : public web_package::mojom::BundleDataSource {
void Read(uint64_t offset, uint64_t length, ReadCallback callback) override {
if (offset >= size_) {
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
return;
}
const uint8_t* start = data_ + offset;
diff --git a/chromium/components/web_package/web_bundle_parser_unittest.cc b/chromium/components/web_package/web_bundle_parser_unittest.cc
index 55e042a98ab..544af7558ef 100644
--- a/chromium/components/web_package/web_bundle_parser_unittest.cc
+++ b/chromium/components/web_package/web_bundle_parser_unittest.cc
@@ -6,7 +6,6 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/optional.h"
#include "base/path_service.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
@@ -14,6 +13,7 @@
#include "components/web_package/test_support/web_bundle_builder.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace web_package {
@@ -46,7 +46,7 @@ class TestDataSource : public mojom::BundleDataSource {
void Read(uint64_t offset, uint64_t length, ReadCallback callback) override {
if (offset >= data_.size()) {
- std::move(callback).Run(base::nullopt);
+ std::move(callback).Run(absl::nullopt);
return;
}
const uint8_t* start =
diff --git a/chromium/components/web_package/web_bundle_utils.h b/chromium/components/web_package/web_bundle_utils.h
index e6800398bd3..e08b86e6acb 100644
--- a/chromium/components/web_package/web_bundle_utils.h
+++ b/chromium/components/web_package/web_bundle_utils.h
@@ -14,6 +14,15 @@ class GURL;
namespace web_package {
+// The max memory limit per process of subrsource web bundles.
+//
+// Note: Currently the network service keeps the binary of the subresource web
+// bundle in the memory. To protect the network service from OOM attacks, we
+// set the max memory limit per renderer process. When the memory usage of
+// subresource web bundles exceeds the limit, the web bundle loading fails,
+// and the subresouce loading from the web bundle will fail on the page.
+constexpr uint64_t kDefaultMaxMemoryPerProcess = 10ull * 1024 * 1024;
+
network::mojom::URLResponseHeadPtr CreateResourceResponse(
const web_package::mojom::BundleResponsePtr& response);
diff --git a/chromium/components/webapk/BUILD.gn b/chromium/components/webapk/BUILD.gn
new file mode 100644
index 00000000000..a7e4ee0e6e6
--- /dev/null
+++ b/chromium/components/webapk/BUILD.gn
@@ -0,0 +1,9 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/protobuf/proto_library.gni")
+
+proto_library("proto") {
+ sources = [ "webapk.proto" ]
+}
diff --git a/chromium/components/webapk/webapk.proto b/chromium/components/webapk/webapk.proto
new file mode 100644
index 00000000000..7685ebbc2c3
--- /dev/null
+++ b/chromium/components/webapk/webapk.proto
@@ -0,0 +1,185 @@
+// 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package webapk;
+
+// Response after creating or updating a WebAPK.
+message WebApkResponse {
+ // Package name to install WebAPK at.
+ optional string package_name = 1;
+
+ // Version code of the WebAPK.
+ optional string version = 2;
+
+ // Unique id identifying session with WebAPK server.
+ optional string token = 6;
+
+ // This flag may be used, for example, if the WebAPK server is unable to
+ // fulfill an update request and likely won't be able to fulfill subsequent
+ // update requests from this WebAPK. One case where the server is unable to
+ // fulfill update requests is if the Web Manifest is dynamically generated
+ // based on the user's country etc. Therefore, we want the client to back off
+ // from spamming update requests too often.
+ optional bool relax_updates = 8;
+
+ reserved 3, 4, 5, 7;
+}
+
+// Sent as part of request to create or update a WebAPK.
+message WebApk {
+ enum UpdateReason {
+ NONE = 1;
+ OLD_SHELL_APK = 2;
+ PRIMARY_ICON_HASH_DIFFERS = 3;
+ SCOPE_DIFFERS = 5;
+ START_URL_DIFFERS = 6;
+ SHORT_NAME_DIFFERS = 7;
+ NAME_DIFFERS = 8;
+ BACKGROUND_COLOR_DIFFERS = 9;
+ THEME_COLOR_DIFFERS = 10;
+ ORIENTATION_DIFFERS = 11;
+ DISPLAY_MODE_DIFFERS = 12;
+ WEB_SHARE_TARGET_DIFFERS = 13;
+ MANUALLY_TRIGGERED = 14;
+ PRIMARY_ICON_MASKABLE_DIFFERS = 15;
+ SHORTCUTS_DIFFER = 16;
+ SPLASH_ICON_HASH_DIFFERS = 17;
+
+ reserved 4;
+ }
+
+ // Package name of the WebAPK.
+ optional string package_name = 1;
+
+ // Version code of the WebAPK.
+ optional string version = 2;
+
+ // The URL of the Web App Manifest.
+ optional string manifest_url = 3;
+
+ // Chrome's package name.
+ optional string requester_application_package = 5;
+
+ // Chrome's version.
+ optional string requester_application_version = 6;
+
+ // The Web App Manifest.
+ optional WebAppManifest manifest = 7;
+
+ // The cpu abi of the browser making the request.
+ optional string android_abi = 8;
+
+ // If set true, this flag indicates that the Web App Manifest of the site is
+ // no longer available.
+ optional bool stale_manifest = 9;
+
+ // A list of all reasons why the WebAPK needs to be updated.
+ repeated UpdateReason update_reasons = 11;
+
+ // The Android OS version (e.g '11').
+ optional string android_version = 12;
+
+ reserved 4, 10;
+}
+
+// Contains data from the Web App Manifest.
+message WebAppManifest {
+ optional string name = 1;
+ optional string short_name = 2;
+ optional string start_url = 4;
+ repeated string scopes = 5;
+ repeated Image icons = 6;
+ optional string orientation = 9;
+ optional string display_mode = 10;
+ optional string theme_color = 11;
+ optional string background_color = 12;
+ repeated ShareTarget share_targets = 17;
+ repeated ShortcutItem shortcuts = 18;
+
+ reserved 3, 7, 8, 13 to 16;
+}
+
+message Image {
+ enum Usage {
+ PRIMARY_ICON = 1;
+ BADGE_ICON = 2;
+ SPLASH_ICON = 3;
+ }
+
+ // Image's URL.
+ optional string src = 1;
+
+ // Murmur2 hash of the icon's bytes. There should not be any transformations
+ // applied to the icon's bytes prior to taking the Murmur2 hash.
+ optional string hash = 5;
+
+ // Actual bytes of the image. This image may be re-encoded from the original
+ // image and may not match the murmur2 hash field above.
+ optional bytes image_data = 6;
+
+ // Possible purposes that an icon can be used for.
+ enum Purpose {
+ // Missing purpose.
+ PURPOSE_UNDEFINED = 0;
+ // The icon can be displayed in any context.
+ ANY = 1;
+
+ // The icon can be used where a monochrome icon with a solid fill is needed.
+ // MONOCHROME = 2; This is not currently used, so ignore it.
+
+ // The icon is designed with the intention to be masked.
+ MASKABLE = 3;
+
+ reserved 2;
+ }
+
+ // The purposes this image may be used for.
+ repeated Purpose purposes = 7;
+
+ // Specifies Chrome's intended usages for the image.
+ repeated Usage usages = 8;
+
+ reserved 2, 3, 4, 9;
+}
+
+// A proto representing a ShareTargetParamsFile
+// https://wicg.github.io/web-share-target/level-2/#sharetargetfiles-and-its-members
+message ShareTargetParamsFile {
+ optional string name = 1;
+ repeated string accept = 2;
+}
+
+// A proto representing ShareTargetParams
+// https://wicg.github.io/web-share-target/#dom-sharetargetparams
+// Each field corresponds to key in ShareData. These are the query parameter
+// keys to be used for the data supplied in a ShareData instance.
+// ShareData: https://w3c.github.io/web-share#dom-sharedata
+message ShareTargetParams {
+ optional string title = 1;
+ optional string text = 2;
+ optional string url = 3;
+ repeated ShareTargetParamsFile files = 4;
+}
+
+// A proto representing a ShareTarget.
+// https://wicg.github.io/web-share-target/#dom-sharetarget
+message ShareTarget {
+ // The URL to be resolved when sharing.
+ optional string action = 2;
+ optional ShareTargetParams params = 3;
+ optional string method = 4;
+ optional string enctype = 5;
+ reserved 1;
+}
+
+message ShortcutItem {
+ optional string name = 1;
+ optional string short_name = 2;
+ optional string url = 3;
+ repeated Image icons = 4;
+}
diff --git a/chromium/components/webapps/browser/BUILD.gn b/chromium/components/webapps/browser/BUILD.gn
index 700bc4065e7..8d5afb1901c 100644
--- a/chromium/components/webapps/browser/BUILD.gn
+++ b/chromium/components/webapps/browser/BUILD.gn
@@ -95,6 +95,7 @@ source_set("browser") {
"//services/device/public/mojom",
"//ui/base",
"//ui/gfx",
+ "//url:gurl_android",
]
}
}
diff --git a/chromium/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc b/chromium/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc
index bd745b9dbf5..fadbd891369 100644
--- a/chromium/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc
+++ b/chromium/components/webapps/browser/android/add_to_homescreen_data_fetcher_unittest.cc
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
-#include "base/optional.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -28,6 +27,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_renderer_host.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
#include "ui/gfx/image/image_unittest_util.h"
@@ -174,8 +174,8 @@ class TestInstallableManager : public InstallableManager {
if (!manifest.icons.empty()) {
primary_icon_url_ = manifest_.icons[0].src;
- primary_icon_.reset(
- new SkBitmap(gfx::test::CreateBitmap(kIconSizePx, kIconSizePx)));
+ primary_icon_ = std::make_unique<SkBitmap>(
+ gfx::test::CreateBitmap(kIconSizePx, kIconSizePx));
}
}
@@ -494,7 +494,7 @@ TEST_F(AddToHomescreenDataFetcherTest, ManifestNameClobbersWebApplicationName) {
// Check the case where we have no icons.
blink::Manifest manifest = BuildDefaultManifest();
manifest.icons.clear();
- manifest.short_name = base::nullopt;
+ manifest.short_name = absl::nullopt;
SetManifest(manifest);
ObserverWaiter waiter;
@@ -508,7 +508,7 @@ TEST_F(AddToHomescreenDataFetcherTest, ManifestNameClobbersWebApplicationName) {
}
blink::Manifest manifest(BuildDefaultManifest());
- manifest.short_name = base::nullopt;
+ manifest.short_name = absl::nullopt;
SetManifest(manifest);
{
@@ -565,8 +565,8 @@ TEST_F(AddToHomescreenDataFetcherTest, ManifestNoNameNoShortName) {
// - WebApplicationInfo::title is used as the "name".
// - We still use the icons from the manifest.
blink::Manifest manifest(BuildDefaultManifest());
- manifest.name = base::nullopt;
- manifest.short_name = base::nullopt;
+ manifest.name = absl::nullopt;
+ manifest.short_name = absl::nullopt;
// Check the case where we don't time out waiting for the service worker.
SetManifest(manifest);
diff --git a/chromium/components/webapps/browser/android/android_webapps_strings.grd b/chromium/components/webapps/browser/android/android_webapps_strings.grd
index db251bb0628..a561f68ac09 100644
--- a/chromium/components/webapps/browser/android/android_webapps_strings.grd
+++ b/chromium/components/webapps/browser/android/android_webapps_strings.grd
@@ -178,10 +178,10 @@
Install
</message>
- <message name="IDS_MENU_ADD_TO_HOMESCREEN" desc="Menu item for adding a shortcut to the Home screen (default title). [CHAR-LIMIT=27]">
+ <message name="IDS_MENU_ADD_TO_HOMESCREEN" desc="Menu item for adding a shortcut to the Home screen (default title). [CHAR_LIMIT=27]">
Add to Home screen
</message>
- <message name="IDS_MENU_ADD_TO_HOMESCREEN_INSTALL" desc="Menu item for adding a shortcut to the Home screen. [CHAR-LIMIT=27]">
+ <message name="IDS_MENU_ADD_TO_HOMESCREEN_INSTALL" desc="Menu item for adding a shortcut to the Home screen. [CHAR_LIMIT=27]">
Install app
</message>
<message name="IDS_ADDED_TO_HOMESCREEN" desc="Text in a toast indicating that the website with the specified name was added to the user's Home screen.">
diff --git a/chromium/components/webapps/browser/android/app_banner_manager_android.cc b/chromium/components/webapps/browser/android/app_banner_manager_android.cc
index a1a29604e0a..360e88727df 100644
--- a/chromium/components/webapps/browser/android/app_banner_manager_android.cc
+++ b/chromium/components/webapps/browser/android/app_banner_manager_android.cc
@@ -12,7 +12,6 @@
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
-#include "base/optional.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/feature_engagement/public/feature_constants.h"
@@ -39,6 +38,7 @@
#include "content/public/browser/web_contents.h"
#include "net/base/url_util.h"
#include "skia/ext/skia_utils_base.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
using base::android::ConvertJavaStringToUTF16;
diff --git a/chromium/components/webapps/browser/android/shortcut_info.cc b/chromium/components/webapps/browser/android/shortcut_info.cc
index 17dc820e406..8bd5150f31e 100644
--- a/chromium/components/webapps/browser/android/shortcut_info.cc
+++ b/chromium/components/webapps/browser/android/shortcut_info.cc
@@ -7,9 +7,9 @@
#include <string>
#include "base/feature_list.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "components/webapps/browser/android/webapps_icon_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
namespace webapps {
diff --git a/chromium/components/webapps/browser/android/shortcut_info.h b/chromium/components/webapps/browser/android/shortcut_info.h
index beee8b9d101..b57b84bf0d0 100644
--- a/chromium/components/webapps/browser/android/shortcut_info.h
+++ b/chromium/components/webapps/browser/android/shortcut_info.h
@@ -11,8 +11,8 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "services/device/public/mojom/screen_orientation_lock_types.mojom-shared.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/skia/include/core/SkColor.h"
#include "url/gurl.h"
@@ -136,15 +136,15 @@ struct ShortcutInfo {
device::mojom::ScreenOrientationLockType orientation =
device::mojom::ScreenOrientationLockType::DEFAULT;
Source source = SOURCE_ADD_TO_HOMESCREEN_SHORTCUT;
- base::Optional<SkColor> theme_color;
- base::Optional<SkColor> background_color;
+ absl::optional<SkColor> theme_color;
+ absl::optional<SkColor> background_color;
int ideal_splash_image_size_in_px = 0;
int minimum_splash_image_size_in_px = 0;
GURL splash_image_url;
GURL best_primary_icon_url;
std::vector<std::string> icon_urls;
std::vector<GURL> screenshot_urls;
- base::Optional<ShareTarget> share_target;
+ absl::optional<ShareTarget> share_target;
// Both shortcut item related vectors have the same size.
std::vector<blink::Manifest::ShortcutItem> shortcut_items;
diff --git a/chromium/components/webapps/browser/android/translations/android_webapps_strings_az.xtb b/chromium/components/webapps/browser/android/translations/android_webapps_strings_az.xtb
index 5af20e24f2d..1c3d91913a5 100644
--- a/chromium/components/webapps/browser/android/translations/android_webapps_strings_az.xtb
+++ b/chromium/components/webapps/browser/android/translations/android_webapps_strings_az.xtb
@@ -1,7 +1,7 @@
<?xml version="1.0" ?>
<!DOCTYPE translationbundle>
<translationbundle lang="az">
-<translation id="2139186145475833000">Ev ekranına əlavə edin</translation>
+<translation id="2139186145475833000">Æsas ekrana É™lavÉ™ edin</translation>
<translation id="2478076885740497414">Tətbiqi quraşdırın</translation>
<translation id="3789841737615482174">Quraşdırın</translation>
<translation id="4665282149850138822"><ph name="NAME" /> əsas ekranınıza əlavə edildi</translation>
diff --git a/chromium/components/webapps/browser/android/webapps_icon_utils.cc b/chromium/components/webapps/browser/android/webapps_icon_utils.cc
index 55f44e24ed3..d63d342b20c 100644
--- a/chromium/components/webapps/browser/android/webapps_icon_utils.cc
+++ b/chromium/components/webapps/browser/android/webapps_icon_utils.cc
@@ -12,6 +12,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/color_analysis.h"
+#include "url/android/gurl_android.h"
#include "url/gurl.h"
using base::android::JavaParamRef;
@@ -120,8 +121,8 @@ SkBitmap WebappsIconUtils::FinalizeLauncherIconInBackground(
}
if (result.is_null()) {
- ScopedJavaLocalRef<jstring> java_url =
- base::android::ConvertUTF8ToJavaString(env, url.spec());
+ ScopedJavaLocalRef<jobject> java_url =
+ url::GURLAndroid::FromNativeGURL(env, url);
SkColor mean_color = SkColorSetRGB(0x91, 0x91, 0x91);
if (!bitmap.isNull())
diff --git a/chromium/components/webapps/browser/banners/app_banner_manager.cc b/chromium/components/webapps/browser/banners/app_banner_manager.cc
index 171a354812b..083d36ee849 100644
--- a/chromium/components/webapps/browser/banners/app_banner_manager.cc
+++ b/chromium/components/webapps/browser/banners/app_banner_manager.cc
@@ -13,7 +13,6 @@
#include "base/compiler_specific.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "base/time/time.h"
#include "components/back_forward_cache/back_forward_cache_disable.h"
@@ -33,6 +32,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/installation/installation.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -649,7 +649,7 @@ void AppBannerManager::DidActivatePortal(
void AppBannerManager::DidUpdateWebManifestURL(
content::RenderFrameHost* target_frame,
- const base::Optional<GURL>& manifest_url) {
+ const absl::optional<GURL>& manifest_url) {
GURL url = validated_url_;
switch (state_) {
case State::INACTIVE:
@@ -879,7 +879,7 @@ void AppBannerManager::ShowBanner() {
// If this is the first time that we are showing the banner for this site,
// record how long it's been since the first visit.
- base::Optional<base::Time> did_show_time =
+ absl::optional<base::Time> did_show_time =
AppBannerSettingsHelper::GetSingleBannerEvent(
web_contents(), validated_url_, GetAppIdentifier(),
AppBannerSettingsHelper::APP_BANNER_EVENT_DID_SHOW);
diff --git a/chromium/components/webapps/browser/banners/app_banner_manager.h b/chromium/components/webapps/browser/banners/app_banner_manager.h
index c0d2dc9f421..39b16f91c37 100644
--- a/chromium/components/webapps/browser/banners/app_banner_manager.h
+++ b/chromium/components/webapps/browser/banners/app_banner_manager.h
@@ -324,7 +324,7 @@ class AppBannerManager : public content::WebContentsObserver,
base::TimeTicks activation_time) override;
void DidUpdateWebManifestURL(
content::RenderFrameHost* target_frame,
- const base::Optional<GURL>& manifest_url) override;
+ const absl::optional<GURL>& manifest_url) override;
void MediaStartedPlaying(const MediaPlayerInfo& media_info,
const content::MediaPlayerId& id) override;
void MediaStoppedPlaying(
diff --git a/chromium/components/webapps/browser/banners/app_banner_settings_helper.cc b/chromium/components/webapps/browser/banners/app_banner_settings_helper.cc
index 8454e20d3a7..b96dd016e71 100644
--- a/chromium/components/webapps/browser/banners/app_banner_settings_helper.cc
+++ b/chromium/components/webapps/browser/banners/app_banner_settings_helper.cc
@@ -101,7 +101,7 @@ class AppPrefs {
base::Value::Type::DICTIONARY);
if (!dict_) {
// Don't allow more than kMaxAppsPerSite dictionaries.
- if (origin_dict_->size() < kMaxAppsPerSite) {
+ if (origin_dict_->DictSize() < kMaxAppsPerSite) {
dict_ =
origin_dict_->SetKey(package_name_or_start_url,
base::Value(base::Value::Type::DICTIONARY));
@@ -166,19 +166,19 @@ void UpdateSiteEngagementToTrigger() {
// Reports whether |event| was recorded within the |period| up until |now|.
// If we get nullopt, we cannot store any more values for |origin_url|.
// Conservatively assume we did block a banner in this case.
-base::Optional<bool> WasEventWithinPeriod(
+absl::optional<bool> WasEventWithinPeriod(
AppBannerSettingsHelper::AppBannerEvent event,
base::TimeDelta period,
content::WebContents* web_contents,
const GURL& origin_url,
const std::string& package_name_or_start_url,
base::Time now) {
- base::Optional<base::Time> event_time =
+ absl::optional<base::Time> event_time =
AppBannerSettingsHelper::GetSingleBannerEvent(
web_contents, origin_url, package_name_or_start_url, event);
if (!event_time)
- return base::nullopt;
+ return absl::nullopt;
// Null times are in the distant past, so the delta between real times and
// null events will always be greater than the limits.
@@ -196,7 +196,7 @@ struct NextInstallTextAnimation {
base::Time last_shown;
base::TimeDelta delay;
- static base::Optional<NextInstallTextAnimation> Get(
+ static absl::optional<NextInstallTextAnimation> Get(
content::WebContents* web_contents,
const GURL& scope);
@@ -206,7 +206,7 @@ struct NextInstallTextAnimation {
const GURL& scope) const;
};
-base::Optional<NextInstallTextAnimation> NextInstallTextAnimation::Get(
+absl::optional<NextInstallTextAnimation> NextInstallTextAnimation::Get(
content::WebContents* web_contents,
const GURL& scope) {
AppPrefs app_prefs(web_contents, scope, scope.spec());
@@ -216,17 +216,17 @@ base::Optional<NextInstallTextAnimation> NextInstallTextAnimation::Get(
const base::Value* next_dict =
app_prefs.dict()->FindKey(kNextInstallTextAnimation);
if (!next_dict || !next_dict->is_dict())
- return base::nullopt;
+ return absl::nullopt;
- base::Optional<base::Time> last_shown =
+ absl::optional<base::Time> last_shown =
util::ValueToTime(next_dict->FindKey(kLastShownKey));
if (!last_shown)
- return base::nullopt;
+ return absl::nullopt;
- base::Optional<base::TimeDelta> delay =
+ absl::optional<base::TimeDelta> delay =
util::ValueToTimeDelta(next_dict->FindKey(kDelayKey));
if (!delay)
- return base::nullopt;
+ return absl::nullopt;
return NextInstallTextAnimation{*last_shown, *delay};
}
@@ -322,7 +322,7 @@ bool AppBannerSettingsHelper::HasBeenInstalled(
content::WebContents* web_contents,
const GURL& origin_url,
const std::string& package_name_or_start_url) {
- base::Optional<base::Time> added_time =
+ absl::optional<base::Time> added_time =
GetSingleBannerEvent(web_contents, origin_url, package_name_or_start_url,
APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN);
@@ -336,7 +336,7 @@ bool AppBannerSettingsHelper::WasBannerRecentlyBlocked(
base::Time now) {
DCHECK(!package_name_or_start_url.empty());
- base::Optional<bool> in_period = WasEventWithinPeriod(
+ absl::optional<bool> in_period = WasEventWithinPeriod(
APP_BANNER_EVENT_DID_BLOCK,
base::TimeDelta::FromDays(gDaysAfterDismissedToShow), web_contents,
origin_url, package_name_or_start_url, now);
@@ -350,7 +350,7 @@ bool AppBannerSettingsHelper::WasBannerRecentlyIgnored(
base::Time now) {
DCHECK(!package_name_or_start_url.empty());
- base::Optional<bool> in_period = WasEventWithinPeriod(
+ absl::optional<bool> in_period = WasEventWithinPeriod(
APP_BANNER_EVENT_DID_SHOW,
base::TimeDelta::FromDays(gDaysAfterIgnoredToShow), web_contents,
origin_url, package_name_or_start_url, now);
@@ -358,7 +358,7 @@ bool AppBannerSettingsHelper::WasBannerRecentlyIgnored(
return in_period.value_or(true);
}
-base::Optional<base::Time> AppBannerSettingsHelper::GetSingleBannerEvent(
+absl::optional<base::Time> AppBannerSettingsHelper::GetSingleBannerEvent(
content::WebContents* web_contents,
const GURL& origin_url,
const std::string& package_name_or_start_url,
@@ -367,7 +367,7 @@ base::Optional<base::Time> AppBannerSettingsHelper::GetSingleBannerEvent(
AppPrefs app_prefs(web_contents, origin_url, package_name_or_start_url);
if (!app_prefs.dict())
- return base::nullopt;
+ return absl::nullopt;
base::Value* internal_time = app_prefs.dict()->FindKeyOfType(
kBannerEventKeys[event], base::Value::Type::DOUBLE);
@@ -388,7 +388,7 @@ void AppBannerSettingsHelper::RecordMinutesFromFirstVisitToShow(
const GURL& origin_url,
const std::string& package_name_or_start_url,
base::Time time) {
- base::Optional<base::Time> could_show_time =
+ absl::optional<base::Time> could_show_time =
GetSingleBannerEvent(web_contents, origin_url, package_name_or_start_url,
APP_BANNER_EVENT_COULD_SHOW);
@@ -466,7 +466,7 @@ void AppBannerSettingsHelper::UpdateFromFieldTrial() {
bool AppBannerSettingsHelper::CanShowInstallTextAnimation(
content::WebContents* web_contents,
const GURL& scope) {
- base::Optional<NextInstallTextAnimation> next_prompt =
+ absl::optional<NextInstallTextAnimation> next_prompt =
NextInstallTextAnimation::Get(web_contents, scope);
if (!next_prompt)
@@ -489,7 +489,7 @@ void AppBannerSettingsHelper::RecordInstallTextAnimationShown(
NextInstallTextAnimation next_prompt = {AppBannerManager::GetCurrentTime(),
kInitialAnimationSuppressionPeriod};
- base::Optional<NextInstallTextAnimation> last_prompt =
+ absl::optional<NextInstallTextAnimation> last_prompt =
NextInstallTextAnimation::Get(web_contents, scope);
if (last_prompt) {
next_prompt.delay =
diff --git a/chromium/components/webapps/browser/banners/app_banner_settings_helper.h b/chromium/components/webapps/browser/banners/app_banner_settings_helper.h
index 9260a01300b..49bf6203eb6 100644
--- a/chromium/components/webapps/browser/banners/app_banner_settings_helper.h
+++ b/chromium/components/webapps/browser/banners/app_banner_settings_helper.h
@@ -9,8 +9,8 @@
#include <string>
#include "base/macros.h"
-#include "base/optional.h"
#include "base/time/time.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
class BrowserContext;
@@ -125,7 +125,7 @@ class AppBannerSettingsHelper {
// Get the time that |event| was recorded, or a nullopt if it no dict to
// record yet(such as exceed max num per site) . Exposed for testing.
- static base::Optional<base::Time> GetSingleBannerEvent(
+ static absl::optional<base::Time> GetSingleBannerEvent(
content::WebContents* web_contents,
const GURL& origin_url,
const std::string& package_name_or_start_url,
diff --git a/chromium/components/webapps/browser/banners/app_banner_settings_helper_unittest.cc b/chromium/components/webapps/browser/banners/app_banner_settings_helper_unittest.cc
index b8b7d868b92..946a067a450 100644
--- a/chromium/components/webapps/browser/banners/app_banner_settings_helper_unittest.cc
+++ b/chromium/components/webapps/browser/banners/app_banner_settings_helper_unittest.cc
@@ -84,7 +84,7 @@ TEST_F(AppBannerSettingsHelperTest, SingleEvents) {
for (int event = AppBannerSettingsHelper::APP_BANNER_EVENT_COULD_SHOW;
event < AppBannerSettingsHelper::APP_BANNER_EVENT_NUM_EVENTS; ++event) {
// Check that by default, there is no event.
- base::Optional<base::Time> event_time =
+ absl::optional<base::Time> event_time =
AppBannerSettingsHelper::GetSingleBannerEvent(
web_contents(), url, kTestPackageName,
AppBannerSettingsHelper::AppBannerEvent(event));
@@ -380,7 +380,7 @@ TEST_F(AppBannerSettingsHelperTest, NulloptSingleBannerEvent) {
AppBannerSettingsHelper::RecordBannerEvent(
web_contents(), url, url_same_origin2,
AppBannerSettingsHelper::APP_BANNER_EVENT_DID_SHOW, one_day_ago);
- base::Optional<base::Time> event_time =
+ absl::optional<base::Time> event_time =
AppBannerSettingsHelper::GetSingleBannerEvent(
web_contents(), url, url_same_origin2,
AppBannerSettingsHelper::APP_BANNER_EVENT_DID_SHOW);
diff --git a/chromium/components/webapps/browser/installable/installable_manager.cc b/chromium/components/webapps/browser/installable/installable_manager.cc
index de794c4afd5..0bba7a67acc 100644
--- a/chromium/components/webapps/browser/installable/installable_manager.cc
+++ b/chromium/components/webapps/browser/installable/installable_manager.cc
@@ -11,7 +11,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
-#include "base/stl_util.h"
+#include "base/containers/contains.h"
#include "base/strings/string_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "build/build_config.h"
@@ -239,8 +239,8 @@ InstallableManager::InstallableManager(content::WebContents* web_contents)
// This is null in unit tests.
if (web_contents) {
content::StoragePartition* storage_partition =
- content::BrowserContext::GetStoragePartition(
- web_contents->GetBrowserContext(), web_contents->GetSiteInstance());
+ web_contents->GetBrowserContext()->GetStoragePartition(
+ web_contents->GetSiteInstance());
DCHECK(storage_partition);
service_worker_context_ = storage_partition->GetServiceWorkerContext();
@@ -461,7 +461,7 @@ bool InstallableManager::IsComplete(const InstallableParams& params) const {
(!params.valid_splash_icon || IsIconFetchComplete(IconUsage::kSplash));
}
-void InstallableManager::Reset(base::Optional<InstallableStatusCode> error) {
+void InstallableManager::Reset(absl::optional<InstallableStatusCode> error) {
DCHECK(!error || error.value() != NO_ERROR_DETECTED);
// Prevent any outstanding callbacks to or from this object from being called.
weak_factory_.InvalidateWeakPtrs();
@@ -965,7 +965,7 @@ void InstallableManager::DidFinishNavigation(
void InstallableManager::DidUpdateWebManifestURL(
content::RenderFrameHost* rfh,
- const base::Optional<GURL>& manifest_url) {
+ const absl::optional<GURL>& manifest_url) {
// A change in the manifest URL invalidates our entire internal state.
Reset(MANIFEST_URL_CHANGED);
}
diff --git a/chromium/components/webapps/browser/installable/installable_manager.h b/chromium/components/webapps/browser/installable/installable_manager.h
index 72d17b7c980..bb161de0b77 100644
--- a/chromium/components/webapps/browser/installable/installable_manager.h
+++ b/chromium/components/webapps/browser/installable/installable_manager.h
@@ -7,14 +7,12 @@
#include <map>
#include <memory>
-#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
#include "base/time/time.h"
#include "components/webapps/browser/installable/installable_data.h"
#include "components/webapps/browser/installable/installable_logging.h"
@@ -25,6 +23,7 @@
#include "content/public/browser/service_worker_context_observer.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"
@@ -190,7 +189,7 @@ class InstallableManager
// Called when navigating to a new page or if the WebContents is destroyed
// whilst waiting for a callback.
// If populated, the given |error| is reported to all queued tasks.
- void Reset(base::Optional<InstallableStatusCode> error = base::nullopt);
+ void Reset(absl::optional<InstallableStatusCode> error = absl::nullopt);
// Sets the fetched bit on the installable and icon subtasks.
// Called if no manifest (or an empty manifest) was fetched from the site.
@@ -240,7 +239,7 @@ class InstallableManager
void DidFinishNavigation(content::NavigationHandle* handle) override;
void DidUpdateWebManifestURL(
content::RenderFrameHost* rfh,
- const base::Optional<GURL>& manifest_url) override;
+ const absl::optional<GURL>& manifest_url) override;
void WebContentsDestroyed() override;
const GURL& manifest_url() const;
diff --git a/chromium/components/webapps/browser/installable/installable_manager_unittest.cc b/chromium/components/webapps/browser/installable/installable_manager_unittest.cc
index 1ebec1d492d..e945e8a3560 100644
--- a/chromium/components/webapps/browser/installable/installable_manager_unittest.cc
+++ b/chromium/components/webapps/browser/installable/installable_manager_unittest.cc
@@ -5,12 +5,12 @@
#include "components/webapps/browser/installable/installable_manager.h"
#include "base/feature_list.h"
-#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/public/common/content_features.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
@@ -73,16 +73,16 @@ TEST_F(InstallableManagerUnitTest, CheckMinimalValidManifest) {
TEST_F(InstallableManagerUnitTest, ManifestRequiresNameOrShortName) {
blink::Manifest manifest = GetValidManifest();
- manifest.name = base::nullopt;
+ manifest.name = absl::nullopt;
EXPECT_TRUE(IsManifestValid(manifest));
EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode());
manifest.name = u"foo";
- manifest.short_name = base::nullopt;
+ manifest.short_name = absl::nullopt;
EXPECT_TRUE(IsManifestValid(manifest));
EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode());
- manifest.name = base::nullopt;
+ manifest.name = absl::nullopt;
EXPECT_FALSE(IsManifestValid(manifest));
EXPECT_EQ(MANIFEST_MISSING_NAME_OR_SHORT_NAME, GetErrorCode());
}
diff --git a/chromium/components/webapps/browser/installable/installable_metrics.cc b/chromium/components/webapps/browser/installable/installable_metrics.cc
index ca7f7082667..85588819526 100644
--- a/chromium/components/webapps/browser/installable/installable_metrics.cc
+++ b/chromium/components/webapps/browser/installable/installable_metrics.cc
@@ -4,6 +4,7 @@
#include "components/webapps/browser/installable/installable_metrics.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "build/build_config.h"
@@ -15,8 +16,8 @@ namespace webapps {
// static
void InstallableMetrics::TrackInstallEvent(WebappInstallSource source) {
DCHECK(IsReportableInstallSource(source));
- UMA_HISTOGRAM_ENUMERATION("Webapp.Install.InstallEvent", source,
- WebappInstallSource::COUNT);
+ base::UmaHistogramEnumeration("Webapp.Install.InstallEvent", source,
+ WebappInstallSource::COUNT);
}
// static
@@ -114,4 +115,9 @@ ServiceWorkerOfflineCapability InstallableMetrics::ConvertFromOfflineCapability(
NOTREACHED();
}
+// static
+void InstallableMetrics::TrackUninstallEvent(WebappUninstallSource source) {
+ base::UmaHistogramEnumeration("Webapp.Install.UninstallEvent", source);
+}
+
} // namespace webapps
diff --git a/chromium/components/webapps/browser/installable/installable_metrics.h b/chromium/components/webapps/browser/installable/installable_metrics.h
index 2ad020cc4d1..ea320b0aaa3 100644
--- a/chromium/components/webapps/browser/installable/installable_metrics.h
+++ b/chromium/components/webapps/browser/installable/installable_metrics.h
@@ -25,6 +25,8 @@ enum class InstallTrigger {
CREATE_SHORTCUT,
};
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
// Sources for triggering webapp installation.
// NOTE: each enum entry which is reportable must be added to
// InstallableMetrics::IsReportableInstallSource().
@@ -91,6 +93,59 @@ enum class WebappInstallSource {
COUNT,
};
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+// Sources for triggering webapp uninstallation.
+enum class WebappUninstallSource {
+ // Unknown surface, potentially in ChromeOS.
+ kUnknown = 0,
+
+ // Menu item from the 3-dot menu of a WebApp window.
+ kAppMenu = 1,
+
+ // Context menu for a WebApp in chrome://apps.
+ kAppsPage = 2,
+
+ // Via OS Settings or Controls.
+ kOsSettings = 3,
+
+ // Uninstalled from Sync.
+ kSync = 4,
+
+ // App management surface, currently ChromeOS-only.
+ kAppManagement = 5,
+
+ // Migration.
+ kMigration = 6,
+
+ // App List (Launcher in ChromeOS).
+ kAppList = 7,
+
+ // Shelf (in ChromeOS).
+ kShelf = 8,
+
+ // Internally managed pre-installed app management.
+ kInternalPreinstalled = 9,
+
+ // Externally managed pre-installed app management.
+ kExternalPreinstalled = 10,
+
+ // Enterprise policy app management.
+ kExternalPolicy = 11,
+
+ // System app management on ChromeOS.
+ kSystemPreinstalled = 12,
+
+ // Placeholder app management for preinstalled apps.
+ kPlaceholderReplacement = 13,
+
+ // Externally managed Arc apps.
+ kArc = 14,
+
+ // Add any new values above this one.
+ kMaxValue = kArc,
+};
+
// This is the result of the promotability check that is recorded in the
// Webapp.CheckServiceWorker.Status histogram.
// Do not reorder or reuse any values in this enum. New values must be added to
@@ -108,7 +163,7 @@ enum class ServiceWorkerOfflineCapability {
class InstallableMetrics {
public:
- // Records |source| in the Webapp.Install.InstallSource histogram.
+ // Records |source| in the Webapp.Install.InstallEvent histogram.
// IsReportableInstallSource(|source|) must be true.
static void TrackInstallEvent(WebappInstallSource source);
@@ -140,6 +195,9 @@ class InstallableMetrics {
static ServiceWorkerOfflineCapability ConvertFromOfflineCapability(
content::OfflineCapability capability);
+ // Records |source| in the Webapp.Install.UninstallEvent histogram.
+ static void TrackUninstallEvent(WebappUninstallSource source);
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(InstallableMetrics);
};
diff --git a/chromium/components/webapps/browser/pwa_install_path_tracker.h b/chromium/components/webapps/browser/pwa_install_path_tracker.h
index 1ed9ef371a3..3755a549f7f 100644
--- a/chromium/components/webapps/browser/pwa_install_path_tracker.h
+++ b/chromium/components/webapps/browser/pwa_install_path_tracker.h
@@ -5,10 +5,8 @@
#ifndef COMPONENTS_WEBAPPS_BROWSER_PWA_INSTALL_PATH_TRACKER_H_
#define COMPONENTS_WEBAPPS_BROWSER_PWA_INSTALL_PATH_TRACKER_H_
-#include <string>
-
-#include "base/optional.h"
#include "components/webapps/browser/installable/installable_metrics.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace webapps {
diff --git a/chromium/components/webapps/services/web_app_origin_association/web_app_origin_association_parser.cc b/chromium/components/webapps/services/web_app_origin_association/web_app_origin_association_parser.cc
index 0f3d7e5b5bd..1bd0c327eee 100644
--- a/chromium/components/webapps/services/web_app_origin_association/web_app_origin_association_parser.cc
+++ b/chromium/components/webapps/services/web_app_origin_association/web_app_origin_association_parser.cc
@@ -29,7 +29,7 @@ mojom::WebAppOriginAssociationPtr WebAppOriginAssociationParser::Parse(
const std::string& data) {
auto parsed_data = base::JSONReader::ReadAndReturnValueWithError(data);
- if (parsed_data.value == base::nullopt) {
+ if (parsed_data.value == absl::nullopt) {
AddErrorInfo(parsed_data.error_message, parsed_data.error_line,
parsed_data.error_column);
failed_ = true;
@@ -89,7 +89,7 @@ WebAppOriginAssociationParser::ParseAssociatedWebApps(
continue;
}
- base::Optional<mojom::AssociatedWebAppPtr> app =
+ absl::optional<mojom::AssociatedWebAppPtr> app =
ParseAssociatedWebApp(app_item);
if (!app)
continue;
@@ -100,12 +100,12 @@ WebAppOriginAssociationParser::ParseAssociatedWebApps(
return result;
}
-base::Optional<mojom::AssociatedWebAppPtr>
+absl::optional<mojom::AssociatedWebAppPtr>
WebAppOriginAssociationParser::ParseAssociatedWebApp(
const base::Value& app_dict) {
- base::Optional<GURL> manifest_url = ParseManifestURL(app_dict);
+ absl::optional<GURL> manifest_url = ParseManifestURL(app_dict);
if (!manifest_url)
- return base::nullopt;
+ return absl::nullopt;
mojom::AssociatedWebAppPtr app = mojom::AssociatedWebApp::New();
app->manifest_url = manifest_url.value();
@@ -120,52 +120,52 @@ WebAppOriginAssociationParser::ParseAssociatedWebApp(
return app;
}
- base::Optional<std::vector<std::string>> paths =
+ absl::optional<std::vector<std::string>> paths =
ParsePaths(*app_details_value, kPathsKey);
if (paths)
app->paths = paths.value();
- base::Optional<std::vector<std::string>> exclude_paths =
+ absl::optional<std::vector<std::string>> exclude_paths =
ParsePaths(*app_details_value, kExcludePathsKey);
if (exclude_paths)
app->exclude_paths = exclude_paths.value();
return app;
}
-base::Optional<GURL> WebAppOriginAssociationParser::ParseManifestURL(
+absl::optional<GURL> WebAppOriginAssociationParser::ParseManifestURL(
const base::Value& app_dict) {
const base::Value* url_value = app_dict.FindKey(kManifestUrlKey);
if (!url_value) {
AddErrorInfo("Associated app ignored. Required property '" +
std::string(kManifestUrlKey) + "' does not exist.");
- return base::nullopt;
+ return absl::nullopt;
}
if (!url_value->is_string()) {
AddErrorInfo("Associated app ignored. Required property '" +
std::string(kManifestUrlKey) + "' is not a string.");
- return base::nullopt;
+ return absl::nullopt;
}
GURL manifest_url(url_value->GetString());
if (!manifest_url.is_valid()) {
AddErrorInfo("Associated app ignored. Required property '" +
std::string(kManifestUrlKey) + "' is not a valid URL.");
- return base::nullopt;
+ return absl::nullopt;
}
return manifest_url;
}
-base::Optional<std::vector<std::string>>
+absl::optional<std::vector<std::string>>
WebAppOriginAssociationParser::ParsePaths(const base::Value& app_details_dict,
const std::string& key) {
const base::Value* paths_value = app_details_dict.FindKey(key);
if (!paths_value)
- return base::nullopt;
+ return absl::nullopt;
if (!paths_value->is_list()) {
AddErrorInfo("Property '" + key + "' ignored, type array expected.");
- return base::nullopt;
+ return absl::nullopt;
}
std::vector<std::string> paths;
diff --git a/chromium/components/webapps/services/web_app_origin_association/web_app_origin_association_parser.h b/chromium/components/webapps/services/web_app_origin_association/web_app_origin_association_parser.h
index f2a34ebe97a..0201aff677d 100644
--- a/chromium/components/webapps/services/web_app_origin_association/web_app_origin_association_parser.h
+++ b/chromium/components/webapps/services/web_app_origin_association/web_app_origin_association_parser.h
@@ -35,10 +35,10 @@ class WebAppOriginAssociationParser {
private:
std::vector<mojom::AssociatedWebAppPtr> ParseAssociatedWebApps(
const base::Value& root_dict);
- base::Optional<mojom::AssociatedWebAppPtr> ParseAssociatedWebApp(
+ absl::optional<mojom::AssociatedWebAppPtr> ParseAssociatedWebApp(
const base::Value& app_dict);
- base::Optional<GURL> ParseManifestURL(const base::Value& app_dict);
- base::Optional<std::vector<std::string>> ParsePaths(
+ absl::optional<GURL> ParseManifestURL(const base::Value& app_dict);
+ absl::optional<std::vector<std::string>> ParsePaths(
const base::Value& app_details_dict,
const std::string& key);
void AddErrorInfo(const std::string& error_msg,
diff --git a/chromium/components/webauthn/android/fido2helper_native_android.cc b/chromium/components/webauthn/android/fido2helper_native_android.cc
index fe0d1204cc3..9193fcaa83d 100644
--- a/chromium/components/webauthn/android/fido2helper_native_android.cc
+++ b/chromium/components/webauthn/android/fido2helper_native_android.cc
@@ -30,7 +30,7 @@ static jboolean JNI_Fido2Helper_ParseAttestationObject(
JavaByteArrayToByteVector(env, jattestation_object_bytes,
&attestation_object_bytes);
- base::Optional<cbor::Value> attestation_object =
+ absl::optional<cbor::Value> attestation_object =
cbor::Reader::Read(attestation_object_bytes);
if (!attestation_object || !attestation_object->is_map()) {
return false;
@@ -66,7 +66,7 @@ static jboolean JNI_Fido2Helper_ParseAttestationObject(
ToJavaByteArray(env, auth_data));
const device::PublicKey* pub_key = result->first.public_key();
- const base::Optional<std::vector<uint8_t>>& der_bytes(pub_key->der_bytes);
+ const absl::optional<std::vector<uint8_t>>& der_bytes(pub_key->der_bytes);
ScopedJavaLocalRef<jbyteArray> spki_java;
if (der_bytes) {
spki_java.Reset(ToJavaByteArray(env, *der_bytes));
diff --git a/chromium/components/webcrypto/algorithms/asymmetric_key_util.h b/chromium/components/webcrypto/algorithms/asymmetric_key_util.h
index 8964ec1b898..2355bd3cdf9 100644
--- a/chromium/components/webcrypto/algorithms/asymmetric_key_util.h
+++ b/chromium/components/webcrypto/algorithms/asymmetric_key_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_WEBCRYPTO_ALGORITHMS_ASYMMETRIC_KEY_UTIL_
-#define COMPONENTS_WEBCRYPTO_ALGORITHMS_ASYMMETRIC_KEY_UTIL_
+#ifndef COMPONENTS_WEBCRYPTO_ALGORITHMS_ASYMMETRIC_KEY_UTIL_H_
+#define COMPONENTS_WEBCRYPTO_ALGORITHMS_ASYMMETRIC_KEY_UTIL_H_
#include "third_party/blink/public/platform/web_crypto_algorithm.h"
#include "third_party/blink/public/platform/web_crypto_key.h"
@@ -60,4 +60,4 @@ Status GetUsagesForGenerateAsymmetricKey(
} // namespace webcrypto
-#endif // COMPONENTS_WEBCRYPTO_ALGORITHMS_ASYMMETRIC_KEY_UTIL_
+#endif // COMPONENTS_WEBCRYPTO_ALGORITHMS_ASYMMETRIC_KEY_UTIL_H_
diff --git a/chromium/components/webcrypto/algorithms/secret_key_util.h b/chromium/components/webcrypto/algorithms/secret_key_util.h
index 2da1798c7aa..f0404f60bda 100644
--- a/chromium/components/webcrypto/algorithms/secret_key_util.h
+++ b/chromium/components/webcrypto/algorithms/secret_key_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_WEBCRYPTO_ALGORITHMS_SECRET_KEY_UTIL_
-#define COMPONENTS_WEBCRYPTO_ALGORITHMS_SECRET_KEY_UTIL_
+#ifndef COMPONENTS_WEBCRYPTO_ALGORITHMS_SECRET_KEY_UTIL_H_
+#define COMPONENTS_WEBCRYPTO_ALGORITHMS_SECRET_KEY_UTIL_H_
#include <stdint.h>
@@ -67,4 +67,4 @@ Status ReadSecretKeyNoExpectedAlgJwk(
} // namespace webcrypto
-#endif // COMPONENTS_WEBCRYPTO_ALGORITHMS_SECRET_KEY_UTIL_
+#endif // COMPONENTS_WEBCRYPTO_ALGORITHMS_SECRET_KEY_UTIL_H_
diff --git a/chromium/components/webcrypto/algorithms/test_helpers.cc b/chromium/components/webcrypto/algorithms/test_helpers.cc
index c981141eeea..d9afec15057 100644
--- a/chromium/components/webcrypto/algorithms/test_helpers.cc
+++ b/chromium/components/webcrypto/algorithms/test_helpers.cc
@@ -161,7 +161,7 @@ std::vector<uint8_t> MakeJsonVector(const base::DictionaryValue& dict) {
re2::RE2::GlobalReplace(&file_contents, re2::RE2("\\s*//.*"), "");
// Parse the JSON to a dictionary.
- base::Optional<base::Value> read_value =
+ absl::optional<base::Value> read_value =
base::JSONReader::Read(file_contents);
if (!read_value.has_value()) {
return ::testing::AssertionFailure()
@@ -381,17 +381,17 @@ Status ImportKeyJwkFromDict(const base::DictionaryValue& dict,
usages, key);
}
-base::Optional<base::DictionaryValue> GetJwkDictionary(
+absl::optional<base::DictionaryValue> GetJwkDictionary(
const std::vector<uint8_t>& json) {
base::StringPiece json_string(reinterpret_cast<const char*>(json.data()),
json.size());
- base::Optional<base::Value> value = base::JSONReader::Read(json_string);
+ absl::optional<base::Value> value = base::JSONReader::Read(json_string);
EXPECT_TRUE(value.has_value());
EXPECT_TRUE(value.value().is_dict());
base::DictionaryValue* dict_value = nullptr;
if (!value.value().GetAsDictionary(&dict_value))
- return base::nullopt;
+ return absl::nullopt;
return std::move(*dict_value);
}
@@ -451,8 +451,8 @@ base::Optional<base::DictionaryValue> GetJwkDictionary(
const std::string& alg_expected,
const std::string& k_expected_hex,
blink::WebCryptoKeyUsageMask use_mask_expected) {
- base::Optional<base::DictionaryValue> dict = GetJwkDictionary(json);
- if (!dict.has_value() || dict.value().empty())
+ absl::optional<base::DictionaryValue> dict = GetJwkDictionary(json);
+ if (!dict.has_value() || dict.value().DictEmpty())
return ::testing::AssertionFailure() << "JSON parsing failed";
// ---- k
@@ -478,8 +478,8 @@ base::Optional<base::DictionaryValue> GetJwkDictionary(
const std::string& n_expected_hex,
const std::string& e_expected_hex,
blink::WebCryptoKeyUsageMask use_mask_expected) {
- base::Optional<base::DictionaryValue> dict = GetJwkDictionary(json);
- if (!dict.has_value() || dict.value().empty())
+ absl::optional<base::DictionaryValue> dict = GetJwkDictionary(json);
+ if (!dict.has_value() || dict.value().DictEmpty())
return ::testing::AssertionFailure() << "JSON parsing failed";
// ---- n
diff --git a/chromium/components/webcrypto/algorithms/test_helpers.h b/chromium/components/webcrypto/algorithms/test_helpers.h
index cf031b494fb..40296348bc9 100644
--- a/chromium/components/webcrypto/algorithms/test_helpers.h
+++ b/chromium/components/webcrypto/algorithms/test_helpers.h
@@ -12,8 +12,8 @@
#include <string>
#include <vector>
-#include "base/optional.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/platform/web_crypto_algorithm.h"
#include "third_party/blink/public/platform/web_crypto_key.h"
@@ -147,7 +147,7 @@ Status ImportKeyJwkFromDict(const base::DictionaryValue& dict,
blink::WebCryptoKey* key);
// Parses a vector of JSON into a dictionary.
-base::Optional<base::DictionaryValue> GetJwkDictionary(
+absl::optional<base::DictionaryValue> GetJwkDictionary(
const std::vector<uint8_t>& json);
// Verifies the input dictionary contains the expected values. Exact matches are
diff --git a/chromium/components/webcrypto/jwk.cc b/chromium/components/webcrypto/jwk.cc
index a7700982622..08d5d0b53dd 100644
--- a/chromium/components/webcrypto/jwk.cc
+++ b/chromium/components/webcrypto/jwk.cc
@@ -207,7 +207,7 @@ Status JwkReader::Init(const CryptoData& bytes,
{
// Limit the visibility for |value| as it is moved to |dict_| (via
// |dict_value|) once it has been loaded successfully.
- base::Optional<base::Value> value = base::JSONReader::Read(json_string);
+ absl::optional<base::Value> value = base::JSONReader::Read(json_string);
base::DictionaryValue* dict_value = nullptr;
if (!value.has_value() || !value.value().GetAsDictionary(&dict_value))
@@ -331,9 +331,10 @@ Status JwkReader::GetOptionalBool(const std::string& member_name,
if (!dict_.Get(member_name, &value))
return Status::Success();
- if (!value->GetAsBoolean(result))
+ if (!value->is_bool())
return Status::ErrorJwkMemberWrongType(member_name, "boolean");
+ *result = value->GetBool();
*member_exists = true;
return Status::Success();
}
diff --git a/chromium/components/webcrypto/webcrypto_impl.cc b/chromium/components/webcrypto/webcrypto_impl.cc
index 42573f7f89f..7418b4897b8 100644
--- a/chromium/components/webcrypto/webcrypto_impl.cc
+++ b/chromium/components/webcrypto/webcrypto_impl.cc
@@ -76,7 +76,7 @@ class CryptoThreadPool {
CryptoThreadPool() : worker_thread_("WebCrypto") {
base::Thread::Options options;
options.joinable = false;
- worker_thread_.StartWithOptions(options);
+ worker_thread_.StartWithOptions(std::move(options));
}
static bool PostTask(const base::Location& from_here, base::OnceClosure task);
diff --git a/chromium/components/webdata/common/BUILD.gn b/chromium/components/webdata/common/BUILD.gn
index 86056697aea..f225e868eb7 100644
--- a/chromium/components/webdata/common/BUILD.gn
+++ b/chromium/components/webdata/common/BUILD.gn
@@ -79,6 +79,10 @@ bundle_data("unit_tests_bundle_data") {
"//components/test/data/web_database/version_89.sql",
"//components/test/data/web_database/version_90.sql",
"//components/test/data/web_database/version_91.sql",
+ "//components/test/data/web_database/version_92.sql",
+ "//components/test/data/web_database/version_93.sql",
+ "//components/test/data/web_database/version_94.sql",
+ "//components/test/data/web_database/version_95.sql",
]
outputs = [ "{{bundle_resources_dir}}/" +
"{{source_root_relative_dir}}/{{source_file_part}}" ]
diff --git a/chromium/components/webdata/common/web_data_service_base.h b/chromium/components/webdata/common/web_data_service_base.h
index 6c340d3c34c..7850557afab 100644
--- a/chromium/components/webdata/common/web_data_service_base.h
+++ b/chromium/components/webdata/common/web_data_service_base.h
@@ -6,7 +6,6 @@
#define COMPONENTS_WEBDATA_COMMON_WEB_DATA_SERVICE_BASE_H_
#include "base/callback.h"
-#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_delete_on_sequence.h"
diff --git a/chromium/components/webdata/common/web_database.cc b/chromium/components/webdata/common/web_database.cc
index d44e95946d9..f05381eb182 100644
--- a/chromium/components/webdata/common/web_database.cc
+++ b/chromium/components/webdata/common/web_database.cc
@@ -14,7 +14,7 @@
// corresponding changes must happen in the unit tests, and new migration test
// added. See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
// static
-const int WebDatabase::kCurrentVersionNumber = 92;
+const int WebDatabase::kCurrentVersionNumber = 96;
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 7ebf94d424e..f87805c6e7e 100644
--- a/chromium/components/webdata/common/web_database_migration_unittest.cc
+++ b/chromium/components/webdata/common/web_database_migration_unittest.cc
@@ -125,7 +125,7 @@ class WebDatabaseMigrationTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest);
};
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 92;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 96;
void WebDatabaseMigrationTest::LoadDatabase(
const base::FilePath::StringType& file) {
@@ -346,9 +346,10 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion53ToCurrent) {
EXPECT_EQ("00000000-0000-0000-0000-000000000001",
s_profiles.ColumnString(0));
EXPECT_EQ(u"Google, Inc.", s_profiles.ColumnString16(1));
- EXPECT_EQ(ASCIIToUTF16("1950 Charleston Rd.\n"
- "(2nd floor)"),
- s_profiles.ColumnString16(2));
+ EXPECT_EQ(
+ u"1950 Charleston Rd.\n"
+ u"(2nd floor)",
+ s_profiles.ColumnString16(2));
EXPECT_EQ(std::u16string(), s_profiles.ColumnString16(3));
EXPECT_EQ(u"Mountain View", s_profiles.ColumnString16(4));
EXPECT_EQ(u"CA", s_profiles.ColumnString16(5));
@@ -2032,8 +2033,130 @@ TEST_F(WebDatabaseMigrationTest, MigrateVersion88ToCurrent) {
// Check version.
EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
- // The card_issuer column should exist.
+ // The instrument_id column should exist.
EXPECT_TRUE(
connection.DoesColumnExist("masked_credit_cards", "instrument_id"));
}
}
+
+// Tests addition of promo code and display strings columns in offer_data table.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion93ToCurrent) {
+ ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_93.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, 93, 83));
+
+ EXPECT_FALSE(connection.DoesColumnExist("offer_data", "promo_code"));
+ EXPECT_FALSE(connection.DoesColumnExist("offer_data", "value_prop_text"));
+ EXPECT_FALSE(connection.DoesColumnExist("offer_data", "see_details_text"));
+ EXPECT_FALSE(
+ connection.DoesColumnExist("offer_data", "usage_instructions_text"));
+ }
+
+ 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));
+
+ // The new offer_data columns should exist.
+ EXPECT_TRUE(connection.DoesColumnExist("offer_data", "promo_code"));
+ EXPECT_TRUE(connection.DoesColumnExist("offer_data", "value_prop_text"));
+ EXPECT_TRUE(connection.DoesColumnExist("offer_data", "see_details_text"));
+ EXPECT_TRUE(
+ connection.DoesColumnExist("offer_data", "usage_instructions_text"));
+ }
+}
+
+// Tests addition of virtual_card_enrollment_state and card_art_url columns in
+// masked_credit_cards table.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion94ToCurrent) {
+ ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_94.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, 94, 83));
+
+ EXPECT_FALSE(connection.DoesTableExist("credit_card_art_images"));
+
+ EXPECT_FALSE(connection.DoesColumnExist("masked_credit_cards",
+ "virtual_card_enrollment_state"));
+ EXPECT_FALSE(
+ connection.DoesColumnExist("masked_credit_cards", "card_art_url"));
+ }
+
+ 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));
+
+ // The virtual_card_enrollment_state column and the card_art_url column
+ // should exist.
+ EXPECT_TRUE(connection.DoesColumnExist("masked_credit_cards",
+ "virtual_card_enrollment_state"));
+ EXPECT_TRUE(
+ connection.DoesColumnExist("masked_credit_cards", "card_art_url"));
+
+ // New columns in credit_card_art_images should exist.
+ EXPECT_TRUE(connection.DoesColumnExist("credit_card_art_images", "id"));
+ EXPECT_TRUE(
+ connection.DoesColumnExist("credit_card_art_images", "instrument_id"));
+ EXPECT_TRUE(
+ connection.DoesColumnExist("credit_card_art_images", "card_art_image"));
+ }
+}
+
+// Tests addition of lock state to the autofill_profile table.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion95ToCurrent) {
+ ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_95.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, 95, 83));
+
+ EXPECT_FALSE(connection.DoesColumnExist(
+ "autofill_profile", "disallow_settings_visible_updates"));
+ }
+
+ 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_FALSE(connection.DoesColumnExist(
+ "autofill_profile", "disallow_settings_visible_updates"));
+ }
+}
diff --git a/chromium/components/webdata_services/BUILD.gn b/chromium/components/webdata_services/BUILD.gn
index 9ca146b4a48..63e24087772 100644
--- a/chromium/components/webdata_services/BUILD.gn
+++ b/chromium/components/webdata_services/BUILD.gn
@@ -24,7 +24,15 @@ static_library("webdata_services") {
]
if (!is_ios) {
- deps += [ "//components/payments/content:utils" ]
+ sources += [
+ "web_data_service_wrapper_factory.cc",
+ "web_data_service_wrapper_factory.h",
+ ]
+ deps += [
+ "//components/keyed_service/content",
+ "//components/payments/content:utils",
+ "//content/public/browser",
+ ]
}
}
diff --git a/chromium/components/webdata_services/DEPS b/chromium/components/webdata_services/DEPS
index b83a086f4ef..ecdf718ec42 100644
--- a/chromium/components/webdata_services/DEPS
+++ b/chromium/components/webdata_services/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+components/autofill/core",
+ "+components/keyed_service/content",
"+components/keyed_service/core",
"+components/password_manager/core/browser/webdata",
"+components/payments/content",
@@ -7,6 +8,7 @@ include_rules = [
"+components/signin/public/webdata",
"+components/sync",
"+components/webdata/common",
+ "+content/public/browser",
"+sql",
"+testing/gtest",
]
diff --git a/chromium/components/webdata_services/web_data_service_wrapper_factory.cc b/chromium/components/webdata_services/web_data_service_wrapper_factory.cc
new file mode 100644
index 00000000000..4cc09674004
--- /dev/null
+++ b/chromium/components/webdata_services/web_data_service_wrapper_factory.cc
@@ -0,0 +1,68 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/webdata_services/web_data_service_wrapper_factory.h"
+
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/payments/content/payment_manifest_web_data_service.h"
+#include "components/webdata_services/web_data_service_wrapper.h"
+#include "content/public/browser/browser_context.h"
+
+namespace webdata_services {
+
+namespace {
+WebDataServiceWrapperFactory* g_instance = nullptr;
+} // namespace
+
+// static
+WebDataServiceWrapper* WebDataServiceWrapperFactory::GetForBrowserContext(
+ content::BrowserContext* context,
+ ServiceAccessType access_type) {
+ DCHECK(context);
+ DCHECK(access_type != ServiceAccessType::IMPLICIT_ACCESS ||
+ !context->IsOffTheRecord());
+ return static_cast<WebDataServiceWrapper*>(
+ GetInstance()->GetServiceForBrowserContext(context, /*create=*/true));
+}
+
+// static
+WebDataServiceWrapper*
+WebDataServiceWrapperFactory::GetForBrowserContextIfExists(
+ content::BrowserContext* context,
+ ServiceAccessType access_type) {
+ DCHECK(context);
+ DCHECK(access_type != ServiceAccessType::IMPLICIT_ACCESS ||
+ !context->IsOffTheRecord());
+ return static_cast<WebDataServiceWrapper*>(
+ GetInstance()->GetServiceForBrowserContext(context, /*create=*/false));
+}
+
+// static
+scoped_refptr<payments::PaymentManifestWebDataService>
+WebDataServiceWrapperFactory::GetPaymentManifestWebDataServiceForBrowserContext(
+ content::BrowserContext* context,
+ ServiceAccessType access_type) {
+ WebDataServiceWrapper* wrapper = GetForBrowserContext(context, access_type);
+ return wrapper ? wrapper->GetPaymentManifestWebData() : nullptr;
+}
+
+// static
+WebDataServiceWrapperFactory* WebDataServiceWrapperFactory::GetInstance() {
+ DCHECK(g_instance);
+ return g_instance;
+}
+
+WebDataServiceWrapperFactory::WebDataServiceWrapperFactory()
+ : BrowserContextKeyedServiceFactory(
+ "WebDataService",
+ BrowserContextDependencyManager::GetInstance()) {
+ DCHECK(!g_instance);
+ g_instance = this;
+}
+
+WebDataServiceWrapperFactory::~WebDataServiceWrapperFactory() {
+ g_instance = nullptr;
+}
+
+} // namespace webdata_services
diff --git a/chromium/components/webdata_services/web_data_service_wrapper_factory.h b/chromium/components/webdata_services/web_data_service_wrapper_factory.h
new file mode 100644
index 00000000000..af4e12d441e
--- /dev/null
+++ b/chromium/components/webdata_services/web_data_service_wrapper_factory.h
@@ -0,0 +1,54 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_WEBDATA_SERVICES_WEB_DATA_SERVICE_WRAPPER_FACTORY_H_
+#define COMPONENTS_WEBDATA_SERVICES_WEB_DATA_SERVICE_WRAPPER_FACTORY_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "components/keyed_service/core/service_access_type.h"
+
+namespace content {
+class BrowserContext;
+} // namespace content
+
+namespace payments {
+class PaymentManifestWebDataService;
+} // namespace payments
+
+class WebDataServiceWrapper;
+
+namespace webdata_services {
+
+// A factory that lazily returns a WebDataServiceWrapper implementation for a
+// given BrowserContext.
+class WebDataServiceWrapperFactory : public BrowserContextKeyedServiceFactory {
+ public:
+ WebDataServiceWrapperFactory(const WebDataServiceWrapperFactory&) = delete;
+ WebDataServiceWrapperFactory& operator=(const WebDataServiceWrapperFactory&) =
+ delete;
+
+ static WebDataServiceWrapper* GetForBrowserContext(
+ content::BrowserContext* context,
+ ServiceAccessType access_type);
+
+ static WebDataServiceWrapper* GetForBrowserContextIfExists(
+ content::BrowserContext* context,
+ ServiceAccessType access_type);
+
+ static scoped_refptr<payments::PaymentManifestWebDataService>
+ GetPaymentManifestWebDataServiceForBrowserContext(
+ content::BrowserContext* context,
+ ServiceAccessType access_type);
+
+ static WebDataServiceWrapperFactory* GetInstance();
+
+ protected:
+ WebDataServiceWrapperFactory();
+ ~WebDataServiceWrapperFactory() override;
+};
+
+} // namespace webdata_services
+
+#endif // COMPONENTS_WEBDATA_SERVICES_WEB_DATA_SERVICE_WRAPPER_FACTORY_H_
diff --git a/chromium/components/webrtc/media_stream_devices_controller.cc b/chromium/components/webrtc/media_stream_devices_controller.cc
index 6285c4de771..07d13512846 100644
--- a/chromium/components/webrtc/media_stream_devices_controller.cc
+++ b/chromium/components/webrtc/media_stream_devices_controller.cc
@@ -450,10 +450,10 @@ bool MediaStreamDevicesController::IsUserAcceptAllowed(
if (!window_android)
return false;
- std::vector<std::string> android_permissions;
- permissions::GetAndroidPermissionsForContentSetting(content_type,
- &android_permissions);
- for (const auto& android_permission : android_permissions) {
+ std::vector<std::string> required_android_permissions;
+ permissions::AppendRequiredAndroidPermissionsForContentSetting(
+ content_type, &required_android_permissions);
+ for (const auto& android_permission : required_android_permissions) {
if (!window_android->HasPermission(android_permission) &&
!window_android->CanRequestPermission(android_permission)) {
return false;
diff --git a/chromium/components/webrtc_logging/browser/log_cleanup.cc b/chromium/components/webrtc_logging/browser/log_cleanup.cc
index cc92f9bd985..1e8361cd13d 100644
--- a/chromium/components/webrtc_logging/browser/log_cleanup.cc
+++ b/chromium/components/webrtc_logging/browser/log_cleanup.cc
@@ -12,10 +12,10 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
-#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/scoped_blocking_call.h"
#include "components/webrtc_logging/browser/text_log_list.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace webrtc_logging {
@@ -28,7 +28,7 @@ namespace {
// be populated with the relevant values. Note that |upload_time| is optional.
bool ReadLineFromIndex(const std::string& line,
base::Time* capture_time,
- base::Optional<base::Time>* upload_time) {
+ absl::optional<base::Time>* upload_time) {
DCHECK(capture_time);
DCHECK(upload_time);
@@ -84,8 +84,8 @@ bool ReadLineFromIndex(const std::string& line,
*capture_time = base::Time::FromDoubleT(capture_time_double);
*upload_time =
has_upload_time
- ? base::make_optional(base::Time::FromDoubleT(upload_time_double))
- : base::nullopt;
+ ? absl::make_optional(base::Time::FromDoubleT(upload_time_double))
+ : absl::nullopt;
return true;
}
@@ -122,7 +122,7 @@ std::string RemoveObsoleteEntriesFromLogIndex(
const std::string line = log_index.substr(pos, line_end - pos);
base::Time capture_time;
- base::Optional<base::Time> upload_time;
+ absl::optional<base::Time> upload_time;
if (ReadLineFromIndex(line, &capture_time, &upload_time)) {
bool line_retained;
if (delete_begin_time.is_max()) {
diff --git a/chromium/components/webxr/android/BUILD.gn b/chromium/components/webxr/android/BUILD.gn
index afd2fe06041..8157608e40c 100644
--- a/chromium/components/webxr/android/BUILD.gn
+++ b/chromium/components/webxr/android/BUILD.gn
@@ -40,6 +40,7 @@ source_set("android") {
deps = [
":android_utils",
"//base",
+ "//components/infobars/android",
"//components/infobars/core",
"//components/resources:android_resources",
"//components/strings",
diff --git a/chromium/components/webxr/android/arcore_install_helper.cc b/chromium/components/webxr/android/arcore_install_helper.cc
index 9be5ab82cc2..b87a22a1e15 100644
--- a/chromium/components/webxr/android/arcore_install_helper.cc
+++ b/chromium/components/webxr/android/arcore_install_helper.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
+#include "components/infobars/android/confirm_infobar.h"
#include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_delegate.h"
#include "components/infobars/core/infobar_manager.h"
@@ -138,7 +139,7 @@ void ArCoreInstallHelper::ShowInfoBar(int render_process_id,
render_frame_id));
infobar_manager->AddInfoBar(
- infobar_manager->CreateConfirmInfoBar(std::move(delegate)));
+ std::make_unique<infobars::ConfirmInfoBar>(std::move(delegate)));
}
void ArCoreInstallHelper::OnInfoBarResponse(int render_process_id,
diff --git a/chromium/components/webxr/mailbox_to_surface_bridge_impl.cc b/chromium/components/webxr/mailbox_to_surface_bridge_impl.cc
index 8b8a70eb3f4..0290b15219d 100644
--- a/chromium/components/webxr/mailbox_to_surface_bridge_impl.cc
+++ b/chromium/components/webxr/mailbox_to_surface_bridge_impl.cc
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/system/sys_info.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
#include "components/viz/common/gpu/context_provider.h"
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/browser_task_traits.h"
diff --git a/chromium/components/webxr/mailbox_to_surface_bridge_impl.h b/chromium/components/webxr/mailbox_to_surface_bridge_impl.h
index d611c65aace..81f41e215a6 100644
--- a/chromium/components/webxr/mailbox_to_surface_bridge_impl.h
+++ b/chromium/components/webxr/mailbox_to_surface_bridge_impl.h
@@ -121,4 +121,4 @@ class MailboxToSurfaceBridgeFactoryImpl
} // namespace webxr
-#endif // COMPONENTS_WEBXR_MAILBOX_TO_SURFACE_BRIDGE_H_
+#endif // COMPONENTS_WEBXR_MAILBOX_TO_SURFACE_BRIDGE_IMPL_H_
diff --git a/chromium/components/wifi/wifi_test.cc b/chromium/components/wifi/wifi_test.cc
index 8bb0ac11f8d..b2dac9c868f 100644
--- a/chromium/components/wifi/wifi_test.cc
+++ b/chromium/components/wifi/wifi_test.cc
@@ -19,7 +19,6 @@
#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/current_thread.h"
#include "base/task/single_thread_task_executor.h"
diff --git a/chromium/components/zoom/zoom_event_manager.h b/chromium/components/zoom/zoom_event_manager.h
index 131a85b1fa7..ecddd2a7d41 100644
--- a/chromium/components/zoom/zoom_event_manager.h
+++ b/chromium/components/zoom/zoom_event_manager.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_ZOOM_ZOOM_EVENT_MANAGER_H_
#define COMPONENTS_ZOOM_ZOOM_EVENT_MANAGER_H_
-#include <memory>
-
#include "base/callback_list.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/components/zucchini/abs32_utils.cc b/chromium/components/zucchini/abs32_utils.cc
index 5d3d6ea8429..ad1c85e382d 100644
--- a/chromium/components/zucchini/abs32_utils.cc
+++ b/chromium/components/zucchini/abs32_utils.cc
@@ -110,7 +110,7 @@ Abs32RvaExtractorWin32::Abs32RvaExtractorWin32(Abs32RvaExtractorWin32&&) =
Abs32RvaExtractorWin32::~Abs32RvaExtractorWin32() = default;
-base::Optional<Abs32RvaExtractorWin32::Unit> Abs32RvaExtractorWin32::GetNext() {
+absl::optional<Abs32RvaExtractorWin32::Unit> Abs32RvaExtractorWin32::GetNext() {
while (cur_abs32_ < end_abs32_) {
offset_t location = *(cur_abs32_++);
if (!addr_.Read(location, image_))
@@ -120,7 +120,7 @@ base::Optional<Abs32RvaExtractorWin32::Unit> Abs32RvaExtractorWin32::GetNext() {
continue;
return Unit{location, target_rva};
}
- return base::nullopt;
+ return absl::nullopt;
}
/******** Abs32ReaderWin32 ********/
@@ -132,7 +132,7 @@ Abs32ReaderWin32::Abs32ReaderWin32(Abs32RvaExtractorWin32&& abs32_rva_extractor,
Abs32ReaderWin32::~Abs32ReaderWin32() = default;
-base::Optional<Reference> Abs32ReaderWin32::GetNext() {
+absl::optional<Reference> Abs32ReaderWin32::GetNext() {
for (auto unit = abs32_rva_extractor_.GetNext(); unit.has_value();
unit = abs32_rva_extractor_.GetNext()) {
offset_t location = unit->location;
@@ -140,7 +140,7 @@ base::Optional<Reference> Abs32ReaderWin32::GetNext() {
if (unsafe_target != kInvalidOffset)
return Reference{location, unsafe_target};
}
- return base::nullopt;
+ return absl::nullopt;
}
/******** Abs32WriterWin32 ********/
diff --git a/chromium/components/zucchini/abs32_utils.h b/chromium/components/zucchini/abs32_utils.h
index 5bc9cf21161..f13f562d474 100644
--- a/chromium/components/zucchini/abs32_utils.h
+++ b/chromium/components/zucchini/abs32_utils.h
@@ -11,10 +11,10 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/zucchini/address_translator.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -78,8 +78,8 @@ class Abs32RvaExtractorWin32 {
~Abs32RvaExtractorWin32();
// Visits given abs32 locations, rejects invalid locations and non-existent
- // RVAs, and returns reference as Unit, or base::nullopt on completion.
- base::Optional<Unit> GetNext();
+ // RVAs, and returns reference as Unit, or absl::nullopt on completion.
+ absl::optional<Unit> GetNext();
private:
ConstBufferView image_;
@@ -97,7 +97,7 @@ class Abs32ReaderWin32 : public ReferenceReader {
~Abs32ReaderWin32() override;
// ReferenceReader:
- base::Optional<Reference> GetNext() override;
+ absl::optional<Reference> GetNext() override;
private:
Abs32RvaExtractorWin32 abs32_rva_extractor_;
diff --git a/chromium/components/zucchini/abs32_utils_unittest.cc b/chromium/components/zucchini/abs32_utils_unittest.cc
index 77a25998e4e..ddbb685a2df 100644
--- a/chromium/components/zucchini/abs32_utils_unittest.cc
+++ b/chromium/components/zucchini/abs32_utils_unittest.cc
@@ -287,7 +287,7 @@ TEST(Abs32UtilsTest, Win32Read32) {
Abs32ReaderWin32 reader(std::move(extractor), translator);
// Loop over |expected_ref| to check element-by-element.
- base::Optional<Reference> ref;
+ absl::optional<Reference> ref;
for (const auto& expected_ref : test_case.expected_refs) {
ref = reader.GetNext();
EXPECT_TRUE(ref.has_value());
@@ -322,7 +322,7 @@ TEST(Abs32UtilsTest, Win32Read64) {
Abs32ReaderWin32 reader(std::move(extractor), translator);
std::vector<Reference> refs;
- base::Optional<Reference> ref;
+ absl::optional<Reference> ref;
for (ref = reader.GetNext(); ref.has_value(); ref = reader.GetNext())
refs.push_back(ref.value());
EXPECT_EQ(expected_refs, refs);
diff --git a/chromium/components/zucchini/disassembler.cc b/chromium/components/zucchini/disassembler.cc
index 0411791c971..4a210acde44 100644
--- a/chromium/components/zucchini/disassembler.cc
+++ b/chromium/components/zucchini/disassembler.cc
@@ -10,8 +10,8 @@ namespace zucchini {
/******** EmptyReferenceReader ********/
-base::Optional<Reference> EmptyReferenceReader::GetNext() {
- return base::nullopt;
+absl::optional<Reference> EmptyReferenceReader::GetNext() {
+ return absl::nullopt;
}
/******** EmptyReferenceWriter ********/
diff --git a/chromium/components/zucchini/disassembler.h b/chromium/components/zucchini/disassembler.h
index 52c69a47fe2..8fd5a3ac462 100644
--- a/chromium/components/zucchini/disassembler.h
+++ b/chromium/components/zucchini/disassembler.h
@@ -20,7 +20,7 @@ namespace zucchini {
// A vacuous ReferenceReader that produces no references.
class EmptyReferenceReader : public ReferenceReader {
public:
- base::Optional<Reference> GetNext() override;
+ absl::optional<Reference> GetNext() override;
};
// A vacuous EmptyReferenceWriter that does not write.
diff --git a/chromium/components/zucchini/disassembler_dex.cc b/chromium/components/zucchini/disassembler_dex.cc
index 373d6457d79..256ccdeb931 100644
--- a/chromium/components/zucchini/disassembler_dex.cc
+++ b/chromium/components/zucchini/disassembler_dex.cc
@@ -18,11 +18,11 @@
#include "base/callback.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
-#include "base/optional.h"
#include "base/strings/stringprintf.h"
#include "components/zucchini/buffer_source.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/io_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -363,13 +363,13 @@ class InstructionReferenceReader : public ReferenceReader {
}
// ReferenceReader:
- base::Optional<Reference> GetNext() override {
+ absl::optional<Reference> GetNext() override {
while (true) {
while (parser_.ReadNext()) {
const auto& v = parser_.value();
DCHECK_NE(v.instr, nullptr);
if (v.instr_offset >= hi_)
- return base::nullopt;
+ return absl::nullopt;
const offset_t location = filter_.Run(v);
if (location == kInvalidOffset || location < lo_)
continue;
@@ -377,7 +377,7 @@ class InstructionReferenceReader : public ReferenceReader {
// assumption |hi_| and |lo_| do not straddle the body of a Reference.
// So |reference_width| is unneeded.
if (location >= hi_)
- return base::nullopt;
+ return absl::nullopt;
offset_t target = mapper_.Run(location);
if (target != kInvalidOffset)
return Reference{location, target};
@@ -386,7 +386,7 @@ class InstructionReferenceReader : public ReferenceReader {
}
++cur_it_;
if (cur_it_ == end_it_)
- return base::nullopt;
+ return absl::nullopt;
parser_ = InstructionParser(image_, *cur_it_);
}
}
@@ -447,7 +447,7 @@ class ItemReferenceReader : public ReferenceReader {
}
// ReferenceReader:
- base::Optional<Reference> GetNext() override {
+ absl::optional<Reference> GetNext() override {
while (cur_idx_ < num_items_) {
const offset_t item_offset = OffsetOfIndex(cur_idx_);
const offset_t location = item_offset + rel_location_;
@@ -478,7 +478,7 @@ class ItemReferenceReader : public ReferenceReader {
++cur_idx_;
return Reference{location, target};
}
- return base::nullopt;
+ return absl::nullopt;
}
private:
@@ -631,7 +631,7 @@ class CachedItemListReferenceReader : public ReferenceReader {
}
// ReferenceReader:
- base::Optional<Reference> GetNext() override {
+ absl::optional<Reference> GetNext() override {
while (cur_it_ < end_it_) {
const offset_t location = *cur_it_ + rel_location_;
if (location >= hi_) // Check is simplified by atomicity assumption.
@@ -649,7 +649,7 @@ class CachedItemListReferenceReader : public ReferenceReader {
continue;
return Reference{location, target};
}
- return base::nullopt;
+ return absl::nullopt;
}
private:
diff --git a/chromium/components/zucchini/disassembler_elf.h b/chromium/components/zucchini/disassembler_elf.h
index e279c291092..60d524ce06a 100644
--- a/chromium/components/zucchini/disassembler_elf.h
+++ b/chromium/components/zucchini/disassembler_elf.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <deque>
#include <memory>
#include <string>
#include <vector>
@@ -178,7 +179,8 @@ class DisassemblerElfIntel : public DisassemblerElf<Traits> {
private:
// Sorted file offsets of rel32 locations.
- std::vector<offset_t> rel32_locations_;
+ // Using std::deque to reduce peak memory footprint.
+ std::deque<offset_t> rel32_locations_;
DISALLOW_COPY_AND_ASSIGN(DisassemblerElfIntel);
};
diff --git a/chromium/components/zucchini/disassembler_win32.h b/chromium/components/zucchini/disassembler_win32.h
index 6c7ba91ceaa..8f9fd58a518 100644
--- a/chromium/components/zucchini/disassembler_win32.h
+++ b/chromium/components/zucchini/disassembler_win32.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <deque>
#include <memory>
#include <string>
#include <utility>
@@ -108,7 +109,8 @@ class DisassemblerWin32 : public Disassembler {
std::vector<offset_t> reloc_block_offsets_;
offset_t reloc_end_ = 0;
std::vector<offset_t> abs32_locations_;
- std::vector<offset_t> rel32_locations_;
+ // Using std::deque to reduce peak memory footprint.
+ std::deque<offset_t> rel32_locations_;
// Initialization states of reference storage, used for lazy initialization.
// TODO(huangs): Investigate whether lazy initialization is useful for memory
diff --git a/chromium/components/zucchini/disassembler_ztf.cc b/chromium/components/zucchini/disassembler_ztf.cc
index c54a7b02f2e..f822d8b14e2 100644
--- a/chromium/components/zucchini/disassembler_ztf.cc
+++ b/chromium/components/zucchini/disassembler_ztf.cc
@@ -290,7 +290,7 @@ class ZtfReferenceReader : public ReferenceReader {
// Walks |offset_| from |lo| to |hi_| running |parser_|. If any matches are
// found they are returned.
- base::Optional<Reference> GetNext() override {
+ absl::optional<Reference> GetNext() override {
T line_col;
for (; offset_ < hi_; ++offset_) {
if (!parser_.MatchAtOffset(offset_, &line_col))
@@ -304,7 +304,7 @@ class ZtfReferenceReader : public ReferenceReader {
offset_ += config_.Width(line_col);
return Reference{location, target};
}
- return base::nullopt;
+ return absl::nullopt;
}
private:
@@ -456,12 +456,12 @@ offset_t ZtfTranslator::LineColToOffset(ztf::LineCol lc) const {
return target;
}
-base::Optional<ztf::LineCol> ZtfTranslator::OffsetToLineCol(
+absl::optional<ztf::LineCol> ZtfTranslator::OffsetToLineCol(
offset_t offset) const {
DCHECK(!line_starts_.empty());
// Don't place a target outside the image.
if (offset >= line_starts_.back())
- return base::nullopt;
+ return absl::nullopt;
auto it = SearchForRange(offset);
ztf::LineCol lc;
lc.line = std::distance(line_starts_.cbegin(), it) + 1;
diff --git a/chromium/components/zucchini/disassembler_ztf.h b/chromium/components/zucchini/disassembler_ztf.h
index 0719093792d..adbead52d19 100644
--- a/chromium/components/zucchini/disassembler_ztf.h
+++ b/chromium/components/zucchini/disassembler_ztf.h
@@ -13,10 +13,10 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/zucchini/disassembler.h"
#include "components/zucchini/image_utils.h"
#include "components/zucchini/type_ztf.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -97,8 +97,8 @@ class ZtfTranslator {
offset_t LineColToOffset(ztf::LineCol line_col) const;
// Returns the ztf::LineCol for an |offset| if it is valid. Otherwise returns
- // base::nullopt.
- base::Optional<ztf::LineCol> OffsetToLineCol(offset_t offset) const;
+ // absl::nullopt.
+ absl::optional<ztf::LineCol> OffsetToLineCol(offset_t offset) const;
private:
// Returns an iterator to the range containing |offset|. Which is represented
diff --git a/chromium/components/zucchini/element_detection.cc b/chromium/components/zucchini/element_detection.cc
index bec16be36dd..8682c787340 100644
--- a/chromium/components/zucchini/element_detection.cc
+++ b/chromium/components/zucchini/element_detection.cc
@@ -118,11 +118,11 @@ std::unique_ptr<Disassembler> MakeDisassemblerOfType(ConstBufferView image,
}
}
-base::Optional<Element> DetectElementFromDisassembler(ConstBufferView image) {
+absl::optional<Element> DetectElementFromDisassembler(ConstBufferView image) {
std::unique_ptr<Disassembler> disasm = MakeDisassemblerWithoutFallback(image);
if (disasm)
return Element({0, disasm->size()}, disasm->GetExeType());
- return base::nullopt;
+ return absl::nullopt;
}
/******** ProgramScanner ********/
@@ -132,18 +132,18 @@ ElementFinder::ElementFinder(ConstBufferView image, ElementDetector&& detector)
ElementFinder::~ElementFinder() = default;
-base::Optional<Element> ElementFinder::GetNext() {
+absl::optional<Element> ElementFinder::GetNext() {
for (; pos_ < image_.size(); ++pos_) {
ConstBufferView test_image =
ConstBufferView::FromRange(image_.begin() + pos_, image_.end());
- base::Optional<Element> element = detector_.Run(test_image);
+ absl::optional<Element> element = detector_.Run(test_image);
if (element) {
element->offset += pos_;
pos_ = element->EndOffset();
return element;
}
}
- return base::nullopt;
+ return absl::nullopt;
}
} // namespace zucchini
diff --git a/chromium/components/zucchini/element_detection.h b/chromium/components/zucchini/element_detection.h
index f90c03326fa..d3dcb470d6e 100644
--- a/chromium/components/zucchini/element_detection.h
+++ b/chromium/components/zucchini/element_detection.h
@@ -11,9 +11,9 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -32,10 +32,10 @@ std::unique_ptr<Disassembler> MakeDisassemblerOfType(ConstBufferView image,
// Attempts to detect an element associated with |image| and returns it, or
// returns nullopt if no element is detected.
using ElementDetector =
- base::RepeatingCallback<base::Optional<Element>(ConstBufferView image)>;
+ base::RepeatingCallback<absl::optional<Element>(ConstBufferView image)>;
// Implementation of ElementDetector using disassemblers.
-base::Optional<Element> DetectElementFromDisassembler(ConstBufferView image);
+absl::optional<Element> DetectElementFromDisassembler(ConstBufferView image);
// A class to scan through an image and iteratively detect elements.
class ElementFinder {
@@ -45,7 +45,7 @@ class ElementFinder {
// Scans for the next executable using |detector|. Returns the next element
// found, or nullopt if no more element can be found.
- base::Optional<Element> GetNext();
+ absl::optional<Element> GetNext();
private:
ConstBufferView image_;
diff --git a/chromium/components/zucchini/element_detection_unittest.cc b/chromium/components/zucchini/element_detection_unittest.cc
index 769c839d882..319a88a9f46 100644
--- a/chromium/components/zucchini/element_detection_unittest.cc
+++ b/chromium/components/zucchini/element_detection_unittest.cc
@@ -45,7 +45,7 @@ class ElementDetectionTest : public ::testing::Test {
image,
base::BindRepeating(
[](ExeTypeMap exe_map, ConstBufferView image,
- ConstBufferView region) -> base::Optional<Element> {
+ ConstBufferView region) -> absl::optional<Element> {
EXPECT_GE(region.begin(), image.begin());
EXPECT_LE(region.end(), image.end());
EXPECT_GE(region.size(), 0U);
@@ -56,7 +56,7 @@ class ElementDetectionTest : public ::testing::Test {
++length;
return Element{{0, length}, exe_map[region[0]]};
}
- return base::nullopt;
+ return absl::nullopt;
},
exe_map_, image));
std::vector<Element> elements;
@@ -74,10 +74,10 @@ TEST_F(ElementDetectionTest, ElementFinderEmpty) {
std::vector<uint8_t> buffer(10, 0);
ElementFinder finder(
ConstBufferView(buffer.data(), buffer.size()),
- base::BindRepeating([](ConstBufferView image) -> base::Optional<Element> {
- return base::nullopt;
+ base::BindRepeating([](ConstBufferView image) -> absl::optional<Element> {
+ return absl::nullopt;
}));
- EXPECT_EQ(base::nullopt, finder.GetNext());
+ EXPECT_EQ(absl::nullopt, finder.GetNext());
}
TEST_F(ElementDetectionTest, ElementFinder) {
diff --git a/chromium/components/zucchini/ensemble_matcher.cc b/chromium/components/zucchini/ensemble_matcher.cc
index 42079d617a8..0ed8a2a72bd 100644
--- a/chromium/components/zucchini/ensemble_matcher.cc
+++ b/chromium/components/zucchini/ensemble_matcher.cc
@@ -9,7 +9,6 @@
#include "base/logging.h"
#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
namespace zucchini {
diff --git a/chromium/components/zucchini/fuzzers/BUILD.gn b/chromium/components/zucchini/fuzzers/BUILD.gn
index 613ac99add2..90c436e8aca 100644
--- a/chromium/components/zucchini/fuzzers/BUILD.gn
+++ b/chromium/components/zucchini/fuzzers/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("//build/config/python.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/protobuf/proto_library.gni")
@@ -72,8 +71,7 @@ proto_library("zucchini_file_pair_proto") {
# Disabled on Windows due to crbug/844826.
if (current_toolchain == host_toolchain && !is_win) {
# Raw Apply Fuzzer Seed:
- # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
- python2_action("zucchini_raw_apply_seed") {
+ action("zucchini_raw_apply_seed") {
script = "generate_fuzzer_data.py"
args = [
@@ -109,8 +107,7 @@ if (current_toolchain == host_toolchain && !is_win) {
}
# ZTF Apply Fuzzer Seed:
- # TODO(crbug.com/1112471): Get this to run cleanly under Python 3.
- python2_action("zucchini_ztf_apply_seed") {
+ action("zucchini_ztf_apply_seed") {
script = "generate_fuzzer_data.py"
# *.ztf files are expected to be valid ZTF format.
diff --git a/chromium/components/zucchini/heuristic_ensemble_matcher.cc b/chromium/components/zucchini/heuristic_ensemble_matcher.cc
index d6acdbd8355..c812cb4bdcb 100644
--- a/chromium/components/zucchini/heuristic_ensemble_matcher.cc
+++ b/chromium/components/zucchini/heuristic_ensemble_matcher.cc
@@ -26,9 +26,9 @@ namespace {
/******** Helper Functions ********/
// Uses |detector| to find embedded executables inside |image|, and returns the
-// result on success, or base::nullopt on failure, which occurs if too many (>
+// result on success, or absl::nullopt on failure, which occurs if too many (>
// |kElementLimit|) elements are found.
-base::Optional<std::vector<Element>> FindEmbeddedElements(
+absl::optional<std::vector<Element>> FindEmbeddedElements(
ConstBufferView image,
const std::string& name,
ElementDetector&& detector) {
@@ -46,7 +46,7 @@ base::Optional<std::vector<Element>> FindEmbeddedElements(
}
if (elements.size() >= kElementLimit) {
LOG(WARNING) << name << ": Found too many elements.";
- return base::nullopt;
+ return absl::nullopt;
}
LOG(INFO) << name << ": Found " << elements.size() << " elements.";
return elements;
@@ -246,12 +246,12 @@ bool HeuristicEnsembleMatcher::RunMatch(ConstBufferView old_image,
LOG(INFO) << "Start matching.";
// Find all elements in "old" and "new".
- base::Optional<std::vector<Element>> old_elements =
+ absl::optional<std::vector<Element>> old_elements =
FindEmbeddedElements(old_image, "Old file",
base::BindRepeating(DetectElementFromDisassembler));
if (!old_elements.has_value())
return false;
- base::Optional<std::vector<Element>> new_elements =
+ absl::optional<std::vector<Element>> new_elements =
FindEmbeddedElements(new_image, "New file",
base::BindRepeating(DetectElementFromDisassembler));
if (!new_elements.has_value())
diff --git a/chromium/components/zucchini/image_utils.h b/chromium/components/zucchini/image_utils.h
index b34b9dcc243..3d4a83ac7e7 100644
--- a/chromium/components/zucchini/image_utils.h
+++ b/chromium/components/zucchini/image_utils.h
@@ -13,10 +13,10 @@
#include "base/format_macros.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
-#include "base/optional.h"
#include "base/strings/stringprintf.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/typed_value.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -94,7 +94,7 @@ class ReferenceReader {
// Returns the next available Reference, or nullopt_t if exhausted.
// Extracted References must be ordered by their location in the image.
- virtual base::Optional<Reference> GetNext() = 0;
+ virtual absl::optional<Reference> GetNext() = 0;
};
// Interface for writing References through member function
diff --git a/chromium/components/zucchini/imposed_ensemble_matcher.cc b/chromium/components/zucchini/imposed_ensemble_matcher.cc
index e735bc4e79e..1c1301b0653 100644
--- a/chromium/components/zucchini/imposed_ensemble_matcher.cc
+++ b/chromium/components/zucchini/imposed_ensemble_matcher.cc
@@ -89,8 +89,8 @@ ImposedMatchParser::Status ImposedMatchParser::Parse(
continue;
}
// Check executable types of sub-images.
- base::Optional<Element> old_element = detector.Run(old_sub_image);
- base::Optional<Element> new_element = detector.Run(new_sub_image);
+ absl::optional<Element> old_element = detector.Run(old_sub_image);
+ absl::optional<Element> new_element = detector.Run(new_sub_image);
if (!old_element || !new_element) {
// Skip unknown types, including those mixed with known types.
bad_matches_.push_back(matches_[read_idx]);
diff --git a/chromium/components/zucchini/imposed_ensemble_matcher_unittest.cc b/chromium/components/zucchini/imposed_ensemble_matcher_unittest.cc
index 85f1016447c..9a6dc7d0fbf 100644
--- a/chromium/components/zucchini/imposed_ensemble_matcher_unittest.cc
+++ b/chromium/components/zucchini/imposed_ensemble_matcher_unittest.cc
@@ -14,12 +14,12 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/check_op.h"
-#include "base/optional.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/disassembler.h"
#include "components/zucchini/element_detection.h"
#include "components/zucchini/image_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -36,14 +36,14 @@ class TestElementDetector {
public:
TestElementDetector() {}
- base::Optional<Element> Run(ConstBufferView image) const {
+ absl::optional<Element> Run(ConstBufferView image) const {
DCHECK_GT(image.size(), 0U);
char first_char = *image.begin();
if (first_char == 'W' || first_char == 'w')
return Element(image.local_region(), kExeTypeWin32X86);
if (first_char == 'E' || first_char == 'e')
return Element(image.local_region(), kExeTypeElfX86);
- return base::nullopt;
+ return absl::nullopt;
}
};
diff --git a/chromium/components/zucchini/integration_test.cc b/chromium/components/zucchini/integration_test.cc
index 2d2e61f7456..1baccc351b3 100644
--- a/chromium/components/zucchini/integration_test.cc
+++ b/chromium/components/zucchini/integration_test.cc
@@ -10,13 +10,13 @@
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
-#include "base/optional.h"
#include "base/path_service.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/patch_reader.h"
#include "components/zucchini/patch_writer.h"
#include "components/zucchini/zucchini.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -59,7 +59,7 @@ void TestGenApply(const std::string& old_filename,
patch_writer.SerializeInto({patch_buffer.data(), patch_buffer.size()});
// Read back generated patch.
- base::Optional<EnsemblePatchReader> patch_reader =
+ absl::optional<EnsemblePatchReader> patch_reader =
EnsemblePatchReader::Create({patch_buffer.data(), patch_buffer.size()});
ASSERT_TRUE(patch_reader.has_value());
diff --git a/chromium/components/zucchini/main_utils.h b/chromium/components/zucchini/main_utils.h
index addb8302406..6c97aad7674 100644
--- a/chromium/components/zucchini/main_utils.h
+++ b/chromium/components/zucchini/main_utils.h
@@ -7,7 +7,6 @@
#include <iosfwd>
-#include "base/files/file_path.h"
#include "components/zucchini/zucchini.h"
// Utilities to run Zucchini command based on command-line input, and to print
diff --git a/chromium/components/zucchini/patch_reader.cc b/chromium/components/zucchini/patch_reader.cc
index 3ec17e45487..99951da1742 100644
--- a/chromium/components/zucchini/patch_reader.cc
+++ b/chromium/components/zucchini/patch_reader.cc
@@ -78,42 +78,42 @@ bool EquivalenceSource::Initialize(BufferSource* source) {
patch::ParseBuffer(source, &copy_count_);
}
-base::Optional<Equivalence> EquivalenceSource::GetNext() {
+absl::optional<Equivalence> EquivalenceSource::GetNext() {
if (src_skip_.empty() || dst_skip_.empty() || copy_count_.empty())
- return base::nullopt;
+ return absl::nullopt;
Equivalence equivalence = {};
uint32_t length = 0;
if (!patch::ParseVarUInt<uint32_t>(&copy_count_, &length))
- return base::nullopt;
+ return absl::nullopt;
equivalence.length = base::strict_cast<offset_t>(length);
int32_t src_offset_diff = 0; // Intentionally signed.
if (!patch::ParseVarInt<int32_t>(&src_skip_, &src_offset_diff))
- return base::nullopt;
+ return absl::nullopt;
base::CheckedNumeric<offset_t> src_offset =
previous_src_offset_ + src_offset_diff;
if (!src_offset.IsValid())
- return base::nullopt;
+ return absl::nullopt;
equivalence.src_offset = src_offset.ValueOrDie();
previous_src_offset_ = src_offset + equivalence.length;
if (!previous_src_offset_.IsValid())
- return base::nullopt;
+ return absl::nullopt;
uint32_t dst_offset_diff = 0; // Intentionally unsigned.
if (!patch::ParseVarUInt<uint32_t>(&dst_skip_, &dst_offset_diff))
- return base::nullopt;
+ return absl::nullopt;
base::CheckedNumeric<offset_t> dst_offset =
previous_dst_offset_ + dst_offset_diff;
if (!dst_offset.IsValid())
- return base::nullopt;
+ return absl::nullopt;
equivalence.dst_offset = dst_offset.ValueOrDie();
previous_dst_offset_ = equivalence.dst_offset + equivalence.length;
if (!previous_dst_offset_.IsValid())
- return base::nullopt;
+ return absl::nullopt;
// Caveat: |equivalence| is assumed to be safe only once the
// ValidateEquivalencesAndExtraData() method has returned true. Prior to this
@@ -131,10 +131,10 @@ bool ExtraDataSource::Initialize(BufferSource* source) {
return patch::ParseBuffer(source, &extra_data_);
}
-base::Optional<ConstBufferView> ExtraDataSource::GetNext(offset_t size) {
+absl::optional<ConstBufferView> ExtraDataSource::GetNext(offset_t size) {
ConstBufferView buffer;
if (!extra_data_.GetRegion(size, &buffer))
- return base::nullopt;
+ return absl::nullopt;
// |buffer| is assumed to always be safe/valid.
return buffer;
}
@@ -150,32 +150,32 @@ bool RawDeltaSource::Initialize(BufferSource* source) {
patch::ParseBuffer(source, &raw_delta_diff_);
}
-base::Optional<RawDeltaUnit> RawDeltaSource::GetNext() {
+absl::optional<RawDeltaUnit> RawDeltaSource::GetNext() {
if (raw_delta_skip_.empty() || raw_delta_diff_.empty())
- return base::nullopt;
+ return absl::nullopt;
RawDeltaUnit raw_delta = {};
uint32_t copy_offset_diff = 0;
if (!patch::ParseVarUInt<uint32_t>(&raw_delta_skip_, &copy_offset_diff))
- return base::nullopt;
+ return absl::nullopt;
base::CheckedNumeric<offset_t> copy_offset =
copy_offset_diff + copy_offset_compensation_;
if (!copy_offset.IsValid())
- return base::nullopt;
+ return absl::nullopt;
raw_delta.copy_offset = copy_offset.ValueOrDie();
if (!raw_delta_diff_.GetValue<int8_t>(&raw_delta.diff))
- return base::nullopt;
+ return absl::nullopt;
// A 0 value for a delta.diff is considered invalid since it has no meaning.
if (!raw_delta.diff)
- return base::nullopt;
+ return absl::nullopt;
// We keep track of the compensation needed for next offset, taking into
// account delta encoding and bias of -1.
copy_offset_compensation_ = copy_offset + 1;
if (!copy_offset_compensation_.IsValid())
- return base::nullopt;
+ return absl::nullopt;
// |raw_delta| is assumed to always be safe/valid.
return raw_delta;
}
@@ -191,12 +191,12 @@ bool ReferenceDeltaSource::Initialize(BufferSource* source) {
return patch::ParseBuffer(source, &source_);
}
-base::Optional<int32_t> ReferenceDeltaSource::GetNext() {
+absl::optional<int32_t> ReferenceDeltaSource::GetNext() {
if (source_.empty())
- return base::nullopt;
+ return absl::nullopt;
int32_t ref_delta = 0;
if (!patch::ParseVarInt<int32_t>(&source_, &ref_delta))
- return base::nullopt;
+ return absl::nullopt;
// |ref_delta| is assumed to always be safe/valid.
return ref_delta;
}
@@ -211,22 +211,22 @@ bool TargetSource::Initialize(BufferSource* source) {
return patch::ParseBuffer(source, &extra_targets_);
}
-base::Optional<offset_t> TargetSource::GetNext() {
+absl::optional<offset_t> TargetSource::GetNext() {
if (extra_targets_.empty())
- return base::nullopt;
+ return absl::nullopt;
uint32_t target_diff = 0;
if (!patch::ParseVarUInt<uint32_t>(&extra_targets_, &target_diff))
- return base::nullopt;
+ return absl::nullopt;
base::CheckedNumeric<offset_t> target = target_diff + target_compensation_;
if (!target.IsValid())
- return base::nullopt;
+ return absl::nullopt;
// We keep track of the compensation needed for next target, taking into
// account delta encoding and bias of -1.
target_compensation_ = target + 1;
if (!target_compensation_.IsValid())
- return base::nullopt;
+ return absl::nullopt;
// Caveat: |target| will be a valid offset_t, but it's up to the caller to
// check whether it's a valid offset for an image.
return offset_t(target.ValueOrDie());
@@ -312,12 +312,12 @@ bool PatchElementReader::ValidateEquivalencesAndExtraData() {
/******** EnsemblePatchReader ********/
-base::Optional<EnsemblePatchReader> EnsemblePatchReader::Create(
+absl::optional<EnsemblePatchReader> EnsemblePatchReader::Create(
ConstBufferView buffer) {
BufferSource source(buffer);
EnsemblePatchReader patch;
if (!patch.Initialize(&source))
- return base::nullopt;
+ return absl::nullopt;
return patch;
}
diff --git a/chromium/components/zucchini/patch_reader.h b/chromium/components/zucchini/patch_reader.h
index 515da500144..93d64b04747 100644
--- a/chromium/components/zucchini/patch_reader.h
+++ b/chromium/components/zucchini/patch_reader.h
@@ -14,11 +14,11 @@
#include "base/debug/stack_trace.h"
#include "base/logging.h"
#include "base/numerics/checked_math.h"
-#include "base/optional.h"
#include "components/zucchini/buffer_source.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.h"
#include "components/zucchini/patch_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -77,8 +77,8 @@ bool ParseVarInt(BufferSource* source, T* value) {
// - bool Initialize(BufferSource* source): Consumes data from BufferSource and
// initializes internal states. Returns true if successful, and false
// otherwise (|source| may be partially consumed).
-// - base::Optional<MAIN_TYPE> GetNext(OPT_PARAMS): Decodes consumed data and
-// returns the next item as base::Optional (returns base::nullopt on failure).
+// - absl::optional<MAIN_TYPE> GetNext(OPT_PARAMS): Decodes consumed data and
+// returns the next item as absl::optional (returns absl::nullopt on failure).
// - bool Done() const: Returns true if no more items remain; otherwise false.
//
// Usage of *Source instances don't mix, and GetNext() have dissimilar
@@ -94,7 +94,7 @@ class EquivalenceSource {
// Core functions.
bool Initialize(BufferSource* source);
- base::Optional<Equivalence> GetNext();
+ absl::optional<Equivalence> GetNext();
bool Done() const {
return src_skip_.empty() && dst_skip_.empty() && copy_count_.empty();
}
@@ -123,7 +123,7 @@ class ExtraDataSource {
// Core functions.
bool Initialize(BufferSource* source);
// |size| is the size in bytes of the buffer requested.
- base::Optional<ConstBufferView> GetNext(offset_t size);
+ absl::optional<ConstBufferView> GetNext(offset_t size);
bool Done() const { return extra_data_.empty(); }
// Accessors for unittest.
@@ -142,7 +142,7 @@ class RawDeltaSource {
// Core functions.
bool Initialize(BufferSource* source);
- base::Optional<RawDeltaUnit> GetNext();
+ absl::optional<RawDeltaUnit> GetNext();
bool Done() const {
return raw_delta_skip_.empty() && raw_delta_diff_.empty();
}
@@ -167,7 +167,7 @@ class ReferenceDeltaSource {
// Core functions.
bool Initialize(BufferSource* source);
- base::Optional<int32_t> GetNext();
+ absl::optional<int32_t> GetNext();
bool Done() const { return source_.empty(); }
// Accessors for unittest.
@@ -186,7 +186,7 @@ class TargetSource {
// Core functions.
bool Initialize(BufferSource* source);
- base::Optional<offset_t> GetNext();
+ absl::optional<offset_t> GetNext();
bool Done() const { return extra_targets_.empty(); }
// Accessors for unittest.
@@ -256,8 +256,8 @@ class PatchElementReader {
class EnsemblePatchReader {
public:
// If data read from |buffer| is well-formed, initializes and returns
- // an instance of EnsemblePatchReader. Otherwise returns base::nullopt.
- static base::Optional<EnsemblePatchReader> Create(ConstBufferView buffer);
+ // an instance of EnsemblePatchReader. Otherwise returns absl::nullopt.
+ static absl::optional<EnsemblePatchReader> Create(ConstBufferView buffer);
EnsemblePatchReader();
EnsemblePatchReader(EnsemblePatchReader&&);
diff --git a/chromium/components/zucchini/patch_writer.h b/chromium/components/zucchini/patch_writer.h
index 34acaf1ce57..3d42173dc47 100644
--- a/chromium/components/zucchini/patch_writer.h
+++ b/chromium/components/zucchini/patch_writer.h
@@ -14,11 +14,11 @@
#include "base/check.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/zucchini/buffer_sink.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.h"
#include "components/zucchini/patch_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -224,10 +224,10 @@ class PatchElementWriter {
private:
ElementMatch element_match_;
- base::Optional<EquivalenceSink> equivalences_;
- base::Optional<ExtraDataSink> extra_data_;
- base::Optional<RawDeltaSink> raw_delta_;
- base::Optional<ReferenceDeltaSink> reference_delta_;
+ absl::optional<EquivalenceSink> equivalences_;
+ absl::optional<ExtraDataSink> extra_data_;
+ absl::optional<RawDeltaSink> raw_delta_;
+ absl::optional<ReferenceDeltaSink> reference_delta_;
std::map<PoolTag, TargetSink> extra_targets_;
};
diff --git a/chromium/components/zucchini/rel32_finder.cc b/chromium/components/zucchini/rel32_finder.cc
index 8fb88f5aaa0..45810d6eea5 100644
--- a/chromium/components/zucchini/rel32_finder.cc
+++ b/chromium/components/zucchini/rel32_finder.cc
@@ -41,7 +41,7 @@ Abs32GapFinder::Abs32GapFinder(ConstBufferView image,
Abs32GapFinder::~Abs32GapFinder() = default;
-base::Optional<ConstBufferView> Abs32GapFinder::GetNext() {
+absl::optional<ConstBufferView> Abs32GapFinder::GetNext() {
// Iterate over |[abs32_current_, abs32_end_)| and emit segments.
while (abs32_current_ != abs32_end_ &&
base_ + *abs32_current_ < region_end_) {
@@ -58,7 +58,7 @@ base::Optional<ConstBufferView> Abs32GapFinder::GetNext() {
current_lo_ = region_end_;
return gap;
}
- return base::nullopt;
+ return absl::nullopt;
}
/******** Rel32Finder ********/
diff --git a/chromium/components/zucchini/rel32_finder.h b/chromium/components/zucchini/rel32_finder.h
index b70b1be961e..5953755a808 100644
--- a/chromium/components/zucchini/rel32_finder.h
+++ b/chromium/components/zucchini/rel32_finder.h
@@ -10,9 +10,9 @@
#include <vector>
#include "base/macros.h"
-#include "base/optional.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -52,7 +52,7 @@ class Abs32GapFinder {
~Abs32GapFinder();
// Returns the next available gap, or nullopt if exhausted.
- base::Optional<ConstBufferView> GetNext();
+ absl::optional<ConstBufferView> GetNext();
private:
const ConstBufferView::const_iterator base_;
@@ -134,10 +134,10 @@ class Rel32FinderIntel : public Rel32Finder {
using Rel32Finder::Rel32Finder;
// Returns the next available Result, or nullopt if exhausted.
- base::Optional<Result> GetNext() {
+ absl::optional<Result> GetNext() {
if (FindNext())
return rel32_;
- return base::nullopt;
+ return absl::nullopt;
}
protected:
diff --git a/chromium/components/zucchini/rel32_finder_unittest.cc b/chromium/components/zucchini/rel32_finder_unittest.cc
index 9da88bfbd0e..42a442c430f 100644
--- a/chromium/components/zucchini/rel32_finder_unittest.cc
+++ b/chromium/components/zucchini/rel32_finder_unittest.cc
@@ -234,7 +234,7 @@ TEST(Rel32FinderX86Test, FindNext) {
EXPECT_FALSE(result->can_point_outside_section);
rel_finder.Accept();
}
- EXPECT_EQ(base::nullopt, rel_finder.GetNext());
+ EXPECT_EQ(absl::nullopt, rel_finder.GetNext());
}
TEST(Rel32FinderX86Test, Accept) {
@@ -349,7 +349,7 @@ TEST(Rel32FinderX64Test, FindNext) {
EXPECT_TRUE(result->can_point_outside_section);
rel_finder.Accept();
}
- EXPECT_EQ(base::nullopt, rel_finder.GetNext());
+ EXPECT_EQ(absl::nullopt, rel_finder.GetNext());
}
// TODO(huangs): Test that integrates Abs32GapFinder and Rel32Finder.
diff --git a/chromium/components/zucchini/rel32_utils.cc b/chromium/components/zucchini/rel32_utils.cc
index 37bcb6f43ec..c22cb23159d 100644
--- a/chromium/components/zucchini/rel32_utils.cc
+++ b/chromium/components/zucchini/rel32_utils.cc
@@ -16,7 +16,7 @@ namespace zucchini {
Rel32ReaderX86::Rel32ReaderX86(ConstBufferView image,
offset_t lo,
offset_t hi,
- const std::vector<offset_t>* locations,
+ const std::deque<offset_t>* locations,
const AddressTranslator& translator)
: image_(image),
target_rva_to_offset_(translator),
@@ -30,7 +30,7 @@ Rel32ReaderX86::Rel32ReaderX86(ConstBufferView image,
Rel32ReaderX86::~Rel32ReaderX86() = default;
-base::Optional<Reference> Rel32ReaderX86::GetNext() {
+absl::optional<Reference> Rel32ReaderX86::GetNext() {
while (current_ < last_ && *current_ < hi_) {
offset_t loc_offset = *(current_++);
DCHECK_LE(loc_offset + 4, image_.size()); // Sanity check.
@@ -41,7 +41,7 @@ base::Optional<Reference> Rel32ReaderX86::GetNext() {
DCHECK_NE(kInvalidOffset, target_offset);
return Reference{loc_offset, target_offset};
}
- return base::nullopt;
+ return absl::nullopt;
}
/******** Rel32ReceptorX86 ********/
diff --git a/chromium/components/zucchini/rel32_utils.h b/chromium/components/zucchini/rel32_utils.h
index 618ed0d5a38..4f7e0f30ed4 100644
--- a/chromium/components/zucchini/rel32_utils.h
+++ b/chromium/components/zucchini/rel32_utils.h
@@ -6,17 +6,17 @@
#define COMPONENTS_ZUCCHINI_REL32_UTILS_H_
#include <algorithm>
+#include <deque>
#include <memory>
-#include <vector>
#include "base/logging.h"
#include "base/macros.h"
-#include "base/optional.h"
#include "components/zucchini/address_translator.h"
#include "components/zucchini/arm_utils.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.h"
#include "components/zucchini/io_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -32,20 +32,20 @@ class Rel32ReaderX86 : public ReferenceReader {
Rel32ReaderX86(ConstBufferView image,
offset_t lo,
offset_t hi,
- const std::vector<offset_t>* locations,
+ const std::deque<offset_t>* locations,
const AddressTranslator& translator);
~Rel32ReaderX86() override;
- // Returns the next reference, or base::nullopt if exhausted.
- base::Optional<Reference> GetNext() override;
+ // Returns the next reference, or absl::nullopt if exhausted.
+ absl::optional<Reference> GetNext() override;
private:
ConstBufferView image_;
AddressTranslator::RvaToOffsetCache target_rva_to_offset_;
AddressTranslator::OffsetToRvaCache location_offset_to_rva_;
const offset_t hi_;
- const std::vector<offset_t>::const_iterator last_;
- std::vector<offset_t>::const_iterator current_;
+ const std::deque<offset_t>::const_iterator last_;
+ std::deque<offset_t>::const_iterator current_;
DISALLOW_COPY_AND_ASSIGN(Rel32ReaderX86);
};
@@ -79,7 +79,7 @@ class Rel32ReaderArm : public ReferenceReader {
Rel32ReaderArm(const AddressTranslator& translator,
ConstBufferView view,
- const std::vector<offset_t>& rel32_locations,
+ const std::deque<offset_t>& rel32_locations,
offset_t lo,
offset_t hi)
: view_(view),
@@ -91,7 +91,7 @@ class Rel32ReaderArm : public ReferenceReader {
rel32_end_ = rel32_locations.end();
}
- base::Optional<Reference> GetNext() override {
+ absl::optional<Reference> GetNext() override {
while (cur_it_ < rel32_end_ && *cur_it_ < hi_) {
offset_t location = *(cur_it_++);
CODE_T code = ADDR_TRAITS::Fetch(view_, location);
@@ -103,15 +103,15 @@ class Rel32ReaderArm : public ReferenceReader {
return Reference{location, target};
}
}
- return base::nullopt;
+ return absl::nullopt;
}
private:
ConstBufferView view_;
AddressTranslator::OffsetToRvaCache offset_to_rva_;
AddressTranslator::RvaToOffsetCache rva_to_offset_;
- std::vector<offset_t>::const_iterator cur_it_;
- std::vector<offset_t>::const_iterator rel32_end_;
+ std::deque<offset_t>::const_iterator cur_it_;
+ std::deque<offset_t>::const_iterator rel32_end_;
offset_t hi_;
DISALLOW_COPY_AND_ASSIGN(Rel32ReaderArm);
diff --git a/chromium/components/zucchini/rel32_utils_unittest.cc b/chromium/components/zucchini/rel32_utils_unittest.cc
index e3d34f41432..32fd7ae6a4a 100644
--- a/chromium/components/zucchini/rel32_utils_unittest.cc
+++ b/chromium/components/zucchini/rel32_utils_unittest.cc
@@ -6,16 +6,17 @@
#include <stdint.h>
+#include <deque>
#include <memory>
#include <utility>
#include <vector>
-#include "base/optional.h"
#include "base/test/gtest_util.h"
#include "components/zucchini/address_translator.h"
#include "components/zucchini/arm_utils.h"
#include "components/zucchini/image_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -39,7 +40,7 @@ void CheckReader(const std::vector<Reference>& expected_refs,
EXPECT_TRUE(ref.has_value());
EXPECT_EQ(expected_ref, ref.value());
}
- EXPECT_EQ(base::nullopt, reader->GetNext()); // Nothing should be left.
+ EXPECT_EQ(absl::nullopt, reader->GetNext()); // Nothing should be left.
}
// Copies displacements from |bytes1| to |bytes2| and checks results against
@@ -88,7 +89,7 @@ TEST(Rel32UtilsTest, Rel32ReaderX86) {
};
ConstBufferView buffer(bytes.data(), bytes.size());
// Specify rel32 locations directly, instead of parsing.
- std::vector<offset_t> rel32_locations = {0x0008U, 0x0010U, 0x0018U, 0x001CU};
+ std::deque<offset_t> rel32_locations = {0x0008U, 0x0010U, 0x0018U, 0x001CU};
// Generate everything.
auto reader1 = std::make_unique<Rel32ReaderX86>(buffer, 0x0000U, 0x0020U,
@@ -163,8 +164,8 @@ TEST(Rel32UtilsTest, Rel32ReaderArm_Arm32) {
};
ConstBufferView region(&bytes[0], bytes.size());
// Specify rel32 locations directly, instead of parsing.
- std::vector<offset_t> rel32_locations_A24 = {0x0008U, 0x0010U, 0x0018U,
- 0x001CU};
+ std::deque<offset_t> rel32_locations_A24 = {0x0008U, 0x0010U, 0x0018U,
+ 0x001CU};
// Generate everything.
auto reader1 =
@@ -427,21 +428,21 @@ TEST(Rel32UtilsTest, Rel32ReaderArm_AArch64) {
MutableBufferView region(&bytes[0], bytes.size());
// Generate Immd26. We specify rel32 locations directly.
- std::vector<offset_t> rel32_locations_Immd26 = {0x0008U};
+ std::deque<offset_t> rel32_locations_Immd26 = {0x0008U};
auto reader1 = std::make_unique<
Rel32ReaderArm<AArch64Rel32Translator::AddrTraits_Immd26>>(
translator, region, rel32_locations_Immd26, 0x0000U, 0x0020U);
CheckReader({{0x0008U, 0x0010U}}, std::move(reader1));
// Generate Immd19.
- std::vector<offset_t> rel32_locations_Immd19 = {0x0010U, 0x0018U};
+ std::deque<offset_t> rel32_locations_Immd19 = {0x0010U, 0x0018U};
auto reader2 = std::make_unique<
Rel32ReaderArm<AArch64Rel32Translator::AddrTraits_Immd19>>(
translator, region, rel32_locations_Immd19, 0x0000U, 0x0020U);
CheckReader({{0x0010U, 0x0014U}, {0x0018U, 0x0010U}}, std::move(reader2));
// Generate Immd14.
- std::vector<offset_t> rel32_locations_Immd14 = {0x001CU};
+ std::deque<offset_t> rel32_locations_Immd14 = {0x001CU};
auto reader3 = std::make_unique<
Rel32ReaderArm<AArch64Rel32Translator::AddrTraits_Immd14>>(
translator, region, rel32_locations_Immd14, 0x0000U, 0x0020U);
diff --git a/chromium/components/zucchini/reloc_elf.cc b/chromium/components/zucchini/reloc_elf.cc
index d4857e86c47..a7d1b38207a 100644
--- a/chromium/components/zucchini/reloc_elf.cc
+++ b/chromium/components/zucchini/reloc_elf.cc
@@ -89,7 +89,7 @@ rva_t RelocReaderElf::GetRelocationTarget(elf::Elf64_Rel rel) const {
return kInvalidRva;
}
-base::Optional<Reference> RelocReaderElf::GetNext() {
+absl::optional<Reference> RelocReaderElf::GetNext() {
offset_t cur_entry_size = cur_section_dimensions_->entry_size;
offset_t cur_section_dimensions_end =
base::checked_cast<offset_t>(cur_section_dimensions_->region.hi());
@@ -98,12 +98,12 @@ base::Optional<Reference> RelocReaderElf::GetNext() {
while (cursor_ >= cur_section_dimensions_end) {
++cur_section_dimensions_;
if (cur_section_dimensions_ == reloc_section_dimensions_.end())
- return base::nullopt;
+ return absl::nullopt;
cur_entry_size = cur_section_dimensions_->entry_size;
cursor_ =
base::checked_cast<offset_t>(cur_section_dimensions_->region.offset);
if (cursor_ + cur_entry_size > hi_)
- return base::nullopt;
+ return absl::nullopt;
cur_section_dimensions_end =
base::checked_cast<offset_t>(cur_section_dimensions_->region.hi());
}
@@ -132,7 +132,7 @@ base::Optional<Reference> RelocReaderElf::GetNext() {
cursor_ += cur_entry_size;
return Reference{location, target};
}
- return base::nullopt;
+ return absl::nullopt;
}
/******** RelocWriterElf ********/
diff --git a/chromium/components/zucchini/reloc_elf.h b/chromium/components/zucchini/reloc_elf.h
index 7fcdbd3521f..ebf2577bbd0 100644
--- a/chromium/components/zucchini/reloc_elf.h
+++ b/chromium/components/zucchini/reloc_elf.h
@@ -11,11 +11,11 @@
#include <vector>
#include "base/numerics/safe_conversions.h"
-#include "base/optional.h"
#include "components/zucchini/address_translator.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.h"
#include "components/zucchini/type_elf.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -68,7 +68,7 @@ class RelocReaderElf : public ReferenceReader {
rva_t GetRelocationTarget(elf::Elf64_Rel rel) const;
// ReferenceReader:
- base::Optional<Reference> GetNext() override;
+ absl::optional<Reference> GetNext() override;
private:
const ConstBufferView image_;
diff --git a/chromium/components/zucchini/reloc_elf_unittest.cc b/chromium/components/zucchini/reloc_elf_unittest.cc
index acbc1863c9f..ac5086abd25 100644
--- a/chromium/components/zucchini/reloc_elf_unittest.cc
+++ b/chromium/components/zucchini/reloc_elf_unittest.cc
@@ -85,7 +85,7 @@ class FakeImageWithReloc {
// Read all references and check.
std::vector<Reference> refs;
- for (base::Optional<Reference> ref = reader->GetNext(); ref.has_value();
+ for (absl::optional<Reference> ref = reader->GetNext(); ref.has_value();
ref = reader->GetNext()) {
refs.push_back(ref.value());
}
diff --git a/chromium/components/zucchini/reloc_win32.cc b/chromium/components/zucchini/reloc_win32.cc
index 6da48f2ab41..b70aa8a187c 100644
--- a/chromium/components/zucchini/reloc_win32.cc
+++ b/chromium/components/zucchini/reloc_win32.cc
@@ -93,14 +93,14 @@ RelocRvaReaderWin32::RelocRvaReaderWin32(RelocRvaReaderWin32&&) = default;
RelocRvaReaderWin32::~RelocRvaReaderWin32() = default;
// Unrolls a nested loop: outer = reloc blocks and inner = reloc entries.
-base::Optional<RelocUnitWin32> RelocRvaReaderWin32::GetNext() {
+absl::optional<RelocUnitWin32> RelocRvaReaderWin32::GetNext() {
// "Outer loop" to find non-empty reloc block.
while (cur_reloc_units_.Remaining() < kRelocUnitSize) {
if (!LoadRelocBlock(cur_reloc_units_.end()))
- return base::nullopt;
+ return absl::nullopt;
}
if (end_it_ - cur_reloc_units_.begin() < kRelocUnitSize)
- return base::nullopt;
+ return absl::nullopt;
// "Inner loop" to extract single reloc unit.
offset_t location =
base::checked_cast<offset_t>(cur_reloc_units_.begin() - image_.begin());
@@ -144,8 +144,8 @@ RelocReaderWin32::RelocReaderWin32(RelocRvaReaderWin32&& reloc_rva_reader,
RelocReaderWin32::~RelocReaderWin32() = default;
// ReferenceReader:
-base::Optional<Reference> RelocReaderWin32::GetNext() {
- for (base::Optional<RelocUnitWin32> unit = reloc_rva_reader_.GetNext();
+absl::optional<Reference> RelocReaderWin32::GetNext() {
+ for (absl::optional<RelocUnitWin32> unit = reloc_rva_reader_.GetNext();
unit.has_value(); unit = reloc_rva_reader_.GetNext()) {
if (unit->type != reloc_type_)
continue;
@@ -158,7 +158,7 @@ base::Optional<Reference> RelocReaderWin32::GetNext() {
offset_t location = unit->location;
return Reference{location, target};
}
- return base::nullopt;
+ return absl::nullopt;
}
/******** RelocWriterWin32 ********/
diff --git a/chromium/components/zucchini/reloc_win32.h b/chromium/components/zucchini/reloc_win32.h
index 207c6e7dfe3..6393702f6cd 100644
--- a/chromium/components/zucchini/reloc_win32.h
+++ b/chromium/components/zucchini/reloc_win32.h
@@ -10,11 +10,11 @@
#include <vector>
-#include "base/optional.h"
#include "components/zucchini/address_translator.h"
#include "components/zucchini/buffer_source.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -65,9 +65,9 @@ class RelocRvaReaderWin32 {
RelocRvaReaderWin32(RelocRvaReaderWin32&&);
~RelocRvaReaderWin32();
- // Successively visits and returns data for each reloc unit, or base::nullopt
+ // Successively visits and returns data for each reloc unit, or absl::nullopt
// when all reloc units are found. Encapsulates block transition details.
- base::Optional<RelocUnitWin32> GetNext();
+ absl::optional<RelocUnitWin32> GetNext();
private:
// Assuming that |block_begin| points to the beginning of a reloc block, loads
@@ -102,7 +102,7 @@ class RelocReaderWin32 : public ReferenceReader {
~RelocReaderWin32() override;
// ReferenceReader:
- base::Optional<Reference> GetNext() override;
+ absl::optional<Reference> GetNext() override;
private:
RelocRvaReaderWin32 reloc_rva_reader_;
diff --git a/chromium/components/zucchini/reloc_win32_unittest.cc b/chromium/components/zucchini/reloc_win32_unittest.cc
index 1b9894f3c8a..e3d33ca2193 100644
--- a/chromium/components/zucchini/reloc_win32_unittest.cc
+++ b/chromium/components/zucchini/reloc_win32_unittest.cc
@@ -219,7 +219,7 @@ TEST_F(RelocUtilsWin32Test, ReadWrite) {
// Read all references and check.
std::vector<Reference> refs;
- for (base::Optional<Reference> ref = reader->GetNext(); ref.has_value();
+ for (absl::optional<Reference> ref = reader->GetNext(); ref.has_value();
ref = reader->GetNext()) {
refs.push_back(ref.value());
}
diff --git a/chromium/components/zucchini/test_reference_reader.cc b/chromium/components/zucchini/test_reference_reader.cc
index 5517fa0003d..b7f8ece8963 100644
--- a/chromium/components/zucchini/test_reference_reader.cc
+++ b/chromium/components/zucchini/test_reference_reader.cc
@@ -11,9 +11,9 @@ TestReferenceReader::TestReferenceReader(const std::vector<Reference>& refs)
TestReferenceReader::~TestReferenceReader() = default;
-base::Optional<Reference> TestReferenceReader::GetNext() {
+absl::optional<Reference> TestReferenceReader::GetNext() {
if (index_ == references_.size())
- return base::nullopt;
+ return absl::nullopt;
return references_[index_++];
}
diff --git a/chromium/components/zucchini/test_reference_reader.h b/chromium/components/zucchini/test_reference_reader.h
index afae1888b21..cc8c0de043a 100644
--- a/chromium/components/zucchini/test_reference_reader.h
+++ b/chromium/components/zucchini/test_reference_reader.h
@@ -9,8 +9,8 @@
#include <vector>
-#include "base/optional.h"
#include "components/zucchini/image_utils.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {
@@ -20,7 +20,7 @@ class TestReferenceReader : public ReferenceReader {
explicit TestReferenceReader(const std::vector<Reference>& refs);
~TestReferenceReader() override;
- base::Optional<Reference> GetNext() override;
+ absl::optional<Reference> GetNext() override;
private:
std::vector<Reference> references_;
diff --git a/chromium/components/zucchini/zucchini_apply.cc b/chromium/components/zucchini/zucchini_apply.cc
index 2d001a1bb3c..10c5638e9ff 100644
--- a/chromium/components/zucchini/zucchini_apply.cc
+++ b/chromium/components/zucchini/zucchini_apply.cc
@@ -32,7 +32,7 @@ bool ApplyEquivalenceAndExtraData(ConstBufferView old_image,
CHECK(next_dst_it >= dst_it);
offset_t gap = static_cast<offset_t>(next_dst_it - dst_it);
- base::Optional<ConstBufferView> extra_data = extra_data_source.GetNext(gap);
+ absl::optional<ConstBufferView> extra_data = extra_data_source.GetNext(gap);
if (!extra_data) {
LOG(ERROR) << "Error reading extra_data";
return false;
@@ -46,7 +46,7 @@ bool ApplyEquivalenceAndExtraData(ConstBufferView old_image,
CHECK_EQ(dst_it, next_dst_it + equivalence->length);
}
offset_t gap = static_cast<offset_t>(new_image.end() - dst_it);
- base::Optional<ConstBufferView> extra_data = extra_data_source.GetNext(gap);
+ absl::optional<ConstBufferView> extra_data = extra_data_source.GetNext(gap);
if (!extra_data) {
LOG(ERROR) << "Error reading extra_data";
return false;
diff --git a/chromium/components/zucchini/zucchini_apply.h b/chromium/components/zucchini/zucchini_apply.h
index 559812eaaeb..abab3843247 100644
--- a/chromium/components/zucchini/zucchini_apply.h
+++ b/chromium/components/zucchini/zucchini_apply.h
@@ -5,8 +5,6 @@
#ifndef COMPONENTS_ZUCCHINI_ZUCCHINI_APPLY_H_
#define COMPONENTS_ZUCCHINI_ZUCCHINI_APPLY_H_
-#include <vector>
-
#include "components/zucchini/image_utils.h"
#include "components/zucchini/patch_reader.h"
#include "components/zucchini/zucchini.h"
diff --git a/chromium/components/zucchini/zucchini_gen.h b/chromium/components/zucchini/zucchini_gen.h
index 17f1fd4b2a4..c92248d7619 100644
--- a/chromium/components/zucchini/zucchini_gen.h
+++ b/chromium/components/zucchini/zucchini_gen.h
@@ -7,10 +7,10 @@
#include <vector>
-#include "base/optional.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.h"
#include "components/zucchini/zucchini.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace zucchini {